diff --git a/.artifactignore b/.artifactignore new file mode 100644 index 000000000000..5af70cce6426 --- /dev/null +++ b/.artifactignore @@ -0,0 +1,12 @@ +**/* +!target/*.bin +!target/*.log +!target/*.img.gz +!target/docker-sonic-vs.gz +!target/docker-ptf.gz +!target/debs/**/*.deb +!target/debs/**/*.deb.log +!target/debs/**/*.deb-install.log +!target/python-wheels/*.whl +!target/python-wheels/*.whl.log +!target/python-wheels/*.whl-install.log diff --git a/.azure-pipelines/build-template.yml b/.azure-pipelines/build-template.yml new file mode 100644 index 000000000000..c1cc04836a94 --- /dev/null +++ b/.azure-pipelines/build-template.yml @@ -0,0 +1,116 @@ +parameters: +- name: platform + type: string + values: + - broadcom + - centec-arm64 + - marvell-armhf + - mellanox + - vs + +- name: platform_arch + type: string + values: + - amd64 + - armhf + - arm64 + default: amd64 + +- name: platform_short + type: string + values: + - brcm + - centec-arm64 + - marvell-armhf + - mlnx + - vs + +- name: cache_mode + type: string + values: + - wcache + - rcache + - cache + +- name: pool + type: string + values: + - sonicbld + - sonicbld_8c + default: sonicbld + +- name: dbg_image + type: boolean + default: false + +- name: swi_image + type: boolean + default: false + +- name: raw_image + type: boolean + default: false + +- name: sync_rpc_image + type: boolean + default: false + +- name: timeout + type: number + default: 600 + +jobs: +- job: + pool: ${{ parameters.pool }} + displayName: ${{ parameters.platform }} + timeoutInMinutes: ${{ parameters.timeout }} + steps: + - template: cleanup.yml + - checkout: self + clean: true + submodules: recursive + displayName: 'Checkout code' + - script: | + git submodule foreach --recursive 'git clean -xfdf || true' + git submodule foreach --recursive 'git reset --hard || true' + git submodule foreach --recursive 'git remote update || true' + git submodule update --init --recursive + displayName: 'Reset submodules' + - script: | + set -e + sudo modprobe overlay + sudo apt-get install -y acl + export DOCKER_DATA_ROOT_FOR_MULTIARCH=/data/march/docker + CACHE_OPTIONS="SONIC_DPKG_CACHE_METHOD=${{ parameters.cache_mode }} SONIC_DPKG_CACHE_SOURCE=/nfs/dpkg_cache/${{ parameters.platform }}" + ENABLE_DOCKER_BASE_PULL=y make configure PLATFORM=${{ parameters.platform }} PLATFORM_ARCH=${{ parameters.platform_arch }} + trap "sudo rm -rf fsroot" EXIT + + if [ ${{ parameters.platform }} == vs ]; then + if [ ${{ parameters.dbg_image }} == true ]; then + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) INSTALL_DEBUG_TOOLS=y target/sonic-vs.img.gz && \ + mv target/sonic-vs.img.gz target/sonic-vs-dbg.img.gz + fi + + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) target/docker-sonic-vs.gz target/sonic-vs.img.gz target/docker-ptf.gz + else + if [ ${{ parameters.dbg_image }} == true ]; then + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) INSTALL_DEBUG_TOOLS=y target/sonic-${{ parameters.platform }}.bin && \ + mv target/sonic-${{ parameters.platform }}.bin target/sonic-${{ parameters.platform }}-dbg.bin + fi + if [ ${{ parameters.swi_image }} == true ]; then + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) ENABLE_IMAGE_SIGNATURE=y target/sonic-aboot-${{ parameters.platform }}.swi + fi + if [ ${{ parameters.raw_image }} == true ]; then + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) target/sonic-${{ parameters.platform }}.raw + fi + if [ ${{ parameters.sync_rpc_image }} == true ]; then + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) ENABLE_SYNCD_RPC=y target/docker-syncd-${{ parameters.platform_short }}-rpc.gz + fi + + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) target/sonic-${{ parameters.platform }}.bin + fi + displayName: 'Build sonic image' + - template: cleanup.yml + - publish: $(System.DefaultWorkingDirectory)/ + artifact: sonic-buildimage.${{ parameters.platform }} + displayName: "Archive sonic image" diff --git a/.azure-pipelines/cleanup.yml b/.azure-pipelines/cleanup.yml new file mode 100644 index 000000000000..ffbcf298b6c9 --- /dev/null +++ b/.azure-pipelines/cleanup.yml @@ -0,0 +1,17 @@ +steps: +- script: | + if sudo [ -f /var/run/march/docker.pid ] ; then + pid=`sudo cat /var/run/march/docker.pid` ; sudo kill $pid + fi + sudo rm -f /var/run/march/docker.pid + sudo rm -rf /data/march/docker + + # clean native docker build + if sudo [ -f dockerfs/var/run/docker.pid ] ; then + pid=`sudo cat dockerfs/var/run/docker.pid` ; sudo kill $pid + fi + sudo rm -rf dockerfs + sudo rm -rf fsroot + username=$(id -un) + sudo chown -R ${username}.${username} . + displayName: "Clean Workspace" diff --git a/.azure-pipelines/official-build.yml b/.azure-pipelines/official-build.yml new file mode 100644 index 000000000000..8524027d7b11 --- /dev/null +++ b/.azure-pipelines/official-build.yml @@ -0,0 +1,62 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +schedules: +- cron: "0 8 * * *" + displayName: Daily midnight build + branches: + include: + - master + always: true + +trigger: none +pr: none + +stages: +- stage: Build + + jobs: + - template: build-template.yml + parameters: + platform: broadcom + platform_short: brcm + cache_mode: wcache + dbg_image: true + swi_image: true + raw_image: true + sync_rpc_image: true + + - template: build-template.yml + parameters: + platform: mellanox + platform_short: mlnx + cache_mode: wcache + dbg_image: true + sync_rpc_image: true + + - template: build-template.yml + parameters: + platform: vs + platform_short: vs + dbg_image: true + cache_mode: wcache + + - template: build-template.yml + parameters: + timeout: 3600 + platform: marvell-armhf + platform_arch: armhf + platform_short: marvell-armhf + cache_mode: wcache + pool: sonicbld_8c + + - template: build-template.yml + parameters: + timeout: 3600 + platform: centec-arm64 + platform_arch: arm64 + platform_short: centec-arm64 + cache_mode: wcache + pool: sonicbld_8c diff --git a/.azure-pipelines/run-test-template.yml b/.azure-pipelines/run-test-template.yml new file mode 100644 index 000000000000..afe5eadec338 --- /dev/null +++ b/.azure-pipelines/run-test-template.yml @@ -0,0 +1,82 @@ +parameters: +- name: dut + type: string +- name: tbname + type: string +- name: tbtype + type: string +- name: ptf_name + type: string + +steps: +- checkout: self + clean: true + displayName: 'checkout sonic-mgmt repo' + +- task: DownloadPipelineArtifact@2 + inputs: + artifact: sonic-buildimage.vs + displayName: "Download sonic-buildimage.vs artifact" + +- script: | + set -x + sudo mkdir -p /data/sonic-vm/images + sudo cp -v ../target/sonic-vs.img.gz /data/sonic-vm/images/sonic-vs.img.gz + sudo gzip -fd /data/sonic-vm/images/sonic-vs.img.gz + username=$(id -un) + sudo chown -R $username.$username /data/sonic-vm + + pushd /data/sonic-mgmt + git remote update + git reset --hard origin/master + sed -i s/use_own_value/${username}/ ansible/veos_vtb + echo aaa > ansible/password.txt + docker exec sonic-mgmt bash -c "pushd /data/sonic-mgmt/ansible;./testbed-cli.sh -d /data/sonic-vm -m $(inventory) -t $(testbed_file) -k ceos refresh-dut ${{ parameters.tbname }} password.txt" && sleep 180 + displayName: "Setup testbed" + +- script: | + rm -rf $(Build.ArtifactStagingDirectory)/* + docker exec sonic-mgmt bash -c "/data/sonic-mgmt/tests/kvmtest.sh -en -T ${{ parameters.tbtype }} ${{ parameters.tbname }} ${{ parameters.dut }}" + displayName: "Run tests" + +- script: | + # save dut state if test fails + virsh_version=$(virsh --version) + if [ $virsh_version == "6.0.0" ]; then + mkdir -p $(Build.ArtifactStagingDirectory)/kvmdump + virsh -c qemu:///system list + virsh -c qemu:///system save ${{ parameters.dut }} $(Build.ArtifactStagingDirectory)/kvmdump/${{ parameters.dut }}.memdmp + virsh -c qemu:///system dumpxml ${{ parameters.dut }} > $(Build.ArtifactStagingDirectory)/kvmdump/${{ parameters.dut }}.xml + img=$(virsh -c qemu:///system domblklist ${{ parameters.dut }} | grep vda | awk '{print $2}') + cp $img $(Build.ArtifactStagingDirectory)/kvmdump/${{ parameters.dut }}.img + virsh -c qemu:///system undefine ${{ parameters.dut }} + fi + + docker commit ${{ parameters.ptf_name }} docker-ptf:$(Build.BuildNumber) + docker save docker-ptf:$(Build.BuildNumber) | gzip -c > $(Build.ArtifactStagingDirectory)/kvmdump/docker-ptf-dump.gz + docker rmi docker-ptf:$(Build.BuildNumber) + displayName: "Collect kvmdump" + condition: failed() + +- script: | + cp -r /data/sonic-mgmt/tests/logs $(Build.ArtifactStagingDirectory)/ + username=$(id -un) + sudo chown -R $username.$username $(Build.ArtifactStagingDirectory) + displayName: "Collect test logs" + condition: succeededOrFailed() + +- publish: $(Build.ArtifactStagingDirectory)/kvmdump + artifact: sonic-buildimage.kvmtest.${{ parameters.tbtype}}.memdump@$(System.JobAttempt) + displayName: "Archive sonic kvm memdump" + condition: failed() + +- publish: $(Build.ArtifactStagingDirectory)/logs + artifact: sonic-buildimage.kvmtest.${{ parameters.tbtype }}.log@$(System.JobAttempt) + displayName: "Archive sonic kvm logs" + condition: succeededOrFailed() + +- task: PublishTestResults@2 + inputs: + testResultsFiles: '$(Build.ArtifactStagingDirectory)/logs/**/*.xml' + testRunTitle: kvmtest.${{ parameters.tbtype }} + condition: succeededOrFailed() diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000000..8790ea4efd61 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,35 @@ +# This is a comment. +# Each line is a file pattern followed by one or more owners. + +# rules are explained here +# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners + +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @lguohan will be requested for review when someone opens +# a pull request. +* @lguohan + +/device/ @jleveque + +# build +/rules/ @qiluo-msft @xumia @lguohan +/Makefile @qiluo-msft @xumia @lguohan +/Makefile.cache @qiluo-msft @xumia @lguohan +/Makefile.work @qiluo-msft @xumia @lguohan +/slave.mk @qiluo-msft @xumia @lguohan +/scripts @qiluo-msft @xumia @lguohan + +# installer +/installer/ @qiluo-msft + +# permission +/files/image_config/sudoers/ @qiluo-msft + +# dockers +/dockers/docker-base*/ @qiluo-msft +/dockers/docker-config-engine*/ @qiluo-msft +/dockers/docker-snmp/ @qiluo-msft + +# src +/src/initramfs-tools/ @qiluo-msft diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 000000000000..d460bdc31d66 --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1,58 @@ + + +#### Description + + + +#### Steps to reproduce the issue: +1. +2. +3. + +#### Describe the results you received: + + +#### Describe the results you expected: + + +#### Output of `show version`: + +``` +(paste your output here) +``` + +#### Additional information you deem important (e.g. issue happens only occasionally): + + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000000..d2c06ae13abe --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,41 @@ + + +#### Why I did it + +#### How I did it + +#### How to verify it + +#### Which release branch to backport (provide reason below if selected) + + + +- [ ] 201811 +- [ ] 201911 +- [ ] 202006 +- [ ] 202012 + +#### Description for the changelog + + + +#### A picture of a cute animal (not mandatory but encouraged) + diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..5e76a6cf92da --- /dev/null +++ b/.gitignore @@ -0,0 +1,78 @@ +# OS-generated files +.DS_Store + +# Build system related +.arch +.platform +.screen +rules/config.user + +# Build artifacts +fsroot/ +fs.* +target/ +*.deb +*.changes +*.buildinfo +*.tar +*.xz +*.gz +*-dbg +*dbg.j2 +*.img + +# Autogenerated Dockerfiles +sonic-slave*/Dockerfile +sonic-slave*/Dockerfile.user +dockers/*/Dockerfile +platform/*/docker-*/Dockerfile + +# Installer-related files and directories +installer/x86_64/platforms/ + +# Misc. files +asic_config_checksum +files/Aboot/boot0 +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 + +# platform +platform/**/*.egg-info +platform/**/*-none-any.whl +platform/**/.pybuild +platform/**/debian/* +platform/**/build +platform/**/*.ko +platform/**/*.mod.c +platform/**/*.mod.o +platform/**/*.o +platform/**/*.d +platform/**/*.cmd +platform/**/*.order +platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/ipmihelper.py +platform/broadcom/sonic-platform-modules-dell/s6100/modules/dell_ich.c +platform/broadcom/sonic-platform-modules-dell/s6100/modules/dell_s6100_lpc.c +platform/broadcom/sonic-platform-modules-dell/z9100/modules/dell_ich.c +platform/broadcom/sonic-platform-modules-dell/z9100/modules/dell_mailbox.c +platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/ipmihelper.py + +# buildinfo +files/build/buildinfo +files/build/tmp +dockers/**/buildinfo +platform/**/buildinfo +sonic-slave*/**/buildinfo diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000000..96e5645dcaee --- /dev/null +++ b/.gitmodules @@ -0,0 +1,90 @@ +[submodule "sonic-swss-common"] + path = src/sonic-swss-common + url = https://github.com/Azure/sonic-swss-common +[submodule "sonic-linux-kernel"] + path = src/sonic-linux-kernel + url = https://github.com/Azure/sonic-linux-kernel +[submodule "sonic-sairedis"] + path = src/sonic-sairedis + url = https://github.com/Azure/sonic-sairedis +[submodule "sonic-swss"] + path = src/sonic-swss + url = https://github.com/Azure/sonic-swss +[submodule "src/p4c-bm/p4c-bm"] + path = platform/p4/p4c-bm/p4c-bm + url = https://github.com/krambn/p4c-bm +[submodule "src/p4-hlir/p4-hlir"] + path = platform/p4/p4-hlir/p4-hlir + url = https://github.com/p4lang/p4-hlir +[submodule "quagga"] + path = src/sonic-quagga + url = https://github.com/Azure/sonic-quagga + branch = debian/0.99.24.1 +[submodule "sonic-dbsyncd"] + path = src/sonic-dbsyncd + url = https://github.com/Azure/sonic-dbsyncd +[submodule "src/sonic-py-swsssdk"] + path = src/sonic-py-swsssdk + url = https://github.com/Azure/sonic-py-swsssdk.git +[submodule "src/sonic-snmpagent"] + path = src/sonic-snmpagent + url = https://github.com/Azure/sonic-snmpagent +[submodule "src/ptf"] + path = src/ptf + url = https://github.com/p4lang/ptf.git +[submodule "src/sonic-utilities"] + path = src/sonic-utilities + url = https://github.com/Azure/sonic-utilities +[submodule "platform/broadcom/sonic-platform-modules-arista"] + path = platform/broadcom/sonic-platform-modules-arista + url = https://github.com/aristanetworks/sonic +[submodule "src/sonic-platform-common"] + path = src/sonic-platform-common + url = https://github.com/Azure/sonic-platform-common +[submodule "src/sonic-platform-daemons"] + path = src/sonic-platform-daemons + url = https://github.com/Azure/sonic-platform-daemons +[submodule "src/sonic-frr/frr"] + path = src/sonic-frr/frr + url = https://github.com/Azure/sonic-frr.git + branch = frr/7.5 +[submodule "platform/p4/p4-hlir/p4-hlir-v1.1"] + path = platform/p4/p4-hlir/p4-hlir-v1.1 + url = https://github.com/p4lang/p4-hlir.git +[submodule "platform/p4/SAI-P4-BM"] + path = platform/p4/SAI-P4-BM + url = https://github.com/Mellanox/SAI-P4-BM.git +[submodule "platform/barefoot/sonic-platform-modules-arista"] + path = platform/barefoot/sonic-platform-modules-arista + url = https://github.com/aristanetworks/sonic +[submodule "platform/mellanox/hw-management/hw-mgmt"] + path = platform/mellanox/hw-management/hw-mgmt + url = https://github.com/Mellanox/hw-mgmt +[submodule "src/redis-dump-load"] + path = src/redis-dump-load + url = https://github.com/p/redis-dump-load.git +[submodule "platform/mellanox/mlnx-sai/SAI-Implementation"] + path = platform/mellanox/mlnx-sai/SAI-Implementation + url = https://github.com/Mellanox/SAI-Implementation +[submodule "src/sonic-mgmt-framework"] + path = src/sonic-mgmt-framework + url = https://github.com/Azure/sonic-mgmt-framework +[submodule "src/sonic-telemetry"] + path = src/sonic-telemetry + url = https://github.com/Azure/sonic-telemetry +[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-ztp"] + path = src/sonic-ztp + url = https://github.com/Azure/sonic-ztp +[submodule "src/sonic-restapi"] + path = src/sonic-restapi + url = https://github.com/Azure/sonic-restapi.git + branch = master +[submodule "src/sonic-mgmt-common"] + path = src/sonic-mgmt-common + url = https://github.com/Azure/sonic-mgmt-common.git +[submodule "src/wpasupplicant/sonic-wpa-supplicant"] + path = src/wpasupplicant/sonic-wpa-supplicant + url = https://github.com/Azure/sonic-wpa-supplicant.git diff --git a/Makefile b/Makefile new file mode 100644 index 000000000000..2231e6d98231 --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +# SONiC make file + +NOJESSIE ?= 1 +NOSTRETCH ?= 0 + +%:: + @echo "+++ --- Making $@ --- +++" +ifeq ($(NOJESSIE), 0) + EXTRA_DOCKER_TARGETS=$(notdir $@) make -f Makefile.work jessie +endif +ifeq ($(NOSTRETCH), 0) + EXTRA_DOCKER_TARGETS=$(notdir $@) BLDENV=stretch make -f Makefile.work stretch +endif + BLDENV=buster make -f Makefile.work $@ + +jessie: + @echo "+++ Making $@ +++" +ifeq ($(NOJESSIE), 0) + make -f Makefile.work jessie +endif + +stretch: + @echo "+++ Making $@ +++" +ifeq ($(NOSTRETCH), 0) + make -f Makefile.work stretch +endif + +init: + @echo "+++ Making $@ +++" + make -f Makefile.work $@ + +clean configure reset showtag sonic-slave-build sonic-slave-bash : + @echo "+++ Making $@ +++" +ifeq ($(NOJESSIE), 0) + make -f Makefile.work $@ +endif +ifeq ($(NOSTRETCH), 0) + BLDENV=stretch make -f Makefile.work $@ +endif + BLDENV=buster make -f Makefile.work $@ + +# Freeze the versions, see more detail options: scripts/versions_manager.py freeze -h +freeze: + @scripts/versions_manager.py freeze $(FREEZE_VERSION_OPTIONS) diff --git a/Makefile.cache b/Makefile.cache new file mode 100644 index 000000000000..4037222ffc93 --- /dev/null +++ b/Makefile.cache @@ -0,0 +1,683 @@ +####################################################################### +# +# Copyright (c) 2020 Broadcom, Inc. +# The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. +# +# Author: Kalimuthu Velappan +# Greg Paussa +# +# Email : kalimuthu.velappan@broadcom.com +# greg.paussa@broadcom.com +# +# 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. +# +####################################################################### +# +# +# DPKG caching framework +# +# SONiC source code composes of multiple open source modules. Eg: Linux, bash, ntp etc. +# Each module considered as a build target in the sonic build framework. +# Each module gets compiled and generate the final debian package(.deb) file. +# There are two types of source code packages used by the SONiC repo. +# +# 1. Module source code is maintained as part of main repo +# Eg: sonic-utilities, Plaform files etc +# +# Some module source code is maintained outside the sonic repo, but +# the build framework is part of sonic main repo. +# The build framework downloads the zipped source content from the web, +# applies a series of patches (if applicable) on the downloaded source code, +# compiles the source and generates the final .deb package(s). +# Eg: bash, ntp, etc +# +# 2. Module source code is maintained as a submodule(SM) in the sonic repo. +# Eg: Frr, swss, Linux etc +# +# +# The sonic build framework uses the module .deb packages that are generated as part of build and +# creates the set of target docker images and the final binary image for distribution. +# +# The caching framework provides the method to cache the module .deb packages and docker images +# into a cache location by tracking module dependency information. +# +# A module can have a set of dependency files, for example Makefiles, source files, scripts, dpkg control files, etc. +# The caching is done based on the SHA hash value of the module dependency file contents. If one of the +# dependency files is changed, the corresponding cache file is also changed. So it automatically creates the new cache file +# for that module. +# +# It provides two levels of caching. +# Global cache := Module doesnt have any local changes. +# Local cache := Used for target when one of its dependency file is modified. +# +# +# Steps for adding new module is given as a template. +# Template File : rules/template.dep +# + + +# Common files and FLAGS +# Run the 'touch cache.skip.common' command in the base directory to exclude the common files from caching +SONIC_COMMON_FILES_LIST := $(if $(wildcard cache.skip.common),, .platform slave.mk rules/functions Makefile.cache) +SONIC_COMMON_FLAGS_LIST := $(CONFIGURED_PLATFORM) \ + $(SONIC_DEBUGGING_ON) \ + $(SONIC_PROFILING_ON) $(SONIC_ENABLE_SYNCD_RPC) +SONIC_COMMON_DPKG_LIST := debian/control debian/changelog debian/rules \ + debian/compat debian/install debian/copyright +SONIC_COMMON_BASE_FILES_LIST := sonic-slave-jessie/Dockerfile.j2 sonic-slave-jessie/Dockerfile.user.j2 \ + sonic-slave-stretch/Dockerfile.j2 sonic-slave-stretch/Dockerfile.user.j2 \ + sonic-slave-buster/Dockerfile.j2 sonic-slave-buster/Dockerfile.user.j2 + + + +include $(RULES_PATH)/*.dep + + +ifneq ($(CONFIGURED_PLATFORM), undefined) +ifeq ($(PDDF_SUPPORT), y) +include $(PLATFORM_PDDF_PATH)/rules.dep +endif + +-include $(PLATFORM_PATH)/rules.dep +endif + +ifndef SONIC_BUILD_QUIETER +$(info "SONIC_DPKG_CACHE_METHOD" : "$(SONIC_DPKG_CACHE_METHOD)") +ifneq ($(SONIC_DPKG_CACHE_METHOD),none) +$(info "DPKG_CACHE_PATH" : "$(SONIC_DPKG_CACHE_SOURCE)") +endif +$(info ) +endif + + +############################################################################### +## Canned sequences +############################################################################### + +SONIC_DPKG_CACHE_DIR := /dpkg_cache +MOD_CACHE_LOCK_SUFFIX := cache_access +MOD_CACHE_LOCK_TIMEOUT := 3600 +SONIC_DPKG_LOCAL_CACHE_DIR=${TARGET_PATH}/cache +$(shell test -d $(SONIC_DPKG_LOCAL_CACHE_DIR) || \ + mkdir -p $(SONIC_DPKG_LOCAL_CACHE_DIR) && chmod 777 $(SONIC_DPKG_LOCAL_CACHE_DIR) ) +$(shell test -w $(SONIC_DPKG_CACHE_DIR) || sudo chmod 777 $(SONIC_DPKG_CACHE_DIR) ) + +DOCKER_LOCKFILE_SUFFIX := access +DOCKER_LOCKFILE_TIMEOUT := 1200 + +# Lock macro for shared file access +# Lock is implemented through flock command with a specified timeout value +# Lock file is created in the specified directory, a separate one for each target file name +# A designated suffix is appended to each target file name, followed by .lock +# +# Parameters: +# $(1) - target file name (without path) +# $(2) - lock file path (only) +# $(3) - designated lock file suffix +# $(4) - flock timeout (in seconds) +# +# $(call MOD_LOCK,file,path,suffix,timeout) +define MOD_LOCK + if [[ ! -f $(2)/$(1)_$(3).lock ]]; then + touch $(2)/$(1)_$(3).lock + chmod 777 $(2)/$(1)_$(3).lock; + fi + $(eval $(1)_lock_fd=$(subst ~,_,$(subst -,_,$(subst +,_,$(subst .,_,$(1)))))) + exec {$($(1)_lock_fd)}<>"$(2)/$(1)_$(3).lock"; + if ! flock -x -w $(4) "$${$($(1)_lock_fd)}" ; then + echo "ERROR: Lock timeout trying to access $(2)/$(1)_$(3).lock"; + exit 1; + fi +endef + +# UnLock macro for shared file access +# +# Parameters: +# $(1) - target file name (without path) +# +# $(call MOD_UNLOCK,file) +define MOD_UNLOCK + eval exec "$${$($(1)_lock_fd)}<&-"; +endef + + +# Calculate the 24 byte SHA value +# GIT_COMMIT_SHA => SHA is derived from last git commit ID +# GIT_CONTENT_SHA => SHA is derived from contents of depdency files +# Args: +# $(1) => target name +define GET_MOD_SHA + $(eval $(1)_MOD_DEP_FILES := $($(1)_DEP_FLAGS_FILE) $($(1)_MOD_HASH_FILE) $($(1)_SMOD_HASH_FILE) ) + $(if $(MDEBUG), $(info $(1)_MOD_DEP_FILES: $($(1)_MOD_DEP_FILES))) + $(eval $(1)_MOD_HASH := $(if $(filter GIT_COMMIT_SHA,$($(1)_CACHE_MODE)),\ + $(shell cd $($(1)_MOD_SRC_PATH) && git log -1 --format="%H"| awk '{print substr($$1,0,23);}' ),\ + $(shell git hash-object $($(1)_MOD_DEP_FILES)| \ + sha1sum | awk '{print substr($$1,0,23);}'))) +endef + + +# Calculate the 24 byte SHA value +# SHA value is derived from dependent files of the target which includes .flags, .sha and .smsha files. +# Args: +# $(1) => target name +define GET_MOD_DEP_SHA + $(eval $(1)_MOD_DEP_PKGS := $(foreach dfile,$($(1)_DEPENDS) $($(1)_RDEPENDS) $($(1)_WHEEL_DEPENDS) \ + $($(1)_PYTHON_DEBS) $($(1)_PYTHON_WHEELS) \ + $($(1)_DBG_DEPENDS) $($(1)_DBG_IMAGE_PACKAGES) $($(1)_LOAD_DOCKERS),\ + $(if $($(dfile)_MAIN_DEB),$($(dfile)_MAIN_DEB),$(dfile))) ) + + $(if $(MDEBUG), $(info $(1)_MOD_DEP_PKGS: $($(1)_MOD_DEP_PKGS))) + + # Warn if there is any missing dependency files + $(eval $(1)_DEP_MOD_SHA_FILES := $(foreach dfile,$($(1)_MOD_DEP_PKGS), \ + $($(dfile)_DEP_FLAGS_FILE) $($(dfile)_MOD_HASH_FILE) $($(dfile)_SMOD_HASH_FILE)) ) + $(eval $(1)_DEP_FILES_MISSING := $(filter-out $(wildcard $($(1)_DEP_MOD_SHA_FILES)),$($(1)_DEP_MOD_SHA_FILES)) ) + $(if $($(1)_DEP_FILES_MISSING), $(warning "[ DPKG ] Dependecy file(s) are not found for $(1) : $($(1)_DEP_FILES_MISSING))) + + $(eval $(1)_DEP_MOD_SHA := $(shell git hash-object $($(1)_DEP_MOD_SHA_FILES) \ + | sha1sum | awk '{print substr($$1,0,23);}')) +endef + + +# Retrive the list of files that are modified for the target. The files can be from +# 1. Any of dependent target is modified +# 2. Files from the target dependency list +# 3. Files from submodule dependency list if the target is a submodule +# +# Args: +# $(1) => target name +define GET_MODIFIED_FILES + $(eval $(1)_FILES_MODIFIED := $(foreach dfile,$($(1)_MOD_DEP_PKGS),$(if $($(dfile)_FILES_MODIFIED),$(dfile))) \ + $(if $($(1)_DEP_FILES), $(shell cat $($(1)_MOD_DEP_FILE) | xargs git status -s)) \ + $(if $($(1)_SMDEP_PATHS), $(foreach path,$($(1)_SMDEP_PATHS), \ + $(shell cd $(path) && git status --ignore-submodules=all -s -uno .))) ) + +endef + +# Loads the deb package from debian cache +# Cache file prefix is formed using SHA value +# The SHA value consists of +# 1. 24 byte SHA value is derived from the dependency files list +# Flags: Module ENV flags file +# Dependent packages : DEPENDS, RDEPENDS, WHEEL_DEPENDS, PYTHON_DEBS, PYTHON_WHEELS, DBG_DEPENDS, DBG_IMAGE_PACKAGES, LOAD_DOCKERS +# 2. 24 byte SHA value from one of the keyword type - GIT_COMMIT_SHA or GIT_CONTENT_SHA +# GIT_COMMIT_SHA - SHA value of the last git commit id if it is a submodule +# GIT_CONTENT_SHA - SHA value is calculated from the target dependency files content. +# Cache is loaded from either local cache or global cache based on the dependency SHA match with the cache filename. +# Otherwise it builds the package from source. +# TODO: +# 1. Extend dpkg for all the chip vendor packages. + +# Args: +# $(1) => target name +# $(2) => target output file name +define LOAD_FROM_CACHE + + # Calculate the modules SHA and its dependency SHA value + $(call GET_MOD_DEP_SHA,$(1)) + $(call GET_MOD_SHA,$(1)) + + # Form the cache file name + $(eval $(1)_MOD_CACHE_FILE := $(1)-$($(1)_DEP_MOD_SHA)-$($(1)_MOD_HASH).tgz) + $(if $(MDEBUG), $(info $(1)_MODE_CACHE_FILE := $($(1)_MOD_CACHE_FILE))) + + # Retrive and log files list that are modified for the target. + $(call GET_MODIFIED_FILES,$(1)) + $(if $($(1)_FILES_MODIFIED), + echo "Target $(1) dependencies are modifed - global cache skipped" >> $($(1)_DST_PATH)/$(1).log + echo "Modified dependencies are : [$($(1)_FILES_MODIFIED)] " >> $($(1)_DST_PATH)/$(1).log + $(eval $(1)_CACHE_DIR := $(SONIC_DPKG_LOCAL_CACHE_DIR))) + + # Choose the cache file path in the following order + # 1. First load from Local cache path + # 2. If not, load from global cache path + $(eval CACHE_FILE_SELECT:=$(or $(wildcard $(SONIC_DPKG_LOCAL_CACHE_DIR)/$($(1)_MOD_CACHE_FILE)), \ + $(wildcard $(SONIC_DPKG_CACHE_DIR)/$($(1)_MOD_CACHE_FILE))) ) + + # Check if any of the derived package is not built + $(eval LOAD_DRV_DEB := $(foreach pkg,$(addprefix $($(1)_DST_PATH)/,$(1) $($(1)_DERIVED_DEBS) $($(1)_EXTRA_DEBS)),$(if $(wildcard $(pkg)),,$(pkg)))) + + # Load the cache if cache is enabled and cache file is present in the cache + # Update the cache_loaded variable + $(if $(and $(CACHE_FILE_SELECT),$(filter $(RCACHE_OPTIONS),$(SONIC_DPKG_CACHE_METHOD))), + $(if $(LOAD_DRV_DEB), $($(1)_CACHE_USER) tar -C $($(1)_BASE_PATH) -mxzvf $(CACHE_FILE_SELECT) 1>> $($(1)_DST_PATH)/$(1).log ,echo ); + echo "File $(CACHE_FILE_SELECT) is loaded from cache into $($(1)_BASE_PATH)" >> $($(1)_DST_PATH)/$(1).log + $(eval $(1)_CACHE_LOADED := Yes) + $(if $(call CHECK_WCACHE_ENABLED,$(1)), $(shell touch $(CACHE_FILE_SELECT))) + echo "[ CACHE::LOADED ] $($(1)_CACHE_DIR)/$($(1)_MOD_CACHE_FILE)" >> $($(1)_DST_PATH)/$(1).log + echo "File $($(1)_CACHE_DIR)/$($(1)_MOD_CACHE_FILE) is not present in cache or cache mode set as $(SONIC_DPKG_CACHE_METHOD) !" >> $($(1)_DST_PATH)/$(1).log + echo "[ CACHE::SKIPPED ] $($(1)_CACHE_DIR)/$($(1)_MOD_CACHE_FILE)" >> $($(1)_DST_PATH)/$(1).log + echo "[ CACHE::SKIPPED ] DEP_FILES - Modified Files: [$($(1)_FILES_MODIFIED)] " >> $($(1)_DST_PATH)/$(1).log + echo "[ CACHE::SKIPPED ] DEPENDS - Modified Files: [$?] " >> $($(1)_DST_PATH)/$(1).log + ) +endef + +# Saves the deb package into debian cache +# A single tared-zip cache is created for .deb and its derived packages in the cache direcory. +# It saves the .deb into global cache only when its dependencies are not changed, +# Otherwise it saves the .deb into local cache +# The cache save is protected with lock. +# Args: +# $(1) => target name +# $(2) => target output file name +define SAVE_INTO_CACHE + + # Calculate the modules SHA and its dependency SHA value + $(call GET_MOD_DEP_SHA,$(1)) + $(call GET_MOD_SHA,$(1)) + + # Form the cache file name + $(eval $(1)_MOD_CACHE_FILE := $(1)-$($(1)_DEP_MOD_SHA)-$($(1)_MOD_HASH).tgz) + $(if $(MDEBUG), $(info $(1)_MOD_CACHE_FILE := $($(1)_MOD_CACHE_FILE))) + + # Retrive and log files list that are modified for the target. + $(call GET_MODIFIED_FILES,$(1)) + + $(eval MOD_CACHE_FILE=$($(1)_MOD_CACHE_FILE)) + $(call MOD_LOCK,$(1),$(SONIC_DPKG_CACHE_DIR),$(MOD_CACHE_LOCK_SUFFIX),$(MOD_CACHE_LOCK_TIMEOUT)) + $(if $($(1)_FILES_MODIFIED), + echo "Target $(1) dependencies are modifed - global save cache skipped" >> $($(1)_DST_PATH)/$(1).log + $(eval $(1)_CACHE_DIR := $(SONIC_DPKG_LOCAL_CACHE_DIR)) + ) + $($(1)_CACHE_USER) tar -C $($(1)_BASE_PATH) -mczvf $($(1)_CACHE_DIR)/$(MOD_CACHE_FILE) $(2) $(addprefix $($(1)_DST_PATH)/,$($(1)_DERIVED_DEBS) $($(1)_EXTRA_DEBS) ) \ + 1>>$($(1)_DST_PATH)/$(1).log + sudo chmod 777 $($(1)_CACHE_DIR)/$(MOD_CACHE_FILE) + + echo "File $($(1)_CACHE_DIR)/$(MOD_CACHE_FILE) saved in cache " >> $($(1)_DST_PATH)/$(1).log + echo "[ CACHE::SAVED ] $($(1)_CACHE_DIR)/$(MOD_CACHE_FILE)" >> $($(1)_DST_PATH)/$(1).log + + $(call MOD_UNLOCK,$(1)) +endef + +# Read from the cache +RCACHE_OPTIONS := cache rcache rwcache +define CHECK_RCACHE_ENABLED +$(if $(and $(filter $(RCACHE_OPTIONS),$(SONIC_DPKG_CACHE_METHOD)),$(filter-out none,$($(1)_CACHE_MODE))),enabled) +endef + +# Write into the cache +WCACHE_OPTIONS := cache wcache rwcache +define CHECK_WCACHE_ENABLED +$(if $(and $(filter $(WCACHE_OPTIONS),$(SONIC_DPKG_CACHE_METHOD)),$(filter-out none,$($(1)_CACHE_MODE))),enabled) +endef + +# It logs the reason why the target is getting built/rebuilt +# Args: +# $(1) => target name +define SHOW_WHY + @echo "[ REASON ] :\ + $(if $(filter $(PHONY),$@), it is phony,\ + $(eval $(1)_PREREQ_PHONY:= $(filter $(PHONY),$^))\ + $(eval $(1)_PREREQ_DNE:= $(filter-out $(wildcard $^) $($(1)_PREREQ_PHONY),$^))\ + $(eval $(1)_PREREQ_NEW:= $(filter-out $($(1)_PREREQ_DNE),$?))\ + $(if $(wildcard $@),$(if $($(1)_PREREQ_NEW), NEWER PREREQUISITES: $($(1)_PREREQ_NEW)), $@ does not exist)\ + $(if $($(1)_PREREQ_DNE), NON-EXISTENT PREREQUISITES: $($(1)_PREREQ_DNE))\ + $(if $($(1)_PREREQ_PHONY), PHONY PREREQUISITES: $($(1)_PREREQ_PHONY)))" >> $($(1)_DST_PATH)/$(1).log + + @echo "[ FLAGS FILE ] : [$($(1)_FILE_FLAGS)] " >> $($(1)_DST_PATH)/$(1).log + @echo "[ FLAGS DEPENDS ] : [$($(1)_DEP_FLAGS_ALL)] " >> $($(1)_DST_PATH)/$(1).log + @echo "[ FLAGS DIFF ] : [$($(1)_FLAGS_DIFF)] " >> $($(1)_DST_PATH)/$(1).log + @$(file >>$($(1)_DST_PATH)/$(1).log, "[ DEP DEPENDS ] : [$($(1)_DEP_FILES_MODIFIED)] ") + @$(file >>$($(1)_DST_PATH)/$(1).log, "[ SMDEP DEPENDS ] : [$($(1)_SMDEP_FILES_MODIFIED)] ") + @$(file >>$($(1)_DST_PATH)/$(1).log, "[ TARGET DEPENDS ] : [$?] ") +endef + + + +# It invokes the Load Cache macro if cache is enabled globally as well as per module level +# Args: +# $(1) => target name +# $(2) => target output file name +define LOAD_CACHE + $(call SHOW_WHY,$(1)) + $(if $(call CHECK_RCACHE_ENABLED,$(1)), $(call LOAD_FROM_CACHE,$(1),$(2)) ) +endef + + +# It invokes the Save Cache if cache is enabled globally as well as per module level +# Args: +# $(1) => target name +# $(2) => target output file name +define SAVE_CACHE + $(if $(call CHECK_WCACHE_ENABLED,$(1)), $(call SAVE_INTO_CACHE,$(1),$(2))) +endef + + + +# Set the target path for each target. +$(foreach pkg, $(SONIC_MAKE_DEBS) $(SONIC_DPKG_DEBS) $(SONIC_ONLINE_DEBS) $(SONIC_COPY_DEBS), \ + $(eval $(pkg)_DST_PATH := $(if $($(pkg)_DST_PATH), $($(pkg)_DST_PATH), $(DEBS_PATH))) \ + $(eval $(DEBS_PATH)/$(pkg)_TARGET := $(pkg)) ) + +$(foreach pkg, $(SONIC_MAKE_FILES), \ + $(eval $(pkg)_DST_PATH := $(if $($(pkg)_DST_PATH), $($(pkg)_DST_PATH), $(FILES_PATH))) \ + $(eval $(FILES_PATH)/$(pkg)_TARGET := $(pkg)) ) + +$(foreach pkg, $(SONIC_PYTHON_STDEB_DEBS), \ + $(eval $(pkg)_DST_PATH := $(if $($(pkg)_DST_PATH), $($(pkg)_DST_PATH), $(PYTHON_DEBS_PATH))) \ + $(eval $(PYTHON_DEBS_PATH)/$(pkg)_TARGET := $(pkg)) ) + +$(foreach pkg, $(SONIC_PYTHON_WHEELS), \ + $(eval $(pkg)_DST_PATH := $(if $($(pkg)_DST_PATH), $($(pkg)_DST_PATH), $(PYTHON_WHEELS_PATH))) \ + $(eval $(PYTHON_WHEELS_PATH)/$(pkg)_TARGET := $(pkg)) ) + +$(foreach pkg, $(SONIC_DOCKER_IMAGES) $(SONIC_DOCKER_DBG_IMAGES), \ + $(eval $(pkg)_DST_PATH := $(if $($(pkg)_DST_PATH), $($(pkg)_DST_PATH), $(TARGET_PATH))) \ + $(eval $(TARGET_PATH)/$(pkg)_TARGET := $(pkg)) ) + +$(foreach pkg, $(SONIC_INSTALL_PKGS), \ + $(eval $(pkg)_DST_PATH := $(if $($(pkg)_DST_PATH), $($(pkg)_DST_PATH), $(FSROOT_PATH))) \ + $(eval $(FSROOT_PATH)/$(pkg)_TARGET := $(pkg)) ) + + +# define the DEP files(.dep and .smdep) and SHA files (.sha and smsha) for each target +$(foreach pkg, $(SONIC_MAKE_DEBS) $(SONIC_DPKG_DEBS) $(SONIC_ONLINE_DEBS) $(SONIC_COPY_DEBS) \ + $(SONIC_MAKE_FILES) $(SONIC_PYTHON_STDEB_DEBS) $(SONIC_PYTHON_WHEELS) \ + $(SONIC_DOCKER_IMAGES) $(SONIC_DOCKER_DBG_IMAGES) $(SONIC_INSTALL_PKGS), \ + $(eval $(pkg)_MOD_SRC_PATH:=$(if $($(pkg)_SRC_PATH),$($(pkg)_SRC_PATH),$($(pkg)_PATH))) \ + $(eval $(pkg)_BASE_PATH:=$(if $($(pkg)_BASE_PATH),$($(pkg)_BASE_PATH),$(CURDIR))) \ + $(eval $(pkg)_DEP_FLAGS_FILE:=$($(pkg)_DST_PATH)/$(pkg).flags) \ + $(eval $(pkg)_MOD_DEP_FILE:=$($(pkg)_DST_PATH)/$(pkg).dep) \ + $(eval $(pkg)_MOD_HASH_FILE:=$($(pkg)_DST_PATH)/$(pkg).dep.sha) \ + $(eval $(pkg)_SMOD_DEP_FILE:=$(if $($(pkg)_SMDEP_FILES),$($(pkg)_DST_PATH)/$(pkg).smdep)) \ + $(eval $(pkg)_SMOD_HASH_FILE:=$(if $($(pkg)_SMDEP_FILES),$($(pkg)_DST_PATH)/$(pkg).smdep.smsha)) \ + $(eval $(pkg)_DEP_FILES_LIST := $($(pkg)_DEP_FLAGS_FILE) $($(pkg)_DEP_FILES) $($(pkg)_SMDEP_FILES)) \ + $(eval $(pkg)_CACHE_DIR := $(SONIC_DPKG_CACHE_DIR)) \ + $(if $(filter-out none,$(SONIC_DPKG_CACHE_METHOD)), \ + $(if $(filter-out none,$($(pkg)_CACHE_MODE)), \ + $(if $($(pkg)_SMDEP_FILES), \ + $(if $($(pkg)_SMDEP_PATHS),,$(info Missing PATH/SRC_PATH attribute for $(pkg) package)) \ + ),\ + $(info [ DPKG ] Cache is not enabled for $(pkg) package)\ + )\ + ) \ + ) + + +# DPGK framework creates three dependency files for each target. +# 1. Flags file (.flags) +# 2. Dependency file (.dep), +# 3. Dependecy SHA hash file (.sha) +# 4. If the target is a submodule, corresponding dependency file and hash file are created +# sub module dependency file (.smdep) +# sub module hash file (.smsha) +# For example: following are the cache framework files for bash module +# target/debs/stretch/bash_4.3-14_amd64.deb => Final debian package +# target/debs/stretch/bash_4.3-14_amd64.deb.flags => Environment Flag file +# target/debs/stretch/bash_4.3-14_amd64.deb.dep => Dependency files list +# target/debs/stretch/bash_4.3-14_amd64.deb.dep.sha => SHA Hash file +# +# +# [1] .flags => contains value of all the environment variables of a target. +# Each target can have dependency with one or more environment variable. +# For example: +# SONIC_DEBUGGING_ON=y +# SONIC_PROFILING_ON=y +# SONIC_SANITIZER_ON=y +# etc +# If any of the ENV flag variables are modified, the target needs to be rebuilt as +# the content of flag file is changed becase of value of ENV variable is changed. +# +# [2] .dep => contains the dependency files list for a target. Eeach traget can have one or more dependency files. +# If any of the ENV flag variables are modified, the target needs to be rebuilt. +# For example: Dependency files list for 'bash' module +# rules/bash.mk +# rules/bash.dep +# src/bash/Makefile +# etc +# +# [3] .sha => contains the 48 byte SHA value for each dependency file present in the .dep file. +# For example: +# 9604676527653dcf7b6046fdda7ba52026b7f56f rules/bash.mk +# 191c345c1270776b3902c9ec91d5e777e0b5e2a3 rules/bash.dep +# 55692fe59303554b5958b04aa62c3651bc34bb6a src/bash/Makefile +# etc +# +# If module target is a sub module in the sonic repo, the following additional files gets created for that target. +# .smdep => contains the dependency files list +# .smsha => contains the SHA hash value for .smdep files list. + + + + + +# ruiles for <.flags> file creation +# +# Each target defines a variable called '_DEP_FLAGS' that contais a list of environment flags for that target and +# that indicates that target needs to be rebuilt if any of the dependent flags are changed. +# An environmental dependency flags file is created with the name as ‘.flags’ for each target. +# This file contains the values of target environment flags and gets updated only when there is a change in the flag's value. +# This file is added as a dependency to the target, so that any change in the file will trigger the target recompilation. +# For Eg: +# target/debs/stretch/linux-headers-4.9.0-9-2-common_4.9.168-1+deb9u3_all.deb.flags +# +# RULE args: +# $(1) => target name +# $(2) => target destination folder path +# $(3) => target file extension +# $(4) => additional flags +# +# It updates the _DEP_FLAGS variable if there is any change in the module flags. + +define FLAGS_DEP_RULES +ALL_DEP_FILES_LIST += $(foreach pkg,$(2), $(if $(filter none,$($(1)_CACHE_MODE)),$(addsuffix .$(3),$(addprefix $(pkg)/, $(1))))) +$(addsuffix .$(3),$(addprefix $(2)/, $(1))) :: $(2)/%.$(3) : + @$$(eval $$*_FILE_FLAGS := $$(shell test -f $$@ && cat $$@)) + @$$(eval $$*_DEP_FLAGS_ALL := $$(shell echo '$$($$*_DEP_FLAGS) $(4)' | sed -E 's/[ ]+/ /g' | sed -E 's/[ ]+$$$$//g')) + @echo '$$($$*_DEP_FLAGS_ALL)' | cmp -s - $$@ || echo '$$($$*_DEP_FLAGS_ALL)' > $$@ + $$(eval $$*_FLAGS_DIFF := $$(filter-out $$($$*_FILE_FLAGS),$$($$*_DEP_FLAGS_ALL)) $$(filter-out $$($$*_DEP_FLAGS_ALL),$$($$*_FILE_FLAGS))) + @$$(if $$(MDEBUG), $$(info FLAGS: $$@, DEP:$$?)) +endef +$(eval $(call FLAGS_DEP_RULES, $(SONIC_MAKE_DEBS) $(SONIC_DPKG_DEBS) $(SONIC_ONLINE_DEBS) $(SONIC_COPY_DEBS), $(DEBS_PATH),flags,$(BLDENV)) ) +$(eval $(call FLAGS_DEP_RULES, $(SONIC_MAKE_FILES), $(FILES_PATH),flags,$(BLDENV))) +$(eval $(call FLAGS_DEP_RULES, $(SONIC_PYTHON_STDEB_DEBS), $(PYTHON_DEBS_PATH),flags)) +$(eval $(call FLAGS_DEP_RULES, $(SONIC_PYTHON_WHEELS), $(PYTHON_WHEELS_PATH),flags)) +$(eval $(call FLAGS_DEP_RULES, $(SONIC_DOCKER_IMAGES) $(SONIC_DOCKER_DBG_IMAGES), $(TARGET_PATH),flags)) +$(eval $(call FLAGS_DEP_RULES, $(SONIC_INSTALL_PKGS), $(FSROOT_PATH),flags)) + + + + +# rules for <.smdep> and <.smsha> file creation +# This rule creates two dependency files for a target if the target is a submodule +# [1] .smdep file +# Each module target defines a variable called '_SMDEP_FILES' that contains the list of sub module dependency files for the target. +# Contents of the '_SMDEP_FILES' variable is stored in this file +# +# [2] .smsha file +# The SHA hash (.smsha) file is created from 48 byte SHA value for each of the dependency files present in the .smdep file +# +# The target needs to be rebuilt if any of the dependent flags are changed. +# The submodule dependency file is created with the name as '.smdep' and the SHA hash file created as '.smdep.smsha'. +# This file is added as a dependency to the target, so that any change in the file will trigger the target recompilation. +# For Eg: +# target/debs/stretch/linux-headers-4.9.0-9-2-common_4.9.168-1+deb9u3_all.deb.smdep +# target/debs/stretch/linux-headers-4.9.0-9-2-common_4.9.168-1+deb9u3_all.deb.smdep.smsha +# +# RULE args: +# $(1) => target name +# $(2) => target destination folder path +# $(3) => target file extension + +define SMSHA_DEP_RULES +ALL_DEP_FILES_LIST += $(foreach pkg,$(2), $($(filter none,$($(1)_CACHE_MODE)), \ + $(addsuffix .$(3),$(addprefix $(pkg)/, $(1))) \ + $(addsuffix .$(3).smsha,$(addprefix $(pkg)/, $(1))))) +$(addsuffix .$(3),$(addprefix $(2)/, $(1))) : $(2)/%.$(3) : \ + $(2)/%.flags $$$$($$$$*_SMDEP_FILES) + @$$(eval $$*_SMDEP_FILES_MODIFIED := $$? ) + @$$(file >$$@,$$(patsubst $$($$*_MOD_SRC_PATH)/%,%,$$($$*_SMDEP_FILES))) + @( cd $$($$*_MOD_SRC_PATH) ; cat $$($$*_BASE_PATH)/$$@ |xargs git hash-object ) >$$@.smsha + @$$(if $$(MDEBUG), $$(info SMDEP:$$@, MOD:$$?)) +endef +$(eval $(call SMSHA_DEP_RULES, $(SONIC_MAKE_DEBS) $(SONIC_DPKG_DEBS) $(SONIC_ONLINE_DEBS) $(SONIC_COPY_DEBS), $(DEBS_PATH),smdep)) +$(eval $(call SMSHA_DEP_RULES, $(SONIC_MAKE_FILES), $(FILES_PATH),smdep)) +$(eval $(call SMSHA_DEP_RULES, $(SONIC_PYTHON_STDEB_DEBS), $(PYTHON_DEBS_PATH),smdep)) +$(eval $(call SMSHA_DEP_RULES, $(SONIC_PYTHON_WHEELS), $(PYTHON_WHEELS_PATH),smdep)) +$(eval $(call SMSHA_DEP_RULES, $(SONIC_DOCKER_IMAGES) $(SONIC_DOCKER_DBG_IMAGES), $(TARGET_PATH),smdep)) + + + + + +# rules for <.dep> and <.sha> file creation +# +# This rule creates two dependency files for the target +# [1] .dep file +# Each module target defines a variable called '_DEP_FILES' that contains the list of dependency files for the target. +# Contents of the '_DEP_FILES' variable is stored in this file +# +# [2] .sha file +# The SHA hash (.sha) file is created from 48 byte SHA value for each of the dependency files present in the .dep file +# +# The target needs to be rebuilt if any of the dependent flags are changed. +# The module dependency file is created with the name as '.dep' and the SHA hash file created as '.dep.sha'. +# This file is added as a dependency to the target, so that any change in the file will trigger the target recompilation. +# For Eg: +# target/debs/stretch/bash_4.3-14_amd64.deb.dep +# target/debs/stretch/bash_4.3-14_amd64.deb.dep.sha +# +# RULE args: +# $(1) => target name +# $(2) => target destination folder path +# $(3) => target file extension +# + +define SHA_DEP_RULES +ALL_DEP_FILES_LIST += $(foreach pkg,$(2), $($(filter none,$($(1)_CACHE_MODE)), \ + $(addsuffix .$(3),$(addprefix $(pkg)/, $(1))) \ + $(addsuffix .$(3).sha,$(addprefix $(pkg)/, $(1))))) +$(addsuffix .$(3),$(addprefix $(2)/, $(1))) : $(2)/%.$(3) : \ + $(2)/%.flags $$$$($$$$*_DEP_FILES) $$$$(if $$$$($$$$*_SMDEP_FILES), $(2)/%.smdep) + @$$(eval $$*_DEP_FILES_MODIFIED := $$? ) + @$$(file >$$@.tmp,$$($$*_DEP_FILES)) + @cat $$@.tmp |xargs git hash-object >$$@.sha.tmp + @if ! cmp -s $$@.sha.tmp $$@.sha; then cp $$@.tmp $$@; cp $$@.sha.tmp $$@.sha; fi + @rm -f $$@.tmp $$@.sha.tmp + @$$(if $$(MDEBUG), $$(info DEP: $$@, MOD:$$?)) +endef +$(eval $(call SHA_DEP_RULES, $(SONIC_MAKE_DEBS) $(SONIC_DPKG_DEBS) $(SONIC_ONLINE_DEBS) $(SONIC_COPY_DEBS), $(DEBS_PATH),dep)) +$(eval $(call SHA_DEP_RULES, $(SONIC_MAKE_FILES), $(FILES_PATH),dep)) +$(eval $(call SHA_DEP_RULES, $(SONIC_PYTHON_STDEB_DEBS), $(PYTHON_DEBS_PATH),dep)) +$(eval $(call SHA_DEP_RULES, $(SONIC_PYTHON_WHEELS), $(PYTHON_WHEELS_PATH),dep)) +$(eval $(call SHA_DEP_RULES, $(SONIC_DOCKER_IMAGES) $(SONIC_DOCKER_DBG_IMAGES), $(TARGET_PATH),dep)) +$(eval $(call SHA_DEP_RULES, $(SONIC_INSTALL_PKGS), $(FSROOT_PATH),dep)) + + + + + +# Clean all the DEP and SHA files for all the DEBS target +SONIC_CACHE_CLEAN_DEBS = $(addsuffix -clean,$(addprefix $(DEBS_PATH)/, \ + $(SONIC_ONLINE_DEBS) \ + $(SONIC_COPY_DEBS) \ + $(SONIC_MAKE_DEBS) \ + $(SONIC_DPKG_DEBS) \ + $(SONIC_DERIVED_DEBS) \ + $(SONIC_EXTRA_DEBS))) +$(SONIC_CACHE_CLEAN_DEBS) :: $(DEBS_PATH)/%-clean : .platform $$(addsuffix -clean,$$(addprefix $(DEBS_PATH)/,$$($$*_MAIN_DEB))) + @rm -f $($*_DEP_FLAGS_FILE) $($*_MOD_HASH_FILE) $($*_SMOD_HASH_FILE) \ + $($*_MOD_DEP_FILE) $($*_SMOD_DEP_FILE) + + +# Clean all the DEP and SHA files for all the FILES target +SONIC_CACHE_CLEAN_FILES = $(addsuffix -clean,$(addprefix $(FILES_PATH)/, \ + $(SONIC_ONLINE_FILES) \ + $(SONIC_COPY_FILES) \ + $(SONIC_MAKE_FILES))) +$(SONIC_CACHE_CLEAN_FILES) :: $(FILES_PATH)/%-clean : .platform + @rm -f $($*_DEP_FLAGS_FILE) $($*_MOD_HASH_FILE) $($*_SMOD_HASH_FILE) \ + $($*_MOD_DEP_FILE) $($*_SMOD_DEP_FILE) + + +# Clean all the DEP and SHA files for all the DOCKER target +SONIC_CACHE_CLEAN_TARGETS = $(addsuffix -clean,$(addprefix $(TARGET_PATH)/, \ + $(SONIC_DOCKER_IMAGES) \ + $(SONIC_DOCKER_DBG_IMAGES) \ + $(SONIC_SIMPLE_DOCKER_IMAGES) \ + $(SONIC_INSTALLERS))) +$(SONIC_CACHE_CLEAN_TARGETS) :: $(TARGET_PATH)/%-clean : .platform + @rm -f $($*_DEP_FLAGS_FILE) $($*_MOD_HASH_FILE) $($*_SMOD_HASH_FILE) \ + $($*_MOD_DEP_FILE) $($*_SMOD_DEP_FILE) + + +# Clean all the DEP and SHA files for all the PYTHON DEBS target +SONIC_CACHE_CLEAN_STDEB_DEBS = $(addsuffix -clean,$(addprefix $(PYTHON_DEBS_PATH)/, \ + $(SONIC_PYTHON_STDEB_DEBS))) +$(SONIC_CACHE_CLEAN_STDEB_DEBS) :: $(PYTHON_DEBS_PATH)/%-clean : .platform + @rm -f $($*_DEP_FLAGS_FILE) $($*_MOD_HASH_FILE) $($*_SMOD_HASH_FILE) \ + $($*_MOD_DEP_FILE) $($*_SMOD_DEP_FILE) + + +# Clean all the DEP and SHA files for all the PYTHON WHEELS target +SONIC_CACHE_CLEAN_WHEELS = $(addsuffix -clean,$(addprefix $(PYTHON_WHEELS_PATH)/, \ + $(SONIC_PYTHON_WHEELS))) +$(SONIC_CACHE_CLEAN_WHEELS) :: $(PYTHON_WHEELS_PATH)/%-clean : .platform + @rm -f $($*_DEP_FLAGS_FILE) $($*_MOD_HASH_FILE) $($*_SMOD_HASH_FILE) \ + $($*_MOD_DEP_FILE) $($*_SMOD_DEP_FILE) + +.PHONY: cclean +cclean:: $(SONIC_CACHE_CLEAN_DEBS) $(SONIC_CACHE_CLEAN_FILES) $(SONIC_CACHE_CLEAN_TARGETS) \ + $(SONIC_CACHE_CLEAN_STDEB_DEBS) $(SONIC_CACHE_CLEAN_WHEELS) + +.PHONY: clean +clean:: cclean + +# Clear all the local cache contents +.PHONY:lcclean +lcclean:: + @rm -f $(TARGET_PATH)/cache/* + + + +# List all main targets and its derived target with indent. +listall : + @$(foreach target,$(SONIC_TARGET_LIST),\ + $(eval DPKG:=$(lastword $(subst /, ,$(target)))) \ + $(eval PATH:= $(subst $(DPKG),,$(target))) \ + $(if $($(DPKG)_MAIN_DEB),, + echo "[$(target)] "; \ + $(foreach pkg,$($(DPKG)_DERIVED_DEBS) $($(DPKG)_EXTRA_DEBS),\ + echo " $(PATH)$(pkg)"; \ + )\ + )\ + ) + +#$(addprefix show-,$(SONIC_TARGET_LIST)):show-%: +show-%: + @$(foreach target,$(SONIC_TARGET_LIST),\ + $(eval DPKG:=$(lastword $(subst /, ,$(target)))) \ + $(eval PATH:= $(subst $(DPKG),,$(target))) \ + $(if $(findstring $*,$(target)), + $(info ) \ + $(eval MDPKG:=$(if $($(DPKG)_MAIN_DEB),$($(DPKG)_MAIN_DEB),$(DPKG))) \ + $(info [$(PATH)$(MDPKG)] ) \ + $(foreach pkg,$($(MDPKG)_DERIVED_DEBS) $($(MDPKG)_EXTRA_DEBS),\ + $(info $(SPACE)$(SPACE)$(SPACE)$(SPACE) $(PATH)$(pkg)) \ + )\ + )\ + ) + $(info ) + + + +# Cache prune - Remove least frequently used cache files. +NUMDAYS ?= 7 # Delete all the cache files which are not used within last 7 days +.PHONY: cprune +cprune: + @find $(SONIC_DPKG_CACHE_DIR) -name "*.tgz" ! -mtime -$(NUMDAYS) -exec rm -f {} \; + + + +# Invoke DPKG dependency only if DPKG cache is enabled. +define dpkg_depend + $(if $(filter-out none,$(SONIC_DPKG_CACHE_METHOD)),$(1)) +endef diff --git a/Makefile.work b/Makefile.work new file mode 100644 index 000000000000..654ccb660eb1 --- /dev/null +++ b/Makefile.work @@ -0,0 +1,347 @@ +############################################################################### +## Wrapper for starting make inside sonic-slave container +# +# Supported parameters: +# +# * PLATFORM: Specific platform we wish to build images for. +# * 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. +# * INCLUDE_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. +# * INSTALL_DEBUG_TOOLS: Install debug tools and debug symbol packeages. +# * USERNAME: Desired username -- default at rules/config +# * PASSWORD: Desired password -- default at rules/config +# * KEEP_SLAVE_ON: Keeps slave container up and active after building process concludes. +# * Note that rm=true is still set, so once user quits from the docker +# * session, the docker will be removed. +# * Please note that with current Stretch build structure, +# * user of KEEP_SLAVE_ON feature will have to be conscious +# * about which docker to stay inside after build is done. +# * - If user desires to stay inside Jessie docker, please issue +# * make KEEP_SLAVE_ON=yes jessie +# * - If user desires to stay inside Stretch docker, please issue +# * make NOJESSIE=1 KEEP_SLAVE_ON=yes +# * SOURCE_FOLDER: host path to be mount as /var/$(USER)/src, only effective when KEEP_SLAVE_ON=yes +# * SONIC_BUILD_JOBS: Specifying number of concurrent build job(s) to run +# * VS_PREPARE_MEM: Prepare memory in VS build (drop cache and compact). +# * Default: yes +# * Values: yes, no +# * KERNEL_PROCURE_METHOD: Specifying method of obtaining kernel Debian package: download or build +# * TELEMETRY_WRITABLE: Enable write/config operations via the gNMI interface. +# * Default: unset +# * Values: y +# * SONIC_DPKG_CACHE_METHOD: Specifying method of obtaining the Debian packages from cache: none or cache +# * SONIC_DPKG_CACHE_SOURCE: Debian package cache location when cache enabled for debian packages +# * BUILD_LOG_TIMESTAMP: Set timestamp in the build log (simple/none) +# +############################################################################### + +SHELL = /bin/bash + +USER := $(shell id -un) +PWD := $(shell pwd) +USER_LC := $(shell echo $(USER) | tr A-Z a-z) + +comma := , + +ifeq ($(USER), root) +$(error Add your user account to docker group and use your user account to make. root or sudo are not supported!) +endif + +# Check for j2cli availability +J2_VER := $(shell j2 --version 2>&1 | grep j2cli | awk '{printf $$2}') +ifeq ($(J2_VER),) +$(error Please install j2cli (sudo pip install j2cli)) +endif + +# Check for minimum Docker version on build host +# Note: Using the greater of CE (17.05.0) and EE (17.06.1) versions that support ARG before FROM +docker_min := 17.06.1 +docker_min_ver := $(shell echo "$(docker_min)" | awk -F. '{printf("%d%03d%03d\n",$$1,$$2,$$3);}' 2>/dev/null) +docker_ver := $(shell docker info 2>/dev/null | grep -i "server version" | rev | cut -d' ' -f1 | rev | awk -F. '{printf("%d%03d%03d\n",$$1,$$2,$$3);}' 2>/dev/null) +docker_is_valid := $(shell if [[ "$(docker_ver)" -lt $(docker_min_ver) ]] ; then echo "0"; else echo "1"; fi) +ifeq (0,$(docker_is_valid)) +$(error SONiC requires Docker version $(docker_min) or later) +endif + +# Remove lock file in case previous run was forcefully stopped +$(shell rm -f .screen) + +MAKEFLAGS += -B + +CONFIGURED_ARCH := $(shell [ -f .arch ] && cat .arch || echo $(PLATFORM_ARCH)) +ifeq ($(CONFIGURED_ARCH),) + override CONFIGURED_ARCH = amd64 +endif +ifeq ($(PLATFORM_ARCH),) + override PLATFORM_ARCH = $(CONFIGURED_ARCH) +endif + +ifeq ($(BLDENV), buster) +SLAVE_DIR = sonic-slave-buster +else ifeq ($(BLDENV), stretch) +SLAVE_DIR = sonic-slave-stretch +else +SLAVE_DIR = sonic-slave-jessie +endif + +include rules/config + +ifeq ($(ENABLE_DOCKER_BASE_PULL),) + override ENABLE_DOCKER_BASE_PULL = n +endif + +ifeq ($(CONFIGURED_ARCH),amd64) +SLAVE_BASE_IMAGE = $(SLAVE_DIR) +else +SLAVE_BASE_IMAGE = $(SLAVE_DIR)-$(CONFIGURED_ARCH) +endif +SLAVE_IMAGE = $(SLAVE_BASE_IMAGE)-$(USER_LC) + +# Generate the version control build info +$(shell SONIC_VERSION_CONTROL_COMPONENTS=$(SONIC_VERSION_CONTROL_COMPONENTS) \ + TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) PACKAGE_URL_PREFIX=$(PACKAGE_URL_PREFIX) \ + scripts/generate_buildinfo_config.sh) + +# Generate the slave Dockerfile, and prepare build info for it +$(shell CONFIGURED_ARCH=$(CONFIGURED_ARCH) j2 $(SLAVE_DIR)/Dockerfile.j2 > $(SLAVE_DIR)/Dockerfile) +$(shell CONFIGURED_ARCH=$(CONFIGURED_ARCH) j2 $(SLAVE_DIR)/Dockerfile.user.j2 > $(SLAVE_DIR)/Dockerfile.user) +$(shell BUILD_SLAVE=y scripts/prepare_docker_buildinfo.sh $(SLAVE_BASE_IMAGE) $(SLAVE_DIR)/Dockerfile $(CONFIGURED_ARCH) "" $(BLDENV)) + +# Add the versions in the tag, if the version change, need to rebuild the slave +SLAVE_BASE_TAG = $(shell cat $(SLAVE_DIR)/Dockerfile $(SLAVE_DIR)/buildinfo/versions/versions-* src/sonic-build-hooks/hooks/* | sha1sum | awk '{print substr($$1,0,11);}') +SLAVE_TAG = $(shell cat $(SLAVE_DIR)/Dockerfile.user $(SLAVE_DIR)/Dockerfile $(SLAVE_DIR)/buildinfo/versions/versions-* | sha1sum | awk '{print substr($$1,0,11);}') + +OVERLAY_MODULE_CHECK := \ + lsmod | grep -q "^overlay " &>/dev/null || \ + zgrep -q 'CONFIG_OVERLAY_FS=y' /proc/config.gz &>/dev/null || \ + grep -q 'CONFIG_OVERLAY_FS=y' /boot/config-$(shell uname -r) &>/dev/null || \ + (echo "ERROR: Module 'overlay' not loaded. Try running 'sudo modprobe overlay'."; exit 1) + +BUILD_TIMESTAMP := $(shell date +%Y%m%d\.%H%M%S) + +ifeq ($(DOCKER_BUILDER_MOUNT),) +override DOCKER_BUILDER_MOUNT := "$(PWD):/sonic" +endif + +ifeq ($(DOCKER_BUILDER_WORKDIR),) +override DOCKER_BUILDER_WORKDIR := "/sonic" +endif + +DOCKER_RUN := docker run --rm=true --privileged --init \ + -v $(DOCKER_BUILDER_MOUNT) \ + -w $(DOCKER_BUILDER_WORKDIR) \ + -e "http_proxy=$(http_proxy)" \ + -e "https_proxy=$(https_proxy)" \ + -i$(shell { if [ -t 0 ]; then echo t; fi }) \ + $(SONIC_BUILDER_EXTRA_CMDLINE) + +ifneq ($(DOCKER_BUILDER_USER_MOUNT),) + DOCKER_RUN += $(foreach mount,$(subst $(comma), ,$(DOCKER_BUILDER_USER_MOUNT)), $(addprefix -v , $(mount))) +endif + +ifdef SONIC_BUILD_QUIETER + DOCKER_RUN += -e "SONIC_BUILD_QUIETER=$(SONIC_BUILD_QUIETER)" +endif + +ifneq ($(SONIC_DPKG_CACHE_SOURCE),) + DOCKER_RUN += -v "$(SONIC_DPKG_CACHE_SOURCE):/dpkg_cache:rw" +endif + +ifeq ($(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD), y) + DOCKER_RUN += -v /var/run/docker.sock:/var/run/docker.sock +endif + +ifneq (,$(filter $(CONFIGURED_ARCH), armhf arm64)) +ifeq ($(DOCKER_DATA_ROOT_FOR_MULTIARCH),) + DOCKER_DATA_ROOT_FOR_MULTIARCH := /var/lib/march/docker +endif + # Multiarch docker cannot start dockerd service due to iptables cannot run over different arch kernel + SONIC_SERVICE_DOCKERD_FOR_MULTIARCH=y + SONIC_NATIVE_DOCKERD_FOR_MUTLIARCH := dockerd --experimental=true --storage-driver=vfs \ + --data-root=$(DOCKER_DATA_ROOT_FOR_MULTIARCH) --exec-root=/var/run/march/docker/ \ + -H unix:///var/run/march/docker.sock -p /var/run/march/docker.pid + DOCKER_RUN += -v /var/run/march/docker.sock:/var/run/docker.sock + DOCKER_RUN += -v /var/run/march/docker.pid:/var/run/docker.pid + DOCKER_RUN += -v /var/run/march/docker:/var/run/docker + DOCKER_RUN += -v $(DOCKER_DATA_ROOT_FOR_MULTIARCH):/var/lib/docker + SONIC_USERFACL_DOCKERD_FOR_MUTLIARCH := setfacl -m user:$(USER):rw /var/run/march/docker.sock + + #Override Native config to prevent docker service + SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD=y + + DOCKER_MULTIARCH_CHECK := docker inspect --type image multiarch/qemu-user-static:register &> /dev/null || (echo "multiarch docker not found ..."; docker run --rm --privileged multiarch/qemu-user-static:register --reset --credential yes) + + DOCKER_SERVICE_SAFE_KILLER := (MARCH_PID=`ps -eo pid,cmd | grep "[0-9] dockerd.*march" | awk '{print $$1}'`; echo "Killing march docker $$MARCH_PID"; [ -z "$$MARCH_PID" ] || sudo kill -9 "$$MARCH_PID";) + DOCKER_SERVICE_MULTIARCH_CHECK := ($(DOCKER_SERVICE_SAFE_KILLER); sudo rm -fr /var/run/march/; (echo "Starting docker march service..."; sudo $(SONIC_NATIVE_DOCKERD_FOR_MUTLIARCH) &) &>/dev/null ; sleep 2; sudo $(SONIC_USERFACL_DOCKERD_FOR_MUTLIARCH);) + + # Docker service to load the compiled dockers-*.gz + # docker 19.0 version above has path/length restriction, so replaced it with soft link in /tmp/ + # Also dockerd does mkdir on the provided softlink, so used two level path "d/d" + D_ROOT=/tmp/d/d + SONIC_NATIVE_DOCKERD_FOR_DOCKERFS := rm -fr $(PWD)/dockerfs; mkdir -p $(PWD)/dockerfs; sudo rm -fr /tmp/d; mkdir -p /tmp/d; ln -s -f $(PWD)/dockerfs $(D_ROOT); \ + sudo dockerd --storage-driver=overlay2 --iptables=false \ + --data-root $(D_ROOT)/var/lib/docker/ --exec-root=$(D_ROOT)/var/run/docker/ \ + -H unix://$(D_ROOT)/var/run/docker.sock -p $(D_ROOT)/var/run/docker.pid & + SONIC_USERFACL_DOCKERD_FOR_DOCKERFS := setfacl -m user:$(USER):rw $(D_ROOT)/var/run/docker.sock + DOCKER_SERVICE_DOCKERFS_CHECK := (sudo docker -H unix://$(D_ROOT)/var/run/docker.sock info &> /dev/null && sudo kill -9 `sudo cat $(D_ROOT)/var/run/docker.pid` && false) || (echo "Starting docker build service..."; (sudo $(SONIC_NATIVE_DOCKERD_FOR_DOCKERFS) ) &> /tmp/dockerfs.log ; sleep 1; sudo $(SONIC_USERFACL_DOCKERD_FOR_DOCKERFS);) + +endif + +DOCKER_BASE_BUILD = docker build --no-cache \ + -t $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) \ + --build-arg http_proxy=$(http_proxy) \ + --build-arg https_proxy=$(https_proxy) \ + $(SLAVE_DIR) + +DOCKER_BASE_PULL = docker pull \ + $(REGISTRY_SERVER):$(REGISTRY_PORT)/$(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) + +DOCKER_BUILD = docker build --no-cache \ + --build-arg user=$(USER) \ + --build-arg uid=$(shell id -u) \ + --build-arg guid=$(shell id -g) \ + --build-arg hostname=$(shell echo $$HOSTNAME) \ + --build-arg slave_base_tag_ref=$(SLAVE_BASE_TAG) \ + -t $(SLAVE_IMAGE):$(SLAVE_TAG) \ + -f $(SLAVE_DIR)/Dockerfile.user \ + $(SLAVE_DIR) + +SONIC_BUILD_INSTRUCTION := make \ + -f slave.mk \ + PLATFORM=$(PLATFORM) \ + PLATFORM_ARCH=$(PLATFORM_ARCH) \ + BUILD_NUMBER=$(BUILD_NUMBER) \ + BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) \ + SONIC_IMAGE_VERSION=$(SONIC_IMAGE_VERSION) \ + ENABLE_DHCP_GRAPH_SERVICE=$(ENABLE_DHCP_GRAPH_SERVICE) \ + ENABLE_ZTP=$(ENABLE_ZTP) \ + SHUTDOWN_BGP_ON_START=$(SHUTDOWN_BGP_ON_START) \ + INCLUDE_KUBERNETES=$(INCLUDE_KUBERNETES) \ + KUBERNETES_VERSION=$(KUBERNETES_VERSION) \ + KUBERNETES_CNI_VERSION=$(KUBERNETES_CNI_VERSION) \ + K8s_GCR_IO_PAUSE_VERSION=$(K8s_GCR_IO_PAUSE_VERSION) \ + SONIC_ENABLE_PFCWD_ON_START=$(ENABLE_PFCWD_ON_START) \ + SONIC_ENABLE_SYNCD_RPC=$(ENABLE_SYNCD_RPC) \ + SONIC_INSTALL_DEBUG_TOOLS=$(INSTALL_DEBUG_TOOLS) \ + MDEBUG=$(MDEBUG) \ + PASSWORD=$(PASSWORD) \ + USERNAME=$(USERNAME) \ + SONIC_BUILD_JOBS=$(SONIC_BUILD_JOBS) \ + SONIC_USE_DOCKER_BUILDKIT=$(SONIC_USE_DOCKER_BUILDKIT) \ + VS_PREPARE_MEM=$(VS_PREPARE_MEM) \ + KERNEL_PROCURE_METHOD=$(KERNEL_PROCURE_METHOD) \ + SONIC_DPKG_CACHE_METHOD=$(SONIC_DPKG_CACHE_METHOD) \ + SONIC_DPKG_CACHE_SOURCE=$(SONIC_DPKG_CACHE_SOURCE) \ + HTTP_PROXY=$(http_proxy) \ + HTTPS_PROXY=$(https_proxy) \ + SONIC_INCLUDE_SYSTEM_TELEMETRY=$(INCLUDE_SYSTEM_TELEMETRY) \ + SONIC_INCLUDE_RESTAPI=$(INCLUDE_RESTAPI) \ + TELEMETRY_WRITABLE=$(TELEMETRY_WRITABLE) \ + EXTRA_DOCKER_TARGETS=$(EXTRA_DOCKER_TARGETS) \ + BUILD_LOG_TIMESTAMP=$(BUILD_LOG_TIMESTAMP) \ + SONIC_ENABLE_IMAGE_SIGNATURE=$(ENABLE_IMAGE_SIGNATURE) \ + ENABLE_HOST_SERVICE_ON_START=$(ENABLE_HOST_SERVICE_ON_START) \ + SLAVE_DIR=$(SLAVE_DIR) \ + $(SONIC_OVERRIDE_BUILD_VARS) + +.PHONY: sonic-slave-build sonic-slave-bash init reset + +.DEFAULT_GOAL := all + +%:: +ifneq (,$(filter $(CONFIGURED_ARCH), armhf arm64)) + @$(DOCKER_MULTIARCH_CHECK) +ifneq ($(BLDENV), ) + @$(DOCKER_SERVICE_MULTIARCH_CHECK) + @$(DOCKER_SERVICE_DOCKERFS_CHECK) +endif +endif + @$(OVERLAY_MODULE_CHECK) + + @pushd src/sonic-build-hooks; TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) make all; popd + @cp src/sonic-build-hooks/buildinfo/sonic-build-hooks* $(SLAVE_DIR)/buildinfo + @docker inspect --type image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) &> /dev/null || \ + { [ $(ENABLE_DOCKER_BASE_PULL) == y ] && { echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Pulling...; } && \ + $(DOCKER_BASE_PULL) && \ + { docker tag $(REGISTRY_SERVER):$(REGISTRY_PORT)/$(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) && \ + scripts/collect_docker_version_files.sh $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) target ; } } || \ + { echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Building... ; \ + $(DOCKER_BASE_BUILD) ; \ + scripts/collect_docker_version_files.sh $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) target ; } + @docker inspect --type image $(SLAVE_IMAGE):$(SLAVE_TAG) &> /dev/null || \ + { echo Image $(SLAVE_IMAGE):$(SLAVE_TAG) not found. Building... ; \ + $(DOCKER_BUILD) ; } +ifeq "$(KEEP_SLAVE_ON)" "yes" + ifdef SOURCE_FOLDER + @$(DOCKER_RUN) -v $(SOURCE_FOLDER):/var/$(USER)/src $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_BUILD_INSTRUCTION) $@; scripts/collect_build_version_files.sh \$$?; /bin/bash" + else + @$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_BUILD_INSTRUCTION) $@; scripts/collect_build_version_files.sh \$$?; /bin/bash" + endif +else + @$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_BUILD_INSTRUCTION) $@; scripts/collect_build_version_files.sh \$$?" +endif + +sonic-build-hooks: + @pushd src/sonic-build-hooks; TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) make all; popd + @cp src/sonic-build-hooks/buildinfo/sonic-build-hooks* $(SLAVE_DIR)/buildinfo + +sonic-slave-base-build : sonic-build-hooks + @$(OVERLAY_MODULE_CHECK) + @echo Checking sonic-slave-base image: $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) + @docker inspect --type image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) &> /dev/null || \ + { [ $(ENABLE_DOCKER_BASE_PULL) == y ] && { echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Pulling...; } && \ + $(DOCKER_BASE_PULL) && \ + { docker tag $(REGISTRY_SERVER):$(REGISTRY_PORT)/$(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) && \ + scripts/collect_docker_version_files.sh $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) target ; } } || \ + { echo Image $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) not found. Building... ; \ + $(DOCKER_BASE_BUILD) ; \ + scripts/collect_docker_version_files.sh $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) target ; } + +sonic-slave-build : sonic-slave-base-build + @echo Checking sonic-slave image: $(SLAVE_IMAGE):$(SLAVE_TAG) + @docker inspect --type image $(SLAVE_IMAGE):$(SLAVE_TAG) &> /dev/null || \ + { echo Image $(SLAVE_IMAGE):$(SLAVE_TAG) not found. Building... ; \ + $(DOCKER_BUILD) ; } + +sonic-slave-bash : sonic-slave-build + @$(DOCKER_RUN) -t $(SLAVE_IMAGE):$(SLAVE_TAG) bash + +sonic-slave-run : sonic-slave-build + @$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) bash -c "$(SONIC_RUN_CMDS)" + +showtag: + @echo $(SLAVE_IMAGE):$(SLAVE_TAG) + @echo $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) + +init : + @git submodule update --init --recursive + @git submodule foreach --recursive '[ -f .git ] && echo "gitdir: $$(realpath --relative-to=. $$(cut -d" " -f2 .git))" > .git' + +.ONESHELL : reset +reset : + @echo && echo -n "Warning! All local changes will be lost. Proceed? [y/N]: " + @read ans && ( + if [ $$ans == y ]; then + echo "Resetting local repository. Please wait..."; + $(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) sudo rm -rf fsroot; + if [[ "$(CONFIGURED_ARCH)" == "armhf" || "$(CONFIGURED_ARCH)" == "arm64" ]]; then + echo "Stopping march $(CONFIGURED_ARCH) docker" + sudo kill -9 `sudo cat /var/run/march/docker.pid` || true + sudo rm -f /var/run/march/docker.pid || true + fi + git clean -xfdf; + git reset --hard; + git submodule foreach --recursive 'git clean -xfdf || true'; + git submodule foreach --recursive 'git reset --hard || true'; + git submodule foreach --recursive 'git remote update || true'; + git submodule update --init --recursive; + echo "Reset complete!"; + else + echo "Reset aborted"; + fi ) diff --git a/README.buildsystem.md b/README.buildsystem.md new file mode 100644 index 000000000000..44fa7e5ffffe --- /dev/null +++ b/README.buildsystem.md @@ -0,0 +1,280 @@ +# SONiC Buildimage Guide +## Overview +SONiC buildimage is a *GNU make* based environment for build process automation. +It consists of two main parts: + * Backend - collection of makefiles and other helpers that define generic target groups, used by recipes + * Frontend - collection of recipes, that define metadata for each build target + +## Structure +File structure of SONiC Buildimage is as follows: +``` +sonic-buildimage/ + Makefile + slave.mk + sonic-slave/ + Dockerfile + rules/ + config + functions + recipe1.mk + .. + dockers/ + docker1/ + Dockerfile.template + .. + src/ + submodule1/ + .. + package1/ + Makefile + .. + platform/ + vendor1/ + .. + target/ + debs/ + python-wheels/ +``` +### Backend +**Makefile**, **slave.mk** and **sonic-slave/Dockerfile** are the backend of buildimage. +*slave.mk* is the actual makefile. It defines a set of rules for *target groups* (more on that later). +You can find a make rule for every target that is defined in recipe there. +*Makefile* is a wrapper over sonic-slave docker image. + +Every part of build is executed in a docker container called sonic-slave, specifically crafted for this environment. +If build is started for the first time on a particular host, a new sonic-slave image will be built form *sonic-slave/Dockerfile* on the machine. +It might take some time, so be patient. +After that all subsequent make commands will be executed inside this container. +*Makefile* takes every target that is passed to make command and delegates it as an entry point to a container, +making process of running container transparent. + +### Frontend +**rules/** has a collection of recipes for platform independent targets. +Every recipe is a file that describes a metadata of a specific target, that is needed for its build. +You might find **rules/config** very useful, as it is a configuration file for a build system, which enables/disables some tweaks. +**dockers/** directory is a place where you can find Dockerfiles for generic docker images. +**src/** is a place where a source code for generic packages goes. +It has both submodules (simple case, just run dpkg-buildpackage to build), +and directories with more complcated components, that provide their own Makefiles. +**platform/** contains all vendor-specific recipes, submodules etc. +Every **platform/[VENDOR]/** directory is a derived part of buildimage frontend, that defines rules and targets for a concrete vendor. + +### Build output +**target/** is basically a build output. You can find all build artifacts there. + +## Recipes and target groups +Now let's go over a definition of recipes and target groups. +**Recipe** is a small makefile that defines a target and set of variables for building it. +If you want to add a new target to buildimage (.deb package or docker image), you have to create a recipe for this target. +**Target group** is a set of targets that are built according to the same rules. +Every recipe sets a target group to which this target belongs. + +### Recipe example +Lets take a recipe for swsscommon as an example: +```make +# libswsscommon package + +LIBSWSSCOMMON = libswsscommon_1.0.0_amd64.deb +$(LIBSWSSCOMMON)_SRC_PATH = $(SRC_PATH)/sonic-swss-common +$(LIBSWSSCOMMON)_DEPENDS += $(LIBHIREDIS_DEV) $(LIBNL3_DEV) $(LIBNL_GENL3_DEV) \ + $(LIBNL_ROUTE3_DEV) $(LIBNL_NF3_DEV) \ + $(LIBNL_CLI_DEV) +$(LIBSWSSCOMMON)_RDEPENDS += $(LIBHIREDIS) $(LIBNL3) $(LIBNL_GENL3) \ + $(LIBNL_ROUTE3) $(LIBNL_NF3) $(LIBNL_CLI) +SONIC_DPKG_DEBS += $(LIBSWSSCOMMON) + +LIBSWSSCOMMON_DEV = libswsscommon-dev_1.0.0_amd64.deb +$(eval $(call add_derived_package,$(LIBSWSSCOMMON),$(LIBSWSSCOMMON_DEV))) +``` +First we define our package swsscommon. +Then we secify **SRC_PATH** (path to sources), +**DEPENDS** (build dependencies), +and **RDEPENDS** (runtime dependencies for docker installation). +Then we add our target to SONIC_DPKG_DEBS target group. +At the end we define a dev package for swsscommon and make it derived from main one. +Using **add_derived_package** just makes a deep copy of package's metadata, so that we don't have to repeat ourselves. + +### Target groups +**SONIC_DPKG_DEBS** +Main target group for building .deb packages. +Define: +```make +SOME_NEW_DEB = some_new_deb.deb # name of your package +$(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name # path to directory with sources +$(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # build dependencies +$(SOME_NEW_DEB)_RDEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # runtime dependencies +SONIC_DPKG_DEBS += $(SOME_NEW_DEB) # add package to this target group +``` + +**SONIC_PYTHON_STDEB_DEBS** +Same as above, but instead of building package using dpkg-buildpackage it executes `python setup.py --command-packages=stdeb.command bdist_deb`. +Define: +```make +SOME_NEW_DEB = some_new_deb.deb # name of your package +$(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name # path to directory with sources +$(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # build dependencies +$(SOME_NEW_DEB)_RDEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # runtime dependencies +SONIC_PYTHON_STDEB_DEBS += $(SOME_NEW_DEB) # add package to this target group +``` + +**SONIC_MAKE_DEBS** +This is a bit more flexible case. +If you have to do some specific type of build or apply pathes prior to build, just define your own Makefile and add it to buildimage. +Define: +```make +SOME_NEW_DEB = some_new_deb.deb # name of your package +$(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name # path to directory with sources +$(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # build dependencies +$(SOME_NEW_DEB)_RDEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... # runtime dependencies +SONIC_MAKE_DEBS += $(SOME_NEW_DEB) # add package to this target group +``` + +If some packages have to be built locally due to some legal issues or they are already prebuilt and available online, you might find next four target groups useful. + +**SONIC_COPY_DEBS** +Those packages will be just copied from specified location on your machine. +Define: +```make +SOME_NEW_DEB = some_new_deb.deb # name of your package +$(SOME_NEW_DEB)_PATH = path/to/some_new_deb.deb # path to file +SONIC_COPY_DEBS += $(SOME_NEW_DEB) # add package to this target group +``` + +**SONIC_COPY_FILES** +Same as above, but applicable for regular files. Use when you need some regular files for installation in docker container. +Define: +```make +SOME_NEW_FILE = some_new_file # name of your file +$(SOME_NEW_FILE)_PATH = path/to/some_new_file # path to file +SONIC_COPY_FILES += $(SOME_NEW_FILE) # add file to this target group +``` + +**SONIC_ONLINE_DEBS** +Target group for debian packages that should be fetched from an online source. +Define: +```make +SOME_NEW_DEB = some_new_deb.deb # name of your package +$(SOME_NEW_DEB)_URL = https://url/to/this/deb.deb # path to file # URL for downloading +SONIC_ONLINE_DEBS += $(SOME_NEW_DEB) # add file to this target group +``` + +**SONIC_ONLINE_FILES** +Target group for regular files that should be fetched from an online source. +Define: +```make +SOME_NEW_FILE = some_new_file # name of your file +$(SOME_NEW_FILE)_URL = https://url/to/this/file # URL for downloading +SONIC_ONLINE_FILES += $(SOME_NEW_FILE) # add file to this target group +``` + +Docker images also have their target groups. +**SONIC_SIMPLE_DOCKER_IMAGES** +As you see from a name of the group, it is intended to build a docker image from a regular Dockerfile. +Define: +```make +SOME_DOCKER = some_docker.gz # name of your docker +$(SOME_DOCKER)_PATH = path/to/your/docker # path to your Dockerfile +SONIC_SIMPLE_DOCKER_IMAGES += $(SOME_DOCKER) # add docker to this group +``` + +**SONIC_DOCKER_IMAGES** +This one is a bit more sophisticated. You can define debian packages from buildimage that will be installed to it, and corresponding Dockerfile will be dinamically generated from a template. +Define: +```make +SOME_DOCKER = some_docker.gz # name of your docker +$(SOME_DOCKER)_PATH = path/to/your/docker # path to your Dockerfile +$(SOME_DOCKER)_DEPENDS += $(SOME_DEB1) $(SOME_DEB2) # .deb packages to install into image +$(SOME_DOCKER)_PYTHON_WHEELS += $(SOME_WHL1) $(SOME_WHL2) # python wheels to install into image +$(SOME_DOCKER)_LOAD_DOCKERS += $(SOME_OTHER_DOCkER) # docker image from which this one is built +SONIC_DOCKER_IMAGES += $(SOME_DOCKER) # add docker to this group +``` + +## Tips & Tricks +Although every target is built inside a sonic-slave container, which exits at the end of build, you can enter bash of sonic-slave using this command: +``` +$ make sonic-slave-bash +``` +It is very useful for debugging when you add a new target and facing some troubles. + +sonic-slave environment is built only once, but if sonic-slave/Dockerfile was updated, you can rebuild it with this command: +``` +$ make sonic-slave-build +``` + +One can print out all available targets by executing the following command: +``` +$ make list +``` + +All target groups are used by one or another recipe, so use those recipes as a reference when adding new ones. + +## Build debug dockers and debug SONiC installer image: +Using 'INSTALL_DEBUG_TOOLS=y' builds the debug image. + +For example: +`INSTALL_DEBUG_TOOLS=y make target/sonic-broadcom.bin` + +* Builds debug docker images. +* Debug images carry a suffix of "-dbg" + * e.g. target/docker-orchagent-dbg.gz +* target/sonic-broadcom.bin is built using debug docker images + * Selective sources are archived and available under /src + * An empty /debug dir is created for use during debug session. + * All debug dockers are mounted with /src:ro and /debug:rw + * Login banner will briefly describe these features. + + +_Note: target/sonic-broadcom.bin name is the same irrespective of built using debug or non-debug dockers._ + +_Recommend: Rename image built using INSTALL_DEBUG_TOOLS=y to mark it explicit. May be `mv target/sonic-broadcom.bin target/sonic-broadcom-dbg.bin`_ + +### Debug dockers +* Built with all available debug symbols. +* Installed with many basic packages that would be required for debugging + * gdb + * gdbserver + * vim + * strace + * openssh-client + * sshpass +* Loadable into any environment that supports docker +* Outside SONiC image, you may run the docker with `--entrypoint=/bin/bash` +* Use -v to map any of your host directories +* To debug a core file in non-SONiC environment that supports docker + * `docker load -i docker--dbg.gz` + * copy your unzipped core file into ~/debug + * `docker run -it --entrypoint=/bin/bash -v ~/debug:/debug ` + * `gdb /usr/bin/ -c /debug/` + +### Debug SONiC image + +* Install this image into the switch that supports this image. + * For platform independent binary, you may use a debug image for virtual switch +* Open the archive in /src, if you would need source code for debugging +* Every debug enabled docker is mounted with /src as read-only +* The host has /debug dir and it is mapped into every debuggable docker as /debug with read-write permission. +* To debug a core + * Copy core into /debug of host and unzip it + * Feel free to create & use sub-dirs as needed. + * Entire /debug is mounted inside docker + * Get into the docker (`docker -it exec bash`) + * `gdb /usr/bin/ -c /debug/` + * Use set-directory in gdb to map appropriate source dir from under /src + * You may set gdb logs to go into /debug +* For live debugging + * Use this as a regular switch + * Get into docker, and you may + * start process under dbg + * attach gdb to running process + * Set required source dir from under /src as needed + * May use /debug to record all geb logs or any spew from debug session. + + ### To enhance debug dockers + * Add to `_DBG_IMAGE_PACKAGES`, additional debug tools that will be pre-installed during build. + * e.g. `$(DOCKER_ORCHAGENT)_DBG_IMAGE_PACKAGES += perl` + * Build will install these tools using "apt" + * Add to `_DBG_DEPENDS`, additional debug .deb packages that will be pre-installed during build. + * e.g. `$(DOCKER_ORCHAGENT)_DBG_DEPENDS += $(SWSS_DBG) $(LIBSWSSCOMMON_DBG) $(LIBSAIREDIS_DBG)` + * Add to `DBG_SRC_ARCHIVE`, the source dirs to archive + * The source files (.c, .cpp, .h & .hpp) under this dir tree are archived. + * e.g. rules/swss.mk has `DBG_SRC_ARCHIVE += swss` diff --git a/README.md b/README.md index d6525945899e..680a9b5140ba 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,230 @@ -# Build Switch Images - buildimage +*static analysis*: + +[![Total alerts](https://img.shields.io/lgtm/alerts/g/Azure/sonic-buildimage.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Azure/sonic-buildimage/alerts/) +[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/Azure/sonic-buildimage.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Azure/sonic-buildimage/context:python) + + +*master builds*: + +[![Barefoot](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-all/badge/icon?subject=Barefoot)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-all) +[![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-all/badge/icon?subject=Broadcom)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-all) +[![Centec](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-all/badge/icon?subject=Centec)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-all) +[![Centec(arm64)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-arm64-all/badge/icon?subject=Centec(arm64))](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-arm64-all) +[![Innovium](https://sonic-jenkins.westus2.cloudapp.azure.com/job/innovium/job/buildimage-invm-all/badge/icon?subject=Innovium)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/innovium/job/buildimage-invm-all) +[![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-all/badge/icon?subject=Mellanox)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-all) +[![Marvell(armhf)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-armhf-all/badge/icon?subject=Marvell(armhf))](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-armhf-all) +[![Nephos](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-all/badge/icon?subject=Nephos)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-all) +[![P4](https://sonic-jenkins.westus2.cloudapp.azure.com/job/p4/job/buildimage-p4-all/badge/icon?subject=P4)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/p4/job/buildimage-p4-all) +[![VS](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-image/badge/icon?subject=VS)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-image) + +*202012 builds*: + +[![Barefoot](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-202012/badge/icon?subject=Barefoot)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-202012/) +[![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-202012/badge/icon?subject=Broadcom)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-202012) +[![Centec](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-202012/badge/icon?subject=Centec)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-202012) +[![Centec(arm64)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-arm64-202012/badge/icon?subject=Centec(arm64))](https://sonic-jenkins.westus2.cloudapp.azure.com/job/centec/job/buildimage-centec-arm64-202012) +[![Innovium](https://sonic-jenkins.westus2.cloudapp.azure.com/job/innovium/job/buildimage-invm-202012/badge/icon?subject=Innovium)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/innovium/job/buildimage-invm-202012/) +[![Marvell(armhf)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-armhf-202012/badge/icon?subject=Marvell(armhf))](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-armhf-202012) +[![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-202012/badge/icon?subject=Mellanox)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-202012) +[![Nephos](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-202012/badge/icon?subject=Nephos)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-202012) +[![VS](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-image-202012/badge/icon?subject=VS)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-image-202012) + +*201911 builds*: + +[![Barefoot](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-201911/badge/icon?subject=Barefoot)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-201911/) +[![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201911/badge/icon?subject=Broadcom)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201911/) +[![Innovium](https://sonic-jenkins.westus2.cloudapp.azure.com/job/innovium/job/buildimage-invm-201911/badge/icon?subject=Innovium)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/innovium/job/buildimage-invm-201911/) +[![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201911/badge/icon?subject=Mellanox)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201911/) +[![Nephos](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201911/badge/icon?subject=Nephos)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201911) +[![VS](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-201911/badge/icon?subject=VS)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-201911) + +*201811 builds*: + +[![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201811/badge/icon?subject=Broadcom)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201811/) +[![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201811/badge/icon?subject=Mellanox)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201811/) +[![Innovium](https://sonic-jenkins.westus2.cloudapp.azure.com/job/innovium/job/buildimage-invm-201811/badge/icon?subject=Innovium)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/innovium/job/buildimage-invm-201811/) +[![Nephos](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201811/badge/icon?subject=Nephos)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201811) +[![VS](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-201811/badge/icon?subject=VS)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-201811) + +*201807 builds*: + +[![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201807/badge/icon?subject=Broadcom)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201807/) +[![Barefoot](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-201807/badge/icon?subject=Barefoot)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/barefoot/job/buildimage-bf-201807/) + +*201803 builds*: + +[![Broadcom](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201803/badge/icon?subject=Broadcom)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/broadcom/job/buildimage-brcm-201803/) +[![Nephos](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201803/badge/icon?subject=Nephos)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/nephos/job/buildimage-nephos-201803/) +[![Marvell](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-201803/badge/icon?subject=Marvell)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/marvell/job/buildimage-mrvl-201803/) +[![Mellanox](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201803/badge/icon?subject=Mellanox)](https://sonic-jenkins.westus2.cloudapp.azure.com/job/mellanox/job/buildimage-mlnx-201803/) + +# sonic-buildimage + +## Build SONiC Switch Images # Description -Build an [Open Network Install Environment (ONIE)](https://github.com/opencomputeproject/onie) compatiable network operating system (NOS) installer image for network switches, and also build docker images running inside the NOS. -# Usage -## Build NOS installer image +Following is the instruction on how to build an [(ONIE)](https://github.com/opencomputeproject/onie) compatible network operating system (NOS) installer image for network switches, and also how to build docker images running inside the NOS. Note that SONiC image are build per ASIC platform. Switches using the same ASIC platform share a common image. For a list of supported switches and ASIC, please refer to this [list](https://github.com/Azure/SONiC/wiki/Supported-Devices-and-Platforms) + +# Hardware +Any server can be a build image server. We are using a server with 1T hard disk. The OS is Ubuntu 16.04. + +## Prerequisites + +Install pip and jinja in host build machine, execute below commands if j2/j2cli is not available: + + sudo apt-get install -y python-pip + sudo python2 -m pip install -U pip==9.0.3 + sudo pip install --force-reinstall --upgrade jinja2>=2.10 + sudo pip install j2cli + +Configure your system to allow running the 'docker' command without 'sudo': + Add current user to the docker group + `sudo gpasswd -a ${USER} docker` + Log out and log back in so that your group membership is re-evaluated + +## SAI Version +Please refer to [SONiC roadmap](https://github.com/Azure/SONiC/wiki/Sonic-Roadmap-Planning) on the SAI version for each SONiC release. + +## Clone or fetch the code repository with all git submodules +To clone the code repository recursively, assuming git version 1.9 or newer: + + git clone https://github.com/Azure/sonic-buildimage.git + +## Usage + +To build SONiC installer image and docker images, run the following commands: + + # Ensure the 'overlay' module is loaded on your development system + sudo modprobe overlay + + # Enter the source directory + cd sonic-buildimage + + # (Optional) Checkout a specific branch. By default, it uses master branch. For example, to checkout the branch 201911, use "git checkout 201911" + git checkout [branch_name] + + # Execute make init once after cloning the repo, or after fetching remote repo with submodule updates + make init + + # Execute make configure once to configure ASIC + make configure PLATFORM=[ASIC_VENDOR] - ./build_debian USERNAME PASSWORD_ENCRYPTED && ./build_image.sh - -For example, the user name is 'acsadmin' and the password is 'YourPaSsWoRd'. + # Build SONiC image + make all - ./build_debian.sh "acsadmin" "$(perl -e 'print crypt("YourPaSsWoRd", "salt"),"\n"')" && ./build_image.sh +## Usage for ARM Architecture +To build Arm32 bit for (ARMHF) platform + ARM build has dependency in docker version 18, + if docker version is 19, downgrade to 18 as below + sudo apt-get install --allow-downgrades -y docker-ce=5:18.09.0~3-0~ubuntu-xenial + sudo apt-get install --allow-downgrades -y docker-ce-cli=5:18.09.0~3-0~ubuntu-xenial -The root is disabled, but the created user could sudo. + # Execute make configure once to configure ASIC and ARCH + make configure PLATFORM=[ASIC_VENDOR] PLATFORM_ARCH=armhf -## Build docker images + make target/sonic-[ASIC_VENDER]-armhf.bin - ./build_docker.sh docker-sswsyncd - ./build_docker.sh docker-database - ./build_docker.sh docker-bgp - ./build_docker.sh docker-snmp - ./build_docker.sh docker-lldp + # example: -# Contribution guide + make configure PLATFORM=marvell-armhf PLATFORM_ARCH=armhf -All contributors must sign a contribution license agreement before contributions can be accepted. Contact kasubra@microsoft.com or daloher@microsoft.com. Later this will be automated. + make target/sonic-marvell-armhf.bin -### GitHub Workflow + + +To build Arm64 bit for platform + + # Execute make configure once to configure ASIC and ARCH + + make configure PLATFORM=[ASIC_VENDOR] PLATFORM_ARCH=arm64 + + # example: + + make configure PLATFORM=marvell-arm64 PLATFORM_ARCH=arm64 + + + **NOTE**: + +- Recommend reserving 50G free space to build one platform. +- If Docker's workspace folder, `/var/lib/docker`, resides on a partition without sufficient free space, you may encounter an error like the following during a Docker container build job: + + `/usr/bin/tar: /path/to/sonic-buildimage/: Cannot write: No space left on device` + + The solution is to [move the directory](https://linuxconfig.org/how-to-move-docker-s-default-var-lib-docker-to-another-directory-on-ubuntu-debian-linux) to a partition with more free space. +- Use `http_proxy=[your_proxy] https_proxy=[your_proxy] make` to enable http(s) proxy in the build process. +- Add your user account to `docker` group and use your user account to make. `root` or `sudo` are not supported. + +The SONiC installer contains all docker images needed. SONiC uses one image for all devices of a same ASIC vendor. The supported ASIC vendors are: + +- PLATFORM=broadcom +- PLATFORM=marvell +- PLATFORM=mellanox +- PLATFORM=cavium +- PLATFORM=centec +- PLATFORM=nephos +- PLATFORM=innovium +- PLATFORM=p4 +- PLATFORM=vs + +For Broadcom ASIC, we build ONIE and EOS image. EOS image is used for Arista devices, ONIE image is used for all other Broadcom ASIC based devices. + + make configure PLATFORM=broadcom + # build debian stretch required targets + BLDENV=stretch make stretch + # build ONIE image + make target/sonic-broadcom.bin + # build EOS image + make target/sonic-aboot-broadcom.swi + +You may find the rules/config file useful. It contains configuration options for the build process, like adding more verbosity or showing dependencies, username and password for base image etc. + +Every docker image is built and saved to target/ directory. +So, for instance, to build only docker-database, execute: + + make target/docker-database.gz + +Same goes for debian packages, which are under target/debs/: + + make target/debs/swss_1.0.0_amd64.deb + +Every target has a clean target, so in order to clean swss, execute: + + make target/debs/swss_1.0.0_amd64.deb-clean + +It is recommended to use clean targets to clean all packages that are built together, like dev packages for instance. In order to be more familiar with build process and make some changes to it, it is recommended to read this short [Documentation](README.buildsystem.md). + +## Build debug dockers and debug SONiC installer image: +SONiC build system supports building dockers and ONE-image with debug tools and debug symbols, to help with live & core debugging. For details refer to [(SONiC Buildimage Guide)](https://github.com/Azure/sonic-buildimage/blob/master/README.buildsystem.md). + +## Notes: +- If you are running make for the first time, a sonic-slave-${USER} docker image will be built automatically. +This may take a while, but it is a one-time action, so please be patient. + +- The root user account is disabled. However, the created user can `sudo`. + +- The target directory is `./target`, containing the NOS installer image and docker images. + - sonic-generic.bin: SONiC switch installer image (ONIE compatible) + - sonic-aboot.bin: SONiC switch installer image (Aboot compatible) + - docker-base.gz: base docker image where other docker images are built from, only used in build process (gzip tar archive) + - docker-database.gz: docker image for in-memory key-value store, used as inter-process communication (gzip tar archive) + - docker-fpm.gz: docker image for quagga with fpm module enabled (gzip tar archive) + - docker-orchagent.gz: docker image for SWitch State Service (SWSS) (gzip tar archive) + - docker-syncd-brcm.gz: docker image for the daemon to sync database and Broadcom switch ASIC (gzip tar archive) + - docker-syncd-cavm.gz: docker image for the daemon to sync database and Cavium switch ASIC (gzip tar archive) + - docker-syncd-mlnx.gz: docker image for the daemon to sync database and Mellanox switch ASIC (gzip tar archive) + - docker-syncd-nephos.gz: docker image for the daemon to sync database and Nephos switch ASIC (gzip tar archive) + - docker-syncd-invm.gz: docker image for the daemon to sync database and Innovium switch ASIC (gzip tar archive) + - docker-sonic-p4.gz: docker image for all-in-one for p4 software switch (gzip tar archive) + - docker-sonic-vs.gz: docker image for all-in-one for software virtual switch (gzip tar archive) + - docker-sonic-mgmt.gz: docker image for [managing, configuring and monitoring SONiC](https://github.com/Azure/sonic-mgmt) (gzip tar archive) + +## Contribution Guide + +All contributors must sign a contribution license agreement before contributions can be accepted. Contact [sonic-cla-agreements@microsoft.com](mailto:sonic-cla-agreements@microsoft.com). + +## GitHub Workflow We're following basic GitHub Flow. If you have no idea what we're talking about, check out [GitHub's official guide](https://guides.github.com/introduction/flow/). Note that merge is only performed by the repository maintainer. @@ -59,3 +256,5 @@ For example: * Push your changes to your private fork and do "pull-request" to this repository * Use a pull request to do code review * Use issues to keep track of what is going on + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/ThirdPartyLicenses.txt b/ThirdPartyLicenses.txt index 99bc267e11f9..376506337e79 100644 --- a/ThirdPartyLicenses.txt +++ b/ThirdPartyLicenses.txt @@ -976,3 +976,197 @@ Microsoft is offering you a license to use the following components, to the exte * Public License instead of this License. But first, please read * . */ + +4. apt-clean, apt-gzip-indexes, apt-no-languages imported from docker v1.11.1 +/* + * Apache License + * Version 2.0, January 2004 + * https://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * Copyright 2013-2016 Docker, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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. + */ diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 000000000000..5d36ff5be8ec --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,136 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +trigger: + branches: + include: + - master + - 202012 + paths: + exclude: + - .github + +pr: + branches: + include: + - master + paths: + exclude: + - .github + +name: $(TeamProject)_$(Build.DefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) + +resources: + repositories: + - repository: sonic-mgmt + type: github + name: Azure/sonic-mgmt + endpoint: build + +stages: +- stage: Build + pool: sonicbld + + jobs: + - template: .azure-pipelines/build-template.yml + parameters: + platform: broadcom + platform_short: brcm + cache_mode: rcache + sync_rpc_image: true + + - template: .azure-pipelines/build-template.yml + parameters: + platform: mellanox + platform_short: mlnx + cache_mode: rcache + sync_rpc_image: true + + - template: .azure-pipelines/build-template.yml + parameters: + platform: vs + platform_short: vs + cache_mode: rcache + +- stage: Test + variables: + - name: inventory + value: veos_vtb + - name: testbed_file + value: vtestbed.csv + + jobs: + - job: + pool: sonictest + displayName: "vstest" + timeoutInMinutes: 60 + steps: + - checkout: self + clean: true + submodules: recursive + displayName: 'Checkout code' + + - task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: build + pipeline: 9 + artifacts: sonic-swss-common.amd64.ubuntu20_04 + runVersion: 'latestFromBranch' + runBranch: 'refs/heads/master' + displayName: "Download sonic swss common deb packages" + + - task: DownloadPipelineArtifact@2 + inputs: + artifact: sonic-buildimage.vs + displayName: "Download sonic-buildimage.vs artifact" + + - script: | + set -x + sudo dpkg -i --force-confask,confnew ../sonic-swss-common.amd64.ubuntu20_04/libswsscommon_1.0.0_amd64.deb + sudo dpkg -i ../sonic-swss-common.amd64.ubuntu20_04/python3-swsscommon_1.0.0_amd64.deb + sudo docker load -i ../target/docker-sonic-vs.gz + docker tag docker-sonic-vs:latest docker-sonic-vs:$(Build.BuildNumber) + username=$(id -un) + + trap "docker ps; docker images; ip netns list; \ + docker rmi docker-sonic-vs:$(Build.BuildNumber); \ + ip netns list | grep -E [-]srv[0-9]+ | awk '{print $1}' | xargs -I {} sudo ip netns delete {}; \ + sudo chown -R ${username}.${username} .; \ + sudo chown -R ${username}.${username} $(System.DefaultWorkingDirectory)" EXIT + pushd platform/vs/tests + sudo py.test -v --junitxml=tr.xml --imgname=docker-sonic-vs:$(Build.BuildNumber) + displayName: "Run vs tests" + + - task: PublishTestResults@2 + inputs: + testResultsFiles: '**/tr.xml' + testRunTitle: vstest + + - job: + pool: sonictest + displayName: "kvmtest-t0" + timeoutInMinutes: 240 + + steps: + - template: .azure-pipelines/run-test-template.yml + parameters: + dut: vlab-01 + tbname: vms-kvm-t0 + ptf_name: ptf_vms6-1 + tbtype: t0 + + - job: + pool: sonictest-t1-lag + displayName: "kvmtest-t1-lag" + timeoutInMinutes: 240 + + steps: + - template: .azure-pipelines/run-test-template.yml + parameters: + dut: vlab-03 + tbname: vms-kvm-t1-lag + ptf_name: ptf_vms6-2 + tbtype: t1-lag diff --git a/build_debian.sh b/build_debian.sh index 453a6c1d6cf6..abe5612e293e 100755 --- a/build_debian.sh +++ b/build_debian.sh @@ -3,26 +3,22 @@ ## an ONIE installer image. ## ## USAGE: -## ./build_debian USERNAME PASSWORD_ENCRYPTED -## PARAMETERS: +## USERNAME=username PASSWORD=password ./build_debian +## ENVIRONMENT: ## USERNAME ## The name of the default admin user -## PASSWORD_ENCRYPTED -## The encrypted password, expected by chpasswd command +## PASSWORD +## The password, expected by chpasswd command ## Default user -USERNAME=$1 [ -n "$USERNAME" ] || { - echo "Error: no or empty USERNAME argument" + echo "Error: no or empty USERNAME" exit 1 } -## Password for the default user, customizable by environment variable -## By default it is an empty password -## You may get a crypted password by: perl -e 'print crypt("YourPaSsWoRd", "salt"),"\n"' -PASSWORD_ENCRYPTED=$2 -[ -n "$PASSWORD_ENCRYPTED" ] || { - echo "Error: no or empty PASSWORD_ENCRYPTED argument" +## Password for the default user +[ -n "$PASSWORD" ] || { + echo "Error: no or empty PASSWORD" exit 1 } @@ -32,11 +28,20 @@ PASSWORD_ENCRYPTED=$2 ## Enable debug output for script set -x -e +CONFIGURED_ARCH=$([ -f .arch ] && cat .arch || echo amd64) + +## docker engine version (with platform) +DOCKER_VERSION=5:18.09.8~3-0~debian-$IMAGE_DISTRO +LINUX_KERNEL_VERSION=4.19.0-12-2 + ## Working directory to prepare the file system FILESYSTEM_ROOT=./fsroot +PLATFORM_DIR=platform ## Hostname for the linux image -HOSTNAME=acs +HOSTNAME=sonic DEFAULT_USERINFO="Default admin user,,," +BUILD_TOOL_PATH=src/sonic-build-hooks/buildinfo +TRUSTED_GPG_DIR=$BUILD_TOOL_PATH/trusted.gpg.d ## Read ONIE image related config file . ./onie-image.conf @@ -55,121 +60,388 @@ DEFAULT_USERINFO="Default admin user,,," ## Prepare the file system directory if [[ -d $FILESYSTEM_ROOT ]]; then - sudo rm -r $FILESYSTEM_ROOT || die "Failed to clean chroot directory" + sudo rm -rf $FILESYSTEM_ROOT || die "Failed to clean chroot directory" fi mkdir -p $FILESYSTEM_ROOT +mkdir -p $FILESYSTEM_ROOT/$PLATFORM_DIR +mkdir -p $FILESYSTEM_ROOT/$PLATFORM_DIR/x86_64-grub +touch $FILESYSTEM_ROOT/$PLATFORM_DIR/firsttime + +## make / as a mountpoint in chroot env, needed by dockerd +pushd $FILESYSTEM_ROOT +sudo mount --bind . . +popd -## Build a basic Debian system by debootstrap -echo '[INFO] Debootstrap...' -sudo debootstrap --arch amd64 jessie $FILESYSTEM_ROOT http://ftp.us.debian.org/debian +## Build the host debian base system +echo '[INFO] Build host debian base system...' +TARGET_PATH=$TARGET_PATH scripts/build_debian_base_system.sh $CONFIGURED_ARCH $IMAGE_DISTRO $FILESYSTEM_ROOT + +# Prepare buildinfo +sudo scripts/prepare_debian_image_buildinfo.sh $CONFIGURED_ARCH $IMAGE_DISTRO $FILESYSTEM_ROOT $http_proxy ## Config hostname and hosts, otherwise 'sudo ...' will complain 'sudo: unable to resolve host ...' sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '$HOSTNAME' > /etc/hostname" sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '127.0.0.1 $HOSTNAME' >> /etc/hosts" +sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '127.0.0.1 localhost' >> /etc/hosts" ## Config basic fstab sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c 'echo "proc /proc proc defaults 0 0" >> /etc/fstab' sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c 'echo "sysfs /sys sysfs defaults 0 0" >> /etc/fstab' +## Setup proxy +[ -n "$http_proxy" ] && sudo /bin/bash -c "echo 'Acquire::http::Proxy \"$http_proxy\";' > $FILESYSTEM_ROOT/etc/apt/apt.conf.d/01proxy" + +trap_push 'sudo LANG=C chroot $FILESYSTEM_ROOT umount /proc || true' +sudo LANG=C chroot $FILESYSTEM_ROOT mount proc /proc -t proc ## Note: mounting is necessary to makedev and install linux image echo '[INFO] Mount all' ## Output all the mounted device for troubleshooting -mount -trap_push 'sudo umount $FILESYSTEM_ROOT/proc || true' -sudo LANG=C chroot $FILESYSTEM_ROOT mount proc /proc -t proc -clean_sys() { - sudo umount $FILESYSTEM_ROOT/sys/fs/cgroup/* \ - $FILESYSTEM_ROOT/sys/fs/cgroup \ - $FILESYSTEM_ROOT/sys || true -} -trap_push 'sudo umount $FILESYSTEM_ROOT/sys || true' -sudo LANG=C chroot $FILESYSTEM_ROOT mount sysfs /sys -t sysfs +sudo LANG=C chroot $FILESYSTEM_ROOT mount + +## Install the trusted gpg public keys +[ -d $TRUSTED_GPG_DIR ] && [ ! -z "$(ls $TRUSTED_GPG_DIR)" ] && sudo cp $TRUSTED_GPG_DIR/* ${FILESYSTEM_ROOT}/etc/apt/trusted.gpg.d/ ## Pointing apt to public apt mirrors and getting latest packages, needed for latest security updates -sudo cp files/sources.list $FILESYSTEM_ROOT/etc/apt/ +sudo cp files/apt/sources.list.$CONFIGURED_ARCH $FILESYSTEM_ROOT/etc/apt/sources.list +sudo cp files/apt/apt.conf.d/{81norecommends,apt-{clean,gzip-indexes,no-languages},no-check-valid-until} $FILESYSTEM_ROOT/etc/apt/apt.conf.d/ ## Note: set lang to prevent locale warnings in your chroot sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y update sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y upgrade echo '[INFO] Install packages for building image' -sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install makedev psmisc +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install makedev psmisc systemd-sysv ## Create device files echo '[INFO] MAKEDEV' -sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c 'cd /dev && MAKEDEV generic' +if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then + sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c 'cd /dev && MAKEDEV generic-arm' +else + sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c 'cd /dev && MAKEDEV generic' +fi ## Install initramfs-tools and linux kernel ## Note: initramfs-tools recommends depending on busybox, and we really want busybox for ## 1. commands such as touch ## 2. mount supports squashfs ## However, 'dpkg -i' plus 'apt-get install -f' will ignore the recommended dependency. So ## we install busybox explicitly -sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install busybox -echo '[INFO] Install ACS linux kernel image' +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install busybox linux-base +echo '[INFO] Install SONiC linux kernel image' ## Note: duplicate apt-get command to ensure every line return zero -sudo dpkg --root=$FILESYSTEM_ROOT -i deps/initramfs-tools_*.deb || \ +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/initramfs-tools-core_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/initramfs-tools_*.deb || \ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f -sudo dpkg --root=$FILESYSTEM_ROOT -i deps/linux-image-3.16.0-4-amd64_*.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 - -## Update initramfs for booting with squashfs+aufs +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install acl +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 +## Hook into initramfs: change fs type from vfat to ext4 on arista switches +sudo mkdir -p $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/ +sudo cp files/initramfs-tools/arista-convertfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-convertfs +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-convertfs +sudo cp files/initramfs-tools/arista-hook $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-hook +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-hook +sudo cp files/initramfs-tools/mke2fs $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/mke2fs +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/mke2fs +sudo cp files/initramfs-tools/setfacl $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/setfacl +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/setfacl + +# Hook into initramfs: rename the management interfaces on arista switches +sudo cp files/initramfs-tools/arista-net $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-net +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-net + +# Hook into initramfs: resize root partition after migration from another NOS to SONiC on Dell switches +sudo cp files/initramfs-tools/resize-rootfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/resize-rootfs +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/resize-rootfs + +# Hook into initramfs: run fsck to repair a non-clean filesystem prior to be mounted +sudo cp files/initramfs-tools/fsck-rootfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/fsck-rootfs +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/fsck-rootfs + ## Hook into initramfs: after partition mount and loop file mount ## 1. Prepare layered file system -## 2. Bind-mount docker working directory (docker aufs cannot work over aufs rootfs) +## 2. Bind-mount docker working directory (docker overlay storage cannot work over overlay rootfs) sudo cp files/initramfs-tools/union-mount $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/union-mount sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/union-mount +sudo cp files/initramfs-tools/varlog $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/varlog +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/varlog +# Management interface (eth0) dhcp can be optionally turned off (during a migration from another NOS to SONiC) +#sudo cp files/initramfs-tools/mgmt-intf-dhcp $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/mgmt-intf-dhcp +#sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/mgmt-intf-dhcp sudo cp files/initramfs-tools/union-fsck $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/union-fsck sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/union-fsck -sudo chroot $FILESYSTEM_ROOT update-initramfs -u +pushd $FILESYSTEM_ROOT/usr/share/initramfs-tools/scripts/init-bottom && sudo patch -p1 < $OLDPWD/files/initramfs-tools/udev.patch; popd +if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then + sudo cp files/initramfs-tools/uboot-utils $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/uboot-utils + sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/uboot-utils + cat files/initramfs-tools/modules.arm | sudo tee -a $FILESYSTEM_ROOT/etc/initramfs-tools/modules > /dev/null +fi +# Update initramfs for load platform specific modules +if [ -f platform/$CONFIGURED_PLATFORM/modules ]; then + cat platform/$CONFIGURED_PLATFORM/modules | sudo tee -a $FILESYSTEM_ROOT/etc/initramfs-tools/modules > /dev/null +fi ## Install docker echo '[INFO] Install docker' -curl -sSL https://get.docker.com/ | sudo LANG=C chroot $FILESYSTEM_ROOT sh -## Remove garbage left by docker installation script -sudo rm $FILESYSTEM_ROOT/etc/apt/sources.list.d/docker.list -sudo chroot $FILESYSTEM_ROOT service docker stop -sudo chroot $FILESYSTEM_ROOT service dbus stop -## Add docker config drop-in to select aufs, otherwise it may other storage driver -## Note: $_ means last argument of last command +## Install apparmor utils since they're missing and apparmor is enabled in the kernel +## Otherwise Docker will fail to start +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install apparmor +sudo cp files/image_config/ntp/ntp-apparmor $FILESYSTEM_ROOT/etc/apparmor.d/local/usr.sbin.ntpd +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install apt-transport-https \ + ca-certificates \ + curl \ + gnupg2 \ + software-properties-common +if [[ $CONFIGURED_ARCH == armhf ]]; then + # update ssl ca certificates for secure pem + sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT c_rehash +fi +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT curl -o /tmp/docker.gpg -fsSL https://download.docker.com/linux/debian/gpg +sudo LANG=C chroot $FILESYSTEM_ROOT apt-key add /tmp/docker.gpg +sudo LANG=C chroot $FILESYSTEM_ROOT rm /tmp/docker.gpg +sudo LANG=C chroot $FILESYSTEM_ROOT add-apt-repository \ + "deb [arch=$CONFIGURED_ARCH] https://download.docker.com/linux/debian $IMAGE_DISTRO stable" +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get update +if dpkg --compare-versions ${DOCKER_VERSION} ge "18.09"; then + sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install docker-ce=${DOCKER_VERSION} docker-ce-cli=${DOCKER_VERSION} +else + sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install docker-ce=${DOCKER_VERSION} +fi + +# Uninstall 'python3-gi' installed as part of 'software-properties-common' to remove debian version of 'PyGObject' +# pip version of 'PyGObject' will be installed during installation of 'sonic-host-services' +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y remove software-properties-common gnupg2 python3-gi + +if [ "$INCLUDE_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 kubernetes-cni=${KUBERNETES_CNI_VERSION}-00 + sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubelet=${KUBERNETES_VERSION}-00 + sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubectl=${KUBERNETES_VERSION}-00 + 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 sudo cp files/docker/docker.service.conf $_ +## Fix systemd race between docker and containerd +sudo sed -i '/After=/s/$/ containerd.service/' $FILESYSTEM_ROOT/lib/systemd/system/docker.service + +## Create redis group +sudo LANG=C chroot $FILESYSTEM_ROOT groupadd -f redis ## Create default user -## Note: user should be in the group with the same name, and also in sudo/docker group -sudo LANG=C chroot $FILESYSTEM_ROOT useradd -G sudo,docker $USERNAME -c "$DEFAULT_USERINFO" -m -s /bin/bash +## Note: user should be in the group with the same name, and also in sudo/docker/redis groups +sudo LANG=C chroot $FILESYSTEM_ROOT useradd -G sudo,docker,redis $USERNAME -c "$DEFAULT_USERINFO" -m -s /bin/bash ## Create password for the default user -echo $USERNAME:$PASSWORD_ENCRYPTED | sudo LANG=C chroot $FILESYSTEM_ROOT chpasswd -e +echo "$USERNAME:$PASSWORD" | sudo LANG=C chroot $FILESYSTEM_ROOT chpasswd -## Pre-install hardware drivers -sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install \ - firmware-linux-nonfree +if [[ $CONFIGURED_ARCH == amd64 ]]; then + ## Pre-install hardware drivers + sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install \ + firmware-linux-nonfree +fi ## Pre-install the fundamental packages ## Note: gdisk is needed for sgdisk in install.sh ## Note: parted is needed for partprobe in install.sh -sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install \ +## Note: ca-certificates is needed for easy_install +## Note: don't install python-apt by pip, older than Debian repo one +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install \ + file \ + ifmetric \ + iproute2 \ + bridge-utils \ + isc-dhcp-client \ sudo \ vim \ tcpdump \ - ntp \ + dbus \ + ntpstat \ openssh-server \ python \ - python-setuptools \ python-apt \ + traceroute \ + iputils-ping \ + net-tools \ + bsdmainutils \ + ca-certificates \ + i2c-tools \ + efibootmgr \ + usbutils \ + pciutils \ + iptables-persistent \ + ebtables \ + logrotate \ + curl \ + kexec-tools \ + less \ + unzip \ gdisk \ - parted \ - efibootmgr + sysfsutils \ + squashfs-tools \ + grub2-common \ + rsyslog \ + ethtool \ + screen \ + hping3 \ + python-scapy \ + tcptraceroute \ + mtr-tiny \ + locales \ + cgroup-tools \ + ipmitool \ + ndisc6 \ + makedumpfile \ + conntrack \ + python-pip \ + python3 \ + python3-distutils \ + python3-pip \ + cron \ + haveged \ + jq + +if [[ $CONFIGURED_ARCH == amd64 ]]; then +## Pre-install the fundamental packages for amd64 (x86) +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install \ + flashrom \ + rasdaemon +fi + +## Set /etc/shadow permissions to -rw-------. +sudo LANG=c chroot $FILESYSTEM_ROOT chmod 600 /etc/shadow + +## Set /etc/passwd, /etc/group permissions to -rw-r--r--. +sudo LANG=c chroot $FILESYSTEM_ROOT chmod 644 /etc/passwd +sudo LANG=c chroot $FILESYSTEM_ROOT chmod 644 /etc/group + +# Needed to install kdump-tools +sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "mkdir -p /etc/initramfs-tools/conf.d" +sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo 'MODULES=most' >> /etc/initramfs-tools/conf.d/driver-policy" + +# Copy vmcore-sysctl.conf to add more vmcore dump flags to kernel +sudo cp files/image_config/kdump/vmcore-sysctl.conf $FILESYSTEM_ROOT/etc/sysctl.d/ + +#Adds a locale to a debian system in non-interactive mode +sudo sed -i '/^#.* en_US.* /s/^#//' $FILESYSTEM_ROOT/etc/locale.gen && \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT locale-gen "en_US.UTF-8" +sudo LANG=en_US.UTF-8 DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT update-locale "LANG=en_US.UTF-8" +sudo LANG=C chroot $FILESYSTEM_ROOT bash -c "find /usr/share/i18n/locales/ ! -name 'en_US' -type f -exec rm -f {} +" + +# Install certain fundamental packages from $IMAGE_DISTRO-backports in order to get +# more up-to-date (but potentially less stable) versions +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y -t $IMAGE_DISTRO-backports install \ + picocom + +if [[ $CONFIGURED_ARCH == amd64 ]]; then + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y download \ + grub-pc-bin + + sudo mv $FILESYSTEM_ROOT/grub-pc-bin*.deb $FILESYSTEM_ROOT/$PLATFORM_DIR/x86_64-grub +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 -## docker-py is needed by Ansible docker module -sudo LANG=C chroot $FILESYSTEM_ROOT easy_install pip -sudo LANG=C chroot $FILESYSTEM_ROOT pip install 'docker-py==1.6.0' -## Remove pip which is unnecessary in the base image -sudo LANG=C chroot $FILESYSTEM_ROOT pip uninstall -y pip +## 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/ +sudo cp -f files/sshd/sshd.service $FILESYSTEM_ROOT/lib/systemd/system/ssh.service +# Config sshd +# 1. Set 'UseDNS' to 'no' +# 2. Configure sshd to close all SSH connetions after 15 minutes of inactivity +sudo augtool -r $FILESYSTEM_ROOT <<'EOF' +touch /files/etc/ssh/sshd_config/EmptyLineHack +rename /files/etc/ssh/sshd_config/EmptyLineHack "" +set /files/etc/ssh/sshd_config/UseDNS no +ins #comment before /files/etc/ssh/sshd_config/UseDNS +set /files/etc/ssh/sshd_config/#comment[following-sibling::*[1][self::UseDNS]] "Disable hostname lookups" -echo '[INFO] Install apt-transport-sftp package from deps directory' -sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install libssh2-1 -sudo dpkg --root=$FILESYSTEM_ROOT -i deps/apt-transport-sftp_*.deb +rm /files/etc/ssh/sshd_config/ClientAliveInterval +rm /files/etc/ssh/sshd_config/ClientAliveCountMax +touch /files/etc/ssh/sshd_config/EmptyLineHack +rename /files/etc/ssh/sshd_config/EmptyLineHack "" +set /files/etc/ssh/sshd_config/ClientAliveInterval 900 +set /files/etc/ssh/sshd_config/ClientAliveCountMax 0 +ins #comment before /files/etc/ssh/sshd_config/ClientAliveInterval +set /files/etc/ssh/sshd_config/#comment[following-sibling::*[1][self::ClientAliveInterval]] "Close inactive client sessions after 15 minutes" +save +quit +EOF +# Configure sshd to listen for v4 connections; disable listening for v6 connections +sudo sed -i 's/^ListenAddress ::/#ListenAddress ::/' $FILESYSTEM_ROOT/etc/ssh/sshd_config +sudo sed -i 's/^#ListenAddress 0.0.0.0/ListenAddress 0.0.0.0/' $FILESYSTEM_ROOT/etc/ssh/sshd_config + +## Config rsyslog +sudo augtool -r $FILESYSTEM_ROOT --autosave " +rm /files/lib/systemd/system/rsyslog.service/Service/ExecStart/arguments +set /files/lib/systemd/system/rsyslog.service/Service/ExecStart/arguments/1 -n +" + +sudo mkdir -p $FILESYSTEM_ROOT/var/core + +# Config sysctl +sudo augtool --autosave " +set /files/etc/sysctl.conf/kernel.core_pattern '|/usr/local/bin/coredump-compress %e %t %p %P' +set /files/etc/sysctl.conf/kernel.softlockup_panic 1 +set /files/etc/sysctl.conf/kernel.panic 10 +set /files/etc/sysctl.conf/kernel.hung_task_timeout_secs 300 +set /files/etc/sysctl.conf/vm.panic_on_oom 2 +set /files/etc/sysctl.conf/fs.suid_dumpable 2 +" -r $FILESYSTEM_ROOT + +sysctl_net_cmd_string="" +while read line; do + [[ "$line" =~ ^#.*$ ]] && continue + sysctl_net_conf_key=`echo $line | awk -F '=' '{print $1}'` + sysctl_net_conf_value=`echo $line | awk -F '=' '{print $2}'` + sysctl_net_cmd_string=$sysctl_net_cmd_string"set /files/etc/sysctl.conf/$sysctl_net_conf_key $sysctl_net_conf_value"$'\n' +done < files/image_config/sysctl/sysctl-net.conf + +sudo augtool --autosave "$sysctl_net_cmd_string" -r $FILESYSTEM_ROOT + +# Upgrade pip via PyPI and uninstall the Debian version +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install --upgrade 'pip<21' +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install --upgrade pip +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get purge -y python-pip python3-pip + +# For building Python packages +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install 'setuptools==40.8.0' +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install 'wheel==0.35.1' +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install 'setuptools==49.6.00' +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install 'wheel==0.35.1' + +# docker Python API package is needed by Ansible docker module as well as some SONiC applications +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install 'docker==4.3.1' + +# Install scapy +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install 'scapy==2.4.4' + +## Note: keep pip installed for maintainance purpose + +# Install GCC, needed for building/installing some Python packages +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install gcc + +## Create /var/run/redis folder for docker-database to mount +sudo mkdir -p $FILESYSTEM_ROOT/var/run/redis ## Config DHCP for eth0 sudo tee -a $FILESYSTEM_ROOT/etc/network/interfaces > /dev/null < /dev/null <> /etc/motd" + sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo 'Running DEBUG image' >> /etc/motd" + sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '**************' >> /etc/motd" + sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '/src has the sources' >> /etc/motd" + sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '/src is mounted in each docker' >> /etc/motd" + sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '/debug is created for core files or temp files' >> /etc/motd" + sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo 'Create a subdir under /debug to upload your files' >> /etc/motd" + sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '/debug is mounted in each docker' >> /etc/motd" + + sudo mkdir -p $FILESYSTEM_ROOT/src + sudo cp $DEBUG_SRC_ARCHIVE_FILE $FILESYSTEM_ROOT/src/ + sudo mkdir -p $FILESYSTEM_ROOT/debug + +fi + +## Add mtd and uboot firmware tools package +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install u-boot-tools mtd-utils device-tree-compiler + +## Update initramfs +sudo chroot $FILESYSTEM_ROOT update-initramfs -u +## Convert initrd image to u-boot format +if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then + INITRD_FILE=initrd.img-${LINUX_KERNEL_VERSION}-${CONFIGURED_ARCH} + if [[ $CONFIGURED_ARCH == armhf ]]; then + INITRD_FILE=initrd.img-${LINUX_KERNEL_VERSION}-armmp + sudo LANG=C chroot $FILESYSTEM_ROOT mkimage -A arm -O linux -T ramdisk -C gzip -d /boot/$INITRD_FILE /boot/u${INITRD_FILE} + ## Overwriting the initrd image with uInitrd + sudo LANG=C chroot $FILESYSTEM_ROOT mv /boot/u${INITRD_FILE} /boot/$INITRD_FILE + elif [[ $CONFIGURED_ARCH == arm64 ]]; then + sudo cp -v $PLATFORM_DIR/${sonic_asic_platform}-${CONFIGURED_ARCH}/sonic_fit.its $FILESYSTEM_ROOT/boot/ + sudo LANG=C chroot $FILESYSTEM_ROOT mkimage -f /boot/sonic_fit.its /boot/sonic_${CONFIGURED_ARCH}.fit + fi +fi + +# Remove GCC +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y remove gcc + ## Clean up apt -sudo LANG=C chroot $FILESYSTEM_ROOT apt-get autoremove +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y autoremove +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get autoclean sudo LANG=C chroot $FILESYSTEM_ROOT apt-get clean -sudo LANG=C chroot $FILESYSTEM_ROOT rm -rf /tmp/* +sudo LANG=C chroot $FILESYSTEM_ROOT bash -c 'rm -rf /usr/share/doc/* /usr/share/locale/* /var/lib/apt/lists/* /tmp/*' + +## Clean up proxy +[ -n "$http_proxy" ] && sudo rm -f $FILESYSTEM_ROOT/etc/apt/apt.conf.d/01proxy ## Umount all echo '[INFO] Umount all' -sudo LANG=C chroot $FILESYSTEM_ROOT fuser -km /sys || true -sudo LANG=C chroot $FILESYSTEM_ROOT umount -lf /sys +## Display all process details access /proc +sudo LANG=C chroot $FILESYSTEM_ROOT fuser -vm /proc +## Kill the processes sudo LANG=C chroot $FILESYSTEM_ROOT fuser -km /proc || true -sudo LANG=C chroot $FILESYSTEM_ROOT umount /proc +## Wait fuser fully kill the processes +sleep 15 +sudo LANG=C chroot $FILESYSTEM_ROOT umount /proc || true ## Prepare empty directory to trigger mount move in initramfs-tools/mount_loop_root, implemented by patching sudo mkdir $FILESYSTEM_ROOT/host ## Compress most file system into squashfs file sudo rm -f $ONIE_INSTALLER_PAYLOAD $FILESYSTEM_SQUASHFS -sudo mksquashfs $FILESYSTEM_ROOT $FILESYSTEM_SQUASHFS -e boot -e var/lib/docker +## Output the file system total size for diag purpose +## Note: -x to skip directories on different file systems, such as /proc +sudo du -hsx $FILESYSTEM_ROOT +sudo mkdir -p $FILESYSTEM_ROOT/var/lib/docker +sudo mksquashfs $FILESYSTEM_ROOT $FILESYSTEM_SQUASHFS -e boot -e var/lib/docker -e $PLATFORM_DIR + +scripts/collect_host_image_version_files.sh $TARGET_PATH $FILESYSTEM_ROOT + +if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then + # Remove qemu arm bin executable used for cross-building + sudo rm -f $FILESYSTEM_ROOT/usr/bin/qemu*static || true + DOCKERFS_PATH=../dockerfs/ +fi + +## Compress docker files +pushd $FILESYSTEM_ROOT && sudo tar czf $OLDPWD/$FILESYSTEM_DOCKERFS -C ${DOCKERFS_PATH}var/lib/docker .; popd -## Compress together with /boot and /var/lib/docker as an installer payload zip file -pushd $FILESYSTEM_ROOT && sudo zip $OLDPWD/$ONIE_INSTALLER_PAYLOAD -r boot/ -r var/lib/docker; popd -sudo zip -g $ONIE_INSTALLER_PAYLOAD $FILESYSTEM_SQUASHFS +## Compress together with /boot, /var/lib/docker and $PLATFORM_DIR as an installer payload zip file +pushd $FILESYSTEM_ROOT && sudo zip $OLDPWD/$ONIE_INSTALLER_PAYLOAD -r boot/ $PLATFORM_DIR/; popd +sudo zip -g -n .squashfs:.gz $ONIE_INSTALLER_PAYLOAD $FILESYSTEM_SQUASHFS $FILESYSTEM_DOCKERFS diff --git a/build_debug_docker_j2.sh b/build_debug_docker_j2.sh new file mode 100755 index 000000000000..0b167cf0f39e --- /dev/null +++ b/build_debug_docker_j2.sh @@ -0,0 +1,44 @@ +#! /bin/bash + +echo " +FROM $1 + +ARG docker_container_name + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +{% if $2 is defined %} +{% if $2|length %} + +COPY \ +{% for deb in $2.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in $2.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +{% endif %} +{% endif %} + +{% if $3 is defined %} +{% if $3|length %} + +RUN apt-get update && apt-get install -f -y \ +{% for dbg in $3.split(' ') -%} +{{ dbg }}{{' '}} +{%- endfor %} + +{% endif %} +{% endif %} + + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +" diff --git a/build_docker.sh b/build_docker.sh index 1b39ea9ce8ed..ec07698d6615 100755 --- a/build_docker.sh +++ b/build_docker.sh @@ -1,61 +1,108 @@ #!/bin/bash -## This script is to automate the preparation for docker images for ACS. +## This script is to automate the preparation for docker images for SONiC. ## If registry server and port provided, the images will be pushed there. -## Usage: -## sudo ./build_docker.sh DOCKER_BUILD_DIR [REGISTRY_SERVER REGISTRY_PORT] -set -x -e +set -e -## Dockerfile directory -DOCKER_BUILD_DIR=$1 -REGISTRY_SERVER=$2 -REGISTRY_PORT=$3 -REGISTRY_USERNAME=$4 -REGISTRY_PASSWD=$5 +. ./functions.sh -[ -d "$DOCKER_BUILD_DIR" ] || { - echo "Invalid DOCKER_BUILD_DIR directory" >&2 - exit 1 +usage() { + cat >&2 <&2 + usage + exit 1 + ;; + esac +done +shift "$((OPTIND - 1))" -## File name for docker image -docker_image_gz=$docker_image_name.gz +## Dockerfile directory +DOCKER_BUILD_DIR=dockers/$1 +shift 1 -[ -n "$docker_image_gz" ] || { - echo "Error: Output docker image filename is empty" +[ -f "$DOCKER_BUILD_DIR"/Dockerfile ] || { + echo "Invalid DOCKER_BUILD_DIR directory" >&2 exit 1 } -function cleanup { - rm -rf $DOCKER_BUILD_DIR/files - rm -rf $DOCKER_BUILD_DIR/deps - docker rmi -f $docker_image_name || true +[ -n "$docker_image_name" ] || { + docker_image_name=$(basename $DOCKER_BUILD_DIR) } -trap cleanup exit ## Copy dependencies ## Note: Dockerfile ADD doesn't support reference files outside the folder, so copy it locally -mkdir -p $DOCKER_BUILD_DIR/deps -cp deps/*.deb $DOCKER_BUILD_DIR/deps +if ls deps/* 1>/dev/null 2>&1; then + trap_push "rm -rf $DOCKER_BUILD_DIR/deps" + mkdir -p $DOCKER_BUILD_DIR/deps + cp -r deps/* $DOCKER_BUILD_DIR/deps +fi ## Copy the suggested Debian sources ## ref: https://wiki.debian.org/SourcesList -mkdir -p $DOCKER_BUILD_DIR/files -cp files/sources.list $DOCKER_BUILD_DIR/files -docker build -t $docker_image_name $DOCKER_BUILD_DIR - -if [ -n "$REGISTRY_SERVER" ] && [ -n "$REGISTRY_PORT" ]; then - ## Add registry information as tag, so will push as latest - ## Temporarily add -f option to prevent error message of Docker engine version < 1.10.0 - docker tag -f $docker_image_name $REGISTRY_SERVER:$REGISTRY_PORT/$docker_image_name - - ## Login the docker image registry server - ## Note: user name and password are passed from command line, use fake email address to bypass login check - docker login -u $REGISTRY_USERNAME -p "$REGISTRY_PASSWD" -e "@" $REGISTRY_SERVER:$REGISTRY_PORT - docker push $REGISTRY_SERVER:$REGISTRY_PORT/$docker_image_name +trap_push "rm -rf $DOCKER_BUILD_DIR/deps" +cp -r files $DOCKER_BUILD_DIR/files +docker_try_rmi $docker_image_name + +## Build the docker image +docker build --no-cache -t $docker_image_name $DOCKER_BUILD_DIR +## Get the ID of the built image +## Note: inspect output has quotation characters, so sed to remove it as an argument +image_id=$(docker inspect --format="{{json .Id}}" $docker_image_name | sed -e 's/^"//' -e 's/"$//') + +## Flatten the image by importing an exported container on this image +## Note: it will squash the image with only one layer and lost all metadata such as ENTRYPOINT, +## so apply only to the base image +## TODO: wait docker-squash supporting Docker 1.10+ +## ref: https://github.com/jwilder/docker-squash/issues/45 +if [ "$docker_image_name" = "docker-base" ]; then + ## Run old image in a container + tmp_container=$(docker run -d ${docker_image_name} /bin/bash) + ## Export the container's filesystem, then import as a new image + docker export $tmp_container | docker import - ${docker_image_name} + ## Remove the container + docker rm -f $tmp_container || true + ## Remove the old image + docker rmi -f $image_id || true fi -docker save $docker_image_name | gzip -c > $docker_image_gz +## Save the docker image in a gz file +mkdir -p target +docker save $docker_image_name | gzip -c > target/$docker_image_name.gz + +if [ -n "$1" ]; then + ./push_docker.sh target/$docker_image_name.gz $@ $docker_image_tag +fi diff --git a/build_image.sh b/build_image.sh index 34e5d783956b..5353e85ab2f3 100755 --- a/build_image.sh +++ b/build_image.sh @@ -1,8 +1,19 @@ #!/bin/bash ## This script is to generate an ONIE installer image based on a file system overload +## Enable debug output for script +set -x -e + ## Read ONIE image related config file -. ./onie-image.conf + +CONFIGURED_ARCH=$([ -f .arch ] && cat .arch || echo amd64) + +if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then + . ./onie-image-${CONFIGURED_ARCH}.conf +else + . ./onie-image.conf +fi + [ -n "$ONIE_IMAGE_PART_SIZE" ] || { echo "Error: Invalid ONIE_IMAGE_PART_SIZE in onie image config file" exit 1 @@ -12,33 +23,137 @@ exit 1 } -## Retrieval short version of Git revision hash for partition metadata -[ -z $(git status --untracked-files=no -s) ] || { - echo "Error: There is local changes not committed to git repo. Cannot get a revision hash for partition metadata." - exit 1 -} -GIT_REVISION=$(git rev-parse --short HEAD) +IMAGE_VERSION="${SONIC_IMAGE_VERSION}" + +generate_onie_installer_image() +{ + # Copy platform-specific ONIE installer config files where onie-mk-demo.sh expects them + rm -rf ./installer/x86_64/platforms/ + mkdir -p ./installer/x86_64/platforms/ + for VENDOR in `ls ./device`; do + for PLATFORM in `ls ./device/$VENDOR`; do + if [ -f ./device/$VENDOR/$PLATFORM/installer.conf ]; then + cp ./device/$VENDOR/$PLATFORM/installer.conf ./installer/x86_64/platforms/$PLATFORM + fi + + done + done -sudo rm -f $OUTPUT_ONIE_IMAGE -if [ "$TARGET_MACHINE" = "generic" ]; then ## Generate an ONIE installer image ## Note: Don't leave blank between lines. It is single line command. - CONSOLE_SPEED=9600 \ - CONSOLE_DEV=0 \ - CONSOLE_FLAG=0 \ - CONSOLE_PORT=0x3f8 \ ./onie-mk-demo.sh $TARGET_PLATFORM $TARGET_MACHINE $TARGET_PLATFORM-$TARGET_MACHINE-$ONIEIMAGE_VERSION \ - installer $TARGET_MACHINE/platform.conf $OUTPUT_ONIE_IMAGE OS $GIT_REVISION $ONIE_IMAGE_PART_SIZE \ + installer platform/$TARGET_MACHINE/platform.conf $OUTPUT_ONIE_IMAGE OS $IMAGE_VERSION $ONIE_IMAGE_PART_SIZE \ $ONIE_INSTALLER_PAYLOAD +} + +if [ "$IMAGE_TYPE" = "onie" ]; then + echo "Build ONIE installer" + mkdir -p `dirname $OUTPUT_ONIE_IMAGE` + sudo rm -f $OUTPUT_ONIE_IMAGE + + generate_onie_installer_image + +## Build a raw partition dump image using the ONIE installer that can be +## used to dd' in-lieu of using the onie-nos-installer. Used while migrating +## into SONiC from other NOS. +elif [ "$IMAGE_TYPE" = "raw" ]; then + + echo "Build RAW image" + mkdir -p `dirname $OUTPUT_RAW_IMAGE` + sudo rm -f $OUTPUT_RAW_IMAGE + + generate_onie_installer_image + + echo "Creating SONiC raw partition : $OUTPUT_RAW_IMAGE of size $RAW_IMAGE_DISK_SIZE MB" + fallocate -l "$RAW_IMAGE_DISK_SIZE"M $OUTPUT_RAW_IMAGE + + # ensure proc is mounted + sudo mount proc /proc -t proc || true + + ## Generate a partition dump that can be used to 'dd' in-lieu of using the onie-nos-installer + ## Run the installer + ## The 'build' install mode of the installer is used to generate this dump. + sudo chmod a+x $OUTPUT_ONIE_IMAGE + sudo ./$OUTPUT_ONIE_IMAGE + + [ -r $OUTPUT_RAW_IMAGE ] || { + echo "Error : $OUTPUT_RAW_IMAGE not generated!" + exit 1 + } + + gzip $OUTPUT_RAW_IMAGE + + [ -r $OUTPUT_RAW_IMAGE.gz ] || { + echo "Error : gzip $OUTPUT_RAW_IMAGE failed!" + exit 1 + } + + mv $OUTPUT_RAW_IMAGE.gz $OUTPUT_RAW_IMAGE + echo "The compressed raw image is in $OUTPUT_RAW_IMAGE" + +elif [ "$IMAGE_TYPE" = "kvm" ]; then + + echo "Build KVM image" + KVM_IMAGE_DISK=${OUTPUT_KVM_IMAGE%.gz} + sudo rm -f $KVM_IMAGE_DISK $KVM_IMAGE_DISK.gz + + generate_onie_installer_image + + SONIC_USERNAME=$USERNAME PASSWD=$PASSWORD sudo -E ./scripts/build_kvm_image.sh $KVM_IMAGE_DISK $onie_recovery_image $OUTPUT_ONIE_IMAGE $KVM_IMAGE_DISK_SIZE + + if [ $? -ne 0 ]; then + echo "Error : build kvm image failed" + exit 1 + fi + + [ -r $KVM_IMAGE_DISK ] || { + echo "Error : $KVM_IMAGE_DISK not generated!" + exit 1 + } + + gzip $KVM_IMAGE_DISK + + [ -r $KVM_IMAGE_DISK.gz ] || { + echo "Error : gzip $KVM_IMAGE_DISK failed!" + exit 1 + } + + echo "The compressed kvm image is in $KVM_IMAGE_DISK.gz" + ## Use 'aboot' as target machine category which includes Aboot as bootloader -elif [ "$TARGET_MACHINE" = "aboot" ]; then - ## Add Aboot boot0 file into the image - cp $ONIE_INSTALLER_PAYLOAD $OUTPUT_ONIE_IMAGE - pushd files/Aboot && sudo zip -g $OLDPWD/$OUTPUT_ONIE_IMAGE boot0; popd - echo "$GIT_REVISION" >> .imagehash - zip -g $OUTPUT_ONIE_IMAGE .imagehash +elif [ "$IMAGE_TYPE" = "aboot" ]; then + echo "Build Aboot installer" + mkdir -p `dirname $OUTPUT_ABOOT_IMAGE` + sudo rm -f $OUTPUT_ABOOT_IMAGE + sudo rm -f $ABOOT_BOOT_IMAGE + ## Add main payload + cp $ONIE_INSTALLER_PAYLOAD $OUTPUT_ABOOT_IMAGE + ## Add Aboot boot0 file + j2 -f env files/Aboot/boot0.j2 ./onie-image.conf > files/Aboot/boot0 + sed -i -e "s/%%IMAGE_VERSION%%/$IMAGE_VERSION/g" files/Aboot/boot0 + pushd files/Aboot && zip -g $OLDPWD/$OUTPUT_ABOOT_IMAGE boot0; popd + pushd files/Aboot && zip -g $OLDPWD/$ABOOT_BOOT_IMAGE boot0; popd + pushd files/image_config/secureboot && zip -g $OLDPWD/$OUTPUT_ABOOT_IMAGE allowlist_paths.conf; popd + echo "$IMAGE_VERSION" >> .imagehash + zip -g $OUTPUT_ABOOT_IMAGE .imagehash + zip -g $ABOOT_BOOT_IMAGE .imagehash rm .imagehash + echo "SWI_VERSION=42.0.0" > version + echo "SWI_MAX_HWEPOCH=2" >> version + echo "SWI_VARIANT=US" >> version + zip -g $OUTPUT_ABOOT_IMAGE version + zip -g $ABOOT_BOOT_IMAGE version + rm version + + zip -g $OUTPUT_ABOOT_IMAGE $ABOOT_BOOT_IMAGE + rm $ABOOT_BOOT_IMAGE + if [ "$SONIC_ENABLE_IMAGE_SIGNATURE" = "y" ]; then + TARGET_CA_CERT="$TARGET_PATH/ca.cert" + rm -f "$TARGET_CA_CERT" + [ -f "$CA_CERT" ] && cp "$CA_CERT" "$TARGET_CA_CERT" + ./scripts/sign_image.sh -i "$OUTPUT_ABOOT_IMAGE" -k "$SIGNING_KEY" -c "$SIGNING_CERT" -a "$TARGET_CA_CERT" + fi else - echo "Error: Non supported target platform: $TARGET_PLATFORM" + echo "Error: Non supported image type $IMAGE_TYPE" exit 1 fi diff --git a/check_install.py b/check_install.py new file mode 100755 index 000000000000..ed0d8018afe7 --- /dev/null +++ b/check_install.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 + +import argparse +import pexpect +import sys +import time + + +def main(): + + parser = argparse.ArgumentParser(description='test_login cmdline parser') + parser.add_argument('-u', default="admin", help='login user name') + parser.add_argument('-P', default="YourPaSsWoRd", help='login password') + parser.add_argument('-p', type=int, default=9000, help='local port') + + args = parser.parse_args() + + KEY_UP = '\x1b[A' + KEY_DOWN = '\x1b[B' + KEY_RIGHT = '\x1b[C' + KEY_LEFT = '\x1b[D' + + login_prompt = 'sonic login:' + passwd_prompt = 'Password:' + cmd_prompt = "{}@sonic:~\$ $".format(args.u) + grub_selection = "The highlighted entry will be executed" + + i = 0 + while True: + try: + p = pexpect.spawn("telnet 127.0.0.1 {}".format(args.p), timeout=600, logfile=sys.stdout, encoding='utf-8') + break + except Exception as e: + print(str(e)) + i += 1 + if i == 10: + raise + time.sleep(1) + + # select ONIE embed + p.expect(grub_selection) + p.sendline(KEY_DOWN) + + # install sonic image + while True: + i = p.expect([login_prompt, passwd_prompt, grub_selection, cmd_prompt]) + if i == 0: + # send user name + p.sendline(args.u) + elif i == 1: + # send password + p.sendline(args.P) + elif i == 2: + # select onie install + p.sendline() + else: + break + + # check version + time.sleep(5) + p.sendline('uptime') + p.expect([cmd_prompt]) + p.sendline('show version') + p.expect([cmd_prompt]) + p.sendline('show ip bgp sum') + p.expect([cmd_prompt]) + p.sendline('sync') + p.expect([cmd_prompt]) + + +if __name__ == '__main__': + main() diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/hx5-as4630-48x1G+4x25G+2x100G.bcm b/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/hx5-as4630-48x1G+4x25G+2x100G.bcm new file mode 100755 index 000000000000..331f6d002647 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/hx5-as4630-48x1G+4x25G+2x100G.bcm @@ -0,0 +1,489 @@ +stable_size=71303168 + +#polarity/lanemap is using TH2 style. +core_clock_frequency=893 +dpp_clock_ratio=2:3 + +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 + +#oversubscribe_mode=1 + +pbmp_xport_xe=0x1FFFFFFE000000000000 + +parity_enable=0 +mem_cache_enable=1 + +l2_mem_entries=32768 +#l3_mem_entries=49152 +#fpem_mem_entries=16384 +l2xmsg_mode=1 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +port_flex_enable=1 +ifp_inports_support_enable=1 + +#3x PM4x10Q (3 * 16 = 48 physical ports) +#Doesn't support oversubscribe in Q mode +#MCQ0 +port_gmii_mode_1=1 #Q mode + +#PHY4 U56 xx1, MDC/MDIO2, PHYADDR:0x00-0x07, 0x08 +port_phy_addr_1=0x40 +port_phy_addr_2=0x41 +port_phy_addr_3=0x42 +port_phy_addr_4=0x43 +port_phy_addr_5=0x44 +port_phy_addr_6=0x45 +port_phy_addr_7=0x46 +port_phy_addr_8=0x47 +phy_port_primary_and_offset_1=0x0100 +phy_port_primary_and_offset_2=0x0101 +phy_port_primary_and_offset_3=0x0102 +phy_port_primary_and_offset_4=0x0103 +phy_port_primary_and_offset_5=0x0104 +phy_port_primary_and_offset_6=0x0105 +phy_port_primary_and_offset_7=0x0106 +phy_port_primary_and_offset_8=0x0107 +dport_map_port_1=26 +dport_map_port_2=25 +dport_map_port_3=28 +dport_map_port_4=27 +dport_map_port_5=30 +dport_map_port_6=29 +dport_map_port_7=32 +dport_map_port_8=31 +portmap_1=1:1 +portmap_2=2:1 +portmap_3=3:1 +portmap_4=4:1 +portmap_5=5:1 +portmap_6=6:1 +portmap_7=7:1 +portmap_8=8:1 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_rx_lane_map_physical{2.0}=0x3210 +phy_chain_rx_lane_map_physical{3.0}=0x3210 +phy_chain_rx_lane_map_physical{4.0}=0x3210 +phy_chain_rx_lane_map_physical{5.0}=0x3210 +phy_chain_rx_lane_map_physical{6.0}=0x3210 +phy_chain_rx_lane_map_physical{7.0}=0x3210 +phy_chain_rx_lane_map_physical{8.0}=0x3210 +phy_chain_tx_lane_map_physical{1.0}=0x3210 +phy_chain_tx_lane_map_physical{2.0}=0x3210 +phy_chain_tx_lane_map_physical{3.0}=0x3210 +phy_chain_tx_lane_map_physical{4.0}=0x3210 +phy_chain_tx_lane_map_physical{5.0}=0x3210 +phy_chain_tx_lane_map_physical{6.0}=0x3210 +phy_chain_tx_lane_map_physical{7.0}=0x3210 +phy_chain_tx_lane_map_physical{8.0}=0x3210 +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x0 + + +#PHY5 U57 x1x, MDC/MDIO2, PHYADDR:0x09-0x10, 0x11 +port_phy_addr_9=0x49 +port_phy_addr_10=0x4A +port_phy_addr_11=0x4B +port_phy_addr_12=0x4C +port_phy_addr_13=0x4D +port_phy_addr_14=0x4E +port_phy_addr_15=0x4F +port_phy_addr_16=0x50 +phy_port_primary_and_offset_9=0x0900 +phy_port_primary_and_offset_10=0x0901 +phy_port_primary_and_offset_11=0x0902 +phy_port_primary_and_offset_12=0x0903 +phy_port_primary_and_offset_13=0x0904 +phy_port_primary_and_offset_14=0x0905 +phy_port_primary_and_offset_15=0x0906 +phy_port_primary_and_offset_16=0x0907 +dport_map_port_9=34 +dport_map_port_10=33 +dport_map_port_11=36 +dport_map_port_12=35 +dport_map_port_13=38 +dport_map_port_14=37 +dport_map_port_15=40 +dport_map_port_16=39 +portmap_9=9:1 +portmap_10=10:1 +portmap_11=11:1 +portmap_12=12:1 +portmap_13=13:1 +portmap_14=14:1 +portmap_15=15:1 +portmap_16=16:1 +phy_chain_rx_lane_map_physical{9.0}=0x3210 +phy_chain_rx_lane_map_physical{10.0}=0x3210 +phy_chain_rx_lane_map_physical{11.0}=0x3210 +phy_chain_rx_lane_map_physical{12.0}=0x3210 +phy_chain_rx_lane_map_physical{13.0}=0x3210 +phy_chain_rx_lane_map_physical{14.0}=0x3210 +phy_chain_rx_lane_map_physical{15.0}=0x3210 +phy_chain_rx_lane_map_physical{16.0}=0x3210 +phy_chain_tx_lane_map_physical{9.0}=0x3210 +phy_chain_tx_lane_map_physical{10.0}=0x3210 +phy_chain_tx_lane_map_physical{11.0}=0x3210 +phy_chain_tx_lane_map_physical{12.0}=0x3210 +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_tx_lane_map_physical{14.0}=0x3210 +phy_chain_tx_lane_map_physical{15.0}=0x3210 +phy_chain_tx_lane_map_physical{16.0}=0x3210 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x0 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 + +#MCQ1 +port_gmii_mode_17=1 #Q mode + +#PHY6 U58 11x, MDC/MDIO2, PHYADDR:0x12-0x19, 0x1A +port_phy_addr_17=0x52 +port_phy_addr_18=0x53 +port_phy_addr_19=0x54 +port_phy_addr_20=0x55 +port_phy_addr_21=0x56 +port_phy_addr_22=0x57 +port_phy_addr_23=0x58 +port_phy_addr_24=0x59 +phy_port_primary_and_offset_17=0x1100 +phy_port_primary_and_offset_18=0x1101 +phy_port_primary_and_offset_19=0x1102 +phy_port_primary_and_offset_20=0x1103 +phy_port_primary_and_offset_21=0x1104 +phy_port_primary_and_offset_22=0x1105 +phy_port_primary_and_offset_23=0x1106 +phy_port_primary_and_offset_24=0x1107 +dport_map_port_17=42 +dport_map_port_18=41 +dport_map_port_19=44 +dport_map_port_20=43 +dport_map_port_21=46 +dport_map_port_22=45 +dport_map_port_23=48 +dport_map_port_24=47 +portmap_17=17:1 +portmap_18=18:1 +portmap_19=19:1 +portmap_20=20:1 +portmap_21=21:1 +portmap_22=22:1 +portmap_23=23:1 +portmap_24=24:1 +phy_chain_rx_lane_map_physical{17.0}=0x3210 +phy_chain_rx_lane_map_physical{18.0}=0x3210 +phy_chain_rx_lane_map_physical{19.0}=0x3210 +phy_chain_rx_lane_map_physical{20.0}=0x3210 +phy_chain_rx_lane_map_physical{21.0}=0x3210 +phy_chain_rx_lane_map_physical{22.0}=0x3210 +phy_chain_rx_lane_map_physical{23.0}=0x3210 +phy_chain_rx_lane_map_physical{24.0}=0x3210 +phy_chain_tx_lane_map_physical{17.0}=0x3210 +phy_chain_tx_lane_map_physical{18.0}=0x3210 +phy_chain_tx_lane_map_physical{19.0}=0x3210 +phy_chain_tx_lane_map_physical{20.0}=0x3210 +phy_chain_tx_lane_map_physical{21.0}=0x3210 +phy_chain_tx_lane_map_physical{22.0}=0x3210 +phy_chain_tx_lane_map_physical{23.0}=0x3210 +phy_chain_tx_lane_map_physical{24.0}=0x3210 +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}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x0 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +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{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 + +#PHY1 U53 xx1, MDC/MDIO0, PHYADDR:0x00-0x07, 0x08 +port_phy_addr_25=0x00 +port_phy_addr_26=0x01 +port_phy_addr_27=0x02 +port_phy_addr_28=0x03 +port_phy_addr_29=0x04 +port_phy_addr_30=0x05 +port_phy_addr_31=0x06 +port_phy_addr_32=0x07 +phy_port_primary_and_offset_25=0x1900 +phy_port_primary_and_offset_26=0x1901 +phy_port_primary_and_offset_27=0x1902 +phy_port_primary_and_offset_28=0x1903 +phy_port_primary_and_offset_29=0x1904 +phy_port_primary_and_offset_30=0x1905 +phy_port_primary_and_offset_31=0x1906 +phy_port_primary_and_offset_32=0x1907 +dport_map_port_25=2 +dport_map_port_26=1 +dport_map_port_27=4 +dport_map_port_28=3 +dport_map_port_29=6 +dport_map_port_30=5 +dport_map_port_31=8 +dport_map_port_32=7 +portmap_25=25:1 +portmap_26=26:1 +portmap_27=27:1 +portmap_28=28:1 +portmap_29=29:1 +portmap_30=30:1 +portmap_31=31:1 +portmap_32=32:1 +phy_chain_rx_lane_map_physical{25.0}=0x3210 +phy_chain_rx_lane_map_physical{26.0}=0x3210 +phy_chain_rx_lane_map_physical{27.0}=0x3210 +phy_chain_rx_lane_map_physical{28.0}=0x3210 +phy_chain_rx_lane_map_physical{29.0}=0x3210 +phy_chain_rx_lane_map_physical{30.0}=0x3210 +phy_chain_rx_lane_map_physical{31.0}=0x3210 +phy_chain_rx_lane_map_physical{32.0}=0x3210 +phy_chain_tx_lane_map_physical{25.0}=0x3210 +phy_chain_tx_lane_map_physical{26.0}=0x3210 +phy_chain_tx_lane_map_physical{27.0}=0x3210 +phy_chain_tx_lane_map_physical{28.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x3210 +phy_chain_tx_lane_map_physical{30.0}=0x3210 +phy_chain_tx_lane_map_physical{31.0}=0x3210 +phy_chain_tx_lane_map_physical{32.0}=0x3210 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.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}=0x0 +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{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 + +#MCQ2 +port_gmii_mode_33=1 #Q mode + +#PHY2 U54 x1x, MDC/MDIO0, PHYADDR:0x09-0x10, 0x11 +port_phy_addr_33=0x0D +port_phy_addr_34=0x0E +port_phy_addr_35=0x0F +port_phy_addr_36=0x10 +port_phy_addr_37=0x09 +port_phy_addr_38=0x0A +port_phy_addr_39=0x0B +port_phy_addr_40=0x0C +phy_port_primary_and_offset_33=0x2504 +phy_port_primary_and_offset_34=0x2505 +phy_port_primary_and_offset_35=0x2506 +phy_port_primary_and_offset_36=0x2507 +phy_port_primary_and_offset_37=0x2500 +phy_port_primary_and_offset_38=0x2501 +phy_port_primary_and_offset_39=0x2502 +phy_port_primary_and_offset_40=0x2503 +dport_map_port_33=14 +dport_map_port_34=13 +dport_map_port_35=16 +dport_map_port_36=15 +dport_map_port_37=10 +dport_map_port_38=9 +dport_map_port_39=12 +dport_map_port_40=11 +portmap_33=33:1 +portmap_34=34:1 +portmap_35=35:1 +portmap_36=36:1 +portmap_37=37:1 +portmap_38=38:1 +portmap_39=39:1 +portmap_40=40:1 +phy_chain_rx_lane_map_physical{33.0}=0x3210 +phy_chain_rx_lane_map_physical{34.0}=0x3210 +phy_chain_rx_lane_map_physical{35.0}=0x3210 +phy_chain_rx_lane_map_physical{36.0}=0x3210 +phy_chain_rx_lane_map_physical{37.0}=0x3210 +phy_chain_rx_lane_map_physical{38.0}=0x3210 +phy_chain_rx_lane_map_physical{39.0}=0x3210 +phy_chain_rx_lane_map_physical{40.0}=0x3210 +phy_chain_tx_lane_map_physical{33.0}=0x3210 +phy_chain_tx_lane_map_physical{34.0}=0x3210 +phy_chain_tx_lane_map_physical{35.0}=0x3210 +phy_chain_tx_lane_map_physical{36.0}=0x3210 +phy_chain_tx_lane_map_physical{37.0}=0x3210 +phy_chain_tx_lane_map_physical{38.0}=0x3210 +phy_chain_tx_lane_map_physical{39.0}=0x3210 +phy_chain_tx_lane_map_physical{40.0}=0x3210 +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x1 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{40.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}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 + +#PHY3 U55 11x, MDC/MDIO0, PHYADDR:0x12-0x19, 0x1A +port_phy_addr_41=0x16 +port_phy_addr_42=0x17 +port_phy_addr_43=0x18 +port_phy_addr_44=0x19 +port_phy_addr_45=0x12 +port_phy_addr_46=0x13 +port_phy_addr_47=0x14 +port_phy_addr_48=0x15 +phy_port_primary_and_offset_41=0x2D00 +phy_port_primary_and_offset_42=0x2D01 +phy_port_primary_and_offset_43=0x2D02 +phy_port_primary_and_offset_44=0x2D03 +phy_port_primary_and_offset_45=0x2D04 +phy_port_primary_and_offset_46=0x2D05 +phy_port_primary_and_offset_47=0x2D06 +phy_port_primary_and_offset_48=0x2D07 +dport_map_port_41=22 +dport_map_port_42=21 +dport_map_port_43=24 +dport_map_port_44=23 +dport_map_port_45=18 +dport_map_port_46=17 +dport_map_port_47=20 +dport_map_port_48=19 +portmap_41=41:1 +portmap_42=42:1 +portmap_43=43:1 +portmap_44=44:1 +portmap_45=45:1 +portmap_46=46:1 +portmap_47=47:1 +portmap_48=48:1 +phy_chain_rx_lane_map_physical{41.0}=0x3210 +phy_chain_rx_lane_map_physical{42.0}=0x3210 +phy_chain_rx_lane_map_physical{43.0}=0x3210 +phy_chain_rx_lane_map_physical{44.0}=0x3210 +phy_chain_rx_lane_map_physical{45.0}=0x3210 +phy_chain_rx_lane_map_physical{46.0}=0x3210 +phy_chain_rx_lane_map_physical{47.0}=0x3210 +phy_chain_rx_lane_map_physical{48.0}=0x3210 +phy_chain_tx_lane_map_physical{41.0}=0x3210 +phy_chain_tx_lane_map_physical{42.0}=0x3210 +phy_chain_tx_lane_map_physical{43.0}=0x3210 +phy_chain_tx_lane_map_physical{44.0}=0x3210 +phy_chain_tx_lane_map_physical{45.0}=0x3210 +phy_chain_tx_lane_map_physical{46.0}=0x3210 +phy_chain_tx_lane_map_physical{47.0}=0x3210 +phy_chain_tx_lane_map_physical{48.0}=0x3210 +phy_chain_rx_polarity_flip_physical{41.0}=0x1 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_tx_polarity_flip_physical{47.0}=0x1 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 + +#3x PM4x25 (3 * 4 = 12 physical ports) +#FC0 +dport_map_port_49=51 +dport_map_port_50=50 +dport_map_port_51=49 +dport_map_port_52=52 +portmap_49=65:25 +portmap_50=66:25 +portmap_51=67:25 +portmap_52=68:25 +#FC1 +dport_map_port_53=57 +dport_map_port_54=58 +dport_map_port_55=59 +dport_map_port_56=60 +portmap_53=69:100:4 +#portmap_55=71:50 +#portmap_54=70:25 +#portmap_55=71:25 +#portmap_56=72:25 +#FC2 +dport_map_port_57=53 +dport_map_port_58=54 +dport_map_port_59=55 +dport_map_port_60=56 +portmap_57=73:100:4 +#portmap_59=75:50 +#portmap_58=74:25 +#portmap_59=75:25 +#portmap_60=76:25 + +#4x PM4x10 (4 * 4 = 16 physical ports) +#MC0 No connection +#MC1 No connection +#MC2 No connection +#MC3 No connection +#portmap_=49:10 +#portmap_=50:10 +#portmap_=51:10 +#portmap_=52:10 + +#portmap_=53:10 +#portmap_=54:10 +#portmap_=55:10 +#portmap_=56:10 + +#portmap_=57:10 +#portmap_=58:10 +#portmap_=59:10 +#portmap_=60:10 + +#portmap_=61:10 +#portmap_=62:10 +#portmap_=63:10 +#portmap_=64:10 diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/port_config.ini b/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/port_config.ini new file mode 100755 index 000000000000..f8965dfe41d0 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index speed autoneg +Ethernet0 26 thousandE1 1 1000 1 +Ethernet1 25 thousandE2 2 1000 1 +Ethernet2 28 thousandE3 3 1000 1 +Ethernet3 27 thousandE4 4 1000 1 +Ethernet4 30 thousandE5 5 1000 1 +Ethernet5 29 thousandE6 6 1000 1 +Ethernet6 32 thousandE7 7 1000 1 +Ethernet7 31 thousandE8 8 1000 1 +Ethernet8 38 thousandE9 9 1000 1 +Ethernet9 37 thousandE10 10 1000 1 +Ethernet10 40 thousandE11 11 1000 1 +Ethernet11 39 thousandE12 12 1000 1 +Ethernet12 34 thousandE13 13 1000 1 +Ethernet13 33 thousandE14 14 1000 1 +Ethernet14 36 thousandE15 15 1000 1 +Ethernet15 35 thousandE16 16 1000 1 +Ethernet16 46 thousandE17 17 1000 1 +Ethernet17 45 thousandE18 18 1000 1 +Ethernet18 48 thousandE19 19 1000 1 +Ethernet19 47 thousandE20 20 1000 1 +Ethernet20 42 thousandE21 21 1000 1 +Ethernet21 41 thousandE22 22 1000 1 +Ethernet22 44 thousandE23 23 1000 1 +Ethernet23 43 thousandE24 24 1000 1 +Ethernet24 2 thousandE25 25 1000 1 +Ethernet25 1 thousandE26 26 1000 1 +Ethernet26 4 thousandE27 27 1000 1 +Ethernet27 3 thousandE28 28 1000 1 +Ethernet28 6 thousandE29 29 1000 1 +Ethernet29 5 thousandE30 30 1000 1 +Ethernet30 8 thousandE31 31 1000 1 +Ethernet31 7 thousandE32 32 1000 1 +Ethernet32 10 thousandE33 33 1000 1 +Ethernet33 9 thousandE34 34 1000 1 +Ethernet34 12 thousandE35 35 1000 1 +Ethernet35 11 thousandE36 36 1000 1 +Ethernet36 14 thousandE37 37 1000 1 +Ethernet37 13 thousandE38 38 1000 1 +Ethernet38 16 thousandE39 39 1000 1 +Ethernet39 15 thousandE40 40 1000 1 +Ethernet40 18 thousandE41 41 1000 1 +Ethernet41 17 thousandE42 42 1000 1 +Ethernet42 20 thousandE43 43 1000 1 +Ethernet43 19 thousandE44 44 1000 1 +Ethernet44 22 thousandE45 45 1000 1 +Ethernet45 21 thousandE46 46 1000 1 +Ethernet46 24 thousandE47 47 1000 1 +Ethernet47 23 thousandE48 48 1000 1 +Ethernet48 67 twentyfiveGigE49 49 25000 0 +Ethernet49 66 twentyfiveGigE50 50 25000 0 +Ethernet50 65 twentyfiveGigE51 51 25000 0 +Ethernet51 68 twentyfiveGigE52 52 25000 0 +Ethernet52 73,74,75,76 hundredGigE53 53 100000 0 +Ethernet56 69,70,71,72 hundredGigE54 54 100000 0 diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/sai.profile b/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/sai.profile new file mode 100755 index 000000000000..5329410fe8b3 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/hx5-as4630-48x1G+4x25G+2x100G.bcm diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/custom_led.bin b/device/accton/x86_64-accton_as4630_54pe-r0/custom_led.bin new file mode 100644 index 000000000000..0f6e37a82492 Binary files /dev/null and b/device/accton/x86_64-accton_as4630_54pe-r0/custom_led.bin differ diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/default_sku b/device/accton/x86_64-accton_as4630_54pe-r0/default_sku new file mode 100755 index 000000000000..64e4213bdc71 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/default_sku @@ -0,0 +1 @@ +Accton-AS4630-54PE t1 diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/installer.conf b/device/accton/x86_64-accton_as4630_54pe-r0/installer.conf new file mode 100755 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/led_proc_init.soc b/device/accton/x86_64-accton_as4630_54pe-r0/led_proc_init.soc new file mode 100755 index 000000000000..5bef973ed2ae --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/led_proc_init.soc @@ -0,0 +1,3 @@ +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led start +led auto on diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/media_settings.json b/device/accton/x86_64-accton_as4630_54pe-r0/media_settings.json new file mode 100644 index 000000000000..656f12355205 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/media_settings.json @@ -0,0 +1,52 @@ +{ + "PORT_MEDIA_SETTINGS": { + "49": { + "Default": { + "preemphasis": { + "lane0":"0x124106" + } + } + }, + "50": { + "Default": { + "preemphasis": { + "lane0":"0x124106" + } + } + }, + "51": { + "Default": { + "preemphasis": { + "lane0":"0x124106" + } + } + }, + "52": { + "Default": { + "preemphasis": { + "lane0":"0x124106" + } + } + }, + "53": { + "Default": { + "preemphasis": { + "lane0":"0x124106", + "lane1":"0x124106", + "lane2":"0x124106", + "lane3":"0x124106" + } + } + }, + "54": { + "Default": { + "preemphasis": { + "lane0":"0x124106", + "lane1":"0x124106", + "lane2":"0x124106", + "lane3":"0x124106" + } + } + } + } +} diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as4630_54pe-r0/plugins/eeprom.py new file mode 100755 index 000000000000..3d0ff81ca574 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/1-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as4630_54pe-r0/plugins/psuutil.py new file mode 100755 index 000000000000..92e08e23afd6 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "10-0050", + 2: "11-0051", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as4630_54pe-r0/plugins/sfputil.py new file mode 100755 index 000000000000..fd660ccdc245 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/plugins/sfputil.py @@ -0,0 +1,196 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import sys + import time + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 49 + PORT_END = 54 + PORTS_IN_BLOCK = 54 + QSFP_START = 53 + + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD_PATH = "/sys/bus/i2c/devices/3-0060/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 49: [18], + 50: [19], + 51: [20], + 52: [21], + 53: [22], + 54: [23], + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = self.BASE_OOM_PATH + "eeprom" + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x][0]) + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + present_path = self.BASE_CPLD_PATH + "module_present_" + str(port_num) + self.__port_to_is_present = present_path + + content = "0" + try: + val_file = open(self.__port_to_is_present) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.QSFP_START or port_num > self.port_end: + return False + + try: + eeprom = None + if not self.get_presence(port_num): + return False + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + # if "Power override" bit is 1 and "Power set" bit is 1 + if ((lpmode & 0x3) == 0x3): + return True + + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + else: + return False + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.QSFP_START or port_num > self.port_end: + return False + + try: + eeprom = None + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + # 0x3:Low Power Mode, 0x1:High Power Mode + regval = 0x3 if lpmode else 0x1 + + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + raise NotImplementedError + + @property + def _get_presence_bitmap(self): + + bits = [] + for x in range(self.port_start, self.port_end+1): + bits.append(str(int(self.get_presence(x)))) + + rev = "".join(bits[::-1]) + return int(rev, 2) + + data = {'present': 0} + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + + if timeout == 0: + cd_ms = sys.maxsize + else: + cd_ms = timeout + + # poll per second + while cd_ms > 0: + reg_value = self._get_presence_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports != 0: + break + time.sleep(1) + cd_ms = cd_ms - 1000 + + if changed_ports != 0: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + mask = (1 << (port - self.port_start)) + if changed_ports & mask: + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as4630_54pe-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/port_config.ini b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/port_config.ini new file mode 100755 index 000000000000..ee60c526227d --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/port_config.ini @@ -0,0 +1,73 @@ +# name lanes alias index speed +Ethernet0 13 tenGigE0 1 10000 +Ethernet1 14 tenGigE1 2 10000 +Ethernet2 15 tenGigE2 3 10000 +Ethernet3 16 tenGigE3 4 10000 +Ethernet4 21 tenGigE4 5 10000 +Ethernet5 22 tenGigE5 6 10000 +Ethernet6 23 tenGigE6 7 10000 +Ethernet7 24 tenGigE7 8 10000 +Ethernet8 25 tenGigE8 9 10000 +Ethernet9 26 tenGigE9 10 10000 +Ethernet10 27 tenGigE10 11 10000 +Ethernet11 28 tenGigE11 12 10000 +Ethernet12 29 tenGigE12 13 10000 +Ethernet13 30 tenGigE13 14 10000 +Ethernet14 31 tenGigE14 15 10000 +Ethernet15 32 tenGigE15 16 10000 +Ethernet16 45 tenGigE16 17 10000 +Ethernet17 46 tenGigE17 18 10000 +Ethernet18 47 tenGigE18 19 10000 +Ethernet19 48 tenGigE19 20 10000 +Ethernet20 49 tenGigE20 21 10000 +Ethernet21 50 tenGigE21 22 10000 +Ethernet22 51 tenGigE22 23 10000 +Ethernet23 52 tenGigE23 24 10000 +Ethernet24 53 tenGigE24 25 10000 +Ethernet25 54 tenGigE25 26 10000 +Ethernet26 55 tenGigE26 27 10000 +Ethernet27 56 tenGigE27 28 10000 +Ethernet28 57 tenGigE28 29 10000 +Ethernet29 58 tenGigE29 30 10000 +Ethernet30 59 tenGigE30 31 10000 +Ethernet31 60 tenGigE31 32 10000 +Ethernet32 61 tenGigE32 33 10000 +Ethernet33 62 tenGigE33 34 10000 +Ethernet34 63 tenGigE34 35 10000 +Ethernet35 64 tenGigE35 36 10000 +Ethernet36 65 tenGigE36 37 10000 +Ethernet37 66 tenGigE37 38 10000 +Ethernet38 67 tenGigE38 39 10000 +Ethernet39 68 tenGigE39 40 10000 +Ethernet40 69 tenGigE40 41 10000 +Ethernet41 70 tenGigE41 42 10000 +Ethernet42 71 tenGigE42 43 10000 +Ethernet43 72 tenGigE43 44 10000 +Ethernet44 73 tenGigE44 45 10000 +Ethernet45 74 tenGigE45 46 10000 +Ethernet46 75 tenGigE46 47 10000 +Ethernet47 76 tenGigE47 48 10000 +Ethernet48 97 tenGigE48 49 10000 +Ethernet49 98 tenGigE49 49 10000 +Ethernet50 99 tenGigE50 49 10000 +Ethernet51 100 tenGigE51 49 10000 +Ethernet52 101 tenGigE52 50 10000 +Ethernet53 102 tenGigE53 50 10000 +Ethernet54 103 tenGigE54 50 10000 +Ethernet55 104 tenGigE55 50 10000 +Ethernet56 81 tenGigE56 51 10000 +Ethernet57 82 tenGigE57 51 10000 +Ethernet58 83 tenGigE58 51 10000 +Ethernet59 84 tenGigE59 51 10000 +Ethernet60 105 tenGigE60 52 10000 +Ethernet61 106 tenGigE61 52 10000 +Ethernet62 107 tenGigE62 52 10000 +Ethernet63 108 tenGigE63 52 10000 +Ethernet64 109 tenGigE64 53 10000 +Ethernet65 110 tenGigE65 53 10000 +Ethernet66 111 tenGigE66 53 10000 +Ethernet67 112 tenGigE67 53 10000 +Ethernet68 77 tenGigE68 54 10000 +Ethernet69 78 tenGigE69 54 10000 +Ethernet70 79 tenGigE70 54 10000 +Ethernet71 80 tenGigE71 54 10000 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/sai.profile b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/sai.profile new file mode 100755 index 000000000000..9020d35fda23 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-as5712-72x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/td2-as5712-72x10G.config.bcm b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/td2-as5712-72x10G.config.bcm new file mode 100644 index 000000000000..1d6286ba3bd7 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/Accton-AS5712-54X/td2-as5712-72x10G.config.bcm @@ -0,0 +1,148 @@ +os=unix +bcm_stat_flags=0 +parity_enable=0 +parity_correction=0 + +bcm_num_cos=10 +l2_mem_entries=32768 +l3_mem_entries=16384 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 + +mmu_lossless=0 +lls_num_l2uc=12 +module_64ports=0 + +#SFI +serdes_if_type=9 + +port_init_cl72=0 +phy_an_c73=5 # TSCMOD_CL73_CL37 + +#sdk6.5.5 only supports 156(default) or 125 +#xgxs_lcpll_xtal_refclk=1 +tslam_dma_enable=1 +table_dma_enable=1 + +#for 72 ports with 48 10G ports and 6 40G ports for breakout mode +pbmp_oversubscribe=0x1fffffffffffffffffe +pbmp_xport_xe=0x1fffffffffffffffffe + +rate_ext_mdio_divisor=96 + +#SFP+ 1-4 from WC3 +portmap_1=13:10 +portmap_2=14:10 +portmap_3=15:10 +portmap_4=16:10 + +#SFP+ 5-8 from WC5 +portmap_5=21:10 +portmap_6=22:10 +portmap_7=23:10 +portmap_8=24:10 + +#SFP+ 9-12 from WC6 +portmap_9=25:10 +portmap_10=26:10 +portmap_11=27:10 +portmap_12=28:10 + +#SFP+ 13-16 from WC7 +portmap_13=29:10 +portmap_14=30:10 +portmap_15=31:10 +portmap_16=32:10 + +#SFP+ 17-20 from WC11 +portmap_17=45:10 +portmap_18=46:10 +portmap_19=47:10 +portmap_20=48:10 + +#SFP+ 21-24 from WC12 +portmap_21=49:10 +portmap_22=50:10 +portmap_23=51:10 +portmap_24=52:10 + +#SFP+ 25-28 from WC13 +portmap_25=53:10 +portmap_26=54:10 +portmap_27=55:10 +portmap_28=56:10 + +#SFP+ 29-32 from WC14 +portmap_29=57:10 +portmap_30=58:10 +portmap_31=59:10 +portmap_32=60:10 + +#SFP+ 33-36 from WC15 +portmap_33=61:10 +portmap_34=62:10 +portmap_35=63:10 +portmap_36=64:10 + +#SFP+ 37-40 from WC16 +portmap_37=65:10 +portmap_38=66:10 +portmap_39=67:10 +portmap_40=68:10 + +#SFP+ 41-44 from WC17 +portmap_41=69:10 +portmap_42=70:10 +portmap_43=71:10 +portmap_44=72:10 + +#SFP+ 45-48 from WC18 +portmap_45=73:10 +portmap_46=74:10 +portmap_47=75:10 +portmap_48=76:10 + +# QSFP+ 49/WC24/port 49 +portmap_49=97:10 +portmap_50=98:10 +portmap_51=99:10 +portmap_52=100:10 + +# QSFP+ 51/WC25/port 50 +portmap_53=101:10 +portmap_54=102:10 +portmap_55=103:10 +portmap_56=104:10 + +# QSFP+ 53/WC20/port 51 +portmap_57=81:10 +portmap_58=82:10 +portmap_59=83:10 +portmap_60=84:10 + +# QSFP+ 50/WC26/port 52 +portmap_61=105:10 +portmap_62=106:10 +portmap_63=107:10 +portmap_64=108:10 + +# QSFP+ 52/WC27/port 53 +portmap_65=109:10 +portmap_66=110:10 +portmap_67=111:10 +portmap_68=112:10 + +# QSFP+ 54/WC19/port 54 +portmap_69=77:10 +portmap_70=78:10 +portmap_71=79:10 +portmap_72=80:10 + +# L3 ECMP +# - In Trident2, VP LAGs share the same table as ECMP group table. +# The first N entries are reserved for VP LAGs, where N is the value of the +# config property "max_vp_lags". By default this was set to 256 +l3_max_ecmp_mode=1 +max_vp_lags=0 + +stable_size=0x2000000 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/default_sku b/device/accton/x86_64-accton_as5712_54x-r0/default_sku new file mode 100644 index 000000000000..a65f8088752a --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS5712-54X t1 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/installer.conf b/device/accton/x86_64-accton_as5712_54x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as5712_54x-r0/led_proc_init.soc new file mode 100644 index 000000000000..85030e1db349 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/led_proc_init.soc @@ -0,0 +1,162 @@ +# LED setting for active +# ----------------------------------------------------------------------------- +# for as5712_54x (48xg+6qxg) +# +# on green - if link up +# off - if link down +# blink - if active +# ----------------------------------------------------------------------------- +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=38 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=41 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=42 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=45 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=46 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=49 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=50 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=53 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=54 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=58 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=59 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=61 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=62 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 + +led 0 stop +led 0 prog \ + 06 FE 80 D2 19 71 08 E0 60 FE E9 D2 0F 75 10 81 \ + 61 FD 02 3F 60 FF 28 32 0F 87 67 4A 96 FF 06 FF \ + D2 2B 74 16 02 1F 60 FF 28 32 0F 87 67 4A 96 FF \ + 06 FF D2 13 74 28 02 0F 60 FF 28 32 0F 87 67 4A \ + 96 FF 06 FF D2 0B 74 3A 3A 48 32 07 32 08 C7 32 \ + 04 C7 97 71 57 77 69 32 00 32 01 B7 97 71 63 32 \ + 0E 77 6B 26 FD 97 27 77 6B 32 0F 87 57 00 00 00 +led 0 start + +led 1 stop +led 1 prog \ + 06 FE 80 D2 19 71 08 E0 60 FE E9 D2 0F 75 10 81 \ + 61 FD 02 20 67 89 02 24 67 89 02 10 67 89 02 28 \ + 67 89 02 2C 67 89 02 0C 67 89 02 2C 67 79 02 28 \ + 67 79 02 24 67 79 02 20 67 79 02 10 67 79 02 0C \ + 67 79 02 0B 60 FF 28 32 0F 87 67 56 96 FF 06 FF \ + D2 FF 74 46 3A 36 32 07 32 08 C7 32 04 C7 97 71 \ + 63 77 75 32 00 32 01 B7 97 71 6F 32 0E 77 77 26 \ + FD 97 27 77 77 32 0F 87 57 12 A0 F8 15 1A 01 75 \ + 85 28 67 56 57 32 0F 87 57 12 A0 F8 15 1A 01 71 \ + A1 28 67 56 80 28 67 56 80 28 67 56 80 28 67 56 \ + 57 32 0F 87 32 0F 87 32 0F 87 32 0F 87 57 00 00 +led 1 start diff --git a/device/accton/x86_64-accton_as5712_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as5712_54x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..951384d5e37d --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as5712_54x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as5712_54x-r0/plugins/psuutil.py new file mode 100755 index 000000000000..a07aebc96312 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "57-0038", + 2: "58-003b", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as5712_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as5712_54x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..5002d842a15f --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/plugins/sfputil.py @@ -0,0 +1,343 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# +try: + import time + import os + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +# from xcvrd +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 54 + PORTS_IN_BLOCK = 54 + QSFP_PORT_START = 49 + QSFP_PORT_END = 54 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD2_PATH = "/sys/bus/i2c/devices/{0}-0061/" + BASE_CPLD3_PATH = "/sys/bus/i2c/devices/{0}-0062/" + I2C_BUS_ORDER = -1 + + # The sidebands of QSFP is different. + qsfp_sb_map = [0, 2, 4, 1, 3, 5] + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 1: [1, 2], + 2: [2, 3], + 3: [3, 4], + 4: [4, 5], + 5: [5, 6], + 6: [6, 7], + 7: [7, 8], + 8: [8, 9], + 9: [9, 10], + 10: [10, 11], + 11: [11, 12], + 12: [12, 13], + 13: [13, 14], + 14: [14, 15], + 15: [15, 16], + 16: [16, 17], + 17: [17, 18], + 18: [18, 19], + 19: [19, 20], + 20: [20, 21], + 21: [21, 22], + 22: [22, 23], + 23: [23, 24], + 24: [24, 25], + 25: [25, 26], + 26: [26, 27], + 27: [27, 28], + 28: [28, 29], + 29: [29, 30], + 30: [30, 31], + 31: [31, 32], + 32: [32, 33], + 33: [33, 34], + 34: [34, 35], + 35: [35, 36], + 36: [36, 37], + 37: [37, 38], + 38: [38, 39], + 39: [39, 40], + 40: [40, 41], + 41: [41, 42], + 42: [42, 43], + 43: [43, 44], + 44: [44, 45], + 45: [45, 46], + 46: [46, 47], + 47: [47, 48], + 48: [48, 49], + 49: [49, 50], # QSFP49 + 50: [51, 52], + 51: [53, 54], + 52: [50, 51], + 53: [52, 53], + 54: [54, 55], # QSFP54 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + # Two i2c buses might get flipped order, check them both. + def update_i2c_order(self): + if self.I2C_BUS_ORDER < 0: + eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + if os.path.exists(eeprom_path): + self.I2C_BUS_ORDER = 0 + eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + if os.path.exists(eeprom_path): + self.I2C_BUS_ORDER = 1 + return self.I2C_BUS_ORDER + + 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 + + order = self.update_i2c_order() + if port_num <= 24: + present_path = self.BASE_CPLD2_PATH.format(order) + else: + present_path = self.BASE_CPLD3_PATH.format(order) + present_path = present_path + "module_present_" + str(port_num) + self.__port_to_is_present = present_path + + content = "0" + try: + val_file = open(self.__port_to_is_present) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def qsfp_sb_remap(self, port_num): + qsfp_start = self.qsfp_port_start + qsfp_index = port_num - qsfp_start + qsfp_index = self.qsfp_sb_map[qsfp_index] + return qsfp_start+qsfp_index + + def get_low_power_mode_cpld(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + order = self.update_i2c_order() + lp_mode_path = self.BASE_CPLD3_PATH.format(order) + lp_mode_path = lp_mode_path + "module_lp_mode_" + q = self.qsfp_sb_remap(port_num) + lp_mode_path = lp_mode_path + str(q) + + content = "0" + try: + val_file = open(lp_mode_path) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + if not self.get_presence(port_num): + return self.get_low_power_mode_cpld(port_num) + + try: + eeprom = None + + eeprom = open(self.port_to_eeprom_mapping[port_num], mode="rb", buffering=0) + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if not (lpmode & 0x1): # 'Power override' bit is 0 + return self.get_low_power_mode_cpld(port_num) + else: + if ((lpmode & 0x2) == 0x2): + return True # Low Power Mode if "Power set" bit is 1 + else: + return False # High Power Mode if "Power set" bit is 0 + except IOError as err: + print("Error: unable to open file: %s" % str(err)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], mode="r+b", buffering=0) + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as err: + print("Error: unable to open file: %s" % str(err)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + order = self.update_i2c_order() + lp_mode_path = self.BASE_CPLD3_PATH.format(order) + mod_rst_path = lp_mode_path + "module_reset_" + q = self.qsfp_sb_remap(port_num) + mod_rst_path = mod_rst_path + str(q) + try: + reg_file = open(mod_rst_path, 'r+', buffering=0) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # toggle reset + reg_file.seek(0) + reg_file.write('0') + time.sleep(1) + reg_file.seek(0) + reg_file.write('1') + reg_file.close() + return True + + @property + def _get_presence_bitmap(self): + nodes = [] + order = self.update_i2c_order() + + present_path = self.BASE_CPLD2_PATH.format(order) + nodes.append(present_path + "module_present_all") + present_path = self.BASE_CPLD3_PATH.format(order) + nodes.append(present_path + "module_present_all") + + bitmap = "" + for node in nodes: + try: + reg_file = open(node) + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap += reg_file.readline().rstrip() + " " + reg_file.close() + + rev = bitmap.split(" ") + rev = "".join(rev[::-1]) + return int(rev, 16) + + data = {'valid': 0, 'last': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + port = 0 + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + reg_value = self._get_presence_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + fp_port = self._port_to_i2c_mapping[port][0] + mask = (1 << (fp_port - 1)) + if changed_ports & mask: + + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['last'] = now + self.data['valid'] = 1 + + return True, port_dict + else: + return True, {} + return False, {} + + def __init__(self): + eeprom_path = self.BASE_OOM_PATH + "eeprom" + + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x][1] + ) + + SfpUtilBase.__init__(self) diff --git a/device/accton/x86_64-accton_as5712_54x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as5712_54x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as5712_54x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/port_config.ini b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/port_config.ini new file mode 100644 index 000000000000..857a8987bc13 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/port_config.ini @@ -0,0 +1,73 @@ +# name lanes alias index speed autoneg +Ethernet0 14 tenGigE0 1 10000 1 +Ethernet1 13 tenGigE1 2 10000 1 +Ethernet2 16 tenGigE2 3 10000 1 +Ethernet3 15 tenGigE3 4 10000 1 +Ethernet4 22 tenGigE4 5 10000 1 +Ethernet5 21 tenGigE5 6 10000 1 +Ethernet6 24 tenGigE6 7 10000 1 +Ethernet7 23 tenGigE7 8 10000 1 +Ethernet8 26 tenGigE8 9 10000 1 +Ethernet9 25 tenGigE9 10 10000 1 +Ethernet10 28 tenGigE10 11 10000 1 +Ethernet11 27 tenGigE11 12 10000 1 +Ethernet12 30 tenGigE12 13 10000 1 +Ethernet13 29 tenGigE13 14 10000 1 +Ethernet14 32 tenGigE14 15 10000 1 +Ethernet15 31 tenGigE15 16 10000 1 +Ethernet16 46 tenGigE16 17 10000 1 +Ethernet17 45 tenGigE17 18 10000 1 +Ethernet18 48 tenGigE18 19 10000 1 +Ethernet19 47 tenGigE19 20 10000 1 +Ethernet20 50 tenGigE20 21 10000 1 +Ethernet21 49 tenGigE21 22 10000 1 +Ethernet22 52 tenGigE22 23 10000 1 +Ethernet23 51 tenGigE23 24 10000 1 +Ethernet24 54 tenGigE24 25 10000 1 +Ethernet25 53 tenGigE25 26 10000 1 +Ethernet26 56 tenGigE26 27 10000 1 +Ethernet27 55 tenGigE27 28 10000 1 +Ethernet28 58 tenGigE28 29 10000 1 +Ethernet29 57 tenGigE29 30 10000 1 +Ethernet30 60 tenGigE30 31 10000 1 +Ethernet31 59 tenGigE31 32 10000 1 +Ethernet32 62 tenGigE32 33 10000 1 +Ethernet33 61 tenGigE33 34 10000 1 +Ethernet34 64 tenGigE34 35 10000 1 +Ethernet35 63 tenGigE35 36 10000 1 +Ethernet36 66 tenGigE36 37 10000 1 +Ethernet37 65 tenGigE37 38 10000 1 +Ethernet38 68 tenGigE38 39 10000 1 +Ethernet39 67 tenGigE39 40 10000 1 +Ethernet40 70 tenGigE40 41 10000 1 +Ethernet41 69 tenGigE41 42 10000 1 +Ethernet42 72 tenGigE42 43 10000 1 +Ethernet43 71 tenGigE43 44 10000 1 +Ethernet44 74 tenGigE44 45 10000 1 +Ethernet45 73 tenGigE45 46 10000 1 +Ethernet46 76 tenGigE46 47 10000 1 +Ethernet47 75 tenGigE47 48 10000 1 +Ethernet48 97 tenGigE48 49 10000 0 +Ethernet49 98 tenGigE49 49 10000 0 +Ethernet50 99 tenGigE50 49 10000 0 +Ethernet51 100 tenGigE51 49 10000 0 +Ethernet52 101 tenGigE52 50 10000 0 +Ethernet53 102 tenGigE53 50 10000 0 +Ethernet54 103 tenGigE54 50 10000 0 +Ethernet55 104 tenGigE55 50 10000 0 +Ethernet56 77 tenGigE56 51 10000 0 +Ethernet57 78 tenGigE57 51 10000 0 +Ethernet58 79 tenGigE58 51 10000 0 +Ethernet59 80 tenGigE59 51 10000 0 +Ethernet60 105 tenGigE60 52 10000 0 +Ethernet61 106 tenGigE61 52 10000 0 +Ethernet62 107 tenGigE62 52 10000 0 +Ethernet63 108 tenGigE63 52 10000 0 +Ethernet64 109 tenGigE64 53 10000 0 +Ethernet65 110 tenGigE65 53 10000 0 +Ethernet66 111 tenGigE66 53 10000 0 +Ethernet67 112 tenGigE67 53 10000 0 +Ethernet68 81 tenGigE68 54 10000 0 +Ethernet69 82 tenGigE69 54 10000 0 +Ethernet70 83 tenGigE70 54 10000 0 +Ethernet71 84 tenGigE71 54 10000 0 diff --git a/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/sai.profile b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/sai.profile new file mode 100644 index 000000000000..3c78aab15dcb --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-as5812t-72x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/td2-as5812t-72x10G.config.bcm b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/td2-as5812t-72x10G.config.bcm new file mode 100644 index 000000000000..23ccc495bbd6 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/td2-as5812t-72x10G.config.bcm @@ -0,0 +1,194 @@ +bcm_num_cos=10 +bcm_stat_flags=0 +bcm_stat_interval=2000000 +bcm_tunnel_term_compatible_mode=1 + +cdma_timeout_usec=3000000 + +fpem_mem_entries=16384 + +ipv6_lpm_128b_enable=0x1 +ifp_inports_support_enable=1 + +l2xmsg_mode=1 +l2_mem_entries=32768 + +l3_alpm_enable=2 +l3_max_ecmp_mode=1 +l3_mem_entries=16384 +l3_alpm_ipv6_128b_bkt_rsvd=1 + +load_firmware=0x101 + +max_vp_lags=0 +module_64ports=1 +miim_intr_enable=0 +mem_cache_enable=0 +mdio_output_delay=15 + +os=unix +oversubscribe_mode=1 + +parity_enable=0 +port_flex_enable=1 +parity_correction=0 +phy_ext_rom_boot_xe=0 +phy_aux_voltage_enable=1 + +#for 72 ports with 48 10G ports and 6 40G ports for breakout mode +pbmp_xport_xe=0x7fffffffffffffffffe +pbmp_oversubscribe=0x7fffffffffffffffffe + +rate_ext_mdio_divisor=96 + +schan_intr_enable=0 +skip_L2_USER_ENTRY=0 +stable_size=0x2000000 +stable_size=0x5500000 ;Specify the stable cache size in bytes used for Warm boot operations + +tdma_timeout_usec=3000000 + +#port-lanes configuration +portmap_1=14:10 +portmap_2=13:10 +portmap_3=16:10 +portmap_4=15:10 +port_phy_addr_1=0x1 +port_phy_addr_2=0x0 +port_phy_addr_3=0x3 +port_phy_addr_4=0x2 + +portmap_5=22:10 +portmap_6=21:10 +portmap_7=24:10 +portmap_8=23:10 +port_phy_addr_5=0x5 +port_phy_addr_6=0x4 +port_phy_addr_7=0x7 +port_phy_addr_8=0x6 + +portmap_9=26:10 +portmap_10=25:10 +portmap_11=28:10 +portmap_12=27:10 +port_phy_addr_9=0x9 +port_phy_addr_10=0x8 +port_phy_addr_11=0xb +port_phy_addr_12=0xa + +portmap_13=30:10 +portmap_14=29:10 +portmap_15=32:10 +portmap_16=31:10 +port_phy_addr_13=0x21 +port_phy_addr_14=0x20 +port_phy_addr_15=0x23 +port_phy_addr_16=0x22 + +portmap_17=46:10 +portmap_18=45:10 +portmap_19=48:10 +portmap_20=47:10 +port_phy_addr_17=0x25 +port_phy_addr_18=0x24 +port_phy_addr_19=0x27 +port_phy_addr_20=0x26 + +portmap_21=50:10 +portmap_22=49:10 +portmap_23=52:10 +portmap_24=51:10 +port_phy_addr_21=0x29 +port_phy_addr_22=0x28 +port_phy_addr_23=0x2b +port_phy_addr_24=0x2a + +portmap_25=54:10 +portmap_26=53:10 +portmap_27=56:10 +portmap_28=55:10 +port_phy_addr_25=0x41 +port_phy_addr_26=0x40 +port_phy_addr_27=0x43 +port_phy_addr_28=0x42 + +portmap_29=58:10 +portmap_30=57:10 +portmap_31=60:10 +portmap_32=59:10 +port_phy_addr_29=0x45 +port_phy_addr_30=0x44 +port_phy_addr_31=0x47 +port_phy_addr_32=0x46 + +portmap_33=62:10 +portmap_34=61:10 +portmap_35=64:10 +portmap_36=63:10 +port_phy_addr_33=0x49 +port_phy_addr_34=0x48 +port_phy_addr_35=0x4b +port_phy_addr_36=0x4a + +portmap_37=66:10 +portmap_38=65:10 +portmap_39=68:10 +portmap_40=67:10 +port_phy_addr_37=0x61 +port_phy_addr_38=0x60 +port_phy_addr_39=0x63 +port_phy_addr_40=0x62 + +portmap_41=70:10 +portmap_42=69:10 +portmap_43=72:10 +portmap_44=71:10 +port_phy_addr_41=0x65 +port_phy_addr_42=0x64 +port_phy_addr_43=0x67 +port_phy_addr_44=0x66 + +portmap_45=74:10 +portmap_46=73:10 +portmap_47=76:10 +portmap_48=75:10 +port_phy_addr_45=0x69 +port_phy_addr_46=0x68 +port_phy_addr_47=0x6b +port_phy_addr_48=0x6a + +#port_49 +portmap_49=97:10 +portmap_50=98:10 +portmap_51=99:10 +portmap_52=100:10 + +#port_50 +portmap_53=101:10 +portmap_54=102:10 +portmap_55=103:10 +portmap_56=104:10 + +#port_51 +portmap_57=77:10 +portmap_58=78:10 +portmap_59=79:10 +portmap_60=80:10 + +#port_52 +portmap_61=105:10 +portmap_62=106:10 +portmap_63=107:10 +portmap_64=108:10 + +#port_53 +portmap_65=109:10 +portmap_66=110:10 +portmap_67=111:10 +portmap_68=112:10 + +#port_54 +portmap_69=81:10 +portmap_70=82:10 +portmap_71=83:10 +portmap_72=84:10 \ No newline at end of file diff --git a/device/accton/x86_64-accton_as5812_54t-r0/default_sku b/device/accton/x86_64-accton_as5812_54t-r0/default_sku new file mode 100644 index 000000000000..87b99bac77be --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54t-r0/default_sku @@ -0,0 +1 @@ +Accton-AS5812-54T t1 diff --git a/device/accton/x86_64-accton_as5812_54t-r0/installer.conf b/device/accton/x86_64-accton_as5812_54t-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54t-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as5812_54t-r0/led_proc_init.soc b/device/accton/x86_64-accton_as5812_54t-r0/led_proc_init.soc new file mode 100644 index 000000000000..954446d4a8ba --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54t-r0/led_proc_init.soc @@ -0,0 +1,94 @@ +# LED setting for active +# ----------------------------------------------------------------------------- +# for as5812_54t (48xg+6qxg) +# +# on green - if link up +# off - if link down +# blink - if active +# ----------------------------------------------------------------------------- + +m xlmac_rx_ctrl.xe0-xe47 STRICT_PREAMBLE=0 + +link on +link off + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=12 REMAP_PORT_1=13 REMAP_PORT_2=14 REMAP_PORT_3=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=8 REMAP_PORT_5=9 REMAP_PORT_6=10 REMAP_PORT_7=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=4 REMAP_PORT_9=5 REMAP_PORT_10=6 REMAP_PORT_11=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0 REMAP_PORT_13=1 REMAP_PORT_14=2 REMAP_PORT_15=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=16 REMAP_PORT_17=17 REMAP_PORT_18=18 REMAP_PORT_19=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=63 REMAP_PORT_21=62 REMAP_PORT_22=61 REMAP_PORT_23=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 REMAP_PORT_25=62 REMAP_PORT_26=61 REMAP_PORT_27=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 REMAP_PORT_29=62 REMAP_PORT_30=61 REMAP_PORT_31=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=62 REMAP_PORT_34=61 REMAP_PORT_35=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=28 REMAP_PORT_37=29 REMAP_PORT_38=30 REMAP_PORT_39=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=24 REMAP_PORT_41=25 REMAP_PORT_42=26 REMAP_PORT_43=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=20 REMAP_PORT_45=21 REMAP_PORT_46=22 REMAP_PORT_47=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=32 REMAP_PORT_49=33 REMAP_PORT_50=34 REMAP_PORT_51=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=63 REMAP_PORT_53=62 REMAP_PORT_54=61 REMAP_PORT_55=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=63 REMAP_PORT_57=62 REMAP_PORT_58=61 REMAP_PORT_59=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=63 REMAP_PORT_2=63 REMAP_PORT_3=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=63 REMAP_PORT_5=63 REMAP_PORT_6=63 REMAP_PORT_7=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=63 REMAP_PORT_9=63 REMAP_PORT_10=63 REMAP_PORT_11=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=15 REMAP_PORT_21=14 REMAP_PORT_22=13 REMAP_PORT_23=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 REMAP_PORT_25=6 REMAP_PORT_26=5 REMAP_PORT_27=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 REMAP_PORT_29=2 REMAP_PORT_30=1 REMAP_PORT_31=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=23 REMAP_PORT_33=22 REMAP_PORT_34=21 REMAP_PORT_35=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=63 REMAP_PORT_37=63 REMAP_PORT_38=63 REMAP_PORT_39=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=63 REMAP_PORT_41=63 REMAP_PORT_42=63 REMAP_PORT_43=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11 REMAP_PORT_49=10 REMAP_PORT_50=9 REMAP_PORT_51=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=24 REMAP_PORT_53=25 REMAP_PORT_54=26 REMAP_PORT_55=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=28 REMAP_PORT_57=29 REMAP_PORT_58=30 REMAP_PORT_59=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=32 REMAP_PORT_61=33 REMAP_PORT_62=34 REMAP_PORT_63=35 +led 0 stop +led 0 prog \ +02 F9 42 80 02 F7 42 00 02 F8 42 00 02 F4 42 48 \ +02 F3 42 24 06 F5 D2 00 74 1E 02 F5 42 05 67 4B \ +86 F8 06 F3 D6 F8 74 1E 86 F0 3E F4 06 F8 88 4A \ +03 75 3C 4A 04 71 41 67 7D 67 91 57 67 7D 67 91 \ +57 67 91 67 7D 57 67 7D 67 7D 57 06 F8 88 80 4A \ +00 27 97 75 46 90 4A 00 27 4A 01 27 B7 97 71 62 \ +77 2C 06 F5 D6 F0 74 75 02 F5 4A 07 37 4E 07 02 \ +F0 42 00 4E 07 06 F5 0A 07 71 46 77 2C 16 F7 06 \ +F9 17 4D DA 07 74 8E 12 F7 52 00 86 F9 57 86 F7 \ +57 16 F7 06 F9 07 4D DA 07 74 A2 12 F7 52 00 86 \ +F9 57 86 F7 57 00 00 00 00 00 00 00 00 00 00 00 \ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +led 0 start + +led 1 stop +led 1 prog \ +02 F9 42 80 02 F7 42 00 02 F8 42 00 02 F4 42 36 \ +02 F3 42 24 02 F6 17 4E 01 67 AD 86 F8 67 AD 86 \ +F8 67 AD 86 F8 67 AD 86 F8 06 F8 D2 18 74 19 12 \ +01 02 10 60 F8 67 7E 12 01 02 0C 60 F8 67 7E 12 \ +01 02 04 60 F8 67 7E 12 01 02 00 60 F8 67 7E 12 \ +01 02 08 60 F8 67 7E 12 01 02 14 60 F8 67 7E 02 \ +F6 07 4E 01 02 18 60 F8 67 AD 86 F8 06 F3 D6 F8 \ +74 68 86 F0 3E F4 16 E0 5A 00 71 AD 77 A2 1A 00 \ +75 AD 77 A2 02 F6 4A 01 71 9F 06 F8 88 4A 03 75 \ +95 4A 04 71 9A 67 DF 67 E3 57 67 E3 67 DF 57 67 \ +E3 57 02 F6 4A 01 71 AA 67 DF 67 DF 57 06 F8 88 \ +80 4A 00 27 97 75 A2 90 4A 00 27 4A 01 27 B7 97 \ +71 C4 77 84 06 F5 D6 F0 74 D7 02 F5 4A 07 37 4E \ +07 02 F0 42 00 4E 07 06 F5 0A 07 71 A2 77 84 22 \ +01 77 E5 22 00 16 F7 06 F9 97 4D DA 07 74 F6 12 \ +F7 52 00 86 F9 57 86 F7 57 00 00 00 00 00 00 00 + + +led 1 start + +link on +led auto on +set RCError=off + diff --git a/device/accton/x86_64-accton_as5812_54t-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as5812_54t-r0/plugins/eeprom.py new file mode 100644 index 000000000000..951384d5e37d --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54t-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as5812_54t-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as5812_54t-r0/plugins/psuutil.py new file mode 100755 index 000000000000..b7a0a2fd66e3 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54t-r0/plugins/psuutil.py @@ -0,0 +1,64 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: ["11-0038", "11-0050"], + 2: ["12-003b", "12-0053"], + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + lst = self.psu_mapping[index] + for i in lst: + node = self.psu_path + i + self.psu_oper_status + try: + with open(node, 'r') as power_status: + status += int(power_status.read()) + except IOError: + return False + + return status > 0 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + lst = self.psu_mapping[index] + for i in lst: + node = self.psu_path + i + self.psu_presence + try: + with open(node, 'r') as presence_status: + status += int(presence_status.read()) + except IOError: + return False + + return status > 0 diff --git a/device/accton/x86_64-accton_as5812_54t-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as5812_54t-r0/plugins/sfputil.py new file mode 100755 index 000000000000..38beeaf6ca5e --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54t-r0/plugins/sfputil.py @@ -0,0 +1,283 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# +try: + import time + import os + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# from xcvrd +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 49 + PORT_END = 54 + PORTS_IN_BLOCK = 54 + QSFP_PORT_START = 49 + QSFP_PORT_END = 54 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD_PATH = "/sys/bus/i2c/devices/{0}-0060/" + I2C_BUS_ORDER = -1 + + # The sidebands of QSFP is different. + # present is in-order. + # But lp_mode and reset are not. + qsfp_sb_map = [0, 2, 4, 1, 3, 5] + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 49: [1, 4], # QSFP_start + 50: [2, 6], + 51: [3, 3], + 52: [4, 5], + 53: [5, 7], + 54: [6, 2], + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = self.BASE_OOM_PATH + "eeprom" + + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x][1] + ) + SfpUtilBase.__init__(self) + + # Two i2c buses might get flipped order, check them both. + def update_i2c_order(self): + if self.I2C_BUS_ORDER < 0: + eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + if os.path.exists(eeprom_path): + self.I2C_BUS_ORDER = 0 + eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + if os.path.exists(eeprom_path): + self.I2C_BUS_ORDER = 1 + return self.I2C_BUS_ORDER + + 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 + + order = self.update_i2c_order() + present_path = self.BASE_CPLD_PATH.format(order) + present_path = present_path + "module_present_" + str(port_num) + self.__port_to_is_present = present_path + + content = "0" + try: + val_file = open(self.__port_to_is_present) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode_cpld(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + order = self.update_i2c_order() + lp_mode_path = self.BASE_CPLD_PATH.format(order) + lp_mode_path = lp_mode_path + "module_lp_mode_" + lp_mode_path = lp_mode_path + str(port_num) + + content = "0" + try: + val_file = open(lp_mode_path) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + if not self.get_presence(port_num): + return self.get_low_power_mode_cpld(port_num) + + try: + eeprom = None + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if not (lpmode & 0x1): # 'Power override' bit is 0 + return self.get_low_power_mode_cpld(port_num) + else: + if ((lpmode & 0x2) == 0x2): + return True # Low Power Mode if "Power set" bit is 1 + else: + return False # High Power Mode if "Power set" bit is 0 + except IOError as err: + print("Error: unable to open file: %s" % str(err)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as err: + print("Error: unable to open file: %s" % str(err)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + order = self.update_i2c_order() + lp_mode_path = self.BASE_CPLD_PATH.format(order) + mod_rst_path = lp_mode_path + "module_reset_" + mod_rst_path = mod_rst_path + str(port_num) + print(mod_rst_path) + + try: + reg_file = open(mod_rst_path, 'r+', buffering=0) + 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 + + @property + def _get_presence_bitmap(self): + nodes = [] + order = self.update_i2c_order() + + present_path = self.BASE_CPLD_PATH.format(order) + nodes.append(present_path + "module_present_all") + + bitmap = "" + for node in nodes: + try: + reg_file = open(node) + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap += reg_file.readline().rstrip() + " " + reg_file.close() + + rev = bitmap.split(" ") + rev = "".join(rev[::-1]) + return int(rev, 16) + + data = {'present': 0} + + def get_transceiver_change_event(self, timeout=2000): + port_dict = {} + port = 0 + + if timeout == 0: + cd_ms = sys.maxsize + else: + cd_ms = timeout + + # poll per second + while cd_ms > 0: + reg_value = self._get_presence_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports != 0: + break + time.sleep(1) + cd_ms = cd_ms - 1000 + + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + fp_port = self._port_to_i2c_mapping[port][0] + mask = (1 << (fp_port - 1)) + if changed_ports & mask: + + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/accton/x86_64-accton_as5812_54t-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as5812_54t-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54t-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as5812_54x-r0/Accton-AS5812-54X/port_config.ini b/device/accton/x86_64-accton_as5812_54x-r0/Accton-AS5812-54X/port_config.ini new file mode 100755 index 000000000000..ee60c526227d --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54x-r0/Accton-AS5812-54X/port_config.ini @@ -0,0 +1,73 @@ +# name lanes alias index speed +Ethernet0 13 tenGigE0 1 10000 +Ethernet1 14 tenGigE1 2 10000 +Ethernet2 15 tenGigE2 3 10000 +Ethernet3 16 tenGigE3 4 10000 +Ethernet4 21 tenGigE4 5 10000 +Ethernet5 22 tenGigE5 6 10000 +Ethernet6 23 tenGigE6 7 10000 +Ethernet7 24 tenGigE7 8 10000 +Ethernet8 25 tenGigE8 9 10000 +Ethernet9 26 tenGigE9 10 10000 +Ethernet10 27 tenGigE10 11 10000 +Ethernet11 28 tenGigE11 12 10000 +Ethernet12 29 tenGigE12 13 10000 +Ethernet13 30 tenGigE13 14 10000 +Ethernet14 31 tenGigE14 15 10000 +Ethernet15 32 tenGigE15 16 10000 +Ethernet16 45 tenGigE16 17 10000 +Ethernet17 46 tenGigE17 18 10000 +Ethernet18 47 tenGigE18 19 10000 +Ethernet19 48 tenGigE19 20 10000 +Ethernet20 49 tenGigE20 21 10000 +Ethernet21 50 tenGigE21 22 10000 +Ethernet22 51 tenGigE22 23 10000 +Ethernet23 52 tenGigE23 24 10000 +Ethernet24 53 tenGigE24 25 10000 +Ethernet25 54 tenGigE25 26 10000 +Ethernet26 55 tenGigE26 27 10000 +Ethernet27 56 tenGigE27 28 10000 +Ethernet28 57 tenGigE28 29 10000 +Ethernet29 58 tenGigE29 30 10000 +Ethernet30 59 tenGigE30 31 10000 +Ethernet31 60 tenGigE31 32 10000 +Ethernet32 61 tenGigE32 33 10000 +Ethernet33 62 tenGigE33 34 10000 +Ethernet34 63 tenGigE34 35 10000 +Ethernet35 64 tenGigE35 36 10000 +Ethernet36 65 tenGigE36 37 10000 +Ethernet37 66 tenGigE37 38 10000 +Ethernet38 67 tenGigE38 39 10000 +Ethernet39 68 tenGigE39 40 10000 +Ethernet40 69 tenGigE40 41 10000 +Ethernet41 70 tenGigE41 42 10000 +Ethernet42 71 tenGigE42 43 10000 +Ethernet43 72 tenGigE43 44 10000 +Ethernet44 73 tenGigE44 45 10000 +Ethernet45 74 tenGigE45 46 10000 +Ethernet46 75 tenGigE46 47 10000 +Ethernet47 76 tenGigE47 48 10000 +Ethernet48 97 tenGigE48 49 10000 +Ethernet49 98 tenGigE49 49 10000 +Ethernet50 99 tenGigE50 49 10000 +Ethernet51 100 tenGigE51 49 10000 +Ethernet52 101 tenGigE52 50 10000 +Ethernet53 102 tenGigE53 50 10000 +Ethernet54 103 tenGigE54 50 10000 +Ethernet55 104 tenGigE55 50 10000 +Ethernet56 81 tenGigE56 51 10000 +Ethernet57 82 tenGigE57 51 10000 +Ethernet58 83 tenGigE58 51 10000 +Ethernet59 84 tenGigE59 51 10000 +Ethernet60 105 tenGigE60 52 10000 +Ethernet61 106 tenGigE61 52 10000 +Ethernet62 107 tenGigE62 52 10000 +Ethernet63 108 tenGigE63 52 10000 +Ethernet64 109 tenGigE64 53 10000 +Ethernet65 110 tenGigE65 53 10000 +Ethernet66 111 tenGigE66 53 10000 +Ethernet67 112 tenGigE67 53 10000 +Ethernet68 77 tenGigE68 54 10000 +Ethernet69 78 tenGigE69 54 10000 +Ethernet70 79 tenGigE70 54 10000 +Ethernet71 80 tenGigE71 54 10000 diff --git a/device/accton/x86_64-accton_as5812_54x-r0/Accton-AS5812-54X/sai.profile b/device/accton/x86_64-accton_as5812_54x-r0/Accton-AS5812-54X/sai.profile new file mode 100755 index 000000000000..0ec3aa1896cf --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54x-r0/Accton-AS5812-54X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-as5812-72x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as5812_54x-r0/Accton-AS5812-54X/td2-as5812-72x10G.config.bcm b/device/accton/x86_64-accton_as5812_54x-r0/Accton-AS5812-54X/td2-as5812-72x10G.config.bcm new file mode 100644 index 000000000000..1d6286ba3bd7 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54x-r0/Accton-AS5812-54X/td2-as5812-72x10G.config.bcm @@ -0,0 +1,148 @@ +os=unix +bcm_stat_flags=0 +parity_enable=0 +parity_correction=0 + +bcm_num_cos=10 +l2_mem_entries=32768 +l3_mem_entries=16384 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 + +mmu_lossless=0 +lls_num_l2uc=12 +module_64ports=0 + +#SFI +serdes_if_type=9 + +port_init_cl72=0 +phy_an_c73=5 # TSCMOD_CL73_CL37 + +#sdk6.5.5 only supports 156(default) or 125 +#xgxs_lcpll_xtal_refclk=1 +tslam_dma_enable=1 +table_dma_enable=1 + +#for 72 ports with 48 10G ports and 6 40G ports for breakout mode +pbmp_oversubscribe=0x1fffffffffffffffffe +pbmp_xport_xe=0x1fffffffffffffffffe + +rate_ext_mdio_divisor=96 + +#SFP+ 1-4 from WC3 +portmap_1=13:10 +portmap_2=14:10 +portmap_3=15:10 +portmap_4=16:10 + +#SFP+ 5-8 from WC5 +portmap_5=21:10 +portmap_6=22:10 +portmap_7=23:10 +portmap_8=24:10 + +#SFP+ 9-12 from WC6 +portmap_9=25:10 +portmap_10=26:10 +portmap_11=27:10 +portmap_12=28:10 + +#SFP+ 13-16 from WC7 +portmap_13=29:10 +portmap_14=30:10 +portmap_15=31:10 +portmap_16=32:10 + +#SFP+ 17-20 from WC11 +portmap_17=45:10 +portmap_18=46:10 +portmap_19=47:10 +portmap_20=48:10 + +#SFP+ 21-24 from WC12 +portmap_21=49:10 +portmap_22=50:10 +portmap_23=51:10 +portmap_24=52:10 + +#SFP+ 25-28 from WC13 +portmap_25=53:10 +portmap_26=54:10 +portmap_27=55:10 +portmap_28=56:10 + +#SFP+ 29-32 from WC14 +portmap_29=57:10 +portmap_30=58:10 +portmap_31=59:10 +portmap_32=60:10 + +#SFP+ 33-36 from WC15 +portmap_33=61:10 +portmap_34=62:10 +portmap_35=63:10 +portmap_36=64:10 + +#SFP+ 37-40 from WC16 +portmap_37=65:10 +portmap_38=66:10 +portmap_39=67:10 +portmap_40=68:10 + +#SFP+ 41-44 from WC17 +portmap_41=69:10 +portmap_42=70:10 +portmap_43=71:10 +portmap_44=72:10 + +#SFP+ 45-48 from WC18 +portmap_45=73:10 +portmap_46=74:10 +portmap_47=75:10 +portmap_48=76:10 + +# QSFP+ 49/WC24/port 49 +portmap_49=97:10 +portmap_50=98:10 +portmap_51=99:10 +portmap_52=100:10 + +# QSFP+ 51/WC25/port 50 +portmap_53=101:10 +portmap_54=102:10 +portmap_55=103:10 +portmap_56=104:10 + +# QSFP+ 53/WC20/port 51 +portmap_57=81:10 +portmap_58=82:10 +portmap_59=83:10 +portmap_60=84:10 + +# QSFP+ 50/WC26/port 52 +portmap_61=105:10 +portmap_62=106:10 +portmap_63=107:10 +portmap_64=108:10 + +# QSFP+ 52/WC27/port 53 +portmap_65=109:10 +portmap_66=110:10 +portmap_67=111:10 +portmap_68=112:10 + +# QSFP+ 54/WC19/port 54 +portmap_69=77:10 +portmap_70=78:10 +portmap_71=79:10 +portmap_72=80:10 + +# L3 ECMP +# - In Trident2, VP LAGs share the same table as ECMP group table. +# The first N entries are reserved for VP LAGs, where N is the value of the +# config property "max_vp_lags". By default this was set to 256 +l3_max_ecmp_mode=1 +max_vp_lags=0 + +stable_size=0x2000000 diff --git a/device/accton/x86_64-accton_as5812_54x-r0/default_sku b/device/accton/x86_64-accton_as5812_54x-r0/default_sku new file mode 100644 index 000000000000..b52f97504176 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS5812-54X t1 diff --git a/device/accton/x86_64-accton_as5812_54x-r0/installer.conf b/device/accton/x86_64-accton_as5812_54x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as5812_54x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as5812_54x-r0/led_proc_init.soc new file mode 100644 index 000000000000..d93e373d0567 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54x-r0/led_proc_init.soc @@ -0,0 +1,162 @@ +# LED setting for active +# ----------------------------------------------------------------------------- +# for as5812_54x (48xg+6qxg) +# +# on green - if link up +# off - if link down +# blink - if active +# ----------------------------------------------------------------------------- +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=38 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=41 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=42 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=45 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=46 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=49 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=50 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=53 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=54 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=58 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=59 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=61 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=62 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 + +led 0 stop +led 0 prog \ + 06 FE 80 D2 19 71 08 E0 60 FE E9 D2 0F 75 10 81 \ + 61 FD 02 3F 60 FF 28 32 0F 87 67 4A 96 FF 06 FF \ + D2 2B 74 16 02 1F 60 FF 28 32 0F 87 67 4A 96 FF \ + 06 FF D2 13 74 28 02 0F 60 FF 28 32 0F 87 67 4A \ + 96 FF 06 FF D2 0B 74 3A 3A 48 32 07 32 08 C7 32 \ + 04 C7 97 71 57 77 69 32 00 32 01 B7 97 71 63 32 \ + 0E 77 6B 26 FD 97 27 77 6B 32 0F 87 57 00 00 00 +led 0 start + +led 1 stop +led 1 prog \ + 06 FE 80 D2 19 71 08 E0 60 FE E9 D2 0F 75 10 81 \ + 61 FD 02 20 67 89 02 24 67 89 02 10 67 89 02 28 \ + 67 89 02 2C 67 89 02 0C 67 89 02 2C 67 79 02 28 \ + 67 79 02 24 67 79 02 20 67 79 02 10 67 79 02 0C \ + 67 79 02 0B 60 FF 28 32 0F 87 67 56 96 FF 06 FF \ + D2 FF 74 46 3A 36 32 07 32 08 C7 32 04 C7 97 71 \ + 63 77 75 32 00 32 01 B7 97 71 6F 32 0E 77 77 26 \ + FD 97 27 77 77 32 0F 87 57 12 A0 F8 15 1A 01 75 \ + 85 28 67 56 57 32 0F 87 57 12 A0 F8 15 1A 01 71 \ + A1 28 67 56 80 28 67 56 80 28 67 56 80 28 67 56 \ + 57 32 0F 87 32 0F 87 32 0F 87 32 0F 87 57 00 00 +led 1 start diff --git a/device/accton/x86_64-accton_as5812_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as5812_54x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..951384d5e37d --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54x-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as5812_54x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as5812_54x-r0/plugins/psuutil.py new file mode 100755 index 000000000000..a07aebc96312 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54x-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "57-0038", + 2: "58-003b", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as5812_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as5812_54x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..be301aea493b --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54x-r0/plugins/sfputil.py @@ -0,0 +1,344 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# +try: + import time + import os + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# from xcvrd +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 54 + PORTS_IN_BLOCK = 54 + QSFP_PORT_START = 49 + QSFP_PORT_END = 54 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD2_PATH = "/sys/bus/i2c/devices/{0}-0061/" + BASE_CPLD3_PATH = "/sys/bus/i2c/devices/{0}-0062/" + I2C_BUS_ORDER = -1 + + # The sidebands of QSFP is different. + # present is in-order. + # But lp_mode and reset are not. + qsfp_sb_map = [0, 2, 4, 1, 3, 5] + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 1: [1, 2], + 2: [2, 3], + 3: [3, 4], + 4: [4, 5], + 5: [5, 6], + 6: [6, 7], + 7: [7, 8], + 8: [8, 9], + 9: [9, 10], + 10: [10, 11], + 11: [11, 12], + 12: [12, 13], + 13: [13, 14], + 14: [14, 15], + 15: [15, 16], + 16: [16, 17], + 17: [17, 18], + 18: [18, 19], + 19: [19, 20], + 20: [20, 21], + 21: [21, 22], + 22: [22, 23], + 23: [23, 24], + 24: [24, 25], + 25: [25, 26], + 26: [26, 27], + 27: [27, 28], + 28: [28, 29], + 29: [29, 30], + 30: [30, 31], + 31: [31, 32], + 32: [32, 33], + 33: [33, 34], + 34: [34, 35], + 35: [35, 36], + 36: [36, 37], + 37: [37, 38], + 38: [38, 39], + 39: [39, 40], + 40: [40, 41], + 41: [41, 42], + 42: [42, 43], + 43: [43, 44], + 44: [44, 45], + 45: [45, 46], + 46: [46, 47], + 47: [47, 48], + 48: [48, 49], + 49: [49, 50], # QSFP_start + 50: [51, 52], + 51: [53, 54], + 52: [50, 51], + 53: [52, 53], + 54: [54, 55], + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = self.BASE_OOM_PATH + "eeprom" + + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x][1] + ) + SfpUtilBase.__init__(self) + + # Two i2c buses might get flipped order, check them both. + def update_i2c_order(self): + if self.I2C_BUS_ORDER < 0: + eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" + if os.path.exists(eeprom_path): + self.I2C_BUS_ORDER = 0 + eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + if os.path.exists(eeprom_path): + self.I2C_BUS_ORDER = 1 + return self.I2C_BUS_ORDER + + 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 + + order = self.update_i2c_order() + if port_num <= 24: + present_path = self.BASE_CPLD2_PATH.format(order) + else: + present_path = self.BASE_CPLD3_PATH.format(order) + + present_path = present_path + "module_present_" + str(port_num) + self.__port_to_is_present = present_path + + content = "0" + try: + val_file = open(self.__port_to_is_present) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def qsfp_sb_remap(self, port_num): + qsfp_start = self.qsfp_port_start + qsfp_index = port_num - qsfp_start + qsfp_index = self.qsfp_sb_map[qsfp_index] + return qsfp_start+qsfp_index + + def get_low_power_mode_cpld(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + order = self.update_i2c_order() + lp_mode_path = self.BASE_CPLD3_PATH.format(order) + lp_mode_path = lp_mode_path + "module_lp_mode_" + q = self.qsfp_sb_remap(port_num) + lp_mode_path = lp_mode_path + str(q) + + content = "0" + try: + val_file = open(lp_mode_path) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + if not self.get_presence(port_num): + return self.get_low_power_mode_cpld(port_num) + + try: + eeprom = None + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if not (lpmode & 0x1): # 'Power override' bit is 0 + return self.get_low_power_mode_cpld(port_num) + else: + if ((lpmode & 0x2) == 0x2): + return True # Low Power Mode if "Power set" bit is 1 + else: + return False # High Power Mode if "Power set" bit is 0 + except IOError as err: + print("Error: unable to open file: %s" % str(err)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as err: + print("Error: unable to open file: %s" % str(err)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + order = self.update_i2c_order() + lp_mode_path = self.BASE_CPLD3_PATH.format(order) + mod_rst_path = lp_mode_path + "module_reset_" + q = self.qsfp_sb_remap(port_num) + mod_rst_path = mod_rst_path + str(q) + + try: + reg_file = open(mod_rst_path, 'r+', buffering=0) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # toggle reset + reg_file.seek(0) + reg_file.write('0') + time.sleep(1) + reg_file.seek(0) + reg_file.write('1') + reg_file.close() + return True + + @property + def _get_presence_bitmap(self): + nodes = [] + order = self.update_i2c_order() + + present_path = self.BASE_CPLD2_PATH.format(order) + nodes.append(present_path + "module_present_all") + present_path = self.BASE_CPLD3_PATH.format(order) + nodes.append(present_path + "module_present_all") + + bitmap = "" + for node in nodes: + try: + reg_file = open(node) + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap += reg_file.readline().rstrip() + " " + reg_file.close() + + rev = bitmap.split(" ") + rev = "".join(rev[::-1]) + return int(rev, 16) + + data = {'valid': 0, 'last': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + port = 0 + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + reg_value = self._get_presence_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + fp_port = self._port_to_i2c_mapping[port][0] + mask = (1 << (fp_port - 1)) + if changed_ports & mask: + + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['last'] = now + self.data['valid'] = 1 + + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/accton/x86_64-accton_as5812_54x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as5812_54x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as5812_54x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/mv2-as5835t-48x10G+6x100G.config.bcm b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/mv2-as5835t-48x10G+6x100G.config.bcm new file mode 100755 index 000000000000..63738e788d54 --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/mv2-as5835t-48x10G+6x100G.config.bcm @@ -0,0 +1,534 @@ +#polarity/lanemap is using TH2 style. +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 + +oversubscribe_mode=1 + +pbmp_xport_xe=0x1FFFFFFFFFFFFFFFE + +parity_enable=0 +mem_cache_enable=0 + +l2_mem_entries=32768 +l3_mem_entries=16384 +fpem_mem_entries=16384 +l2xmsg_mode=1 + +# Platform specfic +bcm_num_cos=10 +bcm_stat_interval=2000000 +cdma_timeout_usec=3000000 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l3_alpm_enable=2 +l3_max_ecmp_mode=1 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +port_flex_enable=1 +schan_intr_enable=0 +stable_size=0x5500000 ;Specify the stable cache size in bytes used for Warm boot operations +tdma_timeout_usec=3000000 +skip_L2_USER_ENTRY=0 +bcm_tunnel_term_compatible_mode=1 +l3_alpm_ipv6_128b_bkt_rsvd=1 + +#FC0 +dport_map_port_1=2 +dport_map_port_2=1 +dport_map_port_3=4 +dport_map_port_4=3 +portmap_1=1:10 +portmap_2=2:10 +portmap_3=3:10 +portmap_4=4:10 +#port_phy_addr_1=0x00 +#port_phy_addr_2=0x01 +#port_phy_addr_3=0x02 +#port_phy_addr_4=0x03 +phy_chain_rx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{2.0}=0x0123 +phy_chain_rx_lane_map_physical{3.0}=0x0123 +phy_chain_rx_lane_map_physical{4.0}=0x0123 +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_tx_lane_map_physical{2.0}=0x0123 +phy_chain_tx_lane_map_physical{3.0}=0x0123 +phy_chain_tx_lane_map_physical{4.0}=0x0123 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 + +#FC1 +dport_map_port_5=6 +dport_map_port_6=5 +dport_map_port_7=8 +dport_map_port_8=7 +portmap_5=5:10 +portmap_6=6:10 +portmap_7=7:10 +portmap_8=8:10 +#port_phy_addr_5=0x04 +#port_phy_addr_6=0x05 +#port_phy_addr_7=0x06 +#port_phy_addr_8=0x07 +phy_chain_rx_lane_map_physical{5.0}=0x0123 +phy_chain_rx_lane_map_physical{6.0}=0x0123 +phy_chain_rx_lane_map_physical{7.0}=0x0123 +phy_chain_rx_lane_map_physical{8.0}=0x0123 +phy_chain_tx_lane_map_physical{5.0}=0x0123 +phy_chain_tx_lane_map_physical{6.0}=0x0123 +phy_chain_tx_lane_map_physical{7.0}=0x0123 +phy_chain_tx_lane_map_physical{8.0}=0x0123 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x0 + +#FC2 +dport_map_port_9=10 +dport_map_port_10=9 +dport_map_port_11=12 +dport_map_port_12=11 +portmap_9=9:10 +portmap_10=10:10 +portmap_11=11:10 +portmap_12=12:10 +#port_phy_addr_9=0x20 +#port_phy_addr_10=0x21 +#port_phy_addr_11=0x22 +#port_phy_addr_12=0x23 +phy_chain_rx_lane_map_physical{9.0}=0x0123 +phy_chain_rx_lane_map_physical{10.0}=0x0123 +phy_chain_rx_lane_map_physical{11.0}=0x0123 +phy_chain_rx_lane_map_physical{12.0}=0x0123 +phy_chain_tx_lane_map_physical{9.0}=0x0123 +phy_chain_tx_lane_map_physical{10.0}=0x0123 +phy_chain_tx_lane_map_physical{11.0}=0x0123 +phy_chain_tx_lane_map_physical{12.0}=0x0123 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 + +#FC3 +dport_map_port_13=14 +dport_map_port_14=13 +dport_map_port_15=16 +dport_map_port_16=15 +portmap_13=13:10 +portmap_14=14:10 +portmap_15=15:10 +portmap_16=16:10 +#port_phy_addr_13=0x24 +#port_phy_addr_14=0x25 +#port_phy_addr_15=0x26 +#port_phy_addr_16=0x27 +phy_chain_rx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{14.0}=0x0123 +phy_chain_rx_lane_map_physical{15.0}=0x0123 +phy_chain_rx_lane_map_physical{16.0}=0x0123 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_tx_lane_map_physical{14.0}=0x0123 +phy_chain_tx_lane_map_physical{15.0}=0x0123 +phy_chain_tx_lane_map_physical{16.0}=0x0123 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x0 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 + +#FC4 +dport_map_port_17=18 +dport_map_port_18=17 +dport_map_port_19=20 +dport_map_port_20=19 +portmap_17=17:10 +portmap_18=18:10 +portmap_19=19:10 +portmap_20=20:10 +#port_phy_addr_17=0x40 +#port_phy_addr_18=0x41 +#port_phy_addr_19=0x42 +#port_phy_addr_20=0x43 +phy_chain_rx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{18.0}=0x0123 +phy_chain_rx_lane_map_physical{19.0}=0x0123 +phy_chain_rx_lane_map_physical{20.0}=0x0123 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_tx_lane_map_physical{18.0}=0x0123 +phy_chain_tx_lane_map_physical{19.0}=0x0123 +phy_chain_tx_lane_map_physical{20.0}=0x0123 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.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 + +#FC5 +dport_map_port_21=22 +dport_map_port_22=21 +dport_map_port_23=24 +dport_map_port_24=23 +portmap_21=21:10 +portmap_22=22:10 +portmap_23=23:10 +portmap_24=24:10 +#port_phy_addr_21=0x44 +#port_phy_addr_22=0x45 +#port_phy_addr_23=0x46 +#port_phy_addr_24=0x47 +phy_chain_rx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_lane_map_physical{22.0}=0x0123 +phy_chain_rx_lane_map_physical{23.0}=0x0123 +phy_chain_rx_lane_map_physical{24.0}=0x0123 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_tx_lane_map_physical{22.0}=0x0123 +phy_chain_tx_lane_map_physical{23.0}=0x0123 +phy_chain_tx_lane_map_physical{24.0}=0x0123 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x0 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 + +#FC6 + +#FC7 +dport_map_port_25=50 +portmap_25=29:100:4 +phy_chain_rx_lane_map_physical{29.0}=0x1302 +phy_chain_rx_lane_map_physical{30.0}=0x1302 +phy_chain_rx_lane_map_physical{31.0}=0x1302 +phy_chain_rx_lane_map_physical{32.0}=0x1302 +phy_chain_tx_lane_map_physical{29.0}=0x2031 +phy_chain_tx_lane_map_physical{30.0}=0x2031 +phy_chain_tx_lane_map_physical{31.0}=0x2031 +phy_chain_tx_lane_map_physical{32.0}=0x2031 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x1 + +#FC8 +dport_map_port_26=51 +portmap_26=33:100:4 +phy_chain_rx_lane_map_physical{33.0}=0x0123 +phy_chain_rx_lane_map_physical{34.0}=0x0123 +phy_chain_rx_lane_map_physical{35.0}=0x0123 +phy_chain_rx_lane_map_physical{36.0}=0x0123 +phy_chain_tx_lane_map_physical{33.0}=0x0123 +phy_chain_tx_lane_map_physical{34.0}=0x0123 +phy_chain_tx_lane_map_physical{35.0}=0x0123 +phy_chain_tx_lane_map_physical{36.0}=0x0123 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 + +#FC9 +dport_map_port_27=49 +dport_map_port_28=52 +dport_map_port_29=53 +dport_map_port_30=54 +portmap_27=37:100:4 +phy_chain_rx_lane_map_physical{37.0}=0x1023 +phy_chain_rx_lane_map_physical{38.0}=0x1023 +phy_chain_rx_lane_map_physical{39.0}=0x1023 +phy_chain_rx_lane_map_physical{40.0}=0x1023 +phy_chain_tx_lane_map_physical{37.0}=0x3210 +phy_chain_tx_lane_map_physical{38.0}=0x3210 +phy_chain_tx_lane_map_physical{39.0}=0x3210 +phy_chain_tx_lane_map_physical{40.0}=0x3210 +phy_chain_rx_polarity_flip_physical{37.0}=0x0 +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_tx_polarity_flip_physical{37.0}=0x0 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 + +#FC10 +dport_map_port_33=57 +portmap_33=41:100:4 +phy_chain_rx_lane_map_physical{41.0}=0x3210 +phy_chain_rx_lane_map_physical{42.0}=0x3210 +phy_chain_rx_lane_map_physical{43.0}=0x3210 +phy_chain_rx_lane_map_physical{44.0}=0x3210 +phy_chain_tx_lane_map_physical{41.0}=0x3210 +phy_chain_tx_lane_map_physical{42.0}=0x3210 +phy_chain_tx_lane_map_physical{43.0}=0x3210 +phy_chain_tx_lane_map_physical{44.0}=0x3210 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x1 +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 + +#FC11 +dport_map_port_34=56 +portmap_34=45:100:4 +phy_chain_rx_lane_map_physical{45.0}=0x3210 +phy_chain_rx_lane_map_physical{46.0}=0x3210 +phy_chain_rx_lane_map_physical{47.0}=0x3210 +phy_chain_rx_lane_map_physical{48.0}=0x3210 +phy_chain_tx_lane_map_physical{45.0}=0x3210 +phy_chain_tx_lane_map_physical{46.0}=0x3210 +phy_chain_tx_lane_map_physical{47.0}=0x3210 +phy_chain_tx_lane_map_physical{48.0}=0x3210 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x0 +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}=0x0 + +#FC12 +dport_map_port_35=55 +dport_map_port_36=58 +dport_map_port_37=59 +dport_map_port_38=60 +portmap_35=49:100:4 +phy_chain_rx_lane_map_physical{49.0}=0x3210 +phy_chain_rx_lane_map_physical{50.0}=0x3210 +phy_chain_rx_lane_map_physical{51.0}=0x3210 +phy_chain_rx_lane_map_physical{52.0}=0x3210 +phy_chain_tx_lane_map_physical{49.0}=0x3210 +phy_chain_tx_lane_map_physical{50.0}=0x3210 +phy_chain_tx_lane_map_physical{51.0}=0x3210 +phy_chain_tx_lane_map_physical{52.0}=0x3210 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 + +#FC13 +dport_map_port_39=26 +dport_map_port_40=25 +dport_map_port_41=28 +dport_map_port_42=27 +portmap_39=53:10 +portmap_40=54:10 +portmap_41=55:10 +portmap_42=56:10 +#port_phy_addr_39=0x60 +#port_phy_addr_40=0x61 +#port_phy_addr_41=0x62 +#port_phy_addr_42=0x63 +phy_chain_rx_lane_map_physical{53.0}=0x3120 +phy_chain_rx_lane_map_physical{54.0}=0x3120 +phy_chain_rx_lane_map_physical{55.0}=0x3120 +phy_chain_rx_lane_map_physical{56.0}=0x3120 +phy_chain_tx_lane_map_physical{53.0}=0x3102 +phy_chain_tx_lane_map_physical{54.0}=0x3102 +phy_chain_tx_lane_map_physical{55.0}=0x3102 +phy_chain_tx_lane_map_physical{56.0}=0x3102 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x1 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x0 +phy_chain_tx_polarity_flip_physical{53.0}=0x0 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 + +#FC14 +dport_map_port_43=30 +dport_map_port_44=29 +dport_map_port_45=32 +dport_map_port_46=31 +portmap_43=57:10 +portmap_44=58:10 +portmap_45=59:10 +portmap_46=60:10 +#port_phy_addr_43=0x64 +#port_phy_addr_44=0x65 +#port_phy_addr_45=0x66 +#port_phy_addr_46=0x67 +phy_chain_rx_lane_map_physical{57.0}=0x3210 +phy_chain_rx_lane_map_physical{58.0}=0x3210 +phy_chain_rx_lane_map_physical{59.0}=0x3210 +phy_chain_rx_lane_map_physical{60.0}=0x3210 +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_lane_map_physical{58.0}=0x3210 +phy_chain_tx_lane_map_physical{59.0}=0x3210 +phy_chain_tx_lane_map_physical{60.0}=0x3210 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 + +#FC15 +dport_map_port_47=34 +dport_map_port_48=33 +dport_map_port_49=36 +dport_map_port_50=35 +portmap_47=61:10 +portmap_48=62:10 +portmap_49=63:10 +portmap_50=64:10 +#port_phy_addr_47=0x100 +#port_phy_addr_48=0x101 +#port_phy_addr_49=0x102 +#port_phy_addr_50=0x103 +phy_chain_rx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{62.0}=0x3210 +phy_chain_rx_lane_map_physical{63.0}=0x3210 +phy_chain_rx_lane_map_physical{64.0}=0x3210 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_tx_lane_map_physical{62.0}=0x3210 +phy_chain_tx_lane_map_physical{63.0}=0x3210 +phy_chain_tx_lane_map_physical{64.0}=0x3210 +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}=0x1 +phy_chain_rx_polarity_flip_physical{64.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}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 + +#FC16 +dport_map_port_51=38 +dport_map_port_52=37 +dport_map_port_53=40 +dport_map_port_54=39 +portmap_51=65:10 +portmap_52=66:10 +portmap_53=67:10 +portmap_54=68:10 +#port_phy_addr_51=0x104 +#port_phy_addr_52=0x105 +#port_phy_addr_53=0x106 +#port_phy_addr_54=0x107 +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{66.0}=0x3210 +phy_chain_rx_lane_map_physical{67.0}=0x3210 +phy_chain_rx_lane_map_physical{68.0}=0x3210 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{66.0}=0x3210 +phy_chain_tx_lane_map_physical{67.0}=0x3210 +phy_chain_tx_lane_map_physical{68.0}=0x3210 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{65.0}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 + +#FC17 +dport_map_port_55=42 +dport_map_port_56=41 +dport_map_port_57=44 +dport_map_port_58=43 +portmap_55=69:10 +portmap_56=70:10 +portmap_57=71:10 +portmap_58=72:10 +#port_phy_addr_55=0x120 +#port_phy_addr_56=0x121 +#port_phy_addr_57=0x122 +#port_phy_addr_58=0x123 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{70.0}=0x3210 +phy_chain_rx_lane_map_physical{71.0}=0x3210 +phy_chain_rx_lane_map_physical{72.0}=0x3210 +phy_chain_tx_lane_map_physical{69.0}=0x3210 +phy_chain_tx_lane_map_physical{70.0}=0x3210 +phy_chain_tx_lane_map_physical{71.0}=0x3210 +phy_chain_tx_lane_map_physical{72.0}=0x3210 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 + +#FC18 +dport_map_port_59=46 +dport_map_port_60=45 +dport_map_port_61=48 +dport_map_port_62=47 +portmap_59=73:10 +portmap_60=74:10 +portmap_61=75:10 +portmap_62=76:10 +#port_phy_addr_59=0x124 +#port_phy_addr_60=0x125 +#port_phy_addr_61=0x126 +#port_phy_addr_62=0x127 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_rx_lane_map_physical{74.0}=0x3210 +phy_chain_rx_lane_map_physical{75.0}=0x3210 +phy_chain_rx_lane_map_physical{76.0}=0x3210 +phy_chain_tx_lane_map_physical{73.0}=0x2031 +phy_chain_tx_lane_map_physical{74.0}=0x2031 +phy_chain_tx_lane_map_physical{75.0}=0x2031 +phy_chain_tx_lane_map_physical{76.0}=0x2031 +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}=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}=0x0 + +#FC19 + +dport_map_port_64=64 +portmap_64=81:10:m +phy_chain_rx_polarity_flip_physical{81.0}=0x1 +phy_chain_tx_polarity_flip_physical{81.0}=0x1 + diff --git a/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/port_config.ini b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/port_config.ini new file mode 100755 index 000000000000..119fe814fee1 --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index speed +Ethernet0 2 tenGigE1 1 10000 +Ethernet1 1 tenGigE2 2 10000 +Ethernet2 4 tenGigE3 3 10000 +Ethernet3 3 tenGigE4 4 10000 +Ethernet4 6 tenGigE5 5 10000 +Ethernet5 5 tenGigE6 6 10000 +Ethernet6 8 tenGigE7 7 10000 +Ethernet7 7 tenGigE8 8 10000 +Ethernet8 10 tenGigE9 9 10000 +Ethernet9 9 tenGigE10 10 10000 +Ethernet10 12 tenGigE11 11 10000 +Ethernet11 11 tenGigE12 12 10000 +Ethernet12 14 tenGigE13 13 10000 +Ethernet13 13 tenGigE14 14 10000 +Ethernet14 16 tenGigE15 15 10000 +Ethernet15 15 tenGigE16 16 10000 +Ethernet16 18 tenGigE17 17 10000 +Ethernet17 17 tenGigE18 18 10000 +Ethernet18 20 tenGigE19 19 10000 +Ethernet19 19 tenGigE20 20 10000 +Ethernet20 22 tenGigE21 21 10000 +Ethernet21 21 tenGigE22 22 10000 +Ethernet22 24 tenGigE23 23 10000 +Ethernet23 23 tenGigE24 24 10000 +Ethernet24 54 tenGigE25 25 10000 +Ethernet25 53 tenGigE26 26 10000 +Ethernet26 56 tenGigE27 27 10000 +Ethernet27 55 tenGigE28 28 10000 +Ethernet28 58 tenGigE29 29 10000 +Ethernet29 57 tenGigE30 30 10000 +Ethernet30 60 tenGigE31 31 10000 +Ethernet31 59 tenGigE32 32 10000 +Ethernet32 62 tenGigE33 33 10000 +Ethernet33 61 tenGigE34 34 10000 +Ethernet34 64 tenGigE35 35 10000 +Ethernet35 63 tenGigE36 36 10000 +Ethernet36 66 tenGigE37 37 10000 +Ethernet37 65 tenGigE38 38 10000 +Ethernet38 68 tenGigE39 39 10000 +Ethernet39 67 tenGigE40 40 10000 +Ethernet40 70 tenGigE41 41 10000 +Ethernet41 69 tenGigE42 42 10000 +Ethernet42 72 tenGigE43 43 10000 +Ethernet43 71 tenGigE44 44 10000 +Ethernet44 74 tenGigE45 45 10000 +Ethernet45 73 tenGigE46 46 10000 +Ethernet46 76 tenGigE47 47 10000 +Ethernet47 75 tenGigE48 48 10000 +Ethernet48 37,38,39,40 hundredGigE49 49 100000 +Ethernet52 29,30,31,32 hundredGigE50 53 100000 +Ethernet56 33,34,35,36 hundredGigE51 57 100000 +Ethernet60 49,50,51,52 hundredGigE52 61 100000 +Ethernet64 45,46,47,48 hundredGigE53 65 100000 +Ethernet68 41,42,43,44 hundredGigE54 69 100000 diff --git a/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/sai.profile b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/sai.profile new file mode 100755 index 000000000000..124811980e70 --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/sai.profile @@ -0,0 +1,3 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/mv2-as5835t-48x10G+6x100G.config.bcm +SAI_BOARD_CONFIG_PATH=/etc/accton +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as5835_54t-r0/default_sku b/device/accton/x86_64-accton_as5835_54t-r0/default_sku new file mode 100644 index 000000000000..d0bfc0f22e8d --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54t-r0/default_sku @@ -0,0 +1 @@ +Accton-AS5835-54T t1 diff --git a/device/accton/x86_64-accton_as5835_54t-r0/installer.conf b/device/accton/x86_64-accton_as5835_54t-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54t-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as5835_54t-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as5835_54t-r0/plugins/eeprom.py new file mode 100644 index 000000000000..951384d5e37d --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54t-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as5835_54t-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as5835_54t-r0/plugins/psuutil.py new file mode 100644 index 000000000000..b22e01f5e9fc --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54t-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "11-0050", + 2: "12-0053", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as5835_54t-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as5835_54t-r0/plugins/sfputil.py new file mode 100644 index 000000000000..7c7e7f941a1f --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54t-r0/plugins/sfputil.py @@ -0,0 +1,307 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 49 + PORT_END = 72 + PORTS_IN_BLOCK = 72 + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 49: 28, # QSFP49 + 50: 28, + 51: 28, + 52: 28, + 53: 29, # QSFP50 + 54: 29, + 55: 29, + 56: 29, + 57: 26, # QSFP51 + 58: 26, + 59: 26, + 60: 26, + 61: 30, # QSFP52 + 62: 30, + 63: 30, + 64: 30, + 65: 31, # QSFP53 + 66: 31, + 67: 31, + 68: 31, + 69: 27, # QSFP54 + 70: 27, + 71: 27, + 72: 27, + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.PORT_START + + @property + def qsfp_port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + + SfpUtilBase.__init__(self) + + # For port 49~54 are QSFP, here presumed they're all split to 4 lanes. + + def get_cage_num(self, port_num): + cage_num = port_num + if (port_num >= self.PORT_START): + cage_num = (port_num - self.PORT_START)/4 + cage_num = cage_num + self.PORT_START + + return cage_num + + 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 + + cage_num = self.get_cage_num(port_num) + path = "/sys/bus/i2c/devices/3-0062/module_present_{0}" + port_ps = path.format(cage_num) + + content = "0" + try: + val_file = open(port_ps) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode_cpld(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cage_num = self.get_cage_num(port_num) + path = "/sys/bus/i2c/devices/3-0062/module_lpmode_{0}" + lp_mode_path = path.format(cage_num) + + try: + val_file = open(lp_mode_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + val_file.close() + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + if not self.get_presence(port_num): + return False + + try: + eeprom = None + + eeprom = open(self.port_to_eeprom_mapping[port_num], mode="rb", buffering=0) + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if not (lpmode & 0x1): # 'Power override' bit is 0 + return self.get_low_power_mode_cpld(port_num) + else: + if ((lpmode & 0x2) == 0x2): + return True # Low Power Mode if "Power set" bit is 1 + else: + return False # High Power Mode if "Power set" bit is 0 + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], mode="r+b", buffering=0) + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cage_num = self.get_cage_num(port_num) + path = "/sys/bus/i2c/devices/3-0062/module_reset_{0}" + port_ps = path.format(cage_num) + try: + reg_file = open(port_ps, mode="w", buffering=0) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # toggle reset + reg_file.seek(0) + reg_file.write('0') + time.sleep(1) + reg_file.seek(0) + reg_file.write('1') + reg_file.close() + + return True + + @property + def _get_presence_bitmap(self): + + bitmap = "" + try: + reg_file = open("/sys/bus/i2c/devices/3-0062/module_present_all") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap += reg_file.readline().rstrip() + " " + reg_file.close() + + rev = bitmap.split(" ") + rev.pop() # Remove the last useless character + + # Save port 49-54 into buffer + tmp = rev.pop() + + # Insert port 1-48 + for i in range(0, 6): + rev.append(hex(0)[2:]) + rev[i] = rev[i].zfill(2) + + # Expand port 49-54 + for i in range(0, 6): + val = (int(tmp, 16) >> i) & 0x1 + rev.append(hex(val)[2:]) + + rev = "".join(rev[::-1]) + return int(rev, 16) + + data = {'valid': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=0): + + start_time = time.time() + port_dict = {} + port = 0 + blocking = False + + if timeout == 0: + blocking = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print('get_transceiver_change_event:' + 'time wrap / invalid timeout value', timeout) + + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + # Check for OIR events and return updated port_dict + + reg_value = self._get_presence_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + mask = (1 << (port - 1)) + if changed_ports & mask: + + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['valid'] = 1 + return True, port_dict + + if blocking: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + print("get_transceiver_change_event: Should not reach here.") + return False, {} diff --git a/device/accton/x86_64-accton_as5835_54t-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as5835_54t-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54t-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as5835_54x-r0/Accton-AS5835-54X/mv2-as5835-48x10G+6x100G.config.bcm b/device/accton/x86_64-accton_as5835_54x-r0/Accton-AS5835-54X/mv2-as5835-48x10G+6x100G.config.bcm new file mode 100644 index 000000000000..e72a490b04d2 --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54x-r0/Accton-AS5835-54X/mv2-as5835-48x10G+6x100G.config.bcm @@ -0,0 +1,467 @@ +#polarity/lanemap is using TH2 style. +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 + +oversubscribe_mode=1 + +pbmp_xport_xe=0x1FFFFFFFFFFFFFFFE + +parity_enable=0 +mem_cache_enable=0 + +l2_mem_entries=32768 +#l3_mem_entries=49152 +#fpem_mem_entries=16384 +l2xmsg_mode=1 + +#FC0 +dport_map_port_1=1 +dport_map_port_2=2 +dport_map_port_3=3 +dport_map_port_4=4 +portmap_1=1:10 +portmap_2=2:10 +portmap_3=3:10 +portmap_4=4:10 +phy_chain_rx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{2.0}=0x0123 +phy_chain_rx_lane_map_physical{3.0}=0x0123 +phy_chain_rx_lane_map_physical{4.0}=0x0123 +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_tx_lane_map_physical{2.0}=0x0123 +phy_chain_tx_lane_map_physical{3.0}=0x0123 +phy_chain_tx_lane_map_physical{4.0}=0x0123 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 + +#FC1 +dport_map_port_5=5 +dport_map_port_6=6 +dport_map_port_7=7 +dport_map_port_8=8 +portmap_5=5:10 +portmap_6=6:10 +portmap_7=7:10 +portmap_8=8:10 +phy_chain_rx_lane_map_physical{5.0}=0x0123 +phy_chain_rx_lane_map_physical{6.0}=0x0123 +phy_chain_rx_lane_map_physical{7.0}=0x0123 +phy_chain_rx_lane_map_physical{8.0}=0x0123 +phy_chain_tx_lane_map_physical{5.0}=0x0123 +phy_chain_tx_lane_map_physical{6.0}=0x0123 +phy_chain_tx_lane_map_physical{7.0}=0x0123 +phy_chain_tx_lane_map_physical{8.0}=0x0123 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 + +#FC2 +dport_map_port_9=9 +dport_map_port_10=10 +dport_map_port_11=11 +dport_map_port_12=12 +portmap_9=9:10 +portmap_10=10:10 +portmap_11=11:10 +portmap_12=12:10 +phy_chain_rx_lane_map_physical{9.0}=0x0123 +phy_chain_rx_lane_map_physical{10.0}=0x0123 +phy_chain_rx_lane_map_physical{11.0}=0x0123 +phy_chain_rx_lane_map_physical{12.0}=0x0123 +phy_chain_tx_lane_map_physical{9.0}=0x0123 +phy_chain_tx_lane_map_physical{10.0}=0x0123 +phy_chain_tx_lane_map_physical{11.0}=0x0123 +phy_chain_tx_lane_map_physical{12.0}=0x0123 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 + +#FC3 +dport_map_port_13=13 +dport_map_port_14=14 +dport_map_port_15=15 +dport_map_port_16=16 +portmap_13=13:10 +portmap_14=14:10 +portmap_15=15:10 +portmap_16=16:10 +phy_chain_rx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{14.0}=0x0123 +phy_chain_rx_lane_map_physical{15.0}=0x0123 +phy_chain_rx_lane_map_physical{16.0}=0x0123 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_tx_lane_map_physical{14.0}=0x0123 +phy_chain_tx_lane_map_physical{15.0}=0x0123 +phy_chain_tx_lane_map_physical{16.0}=0x0123 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x0 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.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 + +#FC4 +dport_map_port_17=17 +dport_map_port_18=18 +dport_map_port_19=19 +dport_map_port_20=20 +portmap_17=17:10 +portmap_18=18:10 +portmap_19=19:10 +portmap_20=20:10 +phy_chain_rx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{18.0}=0x0123 +phy_chain_rx_lane_map_physical{19.0}=0x0123 +phy_chain_rx_lane_map_physical{20.0}=0x0123 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_tx_lane_map_physical{18.0}=0x0123 +phy_chain_tx_lane_map_physical{19.0}=0x0123 +phy_chain_tx_lane_map_physical{20.0}=0x0123 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x1 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{19.0}=0x0 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 + +#FC5 +dport_map_port_21=21 +dport_map_port_22=22 +dport_map_port_23=23 +dport_map_port_24=24 +portmap_21=21:10 +portmap_22=22:10 +portmap_23=23:10 +portmap_24=24:10 +phy_chain_rx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_lane_map_physical{22.0}=0x0123 +phy_chain_rx_lane_map_physical{23.0}=0x0123 +phy_chain_rx_lane_map_physical{24.0}=0x0123 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_tx_lane_map_physical{22.0}=0x0123 +phy_chain_tx_lane_map_physical{23.0}=0x0123 +phy_chain_tx_lane_map_physical{24.0}=0x0123 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x0 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +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}=0x1 + +#FC6 + +#FC7 +dport_map_port_25=50 +portmap_25=29:100:4 +phy_chain_rx_lane_map_physical{29.0}=0x1302 +phy_chain_rx_lane_map_physical{30.0}=0x1302 +phy_chain_rx_lane_map_physical{31.0}=0x1302 +phy_chain_rx_lane_map_physical{32.0}=0x1302 +phy_chain_tx_lane_map_physical{29.0}=0x2031 +phy_chain_tx_lane_map_physical{30.0}=0x2031 +phy_chain_tx_lane_map_physical{31.0}=0x2031 +phy_chain_tx_lane_map_physical{32.0}=0x2031 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x1 + +#FC8 +dport_map_port_26=51 +portmap_26=33:100:4 +phy_chain_rx_lane_map_physical{33.0}=0x1203 +phy_chain_rx_lane_map_physical{34.0}=0x1203 +phy_chain_rx_lane_map_physical{35.0}=0x1203 +phy_chain_rx_lane_map_physical{36.0}=0x1203 +phy_chain_tx_lane_map_physical{33.0}=0x3120 +phy_chain_tx_lane_map_physical{34.0}=0x3120 +phy_chain_tx_lane_map_physical{35.0}=0x3120 +phy_chain_tx_lane_map_physical{36.0}=0x3120 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 + +#FC9 +dport_map_port_27=49 +dport_map_port_28=52 +dport_map_port_29=53 +dport_map_port_30=54 +portmap_27=37:100:4 +phy_chain_rx_lane_map_physical{37.0}=0x2130 +phy_chain_rx_lane_map_physical{38.0}=0x2130 +phy_chain_rx_lane_map_physical{39.0}=0x2130 +phy_chain_rx_lane_map_physical{40.0}=0x2130 +phy_chain_tx_lane_map_physical{37.0}=0x3210 +phy_chain_tx_lane_map_physical{38.0}=0x3210 +phy_chain_tx_lane_map_physical{39.0}=0x3210 +phy_chain_tx_lane_map_physical{40.0}=0x3210 +phy_chain_rx_polarity_flip_physical{37.0}=0x0 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 + +#FC10 +dport_map_port_33=57 +portmap_33=41:100:4 +phy_chain_rx_lane_map_physical{41.0}=0x1320 +phy_chain_rx_lane_map_physical{42.0}=0x1320 +phy_chain_rx_lane_map_physical{43.0}=0x1320 +phy_chain_rx_lane_map_physical{44.0}=0x1320 +phy_chain_tx_lane_map_physical{41.0}=0x3210 +phy_chain_tx_lane_map_physical{42.0}=0x3210 +phy_chain_tx_lane_map_physical{43.0}=0x3210 +phy_chain_tx_lane_map_physical{44.0}=0x3210 +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}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x1 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 + +#FC11 +dport_map_port_34=56 +portmap_34=45:100:4 +phy_chain_rx_lane_map_physical{45.0}=0x3201 +phy_chain_rx_lane_map_physical{46.0}=0x3201 +phy_chain_rx_lane_map_physical{47.0}=0x3201 +phy_chain_rx_lane_map_physical{48.0}=0x3201 +phy_chain_tx_lane_map_physical{45.0}=0x3210 +phy_chain_tx_lane_map_physical{46.0}=0x3210 +phy_chain_tx_lane_map_physical{47.0}=0x3210 +phy_chain_tx_lane_map_physical{48.0}=0x3210 +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_tx_polarity_flip_physical{45.0}=0x0 +phy_chain_tx_polarity_flip_physical{46.0}=0x0 +phy_chain_tx_polarity_flip_physical{47.0}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x0 + +#FC12 +dport_map_port_35=55 +dport_map_port_36=58 +dport_map_port_37=59 +dport_map_port_38=60 +portmap_35=49:100:4 +phy_chain_rx_lane_map_physical{49.0}=0x0312 +phy_chain_rx_lane_map_physical{50.0}=0x0312 +phy_chain_rx_lane_map_physical{51.0}=0x0312 +phy_chain_rx_lane_map_physical{52.0}=0x0312 +phy_chain_tx_lane_map_physical{49.0}=0x3210 +phy_chain_tx_lane_map_physical{50.0}=0x3210 +phy_chain_tx_lane_map_physical{51.0}=0x3210 +phy_chain_tx_lane_map_physical{52.0}=0x3210 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 + +#FC13 +dport_map_port_39=25 +dport_map_port_40=26 +dport_map_port_41=27 +dport_map_port_42=28 +portmap_39=53:10 +portmap_40=54:10 +portmap_41=55:10 +portmap_42=56:10 +phy_chain_rx_lane_map_physical{53.0}=0x3120 +phy_chain_rx_lane_map_physical{54.0}=0x3120 +phy_chain_rx_lane_map_physical{55.0}=0x3120 +phy_chain_rx_lane_map_physical{56.0}=0x3120 +phy_chain_tx_lane_map_physical{53.0}=0x3102 +phy_chain_tx_lane_map_physical{54.0}=0x3102 +phy_chain_tx_lane_map_physical{55.0}=0x3102 +phy_chain_tx_lane_map_physical{56.0}=0x3102 +phy_chain_rx_polarity_flip_physical{53.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 +phy_chain_tx_polarity_flip_physical{53.0}=0x0 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x0 +phy_chain_tx_polarity_flip_physical{56.0}=0x1 + +#FC14 +dport_map_port_43=29 +dport_map_port_44=30 +dport_map_port_45=31 +dport_map_port_46=32 +portmap_43=57:10 +portmap_44=58:10 +portmap_45=59:10 +portmap_46=60:10 +phy_chain_rx_lane_map_physical{57.0}=0x3210 +phy_chain_rx_lane_map_physical{58.0}=0x3210 +phy_chain_rx_lane_map_physical{59.0}=0x3210 +phy_chain_rx_lane_map_physical{60.0}=0x3210 +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_lane_map_physical{58.0}=0x3210 +phy_chain_tx_lane_map_physical{59.0}=0x3210 +phy_chain_tx_lane_map_physical{60.0}=0x3210 +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}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 + +#FC15 +dport_map_port_47=33 +dport_map_port_48=34 +dport_map_port_49=35 +dport_map_port_50=36 +portmap_47=61:10 +portmap_48=62:10 +portmap_49=63:10 +portmap_50=64:10 +phy_chain_rx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{62.0}=0x3210 +phy_chain_rx_lane_map_physical{63.0}=0x3210 +phy_chain_rx_lane_map_physical{64.0}=0x3210 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_tx_lane_map_physical{62.0}=0x3210 +phy_chain_tx_lane_map_physical{63.0}=0x3210 +phy_chain_tx_lane_map_physical{64.0}=0x3210 +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}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 +phy_chain_tx_polarity_flip_physical{61.0}=0x0 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 + +#FC16 +dport_map_port_51=37 +dport_map_port_52=38 +dport_map_port_53=39 +dport_map_port_54=40 +portmap_51=65:10 +portmap_52=66:10 +portmap_53=67:10 +portmap_54=68:10 +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{66.0}=0x3210 +phy_chain_rx_lane_map_physical{67.0}=0x3210 +phy_chain_rx_lane_map_physical{68.0}=0x3210 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{66.0}=0x3210 +phy_chain_tx_lane_map_physical{67.0}=0x3210 +phy_chain_tx_lane_map_physical{68.0}=0x3210 +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}=0x1 +phy_chain_rx_polarity_flip_physical{68.0}=0x1 +phy_chain_tx_polarity_flip_physical{65.0}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x1 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x1 + +#FC17 +dport_map_port_55=41 +dport_map_port_56=42 +dport_map_port_57=43 +dport_map_port_58=44 +portmap_55=69:10 +portmap_56=70:10 +portmap_57=71:10 +portmap_58=72:10 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{70.0}=0x3210 +phy_chain_rx_lane_map_physical{71.0}=0x3210 +phy_chain_rx_lane_map_physical{72.0}=0x3210 +phy_chain_tx_lane_map_physical{69.0}=0x3210 +phy_chain_tx_lane_map_physical{70.0}=0x3210 +phy_chain_tx_lane_map_physical{71.0}=0x3210 +phy_chain_tx_lane_map_physical{72.0}=0x3210 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 + +#FC18 +dport_map_port_59=45 +dport_map_port_60=46 +dport_map_port_61=47 +dport_map_port_62=48 +portmap_59=73:10 +portmap_60=74:10 +portmap_61=75:10 +portmap_62=76:10 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_rx_lane_map_physical{74.0}=0x3210 +phy_chain_rx_lane_map_physical{75.0}=0x3210 +phy_chain_rx_lane_map_physical{76.0}=0x3210 +phy_chain_tx_lane_map_physical{73.0}=0x0231 +phy_chain_tx_lane_map_physical{74.0}=0x0231 +phy_chain_tx_lane_map_physical{75.0}=0x0231 +phy_chain_tx_lane_map_physical{76.0}=0x0231 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{76.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 + +#FC19 + +dport_map_port_64=64 +portmap_64=81:10:m +phy_chain_rx_polarity_flip_physical{81.0}=0x1 +phy_chain_tx_polarity_flip_physical{81.0}=0x1 + diff --git a/device/accton/x86_64-accton_as5835_54x-r0/Accton-AS5835-54X/port_config.ini b/device/accton/x86_64-accton_as5835_54x-r0/Accton-AS5835-54X/port_config.ini new file mode 100644 index 000000000000..1e4405d1a696 --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54x-r0/Accton-AS5835-54X/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index speed +Ethernet0 1 tenGigE1 1 10000 +Ethernet1 2 tenGigE2 2 10000 +Ethernet2 3 tenGigE3 3 10000 +Ethernet3 4 tenGigE4 4 10000 +Ethernet4 5 tenGigE5 5 10000 +Ethernet5 6 tenGigE6 6 10000 +Ethernet6 7 tenGigE7 7 10000 +Ethernet7 8 tenGigE8 8 10000 +Ethernet8 9 tenGigE9 9 10000 +Ethernet9 10 tenGigE10 10 10000 +Ethernet10 11 tenGigE11 11 10000 +Ethernet11 12 tenGigE12 12 10000 +Ethernet12 13 tenGigE13 13 10000 +Ethernet13 14 tenGigE14 14 10000 +Ethernet14 15 tenGigE15 15 10000 +Ethernet15 16 tenGigE16 16 10000 +Ethernet16 17 tenGigE17 17 10000 +Ethernet17 18 tenGigE18 18 10000 +Ethernet18 19 tenGigE19 19 10000 +Ethernet19 20 tenGigE20 20 10000 +Ethernet20 21 tenGigE21 21 10000 +Ethernet21 22 tenGigE22 22 10000 +Ethernet22 23 tenGigE23 23 10000 +Ethernet23 24 tenGigE24 24 10000 +Ethernet24 53 tenGigE25 25 10000 +Ethernet25 54 tenGigE26 26 10000 +Ethernet26 55 tenGigE27 27 10000 +Ethernet27 56 tenGigE28 28 10000 +Ethernet28 57 tenGigE29 29 10000 +Ethernet29 58 tenGigE30 30 10000 +Ethernet30 59 tenGigE31 31 10000 +Ethernet31 60 tenGigE32 32 10000 +Ethernet32 61 tenGigE33 33 10000 +Ethernet33 62 tenGigE34 34 10000 +Ethernet34 63 tenGigE35 35 10000 +Ethernet35 64 tenGigE36 36 10000 +Ethernet36 65 tenGigE37 37 10000 +Ethernet37 66 tenGigE38 38 10000 +Ethernet38 67 tenGigE39 39 10000 +Ethernet39 68 tenGigE40 40 10000 +Ethernet40 69 tenGigE41 41 10000 +Ethernet41 70 tenGigE42 42 10000 +Ethernet42 71 tenGigE43 43 10000 +Ethernet43 72 tenGigE44 44 10000 +Ethernet44 73 tenGigE45 45 10000 +Ethernet45 74 tenGigE46 46 10000 +Ethernet46 75 tenGigE47 47 10000 +Ethernet47 76 tenGigE48 48 10000 +Ethernet48 37,38,39,40 hundredGigE49 49 100000 +Ethernet52 29,30,31,32 hundredGigE50 53 100000 +Ethernet56 33,34,35,36 hundredGigE51 57 100000 +Ethernet60 49,50,51,52 hundredGigE52 61 100000 +Ethernet64 45,46,47,48 hundredGigE53 65 100000 +Ethernet68 41,42,43,44 hundredGigE54 69 100000 diff --git a/device/accton/x86_64-accton_as5835_54x-r0/Accton-AS5835-54X/sai.profile b/device/accton/x86_64-accton_as5835_54x-r0/Accton-AS5835-54X/sai.profile new file mode 100644 index 000000000000..744c6571f7c7 --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54x-r0/Accton-AS5835-54X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/bcm/mv2-as5835-48x10G+6x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as5835_54x-r0/default_sku b/device/accton/x86_64-accton_as5835_54x-r0/default_sku new file mode 100644 index 000000000000..c00cdbf64e5a --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS5835-54X t1 diff --git a/device/accton/x86_64-accton_as5835_54x-r0/installer.conf b/device/accton/x86_64-accton_as5835_54x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as5835_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as5835_54x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..951384d5e37d --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54x-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as5835_54x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as5835_54x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..b22e01f5e9fc --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54x-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "11-0050", + 2: "12-0053", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as5835_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as5835_54x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..b18b15f3e68c --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54x-r0/plugins/sfputil.py @@ -0,0 +1,384 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 72 + PORTS_IN_BLOCK = 72 + QSFP_PORT_START = 49 + QSFP_PORT_END = 72 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _cpld_mapping = { + 0: "3-0060", + 1: "3-0061", + 2: "3-0062", + } + _port_to_i2c_mapping = { + 1: 42, + 2: 43, + 3: 44, + 4: 45, + 5: 46, + 6: 47, + 7: 48, + 8: 49, + 9: 50, + 10: 51, + 11: 52, + 12: 53, + 13: 54, + 14: 55, + 15: 56, + 16: 57, + 17: 58, + 18: 59, + 19: 60, + 20: 61, + 21: 62, + 22: 63, + 23: 64, + 24: 65, + 25: 66, + 26: 67, + 27: 68, + 28: 69, + 29: 70, + 30: 71, + 31: 72, + 32: 73, + 33: 74, + 34: 75, + 35: 76, + 36: 77, + 37: 78, + 38: 79, + 39: 80, + 40: 81, + 41: 82, + 42: 83, + 43: 84, + 44: 85, + 45: 86, + 46: 87, + 47: 88, + 48: 89, + 49: 28, # QSFP49 + 50: 28, + 51: 28, + 52: 28, + 53: 29, # QSFP50 + 54: 29, + 55: 29, + 56: 29, + 57: 26, # QSFP51 + 58: 26, + 59: 26, + 60: 26, + 61: 30, # QSFP52 + 62: 30, + 63: 30, + 64: 30, + 65: 31, # QSFP53 + 66: 31, + 67: 31, + 68: 31, + 69: 27, # QSFP54 + 70: 27, + 71: 27, + 72: 27, + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + + SfpUtilBase.__init__(self) + + # For port 49~54 are QSFP, here presumed they're all split to 4 lanes. + + def get_cage_num(self, port_num): + cage_num = port_num + if (port_num >= self.QSFP_PORT_START): + cage_num = (port_num - self.QSFP_PORT_START)/4 + cage_num = cage_num + self.QSFP_PORT_START + + return cage_num + + # For cage 1~38 are at cpld2, others are at cpld3. + def get_cpld_num(self, port_num): + return 1 if (port_num < 39) else 2 + + 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 + + cage_num = self.get_cage_num(port_num) + cpld_i = self.get_cpld_num(port_num) + + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_present_{1}" + port_ps = path.format(cpld_ps, cage_num) + + content = "0" + try: + val_file = open(port_ps) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode_cpld(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cage_num = self.get_cage_num(port_num) + cpld_i = self.get_cpld_num(port_num) + + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_lpmode_{1}" + lp_mode_path = path.format(cpld_ps, cage_num) + + try: + val_file = open(lp_mode_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + val_file.close() + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + if not self.get_presence(port_num): + return False + + try: + eeprom = None + + eeprom = open(self.port_to_eeprom_mapping[port_num], mode="rb", buffering=0) + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if not (lpmode & 0x1): # 'Power override' bit is 0 + return self.get_low_power_mode_cpld(port_num) + else: + if ((lpmode & 0x2) == 0x2): + return True # Low Power Mode if "Power set" bit is 1 + else: + return False # High Power Mode if "Power set" bit is 0 + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], mode="r+b", buffering=0) + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cage_num = self.get_cage_num(port_num) + cpld_i = self.get_cpld_num(port_num) + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_reset_{1}" + port_ps = path.format(cpld_ps, cage_num) + try: + reg_file = open(port_ps, mode='w', buffering=0) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # toggle reset + reg_file.seek(0) + reg_file.write('0') + time.sleep(1) + reg_file.seek(0) + reg_file.write('1') + reg_file.close() + + return True + + @property + def _get_presence_bitmap(self): + nodes = [] + nodes.append("/sys/bus/i2c/devices/3-0061/module_present_all") + nodes.append("/sys/bus/i2c/devices/3-0062/module_present_all") + + bitmap = "" + for node in nodes: + try: + reg_file = open(node) + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap += reg_file.readline().rstrip() + " " + reg_file.close() + + rev = bitmap.split(" ") + rev.pop() # Remove the last useless character + + # Convert bitmap into continuously port order + rev[4] = hex((int(rev[4], 16) | ((int(rev[5], 16) & 0x3) << 6)))[2:] # Port 33-40 + rev[5] = hex((int(rev[5], 16) >> 2) | ((int(rev[6], 16) & 0x3) << 6))[2:] # Port 41-48 + + # Expand port 49-54 + tmp = rev.pop() + for i in range(2, 8): + val = (int(tmp, 16) >> i) & 0x1 + rev.append(hex(val)[2:]) + + for i in range(0, 6): + rev[i] = rev[i].zfill(2) + + rev = "".join(rev[::-1]) + return int(rev, 16) + + data = {'valid': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=0): + + start_time = time.time() + port_dict = {} + port = 0 + blocking = False + + if timeout == 0: + blocking = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print('get_transceiver_change_event:' + 'time wrap / invalid timeout value', timeout) + + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + # Check for OIR events and return updated port_dict + + reg_value = self._get_presence_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + mask = (1 << (port - 1)) + if changed_ports & mask: + + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['valid'] = 1 + return True, port_dict + + if blocking: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + print("get_transceiver_change_event: Should not reach here.") + return False, {} diff --git a/device/accton/x86_64-accton_as5835_54x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as5835_54x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as5835_54x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/port_config.ini b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/port_config.ini new file mode 100755 index 000000000000..5ad503c619df --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4 fortyGigE1 1 40000 +Ethernet4 5,6,7,8 fortyGigE2 2 40000 +Ethernet8 9,10,11,12 fortyGigE3 3 40000 +Ethernet12 13,14,15,16 fortyGigE4 4 40000 +Ethernet16 17,18,19,20 fortyGigE5 5 40000 +Ethernet20 21,22,23,24 fortyGigE6 6 40000 +Ethernet24 25,26,27,28 fortyGigE7 7 40000 +Ethernet28 29,30,31,32 fortyGigE8 8 40000 +Ethernet32 33,34,35,36 fortyGigE9 9 40000 +Ethernet36 37,38,39,40 fortyGigE10 10 40000 +Ethernet40 41,42,43,44 fortyGigE11 11 40000 +Ethernet44 45,46,47,48 fortyGigE12 12 40000 +Ethernet48 49,50,51,52 fortyGigE13 13 40000 +Ethernet52 53,54,55,56 fortyGigE14 14 40000 +Ethernet56 57,58,59,60 fortyGigE15 15 40000 +Ethernet60 61,62,63,64 fortyGigE16 16 40000 +Ethernet64 65,66,67,68 fortyGigE17 17 40000 +Ethernet68 69,70,71,72 fortyGigE18 18 40000 +Ethernet72 73,74,75,76 fortyGigE19 19 40000 +Ethernet76 77,78,79,80 fortyGigE20 20 40000 +Ethernet80 81,82,83,84 fortyGigE21 21 40000 +Ethernet84 85,86,87,88 fortyGigE22 22 40000 +Ethernet88 89,90,91,92 fortyGigE23 23 40000 +Ethernet92 93,94,95,96 fortyGigE24 24 40000 +Ethernet96 97,98,99,100 fortyGigE25 25 40000 +Ethernet100 101,102,103,104 fortyGigE26 26 40000 +Ethernet104 105,106,107,108 fortyGigE27 27 40000 +Ethernet108 109,110,111,112 fortyGigE28 28 40000 +Ethernet112 113,114,115,116 fortyGigE29 29 40000 +Ethernet116 117,118,119,120 fortyGigE30 30 40000 +Ethernet120 121,122,123,124 fortyGigE31 31 40000 +Ethernet124 125,126,127,128 fortyGigE32 32 40000 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/sai.profile b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/sai.profile new file mode 100644 index 000000000000..6f2a70f146ca --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-as6712-32x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/td2-as6712-32x40G.config.bcm b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/td2-as6712-32x40G.config.bcm new file mode 100644 index 000000000000..54f3c366fdc4 --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/Accton-AS6712-32X/td2-as6712-32x40G.config.bcm @@ -0,0 +1,132 @@ +os=unix +bcm_stat_flags=0 +parity_enable=0 +parity_correction=0 + +l2_mem_entries=163840 +l3_mem_entries=81920 +mmu_lossless=0 +lls_num_l2uc=12 +module_64ports=0 + +#SFI +serdes_if_type=9 + +port_init_cl72=0 +phy_an_c73=5 # TSCMOD_CL73_CL37 + +#sdk6.5.5 only supports 156(default) or 125 +#xgxs_lcpll_xtal_refclk=1 +tslam_dma_enable=1 +table_dma_enable=1 + +#for 32x40G ports for breakout mode +pbmp_oversubscribe=0x1fffffffe +pbmp_xport_xe=0x1fffffffe + +rate_ext_mdio_divisor=96 + +#QSFP+ 1 from WC0 +portmap_1=1:40 + +#QSFP+ 2 from WC1 +portmap_2=5:40 + +#QSFP+ 3 from WC2 +portmap_3=9:40 + +#QSFP+ 4 from WC3 +portmap_4=13:40 + +#QSFP+ 5 from WC4 +portmap_5=17:40 + +#QSFP+ 6 from WC5 +portmap_6=21:40 + +#QSFP+ 7 from WC6 +portmap_7=25:40 + +#QSFP+ 8 from WC7 +portmap_8=29:40 + +#QSFP+ 9 from WC8 +portmap_9=33:40 + +#QSFP+ 10 from WC9 +portmap_10=37:40 + +#QSFP+ 11 from WC10 +portmap_11=41:40 + +#QSFP+ 12 from WC11 +portmap_12=45:40 + +#QSFP+ 13 from WC12 +portmap_13=49:40 + +#QSFP+ 14 from WC13 +portmap_14=53:40 + +#QSFP+ 15 from WC14 +portmap_15=57:40 + +#QSFP+ 16 from WC15 +portmap_16=61:40 + +#QSFP+ 17 from WC16 +portmap_17=65:40 + +#QSFP+ 18 from WC17 +portmap_18=69:40 + +#QSFP+ 19 from WC18 +portmap_19=73:40 + +#QSFP+ 20 from WC19 +portmap_20=77:40 + +#QSFP+ 21 from WC20 +portmap_21=81:40 + +#QSFP+ 22 from WC21 +portmap_22=85:40 + +#QSFP+ 23 from WC22 +portmap_23=89:40 + +#QSFP+ 24 from WC23 +portmap_24=93:40 + +#QSFP+ 25 from WC24 +portmap_25=97:40 + +#QSFP+ 26 from WC25 +portmap_26=101:40 + +#QSFP+ 27 from WC26 +portmap_27=105:40 + +#QSFP+ 28 from WC27 +portmap_28=109:40 + +#QSFP+ 29 from WC28 +portmap_29=113:40 + +#QSFP+ 30 from WC29 +portmap_30=117:40 + +#QSFP+ 31 from WC30 +portmap_31=121:40 + +#QSFP+ 32 from WC31 +portmap_32=125:40 + +# L3 ECMP +# - In Trident2, VP LAGs share the same table as ECMP group table. +# The first N entries are reserved for VP LAGs, where N is the value of the +# config property "max_vp_lags". By default this was set to 256 +l3_max_ecmp_mode=1 +max_vp_lags=0 + +stable_size=0x2000000 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/default_sku b/device/accton/x86_64-accton_as6712_32x-r0/default_sku new file mode 100644 index 000000000000..d8cdd655905b --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS6712-32X t1 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/installer.conf b/device/accton/x86_64-accton_as6712_32x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as6712_32x-r0/led_proc_init.soc new file mode 100644 index 000000000000..9e29adf790de --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/led_proc_init.soc @@ -0,0 +1,104 @@ +# LED setting for active +# ----------------------------------------------------------------------------- +# for as6712_32x (32 qxg) +# ----------------------------------------------------------------------------- + +s CMIC_LEDUP0_DATA_RAM 0 +s CMIC_LEDUP1_DATA_RAM 0 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=7 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=15 + + +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=16 + + +led 0 stop +led 0 prog \ + 02 F9 42 80 02 F7 42 00 02 F8 42 00 02 F4 42 90 02 \ + F3 42 10 67 6A 67 6A 67 38 67 6A 67 6A 67 6A 67 6A \ + 67 6A 67 6A 86 F8 06 F3 D6 F8 74 14 86 F0 3E F4 67 \ + 6A 57 67 7E 57 06 F8 88 80 4A 00 27 97 75 35 90 4A \ + 00 27 4A 01 27 B7 97 71 4F 77 32 06 F5 D6 F0 74 62 \ + 02 F5 4A 07 37 4E 07 02 F0 42 00 4E 07 02 F5 4A 07 \ + 71 32 77 35 16 F7 06 F9 17 4D DA 07 74 7B 12 F7 52 \ + 00 86 F9 57 86 F7 57 16 F7 06 F9 07 4D DA 07 74 8F \ + 12 F7 52 00 86 F9 57 86 F7 57 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 +led 0 start + +led 1 stop +led 1 prog \ + 02 F9 42 80 02 F7 42 00 02 F8 42 01 02 F4 42 90 02 \ + F3 42 11 67 6A 67 6A 67 38 67 6A 67 6A 67 6A 67 6A \ + 67 6A 67 6A 86 F8 06 F3 D6 F8 74 14 86 F0 3E F4 67 \ + 6A 57 67 7E 57 06 F8 88 80 4A 00 27 97 75 35 90 4A \ + 00 27 4A 01 27 B7 97 71 4F 77 32 06 F5 D6 F0 74 62 \ + 02 F5 4A 07 37 4E 07 02 F0 42 00 4E 07 02 F5 4A 07 \ + 71 32 77 35 16 F7 06 F9 17 4D DA 07 74 7B 12 F7 52 \ + 00 86 F9 57 86 F7 57 16 F7 06 F9 07 4D DA 07 74 8F \ + 12 F7 52 00 86 F9 57 86 F7 57 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 +led 1 start diff --git a/device/accton/x86_64-accton_as6712_32x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as6712_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..bf7f2e1f3aec --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +try: + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as6712_32x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as6712_32x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..110c836004c8 --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "35-0038", + 2: "36-003b", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as6712_32x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as6712_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..28c9010abf56 --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/plugins/sfputil.py @@ -0,0 +1,305 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# from xcvrd +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 32 + PORTS_IN_BLOCK = 32 + QSFP_PORT_START = 1 + QSFP_PORT_END = 32 + + I2C_DEV_PATH = "/sys/bus/i2c/devices/" + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + CPLD_ADDRESS = ['-0062', '-0064'] + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 1: [1, 2], + 2: [2, 3], + 3: [3, 4], + 4: [4, 5], + 5: [5, 6], + 6: [6, 7], + 7: [7, 8], + 8: [8, 9], + 9: [9, 10], + 10: [10, 11], + 11: [11, 12], + 12: [12, 13], + 13: [13, 14], + 14: [14, 15], + 15: [15, 16], + 16: [16, 17], + 17: [17, 18], + 18: [18, 19], + 19: [19, 20], + 20: [20, 21], + 21: [21, 22], + 22: [22, 23], + 23: [23, 24], + 24: [24, 25], + 25: [25, 26], + 26: [26, 27], + 27: [27, 28], + 28: [28, 29], + 29: [29, 30], + 30: [30, 31], + 31: [31, 32], + 32: [32, 33], + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = self.BASE_OOM_PATH + "eeprom" + + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x][1] + ) + SfpUtilBase.__init__(self) + + def get_cpld_dev_path(self, port_num): + if port_num <= 16: + cpld_num = 0 + else: + cpld_num = 1 + + # cpld can be at either bus 0 or bus 1. + cpld_path = self.I2C_DEV_PATH + str(0) + self.CPLD_ADDRESS[cpld_num] + if not os.path.exists(cpld_path): + cpld_path = self.I2C_DEV_PATH + str(1) + self.CPLD_ADDRESS[cpld_num] + return cpld_path + + 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 + + cpld_path = self.get_cpld_dev_path(port_num) + present_path = cpld_path + "/module_present_" + present_path += str(self._port_to_i2c_mapping[port_num][0]) + + self.__port_to_is_present = present_path + + content = "0" + try: + val_file = open(self.__port_to_is_present) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode_cpld(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cpld_path = self.get_cpld_dev_path(port_num) + _path = cpld_path + "/module_lp_mode_" + _path += str(self._port_to_i2c_mapping[port_num][0]) + + content = "0" + try: + reg_file = open(_path) + content = reg_file.readline().rstrip() + reg_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + if not self.get_presence(port_num): + return False + + try: + eeprom = None + + eeprom = open(self.port_to_eeprom_mapping[port_num], mode="rb", buffering=0) + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if not (lpmode & 0x1): # 'Power override' bit is 0 + return self.get_low_power_mode_cpld(port_num) + else: + if ((lpmode & 0x2) == 0x2): + return True # Low Power Mode if "Power set" bit is 1 + else: + return False # High Power Mode if "Power set" bit is 0 + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], mode="r+b", buffering=0) + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cpld_path = self.get_cpld_dev_path(port_num) + _path = cpld_path + "/module_reset_" + _path += str(self._port_to_i2c_mapping[port_num][0]) + + try: + reg_file = open(_path, 'w') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_file.seek(0) + reg_file.write('1') + time.sleep(1) + reg_file.seek(0) + reg_file.write('0') + reg_file.close() + + return True + + @property + def get_transceiver_status(self): + nodes = [] + + cpld_path = self.get_cpld_dev_path(self.port_start) + nodes.append(cpld_path + "/module_present_all") + cpld_path = self.get_cpld_dev_path(self.port_end) + nodes.append(cpld_path + "/module_present_all") + + bitmap = "" + for node in nodes: + try: + reg_file = open(node) + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap += reg_file.readline().rstrip() + " " + reg_file.close() + + rev = bitmap.split(" ") + rev = "".join(rev[::-1]) + return int(rev, 16) + + data = {'valid': 0, 'last': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + port = 0 + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + reg_value = self.get_transceiver_status + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + fp_port = self._port_to_i2c_mapping[port][0] + mask = (1 << (fp_port - 1)) + if changed_ports & mask: + + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['last'] = now + self.data['valid'] = 1 + + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/accton/x86_64-accton_as6712_32x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as6712_32x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as6712_32x-r0/sensors.conf b/device/accton/x86_64-accton_as6712_32x-r0/sensors.conf new file mode 100644 index 000000000000..84ee0fd9f333 --- /dev/null +++ b/device/accton/x86_64-accton_as6712_32x-r0/sensors.conf @@ -0,0 +1,23 @@ +# libsensors configuration file for AS6712-32X +# ------------------------------------------------ + +chip "cpr_4011_4mxx-i2c-*-3c" + label in1 "PSU1_VIN" + label in2 "PSU1_VOUT" + label curr1 "PSU1_IIN" + label curr2 "PSU1_IOUT" + label power1 "PSU1_PIN" + label power2 "PSU1_POUT" + label fan1 "PSU1_FAN" + label temp1 "PSU1_TEMP" + +chip "cpr_4011_4mxx-i2c-*-3f" + label in1 "PSU2_VIN" + label in2 "PSU2_VOUT" + label curr1 "PSU2_IIN" + label curr2 "PSU2_IOUT" + label power1 "PSU2_PIN" + label power2 "PSU2_POUT" + label fan1 "PSU2_FAN" + label temp1 "PSU2_TEMP" + diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/buffers.json.j2 b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/buffers.json.j2 new file mode 100644 index 000000000000..9354b7ec5b59 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/buffers_defaults_t0.j2 b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..a47675b8dfa4 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/buffers_defaults_t0.j2 @@ -0,0 +1,72 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 48) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(48, 54) %} + {%- if PORT_ALL.append("Ethernet%d" % (48 + (port_idx-48) * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "static" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "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" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/buffers_defaults_t1.j2 b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..a47675b8dfa4 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/buffers_defaults_t1.j2 @@ -0,0 +1,72 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 48) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(48, 54) %} + {%- if PORT_ALL.append("Ethernet%d" % (48 + (port_idx-48) * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "static" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "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" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/led.bin b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/led.bin new file mode 100644 index 000000000000..bb4426fb59f4 Binary files /dev/null and b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/led.bin differ diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/nephos_dac.dsh b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/nephos_dac.dsh new file mode 100644 index 000000000000..42102053c3fb --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/nephos_dac.dsh @@ -0,0 +1,414 @@ +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=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=26 lane=0 max-speed=100g active=true +init set port-map unit=0 port=51 eth-macro=27 lane=0 max-speed=100g active=true +init set port-map unit=0 port=52 eth-macro=28 lane=0 max-speed=100g active=true +init set port-map unit=0 port=53 eth-macro=29 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 +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=tx data=0x1 +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=0x1.3.0.2 +phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=tx data=0x0.3.1.2 +phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x1.3.0.2 +phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x2.0.3.1 +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=0 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=rx data=0x2.1.0.3 +phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=rx data=0x0.1.3.2 +phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x3.1.0.2 +phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x1.3.0.2 +phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=tx data=0x0.0.0.1 +phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=tx data=0x1.1.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=0 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=rx data=0x0 +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.0.1 +phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=rx data=0x1.0.1.0 +phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x0.0.1.0 +phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=32 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=36 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=40 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=44 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c2 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=cn1 data=0x4.4.4.4 +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c0 data=0x1e.1e.1e.1e +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c1 data=0x2.2.2.2 +phy set mdio portlist=0 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=1 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=2 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=3 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=4 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=5 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=6 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=7 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=8 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=9 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=10 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=11 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=12 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=13 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=14 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=15 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=16 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=17 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=18 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=19 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=20 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=21 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=22 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=23 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=24 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=25 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=26 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=27 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=28 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=29 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=30 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=31 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=32 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=33 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=34 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=35 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=36 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=37 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=38 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=39 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=40 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=41 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=42 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=43 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=44 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=45 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=46 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=47 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=48 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=49 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=50 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=51 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=52 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=53 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=129 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=130 devad=0x1E addr=0x2 data=0x0000 +port set property unit=0 portlist=0-47 speed=25g +port set property unit=0 portlist=48-53 speed=100g +port set property unit=0 portlist=129-130 speed=10g +port set property unit=0 portlist=0-47 medium-type=cr +port set property unit=0 portlist=48-53 medium-type=cr4 +port set property unit=0 portlist=129-130 medium-type=kr +port set adver unit=0 portlist=129-130 speed-10g-kr +port set property unit=0 portlist=129-130 an=enable +port set property unit=0 portlist=129-130 admin=enable +port set property unit=0 portlist=0-53 admin=disable diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/nephos_opt.dsh b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/nephos_opt.dsh new file mode 100644 index 000000000000..ca2bc6497685 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/nephos_opt.dsh @@ -0,0 +1,415 @@ +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=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=26 lane=0 max-speed=100g active=true +init set port-map unit=0 port=51 eth-macro=27 lane=0 max-speed=100g active=true +init set port-map unit=0 port=52 eth-macro=28 lane=0 max-speed=100g active=true +init set port-map unit=0 port=53 eth-macro=29 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 +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap portlist=0 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=1 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=2 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=3 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=4 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=5 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=6 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=7 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=8 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=9 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=10 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=11 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=12 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=13 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=14 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=15 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=16 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=17 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=18 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=19 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=20 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=21 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=22 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=23 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=24 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=25 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=26 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=27 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=28 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=29 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=30 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=31 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=32 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=33 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=34 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=35 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=36 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=37 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=38 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=39 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=40 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=41 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=42 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=43 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=44 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=45 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=46 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=47 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=48 lane-cnt=4 property=tx data=0x1.3.0.2 +phy set lane-swap portlist=49 lane-cnt=4 property=tx data=0x0.3.1.2 +phy set lane-swap portlist=50 lane-cnt=4 property=tx data=0x1.3.0.2 +phy set lane-swap portlist=51 lane-cnt=4 property=tx data=0x2.0.3.1 +phy set lane-swap portlist=52 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=53 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=0 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=1 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=2 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=3 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=4 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=5 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=6 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=7 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=8 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=9 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=10 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=11 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=12 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=13 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=14 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=15 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=16 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=17 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=18 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=19 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=20 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=21 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=22 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=23 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=24 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=25 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=26 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=27 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=28 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=29 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=30 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=31 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=32 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=33 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=34 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=35 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=36 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=37 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=38 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=39 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=40 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=41 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=42 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=43 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=44 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=45 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=46 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=47 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=48 lane-cnt=4 property=rx data=0x2.1.0.3 +phy set lane-swap portlist=49 lane-cnt=4 property=rx data=0x0.1.3.2 +phy set lane-swap portlist=50 lane-cnt=4 property=rx data=0x3.1.0.2 +phy set lane-swap portlist=51 lane-cnt=4 property=rx data=0x1.3.0.2 +phy set lane-swap portlist=52 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=53 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set polarity-rev portlist=0 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=1 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=2 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=3 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=4 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=5 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=6 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=7 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=8 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=9 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=10 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=11 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=12 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=13 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=14 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=15 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=16 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=17 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=18 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=19 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=20 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=21 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=22 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=23 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=24 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=25 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=26 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=27 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=28 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=29 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=30 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=31 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=32 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=33 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=34 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=35 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=36 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=37 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=38 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=39 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=40 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=41 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=42 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=43 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=44 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=45 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=46 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=47 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=48 lane-cnt=4 property=tx data=0x0.0.0.1 +phy set polarity-rev portlist=49 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=50 lane-cnt=4 property=tx data=0x1.1.0.0 +phy set polarity-rev portlist=51 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=52 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=53 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=0 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=1 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=2 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=3 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=4 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=5 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=6 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=7 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=8 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=9 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=10 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=11 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=12 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=13 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=14 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=15 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=16 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=17 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=18 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=19 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=20 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=21 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=22 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=23 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=24 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=25 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=26 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=27 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=28 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=29 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=30 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=31 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=32 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=33 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=34 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=35 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=36 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=37 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=38 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=39 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=40 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=41 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=42 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=43 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=44 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=45 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=46 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=47 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=48 lane-cnt=4 property=rx data=0x0.1.0.1 +phy set polarity-rev portlist=49 lane-cnt=4 property=rx data=0x1.0.1.0 +phy set polarity-rev portlist=50 lane-cnt=4 property=rx data=0x0.0.1.0 +phy set polarity-rev portlist=51 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=52 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=53 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set pre-emphasis portlist=0 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=0 lane-cnt=4 property=cn1 data=0x1.1.1.1 +phy set pre-emphasis portlist=0 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=0 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=4 lane-cnt=4 property=cn1 data=0x1.1.1.1 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=4 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=8 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=8 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=12 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=12 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=16 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=16 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=20 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=20 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=24 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=24 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=28 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=28 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=32 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=32 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=36 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=36 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=40 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=40 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=44 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=44 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=48 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=48 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=49 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=49 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=50 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=50 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=51 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=51 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=52 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=52 lane-cnt=4 property=c1 data=0x8.8.8.8 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=53 lane-cnt=4 property=cn1 data=0x1.1.1.1 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=53 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set mdio portlist=0 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=1 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=2 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=3 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=4 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=5 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=6 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=7 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=8 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=9 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=10 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=11 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=12 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=13 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=14 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=15 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=16 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=17 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=18 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=19 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=20 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=21 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=22 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=23 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=24 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=25 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=26 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=27 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=28 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=29 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=30 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=31 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=32 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=33 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=34 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=35 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=36 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=37 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=38 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=39 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=40 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=41 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=42 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=43 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=44 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=45 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=46 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=47 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=48 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=49 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=50 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=51 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=52 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=53 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=129 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=130 devad=0x1E addr=0x2 data=0x0000 +port set property portlist=0-47 speed=25g +port set property portlist=48-53 speed=100g +port set property portlist=129-130 speed=10g +port set property portlist=0-47 medium-type=sr +port set property portlist=48-53 medium-type=sr4 +port set property portlist=129-130 medium-type=kr +port set adver portlist=129-130 speed-10g-kr +port set property portlist=129-130 an=enable +port set property unit=0 portlist=129-130 admin=enable +port set property unit=0 portlist=0-53 admin=disable + diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/pg_profile_lookup.ini b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/pg_profile_lookup.ini new file mode 100644 index 000000000000..d98b0eca6d19 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/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/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/port_config.ini b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/port_config.ini new file mode 100644 index 000000000000..9b05ff8e63fb --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/port_config.ini @@ -0,0 +1,55 @@ +# 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 104,105,106,107 Ethernet51/1 50 100000 +Ethernet51 108,109,110,111 Ethernet52/1 51 100000 +Ethernet52 112,113,114,115 Ethernet53/1 52 100000 +Ethernet53 116,117,118,119 Ethernet54/1 53 100000 diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/port_config.nps b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/port_config.nps new file mode 100644 index 000000000000..ca2bc6497685 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/port_config.nps @@ -0,0 +1,415 @@ +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=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=26 lane=0 max-speed=100g active=true +init set port-map unit=0 port=51 eth-macro=27 lane=0 max-speed=100g active=true +init set port-map unit=0 port=52 eth-macro=28 lane=0 max-speed=100g active=true +init set port-map unit=0 port=53 eth-macro=29 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 +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap portlist=0 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=1 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=2 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=3 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=4 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=5 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=6 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=7 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=8 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=9 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=10 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=11 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=12 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=13 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=14 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=15 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=16 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=17 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=18 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=19 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=20 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=21 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=22 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=23 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=24 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=25 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=26 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=27 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=28 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=29 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=30 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=31 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=32 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=33 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=34 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=35 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=36 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=37 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=38 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=39 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=40 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=41 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=42 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=43 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=44 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=45 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=46 lane-cnt=1 property=tx data=0x2 +phy set lane-swap portlist=47 lane-cnt=1 property=tx data=0x3 +phy set lane-swap portlist=48 lane-cnt=4 property=tx data=0x1.3.0.2 +phy set lane-swap portlist=49 lane-cnt=4 property=tx data=0x0.3.1.2 +phy set lane-swap portlist=50 lane-cnt=4 property=tx data=0x1.3.0.2 +phy set lane-swap portlist=51 lane-cnt=4 property=tx data=0x2.0.3.1 +phy set lane-swap portlist=52 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=53 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=0 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=1 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=2 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=3 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=4 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=5 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=6 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=7 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=8 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=9 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=10 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=11 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=12 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=13 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=14 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=15 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=16 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=17 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=18 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=19 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=20 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=21 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=22 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=23 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=24 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=25 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=26 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=27 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=28 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=29 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=30 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=31 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=32 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=33 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=34 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=35 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=36 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=37 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=38 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=39 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=40 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=41 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=42 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=43 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=44 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=45 lane-cnt=1 property=rx data=0x2 +phy set lane-swap portlist=46 lane-cnt=1 property=rx data=0x3 +phy set lane-swap portlist=47 lane-cnt=1 property=rx data=0x0 +phy set lane-swap portlist=48 lane-cnt=4 property=rx data=0x2.1.0.3 +phy set lane-swap portlist=49 lane-cnt=4 property=rx data=0x0.1.3.2 +phy set lane-swap portlist=50 lane-cnt=4 property=rx data=0x3.1.0.2 +phy set lane-swap portlist=51 lane-cnt=4 property=rx data=0x1.3.0.2 +phy set lane-swap portlist=52 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=53 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set polarity-rev portlist=0 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=1 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=2 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=3 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=4 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=5 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=6 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=7 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=8 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=9 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=10 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=11 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=12 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=13 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=14 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=15 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=16 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=17 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=18 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=19 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=20 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=21 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=22 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=23 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=24 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=25 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=26 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=27 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=28 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=29 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=30 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=31 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=32 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=33 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=34 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=35 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=36 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=37 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=38 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=39 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=40 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=41 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=42 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=43 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=44 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=45 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=46 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=47 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=48 lane-cnt=4 property=tx data=0x0.0.0.1 +phy set polarity-rev portlist=49 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=50 lane-cnt=4 property=tx data=0x1.1.0.0 +phy set polarity-rev portlist=51 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=52 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=53 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=0 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=1 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=2 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=3 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=4 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=5 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=6 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=7 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=8 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=9 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=10 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=11 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=12 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=13 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=14 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=15 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=16 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=17 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=18 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=19 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=20 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=21 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=22 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=23 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=24 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=25 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=26 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=27 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=28 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=29 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=30 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=31 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=32 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=33 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=34 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=35 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=36 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=37 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=38 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=39 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=40 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=41 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=42 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=43 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=44 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=45 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=46 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=47 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=48 lane-cnt=4 property=rx data=0x0.1.0.1 +phy set polarity-rev portlist=49 lane-cnt=4 property=rx data=0x1.0.1.0 +phy set polarity-rev portlist=50 lane-cnt=4 property=rx data=0x0.0.1.0 +phy set polarity-rev portlist=51 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=52 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=53 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set pre-emphasis portlist=0 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=0 lane-cnt=4 property=cn1 data=0x1.1.1.1 +phy set pre-emphasis portlist=0 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=0 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=4 lane-cnt=4 property=cn1 data=0x1.1.1.1 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=4 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=8 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=8 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=12 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=12 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=16 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=16 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=20 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=20 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=24 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=24 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=28 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=28 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=32 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=32 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=36 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=36 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=40 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=40 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=44 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c0 data=0x1c.1c.1c.1c +phy set pre-emphasis portlist=44 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=48 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=48 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=49 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=49 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=50 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=50 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=51 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis portlist=51 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=52 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=52 lane-cnt=4 property=c1 data=0x8.8.8.8 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis portlist=53 lane-cnt=4 property=cn1 data=0x1.1.1.1 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c0 data=0x1a.1a.1a.1a +phy set pre-emphasis portlist=53 lane-cnt=4 property=c1 data=0x7.7.7.7 +phy set mdio portlist=0 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=1 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=2 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=3 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=4 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=5 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=6 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=7 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=8 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=9 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=10 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=11 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=12 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=13 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=14 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=15 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=16 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=17 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=18 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=19 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=20 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=21 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=22 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=23 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=24 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=25 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=26 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=27 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=28 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=29 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=30 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=31 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=32 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=33 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=34 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=35 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=36 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=37 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=38 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=39 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=40 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=41 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=42 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=43 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=44 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=45 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=46 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=47 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=48 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=49 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=50 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=51 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=52 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=53 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=129 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=130 devad=0x1E addr=0x2 data=0x0000 +port set property portlist=0-47 speed=25g +port set property portlist=48-53 speed=100g +port set property portlist=129-130 speed=10g +port set property portlist=0-47 medium-type=sr +port set property portlist=48-53 medium-type=sr4 +port set property portlist=129-130 medium-type=kr +port set adver portlist=129-130 speed-10g-kr +port set property portlist=129-130 an=enable +port set property unit=0 portlist=129-130 admin=enable +port set property unit=0 portlist=0-53 admin=disable + diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/proc_init.nps b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/proc_init.nps new file mode 100644 index 000000000000..e25c78018adb --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/proc_init.nps @@ -0,0 +1,10 @@ +#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 5 +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 +0 NPS_CFG_TYPE_HASH_L2_FDB_REGION_ENTRY_NUM 0 0 49152 +0 NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM 0 0 32768 + diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/qos.json.j2 b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/qos.json.j2 new file mode 100644 index 000000000000..5c5fc6e4969b --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/qos.json.j2 @@ -0,0 +1,136 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"1", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + }, + "WRED_PROFILE": { + "AZURE_LOSSY" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"613984", + "red_min_threshold":"76608", + "yellow_max_threshold":"628320", + "yellow_min_threshold":"78400", + "green_max_threshold": "642656", + "green_min_threshold": "80192" + }, + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"613984", + "red_min_threshold":"76608", + "yellow_max_threshold":"628320", + "yellow_min_threshold":"78400", + "green_max_threshold": "642656", + "green_min_threshold": "80192" + } + }, + "QUEUE": { + } +} diff --git a/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/sai.profile b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/sai.profile new file mode 100644 index 000000000000..5e4ff9064d5b --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/Accton-AS7116-54X-R0/sai.profile @@ -0,0 +1,2 @@ +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/accton/x86_64-accton_as7116_54x-r0/default_sku b/device/accton/x86_64-accton_as7116_54x-r0/default_sku new file mode 100644 index 000000000000..146edca52638 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7116-54X-R0 t1 diff --git a/device/accton/x86_64-accton_as7116_54x-r0/fancontrol b/device/accton/x86_64-accton_as7116_54x-r0/fancontrol new file mode 100644 index 000000000000..e16d8f936f85 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=/sys/bus/i2c/devices/20-004a/hwmon/hwmon*/temp1_input /sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=/sys/bus/i2c/devices/19-0049/hwmon/hwmon*/temp1_input /sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=/sys/bus/i2c/devices/17-004b/hwmon/hwmon*/temp1_input +FCFANS=/sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=/sys/bus/i2c/devices/1-0063/fan1_input /sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=/sys/bus/i2c/devices/1-0063/fan2_input +/sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=/sys/bus/i2c/devices/1-0063/fan3_input /sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=/sys/bus/i2c/devices/1-0063/fan4_input /sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=/sys/bus/i2c/devices/1-0063/fan5_input +MINTEMP=/sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=49 +MAXTEMP=/sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=58 +MINSTART=/sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=100 +MINSTOP=/sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=40 +MINPWM=/sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=40 +MAXPWM=/sys/bus/i2c/devices/1-0063/fan_duty_cycle_percentage=100 diff --git a/device/accton/x86_64-accton_as7116_54x-r0/installer.conf b/device/accton/x86_64-accton_as7116_54x-r0/installer.conf new file mode 100644 index 000000000000..4eeedca86a48 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pci=noaer" \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7116_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7116_54x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..4241483d68eb --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7116_54x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7116_54x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..40e7257a6f02 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/plugins/psuutil.py @@ -0,0 +1,91 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/10-0050", + "/sys/bus/i2c/devices/11-0053"] + + 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 ", attr_path, " file !") + + 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/accton/x86_64-accton_as7116_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7116_54x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..9f678757f2a8 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/plugins/sfputil.py @@ -0,0 +1,171 @@ +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 0 + _port_end = 53 + _qsfp_port_start = 48 + _ports_in_block = 54 + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 0: 37, + 1: 38, + 2: 39, + 3: 40, + 4: 41, + 5: 42, + 6: 43, + 7: 44, + 8: 45, + 9: 46, + 10: 47, + 11: 48, + 12: 49, + 13: 50, + 14: 51, + 15: 52, + 16: 53, + 17: 54, + 18: 55, + 19: 56, + 20: 57, + 21: 58, + 22: 59, + 23: 60, + 24: 61, + 25: 62, + 26: 63, + 27: 64, + 28: 65, + 29: 66, + 30: 67, + 31: 68, + 32: 69, + 33: 70, + 34: 71, + 35: 72, + 36: 73, + 37: 74, + 38: 75, + 39: 76, + 40: 77, + 41: 78, + 42: 79, + 43: 80, + 44: 81, + 45: 82, + 46: 83, + 47: 84, + 48: 21, + 49: 22, + 50: 23, + 51: 24, + 52: 25, + 53: 26, + } + + _qsfp_ports = list(range(_qsfp_port_start, _ports_in_block + 1)) + + _present_status = dict() + + 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._present_status[x] = SFP_STATUS_REMOVED + + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self._qsfp_port_start or port_num > self._port_end: + print("Error: port %d is not qsfp port" % port_num) + 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): + 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" + port_ps = path.format(self._port_to_i2c_mapping[port_num]) + + reg_value = '0' + try: + reg_file = open(port_ps) + reg_value = reg_file.readline().rstrip() + reg_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if reg_value == '1': + return True + + return False + + def get_transceiver_change_event(self, timeout=0): + raise NotImplementedError + + @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 + + def get_transceiver_change_event(self, timeout=0): + ret_present = dict() + for phy_port in range(self._port_start, self._port_end + 1): + last_present_status = SFP_STATUS_INSERTED if self.get_presence(phy_port) else SFP_STATUS_REMOVED + if self._present_status[phy_port] != last_present_status: + ret_present[phy_port] = last_present_status + self._present_status[phy_port] = last_present_status + + time.sleep(2) + + return True, ret_present diff --git a/device/accton/x86_64-accton_as7116_54x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7116_54x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7116_54x-r0/sensors.conf b/device/accton/x86_64-accton_as7116_54x-r0/sensors.conf new file mode 100644 index 000000000000..9edb51a9e72d --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/sensors.conf @@ -0,0 +1,13 @@ +# libsensors configuration file + +chip "as7116_54x_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/accton/x86_64-accton_as7116_54x-r0/sonic_platform/__init__.py b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..d82f3749319c --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * diff --git a/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/chassis.py b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/chassis.py new file mode 100644 index 000000000000..86ae121c6c82 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/chassis.py @@ -0,0 +1,172 @@ +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# +try: + import sys + import re + import os + import subprocess + import json + import syslog + from sonic_platform_base.chassis_base import ChassisBase + from sonic_py_common.logger import Logger + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu + from sonic_platform.component import Component + from sonic_platform.thermal import Thermal + from sonic_platform.sfp import Sfp + from sonic_platform.eeprom import Tlv +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 5 +NUM_FAN = 2 +NUM_PSU = 2 +NUM_THERMAL = 4 +NUM_SFP = 54 +SFP_PORT_START = 0 +QSFP_PORT_START = 48 +SFP_PORT_END = 47 +QSFP_PORT_END = 53 +HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/" +PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/" +REBOOT_CAUSE_FILE = "reboot-cause.txt" +PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt" +COMPONENT_NAME_LIST = ["BIOS"] +HOST_CHK_CMD = "docker > /dev/null 2>&1" + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + def __init__(self): + super(Chassis, self).__init__() + + for fantray_index in range(0, NUM_FAN_TRAY): + for fan_index in range(0, NUM_FAN): + fan = Fan(fantray_index, fan_index) + self._fan_list.append(fan) + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + self.PORT_START = SFP_PORT_START + self.QSFP_PORT_START = QSFP_PORT_START + self.PORT_END = QSFP_PORT_END + for index in range(0, NUM_SFP): + if index in range(self.QSFP_PORT_START, self.QSPORT_END + 1): + sfp_module = Sfp(index, 'QSFP') + else: + sfp_module = Sfp(index, 'SFP') + self._sfp_list.append(sfp_module) + self._component_name_list = COMPONENT_NAME_LIST + self._watchdog = Watchdog() + self._eeprom = Tlv() + logger.log_info("Chassis loaded successfully") + + 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 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(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_firmware_version(self, component_name): + """ + Retrieves platform-specific hardware/firmware versions for chassis + componenets such as BIOS, CPLD, FPGA, etc. + Args: + type: A string, component name + + Returns: + A string containing platform-specific component versions + """ + self.component = Component(component_name) + if component_name not in self._component_name_list: + return None + return self.component.get_firmware_version() + + def install_component_firmware(self, component_name, image_path): + """ + Install firmware to module + Args: + type: A string, component name. + image_path: A string, path to firmware image. + + Returns: + A boolean, True if install successfully, False if not + """ + self.component = Component(component_name) + if component_name not in self._component_name_list: + return False + return self.component.upgrade_firmware(image_path) + + 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. + """ + description = 'None' + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + + reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) if self.__is_host( + ) else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE + prev_reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.__is_host( + ) else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE + sw_reboot_cause = self.__read_txt_file( + reboot_cause_path) or "Unknown" + prev_sw_reboot_cause = self.__read_txt_file( + prev_reboot_cause_path) or "Unknown" + + if sw_reboot_cause != "Unknown": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = sw_reboot_cause + else: + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + description = 'Unknown reason' + + return (reboot_cause, description) diff --git a/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/component.py b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/component.py new file mode 100644 index 000000000000..15d8e9e15e9d --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/component.py @@ -0,0 +1,82 @@ +############################################################################# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +############################################################################# + +import json +import os.path +import shutil +import shlex +import subprocess + +try: + from sonic_platform_base.device_base import DeviceBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" + + +class Component(DeviceBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_name): + DeviceBase.__init__(self) + self.name = component_name.upper() + + def __run_command(self, command): + # Run bash command and print output to stdout + try: + process = subprocess.Popen( + shlex.split(command), universal_newlines=True, stdout=subprocess.PIPE) + while True: + output = process.stdout.readline() + if output == '' and process.poll() is not None: + break + rc = process.poll() + if rc != 0: + return False + except: + return False + return True + + def __get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + fw_version = None + + if self.name == "BIOS": + fw_version = self.__get_bios_version() + + return fw_version + + def upgrade_firmware(self, image_path): + """ + Install firmware to module + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install successfully, False if not + """ + if not os.path.isfile(image_path): + return False + + if self.name == "BIOS": + print("Not supported") + return False + + return self.__run_command(install_command) diff --git a/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/eeprom.py b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/eeprom.py new file mode 100644 index 000000000000..9cdd09106331 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/eeprom.py @@ -0,0 +1,114 @@ +############################################################################# +# 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 re + from array import array + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + + +class Tlv(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + 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() + err = self.read_eeprom_db() + if err: + # Failed to read EEPROM information from database. Read from cache file + pass + else: + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + return self.__parse_output(decode_output) + + status = self.check_status() + if status < 'ok': + 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/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/fan.py b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/fan.py new file mode 100644 index 000000000000..421e7727ceeb --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/fan.py @@ -0,0 +1,164 @@ +############################################################################# +# +# 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 +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_PATH = "/sys/bus/i2c/devices/1-0063/" +FANTRAY_NAME_LIST = ["FANTRAY-1", "FANTRAY-2", + "FANTRAY-3", "FANTRAY-4", "FANTRAY-5"] +FAN_NAME_LIST = ["front", "rear"] + + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0): + self.fan_index = fan_index + self.fan_tray_index = fan_tray_index + self.fan_presence = "fan{}_present" + self.fan_direction = "fan{}_direction" + self.fan_fault = "fan{}_{}_fault" + self.fan_speed_rpm = "fan{}_{}_speed_rpm" + FanBase.__init__(self) + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except: + return False + return True + + def __search_file_by_name(self, directory, file_name): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name in file_name: + return file_path + return None + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + direction = self.FAN_DIRECTION_EXHAUST + fan_direction_file = (FAN_PATH + + self.fan_direction.format(self.fan_tray_index+1)) + raw = self.__read_txt_file(fan_direction_file).strip('\r\n') + direction = self.FAN_DIRECTION_INTAKE if str( + raw).upper() == "1" else self.FAN_DIRECTION_EXHAUST + + return direction + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 12000 (full speed) + """ + speed = 0 + if self.get_presence(): + fan_speed_file = (FAN_PATH + + self.fan_speed_rpm.format(self.fan_tray_index+1, FAN_NAME_LIST[self.fan_index])) + speed = self.__read_txt_file(fan_speed_file).strip('\r\n') + + return int(speed) + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + target = 0 + if self.get_presence(): + fan_speed_file = (FAN_PATH + + self.fan_speed_rpm.format(self.fan_tray_index+1, FAN_NAME_LIST[self.fan_index])) + target = self.__read_txt_file(fan_speed_file).strip('\r\n') + + 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 10 + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + + Note: + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + return False + + 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 + """ + return False + + 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] + + return fan_name + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + fan_direction_file = (FAN_PATH + + self.fan_presence.format(self.fan_tray_index+1)) + present_str = self.__read_txt_file(fan_direction_file) or '1' + + return int(present_str) == 0 diff --git a/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/platform.py b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/platform.py new file mode 100644 index 000000000000..6e1a90132acc --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/platform.py @@ -0,0 +1,19 @@ +############################################################################# +# 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/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/psu.py b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/psu.py new file mode 100644 index 000000000000..f53b7506bb3e --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/psu.py @@ -0,0 +1,100 @@ +############################################################################# +# psuutil.py +# Platform-specific PSU status interface for SONiC +############################################################################# + +import os.path +import sonic_platform + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_MAX_RPM = 9600 +PSU_NAME_LIST = ["PSU-0", "PSU-1"] + + +class Psu(PsuBase): + """Platform-specific Psu class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/10-0050", + "/sys/bus/i2c/devices/11-0053"] + + def __init__(self): + self.index = psu_index + PsuBase.__init__(self) + + def get_fan(self): + """ + Retrieves object representing the fan module contained in this PSU + Returns: + An object dervied from FanBase representing the fan module + contained in this PSU + """ + # Hardware not supported + return False + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + return self.get_status() + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the PSU status LED + Note: Only support green and off + Returns: + bool: True if status LED state is set successfully, False if not + """ + # Hardware not supported + return False + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return PSU_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + attr_file = 'psu_present' + attr_path = self.SYSFS_PSU_DIR[self.index-1] + '/' + attr_file + status = 0 + try: + with open(attr_path, 'r') as psu_prs: + status = int(psu_prs.read()) + except IOError: + return False + + return status == 1 + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + attr_file = 'psu_power_good' + attr_path = self.SYSFS_PSU_DIR[self.index-1] + '/' + attr_file + status = 0 + try: + with open(attr_path, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 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 new file mode 100644 index 000000000000..2006561ffef0 --- /dev/null +++ b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/sfp.py @@ -0,0 +1,1130 @@ +############################################################################# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +############################################################################# +try: + import os + import time + import subprocess + import syslog + from ctypes import create_string_buffer + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sffbase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +INFO_OFFSET = 0 +DOM_OFFSET = 256 + +QSFP_INFO_OFFSET = 128 +QSFP_DOM_OFFSET = 0 + +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + +# Offset for values in SFP eeprom +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 40 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 1 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNEL_THRESHOLD_OFFSET = 176 +QSFP_CHANNEL_THRESHOLD_WIDTH = 16 + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + + # Port number + PORT_START = 0 + PORT_END = 53 + + port_to_i2c_mapping = { + 0: 37, + 1: 38, + 2: 39, + 3: 40, + 4: 41, + 5: 42, + 6: 43, + 7: 44, + 8: 45, + 9: 46, + 10: 47, + 11: 48, + 12: 49, + 13: 50, + 14: 51, + 15: 52, + 16: 53, + 17: 54, + 18: 55, + 19: 56, + 20: 57, + 21: 58, + 22: 59, + 23: 60, + 24: 61, + 25: 62, + 26: 63, + 27: 64, + 28: 65, + 29: 66, + 30: 67, + 31: 68, + 32: 69, + 33: 70, + 34: 71, + 35: 72, + 36: 73, + 37: 74, + 38: 75, + 39: 76, + 40: 77, + 41: 78, + 42: 79, + 43: 80, + 44: 81, + 45: 82, + 46: 83, + 47: 84, + 48: 21, + 49: 22, + 50: 23, + 51: 24, + 52: 25, + 53: 26, + } + _sfp_port = list(range(48, PORT_END + 1)) + RESET_PATH = "/sys/bus/i2c/devices/{}-0050/sfp_port_reset" + PRS_PATH = "/sys/bus/i2c/devices/{}-0050/sfp_is_present" + + PLATFORM_ROOT_PATH = '/usr/share/sonic/device' + PMON_HWSKU_PATH = '/usr/share/sonic/hwsku' + HOST_CHK_CMD = "docker > /dev/null 2>&1" + + PLATFORM = "x86_64-accton_as7116_54x-r0" + HWSKU = "Accton-AS7116-54X-R0" + + def __init__(self, sfp_index, sfp_type): + # Init index + self.index = sfp_index + self.port_num = self.index + 1 + self.sfp_type = sfp_type + + # Init eeprom path + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom' + self.port_to_eeprom_mapping = {} + for x in range(self.PORT_START, self.PORT_END + 1): + p_num = x - 1 if self.PORT_START == 1 else x + self.port_to_eeprom_mapping[p_num] = eeprom_path.format( + self.port_to_i2c_mapping[p_num]) + + self.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + SfpBase.__init__(self) + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) + hwsku_path = "/".join([platform_path, self.HWSKU] + ) if self.__is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.sfp_index] + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + """ + if self.sfp_type == "SFP": + get_sfp_transceiver_info + else: + get_qsfp_transceiver_info + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + """ + if self.sfp_type == "SFP": + get_sfp_transceiver_bulk_status + else: + get_qsfp_transceiver_bulk_status + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + """ + if self.sfp_type == "SFP": + get_sfp_transceiver_threshold_info + else: + get_qsfp_transceiver_threshold_info + + def get_sfp_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + # check present status + sfpi_obj = sff8472InterfaceId() + if not self.get_presence() or not sfpi_obj: + return {} + + offset = INFO_OFFSET + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_SFP) + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( + sfp_interface_bulk_raw, 0) + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_vendor_name_raw, 0) + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_vendor_pn_raw, 0) + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_SFP) + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_vendor_rev_raw, 0) + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_vendor_sn_raw, 0) + + sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_vendor_oui_raw, 0) + + sfp_vendor_date_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_vendor_date_raw, 0) + + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + compliance_code_dict = dict() + + if sfp_interface_bulk_data: + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data[ + 'data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' + transceiver_info_dict['cable_type'] = "Unknown" + transceiver_info_dict['cable_length'] = "Unknown" + + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_sfp_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + # check present status + sfpd_obj = sff8472Dom() + if not self.get_presence() or not sfpd_obj: + return {} + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = DOM_OFFSET + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_voltage_data = sfpd_obj.parse_channel_monitor_params( + dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_voltage_data['data']['TXPower']['value'] + transceiver_dom_info_dict['rx1power'] = dom_voltage_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_voltage_data['data']['TXBias']['value'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num( + transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_sfp_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + # check present status + sfpd_obj = sff8472Dom() + + if not self.get_presence() and not sfpd_obj: + return {} + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = DOM_OFFSET + transceiver_dom_threshold_info_dict = dict.fromkeys( + self.threshold_dict_keys, 'N/A') + dom_module_threshold_raw = self.__read_eeprom_specific_bytes( + (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) + + 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'] + + for key in transceiver_dom_threshold_info_dict: + transceiver_dom_threshold_info_dict[key] = self._convert_string_to_num( + transceiver_dom_threshold_info_dict[key]) + + return transceiver_dom_threshold_info_dict + + def get_qsfp_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + # check present status + sfpi_obj = sff8436InterfaceId() + if not self.get_presence() or not sfpi_obj: + return {} + + offset = INFO_OFFSET + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_QSFP) + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( + sfp_interface_bulk_raw, 0) + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_vendor_name_raw, 0) + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_vendor_pn_raw, 0) + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_QSFP) + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_vendor_rev_raw, 0) + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_vendor_sn_raw, 0) + + sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_vendor_oui_raw, 0) + + sfp_vendor_date_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_vendor_date_raw, 0) + + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + compliance_code_dict = dict() + + if sfp_interface_bulk_data: + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data[ + 'data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' + transceiver_info_dict['cable_type'] = "Unknown" + transceiver_info_dict['cable_length'] = "Unknown" + + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + + return transceiver_info_dict + + def get_qsfp_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + # check present status + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + + if not self.get_presence() or not sfpi_obj or not sfpd_obj: + return {} + + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + offset = DOM_OFFSET + offset_xcvr = INFO_OFFSET + + # 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( + (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_dom_capability( + qsfp_dom_capability_raw, 0) + else: + return None + + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes( + (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) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['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 = {} + dom_channel_monitor_raw = None + 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( + (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: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (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) + 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'] + + if dom_channel_monitor_raw: + 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'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num( + transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_qsfp_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + # check present status + sfpd_obj = sff8436Dom() + + if not self.get_presence() or not sfpd_obj: + return {} + + transceiver_dom_threshold_dict = dict.fromkeys( + self.threshold_dict_keys, 'N/A') + dom_thres_raw = self.__read_eeprom_specific_bytes( + QSFP_MODULE_THRESHOLD_OFFSET, QSFP_MODULE_THRESHOLD_WIDTH) if self.get_presence() and sfpd_obj else None + + if dom_thres_raw: + module_threshold_values = sfpd_obj.parse_module_threshold_values( + dom_thres_raw, 0) + module_threshold_data = module_threshold_values.get('data') + if module_threshold_data: + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value'] + + dom_thres_raw = self.__read_eeprom_specific_bytes( + QSFP_CHANNEL_THRESHOLD_OFFSET, QSFP_CHANNEL_THRESHOLD_WIDTH) if self.get_presence() and sfpd_obj else None + channel_threshold_values = sfpd_obj.parse_channel_threshold_values( + dom_thres_raw, 0) + channel_threshold_data = channel_threshold_values.get('data') + if channel_threshold_data: + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerhighwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value'] + + for key in transceiver_dom_threshold_dict: + transceiver_dom_threshold_dict[key] = self._convert_string_to_num( + transceiver_dom_threshold_dict[key]) + + return transceiver_dom_threshold_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + rx_los = False + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + rx_los = (sffbase().test_bit(data, 1) != 0) + + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + tx_fault = False + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + tx_fault = (sffbase().test_bit(data, 2) != 0) + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + tx_disable = False + tx_fault = False + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + tx_disable_hard = (sffbase().test_bit( + data, SFP_TX_DISABLE_HARD_BIT) != 0) + tx_disable_soft = (sffbase().test_bit( + data, SFP_TX_DISABLE_SOFT_BIT) != 0) + tx_disable = tx_disable_hard | tx_disable_soft + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + # SFP doesn't support this feature + return 0 + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("temperature", "N/A") + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + Returns: + An integer number of supply voltage in mV + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("voltage", "N/A") + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A") + return [tx1_bs, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A") + return [rx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A") + return [tx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + # SFP doesn't support this feature + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.index] + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw is not None: + # Set bit 6 for Soft TX Disable Select + # 01000000 = 64 and 10111111 = 191 + tx_disable_bit = 64 if tx_disable else 191 + status_control = int(status_control_raw[0], 16) + tx_disable_ctl = (status_control | tx_disable_bit) if tx_disable else ( + status_control & tx_disable_bit) + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="r+b", buffering=0) + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom.seek(SFP_STATUS_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except: + #print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + Returns: + A boolean, True if successful, False if not + """ + # SFP doesn't support this feature + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + # SFP doesn't support this feature + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + # SFP doesn't support this feature + return False + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the SFP + Returns: + bool: True if SFP is present, False if not + """ + presence = False + + try: + with open(self.PRS_PATH.format(self.index), 'r') as sfp_presence: + 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))) + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("model", "N/A") + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("serial", "N/A") diff --git a/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/port_config.ini b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/port_config.ini new file mode 100755 index 000000000000..74865956f61b --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/port_config.ini @@ -0,0 +1,55 @@ +# name lanes +Ethernet0 0 +Ethernet1 1 +Ethernet2 2 +Ethernet3 3 +Ethernet4 4 +Ethernet5 5 +Ethernet6 6 +Ethernet7 7 +Ethernet8 8 +Ethernet9 9 +Ethernet10 10 +Ethernet11 11 +Ethernet12 12 +Ethernet13 13 +Ethernet14 14 +Ethernet15 15 +Ethernet16 16 +Ethernet17 17 +Ethernet18 18 +Ethernet19 19 +Ethernet20 20 +Ethernet21 21 +Ethernet22 22 +Ethernet23 23 +Ethernet24 24 +Ethernet25 25 +Ethernet26 26 +Ethernet27 27 +Ethernet28 28 +Ethernet29 29 +Ethernet30 30 +Ethernet31 31 +Ethernet32 32 +Ethernet33 33 +Ethernet34 34 +Ethernet35 35 +Ethernet36 36 +Ethernet37 37 +Ethernet38 38 +Ethernet39 39 +Ethernet40 40 +Ethernet41 41 +Ethernet42 42 +Ethernet43 43 +Ethernet44 44 +Ethernet45 45 +Ethernet46 46 +Ethernet47 47 +Ethernet48 48 +Ethernet49 49 +Ethernet50 50 +Ethernet51 51 +Ethernet52 52 +Ethernet53 53 diff --git a/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/qos.json.j2 b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/qos.json.j2 new file mode 100755 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/sai.profile b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/sai.profile new file mode 100755 index 000000000000..178dcd002853 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/AS7212-54x/sai.profile @@ -0,0 +1,2 @@ +mode=1 +hwId=as7212-54x diff --git a/device/accton/x86_64-accton_as7212_54x-r0/default_sku b/device/accton/x86_64-accton_as7212_54x-r0/default_sku new file mode 100644 index 000000000000..d8a1bd55cd48 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/default_sku @@ -0,0 +1 @@ +AS7212-54x t1 diff --git a/device/accton/x86_64-accton_as7212_54x-r0/installer.conf b/device/accton/x86_64-accton_as7212_54x-r0/installer.conf new file mode 100755 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as7212_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7212_54x-r0/plugins/eeprom.py new file mode 100755 index 000000000000..951384d5e37d --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7212_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7212_54x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..47e1f9350aff --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/plugins/sfputil.py @@ -0,0 +1,134 @@ +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class sfputil(SfpUtilBase): + """Platform specific sfputil class""" + + port_start = 0 + port_end = 31 + ports_in_block = 32 + + port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 9: 18, + 10: 19, + 11: 20, + 12: 21, + 1: 22, + 2: 23, + 3: 24, + 4: 25, + 6: 26, + 5: 27, + 8: 28, + 7: 29, + 13: 30, + 14: 31, + 15: 32, + 16: 33, + 17: 34, + 18: 35, + 19: 36, + 20: 37, + 25: 38, + 26: 39, + 27: 40, + 28: 41, + 29: 42, + 30: 43, + 31: 44, + 32: 45, + 21: 46, + 22: 47, + 23: 48, + 24: 49, + } + + _qsfp_ports = list(range(0, ports_in_block + 1)) + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + 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+1]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + 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+1]) + + 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): + raise NotImplementedErro + + def get_low_power_mode(self, port_num): + raise NotImplementedErro + + 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+1]) + + reg_value = '0' + try: + reg_file = open(port_ps) + reg_value = reg_file.readline().rstrip() + reg_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return list(range(0, self.ports_in_block + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + 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 diff --git a/device/accton/x86_64-accton_as7212_54x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7212_54x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7212_54x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/port_config.ini b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/port_config.ini new file mode 100644 index 000000000000..93160688d748 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index speed +Ethernet0 41 twentyfiveGigE1 1 25000 +Ethernet1 42 twentyfiveGigE2 2 25000 +Ethernet2 43 twentyfiveGigE3 3 25000 +Ethernet3 44 twentyfiveGigE4 4 25000 +Ethernet4 49 twentyfiveGigE5 5 25000 +Ethernet5 50 twentyfiveGigE6 6 25000 +Ethernet6 51 twentyfiveGigE7 7 25000 +Ethernet7 52 twentyfiveGigE8 8 25000 +Ethernet8 53 twentyfiveGigE9 9 25000 +Ethernet9 54 twentyfiveGigE10 10 25000 +Ethernet10 55 twentyfiveGigE11 11 25000 +Ethernet11 56 twentyfiveGigE12 12 25000 +Ethernet12 65 twentyfiveGigE13 13 25000 +Ethernet13 66 twentyfiveGigE14 14 25000 +Ethernet14 67 twentyfiveGigE15 15 25000 +Ethernet15 68 twentyfiveGigE16 16 25000 +Ethernet16 33 twentyfiveGigE17 17 25000 +Ethernet17 34 twentyfiveGigE18 18 25000 +Ethernet18 35 twentyfiveGigE19 19 25000 +Ethernet19 36 twentyfiveGigE20 20 25000 +Ethernet20 37 twentyfiveGigE21 21 25000 +Ethernet21 38 twentyfiveGigE22 22 25000 +Ethernet22 39 twentyfiveGigE23 23 25000 +Ethernet23 40 twentyfiveGigE24 24 25000 +Ethernet24 69 twentyfiveGigE25 25 25000 +Ethernet25 70 twentyfiveGigE26 26 25000 +Ethernet26 71 twentyfiveGigE27 27 25000 +Ethernet27 72 twentyfiveGigE28 28 25000 +Ethernet28 81 twentyfiveGigE29 29 25000 +Ethernet29 82 twentyfiveGigE30 30 25000 +Ethernet30 83 twentyfiveGigE31 31 25000 +Ethernet31 84 twentyfiveGigE32 32 25000 +Ethernet32 85 twentyfiveGigE33 33 25000 +Ethernet33 86 twentyfiveGigE34 34 25000 +Ethernet34 87 twentyfiveGigE35 35 25000 +Ethernet35 88 twentyfiveGigE36 36 25000 +Ethernet36 97 twentyfiveGigE37 37 25000 +Ethernet37 98 twentyfiveGigE38 38 25000 +Ethernet38 99 twentyfiveGigE39 39 25000 +Ethernet39 100 twentyfiveGigE40 40 25000 +Ethernet40 101 twentyfiveGigE41 41 25000 +Ethernet41 102 twentyfiveGigE42 42 25000 +Ethernet42 103 twentyfiveGigE43 43 25000 +Ethernet43 104 twentyfiveGigE44 44 25000 +Ethernet44 105 twentyfiveGigE45 45 25000 +Ethernet45 106 twentyfiveGigE46 46 25000 +Ethernet46 107 twentyfiveGigE47 47 25000 +Ethernet47 108 twentyfiveGigE48 48 25000 +Ethernet48 5,6,7,8 hundredGigE49 49 100000 +Ethernet52 1,2,3,4 hundredGigE50 50 100000 +Ethernet56 109,110,111,112 hundredGigE51 51 100000 +Ethernet60 21,22,23,24 hundredGigE52 52 100000 +Ethernet64 9,10,11,12 hundredGigE53 53 100000 +Ethernet68 117,118,119,120 hundredGigE54 54 100000 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/sai.profile b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/sai.profile new file mode 100644 index 000000000000..54cdc34801dd --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-as7312-48x25G+6x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/th-as7312-48x25G+6x100G.config.bcm b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/th-as7312-48x25G+6x100G.config.bcm new file mode 100644 index 000000000000..0ac6051b1ad4 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/Accton-AS7312-54X/th-as7312-48x25G+6x100G.config.bcm @@ -0,0 +1,519 @@ +# accton_as7312_54x 48x25G+6x100G SDK config +os=unix +schan_intr_enable=0 + +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x0407ffc00ff00ff003fc3ffc00200222 +pbmp_xport_xe=0x0407ffd00ff00ff403fc3ffc00200222 + +## FC10 ## +dport_map_port_42=1 +dport_map_port_43=2 +dport_map_port_44=3 +dport_map_port_45=4 + +## FC12 ## +dport_map_port_50=5 +dport_map_port_51=6 +dport_map_port_52=7 +dport_map_port_53=8 + +## FC13 ## +dport_map_port_54=9 +dport_map_port_55=10 +dport_map_port_56=11 +dport_map_port_57=12 + +## FC16 ## +dport_map_port_68=13 +dport_map_port_69=14 +dport_map_port_70=15 +dport_map_port_71=16 + +## FC8 ## +dport_map_port_34=17 +dport_map_port_35=18 +dport_map_port_36=19 +dport_map_port_37=20 + +## FC9 ## +dport_map_port_38=21 +dport_map_port_39=22 +dport_map_port_40=23 +dport_map_port_41=24 + +## FC17 ## +dport_map_port_72=25 +dport_map_port_73=26 +dport_map_port_74=27 +dport_map_port_75=28 + +## FC20 ## +dport_map_port_84=29 +dport_map_port_85=30 +dport_map_port_86=31 +dport_map_port_87=32 + +## FC21 ## +dport_map_port_88=33 +dport_map_port_89=34 +dport_map_port_90=35 +dport_map_port_91=36 + +## FC24 ## +dport_map_port_102=37 +dport_map_port_103=38 +dport_map_port_104=39 +dport_map_port_105=40 + +## FC25 ## +dport_map_port_106=41 +dport_map_port_107=42 +dport_map_port_108=43 +dport_map_port_109=44 + +## FC26 ## +dport_map_port_110=45 +dport_map_port_111=46 +dport_map_port_112=47 +dport_map_port_113=48 + +## FC1 ## +dport_map_port_5=49 + +## FC0 ## +dport_map_port_1=50 + +## FC27 ## +dport_map_port_114=51 + +## FC5 ## +dport_map_port_21=52 + +## FC2 ## +dport_map_port_9=53 + +## FC29 ## +dport_map_port_122=54 + +#for KR +#dport_map_port_66=55 +#dport_map_port_100=56 + +#/* Port Map */ +## FC10 ## +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 + +## FC12 ## +portmap_50=49:25 +portmap_51=50:25 +portmap_52=51:25 +portmap_53=52:25 + + +## FC13 ## +portmap_54=53:25 +portmap_55=54:25 +portmap_56=55:25 +portmap_57=56:25 + +## FC16 ## +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 + + +## FC8 ## +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 + +## FC9 ## +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 + +## FC17 ## +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 + +## FC20 ## +portmap_84=81:25 +portmap_85=82:25 +portmap_86=83:25 +portmap_87=84:25 + + +## FC21 ## +portmap_88=85:25 +portmap_89=86:25 +portmap_90=87:25 +portmap_91=88:25 + +## FC24 ## +portmap_102=97:25 +portmap_103=98:25 +portmap_104=99:25 +portmap_105=100:25 + +## FC25 ## +portmap_106=101:25 +portmap_107=102:25 +portmap_108=103:25 +portmap_109=104:25 + +## FC26 ## +portmap_110=105:25 +portmap_111=106:25 +portmap_112=107:25 +portmap_113=108:25 + +## FC1 ## +portmap_5=5:100 + +## FC0 ## +portmap_1=1:100 + +## FC27 ## +portmap_114=109:100 + +## FC5 ## +portmap_21=21:100 + +## FC2 ## +portmap_9=9:100 + +## FC29 ## +portmap_122=117:100 + +# CPU to MAC +# TSC-E management port 1 +#portmap_66=129:10 +# TSC-E management port 2 +#portmap_100=131:10 + +xgxs_rx_lane_map_42=0x2310 +xgxs_rx_lane_map_43=0x2310 +xgxs_rx_lane_map_44=0x2310 +xgxs_rx_lane_map_45=0x2310 +xgxs_rx_lane_map_50=0x3210 +xgxs_rx_lane_map_51=0x3210 +xgxs_rx_lane_map_52=0x3210 +xgxs_rx_lane_map_53=0x3210 +xgxs_rx_lane_map_54=0x3210 +xgxs_rx_lane_map_55=0x3210 +xgxs_rx_lane_map_56=0x3210 +xgxs_rx_lane_map_57=0x3210 +xgxs_rx_lane_map_68=0x0123 +xgxs_rx_lane_map_69=0x0123 +xgxs_rx_lane_map_70=0x0123 +xgxs_rx_lane_map_71=0x0123 +xgxs_rx_lane_map_34=0x0123 +xgxs_rx_lane_map_35=0x0123 +xgxs_rx_lane_map_36=0x0123 +xgxs_rx_lane_map_37=0x0123 +xgxs_rx_lane_map_38=0x0123 +xgxs_rx_lane_map_39=0x0123 +xgxs_rx_lane_map_40=0x0123 +xgxs_rx_lane_map_41=0x0123 +xgxs_rx_lane_map_72=0x3210 +xgxs_rx_lane_map_73=0x3210 +xgxs_rx_lane_map_74=0x3210 +xgxs_rx_lane_map_75=0x3210 +xgxs_rx_lane_map_84=0x1032 +xgxs_rx_lane_map_85=0x1032 +xgxs_rx_lane_map_86=0x1032 +xgxs_rx_lane_map_87=0x1032 +xgxs_rx_lane_map_88=0x2301 +xgxs_rx_lane_map_89=0x2301 +xgxs_rx_lane_map_90=0x2301 +xgxs_rx_lane_map_91=0x2301 +xgxs_rx_lane_map_102=0x0123 +xgxs_rx_lane_map_103=0x0123 +xgxs_rx_lane_map_104=0x0123 +xgxs_rx_lane_map_105=0x0123 +xgxs_rx_lane_map_106=0x3210 +xgxs_rx_lane_map_107=0x3210 +xgxs_rx_lane_map_108=0x3210 +xgxs_rx_lane_map_109=0x3210 +xgxs_rx_lane_map_110=0x1032 +xgxs_rx_lane_map_111=0x1032 +xgxs_rx_lane_map_112=0x1032 +xgxs_rx_lane_map_113=0x1032 +xgxs_rx_lane_map_5=0x3210 +xgxs_rx_lane_map_1=0x3210 +xgxs_rx_lane_map_114=0x0123 +xgxs_rx_lane_map_21=0x0213 +xgxs_rx_lane_map_9=0x3210 +xgxs_rx_lane_map_122=0x1230 + +xgxs_tx_lane_map_42=0x0132 +xgxs_tx_lane_map_43=0x0132 +xgxs_tx_lane_map_44=0x0132 +xgxs_tx_lane_map_45=0x0132 +xgxs_tx_lane_map_50=0x3210 +xgxs_tx_lane_map_51=0x3210 +xgxs_tx_lane_map_52=0x3210 +xgxs_tx_lane_map_53=0x3210 +xgxs_tx_lane_map_54=0x3210 +xgxs_tx_lane_map_55=0x3210 +xgxs_tx_lane_map_56=0x3210 +xgxs_tx_lane_map_57=0x3210 +xgxs_tx_lane_map_68=0x0123 +xgxs_tx_lane_map_69=0x0123 +xgxs_tx_lane_map_70=0x0123 +xgxs_tx_lane_map_71=0x0123 +xgxs_tx_lane_map_34=0x0123 +xgxs_tx_lane_map_35=0x0123 +xgxs_tx_lane_map_36=0x0123 +xgxs_tx_lane_map_37=0x0123 +xgxs_tx_lane_map_38=0x0123 +xgxs_tx_lane_map_39=0x0123 +xgxs_tx_lane_map_40=0x0123 +xgxs_tx_lane_map_41=0x0123 +xgxs_tx_lane_map_72=0x0123 +xgxs_tx_lane_map_73=0x0123 +xgxs_tx_lane_map_74=0x0123 +xgxs_tx_lane_map_75=0x0123 +xgxs_tx_lane_map_84=0x0123 +xgxs_tx_lane_map_85=0x0123 +xgxs_tx_lane_map_86=0x0123 +xgxs_tx_lane_map_87=0x0123 +xgxs_tx_lane_map_88=0x2301 +xgxs_tx_lane_map_89=0x2301 +xgxs_tx_lane_map_90=0x2301 +xgxs_tx_lane_map_91=0x2301 +xgxs_tx_lane_map_102=0x0123 +xgxs_tx_lane_map_103=0x0123 +xgxs_tx_lane_map_104=0x0123 +xgxs_tx_lane_map_105=0x0123 +xgxs_tx_lane_map_106=0x3210 +xgxs_tx_lane_map_107=0x3210 +xgxs_tx_lane_map_108=0x3210 +xgxs_tx_lane_map_109=0x3210 +xgxs_tx_lane_map_110=0x1032 +xgxs_tx_lane_map_111=0x1032 +xgxs_tx_lane_map_112=0x1032 +xgxs_tx_lane_map_113=0x1032 +xgxs_tx_lane_map_5=0x3210 +xgxs_tx_lane_map_1=0x3210 +xgxs_tx_lane_map_114=0x0123 +xgxs_tx_lane_map_21=0x3210 +xgxs_tx_lane_map_9=0x3210 +xgxs_tx_lane_map_122=0x3210 + +#Polarity RX +phy_xaui_rx_polarity_flip_34=0x1 +phy_xaui_rx_polarity_flip_35=0x1 +phy_xaui_rx_polarity_flip_36=0x1 +phy_xaui_rx_polarity_flip_37=0x1 +phy_xaui_rx_polarity_flip_38=0x1 +phy_xaui_rx_polarity_flip_39=0x1 +phy_xaui_rx_polarity_flip_40=0x1 +phy_xaui_rx_polarity_flip_41=0x1 +phy_xaui_rx_polarity_flip_84=0x1 +phy_xaui_rx_polarity_flip_85=0x0 +phy_xaui_rx_polarity_flip_86=0x1 +phy_xaui_rx_polarity_flip_87=0x0 +phy_xaui_rx_polarity_flip_88=0x1 +phy_xaui_rx_polarity_flip_89=0x0 +phy_xaui_rx_polarity_flip_90=0x1 +phy_xaui_rx_polarity_flip_91=0x1 +phy_xaui_rx_polarity_flip_102=0x0 +phy_xaui_rx_polarity_flip_103=0x0 +phy_xaui_rx_polarity_flip_104=0x1 +phy_xaui_rx_polarity_flip_105=0x0 +phy_xaui_rx_polarity_flip_122=0xf +#Polarity TX +phy_xaui_tx_polarity_flip_42=0x1 +phy_xaui_tx_polarity_flip_43=0x1 +phy_xaui_tx_polarity_flip_44=0x1 +phy_xaui_tx_polarity_flip_45=0x1 +phy_xaui_tx_polarity_flip_34=0x1 +phy_xaui_tx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_36=0x1 +phy_xaui_tx_polarity_flip_37=0x1 +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_tx_polarity_flip_39=0x1 +phy_xaui_tx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0x1 +phy_xaui_tx_polarity_flip_72=0x1 +phy_xaui_tx_polarity_flip_73=0x1 +phy_xaui_tx_polarity_flip_74=0x1 +phy_xaui_tx_polarity_flip_75=0x1 +phy_xaui_tx_polarity_flip_84=0x1 +phy_xaui_tx_polarity_flip_85=0x1 +phy_xaui_tx_polarity_flip_86=0x1 +phy_xaui_tx_polarity_flip_87=0x1 +phy_xaui_tx_polarity_flip_88=0x1 +phy_xaui_tx_polarity_flip_89=0x1 +phy_xaui_tx_polarity_flip_90=0x1 +phy_xaui_tx_polarity_flip_91=0x1 +phy_xaui_tx_polarity_flip_102=0x1 +phy_xaui_tx_polarity_flip_103=0x1 +phy_xaui_tx_polarity_flip_104=0x1 +phy_xaui_tx_polarity_flip_105=0x1 +phy_xaui_tx_polarity_flip_122=0xb + +#Driver Current +serdes_driver_current_42=0x8 +serdes_driver_current_43=0x8 +serdes_driver_current_44=0x8 +serdes_driver_current_45=0x8 +serdes_driver_current_50=0x8 +serdes_driver_current_51=0x8 +serdes_driver_current_52=0x8 +serdes_driver_current_53=0x8 +serdes_driver_current_54=0x8 +serdes_driver_current_55=0x8 +serdes_driver_current_56=0x8 +serdes_driver_current_57=0x8 +serdes_driver_current_68=0x8 +serdes_driver_current_69=0x8 +serdes_driver_current_70=0x8 +serdes_driver_current_71=0x8 +serdes_driver_current_34=0x8 +serdes_driver_current_35=0x8 +serdes_driver_current_36=0x8 +serdes_driver_current_37=0x8 +serdes_driver_current_38=0x8 +serdes_driver_current_39=0x8 +serdes_driver_current_40=0x8 +serdes_driver_current_41=0x8 +serdes_driver_current_72=0x8 +serdes_driver_current_73=0x8 +serdes_driver_current_74=0x8 +serdes_driver_current_75=0x8 +serdes_driver_current_84=0x8 +serdes_driver_current_85=0x8 +serdes_driver_current_86=0x8 +serdes_driver_current_87=0x8 +serdes_driver_current_88=0x8 +serdes_driver_current_89=0x8 +serdes_driver_current_90=0x8 +serdes_driver_current_91=0x8 +serdes_driver_current_102=0x8 +serdes_driver_current_103=0x8 +serdes_driver_current_104=0x8 +serdes_driver_current_105=0x8 +serdes_driver_current_106=0x8 +serdes_driver_current_107=0x8 +serdes_driver_current_108=0x8 +serdes_driver_current_109=0x8 +serdes_driver_current_110=0x8 +serdes_driver_current_111=0x8 +serdes_driver_current_112=0x8 +serdes_driver_current_113=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 + +#Preemphasis +serdes_preemphasis_42=0x264006 +serdes_preemphasis_43=0x264006 +serdes_preemphasis_44=0x254106 +serdes_preemphasis_45=0x254106 +serdes_preemphasis_50=0x254106 +serdes_preemphasis_51=0x254106 +serdes_preemphasis_52=0x254106 +serdes_preemphasis_53=0x254106 +serdes_preemphasis_54=0x254106 +serdes_preemphasis_55=0x254106 +serdes_preemphasis_56=0x254106 +serdes_preemphasis_57=0x234306 +serdes_preemphasis_68=0x234306 +serdes_preemphasis_69=0x204606 +serdes_preemphasis_70=0x204606 +serdes_preemphasis_71=0x204606 +serdes_preemphasis_34=0x234306 +serdes_preemphasis_35=0x234306 +serdes_preemphasis_36=0x234306 +serdes_preemphasis_37=0x234306 +serdes_preemphasis_38=0x234306 +serdes_preemphasis_39=0x234306 +serdes_preemphasis_40=0x234306 +serdes_preemphasis_41=0x234306 +serdes_preemphasis_72=0x1e4806 +serdes_preemphasis_73=0x1e4806 +serdes_preemphasis_74=0x1e4806 +serdes_preemphasis_75=0x1e4806 +serdes_preemphasis_84=0x1e4806 +serdes_preemphasis_85=0x1a4c06 +serdes_preemphasis_86=0x1a4c06 +serdes_preemphasis_87=0x1b4b06 +serdes_preemphasis_88=0x1b4b06 +serdes_preemphasis_89=0x1e4806 +serdes_preemphasis_90=0x1e4806 +serdes_preemphasis_91=0x1e4806 +serdes_preemphasis_102=0x1e4806 +serdes_preemphasis_103=0x1e4806 +serdes_preemphasis_104=0x1e4806 +serdes_preemphasis_105=0x1e4806 +serdes_preemphasis_106=0x1e4806 +serdes_preemphasis_107=0x1e4806 +serdes_preemphasis_108=0x1e4806 +serdes_preemphasis_109=0x1e4806 +serdes_preemphasis_110=0x1e4806 +serdes_preemphasis_111=0x1d4906 +serdes_preemphasis_112=0x234306 +serdes_preemphasis_113=0x1f4706 +serdes_preemphasis_lane0_5=0x294106 +serdes_preemphasis_lane1_5=0x294106 +serdes_preemphasis_lane2_5=0x294106 +serdes_preemphasis_lane3_5=0x294106 +serdes_preemphasis_lane0_1=0x294106 +serdes_preemphasis_lane1_1=0x294106 +serdes_preemphasis_lane2_1=0x294106 +serdes_preemphasis_lane3_1=0x294106 +serdes_preemphasis_lane0_114=0x2a4006 +serdes_preemphasis_lane1_114=0x2a4006 +serdes_preemphasis_lane2_114=0x2a4006 +serdes_preemphasis_lane3_114=0x2a4006 +serdes_preemphasis_lane0_21=0x2c3c08 +serdes_preemphasis_lane1_21=0x2a4006 +serdes_preemphasis_lane2_21=0x2a4006 +serdes_preemphasis_lane3_21=0x2a4006 +serdes_preemphasis_lane0_9=0x284206 +serdes_preemphasis_lane1_9=0x284206 +serdes_preemphasis_lane2_9=0x284206 +serdes_preemphasis_lane3_9=0x284206 +serdes_preemphasis_lane0_122=0x283e06 +serdes_preemphasis_lane1_122=0x283e06 +serdes_preemphasis_lane2_122=0x283e06 +serdes_preemphasis_lane3_122=0x294601 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/default_sku b/device/accton/x86_64-accton_as7312_54x-r0/default_sku new file mode 100644 index 000000000000..c3c21a98f0e4 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7312-54X t1 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/installer.conf b/device/accton/x86_64-accton_as7312_54x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7312_54x-r0/led_proc_init.soc new file mode 100755 index 000000000000..3074649497e0 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/led_proc_init.soc @@ -0,0 +1,79 @@ +# accton_as7312_54x 48x25G+6x100G SDK port LED macro init SOC +s CMIC_LEDUP0_DATA_RAM 0 +s CMIC_LEDUP1_DATA_RAM 0 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=63 REMAP_PORT_2=63 REMAP_PORT_3=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=63 REMAP_PORT_5=63 REMAP_PORT_6=63 REMAP_PORT_7=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=27 REMAP_PORT_9=26 REMAP_PORT_10=25 REMAP_PORT_11=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=63 REMAP_PORT_18=63 REMAP_PORT_19=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 REMAP_PORT_21=30 REMAP_PORT_22=29 REMAP_PORT_23=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=15 REMAP_PORT_25=14 REMAP_PORT_26=13 REMAP_PORT_27=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=19 REMAP_PORT_29=18 REMAP_PORT_30=17 REMAP_PORT_31=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=63 REMAP_PORT_34=63 REMAP_PORT_35=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=63 REMAP_PORT_37=63 REMAP_PORT_38=63 REMAP_PORT_39=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 REMAP_PORT_41=34 REMAP_PORT_42=33 REMAP_PORT_43=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=23 REMAP_PORT_49=22 REMAP_PORT_50=21 REMAP_PORT_51=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=19 REMAP_PORT_1=18 REMAP_PORT_2=17 REMAP_PORT_3=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=23 REMAP_PORT_5=22 REMAP_PORT_6=21 REMAP_PORT_7=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 REMAP_PORT_9=2 REMAP_PORT_10=1 REMAP_PORT_11=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=7 REMAP_PORT_17=6 REMAP_PORT_18=5 REMAP_PORT_19=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 REMAP_PORT_25=63 REMAP_PORT_26=63 REMAP_PORT_27=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 REMAP_PORT_29=63 REMAP_PORT_30=63 REMAP_PORT_31=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=15 REMAP_PORT_33=14 REMAP_PORT_34=13 REMAP_PORT_35=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=63 REMAP_PORT_41=63 REMAP_PORT_42=63 REMAP_PORT_43=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=31 REMAP_PORT_49=30 REMAP_PORT_50=29 REMAP_PORT_51=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=35 REMAP_PORT_53=34 REMAP_PORT_54=33 REMAP_PORT_55=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=63 REMAP_PORT_57=63 REMAP_PORT_58=63 REMAP_PORT_59=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=63 REMAP_PORT_62=63 REMAP_PORT_63=63 + +led 0 stop +led 0 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start +led auto on + +led 1 stop +led 1 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start +led auto on diff --git a/device/accton/x86_64-accton_as7312_54x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7312_54x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..951384d5e37d --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7312_54x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7312_54x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..a47dfcab7e94 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 2: "11-0053", + 1: "10-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7312_54x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..7255b2d784e1 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/plugins/sfputil.py @@ -0,0 +1,245 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + 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 = 54 + PORTS_IN_BLOCK = 54 + QSFP_PORT_START = 49 + QSFP_PORT_END = 54 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _cpld_mapping = { + 0: "4-0060", + 1: "5-0062", + 2: "6-0064", + } + _port_to_i2c_mapping = { + 1: 18, + 2: 19, + 3: 20, + 4: 21, + 5: 22, + 6: 23, + 7: 24, + 8: 25, + 9: 26, + 10: 27, + 11: 28, + 12: 29, + 13: 30, + 14: 31, + 15: 32, + 16: 33, + 17: 34, + 18: 35, + 19: 36, + 20: 37, + 21: 38, + 22: 39, + 23: 40, + 24: 41, + 25: 42, + 26: 43, + 27: 44, + 28: 45, + 29: 46, + 30: 47, + 31: 48, + 32: 49, + 33: 50, + 34: 51, + 35: 52, + 36: 53, + 37: 54, + 38: 55, + 39: 56, + 40: 57, + 41: 58, + 42: 59, + 43: 60, + 44: 61, + 45: 62, + 46: 63, + 47: 64, + 48: 65, + 49: 66, # QSFP49 + 50: 67, + 51: 68, + 52: 69, + 53: 70, + 54: 71, # QSFP54 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + + SfpUtilBase.__init__(self) + + def get_cpld_num(self, port_num): + cpld_i = 1 + if (port_num > 24 and port_num < self.qsfp_port_start): + cpld_i = 2 + + if (port_num > 52): + cpld_i = 2 + + return cpld_i + + 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 + + cpld_i = self.get_cpld_num(port_num) + + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_present_{1}" + port_ps = path.format(cpld_ps, port_num) + + content = "0" + try: + val_file = open(port_ps) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + 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.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cpld_i = self.get_cpld_num(port_num) + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_reset_{1}" + port_ps = path.format(cpld_ps, 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_value = '0' + + reg_file.write(reg_value) + reg_file.close() + + return True + + 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 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7312_54x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/__init__.py b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..43435472a423 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ['chassis', 'eeprom', 'platform', 'psu', 'sfp', 'thermal', 'fan'] +from . import platform diff --git a/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/chassis.py b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/chassis.py new file mode 100644 index 000000000000..ceece0f9db83 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/chassis.py @@ -0,0 +1,193 @@ +############################################################################# +# Edgecore +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +import os + +try: + from sonic_platform_base.chassis_base import ChassisBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 6 +NUM_FAN = 2 +NUM_PSU = 2 +NUM_THERMAL = 4 +PORT_END = 54 +NUM_COMPONENT = 4 +HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/" +PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/" +REBOOT_CAUSE_FILE = "reboot-cause.txt" +PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt" +HOST_CHK_CMD = "docker > /dev/null 2>&1" + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + def __init__(self): + ChassisBase.__init__(self) + self._api_helper = APIHelper() + self._api_helper = APIHelper() + self.is_host = self._api_helper.is_host() + + self.config_data = {} + + self.__initialize_fan() + self.__initialize_psu() + self.__initialize_thermals() + self.__initialize_components() + self.__initialize_sfp() + self.__initialize_eeprom() + + def __initialize_sfp(self): + from sonic_platform.sfp import Sfp + for index in range(0, PORT_END): + sfp = Sfp(index) + self._sfp_list.append(sfp) + self.sfp_module_initialized = True + + def __initialize_fan(self): + from sonic_platform.fan import Fan + 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 __initialize_psu(self): + from sonic_platform.psu import Psu + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + + def __initialize_thermals(self): + from sonic_platform.thermal import Thermal + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + def __initialize_eeprom(self): + from sonic_platform.eeprom import Tlv + self._eeprom = Tlv() + + def __initialize_components(self): + from sonic_platform.component import Component + for index in range(0, NUM_COMPONENT): + component = Component(index) + self._component_list.append(component) + + def __initialize_watchdog(self): + from sonic_platform.watchdog import Watchdog + self._watchdog = Watchdog() + + + 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 get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + + return self._api_helper.hwsku + + def get_presence(self): + """ + Retrieves the presence of the Chassis + Returns: + bool: True if Chassis is present, False if not + """ + return True + + 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 True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.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. + """ + + reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) + sw_reboot_cause = self._api_helper.read_txt_file( + reboot_cause_path) or "Unknown" + + + return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause) + + 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, 1 for Ethernet0, 2 for Ethernet4 and so on. + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + if not self.sfp_module_initialized: + self.__initialize_sfp() + + try: + # The index will start from 1 + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + return sfp diff --git a/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/component.py b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/component.py new file mode 100644 index 000000000000..5300e1e73233 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/component.py @@ -0,0 +1,125 @@ +############################################################################# +# Celestica +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +import shlex +import subprocess + +try: + from sonic_platform_base.component_base import ComponentBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CPLD_ADDR_MAPPING = { + "CPLD1": "4-0060", + "CPLD2": "5-0062", + "CPLD3": "6-0064", +} +SYSFS_PATH = "/sys/bus/i2c/devices/" +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" +COMPONENT_LIST= [ + ("CPLD1", "CPLD 1"), + ("CPLD2", "CPLD 2"), + ("CPLD3", "CPLD 3"), + ("BIOS", "Basic Input/Output System") + +] +COMPONENT_DES_LIST = ["CPLD","Basic Input/Output System"] + + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index=0): + self._api_helper=APIHelper() + ComponentBase.__init__(self) + self.index = component_index + self.name = self.get_name() + + def __run_command(self, command): + # Run bash command and print output to stdout + try: + process = subprocess.Popen( + shlex.split(command), stdout=subprocess.PIPE) + while True: + output = process.stdout.readline() + if output == '' and process.poll() is not None: + break + rc = process.poll() + if rc != 0: + return False + except Exception: + return False + return True + + def __get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def __get_cpld_version(self): + # Retrieves the CPLD firmware version + cpld_version = dict() + for cpld_name in CPLD_ADDR_MAPPING: + try: + cpld_path = "{}{}{}".format(SYSFS_PATH, CPLD_ADDR_MAPPING[cpld_name], '/version') + cpld_version_raw= self._api_helper.read_txt_file(cpld_path) + cpld_version[cpld_name] = "{}".format(int(cpld_version_raw,16)) + except Exception as e: + print('Get exception when read cpld') + cpld_version[cpld_name] = 'None' + + return cpld_version + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return COMPONENT_LIST[self.index][0] + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return COMPONENT_LIST[self.index][1] + #return "testhwsku" + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + fw_version = None + if self.name == "BIOS": + fw_version = self.__get_bios_version() + elif "CPLD" in self.name: + cpld_version = self.__get_cpld_version() + fw_version = cpld_version.get(self.name) + + return fw_version + + def install_firmware(self, image_path): + """ + Install firmware to module + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install successfully, False if not + """ + raise NotImplementedError diff --git a/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/eeprom.py b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/eeprom.py new file mode 100644 index 000000000000..1b2f3f276c3e --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/eeprom.py @@ -0,0 +1,102 @@ +try: + import os + import sys + import re + if sys.version_info[0] >= 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + + +class Tlv(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + 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 Exception: + pass + + return _eeprom_info_dict + + def _load_eeprom(self): + original_stdout = sys.stdout + sys.stdout = StringIO() + try: + self.read_eeprom_db() + except Exception: + 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 Exception: + 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 Exception: + pass + + e = self.read_eeprom() + if e is None: + return 0 + + try: + self.update_cache(e) + except Exception: + 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/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/fan.py b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/fan.py new file mode 100644 index 000000000000..fc072941a3d3 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/fan.py @@ -0,0 +1,177 @@ +############################################################################# +# Edgecore +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# +############################################################################# + + +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") + +PSU_FAN_MAX_RPM = 26688 + +CPLD_I2C_PATH = "/sys/bus/i2c/devices/2-0066/fan" +PSU_HWMON_I2C_PATH ="/sys/bus/i2c/devices/{}-00{}/" +PSU_I2C_MAPPING = { + 0: { + "num": 11, + "addr": "5b" + }, + 1: { + "num": 10, + "addr": "58" + }, +} + + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0): + self._api_helper=APIHelper() + 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.psu_i2c_num = PSU_I2C_MAPPING[self.psu_index]['num'] + self.psu_i2c_addr = PSU_I2C_MAPPING[self.psu_index]['addr'] + self.psu_hwmon_path = PSU_HWMON_I2C_PATH.format( + self.psu_i2c_num, self.psu_i2c_addr) + + FanBase.__init__(self) + + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + + + if not self.is_psu_fan: + dir_str = "{}{}{}".format(CPLD_I2C_PATH, self.fan_tray_index, '_direction') + val=self._api_helper.read_txt_file(dir_str) + if val is not None: + if val==0:#F2B + direction=self.FAN_DIRECTION_EXHAUST + else: + direction=self.FAN_DIRECTION_INTAKE + else: + direction=self.FAN_DIRECTION_EXHAUST + + else: #For PSU + dir_str = "{}{}".format(self.psu_hwmon_path,'psu_hwmon_path') + val=self._api_helper.read_txt_file(dir_str) + if val is not None: + if val=='F2B': + direction=self.FAN_DIRECTION_EXHAUST + else: + direction=self.FAN_DIRECTION_INTAKE + else: + direction=self.FAN_DIRECTION_EXHAUST + + return direction + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + + """ + speed = 0 + if self.is_psu_fan: + psu_fan_path= "{}{}".format(self.psu_hwmon_path, 'psu_fan1_speed_rpm') + fan_speed_rpm = self._api_helper.read_txt_file(psu_fan_path) + if fan_speed_rpm is not None: + speed = (int(fan_speed_rpm,10))*100/26688 + if speed > 100: + speed=100 + else: + return 0 + + elif self.get_presence(): + speed_path = "{}{}".format(CPLD_I2C_PATH, '_duty_cycle_percentage') + speed=self._api_helper.read_txt_file(speed_path) + if speed is None: + return 0 + + return int(speed) + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + + Note: + speed_pc = pwm_target/255*100 + + 0 : when PWM mode is use + pwm : when pwm mode is not use + """ + return False #Not supported + + 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 False #Not supported + + 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 + + """ + + if not self.is_psu_fan and self.get_presence(): + speed_path = "{}{}".format(CPLD_I2C_PATH, '_duty_cycle_percentage') + return self._api_helper.write_txt_file(speed_path, int(speed)) + + return False + + 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 + """ + return False #Not supported + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if FAN is present, False if not + """ + present_path = "{}{}{}".format(CPLD_I2C_PATH, self.fan_tray_index+1, '_present') + val=self._api_helper.read_txt_file(present_path) + + if not self.is_psu_fan: + if val is not None: + return int(val, 10)==1 + else: + return False + else: + return True diff --git a/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/helper.py b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/helper.py new file mode 100644 index 000000000000..4cd60ac90611 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/helper.py @@ -0,0 +1,117 @@ +import os +import struct +import subprocess +from mmap import * +from sonic_py_common import device_info + +HOST_CHK_CMD = "docker > /dev/null 2>&1" +EMPTY_STRING = "" + + +class APIHelper(): + + def __init__(self): + (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() + + def is_host(self): + return os.system(HOST_CHK_CMD) == 0 + + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except Exception: + status = False + return status, result + + def run_command(self, cmd): + status = True + result = "" + try: + p = subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + result = raw_data.strip() + except Exception: + status = False + return status, result + + def run_interactive_command(self, cmd): + try: + os.system(cmd) + except Exception: + return False + return True + + 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 write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except IOError: + return False + return True + + 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() + else: + status = False + except Exception: + 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() + else: + status = False + except Exception: + status = False + return status, result + + def ipmi_set_ss_thres(self, id, threshold_key, value): + status = True + result = "" + try: + cmd = "ipmitool sensor thresh '{}' {} {}".format(str(id), str(threshold_key), str(value)) + p = subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result diff --git a/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/platform.py b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/platform.py new file mode 100644 index 000000000000..2f2c2a447fcf --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/platform.py @@ -0,0 +1,21 @@ +############################################################################# +# Edgecore +# +# 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/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/psu.py b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/psu.py new file mode 100644 index 000000000000..cb715515d50e --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/psu.py @@ -0,0 +1,220 @@ +############################################################################# +# Edgecore +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +#import sonic_platform + +try: + from sonic_platform_base.psu_base import PsuBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +I2C_PATH ="/sys/bus/i2c/devices/{0}-00{1}/" + +PSU_NAME_LIST = ["PSU-1", "PSU-2"] +PSU_NUM_FAN = [1, 1] +PSU_HWMON_I2C_MAPPING = { + 0: { + "num": 11, + "addr": "5b" + }, + 1: { + "num": 10, + "addr": "58" + }, +} + +PSU_CPLD_I2C_MAPPING = { + 0: { + "num": 11, + "addr": "53" + }, + 1: { + "num": 10, + "addr": "50" + }, +} + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, psu_index=0): + PsuBase.__init__(self) + self.index = psu_index + self._api_helper = APIHelper() + + self.i2c_num = PSU_HWMON_I2C_MAPPING[self.index]["num"] + self.i2c_addr = PSU_HWMON_I2C_MAPPING[self.index]["addr"] + self.hwmon_path = I2C_PATH.format(self.i2c_num, self.i2c_addr) + + self.i2c_num = PSU_CPLD_I2C_MAPPING[self.index]["num"] + self.i2c_addr = PSU_CPLD_I2C_MAPPING[self.index]["addr"] + self.cpld_path = I2C_PATH.format(self.i2c_num, self.i2c_addr) + self.__initialize_fan() + + def __initialize_fan(self): + from sonic_platform.fan import Fan + for fan_index in range(0, PSU_NUM_FAN[self.index]): + fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index) + self._fan_list.append(fan) + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + vout_path = "{}{}".format(self.hwmon_path, 'psu_v_out') + vout_val=self._api_helper.read_txt_file(vout_path) + return float(vout_val)/ 1000 + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + iout_path = "{}{}".format(self.hwmon_path, 'psu_i_out') + val=self._api_helper.read_txt_file(iout_path) + if val is not None: + return float(val)/1000 + else: + return 0 + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + pout_path = "{}{}".format(self.hwmon_path, 'psu_p_out') + val=self._api_helper.read_txt_file(pout_path) + if val is not None: + return float(val)/1000 + else: + return 0 + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + return self.get_status() + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the PSU status LED + Note: Only support green and off + Returns: + bool: True if status LED state is set successfully, False if not + """ + + return False #Controlled by HW + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + + if self.get_status(): + return True + else: + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temp_path = "{}{}".format(self.hwmon_path, 'psu_temp1_input') + val=self._api_helper.read_txt_file(temp_path) + if val is not None: + return float(val)/1000 + else: + return 0 + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return False #Not supported + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + vout_path = "{}{}".format(self.hwmon_path, 'psu_mfr_vout_max') + vout_val=self._api_helper.read_txt_file(vout_path) + if vout_val is not None: + return float(vout_val)/ 1000 + else: + return 0 + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + vout_path = "{}{}".format(self.hwmon_path, 'psu_mfr_vout_min') + vout_val=self._api_helper.read_txt_file(vout_path) + if vout_val is not None: + return float(vout_val)/ 1000 + else: + return 0 + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return PSU_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + presence_path="{}{}".format(self.cpld_path, 'psu_present') + val=self._api_helper.read_txt_file(presence_path) + if val is not None: + return int(val, 10) == 1 + else: + return 0 + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + power_path="{}{}".format(self.cpld_path, 'psu_power_good') + val=self._api_helper.read_txt_file(power_path) + if val is not None: + return int(val, 10) == 1 + else: + return 0 diff --git a/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/sfp.py b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/sfp.py new file mode 100644 index 000000000000..b5e38017bc90 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/sfp.py @@ -0,0 +1,1228 @@ +############################################################################# +# Edgecore +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# + +import os +import time +import sys + +from ctypes import create_string_buffer + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + #from sonic_platform_base.sonic_sfp.sff8472 import sffbase + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CPLD_I2C_PATH = "/sys/bus/i2c/devices/" + +QSFP_INFO_OFFSET = 128 +QSFP_DOM_OFFSET = 0 + +SFP_INFO_OFFSET = 0 +SFP_DOM_OFFSET = 256 + +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNEL_THRESHOLD_OFFSET = 176 +QSFP_CHANNEL_THRESHOLD_WIDTH = 16 + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + + +# Offset for values in SFP eeprom +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 40 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 1 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + + # Port number + PORT_START = 1 + PORT_END = 54 + QSFP_PORT_START = 49 + + # Path to sysfs + PLATFORM_ROOT_PATH = "/usr/share/sonic/device" + PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" + HOST_CHK_CMD = "docker > /dev/null 2>&1" + + PLATFORM = "x86_64-accton_as7312_54x-r0" + HWSKU = "Accton-AS7312-54X" + + _cpld_mapping = { + 0: "4-0060", + 1: "5-0062", + 2: "6-0064", + } + _port_to_i2c_mapping = { + 1: 18, + 2: 19, + 3: 20, + 4: 21, + 5: 22, + 6: 23, + 7: 24, + 8: 25, + 9: 26, + 10: 27, + 11: 28, + 12: 29, + 13: 30, + 14: 31, + 15: 32, + 16: 33, + 17: 34, + 18: 35, + 19: 36, + 20: 37, + 21: 38, + 22: 39, + 23: 40, + 24: 41, + 25: 42, + 26: 43, + 27: 44, + 28: 45, + 29: 46, + 30: 47, + 31: 48, + 32: 49, + 33: 50, + 34: 51, + 35: 52, + 36: 53, + 37: 54, + 38: 55, + 39: 56, + 40: 57, + 41: 58, + 42: 59, + 43: 60, + 44: 61, + 45: 62, + 46: 63, + 47: 64, + 48: 65, + 49: 66, # QSFP49 + 50: 67, + 51: 68, + 52: 69, + 53: 70, + 54: 71, # QSFP54 + } + + + def __init__(self, sfp_index=0): + self._api_helper=APIHelper() + # Init index + self.index = sfp_index + self.port_num = self.index + 1 + + # Init eeprom path + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + self.port_to_eeprom_mapping = {} + for x in range(self.PORT_START, self.PORT_END + 1): + self.port_to_eeprom_mapping[x] = eeprom_path.format(self._port_to_i2c_mapping[x]) + + self.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + SfpBase.__init__(self) + + def __get_cpld_num(self, port_num): + cpld_i = 1 + if (port_num > 24 and port_num < self.QSFP_PORT_START): + cpld_i = 2 + + if (port_num > 52): + cpld_i = 2 + + return cpld_i + + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def __write_txt_file(self, file_path, value): + try: + with open(file_path, 'w', buffering=0) as fd: + fd.write(str(value)) + except Exception: + return False + return True + + def __is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) + hwsku_path = "/".join([platform_path, self.HWSKU] + ) if self.__is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + if sys.version_info[0] >= 3: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + else: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except Exception: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + # check present status + if self.port_num < 49: + sfpi_obj = sff8472InterfaceId() #SFP + else: + sfpi_obj = sff8436InterfaceId() #QSFP + if not self.get_presence() or not sfpi_obj: + return {} + + if self.port_num < 49: + offset = SFP_INFO_OFFSET + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_SFP) + else: + offset = QSFP_INFO_OFFSET + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_QSFP) + + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( + sfp_interface_bulk_raw, 0) + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_vendor_name_raw, 0) + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_vendor_pn_raw, 0) + + if self.port_num < 49: + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_SFP) + else: + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_QSFP) + + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_vendor_rev_raw, 0) + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_vendor_sn_raw, 0) + + sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_vendor_oui_raw, 0) + + sfp_vendor_date_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_vendor_date_raw, 0) + + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + compliance_code_dict = dict() + + if sfp_interface_bulk_data: + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data[ + 'data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' + transceiver_info_dict['cable_type'] = "Unknown" + transceiver_info_dict['cable_length'] = "Unknown" + + if self.port_num < 49: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + else: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + # check present status + if self.port_num < 49: #SFP case + sfpd_obj = sff8472Dom() + if not self.get_presence() or not sfpd_obj: + return {} + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, SFP_DOM_OFFSET) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = SFP_DOM_OFFSET + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_voltage_data = sfpd_obj.parse_channel_monitor_params( + dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_voltage_data['data']['TXPower']['value'] + transceiver_dom_info_dict['rx1power'] = dom_voltage_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_voltage_data['data']['TXBias']['value'] + + else: #QSFP case + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + + if not self.get_presence() or not sfpi_obj or not sfpd_obj: + return {} + + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + offset = QSFP_DOM_OFFSET + offset_xcvr = QSFP_INFO_OFFSET + + # 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( + (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_dom_capability( + qsfp_dom_capability_raw, 0) + else: + return None + + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes( + (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) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['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 = {} + dom_channel_monitor_raw = None + 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( + (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: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (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) + 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'] + + if dom_channel_monitor_raw: + 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'] + #End of else + + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num( + transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + # check present status + if self.port_num < 49: + sfpd_obj = sff8472Dom() + + if not self.get_presence() and not sfpd_obj: + return {} + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, SFP_DOM_OFFSET) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = SFP_DOM_OFFSET + transceiver_dom_threshold_info_dict = dict.fromkeys( + self.threshold_dict_keys, 'N/A') + dom_module_threshold_raw = self.__read_eeprom_specific_bytes( + (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) + + 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'] + + for key in transceiver_dom_threshold_info_dict: + transceiver_dom_threshold_info_dict[key] = self._convert_string_to_num( + transceiver_dom_threshold_info_dict[key]) + + return transceiver_dom_threshold_info_dict + + + else: + sfpd_obj = sff8436Dom() + + if not self.get_presence() or not sfpd_obj: + return {} + + transceiver_dom_threshold_dict = dict.fromkeys( + self.threshold_dict_keys, 'N/A') + dom_thres_raw = self.__read_eeprom_specific_bytes( + QSFP_MODULE_THRESHOLD_OFFSET, QSFP_MODULE_THRESHOLD_WIDTH) if self.get_presence() and sfpd_obj else None + + if dom_thres_raw: + module_threshold_values = sfpd_obj.parse_module_threshold_values( + dom_thres_raw, 0) + module_threshold_data = module_threshold_values.get('data') + if module_threshold_data: + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value'] + + dom_thres_raw = self.__read_eeprom_specific_bytes( + QSFP_CHANNEL_THRESHOLD_OFFSET, QSFP_CHANNEL_THRESHOLD_WIDTH) if self.get_presence() and sfpd_obj else None + channel_threshold_values = sfpd_obj.parse_channel_threshold_values( + dom_thres_raw, 0) + channel_threshold_data = channel_threshold_values.get('data') + if channel_threshold_data: + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerhighwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value'] + + for key in transceiver_dom_threshold_dict: + transceiver_dom_threshold_dict[key] = self._convert_string_to_num( + transceiver_dom_threshold_dict[key]) + + return transceiver_dom_threshold_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + if self.port_num <49: + return False # SPF port doesn't support this feature + + cpld_i = self.__get_cpld_num(self.port_num) + cpld_path = self._cpld_mapping[cpld_i] + reset_path = "{}{}{}{}".format(CPLD_I2C_PATH, cpld_path, '/module_reset_', self.port_num) + val=self._api_helper.read_txt_file(reset_path) + if val is None: + return 0 + + return int(val, 10)==1 + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + rx_los = False + if self.port_num < 49: + cpld_i = self.__get_cpld_num(self.port_num) + cpld_path = self._cpld_mapping[cpld_i] + rx_path = "{}{}{}{}".format(CPLD_I2C_PATH, cpld_path, '/module_rx_los_', self.port_num) + rx_los=self._api_helper.read_txt_file(rx_path) + if rx_los is None: + return False + #status_control_raw = self.__read_eeprom_specific_bytes( + # SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + #if status_control_raw: + # data = int(status_control_raw[0], 16) + # rx_los = (sffbase().test_bit(data, 1) != 0) + + else: + rx_los_list = [] + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + QSFP_CHANNL_RX_LOS_STATUS_OFFSET, QSFP_CHANNL_RX_LOS_STATUS_WIDTH) if self.get_presence() else None + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + rx_los = rx_los_list[0] and rx_los_list[1] and rx_los_list[2] and rx_los_list[3] + + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + tx_fault = False + if self.port_num < 49: + cpld_i = self.__get_cpld_num(self.port_num) + cpld_path = self._cpld_mapping[cpld_i] + tx_path = "{}{}{}{}".format(CPLD_I2C_PATH, cpld_path, '/module_tx_fault_', self.port_num) + tx_fault=self._api_helper.read_txt_file(tx_path) + if tx_fault is None: + return False + #status_control_raw = self.__read_eeprom_specific_bytes( + # SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + #if status_control_raw: + # data = int(status_control_raw[0], 16) + # tx_fault = (sffbase().test_bit(data, 2) != 0) + else: + tx_fault_list = [] + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET, QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) if self.get_presence() else None + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + tx_fault = tx_fault_list[0] and tx_fault_list[1] and tx_fault_list[2] and tx_fault_list[3] + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + if self.port_num < 49: + tx_disable = False + + cpld_i = self.__get_cpld_num(self.port_num) + cpld_path = self._cpld_mapping[cpld_i] + tx_path = "{}{}{}{}".format(CPLD_I2C_PATH, cpld_path, '/module_tx_disable_', self.port_num) + tx_disable=self._api_helper.read_txt_file(tx_path) + + #status_control_raw = self.__read_eeprom_specific_bytes( + # SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + #if status_control_raw: + # data = int(status_control_raw[0], 16) + # tx_disable_hard = (sffbase().test_bit( + # data, SFP_TX_DISABLE_HARD_BIT) != 0) + # tx_disable_soft = (sffbase().test_bit( + # data, SFP_TX_DISABLE_SOFT_BIT) != 0) + # tx_disable = tx_disable_hard | tx_disable_soft + if tx_disable is not None: + return tx_disable + else: + return False + + else: + tx_disable_list = [] + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + tx_disable_list.append( + 'On' == dom_control_data['data']['TX1Disable']['value']) + tx_disable_list.append( + 'On' == dom_control_data['data']['TX2Disable']['value']) + tx_disable_list.append( + 'On' == dom_control_data['data']['TX3Disable']['value']) + tx_disable_list.append( + 'On' == dom_control_data['data']['TX4Disable']['value']) + + return tx_disable_list + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + if self.port_num < 49: + # SFP doesn't support this feature + return False + else: + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + if self.port_num < 49: + # SFP doesn't support this feature + return False + else: + power_set=self.get_power_set() + power_override = self.get_power_override() + return power_set and power_override + + + def get_power_set(self): + + if self.port_num < 49: + # SFP doesn't support this feature + return False + else: + power_set = False + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + QSFP_POWEROVERRIDE_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + power_set = ( + 'On' == dom_control_data['data']['PowerSet']['value']) + + return power_set + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + if self.port_num < 49: + return False # SFP doesn't support this feature + else: + power_override = False + + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + QSFP_POWEROVERRIDE_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + power_override = ( + 'On' == dom_control_data['data']['PowerOverride']['value']) + + return power_override + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("temperature", "N/A") + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + Returns: + An integer number of supply voltage in mV + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("voltage", "N/A") + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + + tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A") + if self.port_num < 49: + return [tx1_bs, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + tx2_bs = transceiver_dom_info_dict.get("tx2bias", "N/A") + tx3_bs = transceiver_dom_info_dict.get("tx3bias", "N/A") + tx4_bs = transceiver_dom_info_dict.get("tx4bias", "N/A") + return [tx1_bs, tx2_bs, tx3_bs, tx4_bs] if transceiver_dom_info_dict else [] + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + + rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A") + if self.port_num < 49: + return [rx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + rx2_pw = transceiver_dom_info_dict.get("rx2power", "N/A") + rx3_pw = transceiver_dom_info_dict.get("rx3power", "N/A") + rx4_pw = transceiver_dom_info_dict.get("rx4power", "N/A") + return [rx1_pw, rx2_pw, rx3_pw, rx4_pw] if transceiver_dom_info_dict else [] + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A") + if self.port_num < 49: + return [tx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + tx2_pw = transceiver_dom_info_dict.get("tx2power", "N/A") + tx3_pw = transceiver_dom_info_dict.get("tx3power", "N/A") + tx4_pw = transceiver_dom_info_dict.get("tx4power", "N/A") + return [tx1_pw, tx2_pw, tx3_pw, tx4_pw] + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + if self.port_num <49: + return False # SFP doesn't support this feature + + cpld_i = self.__get_cpld_num(self.port_num) + cpld_path = self._cpld_mapping[cpld_i] + reset_path = "{}{}{}{}".format(CPLD_I2C_PATH, cpld_path, '/module_reset_', self.port_num) + ret = self.__write_txt_file(reset_path, 1) + if ret is not True: + return ret + + time.sleep(0.01) + ret = self.__write_txt_file(reset_path, 0) + time.sleep(0.2) + + return ret + + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + if self.port_num < 49: + cpld_i = self.__get_cpld_num(self.port_num) + cpld_path = self._cpld_mapping[cpld_i] + tx_path = "{}{}{}{}".format(CPLD_I2C_PATH, cpld_path, '/module_tx_disable_', self.port_num) + ret = self.__write_txt_file(tx_path, 1 if tx_disable else 0) + time.sleep(0.01) + return ret + + else: + if not self.get_presence(): + return False + sysfsfile_eeprom = None + try: + tx_disable_ctl = 0xf if tx_disable else 0x0 + buffer = create_string_buffer(1) + if sys.version_info[0] >= 3: + buffer[0] = tx_disable_ctl + else: + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print ('Error: unable to open file: ',str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + Returns: + A boolean, True if successful, False if not + """ + + if self.port_num < 49: + return False # SFP doesn't support this feature + else: + if not self.get_presence(): + return False + + sysfsfile_eeprom = None + try: + channel_state = self.get_tx_disable_channel() + + for i in range(4): + channel_mask = (1 << i) + if not (channel & channel_mask): + continue + + if disable: + channel_state |= channel_mask + else: + channel_state &= ~channel_mask + + buffer = create_string_buffer(1) + if sys.version_info[0] >= 3: + buffer[0] = channel_state + else: + buffer[0] = chr(channel_state) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print ('Error: unable to open file: ', str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if self.port_num < 49: + return False # SFP doesn't support this feature + else: + if lpmode is True: + self.set_power_override(True, True) + else: + self.set_power_override(False, False) + + return True + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + if self.port_num < 49: + return False # SFP doesn't support this feature + else: + if not self.get_presence(): + return False + try: + power_override_bit = (1 << 0) if power_override else 0 + power_set_bit = (1 << 1) if power_set else (1 << 3) + + buffer = create_string_buffer(1) + if sys.version_info[0] >= 3: + buffer[0] = (power_override_bit | power_set_bit) + else: + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + with open(self.port_to_eeprom_mapping[self.port_num], "r+b") as fd: + fd.seek(QSFP_POWEROVERRIDE_OFFSET) + fd.write(buffer[0]) + time.sleep(0.01) + except Exception: + print ('Error: unable to open file: ', str(e)) + return False + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + cpld_i = self.__get_cpld_num(self.port_num) + cpld_path = self._cpld_mapping[cpld_i] + present_path = "{}{}{}{}".format(CPLD_I2C_PATH, cpld_path, '/module_present_', self.port_num) + val=self._api_helper.read_txt_file(present_path) + if val is not None: + return int(val, 10)==1 + else: + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("model", "N/A") + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("serial", "N/A") + + 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_transceiver_bulk_status() diff --git a/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/thermal.py b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/thermal.py new file mode 100644 index 000000000000..aeab2caa23db --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54x-r0/sonic_platform/thermal.py @@ -0,0 +1,146 @@ +############################################################################# +# Edgecore +# +# Thermal contains an implementation of SONiC Platform Base API and +# provides the thermal device status which are available in the platform +# +############################################################################# + +import os +import os.path +import glob + +try: + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + THERMAL_NAME_LIST = [] + SYSFS_PATH = "/sys/bus/i2c/devices" + + def __init__(self, thermal_index=0): + self.index = thermal_index + # Add thermal name + self.THERMAL_NAME_LIST.append("Temp sensor 1") + self.THERMAL_NAME_LIST.append("Temp sensor 2") + self.THERMAL_NAME_LIST.append("Temp sensor 3") + self.THERMAL_NAME_LIST.append("Temp sensor 4") + + # Set hwmon path + i2c_path = { + 0: "3-0048/hwmon/hwmon*/", + 1: "3-0049/hwmon/hwmon*/", + 2: "3-004a/hwmon/hwmon*/", + 3: "3-004b/hwmon/hwmon*/", + }.get(self.index, None) + + self.hwmon_path = "{}/{}".format(self.SYSFS_PATH, i2c_path) + self.ss_key = self.THERMAL_NAME_LIST[self.index] + self.ss_index = 1 + + def __read_txt_file(self, file_path): + for filename in glob.glob(file_path): + try: + with open(filename, 'r') as fd: + data =fd.readline().rstrip() + return data + except IOError as e: + pass + + return None + + def __get_temp(self, temp_file): + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_temp = self.__read_txt_file(temp_file_path) + if raw_temp is not None: + return float(raw_temp)/1000 + else: + return 0 + + + def __set_threshold(self, file_name, temperature): + temp_file_path = os.path.join(self.hwmon_path, file_name) + for filename in glob.glob(temp_file_path): + try: + with open(filename, 'w') as fd: + fd.write(str(temperature)) + return True + except IOError as e: + print("IOError") + + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temp_file = "temp{}_input".format(self.ss_index) + return self.__get_temp(temp_file) + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + temp_file = "temp{}_max".format(self.ss_index) + return self.__get_temp(temp_file) + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if not + """ + temp_file = "temp{}_max".format(self.ss_index) + temperature = temperature *1000 + self.__set_threshold(temp_file, temperature) + + return True + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.THERMAL_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the Thermal + Returns: + bool: True if Thermal is present, False if not + """ + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_txt = self.__read_txt_file(temp_file_path) + if raw_txt is not None: + return True + else: + return False + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + + file_str = "temp{}_input".format(self.ss_index) + file_path = os.path.join(self.hwmon_path, file_str) + raw_txt = self.__read_txt_file(file_path) + if raw_txt is None: + return False + else: + return int(raw_txt) != 0 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/port_config.ini b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/port_config.ini new file mode 100755 index 000000000000..93160688d748 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index speed +Ethernet0 41 twentyfiveGigE1 1 25000 +Ethernet1 42 twentyfiveGigE2 2 25000 +Ethernet2 43 twentyfiveGigE3 3 25000 +Ethernet3 44 twentyfiveGigE4 4 25000 +Ethernet4 49 twentyfiveGigE5 5 25000 +Ethernet5 50 twentyfiveGigE6 6 25000 +Ethernet6 51 twentyfiveGigE7 7 25000 +Ethernet7 52 twentyfiveGigE8 8 25000 +Ethernet8 53 twentyfiveGigE9 9 25000 +Ethernet9 54 twentyfiveGigE10 10 25000 +Ethernet10 55 twentyfiveGigE11 11 25000 +Ethernet11 56 twentyfiveGigE12 12 25000 +Ethernet12 65 twentyfiveGigE13 13 25000 +Ethernet13 66 twentyfiveGigE14 14 25000 +Ethernet14 67 twentyfiveGigE15 15 25000 +Ethernet15 68 twentyfiveGigE16 16 25000 +Ethernet16 33 twentyfiveGigE17 17 25000 +Ethernet17 34 twentyfiveGigE18 18 25000 +Ethernet18 35 twentyfiveGigE19 19 25000 +Ethernet19 36 twentyfiveGigE20 20 25000 +Ethernet20 37 twentyfiveGigE21 21 25000 +Ethernet21 38 twentyfiveGigE22 22 25000 +Ethernet22 39 twentyfiveGigE23 23 25000 +Ethernet23 40 twentyfiveGigE24 24 25000 +Ethernet24 69 twentyfiveGigE25 25 25000 +Ethernet25 70 twentyfiveGigE26 26 25000 +Ethernet26 71 twentyfiveGigE27 27 25000 +Ethernet27 72 twentyfiveGigE28 28 25000 +Ethernet28 81 twentyfiveGigE29 29 25000 +Ethernet29 82 twentyfiveGigE30 30 25000 +Ethernet30 83 twentyfiveGigE31 31 25000 +Ethernet31 84 twentyfiveGigE32 32 25000 +Ethernet32 85 twentyfiveGigE33 33 25000 +Ethernet33 86 twentyfiveGigE34 34 25000 +Ethernet34 87 twentyfiveGigE35 35 25000 +Ethernet35 88 twentyfiveGigE36 36 25000 +Ethernet36 97 twentyfiveGigE37 37 25000 +Ethernet37 98 twentyfiveGigE38 38 25000 +Ethernet38 99 twentyfiveGigE39 39 25000 +Ethernet39 100 twentyfiveGigE40 40 25000 +Ethernet40 101 twentyfiveGigE41 41 25000 +Ethernet41 102 twentyfiveGigE42 42 25000 +Ethernet42 103 twentyfiveGigE43 43 25000 +Ethernet43 104 twentyfiveGigE44 44 25000 +Ethernet44 105 twentyfiveGigE45 45 25000 +Ethernet45 106 twentyfiveGigE46 46 25000 +Ethernet46 107 twentyfiveGigE47 47 25000 +Ethernet47 108 twentyfiveGigE48 48 25000 +Ethernet48 5,6,7,8 hundredGigE49 49 100000 +Ethernet52 1,2,3,4 hundredGigE50 50 100000 +Ethernet56 109,110,111,112 hundredGigE51 51 100000 +Ethernet60 21,22,23,24 hundredGigE52 52 100000 +Ethernet64 9,10,11,12 hundredGigE53 53 100000 +Ethernet68 117,118,119,120 hundredGigE54 54 100000 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/sai.profile b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/sai.profile new file mode 100644 index 000000000000..54cdc34801dd --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-as7312-48x25G+6x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/th-as7312-48x25G+6x100G.config.bcm b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/th-as7312-48x25G+6x100G.config.bcm new file mode 100644 index 000000000000..0ac6051b1ad4 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/Accton-AS7312-54XS/th-as7312-48x25G+6x100G.config.bcm @@ -0,0 +1,519 @@ +# accton_as7312_54x 48x25G+6x100G SDK config +os=unix +schan_intr_enable=0 + +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x0407ffc00ff00ff003fc3ffc00200222 +pbmp_xport_xe=0x0407ffd00ff00ff403fc3ffc00200222 + +## FC10 ## +dport_map_port_42=1 +dport_map_port_43=2 +dport_map_port_44=3 +dport_map_port_45=4 + +## FC12 ## +dport_map_port_50=5 +dport_map_port_51=6 +dport_map_port_52=7 +dport_map_port_53=8 + +## FC13 ## +dport_map_port_54=9 +dport_map_port_55=10 +dport_map_port_56=11 +dport_map_port_57=12 + +## FC16 ## +dport_map_port_68=13 +dport_map_port_69=14 +dport_map_port_70=15 +dport_map_port_71=16 + +## FC8 ## +dport_map_port_34=17 +dport_map_port_35=18 +dport_map_port_36=19 +dport_map_port_37=20 + +## FC9 ## +dport_map_port_38=21 +dport_map_port_39=22 +dport_map_port_40=23 +dport_map_port_41=24 + +## FC17 ## +dport_map_port_72=25 +dport_map_port_73=26 +dport_map_port_74=27 +dport_map_port_75=28 + +## FC20 ## +dport_map_port_84=29 +dport_map_port_85=30 +dport_map_port_86=31 +dport_map_port_87=32 + +## FC21 ## +dport_map_port_88=33 +dport_map_port_89=34 +dport_map_port_90=35 +dport_map_port_91=36 + +## FC24 ## +dport_map_port_102=37 +dport_map_port_103=38 +dport_map_port_104=39 +dport_map_port_105=40 + +## FC25 ## +dport_map_port_106=41 +dport_map_port_107=42 +dport_map_port_108=43 +dport_map_port_109=44 + +## FC26 ## +dport_map_port_110=45 +dport_map_port_111=46 +dport_map_port_112=47 +dport_map_port_113=48 + +## FC1 ## +dport_map_port_5=49 + +## FC0 ## +dport_map_port_1=50 + +## FC27 ## +dport_map_port_114=51 + +## FC5 ## +dport_map_port_21=52 + +## FC2 ## +dport_map_port_9=53 + +## FC29 ## +dport_map_port_122=54 + +#for KR +#dport_map_port_66=55 +#dport_map_port_100=56 + +#/* Port Map */ +## FC10 ## +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 + +## FC12 ## +portmap_50=49:25 +portmap_51=50:25 +portmap_52=51:25 +portmap_53=52:25 + + +## FC13 ## +portmap_54=53:25 +portmap_55=54:25 +portmap_56=55:25 +portmap_57=56:25 + +## FC16 ## +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 + + +## FC8 ## +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 + +## FC9 ## +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 + +## FC17 ## +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 + +## FC20 ## +portmap_84=81:25 +portmap_85=82:25 +portmap_86=83:25 +portmap_87=84:25 + + +## FC21 ## +portmap_88=85:25 +portmap_89=86:25 +portmap_90=87:25 +portmap_91=88:25 + +## FC24 ## +portmap_102=97:25 +portmap_103=98:25 +portmap_104=99:25 +portmap_105=100:25 + +## FC25 ## +portmap_106=101:25 +portmap_107=102:25 +portmap_108=103:25 +portmap_109=104:25 + +## FC26 ## +portmap_110=105:25 +portmap_111=106:25 +portmap_112=107:25 +portmap_113=108:25 + +## FC1 ## +portmap_5=5:100 + +## FC0 ## +portmap_1=1:100 + +## FC27 ## +portmap_114=109:100 + +## FC5 ## +portmap_21=21:100 + +## FC2 ## +portmap_9=9:100 + +## FC29 ## +portmap_122=117:100 + +# CPU to MAC +# TSC-E management port 1 +#portmap_66=129:10 +# TSC-E management port 2 +#portmap_100=131:10 + +xgxs_rx_lane_map_42=0x2310 +xgxs_rx_lane_map_43=0x2310 +xgxs_rx_lane_map_44=0x2310 +xgxs_rx_lane_map_45=0x2310 +xgxs_rx_lane_map_50=0x3210 +xgxs_rx_lane_map_51=0x3210 +xgxs_rx_lane_map_52=0x3210 +xgxs_rx_lane_map_53=0x3210 +xgxs_rx_lane_map_54=0x3210 +xgxs_rx_lane_map_55=0x3210 +xgxs_rx_lane_map_56=0x3210 +xgxs_rx_lane_map_57=0x3210 +xgxs_rx_lane_map_68=0x0123 +xgxs_rx_lane_map_69=0x0123 +xgxs_rx_lane_map_70=0x0123 +xgxs_rx_lane_map_71=0x0123 +xgxs_rx_lane_map_34=0x0123 +xgxs_rx_lane_map_35=0x0123 +xgxs_rx_lane_map_36=0x0123 +xgxs_rx_lane_map_37=0x0123 +xgxs_rx_lane_map_38=0x0123 +xgxs_rx_lane_map_39=0x0123 +xgxs_rx_lane_map_40=0x0123 +xgxs_rx_lane_map_41=0x0123 +xgxs_rx_lane_map_72=0x3210 +xgxs_rx_lane_map_73=0x3210 +xgxs_rx_lane_map_74=0x3210 +xgxs_rx_lane_map_75=0x3210 +xgxs_rx_lane_map_84=0x1032 +xgxs_rx_lane_map_85=0x1032 +xgxs_rx_lane_map_86=0x1032 +xgxs_rx_lane_map_87=0x1032 +xgxs_rx_lane_map_88=0x2301 +xgxs_rx_lane_map_89=0x2301 +xgxs_rx_lane_map_90=0x2301 +xgxs_rx_lane_map_91=0x2301 +xgxs_rx_lane_map_102=0x0123 +xgxs_rx_lane_map_103=0x0123 +xgxs_rx_lane_map_104=0x0123 +xgxs_rx_lane_map_105=0x0123 +xgxs_rx_lane_map_106=0x3210 +xgxs_rx_lane_map_107=0x3210 +xgxs_rx_lane_map_108=0x3210 +xgxs_rx_lane_map_109=0x3210 +xgxs_rx_lane_map_110=0x1032 +xgxs_rx_lane_map_111=0x1032 +xgxs_rx_lane_map_112=0x1032 +xgxs_rx_lane_map_113=0x1032 +xgxs_rx_lane_map_5=0x3210 +xgxs_rx_lane_map_1=0x3210 +xgxs_rx_lane_map_114=0x0123 +xgxs_rx_lane_map_21=0x0213 +xgxs_rx_lane_map_9=0x3210 +xgxs_rx_lane_map_122=0x1230 + +xgxs_tx_lane_map_42=0x0132 +xgxs_tx_lane_map_43=0x0132 +xgxs_tx_lane_map_44=0x0132 +xgxs_tx_lane_map_45=0x0132 +xgxs_tx_lane_map_50=0x3210 +xgxs_tx_lane_map_51=0x3210 +xgxs_tx_lane_map_52=0x3210 +xgxs_tx_lane_map_53=0x3210 +xgxs_tx_lane_map_54=0x3210 +xgxs_tx_lane_map_55=0x3210 +xgxs_tx_lane_map_56=0x3210 +xgxs_tx_lane_map_57=0x3210 +xgxs_tx_lane_map_68=0x0123 +xgxs_tx_lane_map_69=0x0123 +xgxs_tx_lane_map_70=0x0123 +xgxs_tx_lane_map_71=0x0123 +xgxs_tx_lane_map_34=0x0123 +xgxs_tx_lane_map_35=0x0123 +xgxs_tx_lane_map_36=0x0123 +xgxs_tx_lane_map_37=0x0123 +xgxs_tx_lane_map_38=0x0123 +xgxs_tx_lane_map_39=0x0123 +xgxs_tx_lane_map_40=0x0123 +xgxs_tx_lane_map_41=0x0123 +xgxs_tx_lane_map_72=0x0123 +xgxs_tx_lane_map_73=0x0123 +xgxs_tx_lane_map_74=0x0123 +xgxs_tx_lane_map_75=0x0123 +xgxs_tx_lane_map_84=0x0123 +xgxs_tx_lane_map_85=0x0123 +xgxs_tx_lane_map_86=0x0123 +xgxs_tx_lane_map_87=0x0123 +xgxs_tx_lane_map_88=0x2301 +xgxs_tx_lane_map_89=0x2301 +xgxs_tx_lane_map_90=0x2301 +xgxs_tx_lane_map_91=0x2301 +xgxs_tx_lane_map_102=0x0123 +xgxs_tx_lane_map_103=0x0123 +xgxs_tx_lane_map_104=0x0123 +xgxs_tx_lane_map_105=0x0123 +xgxs_tx_lane_map_106=0x3210 +xgxs_tx_lane_map_107=0x3210 +xgxs_tx_lane_map_108=0x3210 +xgxs_tx_lane_map_109=0x3210 +xgxs_tx_lane_map_110=0x1032 +xgxs_tx_lane_map_111=0x1032 +xgxs_tx_lane_map_112=0x1032 +xgxs_tx_lane_map_113=0x1032 +xgxs_tx_lane_map_5=0x3210 +xgxs_tx_lane_map_1=0x3210 +xgxs_tx_lane_map_114=0x0123 +xgxs_tx_lane_map_21=0x3210 +xgxs_tx_lane_map_9=0x3210 +xgxs_tx_lane_map_122=0x3210 + +#Polarity RX +phy_xaui_rx_polarity_flip_34=0x1 +phy_xaui_rx_polarity_flip_35=0x1 +phy_xaui_rx_polarity_flip_36=0x1 +phy_xaui_rx_polarity_flip_37=0x1 +phy_xaui_rx_polarity_flip_38=0x1 +phy_xaui_rx_polarity_flip_39=0x1 +phy_xaui_rx_polarity_flip_40=0x1 +phy_xaui_rx_polarity_flip_41=0x1 +phy_xaui_rx_polarity_flip_84=0x1 +phy_xaui_rx_polarity_flip_85=0x0 +phy_xaui_rx_polarity_flip_86=0x1 +phy_xaui_rx_polarity_flip_87=0x0 +phy_xaui_rx_polarity_flip_88=0x1 +phy_xaui_rx_polarity_flip_89=0x0 +phy_xaui_rx_polarity_flip_90=0x1 +phy_xaui_rx_polarity_flip_91=0x1 +phy_xaui_rx_polarity_flip_102=0x0 +phy_xaui_rx_polarity_flip_103=0x0 +phy_xaui_rx_polarity_flip_104=0x1 +phy_xaui_rx_polarity_flip_105=0x0 +phy_xaui_rx_polarity_flip_122=0xf +#Polarity TX +phy_xaui_tx_polarity_flip_42=0x1 +phy_xaui_tx_polarity_flip_43=0x1 +phy_xaui_tx_polarity_flip_44=0x1 +phy_xaui_tx_polarity_flip_45=0x1 +phy_xaui_tx_polarity_flip_34=0x1 +phy_xaui_tx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_36=0x1 +phy_xaui_tx_polarity_flip_37=0x1 +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_tx_polarity_flip_39=0x1 +phy_xaui_tx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0x1 +phy_xaui_tx_polarity_flip_72=0x1 +phy_xaui_tx_polarity_flip_73=0x1 +phy_xaui_tx_polarity_flip_74=0x1 +phy_xaui_tx_polarity_flip_75=0x1 +phy_xaui_tx_polarity_flip_84=0x1 +phy_xaui_tx_polarity_flip_85=0x1 +phy_xaui_tx_polarity_flip_86=0x1 +phy_xaui_tx_polarity_flip_87=0x1 +phy_xaui_tx_polarity_flip_88=0x1 +phy_xaui_tx_polarity_flip_89=0x1 +phy_xaui_tx_polarity_flip_90=0x1 +phy_xaui_tx_polarity_flip_91=0x1 +phy_xaui_tx_polarity_flip_102=0x1 +phy_xaui_tx_polarity_flip_103=0x1 +phy_xaui_tx_polarity_flip_104=0x1 +phy_xaui_tx_polarity_flip_105=0x1 +phy_xaui_tx_polarity_flip_122=0xb + +#Driver Current +serdes_driver_current_42=0x8 +serdes_driver_current_43=0x8 +serdes_driver_current_44=0x8 +serdes_driver_current_45=0x8 +serdes_driver_current_50=0x8 +serdes_driver_current_51=0x8 +serdes_driver_current_52=0x8 +serdes_driver_current_53=0x8 +serdes_driver_current_54=0x8 +serdes_driver_current_55=0x8 +serdes_driver_current_56=0x8 +serdes_driver_current_57=0x8 +serdes_driver_current_68=0x8 +serdes_driver_current_69=0x8 +serdes_driver_current_70=0x8 +serdes_driver_current_71=0x8 +serdes_driver_current_34=0x8 +serdes_driver_current_35=0x8 +serdes_driver_current_36=0x8 +serdes_driver_current_37=0x8 +serdes_driver_current_38=0x8 +serdes_driver_current_39=0x8 +serdes_driver_current_40=0x8 +serdes_driver_current_41=0x8 +serdes_driver_current_72=0x8 +serdes_driver_current_73=0x8 +serdes_driver_current_74=0x8 +serdes_driver_current_75=0x8 +serdes_driver_current_84=0x8 +serdes_driver_current_85=0x8 +serdes_driver_current_86=0x8 +serdes_driver_current_87=0x8 +serdes_driver_current_88=0x8 +serdes_driver_current_89=0x8 +serdes_driver_current_90=0x8 +serdes_driver_current_91=0x8 +serdes_driver_current_102=0x8 +serdes_driver_current_103=0x8 +serdes_driver_current_104=0x8 +serdes_driver_current_105=0x8 +serdes_driver_current_106=0x8 +serdes_driver_current_107=0x8 +serdes_driver_current_108=0x8 +serdes_driver_current_109=0x8 +serdes_driver_current_110=0x8 +serdes_driver_current_111=0x8 +serdes_driver_current_112=0x8 +serdes_driver_current_113=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 + +#Preemphasis +serdes_preemphasis_42=0x264006 +serdes_preemphasis_43=0x264006 +serdes_preemphasis_44=0x254106 +serdes_preemphasis_45=0x254106 +serdes_preemphasis_50=0x254106 +serdes_preemphasis_51=0x254106 +serdes_preemphasis_52=0x254106 +serdes_preemphasis_53=0x254106 +serdes_preemphasis_54=0x254106 +serdes_preemphasis_55=0x254106 +serdes_preemphasis_56=0x254106 +serdes_preemphasis_57=0x234306 +serdes_preemphasis_68=0x234306 +serdes_preemphasis_69=0x204606 +serdes_preemphasis_70=0x204606 +serdes_preemphasis_71=0x204606 +serdes_preemphasis_34=0x234306 +serdes_preemphasis_35=0x234306 +serdes_preemphasis_36=0x234306 +serdes_preemphasis_37=0x234306 +serdes_preemphasis_38=0x234306 +serdes_preemphasis_39=0x234306 +serdes_preemphasis_40=0x234306 +serdes_preemphasis_41=0x234306 +serdes_preemphasis_72=0x1e4806 +serdes_preemphasis_73=0x1e4806 +serdes_preemphasis_74=0x1e4806 +serdes_preemphasis_75=0x1e4806 +serdes_preemphasis_84=0x1e4806 +serdes_preemphasis_85=0x1a4c06 +serdes_preemphasis_86=0x1a4c06 +serdes_preemphasis_87=0x1b4b06 +serdes_preemphasis_88=0x1b4b06 +serdes_preemphasis_89=0x1e4806 +serdes_preemphasis_90=0x1e4806 +serdes_preemphasis_91=0x1e4806 +serdes_preemphasis_102=0x1e4806 +serdes_preemphasis_103=0x1e4806 +serdes_preemphasis_104=0x1e4806 +serdes_preemphasis_105=0x1e4806 +serdes_preemphasis_106=0x1e4806 +serdes_preemphasis_107=0x1e4806 +serdes_preemphasis_108=0x1e4806 +serdes_preemphasis_109=0x1e4806 +serdes_preemphasis_110=0x1e4806 +serdes_preemphasis_111=0x1d4906 +serdes_preemphasis_112=0x234306 +serdes_preemphasis_113=0x1f4706 +serdes_preemphasis_lane0_5=0x294106 +serdes_preemphasis_lane1_5=0x294106 +serdes_preemphasis_lane2_5=0x294106 +serdes_preemphasis_lane3_5=0x294106 +serdes_preemphasis_lane0_1=0x294106 +serdes_preemphasis_lane1_1=0x294106 +serdes_preemphasis_lane2_1=0x294106 +serdes_preemphasis_lane3_1=0x294106 +serdes_preemphasis_lane0_114=0x2a4006 +serdes_preemphasis_lane1_114=0x2a4006 +serdes_preemphasis_lane2_114=0x2a4006 +serdes_preemphasis_lane3_114=0x2a4006 +serdes_preemphasis_lane0_21=0x2c3c08 +serdes_preemphasis_lane1_21=0x2a4006 +serdes_preemphasis_lane2_21=0x2a4006 +serdes_preemphasis_lane3_21=0x2a4006 +serdes_preemphasis_lane0_9=0x284206 +serdes_preemphasis_lane1_9=0x284206 +serdes_preemphasis_lane2_9=0x284206 +serdes_preemphasis_lane3_9=0x284206 +serdes_preemphasis_lane0_122=0x283e06 +serdes_preemphasis_lane1_122=0x283e06 +serdes_preemphasis_lane2_122=0x283e06 +serdes_preemphasis_lane3_122=0x294601 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/default_sku b/device/accton/x86_64-accton_as7312_54xs-r0/default_sku new file mode 100644 index 000000000000..9e6062dee23b --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7312-54XS t1 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/installer.conf b/device/accton/x86_64-accton_as7312_54xs-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7312_54xs-r0/led_proc_init.soc new file mode 100755 index 000000000000..3074649497e0 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/led_proc_init.soc @@ -0,0 +1,79 @@ +# accton_as7312_54x 48x25G+6x100G SDK port LED macro init SOC +s CMIC_LEDUP0_DATA_RAM 0 +s CMIC_LEDUP1_DATA_RAM 0 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=63 REMAP_PORT_2=63 REMAP_PORT_3=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=63 REMAP_PORT_5=63 REMAP_PORT_6=63 REMAP_PORT_7=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=27 REMAP_PORT_9=26 REMAP_PORT_10=25 REMAP_PORT_11=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=63 REMAP_PORT_18=63 REMAP_PORT_19=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 REMAP_PORT_21=30 REMAP_PORT_22=29 REMAP_PORT_23=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=15 REMAP_PORT_25=14 REMAP_PORT_26=13 REMAP_PORT_27=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=19 REMAP_PORT_29=18 REMAP_PORT_30=17 REMAP_PORT_31=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=63 REMAP_PORT_34=63 REMAP_PORT_35=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=63 REMAP_PORT_37=63 REMAP_PORT_38=63 REMAP_PORT_39=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 REMAP_PORT_41=34 REMAP_PORT_42=33 REMAP_PORT_43=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=23 REMAP_PORT_49=22 REMAP_PORT_50=21 REMAP_PORT_51=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=19 REMAP_PORT_1=18 REMAP_PORT_2=17 REMAP_PORT_3=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=23 REMAP_PORT_5=22 REMAP_PORT_6=21 REMAP_PORT_7=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 REMAP_PORT_9=2 REMAP_PORT_10=1 REMAP_PORT_11=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=7 REMAP_PORT_17=6 REMAP_PORT_18=5 REMAP_PORT_19=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 REMAP_PORT_25=63 REMAP_PORT_26=63 REMAP_PORT_27=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 REMAP_PORT_29=63 REMAP_PORT_30=63 REMAP_PORT_31=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=15 REMAP_PORT_33=14 REMAP_PORT_34=13 REMAP_PORT_35=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=63 REMAP_PORT_41=63 REMAP_PORT_42=63 REMAP_PORT_43=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 REMAP_PORT_45=63 REMAP_PORT_46=63 REMAP_PORT_47=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=31 REMAP_PORT_49=30 REMAP_PORT_50=29 REMAP_PORT_51=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=35 REMAP_PORT_53=34 REMAP_PORT_54=33 REMAP_PORT_55=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=63 REMAP_PORT_57=63 REMAP_PORT_58=63 REMAP_PORT_59=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=63 REMAP_PORT_62=63 REMAP_PORT_63=63 + +led 0 stop +led 0 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start +led auto on + +led 1 stop +led 1 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 7E \ + 02 FB 42 24 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start +led auto on diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/eeprom.py new file mode 100644 index 000000000000..951384d5e37d --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/psuutil.py new file mode 100644 index 000000000000..a47dfcab7e94 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 2: "11-0053", + 1: "10-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/sfputil.py new file mode 100644 index 000000000000..7d700fdaf90e --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/plugins/sfputil.py @@ -0,0 +1,246 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + 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 = 54 + PORTS_IN_BLOCK = 54 + QSFP_PORT_START = 49 + QSFP_PORT_END = 54 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _cpld_mapping = { + 0: "4-0060", + 1: "5-0062", + 2: "6-0064", + } + _port_to_i2c_mapping = { + 1: 18, + 2: 19, + 3: 20, + 4: 21, + 5: 22, + 6: 23, + 7: 24, + 8: 25, + 9: 26, + 10: 27, + 11: 28, + 12: 29, + 13: 30, + 14: 31, + 15: 32, + 16: 33, + 17: 34, + 18: 35, + 19: 36, + 20: 37, + 21: 38, + 22: 39, + 23: 40, + 24: 41, + 25: 42, + 26: 43, + 27: 44, + 28: 45, + 29: 46, + 30: 47, + 31: 48, + 32: 49, + 33: 50, + 34: 51, + 35: 52, + 36: 53, + 37: 54, + 38: 55, + 39: 56, + 40: 57, + 41: 58, + 42: 59, + 43: 60, + 44: 61, + 45: 62, + 46: 63, + 47: 64, + 48: 65, + 49: 66, # QSFP49 + 50: 67, + 51: 68, + 52: 69, + 53: 70, + 54: 71, # QSFP54 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + + SfpUtilBase.__init__(self) + + def get_cpld_num(self, port_num): + cpld_i = 1 + if (port_num > 24 and port_num < self.qsfp_port_start): + cpld_i = 2 + + if (port_num > 52): + cpld_i = 2 + + return cpld_i + + 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 + + cpld_i = self.get_cpld_num(port_num) + + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_present_{1}" + port_ps = path.format(cpld_ps, port_num) + + content = "0" + try: + val_file = open(port_ps) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + 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.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cpld_i = self.get_cpld_num(port_num) + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_reset_{1}" + port_ps = path.format(cpld_ps, 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_value = '0' + + reg_file.write(reg_value) + reg_file.close() + + return True + + 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 diff --git a/device/accton/x86_64-accton_as7312_54xs-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7312_54xs-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7312_54xs-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini new file mode 100644 index 000000000000..26d49cdde58c --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/port_config.ini @@ -0,0 +1,28 @@ +# name lanes alias index speed +Ethernet0 28 twentyfiveGigE1 1 25000 +Ethernet1 29 twentyfiveGigE2 2 25000 +Ethernet2 30 twentyfiveGigE3 3 25000 +Ethernet3 31 twentyfiveGigE4 4 25000 +Ethernet4 24 twentyfiveGigE5 5 10000 +Ethernet5 25 twentyfiveGigE6 6 10000 +Ethernet6 26 twentyfiveGigE7 7 10000 +Ethernet7 27 twentyfiveGigE8 8 10000 +Ethernet8 20 twentyfiveGigE9 9 10000 +Ethernet9 21 twentyfiveGigE10 10 10000 +Ethernet10 22 twentyfiveGigE11 11 10000 +Ethernet11 23 twentyfiveGigE12 12 10000 +Ethernet12 16 twentyfiveGigE13 13 10000 +Ethernet13 17 twentyfiveGigE14 14 10000 +Ethernet14 18 twentyfiveGigE15 15 10000 +Ethernet15 19 twentyfiveGigE16 16 10000 +Ethernet16 4 twentyfiveGigE17 17 10000 +Ethernet17 5 twentyfiveGigE18 18 10000 +Ethernet18 6 twentyfiveGigE19 19 10000 +Ethernet19 7 twentyfiveGigE20 20 10000 +Ethernet20 0 twentyfiveGigE21 21 10000 +Ethernet21 1 twentyfiveGigE22 22 10000 +Ethernet22 2 twentyfiveGigE23 23 10000 +Ethernet23 3 twentyfiveGigE24 24 10000 +Ethernet24 67,68,69,70 twentyfiveGigE25 25 100000 +Ethernet25 71,72,73,74 twentyfiveGigE26 26 100000 +Ethernet26 75,76,77,78 twentyfiveGigE27 27 100000 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/qax-as7315-20x10G+4x25G+3x100G.config.bcm b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/qax-as7315-20x10G+4x25G+3x100G.config.bcm new file mode 100644 index 000000000000..0ac6051b1ad4 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/qax-as7315-20x10G+4x25G+3x100G.config.bcm @@ -0,0 +1,519 @@ +# accton_as7312_54x 48x25G+6x100G SDK config +os=unix +schan_intr_enable=0 + +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x0407ffc00ff00ff003fc3ffc00200222 +pbmp_xport_xe=0x0407ffd00ff00ff403fc3ffc00200222 + +## FC10 ## +dport_map_port_42=1 +dport_map_port_43=2 +dport_map_port_44=3 +dport_map_port_45=4 + +## FC12 ## +dport_map_port_50=5 +dport_map_port_51=6 +dport_map_port_52=7 +dport_map_port_53=8 + +## FC13 ## +dport_map_port_54=9 +dport_map_port_55=10 +dport_map_port_56=11 +dport_map_port_57=12 + +## FC16 ## +dport_map_port_68=13 +dport_map_port_69=14 +dport_map_port_70=15 +dport_map_port_71=16 + +## FC8 ## +dport_map_port_34=17 +dport_map_port_35=18 +dport_map_port_36=19 +dport_map_port_37=20 + +## FC9 ## +dport_map_port_38=21 +dport_map_port_39=22 +dport_map_port_40=23 +dport_map_port_41=24 + +## FC17 ## +dport_map_port_72=25 +dport_map_port_73=26 +dport_map_port_74=27 +dport_map_port_75=28 + +## FC20 ## +dport_map_port_84=29 +dport_map_port_85=30 +dport_map_port_86=31 +dport_map_port_87=32 + +## FC21 ## +dport_map_port_88=33 +dport_map_port_89=34 +dport_map_port_90=35 +dport_map_port_91=36 + +## FC24 ## +dport_map_port_102=37 +dport_map_port_103=38 +dport_map_port_104=39 +dport_map_port_105=40 + +## FC25 ## +dport_map_port_106=41 +dport_map_port_107=42 +dport_map_port_108=43 +dport_map_port_109=44 + +## FC26 ## +dport_map_port_110=45 +dport_map_port_111=46 +dport_map_port_112=47 +dport_map_port_113=48 + +## FC1 ## +dport_map_port_5=49 + +## FC0 ## +dport_map_port_1=50 + +## FC27 ## +dport_map_port_114=51 + +## FC5 ## +dport_map_port_21=52 + +## FC2 ## +dport_map_port_9=53 + +## FC29 ## +dport_map_port_122=54 + +#for KR +#dport_map_port_66=55 +#dport_map_port_100=56 + +#/* Port Map */ +## FC10 ## +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 + +## FC12 ## +portmap_50=49:25 +portmap_51=50:25 +portmap_52=51:25 +portmap_53=52:25 + + +## FC13 ## +portmap_54=53:25 +portmap_55=54:25 +portmap_56=55:25 +portmap_57=56:25 + +## FC16 ## +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 + + +## FC8 ## +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 + +## FC9 ## +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 + +## FC17 ## +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 + +## FC20 ## +portmap_84=81:25 +portmap_85=82:25 +portmap_86=83:25 +portmap_87=84:25 + + +## FC21 ## +portmap_88=85:25 +portmap_89=86:25 +portmap_90=87:25 +portmap_91=88:25 + +## FC24 ## +portmap_102=97:25 +portmap_103=98:25 +portmap_104=99:25 +portmap_105=100:25 + +## FC25 ## +portmap_106=101:25 +portmap_107=102:25 +portmap_108=103:25 +portmap_109=104:25 + +## FC26 ## +portmap_110=105:25 +portmap_111=106:25 +portmap_112=107:25 +portmap_113=108:25 + +## FC1 ## +portmap_5=5:100 + +## FC0 ## +portmap_1=1:100 + +## FC27 ## +portmap_114=109:100 + +## FC5 ## +portmap_21=21:100 + +## FC2 ## +portmap_9=9:100 + +## FC29 ## +portmap_122=117:100 + +# CPU to MAC +# TSC-E management port 1 +#portmap_66=129:10 +# TSC-E management port 2 +#portmap_100=131:10 + +xgxs_rx_lane_map_42=0x2310 +xgxs_rx_lane_map_43=0x2310 +xgxs_rx_lane_map_44=0x2310 +xgxs_rx_lane_map_45=0x2310 +xgxs_rx_lane_map_50=0x3210 +xgxs_rx_lane_map_51=0x3210 +xgxs_rx_lane_map_52=0x3210 +xgxs_rx_lane_map_53=0x3210 +xgxs_rx_lane_map_54=0x3210 +xgxs_rx_lane_map_55=0x3210 +xgxs_rx_lane_map_56=0x3210 +xgxs_rx_lane_map_57=0x3210 +xgxs_rx_lane_map_68=0x0123 +xgxs_rx_lane_map_69=0x0123 +xgxs_rx_lane_map_70=0x0123 +xgxs_rx_lane_map_71=0x0123 +xgxs_rx_lane_map_34=0x0123 +xgxs_rx_lane_map_35=0x0123 +xgxs_rx_lane_map_36=0x0123 +xgxs_rx_lane_map_37=0x0123 +xgxs_rx_lane_map_38=0x0123 +xgxs_rx_lane_map_39=0x0123 +xgxs_rx_lane_map_40=0x0123 +xgxs_rx_lane_map_41=0x0123 +xgxs_rx_lane_map_72=0x3210 +xgxs_rx_lane_map_73=0x3210 +xgxs_rx_lane_map_74=0x3210 +xgxs_rx_lane_map_75=0x3210 +xgxs_rx_lane_map_84=0x1032 +xgxs_rx_lane_map_85=0x1032 +xgxs_rx_lane_map_86=0x1032 +xgxs_rx_lane_map_87=0x1032 +xgxs_rx_lane_map_88=0x2301 +xgxs_rx_lane_map_89=0x2301 +xgxs_rx_lane_map_90=0x2301 +xgxs_rx_lane_map_91=0x2301 +xgxs_rx_lane_map_102=0x0123 +xgxs_rx_lane_map_103=0x0123 +xgxs_rx_lane_map_104=0x0123 +xgxs_rx_lane_map_105=0x0123 +xgxs_rx_lane_map_106=0x3210 +xgxs_rx_lane_map_107=0x3210 +xgxs_rx_lane_map_108=0x3210 +xgxs_rx_lane_map_109=0x3210 +xgxs_rx_lane_map_110=0x1032 +xgxs_rx_lane_map_111=0x1032 +xgxs_rx_lane_map_112=0x1032 +xgxs_rx_lane_map_113=0x1032 +xgxs_rx_lane_map_5=0x3210 +xgxs_rx_lane_map_1=0x3210 +xgxs_rx_lane_map_114=0x0123 +xgxs_rx_lane_map_21=0x0213 +xgxs_rx_lane_map_9=0x3210 +xgxs_rx_lane_map_122=0x1230 + +xgxs_tx_lane_map_42=0x0132 +xgxs_tx_lane_map_43=0x0132 +xgxs_tx_lane_map_44=0x0132 +xgxs_tx_lane_map_45=0x0132 +xgxs_tx_lane_map_50=0x3210 +xgxs_tx_lane_map_51=0x3210 +xgxs_tx_lane_map_52=0x3210 +xgxs_tx_lane_map_53=0x3210 +xgxs_tx_lane_map_54=0x3210 +xgxs_tx_lane_map_55=0x3210 +xgxs_tx_lane_map_56=0x3210 +xgxs_tx_lane_map_57=0x3210 +xgxs_tx_lane_map_68=0x0123 +xgxs_tx_lane_map_69=0x0123 +xgxs_tx_lane_map_70=0x0123 +xgxs_tx_lane_map_71=0x0123 +xgxs_tx_lane_map_34=0x0123 +xgxs_tx_lane_map_35=0x0123 +xgxs_tx_lane_map_36=0x0123 +xgxs_tx_lane_map_37=0x0123 +xgxs_tx_lane_map_38=0x0123 +xgxs_tx_lane_map_39=0x0123 +xgxs_tx_lane_map_40=0x0123 +xgxs_tx_lane_map_41=0x0123 +xgxs_tx_lane_map_72=0x0123 +xgxs_tx_lane_map_73=0x0123 +xgxs_tx_lane_map_74=0x0123 +xgxs_tx_lane_map_75=0x0123 +xgxs_tx_lane_map_84=0x0123 +xgxs_tx_lane_map_85=0x0123 +xgxs_tx_lane_map_86=0x0123 +xgxs_tx_lane_map_87=0x0123 +xgxs_tx_lane_map_88=0x2301 +xgxs_tx_lane_map_89=0x2301 +xgxs_tx_lane_map_90=0x2301 +xgxs_tx_lane_map_91=0x2301 +xgxs_tx_lane_map_102=0x0123 +xgxs_tx_lane_map_103=0x0123 +xgxs_tx_lane_map_104=0x0123 +xgxs_tx_lane_map_105=0x0123 +xgxs_tx_lane_map_106=0x3210 +xgxs_tx_lane_map_107=0x3210 +xgxs_tx_lane_map_108=0x3210 +xgxs_tx_lane_map_109=0x3210 +xgxs_tx_lane_map_110=0x1032 +xgxs_tx_lane_map_111=0x1032 +xgxs_tx_lane_map_112=0x1032 +xgxs_tx_lane_map_113=0x1032 +xgxs_tx_lane_map_5=0x3210 +xgxs_tx_lane_map_1=0x3210 +xgxs_tx_lane_map_114=0x0123 +xgxs_tx_lane_map_21=0x3210 +xgxs_tx_lane_map_9=0x3210 +xgxs_tx_lane_map_122=0x3210 + +#Polarity RX +phy_xaui_rx_polarity_flip_34=0x1 +phy_xaui_rx_polarity_flip_35=0x1 +phy_xaui_rx_polarity_flip_36=0x1 +phy_xaui_rx_polarity_flip_37=0x1 +phy_xaui_rx_polarity_flip_38=0x1 +phy_xaui_rx_polarity_flip_39=0x1 +phy_xaui_rx_polarity_flip_40=0x1 +phy_xaui_rx_polarity_flip_41=0x1 +phy_xaui_rx_polarity_flip_84=0x1 +phy_xaui_rx_polarity_flip_85=0x0 +phy_xaui_rx_polarity_flip_86=0x1 +phy_xaui_rx_polarity_flip_87=0x0 +phy_xaui_rx_polarity_flip_88=0x1 +phy_xaui_rx_polarity_flip_89=0x0 +phy_xaui_rx_polarity_flip_90=0x1 +phy_xaui_rx_polarity_flip_91=0x1 +phy_xaui_rx_polarity_flip_102=0x0 +phy_xaui_rx_polarity_flip_103=0x0 +phy_xaui_rx_polarity_flip_104=0x1 +phy_xaui_rx_polarity_flip_105=0x0 +phy_xaui_rx_polarity_flip_122=0xf +#Polarity TX +phy_xaui_tx_polarity_flip_42=0x1 +phy_xaui_tx_polarity_flip_43=0x1 +phy_xaui_tx_polarity_flip_44=0x1 +phy_xaui_tx_polarity_flip_45=0x1 +phy_xaui_tx_polarity_flip_34=0x1 +phy_xaui_tx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_36=0x1 +phy_xaui_tx_polarity_flip_37=0x1 +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_tx_polarity_flip_39=0x1 +phy_xaui_tx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0x1 +phy_xaui_tx_polarity_flip_72=0x1 +phy_xaui_tx_polarity_flip_73=0x1 +phy_xaui_tx_polarity_flip_74=0x1 +phy_xaui_tx_polarity_flip_75=0x1 +phy_xaui_tx_polarity_flip_84=0x1 +phy_xaui_tx_polarity_flip_85=0x1 +phy_xaui_tx_polarity_flip_86=0x1 +phy_xaui_tx_polarity_flip_87=0x1 +phy_xaui_tx_polarity_flip_88=0x1 +phy_xaui_tx_polarity_flip_89=0x1 +phy_xaui_tx_polarity_flip_90=0x1 +phy_xaui_tx_polarity_flip_91=0x1 +phy_xaui_tx_polarity_flip_102=0x1 +phy_xaui_tx_polarity_flip_103=0x1 +phy_xaui_tx_polarity_flip_104=0x1 +phy_xaui_tx_polarity_flip_105=0x1 +phy_xaui_tx_polarity_flip_122=0xb + +#Driver Current +serdes_driver_current_42=0x8 +serdes_driver_current_43=0x8 +serdes_driver_current_44=0x8 +serdes_driver_current_45=0x8 +serdes_driver_current_50=0x8 +serdes_driver_current_51=0x8 +serdes_driver_current_52=0x8 +serdes_driver_current_53=0x8 +serdes_driver_current_54=0x8 +serdes_driver_current_55=0x8 +serdes_driver_current_56=0x8 +serdes_driver_current_57=0x8 +serdes_driver_current_68=0x8 +serdes_driver_current_69=0x8 +serdes_driver_current_70=0x8 +serdes_driver_current_71=0x8 +serdes_driver_current_34=0x8 +serdes_driver_current_35=0x8 +serdes_driver_current_36=0x8 +serdes_driver_current_37=0x8 +serdes_driver_current_38=0x8 +serdes_driver_current_39=0x8 +serdes_driver_current_40=0x8 +serdes_driver_current_41=0x8 +serdes_driver_current_72=0x8 +serdes_driver_current_73=0x8 +serdes_driver_current_74=0x8 +serdes_driver_current_75=0x8 +serdes_driver_current_84=0x8 +serdes_driver_current_85=0x8 +serdes_driver_current_86=0x8 +serdes_driver_current_87=0x8 +serdes_driver_current_88=0x8 +serdes_driver_current_89=0x8 +serdes_driver_current_90=0x8 +serdes_driver_current_91=0x8 +serdes_driver_current_102=0x8 +serdes_driver_current_103=0x8 +serdes_driver_current_104=0x8 +serdes_driver_current_105=0x8 +serdes_driver_current_106=0x8 +serdes_driver_current_107=0x8 +serdes_driver_current_108=0x8 +serdes_driver_current_109=0x8 +serdes_driver_current_110=0x8 +serdes_driver_current_111=0x8 +serdes_driver_current_112=0x8 +serdes_driver_current_113=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 + +#Preemphasis +serdes_preemphasis_42=0x264006 +serdes_preemphasis_43=0x264006 +serdes_preemphasis_44=0x254106 +serdes_preemphasis_45=0x254106 +serdes_preemphasis_50=0x254106 +serdes_preemphasis_51=0x254106 +serdes_preemphasis_52=0x254106 +serdes_preemphasis_53=0x254106 +serdes_preemphasis_54=0x254106 +serdes_preemphasis_55=0x254106 +serdes_preemphasis_56=0x254106 +serdes_preemphasis_57=0x234306 +serdes_preemphasis_68=0x234306 +serdes_preemphasis_69=0x204606 +serdes_preemphasis_70=0x204606 +serdes_preemphasis_71=0x204606 +serdes_preemphasis_34=0x234306 +serdes_preemphasis_35=0x234306 +serdes_preemphasis_36=0x234306 +serdes_preemphasis_37=0x234306 +serdes_preemphasis_38=0x234306 +serdes_preemphasis_39=0x234306 +serdes_preemphasis_40=0x234306 +serdes_preemphasis_41=0x234306 +serdes_preemphasis_72=0x1e4806 +serdes_preemphasis_73=0x1e4806 +serdes_preemphasis_74=0x1e4806 +serdes_preemphasis_75=0x1e4806 +serdes_preemphasis_84=0x1e4806 +serdes_preemphasis_85=0x1a4c06 +serdes_preemphasis_86=0x1a4c06 +serdes_preemphasis_87=0x1b4b06 +serdes_preemphasis_88=0x1b4b06 +serdes_preemphasis_89=0x1e4806 +serdes_preemphasis_90=0x1e4806 +serdes_preemphasis_91=0x1e4806 +serdes_preemphasis_102=0x1e4806 +serdes_preemphasis_103=0x1e4806 +serdes_preemphasis_104=0x1e4806 +serdes_preemphasis_105=0x1e4806 +serdes_preemphasis_106=0x1e4806 +serdes_preemphasis_107=0x1e4806 +serdes_preemphasis_108=0x1e4806 +serdes_preemphasis_109=0x1e4806 +serdes_preemphasis_110=0x1e4806 +serdes_preemphasis_111=0x1d4906 +serdes_preemphasis_112=0x234306 +serdes_preemphasis_113=0x1f4706 +serdes_preemphasis_lane0_5=0x294106 +serdes_preemphasis_lane1_5=0x294106 +serdes_preemphasis_lane2_5=0x294106 +serdes_preemphasis_lane3_5=0x294106 +serdes_preemphasis_lane0_1=0x294106 +serdes_preemphasis_lane1_1=0x294106 +serdes_preemphasis_lane2_1=0x294106 +serdes_preemphasis_lane3_1=0x294106 +serdes_preemphasis_lane0_114=0x2a4006 +serdes_preemphasis_lane1_114=0x2a4006 +serdes_preemphasis_lane2_114=0x2a4006 +serdes_preemphasis_lane3_114=0x2a4006 +serdes_preemphasis_lane0_21=0x2c3c08 +serdes_preemphasis_lane1_21=0x2a4006 +serdes_preemphasis_lane2_21=0x2a4006 +serdes_preemphasis_lane3_21=0x2a4006 +serdes_preemphasis_lane0_9=0x284206 +serdes_preemphasis_lane1_9=0x284206 +serdes_preemphasis_lane2_9=0x284206 +serdes_preemphasis_lane3_9=0x284206 +serdes_preemphasis_lane0_122=0x283e06 +serdes_preemphasis_lane1_122=0x283e06 +serdes_preemphasis_lane2_122=0x283e06 +serdes_preemphasis_lane3_122=0x294601 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/sai.profile b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/sai.profile new file mode 100644 index 000000000000..551599b5eba9 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/Accton-AS7315-27XB/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/qax-as7315-20x10G+4x25G+3x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/default_sku b/device/accton/x86_64-accton_as7315_27xb-r0/default_sku new file mode 100644 index 000000000000..5c1bb0b4a47a --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7315-27XB t1 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/installer.conf b/device/accton/x86_64-accton_as7315_27xb-r0/installer.conf new file mode 100644 index 000000000000..9fa12f888545 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc new file mode 100755 index 000000000000..790ab9cfc931 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/led_proc_init.soc @@ -0,0 +1,24 @@ +# accton_as7315_27xb LED macro init SOC +######################################### +## LED program for BCM88470 Qumran-AX +######################################### +led 0 stop +led 0 prog \ + 02 FC 42 03 02 F9 42 00 02 00 67 26 67 2D 86 F9 \ + 67 2D 86 F9 67 2D 86 F9 67 2D 86 F9 06 F9 D2 24 \ + 74 0A 86 FB 3A 7E 67 59 67 41 67 69 57 67 59 67 \ + 41 67 72 1A 00 75 7B 1A 01 75 3D 77 50 67 59 77 \ + 46 12 A0 F8 15 57 80 28 32 00 32 01 B7 97 75 7F \ + 16 FB 06 FC C8 70 7F 77 7B 06 F9 C2 FC 98 98 12 \ + E0 F8 05 16 F9 CA 03 F1 57 1A 07 27 87 1A 06 27 \ + 87 57 1A 05 27 87 1A 04 27 87 57 32 0E 87 57 32 \ + 0F 87 57 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start +led auto on diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/eeprom.py new file mode 100644 index 000000000000..6f7ad9ef091d --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/4-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py new file mode 100644 index 000000000000..dbc0a1170251 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "13-0053", + 2: "12-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py new file mode 100644 index 000000000000..1a1b61d1e659 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/plugins/sfputil.py @@ -0,0 +1,254 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + import pprint + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# from xcvrd +SFP_STATUS_REMOVED = '0' +SFP_STATUS_INSERTED = '1' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 27 + PORTS_IN_BLOCK = 27 + QSFP_PORT_START = 25 + QSFP_PORT_END = 27 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _cpld_mapping = ["8-0063", "7-0064"] + + _port_to_i2c_mapping = { + 1: 26, + 2: 27, + 3: 28, + 4: 29, + 5: 30, + 6: 31, + 7: 32, + 8: 33, + 9: 34, + 10: 35, + 11: 36, + 12: 37, + 13: 38, + 14: 39, + 15: 40, + 16: 41, + 17: 42, + 18: 43, + 19: 44, + 20: 45, + 21: 46, + 22: 47, + 23: 48, + 24: 49, + 25: 21, # QSFP + 26: 22, + 27: 23, + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + + self.get_transceiver_change_event() + SfpUtilBase.__init__(self) + + def get_cpld_num(self, port_num): + cpld_i = 0 + if (port_num >= self.qsfp_port_start): + cpld_i = 1 + + return cpld_i + + 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 + + cpld_i = self.get_cpld_num(port_num) + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/present_{1}" + index = ((port_num-1) % 24) + 1 + port_ps = path.format(cpld_ps, index) + + content = "0" + try: + val_file = open(port_ps) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + 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.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + raise NotImplementedError + + @property + def _get_present_bitmap(self): + nodes = [] + port_num = [24, 3] + + path = "/sys/bus/i2c/devices/{0}/" + cpld_path = path.format(self._cpld_mapping[0]) + nodes.append((cpld_path + "module_present_all", port_num[0])) + cpld_path = path.format(self._cpld_mapping[1]) + nodes.append((cpld_path + "module_present_all", port_num[1])) + + bitmap = [] + for node in nodes: + try: + reg_file = open(node[0]) + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + cpld_bm = reg_file.readline().rstrip().zfill(node[1]/4) + bitmap.append(cpld_bm) + reg_file.close() + + rev = "".join(bitmap[::-1]) + return int(rev, 16) + + data = {'valid': 0, 'last': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + port = 0 + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + reg_value = self._get_present_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + mask = (1 << (port - 1)) + if changed_ports & mask: + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['last'] = now + self.data['valid'] = 1 + pprint.pprint(port_dict) + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/accton/x86_64-accton_as7315_27xb-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7315_27xb-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7315_27xb-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/port_config.ini b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/port_config.ini new file mode 100755 index 000000000000..10c55c5aeec6 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 3 twentyfiveGigE1 1 25000 +Ethernet1 2 twentyfiveGigE2 2 25000 +Ethernet2 4 twentyfiveGigE3 3 25000 +Ethernet3 8 twentyfiveGigE4 4 25000 +Ethernet4 7 twentyfiveGigE5 5 25000 +Ethernet5 1 twentyfiveGigE6 6 25000 +Ethernet6 5 twentyfiveGigE7 7 25000 +Ethernet7 16 twentyfiveGigE8 8 25000 +Ethernet8 6 twentyfiveGigE9 9 25000 +Ethernet9 14 twentyfiveGigE10 10 25000 +Ethernet10 13 twentyfiveGigE11 11 25000 +Ethernet11 15 twentyfiveGigE12 12 25000 +Ethernet12 23 twentyfiveGigE13 13 25000 +Ethernet13 22 twentyfiveGigE14 14 25000 +Ethernet14 24 twentyfiveGigE15 15 25000 +Ethernet15 32 twentyfiveGigE16 16 25000 +Ethernet16 31 twentyfiveGigE17 17 25000 +Ethernet17 21 twentyfiveGigE18 18 25000 +Ethernet18 29 twentyfiveGigE19 19 25000 +Ethernet19 36 twentyfiveGigE20 20 25000 +Ethernet20 30 twentyfiveGigE21 21 25000 +Ethernet21 34 twentyfiveGigE22 22 25000 +Ethernet22 33 twentyfiveGigE23 23 25000 +Ethernet23 35 twentyfiveGigE24 24 25000 +Ethernet24 43 twentyfiveGigE25 25 25000 +Ethernet25 42 twentyfiveGigE26 26 25000 +Ethernet26 44 twentyfiveGigE27 27 25000 +Ethernet27 52 twentyfiveGigE28 28 25000 +Ethernet28 51 twentyfiveGigE29 29 25000 +Ethernet29 41 twentyfiveGigE30 30 25000 +Ethernet30 49 twentyfiveGigE31 31 25000 +Ethernet31 60 twentyfiveGigE32 32 25000 +Ethernet32 50 twentyfiveGigE33 33 25000 +Ethernet33 58 twentyfiveGigE34 34 25000 +Ethernet34 57 twentyfiveGigE35 35 25000 +Ethernet35 59 twentyfiveGigE36 36 25000 +Ethernet36 62 twentyfiveGigE37 37 25000 +Ethernet37 63 twentyfiveGigE38 38 25000 +Ethernet38 64 twentyfiveGigE39 39 25000 +Ethernet39 65 twentyfiveGigE40 40 25000 +Ethernet40 66 twentyfiveGigE41 41 25000 +Ethernet41 61 twentyfiveGigE42 42 25000 +Ethernet42 68 twentyfiveGigE43 43 25000 +Ethernet43 69 twentyfiveGigE44 44 25000 +Ethernet44 67 twentyfiveGigE45 45 25000 +Ethernet45 71 twentyfiveGigE46 46 25000 +Ethernet46 72 twentyfiveGigE47 47 25000 +Ethernet47 70 twentyfiveGigE48 48 25000 +Ethernet48 77,78,79,80 hundredGigE49 49 100000 +Ethernet52 85,86,87,88 hundredGigE50 50 100000 +Ethernet56 93,94,95,96 hundredGigE51 51 100000 +Ethernet60 97,98,99,100 hundredGigE52 52 100000 +Ethernet64 105,106,107,108 hundredGigE53 53 100000 +Ethernet68 113,114,115,116 hundredGigE54 54 100000 +Ethernet72 121,122,123,124 hundredGigE55 55 100000 +Ethernet76 125,126,127,128 hundredGigE56 56 100000 diff --git a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/sai.profile b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/sai.profile new file mode 100755 index 000000000000..eb932199dfab --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-as7326-48x25G+8x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm new file mode 100755 index 000000000000..5da8cd015da1 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm @@ -0,0 +1,466 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +#polarity/lanemap is using TH2 style. +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +oversubscribe_mode=1 +pbmp_xport_xe=0x7F878787F878787FDFE1E1E1FE1E1E1FE + +parity_enable=0 +mem_cache_enable=0 + +l2_mem_entries=32768 +l3_mem_entries=16384 +fpem_mem_entries=16384 +l2xmsg_mode=1 + +# Platform specfic +bcm_num_cos=10 +bcm_stat_interval=2000000 +cdma_timeout_usec=3000000 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l3_max_ecmp_mode=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +port_flex_enable=1 +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 +skip_L2_USER_ENTRY=0 +bcm_tunnel_term_compatible_mode=1 +l3_alpm_ipv6_128b_bkt_rsvd=1 + +dport_map_port_1=6 +dport_map_port_2=2 +dport_map_port_3=1 +dport_map_port_4=3 +portmap_1=1:25 +portmap_2=2:25 +portmap_3=3:25 +portmap_4=4:25 +phy_chain_rx_lane_map_physical{1.0}=0x1230 +phy_chain_rx_lane_map_physical{2.0}=0x1230 +phy_chain_rx_lane_map_physical{3.0}=0x1230 +phy_chain_rx_lane_map_physical{4.0}=0x1230 +phy_chain_tx_lane_map_physical{1.0}=0x3210 +phy_chain_tx_lane_map_physical{2.0}=0x3210 +phy_chain_tx_lane_map_physical{3.0}=0x3210 +phy_chain_tx_lane_map_physical{4.0}=0x3210 +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x0 +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 + +dport_map_port_5=7 +dport_map_port_6=9 +dport_map_port_7=5 +dport_map_port_8=4 +portmap_5=5:25 +portmap_6=6:25 +portmap_7=7:25 +portmap_8=8:25 +phy_chain_rx_lane_map_physical{5.0}=0x3210 +phy_chain_rx_lane_map_physical{6.0}=0x3210 +phy_chain_rx_lane_map_physical{7.0}=0x3210 +phy_chain_rx_lane_map_physical{8.0}=0x3210 +phy_chain_tx_lane_map_physical{5.0}=0x3210 +phy_chain_tx_lane_map_physical{6.0}=0x3210 +phy_chain_tx_lane_map_physical{7.0}=0x3210 +phy_chain_tx_lane_map_physical{8.0}=0x3210 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 + +dport_map_port_13=11 +dport_map_port_14=10 +dport_map_port_15=12 +dport_map_port_16=8 +portmap_13=13:25 +portmap_14=14:25 +portmap_15=15:25 +portmap_16=16:25 +phy_chain_rx_lane_map_physical{13.0}=0x3012 +phy_chain_rx_lane_map_physical{14.0}=0x3012 +phy_chain_rx_lane_map_physical{15.0}=0x3012 +phy_chain_rx_lane_map_physical{16.0}=0x3012 +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_tx_lane_map_physical{14.0}=0x3210 +phy_chain_tx_lane_map_physical{15.0}=0x3210 +phy_chain_tx_lane_map_physical{16.0}=0x3210 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 + +dport_map_port_21=18 +dport_map_port_22=14 +dport_map_port_23=13 +dport_map_port_24=15 +portmap_21=21:25 +portmap_22=22:25 +portmap_23=23:25 +portmap_24=24:25 +phy_chain_rx_lane_map_physical{21.0}=0x1230 +phy_chain_rx_lane_map_physical{22.0}=0x1230 +phy_chain_rx_lane_map_physical{23.0}=0x1230 +phy_chain_rx_lane_map_physical{24.0}=0x1230 +phy_chain_tx_lane_map_physical{21.0}=0x3210 +phy_chain_tx_lane_map_physical{22.0}=0x3210 +phy_chain_tx_lane_map_physical{23.0}=0x3210 +phy_chain_tx_lane_map_physical{24.0}=0x3210 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x0 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 + +dport_map_port_29=19 +dport_map_port_30=21 +dport_map_port_31=17 +dport_map_port_32=16 +portmap_29=29:25 +portmap_30=30:25 +portmap_31=31:25 +portmap_32=32:25 +phy_chain_rx_lane_map_physical{29.0}=0x3210 +phy_chain_rx_lane_map_physical{30.0}=0x3210 +phy_chain_rx_lane_map_physical{31.0}=0x3210 +phy_chain_rx_lane_map_physical{32.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x3210 +phy_chain_tx_lane_map_physical{30.0}=0x3210 +phy_chain_tx_lane_map_physical{31.0}=0x3210 +phy_chain_tx_lane_map_physical{32.0}=0x3210 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 + +dport_map_port_33=23 +dport_map_port_34=22 +dport_map_port_35=24 +dport_map_port_36=20 +portmap_33=33:25 +portmap_34=34:25 +portmap_35=35:25 +portmap_36=36:25 +phy_chain_rx_lane_map_physical{33.0}=0x3012 +phy_chain_rx_lane_map_physical{34.0}=0x3012 +phy_chain_rx_lane_map_physical{35.0}=0x3012 +phy_chain_rx_lane_map_physical{36.0}=0x3012 +phy_chain_tx_lane_map_physical{33.0}=0x3210 +phy_chain_tx_lane_map_physical{34.0}=0x3210 +phy_chain_tx_lane_map_physical{35.0}=0x3210 +phy_chain_tx_lane_map_physical{36.0}=0x3210 +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x1 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 + +dport_map_port_41=30 +dport_map_port_42=26 +dport_map_port_43=25 +dport_map_port_44=27 +portmap_41=41:25 +portmap_42=42:25 +portmap_43=43:25 +portmap_44=44:25 +phy_chain_rx_lane_map_physical{41.0}=0x1230 +phy_chain_rx_lane_map_physical{42.0}=0x1230 +phy_chain_rx_lane_map_physical{43.0}=0x1230 +phy_chain_rx_lane_map_physical{44.0}=0x1230 +phy_chain_tx_lane_map_physical{41.0}=0x3210 +phy_chain_tx_lane_map_physical{42.0}=0x3210 +phy_chain_tx_lane_map_physical{43.0}=0x3210 +phy_chain_tx_lane_map_physical{44.0}=0x3210 +phy_chain_rx_polarity_flip_physical{41.0}=0x1 +phy_chain_rx_polarity_flip_physical{42.0}=0x0 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.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 + +dport_map_port_49=31 +dport_map_port_50=33 +dport_map_port_51=29 +dport_map_port_52=28 +portmap_49=49:25 +portmap_50=50:25 +portmap_51=51:25 +portmap_52=52:25 +phy_chain_rx_lane_map_physical{49.0}=0x3210 +phy_chain_rx_lane_map_physical{50.0}=0x3210 +phy_chain_rx_lane_map_physical{51.0}=0x3210 +phy_chain_rx_lane_map_physical{52.0}=0x3210 +phy_chain_tx_lane_map_physical{49.0}=0x3210 +phy_chain_tx_lane_map_physical{50.0}=0x3210 +phy_chain_tx_lane_map_physical{51.0}=0x3210 +phy_chain_tx_lane_map_physical{52.0}=0x3210 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.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{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 + +dport_map_port_57=35 +dport_map_port_58=34 +dport_map_port_59=36 +dport_map_port_60=32 +portmap_57=57:25 +portmap_58=58:25 +portmap_59=59:25 +portmap_60=60:25 +phy_chain_rx_lane_map_physical{57.0}=0x3012 +phy_chain_rx_lane_map_physical{58.0}=0x3012 +phy_chain_rx_lane_map_physical{59.0}=0x3012 +phy_chain_rx_lane_map_physical{60.0}=0x3012 +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_lane_map_physical{58.0}=0x3210 +phy_chain_tx_lane_map_physical{59.0}=0x3210 +phy_chain_tx_lane_map_physical{60.0}=0x3210 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 + +dport_map_port_61=42 +dport_map_port_62=37 +dport_map_port_63=38 +dport_map_port_64=39 +portmap_61=61:25 +portmap_62=62:25 +portmap_63=63:25 +portmap_64=64:25 +phy_chain_rx_lane_map_physical{61.0}=0x2310 +phy_chain_rx_lane_map_physical{62.0}=0x2310 +phy_chain_rx_lane_map_physical{63.0}=0x2310 +phy_chain_rx_lane_map_physical{64.0}=0x2310 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_tx_lane_map_physical{62.0}=0x3210 +phy_chain_tx_lane_map_physical{63.0}=0x3210 +phy_chain_tx_lane_map_physical{64.0}=0x3210 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 + +dport_map_port_67=40 +dport_map_port_68=41 +dport_map_port_69=45 +dport_map_port_70=43 +portmap_67=65:25 +portmap_68=66:25 +portmap_69=67:25 +portmap_70=68:25 +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{66.0}=0x3210 +phy_chain_rx_lane_map_physical{67.0}=0x3210 +phy_chain_rx_lane_map_physical{68.0}=0x3210 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{66.0}=0x3210 +phy_chain_tx_lane_map_physical{67.0}=0x3210 +phy_chain_tx_lane_map_physical{68.0}=0x3210 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x1 +phy_chain_tx_polarity_flip_physical{65.0}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x1 +phy_chain_tx_polarity_flip_physical{68.0}=0x1 + +dport_map_port_71=44 +dport_map_port_72=48 +dport_map_port_73=46 +dport_map_port_74=47 +portmap_71=69:25 +portmap_72=70:25 +portmap_73=71:25 +portmap_74=72:25 +phy_chain_rx_lane_map_physical{69.0}=0x1230 +phy_chain_rx_lane_map_physical{70.0}=0x1230 +phy_chain_rx_lane_map_physical{71.0}=0x1230 +phy_chain_rx_lane_map_physical{72.0}=0x1230 +phy_chain_tx_lane_map_physical{69.0}=0x3210 +phy_chain_tx_lane_map_physical{70.0}=0x3210 +phy_chain_tx_lane_map_physical{71.0}=0x3210 +phy_chain_tx_lane_map_physical{72.0}=0x3210 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x1 +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 + +dport_map_port_79=49 +dport_map_port_80=50 +dport_map_port_81=51 +dport_map_port_82=52 +portmap_79=77:100 +phy_chain_rx_lane_map_physical{77.0}=0x2130 +phy_chain_tx_lane_map_physical{77.0}=0x3120 +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_tx_polarity_flip_physical{77.0}=0x0 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.0}=0x1 + +dport_map_port_87=53 +dport_map_port_88=54 +dport_map_port_89=55 +dport_map_port_90=56 +portmap_87=85:100 +phy_chain_rx_lane_map_physical{85.0}=0x1203 +phy_chain_tx_lane_map_physical{85.0}=0x2031 +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_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 + +dport_map_port_95=57 +dport_map_port_96=58 +dport_map_port_97=59 +dport_map_port_98=60 +portmap_95=93:100 +phy_chain_rx_lane_map_physical{93.0}=0x2130 +phy_chain_tx_lane_map_physical{93.0}=0x3210 +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_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 + +dport_map_port_99=61 +dport_map_port_100=62 +dport_map_port_101=63 +dport_map_port_102=64 +portmap_99=97:100 +phy_chain_rx_lane_map_physical{97.0}=0x1203 +phy_chain_tx_lane_map_physical{97.0}=0x2031 +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_rx_polarity_flip_physical{100.0}=0x0 +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 + +dport_map_port_107=65 +dport_map_port_108=66 +dport_map_port_109=67 +dport_map_port_110=68 +portmap_107=105:100 +phy_chain_rx_lane_map_physical{105.0}=0x2130 +phy_chain_tx_lane_map_physical{105.0}=0x3120 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x1 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 + +dport_map_port_115=69 +dport_map_port_116=70 +dport_map_port_117=71 +dport_map_port_118=72 +portmap_115=113:100 +phy_chain_rx_lane_map_physical{113.0}=0x1203 +phy_chain_tx_lane_map_physical{113.0}=0x2031 +phy_chain_rx_polarity_flip_physical{113.0}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{116.0}=0x1 + +dport_map_port_123=73 +dport_map_port_124=74 +dport_map_port_125=75 +dport_map_port_126=76 +portmap_123=121:100 +phy_chain_rx_lane_map_physical{121.0}=0x2130 +phy_chain_tx_lane_map_physical{121.0}=0x3210 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x1 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 + +# Not able to breakout, Since overlap with possible mgmt ports +dport_map_port_127=77 +portmap_127=125:100 +phy_chain_rx_lane_map_physical{125.0}=0x1203 +phy_chain_tx_lane_map_physical{125.0}=0x2031 +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_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 + +#dport_map_port_130=82 +#dport_map_port_66=81 +#portmap_130=128:10:m +#portmap_66=129:10:m diff --git a/device/accton/x86_64-accton_as7326_56x-r0/custom_led.bin b/device/accton/x86_64-accton_as7326_56x-r0/custom_led.bin new file mode 100755 index 000000000000..8495c8216801 Binary files /dev/null and b/device/accton/x86_64-accton_as7326_56x-r0/custom_led.bin differ diff --git a/device/accton/x86_64-accton_as7326_56x-r0/default_sku b/device/accton/x86_64-accton_as7326_56x-r0/default_sku new file mode 100644 index 000000000000..922268da79b6 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7326-56X t1 diff --git a/device/accton/x86_64-accton_as7326_56x-r0/installer.conf b/device/accton/x86_64-accton_as7326_56x-r0/installer.conf new file mode 100755 index 000000000000..1a5c9c96921c --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pcie_aspm=off tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/accton/x86_64-accton_as7326_56x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7326_56x-r0/led_proc_init.soc new file mode 100755 index 000000000000..cb549f2773f9 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/led_proc_init.soc @@ -0,0 +1,6 @@ +#led auto off +#led stop +#m0 load 0 0x0 /usr/share/sonic/platform/linkscan_led_fw.bin +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/accton/x86_64-accton_as7326_56x-r0/linkscan_led_fw.bin b/device/accton/x86_64-accton_as7326_56x-r0/linkscan_led_fw.bin new file mode 100755 index 000000000000..a6a4794ecc2b Binary files /dev/null and b/device/accton/x86_64-accton_as7326_56x-r0/linkscan_led_fw.bin differ diff --git a/device/accton/x86_64-accton_as7326_56x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7326_56x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..4241483d68eb --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7326_56x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7326_56x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..c215bb896772 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 2: "13-0053", + 1: "17-0051", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7326_56x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7326_56x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..965e876691c8 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/plugins/sfputil.py @@ -0,0 +1,312 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# from xcvrd +SFP_STATUS_REMOVED = '0' +SFP_STATUS_INSERTED = '1' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 56 + PORTS_IN_BLOCK = 56 + QSFP_PORT_START = 49 + QSFP_PORT_END = 56 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _cpld_mapping = { + 1: "12-0062", + 2: "18-0060", + 3: "19-0064", + } + + _port_to_i2c_mapping = { + 1: 42, + 2: 41, + 3: 44, + 4: 43, + 5: 47, + 6: 45, + 7: 46, + 8: 50, + 9: 48, + 10: 49, + 11: 52, + 12: 51, + 13: 53, + 14: 56, + 15: 55, + 16: 54, + 17: 58, + 18: 57, + 19: 60, + 20: 59, + 21: 61, + 22: 63, + 23: 62, + 24: 64, + 25: 66, + 26: 68, + 27: 65, + 28: 67, + 29: 69, + 30: 71, + 31: 72, + 32: 70, + 33: 74, + 34: 73, + 35: 76, + 36: 75, + 37: 77, + 38: 79, + 39: 78, + 40: 80, + 41: 81, + 42: 82, + 43: 84, + 44: 85, + 45: 83, + 46: 87, + 47: 88, + 48: 86, + 49: 25, # QSFP49 + 50: 26, + 51: 27, + 52: 28, + 53: 29, + 54: 30, + 55: 31, + 56: 32, # QSFP56 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + + SfpUtilBase.__init__(self) + + # For port 0~23 and 48~51 are at cpld2, others are at cpld3. + def get_cpld_num(self, port_num): + cpld_i = 1 + if (port_num > 30): + cpld_i = 2 + return cpld_i + + 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 + + cpld_i = self.get_cpld_num(port_num) + + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_present_{1}" + port_ps = path.format(cpld_ps, port_num) + + content = "0" + try: + val_file = open(port_ps) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + 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.qsfp_port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + cpld_i = self.get_cpld_num(port_num) + cpld_ps = self._cpld_mapping[cpld_i] + path = "/sys/bus/i2c/devices/{0}/module_reset_{1}" + port_ps = path.format(cpld_ps, port_num) + + self.__port_to_mod_rst = port_ps + try: + reg_file = open(self.__port_to_mod_rst, 'r+', buffering=0) + 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 + + @property + def _get_present_bitmap(self): + nodes = [] + rev = [] + port_num = [30, 26] + + path = "/sys/bus/i2c/devices/{0}/module_present_all" + cpld_i = self.get_cpld_num(self.port_start) + cpld_ps = self._cpld_mapping[cpld_i] + nodes.append((path.format(cpld_ps), port_num[0])) + cpld_i = self.get_cpld_num(self.port_end) + cpld_ps = self._cpld_mapping[cpld_i] + nodes.append((path.format(cpld_ps), port_num[1])) + + bitmaps = "" + for node in nodes: + try: + reg_file = open(node[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap = reg_file.readline().rstrip() + bitmap = bin(int(bitmap, 16))[2:].zfill(node[1]) + rev.append(bitmap) + reg_file.close() + + bitmaps = "".join(rev[::-1]) + bitmaps = hex(int(bitmaps, 2)) + return int(bitmaps, 0) + + data = {'valid': 0, 'last': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + port = 0 + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + reg_value = self._get_present_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + mask = (1 << (port - 1)) + if changed_ports & mask: + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['last'] = now + self.data['valid'] = 1 + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/accton/x86_64-accton_as7326_56x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7326_56x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/port_config.ini b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/port_config.ini new file mode 100644 index 000000000000..c10cd2786941 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 16,17,18,19 +Ethernet4 20,21,22,23 +Ethernet8 24,25,26,27 +Ethernet12 28,29,30,31 +Ethernet16 32,33,34,35 +Ethernet20 36,37,38,39 +Ethernet24 40,41,42,43 +Ethernet28 44,45,46,47 +Ethernet32 0,1,2,3 +Ethernet36 4,5,6,7 +Ethernet40 8,9,10,11 +Ethernet44 12,13,14,15 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 127,126,125,124 +Ethernet68 123,122,121,120 +Ethernet72 115,114,113,112 +Ethernet76 119,118,117,116 +Ethernet80 79,78,77,76 +Ethernet84 75,74,73,72 +Ethernet88 64,65,66,67 +Ethernet92 71,70,68,69 +Ethernet96 111,110,109,108 +Ethernet100 107,106,105,104 +Ethernet104 103,102,101,100 +Ethernet108 99,98,97,96 +Ethernet112 95,94,93,92 +Ethernet116 91,90,89,88 +Ethernet120 87,86,85,84 +Ethernet124 83,82,81,80 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/sai.profile b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/sai.profile new file mode 100644 index 000000000000..457c339c58ab --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-C32/sai.profile @@ -0,0 +1,2 @@ +mode=3 +hwId=as7512 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/port_config.ini b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/port_config.ini new file mode 100644 index 000000000000..c3b669950405 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/port_config.ini @@ -0,0 +1,129 @@ +# name lanes +Ethernet1 0 +Ethernet2 1 +Ethernet3 2 +Ethernet4 3 +Ethernet5 4 +Ethernet6 5 +Ethernet7 6 +Ethernet8 7 +Ethernet9 8 +Ethernet10 9 +Ethernet11 10 +Ethernet12 11 +Ethernet13 12 +Ethernet14 13 +Ethernet15 14 +Ethernet16 15 +Ethernet17 16 +Ethernet18 17 +Ethernet19 18 +Ethernet20 19 +Ethernet21 20 +Ethernet22 21 +Ethernet23 22 +Ethernet24 23 +Ethernet25 24 +Ethernet26 25 +Ethernet27 26 +Ethernet28 27 +Ethernet29 28 +Ethernet30 29 +Ethernet31 30 +Ethernet32 31 +Ethernet33 32 +Ethernet34 33 +Ethernet35 34 +Ethernet36 35 +Ethernet37 36 +Ethernet38 37 +Ethernet39 38 +Ethernet40 39 +Ethernet41 40 +Ethernet42 41 +Ethernet43 42 +Ethernet44 43 +Ethernet45 44 +Ethernet46 45 +Ethernet47 46 +Ethernet48 47 +Ethernet49 48 +Ethernet50 49 +Ethernet51 50 +Ethernet52 51 +Ethernet53 52 +Ethernet54 53 +Ethernet55 54 +Ethernet56 55 +Ethernet57 56 +Ethernet58 57 +Ethernet59 58 +Ethernet60 59 +Ethernet61 60 +Ethernet62 61 +Ethernet63 62 +Ethernet64 63 +Ethernet65 64 +Ethernet66 65 +Ethernet67 66 +Ethernet68 67 +Ethernet69 68 +Ethernet70 69 +Ethernet71 70 +Ethernet72 71 +Ethernet73 72 +Ethernet74 73 +Ethernet75 74 +Ethernet76 75 +Ethernet77 76 +Ethernet78 77 +Ethernet79 78 +Ethernet80 79 +Ethernet81 80 +Ethernet82 81 +Ethernet83 82 +Ethernet84 83 +Ethernet85 84 +Ethernet86 85 +Ethernet87 86 +Ethernet88 87 +Ethernet89 88 +Ethernet90 89 +Ethernet91 90 +Ethernet92 91 +Ethernet93 92 +Ethernet94 93 +Ethernet95 94 +Ethernet96 95 +Ethernet97 96 +Ethernet98 97 +Ethernet99 98 +Ethernet100 99 +Ethernet101 100 +Ethernet102 101 +Ethernet103 102 +Ethernet104 103 +Ethernet105 104 +Ethernet106 105 +Ethernet107 106 +Ethernet108 107 +Ethernet109 108 +Ethernet110 109 +Ethernet111 110 +Ethernet112 111 +Ethernet113 112 +Ethernet114 113 +Ethernet115 114 +Ethernet116 115 +Ethernet117 116 +Ethernet118 117 +Ethernet119 118 +Ethernet120 119 +Ethernet121 120 +Ethernet122 121 +Ethernet123 122 +Ethernet124 123 +Ethernet125 124 +Ethernet126 125 +Ethernet127 126 +Ethernet128 127 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/sai.profile b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/sai.profile new file mode 100644 index 000000000000..471c4395758f --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512-S128/sai.profile @@ -0,0 +1,2 @@ +mode=0 +hwId=as7512 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512/port_config.ini b/device/accton/x86_64-accton_as7512_32x-r0/AS7512/port_config.ini new file mode 100644 index 000000000000..c10cd2786941 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512/port_config.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 16,17,18,19 +Ethernet4 20,21,22,23 +Ethernet8 24,25,26,27 +Ethernet12 28,29,30,31 +Ethernet16 32,33,34,35 +Ethernet20 36,37,38,39 +Ethernet24 40,41,42,43 +Ethernet28 44,45,46,47 +Ethernet32 0,1,2,3 +Ethernet36 4,5,6,7 +Ethernet40 8,9,10,11 +Ethernet44 12,13,14,15 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 127,126,125,124 +Ethernet68 123,122,121,120 +Ethernet72 115,114,113,112 +Ethernet76 119,118,117,116 +Ethernet80 79,78,77,76 +Ethernet84 75,74,73,72 +Ethernet88 64,65,66,67 +Ethernet92 71,70,68,69 +Ethernet96 111,110,109,108 +Ethernet100 107,106,105,104 +Ethernet104 103,102,101,100 +Ethernet108 99,98,97,96 +Ethernet112 95,94,93,92 +Ethernet116 91,90,89,88 +Ethernet120 87,86,85,84 +Ethernet124 83,82,81,80 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/AS7512/sai.profile b/device/accton/x86_64-accton_as7512_32x-r0/AS7512/sai.profile new file mode 100644 index 000000000000..017996f7d7cc --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/AS7512/sai.profile @@ -0,0 +1,2 @@ +mode=1 +hwId=as7512 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/default_sku b/device/accton/x86_64-accton_as7512_32x-r0/default_sku new file mode 100644 index 000000000000..45eb53f68a97 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/default_sku @@ -0,0 +1 @@ +AS7512 t1 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/fancontrol b/device/accton/x86_64-accton_as7512_32x-r0/fancontrol new file mode 100644 index 000000000000..c80163771e86 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/fancontrol @@ -0,0 +1,7 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/3-004b/hwmon/hwmon[[:print:]]*/temp1_input /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/3-004a/hwmon/hwmon[[:print:]]*/temp1_input +FCFANS=/sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan1_front_speed_rpm /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan2_front_speed_rpm /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan3_front_speed_rpm /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan4_front_speed_rpm /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan5_front_speed_rpm /sys/bus/i2c/devices/2-0066/fan_pwm=/sys/bus/i2c/devices/2-0066/fan6_front_speed_rpm +MINTEMP=/sys/bus/i2c/devices/2-0066/fan_pwm=20 +MAXTEMP=/sys/bus/i2c/devices/2-0066/fan_pwm=60 +MINSTART=/sys/bus/i2c/devices/2-0066/fan_pwm=150 +MINSTOP=/sys/bus/i2c/devices/2-0066/fan_pwm=7 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/installer.conf b/device/accton/x86_64-accton_as7512_32x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as7512_32x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7512_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..f2f0703f0a11 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/plugins/eeprom.py @@ -0,0 +1,30 @@ +############################################################################# +# Cavium +# +# 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 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 as 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/1-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7512_32x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7512_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..a999ecc24092 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/plugins/sfputil.py @@ -0,0 +1,136 @@ +#! /usr/bin/python + +try: + import time + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific sfputil class""" + + _port_start = 0 + _port_end = 31 + ports_in_block = 32 + + _port_to_eeprom_mapping = {} + + _qsfp_ports = list(range(0, ports_in_block + 1)) + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom' + for x in range(self.port_start, self.port_end + 1): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + 18) + SfpUtilBase.__init__(self) + + def reset(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" + port_ps = path.format(port_num+18) + + reg_value = '0' + try: + reg_file = open(port_ps) + reg_value = reg_file.readline().rstrip() + reg_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return list(range(0, self.ports_in_block + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + 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 + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) diff --git a/device/accton/x86_64-accton_as7512_32x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7512_32x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7512_32x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/port_config.ini b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/port_config.ini new file mode 100644 index 000000000000..e101ec29d4ad --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 49,50,51,52 hundredGigE1 1 100000 +Ethernet4 53,54,55,56 hundredGigE2 2 100000 +Ethernet8 57,58,59,60 hundredGigE3 3 100000 +Ethernet12 61,62,63,64 hundredGigE4 4 100000 +Ethernet16 65,66,67,68 hundredGigE5 5 100000 +Ethernet20 69,70,71,72 hundredGigE6 6 100000 +Ethernet24 73,74,75,76 hundredGigE7 7 100000 +Ethernet28 77,78,79,80 hundredGigE8 8 100000 +Ethernet32 33,34,35,36 hundredGigE9 9 100000 +Ethernet36 37,38,39,40 hundredGigE10 10 100000 +Ethernet40 41,42,43,44 hundredGigE11 11 100000 +Ethernet44 45,46,47,48 hundredGigE12 12 100000 +Ethernet48 81,82,83,84 hundredGigE13 13 100000 +Ethernet52 85,86,87,88 hundredGigE14 14 100000 +Ethernet56 89,90,91,92 hundredGigE15 15 100000 +Ethernet60 93,94,95,96 hundredGigE16 16 100000 +Ethernet64 97,98,99,100 hundredGigE17 17 100000 +Ethernet68 101,102,103,104 hundredGigE18 18 100000 +Ethernet72 105,106,107,108 hundredGigE19 19 100000 +Ethernet76 109,110,111,112 hundredGigE20 20 100000 +Ethernet80 17,18,19,20 hundredGigE21 21 100000 +Ethernet84 21,22,23,24 hundredGigE22 22 100000 +Ethernet88 25,26,27,28 hundredGigE23 23 100000 +Ethernet92 29,30,31,32 hundredGigE24 24 100000 +Ethernet96 113,114,115,116 hundredGigE25 25 100000 +Ethernet100 117,118,119,120 hundredGigE26 26 100000 +Ethernet104 121,122,123,124 hundredGigE27 27 100000 +Ethernet108 125,126,127,128 hundredGigE28 28 100000 +Ethernet112 1,2,3,4 hundredGigE29 29 100000 +Ethernet116 5,6,7,8 hundredGigE30 30 100000 +Ethernet120 9,10,11,12 hundredGigE31 31 100000 +Ethernet124 13,14,15,16 hundredGigE32 32 100000 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/sai.profile b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/sai.profile new file mode 100644 index 000000000000..6e4d11fb7292 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-as7712-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/th-as7712-32x100G.config.bcm b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/th-as7712-32x100G.config.bcm new file mode 100644 index 000000000000..6ecca8e02a08 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/Accton-AS7712-32X/th-as7712-32x100G.config.bcm @@ -0,0 +1,570 @@ +# accton_as7712_32x 32x100G SDK config +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x444444441111111104444444422222222 +pbmp_xport_xe=0x444444451111111144444444422222222 + +# +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +oversubscribe_mode=1 + +# portmap_0=x:xx +#FC0 +portmap_1=1:100 + +#FC1 +portmap_5=5:100 + +#FC2 +portmap_9=9:100 + +#FC3 +portmap_13=13:100 + +#FC4 +portmap_17=17:100 + +#FC5 +portmap_21=21:100 + +#FC6 +portmap_25=25:100 + +#FC7 +portmap_29=29:100 + +# Tile-1 +#FC8 +portmap_34=33:100 + +#FC9 +portmap_38=37:100 + +#FC10 +portmap_42=41:100 + +#FC11 +portmap_46=45:100 + +#FC12 +portmap_50=49:100 + +#FC13 +portmap_54=53:100 + +#FC14 +portmap_58=57:100 + +#FC15 +portmap_62=61:100 + +#TSC-E Management port 1 +#portmap_66=129:10 +#portmap_67=133:10 + +# Tile-2 +#FC16 +portmap_68=65:100 + +#FC17 +portmap_72=69:100 + +#FC18 +portmap_76=73:100 + +#FC19 +portmap_80=77:100 + +#FC20 +portmap_84=81:100 + +#FC21 +portmap_88=85:100 + +#FC22 +portmap_92=89:100 + +#FC23 +portmap_96=93:100 + +#TSC-E Management port 2 +#portmap_100=131:10 +#portmap_101=134:10 + +# Tile-3 +#FC24 +portmap_102=97:100 + +#FC25 +portmap_106=101:100 + +#FC26 +portmap_110=105:100 + +#FC27 +portmap_114=109:100 + +#FC28 +portmap_118=113:100 + +#FC29 +portmap_122=117:100 + +#FC30 +portmap_126=121:100 + +#FC31 +portmap_130=125:100 + + + +## TX/RX Lane Swap +######### +# port5 # +# FC16 # +######### +xgxs_tx_lane_map_68=0x0123 +xgxs_rx_lane_map_68=0x0123 + +######### +# port8 # +# FC19 # +######### +xgxs_tx_lane_map_80=0x0123 +xgxs_rx_lane_map_80=0x0123 + +######### +# port13# +# FC20 # +######### +xgxs_tx_lane_map_84=0x1032 +xgxs_rx_lane_map_84=0x1032 + +######### +# port14# +# FC21 # +######### +xgxs_tx_lane_map_88=0x0123 +xgxs_rx_lane_map_88=0x0123 + +######### +# port15# +# FC22 # +######### +xgxs_tx_lane_map_92=0x1032 +xgxs_rx_lane_map_92=0x1032 + +######### +# port17# +# FC24 # +######### +xgxs_tx_lane_map_102=0x1032 +xgxs_rx_lane_map_102=0x1032 + +######### +# port18# +# FC25 # +######### +xgxs_tx_lane_map_106=0x0123 +xgxs_rx_lane_map_106=0x0123 + +######### +# port19# +# FC26 # +######### +xgxs_tx_lane_map_110=0x1032 +xgxs_rx_lane_map_110=0x1032 + +######### +# port20# +# FC27 # +######### +xgxs_tx_lane_map_114=0x0123 +xgxs_rx_lane_map_114=0x0123 + +######### +# port26# +# FC29 # +######### +xgxs_tx_lane_map_122=0x0123 +xgxs_rx_lane_map_122=0x0123 + +######### +# port27# +# FC30 # +######### +xgxs_tx_lane_map_126=0x0123 +xgxs_rx_lane_map_126=0x0123 + +######### +# port29# +# FC0 # +######### +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x0123 + +# port30# +# FC1 # +######### +xgxs_tx_lane_map_5=0x0123 +xgxs_rx_lane_map_5=0x0123 + +######### +# port31# +# FC2 # +######### +xgxs_tx_lane_map_9=0x0123 +xgxs_rx_lane_map_9=0x0123 + +######### +# port32# +# FC3 # +######### +xgxs_tx_lane_map_13=0x0123 +xgxs_rx_lane_map_13=0x0123 + + +## RX / TX Serdes lane polarity flip list +## RX / TX Serdes lane polarity flip list +######### +# FC4 # +# port21 # +######### +phy_xaui_tx_polarity_flip_17=0xf + +######### +# FC20 # +# port13 # +######### +phy_xaui_rx_polarity_flip_84=0xf +phy_xaui_tx_polarity_flip_84=0x6 + +######### +# FC21 # +# port14 # +######### +phy_xaui_rx_polarity_flip_88=0xf + +######### +# FC22 # +# port15 # +######### +phy_xaui_rx_polarity_flip_92=0xf +phy_xaui_tx_polarity_flip_92=0xe + + +######### +# FC23 # +# port16 # +######### +phy_xaui_tx_polarity_flip_96=0x1 + +######### +# FC24 # +# port17 # +######### +phy_xaui_tx_polarity_flip_102=0x1 + + +######### +# FC25 # +# port18 # +######### +phy_xaui_rx_polarity_flip_106=0xf + +######### +# FC26 # +# port19 # +######### +phy_xaui_tx_polarity_flip_110=0xe + +######### +# FC27 # +# port20 # +######### +phy_xaui_rx_polarity_flip_114=0x2 + +######### +# FC28 # +# port25 # +######### +phy_xaui_rx_polarity_flip_118=0xa +phy_xaui_tx_polarity_flip_118=0xf + +#Driver Current +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_13=0x8 +serdes_driver_current_lane1_13=0x8 +serdes_driver_current_lane2_13=0x8 +serdes_driver_current_lane3_13=0x8 +serdes_driver_current_lane0_17=0x8 +serdes_driver_current_lane1_17=0x8 +serdes_driver_current_lane2_17=0x8 +serdes_driver_current_lane3_17=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_25=0x8 +serdes_driver_current_lane1_25=0x8 +serdes_driver_current_lane2_25=0x8 +serdes_driver_current_lane3_25=0x8 +serdes_driver_current_lane0_29=0x8 +serdes_driver_current_lane1_29=0x8 +serdes_driver_current_lane2_29=0x8 +serdes_driver_current_lane3_29=0x8 +serdes_driver_current_lane0_34=0x8 +serdes_driver_current_lane1_34=0x8 +serdes_driver_current_lane2_34=0x8 +serdes_driver_current_lane3_34=0x8 +serdes_driver_current_lane0_38=0x8 +serdes_driver_current_lane1_38=0x8 +serdes_driver_current_lane2_38=0x8 +serdes_driver_current_lane3_38=0x8 +serdes_driver_current_lane0_42=0x8 +serdes_driver_current_lane1_42=0x8 +serdes_driver_current_lane2_42=0x8 +serdes_driver_current_lane3_42=0x8 +serdes_driver_current_lane0_46=0x8 +serdes_driver_current_lane1_46=0x8 +serdes_driver_current_lane2_46=0x8 +serdes_driver_current_lane3_46=0x8 +serdes_driver_current_lane0_50=0x8 +serdes_driver_current_lane1_50=0x8 +serdes_driver_current_lane2_50=0x8 +serdes_driver_current_lane3_50=0x8 +serdes_driver_current_lane0_54=0x8 +serdes_driver_current_lane1_54=0x8 +serdes_driver_current_lane2_54=0x8 +serdes_driver_current_lane3_54=0x8 +serdes_driver_current_lane0_58=0x8 +serdes_driver_current_lane1_58=0x8 +serdes_driver_current_lane2_58=0x8 +serdes_driver_current_lane3_58=0x8 +serdes_driver_current_lane0_62=0x8 +serdes_driver_current_lane1_62=0x8 +serdes_driver_current_lane2_62=0x8 +serdes_driver_current_lane3_62=0x8 +serdes_driver_current_lane0_68=0x8 +serdes_driver_current_lane1_68=0x8 +serdes_driver_current_lane2_68=0x8 +serdes_driver_current_lane3_68=0x8 +serdes_driver_current_lane0_72=0x8 +serdes_driver_current_lane1_72=0x8 +serdes_driver_current_lane2_72=0x8 +serdes_driver_current_lane3_72=0x8 +serdes_driver_current_lane0_76=0x8 +serdes_driver_current_lane1_76=0x8 +serdes_driver_current_lane2_76=0x8 +serdes_driver_current_lane3_76=0x8 +serdes_driver_current_lane0_80=0x8 +serdes_driver_current_lane1_80=0x8 +serdes_driver_current_lane2_80=0x8 +serdes_driver_current_lane3_80=0x8 +serdes_driver_current_lane0_84=0x8 +serdes_driver_current_lane1_84=0x8 +serdes_driver_current_lane2_84=0x8 +serdes_driver_current_lane3_84=0x8 +serdes_driver_current_lane0_88=0x8 +serdes_driver_current_lane1_88=0x8 +serdes_driver_current_lane2_88=0x8 +serdes_driver_current_lane3_88=0x8 +serdes_driver_current_lane0_92=0x8 +serdes_driver_current_lane1_92=0x8 +serdes_driver_current_lane2_92=0x8 +serdes_driver_current_lane3_92=0x8 +serdes_driver_current_lane0_96=0x8 +serdes_driver_current_lane1_96=0x8 +serdes_driver_current_lane2_96=0x8 +serdes_driver_current_lane3_96=0x8 +serdes_driver_current_lane0_102=0x8 +serdes_driver_current_lane1_102=0x8 +serdes_driver_current_lane2_102=0x8 +serdes_driver_current_lane3_102=0x8 +serdes_driver_current_lane0_106=0x8 +serdes_driver_current_lane1_106=0x8 +serdes_driver_current_lane2_106=0x8 +serdes_driver_current_lane3_106=0x8 +serdes_driver_current_lane0_110=0x8 +serdes_driver_current_lane1_110=0x8 +serdes_driver_current_lane2_110=0x8 +serdes_driver_current_lane3_110=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_118=0x8 +serdes_driver_current_lane1_118=0x8 +serdes_driver_current_lane2_118=0x8 +serdes_driver_current_lane3_118=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 +serdes_driver_current_lane0_126=0x8 +serdes_driver_current_lane1_126=0x8 +serdes_driver_current_lane2_126=0x8 +serdes_driver_current_lane3_126=0x8 +serdes_driver_current_lane0_130=0x8 +serdes_driver_current_lane1_130=0x8 +serdes_driver_current_lane2_130=0x8 +serdes_driver_current_lane3_130=0x8 + +#Preemphasis +serdes_preemphasis_lane0_1=0x264204 +serdes_preemphasis_lane1_1=0x264204 +serdes_preemphasis_lane2_1=0x264204 +serdes_preemphasis_lane3_1=0x264204 +serdes_preemphasis_lane0_5=0x224406 +serdes_preemphasis_lane1_5=0x224406 +serdes_preemphasis_lane2_5=0x264204 +serdes_preemphasis_lane3_5=0x244206 +serdes_preemphasis_lane0_9=0x204606 +serdes_preemphasis_lane1_9=0x264204 +serdes_preemphasis_lane2_9=0x204606 +serdes_preemphasis_lane3_9=0x224406 +serdes_preemphasis_lane0_13=0x204606 +serdes_preemphasis_lane1_13=0x224406 +serdes_preemphasis_lane2_13=0x224406 +serdes_preemphasis_lane3_13=0x244206 +serdes_preemphasis_lane0_17=0x204606 +serdes_preemphasis_lane1_17=0x204606 +serdes_preemphasis_lane2_17=0x204606 +serdes_preemphasis_lane3_17=0x204606 +serdes_preemphasis_lane0_21=0x204606 +serdes_preemphasis_lane1_21=0x204606 +serdes_preemphasis_lane2_21=0x204606 +serdes_preemphasis_lane3_21=0x224406 +serdes_preemphasis_lane0_25=0x204606 +serdes_preemphasis_lane1_25=0x204606 +serdes_preemphasis_lane2_25=0x204606 +serdes_preemphasis_lane3_25=0x204606 +serdes_preemphasis_lane0_29=0x204606 +serdes_preemphasis_lane1_29=0x204606 +serdes_preemphasis_lane2_29=0x204606 +serdes_preemphasis_lane3_29=0x204606 +serdes_preemphasis_lane0_34=0x284601 +serdes_preemphasis_lane1_34=0x284601 +serdes_preemphasis_lane2_34=0x284601 +serdes_preemphasis_lane3_34=0x284601 +serdes_preemphasis_lane0_38=0x204604 +serdes_preemphasis_lane1_38=0x204604 +serdes_preemphasis_lane2_38=0x224406 +serdes_preemphasis_lane3_38=0x224406 +serdes_preemphasis_lane0_42=0x284601 +serdes_preemphasis_lane1_42=0x294501 +serdes_preemphasis_lane2_42=0x284601 +serdes_preemphasis_lane3_42=0x284601 +serdes_preemphasis_lane0_46=0x204802 +serdes_preemphasis_lane1_46=0x204802 +serdes_preemphasis_lane2_46=0x204802 +serdes_preemphasis_lane3_46=0x204802 +serdes_preemphasis_lane0_50=0x1e4f01 +serdes_preemphasis_lane1_50=0x1e4d01 +serdes_preemphasis_lane2_50=0x1e4f01 +serdes_preemphasis_lane3_50=0x1e4f01 +serdes_preemphasis_lane0_54=0x1f4a03 +serdes_preemphasis_lane1_54=0x1f4a03 +serdes_preemphasis_lane2_54=0x1f4a03 +serdes_preemphasis_lane3_54=0x1f4a03 +serdes_preemphasis_lane0_58=0x1e4f01 +serdes_preemphasis_lane1_58=0x1e4f01 +serdes_preemphasis_lane2_58=0x1e4f01 +serdes_preemphasis_lane3_58=0x1e4f01 +serdes_preemphasis_lane0_62=0x1e4e02 +serdes_preemphasis_lane1_62=0x1e4e02 +serdes_preemphasis_lane2_62=0x1e4e02 +serdes_preemphasis_lane3_62=0x1e4e02 +serdes_preemphasis_lane0_68=0x1e4f01 +serdes_preemphasis_lane1_68=0x1e4f01 +serdes_preemphasis_lane2_68=0x1e4f01 +serdes_preemphasis_lane3_68=0x1e4f01 +serdes_preemphasis_lane0_72=0x1e4e02 +serdes_preemphasis_lane1_72=0x1e4e02 +serdes_preemphasis_lane2_72=0x1e4e02 +serdes_preemphasis_lane3_72=0x1e4e02 +serdes_preemphasis_lane0_76=0x1c4d02 +serdes_preemphasis_lane1_76=0x195002 +serdes_preemphasis_lane2_76=0x195002 +serdes_preemphasis_lane3_76=0x195002 +serdes_preemphasis_lane0_80=0x1e4e02 +serdes_preemphasis_lane1_80=0x1e4e02 +serdes_preemphasis_lane2_80=0x1e4e02 +serdes_preemphasis_lane3_80=0x1e4e02 +serdes_preemphasis_lane0_84=0x234701 +serdes_preemphasis_lane1_84=0x234701 +serdes_preemphasis_lane2_84=0x234701 +serdes_preemphasis_lane3_84=0x234701 +serdes_preemphasis_lane0_88=0x224802 +serdes_preemphasis_lane1_88=0x224602 +serdes_preemphasis_lane2_88=0x224802 +serdes_preemphasis_lane3_88=0x224802 +serdes_preemphasis_lane0_92=0x234801 +serdes_preemphasis_lane1_92=0x244701 +serdes_preemphasis_lane2_92=0x234801 +serdes_preemphasis_lane3_92=0x234601 +serdes_preemphasis_lane0_96=0x204406 +serdes_preemphasis_lane1_96=0x204406 +serdes_preemphasis_lane2_96=0x204406 +serdes_preemphasis_lane3_96=0x224602 +serdes_preemphasis_lane0_102=0x204606 +serdes_preemphasis_lane1_102=0x235002 +serdes_preemphasis_lane2_102=0x204606 +serdes_preemphasis_lane3_102=0x204606 +serdes_preemphasis_lane0_106=0x204606 +serdes_preemphasis_lane1_106=0x204606 +serdes_preemphasis_lane2_106=0x204606 +serdes_preemphasis_lane3_106=0x204606 +serdes_preemphasis_lane0_110=0x204606 +serdes_preemphasis_lane1_110=0x224406 +serdes_preemphasis_lane2_110=0x224406 +serdes_preemphasis_lane3_110=0x224406 +serdes_preemphasis_lane0_114=0x224406 +serdes_preemphasis_lane1_114=0x204606 +serdes_preemphasis_lane2_114=0x204606 +serdes_preemphasis_lane3_114=0x224406 +serdes_preemphasis_lane0_118=0x224406 +serdes_preemphasis_lane1_118=0x224406 +serdes_preemphasis_lane2_118=0x224406 +serdes_preemphasis_lane3_118=0x224406 +serdes_preemphasis_lane0_122=0x244404 +serdes_preemphasis_lane1_122=0x244404 +serdes_preemphasis_lane2_122=0x244404 +serdes_preemphasis_lane3_122=0x244404 +serdes_preemphasis_lane0_126=0x234504 +serdes_preemphasis_lane1_126=0x234404 +serdes_preemphasis_lane2_126=0x224406 +serdes_preemphasis_lane3_126=0x224406 +serdes_preemphasis_lane0_130=0x244404 +serdes_preemphasis_lane1_130=0x244404 +serdes_preemphasis_lane2_130=0x234504 +serdes_preemphasis_lane3_130=0x264501 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/default_sku b/device/accton/x86_64-accton_as7712_32x-r0/default_sku new file mode 100644 index 000000000000..fb1c5c5afc92 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7712-32X t1 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/fancontrol b/device/accton/x86_64-accton_as7712_32x-r0/fancontrol new file mode 100644 index 000000000000..9d057024f946 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/sys_temp +FCFANS=/sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan1_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan2_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan3_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan4_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan5_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan6_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan11_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan12_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan13_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan14_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan15_input /sys/bus/i2c/devices/2-0066/pwm1=/sys/bus/i2c/devices/2-0066/fan16_input +MINTEMP=/sys/bus/i2c/devices/2-0066/pwm1=135 +MAXTEMP=/sys/bus/i2c/devices/2-0066/pwm1=160 +MINSTART=/sys/bus/i2c/devices/2-0066/pwm1=100 +MINSTOP=/sys/bus/i2c/devices/2-0066/pwm1=32 +MINPWM=/sys/bus/i2c/devices/2-0066/pwm1=32 +MAXPWM=/sys/bus/i2c/devices/2-0066/pwm1=69 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/installer.conf b/device/accton/x86_64-accton_as7712_32x-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7712_32x-r0/led_proc_init.soc new file mode 100755 index 000000000000..719cb777719f --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/led_proc_init.soc @@ -0,0 +1,41 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=62 REMAP_PORT_18=61 REMAP_PORT_19=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=59 REMAP_PORT_21=58 REMAP_PORT_22=57 REMAP_PORT_23=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=55 REMAP_PORT_25=54 REMAP_PORT_26=53 REMAP_PORT_27=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=51 REMAP_PORT_29=50 REMAP_PORT_30=49 REMAP_PORT_31=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=47 REMAP_PORT_33=46 REMAP_PORT_34=45 REMAP_PORT_35=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=43 REMAP_PORT_37=42 REMAP_PORT_38=41 REMAP_PORT_39=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=39 REMAP_PORT_41=38 REMAP_PORT_42=37 REMAP_PORT_43=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=35 REMAP_PORT_45=34 REMAP_PORT_46=33 REMAP_PORT_47=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=35 REMAP_PORT_1=34 REMAP_PORT_2=33 REMAP_PORT_3=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=39 REMAP_PORT_5=38 REMAP_PORT_6=37 REMAP_PORT_7=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=43 REMAP_PORT_9=42 REMAP_PORT_10=41 REMAP_PORT_11=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=46 REMAP_PORT_14=45 REMAP_PORT_15=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=3 REMAP_PORT_17=2 REMAP_PORT_18=1 REMAP_PORT_19=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=7 REMAP_PORT_21=6 REMAP_PORT_22=5 REMAP_PORT_23=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=11 REMAP_PORT_25=10 REMAP_PORT_26=9 REMAP_PORT_27=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=15 REMAP_PORT_29=14 REMAP_PORT_30=13 REMAP_PORT_31=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 REMAP_PORT_33=18 REMAP_PORT_34=17 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 REMAP_PORT_41=26 REMAP_PORT_42=25 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 REMAP_PORT_45=30 REMAP_PORT_46=29 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start + +led 1 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start + +led auto on \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7712_32x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7712_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..951384d5e37d --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7712_32x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7712_32x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..a9133f8adccb --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "11-0053", + 2: "10-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7712_32x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7712_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..079a533e4e7d --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/plugins/sfputil.py @@ -0,0 +1,241 @@ +try: + import time + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +# from xcvrd +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 1 + _port_end = 32 + ports_in_block = 32 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 9: 18, + 10: 19, + 11: 20, + 12: 21, + 1: 22, + 2: 23, + 3: 24, + 4: 25, + 6: 26, + 5: 27, + 8: 28, + 7: 29, + 13: 30, + 14: 31, + 15: 32, + 16: 33, + 17: 34, + 18: 35, + 19: 36, + 20: 37, + 25: 38, + 26: 39, + 27: 40, + 28: 41, + 29: 42, + 30: 43, + 31: 44, + 32: 45, + 21: 46, + 22: 47, + 23: 48, + 24: 49, + } + + _qsfp_ports = list(range(0, ports_in_block + 1)) + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/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) + + 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/4-0060/module_reset_{0}" + port_ps = path.format(port_num) + + try: + reg_file = open(port_ps, 'w', buffering=0) + 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 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/4-0060/module_present_{0}" + port_ps = path.format(port_num) + + reg_value = '0' + try: + reg_file = open(port_ps) + reg_value = reg_file.readline().rstrip() + reg_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return list(range(self.port_start, self.ports_in_block + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + @property + def _get_all_presence(self): + nodes = [] + + cpld_path = "/sys/bus/i2c/devices/4-0060/" + nodes.append(cpld_path + "module_present_all") + + bitmap = "" + for node in nodes: + try: + reg_file = open(node) + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap += reg_file.readline().rstrip() + " " + reg_file.close() + + rev = bitmap.split(" ") + rev = "".join(rev[::-1]) + return int(rev, 16) + + data = {'valid': 0, 'last': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + port = 0 + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + reg_value = self._get_all_presence + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + mask = (1 << (port - 1)) + if changed_ports & mask: + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_INSERTED + else: + port_dict[port] = SFP_STATUS_REMOVED + + # Update cache + self.data['present'] = reg_value + self.data['last'] = now + self.data['valid'] = 1 + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/accton/x86_64-accton_as7712_32x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7712_32x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7712_32x-r0/sensors.conf b/device/accton/x86_64-accton_as7712_32x-r0/sensors.conf new file mode 100644 index 000000000000..33d75d598123 --- /dev/null +++ b/device/accton/x86_64-accton_as7712_32x-r0/sensors.conf @@ -0,0 +1,23 @@ +# libsensors configuration file for AS7712-32X +# ------------------------------------------------ +# + +#Comment out the following for sku-sensors-data.yml +#chip "ym2651-*" +# label power1 "PSU Output Power" +# label temp1 "Power Supply Temp" +# label fan1 "Fan Speed" +# +#chip "as7712_32x_fan-*" +# label fan1 "Fan tray 1 front" +# label fan2 "Fan tray 2 front" +# label fan3 "Fan tray 3 front" +# label fan4 "Fan tray 4 front" +# label fan5 "Fan tray 5 front" +# label fan6 "Fan tray 6 front" +# label fan11 "Fan tray 1 rear" +# label fan12 "Fan tray 2 rear" +# label fan13 "Fan tray 3 rear" +# label fan14 "Fan tray 4 rear" +# label fan15 "Fan tray 5 rear" +# label fan16 "Fan tray 6 rear" diff --git a/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/port_config.ini b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/port_config.ini new file mode 100644 index 000000000000..0151b70d71cb --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 49,50,51,52 hundredGigE1 1 100000 +Ethernet4 53,54,55,56 hundredGigE2 2 100000 +Ethernet8 57,58,59,60 hundredGigE3 3 100000 +Ethernet12 61,62,63,64 hundredGigE4 4 100000 +Ethernet16 65,66,67,68 hundredGigE5 5 100000 +Ethernet20 69,70,71,72 hundredGigE6 6 100000 +Ethernet24 73,74,75,76 hundredGigE7 7 100000 +Ethernet28 77,78,79,80 hundredGigE8 8 100000 +Ethernet32 33,34,35,36 hundredGigE9 9 100000 +Ethernet36 37,38,39,40 hundredGigE10 10 100000 +Ethernet40 41,42,43,44 hundredGigE11 11 100000 +Ethernet44 45,46,47,48 hundredGigE12 12 100000 +Ethernet48 81,82,83,84 hundredGigE13 13 100000 +Ethernet52 85,86,87,88 hundredGigE14 14 100000 +Ethernet56 89,90,91,92 hundredGigE15 15 100000 +Ethernet60 93,94,95,96 hundredGigE16 16 100000 +Ethernet64 97,98,99,100 hundredGigE17 17 100000 +Ethernet68 101,102,103,104 hundredGigE18 18 100000 +Ethernet72 105,106,107,108 hundredGigE19 19 100000 +Ethernet76 109,110,111,112 hundredGigE20 20 100000 +Ethernet80 17,18,19,20 hundredGigE21 21 100000 +Ethernet84 21,22,23,24 hundredGigE22 22 100000 +Ethernet88 25,26,27,28 hundredGigE23 23 100000 +Ethernet92 29,30,31,32 hundredGigE24 24 100000 +Ethernet96 113,114,115,116 hundredGigE25 25 100000 +Ethernet100 117,118,119,120 hundredGigE26 26 100000 +Ethernet104 121,122,123,124 hundredGigE27 27 100000 +Ethernet108 125,126,127,128 hundredGigE28 28 100000 +Ethernet112 1,2,3,4 hundredGigE29 29 100000 +Ethernet116 5,6,7,8 hundredGigE30 30 100000 +Ethernet120 9,10,11,12 hundredGigE31 31 100000 +Ethernet124 13,14,15,16 hundredGigE32 32 100000 diff --git a/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/sai.profile b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/sai.profile new file mode 100644 index 000000000000..794c15a5c95a --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-as7716-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/th-as7716-32x100G.config.bcm b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/th-as7716-32x100G.config.bcm new file mode 100644 index 000000000000..1aa9f5d2c16b --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/Accton-AS7716-32X/th-as7716-32x100G.config.bcm @@ -0,0 +1,570 @@ +# accton_as7716_32x 32x100G SDK config +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x444444441111111104444444422222222 +pbmp_xport_xe=0x444444451111111144444444422222222 + +# +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +oversubscribe_mode=1 + +# portmap_0=x:xx +#FC0 +portmap_1=1:100 + +#FC1 +portmap_5=5:100 + +#FC2 +portmap_9=9:100 + +#FC3 +portmap_13=13:100 + +#FC4 +portmap_17=17:100 + +#FC5 +portmap_21=21:100 + +#FC6 +portmap_25=25:100 + +#FC7 +portmap_29=29:100 + +# Tile-1 +#FC8 +portmap_34=33:100 + +#FC9 +portmap_38=37:100 + +#FC10 +portmap_42=41:100 + +#FC11 +portmap_46=45:100 + +#FC12 +portmap_50=49:100 + +#FC13 +portmap_54=53:100 + +#FC14 +portmap_58=57:100 + +#FC15 +portmap_62=61:100 + +#TSC-E Management port 1 +#portmap_66=129:10 +#portmap_67=133:10 + +# Tile-2 +#FC16 +portmap_68=65:100 + +#FC17 +portmap_72=69:100 + +#FC18 +portmap_76=73:100 + +#FC19 +portmap_80=77:100 + +#FC20 +portmap_84=81:100 + +#FC21 +portmap_88=85:100 + +#FC22 +portmap_92=89:100 + +#FC23 +portmap_96=93:100 + +#TSC-E Management port 2 +#portmap_100=131:10 +#portmap_101=134:10 + +# Tile-3 +#FC24 +portmap_102=97:100 + +#FC25 +portmap_106=101:100 + +#FC26 +portmap_110=105:100 + +#FC27 +portmap_114=109:100 + +#FC28 +portmap_118=113:100 + +#FC29 +portmap_122=117:100 + +#FC30 +portmap_126=121:100 + +#FC31 +portmap_130=125:100 + + + +## TX/RX Lane Swap +######### +# port5 # +# FC16 # +######### +xgxs_tx_lane_map_68=0x0123 +xgxs_rx_lane_map_68=0x0123 + +######### +# port8 # +# FC19 # +######### +xgxs_tx_lane_map_80=0x0123 +xgxs_rx_lane_map_80=0x0123 + +######### +# port13# +# FC20 # +######### +xgxs_tx_lane_map_84=0x1032 +xgxs_rx_lane_map_84=0x1032 + +######### +# port14# +# FC21 # +######### +xgxs_tx_lane_map_88=0x0123 +xgxs_rx_lane_map_88=0x0123 + +######### +# port15# +# FC22 # +######### +xgxs_tx_lane_map_92=0x1032 +xgxs_rx_lane_map_92=0x1032 + +######### +# port17# +# FC24 # +######### +xgxs_tx_lane_map_102=0x1032 +xgxs_rx_lane_map_102=0x1032 + +######### +# port18# +# FC25 # +######### +xgxs_tx_lane_map_106=0x0123 +xgxs_rx_lane_map_106=0x0123 + +######### +# port19# +# FC26 # +######### +xgxs_tx_lane_map_110=0x1032 +xgxs_rx_lane_map_110=0x1032 + +######### +# port20# +# FC27 # +######### +xgxs_tx_lane_map_114=0x0123 +xgxs_rx_lane_map_114=0x0123 + +######### +# port26# +# FC29 # +######### +xgxs_tx_lane_map_122=0x0123 +xgxs_rx_lane_map_122=0x0123 + +######### +# port27# +# FC30 # +######### +xgxs_tx_lane_map_126=0x0123 +xgxs_rx_lane_map_126=0x0123 + +######### +# port29# +# FC0 # +######### +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x0123 + +# port30# +# FC1 # +######### +xgxs_tx_lane_map_5=0x0123 +xgxs_rx_lane_map_5=0x0123 + +######### +# port31# +# FC2 # +######### +xgxs_tx_lane_map_9=0x0123 +xgxs_rx_lane_map_9=0x0123 + +######### +# port32# +# FC3 # +######### +xgxs_tx_lane_map_13=0x0123 +xgxs_rx_lane_map_13=0x0123 + + +## RX / TX Serdes lane polarity flip list +## RX / TX Serdes lane polarity flip list +######### +# FC4 # +# port21 # +######### +phy_xaui_tx_polarity_flip_17=0xf + +######### +# FC20 # +# port13 # +######### +phy_xaui_rx_polarity_flip_84=0xf +phy_xaui_tx_polarity_flip_84=0x6 + +######### +# FC21 # +# port14 # +######### +phy_xaui_rx_polarity_flip_88=0xf + +######### +# FC22 # +# port15 # +######### +phy_xaui_rx_polarity_flip_92=0xf +phy_xaui_tx_polarity_flip_92=0xe + + +######### +# FC23 # +# port16 # +######### +phy_xaui_tx_polarity_flip_96=0x1 + +######### +# FC24 # +# port17 # +######### +phy_xaui_tx_polarity_flip_102=0x1 + + +######### +# FC25 # +# port18 # +######### +phy_xaui_rx_polarity_flip_106=0xf + +######### +# FC26 # +# port19 # +######### +phy_xaui_tx_polarity_flip_110=0xe + +######### +# FC27 # +# port20 # +######### +phy_xaui_rx_polarity_flip_114=0x2 + +######### +# FC28 # +# port25 # +######### +phy_xaui_rx_polarity_flip_118=0xa +phy_xaui_tx_polarity_flip_118=0xf + +#Driver Current +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_13=0x8 +serdes_driver_current_lane1_13=0x8 +serdes_driver_current_lane2_13=0x8 +serdes_driver_current_lane3_13=0x8 +serdes_driver_current_lane0_17=0x8 +serdes_driver_current_lane1_17=0x8 +serdes_driver_current_lane2_17=0x8 +serdes_driver_current_lane3_17=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_25=0x8 +serdes_driver_current_lane1_25=0x8 +serdes_driver_current_lane2_25=0x8 +serdes_driver_current_lane3_25=0x8 +serdes_driver_current_lane0_29=0x8 +serdes_driver_current_lane1_29=0x8 +serdes_driver_current_lane2_29=0x8 +serdes_driver_current_lane3_29=0x8 +serdes_driver_current_lane0_34=0x8 +serdes_driver_current_lane1_34=0x8 +serdes_driver_current_lane2_34=0x8 +serdes_driver_current_lane3_34=0x8 +serdes_driver_current_lane0_38=0x8 +serdes_driver_current_lane1_38=0x8 +serdes_driver_current_lane2_38=0x8 +serdes_driver_current_lane3_38=0x8 +serdes_driver_current_lane0_42=0x8 +serdes_driver_current_lane1_42=0x8 +serdes_driver_current_lane2_42=0x8 +serdes_driver_current_lane3_42=0x8 +serdes_driver_current_lane0_46=0x8 +serdes_driver_current_lane1_46=0x8 +serdes_driver_current_lane2_46=0x8 +serdes_driver_current_lane3_46=0x8 +serdes_driver_current_lane0_50=0x8 +serdes_driver_current_lane1_50=0x8 +serdes_driver_current_lane2_50=0x8 +serdes_driver_current_lane3_50=0x8 +serdes_driver_current_lane0_54=0x8 +serdes_driver_current_lane1_54=0x8 +serdes_driver_current_lane2_54=0x8 +serdes_driver_current_lane3_54=0x8 +serdes_driver_current_lane0_58=0x8 +serdes_driver_current_lane1_58=0x8 +serdes_driver_current_lane2_58=0x8 +serdes_driver_current_lane3_58=0x8 +serdes_driver_current_lane0_62=0x8 +serdes_driver_current_lane1_62=0x8 +serdes_driver_current_lane2_62=0x8 +serdes_driver_current_lane3_62=0x8 +serdes_driver_current_lane0_68=0x8 +serdes_driver_current_lane1_68=0x8 +serdes_driver_current_lane2_68=0x8 +serdes_driver_current_lane3_68=0x8 +serdes_driver_current_lane0_72=0x8 +serdes_driver_current_lane1_72=0x8 +serdes_driver_current_lane2_72=0x8 +serdes_driver_current_lane3_72=0x8 +serdes_driver_current_lane0_76=0x8 +serdes_driver_current_lane1_76=0x8 +serdes_driver_current_lane2_76=0x8 +serdes_driver_current_lane3_76=0x8 +serdes_driver_current_lane0_80=0x8 +serdes_driver_current_lane1_80=0x8 +serdes_driver_current_lane2_80=0x8 +serdes_driver_current_lane3_80=0x8 +serdes_driver_current_lane0_84=0x8 +serdes_driver_current_lane1_84=0x8 +serdes_driver_current_lane2_84=0x8 +serdes_driver_current_lane3_84=0x8 +serdes_driver_current_lane0_88=0x8 +serdes_driver_current_lane1_88=0x8 +serdes_driver_current_lane2_88=0x8 +serdes_driver_current_lane3_88=0x8 +serdes_driver_current_lane0_92=0x8 +serdes_driver_current_lane1_92=0x8 +serdes_driver_current_lane2_92=0x8 +serdes_driver_current_lane3_92=0x8 +serdes_driver_current_lane0_96=0x8 +serdes_driver_current_lane1_96=0x8 +serdes_driver_current_lane2_96=0x8 +serdes_driver_current_lane3_96=0x8 +serdes_driver_current_lane0_102=0x8 +serdes_driver_current_lane1_102=0x8 +serdes_driver_current_lane2_102=0x8 +serdes_driver_current_lane3_102=0x8 +serdes_driver_current_lane0_106=0x8 +serdes_driver_current_lane1_106=0x8 +serdes_driver_current_lane2_106=0x8 +serdes_driver_current_lane3_106=0x8 +serdes_driver_current_lane0_110=0x8 +serdes_driver_current_lane1_110=0x8 +serdes_driver_current_lane2_110=0x8 +serdes_driver_current_lane3_110=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_118=0x8 +serdes_driver_current_lane1_118=0x8 +serdes_driver_current_lane2_118=0x8 +serdes_driver_current_lane3_118=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 +serdes_driver_current_lane0_126=0x8 +serdes_driver_current_lane1_126=0x8 +serdes_driver_current_lane2_126=0x8 +serdes_driver_current_lane3_126=0x8 +serdes_driver_current_lane0_130=0x8 +serdes_driver_current_lane1_130=0x8 +serdes_driver_current_lane2_130=0x8 +serdes_driver_current_lane3_130=0x8 + +#Preemphasis +serdes_preemphasis_lane0_1=0x264204 +serdes_preemphasis_lane1_1=0x264204 +serdes_preemphasis_lane2_1=0x264204 +serdes_preemphasis_lane3_1=0x264204 +serdes_preemphasis_lane0_5=0x224406 +serdes_preemphasis_lane1_5=0x224406 +serdes_preemphasis_lane2_5=0x264204 +serdes_preemphasis_lane3_5=0x244206 +serdes_preemphasis_lane0_9=0x204606 +serdes_preemphasis_lane1_9=0x264204 +serdes_preemphasis_lane2_9=0x204606 +serdes_preemphasis_lane3_9=0x224406 +serdes_preemphasis_lane0_13=0x204606 +serdes_preemphasis_lane1_13=0x224406 +serdes_preemphasis_lane2_13=0x224406 +serdes_preemphasis_lane3_13=0x244206 +serdes_preemphasis_lane0_17=0x204606 +serdes_preemphasis_lane1_17=0x204606 +serdes_preemphasis_lane2_17=0x204606 +serdes_preemphasis_lane3_17=0x204606 +serdes_preemphasis_lane0_21=0x204606 +serdes_preemphasis_lane1_21=0x204606 +serdes_preemphasis_lane2_21=0x204606 +serdes_preemphasis_lane3_21=0x224406 +serdes_preemphasis_lane0_25=0x204606 +serdes_preemphasis_lane1_25=0x204606 +serdes_preemphasis_lane2_25=0x204606 +serdes_preemphasis_lane3_25=0x204606 +serdes_preemphasis_lane0_29=0x204606 +serdes_preemphasis_lane1_29=0x204606 +serdes_preemphasis_lane2_29=0x204606 +serdes_preemphasis_lane3_29=0x204606 +serdes_preemphasis_lane0_34=0x284601 +serdes_preemphasis_lane1_34=0x284601 +serdes_preemphasis_lane2_34=0x284601 +serdes_preemphasis_lane3_34=0x284601 +serdes_preemphasis_lane0_38=0x204604 +serdes_preemphasis_lane1_38=0x204604 +serdes_preemphasis_lane2_38=0x224406 +serdes_preemphasis_lane3_38=0x224406 +serdes_preemphasis_lane0_42=0x284601 +serdes_preemphasis_lane1_42=0x294501 +serdes_preemphasis_lane2_42=0x284601 +serdes_preemphasis_lane3_42=0x284601 +serdes_preemphasis_lane0_46=0x204802 +serdes_preemphasis_lane1_46=0x204802 +serdes_preemphasis_lane2_46=0x204802 +serdes_preemphasis_lane3_46=0x204802 +serdes_preemphasis_lane0_50=0x1e4f01 +serdes_preemphasis_lane1_50=0x1e4d01 +serdes_preemphasis_lane2_50=0x1e4f01 +serdes_preemphasis_lane3_50=0x1e4f01 +serdes_preemphasis_lane0_54=0x1f4a03 +serdes_preemphasis_lane1_54=0x1f4a03 +serdes_preemphasis_lane2_54=0x1f4a03 +serdes_preemphasis_lane3_54=0x1f4a03 +serdes_preemphasis_lane0_58=0x1e4f01 +serdes_preemphasis_lane1_58=0x1e4f01 +serdes_preemphasis_lane2_58=0x1e4f01 +serdes_preemphasis_lane3_58=0x1e4f01 +serdes_preemphasis_lane0_62=0x1e4e02 +serdes_preemphasis_lane1_62=0x1e4e02 +serdes_preemphasis_lane2_62=0x1e4e02 +serdes_preemphasis_lane3_62=0x1e4e02 +serdes_preemphasis_lane0_68=0x1e4f01 +serdes_preemphasis_lane1_68=0x1e4f01 +serdes_preemphasis_lane2_68=0x1e4f01 +serdes_preemphasis_lane3_68=0x1e4f01 +serdes_preemphasis_lane0_72=0x1e4e02 +serdes_preemphasis_lane1_72=0x1e4e02 +serdes_preemphasis_lane2_72=0x1e4e02 +serdes_preemphasis_lane3_72=0x1e4e02 +serdes_preemphasis_lane0_76=0x1c4d02 +serdes_preemphasis_lane1_76=0x195002 +serdes_preemphasis_lane2_76=0x195002 +serdes_preemphasis_lane3_76=0x195002 +serdes_preemphasis_lane0_80=0x1e4e02 +serdes_preemphasis_lane1_80=0x1e4e02 +serdes_preemphasis_lane2_80=0x1e4e02 +serdes_preemphasis_lane3_80=0x1e4e02 +serdes_preemphasis_lane0_84=0x234701 +serdes_preemphasis_lane1_84=0x234701 +serdes_preemphasis_lane2_84=0x234701 +serdes_preemphasis_lane3_84=0x234701 +serdes_preemphasis_lane0_88=0x224802 +serdes_preemphasis_lane1_88=0x224602 +serdes_preemphasis_lane2_88=0x224802 +serdes_preemphasis_lane3_88=0x224802 +serdes_preemphasis_lane0_92=0x234801 +serdes_preemphasis_lane1_92=0x244701 +serdes_preemphasis_lane2_92=0x234801 +serdes_preemphasis_lane3_92=0x234601 +serdes_preemphasis_lane0_96=0x204406 +serdes_preemphasis_lane1_96=0x204406 +serdes_preemphasis_lane2_96=0x204406 +serdes_preemphasis_lane3_96=0x224602 +serdes_preemphasis_lane0_102=0x204606 +serdes_preemphasis_lane1_102=0x235002 +serdes_preemphasis_lane2_102=0x204606 +serdes_preemphasis_lane3_102=0x204606 +serdes_preemphasis_lane0_106=0x204606 +serdes_preemphasis_lane1_106=0x204606 +serdes_preemphasis_lane2_106=0x204606 +serdes_preemphasis_lane3_106=0x204606 +serdes_preemphasis_lane0_110=0x204606 +serdes_preemphasis_lane1_110=0x224406 +serdes_preemphasis_lane2_110=0x224406 +serdes_preemphasis_lane3_110=0x224406 +serdes_preemphasis_lane0_114=0x224406 +serdes_preemphasis_lane1_114=0x204606 +serdes_preemphasis_lane2_114=0x204606 +serdes_preemphasis_lane3_114=0x224406 +serdes_preemphasis_lane0_118=0x224406 +serdes_preemphasis_lane1_118=0x224406 +serdes_preemphasis_lane2_118=0x224406 +serdes_preemphasis_lane3_118=0x224406 +serdes_preemphasis_lane0_122=0x244404 +serdes_preemphasis_lane1_122=0x244404 +serdes_preemphasis_lane2_122=0x244404 +serdes_preemphasis_lane3_122=0x244404 +serdes_preemphasis_lane0_126=0x234504 +serdes_preemphasis_lane1_126=0x234404 +serdes_preemphasis_lane2_126=0x224406 +serdes_preemphasis_lane3_126=0x224406 +serdes_preemphasis_lane0_130=0x244404 +serdes_preemphasis_lane1_130=0x244404 +serdes_preemphasis_lane2_130=0x234504 +serdes_preemphasis_lane3_130=0x264501 diff --git a/device/accton/x86_64-accton_as7716_32x-r0/default_sku b/device/accton/x86_64-accton_as7716_32x-r0/default_sku new file mode 100644 index 000000000000..4cd528a50e93 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7716-32X t1 diff --git a/device/accton/x86_64-accton_as7716_32x-r0/installer.conf b/device/accton/x86_64-accton_as7716_32x-r0/installer.conf new file mode 100644 index 000000000000..d97e3195e8fd --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/accton/x86_64-accton_as7716_32x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7716_32x-r0/led_proc_init.soc new file mode 100755 index 000000000000..719cb777719f --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/led_proc_init.soc @@ -0,0 +1,41 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=62 REMAP_PORT_18=61 REMAP_PORT_19=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=59 REMAP_PORT_21=58 REMAP_PORT_22=57 REMAP_PORT_23=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=55 REMAP_PORT_25=54 REMAP_PORT_26=53 REMAP_PORT_27=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=51 REMAP_PORT_29=50 REMAP_PORT_30=49 REMAP_PORT_31=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=47 REMAP_PORT_33=46 REMAP_PORT_34=45 REMAP_PORT_35=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=43 REMAP_PORT_37=42 REMAP_PORT_38=41 REMAP_PORT_39=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=39 REMAP_PORT_41=38 REMAP_PORT_42=37 REMAP_PORT_43=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=35 REMAP_PORT_45=34 REMAP_PORT_46=33 REMAP_PORT_47=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=35 REMAP_PORT_1=34 REMAP_PORT_2=33 REMAP_PORT_3=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=39 REMAP_PORT_5=38 REMAP_PORT_6=37 REMAP_PORT_7=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=43 REMAP_PORT_9=42 REMAP_PORT_10=41 REMAP_PORT_11=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=46 REMAP_PORT_14=45 REMAP_PORT_15=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=3 REMAP_PORT_17=2 REMAP_PORT_18=1 REMAP_PORT_19=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=7 REMAP_PORT_21=6 REMAP_PORT_22=5 REMAP_PORT_23=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=11 REMAP_PORT_25=10 REMAP_PORT_26=9 REMAP_PORT_27=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=15 REMAP_PORT_29=14 REMAP_PORT_30=13 REMAP_PORT_31=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 REMAP_PORT_33=18 REMAP_PORT_34=17 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 REMAP_PORT_41=26 REMAP_PORT_42=25 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 REMAP_PORT_45=30 REMAP_PORT_46=29 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start + +led 1 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start + +led auto on \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7716_32x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7716_32x-r0/plugins/eeprom.py new file mode 100755 index 000000000000..9e4e9970e9f5 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0056/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7716_32x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7716_32x-r0/plugins/psuutil.py new file mode 100755 index 000000000000..5c18e6f51b8e --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "18-0053", + 2: "17-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7716_32x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7716_32x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..7af5098d52f0 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/plugins/sfputil.py @@ -0,0 +1,245 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) +# from xcvrd +SFP_STATUS_REMOVED = '0' +SFP_STATUS_INSERTED = '1' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 32 + PORTS_IN_BLOCK = 32 + + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD_PATH = "/sys/bus/i2c/devices/11-0060/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 1: 29, + 2: 30, + 3: 31, + 4: 32, + 5: 34, + 6: 33, + 7: 36, + 8: 35, + 9: 25, + 10: 26, + 11: 27, + 12: 28, + 13: 37, + 14: 38, + 15: 39, + 16: 40, + 17: 41, + 18: 42, + 19: 43, + 20: 44, + 21: 53, + 22: 54, + 23: 55, + 24: 56, + 25: 45, + 26: 46, + 27: 47, + 28: 48, + 29: 49, + 30: 50, + 31: 51, + 32: 52, + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = self.BASE_OOM_PATH + "eeprom" + + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x] + ) + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + present_path = self.BASE_CPLD_PATH + "module_present_" + str(port_num) + self.__port_to_is_present = present_path + + content = "0" + try: + val_file = open(self.__port_to_is_present) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.port_start or port_num > self.port_end: + return False + + mod_rst_path = self.BASE_CPLD_PATH + "module_reset_" + str(port_num) + self.__port_to_mod_rst = mod_rst_path + try: + reg_file = open(self.__port_to_mod_rst, 'r+') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = '1' + + reg_file.write(reg_value) + reg_file.close() + + return True + + @property + def _get_present_bitmap(self): + nodes = [] + + nodes.append(self.BASE_CPLD_PATH + "module_present_all") + bitmap = "" + for node in nodes: + try: + reg_file = open(node) + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap += reg_file.readline().rstrip() + " " + reg_file.close() + + rev = bitmap.split(" ") + rev = "".join(rev[::-1]) + return int(rev, 16) + + data = {'valid': 0, 'last': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + port = 0 + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + reg_value = self._get_present_bitmap + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + mask = (1 << (port - 1)) + if changed_ports & mask: + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['last'] = now + self.data['valid'] = 1 + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/accton/x86_64-accton_as7716_32x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7716_32x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/port_config.ini b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/port_config.ini new file mode 100755 index 000000000000..1fa6d21d9609 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 49,50,51,52 hundredGigE1 +Ethernet4 53,54,55,56 hundredGigE2 +Ethernet8 57,58,59,60 hundredGigE3 +Ethernet12 61,62,63,64 hundredGigE4 +Ethernet16 65,66,67,68 hundredGigE5 +Ethernet20 69,70,71,72 hundredGigE6 +Ethernet24 73,74,75,76 hundredGigE7 +Ethernet28 77,78,79,80 hundredGigE8 +Ethernet32 33,34,35,36 hundredGigE9 +Ethernet36 37,38,39,40 hundredGigE10 +Ethernet40 41,42,43,44 hundredGigE11 +Ethernet44 45,46,47,48 hundredGigE12 +Ethernet48 81,82,83,84 hundredGigE13 +Ethernet52 85,86,87,88 hundredGigE14 +Ethernet56 89,90,91,92 hundredGigE15 +Ethernet60 93,94,95,96 hundredGigE16 +Ethernet64 97,98,99,100 hundredGigE17 +Ethernet68 101,102,103,104 hundredGigE18 +Ethernet72 105,106,107,108 hundredGigE19 +Ethernet76 109,110,111,112 hundredGigE20 +Ethernet80 17,18,19,20 hundredGigE21 +Ethernet84 21,22,23,24 hundredGigE22 +Ethernet88 25,26,27,28 hundredGigE23 +Ethernet92 29,30,31,32 hundredGigE24 +Ethernet96 113,114,115,116 hundredGigE25 +Ethernet100 117,118,119,120 hundredGigE26 +Ethernet104 121,122,123,124 hundredGigE27 +Ethernet108 125,126,127,128 hundredGigE28 +Ethernet112 1,2,3,4 hundredGigE29 +Ethernet116 5,6,7,8 hundredGigE30 +Ethernet120 9,10,11,12 hundredGigE31 +Ethernet124 13,14,15,16 hundredGigE32 diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/sai.profile b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/sai.profile new file mode 100755 index 000000000000..794c15a5c95a --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-as7716-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/th-as7716-32x100G.config.bcm b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/th-as7716-32x100G.config.bcm new file mode 100644 index 000000000000..1aa9f5d2c16b --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/Accton-AS7716-32XB/th-as7716-32x100G.config.bcm @@ -0,0 +1,570 @@ +# accton_as7716_32x 32x100G SDK config +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_oversubscribe=0x444444441111111104444444422222222 +pbmp_xport_xe=0x444444451111111144444444422222222 + +# +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +oversubscribe_mode=1 + +# portmap_0=x:xx +#FC0 +portmap_1=1:100 + +#FC1 +portmap_5=5:100 + +#FC2 +portmap_9=9:100 + +#FC3 +portmap_13=13:100 + +#FC4 +portmap_17=17:100 + +#FC5 +portmap_21=21:100 + +#FC6 +portmap_25=25:100 + +#FC7 +portmap_29=29:100 + +# Tile-1 +#FC8 +portmap_34=33:100 + +#FC9 +portmap_38=37:100 + +#FC10 +portmap_42=41:100 + +#FC11 +portmap_46=45:100 + +#FC12 +portmap_50=49:100 + +#FC13 +portmap_54=53:100 + +#FC14 +portmap_58=57:100 + +#FC15 +portmap_62=61:100 + +#TSC-E Management port 1 +#portmap_66=129:10 +#portmap_67=133:10 + +# Tile-2 +#FC16 +portmap_68=65:100 + +#FC17 +portmap_72=69:100 + +#FC18 +portmap_76=73:100 + +#FC19 +portmap_80=77:100 + +#FC20 +portmap_84=81:100 + +#FC21 +portmap_88=85:100 + +#FC22 +portmap_92=89:100 + +#FC23 +portmap_96=93:100 + +#TSC-E Management port 2 +#portmap_100=131:10 +#portmap_101=134:10 + +# Tile-3 +#FC24 +portmap_102=97:100 + +#FC25 +portmap_106=101:100 + +#FC26 +portmap_110=105:100 + +#FC27 +portmap_114=109:100 + +#FC28 +portmap_118=113:100 + +#FC29 +portmap_122=117:100 + +#FC30 +portmap_126=121:100 + +#FC31 +portmap_130=125:100 + + + +## TX/RX Lane Swap +######### +# port5 # +# FC16 # +######### +xgxs_tx_lane_map_68=0x0123 +xgxs_rx_lane_map_68=0x0123 + +######### +# port8 # +# FC19 # +######### +xgxs_tx_lane_map_80=0x0123 +xgxs_rx_lane_map_80=0x0123 + +######### +# port13# +# FC20 # +######### +xgxs_tx_lane_map_84=0x1032 +xgxs_rx_lane_map_84=0x1032 + +######### +# port14# +# FC21 # +######### +xgxs_tx_lane_map_88=0x0123 +xgxs_rx_lane_map_88=0x0123 + +######### +# port15# +# FC22 # +######### +xgxs_tx_lane_map_92=0x1032 +xgxs_rx_lane_map_92=0x1032 + +######### +# port17# +# FC24 # +######### +xgxs_tx_lane_map_102=0x1032 +xgxs_rx_lane_map_102=0x1032 + +######### +# port18# +# FC25 # +######### +xgxs_tx_lane_map_106=0x0123 +xgxs_rx_lane_map_106=0x0123 + +######### +# port19# +# FC26 # +######### +xgxs_tx_lane_map_110=0x1032 +xgxs_rx_lane_map_110=0x1032 + +######### +# port20# +# FC27 # +######### +xgxs_tx_lane_map_114=0x0123 +xgxs_rx_lane_map_114=0x0123 + +######### +# port26# +# FC29 # +######### +xgxs_tx_lane_map_122=0x0123 +xgxs_rx_lane_map_122=0x0123 + +######### +# port27# +# FC30 # +######### +xgxs_tx_lane_map_126=0x0123 +xgxs_rx_lane_map_126=0x0123 + +######### +# port29# +# FC0 # +######### +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x0123 + +# port30# +# FC1 # +######### +xgxs_tx_lane_map_5=0x0123 +xgxs_rx_lane_map_5=0x0123 + +######### +# port31# +# FC2 # +######### +xgxs_tx_lane_map_9=0x0123 +xgxs_rx_lane_map_9=0x0123 + +######### +# port32# +# FC3 # +######### +xgxs_tx_lane_map_13=0x0123 +xgxs_rx_lane_map_13=0x0123 + + +## RX / TX Serdes lane polarity flip list +## RX / TX Serdes lane polarity flip list +######### +# FC4 # +# port21 # +######### +phy_xaui_tx_polarity_flip_17=0xf + +######### +# FC20 # +# port13 # +######### +phy_xaui_rx_polarity_flip_84=0xf +phy_xaui_tx_polarity_flip_84=0x6 + +######### +# FC21 # +# port14 # +######### +phy_xaui_rx_polarity_flip_88=0xf + +######### +# FC22 # +# port15 # +######### +phy_xaui_rx_polarity_flip_92=0xf +phy_xaui_tx_polarity_flip_92=0xe + + +######### +# FC23 # +# port16 # +######### +phy_xaui_tx_polarity_flip_96=0x1 + +######### +# FC24 # +# port17 # +######### +phy_xaui_tx_polarity_flip_102=0x1 + + +######### +# FC25 # +# port18 # +######### +phy_xaui_rx_polarity_flip_106=0xf + +######### +# FC26 # +# port19 # +######### +phy_xaui_tx_polarity_flip_110=0xe + +######### +# FC27 # +# port20 # +######### +phy_xaui_rx_polarity_flip_114=0x2 + +######### +# FC28 # +# port25 # +######### +phy_xaui_rx_polarity_flip_118=0xa +phy_xaui_tx_polarity_flip_118=0xf + +#Driver Current +serdes_driver_current_lane0_1=0x8 +serdes_driver_current_lane1_1=0x8 +serdes_driver_current_lane2_1=0x8 +serdes_driver_current_lane3_1=0x8 +serdes_driver_current_lane0_5=0x8 +serdes_driver_current_lane1_5=0x8 +serdes_driver_current_lane2_5=0x8 +serdes_driver_current_lane3_5=0x8 +serdes_driver_current_lane0_9=0x8 +serdes_driver_current_lane1_9=0x8 +serdes_driver_current_lane2_9=0x8 +serdes_driver_current_lane3_9=0x8 +serdes_driver_current_lane0_13=0x8 +serdes_driver_current_lane1_13=0x8 +serdes_driver_current_lane2_13=0x8 +serdes_driver_current_lane3_13=0x8 +serdes_driver_current_lane0_17=0x8 +serdes_driver_current_lane1_17=0x8 +serdes_driver_current_lane2_17=0x8 +serdes_driver_current_lane3_17=0x8 +serdes_driver_current_lane0_21=0x8 +serdes_driver_current_lane1_21=0x8 +serdes_driver_current_lane2_21=0x8 +serdes_driver_current_lane3_21=0x8 +serdes_driver_current_lane0_25=0x8 +serdes_driver_current_lane1_25=0x8 +serdes_driver_current_lane2_25=0x8 +serdes_driver_current_lane3_25=0x8 +serdes_driver_current_lane0_29=0x8 +serdes_driver_current_lane1_29=0x8 +serdes_driver_current_lane2_29=0x8 +serdes_driver_current_lane3_29=0x8 +serdes_driver_current_lane0_34=0x8 +serdes_driver_current_lane1_34=0x8 +serdes_driver_current_lane2_34=0x8 +serdes_driver_current_lane3_34=0x8 +serdes_driver_current_lane0_38=0x8 +serdes_driver_current_lane1_38=0x8 +serdes_driver_current_lane2_38=0x8 +serdes_driver_current_lane3_38=0x8 +serdes_driver_current_lane0_42=0x8 +serdes_driver_current_lane1_42=0x8 +serdes_driver_current_lane2_42=0x8 +serdes_driver_current_lane3_42=0x8 +serdes_driver_current_lane0_46=0x8 +serdes_driver_current_lane1_46=0x8 +serdes_driver_current_lane2_46=0x8 +serdes_driver_current_lane3_46=0x8 +serdes_driver_current_lane0_50=0x8 +serdes_driver_current_lane1_50=0x8 +serdes_driver_current_lane2_50=0x8 +serdes_driver_current_lane3_50=0x8 +serdes_driver_current_lane0_54=0x8 +serdes_driver_current_lane1_54=0x8 +serdes_driver_current_lane2_54=0x8 +serdes_driver_current_lane3_54=0x8 +serdes_driver_current_lane0_58=0x8 +serdes_driver_current_lane1_58=0x8 +serdes_driver_current_lane2_58=0x8 +serdes_driver_current_lane3_58=0x8 +serdes_driver_current_lane0_62=0x8 +serdes_driver_current_lane1_62=0x8 +serdes_driver_current_lane2_62=0x8 +serdes_driver_current_lane3_62=0x8 +serdes_driver_current_lane0_68=0x8 +serdes_driver_current_lane1_68=0x8 +serdes_driver_current_lane2_68=0x8 +serdes_driver_current_lane3_68=0x8 +serdes_driver_current_lane0_72=0x8 +serdes_driver_current_lane1_72=0x8 +serdes_driver_current_lane2_72=0x8 +serdes_driver_current_lane3_72=0x8 +serdes_driver_current_lane0_76=0x8 +serdes_driver_current_lane1_76=0x8 +serdes_driver_current_lane2_76=0x8 +serdes_driver_current_lane3_76=0x8 +serdes_driver_current_lane0_80=0x8 +serdes_driver_current_lane1_80=0x8 +serdes_driver_current_lane2_80=0x8 +serdes_driver_current_lane3_80=0x8 +serdes_driver_current_lane0_84=0x8 +serdes_driver_current_lane1_84=0x8 +serdes_driver_current_lane2_84=0x8 +serdes_driver_current_lane3_84=0x8 +serdes_driver_current_lane0_88=0x8 +serdes_driver_current_lane1_88=0x8 +serdes_driver_current_lane2_88=0x8 +serdes_driver_current_lane3_88=0x8 +serdes_driver_current_lane0_92=0x8 +serdes_driver_current_lane1_92=0x8 +serdes_driver_current_lane2_92=0x8 +serdes_driver_current_lane3_92=0x8 +serdes_driver_current_lane0_96=0x8 +serdes_driver_current_lane1_96=0x8 +serdes_driver_current_lane2_96=0x8 +serdes_driver_current_lane3_96=0x8 +serdes_driver_current_lane0_102=0x8 +serdes_driver_current_lane1_102=0x8 +serdes_driver_current_lane2_102=0x8 +serdes_driver_current_lane3_102=0x8 +serdes_driver_current_lane0_106=0x8 +serdes_driver_current_lane1_106=0x8 +serdes_driver_current_lane2_106=0x8 +serdes_driver_current_lane3_106=0x8 +serdes_driver_current_lane0_110=0x8 +serdes_driver_current_lane1_110=0x8 +serdes_driver_current_lane2_110=0x8 +serdes_driver_current_lane3_110=0x8 +serdes_driver_current_lane0_114=0x8 +serdes_driver_current_lane1_114=0x8 +serdes_driver_current_lane2_114=0x8 +serdes_driver_current_lane3_114=0x8 +serdes_driver_current_lane0_118=0x8 +serdes_driver_current_lane1_118=0x8 +serdes_driver_current_lane2_118=0x8 +serdes_driver_current_lane3_118=0x8 +serdes_driver_current_lane0_122=0x8 +serdes_driver_current_lane1_122=0x8 +serdes_driver_current_lane2_122=0x8 +serdes_driver_current_lane3_122=0x8 +serdes_driver_current_lane0_126=0x8 +serdes_driver_current_lane1_126=0x8 +serdes_driver_current_lane2_126=0x8 +serdes_driver_current_lane3_126=0x8 +serdes_driver_current_lane0_130=0x8 +serdes_driver_current_lane1_130=0x8 +serdes_driver_current_lane2_130=0x8 +serdes_driver_current_lane3_130=0x8 + +#Preemphasis +serdes_preemphasis_lane0_1=0x264204 +serdes_preemphasis_lane1_1=0x264204 +serdes_preemphasis_lane2_1=0x264204 +serdes_preemphasis_lane3_1=0x264204 +serdes_preemphasis_lane0_5=0x224406 +serdes_preemphasis_lane1_5=0x224406 +serdes_preemphasis_lane2_5=0x264204 +serdes_preemphasis_lane3_5=0x244206 +serdes_preemphasis_lane0_9=0x204606 +serdes_preemphasis_lane1_9=0x264204 +serdes_preemphasis_lane2_9=0x204606 +serdes_preemphasis_lane3_9=0x224406 +serdes_preemphasis_lane0_13=0x204606 +serdes_preemphasis_lane1_13=0x224406 +serdes_preemphasis_lane2_13=0x224406 +serdes_preemphasis_lane3_13=0x244206 +serdes_preemphasis_lane0_17=0x204606 +serdes_preemphasis_lane1_17=0x204606 +serdes_preemphasis_lane2_17=0x204606 +serdes_preemphasis_lane3_17=0x204606 +serdes_preemphasis_lane0_21=0x204606 +serdes_preemphasis_lane1_21=0x204606 +serdes_preemphasis_lane2_21=0x204606 +serdes_preemphasis_lane3_21=0x224406 +serdes_preemphasis_lane0_25=0x204606 +serdes_preemphasis_lane1_25=0x204606 +serdes_preemphasis_lane2_25=0x204606 +serdes_preemphasis_lane3_25=0x204606 +serdes_preemphasis_lane0_29=0x204606 +serdes_preemphasis_lane1_29=0x204606 +serdes_preemphasis_lane2_29=0x204606 +serdes_preemphasis_lane3_29=0x204606 +serdes_preemphasis_lane0_34=0x284601 +serdes_preemphasis_lane1_34=0x284601 +serdes_preemphasis_lane2_34=0x284601 +serdes_preemphasis_lane3_34=0x284601 +serdes_preemphasis_lane0_38=0x204604 +serdes_preemphasis_lane1_38=0x204604 +serdes_preemphasis_lane2_38=0x224406 +serdes_preemphasis_lane3_38=0x224406 +serdes_preemphasis_lane0_42=0x284601 +serdes_preemphasis_lane1_42=0x294501 +serdes_preemphasis_lane2_42=0x284601 +serdes_preemphasis_lane3_42=0x284601 +serdes_preemphasis_lane0_46=0x204802 +serdes_preemphasis_lane1_46=0x204802 +serdes_preemphasis_lane2_46=0x204802 +serdes_preemphasis_lane3_46=0x204802 +serdes_preemphasis_lane0_50=0x1e4f01 +serdes_preemphasis_lane1_50=0x1e4d01 +serdes_preemphasis_lane2_50=0x1e4f01 +serdes_preemphasis_lane3_50=0x1e4f01 +serdes_preemphasis_lane0_54=0x1f4a03 +serdes_preemphasis_lane1_54=0x1f4a03 +serdes_preemphasis_lane2_54=0x1f4a03 +serdes_preemphasis_lane3_54=0x1f4a03 +serdes_preemphasis_lane0_58=0x1e4f01 +serdes_preemphasis_lane1_58=0x1e4f01 +serdes_preemphasis_lane2_58=0x1e4f01 +serdes_preemphasis_lane3_58=0x1e4f01 +serdes_preemphasis_lane0_62=0x1e4e02 +serdes_preemphasis_lane1_62=0x1e4e02 +serdes_preemphasis_lane2_62=0x1e4e02 +serdes_preemphasis_lane3_62=0x1e4e02 +serdes_preemphasis_lane0_68=0x1e4f01 +serdes_preemphasis_lane1_68=0x1e4f01 +serdes_preemphasis_lane2_68=0x1e4f01 +serdes_preemphasis_lane3_68=0x1e4f01 +serdes_preemphasis_lane0_72=0x1e4e02 +serdes_preemphasis_lane1_72=0x1e4e02 +serdes_preemphasis_lane2_72=0x1e4e02 +serdes_preemphasis_lane3_72=0x1e4e02 +serdes_preemphasis_lane0_76=0x1c4d02 +serdes_preemphasis_lane1_76=0x195002 +serdes_preemphasis_lane2_76=0x195002 +serdes_preemphasis_lane3_76=0x195002 +serdes_preemphasis_lane0_80=0x1e4e02 +serdes_preemphasis_lane1_80=0x1e4e02 +serdes_preemphasis_lane2_80=0x1e4e02 +serdes_preemphasis_lane3_80=0x1e4e02 +serdes_preemphasis_lane0_84=0x234701 +serdes_preemphasis_lane1_84=0x234701 +serdes_preemphasis_lane2_84=0x234701 +serdes_preemphasis_lane3_84=0x234701 +serdes_preemphasis_lane0_88=0x224802 +serdes_preemphasis_lane1_88=0x224602 +serdes_preemphasis_lane2_88=0x224802 +serdes_preemphasis_lane3_88=0x224802 +serdes_preemphasis_lane0_92=0x234801 +serdes_preemphasis_lane1_92=0x244701 +serdes_preemphasis_lane2_92=0x234801 +serdes_preemphasis_lane3_92=0x234601 +serdes_preemphasis_lane0_96=0x204406 +serdes_preemphasis_lane1_96=0x204406 +serdes_preemphasis_lane2_96=0x204406 +serdes_preemphasis_lane3_96=0x224602 +serdes_preemphasis_lane0_102=0x204606 +serdes_preemphasis_lane1_102=0x235002 +serdes_preemphasis_lane2_102=0x204606 +serdes_preemphasis_lane3_102=0x204606 +serdes_preemphasis_lane0_106=0x204606 +serdes_preemphasis_lane1_106=0x204606 +serdes_preemphasis_lane2_106=0x204606 +serdes_preemphasis_lane3_106=0x204606 +serdes_preemphasis_lane0_110=0x204606 +serdes_preemphasis_lane1_110=0x224406 +serdes_preemphasis_lane2_110=0x224406 +serdes_preemphasis_lane3_110=0x224406 +serdes_preemphasis_lane0_114=0x224406 +serdes_preemphasis_lane1_114=0x204606 +serdes_preemphasis_lane2_114=0x204606 +serdes_preemphasis_lane3_114=0x224406 +serdes_preemphasis_lane0_118=0x224406 +serdes_preemphasis_lane1_118=0x224406 +serdes_preemphasis_lane2_118=0x224406 +serdes_preemphasis_lane3_118=0x224406 +serdes_preemphasis_lane0_122=0x244404 +serdes_preemphasis_lane1_122=0x244404 +serdes_preemphasis_lane2_122=0x244404 +serdes_preemphasis_lane3_122=0x244404 +serdes_preemphasis_lane0_126=0x234504 +serdes_preemphasis_lane1_126=0x234404 +serdes_preemphasis_lane2_126=0x224406 +serdes_preemphasis_lane3_126=0x224406 +serdes_preemphasis_lane0_130=0x244404 +serdes_preemphasis_lane1_130=0x244404 +serdes_preemphasis_lane2_130=0x234504 +serdes_preemphasis_lane3_130=0x264501 diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/default_sku b/device/accton/x86_64-accton_as7716_32xb-r0/default_sku new file mode 100644 index 000000000000..973e749a1fc7 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7716-32XB t1 diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/installer.conf b/device/accton/x86_64-accton_as7716_32xb-r0/installer.conf new file mode 100755 index 000000000000..d97e3195e8fd --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7716_32xb-r0/led_proc_init.soc new file mode 100755 index 000000000000..719cb777719f --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/led_proc_init.soc @@ -0,0 +1,41 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=62 REMAP_PORT_18=61 REMAP_PORT_19=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=59 REMAP_PORT_21=58 REMAP_PORT_22=57 REMAP_PORT_23=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=55 REMAP_PORT_25=54 REMAP_PORT_26=53 REMAP_PORT_27=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=51 REMAP_PORT_29=50 REMAP_PORT_30=49 REMAP_PORT_31=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=47 REMAP_PORT_33=46 REMAP_PORT_34=45 REMAP_PORT_35=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=43 REMAP_PORT_37=42 REMAP_PORT_38=41 REMAP_PORT_39=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=39 REMAP_PORT_41=38 REMAP_PORT_42=37 REMAP_PORT_43=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=35 REMAP_PORT_45=34 REMAP_PORT_46=33 REMAP_PORT_47=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=35 REMAP_PORT_1=34 REMAP_PORT_2=33 REMAP_PORT_3=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=39 REMAP_PORT_5=38 REMAP_PORT_6=37 REMAP_PORT_7=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=43 REMAP_PORT_9=42 REMAP_PORT_10=41 REMAP_PORT_11=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=46 REMAP_PORT_14=45 REMAP_PORT_15=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=3 REMAP_PORT_17=2 REMAP_PORT_18=1 REMAP_PORT_19=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=7 REMAP_PORT_21=6 REMAP_PORT_22=5 REMAP_PORT_23=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=11 REMAP_PORT_25=10 REMAP_PORT_26=9 REMAP_PORT_27=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=15 REMAP_PORT_29=14 REMAP_PORT_30=13 REMAP_PORT_31=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 REMAP_PORT_33=18 REMAP_PORT_34=17 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 REMAP_PORT_41=26 REMAP_PORT_42=25 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 REMAP_PORT_45=30 REMAP_PORT_46=29 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 start + +led 1 prog 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 84 67 98 57 80 18 71 EB 67 98 67 84 57 67 84 67 84 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 start + +led auto on \ No newline at end of file diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/eeprom.py new file mode 100755 index 000000000000..0982e699367a --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/0-0056/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/psuutil.py new file mode 100755 index 000000000000..d4815ac85cec --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "0-0053", + 2: "0-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/sfputil.py new file mode 100755 index 000000000000..af8b9dd2fa02 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/plugins/sfputil.py @@ -0,0 +1,141 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import sys + import subprocess + 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 = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD_PATH = "/sys/bus/i2c/devices/0-0060/" + BASE_I2C_PATH = "/sys/bus/i2c/devices/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 0: [1, 29], + 1: [2, 30], + 2: [3, 31], + 3: [4, 32], + 4: [5, 34], + 5: [6, 33], + 6: [7, 36], + 7: [8, 35], + 8: [9, 25], + 9: [10, 26], + 10: [11, 27], + 11: [12, 28], + 12: [14, 37], + 13: [15, 38], + 14: [16, 39], + 15: [17, 40], + 16: [18, 41], + 17: [19, 42], + 18: [20, 43], + 19: [21, 44], + 20: [22, 53], + 21: [23, 54], + 22: [24, 55], + 23: [25, 56], + 24: [26, 45], + 25: [27, 46], + 26: [28, 47], + 27: [29, 48], + 28: [30, 49], + 29: [31, 50], + 30: [32, 51], + 31: [33, 52], + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + 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 + + present_path = self.BASE_CPLD_PATH + "module_present_" + str(port_num+1) + self.__port_to_is_present = present_path + + content = "0" + try: + val_file = open(self.__port_to_is_present) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def __init__(self): + eeprom_path = self.BASE_I2C_PATH + + for x in range(0, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x][1] + ) + if(x < 9): + if(self.get_presence(x) == 1): + self.port_to_eeprom_mapping[x] = self.BASE_I2C_PATH + "0-000" + str(x+1) + "/eeprom" + + else: + if(self.get_presence(x) == 1): + self.port_to_eeprom_mapping[x] = self.BASE_I2C_PATH + "0-00" + str(x+1) + "/eeprom" + + SfpUtilBase.__init__(self) + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def set_low_power_mode(self, port_num, lpmode): + raise NotImplementedError + + def reset(self, port_num): + if port_num < self.port_start or port_num > self.port_end: + return False + + mod_rst_cmd = "ipmitool raw 0x34 0x11 " + str(port_num+1) + " 0x11 0x1" + subprocess.check_output(mod_rst_cmd, universal_newlines=True) + return True + + 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 diff --git a/device/accton/x86_64-accton_as7716_32xb-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7716_32xb-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7716_32xb-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/port_config.ini b/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/port_config.ini new file mode 100755 index 000000000000..c12f3b3ba276 --- /dev/null +++ b/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4 hundredGigE1 1 100000 +Ethernet4 5,6,7,8 hundredGigE2 2 100000 +Ethernet8 9,10,11,12 hundredGigE3 3 100000 +Ethernet12 13,14,15,16 hundredGigE4 4 100000 +Ethernet16 17,18,19,20 hundredGigE5 5 100000 +Ethernet20 21,22,23,24 hundredGigE6 6 100000 +Ethernet24 25,26,27,28 hundredGigE7 7 100000 +Ethernet28 29,30,31,32 hundredGigE8 8 100000 +Ethernet32 33,34,35,36 hundredGigE9 9 100000 +Ethernet36 37,38,39,40 hundredGigE10 10 100000 +Ethernet40 41,42,43,44 hundredGigE11 11 100000 +Ethernet44 45,46,47,48 hundredGigE12 12 100000 +Ethernet48 49,50,51,52 hundredGigE13 13 100000 +Ethernet52 53,54,55,56 hundredGigE14 14 100000 +Ethernet56 57,58,59,60 hundredGigE15 15 100000 +Ethernet60 61,62,63,64 hundredGigE16 16 100000 +Ethernet64 65,66,67,68 hundredGigE17 17 100000 +Ethernet68 69,70,71,72 hundredGigE18 18 100000 +Ethernet72 73,74,75,76 hundredGigE19 19 100000 +Ethernet76 77,78,79,80 hundredGigE20 20 100000 +Ethernet80 81,82,83,84 hundredGigE21 21 100000 +Ethernet84 85,86,87,88 hundredGigE22 22 100000 +Ethernet88 89,90,91,92 hundredGigE23 23 100000 +Ethernet92 93,94,95,96 hundredGigE24 24 100000 +Ethernet96 97,98,99,100 hundredGigE25 25 100000 +Ethernet100 101,102,103,104 hundredGigE26 26 100000 +Ethernet104 105,106,107,108 hundredGigE27 27 100000 +Ethernet108 109,110,111,112 hundredGigE28 28 100000 +Ethernet112 113,114,115,116 hundredGigE29 29 100000 +Ethernet116 117,118,119,120 hundredGigE30 30 100000 +Ethernet120 121,122,123,124 hundredGigE31 31 100000 +Ethernet124 125,126,127,128 hundredGigE32 32 100000 diff --git a/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/sai.profile b/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/sai.profile new file mode 100644 index 000000000000..276f982e3e3d --- /dev/null +++ b/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-as7726-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/td3-as7726-32x100G.config.bcm b/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/td3-as7726-32x100G.config.bcm new file mode 100755 index 000000000000..f88656bfd5cf --- /dev/null +++ b/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/td3-as7726-32x100G.config.bcm @@ -0,0 +1,494 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +#polarity/lanemap is using TH2 style. +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +oversubscribe_mode=1 + +pbmp_xport_xe=0x4888888888888888c2222222222222222 + +parity_enable=0 +mem_cache_enable=0 + +l2_mem_entries=32768 +l3_mem_entries=16384 +fpem_mem_entries=16384 +l2xmsg_mode=1 + +# Platform specfic +bcm_num_cos=10 +bcm_stat_interval=2000000 +cdma_timeout_usec=3000000 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l3_max_ecmp_mode=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +port_flex_enable=1 +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 +skip_L2_USER_ENTRY=0 +bcm_tunnel_term_compatible_mode=1 +l3_alpm_ipv6_128b_bkt_rsvd=1 +phy_an_c73=1 + +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 + +portmap_1=1:100 +portmap_5=5:100 +portmap_9=9:100 +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_57=57:100 +portmap_61=61:100 +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_99=97:100 +portmap_103=101:100 +portmap_107=105:100 +portmap_111=109:100 +portmap_115=113:100 +portmap_119=117:100 +portmap_123=121:100 +portmap_127=125:100 +#portmap_66=129:10:m +#portmap_130=128:10:m +#portmap_65=130:10 +#portmap_131=131:10 + +phy_chain_rx_lane_map_physical{1.0}=0x1320 +phy_chain_rx_lane_map_physical{5.0}=0x0123 +phy_chain_rx_lane_map_physical{9.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_lane_map_physical{25.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x1230 +phy_chain_rx_lane_map_physical{33.0}=0x0123 +phy_chain_rx_lane_map_physical{37.0}=0x3210 +phy_chain_rx_lane_map_physical{41.0}=0x0123 +phy_chain_rx_lane_map_physical{45.0}=0x3210 +phy_chain_rx_lane_map_physical{49.0}=0x0213 +phy_chain_rx_lane_map_physical{53.0}=0x1320 +phy_chain_rx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{61.0}=0x0123 +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{69.0}=0x1032 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_rx_lane_map_physical{77.0}=0x3201 +phy_chain_rx_lane_map_physical{81.0}=0x3120 +phy_chain_rx_lane_map_physical{85.0}=0x0123 +phy_chain_rx_lane_map_physical{89.0}=0x3210 +phy_chain_rx_lane_map_physical{93.0}=0x0123 +phy_chain_rx_lane_map_physical{97.0}=0x3012 +phy_chain_rx_lane_map_physical{101.0}=0x3210 +phy_chain_rx_lane_map_physical{105.0}=0x3210 +phy_chain_rx_lane_map_physical{109.0}=0x3210 +phy_chain_rx_lane_map_physical{113.0}=0x3210 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_rx_lane_map_physical{121.0}=0x3210 +phy_chain_rx_lane_map_physical{125.0}=0x3210 +phy_chain_tx_lane_map_physical{1.0}=0x3210 +phy_chain_tx_lane_map_physical{5.0}=0x3210 +phy_chain_tx_lane_map_physical{9.0}=0x3210 +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_tx_lane_map_physical{17.0}=0x3210 +phy_chain_tx_lane_map_physical{21.0}=0x3210 +phy_chain_tx_lane_map_physical{25.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x3120 +phy_chain_tx_lane_map_physical{33.0}=0x0123 +phy_chain_tx_lane_map_physical{37.0}=0x3210 +phy_chain_tx_lane_map_physical{41.0}=0x0123 +phy_chain_tx_lane_map_physical{45.0}=0x3210 +phy_chain_tx_lane_map_physical{49.0}=0x2310 +phy_chain_tx_lane_map_physical{53.0}=0x3210 +phy_chain_tx_lane_map_physical{57.0}=0x1230 +phy_chain_tx_lane_map_physical{61.0}=0x1230 +phy_chain_tx_lane_map_physical{65.0}=0x1302 +phy_chain_tx_lane_map_physical{69.0}=0x0123 +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_tx_lane_map_physical{77.0}=0x2013 +phy_chain_tx_lane_map_physical{81.0}=0x3210 +phy_chain_tx_lane_map_physical{85.0}=0x0123 +phy_chain_tx_lane_map_physical{89.0}=0x3210 +phy_chain_tx_lane_map_physical{93.0}=0x0123 +phy_chain_tx_lane_map_physical{97.0}=0x0123 +phy_chain_tx_lane_map_physical{101.0}=0x0123 +phy_chain_tx_lane_map_physical{105.0}=0x0123 +phy_chain_tx_lane_map_physical{109.0}=0x0123 +phy_chain_tx_lane_map_physical{113.0}=0x0123 +phy_chain_tx_lane_map_physical{117.0}=0x0123 +phy_chain_tx_lane_map_physical{121.0}=0x0123 +phy_chain_tx_lane_map_physical{125.0}=0x0123 + +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x1 + +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x1 + +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x1 + +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 + +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 + +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 + +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +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}=0x0 +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}=0x1 + +phy_chain_rx_polarity_flip_physical{41.0}=0x1 +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}=0x0 + +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +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}=0x1 + +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 + +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 + +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.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}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 + +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 + +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x1 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{76.0}=0x1 + +phy_chain_rx_polarity_flip_physical{77.0}=0x0 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x0 + +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x1 +phy_chain_rx_polarity_flip_physical{84.0}=0x1 + +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +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}=0x0 + +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 + +phy_chain_rx_polarity_flip_physical{93.0}=0x0 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 + +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 + +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +phy_chain_rx_polarity_flip_physical{102.0}=0x1 +phy_chain_rx_polarity_flip_physical{103.0}=0x1 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 + +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 + +phy_chain_rx_polarity_flip_physical{117.0}=0x0 +phy_chain_rx_polarity_flip_physical{118.0}=0x1 +phy_chain_rx_polarity_flip_physical{119.0}=0x0 +phy_chain_rx_polarity_flip_physical{120.0}=0x1 + +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 + +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 + +phy_chain_tx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 + +phy_chain_tx_polarity_flip_physical{13.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 + +phy_chain_tx_polarity_flip_physical{17.0}=0x1 +phy_chain_tx_polarity_flip_physical{18.0}=0x0 +phy_chain_tx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x0 + +phy_chain_tx_polarity_flip_physical{21.0}=0x1 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 + +phy_chain_tx_polarity_flip_physical{25.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 + +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 + +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +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}=0x0 + +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 + +phy_chain_tx_polarity_flip_physical{45.0}=0x1 +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}=0x0 + +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x0 +phy_chain_tx_polarity_flip_physical{56.0}=0x1 + +phy_chain_tx_polarity_flip_physical{57.0}=0x1 +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}=0x0 + +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +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}=0x0 + +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}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 + +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 + +phy_chain_tx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x1 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x1 + +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 + +phy_chain_tx_polarity_flip_physical{81.0}=0x1 +phy_chain_tx_polarity_flip_physical{82.0}=0x0 +phy_chain_tx_polarity_flip_physical{83.0}=0x1 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 + +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +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}=0x0 + +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{90.0}=0x0 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 + +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +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}=0x0 + +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 + +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +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}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x0 + +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x0 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x1 +phy_chain_tx_polarity_flip_physical{120.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}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 + +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +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 diff --git a/device/accton/x86_64-accton_as7726_32x-r0/custom_led.bin b/device/accton/x86_64-accton_as7726_32x-r0/custom_led.bin new file mode 100755 index 000000000000..73dcf0e085dc Binary files /dev/null and b/device/accton/x86_64-accton_as7726_32x-r0/custom_led.bin differ diff --git a/device/accton/x86_64-accton_as7726_32x-r0/default_sku b/device/accton/x86_64-accton_as7726_32x-r0/default_sku new file mode 100644 index 000000000000..1573f369d71c --- /dev/null +++ b/device/accton/x86_64-accton_as7726_32x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7726-32X t1 diff --git a/device/accton/x86_64-accton_as7726_32x-r0/installer.conf b/device/accton/x86_64-accton_as7726_32x-r0/installer.conf new file mode 100755 index 000000000000..3455d9ca4ed1 --- /dev/null +++ b/device/accton/x86_64-accton_as7726_32x-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pcie_aspm=off" diff --git a/device/accton/x86_64-accton_as7726_32x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7726_32x-r0/led_proc_init.soc new file mode 100644 index 000000000000..1b1e6403d902 --- /dev/null +++ b/device/accton/x86_64-accton_as7726_32x-r0/led_proc_init.soc @@ -0,0 +1,4 @@ + +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/accton/x86_64-accton_as7726_32x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7726_32x-r0/plugins/eeprom.py new file mode 100755 index 000000000000..5ff41c3bac24 --- /dev/null +++ b/device/accton/x86_64-accton_as7726_32x-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/0-0056/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/1-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7726_32x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7726_32x-r0/plugins/psuutil.py new file mode 100755 index 000000000000..92b453784721 --- /dev/null +++ b/device/accton/x86_64-accton_as7726_32x-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 2: "49-0050", + 1: "50-0053", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7726_32x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7726_32x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..350c2245fe3b --- /dev/null +++ b/device/accton/x86_64-accton_as7726_32x-r0/plugins/sfputil.py @@ -0,0 +1,256 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# from xcvrd +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 32 # 34 cages actually, but last 2 are not at port_config.ini. + PORTS_IN_BLOCK = 32 + + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD_PATH = "/sys/bus/i2c/devices/11-0060/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 1: 21, + 2: 22, + 3: 23, + 4: 24, + 5: 26, + 6: 25, + 7: 28, + 8: 27, + 9: 17, + 10: 18, + 11: 19, + 12: 20, + 13: 29, + 14: 30, + 15: 31, + 16: 32, + 17: 33, + 18: 34, + 19: 35, + 20: 36, + 21: 45, + 22: 46, + 23: 47, + 24: 48, + 25: 37, + 26: 38, + 27: 39, + 28: 40, + 29: 41, + 30: 42, + 31: 43, + 32: 44, + 33: 15, + 34: 16, + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = self.BASE_OOM_PATH + "eeprom" + + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x] + ) + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if not port_num in range(self.port_start, self.port_end+1): + return False + + present_path = self.BASE_CPLD_PATH + "module_present_" + str(port_num) + self.__port_to_is_present = present_path + + content = "0" + try: + val_file = open(self.__port_to_is_present) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.port_start or port_num > self.port_end: + return False + + mod_rst_path = self.BASE_CPLD_PATH + "module_reset_" + str(port_num) + + self.__port_to_mod_rst = mod_rst_path + try: + reg_file = open(self.__port_to_mod_rst, 'r+', buffering=0) + 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 + + @property + def get_transceiver_status(self): + nodes = [] + + cpld_path = self.BASE_CPLD_PATH + nodes.append(cpld_path + "module_present_all") + + bitmap = "" + for node in nodes: + try: + reg_file = open(node) + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap += reg_file.readline().rstrip() + " " + reg_file.close() + + rev = bitmap.split(" ") + rev = "".join(rev[::-1]) + return int(rev, 16) + + data = {'valid': 0, 'last': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + port = 0 + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + reg_value = self.get_transceiver_status + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + fp_port = port + mask = (1 << (fp_port - 1)) + if changed_ports & mask: + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['last'] = now + self.data['valid'] = 1 + + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/accton/x86_64-accton_as7726_32x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7726_32x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7726_32x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/port_config.ini b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/port_config.ini new file mode 100644 index 000000000000..8ebbd52c5543 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index speed +Ethernet0 73,74,75,76 hundredGigE1 1 100000 +Ethernet4 65,66,67,68 hundredGigE2 2 100000 +Ethernet8 81,82,83,84 hundredGigE3 3 100000 +Ethernet12 89,90,91,92 hundredGigE4 4 100000 +Ethernet16 105,106,107,108 hundredGigE5 5 100000 +Ethernet20 97,98,99,100 hundredGigE6 6 100000 +Ethernet24 113,114,115,116 hundredGigE7 7 100000 +Ethernet28 121,122,123,124 hundredGigE8 8 100000 +Ethernet32 41,42,43,44 hundredGigE9 9 100000 +Ethernet36 33,34,35,36 hundredGigE10 10 100000 +Ethernet40 49,50,51,52 hundredGigE11 11 100000 +Ethernet44 57,58,59,60 hundredGigE12 12 100000 +Ethernet48 137,138,139,140 hundredGigE13 13 100000 +Ethernet52 129,130,131,132 hundredGigE14 14 100000 +Ethernet56 145,146,147,148 hundredGigE15 15 100000 +Ethernet60 153,154,155,156 hundredGigE16 16 100000 +Ethernet64 173,174,175,176 hundredGigE17 17 100000 +Ethernet68 165,166,167,168 hundredGigE18 18 100000 +Ethernet72 181,182,183,184 hundredGigE19 19 100000 +Ethernet76 189,190,191,192 hundredGigE20 20 100000 +Ethernet80 13,14,15,16 hundredGigE21 21 100000 +Ethernet84 5,6,7,8 hundredGigE22 22 100000 +Ethernet88 29,30,31,32 hundredGigE23 23 100000 +Ethernet92 21,22,23,24 hundredGigE24 24 100000 +Ethernet96 205,206,207,208 hundredGigE25 25 100000 +Ethernet100 197,198,199,200 hundredGigE26 26 100000 +Ethernet104 213,214,215,216 hundredGigE27 27 100000 +Ethernet108 221,222,223,224 hundredGigE28 28 100000 +Ethernet112 229,230,231,232 hundredGigE29 29 100000 +Ethernet116 237,238,239,240 hundredGigE30 30 100000 +Ethernet120 245,246,247,248 hundredGigE31 31 100000 +Ethernet124 253,254,255,256 hundredGigE32 32 100000 +Ethernet128 69,70,71,72 hundredGigE33 33 100000 +Ethernet132 77,78,79,80 hundredGigE34 34 100000 +Ethernet136 93,94,95,96 hundredGigE35 35 100000 +Ethernet140 85,86,87,88 hundredGigE36 36 100000 +Ethernet144 101,102,103,104 hundredGigE37 37 100000 +Ethernet148 109,110,111,112 hundredGigE38 38 100000 +Ethernet152 125,126,127,128 hundredGigE39 39 100000 +Ethernet156 117,118,119,120 hundredGigE40 40 100000 +Ethernet160 37,38,39,40 hundredGigE41 41 100000 +Ethernet164 45,46,47,48 hundredGigE42 42 100000 +Ethernet168 61,62,63,64 hundredGigE43 43 100000 +Ethernet172 53,54,55,56 hundredGigE44 44 100000 +Ethernet176 133,134,135,136 hundredGigE45 45 100000 +Ethernet180 141,142,143,144 hundredGigE46 46 100000 +Ethernet184 157,158,159,160 hundredGigE47 47 100000 +Ethernet188 149,150,151,152 hundredGigE48 48 100000 +Ethernet192 161,162,163,164 hundredGigE49 49 100000 +Ethernet196 169,170,171,172 hundredGigE50 50 100000 +Ethernet200 185,186,187,188 hundredGigE51 51 100000 +Ethernet204 177,178,179,180 hundredGigE52 52 100000 +Ethernet208 1,2,3,4 hundredGigE53 53 100000 +Ethernet212 9,10,11,12 hundredGigE54 54 100000 +Ethernet216 25,26,27,28 hundredGigE55 55 100000 +Ethernet220 17,18,19,20 hundredGigE56 56 100000 +Ethernet224 193,194,195,196 hundredGigE57 57 100000 +Ethernet228 201,202,203,204 hundredGigE58 58 100000 +Ethernet232 217,218,219,220 hundredGigE59 59 100000 +Ethernet236 209,210,211,212 hundredGigE60 60 100000 +Ethernet240 225,226,227,228 hundredGigE61 61 100000 +Ethernet244 233,234,235,236 hundredGigE62 62 100000 +Ethernet248 249,250,251,252 hundredGigE63 63 100000 +Ethernet252 241,242,243,244 hundredGigE64 64 100000 diff --git a/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/sai.profile b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/sai.profile new file mode 100644 index 000000000000..7c7d74d3ce9e --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-as7816-64x25G-48x100G_row1.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/th2-as7816-64x25G-48x100G_row1.config.bcm b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/th2-as7816-64x25G-48x100G_row1.config.bcm new file mode 100644 index 000000000000..bceebfddaf18 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/Accton-AS7816-64X/th2-as7816-64x25G-48x100G_row1.config.bcm @@ -0,0 +1,1183 @@ +# accton_as7816_64x 64x100G SDK config +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +pbmp_oversubscribe=0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +# platform specific setting +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +oversubscribe_mode=1 +port_flex_enable=1 + +#add loopback port +# port 33 is the first loopback port +#portmap_33=260:10 +# port 66 is the first management port +#portmap_66=257:10 +# port 67 is the second loopback port +#portmap_67=261:10 +# port 100 is the second management port +#portmap_100=259:10 +# port 101 is the third loopback port +#portmap_101=262:10 +# port 135 is the fourth loopback port +#portmap_135=263:10 + +#Port0 +#FC18 +#dport_map_port_34=1 +dport_map_port_34=73 +dport_map_port_35=74 +dport_map_port_36=75 +dport_map_port_37=76 +portmap_34=73:100 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_rx_lane_map_physical{74.0}=0x3210 +phy_chain_rx_lane_map_physical{75.0}=0x3210 +phy_chain_rx_lane_map_physical{76.0}=0x3210 +phy_chain_tx_lane_map_physical{73.0}=0x3021 +phy_chain_tx_lane_map_physical{74.0}=0x3021 +phy_chain_tx_lane_map_physical{75.0}=0x3021 +phy_chain_tx_lane_map_physical{76.0}=0x3021 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{76.0}=0x1 +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x1 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 + +#Port2 +#FC20 +#dport_map_port_39=5 +dport_map_port_39=81 +dport_map_port_40=82 +dport_map_port_41=83 +dport_map_port_42=84 +portmap_39=81:100 +phy_chain_rx_lane_map_physical{81.0}=0x1230 +phy_chain_rx_lane_map_physical{82.0}=0x1230 +phy_chain_rx_lane_map_physical{83.0}=0x1230 +phy_chain_rx_lane_map_physical{84.0}=0x1230 +phy_chain_tx_lane_map_physical{81.0}=0x1032 +phy_chain_tx_lane_map_physical{82.0}=0x1032 +phy_chain_tx_lane_map_physical{83.0}=0x1032 +phy_chain_tx_lane_map_physical{84.0}=0x1032 +phy_chain_rx_polarity_flip_physical{81.0}=0x1 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x1 +phy_chain_rx_polarity_flip_physical{84.0}=0x0 +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}=0x0 + +#Port4 +#FC26 +#dport_map_port_44=9 +dport_map_port_44=105 +dport_map_port_45=106 +dport_map_port_46=107 +dport_map_port_47=108 +portmap_44=105:100 +phy_chain_rx_lane_map_physical{105.0}=0x3210 +phy_chain_rx_lane_map_physical{106.0}=0x3210 +phy_chain_rx_lane_map_physical{107.0}=0x3210 +phy_chain_rx_lane_map_physical{108.0}=0x3210 +phy_chain_tx_lane_map_physical{105.0}=0x0231 +phy_chain_tx_lane_map_physical{106.0}=0x0231 +phy_chain_tx_lane_map_physical{107.0}=0x0231 +phy_chain_tx_lane_map_physical{108.0}=0x0231 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x0 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 + +#Port6 +#FC 28 +#dport_map_port_49=13 +dport_map_port_49=113 +dport_map_port_50=114 +dport_map_port_51=115 +dport_map_port_52=116 +portmap_49=113:100 +phy_chain_rx_lane_map_physical{113.0}=0x3021 +phy_chain_rx_lane_map_physical{114.0}=0x3021 +phy_chain_rx_lane_map_physical{115.0}=0x3021 +phy_chain_rx_lane_map_physical{116.0}=0x3021 +phy_chain_tx_lane_map_physical{113.0}=0x0312 +phy_chain_tx_lane_map_physical{114.0}=0x0312 +phy_chain_tx_lane_map_physical{115.0}=0x0312 +phy_chain_tx_lane_map_physical{116.0}=0x0312 +phy_chain_rx_polarity_flip_physical{113.0}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +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}=0x1 + +#Port8 +#FC10 +#dport_map_port_1=17 +dport_map_port_1=41 +dport_map_port_2=42 +dport_map_port_3=43 +dport_map_port_4=44 +portmap_1=41:100 +phy_chain_rx_lane_map_physical{41.0}=0x0132 +phy_chain_rx_lane_map_physical{42.0}=0x0132 +phy_chain_rx_lane_map_physical{43.0}=0x0132 +phy_chain_rx_lane_map_physical{44.0}=0x0132 +phy_chain_tx_lane_map_physical{41.0}=0x1302 +phy_chain_tx_lane_map_physical{42.0}=0x1302 +phy_chain_tx_lane_map_physical{43.0}=0x1302 +phy_chain_tx_lane_map_physical{44.0}=0x1302 +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}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 + +#Port10 +#FC12 +#dport_map_port_6=21 +dport_map_port_6=49 +dport_map_port_7=50 +dport_map_port_8=51 +dport_map_port_9=52 +portmap_6=49:100 +phy_chain_rx_lane_map_physical{49.0}=0x3210 +phy_chain_rx_lane_map_physical{50.0}=0x3210 +phy_chain_rx_lane_map_physical{51.0}=0x3210 +phy_chain_rx_lane_map_physical{52.0}=0x3210 +phy_chain_tx_lane_map_physical{49.0}=0x3102 +phy_chain_tx_lane_map_physical{50.0}=0x3102 +phy_chain_tx_lane_map_physical{51.0}=0x3102 +phy_chain_tx_lane_map_physical{52.0}=0x3102 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 + +#Port12 +#FC34 +#dport_map_port_68=25 +dport_map_port_68=137 +dport_map_port_69=138 +dport_map_port_70=139 +dport_map_port_71=140 +portmap_68=137:100 +phy_chain_rx_lane_map_physical{137.0}=0x3210 +phy_chain_rx_lane_map_physical{138.0}=0x3210 +phy_chain_rx_lane_map_physical{139.0}=0x3210 +phy_chain_rx_lane_map_physical{140.0}=0x3210 +phy_chain_tx_lane_map_physical{137.0}=0x0213 +phy_chain_tx_lane_map_physical{138.0}=0x0213 +phy_chain_tx_lane_map_physical{139.0}=0x0213 +phy_chain_tx_lane_map_physical{140.0}=0x0213 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x0 +phy_chain_tx_polarity_flip_physical{140.0}=0x0 + +#Port14 +#FC36 +#dport_map_port_73=29 +dport_map_port_73=145 +dport_map_port_74=146 +dport_map_port_75=147 +dport_map_port_76=148 +portmap_73=145:100 +phy_chain_rx_lane_map_physical{145.0}=0x0213 +phy_chain_rx_lane_map_physical{146.0}=0x0213 +phy_chain_rx_lane_map_physical{147.0}=0x0213 +phy_chain_rx_lane_map_physical{148.0}=0x0213 +phy_chain_tx_lane_map_physical{145.0}=0x2301 +phy_chain_tx_lane_map_physical{146.0}=0x2301 +phy_chain_tx_lane_map_physical{147.0}=0x2301 +phy_chain_tx_lane_map_physical{148.0}=0x2301 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x1 +phy_chain_rx_polarity_flip_physical{147.0}=0x0 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{145.0}=0x0 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x1 + +#Port16 +#FC43 +#dport_map_port_78=33 +dport_map_port_78=173 +dport_map_port_79=174 +dport_map_port_80=175 +dport_map_port_81=176 +portmap_78=173:100 +phy_chain_rx_lane_map_physical{173.0}=0x1032 +phy_chain_rx_lane_map_physical{174.0}=0x1032 +phy_chain_rx_lane_map_physical{175.0}=0x1032 +phy_chain_rx_lane_map_physical{176.0}=0x1032 +phy_chain_tx_lane_map_physical{173.0}=0x1203 +phy_chain_tx_lane_map_physical{174.0}=0x1203 +phy_chain_tx_lane_map_physical{175.0}=0x1203 +phy_chain_tx_lane_map_physical{176.0}=0x1203 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x0 +phy_chain_rx_polarity_flip_physical{175.0}=0x0 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{173.0}=0x1 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x0 +phy_chain_tx_polarity_flip_physical{176.0}=0x1 + +#Port18 +#FC45 +#dport_map_port_83=37 +dport_map_port_83=181 +dport_map_port_84=182 +dport_map_port_85=183 +dport_map_port_86=184 +portmap_83=181:100 +phy_chain_rx_lane_map_physical{181.0}=0x0312 +phy_chain_rx_lane_map_physical{182.0}=0x0312 +phy_chain_rx_lane_map_physical{183.0}=0x0312 +phy_chain_rx_lane_map_physical{184.0}=0x0312 +phy_chain_tx_lane_map_physical{181.0}=0x3120 +phy_chain_tx_lane_map_physical{182.0}=0x3120 +phy_chain_tx_lane_map_physical{183.0}=0x3120 +phy_chain_tx_lane_map_physical{184.0}=0x3120 +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x1 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x1 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 + +#Port20 +#FC3 +#dport_map_port_11=41 +dport_map_port_11=13 +dport_map_port_12=14 +dport_map_port_13=15 +dport_map_port_14=16 +portmap_11=13:100 +phy_chain_rx_lane_map_physical{13.0}=0x3120 +phy_chain_rx_lane_map_physical{14.0}=0x3120 +phy_chain_rx_lane_map_physical{15.0}=0x3120 +phy_chain_rx_lane_map_physical{16.0}=0x3120 +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_tx_lane_map_physical{14.0}=0x3210 +phy_chain_tx_lane_map_physical{15.0}=0x3210 +phy_chain_tx_lane_map_physical{16.0}=0x3210 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 + +#Port22 +#FC7 +#dport_map_port_16=45 +dport_map_port_16=29 +dport_map_port_17=30 +dport_map_port_18=31 +dport_map_port_19=32 +portmap_16=29:100 +phy_chain_rx_lane_map_physical{29.0}=0x3021 +phy_chain_rx_lane_map_physical{30.0}=0x3021 +phy_chain_rx_lane_map_physical{31.0}=0x3021 +phy_chain_rx_lane_map_physical{32.0}=0x3021 +phy_chain_tx_lane_map_physical{29.0}=0x2130 +phy_chain_tx_lane_map_physical{30.0}=0x2130 +phy_chain_tx_lane_map_physical{31.0}=0x2130 +phy_chain_tx_lane_map_physical{32.0}=0x2130 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 + +#Port24 +#FC51 +#dport_map_port_102=49 +dport_map_port_102=205 +dport_map_port_103=206 +dport_map_port_104=207 +dport_map_port_105=208 +portmap_102=205:100 +phy_chain_rx_lane_map_physical{205.0}=0x0132 +phy_chain_rx_lane_map_physical{206.0}=0x0132 +phy_chain_rx_lane_map_physical{207.0}=0x0132 +phy_chain_rx_lane_map_physical{208.0}=0x0132 +phy_chain_tx_lane_map_physical{205.0}=0x1230 +phy_chain_tx_lane_map_physical{206.0}=0x1230 +phy_chain_tx_lane_map_physical{207.0}=0x1230 +phy_chain_tx_lane_map_physical{208.0}=0x1230 +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x1 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x1 +phy_chain_tx_polarity_flip_physical{207.0}=0x0 +phy_chain_tx_polarity_flip_physical{208.0}=0x1 + +#Port26 +#FC53 +#dport_map_port_107=53 +dport_map_port_107=213 +dport_map_port_108=214 +dport_map_port_109=215 +dport_map_port_110=216 +portmap_107=213:100 +phy_chain_rx_lane_map_physical{213.0}=0x3210 +phy_chain_rx_lane_map_physical{214.0}=0x3210 +phy_chain_rx_lane_map_physical{215.0}=0x3210 +phy_chain_rx_lane_map_physical{216.0}=0x3210 +phy_chain_tx_lane_map_physical{213.0}=0x1230 +phy_chain_tx_lane_map_physical{214.0}=0x1230 +phy_chain_tx_lane_map_physical{215.0}=0x1230 +phy_chain_tx_lane_map_physical{216.0}=0x1230 +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x0 +phy_chain_rx_polarity_flip_physical{216.0}=0x1 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x1 + +#Port28 +#FC57 +#dport_map_port_112=57 +dport_map_port_112=229 +dport_map_port_113=230 +dport_map_port_114=231 +dport_map_port_115=232 +portmap_112=229:100 +phy_chain_rx_lane_map_physical{229.0}=0x2301 +phy_chain_rx_lane_map_physical{230.0}=0x2301 +phy_chain_rx_lane_map_physical{231.0}=0x2301 +phy_chain_rx_lane_map_physical{232.0}=0x2301 +phy_chain_tx_lane_map_physical{229.0}=0x3210 +phy_chain_tx_lane_map_physical{230.0}=0x3210 +phy_chain_tx_lane_map_physical{231.0}=0x3210 +phy_chain_tx_lane_map_physical{232.0}=0x3210 +phy_chain_rx_polarity_flip_physical{229.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x1 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x0 +phy_chain_tx_polarity_flip_physical{232.0}=0x0 + +#Port30 +#FC61 +#dport_map_port_117=61 +dport_map_port_117=245 +dport_map_port_118=246 +dport_map_port_119=247 +dport_map_port_120=248 +portmap_117=245:100 +phy_chain_rx_lane_map_physical{245.0}=0x0213 +phy_chain_rx_lane_map_physical{246.0}=0x0213 +phy_chain_rx_lane_map_physical{247.0}=0x0213 +phy_chain_rx_lane_map_physical{248.0}=0x0213 +phy_chain_tx_lane_map_physical{245.0}=0x3210 +phy_chain_tx_lane_map_physical{246.0}=0x3210 +phy_chain_tx_lane_map_physical{247.0}=0x3210 +phy_chain_tx_lane_map_physical{248.0}=0x3210 +phy_chain_rx_polarity_flip_physical{245.0}=0x0 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x1 +phy_chain_tx_polarity_flip_physical{248.0}=0x0 + +#Port1 +#FC16 +#dport_map_port_38=65 +dport_map_port_38=65 +portmap_38=65:100 +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 + +#Port3 +#FC22 +#dport_map_port_43=66 +dport_map_port_43=89 +portmap_43=89:100 +phy_chain_rx_lane_map_physical{89.0}=0x0132 +phy_chain_tx_lane_map_physical{89.0}=0x1203 +phy_chain_rx_polarity_flip_physical{89.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{90.0}=0x0 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x1 + +#Port5 +#FC24 +#dport_map_port_48=67 +dport_map_port_48=97 +portmap_48=97:100 +phy_chain_rx_lane_map_physical{97.0}=0x0213 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_rx_polarity_flip_physical{97.0}=0x1 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.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}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 + +#Port7 +#FC30 +#dport_map_port_53=68 +dport_map_port_53=121 +portmap_53=121:100 +phy_chain_rx_lane_map_physical{121.0}=0x3021 +phy_chain_tx_lane_map_physical{121.0}=0x2130 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +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_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 + +#Port9 +#FC8 +#dport_map_port_5=69 +dport_map_port_5=33 +portmap_5=33:100 +phy_chain_rx_lane_map_physical{33.0}=0x2310 +phy_chain_tx_lane_map_physical{33.0}=0x0213 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 + +#Port11 +#FC14 +#dport_map_port_10=70 +dport_map_port_10=57 +portmap_10=57:100 +phy_chain_rx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_lane_map_physical{57.0}=0x1302 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 + +#Port13 +#FC32 +#dport_map_port_72=71 +dport_map_port_72=129 +portmap_72=129:100 +phy_chain_rx_lane_map_physical{129.0}=0x3021 +phy_chain_tx_lane_map_physical{129.0}=0x1203 +phy_chain_rx_polarity_flip_physical{129.0}=0x1 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x1 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 + +#Port15 +#FC38 +#dport_map_port_77=72 +dport_map_port_77=153 +portmap_77=153:100 +phy_chain_rx_lane_map_physical{153.0}=0x0213 +phy_chain_tx_lane_map_physical{153.0}=0x1302 +phy_chain_rx_polarity_flip_physical{153.0}=0x1 +phy_chain_rx_polarity_flip_physical{154.0}=0x0 +phy_chain_rx_polarity_flip_physical{155.0}=0x1 +phy_chain_rx_polarity_flip_physical{156.0}=0x1 +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 + +#Port17 +#FC41 +#dport_map_port_82=73 +dport_map_port_82=165 +portmap_82=165:100 +phy_chain_rx_lane_map_physical{165.0}=0x1230 +phy_chain_tx_lane_map_physical{165.0}=0x2130 +phy_chain_rx_polarity_flip_physical{165.0}=0x1 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x1 +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x1 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 + +#Port19 +#FC47 +#dport_map_port_87=74 +dport_map_port_87=189 +portmap_87=189:100 +phy_chain_rx_lane_map_physical{189.0}=0x0132 +phy_chain_tx_lane_map_physical{189.0}=0x3210 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x1 +phy_chain_rx_polarity_flip_physical{192.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x0 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 + +#Port21 +#FC1 +#dport_map_port_15=75 +dport_map_port_15=5 +portmap_15=5:100 +phy_chain_rx_lane_map_physical{5.0}=0x0213 +phy_chain_tx_lane_map_physical{5.0}=0x0321 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 + +#Port23 +#FC5 +#dport_map_port_20=76 +dport_map_port_20=21 +portmap_20=21:100 +phy_chain_rx_lane_map_physical{21.0}=0x0321 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 + +#Port25 +#FC49 +#dport_map_port_106=77 +dport_map_port_106=197 +portmap_106=197:100 +phy_chain_rx_lane_map_physical{197.0}=0x1230 +phy_chain_tx_lane_map_physical{197.0}=0x3021 +phy_chain_rx_polarity_flip_physical{197.0}=0x0 +phy_chain_rx_polarity_flip_physical{198.0}=0x0 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x1 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 + +#Port27 +#FC55 +#dport_map_port_111=78 +dport_map_port_111=221 +portmap_111=221:100 +phy_chain_rx_lane_map_physical{221.0}=0x3210 +phy_chain_tx_lane_map_physical{221.0}=0x3210 +phy_chain_rx_polarity_flip_physical{221.0}=0x1 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x0 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x0 +phy_chain_tx_polarity_flip_physical{223.0}=0x0 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 + +#Port29 +#FC59 +#dport_map_port_116=79 +dport_map_port_116=237 +portmap_116=237:100 +phy_chain_rx_lane_map_physical{237.0}=0x0123 +phy_chain_tx_lane_map_physical{237.0}=0x3210 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x1 +phy_chain_rx_polarity_flip_physical{240.0}=0x1 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 + +#Port31 +#FC63 +#dport_map_port_121=80 +dport_map_port_121=253 +portmap_121=253:100 +phy_chain_rx_lane_map_physical{253.0}=0x0213 +phy_chain_tx_lane_map_physical{253.0}=0x0312 +phy_chain_rx_polarity_flip_physical{253.0}=0x0 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x1 +phy_chain_tx_polarity_flip_physical{253.0}=0x0 +phy_chain_tx_polarity_flip_physical{254.0}=0x1 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 + +#Port32 +#FC17 +#dport_map_port_54=81 +dport_map_port_54=69 +portmap_54=69:100 +phy_chain_rx_lane_map_physical{69.0}=0x1032 +phy_chain_tx_lane_map_physical{69.0}=0x3102 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x1 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 +#Port33 +#FC19 +#dport_map_port_55=82 +dport_map_port_55=77 +portmap_55=77:100 +phy_chain_rx_lane_map_physical{77.0}=0x1230 +phy_chain_tx_lane_map_physical{77.0}=0x3021 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +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}=0x0 +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}=0x0 +#Port34 +#FC23 +#dport_map_port_56=83 +dport_map_port_56=93 +portmap_56=93:100 +phy_chain_rx_lane_map_physical{93.0}=0x1032 +phy_chain_tx_lane_map_physical{93.0}=0x0231 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 +phy_chain_tx_polarity_flip_physical{93.0}=0x0 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +phy_chain_tx_polarity_flip_physical{95.0}=0x1 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 +#Port35 +#FC21 +#dport_map_port_57=84 +dport_map_port_57=85 +portmap_57=85:100 +phy_chain_rx_lane_map_physical{85.0}=0x0312 +phy_chain_tx_lane_map_physical{85.0}=0x1230 +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}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x1 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +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}=0x0 +#Port36 +#FC25 +#dport_map_port_58=85 +dport_map_port_58=101 +portmap_58=101:100 +phy_chain_rx_lane_map_physical{101.0}=0x1302 +phy_chain_tx_lane_map_physical{101.0}=0x0213 +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}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{104.0}=0x1 +#Port37 +#FC27 +#dport_map_port_59=86 +dport_map_port_59=109 +portmap_59=109:100 +phy_chain_rx_lane_map_physical{109.0}=0x0213 +phy_chain_tx_lane_map_physical{109.0}=0x1032 +phy_chain_rx_polarity_flip_physical{109.0}=0x1 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x0 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 +phy_chain_tx_polarity_flip_physical{109.0}=0x0 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 +#Port38 +#FC31 +#dport_map_port_60=87 +dport_map_port_60=125 +portmap_60=125:100 +phy_chain_rx_lane_map_physical{125.0}=0x2130 +phy_chain_tx_lane_map_physical{125.0}=0x1203 +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_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +#Port39 +#FC29 +#dport_map_port_61=88 +dport_map_port_61=117 +portmap_61=117:100 +phy_chain_rx_lane_map_physical{117.0}=0x3102 +phy_chain_tx_lane_map_physical{117.0}=0x2310 +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{117.0}=0x1 +phy_chain_tx_polarity_flip_physical{118.0}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x1 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +#Port40 +#FC9 +#dport_map_port_21=89 +dport_map_port_21=37 +portmap_21=37:100 +phy_chain_rx_lane_map_physical{37.0}=0x3210 +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +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 +#Port41 +#FC11 +#dport_map_port_22=90 +dport_map_port_22=45 +portmap_22=45:100 +phy_chain_rx_lane_map_physical{45.0}=0x3210 +phy_chain_tx_lane_map_physical{45.0}=0x0123 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x0 +phy_chain_tx_polarity_flip_physical{45.0}=0x0 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_tx_polarity_flip_physical{47.0}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 +#Port42 +#FC15 +#dport_map_port_23=91 +dport_map_port_23=61 +portmap_23=61:100 +phy_chain_rx_lane_map_physical{61.0}=0x3210 +phy_chain_tx_lane_map_physical{61.0}=0x1230 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +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_tx_polarity_flip_physical{61.0}=0x0 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 +#Port43 +#FC13 +#dport_map_port_24=92 +dport_map_port_24=53 +portmap_24=53:100 +phy_chain_rx_lane_map_physical{53.0}=0x3210 +phy_chain_tx_lane_map_physical{53.0}=0x3210 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x0 +phy_chain_tx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 +#Port44 +#FC33 +#dport_map_port_88=93 +dport_map_port_88=133 +portmap_88=133:100 +phy_chain_rx_lane_map_physical{133.0}=0x0312 +phy_chain_tx_lane_map_physical{133.0}=0x2310 +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x0 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x1 +phy_chain_tx_polarity_flip_physical{135.0}=0x0 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 +#Port45 +#FC35 +#dport_map_port_89=94 +dport_map_port_89=141 +portmap_89=141:100 +phy_chain_rx_lane_map_physical{141.0}=0x3012 +phy_chain_tx_lane_map_physical{141.0}=0x0123 +phy_chain_rx_polarity_flip_physical{141.0}=0x1 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x1 +phy_chain_tx_polarity_flip_physical{143.0}=0x0 +phy_chain_tx_polarity_flip_physical{144.0}=0x0 +#Port46 +#FC39 +#dport_map_port_90=95 +dport_map_port_90=157 +portmap_90=157:100 +phy_chain_rx_lane_map_physical{157.0}=0x2103 +phy_chain_tx_lane_map_physical{157.0}=0x0231 +phy_chain_rx_polarity_flip_physical{157.0}=0x0 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x1 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x1 +phy_chain_tx_polarity_flip_physical{159.0}=0x0 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +#Port47 +#FC37 +#dport_map_port_91=96 +dport_map_port_91=149 +portmap_91=149:100 +phy_chain_rx_lane_map_physical{149.0}=0x3120 +phy_chain_tx_lane_map_physical{149.0}=0x1023 +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x0 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x1 +#Port48 +#FC40 +#dport_map_port_92=97 +dport_map_port_92=161 +portmap_92=161:100 +phy_chain_rx_lane_map_physical{161.0}=0x3012 +phy_chain_tx_lane_map_physical{161.0}=0x1023 +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x1 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +#Port49 +#FC42 +#dport_map_port_93=98 +dport_map_port_93=169 +portmap_93=169:100 +phy_chain_rx_lane_map_physical{169.0}=0x3210 +phy_chain_tx_lane_map_physical{169.0}=0x2031 +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x1 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x0 +#Port50 +#FC46 +#dport_map_port_94=99 +dport_map_port_94=185 +portmap_94=185:100 +phy_chain_rx_lane_map_physical{185.0}=0x2310 +phy_chain_tx_lane_map_physical{185.0}=0x3021 +phy_chain_rx_polarity_flip_physical{185.0}=0x1 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x1 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x0 +#Port51 +#FC44 +#dport_map_port_95=100 +dport_map_port_95=177 +portmap_95=177:100 +phy_chain_rx_lane_map_physical{177.0}=0x1032 +phy_chain_tx_lane_map_physical{177.0}=0x2301 +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x1 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x1 +phy_chain_tx_polarity_flip_physical{177.0}=0x1 +phy_chain_tx_polarity_flip_physical{178.0}=0x1 +phy_chain_tx_polarity_flip_physical{179.0}=0x1 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 + +#Port52 +#FC0 +#dport_map_port_27=103 +dport_map_port_27=1 +portmap_27=1:100 +phy_chain_rx_lane_map_physical{1.0}=0x2130 +phy_chain_tx_lane_map_physical{1.0}=0x1203 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +#Port53 +#FC2 +#dport_map_port_28=104 +dport_map_port_28=9 +portmap_28=9:100 +phy_chain_rx_lane_map_physical{9.0}=0x1203 +phy_chain_tx_lane_map_physical{9.0}=0x1230 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +#Port54 +#FC6 +#dport_map_port_25=101 +dport_map_port_25=25 +portmap_25=25:100 +phy_chain_rx_lane_map_physical{25.0}=0x3102 +phy_chain_tx_lane_map_physical{25.0}=0x0132 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 + +#Port55 +#FC4 +#dport_map_port_26=102 +dport_map_port_26=17 +portmap_26=17:100 +phy_chain_rx_lane_map_physical{17.0}=0x3120 +phy_chain_tx_lane_map_physical{17.0}=0x3021 +phy_chain_rx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x0 + +#Port56 +#FC48 +#dport_map_port_122=105 +dport_map_port_122=193 +portmap_122=193:100 +phy_chain_rx_lane_map_physical{193.0}=0x2103 +phy_chain_tx_lane_map_physical{193.0}=0x1230 +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x1 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +#Port57 +#FC50 +#dport_map_port_123=106 +dport_map_port_123=201 +portmap_123=201:100 +phy_chain_rx_lane_map_physical{201.0}=0x0321 +phy_chain_tx_lane_map_physical{201.0}=0x3021 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_tx_polarity_flip_physical{201.0}=0x1 +phy_chain_tx_polarity_flip_physical{202.0}=0x1 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +#Port58 +#FC54 +#dport_map_port_124=107 +dport_map_port_124=217 +portmap_124=217:100 +phy_chain_rx_lane_map_physical{217.0}=0x1203 +phy_chain_tx_lane_map_physical{217.0}=0x2031 +phy_chain_rx_polarity_flip_physical{217.0}=0x1 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 +phy_chain_tx_polarity_flip_physical{217.0}=0x1 +phy_chain_tx_polarity_flip_physical{218.0}=0x0 +phy_chain_tx_polarity_flip_physical{219.0}=0x1 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 +#Port59 +#FC52 +#dport_map_port_125=108 +dport_map_port_125=209 +portmap_125=209:100 +phy_chain_rx_lane_map_physical{209.0}=0x0321 +phy_chain_tx_lane_map_physical{209.0}=0x3102 +phy_chain_rx_polarity_flip_physical{209.0}=0x0 +phy_chain_rx_polarity_flip_physical{210.0}=0x0 +phy_chain_rx_polarity_flip_physical{211.0}=0x1 +phy_chain_rx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{209.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x1 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +#Port60 +#FC56 +#dport_map_port_126=109 +dport_map_port_126=225 +portmap_126=225:100 +phy_chain_rx_lane_map_physical{225.0}=0x2103 +phy_chain_tx_lane_map_physical{225.0}=0x2031 +phy_chain_rx_polarity_flip_physical{225.0}=0x0 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x1 +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x0 +phy_chain_tx_polarity_flip_physical{227.0}=0x1 +phy_chain_tx_polarity_flip_physical{228.0}=0x1 +#Port61 +#FC58 +#dport_map_port_127=110 +dport_map_port_127=233 +portmap_127=233:100 +phy_chain_rx_lane_map_physical{233.0}=0x2130 +phy_chain_tx_lane_map_physical{233.0}=0x0312 +phy_chain_rx_polarity_flip_physical{233.0}=0x0 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +#Port62 +#FC62 +#dport_map_port_128=111 +dport_map_port_128=249 +portmap_128=249:100 +phy_chain_rx_lane_map_physical{249.0}=0x1302 +phy_chain_tx_lane_map_physical{249.0}=0x1302 +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x1 +phy_chain_rx_polarity_flip_physical{251.0}=0x0 +phy_chain_rx_polarity_flip_physical{252.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x1 +phy_chain_tx_polarity_flip_physical{251.0}=0x1 +phy_chain_tx_polarity_flip_physical{252.0}=0x1 +#Port63 +#FC60 +#dport_map_port_129=112 +dport_map_port_129=241 +portmap_129=241:100 +phy_chain_rx_lane_map_physical{241.0}=0x3012 +phy_chain_tx_lane_map_physical{241.0}=0x2301 +phy_chain_rx_polarity_flip_physical{241.0}=0x1 +phy_chain_rx_polarity_flip_physical{242.0}=0x1 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x1 +phy_chain_tx_polarity_flip_physical{241.0}=0x1 +phy_chain_tx_polarity_flip_physical{242.0}=0x0 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 diff --git a/device/accton/x86_64-accton_as7816_64x-r0/default_sku b/device/accton/x86_64-accton_as7816_64x-r0/default_sku new file mode 100644 index 000000000000..31d29c2deb8d --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/default_sku @@ -0,0 +1 @@ +Accton-AS7816-64X t1 diff --git a/device/accton/x86_64-accton_as7816_64x-r0/installer.conf b/device/accton/x86_64-accton_as7816_64x-r0/installer.conf new file mode 100644 index 000000000000..9fa12f888545 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/accton/x86_64-accton_as7816_64x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7816_64x-r0/led_proc_init.soc new file mode 100755 index 000000000000..75a36c6f9c68 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/led_proc_init.soc @@ -0,0 +1,155 @@ +m CMIC_LEDUP0_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 +m CMIC_LEDUP1_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 +m CMIC_LEDUP2_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 +m CMIC_LEDUP3_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=62 REMAP_PORT_2=61 REMAP_PORT_3=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=59 REMAP_PORT_5=58 REMAP_PORT_6=57 REMAP_PORT_7=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=55 REMAP_PORT_9=54 REMAP_PORT_10=53 REMAP_PORT_11=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=51 REMAP_PORT_13=50 REMAP_PORT_14=49 REMAP_PORT_15=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 REMAP_PORT_17=46 REMAP_PORT_18=45 REMAP_PORT_19=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 REMAP_PORT_21=42 REMAP_PORT_22=41 REMAP_PORT_23=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 REMAP_PORT_25=38 REMAP_PORT_26=37 REMAP_PORT_27=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 REMAP_PORT_29=34 REMAP_PORT_30=33 REMAP_PORT_31=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=31 REMAP_PORT_33=30 REMAP_PORT_34=29 REMAP_PORT_35=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=23 REMAP_PORT_41=22 REMAP_PORT_42=21 REMAP_PORT_43=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=19 REMAP_PORT_45=18 REMAP_PORT_46=17 REMAP_PORT_47=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=62 REMAP_PORT_2=61 REMAP_PORT_3=60 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=59 REMAP_PORT_5=58 REMAP_PORT_6=57 REMAP_PORT_7=56 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=55 REMAP_PORT_9=54 REMAP_PORT_10=53 REMAP_PORT_11=52 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=51 REMAP_PORT_13=50 REMAP_PORT_14=49 REMAP_PORT_15=48 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 REMAP_PORT_17=46 REMAP_PORT_18=45 REMAP_PORT_19=44 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 REMAP_PORT_21=42 REMAP_PORT_22=41 REMAP_PORT_23=40 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 REMAP_PORT_25=38 REMAP_PORT_26=37 REMAP_PORT_27=36 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 REMAP_PORT_29=34 REMAP_PORT_30=33 REMAP_PORT_31=32 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=31 REMAP_PORT_33=30 REMAP_PORT_34=29 REMAP_PORT_35=28 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=23 REMAP_PORT_41=22 REMAP_PORT_42=21 REMAP_PORT_43=20 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=19 REMAP_PORT_45=18 REMAP_PORT_46=17 REMAP_PORT_47=16 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 stop +led 0 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +led 1 stop +led 1 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +led 2 stop +led 2 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +led 3 stop +led 3 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +led auto on +led 0 start +led 1 start +led 2 start +led 3 start diff --git a/device/accton/x86_64-accton_as7816_64x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7816_64x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..4241483d68eb --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7816_64x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7816_64x-r0/plugins/psuutil.py new file mode 100755 index 000000000000..b05cf3e477ac --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "10-0053", + 2: "9-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as7816_64x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7816_64x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..0520799d385a --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/plugins/sfputil.py @@ -0,0 +1,269 @@ +try: + import time + import string + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +# from xcvrd +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 1 + _port_end = 64 + ports_in_block = 64 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 61: 25, + 62: 26, + 63: 27, + 64: 28, + 55: 29, + 56: 30, + 53: 31, + 54: 32, + 9: 33, + 10: 34, + 11: 35, + 12: 36, + 1: 37, + 2: 38, + 3: 39, + 4: 40, + 6: 41, + 5: 42, + 8: 43, + 7: 44, + 13: 45, + 14: 46, + 15: 47, + 16: 48, + 17: 49, + 18: 50, + 19: 51, + 20: 52, + 25: 53, + 26: 54, + 27: 55, + 28: 56, + 29: 57, + 30: 58, + 31: 59, + 32: 60, + 21: 61, + 22: 62, + 23: 63, + 24: 64, + 41: 65, + 42: 66, + 43: 67, + 44: 68, + 33: 69, + 34: 70, + 35: 71, + 36: 72, + 45: 73, + 46: 74, + 47: 75, + 48: 76, + 37: 77, + 38: 78, + 39: 79, + 40: 80, + 57: 81, + 58: 82, + 59: 83, + 60: 84, + 49: 85, + 50: 86, + 51: 87, + 52: 88, } + + _qsfp_ports = list(range(0, ports_in_block + 1)) + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/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) + + 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/19-0060/module_reset_{0}" + port_ps = path.format(port_num) + + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # HW will clear reset after set. + reg_file.seek(0) + reg_file.write('1') + reg_file.close() + return True + + 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/19-0060/module_present_{0}" + port_ps = path.format(port_num) + + reg_value = '0' + try: + reg_file = open(port_ps) + reg_value = reg_file.readline().rstrip() + reg_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return list(range(0, self.ports_in_block + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + @property + def _get_present_bitmap(self): + nodes = [] + + cpld_path = "/sys/bus/i2c/devices/19-0060/" + nodes.append(cpld_path + "module_present_all") + + bitmap = "" + for node in nodes: + try: + reg_file = open(node) + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + bitmap += reg_file.readline().rstrip() + " " + reg_file.close() + + rev = bitmap.split(" ") + rev = "".join(rev[::-1]) + return int(rev, 16) + + data = {'valid': 0, 'last': 0, 'present': 0} + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + port = 0 + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + reg_value = self._get_present_bitmap + reg_value = ~reg_value + changed_ports = self.data['present'] ^ reg_value + if changed_ports: + for port in range(self.port_start, self.port_end+1): + # Mask off the bit corresponding to our port + mask = (1 << (port - 1)) + if changed_ports & mask: + if (reg_value & mask) == 0: + port_dict[port] = SFP_STATUS_REMOVED + else: + port_dict[port] = SFP_STATUS_INSERTED + + # Update cache + self.data['present'] = reg_value + self.data['last'] = now + self.data['valid'] = 1 + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/accton/x86_64-accton_as7816_64x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7816_64x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_as9716_32d-r0/Accton-AS9716-32D/port_config.ini b/device/accton/x86_64-accton_as9716_32d-r0/Accton-AS9716-32D/port_config.ini new file mode 100644 index 000000000000..ab5ba53d280e --- /dev/null +++ b/device/accton/x86_64-accton_as9716_32d-r0/Accton-AS9716-32D/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 73,74,75,76,77,78,79,80 fourHundredGigE1 0 400000 +Ethernet8 65,66,67,68,69,70,71,72 fourHundredGigE2 1 400000 +Ethernet16 81,82,83,84,85,86,87,88 fourHundredGigE3 2 400000 +Ethernet24 89,90,91,92,93,94,95,96 fourHundredGigE4 3 400000 +Ethernet32 97,98,99,100,101,102,103,104 fourHundredGigE5 4 400000 +Ethernet40 105,106,107,108,109,110,111,112 fourHundredGigE6 5 400000 +Ethernet48 113,114,115,116,117,118,119,120 fourHundredGigE7 6 400000 +Ethernet56 121,122,123,124,125,126,127,128 fourHundredGigE8 7 400000 +Ethernet64 41,42,43,44,45,46,47,48 fourHundredGigE9 8 400000 +Ethernet72 33,34,35,36,37,38,39,40 fourHundredGigE10 9 400000 +Ethernet80 49,50,51,52,53,54,55,56 fourHundredGigE11 10 400000 +Ethernet88 57,58,59,60,61,62,63,64 fourHundredGigE12 11 400000 +Ethernet96 129,130,131,132,133,134,135,136 fourHundredGigE13 12 400000 +Ethernet104 137,138,139,140,141,142,143,144 fourHundredGigE14 13 400000 +Ethernet112 145,146,147,148,149,150,151,152 fourHundredGigE15 14 400000 +Ethernet120 153,154,155,156,157,158,159,160 fourHundredGigE16 15 400000 +Ethernet128 169,170,171,172,173,174,175,176 fourHundredGigE17 16 400000 +Ethernet136 161,162,163,164,165,166,167,168 fourHundredGigE18 17 400000 +Ethernet144 177,178,179,180,181,182,183,184 fourHundredGigE19 18 400000 +Ethernet152 185,186,187,188,189,190,191,192 fourHundredGigE20 19 400000 +Ethernet160 1,2,3,4,5,6,7,8 fourHundredGigE21 20 400000 +Ethernet168 9,10,11,12,13,14,15,16 fourHundredGigE22 21 400000 +Ethernet176 17,18,19,20,21,22,23,24 fourHundredGigE23 22 400000 +Ethernet184 25,26,27,28,29,30,31,32 fourHundredGigE24 23 400000 +Ethernet192 201,202,203,204,205,206,207,208 fourHundredGigE25 24 400000 +Ethernet200 193,194,195,196,197,198,199,200 fourHundredGigE26 25 400000 +Ethernet208 217,218,219,220,221,222,223,224 fourHundredGigE27 26 400000 +Ethernet216 209,210,211,212,213,214,215,216 fourHundredGigE28 27 400000 +Ethernet224 233,234,235,236,237,238,239,240 fourHundredGigE29 28 400000 +Ethernet232 225,226,227,228,229,230,231,232 fourHundredGigE30 29 400000 +Ethernet240 249,250,251,252,253,254,255,256 fourHundredGigE31 30 400000 +Ethernet248 241,242,243,244,245,246,247,248 fourHundredGigE32 31 400000 diff --git a/device/accton/x86_64-accton_as9716_32d-r0/Accton-AS9716-32D/sai.profile b/device/accton/x86_64-accton_as9716_32d-r0/Accton-AS9716-32D/sai.profile new file mode 100644 index 000000000000..60f0d4b11d63 --- /dev/null +++ b/device/accton/x86_64-accton_as9716_32d-r0/Accton-AS9716-32D/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-as9716-32x400G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/accton/x86_64-accton_as9716_32d-r0/Accton-AS9716-32D/th3-as9716-32x400G.config.bcm b/device/accton/x86_64-accton_as9716_32d-r0/Accton-AS9716-32D/th3-as9716-32x400G.config.bcm new file mode 100644 index 000000000000..5850f4ce4d72 --- /dev/null +++ b/device/accton/x86_64-accton_as9716_32d-r0/Accton-AS9716-32D/th3-as9716-32x400G.config.bcm @@ -0,0 +1,1287 @@ +pbmp_xport_xe.0=0x3ffffffffffffffffffffffffffffffffffffffe + +# Reference specfic +parity_correction=1 +parity_enable=1 +phy_null=1 +#pll_bypass=1 +core_clock_frequency=1325 +dpr_clock_frequency=1000 +device_clock_frequency=1325 +port_flex_enable=1 +l2xmsg_mode.0=1 +l2_mem_entries.0=8192 +l3_alpm_enable.0=2 +l3_mem_entries.0=16384 +mmu_port_num_mc_queue.0=1 +module_64ports.0=1 +multicast_l2_range.0=511 +oversubscribe_mode=1 + +# Platform specfic +arl_clean_timeout_usec=15000000 +asf_mem_profile.0=2 +bcm_num_cos.0=8 +bcm_stat_flags=1 +bcm_stat_jumbo.0=9236 +cdma_timeout_usec.0=15000000 +dma_desc_timeout_usec.0=15000000 +dpr_clock_frequency.0=1000 +max_vp_lags.0=0 +miim_intr_enable.0=0 +sram_scan_enable.0=0 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 + +#BC0# +dport_map_port_1=81 +dport_map_port_2=82 +dport_map_port_3=83 +dport_map_port_4=84 +portmap_1=1:400 +phy_chain_rx_lane_map_physical{1.0}=0x45301726 +phy_chain_rx_lane_map_physical{2.0}=0x45301726 +phy_chain_rx_lane_map_physical{3.0}=0x45301726 +phy_chain_rx_lane_map_physical{4.0}=0x45301726 +phy_chain_rx_lane_map_physical{5.0}=0x45301726 +phy_chain_rx_lane_map_physical{6.0}=0x45301726 +phy_chain_rx_lane_map_physical{7.0}=0x45301726 +phy_chain_rx_lane_map_physical{8.0}=0x45301726 +phy_chain_tx_lane_map_physical{1.0}=0x23761450 +phy_chain_tx_lane_map_physical{2.0}=0x23761450 +phy_chain_tx_lane_map_physical{3.0}=0x23761450 +phy_chain_tx_lane_map_physical{4.0}=0x23761450 +phy_chain_tx_lane_map_physical{5.0}=0x23761450 +phy_chain_tx_lane_map_physical{6.0}=0x23761450 +phy_chain_tx_lane_map_physical{7.0}=0x23761450 +phy_chain_tx_lane_map_physical{8.0}=0x23761450 +serdes_core_rx_polarity_flip_physical{1}=0xA9 +serdes_core_rx_polarity_flip_physical{2}=0xA9 +serdes_core_rx_polarity_flip_physical{3}=0xA9 +serdes_core_rx_polarity_flip_physical{4}=0xA9 +serdes_core_rx_polarity_flip_physical{5}=0xA9 +serdes_core_rx_polarity_flip_physical{6}=0xA9 +serdes_core_rx_polarity_flip_physical{7}=0xA9 +serdes_core_rx_polarity_flip_physical{8}=0xA9 +serdes_core_tx_polarity_flip_physical{1}=0x7E +serdes_core_tx_polarity_flip_physical{2}=0x7E +serdes_core_tx_polarity_flip_physical{3}=0x7E +serdes_core_tx_polarity_flip_physical{4}=0x7E +serdes_core_tx_polarity_flip_physical{5}=0x7E +serdes_core_tx_polarity_flip_physical{6}=0x7E +serdes_core_tx_polarity_flip_physical{7}=0x7E +serdes_core_tx_polarity_flip_physical{8}=0x7E + +#BC1# +dport_map_port_5=85 +dport_map_port_6=86 +dport_map_port_7=87 +dport_map_port_8=88 +portmap_5=9:400 +phy_chain_rx_lane_map_physical{9.0}=0x12650374 +phy_chain_rx_lane_map_physical{10.0}=0x12650374 +phy_chain_rx_lane_map_physical{11.0}=0x12650374 +phy_chain_rx_lane_map_physical{12.0}=0x12650374 +phy_chain_rx_lane_map_physical{13.0}=0x12650374 +phy_chain_rx_lane_map_physical{14.0}=0x12650374 +phy_chain_rx_lane_map_physical{15.0}=0x12650374 +phy_chain_rx_lane_map_physical{16.0}=0x12650374 +phy_chain_tx_lane_map_physical{9.0}=0x70146253 +phy_chain_tx_lane_map_physical{10.0}=0x70146253 +phy_chain_tx_lane_map_physical{11.0}=0x70146253 +phy_chain_tx_lane_map_physical{12.0}=0x70146253 +phy_chain_tx_lane_map_physical{13.0}=0x70146253 +phy_chain_tx_lane_map_physical{14.0}=0x70146253 +phy_chain_tx_lane_map_physical{15.0}=0x70146253 +phy_chain_tx_lane_map_physical{16.0}=0x70146253 +serdes_core_rx_polarity_flip_physical{9}=0x5A +serdes_core_rx_polarity_flip_physical{10}=0x5A +serdes_core_rx_polarity_flip_physical{11}=0x5A +serdes_core_rx_polarity_flip_physical{12}=0x5A +serdes_core_rx_polarity_flip_physical{13}=0x5A +serdes_core_rx_polarity_flip_physical{14}=0x5A +serdes_core_rx_polarity_flip_physical{15}=0x5A +serdes_core_rx_polarity_flip_physical{16}=0x5A +serdes_core_tx_polarity_flip_physical{9}=0x76 +serdes_core_tx_polarity_flip_physical{10}=0x76 +serdes_core_tx_polarity_flip_physical{11}=0x76 +serdes_core_tx_polarity_flip_physical{12}=0x76 +serdes_core_tx_polarity_flip_physical{13}=0x76 +serdes_core_tx_polarity_flip_physical{14}=0x76 +serdes_core_tx_polarity_flip_physical{15}=0x76 +serdes_core_tx_polarity_flip_physical{16}=0x76 + +#BC2# +dport_map_port_9=89 +dport_map_port_10=90 +dport_map_port_11=91 +dport_map_port_12=92 +portmap_9=17:400 +phy_chain_rx_lane_map_physical{17.0}=0x40572136 +phy_chain_rx_lane_map_physical{18.0}=0x40572136 +phy_chain_rx_lane_map_physical{19.0}=0x40572136 +phy_chain_rx_lane_map_physical{20.0}=0x40572136 +phy_chain_rx_lane_map_physical{21.0}=0x40572136 +phy_chain_rx_lane_map_physical{22.0}=0x40572136 +phy_chain_rx_lane_map_physical{23.0}=0x40572136 +phy_chain_rx_lane_map_physical{24.0}=0x40572136 +phy_chain_tx_lane_map_physical{17.0}=0x75324160 +phy_chain_tx_lane_map_physical{18.0}=0x75324160 +phy_chain_tx_lane_map_physical{19.0}=0x75324160 +phy_chain_tx_lane_map_physical{20.0}=0x75324160 +phy_chain_tx_lane_map_physical{21.0}=0x75324160 +phy_chain_tx_lane_map_physical{22.0}=0x75324160 +phy_chain_tx_lane_map_physical{23.0}=0x75324160 +phy_chain_tx_lane_map_physical{24.0}=0x75324160 +serdes_core_rx_polarity_flip_physical{17}=0x78 +serdes_core_rx_polarity_flip_physical{18}=0x78 +serdes_core_rx_polarity_flip_physical{19}=0x78 +serdes_core_rx_polarity_flip_physical{20}=0x78 +serdes_core_rx_polarity_flip_physical{21}=0x78 +serdes_core_rx_polarity_flip_physical{22}=0x78 +serdes_core_rx_polarity_flip_physical{23}=0x78 +serdes_core_rx_polarity_flip_physical{24}=0x78 +serdes_core_tx_polarity_flip_physical{17}=0x3B +serdes_core_tx_polarity_flip_physical{18}=0x3B +serdes_core_tx_polarity_flip_physical{19}=0x3B +serdes_core_tx_polarity_flip_physical{20}=0x3B +serdes_core_tx_polarity_flip_physical{21}=0x3B +serdes_core_tx_polarity_flip_physical{22}=0x3B +serdes_core_tx_polarity_flip_physical{23}=0x3B +serdes_core_tx_polarity_flip_physical{24}=0x3B + +#BC3# +dport_map_port_13=93 +dport_map_port_14=94 +dport_map_port_15=95 +dport_map_port_16=96 +portmap_13=25:400 +phy_chain_rx_lane_map_physical{25.0}=0x20576143 +phy_chain_rx_lane_map_physical{26.0}=0x20576143 +phy_chain_rx_lane_map_physical{27.0}=0x20576143 +phy_chain_rx_lane_map_physical{28.0}=0x20576143 +phy_chain_rx_lane_map_physical{29.0}=0x20576143 +phy_chain_rx_lane_map_physical{30.0}=0x20576143 +phy_chain_rx_lane_map_physical{31.0}=0x20576143 +phy_chain_rx_lane_map_physical{32.0}=0x20576143 +phy_chain_tx_lane_map_physical{25.0}=0x43716520 +phy_chain_tx_lane_map_physical{26.0}=0x43716520 +phy_chain_tx_lane_map_physical{27.0}=0x43716520 +phy_chain_tx_lane_map_physical{28.0}=0x43716520 +phy_chain_tx_lane_map_physical{29.0}=0x43716520 +phy_chain_tx_lane_map_physical{30.0}=0x43716520 +phy_chain_tx_lane_map_physical{31.0}=0x43716520 +phy_chain_tx_lane_map_physical{32.0}=0x43716520 +serdes_core_rx_polarity_flip_physical{25}=0xF8 +serdes_core_rx_polarity_flip_physical{26}=0xF8 +serdes_core_rx_polarity_flip_physical{27}=0xF8 +serdes_core_rx_polarity_flip_physical{28}=0xF8 +serdes_core_rx_polarity_flip_physical{29}=0xF8 +serdes_core_rx_polarity_flip_physical{30}=0xF8 +serdes_core_rx_polarity_flip_physical{31}=0xF8 +serdes_core_rx_polarity_flip_physical{32}=0xF8 +serdes_core_tx_polarity_flip_physical{25}=0x6E +serdes_core_tx_polarity_flip_physical{26}=0x6E +serdes_core_tx_polarity_flip_physical{27}=0x6E +serdes_core_tx_polarity_flip_physical{28}=0x6E +serdes_core_tx_polarity_flip_physical{29}=0x6E +serdes_core_tx_polarity_flip_physical{30}=0x6E +serdes_core_tx_polarity_flip_physical{31}=0x6E +serdes_core_tx_polarity_flip_physical{32}=0x6E + +#BC4# +dport_map_port_24=37 +dport_map_port_25=38 +dport_map_port_26=39 +dport_map_port_27=40 +portmap_24=33:400 +phy_chain_rx_lane_map_physical{33.0}=0x47205361 +phy_chain_rx_lane_map_physical{34.0}=0x47205361 +phy_chain_rx_lane_map_physical{35.0}=0x47205361 +phy_chain_rx_lane_map_physical{36.0}=0x47205361 +phy_chain_rx_lane_map_physical{37.0}=0x47205361 +phy_chain_rx_lane_map_physical{38.0}=0x47205361 +phy_chain_rx_lane_map_physical{39.0}=0x47205361 +phy_chain_rx_lane_map_physical{40.0}=0x47205361 +phy_chain_tx_lane_map_physical{33.0}=0x01452736 +phy_chain_tx_lane_map_physical{34.0}=0x01452736 +phy_chain_tx_lane_map_physical{35.0}=0x01452736 +phy_chain_tx_lane_map_physical{36.0}=0x01452736 +phy_chain_tx_lane_map_physical{37.0}=0x01452736 +phy_chain_tx_lane_map_physical{38.0}=0x01452736 +phy_chain_tx_lane_map_physical{39.0}=0x01452736 +phy_chain_tx_lane_map_physical{40.0}=0x01452736 +serdes_core_rx_polarity_flip_physical{33}=0x87 +serdes_core_rx_polarity_flip_physical{34}=0x87 +serdes_core_rx_polarity_flip_physical{35}=0x87 +serdes_core_rx_polarity_flip_physical{36}=0x87 +serdes_core_rx_polarity_flip_physical{37}=0x87 +serdes_core_rx_polarity_flip_physical{38}=0x87 +serdes_core_rx_polarity_flip_physical{39}=0x87 +serdes_core_rx_polarity_flip_physical{40}=0x87 +serdes_core_tx_polarity_flip_physical{33}=0x27 +serdes_core_tx_polarity_flip_physical{34}=0x27 +serdes_core_tx_polarity_flip_physical{35}=0x27 +serdes_core_tx_polarity_flip_physical{36}=0x27 +serdes_core_tx_polarity_flip_physical{37}=0x27 +serdes_core_tx_polarity_flip_physical{38}=0x27 +serdes_core_tx_polarity_flip_physical{39}=0x27 +serdes_core_tx_polarity_flip_physical{40}=0x27 + +#BC5# +dport_map_port_20=33 +dport_map_port_21=34 +dport_map_port_22=35 +dport_map_port_23=36 +portmap_20=41:400 +phy_chain_rx_lane_map_physical{41.0}=0x45013726 +phy_chain_rx_lane_map_physical{42.0}=0x45013726 +phy_chain_rx_lane_map_physical{43.0}=0x45013726 +phy_chain_rx_lane_map_physical{44.0}=0x45013726 +phy_chain_rx_lane_map_physical{45.0}=0x45013726 +phy_chain_rx_lane_map_physical{46.0}=0x45013726 +phy_chain_rx_lane_map_physical{47.0}=0x45013726 +phy_chain_rx_lane_map_physical{48.0}=0x45013726 +phy_chain_tx_lane_map_physical{41.0}=0x10273564 +phy_chain_tx_lane_map_physical{42.0}=0x10273564 +phy_chain_tx_lane_map_physical{43.0}=0x10273564 +phy_chain_tx_lane_map_physical{44.0}=0x10273564 +phy_chain_tx_lane_map_physical{45.0}=0x10273564 +phy_chain_tx_lane_map_physical{46.0}=0x10273564 +phy_chain_tx_lane_map_physical{47.0}=0x10273564 +phy_chain_tx_lane_map_physical{48.0}=0x10273564 +serdes_core_rx_polarity_flip_physical{41}=0x99 +serdes_core_rx_polarity_flip_physical{42}=0x99 +serdes_core_rx_polarity_flip_physical{43}=0x99 +serdes_core_rx_polarity_flip_physical{44}=0x99 +serdes_core_rx_polarity_flip_physical{45}=0x99 +serdes_core_rx_polarity_flip_physical{46}=0x99 +serdes_core_rx_polarity_flip_physical{47}=0x99 +serdes_core_rx_polarity_flip_physical{48}=0x99 +serdes_core_tx_polarity_flip_physical{41}=0xA8 +serdes_core_tx_polarity_flip_physical{42}=0xA8 +serdes_core_tx_polarity_flip_physical{43}=0xA8 +serdes_core_tx_polarity_flip_physical{44}=0xA8 +serdes_core_tx_polarity_flip_physical{45}=0xA8 +serdes_core_tx_polarity_flip_physical{46}=0xA8 +serdes_core_tx_polarity_flip_physical{47}=0xA8 +serdes_core_tx_polarity_flip_physical{48}=0xA8 + +#BC6# +dport_map_port_28=41 +dport_map_port_29=42 +dport_map_port_30=43 +dport_map_port_31=44 +portmap_28=49:400 +phy_chain_rx_lane_map_physical{49.0}=0x04571326 +phy_chain_rx_lane_map_physical{50.0}=0x04571326 +phy_chain_rx_lane_map_physical{51.0}=0x04571326 +phy_chain_rx_lane_map_physical{52.0}=0x04571326 +phy_chain_rx_lane_map_physical{53.0}=0x04571326 +phy_chain_rx_lane_map_physical{54.0}=0x04571326 +phy_chain_rx_lane_map_physical{55.0}=0x04571326 +phy_chain_rx_lane_map_physical{56.0}=0x04571326 +phy_chain_tx_lane_map_physical{49.0}=0x51230764 +phy_chain_tx_lane_map_physical{50.0}=0x51230764 +phy_chain_tx_lane_map_physical{51.0}=0x51230764 +phy_chain_tx_lane_map_physical{52.0}=0x51230764 +phy_chain_tx_lane_map_physical{53.0}=0x51230764 +phy_chain_tx_lane_map_physical{54.0}=0x51230764 +phy_chain_tx_lane_map_physical{55.0}=0x51230764 +phy_chain_tx_lane_map_physical{56.0}=0x51230764 +serdes_core_rx_polarity_flip_physical{49}=0xB2 +serdes_core_rx_polarity_flip_physical{50}=0xB2 +serdes_core_rx_polarity_flip_physical{51}=0xB2 +serdes_core_rx_polarity_flip_physical{52}=0xB2 +serdes_core_rx_polarity_flip_physical{53}=0xB2 +serdes_core_rx_polarity_flip_physical{54}=0xB2 +serdes_core_rx_polarity_flip_physical{55}=0xB2 +serdes_core_rx_polarity_flip_physical{56}=0xB2 +serdes_core_tx_polarity_flip_physical{49}=0x88 +serdes_core_tx_polarity_flip_physical{50}=0x88 +serdes_core_tx_polarity_flip_physical{51}=0x88 +serdes_core_tx_polarity_flip_physical{52}=0x88 +serdes_core_tx_polarity_flip_physical{53}=0x88 +serdes_core_tx_polarity_flip_physical{54}=0x88 +serdes_core_tx_polarity_flip_physical{55}=0x88 +serdes_core_tx_polarity_flip_physical{56}=0x88 + +#BC7# +dport_map_port_32=45 +dport_map_port_33=46 +dport_map_port_34=47 +dport_map_port_35=48 +portmap_32=57:400 +phy_chain_rx_lane_map_physical{57.0}=0x01675243 +phy_chain_rx_lane_map_physical{58.0}=0x01675243 +phy_chain_rx_lane_map_physical{59.0}=0x01675243 +phy_chain_rx_lane_map_physical{60.0}=0x01675243 +phy_chain_rx_lane_map_physical{61.0}=0x01675243 +phy_chain_rx_lane_map_physical{62.0}=0x01675243 +phy_chain_rx_lane_map_physical{63.0}=0x01675243 +phy_chain_rx_lane_map_physical{64.0}=0x01675243 +phy_chain_tx_lane_map_physical{57.0}=0x37106425 +phy_chain_tx_lane_map_physical{58.0}=0x37106425 +phy_chain_tx_lane_map_physical{59.0}=0x37106425 +phy_chain_tx_lane_map_physical{60.0}=0x37106425 +phy_chain_tx_lane_map_physical{61.0}=0x37106425 +phy_chain_tx_lane_map_physical{62.0}=0x37106425 +phy_chain_tx_lane_map_physical{63.0}=0x37106425 +phy_chain_tx_lane_map_physical{64.0}=0x37106425 +serdes_core_rx_polarity_flip_physical{57}=0x9C +serdes_core_rx_polarity_flip_physical{58}=0x9C +serdes_core_rx_polarity_flip_physical{59}=0x9C +serdes_core_rx_polarity_flip_physical{60}=0x9C +serdes_core_rx_polarity_flip_physical{61}=0x9C +serdes_core_rx_polarity_flip_physical{62}=0x9C +serdes_core_rx_polarity_flip_physical{63}=0x9C +serdes_core_rx_polarity_flip_physical{64}=0x9C +serdes_core_tx_polarity_flip_physical{57}=0x4F +serdes_core_tx_polarity_flip_physical{58}=0x4F +serdes_core_tx_polarity_flip_physical{59}=0x4F +serdes_core_tx_polarity_flip_physical{60}=0x4F +serdes_core_tx_polarity_flip_physical{61}=0x4F +serdes_core_tx_polarity_flip_physical{62}=0x4F +serdes_core_tx_polarity_flip_physical{63}=0x4F +serdes_core_tx_polarity_flip_physical{64}=0x4F + +#BC8# +dport_map_port_44=5 +dport_map_port_45=6 +dport_map_port_46=7 +dport_map_port_47=8 +portmap_44=65:400 +phy_chain_rx_lane_map_physical{65.0}=0x56024713 +phy_chain_rx_lane_map_physical{66.0}=0x56024713 +phy_chain_rx_lane_map_physical{67.0}=0x56024713 +phy_chain_rx_lane_map_physical{68.0}=0x56024713 +phy_chain_rx_lane_map_physical{69.0}=0x56024713 +phy_chain_rx_lane_map_physical{70.0}=0x56024713 +phy_chain_rx_lane_map_physical{71.0}=0x56024713 +phy_chain_rx_lane_map_physical{72.0}=0x56024713 +phy_chain_tx_lane_map_physical{65.0}=0x12673504 +phy_chain_tx_lane_map_physical{66.0}=0x12673504 +phy_chain_tx_lane_map_physical{67.0}=0x12673504 +phy_chain_tx_lane_map_physical{68.0}=0x12673504 +phy_chain_tx_lane_map_physical{69.0}=0x12673504 +phy_chain_tx_lane_map_physical{70.0}=0x12673504 +phy_chain_tx_lane_map_physical{71.0}=0x12673504 +phy_chain_tx_lane_map_physical{72.0}=0x12673504 +serdes_core_rx_polarity_flip_physical{65}=0x4B +serdes_core_rx_polarity_flip_physical{66}=0x4B +serdes_core_rx_polarity_flip_physical{67}=0x4B +serdes_core_rx_polarity_flip_physical{68}=0x4B +serdes_core_rx_polarity_flip_physical{69}=0x4B +serdes_core_rx_polarity_flip_physical{70}=0x4B +serdes_core_rx_polarity_flip_physical{71}=0x4B +serdes_core_rx_polarity_flip_physical{72}=0x4B +serdes_core_tx_polarity_flip_physical{65}=0xB7 +serdes_core_tx_polarity_flip_physical{66}=0xB7 +serdes_core_tx_polarity_flip_physical{67}=0xB7 +serdes_core_tx_polarity_flip_physical{68}=0xB7 +serdes_core_tx_polarity_flip_physical{69}=0xB7 +serdes_core_tx_polarity_flip_physical{70}=0xB7 +serdes_core_tx_polarity_flip_physical{71}=0xB7 +serdes_core_tx_polarity_flip_physical{72}=0xB7 + +#BC9# +dport_map_port_40=1 +dport_map_port_41=2 +dport_map_port_42=3 +dport_map_port_43=4 +portmap_40=73:400 +phy_chain_rx_lane_map_physical{73.0}=0x45231607 +phy_chain_rx_lane_map_physical{74.0}=0x45231607 +phy_chain_rx_lane_map_physical{75.0}=0x45231607 +phy_chain_rx_lane_map_physical{76.0}=0x45231607 +phy_chain_rx_lane_map_physical{77.0}=0x45231607 +phy_chain_rx_lane_map_physical{78.0}=0x45231607 +phy_chain_rx_lane_map_physical{79.0}=0x45231607 +phy_chain_rx_lane_map_physical{80.0}=0x45231607 +phy_chain_tx_lane_map_physical{73.0}=0x04273165 +phy_chain_tx_lane_map_physical{74.0}=0x04273165 +phy_chain_tx_lane_map_physical{75.0}=0x04273165 +phy_chain_tx_lane_map_physical{76.0}=0x04273165 +phy_chain_tx_lane_map_physical{77.0}=0x04273165 +phy_chain_tx_lane_map_physical{78.0}=0x04273165 +phy_chain_tx_lane_map_physical{79.0}=0x04273165 +phy_chain_tx_lane_map_physical{80.0}=0x04273165 +serdes_core_rx_polarity_flip_physical{73}=0x9C +serdes_core_rx_polarity_flip_physical{74}=0x9C +serdes_core_rx_polarity_flip_physical{75}=0x9C +serdes_core_rx_polarity_flip_physical{76}=0x9C +serdes_core_rx_polarity_flip_physical{77}=0x9C +serdes_core_rx_polarity_flip_physical{78}=0x9C +serdes_core_rx_polarity_flip_physical{79}=0x9C +serdes_core_rx_polarity_flip_physical{80}=0x9C +serdes_core_tx_polarity_flip_physical{73}=0xAC +serdes_core_tx_polarity_flip_physical{74}=0xAC +serdes_core_tx_polarity_flip_physical{75}=0xAC +serdes_core_tx_polarity_flip_physical{76}=0xAC +serdes_core_tx_polarity_flip_physical{77}=0xAC +serdes_core_tx_polarity_flip_physical{78}=0xAC +serdes_core_tx_polarity_flip_physical{79}=0xAC +serdes_core_tx_polarity_flip_physical{80}=0xAC + +#BC10# +dport_map_port_48=9 +dport_map_port_49=10 +dport_map_port_50=11 +dport_map_port_51=12 +portmap_48=81:400 +phy_chain_rx_lane_map_physical{81.0}=0x20563147 +phy_chain_rx_lane_map_physical{82.0}=0x20563147 +phy_chain_rx_lane_map_physical{83.0}=0x20563147 +phy_chain_rx_lane_map_physical{84.0}=0x20563147 +phy_chain_rx_lane_map_physical{85.0}=0x20563147 +phy_chain_rx_lane_map_physical{86.0}=0x20563147 +phy_chain_rx_lane_map_physical{87.0}=0x20563147 +phy_chain_rx_lane_map_physical{88.0}=0x20563147 +phy_chain_tx_lane_map_physical{81.0}=0x53216704 +phy_chain_tx_lane_map_physical{82.0}=0x53216704 +phy_chain_tx_lane_map_physical{83.0}=0x53216704 +phy_chain_tx_lane_map_physical{84.0}=0x53216704 +phy_chain_tx_lane_map_physical{85.0}=0x53216704 +phy_chain_tx_lane_map_physical{86.0}=0x53216704 +phy_chain_tx_lane_map_physical{87.0}=0x53216704 +phy_chain_tx_lane_map_physical{88.0}=0x53216704 +serdes_core_rx_polarity_flip_physical{81}=0xE1 +serdes_core_rx_polarity_flip_physical{82}=0xE1 +serdes_core_rx_polarity_flip_physical{83}=0xE1 +serdes_core_rx_polarity_flip_physical{84}=0xE1 +serdes_core_rx_polarity_flip_physical{85}=0xE1 +serdes_core_rx_polarity_flip_physical{86}=0xE1 +serdes_core_rx_polarity_flip_physical{87}=0xE1 +serdes_core_rx_polarity_flip_physical{88}=0xE1 +serdes_core_tx_polarity_flip_physical{81}=0xA2 +serdes_core_tx_polarity_flip_physical{82}=0xA2 +serdes_core_tx_polarity_flip_physical{83}=0xA2 +serdes_core_tx_polarity_flip_physical{84}=0xA2 +serdes_core_tx_polarity_flip_physical{85}=0xA2 +serdes_core_tx_polarity_flip_physical{86}=0xA2 +serdes_core_tx_polarity_flip_physical{87}=0xA2 +serdes_core_tx_polarity_flip_physical{88}=0xA2 + +#BC11# +dport_map_port_52=13 +dport_map_port_53=14 +dport_map_port_54=15 +dport_map_port_55=16 +portmap_52=89:400 +phy_chain_rx_lane_map_physical{89.0}=0x02514376 +phy_chain_rx_lane_map_physical{90.0}=0x02514376 +phy_chain_rx_lane_map_physical{91.0}=0x02514376 +phy_chain_rx_lane_map_physical{92.0}=0x02514376 +phy_chain_rx_lane_map_physical{93.0}=0x02514376 +phy_chain_rx_lane_map_physical{94.0}=0x02514376 +phy_chain_rx_lane_map_physical{95.0}=0x02514376 +phy_chain_rx_lane_map_physical{96.0}=0x02514376 +phy_chain_tx_lane_map_physical{89.0}=0x64012735 +phy_chain_tx_lane_map_physical{90.0}=0x64012735 +phy_chain_tx_lane_map_physical{91.0}=0x64012735 +phy_chain_tx_lane_map_physical{92.0}=0x64012735 +phy_chain_tx_lane_map_physical{93.0}=0x64012735 +phy_chain_tx_lane_map_physical{94.0}=0x64012735 +phy_chain_tx_lane_map_physical{95.0}=0x64012735 +phy_chain_tx_lane_map_physical{96.0}=0x64012735 +serdes_core_rx_polarity_flip_physical{89}=0xE2 +serdes_core_rx_polarity_flip_physical{90}=0xE2 +serdes_core_rx_polarity_flip_physical{91}=0xE2 +serdes_core_rx_polarity_flip_physical{92}=0xE2 +serdes_core_rx_polarity_flip_physical{93}=0xE2 +serdes_core_rx_polarity_flip_physical{94}=0xE2 +serdes_core_rx_polarity_flip_physical{95}=0xE2 +serdes_core_rx_polarity_flip_physical{96}=0xE2 +serdes_core_tx_polarity_flip_physical{89}=0xCF +serdes_core_tx_polarity_flip_physical{90}=0xCF +serdes_core_tx_polarity_flip_physical{91}=0xCF +serdes_core_tx_polarity_flip_physical{92}=0xCF +serdes_core_tx_polarity_flip_physical{93}=0xCF +serdes_core_tx_polarity_flip_physical{94}=0xCF +serdes_core_tx_polarity_flip_physical{95}=0xCF +serdes_core_tx_polarity_flip_physical{96}=0xCF + +#BC12# +dport_map_port_60=17 +dport_map_port_61=18 +dport_map_port_62=19 +dport_map_port_63=20 +portmap_60=97:400 +phy_chain_rx_lane_map_physical{97.0}=0x51276034 +phy_chain_rx_lane_map_physical{98.0}=0x51276034 +phy_chain_rx_lane_map_physical{99.0}=0x51276034 +phy_chain_rx_lane_map_physical{100.0}=0x51276034 +phy_chain_rx_lane_map_physical{101.0}=0x51276034 +phy_chain_rx_lane_map_physical{102.0}=0x51276034 +phy_chain_rx_lane_map_physical{103.0}=0x51276034 +phy_chain_rx_lane_map_physical{104.0}=0x51276034 +phy_chain_tx_lane_map_physical{97.0}=0x05476321 +phy_chain_tx_lane_map_physical{98.0}=0x05476321 +phy_chain_tx_lane_map_physical{99.0}=0x05476321 +phy_chain_tx_lane_map_physical{100.0}=0x05476321 +phy_chain_tx_lane_map_physical{101.0}=0x05476321 +phy_chain_tx_lane_map_physical{102.0}=0x05476321 +phy_chain_tx_lane_map_physical{103.0}=0x05476321 +phy_chain_tx_lane_map_physical{104.0}=0x05476321 +serdes_core_rx_polarity_flip_physical{97}=0x8E +serdes_core_rx_polarity_flip_physical{98}=0x8E +serdes_core_rx_polarity_flip_physical{99}=0x8E +serdes_core_rx_polarity_flip_physical{100}=0x8E +serdes_core_rx_polarity_flip_physical{101}=0x8E +serdes_core_rx_polarity_flip_physical{102}=0x8E +serdes_core_rx_polarity_flip_physical{103}=0x8E +serdes_core_rx_polarity_flip_physical{104}=0x8E +serdes_core_tx_polarity_flip_physical{97}=0xC8 +serdes_core_tx_polarity_flip_physical{98}=0xC8 +serdes_core_tx_polarity_flip_physical{99}=0xC8 +serdes_core_tx_polarity_flip_physical{100}=0xC8 +serdes_core_tx_polarity_flip_physical{101}=0xC8 +serdes_core_tx_polarity_flip_physical{102}=0xC8 +serdes_core_tx_polarity_flip_physical{103}=0xC8 +serdes_core_tx_polarity_flip_physical{104}=0xC8 + +#BC13# +dport_map_port_64=21 +dport_map_port_65=22 +dport_map_port_66=23 +dport_map_port_67=24 +portmap_64=105:400 +phy_chain_rx_lane_map_physical{105.0}=0x74126503 +phy_chain_rx_lane_map_physical{106.0}=0x74126503 +phy_chain_rx_lane_map_physical{107.0}=0x74126503 +phy_chain_rx_lane_map_physical{108.0}=0x74126503 +phy_chain_rx_lane_map_physical{109.0}=0x74126503 +phy_chain_rx_lane_map_physical{110.0}=0x74126503 +phy_chain_rx_lane_map_physical{111.0}=0x74126503 +phy_chain_rx_lane_map_physical{112.0}=0x74126503 +phy_chain_tx_lane_map_physical{105.0}=0x75236140 +phy_chain_tx_lane_map_physical{106.0}=0x75236140 +phy_chain_tx_lane_map_physical{107.0}=0x75236140 +phy_chain_tx_lane_map_physical{108.0}=0x75236140 +phy_chain_tx_lane_map_physical{109.0}=0x75236140 +phy_chain_tx_lane_map_physical{110.0}=0x75236140 +phy_chain_tx_lane_map_physical{111.0}=0x75236140 +phy_chain_tx_lane_map_physical{112.0}=0x75236140 +serdes_core_rx_polarity_flip_physical{105}=0x96 +serdes_core_rx_polarity_flip_physical{106}=0x96 +serdes_core_rx_polarity_flip_physical{107}=0x96 +serdes_core_rx_polarity_flip_physical{108}=0x96 +serdes_core_rx_polarity_flip_physical{109}=0x96 +serdes_core_rx_polarity_flip_physical{110}=0x96 +serdes_core_rx_polarity_flip_physical{111}=0x96 +serdes_core_rx_polarity_flip_physical{112}=0x96 +serdes_core_tx_polarity_flip_physical{105}=0xE1 +serdes_core_tx_polarity_flip_physical{106}=0xE1 +serdes_core_tx_polarity_flip_physical{107}=0xE1 +serdes_core_tx_polarity_flip_physical{108}=0xE1 +serdes_core_tx_polarity_flip_physical{109}=0xE1 +serdes_core_tx_polarity_flip_physical{110}=0xE1 +serdes_core_tx_polarity_flip_physical{111}=0xE1 +serdes_core_tx_polarity_flip_physical{112}=0xE1 + +#BC14# +dport_map_port_68=25 +dport_map_port_69=26 +dport_map_port_70=27 +dport_map_port_71=28 +portmap_68=113:400 +phy_chain_rx_lane_map_physical{113.0}=0x32461057 +phy_chain_rx_lane_map_physical{114.0}=0x32461057 +phy_chain_rx_lane_map_physical{115.0}=0x32461057 +phy_chain_rx_lane_map_physical{116.0}=0x32461057 +phy_chain_rx_lane_map_physical{117.0}=0x32461057 +phy_chain_rx_lane_map_physical{118.0}=0x32461057 +phy_chain_rx_lane_map_physical{119.0}=0x32461057 +phy_chain_rx_lane_map_physical{120.0}=0x32461057 +phy_chain_tx_lane_map_physical{113.0}=0x54107362 +phy_chain_tx_lane_map_physical{114.0}=0x54107362 +phy_chain_tx_lane_map_physical{115.0}=0x54107362 +phy_chain_tx_lane_map_physical{116.0}=0x54107362 +phy_chain_tx_lane_map_physical{117.0}=0x54107362 +phy_chain_tx_lane_map_physical{118.0}=0x54107362 +phy_chain_tx_lane_map_physical{119.0}=0x54107362 +phy_chain_tx_lane_map_physical{120.0}=0x54107362 +serdes_core_rx_polarity_flip_physical{113}=0x47 +serdes_core_rx_polarity_flip_physical{114}=0x47 +serdes_core_rx_polarity_flip_physical{115}=0x47 +serdes_core_rx_polarity_flip_physical{116}=0x47 +serdes_core_rx_polarity_flip_physical{117}=0x47 +serdes_core_rx_polarity_flip_physical{118}=0x47 +serdes_core_rx_polarity_flip_physical{119}=0x47 +serdes_core_rx_polarity_flip_physical{120}=0x47 +serdes_core_tx_polarity_flip_physical{113}=0xBD +serdes_core_tx_polarity_flip_physical{114}=0xBD +serdes_core_tx_polarity_flip_physical{115}=0xBD +serdes_core_tx_polarity_flip_physical{116}=0xBD +serdes_core_tx_polarity_flip_physical{117}=0xBD +serdes_core_tx_polarity_flip_physical{118}=0xBD +serdes_core_tx_polarity_flip_physical{119}=0xBD +serdes_core_tx_polarity_flip_physical{120}=0xBD + +#BC15# +dport_map_port_72=29 +dport_map_port_73=30 +dport_map_port_74=31 +dport_map_port_75=32 +portmap_72=121:400 +phy_chain_rx_lane_map_physical{121.0}=0x75342610 +phy_chain_rx_lane_map_physical{122.0}=0x75342610 +phy_chain_rx_lane_map_physical{123.0}=0x75342610 +phy_chain_rx_lane_map_physical{124.0}=0x75342610 +phy_chain_rx_lane_map_physical{125.0}=0x75342610 +phy_chain_rx_lane_map_physical{126.0}=0x75342610 +phy_chain_rx_lane_map_physical{127.0}=0x75342610 +phy_chain_rx_lane_map_physical{128.0}=0x75342610 +phy_chain_tx_lane_map_physical{121.0}=0x24617350 +phy_chain_tx_lane_map_physical{122.0}=0x24617350 +phy_chain_tx_lane_map_physical{123.0}=0x24617350 +phy_chain_tx_lane_map_physical{124.0}=0x24617350 +phy_chain_tx_lane_map_physical{125.0}=0x24617350 +phy_chain_tx_lane_map_physical{126.0}=0x24617350 +phy_chain_tx_lane_map_physical{127.0}=0x24617350 +phy_chain_tx_lane_map_physical{128.0}=0x24617350 +serdes_core_rx_polarity_flip_physical{121}=0x36 +serdes_core_rx_polarity_flip_physical{122}=0x36 +serdes_core_rx_polarity_flip_physical{123}=0x36 +serdes_core_rx_polarity_flip_physical{124}=0x36 +serdes_core_rx_polarity_flip_physical{125}=0x36 +serdes_core_rx_polarity_flip_physical{126}=0x36 +serdes_core_rx_polarity_flip_physical{127}=0x36 +serdes_core_rx_polarity_flip_physical{128}=0x36 +serdes_core_tx_polarity_flip_physical{121}=0x7F +serdes_core_tx_polarity_flip_physical{122}=0x7F +serdes_core_tx_polarity_flip_physical{123}=0x7F +serdes_core_tx_polarity_flip_physical{124}=0x7F +serdes_core_tx_polarity_flip_physical{125}=0x7F +serdes_core_tx_polarity_flip_physical{126}=0x7F +serdes_core_tx_polarity_flip_physical{127}=0x7F +serdes_core_tx_polarity_flip_physical{128}=0x7F + +#BC16# +dport_map_port_80=49 +dport_map_port_81=50 +dport_map_port_82=51 +dport_map_port_83=52 +portmap_80=129:400 +phy_chain_rx_lane_map_physical{129.0}=0x45302716 +phy_chain_rx_lane_map_physical{130.0}=0x45302716 +phy_chain_rx_lane_map_physical{131.0}=0x45302716 +phy_chain_rx_lane_map_physical{132.0}=0x45302716 +phy_chain_rx_lane_map_physical{133.0}=0x45302716 +phy_chain_rx_lane_map_physical{134.0}=0x45302716 +phy_chain_rx_lane_map_physical{135.0}=0x45302716 +phy_chain_rx_lane_map_physical{136.0}=0x45302716 +phy_chain_tx_lane_map_physical{129.0}=0x24763150 +phy_chain_tx_lane_map_physical{130.0}=0x24763150 +phy_chain_tx_lane_map_physical{131.0}=0x24763150 +phy_chain_tx_lane_map_physical{132.0}=0x24763150 +phy_chain_tx_lane_map_physical{133.0}=0x24763150 +phy_chain_tx_lane_map_physical{134.0}=0x24763150 +phy_chain_tx_lane_map_physical{135.0}=0x24763150 +phy_chain_tx_lane_map_physical{136.0}=0x24763150 +serdes_core_rx_polarity_flip_physical{129}=0xA3 +serdes_core_rx_polarity_flip_physical{130}=0xA3 +serdes_core_rx_polarity_flip_physical{131}=0xA3 +serdes_core_rx_polarity_flip_physical{132}=0xA3 +serdes_core_rx_polarity_flip_physical{133}=0xA3 +serdes_core_rx_polarity_flip_physical{134}=0xA3 +serdes_core_rx_polarity_flip_physical{135}=0xA3 +serdes_core_rx_polarity_flip_physical{136}=0xA3 +serdes_core_tx_polarity_flip_physical{129}=0x5C +serdes_core_tx_polarity_flip_physical{130}=0x5C +serdes_core_tx_polarity_flip_physical{131}=0x5C +serdes_core_tx_polarity_flip_physical{132}=0x5C +serdes_core_tx_polarity_flip_physical{133}=0x5C +serdes_core_tx_polarity_flip_physical{134}=0x5C +serdes_core_tx_polarity_flip_physical{135}=0x5C +serdes_core_tx_polarity_flip_physical{136}=0x5C + +#BC17# +dport_map_port_84=53 +dport_map_port_85=54 +dport_map_port_86=55 +dport_map_port_87=56 +portmap_84=137:400 +phy_chain_rx_lane_map_physical{137.0}=0x12460357 +phy_chain_rx_lane_map_physical{138.0}=0x12460357 +phy_chain_rx_lane_map_physical{139.0}=0x12460357 +phy_chain_rx_lane_map_physical{140.0}=0x12460357 +phy_chain_rx_lane_map_physical{141.0}=0x12460357 +phy_chain_rx_lane_map_physical{142.0}=0x12460357 +phy_chain_rx_lane_map_physical{143.0}=0x12460357 +phy_chain_rx_lane_map_physical{144.0}=0x12460357 +phy_chain_tx_lane_map_physical{137.0}=0x70135462 +phy_chain_tx_lane_map_physical{138.0}=0x70135462 +phy_chain_tx_lane_map_physical{139.0}=0x70135462 +phy_chain_tx_lane_map_physical{140.0}=0x70135462 +phy_chain_tx_lane_map_physical{141.0}=0x70135462 +phy_chain_tx_lane_map_physical{142.0}=0x70135462 +phy_chain_tx_lane_map_physical{143.0}=0x70135462 +phy_chain_tx_lane_map_physical{144.0}=0x70135462 +serdes_core_rx_polarity_flip_physical{137}=0x4B +serdes_core_rx_polarity_flip_physical{138}=0x4B +serdes_core_rx_polarity_flip_physical{139}=0x4B +serdes_core_rx_polarity_flip_physical{140}=0x4B +serdes_core_rx_polarity_flip_physical{141}=0x4B +serdes_core_rx_polarity_flip_physical{142}=0x4B +serdes_core_rx_polarity_flip_physical{143}=0x4B +serdes_core_rx_polarity_flip_physical{144}=0x4B +serdes_core_tx_polarity_flip_physical{137}=0xF8 +serdes_core_tx_polarity_flip_physical{138}=0xF8 +serdes_core_tx_polarity_flip_physical{139}=0xF8 +serdes_core_tx_polarity_flip_physical{140}=0xF8 +serdes_core_tx_polarity_flip_physical{141}=0xF8 +serdes_core_tx_polarity_flip_physical{142}=0xF8 +serdes_core_tx_polarity_flip_physical{143}=0xF8 +serdes_core_tx_polarity_flip_physical{144}=0xF8 + +#BC18# +dport_map_port_88=57 +dport_map_port_89=58 +dport_map_port_90=59 +dport_map_port_91=60 +portmap_88=145:400 +phy_chain_rx_lane_map_physical{145.0}=0x20563147 +phy_chain_rx_lane_map_physical{146.0}=0x20563147 +phy_chain_rx_lane_map_physical{147.0}=0x20563147 +phy_chain_rx_lane_map_physical{148.0}=0x20563147 +phy_chain_rx_lane_map_physical{149.0}=0x20563147 +phy_chain_rx_lane_map_physical{150.0}=0x20563147 +phy_chain_rx_lane_map_physical{151.0}=0x20563147 +phy_chain_rx_lane_map_physical{152.0}=0x20563147 +phy_chain_tx_lane_map_physical{145.0}=0x54126073 +phy_chain_tx_lane_map_physical{146.0}=0x54126073 +phy_chain_tx_lane_map_physical{147.0}=0x54126073 +phy_chain_tx_lane_map_physical{148.0}=0x54126073 +phy_chain_tx_lane_map_physical{149.0}=0x54126073 +phy_chain_tx_lane_map_physical{150.0}=0x54126073 +phy_chain_tx_lane_map_physical{151.0}=0x54126073 +phy_chain_tx_lane_map_physical{152.0}=0x54126073 +serdes_core_rx_polarity_flip_physical{145}=0xE1 +serdes_core_rx_polarity_flip_physical{146}=0xE1 +serdes_core_rx_polarity_flip_physical{147}=0xE1 +serdes_core_rx_polarity_flip_physical{148}=0xE1 +serdes_core_rx_polarity_flip_physical{149}=0xE1 +serdes_core_rx_polarity_flip_physical{150}=0xE1 +serdes_core_rx_polarity_flip_physical{151}=0xE1 +serdes_core_rx_polarity_flip_physical{152}=0xE1 +serdes_core_tx_polarity_flip_physical{145}=0xD5 +serdes_core_tx_polarity_flip_physical{146}=0xD5 +serdes_core_tx_polarity_flip_physical{147}=0xD5 +serdes_core_tx_polarity_flip_physical{148}=0xD5 +serdes_core_tx_polarity_flip_physical{149}=0xD5 +serdes_core_tx_polarity_flip_physical{150}=0xD5 +serdes_core_tx_polarity_flip_physical{151}=0xD5 +serdes_core_tx_polarity_flip_physical{152}=0xD5 + +#BC19# +dport_map_port_92=61 +dport_map_port_93=62 +dport_map_port_94=63 +dport_map_port_95=64 +portmap_92=153:400 +phy_chain_rx_lane_map_physical{153.0}=0x10652473 +phy_chain_rx_lane_map_physical{154.0}=0x10652473 +phy_chain_rx_lane_map_physical{155.0}=0x10652473 +phy_chain_rx_lane_map_physical{156.0}=0x10652473 +phy_chain_rx_lane_map_physical{157.0}=0x10652473 +phy_chain_rx_lane_map_physical{158.0}=0x10652473 +phy_chain_rx_lane_map_physical{159.0}=0x10652473 +phy_chain_rx_lane_map_physical{160.0}=0x10652473 +phy_chain_tx_lane_map_physical{153.0}=0x15036427 +phy_chain_tx_lane_map_physical{154.0}=0x15036427 +phy_chain_tx_lane_map_physical{155.0}=0x15036427 +phy_chain_tx_lane_map_physical{156.0}=0x15036427 +phy_chain_tx_lane_map_physical{157.0}=0x15036427 +phy_chain_tx_lane_map_physical{158.0}=0x15036427 +phy_chain_tx_lane_map_physical{159.0}=0x15036427 +phy_chain_tx_lane_map_physical{160.0}=0x15036427 +serdes_core_rx_polarity_flip_physical{153}=0xB1 +serdes_core_rx_polarity_flip_physical{154}=0xB1 +serdes_core_rx_polarity_flip_physical{155}=0xB1 +serdes_core_rx_polarity_flip_physical{156}=0xB1 +serdes_core_rx_polarity_flip_physical{157}=0xB1 +serdes_core_rx_polarity_flip_physical{158}=0xB1 +serdes_core_rx_polarity_flip_physical{159}=0xB1 +serdes_core_rx_polarity_flip_physical{160}=0xB1 +serdes_core_tx_polarity_flip_physical{153}=0x5E +serdes_core_tx_polarity_flip_physical{154}=0x5E +serdes_core_tx_polarity_flip_physical{155}=0x5E +serdes_core_tx_polarity_flip_physical{156}=0x5E +serdes_core_tx_polarity_flip_physical{157}=0x5E +serdes_core_tx_polarity_flip_physical{158}=0x5E +serdes_core_tx_polarity_flip_physical{159}=0x5E +serdes_core_tx_polarity_flip_physical{160}=0x5E + +#BC20# +dport_map_port_104=69 +dport_map_port_105=70 +dport_map_port_106=71 +dport_map_port_107=72 +portmap_104=161:400 +phy_chain_rx_lane_map_physical{161.0}=0x70125643 +phy_chain_rx_lane_map_physical{162.0}=0x70125643 +phy_chain_rx_lane_map_physical{163.0}=0x70125643 +phy_chain_rx_lane_map_physical{164.0}=0x70125643 +phy_chain_rx_lane_map_physical{165.0}=0x70125643 +phy_chain_rx_lane_map_physical{166.0}=0x70125643 +phy_chain_rx_lane_map_physical{167.0}=0x70125643 +phy_chain_rx_lane_map_physical{168.0}=0x70125643 +phy_chain_tx_lane_map_physical{161.0}=0x21073456 +phy_chain_tx_lane_map_physical{162.0}=0x21073456 +phy_chain_tx_lane_map_physical{163.0}=0x21073456 +phy_chain_tx_lane_map_physical{164.0}=0x21073456 +phy_chain_tx_lane_map_physical{165.0}=0x21073456 +phy_chain_tx_lane_map_physical{166.0}=0x21073456 +phy_chain_tx_lane_map_physical{167.0}=0x21073456 +phy_chain_tx_lane_map_physical{168.0}=0x21073456 +serdes_core_rx_polarity_flip_physical{161}=0x27 +serdes_core_rx_polarity_flip_physical{162}=0x27 +serdes_core_rx_polarity_flip_physical{163}=0x27 +serdes_core_rx_polarity_flip_physical{164}=0x27 +serdes_core_rx_polarity_flip_physical{165}=0x27 +serdes_core_rx_polarity_flip_physical{166}=0x27 +serdes_core_rx_polarity_flip_physical{167}=0x27 +serdes_core_rx_polarity_flip_physical{168}=0x27 +serdes_core_tx_polarity_flip_physical{161}=0x5 +serdes_core_tx_polarity_flip_physical{162}=0x5 +serdes_core_tx_polarity_flip_physical{163}=0x5 +serdes_core_tx_polarity_flip_physical{164}=0x5 +serdes_core_tx_polarity_flip_physical{165}=0x5 +serdes_core_tx_polarity_flip_physical{166}=0x5 +serdes_core_tx_polarity_flip_physical{167}=0x5 +serdes_core_tx_polarity_flip_physical{168}=0x5 + +#BC21# +dport_map_port_100=65 +dport_map_port_101=66 +dport_map_port_102=67 +dport_map_port_103=68 +portmap_100=169:400 +phy_chain_rx_lane_map_physical{169.0}=0x27416350 +phy_chain_rx_lane_map_physical{170.0}=0x27416350 +phy_chain_rx_lane_map_physical{171.0}=0x27416350 +phy_chain_rx_lane_map_physical{172.0}=0x27416350 +phy_chain_rx_lane_map_physical{173.0}=0x27416350 +phy_chain_rx_lane_map_physical{174.0}=0x27416350 +phy_chain_rx_lane_map_physical{175.0}=0x27416350 +phy_chain_rx_lane_map_physical{176.0}=0x27416350 +phy_chain_tx_lane_map_physical{169.0}=0x36570412 +phy_chain_tx_lane_map_physical{170.0}=0x36570412 +phy_chain_tx_lane_map_physical{171.0}=0x36570412 +phy_chain_tx_lane_map_physical{172.0}=0x36570412 +phy_chain_tx_lane_map_physical{173.0}=0x36570412 +phy_chain_tx_lane_map_physical{174.0}=0x36570412 +phy_chain_tx_lane_map_physical{175.0}=0x36570412 +phy_chain_tx_lane_map_physical{176.0}=0x36570412 +serdes_core_rx_polarity_flip_physical{169}=0x3C +serdes_core_rx_polarity_flip_physical{170}=0x3C +serdes_core_rx_polarity_flip_physical{171}=0x3C +serdes_core_rx_polarity_flip_physical{172}=0x3C +serdes_core_rx_polarity_flip_physical{173}=0x3C +serdes_core_rx_polarity_flip_physical{174}=0x3C +serdes_core_rx_polarity_flip_physical{175}=0x3C +serdes_core_rx_polarity_flip_physical{176}=0x3C +serdes_core_tx_polarity_flip_physical{169}=0x7D +serdes_core_tx_polarity_flip_physical{170}=0x7D +serdes_core_tx_polarity_flip_physical{171}=0x7D +serdes_core_tx_polarity_flip_physical{172}=0x7D +serdes_core_tx_polarity_flip_physical{173}=0x7D +serdes_core_tx_polarity_flip_physical{174}=0x7D +serdes_core_tx_polarity_flip_physical{175}=0x7D +serdes_core_tx_polarity_flip_physical{176}=0x7D + +#BC22# +dport_map_port_108=73 +dport_map_port_109=74 +dport_map_port_110=75 +dport_map_port_111=76 +portmap_108=177:400 +phy_chain_rx_lane_map_physical{177.0}=0x04153726 +phy_chain_rx_lane_map_physical{178.0}=0x04153726 +phy_chain_rx_lane_map_physical{179.0}=0x04153726 +phy_chain_rx_lane_map_physical{180.0}=0x04153726 +phy_chain_rx_lane_map_physical{181.0}=0x04153726 +phy_chain_rx_lane_map_physical{182.0}=0x04153726 +phy_chain_rx_lane_map_physical{183.0}=0x04153726 +phy_chain_rx_lane_map_physical{184.0}=0x04153726 +phy_chain_tx_lane_map_physical{177.0}=0x47305162 +phy_chain_tx_lane_map_physical{178.0}=0x47305162 +phy_chain_tx_lane_map_physical{179.0}=0x47305162 +phy_chain_tx_lane_map_physical{180.0}=0x47305162 +phy_chain_tx_lane_map_physical{181.0}=0x47305162 +phy_chain_tx_lane_map_physical{182.0}=0x47305162 +phy_chain_tx_lane_map_physical{183.0}=0x47305162 +phy_chain_tx_lane_map_physical{184.0}=0x47305162 +serdes_core_rx_polarity_flip_physical{177}=0x96 +serdes_core_rx_polarity_flip_physical{178}=0x96 +serdes_core_rx_polarity_flip_physical{179}=0x96 +serdes_core_rx_polarity_flip_physical{180}=0x96 +serdes_core_rx_polarity_flip_physical{181}=0x96 +serdes_core_rx_polarity_flip_physical{182}=0x96 +serdes_core_rx_polarity_flip_physical{183}=0x96 +serdes_core_rx_polarity_flip_physical{184}=0x96 +serdes_core_tx_polarity_flip_physical{177}=0xE9 +serdes_core_tx_polarity_flip_physical{178}=0xE9 +serdes_core_tx_polarity_flip_physical{179}=0xE9 +serdes_core_tx_polarity_flip_physical{180}=0xE9 +serdes_core_tx_polarity_flip_physical{181}=0xE9 +serdes_core_tx_polarity_flip_physical{182}=0xE9 +serdes_core_tx_polarity_flip_physical{183}=0xE9 +serdes_core_tx_polarity_flip_physical{184}=0xE9 + +#BC23# +dport_map_port_112=77 +dport_map_port_113=78 +dport_map_port_114=79 +dport_map_port_115=80 +portmap_112=185:400 +phy_chain_rx_lane_map_physical{185.0}=0x02561347 +phy_chain_rx_lane_map_physical{186.0}=0x02561347 +phy_chain_rx_lane_map_physical{187.0}=0x02561347 +phy_chain_rx_lane_map_physical{188.0}=0x02561347 +phy_chain_rx_lane_map_physical{189.0}=0x02561347 +phy_chain_rx_lane_map_physical{190.0}=0x02561347 +phy_chain_rx_lane_map_physical{191.0}=0x02561347 +phy_chain_rx_lane_map_physical{192.0}=0x02561347 +phy_chain_tx_lane_map_physical{185.0}=0x50327614 +phy_chain_tx_lane_map_physical{186.0}=0x50327614 +phy_chain_tx_lane_map_physical{187.0}=0x50327614 +phy_chain_tx_lane_map_physical{188.0}=0x50327614 +phy_chain_tx_lane_map_physical{189.0}=0x50327614 +phy_chain_tx_lane_map_physical{190.0}=0x50327614 +phy_chain_tx_lane_map_physical{191.0}=0x50327614 +phy_chain_tx_lane_map_physical{192.0}=0x50327614 +serdes_core_rx_polarity_flip_physical{185}=0xE1 +serdes_core_rx_polarity_flip_physical{186}=0xE1 +serdes_core_rx_polarity_flip_physical{187}=0xE1 +serdes_core_rx_polarity_flip_physical{188}=0xE1 +serdes_core_rx_polarity_flip_physical{189}=0xE1 +serdes_core_rx_polarity_flip_physical{190}=0xE1 +serdes_core_rx_polarity_flip_physical{191}=0xE1 +serdes_core_rx_polarity_flip_physical{192}=0xE1 +serdes_core_tx_polarity_flip_physical{185}=0x0 +serdes_core_tx_polarity_flip_physical{186}=0x0 +serdes_core_tx_polarity_flip_physical{187}=0x0 +serdes_core_tx_polarity_flip_physical{188}=0x0 +serdes_core_tx_polarity_flip_physical{189}=0x0 +serdes_core_tx_polarity_flip_physical{190}=0x0 +serdes_core_tx_polarity_flip_physical{191}=0x0 +serdes_core_tx_polarity_flip_physical{192}=0x0 + +#BC24# +dport_map_port_124=101 +dport_map_port_125=102 +dport_map_port_126=103 +dport_map_port_127=104 +portmap_124=193:400 +phy_chain_rx_lane_map_physical{193.0}=0x74126503 +phy_chain_rx_lane_map_physical{194.0}=0x74126503 +phy_chain_rx_lane_map_physical{195.0}=0x74126503 +phy_chain_rx_lane_map_physical{196.0}=0x74126503 +phy_chain_rx_lane_map_physical{197.0}=0x74126503 +phy_chain_rx_lane_map_physical{198.0}=0x74126503 +phy_chain_rx_lane_map_physical{199.0}=0x74126503 +phy_chain_rx_lane_map_physical{200.0}=0x74126503 +phy_chain_tx_lane_map_physical{193.0}=0x43571620 +phy_chain_tx_lane_map_physical{194.0}=0x43571620 +phy_chain_tx_lane_map_physical{195.0}=0x43571620 +phy_chain_tx_lane_map_physical{196.0}=0x43571620 +phy_chain_tx_lane_map_physical{197.0}=0x43571620 +phy_chain_tx_lane_map_physical{198.0}=0x43571620 +phy_chain_tx_lane_map_physical{199.0}=0x43571620 +phy_chain_tx_lane_map_physical{200.0}=0x43571620 +serdes_core_rx_polarity_flip_physical{193}=0x69 +serdes_core_rx_polarity_flip_physical{194}=0x69 +serdes_core_rx_polarity_flip_physical{195}=0x69 +serdes_core_rx_polarity_flip_physical{196}=0x69 +serdes_core_rx_polarity_flip_physical{197}=0x69 +serdes_core_rx_polarity_flip_physical{198}=0x69 +serdes_core_rx_polarity_flip_physical{199}=0x69 +serdes_core_rx_polarity_flip_physical{200}=0x69 +serdes_core_tx_polarity_flip_physical{193}=0xC4 +serdes_core_tx_polarity_flip_physical{194}=0xC4 +serdes_core_tx_polarity_flip_physical{195}=0xC4 +serdes_core_tx_polarity_flip_physical{196}=0xC4 +serdes_core_tx_polarity_flip_physical{197}=0xC4 +serdes_core_tx_polarity_flip_physical{198}=0xC4 +serdes_core_tx_polarity_flip_physical{199}=0xC4 +serdes_core_tx_polarity_flip_physical{200}=0xC4 + +#BC25# +dport_map_port_120=97 +dport_map_port_121=98 +dport_map_port_122=99 +dport_map_port_123=100 +portmap_120=201:400 +phy_chain_rx_lane_map_physical{201.0}=0x45031726 +phy_chain_rx_lane_map_physical{202.0}=0x45031726 +phy_chain_rx_lane_map_physical{203.0}=0x45031726 +phy_chain_rx_lane_map_physical{204.0}=0x45031726 +phy_chain_rx_lane_map_physical{205.0}=0x45031726 +phy_chain_rx_lane_map_physical{206.0}=0x45031726 +phy_chain_rx_lane_map_physical{207.0}=0x45031726 +phy_chain_rx_lane_map_physical{208.0}=0x45031726 +phy_chain_tx_lane_map_physical{201.0}=0x23761450 +phy_chain_tx_lane_map_physical{202.0}=0x23761450 +phy_chain_tx_lane_map_physical{203.0}=0x23761450 +phy_chain_tx_lane_map_physical{204.0}=0x23761450 +phy_chain_tx_lane_map_physical{205.0}=0x23761450 +phy_chain_tx_lane_map_physical{206.0}=0x23761450 +phy_chain_tx_lane_map_physical{207.0}=0x23761450 +phy_chain_tx_lane_map_physical{208.0}=0x23761450 +serdes_core_rx_polarity_flip_physical{201}=0x99 +serdes_core_rx_polarity_flip_physical{202}=0x99 +serdes_core_rx_polarity_flip_physical{203}=0x99 +serdes_core_rx_polarity_flip_physical{204}=0x99 +serdes_core_rx_polarity_flip_physical{205}=0x99 +serdes_core_rx_polarity_flip_physical{206}=0x99 +serdes_core_rx_polarity_flip_physical{207}=0x99 +serdes_core_rx_polarity_flip_physical{208}=0x99 +serdes_core_tx_polarity_flip_physical{201}=0x7F +serdes_core_tx_polarity_flip_physical{202}=0x7F +serdes_core_tx_polarity_flip_physical{203}=0x7F +serdes_core_tx_polarity_flip_physical{204}=0x7F +serdes_core_tx_polarity_flip_physical{205}=0x7F +serdes_core_tx_polarity_flip_physical{206}=0x7F +serdes_core_tx_polarity_flip_physical{207}=0x7F +serdes_core_tx_polarity_flip_physical{208}=0x7F + +#BC26# +dport_map_port_132=109 +dport_map_port_133=110 +dport_map_port_134=111 +dport_map_port_135=112 +portmap_132=209:400 +phy_chain_rx_lane_map_physical{209.0}=0x46150723 +phy_chain_rx_lane_map_physical{210.0}=0x46150723 +phy_chain_rx_lane_map_physical{211.0}=0x46150723 +phy_chain_rx_lane_map_physical{212.0}=0x46150723 +phy_chain_rx_lane_map_physical{213.0}=0x46150723 +phy_chain_rx_lane_map_physical{214.0}=0x46150723 +phy_chain_rx_lane_map_physical{215.0}=0x46150723 +phy_chain_rx_lane_map_physical{216.0}=0x46150723 +phy_chain_tx_lane_map_physical{209.0}=0x12603754 +phy_chain_tx_lane_map_physical{210.0}=0x12603754 +phy_chain_tx_lane_map_physical{211.0}=0x12603754 +phy_chain_tx_lane_map_physical{212.0}=0x12603754 +phy_chain_tx_lane_map_physical{213.0}=0x12603754 +phy_chain_tx_lane_map_physical{214.0}=0x12603754 +phy_chain_tx_lane_map_physical{215.0}=0x12603754 +phy_chain_tx_lane_map_physical{216.0}=0x12603754 +serdes_core_rx_polarity_flip_physical{209}=0xE1 +serdes_core_rx_polarity_flip_physical{210}=0xE1 +serdes_core_rx_polarity_flip_physical{211}=0xE1 +serdes_core_rx_polarity_flip_physical{212}=0xE1 +serdes_core_rx_polarity_flip_physical{213}=0xE1 +serdes_core_rx_polarity_flip_physical{214}=0xE1 +serdes_core_rx_polarity_flip_physical{215}=0xE1 +serdes_core_rx_polarity_flip_physical{216}=0xE1 +serdes_core_tx_polarity_flip_physical{209}=0x29 +serdes_core_tx_polarity_flip_physical{210}=0x29 +serdes_core_tx_polarity_flip_physical{211}=0x29 +serdes_core_tx_polarity_flip_physical{212}=0x29 +serdes_core_tx_polarity_flip_physical{213}=0x29 +serdes_core_tx_polarity_flip_physical{214}=0x29 +serdes_core_tx_polarity_flip_physical{215}=0x29 +serdes_core_tx_polarity_flip_physical{216}=0x29 + +#BC27# +dport_map_port_128=105 +dport_map_port_129=106 +dport_map_port_130=107 +dport_map_port_131=108 +portmap_128=217:400 +phy_chain_rx_lane_map_physical{217.0}=0x46127503 +phy_chain_rx_lane_map_physical{218.0}=0x46127503 +phy_chain_rx_lane_map_physical{219.0}=0x46127503 +phy_chain_rx_lane_map_physical{220.0}=0x46127503 +phy_chain_rx_lane_map_physical{221.0}=0x46127503 +phy_chain_rx_lane_map_physical{222.0}=0x46127503 +phy_chain_rx_lane_map_physical{223.0}=0x46127503 +phy_chain_rx_lane_map_physical{224.0}=0x46127503 +phy_chain_tx_lane_map_physical{217.0}=0x54273016 +phy_chain_tx_lane_map_physical{218.0}=0x54273016 +phy_chain_tx_lane_map_physical{219.0}=0x54273016 +phy_chain_tx_lane_map_physical{220.0}=0x54273016 +phy_chain_tx_lane_map_physical{221.0}=0x54273016 +phy_chain_tx_lane_map_physical{222.0}=0x54273016 +phy_chain_tx_lane_map_physical{223.0}=0x54273016 +phy_chain_tx_lane_map_physical{224.0}=0x54273016 +serdes_core_rx_polarity_flip_physical{217}=0xE1 +serdes_core_rx_polarity_flip_physical{218}=0xE1 +serdes_core_rx_polarity_flip_physical{219}=0xE1 +serdes_core_rx_polarity_flip_physical{220}=0xE1 +serdes_core_rx_polarity_flip_physical{221}=0xE1 +serdes_core_rx_polarity_flip_physical{222}=0xE1 +serdes_core_rx_polarity_flip_physical{223}=0xE1 +serdes_core_rx_polarity_flip_physical{224}=0xE1 +serdes_core_tx_polarity_flip_physical{217}=0x5B +serdes_core_tx_polarity_flip_physical{218}=0x5B +serdes_core_tx_polarity_flip_physical{219}=0x5B +serdes_core_tx_polarity_flip_physical{220}=0x5B +serdes_core_tx_polarity_flip_physical{221}=0x5B +serdes_core_tx_polarity_flip_physical{222}=0x5B +serdes_core_tx_polarity_flip_physical{223}=0x5B +serdes_core_tx_polarity_flip_physical{224}=0x5B + +#BC28# +dport_map_port_144=117 +dport_map_port_145=118 +dport_map_port_146=119 +dport_map_port_147=120 +portmap_144=225:400 +phy_chain_rx_lane_map_physical{225.0}=0x52761340 +phy_chain_rx_lane_map_physical{226.0}=0x52761340 +phy_chain_rx_lane_map_physical{227.0}=0x52761340 +phy_chain_rx_lane_map_physical{228.0}=0x52761340 +phy_chain_rx_lane_map_physical{229.0}=0x52761340 +phy_chain_rx_lane_map_physical{230.0}=0x52761340 +phy_chain_rx_lane_map_physical{231.0}=0x52761340 +phy_chain_rx_lane_map_physical{232.0}=0x52761340 +phy_chain_tx_lane_map_physical{225.0}=0x53462107 +phy_chain_tx_lane_map_physical{226.0}=0x53462107 +phy_chain_tx_lane_map_physical{227.0}=0x53462107 +phy_chain_tx_lane_map_physical{228.0}=0x53462107 +phy_chain_tx_lane_map_physical{229.0}=0x53462107 +phy_chain_tx_lane_map_physical{230.0}=0x53462107 +phy_chain_tx_lane_map_physical{231.0}=0x53462107 +phy_chain_tx_lane_map_physical{232.0}=0x53462107 +serdes_core_rx_polarity_flip_physical{225}=0x3C +serdes_core_rx_polarity_flip_physical{226}=0x3C +serdes_core_rx_polarity_flip_physical{227}=0x3C +serdes_core_rx_polarity_flip_physical{228}=0x3C +serdes_core_rx_polarity_flip_physical{229}=0x3C +serdes_core_rx_polarity_flip_physical{230}=0x3C +serdes_core_rx_polarity_flip_physical{231}=0x3C +serdes_core_rx_polarity_flip_physical{232}=0x3C +serdes_core_tx_polarity_flip_physical{225}=0x71 +serdes_core_tx_polarity_flip_physical{226}=0x71 +serdes_core_tx_polarity_flip_physical{227}=0x71 +serdes_core_tx_polarity_flip_physical{228}=0x71 +serdes_core_tx_polarity_flip_physical{229}=0x71 +serdes_core_tx_polarity_flip_physical{230}=0x71 +serdes_core_tx_polarity_flip_physical{231}=0x71 +serdes_core_tx_polarity_flip_physical{232}=0x71 + +#BC29# +dport_map_port_140=113 +dport_map_port_141=114 +dport_map_port_142=115 +dport_map_port_143=116 +portmap_140=233:400 +phy_chain_rx_lane_map_physical{233.0}=0x45021736 +phy_chain_rx_lane_map_physical{234.0}=0x45021736 +phy_chain_rx_lane_map_physical{235.0}=0x45021736 +phy_chain_rx_lane_map_physical{236.0}=0x45021736 +phy_chain_rx_lane_map_physical{237.0}=0x45021736 +phy_chain_rx_lane_map_physical{238.0}=0x45021736 +phy_chain_rx_lane_map_physical{239.0}=0x45021736 +phy_chain_rx_lane_map_physical{240.0}=0x45021736 +phy_chain_tx_lane_map_physical{233.0}=0x20465371 +phy_chain_tx_lane_map_physical{234.0}=0x20465371 +phy_chain_tx_lane_map_physical{235.0}=0x20465371 +phy_chain_tx_lane_map_physical{236.0}=0x20465371 +phy_chain_tx_lane_map_physical{237.0}=0x20465371 +phy_chain_tx_lane_map_physical{238.0}=0x20465371 +phy_chain_tx_lane_map_physical{239.0}=0x20465371 +phy_chain_tx_lane_map_physical{240.0}=0x20465371 +serdes_core_rx_polarity_flip_physical{233}=0x8B +serdes_core_rx_polarity_flip_physical{234}=0x8B +serdes_core_rx_polarity_flip_physical{235}=0x8B +serdes_core_rx_polarity_flip_physical{236}=0x8B +serdes_core_rx_polarity_flip_physical{237}=0x8B +serdes_core_rx_polarity_flip_physical{238}=0x8B +serdes_core_rx_polarity_flip_physical{239}=0x8B +serdes_core_rx_polarity_flip_physical{240}=0x8B +serdes_core_tx_polarity_flip_physical{233}=0x35 +serdes_core_tx_polarity_flip_physical{234}=0x35 +serdes_core_tx_polarity_flip_physical{235}=0x35 +serdes_core_tx_polarity_flip_physical{236}=0x35 +serdes_core_tx_polarity_flip_physical{237}=0x35 +serdes_core_tx_polarity_flip_physical{238}=0x35 +serdes_core_tx_polarity_flip_physical{239}=0x35 +serdes_core_tx_polarity_flip_physical{240}=0x35 + +#BC30# +dport_map_port_152=125 +dport_map_port_153=126 +dport_map_port_154=127 +dport_map_port_155=128 +portmap_152=241:400 +phy_chain_rx_lane_map_physical{241.0}=0x65721403 +phy_chain_rx_lane_map_physical{242.0}=0x65721403 +phy_chain_rx_lane_map_physical{243.0}=0x65721403 +phy_chain_rx_lane_map_physical{244.0}=0x65721403 +phy_chain_rx_lane_map_physical{245.0}=0x65721403 +phy_chain_rx_lane_map_physical{246.0}=0x65721403 +phy_chain_rx_lane_map_physical{247.0}=0x65721403 +phy_chain_rx_lane_map_physical{248.0}=0x65721403 +phy_chain_tx_lane_map_physical{241.0}=0x32647150 +phy_chain_tx_lane_map_physical{242.0}=0x32647150 +phy_chain_tx_lane_map_physical{243.0}=0x32647150 +phy_chain_tx_lane_map_physical{244.0}=0x32647150 +phy_chain_tx_lane_map_physical{245.0}=0x32647150 +phy_chain_tx_lane_map_physical{246.0}=0x32647150 +phy_chain_tx_lane_map_physical{247.0}=0x32647150 +phy_chain_tx_lane_map_physical{248.0}=0x32647150 +serdes_core_rx_polarity_flip_physical{241}=0x8D +serdes_core_rx_polarity_flip_physical{242}=0x8D +serdes_core_rx_polarity_flip_physical{243}=0x8D +serdes_core_rx_polarity_flip_physical{244}=0x8D +serdes_core_rx_polarity_flip_physical{245}=0x8D +serdes_core_rx_polarity_flip_physical{246}=0x8D +serdes_core_rx_polarity_flip_physical{247}=0x8D +serdes_core_rx_polarity_flip_physical{248}=0x8D +serdes_core_tx_polarity_flip_physical{241}=0x35 +serdes_core_tx_polarity_flip_physical{242}=0x35 +serdes_core_tx_polarity_flip_physical{243}=0x35 +serdes_core_tx_polarity_flip_physical{244}=0x35 +serdes_core_tx_polarity_flip_physical{245}=0x35 +serdes_core_tx_polarity_flip_physical{246}=0x35 +serdes_core_tx_polarity_flip_physical{247}=0x35 +serdes_core_tx_polarity_flip_physical{248}=0x35 + +#BC31# +dport_map_port_148=121 +dport_map_port_149=122 +dport_map_port_150=123 +dport_map_port_151=124 +portmap_148=249:400 +phy_chain_rx_lane_map_physical{249.0}=0x13560247 +phy_chain_rx_lane_map_physical{250.0}=0x13560247 +phy_chain_rx_lane_map_physical{251.0}=0x13560247 +phy_chain_rx_lane_map_physical{252.0}=0x13560247 +phy_chain_rx_lane_map_physical{253.0}=0x13560247 +phy_chain_rx_lane_map_physical{254.0}=0x13560247 +phy_chain_rx_lane_map_physical{255.0}=0x13560247 +phy_chain_rx_lane_map_physical{256.0}=0x13560247 +phy_chain_tx_lane_map_physical{249.0}=0x10456273 +phy_chain_tx_lane_map_physical{250.0}=0x10456273 +phy_chain_tx_lane_map_physical{251.0}=0x10456273 +phy_chain_tx_lane_map_physical{252.0}=0x10456273 +phy_chain_tx_lane_map_physical{253.0}=0x10456273 +phy_chain_tx_lane_map_physical{254.0}=0x10456273 +phy_chain_tx_lane_map_physical{255.0}=0x10456273 +phy_chain_tx_lane_map_physical{256.0}=0x10456273 +serdes_core_rx_polarity_flip_physical{249}=0x2D +serdes_core_rx_polarity_flip_physical{250}=0x2D +serdes_core_rx_polarity_flip_physical{251}=0x2D +serdes_core_rx_polarity_flip_physical{252}=0x2D +serdes_core_rx_polarity_flip_physical{253}=0x2D +serdes_core_rx_polarity_flip_physical{254}=0x2D +serdes_core_rx_polarity_flip_physical{255}=0x2D +serdes_core_rx_polarity_flip_physical{256}=0x2D +serdes_core_tx_polarity_flip_physical{249}=0xD6 +serdes_core_tx_polarity_flip_physical{250}=0xD6 +serdes_core_tx_polarity_flip_physical{251}=0xD6 +serdes_core_tx_polarity_flip_physical{252}=0xD6 +serdes_core_tx_polarity_flip_physical{253}=0xD6 +serdes_core_tx_polarity_flip_physical{254}=0xD6 +serdes_core_tx_polarity_flip_physical{255}=0xD6 +serdes_core_tx_polarity_flip_physical{256}=0xD6 + +#dport_map_port_38=129 +#portmap_38=257:10 +#dport_map_port_118=130 +#portmap_118=258:10 diff --git a/device/accton/x86_64-accton_as9716_32d-r0/custom_led.bin b/device/accton/x86_64-accton_as9716_32d-r0/custom_led.bin new file mode 100644 index 000000000000..07cfab044f60 Binary files /dev/null and b/device/accton/x86_64-accton_as9716_32d-r0/custom_led.bin differ diff --git a/device/accton/x86_64-accton_as9716_32d-r0/default_sku b/device/accton/x86_64-accton_as9716_32d-r0/default_sku new file mode 100644 index 000000000000..ccebae89a34e --- /dev/null +++ b/device/accton/x86_64-accton_as9716_32d-r0/default_sku @@ -0,0 +1 @@ +Accton-AS9716-32D t1 diff --git a/device/accton/x86_64-accton_as9716_32d-r0/installer.conf b/device/accton/x86_64-accton_as9716_32d-r0/installer.conf new file mode 100644 index 000000000000..d5f9419d77ff --- /dev/null +++ b/device/accton/x86_64-accton_as9716_32d-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pcie_aspm=off" diff --git a/device/accton/x86_64-accton_as9716_32d-r0/led_proc_init.soc b/device/accton/x86_64-accton_as9716_32d-r0/led_proc_init.soc new file mode 100644 index 000000000000..57ee7fedaf2b --- /dev/null +++ b/device/accton/x86_64-accton_as9716_32d-r0/led_proc_init.soc @@ -0,0 +1,3 @@ +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/accton/x86_64-accton_as9716_32d-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as9716_32d-r0/plugins/eeprom.py new file mode 100644 index 000000000000..9031f2c60ece --- /dev/null +++ b/device/accton/x86_64-accton_as9716_32d-r0/plugins/eeprom.py @@ -0,0 +1,33 @@ +try: + 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 as e: + raise ImportError(str(e) + "- required module not found") + + +def eeprom_check(): + filepath = "/sys/bus/i2c/devices/0-0057/eeprom" + if os.path.isfile(filepath): + return 1 # now board, 0x57 + else: + return 0 # now board, 0x56 + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + + def __init__(self, name, path, cpld_root, ro): + ret = eeprom_check() + if ret == 1: + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + else: + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as9716_32d-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as9716_32d-r0/plugins/psuutil.py new file mode 100644 index 000000000000..ef49f262dca9 --- /dev/null +++ b/device/accton/x86_64-accton_as9716_32d-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 2: "10-0051", + 1: "9-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/accton/x86_64-accton_as9716_32d-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as9716_32d-r0/plugins/sfputil.py new file mode 100755 index 000000000000..7b3ca53d4ed4 --- /dev/null +++ b/device/accton/x86_64-accton_as9716_32d-r0/plugins/sfputil.py @@ -0,0 +1,290 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import sys + from ctypes import create_string_buffer + 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 = 0 + PORT_END = 33 + PORTS_IN_BLOCK = 34 + + BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" + BASE_CPLD1_PATH = "/sys/bus/i2c/devices/20-0061/" + BASE_CPLD2_PATH = "/sys/bus/i2c/devices/21-0062/" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 0: [1, 25], + 1: [2, 26], + 2: [3, 27], + 3: [4, 28], + 4: [5, 29], + 5: [6, 30], + 6: [7, 31], + 7: [8, 32], + 8: [9, 33], + 9: [10, 34], + 10: [11, 35], + 11: [12, 36], + 12: [13, 37], + 13: [14, 38], + 14: [15, 39], + 15: [16, 40], + 16: [17, 41], + 17: [18, 42], + 18: [19, 43], + 19: [20, 44], + 20: [21, 45], + 21: [22, 46], + 22: [23, 47], + 23: [24, 48], + 24: [25, 49], + 25: [26, 50], + 26: [27, 51], + 27: [28, 52], + 28: [29, 53], + 29: [30, 54], + 30: [31, 55], + 31: [32, 56], + 32: [33, 57], + 33: [34, 58], + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = self.BASE_OOM_PATH + "eeprom" + + for x in range(0, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x][1] + ) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < 16: + present_path = self.BASE_CPLD1_PATH + "module_present_" + str(port_num+1) + else: + present_path = self.BASE_CPLD2_PATH + "module_present_" + str(port_num+1) + self.__port_to_is_present = present_path + + content = "0" + try: + val_file = open(self.__port_to_is_present) + content = val_file.readline().rstrip() + val_file.close() + except IOError as e: + print("Error: unable to access file: %s" % str(e)) + return False + + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + # 0x3:Low Power Mode. "Power override" bit is 1 and "Power set" bit is 1 + # 0x9:High Power Mode. "Power override" bit is 1 ,"Power set" bit is 0 and "High Power Class Enable" bit is 1 + regval = 0x3 if lpmode else 0x9 + + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def reset(self, port_num): + if port_num < self.port_start or port_num > self.port_end: + return False + + if port_num < 16: + mod_rst_path = self.BASE_CPLD1_PATH + "module_reset_" + str(port_num+1) + else: + mod_rst_path = self.BASE_CPLD2_PATH + "module_reset_" + str(port_num+1) + + self.__port_to_mod_rst = mod_rst_path + try: + reg_file = open(self.__port_to_mod_rst, 'r+') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = '1' + + reg_file.write(reg_value) + reg_file.close() + + return True + + def get_cpld_interrupt(self): + port_dict = {} + for i in range(0, 4): + if i == 0 or i == 1: + cpld_i2c_path = self.BASE_CPLD1_PATH + "cpld_intr_" + str(i+1) + else: + cpld_i2c_path = self.BASE_CPLD2_PATH + "cpld_intr_" + str(i+1) + + start_i = (i*8) + end_i = (i*8+8) + try: + val_file = open(cpld_i2c_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + for k in range(start_i, end_i): + port_dict[k] = 0 + return port_dict + + status = val_file.readline().rstrip() + val_file.close() + status = status.strip() + status = int(status, 16) + + interrupt_status = ~(status & 0xff) + if interrupt_status: + port_shift = 0 + for k in range(start_i, end_i): + if interrupt_status & (0x1 << port_shift): + port_dict[k] = 1 + else: + port_dict[k] = 0 + port_shift = port_shift+1 + + return port_dict + + def get_transceiver_change_event(self, timeout=0): + start_time = time.time() + port_dict = {} + ori_present = {} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print('get_transceiver_change_event:' + 'time wrap / invalid timeout value', timeout) + + return False, {} # Time wrap or possibly incorrect timeout + + # for i in range(self.port_start, self.port_end+1): + # ori_present[i]=self.get_presence(i) + + while timeout >= 0: + change_status = 0 + + port_dict = self.get_cpld_interrupt() + present = 0 + for key, value in port_dict.items(): + if value == 1: + present = self.get_presence(key) + change_status = 1 + if present: + port_dict[key] = '1' + else: + port_dict[key] = '0' + + if change_status: + return True, port_dict + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + print("get_evt_change_event: Should not reach here.") + return False, {} diff --git a/device/accton/x86_64-accton_as9716_32d-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as9716_32d-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_as9716_32d-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/config_16Q_FEC544_EVTA_100G.bcm b/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/config_16Q_FEC544_EVTA_100G.bcm new file mode 100755 index 000000000000..a9dfbd4797e1 --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/config_16Q_FEC544_EVTA_100G.bcm @@ -0,0 +1,1489 @@ +pbmp_xport_xe.0=0x3ffffffffffffffffffffffffffffffffffffffe +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 + +init_all_modules=0 +core_clock_frequency=1325 +dpr_clock_frequency=1000 +device_clock_frequency=1325 +port_flex_enable=1 + +l3_alpm_enable=2 +l3_mem_entries=983040 +ipv6_lpm_128b_enable=1 + +#firmware load method, use fast load +load_firmware=0x2 + +serdes_lane_config_dfe=on +serdes_lane_config_media_type=backplane + +port_fec_1=3 +port_fec_2=3 +port_fec_3=3 +port_fec_4=3 +port_fec_5=3 +port_fec_6=3 +port_fec_7=3 +port_fec_8=3 +port_fec_9=3 +port_fec_10=3 +port_fec_11=3 +port_fec_12=3 +port_fec_13=3 +port_fec_14=3 +port_fec_15=3 +port_fec_16=3 +port_fec_20=3 +port_fec_21=3 +port_fec_22=3 +port_fec_23=3 +port_fec_24=3 +port_fec_25=3 +port_fec_26=3 +port_fec_27=3 +port_fec_28=3 +port_fec_29=3 +port_fec_30=3 +port_fec_31=3 +port_fec_32=3 +port_fec_33=3 +port_fec_34=3 +port_fec_35=3 +port_fec_40=3 +port_fec_41=3 +port_fec_42=3 +port_fec_43=3 +port_fec_44=3 +port_fec_45=3 +port_fec_46=3 +port_fec_47=3 +port_fec_48=3 +port_fec_49=3 +port_fec_50=3 +port_fec_51=3 +port_fec_52=3 +port_fec_53=3 +port_fec_54=3 +port_fec_55=3 +port_fec_60=3 +port_fec_61=3 +port_fec_62=3 +port_fec_63=3 +port_fec_64=3 +port_fec_65=3 +port_fec_66=3 +port_fec_67=3 +port_fec_68=3 +port_fec_69=3 +port_fec_70=3 +port_fec_71=3 +port_fec_72=3 +port_fec_73=3 +port_fec_74=3 +port_fec_75=3 +port_fec_80=3 +port_fec_81=3 +port_fec_82=3 +port_fec_83=3 +port_fec_84=3 +port_fec_85=3 +port_fec_86=3 +port_fec_87=3 +port_fec_88=3 +port_fec_89=3 +port_fec_90=3 +port_fec_91=3 +port_fec_92=3 +port_fec_93=3 +port_fec_94=3 +port_fec_95=3 +port_fec_100=3 +port_fec_101=3 +port_fec_102=3 +port_fec_103=3 +port_fec_104=3 +port_fec_105=3 +port_fec_106=3 +port_fec_107=3 +port_fec_108=3 +port_fec_109=3 +port_fec_110=3 +port_fec_111=3 +port_fec_112=3 +port_fec_113=3 +port_fec_114=3 +port_fec_115=3 +port_fec_120=3 +port_fec_121=3 +port_fec_122=3 +port_fec_123=3 +port_fec_124=3 +port_fec_125=3 +port_fec_126=3 +port_fec_127=3 +port_fec_128=3 +port_fec_129=3 +port_fec_130=3 +port_fec_131=3 +port_fec_132=3 +port_fec_133=3 +port_fec_134=3 +port_fec_135=3 +port_fec_140=3 +port_fec_141=3 +port_fec_142=3 +port_fec_143=3 +port_fec_144=3 +port_fec_145=3 +port_fec_146=3 +port_fec_147=3 +port_fec_148=3 +port_fec_149=3 +port_fec_150=3 +port_fec_151=3 +port_fec_152=3 +port_fec_153=3 +port_fec_154=3 +port_fec_155=3 + +dport_map_port_1=3 +dport_map_port_2=4 +dport_map_port_3=1 +dport_map_port_4=2 +portmap_1=1:100 +portmap_2=3:100 +portmap_3=5:100 +portmap_4=7:100 +phy_chain_rx_lane_map_physical{1.0}=0x32145670 +phy_chain_rx_lane_map_physical{2.0}=0x32145670 +phy_chain_rx_lane_map_physical{3.0}=0x32145670 +phy_chain_rx_lane_map_physical{4.0}=0x32145670 +phy_chain_rx_lane_map_physical{5.0}=0x32145670 +phy_chain_rx_lane_map_physical{6.0}=0x32145670 +phy_chain_rx_lane_map_physical{7.0}=0x32145670 +phy_chain_rx_lane_map_physical{8.0}=0x32145670 +phy_chain_tx_lane_map_physical{1.0}=0x32046751 +phy_chain_tx_lane_map_physical{2.0}=0x32046751 +phy_chain_tx_lane_map_physical{3.0}=0x32046751 +phy_chain_tx_lane_map_physical{4.0}=0x32046751 +phy_chain_tx_lane_map_physical{5.0}=0x32046751 +phy_chain_tx_lane_map_physical{6.0}=0x32046751 +phy_chain_tx_lane_map_physical{7.0}=0x32046751 +phy_chain_tx_lane_map_physical{8.0}=0x32046751 +serdes_core_rx_polarity_flip_physical{1}=0xA4 +serdes_core_rx_polarity_flip_physical{2}=0xA4 +serdes_core_rx_polarity_flip_physical{3}=0xA4 +serdes_core_rx_polarity_flip_physical{4}=0xA4 +serdes_core_rx_polarity_flip_physical{5}=0xA4 +serdes_core_rx_polarity_flip_physical{6}=0xA4 +serdes_core_rx_polarity_flip_physical{7}=0xA4 +serdes_core_rx_polarity_flip_physical{8}=0xA4 +serdes_core_tx_polarity_flip_physical{1}=0xE6 +serdes_core_tx_polarity_flip_physical{2}=0xE6 +serdes_core_tx_polarity_flip_physical{3}=0xE6 +serdes_core_tx_polarity_flip_physical{4}=0xE6 +serdes_core_tx_polarity_flip_physical{5}=0xE6 +serdes_core_tx_polarity_flip_physical{6}=0xE6 +serdes_core_tx_polarity_flip_physical{7}=0xE6 +serdes_core_tx_polarity_flip_physical{8}=0xE6 + +dport_map_port_5=19 +dport_map_port_6=20 +dport_map_port_7=17 +dport_map_port_8=18 +portmap_5=9:100 +portmap_6=11:100 +portmap_7=13:100 +portmap_8=15:100 +phy_chain_rx_lane_map_physical{9.0}=0x45673021 +phy_chain_rx_lane_map_physical{10.0}=0x45673021 +phy_chain_rx_lane_map_physical{11.0}=0x45673021 +phy_chain_rx_lane_map_physical{12.0}=0x45673021 +phy_chain_rx_lane_map_physical{13.0}=0x45673021 +phy_chain_rx_lane_map_physical{14.0}=0x45673021 +phy_chain_rx_lane_map_physical{15.0}=0x45673021 +phy_chain_rx_lane_map_physical{16.0}=0x45673021 +phy_chain_tx_lane_map_physical{9.0}=0x13240756 +phy_chain_tx_lane_map_physical{10.0}=0x13240756 +phy_chain_tx_lane_map_physical{11.0}=0x13240756 +phy_chain_tx_lane_map_physical{12.0}=0x13240756 +phy_chain_tx_lane_map_physical{13.0}=0x13240756 +phy_chain_tx_lane_map_physical{14.0}=0x13240756 +phy_chain_tx_lane_map_physical{15.0}=0x13240756 +phy_chain_tx_lane_map_physical{16.0}=0x13240756 +serdes_core_rx_polarity_flip_physical{9}=0x43 +serdes_core_rx_polarity_flip_physical{10}=0x43 +serdes_core_rx_polarity_flip_physical{11}=0x43 +serdes_core_rx_polarity_flip_physical{12}=0x43 +serdes_core_rx_polarity_flip_physical{13}=0x43 +serdes_core_rx_polarity_flip_physical{14}=0x43 +serdes_core_rx_polarity_flip_physical{15}=0x43 +serdes_core_rx_polarity_flip_physical{16}=0x43 +serdes_core_tx_polarity_flip_physical{9}=0x7A +serdes_core_tx_polarity_flip_physical{10}=0x7A +serdes_core_tx_polarity_flip_physical{11}=0x7A +serdes_core_tx_polarity_flip_physical{12}=0x7A +serdes_core_tx_polarity_flip_physical{13}=0x7A +serdes_core_tx_polarity_flip_physical{14}=0x7A +serdes_core_tx_polarity_flip_physical{15}=0x7A +serdes_core_tx_polarity_flip_physical{16}=0x7A + +dport_map_port_9=35 +dport_map_port_10=36 +dport_map_port_11=33 +dport_map_port_12=34 +portmap_9=17:100 +portmap_10=19:100 +portmap_11=21:100 +portmap_12=23:100 +phy_chain_rx_lane_map_physical{17.0}=0x01234576 +phy_chain_rx_lane_map_physical{18.0}=0x01234576 +phy_chain_rx_lane_map_physical{19.0}=0x01234576 +phy_chain_rx_lane_map_physical{20.0}=0x01234576 +phy_chain_rx_lane_map_physical{21.0}=0x01234576 +phy_chain_rx_lane_map_physical{22.0}=0x01234576 +phy_chain_rx_lane_map_physical{23.0}=0x01234576 +phy_chain_rx_lane_map_physical{24.0}=0x01234576 +phy_chain_tx_lane_map_physical{17.0}=0x67451032 +phy_chain_tx_lane_map_physical{18.0}=0x67451032 +phy_chain_tx_lane_map_physical{19.0}=0x67451032 +phy_chain_tx_lane_map_physical{20.0}=0x67451032 +phy_chain_tx_lane_map_physical{21.0}=0x67451032 +phy_chain_tx_lane_map_physical{22.0}=0x67451032 +phy_chain_tx_lane_map_physical{23.0}=0x67451032 +phy_chain_tx_lane_map_physical{24.0}=0x67451032 +serdes_core_rx_polarity_flip_physical{17}=0x2E +serdes_core_rx_polarity_flip_physical{18}=0x2E +serdes_core_rx_polarity_flip_physical{19}=0x2E +serdes_core_rx_polarity_flip_physical{20}=0x2E +serdes_core_rx_polarity_flip_physical{21}=0x2E +serdes_core_rx_polarity_flip_physical{22}=0x2E +serdes_core_rx_polarity_flip_physical{23}=0x2E +serdes_core_rx_polarity_flip_physical{24}=0x2E +serdes_core_tx_polarity_flip_physical{17}=0xD5 +serdes_core_tx_polarity_flip_physical{18}=0xD5 +serdes_core_tx_polarity_flip_physical{19}=0xD5 +serdes_core_tx_polarity_flip_physical{20}=0xD5 +serdes_core_tx_polarity_flip_physical{21}=0xD5 +serdes_core_tx_polarity_flip_physical{22}=0xD5 +serdes_core_tx_polarity_flip_physical{23}=0xD5 +serdes_core_tx_polarity_flip_physical{24}=0xD5 + +dport_map_port_13=51 +dport_map_port_14=52 +dport_map_port_15=49 +dport_map_port_16=50 +portmap_13=25:100 +portmap_14=27:100 +portmap_15=29:100 +portmap_16=31:100 +phy_chain_rx_lane_map_physical{25.0}=0x45017263 +phy_chain_rx_lane_map_physical{26.0}=0x45017263 +phy_chain_rx_lane_map_physical{27.0}=0x45017263 +phy_chain_rx_lane_map_physical{28.0}=0x45017263 +phy_chain_rx_lane_map_physical{29.0}=0x45017263 +phy_chain_rx_lane_map_physical{30.0}=0x45017263 +phy_chain_rx_lane_map_physical{31.0}=0x45017263 +phy_chain_rx_lane_map_physical{32.0}=0x45017263 +phy_chain_tx_lane_map_physical{25.0}=0x30126547 +phy_chain_tx_lane_map_physical{26.0}=0x30126547 +phy_chain_tx_lane_map_physical{27.0}=0x30126547 +phy_chain_tx_lane_map_physical{28.0}=0x30126547 +phy_chain_tx_lane_map_physical{29.0}=0x30126547 +phy_chain_tx_lane_map_physical{30.0}=0x30126547 +phy_chain_tx_lane_map_physical{31.0}=0x30126547 +phy_chain_tx_lane_map_physical{32.0}=0x30126547 +serdes_core_rx_polarity_flip_physical{25}=0x91 +serdes_core_rx_polarity_flip_physical{26}=0x91 +serdes_core_rx_polarity_flip_physical{27}=0x91 +serdes_core_rx_polarity_flip_physical{28}=0x91 +serdes_core_rx_polarity_flip_physical{29}=0x91 +serdes_core_rx_polarity_flip_physical{30}=0x91 +serdes_core_rx_polarity_flip_physical{31}=0x91 +serdes_core_rx_polarity_flip_physical{32}=0x91 +serdes_core_tx_polarity_flip_physical{25}=0x57 +serdes_core_tx_polarity_flip_physical{26}=0x57 +serdes_core_tx_polarity_flip_physical{27}=0x57 +serdes_core_tx_polarity_flip_physical{28}=0x57 +serdes_core_tx_polarity_flip_physical{29}=0x57 +serdes_core_tx_polarity_flip_physical{30}=0x57 +serdes_core_tx_polarity_flip_physical{31}=0x57 +serdes_core_tx_polarity_flip_physical{32}=0x57 + +dport_map_port_20=7 +dport_map_port_21=8 +dport_map_port_22=5 +dport_map_port_23=6 +portmap_20=33:100 +portmap_21=35:100 +portmap_22=37:100 +portmap_23=39:100 +phy_chain_rx_lane_map_physical{33.0}=0x56321074 +phy_chain_rx_lane_map_physical{34.0}=0x56321074 +phy_chain_rx_lane_map_physical{35.0}=0x56321074 +phy_chain_rx_lane_map_physical{36.0}=0x56321074 +phy_chain_rx_lane_map_physical{37.0}=0x56321074 +phy_chain_rx_lane_map_physical{38.0}=0x56321074 +phy_chain_rx_lane_map_physical{39.0}=0x56321074 +phy_chain_rx_lane_map_physical{40.0}=0x56321074 +phy_chain_tx_lane_map_physical{33.0}=0x56103247 +phy_chain_tx_lane_map_physical{34.0}=0x56103247 +phy_chain_tx_lane_map_physical{35.0}=0x56103247 +phy_chain_tx_lane_map_physical{36.0}=0x56103247 +phy_chain_tx_lane_map_physical{37.0}=0x56103247 +phy_chain_tx_lane_map_physical{38.0}=0x56103247 +phy_chain_tx_lane_map_physical{39.0}=0x56103247 +phy_chain_tx_lane_map_physical{40.0}=0x56103247 +serdes_core_rx_polarity_flip_physical{33}=0x96 +serdes_core_rx_polarity_flip_physical{34}=0x96 +serdes_core_rx_polarity_flip_physical{35}=0x96 +serdes_core_rx_polarity_flip_physical{36}=0x96 +serdes_core_rx_polarity_flip_physical{37}=0x96 +serdes_core_rx_polarity_flip_physical{38}=0x96 +serdes_core_rx_polarity_flip_physical{39}=0x96 +serdes_core_rx_polarity_flip_physical{40}=0x96 +serdes_core_tx_polarity_flip_physical{33}=0x15 +serdes_core_tx_polarity_flip_physical{34}=0x15 +serdes_core_tx_polarity_flip_physical{35}=0x15 +serdes_core_tx_polarity_flip_physical{36}=0x15 +serdes_core_tx_polarity_flip_physical{37}=0x15 +serdes_core_tx_polarity_flip_physical{38}=0x15 +serdes_core_tx_polarity_flip_physical{39}=0x15 +serdes_core_tx_polarity_flip_physical{40}=0x15 + +dport_map_port_24=23 +dport_map_port_25=24 +dport_map_port_26=21 +dport_map_port_27=22 +portmap_24=41:100 +portmap_25=43:100 +portmap_26=45:100 +portmap_27=47:100 +phy_chain_rx_lane_map_physical{41.0}=0x76543210 +phy_chain_rx_lane_map_physical{42.0}=0x76543210 +phy_chain_rx_lane_map_physical{43.0}=0x76543210 +phy_chain_rx_lane_map_physical{44.0}=0x76543210 +phy_chain_rx_lane_map_physical{45.0}=0x76543210 +phy_chain_rx_lane_map_physical{46.0}=0x76543210 +phy_chain_rx_lane_map_physical{47.0}=0x76543210 +phy_chain_rx_lane_map_physical{48.0}=0x76543210 +phy_chain_tx_lane_map_physical{41.0}=0x30125476 +phy_chain_tx_lane_map_physical{42.0}=0x30125476 +phy_chain_tx_lane_map_physical{43.0}=0x30125476 +phy_chain_tx_lane_map_physical{44.0}=0x30125476 +phy_chain_tx_lane_map_physical{45.0}=0x30125476 +phy_chain_tx_lane_map_physical{46.0}=0x30125476 +phy_chain_tx_lane_map_physical{47.0}=0x30125476 +phy_chain_tx_lane_map_physical{48.0}=0x30125476 +serdes_core_rx_polarity_flip_physical{41}=0x5A +serdes_core_rx_polarity_flip_physical{42}=0x5A +serdes_core_rx_polarity_flip_physical{43}=0x5A +serdes_core_rx_polarity_flip_physical{44}=0x5A +serdes_core_rx_polarity_flip_physical{45}=0x5A +serdes_core_rx_polarity_flip_physical{46}=0x5A +serdes_core_rx_polarity_flip_physical{47}=0x5A +serdes_core_rx_polarity_flip_physical{48}=0x5A +serdes_core_tx_polarity_flip_physical{41}=0x65 +serdes_core_tx_polarity_flip_physical{42}=0x65 +serdes_core_tx_polarity_flip_physical{43}=0x65 +serdes_core_tx_polarity_flip_physical{44}=0x65 +serdes_core_tx_polarity_flip_physical{45}=0x65 +serdes_core_tx_polarity_flip_physical{46}=0x65 +serdes_core_tx_polarity_flip_physical{47}=0x65 +serdes_core_tx_polarity_flip_physical{48}=0x65 + +dport_map_port_28=39 +dport_map_port_29=40 +dport_map_port_30=37 +dport_map_port_31=38 +portmap_28=49:100 +portmap_29=51:100 +portmap_30=53:100 +portmap_31=55:100 +phy_chain_rx_lane_map_physical{49.0}=0x61023547 +phy_chain_rx_lane_map_physical{50.0}=0x61023547 +phy_chain_rx_lane_map_physical{51.0}=0x61023547 +phy_chain_rx_lane_map_physical{52.0}=0x61023547 +phy_chain_rx_lane_map_physical{53.0}=0x61023547 +phy_chain_rx_lane_map_physical{54.0}=0x61023547 +phy_chain_rx_lane_map_physical{55.0}=0x61023547 +phy_chain_rx_lane_map_physical{56.0}=0x61023547 +phy_chain_tx_lane_map_physical{49.0}=0x07541263 +phy_chain_tx_lane_map_physical{50.0}=0x07541263 +phy_chain_tx_lane_map_physical{51.0}=0x07541263 +phy_chain_tx_lane_map_physical{52.0}=0x07541263 +phy_chain_tx_lane_map_physical{53.0}=0x07541263 +phy_chain_tx_lane_map_physical{54.0}=0x07541263 +phy_chain_tx_lane_map_physical{55.0}=0x07541263 +phy_chain_tx_lane_map_physical{56.0}=0x07541263 +serdes_core_rx_polarity_flip_physical{49}=0x41 +serdes_core_rx_polarity_flip_physical{50}=0x41 +serdes_core_rx_polarity_flip_physical{51}=0x41 +serdes_core_rx_polarity_flip_physical{52}=0x41 +serdes_core_rx_polarity_flip_physical{53}=0x41 +serdes_core_rx_polarity_flip_physical{54}=0x41 +serdes_core_rx_polarity_flip_physical{55}=0x41 +serdes_core_rx_polarity_flip_physical{56}=0x41 +serdes_core_tx_polarity_flip_physical{49}=0x99 +serdes_core_tx_polarity_flip_physical{50}=0x99 +serdes_core_tx_polarity_flip_physical{51}=0x99 +serdes_core_tx_polarity_flip_physical{52}=0x99 +serdes_core_tx_polarity_flip_physical{53}=0x99 +serdes_core_tx_polarity_flip_physical{54}=0x99 +serdes_core_tx_polarity_flip_physical{55}=0x99 +serdes_core_tx_polarity_flip_physical{56}=0x99 + +dport_map_port_32=55 +dport_map_port_33=56 +dport_map_port_34=53 +dport_map_port_35=54 +portmap_32=57:100 +portmap_33=59:100 +portmap_34=61:100 +portmap_35=63:100 +phy_chain_rx_lane_map_physical{57.0}=0x45601273 +phy_chain_rx_lane_map_physical{58.0}=0x45601273 +phy_chain_rx_lane_map_physical{59.0}=0x45601273 +phy_chain_rx_lane_map_physical{60.0}=0x45601273 +phy_chain_rx_lane_map_physical{61.0}=0x45601273 +phy_chain_rx_lane_map_physical{62.0}=0x45601273 +phy_chain_rx_lane_map_physical{63.0}=0x45601273 +phy_chain_rx_lane_map_physical{64.0}=0x45601273 +phy_chain_tx_lane_map_physical{57.0}=0x76231045 +phy_chain_tx_lane_map_physical{58.0}=0x76231045 +phy_chain_tx_lane_map_physical{59.0}=0x76231045 +phy_chain_tx_lane_map_physical{60.0}=0x76231045 +phy_chain_tx_lane_map_physical{61.0}=0x76231045 +phy_chain_tx_lane_map_physical{62.0}=0x76231045 +phy_chain_tx_lane_map_physical{63.0}=0x76231045 +phy_chain_tx_lane_map_physical{64.0}=0x76231045 +serdes_core_rx_polarity_flip_physical{57}=0x49 +serdes_core_rx_polarity_flip_physical{58}=0x49 +serdes_core_rx_polarity_flip_physical{59}=0x49 +serdes_core_rx_polarity_flip_physical{60}=0x49 +serdes_core_rx_polarity_flip_physical{61}=0x49 +serdes_core_rx_polarity_flip_physical{62}=0x49 +serdes_core_rx_polarity_flip_physical{63}=0x49 +serdes_core_rx_polarity_flip_physical{64}=0x49 +serdes_core_tx_polarity_flip_physical{57}=0x25 +serdes_core_tx_polarity_flip_physical{58}=0x25 +serdes_core_tx_polarity_flip_physical{59}=0x25 +serdes_core_tx_polarity_flip_physical{60}=0x25 +serdes_core_tx_polarity_flip_physical{61}=0x25 +serdes_core_tx_polarity_flip_physical{62}=0x25 +serdes_core_tx_polarity_flip_physical{63}=0x25 +serdes_core_tx_polarity_flip_physical{64}=0x25 + +dport_map_port_40=11 +dport_map_port_41=12 +dport_map_port_42=9 +dport_map_port_43=10 +portmap_40=65:100 +portmap_41=67:100 +portmap_42=69:100 +portmap_43=71:100 +phy_chain_rx_lane_map_physical{65.0}=0x73210645 +phy_chain_rx_lane_map_physical{66.0}=0x73210645 +phy_chain_rx_lane_map_physical{67.0}=0x73210645 +phy_chain_rx_lane_map_physical{68.0}=0x73210645 +phy_chain_rx_lane_map_physical{69.0}=0x73210645 +phy_chain_rx_lane_map_physical{70.0}=0x73210645 +phy_chain_rx_lane_map_physical{71.0}=0x73210645 +phy_chain_rx_lane_map_physical{72.0}=0x73210645 +phy_chain_tx_lane_map_physical{65.0}=0x45213076 +phy_chain_tx_lane_map_physical{66.0}=0x45213076 +phy_chain_tx_lane_map_physical{67.0}=0x45213076 +phy_chain_tx_lane_map_physical{68.0}=0x45213076 +phy_chain_tx_lane_map_physical{69.0}=0x45213076 +phy_chain_tx_lane_map_physical{70.0}=0x45213076 +phy_chain_tx_lane_map_physical{71.0}=0x45213076 +phy_chain_tx_lane_map_physical{72.0}=0x45213076 +serdes_core_rx_polarity_flip_physical{65}=0xFF +serdes_core_rx_polarity_flip_physical{66}=0xFF +serdes_core_rx_polarity_flip_physical{67}=0xFF +serdes_core_rx_polarity_flip_physical{68}=0xFF +serdes_core_rx_polarity_flip_physical{69}=0xFF +serdes_core_rx_polarity_flip_physical{70}=0xFF +serdes_core_rx_polarity_flip_physical{71}=0xFF +serdes_core_rx_polarity_flip_physical{72}=0xFF +serdes_core_tx_polarity_flip_physical{65}=0x12 +serdes_core_tx_polarity_flip_physical{66}=0x12 +serdes_core_tx_polarity_flip_physical{67}=0x12 +serdes_core_tx_polarity_flip_physical{68}=0x12 +serdes_core_tx_polarity_flip_physical{69}=0x12 +serdes_core_tx_polarity_flip_physical{70}=0x12 +serdes_core_tx_polarity_flip_physical{71}=0x12 +serdes_core_tx_polarity_flip_physical{72}=0x12 + +dport_map_port_44=27 +dport_map_port_45=28 +dport_map_port_46=25 +dport_map_port_47=26 +portmap_44=73:100 +portmap_45=75:100 +portmap_46=77:100 +portmap_47=79:100 +phy_chain_rx_lane_map_physical{73.0}=0x67543201 +phy_chain_rx_lane_map_physical{74.0}=0x67543201 +phy_chain_rx_lane_map_physical{75.0}=0x67543201 +phy_chain_rx_lane_map_physical{76.0}=0x67543201 +phy_chain_rx_lane_map_physical{77.0}=0x67543201 +phy_chain_rx_lane_map_physical{78.0}=0x67543201 +phy_chain_rx_lane_map_physical{79.0}=0x67543201 +phy_chain_rx_lane_map_physical{80.0}=0x67543201 +phy_chain_tx_lane_map_physical{73.0}=0x31025476 +phy_chain_tx_lane_map_physical{74.0}=0x31025476 +phy_chain_tx_lane_map_physical{75.0}=0x31025476 +phy_chain_tx_lane_map_physical{76.0}=0x31025476 +phy_chain_tx_lane_map_physical{77.0}=0x31025476 +phy_chain_tx_lane_map_physical{78.0}=0x31025476 +phy_chain_tx_lane_map_physical{79.0}=0x31025476 +phy_chain_tx_lane_map_physical{80.0}=0x31025476 +serdes_core_rx_polarity_flip_physical{73}=0x1A +serdes_core_rx_polarity_flip_physical{74}=0x1A +serdes_core_rx_polarity_flip_physical{75}=0x1A +serdes_core_rx_polarity_flip_physical{76}=0x1A +serdes_core_rx_polarity_flip_physical{77}=0x1A +serdes_core_rx_polarity_flip_physical{78}=0x1A +serdes_core_rx_polarity_flip_physical{79}=0x1A +serdes_core_rx_polarity_flip_physical{80}=0x1A +serdes_core_tx_polarity_flip_physical{73}=0xFA +serdes_core_tx_polarity_flip_physical{74}=0xFA +serdes_core_tx_polarity_flip_physical{75}=0xFA +serdes_core_tx_polarity_flip_physical{76}=0xFA +serdes_core_tx_polarity_flip_physical{77}=0xFA +serdes_core_tx_polarity_flip_physical{78}=0xFA +serdes_core_tx_polarity_flip_physical{79}=0xFA +serdes_core_tx_polarity_flip_physical{80}=0xFA + +dport_map_port_48=43 +dport_map_port_49=44 +dport_map_port_50=41 +dport_map_port_51=42 +portmap_48=81:100 +portmap_49=83:100 +portmap_50=85:100 +portmap_51=87:100 +phy_chain_rx_lane_map_physical{81.0}=0x70124356 +phy_chain_rx_lane_map_physical{82.0}=0x70124356 +phy_chain_rx_lane_map_physical{83.0}=0x70124356 +phy_chain_rx_lane_map_physical{84.0}=0x70124356 +phy_chain_rx_lane_map_physical{85.0}=0x70124356 +phy_chain_rx_lane_map_physical{86.0}=0x70124356 +phy_chain_rx_lane_map_physical{87.0}=0x70124356 +phy_chain_rx_lane_map_physical{88.0}=0x70124356 +phy_chain_tx_lane_map_physical{81.0}=0x67541203 +phy_chain_tx_lane_map_physical{82.0}=0x67541203 +phy_chain_tx_lane_map_physical{83.0}=0x67541203 +phy_chain_tx_lane_map_physical{84.0}=0x67541203 +phy_chain_tx_lane_map_physical{85.0}=0x67541203 +phy_chain_tx_lane_map_physical{86.0}=0x67541203 +phy_chain_tx_lane_map_physical{87.0}=0x67541203 +phy_chain_tx_lane_map_physical{88.0}=0x67541203 +serdes_core_rx_polarity_flip_physical{81}=0x6D +serdes_core_rx_polarity_flip_physical{82}=0x6D +serdes_core_rx_polarity_flip_physical{83}=0x6D +serdes_core_rx_polarity_flip_physical{84}=0x6D +serdes_core_rx_polarity_flip_physical{85}=0x6D +serdes_core_rx_polarity_flip_physical{86}=0x6D +serdes_core_rx_polarity_flip_physical{87}=0x6D +serdes_core_rx_polarity_flip_physical{88}=0x6D +serdes_core_tx_polarity_flip_physical{81}=0xE4 +serdes_core_tx_polarity_flip_physical{82}=0xE4 +serdes_core_tx_polarity_flip_physical{83}=0xE4 +serdes_core_tx_polarity_flip_physical{84}=0xE4 +serdes_core_tx_polarity_flip_physical{85}=0xE4 +serdes_core_tx_polarity_flip_physical{86}=0xE4 +serdes_core_tx_polarity_flip_physical{87}=0xE4 +serdes_core_tx_polarity_flip_physical{88}=0xE4 + +dport_map_port_52=59 +dport_map_port_53=60 +dport_map_port_54=57 +dport_map_port_55=58 +portmap_52=89:100 +portmap_53=91:100 +portmap_54=93:100 +portmap_55=95:100 +phy_chain_rx_lane_map_physical{89.0}=0x45017263 +phy_chain_rx_lane_map_physical{90.0}=0x45017263 +phy_chain_rx_lane_map_physical{91.0}=0x45017263 +phy_chain_rx_lane_map_physical{92.0}=0x45017263 +phy_chain_rx_lane_map_physical{93.0}=0x45017263 +phy_chain_rx_lane_map_physical{94.0}=0x45017263 +phy_chain_rx_lane_map_physical{95.0}=0x45017263 +phy_chain_rx_lane_map_physical{96.0}=0x45017263 +phy_chain_tx_lane_map_physical{89.0}=0x62310457 +phy_chain_tx_lane_map_physical{90.0}=0x62310457 +phy_chain_tx_lane_map_physical{91.0}=0x62310457 +phy_chain_tx_lane_map_physical{92.0}=0x62310457 +phy_chain_tx_lane_map_physical{93.0}=0x62310457 +phy_chain_tx_lane_map_physical{94.0}=0x62310457 +phy_chain_tx_lane_map_physical{95.0}=0x62310457 +phy_chain_tx_lane_map_physical{96.0}=0x62310457 +serdes_core_rx_polarity_flip_physical{89}=0xEC +serdes_core_rx_polarity_flip_physical{90}=0xEC +serdes_core_rx_polarity_flip_physical{91}=0xEC +serdes_core_rx_polarity_flip_physical{92}=0xEC +serdes_core_rx_polarity_flip_physical{93}=0xEC +serdes_core_rx_polarity_flip_physical{94}=0xEC +serdes_core_rx_polarity_flip_physical{95}=0xEC +serdes_core_rx_polarity_flip_physical{96}=0xEC +serdes_core_tx_polarity_flip_physical{89}=0x35 +serdes_core_tx_polarity_flip_physical{90}=0x35 +serdes_core_tx_polarity_flip_physical{91}=0x35 +serdes_core_tx_polarity_flip_physical{92}=0x35 +serdes_core_tx_polarity_flip_physical{93}=0x35 +serdes_core_tx_polarity_flip_physical{94}=0x35 +serdes_core_tx_polarity_flip_physical{95}=0x35 +serdes_core_tx_polarity_flip_physical{96}=0x35 + +dport_map_port_60=15 +dport_map_port_61=16 +dport_map_port_62=13 +dport_map_port_63=14 +portmap_60=97:100 +portmap_61=99:100 +portmap_62=101:100 +portmap_63=103:100 +phy_chain_rx_lane_map_physical{97.0}=0x10234567 +phy_chain_rx_lane_map_physical{98.0}=0x10234567 +phy_chain_rx_lane_map_physical{99.0}=0x10234567 +phy_chain_rx_lane_map_physical{100.0}=0x10234567 +phy_chain_rx_lane_map_physical{101.0}=0x10234567 +phy_chain_rx_lane_map_physical{102.0}=0x10234567 +phy_chain_rx_lane_map_physical{103.0}=0x10234567 +phy_chain_rx_lane_map_physical{104.0}=0x10234567 +phy_chain_tx_lane_map_physical{97.0}=0x75462103 +phy_chain_tx_lane_map_physical{98.0}=0x75462103 +phy_chain_tx_lane_map_physical{99.0}=0x75462103 +phy_chain_tx_lane_map_physical{100.0}=0x75462103 +phy_chain_tx_lane_map_physical{101.0}=0x75462103 +phy_chain_tx_lane_map_physical{102.0}=0x75462103 +phy_chain_tx_lane_map_physical{103.0}=0x75462103 +phy_chain_tx_lane_map_physical{104.0}=0x75462103 +serdes_core_rx_polarity_flip_physical{97}=0x65 +serdes_core_rx_polarity_flip_physical{98}=0x65 +serdes_core_rx_polarity_flip_physical{99}=0x65 +serdes_core_rx_polarity_flip_physical{100}=0x65 +serdes_core_rx_polarity_flip_physical{101}=0x65 +serdes_core_rx_polarity_flip_physical{102}=0x65 +serdes_core_rx_polarity_flip_physical{103}=0x65 +serdes_core_rx_polarity_flip_physical{104}=0x65 +serdes_core_tx_polarity_flip_physical{97}=0xDD +serdes_core_tx_polarity_flip_physical{98}=0xDD +serdes_core_tx_polarity_flip_physical{99}=0xDD +serdes_core_tx_polarity_flip_physical{100}=0xDD +serdes_core_tx_polarity_flip_physical{101}=0xDD +serdes_core_tx_polarity_flip_physical{102}=0xDD +serdes_core_tx_polarity_flip_physical{103}=0xDD +serdes_core_tx_polarity_flip_physical{104}=0xDD + +dport_map_port_64=31 +dport_map_port_65=32 +dport_map_port_66=29 +dport_map_port_67=30 +portmap_64=105:100 +portmap_65=107:100 +portmap_66=109:100 +portmap_67=111:100 +phy_chain_rx_lane_map_physical{105.0}=0x32106745 +phy_chain_rx_lane_map_physical{106.0}=0x32106745 +phy_chain_rx_lane_map_physical{107.0}=0x32106745 +phy_chain_rx_lane_map_physical{108.0}=0x32106745 +phy_chain_rx_lane_map_physical{109.0}=0x32106745 +phy_chain_rx_lane_map_physical{110.0}=0x32106745 +phy_chain_rx_lane_map_physical{111.0}=0x32106745 +phy_chain_rx_lane_map_physical{112.0}=0x32106745 +phy_chain_tx_lane_map_physical{105.0}=0x23015746 +phy_chain_tx_lane_map_physical{106.0}=0x23015746 +phy_chain_tx_lane_map_physical{107.0}=0x23015746 +phy_chain_tx_lane_map_physical{108.0}=0x23015746 +phy_chain_tx_lane_map_physical{109.0}=0x23015746 +phy_chain_tx_lane_map_physical{110.0}=0x23015746 +phy_chain_tx_lane_map_physical{111.0}=0x23015746 +phy_chain_tx_lane_map_physical{112.0}=0x23015746 +serdes_core_rx_polarity_flip_physical{105}=0xDB +serdes_core_rx_polarity_flip_physical{106}=0xDB +serdes_core_rx_polarity_flip_physical{107}=0xDB +serdes_core_rx_polarity_flip_physical{108}=0xDB +serdes_core_rx_polarity_flip_physical{109}=0xDB +serdes_core_rx_polarity_flip_physical{110}=0xDB +serdes_core_rx_polarity_flip_physical{111}=0xDB +serdes_core_rx_polarity_flip_physical{112}=0xDB +serdes_core_tx_polarity_flip_physical{105}=0xDC +serdes_core_tx_polarity_flip_physical{106}=0xDC +serdes_core_tx_polarity_flip_physical{107}=0xDC +serdes_core_tx_polarity_flip_physical{108}=0xDC +serdes_core_tx_polarity_flip_physical{109}=0xDC +serdes_core_tx_polarity_flip_physical{110}=0xDC +serdes_core_tx_polarity_flip_physical{111}=0xDC +serdes_core_tx_polarity_flip_physical{112}=0xDC + +dport_map_port_68=47 +dport_map_port_69=48 +dport_map_port_70=45 +dport_map_port_71=46 +portmap_68=113:100 +portmap_69=115:100 +portmap_70=117:100 +portmap_71=119:100 +phy_chain_rx_lane_map_physical{113.0}=0x23104567 +phy_chain_rx_lane_map_physical{114.0}=0x23104567 +phy_chain_rx_lane_map_physical{115.0}=0x23104567 +phy_chain_rx_lane_map_physical{116.0}=0x23104567 +phy_chain_rx_lane_map_physical{117.0}=0x23104567 +phy_chain_rx_lane_map_physical{118.0}=0x23104567 +phy_chain_rx_lane_map_physical{119.0}=0x23104567 +phy_chain_rx_lane_map_physical{120.0}=0x23104567 +phy_chain_tx_lane_map_physical{113.0}=0x65704231 +phy_chain_tx_lane_map_physical{114.0}=0x65704231 +phy_chain_tx_lane_map_physical{115.0}=0x65704231 +phy_chain_tx_lane_map_physical{116.0}=0x65704231 +phy_chain_tx_lane_map_physical{117.0}=0x65704231 +phy_chain_tx_lane_map_physical{118.0}=0x65704231 +phy_chain_tx_lane_map_physical{119.0}=0x65704231 +phy_chain_tx_lane_map_physical{120.0}=0x65704231 +serdes_core_rx_polarity_flip_physical{113}=0x22 +serdes_core_rx_polarity_flip_physical{114}=0x22 +serdes_core_rx_polarity_flip_physical{115}=0x22 +serdes_core_rx_polarity_flip_physical{116}=0x22 +serdes_core_rx_polarity_flip_physical{117}=0x22 +serdes_core_rx_polarity_flip_physical{118}=0x22 +serdes_core_rx_polarity_flip_physical{119}=0x22 +serdes_core_rx_polarity_flip_physical{120}=0x22 +serdes_core_tx_polarity_flip_physical{113}=0x20 +serdes_core_tx_polarity_flip_physical{114}=0x20 +serdes_core_tx_polarity_flip_physical{115}=0x20 +serdes_core_tx_polarity_flip_physical{116}=0x20 +serdes_core_tx_polarity_flip_physical{117}=0x20 +serdes_core_tx_polarity_flip_physical{118}=0x20 +serdes_core_tx_polarity_flip_physical{119}=0x20 +serdes_core_tx_polarity_flip_physical{120}=0x20 + +dport_map_port_72=63 +dport_map_port_73=64 +dport_map_port_74=61 +dport_map_port_75=62 +portmap_72=121:100 +portmap_73=123:100 +portmap_74=125:100 +portmap_75=127:100 +phy_chain_rx_lane_map_physical{121.0}=0x32145670 +phy_chain_rx_lane_map_physical{122.0}=0x32145670 +phy_chain_rx_lane_map_physical{123.0}=0x32145670 +phy_chain_rx_lane_map_physical{124.0}=0x32145670 +phy_chain_rx_lane_map_physical{125.0}=0x32145670 +phy_chain_rx_lane_map_physical{126.0}=0x32145670 +phy_chain_rx_lane_map_physical{127.0}=0x32145670 +phy_chain_rx_lane_map_physical{128.0}=0x32145670 +phy_chain_tx_lane_map_physical{121.0}=0x15764023 +phy_chain_tx_lane_map_physical{122.0}=0x15764023 +phy_chain_tx_lane_map_physical{123.0}=0x15764023 +phy_chain_tx_lane_map_physical{124.0}=0x15764023 +phy_chain_tx_lane_map_physical{125.0}=0x15764023 +phy_chain_tx_lane_map_physical{126.0}=0x15764023 +phy_chain_tx_lane_map_physical{127.0}=0x15764023 +phy_chain_tx_lane_map_physical{128.0}=0x15764023 +serdes_core_rx_polarity_flip_physical{121}=0xB4 +serdes_core_rx_polarity_flip_physical{122}=0xB4 +serdes_core_rx_polarity_flip_physical{123}=0xB4 +serdes_core_rx_polarity_flip_physical{124}=0xB4 +serdes_core_rx_polarity_flip_physical{125}=0xB4 +serdes_core_rx_polarity_flip_physical{126}=0xB4 +serdes_core_rx_polarity_flip_physical{127}=0xB4 +serdes_core_rx_polarity_flip_physical{128}=0xB4 +serdes_core_tx_polarity_flip_physical{121}=0x19 +serdes_core_tx_polarity_flip_physical{122}=0x19 +serdes_core_tx_polarity_flip_physical{123}=0x19 +serdes_core_tx_polarity_flip_physical{124}=0x19 +serdes_core_tx_polarity_flip_physical{125}=0x19 +serdes_core_tx_polarity_flip_physical{126}=0x19 +serdes_core_tx_polarity_flip_physical{127}=0x19 +serdes_core_tx_polarity_flip_physical{128}=0x19 + +dport_map_port_80=67 +dport_map_port_81=68 +dport_map_port_82=65 +dport_map_port_83=66 +portmap_80=129:100 +portmap_81=131:100 +portmap_82=133:100 +portmap_83=135:100 +phy_chain_rx_lane_map_physical{129.0}=0x07654123 +phy_chain_rx_lane_map_physical{130.0}=0x07654123 +phy_chain_rx_lane_map_physical{131.0}=0x07654123 +phy_chain_rx_lane_map_physical{132.0}=0x07654123 +phy_chain_rx_lane_map_physical{133.0}=0x07654123 +phy_chain_rx_lane_map_physical{134.0}=0x07654123 +phy_chain_rx_lane_map_physical{135.0}=0x07654123 +phy_chain_rx_lane_map_physical{136.0}=0x07654123 +phy_chain_tx_lane_map_physical{129.0}=0x31204675 +phy_chain_tx_lane_map_physical{130.0}=0x31204675 +phy_chain_tx_lane_map_physical{131.0}=0x31204675 +phy_chain_tx_lane_map_physical{132.0}=0x31204675 +phy_chain_tx_lane_map_physical{133.0}=0x31204675 +phy_chain_tx_lane_map_physical{134.0}=0x31204675 +phy_chain_tx_lane_map_physical{135.0}=0x31204675 +phy_chain_tx_lane_map_physical{136.0}=0x31204675 +serdes_core_rx_polarity_flip_physical{129}=0xDA +serdes_core_rx_polarity_flip_physical{130}=0xDA +serdes_core_rx_polarity_flip_physical{131}=0xDA +serdes_core_rx_polarity_flip_physical{132}=0xDA +serdes_core_rx_polarity_flip_physical{133}=0xDA +serdes_core_rx_polarity_flip_physical{134}=0xDA +serdes_core_rx_polarity_flip_physical{135}=0xDA +serdes_core_rx_polarity_flip_physical{136}=0xDA +serdes_core_tx_polarity_flip_physical{129}=0x67 +serdes_core_tx_polarity_flip_physical{130}=0x67 +serdes_core_tx_polarity_flip_physical{131}=0x67 +serdes_core_tx_polarity_flip_physical{132}=0x67 +serdes_core_tx_polarity_flip_physical{133}=0x67 +serdes_core_tx_polarity_flip_physical{134}=0x67 +serdes_core_tx_polarity_flip_physical{135}=0x67 +serdes_core_tx_polarity_flip_physical{136}=0x67 + +dport_map_port_84=83 +dport_map_port_85=84 +dport_map_port_86=81 +dport_map_port_87=82 +portmap_84=137:100 +portmap_85=139:100 +portmap_86=141:100 +portmap_87=143:100 +phy_chain_rx_lane_map_physical{137.0}=0x65432107 +phy_chain_rx_lane_map_physical{138.0}=0x65432107 +phy_chain_rx_lane_map_physical{139.0}=0x65432107 +phy_chain_rx_lane_map_physical{140.0}=0x65432107 +phy_chain_rx_lane_map_physical{141.0}=0x65432107 +phy_chain_rx_lane_map_physical{142.0}=0x65432107 +phy_chain_rx_lane_map_physical{143.0}=0x65432107 +phy_chain_rx_lane_map_physical{144.0}=0x65432107 +phy_chain_tx_lane_map_physical{137.0}=0x32140756 +phy_chain_tx_lane_map_physical{138.0}=0x32140756 +phy_chain_tx_lane_map_physical{139.0}=0x32140756 +phy_chain_tx_lane_map_physical{140.0}=0x32140756 +phy_chain_tx_lane_map_physical{141.0}=0x32140756 +phy_chain_tx_lane_map_physical{142.0}=0x32140756 +phy_chain_tx_lane_map_physical{143.0}=0x32140756 +phy_chain_tx_lane_map_physical{144.0}=0x32140756 +serdes_core_rx_polarity_flip_physical{137}=0x68 +serdes_core_rx_polarity_flip_physical{138}=0x68 +serdes_core_rx_polarity_flip_physical{139}=0x68 +serdes_core_rx_polarity_flip_physical{140}=0x68 +serdes_core_rx_polarity_flip_physical{141}=0x68 +serdes_core_rx_polarity_flip_physical{142}=0x68 +serdes_core_rx_polarity_flip_physical{143}=0x68 +serdes_core_rx_polarity_flip_physical{144}=0x68 +serdes_core_tx_polarity_flip_physical{137}=0x2C +serdes_core_tx_polarity_flip_physical{138}=0x2C +serdes_core_tx_polarity_flip_physical{139}=0x2C +serdes_core_tx_polarity_flip_physical{140}=0x2C +serdes_core_tx_polarity_flip_physical{141}=0x2C +serdes_core_tx_polarity_flip_physical{142}=0x2C +serdes_core_tx_polarity_flip_physical{143}=0x2C +serdes_core_tx_polarity_flip_physical{144}=0x2C + +dport_map_port_88=99 +dport_map_port_89=100 +dport_map_port_90=97 +dport_map_port_91=98 +portmap_88=145:100 +portmap_89=147:100 +portmap_90=149:100 +portmap_91=151:100 +phy_chain_rx_lane_map_physical{145.0}=0x02145673 +phy_chain_rx_lane_map_physical{146.0}=0x02145673 +phy_chain_rx_lane_map_physical{147.0}=0x02145673 +phy_chain_rx_lane_map_physical{148.0}=0x02145673 +phy_chain_rx_lane_map_physical{149.0}=0x02145673 +phy_chain_rx_lane_map_physical{150.0}=0x02145673 +phy_chain_rx_lane_map_physical{151.0}=0x02145673 +phy_chain_rx_lane_map_physical{152.0}=0x02145673 +phy_chain_tx_lane_map_physical{145.0}=0x17654023 +phy_chain_tx_lane_map_physical{146.0}=0x17654023 +phy_chain_tx_lane_map_physical{147.0}=0x17654023 +phy_chain_tx_lane_map_physical{148.0}=0x17654023 +phy_chain_tx_lane_map_physical{149.0}=0x17654023 +phy_chain_tx_lane_map_physical{150.0}=0x17654023 +phy_chain_tx_lane_map_physical{151.0}=0x17654023 +phy_chain_tx_lane_map_physical{152.0}=0x17654023 +serdes_core_rx_polarity_flip_physical{145}=0x9A +serdes_core_rx_polarity_flip_physical{146}=0x9A +serdes_core_rx_polarity_flip_physical{147}=0x9A +serdes_core_rx_polarity_flip_physical{148}=0x9A +serdes_core_rx_polarity_flip_physical{149}=0x9A +serdes_core_rx_polarity_flip_physical{150}=0x9A +serdes_core_rx_polarity_flip_physical{151}=0x9A +serdes_core_rx_polarity_flip_physical{152}=0x9A +serdes_core_tx_polarity_flip_physical{145}=0xD6 +serdes_core_tx_polarity_flip_physical{146}=0xD6 +serdes_core_tx_polarity_flip_physical{147}=0xD6 +serdes_core_tx_polarity_flip_physical{148}=0xD6 +serdes_core_tx_polarity_flip_physical{149}=0xD6 +serdes_core_tx_polarity_flip_physical{150}=0xD6 +serdes_core_tx_polarity_flip_physical{151}=0xD6 +serdes_core_tx_polarity_flip_physical{152}=0xD6 + +dport_map_port_92=115 +dport_map_port_93=116 +dport_map_port_94=113 +dport_map_port_95=114 +portmap_92=153:100 +portmap_93=155:100 +portmap_94=157:100 +portmap_95=159:100 +phy_chain_rx_lane_map_physical{153.0}=0x67451023 +phy_chain_rx_lane_map_physical{154.0}=0x67451023 +phy_chain_rx_lane_map_physical{155.0}=0x67451023 +phy_chain_rx_lane_map_physical{156.0}=0x67451023 +phy_chain_rx_lane_map_physical{157.0}=0x67451023 +phy_chain_rx_lane_map_physical{158.0}=0x67451023 +phy_chain_rx_lane_map_physical{159.0}=0x67451023 +phy_chain_rx_lane_map_physical{160.0}=0x67451023 +phy_chain_tx_lane_map_physical{153.0}=0x13205746 +phy_chain_tx_lane_map_physical{154.0}=0x13205746 +phy_chain_tx_lane_map_physical{155.0}=0x13205746 +phy_chain_tx_lane_map_physical{156.0}=0x13205746 +phy_chain_tx_lane_map_physical{157.0}=0x13205746 +phy_chain_tx_lane_map_physical{158.0}=0x13205746 +phy_chain_tx_lane_map_physical{159.0}=0x13205746 +phy_chain_tx_lane_map_physical{160.0}=0x13205746 +serdes_core_rx_polarity_flip_physical{153}=0xE4 +serdes_core_rx_polarity_flip_physical{154}=0xE4 +serdes_core_rx_polarity_flip_physical{155}=0xE4 +serdes_core_rx_polarity_flip_physical{156}=0xE4 +serdes_core_rx_polarity_flip_physical{157}=0xE4 +serdes_core_rx_polarity_flip_physical{158}=0xE4 +serdes_core_rx_polarity_flip_physical{159}=0xE4 +serdes_core_rx_polarity_flip_physical{160}=0xE4 +serdes_core_tx_polarity_flip_physical{153}=0xCC +serdes_core_tx_polarity_flip_physical{154}=0xCC +serdes_core_tx_polarity_flip_physical{155}=0xCC +serdes_core_tx_polarity_flip_physical{156}=0xCC +serdes_core_tx_polarity_flip_physical{157}=0xCC +serdes_core_tx_polarity_flip_physical{158}=0xCC +serdes_core_tx_polarity_flip_physical{159}=0xCC +serdes_core_tx_polarity_flip_physical{160}=0xCC + +dport_map_port_100=71 +dport_map_port_101=72 +dport_map_port_102=69 +dport_map_port_103=70 +portmap_100=161:100 +portmap_101=163:100 +portmap_102=165:100 +portmap_103=167:100 +phy_chain_rx_lane_map_physical{161.0}=0x54321067 +phy_chain_rx_lane_map_physical{162.0}=0x54321067 +phy_chain_rx_lane_map_physical{163.0}=0x54321067 +phy_chain_rx_lane_map_physical{164.0}=0x54321067 +phy_chain_rx_lane_map_physical{165.0}=0x54321067 +phy_chain_rx_lane_map_physical{166.0}=0x54321067 +phy_chain_rx_lane_map_physical{167.0}=0x54321067 +phy_chain_rx_lane_map_physical{168.0}=0x54321067 +phy_chain_tx_lane_map_physical{161.0}=0x40123765 +phy_chain_tx_lane_map_physical{162.0}=0x40123765 +phy_chain_tx_lane_map_physical{163.0}=0x40123765 +phy_chain_tx_lane_map_physical{164.0}=0x40123765 +phy_chain_tx_lane_map_physical{165.0}=0x40123765 +phy_chain_tx_lane_map_physical{166.0}=0x40123765 +phy_chain_tx_lane_map_physical{167.0}=0x40123765 +phy_chain_tx_lane_map_physical{168.0}=0x40123765 +serdes_core_rx_polarity_flip_physical{161}=0x1B +serdes_core_rx_polarity_flip_physical{162}=0x1B +serdes_core_rx_polarity_flip_physical{163}=0x1B +serdes_core_rx_polarity_flip_physical{164}=0x1B +serdes_core_rx_polarity_flip_physical{165}=0x1B +serdes_core_rx_polarity_flip_physical{166}=0x1B +serdes_core_rx_polarity_flip_physical{167}=0x1B +serdes_core_rx_polarity_flip_physical{168}=0x1B +serdes_core_tx_polarity_flip_physical{161}=0xD5 +serdes_core_tx_polarity_flip_physical{162}=0xD5 +serdes_core_tx_polarity_flip_physical{163}=0xD5 +serdes_core_tx_polarity_flip_physical{164}=0xD5 +serdes_core_tx_polarity_flip_physical{165}=0xD5 +serdes_core_tx_polarity_flip_physical{166}=0xD5 +serdes_core_tx_polarity_flip_physical{167}=0xD5 +serdes_core_tx_polarity_flip_physical{168}=0xD5 + +dport_map_port_104=87 +dport_map_port_105=88 +dport_map_port_106=85 +dport_map_port_107=86 +portmap_104=169:100 +portmap_105=171:100 +portmap_106=173:100 +portmap_107=175:100 +phy_chain_rx_lane_map_physical{169.0}=0x76543210 +phy_chain_rx_lane_map_physical{170.0}=0x76543210 +phy_chain_rx_lane_map_physical{171.0}=0x76543210 +phy_chain_rx_lane_map_physical{172.0}=0x76543210 +phy_chain_rx_lane_map_physical{173.0}=0x76543210 +phy_chain_rx_lane_map_physical{174.0}=0x76543210 +phy_chain_rx_lane_map_physical{175.0}=0x76543210 +phy_chain_rx_lane_map_physical{176.0}=0x76543210 +phy_chain_tx_lane_map_physical{169.0}=0x32046751 +phy_chain_tx_lane_map_physical{170.0}=0x32046751 +phy_chain_tx_lane_map_physical{171.0}=0x32046751 +phy_chain_tx_lane_map_physical{172.0}=0x32046751 +phy_chain_tx_lane_map_physical{173.0}=0x32046751 +phy_chain_tx_lane_map_physical{174.0}=0x32046751 +phy_chain_tx_lane_map_physical{175.0}=0x32046751 +phy_chain_tx_lane_map_physical{176.0}=0x32046751 +serdes_core_rx_polarity_flip_physical{169}=0x53 +serdes_core_rx_polarity_flip_physical{170}=0x53 +serdes_core_rx_polarity_flip_physical{171}=0x53 +serdes_core_rx_polarity_flip_physical{172}=0x53 +serdes_core_rx_polarity_flip_physical{173}=0x53 +serdes_core_rx_polarity_flip_physical{174}=0x53 +serdes_core_rx_polarity_flip_physical{175}=0x53 +serdes_core_rx_polarity_flip_physical{176}=0x53 +serdes_core_tx_polarity_flip_physical{169}=0x19 +serdes_core_tx_polarity_flip_physical{170}=0x19 +serdes_core_tx_polarity_flip_physical{171}=0x19 +serdes_core_tx_polarity_flip_physical{172}=0x19 +serdes_core_tx_polarity_flip_physical{173}=0x19 +serdes_core_tx_polarity_flip_physical{174}=0x19 +serdes_core_tx_polarity_flip_physical{175}=0x19 +serdes_core_tx_polarity_flip_physical{176}=0x19 + +dport_map_port_108=103 +dport_map_port_109=104 +dport_map_port_110=101 +dport_map_port_111=102 +portmap_108=177:100 +portmap_109=179:100 +portmap_110=181:100 +portmap_111=183:100 +phy_chain_rx_lane_map_physical{177.0}=0x30126457 +phy_chain_rx_lane_map_physical{178.0}=0x30126457 +phy_chain_rx_lane_map_physical{179.0}=0x30126457 +phy_chain_rx_lane_map_physical{180.0}=0x30126457 +phy_chain_rx_lane_map_physical{181.0}=0x30126457 +phy_chain_rx_lane_map_physical{182.0}=0x30126457 +phy_chain_rx_lane_map_physical{183.0}=0x30126457 +phy_chain_rx_lane_map_physical{184.0}=0x30126457 +phy_chain_tx_lane_map_physical{177.0}=0x67504123 +phy_chain_tx_lane_map_physical{178.0}=0x67504123 +phy_chain_tx_lane_map_physical{179.0}=0x67504123 +phy_chain_tx_lane_map_physical{180.0}=0x67504123 +phy_chain_tx_lane_map_physical{181.0}=0x67504123 +phy_chain_tx_lane_map_physical{182.0}=0x67504123 +phy_chain_tx_lane_map_physical{183.0}=0x67504123 +phy_chain_tx_lane_map_physical{184.0}=0x67504123 +serdes_core_rx_polarity_flip_physical{177}=0x6F +serdes_core_rx_polarity_flip_physical{178}=0x6F +serdes_core_rx_polarity_flip_physical{179}=0x6F +serdes_core_rx_polarity_flip_physical{180}=0x6F +serdes_core_rx_polarity_flip_physical{181}=0x6F +serdes_core_rx_polarity_flip_physical{182}=0x6F +serdes_core_rx_polarity_flip_physical{183}=0x6F +serdes_core_rx_polarity_flip_physical{184}=0x6F +serdes_core_tx_polarity_flip_physical{177}=0x26 +serdes_core_tx_polarity_flip_physical{178}=0x26 +serdes_core_tx_polarity_flip_physical{179}=0x26 +serdes_core_tx_polarity_flip_physical{180}=0x26 +serdes_core_tx_polarity_flip_physical{181}=0x26 +serdes_core_tx_polarity_flip_physical{182}=0x26 +serdes_core_tx_polarity_flip_physical{183}=0x26 +serdes_core_tx_polarity_flip_physical{184}=0x26 + +dport_map_port_112=119 +dport_map_port_113=120 +dport_map_port_114=117 +dport_map_port_115=118 +portmap_112=185:100 +portmap_113=187:100 +portmap_114=189:100 +portmap_115=191:100 +phy_chain_rx_lane_map_physical{185.0}=0x45601273 +phy_chain_rx_lane_map_physical{186.0}=0x45601273 +phy_chain_rx_lane_map_physical{187.0}=0x45601273 +phy_chain_rx_lane_map_physical{188.0}=0x45601273 +phy_chain_rx_lane_map_physical{189.0}=0x45601273 +phy_chain_rx_lane_map_physical{190.0}=0x45601273 +phy_chain_rx_lane_map_physical{191.0}=0x45601273 +phy_chain_rx_lane_map_physical{192.0}=0x45601273 +phy_chain_tx_lane_map_physical{185.0}=0x15234076 +phy_chain_tx_lane_map_physical{186.0}=0x15234076 +phy_chain_tx_lane_map_physical{187.0}=0x15234076 +phy_chain_tx_lane_map_physical{188.0}=0x15234076 +phy_chain_tx_lane_map_physical{189.0}=0x15234076 +phy_chain_tx_lane_map_physical{190.0}=0x15234076 +phy_chain_tx_lane_map_physical{191.0}=0x15234076 +phy_chain_tx_lane_map_physical{192.0}=0x15234076 +serdes_core_rx_polarity_flip_physical{185}=0x49 +serdes_core_rx_polarity_flip_physical{186}=0x49 +serdes_core_rx_polarity_flip_physical{187}=0x49 +serdes_core_rx_polarity_flip_physical{188}=0x49 +serdes_core_rx_polarity_flip_physical{189}=0x49 +serdes_core_rx_polarity_flip_physical{190}=0x49 +serdes_core_rx_polarity_flip_physical{191}=0x49 +serdes_core_rx_polarity_flip_physical{192}=0x49 +serdes_core_tx_polarity_flip_physical{185}=0xE6 +serdes_core_tx_polarity_flip_physical{186}=0xE6 +serdes_core_tx_polarity_flip_physical{187}=0xE6 +serdes_core_tx_polarity_flip_physical{188}=0xE6 +serdes_core_tx_polarity_flip_physical{189}=0xE6 +serdes_core_tx_polarity_flip_physical{190}=0xE6 +serdes_core_tx_polarity_flip_physical{191}=0xE6 +serdes_core_tx_polarity_flip_physical{192}=0xE6 + +dport_map_port_120=75 +dport_map_port_121=76 +dport_map_port_122=73 +dport_map_port_123=74 +portmap_120=193:100 +portmap_121=195:100 +portmap_122=197:100 +portmap_123=199:100 +phy_chain_rx_lane_map_physical{193.0}=0x54632107 +phy_chain_rx_lane_map_physical{194.0}=0x54632107 +phy_chain_rx_lane_map_physical{195.0}=0x54632107 +phy_chain_rx_lane_map_physical{196.0}=0x54632107 +phy_chain_rx_lane_map_physical{197.0}=0x54632107 +phy_chain_rx_lane_map_physical{198.0}=0x54632107 +phy_chain_rx_lane_map_physical{199.0}=0x54632107 +phy_chain_rx_lane_map_physical{200.0}=0x54632107 +phy_chain_tx_lane_map_physical{193.0}=0x41023567 +phy_chain_tx_lane_map_physical{194.0}=0x41023567 +phy_chain_tx_lane_map_physical{195.0}=0x41023567 +phy_chain_tx_lane_map_physical{196.0}=0x41023567 +phy_chain_tx_lane_map_physical{197.0}=0x41023567 +phy_chain_tx_lane_map_physical{198.0}=0x41023567 +phy_chain_tx_lane_map_physical{199.0}=0x41023567 +phy_chain_tx_lane_map_physical{200.0}=0x41023567 +serdes_core_rx_polarity_flip_physical{193}=0xD5 +serdes_core_rx_polarity_flip_physical{194}=0xD5 +serdes_core_rx_polarity_flip_physical{195}=0xD5 +serdes_core_rx_polarity_flip_physical{196}=0xD5 +serdes_core_rx_polarity_flip_physical{197}=0xD5 +serdes_core_rx_polarity_flip_physical{198}=0xD5 +serdes_core_rx_polarity_flip_physical{199}=0xD5 +serdes_core_rx_polarity_flip_physical{200}=0xD5 +serdes_core_tx_polarity_flip_physical{193}=0x1C +serdes_core_tx_polarity_flip_physical{194}=0x1C +serdes_core_tx_polarity_flip_physical{195}=0x1C +serdes_core_tx_polarity_flip_physical{196}=0x1C +serdes_core_tx_polarity_flip_physical{197}=0x1C +serdes_core_tx_polarity_flip_physical{198}=0x1C +serdes_core_tx_polarity_flip_physical{199}=0x1C +serdes_core_tx_polarity_flip_physical{200}=0x1C + +dport_map_port_124=91 +dport_map_port_125=92 +dport_map_port_126=89 +dport_map_port_127=90 +portmap_124=201:100 +portmap_125=203:100 +portmap_126=205:100 +portmap_127=207:100 +phy_chain_rx_lane_map_physical{201.0}=0x76543201 +phy_chain_rx_lane_map_physical{202.0}=0x76543201 +phy_chain_rx_lane_map_physical{203.0}=0x76543201 +phy_chain_rx_lane_map_physical{204.0}=0x76543201 +phy_chain_rx_lane_map_physical{205.0}=0x76543201 +phy_chain_rx_lane_map_physical{206.0}=0x76543201 +phy_chain_rx_lane_map_physical{207.0}=0x76543201 +phy_chain_rx_lane_map_physical{208.0}=0x76543201 +phy_chain_tx_lane_map_physical{201.0}=0x32046751 +phy_chain_tx_lane_map_physical{202.0}=0x32046751 +phy_chain_tx_lane_map_physical{203.0}=0x32046751 +phy_chain_tx_lane_map_physical{204.0}=0x32046751 +phy_chain_tx_lane_map_physical{205.0}=0x32046751 +phy_chain_tx_lane_map_physical{206.0}=0x32046751 +phy_chain_tx_lane_map_physical{207.0}=0x32046751 +phy_chain_tx_lane_map_physical{208.0}=0x32046751 +serdes_core_rx_polarity_flip_physical{201}=0xDA +serdes_core_rx_polarity_flip_physical{202}=0xDA +serdes_core_rx_polarity_flip_physical{203}=0xDA +serdes_core_rx_polarity_flip_physical{204}=0xDA +serdes_core_rx_polarity_flip_physical{205}=0xDA +serdes_core_rx_polarity_flip_physical{206}=0xDA +serdes_core_rx_polarity_flip_physical{207}=0xDA +serdes_core_rx_polarity_flip_physical{208}=0xDA +serdes_core_tx_polarity_flip_physical{201}=0xE6 +serdes_core_tx_polarity_flip_physical{202}=0xE6 +serdes_core_tx_polarity_flip_physical{203}=0xE6 +serdes_core_tx_polarity_flip_physical{204}=0xE6 +serdes_core_tx_polarity_flip_physical{205}=0xE6 +serdes_core_tx_polarity_flip_physical{206}=0xE6 +serdes_core_tx_polarity_flip_physical{207}=0xE6 +serdes_core_tx_polarity_flip_physical{208}=0xE6 + +dport_map_port_128=107 +dport_map_port_129=108 +dport_map_port_130=105 +dport_map_port_131=106 +portmap_128=209:100 +portmap_129=211:100 +portmap_130=213:100 +portmap_131=215:100 +phy_chain_rx_lane_map_physical{209.0}=0x30124756 +phy_chain_rx_lane_map_physical{210.0}=0x30124756 +phy_chain_rx_lane_map_physical{211.0}=0x30124756 +phy_chain_rx_lane_map_physical{212.0}=0x30124756 +phy_chain_rx_lane_map_physical{213.0}=0x30124756 +phy_chain_rx_lane_map_physical{214.0}=0x30124756 +phy_chain_rx_lane_map_physical{215.0}=0x30124756 +phy_chain_rx_lane_map_physical{216.0}=0x30124756 +phy_chain_tx_lane_map_physical{209.0}=0x67504213 +phy_chain_tx_lane_map_physical{210.0}=0x67504213 +phy_chain_tx_lane_map_physical{211.0}=0x67504213 +phy_chain_tx_lane_map_physical{212.0}=0x67504213 +phy_chain_tx_lane_map_physical{213.0}=0x67504213 +phy_chain_tx_lane_map_physical{214.0}=0x67504213 +phy_chain_tx_lane_map_physical{215.0}=0x67504213 +phy_chain_tx_lane_map_physical{216.0}=0x67504213 +serdes_core_rx_polarity_flip_physical{209}=0xED +serdes_core_rx_polarity_flip_physical{210}=0xED +serdes_core_rx_polarity_flip_physical{211}=0xED +serdes_core_rx_polarity_flip_physical{212}=0xED +serdes_core_rx_polarity_flip_physical{213}=0xED +serdes_core_rx_polarity_flip_physical{214}=0xED +serdes_core_rx_polarity_flip_physical{215}=0xED +serdes_core_rx_polarity_flip_physical{216}=0xED +serdes_core_tx_polarity_flip_physical{209}=0xDF +serdes_core_tx_polarity_flip_physical{210}=0xDF +serdes_core_tx_polarity_flip_physical{211}=0xDF +serdes_core_tx_polarity_flip_physical{212}=0xDF +serdes_core_tx_polarity_flip_physical{213}=0xDF +serdes_core_tx_polarity_flip_physical{214}=0xDF +serdes_core_tx_polarity_flip_physical{215}=0xDF +serdes_core_tx_polarity_flip_physical{216}=0xDF + +dport_map_port_132=123 +dport_map_port_133=124 +dport_map_port_134=121 +dport_map_port_135=122 +portmap_132=217:100 +portmap_133=219:100 +portmap_134=221:100 +portmap_135=223:100 +phy_chain_rx_lane_map_physical{217.0}=0x65401273 +phy_chain_rx_lane_map_physical{218.0}=0x65401273 +phy_chain_rx_lane_map_physical{219.0}=0x65401273 +phy_chain_rx_lane_map_physical{220.0}=0x65401273 +phy_chain_rx_lane_map_physical{221.0}=0x65401273 +phy_chain_rx_lane_map_physical{222.0}=0x65401273 +phy_chain_rx_lane_map_physical{223.0}=0x65401273 +phy_chain_rx_lane_map_physical{224.0}=0x65401273 +phy_chain_tx_lane_map_physical{217.0}=0x13524076 +phy_chain_tx_lane_map_physical{218.0}=0x13524076 +phy_chain_tx_lane_map_physical{219.0}=0x13524076 +phy_chain_tx_lane_map_physical{220.0}=0x13524076 +phy_chain_tx_lane_map_physical{221.0}=0x13524076 +phy_chain_tx_lane_map_physical{222.0}=0x13524076 +phy_chain_tx_lane_map_physical{223.0}=0x13524076 +phy_chain_tx_lane_map_physical{224.0}=0x13524076 +serdes_core_rx_polarity_flip_physical{217}=0xD7 +serdes_core_rx_polarity_flip_physical{218}=0xD7 +serdes_core_rx_polarity_flip_physical{219}=0xD7 +serdes_core_rx_polarity_flip_physical{220}=0xD7 +serdes_core_rx_polarity_flip_physical{221}=0xD7 +serdes_core_rx_polarity_flip_physical{222}=0xD7 +serdes_core_rx_polarity_flip_physical{223}=0xD7 +serdes_core_rx_polarity_flip_physical{224}=0xD7 +serdes_core_tx_polarity_flip_physical{217}=0x49 +serdes_core_tx_polarity_flip_physical{218}=0x49 +serdes_core_tx_polarity_flip_physical{219}=0x49 +serdes_core_tx_polarity_flip_physical{220}=0x49 +serdes_core_tx_polarity_flip_physical{221}=0x49 +serdes_core_tx_polarity_flip_physical{222}=0x49 +serdes_core_tx_polarity_flip_physical{223}=0x49 +serdes_core_tx_polarity_flip_physical{224}=0x49 + +dport_map_port_140=79 +dport_map_port_141=80 +dport_map_port_142=77 +dport_map_port_143=78 +portmap_140=225:100 +portmap_141=227:100 +portmap_142=229:100 +portmap_143=231:100 +phy_chain_rx_lane_map_physical{225.0}=0x21036745 +phy_chain_rx_lane_map_physical{226.0}=0x21036745 +phy_chain_rx_lane_map_physical{227.0}=0x21036745 +phy_chain_rx_lane_map_physical{228.0}=0x21036745 +phy_chain_rx_lane_map_physical{229.0}=0x21036745 +phy_chain_rx_lane_map_physical{230.0}=0x21036745 +phy_chain_rx_lane_map_physical{231.0}=0x21036745 +phy_chain_rx_lane_map_physical{232.0}=0x21036745 +phy_chain_tx_lane_map_physical{225.0}=0x56701234 +phy_chain_tx_lane_map_physical{226.0}=0x56701234 +phy_chain_tx_lane_map_physical{227.0}=0x56701234 +phy_chain_tx_lane_map_physical{228.0}=0x56701234 +phy_chain_tx_lane_map_physical{229.0}=0x56701234 +phy_chain_tx_lane_map_physical{230.0}=0x56701234 +phy_chain_tx_lane_map_physical{231.0}=0x56701234 +phy_chain_tx_lane_map_physical{232.0}=0x56701234 +serdes_core_rx_polarity_flip_physical{225}=0xE5 +serdes_core_rx_polarity_flip_physical{226}=0xE5 +serdes_core_rx_polarity_flip_physical{227}=0xE5 +serdes_core_rx_polarity_flip_physical{228}=0xE5 +serdes_core_rx_polarity_flip_physical{229}=0xE5 +serdes_core_rx_polarity_flip_physical{230}=0xE5 +serdes_core_rx_polarity_flip_physical{231}=0xE5 +serdes_core_rx_polarity_flip_physical{232}=0xE5 +serdes_core_tx_polarity_flip_physical{225}=0x4A +serdes_core_tx_polarity_flip_physical{226}=0x4A +serdes_core_tx_polarity_flip_physical{227}=0x4A +serdes_core_tx_polarity_flip_physical{228}=0x4A +serdes_core_tx_polarity_flip_physical{229}=0x4A +serdes_core_tx_polarity_flip_physical{230}=0x4A +serdes_core_tx_polarity_flip_physical{231}=0x4A +serdes_core_tx_polarity_flip_physical{232}=0x4A + +dport_map_port_144=95 +dport_map_port_145=96 +dport_map_port_146=93 +dport_map_port_147=94 +portmap_144=233:100 +portmap_145=235:100 +portmap_146=237:100 +portmap_147=239:100 +phy_chain_rx_lane_map_physical{233.0}=0x76541230 +phy_chain_rx_lane_map_physical{234.0}=0x76541230 +phy_chain_rx_lane_map_physical{235.0}=0x76541230 +phy_chain_rx_lane_map_physical{236.0}=0x76541230 +phy_chain_rx_lane_map_physical{237.0}=0x76541230 +phy_chain_rx_lane_map_physical{238.0}=0x76541230 +phy_chain_rx_lane_map_physical{239.0}=0x76541230 +phy_chain_rx_lane_map_physical{240.0}=0x76541230 +phy_chain_tx_lane_map_physical{233.0}=0x20314675 +phy_chain_tx_lane_map_physical{234.0}=0x20314675 +phy_chain_tx_lane_map_physical{235.0}=0x20314675 +phy_chain_tx_lane_map_physical{236.0}=0x20314675 +phy_chain_tx_lane_map_physical{237.0}=0x20314675 +phy_chain_tx_lane_map_physical{238.0}=0x20314675 +phy_chain_tx_lane_map_physical{239.0}=0x20314675 +phy_chain_tx_lane_map_physical{240.0}=0x20314675 +serdes_core_rx_polarity_flip_physical{233}=0xC9 +serdes_core_rx_polarity_flip_physical{234}=0xC9 +serdes_core_rx_polarity_flip_physical{235}=0xC9 +serdes_core_rx_polarity_flip_physical{236}=0xC9 +serdes_core_rx_polarity_flip_physical{237}=0xC9 +serdes_core_rx_polarity_flip_physical{238}=0xC9 +serdes_core_rx_polarity_flip_physical{239}=0xC9 +serdes_core_rx_polarity_flip_physical{240}=0xC9 +serdes_core_tx_polarity_flip_physical{233}=0xBD +serdes_core_tx_polarity_flip_physical{234}=0xBD +serdes_core_tx_polarity_flip_physical{235}=0xBD +serdes_core_tx_polarity_flip_physical{236}=0xBD +serdes_core_tx_polarity_flip_physical{237}=0xBD +serdes_core_tx_polarity_flip_physical{238}=0xBD +serdes_core_tx_polarity_flip_physical{239}=0xBD +serdes_core_tx_polarity_flip_physical{240}=0xBD + +dport_map_port_148=111 +dport_map_port_149=112 +dport_map_port_150=109 +dport_map_port_151=110 +portmap_148=241:100 +portmap_149=243:100 +portmap_150=245:100 +portmap_151=247:100 +phy_chain_rx_lane_map_physical{241.0}=0x21036754 +phy_chain_rx_lane_map_physical{242.0}=0x21036754 +phy_chain_rx_lane_map_physical{243.0}=0x21036754 +phy_chain_rx_lane_map_physical{244.0}=0x21036754 +phy_chain_rx_lane_map_physical{245.0}=0x21036754 +phy_chain_rx_lane_map_physical{246.0}=0x21036754 +phy_chain_rx_lane_map_physical{247.0}=0x21036754 +phy_chain_rx_lane_map_physical{248.0}=0x21036754 +phy_chain_tx_lane_map_physical{241.0}=0x56740123 +phy_chain_tx_lane_map_physical{242.0}=0x56740123 +phy_chain_tx_lane_map_physical{243.0}=0x56740123 +phy_chain_tx_lane_map_physical{244.0}=0x56740123 +phy_chain_tx_lane_map_physical{245.0}=0x56740123 +phy_chain_tx_lane_map_physical{246.0}=0x56740123 +phy_chain_tx_lane_map_physical{247.0}=0x56740123 +phy_chain_tx_lane_map_physical{248.0}=0x56740123 +serdes_core_rx_polarity_flip_physical{241}=0x15 +serdes_core_rx_polarity_flip_physical{242}=0x15 +serdes_core_rx_polarity_flip_physical{243}=0x15 +serdes_core_rx_polarity_flip_physical{244}=0x15 +serdes_core_rx_polarity_flip_physical{245}=0x15 +serdes_core_rx_polarity_flip_physical{246}=0x15 +serdes_core_rx_polarity_flip_physical{247}=0x15 +serdes_core_rx_polarity_flip_physical{248}=0x15 +serdes_core_tx_polarity_flip_physical{241}=0xEA +serdes_core_tx_polarity_flip_physical{242}=0xEA +serdes_core_tx_polarity_flip_physical{243}=0xEA +serdes_core_tx_polarity_flip_physical{244}=0xEA +serdes_core_tx_polarity_flip_physical{245}=0xEA +serdes_core_tx_polarity_flip_physical{246}=0xEA +serdes_core_tx_polarity_flip_physical{247}=0xEA +serdes_core_tx_polarity_flip_physical{248}=0xEA + +dport_map_port_152=127 +dport_map_port_153=128 +dport_map_port_154=125 +dport_map_port_155=126 +portmap_152=249:100 +portmap_153=251:100 +portmap_154=253:100 +portmap_155=255:100 +phy_chain_rx_lane_map_physical{249.0}=0x01237654 +phy_chain_rx_lane_map_physical{250.0}=0x01237654 +phy_chain_rx_lane_map_physical{251.0}=0x01237654 +phy_chain_rx_lane_map_physical{252.0}=0x01237654 +phy_chain_rx_lane_map_physical{253.0}=0x01237654 +phy_chain_rx_lane_map_physical{254.0}=0x01237654 +phy_chain_rx_lane_map_physical{255.0}=0x01237654 +phy_chain_rx_lane_map_physical{256.0}=0x01237654 +phy_chain_tx_lane_map_physical{249.0}=0x57601432 +phy_chain_tx_lane_map_physical{250.0}=0x57601432 +phy_chain_tx_lane_map_physical{251.0}=0x57601432 +phy_chain_tx_lane_map_physical{252.0}=0x57601432 +phy_chain_tx_lane_map_physical{253.0}=0x57601432 +phy_chain_tx_lane_map_physical{254.0}=0x57601432 +phy_chain_tx_lane_map_physical{255.0}=0x57601432 +phy_chain_tx_lane_map_physical{256.0}=0x57601432 +serdes_core_rx_polarity_flip_physical{249}=0x2A +serdes_core_rx_polarity_flip_physical{250}=0x2A +serdes_core_rx_polarity_flip_physical{251}=0x2A +serdes_core_rx_polarity_flip_physical{252}=0x2A +serdes_core_rx_polarity_flip_physical{253}=0x2A +serdes_core_rx_polarity_flip_physical{254}=0x2A +serdes_core_rx_polarity_flip_physical{255}=0x2A +serdes_core_rx_polarity_flip_physical{256}=0x2A +serdes_core_tx_polarity_flip_physical{249}=0xDE +serdes_core_tx_polarity_flip_physical{250}=0xDE +serdes_core_tx_polarity_flip_physical{251}=0xDE +serdes_core_tx_polarity_flip_physical{252}=0xDE +serdes_core_tx_polarity_flip_physical{253}=0xDE +serdes_core_tx_polarity_flip_physical{254}=0xDE +serdes_core_tx_polarity_flip_physical{255}=0xDE +serdes_core_tx_polarity_flip_physical{256}=0xDE + +dport_map_port_38=299 +portmap_38=257:10 + +dport_map_port_118=300 +portmap_118=258:10 + +portmap_19=259:10 + +portmap_39=260:10 + +portmap_59=261:10 + +portmap_79=262:10 + +portmap_99=263:10 + +portmap_119=264:10 + +portmap_139=265:10 + +portmap_159=266:10 diff --git a/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/config_16Q_FEC544_EVTB_100G.bcm b/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/config_16Q_FEC544_EVTB_100G.bcm new file mode 100755 index 000000000000..676dcdd89bd1 --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/config_16Q_FEC544_EVTB_100G.bcm @@ -0,0 +1,1469 @@ +pbmp_xport_xe.0=0x3ffffffffffffffffffffffffffffffffffffffe +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 + +init_all_modules=0 +core_clock_frequency=1325 +dpr_clock_frequency=1000 +device_clock_frequency=1325 +port_flex_enable=1 + +l3_alpm_enable=2 +l3_mem_entries=983040 +ipv6_lpm_128b_enable=1 + +#firmware load method, use fast load +load_firmware=0x2 + +serdes_lane_config_dfe=on +serdes_lane_config_media_type=backplane + +port_fec_1=3 +port_fec_2=3 +port_fec_3=3 +port_fec_4=3 +port_fec_5=3 +port_fec_6=3 +port_fec_7=3 +port_fec_8=3 +port_fec_9=3 +port_fec_10=3 +port_fec_11=3 +port_fec_12=3 +port_fec_13=3 +port_fec_14=3 +port_fec_15=3 +port_fec_16=3 +port_fec_20=3 +port_fec_21=3 +port_fec_22=3 +port_fec_23=3 +port_fec_24=3 +port_fec_25=3 +port_fec_26=3 +port_fec_27=3 +port_fec_28=3 +port_fec_29=3 +port_fec_30=3 +port_fec_31=3 +port_fec_32=3 +port_fec_33=3 +port_fec_34=3 +port_fec_35=3 +port_fec_40=3 +port_fec_41=3 +port_fec_42=3 +port_fec_43=3 +port_fec_44=3 +port_fec_45=3 +port_fec_46=3 +port_fec_47=3 +port_fec_48=3 +port_fec_49=3 +port_fec_50=3 +port_fec_51=3 +port_fec_52=3 +port_fec_53=3 +port_fec_54=3 +port_fec_55=3 +port_fec_60=3 +port_fec_61=3 +port_fec_62=3 +port_fec_63=3 +port_fec_64=3 +port_fec_65=3 +port_fec_66=3 +port_fec_67=3 +port_fec_68=3 +port_fec_69=3 +port_fec_70=3 +port_fec_71=3 +port_fec_72=3 +port_fec_73=3 +port_fec_74=3 +port_fec_75=3 +port_fec_80=3 +port_fec_81=3 +port_fec_82=3 +port_fec_83=3 +port_fec_84=3 +port_fec_85=3 +port_fec_86=3 +port_fec_87=3 +port_fec_88=3 +port_fec_89=3 +port_fec_90=3 +port_fec_91=3 +port_fec_92=3 +port_fec_93=3 +port_fec_94=3 +port_fec_95=3 +port_fec_100=3 +port_fec_101=3 +port_fec_102=3 +port_fec_103=3 +port_fec_104=3 +port_fec_105=3 +port_fec_106=3 +port_fec_107=3 +port_fec_108=3 +port_fec_109=3 +port_fec_110=3 +port_fec_111=3 +port_fec_112=3 +port_fec_113=3 +port_fec_114=3 +port_fec_115=3 +port_fec_120=3 +port_fec_121=3 +port_fec_122=3 +port_fec_123=3 +port_fec_124=3 +port_fec_125=3 +port_fec_126=3 +port_fec_127=3 +port_fec_128=3 +port_fec_129=3 +port_fec_130=3 +port_fec_131=3 +port_fec_132=3 +port_fec_133=3 +port_fec_134=3 +port_fec_135=3 +port_fec_140=3 +port_fec_141=3 +port_fec_142=3 +port_fec_143=3 +port_fec_144=3 +port_fec_145=3 +port_fec_146=3 +port_fec_147=3 +port_fec_148=3 +port_fec_149=3 +port_fec_150=3 +port_fec_151=3 +port_fec_152=3 +port_fec_153=3 +port_fec_154=3 +port_fec_155=3 + + +dport_map_port_3=1 +dport_map_port_4=2 +dport_map_port_1=3 +dport_map_port_2=4 +portmap_1=1:100 +portmap_2=3:100 +portmap_3=5:100 +portmap_4=7:100 +phy_chain_rx_lane_map_physical{1.0}=0x01237645 +phy_chain_rx_lane_map_physical{2.0}=0x01237645 +phy_chain_rx_lane_map_physical{3.0}=0x01237645 +phy_chain_rx_lane_map_physical{4.0}=0x01237645 +phy_chain_rx_lane_map_physical{5.0}=0x01237645 +phy_chain_rx_lane_map_physical{6.0}=0x01237645 +phy_chain_rx_lane_map_physical{7.0}=0x01237645 +phy_chain_rx_lane_map_physical{8.0}=0x01237645 +phy_chain_tx_lane_map_physical{1.0}=0x32046751 +phy_chain_tx_lane_map_physical{2.0}=0x32046751 +phy_chain_tx_lane_map_physical{3.0}=0x32046751 +phy_chain_tx_lane_map_physical{4.0}=0x32046751 +phy_chain_tx_lane_map_physical{5.0}=0x32046751 +phy_chain_tx_lane_map_physical{6.0}=0x32046751 +phy_chain_tx_lane_map_physical{7.0}=0x32046751 +phy_chain_tx_lane_map_physical{8.0}=0x32046751 +serdes_core_rx_polarity_flip_physical{1}=0x29 +serdes_core_rx_polarity_flip_physical{2}=0x29 +serdes_core_rx_polarity_flip_physical{3}=0x29 +serdes_core_rx_polarity_flip_physical{4}=0x29 +serdes_core_rx_polarity_flip_physical{5}=0x29 +serdes_core_rx_polarity_flip_physical{6}=0x29 +serdes_core_rx_polarity_flip_physical{7}=0x29 +serdes_core_rx_polarity_flip_physical{8}=0x29 +serdes_core_tx_polarity_flip_physical{1}=0xE7 +serdes_core_tx_polarity_flip_physical{2}=0xE7 +serdes_core_tx_polarity_flip_physical{3}=0xE7 +serdes_core_tx_polarity_flip_physical{4}=0xE7 +serdes_core_tx_polarity_flip_physical{5}=0xE7 +serdes_core_tx_polarity_flip_physical{6}=0xE7 +serdes_core_tx_polarity_flip_physical{7}=0xE7 +serdes_core_tx_polarity_flip_physical{8}=0xE7 + +dport_map_port_7=17 +dport_map_port_8=18 +dport_map_port_5=19 +dport_map_port_6=20 +portmap_5=9:100 +portmap_6=11:100 +portmap_7=13:100 +portmap_8=15:100 +phy_chain_rx_lane_map_physical{9.0}=0x45672103 +phy_chain_rx_lane_map_physical{10.0}=0x45672103 +phy_chain_rx_lane_map_physical{11.0}=0x45672103 +phy_chain_rx_lane_map_physical{12.0}=0x45672103 +phy_chain_rx_lane_map_physical{13.0}=0x45672103 +phy_chain_rx_lane_map_physical{14.0}=0x45672103 +phy_chain_rx_lane_map_physical{15.0}=0x45672103 +phy_chain_rx_lane_map_physical{16.0}=0x45672103 +phy_chain_tx_lane_map_physical{9.0}=0x13240756 +phy_chain_tx_lane_map_physical{10.0}=0x13240756 +phy_chain_tx_lane_map_physical{11.0}=0x13240756 +phy_chain_tx_lane_map_physical{12.0}=0x13240756 +phy_chain_tx_lane_map_physical{13.0}=0x13240756 +phy_chain_tx_lane_map_physical{14.0}=0x13240756 +phy_chain_tx_lane_map_physical{15.0}=0x13240756 +phy_chain_tx_lane_map_physical{16.0}=0x13240756 +serdes_core_rx_polarity_flip_physical{9}=0xA5 +serdes_core_rx_polarity_flip_physical{10}=0xA5 +serdes_core_rx_polarity_flip_physical{11}=0xA5 +serdes_core_rx_polarity_flip_physical{12}=0xA5 +serdes_core_rx_polarity_flip_physical{13}=0xA5 +serdes_core_rx_polarity_flip_physical{14}=0xA5 +serdes_core_rx_polarity_flip_physical{15}=0xA5 +serdes_core_rx_polarity_flip_physical{16}=0xA5 +serdes_core_tx_polarity_flip_physical{9}=0x85 +serdes_core_tx_polarity_flip_physical{10}=0x85 +serdes_core_tx_polarity_flip_physical{11}=0x85 +serdes_core_tx_polarity_flip_physical{12}=0x85 +serdes_core_tx_polarity_flip_physical{13}=0x85 +serdes_core_tx_polarity_flip_physical{14}=0x85 +serdes_core_tx_polarity_flip_physical{15}=0x85 +serdes_core_tx_polarity_flip_physical{16}=0x85 + +dport_map_port_11=33 +dport_map_port_12=34 +dport_map_port_9=35 +dport_map_port_10=36 +portmap_9=17:100 +portmap_10=19:100 +portmap_11=21:100 +portmap_12=23:100 +phy_chain_rx_lane_map_physical{17.0}=0x10237456 +phy_chain_rx_lane_map_physical{18.0}=0x10237456 +phy_chain_rx_lane_map_physical{19.0}=0x10237456 +phy_chain_rx_lane_map_physical{20.0}=0x10237456 +phy_chain_rx_lane_map_physical{21.0}=0x10237456 +phy_chain_rx_lane_map_physical{22.0}=0x10237456 +phy_chain_rx_lane_map_physical{23.0}=0x10237456 +phy_chain_rx_lane_map_physical{24.0}=0x10237456 +phy_chain_tx_lane_map_physical{17.0}=0x67451032 +phy_chain_tx_lane_map_physical{18.0}=0x67451032 +phy_chain_tx_lane_map_physical{19.0}=0x67451032 +phy_chain_tx_lane_map_physical{20.0}=0x67451032 +phy_chain_tx_lane_map_physical{21.0}=0x67451032 +phy_chain_tx_lane_map_physical{22.0}=0x67451032 +phy_chain_tx_lane_map_physical{23.0}=0x67451032 +phy_chain_tx_lane_map_physical{24.0}=0x67451032 +serdes_core_rx_polarity_flip_physical{17}=0x6A +serdes_core_rx_polarity_flip_physical{18}=0x6A +serdes_core_rx_polarity_flip_physical{19}=0x6A +serdes_core_rx_polarity_flip_physical{20}=0x6A +serdes_core_rx_polarity_flip_physical{21}=0x6A +serdes_core_rx_polarity_flip_physical{22}=0x6A +serdes_core_rx_polarity_flip_physical{23}=0x6A +serdes_core_rx_polarity_flip_physical{24}=0x6A +serdes_core_tx_polarity_flip_physical{17}=0x94 +serdes_core_tx_polarity_flip_physical{18}=0x94 +serdes_core_tx_polarity_flip_physical{19}=0x94 +serdes_core_tx_polarity_flip_physical{20}=0x94 +serdes_core_tx_polarity_flip_physical{21}=0x94 +serdes_core_tx_polarity_flip_physical{22}=0x94 +serdes_core_tx_polarity_flip_physical{23}=0x94 +serdes_core_tx_polarity_flip_physical{24}=0x94 + +dport_map_port_15=49 +dport_map_port_16=50 +dport_map_port_13=51 +dport_map_port_14=52 +portmap_13=25:100 +portmap_14=27:100 +portmap_15=29:100 +portmap_16=31:100 +phy_chain_rx_lane_map_physical{25.0}=0x76231504 +phy_chain_rx_lane_map_physical{26.0}=0x76231504 +phy_chain_rx_lane_map_physical{27.0}=0x76231504 +phy_chain_rx_lane_map_physical{28.0}=0x76231504 +phy_chain_rx_lane_map_physical{29.0}=0x76231504 +phy_chain_rx_lane_map_physical{30.0}=0x76231504 +phy_chain_rx_lane_map_physical{31.0}=0x76231504 +phy_chain_rx_lane_map_physical{32.0}=0x76231504 +phy_chain_tx_lane_map_physical{25.0}=0x36012457 +phy_chain_tx_lane_map_physical{26.0}=0x36012457 +phy_chain_tx_lane_map_physical{27.0}=0x36012457 +phy_chain_tx_lane_map_physical{28.0}=0x36012457 +phy_chain_tx_lane_map_physical{29.0}=0x36012457 +phy_chain_tx_lane_map_physical{30.0}=0x36012457 +phy_chain_tx_lane_map_physical{31.0}=0x36012457 +phy_chain_tx_lane_map_physical{32.0}=0x36012457 +serdes_core_rx_polarity_flip_physical{25}=0x9E +serdes_core_rx_polarity_flip_physical{26}=0x9E +serdes_core_rx_polarity_flip_physical{27}=0x9E +serdes_core_rx_polarity_flip_physical{28}=0x9E +serdes_core_rx_polarity_flip_physical{29}=0x9E +serdes_core_rx_polarity_flip_physical{30}=0x9E +serdes_core_rx_polarity_flip_physical{31}=0x9E +serdes_core_rx_polarity_flip_physical{32}=0x9E +serdes_core_tx_polarity_flip_physical{25}=0x5D +serdes_core_tx_polarity_flip_physical{26}=0x5D +serdes_core_tx_polarity_flip_physical{27}=0x5D +serdes_core_tx_polarity_flip_physical{28}=0x5D +serdes_core_tx_polarity_flip_physical{29}=0x5D +serdes_core_tx_polarity_flip_physical{30}=0x5D +serdes_core_tx_polarity_flip_physical{31}=0x5D +serdes_core_tx_polarity_flip_physical{32}=0x5D + +dport_map_port_22=5 +dport_map_port_23=6 +dport_map_port_20=7 +dport_map_port_21=8 +portmap_20=33:100 +portmap_21=35:100 +portmap_22=37:100 +portmap_23=39:100 +phy_chain_rx_lane_map_physical{33.0}=0x56327410 +phy_chain_rx_lane_map_physical{34.0}=0x56327410 +phy_chain_rx_lane_map_physical{35.0}=0x56327410 +phy_chain_rx_lane_map_physical{36.0}=0x56327410 +phy_chain_rx_lane_map_physical{37.0}=0x56327410 +phy_chain_rx_lane_map_physical{38.0}=0x56327410 +phy_chain_rx_lane_map_physical{39.0}=0x56327410 +phy_chain_rx_lane_map_physical{40.0}=0x56327410 +phy_chain_tx_lane_map_physical{33.0}=0x65103247 +phy_chain_tx_lane_map_physical{34.0}=0x65103247 +phy_chain_tx_lane_map_physical{35.0}=0x65103247 +phy_chain_tx_lane_map_physical{36.0}=0x65103247 +phy_chain_tx_lane_map_physical{37.0}=0x65103247 +phy_chain_tx_lane_map_physical{38.0}=0x65103247 +phy_chain_tx_lane_map_physical{39.0}=0x65103247 +phy_chain_tx_lane_map_physical{40.0}=0x65103247 +serdes_core_rx_polarity_flip_physical{33}=0xA9 +serdes_core_rx_polarity_flip_physical{34}=0xA9 +serdes_core_rx_polarity_flip_physical{35}=0xA9 +serdes_core_rx_polarity_flip_physical{36}=0xA9 +serdes_core_rx_polarity_flip_physical{37}=0xA9 +serdes_core_rx_polarity_flip_physical{38}=0xA9 +serdes_core_rx_polarity_flip_physical{39}=0xA9 +serdes_core_rx_polarity_flip_physical{40}=0xA9 +serdes_core_tx_polarity_flip_physical{33}=0xF6 +serdes_core_tx_polarity_flip_physical{34}=0xF6 +serdes_core_tx_polarity_flip_physical{35}=0xF6 +serdes_core_tx_polarity_flip_physical{36}=0xF6 +serdes_core_tx_polarity_flip_physical{37}=0xF6 +serdes_core_tx_polarity_flip_physical{38}=0xF6 +serdes_core_tx_polarity_flip_physical{39}=0xF6 +serdes_core_tx_polarity_flip_physical{40}=0xF6 + +dport_map_port_26=21 +dport_map_port_27=22 +dport_map_port_24=23 +dport_map_port_25=24 +portmap_24=41:100 +portmap_25=43:100 +portmap_26=45:100 +portmap_27=47:100 +phy_chain_rx_lane_map_physical{41.0}=0x76543201 +phy_chain_rx_lane_map_physical{42.0}=0x76543201 +phy_chain_rx_lane_map_physical{43.0}=0x76543201 +phy_chain_rx_lane_map_physical{44.0}=0x76543201 +phy_chain_rx_lane_map_physical{45.0}=0x76543201 +phy_chain_rx_lane_map_physical{46.0}=0x76543201 +phy_chain_rx_lane_map_physical{47.0}=0x76543201 +phy_chain_rx_lane_map_physical{48.0}=0x76543201 +phy_chain_tx_lane_map_physical{41.0}=0x03517426 +phy_chain_tx_lane_map_physical{42.0}=0x03517426 +phy_chain_tx_lane_map_physical{43.0}=0x03517426 +phy_chain_tx_lane_map_physical{44.0}=0x03517426 +phy_chain_tx_lane_map_physical{45.0}=0x03517426 +phy_chain_tx_lane_map_physical{46.0}=0x03517426 +phy_chain_tx_lane_map_physical{47.0}=0x03517426 +phy_chain_tx_lane_map_physical{48.0}=0x03517426 +serdes_core_rx_polarity_flip_physical{41}=0x59 +serdes_core_rx_polarity_flip_physical{42}=0x59 +serdes_core_rx_polarity_flip_physical{43}=0x59 +serdes_core_rx_polarity_flip_physical{44}=0x59 +serdes_core_rx_polarity_flip_physical{45}=0x59 +serdes_core_rx_polarity_flip_physical{46}=0x59 +serdes_core_rx_polarity_flip_physical{47}=0x59 +serdes_core_rx_polarity_flip_physical{48}=0x59 +serdes_core_tx_polarity_flip_physical{41}=0x92 +serdes_core_tx_polarity_flip_physical{42}=0x92 +serdes_core_tx_polarity_flip_physical{43}=0x92 +serdes_core_tx_polarity_flip_physical{44}=0x92 +serdes_core_tx_polarity_flip_physical{45}=0x92 +serdes_core_tx_polarity_flip_physical{46}=0x92 +serdes_core_tx_polarity_flip_physical{47}=0x92 +serdes_core_tx_polarity_flip_physical{48}=0x92 + +dport_map_port_30=37 +dport_map_port_31=38 +dport_map_port_28=39 +dport_map_port_29=40 +portmap_28=49:100 +portmap_29=51:100 +portmap_30=53:100 +portmap_31=55:100 +phy_chain_rx_lane_map_physical{49.0}=0x63724510 +phy_chain_rx_lane_map_physical{50.0}=0x63724510 +phy_chain_rx_lane_map_physical{51.0}=0x63724510 +phy_chain_rx_lane_map_physical{52.0}=0x63724510 +phy_chain_rx_lane_map_physical{53.0}=0x63724510 +phy_chain_rx_lane_map_physical{54.0}=0x63724510 +phy_chain_rx_lane_map_physical{55.0}=0x63724510 +phy_chain_rx_lane_map_physical{56.0}=0x63724510 +phy_chain_tx_lane_map_physical{49.0}=0x67450213 +phy_chain_tx_lane_map_physical{50.0}=0x67450213 +phy_chain_tx_lane_map_physical{51.0}=0x67450213 +phy_chain_tx_lane_map_physical{52.0}=0x67450213 +phy_chain_tx_lane_map_physical{53.0}=0x67450213 +phy_chain_tx_lane_map_physical{54.0}=0x67450213 +phy_chain_tx_lane_map_physical{55.0}=0x67450213 +phy_chain_tx_lane_map_physical{56.0}=0x67450213 +serdes_core_rx_polarity_flip_physical{49}=0x4A +serdes_core_rx_polarity_flip_physical{50}=0x4A +serdes_core_rx_polarity_flip_physical{51}=0x4A +serdes_core_rx_polarity_flip_physical{52}=0x4A +serdes_core_rx_polarity_flip_physical{53}=0x4A +serdes_core_rx_polarity_flip_physical{54}=0x4A +serdes_core_rx_polarity_flip_physical{55}=0x4A +serdes_core_rx_polarity_flip_physical{56}=0x4A +serdes_core_tx_polarity_flip_physical{49}=0xCC +serdes_core_tx_polarity_flip_physical{50}=0xCC +serdes_core_tx_polarity_flip_physical{51}=0xCC +serdes_core_tx_polarity_flip_physical{52}=0xCC +serdes_core_tx_polarity_flip_physical{53}=0xCC +serdes_core_tx_polarity_flip_physical{54}=0xCC +serdes_core_tx_polarity_flip_physical{55}=0xCC +serdes_core_tx_polarity_flip_physical{56}=0xCC + +dport_map_port_34=53 +dport_map_port_35=54 +dport_map_port_32=55 +dport_map_port_33=56 +portmap_32=57:100 +portmap_33=59:100 +portmap_34=61:100 +portmap_35=63:100 +phy_chain_rx_lane_map_physical{57.0}=0x74501623 +phy_chain_rx_lane_map_physical{58.0}=0x74501623 +phy_chain_rx_lane_map_physical{59.0}=0x74501623 +phy_chain_rx_lane_map_physical{60.0}=0x74501623 +phy_chain_rx_lane_map_physical{61.0}=0x74501623 +phy_chain_rx_lane_map_physical{62.0}=0x74501623 +phy_chain_rx_lane_map_physical{63.0}=0x74501623 +phy_chain_rx_lane_map_physical{64.0}=0x74501623 +phy_chain_tx_lane_map_physical{57.0}=0x62731045 +phy_chain_tx_lane_map_physical{58.0}=0x62731045 +phy_chain_tx_lane_map_physical{59.0}=0x62731045 +phy_chain_tx_lane_map_physical{60.0}=0x62731045 +phy_chain_tx_lane_map_physical{61.0}=0x62731045 +phy_chain_tx_lane_map_physical{62.0}=0x62731045 +phy_chain_tx_lane_map_physical{63.0}=0x62731045 +phy_chain_tx_lane_map_physical{64.0}=0x62731045 +serdes_core_rx_polarity_flip_physical{57}=0x42 +serdes_core_rx_polarity_flip_physical{58}=0x42 +serdes_core_rx_polarity_flip_physical{59}=0x42 +serdes_core_rx_polarity_flip_physical{60}=0x42 +serdes_core_rx_polarity_flip_physical{61}=0x42 +serdes_core_rx_polarity_flip_physical{62}=0x42 +serdes_core_rx_polarity_flip_physical{63}=0x42 +serdes_core_rx_polarity_flip_physical{64}=0x42 +serdes_core_tx_polarity_flip_physical{57}=0x3A +serdes_core_tx_polarity_flip_physical{58}=0x3A +serdes_core_tx_polarity_flip_physical{59}=0x3A +serdes_core_tx_polarity_flip_physical{60}=0x3A +serdes_core_tx_polarity_flip_physical{61}=0x3A +serdes_core_tx_polarity_flip_physical{62}=0x3A +serdes_core_tx_polarity_flip_physical{63}=0x3A +serdes_core_tx_polarity_flip_physical{64}=0x3A + +dport_map_port_42=9 +dport_map_port_43=10 +dport_map_port_40=11 +dport_map_port_41=12 +portmap_40=65:100 +portmap_41=67:100 +portmap_42=69:100 +portmap_43=71:100 +phy_chain_rx_lane_map_physical{65.0}=0x73625104 +phy_chain_rx_lane_map_physical{66.0}=0x73625104 +phy_chain_rx_lane_map_physical{67.0}=0x73625104 +phy_chain_rx_lane_map_physical{68.0}=0x73625104 +phy_chain_rx_lane_map_physical{69.0}=0x73625104 +phy_chain_rx_lane_map_physical{70.0}=0x73625104 +phy_chain_rx_lane_map_physical{71.0}=0x73625104 +phy_chain_rx_lane_map_physical{72.0}=0x73625104 +phy_chain_tx_lane_map_physical{65.0}=0x42513076 +phy_chain_tx_lane_map_physical{66.0}=0x42513076 +phy_chain_tx_lane_map_physical{67.0}=0x42513076 +phy_chain_tx_lane_map_physical{68.0}=0x42513076 +phy_chain_tx_lane_map_physical{69.0}=0x42513076 +phy_chain_tx_lane_map_physical{70.0}=0x42513076 +phy_chain_tx_lane_map_physical{71.0}=0x42513076 +phy_chain_tx_lane_map_physical{72.0}=0x42513076 +serdes_core_rx_polarity_flip_physical{65}=0xE5 +serdes_core_rx_polarity_flip_physical{66}=0xE5 +serdes_core_rx_polarity_flip_physical{67}=0xE5 +serdes_core_rx_polarity_flip_physical{68}=0xE5 +serdes_core_rx_polarity_flip_physical{69}=0xE5 +serdes_core_rx_polarity_flip_physical{70}=0xE5 +serdes_core_rx_polarity_flip_physical{71}=0xE5 +serdes_core_rx_polarity_flip_physical{72}=0xE5 +serdes_core_tx_polarity_flip_physical{65}=0x5A +serdes_core_tx_polarity_flip_physical{66}=0x5A +serdes_core_tx_polarity_flip_physical{67}=0x5A +serdes_core_tx_polarity_flip_physical{68}=0x5A +serdes_core_tx_polarity_flip_physical{69}=0x5A +serdes_core_tx_polarity_flip_physical{70}=0x5A +serdes_core_tx_polarity_flip_physical{71}=0x5A +serdes_core_tx_polarity_flip_physical{72}=0x5A + +dport_map_port_46=25 +dport_map_port_47=26 +dport_map_port_44=27 +dport_map_port_45=28 +portmap_44=73:100 +portmap_45=75:100 +portmap_46=77:100 +portmap_47=79:100 +phy_chain_rx_lane_map_physical{73.0}=0x64501723 +phy_chain_rx_lane_map_physical{74.0}=0x64501723 +phy_chain_rx_lane_map_physical{75.0}=0x64501723 +phy_chain_rx_lane_map_physical{76.0}=0x64501723 +phy_chain_rx_lane_map_physical{77.0}=0x64501723 +phy_chain_rx_lane_map_physical{78.0}=0x64501723 +phy_chain_rx_lane_map_physical{79.0}=0x64501723 +phy_chain_rx_lane_map_physical{80.0}=0x64501723 +phy_chain_tx_lane_map_physical{73.0}=0x32015476 +phy_chain_tx_lane_map_physical{74.0}=0x32015476 +phy_chain_tx_lane_map_physical{75.0}=0x32015476 +phy_chain_tx_lane_map_physical{76.0}=0x32015476 +phy_chain_tx_lane_map_physical{77.0}=0x32015476 +phy_chain_tx_lane_map_physical{78.0}=0x32015476 +phy_chain_tx_lane_map_physical{79.0}=0x32015476 +phy_chain_tx_lane_map_physical{80.0}=0x32015476 +serdes_core_rx_polarity_flip_physical{73}=0xB6 +serdes_core_rx_polarity_flip_physical{74}=0xB6 +serdes_core_rx_polarity_flip_physical{75}=0xB6 +serdes_core_rx_polarity_flip_physical{76}=0xB6 +serdes_core_rx_polarity_flip_physical{77}=0xB6 +serdes_core_rx_polarity_flip_physical{78}=0xB6 +serdes_core_rx_polarity_flip_physical{79}=0xB6 +serdes_core_rx_polarity_flip_physical{80}=0xB6 +serdes_core_tx_polarity_flip_physical{73}=0x10 +serdes_core_tx_polarity_flip_physical{74}=0x10 +serdes_core_tx_polarity_flip_physical{75}=0x10 +serdes_core_tx_polarity_flip_physical{76}=0x10 +serdes_core_tx_polarity_flip_physical{77}=0x10 +serdes_core_tx_polarity_flip_physical{78}=0x10 +serdes_core_tx_polarity_flip_physical{79}=0x10 +serdes_core_tx_polarity_flip_physical{80}=0x10 + +dport_map_port_50=41 +dport_map_port_51=42 +dport_map_port_48=43 +dport_map_port_49=44 +portmap_48=81:100 +portmap_49=83:100 +portmap_50=85:100 +portmap_51=87:100 +phy_chain_rx_lane_map_physical{81.0}=0x20134567 +phy_chain_rx_lane_map_physical{82.0}=0x20134567 +phy_chain_rx_lane_map_physical{83.0}=0x20134567 +phy_chain_rx_lane_map_physical{84.0}=0x20134567 +phy_chain_rx_lane_map_physical{85.0}=0x20134567 +phy_chain_rx_lane_map_physical{86.0}=0x20134567 +phy_chain_rx_lane_map_physical{87.0}=0x20134567 +phy_chain_rx_lane_map_physical{88.0}=0x20134567 +phy_chain_tx_lane_map_physical{81.0}=0x67540123 +phy_chain_tx_lane_map_physical{82.0}=0x67540123 +phy_chain_tx_lane_map_physical{83.0}=0x67540123 +phy_chain_tx_lane_map_physical{84.0}=0x67540123 +phy_chain_tx_lane_map_physical{85.0}=0x67540123 +phy_chain_tx_lane_map_physical{86.0}=0x67540123 +phy_chain_tx_lane_map_physical{87.0}=0x67540123 +phy_chain_tx_lane_map_physical{88.0}=0x67540123 +serdes_core_rx_polarity_flip_physical{81}=0xBA +serdes_core_rx_polarity_flip_physical{82}=0xBA +serdes_core_rx_polarity_flip_physical{83}=0xBA +serdes_core_rx_polarity_flip_physical{84}=0xBA +serdes_core_rx_polarity_flip_physical{85}=0xBA +serdes_core_rx_polarity_flip_physical{86}=0xBA +serdes_core_rx_polarity_flip_physical{87}=0xBA +serdes_core_rx_polarity_flip_physical{88}=0xBA +serdes_core_tx_polarity_flip_physical{81}=0xAA +serdes_core_tx_polarity_flip_physical{82}=0xAA +serdes_core_tx_polarity_flip_physical{83}=0xAA +serdes_core_tx_polarity_flip_physical{84}=0xAA +serdes_core_tx_polarity_flip_physical{85}=0xAA +serdes_core_tx_polarity_flip_physical{86}=0xAA +serdes_core_tx_polarity_flip_physical{87}=0xAA +serdes_core_tx_polarity_flip_physical{88}=0xAA + +dport_map_port_54=57 +dport_map_port_55=58 +dport_map_port_52=59 +dport_map_port_53=60 +portmap_52=89:100 +portmap_53=91:100 +portmap_54=93:100 +portmap_55=95:100 +phy_chain_rx_lane_map_physical{89.0}=0x36271504 +phy_chain_rx_lane_map_physical{90.0}=0x36271504 +phy_chain_rx_lane_map_physical{91.0}=0x36271504 +phy_chain_rx_lane_map_physical{92.0}=0x36271504 +phy_chain_rx_lane_map_physical{93.0}=0x36271504 +phy_chain_rx_lane_map_physical{94.0}=0x36271504 +phy_chain_rx_lane_map_physical{95.0}=0x36271504 +phy_chain_rx_lane_map_physical{96.0}=0x36271504 +phy_chain_tx_lane_map_physical{89.0}=0x62413507 +phy_chain_tx_lane_map_physical{90.0}=0x62413507 +phy_chain_tx_lane_map_physical{91.0}=0x62413507 +phy_chain_tx_lane_map_physical{92.0}=0x62413507 +phy_chain_tx_lane_map_physical{93.0}=0x62413507 +phy_chain_tx_lane_map_physical{94.0}=0x62413507 +phy_chain_tx_lane_map_physical{95.0}=0x62413507 +phy_chain_tx_lane_map_physical{96.0}=0x62413507 +serdes_core_rx_polarity_flip_physical{89}=0x1C +serdes_core_rx_polarity_flip_physical{90}=0x1C +serdes_core_rx_polarity_flip_physical{91}=0x1C +serdes_core_rx_polarity_flip_physical{92}=0x1C +serdes_core_rx_polarity_flip_physical{93}=0x1C +serdes_core_rx_polarity_flip_physical{94}=0x1C +serdes_core_rx_polarity_flip_physical{95}=0x1C +serdes_core_rx_polarity_flip_physical{96}=0x1C +serdes_core_tx_polarity_flip_physical{89}=0x3B +serdes_core_tx_polarity_flip_physical{90}=0x3B +serdes_core_tx_polarity_flip_physical{91}=0x3B +serdes_core_tx_polarity_flip_physical{92}=0x3B +serdes_core_tx_polarity_flip_physical{93}=0x3B +serdes_core_tx_polarity_flip_physical{94}=0x3B +serdes_core_tx_polarity_flip_physical{95}=0x3B +serdes_core_tx_polarity_flip_physical{96}=0x3B + +dport_map_port_62=13 +dport_map_port_63=14 +dport_map_port_60=15 +dport_map_port_61=16 +portmap_60=97:100 +portmap_61=99:100 +portmap_62=101:100 +portmap_63=103:100 +phy_chain_rx_lane_map_physical{97.0}=0x32510467 +phy_chain_rx_lane_map_physical{98.0}=0x32510467 +phy_chain_rx_lane_map_physical{99.0}=0x32510467 +phy_chain_rx_lane_map_physical{100.0}=0x32510467 +phy_chain_rx_lane_map_physical{101.0}=0x32510467 +phy_chain_rx_lane_map_physical{102.0}=0x32510467 +phy_chain_rx_lane_map_physical{103.0}=0x32510467 +phy_chain_rx_lane_map_physical{104.0}=0x32510467 +phy_chain_tx_lane_map_physical{97.0}=0x57462103 +phy_chain_tx_lane_map_physical{98.0}=0x57462103 +phy_chain_tx_lane_map_physical{99.0}=0x57462103 +phy_chain_tx_lane_map_physical{100.0}=0x57462103 +phy_chain_tx_lane_map_physical{101.0}=0x57462103 +phy_chain_tx_lane_map_physical{102.0}=0x57462103 +phy_chain_tx_lane_map_physical{103.0}=0x57462103 +phy_chain_tx_lane_map_physical{104.0}=0x57462103 +serdes_core_rx_polarity_flip_physical{97}=0xE9 +serdes_core_rx_polarity_flip_physical{98}=0xE9 +serdes_core_rx_polarity_flip_physical{99}=0xE9 +serdes_core_rx_polarity_flip_physical{100}=0xE9 +serdes_core_rx_polarity_flip_physical{101}=0xE9 +serdes_core_rx_polarity_flip_physical{102}=0xE9 +serdes_core_rx_polarity_flip_physical{103}=0xE9 +serdes_core_rx_polarity_flip_physical{104}=0xE9 +serdes_core_tx_polarity_flip_physical{97}=0x1 +serdes_core_tx_polarity_flip_physical{98}=0x1 +serdes_core_tx_polarity_flip_physical{99}=0x1 +serdes_core_tx_polarity_flip_physical{100}=0x1 +serdes_core_tx_polarity_flip_physical{101}=0x1 +serdes_core_tx_polarity_flip_physical{102}=0x1 +serdes_core_tx_polarity_flip_physical{103}=0x1 +serdes_core_tx_polarity_flip_physical{104}=0x1 + +dport_map_port_66=29 +dport_map_port_67=30 +dport_map_port_64=31 +dport_map_port_65=32 +portmap_64=105:100 +portmap_65=107:100 +portmap_66=109:100 +portmap_67=111:100 +phy_chain_rx_lane_map_physical{105.0}=0x32106745 +phy_chain_rx_lane_map_physical{106.0}=0x32106745 +phy_chain_rx_lane_map_physical{107.0}=0x32106745 +phy_chain_rx_lane_map_physical{108.0}=0x32106745 +phy_chain_rx_lane_map_physical{109.0}=0x32106745 +phy_chain_rx_lane_map_physical{110.0}=0x32106745 +phy_chain_rx_lane_map_physical{111.0}=0x32106745 +phy_chain_rx_lane_map_physical{112.0}=0x32106745 +phy_chain_tx_lane_map_physical{105.0}=0x23015746 +phy_chain_tx_lane_map_physical{106.0}=0x23015746 +phy_chain_tx_lane_map_physical{107.0}=0x23015746 +phy_chain_tx_lane_map_physical{108.0}=0x23015746 +phy_chain_tx_lane_map_physical{109.0}=0x23015746 +phy_chain_tx_lane_map_physical{110.0}=0x23015746 +phy_chain_tx_lane_map_physical{111.0}=0x23015746 +phy_chain_tx_lane_map_physical{112.0}=0x23015746 +serdes_core_rx_polarity_flip_physical{105}=0x2A +serdes_core_rx_polarity_flip_physical{106}=0x2A +serdes_core_rx_polarity_flip_physical{107}=0x2A +serdes_core_rx_polarity_flip_physical{108}=0x2A +serdes_core_rx_polarity_flip_physical{109}=0x2A +serdes_core_rx_polarity_flip_physical{110}=0x2A +serdes_core_rx_polarity_flip_physical{111}=0x2A +serdes_core_rx_polarity_flip_physical{112}=0x2A +serdes_core_tx_polarity_flip_physical{105}=0xDA +serdes_core_tx_polarity_flip_physical{106}=0xDA +serdes_core_tx_polarity_flip_physical{107}=0xDA +serdes_core_tx_polarity_flip_physical{108}=0xDA +serdes_core_tx_polarity_flip_physical{109}=0xDA +serdes_core_tx_polarity_flip_physical{110}=0xDA +serdes_core_tx_polarity_flip_physical{111}=0xDA +serdes_core_tx_polarity_flip_physical{112}=0xDA + +dport_map_port_70=45 +dport_map_port_71=46 +dport_map_port_68=47 +dport_map_port_69=48 +portmap_68=113:100 +portmap_69=115:100 +portmap_70=117:100 +portmap_71=119:100 +phy_chain_rx_lane_map_physical{113.0}=0x32451607 +phy_chain_rx_lane_map_physical{114.0}=0x32451607 +phy_chain_rx_lane_map_physical{115.0}=0x32451607 +phy_chain_rx_lane_map_physical{116.0}=0x32451607 +phy_chain_rx_lane_map_physical{117.0}=0x32451607 +phy_chain_rx_lane_map_physical{118.0}=0x32451607 +phy_chain_rx_lane_map_physical{119.0}=0x32451607 +phy_chain_rx_lane_map_physical{120.0}=0x32451607 +phy_chain_tx_lane_map_physical{113.0}=0x65704231 +phy_chain_tx_lane_map_physical{114.0}=0x65704231 +phy_chain_tx_lane_map_physical{115.0}=0x65704231 +phy_chain_tx_lane_map_physical{116.0}=0x65704231 +phy_chain_tx_lane_map_physical{117.0}=0x65704231 +phy_chain_tx_lane_map_physical{118.0}=0x65704231 +phy_chain_tx_lane_map_physical{119.0}=0x65704231 +phy_chain_tx_lane_map_physical{120.0}=0x65704231 +serdes_core_rx_polarity_flip_physical{113}=0xD6 +serdes_core_rx_polarity_flip_physical{114}=0xD6 +serdes_core_rx_polarity_flip_physical{115}=0xD6 +serdes_core_rx_polarity_flip_physical{116}=0xD6 +serdes_core_rx_polarity_flip_physical{117}=0xD6 +serdes_core_rx_polarity_flip_physical{118}=0xD6 +serdes_core_rx_polarity_flip_physical{119}=0xD6 +serdes_core_rx_polarity_flip_physical{120}=0xD6 +serdes_core_tx_polarity_flip_physical{113}=0xDF +serdes_core_tx_polarity_flip_physical{114}=0xDF +serdes_core_tx_polarity_flip_physical{115}=0xDF +serdes_core_tx_polarity_flip_physical{116}=0xDF +serdes_core_tx_polarity_flip_physical{117}=0xDF +serdes_core_tx_polarity_flip_physical{118}=0xDF +serdes_core_tx_polarity_flip_physical{119}=0xDF +serdes_core_tx_polarity_flip_physical{120}=0xDF + +dport_map_port_74=61 +dport_map_port_75=62 +dport_map_port_72=63 +dport_map_port_73=64 +portmap_72=121:100 +portmap_73=123:100 +portmap_74=125:100 +portmap_75=127:100 +phy_chain_rx_lane_map_physical{121.0}=0x12304567 +phy_chain_rx_lane_map_physical{122.0}=0x12304567 +phy_chain_rx_lane_map_physical{123.0}=0x12304567 +phy_chain_rx_lane_map_physical{124.0}=0x12304567 +phy_chain_rx_lane_map_physical{125.0}=0x12304567 +phy_chain_rx_lane_map_physical{126.0}=0x12304567 +phy_chain_rx_lane_map_physical{127.0}=0x12304567 +phy_chain_rx_lane_map_physical{128.0}=0x12304567 +phy_chain_tx_lane_map_physical{121.0}=0x17526403 +phy_chain_tx_lane_map_physical{122.0}=0x17526403 +phy_chain_tx_lane_map_physical{123.0}=0x17526403 +phy_chain_tx_lane_map_physical{124.0}=0x17526403 +phy_chain_tx_lane_map_physical{125.0}=0x17526403 +phy_chain_tx_lane_map_physical{126.0}=0x17526403 +phy_chain_tx_lane_map_physical{127.0}=0x17526403 +phy_chain_tx_lane_map_physical{128.0}=0x17526403 +serdes_core_rx_polarity_flip_physical{121}=0xD5 +serdes_core_rx_polarity_flip_physical{122}=0xD5 +serdes_core_rx_polarity_flip_physical{123}=0xD5 +serdes_core_rx_polarity_flip_physical{124}=0xD5 +serdes_core_rx_polarity_flip_physical{125}=0xD5 +serdes_core_rx_polarity_flip_physical{126}=0xD5 +serdes_core_rx_polarity_flip_physical{127}=0xD5 +serdes_core_rx_polarity_flip_physical{128}=0xD5 +serdes_core_tx_polarity_flip_physical{121}=0xE2 +serdes_core_tx_polarity_flip_physical{122}=0xE2 +serdes_core_tx_polarity_flip_physical{123}=0xE2 +serdes_core_tx_polarity_flip_physical{124}=0xE2 +serdes_core_tx_polarity_flip_physical{125}=0xE2 +serdes_core_tx_polarity_flip_physical{126}=0xE2 +serdes_core_tx_polarity_flip_physical{127}=0xE2 +serdes_core_tx_polarity_flip_physical{128}=0xE2 + +dport_map_port_82=65 +dport_map_port_83=66 +dport_map_port_80=67 +dport_map_port_81=68 +portmap_80=129:100 +portmap_81=131:100 +portmap_82=133:100 +portmap_83=135:100 +phy_chain_rx_lane_map_physical{129.0}=0x70453261 +phy_chain_rx_lane_map_physical{130.0}=0x70453261 +phy_chain_rx_lane_map_physical{131.0}=0x70453261 +phy_chain_rx_lane_map_physical{132.0}=0x70453261 +phy_chain_rx_lane_map_physical{133.0}=0x70453261 +phy_chain_rx_lane_map_physical{134.0}=0x70453261 +phy_chain_rx_lane_map_physical{135.0}=0x70453261 +phy_chain_rx_lane_map_physical{136.0}=0x70453261 +phy_chain_tx_lane_map_physical{129.0}=0x32104675 +phy_chain_tx_lane_map_physical{130.0}=0x32104675 +phy_chain_tx_lane_map_physical{131.0}=0x32104675 +phy_chain_tx_lane_map_physical{132.0}=0x32104675 +phy_chain_tx_lane_map_physical{133.0}=0x32104675 +phy_chain_tx_lane_map_physical{134.0}=0x32104675 +phy_chain_tx_lane_map_physical{135.0}=0x32104675 +phy_chain_tx_lane_map_physical{136.0}=0x32104675 +serdes_core_rx_polarity_flip_physical{129}=0x2B +serdes_core_rx_polarity_flip_physical{130}=0x2B +serdes_core_rx_polarity_flip_physical{131}=0x2B +serdes_core_rx_polarity_flip_physical{132}=0x2B +serdes_core_rx_polarity_flip_physical{133}=0x2B +serdes_core_rx_polarity_flip_physical{134}=0x2B +serdes_core_rx_polarity_flip_physical{135}=0x2B +serdes_core_rx_polarity_flip_physical{136}=0x2B +serdes_core_tx_polarity_flip_physical{129}=0xB0 +serdes_core_tx_polarity_flip_physical{130}=0xB0 +serdes_core_tx_polarity_flip_physical{131}=0xB0 +serdes_core_tx_polarity_flip_physical{132}=0xB0 +serdes_core_tx_polarity_flip_physical{133}=0xB0 +serdes_core_tx_polarity_flip_physical{134}=0xB0 +serdes_core_tx_polarity_flip_physical{135}=0xB0 +serdes_core_tx_polarity_flip_physical{136}=0xB0 + +dport_map_port_86=81 +dport_map_port_87=82 +dport_map_port_84=83 +dport_map_port_85=84 +portmap_84=137:100 +portmap_85=139:100 +portmap_86=141:100 +portmap_87=143:100 +phy_chain_rx_lane_map_physical{137.0}=0x73625410 +phy_chain_rx_lane_map_physical{138.0}=0x73625410 +phy_chain_rx_lane_map_physical{139.0}=0x73625410 +phy_chain_rx_lane_map_physical{140.0}=0x73625410 +phy_chain_rx_lane_map_physical{141.0}=0x73625410 +phy_chain_rx_lane_map_physical{142.0}=0x73625410 +phy_chain_rx_lane_map_physical{143.0}=0x73625410 +phy_chain_rx_lane_map_physical{144.0}=0x73625410 +phy_chain_tx_lane_map_physical{137.0}=0x23407615 +phy_chain_tx_lane_map_physical{138.0}=0x23407615 +phy_chain_tx_lane_map_physical{139.0}=0x23407615 +phy_chain_tx_lane_map_physical{140.0}=0x23407615 +phy_chain_tx_lane_map_physical{141.0}=0x23407615 +phy_chain_tx_lane_map_physical{142.0}=0x23407615 +phy_chain_tx_lane_map_physical{143.0}=0x23407615 +phy_chain_tx_lane_map_physical{144.0}=0x23407615 +serdes_core_rx_polarity_flip_physical{137}=0x67 +serdes_core_rx_polarity_flip_physical{138}=0x67 +serdes_core_rx_polarity_flip_physical{139}=0x67 +serdes_core_rx_polarity_flip_physical{140}=0x67 +serdes_core_rx_polarity_flip_physical{141}=0x67 +serdes_core_rx_polarity_flip_physical{142}=0x67 +serdes_core_rx_polarity_flip_physical{143}=0x67 +serdes_core_rx_polarity_flip_physical{144}=0x67 +serdes_core_tx_polarity_flip_physical{137}=0xC6 +serdes_core_tx_polarity_flip_physical{138}=0xC6 +serdes_core_tx_polarity_flip_physical{139}=0xC6 +serdes_core_tx_polarity_flip_physical{140}=0xC6 +serdes_core_tx_polarity_flip_physical{141}=0xC6 +serdes_core_tx_polarity_flip_physical{142}=0xC6 +serdes_core_tx_polarity_flip_physical{143}=0xC6 +serdes_core_tx_polarity_flip_physical{144}=0xC6 + +dport_map_port_90=97 +dport_map_port_91=98 +dport_map_port_88=99 +dport_map_port_89=100 +portmap_88=145:100 +portmap_89=147:100 +portmap_90=149:100 +portmap_91=151:100 +phy_chain_rx_lane_map_physical{145.0}=0x32016457 +phy_chain_rx_lane_map_physical{146.0}=0x32016457 +phy_chain_rx_lane_map_physical{147.0}=0x32016457 +phy_chain_rx_lane_map_physical{148.0}=0x32016457 +phy_chain_rx_lane_map_physical{149.0}=0x32016457 +phy_chain_rx_lane_map_physical{150.0}=0x32016457 +phy_chain_rx_lane_map_physical{151.0}=0x32016457 +phy_chain_rx_lane_map_physical{152.0}=0x32016457 +phy_chain_tx_lane_map_physical{145.0}=0x76540132 +phy_chain_tx_lane_map_physical{146.0}=0x76540132 +phy_chain_tx_lane_map_physical{147.0}=0x76540132 +phy_chain_tx_lane_map_physical{148.0}=0x76540132 +phy_chain_tx_lane_map_physical{149.0}=0x76540132 +phy_chain_tx_lane_map_physical{150.0}=0x76540132 +phy_chain_tx_lane_map_physical{151.0}=0x76540132 +phy_chain_tx_lane_map_physical{152.0}=0x76540132 +serdes_core_rx_polarity_flip_physical{145}=0x63 +serdes_core_rx_polarity_flip_physical{146}=0x63 +serdes_core_rx_polarity_flip_physical{147}=0x63 +serdes_core_rx_polarity_flip_physical{148}=0x63 +serdes_core_rx_polarity_flip_physical{149}=0x63 +serdes_core_rx_polarity_flip_physical{150}=0x63 +serdes_core_rx_polarity_flip_physical{151}=0x63 +serdes_core_rx_polarity_flip_physical{152}=0x63 +serdes_core_tx_polarity_flip_physical{145}=0xB5 +serdes_core_tx_polarity_flip_physical{146}=0xB5 +serdes_core_tx_polarity_flip_physical{147}=0xB5 +serdes_core_tx_polarity_flip_physical{148}=0xB5 +serdes_core_tx_polarity_flip_physical{149}=0xB5 +serdes_core_tx_polarity_flip_physical{150}=0xB5 +serdes_core_tx_polarity_flip_physical{151}=0xB5 +serdes_core_tx_polarity_flip_physical{152}=0xB5 + +dport_map_port_94=113 +dport_map_port_95=114 +dport_map_port_92=115 +dport_map_port_93=116 +portmap_92=153:100 +portmap_93=155:100 +portmap_94=157:100 +portmap_95=159:100 +phy_chain_rx_lane_map_physical{153.0}=0x32106457 +phy_chain_rx_lane_map_physical{154.0}=0x32106457 +phy_chain_rx_lane_map_physical{155.0}=0x32106457 +phy_chain_rx_lane_map_physical{156.0}=0x32106457 +phy_chain_rx_lane_map_physical{157.0}=0x32106457 +phy_chain_rx_lane_map_physical{158.0}=0x32106457 +phy_chain_rx_lane_map_physical{159.0}=0x32106457 +phy_chain_rx_lane_map_physical{160.0}=0x32106457 +phy_chain_tx_lane_map_physical{153.0}=0x13205746 +phy_chain_tx_lane_map_physical{154.0}=0x13205746 +phy_chain_tx_lane_map_physical{155.0}=0x13205746 +phy_chain_tx_lane_map_physical{156.0}=0x13205746 +phy_chain_tx_lane_map_physical{157.0}=0x13205746 +phy_chain_tx_lane_map_physical{158.0}=0x13205746 +phy_chain_tx_lane_map_physical{159.0}=0x13205746 +phy_chain_tx_lane_map_physical{160.0}=0x13205746 +serdes_core_rx_polarity_flip_physical{153}=0xD3 +serdes_core_rx_polarity_flip_physical{154}=0xD3 +serdes_core_rx_polarity_flip_physical{155}=0xD3 +serdes_core_rx_polarity_flip_physical{156}=0xD3 +serdes_core_rx_polarity_flip_physical{157}=0xD3 +serdes_core_rx_polarity_flip_physical{158}=0xD3 +serdes_core_rx_polarity_flip_physical{159}=0xD3 +serdes_core_rx_polarity_flip_physical{160}=0xD3 +serdes_core_tx_polarity_flip_physical{153}=0x75 +serdes_core_tx_polarity_flip_physical{154}=0x75 +serdes_core_tx_polarity_flip_physical{155}=0x75 +serdes_core_tx_polarity_flip_physical{156}=0x75 +serdes_core_tx_polarity_flip_physical{157}=0x75 +serdes_core_tx_polarity_flip_physical{158}=0x75 +serdes_core_tx_polarity_flip_physical{159}=0x75 +serdes_core_tx_polarity_flip_physical{160}=0x75 + +dport_map_port_102=69 +dport_map_port_103=70 +dport_map_port_100=71 +dport_map_port_101=72 +portmap_100=161:100 +portmap_101=163:100 +portmap_102=165:100 +portmap_103=167:100 +phy_chain_rx_lane_map_physical{161.0}=0x04152736 +phy_chain_rx_lane_map_physical{162.0}=0x04152736 +phy_chain_rx_lane_map_physical{163.0}=0x04152736 +phy_chain_rx_lane_map_physical{164.0}=0x04152736 +phy_chain_rx_lane_map_physical{165.0}=0x04152736 +phy_chain_rx_lane_map_physical{166.0}=0x04152736 +phy_chain_rx_lane_map_physical{167.0}=0x04152736 +phy_chain_rx_lane_map_physical{168.0}=0x04152736 +phy_chain_tx_lane_map_physical{161.0}=0x14207653 +phy_chain_tx_lane_map_physical{162.0}=0x14207653 +phy_chain_tx_lane_map_physical{163.0}=0x14207653 +phy_chain_tx_lane_map_physical{164.0}=0x14207653 +phy_chain_tx_lane_map_physical{165.0}=0x14207653 +phy_chain_tx_lane_map_physical{166.0}=0x14207653 +phy_chain_tx_lane_map_physical{167.0}=0x14207653 +phy_chain_tx_lane_map_physical{168.0}=0x14207653 +serdes_core_rx_polarity_flip_physical{161}=0xB6 +serdes_core_rx_polarity_flip_physical{162}=0xB6 +serdes_core_rx_polarity_flip_physical{163}=0xB6 +serdes_core_rx_polarity_flip_physical{164}=0xB6 +serdes_core_rx_polarity_flip_physical{165}=0xB6 +serdes_core_rx_polarity_flip_physical{166}=0xB6 +serdes_core_rx_polarity_flip_physical{167}=0xB6 +serdes_core_rx_polarity_flip_physical{168}=0xB6 +serdes_core_tx_polarity_flip_physical{161}=0x4E +serdes_core_tx_polarity_flip_physical{162}=0x4E +serdes_core_tx_polarity_flip_physical{163}=0x4E +serdes_core_tx_polarity_flip_physical{164}=0x4E +serdes_core_tx_polarity_flip_physical{165}=0x4E +serdes_core_tx_polarity_flip_physical{166}=0x4E +serdes_core_tx_polarity_flip_physical{167}=0x4E +serdes_core_tx_polarity_flip_physical{168}=0x4E + +dport_map_port_106=85 +dport_map_port_107=86 +dport_map_port_104=87 +dport_map_port_105=88 +portmap_104=169:100 +portmap_105=171:100 +portmap_106=173:100 +portmap_107=175:100 +phy_chain_rx_lane_map_physical{169.0}=0x37261504 +phy_chain_rx_lane_map_physical{170.0}=0x37261504 +phy_chain_rx_lane_map_physical{171.0}=0x37261504 +phy_chain_rx_lane_map_physical{172.0}=0x37261504 +phy_chain_rx_lane_map_physical{173.0}=0x37261504 +phy_chain_rx_lane_map_physical{174.0}=0x37261504 +phy_chain_rx_lane_map_physical{175.0}=0x37261504 +phy_chain_rx_lane_map_physical{176.0}=0x37261504 +phy_chain_tx_lane_map_physical{169.0}=0x30246751 +phy_chain_tx_lane_map_physical{170.0}=0x30246751 +phy_chain_tx_lane_map_physical{171.0}=0x30246751 +phy_chain_tx_lane_map_physical{172.0}=0x30246751 +phy_chain_tx_lane_map_physical{173.0}=0x30246751 +phy_chain_tx_lane_map_physical{174.0}=0x30246751 +phy_chain_tx_lane_map_physical{175.0}=0x30246751 +phy_chain_tx_lane_map_physical{176.0}=0x30246751 +serdes_core_rx_polarity_flip_physical{169}=0x69 +serdes_core_rx_polarity_flip_physical{170}=0x69 +serdes_core_rx_polarity_flip_physical{171}=0x69 +serdes_core_rx_polarity_flip_physical{172}=0x69 +serdes_core_rx_polarity_flip_physical{173}=0x69 +serdes_core_rx_polarity_flip_physical{174}=0x69 +serdes_core_rx_polarity_flip_physical{175}=0x69 +serdes_core_rx_polarity_flip_physical{176}=0x69 +serdes_core_tx_polarity_flip_physical{169}=0x3F +serdes_core_tx_polarity_flip_physical{170}=0x3F +serdes_core_tx_polarity_flip_physical{171}=0x3F +serdes_core_tx_polarity_flip_physical{172}=0x3F +serdes_core_tx_polarity_flip_physical{173}=0x3F +serdes_core_tx_polarity_flip_physical{174}=0x3F +serdes_core_tx_polarity_flip_physical{175}=0x3F +serdes_core_tx_polarity_flip_physical{176}=0x3F + +dport_map_port_110=101 +dport_map_port_111=102 +dport_map_port_108=103 +dport_map_port_109=104 +portmap_108=177:100 +portmap_109=179:100 +portmap_110=181:100 +portmap_111=183:100 +phy_chain_rx_lane_map_physical{177.0}=0x72541063 +phy_chain_rx_lane_map_physical{178.0}=0x72541063 +phy_chain_rx_lane_map_physical{179.0}=0x72541063 +phy_chain_rx_lane_map_physical{180.0}=0x72541063 +phy_chain_rx_lane_map_physical{181.0}=0x72541063 +phy_chain_rx_lane_map_physical{182.0}=0x72541063 +phy_chain_rx_lane_map_physical{183.0}=0x72541063 +phy_chain_rx_lane_map_physical{184.0}=0x72541063 +phy_chain_tx_lane_map_physical{177.0}=0x67504312 +phy_chain_tx_lane_map_physical{178.0}=0x67504312 +phy_chain_tx_lane_map_physical{179.0}=0x67504312 +phy_chain_tx_lane_map_physical{180.0}=0x67504312 +phy_chain_tx_lane_map_physical{181.0}=0x67504312 +phy_chain_tx_lane_map_physical{182.0}=0x67504312 +phy_chain_tx_lane_map_physical{183.0}=0x67504312 +phy_chain_tx_lane_map_physical{184.0}=0x67504312 +serdes_core_rx_polarity_flip_physical{177}=0x9B +serdes_core_rx_polarity_flip_physical{178}=0x9B +serdes_core_rx_polarity_flip_physical{179}=0x9B +serdes_core_rx_polarity_flip_physical{180}=0x9B +serdes_core_rx_polarity_flip_physical{181}=0x9B +serdes_core_rx_polarity_flip_physical{182}=0x9B +serdes_core_rx_polarity_flip_physical{183}=0x9B +serdes_core_rx_polarity_flip_physical{184}=0x9B +serdes_core_tx_polarity_flip_physical{177}=0xD3 +serdes_core_tx_polarity_flip_physical{178}=0xD3 +serdes_core_tx_polarity_flip_physical{179}=0xD3 +serdes_core_tx_polarity_flip_physical{180}=0xD3 +serdes_core_tx_polarity_flip_physical{181}=0xD3 +serdes_core_tx_polarity_flip_physical{182}=0xD3 +serdes_core_tx_polarity_flip_physical{183}=0xD3 +serdes_core_tx_polarity_flip_physical{184}=0xD3 + +dport_map_port_114=117 +dport_map_port_115=118 +dport_map_port_112=119 +dport_map_port_113=120 +portmap_112=185:100 +portmap_113=187:100 +portmap_114=189:100 +portmap_115=191:100 +phy_chain_rx_lane_map_physical{185.0}=0x64570123 +phy_chain_rx_lane_map_physical{186.0}=0x64570123 +phy_chain_rx_lane_map_physical{187.0}=0x64570123 +phy_chain_rx_lane_map_physical{188.0}=0x64570123 +phy_chain_rx_lane_map_physical{189.0}=0x64570123 +phy_chain_rx_lane_map_physical{190.0}=0x64570123 +phy_chain_rx_lane_map_physical{191.0}=0x64570123 +phy_chain_rx_lane_map_physical{192.0}=0x64570123 +phy_chain_tx_lane_map_physical{185.0}=0x15247360 +phy_chain_tx_lane_map_physical{186.0}=0x15247360 +phy_chain_tx_lane_map_physical{187.0}=0x15247360 +phy_chain_tx_lane_map_physical{188.0}=0x15247360 +phy_chain_tx_lane_map_physical{189.0}=0x15247360 +phy_chain_tx_lane_map_physical{190.0}=0x15247360 +phy_chain_tx_lane_map_physical{191.0}=0x15247360 +phy_chain_tx_lane_map_physical{192.0}=0x15247360 +serdes_core_rx_polarity_flip_physical{185}=0xCA +serdes_core_rx_polarity_flip_physical{186}=0xCA +serdes_core_rx_polarity_flip_physical{187}=0xCA +serdes_core_rx_polarity_flip_physical{188}=0xCA +serdes_core_rx_polarity_flip_physical{189}=0xCA +serdes_core_rx_polarity_flip_physical{190}=0xCA +serdes_core_rx_polarity_flip_physical{191}=0xCA +serdes_core_rx_polarity_flip_physical{192}=0xCA +serdes_core_tx_polarity_flip_physical{185}=0x4 +serdes_core_tx_polarity_flip_physical{186}=0x4 +serdes_core_tx_polarity_flip_physical{187}=0x4 +serdes_core_tx_polarity_flip_physical{188}=0x4 +serdes_core_tx_polarity_flip_physical{189}=0x4 +serdes_core_tx_polarity_flip_physical{190}=0x4 +serdes_core_tx_polarity_flip_physical{191}=0x4 +serdes_core_tx_polarity_flip_physical{192}=0x4 + +dport_map_port_122=73 +dport_map_port_123=74 +dport_map_port_120=75 +dport_map_port_121=76 +portmap_120=193:100 +portmap_121=195:100 +portmap_122=197:100 +portmap_123=199:100 +phy_chain_rx_lane_map_physical{193.0}=0x36271504 +phy_chain_rx_lane_map_physical{194.0}=0x36271504 +phy_chain_rx_lane_map_physical{195.0}=0x36271504 +phy_chain_rx_lane_map_physical{196.0}=0x36271504 +phy_chain_rx_lane_map_physical{197.0}=0x36271504 +phy_chain_rx_lane_map_physical{198.0}=0x36271504 +phy_chain_rx_lane_map_physical{199.0}=0x36271504 +phy_chain_rx_lane_map_physical{200.0}=0x36271504 +phy_chain_tx_lane_map_physical{193.0}=0x41203675 +phy_chain_tx_lane_map_physical{194.0}=0x41203675 +phy_chain_tx_lane_map_physical{195.0}=0x41203675 +phy_chain_tx_lane_map_physical{196.0}=0x41203675 +phy_chain_tx_lane_map_physical{197.0}=0x41203675 +phy_chain_tx_lane_map_physical{198.0}=0x41203675 +phy_chain_tx_lane_map_physical{199.0}=0x41203675 +phy_chain_tx_lane_map_physical{200.0}=0x41203675 +serdes_core_rx_polarity_flip_physical{193}=0x49 +serdes_core_rx_polarity_flip_physical{194}=0x49 +serdes_core_rx_polarity_flip_physical{195}=0x49 +serdes_core_rx_polarity_flip_physical{196}=0x49 +serdes_core_rx_polarity_flip_physical{197}=0x49 +serdes_core_rx_polarity_flip_physical{198}=0x49 +serdes_core_rx_polarity_flip_physical{199}=0x49 +serdes_core_rx_polarity_flip_physical{200}=0x49 +serdes_core_tx_polarity_flip_physical{193}=0xE8 +serdes_core_tx_polarity_flip_physical{194}=0xE8 +serdes_core_tx_polarity_flip_physical{195}=0xE8 +serdes_core_tx_polarity_flip_physical{196}=0xE8 +serdes_core_tx_polarity_flip_physical{197}=0xE8 +serdes_core_tx_polarity_flip_physical{198}=0xE8 +serdes_core_tx_polarity_flip_physical{199}=0xE8 +serdes_core_tx_polarity_flip_physical{200}=0xE8 + +dport_map_port_126=89 +dport_map_port_127=90 +dport_map_port_124=91 +dport_map_port_125=92 +portmap_124=201:100 +portmap_125=203:100 +portmap_126=205:100 +portmap_127=207:100 +phy_chain_rx_lane_map_physical{201.0}=0x64570123 +phy_chain_rx_lane_map_physical{202.0}=0x64570123 +phy_chain_rx_lane_map_physical{203.0}=0x64570123 +phy_chain_rx_lane_map_physical{204.0}=0x64570123 +phy_chain_rx_lane_map_physical{205.0}=0x64570123 +phy_chain_rx_lane_map_physical{206.0}=0x64570123 +phy_chain_rx_lane_map_physical{207.0}=0x64570123 +phy_chain_rx_lane_map_physical{208.0}=0x64570123 +phy_chain_tx_lane_map_physical{201.0}=0x32046571 +phy_chain_tx_lane_map_physical{202.0}=0x32046571 +phy_chain_tx_lane_map_physical{203.0}=0x32046571 +phy_chain_tx_lane_map_physical{204.0}=0x32046571 +phy_chain_tx_lane_map_physical{205.0}=0x32046571 +phy_chain_tx_lane_map_physical{206.0}=0x32046571 +phy_chain_tx_lane_map_physical{207.0}=0x32046571 +phy_chain_tx_lane_map_physical{208.0}=0x32046571 +serdes_core_rx_polarity_flip_physical{201}=0xBA +serdes_core_rx_polarity_flip_physical{202}=0xBA +serdes_core_rx_polarity_flip_physical{203}=0xBA +serdes_core_rx_polarity_flip_physical{204}=0xBA +serdes_core_rx_polarity_flip_physical{205}=0xBA +serdes_core_rx_polarity_flip_physical{206}=0xBA +serdes_core_rx_polarity_flip_physical{207}=0xBA +serdes_core_rx_polarity_flip_physical{208}=0xBA +serdes_core_tx_polarity_flip_physical{201}=0x5F +serdes_core_tx_polarity_flip_physical{202}=0x5F +serdes_core_tx_polarity_flip_physical{203}=0x5F +serdes_core_tx_polarity_flip_physical{204}=0x5F +serdes_core_tx_polarity_flip_physical{205}=0x5F +serdes_core_tx_polarity_flip_physical{206}=0x5F +serdes_core_tx_polarity_flip_physical{207}=0x5F +serdes_core_tx_polarity_flip_physical{208}=0x5F + +dport_map_port_130=105 +dport_map_port_131=106 +dport_map_port_128=107 +dport_map_port_129=108 +portmap_128=209:100 +portmap_129=211:100 +portmap_130=213:100 +portmap_131=215:100 +phy_chain_rx_lane_map_physical{209.0}=0x37014526 +phy_chain_rx_lane_map_physical{210.0}=0x37014526 +phy_chain_rx_lane_map_physical{211.0}=0x37014526 +phy_chain_rx_lane_map_physical{212.0}=0x37014526 +phy_chain_rx_lane_map_physical{213.0}=0x37014526 +phy_chain_rx_lane_map_physical{214.0}=0x37014526 +phy_chain_rx_lane_map_physical{215.0}=0x37014526 +phy_chain_rx_lane_map_physical{216.0}=0x37014526 +phy_chain_tx_lane_map_physical{209.0}=0x56704213 +phy_chain_tx_lane_map_physical{210.0}=0x56704213 +phy_chain_tx_lane_map_physical{211.0}=0x56704213 +phy_chain_tx_lane_map_physical{212.0}=0x56704213 +phy_chain_tx_lane_map_physical{213.0}=0x56704213 +phy_chain_tx_lane_map_physical{214.0}=0x56704213 +phy_chain_tx_lane_map_physical{215.0}=0x56704213 +phy_chain_tx_lane_map_physical{216.0}=0x56704213 +serdes_core_rx_polarity_flip_physical{209}=0x19 +serdes_core_rx_polarity_flip_physical{210}=0x19 +serdes_core_rx_polarity_flip_physical{211}=0x19 +serdes_core_rx_polarity_flip_physical{212}=0x19 +serdes_core_rx_polarity_flip_physical{213}=0x19 +serdes_core_rx_polarity_flip_physical{214}=0x19 +serdes_core_rx_polarity_flip_physical{215}=0x19 +serdes_core_rx_polarity_flip_physical{216}=0x19 +serdes_core_tx_polarity_flip_physical{209}=0x35 +serdes_core_tx_polarity_flip_physical{210}=0x35 +serdes_core_tx_polarity_flip_physical{211}=0x35 +serdes_core_tx_polarity_flip_physical{212}=0x35 +serdes_core_tx_polarity_flip_physical{213}=0x35 +serdes_core_tx_polarity_flip_physical{214}=0x35 +serdes_core_tx_polarity_flip_physical{215}=0x35 +serdes_core_tx_polarity_flip_physical{216}=0x35 + +dport_map_port_134=121 +dport_map_port_135=122 +dport_map_port_132=123 +dport_map_port_133=124 +portmap_132=217:100 +portmap_133=219:100 +portmap_134=221:100 +portmap_135=223:100 +phy_chain_rx_lane_map_physical{217.0}=0x65041273 +phy_chain_rx_lane_map_physical{218.0}=0x65041273 +phy_chain_rx_lane_map_physical{219.0}=0x65041273 +phy_chain_rx_lane_map_physical{220.0}=0x65041273 +phy_chain_rx_lane_map_physical{221.0}=0x65041273 +phy_chain_rx_lane_map_physical{222.0}=0x65041273 +phy_chain_rx_lane_map_physical{223.0}=0x65041273 +phy_chain_rx_lane_map_physical{224.0}=0x65041273 +phy_chain_tx_lane_map_physical{217.0}=0x53174620 +phy_chain_tx_lane_map_physical{218.0}=0x53174620 +phy_chain_tx_lane_map_physical{219.0}=0x53174620 +phy_chain_tx_lane_map_physical{220.0}=0x53174620 +phy_chain_tx_lane_map_physical{221.0}=0x53174620 +phy_chain_tx_lane_map_physical{222.0}=0x53174620 +phy_chain_tx_lane_map_physical{223.0}=0x53174620 +phy_chain_tx_lane_map_physical{224.0}=0x53174620 +serdes_core_rx_polarity_flip_physical{217}=0xE6 +serdes_core_rx_polarity_flip_physical{218}=0xE6 +serdes_core_rx_polarity_flip_physical{219}=0xE6 +serdes_core_rx_polarity_flip_physical{220}=0xE6 +serdes_core_rx_polarity_flip_physical{221}=0xE6 +serdes_core_rx_polarity_flip_physical{222}=0xE6 +serdes_core_rx_polarity_flip_physical{223}=0xE6 +serdes_core_rx_polarity_flip_physical{224}=0xE6 +serdes_core_tx_polarity_flip_physical{217}=0xE8 +serdes_core_tx_polarity_flip_physical{218}=0xE8 +serdes_core_tx_polarity_flip_physical{219}=0xE8 +serdes_core_tx_polarity_flip_physical{220}=0xE8 +serdes_core_tx_polarity_flip_physical{221}=0xE8 +serdes_core_tx_polarity_flip_physical{222}=0xE8 +serdes_core_tx_polarity_flip_physical{223}=0xE8 +serdes_core_tx_polarity_flip_physical{224}=0xE8 + +dport_map_port_142=77 +dport_map_port_143=78 +dport_map_port_140=79 +dport_map_port_141=80 +portmap_140=225:100 +portmap_141=227:100 +portmap_142=229:100 +portmap_143=231:100 +phy_chain_rx_lane_map_physical{225.0}=0x32106745 +phy_chain_rx_lane_map_physical{226.0}=0x32106745 +phy_chain_rx_lane_map_physical{227.0}=0x32106745 +phy_chain_rx_lane_map_physical{228.0}=0x32106745 +phy_chain_rx_lane_map_physical{229.0}=0x32106745 +phy_chain_rx_lane_map_physical{230.0}=0x32106745 +phy_chain_rx_lane_map_physical{231.0}=0x32106745 +phy_chain_rx_lane_map_physical{232.0}=0x32106745 +phy_chain_tx_lane_map_physical{225.0}=0x65702134 +phy_chain_tx_lane_map_physical{226.0}=0x65702134 +phy_chain_tx_lane_map_physical{227.0}=0x65702134 +phy_chain_tx_lane_map_physical{228.0}=0x65702134 +phy_chain_tx_lane_map_physical{229.0}=0x65702134 +phy_chain_tx_lane_map_physical{230.0}=0x65702134 +phy_chain_tx_lane_map_physical{231.0}=0x65702134 +phy_chain_tx_lane_map_physical{232.0}=0x65702134 +serdes_core_rx_polarity_flip_physical{225}=0xDA +serdes_core_rx_polarity_flip_physical{226}=0xDA +serdes_core_rx_polarity_flip_physical{227}=0xDA +serdes_core_rx_polarity_flip_physical{228}=0xDA +serdes_core_rx_polarity_flip_physical{229}=0xDA +serdes_core_rx_polarity_flip_physical{230}=0xDA +serdes_core_rx_polarity_flip_physical{231}=0xDA +serdes_core_rx_polarity_flip_physical{232}=0xDA +serdes_core_tx_polarity_flip_physical{225}=0xB2 +serdes_core_tx_polarity_flip_physical{226}=0xB2 +serdes_core_tx_polarity_flip_physical{227}=0xB2 +serdes_core_tx_polarity_flip_physical{228}=0xB2 +serdes_core_tx_polarity_flip_physical{229}=0xB2 +serdes_core_tx_polarity_flip_physical{230}=0xB2 +serdes_core_tx_polarity_flip_physical{231}=0xB2 +serdes_core_tx_polarity_flip_physical{232}=0xB2 + +dport_map_port_146=93 +dport_map_port_147=94 +dport_map_port_144=95 +dport_map_port_145=96 +portmap_144=233:100 +portmap_145=235:100 +portmap_146=237:100 +portmap_147=239:100 +phy_chain_rx_lane_map_physical{233.0}=0x76450321 +phy_chain_rx_lane_map_physical{234.0}=0x76450321 +phy_chain_rx_lane_map_physical{235.0}=0x76450321 +phy_chain_rx_lane_map_physical{236.0}=0x76450321 +phy_chain_rx_lane_map_physical{237.0}=0x76450321 +phy_chain_rx_lane_map_physical{238.0}=0x76450321 +phy_chain_rx_lane_map_physical{239.0}=0x76450321 +phy_chain_rx_lane_map_physical{240.0}=0x76450321 +phy_chain_tx_lane_map_physical{233.0}=0x52301467 +phy_chain_tx_lane_map_physical{234.0}=0x52301467 +phy_chain_tx_lane_map_physical{235.0}=0x52301467 +phy_chain_tx_lane_map_physical{236.0}=0x52301467 +phy_chain_tx_lane_map_physical{237.0}=0x52301467 +phy_chain_tx_lane_map_physical{238.0}=0x52301467 +phy_chain_tx_lane_map_physical{239.0}=0x52301467 +phy_chain_tx_lane_map_physical{240.0}=0x52301467 +serdes_core_rx_polarity_flip_physical{233}=0xE5 +serdes_core_rx_polarity_flip_physical{234}=0xE5 +serdes_core_rx_polarity_flip_physical{235}=0xE5 +serdes_core_rx_polarity_flip_physical{236}=0xE5 +serdes_core_rx_polarity_flip_physical{237}=0xE5 +serdes_core_rx_polarity_flip_physical{238}=0xE5 +serdes_core_rx_polarity_flip_physical{239}=0xE5 +serdes_core_rx_polarity_flip_physical{240}=0xE5 +serdes_core_tx_polarity_flip_physical{233}=0xAA +serdes_core_tx_polarity_flip_physical{234}=0xAA +serdes_core_tx_polarity_flip_physical{235}=0xAA +serdes_core_tx_polarity_flip_physical{236}=0xAA +serdes_core_tx_polarity_flip_physical{237}=0xAA +serdes_core_tx_polarity_flip_physical{238}=0xAA +serdes_core_tx_polarity_flip_physical{239}=0xAA +serdes_core_tx_polarity_flip_physical{240}=0xAA + +dport_map_port_150=109 +dport_map_port_151=110 +dport_map_port_148=111 +dport_map_port_149=112 +portmap_148=241:100 +portmap_149=243:100 +portmap_150=245:100 +portmap_151=247:100 +phy_chain_rx_lane_map_physical{241.0}=0x01276534 +phy_chain_rx_lane_map_physical{242.0}=0x01276534 +phy_chain_rx_lane_map_physical{243.0}=0x01276534 +phy_chain_rx_lane_map_physical{244.0}=0x01276534 +phy_chain_rx_lane_map_physical{245.0}=0x01276534 +phy_chain_rx_lane_map_physical{246.0}=0x01276534 +phy_chain_rx_lane_map_physical{247.0}=0x01276534 +phy_chain_rx_lane_map_physical{248.0}=0x01276534 +phy_chain_tx_lane_map_physical{241.0}=0x67540123 +phy_chain_tx_lane_map_physical{242.0}=0x67540123 +phy_chain_tx_lane_map_physical{243.0}=0x67540123 +phy_chain_tx_lane_map_physical{244.0}=0x67540123 +phy_chain_tx_lane_map_physical{245.0}=0x67540123 +phy_chain_tx_lane_map_physical{246.0}=0x67540123 +phy_chain_tx_lane_map_physical{247.0}=0x67540123 +phy_chain_tx_lane_map_physical{248.0}=0x67540123 +serdes_core_rx_polarity_flip_physical{241}=0x34 +serdes_core_rx_polarity_flip_physical{242}=0x34 +serdes_core_rx_polarity_flip_physical{243}=0x34 +serdes_core_rx_polarity_flip_physical{244}=0x34 +serdes_core_rx_polarity_flip_physical{245}=0x34 +serdes_core_rx_polarity_flip_physical{246}=0x34 +serdes_core_rx_polarity_flip_physical{247}=0x34 +serdes_core_rx_polarity_flip_physical{248}=0x34 +serdes_core_tx_polarity_flip_physical{241}=0x83 +serdes_core_tx_polarity_flip_physical{242}=0x83 +serdes_core_tx_polarity_flip_physical{243}=0x83 +serdes_core_tx_polarity_flip_physical{244}=0x83 +serdes_core_tx_polarity_flip_physical{245}=0x83 +serdes_core_tx_polarity_flip_physical{246}=0x83 +serdes_core_tx_polarity_flip_physical{247}=0x83 +serdes_core_tx_polarity_flip_physical{248}=0x83 + +dport_map_port_154=125 +dport_map_port_155=126 +dport_map_port_152=127 +dport_map_port_153=128 +portmap_152=249:100 +portmap_153=251:100 +portmap_154=253:100 +portmap_155=255:100 +phy_chain_rx_lane_map_physical{249.0}=0x06152347 +phy_chain_rx_lane_map_physical{250.0}=0x06152347 +phy_chain_rx_lane_map_physical{251.0}=0x06152347 +phy_chain_rx_lane_map_physical{252.0}=0x06152347 +phy_chain_rx_lane_map_physical{253.0}=0x06152347 +phy_chain_rx_lane_map_physical{254.0}=0x06152347 +phy_chain_rx_lane_map_physical{255.0}=0x06152347 +phy_chain_rx_lane_map_physical{256.0}=0x06152347 +phy_chain_tx_lane_map_physical{249.0}=0x67501342 +phy_chain_tx_lane_map_physical{250.0}=0x67501342 +phy_chain_tx_lane_map_physical{251.0}=0x67501342 +phy_chain_tx_lane_map_physical{252.0}=0x67501342 +phy_chain_tx_lane_map_physical{253.0}=0x67501342 +phy_chain_tx_lane_map_physical{254.0}=0x67501342 +phy_chain_tx_lane_map_physical{255.0}=0x67501342 +phy_chain_tx_lane_map_physical{256.0}=0x67501342 +serdes_core_rx_polarity_flip_physical{249}=0x19 +serdes_core_rx_polarity_flip_physical{250}=0x19 +serdes_core_rx_polarity_flip_physical{251}=0x19 +serdes_core_rx_polarity_flip_physical{252}=0x19 +serdes_core_rx_polarity_flip_physical{253}=0x19 +serdes_core_rx_polarity_flip_physical{254}=0x19 +serdes_core_rx_polarity_flip_physical{255}=0x19 +serdes_core_rx_polarity_flip_physical{256}=0x19 +serdes_core_tx_polarity_flip_physical{249}=0x7E +serdes_core_tx_polarity_flip_physical{250}=0x7E +serdes_core_tx_polarity_flip_physical{251}=0x7E +serdes_core_tx_polarity_flip_physical{252}=0x7E +serdes_core_tx_polarity_flip_physical{253}=0x7E +serdes_core_tx_polarity_flip_physical{254}=0x7E +serdes_core_tx_polarity_flip_physical{255}=0x7E +serdes_core_tx_polarity_flip_physical{256}=0x7E + diff --git a/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/port_config.ini b/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/port_config.ini new file mode 100755 index 000000000000..cc8e7cbad5fd --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/port_config.ini @@ -0,0 +1,129 @@ +# name lanes alias index +Ethernet1 5,6 onehundredGigE1 0 +Ethernet2 7,8 onehundredGigE2 1 +Ethernet3 1,2 onehundredGigE3 2 +Ethernet4 3,4 onehundredGigE4 3 +Ethernet5 37,38 onehundredGigE5 4 +Ethernet6 39,40 onehundredGigE6 5 +Ethernet7 33,34 onehundredGigE7 6 +Ethernet8 35,36 onehundredGigE8 7 +Ethernet9 69,70 onehundredGigE9 8 +Ethernet10 71,72 onehundredGigE10 9 +Ethernet11 65,66 onehundredGigE11 10 +Ethernet12 67,68 onehundredGigE12 11 +Ethernet13 101,102 onehundredGigE13 12 +Ethernet14 103,104 onehundredGigE14 13 +Ethernet15 97,98 onehundredGigE15 14 +Ethernet16 99,100 onehundredGigE16 15 +Ethernet17 13,14 onehundredGigE17 16 +Ethernet18 15,16 onehundredGigE18 17 +Ethernet19 9,10 onehundredGigE19 18 +Ethernet20 11,12 onehundredGigE20 19 +Ethernet21 45,46 onehundredGigE21 20 +Ethernet22 47,48 onehundredGigE22 21 +Ethernet23 41,42 onehundredGigE23 22 +Ethernet24 43,44 onehundredGigE24 23 +Ethernet25 77,78 onehundredGigE25 24 +Ethernet26 79,80 onehundredGigE26 25 +Ethernet27 73,74 onehundredGigE27 26 +Ethernet28 75,76 onehundredGigE28 27 +Ethernet29 109,110 onehundredGigE29 28 +Ethernet30 111,112 onehundredGigE30 29 +Ethernet31 105,106 onehundredGigE31 30 +Ethernet32 107,108 onehundredGigE32 31 +Ethernet33 21,22 onehundredGigE33 32 +Ethernet34 23,24 onehundredGigE34 33 +Ethernet35 17,18 onehundredGigE35 34 +Ethernet36 19,20 onehundredGigE36 35 +Ethernet37 53,54 onehundredGigE37 36 +Ethernet38 55,56 onehundredGigE38 37 +Ethernet39 49,50 onehundredGigE39 38 +Ethernet40 51,52 onehundredGigE40 39 +Ethernet41 85,86 onehundredGigE41 40 +Ethernet42 87,88 onehundredGigE42 41 +Ethernet43 81,82 onehundredGigE43 42 +Ethernet44 83,84 onehundredGigE44 43 +Ethernet45 117,118 onehundredGigE45 44 +Ethernet46 119,120 onehundredGigE46 45 +Ethernet47 113,114 onehundredGigE47 46 +Ethernet48 115,116 onehundredGigE48 47 +Ethernet49 29,30 onehundredGigE49 48 +Ethernet50 31,32 onehundredGigE50 49 +Ethernet51 25,26 onehundredGigE51 50 +Ethernet52 27,28 onehundredGigE52 51 +Ethernet53 61,62 onehundredGigE53 52 +Ethernet54 63,64 onehundredGigE54 53 +Ethernet55 57,58 onehundredGigE55 54 +Ethernet56 59,60 onehundredGigE56 55 +Ethernet57 93,94 onehundredGigE57 56 +Ethernet58 95,96 onehundredGigE58 57 +Ethernet59 89,90 onehundredGigE59 58 +Ethernet60 91,92 onehundredGigE60 59 +Ethernet61 125,126 onehundredGigE61 60 +Ethernet62 127,128 onehundredGigE62 61 +Ethernet63 121,122 onehundredGigE63 62 +Ethernet64 123,124 onehundredGigE64 63 +Ethernet65 133,134 onehundredGigE65 64 +Ethernet66 135,136 onehundredGigE66 65 +Ethernet67 129,130 onehundredGigE67 66 +Ethernet68 131,132 onehundredGigE68 67 +Ethernet69 165,166 onehundredGigE69 68 +Ethernet70 167,168 onehundredGigE70 69 +Ethernet71 161,162 onehundredGigE71 70 +Ethernet72 163,164 onehundredGigE72 71 +Ethernet73 197,198 onehundredGigE73 72 +Ethernet74 199,200 onehundredGigE74 73 +Ethernet75 193,194 onehundredGigE75 74 +Ethernet76 195,196 onehundredGigE76 75 +Ethernet77 229,230 onehundredGigE77 76 +Ethernet78 231,232 onehundredGigE78 77 +Ethernet79 225,226 onehundredGigE79 78 +Ethernet80 227,228 onehundredGigE80 79 +Ethernet81 141,142 onehundredGigE81 80 +Ethernet82 143,144 onehundredGigE82 81 +Ethernet83 137,138 onehundredGigE83 82 +Ethernet84 139,140 onehundredGigE84 83 +Ethernet85 173,174 onehundredGigE85 84 +Ethernet86 175,176 onehundredGigE86 85 +Ethernet87 169,170 onehundredGigE87 86 +Ethernet88 171,172 onehundredGigE88 87 +Ethernet89 205,206 onehundredGigE89 88 +Ethernet90 207,208 onehundredGigE90 89 +Ethernet91 201,202 onehundredGigE91 90 +Ethernet92 203,204 onehundredGigE92 91 +Ethernet93 237,238 onehundredGigE93 92 +Ethernet94 239,240 onehundredGigE94 93 +Ethernet95 233,234 onehundredGigE95 94 +Ethernet96 235,236 onehundredGigE96 95 +Ethernet97 149,150 onehundredGigE97 96 +Ethernet98 151,152 onehundredGigE98 97 +Ethernet99 145,146 onehundredGigE99 98 +Ethernet100 147,148 onehundredGigE100 99 +Ethernet101 181,182 onehundredGigE101 100 +Ethernet102 183,184 onehundredGigE102 101 +Ethernet103 177,178 onehundredGigE103 102 +Ethernet104 179,180 onehundredGigE104 103 +Ethernet105 213,214 onehundredGigE105 104 +Ethernet106 215,216 onehundredGigE106 105 +Ethernet107 209,210 onehundredGigE107 106 +Ethernet108 211,212 onehundredGigE108 107 +Ethernet109 245,246 onehundredGigE109 108 +Ethernet110 247,248 onehundredGigE110 109 +Ethernet111 241,242 onehundredGigE111 110 +Ethernet112 243,244 onehundredGigE112 111 +Ethernet113 157,158 onehundredGigE113 112 +Ethernet114 159,160 onehundredGigE114 113 +Ethernet115 153,154 onehundredGigE115 114 +Ethernet116 155,156 onehundredGigE116 115 +Ethernet117 189,190 onehundredGigE117 116 +Ethernet118 191,192 onehundredGigE118 117 +Ethernet119 185,186 onehundredGigE119 118 +Ethernet120 187,188 onehundredGigE120 119 +Ethernet121 221,222 onehundredGigE121 120 +Ethernet122 223,224 onehundredGigE122 121 +Ethernet123 217,218 onehundredGigE123 122 +Ethernet124 219,220 onehundredGigE124 123 +Ethernet125 253,254 onehundredGigE125 124 +Ethernet126 255,256 onehundredGigE126 125 +Ethernet127 249,250 onehundredGigE127 126 +Ethernet128 251,252 onehundredGigE128 127 diff --git a/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/sai.profile b/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/sai.profile new file mode 100755 index 000000000000..f76d1e7424ab --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/Accton-MINIPACK/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/config_16Q_FEC544_EVTB_100G.bcm diff --git a/device/accton/x86_64-accton_minipack-r0/default_sku b/device/accton/x86_64-accton_minipack-r0/default_sku new file mode 100644 index 000000000000..21ede3d5ad55 --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/default_sku @@ -0,0 +1 @@ +Accton-MINIPACK t1 diff --git a/device/accton/x86_64-accton_minipack-r0/installer.conf b/device/accton/x86_64-accton_minipack-r0/installer.conf new file mode 100755 index 000000000000..30392541fade --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=57600 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pcie_aspm=off" diff --git a/device/accton/x86_64-accton_minipack-r0/led_proc_init.soc b/device/accton/x86_64-accton_minipack-r0/led_proc_init.soc new file mode 100755 index 000000000000..6b2aaa764072 --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/led_proc_init.soc @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/device/accton/x86_64-accton_minipack-r0/plugins/eeprom.py b/device/accton/x86_64-accton_minipack-r0/plugins/eeprom.py new file mode 100644 index 000000000000..3912194484db --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/1-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0x200, '', True) diff --git a/device/accton/x86_64-accton_minipack-r0/plugins/led_control.py b/device/accton/x86_64-accton_minipack-r0/plugins/led_control.py new file mode 100755 index 000000000000..a11a31062367 --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/plugins/led_control.py @@ -0,0 +1,55 @@ +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import swsssdk + import threading + import os + import logging + import struct + import time + import syslog + from socket import * + from select import * + from minipack.pimutil import PimUtil +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + SONIC_PORT_NAME_PREFIX = "Ethernet" + + def __init__(self): + pim = PimUtil() + pim.init_pim_fpga() + + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return 1, 4 # port linkup, led is green + else: + return 0, 0 # port linkdown, led is off + + def port_link_state_change(self, portname, state): + pim = PimUtil() + port_idx = self._port_name_to_index(portname) + new_control, led_mode = self._port_state_to_mode(port_idx, state) + color, control = pim.get_port_led(port_idx) + + if color == led_mode: + if control == new_control: + return + + pim.set_port_led(port_idx, led_mode, new_control) # port linkup, led is green + # port linkdown, led is off diff --git a/device/accton/x86_64-accton_minipack-r0/plugins/psuutil.py b/device/accton/x86_64-accton_minipack-r0/plugins/psuutil.py new file mode 100644 index 000000000000..2a8bd232db44 --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/plugins/psuutil.py @@ -0,0 +1,56 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.num = 4 + self.psu_path = "/sys/bus/platform/devices/minipack_psensor/" + self.psu_voltage = "/in{0}_input" + + def get_num_psus(self): + return self.num + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_voltage.format(index*2-1) + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status > 0 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_voltage.format(index*2) + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status > 0 diff --git a/device/accton/x86_64-accton_minipack-r0/plugins/sfputil.py b/device/accton/x86_64-accton_minipack-r0/plugins/sfputil.py new file mode 100755 index 000000000000..85dc5f81f5ac --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/plugins/sfputil.py @@ -0,0 +1,145 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase + import os + import sys + from minipack.pimutil import PimUtil +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 128 + + LOCAL_OOM_PATH = "/usr/local/bin/minipack_qsfp/port%d_eeprom" + + _port_to_is_present = {} + _port_to_lp_mode = {} + + _port_to_eeprom_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 list(range(self.PORT_START, self.PORT_END + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def sfp_map(self, index): + port = index + 1 + base = ((port-1)/8*8) + 10 + index = (port - 1) % 8 + index = 7 - index + if (index % 2): + index = index - 1 + else: + index = index + 1 + bus = base + index + return bus + + def __init__(self): + for x in range(0, self.port_end): + self.port_to_eeprom_mapping[x] = self.LOCAL_OOM_PATH % x + + SfpUtilBase.__init__(self) + pim = PimUtil() + pim.init_pim_fpga() + + def __del__(self): + self.value = 0 + + 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 + + pim = PimUtil() + status = pim.get_qsfp_presence(port_num) + return status + + def get_low_power_mode(self, port_num): + if port_num < self.port_start or port_num > self.port_end: + return False + + pim = PimUtil() + return pim.get_low_power_mode(port_num) + + def set_low_power_mode(self, port_num, lpmode): + if port_num < self.port_start or port_num > self.port_end: + return False + pim = PimUtil() + pim.set_low_power_mode(port_num, lpmode) + return True + + def reset(self, port_num): + if port_num < self.port_start or port_num > self.port_end: + return False + pim = PimUtil() + pim.reset(port_num) + return True + + def get_transceiver_change_event(self, timeout=0): + pim = PimUtil() + start_time = time.time() + port_dict = {} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print('get_transceiver_change_event:' + 'time wrap / invalid timeout value', timeout) + + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + change_status = 0 + port_dict = pim.get_qsfp_interrupt() + present = 0 + for key, value in port_dict.items(): + if value == 1: + present = self.get_presence(key) + change_status = 1 + if present: + port_dict[key] = '1' + else: + port_dict[key] = '0' + + if change_status: + return True, port_dict + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + print("get_evt_change_event: Should not reach here.") + return False, {} diff --git a/device/accton/x86_64-accton_minipack-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_minipack-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..584a14b9d942 --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} + diff --git a/device/accton/x86_64-accton_minipack-r0/sensors.conf b/device/accton/x86_64-accton_minipack-r0/sensors.conf new file mode 100755 index 000000000000..966d2f11ad9a --- /dev/null +++ b/device/accton/x86_64-accton_minipack-r0/sensors.conf @@ -0,0 +1,3 @@ +# libsensors configuration file +# ------------------------------------------------ + diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/port_config.ini b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/port_config.ini new file mode 100644 index 000000000000..745cc69428b4 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 33,34,35,36 Ethernet1/0/1 0 100000 +Ethernet4 37,38,39,40 Ethernet1/0/5 1 100000 +Ethernet8 41,42,43,44 Ethernet1/0/9 2 100000 +Ethernet12 45,46,47,48 Ethernet1/0/13 3 100000 +Ethernet16 49,50,51,52 Ethernet1/0/17 4 100000 +Ethernet20 53,54,55,56 Ethernet1/0/21 5 100000 +Ethernet24 57,58,59,60 Ethernet1/0/25 6 100000 +Ethernet28 61,62,63,64 Ethernet1/0/29 7 100000 +Ethernet32 65,66,67,68 Ethernet1/0/33 8 100000 +Ethernet36 69,70,71,72 Ethernet1/0/37 9 100000 +Ethernet40 73,74,75,76 Ethernet1/0/41 10 100000 +Ethernet44 77,78,79,80 Ethernet1/0/45 11 100000 +Ethernet48 81,82,83,84 Ethernet1/0/49 12 100000 +Ethernet52 85,86,87,88 Ethernet1/0/53 13 100000 +Ethernet56 89,90,91,92 Ethernet1/0/57 14 100000 +Ethernet60 93,94,95,96 Ethernet1/0/61 15 100000 +Ethernet64 97,98,99,100 Ethernet1/0/65 16 100000 +Ethernet68 101,102,103,104 Ethernet1/0/69 17 100000 +Ethernet72 105,106,107,108 Ethernet1/0/73 18 100000 +Ethernet76 109,110,111,112 Ethernet1/0/77 19 100000 +Ethernet80 113,114,115,116 Ethernet1/0/81 20 100000 +Ethernet84 117,118,119,120 Ethernet1/0/85 21 100000 +Ethernet88 121,122,123,124 Ethernet1/0/89 22 100000 +Ethernet92 125,126,127,128 Ethernet1/0/93 23 100000 +Ethernet96 1,2,3,4 Ethernet1/0/97 24 100000 +Ethernet100 5,6,7,8 Ethernet1/0/101 25 100000 +Ethernet104 9,10,11,12 Ethernet1/0/105 26 100000 +Ethernet108 13,14,15,16 Ethernet1/0/109 27 100000 +Ethernet112 17,18,19,20 Ethernet1/0/113 28 100000 +Ethernet116 21,22,23,24 Ethernet1/0/117 29 100000 +Ethernet120 25,26,27,28 Ethernet1/0/121 30 100000 +Ethernet124 29,30,31,32 Ethernet1/0/125 31 100000 \ No newline at end of file diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/sai.profile b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/sai.profile new file mode 100644 index 000000000000..66d99a8450c3 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-snh60a0-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/th-snh60a0-32x100G.config.bcm b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/th-snh60a0-32x100G.config.bcm new file mode 100644 index 000000000000..395827122e16 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/Alphanetworks-SNH60A0-320FV2/th-snh60a0-32x100G.config.bcm @@ -0,0 +1,163 @@ +# This property file is for ZION-320F 100G mode only. +# Zion-320F uses Tomahawk BCM56960 as its mac. Besides, it is phyless. +# Note: The settings in this file are not verified yet. + + + +# Set stat collection interval in microseconds. +# Setting this to 0 will prevent counters from being started. +bcm_stat_interval.0=1000000 + +# Linkscan interval in microseconds. +# If non-zero, bcm_init() will start linkscan +bcm_linkscan_interval.0=450000 + + + +# BCM56960 : MMU Cell Buffer Allocation Profile to support ASF (cut-thru) Forwarding +# 0: No cut-through support +# 1: Similar speed profile (Default) +# 2: Extreme speed profile + +os=unix + + + +# EagleCore ports +#portmap_66=129:10 +#portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +#FalconCore[0 - 7] must map to logical port[1 - 32] +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 +#FalconCore[8 - 15] must map to logical port[34 - 65] +portmap_34=33:100 +portmap_35=37:100 +portmap_36=41:100 +portmap_37=45:100 +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 +#FalconCore[16 - 23] must map to logical port[68 - 99] +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 +#FalconCore[24 - 31] must map to logical port[102 - 133] +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=113:100 +portmap_107=117:100 +portmap_108=121:100 +portmap_109=125:100 + +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe +pbmp_oversubscribe=0x0000000000000000000000000000000000003fc000000ff0000003fc000001fe + + + +#core-0 +xgxs_rx_lane_map_ce0=0x3012 +xgxs_rx_lane_map_ce1=0x1230 +xgxs_rx_lane_map_ce2=0x3012 +xgxs_rx_lane_map_ce3=0x1230 +xgxs_rx_lane_map_ce4=0x1230 +xgxs_rx_lane_map_ce5=0x1230 +xgxs_rx_lane_map_ce6=0x1230 +xgxs_rx_lane_map_ce7=0x1230 + +#core-8 +xgxs_rx_lane_map_ce8=0x1032 +xgxs_rx_lane_map_ce9=0x1230 +xgxs_rx_lane_map_ce10=0x1032 +xgxs_rx_lane_map_ce11=0x1230 +xgxs_rx_lane_map_ce12=0x1230 +xgxs_rx_lane_map_ce13=0x3012 +xgxs_rx_lane_map_ce14=0x1230 +xgxs_rx_lane_map_ce15=0x3012 + +#core-16 +xgxs_rx_lane_map_ce16=0x3012 +xgxs_rx_lane_map_ce17=0x3012 +xgxs_rx_lane_map_ce18=0x1230 +xgxs_rx_lane_map_ce19=0x3012 +xgxs_rx_lane_map_ce20=0x3012 +xgxs_rx_lane_map_ce21=0x3012 +xgxs_rx_lane_map_ce22=0x3012 +xgxs_rx_lane_map_ce23=0x3012 + +#core-24 +xgxs_rx_lane_map_ce24=0x3210 +xgxs_rx_lane_map_ce25=0x3012 +xgxs_rx_lane_map_ce26=0x3210 +xgxs_rx_lane_map_ce27=0x3012 +xgxs_rx_lane_map_ce28=0x3012 +xgxs_rx_lane_map_ce29=0x1230 +xgxs_rx_lane_map_ce30=0x3012 +xgxs_rx_lane_map_ce31=0x3012 + +# +# Remap XGXS tx lanes to desired mapping by hardware provide. +#core-0 +xgxs_tx_lane_map_ce0=0x3210 +xgxs_tx_lane_map_ce1=0x1032 +xgxs_tx_lane_map_ce2=0x3210 +xgxs_tx_lane_map_ce3=0x1032 +xgxs_tx_lane_map_ce4=0x3210 +xgxs_tx_lane_map_ce5=0x3210 +xgxs_tx_lane_map_ce6=0x3210 +xgxs_tx_lane_map_ce7=0x1230 + +#core-8 +xgxs_tx_lane_map_ce8=0x2301 +xgxs_tx_lane_map_ce9=0x3210 +xgxs_tx_lane_map_ce10=0x2301 +xgxs_tx_lane_map_ce11=0x3210 +xgxs_tx_lane_map_ce12=0x0123 +xgxs_tx_lane_map_ce13=0x3210 +xgxs_tx_lane_map_ce14=0x0123 +xgxs_tx_lane_map_ce15=0x3210 + +#core-16 +xgxs_tx_lane_map_ce16=0x2301 +xgxs_tx_lane_map_ce17=0x3210 +xgxs_tx_lane_map_ce18=0x0123 +xgxs_tx_lane_map_ce19=0x1032 +xgxs_tx_lane_map_ce20=0x0123 +xgxs_tx_lane_map_ce21=0x1032 +xgxs_tx_lane_map_ce22=0x0123 +xgxs_tx_lane_map_ce23=0x1032 + +#core-24 +xgxs_tx_lane_map_ce24=0x1032 +xgxs_tx_lane_map_ce25=0x1032 +xgxs_tx_lane_map_ce26=0x1032 +xgxs_tx_lane_map_ce27=0x1032 +xgxs_tx_lane_map_ce28=0x1032 +xgxs_tx_lane_map_ce29=0x1032 +xgxs_tx_lane_map_ce30=0x3210 +xgxs_tx_lane_map_ce31=0x3210 + + + +ptp_ts_pll_fref=25000000 +ptp_bs_fref=25000000 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/default_sku b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/default_sku new file mode 100755 index 000000000000..588c4a951df7 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/default_sku @@ -0,0 +1 @@ +Alphanetworks-SNH60A0-320FV2 t1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/fancontrol b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/fancontrol new file mode 100644 index 000000000000..24184113d2be --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/4-004d/hwmon/hwmon3/temp1_input +FCFANS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan1_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan2_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan3_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan4_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan5_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan6_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan11_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan12_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan13_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan14_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan15_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan16_input +MINTEMP=/sys/bus/i2c/devices/0-005e/fan_pwm=50 +MAXTEMP=/sys/bus/i2c/devices/0-005e/fan_pwm=70 +MINSTART=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MINSTOP=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MINPWM=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MAXPWM=/sys/bus/i2c/devices/0-005e/fan_pwm=200 \ No newline at end of file diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/installer.conf b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/led_proc_init.soc b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/led_proc_init.soc new file mode 100644 index 000000000000..c05dbe3326f9 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/led_proc_init.soc @@ -0,0 +1,45 @@ +# LED microprocessor initialization for alphanetworks snh60a0-320fv2 + +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15 REMAP_PORT_17=14 REMAP_PORT_18=13 REMAP_PORT_19=12 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 REMAP_PORT_25=6 REMAP_PORT_26=5 REMAP_PORT_27=4 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 REMAP_PORT_29=2 REMAP_PORT_30=1 REMAP_PORT_31=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=62 REMAP_PORT_34=61 REMAP_PORT_35=60 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59 REMAP_PORT_37=58 REMAP_PORT_38=57 REMAP_PORT_39=56 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55 REMAP_PORT_41=54 REMAP_PORT_42=53 REMAP_PORT_43=52 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51 REMAP_PORT_45=50 REMAP_PORT_46=49 REMAP_PORT_47=48 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47 REMAP_PORT_49=46 REMAP_PORT_50=45 REMAP_PORT_51=44 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43 REMAP_PORT_53=42 REMAP_PORT_54=41 REMAP_PORT_55=40 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39 REMAP_PORT_57=38 REMAP_PORT_58=37 REMAP_PORT_59=36 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35 REMAP_PORT_61=34 REMAP_PORT_62=33 REMAP_PORT_63=32 + +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 stop +led 0 prog 2A 01 86 FF 06 FF C2 7F 60 FF 02 20 60 FE 67 2E 06 FE F2 04 60 FE D2 40 74 0E 70 1C 02 00 60 FE 67 2E 06 FE F2 04 60 FE D2 20 74 20 70 70 02 A0 F6 FE 04 D2 01 70 39 74 5F 06 FE 28 32 00 32 01 B7 97 71 46 75 4E 06 FF C2 04 74 4E 70 5F 67 76 67 72 67 76 67 76 67 76 67 76 67 76 67 76 57 67 76 67 76 67 76 67 76 67 76 67 76 67 76 67 76 57 3A 80 32 0E 87 57 32 0F 87 57 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 2A 01 86 FF 06 FF C2 7F 60 FF 02 00 60 FE 67 1C 06 FE F2 04 60 FE D2 40 74 0E 70 5E 02 A0 F6 FE 04 D2 01 70 27 74 4D 06 FE 28 32 00 32 01 B7 97 71 34 75 3C 06 FF C2 04 74 3C 70 4D 67 64 67 60 67 64 67 64 67 64 67 64 67 64 67 64 57 67 64 67 64 67 64 67 64 67 64 67 64 67 64 67 64 57 3A 80 32 0E 87 57 32 0F 87 57 +led 1 auto on +led 1 start diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/eeprom.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/eeprom.py new file mode 100644 index 000000000000..9e4e9970e9f5 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0056/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/led_control.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/led_control.py new file mode 100644 index 000000000000..4da72e7f7a04 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/led_control.py @@ -0,0 +1,258 @@ +# Platform-specific LED control functionality for SONiC +# + +# try: +# from sonic_led.led_control_base import LedControlBase +# import swsssdk +# except ImportError as e: +# raise ImportError (str(e) + " - required module not found") + +import time + + +class LedControlBase(object): + # __metaclass__ = abc.ABCMeta + + # @abc.abstractmethod + def port_link_state_change(self, port, state): + """ + Called when port link state changes. Update port link state LED here. + + :param port: A string, SONiC port name (e.shg., "Ethernet0") + :param state: A string, the port link state (either "up" or "down") + """ + return + + +### Zion specified ### +read_fan_fault = 0 +is_fan_all_OK = 0 +read_power_status = 0 +is_power_all_OK = 0 +is_thermal_high = 0 +is_reset_button_push = 0 +########################## + + +def sysled_task(): + while True: + system_led_check() + time.sleep(5) + +### Zion specified ### + + +def system_led_check(): + global read_fan_fault, read_power_status, is_fan_all_OK, is_power_all_OK, is_thermal_high, is_reset_button_push + + is_fan_all_OK = 1 + is_power_all_OK = 0 + is_thermal_high = 0 + is_reset_button_push = 0 + with open("/sys/bus/i2c/devices/1-005e/fan1_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan1_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan2_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan2_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan3_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan3_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan4_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan4_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan5_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan5_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + with open("/sys/bus/i2c/devices/1-005e/fan6_fault", "r") as f1: + read_fan_fault = f1.read() + with open("/sys/bus/i2c/devices/9-005f/fan6_led", "w") as f11: + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + f11.write("4") + else: + f11.write("1") + + with open("/sys/bus/i2c/devices/1-005e/psu1_power_good", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + f11.write("1") + else: + f11.write("4") + with open("/sys/bus/i2c/devices/1-005e/psu1_present", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + f11.write("1") + else: + f11.write("4") + with open("/sys/bus/i2c/devices/1-005e/psu2_power_good", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + f11.write("1") + else: + f11.write("4") + with open("/sys/bus/i2c/devices/1-005e/psu2_present", "r") as f1: + read_power_status = f1.read() + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f11: + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + f11.write("1") + else: + f11.write("4") + + with open("/sys/bus/i2c/devices/9-005f/swi_ctrl", "r") as f5: + is_reset_button_push = f5.read() + if str(is_reset_button_push) == "1\n": + is_reset_button_push = 1 + else: + is_reset_button_push = 0 + + with open("/sys/bus/i2c/devices/4-004d/hwmon/hwmon3/temp1_input", "r") as f3: + is_thermal_high = f3.read() + if int(is_thermal_high) >= 70000: + is_thermal_high = 1 + else: + is_thermal_high = 0 + + with open("/sys/bus/i2c/devices/9-005f/sys_status", "w") as f2: + if is_reset_button_push == 1: + f2.write("3") + elif is_fan_all_OK == 0 or is_power_all_OK == 0 or is_thermal_high == 1: + f2.write("4") + else: + f2.write("1") + + return +########## + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + PORT_TABLE_PREFIX = "PORT_TABLE:" + + SONIC_PORT_NAME_PREFIX = "Ethernet" + + LED_SYSFS_PATH_BREAKOUT_CAPABLE = "/sys/class/leds/qsfp{0}_{1}/brightness" + LED_SYSFS_PATH_NO_BREAKOUT = "/sys/class/leds/qsfp{0}/brightness" + + QSFP_BREAKOUT_START_IDX = 1 + QSFP_BREAKOUT_END_IDX = 24 + QSFP_NO_BREAKOUT_START_IDX = 25 + QSFP_NO_BREAKOUT_END_IDX = 32 + + LED_COLOR_OFF = 0 + LED_COLOR_GREEN = 1 + LED_COLOR_YELLOW = 2 + + # Helper method to map SONiC port name to Arista QSFP index + def _port_name_to_qsfp_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + sonic_port_num = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + swss = swsssdk.SonicV2Connector() + swss.connect(swss.APPL_DB) + + lanes = swss.get( + swss.APPL_DB, self.PORT_TABLE_PREFIX + port_name, 'lanes') + + # SONiC port nums are 0-based and increment by 4 + # Arista QSFP indices are 1-based and increment by 1 + return (((sonic_port_num/4) + 1), sonic_port_num % 4, len(lanes.split(','))) + + # Concrete implementation of port_link_state_change() method + + def port_link_state_change_bk(self, port, state): + qsfp_index, lane_index, lanes = self._port_name_to_qsfp_index(port) + + # Ignore invalid QSFP indices + if qsfp_index <= 0 or lanes <= 0 or lanes > 4: + return + + # QSFP indices 1-24 are breakout-capable and have four LEDs, and each LED indicate one lane. + # whereas indices 25-32 are not breakout-capable, and only have one + if qsfp_index <= self.QSFP_BREAKOUT_END_IDX: + # assuming 40G, then we need to control four lanes + led_sysfs_paths = [self.LED_SYSFS_PATH_BREAKOUT_CAPABLE.format( + qsfp_index, i) for i in range(lane_index + 1, lane_index + 1 + lanes)] + else: + led_sysfs_paths = [ + self.LED_SYSFS_PATH_NO_BREAKOUT.format(qsfp_index)] + + for led_sysfs_path in led_sysfs_paths: + led_file = open(led_sysfs_path, "w") + + if state == "up": + led_file.write("%d" % self.LED_COLOR_GREEN) + else: + led_file.write("%d" % self.LED_COLOR_OFF) + + led_file.close() + + # Constructor + def __init__(self): + # Initialize all front-panel status LEDs to green + with open("/sys/bus/i2c/devices/9-005f/sys_locator", "w") as f: + f.write("0") + with open("/sys/bus/i2c/devices/9-005f/sys_pwr", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/sys_status", "w") as f: + f.write("1") + + # Initialize all fan LEDs to green + with open("/sys/bus/i2c/devices/9-005f/fan1_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan2_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan3_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan4_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan5_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/9-005f/fan6_led", "w") as f: + f.write("1") + sysled_task() + + # Initialize: Turn all front panel QSFP LEDs off + # # for qsfp_index in range(self.QSFP_BREAKOUT_START_IDX, self.QSFP_BREAKOUT_END_IDX + 1): + # # for lane in range(1, 5): + # # led_sysfs_path = self.LED_SYSFS_PATH_BREAKOUT_CAPABLE.format(qsfp_index, lane) + # # with open(led_sysfs_path, 'w') as led_file: + # # led_file.write("%d" % self.LED_COLOR_OFF) + + # # for qsfp_index in range(self.QSFP_NO_BREAKOUT_START_IDX, self.QSFP_NO_BREAKOUT_END_IDX + 1): + # # led_sysfs_path = self.LED_SYSFS_PATH_NO_BREAKOUT.format(qsfp_index) + # # with open(led_sysfs_path, 'w') as led_file: + # # led_file.write("%d" % self.LED_COLOR_OFF) diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/psuutil.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/psuutil.py new file mode 100644 index 000000000000..d189349b5d0e --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/psuutil.py @@ -0,0 +1,65 @@ +############################################################################# +# Alphanetworks +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = { + 1: "/psu1_present", + 2: "/psu2_present", + } + self.psu_oper_status = { + 1: "/psu1_power_good", + 2: "/psu2_power_good", + } + self.psu_mapping = "0-005e" + if not os.path.exists(self.psu_path+self.psu_mapping): + self.psu_mapping = "1-005e" + + def get_num_psus(self): + return len(self.psu_presence) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping+self.psu_oper_status[index] + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping + self.psu_presence[index] + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py new file mode 100644 index 000000000000..09679eed8c3b --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/plugins/sfputil.py @@ -0,0 +1,113 @@ +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + first_port = 0 + last_port = 31 + port_num = 32 + + port_to_eeprom = {} + port_to_i2cbus_mapping = { + 1: 14, + 2: 15, + 3: 16, + 4: 17, + } + + eeprom_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_eeprom" + port_reset_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_port_reset" + present_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_is_present" + + _qsfp_ports = list(range(first_port, port_num + 1)) + + @property + def port_start(self): + return self.first_port + + @property + def port_end(self): + return self.last_port + + @property + def qsfp_ports(self): + return list(range(self.first_port, self.port_num + 1)) + + @property + def port_to_eeprom_mapping(self): + return self.port_to_eeprom + + 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 + + def __init__(self): + path = self.eeprom_path + for x in range(self.first_port, self.last_port + 1): + index = (x % 8) + i2c_index = (x / 8) + 1 + self.port_to_eeprom[x] = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + index = (port_num % 8) + i2c_index = (port_num / 8) + 1 + path = self.port_reset_path + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + + try: + reg_file = open(port_path, 'w') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # reset + reg_file.write('1') + + time.sleep(1) + + 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.first_port or port_num > self.last_port: + return False + + index = (port_num % 8) + i2c_index = (port_num / 8) + 1 + path = self.present_path + port_path = path.format(self.port_to_i2cbus_mapping[i2c_index], (index + 1)) + + try: + reg_file = open(port_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/sensors.conf b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/sensors.conf new file mode 100644 index 000000000000..90562c389f00 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60a0_320fv2-r0/sensors.conf @@ -0,0 +1,17 @@ +# libsensors configuration file for snh60a0_320f +# ------------------------------------------------ + +bus "i2c-1" "SMBus I801 adapter at f000" +chip "goreme_power_cpld-*" + label fan1 "Fan tray 1 front" + label fan2 "Fan tray 2 front" + label fan3 "Fan tray 3 front" + label fan4 "Fan tray 4 front" + label fan5 "Fan tray 5 front" + label fan6 "Fan tray 6 front" + label fan11 "Fan tray 1 rear" + label fan12 "Fan tray 2 rear" + label fan13 "Fan tray 3 rear" + label fan14 "Fan tray 4 rear" + label fan15 "Fan tray 5 rear" + label fan16 "Fan tray 6 rear" diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/port_config.ini b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/port_config.ini new file mode 100644 index 000000000000..d365e18da78e --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 5,6,7,8 Ethernet1/0/1 0 100000 +Ethernet4 9,10,11,12 Ethernet1/0/5 1 100000 +Ethernet8 13,14,15,16 Ethernet1/0/9 2 100000 +Ethernet12 1,2,3,4 Ethernet1/0/13 3 100000 +Ethernet16 21,22,23,24 Ethernet1/0/17 4 100000 +Ethernet20 25,26,27,28 Ethernet1/0/21 5 100000 +Ethernet24 29,30,31,32 Ethernet1/0/25 6 100000 +Ethernet28 17,18,19,20 Ethernet1/0/29 7 100000 +Ethernet32 37,38,39,40 Ethernet1/0/33 8 100000 +Ethernet36 41,42,43,44 Ethernet1/0/37 9 100000 +Ethernet40 45,46,47,48 Ethernet1/0/41 10 100000 +Ethernet44 33,34,35,36 Ethernet1/0/45 11 100000 +Ethernet48 53,54,55,56 Ethernet1/0/49 12 100000 +Ethernet52 57,58,59,60 Ethernet1/0/53 13 100000 +Ethernet56 61,62,63,64 Ethernet1/0/57 14 100000 +Ethernet60 49,50,51,52 Ethernet1/0/61 15 100000 +Ethernet64 69,70,71,72 Ethernet1/0/65 16 100000 +Ethernet68 73,74,75,76 Ethernet1/0/69 17 100000 +Ethernet72 77,78,79,80 Ethernet1/0/73 18 100000 +Ethernet76 65,66,67,68 Ethernet1/0/77 19 100000 +Ethernet80 85,86,87,88 Ethernet1/0/81 20 100000 +Ethernet84 89,90,91,92 Ethernet1/0/85 21 100000 +Ethernet88 93,94,95,96 Ethernet1/0/89 22 100000 +Ethernet92 81,82,83,84 Ethernet1/0/93 23 100000 +Ethernet96 101,102,103,104 Ethernet1/0/97 24 100000 +Ethernet100 105,106,107,108 Ethernet1/0/101 25 100000 +Ethernet104 109,110,111,112 Ethernet1/0/105 26 100000 +Ethernet108 97,98,99,100 Ethernet1/0/109 27 100000 +Ethernet112 117,118,119,120 Ethernet1/0/113 28 100000 +Ethernet116 121,122,123,124 Ethernet1/0/117 29 100000 +Ethernet120 125,126,127,128 Ethernet1/0/121 30 100000 +Ethernet124 113,114,115,116 Ethernet1/0/125 31 100000 +Ethernet128 133,134,135,136 Ethernet1/0/129 32 100000 +Ethernet132 137,138,139,140 Ethernet1/0/133 33 100000 +Ethernet136 141,142,143,144 Ethernet1/0/137 34 100000 +Ethernet140 129,130,131,132 Ethernet1/0/141 35 100000 +Ethernet144 149,150,151,152 Ethernet1/0/145 36 100000 +Ethernet148 153,154,155,156 Ethernet1/0/149 37 100000 +Ethernet152 157,158,159,160 Ethernet1/0/153 38 100000 +Ethernet156 145,146,147,148 Ethernet1/0/157 39 100000 +Ethernet160 165,166,167,168 Ethernet1/0/161 40 100000 +Ethernet164 169,170,171,172 Ethernet1/0/165 41 100000 +Ethernet168 173,174,175,176 Ethernet1/0/169 42 100000 +Ethernet172 161,162,163,164 Ethernet1/0/173 43 100000 +Ethernet176 181,182,183,184 Ethernet1/0/177 44 100000 +Ethernet180 185,186,187,188 Ethernet1/0/181 45 100000 +Ethernet184 189,190,191,192 Ethernet1/0/185 46 100000 +Ethernet188 177,178,179,180 Ethernet1/0/189 47 100000 +Ethernet192 197,198,199,200 Ethernet1/0/193 48 100000 +Ethernet196 201,202,203,204 Ethernet1/0/197 49 100000 +Ethernet200 205,206,207,208 Ethernet1/0/201 50 100000 +Ethernet204 193,194,195,196 Ethernet1/0/205 51 100000 +Ethernet208 213,214,215,216 Ethernet1/0/209 52 100000 +Ethernet212 217,218,219,220 Ethernet1/0/213 53 100000 +Ethernet216 221,222,223,224 Ethernet1/0/217 54 100000 +Ethernet220 209,210,211,212 Ethernet1/0/221 55 100000 +Ethernet224 229,230,231,232 Ethernet1/0/225 56 100000 +Ethernet228 233,234,235,236 Ethernet1/0/229 57 100000 +Ethernet232 237,238,239,240 Ethernet1/0/233 58 100000 +Ethernet236 225,226,227,228 Ethernet1/0/237 59 100000 +Ethernet240 245,246,247,248 Ethernet1/0/241 60 100000 +Ethernet244 249,250,251,252 Ethernet1/0/245 61 100000 +Ethernet248 253,254,255,256 Ethernet1/0/249 62 100000 +Ethernet252 241,242,243,244 Ethernet1/0/253 63 100000 +Ethernet256 257 Ethernet1/0/257 64 10000 +Ethernet260 259 Ethernet1/0/261 65 10000 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/sai.profile b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/sai.profile new file mode 100644 index 000000000000..0abb91695d5d --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-snh60b0-64x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/th2-snh60b0-64x100G.config.bcm b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/th2-snh60b0-64x100G.config.bcm new file mode 100644 index 000000000000..60ca5053b971 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/Alphanetworks-SNH60B0-640F/th2-snh60b0-64x100G.config.bcm @@ -0,0 +1,535 @@ +# This property file is for GOREME-2U 1x100G mode only. +# GOREME-2U uses Tomahawk2 BCM56970 as its mac. Besides, it is phyless. +# Note: The settings in this file are not verified yet. + +os=unix + +bcm_stat_interval.0=1000000 +bcm_linkscan_interval.0=250000 + +# Tuning MDIO_OUTPUT_DELAY as 0xf based on HW RD suggesstion and DVT result. +mdio_output_delay.0=0xf + +# Mode control to select L2 Table DMA mode aka L2MODE_POLL (0) or +# L2MOD_FIFO mechanism aka L2MODE_FIFO (1) for L2 table change notification. +l2xmsg_mode=1 + +# Memory table size configs +l2_mem_entries=40960 +l3_mem_entries=40960 + +portmap_66=257:10 +portmap_100=259:10 + +# Falcon core - front port +# FalconCore[0 - 15] must map to logical port[1-16], PIPE-0. +portmap_1=5:100 +portmap_2=9:100 +portmap_3=13:100 +portmap_4=1:100 +portmap_5=21:100 +portmap_6=25:100 +portmap_7=29:100 +portmap_8=17:100 +portmap_9=37:100 +portmap_10=41:100 +portmap_11=45:100 +portmap_12=33:100 +portmap_13=53:100 +portmap_14=57:100 +portmap_15=61:100 +portmap_16=49:100 + +# FalconCore[16 - 31] must map to logical port[34-49], PIPE-1. +portmap_34=69:100 +portmap_35=73:100 +portmap_36=77:100 +portmap_37=65:100 +portmap_38=85:100 +portmap_39=89:100 +portmap_40=93:100 +portmap_41=81:100 +portmap_42=101:100 +portmap_43=105:100 +portmap_44=109:100 +portmap_45=97:100 +portmap_46=117:100 +portmap_47=121:100 +portmap_48=125:100 +portmap_49=113:100 + +# FalconCore[32 - 47] must map to logical port[68-83], PIPE-2. +portmap_68=133:100 +portmap_69=137:100 +portmap_70=141:100 +portmap_71=129:100 +portmap_72=149:100 +portmap_73=153:100 +portmap_74=157:100 +portmap_75=145:100 +portmap_76=165:100 +portmap_77=169:100 +portmap_78=173:100 +portmap_79=161:100 +portmap_80=181:100 +portmap_81=185:100 +portmap_82=189:100 +portmap_83=177:100 + +# FalconCore[48 - 63] must map to logical port[102-117], PIPE-3. +portmap_102=197:100 +portmap_103=201:100 +portmap_104=205:100 +portmap_105=193:100 +portmap_106=213:100 +portmap_107=217:100 +portmap_108=221:100 +portmap_109=209:100 +portmap_110=229:100 +portmap_111=233:100 +portmap_112=237:100 +portmap_113=225:100 +portmap_114=245:100 +portmap_115=249:100 +portmap_116=253:100 +portmap_117=241:100 + +# Configure all front port as CE ports. +pbmp_xport_xe=0x00000000000000000000000000000000003fffd0000ffff40003fffc0001fffe + +# Oversubscription mode +# +# Refers to a switch being configured such that the I/O bandwidth is greater than the +# core bandwidth. +# BCM56970 device supports a maximum I/O bandwidth of 6,400 Gbps when the average packet size +# is greater than 250 bytes. +pbmp_oversubscribe=0x00000000000000000000000000000000003fffc0000ffff00003fffc0001fffe + + + +# core-0~7 +xgxs_rx_lane_map_ce0=0x0213 +xgxs_rx_lane_map_ce1=0x3102 +xgxs_rx_lane_map_ce2=0x1032 +xgxs_rx_lane_map_ce3=0x2103 +xgxs_rx_lane_map_ce4=0x0213 +xgxs_rx_lane_map_ce5=0x2103 +xgxs_rx_lane_map_ce6=0x1230 +xgxs_rx_lane_map_ce7=0x3120 + +# core-8~15 +xgxs_rx_lane_map_ce8=0x0123 +xgxs_rx_lane_map_ce9=0x3102 +xgxs_rx_lane_map_ce10=0x1230 +xgxs_rx_lane_map_ce11=0x0123 +xgxs_rx_lane_map_ce12=0x0123 +xgxs_rx_lane_map_ce13=0X1230 +xgxs_rx_lane_map_ce14=0x1230 +xgxs_rx_lane_map_ce15=0x0123 + +# core-16~23 +xgxs_rx_lane_map_ce16=0x0123 +xgxs_rx_lane_map_ce17=0x1230 +xgxs_rx_lane_map_ce18=0x1230 +xgxs_rx_lane_map_ce19=0x0123 +xgxs_rx_lane_map_ce20=0x0123 +xgxs_rx_lane_map_ce21=0x1230 +xgxs_rx_lane_map_ce22=0x1230 +xgxs_rx_lane_map_ce23=0x0123 + +# core-24~31 +xgxs_rx_lane_map_ce24=0x0123 +xgxs_rx_lane_map_ce25=0x0231 +xgxs_rx_lane_map_ce26=0x2130 +xgxs_rx_lane_map_ce27=0x2103 +xgxs_rx_lane_map_ce28=0x3012 +xgxs_rx_lane_map_ce29=0x3102 +xgxs_rx_lane_map_ce30=0x1032 +xgxs_rx_lane_map_ce31=0x2103 + +# core-32~39 +xgxs_rx_lane_map_ce32=0x3102 +xgxs_rx_lane_map_ce33=0x3102 +xgxs_rx_lane_map_ce34=0x0132 +xgxs_rx_lane_map_ce35=0x3021 +xgxs_rx_lane_map_ce36=0x0213 +xgxs_rx_lane_map_ce37=0x3012 +xgxs_rx_lane_map_ce38=0x2130 +xgxs_rx_lane_map_ce39=0x0123 + +# core-40~47 +xgxs_rx_lane_map_ce40=0x0312 +xgxs_rx_lane_map_ce41=0x0132 +xgxs_rx_lane_map_ce42=0x1230 +xgxs_rx_lane_map_ce43=0x0123 +xgxs_rx_lane_map_ce44=0x0312 +xgxs_rx_lane_map_ce45=0x0132 +xgxs_rx_lane_map_ce46=0x1230 +xgxs_rx_lane_map_ce47=0x0123 + +# core-48~55 +xgxs_rx_lane_map_ce48=0x0123 +xgxs_rx_lane_map_ce49=0x0132 +xgxs_rx_lane_map_ce50=0x1230 +xgxs_rx_lane_map_ce51=0x0123 +xgxs_rx_lane_map_ce52=0x0312 +xgxs_rx_lane_map_ce53=0x0132 +xgxs_rx_lane_map_ce54=0x1230 +xgxs_rx_lane_map_ce55=0x0123 + +# core-56~63 +xgxs_rx_lane_map_ce56=0x0123 +xgxs_rx_lane_map_ce57=0x0312 +xgxs_rx_lane_map_ce58=0x1032 +xgxs_rx_lane_map_ce59=0x2103 +xgxs_rx_lane_map_ce60=0x2103 +xgxs_rx_lane_map_ce61=0x3120 +xgxs_rx_lane_map_ce62=0x1032 +xgxs_rx_lane_map_ce63=0x0213 + +# Remap XGXS tx lanes to desired mapping by hardware provide. +#core-0~7 +xgxs_tx_lane_map_ce0=0x2301 +xgxs_tx_lane_map_ce1=0x2301 +xgxs_tx_lane_map_ce2=0x1302 +xgxs_tx_lane_map_ce3=0x3210 +xgxs_tx_lane_map_ce4=0x2301 +xgxs_tx_lane_map_ce5=0x2301 +xgxs_tx_lane_map_ce6=0x0213 +xgxs_tx_lane_map_ce7=0x3210 + +#core-8~15 +xgxs_tx_lane_map_ce8=0x1230 +xgxs_tx_lane_map_ce9=0x2301 +xgxs_tx_lane_map_ce10=0x0231 +xgxs_tx_lane_map_ce11=0x1230 +xgxs_tx_lane_map_ce12=0x3102 +xgxs_tx_lane_map_ce13=0x2301 +xgxs_tx_lane_map_ce14=0x0231 +xgxs_tx_lane_map_ce15=0x1230 + +#core-16~23 +xgxs_tx_lane_map_ce16=0x3102 +xgxs_tx_lane_map_ce17=0x2301 +xgxs_tx_lane_map_ce18=0x0231 +xgxs_tx_lane_map_ce19=0x1230 +xgxs_tx_lane_map_ce20=0x3102 +xgxs_tx_lane_map_ce21=0x2301 +xgxs_tx_lane_map_ce22=0x0231 +xgxs_tx_lane_map_ce23=0x1230 + +#core-24~31 +xgxs_tx_lane_map_ce24=0x3102 +xgxs_tx_lane_map_ce25=0x2301 +xgxs_tx_lane_map_ce26=0x0321 +xgxs_tx_lane_map_ce27=0x3210 +xgxs_tx_lane_map_ce28=0x1302 +xgxs_tx_lane_map_ce29=0x2031 +xgxs_tx_lane_map_ce30=0x3120 +xgxs_tx_lane_map_ce31=0x3210 + +#core-32~39 +xgxs_tx_lane_map_ce32=0x2310 +xgxs_tx_lane_map_ce33=0x2301 +xgxs_tx_lane_map_ce34=0x1203 +xgxs_tx_lane_map_ce35=0x1032 +xgxs_tx_lane_map_ce36=0x2130 +xgxs_tx_lane_map_ce37=0x2301 +xgxs_tx_lane_map_ce38=0x1302 +xgxs_tx_lane_map_ce39=0x3210 + +#core-40~47 +xgxs_tx_lane_map_ce40=0x3201 +xgxs_tx_lane_map_ce41=0x0231 +xgxs_tx_lane_map_ce42=0x1203 +xgxs_tx_lane_map_ce43=0x1230 +xgxs_tx_lane_map_ce44=0x3201 +xgxs_tx_lane_map_ce45=0x0231 +xgxs_tx_lane_map_ce46=0x1203 +xgxs_tx_lane_map_ce47=0x3210 + +#core-48~55 +xgxs_tx_lane_map_ce48=0x3201 +xgxs_tx_lane_map_ce49=0x0231 +xgxs_tx_lane_map_ce50=0x1203 +xgxs_tx_lane_map_ce51=0x3210 +xgxs_tx_lane_map_ce52=0x3201 +xgxs_tx_lane_map_ce53=0x0231 +xgxs_tx_lane_map_ce54=0x1203 +xgxs_tx_lane_map_ce55=0x3210 + +#core-56~63 +xgxs_tx_lane_map_ce56=0x1203 +xgxs_tx_lane_map_ce57=0x2301 +xgxs_tx_lane_map_ce58=0x0213 +xgxs_tx_lane_map_ce59=0x3210 +xgxs_tx_lane_map_ce60=0x0213 +xgxs_tx_lane_map_ce61=0x3021 +xgxs_tx_lane_map_ce62=0x3210 +xgxs_tx_lane_map_ce63=0x3210 + +serdes_preemphasis_lane0_ce0=0x0c5800 +serdes_preemphasis_lane1_ce0=0x0c5800 +serdes_preemphasis_lane2_ce0=0x0c5800 +serdes_preemphasis_lane3_ce0=0x0c5800 +serdes_preemphasis_lane0_ce1=0x0c5800 +serdes_preemphasis_lane1_ce1=0x0c5800 +serdes_preemphasis_lane2_ce1=0x0c5800 +serdes_preemphasis_lane3_ce1=0x0c5800 +serdes_preemphasis_lane0_ce2=0x0c5800 +serdes_preemphasis_lane1_ce2=0x0c5800 +serdes_preemphasis_lane2_ce2=0x0c5800 +serdes_preemphasis_lane3_ce2=0x0c5800 +serdes_preemphasis_lane0_ce3=0x0c5800 +serdes_preemphasis_lane1_ce3=0x0c5800 +serdes_preemphasis_lane2_ce3=0x0c5800 +serdes_preemphasis_lane3_ce3=0x0c5800 +serdes_preemphasis_lane0_ce4=0x0c5800 +serdes_preemphasis_lane1_ce4=0x0c5800 +serdes_preemphasis_lane2_ce4=0x0c5800 +serdes_preemphasis_lane3_ce4=0x0c5800 +serdes_preemphasis_lane0_ce5=0x0c5800 +serdes_preemphasis_lane1_ce5=0x0c5800 +serdes_preemphasis_lane2_ce5=0x0c5800 +serdes_preemphasis_lane3_ce5=0x0c5800 +serdes_preemphasis_lane0_ce6=0x0c5800 +serdes_preemphasis_lane1_ce6=0x0c5800 +serdes_preemphasis_lane2_ce6=0x0c5800 +serdes_preemphasis_lane3_ce6=0x0c5800 +serdes_preemphasis_lane0_ce7=0x0c5800 +serdes_preemphasis_lane1_ce7=0x0c5800 +serdes_preemphasis_lane2_ce7=0x0c5800 +serdes_preemphasis_lane3_ce7=0x0c5800 +serdes_preemphasis_lane0_ce8=0x0c5800 +serdes_preemphasis_lane1_ce8=0x0c5800 +serdes_preemphasis_lane2_ce8=0x0c5800 +serdes_preemphasis_lane3_ce8=0x0c5800 +serdes_preemphasis_lane0_ce9=0x0c5800 +serdes_preemphasis_lane1_ce9=0x0c5800 +serdes_preemphasis_lane2_ce9=0x0c5800 +serdes_preemphasis_lane3_ce9=0x0c5800 +serdes_preemphasis_lane0_ce10=0x0c5800 +serdes_preemphasis_lane1_ce10=0x0c5800 +serdes_preemphasis_lane2_ce10=0x0c5800 +serdes_preemphasis_lane3_ce10=0x0c5800 +serdes_preemphasis_lane0_ce11=0x0c5800 +serdes_preemphasis_lane1_ce11=0x0c5800 +serdes_preemphasis_lane2_ce11=0x0c5800 +serdes_preemphasis_lane3_ce11=0x0c5800 +serdes_preemphasis_lane0_ce12=0x0c5800 +serdes_preemphasis_lane1_ce12=0x0c5800 +serdes_preemphasis_lane2_ce12=0x0c5800 +serdes_preemphasis_lane3_ce12=0x0c5800 +serdes_preemphasis_lane0_ce13=0x0c5800 +serdes_preemphasis_lane1_ce13=0x0c5800 +serdes_preemphasis_lane2_ce13=0x0c5800 +serdes_preemphasis_lane3_ce13=0x0c5800 +serdes_preemphasis_lane0_ce14=0x0c5800 +serdes_preemphasis_lane1_ce14=0x0c5800 +serdes_preemphasis_lane2_ce14=0x0c5800 +serdes_preemphasis_lane3_ce14=0x0c5800 +serdes_preemphasis_lane0_ce15=0x0c5800 +serdes_preemphasis_lane1_ce15=0x0c5800 +serdes_preemphasis_lane2_ce15=0x0c5800 +serdes_preemphasis_lane3_ce15=0x0c5800 +serdes_preemphasis_lane0_ce16=0x085408 +serdes_preemphasis_lane1_ce16=0x085408 +serdes_preemphasis_lane2_ce16=0x085408 +serdes_preemphasis_lane3_ce16=0x085408 +serdes_preemphasis_lane0_ce17=0x085408 +serdes_preemphasis_lane1_ce17=0x085408 +serdes_preemphasis_lane2_ce17=0x085408 +serdes_preemphasis_lane3_ce17=0x085408 +serdes_preemphasis_lane0_ce18=0x085408 +serdes_preemphasis_lane1_ce18=0x085408 +serdes_preemphasis_lane2_ce18=0x085408 +serdes_preemphasis_lane3_ce18=0x085408 +serdes_preemphasis_lane0_ce19=0x085408 +serdes_preemphasis_lane1_ce19=0x085408 +serdes_preemphasis_lane2_ce19=0x085408 +serdes_preemphasis_lane3_ce19=0x085408 +serdes_preemphasis_lane0_ce20=0x085408 +serdes_preemphasis_lane1_ce20=0x085408 +serdes_preemphasis_lane2_ce20=0x085408 +serdes_preemphasis_lane3_ce20=0x085408 +serdes_preemphasis_lane0_ce21=0x085408 +serdes_preemphasis_lane1_ce21=0x085408 +serdes_preemphasis_lane2_ce21=0x085408 +serdes_preemphasis_lane3_ce21=0x085408 +serdes_preemphasis_lane0_ce22=0x085408 +serdes_preemphasis_lane1_ce22=0x085408 +serdes_preemphasis_lane2_ce22=0x085408 +serdes_preemphasis_lane3_ce22=0x085408 +serdes_preemphasis_lane0_ce23=0x085408 +serdes_preemphasis_lane1_ce23=0x085408 +serdes_preemphasis_lane2_ce23=0x085408 +serdes_preemphasis_lane3_ce23=0x085408 +serdes_preemphasis_lane0_ce24=0x085408 +serdes_preemphasis_lane1_ce24=0x085408 +serdes_preemphasis_lane2_ce24=0x085408 +serdes_preemphasis_lane3_ce24=0x085408 +serdes_preemphasis_lane0_ce25=0x085408 +serdes_preemphasis_lane1_ce25=0x085408 +serdes_preemphasis_lane2_ce25=0x085408 +serdes_preemphasis_lane3_ce25=0x085408 +serdes_preemphasis_lane0_ce26=0x0a500a +serdes_preemphasis_lane1_ce26=0x0a500a +serdes_preemphasis_lane2_ce26=0x0a500a +serdes_preemphasis_lane3_ce26=0x0a500a +serdes_preemphasis_lane0_ce27=0x0a500a +serdes_preemphasis_lane1_ce27=0x0a500a +serdes_preemphasis_lane2_ce27=0x0a500a +serdes_preemphasis_lane3_ce27=0x0a500a +serdes_preemphasis_lane0_ce28=0x0a500a +serdes_preemphasis_lane1_ce28=0x0a500a +serdes_preemphasis_lane2_ce28=0x0a500a +serdes_preemphasis_lane3_ce28=0x0a500a +serdes_preemphasis_lane0_ce29=0x0a500a +serdes_preemphasis_lane1_ce29=0x0a500a +serdes_preemphasis_lane2_ce29=0x0a500a +serdes_preemphasis_lane3_ce29=0x0a500a +serdes_preemphasis_lane0_ce30=0x0a500a +serdes_preemphasis_lane1_ce30=0x0a500a +serdes_preemphasis_lane2_ce30=0x0a500a +serdes_preemphasis_lane3_ce30=0x0a500a +serdes_preemphasis_lane0_ce31=0x0a500a +serdes_preemphasis_lane1_ce31=0x0a500a +serdes_preemphasis_lane2_ce31=0x0a500a +serdes_preemphasis_lane3_ce31=0x0a500a +serdes_preemphasis_lane0_ce32=0x0a500a +serdes_preemphasis_lane1_ce32=0x0a500a +serdes_preemphasis_lane2_ce32=0x0a500a +serdes_preemphasis_lane3_ce32=0x0a500a +serdes_preemphasis_lane0_ce33=0x0a500a +serdes_preemphasis_lane1_ce33=0x0a500a +serdes_preemphasis_lane2_ce33=0x0a500a +serdes_preemphasis_lane3_ce33=0x0a500a +serdes_preemphasis_lane0_ce34=0x0a500a +serdes_preemphasis_lane1_ce34=0x0a500a +serdes_preemphasis_lane2_ce34=0x0a500a +serdes_preemphasis_lane3_ce34=0x0a500a +serdes_preemphasis_lane0_ce35=0x0a500a +serdes_preemphasis_lane1_ce35=0x0a500a +serdes_preemphasis_lane2_ce35=0x0a500a +serdes_preemphasis_lane3_ce35=0x0a500a +serdes_preemphasis_lane0_ce36=0x0a500a +serdes_preemphasis_lane1_ce36=0x0a500a +serdes_preemphasis_lane2_ce36=0x0a500a +serdes_preemphasis_lane3_ce36=0x0a500a +serdes_preemphasis_lane0_ce37=0x0a500a +serdes_preemphasis_lane1_ce37=0x0a500a +serdes_preemphasis_lane2_ce37=0x0a500a +serdes_preemphasis_lane3_ce37=0x0a500a +serdes_preemphasis_lane0_ce38=0x0a500a +serdes_preemphasis_lane1_ce38=0x0a500a +serdes_preemphasis_lane2_ce38=0x0a500a +serdes_preemphasis_lane3_ce38=0x0a500a +serdes_preemphasis_lane0_ce39=0x0a500a +serdes_preemphasis_lane1_ce39=0x0a500a +serdes_preemphasis_lane2_ce39=0x0a500a +serdes_preemphasis_lane3_ce39=0x0a500a +serdes_preemphasis_lane0_ce40=0x085408 +serdes_preemphasis_lane1_ce40=0x085408 +serdes_preemphasis_lane2_ce40=0x085408 +serdes_preemphasis_lane3_ce40=0x085408 +serdes_preemphasis_lane0_ce41=0x085408 +serdes_preemphasis_lane1_ce41=0x085408 +serdes_preemphasis_lane2_ce41=0x085408 +serdes_preemphasis_lane3_ce41=0x085408 +serdes_preemphasis_lane0_ce42=0x085408 +serdes_preemphasis_lane1_ce42=0x085408 +serdes_preemphasis_lane2_ce42=0x085408 +serdes_preemphasis_lane3_ce42=0x085408 +serdes_preemphasis_lane0_ce43=0x085408 +serdes_preemphasis_lane1_ce43=0x085408 +serdes_preemphasis_lane2_ce43=0x085408 +serdes_preemphasis_lane3_ce43=0x085408 +serdes_preemphasis_lane0_ce44=0x085408 +serdes_preemphasis_lane1_ce44=0x085408 +serdes_preemphasis_lane2_ce44=0x085408 +serdes_preemphasis_lane3_ce44=0x085408 +serdes_preemphasis_lane0_ce45=0x085408 +serdes_preemphasis_lane1_ce45=0x085408 +serdes_preemphasis_lane2_ce45=0x085408 +serdes_preemphasis_lane3_ce45=0x085408 +serdes_preemphasis_lane0_ce46=0x085408 +serdes_preemphasis_lane1_ce46=0x085408 +serdes_preemphasis_lane2_ce46=0x085408 +serdes_preemphasis_lane3_ce46=0x085408 +serdes_preemphasis_lane0_ce47=0x085408 +serdes_preemphasis_lane1_ce47=0x085408 +serdes_preemphasis_lane2_ce47=0x085408 +serdes_preemphasis_lane3_ce47=0x085408 +serdes_preemphasis_lane0_ce48=0x085408 +serdes_preemphasis_lane1_ce48=0x085408 +serdes_preemphasis_lane2_ce48=0x085408 +serdes_preemphasis_lane3_ce48=0x085408 +serdes_preemphasis_lane0_ce49=0x085408 +serdes_preemphasis_lane1_ce49=0x085408 +serdes_preemphasis_lane2_ce49=0x085408 +serdes_preemphasis_lane3_ce49=0x085408 +serdes_preemphasis_lane0_ce50=0x085408 +serdes_preemphasis_lane1_ce50=0x085408 +serdes_preemphasis_lane2_ce50=0x085408 +serdes_preemphasis_lane3_ce50=0x085408 +serdes_preemphasis_lane0_ce51=0x085408 +serdes_preemphasis_lane1_ce51=0x085408 +serdes_preemphasis_lane2_ce51=0x085408 +serdes_preemphasis_lane3_ce51=0x085408 +serdes_preemphasis_lane0_ce52=0x085408 +serdes_preemphasis_lane1_ce52=0x085408 +serdes_preemphasis_lane2_ce52=0x085408 +serdes_preemphasis_lane3_ce52=0x085408 +serdes_preemphasis_lane0_ce53=0x085408 +serdes_preemphasis_lane1_ce53=0x085408 +serdes_preemphasis_lane2_ce53=0x085408 +serdes_preemphasis_lane3_ce53=0x085408 +serdes_preemphasis_lane0_ce54=0x085408 +serdes_preemphasis_lane1_ce54=0x085408 +serdes_preemphasis_lane2_ce54=0x085408 +serdes_preemphasis_lane3_ce54=0x085408 +serdes_preemphasis_lane0_ce55=0x085408 +serdes_preemphasis_lane1_ce55=0x085408 +serdes_preemphasis_lane2_ce55=0x085408 +serdes_preemphasis_lane3_ce55=0x085408 +serdes_preemphasis_lane0_ce56=0x0c5800 +serdes_preemphasis_lane1_ce56=0x0c5800 +serdes_preemphasis_lane2_ce56=0x0c5800 +serdes_preemphasis_lane3_ce56=0x0c5800 +serdes_preemphasis_lane0_ce57=0x0c5800 +serdes_preemphasis_lane1_ce57=0x0c5800 +serdes_preemphasis_lane2_ce57=0x0c5800 +serdes_preemphasis_lane3_ce57=0x0c5800 +serdes_preemphasis_lane0_ce58=0x0c5800 +serdes_preemphasis_lane1_ce58=0x0c5800 +serdes_preemphasis_lane2_ce58=0x0c5800 +serdes_preemphasis_lane3_ce58=0x0c5800 +serdes_preemphasis_lane0_ce59=0x0c5800 +serdes_preemphasis_lane1_ce59=0x0c5800 +serdes_preemphasis_lane2_ce59=0x0c5800 +serdes_preemphasis_lane3_ce59=0x0c5800 +serdes_preemphasis_lane0_ce60=0x0c5800 +serdes_preemphasis_lane1_ce60=0x0c5800 +serdes_preemphasis_lane2_ce60=0x0c5800 +serdes_preemphasis_lane3_ce60=0x0c5800 +serdes_preemphasis_lane0_ce61=0x0c5800 +serdes_preemphasis_lane1_ce61=0x0c5800 +serdes_preemphasis_lane2_ce61=0x0c5800 +serdes_preemphasis_lane3_ce61=0x0c5800 +serdes_preemphasis_lane0_ce62=0x0c5800 +serdes_preemphasis_lane1_ce62=0x0c5800 +serdes_preemphasis_lane2_ce62=0x0c5800 +serdes_preemphasis_lane3_ce62=0x0c5800 +serdes_preemphasis_lane0_ce63=0x0c5800 +serdes_preemphasis_lane1_ce63=0x0c5800 +serdes_preemphasis_lane2_ce63=0x0c5800 +serdes_preemphasis_lane3_ce63=0x0c5800 + +# # The TX and RX polarity flip variable. +# # It is affected by lane swapping, we used to debug for TE QSFP28 transceiver. +# # + +# # Used to select the reference clock for Timestamping and BroadSync/10Mhz PLL value. +# # 25MHz LVPECL to BS_PLL0_REFCLK, BS_PLL1_REFCLK, and TS_PLL_REFCLK +# ptp_ts_pll_fref=25000000 +# ptp_bs_fref=25000000 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/default_sku b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/default_sku new file mode 100755 index 000000000000..e262bc70c380 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/default_sku @@ -0,0 +1 @@ +Alphanetworks-SNH60B0-640F t1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/fancontrol b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/fancontrol new file mode 100644 index 000000000000..9d443b3d3e61 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +FCTEMPS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/3-004d/hwmon/hwmon2/temp1_input +FCFANS=/sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan1_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan2_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan3_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan4_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan11_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan12_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan13_input /sys/bus/i2c/devices/0-005e/fan_pwm=/sys/bus/i2c/devices/0-005e/fan14_input +MINTEMP=/sys/bus/i2c/devices/0-005e/fan_pwm=50 +MAXTEMP=/sys/bus/i2c/devices/0-005e/fan_pwm=70 +MINSTART=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MINSTOP=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MINPWM=/sys/bus/i2c/devices/0-005e/fan_pwm=100 +MAXPWM=/sys/bus/i2c/devices/0-005e/fan_pwm=200 \ No newline at end of file diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/installer.conf b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/led_proc_init.soc b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/led_proc_init.soc new file mode 100644 index 000000000000..3fa944a9faba --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/led_proc_init.soc @@ -0,0 +1,111 @@ +# LED microprocessor initialization for alphanetworks snh60b0-640f + +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0x3f REMAP_PORT_1=0x3e REMAP_PORT_2=0x3d REMAP_PORT_3=0x3c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=0x3b REMAP_PORT_5=0x3a REMAP_PORT_6=0x39 REMAP_PORT_7=0x38 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0x37 REMAP_PORT_9=0x36 REMAP_PORT_10=0x35 REMAP_PORT_11=0x34 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0x33 REMAP_PORT_13=0x32 REMAP_PORT_14=0x31 REMAP_PORT_15=0x30 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x2f REMAP_PORT_17=0x2e REMAP_PORT_18=0x2d REMAP_PORT_19=0x2c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x2b REMAP_PORT_21=0x2a REMAP_PORT_22=0x29 REMAP_PORT_23=0x28 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x27 REMAP_PORT_25=0x26 REMAP_PORT_26=0x25 REMAP_PORT_27=0x24 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x23 REMAP_PORT_29=0x22 REMAP_PORT_30=0x21 REMAP_PORT_31=0x20 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x1f REMAP_PORT_33=0x1e REMAP_PORT_34=0x1d REMAP_PORT_35=0x1c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x1b REMAP_PORT_37=0x1a REMAP_PORT_38=0x19 REMAP_PORT_39=0x18 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x17 REMAP_PORT_41=0x16 REMAP_PORT_42=0x15 REMAP_PORT_43=0x14 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x13 REMAP_PORT_45=0x12 REMAP_PORT_46=0x11 REMAP_PORT_47=0x10 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0xf REMAP_PORT_49=0xe REMAP_PORT_50=0xd REMAP_PORT_51=0xc +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0xb REMAP_PORT_53=0xa REMAP_PORT_54=9 REMAP_PORT_55=8 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0xb REMAP_PORT_9=0xa REMAP_PORT_10=9 REMAP_PORT_11=8 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0xf REMAP_PORT_13=0xe REMAP_PORT_14=0xd REMAP_PORT_15=0xc +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x13 REMAP_PORT_17=0x12 REMAP_PORT_18=0x11 REMAP_PORT_19=0x10 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x17 REMAP_PORT_21=0x16 REMAP_PORT_22=0x15 REMAP_PORT_23=0x14 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x1b REMAP_PORT_25=0x1a REMAP_PORT_26=0x19 REMAP_PORT_27=0x18 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x1f REMAP_PORT_29=0x1e REMAP_PORT_30=0x1d REMAP_PORT_31=0x1c +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x23 REMAP_PORT_33=0x22 REMAP_PORT_34=0x21 REMAP_PORT_35=0x20 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x27 REMAP_PORT_37=0x26 REMAP_PORT_38=0x25 REMAP_PORT_39=0x24 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x2b REMAP_PORT_41=0x2a REMAP_PORT_42=0x29 REMAP_PORT_43=0x28 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x2f REMAP_PORT_45=0x2e REMAP_PORT_46=0x2d REMAP_PORT_47=0x2c +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0x33 REMAP_PORT_49=0x32 REMAP_PORT_50=0x31 REMAP_PORT_51=0x30 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0x37 REMAP_PORT_53=0x36 REMAP_PORT_54=0x35 REMAP_PORT_55=0x34 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=0x3b REMAP_PORT_57=0x3a REMAP_PORT_58=0x39 REMAP_PORT_59=0x38 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=0x3f REMAP_PORT_61=0x3e REMAP_PORT_62=0x3d REMAP_PORT_63=0x3c + +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0x3f REMAP_PORT_1=0x3e REMAP_PORT_2=0x3d REMAP_PORT_3=0x3c +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=0x3b REMAP_PORT_5=0x3a REMAP_PORT_6=0x39 REMAP_PORT_7=0x38 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0x37 REMAP_PORT_9=0x36 REMAP_PORT_10=0x35 REMAP_PORT_11=0x34 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0x33 REMAP_PORT_13=0x32 REMAP_PORT_14=0x31 REMAP_PORT_15=0x30 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x2f REMAP_PORT_17=0x2e REMAP_PORT_18=0x2d REMAP_PORT_19=0x2c +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x2b REMAP_PORT_21=0x2a REMAP_PORT_22=0x29 REMAP_PORT_23=0x28 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x27 REMAP_PORT_25=0x26 REMAP_PORT_26=0x25 REMAP_PORT_27=0x24 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x23 REMAP_PORT_29=0x22 REMAP_PORT_30=0x21 REMAP_PORT_31=0x20 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x1f REMAP_PORT_33=0x1e REMAP_PORT_34=0x1d REMAP_PORT_35=0x1c +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x1b REMAP_PORT_37=0x1a REMAP_PORT_38=0x19 REMAP_PORT_39=0x18 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x17 REMAP_PORT_41=0x16 REMAP_PORT_42=0x15 REMAP_PORT_43=0x14 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x13 REMAP_PORT_45=0x12 REMAP_PORT_46=0x11 REMAP_PORT_47=0x10 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0xf REMAP_PORT_49=0xe REMAP_PORT_50=0xd REMAP_PORT_51=0xc +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0xb REMAP_PORT_53=0xa REMAP_PORT_54=9 REMAP_PORT_55=8 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0xb REMAP_PORT_9=0xa REMAP_PORT_10=9 REMAP_PORT_11=8 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0xf REMAP_PORT_13=0xe REMAP_PORT_14=0xd REMAP_PORT_15=0xc +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x13 REMAP_PORT_17=0x12 REMAP_PORT_18=0x11 REMAP_PORT_19=0x10 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x17 REMAP_PORT_21=0x16 REMAP_PORT_22=0x15 REMAP_PORT_23=0x14 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x1b REMAP_PORT_25=0x1a REMAP_PORT_26=0x19 REMAP_PORT_27=0x18 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x1f REMAP_PORT_29=0x1e REMAP_PORT_30=0x1d REMAP_PORT_31=0x1c +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x23 REMAP_PORT_33=0x22 REMAP_PORT_34=0x21 REMAP_PORT_35=0x20 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x27 REMAP_PORT_37=0x26 REMAP_PORT_38=0x25 REMAP_PORT_39=0x24 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x2b REMAP_PORT_41=0x2a REMAP_PORT_42=0x29 REMAP_PORT_43=0x28 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x2f REMAP_PORT_45=0x2e REMAP_PORT_46=0x2d REMAP_PORT_47=0x2c +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0x33 REMAP_PORT_49=0x32 REMAP_PORT_50=0x31 REMAP_PORT_51=0x30 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0x37 REMAP_PORT_53=0x36 REMAP_PORT_54=0x35 REMAP_PORT_55=0x34 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=0x3b REMAP_PORT_57=0x3a REMAP_PORT_58=0x39 REMAP_PORT_59=0x38 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=0x3f REMAP_PORT_61=0x3e REMAP_PORT_62=0x3d REMAP_PORT_63=0x3c + +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0x3f REMAP_PORT_1=1 REMAP_PORT_2=0x3f REMAP_PORT_3=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=0x3f REMAP_PORT_5=0x3f REMAP_PORT_6=0x3f REMAP_PORT_7=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=0x3f REMAP_PORT_9=0x3f REMAP_PORT_10=0x3f REMAP_PORT_11=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=0x3f REMAP_PORT_13=0x3f REMAP_PORT_14=0x3f REMAP_PORT_15=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=0x3f REMAP_PORT_17=0x3f REMAP_PORT_18=0x3f REMAP_PORT_19=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=0x3f REMAP_PORT_21=0x3f REMAP_PORT_22=0x3f REMAP_PORT_23=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=0x3f REMAP_PORT_25=0x3f REMAP_PORT_26=0x3f REMAP_PORT_27=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=0x3f REMAP_PORT_29=0x3f REMAP_PORT_30=0x3f REMAP_PORT_31=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=0x3f REMAP_PORT_33=0x3f REMAP_PORT_34=0x3f REMAP_PORT_35=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=0x3f REMAP_PORT_37=0x3f REMAP_PORT_38=0x3f REMAP_PORT_39=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=0x3f REMAP_PORT_41=0x3f REMAP_PORT_42=0x3f REMAP_PORT_43=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=0x3f REMAP_PORT_45=0x3f REMAP_PORT_46=0x3f REMAP_PORT_47=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=0x3f REMAP_PORT_49=0x3f REMAP_PORT_50=0x3f REMAP_PORT_51=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=0x3f REMAP_PORT_53=0x3f REMAP_PORT_54=0x3f REMAP_PORT_55=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=0x3f REMAP_PORT_57=0x3f REMAP_PORT_58=0x3f REMAP_PORT_59=0x3f +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=0x3f REMAP_PORT_61=0x3f REMAP_PORT_62=0x3f REMAP_PORT_63=0x3f + +led 0 stop +led 0 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 1 auto on +led 1 start + +led 2 stop +led 2 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 2 auto on +led 2 start + +led 3 stop +led 3 prog 86 FF 06 FF C2 7F 60 FF 02 41 60 FE 67 1A 06 FE E2 04 60 FE D2 01 74 0C 77 51 02 9F F6 FE E2 04 04 D2 01 70 27 74 48 06 FE E2 04 90 28 32 00 32 01 B7 97 71 37 75 3F 06 FF C2 10 70 48 74 3F 67 57 67 53 67 57 67 57 57 67 57 67 57 67 57 67 57 57 3A 40 32 0E 87 57 32 0F 87 57 +led 3 auto on +led 3 start + +led 4 stop +led 4 prog 86 FF 06 FF C2 7F 60 FF 02 02 60 FE 67 1A 06 FE E2 01 60 FE D2 00 74 0C 77 6A 02 9F F6 FE 04 D2 01 70 25 74 51 06 FE 90 28 32 03 32 04 97 75 64 97 71 58 75 5E 06 FE 90 28 32 00 32 01 B7 97 71 43 75 4B 06 FF C2 10 70 4E 74 4B 67 6C 57 67 70 57 67 70 67 70 67 70 57 67 6C 67 70 77 35 67 70 67 6C 77 35 67 70 67 70 77 35 3A 06 32 0E 87 57 32 0F 87 57 +led 4 auto on +led 4 start diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/eeprom.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/eeprom.py new file mode 100644 index 000000000000..9e4e9970e9f5 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0056/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/led_control.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/led_control.py new file mode 100644 index 000000000000..53cc43c6cce3 --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/led_control.py @@ -0,0 +1,221 @@ +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +# try: +# from sonic_led.led_control_base import LedControlBase +# import swsssdk +# except ImportError as e: +# raise ImportError (str(e) + " - required module not found") + +import time + + +class LedControlBase(object): + # __metaclass__ = abc.ABCMeta + + # @abc.abstractmethod + def port_link_state_change(self, port, state): + """ + Called when port link state changes. Update port link state LED here. + + :param port: A string, SONiC port name (e.g., "Ethernet0") + :param state: A string, the port link state (either "up" or "down") + """ + return + + +### Goreme specified ### +read_fan_fault = 0 +is_fan_all_OK = 0 +read_power_status = 0 +is_power_all_OK = 0 +is_thermal_high = 0 +is_reset_button_push = 0 +########################## + + +def sysled_task(): + while True: + system_led_check() + time.sleep(5) + +# Goreme System LED checking + + +def system_led_check(): + global read_fan_fault, read_power_status, is_fan_all_OK, is_power_all_OK, is_thermal_high, is_reset_button_push + is_fan_all_OK = 1 + is_power_all_OK = 0 + is_thermal_high = 0 + is_reset_button_push = 0 + with open("/sys/bus/i2c/devices/0-005e/fan1_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan2_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan3_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + with open("/sys/bus/i2c/devices/0-005e/fan4_fault", "r") as f1: + read_fan_fault = f1.read() + if str(read_fan_fault) == str("1\n"): + is_fan_all_OK = 0 + + with open("/sys/bus/i2c/devices/8-005f/fan1_led", "w") as f11: + if int(is_fan_all_OK) == 1: + f11.write("1") + else: + f11.write("4") + + with open("/sys/bus/i2c/devices/0-005e/psu1_power_good", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) != str("1\n"): + is_power_all_OK = -10 + with open("/sys/bus/i2c/devices/0-005e/psu1_present", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + with open("/sys/bus/i2c/devices/0-005e/psu2_power_good", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) != str("1\n"): + is_power_all_OK = -10 + with open("/sys/bus/i2c/devices/0-005e/psu2_present", "r") as f1: + read_power_status = f1.read() + if str(read_power_status) == str("1\n"): + is_power_all_OK = is_power_all_OK + 1 + + with open("/sys/bus/i2c/devices/8-005f/sys_pwr", "w") as f11: + if int(is_power_all_OK) > 0: + f11.write("1") + else: + f11.write("4") + + with open("/sys/bus/i2c/devices/8-005f/swi_ctrl", "r") as f5: + is_reset_button_push = f5.read() + if str(is_reset_button_push) == "1\n": + is_reset_button_push = 1 + else: + is_reset_button_push = 0 + + with open("/sys/bus/i2c/devices/3-004d/hwmon/hwmon2/temp1_input", "r") as f3: + is_thermal_high = f3.read() + if int(is_thermal_high) >= 70000: + is_thermal_high = 1 + else: + is_thermal_high = 0 + + with open("/sys/bus/i2c/devices/8-005f/sys_status", "w") as f2: + if is_reset_button_push == 1: + f2.write("3") + elif is_fan_all_OK == 0 or is_power_all_OK == 0 or is_thermal_high == 1: + f2.write("4") + else: + f2.write("1") + + return +########## + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + PORT_TABLE_PREFIX = "PORT_TABLE:" + + SONIC_PORT_NAME_PREFIX = "Ethernet" + + LED_SYSFS_PATH_BREAKOUT_CAPABLE = "/sys/class/leds/qsfp{0}_{1}/brightness" + LED_SYSFS_PATH_NO_BREAKOUT = "/sys/class/leds/qsfp{0}/brightness" + + QSFP_BREAKOUT_START_IDX = 1 + QSFP_BREAKOUT_END_IDX = 24 + QSFP_NO_BREAKOUT_START_IDX = 25 + QSFP_NO_BREAKOUT_END_IDX = 32 + + LED_COLOR_OFF = 0 + LED_COLOR_GREEN = 1 + LED_COLOR_YELLOW = 2 + + # Helper method to map SONiC port name to Arista QSFP index + def _port_name_to_qsfp_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + sonic_port_num = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + swss = swsssdk.SonicV2Connector() + swss.connect(swss.APPL_DB) + + lanes = swss.get( + swss.APPL_DB, self.PORT_TABLE_PREFIX + port_name, 'lanes') + + # SONiC port nums are 0-based and increment by 4 + # Arista QSFP indices are 1-based and increment by 1 + return (((sonic_port_num/4) + 1), sonic_port_num % 4, len(lanes.split(','))) + + # Concrete implementation of port_link_state_change() method + + def port_link_state_change_bk(self, port, state): + qsfp_index, lane_index, lanes = self._port_name_to_qsfp_index(port) + + # Ignore invalid QSFP indices + if qsfp_index <= 0 or lanes <= 0 or lanes > 4: + return + + # QSFP indices 0-24 are breakout-capable and have four LEDs, and each LED indicate one lane. + # whereas indices 25-32 are not breakout-capable, and only have one + if qsfp_index <= self.QSFP_BREAKOUT_END_IDX: + # assuming 40G, then we need to control four lanes + led_sysfs_paths = [self.LED_SYSFS_PATH_BREAKOUT_CAPABLE.format( + qsfp_index, i) for i in range(lane_index + 1, lane_index + 1 + lanes)] + else: + led_sysfs_paths = [ + self.LED_SYSFS_PATH_NO_BREAKOUT.format(qsfp_index)] + + for led_sysfs_path in led_sysfs_paths: + led_file = open(led_sysfs_path, "w") + + if state == "up": + led_file.write("%d" % self.LED_COLOR_GREEN) + else: + led_file.write("%d" % self.LED_COLOR_OFF) + + led_file.close() + + # Constructor + def __init__(self): + # Initialize all front-panel status LEDs to green + with open("/sys/bus/i2c/devices/8-005f/sys_locator", "w") as f: + f.write("0") + with open("/sys/bus/i2c/devices/8-005f/sys_pwr", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/sys_status", "w") as f: + f.write("1") + + # Initialize all fan LEDs to green + with open("/sys/bus/i2c/devices/8-005f/fan1_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/fan2_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/fan3_led", "w") as f: + f.write("1") + with open("/sys/bus/i2c/devices/8-005f/fan4_led", "w") as f: + f.write("1") + sysled_task() + + # Initialize: Turn all front panel QSFP LEDs off + # # for qsfp_index in range(self.QSFP_BREAKOUT_START_IDX, self.QSFP_BREAKOUT_END_IDX + 1): + # # for lane in range(1, 5): + # # led_sysfs_path = self.LED_SYSFS_PATH_BREAKOUT_CAPABLE.format(qsfp_index, lane) + # # with open(led_sysfs_path, 'w') as led_file: + # # led_file.write("%d" % self.LED_COLOR_OFF) + + # # for qsfp_index in range(self.QSFP_NO_BREAKOUT_START_IDX, self.QSFP_NO_BREAKOUT_END_IDX + 1): + # # led_sysfs_path = self.LED_SYSFS_PATH_NO_BREAKOUT.format(qsfp_index) + # # with open(led_sysfs_path, 'w') as led_file: + # # led_file.write("%d" % self.LED_COLOR_OFF) diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/psuutil.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/psuutil.py new file mode 100644 index 000000000000..d189349b5d0e --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/psuutil.py @@ -0,0 +1,65 @@ +############################################################################# +# Alphanetworks +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = { + 1: "/psu1_present", + 2: "/psu2_present", + } + self.psu_oper_status = { + 1: "/psu1_power_good", + 2: "/psu2_power_good", + } + self.psu_mapping = "0-005e" + if not os.path.exists(self.psu_path+self.psu_mapping): + self.psu_mapping = "1-005e" + + def get_num_psus(self): + return len(self.psu_presence) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping+self.psu_oper_status[index] + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping + self.psu_presence[index] + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py new file mode 100644 index 000000000000..e2c2aae496cc --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/plugins/sfputil.py @@ -0,0 +1,128 @@ +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + first_port = 0 + last_port = 65 + port_num = 63 + + port_to_eeprom = {} + port_to_i2cbus_mapping = { + 1: 13, + 2: 14, + 3: 15, + 4: 16, + 5: 23, + } + + eeprom_path_1 = "/sys/bus/i2c/devices/{0}-0020/sfp{1}_eeprom" + eeprom_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_eeprom" + port_reset_path_1 = "/sys/bus/i2c/devices/{0}-0020/sfp{1}_port_reset" + port_reset_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_port_reset" + present_path_1 = "/sys/bus/i2c/devices/{0}-0020/sfp{1}_is_present" + present_path = "/sys/bus/i2c/devices/{0}-005f/sfp{1}_is_present" + + _qsfp_ports = list(range(first_port, port_num)) + + @property + def port_start(self): + return self.first_port + + @property + def port_end(self): + return self.last_port + + @property + def qsfp_ports(self): + return list(range(self.first_port, self.port_num + 1)) + + @property + def port_to_eeprom_mapping(self): + return self.port_to_eeprom + + 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 + + def __init__(self): + for x in range(self.first_port, self.last_port + 1): + cpld_index = (x / 16) + 1 + index = (x % 16) + 1 + if cpld_index == 5: + path = self.eeprom_path_1 + else: + path = self.eeprom_path + self.port_to_eeprom[x] = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + SfpUtilBase.__init__(self) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.first_port or port_num > self.last_port: + return False + + cpld_index = (port_num / 16) + 1 + index = (port_num % 16) + 1 + if cpld_index == 5: + path = self.port_reset_path_1 + else: + path = self.port_reset_path + port_path = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + + try: + reg_file = open(port_path, 'w') + except IOError as e: + if cpld_index < 5: + print("Error: unable to open file: %s" % str(e)) + return False + + # reset + reg_file.write('1') + + time.sleep(1) + + 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.first_port or port_num > self.last_port: + return False + + cpld_index = (port_num / 16) + 1 + index = (port_num % 16) + 1 + if cpld_index == 5: + path = self.present_path_1 + else: + path = self.present_path + port_path = path.format(self.port_to_i2cbus_mapping[cpld_index], index) + + try: + reg_file = open(port_path) + except IOError as e: + if cpld_index < 5: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False diff --git a/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/sensors.conf b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/sensors.conf new file mode 100644 index 000000000000..0650d9da652b --- /dev/null +++ b/device/alphanetworks/x86_64-alphanetworks_snh60b0_640f-r0/sensors.conf @@ -0,0 +1,13 @@ +# libsensors configuration file for snh60b0_640f +# ------------------------------------------------ + +bus "i2c-1" "SMBus I801 adapter at f000" +chip "goreme_power_cpld-*" + label fan1 "Fan tray 1 front" + label fan2 "Fan tray 2 front" + label fan3 "Fan tray 3 front" + label fan4 "Fan tray 4 front" + label fan11 "Fan tray 1 rear" + label fan12 "Fan tray 2 rear" + label fan13 "Fan tray 3 rear" + label fan14 "Fan tray 4 rear" diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/port_config.ini b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/port_config.ini new file mode 100644 index 000000000000..1cc6c91b1308 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index +Ethernet0 125,126,127,128 Ethernet1/1 1 +Ethernet4 121,122,123,124 Ethernet2/1 2 +Ethernet8 13,14,15,16 Ethernet3/1 3 +Ethernet12 9,10,11,12 Ethernet4/1 4 +Ethernet16 17,18,19,20 Ethernet5/1 5 +Ethernet20 21,22,23,24 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 45,46,47,48 Ethernet11/1 11 +Ethernet44 41,42,43,44 Ethernet12/1 12 +Ethernet48 53,54,55,56 Ethernet13/1 13 +Ethernet52 49,50,51,52 Ethernet14/1 14 +Ethernet56 69,70,71,72 Ethernet15/1 15 +Ethernet60 65,66,67,68 Ethernet16/1 16 +Ethernet64 77 Ethernet17/1 17 +Ethernet65 78 Ethernet17/2 17 +Ethernet66 79 Ethernet17/3 17 +Ethernet67 80 Ethernet17/4 17 +Ethernet68 73 Ethernet18/1 18 +Ethernet69 74 Ethernet18/2 18 +Ethernet70 75 Ethernet18/3 18 +Ethernet71 76 Ethernet18/4 18 +Ethernet72 93 Ethernet19/1 19 +Ethernet73 94 Ethernet19/2 19 +Ethernet74 95 Ethernet19/3 19 +Ethernet75 96 Ethernet19/4 19 +Ethernet76 89 Ethernet20/1 20 +Ethernet77 90 Ethernet20/2 20 +Ethernet78 91 Ethernet20/3 20 +Ethernet79 92 Ethernet20/4 20 +Ethernet80 101 Ethernet21/1 21 +Ethernet81 102 Ethernet21/2 21 +Ethernet82 103 Ethernet21/3 21 +Ethernet83 104 Ethernet21/4 21 +Ethernet84 97 Ethernet22/1 22 +Ethernet85 98 Ethernet22/2 22 +Ethernet86 99 Ethernet22/3 22 +Ethernet87 100 Ethernet22/4 22 +Ethernet88 109 Ethernet23/1 23 +Ethernet89 110 Ethernet23/2 23 +Ethernet90 111 Ethernet23/3 23 +Ethernet91 112 Ethernet23/4 23 +Ethernet92 105 Ethernet24/1 24 +Ethernet93 106 Ethernet24/2 24 +Ethernet94 107 Ethernet24/3 24 +Ethernet95 108 Ethernet24/4 24 +Ethernet96 61,62,63,64 Ethernet25 25 +Ethernet100 57,58,59,60 Ethernet26 26 +Ethernet104 81,82,83,84 Ethernet27 27 +Ethernet108 85,86,87,88 Ethernet28 28 +Ethernet112 117,118,119,120 Ethernet29 29 +Ethernet116 113,114,115,116 Ethernet30 30 +Ethernet120 5,6,7,8 Ethernet31 31 +Ethernet124 1,2,3,4 Ethernet32 32 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/sai.profile b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/sai.profile new file mode 100644 index 000000000000..5c613675c37f --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-a7050-qx32-16x40G+32x10G+8x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/td2-a7050-qx32-16x40G+32x10G+8x40G.config.bcm b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/td2-a7050-qx32-16x40G+32x10G+8x40G.config.bcm new file mode 100644 index 000000000000..d3ee2d5e3b0a --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-Q16S64/td2-a7050-qx32-16x40G+32x10G+8x40G.config.bcm @@ -0,0 +1,706 @@ +#/****************************************************************************** +# * +# * File: config.bcm.cloverdales (7050-QX32) +# * Name: +# * +# * Description: This file contains SDK properties for an Arista +# * Cloverdales platform. +# * +# *----------------------------------------------------------------------------- +# ******************************************************************************/ +#################################################################### +# BCM Config file for Cloverdale platform +# - 16x40g + 32x10g + 8x40G Portmode + +# 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 + +# l2 thread related config vars +l2xmsg_hostbuf_size=8192 +l2xmsg_mode=1 + +bcm_num_cos=10 +bcm_stat_interval=2000000 +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 + +# for GLC transceiver +phy_an_c73=0x0 +phy_an_c37=0x3 + +########################### +#port_init_speed_xe=40000 +#port_init_speed_xe.0=40000 + +#load_firmware=0x0102 +load_firmware.0=2 + +######################### +# All ports are in oversubscription mode +pbmp_oversubscribe=0x1fffffffffffffffffffffffffe +pbmp_xport_xe.0=0x1fffffffffffffffffffffffffe + +########################################## +#skip_L2_USER_ENTRY=0 +phy_aux_voltage_enable=1 +############################### +serdes_fiber_pref=1 +############################### +mdio_output_delay.0=0x0d +############################### +serdes_sgmii_m=0 +xgxs_lcpll_xtal_refclk=1 +xgxs_lcpll_xtal_refclk.0=1 +xgxs_lcpll_xtal_refclk.1=1 +xgxs_lcpll_xtal_refclk.2=1 +xgxs_lcpll_xtal_refclk.3=1 +tdma_intr_enable=1 +tslam_intr_enable=1 +tslam_dma_enable.2=1 +tslam_dma_enable.3=1 +#dport_map_port=0 +#pci2eb_overrid=0 +#bcm_xlate_port_enable.0=0 +#xgxs_pdetect_1=0 +table_dma_enable.0=1 +table_dma_enable.1=1 +table_dma_enable.2=1 +table_dma_enable.3=1 + + +phy_84328_1.0=1 +phy_84328_5.0=1 +phy_84328_9.0=1 +phy_84328_13.0=1 +phy_84328_101.0=1 +phy_84328_102.0=1 +phy_84328_103.0=1 +phy_84328_104.0=1 + +phy_an_c37_1.0=0 +phy_an_c37_5.0=0 +phy_an_c37_9.0=0 +phy_an_c37_13.0=0 +phy_an_c37_17.0=0 +phy_an_c37_21.0=0 +phy_an_c37_25.0=0 +phy_an_c37_29.0=0 +phy_an_c37_33.0=0 +phy_an_c37_37.0=0 +phy_an_c37_41.0=0 +phy_an_c37_45.0=0 +phy_an_c37_49.0=0 +phy_an_c37_53.0=0 +phy_an_c37_57.0=0 +phy_an_c37_61.0=0 +phy_an_c37_65.0=3 +phy_an_c37_66.0=3 +phy_an_c37_67.0=3 +phy_an_c37_68.0=3 +phy_an_c37_69.0=3 +phy_an_c37_70.0=3 +phy_an_c37_71.0=3 +phy_an_c37_72.0=3 +phy_an_c37_73.0=3 +phy_an_c37_74.0=3 +phy_an_c37_75.0=3 +phy_an_c37_76.0=3 +phy_an_c37_77.0=3 +phy_an_c37_78.0=3 +phy_an_c37_79.0=3 +phy_an_c37_80.0=3 +phy_an_c37_81.0=3 +phy_an_c37_82.0=3 +phy_an_c37_83.0=3 +phy_an_c37_84.0=3 +phy_an_c37_85.0=3 +phy_an_c37_86.0=3 +phy_an_c37_87.0=3 +phy_an_c37_88.0=3 +phy_an_c37_89.0=3 +phy_an_c37_90.0=3 +phy_an_c37_91.0=3 +phy_an_c37_92.0=3 +phy_an_c37_93.0=3 +phy_an_c37_94.0=3 +phy_an_c37_95.0=3 +phy_an_c37_96.0=3 +phy_an_c37_97.0=0 +phy_an_c37_98.0=0 +phy_an_c37_99.0=0 +phy_an_c37_100.0=0 +phy_an_c37_101.0=0 +phy_an_c37_102.0=0 +phy_an_c37_103.0=0 +phy_an_c37_104.0=0 + +phy_an_c73_1.0=2 +phy_an_c73_5.0=2 +phy_an_c73_9.0=2 +phy_an_c73_13.0=2 +phy_an_c73_17.0=2 +phy_an_c73_21.0=2 +phy_an_c73_25.0=2 +phy_an_c73_29.0=2 +phy_an_c73_33.0=2 +phy_an_c73_37.0=2 +phy_an_c73_41.0=2 +phy_an_c73_45.0=2 +phy_an_c73_49.0=2 +phy_an_c73_53.0=2 +phy_an_c73_57.0=2 +phy_an_c73_61.0=2 +phy_an_c73_65.0=0 +phy_an_c73_66.0=0 +phy_an_c73_67.0=0 +phy_an_c73_68.0=0 +phy_an_c73_69.0=0 +phy_an_c73_70.0=0 +phy_an_c73_71.0=0 +phy_an_c73_72.0=0 +phy_an_c73_73.0=0 +phy_an_c73_74.0=0 +phy_an_c73_75.0=0 +phy_an_c73_76.0=0 +phy_an_c73_77.0=0 +phy_an_c73_78.0=0 +phy_an_c73_79.0=0 +phy_an_c73_80.0=0 +phy_an_c73_81.0=0 +phy_an_c73_82.0=0 +phy_an_c73_83.0=0 +phy_an_c73_84.0=0 +phy_an_c73_85.0=0 +phy_an_c73_86.0=0 +phy_an_c73_87.0=0 +phy_an_c73_88.0=0 +phy_an_c73_89.0=0 +phy_an_c73_90.0=0 +phy_an_c73_91.0=0 +phy_an_c73_92.0=0 +phy_an_c73_93.0=0 +phy_an_c73_94.0=0 +phy_an_c73_95.0=0 +phy_an_c73_96.0=0 +phy_an_c73_97.0=2 +phy_an_c73_98.0=2 +phy_an_c73_99.0=2 +phy_an_c73_100.0=2 +phy_an_c73_101.0=2 +phy_an_c73_102.0=2 +phy_an_c73_103.0=2 +phy_an_c73_104.0=2 + +phy_aux_voltage_enable_1.0=0x1 +phy_aux_voltage_enable_5.0=0x1 +phy_aux_voltage_enable_9.0=0x1 +phy_aux_voltage_enable_13.0=0x1 +phy_aux_voltage_enable_101.0=0x1 +phy_aux_voltage_enable_102.0=0x1 +phy_aux_voltage_enable_103.0=0x1 +phy_aux_voltage_enable_104.0=0x1 + +phy_ext_rom_boot.0=0 + +phy_ext_rom_boot_1.0=0x0 +phy_ext_rom_boot_5.0=0x0 +phy_ext_rom_boot_9.0=0x0 +phy_ext_rom_boot_13.0=0x0 +phy_ext_rom_boot_101.0=0x0 +phy_ext_rom_boot_102.0=0x0 +phy_ext_rom_boot_103.0=0x0 +phy_ext_rom_boot_104.0=0x0 + + +phy_line_tx_mode_1.0=1 +phy_line_tx_mode_5.0=1 +phy_line_tx_mode_9.0=1 +phy_line_tx_mode_13.0=1 +phy_line_tx_mode_101.0=1 +phy_line_tx_mode_102.0=1 +phy_line_tx_mode_103.0=1 +phy_line_tx_mode_104.0=1 + + +phy_rx_polarity_flip_1.0=0x0 +phy_rx_polarity_flip_5.0=0x0 +phy_rx_polarity_flip_9.0=0x0 +phy_rx_polarity_flip_13.0=0x0 +phy_rx_polarity_flip_101.0=0x0 +phy_rx_polarity_flip_102.0=0x0 +phy_rx_polarity_flip_103.0=0x0 +phy_rx_polarity_flip_104.0=0x0 + +phy_system_tx_mode_1.0=0 +phy_system_tx_mode_5.0=0 +phy_system_tx_mode_9.0=0 +phy_system_tx_mode_13.0=0 +phy_system_tx_mode_101.0=0 +phy_system_tx_mode_102.0=0 +phy_system_tx_mode_103.0=0 +phy_system_tx_mode_104.0=0 + + +phy_tx_polarity_flip_1.0=0x0 +phy_tx_polarity_flip_5.0=0x0 +phy_tx_polarity_flip_9.0=0x0 +phy_tx_polarity_flip_13.0=0x0 +phy_tx_polarity_flip_101.0=0x0 +phy_tx_polarity_flip_102.0=0x0 +phy_tx_polarity_flip_103.0=0x0 +phy_tx_polarity_flip_104.0=0x0 + + +phy_xaui_rx_polarity_flip_1.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x0 +phy_xaui_rx_polarity_flip_9.0=0x0 +phy_xaui_rx_polarity_flip_13.0=0x0 +phy_xaui_rx_polarity_flip_17.0=0x0 +phy_xaui_rx_polarity_flip_21.0=0x0 +phy_xaui_rx_polarity_flip_25.0=0x0 +phy_xaui_rx_polarity_flip_29.0=0x0 +phy_xaui_rx_polarity_flip_33.0=0x0 +phy_xaui_rx_polarity_flip_37.0=0x0 +phy_xaui_rx_polarity_flip_41.0=0x0 +phy_xaui_rx_polarity_flip_45.0=0x0 +phy_xaui_rx_polarity_flip_49.0=0x0 +phy_xaui_rx_polarity_flip_53.0=0x0 +phy_xaui_rx_polarity_flip_57.0=0x0 +phy_xaui_rx_polarity_flip_61.0=0x0 +phy_xaui_rx_polarity_flip_65.0=0x0 +phy_xaui_rx_polarity_flip_66.0=0x0 +phy_xaui_rx_polarity_flip_67.0=0x0 +phy_xaui_rx_polarity_flip_68.0=0x0 +phy_xaui_rx_polarity_flip_69.0=0x0 +phy_xaui_rx_polarity_flip_70.0=0x0 +phy_xaui_rx_polarity_flip_71.0=0x0 +phy_xaui_rx_polarity_flip_72.0=0x0 +phy_xaui_rx_polarity_flip_73.0=0x0 +phy_xaui_rx_polarity_flip_74.0=0x0 +phy_xaui_rx_polarity_flip_75.0=0x0 +phy_xaui_rx_polarity_flip_76.0=0x0 +phy_xaui_rx_polarity_flip_77.0=0x0 +phy_xaui_rx_polarity_flip_78.0=0x0 +phy_xaui_rx_polarity_flip_79.0=0x0 +phy_xaui_rx_polarity_flip_80.0=0x0 +phy_xaui_rx_polarity_flip_81.0=0x0 +phy_xaui_rx_polarity_flip_82.0=0x0 +phy_xaui_rx_polarity_flip_83.0=0x0 +phy_xaui_rx_polarity_flip_84.0=0x0 +phy_xaui_rx_polarity_flip_85.0=0x0 +phy_xaui_rx_polarity_flip_86.0=0x0 +phy_xaui_rx_polarity_flip_87.0=0x0 +phy_xaui_rx_polarity_flip_88.0=0x0 +phy_xaui_rx_polarity_flip_89.0=0x0 +phy_xaui_rx_polarity_flip_90.0=0x0 +phy_xaui_rx_polarity_flip_91.0=0x0 +phy_xaui_rx_polarity_flip_92.0=0x0 +phy_xaui_rx_polarity_flip_93.0=0x0 +phy_xaui_rx_polarity_flip_94.0=0x0 +phy_xaui_rx_polarity_flip_95.0=0x0 +phy_xaui_rx_polarity_flip_96.0=0x0 +phy_xaui_rx_polarity_flip_97.0=0x0 +phy_xaui_rx_polarity_flip_98.0=0x0 +phy_xaui_rx_polarity_flip_99.0=0x0 +phy_xaui_rx_polarity_flip_100.0=0x0 +phy_xaui_rx_polarity_flip_101.0=0x0 +phy_xaui_rx_polarity_flip_102.0=0x0 +phy_xaui_rx_polarity_flip_103.0=0x0 +phy_xaui_rx_polarity_flip_104.0=0x0 + +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_5.0=0x0 +phy_xaui_tx_polarity_flip_9.0=0x0 +phy_xaui_tx_polarity_flip_13.0=0x0 +phy_xaui_tx_polarity_flip_17.0=0x0 +phy_xaui_tx_polarity_flip_21.0=0x0 +phy_xaui_tx_polarity_flip_25.0=0x0 +phy_xaui_tx_polarity_flip_29.0=0x0 +phy_xaui_tx_polarity_flip_33.0=0x0 +phy_xaui_tx_polarity_flip_37.0=0x0 +phy_xaui_tx_polarity_flip_41.0=0x0 +phy_xaui_tx_polarity_flip_45.0=0x0 +phy_xaui_tx_polarity_flip_49.0=0x0 +phy_xaui_tx_polarity_flip_53.0=0x0 +phy_xaui_tx_polarity_flip_57.0=0x0 +phy_xaui_tx_polarity_flip_61.0=0x0 +phy_xaui_tx_polarity_flip_65.0=0x0 +phy_xaui_tx_polarity_flip_66.0=0x0 +phy_xaui_tx_polarity_flip_67.0=0x0 +phy_xaui_tx_polarity_flip_68.0=0x0 +phy_xaui_tx_polarity_flip_69.0=0x0 +phy_xaui_tx_polarity_flip_70.0=0x0 +phy_xaui_tx_polarity_flip_71.0=0x0 +phy_xaui_tx_polarity_flip_72.0=0x0 +phy_xaui_tx_polarity_flip_73.0=0x0 +phy_xaui_tx_polarity_flip_74.0=0x0 +phy_xaui_tx_polarity_flip_75.0=0x0 +phy_xaui_tx_polarity_flip_76.0=0x0 +phy_xaui_tx_polarity_flip_77.0=0x0 +phy_xaui_tx_polarity_flip_78.0=0x0 +phy_xaui_tx_polarity_flip_79.0=0x0 +phy_xaui_tx_polarity_flip_80.0=0x0 +phy_xaui_tx_polarity_flip_81.0=0x0 +phy_xaui_tx_polarity_flip_82.0=0x0 +phy_xaui_tx_polarity_flip_83.0=0x0 +phy_xaui_tx_polarity_flip_84.0=0x0 +phy_xaui_tx_polarity_flip_85.0=0x0 +phy_xaui_tx_polarity_flip_86.0=0x0 +phy_xaui_tx_polarity_flip_87.0=0x0 +phy_xaui_tx_polarity_flip_88.0=0x0 +phy_xaui_tx_polarity_flip_89.0=0x0 +phy_xaui_tx_polarity_flip_90.0=0x0 +phy_xaui_tx_polarity_flip_91.0=0x0 +phy_xaui_tx_polarity_flip_92.0=0x0 +phy_xaui_tx_polarity_flip_93.0=0x0 +phy_xaui_tx_polarity_flip_94.0=0x0 +phy_xaui_tx_polarity_flip_95.0=0x0 +phy_xaui_tx_polarity_flip_96.0=0x0 +phy_xaui_tx_polarity_flip_97.0=0x0 +phy_xaui_tx_polarity_flip_98.0=0x0 +phy_xaui_tx_polarity_flip_99.0=0x0 +phy_xaui_tx_polarity_flip_100.0=0x0 +phy_xaui_tx_polarity_flip_101.0=0x0 +phy_xaui_tx_polarity_flip_102.0=0x0 +phy_xaui_tx_polarity_flip_103.0=0x0 +phy_xaui_tx_polarity_flip_104.0=0x0 + +port_init_autoneg_17.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_25.0=0 +port_init_autoneg_29.0=0 +port_init_autoneg_33.0=0 +port_init_autoneg_37.0=0 +port_init_autoneg_41.0=0 +port_init_autoneg_45.0=0 +port_init_autoneg_49.0=0 +port_init_autoneg_53.0=0 +port_init_autoneg_57.0=0 +port_init_autoneg_61.0=0 +port_init_autoneg_65.0=0 +port_init_autoneg_66.0=0 +port_init_autoneg_67.0=0 +port_init_autoneg_68.0=0 +port_init_autoneg_69.0=0 +port_init_autoneg_70.0=0 +port_init_autoneg_71.0=0 +port_init_autoneg_72.0=0 +port_init_autoneg_73.0=0 +port_init_autoneg_74.0=0 +port_init_autoneg_75.0=0 +port_init_autoneg_76.0=0 +port_init_autoneg_77.0=0 +port_init_autoneg_78.0=0 +port_init_autoneg_79.0=0 +port_init_autoneg_80.0=0 +port_init_autoneg_81.0=0 +port_init_autoneg_82.0=0 +port_init_autoneg_83.0=0 +port_init_autoneg_84.0=0 +port_init_autoneg_85.0=0 +port_init_autoneg_86.0=0 +port_init_autoneg_87.0=0 +port_init_autoneg_88.0=0 +port_init_autoneg_89.0=0 +port_init_autoneg_90.0=0 +port_init_autoneg_91.0=0 +port_init_autoneg_92.0=0 +port_init_autoneg_93.0=0 +port_init_autoneg_94.0=0 +port_init_autoneg_95.0=0 +port_init_autoneg_96.0=0 +port_init_autoneg_97.0=0 +port_init_autoneg_98.0=0 +port_init_autoneg_99.0=0 +port_init_autoneg_100.0=0 + +port_init_cl72_hg.0=0x11 + + +portmap_1.0=125:40 +portmap_5.0=121:40 +portmap_9.0=13:40 +portmap_13.0=9:40 +portmap_17.0=17:40 +portmap_21.0=21:40 +portmap_25.0=25:40 +portmap_29.0=29:40 +portmap_33.0=37:40 +portmap_37.0=33:40 +portmap_41.0=45:40 +portmap_45.0=41:40 +portmap_49.0=53:40 +portmap_53.0=49:40 +portmap_57.0=69:40 +portmap_61.0=65:40 +portmap_65.0=77:10 +portmap_66.0=78:10 +portmap_67.0=79:10 +portmap_68.0=80:10 +portmap_69.0=73:10 +portmap_70.0=74:10 +portmap_71.0=75:10 +portmap_72.0=76:10 +portmap_73.0=93:10 +portmap_74.0=94:10 +portmap_75.0=95:10 +portmap_76.0=96:10 +portmap_77.0=89:10 +portmap_78.0=90:10 +portmap_79.0=91:10 +portmap_80.0=92:10 +portmap_81.0=101:10 +portmap_82.0=102:10 +portmap_83.0=103:10 +portmap_84.0=104:10 +portmap_85.0=97:10 +portmap_86.0=98:10 +portmap_87.0=99:10 +portmap_88.0=100:10 +portmap_89.0=109:10 +portmap_90.0=110:10 +portmap_91.0=111:10 +portmap_92.0=112:10 +portmap_93.0=105:10 +portmap_94.0=106:10 +portmap_95.0=107:10 +portmap_96.0=108:10 +portmap_97.0=61:40 +portmap_98.0=57:40 +portmap_99.0=81:40 +portmap_100.0=85:40 +portmap_101.0=117:40 +portmap_102.0=113:40 +portmap_103.0=5:40 +portmap_104.0=1:40 + +port_phy_addr_1.0=0x4 +port_phy_addr_5.0=0x0 +port_phy_addr_9.0=0x2c +port_phy_addr_13.0=0x28 +port_phy_addr_17.0=0x7f +port_phy_addr_21.0=0x7f +port_phy_addr_25.0=0x7f +port_phy_addr_29.0=0x7f +port_phy_addr_33.0=0x7f +port_phy_addr_37.0=0x7f +port_phy_addr_41.0=0x7f +port_phy_addr_45.0=0x7f +port_phy_addr_49.0=0x7f +port_phy_addr_53.0=0x7f +port_phy_addr_57.0=0x7f +port_phy_addr_61.0=0x7f +port_phy_addr_65.0=0x7f +port_phy_addr_66.0=0x7f +port_phy_addr_67.0=0x7f +port_phy_addr_68.0=0x7f +port_phy_addr_69.0=0x7f +port_phy_addr_70.0=0x7f +port_phy_addr_71.0=0x7f +port_phy_addr_72.0=0x7f +port_phy_addr_73.0=0x7f +port_phy_addr_74.0=0x7f +port_phy_addr_75.0=0x7f +port_phy_addr_76.0=0x7f +port_phy_addr_77.0=0x7f +port_phy_addr_78.0=0x7f +port_phy_addr_79.0=0x7f +port_phy_addr_80.0=0x7f +port_phy_addr_81.0=0x7f +port_phy_addr_82.0=0x7f +port_phy_addr_83.0=0x7f +port_phy_addr_84.0=0x7f +port_phy_addr_85.0=0x7f +port_phy_addr_86.0=0x7f +port_phy_addr_87.0=0x7f +port_phy_addr_88.0=0x7f +port_phy_addr_89.0=0x7f +port_phy_addr_90.0=0x7f +port_phy_addr_91.0=0x7f +port_phy_addr_92.0=0x7f +port_phy_addr_93.0=0x7f +port_phy_addr_94.0=0x7f +port_phy_addr_95.0=0x7f +port_phy_addr_96.0=0x7f +port_phy_addr_97.0=0x7f +port_phy_addr_98.0=0x7f +port_phy_addr_99.0=0x7f +port_phy_addr_100.0=0x7f +port_phy_addr_101.0=0x54 +port_phy_addr_102.0=0x50 +port_phy_addr_103.0=0x7c +port_phy_addr_104.0=0x78 + +port_phy_clause_1.0=0x2d +port_phy_clause_5.0=0x2d +port_phy_clause_9.0=0x2d +port_phy_clause_13.0=0x2d +port_phy_clause_101.0=0x2d +port_phy_clause_102.0=0x2d +port_phy_clause_103.0=0x2d +port_phy_clause_104.0=0x2d + +port_phy_id0_1.0=0x600d +port_phy_id0_5.0=0x600d +port_phy_id0_9.0=0x600d +port_phy_id0_13.0=0x600d +port_phy_id0_101.0=0x600d +port_phy_id0_102.0=0x600d +port_phy_id0_103.0=0x600d +port_phy_id0_104.0=0x600d + +port_phy_id1_1.0=0x8500 +port_phy_id1_5.0=0x8500 +port_phy_id1_9.0=0x8500 +port_phy_id1_13.0=0x8500 +port_phy_id1_101.0=0x8500 +port_phy_id1_102.0=0x8500 +port_phy_id1_103.0=0x8500 +port_phy_id1_104.0=0x8500 + +xgxs_rx_lane_map_1.0=0x0123 +xgxs_rx_lane_map_5.0=0x0123 +xgxs_rx_lane_map_9.0=0x0123 +xgxs_rx_lane_map_13.0=0x0123 +xgxs_rx_lane_map_17.0=0x2031 +xgxs_rx_lane_map_21.0=0x2031 +xgxs_rx_lane_map_25.0=0x2031 +xgxs_rx_lane_map_29.0=0x2031 +xgxs_rx_lane_map_33.0=0x3120 +xgxs_rx_lane_map_37.0=0x3120 +xgxs_rx_lane_map_41.0=0x3120 +xgxs_rx_lane_map_45.0=0x3120 +xgxs_rx_lane_map_49.0=0x3120 +xgxs_rx_lane_map_53.0=0x3120 +xgxs_rx_lane_map_57.0=0x3120 +xgxs_rx_lane_map_61.0=0x3120 +xgxs_rx_lane_map_65.0=0x3120 +xgxs_rx_lane_map_69.0=0x3120 +xgxs_rx_lane_map_73.0=0x3120 +xgxs_rx_lane_map_77.0=0x3120 +xgxs_rx_lane_map_81.0=0x3120 +xgxs_rx_lane_map_85.0=0x3120 +xgxs_rx_lane_map_89.0=0x3120 +xgxs_rx_lane_map_93.0=0x3120 +xgxs_rx_lane_map_97.0=0x1302 +xgxs_rx_lane_map_98.0=0x1302 +xgxs_rx_lane_map_99.0=0x0213 +xgxs_tx_lane_map_100.0=0x0213 +xgxs_tx_lane_map_101.0=0x0123 +xgxs_tx_lane_map_102.0=0x0123 +xgxs_tx_lane_map_103.0=0x0123 +xgxs_tx_lane_map_104.0=0x0123 + +xgxs_tx_lane_map_1.0=0x0123 +xgxs_tx_lane_map_5.0=0x0123 +xgxs_tx_lane_map_9.0=0x0123 +xgxs_tx_lane_map_13.0=0x0123 +xgxs_tx_lane_map_17.0=0x1302 +xgxs_tx_lane_map_21.0=0x1302 +xgxs_tx_lane_map_25.0=0x1302 +xgxs_tx_lane_map_29.0=0x1302 +xgxs_tx_lane_map_33.0=0x3120 +xgxs_tx_lane_map_37.0=0x3120 +xgxs_tx_lane_map_41.0=0x3120 +xgxs_tx_lane_map_45.0=0x3120 +xgxs_tx_lane_map_49.0=0x3120 +xgxs_tx_lane_map_53.0=0x3120 +xgxs_tx_lane_map_57.0=0x3120 +xgxs_tx_lane_map_61.0=0x3120 +xgxs_tx_lane_map_65.0=0x3120 +xgxs_tx_lane_map_69.0=0x3120 +xgxs_tx_lane_map_73.0=0x3120 +xgxs_tx_lane_map_77.0=0x3120 +xgxs_tx_lane_map_81.0=0x3120 +xgxs_tx_lane_map_85.0=0x3120 +xgxs_tx_lane_map_89.0=0x3120 +xgxs_tx_lane_map_93.0=0x3120 +xgxs_tx_lane_map_97.0=0x2031 +xgxs_tx_lane_map_98.0=0x2031 +xgxs_tx_lane_map_99.0=0x0213 +xgxs_rx_lane_map_100.0=0x0213 +xgxs_rx_lane_map_101.0=0x0123 +xgxs_rx_lane_map_102.0=0x0123 +xgxs_rx_lane_map_103.0=0x0123 +xgxs_rx_lane_map_104.0=0x0123 + +serdes_firmware_mode_1.0=1 +serdes_firmware_mode_5.0=1 +serdes_firmware_mode_9.0=1 +serdes_firmware_mode_13.0=1 +serdes_firmware_mode_17.0=2 +serdes_firmware_mode_21.0=2 +serdes_firmware_mode_25.0=2 +serdes_firmware_mode_29.0=2 +serdes_firmware_mode_33.0=2 +serdes_firmware_mode_37.0=2 +serdes_firmware_mode_41.0=2 +serdes_firmware_mode_45.0=2 +serdes_firmware_mode_49.0=2 +serdes_firmware_mode_53.0=2 +serdes_firmware_mode_57.0=2 +serdes_firmware_mode_61.0=2 +serdes_firmware_mode_65.0=2 +serdes_firmware_mode_66.0=2 +serdes_firmware_mode_67.0=2 +serdes_firmware_mode_68.0=2 +serdes_firmware_mode_69.0=2 +serdes_firmware_mode_70.0=2 +serdes_firmware_mode_71.0=2 +serdes_firmware_mode_72.0=2 +serdes_firmware_mode_73.0=2 +serdes_firmware_mode_74.0=2 +serdes_firmware_mode_75.0=2 +serdes_firmware_mode_76.0=2 +serdes_firmware_mode_77.0=2 +serdes_firmware_mode_78.0=2 +serdes_firmware_mode_79.0=2 +serdes_firmware_mode_80.0=2 +serdes_firmware_mode_81.0=2 +serdes_firmware_mode_82.0=2 +serdes_firmware_mode_83.0=2 +serdes_firmware_mode_84.0=2 +serdes_firmware_mode_85.0=2 +serdes_firmware_mode_86.0=2 +serdes_firmware_mode_87.0=2 +serdes_firmware_mode_88.0=2 +serdes_firmware_mode_89.0=2 +serdes_firmware_mode_90.0=2 +serdes_firmware_mode_91.0=2 +serdes_firmware_mode_92.0=2 +serdes_firmware_mode_93.0=2 +serdes_firmware_mode_94.0=2 +serdes_firmware_mode_95.0=2 +serdes_firmware_mode_96.0=2 +serdes_firmware_mode_97.0=2 +serdes_firmware_mode_98.0=2 +serdes_firmware_mode_99.0=2 +serdes_firmware_mode_100.0=2 +serdes_firmware_mode_101.0=1 +serdes_firmware_mode_102.0=1 +serdes_firmware_mode_103.0=1 +serdes_firmware_mode_104.0=1 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers.json.j2 b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/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/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers_defaults_t1.j2 b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/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/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/pg_profile_lookup.ini b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/pg_profile_lookup.ini new file mode 100644 index 000000000000..d8190e4893de --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/pg_profile_lookup.ini @@ -0,0 +1,11 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 40000 5m 46384 18432 45136 -3 2496 + 50000 5m 46592 18432 45344 -3 2496 + 100000 5m 48464 18432 47216 -3 2496 + 40000 40m 48464 18432 47216 -3 2496 + 50000 40m 49296 18432 48048 -3 2496 + 100000 40m 53872 18432 52624 -3 2496 + 40000 300m 64064 18432 62816 -3 2496 + 50000 300m 68848 18432 67600 -3 2496 + 100000 300m 92976 18432 91728 -3 2496 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/port_config.ini b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/port_config.ini new file mode 100644 index 000000000000..212e1da4b0b2 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 125,126,127,128 Ethernet1/1 1 40000 +Ethernet4 121,122,123,124 Ethernet2/1 2 40000 +Ethernet8 13,14,15,16 Ethernet3/1 3 40000 +Ethernet12 9,10,11,12 Ethernet4/1 4 40000 +Ethernet16 17,18,19,20 Ethernet5/1 5 40000 +Ethernet20 21,22,23,24 Ethernet6/1 6 40000 +Ethernet24 25,26,27,28 Ethernet7/1 7 40000 +Ethernet28 29,30,31,32 Ethernet8/1 8 40000 +Ethernet32 37,38,39,40 Ethernet9/1 9 40000 +Ethernet36 33,34,35,36 Ethernet10/1 10 40000 +Ethernet40 45,46,47,48 Ethernet11/1 11 40000 +Ethernet44 41,42,43,44 Ethernet12/1 12 40000 +Ethernet48 53,54,55,56 Ethernet13/1 13 40000 +Ethernet52 49,50,51,52 Ethernet14/1 14 40000 +Ethernet56 69,70,71,72 Ethernet15/1 15 40000 +Ethernet60 65,66,67,68 Ethernet16/1 16 40000 +Ethernet64 77,78,79,80 Ethernet17/1 17 40000 +Ethernet68 73,74,75,76 Ethernet18/1 18 40000 +Ethernet72 93,94,95,96 Ethernet19/1 19 40000 +Ethernet76 89,90,91,92 Ethernet20/1 20 40000 +Ethernet80 101,102,103,104 Ethernet21/1 21 40000 +Ethernet84 97,98,99,100 Ethernet22/1 22 40000 +Ethernet88 109,110,111,112 Ethernet23/1 23 40000 +Ethernet92 105,106,107,108 Ethernet24/1 24 40000 +Ethernet96 61,62,63,64 Ethernet25 25 40000 +Ethernet100 57,58,59,60 Ethernet26 26 40000 +Ethernet104 81,82,83,84 Ethernet27 27 40000 +Ethernet108 85,86,87,88 Ethernet28 28 40000 +Ethernet112 117,118,119,120 Ethernet29 29 40000 +Ethernet116 113,114,115,116 Ethernet30 30 40000 +Ethernet120 5,6,7,8 Ethernet31 31 40000 +Ethernet124 1,2,3,4 Ethernet32 32 40000 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/qos.json.j2 b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/sai.profile b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/sai.profile new file mode 100644 index 000000000000..27d83fcc20e9 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-a7050-qx32-32x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/td2-a7050-qx32-32x40G.config.bcm b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/td2-a7050-qx32-32x40G.config.bcm new file mode 100644 index 000000000000..7537b36411f7 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/Arista-7050-QX32/td2-a7050-qx32-32x40G.config.bcm @@ -0,0 +1,872 @@ +#/****************************************************************************** +# * +# * File: config.bcm.cloverdales (7050-QX32) +# * Name: +# * +# * Description: This file contains SDK properties for an Arista +# * Cloverdales platform. +# * +# *----------------------------------------------------------------------------- +# ******************************************************************************/ +#################################################################### +# BCM Config file for Cloverdale platform +# - 32x40g Portmode + +# 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 + +# l2 thread related config vars +l2xmsg_hostbuf_size=8192 +l2xmsg_mode=1 + +bcm_num_cos=10 +bcm_stat_interval=2000000 +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 + +# for GLC transceiver +phy_an_c73=0x0 +phy_an_c37=0x3 + +########################### +#port_init_speed_xe=40000 +#port_init_speed_xe.0=40000 + +#load_firmware=0x0102 +load_firmware.0=2 + +######################### +# All ports are in oversubscription mode +pbmp_oversubscribe=0x1fffffffffffffffffffffffffe +pbmp_xport_xe.0=0x1fffffffe + +phy_84328_1.0=1 +phy_84328_2.0=1 +phy_84328_29.0=1 +phy_84328_3.0=1 +phy_84328_30.0=1 +phy_84328_31.0=1 +phy_84328_32.0=1 +phy_84328_4.0=1 +phy_an_c37_1.0=3 +phy_an_c37_10.0=3 +phy_an_c37_11.0=3 +phy_an_c37_12.0=3 +phy_an_c37_13.0=3 +phy_an_c37_14.0=3 +phy_an_c37_15.0=3 +phy_an_c37_16.0=3 +phy_an_c37_17.0=3 +phy_an_c37_18.0=3 +phy_an_c37_19.0=3 +phy_an_c37_2.0=3 +phy_an_c37_20.0=3 +phy_an_c37_21.0=3 +phy_an_c37_22.0=3 +phy_an_c37_23.0=3 +phy_an_c37_24.0=3 +phy_an_c37_25.0=3 +phy_an_c37_26.0=3 +phy_an_c37_27.0=3 +phy_an_c37_28.0=3 +phy_an_c37_29.0=3 +phy_an_c37_3.0=3 +phy_an_c37_30.0=3 +phy_an_c37_31.0=3 +phy_an_c37_32.0=3 +phy_an_c37_4.0=3 +phy_an_c37_5.0=3 +phy_an_c37_6.0=3 +phy_an_c37_7.0=3 +phy_an_c37_8.0=3 +phy_an_c37_9.0=3 +phy_an_c73_1.0=1 +phy_an_c73_10.0=1 +phy_an_c73_11.0=1 +phy_an_c73_12.0=1 +phy_an_c73_13.0=1 +phy_an_c73_14.0=1 +phy_an_c73_15.0=1 +phy_an_c73_16.0=1 +phy_an_c73_17.0=1 +phy_an_c73_18.0=1 +phy_an_c73_19.0=1 +phy_an_c73_2.0=1 +phy_an_c73_20.0=1 +phy_an_c73_21.0=1 +phy_an_c73_22.0=1 +phy_an_c73_23.0=1 +phy_an_c73_24.0=1 +phy_an_c73_25.0=1 +phy_an_c73_26.0=1 +phy_an_c73_27.0=1 +phy_an_c73_28.0=1 +phy_an_c73_29.0=1 +phy_an_c73_3.0=1 +phy_an_c73_30.0=1 +phy_an_c73_31.0=1 +phy_an_c73_32.0=1 +phy_an_c73_4.0=1 +phy_an_c73_5.0=1 +phy_an_c73_6.0=1 +phy_an_c73_7.0=1 +phy_an_c73_8.0=1 +phy_an_c73_9.0=1 +phy_aux_voltage_enable_1.0=0x1 +phy_aux_voltage_enable_2.0=0x1 +phy_aux_voltage_enable_29.0=0x1 +phy_aux_voltage_enable_3.0=0x1 +phy_aux_voltage_enable_30.0=0x1 +phy_aux_voltage_enable_31.0=0x1 +phy_aux_voltage_enable_32.0=0x1 +phy_aux_voltage_enable_4.0=0x1 +phy_ext_rom_boot.0=0 +phy_ext_rom_boot_1.0=0x0 +phy_ext_rom_boot_2.0=0x0 +phy_ext_rom_boot_29.0=0x0 +phy_ext_rom_boot_3.0=0x0 +phy_ext_rom_boot_30.0=0x0 +phy_ext_rom_boot_31.0=0x0 +phy_ext_rom_boot_32.0=0x0 +phy_ext_rom_boot_4.0=0x0 +phy_line_tx_mode_1.0=1 +phy_line_tx_mode_2.0=1 +phy_line_tx_mode_29.0=1 +phy_line_tx_mode_3.0=1 +phy_line_tx_mode_30.0=1 +phy_line_tx_mode_31.0=1 +phy_line_tx_mode_32.0=1 +phy_line_tx_mode_4.0=1 +phy_rx_polarity_flip_1.0=0x0 +phy_rx_polarity_flip_2.0=0x0 +phy_rx_polarity_flip_29.0=0x0 +phy_rx_polarity_flip_3.0=0x0 +phy_rx_polarity_flip_30.0=0x0 +phy_rx_polarity_flip_31.0=0x0 +phy_rx_polarity_flip_32.0=0x0 +phy_rx_polarity_flip_4.0=0x0 +phy_system_tx_mode_1.0=0 +phy_system_tx_mode_2.0=0 +phy_system_tx_mode_29.0=0 +phy_system_tx_mode_3.0=0 +phy_system_tx_mode_30.0=0 +phy_system_tx_mode_31.0=0 +phy_system_tx_mode_32.0=0 +phy_system_tx_mode_4.0=0 +phy_tx_polarity_flip_1.0=0x0 +phy_tx_polarity_flip_2.0=0x0 +phy_tx_polarity_flip_29.0=0x0 +phy_tx_polarity_flip_3.0=0x0 +phy_tx_polarity_flip_30.0=0x0 +phy_tx_polarity_flip_31.0=0x0 +phy_tx_polarity_flip_32.0=0x0 +phy_tx_polarity_flip_4.0=0x0 +phy_xaui_rx_polarity_flip_1.0=0x0 +phy_xaui_rx_polarity_flip_10.0=0x0 +phy_xaui_rx_polarity_flip_11.0=0x0 +phy_xaui_rx_polarity_flip_12.0=0x0 +phy_xaui_rx_polarity_flip_13.0=0x0 +phy_xaui_rx_polarity_flip_14.0=0x0 +phy_xaui_rx_polarity_flip_15.0=0x0 +phy_xaui_rx_polarity_flip_16.0=0x0 +phy_xaui_rx_polarity_flip_17.0=0x0 +phy_xaui_rx_polarity_flip_18.0=0x0 +phy_xaui_rx_polarity_flip_19.0=0x0 +phy_xaui_rx_polarity_flip_2.0=0x0 +phy_xaui_rx_polarity_flip_20.0=0x0 +phy_xaui_rx_polarity_flip_21.0=0x0 +phy_xaui_rx_polarity_flip_22.0=0x0 +phy_xaui_rx_polarity_flip_23.0=0x0 +phy_xaui_rx_polarity_flip_24.0=0x0 +phy_xaui_rx_polarity_flip_25.0=0x0 +phy_xaui_rx_polarity_flip_26.0=0x0 +phy_xaui_rx_polarity_flip_27.0=0x0 +phy_xaui_rx_polarity_flip_28.0=0x0 +phy_xaui_rx_polarity_flip_29.0=0x0 +phy_xaui_rx_polarity_flip_3.0=0x0 +phy_xaui_rx_polarity_flip_30.0=0x0 +phy_xaui_rx_polarity_flip_31.0=0x0 +phy_xaui_rx_polarity_flip_32.0=0x0 +phy_xaui_rx_polarity_flip_4.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x0 +phy_xaui_rx_polarity_flip_6.0=0x0 +phy_xaui_rx_polarity_flip_7.0=0x0 +phy_xaui_rx_polarity_flip_8.0=0x0 +phy_xaui_rx_polarity_flip_9.0=0x0 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_10.0=0x0 +phy_xaui_tx_polarity_flip_11.0=0x0 +phy_xaui_tx_polarity_flip_12.0=0x0 +phy_xaui_tx_polarity_flip_13.0=0x0 +phy_xaui_tx_polarity_flip_14.0=0x0 +phy_xaui_tx_polarity_flip_15.0=0x0 +phy_xaui_tx_polarity_flip_16.0=0x0 +phy_xaui_tx_polarity_flip_17.0=0x0 +phy_xaui_tx_polarity_flip_18.0=0x0 +phy_xaui_tx_polarity_flip_19.0=0x0 +phy_xaui_tx_polarity_flip_2.0=0x0 +phy_xaui_tx_polarity_flip_20.0=0x0 +phy_xaui_tx_polarity_flip_21.0=0x0 +phy_xaui_tx_polarity_flip_22.0=0x0 +phy_xaui_tx_polarity_flip_23.0=0x0 +phy_xaui_tx_polarity_flip_24.0=0x0 +phy_xaui_tx_polarity_flip_25.0=0x0 +phy_xaui_tx_polarity_flip_26.0=0x0 +phy_xaui_tx_polarity_flip_27.0=0x0 +phy_xaui_tx_polarity_flip_28.0=0x0 +phy_xaui_tx_polarity_flip_29.0=0x0 +phy_xaui_tx_polarity_flip_3.0=0x0 +phy_xaui_tx_polarity_flip_30.0=0x0 +phy_xaui_tx_polarity_flip_31.0=0x0 +phy_xaui_tx_polarity_flip_32.0=0x0 +phy_xaui_tx_polarity_flip_4.0=0x0 +phy_xaui_tx_polarity_flip_5.0=0x0 +phy_xaui_tx_polarity_flip_6.0=0x0 +phy_xaui_tx_polarity_flip_7.0=0x0 +phy_xaui_tx_polarity_flip_8.0=0x0 +phy_xaui_tx_polarity_flip_9.0=0x0 +port_init_autoneg_10.0=0 +port_init_autoneg_11.0=0 +port_init_autoneg_12.0=0 +port_init_autoneg_13.0=0 +port_init_autoneg_14.0=0 +port_init_autoneg_15.0=0 +port_init_autoneg_16.0=0 +port_init_autoneg_17.0=0 +port_init_autoneg_18.0=0 +port_init_autoneg_19.0=0 +port_init_autoneg_20.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_22.0=0 +port_init_autoneg_23.0=0 +port_init_autoneg_24.0=0 +port_init_autoneg_25.0=0 +port_init_autoneg_26.0=0 +port_init_autoneg_27.0=0 +port_init_autoneg_28.0=0 +port_init_autoneg_5.0=0 +port_init_autoneg_6.0=0 +port_init_autoneg_7.0=0 +port_init_autoneg_8.0=0 +port_init_autoneg_9.0=0 +port_init_cl72_hg.0=0x11 +port_phy_addr_1.0=0x4 +port_phy_addr_10.0=0x7f +port_phy_addr_11.0=0x7f +port_phy_addr_12.0=0x7f +port_phy_addr_13.0=0x7f +port_phy_addr_14.0=0x7f +port_phy_addr_15.0=0x7f +port_phy_addr_16.0=0x7f +port_phy_addr_17.0=0x7f +port_phy_addr_18.0=0x7f +port_phy_addr_19.0=0x7f +port_phy_addr_2.0=0x0 +port_phy_addr_20.0=0x7f +port_phy_addr_21.0=0x7f +port_phy_addr_22.0=0x7f +port_phy_addr_23.0=0x7f +port_phy_addr_24.0=0x7f +port_phy_addr_25.0=0x7f +port_phy_addr_26.0=0x7f +port_phy_addr_27.0=0x7f +port_phy_addr_28.0=0x7f +port_phy_addr_29.0=0x54 +port_phy_addr_3.0=0x2c +port_phy_addr_30.0=0x50 +port_phy_addr_31.0=0x7c +port_phy_addr_32.0=0x78 +port_phy_addr_4.0=0x28 +port_phy_addr_5.0=0x7f +port_phy_addr_6.0=0x7f +port_phy_addr_7.0=0x7f +port_phy_addr_8.0=0x7f +port_phy_addr_9.0=0x7f +port_phy_clause_1.0=0x2d +port_phy_clause_2.0=0x2d +port_phy_clause_29.0=0x2d +port_phy_clause_3.0=0x2d +port_phy_clause_30.0=0x2d +port_phy_clause_31.0=0x2d +port_phy_clause_32.0=0x2d +port_phy_clause_4.0=0x2d +port_phy_id0_1.0=0x600d +port_phy_id0_2.0=0x600d +port_phy_id0_29.0=0x600d +port_phy_id0_3.0=0x600d +port_phy_id0_30.0=0x600d +port_phy_id0_31.0=0x600d +port_phy_id0_32.0=0x600d +port_phy_id0_4.0=0x600d +port_phy_id1_1.0=0x8500 +port_phy_id1_2.0=0x8500 +port_phy_id1_29.0=0x8500 +port_phy_id1_3.0=0x8500 +port_phy_id1_30.0=0x8500 +port_phy_id1_31.0=0x8500 +port_phy_id1_32.0=0x8500 +port_phy_id1_4.0=0x8500 +portmap_1.0=125:40 +portmap_10.0=33:40 +portmap_11.0=45:40 +portmap_12.0=41:40 +portmap_13.0=53:40 +portmap_14.0=49:40 +portmap_15.0=69:40 +portmap_16.0=65:40 +portmap_17.0=77:40 +portmap_18.0=73:40 +portmap_19.0=93:40 +portmap_2.0=121:40 +portmap_20.0=89:40 +portmap_21.0=101:40 +portmap_22.0=97:40 +portmap_23.0=109:40 +portmap_24.0=105:40 +portmap_25.0=61:40 +portmap_26.0=57:40 +portmap_27.0=81:40 +portmap_28.0=85:40 +portmap_29.0=117:40 +portmap_3.0=13:40 +portmap_30.0=113:40 +portmap_31.0=5:40 +portmap_32.0=1:40 +portmap_4.0=9:40 +portmap_5.0=17:40 +portmap_6.0=21:40 +portmap_7.0=25:40 +portmap_8.0=29:40 +portmap_9.0=37:40 +serdes_firmware_mode_1.0=1 +serdes_firmware_mode_10.0=2 +serdes_firmware_mode_11.0=2 +serdes_firmware_mode_12.0=2 +serdes_firmware_mode_13.0=2 +serdes_firmware_mode_14.0=2 +serdes_firmware_mode_15.0=2 +serdes_firmware_mode_16.0=2 +serdes_firmware_mode_17.0=2 +serdes_firmware_mode_18.0=2 +serdes_firmware_mode_19.0=2 +serdes_firmware_mode_2.0=1 +serdes_firmware_mode_20.0=2 +serdes_firmware_mode_21.0=2 +serdes_firmware_mode_22.0=2 +serdes_firmware_mode_23.0=2 +serdes_firmware_mode_24.0=2 +serdes_firmware_mode_25.0=2 +serdes_firmware_mode_26.0=2 +serdes_firmware_mode_27.0=2 +serdes_firmware_mode_28.0=2 +serdes_firmware_mode_29.0=1 +serdes_firmware_mode_3.0=1 +serdes_firmware_mode_30.0=1 +serdes_firmware_mode_31.0=1 +serdes_firmware_mode_32.0=1 +serdes_firmware_mode_4.0=1 +serdes_firmware_mode_5.0=2 +serdes_firmware_mode_6.0=2 +serdes_firmware_mode_7.0=2 +serdes_firmware_mode_8.0=2 +serdes_firmware_mode_9.0=2 +xgxs_lcpll_xtal_refclk.0=1 +xgxs_rx_lane_map_1.0=0x0123 +xgxs_rx_lane_map_10.0=0x3120 +xgxs_rx_lane_map_11.0=0x3120 +xgxs_rx_lane_map_12.0=0x3120 +xgxs_rx_lane_map_13.0=0x3120 +xgxs_rx_lane_map_14.0=0x3120 +xgxs_rx_lane_map_15.0=0x3120 +xgxs_rx_lane_map_16.0=0x3120 +xgxs_rx_lane_map_17.0=0x3120 +xgxs_rx_lane_map_18.0=0x3120 +xgxs_rx_lane_map_19.0=0x3120 +xgxs_rx_lane_map_2.0=0x0123 +xgxs_rx_lane_map_20.0=0x3120 +xgxs_rx_lane_map_21.0=0x3120 +xgxs_rx_lane_map_22.0=0x3120 +xgxs_rx_lane_map_23.0=0x3120 +xgxs_rx_lane_map_24.0=0x3120 +xgxs_rx_lane_map_25.0=0x2031 +xgxs_rx_lane_map_26.0=0x2031 +xgxs_rx_lane_map_27.0=0x0213 +xgxs_rx_lane_map_28.0=0x0213 +xgxs_rx_lane_map_29.0=0x0123 +xgxs_rx_lane_map_3.0=0x0123 +xgxs_rx_lane_map_30.0=0x0123 +xgxs_rx_lane_map_31.0=0x0123 +xgxs_rx_lane_map_32.0=0x0123 +xgxs_rx_lane_map_4.0=0x0123 +xgxs_rx_lane_map_5.0=0x2031 +xgxs_rx_lane_map_6.0=0x2031 +xgxs_rx_lane_map_7.0=0x2031 +xgxs_rx_lane_map_8.0=0x2031 +xgxs_rx_lane_map_9.0=0x3120 +xgxs_tx_lane_map_1.0=0x0123 +xgxs_tx_lane_map_10.0=0x3120 +xgxs_tx_lane_map_11.0=0x3120 +xgxs_tx_lane_map_12.0=0x3120 +xgxs_tx_lane_map_13.0=0x3120 +xgxs_tx_lane_map_14.0=0x3120 +xgxs_tx_lane_map_15.0=0x3120 +xgxs_tx_lane_map_16.0=0x3120 +xgxs_tx_lane_map_17.0=0x3120 +xgxs_tx_lane_map_18.0=0x3120 +xgxs_tx_lane_map_19.0=0x3120 +xgxs_tx_lane_map_2.0=0x0123 +xgxs_tx_lane_map_20.0=0x3120 +xgxs_tx_lane_map_21.0=0x3120 +xgxs_tx_lane_map_22.0=0x3120 +xgxs_tx_lane_map_23.0=0x3120 +xgxs_tx_lane_map_24.0=0x3120 +xgxs_tx_lane_map_25.0=0x2031 +xgxs_tx_lane_map_26.0=0x2031 +xgxs_tx_lane_map_27.0=0x0213 +xgxs_tx_lane_map_28.0=0x0213 +xgxs_tx_lane_map_29.0=0x0123 +xgxs_tx_lane_map_3.0=0x0123 +xgxs_tx_lane_map_30.0=0x0123 +xgxs_tx_lane_map_31.0=0x0123 +xgxs_tx_lane_map_32.0=0x0123 +xgxs_tx_lane_map_4.0=0x0123 +xgxs_tx_lane_map_5.0=0x1302 +xgxs_tx_lane_map_6.0=0x1302 +xgxs_tx_lane_map_7.0=0x1302 +xgxs_tx_lane_map_8.0=0x1302 +xgxs_tx_lane_map_9.0=0x3120 + +########################################## +#skip_L2_USER_ENTRY=0 +phy_aux_voltage_enable=1 +############################### +serdes_fiber_pref=1 +############################### +mdio_output_delay.0=0x0d +############################### +serdes_sgmii_m=0 +xgxs_lcpll_xtal_refclk=1 +xgxs_lcpll_xtal_refclk.1=1 +xgxs_lcpll_xtal_refclk.2=1 +xgxs_lcpll_xtal_refclk.3=1 +tdma_intr_enable=1 +tslam_intr_enable=1 +tslam_dma_enable.2=1 +tslam_dma_enable.3=1 +#dport_map_port=0 +#dport_map_enable=0 +#dport_map_indexed=0 +#bcm_xlate_port_enable.0=0 +#xgxs_pdetect_1=0 +table_dma_enable.0=1 +table_dma_enable.1=1 +table_dma_enable.2=1 +table_dma_enable.3=1 +serdes_driver_current_lane0_1=2 +serdes_pre_driver_current_lane0_1=2 +serdes_preemphasis_lane0_1=0x8fc0 +serdes_driver_current_lane1_1=2 +serdes_pre_driver_current_lane1_1=2 +serdes_preemphasis_lane1_1=0x8fc0 +serdes_driver_current_lane2_1=2 +serdes_pre_driver_current_lane2_1=2 +serdes_preemphasis_lane2_1=0x8fc0 +serdes_driver_current_lane3_1=2 +serdes_pre_driver_current_lane3_1=2 +serdes_preemphasis_lane3_1=0x8fc0 +serdes_driver_current_lane0_2=3 +serdes_pre_driver_current_lane0_2=2 +serdes_preemphasis_lane0_2=0x8fc0 +serdes_driver_current_lane1_2=3 +serdes_pre_driver_current_lane1_2=2 +serdes_preemphasis_lane1_2=0x8fc0 +serdes_driver_current_lane2_2=3 +serdes_pre_driver_current_lane2_2=2 +serdes_preemphasis_lane2_2=0x8fc0 +serdes_driver_current_lane3_2=3 +serdes_pre_driver_current_lane3_2=2 +serdes_preemphasis_lane3_2=0x8fc0 +serdes_driver_current_lane0_3=2 +serdes_pre_driver_current_lane0_3=2 +serdes_preemphasis_lane0_3=0x8fc0 +serdes_driver_current_lane1_3=2 +serdes_pre_driver_current_lane1_3=2 +serdes_preemphasis_lane1_3=0x8fc0 +serdes_driver_current_lane2_3=2 +serdes_pre_driver_current_lane2_3=2 +serdes_preemphasis_lane2_3=0x8fc0 +serdes_driver_current_lane3_3=2 +serdes_pre_driver_current_lane3_3=2 +serdes_preemphasis_lane3_3=0x8fc0 +serdes_driver_current_lane0_4=2 +serdes_pre_driver_current_lane0_4=2 +serdes_preemphasis_lane0_4=0x8fc0 +serdes_driver_current_lane1_4=2 +serdes_pre_driver_current_lane1_4=2 +serdes_preemphasis_lane1_4=0x8fc0 +serdes_driver_current_lane2_4=2 +serdes_pre_driver_current_lane2_4=2 +serdes_preemphasis_lane2_4=0x8fc0 +serdes_driver_current_lane3_4=2 +serdes_pre_driver_current_lane3_4=2 +serdes_preemphasis_lane3_4=0x8fc0 +serdes_driver_current_lane0_5=4 +serdes_pre_driver_current_lane0_5=4 +serdes_preemphasis_lane0_5=0xbf00 +serdes_driver_current_lane1_5=4 +serdes_pre_driver_current_lane1_5=4 +serdes_preemphasis_lane1_5=0xbf00 +serdes_driver_current_lane2_5=4 +serdes_pre_driver_current_lane2_5=4 +serdes_preemphasis_lane2_5=0xbf00 +serdes_driver_current_lane3_5=4 +serdes_pre_driver_current_lane3_5=4 +serdes_preemphasis_lane3_5=0xbf00 +serdes_driver_current_lane0_6=4 +serdes_pre_driver_current_lane0_6=4 +serdes_preemphasis_lane0_6=0xbb10 +serdes_driver_current_lane1_6=4 +serdes_pre_driver_current_lane1_6=4 +serdes_preemphasis_lane1_6=0xbb10 +serdes_driver_current_lane2_6=4 +serdes_pre_driver_current_lane2_6=4 +serdes_preemphasis_lane2_6=0xbb10 +serdes_driver_current_lane3_6=4 +serdes_pre_driver_current_lane3_6=4 +serdes_preemphasis_lane3_6=0xbb10 +serdes_driver_current_lane0_7=3 +serdes_pre_driver_current_lane0_7=3 +serdes_preemphasis_lane0_7=0xcad0 +serdes_driver_current_lane1_7=3 +serdes_pre_driver_current_lane1_7=3 +serdes_preemphasis_lane1_7=0xcad0 +serdes_driver_current_lane2_7=3 +serdes_pre_driver_current_lane2_7=3 +serdes_preemphasis_lane2_7=0xcad0 +serdes_driver_current_lane3_7=3 +serdes_pre_driver_current_lane3_7=3 +serdes_preemphasis_lane3_7=0xcad0 +serdes_driver_current_lane0_8=3 +serdes_pre_driver_current_lane0_8=3 +serdes_preemphasis_lane0_8=0xcad0 +serdes_driver_current_lane1_8=3 +serdes_pre_driver_current_lane1_8=3 +serdes_preemphasis_lane1_8=0xcad0 +serdes_driver_current_lane2_8=3 +serdes_pre_driver_current_lane2_8=3 +serdes_preemphasis_lane2_8=0xcad0 +serdes_driver_current_lane3_8=3 +serdes_pre_driver_current_lane3_8=3 +serdes_preemphasis_lane3_8=0xcad0 +serdes_driver_current_lane0_9=3 +serdes_pre_driver_current_lane0_9=3 +serdes_preemphasis_lane0_9=0xc2f0 +serdes_driver_current_lane1_9=3 +serdes_pre_driver_current_lane1_9=3 +serdes_preemphasis_lane1_9=0xc2f0 +serdes_driver_current_lane2_9=3 +serdes_pre_driver_current_lane2_9=3 +serdes_preemphasis_lane2_9=0xc2f0 +serdes_driver_current_lane3_9=3 +serdes_pre_driver_current_lane3_9=3 +serdes_preemphasis_lane3_9=0xc2f0 +serdes_driver_current_lane0_10=3 +serdes_pre_driver_current_lane0_10=3 +serdes_preemphasis_lane0_10=0xc6e0 +serdes_driver_current_lane1_10=3 +serdes_pre_driver_current_lane1_10=3 +serdes_preemphasis_lane1_10=0xc6e0 +serdes_driver_current_lane2_10=3 +serdes_pre_driver_current_lane2_10=3 +serdes_preemphasis_lane2_10=0xc6e0 +serdes_driver_current_lane3_10=3 +serdes_pre_driver_current_lane3_10=3 +serdes_preemphasis_lane3_10=0xc6e0 +serdes_driver_current_lane0_11=3 +serdes_pre_driver_current_lane0_11=3 +serdes_preemphasis_lane0_11=0xc2f0 +serdes_driver_current_lane1_11=3 +serdes_pre_driver_current_lane1_11=3 +serdes_preemphasis_lane1_11=0xc2f0 +serdes_driver_current_lane2_11=3 +serdes_pre_driver_current_lane2_11=3 +serdes_preemphasis_lane2_11=0xc2f0 +serdes_driver_current_lane3_11=3 +serdes_pre_driver_current_lane3_11=3 +serdes_preemphasis_lane3_11=0xc2f0 +serdes_driver_current_lane0_12=3 +serdes_pre_driver_current_lane0_12=3 +serdes_preemphasis_lane0_12=0xc2f0 +serdes_driver_current_lane1_12=3 +serdes_pre_driver_current_lane1_12=3 +serdes_preemphasis_lane1_12=0xc2f0 +serdes_driver_current_lane2_12=3 +serdes_pre_driver_current_lane2_12=3 +serdes_preemphasis_lane2_12=0xc2f0 +serdes_driver_current_lane3_12=3 +serdes_pre_driver_current_lane3_12=3 +serdes_preemphasis_lane3_12=0xc2f0 +serdes_driver_current_lane0_13=3 +serdes_pre_driver_current_lane0_13=3 +serdes_preemphasis_lane0_13=0xc2f0 +serdes_driver_current_lane1_13=3 +serdes_pre_driver_current_lane1_13=3 +serdes_preemphasis_lane1_13=0xc2f0 +serdes_driver_current_lane2_13=3 +serdes_pre_driver_current_lane2_13=3 +serdes_preemphasis_lane2_13=0xc2f0 +serdes_driver_current_lane3_13=3 +serdes_pre_driver_current_lane3_13=3 +serdes_preemphasis_lane3_13=0xc2f0 +serdes_driver_current_lane0_14=3 +serdes_pre_driver_current_lane0_14=3 +serdes_preemphasis_lane0_14=0xc2f0 +serdes_driver_current_lane1_14=3 +serdes_pre_driver_current_lane1_14=3 +serdes_preemphasis_lane1_14=0xc2f0 +serdes_driver_current_lane2_14=3 +serdes_pre_driver_current_lane2_14=3 +serdes_preemphasis_lane2_14=0xc2f0 +serdes_driver_current_lane3_14=3 +serdes_pre_driver_current_lane3_14=3 +serdes_preemphasis_lane3_14=0xc2f0 +serdes_driver_current_lane0_15=3 +serdes_pre_driver_current_lane0_15=3 +serdes_preemphasis_lane0_15=0xc2f0 +serdes_driver_current_lane1_15=3 +serdes_pre_driver_current_lane1_15=3 +serdes_preemphasis_lane1_15=0xc2f0 +serdes_driver_current_lane2_15=3 +serdes_pre_driver_current_lane2_15=3 +serdes_preemphasis_lane2_15=0xc2f0 +serdes_driver_current_lane3_15=3 +serdes_pre_driver_current_lane3_15=3 +serdes_preemphasis_lane3_15=0xc2f0 +serdes_driver_current_lane0_16=3 +serdes_pre_driver_current_lane0_16=3 +serdes_preemphasis_lane0_16=0xc2f0 +serdes_driver_current_lane1_16=3 +serdes_pre_driver_current_lane1_16=3 +serdes_preemphasis_lane1_16=0xc2f0 +serdes_driver_current_lane2_16=3 +serdes_pre_driver_current_lane2_16=3 +serdes_preemphasis_lane2_16=0xc2f0 +serdes_driver_current_lane3_16=3 +serdes_pre_driver_current_lane3_16=3 +serdes_preemphasis_lane3_16=0xc2f0 +serdes_driver_current_lane0_17=3 +serdes_pre_driver_current_lane0_17=3 +serdes_preemphasis_lane0_17=0xc2f0 +serdes_driver_current_lane1_17=3 +serdes_pre_driver_current_lane1_17=3 +serdes_preemphasis_lane1_17=0xc2f0 +serdes_driver_current_lane2_17=3 +serdes_pre_driver_current_lane2_17=3 +serdes_preemphasis_lane2_17=0xc2f0 +serdes_driver_current_lane3_17=3 +serdes_pre_driver_current_lane3_17=3 +serdes_preemphasis_lane3_17=0xc2f0 +serdes_driver_current_lane0_18=3 +serdes_pre_driver_current_lane0_18=3 +serdes_preemphasis_lane0_18=0xc2f0 +serdes_driver_current_lane1_18=3 +serdes_pre_driver_current_lane1_18=3 +serdes_preemphasis_lane1_18=0xc2f0 +serdes_driver_current_lane2_18=3 +serdes_pre_driver_current_lane2_18=3 +serdes_preemphasis_lane2_18=0xc2f0 +serdes_driver_current_lane3_18=3 +serdes_pre_driver_current_lane3_18=3 +serdes_preemphasis_lane3_18=0xc2f0 +serdes_driver_current_lane0_19=3 +serdes_pre_driver_current_lane0_19=3 +serdes_preemphasis_lane0_19=0xc2f0 +serdes_driver_current_lane1_19=3 +serdes_pre_driver_current_lane1_19=3 +serdes_preemphasis_lane1_19=0xc2f0 +serdes_driver_current_lane2_19=3 +serdes_pre_driver_current_lane2_19=3 +serdes_preemphasis_lane2_19=0xc2f0 +serdes_driver_current_lane3_19=3 +serdes_pre_driver_current_lane3_19=3 +serdes_preemphasis_lane3_19=0xc2f0 +serdes_driver_current_lane0_20=3 +serdes_pre_driver_current_lane0_20=3 +serdes_preemphasis_lane0_20=0xc2f0 +serdes_driver_current_lane1_20=3 +serdes_pre_driver_current_lane1_20=3 +serdes_preemphasis_lane1_20=0xc2f0 +serdes_driver_current_lane2_20=3 +serdes_pre_driver_current_lane2_20=3 +serdes_preemphasis_lane2_20=0xc2f0 +serdes_driver_current_lane3_20=3 +serdes_pre_driver_current_lane3_20=3 +serdes_preemphasis_lane3_20=0xc2f0 +serdes_driver_current_lane0_21=3 +serdes_pre_driver_current_lane0_21=3 +serdes_preemphasis_lane0_21=0xc6e0 +serdes_driver_current_lane1_21=3 +serdes_pre_driver_current_lane1_21=3 +serdes_preemphasis_lane1_21=0xc6e0 +serdes_driver_current_lane2_21=3 +serdes_pre_driver_current_lane2_21=3 +serdes_preemphasis_lane2_21=0xc6e0 +serdes_driver_current_lane3_21=3 +serdes_pre_driver_current_lane3_21=3 +serdes_preemphasis_lane3_21=0xc6e0 +serdes_driver_current_lane0_22=3 +serdes_pre_driver_current_lane0_22=3 +serdes_preemphasis_lane0_22=0xc6e0 +serdes_driver_current_lane1_22=3 +serdes_pre_driver_current_lane1_22=3 +serdes_preemphasis_lane1_22=0xc6e0 +serdes_driver_current_lane2_22=3 +serdes_pre_driver_current_lane2_22=3 +serdes_preemphasis_lane2_22=0xc6e0 +serdes_driver_current_lane3_22=3 +serdes_pre_driver_current_lane3_22=3 +serdes_preemphasis_lane3_22=0xc6e0 +serdes_driver_current_lane0_23=3 +serdes_pre_driver_current_lane0_23=3 +serdes_preemphasis_lane0_23=0xcad0 +serdes_driver_current_lane1_23=3 +serdes_pre_driver_current_lane1_23=3 +serdes_preemphasis_lane1_23=0xcad0 +serdes_driver_current_lane2_23=3 +serdes_pre_driver_current_lane2_23=3 +serdes_preemphasis_lane2_23=0xcad0 +serdes_driver_current_lane3_23=3 +serdes_pre_driver_current_lane3_23=3 +serdes_preemphasis_lane3_23=0xcad0 +serdes_driver_current_lane0_24=3 +serdes_pre_driver_current_lane0_24=3 +serdes_preemphasis_lane0_24=0xcad0 +serdes_driver_current_lane1_24=3 +serdes_pre_driver_current_lane1_24=3 +serdes_preemphasis_lane1_24=0xcad0 +serdes_driver_current_lane2_24=3 +serdes_pre_driver_current_lane2_24=3 +serdes_preemphasis_lane2_24=0xcad0 +serdes_driver_current_lane3_24=3 +serdes_pre_driver_current_lane3_24=3 +serdes_preemphasis_lane3_24=0xcad0 +serdes_driver_current_lane0_25=5 +serdes_pre_driver_current_lane0_25=5 +serdes_preemphasis_lane0_25=0xc2f0 +serdes_driver_current_lane1_25=5 +serdes_pre_driver_current_lane1_25=5 +serdes_preemphasis_lane1_25=0xc2f0 +serdes_driver_current_lane2_25=5 +serdes_pre_driver_current_lane2_25=5 +serdes_preemphasis_lane2_25=0xc2f0 +serdes_driver_current_lane3_25=5 +serdes_pre_driver_current_lane3_25=5 +serdes_preemphasis_lane3_25=0xc2f0 +serdes_driver_current_lane0_26=5 +serdes_pre_driver_current_lane0_26=5 +serdes_preemphasis_lane0_26=0xc2f0 +serdes_driver_current_lane1_26=5 +serdes_pre_driver_current_lane1_26=5 +serdes_preemphasis_lane1_26=0xc2f0 +serdes_driver_current_lane2_26=5 +serdes_pre_driver_current_lane2_26=5 +serdes_preemphasis_lane2_26=0xc2f0 +serdes_driver_current_lane3_26=5 +serdes_pre_driver_current_lane3_26=5 +serdes_preemphasis_lane3_26=0xc2f0 +serdes_driver_current_lane0_27=5 +serdes_pre_driver_current_lane0_27=5 +serdes_preemphasis_lane0_27=0xc2f0 +serdes_driver_current_lane1_27=5 +serdes_pre_driver_current_lane1_27=5 +serdes_preemphasis_lane1_27=0xc2f0 +serdes_driver_current_lane2_27=5 +serdes_pre_driver_current_lane2_27=5 +serdes_preemphasis_lane2_27=0xc2f0 +serdes_driver_current_lane3_27=5 +serdes_pre_driver_current_lane3_27=5 +serdes_preemphasis_lane3_27=0xc2f0 +serdes_driver_current_lane0_28=8 +serdes_pre_driver_current_lane0_28=6 +serdes_preemphasis_lane0_28=0xc2f0 +serdes_driver_current_lane1_28=8 +serdes_pre_driver_current_lane1_28=6 +serdes_preemphasis_lane1_28=0xc2f0 +serdes_driver_current_lane2_28=8 +serdes_pre_driver_current_lane2_28=6 +serdes_preemphasis_lane2_28=0xc2f0 +serdes_driver_current_lane3_28=8 +serdes_pre_driver_current_lane3_28=6 +serdes_preemphasis_lane3_28=0xc2f0 +serdes_driver_current_lane0_29=2 +serdes_pre_driver_current_lane0_29=2 +serdes_preemphasis_lane0_29=0x8fc0 +serdes_driver_current_lane1_29=2 +serdes_pre_driver_current_lane1_29=2 +serdes_preemphasis_lane1_29=0x8fc0 +serdes_driver_current_lane2_29=2 +serdes_pre_driver_current_lane2_29=2 +serdes_preemphasis_lane2_29=0x8fc0 +serdes_driver_current_lane3_29=2 +serdes_pre_driver_current_lane3_29=2 +serdes_preemphasis_lane3_29=0x8fc0 +serdes_driver_current_lane0_30=2 +serdes_pre_driver_current_lane0_30=2 +serdes_preemphasis_lane0_30=0x8fc0 +serdes_driver_current_lane1_30=2 +serdes_pre_driver_current_lane1_30=2 +serdes_preemphasis_lane1_30=0x8fc0 +serdes_driver_current_lane2_30=2 +serdes_pre_driver_current_lane2_30=2 +serdes_preemphasis_lane2_30=0x8fc0 +serdes_driver_current_lane3_30=2 +serdes_pre_driver_current_lane3_30=2 +serdes_preemphasis_lane3_30=0x8fc0 +serdes_driver_current_lane0_31=2 +serdes_pre_driver_current_lane0_31=2 +serdes_preemphasis_lane0_31=0x8fc0 +serdes_driver_current_lane1_31=2 +serdes_pre_driver_current_lane1_31=2 +serdes_preemphasis_lane1_31=0x8fc0 +serdes_driver_current_lane2_31=2 +serdes_pre_driver_current_lane2_31=2 +serdes_preemphasis_lane2_31=0x8fc0 +serdes_driver_current_lane3_31=2 +serdes_pre_driver_current_lane3_31=2 +serdes_preemphasis_lane3_31=0x8fc0 +serdes_driver_current_lane0_32=2 +serdes_pre_driver_current_lane0_32=2 +serdes_preemphasis_lane0_32=0x8fc0 +serdes_driver_current_lane1_32=2 +serdes_pre_driver_current_lane1_32=2 +serdes_preemphasis_lane1_32=0x8fc0 +serdes_driver_current_lane2_32=2 +serdes_pre_driver_current_lane2_32=2 +serdes_preemphasis_lane2_32=0x8fc0 +serdes_driver_current_lane3_32=2 +serdes_pre_driver_current_lane3_32=2 +serdes_preemphasis_lane3_32=0x8fc0 diff --git a/device/arista/x86_64-arista_7050_qx32/default_sku b/device/arista/x86_64-arista_7050_qx32/default_sku new file mode 100644 index 000000000000..8c19bef02a08 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/default_sku @@ -0,0 +1 @@ +Arista-7050-QX32 t1 diff --git a/device/arista/x86_64-arista_7050_qx32/fancontrol b/device/arista/x86_64-arista_7050_qx32/fancontrol new file mode 100644 index 000000000000..1d94fcf7674c --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=5 +DEVPATH=hwmon1=devices/platform/sb800-fans hwmon2=devices/pci0000:00/0000:00:09.0/0000:04:00.0/i2c-5/5-004c +DEVNAME=hwmon1=fans hwmon2=max6658 +FCTEMPS=hwmon1/pwm4=hwmon2/temp1_input hwmon1/pwm3=hwmon2/temp1_input hwmon1/pwm2=hwmon2/temp1_input hwmon1/pwm1=hwmon2/temp1_input +FCFANS=hwmon1/pwm4=hwmon1/fan4_input hwmon1/pwm3=hwmon1/fan3_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm1=hwmon1/fan1_input +MINTEMP=hwmon1/pwm4=30 hwmon1/pwm3=30 hwmon1/pwm2=30 hwmon1/pwm1=30 +MINPWM=hwmon1/pwm4=179 hwmon1/pwm3=179 hwmon1/pwm2=179 hwmon1/pwm1=179 +MAXTEMP=hwmon1/pwm4=40 hwmon1/pwm3=40 hwmon1/pwm2=40 hwmon1/pwm1=40 +MINSTART=hwmon1/pwm4=179 hwmon1/pwm3=179 hwmon1/pwm2=179 hwmon1/pwm1=179 +MINSTOP=hwmon1/pwm4=179 hwmon1/pwm3=179 hwmon1/pwm2=179 hwmon1/pwm1=179 diff --git a/device/arista/x86_64-arista_7050_qx32/platform.json b/device/arista/x86_64-arista_7050_qx32/platform.json new file mode 100644 index 000000000000..9cf2acddfaf3 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/platform.json @@ -0,0 +1,189 @@ +{ + "chassis": { + "name": "DCS-7050QX-32", + "components": [], + "fans": [ + { + "name": "fan1" + }, + { + "name": "fan2" + }, + { + "name": "fan3" + }, + { + "name": "fan4" + } + ], + "fan_drawers": [ + { + "name": "fan1", + "fans": [ + { + "name": "fan1" + } + ] + }, + { + "name": "fan2", + "fans": [ + { + "name": "fan2" + } + ] + }, + { + "name": "fan3", + "fans": [ + { + "name": "fan3" + } + ] + }, + { + "name": "fan4", + "fans": [ + { + "name": "fan4" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Cpu temp sensor" + }, + { + "name": "Board sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Rear temp sensor" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 internal sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 internal sensor" + } + ], + "sfps": [ + { + "name": "qsfp1" + }, + { + "name": "qsfp2" + }, + { + "name": "qsfp3" + }, + { + "name": "qsfp4" + }, + { + "name": "qsfp5" + }, + { + "name": "qsfp6" + }, + { + "name": "qsfp7" + }, + { + "name": "qsfp8" + }, + { + "name": "qsfp9" + }, + { + "name": "qsfp10" + }, + { + "name": "qsfp11" + }, + { + "name": "qsfp12" + }, + { + "name": "qsfp13" + }, + { + "name": "qsfp14" + }, + { + "name": "qsfp15" + }, + { + "name": "qsfp16" + }, + { + "name": "qsfp17" + }, + { + "name": "qsfp18" + }, + { + "name": "qsfp19" + }, + { + "name": "qsfp20" + }, + { + "name": "qsfp21" + }, + { + "name": "qsfp22" + }, + { + "name": "qsfp23" + }, + { + "name": "qsfp24" + }, + { + "name": "qsfp25" + }, + { + "name": "qsfp26" + }, + { + "name": "qsfp27" + }, + { + "name": "qsfp28" + }, + { + "name": "qsfp29" + }, + { + "name": "qsfp30" + }, + { + "name": "qsfp31" + }, + { + "name": "qsfp32" + } + ] + }, + "interfaces": {} +} \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32/platform_reboot b/device/arista/x86_64-arista_7050_qx32/platform_reboot new file mode 120000 index 000000000000..7f94a49e38b0 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/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_7050_qx32/plugins b/device/arista/x86_64-arista_7050_qx32/plugins new file mode 120000 index 000000000000..5fbbf98a6284 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/plugins @@ -0,0 +1 @@ +../x86_64-arista_common/plugins/ \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32/pmon_daemon_control.json b/device/arista/x86_64-arista_7050_qx32/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32/sensors.conf b/device/arista/x86_64-arista_7050_qx32/sensors.conf new file mode 100644 index 000000000000..8b6ca752fe83 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/sensors.conf @@ -0,0 +1,82 @@ +# libsensors configuration file for DCS-7050QX-32 +# ------------------------------------------------ +# + +bus "i2c-5" "SCD 0000:04:00.0 SMBus master 0 bus 0" +bus "i2c-6" "SCD 0000:04:00.0 SMBus master 0 bus 1" +bus "i2c-8" "SCD 0000:04:00.0 SMBus master 0 bus 3" +bus "i2c-9" "SCD 0000:04:00.0 SMBus master 0 bus 4" +bus "i2c-10" "SCD 0000:04:00.0 SMBus master 0 bus 5" + +chip "k10temp-pci-00c3" + label temp1 "Cpu temp sensor" + +chip "lm73-i2c-6-48" + label temp1 "Back panel temp sensor" + set temp1_max 65 + #set temp1_max_alarm 75 # read-only + +chip "max6658-i2c-5-4c" + label temp1 "Board temp sensor" + set temp1_max 65 + set temp1_crit 75 + + label temp2 "Front panel temp sensor" + set temp2_max 65 + set temp2_crit 75 + +# disabled because of some eeprom corruption risks +#chip "pmbus-i2c-6-4e" +# label temp1 "Power controller sensor 1" +# set temp1_max 60 +# set temp1_crit 70 + +# label temp2 "Power controller sensor 2" +# set temp2_max 60 +# set temp2_crit 70 + +# ignore curr1 + +chip "dps460-i2c-8-58" + label temp1 "Power supply 1 inlet temp sensor" + # maximum and critical thresholds are not supported for this psu + set temp1_max 60 + set temp1_crit 70 + + label temp2 "Power supply 1 internal sensor" + set temp2_max 60 + set temp2_crit 70 + + ignore temp3 + + set in1_max 250 + set in1_crit 255 + set power1_max 525 + set power2_max 460 + set power2_crit 462 + set curr1_max 5.28 + set curr1_crit 5.30 + set curr2_max 36 + set curr2_crit 37 + +chip "dps460-i2c-9-58" + label temp1 "Power supply 2 inlet temp sensor" + # maximum and critical thresholds are not supported for this psu + set temp1_max 60 + set temp1_crit 70 + + label temp2 "Power supply 2 internal sensor" + set temp2_max 60 + set temp2_crit 70 + + ignore temp3 + + set in1_max 250 + set in1_crit 255 + set power1_max 525 + set power2_max 460 + set power2_crit 462 + set curr1_max 5.28 + set curr1_crit 5.30 + set curr2_max 36 + set curr2_crit 37 diff --git a/device/arista/x86_64-arista_7050_qx32/system_health_monitoring_config.json b/device/arista/x86_64-arista_7050_qx32/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32/thermal_policy.json b/device/arista/x86_64-arista_7050_qx32/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/buffers.json.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/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/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/buffers_defaults_t1.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/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/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/hwsku-init b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/hwsku-init new file mode 100755 index 000000000000..415bca984228 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/hwsku-init @@ -0,0 +1,3 @@ +#!/bin/bash + +echo 0 > /sys/devices/pci0000:00/0000:00:02.2/0000:02:00.0/mux diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/pg_profile_lookup.ini b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/pg_profile_lookup.ini new file mode 100644 index 000000000000..d8190e4893de --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/pg_profile_lookup.ini @@ -0,0 +1,11 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 40000 5m 46384 18432 45136 -3 2496 + 50000 5m 46592 18432 45344 -3 2496 + 100000 5m 48464 18432 47216 -3 2496 + 40000 40m 48464 18432 47216 -3 2496 + 50000 40m 49296 18432 48048 -3 2496 + 100000 40m 53872 18432 52624 -3 2496 + 40000 300m 64064 18432 62816 -3 2496 + 50000 300m 68848 18432 67600 -3 2496 + 100000 300m 92976 18432 91728 -3 2496 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/port_config.ini b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/port_config.ini new file mode 100644 index 000000000000..857b126bf833 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 9,10,11,12 Ethernet5/1 5 40000 +Ethernet4 13,14,15,16 Ethernet6/1 6 40000 +Ethernet8 17,18,19,20 Ethernet7/1 7 40000 +Ethernet12 21,22,23,24 Ethernet8/1 8 40000 +Ethernet16 29,30,31,32 Ethernet9/1 9 40000 +Ethernet20 25,26,27,28 Ethernet10/1 10 40000 +Ethernet24 33,34,35,36 Ethernet11/1 11 40000 +Ethernet28 37,38,39,40 Ethernet12/1 12 40000 +Ethernet32 45,46,47,48 Ethernet13/1 13 40000 +Ethernet36 41,42,43,44 Ethernet14/1 14 40000 +Ethernet40 49,50,51,52 Ethernet15/1 15 40000 +Ethernet44 53,54,55,56 Ethernet16/1 16 40000 +Ethernet48 69,70,71,72 Ethernet17/1 17 40000 +Ethernet52 65,66,67,68 Ethernet18/1 18 40000 +Ethernet56 73,74,75,76 Ethernet19/1 19 40000 +Ethernet60 77,78,79,80 Ethernet20/1 20 40000 +Ethernet64 93,94,95,96 Ethernet21/1 21 40000 +Ethernet68 89,90,91,92 Ethernet22/1 22 40000 +Ethernet72 97,98,99,100 Ethernet23/1 23 40000 +Ethernet76 101,102,103,104 Ethernet24/1 24 40000 +Ethernet80 109,110,111,112 Ethernet25/1 25 40000 +Ethernet84 105,106,107,108 Ethernet26/1 26 40000 +Ethernet88 121,122,123,124 Ethernet27/1 27 40000 +Ethernet92 125,126,127,128 Ethernet28/1 28 40000 +Ethernet96 61,62,63,64 Ethernet29 29 40000 +Ethernet100 57,58,59,60 Ethernet30 30 40000 +Ethernet104 81,82,83,84 Ethernet31 31 40000 +Ethernet108 85,86,87,88 Ethernet32 32 40000 +Ethernet112 117,118,119,120 Ethernet33 33 40000 +Ethernet116 113,114,115,116 Ethernet34 34 40000 +Ethernet120 1,2,3,4 Ethernet35 35 40000 +Ethernet124 5,6,7,8 Ethernet36 36 40000 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/qos.json.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/sai.profile b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/sai.profile new file mode 100644 index 000000000000..cbaa8cdfd51a --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-a7050-qx32s-32x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/td2-a7050-qx32s-32x40G.config.bcm b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/td2-a7050-qx32s-32x40G.config.bcm new file mode 100644 index 000000000000..31521e4c43ae --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050-QX-32S/td2-a7050-qx32s-32x40G.config.bcm @@ -0,0 +1,744 @@ +#/****************************************************************************** +# * +# * File: config.bcm.clearlake (7050-QX32S) +# * Name: +# * +# * Description: This file contains SDK properties for an Arista +# * Clearlake platform. +# * +# *----------------------------------------------------------------------------- +# ******************************************************************************/ +#################################################################### +# BCM Config file for Clearlake platform +# - 32x40g Portmode + +# 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 + +# l2 thread related config vars +l2xmsg_hostbuf_size=8192 +l2xmsg_mode=1 + +bcm_num_cos=10 +bcm_stat_interval=2000000 +lls_num_l2uc=12 +max_vp_lags=0 +miim_intr_enable=0 +mmu_lossless=0 +module_64ports=0 + +stable_size=0x2000000 + +schan_intr_enable=0 +tdma_timeout_usec=5000000 +tslam_timeout_usec=15000000 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 + +############################### +serdes_fiber_pref=1 +############################### +mdio_output_delay=0x0d +############################### +xgxs_lcpll_xtal_refclk=1 +tdma_intr_enable=1 +tslam_intr_enable=1 +table_dma_enable=1 + +pbmp_oversubscribe.0=0x1fffffffffffffffffffffffffe +pbmp_xport_xe.0=0x1fffffffffffffffffffffffffe +phy_an_c37_1.0=3 +phy_an_c37_5.0=3 +phy_an_c37_9.0=3 +phy_an_c37_13.0=3 +phy_an_c37_17.0=3 +phy_an_c37_21.0=3 +phy_an_c37_25.0=3 +phy_an_c37_29.0=3 +phy_an_c37_33.0=3 +phy_an_c37_37.0=3 +phy_an_c37_41.0=3 +phy_an_c37_45.0=3 +phy_an_c37_49.0=3 +phy_an_c37_53.0=3 +phy_an_c37_57.0=3 +phy_an_c37_61.0=3 +phy_an_c37_65.0=3 +phy_an_c37_69.0=3 +phy_an_c37_73.0=3 +phy_an_c37_77.0=3 +phy_an_c37_81.0=3 +phy_an_c37_85.0=3 +phy_an_c37_89.0=3 +phy_an_c37_93.0=3 +phy_an_c37_97.0=0 +phy_an_c37_98.0=0 +phy_an_c37_99.0=0 +phy_an_c37_100.0=0 +phy_an_c37_101.0=0 +phy_an_c37_102.0=0 +phy_an_c37_103.0=0 +phy_an_c37_104.0=0 +phy_an_c73_1.0=0 +phy_an_c73_5.0=0 +phy_an_c73_9.0=0 +phy_an_c73_13.0=0 +phy_an_c73_17.0=0 +phy_an_c73_21.0=0 +phy_an_c73_25.0=0 +phy_an_c73_29.0=0 +phy_an_c73_33.0=0 +phy_an_c73_37.0=0 +phy_an_c73_41.0=0 +phy_an_c73_45.0=0 +phy_an_c73_49.0=0 +phy_an_c73_53.0=0 +phy_an_c73_57.0=0 +phy_an_c73_61.0=0 +phy_an_c73_65.0=0 +phy_an_c73_69.0=0 +phy_an_c73_73.0=0 +phy_an_c73_77.0=0 +phy_an_c73_81.0=0 +phy_an_c73_85.0=0 +phy_an_c73_89.0=0 +phy_an_c73_93.0=0 +phy_an_c73_97.0=2 +phy_an_c73_98.0=2 +phy_an_c73_99.0=2 +phy_an_c73_100.0=2 +phy_an_c73_101.0=2 +phy_an_c73_102.0=2 +phy_an_c73_103.0=2 +phy_an_c73_104.0=2 +phy_xaui_rx_polarity_flip_1.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x0 +phy_xaui_rx_polarity_flip_9.0=0x4 +phy_xaui_rx_polarity_flip_13.0=0x0 +phy_xaui_rx_polarity_flip_17.0=0xb +phy_xaui_rx_polarity_flip_21.0=0x3 +phy_xaui_rx_polarity_flip_25.0=0xb +phy_xaui_rx_polarity_flip_29.0=0xf +phy_xaui_rx_polarity_flip_33.0=0xb +phy_xaui_rx_polarity_flip_37.0=0x3 +phy_xaui_rx_polarity_flip_41.0=0xb +phy_xaui_rx_polarity_flip_45.0=0x0 +phy_xaui_rx_polarity_flip_49.0=0x4 +phy_xaui_rx_polarity_flip_53.0=0xc +phy_xaui_rx_polarity_flip_57.0=0x4 +phy_xaui_rx_polarity_flip_61.0=0x0 +phy_xaui_rx_polarity_flip_65.0=0xb +phy_xaui_rx_polarity_flip_69.0=0x3 +phy_xaui_rx_polarity_flip_73.0=0xb +phy_xaui_rx_polarity_flip_77.0=0xf +phy_xaui_rx_polarity_flip_81.0=0xb +phy_xaui_rx_polarity_flip_85.0=0x3 +phy_xaui_rx_polarity_flip_89.0=0x4 +phy_xaui_rx_polarity_flip_93.0=0x0 +phy_xaui_rx_polarity_flip_97.0=0xb +phy_xaui_rx_polarity_flip_98.0=0x3 +phy_xaui_rx_polarity_flip_99.0=0x4 +phy_xaui_rx_polarity_flip_100.0=0x0 +phy_xaui_rx_polarity_flip_101.0=0x0 +phy_xaui_rx_polarity_flip_102.0=0xe +phy_xaui_rx_polarity_flip_103.0=0x0 +phy_xaui_rx_polarity_flip_104.0=0x0 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_5.0=0x0 +phy_xaui_tx_polarity_flip_9.0=0x2 +phy_xaui_tx_polarity_flip_13.0=0x0 +phy_xaui_tx_polarity_flip_17.0=0xd +phy_xaui_tx_polarity_flip_21.0=0xc +phy_xaui_tx_polarity_flip_25.0=0xd +phy_xaui_tx_polarity_flip_29.0=0xf +phy_xaui_tx_polarity_flip_33.0=0xd +phy_xaui_tx_polarity_flip_37.0=0xc +phy_xaui_tx_polarity_flip_41.0=0xd +phy_xaui_tx_polarity_flip_45.0=0x0 +phy_xaui_tx_polarity_flip_49.0=0x2 +phy_xaui_tx_polarity_flip_53.0=0x3 +phy_xaui_tx_polarity_flip_57.0=0x2 +phy_xaui_tx_polarity_flip_61.0=0x0 +phy_xaui_tx_polarity_flip_65.0=0xd +phy_xaui_tx_polarity_flip_69.0=0xc +phy_xaui_tx_polarity_flip_73.0=0xd +phy_xaui_tx_polarity_flip_77.0=0xf +phy_xaui_tx_polarity_flip_81.0=0xd +phy_xaui_tx_polarity_flip_85.0=0xc +phy_xaui_tx_polarity_flip_89.0=0x2 +phy_xaui_tx_polarity_flip_93.0=0x0 +phy_xaui_tx_polarity_flip_97.0=0xd +phy_xaui_tx_polarity_flip_98.0=0xc +phy_xaui_tx_polarity_flip_99.0=0x2 +phy_xaui_tx_polarity_flip_100.0=0x0 +phy_xaui_tx_polarity_flip_101.0=0x0 +phy_xaui_tx_polarity_flip_102.0=0x7 +phy_xaui_tx_polarity_flip_103.0=0x2 +phy_xaui_tx_polarity_flip_104.0=0x0 +port_init_autoneg_1.0=0 +port_init_autoneg_5.0=0 +port_init_autoneg_9.0=0 +port_init_autoneg_13.0=0 +port_init_autoneg_17.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_25.0=0 +port_init_autoneg_29.0=0 +port_init_autoneg_33.0=0 +port_init_autoneg_37.0=0 +port_init_autoneg_41.0=0 +port_init_autoneg_45.0=0 +port_init_autoneg_49.0=0 +port_init_autoneg_53.0=0 +port_init_autoneg_57.0=0 +port_init_autoneg_61.0=0 +port_init_autoneg_65.0=0 +port_init_autoneg_69.0=0 +port_init_autoneg_73.0=0 +port_init_autoneg_77.0=0 +port_init_autoneg_81.0=0 +port_init_autoneg_85.0=0 +port_init_autoneg_89.0=0 +port_init_autoneg_93.0=0 +port_init_autoneg_97.0=0 +port_init_autoneg_98.0=0 +port_init_autoneg_99.0=0 +port_init_autoneg_100.0=0 +port_init_autoneg_101.0=0 +port_init_autoneg_102.0=0 +port_init_autoneg_103.0=0 +port_init_autoneg_104.0=0 +port_init_cl72_hg.0=0x11 +port_phy_addr_1.0=0x7f +port_phy_addr_5.0=0x7f +port_phy_addr_9.0=0x7f +port_phy_addr_13.0=0x7f +port_phy_addr_17.0=0x7f +port_phy_addr_21.0=0x7f +port_phy_addr_25.0=0x7f +port_phy_addr_29.0=0x7f +port_phy_addr_33.0=0x7f +port_phy_addr_37.0=0x7f +port_phy_addr_41.0=0x7f +port_phy_addr_45.0=0x7f +port_phy_addr_49.0=0x7f +port_phy_addr_53.0=0x7f +port_phy_addr_57.0=0x7f +port_phy_addr_61.0=0x7f +port_phy_addr_65.0=0x7f +port_phy_addr_69.0=0x7f +port_phy_addr_73.0=0x7f +port_phy_addr_77.0=0x7f +port_phy_addr_81.0=0x7f +port_phy_addr_85.0=0x7f +port_phy_addr_89.0=0x7f +port_phy_addr_93.0=0x7f +port_phy_addr_97.0=0x7f +port_phy_addr_98.0=0x7f +port_phy_addr_99.0=0x7f +port_phy_addr_100.0=0x7f +port_phy_addr_101.0=0x7f +port_phy_addr_102.0=0x7f +port_phy_addr_103.0=0x7f +port_phy_addr_104.0=0x7f +portmap_1.0=9:40 +portmap_5.0=13:40 +portmap_9.0=17:40 +portmap_13.0=21:40 +portmap_17.0=29:40 +portmap_21.0=25:40 +portmap_25.0=33:40 +portmap_29.0=37:40 +portmap_33.0=45:40 +portmap_37.0=41:40 +portmap_41.0=49:40 +portmap_45.0=53:40 +portmap_49.0=69:40 +portmap_53.0=65:40 +portmap_57.0=73:40 +portmap_61.0=77:40 +portmap_65.0=93:40 +portmap_69.0=89:40 +portmap_73.0=97:40 +portmap_77.0=101:40 +portmap_81.0=109:40 +portmap_85.0=105:40 +portmap_89.0=121:40 +portmap_93.0=125:40 +portmap_97.0=61:40 +portmap_98.0=57:40 +portmap_99.0=81:40 +portmap_100.0=85:40 +portmap_101.0=117:40 +portmap_102.0=113:40 +portmap_103.0=1:40 +portmap_104.0=5:40 +serdes_firmware_mode_1.0=2 +serdes_firmware_mode_5.0=2 +serdes_firmware_mode_9.0=2 +serdes_firmware_mode_13.0=2 +serdes_firmware_mode_17.0=2 +serdes_firmware_mode_21.0=2 +serdes_firmware_mode_25.0=2 +serdes_firmware_mode_29.0=2 +serdes_firmware_mode_33.0=2 +serdes_firmware_mode_37.0=2 +serdes_firmware_mode_41.0=2 +serdes_firmware_mode_45.0=2 +serdes_firmware_mode_49.0=2 +serdes_firmware_mode_53.0=2 +serdes_firmware_mode_57.0=2 +serdes_firmware_mode_61.0=2 +serdes_firmware_mode_65.0=2 +serdes_firmware_mode_69.0=2 +serdes_firmware_mode_73.0=2 +serdes_firmware_mode_77.0=2 +serdes_firmware_mode_81.0=2 +serdes_firmware_mode_85.0=2 +serdes_firmware_mode_89.0=2 +serdes_firmware_mode_93.0=2 +serdes_firmware_mode_97.0=2 +serdes_firmware_mode_98.0=2 +serdes_firmware_mode_99.0=2 +serdes_firmware_mode_100.0=2 +serdes_firmware_mode_101.0=2 +serdes_firmware_mode_102.0=2 +serdes_firmware_mode_103.0=2 +serdes_firmware_mode_104.0=2 +xgxs_rx_lane_map_1.0=0x3210 +xgxs_rx_lane_map_5.0=0x0321 +xgxs_rx_lane_map_9.0=0x1302 +xgxs_rx_lane_map_13.0=0x0213 +xgxs_rx_lane_map_17.0=0x1302 +xgxs_rx_lane_map_21.0=0x1302 +xgxs_rx_lane_map_25.0=0x1302 +xgxs_rx_lane_map_29.0=0x0213 +xgxs_rx_lane_map_33.0=0x1302 +xgxs_rx_lane_map_37.0=0x1302 +xgxs_rx_lane_map_41.0=0x1302 +xgxs_rx_lane_map_45.0=0x0213 +xgxs_rx_lane_map_49.0=0x1302 +xgxs_rx_lane_map_53.0=0x1302 +xgxs_rx_lane_map_57.0=0x1302 +xgxs_rx_lane_map_61.0=0x0213 +xgxs_rx_lane_map_65.0=0x1302 +xgxs_rx_lane_map_69.0=0x1302 +xgxs_rx_lane_map_73.0=0x1302 +xgxs_rx_lane_map_77.0=0x0213 +xgxs_rx_lane_map_81.0=0x1302 +xgxs_rx_lane_map_85.0=0x1302 +xgxs_rx_lane_map_89.0=0x1302 +xgxs_rx_lane_map_93.0=0x0213 +xgxs_rx_lane_map_97.0=0x1302 +xgxs_rx_lane_map_98.0=0x1302 +xgxs_rx_lane_map_99.0=0x1302 +xgxs_rx_lane_map_100.0=0x0213 +xgxs_rx_lane_map_101.0=0x0213 +xgxs_rx_lane_map_102.0=0x1302 +xgxs_rx_lane_map_103.0=0x0123 +xgxs_rx_lane_map_104.0=0x2031 +xgxs_tx_lane_map_1.0=0x0123 +xgxs_tx_lane_map_5.0=0x0321 +xgxs_tx_lane_map_9.0=0x2031 +xgxs_tx_lane_map_13.0=0x0213 +xgxs_tx_lane_map_17.0=0x2031 +xgxs_tx_lane_map_21.0=0x2031 +xgxs_tx_lane_map_25.0=0x2031 +xgxs_tx_lane_map_29.0=0x0213 +xgxs_tx_lane_map_33.0=0x2031 +xgxs_tx_lane_map_37.0=0x2031 +xgxs_tx_lane_map_41.0=0x2031 +xgxs_tx_lane_map_45.0=0x0213 +xgxs_tx_lane_map_49.0=0x2031 +xgxs_tx_lane_map_53.0=0x2031 +xgxs_tx_lane_map_57.0=0x2031 +xgxs_tx_lane_map_61.0=0x0213 +xgxs_tx_lane_map_65.0=0x2031 +xgxs_tx_lane_map_69.0=0x2031 +xgxs_tx_lane_map_73.0=0x2031 +xgxs_tx_lane_map_77.0=0x0213 +xgxs_tx_lane_map_81.0=0x2031 +xgxs_tx_lane_map_85.0=0x2031 +xgxs_tx_lane_map_89.0=0x2031 +xgxs_tx_lane_map_93.0=0x0213 +xgxs_tx_lane_map_97.0=0x2031 +xgxs_tx_lane_map_98.0=0x2031 +xgxs_tx_lane_map_99.0=0x2031 +xgxs_tx_lane_map_100.0=0x0213 +xgxs_tx_lane_map_101.0=0x0213 +xgxs_tx_lane_map_102.0=0x2031 +xgxs_tx_lane_map_103.0=0x3120 +xgxs_tx_lane_map_104.0=0x1302 + +# tuning parameters +serdes_preemphasis_lane0_1.0=0x81f7 +serdes_preemphasis_lane1_1.0=0x81f7 +serdes_preemphasis_lane2_1.0=0x81f7 +serdes_preemphasis_lane3_1.0=0x81f7 +serdes_pre_driver_current_lane0_5.0=0x7 +serdes_driver_current_lane0_5.0=0x7 +serdes_preemphasis_lane0_5.0=0xc2f0 +serdes_pre_driver_current_lane1_5.0=0x7 +serdes_driver_current_lane1_5.0=0x7 +serdes_preemphasis_lane1_5.0=0xc2f0 +serdes_pre_driver_current_lane2_5.0=0x7 +serdes_driver_current_lane2_5.0=0x7 +serdes_preemphasis_lane2_5.0=0xc2f0 +serdes_pre_driver_current_lane3_5.0=0x7 +serdes_driver_current_lane3_5.0=0x7 +serdes_preemphasis_lane3_5.0=0xc2f0 +serdes_pre_driver_current_lane0_9.0=0x7 +serdes_driver_current_lane0_9.0=0x7 +serdes_preemphasis_lane0_9.0=0xbb10 +serdes_pre_driver_current_lane1_9.0=0x7 +serdes_driver_current_lane1_9.0=0x7 +serdes_preemphasis_lane1_9.0=0xbb10 +serdes_pre_driver_current_lane2_9.0=0x7 +serdes_driver_current_lane2_9.0=0x7 +serdes_preemphasis_lane2_9.0=0xbb10 +serdes_pre_driver_current_lane3_9.0=0x7 +serdes_driver_current_lane3_9.0=0x7 +serdes_preemphasis_lane3_9.0=0xbb10 +serdes_pre_driver_current_lane0_13.0=0x7 +serdes_driver_current_lane0_13.0=0x7 +serdes_preemphasis_lane0_13.0=0xbb10 +serdes_pre_driver_current_lane1_13.0=0x7 +serdes_driver_current_lane1_13.0=0x7 +serdes_preemphasis_lane1_13.0=0xbb10 +serdes_pre_driver_current_lane2_13.0=0x7 +serdes_driver_current_lane2_13.0=0x7 +serdes_preemphasis_lane2_13.0=0xbb10 +serdes_pre_driver_current_lane3_13.0=0x7 +serdes_driver_current_lane3_13.0=0x7 +serdes_preemphasis_lane3_13.0=0xbb10 +serdes_pre_driver_current_lane0_17.0=0x6 +serdes_driver_current_lane0_17.0=0x6 +serdes_preemphasis_lane0_17.0=0xb720 +serdes_pre_driver_current_lane1_17.0=0x6 +serdes_driver_current_lane1_17.0=0x6 +serdes_preemphasis_lane1_17.0=0xb720 +serdes_pre_driver_current_lane2_17.0=0x6 +serdes_driver_current_lane2_17.0=0x6 +serdes_preemphasis_lane2_17.0=0xb720 +serdes_pre_driver_current_lane3_17.0=0x6 +serdes_driver_current_lane3_17.0=0x6 +serdes_preemphasis_lane3_17.0=0xb720 +serdes_pre_driver_current_lane0_21.0=0x7 +serdes_driver_current_lane0_21.0=0x7 +serdes_preemphasis_lane0_21.0=0xbb10 +serdes_pre_driver_current_lane1_21.0=0x7 +serdes_driver_current_lane1_21.0=0x7 +serdes_preemphasis_lane1_21.0=0xbb10 +serdes_pre_driver_current_lane2_21.0=0x7 +serdes_driver_current_lane2_21.0=0x7 +serdes_preemphasis_lane2_21.0=0xbb10 +serdes_pre_driver_current_lane3_21.0=0x7 +serdes_driver_current_lane3_21.0=0x7 +serdes_preemphasis_lane3_21.0=0xbb10 +serdes_pre_driver_current_lane0_25.0=0x5 +serdes_driver_current_lane0_25.0=0x5 +serdes_preemphasis_lane0_25.0=0xb720 +serdes_pre_driver_current_lane1_25.0=0x5 +serdes_driver_current_lane1_25.0=0x5 +serdes_preemphasis_lane1_25.0=0xb720 +serdes_pre_driver_current_lane2_25.0=0x5 +serdes_driver_current_lane2_25.0=0x5 +serdes_preemphasis_lane2_25.0=0xb720 +serdes_pre_driver_current_lane3_25.0=0x5 +serdes_driver_current_lane3_25.0=0x5 +serdes_preemphasis_lane3_25.0=0xb720 +serdes_pre_driver_current_lane0_29.0=0x5 +serdes_driver_current_lane0_29.0=0x5 +serdes_preemphasis_lane0_29.0=0xb720 +serdes_pre_driver_current_lane1_29.0=0x5 +serdes_driver_current_lane1_29.0=0x5 +serdes_preemphasis_lane1_29.0=0xb720 +serdes_pre_driver_current_lane2_29.0=0x5 +serdes_driver_current_lane2_29.0=0x5 +serdes_preemphasis_lane2_29.0=0xb720 +serdes_pre_driver_current_lane3_29.0=0x5 +serdes_driver_current_lane3_29.0=0x5 +serdes_preemphasis_lane3_29.0=0xb720 +serdes_pre_driver_current_lane0_33.0=0x4 +serdes_driver_current_lane0_33.0=0x4 +serdes_preemphasis_lane0_33.0=0xb720 +serdes_pre_driver_current_lane1_33.0=0x4 +serdes_driver_current_lane1_33.0=0x4 +serdes_preemphasis_lane1_33.0=0xb720 +serdes_pre_driver_current_lane2_33.0=0x4 +serdes_driver_current_lane2_33.0=0x4 +serdes_preemphasis_lane2_33.0=0xb720 +serdes_pre_driver_current_lane3_33.0=0x4 +serdes_driver_current_lane3_33.0=0x4 +serdes_preemphasis_lane3_33.0=0xb720 +serdes_pre_driver_current_lane0_37.0=0x5 +serdes_driver_current_lane0_37.0=0x5 +serdes_preemphasis_lane0_37.0=0xb720 +serdes_pre_driver_current_lane1_37.0=0x5 +serdes_driver_current_lane1_37.0=0x5 +serdes_preemphasis_lane1_37.0=0xb720 +serdes_pre_driver_current_lane2_37.0=0x5 +serdes_driver_current_lane2_37.0=0x5 +serdes_preemphasis_lane2_37.0=0xb720 +serdes_pre_driver_current_lane3_37.0=0x5 +serdes_driver_current_lane3_37.0=0x5 +serdes_preemphasis_lane3_37.0=0xb720 +serdes_pre_driver_current_lane0_41.0=0x3 +serdes_driver_current_lane0_41.0=0x3 +serdes_preemphasis_lane0_41.0=0xb330 +serdes_pre_driver_current_lane1_41.0=0x3 +serdes_driver_current_lane1_41.0=0x3 +serdes_preemphasis_lane1_41.0=0xb330 +serdes_pre_driver_current_lane2_41.0=0x3 +serdes_driver_current_lane2_41.0=0x3 +serdes_preemphasis_lane2_41.0=0xb330 +serdes_pre_driver_current_lane3_41.0=0x3 +serdes_driver_current_lane3_41.0=0x3 +serdes_preemphasis_lane3_41.0=0xb330 +serdes_pre_driver_current_lane0_45.0=0x4 +serdes_driver_current_lane0_45.0=0x4 +serdes_preemphasis_lane0_45.0=0xb720 +serdes_pre_driver_current_lane1_45.0=0x4 +serdes_driver_current_lane1_45.0=0x4 +serdes_preemphasis_lane1_45.0=0xb720 +serdes_pre_driver_current_lane2_45.0=0x4 +serdes_driver_current_lane2_45.0=0x4 +serdes_preemphasis_lane2_45.0=0xb720 +serdes_pre_driver_current_lane3_45.0=0x4 +serdes_driver_current_lane3_45.0=0x4 +serdes_preemphasis_lane3_45.0=0xb720 +serdes_pre_driver_current_lane0_49.0=0x3 +serdes_driver_current_lane0_49.0=0x3 +serdes_preemphasis_lane0_49.0=0xb330 +serdes_pre_driver_current_lane1_49.0=0x3 +serdes_driver_current_lane1_49.0=0x3 +serdes_preemphasis_lane1_49.0=0xb330 +serdes_pre_driver_current_lane2_49.0=0x3 +serdes_driver_current_lane2_49.0=0x3 +serdes_preemphasis_lane2_49.0=0xb330 +serdes_pre_driver_current_lane3_49.0=0x3 +serdes_driver_current_lane3_49.0=0x3 +serdes_preemphasis_lane3_49.0=0xb330 +serdes_pre_driver_current_lane0_53.0=0x4 +serdes_driver_current_lane0_53.0=0x4 +serdes_preemphasis_lane0_53.0=0xb720 +serdes_pre_driver_current_lane1_53.0=0x4 +serdes_driver_current_lane1_53.0=0x4 +serdes_preemphasis_lane1_53.0=0xb720 +serdes_pre_driver_current_lane2_53.0=0x4 +serdes_driver_current_lane2_53.0=0x4 +serdes_preemphasis_lane2_53.0=0xb720 +serdes_pre_driver_current_lane3_53.0=0x4 +serdes_driver_current_lane3_53.0=0x4 +serdes_preemphasis_lane3_53.0=0xb720 +serdes_pre_driver_current_lane0_57.0=0x3 +serdes_driver_current_lane0_57.0=0x3 +serdes_preemphasis_lane0_57.0=0xb330 +serdes_pre_driver_current_lane1_57.0=0x3 +serdes_driver_current_lane1_57.0=0x3 +serdes_preemphasis_lane1_57.0=0xb330 +serdes_pre_driver_current_lane2_57.0=0x3 +serdes_driver_current_lane2_57.0=0x3 +serdes_preemphasis_lane2_57.0=0xb330 +serdes_pre_driver_current_lane3_57.0=0x3 +serdes_driver_current_lane3_57.0=0x3 +serdes_preemphasis_lane3_57.0=0xb330 +serdes_pre_driver_current_lane0_61.0=0x4 +serdes_driver_current_lane0_61.0=0x4 +serdes_preemphasis_lane0_61.0=0xb720 +serdes_pre_driver_current_lane1_61.0=0x4 +serdes_driver_current_lane1_61.0=0x4 +serdes_preemphasis_lane1_61.0=0xb720 +serdes_pre_driver_current_lane2_61.0=0x4 +serdes_driver_current_lane2_61.0=0x4 +serdes_preemphasis_lane2_61.0=0xb720 +serdes_pre_driver_current_lane3_61.0=0x4 +serdes_driver_current_lane3_61.0=0x4 +serdes_preemphasis_lane3_61.0=0xb720 +serdes_pre_driver_current_lane0_65.0=0x4 +serdes_driver_current_lane0_65.0=0x4 +serdes_preemphasis_lane0_65.0=0xb720 +serdes_pre_driver_current_lane1_65.0=0x4 +serdes_driver_current_lane1_65.0=0x4 +serdes_preemphasis_lane1_65.0=0xb720 +serdes_pre_driver_current_lane2_65.0=0x4 +serdes_driver_current_lane2_65.0=0x4 +serdes_preemphasis_lane2_65.0=0xb720 +serdes_pre_driver_current_lane3_65.0=0x4 +serdes_driver_current_lane3_65.0=0x4 +serdes_preemphasis_lane3_65.0=0xb720 +serdes_pre_driver_current_lane0_69.0=0x4 +serdes_driver_current_lane0_69.0=0x4 +serdes_preemphasis_lane0_69.0=0xb720 +serdes_pre_driver_current_lane1_69.0=0x4 +serdes_driver_current_lane1_69.0=0x4 +serdes_preemphasis_lane1_69.0=0xb720 +serdes_pre_driver_current_lane2_69.0=0x4 +serdes_driver_current_lane2_69.0=0x4 +serdes_preemphasis_lane2_69.0=0xb720 +serdes_pre_driver_current_lane3_69.0=0x4 +serdes_driver_current_lane3_69.0=0x4 +serdes_preemphasis_lane3_69.0=0xb720 +serdes_pre_driver_current_lane0_73.0=0x4 +serdes_driver_current_lane0_73.0=0x4 +serdes_preemphasis_lane0_73.0=0xb720 +serdes_pre_driver_current_lane1_73.0=0x4 +serdes_driver_current_lane1_73.0=0x4 +serdes_preemphasis_lane1_73.0=0xb720 +serdes_pre_driver_current_lane2_73.0=0x4 +serdes_driver_current_lane2_73.0=0x4 +serdes_preemphasis_lane2_73.0=0xb720 +serdes_pre_driver_current_lane3_73.0=0x4 +serdes_driver_current_lane3_73.0=0x4 +serdes_preemphasis_lane3_73.0=0xb720 +serdes_pre_driver_current_lane0_77.0=0x5 +serdes_driver_current_lane0_77.0=0x5 +serdes_preemphasis_lane0_77.0=0xb720 +serdes_pre_driver_current_lane1_77.0=0x5 +serdes_driver_current_lane1_77.0=0x5 +serdes_preemphasis_lane1_77.0=0xb720 +serdes_pre_driver_current_lane2_77.0=0x5 +serdes_driver_current_lane2_77.0=0x5 +serdes_preemphasis_lane2_77.0=0xb720 +serdes_pre_driver_current_lane3_77.0=0x5 +serdes_driver_current_lane3_77.0=0x5 +serdes_preemphasis_lane3_77.0=0xb720 +serdes_pre_driver_current_lane0_81.0=0x5 +serdes_driver_current_lane0_81.0=0x5 +serdes_preemphasis_lane0_81.0=0xb720 +serdes_pre_driver_current_lane1_81.0=0x5 +serdes_driver_current_lane1_81.0=0x5 +serdes_preemphasis_lane1_81.0=0xb720 +serdes_pre_driver_current_lane2_81.0=0x5 +serdes_driver_current_lane2_81.0=0x5 +serdes_preemphasis_lane2_81.0=0xb720 +serdes_pre_driver_current_lane3_81.0=0x5 +serdes_driver_current_lane3_81.0=0x5 +serdes_preemphasis_lane3_81.0=0xb720 +serdes_pre_driver_current_lane0_85.0=0x5 +serdes_driver_current_lane0_85.0=0x5 +serdes_preemphasis_lane0_85.0=0xb720 +serdes_pre_driver_current_lane1_85.0=0x5 +serdes_driver_current_lane1_85.0=0x5 +serdes_preemphasis_lane1_85.0=0xb720 +serdes_pre_driver_current_lane2_85.0=0x5 +serdes_driver_current_lane2_85.0=0x5 +serdes_preemphasis_lane2_85.0=0xb720 +serdes_pre_driver_current_lane3_85.0=0x5 +serdes_driver_current_lane3_85.0=0x5 +serdes_preemphasis_lane3_85.0=0xb720 +serdes_pre_driver_current_lane0_89.0=0x6 +serdes_driver_current_lane0_89.0=0x6 +serdes_preemphasis_lane0_89.0=0xb720 +serdes_pre_driver_current_lane1_89.0=0x6 +serdes_driver_current_lane1_89.0=0x6 +serdes_preemphasis_lane1_89.0=0xb720 +serdes_pre_driver_current_lane2_89.0=0x6 +serdes_driver_current_lane2_89.0=0x6 +serdes_preemphasis_lane2_89.0=0xb720 +serdes_pre_driver_current_lane3_89.0=0x6 +serdes_driver_current_lane3_89.0=0x6 +serdes_preemphasis_lane3_89.0=0xb720 +serdes_pre_driver_current_lane0_93.0=0x7 +serdes_driver_current_lane0_93.0=0x7 +serdes_preemphasis_lane0_93.0=0xbb10 +serdes_pre_driver_current_lane1_93.0=0x7 +serdes_driver_current_lane1_93.0=0x7 +serdes_preemphasis_lane1_93.0=0xbb10 +serdes_pre_driver_current_lane2_93.0=0x7 +serdes_driver_current_lane2_93.0=0x7 +serdes_preemphasis_lane2_93.0=0xbb10 +serdes_pre_driver_current_lane3_93.0=0x7 +serdes_driver_current_lane3_93.0=0x7 +serdes_preemphasis_lane3_93.0=0xbb10 +serdes_pre_driver_current_lane0_97.0=0x5 +serdes_driver_current_lane0_97.0=0x5 +serdes_preemphasis_lane0_97.0=0xb720 +serdes_pre_driver_current_lane1_97.0=0x5 +serdes_driver_current_lane1_97.0=0x5 +serdes_preemphasis_lane1_97.0=0xb720 +serdes_pre_driver_current_lane2_97.0=0x5 +serdes_driver_current_lane2_97.0=0x5 +serdes_preemphasis_lane2_97.0=0xb720 +serdes_pre_driver_current_lane3_97.0=0x5 +serdes_driver_current_lane3_97.0=0x5 +serdes_preemphasis_lane3_97.0=0xb720 +serdes_pre_driver_current_lane0_98.0=0x6 +serdes_driver_current_lane0_98.0=0x6 +serdes_preemphasis_lane0_98.0=0xb720 +serdes_pre_driver_current_lane1_98.0=0x6 +serdes_driver_current_lane1_98.0=0x6 +serdes_preemphasis_lane1_98.0=0xb720 +serdes_pre_driver_current_lane2_98.0=0x6 +serdes_driver_current_lane2_98.0=0x6 +serdes_preemphasis_lane2_98.0=0xb720 +serdes_pre_driver_current_lane3_98.0=0x6 +serdes_driver_current_lane3_98.0=0x6 +serdes_preemphasis_lane3_98.0=0xb720 +serdes_pre_driver_current_lane0_99.0=0x5 +serdes_driver_current_lane0_99.0=0x5 +serdes_preemphasis_lane0_99.0=0xb720 +serdes_pre_driver_current_lane1_99.0=0x5 +serdes_driver_current_lane1_99.0=0x5 +serdes_preemphasis_lane1_99.0=0xb720 +serdes_pre_driver_current_lane2_99.0=0x5 +serdes_driver_current_lane2_99.0=0x5 +serdes_preemphasis_lane2_99.0=0xb720 +serdes_pre_driver_current_lane3_99.0=0x5 +serdes_driver_current_lane3_99.0=0x5 +serdes_preemphasis_lane3_99.0=0xb720 +serdes_pre_driver_current_lane0_100.0=0x7 +serdes_driver_current_lane0_100.0=0x7 +serdes_preemphasis_lane0_100.0=0xbb10 +serdes_pre_driver_current_lane1_100.0=0x7 +serdes_driver_current_lane1_100.0=0x7 +serdes_preemphasis_lane1_100.0=0xbb10 +serdes_pre_driver_current_lane2_100.0=0x7 +serdes_driver_current_lane2_100.0=0x7 +serdes_preemphasis_lane2_100.0=0xbb10 +serdes_pre_driver_current_lane3_100.0=0x7 +serdes_driver_current_lane3_100.0=0x7 +serdes_preemphasis_lane3_100.0=0xbb10 +serdes_pre_driver_current_lane0_101.0=0x7 +serdes_driver_current_lane0_101.0=0x7 +serdes_preemphasis_lane0_101.0=0xbb10 +serdes_pre_driver_current_lane1_101.0=0x7 +serdes_driver_current_lane1_101.0=0x7 +serdes_preemphasis_lane1_101.0=0xbb10 +serdes_pre_driver_current_lane2_101.0=0x7 +serdes_driver_current_lane2_101.0=0x7 +serdes_preemphasis_lane2_101.0=0xbb10 +serdes_pre_driver_current_lane3_101.0=0x7 +serdes_driver_current_lane3_101.0=0x7 +serdes_preemphasis_lane3_101.0=0xbb10 +serdes_pre_driver_current_lane0_102.0=0x7 +serdes_driver_current_lane0_102.0=0x7 +serdes_preemphasis_lane0_102.0=0xbb10 +serdes_pre_driver_current_lane1_102.0=0x7 +serdes_driver_current_lane1_102.0=0x7 +serdes_preemphasis_lane1_102.0=0xbb10 +serdes_pre_driver_current_lane2_102.0=0x7 +serdes_driver_current_lane2_102.0=0x7 +serdes_preemphasis_lane2_102.0=0xbb10 +serdes_pre_driver_current_lane3_102.0=0x7 +serdes_driver_current_lane3_102.0=0x7 +serdes_preemphasis_lane3_102.0=0xbb10 +serdes_preemphasis_lane0_103.0=0x81f4 +serdes_preemphasis_lane1_103.0=0x81f4 +serdes_preemphasis_lane2_103.0=0x81f4 +serdes_preemphasis_lane3_103.0=0x81f4 +serdes_preemphasis_lane0_104.0=0x81f5 +serdes_preemphasis_lane1_104.0=0x81f5 +serdes_preemphasis_lane2_104.0=0x81f5 +serdes_preemphasis_lane3_104.0=0x81f5 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers.json.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers_defaults_t1.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..f72e3eb06fb5 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/buffers_defaults_t1.j2 @@ -0,0 +1,49 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% if PORT_ALL.append("Ethernet0") %}{% endif %} + {% if PORT_ALL.append("Ethernet1") %}{% endif %} + {% if PORT_ALL.append("Ethernet2") %}{% endif %} + {% if PORT_ALL.append("Ethernet3") %}{% endif %} + {% for port_idx in range(1,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": "8072396", + "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/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/hwsku-init b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/hwsku-init new file mode 100755 index 000000000000..ffc913582aa7 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/hwsku-init @@ -0,0 +1,3 @@ +#!/bin/bash + +echo 1 > /sys/devices/pci0000:00/0000:00:02.2/0000:02:00.0/mux diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/pg_profile_lookup.ini b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/pg_profile_lookup.ini new file mode 100644 index 000000000000..f961fd33b138 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/pg_profile_lookup.ini @@ -0,0 +1,14 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 41808 18432 40560 -4 2496 + 40000 5m 41808 18432 40560 -4 2496 + 50000 5m 41808 18432 40560 -4 2496 + 100000 5m 41808 18432 40560 -4 2496 + 10000 40m 41808 18432 40560 -4 2496 + 40000 40m 41808 18432 40560 -4 2496 + 50000 40m 41808 18432 40560 -4 2496 + 100000 40m 41808 18432 40560 -4 2496 + 10000 300m 41808 18432 40560 -4 2496 + 40000 300m 41808 18432 40560 -4 2496 + 50000 300m 41808 18432 40560 -4 2496 + 100000 300m 41808 18432 40560 -4 2496 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/port_config.ini b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/port_config.ini new file mode 100644 index 000000000000..dafdb570e9cc --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/port_config.ini @@ -0,0 +1,36 @@ +# name lanes alias index +Ethernet0 9 Ethernet1 1 +Ethernet1 10 Ethernet2 2 +Ethernet2 11 Ethernet3 3 +Ethernet3 12 Ethernet4 4 +Ethernet4 13,14,15,16 Ethernet6/1 6 +Ethernet8 17,18,19,20 Ethernet7/1 7 +Ethernet12 21,22,23,24 Ethernet8/1 8 +Ethernet16 29,30,31,32 Ethernet9/1 9 +Ethernet20 25,26,27,28 Ethernet10/1 10 +Ethernet24 33,34,35,36 Ethernet11/1 11 +Ethernet28 37,38,39,40 Ethernet12/1 12 +Ethernet32 45,46,47,48 Ethernet13/1 13 +Ethernet36 41,42,43,44 Ethernet14/1 14 +Ethernet40 49,50,51,52 Ethernet15/1 15 +Ethernet44 53,54,55,56 Ethernet16/1 16 +Ethernet48 69,70,71,72 Ethernet17/1 17 +Ethernet52 65,66,67,68 Ethernet18/1 18 +Ethernet56 73,74,75,76 Ethernet19/1 19 +Ethernet60 77,78,79,80 Ethernet20/1 20 +Ethernet64 93,94,95,96 Ethernet21/1 21 +Ethernet68 89,90,91,92 Ethernet22/1 22 +Ethernet72 97,98,99,100 Ethernet23/1 23 +Ethernet76 101,102,103,104 Ethernet24/1 24 +Ethernet80 109,110,111,112 Ethernet25/1 25 +Ethernet84 105,106,107,108 Ethernet26/1 26 +Ethernet88 121,122,123,124 Ethernet27/1 27 +Ethernet92 125,126,127,128 Ethernet28/1 28 +Ethernet96 61,62,63,64 Ethernet29 29 +Ethernet100 57,58,59,60 Ethernet30 30 +Ethernet104 81,82,83,84 Ethernet31 31 +Ethernet108 85,86,87,88 Ethernet32 32 +Ethernet112 117,118,119,120 Ethernet33 33 +Ethernet116 113,114,115,116 Ethernet34 34 +Ethernet120 1,2,3,4 Ethernet35 35 +Ethernet124 5,6,7,8 Ethernet36 36 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/qos.json.j2 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/qos.json.j2 new file mode 100644 index 000000000000..1accac3ddd0d --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/qos.json.j2 @@ -0,0 +1,148 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"312000", + "red_min_threshold":"104000", + "yellow_max_threshold":"312000", + "yellow_min_threshold":"104000", + "green_max_threshold":"312000", + "green_min_threshold":"104000" + } + }, + "QUEUE": { + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4" : { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3" : { + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|4" : { + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0" : { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|1" : { + "scheduler" : "[SCHEDULER|scheduler.2]" + } + } +} diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/sai.profile b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/sai.profile new file mode 100644 index 000000000000..0be2fc5e0f45 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-a7050-q31s4-31x40G-4x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/td2-a7050-q31s4-31x40G-4x10G.config.bcm b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/td2-a7050-q31s4-31x40G-4x10G.config.bcm new file mode 100644 index 000000000000..4819c7929ecd --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX-32S-S4Q31/td2-a7050-q31s4-31x40G-4x10G.config.bcm @@ -0,0 +1,675 @@ +arl_clean_timeout_usec=15000000 +bcm_num_cos.0=8 +bcm_stat_flags=1 +bcm_stat_jumbo.0=9236 +cdma_timeout_usec.0=15000000 +dma_desc_timeout_usec.0=15000000 +higig2_hdr_mode.0=1 +ipv6_lpm_128b_enable.0=2 +l2xmsg_mode.0=1 +max_vp_lags.0=0 +mdio_output_delay=0x0d +miim_intr_enable.0=0 +module_64ports.0=0 +os=unix +pbmp_oversubscribe.0=0x1fffffffffffffffffffffffffe +pbmp_xport_xe.0=0x1fffffffffffffffffffffffffe +phy_an_c37_1.0=3 +phy_an_c37_5.0=3 +phy_an_c37_9.0=3 +phy_an_c37_13.0=3 +phy_an_c37_17.0=3 +phy_an_c37_21.0=3 +phy_an_c37_25.0=3 +phy_an_c37_29.0=3 +phy_an_c37_33.0=3 +phy_an_c37_37.0=3 +phy_an_c37_41.0=3 +phy_an_c37_45.0=3 +phy_an_c37_49.0=3 +phy_an_c37_53.0=3 +phy_an_c37_57.0=3 +phy_an_c37_61.0=3 +phy_an_c37_65.0=3 +phy_an_c37_69.0=3 +phy_an_c37_73.0=3 +phy_an_c37_77.0=3 +phy_an_c37_81.0=3 +phy_an_c37_85.0=3 +phy_an_c37_89.0=3 +phy_an_c37_93.0=3 +phy_an_c37_97.0=0 +phy_an_c37_98.0=0 +phy_an_c37_99.0=0 +phy_an_c37_100.0=0 +phy_an_c37_101.0=0 +phy_an_c37_102.0=0 +phy_an_c37_103.0=0 +phy_an_c37_104.0=0 +phy_an_c73_1.0=0 +phy_an_c73_5.0=0 +phy_an_c73_9.0=0 +phy_an_c73_13.0=0 +phy_an_c73_17.0=0 +phy_an_c73_21.0=0 +phy_an_c73_25.0=0 +phy_an_c73_29.0=0 +phy_an_c73_33.0=0 +phy_an_c73_37.0=0 +phy_an_c73_41.0=0 +phy_an_c73_45.0=0 +phy_an_c73_49.0=0 +phy_an_c73_53.0=0 +phy_an_c73_57.0=0 +phy_an_c73_61.0=0 +phy_an_c73_65.0=0 +phy_an_c73_69.0=0 +phy_an_c73_73.0=0 +phy_an_c73_77.0=0 +phy_an_c73_81.0=0 +phy_an_c73_85.0=0 +phy_an_c73_89.0=0 +phy_an_c73_93.0=0 +phy_an_c73_97.0=2 +phy_an_c73_98.0=2 +phy_an_c73_99.0=2 +phy_an_c73_100.0=2 +phy_an_c73_101.0=2 +phy_an_c73_102.0=2 +phy_an_c73_103.0=2 +phy_an_c73_104.0=2 +phy_xaui_rx_polarity_flip_1.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x0 +phy_xaui_rx_polarity_flip_9.0=0x4 +phy_xaui_rx_polarity_flip_13.0=0x0 +phy_xaui_rx_polarity_flip_17.0=0xb +phy_xaui_rx_polarity_flip_21.0=0x3 +phy_xaui_rx_polarity_flip_25.0=0xb +phy_xaui_rx_polarity_flip_29.0=0xf +phy_xaui_rx_polarity_flip_33.0=0xb +phy_xaui_rx_polarity_flip_37.0=0x3 +phy_xaui_rx_polarity_flip_41.0=0xb +phy_xaui_rx_polarity_flip_45.0=0x0 +phy_xaui_rx_polarity_flip_49.0=0x4 +phy_xaui_rx_polarity_flip_53.0=0xc +phy_xaui_rx_polarity_flip_57.0=0x4 +phy_xaui_rx_polarity_flip_61.0=0x0 +phy_xaui_rx_polarity_flip_65.0=0xb +phy_xaui_rx_polarity_flip_69.0=0x3 +phy_xaui_rx_polarity_flip_73.0=0xb +phy_xaui_rx_polarity_flip_77.0=0xf +phy_xaui_rx_polarity_flip_81.0=0xb +phy_xaui_rx_polarity_flip_85.0=0x3 +phy_xaui_rx_polarity_flip_89.0=0x4 +phy_xaui_rx_polarity_flip_93.0=0x0 +phy_xaui_rx_polarity_flip_97.0=0xb +phy_xaui_rx_polarity_flip_98.0=0x3 +phy_xaui_rx_polarity_flip_99.0=0x4 +phy_xaui_rx_polarity_flip_100.0=0x0 +phy_xaui_rx_polarity_flip_101.0=0x0 +phy_xaui_rx_polarity_flip_102.0=0xe +phy_xaui_rx_polarity_flip_103.0=0x0 +phy_xaui_rx_polarity_flip_104.0=0x0 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_5.0=0x0 +phy_xaui_tx_polarity_flip_9.0=0x2 +phy_xaui_tx_polarity_flip_13.0=0x0 +phy_xaui_tx_polarity_flip_17.0=0xd +phy_xaui_tx_polarity_flip_21.0=0xc +phy_xaui_tx_polarity_flip_25.0=0xd +phy_xaui_tx_polarity_flip_29.0=0xf +phy_xaui_tx_polarity_flip_33.0=0xd +phy_xaui_tx_polarity_flip_37.0=0xc +phy_xaui_tx_polarity_flip_41.0=0xd +phy_xaui_tx_polarity_flip_45.0=0x0 +phy_xaui_tx_polarity_flip_49.0=0x2 +phy_xaui_tx_polarity_flip_53.0=0x3 +phy_xaui_tx_polarity_flip_57.0=0x2 +phy_xaui_tx_polarity_flip_61.0=0x0 +phy_xaui_tx_polarity_flip_65.0=0xd +phy_xaui_tx_polarity_flip_69.0=0xc +phy_xaui_tx_polarity_flip_73.0=0xd +phy_xaui_tx_polarity_flip_77.0=0xf +phy_xaui_tx_polarity_flip_81.0=0xd +phy_xaui_tx_polarity_flip_85.0=0xc +phy_xaui_tx_polarity_flip_89.0=0x2 +phy_xaui_tx_polarity_flip_93.0=0x0 +phy_xaui_tx_polarity_flip_97.0=0xd +phy_xaui_tx_polarity_flip_98.0=0xc +phy_xaui_tx_polarity_flip_99.0=0x2 +phy_xaui_tx_polarity_flip_100.0=0x0 +phy_xaui_tx_polarity_flip_101.0=0x0 +phy_xaui_tx_polarity_flip_102.0=0x7 +phy_xaui_tx_polarity_flip_103.0=0x2 +phy_xaui_tx_polarity_flip_104.0=0x0 +port_init_autoneg_1.0=0 +port_init_autoneg_5.0=0 +port_init_autoneg_9.0=0 +port_init_autoneg_13.0=0 +port_init_autoneg_17.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_25.0=0 +port_init_autoneg_29.0=0 +port_init_autoneg_33.0=0 +port_init_autoneg_37.0=0 +port_init_autoneg_41.0=0 +port_init_autoneg_45.0=0 +port_init_autoneg_49.0=0 +port_init_autoneg_53.0=0 +port_init_autoneg_57.0=0 +port_init_autoneg_61.0=0 +port_init_autoneg_65.0=0 +port_init_autoneg_69.0=0 +port_init_autoneg_73.0=0 +port_init_autoneg_77.0=0 +port_init_autoneg_81.0=0 +port_init_autoneg_85.0=0 +port_init_autoneg_89.0=0 +port_init_autoneg_93.0=0 +port_init_autoneg_97.0=0 +port_init_autoneg_98.0=0 +port_init_autoneg_99.0=0 +port_init_autoneg_100.0=0 +port_init_autoneg_101.0=0 +port_init_autoneg_102.0=0 +port_init_autoneg_103.0=0 +port_init_autoneg_104.0=0 +port_init_cl72.0=0 +portmap_1.0=9:10 +portmap_2.0=10:10 +portmap_3.0=11:10 +portmap_4.0=12:10 +portmap_5.0=13:40 +portmap_9.0=17:40 +portmap_13.0=21:40 +portmap_17.0=29:40 +portmap_21.0=25:40 +portmap_25.0=33:40 +portmap_29.0=37:40 +portmap_33.0=45:40 +portmap_37.0=41:40 +portmap_41.0=49:40 +portmap_45.0=53:40 +portmap_49.0=69:40 +portmap_53.0=65:40 +portmap_57.0=73:40 +portmap_61.0=77:40 +portmap_65.0=93:40 +portmap_69.0=89:40 +portmap_73.0=97:40 +portmap_77.0=101:40 +portmap_81.0=109:40 +portmap_85.0=105:40 +portmap_89.0=121:40 +portmap_93.0=125:40 +portmap_97.0=61:40 +portmap_98.0=57:40 +portmap_99.0=81:40 +portmap_100.0=85:40 +portmap_101.0=117:40 +portmap_102.0=113:40 +portmap_103.0=1:40 +portmap_104.0=5:40 +schan_intr_enable=0 +serdes_firmware_mode_1.0=2 +serdes_firmware_mode_5.0=2 +serdes_firmware_mode_9.0=2 +serdes_firmware_mode_13.0=2 +serdes_firmware_mode_17.0=2 +serdes_firmware_mode_21.0=2 +serdes_firmware_mode_25.0=2 +serdes_firmware_mode_29.0=2 +serdes_firmware_mode_33.0=2 +serdes_firmware_mode_37.0=2 +serdes_firmware_mode_41.0=2 +serdes_firmware_mode_45.0=2 +serdes_firmware_mode_49.0=2 +serdes_firmware_mode_53.0=2 +serdes_firmware_mode_57.0=2 +serdes_firmware_mode_61.0=2 +serdes_firmware_mode_65.0=2 +serdes_firmware_mode_69.0=2 +serdes_firmware_mode_73.0=2 +serdes_firmware_mode_77.0=2 +serdes_firmware_mode_81.0=2 +serdes_firmware_mode_85.0=2 +serdes_firmware_mode_89.0=2 +serdes_firmware_mode_93.0=2 +serdes_firmware_mode_97.0=2 +serdes_firmware_mode_98.0=2 +serdes_firmware_mode_99.0=2 +serdes_firmware_mode_100.0=2 +serdes_firmware_mode_101.0=2 +serdes_firmware_mode_102.0=2 +serdes_firmware_mode_103.0=2 +serdes_firmware_mode_104.0=2 +stable_size=0x2000000 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 +xgxs_lcpll_xtal_refclk.0=1 +xgxs_rx_lane_map_1.0=0x3210 +xgxs_rx_lane_map_5.0=0x0321 +xgxs_rx_lane_map_9.0=0x1302 +xgxs_rx_lane_map_13.0=0x0213 +xgxs_rx_lane_map_17.0=0x1302 +xgxs_rx_lane_map_21.0=0x1302 +xgxs_rx_lane_map_25.0=0x1302 +xgxs_rx_lane_map_29.0=0x0213 +xgxs_rx_lane_map_33.0=0x1302 +xgxs_rx_lane_map_37.0=0x1302 +xgxs_rx_lane_map_41.0=0x1302 +xgxs_rx_lane_map_45.0=0x0213 +xgxs_rx_lane_map_49.0=0x1302 +xgxs_rx_lane_map_53.0=0x1302 +xgxs_rx_lane_map_57.0=0x1302 +xgxs_rx_lane_map_61.0=0x0213 +xgxs_rx_lane_map_65.0=0x1302 +xgxs_rx_lane_map_69.0=0x1302 +xgxs_rx_lane_map_73.0=0x1302 +xgxs_rx_lane_map_77.0=0x0213 +xgxs_rx_lane_map_81.0=0x1302 +xgxs_rx_lane_map_85.0=0x1302 +xgxs_rx_lane_map_89.0=0x1302 +xgxs_rx_lane_map_93.0=0x0213 +xgxs_rx_lane_map_97.0=0x1302 +xgxs_rx_lane_map_98.0=0x1302 +xgxs_rx_lane_map_99.0=0x1302 +xgxs_rx_lane_map_100.0=0x0213 +xgxs_rx_lane_map_101.0=0x0213 +xgxs_rx_lane_map_102.0=0x1302 +xgxs_rx_lane_map_103.0=0x0123 +xgxs_rx_lane_map_104.0=0x2031 +xgxs_tx_lane_map_1.0=0x0123 +xgxs_tx_lane_map_5.0=0x0321 +xgxs_tx_lane_map_9.0=0x2031 +xgxs_tx_lane_map_13.0=0x0213 +xgxs_tx_lane_map_17.0=0x2031 +xgxs_tx_lane_map_21.0=0x2031 +xgxs_tx_lane_map_25.0=0x2031 +xgxs_tx_lane_map_29.0=0x0213 +xgxs_tx_lane_map_33.0=0x2031 +xgxs_tx_lane_map_37.0=0x2031 +xgxs_tx_lane_map_41.0=0x2031 +xgxs_tx_lane_map_45.0=0x0213 +xgxs_tx_lane_map_49.0=0x2031 +xgxs_tx_lane_map_53.0=0x2031 +xgxs_tx_lane_map_57.0=0x2031 +xgxs_tx_lane_map_61.0=0x0213 +xgxs_tx_lane_map_65.0=0x2031 +xgxs_tx_lane_map_69.0=0x2031 +xgxs_tx_lane_map_73.0=0x2031 +xgxs_tx_lane_map_77.0=0x0213 +xgxs_tx_lane_map_81.0=0x2031 +xgxs_tx_lane_map_85.0=0x2031 +xgxs_tx_lane_map_89.0=0x2031 +xgxs_tx_lane_map_93.0=0x0213 +xgxs_tx_lane_map_97.0=0x2031 +xgxs_tx_lane_map_98.0=0x2031 +xgxs_tx_lane_map_99.0=0x2031 +xgxs_tx_lane_map_100.0=0x0213 +xgxs_tx_lane_map_101.0=0x0213 +xgxs_tx_lane_map_102.0=0x2031 +xgxs_tx_lane_map_103.0=0x3120 +xgxs_tx_lane_map_104.0=0x1302 + +# tuning parameters +serdes_preemphasis_lane0_1.0=0x81f7 +serdes_preemphasis_lane1_1.0=0x81f7 +serdes_preemphasis_lane2_1.0=0x81f7 +serdes_preemphasis_lane3_1.0=0x81f7 +serdes_pre_driver_current_lane0_5.0=0x7 +serdes_driver_current_lane0_5.0=0x7 +serdes_preemphasis_lane0_5.0=0xc2f0 +serdes_pre_driver_current_lane1_5.0=0x7 +serdes_driver_current_lane1_5.0=0x7 +serdes_preemphasis_lane1_5.0=0xc2f0 +serdes_pre_driver_current_lane2_5.0=0x7 +serdes_driver_current_lane2_5.0=0x7 +serdes_preemphasis_lane2_5.0=0xc2f0 +serdes_pre_driver_current_lane3_5.0=0x7 +serdes_driver_current_lane3_5.0=0x7 +serdes_preemphasis_lane3_5.0=0xc2f0 +serdes_pre_driver_current_lane0_9.0=0x7 +serdes_driver_current_lane0_9.0=0x7 +serdes_preemphasis_lane0_9.0=0xbb10 +serdes_pre_driver_current_lane1_9.0=0x7 +serdes_driver_current_lane1_9.0=0x7 +serdes_preemphasis_lane1_9.0=0xbb10 +serdes_pre_driver_current_lane2_9.0=0x7 +serdes_driver_current_lane2_9.0=0x7 +serdes_preemphasis_lane2_9.0=0xbb10 +serdes_pre_driver_current_lane3_9.0=0x7 +serdes_driver_current_lane3_9.0=0x7 +serdes_preemphasis_lane3_9.0=0xbb10 +serdes_pre_driver_current_lane0_13.0=0x7 +serdes_driver_current_lane0_13.0=0x7 +serdes_preemphasis_lane0_13.0=0xbb10 +serdes_pre_driver_current_lane1_13.0=0x7 +serdes_driver_current_lane1_13.0=0x7 +serdes_preemphasis_lane1_13.0=0xbb10 +serdes_pre_driver_current_lane2_13.0=0x7 +serdes_driver_current_lane2_13.0=0x7 +serdes_preemphasis_lane2_13.0=0xbb10 +serdes_pre_driver_current_lane3_13.0=0x7 +serdes_driver_current_lane3_13.0=0x7 +serdes_preemphasis_lane3_13.0=0xbb10 +serdes_pre_driver_current_lane0_17.0=0x6 +serdes_driver_current_lane0_17.0=0x6 +serdes_preemphasis_lane0_17.0=0xb720 +serdes_pre_driver_current_lane1_17.0=0x6 +serdes_driver_current_lane1_17.0=0x6 +serdes_preemphasis_lane1_17.0=0xb720 +serdes_pre_driver_current_lane2_17.0=0x6 +serdes_driver_current_lane2_17.0=0x6 +serdes_preemphasis_lane2_17.0=0xb720 +serdes_pre_driver_current_lane3_17.0=0x6 +serdes_driver_current_lane3_17.0=0x6 +serdes_preemphasis_lane3_17.0=0xb720 +serdes_pre_driver_current_lane0_21.0=0x7 +serdes_driver_current_lane0_21.0=0x7 +serdes_preemphasis_lane0_21.0=0xbb10 +serdes_pre_driver_current_lane1_21.0=0x7 +serdes_driver_current_lane1_21.0=0x7 +serdes_preemphasis_lane1_21.0=0xbb10 +serdes_pre_driver_current_lane2_21.0=0x7 +serdes_driver_current_lane2_21.0=0x7 +serdes_preemphasis_lane2_21.0=0xbb10 +serdes_pre_driver_current_lane3_21.0=0x7 +serdes_driver_current_lane3_21.0=0x7 +serdes_preemphasis_lane3_21.0=0xbb10 +serdes_pre_driver_current_lane0_25.0=0x5 +serdes_driver_current_lane0_25.0=0x5 +serdes_preemphasis_lane0_25.0=0xb720 +serdes_pre_driver_current_lane1_25.0=0x5 +serdes_driver_current_lane1_25.0=0x5 +serdes_preemphasis_lane1_25.0=0xb720 +serdes_pre_driver_current_lane2_25.0=0x5 +serdes_driver_current_lane2_25.0=0x5 +serdes_preemphasis_lane2_25.0=0xb720 +serdes_pre_driver_current_lane3_25.0=0x5 +serdes_driver_current_lane3_25.0=0x5 +serdes_preemphasis_lane3_25.0=0xb720 +serdes_pre_driver_current_lane0_29.0=0x5 +serdes_driver_current_lane0_29.0=0x5 +serdes_preemphasis_lane0_29.0=0xb720 +serdes_pre_driver_current_lane1_29.0=0x5 +serdes_driver_current_lane1_29.0=0x5 +serdes_preemphasis_lane1_29.0=0xb720 +serdes_pre_driver_current_lane2_29.0=0x5 +serdes_driver_current_lane2_29.0=0x5 +serdes_preemphasis_lane2_29.0=0xb720 +serdes_pre_driver_current_lane3_29.0=0x5 +serdes_driver_current_lane3_29.0=0x5 +serdes_preemphasis_lane3_29.0=0xb720 +serdes_pre_driver_current_lane0_33.0=0x4 +serdes_driver_current_lane0_33.0=0x4 +serdes_preemphasis_lane0_33.0=0xb720 +serdes_pre_driver_current_lane1_33.0=0x4 +serdes_driver_current_lane1_33.0=0x4 +serdes_preemphasis_lane1_33.0=0xb720 +serdes_pre_driver_current_lane2_33.0=0x4 +serdes_driver_current_lane2_33.0=0x4 +serdes_preemphasis_lane2_33.0=0xb720 +serdes_pre_driver_current_lane3_33.0=0x4 +serdes_driver_current_lane3_33.0=0x4 +serdes_preemphasis_lane3_33.0=0xb720 +serdes_pre_driver_current_lane0_37.0=0x5 +serdes_driver_current_lane0_37.0=0x5 +serdes_preemphasis_lane0_37.0=0xb720 +serdes_pre_driver_current_lane1_37.0=0x5 +serdes_driver_current_lane1_37.0=0x5 +serdes_preemphasis_lane1_37.0=0xb720 +serdes_pre_driver_current_lane2_37.0=0x5 +serdes_driver_current_lane2_37.0=0x5 +serdes_preemphasis_lane2_37.0=0xb720 +serdes_pre_driver_current_lane3_37.0=0x5 +serdes_driver_current_lane3_37.0=0x5 +serdes_preemphasis_lane3_37.0=0xb720 +serdes_pre_driver_current_lane0_41.0=0x3 +serdes_driver_current_lane0_41.0=0x3 +serdes_preemphasis_lane0_41.0=0xb330 +serdes_pre_driver_current_lane1_41.0=0x3 +serdes_driver_current_lane1_41.0=0x3 +serdes_preemphasis_lane1_41.0=0xb330 +serdes_pre_driver_current_lane2_41.0=0x3 +serdes_driver_current_lane2_41.0=0x3 +serdes_preemphasis_lane2_41.0=0xb330 +serdes_pre_driver_current_lane3_41.0=0x3 +serdes_driver_current_lane3_41.0=0x3 +serdes_preemphasis_lane3_41.0=0xb330 +serdes_pre_driver_current_lane0_45.0=0x4 +serdes_driver_current_lane0_45.0=0x4 +serdes_preemphasis_lane0_45.0=0xb720 +serdes_pre_driver_current_lane1_45.0=0x4 +serdes_driver_current_lane1_45.0=0x4 +serdes_preemphasis_lane1_45.0=0xb720 +serdes_pre_driver_current_lane2_45.0=0x4 +serdes_driver_current_lane2_45.0=0x4 +serdes_preemphasis_lane2_45.0=0xb720 +serdes_pre_driver_current_lane3_45.0=0x4 +serdes_driver_current_lane3_45.0=0x4 +serdes_preemphasis_lane3_45.0=0xb720 +serdes_pre_driver_current_lane0_49.0=0x3 +serdes_driver_current_lane0_49.0=0x3 +serdes_preemphasis_lane0_49.0=0xb330 +serdes_pre_driver_current_lane1_49.0=0x3 +serdes_driver_current_lane1_49.0=0x3 +serdes_preemphasis_lane1_49.0=0xb330 +serdes_pre_driver_current_lane2_49.0=0x3 +serdes_driver_current_lane2_49.0=0x3 +serdes_preemphasis_lane2_49.0=0xb330 +serdes_pre_driver_current_lane3_49.0=0x3 +serdes_driver_current_lane3_49.0=0x3 +serdes_preemphasis_lane3_49.0=0xb330 +serdes_pre_driver_current_lane0_53.0=0x4 +serdes_driver_current_lane0_53.0=0x4 +serdes_preemphasis_lane0_53.0=0xb720 +serdes_pre_driver_current_lane1_53.0=0x4 +serdes_driver_current_lane1_53.0=0x4 +serdes_preemphasis_lane1_53.0=0xb720 +serdes_pre_driver_current_lane2_53.0=0x4 +serdes_driver_current_lane2_53.0=0x4 +serdes_preemphasis_lane2_53.0=0xb720 +serdes_pre_driver_current_lane3_53.0=0x4 +serdes_driver_current_lane3_53.0=0x4 +serdes_preemphasis_lane3_53.0=0xb720 +serdes_pre_driver_current_lane0_57.0=0x3 +serdes_driver_current_lane0_57.0=0x3 +serdes_preemphasis_lane0_57.0=0xb330 +serdes_pre_driver_current_lane1_57.0=0x3 +serdes_driver_current_lane1_57.0=0x3 +serdes_preemphasis_lane1_57.0=0xb330 +serdes_pre_driver_current_lane2_57.0=0x3 +serdes_driver_current_lane2_57.0=0x3 +serdes_preemphasis_lane2_57.0=0xb330 +serdes_pre_driver_current_lane3_57.0=0x3 +serdes_driver_current_lane3_57.0=0x3 +serdes_preemphasis_lane3_57.0=0xb330 +serdes_pre_driver_current_lane0_61.0=0x4 +serdes_driver_current_lane0_61.0=0x4 +serdes_preemphasis_lane0_61.0=0xb720 +serdes_pre_driver_current_lane1_61.0=0x4 +serdes_driver_current_lane1_61.0=0x4 +serdes_preemphasis_lane1_61.0=0xb720 +serdes_pre_driver_current_lane2_61.0=0x4 +serdes_driver_current_lane2_61.0=0x4 +serdes_preemphasis_lane2_61.0=0xb720 +serdes_pre_driver_current_lane3_61.0=0x4 +serdes_driver_current_lane3_61.0=0x4 +serdes_preemphasis_lane3_61.0=0xb720 +serdes_pre_driver_current_lane0_65.0=0x4 +serdes_driver_current_lane0_65.0=0x4 +serdes_preemphasis_lane0_65.0=0xb720 +serdes_pre_driver_current_lane1_65.0=0x4 +serdes_driver_current_lane1_65.0=0x4 +serdes_preemphasis_lane1_65.0=0xb720 +serdes_pre_driver_current_lane2_65.0=0x4 +serdes_driver_current_lane2_65.0=0x4 +serdes_preemphasis_lane2_65.0=0xb720 +serdes_pre_driver_current_lane3_65.0=0x4 +serdes_driver_current_lane3_65.0=0x4 +serdes_preemphasis_lane3_65.0=0xb720 +serdes_pre_driver_current_lane0_69.0=0x4 +serdes_driver_current_lane0_69.0=0x4 +serdes_preemphasis_lane0_69.0=0xb720 +serdes_pre_driver_current_lane1_69.0=0x4 +serdes_driver_current_lane1_69.0=0x4 +serdes_preemphasis_lane1_69.0=0xb720 +serdes_pre_driver_current_lane2_69.0=0x4 +serdes_driver_current_lane2_69.0=0x4 +serdes_preemphasis_lane2_69.0=0xb720 +serdes_pre_driver_current_lane3_69.0=0x4 +serdes_driver_current_lane3_69.0=0x4 +serdes_preemphasis_lane3_69.0=0xb720 +serdes_pre_driver_current_lane0_73.0=0x4 +serdes_driver_current_lane0_73.0=0x4 +serdes_preemphasis_lane0_73.0=0xb720 +serdes_pre_driver_current_lane1_73.0=0x4 +serdes_driver_current_lane1_73.0=0x4 +serdes_preemphasis_lane1_73.0=0xb720 +serdes_pre_driver_current_lane2_73.0=0x4 +serdes_driver_current_lane2_73.0=0x4 +serdes_preemphasis_lane2_73.0=0xb720 +serdes_pre_driver_current_lane3_73.0=0x4 +serdes_driver_current_lane3_73.0=0x4 +serdes_preemphasis_lane3_73.0=0xb720 +serdes_pre_driver_current_lane0_77.0=0x5 +serdes_driver_current_lane0_77.0=0x5 +serdes_preemphasis_lane0_77.0=0xb720 +serdes_pre_driver_current_lane1_77.0=0x5 +serdes_driver_current_lane1_77.0=0x5 +serdes_preemphasis_lane1_77.0=0xb720 +serdes_pre_driver_current_lane2_77.0=0x5 +serdes_driver_current_lane2_77.0=0x5 +serdes_preemphasis_lane2_77.0=0xb720 +serdes_pre_driver_current_lane3_77.0=0x5 +serdes_driver_current_lane3_77.0=0x5 +serdes_preemphasis_lane3_77.0=0xb720 +serdes_pre_driver_current_lane0_81.0=0x5 +serdes_driver_current_lane0_81.0=0x5 +serdes_preemphasis_lane0_81.0=0xb720 +serdes_pre_driver_current_lane1_81.0=0x5 +serdes_driver_current_lane1_81.0=0x5 +serdes_preemphasis_lane1_81.0=0xb720 +serdes_pre_driver_current_lane2_81.0=0x5 +serdes_driver_current_lane2_81.0=0x5 +serdes_preemphasis_lane2_81.0=0xb720 +serdes_pre_driver_current_lane3_81.0=0x5 +serdes_driver_current_lane3_81.0=0x5 +serdes_preemphasis_lane3_81.0=0xb720 +serdes_pre_driver_current_lane0_85.0=0x5 +serdes_driver_current_lane0_85.0=0x5 +serdes_preemphasis_lane0_85.0=0xb720 +serdes_pre_driver_current_lane1_85.0=0x5 +serdes_driver_current_lane1_85.0=0x5 +serdes_preemphasis_lane1_85.0=0xb720 +serdes_pre_driver_current_lane2_85.0=0x5 +serdes_driver_current_lane2_85.0=0x5 +serdes_preemphasis_lane2_85.0=0xb720 +serdes_pre_driver_current_lane3_85.0=0x5 +serdes_driver_current_lane3_85.0=0x5 +serdes_preemphasis_lane3_85.0=0xb720 +serdes_pre_driver_current_lane0_89.0=0x6 +serdes_driver_current_lane0_89.0=0x6 +serdes_preemphasis_lane0_89.0=0xb720 +serdes_pre_driver_current_lane1_89.0=0x6 +serdes_driver_current_lane1_89.0=0x6 +serdes_preemphasis_lane1_89.0=0xb720 +serdes_pre_driver_current_lane2_89.0=0x6 +serdes_driver_current_lane2_89.0=0x6 +serdes_preemphasis_lane2_89.0=0xb720 +serdes_pre_driver_current_lane3_89.0=0x6 +serdes_driver_current_lane3_89.0=0x6 +serdes_preemphasis_lane3_89.0=0xb720 +serdes_pre_driver_current_lane0_93.0=0x7 +serdes_driver_current_lane0_93.0=0x7 +serdes_preemphasis_lane0_93.0=0xbb10 +serdes_pre_driver_current_lane1_93.0=0x7 +serdes_driver_current_lane1_93.0=0x7 +serdes_preemphasis_lane1_93.0=0xbb10 +serdes_pre_driver_current_lane2_93.0=0x7 +serdes_driver_current_lane2_93.0=0x7 +serdes_preemphasis_lane2_93.0=0xbb10 +serdes_pre_driver_current_lane3_93.0=0x7 +serdes_driver_current_lane3_93.0=0x7 +serdes_preemphasis_lane3_93.0=0xbb10 +serdes_pre_driver_current_lane0_97.0=0x5 +serdes_driver_current_lane0_97.0=0x5 +serdes_preemphasis_lane0_97.0=0xb720 +serdes_pre_driver_current_lane1_97.0=0x5 +serdes_driver_current_lane1_97.0=0x5 +serdes_preemphasis_lane1_97.0=0xb720 +serdes_pre_driver_current_lane2_97.0=0x5 +serdes_driver_current_lane2_97.0=0x5 +serdes_preemphasis_lane2_97.0=0xb720 +serdes_pre_driver_current_lane3_97.0=0x5 +serdes_driver_current_lane3_97.0=0x5 +serdes_preemphasis_lane3_97.0=0xb720 +serdes_pre_driver_current_lane0_98.0=0x6 +serdes_driver_current_lane0_98.0=0x6 +serdes_preemphasis_lane0_98.0=0xb720 +serdes_pre_driver_current_lane1_98.0=0x6 +serdes_driver_current_lane1_98.0=0x6 +serdes_preemphasis_lane1_98.0=0xb720 +serdes_pre_driver_current_lane2_98.0=0x6 +serdes_driver_current_lane2_98.0=0x6 +serdes_preemphasis_lane2_98.0=0xb720 +serdes_pre_driver_current_lane3_98.0=0x6 +serdes_driver_current_lane3_98.0=0x6 +serdes_preemphasis_lane3_98.0=0xb720 +serdes_pre_driver_current_lane0_99.0=0x5 +serdes_driver_current_lane0_99.0=0x5 +serdes_preemphasis_lane0_99.0=0xb720 +serdes_pre_driver_current_lane1_99.0=0x5 +serdes_driver_current_lane1_99.0=0x5 +serdes_preemphasis_lane1_99.0=0xb720 +serdes_pre_driver_current_lane2_99.0=0x5 +serdes_driver_current_lane2_99.0=0x5 +serdes_preemphasis_lane2_99.0=0xb720 +serdes_pre_driver_current_lane3_99.0=0x5 +serdes_driver_current_lane3_99.0=0x5 +serdes_preemphasis_lane3_99.0=0xb720 +serdes_pre_driver_current_lane0_100.0=0x7 +serdes_driver_current_lane0_100.0=0x7 +serdes_preemphasis_lane0_100.0=0xbb10 +serdes_pre_driver_current_lane1_100.0=0x7 +serdes_driver_current_lane1_100.0=0x7 +serdes_preemphasis_lane1_100.0=0xbb10 +serdes_pre_driver_current_lane2_100.0=0x7 +serdes_driver_current_lane2_100.0=0x7 +serdes_preemphasis_lane2_100.0=0xbb10 +serdes_pre_driver_current_lane3_100.0=0x7 +serdes_driver_current_lane3_100.0=0x7 +serdes_preemphasis_lane3_100.0=0xbb10 +serdes_pre_driver_current_lane0_101.0=0x7 +serdes_driver_current_lane0_101.0=0x7 +serdes_preemphasis_lane0_101.0=0xbb10 +serdes_pre_driver_current_lane1_101.0=0x7 +serdes_driver_current_lane1_101.0=0x7 +serdes_preemphasis_lane1_101.0=0xbb10 +serdes_pre_driver_current_lane2_101.0=0x7 +serdes_driver_current_lane2_101.0=0x7 +serdes_preemphasis_lane2_101.0=0xbb10 +serdes_pre_driver_current_lane3_101.0=0x7 +serdes_driver_current_lane3_101.0=0x7 +serdes_preemphasis_lane3_101.0=0xbb10 +serdes_pre_driver_current_lane0_102.0=0x7 +serdes_driver_current_lane0_102.0=0x7 +serdes_preemphasis_lane0_102.0=0xbb10 +serdes_pre_driver_current_lane1_102.0=0x7 +serdes_driver_current_lane1_102.0=0x7 +serdes_preemphasis_lane1_102.0=0xbb10 +serdes_pre_driver_current_lane2_102.0=0x7 +serdes_driver_current_lane2_102.0=0x7 +serdes_preemphasis_lane2_102.0=0xbb10 +serdes_pre_driver_current_lane3_102.0=0x7 +serdes_driver_current_lane3_102.0=0x7 +serdes_preemphasis_lane3_102.0=0xbb10 +serdes_preemphasis_lane0_103.0=0x81f4 +serdes_preemphasis_lane1_103.0=0x81f4 +serdes_preemphasis_lane2_103.0=0x81f4 +serdes_preemphasis_lane3_103.0=0x81f4 +serdes_preemphasis_lane0_104.0=0x81f5 +serdes_preemphasis_lane1_104.0=0x81f5 +serdes_preemphasis_lane2_104.0=0x81f5 +serdes_preemphasis_lane3_104.0=0x81f5 diff --git a/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX32S-Q32 b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX32S-Q32 new file mode 120000 index 000000000000..6a90d8a3ac70 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/Arista-7050QX32S-Q32 @@ -0,0 +1 @@ +Arista-7050-QX-32S \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32s/default_sku b/device/arista/x86_64-arista_7050_qx32s/default_sku new file mode 100644 index 000000000000..657093e0b603 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/default_sku @@ -0,0 +1 @@ +Arista-7050-QX-32S t1 diff --git a/device/arista/x86_64-arista_7050_qx32s/fancontrol b/device/arista/x86_64-arista_7050_qx32s/fancontrol new file mode 100644 index 000000000000..9c329897c9e4 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=5 +DEVPATH=hwmon2=devices/pci0000:00/0000:00:02.2/0000:02:00.0/i2c-2/2-004c hwmon4=devices/pci0000:00/0000:00:02.2/0000:02:00.0/i2c-3/3-0060 +DEVNAME=hwmon2=max6658 hwmon4=crow_cpld +FCTEMPS=hwmon4/pwm4=hwmon2/temp1_input hwmon4/pwm3=hwmon2/temp1_input hwmon4/pwm2=hwmon2/temp1_input hwmon4/pwm1=hwmon2/temp1_input +FCFANS=hwmon4/pwm4=hwmon4/fan4_input hwmon4/pwm3=hwmon4/fan3_input hwmon4/pwm2=hwmon4/fan2_input hwmon4/pwm1=hwmon4/fan1_input +MINTEMP=hwmon4/pwm4=35 hwmon4/pwm3=35 hwmon4/pwm2=35 hwmon4/pwm1=35 +MINPWM=hwmon4/pwm4=179 hwmon4/pwm3=179 hwmon4/pwm2=179 hwmon4/pwm1=179 +MAXTEMP=hwmon4/pwm4=45 hwmon4/pwm3=45 hwmon4/pwm2=45 hwmon4/pwm1=45 +MINSTART=hwmon4/pwm4=179 hwmon4/pwm3=179 hwmon4/pwm2=179 hwmon4/pwm1=179 +MINSTOP=hwmon4/pwm4=179 hwmon4/pwm3=179 hwmon4/pwm2=179 hwmon4/pwm1=179 diff --git a/device/arista/x86_64-arista_7050_qx32s/pcie.yaml b/device/arista/x86_64-arista_7050_qx32s/pcie.yaml new file mode 100644 index 000000000000..d40522ff4998 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/pcie.yaml @@ -0,0 +1,135 @@ +- bus: '00' + dev: '00' + fn: '0' + id: '1536' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Root + Complex' +- bus: '00' + dev: '01' + fn: '0' + id: '9831' + name: 'VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Kabini + [Radeon HD 8400E]' +- bus: '00' + dev: '02' + fn: '0' + id: '1538' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Function + 0' +- bus: '00' + dev: '02' + fn: '1' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '2' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '3' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '4' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '5' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '11' + fn: '0' + id: '7801' + name: 'SATA controller: Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI + mode] (rev 40)' +- bus: '00' + dev: '12' + fn: '0' + id: '7807' + name: 'USB controller: Advanced Micro Devices, Inc. [AMD] FCH USB OHCI Controller + (rev 39)' +- bus: '00' + dev: '12' + fn: '2' + id: '7808' + name: 'USB controller: Advanced Micro Devices, Inc. [AMD] FCH USB EHCI Controller + (rev 39)' +- bus: '00' + dev: '14' + fn: '0' + id: 780b + name: 'SMBus: Advanced Micro Devices, Inc. [AMD] FCH SMBus Controller (rev 3a)' +- bus: '00' + dev: '14' + fn: '3' + id: 780e + name: 'ISA bridge: Advanced Micro Devices, Inc. [AMD] FCH LPC Bridge (rev 11)' +- bus: '00' + dev: '14' + fn: '7' + id: '7813' + name: 'SD Host controller: Advanced Micro Devices, Inc. [AMD] FCH SD Flash Controller + (rev 01)' +- bus: '00' + dev: '18' + fn: '0' + id: '1530' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Function + 0' +- bus: '00' + dev: '18' + fn: '1' + id: '1531' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Function + 1' +- bus: '00' + dev: '18' + fn: '2' + id: '1532' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Function + 2' +- bus: '00' + dev: '18' + fn: '3' + id: '1533' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Function + 3' +- bus: '00' + dev: '18' + fn: '4' + id: '1534' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Function + 4' +- bus: '00' + dev: '18' + fn: '5' + id: '1535' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Function + 5' +- bus: '01' + dev: '00' + fn: '0' + id: b850 + name: 'Ethernet controller: Broadcom Limited Broadcom BCM56850 Switch ASIC (rev + 03)' +- bus: '02' + dev: '00' + fn: '0' + id: '0001' + name: 'System peripheral: Arastra Inc. Device 0001 (rev 01)' +- bus: '04' + dev: '00' + fn: '0' + id: '1682' + name: 'Ethernet controller: Broadcom Limited NetXtreme BCM57762 Gigabit Ethernet + PCIe (rev 20)' diff --git a/device/arista/x86_64-arista_7050_qx32s/platform.json b/device/arista/x86_64-arista_7050_qx32s/platform.json new file mode 100644 index 000000000000..7d725b59fe13 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/platform.json @@ -0,0 +1,197 @@ +{ + "chassis": { + "name": "DCS-7050QX-32S", + "components": [], + "fans": [], + "fan_drawers": [ + { + "name": "slot1", + "fans": [ + { + "name": "fan1" + } + ] + }, + { + "name": "slot2", + "fans": [ + { + "name": "fan2" + } + ] + }, + { + "name": "slot3", + "fans": [ + { + "name": "fan3" + } + ] + }, + { + "name": "slot4", + "fans": [ + { + "name": "fan4" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Cpu temp sensor" + }, + { + "name": "Cpu board temp sensor" + }, + { + "name": "Back-panel temp sensor" + }, + { + "name": "Board Sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Power supply 1 hotspot sensor" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 exhaust temp sensor" + }, + { + "name": "Power supply 2 hotspot sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 exhaust temp sensor" + } + ], + "sfps": [ + { + "name": "sfp1" + }, + { + "name": "sfp2" + }, + { + "name": "sfp3" + }, + { + "name": "sfp4" + }, + { + "name": "qsfp5" + }, + { + "name": "qsfp6" + }, + { + "name": "qsfp7" + }, + { + "name": "qsfp8" + }, + { + "name": "qsfp9" + }, + { + "name": "qsfp10" + }, + { + "name": "qsfp11" + }, + { + "name": "qsfp12" + }, + { + "name": "qsfp13" + }, + { + "name": "qsfp14" + }, + { + "name": "qsfp15" + }, + { + "name": "qsfp16" + }, + { + "name": "qsfp17" + }, + { + "name": "qsfp18" + }, + { + "name": "qsfp19" + }, + { + "name": "qsfp20" + }, + { + "name": "qsfp21" + }, + { + "name": "qsfp22" + }, + { + "name": "qsfp23" + }, + { + "name": "qsfp24" + }, + { + "name": "qsfp25" + }, + { + "name": "qsfp26" + }, + { + "name": "qsfp27" + }, + { + "name": "qsfp28" + }, + { + "name": "qsfp29" + }, + { + "name": "qsfp30" + }, + { + "name": "qsfp31" + }, + { + "name": "qsfp32" + }, + { + "name": "qsfp33" + }, + { + "name": "qsfp34" + }, + { + "name": "qsfp35" + }, + { + "name": "qsfp36" + } + ] + }, + "interfaces": {} +} \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32s/platform_reboot b/device/arista/x86_64-arista_7050_qx32s/platform_reboot new file mode 120000 index 000000000000..7f94a49e38b0 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/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_7050_qx32s/plugins/eeprom.py b/device/arista/x86_64-arista_7050_qx32s/plugins/eeprom.py new file mode 120000 index 000000000000..35cfaff3de4e --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/plugins/eeprom.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/eeprom.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32s/plugins/led_control.py b/device/arista/x86_64-arista_7050_qx32s/plugins/led_control.py new file mode 120000 index 000000000000..8d733780117e --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/plugins/led_control.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/led_control.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32s/plugins/psuutil.py b/device/arista/x86_64-arista_7050_qx32s/plugins/psuutil.py new file mode 120000 index 000000000000..2b0024ade969 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/plugins/psuutil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/psuutil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32s/plugins/sfputil.py b/device/arista/x86_64-arista_7050_qx32s/plugins/sfputil.py new file mode 120000 index 000000000000..c333e23763d7 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/plugins/sfputil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/sfputil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32s/pmon_daemon_control.json b/device/arista/x86_64-arista_7050_qx32s/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32s/sensors.conf b/device/arista/x86_64-arista_7050_qx32s/sensors.conf new file mode 100644 index 000000000000..6030de90eea5 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/sensors.conf @@ -0,0 +1,40 @@ +# libsensors configuration file for DCS-7050QX-32S +# ------------------------------------------------ +# + +bus "i2c-2" "SCD 0000:02:00.0 SMBus master 0 bus 0" +bus "i2c-3" "SCD 0000:02:00.0 SMBus master 0 bus 1" +bus "i2c-5" "SCD 0000:02:00.0 SMBus master 0 bus 3" +bus "i2c-6" "SCD 0000:02:00.0 SMBus master 0 bus 4" +bus "i2c-7" "SCD 0000:02:00.0 SMBus master 0 bus 5" + +chip "k10temp-pci-00c3" + label temp1 "Cpu temp sensor" + +chip "max6658-i2c-2-4c" + label temp1 "Board temp sensor" + set temp1_max 55 + set temp1_crit 70 + + label temp2 "Front panel temp sensor" + set temp2_max 65 + set temp2_crit 75 + +chip "max6658-i2c-3-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 80 + +chip "pmbus-i2c-6-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-5-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_7050_qx32s/system_health_monitoring_config.json b/device/arista/x86_64-arista_7050_qx32s/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32s/thermal_policy.json b/device/arista/x86_64-arista_7050_qx32s/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file 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..4b96b8cf87c9 --- /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 speed +Ethernet0 1,2,3,4 Ethernet1/1 1 100000 +Ethernet4 5,6,7,8 Ethernet2/1 2 100000 +Ethernet8 9,10,11,12 Ethernet3/1 3 100000 +Ethernet12 13,14,15,16 Ethernet4/1 4 100000 +Ethernet16 21,22,23,24 Ethernet5/1 5 100000 +Ethernet20 17,18,19,20 Ethernet6/1 6 100000 +Ethernet24 25,26,27,28 Ethernet7/1 7 100000 +Ethernet28 29,30,31,32 Ethernet8/1 8 100000 +Ethernet32 37,38,39,40 Ethernet9/1 9 100000 +Ethernet36 33,34,35,36 Ethernet10/1 10 100000 +Ethernet40 41,42,43,44 Ethernet11/1 11 100000 +Ethernet44 45,46,47,48 Ethernet12/1 12 100000 +Ethernet48 53,54,55,56 Ethernet13/1 13 100000 +Ethernet52 49,50,51,52 Ethernet14/1 14 100000 +Ethernet56 57,58,59,60 Ethernet15/1 15 100000 +Ethernet60 61,62,63,64 Ethernet16/1 16 100000 +Ethernet64 69,70,71,72 Ethernet17/1 17 100000 +Ethernet68 65,66,67,68 Ethernet18/1 18 100000 +Ethernet72 73,74,75,76 Ethernet19/1 19 100000 +Ethernet76 77,78,79,80 Ethernet20/1 20 100000 +Ethernet80 85,86,87,88 Ethernet21/1 21 100000 +Ethernet84 81,82,83,84 Ethernet22/1 22 100000 +Ethernet88 89,90,91,92 Ethernet23/1 23 100000 +Ethernet92 93,94,95,96 Ethernet24/1 24 100000 +Ethernet96 101,102,103,104 Ethernet25/1 25 100000 +Ethernet100 97,98,99,100 Ethernet26/1 26 100000 +Ethernet104 105,106,107,108 Ethernet27/1 27 100000 +Ethernet108 109,110,111,112 Ethernet28/1 28 100000 +Ethernet112 117,118,119,120 Ethernet29/1 29 100000 +Ethernet116 113,114,115,116 Ethernet30/1 30 100000 +Ethernet120 121,122,123,124 Ethernet31/1 31 100000 +Ethernet124 125,126,127,128 Ethernet32/1 32 100000 +Ethernet128 129 Ethernet33 33 10000 +Ethernet132 128 Ethernet34 34 10000 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..7d96f190de73 --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-a7050cx3-32s-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 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..c3b350204875 --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/td3-a7050cx3-32s-32x100G.config.bcm @@ -0,0 +1,512 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +host_as_route_disable=1 +use_all_splithorizon_groups=1 +riot_enable=1 +sai_tunnel_support=1 +riot_overlay_l3_intf_mem_size=4096 +riot_overlay_l3_egress_mem_size=32768 +l3_ecmp_levels=3 +riot_overlay_ecmp_resilient_hash_size=16384 +flow_init_mode=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +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 +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/Arista-7050CX3-32S-D48C8/port_config.ini b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/port_config.ini new file mode 100644 index 000000000000..25670f87d9cc --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 1,2 Ethernet1/1 1 50000 +Ethernet2 3,4 Ethernet1/3 1 50000 +Ethernet4 5,6 Ethernet2/1 2 50000 +Ethernet6 7,8 Ethernet2/3 2 50000 +Ethernet8 9,10 Ethernet3/1 3 50000 +Ethernet10 11,12 Ethernet3/3 3 50000 +Ethernet12 13,14 Ethernet4/1 4 50000 +Ethernet14 15,16 Ethernet4/3 4 50000 +Ethernet16 21,22 Ethernet5/1 5 50000 +Ethernet18 23,24 Ethernet5/3 5 50000 +Ethernet20 17,18 Ethernet6/1 6 50000 +Ethernet22 19,20 Ethernet6/3 6 50000 +Ethernet24 25,26,27,28 Ethernet7/1 7 100000 +Ethernet28 29,30,31,32 Ethernet8/1 8 100000 +Ethernet32 37,38,39,40 Ethernet9/1 9 100000 +Ethernet36 33,34,35,36 Ethernet10/1 10 100000 +Ethernet40 41,42 Ethernet11/1 11 50000 +Ethernet42 43,44 Ethernet11/3 11 50000 +Ethernet44 45,46 Ethernet12/1 12 50000 +Ethernet46 47,48 Ethernet12/3 12 50000 +Ethernet48 53,54 Ethernet13/1 13 50000 +Ethernet50 55,56 Ethernet13/3 13 50000 +Ethernet52 49,50 Ethernet14/1 14 50000 +Ethernet54 51,52 Ethernet14/3 14 50000 +Ethernet56 57,58 Ethernet15/1 15 50000 +Ethernet58 59,60 Ethernet15/3 15 50000 +Ethernet60 61,62 Ethernet16/1 16 50000 +Ethernet62 63,64 Ethernet16/3 16 50000 +Ethernet64 69,70 Ethernet17/1 17 50000 +Ethernet66 71,72 Ethernet17/3 17 50000 +Ethernet68 65,66 Ethernet18/1 18 50000 +Ethernet70 67,68 Ethernet18/3 18 50000 +Ethernet72 73,74 Ethernet19/1 19 50000 +Ethernet74 75,76 Ethernet19/3 19 50000 +Ethernet76 77,78 Ethernet20/1 20 50000 +Ethernet78 79,80 Ethernet20/3 20 50000 +Ethernet80 85,86 Ethernet21/1 21 50000 +Ethernet82 87,88 Ethernet21/3 21 50000 +Ethernet84 81,82 Ethernet22/1 22 50000 +Ethernet86 83,84 Ethernet22/3 22 50000 +Ethernet88 89,90,91,92 Ethernet23/1 23 100000 +Ethernet92 93,94,95,96 Ethernet24/1 24 100000 +Ethernet96 101,102,103,104 Ethernet25/1 25 100000 +Ethernet100 97,98,99,100 Ethernet26/1 26 100000 +Ethernet104 105,106 Ethernet27/1 27 50000 +Ethernet106 107,108 Ethernet27/3 27 50000 +Ethernet108 109,110 Ethernet28/1 28 50000 +Ethernet110 111,112 Ethernet28/3 28 50000 +Ethernet112 117,118 Ethernet29/1 29 50000 +Ethernet114 119,120 Ethernet29/3 29 50000 +Ethernet116 113,114 Ethernet30/1 30 50000 +Ethernet118 115,116 Ethernet30/3 30 50000 +Ethernet120 121,122 Ethernet31/1 31 50000 +Ethernet122 123,124 Ethernet31/3 31 50000 +Ethernet124 125,126 Ethernet32/1 32 50000 +Ethernet126 127,128 Ethernet32/3 32 50000 diff --git a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/sai.profile b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/sai.profile new file mode 100644 index 000000000000..1865041f8d9f --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-a7050cx3-32s-48x50G+8x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/td3-a7050cx3-32s-48x50G+8x100G.config.bcm b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/td3-a7050cx3-32s-48x50G+8x100G.config.bcm new file mode 100644 index 000000000000..1b5b7e338708 --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/td3-a7050cx3-32s-48x50G+8x100G.config.bcm @@ -0,0 +1,555 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +host_as_route_disable=1 +use_all_splithorizon_groups=1 +riot_enable=1 +sai_tunnel_support=1 +riot_overlay_l3_intf_mem_size=4096 +riot_overlay_l3_egress_mem_size=32768 +l3_ecmp_levels=3 +riot_overlay_ecmp_resilient_hash_size=16384 +flow_init_mode=1 +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=0x7ffffffffffffffffffffffffffffffffe +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 +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{5.0}=0x3120 +phy_chain_rx_lane_map_physical{9.0}=0x3120 +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{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{93.0}=0x0213 +phy_chain_rx_lane_map_physical{97.0}=0x2130 +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_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x1 +phy_chain_rx_polarity_flip_physical{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +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{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{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{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{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{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{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{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{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_rx_polarity_flip_physical{100.0}=0x1 +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{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{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{131.0}=0x0 +phy_chain_tx_lane_map_physical{1.0}=0x3021 +phy_chain_tx_lane_map_physical{5.0}=0x1203 +phy_chain_tx_lane_map_physical{9.0}=0x0213 +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{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{93.0}=0x2130 +phy_chain_tx_lane_map_physical{97.0}=0x1302 +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_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +phy_chain_tx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x1 +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{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{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{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{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{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{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{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{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 +phy_chain_tx_polarity_flip_physical{100.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{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{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{131.0}=0x0 +portmap_1=1:50:2 +portmap_3=3:50:2 +portmap_5=5:50:2 +portmap_7=7:50:2 +portmap_9=9:50:2 +portmap_11=11:50:2 +portmap_13=13:50:2 +portmap_15=15:50:2 +portmap_17=17:50:2 +portmap_19=19:50:2 +portmap_21=21:50:2 +portmap_23=23:50:2 +portmap_25=25:100 +portmap_29=29:100 +portmap_33=33:100 +portmap_37=37:100 +portmap_41=41:50:2 +portmap_43=43:50:2 +portmap_45=45:50:2 +portmap_47=47:50:2 +portmap_49=49:50:2 +portmap_51=51:50:2 +portmap_53=53:50:2 +portmap_55=55:50:2 +portmap_57=57:50:2 +portmap_59=59:50:2 +portmap_61=61:50:2 +portmap_63=63:50:2 +# skip 2 +portmap_67=65:50:2 +portmap_69=67:50:2 +portmap_71=69:50:2 +portmap_73=71:50:2 +portmap_75=73:50:2 +portmap_77=75:50:2 +portmap_79=77:50:2 +portmap_81=79:50:2 +portmap_83=81:50:2 +portmap_85=83:50:2 +portmap_87=85:50:2 +portmap_89=87:50:2 +portmap_91=89:100 +portmap_95=93:100 +portmap_99=97:100 +portmap_103=101:100 +portmap_107=105:50:2 +portmap_109=107:50:2 +portmap_111=109:50:2 +portmap_113=111:50:2 +portmap_115=113:50:2 +portmap_117=115:50:2 +portmap_119=117:50:2 +portmap_121=119:50:2 +portmap_123=121:50:2 +portmap_125=123:50:2 +portmap_127=125:50:2 +portmap_129=127:50:2 +serdes_core_rx_polarity_flip_physical{1}=0x8 +serdes_core_rx_polarity_flip_physical{5}=0x2 +serdes_core_rx_polarity_flip_physical{9}=0xc +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{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{93}=0xc +serdes_core_rx_polarity_flip_physical{97}=0xb +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{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_tx_polarity_flip_physical{1}=0x3 +serdes_core_tx_polarity_flip_physical{5}=0xb +serdes_core_tx_polarity_flip_physical{9}=0x3 +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{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{93}=0xc +serdes_core_tx_polarity_flip_physical{97}=0xf +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{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_preemphasis_1=0x45808 +serdes_preemphasis_3=0x45808 +serdes_preemphasis_5=0x45808 +serdes_preemphasis_7=0x45808 +serdes_preemphasis_9=0x45808 +serdes_preemphasis_11=0x45808 +serdes_preemphasis_13=0x45808 +serdes_preemphasis_15=0x45808 +serdes_preemphasis_17=0x45808 +serdes_preemphasis_19=0x45808 +serdes_preemphasis_21=0x45808 +serdes_preemphasis_23=0x45808 +serdes_preemphasis_25=0xd3e05 +serdes_preemphasis_29=0xd3e05 +serdes_preemphasis_33=0xb3403 +serdes_preemphasis_37=0x93603 +serdes_preemphasis_41=0x580c +serdes_preemphasis_43=0x580c +serdes_preemphasis_45=0x580c +serdes_preemphasis_47=0x580c +serdes_preemphasis_49=0x580c +serdes_preemphasis_51=0x580c +serdes_preemphasis_53=0x580c +serdes_preemphasis_55=0x580c +serdes_preemphasis_57=0x580c +serdes_preemphasis_59=0x580c +serdes_preemphasis_61=0x580c +serdes_preemphasis_63=0x580c +serdes_preemphasis_67=0x580c +serdes_preemphasis_69=0x580c +serdes_preemphasis_71=0x580c +serdes_preemphasis_73=0x580c +serdes_preemphasis_75=0x580c +serdes_preemphasis_77=0x580c +serdes_preemphasis_79=0x580c +serdes_preemphasis_81=0x580c +serdes_preemphasis_83=0x580c +serdes_preemphasis_85=0x580c +serdes_preemphasis_87=0x580c +serdes_preemphasis_89=0x580c +serdes_preemphasis_91=0x93603 +serdes_preemphasis_95=0xd3e05 +serdes_preemphasis_99=0xb3403 +serdes_preemphasis_103=0xd3e05 +serdes_preemphasis_107=0x85804 +serdes_preemphasis_109=0x85804 +serdes_preemphasis_111=0x85804 +serdes_preemphasis_113=0x85804 +serdes_preemphasis_115=0x85804 +serdes_preemphasis_117=0x85804 +serdes_preemphasis_119=0x85804 +serdes_preemphasis_121=0x85804 +serdes_preemphasis_123=0x85804 +serdes_preemphasis_125=0x85804 +serdes_preemphasis_127=0x85804 +serdes_preemphasis_129=0x85804 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/pcie.yaml b/device/arista/x86_64-arista_7050cx3_32s/pcie.yaml new file mode 100644 index 000000000000..f56c87185f3c --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/pcie.yaml @@ -0,0 +1,133 @@ +- bus: '00' + dev: '00' + fn: '0' + id: '1566' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Root Complex' +- bus: '00' + dev: '00' + fn: '2' + id: '1567' + name: 'IOMMU: Advanced Micro Devices, Inc. [AMD] Mullins IOMMU' +- bus: '00' + dev: '02' + fn: '0' + id: 156b + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Host Bridge' +- bus: '00' + dev: '02' + fn: '1' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '2' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '3' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '4' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '5' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: 08 + fn: '0' + id: '1537' + name: 'Encryption controller: Advanced Micro Devices, Inc. [AMD] Kabini/Mullins + PSP-Platform Security Processor' +- bus: '00' + dev: '11' + fn: '0' + id: '7801' + name: 'SATA controller: Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI + mode] (rev 40)' +- bus: '00' + dev: '12' + fn: '0' + id: '7808' + name: 'USB controller: Advanced Micro Devices, Inc. [AMD] FCH USB EHCI Controller + (rev 39)' +- bus: '00' + dev: '14' + fn: '0' + id: 780b + name: 'SMBus: Advanced Micro Devices, Inc. [AMD] FCH SMBus Controller (rev 42)' +- bus: '00' + dev: '14' + fn: '3' + id: 780e + name: 'ISA bridge: Advanced Micro Devices, Inc. [AMD] FCH LPC Bridge (rev 11)' +- bus: '00' + dev: '14' + fn: '7' + id: '7813' + name: 'SD Host controller: Advanced Micro Devices, Inc. [AMD] FCH SD Flash Controller + (rev 01)' +- bus: '00' + dev: '18' + fn: '0' + id: '1580' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 0' +- bus: '00' + dev: '18' + fn: '1' + id: '1581' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 1' +- bus: '00' + dev: '18' + fn: '2' + id: '1582' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 2' +- bus: '00' + dev: '18' + fn: '3' + id: '1583' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 3' +- bus: '00' + dev: '18' + fn: '4' + id: '1584' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 4' +- bus: '00' + dev: '18' + fn: '5' + id: '1585' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 5' +- bus: '01' + dev: '00' + fn: '0' + id: b870 + name: 'Ethernet controller: Broadcom Limited Device b870 (rev 01)' +- bus: '02' + dev: '00' + fn: '0' + id: '0001' + name: 'System peripheral: Arastra Inc. Device 0001 (rev 01)' +- bus: '04' + dev: '00' + fn: '0' + id: '1682' + name: 'Ethernet controller: Broadcom Limited NetXtreme BCM57762 Gigabit Ethernet + PCIe (rev 20)' diff --git a/device/arista/x86_64-arista_7050cx3_32s/platform.json b/device/arista/x86_64-arista_7050cx3_32s/platform.json new file mode 100644 index 000000000000..632747ad2333 --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/platform.json @@ -0,0 +1,191 @@ +{ + "chassis": { + "name": "DCS-7050CX3-32S", + "components": [], + "fans": [], + "fan_drawers": [ + { + "name": "slot1", + "fans": [ + { + "name": "fan1" + } + ] + }, + { + "name": "slot2", + "fans": [ + { + "name": "fan2" + } + ] + }, + { + "name": "slot3", + "fans": [ + { + "name": "fan3" + } + ] + }, + { + "name": "slot4", + "fans": [ + { + "name": "fan4" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Cpu temp sensor" + }, + { + "name": "Cpu board temp sensor" + }, + { + "name": "Back-panel temp sensor" + }, + { + "name": "Board temp sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Power supply 1 hotspot sensor" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 exhaust temp sensor" + }, + { + "name": "Power supply 2 hotspot sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 exhaust temp sensor" + } + ], + "sfps": [ + { + "name": "qsfp1" + }, + { + "name": "qsfp2" + }, + { + "name": "qsfp3" + }, + { + "name": "qsfp4" + }, + { + "name": "qsfp5" + }, + { + "name": "qsfp6" + }, + { + "name": "qsfp7" + }, + { + "name": "qsfp8" + }, + { + "name": "qsfp9" + }, + { + "name": "qsfp10" + }, + { + "name": "qsfp11" + }, + { + "name": "qsfp12" + }, + { + "name": "qsfp13" + }, + { + "name": "qsfp14" + }, + { + "name": "qsfp15" + }, + { + "name": "qsfp16" + }, + { + "name": "qsfp17" + }, + { + "name": "qsfp18" + }, + { + "name": "qsfp19" + }, + { + "name": "qsfp20" + }, + { + "name": "qsfp21" + }, + { + "name": "qsfp22" + }, + { + "name": "qsfp23" + }, + { + "name": "qsfp24" + }, + { + "name": "qsfp25" + }, + { + "name": "qsfp26" + }, + { + "name": "qsfp27" + }, + { + "name": "qsfp28" + }, + { + "name": "qsfp29" + }, + { + "name": "qsfp30" + }, + { + "name": "qsfp31" + }, + { + "name": "qsfp32" + }, + { + "name": "sfp33" + }, + { + "name": "sfp34" + } + ] + }, + "interfaces": {} +} \ No newline at end of file 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/eeprom.py b/device/arista/x86_64-arista_7050cx3_32s/plugins/eeprom.py new file mode 120000 index 000000000000..35cfaff3de4e --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/plugins/eeprom.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/eeprom.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050cx3_32s/plugins/led_control.py b/device/arista/x86_64-arista_7050cx3_32s/plugins/led_control.py new file mode 120000 index 000000000000..8d733780117e --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/plugins/led_control.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/led_control.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050cx3_32s/plugins/psuutil.py b/device/arista/x86_64-arista_7050cx3_32s/plugins/psuutil.py new file mode 120000 index 000000000000..2b0024ade969 --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/plugins/psuutil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/psuutil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050cx3_32s/plugins/sfputil.py b/device/arista/x86_64-arista_7050cx3_32s/plugins/sfputil.py new file mode 120000 index 000000000000..c333e23763d7 --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/plugins/sfputil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/sfputil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050cx3_32s/pmon_daemon_control.json b/device/arista/x86_64-arista_7050cx3_32s/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ 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_7050cx3_32s/system_health_monitoring_config.json b/device/arista/x86_64-arista_7050cx3_32s/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050cx3_32s/thermal_policy.json b/device/arista/x86_64-arista_7050cx3_32s/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050sx3_48c8 b/device/arista/x86_64-arista_7050sx3_48c8 new file mode 120000 index 000000000000..0334c5411d31 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48c8 @@ -0,0 +1 @@ +x86_64-arista_7050sx3_48yc8 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/buffers.json.j2 b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..b6e6a948928d --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/buffers_defaults_t0.j2 @@ -0,0 +1,50 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,28) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(28,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": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/pg_profile_lookup.ini b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/pg_profile_lookup.ini new file mode 100644 index 000000000000..0b5d680edda7 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 0 2288 + 25000 5m 1248 2288 53248 0 2288 + 40000 5m 1248 2288 66560 0 2288 + 50000 5m 1248 2288 79872 0 2288 + 100000 5m 1248 2288 165568 0 2288 + 10000 40m 1248 2288 37024 0 2288 + 25000 40m 1248 2288 56160 0 2288 + 40000 40m 1248 2288 71552 0 2288 + 50000 40m 1248 2288 85696 0 2288 + 100000 40m 1248 2288 177632 0 2288 + 10000 300m 1248 2288 46176 0 2288 + 25000 300m 1248 2288 79040 0 2288 + 40000 300m 1248 2288 108160 0 2288 + 50000 300m 1248 2288 141856 0 2288 + 100000 300m 1248 2288 268736 0 2288 diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/port_config.ini b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/port_config.ini new file mode 100644 index 000000000000..bccaa602f203 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 1,2 Ethernet1/1 1 25000 +Ethernet2 3,4 Ethernet1/3 1 25000 +Ethernet4 5,6 Ethernet2/1 2 25000 +Ethernet6 7,8 Ethernet2/3 2 25000 +Ethernet8 9,10 Ethernet3/1 3 25000 +Ethernet10 11,12 Ethernet3/3 3 25000 +Ethernet12 13,14 Ethernet4/1 4 25000 +Ethernet14 15,16 Ethernet4/3 4 25000 +Ethernet16 21,22 Ethernet5/1 5 25000 +Ethernet18 23,24 Ethernet5/3 5 25000 +Ethernet20 17,18 Ethernet6/1 6 25000 +Ethernet22 19,20 Ethernet6/3 6 25000 +Ethernet24 25,26 Ethernet7/1 7 25000 +Ethernet26 27,28 Ethernet7/3 7 25000 +Ethernet28 29,30 Ethernet8/1 8 25000 +Ethernet30 31,32 Ethernet8/3 8 25000 +Ethernet32 37,38 Ethernet9/1 9 25000 +Ethernet34 39,40 Ethernet9/3 9 25000 +Ethernet36 33,34 Ethernet10/1 10 25000 +Ethernet38 35,46 Ethernet10/3 10 25000 +Ethernet40 41,42 Ethernet11/1 11 25000 +Ethernet42 43,44 Ethernet11/3 11 25000 +Ethernet44 45,46 Ethernet12/1 12 25000 +Ethernet46 47,48 Ethernet12/3 12 25000 +Ethernet48 53,54 Ethernet13/1 13 25000 +Ethernet50 55,56 Ethernet13/3 13 25000 +Ethernet52 49,50 Ethernet14/1 14 25000 +Ethernet54 51,52 Ethernet14/3 14 25000 +Ethernet56 57,58 Ethernet15/1 15 25000 +Ethernet58 59,60 Ethernet15/3 15 25000 +Ethernet60 61,62 Ethernet16/1 16 25000 +Ethernet62 63,64 Ethernet16/3 16 25000 +Ethernet64 69,70 Ethernet17/1 17 25000 +Ethernet66 71,72 Ethernet17/3 17 25000 +Ethernet68 65,66 Ethernet18/1 18 25000 +Ethernet70 67,68 Ethernet18/3 18 25000 +Ethernet72 73,74 Ethernet19/1 19 25000 +Ethernet74 75,76 Ethernet19/3 19 25000 +Ethernet76 77,78 Ethernet20/1 20 25000 +Ethernet78 79,80 Ethernet20/3 20 25000 +Ethernet80 85,86 Ethernet21/1 21 25000 +Ethernet82 87,88 Ethernet21/3 21 25000 +Ethernet84 81,82 Ethernet22/1 22 25000 +Ethernet86 83,84 Ethernet22/3 22 25000 +Ethernet88 89,90 Ethernet23/1 23 25000 +Ethernet88 91,92 Ethernet23/3 23 25000 +Ethernet92 93,94 Ethernet24/1 24 25000 +Ethernet92 95,96 Ethernet24/3 24 25000 +Ethernet96 101,102,103,104 Ethernet25/1 25 100000 +Ethernet100 97,98,99,100 Ethernet26/1 26 100000 +Ethernet104 105,106,107,108 Ethernet27/1 27 100000 +Ethernet108 109,110,111,112 Ethernet28/1 28 100000 +Ethernet112 117,118,119,120 Ethernet29/1 29 100000 +Ethernet116 113,114,115,116 Ethernet30/1 30 100000 +Ethernet120 121,122,123,124 Ethernet31/1 31 100000 +Ethernet124 125,126,127,128 Ethernet32/1 32 100000 diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/qos.json.j2 b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/qos.json.j2 new file mode 100644 index 000000000000..34002048afdb --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/qos.json.j2 @@ -0,0 +1,21 @@ +{%- macro generate_wred_profiles() %} + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "250000", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, +{%- endmacro %} + +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/sai.profile b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/sai.profile new file mode 100644 index 000000000000..7342226cd38c --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-a7050sx3_48yc8-48x25G+8x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/td3-a7050sx3_48yc8-48x25G+8x100G.config.bcm b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/td3-a7050sx3_48yc8-48x25G+8x100G.config.bcm new file mode 100644 index 000000000000..aa9b32d4a350 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/Arista-7050SX3-48YC8/td3-a7050sx3_48yc8-48x25G+8x100G.config.bcm @@ -0,0 +1,422 @@ +PHY_AN_ALLOW_PLL_CHANGE=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=8 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +fpem_mem_entries=0 +higig2_hdr_mode=1 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0 +l2xmsg_mode=1 +l2_mem_entries=163840 +l3_mem_entries=147456 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +multicast_l2_range=16383 +multicast_l3_range=0 +num_ipv6_lpm_128b_entries=0 +os=unix +oversubscribe_mode=1 +pbmp_xport_xe=0x1ffffffe1ffffffe +phy_an_c73_1=1 +phy_an_c73_2=1 +phy_an_c73_3=1 +phy_an_c73_4=1 +phy_an_c73_5=1 +phy_an_c73_6=1 +phy_an_c73_7=1 +phy_an_c73_8=1 +phy_an_c73_9=1 +phy_an_c73_10=1 +phy_an_c73_11=1 +phy_an_c73_12=1 +phy_an_c73_13=1 +phy_an_c73_14=1 +phy_an_c73_15=1 +phy_an_c73_16=1 +phy_an_c73_17=1 +phy_an_c73_18=1 +phy_an_c73_19=1 +phy_an_c73_20=1 +phy_an_c73_21=1 +phy_an_c73_22=1 +phy_an_c73_23=1 +phy_an_c73_24=1 +phy_an_c73_25=0 +phy_an_c73_26=0 +phy_an_c73_27=0 +phy_an_c73_28=0 +phy_an_c73_33=1 +phy_an_c73_34=1 +phy_an_c73_35=1 +phy_an_c73_36=1 +phy_an_c73_37=1 +phy_an_c73_38=1 +phy_an_c73_39=1 +phy_an_c73_40=1 +phy_an_c73_41=1 +phy_an_c73_42=1 +phy_an_c73_43=1 +phy_an_c73_44=1 +phy_an_c73_45=1 +phy_an_c73_46=1 +phy_an_c73_47=1 +phy_an_c73_48=1 +phy_an_c73_49=1 +phy_an_c73_50=1 +phy_an_c73_51=1 +phy_an_c73_52=1 +phy_an_c73_53=1 +phy_an_c73_54=1 +phy_an_c73_55=1 +phy_an_c73_56=1 +phy_an_c73_57=0 +phy_an_c73_58=0 +phy_an_c73_59=0 +phy_an_c73_60=0 +phy_chain_rx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{5.0}=0x0123 +phy_chain_rx_lane_map_physical{9.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_lane_map_physical{25.0}=0x0213 +phy_chain_rx_lane_map_physical{29.0}=0x2031 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x3120 +phy_chain_rx_lane_map_physical{41.0}=0x2031 +phy_chain_rx_lane_map_physical{45.0}=0x0213 +phy_chain_rx_lane_map_physical{49.0}=0x2031 +phy_chain_rx_lane_map_physical{53.0}=0x0213 +phy_chain_rx_lane_map_physical{57.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_rx_lane_map_physical{77.0}=0x3210 +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x1 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x1 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +phy_chain_rx_polarity_flip_physical{41.0}=0x1 +phy_chain_rx_polarity_flip_physical{42.0}=0x0 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x1 +phy_chain_rx_polarity_flip_physical{53.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x0 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x1 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x1 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{76.0}=0x1 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +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}=0x0 +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_tx_lane_map_physical{5.0}=0x0123 +phy_chain_tx_lane_map_physical{9.0}=0x0123 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_tx_lane_map_physical{25.0}=0x0123 +phy_chain_tx_lane_map_physical{29.0}=0x3210 +phy_chain_tx_lane_map_physical{33.0}=0x0123 +phy_chain_tx_lane_map_physical{37.0}=0x3201 +phy_chain_tx_lane_map_physical{41.0}=0x3201 +phy_chain_tx_lane_map_physical{45.0}=0x0123 +phy_chain_tx_lane_map_physical{49.0}=0x3201 +phy_chain_tx_lane_map_physical{53.0}=0x0132 +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{69.0}=0x3210 +phy_chain_tx_lane_map_physical{73.0}=0x3210 +phy_chain_tx_lane_map_physical{77.0}=0x3210 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +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{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +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}=0x0 +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{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +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}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x1 +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{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 +phy_chain_tx_polarity_flip_physical{65.0}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +portmap_1=1:25 +portmap_2=2:25 +portmap_3=3:25 +portmap_4=4:25 +portmap_5=5:25 +portmap_6=6:25 +portmap_7=7:25 +portmap_8=8:25 +portmap_9=9:25 +portmap_10=10:25 +portmap_11=11:25 +portmap_12=12:25 +portmap_13=13:25 +portmap_14=14:25 +portmap_15=15:25 +portmap_16=16:25 +portmap_17=17:25 +portmap_18=18:25 +portmap_19=19:25 +portmap_20=20:25 +portmap_21=21:25 +portmap_22=22:25 +portmap_23=23:25 +portmap_24=24:25 +portmap_25=25:100:4 +portmap_26=29:100:4 +portmap_27=33:100:4 +portmap_28=37:100:4 +portmap_33=57:25 +portmap_34=58:25 +portmap_35=59:25 +portmap_36=60:25 +portmap_37=61:25 +portmap_38=62:25 +portmap_39=63:25 +portmap_40=64:25 +portmap_41=65:25 +portmap_42=66:25 +portmap_43=67:25 +portmap_44=68:25 +portmap_45=69:25 +portmap_46=70:25 +portmap_47=71:25 +portmap_48=72:25 +portmap_49=73:25 +portmap_50=74:25 +portmap_51=75:25 +portmap_52=76:25 +portmap_53=77:25 +portmap_54=78:25 +portmap_55=79:25 +portmap_56=80:25 +portmap_57=41:100:4 +portmap_58=45:100:4 +portmap_59=49:100:4 +portmap_60=53:100:4 +port_flex_enable=1 +port_init_autoneg_1=0 +port_init_autoneg_5=0 +port_init_autoneg_9=0 +port_init_autoneg_13=0 +port_init_autoneg_17=0 +port_init_autoneg_21=0 +port_init_autoneg_25=0 +port_init_autoneg_26=0 +port_init_autoneg_27=0 +port_init_autoneg_28=0 +port_init_autoneg_33=0 +port_init_autoneg_37=0 +port_init_autoneg_41=0 +port_init_autoneg_45=0 +port_init_autoneg_49=0 +port_init_autoneg_53=0 +port_init_autoneg_57=0 +port_init_autoneg_58=0 +port_init_autoneg_59=0 +port_init_autoneg_60=0 +port_phy_addr_1=0xff +port_phy_addr_5=0xff +port_phy_addr_9=0xff +port_phy_addr_13=0xff +port_phy_addr_17=0xff +port_phy_addr_21=0xff +port_phy_addr_25=0xff +port_phy_addr_26=0xff +port_phy_addr_27=0xff +port_phy_addr_28=0xff +port_phy_addr_33=0xff +port_phy_addr_37=0xff +port_phy_addr_41=0xff +port_phy_addr_45=0xff +port_phy_addr_49=0xff +port_phy_addr_53=0xff +port_phy_addr_57=0xff +port_phy_addr_58=0xff +port_phy_addr_59=0xff +port_phy_addr_60=0xff +robust_hash_disable_egress_vlan=1 +robust_hash_disable_mpls=1 +robust_hash_disable_vlan=1 +serdes_core_rx_polarity_flip_physical{1}=0xa +serdes_core_rx_polarity_flip_physical{5}=0x5 +serdes_core_rx_polarity_flip_physical{9}=0x5 +serdes_core_rx_polarity_flip_physical{13}=0x5 +serdes_core_rx_polarity_flip_physical{17}=0xa +serdes_core_rx_polarity_flip_physical{21}=0x5 +serdes_core_rx_polarity_flip_physical{25}=0x0 +serdes_core_rx_polarity_flip_physical{29}=0xc +serdes_core_rx_polarity_flip_physical{33}=0x3 +serdes_core_rx_polarity_flip_physical{37}=0x1 +serdes_core_rx_polarity_flip_physical{41}=0x9 +serdes_core_rx_polarity_flip_physical{45}=0x9 +serdes_core_rx_polarity_flip_physical{49}=0x8 +serdes_core_rx_polarity_flip_physical{53}=0x9 +serdes_core_rx_polarity_flip_physical{57}=0xa +serdes_core_rx_polarity_flip_physical{61}=0x5 +serdes_core_rx_polarity_flip_physical{65}=0xa +serdes_core_rx_polarity_flip_physical{69}=0xa +serdes_core_rx_polarity_flip_physical{73}=0xa +serdes_core_rx_polarity_flip_physical{77}=0x5 +serdes_core_tx_polarity_flip_physical{1}=0x0 +serdes_core_tx_polarity_flip_physical{5}=0x0 +serdes_core_tx_polarity_flip_physical{9}=0x0 +serdes_core_tx_polarity_flip_physical{13}=0x0 +serdes_core_tx_polarity_flip_physical{17}=0x0 +serdes_core_tx_polarity_flip_physical{21}=0x0 +serdes_core_tx_polarity_flip_physical{25}=0x0 +serdes_core_tx_polarity_flip_physical{29}=0x0 +serdes_core_tx_polarity_flip_physical{33}=0x0 +serdes_core_tx_polarity_flip_physical{37}=0x8 +serdes_core_tx_polarity_flip_physical{41}=0x0 +serdes_core_tx_polarity_flip_physical{45}=0x8 +serdes_core_tx_polarity_flip_physical{49}=0x1 +serdes_core_tx_polarity_flip_physical{53}=0x0 +serdes_core_tx_polarity_flip_physical{57}=0xf +serdes_core_tx_polarity_flip_physical{61}=0x7 +serdes_core_tx_polarity_flip_physical{65}=0x0 +serdes_core_tx_polarity_flip_physical{69}=0x0 +serdes_core_tx_polarity_flip_physical{73}=0x0 +serdes_core_tx_polarity_flip_physical{77}=0x0 +tdma_timeout_usec=15000000 +tslam_timeout_usec=15000000 diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/default_sku b/device/arista/x86_64-arista_7050sx3_48yc8/default_sku new file mode 100644 index 000000000000..4332a11e9f75 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/default_sku @@ -0,0 +1 @@ +Arista-7050SX3-48YC8 t1 diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/platform_reboot b/device/arista/x86_64-arista_7050sx3_48yc8/platform_reboot new file mode 120000 index 000000000000..7f94a49e38b0 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/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_7050sx3_48yc8/plugins/eeprom.py b/device/arista/x86_64-arista_7050sx3_48yc8/plugins/eeprom.py new file mode 120000 index 000000000000..35cfaff3de4e --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/plugins/eeprom.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/eeprom.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/plugins/led_control.py b/device/arista/x86_64-arista_7050sx3_48yc8/plugins/led_control.py new file mode 120000 index 000000000000..8d733780117e --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/plugins/led_control.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/led_control.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/plugins/psuutil.py b/device/arista/x86_64-arista_7050sx3_48yc8/plugins/psuutil.py new file mode 120000 index 000000000000..2b0024ade969 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/plugins/psuutil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/psuutil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/plugins/sfputil.py b/device/arista/x86_64-arista_7050sx3_48yc8/plugins/sfputil.py new file mode 120000 index 000000000000..c333e23763d7 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/plugins/sfputil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/sfputil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/pmon_daemon_control.json b/device/arista/x86_64-arista_7050sx3_48yc8/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/sensors.conf b/device/arista/x86_64-arista_7050sx3_48yc8/sensors.conf new file mode 100644 index 000000000000..c6c60f294675 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/sensors.conf @@ -0,0 +1,50 @@ +# libsensors configuration file for DCS-7050SX3-48YC8 +# --------------------------------------------------- +# + +bus "i2c-8" "SCD 0000:02:00.0 SMBus master 0 bus 0" +bus "i2c-9" "SCD 0000:02:00.0 SMBus master 0 bus 1" +bus "i2c-10" "SCD 0000:02:00.0 SMBus master 0 bus 2" +bus "i2c-72" "SCD 0000:00:09.0 SMBus master 0 bus 2" + +chip "k10temp-pci-00c3" + label temp1 "Cpu temp sensor" + +chip "pmbus-i2c-8-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-9-58" + label temp1 "Power supply 2 hotspot sensor" + label temp2 "Power supply 2 inlet temp sensor" + label temp3 "Power supply 2 sensor" + +chip "max6658-i2c-72-4c" + label temp1 "Board temp sensor" + set temp1_max 75 + set temp1_crit 85 + + label temp2 "Front panel temp sensor" + set temp2_max 75 + set temp2_crit 85 + +chip "tmp464-i2c-10-48" + label temp1 "Switch Card temp sensor" + set temp1_max 100 + set temp1_crit 110 + + label temp2 "Front-panel temp sensor" + set temp2_max 65 + set temp2_crit 75 + + label temp3 "Front PCB temp sensor" + set temp3_max 75 + set temp3_crit 80 + + ignore temp4 + ignore temp5 + ignore temp6 + ignore temp7 + ignore temp8 + ignore temp9 diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/system_health_monitoring_config.json b/device/arista/x86_64-arista_7050sx3_48yc8/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050sx3_48yc8/thermal_policy.json b/device/arista/x86_64-arista_7050sx3_48yc8/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7050sx3_48yc8/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32-T1 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32-T1 new file mode 120000 index 000000000000..42c11d5f05fb --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32-T1 @@ -0,0 +1 @@ +Arista-7060CX-32S-C32 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/buffers.json.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..0869e63968ac --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/buffers_defaults_t0.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,128,4) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/buffers_defaults_t1.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..80e96bdceca7 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/buffers_defaults_t1.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,128,4) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/pg_profile_lookup.ini b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/pg_profile_lookup.ini new file mode 100644 index 000000000000..673df369a9bb --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 0 2288 + 25000 5m 1248 2288 53248 0 2288 + 40000 5m 1248 2288 66560 0 2288 + 50000 5m 1248 2288 90272 0 2288 + 100000 5m 1248 2288 165568 0 2288 + 10000 40m 1248 2288 37024 0 2288 + 25000 40m 1248 2288 53248 0 2288 + 40000 40m 1248 2288 71552 0 2288 + 50000 40m 1248 2288 96096 0 2288 + 100000 40m 1248 2288 177632 0 2288 + 10000 300m 1248 2288 46176 0 2288 + 25000 300m 1248 2288 79040 0 2288 + 40000 300m 1248 2288 108160 0 2288 + 50000 300m 1248 2288 141856 0 2288 + 100000 300m 1248 2288 268736 0 2288 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/port_config.ini b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/port_config.ini new file mode 100644 index 000000000000..bfe4a721141d --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 33,34,35,36 Ethernet1/1 1 +Ethernet4 37,38,39,40 Ethernet2/1 2 +Ethernet8 41,42,43,44 Ethernet3/1 3 +Ethernet12 45,46,47,48 Ethernet4/1 4 +Ethernet16 49,50,51,52 Ethernet5/1 5 +Ethernet20 53,54,55,56 Ethernet6/1 6 +Ethernet24 57,58,59,60 Ethernet7/1 7 +Ethernet28 61,62,63,64 Ethernet8/1 8 +Ethernet32 65,66,67,68 Ethernet9/1 9 +Ethernet36 69,70,71,72 Ethernet10/1 10 +Ethernet40 73,74,75,76 Ethernet11/1 11 +Ethernet44 77,78,79,80 Ethernet12/1 12 +Ethernet48 81,82,83,84 Ethernet13/1 13 +Ethernet52 85,86,87,88 Ethernet14/1 14 +Ethernet56 89,90,91,92 Ethernet15/1 15 +Ethernet60 93,94,95,96 Ethernet16/1 16 +Ethernet64 97,98,99,100 Ethernet17/1 17 +Ethernet68 101,102,103,104 Ethernet18/1 18 +Ethernet72 105,106,107,108 Ethernet19/1 19 +Ethernet76 109,110,111,112 Ethernet20/1 20 +Ethernet80 113,114,115,116 Ethernet21/1 21 +Ethernet84 117,118,119,120 Ethernet22/1 22 +Ethernet88 121,122,123,124 Ethernet23/1 23 +Ethernet92 125,126,127,128 Ethernet24/1 24 +Ethernet96 1,2,3,4 Ethernet25/1 25 +Ethernet100 5,6,7,8 Ethernet26/1 26 +Ethernet104 9,10,11,12 Ethernet27/1 27 +Ethernet108 13,14,15,16 Ethernet28/1 28 +Ethernet112 17,18,19,20 Ethernet29/1 29 +Ethernet116 21,22,23,24 Ethernet30/1 30 +Ethernet120 25,26,27,28 Ethernet31/1 31 +Ethernet124 29,30,31,32 Ethernet32/1 32 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/qos.json.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/qos.json.j2 new file mode 100644 index 000000000000..34002048afdb --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/qos.json.j2 @@ -0,0 +1,21 @@ +{%- macro generate_wred_profiles() %} + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "250000", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, +{%- endmacro %} + +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/sai.profile b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/sai.profile new file mode 100644 index 000000000000..66f88f894c30 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-a7060-cx32s-32x100G-t1.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/th-a7060-cx32s-32x100G-t1.config.bcm b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/th-a7060-cx32s-32x100G-t1.config.bcm new file mode 100644 index 000000000000..95a947003fbc --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-C32/th-a7060-cx32s-32x100G-t1.config.bcm @@ -0,0 +1,446 @@ +# Arista 7060CX-32S + +phy_an_allow_pll_change=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +higig2_hdr_mode=1 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +l2xmsg_mode=1 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +os=unix +oversubscribe_mode=1 +ptp_bs_fref.0=25000000 +ptp_ts_pll_fref.0=25000000 +robust_hash_disable_egress_vlan.0=1 +robust_hash_disable_mpls.0=1 +robust_hash_disable_vlan.0=1 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 +pbmp_xport_xe.0=0x7ffffffffffffffffffffffffffffffffe +phy_an_allow_pll_change_hg.0=0 +phy_an_c73_1.0=1 +phy_an_c73_2.0=1 +phy_an_c73_3.0=1 +phy_an_c73_4.0=1 +phy_an_c73_5.0=1 +phy_an_c73_6.0=1 +phy_an_c73_7.0=1 +phy_an_c73_8.0=1 +phy_an_c73_34.0=1 +phy_an_c73_35.0=1 +phy_an_c73_36.0=1 +phy_an_c73_37.0=1 +phy_an_c73_38.0=1 +phy_an_c73_39.0=1 +phy_an_c73_40.0=1 +phy_an_c73_41.0=1 +phy_an_c73_68.0=1 +phy_an_c73_69.0=1 +phy_an_c73_70.0=1 +phy_an_c73_71.0=1 +phy_an_c73_72.0=1 +phy_an_c73_73.0=1 +phy_an_c73_74.0=1 +phy_an_c73_75.0=1 +phy_an_c73_102.0=1 +phy_an_c73_103.0=1 +phy_an_c73_104.0=1 +phy_an_c73_105.0=1 +phy_an_c73_106.0=1 +phy_an_c73_107.0=1 +phy_an_c73_108.0=1 +phy_an_c73_109.0=1 +phy_an_fec_1.0=1 +phy_an_fec_2.0=1 +phy_an_fec_3.0=1 +phy_an_fec_4.0=1 +phy_an_fec_5.0=1 +phy_an_fec_6.0=1 +phy_an_fec_7.0=1 +phy_an_fec_8.0=1 +phy_an_fec_9.0=1 +phy_an_fec_10.0=1 +phy_an_fec_11.0=1 +phy_an_fec_12.0=1 +phy_an_fec_13.0=1 +phy_an_fec_14.0=1 +phy_an_fec_15.0=1 +phy_an_fec_16.0=1 +phy_an_fec_17.0=1 +phy_an_fec_18.0=1 +phy_an_fec_19.0=1 +phy_an_fec_20.0=1 +phy_an_fec_21.0=1 +phy_an_fec_22.0=1 +phy_an_fec_23.0=1 +phy_an_fec_24.0=1 +phy_an_fec_25.0=1 +phy_an_fec_26.0=1 +phy_an_fec_27.0=1 +phy_an_fec_28.0=1 +phy_an_fec_29.0=1 +phy_an_fec_30.0=1 +phy_an_fec_31.0=1 +phy_an_fec_32.0=1 +phy_an_fec_34.0=1 +phy_an_fec_38.0=1 +phy_an_fec_39.0=1 +phy_an_fec_40.0=1 +phy_an_fec_41.0=1 +phy_an_fec_42.0=1 +phy_an_fec_43.0=1 +phy_an_fec_44.0=1 +phy_an_fec_45.0=1 +phy_an_fec_46.0=1 +phy_an_fec_47.0=1 +phy_an_fec_48.0=1 +phy_an_fec_49.0=1 +phy_an_fec_50.0=1 +phy_an_fec_51.0=1 +phy_an_fec_52.0=1 +phy_an_fec_53.0=1 +phy_an_fec_54.0=1 +phy_an_fec_55.0=1 +phy_an_fec_56.0=1 +phy_an_fec_57.0=1 +phy_an_fec_58.0=1 +phy_an_fec_59.0=1 +phy_an_fec_60.0=1 +phy_an_fec_61.0=1 +phy_an_fec_62.0=1 +phy_an_fec_63.0=1 +phy_an_fec_64.0=1 +phy_an_fec_65.0=1 +phy_an_fec_68.0=1 +phy_an_fec_69.0=1 +phy_an_fec_70.0=1 +phy_an_fec_71.0=1 +phy_an_fec_72.0=1 +phy_an_fec_73.0=1 +phy_an_fec_74.0=1 +phy_an_fec_75.0=1 +phy_an_fec_76.0=1 +phy_an_fec_77.0=1 +phy_an_fec_78.0=1 +phy_an_fec_79.0=1 +phy_an_fec_80.0=1 +phy_an_fec_81.0=1 +phy_an_fec_82.0=1 +phy_an_fec_83.0=1 +phy_an_fec_84.0=1 +phy_an_fec_85.0=1 +phy_an_fec_86.0=1 +phy_an_fec_87.0=1 +phy_an_fec_88.0=1 +phy_an_fec_89.0=1 +phy_an_fec_90.0=1 +phy_an_fec_91.0=1 +phy_an_fec_92.0=1 +phy_an_fec_93.0=1 +phy_an_fec_94.0=1 +phy_an_fec_95.0=1 +phy_an_fec_96.0=1 +phy_an_fec_97.0=1 +phy_an_fec_98.0=1 +phy_an_fec_99.0=1 +phy_an_fec_102.0=1 +phy_an_fec_103.0=1 +phy_an_fec_104.0=1 +phy_an_fec_105.0=1 +phy_an_fec_106.0=1 +phy_an_fec_107.0=1 +phy_an_fec_108.0=1 +phy_an_fec_109.0=1 +phy_an_fec_110.0=1 +phy_an_fec_111.0=1 +phy_an_fec_112.0=1 +phy_an_fec_113.0=1 +phy_an_fec_114.0=1 +phy_an_fec_115.0=1 +phy_an_fec_116.0=1 +phy_an_fec_117.0=1 +phy_an_fec_118.0=1 +phy_an_fec_119.0=1 +phy_an_fec_120.0=1 +phy_an_fec_121.0=1 +phy_an_fec_122.0=1 +phy_an_fec_123.0=1 +phy_an_fec_124.0=1 +phy_an_fec_125.0=1 +phy_an_fec_126.0=1 +phy_an_fec_127.0=1 +phy_an_fec_128.0=1 +phy_an_fec_129.0=1 +phy_an_fec_130.0=1 +phy_an_fec_131.0=1 +phy_an_fec_132.0=1 +phy_an_fec_133.0=1 +phy_xaui_rx_polarity_flip_1.0=0x1 +phy_xaui_rx_polarity_flip_2.0=0x5 +phy_xaui_rx_polarity_flip_3.0=0x1 +phy_xaui_rx_polarity_flip_4.0=0x7 +phy_xaui_rx_polarity_flip_5.0=0xc +phy_xaui_rx_polarity_flip_6.0=0xf +phy_xaui_rx_polarity_flip_7.0=0xc +phy_xaui_rx_polarity_flip_8.0=0xf +phy_xaui_rx_polarity_flip_34.0=0x0 +phy_xaui_rx_polarity_flip_35.0=0x7 +phy_xaui_rx_polarity_flip_36.0=0x4 +phy_xaui_rx_polarity_flip_37.0=0x7 +phy_xaui_rx_polarity_flip_38.0=0x4 +phy_xaui_rx_polarity_flip_39.0=0x6 +phy_xaui_rx_polarity_flip_40.0=0x1 +phy_xaui_rx_polarity_flip_41.0=0x2 +phy_xaui_rx_polarity_flip_68.0=0xd +phy_xaui_rx_polarity_flip_69.0=0x6 +phy_xaui_rx_polarity_flip_70.0=0x1 +phy_xaui_rx_polarity_flip_71.0=0x8 +phy_xaui_rx_polarity_flip_72.0=0x7 +phy_xaui_rx_polarity_flip_73.0=0xc +phy_xaui_rx_polarity_flip_74.0=0x7 +phy_xaui_rx_polarity_flip_75.0=0x8 +phy_xaui_rx_polarity_flip_102.0=0xb +phy_xaui_rx_polarity_flip_103.0=0xc +phy_xaui_rx_polarity_flip_104.0=0x3 +phy_xaui_rx_polarity_flip_105.0=0xc +phy_xaui_rx_polarity_flip_106.0=0xb +phy_xaui_rx_polarity_flip_107.0=0x5 +phy_xaui_rx_polarity_flip_108.0=0x1 +phy_xaui_rx_polarity_flip_109.0=0x9 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_2.0=0xe +phy_xaui_tx_polarity_flip_3.0=0x2 +phy_xaui_tx_polarity_flip_4.0=0xe +phy_xaui_tx_polarity_flip_5.0=0xc +phy_xaui_tx_polarity_flip_6.0=0xf +phy_xaui_tx_polarity_flip_7.0=0xc +phy_xaui_tx_polarity_flip_8.0=0xf +phy_xaui_tx_polarity_flip_34.0=0x0 +phy_xaui_tx_polarity_flip_35.0=0xe +phy_xaui_tx_polarity_flip_36.0=0x0 +phy_xaui_tx_polarity_flip_37.0=0xe +phy_xaui_tx_polarity_flip_38.0=0xf +phy_xaui_tx_polarity_flip_39.0=0xe +phy_xaui_tx_polarity_flip_40.0=0x6 +phy_xaui_tx_polarity_flip_41.0=0xb +phy_xaui_tx_polarity_flip_68.0=0x9 +phy_xaui_tx_polarity_flip_69.0=0xb +phy_xaui_tx_polarity_flip_70.0=0xd +phy_xaui_tx_polarity_flip_71.0=0x9 +phy_xaui_tx_polarity_flip_72.0=0x6 +phy_xaui_tx_polarity_flip_73.0=0xc +phy_xaui_tx_polarity_flip_74.0=0x9 +phy_xaui_tx_polarity_flip_75.0=0x9 +phy_xaui_tx_polarity_flip_102.0=0x6 +phy_xaui_tx_polarity_flip_103.0=0xb +phy_xaui_tx_polarity_flip_104.0=0x6 +phy_xaui_tx_polarity_flip_105.0=0xb +phy_xaui_tx_polarity_flip_106.0=0x6 +phy_xaui_tx_polarity_flip_107.0=0xf +phy_xaui_tx_polarity_flip_108.0=0x6 +phy_xaui_tx_polarity_flip_109.0=0xc +portmap_1.0=1:100 +portmap_2.0=5:100 +portmap_3.0=9:100 +portmap_4.0=13:100 +portmap_5.0=17:100 +portmap_6.0=21:100 +portmap_7.0=25:100 +portmap_8.0=29:100 +portmap_34.0=33:100 +portmap_35.0=37:100 +portmap_36.0=41:100 +portmap_37.0=45:100 +portmap_38.0=49:100 +portmap_39.0=53:100 +portmap_40.0=57:100 +portmap_41.0=61:100 +portmap_68.0=65:100 +portmap_69.0=69:100 +portmap_70.0=73:100 +portmap_71.0=77:100 +portmap_72.0=81:100 +portmap_73.0=85:100 +portmap_74.0=89:100 +portmap_75.0=93:100 +portmap_102.0=97:100 +portmap_103.0=101:100 +portmap_104.0=105:100 +portmap_105.0=109:100 +portmap_106.0=113:100 +portmap_107.0=117:100 +portmap_108.0=121:100 +portmap_109.0=125:100 +port_phy_addr_1.0=0xff +port_phy_addr_2.0=0xff +port_phy_addr_3.0=0xff +port_phy_addr_4.0=0xff +port_phy_addr_5.0=0xff +port_phy_addr_6.0=0xff +port_phy_addr_7.0=0xff +port_phy_addr_8.0=0xff +port_phy_addr_34.0=0xff +port_phy_addr_35.0=0xff +port_phy_addr_36.0=0xff +port_phy_addr_37.0=0xff +port_phy_addr_38.0=0xff +port_phy_addr_39.0=0xff +port_phy_addr_40.0=0xff +port_phy_addr_41.0=0xff +port_phy_addr_68.0=0xff +port_phy_addr_69.0=0xff +port_phy_addr_70.0=0xff +port_phy_addr_71.0=0xff +port_phy_addr_72.0=0xff +port_phy_addr_73.0=0xff +port_phy_addr_74.0=0xff +port_phy_addr_75.0=0xff +port_phy_addr_102.0=0xff +port_phy_addr_103.0=0xff +port_phy_addr_104.0=0xff +port_phy_addr_105.0=0xff +port_phy_addr_106.0=0xff +port_phy_addr_107.0=0xff +port_phy_addr_108.0=0xff +port_phy_addr_109.0=0xff +xgxs_rx_lane_map_1.0=0x3210 +xgxs_rx_lane_map_2.0=0x3210 +xgxs_rx_lane_map_3.0=0x3210 +xgxs_rx_lane_map_4.0=0x3210 +xgxs_rx_lane_map_5.0=0x0123 +xgxs_rx_lane_map_6.0=0x2301 +xgxs_rx_lane_map_7.0=0x0123 +xgxs_rx_lane_map_8.0=0x2301 +xgxs_rx_lane_map_34.0=0x0123 +xgxs_rx_lane_map_35.0=0x0321 +xgxs_rx_lane_map_36.0=0x0321 +xgxs_rx_lane_map_37.0=0x0321 +xgxs_rx_lane_map_38.0=0x1230 +xgxs_rx_lane_map_39.0=0x2301 +xgxs_rx_lane_map_40.0=0x1230 +xgxs_rx_lane_map_41.0=0x2103 +xgxs_rx_lane_map_68.0=0x1230 +xgxs_rx_lane_map_69.0=0x2301 +xgxs_rx_lane_map_70.0=0x1230 +xgxs_rx_lane_map_71.0=0x2103 +xgxs_rx_lane_map_72.0=0x1230 +xgxs_rx_lane_map_73.0=0x2301 +xgxs_rx_lane_map_74.0=0x1230 +xgxs_rx_lane_map_75.0=0x2103 +xgxs_rx_lane_map_102.0=0x3210 +xgxs_rx_lane_map_103.0=0x3210 +xgxs_rx_lane_map_104.0=0x3210 +xgxs_rx_lane_map_105.0=0x3210 +xgxs_rx_lane_map_106.0=0x3210 +xgxs_rx_lane_map_107.0=0x3210 +xgxs_rx_lane_map_108.0=0x3210 +xgxs_rx_lane_map_109.0=0x3210 +xgxs_tx_lane_map_1.0=0x0321 +xgxs_tx_lane_map_2.0=0x2301 +xgxs_tx_lane_map_3.0=0x0321 +xgxs_tx_lane_map_4.0=0x2301 +xgxs_tx_lane_map_5.0=0x0123 +xgxs_tx_lane_map_6.0=0x0123 +xgxs_tx_lane_map_7.0=0x0123 +xgxs_tx_lane_map_8.0=0x0123 +xgxs_tx_lane_map_34.0=0x2301 +xgxs_tx_lane_map_35.0=0x0321 +xgxs_tx_lane_map_36.0=0x2301 +xgxs_tx_lane_map_37.0=0x0321 +xgxs_tx_lane_map_38.0=0x0123 +xgxs_tx_lane_map_39.0=0x1230 +xgxs_tx_lane_map_40.0=0x2301 +xgxs_tx_lane_map_41.0=0x1032 +xgxs_tx_lane_map_68.0=0x0123 +xgxs_tx_lane_map_69.0=0x1230 +xgxs_tx_lane_map_70.0=0x2301 +xgxs_tx_lane_map_71.0=0x1032 +xgxs_tx_lane_map_72.0=0x0123 +xgxs_tx_lane_map_73.0=0x1230 +xgxs_tx_lane_map_74.0=0x2301 +xgxs_tx_lane_map_75.0=0x1032 +xgxs_tx_lane_map_102.0=0x0321 +xgxs_tx_lane_map_103.0=0x2301 +xgxs_tx_lane_map_104.0=0x0321 +xgxs_tx_lane_map_105.0=0x2301 +xgxs_tx_lane_map_106.0=0x0321 +xgxs_tx_lane_map_107.0=0x2301 +xgxs_tx_lane_map_108.0=0x0321 +xgxs_tx_lane_map_109.0=0x2301 + +# tuning parameters for 25g serdes fiber +serdes_driver_current_1=0xa +serdes_preemphasis_1=0x284008 +serdes_driver_current_2=0xa +serdes_preemphasis_2=0x284008 +serdes_driver_current_3=0xa +serdes_preemphasis_3=0x284008 +serdes_driver_current_4=0xa +serdes_preemphasis_4=0x284008 +serdes_driver_current_5=0xa +serdes_preemphasis_5=0x284008 +serdes_driver_current_6=0xa +serdes_preemphasis_6=0x284008 +serdes_driver_current_7=0xa +serdes_preemphasis_7=0x284008 +serdes_driver_current_8=0xd +serdes_preemphasis_8=0x303808 +serdes_driver_current_34=0xd +serdes_preemphasis_34=0x303808 +serdes_driver_current_35=0xd +serdes_preemphasis_35=0x303808 +serdes_driver_current_36=0xd +serdes_preemphasis_36=0x303808 +serdes_driver_current_37=0xd +serdes_preemphasis_37=0x303808 +serdes_driver_current_38=0xf +serdes_preemphasis_38=0x373108 +serdes_driver_current_39=0xf +serdes_preemphasis_39=0x373108 +serdes_driver_current_40=0xf +serdes_preemphasis_40=0x373108 +serdes_driver_current_41=0xf +serdes_preemphasis_41=0x373108 +serdes_driver_current_68=0xf +serdes_preemphasis_68=0x373108 +serdes_driver_current_69=0xf +serdes_preemphasis_69=0x373108 +serdes_driver_current_70=0xf +serdes_preemphasis_70=0x373108 +serdes_driver_current_71=0xf +serdes_preemphasis_71=0x373108 +serdes_driver_current_72=0xd +serdes_preemphasis_72=0x303808 +serdes_driver_current_73=0xd +serdes_preemphasis_73=0x303808 +serdes_driver_current_74=0xd +serdes_preemphasis_74=0x303808 +serdes_driver_current_75=0xd +serdes_preemphasis_75=0x303808 +serdes_driver_current_102=0xa +serdes_preemphasis_102=0x284008 +serdes_driver_current_103=0xa +serdes_preemphasis_103=0x284008 +serdes_driver_current_104=0xa +serdes_preemphasis_104=0x284008 +serdes_driver_current_105=0xa +serdes_preemphasis_105=0x284008 +serdes_driver_current_106=0xa +serdes_preemphasis_106=0x284008 +serdes_driver_current_107=0xa +serdes_preemphasis_107=0x284008 +serdes_driver_current_108=0xa +serdes_preemphasis_108=0x284008 +serdes_driver_current_109=0xa +serdes_preemphasis_109=0x284008 + +mmu_init_config="MSFT-TH-Tier1" diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/buffers.json.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..1430479d08e0 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/buffers_defaults_t0.j2 @@ -0,0 +1,61 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,6) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(10,22) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(26,32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(6,10) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(22,26) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/pg_profile_lookup.ini b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/pg_profile_lookup.ini new file mode 100644 index 000000000000..0b5d680edda7 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 0 2288 + 25000 5m 1248 2288 53248 0 2288 + 40000 5m 1248 2288 66560 0 2288 + 50000 5m 1248 2288 79872 0 2288 + 100000 5m 1248 2288 165568 0 2288 + 10000 40m 1248 2288 37024 0 2288 + 25000 40m 1248 2288 56160 0 2288 + 40000 40m 1248 2288 71552 0 2288 + 50000 40m 1248 2288 85696 0 2288 + 100000 40m 1248 2288 177632 0 2288 + 10000 300m 1248 2288 46176 0 2288 + 25000 300m 1248 2288 79040 0 2288 + 40000 300m 1248 2288 108160 0 2288 + 50000 300m 1248 2288 141856 0 2288 + 100000 300m 1248 2288 268736 0 2288 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/port_config.ini b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/port_config.ini new file mode 100644 index 000000000000..0366a339f6f9 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 33,34 Ethernet1/1 1 50000 +Ethernet2 35,36 Ethernet1/3 1 50000 +Ethernet4 37,38 Ethernet2/1 2 50000 +Ethernet6 39,40 Ethernet2/3 2 50000 +Ethernet8 41,42 Ethernet3/1 3 50000 +Ethernet10 43,44 Ethernet3/3 3 50000 +Ethernet12 45,46 Ethernet4/1 4 50000 +Ethernet14 47,48 Ethernet4/3 4 50000 +Ethernet16 49,50 Ethernet5/1 5 50000 +Ethernet18 51,52 Ethernet5/3 5 50000 +Ethernet20 53,54 Ethernet6/1 6 50000 +Ethernet22 55,56 Ethernet6/3 6 50000 +Ethernet24 57,58,59,60 Ethernet7/1 7 100000 +Ethernet28 61,62,63,64 Ethernet8/1 8 100000 +Ethernet32 65,66,67,68 Ethernet9/1 9 100000 +Ethernet36 69,70,71,72 Ethernet10/1 10 100000 +Ethernet40 73,74 Ethernet11/1 11 50000 +Ethernet42 75,76 Ethernet11/3 11 50000 +Ethernet44 77,78 Ethernet12/1 12 50000 +Ethernet46 79,80 Ethernet12/3 12 50000 +Ethernet48 81,82 Ethernet13/1 13 50000 +Ethernet50 83,84 Ethernet13/3 13 50000 +Ethernet52 85,86 Ethernet14/1 14 50000 +Ethernet54 87,88 Ethernet14/3 14 50000 +Ethernet56 89,90 Ethernet15/1 15 50000 +Ethernet58 91,92 Ethernet15/3 15 50000 +Ethernet60 93,94 Ethernet16/1 16 50000 +Ethernet62 95,96 Ethernet16/3 16 50000 +Ethernet64 97,98 Ethernet17/1 17 50000 +Ethernet66 99,100 Ethernet17/3 17 50000 +Ethernet68 101,102 Ethernet18/1 18 50000 +Ethernet70 103,104 Ethernet18/3 18 50000 +Ethernet72 105,106 Ethernet19/1 19 50000 +Ethernet74 107,108 Ethernet19/3 19 50000 +Ethernet76 109,110 Ethernet20/1 20 50000 +Ethernet78 111,112 Ethernet20/3 20 50000 +Ethernet80 113,114 Ethernet21/1 21 50000 +Ethernet82 115,116 Ethernet21/3 21 50000 +Ethernet84 117,118 Ethernet22/1 22 50000 +Ethernet86 119,120 Ethernet22/3 22 50000 +Ethernet88 121,122,123,124 Ethernet23/1 23 100000 +Ethernet92 125,126,127,128 Ethernet24/1 24 100000 +Ethernet96 1,2,3,4 Ethernet25/1 25 100000 +Ethernet100 5,6,7,8 Ethernet26/1 26 100000 +Ethernet104 9,10 Ethernet27/1 27 50000 +Ethernet106 11,12 Ethernet27/3 27 50000 +Ethernet108 13,14 Ethernet28/1 28 50000 +Ethernet110 15,16 Ethernet28/3 28 50000 +Ethernet112 17,18 Ethernet29/1 29 50000 +Ethernet114 19,20 Ethernet29/3 29 50000 +Ethernet116 21,22 Ethernet30/1 30 50000 +Ethernet118 23,24 Ethernet30/3 30 50000 +Ethernet120 25,26 Ethernet31/1 31 50000 +Ethernet122 27,28 Ethernet31/3 31 50000 +Ethernet124 29,30 Ethernet32/1 32 50000 +Ethernet126 31,32 Ethernet32/3 32 50000 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/qos.json.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/qos.json.j2 new file mode 100644 index 000000000000..34002048afdb --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/qos.json.j2 @@ -0,0 +1,21 @@ +{%- macro generate_wred_profiles() %} + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "250000", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, +{%- endmacro %} + +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/sai.profile b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/sai.profile new file mode 100644 index 000000000000..692f79decc1f --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-a7060-cx32s-8x100G+48x50G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/th-a7060-cx32s-8x100G+48x50G.config.bcm b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/th-a7060-cx32s-8x100G+48x50G.config.bcm new file mode 100644 index 000000000000..5c70d324dbb3 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-D48C8/th-a7060-cx32s-8x100G+48x50G.config.bcm @@ -0,0 +1,547 @@ +# Arista 7060CX-32S + +phy_an_allow_pll_change=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +higig2_hdr_mode=1 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +l2xmsg_mode=1 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +os=unix +oversubscribe_mode=1 +ptp_bs_fref.0=25000000 +ptp_ts_pll_fref.0=25000000 +robust_hash_disable_egress_vlan.0=1 +robust_hash_disable_mpls.0=1 +robust_hash_disable_vlan.0=1 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +phy_an_allow_pll_change_hg.0=0 +dport_map_direct=1 +phy_an_c73=1 + +phy_an_fec_1.0=1 +phy_an_fec_2.0=1 +phy_an_fec_3.0=1 +phy_an_fec_4.0=1 +phy_an_fec_5.0=1 +phy_an_fec_6.0=1 +phy_an_fec_7.0=1 +phy_an_fec_8.0=1 +phy_an_fec_9.0=1 +phy_an_fec_10.0=1 +phy_an_fec_11.0=1 +phy_an_fec_12.0=1 +phy_an_fec_13.0=1 +phy_an_fec_14.0=1 +phy_an_fec_34.0=1 +phy_an_fec_35.0=1 +phy_an_fec_36.0=1 +phy_an_fec_37.0=1 +phy_an_fec_38.0=1 +phy_an_fec_39.0=1 +phy_an_fec_40.0=1 +phy_an_fec_41.0=1 +phy_an_fec_42.0=1 +phy_an_fec_43.0=1 +phy_an_fec_44.0=1 +phy_an_fec_45.0=1 +phy_an_fec_46.0=1 +phy_an_fec_47.0=1 +phy_an_fec_68.0=1 +phy_an_fec_69.0=1 +phy_an_fec_70.0=1 +phy_an_fec_71.0=1 +phy_an_fec_72.0=1 +phy_an_fec_73.0=1 +phy_an_fec_74.0=1 +phy_an_fec_75.0=1 +phy_an_fec_76.0=1 +phy_an_fec_77.0=1 +phy_an_fec_78.0=1 +phy_an_fec_79.0=1 +phy_an_fec_80.0=1 +phy_an_fec_81.0=1 +phy_an_fec_102.0=1 +phy_an_fec_103.0=1 +phy_an_fec_104.0=1 +phy_an_fec_105.0=1 +phy_an_fec_106.0=1 +phy_an_fec_107.0=1 +phy_an_fec_108.0=1 +phy_an_fec_109.0=1 +phy_an_fec_110.0=1 +phy_an_fec_111.0=1 +phy_an_fec_112.0=1 +phy_an_fec_113.0=1 +phy_an_fec_114.0=1 +phy_an_fec_115.0=1 + +# Q1 +portmap_1.0=1:100 +portmap_2.0=5:100 +portmap_3.0=9:50:2 +portmap_4.0=11:50:2 +portmap_5.0=13:50:2 +portmap_6.0=15:50:2 +portmap_7.0=17:50:2 +portmap_8.0=19:50:2 +portmap_9.0=21:50:2 +portmap_10.0=23:50:2 +portmap_11.0=25:50:2 +portmap_12.0=27:50:2 +portmap_13.0=29:50:2 +portmap_14.0=31:50:2 +phy_xaui_rx_polarity_flip_1.0=0x1 +phy_xaui_rx_polarity_flip_2.0=0x5 +phy_xaui_rx_polarity_flip_3.0=0x1 +phy_xaui_rx_polarity_flip_4.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x3 +phy_xaui_rx_polarity_flip_6.0=0x1 +phy_xaui_rx_polarity_flip_7.0=0x0 +phy_xaui_rx_polarity_flip_8.0=0x3 +phy_xaui_rx_polarity_flip_9.0=0x3 +phy_xaui_rx_polarity_flip_10.0=0x3 +phy_xaui_rx_polarity_flip_11.0=0x0 +phy_xaui_rx_polarity_flip_12.0=0x3 +phy_xaui_rx_polarity_flip_13.0=0x3 +phy_xaui_rx_polarity_flip_14.0=0x3 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_2.0=0xe +phy_xaui_tx_polarity_flip_3.0=0x2 +phy_xaui_tx_polarity_flip_4.0=0x0 +phy_xaui_tx_polarity_flip_5.0=0x2 +phy_xaui_tx_polarity_flip_6.0=0x3 +phy_xaui_tx_polarity_flip_7.0=0x0 +phy_xaui_tx_polarity_flip_8.0=0x3 +phy_xaui_tx_polarity_flip_9.0=0x3 +phy_xaui_tx_polarity_flip_10.0=0x3 +phy_xaui_tx_polarity_flip_11.0=0x0 +phy_xaui_tx_polarity_flip_12.0=0x3 +phy_xaui_tx_polarity_flip_13.0=0x3 +phy_xaui_tx_polarity_flip_14.0=0x3 +port_phy_addr_1.0=0xff +port_phy_addr_2.0=0xff +port_phy_addr_3.0=0xff +port_phy_addr_4.0=0xff +port_phy_addr_5.0=0xff +port_phy_addr_6.0=0xff +port_phy_addr_7.0=0xff +port_phy_addr_8.0=0xff +port_phy_addr_9.0=0xff +port_phy_addr_10.0=0xff +port_phy_addr_11.0=0xff +port_phy_addr_12.0=0xff +port_phy_addr_13.0=0xff +port_phy_addr_14.0=0xff +xgxs_rx_lane_map_1.0=0x3210 +xgxs_rx_lane_map_2.0=0x3210 +xgxs_rx_lane_map_3.0=0x3210 +xgxs_rx_lane_map_4.0=0x3210 +xgxs_rx_lane_map_5.0=0x3210 +xgxs_rx_lane_map_6.0=0x3210 +xgxs_rx_lane_map_7.0=0x0123 +xgxs_rx_lane_map_8.0=0x0123 +xgxs_rx_lane_map_9.0=0x2301 +xgxs_rx_lane_map_10.0=0x2301 +xgxs_rx_lane_map_11.0=0x0123 +xgxs_rx_lane_map_12.0=0x0123 +xgxs_rx_lane_map_13.0=0x2301 +xgxs_rx_lane_map_14.0=0x2301 +xgxs_tx_lane_map_1.0=0x0321 +xgxs_tx_lane_map_2.0=0x2301 +xgxs_tx_lane_map_3.0=0x0321 +xgxs_tx_lane_map_4.0=0x0321 +xgxs_tx_lane_map_5.0=0x2301 +xgxs_tx_lane_map_6.0=0x2301 +xgxs_tx_lane_map_7.0=0x0123 +xgxs_tx_lane_map_8.0=0x0123 +xgxs_tx_lane_map_9.0=0x0123 +xgxs_tx_lane_map_10.0=0x0123 +xgxs_tx_lane_map_11.0=0x0123 +xgxs_tx_lane_map_12.0=0x0123 +xgxs_tx_lane_map_13.0=0x0123 +xgxs_tx_lane_map_14.0=0x0123 + +# Q2 +portmap_34.0=33:50:2 +portmap_35.0=35:50:2 +portmap_36.0=37:50:2 +portmap_37.0=39:50:2 +portmap_38.0=41:50:2 +portmap_39.0=43:50:2 +portmap_40.0=45:50:2 +portmap_41.0=47:50:2 +portmap_42.0=49:50:2 +portmap_43.0=51:50:2 +portmap_44.0=53:50:2 +portmap_45.0=55:50:2 +portmap_46.0=57:100 +portmap_47.0=61:100 +phy_xaui_rx_polarity_flip_34.0=0x0 +phy_xaui_rx_polarity_flip_35.0=0x0 +phy_xaui_rx_polarity_flip_36.0=0x3 +phy_xaui_rx_polarity_flip_37.0=0x1 +phy_xaui_rx_polarity_flip_38.0=0x0 +phy_xaui_rx_polarity_flip_39.0=0x1 +phy_xaui_rx_polarity_flip_40.0=0x3 +phy_xaui_rx_polarity_flip_41.0=0x1 +phy_xaui_rx_polarity_flip_42.0=0x0 +phy_xaui_rx_polarity_flip_43.0=0x1 +phy_xaui_rx_polarity_flip_44.0=0x2 +phy_xaui_rx_polarity_flip_45.0=0x1 +phy_xaui_rx_polarity_flip_46.0=0x1 +phy_xaui_rx_polarity_flip_47.0=0x2 +phy_xaui_tx_polarity_flip_34.0=0x0 +phy_xaui_tx_polarity_flip_35.0=0x0 +phy_xaui_tx_polarity_flip_36.0=0x2 +phy_xaui_tx_polarity_flip_37.0=0x3 +phy_xaui_tx_polarity_flip_38.0=0x0 +phy_xaui_tx_polarity_flip_39.0=0x0 +phy_xaui_tx_polarity_flip_40.0=0x2 +phy_xaui_tx_polarity_flip_41.0=0x3 +phy_xaui_tx_polarity_flip_42.0=0x3 +phy_xaui_tx_polarity_flip_43.0=0x3 +phy_xaui_tx_polarity_flip_44.0=0x2 +phy_xaui_tx_polarity_flip_45.0=0x3 +phy_xaui_tx_polarity_flip_46.0=0x6 +phy_xaui_tx_polarity_flip_47.0=0xb +port_phy_addr_34.0=0xff +port_phy_addr_35.0=0xff +port_phy_addr_36.0=0xff +port_phy_addr_37.0=0xff +port_phy_addr_38.0=0xff +port_phy_addr_39.0=0xff +port_phy_addr_40.0=0xff +port_phy_addr_41.0=0xff +port_phy_addr_42.0=0xff +port_phy_addr_43.0=0xff +port_phy_addr_44.0=0xff +port_phy_addr_45.0=0xff +port_phy_addr_46.0=0xff +port_phy_addr_47.0=0xff +xgxs_rx_lane_map_34.0=0x0123 +xgxs_rx_lane_map_35.0=0x0123 +xgxs_rx_lane_map_36.0=0x0321 +xgxs_rx_lane_map_37.0=0x0321 +xgxs_rx_lane_map_38.0=0x0321 +xgxs_rx_lane_map_39.0=0x0321 +xgxs_rx_lane_map_40.0=0x0321 +xgxs_rx_lane_map_41.0=0x0321 +xgxs_rx_lane_map_42.0=0x1230 +xgxs_rx_lane_map_43.0=0x1230 +xgxs_rx_lane_map_44.0=0x2301 +xgxs_rx_lane_map_45.0=0x2301 +xgxs_rx_lane_map_46.0=0x1230 +xgxs_rx_lane_map_47.0=0x2103 +xgxs_tx_lane_map_34.0=0x2301 +xgxs_tx_lane_map_35.0=0x2301 +xgxs_tx_lane_map_36.0=0x0321 +xgxs_tx_lane_map_37.0=0x0321 +xgxs_tx_lane_map_38.0=0x2301 +xgxs_tx_lane_map_39.0=0x2301 +xgxs_tx_lane_map_40.0=0x0321 +xgxs_tx_lane_map_41.0=0x0321 +xgxs_tx_lane_map_42.0=0x0123 +xgxs_tx_lane_map_43.0=0x0123 +xgxs_tx_lane_map_44.0=0x1230 +xgxs_tx_lane_map_45.0=0x1230 +xgxs_tx_lane_map_46.0=0x2301 +xgxs_tx_lane_map_47.0=0x1032 + +# Q3 +portmap_68.0=65:100 +portmap_69.0=69:100 +portmap_70.0=73:50:2 +portmap_71.0=75:50:2 +portmap_72.0=77:50:2 +portmap_73.0=79:50:2 +portmap_74.0=81:50:2 +portmap_75.0=83:50:2 +portmap_76.0=85:50:2 +portmap_77.0=87:50:2 +portmap_78.0=89:50:2 +portmap_79.0=91:50:2 +portmap_80.0=93:50:2 +portmap_81.0=95:50:2 +phy_xaui_rx_polarity_flip_68.0=0xd +phy_xaui_rx_polarity_flip_69.0=0x6 +phy_xaui_rx_polarity_flip_70.0=0x1 +phy_xaui_rx_polarity_flip_71.0=0x0 +phy_xaui_rx_polarity_flip_72.0=0x0 +phy_xaui_rx_polarity_flip_73.0=0x2 +phy_xaui_rx_polarity_flip_74.0=0x3 +phy_xaui_rx_polarity_flip_75.0=0x1 +phy_xaui_rx_polarity_flip_76.0=0x0 +phy_xaui_rx_polarity_flip_77.0=0x3 +phy_xaui_rx_polarity_flip_78.0=0x3 +phy_xaui_rx_polarity_flip_79.0=0x1 +phy_xaui_rx_polarity_flip_80.0=0x0 +phy_xaui_rx_polarity_flip_81.0=0x2 +phy_xaui_tx_polarity_flip_68.0=0x9 +phy_xaui_tx_polarity_flip_69.0=0xb +phy_xaui_tx_polarity_flip_70.0=0x1 +phy_xaui_tx_polarity_flip_71.0=0x3 +phy_xaui_tx_polarity_flip_72.0=0x1 +phy_xaui_tx_polarity_flip_73.0=0x2 +phy_xaui_tx_polarity_flip_74.0=0x2 +phy_xaui_tx_polarity_flip_75.0=0x1 +phy_xaui_tx_polarity_flip_76.0=0x0 +phy_xaui_tx_polarity_flip_77.0=0x3 +phy_xaui_tx_polarity_flip_78.0=0x1 +phy_xaui_tx_polarity_flip_79.0=0x2 +phy_xaui_tx_polarity_flip_80.0=0x1 +phy_xaui_tx_polarity_flip_81.0=0x2 +port_phy_addr_68.0=0xff +port_phy_addr_69.0=0xff +port_phy_addr_70.0=0xff +port_phy_addr_71.0=0xff +port_phy_addr_72.0=0xff +port_phy_addr_73.0=0xff +port_phy_addr_74.0=0xff +port_phy_addr_75.0=0xff +port_phy_addr_76.0=0xff +port_phy_addr_77.0=0xff +port_phy_addr_78.0=0xff +port_phy_addr_79.0=0xff +port_phy_addr_80.0=0xff +port_phy_addr_81.0=0xff +xgxs_rx_lane_map_68.0=0x1230 +xgxs_rx_lane_map_69.0=0x2301 +xgxs_rx_lane_map_70.0=0x1230 +xgxs_rx_lane_map_71.0=0x1230 +xgxs_rx_lane_map_72.0=0x2103 +xgxs_rx_lane_map_73.0=0x2103 +xgxs_rx_lane_map_74.0=0x1230 +xgxs_rx_lane_map_75.0=0x1230 +xgxs_rx_lane_map_76.0=0x2301 +xgxs_rx_lane_map_77.0=0x2301 +xgxs_rx_lane_map_78.0=0x1230 +xgxs_rx_lane_map_79.0=0x1230 +xgxs_rx_lane_map_80.0=0x2103 +xgxs_rx_lane_map_81.0=0x2103 +xgxs_tx_lane_map_68.0=0x0123 +xgxs_tx_lane_map_69.0=0x1230 +xgxs_tx_lane_map_70.0=0x2301 +xgxs_tx_lane_map_71.0=0x2301 +xgxs_tx_lane_map_72.0=0x1032 +xgxs_tx_lane_map_73.0=0x1032 +xgxs_tx_lane_map_74.0=0x0123 +xgxs_tx_lane_map_75.0=0x0123 +xgxs_tx_lane_map_76.0=0x1230 +xgxs_tx_lane_map_77.0=0x1230 +xgxs_tx_lane_map_78.0=0x2301 +xgxs_tx_lane_map_79.0=0x2301 +xgxs_tx_lane_map_80.0=0x1032 +xgxs_tx_lane_map_81.0=0x1032 + +# Q4 +portmap_102.0=97:50:2 +portmap_103.0=99:50:2 +portmap_104.0=101:50:2 +portmap_105.0=103:50:2 +portmap_106.0=105:50:2 +portmap_107.0=107:50:2 +portmap_108.0=109:50:2 +portmap_109.0=111:50:2 +portmap_110.0=113:50:2 +portmap_111.0=115:50:2 +portmap_112.0=117:50:2 +portmap_113.0=119:50:2 +portmap_114.0=121:100 +portmap_115.0=125:100 +phy_xaui_rx_polarity_flip_102.0=0x3 +phy_xaui_rx_polarity_flip_103.0=0x2 +phy_xaui_rx_polarity_flip_104.0=0x0 +phy_xaui_rx_polarity_flip_105.0=0x3 +phy_xaui_rx_polarity_flip_106.0=0x3 +phy_xaui_rx_polarity_flip_107.0=0x0 +phy_xaui_rx_polarity_flip_108.0=0x0 +phy_xaui_rx_polarity_flip_109.0=0x3 +phy_xaui_rx_polarity_flip_110.0=0x3 +phy_xaui_rx_polarity_flip_111.0=0x2 +phy_xaui_rx_polarity_flip_112.0=0x1 +phy_xaui_rx_polarity_flip_113.0=0x1 +phy_xaui_rx_polarity_flip_114.0=0x1 +phy_xaui_rx_polarity_flip_115.0=0x9 +phy_xaui_tx_polarity_flip_102.0=0x2 +phy_xaui_tx_polarity_flip_103.0=0x1 +phy_xaui_tx_polarity_flip_104.0=0x3 +phy_xaui_tx_polarity_flip_105.0=0x2 +phy_xaui_tx_polarity_flip_106.0=0x2 +phy_xaui_tx_polarity_flip_107.0=0x1 +phy_xaui_tx_polarity_flip_108.0=0x3 +phy_xaui_tx_polarity_flip_109.0=0x2 +phy_xaui_tx_polarity_flip_110.0=0x2 +phy_xaui_tx_polarity_flip_111.0=0x1 +phy_xaui_tx_polarity_flip_112.0=0x3 +phy_xaui_tx_polarity_flip_113.0=0x3 +phy_xaui_tx_polarity_flip_114.0=0x6 +phy_xaui_tx_polarity_flip_115.0=0xc +port_phy_addr_102.0=0xff +port_phy_addr_103.0=0xff +port_phy_addr_104.0=0xff +port_phy_addr_105.0=0xff +port_phy_addr_106.0=0xff +port_phy_addr_107.0=0xff +port_phy_addr_108.0=0xff +port_phy_addr_109.0=0xff +port_phy_addr_110.0=0xff +port_phy_addr_111.0=0xff +port_phy_addr_112.0=0xff +port_phy_addr_113.0=0xff +port_phy_addr_114.0=0xff +port_phy_addr_115.0=0xff +xgxs_rx_lane_map_102.0=0x3210 +xgxs_rx_lane_map_103.0=0x3210 +xgxs_rx_lane_map_104.0=0x3210 +xgxs_rx_lane_map_105.0=0x3210 +xgxs_rx_lane_map_106.0=0x3210 +xgxs_rx_lane_map_107.0=0x3210 +xgxs_rx_lane_map_108.0=0x3210 +xgxs_rx_lane_map_109.0=0x3210 +xgxs_rx_lane_map_110.0=0x3210 +xgxs_rx_lane_map_111.0=0x3210 +xgxs_rx_lane_map_112.0=0x3210 +xgxs_rx_lane_map_114.0=0x3210 +xgxs_rx_lane_map_115.0=0x3210 +xgxs_tx_lane_map_102.0=0x0321 +xgxs_tx_lane_map_103.0=0x0321 +xgxs_tx_lane_map_104.0=0x2301 +xgxs_tx_lane_map_105.0=0x2301 +xgxs_tx_lane_map_106.0=0x0321 +xgxs_tx_lane_map_107.0=0x0321 +xgxs_tx_lane_map_108.0=0x2301 +xgxs_tx_lane_map_109.0=0x2301 +xgxs_tx_lane_map_110.0=0x0321 +xgxs_tx_lane_map_111.0=0x0321 +xgxs_tx_lane_map_112.0=0x2301 +xgxs_tx_lane_map_113.0=0x2301 +xgxs_tx_lane_map_114.0=0x0321 +xgxs_tx_lane_map_115.0=0x2301 + +# tuning parameters +serdes_driver_current_1=0xa +serdes_preemphasis_1=0x284008 +serdes_driver_current_2=0xa +serdes_preemphasis_2=0x284008 +serdes_driver_current_3=0xf +serdes_preemphasis_3=0x46408 +serdes_driver_current_4=0xf +serdes_preemphasis_4=0x46408 +serdes_driver_current_5=0xf +serdes_preemphasis_5=0x46408 +serdes_driver_current_6=0xf +serdes_preemphasis_6=0x46408 +serdes_driver_current_7=0xf +serdes_preemphasis_7=0x46408 +serdes_driver_current_8=0xf +serdes_preemphasis_8=0x46408 +serdes_driver_current_9=0xf +serdes_preemphasis_9=0x46408 +serdes_driver_current_10=0xf +serdes_preemphasis_10=0x46408 +serdes_driver_current_11=0xf +serdes_preemphasis_11=0x46408 +serdes_driver_current_12=0xf +serdes_preemphasis_12=0x46408 +serdes_driver_current_13=0xf +serdes_preemphasis_13=0x46408 +serdes_driver_current_14=0xf +serdes_preemphasis_14=0x46408 +serdes_driver_current_34=0xf +serdes_preemphasis_34=0x46408 +serdes_driver_current_35=0xf +serdes_preemphasis_35=0x46408 +serdes_driver_current_36=0xf +serdes_preemphasis_36=0x46408 +serdes_driver_current_37=0xf +serdes_preemphasis_37=0x46408 +serdes_driver_current_38=0xf +serdes_preemphasis_38=0x46408 +serdes_driver_current_39=0xf +serdes_preemphasis_39=0x46408 +serdes_driver_current_40=0xf +serdes_preemphasis_40=0x46408 +serdes_driver_current_41=0xf +serdes_preemphasis_41=0x46408 +serdes_driver_current_42=0xf +serdes_preemphasis_42=0x46408 +serdes_driver_current_43=0xf +serdes_preemphasis_43=0x46408 +serdes_driver_current_44=0xf +serdes_preemphasis_44=0x46408 +serdes_driver_current_45=0xf +serdes_preemphasis_45=0x46408 +serdes_driver_current_46=0xf +serdes_preemphasis_46=0x373108 +serdes_driver_current_47=0xf +serdes_preemphasis_47=0x373108 +serdes_driver_current_68=0xf +serdes_preemphasis_68=0x373108 +serdes_driver_current_69=0xf +serdes_preemphasis_69=0x373108 +serdes_driver_current_70=0xf +serdes_preemphasis_70=0x46408 +serdes_driver_current_71=0xf +serdes_preemphasis_71=0x46408 +serdes_driver_current_72=0xf +serdes_preemphasis_72=0x46408 +serdes_driver_current_73=0xf +serdes_preemphasis_73=0x46408 +serdes_driver_current_74=0xf +serdes_preemphasis_74=0x46408 +serdes_driver_current_75=0xf +serdes_preemphasis_75=0x46408 +serdes_driver_current_76=0xf +serdes_preemphasis_76=0x46408 +serdes_driver_current_77=0xf +serdes_preemphasis_77=0x46408 +serdes_driver_current_78=0xf +serdes_preemphasis_78=0x46408 +serdes_driver_current_79=0xf +serdes_preemphasis_79=0x46408 +serdes_driver_current_80=0xf +serdes_preemphasis_80=0x46408 +serdes_driver_current_81=0xf +serdes_preemphasis_81=0x46408 +serdes_driver_current_102=0xf +serdes_preemphasis_102=0x46408 +serdes_driver_current_103=0xf +serdes_preemphasis_103=0x46408 +serdes_driver_current_104=0xf +serdes_preemphasis_104=0x46408 +serdes_driver_current_105=0xf +serdes_preemphasis_105=0x46408 +serdes_driver_current_106=0xf +serdes_preemphasis_106=0x46408 +serdes_driver_current_107=0xf +serdes_preemphasis_107=0x46408 +serdes_driver_current_108=0xf +serdes_preemphasis_108=0x46408 +serdes_driver_current_109=0xf +serdes_preemphasis_109=0x46408 +serdes_driver_current_110=0xf +serdes_preemphasis_110=0x46408 +serdes_driver_current_111=0xf +serdes_preemphasis_111=0x46408 +serdes_driver_current_112=0xf +serdes_preemphasis_112=0x46408 +serdes_driver_current_113=0xf +serdes_preemphasis_113=0x46408 +serdes_driver_current_114=0xa +serdes_preemphasis_114=0x284008 +serdes_driver_current_115=0xa +serdes_preemphasis_115=0x284008 + +mmu_init_config="MSFT-TH-Tier0" diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/buffers.json.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..4858c7a67e65 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/buffers_defaults_t0.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '5m' %} + +{%- 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": "11213696", + "type": "ingress", + "mode": "dynamic", + "xoff": "3855488" + }, + "egress_lossy_pool": { + "size": "9532224", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/pg_profile_lookup.ini b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/pg_profile_lookup.ini new file mode 100644 index 000000000000..7222f8014925 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -4 2288 + 25000 5m 1248 2288 53248 -4 2288 + 40000 5m 1248 2288 66560 -4 2288 + 50000 5m 1248 2288 79872 -4 2288 + 100000 5m 1248 2288 165568 -4 2288 + 10000 40m 1248 2288 37024 -4 2288 + 25000 40m 1248 2288 56160 -4 2288 + 40000 40m 1248 2288 71552 -4 2288 + 50000 40m 1248 2288 85696 -4 2288 + 100000 40m 1248 2288 177632 -4 2288 + 10000 300m 1248 2288 46176 -4 2288 + 25000 300m 1248 2288 79040 -4 2288 + 40000 300m 1248 2288 108160 -4 2288 + 50000 300m 1248 2288 131456 -4 2288 + 100000 300m 1248 2288 268736 -4 2288 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/port_config.ini b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/port_config.ini new file mode 100644 index 000000000000..4ef0dce97b24 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 33,34,35,36 Ethernet1/1 1 100000 +Ethernet4 37,38,39,40 Ethernet2/1 2 100000 +Ethernet8 41,42,43,44 Ethernet3/1 3 40000 +Ethernet12 45,46,47,48 Ethernet4/1 4 40000 +Ethernet16 49,50,51,52 Ethernet5/1 5 40000 +Ethernet20 53,54,55,56 Ethernet6/1 6 40000 +Ethernet24 57,58,59,60 Ethernet7/1 7 40000 +Ethernet28 61,62,63,64 Ethernet8/1 8 40000 +Ethernet32 65,66,67,68 Ethernet9/1 9 100000 +Ethernet36 69,70,71,72 Ethernet10/1 10 100000 +Ethernet40 73,74,75,76 Ethernet11/1 11 40000 +Ethernet44 77,78,79,80 Ethernet12/1 12 40000 +Ethernet48 81,82,83,84 Ethernet13/1 13 40000 +Ethernet52 85,86,87,88 Ethernet14/1 14 40000 +Ethernet56 89,90,91,92 Ethernet15/1 15 40000 +Ethernet60 93,94,95,96 Ethernet16/1 16 40000 +Ethernet64 97,98,99,100 Ethernet17/1 17 100000 +Ethernet68 101,102,103,104 Ethernet18/1 18 100000 +Ethernet72 105,106,107,108 Ethernet19/1 19 40000 +Ethernet76 109,110,111,112 Ethernet20/1 20 40000 +Ethernet80 113,114,115,116 Ethernet21/1 21 40000 +Ethernet84 117,118,119,120 Ethernet22/1 22 40000 +Ethernet88 121,122,123,124 Ethernet23/1 23 40000 +Ethernet92 125,126,127,128 Ethernet24/1 24 40000 +Ethernet96 1,2,3,4 Ethernet25/1 25 100000 +Ethernet100 5,6,7,8 Ethernet26/1 26 100000 +Ethernet104 9,10,11,12 Ethernet27/1 27 40000 +Ethernet108 13,14,15,16 Ethernet28/1 28 40000 +Ethernet112 17,18,19,20 Ethernet29/1 29 40000 +Ethernet116 21,22,23,24 Ethernet30/1 30 40000 +Ethernet120 25,26,27,28 Ethernet31/1 31 40000 +Ethernet124 29,30,31,32 Ethernet32/1 32 40000 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/qos.json.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/sai.profile b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/sai.profile new file mode 100644 index 000000000000..08abf1198948 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-a7060-cx32s-8x100G+24x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/th-a7060-cx32s-8x100G+24x40G.config.bcm b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/th-a7060-cx32s-8x100G+24x40G.config.bcm new file mode 100644 index 000000000000..05908a259c48 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q24C8/th-a7060-cx32s-8x100G+24x40G.config.bcm @@ -0,0 +1,446 @@ +# Arista 7060CX-32S + +phy_an_allow_pll_change=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +higig2_hdr_mode=1 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +l2xmsg_mode=1 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +os=unix +oversubscribe_mode=1 +ptp_bs_fref.0=25000000 +ptp_ts_pll_fref.0=25000000 +robust_hash_disable_egress_vlan.0=1 +robust_hash_disable_mpls.0=1 +robust_hash_disable_vlan.0=1 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 +pbmp_xport_xe.0=0x7ffffffffffffffffffffffffffffffffe +phy_an_allow_pll_change_hg.0=0 +phy_an_c73_1.0=1 +phy_an_c73_2.0=1 +phy_an_c73_3.0=1 +phy_an_c73_4.0=1 +phy_an_c73_5.0=1 +phy_an_c73_6.0=1 +phy_an_c73_7.0=1 +phy_an_c73_8.0=1 +phy_an_c73_34.0=1 +phy_an_c73_35.0=1 +phy_an_c73_36.0=1 +phy_an_c73_37.0=1 +phy_an_c73_38.0=1 +phy_an_c73_39.0=1 +phy_an_c73_40.0=1 +phy_an_c73_41.0=1 +phy_an_c73_68.0=1 +phy_an_c73_69.0=1 +phy_an_c73_70.0=1 +phy_an_c73_71.0=1 +phy_an_c73_72.0=1 +phy_an_c73_73.0=1 +phy_an_c73_74.0=1 +phy_an_c73_75.0=1 +phy_an_c73_102.0=1 +phy_an_c73_103.0=1 +phy_an_c73_104.0=1 +phy_an_c73_105.0=1 +phy_an_c73_106.0=1 +phy_an_c73_107.0=1 +phy_an_c73_108.0=1 +phy_an_c73_109.0=1 +phy_an_fec_1.0=1 +phy_an_fec_2.0=1 +phy_an_fec_3.0=1 +phy_an_fec_4.0=1 +phy_an_fec_5.0=1 +phy_an_fec_6.0=1 +phy_an_fec_7.0=1 +phy_an_fec_8.0=1 +phy_an_fec_9.0=1 +phy_an_fec_10.0=1 +phy_an_fec_11.0=1 +phy_an_fec_12.0=1 +phy_an_fec_13.0=1 +phy_an_fec_14.0=1 +phy_an_fec_15.0=1 +phy_an_fec_16.0=1 +phy_an_fec_17.0=1 +phy_an_fec_18.0=1 +phy_an_fec_19.0=1 +phy_an_fec_20.0=1 +phy_an_fec_21.0=1 +phy_an_fec_22.0=1 +phy_an_fec_23.0=1 +phy_an_fec_24.0=1 +phy_an_fec_25.0=1 +phy_an_fec_26.0=1 +phy_an_fec_27.0=1 +phy_an_fec_28.0=1 +phy_an_fec_29.0=1 +phy_an_fec_30.0=1 +phy_an_fec_31.0=1 +phy_an_fec_32.0=1 +phy_an_fec_34.0=1 +phy_an_fec_38.0=1 +phy_an_fec_39.0=1 +phy_an_fec_40.0=1 +phy_an_fec_41.0=1 +phy_an_fec_42.0=1 +phy_an_fec_43.0=1 +phy_an_fec_44.0=1 +phy_an_fec_45.0=1 +phy_an_fec_46.0=1 +phy_an_fec_47.0=1 +phy_an_fec_48.0=1 +phy_an_fec_49.0=1 +phy_an_fec_50.0=1 +phy_an_fec_51.0=1 +phy_an_fec_52.0=1 +phy_an_fec_53.0=1 +phy_an_fec_54.0=1 +phy_an_fec_55.0=1 +phy_an_fec_56.0=1 +phy_an_fec_57.0=1 +phy_an_fec_58.0=1 +phy_an_fec_59.0=1 +phy_an_fec_60.0=1 +phy_an_fec_61.0=1 +phy_an_fec_62.0=1 +phy_an_fec_63.0=1 +phy_an_fec_64.0=1 +phy_an_fec_65.0=1 +phy_an_fec_68.0=1 +phy_an_fec_69.0=1 +phy_an_fec_70.0=1 +phy_an_fec_71.0=1 +phy_an_fec_72.0=1 +phy_an_fec_73.0=1 +phy_an_fec_74.0=1 +phy_an_fec_75.0=1 +phy_an_fec_76.0=1 +phy_an_fec_77.0=1 +phy_an_fec_78.0=1 +phy_an_fec_79.0=1 +phy_an_fec_80.0=1 +phy_an_fec_81.0=1 +phy_an_fec_82.0=1 +phy_an_fec_83.0=1 +phy_an_fec_84.0=1 +phy_an_fec_85.0=1 +phy_an_fec_86.0=1 +phy_an_fec_87.0=1 +phy_an_fec_88.0=1 +phy_an_fec_89.0=1 +phy_an_fec_90.0=1 +phy_an_fec_91.0=1 +phy_an_fec_92.0=1 +phy_an_fec_93.0=1 +phy_an_fec_94.0=1 +phy_an_fec_95.0=1 +phy_an_fec_96.0=1 +phy_an_fec_97.0=1 +phy_an_fec_98.0=1 +phy_an_fec_99.0=1 +phy_an_fec_102.0=1 +phy_an_fec_103.0=1 +phy_an_fec_104.0=1 +phy_an_fec_105.0=1 +phy_an_fec_106.0=1 +phy_an_fec_107.0=1 +phy_an_fec_108.0=1 +phy_an_fec_109.0=1 +phy_an_fec_110.0=1 +phy_an_fec_111.0=1 +phy_an_fec_112.0=1 +phy_an_fec_113.0=1 +phy_an_fec_114.0=1 +phy_an_fec_115.0=1 +phy_an_fec_116.0=1 +phy_an_fec_117.0=1 +phy_an_fec_118.0=1 +phy_an_fec_119.0=1 +phy_an_fec_120.0=1 +phy_an_fec_121.0=1 +phy_an_fec_122.0=1 +phy_an_fec_123.0=1 +phy_an_fec_124.0=1 +phy_an_fec_125.0=1 +phy_an_fec_126.0=1 +phy_an_fec_127.0=1 +phy_an_fec_128.0=1 +phy_an_fec_129.0=1 +phy_an_fec_130.0=1 +phy_an_fec_131.0=1 +phy_an_fec_132.0=1 +phy_an_fec_133.0=1 +phy_xaui_rx_polarity_flip_1.0=0x1 +phy_xaui_rx_polarity_flip_2.0=0x5 +phy_xaui_rx_polarity_flip_3.0=0x1 +phy_xaui_rx_polarity_flip_4.0=0x7 +phy_xaui_rx_polarity_flip_5.0=0xc +phy_xaui_rx_polarity_flip_6.0=0xf +phy_xaui_rx_polarity_flip_7.0=0xc +phy_xaui_rx_polarity_flip_8.0=0xf +phy_xaui_rx_polarity_flip_34.0=0x0 +phy_xaui_rx_polarity_flip_35.0=0x7 +phy_xaui_rx_polarity_flip_36.0=0x4 +phy_xaui_rx_polarity_flip_37.0=0x7 +phy_xaui_rx_polarity_flip_38.0=0x4 +phy_xaui_rx_polarity_flip_39.0=0x6 +phy_xaui_rx_polarity_flip_40.0=0x1 +phy_xaui_rx_polarity_flip_41.0=0x2 +phy_xaui_rx_polarity_flip_68.0=0xd +phy_xaui_rx_polarity_flip_69.0=0x6 +phy_xaui_rx_polarity_flip_70.0=0x1 +phy_xaui_rx_polarity_flip_71.0=0x8 +phy_xaui_rx_polarity_flip_72.0=0x7 +phy_xaui_rx_polarity_flip_73.0=0xc +phy_xaui_rx_polarity_flip_74.0=0x7 +phy_xaui_rx_polarity_flip_75.0=0x8 +phy_xaui_rx_polarity_flip_102.0=0xb +phy_xaui_rx_polarity_flip_103.0=0xc +phy_xaui_rx_polarity_flip_104.0=0x3 +phy_xaui_rx_polarity_flip_105.0=0xc +phy_xaui_rx_polarity_flip_106.0=0xb +phy_xaui_rx_polarity_flip_107.0=0x5 +phy_xaui_rx_polarity_flip_108.0=0x1 +phy_xaui_rx_polarity_flip_109.0=0x9 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_2.0=0xe +phy_xaui_tx_polarity_flip_3.0=0x2 +phy_xaui_tx_polarity_flip_4.0=0xe +phy_xaui_tx_polarity_flip_5.0=0xc +phy_xaui_tx_polarity_flip_6.0=0xf +phy_xaui_tx_polarity_flip_7.0=0xc +phy_xaui_tx_polarity_flip_8.0=0xf +phy_xaui_tx_polarity_flip_34.0=0x0 +phy_xaui_tx_polarity_flip_35.0=0xe +phy_xaui_tx_polarity_flip_36.0=0x0 +phy_xaui_tx_polarity_flip_37.0=0xe +phy_xaui_tx_polarity_flip_38.0=0xf +phy_xaui_tx_polarity_flip_39.0=0xe +phy_xaui_tx_polarity_flip_40.0=0x6 +phy_xaui_tx_polarity_flip_41.0=0xb +phy_xaui_tx_polarity_flip_68.0=0x9 +phy_xaui_tx_polarity_flip_69.0=0xb +phy_xaui_tx_polarity_flip_70.0=0xd +phy_xaui_tx_polarity_flip_71.0=0x9 +phy_xaui_tx_polarity_flip_72.0=0x6 +phy_xaui_tx_polarity_flip_73.0=0xc +phy_xaui_tx_polarity_flip_74.0=0x9 +phy_xaui_tx_polarity_flip_75.0=0x9 +phy_xaui_tx_polarity_flip_102.0=0x6 +phy_xaui_tx_polarity_flip_103.0=0xb +phy_xaui_tx_polarity_flip_104.0=0x6 +phy_xaui_tx_polarity_flip_105.0=0xb +phy_xaui_tx_polarity_flip_106.0=0x6 +phy_xaui_tx_polarity_flip_107.0=0xf +phy_xaui_tx_polarity_flip_108.0=0x6 +phy_xaui_tx_polarity_flip_109.0=0xc +portmap_1.0=1:100 +portmap_2.0=5:100 +portmap_3.0=9:40 +portmap_4.0=13:40 +portmap_5.0=17:40 +portmap_6.0=21:40 +portmap_7.0=25:40 +portmap_8.0=29:40 +portmap_34.0=33:100 +portmap_35.0=37:100 +portmap_36.0=41:40 +portmap_37.0=45:40 +portmap_38.0=49:40 +portmap_39.0=53:40 +portmap_40.0=57:40 +portmap_41.0=61:40 +portmap_68.0=65:100 +portmap_69.0=69:100 +portmap_70.0=73:40 +portmap_71.0=77:40 +portmap_72.0=81:40 +portmap_73.0=85:40 +portmap_74.0=89:40 +portmap_75.0=93:40 +portmap_102.0=97:100 +portmap_103.0=101:100 +portmap_104.0=105:40 +portmap_105.0=109:40 +portmap_106.0=113:40 +portmap_107.0=117:40 +portmap_108.0=121:40 +portmap_109.0=125:40 +port_phy_addr_1.0=0xff +port_phy_addr_2.0=0xff +port_phy_addr_3.0=0xff +port_phy_addr_4.0=0xff +port_phy_addr_5.0=0xff +port_phy_addr_6.0=0xff +port_phy_addr_7.0=0xff +port_phy_addr_8.0=0xff +port_phy_addr_34.0=0xff +port_phy_addr_35.0=0xff +port_phy_addr_36.0=0xff +port_phy_addr_37.0=0xff +port_phy_addr_38.0=0xff +port_phy_addr_39.0=0xff +port_phy_addr_40.0=0xff +port_phy_addr_41.0=0xff +port_phy_addr_68.0=0xff +port_phy_addr_69.0=0xff +port_phy_addr_70.0=0xff +port_phy_addr_71.0=0xff +port_phy_addr_72.0=0xff +port_phy_addr_73.0=0xff +port_phy_addr_74.0=0xff +port_phy_addr_75.0=0xff +port_phy_addr_102.0=0xff +port_phy_addr_103.0=0xff +port_phy_addr_104.0=0xff +port_phy_addr_105.0=0xff +port_phy_addr_106.0=0xff +port_phy_addr_107.0=0xff +port_phy_addr_108.0=0xff +port_phy_addr_109.0=0xff +xgxs_rx_lane_map_1.0=0x3210 +xgxs_rx_lane_map_2.0=0x3210 +xgxs_rx_lane_map_3.0=0x3210 +xgxs_rx_lane_map_4.0=0x3210 +xgxs_rx_lane_map_5.0=0x0123 +xgxs_rx_lane_map_6.0=0x2301 +xgxs_rx_lane_map_7.0=0x0123 +xgxs_rx_lane_map_8.0=0x2301 +xgxs_rx_lane_map_34.0=0x0123 +xgxs_rx_lane_map_35.0=0x0321 +xgxs_rx_lane_map_36.0=0x0321 +xgxs_rx_lane_map_37.0=0x0321 +xgxs_rx_lane_map_38.0=0x1230 +xgxs_rx_lane_map_39.0=0x2301 +xgxs_rx_lane_map_40.0=0x1230 +xgxs_rx_lane_map_41.0=0x2103 +xgxs_rx_lane_map_68.0=0x1230 +xgxs_rx_lane_map_69.0=0x2301 +xgxs_rx_lane_map_70.0=0x1230 +xgxs_rx_lane_map_71.0=0x2103 +xgxs_rx_lane_map_72.0=0x1230 +xgxs_rx_lane_map_73.0=0x2301 +xgxs_rx_lane_map_74.0=0x1230 +xgxs_rx_lane_map_75.0=0x2103 +xgxs_rx_lane_map_102.0=0x3210 +xgxs_rx_lane_map_103.0=0x3210 +xgxs_rx_lane_map_104.0=0x3210 +xgxs_rx_lane_map_105.0=0x3210 +xgxs_rx_lane_map_106.0=0x3210 +xgxs_rx_lane_map_107.0=0x3210 +xgxs_rx_lane_map_108.0=0x3210 +xgxs_rx_lane_map_109.0=0x3210 +xgxs_tx_lane_map_1.0=0x0321 +xgxs_tx_lane_map_2.0=0x2301 +xgxs_tx_lane_map_3.0=0x0321 +xgxs_tx_lane_map_4.0=0x2301 +xgxs_tx_lane_map_5.0=0x0123 +xgxs_tx_lane_map_6.0=0x0123 +xgxs_tx_lane_map_7.0=0x0123 +xgxs_tx_lane_map_8.0=0x0123 +xgxs_tx_lane_map_34.0=0x2301 +xgxs_tx_lane_map_35.0=0x0321 +xgxs_tx_lane_map_36.0=0x2301 +xgxs_tx_lane_map_37.0=0x0321 +xgxs_tx_lane_map_38.0=0x0123 +xgxs_tx_lane_map_39.0=0x1230 +xgxs_tx_lane_map_40.0=0x2301 +xgxs_tx_lane_map_41.0=0x1032 +xgxs_tx_lane_map_68.0=0x0123 +xgxs_tx_lane_map_69.0=0x1230 +xgxs_tx_lane_map_70.0=0x2301 +xgxs_tx_lane_map_71.0=0x1032 +xgxs_tx_lane_map_72.0=0x0123 +xgxs_tx_lane_map_73.0=0x1230 +xgxs_tx_lane_map_74.0=0x2301 +xgxs_tx_lane_map_75.0=0x1032 +xgxs_tx_lane_map_102.0=0x0321 +xgxs_tx_lane_map_103.0=0x2301 +xgxs_tx_lane_map_104.0=0x0321 +xgxs_tx_lane_map_105.0=0x2301 +xgxs_tx_lane_map_106.0=0x0321 +xgxs_tx_lane_map_107.0=0x2301 +xgxs_tx_lane_map_108.0=0x0321 +xgxs_tx_lane_map_109.0=0x2301 + +# tuning parameters for 25g serdes fiber +serdes_driver_current_1=0xa +serdes_preemphasis_1=0x284008 +serdes_driver_current_2=0xa +serdes_preemphasis_2=0x284008 +serdes_driver_current_3=0x8 +serdes_preemphasis_3=0x185800 +serdes_driver_current_4=0x8 +serdes_preemphasis_4=0x185800 +serdes_driver_current_5=0x8 +serdes_preemphasis_5=0x185800 +serdes_driver_current_6=0x8 +serdes_preemphasis_6=0x185800 +serdes_driver_current_7=0xf +serdes_preemphasis_7=0x205000 +serdes_driver_current_8=0xf +serdes_preemphasis_8=0x205000 +serdes_driver_current_34=0xd +serdes_preemphasis_34=0x303808 +serdes_driver_current_35=0xd +serdes_preemphasis_35=0x303808 +serdes_driver_current_36=0xf +serdes_preemphasis_36=0x205000 +serdes_driver_current_37=0xf +serdes_preemphasis_37=0x205000 +serdes_driver_current_38=0x8 +serdes_preemphasis_38=0x185800 +serdes_driver_current_39=0x8 +serdes_preemphasis_39=0x185800 +serdes_driver_current_40=0x8 +serdes_preemphasis_40=0x185800 +serdes_driver_current_41=0x8 +serdes_preemphasis_41=0x185800 +serdes_driver_current_68=0xf +serdes_preemphasis_68=0x373108 +serdes_driver_current_69=0xf +serdes_preemphasis_69=0x373108 +serdes_driver_current_70=0x4 +serdes_preemphasis_70=0x145c00 +serdes_driver_current_71=0x4 +serdes_preemphasis_71=0x145c00 +serdes_driver_current_72=0x4 +serdes_preemphasis_72=0x145c00 +serdes_driver_current_73=0x4 +serdes_preemphasis_73=0x145c00 +serdes_driver_current_74=0x4 +serdes_preemphasis_74=0x145c00 +serdes_driver_current_75=0x4 +serdes_preemphasis_75=0x145c00 +serdes_driver_current_102=0xa +serdes_preemphasis_102=0x284008 +serdes_driver_current_103=0xa +serdes_preemphasis_103=0x284008 +serdes_driver_current_104=0x4 +serdes_preemphasis_104=0x145c00 +serdes_driver_current_105=0x4 +serdes_preemphasis_105=0x145c00 +serdes_driver_current_106=0x4 +serdes_preemphasis_106=0x145c00 +serdes_driver_current_107=0x4 +serdes_preemphasis_107=0x145c00 +serdes_driver_current_108=0x4 +serdes_preemphasis_108=0x145c00 +serdes_driver_current_109=0x4 +serdes_preemphasis_109=0x145c00 + +mmu_init_config="MSFT-TH-Tier1" diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/buffers.json.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..0869e63968ac --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/buffers_defaults_t0.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,128,4) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/buffers_defaults_t1.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..80e96bdceca7 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/buffers_defaults_t1.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,128,4) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/pg_profile_lookup.ini b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/pg_profile_lookup.ini new file mode 100644 index 000000000000..673df369a9bb --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 0 2288 + 25000 5m 1248 2288 53248 0 2288 + 40000 5m 1248 2288 66560 0 2288 + 50000 5m 1248 2288 90272 0 2288 + 100000 5m 1248 2288 165568 0 2288 + 10000 40m 1248 2288 37024 0 2288 + 25000 40m 1248 2288 53248 0 2288 + 40000 40m 1248 2288 71552 0 2288 + 50000 40m 1248 2288 96096 0 2288 + 100000 40m 1248 2288 177632 0 2288 + 10000 300m 1248 2288 46176 0 2288 + 25000 300m 1248 2288 79040 0 2288 + 40000 300m 1248 2288 108160 0 2288 + 50000 300m 1248 2288 141856 0 2288 + 100000 300m 1248 2288 268736 0 2288 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/port_config.ini b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/port_config.ini new file mode 100644 index 000000000000..bfe4a721141d --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 33,34,35,36 Ethernet1/1 1 +Ethernet4 37,38,39,40 Ethernet2/1 2 +Ethernet8 41,42,43,44 Ethernet3/1 3 +Ethernet12 45,46,47,48 Ethernet4/1 4 +Ethernet16 49,50,51,52 Ethernet5/1 5 +Ethernet20 53,54,55,56 Ethernet6/1 6 +Ethernet24 57,58,59,60 Ethernet7/1 7 +Ethernet28 61,62,63,64 Ethernet8/1 8 +Ethernet32 65,66,67,68 Ethernet9/1 9 +Ethernet36 69,70,71,72 Ethernet10/1 10 +Ethernet40 73,74,75,76 Ethernet11/1 11 +Ethernet44 77,78,79,80 Ethernet12/1 12 +Ethernet48 81,82,83,84 Ethernet13/1 13 +Ethernet52 85,86,87,88 Ethernet14/1 14 +Ethernet56 89,90,91,92 Ethernet15/1 15 +Ethernet60 93,94,95,96 Ethernet16/1 16 +Ethernet64 97,98,99,100 Ethernet17/1 17 +Ethernet68 101,102,103,104 Ethernet18/1 18 +Ethernet72 105,106,107,108 Ethernet19/1 19 +Ethernet76 109,110,111,112 Ethernet20/1 20 +Ethernet80 113,114,115,116 Ethernet21/1 21 +Ethernet84 117,118,119,120 Ethernet22/1 22 +Ethernet88 121,122,123,124 Ethernet23/1 23 +Ethernet92 125,126,127,128 Ethernet24/1 24 +Ethernet96 1,2,3,4 Ethernet25/1 25 +Ethernet100 5,6,7,8 Ethernet26/1 26 +Ethernet104 9,10,11,12 Ethernet27/1 27 +Ethernet108 13,14,15,16 Ethernet28/1 28 +Ethernet112 17,18,19,20 Ethernet29/1 29 +Ethernet116 21,22,23,24 Ethernet30/1 30 +Ethernet120 25,26,27,28 Ethernet31/1 31 +Ethernet124 29,30,31,32 Ethernet32/1 32 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/qos.json.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/qos.json.j2 new file mode 100644 index 000000000000..34002048afdb --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/qos.json.j2 @@ -0,0 +1,21 @@ +{%- macro generate_wred_profiles() %} + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "250000", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, +{%- endmacro %} + +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/sai.profile.j2 b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/sai.profile.j2 new file mode 100644 index 000000000000..5a50185247a0 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/sai.profile.j2 @@ -0,0 +1,14 @@ +{# Get sai.profile based on switch_role #} +{%- if DEVICE_METADATA is defined -%} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] -%} +{%- if 'torrouter' in switch_role.lower() %} +{% set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-a7060-cx32s-32x40G-t0.config.bcm' -%} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-a7060-cx32s-32x40G-t1.config.bcm' -%} +{%- endif %} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-a7060-cx32s-32x40G-t1.config.bcm' -%} +{%- endif %} +{# Write the contents of sai_ profile_filename to sai.profile file #} +{{ sai_profile_contents }} +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/th-a7060-cx32s-32x40G-t0.config.bcm b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/th-a7060-cx32s-32x40G-t0.config.bcm new file mode 100644 index 000000000000..c011ad93f4d7 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/th-a7060-cx32s-32x40G-t0.config.bcm @@ -0,0 +1,444 @@ +# Arista 7060CX-32S + +phy_an_allow_pll_change=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +higig2_hdr_mode=1 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +l2xmsg_mode=1 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +os=unix +oversubscribe_mode=1 +ptp_bs_fref.0=25000000 +ptp_ts_pll_fref.0=25000000 +robust_hash_disable_egress_vlan.0=1 +robust_hash_disable_mpls.0=1 +robust_hash_disable_vlan.0=1 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 +pbmp_xport_xe.0=0x7ffffffffffffffffffffffffffffffffe +phy_an_allow_pll_change_hg.0=0 +phy_an_c73_1.0=1 +phy_an_c73_2.0=1 +phy_an_c73_3.0=1 +phy_an_c73_4.0=1 +phy_an_c73_5.0=1 +phy_an_c73_6.0=1 +phy_an_c73_7.0=1 +phy_an_c73_8.0=1 +phy_an_c73_34.0=1 +phy_an_c73_35.0=1 +phy_an_c73_36.0=1 +phy_an_c73_37.0=1 +phy_an_c73_38.0=1 +phy_an_c73_39.0=1 +phy_an_c73_40.0=1 +phy_an_c73_41.0=1 +phy_an_c73_68.0=1 +phy_an_c73_69.0=1 +phy_an_c73_70.0=1 +phy_an_c73_71.0=1 +phy_an_c73_72.0=1 +phy_an_c73_73.0=1 +phy_an_c73_74.0=1 +phy_an_c73_75.0=1 +phy_an_c73_102.0=1 +phy_an_c73_103.0=1 +phy_an_c73_104.0=1 +phy_an_c73_105.0=1 +phy_an_c73_106.0=1 +phy_an_c73_107.0=1 +phy_an_c73_108.0=1 +phy_an_c73_109.0=1 +phy_an_fec_1.0=1 +phy_an_fec_2.0=1 +phy_an_fec_3.0=1 +phy_an_fec_4.0=1 +phy_an_fec_5.0=1 +phy_an_fec_6.0=1 +phy_an_fec_7.0=1 +phy_an_fec_8.0=1 +phy_an_fec_9.0=1 +phy_an_fec_10.0=1 +phy_an_fec_11.0=1 +phy_an_fec_12.0=1 +phy_an_fec_13.0=1 +phy_an_fec_14.0=1 +phy_an_fec_15.0=1 +phy_an_fec_16.0=1 +phy_an_fec_17.0=1 +phy_an_fec_18.0=1 +phy_an_fec_19.0=1 +phy_an_fec_20.0=1 +phy_an_fec_21.0=1 +phy_an_fec_22.0=1 +phy_an_fec_23.0=1 +phy_an_fec_24.0=1 +phy_an_fec_25.0=1 +phy_an_fec_26.0=1 +phy_an_fec_27.0=1 +phy_an_fec_28.0=1 +phy_an_fec_29.0=1 +phy_an_fec_30.0=1 +phy_an_fec_31.0=1 +phy_an_fec_32.0=1 +phy_an_fec_34.0=1 +phy_an_fec_38.0=1 +phy_an_fec_39.0=1 +phy_an_fec_40.0=1 +phy_an_fec_41.0=1 +phy_an_fec_42.0=1 +phy_an_fec_43.0=1 +phy_an_fec_44.0=1 +phy_an_fec_45.0=1 +phy_an_fec_46.0=1 +phy_an_fec_47.0=1 +phy_an_fec_48.0=1 +phy_an_fec_49.0=1 +phy_an_fec_50.0=1 +phy_an_fec_51.0=1 +phy_an_fec_52.0=1 +phy_an_fec_53.0=1 +phy_an_fec_54.0=1 +phy_an_fec_55.0=1 +phy_an_fec_56.0=1 +phy_an_fec_57.0=1 +phy_an_fec_58.0=1 +phy_an_fec_59.0=1 +phy_an_fec_60.0=1 +phy_an_fec_61.0=1 +phy_an_fec_62.0=1 +phy_an_fec_63.0=1 +phy_an_fec_64.0=1 +phy_an_fec_65.0=1 +phy_an_fec_68.0=1 +phy_an_fec_69.0=1 +phy_an_fec_70.0=1 +phy_an_fec_71.0=1 +phy_an_fec_72.0=1 +phy_an_fec_73.0=1 +phy_an_fec_74.0=1 +phy_an_fec_75.0=1 +phy_an_fec_76.0=1 +phy_an_fec_77.0=1 +phy_an_fec_78.0=1 +phy_an_fec_79.0=1 +phy_an_fec_80.0=1 +phy_an_fec_81.0=1 +phy_an_fec_82.0=1 +phy_an_fec_83.0=1 +phy_an_fec_84.0=1 +phy_an_fec_85.0=1 +phy_an_fec_86.0=1 +phy_an_fec_87.0=1 +phy_an_fec_88.0=1 +phy_an_fec_89.0=1 +phy_an_fec_90.0=1 +phy_an_fec_91.0=1 +phy_an_fec_92.0=1 +phy_an_fec_93.0=1 +phy_an_fec_94.0=1 +phy_an_fec_95.0=1 +phy_an_fec_96.0=1 +phy_an_fec_97.0=1 +phy_an_fec_98.0=1 +phy_an_fec_99.0=1 +phy_an_fec_102.0=1 +phy_an_fec_103.0=1 +phy_an_fec_104.0=1 +phy_an_fec_105.0=1 +phy_an_fec_106.0=1 +phy_an_fec_107.0=1 +phy_an_fec_108.0=1 +phy_an_fec_109.0=1 +phy_an_fec_110.0=1 +phy_an_fec_111.0=1 +phy_an_fec_112.0=1 +phy_an_fec_113.0=1 +phy_an_fec_114.0=1 +phy_an_fec_115.0=1 +phy_an_fec_116.0=1 +phy_an_fec_117.0=1 +phy_an_fec_118.0=1 +phy_an_fec_119.0=1 +phy_an_fec_120.0=1 +phy_an_fec_121.0=1 +phy_an_fec_122.0=1 +phy_an_fec_123.0=1 +phy_an_fec_124.0=1 +phy_an_fec_125.0=1 +phy_an_fec_126.0=1 +phy_an_fec_127.0=1 +phy_an_fec_128.0=1 +phy_an_fec_129.0=1 +phy_an_fec_130.0=1 +phy_an_fec_131.0=1 +phy_an_fec_132.0=1 +phy_an_fec_133.0=1 +phy_xaui_rx_polarity_flip_1.0=0x1 +phy_xaui_rx_polarity_flip_2.0=0x5 +phy_xaui_rx_polarity_flip_3.0=0x1 +phy_xaui_rx_polarity_flip_4.0=0x7 +phy_xaui_rx_polarity_flip_5.0=0xc +phy_xaui_rx_polarity_flip_6.0=0xf +phy_xaui_rx_polarity_flip_7.0=0xc +phy_xaui_rx_polarity_flip_8.0=0xf +phy_xaui_rx_polarity_flip_34.0=0x0 +phy_xaui_rx_polarity_flip_35.0=0x7 +phy_xaui_rx_polarity_flip_36.0=0x4 +phy_xaui_rx_polarity_flip_37.0=0x7 +phy_xaui_rx_polarity_flip_38.0=0x4 +phy_xaui_rx_polarity_flip_39.0=0x6 +phy_xaui_rx_polarity_flip_40.0=0x1 +phy_xaui_rx_polarity_flip_41.0=0x2 +phy_xaui_rx_polarity_flip_68.0=0xd +phy_xaui_rx_polarity_flip_69.0=0x6 +phy_xaui_rx_polarity_flip_70.0=0x1 +phy_xaui_rx_polarity_flip_71.0=0x8 +phy_xaui_rx_polarity_flip_72.0=0x7 +phy_xaui_rx_polarity_flip_73.0=0xc +phy_xaui_rx_polarity_flip_74.0=0x7 +phy_xaui_rx_polarity_flip_75.0=0x8 +phy_xaui_rx_polarity_flip_102.0=0xb +phy_xaui_rx_polarity_flip_103.0=0xc +phy_xaui_rx_polarity_flip_104.0=0x3 +phy_xaui_rx_polarity_flip_105.0=0xc +phy_xaui_rx_polarity_flip_106.0=0xb +phy_xaui_rx_polarity_flip_107.0=0x5 +phy_xaui_rx_polarity_flip_108.0=0x1 +phy_xaui_rx_polarity_flip_109.0=0x9 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_2.0=0xe +phy_xaui_tx_polarity_flip_3.0=0x2 +phy_xaui_tx_polarity_flip_4.0=0xe +phy_xaui_tx_polarity_flip_5.0=0xc +phy_xaui_tx_polarity_flip_6.0=0xf +phy_xaui_tx_polarity_flip_7.0=0xc +phy_xaui_tx_polarity_flip_8.0=0xf +phy_xaui_tx_polarity_flip_34.0=0x0 +phy_xaui_tx_polarity_flip_35.0=0xe +phy_xaui_tx_polarity_flip_36.0=0x0 +phy_xaui_tx_polarity_flip_37.0=0xe +phy_xaui_tx_polarity_flip_38.0=0xf +phy_xaui_tx_polarity_flip_39.0=0xe +phy_xaui_tx_polarity_flip_40.0=0x6 +phy_xaui_tx_polarity_flip_41.0=0xb +phy_xaui_tx_polarity_flip_68.0=0x9 +phy_xaui_tx_polarity_flip_69.0=0xb +phy_xaui_tx_polarity_flip_70.0=0xd +phy_xaui_tx_polarity_flip_71.0=0x9 +phy_xaui_tx_polarity_flip_72.0=0x6 +phy_xaui_tx_polarity_flip_73.0=0xc +phy_xaui_tx_polarity_flip_74.0=0x9 +phy_xaui_tx_polarity_flip_75.0=0x9 +phy_xaui_tx_polarity_flip_102.0=0x6 +phy_xaui_tx_polarity_flip_103.0=0xb +phy_xaui_tx_polarity_flip_104.0=0x6 +phy_xaui_tx_polarity_flip_105.0=0xb +phy_xaui_tx_polarity_flip_106.0=0x6 +phy_xaui_tx_polarity_flip_107.0=0xf +phy_xaui_tx_polarity_flip_108.0=0x6 +phy_xaui_tx_polarity_flip_109.0=0xc +portmap_1.0=1:40 +portmap_2.0=5:40 +portmap_3.0=9:40 +portmap_4.0=13:40 +portmap_5.0=17:40 +portmap_6.0=21:40 +portmap_7.0=25:40 +portmap_8.0=29:40 +portmap_34.0=33:40 +portmap_35.0=37:40 +portmap_36.0=41:40 +portmap_37.0=45:40 +portmap_38.0=49:40 +portmap_39.0=53:40 +portmap_40.0=57:40 +portmap_41.0=61:40 +portmap_68.0=65:40 +portmap_69.0=69:40 +portmap_70.0=73:40 +portmap_71.0=77:40 +portmap_72.0=81:40 +portmap_73.0=85:40 +portmap_74.0=89:40 +portmap_75.0=93:40 +portmap_102.0=97:40 +portmap_103.0=101:40 +portmap_104.0=105:40 +portmap_105.0=109:40 +portmap_106.0=113:40 +portmap_107.0=117:40 +portmap_108.0=121:40 +portmap_109.0=125:40 +port_phy_addr_1.0=0xff +port_phy_addr_2.0=0xff +port_phy_addr_3.0=0xff +port_phy_addr_4.0=0xff +port_phy_addr_5.0=0xff +port_phy_addr_6.0=0xff +port_phy_addr_7.0=0xff +port_phy_addr_8.0=0xff +port_phy_addr_34.0=0xff +port_phy_addr_35.0=0xff +port_phy_addr_36.0=0xff +port_phy_addr_37.0=0xff +port_phy_addr_38.0=0xff +port_phy_addr_39.0=0xff +port_phy_addr_40.0=0xff +port_phy_addr_41.0=0xff +port_phy_addr_68.0=0xff +port_phy_addr_69.0=0xff +port_phy_addr_70.0=0xff +port_phy_addr_71.0=0xff +port_phy_addr_72.0=0xff +port_phy_addr_73.0=0xff +port_phy_addr_74.0=0xff +port_phy_addr_75.0=0xff +port_phy_addr_102.0=0xff +port_phy_addr_103.0=0xff +port_phy_addr_104.0=0xff +port_phy_addr_105.0=0xff +port_phy_addr_106.0=0xff +port_phy_addr_107.0=0xff +port_phy_addr_108.0=0xff +port_phy_addr_109.0=0xff +xgxs_rx_lane_map_1.0=0x3210 +xgxs_rx_lane_map_2.0=0x3210 +xgxs_rx_lane_map_3.0=0x3210 +xgxs_rx_lane_map_4.0=0x3210 +xgxs_rx_lane_map_5.0=0x0123 +xgxs_rx_lane_map_6.0=0x2301 +xgxs_rx_lane_map_7.0=0x0123 +xgxs_rx_lane_map_8.0=0x2301 +xgxs_rx_lane_map_34.0=0x0123 +xgxs_rx_lane_map_35.0=0x0321 +xgxs_rx_lane_map_36.0=0x0321 +xgxs_rx_lane_map_37.0=0x0321 +xgxs_rx_lane_map_38.0=0x1230 +xgxs_rx_lane_map_39.0=0x2301 +xgxs_rx_lane_map_40.0=0x1230 +xgxs_rx_lane_map_41.0=0x2103 +xgxs_rx_lane_map_68.0=0x1230 +xgxs_rx_lane_map_69.0=0x2301 +xgxs_rx_lane_map_70.0=0x1230 +xgxs_rx_lane_map_71.0=0x2103 +xgxs_rx_lane_map_72.0=0x1230 +xgxs_rx_lane_map_73.0=0x2301 +xgxs_rx_lane_map_74.0=0x1230 +xgxs_rx_lane_map_75.0=0x2103 +xgxs_rx_lane_map_102.0=0x3210 +xgxs_rx_lane_map_103.0=0x3210 +xgxs_rx_lane_map_104.0=0x3210 +xgxs_rx_lane_map_105.0=0x3210 +xgxs_rx_lane_map_106.0=0x3210 +xgxs_rx_lane_map_107.0=0x3210 +xgxs_rx_lane_map_108.0=0x3210 +xgxs_rx_lane_map_109.0=0x3210 +xgxs_tx_lane_map_1.0=0x0321 +xgxs_tx_lane_map_2.0=0x2301 +xgxs_tx_lane_map_3.0=0x0321 +xgxs_tx_lane_map_4.0=0x2301 +xgxs_tx_lane_map_5.0=0x0123 +xgxs_tx_lane_map_6.0=0x0123 +xgxs_tx_lane_map_7.0=0x0123 +xgxs_tx_lane_map_8.0=0x0123 +xgxs_tx_lane_map_34.0=0x2301 +xgxs_tx_lane_map_35.0=0x0321 +xgxs_tx_lane_map_36.0=0x2301 +xgxs_tx_lane_map_37.0=0x0321 +xgxs_tx_lane_map_38.0=0x0123 +xgxs_tx_lane_map_39.0=0x1230 +xgxs_tx_lane_map_40.0=0x2301 +xgxs_tx_lane_map_41.0=0x1032 +xgxs_tx_lane_map_68.0=0x0123 +xgxs_tx_lane_map_69.0=0x1230 +xgxs_tx_lane_map_70.0=0x2301 +xgxs_tx_lane_map_71.0=0x1032 +xgxs_tx_lane_map_72.0=0x0123 +xgxs_tx_lane_map_73.0=0x1230 +xgxs_tx_lane_map_74.0=0x2301 +xgxs_tx_lane_map_75.0=0x1032 +xgxs_tx_lane_map_102.0=0x0321 +xgxs_tx_lane_map_103.0=0x2301 +xgxs_tx_lane_map_104.0=0x0321 +xgxs_tx_lane_map_105.0=0x2301 +xgxs_tx_lane_map_106.0=0x0321 +xgxs_tx_lane_map_107.0=0x2301 +xgxs_tx_lane_map_108.0=0x0321 +xgxs_tx_lane_map_109.0=0x2301 +serdes_driver_current_1=0x4 +serdes_preemphasis_1=0x145c00 +serdes_driver_current_2=0x4 +serdes_preemphasis_2=0x145c00 +serdes_driver_current_3=0x8 +serdes_preemphasis_3=0x185800 +serdes_driver_current_4=0x8 +serdes_preemphasis_4=0x185800 +serdes_driver_current_5=0x8 +serdes_preemphasis_5=0x185800 +serdes_driver_current_6=0x8 +serdes_preemphasis_6=0x185800 +serdes_driver_current_7=0xf +serdes_preemphasis_7=0x205000 +serdes_driver_current_8=0xf +serdes_preemphasis_8=0x205000 +serdes_driver_current_34=0xf +serdes_preemphasis_34=0x205000 +serdes_driver_current_35=0xf +serdes_preemphasis_35=0x205000 +serdes_driver_current_36=0xf +serdes_preemphasis_36=0x205000 +serdes_driver_current_37=0xf +serdes_preemphasis_37=0x205000 +serdes_driver_current_38=0x8 +serdes_preemphasis_38=0x185800 +serdes_driver_current_39=0x8 +serdes_preemphasis_39=0x185800 +serdes_driver_current_40=0x8 +serdes_preemphasis_40=0x185800 +serdes_driver_current_41=0x8 +serdes_preemphasis_41=0x185800 +serdes_driver_current_68=0x4 +serdes_preemphasis_68=0x145c00 +serdes_driver_current_69=0x4 +serdes_preemphasis_69=0x145c00 +serdes_driver_current_70=0x4 +serdes_preemphasis_70=0x145c00 +serdes_driver_current_71=0x4 +serdes_preemphasis_71=0x145c00 +serdes_driver_current_72=0x4 +serdes_preemphasis_72=0x145c00 +serdes_driver_current_73=0x4 +serdes_preemphasis_73=0x145c00 +serdes_driver_current_74=0x4 +serdes_preemphasis_74=0x145c00 +serdes_driver_current_75=0x4 +serdes_preemphasis_75=0x145c00 +serdes_driver_current_102=0x4 +serdes_preemphasis_102=0x145c00 +serdes_driver_current_103=0x4 +serdes_preemphasis_103=0x145c00 +serdes_driver_current_104=0x4 +serdes_preemphasis_104=0x145c00 +serdes_driver_current_105=0x4 +serdes_preemphasis_105=0x145c00 +serdes_driver_current_106=0x4 +serdes_preemphasis_106=0x145c00 +serdes_driver_current_107=0x4 +serdes_preemphasis_107=0x145c00 +serdes_driver_current_108=0x4 +serdes_preemphasis_108=0x145c00 +serdes_driver_current_109=0x4 +serdes_preemphasis_109=0x145c00 + +mmu_init_config="MSFT-TH-Tier0" diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/th-a7060-cx32s-32x40G-t1.config.bcm b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/th-a7060-cx32s-32x40G-t1.config.bcm new file mode 100644 index 000000000000..65a7d57b5513 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-Q32/th-a7060-cx32s-32x40G-t1.config.bcm @@ -0,0 +1,444 @@ +# Arista 7060CX-32S + +phy_an_allow_pll_change=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +higig2_hdr_mode=1 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +l2xmsg_mode=1 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +os=unix +oversubscribe_mode=1 +ptp_bs_fref.0=25000000 +ptp_ts_pll_fref.0=25000000 +robust_hash_disable_egress_vlan.0=1 +robust_hash_disable_mpls.0=1 +robust_hash_disable_vlan.0=1 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 +pbmp_xport_xe.0=0x7ffffffffffffffffffffffffffffffffe +phy_an_allow_pll_change_hg.0=0 +phy_an_c73_1.0=1 +phy_an_c73_2.0=1 +phy_an_c73_3.0=1 +phy_an_c73_4.0=1 +phy_an_c73_5.0=1 +phy_an_c73_6.0=1 +phy_an_c73_7.0=1 +phy_an_c73_8.0=1 +phy_an_c73_34.0=1 +phy_an_c73_35.0=1 +phy_an_c73_36.0=1 +phy_an_c73_37.0=1 +phy_an_c73_38.0=1 +phy_an_c73_39.0=1 +phy_an_c73_40.0=1 +phy_an_c73_41.0=1 +phy_an_c73_68.0=1 +phy_an_c73_69.0=1 +phy_an_c73_70.0=1 +phy_an_c73_71.0=1 +phy_an_c73_72.0=1 +phy_an_c73_73.0=1 +phy_an_c73_74.0=1 +phy_an_c73_75.0=1 +phy_an_c73_102.0=1 +phy_an_c73_103.0=1 +phy_an_c73_104.0=1 +phy_an_c73_105.0=1 +phy_an_c73_106.0=1 +phy_an_c73_107.0=1 +phy_an_c73_108.0=1 +phy_an_c73_109.0=1 +phy_an_fec_1.0=1 +phy_an_fec_2.0=1 +phy_an_fec_3.0=1 +phy_an_fec_4.0=1 +phy_an_fec_5.0=1 +phy_an_fec_6.0=1 +phy_an_fec_7.0=1 +phy_an_fec_8.0=1 +phy_an_fec_9.0=1 +phy_an_fec_10.0=1 +phy_an_fec_11.0=1 +phy_an_fec_12.0=1 +phy_an_fec_13.0=1 +phy_an_fec_14.0=1 +phy_an_fec_15.0=1 +phy_an_fec_16.0=1 +phy_an_fec_17.0=1 +phy_an_fec_18.0=1 +phy_an_fec_19.0=1 +phy_an_fec_20.0=1 +phy_an_fec_21.0=1 +phy_an_fec_22.0=1 +phy_an_fec_23.0=1 +phy_an_fec_24.0=1 +phy_an_fec_25.0=1 +phy_an_fec_26.0=1 +phy_an_fec_27.0=1 +phy_an_fec_28.0=1 +phy_an_fec_29.0=1 +phy_an_fec_30.0=1 +phy_an_fec_31.0=1 +phy_an_fec_32.0=1 +phy_an_fec_34.0=1 +phy_an_fec_38.0=1 +phy_an_fec_39.0=1 +phy_an_fec_40.0=1 +phy_an_fec_41.0=1 +phy_an_fec_42.0=1 +phy_an_fec_43.0=1 +phy_an_fec_44.0=1 +phy_an_fec_45.0=1 +phy_an_fec_46.0=1 +phy_an_fec_47.0=1 +phy_an_fec_48.0=1 +phy_an_fec_49.0=1 +phy_an_fec_50.0=1 +phy_an_fec_51.0=1 +phy_an_fec_52.0=1 +phy_an_fec_53.0=1 +phy_an_fec_54.0=1 +phy_an_fec_55.0=1 +phy_an_fec_56.0=1 +phy_an_fec_57.0=1 +phy_an_fec_58.0=1 +phy_an_fec_59.0=1 +phy_an_fec_60.0=1 +phy_an_fec_61.0=1 +phy_an_fec_62.0=1 +phy_an_fec_63.0=1 +phy_an_fec_64.0=1 +phy_an_fec_65.0=1 +phy_an_fec_68.0=1 +phy_an_fec_69.0=1 +phy_an_fec_70.0=1 +phy_an_fec_71.0=1 +phy_an_fec_72.0=1 +phy_an_fec_73.0=1 +phy_an_fec_74.0=1 +phy_an_fec_75.0=1 +phy_an_fec_76.0=1 +phy_an_fec_77.0=1 +phy_an_fec_78.0=1 +phy_an_fec_79.0=1 +phy_an_fec_80.0=1 +phy_an_fec_81.0=1 +phy_an_fec_82.0=1 +phy_an_fec_83.0=1 +phy_an_fec_84.0=1 +phy_an_fec_85.0=1 +phy_an_fec_86.0=1 +phy_an_fec_87.0=1 +phy_an_fec_88.0=1 +phy_an_fec_89.0=1 +phy_an_fec_90.0=1 +phy_an_fec_91.0=1 +phy_an_fec_92.0=1 +phy_an_fec_93.0=1 +phy_an_fec_94.0=1 +phy_an_fec_95.0=1 +phy_an_fec_96.0=1 +phy_an_fec_97.0=1 +phy_an_fec_98.0=1 +phy_an_fec_99.0=1 +phy_an_fec_102.0=1 +phy_an_fec_103.0=1 +phy_an_fec_104.0=1 +phy_an_fec_105.0=1 +phy_an_fec_106.0=1 +phy_an_fec_107.0=1 +phy_an_fec_108.0=1 +phy_an_fec_109.0=1 +phy_an_fec_110.0=1 +phy_an_fec_111.0=1 +phy_an_fec_112.0=1 +phy_an_fec_113.0=1 +phy_an_fec_114.0=1 +phy_an_fec_115.0=1 +phy_an_fec_116.0=1 +phy_an_fec_117.0=1 +phy_an_fec_118.0=1 +phy_an_fec_119.0=1 +phy_an_fec_120.0=1 +phy_an_fec_121.0=1 +phy_an_fec_122.0=1 +phy_an_fec_123.0=1 +phy_an_fec_124.0=1 +phy_an_fec_125.0=1 +phy_an_fec_126.0=1 +phy_an_fec_127.0=1 +phy_an_fec_128.0=1 +phy_an_fec_129.0=1 +phy_an_fec_130.0=1 +phy_an_fec_131.0=1 +phy_an_fec_132.0=1 +phy_an_fec_133.0=1 +phy_xaui_rx_polarity_flip_1.0=0x1 +phy_xaui_rx_polarity_flip_2.0=0x5 +phy_xaui_rx_polarity_flip_3.0=0x1 +phy_xaui_rx_polarity_flip_4.0=0x7 +phy_xaui_rx_polarity_flip_5.0=0xc +phy_xaui_rx_polarity_flip_6.0=0xf +phy_xaui_rx_polarity_flip_7.0=0xc +phy_xaui_rx_polarity_flip_8.0=0xf +phy_xaui_rx_polarity_flip_34.0=0x0 +phy_xaui_rx_polarity_flip_35.0=0x7 +phy_xaui_rx_polarity_flip_36.0=0x4 +phy_xaui_rx_polarity_flip_37.0=0x7 +phy_xaui_rx_polarity_flip_38.0=0x4 +phy_xaui_rx_polarity_flip_39.0=0x6 +phy_xaui_rx_polarity_flip_40.0=0x1 +phy_xaui_rx_polarity_flip_41.0=0x2 +phy_xaui_rx_polarity_flip_68.0=0xd +phy_xaui_rx_polarity_flip_69.0=0x6 +phy_xaui_rx_polarity_flip_70.0=0x1 +phy_xaui_rx_polarity_flip_71.0=0x8 +phy_xaui_rx_polarity_flip_72.0=0x7 +phy_xaui_rx_polarity_flip_73.0=0xc +phy_xaui_rx_polarity_flip_74.0=0x7 +phy_xaui_rx_polarity_flip_75.0=0x8 +phy_xaui_rx_polarity_flip_102.0=0xb +phy_xaui_rx_polarity_flip_103.0=0xc +phy_xaui_rx_polarity_flip_104.0=0x3 +phy_xaui_rx_polarity_flip_105.0=0xc +phy_xaui_rx_polarity_flip_106.0=0xb +phy_xaui_rx_polarity_flip_107.0=0x5 +phy_xaui_rx_polarity_flip_108.0=0x1 +phy_xaui_rx_polarity_flip_109.0=0x9 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_2.0=0xe +phy_xaui_tx_polarity_flip_3.0=0x2 +phy_xaui_tx_polarity_flip_4.0=0xe +phy_xaui_tx_polarity_flip_5.0=0xc +phy_xaui_tx_polarity_flip_6.0=0xf +phy_xaui_tx_polarity_flip_7.0=0xc +phy_xaui_tx_polarity_flip_8.0=0xf +phy_xaui_tx_polarity_flip_34.0=0x0 +phy_xaui_tx_polarity_flip_35.0=0xe +phy_xaui_tx_polarity_flip_36.0=0x0 +phy_xaui_tx_polarity_flip_37.0=0xe +phy_xaui_tx_polarity_flip_38.0=0xf +phy_xaui_tx_polarity_flip_39.0=0xe +phy_xaui_tx_polarity_flip_40.0=0x6 +phy_xaui_tx_polarity_flip_41.0=0xb +phy_xaui_tx_polarity_flip_68.0=0x9 +phy_xaui_tx_polarity_flip_69.0=0xb +phy_xaui_tx_polarity_flip_70.0=0xd +phy_xaui_tx_polarity_flip_71.0=0x9 +phy_xaui_tx_polarity_flip_72.0=0x6 +phy_xaui_tx_polarity_flip_73.0=0xc +phy_xaui_tx_polarity_flip_74.0=0x9 +phy_xaui_tx_polarity_flip_75.0=0x9 +phy_xaui_tx_polarity_flip_102.0=0x6 +phy_xaui_tx_polarity_flip_103.0=0xb +phy_xaui_tx_polarity_flip_104.0=0x6 +phy_xaui_tx_polarity_flip_105.0=0xb +phy_xaui_tx_polarity_flip_106.0=0x6 +phy_xaui_tx_polarity_flip_107.0=0xf +phy_xaui_tx_polarity_flip_108.0=0x6 +phy_xaui_tx_polarity_flip_109.0=0xc +portmap_1.0=1:40 +portmap_2.0=5:40 +portmap_3.0=9:40 +portmap_4.0=13:40 +portmap_5.0=17:40 +portmap_6.0=21:40 +portmap_7.0=25:40 +portmap_8.0=29:40 +portmap_34.0=33:40 +portmap_35.0=37:40 +portmap_36.0=41:40 +portmap_37.0=45:40 +portmap_38.0=49:40 +portmap_39.0=53:40 +portmap_40.0=57:40 +portmap_41.0=61:40 +portmap_68.0=65:40 +portmap_69.0=69:40 +portmap_70.0=73:40 +portmap_71.0=77:40 +portmap_72.0=81:40 +portmap_73.0=85:40 +portmap_74.0=89:40 +portmap_75.0=93:40 +portmap_102.0=97:40 +portmap_103.0=101:40 +portmap_104.0=105:40 +portmap_105.0=109:40 +portmap_106.0=113:40 +portmap_107.0=117:40 +portmap_108.0=121:40 +portmap_109.0=125:40 +port_phy_addr_1.0=0xff +port_phy_addr_2.0=0xff +port_phy_addr_3.0=0xff +port_phy_addr_4.0=0xff +port_phy_addr_5.0=0xff +port_phy_addr_6.0=0xff +port_phy_addr_7.0=0xff +port_phy_addr_8.0=0xff +port_phy_addr_34.0=0xff +port_phy_addr_35.0=0xff +port_phy_addr_36.0=0xff +port_phy_addr_37.0=0xff +port_phy_addr_38.0=0xff +port_phy_addr_39.0=0xff +port_phy_addr_40.0=0xff +port_phy_addr_41.0=0xff +port_phy_addr_68.0=0xff +port_phy_addr_69.0=0xff +port_phy_addr_70.0=0xff +port_phy_addr_71.0=0xff +port_phy_addr_72.0=0xff +port_phy_addr_73.0=0xff +port_phy_addr_74.0=0xff +port_phy_addr_75.0=0xff +port_phy_addr_102.0=0xff +port_phy_addr_103.0=0xff +port_phy_addr_104.0=0xff +port_phy_addr_105.0=0xff +port_phy_addr_106.0=0xff +port_phy_addr_107.0=0xff +port_phy_addr_108.0=0xff +port_phy_addr_109.0=0xff +xgxs_rx_lane_map_1.0=0x3210 +xgxs_rx_lane_map_2.0=0x3210 +xgxs_rx_lane_map_3.0=0x3210 +xgxs_rx_lane_map_4.0=0x3210 +xgxs_rx_lane_map_5.0=0x0123 +xgxs_rx_lane_map_6.0=0x2301 +xgxs_rx_lane_map_7.0=0x0123 +xgxs_rx_lane_map_8.0=0x2301 +xgxs_rx_lane_map_34.0=0x0123 +xgxs_rx_lane_map_35.0=0x0321 +xgxs_rx_lane_map_36.0=0x0321 +xgxs_rx_lane_map_37.0=0x0321 +xgxs_rx_lane_map_38.0=0x1230 +xgxs_rx_lane_map_39.0=0x2301 +xgxs_rx_lane_map_40.0=0x1230 +xgxs_rx_lane_map_41.0=0x2103 +xgxs_rx_lane_map_68.0=0x1230 +xgxs_rx_lane_map_69.0=0x2301 +xgxs_rx_lane_map_70.0=0x1230 +xgxs_rx_lane_map_71.0=0x2103 +xgxs_rx_lane_map_72.0=0x1230 +xgxs_rx_lane_map_73.0=0x2301 +xgxs_rx_lane_map_74.0=0x1230 +xgxs_rx_lane_map_75.0=0x2103 +xgxs_rx_lane_map_102.0=0x3210 +xgxs_rx_lane_map_103.0=0x3210 +xgxs_rx_lane_map_104.0=0x3210 +xgxs_rx_lane_map_105.0=0x3210 +xgxs_rx_lane_map_106.0=0x3210 +xgxs_rx_lane_map_107.0=0x3210 +xgxs_rx_lane_map_108.0=0x3210 +xgxs_rx_lane_map_109.0=0x3210 +xgxs_tx_lane_map_1.0=0x0321 +xgxs_tx_lane_map_2.0=0x2301 +xgxs_tx_lane_map_3.0=0x0321 +xgxs_tx_lane_map_4.0=0x2301 +xgxs_tx_lane_map_5.0=0x0123 +xgxs_tx_lane_map_6.0=0x0123 +xgxs_tx_lane_map_7.0=0x0123 +xgxs_tx_lane_map_8.0=0x0123 +xgxs_tx_lane_map_34.0=0x2301 +xgxs_tx_lane_map_35.0=0x0321 +xgxs_tx_lane_map_36.0=0x2301 +xgxs_tx_lane_map_37.0=0x0321 +xgxs_tx_lane_map_38.0=0x0123 +xgxs_tx_lane_map_39.0=0x1230 +xgxs_tx_lane_map_40.0=0x2301 +xgxs_tx_lane_map_41.0=0x1032 +xgxs_tx_lane_map_68.0=0x0123 +xgxs_tx_lane_map_69.0=0x1230 +xgxs_tx_lane_map_70.0=0x2301 +xgxs_tx_lane_map_71.0=0x1032 +xgxs_tx_lane_map_72.0=0x0123 +xgxs_tx_lane_map_73.0=0x1230 +xgxs_tx_lane_map_74.0=0x2301 +xgxs_tx_lane_map_75.0=0x1032 +xgxs_tx_lane_map_102.0=0x0321 +xgxs_tx_lane_map_103.0=0x2301 +xgxs_tx_lane_map_104.0=0x0321 +xgxs_tx_lane_map_105.0=0x2301 +xgxs_tx_lane_map_106.0=0x0321 +xgxs_tx_lane_map_107.0=0x2301 +xgxs_tx_lane_map_108.0=0x0321 +xgxs_tx_lane_map_109.0=0x2301 +serdes_driver_current_1=0x4 +serdes_preemphasis_1=0x145c00 +serdes_driver_current_2=0x4 +serdes_preemphasis_2=0x145c00 +serdes_driver_current_3=0x8 +serdes_preemphasis_3=0x185800 +serdes_driver_current_4=0x8 +serdes_preemphasis_4=0x185800 +serdes_driver_current_5=0x8 +serdes_preemphasis_5=0x185800 +serdes_driver_current_6=0x8 +serdes_preemphasis_6=0x185800 +serdes_driver_current_7=0xf +serdes_preemphasis_7=0x205000 +serdes_driver_current_8=0xf +serdes_preemphasis_8=0x205000 +serdes_driver_current_34=0xf +serdes_preemphasis_34=0x205000 +serdes_driver_current_35=0xf +serdes_preemphasis_35=0x205000 +serdes_driver_current_36=0xf +serdes_preemphasis_36=0x205000 +serdes_driver_current_37=0xf +serdes_preemphasis_37=0x205000 +serdes_driver_current_38=0x8 +serdes_preemphasis_38=0x185800 +serdes_driver_current_39=0x8 +serdes_preemphasis_39=0x185800 +serdes_driver_current_40=0x8 +serdes_preemphasis_40=0x185800 +serdes_driver_current_41=0x8 +serdes_preemphasis_41=0x185800 +serdes_driver_current_68=0x4 +serdes_preemphasis_68=0x145c00 +serdes_driver_current_69=0x4 +serdes_preemphasis_69=0x145c00 +serdes_driver_current_70=0x4 +serdes_preemphasis_70=0x145c00 +serdes_driver_current_71=0x4 +serdes_preemphasis_71=0x145c00 +serdes_driver_current_72=0x4 +serdes_preemphasis_72=0x145c00 +serdes_driver_current_73=0x4 +serdes_preemphasis_73=0x145c00 +serdes_driver_current_74=0x4 +serdes_preemphasis_74=0x145c00 +serdes_driver_current_75=0x4 +serdes_preemphasis_75=0x145c00 +serdes_driver_current_102=0x4 +serdes_preemphasis_102=0x145c00 +serdes_driver_current_103=0x4 +serdes_preemphasis_103=0x145c00 +serdes_driver_current_104=0x4 +serdes_preemphasis_104=0x145c00 +serdes_driver_current_105=0x4 +serdes_preemphasis_105=0x145c00 +serdes_driver_current_106=0x4 +serdes_preemphasis_106=0x145c00 +serdes_driver_current_107=0x4 +serdes_preemphasis_107=0x145c00 +serdes_driver_current_108=0x4 +serdes_preemphasis_108=0x145c00 +serdes_driver_current_109=0x4 +serdes_preemphasis_109=0x145c00 + +mmu_init_config="MSFT-TH-Tier1" diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-T96C8/port_config.ini b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-T96C8/port_config.ini new file mode 100644 index 000000000000..ddb80965e1de --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-T96C8/port_config.ini @@ -0,0 +1,105 @@ +# name lanes alias index speed +Ethernet0 33 Ethernet1/1 1 25000 +Ethernet1 34 Ethernet1/2 1 25000 +Ethernet2 35 Ethernet1/3 1 25000 +Ethernet3 36 Ethernet1/4 1 25000 +Ethernet4 37 Ethernet2/1 2 25000 +Ethernet5 38 Ethernet2/2 2 25000 +Ethernet6 39 Ethernet2/3 2 25000 +Ethernet7 40 Ethernet2/4 2 25000 +Ethernet8 41 Ethernet3/1 3 25000 +Ethernet9 42 Ethernet3/2 3 25000 +Ethernet10 43 Ethernet3/3 3 25000 +Ethernet11 44 Ethernet3/4 3 25000 +Ethernet12 45 Ethernet4/1 4 25000 +Ethernet13 46 Ethernet4/2 4 25000 +Ethernet14 47 Ethernet4/3 4 25000 +Ethernet15 48 Ethernet4/4 4 25000 +Ethernet16 49 Ethernet5/1 5 25000 +Ethernet17 50 Ethernet5/2 5 25000 +Ethernet18 51 Ethernet5/3 5 25000 +Ethernet19 52 Ethernet5/4 5 25000 +Ethernet20 53 Ethernet6/1 6 25000 +Ethernet21 54 Ethernet6/2 6 25000 +Ethernet22 55 Ethernet6/3 6 25000 +Ethernet23 56 Ethernet6/4 6 25000 +Ethernet24 57,58,59,60 Ethernet7/1 7 100000 +Ethernet28 61,62,63,64 Ethernet8/1 8 100000 +Ethernet32 65,66,67,68 Ethernet9/1 9 100000 +Ethernet36 69,70,71,72 Ethernet10/1 10 100000 +Ethernet40 73 Ethernet11/1 11 25000 +Ethernet41 74 Ethernet11/2 11 25000 +Ethernet42 75 Ethernet11/3 11 25000 +Ethernet43 76 Ethernet11/4 11 25000 +Ethernet44 77 Ethernet12/1 12 25000 +Ethernet45 78 Ethernet12/2 12 25000 +Ethernet46 79 Ethernet12/3 12 25000 +Ethernet47 80 Ethernet12/4 12 25000 +Ethernet48 81 Ethernet13/1 13 25000 +Ethernet49 82 Ethernet13/2 13 25000 +Ethernet50 83 Ethernet13/3 13 25000 +Ethernet51 84 Ethernet13/4 13 25000 +Ethernet52 85 Ethernet14/1 14 25000 +Ethernet53 86 Ethernet14/2 14 25000 +Ethernet54 87 Ethernet14/3 14 25000 +Ethernet55 88 Ethernet14/4 14 25000 +Ethernet56 89 Ethernet15/1 15 25000 +Ethernet57 90 Ethernet15/2 15 25000 +Ethernet58 91 Ethernet15/3 15 25000 +Ethernet59 92 Ethernet15/4 15 25000 +Ethernet60 93 Ethernet16/1 16 25000 +Ethernet61 94 Ethernet16/2 16 25000 +Ethernet62 95 Ethernet16/3 16 25000 +Ethernet63 96 Ethernet16/4 16 25000 +Ethernet64 97 Ethernet17/1 17 25000 +Ethernet65 98 Ethernet17/2 17 25000 +Ethernet66 99 Ethernet17/3 17 25000 +Ethernet67 100 Ethernet17/4 17 25000 +Ethernet68 101 Ethernet18/1 18 25000 +Ethernet69 102 Ethernet18/2 18 25000 +Ethernet70 103 Ethernet18/3 18 25000 +Ethernet71 104 Ethernet18/4 18 25000 +Ethernet72 105 Ethernet19/1 19 25000 +Ethernet73 106 Ethernet19/2 19 25000 +Ethernet74 107 Ethernet19/3 19 25000 +Ethernet75 108 Ethernet19/4 19 25000 +Ethernet76 109 Ethernet20/1 20 25000 +Ethernet77 110 Ethernet20/2 20 25000 +Ethernet78 111 Ethernet20/3 20 25000 +Ethernet79 112 Ethernet20/4 20 25000 +Ethernet80 113 Ethernet21/1 21 25000 +Ethernet81 114 Ethernet21/2 21 25000 +Ethernet82 115 Ethernet21/3 21 25000 +Ethernet83 116 Ethernet21/4 21 25000 +Ethernet84 117 Ethernet22/1 22 25000 +Ethernet85 118 Ethernet22/2 22 25000 +Ethernet86 119 Ethernet22/3 22 25000 +Ethernet87 120 Ethernet22/4 22 25000 +Ethernet88 121,122,123,124 Ethernet23/1 23 100000 +Ethernet92 125,126,127,128 Ethernet24/1 24 100000 +Ethernet96 1,2,3,4 Ethernet25/1 25 100000 +Ethernet100 5,6,7,8 Ethernet26/1 26 100000 +Ethernet104 9 Ethernet27/1 27 25000 +Ethernet105 10 Ethernet27/2 27 25000 +Ethernet106 11 Ethernet27/3 27 25000 +Ethernet107 12 Ethernet27/4 27 25000 +Ethernet108 13 Ethernet28/1 28 25000 +Ethernet109 14 Ethernet28/2 28 25000 +Ethernet110 15 Ethernet28/3 28 25000 +Ethernet111 16 Ethernet28/4 28 25000 +Ethernet112 17 Ethernet29/1 29 25000 +Ethernet113 18 Ethernet29/2 29 25000 +Ethernet114 19 Ethernet29/3 29 25000 +Ethernet115 20 Ethernet29/4 29 25000 +Ethernet116 21 Ethernet30/1 30 25000 +Ethernet117 22 Ethernet30/2 30 25000 +Ethernet118 23 Ethernet30/3 30 25000 +Ethernet119 24 Ethernet30/4 30 25000 +Ethernet120 25 Ethernet31/1 31 25000 +Ethernet121 26 Ethernet31/2 31 25000 +Ethernet122 27 Ethernet31/3 31 25000 +Ethernet123 28 Ethernet31/4 31 25000 +Ethernet124 29 Ethernet32/1 32 25000 +Ethernet125 30 Ethernet32/2 32 25000 +Ethernet126 31 Ethernet32/3 32 25000 +Ethernet127 32 Ethernet32/4 32 25000 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-T96C8/sai.profile b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-T96C8/sai.profile new file mode 100644 index 000000000000..f9a1e2bdc4d6 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-T96C8/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-a7060-cx32s-8x100G+96x25G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-T96C8/th-a7060-cx32s-8x100G+96x25G.config.bcm b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-T96C8/th-a7060-cx32s-8x100G+96x25G.config.bcm new file mode 100644 index 000000000000..467d428830c9 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/Arista-7060CX-32S-T96C8/th-a7060-cx32s-8x100G+96x25G.config.bcm @@ -0,0 +1,780 @@ +# Arista 7060CX-32S + +phy_an_allow_pll_change=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +higig2_hdr_mode=1 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +l2xmsg_mode=1 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +os=unix +oversubscribe_mode=1 +ptp_bs_fref.0=25000000 +ptp_ts_pll_fref.0=25000000 +robust_hash_disable_egress_vlan.0=1 +robust_hash_disable_mpls.0=1 +robust_hash_disable_vlan.0=1 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +phy_an_allow_pll_change_hg.0=0 +dport_map_direct=1 +phy_an_c73=1 + +phy_an_fec_1.0=1 +phy_an_fec_2.0=1 +phy_an_fec_3.0=1 +phy_an_fec_4.0=1 +phy_an_fec_5.0=1 +phy_an_fec_6.0=1 +phy_an_fec_7.0=1 +phy_an_fec_8.0=1 +phy_an_fec_9.0=1 +phy_an_fec_10.0=1 +phy_an_fec_11.0=1 +phy_an_fec_12.0=1 +phy_an_fec_13.0=1 +phy_an_fec_14.0=1 +phy_an_fec_15.0=1 +phy_an_fec_16.0=1 +phy_an_fec_17.0=1 +phy_an_fec_18.0=1 +phy_an_fec_19.0=1 +phy_an_fec_20.0=1 +phy_an_fec_21.0=1 +phy_an_fec_22.0=1 +phy_an_fec_23.0=1 +phy_an_fec_24.0=1 +phy_an_fec_25.0=1 +phy_an_fec_26.0=1 +phy_an_fec_34.0=1 +phy_an_fec_35.0=1 +phy_an_fec_36.0=1 +phy_an_fec_37.0=1 +phy_an_fec_38.0=1 +phy_an_fec_39.0=1 +phy_an_fec_40.0=1 +phy_an_fec_41.0=1 +phy_an_fec_42.0=1 +phy_an_fec_43.0=1 +phy_an_fec_44.0=1 +phy_an_fec_45.0=1 +phy_an_fec_46.0=1 +phy_an_fec_47.0=1 +phy_an_fec_48.0=1 +phy_an_fec_49.0=1 +phy_an_fec_50.0=1 +phy_an_fec_51.0=1 +phy_an_fec_52.0=1 +phy_an_fec_53.0=1 +phy_an_fec_54.0=1 +phy_an_fec_55.0=1 +phy_an_fec_56.0=1 +phy_an_fec_57.0=1 +phy_an_fec_58.0=1 +phy_an_fec_59.0=1 +phy_an_fec_68.0=1 +phy_an_fec_69.0=1 +phy_an_fec_70.0=1 +phy_an_fec_71.0=1 +phy_an_fec_72.0=1 +phy_an_fec_73.0=1 +phy_an_fec_74.0=1 +phy_an_fec_75.0=1 +phy_an_fec_76.0=1 +phy_an_fec_77.0=1 +phy_an_fec_78.0=1 +phy_an_fec_79.0=1 +phy_an_fec_80.0=1 +phy_an_fec_81.0=1 +phy_an_fec_82.0=1 +phy_an_fec_83.0=1 +phy_an_fec_84.0=1 +phy_an_fec_85.0=1 +phy_an_fec_86.0=1 +phy_an_fec_87.0=1 +phy_an_fec_88.0=1 +phy_an_fec_89.0=1 +phy_an_fec_90.0=1 +phy_an_fec_91.0=1 +phy_an_fec_92.0=1 +phy_an_fec_93.0=1 +phy_an_fec_102.0=1 +phy_an_fec_103.0=1 +phy_an_fec_104.0=1 +phy_an_fec_105.0=1 +phy_an_fec_106.0=1 +phy_an_fec_107.0=1 +phy_an_fec_108.0=1 +phy_an_fec_109.0=1 +phy_an_fec_110.0=1 +phy_an_fec_111.0=1 +phy_an_fec_112.0=1 +phy_an_fec_113.0=1 +phy_an_fec_114.0=1 +phy_an_fec_115.0=1 +phy_an_fec_116.0=1 +phy_an_fec_117.0=1 +phy_an_fec_118.0=1 +phy_an_fec_119.0=1 +phy_an_fec_120.0=1 +phy_an_fec_121.0=1 +phy_an_fec_122.0=1 +phy_an_fec_123.0=1 +phy_an_fec_124.0=1 +phy_an_fec_125.0=1 +phy_an_fec_126.0=1 +phy_an_fec_127.0=1 + +# Q1 +portmap_1.0=1:100 +portmap_2.0=5:100 +portmap_3.0=9:25 +portmap_4.0=10:25 +portmap_5.0=11:25 +portmap_6.0=12:25 +portmap_7.0=13:25 +portmap_8.0=14:25 +portmap_9.0=15:25 +portmap_10.0=16:25 +portmap_11.0=17:25 +portmap_12.0=18:25 +portmap_13.0=19:25 +portmap_14.0=20:25 +portmap_15.0=21:25 +portmap_16.0=22:25 +portmap_17.0=23:25 +portmap_18.0=24:25 +portmap_19.0=25:25 +portmap_20.0=26:25 +portmap_21.0=27:25 +portmap_22.0=28:25 +portmap_23.0=29:25 +portmap_24.0=30:25 +portmap_25.0=31:25 +portmap_26.0=32:25 +phy_xaui_rx_polarity_flip_1.0=0x1 +phy_xaui_rx_polarity_flip_2.0=0x5 +phy_xaui_rx_polarity_flip_3.0=0x1 +phy_xaui_rx_polarity_flip_4.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x0 +phy_xaui_rx_polarity_flip_6.0=0x0 +phy_xaui_rx_polarity_flip_7.0=0x1 +phy_xaui_rx_polarity_flip_8.0=0x1 +phy_xaui_rx_polarity_flip_9.0=0x1 +phy_xaui_rx_polarity_flip_10.0=0x0 +phy_xaui_rx_polarity_flip_11.0=0x0 +phy_xaui_rx_polarity_flip_12.0=0x0 +phy_xaui_rx_polarity_flip_13.0=0x1 +phy_xaui_rx_polarity_flip_14.0=0x1 +phy_xaui_rx_polarity_flip_15.0=0x1 +phy_xaui_rx_polarity_flip_16.0=0x1 +phy_xaui_rx_polarity_flip_17.0=0x1 +phy_xaui_rx_polarity_flip_18.0=0x1 +phy_xaui_rx_polarity_flip_19.0=0x0 +phy_xaui_rx_polarity_flip_20.0=0x0 +phy_xaui_rx_polarity_flip_21.0=0x1 +phy_xaui_rx_polarity_flip_22.0=0x1 +phy_xaui_rx_polarity_flip_23.0=0x1 +phy_xaui_rx_polarity_flip_24.0=0x1 +phy_xaui_rx_polarity_flip_25.0=0x1 +phy_xaui_rx_polarity_flip_26.0=0x1 +phy_xaui_tx_polarity_flip_1.0=0x0 +phy_xaui_tx_polarity_flip_2.0=0xe +phy_xaui_tx_polarity_flip_3.0=0x0 +phy_xaui_tx_polarity_flip_4.0=0x1 +phy_xaui_tx_polarity_flip_5.0=0x0 +phy_xaui_tx_polarity_flip_6.0=0x0 +phy_xaui_tx_polarity_flip_7.0=0x0 +phy_xaui_tx_polarity_flip_8.0=0x1 +phy_xaui_tx_polarity_flip_9.0=0x1 +phy_xaui_tx_polarity_flip_10.0=0x1 +phy_xaui_tx_polarity_flip_11.0=0x0 +phy_xaui_tx_polarity_flip_12.0=0x0 +phy_xaui_tx_polarity_flip_13.0=0x1 +phy_xaui_tx_polarity_flip_14.0=0x1 +phy_xaui_tx_polarity_flip_15.0=0x1 +phy_xaui_tx_polarity_flip_16.0=0x1 +phy_xaui_tx_polarity_flip_17.0=0x1 +phy_xaui_tx_polarity_flip_18.0=0x1 +phy_xaui_tx_polarity_flip_19.0=0x0 +phy_xaui_tx_polarity_flip_20.0=0x0 +phy_xaui_tx_polarity_flip_21.0=0x1 +phy_xaui_tx_polarity_flip_22.0=0x1 +phy_xaui_tx_polarity_flip_23.0=0x1 +phy_xaui_tx_polarity_flip_24.0=0x1 +phy_xaui_tx_polarity_flip_25.0=0x1 +phy_xaui_tx_polarity_flip_26.0=0x1 +xgxs_rx_lane_map_1.0=0x3210 +xgxs_rx_lane_map_2.0=0x3210 +xgxs_rx_lane_map_3.0=0x3210 +xgxs_rx_lane_map_5.0=0x3210 +xgxs_rx_lane_map_7.0=0x3210 +xgxs_rx_lane_map_9.0=0x3210 +xgxs_rx_lane_map_11.0=0x0123 +xgxs_rx_lane_map_13.0=0x0123 +xgxs_rx_lane_map_15.0=0x2301 +xgxs_rx_lane_map_17.0=0x2301 +xgxs_rx_lane_map_19.0=0x0123 +xgxs_rx_lane_map_21.0=0x0123 +xgxs_rx_lane_map_23.0=0x2301 +xgxs_rx_lane_map_25.0=0x2301 +xgxs_tx_lane_map_1.0=0x0321 +xgxs_tx_lane_map_2.0=0x2301 +xgxs_tx_lane_map_3.0=0x0321 +xgxs_tx_lane_map_5.0=0x0321 +xgxs_tx_lane_map_7.0=0x2301 +xgxs_tx_lane_map_9.0=0x2301 +xgxs_tx_lane_map_11.0=0x0123 +xgxs_tx_lane_map_13.0=0x0123 +xgxs_tx_lane_map_15.0=0x0123 +xgxs_tx_lane_map_17.0=0x0123 +xgxs_tx_lane_map_19.0=0x0123 +xgxs_tx_lane_map_21.0=0x0123 +xgxs_tx_lane_map_23.0=0x0123 +xgxs_tx_lane_map_25.0=0x0123 + +# Q2 +portmap_34.0=33:25 +portmap_35.0=34:25 +portmap_36.0=35:25 +portmap_37.0=36:25 +portmap_38.0=37:25 +portmap_39.0=38:25 +portmap_40.0=39:25 +portmap_41.0=40:25 +portmap_42.0=41:25 +portmap_43.0=42:25 +portmap_44.0=43:25 +portmap_45.0=44:25 +portmap_46.0=45:25 +portmap_47.0=46:25 +portmap_48.0=47:25 +portmap_49.0=48:25 +portmap_50.0=49:25 +portmap_51.0=50:25 +portmap_52.0=51:25 +portmap_53.0=52:25 +portmap_54.0=53:25 +portmap_55.0=54:25 +portmap_56.0=55:25 +portmap_57.0=56:25 +portmap_58.0=57:100 +portmap_59.0=61:100 +phy_xaui_rx_polarity_flip_34.0=0x0 +phy_xaui_rx_polarity_flip_35.0=0x0 +phy_xaui_rx_polarity_flip_36.0=0x0 +phy_xaui_rx_polarity_flip_37.0=0x0 +phy_xaui_rx_polarity_flip_38.0=0x1 +phy_xaui_rx_polarity_flip_39.0=0x1 +phy_xaui_rx_polarity_flip_40.0=0x1 +phy_xaui_rx_polarity_flip_41.0=0x0 +phy_xaui_rx_polarity_flip_42.0=0x0 +phy_xaui_rx_polarity_flip_43.0=0x0 +phy_xaui_rx_polarity_flip_44.0=0x1 +phy_xaui_rx_polarity_flip_45.0=0x0 +phy_xaui_rx_polarity_flip_46.0=0x1 +phy_xaui_rx_polarity_flip_47.0=0x1 +phy_xaui_rx_polarity_flip_48.0=0x1 +phy_xaui_rx_polarity_flip_49.0=0x0 +phy_xaui_rx_polarity_flip_50.0=0x0 +phy_xaui_rx_polarity_flip_51.0=0x0 +phy_xaui_rx_polarity_flip_52.0=0x1 +phy_xaui_rx_polarity_flip_53.0=0x0 +phy_xaui_rx_polarity_flip_54.0=0x0 +phy_xaui_rx_polarity_flip_55.0=0x1 +phy_xaui_rx_polarity_flip_56.0=0x1 +phy_xaui_rx_polarity_flip_57.0=0x0 +phy_xaui_rx_polarity_flip_58.0=0x1 +phy_xaui_rx_polarity_flip_59.0=0x2 +phy_xaui_tx_polarity_flip_34.0=0x0 +phy_xaui_tx_polarity_flip_34.0=0x0 +phy_xaui_tx_polarity_flip_36.0=0x0 +phy_xaui_tx_polarity_flip_36.0=0x0 +phy_xaui_tx_polarity_flip_38.0=0x0 +phy_xaui_tx_polarity_flip_39.0=0x1 +phy_xaui_tx_polarity_flip_40.0=0x1 +phy_xaui_tx_polarity_flip_41.0=0x1 +phy_xaui_tx_polarity_flip_42.0=0x0 +phy_xaui_tx_polarity_flip_43.0=0x0 +phy_xaui_tx_polarity_flip_44.0=0x0 +phy_xaui_tx_polarity_flip_45.0=0x0 +phy_xaui_tx_polarity_flip_46.0=0x0 +phy_xaui_tx_polarity_flip_47.0=0x1 +phy_xaui_tx_polarity_flip_48.0=0x1 +phy_xaui_tx_polarity_flip_49.0=0x1 +phy_xaui_tx_polarity_flip_50.0=0x1 +phy_xaui_tx_polarity_flip_51.0=0x1 +phy_xaui_tx_polarity_flip_52.0=0x1 +phy_xaui_tx_polarity_flip_53.0=0x1 +phy_xaui_tx_polarity_flip_54.0=0x0 +phy_xaui_tx_polarity_flip_55.0=0x1 +phy_xaui_tx_polarity_flip_56.0=0x1 +phy_xaui_tx_polarity_flip_57.0=0x1 +phy_xaui_tx_polarity_flip_58.0=0x6 +phy_xaui_tx_polarity_flip_59.0=0xb +xgxs_rx_lane_map_34.0=0x0123 +xgxs_rx_lane_map_36.0=0x0123 +xgxs_rx_lane_map_38.0=0x0321 +xgxs_rx_lane_map_40.0=0x0321 +xgxs_rx_lane_map_42.0=0x0321 +xgxs_rx_lane_map_44.0=0x0321 +xgxs_rx_lane_map_46.0=0x0321 +xgxs_rx_lane_map_48.0=0x0321 +xgxs_rx_lane_map_50.0=0x1230 +xgxs_rx_lane_map_52.0=0x1230 +xgxs_rx_lane_map_54.0=0x2301 +xgxs_rx_lane_map_56.0=0x2301 +xgxs_rx_lane_map_58.0=0x1230 +xgxs_rx_lane_map_59.0=0x2103 +xgxs_tx_lane_map_34.0=0x2301 +xgxs_tx_lane_map_36.0=0x2301 +xgxs_tx_lane_map_38.0=0x0321 +xgxs_tx_lane_map_40.0=0x0321 +xgxs_tx_lane_map_42.0=0x2301 +xgxs_tx_lane_map_44.0=0x2301 +xgxs_tx_lane_map_46.0=0x0321 +xgxs_tx_lane_map_48.0=0x0321 +xgxs_tx_lane_map_50.0=0x0123 +xgxs_tx_lane_map_52.0=0x0123 +xgxs_tx_lane_map_54.0=0x1230 +xgxs_tx_lane_map_56.0=0x1230 +xgxs_tx_lane_map_58.0=0x2301 +xgxs_tx_lane_map_59.0=0x1032 + +# Q3 +portmap_68.0=65:100 +portmap_69.0=69:100 +portmap_70.0=73:25 +portmap_71.0=74:25 +portmap_72.0=75:25 +portmap_73.0=76:25 +portmap_74.0=77:25 +portmap_75.0=78:25 +portmap_76.0=79:25 +portmap_77.0=80:25 +portmap_78.0=81:25 +portmap_79.0=82:25 +portmap_80.0=83:25 +portmap_81.0=84:25 +portmap_82.0=85:25 +portmap_83.0=86:25 +portmap_84.0=87:25 +portmap_85.0=88:25 +portmap_86.0=89:25 +portmap_87.0=90:25 +portmap_88.0=91:25 +portmap_89.0=92:25 +portmap_90.0=93:25 +portmap_91.0=94:25 +portmap_92.0=95:25 +portmap_93.0=96:25 +phy_xaui_rx_polarity_flip_68.0=0xd +phy_xaui_rx_polarity_flip_69.0=0x6 +phy_xaui_rx_polarity_flip_70.0=0x1 +phy_xaui_rx_polarity_flip_71.0=0x0 +phy_xaui_rx_polarity_flip_72.0=0x0 +phy_xaui_rx_polarity_flip_73.0=0x0 +phy_xaui_rx_polarity_flip_74.0=0x0 +phy_xaui_rx_polarity_flip_75.0=0x0 +phy_xaui_rx_polarity_flip_76.0=0x0 +phy_xaui_rx_polarity_flip_77.0=0x1 +phy_xaui_rx_polarity_flip_78.0=0x1 +phy_xaui_rx_polarity_flip_79.0=0x1 +phy_xaui_rx_polarity_flip_80.0=0x1 +phy_xaui_rx_polarity_flip_81.0=0x0 +phy_xaui_rx_polarity_flip_82.0=0x0 +phy_xaui_rx_polarity_flip_83.0=0x0 +phy_xaui_rx_polarity_flip_84.0=0x1 +phy_xaui_rx_polarity_flip_85.0=0x1 +phy_xaui_rx_polarity_flip_86.0=0x1 +phy_xaui_rx_polarity_flip_87.0=0x1 +phy_xaui_rx_polarity_flip_88.0=0x1 +phy_xaui_rx_polarity_flip_89.0=0x0 +phy_xaui_rx_polarity_flip_90.0=0x0 +phy_xaui_rx_polarity_flip_91.0=0x0 +phy_xaui_rx_polarity_flip_92.0=0x0 +phy_xaui_rx_polarity_flip_93.0=0x1 +phy_xaui_tx_polarity_flip_68.0=0x9 +phy_xaui_tx_polarity_flip_69.0=0xb +phy_xaui_tx_polarity_flip_70.0=0x1 +phy_xaui_tx_polarity_flip_71.0=0x0 +phy_xaui_tx_polarity_flip_72.0=0x1 +phy_xaui_tx_polarity_flip_73.0=0x1 +phy_xaui_tx_polarity_flip_74.0=0x1 +phy_xaui_tx_polarity_flip_75.0=0x0 +phy_xaui_tx_polarity_flip_76.0=0x0 +phy_xaui_tx_polarity_flip_77.0=0x1 +phy_xaui_tx_polarity_flip_78.0=0x0 +phy_xaui_tx_polarity_flip_79.0=0x1 +phy_xaui_tx_polarity_flip_80.0=0x1 +phy_xaui_tx_polarity_flip_81.0=0x0 +phy_xaui_tx_polarity_flip_82.0=0x0 +phy_xaui_tx_polarity_flip_83.0=0x0 +phy_xaui_tx_polarity_flip_84.0=0x1 +phy_xaui_tx_polarity_flip_85.0=0x1 +phy_xaui_tx_polarity_flip_86.0=0x1 +phy_xaui_tx_polarity_flip_87.0=0x0 +phy_xaui_tx_polarity_flip_88.0=0x0 +phy_xaui_tx_polarity_flip_89.0=0x1 +phy_xaui_tx_polarity_flip_90.0=0x1 +phy_xaui_tx_polarity_flip_91.0=0x0 +phy_xaui_tx_polarity_flip_92.0=0x0 +phy_xaui_tx_polarity_flip_93.0=0x1 +xgxs_rx_lane_map_68.0=0x1230 +xgxs_rx_lane_map_69.0=0x2301 +xgxs_rx_lane_map_70.0=0x1230 +xgxs_rx_lane_map_72.0=0x1230 +xgxs_rx_lane_map_74.0=0x2103 +xgxs_rx_lane_map_76.0=0x2103 +xgxs_rx_lane_map_78.0=0x1230 +xgxs_rx_lane_map_80.0=0x1230 +xgxs_rx_lane_map_82.0=0x2301 +xgxs_rx_lane_map_84.0=0x2301 +xgxs_rx_lane_map_86.0=0x1230 +xgxs_rx_lane_map_88.0=0x1230 +xgxs_rx_lane_map_90.0=0x2103 +xgxs_rx_lane_map_92.0=0x2103 +xgxs_tx_lane_map_68.0=0x0123 +xgxs_tx_lane_map_69.0=0x1230 +xgxs_tx_lane_map_70.0=0x2301 +xgxs_tx_lane_map_72.0=0x2301 +xgxs_tx_lane_map_74.0=0x1032 +xgxs_tx_lane_map_76.0=0x1032 +xgxs_tx_lane_map_78.0=0x0123 +xgxs_tx_lane_map_80.0=0x0123 +xgxs_tx_lane_map_82.0=0x1230 +xgxs_tx_lane_map_84.0=0x1230 +xgxs_tx_lane_map_86.0=0x2301 +xgxs_tx_lane_map_88.0=0x2301 +xgxs_tx_lane_map_90.0=0x1032 +xgxs_tx_lane_map_92.0=0x1032 + +# Q4 +portmap_102.0=97:25 +portmap_103.0=98:25 +portmap_104.0=99:25 +portmap_105.0=100:25 +portmap_106.0=101:25 +portmap_107.0=102:25 +portmap_108.0=103:25 +portmap_109.0=104:25 +portmap_110.0=105:25 +portmap_111.0=106:25 +portmap_112.0=107:25 +portmap_113.0=108:25 +portmap_114.0=109:25 +portmap_115.0=110:25 +portmap_116.0=111:25 +portmap_117.0=112:25 +portmap_118.0=113:25 +portmap_119.0=114:25 +portmap_120.0=115:25 +portmap_121.0=116:25 +portmap_122.0=117:25 +portmap_123.0=118:25 +portmap_124.0=119:25 +portmap_125.0=120:25 +portmap_126.0=121:100 +portmap_127.0=125:100 +phy_xaui_rx_polarity_flip_102.0=0x1 +phy_xaui_rx_polarity_flip_103.0=0x1 +phy_xaui_rx_polarity_flip_104.0=0x0 +phy_xaui_rx_polarity_flip_105.0=0x1 +phy_xaui_rx_polarity_flip_106.0=0x0 +phy_xaui_rx_polarity_flip_107.0=0x0 +phy_xaui_rx_polarity_flip_108.0=0x1 +phy_xaui_rx_polarity_flip_109.0=0x1 +phy_xaui_rx_polarity_flip_110.0=0x1 +phy_xaui_rx_polarity_flip_111.0=0x1 +phy_xaui_rx_polarity_flip_112.0=0x0 +phy_xaui_rx_polarity_flip_113.0=0x0 +phy_xaui_rx_polarity_flip_114.0=0x0 +phy_xaui_rx_polarity_flip_115.0=0x0 +phy_xaui_rx_polarity_flip_116.0=0x1 +phy_xaui_rx_polarity_flip_117.0=0x1 +phy_xaui_rx_polarity_flip_118.0=0x1 +phy_xaui_rx_polarity_flip_119.0=0x1 +phy_xaui_rx_polarity_flip_120.0=0x0 +phy_xaui_rx_polarity_flip_121.0=0x1 +phy_xaui_rx_polarity_flip_122.0=0x1 +phy_xaui_rx_polarity_flip_123.0=0x0 +phy_xaui_rx_polarity_flip_124.0=0x1 +phy_xaui_rx_polarity_flip_125.0=0x0 +phy_xaui_rx_polarity_flip_126.0=0x1 +phy_xaui_rx_polarity_flip_127.0=0x9 +phy_xaui_tx_polarity_flip_102.0=0x0 +phy_xaui_tx_polarity_flip_103.0=0x1 +phy_xaui_tx_polarity_flip_104.0=0x1 +phy_xaui_tx_polarity_flip_105.0=0x0 +phy_xaui_tx_polarity_flip_106.0=0x1 +phy_xaui_tx_polarity_flip_107.0=0x1 +phy_xaui_tx_polarity_flip_108.0=0x0 +phy_xaui_tx_polarity_flip_109.0=0x1 +phy_xaui_tx_polarity_flip_110.0=0x0 +phy_xaui_tx_polarity_flip_111.0=0x1 +phy_xaui_tx_polarity_flip_112.0=0x1 +phy_xaui_tx_polarity_flip_113.0=0x0 +phy_xaui_tx_polarity_flip_114.0=0x1 +phy_xaui_tx_polarity_flip_115.0=0x1 +phy_xaui_tx_polarity_flip_116.0=0x0 +phy_xaui_tx_polarity_flip_117.0=0x1 +phy_xaui_tx_polarity_flip_118.0=0x0 +phy_xaui_tx_polarity_flip_119.0=0x1 +phy_xaui_tx_polarity_flip_120.0=0x1 +phy_xaui_tx_polarity_flip_121.0=0x0 +phy_xaui_tx_polarity_flip_122.0=0x1 +phy_xaui_tx_polarity_flip_123.0=0x1 +phy_xaui_tx_polarity_flip_124.0=0x1 +phy_xaui_tx_polarity_flip_125.0=0x1 +phy_xaui_tx_polarity_flip_126.0=0x6 +phy_xaui_tx_polarity_flip_127.0=0xc +xgxs_rx_lane_map_102.0=0x3210 +xgxs_rx_lane_map_104.0=0x3210 +xgxs_rx_lane_map_106.0=0x3210 +xgxs_rx_lane_map_108.0=0x3210 +xgxs_rx_lane_map_110.0=0x3210 +xgxs_rx_lane_map_112.0=0x3210 +xgxs_rx_lane_map_114.0=0x3210 +xgxs_rx_lane_map_116.0=0x3210 +xgxs_rx_lane_map_118.0=0x3210 +xgxs_rx_lane_map_120.0=0x3210 +xgxs_rx_lane_map_122.0=0x3210 +xgxs_rx_lane_map_124.0=0x3210 +xgxs_rx_lane_map_126.0=0x3210 +xgxs_rx_lane_map_127.0=0x3210 +xgxs_tx_lane_map_102.0=0x0321 +xgxs_tx_lane_map_104.0=0x0321 +xgxs_tx_lane_map_106.0=0x2301 +xgxs_tx_lane_map_108.0=0x2301 +xgxs_tx_lane_map_110.0=0x0321 +xgxs_tx_lane_map_112.0=0x0321 +xgxs_tx_lane_map_114.0=0x2301 +xgxs_tx_lane_map_116.0=0x2301 +xgxs_tx_lane_map_118.0=0x0321 +xgxs_tx_lane_map_120.0=0x0321 +xgxs_tx_lane_map_122.0=0x2301 +xgxs_tx_lane_map_124.0=0x2301 +xgxs_tx_lane_map_126.0=0x0321 +xgxs_tx_lane_map_127.0=0x2301 + +#mmu_init_config="MSFT-TH-Tier0" + +# tuning parameters +serdes_driver_current_1=0xa +serdes_preemphasis_1=0x284008 +serdes_driver_current_2=0xa +serdes_preemphasis_2=0x284008 +serdes_driver_current_3=0xf +serdes_preemphasis_3=0x46408 +serdes_driver_current_4=0xf +serdes_preemphasis_4=0x46408 +serdes_driver_current_5=0xf +serdes_preemphasis_5=0x46408 +serdes_driver_current_6=0xf +serdes_preemphasis_6=0x46408 +serdes_driver_current_7=0xf +serdes_preemphasis_7=0x46408 +serdes_driver_current_8=0xf +serdes_preemphasis_8=0x46408 +serdes_driver_current_9=0xf +serdes_preemphasis_9=0x46408 +serdes_driver_current_10=0xf +serdes_preemphasis_10=0x46408 +serdes_driver_current_11=0xf +serdes_preemphasis_11=0x46408 +serdes_driver_current_12=0xf +serdes_preemphasis_12=0x46408 +serdes_driver_current_13=0xf +serdes_preemphasis_13=0x46408 +serdes_driver_current_14=0xf +serdes_preemphasis_14=0x46408 +serdes_driver_current_15=0xf +serdes_preemphasis_15=0x46408 +serdes_driver_current_16=0xf +serdes_preemphasis_16=0x46408 +serdes_driver_current_17=0xf +serdes_preemphasis_17=0x46408 +serdes_driver_current_18=0xf +serdes_preemphasis_18=0x46408 +serdes_driver_current_19=0xf +serdes_preemphasis_19=0x46408 +serdes_driver_current_20=0xf +serdes_preemphasis_20=0x46408 +serdes_driver_current_21=0xf +serdes_preemphasis_21=0x46408 +serdes_driver_current_22=0xf +serdes_preemphasis_22=0x46408 +serdes_driver_current_23=0xf +serdes_preemphasis_23=0x46408 +serdes_driver_current_24=0xf +serdes_preemphasis_24=0x46408 +serdes_driver_current_25=0xf +serdes_preemphasis_25=0x46408 +serdes_driver_current_26=0xf +serdes_preemphasis_26=0x46408 +serdes_driver_current_34=0xf +serdes_preemphasis_34=0x46408 +serdes_driver_current_35=0xf +serdes_preemphasis_35=0x46408 +serdes_driver_current_36=0xf +serdes_preemphasis_36=0x46408 +serdes_driver_current_37=0xf +serdes_preemphasis_37=0x46408 +serdes_driver_current_38=0xf +serdes_preemphasis_38=0x46408 +serdes_driver_current_39=0xf +serdes_preemphasis_39=0x46408 +serdes_driver_current_40=0xf +serdes_preemphasis_40=0x46408 +serdes_driver_current_41=0xf +serdes_preemphasis_41=0x46408 +serdes_driver_current_42=0xf +serdes_preemphasis_42=0x46408 +serdes_driver_current_43=0xf +serdes_preemphasis_43=0x46408 +serdes_driver_current_44=0xf +serdes_preemphasis_44=0x46408 +serdes_driver_current_45=0xf +serdes_preemphasis_45=0x46408 +serdes_driver_current_46=0xf +serdes_preemphasis_46=0x46408 +serdes_driver_current_47=0xf +serdes_preemphasis_47=0x46408 +serdes_driver_current_48=0xf +serdes_preemphasis_48=0x46408 +serdes_driver_current_49=0xf +serdes_preemphasis_49=0x46408 +serdes_driver_current_50=0xf +serdes_preemphasis_50=0x46408 +serdes_driver_current_51=0xf +serdes_preemphasis_51=0x46408 +serdes_driver_current_52=0xf +serdes_preemphasis_52=0x46408 +serdes_driver_current_53=0xf +serdes_preemphasis_53=0x46408 +serdes_driver_current_54=0xf +serdes_preemphasis_54=0x46408 +serdes_driver_current_55=0xf +serdes_preemphasis_55=0x46408 +serdes_driver_current_56=0xf +serdes_preemphasis_56=0x46408 +serdes_driver_current_57=0xf +serdes_preemphasis_57=0x46408 +serdes_driver_current_58=0xf +serdes_preemphasis_58=0x373108 +serdes_driver_current_59=0xf +serdes_preemphasis_59=0x373108 +serdes_driver_current_68=0xf +serdes_preemphasis_68=0x373108 +serdes_driver_current_69=0xf +serdes_preemphasis_69=0x373108 +serdes_driver_current_70=0xf +serdes_preemphasis_70=0x46408 +serdes_driver_current_71=0xf +serdes_preemphasis_71=0x46408 +serdes_driver_current_72=0xf +serdes_preemphasis_72=0x46408 +serdes_driver_current_73=0xf +serdes_preemphasis_73=0x46408 +serdes_driver_current_74=0xf +serdes_preemphasis_74=0x46408 +serdes_driver_current_75=0xf +serdes_preemphasis_75=0x46408 +serdes_driver_current_76=0xf +serdes_preemphasis_76=0x46408 +serdes_driver_current_77=0xf +serdes_preemphasis_77=0x46408 +serdes_driver_current_78=0xf +serdes_preemphasis_78=0x46408 +serdes_driver_current_79=0xf +serdes_preemphasis_79=0x46408 +serdes_driver_current_80=0xf +serdes_preemphasis_80=0x46408 +serdes_driver_current_81=0xf +serdes_preemphasis_81=0x46408 +serdes_driver_current_82=0xf +serdes_preemphasis_82=0x46408 +serdes_driver_current_83=0xf +serdes_preemphasis_83=0x46408 +serdes_driver_current_84=0xf +serdes_preemphasis_84=0x46408 +serdes_driver_current_85=0xf +serdes_preemphasis_85=0x46408 +serdes_driver_current_86=0xf +serdes_preemphasis_86=0x46408 +serdes_driver_current_87=0xf +serdes_preemphasis_87=0x46408 +serdes_driver_current_88=0xf +serdes_preemphasis_88=0x46408 +serdes_driver_current_89=0xf +serdes_preemphasis_89=0x46408 +serdes_driver_current_90=0xf +serdes_preemphasis_90=0x46408 +serdes_driver_current_91=0xf +serdes_preemphasis_91=0x46408 +serdes_driver_current_92=0xf +serdes_preemphasis_92=0x46408 +serdes_driver_current_93=0xf +serdes_preemphasis_93=0x46408 +serdes_driver_current_102=0xf +serdes_preemphasis_102=0x46408 +serdes_driver_current_103=0xf +serdes_preemphasis_103=0x46408 +serdes_driver_current_104=0xf +serdes_preemphasis_104=0x46408 +serdes_driver_current_105=0xf +serdes_preemphasis_105=0x46408 +serdes_driver_current_106=0xf +serdes_preemphasis_106=0x46408 +serdes_driver_current_107=0xf +serdes_preemphasis_107=0x46408 +serdes_driver_current_108=0xf +serdes_preemphasis_108=0x46408 +serdes_driver_current_109=0xf +serdes_preemphasis_109=0x46408 +serdes_driver_current_110=0xf +serdes_preemphasis_110=0x46408 +serdes_driver_current_111=0xf +serdes_preemphasis_111=0x46408 +serdes_driver_current_112=0xf +serdes_preemphasis_112=0x46408 +serdes_driver_current_113=0xf +serdes_preemphasis_113=0x46408 +serdes_driver_current_114=0xf +serdes_preemphasis_114=0x46408 +serdes_driver_current_115=0xf +serdes_preemphasis_115=0x46408 +serdes_driver_current_116=0xf +serdes_preemphasis_116=0x46408 +serdes_driver_current_117=0xf +serdes_preemphasis_117=0x46408 +serdes_driver_current_118=0xf +serdes_preemphasis_118=0x46408 +serdes_driver_current_119=0xf +serdes_preemphasis_119=0x46408 +serdes_driver_current_120=0xf +serdes_preemphasis_120=0x46408 +serdes_driver_current_121=0xf +serdes_preemphasis_121=0x46408 +serdes_driver_current_122=0xf +serdes_preemphasis_122=0x46408 +serdes_driver_current_123=0xf +serdes_preemphasis_123=0x46408 +serdes_driver_current_124=0xf +serdes_preemphasis_124=0x46408 +serdes_driver_current_125=0xf +serdes_preemphasis_125=0x46408 +serdes_driver_current_126=0xa +serdes_preemphasis_126=0x284008 +serdes_driver_current_127=0xa +serdes_preemphasis_127=0x284008 diff --git a/device/arista/x86_64-arista_7060_cx32s/default_sku b/device/arista/x86_64-arista_7060_cx32s/default_sku new file mode 100644 index 000000000000..e94d12dba895 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/default_sku @@ -0,0 +1 @@ +Arista-7060CX-32S-C32 t1 diff --git a/device/arista/x86_64-arista_7060_cx32s/fancontrol b/device/arista/x86_64-arista_7060_cx32s/fancontrol new file mode 100644 index 000000000000..43f885a9f246 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=5 +DEVPATH=hwmon2=devices/pci0000:00/0000:00:02.2/0000:02:00.0/i2c-2/2-001a hwmon4=devices/pci0000:00/0000:00:02.2/0000:02:00.0/i2c-3/3-0060 +DEVNAME=hwmon2=max6697 hwmon4=crow_cpld +FCTEMPS=hwmon4/pwm4=hwmon2/temp1_input hwmon4/pwm3=hwmon2/temp1_input hwmon4/pwm2=hwmon2/temp1_input hwmon4/pwm1=hwmon2/temp1_input +FCFANS=hwmon4/pwm4=hwmon4/fan4_input hwmon4/pwm3=hwmon4/fan3_input hwmon4/pwm2=hwmon4/fan2_input hwmon4/pwm1=hwmon4/fan1_input +MINTEMP=hwmon4/pwm4=40 hwmon4/pwm3=40 hwmon4/pwm2=40 hwmon4/pwm1=40 +MINPWM=hwmon4/pwm4=179 hwmon4/pwm3=179 hwmon4/pwm2=179 hwmon4/pwm1=179 +MAXTEMP=hwmon4/pwm4=50 hwmon4/pwm3=50 hwmon4/pwm2=50 hwmon4/pwm1=50 +MINSTART=hwmon4/pwm4=179 hwmon4/pwm3=179 hwmon4/pwm2=179 hwmon4/pwm1=179 +MINSTOP=hwmon4/pwm4=179 hwmon4/pwm3=179 hwmon4/pwm2=179 hwmon4/pwm1=179 diff --git a/device/arista/x86_64-arista_7060_cx32s/pcie.yaml b/device/arista/x86_64-arista_7060_cx32s/pcie.yaml new file mode 100644 index 000000000000..a988a7d1c5fc --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/pcie.yaml @@ -0,0 +1,140 @@ +- bus: '00' + dev: '00' + fn: '0' + id: '1566' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Root Complex' +- bus: '00' + dev: '00' + fn: '2' + id: '1567' + name: 'IOMMU: Advanced Micro Devices, Inc. [AMD] Mullins IOMMU' +- bus: '00' + dev: '02' + fn: '0' + id: 156b + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Host Bridge' +- bus: '00' + dev: '02' + fn: '1' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '2' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '3' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '4' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: '02' + fn: '5' + id: '1439' + name: 'PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 16h Processor Functions + 5:1' +- bus: '00' + dev: 08 + fn: '0' + id: '1537' + name: 'Encryption controller: Advanced Micro Devices, Inc. [AMD] Kabini/Mullins + PSP-Platform Security Processor' +- bus: '00' + dev: '11' + fn: '0' + id: '7801' + name: 'SATA controller: Advanced Micro Devices, Inc. [AMD] FCH SATA Controller [AHCI + mode] (rev 40)' +- bus: '00' + dev: '12' + fn: '0' + id: '7808' + name: 'USB controller: Advanced Micro Devices, Inc. [AMD] FCH USB EHCI Controller + (rev 39)' +- bus: '00' + dev: '14' + fn: '0' + id: 780b + name: 'SMBus: Advanced Micro Devices, Inc. [AMD] FCH SMBus Controller (rev 42)' +- bus: '00' + dev: '14' + fn: '3' + id: 780e + name: 'ISA bridge: Advanced Micro Devices, Inc. [AMD] FCH LPC Bridge (rev 11)' +- bus: '00' + dev: '14' + fn: '7' + id: '7813' + name: 'SD Host controller: Advanced Micro Devices, Inc. [AMD] FCH SD Flash Controller + (rev 01)' +- bus: '00' + dev: '18' + fn: '0' + id: '1580' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 0' +- bus: '00' + dev: '18' + fn: '1' + id: '1581' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 1' +- bus: '00' + dev: '18' + fn: '2' + id: '1582' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 2' +- bus: '00' + dev: '18' + fn: '3' + id: '1583' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 3' +- bus: '00' + dev: '18' + fn: '4' + id: '1584' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 4' +- bus: '00' + dev: '18' + fn: '5' + id: '1585' + name: 'Host bridge: Advanced Micro Devices, Inc. [AMD] Family 16h (Models 30h-3fh) + Processor Function 5' +- bus: '01' + dev: '00' + fn: '0' + id: b960 + name: 'Ethernet controller: Broadcom Limited Broadcom BCM56960 Switch ASIC (rev + 12)' +- bus: '01' + dev: '00' + fn: '1' + id: b960 + name: 'Ethernet controller: Broadcom Limited Broadcom BCM56960 Switch ASIC (rev + 12)' +- bus: '02' + dev: '00' + fn: '0' + id: '0001' + name: 'System peripheral: Arastra Inc. Device 0001 (rev 01)' +- bus: '04' + dev: '00' + fn: '0' + id: '1682' + name: 'Ethernet controller: Broadcom Limited NetXtreme BCM57762 Gigabit Ethernet + PCIe (rev 20)' diff --git a/device/arista/x86_64-arista_7060_cx32s/platform.json b/device/arista/x86_64-arista_7060_cx32s/platform.json new file mode 100644 index 000000000000..fe62f3db0c53 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/platform.json @@ -0,0 +1,197 @@ +{ + "chassis": { + "name": "DCS-7060CX-32S", + "components": [], + "fans": [], + "fan_drawers": [ + { + "name": "slot1", + "fans": [ + { + "name": "fan1" + } + ] + }, + { + "name": "slot2", + "fans": [ + { + "name": "fan2" + } + ] + }, + { + "name": "slot3", + "fans": [ + { + "name": "fan3" + } + ] + }, + { + "name": "slot4", + "fans": [ + { + "name": "fan4" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Cpu temp sensor" + }, + { + "name": "Cpu board temp sensor" + }, + { + "name": "Back-panel temp sensor" + }, + { + "name": "Board sensor" + }, + { + "name": "Switch chip left sensor" + }, + { + "name": "Switch chip right sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Power supply 1 hotspot sensor" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 exhaust temp sensor" + }, + { + "name": "Power supply 2 hotspot sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 exhaust temp sensor" + } + ], + "sfps": [ + { + "name": "qsfp1" + }, + { + "name": "qsfp2" + }, + { + "name": "qsfp3" + }, + { + "name": "qsfp4" + }, + { + "name": "qsfp5" + }, + { + "name": "qsfp6" + }, + { + "name": "qsfp7" + }, + { + "name": "qsfp8" + }, + { + "name": "qsfp9" + }, + { + "name": "qsfp10" + }, + { + "name": "qsfp11" + }, + { + "name": "qsfp12" + }, + { + "name": "qsfp13" + }, + { + "name": "qsfp14" + }, + { + "name": "qsfp15" + }, + { + "name": "qsfp16" + }, + { + "name": "qsfp17" + }, + { + "name": "qsfp18" + }, + { + "name": "qsfp19" + }, + { + "name": "qsfp20" + }, + { + "name": "qsfp21" + }, + { + "name": "qsfp22" + }, + { + "name": "qsfp23" + }, + { + "name": "qsfp24" + }, + { + "name": "qsfp25" + }, + { + "name": "qsfp26" + }, + { + "name": "qsfp27" + }, + { + "name": "qsfp28" + }, + { + "name": "qsfp29" + }, + { + "name": "qsfp30" + }, + { + "name": "qsfp31" + }, + { + "name": "qsfp32" + }, + { + "name": "sfp33" + }, + { + "name": "sfp34" + } + ] + }, + "interfaces": {} +} \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060_cx32s/platform_reboot b/device/arista/x86_64-arista_7060_cx32s/platform_reboot new file mode 120000 index 000000000000..7f94a49e38b0 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/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_7060_cx32s/plugins/eeprom.py b/device/arista/x86_64-arista_7060_cx32s/plugins/eeprom.py new file mode 120000 index 000000000000..35cfaff3de4e --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/plugins/eeprom.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/eeprom.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060_cx32s/plugins/led_control.py b/device/arista/x86_64-arista_7060_cx32s/plugins/led_control.py new file mode 120000 index 000000000000..8d733780117e --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/plugins/led_control.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/led_control.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060_cx32s/plugins/psuutil.py b/device/arista/x86_64-arista_7060_cx32s/plugins/psuutil.py new file mode 120000 index 000000000000..2b0024ade969 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/plugins/psuutil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/psuutil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060_cx32s/plugins/sfputil.py b/device/arista/x86_64-arista_7060_cx32s/plugins/sfputil.py new file mode 120000 index 000000000000..c333e23763d7 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/plugins/sfputil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/sfputil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060_cx32s/pmon_daemon_control.json b/device/arista/x86_64-arista_7060_cx32s/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060_cx32s/sensors.conf b/device/arista/x86_64-arista_7060_cx32s/sensors.conf new file mode 100644 index 000000000000..57e785881912 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/sensors.conf @@ -0,0 +1,51 @@ +# libsensors configuration file for DCS-7060CX-32S +# ------------------------------------------------ +# + +bus "i2c-2" "SCD 0000:02:00.0 SMBus master 0 bus 0" +bus "i2c-3" "SCD 0000:02:00.0 SMBus master 0 bus 1" +bus "i2c-5" "SCD 0000:02:00.0 SMBus master 0 bus 3" +bus "i2c-6" "SCD 0000:02:00.0 SMBus master 0 bus 4" +bus "i2c-7" "SCD 0000:02:00.0 SMBus master 0 bus 5" + +chip "k10temp-pci-00c3" + label temp1 "Cpu temp sensor" + +chip "max6697-i2c-2-1a" + label temp1 "Board sensor" + set temp1_max 95 + + label temp2 "Switch chip left sensor" + set temp2_max 95 + set temp2_crit 105 + + ignore temp3 + ignore temp4 + ignore temp5 + + label temp6 "Switch chip right sensor" + set temp6_max 95 + set temp6_crit 105 + + label temp7 "Front panel temp sensor" + set temp7_max 65 + set temp7_crit 75 + +chip "max6658-i2c-3-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 80 + +chip "pmbus-i2c-6-58" + label temp1 "Power supply 1 hotspot sensor" + label temp2 "Power supply 1 inlet temp sensor" + label temp3 "Power supply 1 exhaust temp sensor" + +chip "pmbus-i2c-5-58" + label temp1 "Power supply 2 hotspot sensor" + label temp2 "Power supply 2 inlet temp sensor" + label temp3 "Power supply 2 exhaust temp sensor" diff --git a/device/arista/x86_64-arista_7060_cx32s/system_health_monitoring_config.json b/device/arista/x86_64-arista_7060_cx32s/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060_cx32s/thermal_policy.json b/device/arista/x86_64-arista_7060_cx32s/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file 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.json b/device/arista/x86_64-arista_7060cx2_32s/platform.json new file mode 100644 index 000000000000..fae3f8764735 --- /dev/null +++ b/device/arista/x86_64-arista_7060cx2_32s/platform.json @@ -0,0 +1,197 @@ +{ + "chassis": { + "name": "DCS-7060CX2-32S", + "components": [], + "fans": [], + "fan_drawers": [ + { + "name": "slot1", + "fans": [ + { + "name": "fan1" + } + ] + }, + { + "name": "slot2", + "fans": [ + { + "name": "fan2" + } + ] + }, + { + "name": "slot3", + "fans": [ + { + "name": "fan3" + } + ] + }, + { + "name": "slot4", + "fans": [ + { + "name": "fan4" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Cpu temp sensor" + }, + { + "name": "Cpu board temp sensor" + }, + { + "name": "Back-panel temp sensor" + }, + { + "name": "Board sensor" + }, + { + "name": "Switch chip left sensor" + }, + { + "name": "Switch chip right sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Power supply 1 hotspot sensor" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 exhaust temp sensor" + }, + { + "name": "Power supply 2 hotspot sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 exhaust temp sensor" + } + ], + "sfps": [ + { + "name": "qsfp1" + }, + { + "name": "qsfp2" + }, + { + "name": "qsfp3" + }, + { + "name": "qsfp4" + }, + { + "name": "qsfp5" + }, + { + "name": "qsfp6" + }, + { + "name": "qsfp7" + }, + { + "name": "qsfp8" + }, + { + "name": "qsfp9" + }, + { + "name": "qsfp10" + }, + { + "name": "qsfp11" + }, + { + "name": "qsfp12" + }, + { + "name": "qsfp13" + }, + { + "name": "qsfp14" + }, + { + "name": "qsfp15" + }, + { + "name": "qsfp16" + }, + { + "name": "qsfp17" + }, + { + "name": "qsfp18" + }, + { + "name": "qsfp19" + }, + { + "name": "qsfp20" + }, + { + "name": "qsfp21" + }, + { + "name": "qsfp22" + }, + { + "name": "qsfp23" + }, + { + "name": "qsfp24" + }, + { + "name": "qsfp25" + }, + { + "name": "qsfp26" + }, + { + "name": "qsfp27" + }, + { + "name": "qsfp28" + }, + { + "name": "qsfp29" + }, + { + "name": "qsfp30" + }, + { + "name": "qsfp31" + }, + { + "name": "qsfp32" + }, + { + "name": "sfp33" + }, + { + "name": "sfp34" + } + ] + }, + "interfaces": {} +} 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/pmon_daemon_control.json b/device/arista/x86_64-arista_7060cx2_32s/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7060cx2_32s/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ 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_7060cx2_32s/system_health_monitoring_config.json b/device/arista/x86_64-arista_7060cx2_32s/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7060cx2_32s/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060cx2_32s/thermal_policy.json b/device/arista/x86_64-arista_7060cx2_32s/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7060cx2_32s/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/Arista-7060DX4-C32 b/device/arista/x86_64-arista_7060dx4_32/Arista-7060DX4-C32 new file mode 120000 index 000000000000..19cc64c75f13 --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/Arista-7060DX4-C32 @@ -0,0 +1 @@ +../x86_64-arista_7060px4_32/Arista-7060DX4-C32 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/Arista-7060PX4-C64 b/device/arista/x86_64-arista_7060dx4_32/Arista-7060PX4-C64 new file mode 120000 index 000000000000..f0d5c7697f08 --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/Arista-7060PX4-C64 @@ -0,0 +1 @@ +../x86_64-arista_7060px4_32/Arista-7060PX4-C64 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/Arista-7060PX4-O32 b/device/arista/x86_64-arista_7060dx4_32/Arista-7060PX4-O32 new file mode 120000 index 000000000000..1e0685f3fb42 --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/Arista-7060PX4-O32 @@ -0,0 +1 @@ +../x86_64-arista_7060px4_32/Arista-7060PX4-O32 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/default_sku b/device/arista/x86_64-arista_7060dx4_32/default_sku new file mode 120000 index 000000000000..ebca56647346 --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/default_sku @@ -0,0 +1 @@ +../x86_64-arista_7060px4_32/default_sku \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/fancontrol b/device/arista/x86_64-arista_7060dx4_32/fancontrol new file mode 120000 index 000000000000..099befbdee42 --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/fancontrol @@ -0,0 +1 @@ +../x86_64-arista_7060px4_32/fancontrol \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/platform.json b/device/arista/x86_64-arista_7060dx4_32/platform.json new file mode 100644 index 000000000000..d37370b0d948 --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/platform.json @@ -0,0 +1,223 @@ +{ + "chassis": { + "name": "DCS-7060DX4-32", + "components": [], + "fans": [], + "fan_drawers": [ + { + "name": "slot1", + "fans": [ + { + "name": "fan1" + } + ] + }, + { + "name": "slot2", + "fans": [ + { + "name": "fan2" + } + ] + }, + { + "name": "slot3", + "fans": [ + { + "name": "fan3" + } + ] + }, + { + "name": "slot4", + "fans": [ + { + "name": "fan4" + } + ] + }, + { + "name": "slot5", + "fans": [ + { + "name": "fan5" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Board sensor" + }, + { + "name": "Switch board middle sensor" + }, + { + "name": "Switch board left sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Switch chip diode 1 sensor" + }, + { + "name": "Switch chip diode 2 sensor" + }, + { + "name": "PCH temp sensor" + }, + { + "name": "Physical id 0" + }, + { + "name": "CPU core0 temp sensor" + }, + { + "name": "CPU core1 temp sensor" + }, + { + "name": "CPU board temp sensor" + }, + { + "name": "Back-panel temp sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Power supply 1 hotspot sensor" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 exhaust temp sensor" + }, + { + "name": "Power supply 2 hotspot sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 exhaust temp sensor" + } + ], + "sfps": [ + { + "name": "osfp1" + }, + { + "name": "osfp2" + }, + { + "name": "osfp3" + }, + { + "name": "osfp4" + }, + { + "name": "osfp5" + }, + { + "name": "osfp6" + }, + { + "name": "osfp7" + }, + { + "name": "osfp8" + }, + { + "name": "osfp9" + }, + { + "name": "osfp10" + }, + { + "name": "osfp11" + }, + { + "name": "osfp12" + }, + { + "name": "osfp13" + }, + { + "name": "osfp14" + }, + { + "name": "osfp15" + }, + { + "name": "osfp16" + }, + { + "name": "osfp17" + }, + { + "name": "osfp18" + }, + { + "name": "osfp19" + }, + { + "name": "osfp20" + }, + { + "name": "osfp21" + }, + { + "name": "osfp22" + }, + { + "name": "osfp23" + }, + { + "name": "osfp24" + }, + { + "name": "osfp25" + }, + { + "name": "osfp26" + }, + { + "name": "osfp27" + }, + { + "name": "osfp28" + }, + { + "name": "osfp29" + }, + { + "name": "osfp30" + }, + { + "name": "osfp31" + }, + { + "name": "osfp32" + }, + { + "name": "sfp33" + }, + { + "name": "sfp34" + } + ] + }, + "interfaces": {} +} diff --git a/device/arista/x86_64-arista_7060dx4_32/platform_reboot b/device/arista/x86_64-arista_7060dx4_32/platform_reboot new file mode 120000 index 000000000000..d82455f8577b --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/platform_reboot @@ -0,0 +1 @@ +../x86_64-arista_7060px4_32/platform_reboot \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/plugins b/device/arista/x86_64-arista_7060dx4_32/plugins new file mode 120000 index 000000000000..b2db88a63359 --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/plugins @@ -0,0 +1 @@ +../x86_64-arista_7060px4_32/plugins \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/pmon_daemon_control.json b/device/arista/x86_64-arista_7060dx4_32/pmon_daemon_control.json new file mode 120000 index 000000000000..247cff87a9ea --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_7060px4_32/pmon_daemon_control.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/sensors.conf b/device/arista/x86_64-arista_7060dx4_32/sensors.conf new file mode 120000 index 000000000000..efe0b2605896 --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/sensors.conf @@ -0,0 +1 @@ +../x86_64-arista_7060px4_32/sensors.conf \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/system_health_monitoring_config.json b/device/arista/x86_64-arista_7060dx4_32/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060dx4_32/thermal_policy.json b/device/arista/x86_64-arista_7060dx4_32/thermal_policy.json new file mode 120000 index 000000000000..a14947df5b5c --- /dev/null +++ b/device/arista/x86_64-arista_7060dx4_32/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_7060px4_32/thermal_policy.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060px4_32/Arista-7060DX4-C32/port_config.ini b/device/arista/x86_64-arista_7060px4_32/Arista-7060DX4-C32/port_config.ini new file mode 100644 index 000000000000..45ef9b7754b9 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/Arista-7060DX4-C32/port_config.ini @@ -0,0 +1,35 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4,5,6,7,8 Ethernet1/1 1 400000 +Ethernet8 9,10,11,12,13,14,15,16 Ethernet2/1 2 400000 +Ethernet16 17,18,19,20,21,22,23,24 Ethernet3/1 3 400000 +Ethernet24 25,26,27,28,29,30,31,32 Ethernet4/1 4 400000 +Ethernet32 33,34,35,36,37,38,39,40 Ethernet5/1 5 400000 +Ethernet40 41,42,43,44,45,46,47,48 Ethernet6/1 6 400000 +Ethernet48 49,50,51,52,53,54,55,56 Ethernet7/1 7 400000 +Ethernet56 57,58,59,60,61,62,63,64 Ethernet8/1 8 400000 +Ethernet64 65,66,67,68,69,70,71,72 Ethernet9/1 9 400000 +Ethernet72 73,74,75,76,77,78,79,80 Ethernet10/1 10 400000 +Ethernet80 81,82,83,84,85,86,87,88 Ethernet11/1 11 400000 +Ethernet88 89,90,91,92,93,94,95,96 Ethernet12/1 12 400000 +Ethernet96 97,98,99,100,101,102,103,104 Ethernet13/1 13 400000 +Ethernet104 105,106,107,108,109,110,111,112 Ethernet14/1 14 400000 +Ethernet112 113,114,115,116,117,118,119,120 Ethernet15/1 15 400000 +Ethernet120 121,122,123,124,125,126,127,128 Ethernet16/1 16 400000 +Ethernet128 129,130,131,132,133,134,135,136 Ethernet17/1 17 400000 +Ethernet136 137,138,139,140,141,142,143,144 Ethernet18/1 18 400000 +Ethernet144 145,146,147,148,149,150,151,152 Ethernet19/1 19 400000 +Ethernet152 153,154,155,156,157,158,159,160 Ethernet20/1 20 400000 +Ethernet160 161,162,163,164,165,166,167,168 Ethernet21/1 21 400000 +Ethernet168 169,170,171,172,173,174,175,176 Ethernet22/1 22 400000 +Ethernet176 177,178,179,180,181,182,183,184 Ethernet23/1 23 400000 +Ethernet184 185,186,187,188,189,190,191,192 Ethernet24/1 24 400000 +Ethernet192 193,194,195,196,197,198,199,200 Ethernet25/1 25 400000 +Ethernet200 201,202,203,204,205,206,207,208 Ethernet26/1 26 400000 +Ethernet208 209,210,211,212,213,214,215,216 Ethernet27/1 27 400000 +Ethernet216 217,218,219,220,221,222,223,224 Ethernet28/1 28 400000 +Ethernet224 225,226,227,228,229,230,231,232 Ethernet29/1 29 400000 +Ethernet232 233,234,235,236,237,238,239,240 Ethernet30/1 30 400000 +Ethernet240 241,242,243,244,245,246,247,248 Ethernet31/1 31 400000 +Ethernet248 249,250,251,252,253,254,255,256 Ethernet32/1 32 400000 +Ethernet256 258 Ethernet33 33 10000 +Ethernet260 257 Ethernet34 34 10000 diff --git a/device/arista/x86_64-arista_7060px4_32/Arista-7060DX4-C32/sai.profile b/device/arista/x86_64-arista_7060px4_32/Arista-7060DX4-C32/sai.profile new file mode 100644 index 000000000000..296b1c8b0ecb --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/Arista-7060DX4-C32/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-a7060dx4-c32-32x400G.config.bcm diff --git a/device/arista/x86_64-arista_7060px4_32/Arista-7060DX4-C32/th3-a7060dx4-c32-32x400G.config.bcm b/device/arista/x86_64-arista_7060px4_32/Arista-7060DX4-C32/th3-a7060dx4-c32-32x400G.config.bcm new file mode 100644 index 000000000000..7bd96fed83b8 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/Arista-7060DX4-C32/th3-a7060dx4-c32-32x400G.config.bcm @@ -0,0 +1,848 @@ +arl_clean_timeout_usec=15000000 +asf_mem_profile.0=2 +bcm_num_cos.0=8 +bcm_stat_flags=1 +bcm_stat_jumbo.0=9236 +cdma_timeout_usec.0=15000000 +disable_pcie_firmware_check.0=1 +dma_desc_timeout_usec.0=15000000 +dpr_clock_frequency.0=1000 +l2xmsg_mode.0=1 +l2_mem_entries.0=8192 +l3_alpm_enable.0=2 +l3_mem_entries.0=16384 +max_vp_lags.0=0 +miim_intr_enable.0=0 +module_64ports.0=1 +multicast_l2_range.0=511 +oversubscribe_mode=1 +parity_correction=1 +parity_enable=1 +pbmp_xport_xe.0=0x3ffffffffffffffffffffffffffffffffffffffe +phy_an_c37_38.0=2 +phy_an_c37_118.0=2 +phy_an_c73_1.0=1 +phy_an_c73_2.0=1 +phy_an_c73_3.0=1 +phy_an_c73_4.0=1 +phy_an_c73_20.0=1 +phy_an_c73_21.0=1 +phy_an_c73_22.0=1 +phy_an_c73_23.0=1 +phy_an_c73_38.0=0 +phy_an_c73_40.0=1 +phy_an_c73_41.0=1 +phy_an_c73_42.0=1 +phy_an_c73_43.0=1 +phy_an_c73_60.0=1 +phy_an_c73_61.0=1 +phy_an_c73_62.0=1 +phy_an_c73_63.0=1 +phy_an_c73_80.0=1 +phy_an_c73_81.0=1 +phy_an_c73_82.0=1 +phy_an_c73_83.0=1 +phy_an_c73_100.0=1 +phy_an_c73_101.0=1 +phy_an_c73_102.0=1 +phy_an_c73_103.0=1 +phy_an_c73_118.0=0 +phy_an_c73_120.0=1 +phy_an_c73_121.0=1 +phy_an_c73_122.0=1 +phy_an_c73_123.0=1 +phy_an_c73_140.0=1 +phy_an_c73_141.0=1 +phy_an_c73_142.0=1 +phy_an_c73_143.0=1 +phy_chain_rx_lane_map_physical{1.0}=0x42537160 +phy_chain_rx_lane_map_physical{9.0}=0x60715342 +phy_chain_rx_lane_map_physical{17.0}=0x06173425 +phy_chain_rx_lane_map_physical{25.0}=0x02471356 +phy_chain_rx_lane_map_physical{33.0}=0x27160534 +phy_chain_rx_lane_map_physical{41.0}=0x02461357 +phy_chain_rx_lane_map_physical{49.0}=0x26150437 +phy_chain_rx_lane_map_physical{57.0}=0x02461357 +phy_chain_rx_lane_map_physical{65.0}=0x27140536 +phy_chain_rx_lane_map_physical{73.0}=0x02471356 +phy_chain_rx_lane_map_physical{81.0}=0x27140536 +phy_chain_rx_lane_map_physical{89.0}=0x02471356 +phy_chain_rx_lane_map_physical{97.0}=0x02461357 +phy_chain_rx_lane_map_physical{105.0}=0x57124603 +phy_chain_rx_lane_map_physical{113.0}=0x17243506 +phy_chain_rx_lane_map_physical{121.0}=0x46315720 +phy_chain_rx_lane_map_physical{129.0}=0x60534271 +phy_chain_rx_lane_map_physical{137.0}=0x02461357 +phy_chain_rx_lane_map_physical{145.0}=0x27140536 +phy_chain_rx_lane_map_physical{153.0}=0x50271463 +phy_chain_rx_lane_map_physical{161.0}=0x31652074 +phy_chain_rx_lane_map_physical{169.0}=0x02461357 +phy_chain_rx_lane_map_physical{177.0}=0x26140537 +phy_chain_rx_lane_map_physical{185.0}=0x02461357 +phy_chain_rx_lane_map_physical{193.0}=0x26140537 +phy_chain_rx_lane_map_physical{201.0}=0x02461357 +phy_chain_rx_lane_map_physical{209.0}=0x27140536 +phy_chain_rx_lane_map_physical{217.0}=0x02641357 +phy_chain_rx_lane_map_physical{225.0}=0x60734251 +phy_chain_rx_lane_map_physical{233.0}=0x31462057 +phy_chain_rx_lane_map_physical{241.0}=0x60715342 +phy_chain_rx_lane_map_physical{249.0}=0x35216047 +phy_chain_rx_lane_map_physical{257.0}=0x3210 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +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{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +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{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{47.0}=0x1 +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{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x1 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +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}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x1 +phy_chain_rx_polarity_flip_physical{80.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}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x1 +phy_chain_rx_polarity_flip_physical{99.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +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}=0x0 +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}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x1 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 +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}=0x1 +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{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 +phy_chain_rx_polarity_flip_physical{125.0}=0x0 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x0 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x1 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_rx_polarity_flip_physical{141.0}=0x0 +phy_chain_rx_polarity_flip_physical{142.0}=0x1 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x1 +phy_chain_rx_polarity_flip_physical{147.0}=0x0 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_rx_polarity_flip_physical{149.0}=0x1 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x0 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x1 +phy_chain_rx_polarity_flip_physical{157.0}=0x1 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x1 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x1 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x0 +phy_chain_rx_polarity_flip_physical{168.0}=0x0 +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x1 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x1 +phy_chain_rx_polarity_flip_physical{175.0}=0x1 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 +phy_chain_rx_polarity_flip_physical{177.0}=0x0 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x0 +phy_chain_rx_polarity_flip_physical{181.0}=0x1 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_rx_polarity_flip_physical{185.0}=0x0 +phy_chain_rx_polarity_flip_physical{186.0}=0x1 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x1 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x0 +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x1 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_rx_polarity_flip_physical{205.0}=0x0 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x1 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x0 +phy_chain_rx_polarity_flip_physical{213.0}=0x1 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x0 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 +phy_chain_rx_polarity_flip_physical{217.0}=0x0 +phy_chain_rx_polarity_flip_physical{218.0}=0x1 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x0 +phy_chain_rx_polarity_flip_physical{221.0}=0x0 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x1 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 +phy_chain_rx_polarity_flip_physical{225.0}=0x0 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x0 +phy_chain_rx_polarity_flip_physical{229.0}=0x0 +phy_chain_rx_polarity_flip_physical{230.0}=0x1 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x0 +phy_chain_rx_polarity_flip_physical{233.0}=0x0 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x1 +phy_chain_rx_polarity_flip_physical{241.0}=0x1 +phy_chain_rx_polarity_flip_physical{242.0}=0x0 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x0 +phy_chain_rx_polarity_flip_physical{245.0}=0x0 +phy_chain_rx_polarity_flip_physical{246.0}=0x1 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 +phy_chain_rx_polarity_flip_physical{249.0}=0x1 +phy_chain_rx_polarity_flip_physical{250.0}=0x1 +phy_chain_rx_polarity_flip_physical{251.0}=0x0 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 +phy_chain_rx_polarity_flip_physical{253.0}=0x0 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x1 +phy_chain_rx_polarity_flip_physical{256.0}=0x1 +phy_chain_rx_polarity_flip_physical{257.0}=0x0 +phy_chain_rx_polarity_flip_physical{258.0}=0x0 +phy_chain_tx_lane_map_physical{1.0}=0x30451627 +phy_chain_tx_lane_map_physical{9.0}=0x74532610 +phy_chain_tx_lane_map_physical{17.0}=0x51407362 +phy_chain_tx_lane_map_physical{25.0}=0x27160435 +phy_chain_tx_lane_map_physical{33.0}=0x65347021 +phy_chain_tx_lane_map_physical{41.0}=0x16072435 +phy_chain_tx_lane_map_physical{49.0}=0x75126430 +phy_chain_tx_lane_map_physical{57.0}=0x26071435 +phy_chain_tx_lane_map_physical{65.0}=0x75026431 +phy_chain_tx_lane_map_physical{73.0}=0x26071435 +phy_chain_tx_lane_map_physical{81.0}=0x75026431 +phy_chain_tx_lane_map_physical{89.0}=0x26071435 +phy_chain_tx_lane_map_physical{97.0}=0x03746521 +phy_chain_tx_lane_map_physical{105.0}=0x06142735 +phy_chain_tx_lane_map_physical{113.0}=0x56237014 +phy_chain_tx_lane_map_physical{121.0}=0x01426375 +phy_chain_tx_lane_map_physical{129.0}=0x12673450 +phy_chain_tx_lane_map_physical{137.0}=0x45062731 +phy_chain_tx_lane_map_physical{145.0}=0x56237014 +phy_chain_tx_lane_map_physical{153.0}=0x56012437 +phy_chain_tx_lane_map_physical{161.0}=0x76215430 +phy_chain_tx_lane_map_physical{169.0}=0x57362410 +phy_chain_tx_lane_map_physical{177.0}=0x76215430 +phy_chain_tx_lane_map_physical{185.0}=0x57362410 +phy_chain_tx_lane_map_physical{193.0}=0x76215430 +phy_chain_tx_lane_map_physical{201.0}=0x57362410 +phy_chain_tx_lane_map_physical{209.0}=0x76215430 +phy_chain_tx_lane_map_physical{217.0}=0x57261430 +phy_chain_tx_lane_map_physical{225.0}=0x65217430 +phy_chain_tx_lane_map_physical{233.0}=0x45063721 +phy_chain_tx_lane_map_physical{241.0}=0x75216430 +phy_chain_tx_lane_map_physical{249.0}=0x64275130 +phy_chain_tx_lane_map_physical{257.0}=0x3210 +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{17.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +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{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}=0x0 +phy_chain_tx_polarity_flip_physical{60.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}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.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}=0x0 +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{81.0}=0x1 +phy_chain_tx_polarity_flip_physical{82.0}=0x1 +phy_chain_tx_polarity_flip_physical{83.0}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 +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{91.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{109.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +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}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x0 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x1 +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{130.0}=0x1 +phy_chain_tx_polarity_flip_physical{131.0}=0x0 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x1 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x0 +phy_chain_tx_polarity_flip_physical{136.0}=0x0 +phy_chain_tx_polarity_flip_physical{137.0}=0x0 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x1 +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x1 +phy_chain_tx_polarity_flip_physical{143.0}=0x0 +phy_chain_tx_polarity_flip_physical{144.0}=0x0 +phy_chain_tx_polarity_flip_physical{145.0}=0x0 +phy_chain_tx_polarity_flip_physical{146.0}=0x1 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x0 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x1 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x1 +phy_chain_tx_polarity_flip_physical{159.0}=0x1 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x1 +phy_chain_tx_polarity_flip_physical{163.0}=0x1 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{165.0}=0x0 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x1 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x1 +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x1 +phy_chain_tx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x1 +phy_chain_tx_polarity_flip_physical{179.0}=0x1 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 +phy_chain_tx_polarity_flip_physical{185.0}=0x1 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x0 +phy_chain_tx_polarity_flip_physical{190.0}=0x1 +phy_chain_tx_polarity_flip_physical{191.0}=0x1 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x1 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x0 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x0 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 +phy_chain_tx_polarity_flip_physical{201.0}=0x1 +phy_chain_tx_polarity_flip_physical{202.0}=0x0 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x1 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 +phy_chain_tx_polarity_flip_physical{209.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x1 +phy_chain_tx_polarity_flip_physical{211.0}=0x1 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x0 +phy_chain_tx_polarity_flip_physical{217.0}=0x0 +phy_chain_tx_polarity_flip_physical{218.0}=0x1 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x1 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x1 +phy_chain_tx_polarity_flip_physical{223.0}=0x1 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 +phy_chain_tx_polarity_flip_physical{225.0}=0x0 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x1 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x0 +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x1 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 +phy_chain_tx_polarity_flip_physical{241.0}=0x0 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 +phy_chain_tx_polarity_flip_physical{245.0}=0x0 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x1 +phy_chain_tx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x1 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 +phy_chain_tx_polarity_flip_physical{253.0}=0x0 +phy_chain_tx_polarity_flip_physical{254.0}=0x0 +phy_chain_tx_polarity_flip_physical{255.0}=0x1 +phy_chain_tx_polarity_flip_physical{256.0}=0x1 +phy_chain_tx_polarity_flip_physical{257.0}=0x0 +phy_chain_tx_polarity_flip_physical{258.0}=0x0 +portmap_1.0=1:400 +portmap_2.0=9:400 +portmap_3.0=17:400 +portmap_4.0=25:400 +portmap_20.0=33:400 +portmap_21.0=41:400 +portmap_22.0=49:400 +portmap_23.0=57:400 +portmap_38.0=257:10 +portmap_40.0=65:400 +portmap_41.0=73:400 +portmap_42.0=81:400 +portmap_43.0=89:400 +portmap_60.0=97:400 +portmap_61.0=105:400 +portmap_62.0=113:400 +portmap_63.0=121:400 +portmap_80.0=129:400 +portmap_81.0=137:400 +portmap_82.0=145:400 +portmap_83.0=153:400 +portmap_100.0=161:400 +portmap_101.0=169:400 +portmap_102.0=177:400 +portmap_103.0=185:400 +portmap_118.0=258:10 +portmap_120.0=193:400 +portmap_121.0=201:400 +portmap_122.0=209:400 +portmap_123.0=217:400 +portmap_140.0=225:400 +portmap_141.0=233:400 +portmap_142.0=241:400 +portmap_143.0=249:400 +port_init_autoneg_1.0=0 +port_init_autoneg_2.0=0 +port_init_autoneg_3.0=0 +port_init_autoneg_4.0=0 +port_init_autoneg_20.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_22.0=0 +port_init_autoneg_23.0=0 +port_init_autoneg_38.0=0 +port_init_autoneg_40.0=0 +port_init_autoneg_41.0=0 +port_init_autoneg_42.0=0 +port_init_autoneg_43.0=0 +port_init_autoneg_60.0=0 +port_init_autoneg_61.0=0 +port_init_autoneg_62.0=0 +port_init_autoneg_63.0=0 +port_init_autoneg_80.0=0 +port_init_autoneg_81.0=0 +port_init_autoneg_82.0=0 +port_init_autoneg_83.0=0 +port_init_autoneg_100.0=0 +port_init_autoneg_101.0=0 +port_init_autoneg_102.0=0 +port_init_autoneg_103.0=0 +port_init_autoneg_118.0=0 +port_init_autoneg_120.0=0 +port_init_autoneg_121.0=0 +port_init_autoneg_122.0=0 +port_init_autoneg_123.0=0 +port_init_autoneg_140.0=0 +port_init_autoneg_141.0=0 +port_init_autoneg_142.0=0 +port_init_autoneg_143.0=0 +port_phy_addr_1.0=0xff +port_phy_addr_2.0=0xff +port_phy_addr_3.0=0xff +port_phy_addr_4.0=0xff +port_phy_addr_20.0=0xff +port_phy_addr_21.0=0xff +port_phy_addr_22.0=0xff +port_phy_addr_23.0=0xff +port_phy_addr_38.0=0xff +port_phy_addr_40.0=0xff +port_phy_addr_41.0=0xff +port_phy_addr_42.0=0xff +port_phy_addr_43.0=0xff +port_phy_addr_60.0=0xff +port_phy_addr_61.0=0xff +port_phy_addr_62.0=0xff +port_phy_addr_63.0=0xff +port_phy_addr_80.0=0xff +port_phy_addr_81.0=0xff +port_phy_addr_82.0=0xff +port_phy_addr_83.0=0xff +port_phy_addr_100.0=0xff +port_phy_addr_101.0=0xff +port_phy_addr_102.0=0xff +port_phy_addr_103.0=0xff +port_phy_addr_118.0=0xff +port_phy_addr_120.0=0xff +port_phy_addr_121.0=0xff +port_phy_addr_122.0=0xff +port_phy_addr_123.0=0xff +port_phy_addr_140.0=0xff +port_phy_addr_141.0=0xff +port_phy_addr_142.0=0xff +port_phy_addr_143.0=0xff +robust_hash_disable_egress_vlan.0=1 +robust_hash_disable_mpls.0=1 +robust_hash_disable_vlan.0=1 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 + +# Tuning +serdes_core_rx_polarity_flip_physical{1}=0x96 +serdes_core_rx_polarity_flip_physical{9}=0x69 +serdes_core_rx_polarity_flip_physical{17}=0x93 +serdes_core_rx_polarity_flip_physical{25}=0xd3 +serdes_core_rx_polarity_flip_physical{33}=0xcc +serdes_core_rx_polarity_flip_physical{41}=0xc3 +serdes_core_rx_polarity_flip_physical{49}=0x99 +serdes_core_rx_polarity_flip_physical{57}=0xc3 +serdes_core_rx_polarity_flip_physical{65}=0xcc +serdes_core_rx_polarity_flip_physical{73}=0xd2 +serdes_core_rx_polarity_flip_physical{81}=0xcc +serdes_core_rx_polarity_flip_physical{89}=0xd2 +serdes_core_rx_polarity_flip_physical{97}=0xc3 +serdes_core_rx_polarity_flip_physical{105}=0xd2 +serdes_core_rx_polarity_flip_physical{113}=0x66 +serdes_core_rx_polarity_flip_physical{121}=0xf0 +serdes_core_rx_polarity_flip_physical{129}=0x99 +serdes_core_rx_polarity_flip_physical{137}=0xc3 +serdes_core_rx_polarity_flip_physical{145}=0xcc +serdes_core_rx_polarity_flip_physical{153}=0x99 +serdes_core_rx_polarity_flip_physical{161}=0xd2 +serdes_core_rx_polarity_flip_physical{169}=0xc3 +serdes_core_rx_polarity_flip_physical{177}=0x8d +serdes_core_rx_polarity_flip_physical{185}=0xc3 +serdes_core_rx_polarity_flip_physical{193}=0x8d +serdes_core_rx_polarity_flip_physical{201}=0xc3 +serdes_core_rx_polarity_flip_physical{209}=0xcc +serdes_core_rx_polarity_flip_physical{217}=0xc3 +serdes_core_rx_polarity_flip_physical{225}=0x66 +serdes_core_rx_polarity_flip_physical{233}=0xf +serdes_core_rx_polarity_flip_physical{241}=0x69 +serdes_core_rx_polarity_flip_physical{249}=0x9a +serdes_core_rx_polarity_flip_physical{257}=0x0 +serdes_core_tx_polarity_flip_physical{1}=0xac +serdes_core_tx_polarity_flip_physical{9}=0xa9 +serdes_core_tx_polarity_flip_physical{17}=0x99 +serdes_core_tx_polarity_flip_physical{25}=0xc9 +serdes_core_tx_polarity_flip_physical{33}=0x4e +serdes_core_tx_polarity_flip_physical{41}=0x39 +serdes_core_tx_polarity_flip_physical{49}=0xd1 +serdes_core_tx_polarity_flip_physical{57}=0xb1 +serdes_core_tx_polarity_flip_physical{65}=0xf0 +serdes_core_tx_polarity_flip_physical{73}=0xb1 +serdes_core_tx_polarity_flip_physical{81}=0xf0 +serdes_core_tx_polarity_flip_physical{89}=0xb1 +serdes_core_tx_polarity_flip_physical{97}=0x6e +serdes_core_tx_polarity_flip_physical{105}=0xd8 +serdes_core_tx_polarity_flip_physical{113}=0xac +serdes_core_tx_polarity_flip_physical{121}=0x6c +serdes_core_tx_polarity_flip_physical{129}=0xac +serdes_core_tx_polarity_flip_physical{137}=0x6c +serdes_core_tx_polarity_flip_physical{145}=0xac +serdes_core_tx_polarity_flip_physical{153}=0xe9 +serdes_core_tx_polarity_flip_physical{161}=0xa9 +serdes_core_tx_polarity_flip_physical{169}=0xc9 +serdes_core_tx_polarity_flip_physical{177}=0xa9 +serdes_core_tx_polarity_flip_physical{185}=0xc9 +serdes_core_tx_polarity_flip_physical{193}=0xa9 +serdes_core_tx_polarity_flip_physical{201}=0xc9 +serdes_core_tx_polarity_flip_physical{209}=0xa9 +serdes_core_tx_polarity_flip_physical{217}=0xe1 +serdes_core_tx_polarity_flip_physical{225}=0x69 +serdes_core_tx_polarity_flip_physical{233}=0x66 +serdes_core_tx_polarity_flip_physical{241}=0xe1 +serdes_core_tx_polarity_flip_physical{249}=0xc6 +serdes_core_tx_polarity_flip_physical{257}=0x0 +serdes_tx_taps_cd0=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd1=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd2=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd3=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd4=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd5=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd6=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd7=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd8=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd9=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd10=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd11=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd12=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd13=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd14=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd15=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd16=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd17=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd18=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd19=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd20=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd21=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd22=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd23=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd24=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd25=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd26=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd27=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd28=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd29=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd30=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd31=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd32=pam4:1:34:9:0:0:0 +serdes_tx_taps_cd33=pam4:1:34:9:0:0:0 diff --git a/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-C64/port_config.ini b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-C64/port_config.ini new file mode 100644 index 000000000000..3a6435986491 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-C64/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4 Ethernet1/1 1 100000 +Ethernet4 5,6,7,8 Ethernet1/5 1 100000 +Ethernet8 9,10,11,12 Ethernet2/1 2 100000 +Ethernet12 13,14,15,16 Ethernet2/5 2 100000 +Ethernet16 17,18,19,20 Ethernet3/1 3 100000 +Ethernet20 21,22,23,24 Ethernet3/5 3 100000 +Ethernet24 25,26,27,28 Ethernet4/1 4 100000 +Ethernet28 29,30,31,32 Ethernet4/5 4 100000 +Ethernet32 33,34,35,36 Ethernet5/1 5 100000 +Ethernet36 37,38,39,40 Ethernet5/5 5 100000 +Ethernet40 41,42,43,44 Ethernet6/1 6 100000 +Ethernet44 45,46,47,48 Ethernet6/5 6 100000 +Ethernet48 49,50,51,52 Ethernet7/1 7 100000 +Ethernet52 53,54,55,56 Ethernet7/5 7 100000 +Ethernet56 57,58,59,60 Ethernet8/1 8 100000 +Ethernet60 61,62,63,64 Ethernet8/5 8 100000 +Ethernet64 65,66,67,68 Ethernet9/1 9 100000 +Ethernet68 69,70,71,72 Ethernet9/5 9 100000 +Ethernet72 73,74,75,76 Ethernet10/1 10 100000 +Ethernet76 77,78,79,80 Ethernet10/5 10 100000 +Ethernet80 81,82,83,84 Ethernet11/1 11 100000 +Ethernet84 85,86,87,88 Ethernet11/5 11 100000 +Ethernet88 89,90,91,92 Ethernet12/1 12 100000 +Ethernet92 93,94,95,96 Ethernet12/5 12 100000 +Ethernet96 97,98,99,100 Ethernet13/1 13 100000 +Ethernet100 101,102,103,104 Ethernet13/5 13 100000 +Ethernet104 105,106,107,108 Ethernet14/1 14 100000 +Ethernet108 109,110,111,112 Ethernet14/5 14 100000 +Ethernet112 113,114,115,116 Ethernet15/1 15 100000 +Ethernet116 117,118,119,120 Ethernet15/5 15 100000 +Ethernet120 121,122,123,124 Ethernet16/1 16 100000 +Ethernet124 125,126,127,128 Ethernet16/5 16 100000 +Ethernet128 129,130,131,132 Ethernet17/1 17 100000 +Ethernet132 133,134,135,136 Ethernet17/5 17 100000 +Ethernet136 137,138,139,140 Ethernet18/1 18 100000 +Ethernet140 141,142,143,144 Ethernet18/5 18 100000 +Ethernet144 145,146,147,148 Ethernet19/1 19 100000 +Ethernet148 149,150,151,152 Ethernet19/5 19 100000 +Ethernet152 153,154,155,156 Ethernet20/1 20 100000 +Ethernet156 157,158,159,160 Ethernet20/5 20 100000 +Ethernet160 161,162,163,164 Ethernet21/1 21 100000 +Ethernet164 165,166,167,168 Ethernet21/5 21 100000 +Ethernet168 169,170,171,172 Ethernet22/1 22 100000 +Ethernet172 173,174,175,176 Ethernet22/5 22 100000 +Ethernet176 177,178,179,180 Ethernet23/1 23 100000 +Ethernet180 181,182,183,184 Ethernet23/5 23 100000 +Ethernet184 185,186,187,188 Ethernet24/1 24 100000 +Ethernet188 189,190,191,192 Ethernet24/5 24 100000 +Ethernet192 193,194,195,196 Ethernet25/1 25 100000 +Ethernet196 197,198,199,200 Ethernet25/5 25 100000 +Ethernet200 201,202,203,204 Ethernet26/1 26 100000 +Ethernet204 205,206,207,208 Ethernet26/5 26 100000 +Ethernet208 209,210,211,212 Ethernet27/1 27 100000 +Ethernet212 213,214,215,216 Ethernet27/5 27 100000 +Ethernet216 217,218,219,220 Ethernet28/1 28 100000 +Ethernet220 221,222,223,224 Ethernet28/5 28 100000 +Ethernet224 225,226,227,228 Ethernet29/1 29 100000 +Ethernet228 229,230,231,232 Ethernet29/5 29 100000 +Ethernet232 233,234,235,236 Ethernet30/1 30 100000 +Ethernet236 237,238,239,240 Ethernet30/5 30 100000 +Ethernet240 241,242,243,244 Ethernet31/1 31 100000 +Ethernet244 245,246,247,248 Ethernet31/5 31 100000 +Ethernet248 249,250,251,252 Ethernet32/1 32 100000 +Ethernet252 253,254,255,256 Ethernet32/5 32 100000 +Ethernet256 258 Ethernet33 33 10000 +Ethernet260 257 Ethernet34 34 10000 diff --git a/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-C64/sai.profile b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-C64/sai.profile new file mode 100644 index 000000000000..9d051624c589 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-C64/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-a7060px4-32-64x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-C64/th3-a7060px4-32-64x100G.config.bcm b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-C64/th3-a7060px4-32-64x100G.config.bcm new file mode 100644 index 000000000000..52e3424aaf55 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-C64/th3-a7060px4-32-64x100G.config.bcm @@ -0,0 +1,942 @@ +arl_clean_timeout_usec=15000000 +asf_mem_profile.0=2 +bcm_num_cos.0=8 +bcm_stat_flags=1 +bcm_stat_jumbo.0=9236 +cdma_timeout_usec.0=15000000 +disable_pcie_firmware_check.0=1 +dma_desc_timeout_usec.0=15000000 +dpr_clock_frequency.0=1000 +l2xmsg_mode.0=1 +l2_mem_entries.0=8192 +l3_alpm_enable.0=2 +l3_mem_entries.0=16384 +max_vp_lags.0=0 +miim_intr_enable.0=0 +module_64ports.0=1 +multicast_l2_range.0=511 +oversubscribe_mode=1 +parity_correction=1 +parity_enable=1 +pbmp_xport_xe.0=0x3ffffffffffffffffffffffffffffffffffffffe +phy_an_c37_38.0=2 +phy_an_c37_118.0=2 +phy_an_c37_1.0=1 +phy_an_c37_2.0=1 +phy_an_c37_3.0=1 +phy_an_c37_4.0=1 +phy_an_c37_5.0=1 +phy_an_c37_6.0=1 +phy_an_c37_7.0=1 +phy_an_c37_8.0=1 +phy_an_c37_20.0=1 +phy_an_c37_21.0=1 +phy_an_c37_22.0=1 +phy_an_c37_23.0=1 +phy_an_c37_24.0=1 +phy_an_c37_25.0=1 +phy_an_c37_26.0=1 +phy_an_c37_27.0=1 +phy_an_c37_38.0=0 +phy_an_c37_40.0=1 +phy_an_c37_41.0=1 +phy_an_c37_42.0=1 +phy_an_c37_43.0=1 +phy_an_c37_44.0=1 +phy_an_c37_45.0=1 +phy_an_c37_46.0=1 +phy_an_c37_47.0=1 +phy_an_c37_60.0=1 +phy_an_c37_61.0=1 +phy_an_c37_62.0=1 +phy_an_c37_63.0=1 +phy_an_c37_64.0=1 +phy_an_c37_65.0=1 +phy_an_c37_66.0=1 +phy_an_c37_67.0=1 +phy_an_c37_80.0=1 +phy_an_c37_81.0=1 +phy_an_c37_82.0=1 +phy_an_c37_83.0=1 +phy_an_c37_84.0=1 +phy_an_c37_85.0=1 +phy_an_c37_86.0=1 +phy_an_c37_87.0=1 +phy_an_c37_100.0=1 +phy_an_c37_101.0=1 +phy_an_c37_102.0=1 +phy_an_c37_103.0=1 +phy_an_c37_104.0=1 +phy_an_c37_105.0=1 +phy_an_c37_106.0=1 +phy_an_c37_107.0=1 +phy_an_c37_118.0=0 +phy_an_c37_120.0=1 +phy_an_c37_121.0=1 +phy_an_c37_122.0=1 +phy_an_c37_123.0=1 +phy_an_c37_124.0=1 +phy_an_c37_125.0=1 +phy_an_c37_126.0=1 +phy_an_c37_127.0=1 +phy_an_c37_140.0=1 +phy_an_c37_141.0=1 +phy_an_c37_142.0=1 +phy_an_c37_143.0=1 +phy_an_c37_144.0=1 +phy_an_c37_145.0=1 +phy_an_c37_146.0=1 +phy_an_c37_147.0=1 +phy_chain_rx_lane_map_physical{1.0}=0x72634150 +phy_chain_rx_lane_map_physical{9.0}=0x63725041 +phy_chain_rx_lane_map_physical{17.0}=0x23071465 +phy_chain_rx_lane_map_physical{25.0}=0x03125746 +phy_chain_rx_lane_map_physical{33.0}=0x12063574 +phy_chain_rx_lane_map_physical{41.0}=0x03125647 +phy_chain_rx_lane_map_physical{49.0}=0x12053467 +phy_chain_rx_lane_map_physical{57.0}=0x03125647 +phy_chain_rx_lane_map_physical{65.0}=0x12043576 +phy_chain_rx_lane_map_physical{73.0}=0x03125746 +phy_chain_rx_lane_map_physical{81.0}=0x12043576 +phy_chain_rx_lane_map_physical{89.0}=0x03125746 +phy_chain_rx_lane_map_physical{97.0}=0x40165327 +phy_chain_rx_lane_map_physical{105.0}=0x56470213 +phy_chain_rx_lane_map_physical{113.0}=0x21340576 +phy_chain_rx_lane_map_physical{121.0}=0x47562130 +phy_chain_rx_lane_map_physical{129.0}=0x56437201 +phy_chain_rx_lane_map_physical{137.0}=0x03125647 +phy_chain_rx_lane_map_physical{145.0}=0x12043576 +phy_chain_rx_lane_map_physical{153.0}=0x54106723 +phy_chain_rx_lane_map_physical{161.0}=0x63257014 +phy_chain_rx_lane_map_physical{169.0}=0x03125647 +phy_chain_rx_lane_map_physical{177.0}=0x12043567 +phy_chain_rx_lane_map_physical{185.0}=0x03125647 +phy_chain_rx_lane_map_physical{193.0}=0x12043567 +phy_chain_rx_lane_map_physical{201.0}=0x03125647 +phy_chain_rx_lane_map_physical{209.0}=0x12043576 +phy_chain_rx_lane_map_physical{217.0}=0x03125467 +phy_chain_rx_lane_map_physical{225.0}=0x12073465 +phy_chain_rx_lane_map_physical{233.0}=0x30215647 +phy_chain_rx_lane_map_physical{241.0}=0x23071564 +phy_chain_rx_lane_map_physical{249.0}=0x72634150 +phy_chain_rx_lane_map_physical{257.0}=0x3210 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +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{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +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{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{47.0}=0x1 +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{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x1 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +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}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x1 +phy_chain_rx_polarity_flip_physical{80.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}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x1 +phy_chain_rx_polarity_flip_physical{99.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +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}=0x0 +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}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x1 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 +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}=0x1 +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{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 +phy_chain_rx_polarity_flip_physical{125.0}=0x0 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x0 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x1 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_rx_polarity_flip_physical{141.0}=0x0 +phy_chain_rx_polarity_flip_physical{142.0}=0x1 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x1 +phy_chain_rx_polarity_flip_physical{147.0}=0x0 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_rx_polarity_flip_physical{149.0}=0x1 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x0 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x1 +phy_chain_rx_polarity_flip_physical{157.0}=0x1 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x1 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x1 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x0 +phy_chain_rx_polarity_flip_physical{168.0}=0x0 +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x1 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x1 +phy_chain_rx_polarity_flip_physical{175.0}=0x1 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 +phy_chain_rx_polarity_flip_physical{177.0}=0x0 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x0 +phy_chain_rx_polarity_flip_physical{181.0}=0x1 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_rx_polarity_flip_physical{185.0}=0x0 +phy_chain_rx_polarity_flip_physical{186.0}=0x1 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x1 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x0 +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x1 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_rx_polarity_flip_physical{205.0}=0x0 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x1 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x0 +phy_chain_rx_polarity_flip_physical{213.0}=0x1 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x0 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 +phy_chain_rx_polarity_flip_physical{217.0}=0x0 +phy_chain_rx_polarity_flip_physical{218.0}=0x1 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x0 +phy_chain_rx_polarity_flip_physical{221.0}=0x0 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x1 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 +phy_chain_rx_polarity_flip_physical{225.0}=0x0 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x0 +phy_chain_rx_polarity_flip_physical{229.0}=0x0 +phy_chain_rx_polarity_flip_physical{230.0}=0x1 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x0 +phy_chain_rx_polarity_flip_physical{233.0}=0x0 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x1 +phy_chain_rx_polarity_flip_physical{241.0}=0x1 +phy_chain_rx_polarity_flip_physical{242.0}=0x0 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x0 +phy_chain_rx_polarity_flip_physical{245.0}=0x0 +phy_chain_rx_polarity_flip_physical{246.0}=0x1 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 +phy_chain_rx_polarity_flip_physical{249.0}=0x1 +phy_chain_rx_polarity_flip_physical{250.0}=0x1 +phy_chain_rx_polarity_flip_physical{251.0}=0x0 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 +phy_chain_rx_polarity_flip_physical{253.0}=0x0 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x1 +phy_chain_rx_polarity_flip_physical{256.0}=0x1 +phy_chain_rx_polarity_flip_physical{257.0}=0x0 +phy_chain_rx_polarity_flip_physical{258.0}=0x0 +phy_chain_tx_lane_map_physical{1.0}=0x13245076 +phy_chain_tx_lane_map_physical{9.0}=0x76501423 +phy_chain_tx_lane_map_physical{17.0}=0x75643120 +phy_chain_tx_lane_map_physical{25.0}=0x74653201 +phy_chain_tx_lane_map_physical{33.0}=0x75603124 +phy_chain_tx_lane_map_physical{41.0}=0x64753120 +phy_chain_tx_lane_map_physical{49.0}=0x65741032 +phy_chain_tx_lane_map_physical{57.0}=0x64753210 +phy_chain_tx_lane_map_physical{65.0}=0x65740132 +phy_chain_tx_lane_map_physical{73.0}=0x64753210 +phy_chain_tx_lane_map_physical{81.0}=0x65740132 +phy_chain_tx_lane_map_physical{89.0}=0x64753210 +phy_chain_tx_lane_map_physical{97.0}=0x63057124 +phy_chain_tx_lane_map_physical{105.0}=0x67453021 +phy_chain_tx_lane_map_physical{113.0}=0x76502413 +phy_chain_tx_lane_map_physical{121.0}=0x13257064 +phy_chain_tx_lane_map_physical{129.0}=0x32146057 +phy_chain_tx_lane_map_physical{137.0}=0x57613420 +phy_chain_tx_lane_map_physical{145.0}=0x76502413 +phy_chain_tx_lane_map_physical{153.0}=0x64173520 +phy_chain_tx_lane_map_physical{161.0}=0x56742031 +phy_chain_tx_lane_map_physical{169.0}=0x74601523 +phy_chain_tx_lane_map_physical{177.0}=0x56742031 +phy_chain_tx_lane_map_physical{185.0}=0x74601523 +phy_chain_tx_lane_map_physical{193.0}=0x56742031 +phy_chain_tx_lane_map_physical{201.0}=0x74601523 +phy_chain_tx_lane_map_physical{209.0}=0x56742031 +phy_chain_tx_lane_map_physical{217.0}=0x74603512 +phy_chain_tx_lane_map_physical{225.0}=0x75642031 +phy_chain_tx_lane_map_physical{233.0}=0x57612430 +phy_chain_tx_lane_map_physical{241.0}=0x65742031 +phy_chain_tx_lane_map_physical{249.0}=0x52316470 +phy_chain_tx_lane_map_physical{257.0}=0x3210 +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{17.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +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{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}=0x0 +phy_chain_tx_polarity_flip_physical{60.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}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.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}=0x0 +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{81.0}=0x1 +phy_chain_tx_polarity_flip_physical{82.0}=0x1 +phy_chain_tx_polarity_flip_physical{83.0}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 +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{91.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{109.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +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}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x0 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x1 +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{130.0}=0x1 +phy_chain_tx_polarity_flip_physical{131.0}=0x0 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x1 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x0 +phy_chain_tx_polarity_flip_physical{136.0}=0x0 +phy_chain_tx_polarity_flip_physical{137.0}=0x0 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x1 +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x1 +phy_chain_tx_polarity_flip_physical{143.0}=0x0 +phy_chain_tx_polarity_flip_physical{144.0}=0x0 +phy_chain_tx_polarity_flip_physical{145.0}=0x0 +phy_chain_tx_polarity_flip_physical{146.0}=0x1 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x0 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x1 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x1 +phy_chain_tx_polarity_flip_physical{159.0}=0x1 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x1 +phy_chain_tx_polarity_flip_physical{163.0}=0x1 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{165.0}=0x0 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x1 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x1 +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x1 +phy_chain_tx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x1 +phy_chain_tx_polarity_flip_physical{179.0}=0x1 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 +phy_chain_tx_polarity_flip_physical{185.0}=0x1 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x0 +phy_chain_tx_polarity_flip_physical{190.0}=0x1 +phy_chain_tx_polarity_flip_physical{191.0}=0x1 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x1 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x0 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x0 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 +phy_chain_tx_polarity_flip_physical{201.0}=0x1 +phy_chain_tx_polarity_flip_physical{202.0}=0x0 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x1 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 +phy_chain_tx_polarity_flip_physical{209.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x1 +phy_chain_tx_polarity_flip_physical{211.0}=0x1 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x0 +phy_chain_tx_polarity_flip_physical{217.0}=0x0 +phy_chain_tx_polarity_flip_physical{218.0}=0x1 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x1 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x1 +phy_chain_tx_polarity_flip_physical{223.0}=0x1 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 +phy_chain_tx_polarity_flip_physical{225.0}=0x0 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x1 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x0 +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x1 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 +phy_chain_tx_polarity_flip_physical{241.0}=0x0 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 +phy_chain_tx_polarity_flip_physical{245.0}=0x0 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x1 +phy_chain_tx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x1 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 +phy_chain_tx_polarity_flip_physical{253.0}=0x0 +phy_chain_tx_polarity_flip_physical{254.0}=0x0 +phy_chain_tx_polarity_flip_physical{255.0}=0x1 +phy_chain_tx_polarity_flip_physical{256.0}=0x1 +phy_chain_tx_polarity_flip_physical{257.0}=0x0 +phy_chain_tx_polarity_flip_physical{258.0}=0x0 +portmap_1.0=1:100:4 +portmap_2.0=5:100:4 +portmap_3.0=9:100:4 +portmap_4.0=13:100:4 +portmap_5.0=17:100:4 +portmap_6.0=21:100:4 +portmap_7.0=25:100:4 +portmap_8.0=29:100:4 +portmap_20.0=33:100:4 +portmap_21.0=37:100:4 +portmap_22.0=41:100:4 +portmap_23.0=45:100:4 +portmap_24.0=49:100:4 +portmap_25.0=53:100:4 +portmap_26.0=57:100:4 +portmap_27.0=61:100:4 +portmap_38.0=257:10 +portmap_40.0=65:100:4 +portmap_41.0=69:100:4 +portmap_42.0=73:100:4 +portmap_43.0=77:100:4 +portmap_44.0=81:100:4 +portmap_45.0=85:100:4 +portmap_46.0=89:100:4 +portmap_47.0=93:100:4 +portmap_60.0=97:100:4 +portmap_61.0=101:100:4 +portmap_62.0=105:100:4 +portmap_63.0=109:100:4 +portmap_64.0=113:100:4 +portmap_65.0=117:100:4 +portmap_66.0=121:100:4 +portmap_67.0=125:100:4 +portmap_80.0=129:100:4 +portmap_81.0=133:100:4 +portmap_82.0=137:100:4 +portmap_83.0=141:100:4 +portmap_84.0=145:100:4 +portmap_85.0=149:100:4 +portmap_86.0=153:100:4 +portmap_87.0=157:100:4 +portmap_100.0=161:100:4 +portmap_101.0=165:100:4 +portmap_102.0=169:100:4 +portmap_103.0=173:100:4 +portmap_104.0=177:100:4 +portmap_105.0=181:100:4 +portmap_106.0=185:100:4 +portmap_107.0=189:100:4 +portmap_118.0=258:10 +portmap_120.0=193:100:4 +portmap_121.0=197:100:4 +portmap_122.0=201:100:4 +portmap_123.0=205:100:4 +portmap_124.0=209:100:4 +portmap_125.0=213:100:4 +portmap_126.0=217:100:4 +portmap_127.0=221:100:4 +portmap_140.0=225:100:4 +portmap_141.0=229:100:4 +portmap_142.0=233:100:4 +portmap_143.0=237:100:4 +portmap_144.0=241:100:4 +portmap_145.0=245:100:4 +portmap_146.0=249:100:4 +portmap_147.0=253:100:4 +port_init_autoneg_1.0=0 +port_init_autoneg_2.0=0 +port_init_autoneg_3.0=0 +port_init_autoneg_4.0=0 +port_init_autoneg_5.0=0 +port_init_autoneg_6.0=0 +port_init_autoneg_7.0=0 +port_init_autoneg_8.0=0 +port_init_autoneg_20.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_22.0=0 +port_init_autoneg_23.0=0 +port_init_autoneg_24.0=0 +port_init_autoneg_25.0=0 +port_init_autoneg_26.0=0 +port_init_autoneg_27.0=0 +port_init_autoneg_38.0=0 +port_init_autoneg_40.0=0 +port_init_autoneg_41.0=0 +port_init_autoneg_42.0=0 +port_init_autoneg_43.0=0 +port_init_autoneg_44.0=0 +port_init_autoneg_45.0=0 +port_init_autoneg_46.0=0 +port_init_autoneg_47.0=0 +port_init_autoneg_60.0=0 +port_init_autoneg_61.0=0 +port_init_autoneg_62.0=0 +port_init_autoneg_63.0=0 +port_init_autoneg_64.0=0 +port_init_autoneg_65.0=0 +port_init_autoneg_66.0=0 +port_init_autoneg_67.0=0 +port_init_autoneg_80.0=0 +port_init_autoneg_81.0=0 +port_init_autoneg_82.0=0 +port_init_autoneg_83.0=0 +port_init_autoneg_84.0=0 +port_init_autoneg_85.0=0 +port_init_autoneg_86.0=0 +port_init_autoneg_87.0=0 +port_init_autoneg_100.0=0 +port_init_autoneg_101.0=0 +port_init_autoneg_102.0=0 +port_init_autoneg_103.0=0 +port_init_autoneg_104.0=0 +port_init_autoneg_105.0=0 +port_init_autoneg_106.0=0 +port_init_autoneg_107.0=0 +port_init_autoneg_118.0=0 +port_init_autoneg_120.0=0 +port_init_autoneg_121.0=0 +port_init_autoneg_122.0=0 +port_init_autoneg_123.0=0 +port_init_autoneg_124.0=0 +port_init_autoneg_125.0=0 +port_init_autoneg_126.0=0 +port_init_autoneg_127.0=0 +port_init_autoneg_140.0=0 +port_init_autoneg_141.0=0 +port_init_autoneg_142.0=0 +port_init_autoneg_143.0=0 +port_init_autoneg_144.0=0 +port_init_autoneg_145.0=0 +port_init_autoneg_146.0=0 +port_init_autoneg_147.0=0 +port_phy_addr_1.0=0xff +port_phy_addr_2.0=0xff +port_phy_addr_3.0=0xff +port_phy_addr_4.0=0xff +port_phy_addr_5.0=0xff +port_phy_addr_6.0=0xff +port_phy_addr_7.0=0xff +port_phy_addr_8.0=0xff +port_phy_addr_20.0=0xff +port_phy_addr_21.0=0xff +port_phy_addr_22.0=0xff +port_phy_addr_23.0=0xff +port_phy_addr_24.0=0xff +port_phy_addr_25.0=0xff +port_phy_addr_26.0=0xff +port_phy_addr_27.0=0xff +port_phy_addr_38.0=0xff +port_phy_addr_40.0=0xff +port_phy_addr_41.0=0xff +port_phy_addr_42.0=0xff +port_phy_addr_43.0=0xff +port_phy_addr_44.0=0xff +port_phy_addr_45.0=0xff +port_phy_addr_46.0=0xff +port_phy_addr_47.0=0xff +port_phy_addr_60.0=0xff +port_phy_addr_61.0=0xff +port_phy_addr_62.0=0xff +port_phy_addr_63.0=0xff +port_phy_addr_64.0=0xff +port_phy_addr_65.0=0xff +port_phy_addr_66.0=0xff +port_phy_addr_67.0=0xff +port_phy_addr_80.0=0xff +port_phy_addr_81.0=0xff +port_phy_addr_82.0=0xff +port_phy_addr_83.0=0xff +port_phy_addr_84.0=0xff +port_phy_addr_85.0=0xff +port_phy_addr_86.0=0xff +port_phy_addr_87.0=0xff +port_phy_addr_100.0=0xff +port_phy_addr_101.0=0xff +port_phy_addr_102.0=0xff +port_phy_addr_103.0=0xff +port_phy_addr_104.0=0xff +port_phy_addr_105.0=0xff +port_phy_addr_106.0=0xff +port_phy_addr_107.0=0xff +port_phy_addr_118.0=0xff +port_phy_addr_120.0=0xff +port_phy_addr_121.0=0xff +port_phy_addr_122.0=0xff +port_phy_addr_123.0=0xff +port_phy_addr_124.0=0xff +port_phy_addr_125.0=0xff +port_phy_addr_126.0=0xff +port_phy_addr_127.0=0xff +port_phy_addr_140.0=0xff +port_phy_addr_141.0=0xff +port_phy_addr_142.0=0xff +port_phy_addr_143.0=0xff +port_phy_addr_144.0=0xff +port_phy_addr_145.0=0xff +port_phy_addr_146.0=0xff +port_phy_addr_147.0=0xff +robust_hash_disable_egress_vlan.0=1 +robust_hash_disable_mpls.0=1 +robust_hash_disable_vlan.0=1 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 + +# Tuning +serdes_core_rx_polarity_flip_physical{1}=0x69 +serdes_core_rx_polarity_flip_physical{9}=0x69 +serdes_core_rx_polarity_flip_physical{17}=0xe4 +serdes_core_rx_polarity_flip_physical{25}=0x62 +serdes_core_rx_polarity_flip_physical{33}=0x33 +serdes_core_rx_polarity_flip_physical{41}=0x66 +serdes_core_rx_polarity_flip_physical{49}=0x24 +serdes_core_rx_polarity_flip_physical{57}=0x66 +serdes_core_rx_polarity_flip_physical{65}=0x33 +serdes_core_rx_polarity_flip_physical{73}=0x63 +serdes_core_rx_polarity_flip_physical{81}=0x33 +serdes_core_rx_polarity_flip_physical{89}=0x63 +serdes_core_rx_polarity_flip_physical{97}=0x1e +serdes_core_rx_polarity_flip_physical{105}=0x63 +serdes_core_rx_polarity_flip_physical{113}=0xdb +serdes_core_rx_polarity_flip_physical{121}=0x69 +serdes_core_rx_polarity_flip_physical{129}=0x24 +serdes_core_rx_polarity_flip_physical{137}=0x66 +serdes_core_rx_polarity_flip_physical{145}=0x33 +serdes_core_rx_polarity_flip_physical{153}=0x5a +serdes_core_rx_polarity_flip_physical{161}=0xf +serdes_core_rx_polarity_flip_physical{169}=0x66 +serdes_core_rx_polarity_flip_physical{177}=0x30 +serdes_core_rx_polarity_flip_physical{185}=0x66 +serdes_core_rx_polarity_flip_physical{193}=0x30 +serdes_core_rx_polarity_flip_physical{201}=0x66 +serdes_core_rx_polarity_flip_physical{209}=0x33 +serdes_core_rx_polarity_flip_physical{217}=0x66 +serdes_core_rx_polarity_flip_physical{225}=0x24 +serdes_core_rx_polarity_flip_physical{233}=0x96 +serdes_core_rx_polarity_flip_physical{241}=0xe1 +serdes_core_rx_polarity_flip_physical{249}=0xc3 +serdes_core_rx_polarity_flip_physical{257}=0x0 +serdes_core_tx_polarity_flip_physical{1}=0x7b +serdes_core_tx_polarity_flip_physical{9}=0x4d +serdes_core_tx_polarity_flip_physical{17}=0x69 +serdes_core_tx_polarity_flip_physical{25}=0x69 +serdes_core_tx_polarity_flip_physical{33}=0x78 +serdes_core_tx_polarity_flip_physical{41}=0xcc +serdes_core_tx_polarity_flip_physical{49}=0xcf +serdes_core_tx_polarity_flip_physical{57}=0xca +serdes_core_tx_polarity_flip_physical{65}=0xc3 +serdes_core_tx_polarity_flip_physical{73}=0xca +serdes_core_tx_polarity_flip_physical{81}=0xc3 +serdes_core_tx_polarity_flip_physical{89}=0xca +serdes_core_tx_polarity_flip_physical{97}=0x70 +serdes_core_tx_polarity_flip_physical{105}=0x59 +serdes_core_tx_polarity_flip_physical{113}=0x12 +serdes_core_tx_polarity_flip_physical{121}=0x3c +serdes_core_tx_polarity_flip_physical{129}=0x12 +serdes_core_tx_polarity_flip_physical{137}=0x3c +serdes_core_tx_polarity_flip_physical{145}=0x12 +serdes_core_tx_polarity_flip_physical{153}=0x68 +serdes_core_tx_polarity_flip_physical{161}=0x6 +serdes_core_tx_polarity_flip_physical{169}=0x69 +serdes_core_tx_polarity_flip_physical{177}=0x6 +serdes_core_tx_polarity_flip_physical{185}=0x69 +serdes_core_tx_polarity_flip_physical{193}=0x6 +serdes_core_tx_polarity_flip_physical{201}=0x69 +serdes_core_tx_polarity_flip_physical{209}=0x6 +serdes_core_tx_polarity_flip_physical{217}=0x6a +serdes_core_tx_polarity_flip_physical{225}=0x66 +serdes_core_tx_polarity_flip_physical{233}=0x36 +serdes_core_tx_polarity_flip_physical{241}=0xc6 +serdes_core_tx_polarity_flip_physical{249}=0xc3 +serdes_core_tx_polarity_flip_physical{257}=0x0 diff --git a/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-O32/port_config.ini b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-O32/port_config.ini new file mode 100644 index 000000000000..45ef9b7754b9 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-O32/port_config.ini @@ -0,0 +1,35 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4,5,6,7,8 Ethernet1/1 1 400000 +Ethernet8 9,10,11,12,13,14,15,16 Ethernet2/1 2 400000 +Ethernet16 17,18,19,20,21,22,23,24 Ethernet3/1 3 400000 +Ethernet24 25,26,27,28,29,30,31,32 Ethernet4/1 4 400000 +Ethernet32 33,34,35,36,37,38,39,40 Ethernet5/1 5 400000 +Ethernet40 41,42,43,44,45,46,47,48 Ethernet6/1 6 400000 +Ethernet48 49,50,51,52,53,54,55,56 Ethernet7/1 7 400000 +Ethernet56 57,58,59,60,61,62,63,64 Ethernet8/1 8 400000 +Ethernet64 65,66,67,68,69,70,71,72 Ethernet9/1 9 400000 +Ethernet72 73,74,75,76,77,78,79,80 Ethernet10/1 10 400000 +Ethernet80 81,82,83,84,85,86,87,88 Ethernet11/1 11 400000 +Ethernet88 89,90,91,92,93,94,95,96 Ethernet12/1 12 400000 +Ethernet96 97,98,99,100,101,102,103,104 Ethernet13/1 13 400000 +Ethernet104 105,106,107,108,109,110,111,112 Ethernet14/1 14 400000 +Ethernet112 113,114,115,116,117,118,119,120 Ethernet15/1 15 400000 +Ethernet120 121,122,123,124,125,126,127,128 Ethernet16/1 16 400000 +Ethernet128 129,130,131,132,133,134,135,136 Ethernet17/1 17 400000 +Ethernet136 137,138,139,140,141,142,143,144 Ethernet18/1 18 400000 +Ethernet144 145,146,147,148,149,150,151,152 Ethernet19/1 19 400000 +Ethernet152 153,154,155,156,157,158,159,160 Ethernet20/1 20 400000 +Ethernet160 161,162,163,164,165,166,167,168 Ethernet21/1 21 400000 +Ethernet168 169,170,171,172,173,174,175,176 Ethernet22/1 22 400000 +Ethernet176 177,178,179,180,181,182,183,184 Ethernet23/1 23 400000 +Ethernet184 185,186,187,188,189,190,191,192 Ethernet24/1 24 400000 +Ethernet192 193,194,195,196,197,198,199,200 Ethernet25/1 25 400000 +Ethernet200 201,202,203,204,205,206,207,208 Ethernet26/1 26 400000 +Ethernet208 209,210,211,212,213,214,215,216 Ethernet27/1 27 400000 +Ethernet216 217,218,219,220,221,222,223,224 Ethernet28/1 28 400000 +Ethernet224 225,226,227,228,229,230,231,232 Ethernet29/1 29 400000 +Ethernet232 233,234,235,236,237,238,239,240 Ethernet30/1 30 400000 +Ethernet240 241,242,243,244,245,246,247,248 Ethernet31/1 31 400000 +Ethernet248 249,250,251,252,253,254,255,256 Ethernet32/1 32 400000 +Ethernet256 258 Ethernet33 33 10000 +Ethernet260 257 Ethernet34 34 10000 diff --git a/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-O32/sai.profile b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-O32/sai.profile new file mode 100644 index 000000000000..c9a6b4d330ce --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-O32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-a7060px4-o32-32x400G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-O32/th3-a7060px4-o32-32x400G.config.bcm b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-O32/th3-a7060px4-o32-32x400G.config.bcm new file mode 100644 index 000000000000..0cf9ae8f3a65 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/Arista-7060PX4-O32/th3-a7060px4-o32-32x400G.config.bcm @@ -0,0 +1,848 @@ +arl_clean_timeout_usec=15000000 +asf_mem_profile.0=2 +bcm_num_cos.0=8 +bcm_stat_flags=1 +bcm_stat_jumbo.0=9236 +cdma_timeout_usec.0=15000000 +disable_pcie_firmware_check.0=1 +dma_desc_timeout_usec.0=15000000 +dpr_clock_frequency.0=1000 +l2xmsg_mode.0=1 +l2_mem_entries.0=8192 +l3_alpm_enable.0=2 +l3_mem_entries.0=16384 +max_vp_lags.0=0 +miim_intr_enable.0=0 +module_64ports.0=1 +multicast_l2_range.0=511 +oversubscribe_mode=1 +parity_correction=1 +parity_enable=1 +pbmp_xport_xe.0=0x3ffffffffffffffffffffffffffffffffffffffe +phy_an_c37_38.0=2 +phy_an_c37_118.0=2 +phy_an_c73_1.0=1 +phy_an_c73_2.0=1 +phy_an_c73_3.0=1 +phy_an_c73_4.0=1 +phy_an_c73_20.0=1 +phy_an_c73_21.0=1 +phy_an_c73_22.0=1 +phy_an_c73_23.0=1 +phy_an_c73_38.0=0 +phy_an_c73_40.0=1 +phy_an_c73_41.0=1 +phy_an_c73_42.0=1 +phy_an_c73_43.0=1 +phy_an_c73_60.0=1 +phy_an_c73_61.0=1 +phy_an_c73_62.0=1 +phy_an_c73_63.0=1 +phy_an_c73_80.0=1 +phy_an_c73_81.0=1 +phy_an_c73_82.0=1 +phy_an_c73_83.0=1 +phy_an_c73_100.0=1 +phy_an_c73_101.0=1 +phy_an_c73_102.0=1 +phy_an_c73_103.0=1 +phy_an_c73_118.0=0 +phy_an_c73_120.0=1 +phy_an_c73_121.0=1 +phy_an_c73_122.0=1 +phy_an_c73_123.0=1 +phy_an_c73_140.0=1 +phy_an_c73_141.0=1 +phy_an_c73_142.0=1 +phy_an_c73_143.0=1 +phy_chain_rx_lane_map_physical{1.0}=0x72634150 +phy_chain_rx_lane_map_physical{9.0}=0x63725041 +phy_chain_rx_lane_map_physical{17.0}=0x23071465 +phy_chain_rx_lane_map_physical{25.0}=0x03125746 +phy_chain_rx_lane_map_physical{33.0}=0x12063574 +phy_chain_rx_lane_map_physical{41.0}=0x03125647 +phy_chain_rx_lane_map_physical{49.0}=0x12053467 +phy_chain_rx_lane_map_physical{57.0}=0x03125647 +phy_chain_rx_lane_map_physical{65.0}=0x12043576 +phy_chain_rx_lane_map_physical{73.0}=0x03125746 +phy_chain_rx_lane_map_physical{81.0}=0x12043576 +phy_chain_rx_lane_map_physical{89.0}=0x03125746 +phy_chain_rx_lane_map_physical{97.0}=0x40165327 +phy_chain_rx_lane_map_physical{105.0}=0x56470213 +phy_chain_rx_lane_map_physical{113.0}=0x21340576 +phy_chain_rx_lane_map_physical{121.0}=0x47562130 +phy_chain_rx_lane_map_physical{129.0}=0x56437201 +phy_chain_rx_lane_map_physical{137.0}=0x03125647 +phy_chain_rx_lane_map_physical{145.0}=0x12043576 +phy_chain_rx_lane_map_physical{153.0}=0x54106723 +phy_chain_rx_lane_map_physical{161.0}=0x63257014 +phy_chain_rx_lane_map_physical{169.0}=0x03125647 +phy_chain_rx_lane_map_physical{177.0}=0x12043567 +phy_chain_rx_lane_map_physical{185.0}=0x03125647 +phy_chain_rx_lane_map_physical{193.0}=0x12043567 +phy_chain_rx_lane_map_physical{201.0}=0x03125647 +phy_chain_rx_lane_map_physical{209.0}=0x12043576 +phy_chain_rx_lane_map_physical{217.0}=0x03125467 +phy_chain_rx_lane_map_physical{225.0}=0x12073465 +phy_chain_rx_lane_map_physical{233.0}=0x30215647 +phy_chain_rx_lane_map_physical{241.0}=0x23071564 +phy_chain_rx_lane_map_physical{249.0}=0x72634150 +phy_chain_rx_lane_map_physical{257.0}=0x3210 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +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{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +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{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{47.0}=0x1 +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{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x1 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +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}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x1 +phy_chain_rx_polarity_flip_physical{80.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}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x1 +phy_chain_rx_polarity_flip_physical{99.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +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}=0x0 +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}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x1 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 +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}=0x1 +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{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 +phy_chain_rx_polarity_flip_physical{125.0}=0x0 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x0 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x1 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_rx_polarity_flip_physical{141.0}=0x0 +phy_chain_rx_polarity_flip_physical{142.0}=0x1 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x1 +phy_chain_rx_polarity_flip_physical{147.0}=0x0 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_rx_polarity_flip_physical{149.0}=0x1 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x0 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x1 +phy_chain_rx_polarity_flip_physical{157.0}=0x1 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x1 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x1 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x0 +phy_chain_rx_polarity_flip_physical{168.0}=0x0 +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x1 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x1 +phy_chain_rx_polarity_flip_physical{175.0}=0x1 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 +phy_chain_rx_polarity_flip_physical{177.0}=0x0 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x0 +phy_chain_rx_polarity_flip_physical{181.0}=0x1 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_rx_polarity_flip_physical{185.0}=0x0 +phy_chain_rx_polarity_flip_physical{186.0}=0x1 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x1 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x0 +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x1 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_rx_polarity_flip_physical{205.0}=0x0 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x1 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x0 +phy_chain_rx_polarity_flip_physical{213.0}=0x1 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x0 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 +phy_chain_rx_polarity_flip_physical{217.0}=0x0 +phy_chain_rx_polarity_flip_physical{218.0}=0x1 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x0 +phy_chain_rx_polarity_flip_physical{221.0}=0x0 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x1 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 +phy_chain_rx_polarity_flip_physical{225.0}=0x0 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x0 +phy_chain_rx_polarity_flip_physical{229.0}=0x0 +phy_chain_rx_polarity_flip_physical{230.0}=0x1 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x0 +phy_chain_rx_polarity_flip_physical{233.0}=0x0 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x1 +phy_chain_rx_polarity_flip_physical{241.0}=0x1 +phy_chain_rx_polarity_flip_physical{242.0}=0x0 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x0 +phy_chain_rx_polarity_flip_physical{245.0}=0x0 +phy_chain_rx_polarity_flip_physical{246.0}=0x1 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 +phy_chain_rx_polarity_flip_physical{249.0}=0x1 +phy_chain_rx_polarity_flip_physical{250.0}=0x1 +phy_chain_rx_polarity_flip_physical{251.0}=0x0 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 +phy_chain_rx_polarity_flip_physical{253.0}=0x0 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x1 +phy_chain_rx_polarity_flip_physical{256.0}=0x1 +phy_chain_rx_polarity_flip_physical{257.0}=0x0 +phy_chain_rx_polarity_flip_physical{258.0}=0x0 +phy_chain_tx_lane_map_physical{1.0}=0x13245076 +phy_chain_tx_lane_map_physical{9.0}=0x76501423 +phy_chain_tx_lane_map_physical{17.0}=0x75643120 +phy_chain_tx_lane_map_physical{25.0}=0x74653201 +phy_chain_tx_lane_map_physical{33.0}=0x75603124 +phy_chain_tx_lane_map_physical{41.0}=0x64753120 +phy_chain_tx_lane_map_physical{49.0}=0x65741032 +phy_chain_tx_lane_map_physical{57.0}=0x64753210 +phy_chain_tx_lane_map_physical{65.0}=0x65740132 +phy_chain_tx_lane_map_physical{73.0}=0x64753210 +phy_chain_tx_lane_map_physical{81.0}=0x65740132 +phy_chain_tx_lane_map_physical{89.0}=0x64753210 +phy_chain_tx_lane_map_physical{97.0}=0x63057124 +phy_chain_tx_lane_map_physical{105.0}=0x67453021 +phy_chain_tx_lane_map_physical{113.0}=0x76502413 +phy_chain_tx_lane_map_physical{121.0}=0x13257064 +phy_chain_tx_lane_map_physical{129.0}=0x32146057 +phy_chain_tx_lane_map_physical{137.0}=0x57613420 +phy_chain_tx_lane_map_physical{145.0}=0x76502413 +phy_chain_tx_lane_map_physical{153.0}=0x64173520 +phy_chain_tx_lane_map_physical{161.0}=0x56742031 +phy_chain_tx_lane_map_physical{169.0}=0x74601523 +phy_chain_tx_lane_map_physical{177.0}=0x56742031 +phy_chain_tx_lane_map_physical{185.0}=0x74601523 +phy_chain_tx_lane_map_physical{193.0}=0x56742031 +phy_chain_tx_lane_map_physical{201.0}=0x74601523 +phy_chain_tx_lane_map_physical{209.0}=0x56742031 +phy_chain_tx_lane_map_physical{217.0}=0x74603512 +phy_chain_tx_lane_map_physical{225.0}=0x75642031 +phy_chain_tx_lane_map_physical{233.0}=0x57612430 +phy_chain_tx_lane_map_physical{241.0}=0x65742031 +phy_chain_tx_lane_map_physical{249.0}=0x52316470 +phy_chain_tx_lane_map_physical{257.0}=0x3210 +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{17.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +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{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}=0x0 +phy_chain_tx_polarity_flip_physical{60.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}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.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}=0x0 +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{81.0}=0x1 +phy_chain_tx_polarity_flip_physical{82.0}=0x1 +phy_chain_tx_polarity_flip_physical{83.0}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 +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{91.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{109.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +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}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x0 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x1 +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{130.0}=0x1 +phy_chain_tx_polarity_flip_physical{131.0}=0x0 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x1 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x0 +phy_chain_tx_polarity_flip_physical{136.0}=0x0 +phy_chain_tx_polarity_flip_physical{137.0}=0x0 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x1 +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x1 +phy_chain_tx_polarity_flip_physical{143.0}=0x0 +phy_chain_tx_polarity_flip_physical{144.0}=0x0 +phy_chain_tx_polarity_flip_physical{145.0}=0x0 +phy_chain_tx_polarity_flip_physical{146.0}=0x1 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x0 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x1 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x1 +phy_chain_tx_polarity_flip_physical{159.0}=0x1 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x1 +phy_chain_tx_polarity_flip_physical{163.0}=0x1 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{165.0}=0x0 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x1 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x1 +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x1 +phy_chain_tx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x1 +phy_chain_tx_polarity_flip_physical{179.0}=0x1 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 +phy_chain_tx_polarity_flip_physical{185.0}=0x1 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x0 +phy_chain_tx_polarity_flip_physical{190.0}=0x1 +phy_chain_tx_polarity_flip_physical{191.0}=0x1 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x1 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x0 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x0 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 +phy_chain_tx_polarity_flip_physical{201.0}=0x1 +phy_chain_tx_polarity_flip_physical{202.0}=0x0 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x1 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 +phy_chain_tx_polarity_flip_physical{209.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x1 +phy_chain_tx_polarity_flip_physical{211.0}=0x1 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x0 +phy_chain_tx_polarity_flip_physical{217.0}=0x0 +phy_chain_tx_polarity_flip_physical{218.0}=0x1 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x1 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x1 +phy_chain_tx_polarity_flip_physical{223.0}=0x1 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 +phy_chain_tx_polarity_flip_physical{225.0}=0x0 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x1 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x0 +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x1 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 +phy_chain_tx_polarity_flip_physical{241.0}=0x0 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 +phy_chain_tx_polarity_flip_physical{245.0}=0x0 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x1 +phy_chain_tx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x1 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 +phy_chain_tx_polarity_flip_physical{253.0}=0x0 +phy_chain_tx_polarity_flip_physical{254.0}=0x0 +phy_chain_tx_polarity_flip_physical{255.0}=0x1 +phy_chain_tx_polarity_flip_physical{256.0}=0x1 +phy_chain_tx_polarity_flip_physical{257.0}=0x0 +phy_chain_tx_polarity_flip_physical{258.0}=0x0 +portmap_1.0=1:400 +portmap_2.0=9:400 +portmap_3.0=17:400 +portmap_4.0=25:400 +portmap_20.0=33:400 +portmap_21.0=41:400 +portmap_22.0=49:400 +portmap_23.0=57:400 +portmap_38.0=257:10 +portmap_40.0=65:400 +portmap_41.0=73:400 +portmap_42.0=81:400 +portmap_43.0=89:400 +portmap_60.0=97:400 +portmap_61.0=105:400 +portmap_62.0=113:400 +portmap_63.0=121:400 +portmap_80.0=129:400 +portmap_81.0=137:400 +portmap_82.0=145:400 +portmap_83.0=153:400 +portmap_100.0=161:400 +portmap_101.0=169:400 +portmap_102.0=177:400 +portmap_103.0=185:400 +portmap_118.0=258:10 +portmap_120.0=193:400 +portmap_121.0=201:400 +portmap_122.0=209:400 +portmap_123.0=217:400 +portmap_140.0=225:400 +portmap_141.0=233:400 +portmap_142.0=241:400 +portmap_143.0=249:400 +port_init_autoneg_1.0=0 +port_init_autoneg_2.0=0 +port_init_autoneg_3.0=0 +port_init_autoneg_4.0=0 +port_init_autoneg_20.0=0 +port_init_autoneg_21.0=0 +port_init_autoneg_22.0=0 +port_init_autoneg_23.0=0 +port_init_autoneg_38.0=0 +port_init_autoneg_40.0=0 +port_init_autoneg_41.0=0 +port_init_autoneg_42.0=0 +port_init_autoneg_43.0=0 +port_init_autoneg_60.0=0 +port_init_autoneg_61.0=0 +port_init_autoneg_62.0=0 +port_init_autoneg_63.0=0 +port_init_autoneg_80.0=0 +port_init_autoneg_81.0=0 +port_init_autoneg_82.0=0 +port_init_autoneg_83.0=0 +port_init_autoneg_100.0=0 +port_init_autoneg_101.0=0 +port_init_autoneg_102.0=0 +port_init_autoneg_103.0=0 +port_init_autoneg_118.0=0 +port_init_autoneg_120.0=0 +port_init_autoneg_121.0=0 +port_init_autoneg_122.0=0 +port_init_autoneg_123.0=0 +port_init_autoneg_140.0=0 +port_init_autoneg_141.0=0 +port_init_autoneg_142.0=0 +port_init_autoneg_143.0=0 +port_phy_addr_1.0=0xff +port_phy_addr_2.0=0xff +port_phy_addr_3.0=0xff +port_phy_addr_4.0=0xff +port_phy_addr_20.0=0xff +port_phy_addr_21.0=0xff +port_phy_addr_22.0=0xff +port_phy_addr_23.0=0xff +port_phy_addr_38.0=0xff +port_phy_addr_40.0=0xff +port_phy_addr_41.0=0xff +port_phy_addr_42.0=0xff +port_phy_addr_43.0=0xff +port_phy_addr_60.0=0xff +port_phy_addr_61.0=0xff +port_phy_addr_62.0=0xff +port_phy_addr_63.0=0xff +port_phy_addr_80.0=0xff +port_phy_addr_81.0=0xff +port_phy_addr_82.0=0xff +port_phy_addr_83.0=0xff +port_phy_addr_100.0=0xff +port_phy_addr_101.0=0xff +port_phy_addr_102.0=0xff +port_phy_addr_103.0=0xff +port_phy_addr_118.0=0xff +port_phy_addr_120.0=0xff +port_phy_addr_121.0=0xff +port_phy_addr_122.0=0xff +port_phy_addr_123.0=0xff +port_phy_addr_140.0=0xff +port_phy_addr_141.0=0xff +port_phy_addr_142.0=0xff +port_phy_addr_143.0=0xff +robust_hash_disable_egress_vlan.0=1 +robust_hash_disable_mpls.0=1 +robust_hash_disable_vlan.0=1 +tdma_timeout_usec.0=15000000 +tslam_timeout_usec.0=15000000 + +# Tuning +serdes_core_rx_polarity_flip_physical{1}=0x69 +serdes_core_rx_polarity_flip_physical{9}=0x69 +serdes_core_rx_polarity_flip_physical{17}=0xe4 +serdes_core_rx_polarity_flip_physical{25}=0x62 +serdes_core_rx_polarity_flip_physical{33}=0x33 +serdes_core_rx_polarity_flip_physical{41}=0x66 +serdes_core_rx_polarity_flip_physical{49}=0x24 +serdes_core_rx_polarity_flip_physical{57}=0x66 +serdes_core_rx_polarity_flip_physical{65}=0x33 +serdes_core_rx_polarity_flip_physical{73}=0x63 +serdes_core_rx_polarity_flip_physical{81}=0x33 +serdes_core_rx_polarity_flip_physical{89}=0x63 +serdes_core_rx_polarity_flip_physical{97}=0x1e +serdes_core_rx_polarity_flip_physical{105}=0x63 +serdes_core_rx_polarity_flip_physical{113}=0xdb +serdes_core_rx_polarity_flip_physical{121}=0x69 +serdes_core_rx_polarity_flip_physical{129}=0x24 +serdes_core_rx_polarity_flip_physical{137}=0x66 +serdes_core_rx_polarity_flip_physical{145}=0x33 +serdes_core_rx_polarity_flip_physical{153}=0x5a +serdes_core_rx_polarity_flip_physical{161}=0xf +serdes_core_rx_polarity_flip_physical{169}=0x66 +serdes_core_rx_polarity_flip_physical{177}=0x30 +serdes_core_rx_polarity_flip_physical{185}=0x66 +serdes_core_rx_polarity_flip_physical{193}=0x30 +serdes_core_rx_polarity_flip_physical{201}=0x66 +serdes_core_rx_polarity_flip_physical{209}=0x33 +serdes_core_rx_polarity_flip_physical{217}=0x66 +serdes_core_rx_polarity_flip_physical{225}=0x24 +serdes_core_rx_polarity_flip_physical{233}=0x96 +serdes_core_rx_polarity_flip_physical{241}=0xe1 +serdes_core_rx_polarity_flip_physical{249}=0xc3 +serdes_core_rx_polarity_flip_physical{257}=0x0 +serdes_core_tx_polarity_flip_physical{1}=0x7b +serdes_core_tx_polarity_flip_physical{9}=0x4d +serdes_core_tx_polarity_flip_physical{17}=0x69 +serdes_core_tx_polarity_flip_physical{25}=0x69 +serdes_core_tx_polarity_flip_physical{33}=0x78 +serdes_core_tx_polarity_flip_physical{41}=0xcc +serdes_core_tx_polarity_flip_physical{49}=0xcf +serdes_core_tx_polarity_flip_physical{57}=0xca +serdes_core_tx_polarity_flip_physical{65}=0xc3 +serdes_core_tx_polarity_flip_physical{73}=0xca +serdes_core_tx_polarity_flip_physical{81}=0xc3 +serdes_core_tx_polarity_flip_physical{89}=0xca +serdes_core_tx_polarity_flip_physical{97}=0x70 +serdes_core_tx_polarity_flip_physical{105}=0x59 +serdes_core_tx_polarity_flip_physical{113}=0x12 +serdes_core_tx_polarity_flip_physical{121}=0x3c +serdes_core_tx_polarity_flip_physical{129}=0x12 +serdes_core_tx_polarity_flip_physical{137}=0x3c +serdes_core_tx_polarity_flip_physical{145}=0x12 +serdes_core_tx_polarity_flip_physical{153}=0x68 +serdes_core_tx_polarity_flip_physical{161}=0x6 +serdes_core_tx_polarity_flip_physical{169}=0x69 +serdes_core_tx_polarity_flip_physical{177}=0x6 +serdes_core_tx_polarity_flip_physical{185}=0x69 +serdes_core_tx_polarity_flip_physical{193}=0x6 +serdes_core_tx_polarity_flip_physical{201}=0x69 +serdes_core_tx_polarity_flip_physical{209}=0x6 +serdes_core_tx_polarity_flip_physical{217}=0x6a +serdes_core_tx_polarity_flip_physical{225}=0x66 +serdes_core_tx_polarity_flip_physical{233}=0x36 +serdes_core_tx_polarity_flip_physical{241}=0xc6 +serdes_core_tx_polarity_flip_physical{249}=0xc3 +serdes_core_tx_polarity_flip_physical{257}=0x0 +serdes_tx_taps_cd0=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd1=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd2=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd3=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd4=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd5=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd6=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd7=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd8=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd9=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd10=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd11=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd12=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd13=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd14=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd15=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd16=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd17=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd18=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd19=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd20=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd21=pam4:-28:124:0:4:0:0 +serdes_tx_taps_cd22=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd23=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd24=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd25=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd26=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd27=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd28=pam4:-28:120:-4:4:0:0 +serdes_tx_taps_cd29=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd30=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd31=pam4:-28:124:-12:4:0:0 +serdes_tx_taps_cd32=pam4:1:34:9:0:0:0 +serdes_tx_taps_cd33=pam4:1:34:9:0:0:0 diff --git a/device/arista/x86_64-arista_7060px4_32/default_sku b/device/arista/x86_64-arista_7060px4_32/default_sku new file mode 100644 index 000000000000..810b6667a18e --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/default_sku @@ -0,0 +1 @@ +Arista-7060PX4-O32 t1 diff --git a/device/arista/x86_64-arista_7060px4_32/fancontrol b/device/arista/x86_64-arista_7060px4_32/fancontrol new file mode 100644 index 000000000000..e0834b0728ff --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=5 +DEVPATH=hwmon3=devices/pci0000:ff/0000:ff:0b.3/i2c-73/73-004c hwmon4=devices/pci0000:ff/0000:ff:0b.3/i2c-85/85-0060 +DEVNAME=hwmon3=max6658 hwmon4=tehama_cpld +FCTEMPS=hwmon4/pwm5=hwmon3/temp1_input hwmon4/pwm4=hwmon3/temp1_input hwmon4/pwm3=hwmon3/temp1_input hwmon4/pwm2=hwmon3/temp1_input hwmon4/pwm1=hwmon3/temp1_input +FCFANS=hwmon4/pwm5=hwmon4/fan5_input hwmon4/pwm4=hwmon4/fan4_input hwmon4/pwm3=hwmon4/fan3_input hwmon4/pwm2=hwmon4/fan2_input hwmon4/pwm1=hwmon4/fan1_input +MINTEMP=hwmon4/pwm5=50 hwmon4/pwm4=50 hwmon4/pwm3=50 hwmon4/pwm2=50 hwmon4/pwm1=50 +MINPWM=hwmon4/pwm5=128 hwmon4/pwm4=128 hwmon4/pwm3=128 hwmon4/pwm2=128 hwmon4/pwm1=128 +MAXTEMP=hwmon4/pwm5=60 hwmon4/pwm4=60 hwmon4/pwm3=60 hwmon4/pwm2=60 hwmon4/pwm1=60 +MINSTART=hwmon4/pwm5=128 hwmon4/pwm4=128 hwmon4/pwm3=128 hwmon4/pwm2=128 hwmon4/pwm1=128 +MINSTOP=hwmon4/pwm5=128 hwmon4/pwm4=128 hwmon4/pwm3=128 hwmon4/pwm2=128 hwmon4/pwm1=128 diff --git a/device/arista/x86_64-arista_7060px4_32/platform.json b/device/arista/x86_64-arista_7060px4_32/platform.json new file mode 100644 index 000000000000..b486b9152c06 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/platform.json @@ -0,0 +1,223 @@ +{ + "chassis": { + "name": "DCS-7060PX4-32", + "components": [], + "fans": [], + "fan_drawers": [ + { + "name": "slot1", + "fans": [ + { + "name": "fan1" + } + ] + }, + { + "name": "slot2", + "fans": [ + { + "name": "fan2" + } + ] + }, + { + "name": "slot3", + "fans": [ + { + "name": "fan3" + } + ] + }, + { + "name": "slot4", + "fans": [ + { + "name": "fan4" + } + ] + }, + { + "name": "slot5", + "fans": [ + { + "name": "fan5" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Board sensor" + }, + { + "name": "Switch board middle sensor" + }, + { + "name": "Switch board left sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Switch chip diode 1 sensor" + }, + { + "name": "Switch chip diode 2 sensor" + }, + { + "name": "PCH temp sensor" + }, + { + "name": "Physical id 0" + }, + { + "name": "CPU core0 temp sensor" + }, + { + "name": "CPU core1 temp sensor" + }, + { + "name": "CPU board temp sensor" + }, + { + "name": "Back-panel temp sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Power supply 1 hotspot sensor" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 exhaust temp sensor" + }, + { + "name": "Power supply 2 hotspot sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 exhaust temp sensor" + } + ], + "sfps": [ + { + "name": "osfp1" + }, + { + "name": "osfp2" + }, + { + "name": "osfp3" + }, + { + "name": "osfp4" + }, + { + "name": "osfp5" + }, + { + "name": "osfp6" + }, + { + "name": "osfp7" + }, + { + "name": "osfp8" + }, + { + "name": "osfp9" + }, + { + "name": "osfp10" + }, + { + "name": "osfp11" + }, + { + "name": "osfp12" + }, + { + "name": "osfp13" + }, + { + "name": "osfp14" + }, + { + "name": "osfp15" + }, + { + "name": "osfp16" + }, + { + "name": "osfp17" + }, + { + "name": "osfp18" + }, + { + "name": "osfp19" + }, + { + "name": "osfp20" + }, + { + "name": "osfp21" + }, + { + "name": "osfp22" + }, + { + "name": "osfp23" + }, + { + "name": "osfp24" + }, + { + "name": "osfp25" + }, + { + "name": "osfp26" + }, + { + "name": "osfp27" + }, + { + "name": "osfp28" + }, + { + "name": "osfp29" + }, + { + "name": "osfp30" + }, + { + "name": "osfp31" + }, + { + "name": "osfp32" + }, + { + "name": "sfp33" + }, + { + "name": "sfp34" + } + ] + }, + "interfaces": {} +} \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060px4_32/platform_reboot b/device/arista/x86_64-arista_7060px4_32/platform_reboot new file mode 120000 index 000000000000..7f94a49e38b0 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/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_7060px4_32/plugins b/device/arista/x86_64-arista_7060px4_32/plugins new file mode 120000 index 000000000000..5fbbf98a6284 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/plugins @@ -0,0 +1 @@ +../x86_64-arista_common/plugins/ \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060px4_32/pmon_daemon_control.json b/device/arista/x86_64-arista_7060px4_32/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060px4_32/sensors.conf b/device/arista/x86_64-arista_7060px4_32/sensors.conf new file mode 100644 index 000000000000..2168c765fb77 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/sensors.conf @@ -0,0 +1,34 @@ +# libsensors configuration file for DCS-7060X3-32 +# ------------------------------------------------# + +bus "i2c-9" "SCD 0000:07:00.0 SMBus master 1 bus 0" +bus "i2c-12" "SCD 0000:07:00.0 SMBus master 1 bus 3" +bus "i2c-13" "SCD 0000:07:00.0 SMBus master 1 bus 4" +bus "i2c-73" "SCD 0000:ff:0b.3 SMBus master 0 bus 0" +bus "i2c-85" "SCD 0000:ff:0b.3 SMBus master 3 bus 0" + +chip "max6581-i2c-9-4d" + ignore temp1 + label temp2 "TH3 exhaust temp sensor" + label temp3 "Left edge PCB rear temp sensor" + label temp4 "Inlet temp sensor" + ignore temp5 + ignore temp6 + label temp7 "Diode temp sensor 1" + label temp8 "Diode temp sensor 2" + +chip "pmbus-i2c-12-58" + label temp1 "Power supply 1 hotspot sensor" + label temp2 "Power supply 1 inlet temp sensor" + label temp3 "Power supply 1 exhaust temp sensor" + +chip "pmbus-i2c-13-58" + label temp1 "Power supply 2 hotspot sensor" + label temp2 "Power supply 2 inlet temp sensor" + label temp3 "Power supply 2 exhaust temp sensor" + +chip "max6658-i2c-73-4c" + label temp1 "Back panel temp sensor 1" + label temp2 "Back panel temp sensor 2" + +chip "tehama_cpld-i2c-85-60" diff --git a/device/arista/x86_64-arista_7060px4_32/system_health_monitoring_config.json b/device/arista/x86_64-arista_7060px4_32/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060px4_32/thermal_policy.json b/device/arista/x86_64-arista_7060px4_32/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ 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/pmon_daemon_control.json b/device/arista/x86_64-arista_7170_32c/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7170_32c/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ 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_32c/system_health_monitoring_config.json b/device/arista/x86_64-arista_7170_32c/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7170_32c/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_32c/thermal_policy.json b/device/arista/x86_64-arista_7170_32c/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7170_32c/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ 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/pmon_daemon_control.json b/device/arista/x86_64-arista_7170_32cd/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7170_32cd/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ 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/arista/x86_64-arista_7170_32cd/system_health_monitoring_config.json b/device/arista/x86_64-arista_7170_32cd/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7170_32cd/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_32cd/thermal_policy.json b/device/arista/x86_64-arista_7170_32cd/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7170_32cd/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/board_lane_map.json b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/board_lane_map.json new file mode 100644 index 000000000000..04f2a9044a45 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/board_lane_map.json @@ -0,0 +1,3601 @@ +{ +"board_name": "7170-64C", +"enable_debug_log": 0, +"board_lane_map_entry": [ +{ +"connector": 1, +"device_id": 0, +"mac_block": 63, +"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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 2, +"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": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 1, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 3, +"device_id": 0, +"mac_block": 61, +"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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 4, +"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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 5, +"device_id": 0, +"mac_block": 55, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 6, +"device_id": 0, +"mac_block": 58, +"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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 7, +"device_id": 0, +"mac_block": 53, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 8, +"device_id": 0, +"mac_block": 15, +"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": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 9, +"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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 10, +"device_id": 0, +"mac_block": 13, +"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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 11, +"device_id": 0, +"mac_block": 9, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 1, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 12, +"device_id": 0, +"mac_block": 7, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 13, +"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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 14, +"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": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 15, +"device_id": 0, +"mac_block": 51, +"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": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 1, + "rx_lane": 2, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 16, +"device_id": 0, +"mac_block": 50, +"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": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + } +}, + +{ +"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": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 1, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 18, +"device_id": 0, +"mac_block": 48, +"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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 19, +"device_id": 0, +"mac_block": 29, +"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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 20, +"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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 21, +"device_id": 0, +"mac_block": 24, +"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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 22, +"device_id": 0, +"mac_block": 25, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 23, +"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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 24, +"device_id": 0, +"mac_block": 19, +"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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 25, +"device_id": 0, +"mac_block": 43, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 26, +"device_id": 0, +"mac_block": 17, +"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": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 1, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 1, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 27, +"device_id": 0, +"mac_block": 41, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 28, +"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": 1, + "serdes_params": { + "tx_eq_pre": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 29, +"device_id": 0, +"mac_block": 35, +"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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 30, +"device_id": 0, +"mac_block": 38, +"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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 31, +"device_id": 0, +"mac_block": 33, +"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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 32, +"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": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 1, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 33, +"device_id": 0, +"mac_block": 1, +"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": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 34, +"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": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 35, +"device_id": 0, +"mac_block": 59, +"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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 36, +"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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 37, +"device_id": 0, +"mac_block": 57, +"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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 38, +"device_id": 0, +"mac_block": 56, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 39, +"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": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 1, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 40, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 41, +"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": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 42, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 43, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 44, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 1, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 45, +"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": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 46, +"device_id": 0, +"mac_block": 3, +"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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 47, +"device_id": 0, +"mac_block": 49, +"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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 48, +"device_id": 0, +"mac_block": 52, +"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": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 1, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 49, +"device_id": 0, +"mac_block": 47, +"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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 50, +"device_id": 0, +"mac_block": 45, +"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": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 1, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 1, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 51, +"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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 52, +"device_id": 0, +"mac_block": 30, +"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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "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": 10, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 53, +"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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "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": 9, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 54, +"device_id": 0, +"mac_block": 23, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 1, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 1, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 55, +"device_id": 0, +"mac_block": 20, +"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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 56, +"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": 0, + "serdes_params": { + "tx_eq_pre": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 57, +"device_id": 0, +"mac_block": 18, +"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": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 1, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 58, +"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": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 1, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 59, +"device_id": 0, +"mac_block": 39, +"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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 60, +"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": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 9, + "tx_eq_post": 0, + "tx_eq_attn": 2 + } + } +}, + +{ +"connector": 61, +"device_id": 0, +"mac_block": 37, +"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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 62, +"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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "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": 7, + "tx_eq_post": 1, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 63, +"device_id": 0, +"mac_block": 31, +"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": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane1": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 1, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane2": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 1, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + }, + "lane3": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 8, + "tx_eq_post": 2, + "tx_eq_attn": 1 + } + } +}, + +{ +"connector": 64, +"device_id": 0, +"mac_block": 34, +"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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "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": 9, + "tx_eq_post": 3, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 65, +"device_id": 0, +"mac_block": 64, +"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": 5, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 66, +"device_id": 0, +"mac_block": 64, +"media_type": "copper", + "lane0": { + "mac_ch": 1, + "tx_lane": 1, + "tx_pn_swap": 0, + "rx_lane": 1, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 5, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 67, +"device_id": 0, +"mac_block": 64, +"media_type": "copper", + "lane0": { + "mac_ch": 2, + "tx_lane": 2, + "tx_pn_swap": 0, + "rx_lane": 2, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 5, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +}, + +{ +"connector": 68, +"device_id": 0, +"mac_block": 64, +"media_type": "copper", + "lane0": { + "mac_ch": 3, + "tx_lane": 3, + "tx_pn_swap": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 5, + "tx_eq_post": 0, + "tx_eq_attn": 0 + } + } +} + ] +} \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/buffers.json.j2 b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/buffers.json.j2 new file mode 100644 index 000000000000..e6e9e844469b --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..35188dbeb382 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/buffers_defaults_t0.j2 @@ -0,0 +1,71 @@ +{% 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' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic", + "xoff": "2867200" + }, + "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_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "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":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/buffers_defaults_t1.j2 b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..eb945c25e636 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/buffers_defaults_t1.j2 @@ -0,0 +1,71 @@ +{% 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' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic", + "xoff": "2867200" + }, + "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_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "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":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/pg_profile_lookup.ini b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/pg_profile_lookup.ini new file mode 100644 index 000000000000..78a72d842acd --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 34816 18432 16384 7 + 25000 5m 34816 18432 16384 7 + 40000 5m 34816 18432 16384 7 + 50000 5m 34816 18432 16384 7 + 100000 5m 36864 18432 18432 7 + 10000 40m 36864 18432 18432 7 + 25000 40m 39936 18432 21504 7 + 40000 40m 41984 18432 23552 7 + 50000 40m 41984 18432 23552 7 + 100000 40m 54272 18432 35840 7 + 10000 300m 49152 18432 30720 7 + 25000 300m 71680 18432 53248 7 + 40000 300m 94208 18432 75776 7 + 50000 300m 94208 18432 75776 7 + 100000 300m 184320 18432 165888 7 diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/port_config.ini b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/port_config.ini new file mode 100644 index 000000000000..cbff872de9c8 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/port_config.ini @@ -0,0 +1,65 @@ +# 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 +Ethernet128 128,129,130,131 Ethernet33/1 100000 33 +Ethernet132 132,133,134,135 Ethernet34/1 100000 34 +Ethernet136 136,137,138,139 Ethernet35/1 100000 35 +Ethernet140 140,141,142,143 Ethernet36/1 100000 36 +Ethernet144 144,145,146,147 Ethernet37/1 100000 37 +Ethernet148 148,149,150,151 Ethernet38/1 100000 38 +Ethernet152 152,153,154,155 Ethernet39/1 100000 39 +Ethernet156 156,157,158,159 Ethernet40/1 100000 40 +Ethernet160 160,161,162,163 Ethernet41/1 100000 41 +Ethernet164 164,165,166,167 Ethernet42/1 100000 42 +Ethernet168 168,169,170,171 Ethernet43/1 100000 43 +Ethernet172 172,173,174,175 Ethernet44/1 100000 44 +Ethernet176 176,177,178,179 Ethernet45/1 100000 45 +Ethernet180 180,181,182,183 Ethernet46/1 100000 46 +Ethernet184 184,185,186,187 Ethernet47/1 100000 47 +Ethernet188 188,189,190,191 Ethernet48/1 100000 48 +Ethernet192 192,193,194,195 Ethernet49/1 100000 49 +Ethernet196 196,197,198,199 Ethernet50/1 100000 50 +Ethernet200 200,201,202,203 Ethernet51/1 100000 51 +Ethernet204 204,205,206,207 Ethernet52/1 100000 52 +Ethernet208 208,209,210,211 Ethernet53/1 100000 53 +Ethernet212 212,213,214,215 Ethernet54/1 100000 54 +Ethernet216 216,217,218,219 Ethernet55/1 100000 55 +Ethernet220 220,221,222,223 Ethernet56/1 100000 56 +Ethernet224 224,225,226,227 Ethernet57/1 100000 57 +Ethernet228 228,229,230,231 Ethernet58/1 100000 58 +Ethernet232 232,233,234,235 Ethernet59/1 100000 59 +Ethernet236 236,237,238,239 Ethernet60/1 100000 60 +Ethernet240 240,241,242,243 Ethernet61/1 100000 61 +Ethernet244 244,245,246,247 Ethernet62/1 100000 62 +Ethernet248 248,249,250,251 Ethernet63/1 100000 63 +Ethernet252 252,253,254,255 Ethernet64/1 100000 64 diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/qos.json.j2 b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/switch-sai.conf b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/switch-sai.conf new file mode 100644 index 000000000000..0a807b1c9ea7 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/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_64c/Arista-7170-64C/switch-tna-sai.conf b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/switch-tna-sai.conf new file mode 100644 index 000000000000..ece3fcbe6a90 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-64C/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_64c/Arista-7170-Q59S20/board_lane_map.json b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/board_lane_map.json new file mode 100644 index 000000000000..dc81608655b7 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/board_lane_map.json @@ -0,0 +1,3534 @@ +{ + "board_name": "7170-64C", + "enable_debug_log": 0, + "board_lane_map_entry": [ + { + "connector": 1, + "device_id": 0, + "mac_block": 63, + "media_type": "optic", + "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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 2, + "device_id": 0, + "mac_block": 2, + "media_type": "optic", + "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": 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": 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": 61, + "media_type": "optic", + "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": 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": 1, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 4, + "device_id": 0, + "mac_block": 60, + "media_type": "optic", + "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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 5, + "device_id": 0, + "mac_block": 55, + "media_type": "optic", + "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": 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": 0, + "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": 58, + "media_type": "optic", + "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": 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": 7, + "device_id": 0, + "mac_block": 53, + "media_type": "optic", + "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": 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": 0, + "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": 15, + "media_type": "optic", + "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": 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": 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": 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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 10, + "device_id": 0, + "mac_block": 13, + "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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 11, + "device_id": 0, + "mac_block": 9, + "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": 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": 12, + "device_id": 0, + "mac_block": 7, + "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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 13, + "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": 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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 14, + "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": 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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 15, + "device_id": 0, + "mac_block": 51, + "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": 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": 16, + "device_id": 0, + "mac_block": 50, + "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": 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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 18, + "device_id": 0, + "mac_block": 48, + "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": 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": 19, + "device_id": 0, + "mac_block": 29, + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 20, + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 21, + "device_id": 0, + "mac_block": 24, + "media_type": "optic", + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 22, + "device_id": 0, + "mac_block": 25, + "media_type": "optic", + "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": 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": 0, + "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": 21, + "media_type": "optic", + "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": 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": 24, + "device_id": 0, + "mac_block": 19, + "media_type": "optic", + "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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 25, + "device_id": 0, + "mac_block": 43, + "media_type": "optic", + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 26, + "device_id": 0, + "mac_block": 17, + "media_type": "optic", + "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": 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": 27, + "device_id": 0, + "mac_block": 41, + "media_type": "optic", + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 28, + "device_id": 0, + "mac_block": 40, + "media_type": "optic", + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 29, + "device_id": 0, + "mac_block": 35, + "media_type": "optic", + "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": 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": 30, + "device_id": 0, + "mac_block": 38, + "media_type": "optic", + "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": 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": 33, + "media_type": "optic", + "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": 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": 32, + "device_id": 0, + "mac_block": 32, + "media_type": "optic", + "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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 33, + "device_id": 0, + "mac_block": 1, + "media_type": "optic", + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 34, + "device_id": 0, + "mac_block": 0, + "media_type": "optic", + "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": 35, + "device_id": 0, + "mac_block": 59, + "media_type": "optic", + "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": 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": 36, + "device_id": 0, + "mac_block": 62, + "media_type": "optic", + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 37, + "device_id": 0, + "mac_block": 57, + "media_type": "optic", + "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": 38, + "device_id": 0, + "mac_block": 56, + "media_type": "optic", + "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": 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": 39, + "device_id": 0, + "mac_block": 16, + "media_type": "optic", + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 40, + "device_id": 0, + "mac_block": 54, + "media_type": "optic", + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 41, + "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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 42, + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 43, + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 44, + "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": 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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 45, + "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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 46, + "device_id": 0, + "mac_block": 3, + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 47, + "device_id": 0, + "mac_block": 49, + "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": 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": 48, + "device_id": 0, + "mac_block": 52, + "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": 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": 49, + "device_id": 0, + "mac_block": 47, + "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": 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": 50, + "device_id": 0, + "mac_block": 45, + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 51, + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 52, + "device_id": 0, + "mac_block": 30, + "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": 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": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 53, + "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": 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": 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": 54, + "device_id": 0, + "mac_block": 23, + "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": 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": 55, + "device_id": 0, + "mac_block": 20, + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 56, + "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": 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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 57, + "device_id": 0, + "mac_block": 18, + "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": 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": 58, + "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": 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": 59, + "device_id": 0, + "mac_block": 39, + "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": 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": 60, + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 1, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 61, + "device_id": 0, + "mac_block": 37, + "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": 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": 62, + "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": 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": 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": 63, + "device_id": 0, + "mac_block": 31, + "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": 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": 0, + "rx_lane": 3, + "rx_pn_swap": 0, + "serdes_params": { + "tx_eq_pre": 2, + "tx_eq_post": 4, + "tx_eq_attn": 0 + } + } + }, + { + "connector": 64, + "device_id": 0, + "mac_block": 34, + "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": 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": 65, + "device_id": 0, + "mac_block": 64, + "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 + } + } + }, + { + "connector": 66, + "device_id": 0, + "mac_block": 64, + "media_type": "copper", + "lane0": { + "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 + } + } + }, + { + "connector": 67, + "device_id": 0, + "mac_block": 64, + "media_type": "copper", + "lane0": { + "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 + } + } + }, + { + "connector": 68, + "device_id": 0, + "mac_block": 64, + "media_type": "copper", + "lane0": { + "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 + } + } + } + ] +} \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/buffers.json.j2 b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/buffers.json.j2 new file mode 100644 index 000000000000..e6e9e844469b --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..8cd886c14ffd --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/buffers_defaults_t0.j2 @@ -0,0 +1,83 @@ +{% 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' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,20) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(80,88) %} + {%- if PORT_ALL.append("Ethernet%d" % port_idx) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(22,32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(128,140) %} + {%- if PORT_ALL.append("Ethernet%d" % port_idx) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(35,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic", + "xoff": "2867200" + }, + "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_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "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":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/buffers_defaults_t1.j2 b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..e14ad9214743 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/buffers_defaults_t1.j2 @@ -0,0 +1,83 @@ +{% 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' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,20) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(80,88) %} + {%- if PORT_ALL.append("Ethernet%d" % port_idx) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(22,32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(128,140) %} + {%- if PORT_ALL.append("Ethernet%d" % port_idx) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(35,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic", + "xoff": "2867200" + }, + "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_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "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":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/pg_profile_lookup.ini b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/pg_profile_lookup.ini new file mode 100644 index 000000000000..78a72d842acd --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 34816 18432 16384 7 + 25000 5m 34816 18432 16384 7 + 40000 5m 34816 18432 16384 7 + 50000 5m 34816 18432 16384 7 + 100000 5m 36864 18432 18432 7 + 10000 40m 36864 18432 18432 7 + 25000 40m 39936 18432 21504 7 + 40000 40m 41984 18432 23552 7 + 50000 40m 41984 18432 23552 7 + 100000 40m 54272 18432 35840 7 + 10000 300m 49152 18432 30720 7 + 25000 300m 71680 18432 53248 7 + 40000 300m 94208 18432 75776 7 + 50000 300m 94208 18432 75776 7 + 100000 300m 184320 18432 165888 7 diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/port_config.ini b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/port_config.ini new file mode 100644 index 000000000000..cf01e339b810 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/port_config.ini @@ -0,0 +1,80 @@ +# name lanes alias speed index autoneg +Ethernet0 0,1,2,3 Ethernet1/1 40000 1 0 +Ethernet4 4,5,6,7 Ethernet2/1 40000 2 0 +Ethernet8 8,9,10,11 Ethernet3/1 40000 3 0 +Ethernet12 12,13,14,15 Ethernet4/1 40000 4 0 +Ethernet16 16,17,18,19 Ethernet5/1 40000 5 0 +Ethernet20 20,21,22,23 Ethernet6/1 40000 6 0 +Ethernet24 24,25,26,27 Ethernet7/1 40000 7 0 +Ethernet28 28,29,30,31 Ethernet8/1 40000 8 0 +Ethernet32 32,33,34,35 Ethernet9/1 40000 9 1 +Ethernet36 36,37,38,39 Ethernet10/1 40000 10 1 +Ethernet40 40,41,42,43 Ethernet11/1 40000 11 1 +Ethernet44 44,45,46,47 Ethernet12/1 40000 12 1 +Ethernet48 48,49,50,51 Ethernet13/1 40000 13 1 +Ethernet52 52,53,54,55 Ethernet14/1 40000 14 1 +Ethernet56 56,57,58,59 Ethernet15/1 40000 15 1 +Ethernet60 60,61,62,63 Ethernet16/1 40000 16 1 +Ethernet64 64,65,66,67 Ethernet17/1 40000 17 1 +Ethernet68 68,69,70,71 Ethernet18/1 40000 18 1 +Ethernet72 72,73,74,75 Ethernet19/1 40000 19 1 +Ethernet76 76,77,78,79 Ethernet20/1 40000 20 1 +Ethernet80 80 Ethernet21/1 10000 21 0 +Ethernet81 81 Ethernet21/2 10000 21 0 +Ethernet82 82 Ethernet21/3 10000 21 0 +Ethernet83 83 Ethernet21/4 10000 21 0 +Ethernet84 84 Ethernet22/1 10000 22 0 +Ethernet85 85 Ethernet22/2 10000 22 0 +Ethernet86 86 Ethernet22/3 10000 22 0 +Ethernet87 87 Ethernet22/4 10000 22 0 +Ethernet88 88,89,90,91 Ethernet23/1 40000 23 0 +Ethernet92 92,93,94,95 Ethernet24/1 40000 24 0 +Ethernet96 96,97,98,99 Ethernet25/1 40000 25 0 +Ethernet100 100,101,102,103 Ethernet26/1 40000 26 0 +Ethernet104 104,105,106,107 Ethernet27/1 40000 27 0 +Ethernet108 108,109,110,111 Ethernet28/1 40000 28 0 +Ethernet112 112,113,114,115 Ethernet29/1 40000 29 0 +Ethernet116 116,117,118,119 Ethernet30/1 40000 30 0 +Ethernet120 120,121,122,123 Ethernet31/1 40000 31 0 +Ethernet124 124,125,126,127 Ethernet32/1 40000 32 0 +Ethernet128 128 Ethernet33/1 10000 33 0 +Ethernet129 129 Ethernet33/2 10000 33 0 +Ethernet130 130 Ethernet33/3 10000 33 0 +Ethernet131 131 Ethernet33/4 10000 33 0 +Ethernet132 132 Ethernet34/1 10000 34 0 +Ethernet133 133 Ethernet34/2 10000 34 0 +Ethernet134 134 Ethernet34/3 10000 34 0 +Ethernet135 135 Ethernet34/4 10000 34 0 +Ethernet136 136 Ethernet35/1 10000 35 0 +Ethernet137 137 Ethernet35/2 10000 35 0 +Ethernet138 138 Ethernet35/3 10000 35 0 +Ethernet139 139 Ethernet35/4 10000 35 0 +Ethernet140 140,141,142,143 Ethernet36/1 40000 36 0 +Ethernet144 144,145,146,147 Ethernet37/1 40000 37 0 +Ethernet148 148,149,150,151 Ethernet38/1 40000 38 0 +Ethernet152 152,153,154,155 Ethernet39/1 40000 39 0 +Ethernet156 156,157,158,159 Ethernet40/1 40000 40 0 +Ethernet160 160,161,162,163 Ethernet41/1 40000 41 1 +Ethernet164 164,165,166,167 Ethernet42/1 40000 42 1 +Ethernet168 168,169,170,171 Ethernet43/1 40000 43 1 +Ethernet172 172,173,174,175 Ethernet44/1 40000 44 1 +Ethernet176 176,177,178,179 Ethernet45/1 40000 45 1 +Ethernet180 180,181,182,183 Ethernet46/1 40000 46 1 +Ethernet184 184,185,186,187 Ethernet47/1 40000 47 1 +Ethernet188 188,189,190,191 Ethernet48/1 40000 48 1 +Ethernet192 192,193,194,195 Ethernet49/1 40000 49 1 +Ethernet196 196,197,198,199 Ethernet50/1 40000 50 1 +Ethernet200 200,201,202,203 Ethernet51/1 40000 51 1 +Ethernet204 204,205,206,207 Ethernet52/1 40000 52 1 +Ethernet208 208,209,210,211 Ethernet53/1 40000 53 1 +Ethernet212 212,213,214,215 Ethernet54/1 40000 54 1 +Ethernet216 216,217,218,219 Ethernet55/1 40000 55 1 +Ethernet220 220,221,222,223 Ethernet56/1 40000 56 1 +Ethernet224 224,225,226,227 Ethernet57/1 40000 57 1 +Ethernet228 228,229,230,231 Ethernet58/1 40000 58 1 +Ethernet232 232,233,234,235 Ethernet59/1 40000 59 1 +Ethernet236 236,237,238,239 Ethernet60/1 40000 60 1 +Ethernet240 240,241,242,243 Ethernet61/1 40000 61 1 +Ethernet244 244,245,246,247 Ethernet62/1 40000 62 1 +Ethernet248 248,249,250,251 Ethernet63/1 40000 63 1 +Ethernet252 252,253,254,255 Ethernet64/1 40000 64 1 diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/qos.json.j2 b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/switch-sai.conf b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/switch-sai.conf new file mode 100644 index 000000000000..0a807b1c9ea7 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/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_64c/Arista-7170-Q59S20/switch-tna-sai.conf b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/switch-tna-sai.conf new file mode 100644 index 000000000000..ece3fcbe6a90 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/Arista-7170-Q59S20/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_64c/default_sku b/device/arista/x86_64-arista_7170_64c/default_sku new file mode 100644 index 000000000000..c3355162a6da --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/default_sku @@ -0,0 +1 @@ +Arista-7170-64C t1 diff --git a/device/arista/x86_64-arista_7170_64c/fancontrol b/device/arista/x86_64-arista_7170_64c/fancontrol new file mode 100644 index 000000000000..7236dbf4d18d --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=5 +DEVPATH=hwmon2=devices/pci0000:00/0000:00:1c.0/0000:06:00.0/i2c-8/8-004c hwmon4=devices/pci0000:ff/0000:ff:0b.3/i2c-93/93-0060 +DEVNAME=hwmon2=max6658 hwmon4=la_cpld +FCTEMPS=hwmon4/pwm4=hwmon2/temp1_input hwmon4/pwm3=hwmon2/temp1_input hwmon4/pwm2=hwmon2/temp1_input hwmon4/pwm1=hwmon2/temp1_input +FCFANS=hwmon4/pwm4=hwmon4/fan4_input hwmon4/pwm3=hwmon4/fan3_input hwmon4/pwm2=hwmon4/fan2_input hwmon4/pwm1=hwmon4/fan1_input +MINTEMP=hwmon4/pwm4=50 hwmon4/pwm3=50 hwmon4/pwm2=50 hwmon4/pwm1=50 +MINPWM=hwmon4/pwm4=128 hwmon4/pwm3=128 hwmon4/pwm2=128 hwmon4/pwm1=128 +MAXTEMP=hwmon4/pwm4=60 hwmon4/pwm3=60 hwmon4/pwm2=60 hwmon4/pwm1=60 +MINSTART=hwmon4/pwm4=128 hwmon4/pwm3=128 hwmon4/pwm2=128 hwmon4/pwm1=128 +MINSTOP=hwmon4/pwm4=128 hwmon4/pwm3=128 hwmon4/pwm2=128 hwmon4/pwm1=128 diff --git a/device/arista/x86_64-arista_7170_64c/platform.json b/device/arista/x86_64-arista_7170_64c/platform.json new file mode 100644 index 000000000000..d9207b1ba9cc --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/platform.json @@ -0,0 +1,299 @@ +{ + "chassis": { + "name": "DCS-7170-64C", + "components": [], + "fans": [], + "fan_drawers": [ + { + "name": "slot1", + "fans": [ + { + "name": "fan1" + } + ] + }, + { + "name": "slot2", + "fans": [ + { + "name": "fan2" + } + ] + }, + { + "name": "slot3", + "fans": [ + { + "name": "fan3" + } + ] + }, + { + "name": "slot4", + "fans": [ + { + "name": "fan4" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Board sensor" + }, + { + "name": "Switch Chip sensor" + }, + { + "name": "PCH temp sensor" + }, + { + "name": "Physical id 0" + }, + { + "name": "CPU core0 temp sensor" + }, + { + "name": "CPU core1 temp sensor" + }, + { + "name": "CPU board temp sensor" + }, + { + "name": "Back-panel temp sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Power supply 1 hotspot sensor" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 exhaust temp sensor" + }, + { + "name": "Power supply 2 hotspot sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 exhaust temp sensor" + } + ], + "sfps": [ + { + "name": "qsfp1" + }, + { + "name": "qsfp2" + }, + { + "name": "qsfp3" + }, + { + "name": "qsfp4" + }, + { + "name": "qsfp5" + }, + { + "name": "qsfp6" + }, + { + "name": "qsfp7" + }, + { + "name": "qsfp8" + }, + { + "name": "qsfp9" + }, + { + "name": "qsfp10" + }, + { + "name": "qsfp11" + }, + { + "name": "qsfp12" + }, + { + "name": "qsfp13" + }, + { + "name": "qsfp14" + }, + { + "name": "qsfp15" + }, + { + "name": "qsfp16" + }, + { + "name": "qsfp17" + }, + { + "name": "qsfp18" + }, + { + "name": "qsfp19" + }, + { + "name": "qsfp20" + }, + { + "name": "qsfp21" + }, + { + "name": "qsfp22" + }, + { + "name": "qsfp23" + }, + { + "name": "qsfp24" + }, + { + "name": "qsfp25" + }, + { + "name": "qsfp26" + }, + { + "name": "qsfp27" + }, + { + "name": "qsfp28" + }, + { + "name": "qsfp29" + }, + { + "name": "qsfp30" + }, + { + "name": "qsfp31" + }, + { + "name": "qsfp32" + }, + { + "name": "qsfp33" + }, + { + "name": "qsfp34" + }, + { + "name": "qsfp35" + }, + { + "name": "qsfp36" + }, + { + "name": "qsfp37" + }, + { + "name": "qsfp38" + }, + { + "name": "qsfp39" + }, + { + "name": "qsfp40" + }, + { + "name": "qsfp41" + }, + { + "name": "qsfp42" + }, + { + "name": "qsfp43" + }, + { + "name": "qsfp44" + }, + { + "name": "qsfp45" + }, + { + "name": "qsfp46" + }, + { + "name": "qsfp47" + }, + { + "name": "qsfp48" + }, + { + "name": "qsfp49" + }, + { + "name": "qsfp50" + }, + { + "name": "qsfp51" + }, + { + "name": "qsfp52" + }, + { + "name": "qsfp53" + }, + { + "name": "qsfp54" + }, + { + "name": "qsfp55" + }, + { + "name": "qsfp56" + }, + { + "name": "qsfp57" + }, + { + "name": "qsfp58" + }, + { + "name": "qsfp59" + }, + { + "name": "qsfp60" + }, + { + "name": "qsfp61" + }, + { + "name": "qsfp62" + }, + { + "name": "qsfp63" + }, + { + "name": "qsfp64" + }, + { + "name": "sfp65" + }, + { + "name": "sfp66" + } + ] + }, + "interfaces": {} +} \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_64c/platform_reboot b/device/arista/x86_64-arista_7170_64c/platform_reboot new file mode 120000 index 000000000000..7f94a49e38b0 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/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_64c/plugins b/device/arista/x86_64-arista_7170_64c/plugins new file mode 120000 index 000000000000..5fbbf98a6284 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/plugins @@ -0,0 +1 @@ +../x86_64-arista_common/plugins/ \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_64c/pmon_daemon_control.json b/device/arista/x86_64-arista_7170_64c/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_64c/sensors.conf b/device/arista/x86_64-arista_7170_64c/sensors.conf new file mode 100644 index 000000000000..5b1e592cbe21 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/sensors.conf @@ -0,0 +1,59 @@ +# libsensors configuration file for DCS-7260CX3-64 +# ------------------------------------------------ + +bus "i2c-6" "SCD 0000:06:00.0 SMBus master 0 bus 5" +bus "i2c-7" "SCD 0000:06:00.0 SMBus master 0 bus 6" +bus "i2c-8" "SCD 0000:06:00.0 SMBus master 0 bus 7" +bus "i2c-81" "SCD 0000:ff:0b.3 SMBus master 0 bus 0" +bus "i2c-93" "SCD 0000:ff:0b.3 SMBus master 3 bus 0" +bus "i2c-96" "SCD 0000:ff:0b.3 SMBus master 3 bus 3" + +chip "max6658-i2c-8-4c" + label temp1 "Temp sensor near ASIC" + + set temp1_max 100 + set temp1_crit 110 + set temp1_min -55 + + set temp2_max 100 + set temp2_crit 110 + set temp2_min -55 + ignore temp2 + +chip "pmbus-i2c-6-58" + label temp1 "PSU1 primary hotspot temp" + label temp2 "PSU1 inlet temp" + label temp3 "PSU1 exhaust temp" + + # setting maximum and critical thresholds is not supported for this psu + # fault and warning limits defined internally by hardware + + ignore fan2 + ignore fan3 + +chip "pmbus-i2c-7-58" + label temp1 "PSU2 primary hotspot temp" + label temp2 "PSU2 inlet temp" + label temp3 "PSU2 exhaust temp" + + # setting maximum and critical thresholds is not supported for this psu + # fault and warning limits defined internally by hardware + + ignore fan2 + ignore fan3 + +chip "max6658-i2c-81-4c" + label temp1 "Rear air temp1" + label temp2 "Rear air temp2" + + set temp1_max 70 + set temp1_crit 80 + set temp1_min -55 + set temp2_max 70 + set temp2_crit 80 + set temp2_min -55 + +chip "lm73-i2c-96-48" + label temp1 "Front air temp" + + set temp1_max 65 diff --git a/device/arista/x86_64-arista_7170_64c/system_health_monitoring_config.json b/device/arista/x86_64-arista_7170_64c/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_64c/thermal_policy.json b/device/arista/x86_64-arista_7170_64c/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-C64/port_config.ini b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-C64/port_config.ini new file mode 100644 index 000000000000..3940948a3541 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-C64/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 77,78,79,80 Ethernet1/1 1 100000 +Ethernet4 65,66,67,68 Ethernet2/1 2 100000 +Ethernet8 85,86,87,88 Ethernet3/1 3 100000 +Ethernet12 89,90,91,92 Ethernet4/1 4 100000 +Ethernet16 109,110,111,112 Ethernet5/1 5 100000 +Ethernet20 97,98,99,100 Ethernet6/1 6 100000 +Ethernet24 5,6,7,8 Ethernet7/1 7 100000 +Ethernet28 13,14,15,16 Ethernet8/1 8 100000 +Ethernet32 25,26,27,28 Ethernet9/1 9 100000 +Ethernet36 21,22,23,24 Ethernet10/1 10 100000 +Ethernet40 37,38,39,40 Ethernet11/1 11 100000 +Ethernet44 45,46,47,48 Ethernet12/1 12 100000 +Ethernet48 57,58,59,60 Ethernet13/1 13 100000 +Ethernet52 53,54,55,56 Ethernet14/1 14 100000 +Ethernet56 117,118,119,120 Ethernet15/1 15 100000 +Ethernet60 121,122,123,124 Ethernet16/1 16 100000 +Ethernet64 141,142,143,144 Ethernet17/1 17 100000 +Ethernet68 133,134,135,136 Ethernet18/1 18 100000 +Ethernet72 197,198,199,200 Ethernet19/1 19 100000 +Ethernet76 205,206,207,208 Ethernet20/1 20 100000 +Ethernet80 217,218,219,220 Ethernet21/1 21 100000 +Ethernet84 213,214,215,216 Ethernet22/1 22 100000 +Ethernet88 229,230,231,232 Ethernet23/1 23 100000 +Ethernet92 237,238,239,240 Ethernet24/1 24 100000 +Ethernet96 249,250,251,252 Ethernet25/1 25 100000 +Ethernet100 245,246,247,248 Ethernet26/1 26 100000 +Ethernet104 149,150,151,152 Ethernet27/1 27 100000 +Ethernet108 153,154,155,156 Ethernet28/1 28 100000 +Ethernet112 173,174,175,176 Ethernet29/1 29 100000 +Ethernet116 161,162,163,164 Ethernet30/1 30 100000 +Ethernet120 181,182,183,184 Ethernet31/1 31 100000 +Ethernet124 185,186,187,188 Ethernet32/1 32 100000 +Ethernet128 69,70,71,72 Ethernet33/1 33 100000 +Ethernet132 73,74,75,76 Ethernet34/1 34 100000 +Ethernet136 93,94,95,96 Ethernet35/1 35 100000 +Ethernet140 81,82,83,84 Ethernet36/1 36 100000 +Ethernet144 101,102,103,104 Ethernet37/1 37 100000 +Ethernet148 105,106,107,108 Ethernet38/1 38 100000 +Ethernet152 9,10,11,12 Ethernet39/1 39 100000 +Ethernet156 1,2,3,4 Ethernet40/1 40 100000 +Ethernet160 17,18,19,20 Ethernet41/1 41 100000 +Ethernet164 29,30,31,32 Ethernet42/1 42 100000 +Ethernet168 41,42,43,44 Ethernet43/1 43 100000 +Ethernet172 33,34,35,36 Ethernet44/1 44 100000 +Ethernet176 49,50,51,52 Ethernet45/1 45 100000 +Ethernet180 61,62,63,64 Ethernet46/1 46 100000 +Ethernet184 125,126,127,128 Ethernet47/1 47 100000 +Ethernet188 113,114,115,116 Ethernet48/1 48 100000 +Ethernet192 129,130,131,132 Ethernet49/1 49 100000 +Ethernet196 137,138,139,140 Ethernet50/1 50 100000 +Ethernet200 201,202,203,204 Ethernet51/1 51 100000 +Ethernet204 193,194,195,196 Ethernet52/1 52 100000 +Ethernet208 209,210,211,212 Ethernet53/1 53 100000 +Ethernet212 221,222,223,224 Ethernet54/1 54 100000 +Ethernet216 233,234,235,236 Ethernet55/1 55 100000 +Ethernet220 225,226,227,228 Ethernet56/1 56 100000 +Ethernet224 241,242,243,244 Ethernet57/1 57 100000 +Ethernet228 253,254,255,256 Ethernet58/1 58 100000 +Ethernet232 157,158,159,160 Ethernet59/1 59 100000 +Ethernet236 145,146,147,148 Ethernet60/1 60 100000 +Ethernet240 165,166,167,168 Ethernet61/1 61 100000 +Ethernet244 169,170,171,172 Ethernet62/1 62 100000 +Ethernet248 189,190,191,192 Ethernet63/1 63 100000 +Ethernet252 177,178,179,180 Ethernet64/1 64 100000 +Ethernet256 257 Ethernet65 65 10000 +Ethernet260 259 Ethernet66 66 10000 diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-C64/sai.profile b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-C64/sai.profile new file mode 100644 index 000000000000..2607bef50850 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-C64/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-a7260cx3-64-64x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-C64/th2-a7260cx3-64-64x100G.config.bcm b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-C64/th2-a7260cx3-64-64x100G.config.bcm new file mode 100644 index 000000000000..13fdd280e857 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-C64/th2-a7260cx3-64-64x100G.config.bcm @@ -0,0 +1,1013 @@ +PHY_AN_ALLOW_PLL_CHANGE=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +core_clock_frequency=1700 +dma_desc_timeout_usec=15000000 +dpp_clock_ratio=2:3 +higig2_hdr_mode=1 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +l2xmsg_mode=1 +max_vp_lags=0 +mem_scan_enable=1 +miim_intr_enable=0 +module_64ports=1 +os=unix +oversubscribe_mode=1 +pbmp_xport_xe=0x40003ffff0000ffffc0003fffe0001fffe +phy_an_allow_pll_change_hg=0 +phy_an_c73_100=1 +phy_an_c73_102=1 +phy_an_c73_103=1 +phy_an_c73_104=1 +phy_an_c73_105=1 +phy_an_c73_106=1 +phy_an_c73_107=1 +phy_an_c73_108=1 +phy_an_c73_109=1 +phy_an_c73_10=1 +phy_an_c73_110=1 +phy_an_c73_111=1 +phy_an_c73_112=1 +phy_an_c73_113=1 +phy_an_c73_114=1 +phy_an_c73_115=1 +phy_an_c73_116=1 +phy_an_c73_117=1 +phy_an_c73_11=1 +phy_an_c73_12=1 +phy_an_c73_13=1 +phy_an_c73_14=1 +phy_an_c73_15=1 +phy_an_c73_16=1 +phy_an_c73_1=1 +phy_an_c73_2=1 +phy_an_c73_34=1 +phy_an_c73_35=1 +phy_an_c73_36=1 +phy_an_c73_37=1 +phy_an_c73_38=1 +phy_an_c73_39=1 +phy_an_c73_3=1 +phy_an_c73_40=1 +phy_an_c73_41=1 +phy_an_c73_42=1 +phy_an_c73_43=1 +phy_an_c73_44=1 +phy_an_c73_45=1 +phy_an_c73_46=1 +phy_an_c73_47=1 +phy_an_c73_48=1 +phy_an_c73_49=1 +phy_an_c73_4=1 +phy_an_c73_5=1 +phy_an_c73_66=1 +phy_an_c73_68=1 +phy_an_c73_69=1 +phy_an_c73_6=1 +phy_an_c73_70=1 +phy_an_c73_71=1 +phy_an_c73_72=1 +phy_an_c73_73=1 +phy_an_c73_74=1 +phy_an_c73_75=1 +phy_an_c73_76=1 +phy_an_c73_77=1 +phy_an_c73_78=1 +phy_an_c73_79=1 +phy_an_c73_7=1 +phy_an_c73_80=1 +phy_an_c73_81=1 +phy_an_c73_82=1 +phy_an_c73_83=1 +phy_an_c73_8=1 +phy_an_c73_9=1 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_rx_lane_map_physical{101.0}=0x0123 +phy_chain_rx_lane_map_physical{105.0}=0x0123 +phy_chain_rx_lane_map_physical{109.0}=0x0123 +phy_chain_rx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_rx_lane_map_physical{121.0}=0x3210 +phy_chain_rx_lane_map_physical{125.0}=0x1203 +phy_chain_rx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{13.0}=0x0321 +phy_chain_rx_lane_map_physical{133.0}=0x1032 +phy_chain_rx_lane_map_physical{137.0}=0x3210 +phy_chain_rx_lane_map_physical{141.0}=0x0123 +phy_chain_rx_lane_map_physical{145.0}=0x3210 +phy_chain_rx_lane_map_physical{149.0}=0x2310 +phy_chain_rx_lane_map_physical{153.0}=0x0132 +phy_chain_rx_lane_map_physical{157.0}=0x1302 +phy_chain_rx_lane_map_physical{161.0}=0x3021 +phy_chain_rx_lane_map_physical{165.0}=0x2031 +phy_chain_rx_lane_map_physical{169.0}=0x2031 +phy_chain_rx_lane_map_physical{17.0}=0x3210 +phy_chain_rx_lane_map_physical{173.0}=0x1302 +phy_chain_rx_lane_map_physical{177.0}=0x2031 +phy_chain_rx_lane_map_physical{181.0}=0x0213 +phy_chain_rx_lane_map_physical{185.0}=0x0213 +phy_chain_rx_lane_map_physical{189.0}=0x1302 +phy_chain_rx_lane_map_physical{193.0}=0x3120 +phy_chain_rx_lane_map_physical{197.0}=0x0231 +phy_chain_rx_lane_map_physical{201.0}=0x2031 +phy_chain_rx_lane_map_physical{205.0}=0x0213 +phy_chain_rx_lane_map_physical{209.0}=0x2013 +phy_chain_rx_lane_map_physical{21.0}=0x3021 +phy_chain_rx_lane_map_physical{213.0}=0x3021 +phy_chain_rx_lane_map_physical{217.0}=0x0231 +phy_chain_rx_lane_map_physical{221.0}=0x2031 +phy_chain_rx_lane_map_physical{225.0}=0x1203 +phy_chain_rx_lane_map_physical{229.0}=0x1230 +phy_chain_rx_lane_map_physical{233.0}=0x3021 +phy_chain_rx_lane_map_physical{237.0}=0x1032 +phy_chain_rx_lane_map_physical{241.0}=0x2301 +phy_chain_rx_lane_map_physical{245.0}=0x0321 +phy_chain_rx_lane_map_physical{249.0}=0x2301 +phy_chain_rx_lane_map_physical{25.0}=0x2301 +phy_chain_rx_lane_map_physical{253.0}=0x2301 +phy_chain_rx_lane_map_physical{257.0}=0x3210 +phy_chain_rx_lane_map_physical{29.0}=0x3021 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 +phy_chain_rx_lane_map_physical{41.0}=0x3021 +phy_chain_rx_lane_map_physical{45.0}=0x1023 +phy_chain_rx_lane_map_physical{49.0}=0x0213 +phy_chain_rx_lane_map_physical{5.0}=0x3201 +phy_chain_rx_lane_map_physical{53.0}=0x3201 +phy_chain_rx_lane_map_physical{57.0}=0x2013 +phy_chain_rx_lane_map_physical{61.0}=0x0213 +phy_chain_rx_lane_map_physical{65.0}=0x1203 +phy_chain_rx_lane_map_physical{69.0}=0x0213 +phy_chain_rx_lane_map_physical{73.0}=0x0213 +phy_chain_rx_lane_map_physical{77.0}=0x3120 +phy_chain_rx_lane_map_physical{81.0}=0x0213 +phy_chain_rx_lane_map_physical{85.0}=0x2031 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_rx_lane_map_physical{9.0}=0x0321 +phy_chain_rx_lane_map_physical{93.0}=0x3120 +phy_chain_rx_lane_map_physical{97.0}=0x1203 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +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{11.0}=0x1 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +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{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +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}=0x1 +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{130.0}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{133.0}=0x1 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_rx_polarity_flip_physical{141.0}=0x1 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x0 +phy_chain_rx_polarity_flip_physical{147.0}=0x1 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x1 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x1 +phy_chain_rx_polarity_flip_physical{156.0}=0x0 +phy_chain_rx_polarity_flip_physical{157.0}=0x0 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x1 +phy_chain_rx_polarity_flip_physical{169.0}=0x1 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x0 +phy_chain_rx_polarity_flip_physical{175.0}=0x1 +phy_chain_rx_polarity_flip_physical{176.0}=0x1 +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x1 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{18.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x0 +phy_chain_rx_polarity_flip_physical{181.0}=0x1 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_rx_polarity_flip_physical{185.0}=0x0 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x1 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_rx_polarity_flip_physical{190.0}=0x0 +phy_chain_rx_polarity_flip_physical{191.0}=0x1 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x1 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x0 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x0 +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x0 +phy_chain_rx_polarity_flip_physical{215.0}=0x1 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 +phy_chain_rx_polarity_flip_physical{217.0}=0x0 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 +phy_chain_rx_polarity_flip_physical{221.0}=0x0 +phy_chain_rx_polarity_flip_physical{222.0}=0x0 +phy_chain_rx_polarity_flip_physical{223.0}=0x1 +phy_chain_rx_polarity_flip_physical{224.0}=0x1 +phy_chain_rx_polarity_flip_physical{225.0}=0x1 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x0 +phy_chain_rx_polarity_flip_physical{228.0}=0x1 +phy_chain_rx_polarity_flip_physical{229.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x1 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 +phy_chain_rx_polarity_flip_physical{233.0}=0x1 +phy_chain_rx_polarity_flip_physical{234.0}=0x0 +phy_chain_rx_polarity_flip_physical{235.0}=0x0 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 +phy_chain_rx_polarity_flip_physical{241.0}=0x1 +phy_chain_rx_polarity_flip_physical{242.0}=0x0 +phy_chain_rx_polarity_flip_physical{243.0}=0x1 +phy_chain_rx_polarity_flip_physical{244.0}=0x0 +phy_chain_rx_polarity_flip_physical{245.0}=0x1 +phy_chain_rx_polarity_flip_physical{246.0}=0x1 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x0 +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{250.0}=0x1 +phy_chain_rx_polarity_flip_physical{251.0}=0x0 +phy_chain_rx_polarity_flip_physical{252.0}=0x1 +phy_chain_rx_polarity_flip_physical{253.0}=0x1 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x1 +phy_chain_rx_polarity_flip_physical{256.0}=0x0 +phy_chain_rx_polarity_flip_physical{257.0}=0x0 +phy_chain_rx_polarity_flip_physical{259.0}=0x0 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +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}=0x1 +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{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +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{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 +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{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.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}=0x0 +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{8.0}=0x1 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x1 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 +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}=0x0 +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}=0x2031 +phy_chain_tx_lane_map_physical{101.0}=0x1023 +phy_chain_tx_lane_map_physical{105.0}=0x1302 +phy_chain_tx_lane_map_physical{109.0}=0x0321 +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_tx_lane_map_physical{117.0}=0x3120 +phy_chain_tx_lane_map_physical{121.0}=0x3102 +phy_chain_tx_lane_map_physical{125.0}=0x3210 +phy_chain_tx_lane_map_physical{129.0}=0x1023 +phy_chain_tx_lane_map_physical{13.0}=0x3021 +phy_chain_tx_lane_map_physical{133.0}=0x3210 +phy_chain_tx_lane_map_physical{137.0}=0x2031 +phy_chain_tx_lane_map_physical{141.0}=0x1302 +phy_chain_tx_lane_map_physical{145.0}=0x3210 +phy_chain_tx_lane_map_physical{149.0}=0x0213 +phy_chain_tx_lane_map_physical{153.0}=0x3210 +phy_chain_tx_lane_map_physical{157.0}=0x1320 +phy_chain_tx_lane_map_physical{161.0}=0x3210 +phy_chain_tx_lane_map_physical{165.0}=0x0231 +phy_chain_tx_lane_map_physical{169.0}=0x3120 +phy_chain_tx_lane_map_physical{17.0}=0x1032 +phy_chain_tx_lane_map_physical{173.0}=0x0312 +phy_chain_tx_lane_map_physical{177.0}=0x0231 +phy_chain_tx_lane_map_physical{181.0}=0x3210 +phy_chain_tx_lane_map_physical{185.0}=0x3210 +phy_chain_tx_lane_map_physical{189.0}=0x1320 +phy_chain_tx_lane_map_physical{193.0}=0x0321 +phy_chain_tx_lane_map_physical{197.0}=0x3120 +phy_chain_tx_lane_map_physical{201.0}=0x3120 +phy_chain_tx_lane_map_physical{205.0}=0x0123 +phy_chain_tx_lane_map_physical{209.0}=0x3120 +phy_chain_tx_lane_map_physical{21.0}=0x0213 +phy_chain_tx_lane_map_physical{213.0}=0x3021 +phy_chain_tx_lane_map_physical{217.0}=0x0312 +phy_chain_tx_lane_map_physical{221.0}=0x2301 +phy_chain_tx_lane_map_physical{225.0}=0x0123 +phy_chain_tx_lane_map_physical{229.0}=0x2031 +phy_chain_tx_lane_map_physical{233.0}=0x0231 +phy_chain_tx_lane_map_physical{237.0}=0x0213 +phy_chain_tx_lane_map_physical{241.0}=0x1320 +phy_chain_tx_lane_map_physical{245.0}=0x2031 +phy_chain_tx_lane_map_physical{249.0}=0x3120 +phy_chain_tx_lane_map_physical{25.0}=0x0231 +phy_chain_tx_lane_map_physical{253.0}=0x0321 +phy_chain_tx_lane_map_physical{257.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x1230 +phy_chain_tx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{37.0}=0x0123 +phy_chain_tx_lane_map_physical{41.0}=0x0213 +phy_chain_tx_lane_map_physical{45.0}=0x0132 +phy_chain_tx_lane_map_physical{49.0}=0x2031 +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_tx_lane_map_physical{53.0}=0x2301 +phy_chain_tx_lane_map_physical{57.0}=0x2031 +phy_chain_tx_lane_map_physical{61.0}=0x2031 +phy_chain_tx_lane_map_physical{65.0}=0x1230 +phy_chain_tx_lane_map_physical{69.0}=0x2013 +phy_chain_tx_lane_map_physical{73.0}=0x0213 +phy_chain_tx_lane_map_physical{77.0}=0x2310 +phy_chain_tx_lane_map_physical{81.0}=0x0321 +phy_chain_tx_lane_map_physical{85.0}=0x2013 +phy_chain_tx_lane_map_physical{89.0}=0x0213 +phy_chain_tx_lane_map_physical{9.0}=0x3012 +phy_chain_tx_lane_map_physical{93.0}=0x3102 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{104.0}=0x0 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 +phy_chain_tx_polarity_flip_physical{109.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x0 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x1 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x1 +phy_chain_tx_polarity_flip_physical{134.0}=0x1 +phy_chain_tx_polarity_flip_physical{135.0}=0x1 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x1 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x1 +phy_chain_tx_polarity_flip_physical{141.0}=0x0 +phy_chain_tx_polarity_flip_physical{142.0}=0x1 +phy_chain_tx_polarity_flip_physical{143.0}=0x1 +phy_chain_tx_polarity_flip_physical{144.0}=0x1 +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x1 +phy_chain_tx_polarity_flip_physical{147.0}=0x1 +phy_chain_tx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{153.0}=0x1 +phy_chain_tx_polarity_flip_physical{154.0}=0x0 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x1 +phy_chain_tx_polarity_flip_physical{163.0}=0x1 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x1 +phy_chain_tx_polarity_flip_physical{167.0}=0x1 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x0 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x1 +phy_chain_tx_polarity_flip_physical{171.0}=0x1 +phy_chain_tx_polarity_flip_physical{172.0}=0x1 +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x0 +phy_chain_tx_polarity_flip_physical{175.0}=0x1 +phy_chain_tx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{177.0}=0x1 +phy_chain_tx_polarity_flip_physical{178.0}=0x0 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x1 +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x1 +phy_chain_tx_polarity_flip_physical{187.0}=0x1 +phy_chain_tx_polarity_flip_physical{188.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x0 +phy_chain_tx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x0 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 +phy_chain_tx_polarity_flip_physical{193.0}=0x1 +phy_chain_tx_polarity_flip_physical{194.0}=0x1 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x0 +phy_chain_tx_polarity_flip_physical{198.0}=0x1 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x1 +phy_chain_tx_polarity_flip_physical{201.0}=0x1 +phy_chain_tx_polarity_flip_physical{202.0}=0x1 +phy_chain_tx_polarity_flip_physical{203.0}=0x1 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x1 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x1 +phy_chain_tx_polarity_flip_physical{209.0}=0x1 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x1 +phy_chain_tx_polarity_flip_physical{211.0}=0x1 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x1 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x1 +phy_chain_tx_polarity_flip_physical{217.0}=0x1 +phy_chain_tx_polarity_flip_physical{218.0}=0x1 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x1 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x0 +phy_chain_tx_polarity_flip_physical{223.0}=0x0 +phy_chain_tx_polarity_flip_physical{224.0}=0x1 +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x1 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x1 +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x0 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 +phy_chain_tx_polarity_flip_physical{241.0}=0x1 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x1 +phy_chain_tx_polarity_flip_physical{247.0}=0x1 +phy_chain_tx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x0 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 +phy_chain_tx_polarity_flip_physical{253.0}=0x1 +phy_chain_tx_polarity_flip_physical{254.0}=0x1 +phy_chain_tx_polarity_flip_physical{255.0}=0x1 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 +phy_chain_tx_polarity_flip_physical{257.0}=0x0 +phy_chain_tx_polarity_flip_physical{259.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{45.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 +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{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 +phy_chain_tx_polarity_flip_physical{61.0}=0x0 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +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}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 +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{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x0 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x0 +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x1 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +port_init_autoneg_100=0 +port_init_autoneg_102=0 +port_init_autoneg_103=0 +port_init_autoneg_104=0 +port_init_autoneg_105=0 +port_init_autoneg_106=0 +port_init_autoneg_107=0 +port_init_autoneg_108=0 +port_init_autoneg_109=0 +port_init_autoneg_10=0 +port_init_autoneg_110=0 +port_init_autoneg_111=0 +port_init_autoneg_112=0 +port_init_autoneg_113=0 +port_init_autoneg_114=0 +port_init_autoneg_115=0 +port_init_autoneg_116=0 +port_init_autoneg_117=0 +port_init_autoneg_11=0 +port_init_autoneg_12=0 +port_init_autoneg_13=0 +port_init_autoneg_14=0 +port_init_autoneg_15=0 +port_init_autoneg_16=0 +port_init_autoneg_1=0 +port_init_autoneg_2=0 +port_init_autoneg_34=0 +port_init_autoneg_35=0 +port_init_autoneg_36=0 +port_init_autoneg_37=0 +port_init_autoneg_38=0 +port_init_autoneg_39=0 +port_init_autoneg_3=0 +port_init_autoneg_40=0 +port_init_autoneg_41=0 +port_init_autoneg_42=0 +port_init_autoneg_43=0 +port_init_autoneg_44=0 +port_init_autoneg_45=0 +port_init_autoneg_46=0 +port_init_autoneg_47=0 +port_init_autoneg_48=0 +port_init_autoneg_49=0 +port_init_autoneg_4=0 +port_init_autoneg_5=0 +port_init_autoneg_66=0 +port_init_autoneg_68=0 +port_init_autoneg_69=0 +port_init_autoneg_6=0 +port_init_autoneg_70=0 +port_init_autoneg_71=0 +port_init_autoneg_72=0 +port_init_autoneg_73=0 +port_init_autoneg_74=0 +port_init_autoneg_75=0 +port_init_autoneg_76=0 +port_init_autoneg_77=0 +port_init_autoneg_78=0 +port_init_autoneg_79=0 +port_init_autoneg_7=0 +port_init_autoneg_80=0 +port_init_autoneg_81=0 +port_init_autoneg_82=0 +port_init_autoneg_83=0 +port_init_autoneg_8=0 +port_init_autoneg_9=0 +port_init_cl72_hg=1 +port_phy_addr_100=0xff +port_phy_addr_102=0xff +port_phy_addr_103=0xff +port_phy_addr_104=0xff +port_phy_addr_105=0xff +port_phy_addr_106=0xff +port_phy_addr_107=0xff +port_phy_addr_108=0xff +port_phy_addr_109=0xff +port_phy_addr_10=0xff +port_phy_addr_110=0xff +port_phy_addr_111=0xff +port_phy_addr_112=0xff +port_phy_addr_113=0xff +port_phy_addr_114=0xff +port_phy_addr_115=0xff +port_phy_addr_116=0xff +port_phy_addr_117=0xff +port_phy_addr_11=0xff +port_phy_addr_12=0xff +port_phy_addr_13=0xff +port_phy_addr_14=0xff +port_phy_addr_15=0xff +port_phy_addr_16=0xff +port_phy_addr_1=0xff +port_phy_addr_2=0xff +port_phy_addr_34=0xff +port_phy_addr_35=0xff +port_phy_addr_36=0xff +port_phy_addr_37=0xff +port_phy_addr_38=0xff +port_phy_addr_39=0xff +port_phy_addr_3=0xff +port_phy_addr_40=0xff +port_phy_addr_41=0xff +port_phy_addr_42=0xff +port_phy_addr_43=0xff +port_phy_addr_44=0xff +port_phy_addr_45=0xff +port_phy_addr_46=0xff +port_phy_addr_47=0xff +port_phy_addr_48=0xff +port_phy_addr_49=0xff +port_phy_addr_4=0xff +port_phy_addr_5=0xff +port_phy_addr_66=0xff +port_phy_addr_68=0xff +port_phy_addr_69=0xff +port_phy_addr_6=0xff +port_phy_addr_70=0xff +port_phy_addr_71=0xff +port_phy_addr_72=0xff +port_phy_addr_73=0xff +port_phy_addr_74=0xff +port_phy_addr_75=0xff +port_phy_addr_76=0xff +port_phy_addr_77=0xff +port_phy_addr_78=0xff +port_phy_addr_79=0xff +port_phy_addr_7=0xff +port_phy_addr_80=0xff +port_phy_addr_81=0xff +port_phy_addr_82=0xff +port_phy_addr_83=0xff +port_phy_addr_8=0xff +port_phy_addr_9=0xff +portmap_100=259:10 +portmap_101=262:10 +portmap_102=217:100 +portmap_103=213:100 +portmap_104=229:100 +portmap_105=237:100 +portmap_106=249:100 +portmap_107=245:100 +portmap_108=209:100 +portmap_109=221:100 +portmap_10=29:100 +portmap_110=233:100 +portmap_111=225:100 +portmap_112=241:100 +portmap_113=253:100 +portmap_114=197:100 +portmap_115=205:100 +portmap_116=201:100 +portmap_117=193:100 +portmap_11=41:100 +portmap_12=33:100 +portmap_134=263:10 +portmap_13=57:100 +portmap_14=53:100 +portmap_15=49:100 +portmap_16=61:100 +portmap_1=5:100 +portmap_2=13:100 +portmap_33=260:10 +portmap_34=77:100 +portmap_35=65:100 +portmap_36=85:100 +portmap_37=89:100 +portmap_38=109:100 +portmap_39=97:100 +portmap_3=25:100 +portmap_40=69:100 +portmap_41=73:100 +portmap_42=93:100 +portmap_43=81:100 +portmap_44=101:100 +portmap_45=105:100 +portmap_46=117:100 +portmap_47=121:100 +portmap_48=125:100 +portmap_49=113:100 +portmap_4=21:100 +portmap_5=37:100 +portmap_66=257:10 +portmap_67=261:10 +portmap_68=149:100 +portmap_69=153:100 +portmap_6=45:100 +portmap_70=173:100 +portmap_71=161:100 +portmap_72=181:100 +portmap_73=185:100 +portmap_74=157:100 +portmap_75=145:100 +portmap_76=165:100 +portmap_77=169:100 +portmap_78=189:100 +portmap_79=177:100 +portmap_7=9:100 +portmap_80=141:100 +portmap_81=133:100 +portmap_82=129:100 +portmap_83=137:100 +portmap_8=1:100 +portmap_9=17:100 +robust_hash_disable_egress_vlan=1 +robust_hash_disable_mpls=1 +robust_hash_disable_vlan=1 +stable_size=0x5500000 +stable_size=0x5500000 +tdma_timeout_usec=15000000 +tslam_timeout_usec=15000000 + +# tuning parameters +serdes_preemphasis_1=0x184606 +serdes_preemphasis_2=0x164108 +serdes_preemphasis_3=0x164308 +serdes_preemphasis_4=0x144108 +serdes_preemphasis_5=0x144108 +serdes_preemphasis_6=0x164106 +serdes_preemphasis_7=0x184507 +serdes_preemphasis_8=0x184606 +serdes_preemphasis_9=0x184507 +serdes_preemphasis_10=0x194407 +serdes_preemphasis_11=0x194407 +serdes_preemphasis_12=0x184507 +serdes_preemphasis_13=0x144108 +serdes_preemphasis_14=0x144108 +serdes_preemphasis_15=0x194407 +serdes_preemphasis_16=0x194407 +serdes_preemphasis_34=0x184408 +serdes_preemphasis_35=0x184606 +serdes_preemphasis_36=0x164308 +serdes_preemphasis_37=0x184606 +serdes_preemphasis_38=0x164108 +serdes_preemphasis_39=0x184606 +serdes_preemphasis_40=0xe3206 +serdes_preemphasis_41=0xe3205 +serdes_preemphasis_42=0x103a06 +serdes_preemphasis_43=0xe3205 +serdes_preemphasis_44=0x184606 +serdes_preemphasis_45=0x184507 +serdes_preemphasis_46=0x144108 +serdes_preemphasis_47=0x103a07 +serdes_preemphasis_48=0x194407 +serdes_preemphasis_49=0x194407 +serdes_preemphasis_66=0x43004 +serdes_preemphasis_68=0x164308 +serdes_preemphasis_69=0x164408 +serdes_preemphasis_70=0xe3206 +serdes_preemphasis_71=0xe3205 +serdes_preemphasis_72=0xe3205 +serdes_preemphasis_73=0xe3206 +serdes_preemphasis_74=0x164108 +serdes_preemphasis_75=0x184606 +serdes_preemphasis_76=0x164608 +serdes_preemphasis_77=0x184507 +serdes_preemphasis_78=0x184507 +serdes_preemphasis_79=0x184606 +serdes_preemphasis_80=0x184606 +serdes_preemphasis_81=0x184407 +serdes_preemphasis_82=0x103706 +serdes_preemphasis_83=0x103706 +serdes_preemphasis_100=0x43004 +serdes_preemphasis_102=0x184408 +serdes_preemphasis_103=0x184606 +serdes_preemphasis_104=0x184606 +serdes_preemphasis_105=0x16410a +serdes_preemphasis_106=0x184408 +serdes_preemphasis_107=0x194308 +serdes_preemphasis_108=0x144108 +serdes_preemphasis_109=0x144108 +serdes_preemphasis_110=0x144108 +serdes_preemphasis_111=0x144108 +serdes_preemphasis_112=0x164608 +serdes_preemphasis_113=0x164608 +serdes_preemphasis_114=0x174507 +serdes_preemphasis_115=0x184606 +serdes_preemphasis_116=0x103706 +serdes_preemphasis_117=0x133c06 diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/buffers.json.j2 b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/buffers.json.j2 new file mode 100644 index 000000000000..e6e9e844469b --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..74579a022dcb --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/buffers_defaults_t0.j2 @@ -0,0 +1,54 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,12) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(20,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(12,20) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "33329088", + "type": "ingress", + "mode": "dynamic", + "xoff": "7827456" + }, + "egress_lossy_pool": { + "size": "26663272", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "42349632", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"44302336" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"42349632" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1664", + "dynamic_th":"-1" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/pg_profile_lookup.ini b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/pg_profile_lookup.ini new file mode 100644 index 000000000000..ed0005610b71 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/pg_profile_lookup.ini @@ -0,0 +1,8 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 50000 5m 1248 1248 56160 -3 2496 + 100000 5m 1248 1248 96928 -3 2496 + 50000 40m 1248 1248 96096 -3 2496 + 100000 40m 1248 1248 177632 -3 2496 + 50000 300m 1248 1248 141856 -3 2496 + 100000 300m 1248 1248 268736 -3 2496 diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/port_config.ini b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/port_config.ini new file mode 100644 index 000000000000..c06fdd581ec4 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/port_config.ini @@ -0,0 +1,123 @@ +# name lanes alias index speed +Ethernet0 77,78 Ethernet1/1 1 50000 +Ethernet2 79,80 Ethernet1/3 1 50000 +Ethernet4 65,66 Ethernet2/1 2 50000 +Ethernet6 67,68 Ethernet2/3 2 50000 +Ethernet8 85,86 Ethernet3/1 3 50000 +Ethernet10 87,88 Ethernet3/3 3 50000 +Ethernet12 89,90 Ethernet4/1 4 50000 +Ethernet14 91,92 Ethernet4/3 4 50000 +Ethernet16 109,110 Ethernet5/1 5 50000 +Ethernet18 111,112 Ethernet5/3 5 50000 +Ethernet20 97,98 Ethernet6/1 6 50000 +Ethernet22 99,100 Ethernet6/3 6 50000 +Ethernet24 5,6 Ethernet7/1 7 50000 +Ethernet26 7,8 Ethernet7/3 7 50000 +Ethernet28 13,14 Ethernet8/1 8 50000 +Ethernet30 15,16 Ethernet8/3 8 50000 +Ethernet32 25,26 Ethernet9/1 9 50000 +Ethernet34 27,28 Ethernet9/3 9 50000 +Ethernet36 21,22 Ethernet10/1 10 50000 +Ethernet38 23,24 Ethernet10/3 10 50000 +Ethernet40 37,38 Ethernet11/1 11 50000 +Ethernet42 39,40 Ethernet11/3 11 50000 +Ethernet44 45,46 Ethernet12/1 12 50000 +Ethernet46 47,48 Ethernet12/3 12 50000 +Ethernet48 57,58,59,60 Ethernet13/1 13 100000 +Ethernet52 53,54,55,56 Ethernet14/1 14 100000 +Ethernet56 117,118,119,120 Ethernet15/1 15 100000 +Ethernet60 121,122,123,124 Ethernet16/1 16 100000 +Ethernet64 141,142,143,144 Ethernet17/1 17 100000 +Ethernet68 133,134,135,136 Ethernet18/1 18 100000 +Ethernet72 197,198,199,200 Ethernet19/1 19 100000 +Ethernet76 205,206,207,208 Ethernet20/1 20 100000 +Ethernet80 217,218 Ethernet21/1 21 50000 +Ethernet82 219,220 Ethernet21/3 21 50000 +Ethernet84 213,214 Ethernet22/1 22 50000 +Ethernet86 215,216 Ethernet22/3 22 50000 +Ethernet88 229,230 Ethernet23/1 23 50000 +Ethernet90 231,232 Ethernet23/3 23 50000 +Ethernet92 237,238 Ethernet24/1 24 50000 +Ethernet94 239,240 Ethernet24/3 24 50000 +Ethernet96 249,250 Ethernet25/1 25 50000 +Ethernet98 251,252 Ethernet25/3 25 50000 +Ethernet100 245,246 Ethernet26/1 26 50000 +Ethernet102 247,248 Ethernet26/3 26 50000 +Ethernet104 149,150 Ethernet27/1 27 50000 +Ethernet106 151,152 Ethernet27/3 27 50000 +Ethernet108 153,154 Ethernet28/1 28 50000 +Ethernet110 155,156 Ethernet28/3 28 50000 +Ethernet112 173,174 Ethernet29/1 29 50000 +Ethernet114 175,176 Ethernet29/3 29 50000 +Ethernet116 161,162 Ethernet30/1 30 50000 +Ethernet118 163,164 Ethernet30/3 30 50000 +Ethernet120 181,182 Ethernet31/1 31 50000 +Ethernet122 183,184 Ethernet31/3 31 50000 +Ethernet124 185,186 Ethernet32/1 32 50000 +Ethernet126 187,188 Ethernet32/3 32 50000 +Ethernet128 69,70 Ethernet33/1 33 50000 +Ethernet130 71,72 Ethernet33/3 33 50000 +Ethernet132 73,74 Ethernet34/1 34 50000 +Ethernet134 75,76 Ethernet34/3 34 50000 +Ethernet136 93,94 Ethernet35/1 35 50000 +Ethernet138 95,96 Ethernet35/3 35 50000 +Ethernet140 81,82 Ethernet36/1 36 50000 +Ethernet142 83,84 Ethernet36/3 36 50000 +Ethernet144 101,102 Ethernet37/1 37 50000 +Ethernet146 103,104 Ethernet37/3 37 50000 +Ethernet148 105,106 Ethernet38/1 38 50000 +Ethernet150 107,108 Ethernet38/3 38 50000 +Ethernet152 9,10 Ethernet39/1 39 50000 +Ethernet154 11,12 Ethernet39/3 39 50000 +Ethernet156 1,2 Ethernet40/1 40 50000 +Ethernet158 3,4 Ethernet40/3 40 50000 +Ethernet160 17,18 Ethernet41/1 41 50000 +Ethernet162 19,20 Ethernet41/3 41 50000 +Ethernet164 29,30 Ethernet42/1 42 50000 +Ethernet166 31,32 Ethernet42/3 42 50000 +Ethernet168 41,42 Ethernet43/1 43 50000 +Ethernet170 43,44 Ethernet43/3 43 50000 +Ethernet172 33,34 Ethernet44/1 44 50000 +Ethernet174 35,36 Ethernet44/3 44 50000 +Ethernet176 49,50 Ethernet45/1 45 50000 +Ethernet178 51,52 Ethernet45/3 45 50000 +Ethernet180 61,62 Ethernet46/1 46 50000 +Ethernet182 63,64 Ethernet46/3 46 50000 +Ethernet184 125,126 Ethernet47/1 47 50000 +Ethernet186 127,128 Ethernet47/3 47 50000 +Ethernet188 113,114 Ethernet48/1 48 50000 +Ethernet190 115,116 Ethernet48/3 48 50000 +Ethernet192 129,130 Ethernet49/1 49 50000 +Ethernet194 131,132 Ethernet49/3 49 50000 +Ethernet196 137,138 Ethernet50/1 50 50000 +Ethernet198 139,140 Ethernet50/3 50 50000 +Ethernet200 201,202 Ethernet51/1 51 50000 +Ethernet202 203,204 Ethernet51/3 51 50000 +Ethernet204 193,194 Ethernet52/1 52 50000 +Ethernet206 195,196 Ethernet52/3 52 50000 +Ethernet208 209,210 Ethernet53/1 53 50000 +Ethernet210 211,212 Ethernet53/3 53 50000 +Ethernet212 221,222 Ethernet54/1 54 50000 +Ethernet214 223,224 Ethernet54/3 54 50000 +Ethernet216 233,234 Ethernet55/1 55 50000 +Ethernet218 235,236 Ethernet55/3 55 50000 +Ethernet220 225,226 Ethernet56/1 56 50000 +Ethernet222 227,228 Ethernet56/3 56 50000 +Ethernet224 241,242 Ethernet57/1 57 50000 +Ethernet226 243,244 Ethernet57/3 57 50000 +Ethernet228 253,254 Ethernet58/1 58 50000 +Ethernet230 255,256 Ethernet58/3 58 50000 +Ethernet232 157,158 Ethernet59/1 59 50000 +Ethernet234 159,160 Ethernet59/3 59 50000 +Ethernet236 145,146 Ethernet60/1 60 50000 +Ethernet238 147,148 Ethernet60/3 60 50000 +Ethernet240 165,166 Ethernet61/1 61 50000 +Ethernet242 167,168 Ethernet61/3 61 50000 +Ethernet244 169,170 Ethernet62/1 62 50000 +Ethernet246 171,172 Ethernet62/3 62 50000 +Ethernet248 189,190 Ethernet63/1 63 50000 +Ethernet250 191,192 Ethernet63/3 63 50000 +Ethernet252 177,178 Ethernet64/1 64 50000 +Ethernet254 179,180 Ethernet64/3 64 50000 +Ethernet256 257 Ethernet65 65 10000 +Ethernet260 259 Ethernet66 66 10000 diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/qos.json.j2 b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/sai.profile b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/sai.profile new file mode 100644 index 000000000000..166f5c5b6e1a --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-a7260cx3-64-112x50G+8x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/th2-a7260cx3-64-112x50G+8x100G.config.bcm b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/th2-a7260cx3-64-112x50G+8x100G.config.bcm new file mode 100644 index 000000000000..6e4c266b1db4 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-D108C8/th2-a7260cx3-64-112x50G+8x100G.config.bcm @@ -0,0 +1,936 @@ +PHY_AN_ALLOW_PLL_CHANGE=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +core_clock_frequency=1700 +dma_desc_timeout_usec=15000000 +dpp_clock_ratio=2:3 +higig2_hdr_mode=1 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +l2xmsg_mode=1 +max_vp_lags=0 +mem_scan_enable=1 +miim_intr_enable=0 +module_64ports=1 +os=unix +oversubscribe_mode=1 +pbmp_xport_xe=0xfffffffd3fffffff4fffffffc7ffffffe +#pbmp_xport_xe=0x47fffffff1fffffffcfffffffe7ffffffe +phy_an_allow_pll_change_hg=0 +phy_an_c73=1 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_rx_lane_map_physical{101.0}=0x0123 +phy_chain_rx_lane_map_physical{105.0}=0x0123 +phy_chain_rx_lane_map_physical{109.0}=0x0123 +phy_chain_rx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_rx_lane_map_physical{121.0}=0x3210 +phy_chain_rx_lane_map_physical{125.0}=0x1203 +phy_chain_rx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{13.0}=0x0321 +phy_chain_rx_lane_map_physical{133.0}=0x1032 +phy_chain_rx_lane_map_physical{137.0}=0x3210 +phy_chain_rx_lane_map_physical{141.0}=0x0123 +phy_chain_rx_lane_map_physical{145.0}=0x3210 +phy_chain_rx_lane_map_physical{149.0}=0x2310 +phy_chain_rx_lane_map_physical{153.0}=0x0132 +phy_chain_rx_lane_map_physical{157.0}=0x1302 +phy_chain_rx_lane_map_physical{161.0}=0x3021 +phy_chain_rx_lane_map_physical{165.0}=0x2031 +phy_chain_rx_lane_map_physical{169.0}=0x2031 +phy_chain_rx_lane_map_physical{17.0}=0x3210 +phy_chain_rx_lane_map_physical{173.0}=0x1302 +phy_chain_rx_lane_map_physical{177.0}=0x2031 +phy_chain_rx_lane_map_physical{181.0}=0x0213 +phy_chain_rx_lane_map_physical{185.0}=0x0213 +phy_chain_rx_lane_map_physical{189.0}=0x1302 +phy_chain_rx_lane_map_physical{193.0}=0x3120 +phy_chain_rx_lane_map_physical{197.0}=0x0231 +phy_chain_rx_lane_map_physical{201.0}=0x2031 +phy_chain_rx_lane_map_physical{205.0}=0x0213 +phy_chain_rx_lane_map_physical{209.0}=0x2013 +phy_chain_rx_lane_map_physical{21.0}=0x3021 +phy_chain_rx_lane_map_physical{213.0}=0x3021 +phy_chain_rx_lane_map_physical{217.0}=0x0231 +phy_chain_rx_lane_map_physical{221.0}=0x2031 +phy_chain_rx_lane_map_physical{225.0}=0x1203 +phy_chain_rx_lane_map_physical{229.0}=0x1230 +phy_chain_rx_lane_map_physical{233.0}=0x3021 +phy_chain_rx_lane_map_physical{237.0}=0x1032 +phy_chain_rx_lane_map_physical{241.0}=0x2301 +phy_chain_rx_lane_map_physical{245.0}=0x0321 +phy_chain_rx_lane_map_physical{249.0}=0x2301 +phy_chain_rx_lane_map_physical{25.0}=0x2301 +phy_chain_rx_lane_map_physical{253.0}=0x2301 +phy_chain_rx_lane_map_physical{257.0}=0x3210 +phy_chain_rx_lane_map_physical{29.0}=0x3021 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 +phy_chain_rx_lane_map_physical{41.0}=0x3021 +phy_chain_rx_lane_map_physical{45.0}=0x1023 +phy_chain_rx_lane_map_physical{49.0}=0x0213 +phy_chain_rx_lane_map_physical{5.0}=0x3201 +phy_chain_rx_lane_map_physical{53.0}=0x3201 +phy_chain_rx_lane_map_physical{57.0}=0x2013 +phy_chain_rx_lane_map_physical{61.0}=0x0213 +phy_chain_rx_lane_map_physical{65.0}=0x1203 +phy_chain_rx_lane_map_physical{69.0}=0x0213 +phy_chain_rx_lane_map_physical{73.0}=0x0213 +phy_chain_rx_lane_map_physical{77.0}=0x3120 +phy_chain_rx_lane_map_physical{81.0}=0x0213 +phy_chain_rx_lane_map_physical{85.0}=0x2031 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_rx_lane_map_physical{9.0}=0x0321 +phy_chain_rx_lane_map_physical{93.0}=0x3120 +phy_chain_rx_lane_map_physical{97.0}=0x1203 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +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{11.0}=0x1 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +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{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +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}=0x1 +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{130.0}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{133.0}=0x1 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_rx_polarity_flip_physical{141.0}=0x1 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x0 +phy_chain_rx_polarity_flip_physical{147.0}=0x1 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x1 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x1 +phy_chain_rx_polarity_flip_physical{156.0}=0x0 +phy_chain_rx_polarity_flip_physical{157.0}=0x0 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x1 +phy_chain_rx_polarity_flip_physical{169.0}=0x1 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x0 +phy_chain_rx_polarity_flip_physical{175.0}=0x1 +phy_chain_rx_polarity_flip_physical{176.0}=0x1 +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x1 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{18.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x0 +phy_chain_rx_polarity_flip_physical{181.0}=0x1 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_rx_polarity_flip_physical{185.0}=0x0 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x1 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_rx_polarity_flip_physical{190.0}=0x0 +phy_chain_rx_polarity_flip_physical{191.0}=0x1 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x1 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x0 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x0 +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x0 +phy_chain_rx_polarity_flip_physical{215.0}=0x1 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 +phy_chain_rx_polarity_flip_physical{217.0}=0x0 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 +phy_chain_rx_polarity_flip_physical{221.0}=0x0 +phy_chain_rx_polarity_flip_physical{222.0}=0x0 +phy_chain_rx_polarity_flip_physical{223.0}=0x1 +phy_chain_rx_polarity_flip_physical{224.0}=0x1 +phy_chain_rx_polarity_flip_physical{225.0}=0x1 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x0 +phy_chain_rx_polarity_flip_physical{228.0}=0x1 +phy_chain_rx_polarity_flip_physical{229.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x1 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 +phy_chain_rx_polarity_flip_physical{233.0}=0x1 +phy_chain_rx_polarity_flip_physical{234.0}=0x0 +phy_chain_rx_polarity_flip_physical{235.0}=0x0 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 +phy_chain_rx_polarity_flip_physical{241.0}=0x1 +phy_chain_rx_polarity_flip_physical{242.0}=0x0 +phy_chain_rx_polarity_flip_physical{243.0}=0x1 +phy_chain_rx_polarity_flip_physical{244.0}=0x0 +phy_chain_rx_polarity_flip_physical{245.0}=0x1 +phy_chain_rx_polarity_flip_physical{246.0}=0x1 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x0 +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{250.0}=0x1 +phy_chain_rx_polarity_flip_physical{251.0}=0x0 +phy_chain_rx_polarity_flip_physical{252.0}=0x1 +phy_chain_rx_polarity_flip_physical{253.0}=0x1 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x1 +phy_chain_rx_polarity_flip_physical{256.0}=0x0 +phy_chain_rx_polarity_flip_physical{257.0}=0x0 +phy_chain_rx_polarity_flip_physical{259.0}=0x0 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +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}=0x1 +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{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +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{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 +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{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.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}=0x0 +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{8.0}=0x1 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x1 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 +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}=0x0 +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}=0x2031 +phy_chain_tx_lane_map_physical{101.0}=0x1023 +phy_chain_tx_lane_map_physical{105.0}=0x1302 +phy_chain_tx_lane_map_physical{109.0}=0x0321 +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_tx_lane_map_physical{117.0}=0x3120 +phy_chain_tx_lane_map_physical{121.0}=0x3102 +phy_chain_tx_lane_map_physical{125.0}=0x3210 +phy_chain_tx_lane_map_physical{129.0}=0x1023 +phy_chain_tx_lane_map_physical{13.0}=0x3021 +phy_chain_tx_lane_map_physical{133.0}=0x3210 +phy_chain_tx_lane_map_physical{137.0}=0x2031 +phy_chain_tx_lane_map_physical{141.0}=0x1302 +phy_chain_tx_lane_map_physical{145.0}=0x3210 +phy_chain_tx_lane_map_physical{149.0}=0x0213 +phy_chain_tx_lane_map_physical{153.0}=0x3210 +phy_chain_tx_lane_map_physical{157.0}=0x1320 +phy_chain_tx_lane_map_physical{161.0}=0x3210 +phy_chain_tx_lane_map_physical{165.0}=0x0231 +phy_chain_tx_lane_map_physical{169.0}=0x3120 +phy_chain_tx_lane_map_physical{17.0}=0x1032 +phy_chain_tx_lane_map_physical{173.0}=0x0312 +phy_chain_tx_lane_map_physical{177.0}=0x0231 +phy_chain_tx_lane_map_physical{181.0}=0x3210 +phy_chain_tx_lane_map_physical{185.0}=0x3210 +phy_chain_tx_lane_map_physical{189.0}=0x1320 +phy_chain_tx_lane_map_physical{193.0}=0x0321 +phy_chain_tx_lane_map_physical{197.0}=0x3120 +phy_chain_tx_lane_map_physical{201.0}=0x3120 +phy_chain_tx_lane_map_physical{205.0}=0x0123 +phy_chain_tx_lane_map_physical{209.0}=0x3120 +phy_chain_tx_lane_map_physical{21.0}=0x0213 +phy_chain_tx_lane_map_physical{213.0}=0x3021 +phy_chain_tx_lane_map_physical{217.0}=0x0312 +phy_chain_tx_lane_map_physical{221.0}=0x2301 +phy_chain_tx_lane_map_physical{225.0}=0x0123 +phy_chain_tx_lane_map_physical{229.0}=0x2031 +phy_chain_tx_lane_map_physical{233.0}=0x0231 +phy_chain_tx_lane_map_physical{237.0}=0x0213 +phy_chain_tx_lane_map_physical{241.0}=0x1320 +phy_chain_tx_lane_map_physical{245.0}=0x2031 +phy_chain_tx_lane_map_physical{249.0}=0x3120 +phy_chain_tx_lane_map_physical{25.0}=0x0231 +phy_chain_tx_lane_map_physical{253.0}=0x0321 +phy_chain_tx_lane_map_physical{257.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x1230 +phy_chain_tx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{37.0}=0x0123 +phy_chain_tx_lane_map_physical{41.0}=0x0213 +phy_chain_tx_lane_map_physical{45.0}=0x0132 +phy_chain_tx_lane_map_physical{49.0}=0x2031 +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_tx_lane_map_physical{53.0}=0x2301 +phy_chain_tx_lane_map_physical{57.0}=0x2031 +phy_chain_tx_lane_map_physical{61.0}=0x2031 +phy_chain_tx_lane_map_physical{65.0}=0x1230 +phy_chain_tx_lane_map_physical{69.0}=0x2013 +phy_chain_tx_lane_map_physical{73.0}=0x0213 +phy_chain_tx_lane_map_physical{77.0}=0x2310 +phy_chain_tx_lane_map_physical{81.0}=0x0321 +phy_chain_tx_lane_map_physical{85.0}=0x2013 +phy_chain_tx_lane_map_physical{89.0}=0x0213 +phy_chain_tx_lane_map_physical{9.0}=0x3012 +phy_chain_tx_lane_map_physical{93.0}=0x3102 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{104.0}=0x0 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 +phy_chain_tx_polarity_flip_physical{109.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x0 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x1 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x1 +phy_chain_tx_polarity_flip_physical{134.0}=0x1 +phy_chain_tx_polarity_flip_physical{135.0}=0x1 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x1 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x1 +phy_chain_tx_polarity_flip_physical{141.0}=0x0 +phy_chain_tx_polarity_flip_physical{142.0}=0x1 +phy_chain_tx_polarity_flip_physical{143.0}=0x1 +phy_chain_tx_polarity_flip_physical{144.0}=0x1 +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x1 +phy_chain_tx_polarity_flip_physical{147.0}=0x1 +phy_chain_tx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{153.0}=0x1 +phy_chain_tx_polarity_flip_physical{154.0}=0x0 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x1 +phy_chain_tx_polarity_flip_physical{163.0}=0x1 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x1 +phy_chain_tx_polarity_flip_physical{167.0}=0x1 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x0 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x1 +phy_chain_tx_polarity_flip_physical{171.0}=0x1 +phy_chain_tx_polarity_flip_physical{172.0}=0x1 +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x0 +phy_chain_tx_polarity_flip_physical{175.0}=0x1 +phy_chain_tx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{177.0}=0x1 +phy_chain_tx_polarity_flip_physical{178.0}=0x0 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x1 +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x1 +phy_chain_tx_polarity_flip_physical{187.0}=0x1 +phy_chain_tx_polarity_flip_physical{188.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x0 +phy_chain_tx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x0 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 +phy_chain_tx_polarity_flip_physical{193.0}=0x1 +phy_chain_tx_polarity_flip_physical{194.0}=0x1 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x0 +phy_chain_tx_polarity_flip_physical{198.0}=0x1 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x1 +phy_chain_tx_polarity_flip_physical{201.0}=0x1 +phy_chain_tx_polarity_flip_physical{202.0}=0x1 +phy_chain_tx_polarity_flip_physical{203.0}=0x1 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x1 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x1 +phy_chain_tx_polarity_flip_physical{209.0}=0x1 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x1 +phy_chain_tx_polarity_flip_physical{211.0}=0x1 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x1 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x1 +phy_chain_tx_polarity_flip_physical{217.0}=0x1 +phy_chain_tx_polarity_flip_physical{218.0}=0x1 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x1 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x0 +phy_chain_tx_polarity_flip_physical{223.0}=0x0 +phy_chain_tx_polarity_flip_physical{224.0}=0x1 +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x1 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x1 +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x0 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 +phy_chain_tx_polarity_flip_physical{241.0}=0x1 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x1 +phy_chain_tx_polarity_flip_physical{247.0}=0x1 +phy_chain_tx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x0 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 +phy_chain_tx_polarity_flip_physical{253.0}=0x1 +phy_chain_tx_polarity_flip_physical{254.0}=0x1 +phy_chain_tx_polarity_flip_physical{255.0}=0x1 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 +phy_chain_tx_polarity_flip_physical{257.0}=0x0 +phy_chain_tx_polarity_flip_physical{259.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{45.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 +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{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 +phy_chain_tx_polarity_flip_physical{61.0}=0x0 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +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}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 +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{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x0 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x0 +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x1 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 + +port_init_cl72_hg=1 + + + + + + + +robust_hash_disable_egress_vlan=1 +robust_hash_disable_mpls=1 +robust_hash_disable_vlan=1 +stable_size=0x5500000 +stable_size=0x5500000 +tdma_timeout_usec=15000000 +tslam_timeout_usec=15000000 +dport_map_direct=1 +portmap_1=5:50 +portmap_2=7:50 +portmap_3=13:50 +portmap_4=15:50 +portmap_5=25:50 +portmap_6=27:50 +portmap_7=21:50 +portmap_8=23:50 +portmap_9=37:50 +portmap_10=39:50 +portmap_11=45:50 +portmap_12=47:50 +portmap_13=57:100 +portmap_14=53:100 +portmap_15=9:50 +portmap_16=11:50 +portmap_17=1:50 +portmap_18=3:50 +portmap_19=17:50 +portmap_20=19:50 +portmap_21=29:50 +portmap_22=31:50 +portmap_23=41:50 +portmap_24=43:50 +portmap_25=33:50 +portmap_26=35:50 +portmap_27=49:50 +portmap_28=51:50 +portmap_29=61:50 +portmap_30=63:50 +portmap_34=77:50 +portmap_35=79:50 +portmap_36=65:50 +portmap_37=67:50 +portmap_38=85:50 +portmap_39=87:50 +portmap_40=89:50 +portmap_41=91:50 +portmap_42=109:50 +portmap_43=111:50 +portmap_44=97:50 +portmap_45=99:50 +portmap_46=117:100 +portmap_47=121:100 +portmap_48=69:50 +portmap_49=71:50 +portmap_50=73:50 +portmap_51=75:50 +portmap_52=93:50 +portmap_53=95:50 +portmap_54=81:50 +portmap_55=83:50 +portmap_56=101:50 +portmap_57=103:50 +portmap_58=105:50 +portmap_59=107:50 +portmap_60=125:50 +portmap_61=127:50 +portmap_62=113:50 +portmap_63=115:50 +portmap_66=257:10 +portmap_68=141:100 +portmap_69=133:100 +portmap_70=149:50 +portmap_71=151:50 +portmap_72=153:50 +portmap_73=155:50 +portmap_74=173:50 +portmap_75=175:50 +portmap_76=161:50 +portmap_77=163:50 +portmap_78=181:50 +portmap_79=183:50 +portmap_80=185:50 +portmap_81=187:50 +portmap_82=129:50 +portmap_83=131:50 +portmap_84=137:50 +portmap_85=139:50 +portmap_86=157:50 +portmap_87=159:50 +portmap_88=145:50 +portmap_89=147:50 +portmap_90=165:50 +portmap_91=167:50 +portmap_92=169:50 +portmap_93=171:50 +portmap_94=189:50 +portmap_95=191:50 +portmap_96=177:50 +portmap_97=179:50 +portmap_100=259:10 +portmap_102=197:100 +portmap_103=205:100 +portmap_104=217:50 +portmap_105=219:50 +portmap_106=213:50 +portmap_107=215:50 +portmap_108=229:50 +portmap_109=231:50 +portmap_110=237:50 +portmap_111=239:50 +portmap_112=249:50 +portmap_113=251:50 +portmap_114=245:50 +portmap_115=247:50 +portmap_116=201:50 +portmap_117=203:50 +portmap_118=193:50 +portmap_119=195:50 +portmap_120=209:50 +portmap_121=211:50 +portmap_122=221:50 +portmap_123=223:50 +portmap_124=233:50 +portmap_125=235:50 +portmap_126=225:50 +portmap_127=227:50 +portmap_128=241:50 +portmap_129=243:50 +portmap_130=253:50 +portmap_131=255:50 + +# tuning parameters +serdes_preemphasis_1=0x580c +serdes_preemphasis_2=0x580c +serdes_preemphasis_3=0x580c +serdes_preemphasis_4=0x580c +serdes_preemphasis_5=0x580c +serdes_preemphasis_6=0x580c +serdes_preemphasis_7=0x580c +serdes_preemphasis_8=0x580c +serdes_preemphasis_9=0x580c +serdes_preemphasis_10=0x580c +serdes_preemphasis_11=0x580c +serdes_preemphasis_12=0x580c +serdes_preemphasis_13=0x144108 +serdes_preemphasis_14=0x144108 +serdes_preemphasis_15=0x580c +serdes_preemphasis_16=0x580c +serdes_preemphasis_17=0x580c +serdes_preemphasis_18=0x580c +serdes_preemphasis_19=0x580c +serdes_preemphasis_20=0x580c +serdes_preemphasis_21=0x580c +serdes_preemphasis_22=0x580c +serdes_preemphasis_23=0x580c +serdes_preemphasis_24=0x580c +serdes_preemphasis_25=0x580c +serdes_preemphasis_26=0x580c +serdes_preemphasis_27=0x580c +serdes_preemphasis_28=0x580c +serdes_preemphasis_29=0x580c +serdes_preemphasis_30=0x580c +serdes_preemphasis_34=0x580c +serdes_preemphasis_35=0x580c +serdes_preemphasis_36=0x580c +serdes_preemphasis_37=0x580c +serdes_preemphasis_38=0x580c +serdes_preemphasis_39=0x580c +serdes_preemphasis_40=0x580c +serdes_preemphasis_41=0x580c +serdes_preemphasis_42=0x580c +serdes_preemphasis_43=0x580c +serdes_preemphasis_44=0x580c +serdes_preemphasis_45=0x580c +serdes_preemphasis_46=0x144108 +serdes_preemphasis_47=0x103a07 +serdes_preemphasis_48=0x580c +serdes_preemphasis_49=0x580c +serdes_preemphasis_50=0x580c +serdes_preemphasis_51=0x580c +serdes_preemphasis_52=0x580c +serdes_preemphasis_53=0x580c +serdes_preemphasis_54=0x580c +serdes_preemphasis_55=0x580c +serdes_preemphasis_56=0x580c +serdes_preemphasis_57=0x580c +serdes_preemphasis_58=0x580c +serdes_preemphasis_59=0x580c +serdes_preemphasis_60=0x580c +serdes_preemphasis_61=0x580c +serdes_preemphasis_62=0x580c +serdes_preemphasis_63=0x580c +serdes_preemphasis_66=0x43004 +serdes_preemphasis_68=0x184606 +serdes_preemphasis_69=0x184407 +serdes_preemphasis_70=0x580c +serdes_preemphasis_71=0x580c +serdes_preemphasis_72=0x580c +serdes_preemphasis_73=0x580c +serdes_preemphasis_74=0x580c +serdes_preemphasis_75=0x580c +serdes_preemphasis_76=0x580c +serdes_preemphasis_77=0x580c +serdes_preemphasis_78=0x580c +serdes_preemphasis_79=0x580c +serdes_preemphasis_80=0x580c +serdes_preemphasis_81=0x580c +serdes_preemphasis_82=0x580c +serdes_preemphasis_83=0x580c +serdes_preemphasis_84=0x580c +serdes_preemphasis_85=0x580c +serdes_preemphasis_86=0x580c +serdes_preemphasis_87=0x580c +serdes_preemphasis_88=0x580c +serdes_preemphasis_89=0x580c +serdes_preemphasis_90=0x580c +serdes_preemphasis_91=0x580c +serdes_preemphasis_92=0x580c +serdes_preemphasis_93=0x580c +serdes_preemphasis_94=0x580c +serdes_preemphasis_95=0x580c +serdes_preemphasis_96=0x580c +serdes_preemphasis_97=0x580c +serdes_preemphasis_100=0x43004 +serdes_preemphasis_102=0x174507 +serdes_preemphasis_103=0x184606 +serdes_preemphasis_104=0x580c +serdes_preemphasis_105=0x580c +serdes_preemphasis_106=0x580c +serdes_preemphasis_107=0x580c +serdes_preemphasis_108=0x580c +serdes_preemphasis_109=0x580c +serdes_preemphasis_110=0x580c +serdes_preemphasis_111=0x580c +serdes_preemphasis_112=0x580c +serdes_preemphasis_113=0x580c +serdes_preemphasis_114=0x580c +serdes_preemphasis_115=0x580c +serdes_preemphasis_116=0x580c +serdes_preemphasis_117=0x580c +serdes_preemphasis_118=0x580c +serdes_preemphasis_119=0x580c +serdes_preemphasis_120=0x580c +serdes_preemphasis_121=0x580c +serdes_preemphasis_122=0x580c +serdes_preemphasis_123=0x580c +serdes_preemphasis_124=0x580c +serdes_preemphasis_125=0x580c +serdes_preemphasis_126=0x580c +serdes_preemphasis_127=0x580c +serdes_preemphasis_128=0x580c +serdes_preemphasis_129=0x580c +serdes_preemphasis_130=0x580c +serdes_preemphasis_131=0x580c + +mmu_init_config="MSFT-TH2-Tier0" diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q44 b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q44 new file mode 120000 index 000000000000..a5c923950dc8 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q44 @@ -0,0 +1 @@ +Arista-7260CX3-Q64 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/buffers.json.j2 b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/buffers.json.j2 new file mode 100644 index 000000000000..e6e9e844469b --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/buffers_defaults_t0.j2 b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..3442612f70b2 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/buffers_defaults_t0.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "33329088", + "type": "ingress", + "mode": "dynamic", + "xoff": "7827456" + }, + "egress_lossy_pool": { + "size": "26663272", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "42349632", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"44302336" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"42349632" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1664", + "dynamic_th":"-1" + } + }, +{%- endmacro %} diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/pg_profile_lookup.ini b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/pg_profile_lookup.ini new file mode 100644 index 000000000000..ac33b4f961fb --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/pg_profile_lookup.ini @@ -0,0 +1,11 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 40000 5m 1248 1248 56160 -3 2496 + 50000 5m 1248 1248 56160 -3 2496 + 100000 5m 1248 1248 96928 -3 2496 + 40000 40m 1248 1248 71552 -3 2496 + 50000 40m 1248 1248 96096 -3 2496 + 100000 40m 1248 1248 177632 -3 2496 + 40000 300m 1248 1248 108160 -3 2496 + 50000 300m 1248 1248 141856 -3 2496 + 100000 300m 1248 1248 268736 -3 2496 diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/port_config.ini b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/port_config.ini new file mode 100644 index 000000000000..de49cb6971a3 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 77,78,79,80 Ethernet1/1 1 40000 +Ethernet4 65,66,67,68 Ethernet2/1 2 40000 +Ethernet8 85,86,87,88 Ethernet3/1 3 40000 +Ethernet12 89,90,91,92 Ethernet4/1 4 40000 +Ethernet16 109,110,111,112 Ethernet5/1 5 40000 +Ethernet20 97,98,99,100 Ethernet6/1 6 40000 +Ethernet24 5,6,7,8 Ethernet7/1 7 40000 +Ethernet28 13,14,15,16 Ethernet8/1 8 40000 +Ethernet32 25,26,27,28 Ethernet9/1 9 40000 +Ethernet36 21,22,23,24 Ethernet10/1 10 40000 +Ethernet40 37,38,39,40 Ethernet11/1 11 40000 +Ethernet44 45,46,47,48 Ethernet12/1 12 40000 +Ethernet48 57,58,59,60 Ethernet13/1 13 40000 +Ethernet52 53,54,55,56 Ethernet14/1 14 40000 +Ethernet56 117,118,119,120 Ethernet15/1 15 40000 +Ethernet60 121,122,123,124 Ethernet16/1 16 40000 +Ethernet64 141,142,143,144 Ethernet17/1 17 40000 +Ethernet68 133,134,135,136 Ethernet18/1 18 40000 +Ethernet72 197,198,199,200 Ethernet19/1 19 40000 +Ethernet76 205,206,207,208 Ethernet20/1 20 40000 +Ethernet80 217,218,219,220 Ethernet21/1 21 40000 +Ethernet84 213,214,215,216 Ethernet22/1 22 40000 +Ethernet88 229,230,231,232 Ethernet23/1 23 40000 +Ethernet92 237,238,239,240 Ethernet24/1 24 40000 +Ethernet96 249,250,251,252 Ethernet25/1 25 40000 +Ethernet100 245,246,247,248 Ethernet26/1 26 40000 +Ethernet104 149,150,151,152 Ethernet27/1 27 40000 +Ethernet108 153,154,155,156 Ethernet28/1 28 40000 +Ethernet112 173,174,175,176 Ethernet29/1 29 40000 +Ethernet116 161,162,163,164 Ethernet30/1 30 40000 +Ethernet120 181,182,183,184 Ethernet31/1 31 40000 +Ethernet124 185,186,187,188 Ethernet32/1 32 40000 +Ethernet128 69,70,71,72 Ethernet33/1 33 40000 +Ethernet132 73,74,75,76 Ethernet34/1 34 40000 +Ethernet136 93,94,95,96 Ethernet35/1 35 40000 +Ethernet140 81,82,83,84 Ethernet36/1 36 40000 +Ethernet144 101,102,103,104 Ethernet37/1 37 40000 +Ethernet148 105,106,107,108 Ethernet38/1 38 40000 +Ethernet152 9,10,11,12 Ethernet39/1 39 40000 +Ethernet156 1,2,3,4 Ethernet40/1 40 40000 +Ethernet160 17,18,19,20 Ethernet41/1 41 40000 +Ethernet164 29,30,31,32 Ethernet42/1 42 40000 +Ethernet168 41,42,43,44 Ethernet43/1 43 40000 +Ethernet172 33,34,35,36 Ethernet44/1 44 40000 +Ethernet176 49,50,51,52 Ethernet45/1 45 40000 +Ethernet180 61,62,63,64 Ethernet46/1 46 40000 +Ethernet184 125,126,127,128 Ethernet47/1 47 40000 +Ethernet188 113,114,115,116 Ethernet48/1 48 40000 +Ethernet192 129,130,131,132 Ethernet49/1 49 40000 +Ethernet196 137,138,139,140 Ethernet50/1 50 40000 +Ethernet200 201,202,203,204 Ethernet51/1 51 40000 +Ethernet204 193,194,195,196 Ethernet52/1 52 40000 +Ethernet208 209,210,211,212 Ethernet53/1 53 40000 +Ethernet212 221,222,223,224 Ethernet54/1 54 40000 +Ethernet216 233,234,235,236 Ethernet55/1 55 40000 +Ethernet220 225,226,227,228 Ethernet56/1 56 40000 +Ethernet224 241,242,243,244 Ethernet57/1 57 40000 +Ethernet228 253,254,255,256 Ethernet58/1 58 40000 +Ethernet232 157,158,159,160 Ethernet59/1 59 40000 +Ethernet236 145,146,147,148 Ethernet60/1 60 40000 +Ethernet240 165,166,167,168 Ethernet61/1 61 40000 +Ethernet244 169,170,171,172 Ethernet62/1 62 40000 +Ethernet248 189,190,191,192 Ethernet63/1 63 40000 +Ethernet252 177,178,179,180 Ethernet64/1 64 40000 +Ethernet256 257 Ethernet65 65 10000 +Ethernet260 259 Ethernet66 66 10000 diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/qos.json.j2 b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/sai.profile b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/sai.profile new file mode 100644 index 000000000000..a89cba46c3d1 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-a7260cx3-64-64x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/th2-a7260cx3-64-64x40G.config.bcm b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/th2-a7260cx3-64-64x40G.config.bcm new file mode 100644 index 000000000000..e26a8131efdb --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/Arista-7260CX3-Q64/th2-a7260cx3-64-64x40G.config.bcm @@ -0,0 +1,1015 @@ +PHY_AN_ALLOW_PLL_CHANGE=1 +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +core_clock_frequency=1700 +dma_desc_timeout_usec=15000000 +dpp_clock_ratio=2:3 +higig2_hdr_mode=1 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +l2xmsg_mode=1 +max_vp_lags=0 +mem_scan_enable=1 +miim_intr_enable=0 +module_64ports=1 +os=unix +oversubscribe_mode=1 +pbmp_xport_xe=0x40003ffff0000ffffc0003fffe0001fffe +phy_an_allow_pll_change_hg=0 +phy_an_c73_100=1 +phy_an_c73_102=1 +phy_an_c73_103=1 +phy_an_c73_104=1 +phy_an_c73_105=1 +phy_an_c73_106=1 +phy_an_c73_107=1 +phy_an_c73_108=1 +phy_an_c73_109=1 +phy_an_c73_10=1 +phy_an_c73_110=1 +phy_an_c73_111=1 +phy_an_c73_112=1 +phy_an_c73_113=1 +phy_an_c73_114=1 +phy_an_c73_115=1 +phy_an_c73_116=1 +phy_an_c73_117=1 +phy_an_c73_11=1 +phy_an_c73_12=1 +phy_an_c73_13=1 +phy_an_c73_14=1 +phy_an_c73_15=1 +phy_an_c73_16=1 +phy_an_c73_1=1 +phy_an_c73_2=1 +phy_an_c73_34=1 +phy_an_c73_35=1 +phy_an_c73_36=1 +phy_an_c73_37=1 +phy_an_c73_38=1 +phy_an_c73_39=1 +phy_an_c73_3=1 +phy_an_c73_40=1 +phy_an_c73_41=1 +phy_an_c73_42=1 +phy_an_c73_43=1 +phy_an_c73_44=1 +phy_an_c73_45=1 +phy_an_c73_46=1 +phy_an_c73_47=1 +phy_an_c73_48=1 +phy_an_c73_49=1 +phy_an_c73_4=1 +phy_an_c73_5=1 +phy_an_c73_66=1 +phy_an_c73_68=1 +phy_an_c73_69=1 +phy_an_c73_6=1 +phy_an_c73_70=1 +phy_an_c73_71=1 +phy_an_c73_72=1 +phy_an_c73_73=1 +phy_an_c73_74=1 +phy_an_c73_75=1 +phy_an_c73_76=1 +phy_an_c73_77=1 +phy_an_c73_78=1 +phy_an_c73_79=1 +phy_an_c73_7=1 +phy_an_c73_80=1 +phy_an_c73_81=1 +phy_an_c73_82=1 +phy_an_c73_83=1 +phy_an_c73_8=1 +phy_an_c73_9=1 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_rx_lane_map_physical{101.0}=0x0123 +phy_chain_rx_lane_map_physical{105.0}=0x0123 +phy_chain_rx_lane_map_physical{109.0}=0x0123 +phy_chain_rx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_rx_lane_map_physical{121.0}=0x3210 +phy_chain_rx_lane_map_physical{125.0}=0x1203 +phy_chain_rx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{13.0}=0x0321 +phy_chain_rx_lane_map_physical{133.0}=0x1032 +phy_chain_rx_lane_map_physical{137.0}=0x3210 +phy_chain_rx_lane_map_physical{141.0}=0x0123 +phy_chain_rx_lane_map_physical{145.0}=0x3210 +phy_chain_rx_lane_map_physical{149.0}=0x2310 +phy_chain_rx_lane_map_physical{153.0}=0x0132 +phy_chain_rx_lane_map_physical{157.0}=0x1302 +phy_chain_rx_lane_map_physical{161.0}=0x3021 +phy_chain_rx_lane_map_physical{165.0}=0x2031 +phy_chain_rx_lane_map_physical{169.0}=0x2031 +phy_chain_rx_lane_map_physical{17.0}=0x3210 +phy_chain_rx_lane_map_physical{173.0}=0x1302 +phy_chain_rx_lane_map_physical{177.0}=0x2031 +phy_chain_rx_lane_map_physical{181.0}=0x0213 +phy_chain_rx_lane_map_physical{185.0}=0x0213 +phy_chain_rx_lane_map_physical{189.0}=0x1302 +phy_chain_rx_lane_map_physical{193.0}=0x3120 +phy_chain_rx_lane_map_physical{197.0}=0x0231 +phy_chain_rx_lane_map_physical{201.0}=0x2031 +phy_chain_rx_lane_map_physical{205.0}=0x0213 +phy_chain_rx_lane_map_physical{209.0}=0x2013 +phy_chain_rx_lane_map_physical{21.0}=0x3021 +phy_chain_rx_lane_map_physical{213.0}=0x3021 +phy_chain_rx_lane_map_physical{217.0}=0x0231 +phy_chain_rx_lane_map_physical{221.0}=0x2031 +phy_chain_rx_lane_map_physical{225.0}=0x1203 +phy_chain_rx_lane_map_physical{229.0}=0x1230 +phy_chain_rx_lane_map_physical{233.0}=0x3021 +phy_chain_rx_lane_map_physical{237.0}=0x1032 +phy_chain_rx_lane_map_physical{241.0}=0x2301 +phy_chain_rx_lane_map_physical{245.0}=0x0321 +phy_chain_rx_lane_map_physical{249.0}=0x2301 +phy_chain_rx_lane_map_physical{25.0}=0x2301 +phy_chain_rx_lane_map_physical{253.0}=0x2301 +phy_chain_rx_lane_map_physical{257.0}=0x3210 +phy_chain_rx_lane_map_physical{29.0}=0x3021 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 +phy_chain_rx_lane_map_physical{41.0}=0x3021 +phy_chain_rx_lane_map_physical{45.0}=0x1023 +phy_chain_rx_lane_map_physical{49.0}=0x0213 +phy_chain_rx_lane_map_physical{5.0}=0x3201 +phy_chain_rx_lane_map_physical{53.0}=0x3201 +phy_chain_rx_lane_map_physical{57.0}=0x2013 +phy_chain_rx_lane_map_physical{61.0}=0x0213 +phy_chain_rx_lane_map_physical{65.0}=0x1203 +phy_chain_rx_lane_map_physical{69.0}=0x0213 +phy_chain_rx_lane_map_physical{73.0}=0x0213 +phy_chain_rx_lane_map_physical{77.0}=0x3120 +phy_chain_rx_lane_map_physical{81.0}=0x0213 +phy_chain_rx_lane_map_physical{85.0}=0x2031 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_rx_lane_map_physical{9.0}=0x0321 +phy_chain_rx_lane_map_physical{93.0}=0x3120 +phy_chain_rx_lane_map_physical{97.0}=0x1203 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +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{11.0}=0x1 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +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{12.0}=0x1 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +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}=0x1 +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{130.0}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{133.0}=0x1 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_rx_polarity_flip_physical{141.0}=0x1 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x0 +phy_chain_rx_polarity_flip_physical{147.0}=0x1 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x1 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x1 +phy_chain_rx_polarity_flip_physical{156.0}=0x0 +phy_chain_rx_polarity_flip_physical{157.0}=0x0 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x1 +phy_chain_rx_polarity_flip_physical{169.0}=0x1 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x0 +phy_chain_rx_polarity_flip_physical{175.0}=0x1 +phy_chain_rx_polarity_flip_physical{176.0}=0x1 +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x1 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{18.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x0 +phy_chain_rx_polarity_flip_physical{181.0}=0x1 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_rx_polarity_flip_physical{185.0}=0x0 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x1 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_rx_polarity_flip_physical{190.0}=0x0 +phy_chain_rx_polarity_flip_physical{191.0}=0x1 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x1 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x0 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x0 +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x0 +phy_chain_rx_polarity_flip_physical{215.0}=0x1 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 +phy_chain_rx_polarity_flip_physical{217.0}=0x0 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 +phy_chain_rx_polarity_flip_physical{221.0}=0x0 +phy_chain_rx_polarity_flip_physical{222.0}=0x0 +phy_chain_rx_polarity_flip_physical{223.0}=0x1 +phy_chain_rx_polarity_flip_physical{224.0}=0x1 +phy_chain_rx_polarity_flip_physical{225.0}=0x1 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x0 +phy_chain_rx_polarity_flip_physical{228.0}=0x1 +phy_chain_rx_polarity_flip_physical{229.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x1 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 +phy_chain_rx_polarity_flip_physical{233.0}=0x1 +phy_chain_rx_polarity_flip_physical{234.0}=0x0 +phy_chain_rx_polarity_flip_physical{235.0}=0x0 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 +phy_chain_rx_polarity_flip_physical{241.0}=0x1 +phy_chain_rx_polarity_flip_physical{242.0}=0x0 +phy_chain_rx_polarity_flip_physical{243.0}=0x1 +phy_chain_rx_polarity_flip_physical{244.0}=0x0 +phy_chain_rx_polarity_flip_physical{245.0}=0x1 +phy_chain_rx_polarity_flip_physical{246.0}=0x1 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x0 +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{250.0}=0x1 +phy_chain_rx_polarity_flip_physical{251.0}=0x0 +phy_chain_rx_polarity_flip_physical{252.0}=0x1 +phy_chain_rx_polarity_flip_physical{253.0}=0x1 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x1 +phy_chain_rx_polarity_flip_physical{256.0}=0x0 +phy_chain_rx_polarity_flip_physical{257.0}=0x0 +phy_chain_rx_polarity_flip_physical{259.0}=0x0 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +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}=0x1 +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{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +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{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 +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{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.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}=0x0 +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{8.0}=0x1 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x1 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 +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}=0x0 +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}=0x2031 +phy_chain_tx_lane_map_physical{101.0}=0x1023 +phy_chain_tx_lane_map_physical{105.0}=0x1302 +phy_chain_tx_lane_map_physical{109.0}=0x0321 +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_tx_lane_map_physical{117.0}=0x3120 +phy_chain_tx_lane_map_physical{121.0}=0x3102 +phy_chain_tx_lane_map_physical{125.0}=0x3210 +phy_chain_tx_lane_map_physical{129.0}=0x1023 +phy_chain_tx_lane_map_physical{13.0}=0x3021 +phy_chain_tx_lane_map_physical{133.0}=0x3210 +phy_chain_tx_lane_map_physical{137.0}=0x2031 +phy_chain_tx_lane_map_physical{141.0}=0x1302 +phy_chain_tx_lane_map_physical{145.0}=0x3210 +phy_chain_tx_lane_map_physical{149.0}=0x0213 +phy_chain_tx_lane_map_physical{153.0}=0x3210 +phy_chain_tx_lane_map_physical{157.0}=0x1320 +phy_chain_tx_lane_map_physical{161.0}=0x3210 +phy_chain_tx_lane_map_physical{165.0}=0x0231 +phy_chain_tx_lane_map_physical{169.0}=0x3120 +phy_chain_tx_lane_map_physical{17.0}=0x1032 +phy_chain_tx_lane_map_physical{173.0}=0x0312 +phy_chain_tx_lane_map_physical{177.0}=0x0231 +phy_chain_tx_lane_map_physical{181.0}=0x3210 +phy_chain_tx_lane_map_physical{185.0}=0x3210 +phy_chain_tx_lane_map_physical{189.0}=0x1320 +phy_chain_tx_lane_map_physical{193.0}=0x0321 +phy_chain_tx_lane_map_physical{197.0}=0x3120 +phy_chain_tx_lane_map_physical{201.0}=0x3120 +phy_chain_tx_lane_map_physical{205.0}=0x0123 +phy_chain_tx_lane_map_physical{209.0}=0x3120 +phy_chain_tx_lane_map_physical{21.0}=0x0213 +phy_chain_tx_lane_map_physical{213.0}=0x3021 +phy_chain_tx_lane_map_physical{217.0}=0x0312 +phy_chain_tx_lane_map_physical{221.0}=0x2301 +phy_chain_tx_lane_map_physical{225.0}=0x0123 +phy_chain_tx_lane_map_physical{229.0}=0x2031 +phy_chain_tx_lane_map_physical{233.0}=0x0231 +phy_chain_tx_lane_map_physical{237.0}=0x0213 +phy_chain_tx_lane_map_physical{241.0}=0x1320 +phy_chain_tx_lane_map_physical{245.0}=0x2031 +phy_chain_tx_lane_map_physical{249.0}=0x3120 +phy_chain_tx_lane_map_physical{25.0}=0x0231 +phy_chain_tx_lane_map_physical{253.0}=0x0321 +phy_chain_tx_lane_map_physical{257.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x1230 +phy_chain_tx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{37.0}=0x0123 +phy_chain_tx_lane_map_physical{41.0}=0x0213 +phy_chain_tx_lane_map_physical{45.0}=0x0132 +phy_chain_tx_lane_map_physical{49.0}=0x2031 +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_tx_lane_map_physical{53.0}=0x2301 +phy_chain_tx_lane_map_physical{57.0}=0x2031 +phy_chain_tx_lane_map_physical{61.0}=0x2031 +phy_chain_tx_lane_map_physical{65.0}=0x1230 +phy_chain_tx_lane_map_physical{69.0}=0x2013 +phy_chain_tx_lane_map_physical{73.0}=0x0213 +phy_chain_tx_lane_map_physical{77.0}=0x2310 +phy_chain_tx_lane_map_physical{81.0}=0x0321 +phy_chain_tx_lane_map_physical{85.0}=0x2013 +phy_chain_tx_lane_map_physical{89.0}=0x0213 +phy_chain_tx_lane_map_physical{9.0}=0x3012 +phy_chain_tx_lane_map_physical{93.0}=0x3102 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{104.0}=0x0 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 +phy_chain_tx_polarity_flip_physical{109.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x0 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x1 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x1 +phy_chain_tx_polarity_flip_physical{134.0}=0x1 +phy_chain_tx_polarity_flip_physical{135.0}=0x1 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x1 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x1 +phy_chain_tx_polarity_flip_physical{141.0}=0x0 +phy_chain_tx_polarity_flip_physical{142.0}=0x1 +phy_chain_tx_polarity_flip_physical{143.0}=0x1 +phy_chain_tx_polarity_flip_physical{144.0}=0x1 +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x1 +phy_chain_tx_polarity_flip_physical{147.0}=0x1 +phy_chain_tx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{153.0}=0x1 +phy_chain_tx_polarity_flip_physical{154.0}=0x0 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x1 +phy_chain_tx_polarity_flip_physical{163.0}=0x1 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x1 +phy_chain_tx_polarity_flip_physical{167.0}=0x1 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x0 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x1 +phy_chain_tx_polarity_flip_physical{171.0}=0x1 +phy_chain_tx_polarity_flip_physical{172.0}=0x1 +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x0 +phy_chain_tx_polarity_flip_physical{175.0}=0x1 +phy_chain_tx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{177.0}=0x1 +phy_chain_tx_polarity_flip_physical{178.0}=0x0 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x1 +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x1 +phy_chain_tx_polarity_flip_physical{187.0}=0x1 +phy_chain_tx_polarity_flip_physical{188.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x0 +phy_chain_tx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x0 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 +phy_chain_tx_polarity_flip_physical{193.0}=0x1 +phy_chain_tx_polarity_flip_physical{194.0}=0x1 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x0 +phy_chain_tx_polarity_flip_physical{198.0}=0x1 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x1 +phy_chain_tx_polarity_flip_physical{201.0}=0x1 +phy_chain_tx_polarity_flip_physical{202.0}=0x1 +phy_chain_tx_polarity_flip_physical{203.0}=0x1 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x1 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x1 +phy_chain_tx_polarity_flip_physical{209.0}=0x1 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x1 +phy_chain_tx_polarity_flip_physical{211.0}=0x1 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x1 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x1 +phy_chain_tx_polarity_flip_physical{217.0}=0x1 +phy_chain_tx_polarity_flip_physical{218.0}=0x1 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x1 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x0 +phy_chain_tx_polarity_flip_physical{223.0}=0x0 +phy_chain_tx_polarity_flip_physical{224.0}=0x1 +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x1 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x1 +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x0 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 +phy_chain_tx_polarity_flip_physical{241.0}=0x1 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x1 +phy_chain_tx_polarity_flip_physical{247.0}=0x1 +phy_chain_tx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x0 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 +phy_chain_tx_polarity_flip_physical{253.0}=0x1 +phy_chain_tx_polarity_flip_physical{254.0}=0x1 +phy_chain_tx_polarity_flip_physical{255.0}=0x1 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 +phy_chain_tx_polarity_flip_physical{257.0}=0x0 +phy_chain_tx_polarity_flip_physical{259.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{45.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 +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{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 +phy_chain_tx_polarity_flip_physical{61.0}=0x0 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +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}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 +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{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x0 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x0 +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x1 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +port_init_autoneg_100=0 +port_init_autoneg_102=0 +port_init_autoneg_103=0 +port_init_autoneg_104=0 +port_init_autoneg_105=0 +port_init_autoneg_106=0 +port_init_autoneg_107=0 +port_init_autoneg_108=0 +port_init_autoneg_109=0 +port_init_autoneg_10=0 +port_init_autoneg_110=0 +port_init_autoneg_111=0 +port_init_autoneg_112=0 +port_init_autoneg_113=0 +port_init_autoneg_114=0 +port_init_autoneg_115=0 +port_init_autoneg_116=0 +port_init_autoneg_117=0 +port_init_autoneg_11=0 +port_init_autoneg_12=0 +port_init_autoneg_13=0 +port_init_autoneg_14=0 +port_init_autoneg_15=0 +port_init_autoneg_16=0 +port_init_autoneg_1=0 +port_init_autoneg_2=0 +port_init_autoneg_34=0 +port_init_autoneg_35=0 +port_init_autoneg_36=0 +port_init_autoneg_37=0 +port_init_autoneg_38=0 +port_init_autoneg_39=0 +port_init_autoneg_3=0 +port_init_autoneg_40=0 +port_init_autoneg_41=0 +port_init_autoneg_42=0 +port_init_autoneg_43=0 +port_init_autoneg_44=0 +port_init_autoneg_45=0 +port_init_autoneg_46=0 +port_init_autoneg_47=0 +port_init_autoneg_48=0 +port_init_autoneg_49=0 +port_init_autoneg_4=0 +port_init_autoneg_5=0 +port_init_autoneg_66=0 +port_init_autoneg_68=0 +port_init_autoneg_69=0 +port_init_autoneg_6=0 +port_init_autoneg_70=0 +port_init_autoneg_71=0 +port_init_autoneg_72=0 +port_init_autoneg_73=0 +port_init_autoneg_74=0 +port_init_autoneg_75=0 +port_init_autoneg_76=0 +port_init_autoneg_77=0 +port_init_autoneg_78=0 +port_init_autoneg_79=0 +port_init_autoneg_7=0 +port_init_autoneg_80=0 +port_init_autoneg_81=0 +port_init_autoneg_82=0 +port_init_autoneg_83=0 +port_init_autoneg_8=0 +port_init_autoneg_9=0 +port_init_cl72_hg=1 +port_phy_addr_100=0xff +port_phy_addr_102=0xff +port_phy_addr_103=0xff +port_phy_addr_104=0xff +port_phy_addr_105=0xff +port_phy_addr_106=0xff +port_phy_addr_107=0xff +port_phy_addr_108=0xff +port_phy_addr_109=0xff +port_phy_addr_10=0xff +port_phy_addr_110=0xff +port_phy_addr_111=0xff +port_phy_addr_112=0xff +port_phy_addr_113=0xff +port_phy_addr_114=0xff +port_phy_addr_115=0xff +port_phy_addr_116=0xff +port_phy_addr_117=0xff +port_phy_addr_11=0xff +port_phy_addr_12=0xff +port_phy_addr_13=0xff +port_phy_addr_14=0xff +port_phy_addr_15=0xff +port_phy_addr_16=0xff +port_phy_addr_1=0xff +port_phy_addr_2=0xff +port_phy_addr_34=0xff +port_phy_addr_35=0xff +port_phy_addr_36=0xff +port_phy_addr_37=0xff +port_phy_addr_38=0xff +port_phy_addr_39=0xff +port_phy_addr_3=0xff +port_phy_addr_40=0xff +port_phy_addr_41=0xff +port_phy_addr_42=0xff +port_phy_addr_43=0xff +port_phy_addr_44=0xff +port_phy_addr_45=0xff +port_phy_addr_46=0xff +port_phy_addr_47=0xff +port_phy_addr_48=0xff +port_phy_addr_49=0xff +port_phy_addr_4=0xff +port_phy_addr_5=0xff +port_phy_addr_66=0xff +port_phy_addr_68=0xff +port_phy_addr_69=0xff +port_phy_addr_6=0xff +port_phy_addr_70=0xff +port_phy_addr_71=0xff +port_phy_addr_72=0xff +port_phy_addr_73=0xff +port_phy_addr_74=0xff +port_phy_addr_75=0xff +port_phy_addr_76=0xff +port_phy_addr_77=0xff +port_phy_addr_78=0xff +port_phy_addr_79=0xff +port_phy_addr_7=0xff +port_phy_addr_80=0xff +port_phy_addr_81=0xff +port_phy_addr_82=0xff +port_phy_addr_83=0xff +port_phy_addr_8=0xff +port_phy_addr_9=0xff +portmap_100=259:10 +portmap_101=262:10 +portmap_102=217:40 +portmap_103=213:40 +portmap_104=229:40 +portmap_105=237:40 +portmap_106=249:40 +portmap_107=245:40 +portmap_108=209:40 +portmap_109=221:40 +portmap_10=29:40 +portmap_110=233:40 +portmap_111=225:40 +portmap_112=241:40 +portmap_113=253:40 +portmap_114=197:40 +portmap_115=205:40 +portmap_116=201:40 +portmap_117=193:40 +portmap_11=41:40 +portmap_12=33:40 +portmap_134=263:10 +portmap_13=57:40 +portmap_14=53:40 +portmap_15=49:40 +portmap_16=61:40 +portmap_1=5:40 +portmap_2=13:40 +portmap_33=260:10 +portmap_34=77:40 +portmap_35=65:40 +portmap_36=85:40 +portmap_37=89:40 +portmap_38=109:40 +portmap_39=97:40 +portmap_3=25:40 +portmap_40=69:40 +portmap_41=73:40 +portmap_42=93:40 +portmap_43=81:40 +portmap_44=101:40 +portmap_45=105:40 +portmap_46=117:40 +portmap_47=121:40 +portmap_48=125:40 +portmap_49=113:40 +portmap_4=21:40 +portmap_5=37:40 +portmap_66=257:10 +portmap_67=261:10 +portmap_68=149:40 +portmap_69=153:40 +portmap_6=45:40 +portmap_70=173:40 +portmap_71=161:40 +portmap_72=181:40 +portmap_73=185:40 +portmap_74=157:40 +portmap_75=145:40 +portmap_76=165:40 +portmap_77=169:40 +portmap_78=189:40 +portmap_79=177:40 +portmap_7=9:40 +portmap_80=141:40 +portmap_81=133:40 +portmap_82=129:40 +portmap_83=137:40 +portmap_8=1:40 +portmap_9=17:40 +robust_hash_disable_egress_vlan=1 +robust_hash_disable_mpls=1 +robust_hash_disable_vlan=1 +stable_size=0x5500000 +stable_size=0x5500000 +tdma_timeout_usec=15000000 +tslam_timeout_usec=15000000 + +# tuning parameters +serdes_preemphasis_1=0x105004 +serdes_preemphasis_2=0x105004 +serdes_preemphasis_3=0x105004 +serdes_preemphasis_4=0x105004 +serdes_preemphasis_5=0x105004 +serdes_preemphasis_6=0x105004 +serdes_preemphasis_7=0x105004 +serdes_preemphasis_8=0x105004 +serdes_preemphasis_9=0x105004 +serdes_preemphasis_10=0x105004 +serdes_preemphasis_11=0x105004 +serdes_preemphasis_12=0x105004 +serdes_preemphasis_13=0x71f01 +serdes_preemphasis_14=0x72101 +serdes_preemphasis_15=0x105004 +serdes_preemphasis_16=0x105004 +serdes_preemphasis_34=0x105004 +serdes_preemphasis_35=0x105004 +serdes_preemphasis_36=0x105004 +serdes_preemphasis_37=0x105004 +serdes_preemphasis_38=0x105004 +serdes_preemphasis_39=0x105004 +serdes_preemphasis_40=0x105004 +serdes_preemphasis_41=0x105004 +serdes_preemphasis_42=0x105004 +serdes_preemphasis_43=0x105004 +serdes_preemphasis_44=0x105004 +serdes_preemphasis_45=0x105004 +serdes_preemphasis_46=0x61d01 +serdes_preemphasis_47=0x51a01 +serdes_preemphasis_48=0x105004 +serdes_preemphasis_49=0x105004 +serdes_preemphasis_66=0x43004 +serdes_preemphasis_68=0x105004 +serdes_preemphasis_69=0x105004 +serdes_preemphasis_70=0x105004 +serdes_preemphasis_71=0x105004 +serdes_preemphasis_72=0x105004 +serdes_preemphasis_73=0x105004 +serdes_preemphasis_74=0x105004 +serdes_preemphasis_75=0x105004 +serdes_preemphasis_76=0x105004 +serdes_preemphasis_77=0x105004 +serdes_preemphasis_78=0x105004 +serdes_preemphasis_79=0x105004 +serdes_preemphasis_80=0x61d01 +serdes_preemphasis_81=0x51b01 +serdes_preemphasis_82=0x105004 +serdes_preemphasis_83=0x105004 +serdes_preemphasis_100=0x43004 +serdes_preemphasis_102=0x105004 +serdes_preemphasis_103=0x105004 +serdes_preemphasis_104=0x105004 +serdes_preemphasis_105=0x105004 +serdes_preemphasis_106=0x105004 +serdes_preemphasis_107=0x105004 +serdes_preemphasis_108=0x105004 +serdes_preemphasis_109=0x105004 +serdes_preemphasis_110=0x105004 +serdes_preemphasis_111=0x105004 +serdes_preemphasis_112=0x105004 +serdes_preemphasis_113=0x105004 +serdes_preemphasis_114=0x61c01 +serdes_preemphasis_115=0x61c01 +serdes_preemphasis_116=0x105004 +serdes_preemphasis_117=0x105004 + +mmu_init_config="MSFT-TH2-Tier0" diff --git a/device/arista/x86_64-arista_7260cx3_64/default_sku b/device/arista/x86_64-arista_7260cx3_64/default_sku new file mode 100644 index 000000000000..959766d95f5c --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/default_sku @@ -0,0 +1 @@ +Arista-7260CX3-C64 t1 diff --git a/device/arista/x86_64-arista_7260cx3_64/fancontrol b/device/arista/x86_64-arista_7260cx3_64/fancontrol new file mode 100644 index 000000000000..eb64fb3e670e --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=5 +DEVPATH=hwmon2=devices/pci0000:00/0000:00:1c.0/0000:06:00.0/i2c-1/1-004c hwmon4=devices/pci0000:ff/0000:ff:0b.3/i2c-85/85-0060 +DEVNAME=hwmon2=max6658 hwmon4=la_cpld +FCTEMPS=hwmon4/pwm4=hwmon2/temp1_input hwmon4/pwm3=hwmon2/temp1_input hwmon4/pwm2=hwmon2/temp1_input hwmon4/pwm1=hwmon2/temp1_input +FCFANS=hwmon4/pwm4=hwmon4/fan4_input hwmon4/pwm3=hwmon4/fan3_input hwmon4/pwm2=hwmon4/fan2_input hwmon4/pwm1=hwmon4/fan1_input +MINTEMP=hwmon4/pwm4=50 hwmon4/pwm3=50 hwmon4/pwm2=50 hwmon4/pwm1=50 +MINPWM=hwmon4/pwm4=128 hwmon4/pwm3=128 hwmon4/pwm2=128 hwmon4/pwm1=128 +MAXTEMP=hwmon4/pwm4=60 hwmon4/pwm3=60 hwmon4/pwm2=60 hwmon4/pwm1=60 +MINSTART=hwmon4/pwm4=128 hwmon4/pwm3=128 hwmon4/pwm2=128 hwmon4/pwm1=128 +MINSTOP=hwmon4/pwm4=128 hwmon4/pwm3=128 hwmon4/pwm2=128 hwmon4/pwm1=128 diff --git a/device/arista/x86_64-arista_7260cx3_64/pcie.yaml b/device/arista/x86_64-arista_7260cx3_64/pcie.yaml new file mode 100644 index 000000000000..a2540013703e --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/pcie.yaml @@ -0,0 +1,426 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 6f00 + name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 6f02 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '01' + fn: '1' + id: 6f03 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 6f04 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '2' + id: 6f06 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 6f08 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '05' + fn: '0' + id: 6f28 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Map/VTd_Misc/System Management (rev 03)' +- bus: '00' + dev: '05' + fn: '1' + id: 6f29 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO Hot Plug (rev 03)' +- bus: '00' + dev: '05' + fn: '2' + id: 6f2a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO RAS/Control Status/Global Errors (rev 03)' +- bus: '00' + dev: '05' + fn: '4' + id: 6f2c + name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev + 03)' +- bus: '00' + dev: '14' + fn: '0' + id: 8c31 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + xHCI (rev 05)' +- bus: '00' + dev: 1c + fn: '0' + id: 8c10 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #1 (rev d5)' +- bus: '00' + dev: 1c + fn: '4' + id: 8c18 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #5 (rev d5)' +- bus: '00' + dev: 1f + fn: '0' + id: 8c54 + name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard + SKU LPC Controller (rev 05)' +- bus: '00' + dev: 1f + fn: '2' + id: 8c02 + name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port + SATA Controller 1 [AHCI mode] (rev 05)' +- bus: '00' + dev: 1f + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller + (rev 05)' +- bus: '00' + dev: 1f + fn: '6' + id: 8c24 + name: 'Signal processing controller: Intel Corporation 8 Series Chipset Family Thermal + Management Controller (rev 05)' +- bus: '01' + dev: '00' + fn: '0' + id: '1682' + name: 'Ethernet controller: Broadcom Limited NetXtreme BCM57762 Gigabit Ethernet + PCIe (rev 20)' +- bus: '02' + dev: '00' + fn: '0' + id: '1682' + name: 'Ethernet controller: Broadcom Limited NetXtreme BCM57762 Gigabit Ethernet + PCIe (rev 20)' +- bus: '03' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '03' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '03' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '03' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '04' + dev: '00' + fn: '0' + id: 15a7 + name: 'Ethernet controller: Intel Corporation Device 15a7' +- bus: '04' + dev: '00' + fn: '1' + id: 15a7 + name: 'Ethernet controller: Intel Corporation Device 15a7' +- bus: '06' + dev: '00' + fn: '0' + id: '0001' + name: 'System peripheral: Arastra Inc. Device 0001 (rev 01)' +- bus: '07' + dev: '00' + fn: '0' + id: b971 + name: 'Ethernet controller: Broadcom Limited Device b971 (rev 11)' +- bus: '07' + dev: '00' + fn: '1' + id: b971 + name: 'Ethernet controller: Broadcom Limited Device b971 (rev 11)' +- bus: ff + dev: 0b + fn: '0' + id: 6f81 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '1' + id: 6f36 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '2' + id: 6f37 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '3' + id: '0001' + name: 'System peripheral: Arastra Inc. Device 0001 (rev 03)' +- bus: ff + dev: 0c + fn: '0' + id: 6fe0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '1' + id: 6fe1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '0' + id: 6ff8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '4' + id: 6ffc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '5' + id: 6ffd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '6' + id: 6ffe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: '10' + fn: '0' + id: 6f1d + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '1' + id: 6f34 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '5' + id: 6f1e + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '6' + id: 6f7d + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '7' + id: 6f1f + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '12' + fn: '0' + id: 6fa0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '12' + fn: '1' + id: 6f30 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '13' + fn: '0' + id: 6fa8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '1' + id: 6f71 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '2' + id: 6faa + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '3' + id: 6fab + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '4' + id: 6fac + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '5' + id: 6fad + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '6' + id: 6fae + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Broadcast (rev 03)' +- bus: ff + dev: '13' + fn: '7' + id: 6faf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Global Broadcast (rev 03)' +- bus: ff + dev: '14' + fn: '0' + id: 6fb0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '1' + id: 6fb1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '2' + id: 6fb2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Error (rev 03)' +- bus: ff + dev: '14' + fn: '3' + id: 6fb3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Error (rev 03)' +- bus: ff + dev: '14' + fn: '4' + id: 6fbc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '5' + id: 6fbd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '6' + id: 6fbe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '7' + id: 6fbf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '15' + fn: '0' + id: 6fb4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '1' + id: 6fb5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '2' + id: 6fb6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Error (rev 03)' +- bus: ff + dev: '15' + fn: '3' + id: 6fb7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Error (rev 03)' +- bus: ff + dev: 1e + fn: '0' + id: 6f98 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '1' + id: 6f99 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '2' + id: 6f9a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '3' + id: 6fc0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '4' + id: 6f9c + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '0' + id: 6f88 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '2' + id: 6f8a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' diff --git a/device/arista/x86_64-arista_7260cx3_64/platform.json b/device/arista/x86_64-arista_7260cx3_64/platform.json new file mode 100644 index 000000000000..d489bd9506c9 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/platform.json @@ -0,0 +1,296 @@ +{ + "chassis": { + "name": "DCS-7260CX3-64", + "components": [], + "fans": [], + "fan_drawers": [ + { + "name": "slot1", + "fans": [ + { + "name": "fan1" + } + ] + }, + { + "name": "slot2", + "fans": [ + { + "name": "fan2" + } + ] + }, + { + "name": "slot3", + "fans": [ + { + "name": "fan3" + } + ] + }, + { + "name": "slot4", + "fans": [ + { + "name": "fan4" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Board sensor" + }, + { + "name": "PCH temp sensor" + }, + { + "name": "Physical id 0" + }, + { + "name": "CPU core0 temp sensor" + }, + { + "name": "CPU core1 temp sensor" + }, + { + "name": "CPU board temp sensor" + }, + { + "name": "Back-panel temp sensor" + }, + { + "name": "Front-panel temp sensor" + }, + { + "name": "Power supply 1 hotspot sensor" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 exhaust temp sensor" + }, + { + "name": "Power supply 2 hotspot sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 exhaust temp sensor" + } + ], + "sfps": [ + { + "name": "qsfp1" + }, + { + "name": "qsfp2" + }, + { + "name": "qsfp3" + }, + { + "name": "qsfp4" + }, + { + "name": "qsfp5" + }, + { + "name": "qsfp6" + }, + { + "name": "qsfp7" + }, + { + "name": "qsfp8" + }, + { + "name": "qsfp9" + }, + { + "name": "qsfp10" + }, + { + "name": "qsfp11" + }, + { + "name": "qsfp12" + }, + { + "name": "qsfp13" + }, + { + "name": "qsfp14" + }, + { + "name": "qsfp15" + }, + { + "name": "qsfp16" + }, + { + "name": "qsfp17" + }, + { + "name": "qsfp18" + }, + { + "name": "qsfp19" + }, + { + "name": "qsfp20" + }, + { + "name": "qsfp21" + }, + { + "name": "qsfp22" + }, + { + "name": "qsfp23" + }, + { + "name": "qsfp24" + }, + { + "name": "qsfp25" + }, + { + "name": "qsfp26" + }, + { + "name": "qsfp27" + }, + { + "name": "qsfp28" + }, + { + "name": "qsfp29" + }, + { + "name": "qsfp30" + }, + { + "name": "qsfp31" + }, + { + "name": "qsfp32" + }, + { + "name": "qsfp33" + }, + { + "name": "qsfp34" + }, + { + "name": "qsfp35" + }, + { + "name": "qsfp36" + }, + { + "name": "qsfp37" + }, + { + "name": "qsfp38" + }, + { + "name": "qsfp39" + }, + { + "name": "qsfp40" + }, + { + "name": "qsfp41" + }, + { + "name": "qsfp42" + }, + { + "name": "qsfp43" + }, + { + "name": "qsfp44" + }, + { + "name": "qsfp45" + }, + { + "name": "qsfp46" + }, + { + "name": "qsfp47" + }, + { + "name": "qsfp48" + }, + { + "name": "qsfp49" + }, + { + "name": "qsfp50" + }, + { + "name": "qsfp51" + }, + { + "name": "qsfp52" + }, + { + "name": "qsfp53" + }, + { + "name": "qsfp54" + }, + { + "name": "qsfp55" + }, + { + "name": "qsfp56" + }, + { + "name": "qsfp57" + }, + { + "name": "qsfp58" + }, + { + "name": "qsfp59" + }, + { + "name": "qsfp60" + }, + { + "name": "qsfp61" + }, + { + "name": "qsfp62" + }, + { + "name": "qsfp63" + }, + { + "name": "qsfp64" + }, + { + "name": "sfp65" + }, + { + "name": "sfp66" + } + ] + }, + "interfaces": {} +} \ No newline at end of file diff --git a/device/arista/x86_64-arista_7260cx3_64/platform_reboot b/device/arista/x86_64-arista_7260cx3_64/platform_reboot new file mode 120000 index 000000000000..7f94a49e38b0 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/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_7260cx3_64/plugins/eeprom.py b/device/arista/x86_64-arista_7260cx3_64/plugins/eeprom.py new file mode 120000 index 000000000000..35cfaff3de4e --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/plugins/eeprom.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/eeprom.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7260cx3_64/plugins/led_control.py b/device/arista/x86_64-arista_7260cx3_64/plugins/led_control.py new file mode 120000 index 000000000000..8d733780117e --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/plugins/led_control.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/led_control.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7260cx3_64/plugins/psuutil.py b/device/arista/x86_64-arista_7260cx3_64/plugins/psuutil.py new file mode 120000 index 000000000000..2b0024ade969 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/plugins/psuutil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/psuutil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7260cx3_64/plugins/sfputil.py b/device/arista/x86_64-arista_7260cx3_64/plugins/sfputil.py new file mode 120000 index 000000000000..c333e23763d7 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/plugins/sfputil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/sfputil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7260cx3_64/pmon_daemon_control.json b/device/arista/x86_64-arista_7260cx3_64/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7260cx3_64/sensors.conf b/device/arista/x86_64-arista_7260cx3_64/sensors.conf new file mode 100644 index 000000000000..1dc02fbaef98 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/sensors.conf @@ -0,0 +1,53 @@ +# libsensors configuration file for DCS-7260CX3-64 +# ------------------------------------------------# + +bus "i2c-1" "SCD 0000:06:00.0 SMBus master 0 bus 0" +bus "i2c-3" "SCD 0000:06:00.0 SMBus master 0 bus 2" +bus "i2c-4" "SCD 0000:06:00.0 SMBus master 0 bus 3" +bus "i2c-73" "SCD 0000:ff:0b.3 SMBus master 0 bus 0" +bus "i2c-88" "SCD 0000:ff:0b.3 SMBus master 3 bus 3" + +chip "max6658-i2c-1-4c" + label temp1 "Asic temp sensor" + + set temp1_max 65 + set temp1_crit 75 + + ignore temp2 + +chip "pmbus-i2c-3-58" + label temp1 "Power supply 1 hotspot sensor" + label temp2 "Power supply 1 inlet temp sensor" + label temp3 "Power supply 1 exhaust temp sensor" + + # setting maximum and critical thresholds is not supported for this psu + # fault and warning limits defined internally by hardware + + ignore fan2 + ignore fan3 + +chip "pmbus-i2c-4-58" + label temp1 "Power supply 2 hotspot sensor" + label temp2 "Power supply 2 inlet temp sensor" + label temp3 "Power supply 2 exhaust temp sensor" + + # setting maximum and critical thresholds is not supported for this psu + # fault and warning limits defined internally by hardware + + ignore fan2 + ignore fan3 + +chip "max6658-i2c-73-4c" + label temp1 "Back panel temp sensor 1" + label temp2 "Back panel temp sensor 2" + + set temp1_max 65 + set temp1_crit 75 + set temp2_max 65 + set temp2_crit 75 + +chip "lm73-i2c-88-48" + label temp1 "Front panel temp sensor" + + set temp1_max 65 + set temp1_crit 75 diff --git a/device/arista/x86_64-arista_7260cx3_64/system_health_monitoring_config.json b/device/arista/x86_64-arista_7260cx3_64/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7260cx3_64/thermal_policy.json b/device/arista/x86_64-arista_7260cx3_64/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32d4/Arista-7280CR3-C40/jr2-a7280cr3-32d4-40x100G.config.bcm b/device/arista/x86_64-arista_7280cr3_32d4/Arista-7280CR3-C40/jr2-a7280cr3-32d4-40x100G.config.bcm new file mode 100644 index 000000000000..4e9d02fdc821 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/Arista-7280CR3-C40/jr2-a7280cr3-32d4-40x100G.config.bcm @@ -0,0 +1,769 @@ +soc_family.BCM8869X=BCM8869X + +custom_feature_ucode_path=u_code_db2pem.txt +system_headers_mode=1 +suppress_unknown_prop_warnings=1 +l4_protocols_load_balancing_enable=1 +fabric_logical_port_base=512 +trunk_group_max_members=128 +num_olp_tm_ports.BCM8869X=1 + +ucode_port_0.BCM8869X=CPU.0:core_0.0 +ucode_port_200.BCM8869X=CPU.8:core_1.200 +ucode_port_201.BCM8869X=CPU.16:core_0.201 +ucode_port_202.BCM8869X=CPU.24:core_1.202 +ucode_port_203.BCM8869X=CPU.32:core_0.203 + +port_init_speed_xe.BCM8869X=10000 +port_init_speed_xl.BCM8869X=40000 +port_init_speed_le.BCM8869X=50000 +port_init_speed_ce.BCM8869X=100000 +port_init_speed_cc.BCM8869X=200000 +port_init_speed_cd.BCM8869X=400000 +port_init_speed_il.BCM8869X=10312 + +port_init_cl72=0 + +serdes_tx_taps_1=pam4:-16:64:0:3:0:0 +serdes_tx_taps_2=pam4:-16:64:0:3:0:0 +serdes_tx_taps_3=pam4:-16:64:0:3:0:0 +serdes_tx_taps_4=pam4:-16:64:0:3:0:0 +serdes_tx_taps_5=pam4:-16:64:0:3:0:0 +serdes_tx_taps_6=pam4:-16:64:0:3:0:0 +serdes_tx_taps_7=pam4:-16:64:0:3:0:0 +serdes_tx_taps_8=pam4:-16:64:0:3:0:0 +serdes_tx_taps_9=pam4:-8:60:0:0:0:0 +serdes_tx_taps_10=pam4:-8:60:0:0:0:0 +serdes_tx_taps_11=pam4:-8:60:0:0:0:0 +serdes_tx_taps_12=pam4:-8:60:0:0:0:0 +serdes_tx_taps_13=pam4:-8:60:0:0:0:0 +serdes_tx_taps_14=pam4:-8:60:0:0:0:0 +serdes_tx_taps_15=pam4:-8:60:0:0:0:0 +serdes_tx_taps_16=pam4:-8:60:0:0:0:0 +serdes_tx_taps_17=pam4:-8:60:0:0:0:0 +serdes_tx_taps_18=pam4:-8:60:0:0:0:0 +serdes_tx_taps_19=pam4:-8:60:0:0:0:0 +serdes_tx_taps_20=pam4:-8:60:0:0:0:0 +serdes_tx_taps_21=pam4:-8:60:0:0:0:0 +serdes_tx_taps_22=pam4:-8:60:0:0:0:0 +serdes_tx_taps_23=pam4:-8:60:0:0:0:0 +serdes_tx_taps_24=pam4:-8:60:0:0:0:0 +serdes_tx_taps_25=pam4:-8:60:0:0:0:0 +serdes_tx_taps_26=pam4:-8:60:0:0:0:0 +serdes_tx_taps_27=pam4:-8:60:0:0:0:0 +serdes_tx_taps_28=pam4:-8:60:0:0:0:0 +serdes_tx_taps_29=pam4:-16:60:0:3:0:0 +serdes_tx_taps_30=pam4:-16:60:0:3:0:0 +serdes_tx_taps_31=pam4:-16:60:0:3:0:0 +serdes_tx_taps_32=pam4:-16:60:0:3:0:0 +serdes_tx_taps_33=nrz:0:71:-16:-5:0:0 +serdes_tx_taps_34=nrz:0:71:-16:-5:0:0 +serdes_tx_taps_35=nrz:0:78:-22:-4:0:0 +serdes_tx_taps_36=nrz:0:78:-22:-4:0:0 +serdes_tx_taps_37=nrz:0:72:-18:-5:0:0 +serdes_tx_taps_38=nrz:0:72:-18:-5:0:0 +serdes_tx_taps_39=nrz:0:68:-17:-6:0:0 +serdes_tx_taps_40=nrz:0:68:-17:-6:0:0 + +ucode_port_100.BCM8869X=RCY_MIRROR.0:core_0.100 +ucode_port_101.BCM8869X=RCY_MIRROR.1:core_0.101 +ucode_port_102.BCM8869X=RCY_MIRROR.2:core_0.102 +ucode_port_103.BCM8869X=RCY_MIRROR.3:core_0.103 +ucode_port_104.BCM8869X=RCY_MIRROR.4:core_0.104 +ucode_port_105.BCM8869X=RCY_MIRROR.5:core_0.105 +ucode_port_106.BCM8869X=RCY_MIRROR.6:core_0.106 +ucode_port_107.BCM8869X=RCY_MIRROR.7:core_0.107 +ucode_port_108.BCM8869X=RCY_MIRROR.8:core_0.108 +ucode_port_109.BCM8869X=RCY_MIRROR.9:core_0.109 +ucode_port_110.BCM8869X=RCY_MIRROR.10:core_0.110 +ucode_port_111.BCM8869X=RCY_MIRROR.11:core_0.111 +ucode_port_112.BCM8869X=RCY_MIRROR.12:core_0.112 +ucode_port_113.BCM8869X=RCY_MIRROR.13:core_0.113 +ucode_port_114.BCM8869X=RCY_MIRROR.14:core_0.114 +ucode_port_115.BCM8869X=RCY_MIRROR.15:core_0.115 +ucode_port_116.BCM8869X=RCY_MIRROR.16:core_0.116 +ucode_port_117.BCM8869X=RCY_MIRROR.17:core_0.117 +ucode_port_118.BCM8869X=RCY_MIRROR.18:core_0.118 +ucode_port_119.BCM8869X=RCY_MIRROR.19:core_0.119 +ucode_port_120.BCM8869X=RCY_MIRROR.0:core_1.120 +ucode_port_121.BCM8869X=RCY_MIRROR.1:core_1.121 +ucode_port_122.BCM8869X=RCY_MIRROR.2:core_1.122 +ucode_port_123.BCM8869X=RCY_MIRROR.3:core_1.123 +ucode_port_124.BCM8869X=RCY_MIRROR.4:core_1.124 +ucode_port_125.BCM8869X=RCY_MIRROR.5:core_1.125 +ucode_port_126.BCM8869X=RCY_MIRROR.6:core_1.126 +ucode_port_127.BCM8869X=RCY_MIRROR.7:core_1.127 +ucode_port_128.BCM8869X=RCY_MIRROR.8:core_1.128 +ucode_port_129.BCM8869X=RCY_MIRROR.9:core_1.129 +ucode_port_130.BCM8869X=RCY_MIRROR.10:core_1.130 +ucode_port_131.BCM8869X=RCY_MIRROR.11:core_1.131 +ucode_port_132.BCM8869X=RCY_MIRROR.12:core_1.132 +ucode_port_133.BCM8869X=RCY_MIRROR.13:core_1.133 +ucode_port_134.BCM8869X=RCY_MIRROR.14:core_1.134 +ucode_port_135.BCM8869X=RCY_MIRROR.15:core_1.135 +ucode_port_136.BCM8869X=RCY_MIRROR.16:core_1.136 +ucode_port_137.BCM8869X=RCY_MIRROR.17:core_1.137 +ucode_port_138.BCM8869X=RCY_MIRROR.18:core_1.138 +ucode_port_139.BCM8869X=RCY_MIRROR.19:core_1.139 + +port_priorities.BCM8869X=8 + +ucode_port_240.BCM8869X=OLP:core_0.240 + +sw_state_max_size.BCM8869X=750000000 + +stable_location.BCM8869X=4 +stable_location.BCM8869X_ADAPTER=3 + +stable_filename.BCM8869X_ADAPTER=warmboot_data_0 +stable_filename=/dev/shm/warmboot_data_0 +stable_filename.1=/dev/shm/warmboot_data_1 +stable_filename.2=/dev/shm/warmboot_data_2 + +stable_size.BCM8869X=800000000 + +tm_port_header_type_in_0.BCM8869X=INJECTED_2 +tm_port_header_type_out_0.BCM8869X=CPU + +tm_port_header_type_in_200.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_200.BCM8869X=ETH +tm_port_header_type_in_201.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_201.BCM8869X=ETH +tm_port_header_type_in_202.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_202.BCM8869X=ETH +tm_port_header_type_in_203.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_203.BCM8869X=ETH + +sat_enable.BCM8869X=1 +tm_port_header_type_out_210.BCM8869X=CPU +tm_port_header_type_in_210.BCM8869X=INJECTED_2 + +tm_port_header_type_in_211.BCM8869X=INJECTED_2 +tm_port_header_type_out_211.BCM8869X=CPU +tm_port_header_type_in_212.BCM8869X=INJECTED_2 +tm_port_header_type_out_212.BCM8869X=CPU + +tm_port_header_type_in_240.BCM8869X=INJECTED_2 +tm_port_header_type_out_240.BCM8869X=RAW + +dtm_flow_mapping_mode_region_64.BCM8869X=3 +dtm_flow_mapping_mode_region_65.BCM8869X=3 +dtm_flow_mapping_mode_region_66.BCM8869X=3 +dtm_flow_mapping_mode_region_67.BCM8869X=3 +dtm_flow_mapping_mode_region_68.BCM8869X=3 +dtm_flow_mapping_mode_region_69.BCM8869X=3 +dtm_flow_mapping_mode_region_70.BCM8869X=3 +dtm_flow_mapping_mode_region_71.BCM8869X=3 +dtm_flow_mapping_mode_region_72.BCM8869X=3 +dtm_flow_mapping_mode_region_73.BCM8869X=3 +dtm_flow_mapping_mode_region_74.BCM8869X=3 +dtm_flow_mapping_mode_region_75.BCM8869X=3 +dtm_flow_mapping_mode_region_76.BCM8869X=3 +dtm_flow_mapping_mode_region_77.BCM8869X=3 +dtm_flow_mapping_mode_region_78.BCM8869X=3 +dtm_flow_mapping_mode_region_79.BCM8869X=7 +dtm_flow_mapping_mode_region_80.BCM8869X=3 +dtm_flow_mapping_mode_region_81.BCM8869X=1 +dtm_flow_mapping_mode_region_82.BCM8869X=3 +dtm_flow_mapping_mode_region_83.BCM8869X=3 +dtm_flow_mapping_mode_region_84.BCM8869X=3 +dtm_flow_mapping_mode_region_85.BCM8869X=3 +dtm_flow_mapping_mode_region_86.BCM8869X=3 +dtm_flow_mapping_mode_region_87.BCM8869X=3 +dtm_flow_mapping_mode_region_88.BCM8869X=3 +dtm_flow_mapping_mode_region_89.BCM8869X=3 +dtm_flow_mapping_mode_region_90.BCM8869X=3 +dtm_flow_mapping_mode_region_91.BCM8869X=3 +dtm_flow_mapping_mode_region_92.BCM8869X=3 +dtm_flow_mapping_mode_region_93.BCM8869X=3 +dtm_flow_mapping_mode_region_94.BCM8869X=3 + +dtm_flow_nof_remote_cores_region_1.BCM8869X=2 +dtm_flow_nof_remote_cores_region_2.BCM8869X=2 +dtm_flow_nof_remote_cores_region_3.BCM8869X=2 +dtm_flow_nof_remote_cores_region_4.BCM8869X=2 +dtm_flow_nof_remote_cores_region_5.BCM8869X=2 +dtm_flow_nof_remote_cores_region_6.BCM8869X=2 +dtm_flow_nof_remote_cores_region_7.BCM8869X=2 +dtm_flow_nof_remote_cores_region_8.BCM8869X=2 +dtm_flow_nof_remote_cores_region_9.BCM8869X=2 +dtm_flow_nof_remote_cores_region_10.BCM8869X=2 +dtm_flow_nof_remote_cores_region_11.BCM8869X=2 +dtm_flow_nof_remote_cores_region_12.BCM8869X=2 +dtm_flow_nof_remote_cores_region_13.BCM8869X=2 +dtm_flow_nof_remote_cores_region_14.BCM8869X=2 +dtm_flow_nof_remote_cores_region_15.BCM8869X=2 +dtm_flow_nof_remote_cores_region_16.BCM8869X=2 +dtm_flow_nof_remote_cores_region_17.BCM8869X=2 +dtm_flow_nof_remote_cores_region_18.BCM8869X=2 +dtm_flow_nof_remote_cores_region_19.BCM8869X=2 +dtm_flow_nof_remote_cores_region_20.BCM8869X=2 +dtm_flow_nof_remote_cores_region_21.BCM8869X=2 +dtm_flow_nof_remote_cores_region_22.BCM8869X=2 +dtm_flow_nof_remote_cores_region_23.BCM8869X=2 +dtm_flow_nof_remote_cores_region_24.BCM8869X=2 +dtm_flow_nof_remote_cores_region_25.BCM8869X=2 +dtm_flow_nof_remote_cores_region_26.BCM8869X=2 +dtm_flow_nof_remote_cores_region_27.BCM8869X=2 +dtm_flow_nof_remote_cores_region_28.BCM8869X=2 +dtm_flow_nof_remote_cores_region_29.BCM8869X=2 +dtm_flow_nof_remote_cores_region_30.BCM8869X=2 +dtm_flow_nof_remote_cores_region_31.BCM8869X=2 +dtm_flow_nof_remote_cores_region_32.BCM8869X=2 +dtm_flow_nof_remote_cores_region_33.BCM8869X=2 +dtm_flow_nof_remote_cores_region_34.BCM8869X=2 +dtm_flow_nof_remote_cores_region_35.BCM8869X=2 +dtm_flow_nof_remote_cores_region_36.BCM8869X=2 +dtm_flow_nof_remote_cores_region_37.BCM8869X=2 +dtm_flow_nof_remote_cores_region_38.BCM8869X=2 +dtm_flow_nof_remote_cores_region_39.BCM8869X=2 +dtm_flow_nof_remote_cores_region_40.BCM8869X=2 +dtm_flow_nof_remote_cores_region_41.BCM8869X=2 +dtm_flow_nof_remote_cores_region_42.BCM8869X=2 +dtm_flow_nof_remote_cores_region_43.BCM8869X=2 +dtm_flow_nof_remote_cores_region_44.BCM8869X=2 +dtm_flow_nof_remote_cores_region_45.BCM8869X=2 +dtm_flow_nof_remote_cores_region_46.BCM8869X=2 +dtm_flow_nof_remote_cores_region_47.BCM8869X=2 +dtm_flow_nof_remote_cores_region_48.BCM8869X=2 +dtm_flow_nof_remote_cores_region_49.BCM8869X=2 +dtm_flow_nof_remote_cores_region_50.BCM8869X=2 +dtm_flow_nof_remote_cores_region_51.BCM8869X=2 +dtm_flow_nof_remote_cores_region_52.BCM8869X=2 +dtm_flow_nof_remote_cores_region_53.BCM8869X=2 +dtm_flow_nof_remote_cores_region_54.BCM8869X=2 +dtm_flow_nof_remote_cores_region_55.BCM8869X=2 +dtm_flow_nof_remote_cores_region_56.BCM8869X=2 +dtm_flow_nof_remote_cores_region_57.BCM8869X=2 +dtm_flow_nof_remote_cores_region_58.BCM8869X=2 +dtm_flow_nof_remote_cores_region_59.BCM8869X=2 +dtm_flow_nof_remote_cores_region_60.BCM8869X=2 + +mdb_profile.BCM8869X=l3-xl + +outlif_logical_to_physical_phase_map_1=S1 +outlif_logical_to_physical_phase_map_2=L1 +outlif_logical_to_physical_phase_map_3=XL +outlif_logical_to_physical_phase_map_4=L2 +outlif_logical_to_physical_phase_map_5=M1 +outlif_logical_to_physical_phase_map_6=M2 +outlif_logical_to_physical_phase_map_7=M3 +outlif_logical_to_physical_phase_map_8=S2 + +outlif_physical_phase_data_granularity_S1=60 +outlif_physical_phase_data_granularity_S2=60 +outlif_physical_phase_data_granularity_M1=60 +outlif_physical_phase_data_granularity_M2=60 +outlif_physical_phase_data_granularity_M3=60 +outlif_physical_phase_data_granularity_L1=60 +outlif_physical_phase_data_granularity_L2=60 +outlif_physical_phase_data_granularity_XL=60 + +port_init_speed_fabric.BCM8869X=53125 + +fabric_connect_mode.BCM8869X=SINGLE_FAP +protocol_traps_mode.BCM8869X=IN_LIF + +schan_intr_enable.BCM8869X=0 +tdma_intr_enable.BCM8869X=0 +tslam_intr_enable.BCM8869X=0 +miim_intr_enable.BCM8869X=0 +schan_timeout_usec.BCM8869X=300000 +tdma_timeout_usec.BCM8869X=1000000 +tslam_timeout_usec.BCM8869X=1000000 + +appl_enable_intr_init.BCM8869X=1 +polled_irq_mode.BCM8869X=1 +polled_irq_delay.BCM8869X=1000 + +bcm_stat_interval.BCM8869X=1000 + +mem_cache_enable_ecc.BCM8869X=1 +mem_cache_enable_parity.BCM8869X=1 + +serdes_nif_clk_freq_in.BCM8869X_A0=2 +serdes_nif_clk_freq_out.BCM8869X_A0=1 +serdes_fabric_clk_freq_in.BCM8869X_A0=2 +serdes_fabric_clk_freq_out.BCM8869X_A0=1 + +serdes_nif_clk_freq_in.BCM8869X=1 +serdes_nif_clk_freq_out.BCM8869X=bypass +serdes_fabric_clk_freq_in.BCM8869X=1 +serdes_fabric_clk_freq_out.BCM8869X=bypass + +dram_phy_tune_mode_on_init.BCM8869X=RUN_TUNE + +dport_map_direct.BCM8869X=1 + +pmf_sexem3_stage.BCM8869X=IPMF3 + +lane_to_serdes_map_fabric_lane0.0=rx0:tx0 +lane_to_serdes_map_fabric_lane1.0=rx1:tx1 +lane_to_serdes_map_fabric_lane2.0=rx2:tx2 +lane_to_serdes_map_fabric_lane3.0=rx3:tx3 +lane_to_serdes_map_fabric_lane4.0=rx4:tx4 +lane_to_serdes_map_fabric_lane5.0=rx5:tx5 +lane_to_serdes_map_fabric_lane6.0=rx6:tx6 +lane_to_serdes_map_fabric_lane7.0=rx7:tx7 +lane_to_serdes_map_fabric_lane8.0=rx8:tx8 +lane_to_serdes_map_fabric_lane9.0=rx9:tx9 +lane_to_serdes_map_fabric_lane10.0=rx10:tx10 +lane_to_serdes_map_fabric_lane11.0=rx11:tx11 +lane_to_serdes_map_fabric_lane12.0=rx12:tx12 +lane_to_serdes_map_fabric_lane13.0=rx13:tx13 +lane_to_serdes_map_fabric_lane14.0=rx14:tx14 +lane_to_serdes_map_fabric_lane15.0=rx15:tx15 +lane_to_serdes_map_fabric_lane16.0=rx16:tx16 +lane_to_serdes_map_fabric_lane17.0=rx17:tx17 +lane_to_serdes_map_fabric_lane18.0=rx18:tx18 +lane_to_serdes_map_fabric_lane19.0=rx19:tx19 +lane_to_serdes_map_fabric_lane20.0=rx20:tx20 +lane_to_serdes_map_fabric_lane21.0=rx21:tx21 +lane_to_serdes_map_fabric_lane22.0=rx22:tx22 +lane_to_serdes_map_fabric_lane23.0=rx23:tx23 +lane_to_serdes_map_fabric_lane24.0=rx24:tx24 +lane_to_serdes_map_fabric_lane25.0=rx25:tx25 +lane_to_serdes_map_fabric_lane26.0=rx26:tx26 +lane_to_serdes_map_fabric_lane27.0=rx27:tx27 +lane_to_serdes_map_fabric_lane28.0=rx28:tx28 +lane_to_serdes_map_fabric_lane29.0=rx29:tx29 +lane_to_serdes_map_fabric_lane30.0=rx30:tx30 +lane_to_serdes_map_fabric_lane31.0=rx31:tx31 +lane_to_serdes_map_fabric_lane32.0=rx32:tx32 +lane_to_serdes_map_fabric_lane33.0=rx33:tx33 +lane_to_serdes_map_fabric_lane34.0=rx34:tx34 +lane_to_serdes_map_fabric_lane35.0=rx35:tx35 +lane_to_serdes_map_fabric_lane36.0=rx36:tx36 +lane_to_serdes_map_fabric_lane37.0=rx37:tx37 +lane_to_serdes_map_fabric_lane38.0=rx38:tx38 +lane_to_serdes_map_fabric_lane39.0=rx39:tx39 +lane_to_serdes_map_fabric_lane40.0=rx40:tx40 +lane_to_serdes_map_fabric_lane41.0=rx41:tx41 +lane_to_serdes_map_fabric_lane42.0=rx42:tx42 +lane_to_serdes_map_fabric_lane43.0=rx43:tx43 +lane_to_serdes_map_fabric_lane44.0=rx44:tx44 +lane_to_serdes_map_fabric_lane45.0=rx45:tx45 +lane_to_serdes_map_fabric_lane46.0=rx46:tx46 +lane_to_serdes_map_fabric_lane47.0=rx47:tx47 +lane_to_serdes_map_fabric_lane48.0=rx48:tx48 +lane_to_serdes_map_fabric_lane49.0=rx49:tx49 +lane_to_serdes_map_fabric_lane50.0=rx50:tx50 +lane_to_serdes_map_fabric_lane51.0=rx51:tx51 +lane_to_serdes_map_fabric_lane52.0=rx52:tx52 +lane_to_serdes_map_fabric_lane53.0=rx53:tx53 +lane_to_serdes_map_fabric_lane54.0=rx54:tx54 +lane_to_serdes_map_fabric_lane55.0=rx55:tx55 +lane_to_serdes_map_fabric_lane56.0=rx56:tx56 +lane_to_serdes_map_fabric_lane57.0=rx57:tx57 +lane_to_serdes_map_fabric_lane58.0=rx58:tx58 +lane_to_serdes_map_fabric_lane59.0=rx59:tx59 +lane_to_serdes_map_fabric_lane60.0=rx60:tx60 +lane_to_serdes_map_fabric_lane61.0=rx61:tx61 +lane_to_serdes_map_fabric_lane62.0=rx62:tx62 +lane_to_serdes_map_fabric_lane63.0=rx63:tx63 +lane_to_serdes_map_fabric_lane64.0=rx64:tx64 +lane_to_serdes_map_fabric_lane65.0=rx65:tx65 +lane_to_serdes_map_fabric_lane66.0=rx66:tx66 +lane_to_serdes_map_fabric_lane67.0=rx67:tx67 +lane_to_serdes_map_fabric_lane68.0=rx68:tx68 +lane_to_serdes_map_fabric_lane69.0=rx69:tx69 +lane_to_serdes_map_fabric_lane70.0=rx70:tx70 +lane_to_serdes_map_fabric_lane71.0=rx71:tx71 +lane_to_serdes_map_fabric_lane72.0=rx72:tx72 +lane_to_serdes_map_fabric_lane73.0=rx73:tx73 +lane_to_serdes_map_fabric_lane74.0=rx74:tx74 +lane_to_serdes_map_fabric_lane75.0=rx75:tx75 +lane_to_serdes_map_fabric_lane76.0=rx76:tx76 +lane_to_serdes_map_fabric_lane77.0=rx77:tx77 +lane_to_serdes_map_fabric_lane78.0=rx78:tx78 +lane_to_serdes_map_fabric_lane79.0=rx79:tx79 +lane_to_serdes_map_fabric_lane80.0=rx80:tx80 +lane_to_serdes_map_fabric_lane81.0=rx81:tx81 +lane_to_serdes_map_fabric_lane82.0=rx82:tx82 +lane_to_serdes_map_fabric_lane83.0=rx83:tx83 +lane_to_serdes_map_fabric_lane84.0=rx84:tx84 +lane_to_serdes_map_fabric_lane85.0=rx85:tx85 +lane_to_serdes_map_fabric_lane86.0=rx86:tx86 +lane_to_serdes_map_fabric_lane87.0=rx87:tx87 +lane_to_serdes_map_fabric_lane88.0=rx88:tx88 +lane_to_serdes_map_fabric_lane89.0=rx89:tx89 +lane_to_serdes_map_fabric_lane90.0=rx90:tx90 +lane_to_serdes_map_fabric_lane91.0=rx91:tx91 +lane_to_serdes_map_fabric_lane92.0=rx92:tx92 +lane_to_serdes_map_fabric_lane93.0=rx93:tx93 +lane_to_serdes_map_fabric_lane94.0=rx94:tx94 +lane_to_serdes_map_fabric_lane95.0=rx95:tx95 +lane_to_serdes_map_fabric_lane96.0=rx96:tx96 +lane_to_serdes_map_fabric_lane97.0=rx97:tx97 +lane_to_serdes_map_fabric_lane98.0=rx98:tx98 +lane_to_serdes_map_fabric_lane99.0=rx99:tx99 +lane_to_serdes_map_fabric_lane100.0=rx100:tx100 +lane_to_serdes_map_fabric_lane101.0=rx101:tx101 +lane_to_serdes_map_fabric_lane102.0=rx102:tx102 +lane_to_serdes_map_fabric_lane103.0=rx103:tx103 +lane_to_serdes_map_fabric_lane104.0=rx104:tx104 +lane_to_serdes_map_fabric_lane105.0=rx105:tx105 +lane_to_serdes_map_fabric_lane106.0=rx106:tx106 +lane_to_serdes_map_fabric_lane107.0=rx107:tx107 +lane_to_serdes_map_fabric_lane108.0=rx108:tx108 +lane_to_serdes_map_fabric_lane109.0=rx109:tx109 +lane_to_serdes_map_fabric_lane110.0=rx110:tx110 +lane_to_serdes_map_fabric_lane111.0=rx111:tx111 + +lane_to_serdes_map_nif_lane0.0=rx5:tx7 +lane_to_serdes_map_nif_lane1.0=rx7:tx6 +lane_to_serdes_map_nif_lane2.0=rx4:tx5 +lane_to_serdes_map_nif_lane3.0=rx6:tx4 +lane_to_serdes_map_nif_lane4.0=rx0:tx0 +lane_to_serdes_map_nif_lane5.0=rx1:tx1 +lane_to_serdes_map_nif_lane6.0=rx2:tx3 +lane_to_serdes_map_nif_lane7.0=rx3:tx2 +lane_to_serdes_map_nif_lane8.0=rx13:tx15 +lane_to_serdes_map_nif_lane9.0=rx12:tx14 +lane_to_serdes_map_nif_lane10.0=rx15:tx13 +lane_to_serdes_map_nif_lane11.0=rx14:tx12 +lane_to_serdes_map_nif_lane12.0=rx10:tx10 +lane_to_serdes_map_nif_lane13.0=rx8:tx9 +lane_to_serdes_map_nif_lane14.0=rx9:tx11 +lane_to_serdes_map_nif_lane15.0=rx11:tx8 +lane_to_serdes_map_nif_lane16.0=rx23:tx23 +lane_to_serdes_map_nif_lane17.0=rx21:tx22 +lane_to_serdes_map_nif_lane18.0=rx22:tx21 +lane_to_serdes_map_nif_lane19.0=rx20:tx20 +lane_to_serdes_map_nif_lane20.0=rx16:tx18 +lane_to_serdes_map_nif_lane21.0=rx17:tx17 +lane_to_serdes_map_nif_lane22.0=rx18:tx16 +lane_to_serdes_map_nif_lane23.0=rx19:tx19 +lane_to_serdes_map_nif_lane24.0=rx31:tx31 +lane_to_serdes_map_nif_lane25.0=rx30:tx30 +lane_to_serdes_map_nif_lane26.0=rx29:tx29 +lane_to_serdes_map_nif_lane27.0=rx28:tx28 +lane_to_serdes_map_nif_lane28.0=rx24:tx26 +lane_to_serdes_map_nif_lane29.0=rx26:tx25 +lane_to_serdes_map_nif_lane30.0=rx25:tx24 +lane_to_serdes_map_nif_lane31.0=rx27:tx27 +lane_to_serdes_map_nif_lane32.0=rx38:tx34 +lane_to_serdes_map_nif_lane33.0=rx34:tx39 +lane_to_serdes_map_nif_lane34.0=rx39:tx33 +lane_to_serdes_map_nif_lane35.0=rx32:tx38 +lane_to_serdes_map_nif_lane36.0=rx36:tx35 +lane_to_serdes_map_nif_lane37.0=rx33:tx37 +lane_to_serdes_map_nif_lane38.0=rx37:tx32 +lane_to_serdes_map_nif_lane39.0=rx35:tx36 +lane_to_serdes_map_nif_lane40.0=rx46:tx41 +lane_to_serdes_map_nif_lane41.0=rx41:tx46 +lane_to_serdes_map_nif_lane42.0=rx45:tx42 +lane_to_serdes_map_nif_lane43.0=rx40:tx47 +lane_to_serdes_map_nif_lane44.0=rx47:tx40 +lane_to_serdes_map_nif_lane45.0=rx43:tx44 +lane_to_serdes_map_nif_lane46.0=rx44:tx43 +lane_to_serdes_map_nif_lane47.0=rx42:tx45 +lane_to_serdes_map_nif_lane48.0=rx55:tx55 +lane_to_serdes_map_nif_lane49.0=rx54:tx54 +lane_to_serdes_map_nif_lane50.0=rx53:tx53 +lane_to_serdes_map_nif_lane51.0=rx52:tx52 +lane_to_serdes_map_nif_lane52.0=rx48:tx48 +lane_to_serdes_map_nif_lane53.0=rx49:tx49 +lane_to_serdes_map_nif_lane54.0=rx50:tx50 +lane_to_serdes_map_nif_lane55.0=rx51:tx51 +lane_to_serdes_map_nif_lane56.0=rx60:tx60 +lane_to_serdes_map_nif_lane57.0=rx61:tx61 +lane_to_serdes_map_nif_lane58.0=rx62:tx63 +lane_to_serdes_map_nif_lane59.0=rx63:tx62 +lane_to_serdes_map_nif_lane60.0=rx58:tx59 +lane_to_serdes_map_nif_lane61.0=rx59:tx56 +lane_to_serdes_map_nif_lane62.0=rx57:tx58 +lane_to_serdes_map_nif_lane63.0=rx56:tx57 +lane_to_serdes_map_nif_lane64.0=rx68:tx69 +lane_to_serdes_map_nif_lane65.0=rx69:tx68 +lane_to_serdes_map_nif_lane66.0=rx70:tx71 +lane_to_serdes_map_nif_lane67.0=rx71:tx70 +lane_to_serdes_map_nif_lane68.0=rx67:tx64 +lane_to_serdes_map_nif_lane69.0=rx66:tx67 +lane_to_serdes_map_nif_lane70.0=rx65:tx65 +lane_to_serdes_map_nif_lane71.0=rx64:tx66 +lane_to_serdes_map_nif_lane72.0=rx78:tx76 +lane_to_serdes_map_nif_lane73.0=rx76:tx77 +lane_to_serdes_map_nif_lane74.0=rx79:tx78 +lane_to_serdes_map_nif_lane75.0=rx77:tx79 +lane_to_serdes_map_nif_lane76.0=rx75:tx72 +lane_to_serdes_map_nif_lane77.0=rx74:tx75 +lane_to_serdes_map_nif_lane78.0=rx73:tx73 +lane_to_serdes_map_nif_lane79.0=rx72:tx74 +lane_to_serdes_map_nif_lane80.0=rx83:tx84 +lane_to_serdes_map_nif_lane81.0=rx87:tx80 +lane_to_serdes_map_nif_lane82.0=rx82:tx85 +lane_to_serdes_map_nif_lane83.0=rx84:tx83 +lane_to_serdes_map_nif_lane84.0=rx80:tx86 +lane_to_serdes_map_nif_lane85.0=rx85:tx81 +lane_to_serdes_map_nif_lane86.0=rx81:tx87 +lane_to_serdes_map_nif_lane87.0=rx86:tx82 +lane_to_serdes_map_nif_lane88.0=rx90:tx93 +lane_to_serdes_map_nif_lane89.0=rx88:tx91 +lane_to_serdes_map_nif_lane90.0=rx91:tx92 +lane_to_serdes_map_nif_lane91.0=rx95:tx88 +lane_to_serdes_map_nif_lane92.0=rx94:tx95 +lane_to_serdes_map_nif_lane93.0=rx93:tx90 +lane_to_serdes_map_nif_lane94.0=rx89:tx94 +lane_to_serdes_map_nif_lane95.0=rx92:tx89 + +phy_rx_polarity_flip_phy0=0 +phy_rx_polarity_flip_phy1=1 +phy_rx_polarity_flip_phy2=0 +phy_rx_polarity_flip_phy3=0 +phy_rx_polarity_flip_phy4=0 +phy_rx_polarity_flip_phy5=0 +phy_rx_polarity_flip_phy6=0 +phy_rx_polarity_flip_phy7=0 +phy_rx_polarity_flip_phy8=1 +phy_rx_polarity_flip_phy9=1 +phy_rx_polarity_flip_phy10=1 +phy_rx_polarity_flip_phy11=1 +phy_rx_polarity_flip_phy12=0 +phy_rx_polarity_flip_phy13=1 +phy_rx_polarity_flip_phy14=1 +phy_rx_polarity_flip_phy15=1 +phy_rx_polarity_flip_phy16=0 +phy_rx_polarity_flip_phy17=1 +phy_rx_polarity_flip_phy18=1 +phy_rx_polarity_flip_phy19=0 +phy_rx_polarity_flip_phy20=0 +phy_rx_polarity_flip_phy21=0 +phy_rx_polarity_flip_phy22=0 +phy_rx_polarity_flip_phy23=0 +phy_rx_polarity_flip_phy24=1 +phy_rx_polarity_flip_phy25=1 +phy_rx_polarity_flip_phy26=1 +phy_rx_polarity_flip_phy27=0 +phy_rx_polarity_flip_phy28=0 +phy_rx_polarity_flip_phy29=1 +phy_rx_polarity_flip_phy30=1 +phy_rx_polarity_flip_phy31=0 +phy_rx_polarity_flip_phy32=1 +phy_rx_polarity_flip_phy33=0 +phy_rx_polarity_flip_phy34=0 +phy_rx_polarity_flip_phy35=0 +phy_rx_polarity_flip_phy36=0 +phy_rx_polarity_flip_phy37=1 +phy_rx_polarity_flip_phy38=0 +phy_rx_polarity_flip_phy39=1 + +phy_rx_polarity_flip_phy40=1 +phy_rx_polarity_flip_phy41=1 +phy_rx_polarity_flip_phy42=0 +phy_rx_polarity_flip_phy43=0 +phy_rx_polarity_flip_phy44=1 +phy_rx_polarity_flip_phy45=0 +phy_rx_polarity_flip_phy46=1 +phy_rx_polarity_flip_phy47=0 + +phy_rx_polarity_flip_phy48=1 +phy_rx_polarity_flip_phy49=1 +phy_rx_polarity_flip_phy50=1 +phy_rx_polarity_flip_phy51=1 +phy_rx_polarity_flip_phy52=0 +phy_rx_polarity_flip_phy53=0 +phy_rx_polarity_flip_phy54=0 +phy_rx_polarity_flip_phy55=0 +phy_rx_polarity_flip_phy56=0 +phy_rx_polarity_flip_phy57=0 +phy_rx_polarity_flip_phy58=0 +phy_rx_polarity_flip_phy59=0 +phy_rx_polarity_flip_phy60=1 +phy_rx_polarity_flip_phy61=1 +phy_rx_polarity_flip_phy62=1 +phy_rx_polarity_flip_phy63=1 +phy_rx_polarity_flip_phy64=1 +phy_rx_polarity_flip_phy65=1 +phy_rx_polarity_flip_phy66=1 +phy_rx_polarity_flip_phy67=1 +phy_rx_polarity_flip_phy68=1 +phy_rx_polarity_flip_phy69=1 +phy_rx_polarity_flip_phy70=1 +phy_rx_polarity_flip_phy71=1 +phy_rx_polarity_flip_phy72=1 +phy_rx_polarity_flip_phy73=0 +phy_rx_polarity_flip_phy74=0 +phy_rx_polarity_flip_phy75=1 +phy_rx_polarity_flip_phy76=1 +phy_rx_polarity_flip_phy77=1 +phy_rx_polarity_flip_phy78=1 +phy_rx_polarity_flip_phy79=1 + +phy_rx_polarity_flip_phy80=1 +phy_rx_polarity_flip_phy81=1 +phy_rx_polarity_flip_phy82=1 +phy_rx_polarity_flip_phy83=0 +phy_rx_polarity_flip_phy84=1 +phy_rx_polarity_flip_phy85=0 +phy_rx_polarity_flip_phy86=1 +phy_rx_polarity_flip_phy87=0 + +phy_rx_polarity_flip_phy88=1 +phy_rx_polarity_flip_phy89=0 +phy_rx_polarity_flip_phy90=0 +phy_rx_polarity_flip_phy91=1 +phy_rx_polarity_flip_phy92=1 +phy_rx_polarity_flip_phy93=0 +phy_rx_polarity_flip_phy94=0 +phy_rx_polarity_flip_phy95=1 + +phy_tx_polarity_flip_phy0=1 +phy_tx_polarity_flip_phy1=1 +phy_tx_polarity_flip_phy2=1 +phy_tx_polarity_flip_phy3=1 +phy_tx_polarity_flip_phy4=1 +phy_tx_polarity_flip_phy5=1 +phy_tx_polarity_flip_phy6=0 +phy_tx_polarity_flip_phy7=0 +phy_tx_polarity_flip_phy8=1 +phy_tx_polarity_flip_phy9=1 +phy_tx_polarity_flip_phy10=1 +phy_tx_polarity_flip_phy11=1 +phy_tx_polarity_flip_phy12=1 +phy_tx_polarity_flip_phy13=1 +phy_tx_polarity_flip_phy14=0 +phy_tx_polarity_flip_phy15=0 +phy_tx_polarity_flip_phy16=0 +phy_tx_polarity_flip_phy17=0 +phy_tx_polarity_flip_phy18=0 +phy_tx_polarity_flip_phy19=0 +phy_tx_polarity_flip_phy20=0 +phy_tx_polarity_flip_phy21=0 +phy_tx_polarity_flip_phy22=0 +phy_tx_polarity_flip_phy23=0 +phy_tx_polarity_flip_phy24=0 +phy_tx_polarity_flip_phy25=0 +phy_tx_polarity_flip_phy26=0 +phy_tx_polarity_flip_phy27=0 +phy_tx_polarity_flip_phy28=0 +phy_tx_polarity_flip_phy29=0 +phy_tx_polarity_flip_phy30=0 +phy_tx_polarity_flip_phy31=0 +phy_tx_polarity_flip_phy32=1 +phy_tx_polarity_flip_phy33=0 +phy_tx_polarity_flip_phy34=0 +phy_tx_polarity_flip_phy35=1 +phy_tx_polarity_flip_phy36=1 +phy_tx_polarity_flip_phy37=0 +phy_tx_polarity_flip_phy38=1 +phy_tx_polarity_flip_phy39=0 + +phy_tx_polarity_flip_phy40=0 +phy_tx_polarity_flip_phy41=1 +phy_tx_polarity_flip_phy42=1 +phy_tx_polarity_flip_phy43=0 +phy_tx_polarity_flip_phy44=1 +phy_tx_polarity_flip_phy45=0 +phy_tx_polarity_flip_phy46=1 +phy_tx_polarity_flip_phy47=0 + +phy_tx_polarity_flip_phy48=0 +phy_tx_polarity_flip_phy49=0 +phy_tx_polarity_flip_phy50=0 +phy_tx_polarity_flip_phy51=0 +phy_tx_polarity_flip_phy52=0 +phy_tx_polarity_flip_phy53=0 +phy_tx_polarity_flip_phy54=0 +phy_tx_polarity_flip_phy55=0 +phy_tx_polarity_flip_phy56=1 +phy_tx_polarity_flip_phy57=1 +phy_tx_polarity_flip_phy58=0 +phy_tx_polarity_flip_phy59=0 +phy_tx_polarity_flip_phy60=1 +phy_tx_polarity_flip_phy61=1 +phy_tx_polarity_flip_phy62=0 +phy_tx_polarity_flip_phy63=0 +phy_tx_polarity_flip_phy64=0 +phy_tx_polarity_flip_phy65=0 +phy_tx_polarity_flip_phy66=0 +phy_tx_polarity_flip_phy67=0 +phy_tx_polarity_flip_phy68=0 +phy_tx_polarity_flip_phy69=0 +phy_tx_polarity_flip_phy70=1 +phy_tx_polarity_flip_phy71=1 +phy_tx_polarity_flip_phy72=1 +phy_tx_polarity_flip_phy73=1 +phy_tx_polarity_flip_phy74=1 +phy_tx_polarity_flip_phy75=1 +phy_tx_polarity_flip_phy76=0 +phy_tx_polarity_flip_phy77=0 +phy_tx_polarity_flip_phy78=1 +phy_tx_polarity_flip_phy79=1 + +phy_tx_polarity_flip_phy80=1 +phy_tx_polarity_flip_phy81=1 +phy_tx_polarity_flip_phy82=0 +phy_tx_polarity_flip_phy83=0 +phy_tx_polarity_flip_phy84=1 +phy_tx_polarity_flip_phy85=1 +phy_tx_polarity_flip_phy86=1 +phy_tx_polarity_flip_phy87=1 + +phy_tx_polarity_flip_phy88=0 +phy_tx_polarity_flip_phy89=0 +phy_tx_polarity_flip_phy90=1 +phy_tx_polarity_flip_phy91=1 +phy_tx_polarity_flip_phy92=1 +phy_tx_polarity_flip_phy93=1 +phy_tx_polarity_flip_phy94=1 +phy_tx_polarity_flip_phy95=1 + +ucode_port_1=CGE2_0:core_0.1 +ucode_port_2=CGE2_1:core_0.2 +ucode_port_3=CGE2_2:core_0.3 +ucode_port_4=CGE2_3:core_0.4 +ucode_port_5=CGE2_4:core_0.5 +ucode_port_6=CGE2_5:core_0.6 +ucode_port_7=CGE2_6:core_0.7 +ucode_port_8=CGE2_7:core_0.8 +ucode_port_9=CGE2_8:core_0.9 +ucode_port_10=CGE2_9:core_0.10 +ucode_port_11=CGE2_10:core_0.11 +ucode_port_12=CGE2_11:core_0.12 +ucode_port_13=CGE2_12:core_0.13 +ucode_port_14=CGE2_13:core_0.14 +ucode_port_15=CGE2_14:core_0.15 +ucode_port_16=CGE2_15:core_0.16 +ucode_port_17=CGE2_36:core_1.17 +ucode_port_18=CGE2_37:core_1.18 +ucode_port_19=CGE2_38:core_1.19 +ucode_port_20=CGE2_39:core_1.20 +ucode_port_21=CGE2_32:core_1.21 +ucode_port_22=CGE2_33:core_1.22 +ucode_port_23=CGE2_34:core_1.23 +ucode_port_24=CGE2_35:core_1.24 +ucode_port_25=CGE2_28:core_1.25 +ucode_port_26=CGE2_29:core_1.26 +ucode_port_27=CGE2_30:core_1.27 +ucode_port_28=CGE2_31:core_1.28 +ucode_port_29=CGE2_24:core_1.29 +ucode_port_30=CGE2_25:core_1.30 +ucode_port_31=CGE2_26:core_1.31 +ucode_port_32=CGE2_27:core_1.32 + +port_fec_33=2 +port_fec_34=2 +port_fec_35=2 +port_fec_36=2 +port_fec_37=2 +port_fec_38=2 +port_fec_39=2 +port_fec_40=2 + +ucode_port_33=CGE8:core_0.33 +ucode_port_34=CGE9:core_0.34 +ucode_port_35=CGE10:core_0.35 +ucode_port_36=CGE11:core_0.36 +ucode_port_37=CGE22:core_1.37 +ucode_port_38=CGE23:core_1.38 +ucode_port_39=CGE20:core_1.39 +ucode_port_40=CGE21:core_1.40 + +rif_id_max=0x4000 + +dma_desc_aggregator_chain_length_max.BCM8869X=1000 +dma_desc_aggregator_buff_size_kb.BCM8869X=100 +dma_desc_aggregator_timeout_usec.BCM8869X=1000 +dma_desc_aggregator_enable_specific_MDB_LPM.BCM8869X=1 +dma_desc_aggregator_enable_specific_MDB_FEC.BCM8869X=1 diff --git a/device/arista/x86_64-arista_7280cr3_32d4/Arista-7280CR3-C40/port_config.ini b/device/arista/x86_64-arista_7280cr3_32d4/Arista-7280CR3-C40/port_config.ini new file mode 100644 index 000000000000..2ba638aee50d --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/Arista-7280CR3-C40/port_config.ini @@ -0,0 +1,41 @@ +# name lanes alias index speed +Ethernet0 0,1 Ethernet1/1 1 100000 +Ethernet4 2,3 Ethernet2/1 2 100000 +Ethernet8 4,5 Ethernet3/1 3 100000 +Ethernet12 6,7 Ethernet4/1 4 100000 +Ethernet16 8,9 Ethernet5/1 5 100000 +Ethernet20 10,11 Ethernet6/1 6 100000 +Ethernet24 12,13 Ethernet7/1 7 100000 +Ethernet28 14,15 Ethernet8/1 8 100000 +Ethernet32 16,17 Ethernet9/1 9 100000 +Ethernet36 18,19 Ethernet10/1 10 100000 +Ethernet40 20,21 Ethernet11/1 11 100000 +Ethernet44 22,23 Ethernet12/1 12 100000 +Ethernet48 24,25 Ethernet13/1 13 100000 +Ethernet52 26,27 Ethernet14/1 14 100000 +Ethernet56 28,29 Ethernet15/1 15 100000 +Ethernet60 30,31 Ethernet16/1 16 100000 +Ethernet64 72,73 Ethernet17/1 17 100000 +Ethernet68 74,75 Ethernet18/1 18 100000 +Ethernet72 76,77 Ethernet19/1 19 100000 +Ethernet76 78,79 Ethernet20/1 20 100000 +Ethernet80 64,65 Ethernet21/1 21 100000 +Ethernet84 66,67 Ethernet22/1 22 100000 +Ethernet88 68,69 Ethernet23/1 23 100000 +Ethernet92 70,71 Ethernet24/1 24 100000 +Ethernet96 56,57 Ethernet25/1 25 100000 +Ethernet100 58,59 Ethernet26/1 26 100000 +Ethernet104 60,61 Ethernet27/1 27 100000 +Ethernet108 62,63 Ethernet28/1 28 100000 +Ethernet112 48,49 Ethernet29/1 29 100000 +Ethernet116 50,51 Ethernet30/1 30 100000 +Ethernet120 52,53 Ethernet31/1 31 100000 +Ethernet124 54,55 Ethernet32/1 32 100000 +Ethernet128 32,33,34,35 Ethernet33/1 33 100000 +Ethernet132 36,37,38,39 Ethernet33/5 33 100000 +Ethernet136 40,41,42,43 Ethernet34/1 34 100000 +Ethernet140 44,45,46,47 Ethernet34/5 34 100000 +Ethernet144 88,89,90,91 Ethernet35/1 35 100000 +Ethernet148 92,93,94,95 Ethernet35/5 35 100000 +Ethernet152 80,81,82,83 Ethernet36/1 36 100000 +Ethernet156 84,85,86,87 Ethernet36/5 36 100000 diff --git a/device/arista/x86_64-arista_7280cr3_32d4/Arista-7280CR3-C40/sai.profile b/device/arista/x86_64-arista_7280cr3_32d4/Arista-7280CR3-C40/sai.profile new file mode 100644 index 000000000000..17ef703d798d --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/Arista-7280CR3-C40/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/jr2-a7280cr3-32d4-40x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7280cr3_32d4/default_sku b/device/arista/x86_64-arista_7280cr3_32d4/default_sku new file mode 100644 index 000000000000..a65e1f845ad3 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/default_sku @@ -0,0 +1 @@ +Arista-7280CR3-C32P4 t1 diff --git a/device/arista/x86_64-arista_7280cr3_32d4/fancontrol b/device/arista/x86_64-arista_7280cr3_32d4/fancontrol new file mode 120000 index 000000000000..6a53b7541071 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/fancontrol @@ -0,0 +1 @@ +../x86_64-arista_7280cr3_32p4/fancontrol \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32d4/platform.json b/device/arista/x86_64-arista_7280cr3_32d4/platform.json new file mode 100644 index 000000000000..39b91ddd0f63 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/platform.json @@ -0,0 +1,207 @@ +{ + "chassis": { + "name": "DCS-7280CR3K-32D4", + "components": [], + "fans": [], + "fan_drawers": [ + { + "name": "slot1", + "fans": [ + { + "name": "fan1" + }, + { + "name": "fan2" + } + ] + }, + { + "name": "slot2", + "fans": [ + { + "name": "fan3" + }, + { + "name": "fan4" + } + ] + }, + { + "name": "slot3", + "fans": [ + { + "name": "fan5" + }, + { + "name": "fan6" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Cpu temp sensor" + }, + { + "name": "CPU board temp sensor" + }, + { + "name": "Back-panel temp sensor" + }, + { + "name": "Board Sensor" + }, + { + "name": "Front Air" + }, + { + "name": "Rear Air" + }, + { + "name": "Fap 0 Core 0" + }, + { + "name": "Fap 0 Core 1" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 secondary hotspot sensor" + }, + { + "name": "Power supply 1 primary hotspot sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 secondary hotspot sensor" + }, + { + "name": "Power supply 2 primary hotspot sensor" + } + ], + "sfps": [ + { + "name": "qsfp1" + }, + { + "name": "qsfp2" + }, + { + "name": "qsfp3" + }, + { + "name": "qsfp4" + }, + { + "name": "qsfp5" + }, + { + "name": "qsfp6" + }, + { + "name": "qsfp7" + }, + { + "name": "qsfp8" + }, + { + "name": "qsfp9" + }, + { + "name": "qsfp10" + }, + { + "name": "qsfp11" + }, + { + "name": "qsfp12" + }, + { + "name": "qsfp13" + }, + { + "name": "qsfp14" + }, + { + "name": "qsfp15" + }, + { + "name": "qsfp16" + }, + { + "name": "qsfp17" + }, + { + "name": "qsfp18" + }, + { + "name": "qsfp19" + }, + { + "name": "qsfp20" + }, + { + "name": "qsfp21" + }, + { + "name": "qsfp22" + }, + { + "name": "qsfp23" + }, + { + "name": "qsfp24" + }, + { + "name": "qsfp25" + }, + { + "name": "qsfp26" + }, + { + "name": "qsfp27" + }, + { + "name": "qsfp28" + }, + { + "name": "qsfp29" + }, + { + "name": "qsfp30" + }, + { + "name": "qsfp31" + }, + { + "name": "qsfp32" + }, + { + "name": "osfp33" + }, + { + "name": "osfp34" + }, + { + "name": "osfp35" + }, + { + "name": "osfp36" + } + ] + }, + "interfaces": {} +} \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32d4/platform_reboot b/device/arista/x86_64-arista_7280cr3_32d4/platform_reboot new file mode 120000 index 000000000000..7f94a49e38b0 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/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_7280cr3_32d4/plugins b/device/arista/x86_64-arista_7280cr3_32d4/plugins new file mode 120000 index 000000000000..5fbbf98a6284 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/plugins @@ -0,0 +1 @@ +../x86_64-arista_common/plugins/ \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32d4/pmon_daemon_control.json b/device/arista/x86_64-arista_7280cr3_32d4/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32d4/sensors.conf b/device/arista/x86_64-arista_7280cr3_32d4/sensors.conf new file mode 120000 index 000000000000..0b3f7a039764 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/sensors.conf @@ -0,0 +1 @@ +../x86_64-arista_7280cr3_32p4/sensors.conf \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32d4/system_health_monitoring_config.json b/device/arista/x86_64-arista_7280cr3_32d4/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32d4/thermal_policy.json b/device/arista/x86_64-arista_7280cr3_32d4/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32d4/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C28S8/jr2-a7280cr3-32p4-28x100G-8x10G.config.bcm b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C28S8/jr2-a7280cr3-32p4-28x100G-8x10G.config.bcm new file mode 100644 index 000000000000..541e26302dc0 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C28S8/jr2-a7280cr3-32p4-28x100G-8x10G.config.bcm @@ -0,0 +1,741 @@ +soc_family.BCM8869X=BCM8869X + +custom_feature_ucode_path=u_code_db2pem.txt +system_headers_mode=1 +suppress_unknown_prop_warnings=1 +l4_protocols_load_balancing_enable=1 +fabric_logical_port_base=512 +trunk_group_max_members=128 +num_olp_tm_ports.BCM8869X=1 + +ucode_port_0.BCM8869X=CPU.0:core_0.0 +ucode_port_200.BCM8869X=CPU.8:core_1.200 +ucode_port_201.BCM8869X=CPU.16:core_0.201 +ucode_port_202.BCM8869X=CPU.24:core_1.202 +ucode_port_203.BCM8869X=CPU.32:core_0.203 + +port_init_speed_xe.BCM8869X=10000 +port_init_speed_xl.BCM8869X=40000 +port_init_speed_le.BCM8869X=50000 +port_init_speed_ce.BCM8869X=100000 +port_init_speed_cc.BCM8869X=200000 +port_init_speed_cd.BCM8869X=400000 +port_init_speed_il.BCM8869X=10312 + +port_init_cl72=0 + +serdes_tx_taps_1=pam4:-16:64:0:3:0:0 +serdes_tx_taps_2=pam4:-16:64:0:3:0:0 +serdes_tx_taps_3=pam4:-16:64:0:3:0:0 +serdes_tx_taps_4=pam4:-16:64:0:3:0:0 +serdes_tx_taps_5=pam4:-16:64:0:3:0:0 +serdes_tx_taps_6=pam4:-16:64:0:3:0:0 +serdes_tx_taps_7=pam4:-16:64:0:3:0:0 +serdes_tx_taps_8=pam4:-16:64:0:3:0:0 +serdes_tx_taps_9=pam4:-8:60:0:0:0:0 +serdes_tx_taps_10=pam4:-8:60:0:0:0:0 +serdes_tx_taps_11=pam4:-8:60:0:0:0:0 +serdes_tx_taps_12=pam4:-8:60:0:0:0:0 +serdes_tx_taps_13=pam4:-8:60:0:0:0:0 +serdes_tx_taps_14=pam4:-8:60:0:0:0:0 +serdes_tx_taps_15=pam4:-8:60:0:0:0:0 +serdes_tx_taps_16=pam4:-8:60:0:0:0:0 +serdes_tx_taps_17=pam4:-8:60:0:0:0:0 +serdes_tx_taps_18=pam4:-8:60:0:0:0:0 +serdes_tx_taps_19=pam4:-8:60:0:0:0:0 +serdes_tx_taps_20=pam4:-8:60:0:0:0:0 +serdes_tx_taps_21=pam4:-8:60:0:0:0:0 +serdes_tx_taps_22=pam4:-8:60:0:0:0:0 +serdes_tx_taps_23=pam4:-8:60:0:0:0:0 +serdes_tx_taps_24=pam4:-8:60:0:0:0:0 +serdes_tx_taps_25=pam4:-8:60:0:0:0:0 +serdes_tx_taps_26=pam4:-8:60:0:0:0:0 +serdes_tx_taps_27=pam4:-8:60:0:0:0:0 +serdes_tx_taps_28=pam4:-8:60:0:0:0:0 +serdes_tx_taps_29=nrz:0:127:0:0:0:0 +serdes_tx_taps_30=nrz:0:127:0:0:0:0 +serdes_tx_taps_31=nrz:0:127:0:0:0:0 +serdes_tx_taps_32=nrz:0:127:0:0:0:0 +serdes_tx_taps_33=nrz:0:127:0:0:0:0 +serdes_tx_taps_34=nrz:0:127:0:0:0:0 +serdes_tx_taps_35=nrz:0:127:0:0:0:0 +serdes_tx_taps_36=nrz:0:127:0:0:0:0 + +ucode_port_100.BCM8869X=RCY_MIRROR.0:core_0.100 +ucode_port_101.BCM8869X=RCY_MIRROR.1:core_0.101 +ucode_port_102.BCM8869X=RCY_MIRROR.2:core_0.102 +ucode_port_103.BCM8869X=RCY_MIRROR.3:core_0.103 +ucode_port_104.BCM8869X=RCY_MIRROR.4:core_0.104 +ucode_port_105.BCM8869X=RCY_MIRROR.5:core_0.105 +ucode_port_106.BCM8869X=RCY_MIRROR.6:core_0.106 +ucode_port_107.BCM8869X=RCY_MIRROR.7:core_0.107 +ucode_port_108.BCM8869X=RCY_MIRROR.8:core_0.108 +ucode_port_109.BCM8869X=RCY_MIRROR.9:core_0.109 +ucode_port_110.BCM8869X=RCY_MIRROR.10:core_0.110 +ucode_port_111.BCM8869X=RCY_MIRROR.11:core_0.111 +ucode_port_112.BCM8869X=RCY_MIRROR.12:core_0.112 +ucode_port_113.BCM8869X=RCY_MIRROR.13:core_0.113 +ucode_port_114.BCM8869X=RCY_MIRROR.14:core_0.114 +ucode_port_115.BCM8869X=RCY_MIRROR.15:core_0.115 +ucode_port_116.BCM8869X=RCY_MIRROR.16:core_0.116 +ucode_port_117.BCM8869X=RCY_MIRROR.17:core_0.117 +ucode_port_118.BCM8869X=RCY_MIRROR.18:core_0.118 +ucode_port_119.BCM8869X=RCY_MIRROR.19:core_0.119 +ucode_port_120.BCM8869X=RCY_MIRROR.0:core_1.120 +ucode_port_121.BCM8869X=RCY_MIRROR.1:core_1.121 +ucode_port_122.BCM8869X=RCY_MIRROR.2:core_1.122 +ucode_port_123.BCM8869X=RCY_MIRROR.3:core_1.123 +ucode_port_124.BCM8869X=RCY_MIRROR.4:core_1.124 +ucode_port_125.BCM8869X=RCY_MIRROR.5:core_1.125 +ucode_port_126.BCM8869X=RCY_MIRROR.6:core_1.126 +ucode_port_127.BCM8869X=RCY_MIRROR.7:core_1.127 +ucode_port_128.BCM8869X=RCY_MIRROR.8:core_1.128 +ucode_port_129.BCM8869X=RCY_MIRROR.9:core_1.129 +ucode_port_130.BCM8869X=RCY_MIRROR.10:core_1.130 +ucode_port_131.BCM8869X=RCY_MIRROR.11:core_1.131 +ucode_port_132.BCM8869X=RCY_MIRROR.12:core_1.132 +ucode_port_133.BCM8869X=RCY_MIRROR.13:core_1.133 +ucode_port_134.BCM8869X=RCY_MIRROR.14:core_1.134 +ucode_port_135.BCM8869X=RCY_MIRROR.15:core_1.135 +ucode_port_136.BCM8869X=RCY_MIRROR.16:core_1.136 +ucode_port_137.BCM8869X=RCY_MIRROR.17:core_1.137 +ucode_port_138.BCM8869X=RCY_MIRROR.18:core_1.138 +ucode_port_139.BCM8869X=RCY_MIRROR.19:core_1.139 + +port_priorities.BCM8869X=8 + +ucode_port_240.BCM8869X=OLP:core_0.240 + +sw_state_max_size.BCM8869X=750000000 + +stable_location.BCM8869X=4 +stable_location.BCM8869X_ADAPTER=3 + +stable_filename.BCM8869X_ADAPTER=warmboot_data_0 +stable_filename=/dev/shm/warmboot_data_0 +stable_filename.1=/dev/shm/warmboot_data_1 +stable_filename.2=/dev/shm/warmboot_data_2 + +stable_size.BCM8869X=800000000 + +tm_port_header_type_in_0.BCM8869X=INJECTED_2 +tm_port_header_type_out_0.BCM8869X=CPU + +tm_port_header_type_in_200.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_200.BCM8869X=ETH +tm_port_header_type_in_201.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_201.BCM8869X=ETH +tm_port_header_type_in_202.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_202.BCM8869X=ETH +tm_port_header_type_in_203.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_203.BCM8869X=ETH + +sat_enable.BCM8869X=1 +tm_port_header_type_out_210.BCM8869X=CPU +tm_port_header_type_in_210.BCM8869X=INJECTED_2 + +tm_port_header_type_in_211.BCM8869X=INJECTED_2 +tm_port_header_type_out_211.BCM8869X=CPU +tm_port_header_type_in_212.BCM8869X=INJECTED_2 +tm_port_header_type_out_212.BCM8869X=CPU + +tm_port_header_type_in_240.BCM8869X=INJECTED_2 +tm_port_header_type_out_240.BCM8869X=RAW + +dtm_flow_mapping_mode_region_64.BCM8869X=3 +dtm_flow_mapping_mode_region_65.BCM8869X=3 +dtm_flow_mapping_mode_region_66.BCM8869X=3 +dtm_flow_mapping_mode_region_67.BCM8869X=3 +dtm_flow_mapping_mode_region_68.BCM8869X=3 +dtm_flow_mapping_mode_region_69.BCM8869X=3 +dtm_flow_mapping_mode_region_70.BCM8869X=3 +dtm_flow_mapping_mode_region_71.BCM8869X=3 +dtm_flow_mapping_mode_region_72.BCM8869X=3 +dtm_flow_mapping_mode_region_73.BCM8869X=3 +dtm_flow_mapping_mode_region_74.BCM8869X=3 +dtm_flow_mapping_mode_region_75.BCM8869X=3 +dtm_flow_mapping_mode_region_76.BCM8869X=3 +dtm_flow_mapping_mode_region_77.BCM8869X=3 +dtm_flow_mapping_mode_region_78.BCM8869X=3 +dtm_flow_mapping_mode_region_79.BCM8869X=7 +dtm_flow_mapping_mode_region_80.BCM8869X=3 +dtm_flow_mapping_mode_region_81.BCM8869X=1 +dtm_flow_mapping_mode_region_82.BCM8869X=3 +dtm_flow_mapping_mode_region_83.BCM8869X=3 +dtm_flow_mapping_mode_region_84.BCM8869X=3 +dtm_flow_mapping_mode_region_85.BCM8869X=3 +dtm_flow_mapping_mode_region_86.BCM8869X=3 +dtm_flow_mapping_mode_region_87.BCM8869X=3 +dtm_flow_mapping_mode_region_88.BCM8869X=3 +dtm_flow_mapping_mode_region_89.BCM8869X=3 +dtm_flow_mapping_mode_region_90.BCM8869X=3 +dtm_flow_mapping_mode_region_91.BCM8869X=3 +dtm_flow_mapping_mode_region_92.BCM8869X=3 +dtm_flow_mapping_mode_region_93.BCM8869X=3 +dtm_flow_mapping_mode_region_94.BCM8869X=3 + +dtm_flow_nof_remote_cores_region_1.BCM8869X=2 +dtm_flow_nof_remote_cores_region_2.BCM8869X=2 +dtm_flow_nof_remote_cores_region_3.BCM8869X=2 +dtm_flow_nof_remote_cores_region_4.BCM8869X=2 +dtm_flow_nof_remote_cores_region_5.BCM8869X=2 +dtm_flow_nof_remote_cores_region_6.BCM8869X=2 +dtm_flow_nof_remote_cores_region_7.BCM8869X=2 +dtm_flow_nof_remote_cores_region_8.BCM8869X=2 +dtm_flow_nof_remote_cores_region_9.BCM8869X=2 +dtm_flow_nof_remote_cores_region_10.BCM8869X=2 +dtm_flow_nof_remote_cores_region_11.BCM8869X=2 +dtm_flow_nof_remote_cores_region_12.BCM8869X=2 +dtm_flow_nof_remote_cores_region_13.BCM8869X=2 +dtm_flow_nof_remote_cores_region_14.BCM8869X=2 +dtm_flow_nof_remote_cores_region_15.BCM8869X=2 +dtm_flow_nof_remote_cores_region_16.BCM8869X=2 +dtm_flow_nof_remote_cores_region_17.BCM8869X=2 +dtm_flow_nof_remote_cores_region_18.BCM8869X=2 +dtm_flow_nof_remote_cores_region_19.BCM8869X=2 +dtm_flow_nof_remote_cores_region_20.BCM8869X=2 +dtm_flow_nof_remote_cores_region_21.BCM8869X=2 +dtm_flow_nof_remote_cores_region_22.BCM8869X=2 +dtm_flow_nof_remote_cores_region_23.BCM8869X=2 +dtm_flow_nof_remote_cores_region_24.BCM8869X=2 +dtm_flow_nof_remote_cores_region_25.BCM8869X=2 +dtm_flow_nof_remote_cores_region_26.BCM8869X=2 +dtm_flow_nof_remote_cores_region_27.BCM8869X=2 +dtm_flow_nof_remote_cores_region_28.BCM8869X=2 +dtm_flow_nof_remote_cores_region_29.BCM8869X=2 +dtm_flow_nof_remote_cores_region_30.BCM8869X=2 +dtm_flow_nof_remote_cores_region_31.BCM8869X=2 +dtm_flow_nof_remote_cores_region_32.BCM8869X=2 +dtm_flow_nof_remote_cores_region_33.BCM8869X=2 +dtm_flow_nof_remote_cores_region_34.BCM8869X=2 +dtm_flow_nof_remote_cores_region_35.BCM8869X=2 +dtm_flow_nof_remote_cores_region_36.BCM8869X=2 +dtm_flow_nof_remote_cores_region_37.BCM8869X=2 +dtm_flow_nof_remote_cores_region_38.BCM8869X=2 +dtm_flow_nof_remote_cores_region_39.BCM8869X=2 +dtm_flow_nof_remote_cores_region_40.BCM8869X=2 +dtm_flow_nof_remote_cores_region_41.BCM8869X=2 +dtm_flow_nof_remote_cores_region_42.BCM8869X=2 +dtm_flow_nof_remote_cores_region_43.BCM8869X=2 +dtm_flow_nof_remote_cores_region_44.BCM8869X=2 +dtm_flow_nof_remote_cores_region_45.BCM8869X=2 +dtm_flow_nof_remote_cores_region_46.BCM8869X=2 +dtm_flow_nof_remote_cores_region_47.BCM8869X=2 +dtm_flow_nof_remote_cores_region_48.BCM8869X=2 +dtm_flow_nof_remote_cores_region_49.BCM8869X=2 +dtm_flow_nof_remote_cores_region_50.BCM8869X=2 +dtm_flow_nof_remote_cores_region_51.BCM8869X=2 +dtm_flow_nof_remote_cores_region_52.BCM8869X=2 +dtm_flow_nof_remote_cores_region_53.BCM8869X=2 +dtm_flow_nof_remote_cores_region_54.BCM8869X=2 +dtm_flow_nof_remote_cores_region_55.BCM8869X=2 +dtm_flow_nof_remote_cores_region_56.BCM8869X=2 +dtm_flow_nof_remote_cores_region_57.BCM8869X=2 +dtm_flow_nof_remote_cores_region_58.BCM8869X=2 +dtm_flow_nof_remote_cores_region_59.BCM8869X=2 +dtm_flow_nof_remote_cores_region_60.BCM8869X=2 + +mdb_profile.BCM8869X=l3-xl + +outlif_logical_to_physical_phase_map_1=S1 +outlif_logical_to_physical_phase_map_2=L1 +outlif_logical_to_physical_phase_map_3=XL +outlif_logical_to_physical_phase_map_4=L2 +outlif_logical_to_physical_phase_map_5=M1 +outlif_logical_to_physical_phase_map_6=M2 +outlif_logical_to_physical_phase_map_7=M3 +outlif_logical_to_physical_phase_map_8=S2 + +outlif_physical_phase_data_granularity_S1=60 +outlif_physical_phase_data_granularity_S2=60 +outlif_physical_phase_data_granularity_M1=60 +outlif_physical_phase_data_granularity_M2=60 +outlif_physical_phase_data_granularity_M3=60 +outlif_physical_phase_data_granularity_L1=60 +outlif_physical_phase_data_granularity_L2=60 +outlif_physical_phase_data_granularity_XL=60 + +port_init_speed_fabric.BCM8869X=53125 + +fabric_connect_mode.BCM8869X=SINGLE_FAP +protocol_traps_mode.BCM8869X=IN_LIF + +schan_intr_enable.BCM8869X=0 +tdma_intr_enable.BCM8869X=0 +tslam_intr_enable.BCM8869X=0 +miim_intr_enable.BCM8869X=0 +schan_timeout_usec.BCM8869X=300000 +tdma_timeout_usec.BCM8869X=1000000 +tslam_timeout_usec.BCM8869X=1000000 + +appl_enable_intr_init.BCM8869X=1 +polled_irq_mode.BCM8869X=1 +polled_irq_delay.BCM8869X=1000 + +bcm_stat_interval.BCM8869X=1000 + +mem_cache_enable_ecc.BCM8869X=1 +mem_cache_enable_parity.BCM8869X=1 + +serdes_nif_clk_freq_in.BCM8869X_A0=2 +serdes_nif_clk_freq_out.BCM8869X_A0=1 +serdes_fabric_clk_freq_in.BCM8869X_A0=2 +serdes_fabric_clk_freq_out.BCM8869X_A0=1 + +serdes_nif_clk_freq_in.BCM8869X=1 +serdes_nif_clk_freq_out.BCM8869X=bypass +serdes_fabric_clk_freq_in.BCM8869X=1 +serdes_fabric_clk_freq_out.BCM8869X=bypass + +dram_phy_tune_mode_on_init.BCM8869X=RUN_TUNE + +dport_map_direct.BCM8869X=1 + +pmf_sexem3_stage.BCM8869X=IPMF3 + +lane_to_serdes_map_fabric_lane0.0=rx0:tx0 +lane_to_serdes_map_fabric_lane1.0=rx1:tx1 +lane_to_serdes_map_fabric_lane2.0=rx2:tx2 +lane_to_serdes_map_fabric_lane3.0=rx3:tx3 +lane_to_serdes_map_fabric_lane4.0=rx4:tx4 +lane_to_serdes_map_fabric_lane5.0=rx5:tx5 +lane_to_serdes_map_fabric_lane6.0=rx6:tx6 +lane_to_serdes_map_fabric_lane7.0=rx7:tx7 +lane_to_serdes_map_fabric_lane8.0=rx8:tx8 +lane_to_serdes_map_fabric_lane9.0=rx9:tx9 +lane_to_serdes_map_fabric_lane10.0=rx10:tx10 +lane_to_serdes_map_fabric_lane11.0=rx11:tx11 +lane_to_serdes_map_fabric_lane12.0=rx12:tx12 +lane_to_serdes_map_fabric_lane13.0=rx13:tx13 +lane_to_serdes_map_fabric_lane14.0=rx14:tx14 +lane_to_serdes_map_fabric_lane15.0=rx15:tx15 +lane_to_serdes_map_fabric_lane16.0=rx16:tx16 +lane_to_serdes_map_fabric_lane17.0=rx17:tx17 +lane_to_serdes_map_fabric_lane18.0=rx18:tx18 +lane_to_serdes_map_fabric_lane19.0=rx19:tx19 +lane_to_serdes_map_fabric_lane20.0=rx20:tx20 +lane_to_serdes_map_fabric_lane21.0=rx21:tx21 +lane_to_serdes_map_fabric_lane22.0=rx22:tx22 +lane_to_serdes_map_fabric_lane23.0=rx23:tx23 +lane_to_serdes_map_fabric_lane24.0=rx24:tx24 +lane_to_serdes_map_fabric_lane25.0=rx25:tx25 +lane_to_serdes_map_fabric_lane26.0=rx26:tx26 +lane_to_serdes_map_fabric_lane27.0=rx27:tx27 +lane_to_serdes_map_fabric_lane28.0=rx28:tx28 +lane_to_serdes_map_fabric_lane29.0=rx29:tx29 +lane_to_serdes_map_fabric_lane30.0=rx30:tx30 +lane_to_serdes_map_fabric_lane31.0=rx31:tx31 +lane_to_serdes_map_fabric_lane32.0=rx32:tx32 +lane_to_serdes_map_fabric_lane33.0=rx33:tx33 +lane_to_serdes_map_fabric_lane34.0=rx34:tx34 +lane_to_serdes_map_fabric_lane35.0=rx35:tx35 +lane_to_serdes_map_fabric_lane36.0=rx36:tx36 +lane_to_serdes_map_fabric_lane37.0=rx37:tx37 +lane_to_serdes_map_fabric_lane38.0=rx38:tx38 +lane_to_serdes_map_fabric_lane39.0=rx39:tx39 +lane_to_serdes_map_fabric_lane40.0=rx40:tx40 +lane_to_serdes_map_fabric_lane41.0=rx41:tx41 +lane_to_serdes_map_fabric_lane42.0=rx42:tx42 +lane_to_serdes_map_fabric_lane43.0=rx43:tx43 +lane_to_serdes_map_fabric_lane44.0=rx44:tx44 +lane_to_serdes_map_fabric_lane45.0=rx45:tx45 +lane_to_serdes_map_fabric_lane46.0=rx46:tx46 +lane_to_serdes_map_fabric_lane47.0=rx47:tx47 +lane_to_serdes_map_fabric_lane48.0=rx48:tx48 +lane_to_serdes_map_fabric_lane49.0=rx49:tx49 +lane_to_serdes_map_fabric_lane50.0=rx50:tx50 +lane_to_serdes_map_fabric_lane51.0=rx51:tx51 +lane_to_serdes_map_fabric_lane52.0=rx52:tx52 +lane_to_serdes_map_fabric_lane53.0=rx53:tx53 +lane_to_serdes_map_fabric_lane54.0=rx54:tx54 +lane_to_serdes_map_fabric_lane55.0=rx55:tx55 +lane_to_serdes_map_fabric_lane56.0=rx56:tx56 +lane_to_serdes_map_fabric_lane57.0=rx57:tx57 +lane_to_serdes_map_fabric_lane58.0=rx58:tx58 +lane_to_serdes_map_fabric_lane59.0=rx59:tx59 +lane_to_serdes_map_fabric_lane60.0=rx60:tx60 +lane_to_serdes_map_fabric_lane61.0=rx61:tx61 +lane_to_serdes_map_fabric_lane62.0=rx62:tx62 +lane_to_serdes_map_fabric_lane63.0=rx63:tx63 +lane_to_serdes_map_fabric_lane64.0=rx64:tx64 +lane_to_serdes_map_fabric_lane65.0=rx65:tx65 +lane_to_serdes_map_fabric_lane66.0=rx66:tx66 +lane_to_serdes_map_fabric_lane67.0=rx67:tx67 +lane_to_serdes_map_fabric_lane68.0=rx68:tx68 +lane_to_serdes_map_fabric_lane69.0=rx69:tx69 +lane_to_serdes_map_fabric_lane70.0=rx70:tx70 +lane_to_serdes_map_fabric_lane71.0=rx71:tx71 +lane_to_serdes_map_fabric_lane72.0=rx72:tx72 +lane_to_serdes_map_fabric_lane73.0=rx73:tx73 +lane_to_serdes_map_fabric_lane74.0=rx74:tx74 +lane_to_serdes_map_fabric_lane75.0=rx75:tx75 +lane_to_serdes_map_fabric_lane76.0=rx76:tx76 +lane_to_serdes_map_fabric_lane77.0=rx77:tx77 +lane_to_serdes_map_fabric_lane78.0=rx78:tx78 +lane_to_serdes_map_fabric_lane79.0=rx79:tx79 +lane_to_serdes_map_fabric_lane80.0=rx80:tx80 +lane_to_serdes_map_fabric_lane81.0=rx81:tx81 +lane_to_serdes_map_fabric_lane82.0=rx82:tx82 +lane_to_serdes_map_fabric_lane83.0=rx83:tx83 +lane_to_serdes_map_fabric_lane84.0=rx84:tx84 +lane_to_serdes_map_fabric_lane85.0=rx85:tx85 +lane_to_serdes_map_fabric_lane86.0=rx86:tx86 +lane_to_serdes_map_fabric_lane87.0=rx87:tx87 +lane_to_serdes_map_fabric_lane88.0=rx88:tx88 +lane_to_serdes_map_fabric_lane89.0=rx89:tx89 +lane_to_serdes_map_fabric_lane90.0=rx90:tx90 +lane_to_serdes_map_fabric_lane91.0=rx91:tx91 +lane_to_serdes_map_fabric_lane92.0=rx92:tx92 +lane_to_serdes_map_fabric_lane93.0=rx93:tx93 +lane_to_serdes_map_fabric_lane94.0=rx94:tx94 +lane_to_serdes_map_fabric_lane95.0=rx95:tx95 +lane_to_serdes_map_fabric_lane96.0=rx96:tx96 +lane_to_serdes_map_fabric_lane97.0=rx97:tx97 +lane_to_serdes_map_fabric_lane98.0=rx98:tx98 +lane_to_serdes_map_fabric_lane99.0=rx99:tx99 +lane_to_serdes_map_fabric_lane100.0=rx100:tx100 +lane_to_serdes_map_fabric_lane101.0=rx101:tx101 +lane_to_serdes_map_fabric_lane102.0=rx102:tx102 +lane_to_serdes_map_fabric_lane103.0=rx103:tx103 +lane_to_serdes_map_fabric_lane104.0=rx104:tx104 +lane_to_serdes_map_fabric_lane105.0=rx105:tx105 +lane_to_serdes_map_fabric_lane106.0=rx106:tx106 +lane_to_serdes_map_fabric_lane107.0=rx107:tx107 +lane_to_serdes_map_fabric_lane108.0=rx108:tx108 +lane_to_serdes_map_fabric_lane109.0=rx109:tx109 +lane_to_serdes_map_fabric_lane110.0=rx110:tx110 +lane_to_serdes_map_fabric_lane111.0=rx111:tx111 + +lane_to_serdes_map_nif_lane0.0=rx5:tx7 +lane_to_serdes_map_nif_lane1.0=rx7:tx6 +lane_to_serdes_map_nif_lane2.0=rx4:tx5 +lane_to_serdes_map_nif_lane3.0=rx6:tx4 +lane_to_serdes_map_nif_lane4.0=rx0:tx0 +lane_to_serdes_map_nif_lane5.0=rx1:tx1 +lane_to_serdes_map_nif_lane6.0=rx2:tx3 +lane_to_serdes_map_nif_lane7.0=rx3:tx2 +lane_to_serdes_map_nif_lane8.0=rx13:tx15 +lane_to_serdes_map_nif_lane9.0=rx12:tx14 +lane_to_serdes_map_nif_lane10.0=rx15:tx13 +lane_to_serdes_map_nif_lane11.0=rx14:tx12 +lane_to_serdes_map_nif_lane12.0=rx10:tx10 +lane_to_serdes_map_nif_lane13.0=rx8:tx9 +lane_to_serdes_map_nif_lane14.0=rx9:tx11 +lane_to_serdes_map_nif_lane15.0=rx11:tx8 +lane_to_serdes_map_nif_lane16.0=rx23:tx23 +lane_to_serdes_map_nif_lane17.0=rx21:tx22 +lane_to_serdes_map_nif_lane18.0=rx22:tx21 +lane_to_serdes_map_nif_lane19.0=rx20:tx20 +lane_to_serdes_map_nif_lane20.0=rx16:tx18 +lane_to_serdes_map_nif_lane21.0=rx17:tx17 +lane_to_serdes_map_nif_lane22.0=rx18:tx16 +lane_to_serdes_map_nif_lane23.0=rx19:tx19 +lane_to_serdes_map_nif_lane24.0=rx31:tx31 +lane_to_serdes_map_nif_lane25.0=rx30:tx30 +lane_to_serdes_map_nif_lane26.0=rx29:tx29 +lane_to_serdes_map_nif_lane27.0=rx28:tx28 +lane_to_serdes_map_nif_lane28.0=rx24:tx26 +lane_to_serdes_map_nif_lane29.0=rx26:tx25 +lane_to_serdes_map_nif_lane30.0=rx25:tx24 +lane_to_serdes_map_nif_lane31.0=rx27:tx27 +lane_to_serdes_map_nif_lane32.0=rx39:tx35 +lane_to_serdes_map_nif_lane33.0=rx38:tx36 +lane_to_serdes_map_nif_lane34.0=rx32:tx32 +lane_to_serdes_map_nif_lane35.0=rx37:tx37 +lane_to_serdes_map_nif_lane36.0=rx33:tx34 +lane_to_serdes_map_nif_lane37.0=rx34:tx38 +lane_to_serdes_map_nif_lane38.0=rx35:tx33 +lane_to_serdes_map_nif_lane39.0=rx36:tx39 +lane_to_serdes_map_nif_lane40.0=rx44:tx47 +lane_to_serdes_map_nif_lane41.0=rx43:tx41 +lane_to_serdes_map_nif_lane42.0=rx47:tx46 +lane_to_serdes_map_nif_lane43.0=rx42:tx42 +lane_to_serdes_map_nif_lane44.0=rx45:tx45 +lane_to_serdes_map_nif_lane45.0=rx41:tx40 +lane_to_serdes_map_nif_lane46.0=rx46:tx44 +lane_to_serdes_map_nif_lane47.0=rx40:tx43 +lane_to_serdes_map_nif_lane48.0=rx55:tx55 +lane_to_serdes_map_nif_lane49.0=rx54:tx54 +lane_to_serdes_map_nif_lane50.0=rx53:tx53 +lane_to_serdes_map_nif_lane51.0=rx52:tx52 +lane_to_serdes_map_nif_lane52.0=rx48:tx48 +lane_to_serdes_map_nif_lane53.0=rx49:tx49 +lane_to_serdes_map_nif_lane54.0=rx50:tx50 +lane_to_serdes_map_nif_lane55.0=rx51:tx51 +lane_to_serdes_map_nif_lane56.0=rx60:tx60 +lane_to_serdes_map_nif_lane57.0=rx61:tx61 +lane_to_serdes_map_nif_lane58.0=rx62:tx63 +lane_to_serdes_map_nif_lane59.0=rx63:tx62 +lane_to_serdes_map_nif_lane60.0=rx58:tx59 +lane_to_serdes_map_nif_lane61.0=rx59:tx56 +lane_to_serdes_map_nif_lane62.0=rx57:tx58 +lane_to_serdes_map_nif_lane63.0=rx56:tx57 +lane_to_serdes_map_nif_lane64.0=rx68:tx69 +lane_to_serdes_map_nif_lane65.0=rx69:tx68 +lane_to_serdes_map_nif_lane66.0=rx70:tx71 +lane_to_serdes_map_nif_lane67.0=rx71:tx70 +lane_to_serdes_map_nif_lane68.0=rx67:tx64 +lane_to_serdes_map_nif_lane69.0=rx66:tx67 +lane_to_serdes_map_nif_lane70.0=rx65:tx65 +lane_to_serdes_map_nif_lane71.0=rx64:tx66 +lane_to_serdes_map_nif_lane72.0=rx78:tx76 +lane_to_serdes_map_nif_lane73.0=rx76:tx77 +lane_to_serdes_map_nif_lane74.0=rx79:tx78 +lane_to_serdes_map_nif_lane75.0=rx77:tx79 +lane_to_serdes_map_nif_lane76.0=rx75:tx72 +lane_to_serdes_map_nif_lane77.0=rx74:tx75 +lane_to_serdes_map_nif_lane78.0=rx73:tx73 +lane_to_serdes_map_nif_lane79.0=rx72:tx74 +lane_to_serdes_map_nif_lane80.0=rx81:tx83 +lane_to_serdes_map_nif_lane81.0=rx85:tx84 +lane_to_serdes_map_nif_lane82.0=rx80:tx80 +lane_to_serdes_map_nif_lane83.0=rx86:tx85 +lane_to_serdes_map_nif_lane84.0=rx82:tx82 +lane_to_serdes_map_nif_lane85.0=rx87:tx86 +lane_to_serdes_map_nif_lane86.0=rx83:tx81 +lane_to_serdes_map_nif_lane87.0=rx84:tx87 +lane_to_serdes_map_nif_lane88.0=rx91:tx95 +lane_to_serdes_map_nif_lane89.0=rx90:tx89 +lane_to_serdes_map_nif_lane90.0=rx95:tx94 +lane_to_serdes_map_nif_lane91.0=rx89:tx90 +lane_to_serdes_map_nif_lane92.0=rx93:tx93 +lane_to_serdes_map_nif_lane93.0=rx94:tx88 +lane_to_serdes_map_nif_lane94.0=rx92:tx92 +lane_to_serdes_map_nif_lane95.0=rx88:tx91 +phy_rx_polarity_flip_phy0=0 +phy_rx_polarity_flip_phy1=1 +phy_rx_polarity_flip_phy2=0 +phy_rx_polarity_flip_phy3=0 +phy_rx_polarity_flip_phy4=0 +phy_rx_polarity_flip_phy5=0 +phy_rx_polarity_flip_phy6=0 +phy_rx_polarity_flip_phy7=0 +phy_rx_polarity_flip_phy8=1 +phy_rx_polarity_flip_phy9=1 +phy_rx_polarity_flip_phy10=1 +phy_rx_polarity_flip_phy11=1 +phy_rx_polarity_flip_phy12=0 +phy_rx_polarity_flip_phy13=1 +phy_rx_polarity_flip_phy14=1 +phy_rx_polarity_flip_phy15=1 +phy_rx_polarity_flip_phy16=0 +phy_rx_polarity_flip_phy17=1 +phy_rx_polarity_flip_phy18=1 +phy_rx_polarity_flip_phy19=0 +phy_rx_polarity_flip_phy20=0 +phy_rx_polarity_flip_phy21=0 +phy_rx_polarity_flip_phy22=0 +phy_rx_polarity_flip_phy23=0 +phy_rx_polarity_flip_phy24=1 +phy_rx_polarity_flip_phy25=1 +phy_rx_polarity_flip_phy26=1 +phy_rx_polarity_flip_phy27=0 +phy_rx_polarity_flip_phy28=0 +phy_rx_polarity_flip_phy29=1 +phy_rx_polarity_flip_phy30=1 +phy_rx_polarity_flip_phy31=0 +phy_rx_polarity_flip_phy32=0 +phy_rx_polarity_flip_phy33=1 +phy_rx_polarity_flip_phy34=1 +phy_rx_polarity_flip_phy35=0 +phy_rx_polarity_flip_phy36=0 +phy_rx_polarity_flip_phy37=0 +phy_rx_polarity_flip_phy38=1 +phy_rx_polarity_flip_phy39=0 +phy_rx_polarity_flip_phy40=1 +phy_rx_polarity_flip_phy41=1 +phy_rx_polarity_flip_phy42=0 +phy_rx_polarity_flip_phy43=0 +phy_rx_polarity_flip_phy44=1 +phy_rx_polarity_flip_phy45=1 +phy_rx_polarity_flip_phy46=0 +phy_rx_polarity_flip_phy47=0 +phy_rx_polarity_flip_phy48=1 +phy_rx_polarity_flip_phy49=1 +phy_rx_polarity_flip_phy50=1 +phy_rx_polarity_flip_phy51=1 +phy_rx_polarity_flip_phy52=0 +phy_rx_polarity_flip_phy53=0 +phy_rx_polarity_flip_phy54=0 +phy_rx_polarity_flip_phy55=0 +phy_rx_polarity_flip_phy56=0 +phy_rx_polarity_flip_phy57=0 +phy_rx_polarity_flip_phy58=0 +phy_rx_polarity_flip_phy59=0 +phy_rx_polarity_flip_phy60=1 +phy_rx_polarity_flip_phy61=1 +phy_rx_polarity_flip_phy62=1 +phy_rx_polarity_flip_phy63=1 +phy_rx_polarity_flip_phy64=1 +phy_rx_polarity_flip_phy65=1 +phy_rx_polarity_flip_phy66=1 +phy_rx_polarity_flip_phy67=1 +phy_rx_polarity_flip_phy68=1 +phy_rx_polarity_flip_phy69=1 +phy_rx_polarity_flip_phy70=1 +phy_rx_polarity_flip_phy71=1 +phy_rx_polarity_flip_phy72=1 +phy_rx_polarity_flip_phy73=0 +phy_rx_polarity_flip_phy74=0 +phy_rx_polarity_flip_phy75=1 +phy_rx_polarity_flip_phy76=1 +phy_rx_polarity_flip_phy77=1 +phy_rx_polarity_flip_phy78=1 +phy_rx_polarity_flip_phy79=1 +phy_rx_polarity_flip_phy80=0 +phy_rx_polarity_flip_phy81=0 +phy_rx_polarity_flip_phy82=1 +phy_rx_polarity_flip_phy83=1 +phy_rx_polarity_flip_phy84=1 +phy_rx_polarity_flip_phy85=0 +phy_rx_polarity_flip_phy86=1 +phy_rx_polarity_flip_phy87=1 +phy_rx_polarity_flip_phy88=0 +phy_rx_polarity_flip_phy89=0 +phy_rx_polarity_flip_phy90=1 +phy_rx_polarity_flip_phy91=1 +phy_rx_polarity_flip_phy92=0 +phy_rx_polarity_flip_phy93=1 +phy_rx_polarity_flip_phy94=0 +phy_rx_polarity_flip_phy95=0 +phy_tx_polarity_flip_phy0=1 +phy_tx_polarity_flip_phy1=1 +phy_tx_polarity_flip_phy2=1 +phy_tx_polarity_flip_phy3=1 +phy_tx_polarity_flip_phy4=1 +phy_tx_polarity_flip_phy5=1 +phy_tx_polarity_flip_phy6=0 +phy_tx_polarity_flip_phy7=0 +phy_tx_polarity_flip_phy8=1 +phy_tx_polarity_flip_phy9=1 +phy_tx_polarity_flip_phy10=1 +phy_tx_polarity_flip_phy11=1 +phy_tx_polarity_flip_phy12=1 +phy_tx_polarity_flip_phy13=1 +phy_tx_polarity_flip_phy14=0 +phy_tx_polarity_flip_phy15=0 +phy_tx_polarity_flip_phy16=0 +phy_tx_polarity_flip_phy17=0 +phy_tx_polarity_flip_phy18=0 +phy_tx_polarity_flip_phy19=0 +phy_tx_polarity_flip_phy20=0 +phy_tx_polarity_flip_phy21=0 +phy_tx_polarity_flip_phy22=0 +phy_tx_polarity_flip_phy23=0 +phy_tx_polarity_flip_phy24=0 +phy_tx_polarity_flip_phy25=0 +phy_tx_polarity_flip_phy26=0 +phy_tx_polarity_flip_phy27=0 +phy_tx_polarity_flip_phy28=0 +phy_tx_polarity_flip_phy29=0 +phy_tx_polarity_flip_phy30=0 +phy_tx_polarity_flip_phy31=0 +phy_tx_polarity_flip_phy32=0 +phy_tx_polarity_flip_phy33=0 +phy_tx_polarity_flip_phy34=1 +phy_tx_polarity_flip_phy35=1 +phy_tx_polarity_flip_phy36=1 +phy_tx_polarity_flip_phy37=0 +phy_tx_polarity_flip_phy38=0 +phy_tx_polarity_flip_phy39=1 +phy_tx_polarity_flip_phy40=1 +phy_tx_polarity_flip_phy41=1 +phy_tx_polarity_flip_phy42=0 +phy_tx_polarity_flip_phy43=1 +phy_tx_polarity_flip_phy44=1 +phy_tx_polarity_flip_phy45=1 +phy_tx_polarity_flip_phy46=0 +phy_tx_polarity_flip_phy47=0 +phy_tx_polarity_flip_phy48=0 +phy_tx_polarity_flip_phy49=0 +phy_tx_polarity_flip_phy50=0 +phy_tx_polarity_flip_phy51=0 +phy_tx_polarity_flip_phy52=0 +phy_tx_polarity_flip_phy53=0 +phy_tx_polarity_flip_phy54=0 +phy_tx_polarity_flip_phy55=0 +phy_tx_polarity_flip_phy56=1 +phy_tx_polarity_flip_phy57=1 +phy_tx_polarity_flip_phy58=0 +phy_tx_polarity_flip_phy59=0 +phy_tx_polarity_flip_phy60=1 +phy_tx_polarity_flip_phy61=1 +phy_tx_polarity_flip_phy62=0 +phy_tx_polarity_flip_phy63=0 +phy_tx_polarity_flip_phy64=0 +phy_tx_polarity_flip_phy65=0 +phy_tx_polarity_flip_phy66=0 +phy_tx_polarity_flip_phy67=0 +phy_tx_polarity_flip_phy68=0 +phy_tx_polarity_flip_phy69=0 +phy_tx_polarity_flip_phy70=1 +phy_tx_polarity_flip_phy71=1 +phy_tx_polarity_flip_phy72=1 +phy_tx_polarity_flip_phy73=1 +phy_tx_polarity_flip_phy74=1 +phy_tx_polarity_flip_phy75=1 +phy_tx_polarity_flip_phy76=0 +phy_tx_polarity_flip_phy77=0 +phy_tx_polarity_flip_phy78=1 +phy_tx_polarity_flip_phy79=1 +phy_tx_polarity_flip_phy80=0 +phy_tx_polarity_flip_phy81=1 +phy_tx_polarity_flip_phy82=1 +phy_tx_polarity_flip_phy83=1 +phy_tx_polarity_flip_phy84=1 +phy_tx_polarity_flip_phy85=0 +phy_tx_polarity_flip_phy86=0 +phy_tx_polarity_flip_phy87=1 +phy_tx_polarity_flip_phy88=1 +phy_tx_polarity_flip_phy89=0 +phy_tx_polarity_flip_phy90=0 +phy_tx_polarity_flip_phy91=1 +phy_tx_polarity_flip_phy92=1 +phy_tx_polarity_flip_phy93=1 +phy_tx_polarity_flip_phy94=0 +phy_tx_polarity_flip_phy95=0 + +ucode_port_1=CGE2_0:core_0.1 +ucode_port_2=CGE2_1:core_0.2 +ucode_port_3=CGE2_2:core_0.3 +ucode_port_4=CGE2_3:core_0.4 +ucode_port_5=CGE2_4:core_0.5 +ucode_port_6=CGE2_5:core_0.6 +ucode_port_7=CGE2_6:core_0.7 +ucode_port_8=CGE2_7:core_0.8 +ucode_port_9=CGE2_8:core_0.9 +ucode_port_10=CGE2_9:core_0.10 +ucode_port_11=CGE2_10:core_0.11 +ucode_port_12=CGE2_11:core_0.12 +ucode_port_13=CGE2_12:core_0.13 +ucode_port_14=CGE2_13:core_0.14 +ucode_port_15=CGE2_14:core_0.15 +ucode_port_16=CGE2_15:core_0.16 +ucode_port_17=CGE2_36:core_1.17 +ucode_port_18=CGE2_37:core_1.18 +ucode_port_19=CGE2_38:core_1.19 +ucode_port_20=CGE2_39:core_1.20 +ucode_port_21=CGE2_32:core_1.21 +ucode_port_22=CGE2_33:core_1.22 +ucode_port_23=CGE2_34:core_1.23 +ucode_port_24=CGE2_35:core_1.24 +ucode_port_25=CGE2_28:core_1.25 +ucode_port_26=CGE2_29:core_1.26 +ucode_port_27=CGE2_30:core_1.27 +ucode_port_28=CGE2_31:core_1.28 +ucode_port_29=XE48:core_1.29 +ucode_port_30=XE49:core_1.30 +ucode_port_31=XE50:core_1.31 +ucode_port_32=XE51:core_1.32 +ucode_port_33=XE52:core_1.33 +ucode_port_34=XE53:core_1.34 +ucode_port_35=XE54:core_1.35 +ucode_port_36=XE55:core_1.36 + +rif_id_max=0x4000 + +dma_desc_aggregator_chain_length_max.BCM8869X=1000 +dma_desc_aggregator_buff_size_kb.BCM8869X=100 +dma_desc_aggregator_timeout_usec.BCM8869X=1000 +dma_desc_aggregator_enable_specific_MDB_LPM.BCM8869X=1 +dma_desc_aggregator_enable_specific_MDB_FEC.BCM8869X=1 diff --git a/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C28S8/port_config.ini b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C28S8/port_config.ini new file mode 100644 index 000000000000..cb1c2a4663e8 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C28S8/port_config.ini @@ -0,0 +1,37 @@ +# name lanes alias index speed +Ethernet0 0,1 Ethernet1/1 1 100000 +Ethernet4 2,3 Ethernet2/1 2 100000 +Ethernet8 4,5 Ethernet3/1 3 100000 +Ethernet12 6,7 Ethernet4/1 4 100000 +Ethernet16 8,9 Ethernet5/1 5 100000 +Ethernet20 10,11 Ethernet6/1 6 100000 +Ethernet24 12,13 Ethernet7/1 7 100000 +Ethernet28 14,15 Ethernet8/1 8 100000 +Ethernet32 16,17 Ethernet9/1 9 100000 +Ethernet36 18,19 Ethernet10/1 10 100000 +Ethernet40 20,21 Ethernet11/1 11 100000 +Ethernet44 22,23 Ethernet12/1 12 100000 +Ethernet48 24,25 Ethernet13/1 13 100000 +Ethernet52 26,27 Ethernet14/1 14 100000 +Ethernet56 28,29 Ethernet15/1 15 100000 +Ethernet60 30,31 Ethernet16/1 16 100000 +Ethernet64 72,73 Ethernet17/1 17 100000 +Ethernet68 74,75 Ethernet18/1 18 100000 +Ethernet72 76,77 Ethernet19/1 19 100000 +Ethernet76 78,79 Ethernet20/1 20 100000 +Ethernet80 64,65 Ethernet21/1 21 100000 +Ethernet84 66,67 Ethernet22/1 22 100000 +Ethernet88 68,69 Ethernet23/1 23 100000 +Ethernet92 70,71 Ethernet24/1 24 100000 +Ethernet96 56,57 Ethernet25/1 25 100000 +Ethernet100 58,59 Ethernet26/1 26 100000 +Ethernet104 60,61 Ethernet27/1 27 100000 +Ethernet108 62,63 Ethernet28/1 28 100000 +Ethernet112 48 Ethernet29/1 29 10000 +Ethernet113 49 Ethernet29/2 29 10000 +Ethernet114 50 Ethernet29/3 29 10000 +Ethernet115 51 Ethernet29/4 29 10000 +Ethernet120 52 Ethernet31/1 31 10000 +Ethernet121 53 Ethernet31/2 31 10000 +Ethernet122 54 Ethernet31/3 31 10000 +Ethernet123 55 Ethernet31/4 31 10000 diff --git a/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C28S8/sai.profile b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C28S8/sai.profile new file mode 100644 index 000000000000..f0554cdb874f --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C28S8/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/jr2-a7280cr3-32p4-28x100G-8x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C32D4 b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C32D4 new file mode 120000 index 000000000000..cfdaca201c0a --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C32D4 @@ -0,0 +1 @@ +Arista-7280CR3-C32P4 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C32P4/port_config.ini b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C32P4/port_config.ini new file mode 100644 index 000000000000..976eae864d55 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C32P4/port_config.ini @@ -0,0 +1,37 @@ +# name lanes alias index speed +Ethernet0 1,2 Ethernet1/1 1 100000 +Ethernet4 3,4 Ethernet2/1 2 100000 +Ethernet8 5,6 Ethernet3/1 3 100000 +Ethernet12 7,8 Ethernet4/1 4 100000 +Ethernet16 9,10 Ethernet5/1 5 100000 +Ethernet20 11,12 Ethernet6/1 6 100000 +Ethernet24 13,14 Ethernet7/1 7 100000 +Ethernet28 15,16 Ethernet8/1 8 100000 +Ethernet32 17,18 Ethernet9/1 9 100000 +Ethernet36 19,20 Ethernet10/1 10 100000 +Ethernet40 21,22 Ethernet11/1 11 100000 +Ethernet44 23,24 Ethernet12/1 12 100000 +Ethernet48 25,26 Ethernet13/1 13 100000 +Ethernet52 27,28 Ethernet14/1 14 100000 +Ethernet56 29,30 Ethernet15/1 15 100000 +Ethernet60 31,32 Ethernet16/1 16 100000 +Ethernet64 73,74 Ethernet17/1 17 100000 +Ethernet68 75,76 Ethernet18/1 18 100000 +Ethernet72 77,78 Ethernet19/1 19 100000 +Ethernet76 79,80 Ethernet20/1 20 100000 +Ethernet80 65,66 Ethernet21/1 21 100000 +Ethernet84 67,68 Ethernet22/1 22 100000 +Ethernet88 69,70 Ethernet23/1 23 100000 +Ethernet92 71,72 Ethernet24/1 24 100000 +Ethernet96 57,58 Ethernet25/1 25 100000 +Ethernet100 59,60 Ethernet26/1 26 100000 +Ethernet104 61,62 Ethernet27/1 27 100000 +Ethernet108 63,64 Ethernet28/1 28 100000 +Ethernet112 49,50 Ethernet29/1 29 100000 +Ethernet116 51,52 Ethernet30/1 30 100000 +Ethernet120 53,54 Ethernet31/1 31 100000 +Ethernet124 55,56 Ethernet32/1 32 100000 +Ethernet128 33,34,35,36,37,38,39,40 Ethernet33/1 33 400000 +Ethernet132 41,42,43,44,45,46,47,48 Ethernet34/1 34 400000 +Ethernet136 89,90,91,92,93,94,95,96 Ethernet35/1 35 400000 +Ethernet140 81,82,83,84,85,86,87,88 Ethernet36/1 36 400000 diff --git a/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C40/jr2-a7280cr3-32p4-40x100G.config.bcm b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C40/jr2-a7280cr3-32p4-40x100G.config.bcm new file mode 100644 index 000000000000..ca3c266eadfc --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C40/jr2-a7280cr3-32p4-40x100G.config.bcm @@ -0,0 +1,759 @@ +soc_family.BCM8869X=BCM8869X + +custom_feature_ucode_path=u_code_db2pem.txt +system_headers_mode=1 +suppress_unknown_prop_warnings=1 +l4_protocols_load_balancing_enable=1 +fabric_logical_port_base=512 +trunk_group_max_members=128 +num_olp_tm_ports.BCM8869X=1 + +ucode_port_0.BCM8869X=CPU.0:core_0.0 +ucode_port_200.BCM8869X=CPU.8:core_1.200 +ucode_port_201.BCM8869X=CPU.16:core_0.201 +ucode_port_202.BCM8869X=CPU.24:core_1.202 +ucode_port_203.BCM8869X=CPU.32:core_0.203 + +port_init_speed_xe.BCM8869X=10000 +port_init_speed_xl.BCM8869X=40000 +port_init_speed_le.BCM8869X=50000 +port_init_speed_ce.BCM8869X=100000 +port_init_speed_cc.BCM8869X=200000 +port_init_speed_cd.BCM8869X=400000 +port_init_speed_il.BCM8869X=10312 + +port_init_cl72=0 + +serdes_tx_taps_1=pam4:-16:64:0:3:0:0 +serdes_tx_taps_2=pam4:-16:64:0:3:0:0 +serdes_tx_taps_3=pam4:-16:64:0:3:0:0 +serdes_tx_taps_4=pam4:-16:64:0:3:0:0 +serdes_tx_taps_5=pam4:-16:64:0:3:0:0 +serdes_tx_taps_6=pam4:-16:64:0:3:0:0 +serdes_tx_taps_7=pam4:-16:64:0:3:0:0 +serdes_tx_taps_8=pam4:-16:64:0:3:0:0 +serdes_tx_taps_9=pam4:-8:60:0:0:0:0 +serdes_tx_taps_10=pam4:-8:60:0:0:0:0 +serdes_tx_taps_11=pam4:-8:60:0:0:0:0 +serdes_tx_taps_12=pam4:-8:60:0:0:0:0 +serdes_tx_taps_13=pam4:-8:60:0:0:0:0 +serdes_tx_taps_14=pam4:-8:60:0:0:0:0 +serdes_tx_taps_15=pam4:-8:60:0:0:0:0 +serdes_tx_taps_16=pam4:-8:60:0:0:0:0 +serdes_tx_taps_17=pam4:-8:60:0:0:0:0 +serdes_tx_taps_18=pam4:-8:60:0:0:0:0 +serdes_tx_taps_19=pam4:-8:60:0:0:0:0 +serdes_tx_taps_20=pam4:-8:60:0:0:0:0 +serdes_tx_taps_21=pam4:-8:60:0:0:0:0 +serdes_tx_taps_22=pam4:-8:60:0:0:0:0 +serdes_tx_taps_23=pam4:-8:60:0:0:0:0 +serdes_tx_taps_24=pam4:-8:60:0:0:0:0 +serdes_tx_taps_25=pam4:-8:60:0:0:0:0 +serdes_tx_taps_26=pam4:-8:60:0:0:0:0 +serdes_tx_taps_27=pam4:-8:60:0:0:0:0 +serdes_tx_taps_28=pam4:-8:60:0:0:0:0 +serdes_tx_taps_29=pam4:-16:60:0:3:0:0 +serdes_tx_taps_30=pam4:-16:60:0:3:0:0 +serdes_tx_taps_31=pam4:-16:60:0:3:0:0 +serdes_tx_taps_32=pam4:-16:60:0:3:0:0 +serdes_tx_taps_33=nrz:0:71:-16:-5:0:0 +serdes_tx_taps_34=nrz:0:71:-16:-5:0:0 +serdes_tx_taps_35=nrz:0:78:-22:-4:0:0 +serdes_tx_taps_36=nrz:0:78:-22:-4:0:0 +serdes_tx_taps_37=nrz:0:72:-18:-5:0:0 +serdes_tx_taps_38=nrz:0:72:-18:-5:0:0 +serdes_tx_taps_39=nrz:0:68:-17:-6:0:0 +serdes_tx_taps_40=nrz:0:68:-17:-6:0:0 + +ucode_port_100.BCM8869X=RCY_MIRROR.0:core_0.100 +ucode_port_101.BCM8869X=RCY_MIRROR.1:core_0.101 +ucode_port_102.BCM8869X=RCY_MIRROR.2:core_0.102 +ucode_port_103.BCM8869X=RCY_MIRROR.3:core_0.103 +ucode_port_104.BCM8869X=RCY_MIRROR.4:core_0.104 +ucode_port_105.BCM8869X=RCY_MIRROR.5:core_0.105 +ucode_port_106.BCM8869X=RCY_MIRROR.6:core_0.106 +ucode_port_107.BCM8869X=RCY_MIRROR.7:core_0.107 +ucode_port_108.BCM8869X=RCY_MIRROR.8:core_0.108 +ucode_port_109.BCM8869X=RCY_MIRROR.9:core_0.109 +ucode_port_110.BCM8869X=RCY_MIRROR.10:core_0.110 +ucode_port_111.BCM8869X=RCY_MIRROR.11:core_0.111 +ucode_port_112.BCM8869X=RCY_MIRROR.12:core_0.112 +ucode_port_113.BCM8869X=RCY_MIRROR.13:core_0.113 +ucode_port_114.BCM8869X=RCY_MIRROR.14:core_0.114 +ucode_port_115.BCM8869X=RCY_MIRROR.15:core_0.115 +ucode_port_116.BCM8869X=RCY_MIRROR.16:core_0.116 +ucode_port_117.BCM8869X=RCY_MIRROR.17:core_0.117 +ucode_port_118.BCM8869X=RCY_MIRROR.18:core_0.118 +ucode_port_119.BCM8869X=RCY_MIRROR.19:core_0.119 +ucode_port_120.BCM8869X=RCY_MIRROR.0:core_1.120 +ucode_port_121.BCM8869X=RCY_MIRROR.1:core_1.121 +ucode_port_122.BCM8869X=RCY_MIRROR.2:core_1.122 +ucode_port_123.BCM8869X=RCY_MIRROR.3:core_1.123 +ucode_port_124.BCM8869X=RCY_MIRROR.4:core_1.124 +ucode_port_125.BCM8869X=RCY_MIRROR.5:core_1.125 +ucode_port_126.BCM8869X=RCY_MIRROR.6:core_1.126 +ucode_port_127.BCM8869X=RCY_MIRROR.7:core_1.127 +ucode_port_128.BCM8869X=RCY_MIRROR.8:core_1.128 +ucode_port_129.BCM8869X=RCY_MIRROR.9:core_1.129 +ucode_port_130.BCM8869X=RCY_MIRROR.10:core_1.130 +ucode_port_131.BCM8869X=RCY_MIRROR.11:core_1.131 +ucode_port_132.BCM8869X=RCY_MIRROR.12:core_1.132 +ucode_port_133.BCM8869X=RCY_MIRROR.13:core_1.133 +ucode_port_134.BCM8869X=RCY_MIRROR.14:core_1.134 +ucode_port_135.BCM8869X=RCY_MIRROR.15:core_1.135 +ucode_port_136.BCM8869X=RCY_MIRROR.16:core_1.136 +ucode_port_137.BCM8869X=RCY_MIRROR.17:core_1.137 +ucode_port_138.BCM8869X=RCY_MIRROR.18:core_1.138 +ucode_port_139.BCM8869X=RCY_MIRROR.19:core_1.139 + +port_priorities.BCM8869X=8 + +ucode_port_213.BCM8869X=OLP:core_0.213 + +sw_state_max_size.BCM8869X=750000000 + +stable_location.BCM8869X=4 +stable_location.BCM8869X_ADAPTER=3 + +stable_filename.BCM8869X_ADAPTER=warmboot_data_0 +stable_filename=/dev/shm/warmboot_data_0 +stable_filename.1=/dev/shm/warmboot_data_1 +stable_filename.2=/dev/shm/warmboot_data_2 + +stable_size.BCM8869X=800000000 + +tm_port_header_type_in_0.BCM8869X=INJECTED_2 +tm_port_header_type_out_0.BCM8869X=CPU + +tm_port_header_type_in_200.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_200.BCM8869X=ETH +tm_port_header_type_in_201.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_201.BCM8869X=ETH +tm_port_header_type_in_202.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_202.BCM8869X=ETH +tm_port_header_type_in_203.BCM8869X=INJECTED_2_PP +tm_port_header_type_out_203.BCM8869X=ETH + +sat_enable.BCM8869X=1 +tm_port_header_type_out_210.BCM8869X=CPU +tm_port_header_type_in_210.BCM8869X=INJECTED_2 + +tm_port_header_type_in_211.BCM8869X=INJECTED_2 +tm_port_header_type_out_211.BCM8869X=CPU +tm_port_header_type_in_212.BCM8869X=INJECTED_2 +tm_port_header_type_out_212.BCM8869X=CPU + +tm_port_header_type_in_213.BCM8869X=INJECTED_2 +tm_port_header_type_out_213.BCM8869X=RAW + +dtm_flow_mapping_mode_region_64.BCM8869X=3 +dtm_flow_mapping_mode_region_65.BCM8869X=3 +dtm_flow_mapping_mode_region_66.BCM8869X=3 +dtm_flow_mapping_mode_region_67.BCM8869X=3 +dtm_flow_mapping_mode_region_68.BCM8869X=3 +dtm_flow_mapping_mode_region_69.BCM8869X=3 +dtm_flow_mapping_mode_region_70.BCM8869X=3 +dtm_flow_mapping_mode_region_71.BCM8869X=3 +dtm_flow_mapping_mode_region_72.BCM8869X=3 +dtm_flow_mapping_mode_region_73.BCM8869X=3 +dtm_flow_mapping_mode_region_74.BCM8869X=3 +dtm_flow_mapping_mode_region_75.BCM8869X=3 +dtm_flow_mapping_mode_region_76.BCM8869X=3 +dtm_flow_mapping_mode_region_77.BCM8869X=3 +dtm_flow_mapping_mode_region_78.BCM8869X=3 +dtm_flow_mapping_mode_region_79.BCM8869X=7 +dtm_flow_mapping_mode_region_80.BCM8869X=3 +dtm_flow_mapping_mode_region_81.BCM8869X=1 +dtm_flow_mapping_mode_region_82.BCM8869X=3 +dtm_flow_mapping_mode_region_83.BCM8869X=3 +dtm_flow_mapping_mode_region_84.BCM8869X=3 +dtm_flow_mapping_mode_region_85.BCM8869X=3 +dtm_flow_mapping_mode_region_86.BCM8869X=3 +dtm_flow_mapping_mode_region_87.BCM8869X=3 +dtm_flow_mapping_mode_region_88.BCM8869X=3 +dtm_flow_mapping_mode_region_89.BCM8869X=3 +dtm_flow_mapping_mode_region_90.BCM8869X=3 +dtm_flow_mapping_mode_region_91.BCM8869X=3 +dtm_flow_mapping_mode_region_92.BCM8869X=3 +dtm_flow_mapping_mode_region_93.BCM8869X=3 +dtm_flow_mapping_mode_region_94.BCM8869X=3 + +dtm_flow_nof_remote_cores_region_1.BCM8869X=2 +dtm_flow_nof_remote_cores_region_2.BCM8869X=2 +dtm_flow_nof_remote_cores_region_3.BCM8869X=2 +dtm_flow_nof_remote_cores_region_4.BCM8869X=2 +dtm_flow_nof_remote_cores_region_5.BCM8869X=2 +dtm_flow_nof_remote_cores_region_6.BCM8869X=2 +dtm_flow_nof_remote_cores_region_7.BCM8869X=2 +dtm_flow_nof_remote_cores_region_8.BCM8869X=2 +dtm_flow_nof_remote_cores_region_9.BCM8869X=2 +dtm_flow_nof_remote_cores_region_10.BCM8869X=2 +dtm_flow_nof_remote_cores_region_11.BCM8869X=2 +dtm_flow_nof_remote_cores_region_12.BCM8869X=2 +dtm_flow_nof_remote_cores_region_13.BCM8869X=2 +dtm_flow_nof_remote_cores_region_14.BCM8869X=2 +dtm_flow_nof_remote_cores_region_15.BCM8869X=2 +dtm_flow_nof_remote_cores_region_16.BCM8869X=2 +dtm_flow_nof_remote_cores_region_17.BCM8869X=2 +dtm_flow_nof_remote_cores_region_18.BCM8869X=2 +dtm_flow_nof_remote_cores_region_19.BCM8869X=2 +dtm_flow_nof_remote_cores_region_20.BCM8869X=2 +dtm_flow_nof_remote_cores_region_21.BCM8869X=2 +dtm_flow_nof_remote_cores_region_22.BCM8869X=2 +dtm_flow_nof_remote_cores_region_23.BCM8869X=2 +dtm_flow_nof_remote_cores_region_24.BCM8869X=2 +dtm_flow_nof_remote_cores_region_25.BCM8869X=2 +dtm_flow_nof_remote_cores_region_26.BCM8869X=2 +dtm_flow_nof_remote_cores_region_27.BCM8869X=2 +dtm_flow_nof_remote_cores_region_28.BCM8869X=2 +dtm_flow_nof_remote_cores_region_29.BCM8869X=2 +dtm_flow_nof_remote_cores_region_30.BCM8869X=2 +dtm_flow_nof_remote_cores_region_31.BCM8869X=2 +dtm_flow_nof_remote_cores_region_32.BCM8869X=2 +dtm_flow_nof_remote_cores_region_33.BCM8869X=2 +dtm_flow_nof_remote_cores_region_34.BCM8869X=2 +dtm_flow_nof_remote_cores_region_35.BCM8869X=2 +dtm_flow_nof_remote_cores_region_36.BCM8869X=2 +dtm_flow_nof_remote_cores_region_37.BCM8869X=2 +dtm_flow_nof_remote_cores_region_38.BCM8869X=2 +dtm_flow_nof_remote_cores_region_39.BCM8869X=2 +dtm_flow_nof_remote_cores_region_40.BCM8869X=2 +dtm_flow_nof_remote_cores_region_41.BCM8869X=2 +dtm_flow_nof_remote_cores_region_42.BCM8869X=2 +dtm_flow_nof_remote_cores_region_43.BCM8869X=2 +dtm_flow_nof_remote_cores_region_44.BCM8869X=2 +dtm_flow_nof_remote_cores_region_45.BCM8869X=2 +dtm_flow_nof_remote_cores_region_46.BCM8869X=2 +dtm_flow_nof_remote_cores_region_47.BCM8869X=2 +dtm_flow_nof_remote_cores_region_48.BCM8869X=2 +dtm_flow_nof_remote_cores_region_49.BCM8869X=2 +dtm_flow_nof_remote_cores_region_50.BCM8869X=2 +dtm_flow_nof_remote_cores_region_51.BCM8869X=2 +dtm_flow_nof_remote_cores_region_52.BCM8869X=2 +dtm_flow_nof_remote_cores_region_53.BCM8869X=2 +dtm_flow_nof_remote_cores_region_54.BCM8869X=2 +dtm_flow_nof_remote_cores_region_55.BCM8869X=2 +dtm_flow_nof_remote_cores_region_56.BCM8869X=2 +dtm_flow_nof_remote_cores_region_57.BCM8869X=2 +dtm_flow_nof_remote_cores_region_58.BCM8869X=2 +dtm_flow_nof_remote_cores_region_59.BCM8869X=2 +dtm_flow_nof_remote_cores_region_60.BCM8869X=2 + +mdb_profile.BCM8869X=l3-xl + +outlif_logical_to_physical_phase_map_1=S1 +outlif_logical_to_physical_phase_map_2=L1 +outlif_logical_to_physical_phase_map_3=XL +outlif_logical_to_physical_phase_map_4=L2 +outlif_logical_to_physical_phase_map_5=M1 +outlif_logical_to_physical_phase_map_6=M2 +outlif_logical_to_physical_phase_map_7=M3 +outlif_logical_to_physical_phase_map_8=S2 + +outlif_physical_phase_data_granularity_S1=60 +outlif_physical_phase_data_granularity_S2=60 +outlif_physical_phase_data_granularity_M1=60 +outlif_physical_phase_data_granularity_M2=60 +outlif_physical_phase_data_granularity_M3=60 +outlif_physical_phase_data_granularity_L1=60 +outlif_physical_phase_data_granularity_L2=60 +outlif_physical_phase_data_granularity_XL=60 + +port_init_speed_fabric.BCM8869X=53125 + +fabric_connect_mode.BCM8869X=SINGLE_FAP +protocol_traps_mode.BCM8869X=IN_LIF + +schan_intr_enable.BCM8869X=0 +tdma_intr_enable.BCM8869X=0 +tslam_intr_enable.BCM8869X=0 +miim_intr_enable.BCM8869X=0 +schan_timeout_usec.BCM8869X=300000 +tdma_timeout_usec.BCM8869X=1000000 +tslam_timeout_usec.BCM8869X=1000000 + +appl_enable_intr_init.BCM8869X=1 +polled_irq_mode.BCM8869X=1 +polled_irq_delay.BCM8869X=1000 + +bcm_stat_interval.BCM8869X=1000 + +mem_cache_enable_ecc.BCM8869X=1 +mem_cache_enable_parity.BCM8869X=1 + +serdes_nif_clk_freq_in.BCM8869X_A0=2 +serdes_nif_clk_freq_out.BCM8869X_A0=1 +serdes_fabric_clk_freq_in.BCM8869X_A0=2 +serdes_fabric_clk_freq_out.BCM8869X_A0=1 + +serdes_nif_clk_freq_in.BCM8869X=1 +serdes_nif_clk_freq_out.BCM8869X=bypass +serdes_fabric_clk_freq_in.BCM8869X=1 +serdes_fabric_clk_freq_out.BCM8869X=bypass + +dram_phy_tune_mode_on_init.BCM8869X=RUN_TUNE + +dport_map_direct.BCM8869X=1 + +pmf_sexem3_stage.BCM8869X=IPMF3 + +lane_to_serdes_map_fabric_lane0.0=rx0:tx0 +lane_to_serdes_map_fabric_lane1.0=rx1:tx1 +lane_to_serdes_map_fabric_lane2.0=rx2:tx2 +lane_to_serdes_map_fabric_lane3.0=rx3:tx3 +lane_to_serdes_map_fabric_lane4.0=rx4:tx4 +lane_to_serdes_map_fabric_lane5.0=rx5:tx5 +lane_to_serdes_map_fabric_lane6.0=rx6:tx6 +lane_to_serdes_map_fabric_lane7.0=rx7:tx7 +lane_to_serdes_map_fabric_lane8.0=rx8:tx8 +lane_to_serdes_map_fabric_lane9.0=rx9:tx9 +lane_to_serdes_map_fabric_lane10.0=rx10:tx10 +lane_to_serdes_map_fabric_lane11.0=rx11:tx11 +lane_to_serdes_map_fabric_lane12.0=rx12:tx12 +lane_to_serdes_map_fabric_lane13.0=rx13:tx13 +lane_to_serdes_map_fabric_lane14.0=rx14:tx14 +lane_to_serdes_map_fabric_lane15.0=rx15:tx15 +lane_to_serdes_map_fabric_lane16.0=rx16:tx16 +lane_to_serdes_map_fabric_lane17.0=rx17:tx17 +lane_to_serdes_map_fabric_lane18.0=rx18:tx18 +lane_to_serdes_map_fabric_lane19.0=rx19:tx19 +lane_to_serdes_map_fabric_lane20.0=rx20:tx20 +lane_to_serdes_map_fabric_lane21.0=rx21:tx21 +lane_to_serdes_map_fabric_lane22.0=rx22:tx22 +lane_to_serdes_map_fabric_lane23.0=rx23:tx23 +lane_to_serdes_map_fabric_lane24.0=rx24:tx24 +lane_to_serdes_map_fabric_lane25.0=rx25:tx25 +lane_to_serdes_map_fabric_lane26.0=rx26:tx26 +lane_to_serdes_map_fabric_lane27.0=rx27:tx27 +lane_to_serdes_map_fabric_lane28.0=rx28:tx28 +lane_to_serdes_map_fabric_lane29.0=rx29:tx29 +lane_to_serdes_map_fabric_lane30.0=rx30:tx30 +lane_to_serdes_map_fabric_lane31.0=rx31:tx31 +lane_to_serdes_map_fabric_lane32.0=rx32:tx32 +lane_to_serdes_map_fabric_lane33.0=rx33:tx33 +lane_to_serdes_map_fabric_lane34.0=rx34:tx34 +lane_to_serdes_map_fabric_lane35.0=rx35:tx35 +lane_to_serdes_map_fabric_lane36.0=rx36:tx36 +lane_to_serdes_map_fabric_lane37.0=rx37:tx37 +lane_to_serdes_map_fabric_lane38.0=rx38:tx38 +lane_to_serdes_map_fabric_lane39.0=rx39:tx39 +lane_to_serdes_map_fabric_lane40.0=rx40:tx40 +lane_to_serdes_map_fabric_lane41.0=rx41:tx41 +lane_to_serdes_map_fabric_lane42.0=rx42:tx42 +lane_to_serdes_map_fabric_lane43.0=rx43:tx43 +lane_to_serdes_map_fabric_lane44.0=rx44:tx44 +lane_to_serdes_map_fabric_lane45.0=rx45:tx45 +lane_to_serdes_map_fabric_lane46.0=rx46:tx46 +lane_to_serdes_map_fabric_lane47.0=rx47:tx47 +lane_to_serdes_map_fabric_lane48.0=rx48:tx48 +lane_to_serdes_map_fabric_lane49.0=rx49:tx49 +lane_to_serdes_map_fabric_lane50.0=rx50:tx50 +lane_to_serdes_map_fabric_lane51.0=rx51:tx51 +lane_to_serdes_map_fabric_lane52.0=rx52:tx52 +lane_to_serdes_map_fabric_lane53.0=rx53:tx53 +lane_to_serdes_map_fabric_lane54.0=rx54:tx54 +lane_to_serdes_map_fabric_lane55.0=rx55:tx55 +lane_to_serdes_map_fabric_lane56.0=rx56:tx56 +lane_to_serdes_map_fabric_lane57.0=rx57:tx57 +lane_to_serdes_map_fabric_lane58.0=rx58:tx58 +lane_to_serdes_map_fabric_lane59.0=rx59:tx59 +lane_to_serdes_map_fabric_lane60.0=rx60:tx60 +lane_to_serdes_map_fabric_lane61.0=rx61:tx61 +lane_to_serdes_map_fabric_lane62.0=rx62:tx62 +lane_to_serdes_map_fabric_lane63.0=rx63:tx63 +lane_to_serdes_map_fabric_lane64.0=rx64:tx64 +lane_to_serdes_map_fabric_lane65.0=rx65:tx65 +lane_to_serdes_map_fabric_lane66.0=rx66:tx66 +lane_to_serdes_map_fabric_lane67.0=rx67:tx67 +lane_to_serdes_map_fabric_lane68.0=rx68:tx68 +lane_to_serdes_map_fabric_lane69.0=rx69:tx69 +lane_to_serdes_map_fabric_lane70.0=rx70:tx70 +lane_to_serdes_map_fabric_lane71.0=rx71:tx71 +lane_to_serdes_map_fabric_lane72.0=rx72:tx72 +lane_to_serdes_map_fabric_lane73.0=rx73:tx73 +lane_to_serdes_map_fabric_lane74.0=rx74:tx74 +lane_to_serdes_map_fabric_lane75.0=rx75:tx75 +lane_to_serdes_map_fabric_lane76.0=rx76:tx76 +lane_to_serdes_map_fabric_lane77.0=rx77:tx77 +lane_to_serdes_map_fabric_lane78.0=rx78:tx78 +lane_to_serdes_map_fabric_lane79.0=rx79:tx79 +lane_to_serdes_map_fabric_lane80.0=rx80:tx80 +lane_to_serdes_map_fabric_lane81.0=rx81:tx81 +lane_to_serdes_map_fabric_lane82.0=rx82:tx82 +lane_to_serdes_map_fabric_lane83.0=rx83:tx83 +lane_to_serdes_map_fabric_lane84.0=rx84:tx84 +lane_to_serdes_map_fabric_lane85.0=rx85:tx85 +lane_to_serdes_map_fabric_lane86.0=rx86:tx86 +lane_to_serdes_map_fabric_lane87.0=rx87:tx87 +lane_to_serdes_map_fabric_lane88.0=rx88:tx88 +lane_to_serdes_map_fabric_lane89.0=rx89:tx89 +lane_to_serdes_map_fabric_lane90.0=rx90:tx90 +lane_to_serdes_map_fabric_lane91.0=rx91:tx91 +lane_to_serdes_map_fabric_lane92.0=rx92:tx92 +lane_to_serdes_map_fabric_lane93.0=rx93:tx93 +lane_to_serdes_map_fabric_lane94.0=rx94:tx94 +lane_to_serdes_map_fabric_lane95.0=rx95:tx95 +lane_to_serdes_map_fabric_lane96.0=rx96:tx96 +lane_to_serdes_map_fabric_lane97.0=rx97:tx97 +lane_to_serdes_map_fabric_lane98.0=rx98:tx98 +lane_to_serdes_map_fabric_lane99.0=rx99:tx99 +lane_to_serdes_map_fabric_lane100.0=rx100:tx100 +lane_to_serdes_map_fabric_lane101.0=rx101:tx101 +lane_to_serdes_map_fabric_lane102.0=rx102:tx102 +lane_to_serdes_map_fabric_lane103.0=rx103:tx103 +lane_to_serdes_map_fabric_lane104.0=rx104:tx104 +lane_to_serdes_map_fabric_lane105.0=rx105:tx105 +lane_to_serdes_map_fabric_lane106.0=rx106:tx106 +lane_to_serdes_map_fabric_lane107.0=rx107:tx107 +lane_to_serdes_map_fabric_lane108.0=rx108:tx108 +lane_to_serdes_map_fabric_lane109.0=rx109:tx109 +lane_to_serdes_map_fabric_lane110.0=rx110:tx110 +lane_to_serdes_map_fabric_lane111.0=rx111:tx111 + +lane_to_serdes_map_nif_lane0.0=rx5:tx7 +lane_to_serdes_map_nif_lane1.0=rx7:tx6 +lane_to_serdes_map_nif_lane2.0=rx4:tx5 +lane_to_serdes_map_nif_lane3.0=rx6:tx4 +lane_to_serdes_map_nif_lane4.0=rx0:tx0 +lane_to_serdes_map_nif_lane5.0=rx1:tx1 +lane_to_serdes_map_nif_lane6.0=rx2:tx3 +lane_to_serdes_map_nif_lane7.0=rx3:tx2 +lane_to_serdes_map_nif_lane8.0=rx13:tx15 +lane_to_serdes_map_nif_lane9.0=rx12:tx14 +lane_to_serdes_map_nif_lane10.0=rx15:tx13 +lane_to_serdes_map_nif_lane11.0=rx14:tx12 +lane_to_serdes_map_nif_lane12.0=rx10:tx10 +lane_to_serdes_map_nif_lane13.0=rx8:tx9 +lane_to_serdes_map_nif_lane14.0=rx9:tx11 +lane_to_serdes_map_nif_lane15.0=rx11:tx8 +lane_to_serdes_map_nif_lane16.0=rx23:tx23 +lane_to_serdes_map_nif_lane17.0=rx21:tx22 +lane_to_serdes_map_nif_lane18.0=rx22:tx21 +lane_to_serdes_map_nif_lane19.0=rx20:tx20 +lane_to_serdes_map_nif_lane20.0=rx16:tx18 +lane_to_serdes_map_nif_lane21.0=rx17:tx17 +lane_to_serdes_map_nif_lane22.0=rx18:tx16 +lane_to_serdes_map_nif_lane23.0=rx19:tx19 +lane_to_serdes_map_nif_lane24.0=rx31:tx31 +lane_to_serdes_map_nif_lane25.0=rx30:tx30 +lane_to_serdes_map_nif_lane26.0=rx29:tx29 +lane_to_serdes_map_nif_lane27.0=rx28:tx28 +lane_to_serdes_map_nif_lane28.0=rx24:tx26 +lane_to_serdes_map_nif_lane29.0=rx26:tx25 +lane_to_serdes_map_nif_lane30.0=rx25:tx24 +lane_to_serdes_map_nif_lane31.0=rx27:tx27 +lane_to_serdes_map_nif_lane32.0=rx39:tx35 +lane_to_serdes_map_nif_lane33.0=rx38:tx36 +lane_to_serdes_map_nif_lane34.0=rx32:tx32 +lane_to_serdes_map_nif_lane35.0=rx37:tx37 +lane_to_serdes_map_nif_lane36.0=rx33:tx34 +lane_to_serdes_map_nif_lane37.0=rx34:tx38 +lane_to_serdes_map_nif_lane38.0=rx35:tx33 +lane_to_serdes_map_nif_lane39.0=rx36:tx39 +lane_to_serdes_map_nif_lane40.0=rx44:tx47 +lane_to_serdes_map_nif_lane41.0=rx43:tx41 +lane_to_serdes_map_nif_lane42.0=rx47:tx46 +lane_to_serdes_map_nif_lane43.0=rx42:tx42 +lane_to_serdes_map_nif_lane44.0=rx45:tx45 +lane_to_serdes_map_nif_lane45.0=rx41:tx40 +lane_to_serdes_map_nif_lane46.0=rx46:tx44 +lane_to_serdes_map_nif_lane47.0=rx40:tx43 +lane_to_serdes_map_nif_lane48.0=rx55:tx55 +lane_to_serdes_map_nif_lane49.0=rx54:tx54 +lane_to_serdes_map_nif_lane50.0=rx53:tx53 +lane_to_serdes_map_nif_lane51.0=rx52:tx52 +lane_to_serdes_map_nif_lane52.0=rx48:tx48 +lane_to_serdes_map_nif_lane53.0=rx49:tx49 +lane_to_serdes_map_nif_lane54.0=rx50:tx50 +lane_to_serdes_map_nif_lane55.0=rx51:tx51 +lane_to_serdes_map_nif_lane56.0=rx60:tx60 +lane_to_serdes_map_nif_lane57.0=rx61:tx61 +lane_to_serdes_map_nif_lane58.0=rx62:tx63 +lane_to_serdes_map_nif_lane59.0=rx63:tx62 +lane_to_serdes_map_nif_lane60.0=rx58:tx59 +lane_to_serdes_map_nif_lane61.0=rx59:tx56 +lane_to_serdes_map_nif_lane62.0=rx57:tx58 +lane_to_serdes_map_nif_lane63.0=rx56:tx57 +lane_to_serdes_map_nif_lane64.0=rx68:tx69 +lane_to_serdes_map_nif_lane65.0=rx69:tx68 +lane_to_serdes_map_nif_lane66.0=rx70:tx71 +lane_to_serdes_map_nif_lane67.0=rx71:tx70 +lane_to_serdes_map_nif_lane68.0=rx67:tx64 +lane_to_serdes_map_nif_lane69.0=rx66:tx67 +lane_to_serdes_map_nif_lane70.0=rx65:tx65 +lane_to_serdes_map_nif_lane71.0=rx64:tx66 +lane_to_serdes_map_nif_lane72.0=rx78:tx76 +lane_to_serdes_map_nif_lane73.0=rx76:tx77 +lane_to_serdes_map_nif_lane74.0=rx79:tx78 +lane_to_serdes_map_nif_lane75.0=rx77:tx79 +lane_to_serdes_map_nif_lane76.0=rx75:tx72 +lane_to_serdes_map_nif_lane77.0=rx74:tx75 +lane_to_serdes_map_nif_lane78.0=rx73:tx73 +lane_to_serdes_map_nif_lane79.0=rx72:tx74 +lane_to_serdes_map_nif_lane80.0=rx81:tx83 +lane_to_serdes_map_nif_lane81.0=rx85:tx84 +lane_to_serdes_map_nif_lane82.0=rx80:tx80 +lane_to_serdes_map_nif_lane83.0=rx86:tx85 +lane_to_serdes_map_nif_lane84.0=rx82:tx82 +lane_to_serdes_map_nif_lane85.0=rx87:tx86 +lane_to_serdes_map_nif_lane86.0=rx83:tx81 +lane_to_serdes_map_nif_lane87.0=rx84:tx87 +lane_to_serdes_map_nif_lane88.0=rx91:tx95 +lane_to_serdes_map_nif_lane89.0=rx90:tx89 +lane_to_serdes_map_nif_lane90.0=rx95:tx94 +lane_to_serdes_map_nif_lane91.0=rx89:tx90 +lane_to_serdes_map_nif_lane92.0=rx93:tx93 +lane_to_serdes_map_nif_lane93.0=rx94:tx88 +lane_to_serdes_map_nif_lane94.0=rx92:tx92 +lane_to_serdes_map_nif_lane95.0=rx88:tx91 +phy_rx_polarity_flip_phy0=0 +phy_rx_polarity_flip_phy1=1 +phy_rx_polarity_flip_phy2=0 +phy_rx_polarity_flip_phy3=0 +phy_rx_polarity_flip_phy4=0 +phy_rx_polarity_flip_phy5=0 +phy_rx_polarity_flip_phy6=0 +phy_rx_polarity_flip_phy7=0 +phy_rx_polarity_flip_phy8=1 +phy_rx_polarity_flip_phy9=1 +phy_rx_polarity_flip_phy10=1 +phy_rx_polarity_flip_phy11=1 +phy_rx_polarity_flip_phy12=0 +phy_rx_polarity_flip_phy13=1 +phy_rx_polarity_flip_phy14=1 +phy_rx_polarity_flip_phy15=1 +phy_rx_polarity_flip_phy16=0 +phy_rx_polarity_flip_phy17=1 +phy_rx_polarity_flip_phy18=1 +phy_rx_polarity_flip_phy19=0 +phy_rx_polarity_flip_phy20=0 +phy_rx_polarity_flip_phy21=0 +phy_rx_polarity_flip_phy22=0 +phy_rx_polarity_flip_phy23=0 +phy_rx_polarity_flip_phy24=1 +phy_rx_polarity_flip_phy25=1 +phy_rx_polarity_flip_phy26=1 +phy_rx_polarity_flip_phy27=0 +phy_rx_polarity_flip_phy28=0 +phy_rx_polarity_flip_phy29=1 +phy_rx_polarity_flip_phy30=1 +phy_rx_polarity_flip_phy31=0 +phy_rx_polarity_flip_phy32=0 +phy_rx_polarity_flip_phy33=1 +phy_rx_polarity_flip_phy34=1 +phy_rx_polarity_flip_phy35=0 +phy_rx_polarity_flip_phy36=0 +phy_rx_polarity_flip_phy37=0 +phy_rx_polarity_flip_phy38=1 +phy_rx_polarity_flip_phy39=0 +phy_rx_polarity_flip_phy40=1 +phy_rx_polarity_flip_phy41=1 +phy_rx_polarity_flip_phy42=0 +phy_rx_polarity_flip_phy43=0 +phy_rx_polarity_flip_phy44=1 +phy_rx_polarity_flip_phy45=1 +phy_rx_polarity_flip_phy46=0 +phy_rx_polarity_flip_phy47=0 +phy_rx_polarity_flip_phy48=1 +phy_rx_polarity_flip_phy49=1 +phy_rx_polarity_flip_phy50=1 +phy_rx_polarity_flip_phy51=1 +phy_rx_polarity_flip_phy52=0 +phy_rx_polarity_flip_phy53=0 +phy_rx_polarity_flip_phy54=0 +phy_rx_polarity_flip_phy55=0 +phy_rx_polarity_flip_phy56=0 +phy_rx_polarity_flip_phy57=0 +phy_rx_polarity_flip_phy58=0 +phy_rx_polarity_flip_phy59=0 +phy_rx_polarity_flip_phy60=1 +phy_rx_polarity_flip_phy61=1 +phy_rx_polarity_flip_phy62=1 +phy_rx_polarity_flip_phy63=1 +phy_rx_polarity_flip_phy64=1 +phy_rx_polarity_flip_phy65=1 +phy_rx_polarity_flip_phy66=1 +phy_rx_polarity_flip_phy67=1 +phy_rx_polarity_flip_phy68=1 +phy_rx_polarity_flip_phy69=1 +phy_rx_polarity_flip_phy70=1 +phy_rx_polarity_flip_phy71=1 +phy_rx_polarity_flip_phy72=1 +phy_rx_polarity_flip_phy73=0 +phy_rx_polarity_flip_phy74=0 +phy_rx_polarity_flip_phy75=1 +phy_rx_polarity_flip_phy76=1 +phy_rx_polarity_flip_phy77=1 +phy_rx_polarity_flip_phy78=1 +phy_rx_polarity_flip_phy79=1 +phy_rx_polarity_flip_phy80=0 +phy_rx_polarity_flip_phy81=0 +phy_rx_polarity_flip_phy82=1 +phy_rx_polarity_flip_phy83=1 +phy_rx_polarity_flip_phy84=1 +phy_rx_polarity_flip_phy85=0 +phy_rx_polarity_flip_phy86=1 +phy_rx_polarity_flip_phy87=1 +phy_rx_polarity_flip_phy88=0 +phy_rx_polarity_flip_phy89=0 +phy_rx_polarity_flip_phy90=1 +phy_rx_polarity_flip_phy91=1 +phy_rx_polarity_flip_phy92=0 +phy_rx_polarity_flip_phy93=1 +phy_rx_polarity_flip_phy94=0 +phy_rx_polarity_flip_phy95=0 +phy_tx_polarity_flip_phy0=1 +phy_tx_polarity_flip_phy1=1 +phy_tx_polarity_flip_phy2=1 +phy_tx_polarity_flip_phy3=1 +phy_tx_polarity_flip_phy4=1 +phy_tx_polarity_flip_phy5=1 +phy_tx_polarity_flip_phy6=0 +phy_tx_polarity_flip_phy7=0 +phy_tx_polarity_flip_phy8=1 +phy_tx_polarity_flip_phy9=1 +phy_tx_polarity_flip_phy10=1 +phy_tx_polarity_flip_phy11=1 +phy_tx_polarity_flip_phy12=1 +phy_tx_polarity_flip_phy13=1 +phy_tx_polarity_flip_phy14=0 +phy_tx_polarity_flip_phy15=0 +phy_tx_polarity_flip_phy16=0 +phy_tx_polarity_flip_phy17=0 +phy_tx_polarity_flip_phy18=0 +phy_tx_polarity_flip_phy19=0 +phy_tx_polarity_flip_phy20=0 +phy_tx_polarity_flip_phy21=0 +phy_tx_polarity_flip_phy22=0 +phy_tx_polarity_flip_phy23=0 +phy_tx_polarity_flip_phy24=0 +phy_tx_polarity_flip_phy25=0 +phy_tx_polarity_flip_phy26=0 +phy_tx_polarity_flip_phy27=0 +phy_tx_polarity_flip_phy28=0 +phy_tx_polarity_flip_phy29=0 +phy_tx_polarity_flip_phy30=0 +phy_tx_polarity_flip_phy31=0 +phy_tx_polarity_flip_phy32=0 +phy_tx_polarity_flip_phy33=0 +phy_tx_polarity_flip_phy34=1 +phy_tx_polarity_flip_phy35=1 +phy_tx_polarity_flip_phy36=1 +phy_tx_polarity_flip_phy37=0 +phy_tx_polarity_flip_phy38=0 +phy_tx_polarity_flip_phy39=1 +phy_tx_polarity_flip_phy40=1 +phy_tx_polarity_flip_phy41=1 +phy_tx_polarity_flip_phy42=0 +phy_tx_polarity_flip_phy43=1 +phy_tx_polarity_flip_phy44=1 +phy_tx_polarity_flip_phy45=1 +phy_tx_polarity_flip_phy46=0 +phy_tx_polarity_flip_phy47=0 +phy_tx_polarity_flip_phy48=0 +phy_tx_polarity_flip_phy49=0 +phy_tx_polarity_flip_phy50=0 +phy_tx_polarity_flip_phy51=0 +phy_tx_polarity_flip_phy52=0 +phy_tx_polarity_flip_phy53=0 +phy_tx_polarity_flip_phy54=0 +phy_tx_polarity_flip_phy55=0 +phy_tx_polarity_flip_phy56=1 +phy_tx_polarity_flip_phy57=1 +phy_tx_polarity_flip_phy58=0 +phy_tx_polarity_flip_phy59=0 +phy_tx_polarity_flip_phy60=1 +phy_tx_polarity_flip_phy61=1 +phy_tx_polarity_flip_phy62=0 +phy_tx_polarity_flip_phy63=0 +phy_tx_polarity_flip_phy64=0 +phy_tx_polarity_flip_phy65=0 +phy_tx_polarity_flip_phy66=0 +phy_tx_polarity_flip_phy67=0 +phy_tx_polarity_flip_phy68=0 +phy_tx_polarity_flip_phy69=0 +phy_tx_polarity_flip_phy70=1 +phy_tx_polarity_flip_phy71=1 +phy_tx_polarity_flip_phy72=1 +phy_tx_polarity_flip_phy73=1 +phy_tx_polarity_flip_phy74=1 +phy_tx_polarity_flip_phy75=1 +phy_tx_polarity_flip_phy76=0 +phy_tx_polarity_flip_phy77=0 +phy_tx_polarity_flip_phy78=1 +phy_tx_polarity_flip_phy79=1 +phy_tx_polarity_flip_phy80=0 +phy_tx_polarity_flip_phy81=1 +phy_tx_polarity_flip_phy82=1 +phy_tx_polarity_flip_phy83=1 +phy_tx_polarity_flip_phy84=1 +phy_tx_polarity_flip_phy85=0 +phy_tx_polarity_flip_phy86=0 +phy_tx_polarity_flip_phy87=1 +phy_tx_polarity_flip_phy88=1 +phy_tx_polarity_flip_phy89=0 +phy_tx_polarity_flip_phy90=0 +phy_tx_polarity_flip_phy91=1 +phy_tx_polarity_flip_phy92=1 +phy_tx_polarity_flip_phy93=1 +phy_tx_polarity_flip_phy94=0 +phy_tx_polarity_flip_phy95=0 + +ucode_port_1=CGE2_0:core_0.1 +ucode_port_2=CGE2_1:core_0.2 +ucode_port_3=CGE2_2:core_0.3 +ucode_port_4=CGE2_3:core_0.4 +ucode_port_5=CGE2_4:core_0.5 +ucode_port_6=CGE2_5:core_0.6 +ucode_port_7=CGE2_6:core_0.7 +ucode_port_8=CGE2_7:core_0.8 +ucode_port_9=CGE2_8:core_0.9 +ucode_port_10=CGE2_9:core_0.10 +ucode_port_11=CGE2_10:core_0.11 +ucode_port_12=CGE2_11:core_0.12 +ucode_port_13=CGE2_12:core_0.13 +ucode_port_14=CGE2_13:core_0.14 +ucode_port_15=CGE2_14:core_0.15 +ucode_port_16=CGE2_15:core_0.16 +ucode_port_17=CGE2_36:core_1.17 +ucode_port_18=CGE2_37:core_1.18 +ucode_port_19=CGE2_38:core_1.19 +ucode_port_20=CGE2_39:core_1.20 +ucode_port_21=CGE2_32:core_1.21 +ucode_port_22=CGE2_33:core_1.22 +ucode_port_23=CGE2_34:core_1.23 +ucode_port_24=CGE2_35:core_1.24 +ucode_port_25=CGE2_28:core_1.25 +ucode_port_26=CGE2_29:core_1.26 +ucode_port_27=CGE2_30:core_1.27 +ucode_port_28=CGE2_31:core_1.28 +ucode_port_29=CGE2_24:core_1.29 +ucode_port_30=CGE2_25:core_1.30 +ucode_port_31=CGE2_26:core_1.31 +ucode_port_32=CGE2_27:core_1.32 + +port_fec_33=2 +port_fec_34=2 +port_fec_35=2 +port_fec_36=2 +port_fec_37=2 +port_fec_38=2 +port_fec_39=2 +port_fec_40=2 + +ucode_port_33=CGE8:core_0.33 +ucode_port_34=CGE9:core_0.34 +ucode_port_35=CGE10:core_0.35 +ucode_port_36=CGE11:core_0.36 +ucode_port_37=CGE22:core_1.37 +ucode_port_38=CGE23:core_1.38 +ucode_port_39=CGE20:core_1.39 +ucode_port_40=CGE21:core_1.40 + +rif_id_max=0x4000 + +dma_desc_aggregator_chain_length_max.BCM8869X=1000 +dma_desc_aggregator_buff_size_kb.BCM8869X=100 +dma_desc_aggregator_timeout_usec.BCM8869X=1000 +dma_desc_aggregator_enable_specific_MDB_LPM.BCM8869X=1 +dma_desc_aggregator_enable_specific_MDB_FEC.BCM8869X=1 diff --git a/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C40/port_config.ini b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C40/port_config.ini new file mode 100644 index 000000000000..2ba638aee50d --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C40/port_config.ini @@ -0,0 +1,41 @@ +# name lanes alias index speed +Ethernet0 0,1 Ethernet1/1 1 100000 +Ethernet4 2,3 Ethernet2/1 2 100000 +Ethernet8 4,5 Ethernet3/1 3 100000 +Ethernet12 6,7 Ethernet4/1 4 100000 +Ethernet16 8,9 Ethernet5/1 5 100000 +Ethernet20 10,11 Ethernet6/1 6 100000 +Ethernet24 12,13 Ethernet7/1 7 100000 +Ethernet28 14,15 Ethernet8/1 8 100000 +Ethernet32 16,17 Ethernet9/1 9 100000 +Ethernet36 18,19 Ethernet10/1 10 100000 +Ethernet40 20,21 Ethernet11/1 11 100000 +Ethernet44 22,23 Ethernet12/1 12 100000 +Ethernet48 24,25 Ethernet13/1 13 100000 +Ethernet52 26,27 Ethernet14/1 14 100000 +Ethernet56 28,29 Ethernet15/1 15 100000 +Ethernet60 30,31 Ethernet16/1 16 100000 +Ethernet64 72,73 Ethernet17/1 17 100000 +Ethernet68 74,75 Ethernet18/1 18 100000 +Ethernet72 76,77 Ethernet19/1 19 100000 +Ethernet76 78,79 Ethernet20/1 20 100000 +Ethernet80 64,65 Ethernet21/1 21 100000 +Ethernet84 66,67 Ethernet22/1 22 100000 +Ethernet88 68,69 Ethernet23/1 23 100000 +Ethernet92 70,71 Ethernet24/1 24 100000 +Ethernet96 56,57 Ethernet25/1 25 100000 +Ethernet100 58,59 Ethernet26/1 26 100000 +Ethernet104 60,61 Ethernet27/1 27 100000 +Ethernet108 62,63 Ethernet28/1 28 100000 +Ethernet112 48,49 Ethernet29/1 29 100000 +Ethernet116 50,51 Ethernet30/1 30 100000 +Ethernet120 52,53 Ethernet31/1 31 100000 +Ethernet124 54,55 Ethernet32/1 32 100000 +Ethernet128 32,33,34,35 Ethernet33/1 33 100000 +Ethernet132 36,37,38,39 Ethernet33/5 33 100000 +Ethernet136 40,41,42,43 Ethernet34/1 34 100000 +Ethernet140 44,45,46,47 Ethernet34/5 34 100000 +Ethernet144 88,89,90,91 Ethernet35/1 35 100000 +Ethernet148 92,93,94,95 Ethernet35/5 35 100000 +Ethernet152 80,81,82,83 Ethernet36/1 36 100000 +Ethernet156 84,85,86,87 Ethernet36/5 36 100000 diff --git a/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C40/sai.profile b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C40/sai.profile new file mode 100644 index 000000000000..ac1394486c61 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/Arista-7280CR3-C40/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/jr2-a7280cr3-32p4-40x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/arista/x86_64-arista_7280cr3_32p4/default_sku b/device/arista/x86_64-arista_7280cr3_32p4/default_sku new file mode 100644 index 000000000000..a65e1f845ad3 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/default_sku @@ -0,0 +1 @@ +Arista-7280CR3-C32P4 t1 diff --git a/device/arista/x86_64-arista_7280cr3_32p4/fancontrol b/device/arista/x86_64-arista_7280cr3_32p4/fancontrol new file mode 100644 index 000000000000..55a48e095084 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=5 +DEVPATH=hwmon2=devices/pci0000:00/0000:00:09.0 hwmon3=devices/pci0000:00/0000:00:09.0/i2c-56/56-004c +DEVNAME=hwmon2=scd_fan_p3 hwmon3=max6658 +FCTEMPS=hwmon2/pwm6=hwmon3/temp1_input hwmon2/pwm5=hwmon3/temp1_input hwmon2/pwm4=hwmon3/temp1_input hwmon2/pwm3=hwmon3/temp1_input hwmon2/pwm2=hwmon3/temp1_input hwmon2/pwm1=hwmon3/temp1_input +FCFANS=hwmon2/pwm6=hwmon2/fan6_input hwmon2/pwm5=hwmon2/fan5_input hwmon2/pwm4=hwmon2/fan4_input hwmon2/pwm3=hwmon2/fan3_input hwmon2/pwm2=hwmon2/fan2_input hwmon2/pwm1=hwmon2/fan1_input +MINTEMP=hwmon2/pwm6=50 hwmon2/pwm5=50 hwmon2/pwm4=50 hwmon2/pwm3=50 hwmon2/pwm2=50 hwmon2/pwm1=50 +MINPWM=hwmon2/pwm6=128 hwmon2/pwm5=128 hwmon2/pwm4=128 hwmon2/pwm3=128 hwmon2/pwm2=128 hwmon2/pwm1=128 +MAXTEMP=hwmon2/pwm6=60 hwmon2/pwm5=60 hwmon2/pwm4=60 hwmon2/pwm3=60 hwmon2/pwm2=60 hwmon2/pwm1=60 +MINSTART=hwmon2/pwm6=128 hwmon2/pwm5=128 hwmon2/pwm4=128 hwmon2/pwm3=128 hwmon2/pwm2=128 hwmon2/pwm1=128 +MINSTOP=hwmon2/pwm6=128 hwmon2/pwm5=128 hwmon2/pwm4=128 hwmon2/pwm3=128 hwmon2/pwm2=128 hwmon2/pwm1=128 diff --git a/device/arista/x86_64-arista_7280cr3_32p4/platform.json b/device/arista/x86_64-arista_7280cr3_32p4/platform.json new file mode 100644 index 000000000000..ebde92784715 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/platform.json @@ -0,0 +1,207 @@ +{ + "chassis": { + "name": "DCS-7280CR3K-32P4", + "components": [], + "fans": [], + "fan_drawers": [ + { + "name": "slot1", + "fans": [ + { + "name": "fan1" + }, + { + "name": "fan2" + } + ] + }, + { + "name": "slot2", + "fans": [ + { + "name": "fan3" + }, + { + "name": "fan4" + } + ] + }, + { + "name": "slot3", + "fans": [ + { + "name": "fan5" + }, + { + "name": "fan6" + } + ] + } + ], + "psus": [ + { + "name": "psu1", + "fans": [] + }, + { + "name": "psu2", + "fans": [] + } + ], + "thermals": [ + { + "name": "Cpu temp sensor" + }, + { + "name": "CPU board temp sensor" + }, + { + "name": "Back-panel temp sensor" + }, + { + "name": "Board Sensor" + }, + { + "name": "Front Air" + }, + { + "name": "Rear Air" + }, + { + "name": "Fap 0 Core 0" + }, + { + "name": "Fap 0 Core 1" + }, + { + "name": "Power supply 1 inlet temp sensor" + }, + { + "name": "Power supply 1 secondary hotspot sensor" + }, + { + "name": "Power supply 1 primary hotspot sensor" + }, + { + "name": "Power supply 2 inlet temp sensor" + }, + { + "name": "Power supply 2 secondary hotspot sensor" + }, + { + "name": "Power supply 2 primary hotspot sensor" + } + ], + "sfps": [ + { + "name": "qsfp1" + }, + { + "name": "qsfp2" + }, + { + "name": "qsfp3" + }, + { + "name": "qsfp4" + }, + { + "name": "qsfp5" + }, + { + "name": "qsfp6" + }, + { + "name": "qsfp7" + }, + { + "name": "qsfp8" + }, + { + "name": "qsfp9" + }, + { + "name": "qsfp10" + }, + { + "name": "qsfp11" + }, + { + "name": "qsfp12" + }, + { + "name": "qsfp13" + }, + { + "name": "qsfp14" + }, + { + "name": "qsfp15" + }, + { + "name": "qsfp16" + }, + { + "name": "qsfp17" + }, + { + "name": "qsfp18" + }, + { + "name": "qsfp19" + }, + { + "name": "qsfp20" + }, + { + "name": "qsfp21" + }, + { + "name": "qsfp22" + }, + { + "name": "qsfp23" + }, + { + "name": "qsfp24" + }, + { + "name": "qsfp25" + }, + { + "name": "qsfp26" + }, + { + "name": "qsfp27" + }, + { + "name": "qsfp28" + }, + { + "name": "qsfp29" + }, + { + "name": "qsfp30" + }, + { + "name": "qsfp31" + }, + { + "name": "qsfp32" + }, + { + "name": "osfp33" + }, + { + "name": "osfp34" + }, + { + "name": "osfp35" + }, + { + "name": "osfp36" + } + ] + }, + "interfaces": {} +} diff --git a/device/arista/x86_64-arista_7280cr3_32p4/platform_reboot b/device/arista/x86_64-arista_7280cr3_32p4/platform_reboot new file mode 120000 index 000000000000..7f94a49e38b0 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/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_7280cr3_32p4/plugins b/device/arista/x86_64-arista_7280cr3_32p4/plugins new file mode 120000 index 000000000000..5fbbf98a6284 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/plugins @@ -0,0 +1 @@ +../x86_64-arista_common/plugins/ \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32p4/pmon_daemon_control.json b/device/arista/x86_64-arista_7280cr3_32p4/pmon_daemon_control.json new file mode 120000 index 000000000000..51d5ab7b0059 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32p4/sensors.conf b/device/arista/x86_64-arista_7280cr3_32p4/sensors.conf new file mode 100644 index 000000000000..2a80dbd612ac --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/sensors.conf @@ -0,0 +1,66 @@ +# libsensors configuration file for DCS-7280CR3-32P4 +# ------------------------------------------------# + +bus "i2c-8" "SCD 0000:02:00.0 SMBus master 0 bus 0" +bus "i2c-14" "SCD 0000:02:00.0 SMBus master 0 bus 6" +bus "i2c-15" "SCD 0000:02:00.0 SMBus master 0 bus 7" +bus "i2c-56" "SCD 0000:00:09.0 SMBus master 0 bus 0" + +chip "tmp468-i2c-8-48" + label temp1 "Board sensor" + label temp2 "Front air (inlet) sensor" + label temp3 "Rear air sensor" + label temp4 "Front left sensor" + label temp5 "Front right sensor" + label temp6 "Rear left sensor" + label temp7 "Rear right sensor" + label temp8 "Asic temp sensor 1" + label temp9 "Asic temp sensor 2" + + set temp1_max 75 + set temp1_crit 80 + set temp2_max 65 + set temp2_crit 75 + set temp3_max 65 + set temp3_crit 75 + ignore temp4 + ignore temp5 + ignore temp6 + ignore temp7 + set temp8_max 100 + set temp8_crit 110 + set temp9_max 100 + set temp9_crit 110 + +chip "pmbus-i2c-14-58" + label temp1 "Power supply 1 hotspot sensor" + label temp2 "Power supply 1 inlet temp sensor" + label temp3 "Power supply 1 exhaust temp sensor" + + # setting maximum and critical thresholds is not supported for this psu + # fault and warning limits defined internally by hardware + + ignore fan2 + ignore fan3 + ignore fan4 + +chip "pmbus-i2c-15-58" + label temp1 "Power supply 2 hotspot sensor" + label temp2 "Power supply 2 inlet temp sensor" + label temp3 "Power supply 2 exhaust temp sensor" + + # setting maximum and critical thresholds is not supported for this psu + # fault and warning limits defined internally by hardware + + ignore fan2 + ignore fan3 + ignore fan4 + +chip "max6658-i2c-56-4c" + label temp1 "Back panel temp sensor 1" + label temp2 "Back panel temp sensor 2" + + set temp1_max 75 + set temp1_crit 85 + set temp2_max 75 + set temp2_crit 85 diff --git a/device/arista/x86_64-arista_7280cr3_32p4/system_health_monitoring_config.json b/device/arista/x86_64-arista_7280cr3_32p4/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32p4/thermal_policy.json b/device/arista/x86_64-arista_7280cr3_32p4/thermal_policy.json new file mode 120000 index 000000000000..0991dc7f3638 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-arista_common/thermal_policy.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3k_32d4 b/device/arista/x86_64-arista_7280cr3k_32d4 new file mode 120000 index 000000000000..50478132d933 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3k_32d4 @@ -0,0 +1 @@ +x86_64-arista_7280cr3_32d4 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3k_32p4 b/device/arista/x86_64-arista_7280cr3k_32p4 new file mode 120000 index 000000000000..d6e2ddbb64bd --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3k_32p4 @@ -0,0 +1 @@ +x86_64-arista_7280cr3_32p4 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3mk_32d4 b/device/arista/x86_64-arista_7280cr3mk_32d4 new file mode 120000 index 000000000000..50478132d933 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3mk_32d4 @@ -0,0 +1 @@ +x86_64-arista_7280cr3_32d4 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3mk_32p4 b/device/arista/x86_64-arista_7280cr3mk_32p4 new file mode 120000 index 000000000000..d6e2ddbb64bd --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3mk_32p4 @@ -0,0 +1 @@ +x86_64-arista_7280cr3_32p4 \ No newline at end of file diff --git a/device/arista/x86_64-arista_7800_sup/chassisdb.conf b/device/arista/x86_64-arista_7800_sup/chassisdb.conf new file mode 100644 index 000000000000..3918a00c4ee9 --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/chassisdb.conf @@ -0,0 +1,2 @@ +start_chassis_db=1 +chassis_db_address=127.100.1.1 diff --git a/device/arista/x86_64-arista_7800_sup/platform_reboot b/device/arista/x86_64-arista_7800_sup/platform_reboot new file mode 120000 index 000000000000..7f94a49e38b0 --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/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_7800_sup/plugins/eeprom.py b/device/arista/x86_64-arista_7800_sup/plugins/eeprom.py new file mode 120000 index 000000000000..35cfaff3de4e --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/plugins/eeprom.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/eeprom.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7800_sup/plugins/led_control.py b/device/arista/x86_64-arista_7800_sup/plugins/led_control.py new file mode 120000 index 000000000000..8d733780117e --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/plugins/led_control.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/led_control.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7800_sup/plugins/psuutil.py b/device/arista/x86_64-arista_7800_sup/plugins/psuutil.py new file mode 120000 index 000000000000..2b0024ade969 --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/plugins/psuutil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/psuutil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7800_sup/plugins/sfputil.py b/device/arista/x86_64-arista_7800_sup/plugins/sfputil.py new file mode 120000 index 000000000000..c333e23763d7 --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/plugins/sfputil.py @@ -0,0 +1 @@ +../../x86_64-arista_common/plugins/sfputil.py \ No newline at end of file diff --git a/device/arista/x86_64-arista_7800_sup/plugins/udevprefix.conf b/device/arista/x86_64-arista_7800_sup/plugins/udevprefix.conf new file mode 100644 index 000000000000..e2f2966c864d --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/plugins/udevprefix.conf @@ -0,0 +1 @@ +ttySCD \ No newline at end of file diff --git a/device/arista/x86_64-arista_7800_sup/pmon_daemon_control.json b/device/arista/x86_64-arista_7800_sup/pmon_daemon_control.json new file mode 100644 index 000000000000..fbec8f525160 --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_ledd": true, + "skip_xcvrd": true +} diff --git a/device/arista/x86_64-arista_7800_sup/system_health_monitoring_config.json b/device/arista/x86_64-arista_7800_sup/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7800r3_48cq2_lc/chassisdb.conf b/device/arista/x86_64-arista_7800r3_48cq2_lc/chassisdb.conf new file mode 100644 index 000000000000..75dc7d65703b --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cq2_lc/chassisdb.conf @@ -0,0 +1 @@ +chassis_db_address=127.100.1.1 diff --git a/device/arista/x86_64-arista_7800r3_48cq2_lc/plugins b/device/arista/x86_64-arista_7800r3_48cq2_lc/plugins new file mode 120000 index 000000000000..5fbbf98a6284 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cq2_lc/plugins @@ -0,0 +1 @@ +../x86_64-arista_common/plugins/ \ No newline at end of file diff --git a/generic/platform.conf b/device/arista/x86_64-arista_7800r3_48cq2_lc/sensors.conf similarity index 100% rename from generic/platform.conf rename to device/arista/x86_64-arista_7800r3_48cq2_lc/sensors.conf diff --git a/device/arista/x86_64-arista_7800r3_48cq2_lc/system_health_monitoring_config.json b/device/arista/x86_64-arista_7800r3_48cq2_lc/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cq2_lc/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7800r3_48cqm2_lc/plugins b/device/arista/x86_64-arista_7800r3_48cqm2_lc/plugins new file mode 120000 index 000000000000..5fbbf98a6284 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cqm2_lc/plugins @@ -0,0 +1 @@ +../x86_64-arista_common/plugins/ \ No newline at end of file diff --git a/device/arista/x86_64-arista_7800r3_48cqm2_lc/sensors.conf b/device/arista/x86_64-arista_7800r3_48cqm2_lc/sensors.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/arista/x86_64-arista_7800r3_48cqm2_lc/system_health_monitoring_config.json b/device/arista/x86_64-arista_7800r3_48cqm2_lc/system_health_monitoring_config.json new file mode 120000 index 000000000000..1185f771fa8e --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cqm2_lc/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-arista_common/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_common/platform_reboot b/device/arista/x86_64-arista_common/platform_reboot new file mode 100755 index 000000000000..1c3f954c03cc --- /dev/null +++ b/device/arista/x86_64-arista_common/platform_reboot @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import arista.platforms +from arista.utils.sonic_reboot import reboot + + +def main(): + # reboot the system + reboot() + + +if __name__ == "__main__": + main() diff --git a/device/arista/x86_64-arista_common/plugins/eeprom.py b/device/arista/x86_64-arista_common/plugins/eeprom.py new file mode 100644 index 000000000000..3cc5a6b13c59 --- /dev/null +++ b/device/arista/x86_64-arista_common/plugins/eeprom.py @@ -0,0 +1,11 @@ +# +# Arista eeprom processing for SONiC +# Uses the arista driver library to obtain the TlvInfoDecoder +# + +try: + import arista.utils.sonic_eeprom as arista_eeprom +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +board = arista_eeprom.getTlvInfoDecoder() diff --git a/device/arista/x86_64-arista_common/plugins/led_control.py b/device/arista/x86_64-arista_common/plugins/led_control.py new file mode 100644 index 000000000000..8ea9f70a8604 --- /dev/null +++ b/device/arista/x86_64-arista_common/plugins/led_control.py @@ -0,0 +1,10 @@ +# +# Arista LED controls for SONiC +# + +try: + import arista.utils.sonic_leds as arista_leds +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +LedControl = arista_leds.getLedControl() diff --git a/device/arista/x86_64-arista_common/plugins/psuutil.py b/device/arista/x86_64-arista_common/plugins/psuutil.py new file mode 100644 index 000000000000..14755365257b --- /dev/null +++ b/device/arista/x86_64-arista_common/plugins/psuutil.py @@ -0,0 +1,10 @@ +# +# Arista PSU interface for SONiC +# + +try: + import arista.utils.sonic_psu as arista_psuutil +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +PsuUtil = arista_psuutil.getPsuUtil() diff --git a/device/arista/x86_64-arista_common/plugins/sfputil.py b/device/arista/x86_64-arista_common/plugins/sfputil.py new file mode 100644 index 000000000000..4c99ad533f27 --- /dev/null +++ b/device/arista/x86_64-arista_common/plugins/sfputil.py @@ -0,0 +1,10 @@ +# +# Arista SFP transceiver interface for SONiC +# + +try: + import arista.utils.sonic_sfputil as arista_sfputil +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +SfpUtil = arista_sfputil.getSfpUtil() diff --git a/device/arista/x86_64-arista_common/pmon_daemon_control.json b/device/arista/x86_64-arista_common/pmon_daemon_control.json new file mode 100644 index 000000000000..6453cd2c5d0d --- /dev/null +++ b/device/arista/x86_64-arista_common/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_fancontrol": true +} + diff --git a/device/arista/x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json b/device/arista/x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json new file mode 100644 index 000000000000..75db6d97558a --- /dev/null +++ b/device/arista/x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json @@ -0,0 +1,4 @@ +{ + "skip_thermalctld": true +} + diff --git a/device/arista/x86_64-arista_common/system_health_monitoring_config.json b/device/arista/x86_64-arista_common/system_health_monitoring_config.json new file mode 100644 index 000000000000..5ceec23fd26f --- /dev/null +++ b/device/arista/x86_64-arista_common/system_health_monitoring_config.json @@ -0,0 +1,16 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "asic", + "psu.temperature", + "PSU2 Fan", + "PSU1 Fan" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "amber", + "normal": "green", + "booting": "amber_blink" + } +} diff --git a/device/arista/x86_64-arista_common/thermal_policy.json b/device/arista/x86_64-arista_common/thermal_policy.json new file mode 100644 index 000000000000..bc1bd0acfad0 --- /dev/null +++ b/device/arista/x86_64-arista_common/thermal_policy.json @@ -0,0 +1,60 @@ +{ + "thermal_control_algorithm": { + "run_at_boot_up": "true", + "fan_speed_when_suspend": "100" + }, + "info_types": [ + { + "type": "control_info" + }, + { + "type": "fan_info" + }, + { + "type": "thermal_info" + } + ], + "policies": [ + { + "name": "any thermal critical", + "conditions": [ + { + "type": "thermal.any.critical" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any thermal overheat", + "conditions": [ + { + "type": "thermal.any.overheat" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "normal operations", + "conditions": [ + { + "type": "normal" + } + ], + "actions": [ + { + "type": "thermal_control.control" + } + ] + } + ] +} diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/default_sku b/device/barefoot/x86_64-accton_as9516_32d-r0/default_sku new file mode 100644 index 000000000000..517fa893ae11 --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/default_sku @@ -0,0 +1 @@ +newport t1 diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/installer.conf b/device/barefoot/x86_64-accton_as9516_32d-r0/installer.conf new file mode 100644 index 000000000000..3714ff053bb0 --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=57600 diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/newport/buffers.json.j2 b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/newport/buffers_defaults_t0.j2 b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..33698097285e --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/buffers_defaults_t0.j2 @@ -0,0 +1,71 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '23850816' %} +{% set ingress_lossy_pool_size = '36222208' %} +{% set egress_lossless_pool_size = '29482816' %} +{% set egress_lossy_pool_size = '26400000' %} + +{%- 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": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic", + "xoff": "36222208" + }, + "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_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "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":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/newport/buffers_defaults_t1.j2 b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..33698097285e --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/buffers_defaults_t1.j2 @@ -0,0 +1,71 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '23850816' %} +{% set ingress_lossy_pool_size = '36222208' %} +{% set egress_lossless_pool_size = '29482816' %} +{% set egress_lossy_pool_size = '26400000' %} + +{%- 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": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic", + "xoff": "36222208" + }, + "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_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "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":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/newport/pg_profile_lookup.ini b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/pg_profile_lookup.ini new file mode 100644 index 000000000000..602400325be0 --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/pg_profile_lookup.ini @@ -0,0 +1,20 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 34816 18432 16384 7 + 25000 5m 34816 18432 16384 7 + 40000 5m 34816 18432 16384 7 + 50000 5m 34816 18432 16384 7 + 100000 5m 36864 18432 18432 7 + 400000 5m 36864 18432 18432 7 + 10000 40m 36864 18432 18432 7 + 25000 40m 39936 18432 21504 7 + 40000 40m 41984 18432 23552 7 + 50000 40m 41984 18432 23552 7 + 100000 40m 54272 18432 35840 7 + 400000 40m 54272 18432 35840 7 + 10000 300m 49152 18432 30720 7 + 25000 300m 71680 18432 53248 7 + 40000 300m 94208 18432 75776 7 + 50000 300m 94208 18432 75776 7 + 100000 300m 184320 18432 165888 7 + 400000 300m 184320 18432 165888 7 diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/newport/port_config.ini b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/port_config.ini new file mode 100644 index 000000000000..3a3be79dc675 --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed autoneg fec +Ethernet0 0,1,2,3,4,5,6,7 Ethernet0 1 400000 0 rs +Ethernet8 8,9,10,11,12,13,14,15 Ethernet8 2 400000 0 rs +Ethernet16 16,17,18,19,20,21,22,23 Ethernet16 3 400000 0 rs +Ethernet24 24,25,26,27,28,29,30,31 Ethernet24 4 400000 0 rs +Ethernet32 32,33,34,35,36,37,38,39 Ethernet32 5 400000 0 rs +Ethernet40 40,41,42,43,44,45,46,47 Ethernet40 6 400000 0 rs +Ethernet48 48,49,50,51,52,53,54,55 Ethernet48 7 400000 0 rs +Ethernet56 56,57,58,59,60,61,62,63 Ethernet56 8 400000 0 rs +Ethernet64 64,65,66,67,68,69,70,71 Ethernet64 9 400000 0 rs +Ethernet72 72,73,74,75,76,77,78,79 Ethernet72 10 400000 0 rs +Ethernet80 80,81,82,83,84,85,86,87 Ethernet80 11 400000 0 rs +Ethernet88 88,89,90,91,92,93,94,95 Ethernet88 12 400000 0 rs +Ethernet96 96,97,98,99,100,101,102,103 Ethernet96 13 400000 0 rs +Ethernet104 104,105,106,107,108,109,110,111 Ethernet104 14 400000 0 rs +Ethernet112 112,113,114,115,116,117,118,119 Ethernet112 15 400000 0 rs +Ethernet120 120,121,122,123,124,125,126,127 Ethernet120 16 400000 0 rs +Ethernet128 128,129,130,131,132,133,134,135 Ethernet128 17 400000 0 rs +Ethernet136 136,137,138,139,140,141,142,143 Ethernet136 18 400000 0 rs +Ethernet144 144,145,146,147,148,149,150,151 Ethernet144 19 400000 0 rs +Ethernet152 152,153,154,155,156,157,158,159 Ethernet152 20 400000 0 rs +Ethernet160 160,161,162,163,164,165,166,167 Ethernet160 21 400000 0 rs +Ethernet168 168,169,170,171,172,173,174,175 Ethernet168 22 400000 0 rs +Ethernet176 176,177,178,179,180,181,182,183 Ethernet176 23 400000 0 rs +Ethernet184 184,185,186,187,188,189,190,191 Ethernet184 24 400000 0 rs +Ethernet192 192,193,194,195,196,197,198,199 Ethernet192 25 400000 0 rs +Ethernet200 200,201,202,203,204,205,206,207 Ethernet200 26 400000 0 rs +Ethernet208 208,209,210,211,212,213,214,215 Ethernet208 27 400000 0 rs +Ethernet216 216,217,218,219,220,221,222,223 Ethernet216 28 400000 0 rs +Ethernet224 224,225,226,227,228,229,230,231 Ethernet224 29 400000 0 rs +Ethernet232 232,233,234,235,236,237,238,239 Ethernet232 30 400000 0 rs +Ethernet240 240,241,242,243,244,245,246,247 Ethernet240 31 400000 0 rs +Ethernet248 248,249,250,251,252,253,254,255 Ethernet248 32 400000 0 rs diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/newport/qos.json.j2 b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/qos.json.j2 new file mode 100644 index 000000000000..a685277448f1 --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/qos.json.j2 @@ -0,0 +1,10 @@ +{%- macro generate_tc_to_pg_map() %} + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, +{%- endmacro %} + +{%- include 'qos_config.j2' %} diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/newport/sai.profile b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/sai.profile new file mode 100644 index 000000000000..037b5c135370 --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/sai.profile @@ -0,0 +1,3 @@ +SAI_KEY_WARM_BOOT_WRITE_FILE=/var/warmboot/sai-warmboot.bin +SAI_KEY_WARM_BOOT_READ_FILE=/var/warmboot/sai-warmboot.bin + diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/newport/switch-tna-sai.conf b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/switch-tna-sai.conf new file mode 100644 index 000000000000..ca838c1bb5da --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/newport/switch-tna-sai.conf @@ -0,0 +1,41 @@ +{ + "instance": 0, + "chip_list": [ + { + "id": "asic-0", + "chip_family": "Tofino2", + "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, + "agent0": "lib/platform/x86_64-accton_as9516bf_32d-r0/libpltfm_mgr.so", + "p4_programs": [ + { + "p4_pipelines": [ + { + "p4_pipeline_name": "pipe", + "config": "share/switch/pipe/tofino2.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, + "cpu_port": "eth2" + } + ] + } + ] +} diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/pcie.yaml b/device/barefoot/x86_64-accton_as9516_32d-r0/pcie.yaml new file mode 100644 index 000000000000..c45064a9f73c --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/pcie.yaml @@ -0,0 +1,428 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 6f00 + name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 6f02 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '01' + fn: '1' + id: 6f03 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 6f04 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '2' + id: 6f06 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 6f08 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '05' + fn: '0' + id: 6f28 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Map/VTd_Misc/System Management (rev 03)' +- bus: '00' + dev: '05' + fn: '1' + id: 6f29 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO Hot Plug (rev 03)' +- bus: '00' + dev: '05' + fn: '2' + id: 6f2a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO RAS/Control Status/Global Errors (rev 03)' +- bus: '00' + dev: '05' + fn: '4' + id: 6f2c + name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev + 03)' +- bus: '00' + dev: '16' + fn: '0' + id: 8c3a + name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset + Family MEI Controller #1 (rev 04)' +- bus: '00' + dev: '16' + fn: '1' + id: 8c3b + name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset + Family MEI Controller #2 (rev 04)' +- bus: '00' + dev: 1c + fn: '0' + id: 8c10 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #1 (rev d5)' +- bus: '00' + dev: 1d + fn: '0' + id: 8c26 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + EHCI #1 (rev 05)' +- bus: '00' + dev: 1f + fn: '0' + id: 8c54 + name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard + SKU LPC Controller (rev 05)' +- bus: '00' + dev: 1f + fn: '2' + id: 8c02 + name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port + SATA Controller 1 [AHCI mode] (rev 05)' +- bus: '00' + dev: 1f + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller + (rev 05)' +- bus: '02' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '03' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '03' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '03' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '03' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '04' + dev: '00' + fn: '0' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '04' + dev: '00' + fn: '1' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '06' + dev: '00' + fn: '0' + id: '0100' + name: 'Ethernet controller: Device 1d1c:0100' +- bus: '07' + dev: '00' + fn: '0' + id: 01f0 + name: 'Memory controller: Device 1d1c:01f0' +- bus: ff + dev: 0b + fn: '0' + id: 6f81 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '1' + id: 6f36 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '2' + id: 6f37 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '3' + id: 6f76 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link Debug (rev 03)' +- bus: ff + dev: 0c + fn: '0' + id: 6fe0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '1' + id: 6fe1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '2' + id: 6fe2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '3' + id: 6fe3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '0' + id: 6ff8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '4' + id: 6ffc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '5' + id: 6ffd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '6' + id: 6ffe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: '10' + fn: '0' + id: 6f1d + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '1' + id: 6f34 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '5' + id: 6f1e + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '6' + id: 6f7d + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '7' + id: 6f1f + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '12' + fn: '0' + id: 6fa0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '12' + fn: '1' + id: 6f30 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '13' + fn: '0' + id: 6fa8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '1' + id: 6f71 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '2' + id: 6faa + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '3' + id: 6fab + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '4' + id: 6fac + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '5' + id: 6fad + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '6' + id: 6fae + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Broadcast (rev 03)' +- bus: ff + dev: '13' + fn: '7' + id: 6faf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Global Broadcast (rev 03)' +- bus: ff + dev: '14' + fn: '0' + id: 6fb0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '1' + id: 6fb1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '2' + id: 6fb2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Error (rev 03)' +- bus: ff + dev: '14' + fn: '3' + id: 6fb3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Error (rev 03)' +- bus: ff + dev: '14' + fn: '4' + id: 6fbc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '5' + id: 6fbd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '6' + id: 6fbe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '7' + id: 6fbf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '15' + fn: '0' + id: 6fb4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '1' + id: 6fb5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '2' + id: 6fb6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Error (rev 03)' +- bus: ff + dev: '15' + fn: '3' + id: 6fb7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Error (rev 03)' +- bus: ff + dev: 1e + fn: '0' + id: 6f98 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '1' + id: 6f99 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '2' + id: 6f9a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '3' + id: 6fc0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '4' + id: 6f9c + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '0' + id: 6f88 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '2' + id: 6f8a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/plugins b/device/barefoot/x86_64-accton_as9516_32d-r0/plugins new file mode 120000 index 000000000000..a8464d1ec2b6 --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/plugins @@ -0,0 +1 @@ +../x86_64-accton_wedge100bf_32x-r0/plugins/ \ No newline at end of file diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/pmon_daemon_control.json b/device/barefoot/x86_64-accton_as9516_32d-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..c4573af5e93d --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/pmon_daemon_control.json @@ -0,0 +1,9 @@ +{ + "skip_pcied": false, + "skip_fancontrol": true, + "skip_thermalctld": true, + "skip_ledd": true, + "skip_xcvrd": false, + "skip_psud": false, + "skip_syseepromd": false +} diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/syncd.conf b/device/barefoot/x86_64-accton_as9516_32d-r0/syncd.conf new file mode 100644 index 000000000000..11956f83a5af --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/syncd.conf @@ -0,0 +1,29 @@ +#!/bin/bash + + +y_profile_set() { + P4_PROFILE=$(sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["p4_profile"]') + if [[ -n "$P4_PROFILE" || ( ! -L /opt/bfn/install && -e /opt/bfn/install ) ]]; then + return + fi + + if [[ $(readlink /opt/bfn/install) =~ "install_y" ]]; then + echo "/opt/bfn/install is a link to Y profile" + return + fi + + Y_PROFILE=$(ls -d /opt/bfn/install_y*_profile 2> /dev/null | head -1) + if [[ -z $Y_PROFILE ]]; then + echo "No P4 profile found for Newport" + return + fi + + echo "Link /opt/bfn/install to $Y_PROFILE" + ln -srfn $Y_PROFILE /opt/bfn/install +} + +( + unset PYTHONPATH + unset PYTHONHOME + y_profile_set +) diff --git a/device/barefoot/x86_64-accton_as9516bf_32d-r0 b/device/barefoot/x86_64-accton_as9516bf_32d-r0 new file mode 120000 index 000000000000..93f47d51b742 --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516bf_32d-r0 @@ -0,0 +1 @@ +x86_64-accton_as9516_32d-r0 \ No newline at end of file diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/default_sku b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/default_sku new file mode 100644 index 000000000000..e2f0630cc576 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/default_sku @@ -0,0 +1 @@ +montara t1 diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/installer.conf b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/installer.conf new file mode 100644 index 000000000000..3714ff053bb0 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=57600 diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers.json.j2 b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t0.j2 b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..73e95a457a2a --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t0.j2 @@ -0,0 +1,83 @@ +{% 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' %} + +{%- 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": "{{ 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":"4096", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"4096", + "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":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t1.j2 b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..fce82ea2edf5 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t1.j2 @@ -0,0 +1,83 @@ +{% 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' %} + +{%- 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": "{{ 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":"4096", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"4096", + "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":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/hwsku.json b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/hwsku.json new file mode 100644 index 000000000000..a253fa3bd480 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/hwsku.json @@ -0,0 +1,164 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + } + } +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/pg_profile_lookup.ini b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/pg_profile_lookup.ini new file mode 100644 index 000000000000..b66b129fe43f --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/port_config.ini b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/port_config.ini new file mode 100644 index 000000000000..d98c55a4e882 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed autoneg fec +Ethernet0 0,1,2,3 Ethernet0 1 100000 0 rs +Ethernet4 4,5,6,7 Ethernet4 2 100000 0 rs +Ethernet8 8,9,10,11 Ethernet8 3 100000 0 rs +Ethernet12 12,13,14,15 Ethernet12 4 100000 0 rs +Ethernet16 16,17,18,19 Ethernet16 5 100000 0 rs +Ethernet20 20,21,22,23 Ethernet20 6 100000 0 rs +Ethernet24 24,25,26,27 Ethernet24 7 100000 0 rs +Ethernet28 28,29,30,31 Ethernet28 8 100000 0 rs +Ethernet32 32,33,34,35 Ethernet32 9 100000 0 rs +Ethernet36 36,37,38,39 Ethernet36 10 100000 0 rs +Ethernet40 40,41,42,43 Ethernet40 11 100000 0 rs +Ethernet44 44,45,46,47 Ethernet44 12 100000 0 rs +Ethernet48 48,49,50,51 Ethernet48 13 100000 0 rs +Ethernet52 52,53,54,55 Ethernet52 14 100000 0 rs +Ethernet56 56,57,58,59 Ethernet56 15 100000 0 rs +Ethernet60 60,61,62,63 Ethernet60 16 100000 0 rs +Ethernet64 64,65,66,67 Ethernet64 17 100000 0 rs +Ethernet68 68,69,70,71 Ethernet68 18 100000 0 rs +Ethernet72 72,73,74,75 Ethernet72 19 100000 0 rs +Ethernet76 76,77,78,79 Ethernet76 20 100000 0 rs +Ethernet80 80,81,82,83 Ethernet80 21 100000 0 rs +Ethernet84 84,85,86,87 Ethernet84 22 100000 0 rs +Ethernet88 88,89,90,91 Ethernet88 23 100000 0 rs +Ethernet92 92,93,94,95 Ethernet92 24 100000 0 rs +Ethernet96 96,97,98,99 Ethernet96 25 100000 0 rs +Ethernet100 100,101,102,103 Ethernet100 26 100000 0 rs +Ethernet104 104,105,106,107 Ethernet104 27 100000 0 rs +Ethernet108 108,109,110,111 Ethernet108 28 100000 0 rs +Ethernet112 112,113,114,115 Ethernet112 29 100000 0 rs +Ethernet116 116,117,118,119 Ethernet116 30 100000 0 rs +Ethernet120 120,121,122,123 Ethernet120 31 100000 0 rs +Ethernet124 124,125,126,127 Ethernet124 32 100000 0 rs diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/qos.json.j2 b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/qos.json.j2 new file mode 100644 index 000000000000..a685277448f1 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/qos.json.j2 @@ -0,0 +1,10 @@ +{%- macro generate_tc_to_pg_map() %} + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, +{%- endmacro %} + +{%- include 'qos_config.j2' %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/sai.profile b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/sai.profile new file mode 100644 index 000000000000..037b5c135370 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/sai.profile @@ -0,0 +1,3 @@ +SAI_KEY_WARM_BOOT_WRITE_FILE=/var/warmboot/sai-warmboot.bin +SAI_KEY_WARM_BOOT_READ_FILE=/var/warmboot/sai-warmboot.bin + diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/switch-sai.conf b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/switch-sai.conf new file mode 100644 index 000000000000..fc224c9602e4 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/switch-sai.conf @@ -0,0 +1,34 @@ +{ + "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" + } + ], + "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", + "agent0": "lib/platform/x86_64-accton_wedge100bf_32x-r0/libpltfm_mgr.so", + "switchapi_port_add": false, + "non_default_port_ppgs": 5 + } + ] +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/switch-tna-sai.conf b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/switch-tna-sai.conf new file mode 100644 index 000000000000..085a1b8dcdfc --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/switch-tna-sai.conf @@ -0,0 +1,40 @@ +{ + "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, + "agent0": "lib/platform/x86_64-accton_wedge100bf_32x-r0/libpltfm_mgr.so", + "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/barefoot/x86_64-accton_wedge100bf_32x-r0/pcie.yaml b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/pcie.yaml new file mode 100644 index 000000000000..ab38096c9740 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/pcie.yaml @@ -0,0 +1,412 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 6f00 + name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 6f02 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '01' + fn: '1' + id: 6f03 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 6f04 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '2' + id: 6f06 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 6f08 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '05' + fn: '0' + id: 6f28 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Map/VTd_Misc/System Management (rev 03)' +- bus: '00' + dev: '05' + fn: '1' + id: 6f29 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO Hot Plug (rev 03)' +- bus: '00' + dev: '05' + fn: '2' + id: 6f2a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO RAS/Control Status/Global Errors (rev 03)' +- bus: '00' + dev: '05' + fn: '4' + id: 6f2c + name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev + 03)' +- bus: '00' + dev: '14' + fn: '0' + id: 8c31 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + xHCI (rev 05)' +- bus: '00' + dev: 1d + fn: '0' + id: 8c26 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + EHCI #1 (rev 05)' +- bus: '00' + dev: 1f + fn: '0' + id: 8c54 + name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard + SKU LPC Controller (rev 05)' +- bus: '00' + dev: 1f + fn: '2' + id: 8c02 + name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port + SATA Controller 1 [AHCI mode] (rev 05)' +- bus: '00' + dev: 1f + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller + (rev 05)' +- bus: '00' + dev: 1f + fn: '6' + id: 8c24 + name: 'Signal processing controller: Intel Corporation 8 Series Chipset Family Thermal + Management Controller (rev 05)' +- bus: '02' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '03' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '03' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '03' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '03' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '04' + dev: '00' + fn: '0' + id: 10a6 + name: 'Unassigned class [ff00]: Intel Corporation 82599EB 10-Gigabit Dummy Function' +- bus: '05' + dev: '00' + fn: '0' + id: '0010' + name: 'Unassigned class [ff00]: Device 1d1c:0010 (rev 10)' +- bus: ff + dev: 0b + fn: '0' + id: 6f81 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '1' + id: 6f36 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '2' + id: 6f37 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '3' + id: 6f76 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link Debug (rev 03)' +- bus: ff + dev: 0c + fn: '0' + id: 6fe0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '1' + id: 6fe1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '2' + id: 6fe2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '3' + id: 6fe3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '0' + id: 6ff8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '4' + id: 6ffc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '5' + id: 6ffd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '6' + id: 6ffe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: '10' + fn: '0' + id: 6f1d + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '1' + id: 6f34 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '5' + id: 6f1e + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '6' + id: 6f7d + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '7' + id: 6f1f + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '12' + fn: '0' + id: 6fa0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '12' + fn: '1' + id: 6f30 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '13' + fn: '0' + id: 6fa8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '1' + id: 6f71 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '2' + id: 6faa + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '3' + id: 6fab + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '4' + id: 6fac + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '5' + id: 6fad + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '6' + id: 6fae + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Broadcast (rev 03)' +- bus: ff + dev: '13' + fn: '7' + id: 6faf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Global Broadcast (rev 03)' +- bus: ff + dev: '14' + fn: '0' + id: 6fb0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '1' + id: 6fb1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '2' + id: 6fb2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Error (rev 03)' +- bus: ff + dev: '14' + fn: '3' + id: 6fb3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Error (rev 03)' +- bus: ff + dev: '14' + fn: '4' + id: 6fbc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '5' + id: 6fbd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '6' + id: 6fbe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '7' + id: 6fbf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '15' + fn: '0' + id: 6fb4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '1' + id: 6fb5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '2' + id: 6fb6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Error (rev 03)' +- bus: ff + dev: '15' + fn: '3' + id: 6fb7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Error (rev 03)' +- bus: ff + dev: 1e + fn: '0' + id: 6f98 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '1' + id: 6f99 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '2' + id: 6f9a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '3' + id: 6fc0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '4' + id: 6f9c + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '0' + id: 6f88 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '2' + id: 6f8a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/platform.json b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/platform.json new file mode 100644 index 000000000000..b7f3756b1be1 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/platform.json @@ -0,0 +1,292 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "breakout_modes": { + "1x100G[40G]": ["Ethernet0"], + "2x50G": ["Ethernet0", "Ethernet2"], + "4x25G[10G]": ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "breakout_modes": { + "1x100G[40G]": ["Ethernet4"], + "2x50G": ["Ethernet4", "Ethernet6"], + "4x25G[10G]": ["Ethernet4", "Ethernet5", "Ethernet6", "Ethernet7"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "breakout_modes": { + "1x100G[40G]": ["Ethernet8"], + "2x50G": ["Ethernet8", "Ethernet10"], + "4x25G[10G]": ["Ethernet8", "Ethernet9", "Ethernet10", "Ethernet11"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "breakout_modes": { + "1x100G[40G]": ["Ethernet12"], + "2x50G": ["Ethernet12", "Ethernet14"], + "4x25G[10G]": ["Ethernet12", "Ethernet13", "Ethernet14", "Ethernet15"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "breakout_modes": { + "1x100G[40G]": ["Ethernet16"], + "2x50G": ["Ethernet16", "Ethernet18"], + "4x25G[10G]": ["Ethernet16", "Ethernet17", "Ethernet18", "Ethernet19"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "breakout_modes": { + "1x100G[40G]": ["Ethernet20"], + "2x50G": ["Ethernet20", "Ethernet22"], + "4x25G[10G]": ["Ethernet20", "Ethernet21", "Ethernet22", "Ethernet23"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "breakout_modes": { + "1x100G[40G]": ["Ethernet24"], + "2x50G": ["Ethernet24", "Ethernet26"], + "4x25G[10G]": ["Ethernet24", "Ethernet25", "Ethernet26", "Ethernet27"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "breakout_modes": { + "1x100G[40G]": ["Ethernet28"], + "2x50G": ["Ethernet28", "Ethernet30"], + "4x25G[10G]": ["Ethernet28", "Ethernet29", "Ethernet30", "Ethernet31"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "breakout_modes": { + "1x100G[40G]": ["Ethernet32"], + "2x50G": ["Ethernet32", "Ethernet34"], + "4x25G[10G]": ["Ethernet32", "Ethernet33", "Ethernet34", "Ethernet35"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "breakout_modes": { + "1x100G[40G]": ["Ethernet36"], + "2x50G": ["Ethernet36", "Ethernet38"], + "4x25G[10G]": ["Ethernet36", "Ethernet37", "Ethernet38", "Ethernet39"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "breakout_modes": { + "1x100G[40G]": ["Ethernet40"], + "2x50G": ["Ethernet40", "Ethernet42"], + "4x25G[10G]": ["Ethernet40", "Ethernet41", "Ethernet42", "Ethernet43"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "breakout_modes": { + "1x100G[40G]": ["Ethernet44"], + "2x50G": ["Ethernet44", "Ethernet46"], + "4x25G[10G]": ["Ethernet44", "Ethernet45", "Ethernet46", "Ethernet47"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "breakout_modes": { + "1x100G[40G]": ["Ethernet48"], + "2x50G": ["Ethernet48", "Ethernet50"], + "4x25G[10G]": ["Ethernet48", "Ethernet49", "Ethernet50", "Ethernet51"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "breakout_modes": { + "1x100G[40G]": ["Ethernet52"], + "2x50G": ["Ethernet52", "Ethernet54"], + "4x25G[10G]": ["Ethernet52", "Ethernet53", "Ethernet54", "Ethernet55"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "breakout_modes": { + "1x100G[40G]": ["Ethernet56"], + "2x50G": ["Ethernet56", "Ethernet58"], + "4x25G[10G]": ["Ethernet56", "Ethernet57", "Ethernet58", "Ethernet59"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "breakout_modes": { + "1x100G[40G]": ["Ethernet60"], + "2x50G": ["Ethernet60", "Ethernet62"], + "4x25G[10G]": ["Ethernet60", "Ethernet61", "Ethernet62", "Ethernet63"] + } + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "64,65,66,67", + "breakout_modes": { + "1x100G[40G]": ["Ethernet64"], + "2x50G": ["Ethernet64", "Ethernet66"], + "4x25G[10G]": ["Ethernet64", "Ethernet65", "Ethernet66", "Ethernet67"] + } + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "68,69,70,71", + "breakout_modes": { + "1x100G[40G]": ["Ethernet68"], + "2x50G": ["Ethernet68", "Ethernet70"], + "4x25G[10G]": ["Ethernet68", "Ethernet69", "Ethernet70", "Ethernet71"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "breakout_modes": { + "1x100G[40G]": ["Ethernet72"], + "2x50G": ["Ethernet72", "Ethernet74"], + "4x25G[10G]": ["Ethernet72", "Ethernet73", "Ethernet74", "Ethernet75"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "breakout_modes": { + "1x100G[40G]": ["Ethernet76"], + "2x50G": ["Ethernet76", "Ethernet78"], + "4x25G[10G]": ["Ethernet76", "Ethernet77", "Ethernet78", "Ethernet79"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "breakout_modes": { + "1x100G[40G]": ["Ethernet80"], + "2x50G": ["Ethernet80", "Ethernet82"], + "4x25G[10G]": ["Ethernet80", "Ethernet81", "Ethernet82", "Ethernet83"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "breakout_modes": { + "1x100G[40G]": ["Ethernet84"], + "2x50G": ["Ethernet84", "Ethernet86"], + "4x25G[10G]": ["Ethernet84", "Ethernet85", "Ethernet86", "Ethernet87"] + } + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "88,89,90,91", + "breakout_modes": { + "1x100G[40G]": ["Ethernet88"], + "2x50G": ["Ethernet88", "Ethernet90"], + "4x25G[10G]": ["Ethernet88", "Ethernet89", "Ethernet90", "Ethernet91"] + } + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "92,93,94,95", + "breakout_modes": { + "1x100G[40G]": ["Ethernet92"], + "2x50G": ["Ethernet92", "Ethernet94"], + "4x25G[10G]": ["Ethernet92", "Ethernet93", "Ethernet94", "Ethernet95"] + } + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "96,97,98,99", + "breakout_modes": { + "1x100G[40G]": ["Ethernet96"], + "2x50G": ["Ethernet96", "Ethernet98"], + "4x25G[10G]": ["Ethernet96", "Ethernet97", "Ethernet98", "Ethernet99"] + } + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "100,101,102,103", + "breakout_modes": { + "1x100G[40G]": ["Ethernet100"], + "2x50G": ["Ethernet100", "Ethernet102"], + "4x25G[10G]": ["Ethernet100", "Ethernet101", "Ethernet102", "Ethernet103"] + } + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "104,105,106,107", + "breakout_modes": { + "1x100G[40G]": ["Ethernet104"], + "2x50G": ["Ethernet104", "Ethernet106"], + "4x25G[10G]": ["Ethernet104", "Ethernet105", "Ethernet106", "Ethernet107"] + } + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "108,109,110,111", + "breakout_modes": { + "1x100G[40G]": ["Ethernet108"], + "2x50G": ["Ethernet108", "Ethernet110"], + "4x25G[10G]": ["Ethernet108", "Ethernet109", "Ethernet110", "Ethernet111"] + } + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "112,113,114,115", + "breakout_modes": { + "1x100G[40G]": ["Ethernet112"], + "2x50G": ["Ethernet112", "Ethernet114"], + "4x25G[10G]": ["Ethernet112", "Ethernet113", "Ethernet112", "Ethernet113"] + } + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "116,117,118,119", + "breakout_modes": { + "1x100G[40G]": ["Ethernet116"], + "2x50G": ["Ethernet116", "Ethernet118"], + "4x25G[10G]": ["Ethernet116", "Ethernet117", "Ethernet118", "Ethernet119"] + } + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "120,121,122,123", + "breakout_modes": { + "1x100G[40G]": ["Ethernet120"], + "2x50G": ["Ethernet120", "Ethernet122"], + "4x25G[10G]": ["Ethernet120", "Ethernet121", "Ethernet122", "Ethernet123"] + } + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "124,125,126,127", + "breakout_modes": { + "1x100G[40G]": ["Ethernet124"], + "2x50G": ["Ethernet124", "Ethernet126"], + "4x25G[10G]": ["Ethernet124", "Ethernet125", "Ethernet126", "Ethernet127"] + } + } + } +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/eeprom.py b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..b94fab471b95 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/eeprom.py @@ -0,0 +1,184 @@ +try: + import importlib + import time + import os + import re + import sys + import errno + import datetime + import logging + import logging.config + import yaml + + sys.path.append(os.path.dirname(__file__)) + import pltfm_mgr_rpc + from pltfm_mgr_rpc.ttypes import * + + from thrift.transport import TSocket + from thrift.transport import TTransport + from thrift.protocol import TBinaryProtocol + from thrift.protocol import TMultiplexedProtocol + + from argparse import ArgumentParser + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +if sys.version_info.major == 3: + STRING_TYPE = str +else: + STRING_TYPE = basestring + + +eeprom_default_dict = { + "prod_name": ("Product Name", "0x21", 12), + "odm_pcba_part_num": ("Part Number", "0x22", 13), + "prod_ser_num": ("Serial Number", "0x23", 12), + "ext_mac_addr": ("Extended MAC Address Base", "0x24", 12), + "sys_mfg_date": ("System Manufacturing Date", "0x25", 4), + "prod_ver": ("Product Version", "0x26", 1), + "ext_mac_addr_size": ("Extende MAC Address Size", "0x2A", 2), + "sys_mfger": ("Manufacturer", "0x2B", 8) +} + +eeprom_dict = {"version": ("Version", None, 0), + "pcb_mfger": ("PCB Manufacturer", "0x01", 8), + "prod_ser_num": ("Serial Number", "0x23", 12), + "bfn_pcba_part_num": ("Switch PCBA Part Number", "0x02", 12), + "odm_pcba_part_num": ("Part Number", "0x22", 13), + "bfn_pcbb_part_num": ("Switch PCBB Part Number", "0x04", 12), + "sys_asm_part_num": ("System Assembly Part Number", "0x05", 12), + "prod_state": ("Product Production State", "0x06", 1), + "location": ("EEPROM Location of Fabric", "0x07", 8), + "ext_mac_addr_size": ("Extende MAC Address Size", "0x08", 2), + "sys_mfg_date": ("System Manufacturing Date", "0x25", 4), + "prod_name": ("Product Name", "0x21", 12), + "prod_ver": ("Product Version", "0x26", 1), + "prod_part_num": ("Product Part Number", "0x09", 8), + "sys_mfger": ("Manufacturer", "0x2B", 8), + "assembled_at": ("Assembled at", "0x08", 8), + "prod_ast_tag": ("Product Asset Tag", "0x09", 12), + "loc_mac_addr": ("Local MAC address", "0x0A", 12), + "odm_pcba_ser_num": ("ODM PBCA Serial Number", "0x0B", 12), + "ext_mac_addr": ("Extended MAC Address Base", "0x0C", 12), + "prod_sub_ver": ("Product Sub Version", "0x0D", 1) + } + +product_dict = {"Montara": "Wedge100BF-32X-O-AC-F-BF", + "Lower MAV": "Wedge100BF-65X-O-AC-F-BF", + "Upper MAV": "Wedge100BF-65X-O-AC-F-BF" + } + +thrift_server = 'localhost' +transport = None +pltfm_mgr = None + +EEPROM_SYMLINK = "/var/run/platform/eeprom/syseeprom" +EEPROM_STATUS = "/var/run/platform/eeprom/status" + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + RETRIES = 35 + + def __init__(self, name, path, cpld_root, ro): + + with open(os.path.dirname(__file__) + "/logging.conf", 'r') as f: + config_dict = yaml.load(f, yaml.SafeLoader) + logging.config.dictConfig(config_dict) + + if not os.path.exists(os.path.dirname(EEPROM_SYMLINK)): + try: + os.makedirs(os.path.dirname(EEPROM_SYMLINK)) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + open(EEPROM_SYMLINK, 'a').close() + f = open(EEPROM_STATUS, 'w') + f.write("initializing..") + f.close() + + self.eeprom_path = EEPROM_SYMLINK + super(board, self).__init__(self.eeprom_path, 0, EEPROM_STATUS, True) + + for attempt in range(self.RETRIES): + if self.eeprom_init(): + break + if attempt + 1 == self.RETRIES: + raise RuntimeError("eeprom.py: Initialization failed") + time.sleep(1) + + def thrift_setup(self): + global thrift_server, transport, pltfm_mgr + transport = TSocket.TSocket(thrift_server, 9090) + + transport = TTransport.TBufferedTransport(transport) + bprotocol = TBinaryProtocol.TBinaryProtocol(transport) + + pltfm_mgr_client_module = importlib.import_module( + ".".join(["pltfm_mgr_rpc", "pltfm_mgr_rpc"])) + pltfm_mgr_protocol = TMultiplexedProtocol.TMultiplexedProtocol( + bprotocol, "pltfm_mgr_rpc") + pltfm_mgr = pltfm_mgr_client_module.Client(pltfm_mgr_protocol) + + transport.open() + + def thrift_teardown(self): + global transport + transport.close() + + def eeprom_init(self): + global pltfm_mgr + + try: + self.thrift_setup() + eeprom = pltfm_mgr.pltfm_mgr_sys_eeprom_get() + self.thrift_teardown() + except: + return False + + f = open(EEPROM_STATUS, 'w') + f.write("ok") + f.close() + + eeprom_params = "" + for attr, val in eeprom.__dict__.items(): + if val is None: + continue + + elem = eeprom_default_dict.get(attr) + if elem is None: + continue + + if isinstance(val, STRING_TYPE): + value = val.replace('\0', '') + else: + value = str(val) + + if attr == "sys_mfg_date": + value = datetime.datetime.strptime( + value, '%m-%d-%y').strftime('%m/%d/%Y 00:00:00') + + product = product_dict.get(value) + if product is not None: + value = product + if len(eeprom_params) > 0: + eeprom_params += "," + eeprom_params += "{0:s}={1:s}".format(elem[1], value) + + orig_stdout = sys.stdout + sys.stdout = StringIO() + new_e = eeprom_tlvinfo.TlvInfoDecoder.set_eeprom( + self, "", [eeprom_params]) + sys.stdout = orig_stdout + eeprom_base.EepromDecoder.write_eeprom(self, new_e) + + return True diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/logging.conf b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/logging.conf new file mode 100644 index 000000000000..d7fd84773404 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/logging.conf @@ -0,0 +1,17 @@ +version: 1 +disable_existing_loggers: False + +formatters: + simple: + format: '%(asctime)s %(name)-30s %(levelname)-7s %(message)s' + +handlers: + file: + class: logging.handlers.RotatingFileHandler + formatter: simple + filename: /var/log/platform.log + +root: + level: ERROR + handlers: + - 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 new file mode 100644 index 000000000000..414c3d6389c5 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/__init__.py @@ -0,0 +1 @@ +__all__ = ['ttypes', 'pltfm_mgr_rpc'] diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/pltfm_mgr_rpc.py b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/pltfm_mgr_rpc.py new file mode 100644 index 000000000000..8f5b89e4312a --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/pltfm_mgr_rpc.py @@ -0,0 +1,2940 @@ +# +# Autogenerated by Thrift Compiler (0.10.0) +# +# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING +# +# options string: py +# + +from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException +from thrift.protocol.TProtocol import TProtocolException +import sys +import logging +from .ttypes import * +from thrift.Thrift import TProcessor +from thrift.transport import TTransport + + +class Iface(object): + def pltfm_mgr_dummy(self, device): + """ + Parameters: + - device + """ + pass + + def pltfm_mgr_sys_tmp_get(self): + pass + + def pltfm_mgr_sys_eeprom_get(self): + pass + + def pltfm_mgr_pwr_supply_present_get(self, ps_num): + """ + Parameters: + - ps_num + """ + pass + + def pltfm_mgr_pwr_supply_info_get(self, ps_num): + """ + Parameters: + - ps_num + """ + pass + + def pltfm_mgr_pwr_rail_info_get(self, ps_num): + """ + Parameters: + - ps_num + """ + pass + + def pltfm_mgr_fan_speed_set(self, fan_num, percent): + """ + Parameters: + - fan_num + - percent + """ + pass + + def pltfm_mgr_fan_info_get(self, fan_num): + """ + Parameters: + - fan_num + """ + pass + + def pltfm_mgr_qsfp_presence_get(self, port_num): + """ + Parameters: + - port_num + """ + pass + + def pltfm_mgr_qsfp_info_get(self, port_num): + """ + Parameters: + - port_num + """ + pass + + def pltfm_mgr_qsfp_get_max_port(self): + pass + + def pltfm_mgr_qsfp_reset(self, port_num, reset): + """ + Parameters: + - port_num + - reset + """ + pass + + def pltfm_mgr_qsfp_lpmode_get(self, port_num): + """ + Parameters: + - port_num + """ + pass + + def pltfm_mgr_qsfp_lpmode_set(self, port_num, lpmode): + """ + Parameters: + - port_num + - lpmode + """ + pass + + def pltfm_mgr_sensor_info_get(self, options): + """ + Parameters: + - options + """ + pass + + +class Client(Iface): + def __init__(self, iprot, oprot=None): + self._iprot = self._oprot = iprot + if oprot is not None: + self._oprot = oprot + self._seqid = 0 + + def pltfm_mgr_dummy(self, device): + """ + Parameters: + - device + """ + self.send_pltfm_mgr_dummy(device) + return self.recv_pltfm_mgr_dummy() + + def send_pltfm_mgr_dummy(self, device): + self._oprot.writeMessageBegin('pltfm_mgr_dummy', TMessageType.CALL, self._seqid) + args = pltfm_mgr_dummy_args() + args.device = device + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_dummy(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_dummy_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_dummy failed: unknown result") + + def pltfm_mgr_sys_tmp_get(self): + self.send_pltfm_mgr_sys_tmp_get() + return self.recv_pltfm_mgr_sys_tmp_get() + + def send_pltfm_mgr_sys_tmp_get(self): + self._oprot.writeMessageBegin('pltfm_mgr_sys_tmp_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_sys_tmp_get_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_sys_tmp_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_sys_tmp_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_sys_tmp_get failed: unknown result") + + def pltfm_mgr_sys_eeprom_get(self): + self.send_pltfm_mgr_sys_eeprom_get() + return self.recv_pltfm_mgr_sys_eeprom_get() + + def send_pltfm_mgr_sys_eeprom_get(self): + self._oprot.writeMessageBegin('pltfm_mgr_sys_eeprom_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_sys_eeprom_get_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_sys_eeprom_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_sys_eeprom_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_sys_eeprom_get failed: unknown result") + + def pltfm_mgr_pwr_supply_present_get(self, ps_num): + """ + Parameters: + - ps_num + """ + self.send_pltfm_mgr_pwr_supply_present_get(ps_num) + return self.recv_pltfm_mgr_pwr_supply_present_get() + + def send_pltfm_mgr_pwr_supply_present_get(self, ps_num): + self._oprot.writeMessageBegin('pltfm_mgr_pwr_supply_present_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_pwr_supply_present_get_args() + args.ps_num = ps_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_pwr_supply_present_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_pwr_supply_present_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_pwr_supply_present_get failed: unknown result") + + def pltfm_mgr_pwr_supply_info_get(self, ps_num): + """ + Parameters: + - ps_num + """ + self.send_pltfm_mgr_pwr_supply_info_get(ps_num) + return self.recv_pltfm_mgr_pwr_supply_info_get() + + def send_pltfm_mgr_pwr_supply_info_get(self, ps_num): + self._oprot.writeMessageBegin('pltfm_mgr_pwr_supply_info_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_pwr_supply_info_get_args() + args.ps_num = ps_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_pwr_supply_info_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_pwr_supply_info_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_pwr_supply_info_get failed: unknown result") + + def pltfm_mgr_pwr_rail_info_get(self, ps_num): + """ + Parameters: + - ps_num + """ + self.send_pltfm_mgr_pwr_rail_info_get(ps_num) + return self.recv_pltfm_mgr_pwr_rail_info_get() + + def send_pltfm_mgr_pwr_rail_info_get(self, ps_num): + self._oprot.writeMessageBegin('pltfm_mgr_pwr_rail_info_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_pwr_rail_info_get_args() + args.ps_num = ps_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_pwr_rail_info_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_pwr_rail_info_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_pwr_rail_info_get failed: unknown result") + + def pltfm_mgr_fan_speed_set(self, fan_num, percent): + """ + Parameters: + - fan_num + - percent + """ + self.send_pltfm_mgr_fan_speed_set(fan_num, percent) + return self.recv_pltfm_mgr_fan_speed_set() + + def send_pltfm_mgr_fan_speed_set(self, fan_num, percent): + self._oprot.writeMessageBegin('pltfm_mgr_fan_speed_set', TMessageType.CALL, self._seqid) + args = pltfm_mgr_fan_speed_set_args() + args.fan_num = fan_num + args.percent = percent + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_fan_speed_set(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_fan_speed_set_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_fan_speed_set failed: unknown result") + + def pltfm_mgr_fan_info_get(self, fan_num): + """ + Parameters: + - fan_num + """ + self.send_pltfm_mgr_fan_info_get(fan_num) + return self.recv_pltfm_mgr_fan_info_get() + + def send_pltfm_mgr_fan_info_get(self, fan_num): + self._oprot.writeMessageBegin('pltfm_mgr_fan_info_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_fan_info_get_args() + args.fan_num = fan_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_fan_info_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_fan_info_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_fan_info_get failed: unknown result") + + def pltfm_mgr_qsfp_presence_get(self, port_num): + """ + Parameters: + - port_num + """ + self.send_pltfm_mgr_qsfp_presence_get(port_num) + return self.recv_pltfm_mgr_qsfp_presence_get() + + def send_pltfm_mgr_qsfp_presence_get(self, port_num): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_presence_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_presence_get_args() + args.port_num = port_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_presence_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_presence_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_qsfp_presence_get failed: unknown result") + + def pltfm_mgr_qsfp_info_get(self, port_num): + """ + Parameters: + - port_num + """ + self.send_pltfm_mgr_qsfp_info_get(port_num) + return self.recv_pltfm_mgr_qsfp_info_get() + + def send_pltfm_mgr_qsfp_info_get(self, port_num): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_info_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_info_get_args() + args.port_num = port_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_info_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_info_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_qsfp_info_get failed: unknown result") + + def pltfm_mgr_qsfp_get_max_port(self): + self.send_pltfm_mgr_qsfp_get_max_port() + return self.recv_pltfm_mgr_qsfp_get_max_port() + + def send_pltfm_mgr_qsfp_get_max_port(self): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_get_max_port', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_get_max_port_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_get_max_port(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_get_max_port_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_qsfp_get_max_port failed: unknown result") + + def pltfm_mgr_qsfp_reset(self, port_num, reset): + """ + Parameters: + - port_num + - reset + """ + self.send_pltfm_mgr_qsfp_reset(port_num, reset) + return self.recv_pltfm_mgr_qsfp_reset() + + def send_pltfm_mgr_qsfp_reset(self, port_num, reset): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_reset', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_reset_args() + args.port_num = port_num + args.reset = reset + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_reset(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_reset_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_qsfp_reset failed: unknown result") + + def pltfm_mgr_qsfp_lpmode_get(self, port_num): + """ + Parameters: + - port_num + """ + self.send_pltfm_mgr_qsfp_lpmode_get(port_num) + return self.recv_pltfm_mgr_qsfp_lpmode_get() + + def send_pltfm_mgr_qsfp_lpmode_get(self, port_num): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_lpmode_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_lpmode_get_args() + args.port_num = port_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_lpmode_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_lpmode_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_qsfp_lpmode_get failed: unknown result") + + def pltfm_mgr_qsfp_lpmode_set(self, port_num, lpmode): + """ + Parameters: + - port_num + - lpmode + """ + self.send_pltfm_mgr_qsfp_lpmode_set(port_num, lpmode) + return self.recv_pltfm_mgr_qsfp_lpmode_set() + + def send_pltfm_mgr_qsfp_lpmode_set(self, port_num, lpmode): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_lpmode_set', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_lpmode_set_args() + args.port_num = port_num + args.lpmode = lpmode + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_lpmode_set(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_lpmode_set_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_qsfp_lpmode_set failed: unknown result") + + def pltfm_mgr_sensor_info_get(self, options): + """ + Parameters: + - options + """ + self.send_pltfm_mgr_sensor_info_get(options) + return self.recv_pltfm_mgr_sensor_info_get() + + def send_pltfm_mgr_sensor_info_get(self, options): + self._oprot.writeMessageBegin('pltfm_mgr_sensor_info_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_sensor_info_get_args() + args.options = options + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_sensor_info_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_sensor_info_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, + "pltfm_mgr_sensor_info_get failed: unknown result") + + +class Processor(Iface, TProcessor): + def __init__(self, handler): + self._handler = handler + self._processMap = {} + self._processMap["pltfm_mgr_dummy"] = Processor.process_pltfm_mgr_dummy + self._processMap["pltfm_mgr_sys_tmp_get"] = Processor.process_pltfm_mgr_sys_tmp_get + self._processMap["pltfm_mgr_sys_eeprom_get"] = Processor.process_pltfm_mgr_sys_eeprom_get + self._processMap["pltfm_mgr_pwr_supply_present_get"] = Processor.process_pltfm_mgr_pwr_supply_present_get + self._processMap["pltfm_mgr_pwr_supply_info_get"] = Processor.process_pltfm_mgr_pwr_supply_info_get + self._processMap["pltfm_mgr_pwr_rail_info_get"] = Processor.process_pltfm_mgr_pwr_rail_info_get + self._processMap["pltfm_mgr_fan_speed_set"] = Processor.process_pltfm_mgr_fan_speed_set + self._processMap["pltfm_mgr_fan_info_get"] = Processor.process_pltfm_mgr_fan_info_get + self._processMap["pltfm_mgr_qsfp_presence_get"] = Processor.process_pltfm_mgr_qsfp_presence_get + self._processMap["pltfm_mgr_qsfp_info_get"] = Processor.process_pltfm_mgr_qsfp_info_get + self._processMap["pltfm_mgr_qsfp_get_max_port"] = Processor.process_pltfm_mgr_qsfp_get_max_port + self._processMap["pltfm_mgr_qsfp_reset"] = Processor.process_pltfm_mgr_qsfp_reset + self._processMap["pltfm_mgr_qsfp_lpmode_get"] = Processor.process_pltfm_mgr_qsfp_lpmode_get + self._processMap["pltfm_mgr_qsfp_lpmode_set"] = Processor.process_pltfm_mgr_qsfp_lpmode_set + self._processMap["pltfm_mgr_sensor_info_get"] = Processor.process_pltfm_mgr_sensor_info_get + + def process(self, iprot, oprot): + (name, type, seqid) = iprot.readMessageBegin() + if name not in self._processMap: + iprot.skip(TType.STRUCT) + iprot.readMessageEnd() + x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) + oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) + x.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + return + else: + self._processMap[name](self, seqid, iprot, oprot) + return True + + def process_pltfm_mgr_dummy(self, seqid, iprot, oprot): + args = pltfm_mgr_dummy_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_dummy_result() + try: + result.success = self._handler.pltfm_mgr_dummy(args.device) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_dummy", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_sys_tmp_get(self, seqid, iprot, oprot): + args = pltfm_mgr_sys_tmp_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_sys_tmp_get_result() + try: + result.success = self._handler.pltfm_mgr_sys_tmp_get() + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_sys_tmp_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_sys_eeprom_get(self, seqid, iprot, oprot): + args = pltfm_mgr_sys_eeprom_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_sys_eeprom_get_result() + try: + result.success = self._handler.pltfm_mgr_sys_eeprom_get() + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_sys_eeprom_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_pwr_supply_present_get(self, seqid, iprot, oprot): + args = pltfm_mgr_pwr_supply_present_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_pwr_supply_present_get_result() + try: + result.success = self._handler.pltfm_mgr_pwr_supply_present_get(args.ps_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_pwr_supply_present_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_pwr_supply_info_get(self, seqid, iprot, oprot): + args = pltfm_mgr_pwr_supply_info_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_pwr_supply_info_get_result() + try: + result.success = self._handler.pltfm_mgr_pwr_supply_info_get(args.ps_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_pwr_supply_info_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_pwr_rail_info_get(self, seqid, iprot, oprot): + args = pltfm_mgr_pwr_rail_info_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_pwr_rail_info_get_result() + try: + result.success = self._handler.pltfm_mgr_pwr_rail_info_get(args.ps_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_pwr_rail_info_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_fan_speed_set(self, seqid, iprot, oprot): + args = pltfm_mgr_fan_speed_set_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_fan_speed_set_result() + try: + result.success = self._handler.pltfm_mgr_fan_speed_set(args.fan_num, args.percent) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_fan_speed_set", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_fan_info_get(self, seqid, iprot, oprot): + args = pltfm_mgr_fan_info_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_fan_info_get_result() + try: + result.success = self._handler.pltfm_mgr_fan_info_get(args.fan_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_fan_info_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_presence_get(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_presence_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_presence_get_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_presence_get(args.port_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_presence_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_info_get(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_info_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_info_get_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_info_get(args.port_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_info_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_get_max_port(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_get_max_port_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_get_max_port_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_get_max_port() + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_get_max_port", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_reset(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_reset_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_reset_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_reset(args.port_num, args.reset) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_reset", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_lpmode_get(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_lpmode_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_lpmode_get_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_lpmode_get(args.port_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_lpmode_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_lpmode_set(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_lpmode_set_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_lpmode_set_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_lpmode_set(args.port_num, args.lpmode) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_lpmode_set", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_sensor_info_get(self, seqid, iprot, oprot): + args = pltfm_mgr_sensor_info_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_sensor_info_get_result() + try: + result.success = self._handler.pltfm_mgr_sensor_info_get(args.options) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_sensor_info_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + +# HELPER FUNCTIONS AND STRUCTURES + + +class pltfm_mgr_dummy_args(object): + """ + Attributes: + - device + """ + + thrift_spec = ( + None, # 0 + (1, TType.BYTE, 'device', None, None, ), # 1 + ) + + def __init__(self, device=None,): + self.device = device + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.BYTE: + self.device = iprot.readByte() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_dummy_args') + if self.device is not None: + oprot.writeFieldBegin('device', TType.BYTE, 1) + oprot.writeByte(self.device) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_dummy_result(object): + """ + Attributes: + - success + """ + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + ) + + def __init__(self, success=None,): + self.success = success + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.I32: + self.success = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_dummy_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.I32, 0) + oprot.writeI32(self.success) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sys_tmp_get_args(object): + + thrift_spec = ( + ) + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sys_tmp_get_args') + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sys_tmp_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (pltfm_mgr_sys_tmp_t, pltfm_mgr_sys_tmp_t.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = pltfm_mgr_sys_tmp_t() + self.success.read(iprot) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sys_tmp_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sys_eeprom_get_args(object): + + thrift_spec = ( + ) + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sys_eeprom_get_args') + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sys_eeprom_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (pltfm_mgr_eeprom_t, pltfm_mgr_eeprom_t.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = pltfm_mgr_eeprom_t() + self.success.read(iprot) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sys_eeprom_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_supply_present_get_args(object): + """ + Attributes: + - ps_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I16, 'ps_num', None, None, ), # 1 + ) + + def __init__(self, ps_num=None,): + self.ps_num = ps_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I16: + self.ps_num = iprot.readI16() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_supply_present_get_args') + if self.ps_num is not None: + oprot.writeFieldBegin('ps_num', TType.I16, 1) + oprot.writeI16(self.ps_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_supply_present_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.BOOL: + self.success = iprot.readBool() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_supply_present_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.BOOL, 0) + oprot.writeBool(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_supply_info_get_args(object): + """ + Attributes: + - ps_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I16, 'ps_num', None, None, ), # 1 + ) + + def __init__(self, ps_num=None,): + self.ps_num = ps_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I16: + self.ps_num = iprot.readI16() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_supply_info_get_args') + if self.ps_num is not None: + oprot.writeFieldBegin('ps_num', TType.I16, 1) + oprot.writeI16(self.ps_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_supply_info_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (pltfm_mgr_pwr_supply_info_t, pltfm_mgr_pwr_supply_info_t.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = pltfm_mgr_pwr_supply_info_t() + self.success.read(iprot) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_supply_info_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_rail_info_get_args(object): + """ + Attributes: + - ps_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I16, 'ps_num', None, None, ), # 1 + ) + + def __init__(self, ps_num=None,): + self.ps_num = ps_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I16: + self.ps_num = iprot.readI16() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_rail_info_get_args') + if self.ps_num is not None: + oprot.writeFieldBegin('ps_num', TType.I16, 1) + oprot.writeI16(self.ps_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_rail_info_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (pltfm_mgr_pwr_rail_info_t, pltfm_mgr_pwr_rail_info_t.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = pltfm_mgr_pwr_rail_info_t() + self.success.read(iprot) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_rail_info_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_fan_speed_set_args(object): + """ + Attributes: + - fan_num + - percent + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'fan_num', None, None, ), # 1 + (2, TType.I32, 'percent', None, None, ), # 2 + ) + + def __init__(self, fan_num=None, percent=None,): + self.fan_num = fan_num + self.percent = percent + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.fan_num = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.I32: + self.percent = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_fan_speed_set_args') + if self.fan_num is not None: + oprot.writeFieldBegin('fan_num', TType.I32, 1) + oprot.writeI32(self.fan_num) + oprot.writeFieldEnd() + if self.percent is not None: + oprot.writeFieldBegin('percent', TType.I32, 2) + oprot.writeI32(self.percent) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_fan_speed_set_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.I32: + self.success = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_fan_speed_set_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.I32, 0) + oprot.writeI32(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_fan_info_get_args(object): + """ + Attributes: + - fan_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'fan_num', None, None, ), # 1 + ) + + def __init__(self, fan_num=None,): + self.fan_num = fan_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.fan_num = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_fan_info_get_args') + if self.fan_num is not None: + oprot.writeFieldBegin('fan_num', TType.I32, 1) + oprot.writeI32(self.fan_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_fan_info_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (pltfm_mgr_fan_info_t, pltfm_mgr_fan_info_t.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = pltfm_mgr_fan_info_t() + self.success.read(iprot) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_fan_info_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_presence_get_args(object): + """ + Attributes: + - port_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'port_num', None, None, ), # 1 + ) + + def __init__(self, port_num=None,): + self.port_num = port_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.port_num = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_presence_get_args') + if self.port_num is not None: + oprot.writeFieldBegin('port_num', TType.I32, 1) + oprot.writeI32(self.port_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_presence_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.BOOL: + self.success = iprot.readBool() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_presence_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.BOOL, 0) + oprot.writeBool(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_info_get_args(object): + """ + Attributes: + - port_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'port_num', None, None, ), # 1 + ) + + def __init__(self, port_num=None,): + self.port_num = port_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.port_num = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_info_get_args') + if self.port_num is not None: + oprot.writeFieldBegin('port_num', TType.I32, 1) + oprot.writeI32(self.port_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_info_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRING, 'success', 'UTF8', None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRING: + self.success = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_info_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRING, 0) + oprot.writeString(self.success.encode('utf-8') if sys.version_info[0] == 2 else self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_get_max_port_args(object): + + thrift_spec = ( + ) + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_get_max_port_args') + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_get_max_port_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.I32: + self.success = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_get_max_port_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.I32, 0) + oprot.writeI32(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_reset_args(object): + """ + Attributes: + - port_num + - reset + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'port_num', None, None, ), # 1 + (2, TType.BOOL, 'reset', None, None, ), # 2 + ) + + def __init__(self, port_num=None, reset=None,): + self.port_num = port_num + self.reset = reset + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.port_num = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.BOOL: + self.reset = iprot.readBool() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_reset_args') + if self.port_num is not None: + oprot.writeFieldBegin('port_num', TType.I32, 1) + oprot.writeI32(self.port_num) + oprot.writeFieldEnd() + if self.reset is not None: + oprot.writeFieldBegin('reset', TType.BOOL, 2) + oprot.writeBool(self.reset) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_reset_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.I32: + self.success = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_reset_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.I32, 0) + oprot.writeI32(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_lpmode_get_args(object): + """ + Attributes: + - port_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'port_num', None, None, ), # 1 + ) + + def __init__(self, port_num=None,): + self.port_num = port_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.port_num = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_lpmode_get_args') + if self.port_num is not None: + oprot.writeFieldBegin('port_num', TType.I32, 1) + oprot.writeI32(self.port_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_lpmode_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.BOOL: + self.success = iprot.readBool() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_lpmode_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.BOOL, 0) + oprot.writeBool(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_lpmode_set_args(object): + """ + Attributes: + - port_num + - lpmode + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'port_num', None, None, ), # 1 + (2, TType.BOOL, 'lpmode', None, None, ), # 2 + ) + + def __init__(self, port_num=None, lpmode=None,): + self.port_num = port_num + self.lpmode = lpmode + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.port_num = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.BOOL: + self.lpmode = iprot.readBool() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_lpmode_set_args') + if self.port_num is not None: + oprot.writeFieldBegin('port_num', TType.I32, 1) + oprot.writeI32(self.port_num) + oprot.writeFieldEnd() + if self.lpmode is not None: + oprot.writeFieldBegin('lpmode', TType.BOOL, 2) + oprot.writeBool(self.lpmode) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_lpmode_set_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.I32: + self.success = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_lpmode_set_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.I32, 0) + oprot.writeI32(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sensor_info_get_args(object): + """ + Attributes: + - options + """ + + thrift_spec = ( + None, # 0 + (1, TType.STRING, 'options', 'UTF8', None, ), # 1 + ) + + def __init__(self, options=None,): + self.options = options + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRING: + self.options = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sensor_info_get_args') + if self.options is not None: + oprot.writeFieldBegin('options', TType.STRING, 1) + oprot.writeString(self.options.encode('utf-8') if sys.version_info[0] == 2 else self.options) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sensor_info_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRING, 'success', 'UTF8', None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRING: + self.success = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sensor_info_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRING, 0) + oprot.writeString(self.success.encode('utf-8') if sys.version_info[0] == 2 else self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/ttypes.py b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/ttypes.py new file mode 100644 index 000000000000..1f88c3c1f94f --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/pltfm_mgr_rpc/ttypes.py @@ -0,0 +1,1081 @@ +# +# Autogenerated by Thrift Compiler (0.10.0) +# +# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING +# +# options string: py +# + +from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException +from thrift.protocol.TProtocol import TProtocolException +import sys + +from thrift.transport import TTransport + + +class pltfm_mgr_sys_tmp_t(object): + """ + Attributes: + - tmp1 + - tmp2 + - tmp3 + - tmp4 + - tmp5 + - tmp6 + - tmp7 + - tmp8 + - tmp9 + - tmp10 + """ + + thrift_spec = ( + None, # 0 + (1, TType.DOUBLE, 'tmp1', None, None, ), # 1 + (2, TType.DOUBLE, 'tmp2', None, None, ), # 2 + (3, TType.DOUBLE, 'tmp3', None, None, ), # 3 + (4, TType.DOUBLE, 'tmp4', None, None, ), # 4 + (5, TType.DOUBLE, 'tmp5', None, None, ), # 5 + (6, TType.DOUBLE, 'tmp6', None, None, ), # 6 + (7, TType.DOUBLE, 'tmp7', None, None, ), # 7 + (8, TType.DOUBLE, 'tmp8', None, None, ), # 8 + (9, TType.DOUBLE, 'tmp9', None, None, ), # 9 + (10, TType.DOUBLE, 'tmp10', None, None, ), # 10 + ) + + def __init__(self, tmp1=None, tmp2=None, tmp3=None, tmp4=None, tmp5=None, tmp6=None, tmp7=None, tmp8=None, tmp9=None, tmp10=None,): + self.tmp1 = tmp1 + self.tmp2 = tmp2 + self.tmp3 = tmp3 + self.tmp4 = tmp4 + self.tmp5 = tmp5 + self.tmp6 = tmp6 + self.tmp7 = tmp7 + self.tmp8 = tmp8 + self.tmp9 = tmp9 + self.tmp10 = tmp10 + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.DOUBLE: + self.tmp1 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.DOUBLE: + self.tmp2 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.DOUBLE: + self.tmp3 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.DOUBLE: + self.tmp4 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 5: + if ftype == TType.DOUBLE: + self.tmp5 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 6: + if ftype == TType.DOUBLE: + self.tmp6 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 7: + if ftype == TType.DOUBLE: + self.tmp7 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 8: + if ftype == TType.DOUBLE: + self.tmp8 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 9: + if ftype == TType.DOUBLE: + self.tmp9 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 10: + if ftype == TType.DOUBLE: + self.tmp10 = iprot.readDouble() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sys_tmp_t') + if self.tmp1 is not None: + oprot.writeFieldBegin('tmp1', TType.DOUBLE, 1) + oprot.writeDouble(self.tmp1) + oprot.writeFieldEnd() + if self.tmp2 is not None: + oprot.writeFieldBegin('tmp2', TType.DOUBLE, 2) + oprot.writeDouble(self.tmp2) + oprot.writeFieldEnd() + if self.tmp3 is not None: + oprot.writeFieldBegin('tmp3', TType.DOUBLE, 3) + oprot.writeDouble(self.tmp3) + oprot.writeFieldEnd() + if self.tmp4 is not None: + oprot.writeFieldBegin('tmp4', TType.DOUBLE, 4) + oprot.writeDouble(self.tmp4) + oprot.writeFieldEnd() + if self.tmp5 is not None: + oprot.writeFieldBegin('tmp5', TType.DOUBLE, 5) + oprot.writeDouble(self.tmp5) + oprot.writeFieldEnd() + if self.tmp6 is not None: + oprot.writeFieldBegin('tmp6', TType.DOUBLE, 6) + oprot.writeDouble(self.tmp6) + oprot.writeFieldEnd() + if self.tmp7 is not None: + oprot.writeFieldBegin('tmp7', TType.DOUBLE, 7) + oprot.writeDouble(self.tmp7) + oprot.writeFieldEnd() + if self.tmp8 is not None: + oprot.writeFieldBegin('tmp8', TType.DOUBLE, 8) + oprot.writeDouble(self.tmp8) + oprot.writeFieldEnd() + if self.tmp9 is not None: + oprot.writeFieldBegin('tmp9', TType.DOUBLE, 9) + oprot.writeDouble(self.tmp9) + oprot.writeFieldEnd() + if self.tmp10 is not None: + oprot.writeFieldBegin('tmp10', TType.DOUBLE, 10) + oprot.writeDouble(self.tmp10) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_eeprom_t(object): + """ + Attributes: + - version + - prod_name + - prod_part_num + - sys_asm_part_num + - bfn_pcba_part_num + - bfn_pcbb_part_num + - odm_pcba_part_num + - odm_pcba_ser_num + - prod_state + - prod_ver + - prod_sub_ver + - prod_ser_num + - prod_ast_tag + - sys_mfger + - sys_mfg_date + - pcb_mfger + - assembled_at + - loc_mac_addr + - ext_mac_addr + - ext_mac_addr_size + - location + - crc8 + """ + + thrift_spec = ( + None, # 0 + (1, TType.I16, 'version', None, None, ), # 1 + (2, TType.STRING, 'prod_name', 'UTF8', None, ), # 2 + (3, TType.STRING, 'prod_part_num', 'UTF8', None, ), # 3 + (4, TType.STRING, 'sys_asm_part_num', 'UTF8', None, ), # 4 + (5, TType.STRING, 'bfn_pcba_part_num', 'UTF8', None, ), # 5 + (6, TType.STRING, 'bfn_pcbb_part_num', 'UTF8', None, ), # 6 + (7, TType.STRING, 'odm_pcba_part_num', 'UTF8', None, ), # 7 + (8, TType.STRING, 'odm_pcba_ser_num', 'UTF8', None, ), # 8 + (9, TType.I16, 'prod_state', None, None, ), # 9 + (10, TType.I16, 'prod_ver', None, None, ), # 10 + (11, TType.I16, 'prod_sub_ver', None, None, ), # 11 + (12, TType.STRING, 'prod_ser_num', 'UTF8', None, ), # 12 + (13, TType.STRING, 'prod_ast_tag', 'UTF8', None, ), # 13 + (14, TType.STRING, 'sys_mfger', 'UTF8', None, ), # 14 + (15, TType.STRING, 'sys_mfg_date', 'UTF8', None, ), # 15 + (16, TType.STRING, 'pcb_mfger', 'UTF8', None, ), # 16 + (17, TType.STRING, 'assembled_at', 'UTF8', None, ), # 17 + (18, TType.STRING, 'loc_mac_addr', 'UTF8', None, ), # 18 + (19, TType.STRING, 'ext_mac_addr', 'UTF8', None, ), # 19 + (20, TType.I32, 'ext_mac_addr_size', None, None, ), # 20 + (21, TType.STRING, 'location', 'UTF8', None, ), # 21 + (22, TType.I16, 'crc8', None, None, ), # 22 + ) + + def __init__(self, version=None, prod_name=None, prod_part_num=None, sys_asm_part_num=None, bfn_pcba_part_num=None, bfn_pcbb_part_num=None, odm_pcba_part_num=None, odm_pcba_ser_num=None, prod_state=None, prod_ver=None, prod_sub_ver=None, prod_ser_num=None, prod_ast_tag=None, sys_mfger=None, sys_mfg_date=None, pcb_mfger=None, assembled_at=None, loc_mac_addr=None, ext_mac_addr=None, ext_mac_addr_size=None, location=None, crc8=None,): + self.version = version + self.prod_name = prod_name + self.prod_part_num = prod_part_num + self.sys_asm_part_num = sys_asm_part_num + self.bfn_pcba_part_num = bfn_pcba_part_num + self.bfn_pcbb_part_num = bfn_pcbb_part_num + self.odm_pcba_part_num = odm_pcba_part_num + self.odm_pcba_ser_num = odm_pcba_ser_num + self.prod_state = prod_state + self.prod_ver = prod_ver + self.prod_sub_ver = prod_sub_ver + self.prod_ser_num = prod_ser_num + self.prod_ast_tag = prod_ast_tag + self.sys_mfger = sys_mfger + self.sys_mfg_date = sys_mfg_date + self.pcb_mfger = pcb_mfger + self.assembled_at = assembled_at + self.loc_mac_addr = loc_mac_addr + self.ext_mac_addr = ext_mac_addr + self.ext_mac_addr_size = ext_mac_addr_size + self.location = location + self.crc8 = crc8 + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I16: + self.version = iprot.readI16() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.STRING: + self.prod_name = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.STRING: + self.prod_part_num = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.STRING: + self.sys_asm_part_num = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 5: + if ftype == TType.STRING: + self.bfn_pcba_part_num = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 6: + if ftype == TType.STRING: + self.bfn_pcbb_part_num = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 7: + if ftype == TType.STRING: + self.odm_pcba_part_num = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 8: + if ftype == TType.STRING: + self.odm_pcba_ser_num = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 9: + if ftype == TType.I16: + self.prod_state = iprot.readI16() + else: + iprot.skip(ftype) + elif fid == 10: + if ftype == TType.I16: + self.prod_ver = iprot.readI16() + else: + iprot.skip(ftype) + elif fid == 11: + if ftype == TType.I16: + self.prod_sub_ver = iprot.readI16() + else: + iprot.skip(ftype) + elif fid == 12: + if ftype == TType.STRING: + self.prod_ser_num = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 13: + if ftype == TType.STRING: + self.prod_ast_tag = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 14: + if ftype == TType.STRING: + self.sys_mfger = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 15: + if ftype == TType.STRING: + self.sys_mfg_date = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 16: + if ftype == TType.STRING: + self.pcb_mfger = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 17: + if ftype == TType.STRING: + self.assembled_at = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 18: + if ftype == TType.STRING: + self.loc_mac_addr = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 19: + if ftype == TType.STRING: + self.ext_mac_addr = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 20: + if ftype == TType.I32: + self.ext_mac_addr_size = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 21: + if ftype == TType.STRING: + self.location = iprot.readString().decode( + 'utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 22: + if ftype == TType.I16: + self.crc8 = iprot.readI16() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_eeprom_t') + if self.version is not None: + oprot.writeFieldBegin('version', TType.I16, 1) + oprot.writeI16(self.version) + oprot.writeFieldEnd() + if self.prod_name is not None: + oprot.writeFieldBegin('prod_name', TType.STRING, 2) + oprot.writeString(self.prod_name.encode('utf-8') if sys.version_info[0] == 2 else self.prod_name) + oprot.writeFieldEnd() + if self.prod_part_num is not None: + oprot.writeFieldBegin('prod_part_num', TType.STRING, 3) + oprot.writeString(self.prod_part_num.encode('utf-8') if sys.version_info[0] == 2 else self.prod_part_num) + oprot.writeFieldEnd() + if self.sys_asm_part_num is not None: + oprot.writeFieldBegin('sys_asm_part_num', TType.STRING, 4) + oprot.writeString(self.sys_asm_part_num.encode('utf-8') + if sys.version_info[0] == 2 else self.sys_asm_part_num) + oprot.writeFieldEnd() + if self.bfn_pcba_part_num is not None: + oprot.writeFieldBegin('bfn_pcba_part_num', TType.STRING, 5) + oprot.writeString(self.bfn_pcba_part_num.encode('utf-8') + if sys.version_info[0] == 2 else self.bfn_pcba_part_num) + oprot.writeFieldEnd() + if self.bfn_pcbb_part_num is not None: + oprot.writeFieldBegin('bfn_pcbb_part_num', TType.STRING, 6) + oprot.writeString(self.bfn_pcbb_part_num.encode('utf-8') + if sys.version_info[0] == 2 else self.bfn_pcbb_part_num) + oprot.writeFieldEnd() + if self.odm_pcba_part_num is not None: + oprot.writeFieldBegin('odm_pcba_part_num', TType.STRING, 7) + oprot.writeString(self.odm_pcba_part_num.encode('utf-8') + if sys.version_info[0] == 2 else self.odm_pcba_part_num) + oprot.writeFieldEnd() + if self.odm_pcba_ser_num is not None: + oprot.writeFieldBegin('odm_pcba_ser_num', TType.STRING, 8) + oprot.writeString(self.odm_pcba_ser_num.encode('utf-8') + if sys.version_info[0] == 2 else self.odm_pcba_ser_num) + oprot.writeFieldEnd() + if self.prod_state is not None: + oprot.writeFieldBegin('prod_state', TType.I16, 9) + oprot.writeI16(self.prod_state) + oprot.writeFieldEnd() + if self.prod_ver is not None: + oprot.writeFieldBegin('prod_ver', TType.I16, 10) + oprot.writeI16(self.prod_ver) + oprot.writeFieldEnd() + if self.prod_sub_ver is not None: + oprot.writeFieldBegin('prod_sub_ver', TType.I16, 11) + oprot.writeI16(self.prod_sub_ver) + oprot.writeFieldEnd() + if self.prod_ser_num is not None: + oprot.writeFieldBegin('prod_ser_num', TType.STRING, 12) + oprot.writeString(self.prod_ser_num.encode('utf-8') if sys.version_info[0] == 2 else self.prod_ser_num) + oprot.writeFieldEnd() + if self.prod_ast_tag is not None: + oprot.writeFieldBegin('prod_ast_tag', TType.STRING, 13) + oprot.writeString(self.prod_ast_tag.encode('utf-8') if sys.version_info[0] == 2 else self.prod_ast_tag) + oprot.writeFieldEnd() + if self.sys_mfger is not None: + oprot.writeFieldBegin('sys_mfger', TType.STRING, 14) + oprot.writeString(self.sys_mfger.encode('utf-8') if sys.version_info[0] == 2 else self.sys_mfger) + oprot.writeFieldEnd() + if self.sys_mfg_date is not None: + oprot.writeFieldBegin('sys_mfg_date', TType.STRING, 15) + oprot.writeString(self.sys_mfg_date.encode('utf-8') if sys.version_info[0] == 2 else self.sys_mfg_date) + oprot.writeFieldEnd() + if self.pcb_mfger is not None: + oprot.writeFieldBegin('pcb_mfger', TType.STRING, 16) + oprot.writeString(self.pcb_mfger.encode('utf-8') if sys.version_info[0] == 2 else self.pcb_mfger) + oprot.writeFieldEnd() + if self.assembled_at is not None: + oprot.writeFieldBegin('assembled_at', TType.STRING, 17) + oprot.writeString(self.assembled_at.encode('utf-8') if sys.version_info[0] == 2 else self.assembled_at) + oprot.writeFieldEnd() + if self.loc_mac_addr is not None: + oprot.writeFieldBegin('loc_mac_addr', TType.STRING, 18) + oprot.writeString(self.loc_mac_addr.encode('utf-8') if sys.version_info[0] == 2 else self.loc_mac_addr) + oprot.writeFieldEnd() + if self.ext_mac_addr is not None: + oprot.writeFieldBegin('ext_mac_addr', TType.STRING, 19) + oprot.writeString(self.ext_mac_addr.encode('utf-8') if sys.version_info[0] == 2 else self.ext_mac_addr) + oprot.writeFieldEnd() + if self.ext_mac_addr_size is not None: + oprot.writeFieldBegin('ext_mac_addr_size', TType.I32, 20) + oprot.writeI32(self.ext_mac_addr_size) + oprot.writeFieldEnd() + if self.location is not None: + oprot.writeFieldBegin('location', TType.STRING, 21) + oprot.writeString(self.location.encode('utf-8') if sys.version_info[0] == 2 else self.location) + oprot.writeFieldEnd() + if self.crc8 is not None: + oprot.writeFieldBegin('crc8', TType.I16, 22) + oprot.writeI16(self.crc8) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_supply_info_t(object): + """ + Attributes: + - vin + - vout + - iout + - pwr_out + - fspeed + - ffault + - load_sharing + - model + - serial + - rev + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'vin', None, None, ), # 1 + (2, TType.I32, 'vout', None, None, ), # 2 + (3, TType.I32, 'iout', None, None, ), # 3 + (4, TType.I32, 'pwr_out', None, None, ), # 4 + (5, TType.I32, 'fspeed', None, None, ), # 5 + (6, TType.BOOL, 'ffault', None, None, ), # 6 + (7, TType.BOOL, 'load_sharing', None, None, ), # 7 + (8, TType.STRING, 'model', 'UTF8', None, ), # 8 + (9, TType.STRING, 'serial', 'UTF8', None, ), # 9 + (10, TType.STRING, 'rev', 'UTF8', None, ), # 10 + ) + + def __init__(self, vin=None, vout=None, iout=None, pwr_out=None, fspeed=None, ffault=None, load_sharing=None, model=None, serial=None, rev=None,): + self.vin = vin + self.vout = vout + self.iout = iout + self.pwr_out = pwr_out + self.fspeed = fspeed + self.ffault = ffault + self.load_sharing = load_sharing + self.model = model + self.serial = serial + self.rev = rev + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.vin = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.I32: + self.vout = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.I32: + self.iout = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.I32: + self.pwr_out = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 5: + if ftype == TType.I32: + self.fspeed = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 6: + if ftype == TType.BOOL: + self.ffault = iprot.readBool() + else: + iprot.skip(ftype) + elif fid == 7: + if ftype == TType.BOOL: + self.load_sharing = iprot.readBool() + else: + iprot.skip(ftype) + elif fid == 8: + if ftype == TType.STRING: + self.model = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 9: + if ftype == TType.STRING: + self.serial = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 10: + if ftype == TType.STRING: + self.rev = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_supply_info_t') + if self.vin is not None: + oprot.writeFieldBegin('vin', TType.I32, 1) + oprot.writeI32(self.vin) + oprot.writeFieldEnd() + if self.vout is not None: + oprot.writeFieldBegin('vout', TType.I32, 2) + oprot.writeI32(self.vout) + oprot.writeFieldEnd() + if self.iout is not None: + oprot.writeFieldBegin('iout', TType.I32, 3) + oprot.writeI32(self.iout) + oprot.writeFieldEnd() + if self.pwr_out is not None: + oprot.writeFieldBegin('pwr_out', TType.I32, 4) + oprot.writeI32(self.pwr_out) + oprot.writeFieldEnd() + if self.fspeed is not None: + oprot.writeFieldBegin('fspeed', TType.I32, 5) + oprot.writeI32(self.fspeed) + oprot.writeFieldEnd() + if self.ffault is not None: + oprot.writeFieldBegin('ffault', TType.BOOL, 6) + oprot.writeBool(self.ffault) + oprot.writeFieldEnd() + if self.load_sharing is not None: + oprot.writeFieldBegin('load_sharing', TType.BOOL, 7) + oprot.writeBool(self.load_sharing) + oprot.writeFieldEnd() + if self.model is not None: + oprot.writeFieldBegin('model', TType.STRING, 8) + oprot.writeString(self.model.encode('utf-8') if sys.version_info[0] == 2 else self.model) + oprot.writeFieldEnd() + if self.serial is not None: + oprot.writeFieldBegin('serial', TType.STRING, 9) + oprot.writeString(self.serial.encode('utf-8') if sys.version_info[0] == 2 else self.serial) + oprot.writeFieldEnd() + if self.rev is not None: + oprot.writeFieldBegin('rev', TType.STRING, 10) + oprot.writeString(self.rev.encode('utf-8') if sys.version_info[0] == 2 else self.rev) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_rail_info_t(object): + """ + Attributes: + - vrail1 + - vrail2 + - vrail3 + - vrail4 + - vrail5 + - vrail6 + - vrail7 + - vrail8 + - vrail9 + - vrail10 + - vrail11 + - vrail12 + - vrail13 + - vrail14 + - vrail15 + - vrail16 + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'vrail1', None, None, ), # 1 + (2, TType.I32, 'vrail2', None, None, ), # 2 + (3, TType.I32, 'vrail3', None, None, ), # 3 + (4, TType.I32, 'vrail4', None, None, ), # 4 + (5, TType.I32, 'vrail5', None, None, ), # 5 + (6, TType.I32, 'vrail6', None, None, ), # 6 + (7, TType.I32, 'vrail7', None, None, ), # 7 + (8, TType.I32, 'vrail8', None, None, ), # 8 + (9, TType.I32, 'vrail9', None, None, ), # 9 + (10, TType.I32, 'vrail10', None, None, ), # 10 + (11, TType.I32, 'vrail11', None, None, ), # 11 + (12, TType.I32, 'vrail12', None, None, ), # 12 + (13, TType.I32, 'vrail13', None, None, ), # 13 + (14, TType.I32, 'vrail14', None, None, ), # 14 + (15, TType.I32, 'vrail15', None, None, ), # 15 + (16, TType.I32, 'vrail16', None, None, ), # 16 + ) + + def __init__(self, vrail1=None, vrail2=None, vrail3=None, vrail4=None, vrail5=None, vrail6=None, vrail7=None, vrail8=None, vrail9=None, vrail10=None, vrail11=None, vrail12=None, vrail13=None, vrail14=None, vrail15=None, vrail16=None,): + self.vrail1 = vrail1 + self.vrail2 = vrail2 + self.vrail3 = vrail3 + self.vrail4 = vrail4 + self.vrail5 = vrail5 + self.vrail6 = vrail6 + self.vrail7 = vrail7 + self.vrail8 = vrail8 + self.vrail9 = vrail9 + self.vrail10 = vrail10 + self.vrail11 = vrail11 + self.vrail12 = vrail12 + self.vrail13 = vrail13 + self.vrail14 = vrail14 + self.vrail15 = vrail15 + self.vrail16 = vrail16 + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.vrail1 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.I32: + self.vrail2 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.I32: + self.vrail3 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.I32: + self.vrail4 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 5: + if ftype == TType.I32: + self.vrail5 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 6: + if ftype == TType.I32: + self.vrail6 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 7: + if ftype == TType.I32: + self.vrail7 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 8: + if ftype == TType.I32: + self.vrail8 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 9: + if ftype == TType.I32: + self.vrail9 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 10: + if ftype == TType.I32: + self.vrail10 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 11: + if ftype == TType.I32: + self.vrail11 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 12: + if ftype == TType.I32: + self.vrail12 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 13: + if ftype == TType.I32: + self.vrail13 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 14: + if ftype == TType.I32: + self.vrail14 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 15: + if ftype == TType.I32: + self.vrail15 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 16: + if ftype == TType.I32: + self.vrail16 = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_rail_info_t') + if self.vrail1 is not None: + oprot.writeFieldBegin('vrail1', TType.I32, 1) + oprot.writeI32(self.vrail1) + oprot.writeFieldEnd() + if self.vrail2 is not None: + oprot.writeFieldBegin('vrail2', TType.I32, 2) + oprot.writeI32(self.vrail2) + oprot.writeFieldEnd() + if self.vrail3 is not None: + oprot.writeFieldBegin('vrail3', TType.I32, 3) + oprot.writeI32(self.vrail3) + oprot.writeFieldEnd() + if self.vrail4 is not None: + oprot.writeFieldBegin('vrail4', TType.I32, 4) + oprot.writeI32(self.vrail4) + oprot.writeFieldEnd() + if self.vrail5 is not None: + oprot.writeFieldBegin('vrail5', TType.I32, 5) + oprot.writeI32(self.vrail5) + oprot.writeFieldEnd() + if self.vrail6 is not None: + oprot.writeFieldBegin('vrail6', TType.I32, 6) + oprot.writeI32(self.vrail6) + oprot.writeFieldEnd() + if self.vrail7 is not None: + oprot.writeFieldBegin('vrail7', TType.I32, 7) + oprot.writeI32(self.vrail7) + oprot.writeFieldEnd() + if self.vrail8 is not None: + oprot.writeFieldBegin('vrail8', TType.I32, 8) + oprot.writeI32(self.vrail8) + oprot.writeFieldEnd() + if self.vrail9 is not None: + oprot.writeFieldBegin('vrail9', TType.I32, 9) + oprot.writeI32(self.vrail9) + oprot.writeFieldEnd() + if self.vrail10 is not None: + oprot.writeFieldBegin('vrail10', TType.I32, 10) + oprot.writeI32(self.vrail10) + oprot.writeFieldEnd() + if self.vrail11 is not None: + oprot.writeFieldBegin('vrail11', TType.I32, 11) + oprot.writeI32(self.vrail11) + oprot.writeFieldEnd() + if self.vrail12 is not None: + oprot.writeFieldBegin('vrail12', TType.I32, 12) + oprot.writeI32(self.vrail12) + oprot.writeFieldEnd() + if self.vrail13 is not None: + oprot.writeFieldBegin('vrail13', TType.I32, 13) + oprot.writeI32(self.vrail13) + oprot.writeFieldEnd() + if self.vrail14 is not None: + oprot.writeFieldBegin('vrail14', TType.I32, 14) + oprot.writeI32(self.vrail14) + oprot.writeFieldEnd() + if self.vrail15 is not None: + oprot.writeFieldBegin('vrail15', TType.I32, 15) + oprot.writeI32(self.vrail15) + oprot.writeFieldEnd() + if self.vrail16 is not None: + oprot.writeFieldBegin('vrail16', TType.I32, 16) + oprot.writeI32(self.vrail16) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_fan_info_t(object): + """ + Attributes: + - fan_num + - front_rpm + - rear_rpm + - percent + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'fan_num', None, None, ), # 1 + (2, TType.I32, 'front_rpm', None, None, ), # 2 + (3, TType.I32, 'rear_rpm', None, None, ), # 3 + (4, TType.I32, 'percent', None, None, ), # 4 + ) + + def __init__(self, fan_num=None, front_rpm=None, rear_rpm=None, percent=None,): + self.fan_num = fan_num + self.front_rpm = front_rpm + self.rear_rpm = rear_rpm + self.percent = percent + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.fan_num = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.I32: + self.front_rpm = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.I32: + self.rear_rpm = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.I32: + self.percent = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_fan_info_t') + if self.fan_num is not None: + oprot.writeFieldBegin('fan_num', TType.I32, 1) + oprot.writeI32(self.fan_num) + oprot.writeFieldEnd() + if self.front_rpm is not None: + oprot.writeFieldBegin('front_rpm', TType.I32, 2) + oprot.writeI32(self.front_rpm) + oprot.writeFieldEnd() + if self.rear_rpm is not None: + oprot.writeFieldBegin('rear_rpm', TType.I32, 3) + oprot.writeI32(self.rear_rpm) + oprot.writeFieldEnd() + if self.percent is not None: + oprot.writeFieldBegin('percent', TType.I32, 4) + oprot.writeI32(self.percent) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class InvalidPltfmMgrOperation(TException): + """ + Attributes: + - code + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'code', None, None, ), # 1 + ) + + def __init__(self, code=None,): + self.code = code + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.code = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('InvalidPltfmMgrOperation') + if self.code is not None: + oprot.writeFieldBegin('code', TType.I32, 1) + oprot.writeI32(self.code) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __str__(self): + return repr(self) + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in list(self.__dict__.items())] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/psuutil.py b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..0ef5162d282c --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/psuutil.py @@ -0,0 +1,96 @@ +try: + import os + import sys + import importlib + + sys.path.append(os.path.dirname(__file__)) + import pltfm_mgr_rpc + from pltfm_mgr_rpc.ttypes import * + + from thrift.transport import TSocket + from thrift.transport import TTransport + from thrift.protocol import TBinaryProtocol + from thrift.protocol import TMultiplexedProtocol + + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +thrift_server = 'localhost' +transport = None +pltfm_mgr = None + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def thrift_setup(self): + global thrift_server, transport, pltfm_mgr + transport = TSocket.TSocket(thrift_server, 9090) + + transport = TTransport.TBufferedTransport(transport) + bprotocol = TBinaryProtocol.TBinaryProtocol(transport) + + pltfm_mgr_client_module = importlib.import_module( + ".".join(["pltfm_mgr_rpc", "pltfm_mgr_rpc"])) + pltfm_mgr_protocol = TMultiplexedProtocol.TMultiplexedProtocol( + bprotocol, "pltfm_mgr_rpc") + pltfm_mgr = pltfm_mgr_client_module.Client(pltfm_mgr_protocol) + + transport.open() + + def thrift_teardown(self): + global transport + transport.close() + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + global pltfm_mgr + + try: + self.thrift_setup() + psu_info = pltfm_mgr.pltfm_mgr_pwr_supply_info_get(index) + self.thrift_teardown() + except: + return False + + return (psu_info.ffault == False) + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + global pltfm_mgr + + try: + self.thrift_setup() + status = pltfm_mgr.pltfm_mgr_pwr_supply_present_get(index) + self.thrift_teardown() + except: + return False + + return status diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/sfputil.py b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..41d75501f491 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/plugins/sfputil.py @@ -0,0 +1,250 @@ +try: + import os + import sys + import importlib + import time + + sys.path.append(os.path.dirname(__file__)) + import pltfm_mgr_rpc + from pltfm_mgr_rpc.ttypes import * + + from thrift.transport import TSocket + from thrift.transport import TTransport + from thrift.protocol import TBinaryProtocol + from thrift.protocol import TMultiplexedProtocol + + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +thrift_server = 'localhost' +transport = None +pltfm_mgr = None + +SFP_EEPROM_CACHE = "/var/run/platform/sfp/cache" + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 0 + PORTS_IN_BLOCK = 0 + QSFP_PORT_START = 1 + QSFP_PORT_END = 0 + EEPROM_OFFSET = 0 + QSFP_CHECK_INTERVAL = 4 + THRIFT_RETRIES = 5 + THRIFT_TIMEOUT = 5 + + @property + def port_start(self): + self.update_port_info() + return self.PORT_START + + @property + def port_end(self): + self.update_port_info() + return self.PORT_END + + @property + def qsfp_ports(self): + self.update_port_info() + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + print("dependency on sysfs has been removed") + raise Exception() + + def __init__(self): + self.ready = False + self.phy_port_dict = {'-1': 'system_not_ready'} + self.phy_port_cur_state = {} + self.qsfp_interval = self.QSFP_CHECK_INTERVAL + + if not os.path.exists(os.path.dirname(SFP_EEPROM_CACHE)): + try: + os.makedirs(os.path.dirname(SFP_EEPROM_CACHE)) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + open(SFP_EEPROM_CACHE, 'ab').close() + + SfpUtilBase.__init__(self) + + def update_port_info(self): + global pltfm_mgr + + if self.QSFP_PORT_END == 0: + self.thrift_setup() + self.QSFP_PORT_END = pltfm_mgr.pltfm_mgr_qsfp_get_max_port() + self.PORT_END = self.QSFP_PORT_END + self.PORTS_IN_BLOCK = self.QSFP_PORT_END + self.thrift_teardown() + + def thrift_setup(self): + global thrift_server, transport, pltfm_mgr + transport = TSocket.TSocket(thrift_server, 9090) + + transport = TTransport.TBufferedTransport(transport) + bprotocol = TBinaryProtocol.TBinaryProtocol(transport) + + pltfm_mgr_client_module = importlib.import_module(".".join(["pltfm_mgr_rpc", "pltfm_mgr_rpc"])) + pltfm_mgr_protocol = TMultiplexedProtocol.TMultiplexedProtocol(bprotocol, "pltfm_mgr_rpc") + pltfm_mgr = pltfm_mgr_client_module.Client(pltfm_mgr_protocol) + + for i in range(self.THRIFT_RETRIES): + try: + transport.open() + if i: + # The main thrift server is starded without platform api + # Platform api is added later during syncd initialization + # So we need to wait a little bit before do any platform api call + # Just in case when can't connect from the first try (warm-reboot case) + time.sleep(self.THRIFT_TIMEOUT) + break + except TTransport.TTransportException as e: + if e.type != TTransport.TTransportException.NOT_OPEN or i >= self.THRIFT_RETRIES - 1: + raise e + time.sleep(self.THRIFT_TIMEOUT) + + def thrift_teardown(self): + global transport + transport.close() + + 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 + + presence = False + + try: + self.thrift_setup() + presence = pltfm_mgr.pltfm_mgr_qsfp_presence_get(port_num) + self.thrift_teardown() + except Exception as e: + print(e.__doc__) + print(e.message) + + return presence + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + self.thrift_setup() + lpmode = pltfm_mgr.pltfm_mgr_qsfp_lpmode_get(port_num) + self.thrift_teardown() + return lpmode + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + self.thrift_setup() + status = pltfm_mgr.pltfm_mgr_qsfp_lpmode_set(port_num, lpmode) + self.thrift_teardown() + return (status == 0) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + self.thrift_setup() + status = pltfm_mgr.pltfm_mgr_qsfp_reset(port_num, True) + status = pltfm_mgr.pltfm_mgr_qsfp_reset(port_num, False) + self.thrift_teardown() + return (status == 0) + + def check_transceiver_change(self): + if not self.ready: + return + + self.phy_port_dict = {} + + try: + self.thrift_setup() + except: + return + + # Get presence of each SFP + for port in range(self.port_start, self.port_end + 1): + try: + sfp_resent = pltfm_mgr.pltfm_mgr_qsfp_presence_get(port) + except: + sfp_resent = False + sfp_state = '1' if sfp_resent else '0' + + if port in self.phy_port_cur_state: + if self.phy_port_cur_state[port] != sfp_state: + self.phy_port_dict[port] = sfp_state + else: + self.phy_port_dict[port] = sfp_state + + # Update port current state + self.phy_port_cur_state[port] = sfp_state + + self.thrift_teardown() + + def get_transceiver_change_event(self, timeout=0): + forever = False + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + while forever or timeout > 0: + if not self.ready: + try: + self.thrift_setup() + self.thrift_teardown() + except: + pass + else: + self.ready = True + self.phy_port_dict = {} + break + elif self.qsfp_interval == 0: + self.qsfp_interval = self.QSFP_CHECK_INTERVAL + + # Process transceiver plug-in/out event + self.check_transceiver_change() + + # Break if tranceiver state has changed + if bool(self.phy_port_dict): + break + + if timeout: + timeout -= 1 + + if self.qsfp_interval: + self.qsfp_interval -= 1 + + time.sleep(1) + + return self.ready, self.phy_port_dict + + def _get_port_eeprom_path(self, port_num, devid): + eeprom_path = None + + self.thrift_setup() + presence = pltfm_mgr.pltfm_mgr_qsfp_presence_get(port_num) + if presence == True: + eeprom_cache = open(SFP_EEPROM_CACHE, 'wb') + eeprom_hex = pltfm_mgr.pltfm_mgr_qsfp_info_get(port_num) + eeprom_raw = bytearray.fromhex(eeprom_hex) + eeprom_cache.write(eeprom_raw) + eeprom_cache.close() + eeprom_path = SFP_EEPROM_CACHE + self.thrift_teardown() + + return eeprom_path diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/pmon_daemon_control.json b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..70bce43bbf67 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/pmon_daemon_control.json @@ -0,0 +1,9 @@ +{ + "skip_pcied": false, + "skip_fancontrol": true, + "skip_thermalctld": true, + "skip_ledd": true, + "skip_xcvrd": false, + "skip_psud": false, + "skip_syseepromd": false +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/default_sku b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/default_sku new file mode 100644 index 000000000000..ba06df1e2a59 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/default_sku @@ -0,0 +1 @@ +mavericks t1 diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/installer.conf b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/installer.conf new file mode 100644 index 000000000000..3714ff053bb0 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=57600 diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers.json.j2 b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t0.j2 b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..e5b949faed00 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t0.j2 @@ -0,0 +1,83 @@ +{% 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' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- 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":"4096", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"4096", + "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":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t1.j2 b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..1d8096c0d6cc --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t1.j2 @@ -0,0 +1,83 @@ +{% 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' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- 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":"4096", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"4096", + "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":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/hwsku.json b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/hwsku.json new file mode 100644 index 000000000000..857b00852c0b --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/hwsku.json @@ -0,0 +1,329 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet128": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet132": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet136": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet140": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet144": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet148": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet152": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet156": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet160": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet164": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet168": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet172": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet176": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet180": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet184": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet188": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet196": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet204": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet208": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet212": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet216": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet220": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet224": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet228": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet232": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet236": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet240": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet244": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet248": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet252": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet256": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "none" + } + } +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/pg_profile_lookup.ini b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/pg_profile_lookup.ini new file mode 100644 index 000000000000..b66b129fe43f --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/port_config.ini b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/port_config.ini new file mode 100644 index 000000000000..def494da0081 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/port_config.ini @@ -0,0 +1,66 @@ +# name lanes alias index speed autoneg fec +Ethernet0 0,1,2,3 Ethernet0 1 100000 0 rs +Ethernet4 4,5,6,7 Ethernet4 2 100000 0 rs +Ethernet8 8,9,10,11 Ethernet8 3 100000 0 rs +Ethernet12 12,13,14,15 Ethernet12 4 100000 0 rs +Ethernet16 16,17,18,19 Ethernet16 5 100000 0 rs +Ethernet20 20,21,22,23 Ethernet20 6 100000 0 rs +Ethernet24 24,25,26,27 Ethernet24 7 100000 0 rs +Ethernet28 28,29,30,31 Ethernet28 8 100000 0 rs +Ethernet32 32,33,34,35 Ethernet32 9 100000 0 rs +Ethernet36 36,37,38,39 Ethernet36 10 100000 0 rs +Ethernet40 40,41,42,43 Ethernet40 11 100000 0 rs +Ethernet44 44,45,46,47 Ethernet44 12 100000 0 rs +Ethernet48 48,49,50,51 Ethernet48 13 100000 0 rs +Ethernet52 52,53,54,55 Ethernet52 14 100000 0 rs +Ethernet56 56,57,58,59 Ethernet56 15 100000 0 rs +Ethernet60 60,61,62,63 Ethernet60 16 100000 0 rs +Ethernet64 64,65,66,67 Ethernet64 17 100000 0 rs +Ethernet68 68,69,70,71 Ethernet68 18 100000 0 rs +Ethernet72 72,73,74,75 Ethernet72 19 100000 0 rs +Ethernet76 76,77,78,79 Ethernet76 20 100000 0 rs +Ethernet80 80,81,82,83 Ethernet80 21 100000 0 rs +Ethernet84 84,85,86,87 Ethernet84 22 100000 0 rs +Ethernet88 88,89,90,91 Ethernet88 23 100000 0 rs +Ethernet92 92,93,94,95 Ethernet92 24 100000 0 rs +Ethernet96 96,97,98,99 Ethernet96 25 100000 0 rs +Ethernet100 100,101,102,103 Ethernet100 26 100000 0 rs +Ethernet104 104,105,106,107 Ethernet104 27 100000 0 rs +Ethernet108 108,109,110,111 Ethernet108 28 100000 0 rs +Ethernet112 112,113,114,115 Ethernet112 29 100000 0 rs +Ethernet116 116,117,118,119 Ethernet116 30 100000 0 rs +Ethernet120 120,121,122,123 Ethernet120 31 100000 0 rs +Ethernet124 124,125,126,127 Ethernet124 32 100000 0 rs +Ethernet128 128,129,130,131 Ethernet128 33 100000 0 rs +Ethernet132 132,133,134,135 Ethernet132 34 100000 0 rs +Ethernet136 136,137,138,139 Ethernet136 35 100000 0 rs +Ethernet140 140,141,142,143 Ethernet140 36 100000 0 rs +Ethernet144 144,145,146,147 Ethernet144 37 100000 0 rs +Ethernet148 148,149,150,151 Ethernet148 38 100000 0 rs +Ethernet152 152,153,154,155 Ethernet152 39 100000 0 rs +Ethernet156 156,157,158,159 Ethernet156 40 100000 0 rs +Ethernet160 160,161,162,163 Ethernet169 41 100000 0 rs +Ethernet164 164,165,166,167 Ethernet164 42 100000 0 rs +Ethernet168 168,169,170,171 Ethernet168 43 100000 0 rs +Ethernet172 172,173,174,175 Ethernet172 44 100000 0 rs +Ethernet176 176,177,178,179 Ethernet176 45 100000 0 rs +Ethernet180 180,181,182,183 Ethernet180 46 100000 0 rs +Ethernet184 184,185,186,187 Ethernet184 47 100000 0 rs +Ethernet188 188,189,190,191 Ethernet188 48 100000 0 rs +Ethernet192 192,193,194,195 Ethernet192 49 100000 0 rs +Ethernet196 196,197,198,199 Ethernet196 50 100000 0 rs +Ethernet200 200,201,202,203 Ethernet200 51 100000 0 rs +Ethernet204 204,205,206,207 Ethernet204 52 100000 0 rs +Ethernet208 208,209,210,211 Ethernet208 53 100000 0 rs +Ethernet212 212,213,214,215 Ethernet212 54 100000 0 rs +Ethernet216 216,217,218,219 Ethernet216 55 100000 0 rs +Ethernet220 220,221,222,223 Ethernet220 56 100000 0 rs +Ethernet224 224,225,226,227 Ethernet224 57 100000 0 rs +Ethernet228 228,229,230,231 Ethernet228 58 100000 0 rs +Ethernet232 232,233,234,235 Ethernet232 59 100000 0 rs +Ethernet236 236,237,238,239 Ethernet236 60 100000 0 rs +Ethernet240 240,241,242,243 Ethernet240 61 100000 0 rs +Ethernet244 244,245,246,247 Ethernet244 62 100000 0 rs +Ethernet248 248,249,250,251 Ethernet248 63 100000 0 rs +Ethernet252 252,253,254,255 Ethernet252 64 100000 0 rs +Ethernet256 256,257,258,259 Ethernet256 65 100000 0 none diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/qos.json.j2 b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/qos.json.j2 new file mode 100644 index 000000000000..a685277448f1 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/qos.json.j2 @@ -0,0 +1,10 @@ +{%- macro generate_tc_to_pg_map() %} + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, +{%- endmacro %} + +{%- include 'qos_config.j2' %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/sai.profile b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/sai.profile new file mode 100644 index 000000000000..037b5c135370 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/sai.profile @@ -0,0 +1,3 @@ +SAI_KEY_WARM_BOOT_WRITE_FILE=/var/warmboot/sai-warmboot.bin +SAI_KEY_WARM_BOOT_READ_FILE=/var/warmboot/sai-warmboot.bin + diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/switch-sai.conf b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/switch-sai.conf new file mode 100644 index 000000000000..81a7d7bc28c3 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/switch-sai.conf @@ -0,0 +1,34 @@ +{ + "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" + } + ], + "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", + "agent0": "lib/platform/x86_64-accton_wedge100bf_65x-r0/libpltfm_mgr.so", + "switchapi_port_add": false, + "non_default_port_ppgs": 5 + } + ] +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/switch-tna-sai.conf b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/switch-tna-sai.conf new file mode 100644 index 000000000000..ddcb9d4ba287 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/switch-tna-sai.conf @@ -0,0 +1,40 @@ +{ + "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, + "agent0": "lib/platform/x86_64-accton_wedge100bf_65x-r0/libpltfm_mgr.so", + "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/barefoot/x86_64-accton_wedge100bf_65x-r0/platform.json b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/platform.json new file mode 100644 index 000000000000..a2394135c0fc --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/platform.json @@ -0,0 +1,589 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "breakout_modes": { + "1x100G[40G]": ["Ethernet0"], + "2x50G": ["Ethernet0", "Ethernet2"], + "4x25G[10G]": ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "breakout_modes": { + "1x100G[40G]": ["Ethernet4"], + "2x50G": ["Ethernet4", "Ethernet6"], + "4x25G[10G]": ["Ethernet4", "Ethernet5", "Ethernet6", "Ethernet7"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "breakout_modes": { + "1x100G[40G]": ["Ethernet8"], + "2x50G": ["Ethernet8", "Ethernet10"], + "4x25G[10G]": ["Ethernet8", "Ethernet9", "Ethernet10", "Ethernet11"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "breakout_modes": { + "1x100G[40G]": ["Ethernet12"], + "2x50G": ["Ethernet12", "Ethernet14"], + "4x25G[10G]": ["Ethernet12", "Ethernet13", "Ethernet14", "Ethernet15"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "breakout_modes": { + "1x100G[40G]": ["Ethernet16"], + "2x50G": ["Ethernet16", "Ethernet18"], + "4x25G[10G]": ["Ethernet16", "Ethernet17", "Ethernet18", "Ethernet19"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "breakout_modes": { + "1x100G[40G]": ["Ethernet20"], + "2x50G": ["Ethernet20", "Ethernet22"], + "4x25G[10G]": ["Ethernet20", "Ethernet21", "Ethernet22", "Ethernet23"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "breakout_modes": { + "1x100G[40G]": ["Ethernet24"], + "2x50G": ["Ethernet24", "Ethernet26"], + "4x25G[10G]": ["Ethernet24", "Ethernet25", "Ethernet26", "Ethernet27"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "breakout_modes": { + "1x100G[40G]": ["Ethernet28"], + "2x50G": ["Ethernet28", "Ethernet30"], + "4x25G[10G]": ["Ethernet28", "Ethernet29", "Ethernet30", "Ethernet31"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "breakout_modes": { + "1x100G[40G]": ["Ethernet32"], + "2x50G": ["Ethernet32", "Ethernet34"], + "4x25G[10G]": ["Ethernet32", "Ethernet33", "Ethernet34", "Ethernet35"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "breakout_modes": { + "1x100G[40G]": ["Ethernet36"], + "2x50G": ["Ethernet36", "Ethernet38"], + "4x25G[10G]": ["Ethernet36", "Ethernet37", "Ethernet38", "Ethernet39"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "breakout_modes": { + "1x100G[40G]": ["Ethernet40"], + "2x50G": ["Ethernet40", "Ethernet42"], + "4x25G[10G]": ["Ethernet40", "Ethernet41", "Ethernet42", "Ethernet43"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "breakout_modes": { + "1x100G[40G]": ["Ethernet44"], + "2x50G": ["Ethernet44", "Ethernet46"], + "4x25G[10G]": ["Ethernet44", "Ethernet45", "Ethernet46", "Ethernet47"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "breakout_modes": { + "1x100G[40G]": ["Ethernet48"], + "2x50G": ["Ethernet48", "Ethernet50"], + "4x25G[10G]": ["Ethernet48", "Ethernet49", "Ethernet50", "Ethernet51"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "breakout_modes": { + "1x100G[40G]": ["Ethernet52"], + "2x50G": ["Ethernet52", "Ethernet54"], + "4x25G[10G]": ["Ethernet52", "Ethernet53", "Ethernet54", "Ethernet55"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "breakout_modes": { + "1x100G[40G]": ["Ethernet56"], + "2x50G": ["Ethernet56", "Ethernet58"], + "4x25G[10G]": ["Ethernet56", "Ethernet57", "Ethernet58", "Ethernet59"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "breakout_modes": { + "1x100G[40G]": ["Ethernet60"], + "2x50G": ["Ethernet60", "Ethernet62"], + "4x25G[10G]": ["Ethernet60", "Ethernet61", "Ethernet62", "Ethernet63"] + } + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "64,65,66,67", + "breakout_modes": { + "1x100G[40G]": ["Ethernet64"], + "2x50G": ["Ethernet64", "Ethernet66"], + "4x25G[10G]": ["Ethernet64", "Ethernet65", "Ethernet66", "Ethernet67"] + } + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "68,69,70,71", + "breakout_modes": { + "1x100G[40G]": ["Ethernet68"], + "2x50G": ["Ethernet68", "Ethernet70"], + "4x25G[10G]": ["Ethernet68", "Ethernet69", "Ethernet70", "Ethernet71"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "breakout_modes": { + "1x100G[40G]": ["Ethernet72"], + "2x50G": ["Ethernet72", "Ethernet74"], + "4x25G[10G]": ["Ethernet72", "Ethernet73", "Ethernet74", "Ethernet75"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "breakout_modes": { + "1x100G[40G]": ["Ethernet76"], + "2x50G": ["Ethernet76", "Ethernet78"], + "4x25G[10G]": ["Ethernet76", "Ethernet77", "Ethernet78", "Ethernet79"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "breakout_modes": { + "1x100G[40G]": ["Ethernet80"], + "2x50G": ["Ethernet80", "Ethernet82"], + "4x25G[10G]": ["Ethernet80", "Ethernet81", "Ethernet82", "Ethernet83"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "breakout_modes": { + "1x100G[40G]": ["Ethernet84"], + "2x50G": ["Ethernet84", "Ethernet86"], + "4x25G[10G]": ["Ethernet84", "Ethernet85", "Ethernet86", "Ethernet87"] + } + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "88,89,90,91", + "breakout_modes": { + "1x100G[40G]": ["Ethernet88"], + "2x50G": ["Ethernet88", "Ethernet90"], + "4x25G[10G]": ["Ethernet88", "Ethernet89", "Ethernet90", "Ethernet91"] + } + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "92,93,94,95", + "breakout_modes": { + "1x100G[40G]": ["Ethernet92"], + "2x50G": ["Ethernet92", "Ethernet94"], + "4x25G[10G]": ["Ethernet92", "Ethernet93", "Ethernet94", "Ethernet95"] + } + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "96,97,98,99", + "breakout_modes": { + "1x100G[40G]": ["Ethernet96"], + "2x50G": ["Ethernet96", "Ethernet98"], + "4x25G[10G]": ["Ethernet96", "Ethernet97", "Ethernet98", "Ethernet99"] + } + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "100,101,102,103", + "breakout_modes": { + "1x100G[40G]": ["Ethernet100"], + "2x50G": ["Ethernet100", "Ethernet102"], + "4x25G[10G]": ["Ethernet100", "Ethernet101", "Ethernet102", "Ethernet103"] + } + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "104,105,106,107", + "breakout_modes": { + "1x100G[40G]": ["Ethernet104"], + "2x50G": ["Ethernet104", "Ethernet106"], + "4x25G[10G]": ["Ethernet104", "Ethernet105", "Ethernet106", "Ethernet107"] + } + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "108,109,110,111", + "breakout_modes": { + "1x100G[40G]": ["Ethernet108"], + "2x50G": ["Ethernet108", "Ethernet110"], + "4x25G[10G]": ["Ethernet108", "Ethernet109", "Ethernet110", "Ethernet111"] + } + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "112,113,114,115", + "breakout_modes": { + "1x100G[40G]": ["Ethernet112"], + "2x50G": ["Ethernet112", "Ethernet114"], + "4x25G[10G]": ["Ethernet112", "Ethernet113", "Ethernet114", "Ethernet115"] + } + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "116,117,118,119", + "breakout_modes": { + "1x100G[40G]": ["Ethernet116"], + "2x50G": ["Ethernet116", "Ethernet118"], + "4x25G[10G]": ["Ethernet116", "Ethernet117", "Ethernet118", "Ethernet119"] + } + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "120,121,122,123", + "breakout_modes": { + "1x100G[40G]": ["Ethernet120"], + "2x50G": ["Ethernet120", "Ethernet122"], + "4x25G[10G]": ["Ethernet120", "Ethernet121", "Ethernet122", "Ethernet123"] + } + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "124,125,126,127", + "breakout_modes": { + "1x100G[40G]": ["Ethernet124"], + "2x50G": ["Ethernet124", "Ethernet126"], + "4x25G[10G]": ["Ethernet124", "Ethernet125", "Ethernet126", "Ethernet127"] + } + }, + "Ethernet128": { + "index": "33,33,33,33", + "lanes": "128,129,130,131", + "breakout_modes": { + "1x100G[40G]": ["Ethernet128"], + "2x50G": ["Ethernet128", "Ethernet130"], + "4x25G[10G]": ["Ethernet128", "Ethernet129", "Ethernet130", "Ethernet131"] + } + }, + "Ethernet132": { + "index": "34,34,34,34", + "lanes": "132,133,134,135", + "breakout_modes": { + "1x100G[40G]": ["Ethernet132"], + "2x50G": ["Ethernet132", "Ethernet134"], + "4x25G[10G]": ["Ethernet132", "Ethernet133", "Ethernet134", "Ethernet135"] + } + }, + "Ethernet136": { + "index": "35,35,35,35", + "lanes": "136,137,138,139", + "breakout_modes": { + "1x100G[40G]": ["Ethernet136"], + "2x50G": ["Ethernet136", "Ethernet138"], + "4x25G[10G]": ["Ethernet136", "Ethernet137", "Ethernet138", "Ethernet139"] + } + }, + "Ethernet140": { + "index": "36,36,36,36", + "lanes": "140,141,142,143", + "breakout_modes": { + "1x100G[40G]": ["Ethernet140"], + "2x50G": ["Ethernet140", "Ethernet142"], + "4x25G[10G]": ["Ethernet140", "Ethernet141", "Ethernet142", "Ethernet143"] + } + }, + "Ethernet144": { + "index": "37,37,37,37", + "lanes": "144,145,146,147", + "breakout_modes": { + "1x100G[40G]": ["Ethernet144"], + "2x50G": ["Ethernet144", "Ethernet146"], + "4x25G[10G]": ["Ethernet144", "Ethernet145", "Ethernet146", "Ethernet147"] + } + }, + "Ethernet148": { + "index": "38,38,38,38", + "lanes": "148,149,150,151", + "breakout_modes": { + "1x100G[40G]": ["Ethernet148"], + "2x50G": ["Ethernet148", "Ethernet150"], + "4x25G[10G]": ["Ethernet148", "Ethernet149", "Ethernet150", "Ethernet151"] + } + }, + "Ethernet152": { + "index": "39,39,39,39", + "lanes": "152,153,154,155", + "breakout_modes": { + "1x100G[40G]": ["Ethernet152"], + "2x50G": ["Ethernet152", "Ethernet154"], + "4x25G[10G]": ["Ethernet152", "Ethernet153", "Ethernet154", "Ethernet155"] + } + }, + "Ethernet156": { + "index": "40,40,40,40", + "lanes": "156,157,158,159", + "breakout_modes": { + "1x100G[40G]": ["Ethernet156"], + "2x50G": ["Ethernet156", "Ethernet158"], + "4x25G[10G]": ["Ethernet156", "Ethernet157", "Ethernet158", "Ethernet159"] + } + }, + "Ethernet160": { + "index": "41,41,41,41", + "lanes": "160,161,162,163", + "breakout_modes": { + "1x100G[40G]": ["Ethernet160"], + "2x50G": ["Ethernet160", "Ethernet162"], + "4x25G[10G]": ["Ethernet160", "Ethernet161", "Ethernet162", "Ethernet163"] + } + }, + "Ethernet164": { + "index": "42,42,42,42", + "lanes": "164,165,166,167", + "breakout_modes": { + "1x100G[40G]": ["Ethernet164"], + "2x50G": ["Ethernet164", "Ethernet166"], + "4x25G[10G]": ["Ethernet164", "Ethernet165", "Ethernet166", "Ethernet167"] + } + }, + "Ethernet168": { + "index": "43,43,43,43", + "lanes": "168,169,170,171", + "breakout_modes": { + "1x100G[40G]": ["Ethernet168"], + "2x50G": ["Ethernet168", "Ethernet170"], + "4x25G[10G]": ["Ethernet168", "Ethernet169", "Ethernet170", "Ethernet171"] + } + }, + "Ethernet172": { + "index": "44,44,44,44", + "lanes": "172,173,174,175", + "breakout_modes": { + "1x100G[40G]": ["Ethernet172"], + "2x50G": ["Ethernet172", "Ethernet174"], + "4x25G[10G]": ["Ethernet172", "Ethernet173", "Ethernet174", "Ethernet175"] + } + }, + "Ethernet176": { + "index": "45,45,45,45", + "lanes": "176,177,178,179", + "breakout_modes": { + "1x100G[40G]": ["Ethernet176"], + "2x50G": ["Ethernet176", "Ethernet178"], + "4x25G[10G]": ["Ethernet176", "Ethernet177", "Ethernet178", "Ethernet179"] + } + }, + "Ethernet180": { + "index": "46,46,46,46", + "lanes": "180,181,182,183", + "breakout_modes": { + "1x100G[40G]": ["Ethernet180"], + "2x50G": ["Ethernet180", "Ethernet182"], + "4x25G[10G]": ["Ethernet180", "Ethernet181", "Ethernet182", "Ethernet183"] + } + }, + "Ethernet184": { + "index": "47,47,47,47", + "lanes": "184,185,186,187", + "breakout_modes": { + "1x100G[40G]": ["Ethernet184"], + "2x50G": ["Ethernet184", "Ethernet186"], + "4x25G[10G]": ["Ethernet184", "Ethernet185", "Ethernet186", "Ethernet187"] + } + }, + "Ethernet188": { + "index": "48,48,48,48", + "lanes": "188,189,190,191", + "breakout_modes": { + "1x100G[40G]": ["Ethernet188"], + "2x50G": ["Ethernet188", "Ethernet190"], + "4x25G[10G]": ["Ethernet188", "Ethernet189", "Ethernet190", "Ethernet191"] + } + }, + "Ethernet192": { + "index": "49,49,49,49", + "lanes": "192,193,194,195", + "breakout_modes": { + "1x100G[40G]": ["Ethernet192"], + "2x50G": ["Ethernet192", "Ethernet194"], + "4x25G[10G]": ["Ethernet192", "Ethernet193", "Ethernet194", "Ethernet195"] + } + }, + "Ethernet196": { + "index": "50,50,50,50", + "lanes": "196,197,198,199", + "breakout_modes": { + "1x100G[40G]": ["Ethernet196"], + "2x50G": ["Ethernet196", "Ethernet198"], + "4x25G[10G]": ["Ethernet196", "Ethernet197", "Ethernet198", "Ethernet199"] + } + }, + "Ethernet200": { + "index": "51,51,51,51", + "lanes": "200,201,202,203", + "breakout_modes": { + "1x100G[40G]": ["Ethernet200"], + "2x50G": ["Ethernet200", "Ethernet202"], + "4x25G[10G]": ["Ethernet200", "Ethernet201", "Ethernet202", "Ethernet203"] + } + }, + "Ethernet204": { + "index": "52,52,52,52", + "lanes": "204,205,206,207", + "breakout_modes": { + "1x100G[40G]": ["Ethernet204"], + "2x50G": ["Ethernet204", "Ethernet206"], + "4x25G[10G]": ["Ethernet204", "Ethernet205", "Ethernet206", "Ethernet207"] + } + }, + "Ethernet208": { + "index": "53,53,53,53", + "lanes": "208,209,210,211", + "breakout_modes": { + "1x100G[40G]": ["Ethernet208"], + "2x50G": ["Ethernet208", "Ethernet210"], + "4x25G[10G]": ["Ethernet208", "Ethernet209", "Ethernet210", "Ethernet211"] + } + }, + "Ethernet212": { + "index": "54,54,54,54", + "lanes": "212,213,214,215", + "breakout_modes": { + "1x100G[40G]": ["Ethernet212"], + "2x50G": ["Ethernet212", "Ethernet214"], + "4x25G[10G]": ["Ethernet212", "Ethernet213", "Ethernet214", "Ethernet215"] + } + }, + "Ethernet216": { + "index": "55,55,55,55", + "lanes": "216,217,218,219", + "breakout_modes": { + "1x100G[40G]": ["Ethernet216"], + "2x50G": ["Ethernet216", "Ethernet218"], + "4x25G[10G]": ["Ethernet216", "Ethernet217", "Ethernet218", "Ethernet219"] + } + }, + "Ethernet220": { + "index": "56,56,56,56", + "lanes": "220,221,222,223", + "breakout_modes": { + "1x100G[40G]": ["Ethernet220"], + "2x50G": ["Ethernet220", "Ethernet222"], + "4x25G[10G]": ["Ethernet220", "Ethernet221", "Ethernet222", "Ethernet223"] + } + }, + "Ethernet224": { + "index": "57,57,57,57", + "lanes": "224,225,226,227", + "breakout_modes": { + "1x100G[40G]": ["Ethernet224"], + "2x50G": ["Ethernet224", "Ethernet226"], + "4x25G[10G]": ["Ethernet224", "Ethernet225", "Ethernet226", "Ethernet227"] + } + }, + "Ethernet228": { + "index": "58,58,58,58", + "lanes": "228,229,230,231", + "breakout_modes": { + "1x100G[40G]": ["Ethernet228"], + "2x50G": ["Ethernet228", "Ethernet230"], + "4x25G[10G]": ["Ethernet228", "Ethernet229", "Ethernet230", "Ethernet231"] + } + }, + "Ethernet232": { + "index": "59,59,59,59", + "lanes": "232,233,234,235", + "breakout_modes": { + "1x100G[40G]": ["Ethernet232"], + "2x50G": ["Ethernet232", "Ethernet234"], + "4x25G[10G]": ["Ethernet232", "Ethernet233", "Ethernet234", "Ethernet235"] + } + }, + "Ethernet236": { + "index": "60,60,60,60", + "lanes": "236,237,238,239", + "breakout_modes": { + "1x100G[40G]": ["Ethernet236"], + "2x50G": ["Ethernet236", "Ethernet238"], + "4x25G[10G]": ["Ethernet236", "Ethernet237", "Ethernet238", "Ethernet239"] + } + }, + "Ethernet240": { + "index": "61,61,61,61", + "lanes": "240,241,242,243", + "breakout_modes": { + "1x100G[40G]": ["Ethernet240"], + "2x50G": ["Ethernet240", "Ethernet242"], + "4x25G[10G]": ["Ethernet240", "Ethernet241", "Ethernet242", "Ethernet243"] + } + }, + "Ethernet244": { + "index": "62,62,62,62", + "lanes": "244,245,246,247", + "breakout_modes": { + "1x100G[40G]": ["Ethernet244"], + "2x50G": ["Ethernet244", "Ethernet246"], + "4x25G[10G]": ["Ethernet244", "Ethernet245", "Ethernet246", "Ethernet247"] + } + }, + "Ethernet248": { + "index": "63,63,63,63", + "lanes": "248,249,250,251", + "breakout_modes": { + "1x100G[40G]": ["Ethernet248"], + "2x50G": ["Ethernet248", "Ethernet250"], + "4x25G[10G]": ["Ethernet248", "Ethernet249", "Ethernet250", "Ethernet251"] + } + }, + "Ethernet252": { + "index": "64,64,64,64", + "lanes": "252,253,254,255", + "breakout_modes": { + "1x100G[40G]": ["Ethernet252"], + "2x50G": ["Ethernet252", "Ethernet254"], + "4x25G[10G]": ["Ethernet252", "Ethernet253", "Ethernet254", "Ethernet255"] + } + }, + "Ethernet256": { + "index": "65,65,65,65", + "lanes": "256,257,258,259", + "breakout_modes": { + "1x100G[40G]": ["Ethernet256"], + "2x50G": ["Ethernet256", "Ethernet258"], + "4x25G[10G]": ["Ethernet256", "Ethernet257", "Ethernet258", "Ethernet259"] + } + } + } +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/plugins b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/plugins new file mode 120000 index 000000000000..a8464d1ec2b6 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/plugins @@ -0,0 +1 @@ +../x86_64-accton_wedge100bf_32x-r0/plugins/ \ No newline at end of file diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/pmon_daemon_control.json b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..f94fa8370273 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/pmon_daemon_control.json @@ -0,0 +1,9 @@ +{ + "skip_pcied": true, + "skip_fancontrol": true, + "skip_thermalctld": true, + "skip_ledd": true, + "skip_xcvrd": false, + "skip_psud": false, + "skip_syseepromd": false +} diff --git a/device/broadcom/x86_64-bcm_xlr-r0/BCM956960K/port_config.ini b/device/broadcom/x86_64-bcm_xlr-r0/BCM956960K/port_config.ini new file mode 100644 index 000000000000..21c7013090ba --- /dev/null +++ b/device/broadcom/x86_64-bcm_xlr-r0/BCM956960K/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4 Ethernet1/0/1 0 100000 +Ethernet4 5,6,7,8 Ethernet1/0/5 1 100000 +Ethernet8 9,10,11,12 Ethernet1/0/9 2 100000 +Ethernet12 13,14,15,16 Ethernet1/0/13 3 100000 +Ethernet16 17,18,19,20 Ethernet1/0/17 4 100000 +Ethernet20 21,22,23,24 Ethernet1/0/21 5 100000 +Ethernet24 25,26,27,28 Ethernet1/0/25 6 100000 +Ethernet28 29,30,31,32 Ethernet1/0/29 7 100000 +Ethernet32 33,34,35,36 Ethernet1/0/33 8 100000 +Ethernet36 37,38,39,40 Ethernet1/0/37 9 100000 +Ethernet40 41,42,43,44 Ethernet1/0/41 10 100000 +Ethernet44 45,46,47,48 Ethernet1/0/45 11 100000 +Ethernet48 49,50,51,52 Ethernet1/0/49 12 100000 +Ethernet52 53,54,55,56 Ethernet1/0/53 13 100000 +Ethernet56 57,58,59,60 Ethernet1/0/57 14 100000 +Ethernet60 61,62,63,64 Ethernet1/0/61 15 100000 +Ethernet64 65,66,67,68 Ethernet1/0/65 16 100000 +Ethernet68 69,70,71,72 Ethernet1/0/69 17 100000 +Ethernet72 73,74,75,76 Ethernet1/0/73 18 100000 +Ethernet76 77,78,79,80 Ethernet1/0/77 19 100000 +Ethernet80 81,82,83,84 Ethernet1/0/81 20 100000 +Ethernet84 85,86,87,88 Ethernet1/0/85 21 100000 +Ethernet88 89,90,91,92 Ethernet1/0/89 22 100000 +Ethernet92 93,94,95,96 Ethernet1/0/93 23 100000 +Ethernet96 97,98,99,100 Ethernet1/0/97 24 100000 +Ethernet100 101,102,103,104 Ethernet1/0/101 25 100000 +Ethernet104 105,106,107,108 Ethernet1/0/105 26 100000 +Ethernet108 109,110,111,112 Ethernet1/0/109 27 100000 +Ethernet112 113,114,115,116 Ethernet1/0/113 28 100000 +Ethernet116 117,118,119,120 Ethernet1/0/117 29 100000 +Ethernet120 121,122,123,124 Ethernet1/0/121 30 100000 +Ethernet124 125,126,127,128 Ethernet1/0/125 31 100000 diff --git a/device/broadcom/x86_64-bcm_xlr-r0/BCM956960K/sai.profile b/device/broadcom/x86_64-bcm_xlr-r0/BCM956960K/sai.profile new file mode 100644 index 000000000000..9e6a31e3d1e9 --- /dev/null +++ b/device/broadcom/x86_64-bcm_xlr-r0/BCM956960K/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th_32x100.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/broadcom/x86_64-bcm_xlr-r0/BCM956960K/th_32x100.config.bcm b/device/broadcom/x86_64-bcm_xlr-r0/BCM956960K/th_32x100.config.bcm new file mode 100644 index 000000000000..16f18dcd2fd0 --- /dev/null +++ b/device/broadcom/x86_64-bcm_xlr-r0/BCM956960K/th_32x100.config.bcm @@ -0,0 +1,77 @@ +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 +portmap_34=33:100 +portmap_35=37:100 +portmap_36=41:100 +portmap_37=45:100 +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=113:100 +portmap_107=117:100 +portmap_108=121:100 +portmap_109=125:100 +oversubscribe_mode=1 +portmap_66=129:10 +portmap_100=131:10 +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 +xgxs_tx_lane_map_ce18=0x1032 +xgxs_rx_lane_map_ce18=0x1032 +xgxs_rx_lane_map_ce19=0x2301 +xgxs_rx_lane_map_ce20=0x2301 +xgxs_rx_lane_map_ce21=0x2301 +xgxs_rx_lane_map_ce22=0x2301 +xgxs_rx_lane_map_ce23=0x2301 +xgxs_rx_lane_map_ce24=0x2301 +xgxs_rx_lane_map_ce25=0x2301 +xgxs_rx_lane_map_ce26=0x2301 +xgxs_rx_lane_map_ce27=0x2301 +xgxs_rx_lane_map_ce28=0x2301 +phy_xaui_rx_polarity_flip_ce4=0x2 +phy_xaui_tx_polarity_flip_ce5=0x8 +phy_xaui_rx_polarity_flip_ce5=0x5 +phy_xaui_rx_polarity_flip_ce6=0x2 +phy_xaui_tx_polarity_flip_ce7=0x8 +phy_xaui_tx_polarity_flip_ce8=0x8 +phy_xaui_rx_polarity_flip_ce8=0x8 +phy_xaui_tx_polarity_flip_ce10=0x8 +phy_xaui_rx_polarity_flip_ce10=0x1 +phy_xaui_rx_polarity_flip_ce11=0x2 +phy_xaui_tx_polarity_flip_ce19=0x2 +phy_xaui_rx_polarity_flip_ce19=0x3 +phy_xaui_tx_polarity_flip_ce20=0x8 +phy_xaui_rx_polarity_flip_ce21=0x4 +phy_xaui_tx_polarity_flip_ce22=0x8 +phy_xaui_rx_polarity_flip_ce22=0x8 +phy_xaui_rx_polarity_flip_ce23=0x4 +phy_xaui_rx_polarity_flip_ce24=0x4 +phy_xaui_tx_polarity_flip_ce25=0x8 +phy_xaui_rx_polarity_flip_ce25=0x8 +phy_xaui_rx_polarity_flip_ce26=0x4 +phy_xaui_tx_polarity_flip_ce27=0x8 +phy_xaui_rx_polarity_flip_ce27=0x8 +l2xmsg_mode=1 +fpem_mem_entries=32768 diff --git a/device/broadcom/x86_64-bcm_xlr-r0/default_sku b/device/broadcom/x86_64-bcm_xlr-r0/default_sku new file mode 100644 index 000000000000..0f9dd1d379c4 --- /dev/null +++ b/device/broadcom/x86_64-bcm_xlr-r0/default_sku @@ -0,0 +1 @@ +bcm_xlr t1 diff --git a/device/broadcom/x86_64-bcm_xlr-r0/installer.conf b/device/broadcom/x86_64-bcm_xlr-r0/installer.conf new file mode 100644 index 000000000000..32c7bd1c1724 --- /dev/null +++ b/device/broadcom/x86_64-bcm_xlr-r0/installer.conf @@ -0,0 +1,9 @@ +if [ -d /sys/devices/pci0000:00/0000:00:13.0 ]; then + CONSOLE_PORT=0x3e8 + CONSOLE_DEV=2 +else + CONSOLE_PORT=0x3f8 + CONSOLE_DEV=0 +fi +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="libata.dma=0 libata.noacpi=1" +CONSOLE_SPEED=115200 diff --git a/device/broadcom/x86_64-bcm_xlr-r0/plugins/eeprom.py b/device/broadcom/x86_64-bcm_xlr-r0/plugins/eeprom.py new file mode 100644 index 000000000000..0a4e11155711 --- /dev/null +++ b/device/broadcom/x86_64-bcm_xlr-r0/plugins/eeprom.py @@ -0,0 +1,31 @@ +############################################################################# +# Broadcom XLR/GTS 'eeprom' support +# +# 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 +# +# Note: the file /usr/share/sonic/platform/sys_eeprom.bin is generated +# by the script brcm-xlr-gts-create-eeprom-file.py +############################################################################# + +import os + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/usr/share/sonic/platform/sys_eeprom.bin" + if os.path.isfile(self.eeprom_path) is False: + self.eeprom_path = "/usr/share/sonic/device/x86_64-bcm_xlr-r0/sys_eeprom.bin" + super(board, self).__init__(self.eeprom_path, 0, '', False, True) + + def serial_number_str(self, e): + """Return service tag instead of serial number""" + return "No service tag" diff --git a/device/broadcom/x86_64-bcm_xlr-r0/plugins/psuutil.py b/device/broadcom/x86_64-bcm_xlr-r0/plugins/psuutil.py new file mode 100644 index 000000000000..fefc3c3494e5 --- /dev/null +++ b/device/broadcom/x86_64-bcm_xlr-r0/plugins/psuutil.py @@ -0,0 +1,39 @@ +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 0 + + 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 + """ + return False + + 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 + """ + return False diff --git a/device/broadcom/x86_64-bcm_xlr-r0/plugins/sfputil.py b/device/broadcom/x86_64-bcm_xlr-r0/plugins/sfputil.py new file mode 100644 index 000000000000..f526706f5dd4 --- /dev/null +++ b/device/broadcom/x86_64-bcm_xlr-r0/plugins/sfputil.py @@ -0,0 +1,48 @@ +try: + import time + import os + 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 = 52 + _port_to_eeprom_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 [] + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + return False + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def set_low_power_mode(self, port_num, lpmode): + raise NotImplementedError + + def reset(self, port_num): + raise NotImplementedError + + def get_transceiver_change_event(self, timeout=0): + raise NotImplementedError diff --git a/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/helix4-e1031-48x1G+4x10G.config.bcm b/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/helix4-e1031-48x1G+4x10G.config.bcm new file mode 100644 index 000000000000..c7942d6fc0b8 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/helix4-e1031-48x1G+4x10G.config.bcm @@ -0,0 +1,64 @@ +bcm56340_4x10=1 +bcm56340_config=1 +dport_map_direct=0 +ext_sram_freq=0 +ext_tcam_freq=0 +phy_null_ge48=1 +phy_port_primary_and_offset_ge0=0x0000 +phy_port_primary_and_offset_ge1=0x0001 +phy_port_primary_and_offset_ge2=0x0002 +phy_port_primary_and_offset_ge3=0x0003 +phy_port_primary_and_offset_ge4=0x0004 +phy_port_primary_and_offset_ge5=0x0005 +phy_port_primary_and_offset_ge6=0x0006 +phy_port_primary_and_offset_ge7=0x0007 +phy_port_primary_and_offset_ge8=0x0800 +phy_port_primary_and_offset_ge9=0x0801 +phy_port_primary_and_offset_ge10=0x0802 +phy_port_primary_and_offset_ge11=0x0803 +phy_port_primary_and_offset_ge12=0x0804 +phy_port_primary_and_offset_ge13=0x0805 +phy_port_primary_and_offset_ge14=0x0806 +phy_port_primary_and_offset_ge15=0x0807 +phy_port_primary_and_offset_ge16=0x1000 +phy_port_primary_and_offset_ge17=0x1001 +phy_port_primary_and_offset_ge18=0x1002 +phy_port_primary_and_offset_ge19=0x1003 +phy_port_primary_and_offset_ge20=0x1004 +phy_port_primary_and_offset_ge21=0x1005 +phy_port_primary_and_offset_ge22=0x1006 +phy_port_primary_and_offset_ge23=0x1007 +phy_port_primary_and_offset_ge24=0x1800 +phy_port_primary_and_offset_ge25=0x1801 +phy_port_primary_and_offset_ge26=0x1802 +phy_port_primary_and_offset_ge27=0x1803 +phy_port_primary_and_offset_ge28=0x1804 +phy_port_primary_and_offset_ge29=0x1805 +phy_port_primary_and_offset_ge30=0x1806 +phy_port_primary_and_offset_ge31=0x1807 +phy_port_primary_and_offset_ge32=0x2000 +phy_port_primary_and_offset_ge33=0x2001 +phy_port_primary_and_offset_ge34=0x2002 +phy_port_primary_and_offset_ge35=0x2003 +phy_port_primary_and_offset_ge36=0x2004 +phy_port_primary_and_offset_ge37=0x2005 +phy_port_primary_and_offset_ge38=0x2006 +phy_port_primary_and_offset_ge39=0x2007 +phy_port_primary_and_offset_ge40=0x2800 +phy_port_primary_and_offset_ge41=0x2801 +phy_port_primary_and_offset_ge42=0x2802 +phy_port_primary_and_offset_ge43=0x2803 +phy_port_primary_and_offset_ge44=0x2804 +phy_port_primary_and_offset_ge45=0x2805 +phy_port_primary_and_offset_ge46=0x2806 +phy_port_primary_and_offset_ge47=0x2807 +phy_xaui_rx_polarity_flip_xe0=1 +phy_xaui_rx_polarity_flip_xe1=0 +phy_xaui_rx_polarity_flip_xe2=1 +phy_xaui_rx_polarity_flip_xe3=0 +phy_xaui_tx_polarity_flip_xe0=1 +phy_xaui_tx_polarity_flip_xe1=0 +phy_xaui_tx_polarity_flip_xe2=1 +phy_xaui_tx_polarity_flip_xe3=0 +xgxs_rx_lane_map_xe0=0x1032 +xgxs_tx_lane_map_xe0=0x2301 diff --git a/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/port_config.ini b/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/port_config.ini new file mode 100644 index 000000000000..a2b64ea155df --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/port_config.ini @@ -0,0 +1,53 @@ +# name lanes index speed alias autoneg +Ethernet0 2 1 1000 etp1 1 +Ethernet1 1 2 1000 etp2 1 +Ethernet2 4 3 1000 etp3 1 +Ethernet3 3 4 1000 etp4 1 +Ethernet4 6 5 1000 etp5 1 +Ethernet5 5 6 1000 etp6 1 +Ethernet6 8 7 1000 etp7 1 +Ethernet7 7 8 1000 etp8 1 +Ethernet8 10 9 1000 etp9 1 +Ethernet9 9 10 1000 etp10 1 +Ethernet10 12 11 1000 etp11 1 +Ethernet11 11 12 1000 etp12 1 +Ethernet12 14 13 1000 etp13 1 +Ethernet13 13 14 1000 etp14 1 +Ethernet14 16 15 1000 etp15 1 +Ethernet15 15 16 1000 etp16 1 +Ethernet16 18 17 1000 etp17 1 +Ethernet17 17 18 1000 etp18 1 +Ethernet18 20 19 1000 etp19 1 +Ethernet19 19 20 1000 etp20 1 +Ethernet20 22 21 1000 etp21 1 +Ethernet21 21 22 1000 etp22 1 +Ethernet22 24 23 1000 etp23 1 +Ethernet23 23 24 1000 etp24 1 +Ethernet24 26 25 1000 etp25 1 +Ethernet25 25 26 1000 etp26 1 +Ethernet26 28 27 1000 etp27 1 +Ethernet27 27 28 1000 etp28 1 +Ethernet28 30 29 1000 etp29 1 +Ethernet29 29 30 1000 etp30 1 +Ethernet30 32 31 1000 etp31 1 +Ethernet31 31 32 1000 etp32 1 +Ethernet32 34 33 1000 etp33 1 +Ethernet33 33 34 1000 etp34 1 +Ethernet34 36 35 1000 etp35 1 +Ethernet35 35 36 1000 etp36 1 +Ethernet36 38 37 1000 etp37 1 +Ethernet37 37 38 1000 etp38 1 +Ethernet38 40 39 1000 etp39 1 +Ethernet39 39 40 1000 etp40 1 +Ethernet40 42 41 1000 etp41 1 +Ethernet41 41 42 1000 etp42 1 +Ethernet42 44 43 1000 etp43 1 +Ethernet43 43 44 1000 etp44 1 +Ethernet44 46 45 1000 etp45 1 +Ethernet45 45 46 1000 etp46 1 +Ethernet46 48 47 1000 etp47 1 +Ethernet47 47 48 1000 etp48 1 +Ethernet48 54 49 10000 etp49 0 +Ethernet49 53 50 10000 etp50 0 +Ethernet50 56 51 10000 etp51 0 +Ethernet51 55 52 10000 etp52 0 diff --git a/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/sai.profile b/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/sai.profile new file mode 100644 index 000000000000..a98bdc993e73 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/helix4-e1031-48x1G+4x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_e1031-r0/default_sku b/device/celestica/x86_64-cel_e1031-r0/default_sku new file mode 100644 index 000000000000..89a0aac4181a --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/default_sku @@ -0,0 +1 @@ +Celestica-E1031-T48S4 t1 diff --git a/device/celestica/x86_64-cel_e1031-r0/fancontrol-B2F b/device/celestica/x86_64-cel_e1031-r0/fancontrol-B2F new file mode 100644 index 000000000000..883f3c0c899d --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/fancontrol-B2F @@ -0,0 +1,13 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=2 +DEVPATH=hwmon3=devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-23/23-004d hwmon2=devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-11/11-001a +DEVNAME=hwmon3=emc2305 hwmon2=max6699 +FCTEMPS=hwmon3/device/pwm1=hwmon2/temp1_input hwmon3/device/pwm2=hwmon2/temp1_input hwmon3/device/pwm4=hwmon2/temp1_input +FCFANS=hwmon3/device/pwm1=hwmon3/device/fan1_input hwmon3/device/pwm2=hwmon3/device/fan2_input hwmon3/device/pwm4=hwmon3/device/fan4_input +MINTEMP=hwmon3/device/pwm1=27 hwmon3/device/pwm2=27 hwmon3/device/pwm4=27 +MAXTEMP=hwmon3/device/pwm1=46 hwmon3/device/pwm2=46 hwmon3/device/pwm4=46 +MINSTART=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102 +MINSTOP=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102 +MINPWM=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102 +MAXPWM=hwmon3/device/pwm1=255 hwmon3/device/pwm2=255 hwmon3/device/pwm4=255 +THYST=hwmon3/device/pwm1=2 hwmon3/device/pwm2=2 hwmon3/device/pwm4=2 diff --git a/device/celestica/x86_64-cel_e1031-r0/fancontrol-F2B b/device/celestica/x86_64-cel_e1031-r0/fancontrol-F2B new file mode 100644 index 000000000000..3be1f7e339ca --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/fancontrol-F2B @@ -0,0 +1,13 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=2 +DEVPATH=hwmon3=devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-23/23-004d hwmon2=devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-11/11-001a +DEVNAME=hwmon3=emc2305 hwmon2=max6697 +FCTEMPS=hwmon3/device/pwm1=hwmon2/temp3_input hwmon3/device/pwm2=hwmon2/temp3_input hwmon3/device/pwm4=hwmon2/temp3_input +FCFANS=hwmon3/device/pwm1=hwmon3/device/fan1_input hwmon3/device/pwm2=hwmon3/device/fan2_input hwmon3/device/pwm4=hwmon3/device/fan4_input +MINTEMP=hwmon3/device/pwm1=29 hwmon3/device/pwm2=29 hwmon3/device/pwm4=29 +MAXTEMP=hwmon3/device/pwm1=46 hwmon3/device/pwm2=46 hwmon3/device/pwm4=46 +MINSTART=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102 +MINSTOP=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102 +MINPWM=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102 +MAXPWM=hwmon3/device/pwm1=255 hwmon3/device/pwm2=255 hwmon3/device/pwm4=255 +THYST=hwmon3/device/pwm1=2 hwmon3/device/pwm2=2 hwmon3/device/pwm4=2 diff --git a/device/celestica/x86_64-cel_e1031-r0/installer.conf b/device/celestica/x86_64-cel_e1031-r0/installer.conf new file mode 100644 index 000000000000..b158400b2292 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=9600 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="module_blacklist=gpio_ich" diff --git a/device/celestica/x86_64-cel_e1031-r0/pcie.yaml b/device/celestica/x86_64-cel_e1031-r0/pcie.yaml new file mode 100644 index 000000000000..485ac3512fe5 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/pcie.yaml @@ -0,0 +1,76 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 1f0f + name: 'Host bridge: Intel Corporation Atom processor C2000 SoC Transaction Router' +- bus: '00' + dev: '01' + fn: '0' + id: 1f10 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 1' +- bus: '00' + dev: '02' + fn: '0' + id: 1f11 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 2' +- bus: '00' + dev: '03' + fn: '0' + id: 1f12 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 3' +- bus: '00' + dev: '04' + fn: '0' + id: 1f13 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 4' +- bus: '00' + dev: 0e + fn: '0' + id: 1f14 + name: 'Host bridge: Intel Corporation Atom processor C2000 RAS' +- bus: '00' + dev: 0f + fn: '0' + id: 1f16 + name: 'IOMMU: Intel Corporation Atom processor C2000 RCEC' +- bus: '00' + dev: '13' + fn: '0' + id: 1f15 + name: 'System peripheral: Intel Corporation Atom processor C2000 SMBus 2.0' +- bus: '00' + dev: '14' + fn: '0' + id: 1f41 + name: 'Ethernet controller: Intel Corporation Ethernet Connection I354' +- bus: '00' + dev: '16' + fn: '0' + id: 1f2c + name: 'USB controller: Intel Corporation Atom processor C2000 USB Enhanced Host Controller' +- bus: '00' + dev: '17' + fn: '0' + id: 1f22 + name: 'SATA controller: Intel Corporation Atom processor C2000 AHCI SATA2 Controller' +- bus: '00' + dev: 1f + fn: '0' + id: 1f38 + name: 'ISA bridge: Intel Corporation Atom processor C2000 PCU' +- bus: '00' + dev: 1f + fn: '3' + id: 1f3c + name: 'SMBus: Intel Corporation Atom processor C2000 PCU SMBus' +- bus: '01' + dev: '00' + fn: '0' + id: b340 + name: 'Ethernet controller: Broadcom Limited Device b340' +- bus: '01' + dev: '00' + fn: '1' + id: b340 + name: 'Ethernet controller: Broadcom Limited Device b340' + diff --git a/device/celestica/x86_64-cel_e1031-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_e1031-r0/plugins/eeprom.py new file mode 100644 index 000000000000..4728d562cc7a --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Celestica Haliburton +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0050/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/celestica/x86_64-cel_e1031-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_e1031-r0/plugins/psuutil.py new file mode 100644 index 000000000000..8e019efbebcd --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/plugins/psuutil.py @@ -0,0 +1,59 @@ +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/devices/platform/e1031.smc/" + self.psu_presence = "psu{}_prs" + self.psu_oper_status = "psu{}_status" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined by 1-based index + + :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 + """ + psu_location = ["R", "L"] + status = 0 + try: + with open(self.psu_path + self.psu_oper_status.format(psu_location[index - 1]), 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined by 1-based index + + :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 + """ + psu_location = ["R", "L"] + status = 0 + try: + with open(self.psu_path + self.psu_presence.format(psu_location[index - 1]), 'r') as psu_prs: + status = int(psu_prs.read()) + except IOError: + return False + + return status == 1 diff --git a/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py new file mode 100644 index 000000000000..d65f2cf3f54f --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py @@ -0,0 +1,153 @@ +try: + import time + import os + import select + 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 = 52 + port_to_i2c_mapping = { + 1: None, + 2: None, + 3: None, + 4: None, + 5: None, + 6: None, + 7: None, + 8: None, + 9: None, + 10: None, + 11: None, + 12: None, + 13: None, + 14: None, + 15: None, + 16: None, + 17: None, + 18: None, + 19: None, + 20: None, + 21: None, + 22: None, + 23: None, + 24: None, + 25: None, + 26: None, + 27: None, + 28: None, + 29: None, + 30: None, + 31: None, + 32: None, + 33: None, + 34: None, + 35: None, + 36: None, + 37: None, + 38: None, + 39: None, + 40: None, + 41: None, + 42: None, + 43: None, + 44: None, + 45: None, + 46: None, + 47: None, + 48: None, + 49: 15, + 50: 14, + 51: 17, + 52: 16 + } + _port_to_eeprom_mapping = {} + _sfp_port = list(range(49, PORT_END + 1)) + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return [] + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + 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): + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + sfp_modabs_path = '/sys/devices/platform/e1031.smc/SFP/sfp_modabs' + + if port_num not in self._sfp_port: + return False + + status = 1 + try: + with open(sfp_modabs_path, 'r') as port_status: + status = int(port_status.read(), 16) + status = (status >> (port_num - 49)) & 1 + except IOError: + return False + + return status == 0 + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def set_low_power_mode(self, port_num, lpmode): + raise NotImplementedError + + def reset(self, port_num): + raise NotImplementedError + + def get_transceiver_change_event(self, timeout=0): + epoll = select.epoll() + port_dict = {} + timeout_sec = timeout/1000 + modabs_interrupt_path = '/sys/devices/platform/e1031.smc/SFP/modabs_int' + try: + # We get notified when there is an SCI interrupt from GPIO SUS7 + fd = open("/sys/devices/platform/hlx-ich.0/sci_int_gpio_sus7", "r") + fd.read() + + epoll.register(fd.fileno(), select.EPOLLIN & select.EPOLLET) + events = epoll.poll(timeout=timeout_sec if timeout != 0 else -1) + if events: + found_flag = 0 + # Read the QSFP ABS interrupt & status registers + with open(modabs_interrupt_path, 'r') as port_changes: + changes = int(port_changes.read(), 16) + for port_num in self._sfp_port: + change = (changes >> (port_num - 49)) & 1 + if change == 1: + port_dict[str(port_num)] = str(int(self.get_presence(port_num))) + found_flag = 1 + + if not found_flag: + return False, {} + + return True, port_dict + + finally: + fd.close() + epoll.close() + + return False, {} 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/sensors.conf b/device/celestica/x86_64-cel_e1031-r0/sensors.conf new file mode 100644 index 000000000000..64d49af1cf89 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sensors.conf @@ -0,0 +1,40 @@ +# libsensors configuration file for Celestica E1031. +# The i2c bus portion is omit because adapter name +# changes every time when system boot up. + +bus "i2c-3" "i2c-0-mux (chan_id 1)" +bus "i2c-11" "i2c-8-mux (chan_id 1)" + +chip "max6699-i2c-3-1a" + label temp2 "CPU board temperature sensor : 1" + label temp3 "CPU board temperature sensor : 2" + set temp2_max 90 + set temp3_max 90 + ignore temp1 + ignore temp4 + ignore temp5 + ignore temp6 + ignore temp7 + +chip "max6699-i2c-11-1a" + label temp1 "Rear panel-Inlet ambient sensor" + label temp2 "Rear panel-Helix shutdown sensor" + label temp3 "Front panel-Inlet ambient sensor (right)" + label temp4 "Front panel-Helix shutdown sensor" + label temp5 "Front panel-Inlet ambient sensor (left)" + set temp1_max 55 + set temp2_max 85 + set temp3_max 55 + set temp4_max 85 + set temp5_max 55 + ignore temp6 + ignore temp7 + + +chip "emc2305-i2c-*-4d" + ignore fan3 + ignore fan5 + label fan4 "Fan 1 :" + label fan2 "Fan 2 :" + label fan1 "Fan 3 :" + diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/__init__.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..d82f3749319c --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * 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 new file mode 100644 index 000000000000..40c4bb4ef73b --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/chassis.py @@ -0,0 +1,147 @@ +############################################################################# +# 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.fan import Fan + from sonic_platform.psu import Psu + from sonic_platform.component import Component + from sonic_platform.thermal import Thermal + from sonic_platform.sfp import Sfp + from sonic_platform.eeprom import Tlv +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 3 +NUM_FAN = 1 +NUM_PSU = 2 +NUM_THERMAL = 7 +NUM_SFP = 52 +NUM_COMPONENT = 3 +RESET_REGISTER = "0x112" +HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/previous-reboot-cause.txt" +PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/previous-reboot-cause.txt" +HOST_CHK_CMD = "docker > /dev/null 2>&1" + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + def __init__(self): + ChassisBase.__init__(self) + self.config_data = {} + 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) + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + # 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._reboot_cause_path = HOST_REBOOT_CAUSE_PATH if self.__is_host( + ) else PMON_REBOOT_CAUSE_PATH + + self._eeprom = Tlv() + + 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 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(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. + """ + description = 'None' + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + hw_reboot_cause = self._component_list[0].get_register_value(RESET_REGISTER) + sw_reboot_cause = self.__read_txt_file( + self._reboot_cause_path) or "Unknown" + + if hw_reboot_cause == "0x55": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = sw_reboot_cause + elif hw_reboot_cause == "0x11": + reboot_cause = self.REBOOT_CAUSE_POWER_LOSS + elif hw_reboot_cause == "0x33": + reboot_cause = self.REBOOT_CAUSE_WATCHDOG + else: + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + 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 new file mode 100644 index 000000000000..7fdfc8756a4d --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/component.py @@ -0,0 +1,144 @@ +############################################################################# +# Celestica +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +import json +import os.path +import shutil +import shlex +import subprocess + +try: + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MMC_CPLD_ADDR = '0x100' +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" +CONFIG_DB_PATH = "/etc/sonic/config_db.json" +SMC_CPLD_PATH = "/sys/devices/platform/e1031.smc/version" +GETREG_PATH = "/sys/devices/platform/e1031.smc/getreg" +COMPONENT_NAME_LIST = ["SMC_CPLD", "MMC_CPLD", "BIOS"] +COMPONENT_DES_LIST = ["System Management Controller", + "Module Management CPLD", "Basic Input/Output System"] + + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index): + ComponentBase.__init__(self) + self.index = component_index + self.name = self.get_name() + + def __run_command(self, command): + # Run bash command and print output to stdout + try: + process = subprocess.Popen( + shlex.split(command), universal_newlines=True, stdout=subprocess.PIPE) + while True: + output = process.stdout.readline() + if output == '' and process.poll() is not None: + break + rc = process.poll() + if rc != 0: + return False + except: + return False + return True + + def __get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def get_register_value(self, register): + # Retrieves the cpld register value + cmd = "echo {1} > {0}; cat {0}".format(GETREG_PATH, register) + p = subprocess.Popen( + cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err is not '': + return None + return raw_data.strip() + + def __get_cpld_version(self): + # Retrieves the CPLD firmware version + cpld_version = dict() + with open(SMC_CPLD_PATH, 'r') as fd: + smc_cpld_version = fd.read() + smc_cpld_version = 'None' if smc_cpld_version is 'None' else "{}.{}".format( + int(smc_cpld_version[2], 16), int(smc_cpld_version[3], 16)) + + mmc_cpld_version = self.get_register_value(MMC_CPLD_ADDR) + mmc_cpld_version = 'None' if mmc_cpld_version is 'None' else "{}.{}".format( + int(mmc_cpld_version[2], 16), int(mmc_cpld_version[3], 16)) + + cpld_version["SMC_CPLD"] = smc_cpld_version + cpld_version["MMC_CPLD"] = mmc_cpld_version + return cpld_version + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return COMPONENT_NAME_LIST[self.index] + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return COMPONENT_DES_LIST[self.index] + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + fw_version = None + + if self.name == "BIOS": + fw_version = self.__get_bios_version() + elif "CPLD" in self.name: + cpld_version = self.__get_cpld_version() + fw_version = cpld_version.get(self.name) + + return fw_version + + def install_firmware(self, image_path): + """ + Install firmware to module + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install successfully, False if not + """ + if not os.path.isfile(image_path): + return False + + if "CPLD" in self.name: + img_name = os.path.basename(image_path) + root, ext = os.path.splitext(img_name) + ext = ".vme" if ext == "" else ext + 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 + + return self.__run_command(install_command) diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/eeprom.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/eeprom.py new file mode 100644 index 000000000000..0058fccfa0ca --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/eeprom.py @@ -0,0 +1,114 @@ +############################################################################# +# Celestica Haliburton +# +# 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 re + from array import array + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + + +class Tlv(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0050/eeprom" + 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/device/celestica/x86_64-cel_e1031-r0/sonic_platform/fan.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/fan.py new file mode 100644 index 000000000000..18cf513800aa --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/fan.py @@ -0,0 +1,249 @@ +############################################################################# +# 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 +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +EMC2305_PATH = "/sys/bus/i2c/drivers/emc2305/" +FAN_PATH = "/sys/devices/platform/e1031.smc/" +EMC2305_MAX_PWM = 255 +EMC2305_FAN_PWM = "pwm{}" +EMC2305_FAN_TARGET = "fan{}_target" +EMC2305_FAN_INPUT = "pwm{}" +FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3"] +PSU_FAN_MAX_RPM = 11000 +PSU_HWMON_PATH = "/sys/bus/i2c/devices/i2c-{0}/{0}-00{1}/hwmon" +PSU_I2C_MAPPING = { + 0: { + "num": 13, + "addr": "5b" + }, + 1: { + "num": 12, + "addr": "5a" + }, +} + + +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.psu_i2c_num = PSU_I2C_MAPPING[self.psu_index]["num"] + self.psu_i2c_addr = PSU_I2C_MAPPING[self.psu_index]["addr"] + self.psu_hwmon_path = PSU_HWMON_PATH.format( + self.psu_i2c_num, self.psu_i2c_addr) + + # e1031 fan attributes + # Single emc2305 chip located at i2c-23-4d + # to control a fan module + self.emc2305_chip_mapping = [ + { + 'device': "23-004d", + 'index_map': [1, 2, 4] + } + ] + self.fan_e1031_presence = "fan{}_prs" + self.fan_e1031_direction = "fan{}_dir" + self.fan_e1031_led = "fan{}_led" + self.fan_e1031_led_col_map = { + self.STATUS_LED_COLOR_GREEN: "green", + self.STATUS_LED_COLOR_RED: "amber", + self.STATUS_LED_COLOR_OFF: "off" + } + FanBase.__init__(self) + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except: + return False + return True + + def __search_file_by_name(self, directory, file_name): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name in file_name: + return file_path + return None + + def get_direction(self): + """ + Retrieves the direction of fan + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + direction = self.FAN_DIRECTION_EXHAUST + if not self.is_psu_fan: + fan_direction_file = (FAN_PATH + + self.fan_e1031_direction.format(self.fan_tray_index+1)) + raw = self.__read_txt_file(fan_direction_file).strip('\r\n') + direction = self.FAN_DIRECTION_INTAKE if str( + raw).upper() == "F2B" else self.FAN_DIRECTION_EXHAUST + + return direction + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + + Note: + speed = pwm_in/255*100 + """ + speed = 0 + if self.is_psu_fan: + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + self.psu_hwmon_path, fan_speed_sysfs_name) + fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0 + fan_speed_raw = float(fan_speed_rpm)/PSU_FAN_MAX_RPM * 100 + speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM) + elif self.get_presence(): + chip = self.emc2305_chip_mapping[self.fan_index] + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_PATH, device, EMC2305_FAN_INPUT) + sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index]) + raw = self.__read_txt_file(sysfs_path).strip('\r\n') + pwm = int(raw, 10) if raw else 0 + speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM)) + + return int(speed) + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + + Note: + speed_pc = pwm_target/255*100 + + 0 : when PWM mode is use + pwm : when pwm mode is not use + """ + target = 0 + if not self.is_psu_fan: + chip = self.emc2305_chip_mapping[self.fan_index] + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_PATH, device, EMC2305_FAN_TARGET) + sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index]) + raw = self.__read_txt_file(sysfs_path).strip('\r\n') + pwm = int(raw, 10) if raw else 0 + target = math.ceil(float(pwm) * 100 / EMC2305_MAX_PWM) + + 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 10 + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + + Note: + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + pwm = speed * 255 / 100 + if not self.is_psu_fan and self.get_presence(): + chip = self.emc2305_chip_mapping[self.fan_index] + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_PATH, device, EMC2305_FAN_PWM) + sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index]) + return self.__write_txt_file(sysfs_path, int(pwm)) + + return False + + 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 + """ + set_status_led = False + if not self.is_psu_fan: + fan_led_file = (FAN_PATH + + self.fan_e1031_led.format(self.fan_tray_index+1)) + + set_status_led = self.__write_txt_file( + fan_led_file, self.fan_e1031_led_col_map[color]) if self.get_presence() else False + + return set_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] 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 PSU + Returns: + bool: True if PSU is present, False if not + """ + fan_direction_file = (FAN_PATH + + self.fan_e1031_presence.format(self.fan_tray_index+1)) + present_str = self.__read_txt_file(fan_direction_file) or '1' + + return int(present_str) == 0 if not self.is_psu_fan else True diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/platform.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/platform.py new file mode 100644 index 000000000000..7d98ec9f7cdf --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/platform.py @@ -0,0 +1,21 @@ +############################################################################# +# 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/device/celestica/x86_64-cel_e1031-r0/sonic_platform/psu.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/psu.py new file mode 100644 index 000000000000..27d70f123c59 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/psu.py @@ -0,0 +1,199 @@ +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path +import sonic_platform + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN_E1031_SPEED_PATH = "/sys/class/hwmon/hwmon{}/fan1_input" +HWMON_PATH = "/sys/bus/i2c/devices/i2c-{0}/{0}-00{1}/hwmon" +FAN_MAX_RPM = 11000 +PSU_NAME_LIST = ["PSU-R", "PSU-L"] +PSU_NUM_FAN = [1, 1] +PSU_I2C_MAPPING = { + 0: { + "num": 13, + "addr": "5b" + }, + 1: { + "num": 12, + "addr": "5a" + }, +} + + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, psu_index): + PsuBase.__init__(self) + self.index = psu_index + self.psu_path = "/sys/devices/platform/e1031.smc/" + self.psu_presence = "psu{}_prs" + self.psu_oper_status = "psu{}_status" + self.i2c_num = PSU_I2C_MAPPING[self.index]["num"] + self.i2c_addr = PSU_I2C_MAPPING[self.index]["addr"] + self.hwmon_path = HWMON_PATH.format(self.i2c_num, self.i2c_addr) + for fan_index in range(0, PSU_NUM_FAN[self.index]): + fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index) + self._fan_list.append(fan) + PsuBase.__init__(self) + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __search_file_by_contain(self, directory, search_str, file_start): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name.startswith(file_start) and search_str in self.__read_txt_file(file_path): + return file_path + return None + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + psu_voltage = 0.0 + voltage_name = "in{}_input" + voltage_label = "vout1" + + vout_label_path = self.__search_file_by_contain( + self.hwmon_path, voltage_label, "in") + if vout_label_path: + dir_name = os.path.dirname(vout_label_path) + basename = os.path.basename(vout_label_path) + in_num = ''.join(list(filter(str.isdigit, basename))) + vout_path = os.path.join( + dir_name, voltage_name.format(in_num)) + vout_val = self.__read_txt_file(vout_path) + psu_voltage = float(vout_val) / 1000 + + return psu_voltage + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + psu_current = 0.0 + current_name = "curr{}_input" + current_label = "iout1" + + curr_label_path = self.__search_file_by_contain( + self.hwmon_path, current_label, "cur") + if curr_label_path: + dir_name = os.path.dirname(curr_label_path) + basename = os.path.basename(curr_label_path) + cur_num = ''.join(list(filter(str.isdigit, basename))) + cur_path = os.path.join( + dir_name, current_name.format(cur_num)) + cur_val = self.__read_txt_file(cur_path) + psu_current = float(cur_val) / 1000 + + return psu_current + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + psu_power = 0.0 + current_name = "power{}_input" + current_label = "pout1" + + pw_label_path = self.__search_file_by_contain( + self.hwmon_path, current_label, "power") + if pw_label_path: + dir_name = os.path.dirname(pw_label_path) + basename = os.path.basename(pw_label_path) + pw_num = ''.join(list(filter(str.isdigit, basename))) + pw_path = os.path.join( + dir_name, current_name.format(pw_num)) + pw_val = self.__read_txt_file(pw_path) + psu_power = float(pw_val) / 1000000 + + return psu_power + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + return self.get_status() + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the PSU status LED + Note: Only support green and off + Returns: + bool: True if status LED state is set successfully, False if not + """ + # Hardware not supported + return False + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + # Hardware not supported + return self.STATUS_LED_COLOR_OFF + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return PSU_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + psu_location = ["R", "L"] + presences_status = self.__read_txt_file( + self.psu_path + self.psu_presence.format(psu_location[self.index])) or 0 + + return int(presences_status) == 1 + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + psu_location = ["R", "L"] + power_status = self.__read_txt_file( + self.psu_path + self.psu_oper_status.format(psu_location[self.index])) or 0 + + return int(power_status) == 1 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 new file mode 100644 index 000000000000..608111d7e2fd --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/sfp.py @@ -0,0 +1,714 @@ +############################################################################# +# Celestica +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# + +import os +import time +import subprocess +from ctypes import create_string_buffer + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sffbase + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +INFO_OFFSET = 0 +DOM_OFFSET = 256 + +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + +# Offset for values in SFP eeprom +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 40 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 1 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + + # Port number + PORT_START = 1 + PORT_END = 52 + port_to_i2c_mapping = { + 49: 15, + 50: 14, + 51: 17, + 52: 16 + } + _sfp_port = list(range(49, PORT_END + 1)) + PRS_PATH = "/sys/devices/platform/e1031.smc/SFP/sfp_modabs" + PLATFORM_ROOT_PATH = '/usr/share/sonic/device' + PMON_HWSKU_PATH = '/usr/share/sonic/hwsku' + HOST_CHK_CMD = "docker > /dev/null 2>&1" + + PLATFORM = "x86_64-cel_e1031-r0" + HWSKU = "Celestica-E1031-T48S4" + + def __init__(self, sfp_index): + # Init index + self.index = sfp_index + self.port_num = self.index + + # Init eeprom path + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' + self.port_to_eeprom_mapping = {} + for x in range(self.PORT_START, self.PORT_END + 1): + if x not in self._sfp_port: + self.port_to_i2c_mapping[x] = None + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self.port_to_i2c_mapping[x]) + + self.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + SfpBase.__init__(self) + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) + hwsku_path = "/".join([platform_path, self.HWSKU] + ) if self.__is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + # check present status + sfpi_obj = sff8472InterfaceId() + if not self.get_presence() or not sfpi_obj: + return {} + + offset = INFO_OFFSET + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_SFP) + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( + sfp_interface_bulk_raw, 0) + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_vendor_name_raw, 0) + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_vendor_pn_raw, 0) + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_SFP) + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_vendor_rev_raw, 0) + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_vendor_sn_raw, 0) + + sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_vendor_oui_raw, 0) + + sfp_vendor_date_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_vendor_date_raw, 0) + + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + compliance_code_dict = dict() + + if sfp_interface_bulk_data: + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data[ + 'data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' + transceiver_info_dict['cable_type'] = "Unknown" + transceiver_info_dict['cable_length'] = "Unknown" + + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + # check present status + sfpd_obj = sff8472Dom() + if not self.get_presence() or not sfpd_obj: + return {} + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = DOM_OFFSET + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_voltage_data = sfpd_obj.parse_channel_monitor_params( + dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_voltage_data['data']['TXPower']['value'] + transceiver_dom_info_dict['rx1power'] = dom_voltage_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_voltage_data['data']['TXBias']['value'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num( + transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + # check present status + sfpd_obj = sff8472Dom() + + if not self.get_presence() and not sfpd_obj: + return {} + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = DOM_OFFSET + transceiver_dom_threshold_info_dict = dict.fromkeys( + self.threshold_dict_keys, 'N/A') + dom_module_threshold_raw = self.__read_eeprom_specific_bytes( + (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) + + 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'] + + for key in transceiver_dom_threshold_info_dict: + transceiver_dom_threshold_info_dict[key] = self._convert_string_to_num( + transceiver_dom_threshold_info_dict[key]) + + return transceiver_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + rx_los = False + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + rx_los = (sffbase().test_bit(data, 1) != 0) + + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + tx_fault = False + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + tx_fault = (sffbase().test_bit(data, 2) != 0) + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + tx_disable = False + tx_fault = False + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + tx_disable_hard = (sffbase().test_bit( + data, SFP_TX_DISABLE_HARD_BIT) != 0) + tx_disable_soft = (sffbase().test_bit( + data, SFP_TX_DISABLE_SOFT_BIT) != 0) + tx_disable = tx_disable_hard | tx_disable_soft + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + # SFP doesn't support this feature + return 0 + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("temperature", "N/A") + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + Returns: + An integer number of supply voltage in mV + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("voltage", "N/A") + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A") + return [tx1_bs, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A") + return [rx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A") + return [tx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + # SFP doesn't support this feature + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw is not None: + # Set bit 6 for Soft TX Disable Select + # 01000000 = 64 and 10111111 = 191 + tx_disable_bit = 64 if tx_disable else 191 + status_control = int(status_control_raw[0], 16) + tx_disable_ctl = (status_control | tx_disable_bit) if tx_disable else ( + status_control & tx_disable_bit) + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="r+b", buffering=0) + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom.seek(SFP_STATUS_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except: + #print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + Returns: + A boolean, True if successful, False if not + """ + # SFP doesn't support this feature + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + # SFP doesn't support this feature + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + # SFP doesn't support this feature + return False + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + if self.port_num not in self._sfp_port: + return False + + status = 1 + try: + with open(self.PRS_PATH, 'r') as port_status: + status = int(port_status.read(), 16) + status = (status >> (self.port_num - 49)) & 1 + except IOError: + return False + + return status == 0 + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("model", "N/A") + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("serial", "N/A") diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/thermal.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/thermal.py new file mode 100644 index 000000000000..157f49a7c3e2 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/thermal.py @@ -0,0 +1,162 @@ +############################################################################# +# Celestica +# +# Thermal contains an implementation of SONiC Platform Base API and +# provides the thermal device status which are available in the platform +# +############################################################################# + +import os +import re +import os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + THERMAL_NAME_LIST = [] + MAINBOARD_SS_PATH = "/sys/class/i2c-adapter/i2c-11/11-001a/hwmon/hwmon2" + CPUBOARD_SS_PATH = "/sys/class/i2c-adapter/i2c-3/3-001a/hwmon/hwmon1" + SS_CONFIG_PATH = "/usr/share/sonic/device/x86_64-cel_e1031-r0/sensors.conf" + + def __init__(self, thermal_index): + self.index = thermal_index + + # Add thermal name + self.THERMAL_NAME_LIST.append("Rear panel-Inlet ambient sensor") + self.THERMAL_NAME_LIST.append("Rear panel-Helix shutdown sensor") + self.THERMAL_NAME_LIST.append( + "Front panel-Inlet ambient sensor (right)") + self.THERMAL_NAME_LIST.append("Front panel-Helix shutdown sensor") + self.THERMAL_NAME_LIST.append( + "Front panel-Inlet ambient sensor (left)") + self.THERMAL_NAME_LIST.append("CPU board temperature sensor : 1") + self.THERMAL_NAME_LIST.append("CPU board temperature sensor : 2") + + # Set hwmon path + self.ss_index, self.hwmon_path = self.__get_ss_info(self.index) + self.ss_key = self.THERMAL_NAME_LIST[self.index] + + def __get_ss_info(self, index): + if self.index <= 4: + ss_path = self.MAINBOARD_SS_PATH + ss_index = index+1 + else: + ss_path = self.CPUBOARD_SS_PATH + ss_index = index-3 + return ss_index, ss_path + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + raise IOError("Unable to open %s file !" % file_path) + + def __get_temp(self, temp_file): + temp_file_path = os.path.join(self.hwmon_path, temp_file) + raw_temp = self.__read_txt_file(temp_file_path) + temp = float(raw_temp)/1000 + return "{:.3f}".format(temp) + + def __set_threshold(self, file_name, temperature): + temp_file_path = os.path.join(self.hwmon_path, file_name) + try: + with open(temp_file_path, 'w') as fd: + fd.write(str(temperature)) + return True + except IOError: + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temp_file = "temp{}_input".format(self.ss_index) + return self.__get_temp(temp_file) + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + temp_file = "temp{}_max".format(self.ss_index) + return self.__get_temp(temp_file) + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if not + """ + temp_file = "temp{}_max".format(self.ss_index) + is_set = self.__set_threshold(temp_file, int(temperature*1000)) + file_set = False + if is_set: + try: + with open(self.SS_CONFIG_PATH, 'r+') as f: + content = f.readlines() + f.seek(0) + ss_found = False + for idx, val in enumerate(content): + if self.ss_key in val: + ss_found = True + elif ss_found and temp_file in val: + content[idx] = " set {} {}\n".format( + temp_file, temperature) + f.writelines(content) + file_set = True + break + except IOError: + file_set = False + + return is_set & file_set + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.THERMAL_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self.hwmon_path, temp_file) + return os.path.isfile(temp_file_path) + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + if not self.get_presence(): + return False + + fault_file = "temp{}_fault".format(self.ss_index) + fault_file_path = os.path.join(self.hwmon_path, fault_file) + if not os.path.isfile(fault_file_path): + return True + + raw_txt = self.__read_txt_file(fault_file_path) + return int(raw_txt) == 0 diff --git a/device/celestica/x86_64-cel_e1031-r0/sonic_platform/watchdog.py b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/watchdog.py new file mode 100644 index 000000000000..882285251784 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/sonic_platform/watchdog.py @@ -0,0 +1,231 @@ +############################################################################# +# Celestica +# +# Watchdog contains an implementation of SONiC Platform Base API +# +############################################################################# +import ctypes +import fcntl +import os +import subprocess +import time +import array + +try: + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +""" ioctl constants """ +IO_WRITE = 0x40000000 +IO_READ = 0x80000000 +IO_READ_WRITE = 0xC0000000 +IO_SIZE_INT = 0x00040000 +IO_SIZE_40 = 0x00280000 +IO_TYPE_WATCHDOG = ord('W') << 8 + +WDR_INT = IO_READ | IO_SIZE_INT | IO_TYPE_WATCHDOG +WDR_40 = IO_READ | IO_SIZE_40 | IO_TYPE_WATCHDOG +WDWR_INT = IO_READ_WRITE | IO_SIZE_INT | IO_TYPE_WATCHDOG + +""" Watchdog ioctl commands """ +WDIOC_GETSUPPORT = 0 | WDR_40 +WDIOC_GETSTATUS = 1 | WDR_INT +WDIOC_GETBOOTSTATUS = 2 | WDR_INT +WDIOC_GETTEMP = 3 | WDR_INT +WDIOC_SETOPTIONS = 4 | WDR_INT +WDIOC_KEEPALIVE = 5 | WDR_INT +WDIOC_SETTIMEOUT = 6 | WDWR_INT +WDIOC_GETTIMEOUT = 7 | WDR_INT +WDIOC_SETPRETIMEOUT = 8 | WDWR_INT +WDIOC_GETPRETIMEOUT = 9 | WDR_INT +WDIOC_GETTIMELEFT = 10 | WDR_INT + +""" Watchdog status constants """ +WDIOS_DISABLECARD = 0x0001 +WDIOS_ENABLECARD = 0x0002 + +WDT_COMMON_ERROR = -1 +WD_MAIN_IDENTITY = "iTCO_wdt" +WDT_SYSFS_PATH = "/sys/class/watchdog/" + + +class Watchdog(WatchdogBase): + + def __init__(self): + + self.watchdog, self.wdt_main_dev_name = self._get_wdt() + self.status_path = "/sys/class/watchdog/%s/status" % self.wdt_main_dev_name + self.state_path = "/sys/class/watchdog/%s/state" % self.wdt_main_dev_name + self.timeout_path = "/sys/class/watchdog/%s/timeout" % self.wdt_main_dev_name + # Set default value + self._disable() + self.armed = False + self.timeout = self._gettimeout(self.timeout_path) + + def _is_wd_main(self, dev): + """ + Checks watchdog identity + """ + identity = self._read_file( + "{}/{}/identity".format(WDT_SYSFS_PATH, dev)) + return identity == WD_MAIN_IDENTITY + + def _get_wdt(self): + """ + Retrieves watchdog device + """ + wdt_main_dev_list = [dev for dev in os.listdir( + "/dev/") if dev.startswith("watchdog") and self._is_wd_main(dev)] + if not wdt_main_dev_list: + return None + wdt_main_dev_name = wdt_main_dev_list[0] + watchdog_device_path = "/dev/{}".format(wdt_main_dev_name) + watchdog = os.open(watchdog_device_path, os.O_RDWR) + return watchdog, wdt_main_dev_name + + def _read_file(self, file_path): + """ + Read text file + """ + try: + with open(file_path, "r") as fd: + txt = fd.read() + except IOError: + return WDT_COMMON_ERROR + return txt.strip() + + def _enable(self): + """ + Turn on the watchdog timer + """ + req = array.array('h', [WDIOS_ENABLECARD]) + fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False) + + def _disable(self): + """ + Turn off the watchdog timer + """ + req = array.array('h', [WDIOS_DISABLECARD]) + fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False) + + def _keepalive(self): + """ + Keep alive watchdog timer + """ + fcntl.ioctl(self.watchdog, WDIOC_KEEPALIVE) + + def _settimeout(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + req = array.array('I', [seconds]) + fcntl.ioctl(self.watchdog, WDIOC_SETTIMEOUT, req, True) + return int(req[0]) + + def _gettimeout(self, timeout_path): + """ + Get watchdog timeout + @return watchdog timeout + """ + req = array.array('I', [0]) + fcntl.ioctl(self.watchdog, WDIOC_GETTIMEOUT, req, True) + + return int(req[0]) + + def _gettimeleft(self): + """ + Get time left before watchdog timer expires + @return time left in seconds + """ + req = array.array('I', [0]) + fcntl.ioctl(self.watchdog, WDIOC_GETTIMELEFT, req, True) + + return int(req[0]) + + ################################################################# + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* available + value. + Returns: + An integer specifying the *actual* number of seconds the watchdog + was armed with. On failure returns -1. + """ + + ret = WDT_COMMON_ERROR + if seconds < 0: + return ret + + try: + if self.timeout != seconds: + self.timeout = self._settimeout(seconds) + if self.armed: + self._keepalive() + else: + self._enable() + self.armed = True + ret = self.timeout + except IOError as e: + pass + + return ret + + def disarm(self): + """ + Disarm the hardware watchdog + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + disarmed = False + if self.is_armed(): + try: + self._disable() + self.armed = False + disarmed = True + except IOError: + pass + + return disarmed + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + Returns: + A boolean, True if watchdog is armed, False if not + """ + + return self.armed + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds remaining on + the watchdog timer + Returns: + An integer specifying the number of seconds remaining on thei + watchdog timer. If the watchdog is not armed, returns -1. + """ + + timeleft = WDT_COMMON_ERROR + + if self.armed: + try: + timeleft = self._gettimeleft() + except IOError: + pass + + return timeleft + + def __del__(self): + """ + Close watchdog + """ + + os.close(self.watchdog) diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/buffers.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/buffers.json.j2 new file mode 100644 index 000000000000..45cebf3b7144 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 64 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/config_64x100G_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/config_64x100G_midstone200i.yaml new file mode 100755 index 000000000000..0b7e1a2db9d6 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/config_64x100G_midstone200i.yaml @@ -0,0 +1,639 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "innovium.77700_B" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "128" + type: "cpu" + - fec: "KRFEC" + id: "1" + lanes: "0:4" + serdes_group: "31" + speed: "100G" + sysport: "1" + type: "eth" + - fec: "KRFEC" + id: "2" + lanes: "4:4" + serdes_group: "31" + speed: "100G" + sysport: "2" + type: "eth" + - fec: "KRFEC" + id: "3" + lanes: "4:4" + serdes_group: "30" + speed: "100G" + sysport: "3" + type: "eth" + - fec: "KRFEC" + id: "4" + lanes: "0:4" + serdes_group: "30" + speed: "100G" + sysport: "4" + type: "eth" + - fec: "KRFEC" + id: "5" + lanes: "0:4" + serdes_group: "29" + speed: "100G" + sysport: "5" + type: "eth" + - fec: "KRFEC" + id: "6" + lanes: "4:4" + serdes_group: "29" + speed: "100G" + sysport: "6" + type: "eth" + - fec: "KRFEC" + id: "7" + lanes: "4:4" + serdes_group: "28" + speed: "100G" + sysport: "7" + type: "eth" + - fec: "KRFEC" + id: "8" + lanes: "0:4" + serdes_group: "28" + speed: "100G" + sysport: "8" + type: "eth" + - fec: "KRFEC" + id: "9" + lanes: "0:4" + serdes_group: "27" + speed: "100G" + sysport: "9" + type: "eth" + - fec: "KRFEC" + id: "10" + lanes: "4:4" + serdes_group: "27" + speed: "100G" + sysport: "10" + type: "eth" + - fec: "KRFEC" + id: "11" + lanes: "4:4" + serdes_group: "26" + speed: "100G" + sysport: "11" + type: "eth" + - fec: "KRFEC" + id: "12" + lanes: "0:4" + serdes_group: "26" + speed: "100G" + sysport: "12" + type: "eth" + - fec: "KRFEC" + id: "13" + lanes: "0:4" + serdes_group: "25" + speed: "100G" + sysport: "13" + type: "eth" + - fec: "KRFEC" + id: "14" + lanes: "4:4" + serdes_group: "25" + speed: "100G" + sysport: "14" + type: "eth" + - fec: "KRFEC" + id: "15" + lanes: "4:4" + serdes_group: "24" + speed: "100G" + sysport: "15" + type: "eth" + - fec: "KRFEC" + id: "16" + lanes: "0:4" + serdes_group: "24" + speed: "100G" + sysport: "16" + type: "eth" + - fec: "KRFEC" + id: "17" + lanes: "0:4" + serdes_group: "23" + speed: "100G" + sysport: "17" + type: "eth" + - fec: "KRFEC" + id: "18" + lanes: "4:4" + serdes_group: "23" + speed: "100G" + sysport: "18" + type: "eth" + - fec: "KRFEC" + id: "19" + lanes: "4:4" + serdes_group: "22" + speed: "100G" + sysport: "19" + type: "eth" + - fec: "KRFEC" + id: "20" + lanes: "0:4" + serdes_group: "22" + speed: "100G" + sysport: "20" + type: "eth" + - fec: "KRFEC" + id: "21" + lanes: "0:4" + serdes_group: "21" + speed: "100G" + sysport: "21" + type: "eth" + - fec: "KRFEC" + id: "22" + lanes: "4:4" + serdes_group: "21" + speed: "100G" + sysport: "22" + type: "eth" + - fec: "KRFEC" + id: "23" + lanes: "4:4" + serdes_group: "20" + speed: "100G" + sysport: "23" + type: "eth" + - fec: "KRFEC" + id: "24" + lanes: "0:4" + serdes_group: "20" + speed: "100G" + sysport: "24" + type: "eth" + - fec: "KRFEC" + id: "25" + lanes: "0:4" + serdes_group: "19" + speed: "100G" + sysport: "25" + type: "eth" + - fec: "KRFEC" + id: "26" + lanes: "4:4" + serdes_group: "19" + speed: "100G" + sysport: "26" + type: "eth" + - fec: "KRFEC" + id: "27" + lanes: "4:4" + serdes_group: "18" + speed: "100G" + sysport: "27" + type: "eth" + - fec: "KRFEC" + id: "28" + lanes: "0:4" + serdes_group: "18" + speed: "100G" + sysport: "28" + type: "eth" + - fec: "KRFEC" + id: "29" + lanes: "0:4" + serdes_group: "17" + speed: "100G" + sysport: "29" + type: "eth" + - fec: "KRFEC" + id: "30" + lanes: "4:4" + serdes_group: "17" + speed: "100G" + sysport: "30" + type: "eth" + - fec: "KRFEC" + id: "31" + lanes: "4:4" + serdes_group: "16" + speed: "100G" + sysport: "31" + type: "eth" + - fec: "KRFEC" + id: "32" + lanes: "0:4" + serdes_group: "16" + speed: "100G" + sysport: "32" + type: "eth" + - fec: "KRFEC" + id: "33" + lanes: "0:4" + serdes_group: "15" + speed: "100G" + sysport: "33" + type: "eth" + - fec: "KRFEC" + id: "34" + lanes: "4:4" + serdes_group: "15" + speed: "100G" + sysport: "34" + type: "eth" + - fec: "KRFEC" + id: "35" + lanes: "4:4" + serdes_group: "14" + speed: "100G" + sysport: "35" + type: "eth" + - fec: "KRFEC" + id: "36" + lanes: "0:4" + serdes_group: "14" + speed: "100G" + sysport: "36" + type: "eth" + - fec: "KRFEC" + id: "37" + lanes: "0:4" + serdes_group: "13" + speed: "100G" + sysport: "37" + type: "eth" + - fec: "KRFEC" + id: "38" + lanes: "4:4" + serdes_group: "13" + speed: "100G" + sysport: "38" + type: "eth" + - fec: "KRFEC" + id: "39" + lanes: "4:4" + serdes_group: "12" + speed: "100G" + sysport: "39" + type: "eth" + - fec: "KRFEC" + id: "40" + lanes: "0:4" + serdes_group: "12" + speed: "100G" + sysport: "40" + type: "eth" + - fec: "KRFEC" + id: "41" + lanes: "0:4" + serdes_group: "11" + speed: "100G" + sysport: "41" + type: "eth" + - fec: "KRFEC" + id: "42" + lanes: "4:4" + serdes_group: "11" + speed: "100G" + sysport: "42" + type: "eth" + - fec: "KRFEC" + id: "43" + lanes: "4:4" + serdes_group: "10" + speed: "100G" + sysport: "43" + type: "eth" + - fec: "KRFEC" + id: "44" + lanes: "0:4" + serdes_group: "10" + speed: "100G" + sysport: "44" + type: "eth" + - fec: "KRFEC" + id: "45" + lanes: "0:4" + serdes_group: "9" + speed: "100G" + sysport: "45" + type: "eth" + - fec: "KRFEC" + id: "46" + lanes: "4:4" + serdes_group: "9" + speed: "100G" + sysport: "46" + type: "eth" + - fec: "KRFEC" + id: "47" + lanes: "4:4" + serdes_group: "8" + speed: "100G" + sysport: "47" + type: "eth" + - fec: "KRFEC" + id: "48" + lanes: "0:4" + serdes_group: "8" + speed: "100G" + sysport: "48" + type: "eth" + - fec: "KRFEC" + id: "49" + lanes: "0:4" + serdes_group: "7" + speed: "100G" + sysport: "49" + type: "eth" + - fec: "KRFEC" + id: "50" + lanes: "4:4" + serdes_group: "7" + speed: "100G" + sysport: "50" + type: "eth" + - fec: "KRFEC" + id: "51" + lanes: "4:4" + serdes_group: "6" + speed: "100G" + sysport: "51" + type: "eth" + - fec: "KRFEC" + id: "52" + lanes: "0:4" + serdes_group: "6" + speed: "100G" + sysport: "52" + type: "eth" + - fec: "KRFEC" + id: "53" + lanes: "0:4" + serdes_group: "5" + speed: "100G" + sysport: "53" + type: "eth" + - fec: "KRFEC" + id: "54" + lanes: "4:4" + serdes_group: "5" + speed: "100G" + sysport: "54" + type: "eth" + - fec: "KRFEC" + id: "55" + lanes: "4:4" + serdes_group: "4" + speed: "100G" + sysport: "55" + type: "eth" + - fec: "KRFEC" + id: "56" + lanes: "0:4" + serdes_group: "4" + speed: "100G" + sysport: "56" + type: "eth" + - fec: "KRFEC" + id: "57" + lanes: "0:4" + serdes_group: "3" + speed: "100G" + sysport: "57" + type: "eth" + - fec: "KRFEC" + id: "58" + lanes: "4:4" + serdes_group: "3" + speed: "100G" + sysport: "58" + type: "eth" + - fec: "KRFEC" + id: "59" + lanes: "4:4" + serdes_group: "2" + speed: "100G" + sysport: "59" + type: "eth" + - fec: "KRFEC" + id: "60" + lanes: "0:4" + serdes_group: "2" + speed: "100G" + sysport: "60" + type: "eth" + - fec: "KRFEC" + id: "61" + lanes: "0:4" + serdes_group: "1" + speed: "100G" + sysport: "61" + type: "eth" + - fec: "KRFEC" + id: "62" + lanes: "4:4" + serdes_group: "1" + speed: "100G" + sysport: "62" + type: "eth" + - fec: "KRFEC" + id: "63" + lanes: "4:4" + serdes_group: "0" + speed: "100G" + sysport: "63" + type: "eth" + - fec: "KRFEC" + id: "64" + lanes: "0:4" + serdes_group: "0" + speed: "100G" + sysport: "64" + type: "eth" + isg: + - id: "0" + tx_polarity: "00101001" + rx_polarity: "01110001" + lane_swap: "01234567" + - id: "1" + tx_polarity: "10111111" + rx_polarity: "11100100" + lane_swap: "01234567" + - id: "2" + tx_polarity: "00100010" + rx_polarity: "00010001" + lane_swap: "01234567" + - id: "3" + tx_polarity: "00101010" + rx_polarity: "11011101" + lane_swap: "01234567" + - id: "4" + tx_polarity: "10111110" + rx_polarity: "10010101" + lane_swap: "01234567" + - id: "5" + tx_polarity: "01101000" + rx_polarity: "10111001" + lane_swap: "01234567" + - id: "6" + tx_polarity: "01110110" + rx_polarity: "01110011" + lane_swap: "01234567" + - id: "7" + tx_polarity: "01001000" + rx_polarity: "10111001" + lane_swap: "01234567" + - id: "8" + tx_polarity: "11000100" + rx_polarity: "01000000" + lane_swap: "01234567" + - id: "9" + tx_polarity: "10001010" + rx_polarity: "10100100" + lane_swap: "01234567" + - id: "10" + tx_polarity: "11000110" + rx_polarity: "00011101" + lane_swap: "01234567" + - id: "11" + tx_polarity: "01000111" + rx_polarity: "00000101" + lane_swap: "01234567" + - id: "12" + tx_polarity: "01111000" + rx_polarity: "11100000" + lane_swap: "01234567" + - id: "13" + tx_polarity: "10011111" + rx_polarity: "00101111" + lane_swap: "01234567" + - id: "14" + tx_polarity: "00101001" + rx_polarity: "00011000" + lane_swap: "01234567" + - id: "15" + tx_polarity: "10110111" + rx_polarity: "00110110" + lane_swap: "01234567" + - id: "16" + tx_polarity: "00101001" + rx_polarity: "00000111" + lane_swap: "01234567" + - id: "17" + tx_polarity: "10100111" + rx_polarity: "10001000" + lane_swap: "01234567" + - id: "18" + tx_polarity: "00011001" + rx_polarity: "11111110" + lane_swap: "01234567" + - id: "19" + tx_polarity: "10010101" + rx_polarity: "10011010" + lane_swap: "01234567" + - id: "20" + tx_polarity: "00101001" + rx_polarity: "01100000" + lane_swap: "01234567" + - id: "21" + tx_polarity: "10010111" + rx_polarity: "01111001" + lane_swap: "01234567" + - id: "22" + tx_polarity: "00101001" + rx_polarity: "11010011" + lane_swap: "01234567" + - id: "23" + tx_polarity: "10110111" + rx_polarity: "01111011" + lane_swap: "01234567" + - id: "24" + tx_polarity: "00101001" + rx_polarity: "11101011" + lane_swap: "01234567" + - id: "25" + tx_polarity: "10110111" + rx_polarity: "11010111" + lane_swap: "01234567" + - id: "26" + tx_polarity: "00100001" + rx_polarity: "00101101" + lane_swap: "01234567" + - id: "27" + tx_polarity: "11000111" + rx_polarity: "11011001" + lane_swap: "01234567" + - id: "28" + tx_polarity: "00100001" + rx_polarity: "01010011" + lane_swap: "01234567" + - id: "29" + tx_polarity: "10110111" + rx_polarity: "01111001" + lane_swap: "01234567" + - id: "30" + tx_polarity: "00101001" + rx_polarity: "00110001" + lane_swap: "01234567" + - id: "31" + tx_polarity: "10110101" + rx_polarity: "01101101" + lane_swap: "01234567" + - id: "32" + tx_polarity: "00000000" + rx_polarity: "00000000" + lane_swap: "01234567" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/inno.config.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/inno.config.yaml new file mode 100755 index 000000000000..b2a079136abc --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_64x100G_midstone200i.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/innovium.77700_B b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/port_config.ini b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/port_config.ini new file mode 100755 index 000000000000..c9b30d768d57 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/port_config.ini @@ -0,0 +1,65 @@ +# name lanes speed index mtu +Ethernet0 249,250,251,252 100000 1 9126 +Ethernet4 253,254,255,256 100000 2 9126 +Ethernet8 245,246,247,248 100000 3 9126 +Ethernet12 241,242,243,244 100000 4 9126 +Ethernet16 233,234,235,236 100000 5 9126 +Ethernet20 237,238,239,240 100000 6 9126 +Ethernet24 229,230,231,232 100000 7 9126 +Ethernet28 225,226,227,228 100000 8 9126 +Ethernet32 217,218,219,220 100000 9 9126 +Ethernet36 221,222,223,224 100000 10 9126 +Ethernet40 213,214,215,216 100000 11 9126 +Ethernet44 209,210,211,212 100000 12 9126 +Ethernet48 201,202,203,204 100000 13 9126 +Ethernet52 205,206,207,208 100000 14 9126 +Ethernet56 197,198,199,200 100000 15 9126 +Ethernet60 193,194,195,196 100000 16 9126 +Ethernet64 185,186,187,188 100000 17 9126 +Ethernet68 189,190,191,192 100000 18 9126 +Ethernet72 181,182,183,184 100000 19 9126 +Ethernet76 177,178,179,180 100000 20 9126 +Ethernet80 169,170,171,172 100000 21 9126 +Ethernet84 173,174,175,176 100000 22 9126 +Ethernet88 165,166,167,168 100000 23 9126 +Ethernet92 161,162,163,164 100000 24 9126 +Ethernet96 153,154,155,156 100000 25 9126 +Ethernet100 157,158,159,160 100000 26 9126 +Ethernet104 149,150,151,152 100000 27 9126 +Ethernet108 145,146,147,148 100000 28 9126 +Ethernet112 137,138,139,140 100000 29 9126 +Ethernet116 141,142,143,144 100000 30 9126 +Ethernet120 133,134,135,136 100000 31 9126 +Ethernet124 129,130,131,132 100000 32 9126 +Ethernet128 121,122,123,124 100000 33 9126 +Ethernet132 125,126,127,128 100000 34 9126 +Ethernet136 117,118,119,120 100000 35 9126 +Ethernet140 113,114,115,116 100000 36 9126 +Ethernet144 105,106,107,108 100000 37 9126 +Ethernet148 109,110,111,112 100000 38 9126 +Ethernet152 101,102,103,104 100000 39 9126 +Ethernet156 97,98,99,100 100000 40 9126 +Ethernet160 89,90,91,92 100000 41 9126 +Ethernet164 93,94,95,96 100000 42 9126 +Ethernet168 85,86,87,88 100000 43 9126 +Ethernet172 81,82,83,84 100000 44 9126 +Ethernet176 73,74,75,76 100000 45 9126 +Ethernet180 77,78,79,80 100000 46 9126 +Ethernet184 69,70,71,72 100000 47 9126 +Ethernet188 65,66,67,68 100000 48 9126 +Ethernet192 57,58,59,60 100000 49 9126 +Ethernet196 61,62,63,64 100000 50 9126 +Ethernet200 53,54,55,56 100000 51 9126 +Ethernet204 49,50,51,52 100000 52 9126 +Ethernet208 41,42,43,44 100000 53 9126 +Ethernet212 45,46,47,48 100000 54 9126 +Ethernet216 37,38,39,40 100000 55 9126 +Ethernet220 33,34,35,36 100000 56 9126 +Ethernet224 25,26,27,28 100000 57 9126 +Ethernet228 29,30,31,32 100000 58 9126 +Ethernet232 21,22,23,24 100000 59 9126 +Ethernet236 17,18,19,20 100000 60 9126 +Ethernet240 9,10,11,12 100000 61 9126 +Ethernet244 13,14,15,16 100000 62 9126 +Ethernet248 5,6,7,8 100000 63 9126 +Ethernet252 1,2,3,4 100000 64 9126 diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/qos.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/qos.json.j2 new file mode 100755 index 000000000000..16f9b42a2166 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 64 -%} +{# 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*4)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/sai.profile b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/buffers.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/buffers.json.j2 new file mode 100644 index 000000000000..9529fbf52fb5 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 128 -%} + +{# 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*2)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/config_128x100G_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/config_128x100G_midstone200i.yaml new file mode 100644 index 000000000000..342d223a96e1 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/config_128x100G_midstone200i.yaml @@ -0,0 +1,1100 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_B" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KPFEC" + id: "249" + lanes: "0:2" + serdes_group: "31" + speed: "100G" + sysport: "249" + type: "eth" + - fec: "KPFEC" + id: "251" + lanes: "2:2" + serdes_group: "31" + speed: "100G" + sysport: "251" + type: "eth" + - fec: "KPFEC" + id: "253" + lanes: "4:2" + serdes_group: "31" + speed: "100G" + sysport: "253" + type: "eth" + - fec: "KPFEC" + id: "255" + lanes: "6:2" + serdes_group: "31" + speed: "100G" + sysport: "255" + type: "eth" + - fec: "KPFEC" + id: "245" + lanes: "4:2" + serdes_group: "30" + speed: "100G" + sysport: "245" + type: "eth" + - fec: "KPFEC" + id: "247" + lanes: "6:2" + serdes_group: "30" + speed: "100G" + sysport: "247" + type: "eth" + - fec: "KPFEC" + id: "241" + lanes: "0:2" + serdes_group: "30" + speed: "100G" + sysport: "241" + type: "eth" + - fec: "KPFEC" + id: "243" + lanes: "2:2" + serdes_group: "30" + speed: "100G" + sysport: "243" + type: "eth" + - fec: "KPFEC" + id: "233" + lanes: "0:2" + serdes_group: "29" + speed: "100G" + sysport: "233" + type: "eth" + - fec: "KPFEC" + id: "235" + lanes: "2:2" + serdes_group: "29" + speed: "100G" + sysport: "235" + type: "eth" + - fec: "KPFEC" + id: "237" + lanes: "4:2" + serdes_group: "29" + speed: "100G" + sysport: "237" + type: "eth" + - fec: "KPFEC" + id: "239" + lanes: "6:2" + serdes_group: "29" + speed: "100G" + sysport: "239" + type: "eth" + - fec: "KPFEC" + id: "229" + lanes: "4:2" + serdes_group: "28" + speed: "100G" + sysport: "229" + type: "eth" + - fec: "KPFEC" + id: "231" + lanes: "6:2" + serdes_group: "28" + speed: "100G" + sysport: "231" + type: "eth" + - fec: "KPFEC" + id: "225" + lanes: "0:2" + serdes_group: "28" + speed: "100G" + sysport: "225" + type: "eth" + - fec: "KPFEC" + id: "227" + lanes: "2:2" + serdes_group: "28" + speed: "100G" + sysport: "227" + type: "eth" + - fec: "KPFEC" + id: "217" + lanes: "0:2" + serdes_group: "27" + speed: "100G" + sysport: "217" + type: "eth" + - fec: "KPFEC" + id: "219" + lanes: "2:2" + serdes_group: "27" + speed: "100G" + sysport: "219" + type: "eth" + - fec: "KPFEC" + id: "221" + lanes: "4:2" + serdes_group: "27" + speed: "100G" + sysport: "221" + type: "eth" + - fec: "KPFEC" + id: "223" + lanes: "6:2" + serdes_group: "27" + speed: "100G" + sysport: "223" + type: "eth" + - fec: "KPFEC" + id: "213" + lanes: "4:2" + serdes_group: "26" + speed: "100G" + sysport: "213" + type: "eth" + - fec: "KPFEC" + id: "215" + lanes: "6:2" + serdes_group: "26" + speed: "100G" + sysport: "215" + type: "eth" + - fec: "KPFEC" + id: "209" + lanes: "0:2" + serdes_group: "26" + speed: "100G" + sysport: "209" + type: "eth" + - fec: "KPFEC" + id: "211" + lanes: "2:2" + serdes_group: "26" + speed: "100G" + sysport: "211" + type: "eth" + - fec: "KPFEC" + id: "201" + lanes: "0:2" + serdes_group: "25" + speed: "100G" + sysport: "201" + type: "eth" + - fec: "KPFEC" + id: "203" + lanes: "2:2" + serdes_group: "25" + speed: "100G" + sysport: "203" + type: "eth" + - fec: "KPFEC" + id: "205" + lanes: "4:2" + serdes_group: "25" + speed: "100G" + sysport: "205" + type: "eth" + - fec: "KPFEC" + id: "207" + lanes: "6:2" + serdes_group: "25" + speed: "100G" + sysport: "207" + type: "eth" + - fec: "KPFEC" + id: "197" + lanes: "4:2" + serdes_group: "24" + speed: "100G" + sysport: "197" + type: "eth" + - fec: "KPFEC" + id: "199" + lanes: "6:2" + serdes_group: "24" + speed: "100G" + sysport: "199" + type: "eth" + - fec: "KPFEC" + id: "193" + lanes: "0:2" + serdes_group: "24" + speed: "100G" + sysport: "193" + type: "eth" + - fec: "KPFEC" + id: "195" + lanes: "2:2" + serdes_group: "24" + speed: "100G" + sysport: "195" + type: "eth" + - fec: "KPFEC" + id: "185" + lanes: "0:2" + serdes_group: "23" + speed: "100G" + sysport: "185" + type: "eth" + - fec: "KPFEC" + id: "187" + lanes: "2:2" + serdes_group: "23" + speed: "100G" + sysport: "187" + type: "eth" + - fec: "KPFEC" + id: "189" + lanes: "4:2" + serdes_group: "23" + speed: "100G" + sysport: "189" + type: "eth" + - fec: "KPFEC" + id: "191" + lanes: "6:2" + serdes_group: "23" + speed: "100G" + sysport: "191" + type: "eth" + - fec: "KPFEC" + id: "181" + lanes: "4:2" + serdes_group: "22" + speed: "100G" + sysport: "181" + type: "eth" + - fec: "KPFEC" + id: "183" + lanes: "6:2" + serdes_group: "22" + speed: "100G" + sysport: "183" + type: "eth" + - fec: "KPFEC" + id: "177" + lanes: "0:2" + serdes_group: "22" + speed: "100G" + sysport: "177" + type: "eth" + - fec: "KPFEC" + id: "179" + lanes: "2:2" + serdes_group: "22" + speed: "100G" + sysport: "179" + type: "eth" + - fec: "KPFEC" + id: "169" + lanes: "0:2" + serdes_group: "21" + speed: "100G" + sysport: "169" + type: "eth" + - fec: "KPFEC" + id: "171" + lanes: "2:2" + serdes_group: "21" + speed: "100G" + sysport: "171" + type: "eth" + - fec: "KPFEC" + id: "173" + lanes: "4:2" + serdes_group: "21" + speed: "100G" + sysport: "173" + type: "eth" + - fec: "KPFEC" + id: "175" + lanes: "6:2" + serdes_group: "21" + speed: "100G" + sysport: "175" + type: "eth" + - fec: "KPFEC" + id: "165" + lanes: "4:2" + serdes_group: "20" + speed: "100G" + sysport: "165" + type: "eth" + - fec: "KPFEC" + id: "167" + lanes: "6:2" + serdes_group: "20" + speed: "100G" + sysport: "167" + type: "eth" + - fec: "KPFEC" + id: "161" + lanes: "0:2" + serdes_group: "20" + speed: "100G" + sysport: "161" + type: "eth" + - fec: "KPFEC" + id: "163" + lanes: "2:2" + serdes_group: "20" + speed: "100G" + sysport: "163" + type: "eth" + - fec: "KPFEC" + id: "153" + lanes: "0:2" + serdes_group: "19" + speed: "100G" + sysport: "153" + type: "eth" + - fec: "KPFEC" + id: "155" + lanes: "2:2" + serdes_group: "19" + speed: "100G" + sysport: "155" + type: "eth" + - fec: "KPFEC" + id: "157" + lanes: "4:2" + serdes_group: "19" + speed: "100G" + sysport: "157" + type: "eth" + - fec: "KPFEC" + id: "159" + lanes: "6:2" + serdes_group: "19" + speed: "100G" + sysport: "159" + type: "eth" + - fec: "KPFEC" + id: "149" + lanes: "4:2" + serdes_group: "18" + speed: "100G" + sysport: "149" + type: "eth" + - fec: "KPFEC" + id: "151" + lanes: "6:2" + serdes_group: "18" + speed: "100G" + sysport: "151" + type: "eth" + - fec: "KPFEC" + id: "145" + lanes: "0:2" + serdes_group: "18" + speed: "100G" + sysport: "145" + type: "eth" + - fec: "KPFEC" + id: "147" + lanes: "2:2" + serdes_group: "18" + speed: "100G" + sysport: "147" + type: "eth" + - fec: "KPFEC" + id: "137" + lanes: "0:2" + serdes_group: "17" + speed: "100G" + sysport: "137" + type: "eth" + - fec: "KPFEC" + id: "139" + lanes: "2:2" + serdes_group: "17" + speed: "100G" + sysport: "139" + type: "eth" + - fec: "KPFEC" + id: "141" + lanes: "4:2" + serdes_group: "17" + speed: "100G" + sysport: "141" + type: "eth" + - fec: "KPFEC" + id: "143" + lanes: "6:2" + serdes_group: "17" + speed: "100G" + sysport: "143" + type: "eth" + - fec: "KPFEC" + id: "133" + lanes: "4:2" + serdes_group: "16" + speed: "100G" + sysport: "133" + type: "eth" + - fec: "KPFEC" + id: "135" + lanes: "6:2" + serdes_group: "16" + speed: "100G" + sysport: "135" + type: "eth" + - fec: "KPFEC" + id: "129" + lanes: "0:2" + serdes_group: "16" + speed: "100G" + sysport: "129" + type: "eth" + - fec: "KPFEC" + id: "131" + lanes: "2:2" + serdes_group: "16" + speed: "100G" + sysport: "131" + type: "eth" + - fec: "KPFEC" + id: "121" + lanes: "0:2" + serdes_group: "15" + speed: "100G" + sysport: "121" + type: "eth" + - fec: "KPFEC" + id: "123" + lanes: "2:2" + serdes_group: "15" + speed: "100G" + sysport: "123" + type: "eth" + - fec: "KPFEC" + id: "125" + lanes: "4:2" + serdes_group: "15" + speed: "100G" + sysport: "125" + type: "eth" + - fec: "KPFEC" + id: "127" + lanes: "6:2" + serdes_group: "15" + speed: "100G" + sysport: "127" + type: "eth" + - fec: "KPFEC" + id: "117" + lanes: "4:2" + serdes_group: "14" + speed: "100G" + sysport: "117" + type: "eth" + - fec: "KPFEC" + id: "119" + lanes: "6:2" + serdes_group: "14" + speed: "100G" + sysport: "119" + type: "eth" + - fec: "KPFEC" + id: "113" + lanes: "0:2" + serdes_group: "14" + speed: "100G" + sysport: "113" + type: "eth" + - fec: "KPFEC" + id: "115" + lanes: "2:2" + serdes_group: "14" + speed: "100G" + sysport: "115" + type: "eth" + - fec: "KPFEC" + id: "105" + lanes: "0:2" + serdes_group: "13" + speed: "100G" + sysport: "105" + type: "eth" + - fec: "KPFEC" + id: "107" + lanes: "2:2" + serdes_group: "13" + speed: "100G" + sysport: "107" + type: "eth" + - fec: "KPFEC" + id: "109" + lanes: "4:2" + serdes_group: "13" + speed: "100G" + sysport: "109" + type: "eth" + - fec: "KPFEC" + id: "111" + lanes: "6:2" + serdes_group: "13" + speed: "100G" + sysport: "111" + type: "eth" + - fec: "KPFEC" + id: "101" + lanes: "4:2" + serdes_group: "12" + speed: "100G" + sysport: "101" + type: "eth" + - fec: "KPFEC" + id: "103" + lanes: "6:2" + serdes_group: "12" + speed: "100G" + sysport: "103" + type: "eth" + - fec: "KPFEC" + id: "97" + lanes: "0:2" + serdes_group: "12" + speed: "100G" + sysport: "97" + type: "eth" + - fec: "KPFEC" + id: "99" + lanes: "2:2" + serdes_group: "12" + speed: "100G" + sysport: "99" + type: "eth" + - fec: "KPFEC" + id: "89" + lanes: "0:2" + serdes_group: "11" + speed: "100G" + sysport: "89" + type: "eth" + - fec: "KPFEC" + id: "91" + lanes: "2:2" + serdes_group: "11" + speed: "100G" + sysport: "91" + type: "eth" + - fec: "KPFEC" + id: "93" + lanes: "4:2" + serdes_group: "11" + speed: "100G" + sysport: "93" + type: "eth" + - fec: "KPFEC" + id: "95" + lanes: "6:2" + serdes_group: "11" + speed: "100G" + sysport: "95" + type: "eth" + - fec: "KPFEC" + id: "85" + lanes: "4:2" + serdes_group: "10" + speed: "100G" + sysport: "85" + type: "eth" + - fec: "KPFEC" + id: "87" + lanes: "6:2" + serdes_group: "10" + speed: "100G" + sysport: "87" + type: "eth" + - fec: "KPFEC" + id: "87" + lanes: "0:2" + serdes_group: "10" + speed: "100G" + sysport: "87" + type: "eth" + - fec: "KPFEC" + id: "83" + lanes: "2:2" + serdes_group: "10" + speed: "100G" + sysport: "83" + type: "eth" + - fec: "KPFEC" + id: "89" + lanes: "0:2" + serdes_group: "9" + speed: "100G" + sysport: "89" + type: "eth" + - fec: "KPFEC" + id: "75" + lanes: "2:2" + serdes_group: "9" + speed: "100G" + sysport: "75" + type: "eth" + - fec: "KPFEC" + id: "91" + lanes: "4:2" + serdes_group: "9" + speed: "100G" + sysport: "91" + type: "eth" + - fec: "KPFEC" + id: "79" + lanes: "6:2" + serdes_group: "9" + speed: "100G" + sysport: "79" + type: "eth" + - fec: "KPFEC" + id: "93" + lanes: "4:2" + serdes_group: "8" + speed: "100G" + sysport: "93" + type: "eth" + - fec: "KPFEC" + id: "71" + lanes: "6:2" + serdes_group: "8" + speed: "100G" + sysport: "71" + type: "eth" + - fec: "KPFEC" + id: "95" + lanes: "0:2" + serdes_group: "8" + speed: "100G" + sysport: "95" + type: "eth" + - fec: "KPFEC" + id: "67" + lanes: "2:2" + serdes_group: "8" + speed: "100G" + sysport: "67" + type: "eth" + - fec: "KPFEC" + id: "97" + lanes: "0:2" + serdes_group: "7" + speed: "100G" + sysport: "97" + type: "eth" + - fec: "KPFEC" + id: "59" + lanes: "2:2" + serdes_group: "7" + speed: "100G" + sysport: "59" + type: "eth" + - fec: "KPFEC" + id: "99" + lanes: "4:2" + serdes_group: "7" + speed: "100G" + sysport: "99" + type: "eth" + - fec: "KPFEC" + id: "63" + lanes: "6:2" + serdes_group: "7" + speed: "100G" + sysport: "63" + type: "eth" + - fec: "KPFEC" + id: "101" + lanes: "4:2" + serdes_group: "6" + speed: "100G" + sysport: "101" + type: "eth" + - fec: "KPFEC" + id: "55" + lanes: "6:2" + serdes_group: "6" + speed: "100G" + sysport: "55" + type: "eth" + - fec: "KPFEC" + id: "103" + lanes: "0:2" + serdes_group: "6" + speed: "100G" + sysport: "103" + type: "eth" + - fec: "KPFEC" + id: "51" + lanes: "2:2" + serdes_group: "6" + speed: "100G" + sysport: "51" + type: "eth" + - fec: "KPFEC" + id: "105" + lanes: "0:2" + serdes_group: "5" + speed: "100G" + sysport: "105" + type: "eth" + - fec: "KPFEC" + id: "43" + lanes: "2:2" + serdes_group: "5" + speed: "100G" + sysport: "43" + type: "eth" + - fec: "KPFEC" + id: "107" + lanes: "4:2" + serdes_group: "5" + speed: "100G" + sysport: "107" + type: "eth" + - fec: "KPFEC" + id: "47" + lanes: "6:2" + serdes_group: "5" + speed: "100G" + sysport: "47" + type: "eth" + - fec: "KPFEC" + id: "109" + lanes: "4:2" + serdes_group: "4" + speed: "100G" + sysport: "109" + type: "eth" + - fec: "KPFEC" + id: "39" + lanes: "6:2" + serdes_group: "4" + speed: "100G" + sysport: "39" + type: "eth" + - fec: "KPFEC" + id: "111" + lanes: "0:2" + serdes_group: "4" + speed: "100G" + sysport: "111" + type: "eth" + - fec: "KPFEC" + id: "35" + lanes: "2:2" + serdes_group: "4" + speed: "100G" + sysport: "35" + type: "eth" + - fec: "KPFEC" + id: "113" + lanes: "0:2" + serdes_group: "3" + speed: "100G" + sysport: "113" + type: "eth" + - fec: "KPFEC" + id: "27" + lanes: "2:2" + serdes_group: "3" + speed: "100G" + sysport: "27" + type: "eth" + - fec: "KPFEC" + id: "115" + lanes: "4:2" + serdes_group: "3" + speed: "100G" + sysport: "115" + type: "eth" + - fec: "KPFEC" + id: "31" + lanes: "6:2" + serdes_group: "3" + speed: "100G" + sysport: "31" + type: "eth" + - fec: "KPFEC" + id: "117" + lanes: "4:2" + serdes_group: "2" + speed: "100G" + sysport: "117" + type: "eth" + - fec: "KPFEC" + id: "23" + lanes: "6:2" + serdes_group: "2" + speed: "100G" + sysport: "23" + type: "eth" + - fec: "KPFEC" + id: "119" + lanes: "0:2" + serdes_group: "2" + speed: "100G" + sysport: "119" + type: "eth" + - fec: "KPFEC" + id: "19" + lanes: "2:2" + serdes_group: "2" + speed: "100G" + sysport: "19" + type: "eth" + - fec: "KPFEC" + id: "121" + lanes: "0:2" + serdes_group: "1" + speed: "100G" + sysport: "121" + type: "eth" + - fec: "KPFEC" + id: "11" + lanes: "2:2" + serdes_group: "1" + speed: "100G" + sysport: "11" + type: "eth" + - fec: "KPFEC" + id: "123" + lanes: "4:2" + serdes_group: "1" + speed: "100G" + sysport: "123" + type: "eth" + - fec: "KPFEC" + id: "15" + lanes: "6:2" + serdes_group: "1" + speed: "100G" + sysport: "15" + type: "eth" + - fec: "KPFEC" + id: "125" + lanes: "4:2" + serdes_group: "0" + speed: "100G" + sysport: "125" + type: "eth" + - fec: "KPFEC" + id: "7" + lanes: "6:2" + serdes_group: "0" + speed: "100G" + sysport: "7" + type: "eth" + - fec: "KPFEC" + id: "127" + lanes: "0:2" + serdes_group: "0" + speed: "100G" + sysport: "127" + type: "eth" + - fec: "KPFEC" + id: "3" + lanes: "2:2" + serdes_group: "0" + speed: "100G" + sysport: "3" + type: "eth" + - fec: "NONE" + id: "257" + lanes: "0:1" + serdes_group: "32" + speed: "10G" + sysport: "257" + type: "mgmt 0" + - fec: "NONE" + id: "258" + lanes: "1:1" + serdes_group: "32" + speed: "10G" + sysport: "258" + type: "mgmt 1" + isg: + - id: "0" + lane_swap: "01234567" + rx_polarity: "01110001" + tx_polarity: "00101001" + - id: "1" + lane_swap: "01234567" + rx_polarity: "11100100" + tx_polarity: "10111111" + - id: "2" + lane_swap: "01234567" + rx_polarity: "00010001" + tx_polarity: "00100010" + - id: "3" + lane_swap: "01234567" + rx_polarity: "11011101" + tx_polarity: "00101010" + - id: "4" + lane_swap: "01234567" + rx_polarity: "10010101" + tx_polarity: "10111110" + - id: "5" + lane_swap: "01234567" + rx_polarity: "10111001" + tx_polarity: "01101000" + - id: "6" + lane_swap: "01234567" + rx_polarity: "01110011" + tx_polarity: "01110110" + - id: "7" + lane_swap: "01234567" + rx_polarity: "10111001" + tx_polarity: "01001000" + - id: "8" + lane_swap: "01234567" + rx_polarity: "01000000" + tx_polarity: "11000100" + - id: "9" + lane_swap: "01234567" + rx_polarity: "10100100" + tx_polarity: "10001010" + - id: "10" + lane_swap: "01234567" + rx_polarity: "00011101" + tx_polarity: "11000110" + - id: "11" + lane_swap: "01234567" + rx_polarity: "00000101" + tx_polarity: "01000111" + - id: "12" + lane_swap: "01234567" + rx_polarity: "11100000" + tx_polarity: "01111000" + - id: "13" + lane_swap: "01234567" + rx_polarity: "00101111" + tx_polarity: "10011111" + - id: "14" + lane_swap: "01234567" + rx_polarity: "00011000" + tx_polarity: "00101001" + - id: "15" + lane_swap: "01234567" + rx_polarity: "00110110" + tx_polarity: "10110111" + - id: "16" + lane_swap: "01234567" + rx_polarity: "00000111" + tx_polarity: "00101001" + - id: "17" + lane_swap: "01234567" + rx_polarity: "10001000" + tx_polarity: "10100111" + - id: "18" + lane_swap: "01234567" + rx_polarity: "11111110" + tx_polarity: "00011001" + - id: "19" + lane_swap: "01234567" + rx_polarity: "10011010" + tx_polarity: "10010101" + - id: "20" + lane_swap: "01234567" + rx_polarity: "01100000" + tx_polarity: "00101001" + - id: "21" + lane_swap: "01234567" + rx_polarity: "01111001" + tx_polarity: "10010111" + - id: "22" + lane_swap: "01234567" + rx_polarity: "11010011" + tx_polarity: "00101001" + - id: "23" + lane_swap: "01234567" + rx_polarity: "01111011" + tx_polarity: "10110111" + - id: "24" + lane_swap: "01234567" + rx_polarity: "11101011" + tx_polarity: "00101001" + - id: "25" + lane_swap: "01234567" + rx_polarity: "11010111" + tx_polarity: "10110111" + - id: "26" + lane_swap: "01234567" + rx_polarity: "00101101" + tx_polarity: "00100001" + - id: "27" + lane_swap: "01234567" + rx_polarity: "11011001" + tx_polarity: "11000111" + - id: "28" + lane_swap: "01234567" + rx_polarity: "01010011" + tx_polarity: "00100001" + - id: "29" + lane_swap: "01234567" + rx_polarity: "01111001" + tx_polarity: "10110111" + - id: "30" + lane_swap: "01234567" + rx_polarity: "00110001" + tx_polarity: "00101001" + - id: "31" + lane_swap: "01234567" + rx_polarity: "01101101" + tx_polarity: "10110101" + - id: "32" + lane_swap: "01234567" + rx_polarity: "00000000" + tx_polarity: "00000000" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/inno.config.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/inno.config.yaml new file mode 100755 index 000000000000..66e43d312efb --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_128x100G_midstone200i.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/innovium.77700_B b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/port_config.ini b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/port_config.ini new file mode 100644 index 000000000000..9366905c4eba --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/port_config.ini @@ -0,0 +1,131 @@ +# name lanes speed index mtu +Ethernet0 249,250 100000 0 9126 +Ethernet2 251,252 100000 0 9126 +Ethernet4 253,254 100000 1 9126 +Ethernet6 255,256 100000 1 9126 +Ethernet8 245,246 100000 2 9126 +Ethernet10 247,248 100000 2 9126 +Ethernet12 241,242 100000 3 9126 +Ethernet14 243,244 100000 3 9126 +Ethernet16 233,234 100000 4 9126 +Ethernet18 235,236 100000 4 9126 +Ethernet20 237,238 100000 5 9126 +Ethernet22 239,240 100000 5 9126 +Ethernet24 229,230 100000 6 9126 +Ethernet26 231,232 100000 6 9126 +Ethernet28 225,226 100000 7 9126 +Ethernet30 227,228 100000 7 9126 +Ethernet32 217,218 100000 8 9126 +Ethernet34 219,220 100000 8 9126 +Ethernet36 221,222 100000 9 9126 +Ethernet38 223,224 100000 9 9126 +Ethernet40 213,214 100000 10 9126 +Ethernet42 215,216 100000 10 9126 +Ethernet44 209,210 100000 11 9126 +Ethernet46 211,212 100000 11 9126 +Ethernet48 201,202 100000 12 9126 +Ethernet50 203,204 100000 12 9126 +Ethernet52 205,206 100000 13 9126 +Ethernet54 207,208 100000 13 9126 +Ethernet56 197,198 100000 14 9126 +Ethernet58 199,200 100000 14 9126 +Ethernet60 193,194 100000 15 9126 +Ethernet62 195,196 100000 15 9126 +Ethernet64 185,186 100000 16 9126 +Ethernet66 187,188 100000 16 9126 +Ethernet68 189,190 100000 17 9126 +Ethernet70 191,192 100000 17 9126 +Ethernet72 181,182 100000 18 9126 +Ethernet74 183,184 100000 18 9126 +Ethernet76 177,178 100000 19 9126 +Ethernet78 179,180 100000 19 9126 +Ethernet80 169,170 100000 20 9126 +Ethernet82 171,172 100000 20 9126 +Ethernet84 173,174 100000 21 9126 +Ethernet86 175,176 100000 21 9126 +Ethernet88 165,166 100000 22 9126 +Ethernet90 167,168 100000 22 9126 +Ethernet92 161,162 100000 23 9126 +Ethernet94 163,164 100000 23 9126 +Ethernet96 153,154 100000 24 9126 +Ethernet98 155,156 100000 24 9126 +Ethernet100 157,158 100000 25 9126 +Ethernet102 159,160 100000 25 9126 +Ethernet104 149,150 100000 26 9126 +Ethernet106 151,152 100000 26 9126 +Ethernet108 145,146 100000 27 9126 +Ethernet110 147,148 100000 27 9126 +Ethernet112 137,138 100000 28 9126 +Ethernet114 139,140 100000 28 9126 +Ethernet116 141,142 100000 29 9126 +Ethernet118 143,144 100000 29 9126 +Ethernet120 133,134 100000 30 9126 +Ethernet122 135,136 100000 30 9126 +Ethernet124 129,130 100000 31 9126 +Ethernet126 131,132 100000 31 9126 +Ethernet128 121,122 100000 32 9126 +Ethernet130 123,124 100000 32 9126 +Ethernet132 125,126 100000 33 9126 +Ethernet134 127,128 100000 33 9126 +Ethernet136 117,118 100000 34 9126 +Ethernet138 119,120 100000 34 9126 +Ethernet140 113,114 100000 35 9126 +Ethernet142 115,116 100000 35 9126 +Ethernet144 105,106 100000 36 9126 +Ethernet146 107,108 100000 36 9126 +Ethernet148 109,110 100000 37 9126 +Ethernet150 111,112 100000 37 9126 +Ethernet152 101,102 100000 38 9126 +Ethernet154 103,104 100000 38 9126 +Ethernet156 97,98 100000 39 9126 +Ethernet158 99,100 100000 39 9126 +Ethernet160 89,90 100000 40 9126 +Ethernet162 91,92 100000 40 9126 +Ethernet164 93,94 100000 41 9126 +Ethernet166 95,96 100000 41 9126 +Ethernet168 85,86 100000 42 9126 +Ethernet170 87,88 100000 42 9126 +Ethernet172 81,82 100000 43 9126 +Ethernet174 83,84 100000 43 9126 +Ethernet176 73,74 100000 44 9126 +Ethernet178 75,76 100000 44 9126 +Ethernet180 77,78 100000 45 9126 +Ethernet182 79,80 100000 45 9126 +Ethernet184 69,70 100000 46 9126 +Ethernet186 71,72 100000 46 9126 +Ethernet188 65,66 100000 47 9126 +Ethernet190 67,68 100000 47 9126 +Ethernet192 57,58 100000 48 9126 +Ethernet194 59,60 100000 48 9126 +Ethernet196 61,62 100000 49 9126 +Ethernet198 63,64 100000 49 9126 +Ethernet200 53,54 100000 50 9126 +Ethernet202 55,56 100000 50 9126 +Ethernet204 49,50 100000 51 9126 +Ethernet206 51,52 100000 51 9126 +Ethernet208 41,42 100000 52 9126 +Ethernet210 43,44 100000 52 9126 +Ethernet212 45,46 100000 53 9126 +Ethernet214 47,48 100000 53 9126 +Ethernet216 37,38 100000 54 9126 +Ethernet218 39,40 100000 54 9126 +Ethernet220 33,34 100000 55 9126 +Ethernet222 35,36 100000 55 9126 +Ethernet224 25,26 100000 56 9126 +Ethernet226 27,28 100000 56 9126 +Ethernet228 29,30 100000 57 9126 +Ethernet230 31,32 100000 57 9126 +Ethernet232 21,22 100000 58 9126 +Ethernet234 23,24 100000 58 9126 +Ethernet236 17,18 100000 59 9126 +Ethernet238 19,20 100000 59 9126 +Ethernet240 9,10 100000 60 9126 +Ethernet242 11,12 100000 60 9126 +Ethernet244 13,14 100000 61 9126 +Ethernet246 15,16 100000 61 9126 +Ethernet248 5,6 100000 62 9126 +Ethernet250 7,8 100000 62 9126 +Ethernet252 1,2 100000 63 9126 +Ethernet254 3,4 100000 63 9126 +Ethernet256 257 10000 64 9126 +Ethernet257 258 10000 65 9126 diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/qos.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/qos.json.j2 new file mode 100755 index 000000000000..733bd51dc86f --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 128 -%} +{# 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*2)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/sai.profile b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_128x100/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/buffers.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/buffers.json.j2 new file mode 100644 index 000000000000..4fca9cbcd156 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 32 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/config_32x400G_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/config_32x400G_midstone200i.yaml new file mode 100644 index 000000000000..6c387ee17c23 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/config_32x400G_midstone200i.yaml @@ -0,0 +1,429 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_A" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "257" + type: "cpu" + - fec: "KPFEC" + id: "249" + lanes: "0:8" + serdes_group: "31" + speed: "400G" + sysport: "249" + type: "eth" + - fec: "KPFEC" + id: "241" + lanes: "0:8" + serdes_group: "30" + speed: "400G" + sysport: "241" + type: "eth" + - fec: "KPFEC" + id: "233" + lanes: "0:8" + serdes_group: "29" + speed: "400G" + sysport: "233" + type: "eth" + - fec: "KPFEC" + id: "225" + lanes: "0:8" + serdes_group: "28" + speed: "400G" + sysport: "225" + type: "eth" + - fec: "KPFEC" + id: "217" + lanes: "0:8" + serdes_group: "27" + speed: "400G" + sysport: "217" + type: "eth" + - fec: "KPFEC" + id: "209" + lanes: "0:8" + serdes_group: "26" + speed: "400G" + sysport: "209" + type: "eth" + - fec: "KPFEC" + id: "201" + lanes: "0:8" + serdes_group: "25" + speed: "400G" + sysport: "201" + type: "eth" + - fec: "KPFEC" + id: "193" + lanes: "0:8" + serdes_group: "24" + speed: "400G" + sysport: "193" + type: "eth" + - fec: "KPFEC" + id: "185" + lanes: "0:8" + serdes_group: "23" + speed: "400G" + sysport: "185" + type: "eth" + - fec: "KPFEC" + id: "177" + lanes: "0:8" + serdes_group: "22" + speed: "400G" + sysport: "177" + type: "eth" + - fec: "KPFEC" + id: "169" + lanes: "0:8" + serdes_group: "21" + speed: "400G" + sysport: "169" + type: "eth" + - fec: "KPFEC" + id: "161" + lanes: "0:8" + serdes_group: "20" + speed: "400G" + sysport: "161" + type: "eth" + - fec: "KPFEC" + id: "153" + lanes: "0:8" + serdes_group: "19" + speed: "400G" + sysport: "153" + type: "eth" + - fec: "KPFEC" + id: "145" + lanes: "0:8" + serdes_group: "18" + speed: "400G" + sysport: "145" + type: "eth" + - fec: "KPFEC" + id: "137" + lanes: "0:8" + serdes_group: "17" + speed: "400G" + sysport: "137" + type: "eth" + - fec: "KPFEC" + id: "129" + lanes: "0:8" + serdes_group: "16" + speed: "400G" + sysport: "129" + type: "eth" + - fec: "KPFEC" + id: "121" + lanes: "0:8" + serdes_group: "15" + speed: "400G" + sysport: "121" + type: "eth" + - fec: "KPFEC" + id: "113" + lanes: "0:8" + serdes_group: "14" + speed: "400G" + sysport: "113" + type: "eth" + - fec: "KPFEC" + id: "105" + lanes: "0:8" + serdes_group: "13" + speed: "400G" + sysport: "105" + type: "eth" + - fec: "KPFEC" + id: "97" + lanes: "0:8" + serdes_group: "12" + speed: "400G" + sysport: "97" + type: "eth" + - fec: "KPFEC" + id: "89" + lanes: "0:8" + serdes_group: "11" + speed: "400G" + sysport: "89" + type: "eth" + - fec: "KPFEC" + id: "81" + lanes: "0:8" + serdes_group: "10" + speed: "400G" + sysport: "81" + type: "eth" + - fec: "KPFEC" + id: "73" + lanes: "0:8" + serdes_group: "9" + speed: "400G" + sysport: "73" + type: "eth" + - fec: "KPFEC" + id: "65" + lanes: "0:8" + serdes_group: "8" + speed: "400G" + sysport: "65" + type: "eth" + - fec: "KPFEC" + id: "57" + lanes: "0:8" + serdes_group: "7" + speed: "400G" + sysport: "57" + type: "eth" + - fec: "KPFEC" + id: "49" + lanes: "0:8" + serdes_group: "6" + speed: "400G" + sysport: "49" + type: "eth" + - fec: "KPFEC" + id: "41" + lanes: "0:8" + serdes_group: "5" + speed: "400G" + sysport: "41" + type: "eth" + - fec: "KPFEC" + id: "33" + lanes: "0:8" + serdes_group: "4" + speed: "400G" + sysport: "33" + type: "eth" + - fec: "KPFEC" + id: "25" + lanes: "0:8" + serdes_group: "3" + speed: "400G" + sysport: "25" + type: "eth" + - fec: "KPFEC" + id: "17" + lanes: "0:8" + serdes_group: "2" + speed: "400G" + sysport: "17" + type: "eth" + - fec: "KPFEC" + id: "9" + lanes: "0:8" + serdes_group: "1" + speed: "400G" + sysport: "9" + type: "eth" + - fec: "KPFEC" + id: "1" + lanes: "0:8" + serdes_group: "0" + speed: "400G" + sysport: "1" + type: "eth" + - fec: "NONE" + id: "257" + lanes: "0:1" + serdes_group: "32" + speed: "10G" + sysport: "257" + type: "mgmt 0" + - fec: "NONE" + id: "258" + lanes: "1:1" + serdes_group: "32" + speed: "10G" + sysport: "258" + type: "mgmt 1" + isg: + - id: "0" + lane_swap: "01234567" + rx_polarity: "01110001" + tx_polarity: "00101001" + - id: "1" + lane_swap: "01234567" + rx_polarity: "11100100" + tx_polarity: "10111111" + - id: "2" + lane_swap: "01234567" + rx_polarity: "00010001" + tx_polarity: "00100010" + - id: "3" + lane_swap: "01234567" + rx_polarity: "11011101" + tx_polarity: "00101010" + - id: "4" + lane_swap: "01234567" + rx_polarity: "10010101" + tx_polarity: "10111110" + - id: "5" + lane_swap: "01234567" + rx_polarity: "10111001" + tx_polarity: "01101000" + - id: "6" + lane_swap: "01234567" + rx_polarity: "01110011" + tx_polarity: "01110110" + - id: "7" + lane_swap: "01234567" + rx_polarity: "10111001" + tx_polarity: "01001000" + - id: "8" + lane_swap: "01234567" + rx_polarity: "01000000" + tx_polarity: "11000100" + - id: "9" + lane_swap: "01234567" + rx_polarity: "10100100" + tx_polarity: "10001010" + - id: "10" + lane_swap: "01234567" + rx_polarity: "00011101" + tx_polarity: "11000110" + - id: "11" + lane_swap: "01234567" + rx_polarity: "00000101" + tx_polarity: "01000111" + - id: "12" + lane_swap: "01234567" + rx_polarity: "11100000" + tx_polarity: "01111000" + - id: "13" + lane_swap: "01234567" + rx_polarity: "00101111" + tx_polarity: "10011111" + - id: "14" + lane_swap: "01234567" + rx_polarity: "00011000" + tx_polarity: "00101001" + - id: "15" + lane_swap: "01234567" + rx_polarity: "00110110" + tx_polarity: "10110111" + - id: "16" + lane_swap: "01234567" + rx_polarity: "00000111" + tx_polarity: "00101001" + - id: "17" + lane_swap: "01234567" + rx_polarity: "10001000" + tx_polarity: "10100111" + - id: "18" + lane_swap: "01234567" + rx_polarity: "11111110" + tx_polarity: "00011001" + - id: "19" + lane_swap: "01234567" + rx_polarity: "10011010" + tx_polarity: "10010101" + - id: "20" + lane_swap: "01234567" + rx_polarity: "01100000" + tx_polarity: "00101001" + - id: "21" + lane_swap: "01234567" + rx_polarity: "01111001" + tx_polarity: "10010111" + - id: "22" + lane_swap: "01234567" + rx_polarity: "11010011" + tx_polarity: "00101001" + - id: "23" + lane_swap: "01234567" + rx_polarity: "01111011" + tx_polarity: "10110111" + - id: "24" + lane_swap: "01234567" + rx_polarity: "11101011" + tx_polarity: "00101001" + - id: "25" + lane_swap: "01234567" + rx_polarity: "11010111" + tx_polarity: "10110111" + - id: "26" + lane_swap: "01234567" + rx_polarity: "00101101" + tx_polarity: "00100001" + - id: "27" + lane_swap: "01234567" + rx_polarity: "11011001" + tx_polarity: "11000111" + - id: "28" + lane_swap: "01234567" + rx_polarity: "01010011" + tx_polarity: "00100001" + - id: "29" + lane_swap: "01234567" + rx_polarity: "01111001" + tx_polarity: "10110111" + - id: "30" + lane_swap: "01234567" + rx_polarity: "00110001" + tx_polarity: "00101001" + - id: "31" + lane_swap: "01234567" + rx_polarity: "01101101" + tx_polarity: "10110101" + - id: "32" + lane_swap: "01234567" + rx_polarity: "00000000" + tx_polarity: "00000000" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/inno.config.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/inno.config.yaml new file mode 100755 index 000000000000..bf1c8f41009f --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_32x400G_midstone200i.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_A" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/innovium.77700_A b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/innovium.77700_A new file mode 100644 index 000000000000..84aa41983606 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/innovium.77700_A @@ -0,0 +1,59 @@ +sku: innovium.77700_A + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 6, 5, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 8:0 + ib: 1 + pic_id: 5 + + isg 31: + mode: 8:0 + ib: 0 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/port_config.ini b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/port_config.ini new file mode 100644 index 000000000000..c8ded273cca8 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/port_config.ini @@ -0,0 +1,35 @@ +# name lanes speed index mtu fec +Ethernet0 249,250,251,252 400000 0 9126 rs +Ethernet8 241,242,243,244 400000 2 9126 rs +Ethernet16 233,234,235,236 400000 4 9126 rs +Ethernet24 225,226,227,228 400000 6 9126 rs +Ethernet32 217,218,219,220 400000 8 9126 rs +Ethernet40 209,210,211,212 400000 10 9126 rs +Ethernet48 201,202,203,204 400000 12 9126 rs +Ethernet56 193,194,195,196 400000 14 9126 rs +Ethernet64 185,186,187,188 400000 16 9126 rs +Ethernet72 177,178,179,180 400000 18 9126 rs +Ethernet80 169,170,171,172 400000 20 9126 rs +Ethernet88 161,162,163,164 400000 22 9126 rs +Ethernet96 153,154,155,156 400000 24 9126 rs +Ethernet104 145,146,147,148 400000 26 9126 rs +Ethernet112 137,138,139,140 400000 28 9126 rs +Ethernet120 129,130,131,132 400000 30 9126 rs +Ethernet128 121,122,123,124 400000 32 9126 rs +Ethernet136 113,114,115,116 400000 34 9126 rs +Ethernet144 105,106,107,108 400000 36 9126 rs +Ethernet152 97,98,99,100 400000 38 9126 rs +Ethernet160 89,90,91,92 400000 40 9126 rs +Ethernet168 81,82,83,84 400000 42 9126 rs +Ethernet176 73,74,75,76 400000 44 9126 rs +Ethernet184 65,66,67,68 400000 46 9126 rs +Ethernet192 57,58,59,60 400000 48 9126 rs +Ethernet200 49,50,51,52 400000 50 9126 rs +Ethernet208 41,42,43,44 400000 52 9126 rs +Ethernet216 33,34,35,36 400000 54 9126 rs +Ethernet224 25,26,27,28 400000 56 9126 rs +Ethernet232 17,18,19,20 400000 58 9126 rs +Ethernet240 9,10,11,12 400000 60 9126 rs +Ethernet248 1,2,3,4 400000 62 9126 rs +Ethernet256 257 10000 64 9126 none +Ethernet257 258 10000 65 9126 none diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/qos.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/qos.json.j2 new file mode 100755 index 000000000000..6c734d46ff2f --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 32 -%} +{# 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*4)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/sai.profile b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_32x400/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/buffers.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/buffers.json.j2 new file mode 100644 index 000000000000..45cebf3b7144 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 64 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/config_64x100G_nrz_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/config_64x100G_nrz_midstone200i.yaml new file mode 100644 index 000000000000..813d012ca3d5 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/config_64x100G_nrz_midstone200i.yaml @@ -0,0 +1,785 @@ +ifcs: + options: + log_level: "off" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_B" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KRFEC" + id: "249" + lanes: "0:4" + serdes_group: "31" + speed: "100G" + sysport: "249" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "253" + lanes: "4:4" + serdes_group: "31" + speed: "100G" + sysport: "253" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "245" + lanes: "4:4" + serdes_group: "30" + speed: "100G" + sysport: "245" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "241" + lanes: "0:4" + serdes_group: "30" + speed: "100G" + sysport: "241" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "233" + lanes: "0:4" + serdes_group: "29" + speed: "100G" + sysport: "233" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "237" + lanes: "4:4" + serdes_group: "29" + speed: "100G" + sysport: "237" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "229" + lanes: "4:4" + serdes_group: "28" + speed: "100G" + sysport: "229" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "225" + lanes: "0:4" + serdes_group: "28" + speed: "100G" + sysport: "225" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "217" + lanes: "0:4" + serdes_group: "27" + speed: "100G" + sysport: "217" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "221" + lanes: "4:4" + serdes_group: "27" + speed: "100G" + sysport: "221" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "213" + lanes: "4:4" + serdes_group: "26" + speed: "100G" + sysport: "213" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "209" + lanes: "0:4" + serdes_group: "26" + speed: "100G" + sysport: "209" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "201" + lanes: "0:4" + serdes_group: "25" + speed: "100G" + sysport: "201" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "205" + lanes: "4:4" + serdes_group: "25" + speed: "100G" + sysport: "205" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "197" + lanes: "4:4" + serdes_group: "24" + speed: "100G" + sysport: "197" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "193" + lanes: "0:4" + serdes_group: "24" + speed: "100G" + sysport: "193" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "185" + lanes: "0:4" + serdes_group: "23" + speed: "100G" + sysport: "185" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "189" + lanes: "4:4" + serdes_group: "23" + speed: "100G" + sysport: "189" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "181" + lanes: "4:4" + serdes_group: "22" + speed: "100G" + sysport: "181" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "177" + lanes: "0:4" + serdes_group: "22" + speed: "100G" + sysport: "177" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "169" + lanes: "0:4" + serdes_group: "21" + speed: "100G" + sysport: "169" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "173" + lanes: "4:4" + serdes_group: "21" + speed: "100G" + sysport: "173" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "165" + lanes: "4:4" + serdes_group: "20" + speed: "100G" + sysport: "165" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "161" + lanes: "0:4" + serdes_group: "20" + speed: "100G" + sysport: "161" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "153" + lanes: "0:4" + serdes_group: "19" + speed: "100G" + sysport: "153" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "157" + lanes: "4:4" + serdes_group: "19" + speed: "100G" + sysport: "157" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "149" + lanes: "4:4" + serdes_group: "18" + speed: "100G" + sysport: "149" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "145" + lanes: "0:4" + serdes_group: "18" + speed: "100G" + sysport: "145" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "137" + lanes: "0:4" + serdes_group: "17" + speed: "100G" + sysport: "137" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "141" + lanes: "4:4" + serdes_group: "17" + speed: "100G" + sysport: "141" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "133" + lanes: "4:4" + serdes_group: "16" + speed: "100G" + sysport: "133" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "129" + lanes: "0:4" + serdes_group: "16" + speed: "100G" + sysport: "129" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "121" + lanes: "0:4" + serdes_group: "15" + speed: "100G" + sysport: "121" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "125" + lanes: "4:4" + serdes_group: "15" + speed: "100G" + sysport: "125" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "117" + lanes: "4:4" + serdes_group: "14" + speed: "100G" + sysport: "117" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "113" + lanes: "0:4" + serdes_group: "14" + speed: "100G" + sysport: "113" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "105" + lanes: "0:4" + serdes_group: "13" + speed: "100G" + sysport: "105" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "109" + lanes: "4:4" + serdes_group: "13" + speed: "100G" + sysport: "109" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "101" + lanes: "4:4" + serdes_group: "12" + speed: "100G" + sysport: "101" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "97" + lanes: "0:4" + serdes_group: "12" + speed: "100G" + sysport: "97" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "89" + lanes: "0:4" + serdes_group: "11" + speed: "100G" + sysport: "89" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "93" + lanes: "4:4" + serdes_group: "11" + speed: "100G" + sysport: "93" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "85" + lanes: "4:4" + serdes_group: "10" + speed: "100G" + sysport: "85" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "81" + lanes: "0:4" + serdes_group: "10" + speed: "100G" + sysport: "81" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "73" + lanes: "0:4" + serdes_group: "9" + speed: "100G" + sysport: "73" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "77" + lanes: "4:4" + serdes_group: "9" + speed: "100G" + sysport: "77" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "69" + lanes: "4:4" + serdes_group: "8" + speed: "100G" + sysport: "69" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "65" + lanes: "0:4" + serdes_group: "8" + speed: "100G" + sysport: "65" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "57" + lanes: "0:4" + serdes_group: "7" + speed: "100G" + sysport: "57" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "61" + lanes: "4:4" + serdes_group: "7" + speed: "100G" + sysport: "61" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "53" + lanes: "4:4" + serdes_group: "6" + speed: "100G" + sysport: "53" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "49" + lanes: "0:4" + serdes_group: "6" + speed: "100G" + sysport: "49" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "53" + lanes: "0:4" + serdes_group: "5" + speed: "100G" + sysport: "53" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "45" + lanes: "4:4" + serdes_group: "5" + speed: "100G" + sysport: "45" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "37" + lanes: "4:4" + serdes_group: "4" + speed: "100G" + sysport: "37" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "33" + lanes: "0:4" + serdes_group: "4" + speed: "100G" + sysport: "33" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "57" + lanes: "0:4" + serdes_group: "3" + speed: "100G" + sysport: "57" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "29" + lanes: "4:4" + serdes_group: "3" + speed: "100G" + sysport: "29" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "21" + lanes: "4:4" + serdes_group: "2" + speed: "100G" + sysport: "21" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "17" + lanes: "0:4" + serdes_group: "2" + speed: "100G" + sysport: "17" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "61" + lanes: "0:4" + serdes_group: "1" + speed: "100G" + sysport: "61" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "13" + lanes: "4:4" + serdes_group: "1" + speed: "100G" + sysport: "13" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "5" + lanes: "4:4" + serdes_group: "0" + speed: "100G" + sysport: "5" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "1" + lanes: "0:4" + serdes_group: "0" + speed: "100G" + sysport: "1" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "NONE" + id: "257" + lanes: "0:1" + serdes_group: "32" + speed: "10G" + sysport: "257" + type: "mgmt 0" + admin_state: "true" + loopback: "none" + - fec: "NONE" + id: "258" + lanes: "1:1" + serdes_group: "32" + speed: "10G" + sysport: "258" + type: "mgmt 1" + admin_state: "true" + loopback: "none" + isg: + - id: "0" + lane_swap: "01234567" + rx_polarity: "01110001" + tx_polarity: "00101001" + - id: "1" + lane_swap: "01234567" + rx_polarity: "11100100" + tx_polarity: "10111111" + - id: "2" + lane_swap: "01234567" + rx_polarity: "00010001" + tx_polarity: "00100010" + - id: "3" + lane_swap: "01234567" + rx_polarity: "11011101" + tx_polarity: "00101010" + - id: "4" + lane_swap: "01234567" + rx_polarity: "10010101" + tx_polarity: "10111110" + - id: "5" + lane_swap: "01234567" + rx_polarity: "10111001" + tx_polarity: "01101000" + - id: "6" + lane_swap: "01234567" + rx_polarity: "01110011" + tx_polarity: "01110110" + - id: "7" + lane_swap: "01234567" + rx_polarity: "10111001" + tx_polarity: "01001000" + - id: "8" + lane_swap: "01234567" + rx_polarity: "01000000" + tx_polarity: "11000100" + - id: "9" + lane_swap: "01234567" + rx_polarity: "10100100" + tx_polarity: "10001010" + - id: "10" + lane_swap: "01234567" + rx_polarity: "00011101" + tx_polarity: "11000110" + - id: "11" + lane_swap: "01234567" + rx_polarity: "00000101" + tx_polarity: "01000111" + - id: "12" + lane_swap: "01234567" + rx_polarity: "11100000" + tx_polarity: "01111000" + - id: "13" + lane_swap: "01234567" + rx_polarity: "00101111" + tx_polarity: "10011111" + - id: "14" + lane_swap: "01234567" + rx_polarity: "00011000" + tx_polarity: "00101001" + - id: "15" + lane_swap: "01234567" + rx_polarity: "00110110" + tx_polarity: "10110111" + - id: "16" + lane_swap: "01234567" + rx_polarity: "00000111" + tx_polarity: "00101001" + - id: "17" + lane_swap: "01234567" + rx_polarity: "10001000" + tx_polarity: "10100111" + - id: "18" + lane_swap: "01234567" + rx_polarity: "11111110" + tx_polarity: "00011001" + - id: "19" + lane_swap: "01234567" + rx_polarity: "10011010" + tx_polarity: "10010101" + - id: "20" + lane_swap: "01234567" + rx_polarity: "01100000" + tx_polarity: "00101001" + - id: "21" + lane_swap: "01234567" + rx_polarity: "01111001" + tx_polarity: "10010111" + - id: "22" + lane_swap: "01234567" + rx_polarity: "11010011" + tx_polarity: "00101001" + - id: "23" + lane_swap: "01234567" + rx_polarity: "01111011" + tx_polarity: "10110111" + - id: "24" + lane_swap: "01234567" + rx_polarity: "11101011" + tx_polarity: "00101001" + - id: "25" + lane_swap: "01234567" + rx_polarity: "11010111" + tx_polarity: "10110111" + - id: "26" + lane_swap: "01234567" + rx_polarity: "00101101" + tx_polarity: "00100001" + - id: "27" + lane_swap: "01234567" + rx_polarity: "11011001" + tx_polarity: "11000111" + - id: "28" + lane_swap: "01234567" + rx_polarity: "01010011" + tx_polarity: "00100001" + - id: "29" + lane_swap: "01234567" + rx_polarity: "01111001" + tx_polarity: "10110111" + - id: "30" + lane_swap: "01234567" + rx_polarity: "00110001" + tx_polarity: "00101001" + - id: "31" + lane_swap: "01234567" + rx_polarity: "01101101" + tx_polarity: "10110101" + - id: "32" + lane_swap: "01234567" + rx_polarity: "00000000" + tx_polarity: "00000000" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/inno.config.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/inno.config.yaml new file mode 100755 index 000000000000..7dea4565d8e6 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_64x100G_nrz_midstone200i.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/innovium.77700_B b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/port_config.ini b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/port_config.ini new file mode 100644 index 000000000000..cb862ff9b523 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/port_config.ini @@ -0,0 +1,67 @@ +# name lanes speed index mtu +Ethernet0 249,250,251,252 100000 0 9126 +Ethernet4 253,254,255,256 100000 1 9126 +Ethernet8 245,246,247,248 100000 2 9126 +Ethernet12 241,242,243,244 100000 3 9126 +Ethernet16 233,234,235,236 100000 4 9126 +Ethernet20 237,238,239,240 100000 5 9126 +Ethernet24 229,230,231,232 100000 6 9126 +Ethernet28 225,226,227,228 100000 7 9126 +Ethernet32 217,218,219,220 100000 8 9126 +Ethernet36 221,222,223,224 100000 9 9126 +Ethernet40 213,214,215,216 100000 10 9126 +Ethernet44 209,210,211,212 100000 11 9126 +Ethernet48 201,202,203,204 100000 12 9126 +Ethernet52 205,206,207,208 100000 13 9126 +Ethernet56 197,198,199,200 100000 14 9126 +Ethernet60 193,194,195,196 100000 15 9126 +Ethernet64 185,186,187,188 100000 16 9126 +Ethernet68 189,190,191,192 100000 17 9126 +Ethernet72 181,182,183,184 100000 18 9126 +Ethernet76 177,178,179,180 100000 19 9126 +Ethernet80 169,170,171,172 100000 20 9126 +Ethernet84 173,174,175,176 100000 21 9126 +Ethernet88 165,166,167,168 100000 22 9126 +Ethernet92 161,162,163,164 100000 23 9126 +Ethernet96 153,154,155,156 100000 24 9126 +Ethernet100 157,158,159,160 100000 25 9126 +Ethernet104 149,150,151,152 100000 26 9126 +Ethernet108 145,146,147,148 100000 27 9126 +Ethernet112 137,138,139,140 100000 28 9126 +Ethernet116 141,142,143,144 100000 29 9126 +Ethernet120 133,134,135,136 100000 30 9126 +Ethernet124 129,130,131,132 100000 31 9126 +Ethernet128 121,122,123,124 100000 32 9126 +Ethernet132 125,126,127,128 100000 33 9126 +Ethernet136 117,118,119,120 100000 34 9126 +Ethernet140 113,114,115,116 100000 35 9126 +Ethernet144 105,106,107,108 100000 36 9126 +Ethernet148 109,110,111,112 100000 37 9126 +Ethernet152 101,102,103,104 100000 38 9126 +Ethernet156 97,98,99,100 100000 39 9126 +Ethernet160 89,90,91,92 100000 40 9126 +Ethernet164 93,94,95,96 100000 41 9126 +Ethernet168 85,86,87,88 100000 42 9126 +Ethernet172 81,82,83,84 100000 43 9126 +Ethernet176 73,74,75,76 100000 44 9126 +Ethernet180 77,78,79,80 100000 45 9126 +Ethernet184 69,70,71,72 100000 46 9126 +Ethernet188 65,66,67,68 100000 47 9126 +Ethernet192 57,58,59,60 100000 48 9126 +Ethernet196 61,62,63,64 100000 49 9126 +Ethernet200 53,54,55,56 100000 50 9126 +Ethernet204 49,50,51,52 100000 51 9126 +Ethernet208 41,42,43,44 100000 52 9126 +Ethernet212 45,46,47,48 100000 53 9126 +Ethernet216 37,38,39,40 100000 54 9126 +Ethernet220 33,34,35,36 100000 55 9126 +Ethernet224 25,26,27,28 100000 56 9126 +Ethernet228 29,30,31,32 100000 57 9126 +Ethernet232 21,22,23,24 100000 58 9126 +Ethernet236 17,18,19,20 100000 59 9126 +Ethernet240 9,10,11,12 100000 60 9126 +Ethernet244 13,14,15,16 100000 61 9126 +Ethernet248 5,6,7,8 100000 62 9126 +Ethernet252 1,2,3,4 100000 63 9126 +Ethernet256 257 10000 64 9126 +Ethernet257 258 10000 65 9126 diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/qos.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/qos.json.j2 new file mode 100755 index 000000000000..16f9b42a2166 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 64 -%} +{# 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*4)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/sai.profile b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/buffers.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/buffers.json.j2 new file mode 100644 index 000000000000..0285e389fd63 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/buffers.json.j2 @@ -0,0 +1,121 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_speed = '100G' %} +{% set default_ports_num = 32 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/config_64x100G_nrz_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/config_64x100G_nrz_midstone200i.yaml new file mode 100644 index 000000000000..8fb6a114a46c --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/config_64x100G_nrz_midstone200i.yaml @@ -0,0 +1,767 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_B" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "bootstrap_lossless" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "65" + type: "cpu" + - fec: "KRFEC" + id: "1" + lanes: "0:4" + serdes_group: "31" + speed: "100G" + sysport: "1" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "2" + lanes: "4:4" + serdes_group: "31" + speed: "100G" + sysport: "2" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "3" + lanes: "4:4" + serdes_group: "30" + speed: "100G" + sysport: "3" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "4" + lanes: "0:4" + serdes_group: "30" + speed: "100G" + sysport: "4" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "5" + lanes: "0:4" + serdes_group: "29" + speed: "100G" + sysport: "5" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "6" + lanes: "4:4" + serdes_group: "29" + speed: "100G" + sysport: "6" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "7" + lanes: "4:4" + serdes_group: "28" + speed: "100G" + sysport: "7" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "8" + lanes: "0:4" + serdes_group: "28" + speed: "100G" + sysport: "8" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "9" + lanes: "0:4" + serdes_group: "27" + speed: "100G" + sysport: "9" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "10" + lanes: "4:4" + serdes_group: "27" + speed: "100G" + sysport: "10" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "11" + lanes: "4:4" + serdes_group: "26" + speed: "100G" + sysport: "11" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "12" + lanes: "0:4" + serdes_group: "26" + speed: "100G" + sysport: "12" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "13" + lanes: "0:4" + serdes_group: "25" + speed: "100G" + sysport: "13" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "14" + lanes: "4:4" + serdes_group: "25" + speed: "100G" + sysport: "14" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "15" + lanes: "4:4" + serdes_group: "24" + speed: "100G" + sysport: "15" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "16" + lanes: "0:4" + serdes_group: "24" + speed: "100G" + sysport: "16" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "17" + lanes: "0:4" + serdes_group: "23" + speed: "100G" + sysport: "17" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "18" + lanes: "4:4" + serdes_group: "23" + speed: "100G" + sysport: "18" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "19" + lanes: "4:4" + serdes_group: "22" + speed: "100G" + sysport: "19" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "20" + lanes: "0:4" + serdes_group: "22" + speed: "100G" + sysport: "20" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "21" + lanes: "0:4" + serdes_group: "21" + speed: "100G" + sysport: "21" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "22" + lanes: "4:4" + serdes_group: "21" + speed: "100G" + sysport: "22" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "23" + lanes: "4:4" + serdes_group: "20" + speed: "100G" + sysport: "23" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "24" + lanes: "0:4" + serdes_group: "20" + speed: "100G" + sysport: "24" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "25" + lanes: "0:4" + serdes_group: "19" + speed: "100G" + sysport: "25" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "26" + lanes: "4:4" + serdes_group: "19" + speed: "100G" + sysport: "26" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "27" + lanes: "4:4" + serdes_group: "18" + speed: "100G" + sysport: "27" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "28" + lanes: "0:4" + serdes_group: "18" + speed: "100G" + sysport: "28" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "29" + lanes: "0:4" + serdes_group: "17" + speed: "100G" + sysport: "29" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "30" + lanes: "4:4" + serdes_group: "17" + speed: "100G" + sysport: "30" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "31" + lanes: "4:4" + serdes_group: "16" + speed: "100G" + sysport: "31" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "32" + lanes: "0:4" + serdes_group: "16" + speed: "100G" + sysport: "32" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "33" + lanes: "0:4" + serdes_group: "15" + speed: "100G" + sysport: "33" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "34" + lanes: "4:4" + serdes_group: "15" + speed: "100G" + sysport: "34" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "35" + lanes: "4:4" + serdes_group: "14" + speed: "100G" + sysport: "35" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "36" + lanes: "0:4" + serdes_group: "14" + speed: "100G" + sysport: "36" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "37" + lanes: "0:4" + serdes_group: "13" + speed: "100G" + sysport: "37" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "38" + lanes: "4:4" + serdes_group: "13" + speed: "100G" + sysport: "38" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "39" + lanes: "4:4" + serdes_group: "12" + speed: "100G" + sysport: "39" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "40" + lanes: "0:4" + serdes_group: "12" + speed: "100G" + sysport: "40" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "41" + lanes: "0:4" + serdes_group: "11" + speed: "100G" + sysport: "41" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "42" + lanes: "4:4" + serdes_group: "11" + speed: "100G" + sysport: "42" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "43" + lanes: "4:4" + serdes_group: "10" + speed: "100G" + sysport: "43" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "44" + lanes: "0:4" + serdes_group: "10" + speed: "100G" + sysport: "44" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "45" + lanes: "0:4" + serdes_group: "9" + speed: "100G" + sysport: "45" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "46" + lanes: "4:4" + serdes_group: "9" + speed: "100G" + sysport: "46" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "47" + lanes: "4:4" + serdes_group: "8" + speed: "100G" + sysport: "47" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "48" + lanes: "0:4" + serdes_group: "8" + speed: "100G" + sysport: "48" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "49" + lanes: "0:4" + serdes_group: "7" + speed: "100G" + sysport: "49" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "50" + lanes: "4:4" + serdes_group: "7" + speed: "100G" + sysport: "50" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "51" + lanes: "4:4" + serdes_group: "6" + speed: "100G" + sysport: "51" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "52" + lanes: "0:4" + serdes_group: "6" + speed: "100G" + sysport: "52" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "53" + lanes: "0:4" + serdes_group: "5" + speed: "100G" + sysport: "53" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "54" + lanes: "4:4" + serdes_group: "5" + speed: "100G" + sysport: "54" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "55" + lanes: "4:4" + serdes_group: "4" + speed: "100G" + sysport: "55" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "56" + lanes: "0:4" + serdes_group: "4" + speed: "100G" + sysport: "56" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "57" + lanes: "0:4" + serdes_group: "3" + speed: "100G" + sysport: "57" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "58" + lanes: "4:4" + serdes_group: "3" + speed: "100G" + sysport: "58" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "59" + lanes: "4:4" + serdes_group: "2" + speed: "100G" + sysport: "59" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "60" + lanes: "0:4" + serdes_group: "2" + speed: "100G" + sysport: "60" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "61" + lanes: "0:4" + serdes_group: "1" + speed: "100G" + sysport: "61" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "62" + lanes: "4:4" + serdes_group: "1" + speed: "100G" + sysport: "62" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "63" + lanes: "4:4" + serdes_group: "0" + speed: "100G" + sysport: "63" + type: "eth" + admin_state: "true" + loopback: "none" + - fec: "KRFEC" + id: "64" + lanes: "0:4" + serdes_group: "0" + speed: "100G" + sysport: "64" + type: "eth" + admin_state: "true" + loopback: "none" + isg: + - id: "0" + lane_swap: "01234567" + rx_polarity: "01110001" + tx_polarity: "00101001" + - id: "1" + lane_swap: "01234567" + rx_polarity: "11100100" + tx_polarity: "10111111" + - id: "2" + lane_swap: "01234567" + rx_polarity: "00010001" + tx_polarity: "00100010" + - id: "3" + lane_swap: "01234567" + rx_polarity: "11011101" + tx_polarity: "00101010" + - id: "4" + lane_swap: "01234567" + rx_polarity: "10010101" + tx_polarity: "10111110" + - id: "5" + lane_swap: "01234567" + rx_polarity: "10111001" + tx_polarity: "01101000" + - id: "6" + lane_swap: "01234567" + rx_polarity: "01110011" + tx_polarity: "01110110" + - id: "7" + lane_swap: "01234567" + rx_polarity: "10111001" + tx_polarity: "01001000" + - id: "8" + lane_swap: "01234567" + rx_polarity: "01000000" + tx_polarity: "11000100" + - id: "9" + lane_swap: "01234567" + rx_polarity: "10100100" + tx_polarity: "10001010" + - id: "10" + lane_swap: "01234567" + rx_polarity: "00011101" + tx_polarity: "11000110" + - id: "11" + lane_swap: "01234567" + rx_polarity: "00000101" + tx_polarity: "01000111" + - id: "12" + lane_swap: "01234567" + rx_polarity: "11100000" + tx_polarity: "01111000" + - id: "13" + lane_swap: "01234567" + rx_polarity: "00101111" + tx_polarity: "10011111" + - id: "14" + lane_swap: "01234567" + rx_polarity: "00011000" + tx_polarity: "00101001" + - id: "15" + lane_swap: "01234567" + rx_polarity: "00110110" + tx_polarity: "10110111" + - id: "16" + lane_swap: "01234567" + rx_polarity: "00000111" + tx_polarity: "00101001" + - id: "17" + lane_swap: "01234567" + rx_polarity: "10001000" + tx_polarity: "10100111" + - id: "18" + lane_swap: "01234567" + rx_polarity: "11111110" + tx_polarity: "00011001" + - id: "19" + lane_swap: "01234567" + rx_polarity: "10011010" + tx_polarity: "10010101" + - id: "20" + lane_swap: "01234567" + rx_polarity: "01100000" + tx_polarity: "00101001" + - id: "21" + lane_swap: "01234567" + rx_polarity: "01111001" + tx_polarity: "10010111" + - id: "22" + lane_swap: "01234567" + rx_polarity: "11010011" + tx_polarity: "00101001" + - id: "23" + lane_swap: "01234567" + rx_polarity: "01111011" + tx_polarity: "10110111" + - id: "24" + lane_swap: "01234567" + rx_polarity: "11101011" + tx_polarity: "00101001" + - id: "25" + lane_swap: "01234567" + rx_polarity: "11010111" + tx_polarity: "10110111" + - id: "26" + lane_swap: "01234567" + rx_polarity: "00101101" + tx_polarity: "00100001" + - id: "27" + lane_swap: "01234567" + rx_polarity: "11011001" + tx_polarity: "11000111" + - id: "28" + lane_swap: "01234567" + rx_polarity: "01010011" + tx_polarity: "00100001" + - id: "29" + lane_swap: "01234567" + rx_polarity: "01111001" + tx_polarity: "10110111" + - id: "30" + lane_swap: "01234567" + rx_polarity: "00110001" + tx_polarity: "00101001" + - id: "31" + lane_swap: "01234567" + rx_polarity: "01101101" + tx_polarity: "10110101" + - id: "32" + lane_swap: "01234567" + rx_polarity: "00000000" + tx_polarity: "00000000" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/inno.config.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/inno.config.yaml new file mode 100755 index 000000000000..490de1ca3fdc --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_64x100G_nrz_midstone200i.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/innovium.77700_B b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/port_config.ini b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/port_config.ini new file mode 100644 index 000000000000..462950d390b6 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/port_config.ini @@ -0,0 +1,65 @@ +# name lanes speed mtu +Ethernet0 249,250,251,252 100000 9126 +Ethernet4 253,254,255,256 100000 9126 +Ethernet8 245,246,247,248 100000 9126 +Ethernet12 241,242,243,244 100000 9126 +Ethernet16 233,234,235,236 100000 9126 +Ethernet20 237,238,239,240 100000 9126 +Ethernet24 229,230,231,232 100000 9126 +Ethernet28 225,226,227,228 100000 9126 +Ethernet32 217,218,219,220 100000 9126 +Ethernet36 221,222,223,224 100000 9126 +Ethernet40 213,214,215,216 100000 9126 +Ethernet44 209,210,211,212 100000 9126 +Ethernet48 201,202,203,204 100000 9126 +Ethernet52 205,206,207,208 100000 9126 +Ethernet56 197,198,199,200 100000 9126 +Ethernet60 193,194,195,196 100000 9126 +Ethernet64 185,186,187,188 100000 9126 +Ethernet68 189,190,191,192 100000 9126 +Ethernet72 181,182,183,184 100000 9126 +Ethernet76 177,178,179,180 100000 9126 +Ethernet80 169,170,171,172 100000 9126 +Ethernet84 173,174,175,176 100000 9126 +Ethernet88 165,166,167,168 100000 9126 +Ethernet92 161,162,163,164 100000 9126 +Ethernet96 153,154,155,156 100000 9126 +Ethernet100 157,158,159,160 100000 9126 +Ethernet104 149,150,151,152 100000 9126 +Ethernet108 145,146,147,148 100000 9126 +Ethernet112 137,138,139,140 100000 9126 +Ethernet116 141,142,143,144 100000 9126 +Ethernet120 133,134,135,136 100000 9126 +Ethernet124 129,130,131,132 100000 9126 +Ethernet128 121,122,123,124 100000 9126 +Ethernet132 125,126,127,128 100000 9126 +Ethernet136 117,118,119,120 100000 9126 +Ethernet140 113,114,115,116 100000 9126 +Ethernet144 105,106,107,108 100000 9126 +Ethernet148 109,110,111,112 100000 9126 +Ethernet152 101,102,103,104 100000 9126 +Ethernet156 97,98,99,100 100000 9126 +Ethernet160 89,90,91,92 100000 9126 +Ethernet164 93,94,95,96 100000 9126 +Ethernet168 85,86,87,88 100000 9126 +Ethernet172 81,82,83,84 100000 9126 +Ethernet176 73,74,75,76 100000 9126 +Ethernet180 77,78,79,80 100000 9126 +Ethernet184 69,70,71,72 100000 9126 +Ethernet188 65,66,67,68 100000 9126 +Ethernet192 57,58,59,60 100000 9126 +Ethernet196 61,62,63,64 100000 9126 +Ethernet200 53,54,55,56 100000 9126 +Ethernet204 49,50,51,52 100000 9126 +Ethernet208 41,42,43,44 100000 9126 +Ethernet212 45,46,47,48 100000 9126 +Ethernet216 37,38,39,40 100000 9126 +Ethernet220 33,34,35,36 100000 9126 +Ethernet224 25,26,27,28 100000 9126 +Ethernet228 29,30,31,32 100000 9126 +Ethernet232 21,22,23,24 100000 9126 +Ethernet236 17,18,19,20 100000 9126 +Ethernet240 9,10,11,12 100000 9126 +Ethernet244 13,14,15,16 100000 9126 +Ethernet248 5,6,7,8 100000 9126 +Ethernet252 1,2,3,4 100000 9126 diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/qos.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/qos.json.j2 new file mode 100755 index 000000000000..b22aa6ef599b --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/qos.json.j2 @@ -0,0 +1,102 @@ +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "Ethernet180,Ethernet8,Ethernet44,Ethernet184,Ethernet188,Ethernet0,Ethernet4,Ethernet108,Ethernet248,Ethernet100,Ethernet244,Ethernet128,Ethernet104,Ethernet240,Ethernet40,Ethernet228,Ethernet96,Ethernet168,Ethernet148,Ethernet204,Ethernet120,Ethernet220,Ethernet144,Ethernet208,Ethernet160,Ethernet224,Ethernet140,Ethernet56,Ethernet164,Ethernet76,Ethernet72,Ethernet32,Ethernet16,Ethernet36,Ethernet12,Ethernet196,Ethernet28,Ethernet192,Ethernet200,Ethernet124,Ethernet24,Ethernet116,Ethernet80,Ethernet112,Ethernet84,Ethernet152,Ethernet136,Ethernet156,Ethernet92,Ethernet132,Ethernet48,Ethernet232,Ethernet172,Ethernet216,Ethernet236,Ethernet176,Ethernet212,Ethernet64,Ethernet88,Ethernet60,Ethernet52,Ethernet20,Ethernet68,Ethernet252": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/sai.profile b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x100nrz/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/buffers.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/buffers.json.j2 new file mode 100644 index 000000000000..45cebf3b7144 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 64 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/config_64x200G_midstone200i.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/config_64x200G_midstone200i.yaml new file mode 100644 index 000000000000..7133de54e493 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/config_64x200G_midstone200i.yaml @@ -0,0 +1,653 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_B" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KPFEC" + id: "249" + lanes: "0:4" + serdes_group: "31" + speed: "200G" + sysport: "249" + type: "eth" + - fec: "KPFEC" + id: "253" + lanes: "4:4" + serdes_group: "31" + speed: "200G" + sysport: "253" + type: "eth" + - fec: "KPFEC" + id: "245" + lanes: "4:4" + serdes_group: "30" + speed: "200G" + sysport: "245" + type: "eth" + - fec: "KPFEC" + id: "241" + lanes: "0:4" + serdes_group: "30" + speed: "200G" + sysport: "241" + type: "eth" + - fec: "KPFEC" + id: "233" + lanes: "0:4" + serdes_group: "29" + speed: "200G" + sysport: "233" + type: "eth" + - fec: "KPFEC" + id: "237" + lanes: "4:4" + serdes_group: "29" + speed: "200G" + sysport: "237" + type: "eth" + - fec: "KPFEC" + id: "229" + lanes: "4:4" + serdes_group: "28" + speed: "200G" + sysport: "229" + type: "eth" + - fec: "KPFEC" + id: "225" + lanes: "0:4" + serdes_group: "28" + speed: "200G" + sysport: "225" + type: "eth" + - fec: "KPFEC" + id: "217" + lanes: "0:4" + serdes_group: "27" + speed: "200G" + sysport: "217" + type: "eth" + - fec: "KPFEC" + id: "221" + lanes: "4:4" + serdes_group: "27" + speed: "200G" + sysport: "221" + type: "eth" + - fec: "KPFEC" + id: "213" + lanes: "4:4" + serdes_group: "26" + speed: "200G" + sysport: "213" + type: "eth" + - fec: "KPFEC" + id: "209" + lanes: "0:4" + serdes_group: "26" + speed: "200G" + sysport: "209" + type: "eth" + - fec: "KPFEC" + id: "201" + lanes: "0:4" + serdes_group: "25" + speed: "200G" + sysport: "201" + type: "eth" + - fec: "KPFEC" + id: "205" + lanes: "4:4" + serdes_group: "25" + speed: "200G" + sysport: "205" + type: "eth" + - fec: "KPFEC" + id: "197" + lanes: "4:4" + serdes_group: "24" + speed: "200G" + sysport: "197" + type: "eth" + - fec: "KPFEC" + id: "193" + lanes: "0:4" + serdes_group: "24" + speed: "200G" + sysport: "193" + type: "eth" + - fec: "KPFEC" + id: "185" + lanes: "0:4" + serdes_group: "23" + speed: "200G" + sysport: "185" + type: "eth" + - fec: "KPFEC" + id: "189" + lanes: "4:4" + serdes_group: "23" + speed: "200G" + sysport: "189" + type: "eth" + - fec: "KPFEC" + id: "181" + lanes: "4:4" + serdes_group: "22" + speed: "200G" + sysport: "181" + type: "eth" + - fec: "KPFEC" + id: "177" + lanes: "0:4" + serdes_group: "22" + speed: "200G" + sysport: "177" + type: "eth" + - fec: "KPFEC" + id: "169" + lanes: "0:4" + serdes_group: "21" + speed: "200G" + sysport: "169" + type: "eth" + - fec: "KPFEC" + id: "173" + lanes: "4:4" + serdes_group: "21" + speed: "200G" + sysport: "173" + type: "eth" + - fec: "KPFEC" + id: "165" + lanes: "4:4" + serdes_group: "20" + speed: "200G" + sysport: "165" + type: "eth" + - fec: "KPFEC" + id: "161" + lanes: "0:4" + serdes_group: "20" + speed: "200G" + sysport: "161" + type: "eth" + - fec: "KPFEC" + id: "153" + lanes: "0:4" + serdes_group: "19" + speed: "200G" + sysport: "153" + type: "eth" + - fec: "KPFEC" + id: "157" + lanes: "4:4" + serdes_group: "19" + speed: "200G" + sysport: "157" + type: "eth" + - fec: "KPFEC" + id: "149" + lanes: "4:4" + serdes_group: "18" + speed: "200G" + sysport: "149" + type: "eth" + - fec: "KPFEC" + id: "145" + lanes: "0:4" + serdes_group: "18" + speed: "200G" + sysport: "145" + type: "eth" + - fec: "KPFEC" + id: "137" + lanes: "0:4" + serdes_group: "17" + speed: "200G" + sysport: "137" + type: "eth" + - fec: "KPFEC" + id: "141" + lanes: "4:4" + serdes_group: "17" + speed: "200G" + sysport: "141" + type: "eth" + - fec: "KPFEC" + id: "133" + lanes: "4:4" + serdes_group: "16" + speed: "200G" + sysport: "133" + type: "eth" + - fec: "KPFEC" + id: "129" + lanes: "0:4" + serdes_group: "16" + speed: "200G" + sysport: "129" + type: "eth" + - fec: "KPFEC" + id: "121" + lanes: "0:4" + serdes_group: "15" + speed: "200G" + sysport: "121" + type: "eth" + - fec: "KPFEC" + id: "125" + lanes: "4:4" + serdes_group: "15" + speed: "200G" + sysport: "125" + type: "eth" + - fec: "KPFEC" + id: "117" + lanes: "4:4" + serdes_group: "14" + speed: "200G" + sysport: "117" + type: "eth" + - fec: "KPFEC" + id: "113" + lanes: "0:4" + serdes_group: "14" + speed: "200G" + sysport: "113" + type: "eth" + - fec: "KPFEC" + id: "105" + lanes: "0:4" + serdes_group: "13" + speed: "200G" + sysport: "105" + type: "eth" + - fec: "KPFEC" + id: "109" + lanes: "4:4" + serdes_group: "13" + speed: "200G" + sysport: "109" + type: "eth" + - fec: "KPFEC" + id: "101" + lanes: "4:4" + serdes_group: "12" + speed: "200G" + sysport: "101" + type: "eth" + - fec: "KPFEC" + id: "97" + lanes: "0:4" + serdes_group: "12" + speed: "200G" + sysport: "97" + type: "eth" + - fec: "KPFEC" + id: "89" + lanes: "0:4" + serdes_group: "11" + speed: "200G" + sysport: "89" + type: "eth" + - fec: "KPFEC" + id: "93" + lanes: "4:4" + serdes_group: "11" + speed: "200G" + sysport: "93" + type: "eth" + - fec: "KPFEC" + id: "85" + lanes: "4:4" + serdes_group: "10" + speed: "200G" + sysport: "85" + type: "eth" + - fec: "KPFEC" + id: "81" + lanes: "0:4" + serdes_group: "10" + speed: "200G" + sysport: "81" + type: "eth" + - fec: "KPFEC" + id: "73" + lanes: "0:4" + serdes_group: "9" + speed: "200G" + sysport: "73" + type: "eth" + - fec: "KPFEC" + id: "77" + lanes: "4:4" + serdes_group: "9" + speed: "200G" + sysport: "77" + type: "eth" + - fec: "KPFEC" + id: "69" + lanes: "4:4" + serdes_group: "8" + speed: "200G" + sysport: "69" + type: "eth" + - fec: "KPFEC" + id: "65" + lanes: "0:4" + serdes_group: "8" + speed: "200G" + sysport: "65" + type: "eth" + - fec: "KPFEC" + id: "57" + lanes: "0:4" + serdes_group: "7" + speed: "200G" + sysport: "57" + type: "eth" + - fec: "KPFEC" + id: "61" + lanes: "4:4" + serdes_group: "7" + speed: "200G" + sysport: "61" + type: "eth" + - fec: "KPFEC" + id: "53" + lanes: "4:4" + serdes_group: "6" + speed: "200G" + sysport: "53" + type: "eth" + - fec: "KPFEC" + id: "49" + lanes: "0:4" + serdes_group: "6" + speed: "200G" + sysport: "49" + type: "eth" + - fec: "KPFEC" + id: "41" + lanes: "0:4" + serdes_group: "5" + speed: "200G" + sysport: "41" + type: "eth" + - fec: "KPFEC" + id: "45" + lanes: "4:4" + serdes_group: "5" + speed: "200G" + sysport: "45" + type: "eth" + - fec: "KPFEC" + id: "37" + lanes: "4:4" + serdes_group: "4" + speed: "200G" + sysport: "37" + type: "eth" + - fec: "KPFEC" + id: "33" + lanes: "0:4" + serdes_group: "4" + speed: "200G" + sysport: "33" + type: "eth" + - fec: "KPFEC" + id: "25" + lanes: "0:4" + serdes_group: "3" + speed: "200G" + sysport: "25" + type: "eth" + - fec: "KPFEC" + id: "29" + lanes: "4:4" + serdes_group: "3" + speed: "200G" + sysport: "29" + type: "eth" + - fec: "KPFEC" + id: "21" + lanes: "4:4" + serdes_group: "2" + speed: "200G" + sysport: "21" + type: "eth" + - fec: "KPFEC" + id: "17" + lanes: "0:4" + serdes_group: "2" + speed: "200G" + sysport: "17" + type: "eth" + - fec: "KPFEC" + id: "9" + lanes: "0:4" + serdes_group: "1" + speed: "200G" + sysport: "9" + type: "eth" + - fec: "KPFEC" + id: "13" + lanes: "4:4" + serdes_group: "1" + speed: "200G" + sysport: "13" + type: "eth" + - fec: "KPFEC" + id: "5" + lanes: "4:4" + serdes_group: "0" + speed: "200G" + sysport: "5" + type: "eth" + - fec: "KPFEC" + id: "1" + lanes: "0:4" + serdes_group: "0" + speed: "200G" + sysport: "1" + type: "eth" + - fec: "NONE" + id: "257" + lanes: "0:1" + serdes_group: "32" + speed: "10G" + sysport: "257" + type: "mgmt 0" + - fec: "NONE" + id: "258" + lanes: "1:1" + serdes_group: "32" + speed: "10G" + sysport: "258" + type: "mgmt 0" + isg: + - id: "0" + lane_swap: "01234567" + rx_polarity: "01110001" + tx_polarity: "00101001" + - id: "1" + lane_swap: "01234567" + rx_polarity: "11100100" + tx_polarity: "10111111" + - id: "2" + lane_swap: "01234567" + rx_polarity: "00010001" + tx_polarity: "00100010" + - id: "3" + lane_swap: "01234567" + rx_polarity: "11011101" + tx_polarity: "00101010" + - id: "4" + lane_swap: "01234567" + rx_polarity: "10010101" + tx_polarity: "10111110" + - id: "5" + lane_swap: "01234567" + rx_polarity: "10111001" + tx_polarity: "01101000" + - id: "6" + lane_swap: "01234567" + rx_polarity: "01110011" + tx_polarity: "01110110" + - id: "7" + lane_swap: "01234567" + rx_polarity: "10111001" + tx_polarity: "01001000" + - id: "8" + lane_swap: "01234567" + rx_polarity: "01000000" + tx_polarity: "11000100" + - id: "9" + lane_swap: "01234567" + rx_polarity: "10100100" + tx_polarity: "10001010" + - id: "10" + lane_swap: "01234567" + rx_polarity: "00011101" + tx_polarity: "11000110" + - id: "11" + lane_swap: "01234567" + rx_polarity: "00000101" + tx_polarity: "01000111" + - id: "12" + lane_swap: "01234567" + rx_polarity: "11100000" + tx_polarity: "01111000" + - id: "13" + lane_swap: "01234567" + rx_polarity: "00101111" + tx_polarity: "10011111" + - id: "14" + lane_swap: "01234567" + rx_polarity: "00011000" + tx_polarity: "00101001" + - id: "15" + lane_swap: "01234567" + rx_polarity: "00110110" + tx_polarity: "10110111" + - id: "16" + lane_swap: "01234567" + rx_polarity: "00000111" + tx_polarity: "00101001" + - id: "17" + lane_swap: "01234567" + rx_polarity: "10001000" + tx_polarity: "10100111" + - id: "18" + lane_swap: "01234567" + rx_polarity: "11111110" + tx_polarity: "00011001" + - id: "19" + lane_swap: "01234567" + rx_polarity: "10011010" + tx_polarity: "10010101" + - id: "20" + lane_swap: "01234567" + rx_polarity: "01100000" + tx_polarity: "00101001" + - id: "21" + lane_swap: "01234567" + rx_polarity: "01111001" + tx_polarity: "10010111" + - id: "22" + lane_swap: "01234567" + rx_polarity: "11010011" + tx_polarity: "00101001" + - id: "23" + lane_swap: "01234567" + rx_polarity: "01111011" + tx_polarity: "10110111" + - id: "24" + lane_swap: "01234567" + rx_polarity: "11101011" + tx_polarity: "00101001" + - id: "25" + lane_swap: "01234567" + rx_polarity: "11010111" + tx_polarity: "10110111" + - id: "26" + lane_swap: "01234567" + rx_polarity: "00101101" + tx_polarity: "00100001" + - id: "27" + lane_swap: "01234567" + rx_polarity: "11011001" + tx_polarity: "11000111" + - id: "28" + lane_swap: "01234567" + rx_polarity: "01010011" + tx_polarity: "00100001" + - id: "29" + lane_swap: "01234567" + rx_polarity: "01111001" + tx_polarity: "10110111" + - id: "30" + lane_swap: "01234567" + rx_polarity: "00110001" + tx_polarity: "00101001" + - id: "31" + lane_swap: "01234567" + rx_polarity: "01101101" + tx_polarity: "10110101" + - id: "32" + lane_swap: "01234567" + rx_polarity: "00000000" + tx_polarity: "00000000" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/inno.config.yaml b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/inno.config.yaml new file mode 100755 index 000000000000..970a5830339e --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_64x200G_midstone200i.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/innovium.77700_B b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/port_config.ini b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/port_config.ini new file mode 100644 index 000000000000..3dcbf72bc324 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/port_config.ini @@ -0,0 +1,67 @@ +# name lanes speed index mtu fec +Ethernet0 249,250,251,252 200000 0 9126 rs +Ethernet4 253,254,255,256 200000 1 9126 rs +Ethernet8 245,246,247,248 200000 2 9126 rs +Ethernet12 241,242,243,244 200000 3 9126 rs +Ethernet16 233,234,235,236 200000 4 9126 rs +Ethernet20 237,238,239,240 200000 5 9126 rs +Ethernet24 229,230,231,232 200000 6 9126 rs +Ethernet28 225,226,227,228 200000 7 9126 rs +Ethernet32 217,218,219,220 200000 8 9126 rs +Ethernet36 221,222,223,224 200000 9 9126 rs +Ethernet40 213,214,215,216 200000 10 9126 rs +Ethernet44 209,210,211,212 200000 11 9126 rs +Ethernet48 201,202,203,204 200000 12 9126 rs +Ethernet52 205,206,207,208 200000 13 9126 rs +Ethernet56 197,198,199,200 200000 14 9126 rs +Ethernet60 193,194,195,196 200000 15 9126 rs +Ethernet64 185,186,187,188 200000 16 9126 rs +Ethernet68 189,190,191,192 200000 17 9126 rs +Ethernet72 181,182,183,184 200000 18 9126 rs +Ethernet76 177,178,179,180 200000 19 9126 rs +Ethernet80 169,170,171,172 200000 20 9126 rs +Ethernet84 173,174,175,176 200000 21 9126 rs +Ethernet88 165,166,167,168 200000 22 9126 rs +Ethernet92 161,162,163,164 200000 23 9126 rs +Ethernet96 153,154,155,156 200000 24 9126 rs +Ethernet100 157,158,159,160 200000 25 9126 rs +Ethernet104 149,150,151,152 200000 26 9126 rs +Ethernet108 145,146,147,148 200000 27 9126 rs +Ethernet112 137,138,139,140 200000 28 9126 rs +Ethernet116 141,142,143,144 200000 29 9126 rs +Ethernet120 133,134,135,136 200000 30 9126 rs +Ethernet124 129,130,131,132 200000 31 9126 rs +Ethernet128 121,122,123,124 200000 32 9126 rs +Ethernet132 125,126,127,128 200000 33 9126 rs +Ethernet136 117,118,119,120 200000 34 9126 rs +Ethernet140 113,114,115,116 200000 35 9126 rs +Ethernet144 105,106,107,108 200000 36 9126 rs +Ethernet148 109,110,111,112 200000 37 9126 rs +Ethernet152 101,102,103,104 200000 38 9126 rs +Ethernet156 97,98,99,100 200000 39 9126 rs +Ethernet160 89,90,91,92 200000 40 9126 rs +Ethernet164 93,94,95,96 200000 41 9126 rs +Ethernet168 85,86,87,88 200000 42 9126 rs +Ethernet172 81,82,83,84 200000 43 9126 rs +Ethernet176 73,74,75,76 200000 44 9126 rs +Ethernet180 77,78,79,80 200000 45 9126 rs +Ethernet184 69,70,71,72 200000 46 9126 rs +Ethernet188 65,66,67,68 200000 47 9126 rs +Ethernet192 57,58,59,60 200000 48 9126 rs +Ethernet196 61,62,63,64 200000 49 9126 rs +Ethernet200 53,54,55,56 200000 50 9126 rs +Ethernet204 49,50,51,52 200000 51 9126 rs +Ethernet208 41,42,43,44 200000 52 9126 rs +Ethernet212 45,46,47,48 200000 53 9126 rs +Ethernet216 37,38,39,40 200000 54 9126 rs +Ethernet220 33,34,35,36 200000 55 9126 rs +Ethernet224 25,26,27,28 200000 56 9126 rs +Ethernet228 29,30,31,32 200000 57 9126 rs +Ethernet232 21,22,23,24 200000 58 9126 rs +Ethernet236 17,18,19,20 200000 59 9126 rs +Ethernet240 9,10,11,12 200000 60 9126 rs +Ethernet244 13,14,15,16 200000 61 9126 rs +Ethernet248 5,6,7,8 200000 62 9126 rs +Ethernet252 1,2,3,4 200000 63 9126 rs +Ethernet256 257 10000 64 9126 none +Ethernet257 258 10000 65 9126 none diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/qos.json.j2 b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/qos.json.j2 new file mode 100755 index 000000000000..16f9b42a2166 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 64 -%} +{# 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*4)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/sai.profile b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/Midstone-200i_64x200/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/celestica/x86_64-cel_midstone-r0/default_sku b/device/celestica/x86_64-cel_midstone-r0/default_sku new file mode 100755 index 000000000000..6fe6e28064bd --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/default_sku @@ -0,0 +1 @@ +Midstone-200i t1 diff --git a/device/celestica/x86_64-cel_midstone-r0/fancontrol b/device/celestica/x86_64-cel_midstone-r0/fancontrol new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/device/celestica/x86_64-cel_midstone-r0/installer.conf b/device/celestica/x86_64-cel_midstone-r0/installer.conf new file mode 100755 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/celestica/x86_64-cel_midstone-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_midstone-r0/plugins/eeprom.py new file mode 100755 index 000000000000..c8b593a15003 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Celestica Midstone-200i +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/celestica/x86_64-cel_midstone-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_midstone-r0/plugins/psuutil.py new file mode 100644 index 000000000000..0c93576e1fba --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/plugins/psuutil.py @@ -0,0 +1,58 @@ +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path +import subprocess + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 1 + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 1 + return status == 1 diff --git a/device/celestica/x86_64-cel_midstone-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_midstone-r0/plugins/sfputil.py new file mode 100755 index 000000000000..8b3b06ff00ef --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/plugins/sfputil.py @@ -0,0 +1,205 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 65 + QSFP_PORT_START = PORT_START + QSFP_PORT_END = 63 + + EEPROM_OFFSET = 1 + + _port_to_eeprom_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 list(range(self.QSFP_PORT_START, self.QSFP_PORT_END+1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + if self.port_start == 1: + offset = self.EEPROM_OFFSET - 1 + else: + offset = self.EEPROM_OFFSET + + for x in range(self.port_start, self.port_end + 1): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + offset) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/ms200i_cpld/qsfp_modprs") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/ms200i_cpld/qsfp_lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/ms200i_cpld/qsfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value).strip('L') + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/ms200i_cpld/qsfp_reset" + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value).rstrip('L')) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value).rstrip('L')) + reg_file.close() + + return True 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_midstone-r0/sensors.conf b/device/celestica/x86_64-cel_midstone-r0/sensors.conf new file mode 100755 index 000000000000..7c9a6321dfc0 --- /dev/null +++ b/device/celestica/x86_64-cel_midstone-r0/sensors.conf @@ -0,0 +1,2 @@ +# libsensors configuration file for Celestica Midstone-200i. +# The i2c bus portion is omit because adapter name diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/buffers.json.j2 b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/buffers_defaults_t0.j2 b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..4dd6bd96ad96 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/buffers_defaults_t0.j2 @@ -0,0 +1,54 @@ + +{%- set default_cable = '5m' %} + +{%- set ports2cable = { + 'torrouter_server' : '300m', + 'leafrouter_torrouter' : '300m', + 'spinerouter_leafrouter' : '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": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/buffers_defaults_t1.j2 b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..3c93fb8fe2e3 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/buffers_defaults_t1.j2 @@ -0,0 +1,54 @@ + +{%- set default_cable = '40m' %} + +{%- set ports2cable = { + 'torrouter_server' : '300m', + 'leafrouter_torrouter' : '300m', + 'spinerouter_leafrouter' : '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": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/pg_profile_lookup.ini b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/pg_profile_lookup.ini new file mode 100644 index 000000000000..673df369a9bb --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 0 2288 + 25000 5m 1248 2288 53248 0 2288 + 40000 5m 1248 2288 66560 0 2288 + 50000 5m 1248 2288 90272 0 2288 + 100000 5m 1248 2288 165568 0 2288 + 10000 40m 1248 2288 37024 0 2288 + 25000 40m 1248 2288 53248 0 2288 + 40000 40m 1248 2288 71552 0 2288 + 50000 40m 1248 2288 96096 0 2288 + 100000 40m 1248 2288 177632 0 2288 + 10000 300m 1248 2288 46176 0 2288 + 25000 300m 1248 2288 79040 0 2288 + 40000 300m 1248 2288 108160 0 2288 + 50000 300m 1248 2288 141856 0 2288 + 100000 300m 1248 2288 268736 0 2288 diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/port_config.ini new file mode 100644 index 000000000000..24e7b3c99858 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias speed index +Ethernet0 65,66,67,68 etp1 100000 1 +Ethernet4 69,70,71,72 etp2 100000 2 +Ethernet8 73,74,75,76 etp3 100000 3 +Ethernet12 77,78,79,80 etp4 100000 4 +Ethernet16 33,34,35,36 etp5 100000 5 +Ethernet20 37,38,39,40 etp6 100000 6 +Ethernet24 41,42,43,44 etp7 100000 7 +Ethernet28 45,46,47,48 etp8 100000 8 +Ethernet32 49,50,51,52 etp9 100000 9 +Ethernet36 53,54,55,56 etp10 100000 10 +Ethernet40 57,58,59,60 etp11 100000 11 +Ethernet44 61,62,63,64 etp12 100000 12 +Ethernet48 81,82,83,84 etp13 100000 13 +Ethernet52 85,86,87,88 etp14 100000 14 +Ethernet56 89,90,91,92 etp15 100000 15 +Ethernet60 93,94,95,96 etp16 100000 16 +Ethernet64 97,98,99,100 etp17 100000 17 +Ethernet68 101,102,103,104 etp18 100000 18 +Ethernet72 105,106,107,108 etp19 100000 19 +Ethernet76 109,110,111,112 etp20 100000 20 +Ethernet80 1,2,3,4 etp21 100000 21 +Ethernet84 5,6,7,8 etp22 100000 22 +Ethernet88 9,10,11,12 etp23 100000 23 +Ethernet92 13,14,15,16 etp24 100000 24 +Ethernet96 17,18,19,20 etp25 100000 25 +Ethernet100 21,22,23,24 etp26 100000 26 +Ethernet104 25,26,27,28 etp27 100000 27 +Ethernet108 29,30,31,32 etp28 100000 28 +Ethernet112 113,114,115,116 etp29 100000 29 +Ethernet116 117,118,119,120 etp30 100000 30 +Ethernet120 121,122,123,124 etp31 100000 31 +Ethernet124 125,126,127,128 etp32 100000 32 diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/qos.json.j2 b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/qos.json.j2 new file mode 100644 index 000000000000..34002048afdb --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/qos.json.j2 @@ -0,0 +1,21 @@ +{%- macro generate_wred_profiles() %} + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "250000", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, +{%- endmacro %} + +{%- include 'qos_config.j2' %} diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/sai.profile.j2 b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/sai.profile.j2 new file mode 100644 index 000000000000..5feba4956931 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/sai.profile.j2 @@ -0,0 +1,14 @@ +{# Get sai.profile based on switch_role #} +{%- if DEVICE_METADATA is defined and DEVICE_METADATA['localhost'] is defined and DEVICE_METADATA['localhost']['type'] is defined -%} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] -%} +{%- if 'torrouter' in switch_role.lower() %} +{% set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-seastone-dx010-32x100G-t0.config.bcm' -%} +{%- else %} +{% set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-seastone-dx010-32x100G-t1.config.bcm' -%} +{%- endif %} +{%- else %} +{% set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-seastone-dx010-32x100G-t1.config.bcm' -%} +{%- endif %} +{# Write the contents of sai_ profile_filename to sai.profile file #} +{{ sai_profile_contents }} +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/th-seastone-dx010-32x100G-t0.config.bcm b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/th-seastone-dx010-32x100G-t0.config.bcm new file mode 100644 index 000000000000..7c315460dc8e --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/th-seastone-dx010-32x100G-t0.config.bcm @@ -0,0 +1,376 @@ +# Define default OS / SAL +os=unix + +# all XPORTs to XE ports +#pbmp_xport_xe=0x1fffffffe +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +pbmp_oversubscribe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe + +# Mode control to select L2 Table DMA mode aka L2MODE_POLL (0) or +# L2MOD_FIFO mechanism aka L2MODE_FIFO (1) for L2 table change notification. +l2xmsg_mode=1 + +# Memory table size configs +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +mmu_lossless=0 + +################################################################################### +# Celestica Customize for SeaStone +################################################################################### + +#ext mdio frequency to 495/0x80/2(1.933Mhz) or 415/0x80/2(1.62MHz) +# default is 40 +# Set external MDIO freq to 6.19MHz (495MHz) or 5.19MHz (415MHz) +#* target_freq is core_clock_freq * DIVIDEND / DIVISOR / 2 +# +rate_ext_mdio_divisor=0x80 + +# use internal rom boot +phy_ext_rom_boot=0 + +#fpem_mem_entries=32768 +oversubscribe_mode=1 +#pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + + +dport_map_enable=1 + +dport_map_port_68=1 +dport_map_port_72=5 +dport_map_port_76=9 +dport_map_port_80=13 +dport_map_port_34=17 +dport_map_port_38=21 +dport_map_port_42=25 +dport_map_port_46=29 +dport_map_port_50=33 +dport_map_port_54=37 +dport_map_port_58=41 +dport_map_port_62=45 +dport_map_port_84=49 +dport_map_port_88=53 +dport_map_port_92=57 +dport_map_port_96=61 +dport_map_port_102=65 +dport_map_port_106=69 +dport_map_port_110=73 +dport_map_port_114=77 +dport_map_port_1=81 +dport_map_port_5=85 +dport_map_port_9=89 +dport_map_port_13=93 +dport_map_port_17=97 +dport_map_port_21=101 +dport_map_port_25=105 +dport_map_port_29=109 +dport_map_port_118=113 +dport_map_port_122=117 +dport_map_port_126=121 +dport_map_port_130=125 + + +# port mapping +portmap_68=65:100:4 +portmap_72=69:100:4 +portmap_76=73:100:4 +portmap_80=77:100:4 +portmap_34=33:100:4 +portmap_38=37:100:4 +portmap_42=41:100:4 +portmap_46=45:100:4 +portmap_50=49:100:4 +portmap_54=53:100:4 +portmap_58=57:100:4 +portmap_62=61:100:4 +portmap_84=81:100:4 +portmap_88=85:100:4 +portmap_92=89:100:4 +portmap_96=93:100:4 +portmap_102=97:100:4 +portmap_106=101:100:4 +portmap_110=105:100:4 +portmap_114=109:100:4 +portmap_1=1:100:4 +portmap_5=5:100:4 +portmap_9=9:100:4 +portmap_13=13:100:4 +portmap_17=17:100:4 +portmap_21=21:100:4 +portmap_25=25:100:4 +portmap_29=29:100:4 +portmap_118=113:100:4 +portmap_122=117:100:4 +portmap_126=121:100:4 +portmap_130=125:100:4 +#portmap_66=129:10 +#portmap_100=131:10 + +#WC16 +xgxs_tx_lane_map_68=0x3201 +xgxs_rx_lane_map_68=0x2310 + + +#WC17 +xgxs_tx_lane_map_72=0x3201 +xgxs_rx_lane_map_72=0x2301 + +#WC18 +xgxs_tx_lane_map_76=0x0132 +xgxs_rx_lane_map_76=0x0123 + +#WC19 +xgxs_tx_lane_map_80=0x2031 +xgxs_rx_lane_map_80=0x1320 + +#WC8 +xgxs_tx_lane_map_34=0x3021 +xgxs_rx_lane_map_34=0x0213 + +#WC9 +xgxs_tx_lane_map_38=0x3210 +xgxs_rx_lane_map_38=0x1023 + +#WC10 +xgxs_tx_lane_map_42=0x2310 +xgxs_rx_lane_map_42=0x3210 + +#WC11 +xgxs_tx_lane_map_46=0x1032 +xgxs_rx_lane_map_46=0x1302 + +#WC12 +xgxs_tx_lane_map_50=0x3201 +xgxs_rx_lane_map_50=0x0213 + + +#WC13 +xgxs_tx_lane_map_54=0x2301 +xgxs_rx_lane_map_54=0x2310 + +#WC14 +xgxs_tx_lane_map_58=0x3201 +xgxs_rx_lane_map_58=0x0213 + +#WC15 +xgxs_tx_lane_map_62=0x1302 +xgxs_rx_lane_map_62=0x2310 + +#WC20 +xgxs_tx_lane_map_84=0x0213 +xgxs_rx_lane_map_84=0x2301 + +#WC21 +xgxs_tx_lane_map_88=0x0132 +xgxs_rx_lane_map_88=0x3210 + +#WC22 +xgxs_tx_lane_map_92=0x0132 +xgxs_rx_lane_map_92=0x2031 + +#WC23 +xgxs_tx_lane_map_96=0x2031 +xgxs_rx_lane_map_96=0x3201 + +#WC24 +xgxs_tx_lane_map_102=0x0132 +xgxs_rx_lane_map_102=0x2301 + +#WC25 +xgxs_tx_lane_map_106=0x0132 +xgxs_rx_lane_map_106=0x3201 + +#WC26 +xgxs_tx_lane_map_110=0x0132 +xgxs_rx_lane_map_110=0x2031 + +#WC27 +xgxs_tx_lane_map_114=0x2031 +xgxs_rx_lane_map_114=0x2301 + + +#WC0 +xgxs_tx_lane_map_1=0x3210 +xgxs_rx_lane_map_1=0x3120 + +#WC1 +xgxs_tx_lane_map_5=0x0132 +xgxs_rx_lane_map_5=0x1023 + +#WC2 +xgxs_tx_lane_map_9=0x3201 +xgxs_rx_lane_map_9=0x3120 + +#WC3 +xgxs_tx_lane_map_13=0x2031 +xgxs_rx_lane_map_13=0x1032 + +#WC4 +xgxs_tx_lane_map_17=0x2310 +xgxs_rx_lane_map_17=0x3210 + +#WC5 +xgxs_tx_lane_map_21=0x2301 +xgxs_rx_lane_map_21=0x3120 + +#WC6 +xgxs_tx_lane_map_25=0x3201 +xgxs_rx_lane_map_25=0x0213 + +#WC7 +xgxs_tx_lane_map_29=0x1302 +xgxs_rx_lane_map_29=0x1023 + +#WC28 +xgxs_tx_lane_map_118=0x1320 +xgxs_rx_lane_map_118=0x1302 + +#WC29 +xgxs_tx_lane_map_122=0x1032 +xgxs_rx_lane_map_122=0x1023 + +#WC30 +xgxs_tx_lane_map_126=0x3120 +xgxs_rx_lane_map_126=0x3120 + +#WC31 +xgxs_tx_lane_map_130=0x1302 +xgxs_rx_lane_map_130=0x2310 + +#PN + +#WC16 +phy_xaui_tx_polarity_flip_68=0x0000 +phy_xaui_rx_polarity_flip_68=0x0000 + +#WC17 +phy_xaui_tx_polarity_flip_72=0x000D +phy_xaui_rx_polarity_flip_72=0x0002 + + +#WC18 +phy_xaui_tx_polarity_flip_76=0x000F +phy_xaui_rx_polarity_flip_76=0x0000 + +#WC19 +phy_xaui_tx_polarity_flip_80=0x000F +phy_xaui_rx_polarity_flip_80=0x000F + + +#WC8 +phy_xaui_tx_polarity_flip_34=0x000E +phy_xaui_rx_polarity_flip_34=0x0000 + +#WC9 +phy_xaui_tx_polarity_flip_38=0x0008 +phy_xaui_rx_polarity_flip_38=0x0000 + +#WC10 +phy_xaui_tx_polarity_flip_42=0x000D +phy_xaui_rx_polarity_flip_42=0x0000 + +#WC11 +phy_xaui_tx_polarity_flip_46=0x0000 +phy_xaui_rx_polarity_flip_46=0x0000 + + +#WC12 +phy_xaui_tx_polarity_flip_50=0x0002 +phy_xaui_rx_polarity_flip_50=0x0000 + +#WC13 +phy_xaui_tx_polarity_flip_54=0x0002 +phy_xaui_rx_polarity_flip_54=0x0000 + +#WC14 +phy_xaui_tx_polarity_flip_58=0x0000 +phy_xaui_rx_polarity_flip_58=0x0000 + +#WC15 +phy_xaui_tx_polarity_flip_62=0x000A +phy_xaui_rx_polarity_flip_62=0x000F + + +#WC20 + phy_xaui_tx_polarity_flip_84=0x0007 + phy_xaui_rx_polarity_flip_84=0x000E + +#WC21 +phy_xaui_tx_polarity_flip_88=0x000D +phy_xaui_rx_polarity_flip_88=0x000D + +#WC22 +phy_xaui_tx_polarity_flip_92=0x000F +phy_xaui_rx_polarity_flip_92=0x0008 + +#WC23 +phy_xaui_tx_polarity_flip_96=0x0005 +phy_xaui_rx_polarity_flip_96=0x0000 + +#WC24 +phy_xaui_tx_polarity_flip_102=0x0000 +phy_xaui_rx_polarity_flip_102=0x000F + +#WC25 +phy_xaui_tx_polarity_flip_106=0x000F +phy_xaui_rx_polarity_flip_106=0x0000 + +#WC26 +phy_xaui_tx_polarity_flip_110=0x000F +phy_xaui_rx_polarity_flip_110=0x000F + +#WC27 +phy_xaui_tx_polarity_flip_114=0x000F +phy_xaui_rx_polarity_flip_114=0x0007 + +#WC0 +phy_xaui_tx_polarity_flip_1=0x0003 +phy_xaui_rx_polarity_flip_1=0x000F + +#WC1 +phy_xaui_tx_polarity_flip_5=0x0007 +phy_xaui_rx_polarity_flip_5=0x0000 + +#WC2 +phy_xaui_tx_polarity_flip_9=0x0002 +phy_xaui_rx_polarity_flip_9=0x0008 + +#WC3 +phy_xaui_tx_polarity_flip_13=0x000F +phy_xaui_rx_polarity_flip_13=0x0000 + +#WC4 +phy_xaui_tx_polarity_flip_17=0x0007 +phy_xaui_rx_polarity_flip_17=0x0000 + +#WC5 +phy_xaui_tx_polarity_flip_21=0x0000 +phy_xaui_rx_polarity_flip_21=0x0000 + +#WC6 +phy_xaui_tx_polarity_flip_25=0x0002 +phy_xaui_rx_polarity_flip_25=0x0005 + +#WC7 +phy_xaui_tx_polarity_flip_29=0x0002 +phy_xaui_rx_polarity_flip_29=0x0000 + +#WC28 +phy_xaui_tx_polarity_flip_118=0x000F +phy_xaui_rx_polarity_flip_118=0x000F + +#WC29 +phy_xaui_tx_polarity_flip_122=0x0004 +phy_xaui_rx_polarity_flip_122=0x0000 + +#WC30 +phy_xaui_tx_polarity_flip_126=0x000F +phy_xaui_rx_polarity_flip_126=0x0000 + +#WC31 +phy_xaui_tx_polarity_flip_130=0x0006 +phy_xaui_rx_polarity_flip_130=0x0000 + +mmu_init_config="MSFT-TH-Tier0" diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/th-seastone-dx010-32x100G-t1.config.bcm b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/th-seastone-dx010-32x100G-t1.config.bcm new file mode 100644 index 000000000000..effdfb5d7570 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-C32/th-seastone-dx010-32x100G-t1.config.bcm @@ -0,0 +1,696 @@ +# Define default OS / SAL +os=unix + +# all XPORTs to XE ports +#pbmp_xport_xe=0x1fffffffe +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +pbmp_oversubscribe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe + +# Mode control to select L2 Table DMA mode aka L2MODE_POLL (0) or +# L2MOD_FIFO mechanism aka L2MODE_FIFO (1) for L2 table change notification. +l2xmsg_mode=1 + +# Memory table size configs +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +mmu_lossless=0 + +################################################################################### +# Celestica Customize for SeaStone +################################################################################### + +#ext mdio frequency to 495/0x80/2(1.933Mhz) or 415/0x80/2(1.62MHz) +# default is 40 +# Set external MDIO freq to 6.19MHz (495MHz) or 5.19MHz (415MHz) +#* target_freq is core_clock_freq * DIVIDEND / DIVISOR / 2 +# +rate_ext_mdio_divisor=0x80 + +# use internal rom boot +phy_ext_rom_boot=0 + +#fpem_mem_entries=32768 +oversubscribe_mode=1 +#pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + + +dport_map_enable=1 + +dport_map_port_68=1 +dport_map_port_72=5 +dport_map_port_76=9 +dport_map_port_80=13 +dport_map_port_34=17 +dport_map_port_38=21 +dport_map_port_42=25 +dport_map_port_46=29 +dport_map_port_50=33 +dport_map_port_54=37 +dport_map_port_58=41 +dport_map_port_62=45 +dport_map_port_84=49 +dport_map_port_88=53 +dport_map_port_92=57 +dport_map_port_96=61 +dport_map_port_102=65 +dport_map_port_106=69 +dport_map_port_110=73 +dport_map_port_114=77 +dport_map_port_1=81 +dport_map_port_5=85 +dport_map_port_9=89 +dport_map_port_13=93 +dport_map_port_17=97 +dport_map_port_21=101 +dport_map_port_25=105 +dport_map_port_29=109 +dport_map_port_118=113 +dport_map_port_122=117 +dport_map_port_126=121 +dport_map_port_130=125 + + +# port mapping +portmap_68=65:100:4 +portmap_72=69:100:4 +portmap_76=73:100:4 +portmap_80=77:100:4 +portmap_34=33:100:4 +portmap_38=37:100:4 +portmap_42=41:100:4 +portmap_46=45:100:4 +portmap_50=49:100:4 +portmap_54=53:100:4 +portmap_58=57:100:4 +portmap_62=61:100:4 +portmap_84=81:100:4 +portmap_88=85:100:4 +portmap_92=89:100:4 +portmap_96=93:100:4 +portmap_102=97:100:4 +portmap_106=101:100:4 +portmap_110=105:100:4 +portmap_114=109:100:4 +portmap_1=1:100:4 +portmap_5=5:100:4 +portmap_9=9:100:4 +portmap_13=13:100:4 +portmap_17=17:100:4 +portmap_21=21:100:4 +portmap_25=25:100:4 +portmap_29=29:100:4 +portmap_118=113:100:4 +portmap_122=117:100:4 +portmap_126=121:100:4 +portmap_130=125:100:4 +#portmap_66=129:10 +#portmap_100=131:10 + +#WC16 +xgxs_tx_lane_map_68=0x3201 +xgxs_rx_lane_map_68=0x2310 + + +#WC17 +xgxs_tx_lane_map_72=0x3201 +xgxs_rx_lane_map_72=0x2301 + +#WC18 +xgxs_tx_lane_map_76=0x0132 +xgxs_rx_lane_map_76=0x0123 + +#WC19 +xgxs_tx_lane_map_80=0x2031 +xgxs_rx_lane_map_80=0x1320 + +#WC8 +xgxs_tx_lane_map_34=0x3021 +xgxs_rx_lane_map_34=0x0213 + +#WC9 +xgxs_tx_lane_map_38=0x3210 +xgxs_rx_lane_map_38=0x1023 + +#WC10 +xgxs_tx_lane_map_42=0x2310 +xgxs_rx_lane_map_42=0x3210 + +#WC11 +xgxs_tx_lane_map_46=0x1032 +xgxs_rx_lane_map_46=0x1302 + +#WC12 +xgxs_tx_lane_map_50=0x3201 +xgxs_rx_lane_map_50=0x0213 + + +#WC13 +xgxs_tx_lane_map_54=0x2301 +xgxs_rx_lane_map_54=0x2310 + +#WC14 +xgxs_tx_lane_map_58=0x3201 +xgxs_rx_lane_map_58=0x0213 + +#WC15 +xgxs_tx_lane_map_62=0x1302 +xgxs_rx_lane_map_62=0x2310 + +#WC20 +xgxs_tx_lane_map_84=0x0213 +xgxs_rx_lane_map_84=0x2301 + +#WC21 +xgxs_tx_lane_map_88=0x0132 +xgxs_rx_lane_map_88=0x3210 + +#WC22 +xgxs_tx_lane_map_92=0x0132 +xgxs_rx_lane_map_92=0x2031 + +#WC23 +xgxs_tx_lane_map_96=0x2031 +xgxs_rx_lane_map_96=0x3201 + +#WC24 +xgxs_tx_lane_map_102=0x0132 +xgxs_rx_lane_map_102=0x2301 + +#WC25 +xgxs_tx_lane_map_106=0x0132 +xgxs_rx_lane_map_106=0x3201 + +#WC26 +xgxs_tx_lane_map_110=0x0132 +xgxs_rx_lane_map_110=0x2031 + +#WC27 +xgxs_tx_lane_map_114=0x2031 +xgxs_rx_lane_map_114=0x2301 + + +#WC0 +xgxs_tx_lane_map_1=0x3210 +xgxs_rx_lane_map_1=0x3120 + +#WC1 +xgxs_tx_lane_map_5=0x0132 +xgxs_rx_lane_map_5=0x1023 + +#WC2 +xgxs_tx_lane_map_9=0x3201 +xgxs_rx_lane_map_9=0x3120 + +#WC3 +xgxs_tx_lane_map_13=0x2031 +xgxs_rx_lane_map_13=0x1032 + +#WC4 +xgxs_tx_lane_map_17=0x2310 +xgxs_rx_lane_map_17=0x3210 + +#WC5 +xgxs_tx_lane_map_21=0x2301 +xgxs_rx_lane_map_21=0x3120 + +#WC6 +xgxs_tx_lane_map_25=0x3201 +xgxs_rx_lane_map_25=0x0213 + +#WC7 +xgxs_tx_lane_map_29=0x1302 +xgxs_rx_lane_map_29=0x1023 + +#WC28 +xgxs_tx_lane_map_118=0x1320 +xgxs_rx_lane_map_118=0x1302 + +#WC29 +xgxs_tx_lane_map_122=0x1032 +xgxs_rx_lane_map_122=0x1023 + +#WC30 +xgxs_tx_lane_map_126=0x3120 +xgxs_rx_lane_map_126=0x3120 + +#WC31 +xgxs_tx_lane_map_130=0x1302 +xgxs_rx_lane_map_130=0x2310 + +#PN + +#WC16 +phy_xaui_tx_polarity_flip_68=0x0000 +phy_xaui_rx_polarity_flip_68=0x0000 + +#WC17 +phy_xaui_tx_polarity_flip_72=0x000D +phy_xaui_rx_polarity_flip_72=0x0002 + + +#WC18 +phy_xaui_tx_polarity_flip_76=0x000F +phy_xaui_rx_polarity_flip_76=0x0000 + +#WC19 +phy_xaui_tx_polarity_flip_80=0x000F +phy_xaui_rx_polarity_flip_80=0x000F + + +#WC8 +phy_xaui_tx_polarity_flip_34=0x000E +phy_xaui_rx_polarity_flip_34=0x0000 + +#WC9 +phy_xaui_tx_polarity_flip_38=0x0008 +phy_xaui_rx_polarity_flip_38=0x0000 + +#WC10 +phy_xaui_tx_polarity_flip_42=0x000D +phy_xaui_rx_polarity_flip_42=0x0000 + +#WC11 +phy_xaui_tx_polarity_flip_46=0x0000 +phy_xaui_rx_polarity_flip_46=0x0000 + + +#WC12 +phy_xaui_tx_polarity_flip_50=0x0002 +phy_xaui_rx_polarity_flip_50=0x0000 + +#WC13 +phy_xaui_tx_polarity_flip_54=0x0002 +phy_xaui_rx_polarity_flip_54=0x0000 + +#WC14 +phy_xaui_tx_polarity_flip_58=0x0000 +phy_xaui_rx_polarity_flip_58=0x0000 + +#WC15 +phy_xaui_tx_polarity_flip_62=0x000A +phy_xaui_rx_polarity_flip_62=0x000F + + +#WC20 + phy_xaui_tx_polarity_flip_84=0x0007 + phy_xaui_rx_polarity_flip_84=0x000E + +#WC21 +phy_xaui_tx_polarity_flip_88=0x000D +phy_xaui_rx_polarity_flip_88=0x000D + +#WC22 +phy_xaui_tx_polarity_flip_92=0x000F +phy_xaui_rx_polarity_flip_92=0x0008 + +#WC23 +phy_xaui_tx_polarity_flip_96=0x0005 +phy_xaui_rx_polarity_flip_96=0x0000 + +#WC24 +phy_xaui_tx_polarity_flip_102=0x0000 +phy_xaui_rx_polarity_flip_102=0x000F + +#WC25 +phy_xaui_tx_polarity_flip_106=0x000F +phy_xaui_rx_polarity_flip_106=0x0000 + +#WC26 +phy_xaui_tx_polarity_flip_110=0x000F +phy_xaui_rx_polarity_flip_110=0x000F + +#WC27 +phy_xaui_tx_polarity_flip_114=0x000F +phy_xaui_rx_polarity_flip_114=0x0007 + +#WC0 +phy_xaui_tx_polarity_flip_1=0x0003 +phy_xaui_rx_polarity_flip_1=0x000F + +#WC1 +phy_xaui_tx_polarity_flip_5=0x0007 +phy_xaui_rx_polarity_flip_5=0x0000 + +#WC2 +phy_xaui_tx_polarity_flip_9=0x0002 +phy_xaui_rx_polarity_flip_9=0x0008 + +#WC3 +phy_xaui_tx_polarity_flip_13=0x000F +phy_xaui_rx_polarity_flip_13=0x0000 + +#WC4 +phy_xaui_tx_polarity_flip_17=0x0007 +phy_xaui_rx_polarity_flip_17=0x0000 + +#WC5 +phy_xaui_tx_polarity_flip_21=0x0000 +phy_xaui_rx_polarity_flip_21=0x0000 + +#WC6 +phy_xaui_tx_polarity_flip_25=0x0002 +phy_xaui_rx_polarity_flip_25=0x0005 + +#WC7 +phy_xaui_tx_polarity_flip_29=0x0002 +phy_xaui_rx_polarity_flip_29=0x0000 + +#WC28 +phy_xaui_tx_polarity_flip_118=0x000F +phy_xaui_rx_polarity_flip_118=0x000F + +#WC29 +phy_xaui_tx_polarity_flip_122=0x0004 +phy_xaui_rx_polarity_flip_122=0x0000 + +#WC30 +phy_xaui_tx_polarity_flip_126=0x000F +phy_xaui_rx_polarity_flip_126=0x0000 + +#WC31 +phy_xaui_tx_polarity_flip_130=0x0006 +phy_xaui_rx_polarity_flip_130=0x0000 + +#ce0 +serdes_driver_current_lane0_68=0x0b +serdes_driver_current_lane1_68=0x0b +serdes_driver_current_lane2_68=0x0b +serdes_driver_current_lane3_68=0x0b +serdes_preemphasis_lane0_68=0x2d3f04 +serdes_preemphasis_lane1_68=0x2b4104 +serdes_preemphasis_lane2_68=0x2b4104 +serdes_preemphasis_lane3_68=0x2d3f04 + +#ce1 +serdes_driver_current_lane0_72=0x0b +serdes_driver_current_lane1_72=0x0a +serdes_driver_current_lane2_72=0x0a +serdes_driver_current_lane3_72=0x0b +serdes_preemphasis_lane0_72=0x2b4104 +serdes_preemphasis_lane1_72=0x294403 +serdes_preemphasis_lane2_72=0x294403 +serdes_preemphasis_lane3_72=0x2b4104 + +#ce2 +serdes_driver_current_lane0_76=0x0a +serdes_driver_current_lane1_76=0x0a +serdes_driver_current_lane2_76=0x0a +serdes_driver_current_lane3_76=0x0a +serdes_preemphasis_lane0_76=0x294403 +serdes_preemphasis_lane1_76=0x294403 +serdes_preemphasis_lane2_76=0x294403 +serdes_preemphasis_lane3_76=0x294403 + +#ce3 +serdes_driver_current_lane0_80=0x0a +serdes_driver_current_lane1_80=0x0a +serdes_driver_current_lane2_80=0x0a +serdes_driver_current_lane3_80=0x0a +serdes_preemphasis_lane0_80=0x254902 +serdes_preemphasis_lane1_80=0x254902 +serdes_preemphasis_lane2_80=0x294403 +serdes_preemphasis_lane3_80=0x294403 + +#ce4 +serdes_driver_current_lane0_34=0x0b +serdes_driver_current_lane1_34=0x0b +serdes_driver_current_lane2_34=0x0b +serdes_driver_current_lane3_34=0x0b +serdes_preemphasis_lane0_34=0x2b4104 +serdes_preemphasis_lane1_34=0x2d3f04 +serdes_preemphasis_lane2_34=0x2d3f04 +serdes_preemphasis_lane3_34=0x2b4104 + +#ce5 +serdes_driver_current_lane0_38=0x0a +serdes_driver_current_lane1_38=0x0b +serdes_driver_current_lane2_38=0x0b +serdes_driver_current_lane3_38=0x0b +serdes_preemphasis_lane0_38=0x294403 +serdes_preemphasis_lane1_38=0x2b4104 +serdes_preemphasis_lane2_38=0x2b4104 +serdes_preemphasis_lane3_38=0x2b4104 + +#ce6 +serdes_driver_current_lane0_42=0x0a +serdes_driver_current_lane1_42=0x0b +serdes_driver_current_lane2_42=0x0a +serdes_driver_current_lane3_42=0x0a +serdes_preemphasis_lane0_42=0x294403 +serdes_preemphasis_lane1_42=0x2b4104 +serdes_preemphasis_lane2_42=0x294403 +serdes_preemphasis_lane3_42=0x294403 + +#ce7 +serdes_driver_current_lane0_46=0x0a +serdes_driver_current_lane1_46=0x0a +serdes_driver_current_lane2_46=0x0a +serdes_driver_current_lane3_46=0x0a +serdes_preemphasis_lane0_46=0x254902 +serdes_preemphasis_lane1_46=0x294403 +serdes_preemphasis_lane2_46=0x254902 +serdes_preemphasis_lane3_46=0x294403 + +#ce8 +serdes_driver_current_lane0_50=0x0a +serdes_driver_current_lane1_50=0x0a +serdes_driver_current_lane2_50=0x0a +serdes_driver_current_lane3_50=0x0a +serdes_preemphasis_lane0_50=0x294403 +serdes_preemphasis_lane1_50=0x254902 +serdes_preemphasis_lane2_50=0x254902 +serdes_preemphasis_lane3_50=0x254902 + +#ce9 +serdes_driver_current_lane0_54=0x0a +serdes_driver_current_lane1_54=0x09 +serdes_driver_current_lane2_54=0x0a +serdes_driver_current_lane3_54=0x09 +serdes_preemphasis_lane0_54=0x254902 +serdes_preemphasis_lane1_54=0x244a02 +serdes_preemphasis_lane2_54=0x254902 +serdes_preemphasis_lane3_54=0x244a02 + +#ce10 +serdes_driver_current_lane0_58=0x0a +serdes_driver_current_lane1_58=0x09 +serdes_driver_current_lane2_58=0x09 +serdes_driver_current_lane3_58=0x0a +serdes_preemphasis_lane0_58=0x254902 +serdes_preemphasis_lane1_58=0x244a02 +serdes_preemphasis_lane2_58=0x244a02 +serdes_preemphasis_lane3_58=0x254902 + +#ce11 +serdes_driver_current_lane0_62=0x09 +serdes_driver_current_lane1_62=0x0a +serdes_driver_current_lane2_62=0x09 +serdes_driver_current_lane3_62=0x09 +serdes_preemphasis_lane0_62=0x244a02 +serdes_preemphasis_lane1_62=0x254902 +serdes_preemphasis_lane2_62=0x244a02 +serdes_preemphasis_lane3_62=0x244a02 + +#ce12 +serdes_driver_current_lane0_84=0x09 +serdes_driver_current_lane1_84=0x09 +serdes_driver_current_lane2_84=0x09 +serdes_driver_current_lane3_84=0x09 +serdes_preemphasis_lane0_84=0x204e02 +serdes_preemphasis_lane1_84=0x204e02 +serdes_preemphasis_lane2_84=0x204e02 +serdes_preemphasis_lane3_84=0x204e02 + +#ce13 +serdes_driver_current_lane0_88=0x09 +serdes_driver_current_lane1_88=0x08 +serdes_driver_current_lane2_88=0x08 +serdes_driver_current_lane3_88=0x09 +serdes_preemphasis_lane0_88=0x204e02 +serdes_preemphasis_lane1_88=0x1d5102 +serdes_preemphasis_lane2_88=0x1d5102 +serdes_preemphasis_lane3_88=0x204e02 + +#ce14 +serdes_driver_current_lane0_92=0x09 +serdes_driver_current_lane1_92=0x08 +serdes_driver_current_lane2_92=0x08 +serdes_driver_current_lane3_92=0x09 +serdes_preemphasis_lane0_92=0x204e02 +serdes_preemphasis_lane1_92=0x1d5102 +serdes_preemphasis_lane2_92=0x1d5102 +serdes_preemphasis_lane3_92=0x204e02 + +#ce15 +serdes_driver_current_lane0_96=0x08 +serdes_driver_current_lane1_96=0x08 +serdes_driver_current_lane2_96=0x09 +serdes_driver_current_lane3_96=0x09 +serdes_preemphasis_lane0_96=0x1d5102 +serdes_preemphasis_lane1_96=0x1d5102 +serdes_preemphasis_lane2_96=0x204e02 +serdes_preemphasis_lane3_96=0x204e02 + +#ce16 +serdes_driver_current_lane0_102=0x09 +serdes_driver_current_lane1_102=0x08 +serdes_driver_current_lane2_102=0x08 +serdes_driver_current_lane3_102=0x09 +serdes_preemphasis_lane0_102=0x204e02 +serdes_preemphasis_lane1_102=0x1d5102 +serdes_preemphasis_lane2_102=0x1d5102 +serdes_preemphasis_lane3_102=0x224c02 + +#ce17 +serdes_driver_current_lane0_106=0x09 +serdes_driver_current_lane1_106=0x08 +serdes_driver_current_lane2_106=0x08 +serdes_driver_current_lane3_106=0x09 +serdes_preemphasis_lane0_106=0x204e02 +serdes_preemphasis_lane1_106=0x1d5102 +serdes_preemphasis_lane2_106=0x1d5102 +serdes_preemphasis_lane3_106=0x204e02 + +#ce18 +serdes_driver_current_lane0_110=0x09 +serdes_driver_current_lane1_110=0x08 +serdes_driver_current_lane2_110=0x08 +serdes_driver_current_lane3_110=0x09 +serdes_preemphasis_lane0_110=0x204e02 +serdes_preemphasis_lane1_110=0x1d5102 +serdes_preemphasis_lane2_110=0x1d5102 +serdes_preemphasis_lane3_110=0x204e02 + +#ce19 +serdes_driver_current_lane0_114=0x09 +serdes_driver_current_lane1_114=0x08 +serdes_driver_current_lane2_114=0x09 +serdes_driver_current_lane3_114=0x09 +serdes_preemphasis_lane0_114=0x204e02 +serdes_preemphasis_lane1_114=0x1d5102 +serdes_preemphasis_lane2_114=0x224c02 +serdes_preemphasis_lane3_114=0x224c02 + +#ce20 +serdes_driver_current_lane0_1=0x09 +serdes_driver_current_lane1_1=0x0a +serdes_driver_current_lane2_1=0x09 +serdes_driver_current_lane3_1=0x0a +serdes_preemphasis_lane0_1=0x244a02 +serdes_preemphasis_lane1_1=0x254902 +serdes_preemphasis_lane2_1=0x244a02 +serdes_preemphasis_lane3_1=0x254902 + +#ce21 +serdes_driver_current_lane0_5=0x09 +serdes_driver_current_lane1_5=0x09 +serdes_driver_current_lane2_5=0x09 +serdes_driver_current_lane3_5=0x0a +serdes_preemphasis_lane0_5=0x244a02 +serdes_preemphasis_lane1_5=0x244a02 +serdes_preemphasis_lane2_5=0x244a02 +serdes_preemphasis_lane3_5=0x254902 + +#ce22 +serdes_driver_current_lane0_9=0x0a +serdes_driver_current_lane1_9=0x0a +serdes_driver_current_lane2_9=0x0a +serdes_driver_current_lane3_9=0x0a +serdes_preemphasis_lane0_9=0x254902 +serdes_preemphasis_lane1_9=0x254902 +serdes_preemphasis_lane2_9=0x254902 +serdes_preemphasis_lane3_9=0x294403 + +#ce23 +serdes_driver_current_lane0_13=0x09 +serdes_driver_current_lane1_13=0x0a +serdes_driver_current_lane2_13=0x0a +serdes_driver_current_lane3_13=0x0a +serdes_preemphasis_lane0_13=0x244a02 +serdes_preemphasis_lane1_13=0x254902 +serdes_preemphasis_lane2_13=0x294403 +serdes_preemphasis_lane3_13=0x294403 + +#ce24 +serdes_driver_current_lane0_17=0x0a +serdes_driver_current_lane1_17=0x0a +serdes_driver_current_lane2_17=0x0a +serdes_driver_current_lane3_17=0x0a +serdes_preemphasis_lane0_17=0x254902 +serdes_preemphasis_lane1_17=0x294403 +serdes_preemphasis_lane2_17=0x294403 +serdes_preemphasis_lane3_17=0x294403 + +#ce25 +serdes_driver_current_lane0_21=0x0a +serdes_driver_current_lane1_21=0x0a +serdes_driver_current_lane2_21=0x0a +serdes_driver_current_lane3_21=0x0a +serdes_preemphasis_lane0_21=0x294403 +serdes_preemphasis_lane1_21=0x294403 +serdes_preemphasis_lane2_21=0x294403 +serdes_preemphasis_lane3_21=0x254902 + +#ce26 +serdes_driver_current_lane0_25=0x0b +serdes_driver_current_lane1_25=0x0b +serdes_driver_current_lane2_25=0x0b +serdes_driver_current_lane3_25=0x0b +serdes_preemphasis_lane0_25=0x2b4104 +serdes_preemphasis_lane1_25=0x2b4104 +serdes_preemphasis_lane2_25=0x2b4104 +serdes_preemphasis_lane3_25=0x2d3f04 + +#ce27 +serdes_driver_current_lane0_29=0x0b +serdes_driver_current_lane1_29=0x0b +serdes_driver_current_lane2_29=0x0b +serdes_driver_current_lane3_29=0x0a +serdes_preemphasis_lane0_29=0x2d3f04 +serdes_preemphasis_lane1_29=0x2d3f04 +serdes_preemphasis_lane2_29=0x2b4104 +serdes_preemphasis_lane3_29=0x294403 + +#ce28 +serdes_driver_current_lane0_118=0x0a +serdes_driver_current_lane1_118=0x0a +serdes_driver_current_lane2_118=0x0a +serdes_driver_current_lane3_118=0x0a +serdes_preemphasis_lane0_118=0x254902 +serdes_preemphasis_lane1_118=0x294403 +serdes_preemphasis_lane2_118=0x294403 +serdes_preemphasis_lane3_118=0x254902 + +#ce29 +serdes_driver_current_lane0_122=0x0a +serdes_driver_current_lane1_122=0x0a +serdes_driver_current_lane2_122=0x0a +serdes_driver_current_lane3_122=0x0a +serdes_preemphasis_lane0_122=0x294403 +serdes_preemphasis_lane1_122=0x294403 +serdes_preemphasis_lane2_122=0x294403 +serdes_preemphasis_lane3_122=0x294403 + +#ce30 +serdes_driver_current_lane0_126=0x0a +serdes_driver_current_lane1_126=0x0a +serdes_driver_current_lane2_126=0x0b +serdes_driver_current_lane3_126=0x0b +serdes_preemphasis_lane0_126=0x294403 +serdes_preemphasis_lane1_126=0x294403 +serdes_preemphasis_lane2_126=0x2b4104 +serdes_preemphasis_lane3_126=0x2b4104 + +#ce31 +serdes_driver_current_lane0_130=0x0b +serdes_driver_current_lane1_130=0x0b +serdes_driver_current_lane2_130=0x0b +serdes_driver_current_lane3_130=0x0b +serdes_preemphasis_lane0_130=0x2d3f04 +serdes_preemphasis_lane1_130=0x2d3f04 +serdes_preemphasis_lane2_130=0x2b4104 +serdes_preemphasis_lane3_130=0x2b4104 + +mmu_init_config="MSFT-TH-Tier1" diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/buffers.json.j2 b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/buffers_defaults_t0.j2 b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..4e4489f84a87 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/buffers_defaults_t0.j2 @@ -0,0 +1,69 @@ + +{%- set default_cable = '5m' %} + +{%- set ports2cable = { + 'torrouter_server' : '300m', + 'leafrouter_torrouter' : '300m', + 'spinerouter_leafrouter' : '300m' + } +-%} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,9) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(14,17) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(22,31) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(10,13) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(18,21) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/pg_profile_lookup.ini b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/pg_profile_lookup.ini new file mode 100644 index 000000000000..673df369a9bb --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 0 2288 + 25000 5m 1248 2288 53248 0 2288 + 40000 5m 1248 2288 66560 0 2288 + 50000 5m 1248 2288 90272 0 2288 + 100000 5m 1248 2288 165568 0 2288 + 10000 40m 1248 2288 37024 0 2288 + 25000 40m 1248 2288 53248 0 2288 + 40000 40m 1248 2288 71552 0 2288 + 50000 40m 1248 2288 96096 0 2288 + 100000 40m 1248 2288 177632 0 2288 + 10000 300m 1248 2288 46176 0 2288 + 25000 300m 1248 2288 79040 0 2288 + 40000 300m 1248 2288 108160 0 2288 + 50000 300m 1248 2288 141856 0 2288 + 100000 300m 1248 2288 268736 0 2288 diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/port_config.ini new file mode 100644 index 000000000000..7595dfbb3fed --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias speed index +Ethernet0 65,66 etp1a 50000 1 +Ethernet2 67,68 etp1b 50000 1 +Ethernet4 69,70 etp2a 50000 2 +Ethernet6 71,72 etp2b 50000 2 +Ethernet8 73,74 etp3a 50000 3 +Ethernet10 75,76 etp3b 50000 3 +Ethernet12 77,78 etp4a 50000 4 +Ethernet14 79,80 etp4b 50000 4 +Ethernet16 33,34 etp5a 50000 5 +Ethernet18 35,36 etp5b 50000 5 +Ethernet20 37,38 etp6a 50000 6 +Ethernet22 39,40 etp6b 50000 6 +Ethernet24 41,42 etp7a 50000 7 +Ethernet26 43,44 etp7b 50000 7 +Ethernet28 45,46 etp8a 50000 8 +Ethernet30 47,48 etp8b 50000 8 +Ethernet32 49,50 etp9a 50000 9 +Ethernet34 51,52 etp9b 50000 9 +Ethernet36 53,54 etp10a 50000 10 +Ethernet38 55,56 etp10b 50000 10 +Ethernet40 57,58,59,60 etp11 100000 11 +Ethernet44 61,62,63,64 etp12 100000 12 +Ethernet48 81,82,83,84 etp13 100000 13 +Ethernet52 85,86,87,88 etp14 100000 14 +Ethernet56 89,90 etp15a 50000 15 +Ethernet58 91,92 etp15b 50000 15 +Ethernet60 93,94 etp16a 50000 16 +Ethernet62 95,96 etp16b 50000 16 +Ethernet64 97,98 etp17a 50000 17 +Ethernet66 99,100 etp17b 50000 17 +Ethernet68 101,102 etp18a 50000 18 +Ethernet70 103,104 etp18b 50000 18 +Ethernet72 105,106,107,108 etp19 100000 19 +Ethernet76 109,110,111,112 etp20 100000 20 +Ethernet80 1,2,3,4 etp21 100000 21 +Ethernet84 5,6,7,8 etp22 100000 22 +Ethernet88 9,10 etp23a 50000 23 +Ethernet90 11,12 etp23b 50000 23 +Ethernet92 13,14 etp24a 50000 24 +Ethernet94 15,16 etp24b 50000 24 +Ethernet96 17,18 etp25a 50000 25 +Ethernet98 19,20 etp25b 50000 25 +Ethernet100 21,22 etp26a 50000 26 +Ethernet102 23,24 etp26b 50000 26 +Ethernet104 25,26 etp27a 50000 27 +Ethernet106 27,28 etp27b 50000 27 +Ethernet108 29,30 etp28a 50000 28 +Ethernet110 31,32 etp28b 50000 28 +Ethernet112 113,114 etp29a 50000 29 +Ethernet114 115,116 etp29b 50000 29 +Ethernet116 117,118 etp30a 50000 30 +Ethernet118 119,120 etp30b 50000 30 +Ethernet120 121,122 etp31a 50000 31 +Ethernet122 123,124 etp31b 50000 31 +Ethernet124 125,126 etp32a 50000 32 +Ethernet126 127,128 etp32b 50000 32 diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/qos.json.j2 b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/qos.json.j2 new file mode 100644 index 000000000000..34002048afdb --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/qos.json.j2 @@ -0,0 +1,21 @@ +{%- macro generate_wred_profiles() %} + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "250000", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, +{%- endmacro %} + +{%- include 'qos_config.j2' %} diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/sai.profile new file mode 100644 index 000000000000..50220639519c --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-seastone-dx010-48x50G+8x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/th-seastone-dx010-48x50G+8x100G.config.bcm b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/th-seastone-dx010-48x50G+8x100G.config.bcm new file mode 100644 index 000000000000..6707aa71df09 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Celestica-DX010-D48C8/th-seastone-dx010-48x50G+8x100G.config.bcm @@ -0,0 +1,648 @@ +os=unix +l2xmsg_mode=1 +parity_enable=0 +rate_ext_mdio_divisor=0x80 +phy_ext_rom_boot=0 +fpem_mem_entries=32768 +l2xmsg_mode=1 +oversubscribe_mode=1 +pbmp_xport_xe=0xcccc44cc33113333044cccccc66666622 + + +dport_map_enable=1 +dport_map_port_68=1 +dport_map_port_69=2 + +dport_map_port_72=5 +dport_map_port_73=6 + +dport_map_port_76=9 +dport_map_port_77=10 + +dport_map_port_80=13 +dport_map_port_81=14 + +dport_map_port_34=17 +dport_map_port_35=18 + +dport_map_port_38=21 +dport_map_port_39=22 + +dport_map_port_42=25 +dport_map_port_43=26 + +dport_map_port_46=29 +dport_map_port_47=30 + +dport_map_port_50=33 +dport_map_port_51=34 + +dport_map_port_54=37 +dport_map_port_55=38 + +dport_map_port_58=41 + +dport_map_port_62=45 + +dport_map_port_84=49 + +dport_map_port_88=53 + +dport_map_port_92=57 +dport_map_port_93=58 + +dport_map_port_96=61 +dport_map_port_97=62 + +dport_map_port_102=65 +dport_map_port_103=66 + +dport_map_port_106=69 +dport_map_port_107=70 + +dport_map_port_110=73 + +dport_map_port_114=77 + +dport_map_port_1=81 + +dport_map_port_5=85 + +dport_map_port_9=89 +dport_map_port_10=90 + +dport_map_port_13=93 +dport_map_port_14=94 + +dport_map_port_17=97 +dport_map_port_18=98 + +dport_map_port_21=101 +dport_map_port_22=102 + +dport_map_port_25=105 +dport_map_port_26=106 + +dport_map_port_29=109 +dport_map_port_30=110 + +dport_map_port_118=113 +dport_map_port_119=114 + +dport_map_port_122=117 +dport_map_port_123=118 + +dport_map_port_126=121 +dport_map_port_127=122 + +dport_map_port_130=125 +dport_map_port_131=126 + + +# port mapping +portmap_68=65:50:2 +portmap_69=67:50:2 + +portmap_72=69:50:2 +portmap_73=71:50:2 + +portmap_76=73:50:2 +portmap_77=75:50:2 + +portmap_80=77:50:2 +portmap_81=79:50:2 + +portmap_34=33:50:2 +portmap_35=35:50:2 + +portmap_38=37:50:2 +portmap_39=39:50:2 + +portmap_42=41:50:2 +portmap_43=43:50:2 + +portmap_46=45:50:2 +portmap_47=47:50:2 + +portmap_50=49:50:2 +portmap_51=51:50:2 + +portmap_54=53:50:2 +portmap_55=55:50:2 + +portmap_58=57:100:4 + +portmap_62=61:100:4 + +portmap_84=81:100:4 + +portmap_88=85:100:4 + +portmap_92=89:50:2 +portmap_93=91:50:2 + +portmap_96=93:50:2 +portmap_97=95:50:2 + +portmap_102=97:50:2 +portmap_103=99:50:2 + +portmap_106=101:50:2 +portmap_107=103:50:2 + +portmap_110=105:100:4 + +portmap_114=109:100:4 + +portmap_1=1:100:4 + +portmap_5=5:100:4 + +portmap_9=9:50:2 +portmap_10=11:50:2 + +portmap_13=13:50:2 +portmap_14=15:50:2 + +portmap_17=17:50:2 +portmap_18=19:50:2 + +portmap_21=21:50:2 +portmap_22=23:50:2 + +portmap_25=25:50:2 +portmap_26=27:50:2 + +portmap_29=29:50:2 +portmap_30=31:50:2 + +portmap_118=113:50:2 +portmap_119=115:50:2 + +portmap_122=117:50:2 +portmap_123=119:50:2 + +portmap_126=121:50:2 +portmap_127=123:50:2 + +portmap_130=125:50:2 +portmap_131=127:50:2 + + +#WC16 +xgxs_tx_lane_map_68=0x1023 +xgxs_rx_lane_map_68=0x0132 +xgxs_tx_lane_map_69=0x1023 +xgxs_rx_lane_map_69=0x0132 + + +#WC17 +xgxs_tx_lane_map_72=0x1023 +xgxs_rx_lane_map_72=0x1032 +xgxs_tx_lane_map_73=0x1023 +xgxs_rx_lane_map_73=0x1032 + +#WC18 +xgxs_tx_lane_map_76=0x2310 +xgxs_rx_lane_map_76=0x3210 +xgxs_tx_lane_map_77=0x2310 +xgxs_rx_lane_map_77=0x3210 + +#WC19 +xgxs_tx_lane_map_80=0x1302 +xgxs_rx_lane_map_80=0x0231 +xgxs_tx_lane_map_81=0x1302 +xgxs_rx_lane_map_81=0x0231 +#WC8 +xgxs_tx_lane_map_34=0x1203 +xgxs_rx_lane_map_34=0x3120 +xgxs_tx_lane_map_35=0x1203 +xgxs_rx_lane_map_35=0x3120 + +#WC9 +xgxs_tx_lane_map_38=0x0123 +xgxs_rx_lane_map_38=0x3201 +xgxs_tx_lane_map_39=0x0123 +xgxs_rx_lane_map_39=0x3201 + +#WC10 +xgxs_tx_lane_map_42=0x0132 +xgxs_rx_lane_map_42=0x0123 +xgxs_tx_lane_map_43=0x0132 +xgxs_rx_lane_map_43=0x0123 + +#WC11 +xgxs_tx_lane_map_46=0x2301 +xgxs_rx_lane_map_46=0x2031 +xgxs_tx_lane_map_47=0x2301 +xgxs_rx_lane_map_47=0x2031 + +#WC12 +xgxs_tx_lane_map_50=0x1032 +xgxs_rx_lane_map_50=0x3120 +xgxs_tx_lane_map_51=0x1032 +xgxs_rx_lane_map_51=0x3120 + + +#WC13 +xgxs_tx_lane_map_54=0x1032 +xgxs_rx_lane_map_54=0x0132 +xgxs_tx_lane_map_55=0x1032 +xgxs_rx_lane_map_55=0x0132 + +#WC14 + xgxs_tx_lane_map_58=0x1032 + xgxs_rx_lane_map_58=0x3120 + +#WC15 +xgxs_tx_lane_map_62=0x2031 +xgxs_rx_lane_map_62=0x0132 + +#WC20 + xgxs_tx_lane_map_84=0x3120 + xgxs_rx_lane_map_84=0x1032 + +#WC21 +xgxs_tx_lane_map_88=0x2310 +xgxs_rx_lane_map_88=0x0123 + +#WC22 +xgxs_tx_lane_map_92=0x2310 +xgxs_rx_lane_map_92=0x1302 +xgxs_tx_lane_map_93=0x2310 +xgxs_rx_lane_map_93=0x1302 + +#WC23 +xgxs_tx_lane_map_96=0x1302 +xgxs_rx_lane_map_96=0x1023 +xgxs_tx_lane_map_97=0x1302 +xgxs_rx_lane_map_97=0x1023 + +#WC24 +xgxs_tx_lane_map_102=0x2310 +xgxs_rx_lane_map_102=0x1032 +xgxs_tx_lane_map_103=0x2310 +xgxs_rx_lane_map_103=0x1032 + +#WC25 +xgxs_tx_lane_map_106=0x2310 +xgxs_rx_lane_map_106=0x1023 +xgxs_tx_lane_map_107=0x2310 +xgxs_rx_lane_map_107=0x1023 + +#WC26 +xgxs_tx_lane_map_110=0x2310 +xgxs_rx_lane_map_110=0x1302 + +#WC27 +xgxs_tx_lane_map_114=0x1302 +xgxs_rx_lane_map_114=0x1032 + +#WC0 +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x0213 + +#WC1 +xgxs_tx_lane_map_5=0x2310 +xgxs_rx_lane_map_5=0x3201 + +#WC2 +xgxs_tx_lane_map_9=0x1023 +xgxs_rx_lane_map_9=0x0213 +xgxs_tx_lane_map_10=0x1023 +xgxs_rx_lane_map_10=0x0213 + +#WC3 +xgxs_tx_lane_map_13=0x1302 +xgxs_rx_lane_map_13=0x3201 +xgxs_tx_lane_map_14=0x1302 +xgxs_rx_lane_map_14=0x3201 + +#WC4 +xgxs_tx_lane_map_17=0x0132 +xgxs_rx_lane_map_17=0x0123 +xgxs_tx_lane_map_18=0x0132 +xgxs_rx_lane_map_18=0x0123 + +#WC5 +xgxs_tx_lane_map_21=0x1032 +xgxs_rx_lane_map_21=0x0213 +xgxs_tx_lane_map_22=0x1032 +xgxs_rx_lane_map_22=0x0213 + +#WC6 +xgxs_tx_lane_map_25=0x1023 +xgxs_rx_lane_map_25=0x3120 +xgxs_tx_lane_map_26=0x1023 +xgxs_rx_lane_map_26=0x3120 + +#WC7 +xgxs_tx_lane_map_29=0x2031 +xgxs_rx_lane_map_29=0x3201 +xgxs_tx_lane_map_30=0x2031 +xgxs_rx_lane_map_30=0x3201 + +#WC28 +xgxs_tx_lane_map_118=0x0231 +xgxs_rx_lane_map_118=0x2031 +xgxs_tx_lane_map_119=0x0231 +xgxs_rx_lane_map_119=0x2031 + +#WC29 +xgxs_tx_lane_map_122=0x3201 +xgxs_rx_lane_map_122=0x2301 +xgxs_tx_lane_map_123=0x3201 +xgxs_rx_lane_map_123=0x2301 + +#WC30 +xgxs_tx_lane_map_126=0x0213 +xgxs_rx_lane_map_126=0x0213 +xgxs_tx_lane_map_127=0x0213 +xgxs_rx_lane_map_127=0x0213 + +#WC31 +xgxs_tx_lane_map_130=0x2031 +xgxs_rx_lane_map_130=0x1032 +xgxs_tx_lane_map_131=0x2031 +xgxs_rx_lane_map_131=0x1032 + +#PN + +#WC16 +phy_xaui_tx_polarity_flip_68=0x0000 +phy_xaui_rx_polarity_flip_68=0x0000 +phy_xaui_tx_polarity_flip_69=0x0000 +phy_xaui_rx_polarity_flip_69=0x0000 + +#WC17 +phy_xaui_tx_polarity_flip_72=0x0003 +phy_xaui_rx_polarity_flip_72=0x0000 +phy_xaui_tx_polarity_flip_73=0x0002 +phy_xaui_rx_polarity_flip_73=0x0001 + + + +#WC18 +phy_xaui_tx_polarity_flip_76=0x0003 +phy_xaui_rx_polarity_flip_76=0x0000 +phy_xaui_tx_polarity_flip_77=0x0003 +phy_xaui_rx_polarity_flip_77=0x0000 + + +#WC19 +phy_xaui_tx_polarity_flip_80=0x0003 +phy_xaui_rx_polarity_flip_80=0x0003 +phy_xaui_tx_polarity_flip_81=0x0003 +phy_xaui_rx_polarity_flip_81=0x0003 + + +#WC8 +phy_xaui_tx_polarity_flip_34=0x0003 +phy_xaui_rx_polarity_flip_34=0x0000 +phy_xaui_tx_polarity_flip_35=0x0001 +phy_xaui_rx_polarity_flip_35=0x0000 + + +#WC9 +phy_xaui_tx_polarity_flip_38=0x0001 +phy_xaui_rx_polarity_flip_38=0x0000 +phy_xaui_tx_polarity_flip_39=0x0000 +phy_xaui_rx_polarity_flip_39=0x0000 + + +#WC10 +phy_xaui_tx_polarity_flip_42=0x0003 +phy_xaui_rx_polarity_flip_42=0x0000 +phy_xaui_tx_polarity_flip_43=0x0002 +phy_xaui_rx_polarity_flip_43=0x0000 + + +#WC11 +phy_xaui_tx_polarity_flip_46=0x0000 +phy_xaui_rx_polarity_flip_46=0x0000 +phy_xaui_tx_polarity_flip_47=0x0000 +phy_xaui_rx_polarity_flip_47=0x0000 + + +#WC12 +phy_xaui_tx_polarity_flip_50=0x0000 +phy_xaui_rx_polarity_flip_50=0x0000 +phy_xaui_tx_polarity_flip_51=0x0001 +phy_xaui_rx_polarity_flip_51=0x0000 + +#WC13 +phy_xaui_tx_polarity_flip_54=0x0000 +phy_xaui_rx_polarity_flip_54=0x0000 +phy_xaui_tx_polarity_flip_55=0x0001 +phy_xaui_rx_polarity_flip_55=0x0000 + +#WC14 +phy_xaui_tx_polarity_flip_58=0x0000 +phy_xaui_rx_polarity_flip_58=0x0000 + +#WC15 +phy_xaui_tx_polarity_flip_62=0x0005 +phy_xaui_rx_polarity_flip_62=0x000F + +#WC20 + phy_xaui_tx_polarity_flip_84=0x000E + phy_xaui_rx_polarity_flip_84=0x0007 + +#WC21 +phy_xaui_tx_polarity_flip_88=0x000B +phy_xaui_rx_polarity_flip_88=0x000B + +#WC22 +phy_xaui_tx_polarity_flip_92=0x0003 +phy_xaui_rx_polarity_flip_92=0x0001 +phy_xaui_tx_polarity_flip_93=0x0003 +phy_xaui_rx_polarity_flip_93=0x0000 + + +#WC23 +phy_xaui_tx_polarity_flip_96=0x0002 +phy_xaui_rx_polarity_flip_96=0x0000 +phy_xaui_tx_polarity_flip_97=0x0002 +phy_xaui_rx_polarity_flip_97=0x0000 + +#WC24 +phy_xaui_tx_polarity_flip_102=0x0000 +phy_xaui_rx_polarity_flip_102=0x0003 +phy_xaui_tx_polarity_flip_103=0x0000 +phy_xaui_rx_polarity_flip_103=0x0003 + + +#WC25 +phy_xaui_tx_polarity_flip_106=0x0003 +phy_xaui_rx_polarity_flip_106=0x0000 +phy_xaui_tx_polarity_flip_107=0x0003 +phy_xaui_rx_polarity_flip_107=0x0000 + +#WC26 +phy_xaui_tx_polarity_flip_110=0x000F +phy_xaui_rx_polarity_flip_110=0x000F + +#WC27 +phy_xaui_tx_polarity_flip_114=0x000F +phy_xaui_rx_polarity_flip_114=0x000E + +#WC0 +phy_xaui_tx_polarity_flip_1=0x000C +phy_xaui_rx_polarity_flip_1=0x000F + +#WC1 +phy_xaui_tx_polarity_flip_5=0x000E +phy_xaui_rx_polarity_flip_5=0x0000 + +#WC2 +phy_xaui_tx_polarity_flip_9=0x0000 +phy_xaui_rx_polarity_flip_9=0x0001 +phy_xaui_tx_polarity_flip_10=0x0001 +phy_xaui_rx_polarity_flip_10=0x0000 + + +#WC3 +phy_xaui_tx_polarity_flip_13=0x0003 +phy_xaui_rx_polarity_flip_13=0x0000 +phy_xaui_tx_polarity_flip_14=0x0003 +phy_xaui_rx_polarity_flip_14=0x0000 + +#WC4 +phy_xaui_tx_polarity_flip_17=0x0002 +phy_xaui_rx_polarity_flip_17=0x0000 +phy_xaui_tx_polarity_flip_18=0x0003 +phy_xaui_rx_polarity_flip_18=0x0000 + + +#WC5 +phy_xaui_tx_polarity_flip_21=0x0000 +phy_xaui_rx_polarity_flip_21=0x0000 +phy_xaui_tx_polarity_flip_22=0x0000 +phy_xaui_rx_polarity_flip_22=0x0000 + + +#WC6 +phy_xaui_tx_polarity_flip_25=0x0000 +phy_xaui_rx_polarity_flip_25=0x0002 +phy_xaui_tx_polarity_flip_26=0x0001 +phy_xaui_rx_polarity_flip_26=0x0002 + + +#WC7 +phy_xaui_tx_polarity_flip_29=0x0000 +phy_xaui_rx_polarity_flip_29=0x0000 +phy_xaui_tx_polarity_flip_30=0x0001 +phy_xaui_rx_polarity_flip_30=0x0000 + + +#WC28 +phy_xaui_tx_polarity_flip_118=0x0003 +phy_xaui_rx_polarity_flip_118=0x0003 +phy_xaui_tx_polarity_flip_119=0x0003 +phy_xaui_rx_polarity_flip_119=0x0003 + + +#WC29 +phy_xaui_tx_polarity_flip_122=0x0002 +phy_xaui_rx_polarity_flip_122=0x0000 +phy_xaui_tx_polarity_flip_123=0x0000 +phy_xaui_rx_polarity_flip_123=0x0000 + + +#WC30 +phy_xaui_tx_polarity_flip_126=0x0003 +phy_xaui_rx_polarity_flip_126=0x0000 +phy_xaui_tx_polarity_flip_127=0x0003 +phy_xaui_rx_polarity_flip_127=0x0000 + + +#WC31 +phy_xaui_tx_polarity_flip_130=0x0002 +phy_xaui_rx_polarity_flip_130=0x0000 +phy_xaui_tx_polarity_flip_131=0x0001 +phy_xaui_rx_polarity_flip_131=0x0000 + +#xe +serdes_driver_current=0x0a +serdes_preemphasis=0x1a5402 + +#ce0 +serdes_driver_current_lane0_58=0x0a +serdes_driver_current_lane1_58=0x09 +serdes_driver_current_lane2_58=0x09 +serdes_driver_current_lane3_58=0x0a +serdes_preemphasis_lane0_58=0x254902 +serdes_preemphasis_lane1_58=0x244a02 +serdes_preemphasis_lane2_58=0x244a02 +serdes_preemphasis_lane3_58=0x254902 + +#ce1 +serdes_driver_current_lane0_62=0x09 +serdes_driver_current_lane1_62=0x0a +serdes_driver_current_lane2_62=0x09 +serdes_driver_current_lane3_62=0x09 +serdes_preemphasis_lane0_62=0x244a02 +serdes_preemphasis_lane1_62=0x254902 +serdes_preemphasis_lane2_62=0x244a02 +serdes_preemphasis_lane3_62=0x244a02 + +#ce2 +serdes_driver_current_lane0_84=0x09 +serdes_driver_current_lane1_84=0x09 +serdes_driver_current_lane2_84=0x09 +serdes_driver_current_lane3_84=0x09 +serdes_preemphasis_lane0_84=0x204e02 +serdes_preemphasis_lane1_84=0x204e02 +serdes_preemphasis_lane2_84=0x204e02 +serdes_preemphasis_lane3_84=0x204e02 + +#ce3 +serdes_driver_current_lane0_88=0x09 +serdes_driver_current_lane1_88=0x08 +serdes_driver_current_lane2_88=0x08 +serdes_driver_current_lane3_88=0x09 +serdes_preemphasis_lane0_88=0x204e02 +serdes_preemphasis_lane1_88=0x1d5102 +serdes_preemphasis_lane2_88=0x1d5102 +serdes_preemphasis_lane3_88=0x204e02 + +#ce4 +serdes_driver_current_lane0_110=0x09 +serdes_driver_current_lane1_110=0x08 +serdes_driver_current_lane2_110=0x08 +serdes_driver_current_lane3_110=0x09 +serdes_preemphasis_lane0_110=0x204e02 +serdes_preemphasis_lane1_110=0x1d5102 +serdes_preemphasis_lane2_110=0x1d5102 +serdes_preemphasis_lane3_110=0x204e02 + +#ce5 +serdes_driver_current_lane0_114=0x09 +serdes_driver_current_lane1_114=0x08 +serdes_driver_current_lane2_114=0x09 +serdes_driver_current_lane3_114=0x09 +serdes_preemphasis_lane0_114=0x204e02 +serdes_preemphasis_lane1_114=0x1d5102 +serdes_preemphasis_lane2_114=0x224c02 +serdes_preemphasis_lane3_114=0x224c02 + +#ce6 +serdes_driver_current_lane0_1=0x09 +serdes_driver_current_lane1_1=0x0a +serdes_driver_current_lane2_1=0x09 +serdes_driver_current_lane3_1=0x0a +serdes_preemphasis_lane0_1=0x244a02 +serdes_preemphasis_lane1_1=0x254902 +serdes_preemphasis_lane2_1=0x244a02 +serdes_preemphasis_lane3_1=0x254902 + +#ce7 +serdes_driver_current_lane0_5=0x09 +serdes_driver_current_lane1_5=0x09 +serdes_driver_current_lane2_5=0x09 +serdes_driver_current_lane3_5=0x0a +serdes_preemphasis_lane0_5=0x244a02 +serdes_preemphasis_lane1_5=0x244a02 +serdes_preemphasis_lane2_5=0x244a02 +serdes_preemphasis_lane3_5=0x254902 + diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/hwsku.json b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/hwsku.json new file mode 100644 index 000000000000..b578376a3313 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet4": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet8": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet12": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet16": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet20": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet24": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet28": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet32": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet36": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet40": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet44": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet48": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet52": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet56": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet60": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet64": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet68": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet72": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet76": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet80": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet84": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet88": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet92": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet96": { + "default_brkout_mode": "2x50G" + }, + "Ethernet100": { + "default_brkout_mode": "2x50G" + }, + "Ethernet104": { + "default_brkout_mode": "2x50G" + }, + "Ethernet108": { + "default_brkout_mode": "2x50G" + }, + "Ethernet112": { + "default_brkout_mode": "2x50G" + }, + "Ethernet116": { + "default_brkout_mode": "2x50G" + }, + "Ethernet120": { + "default_brkout_mode": "2x50G" + }, + "Ethernet124": { + "default_brkout_mode": "2x50G" + } + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/port_config.ini new file mode 100644 index 000000000000..7f977a26e1f3 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/port_config.ini @@ -0,0 +1,113 @@ +# name lanes alias index speed +Ethernet0 65 Eth1/1 1 10000 +Ethernet1 66 Eth1/2 1 10000 +Ethernet2 67 Eth1/3 1 10000 +Ethernet3 68 Eth1/4 1 10000 +Ethernet4 69 Eth2/1 2 10000 +Ethernet5 70 Eth2/2 2 10000 +Ethernet6 71 Eth2/3 2 10000 +Ethernet7 72 Eth2/4 2 10000 +Ethernet8 73 Eth3/1 3 10000 +Ethernet9 74 Eth3/2 3 10000 +Ethernet10 75 Eth3/3 3 10000 +Ethernet11 76 Eth3/4 3 10000 +Ethernet12 77 Eth4/1 4 10000 +Ethernet13 78 Eth4/2 4 10000 +Ethernet14 79 Eth4/3 4 10000 +Ethernet15 80 Eth4/4 4 10000 +Ethernet16 33 Eth5/1 5 10000 +Ethernet17 34 Eth5/2 5 10000 +Ethernet18 35 Eth5/3 5 10000 +Ethernet19 36 Eth5/4 5 10000 +Ethernet20 37 Eth6/1 6 10000 +Ethernet21 38 Eth6/2 6 10000 +Ethernet22 39 Eth6/3 6 10000 +Ethernet23 40 Eth6/4 6 10000 +Ethernet24 41 Eth7/1 7 10000 +Ethernet25 42 Eth7/2 7 10000 +Ethernet26 43 Eth7/3 7 10000 +Ethernet27 44 Eth7/4 7 10000 +Ethernet28 45 Eth8/1 8 10000 +Ethernet29 46 Eth8/2 8 10000 +Ethernet30 47 Eth8/3 8 10000 +Ethernet31 48 Eth8/4 8 10000 +Ethernet32 49 Eth9/1 9 10000 +Ethernet33 50 Eth9/2 9 10000 +Ethernet34 51 Eth9/3 9 10000 +Ethernet35 52 Eth9/4 9 10000 +Ethernet36 53 Eth10/1 10 10000 +Ethernet37 54 Eth10/2 10 10000 +Ethernet38 55 Eth10/3 10 10000 +Ethernet39 56 Eth10/4 10 10000 +Ethernet40 57 Eth11/1 11 10000 +Ethernet41 58 Eth11/2 11 10000 +Ethernet42 59 Eth11/3 11 10000 +Ethernet43 60 Eth11/4 11 10000 +Ethernet44 61 Eth12/1 12 10000 +Ethernet45 62 Eth12/2 12 10000 +Ethernet46 63 Eth12/3 12 10000 +Ethernet47 64 Eth12/4 12 10000 +Ethernet48 81 Eth13/1 13 10000 +Ethernet49 82 Eth13/2 13 10000 +Ethernet50 83 Eth13/3 13 10000 +Ethernet51 84 Eth13/4 13 10000 +Ethernet52 85 Eth14/1 14 10000 +Ethernet53 86 Eth14/2 14 10000 +Ethernet54 87 Eth14/3 14 10000 +Ethernet55 88 Eth14/4 14 10000 +Ethernet56 89 Eth15/1 15 10000 +Ethernet57 90 Eth15/2 15 10000 +Ethernet58 91 Eth15/3 15 10000 +Ethernet59 92 Eth15/4 15 10000 +Ethernet60 93 Eth16/1 16 10000 +Ethernet61 94 Eth16/2 16 10000 +Ethernet62 95 Eth16/3 16 10000 +Ethernet63 96 Eth16/4 16 10000 +Ethernet64 97 Eth17/1 17 10000 +Ethernet65 98 Eth17/2 17 10000 +Ethernet66 99 Eth17/3 17 10000 +Ethernet67 100 Eth17/4 17 10000 +Ethernet68 101 Eth18/1 18 10000 +Ethernet69 102 Eth18/2 18 10000 +Ethernet70 103 Eth18/3 18 10000 +Ethernet71 104 Eth18/4 18 10000 +Ethernet72 105 Eth19/1 19 10000 +Ethernet73 106 Eth19/2 19 10000 +Ethernet74 107 Eth19/3 19 10000 +Ethernet75 108 Eth19/4 19 10000 +Ethernet76 109 Eth20/1 20 10000 +Ethernet77 110 Eth20/2 20 10000 +Ethernet78 111 Eth20/3 20 10000 +Ethernet79 112 Eth20/4 20 10000 +Ethernet80 1 Eth21/1 21 10000 +Ethernet81 2 Eth21/2 21 10000 +Ethernet82 3 Eth21/3 21 10000 +Ethernet83 4 Eth21/4 21 10000 +Ethernet84 5 Eth22/1 22 10000 +Ethernet85 6 Eth22/2 22 10000 +Ethernet86 7 Eth22/3 22 10000 +Ethernet87 8 Eth22/4 22 10000 +Ethernet88 9 Eth23/1 23 10000 +Ethernet89 10 Eth23/2 23 10000 +Ethernet90 11 Eth23/3 23 10000 +Ethernet91 12 Eth23/4 23 10000 +Ethernet92 13 Eth24/1 24 10000 +Ethernet93 14 Eth24/2 24 10000 +Ethernet94 15 Eth24/3 25 10000 +Ethernet95 16 Eth24/4 25 10000 +Ethernet96 17,18 Eth25/1 26 50000 +Ethernet98 19,20 Eth25/2 26 50000 +Ethernet100 21,22 Eth26/1 27 50000 +Ethernet102 23,24 Eth26/2 27 50000 +Ethernet104 25,26 Eth27/1 28 50000 +Ethernet106 27,28 Eth27/2 28 50000 +Ethernet108 29,30 Eth28/1 29 50000 +Ethernet110 31,32 Eth28/2 29 50000 +Ethernet112 113,114 Eth29/1 30 50000 +Ethernet114 115,116 Eth29/2 30 50000 +Ethernet116 117,118 Eth30/1 31 50000 +Ethernet118 119,120 Eth30/2 31 50000 +Ethernet120 121,122 Eth31/1 32 50000 +Ethernet122 123,124 Eth31/2 32 50000 +Ethernet124 125,126 Eth32/1 32 50000 +Ethernet126 127,128 Eth32/2 32 50000 \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/sai.profile new file mode 100644 index 000000000000..7342ae8002e8 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-10-50/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/Seastone-DX010-25-50/hwsku.json b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/hwsku.json new file mode 100644 index 000000000000..b578376a3313 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet4": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet8": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet12": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet16": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet20": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet24": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet28": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet32": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet36": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet40": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet44": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet48": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet52": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet56": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet60": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet64": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet68": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet72": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet76": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet80": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet84": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet88": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet92": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet96": { + "default_brkout_mode": "2x50G" + }, + "Ethernet100": { + "default_brkout_mode": "2x50G" + }, + "Ethernet104": { + "default_brkout_mode": "2x50G" + }, + "Ethernet108": { + "default_brkout_mode": "2x50G" + }, + "Ethernet112": { + "default_brkout_mode": "2x50G" + }, + "Ethernet116": { + "default_brkout_mode": "2x50G" + }, + "Ethernet120": { + "default_brkout_mode": "2x50G" + }, + "Ethernet124": { + "default_brkout_mode": "2x50G" + } + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/port_config.ini new file mode 100644 index 000000000000..bcf1388e7c5b --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/port_config.ini @@ -0,0 +1,113 @@ +# name lanes alias index speed +Ethernet0 65 Eth1/1 1 25000 +Ethernet1 66 Eth1/2 1 25000 +Ethernet2 67 Eth1/3 1 25000 +Ethernet3 68 Eth1/4 1 25000 +Ethernet4 69 Eth2/1 2 25000 +Ethernet5 70 Eth2/2 2 25000 +Ethernet6 71 Eth2/3 2 25000 +Ethernet7 72 Eth2/4 2 25000 +Ethernet8 73 Eth3/1 3 25000 +Ethernet9 74 Eth3/2 3 25000 +Ethernet10 75 Eth3/3 3 25000 +Ethernet11 76 Eth3/4 3 25000 +Ethernet12 77 Eth4/1 4 25000 +Ethernet13 78 Eth4/2 4 25000 +Ethernet14 79 Eth4/3 4 25000 +Ethernet15 80 Eth4/4 4 25000 +Ethernet16 33 Eth5/1 5 25000 +Ethernet17 34 Eth5/2 5 25000 +Ethernet18 35 Eth5/3 5 25000 +Ethernet19 36 Eth5/4 5 25000 +Ethernet20 37 Eth6/1 6 25000 +Ethernet21 38 Eth6/2 6 25000 +Ethernet22 39 Eth6/3 6 25000 +Ethernet23 40 Eth6/4 6 25000 +Ethernet24 41 Eth7/1 7 25000 +Ethernet25 42 Eth7/2 7 25000 +Ethernet26 43 Eth7/3 7 25000 +Ethernet27 44 Eth7/4 7 25000 +Ethernet28 45 Eth8/1 8 25000 +Ethernet29 46 Eth8/2 8 25000 +Ethernet30 47 Eth8/3 8 25000 +Ethernet31 48 Eth8/4 8 25000 +Ethernet32 49 Eth9/1 9 25000 +Ethernet33 50 Eth9/2 9 25000 +Ethernet34 51 Eth9/3 9 25000 +Ethernet35 52 Eth9/4 9 25000 +Ethernet36 53 Eth10/1 10 25000 +Ethernet37 54 Eth10/2 10 25000 +Ethernet38 55 Eth10/3 10 25000 +Ethernet39 56 Eth10/4 10 25000 +Ethernet40 57 Eth11/1 11 25000 +Ethernet41 58 Eth11/2 11 25000 +Ethernet42 59 Eth11/3 11 25000 +Ethernet43 60 Eth11/4 11 25000 +Ethernet44 61 Eth12/1 12 25000 +Ethernet45 62 Eth12/2 12 25000 +Ethernet46 63 Eth12/3 12 25000 +Ethernet47 64 Eth12/4 12 25000 +Ethernet48 81 Eth13/1 13 25000 +Ethernet49 82 Eth13/2 13 25000 +Ethernet50 83 Eth13/3 13 25000 +Ethernet51 84 Eth13/4 13 25000 +Ethernet52 85 Eth14/1 14 25000 +Ethernet53 86 Eth14/2 14 25000 +Ethernet54 87 Eth14/3 14 25000 +Ethernet55 88 Eth14/4 14 25000 +Ethernet56 89 Eth15/1 15 25000 +Ethernet57 90 Eth15/2 15 25000 +Ethernet58 91 Eth15/3 15 25000 +Ethernet59 92 Eth15/4 15 25000 +Ethernet60 93 Eth16/1 16 25000 +Ethernet61 94 Eth16/2 16 25000 +Ethernet62 95 Eth16/3 16 25000 +Ethernet63 96 Eth16/4 16 25000 +Ethernet64 97 Eth17/1 17 25000 +Ethernet65 98 Eth17/2 17 25000 +Ethernet66 99 Eth17/3 17 25000 +Ethernet67 100 Eth17/4 17 25000 +Ethernet68 101 Eth18/1 18 25000 +Ethernet69 102 Eth18/2 18 25000 +Ethernet70 103 Eth18/3 18 25000 +Ethernet71 104 Eth18/4 18 25000 +Ethernet72 105 Eth19/1 19 25000 +Ethernet73 106 Eth19/2 19 25000 +Ethernet74 107 Eth19/3 19 25000 +Ethernet75 108 Eth19/4 19 25000 +Ethernet76 109 Eth20/1 20 25000 +Ethernet77 110 Eth20/2 20 25000 +Ethernet78 111 Eth20/3 20 25000 +Ethernet79 112 Eth20/4 20 25000 +Ethernet80 1 Eth21/1 21 25000 +Ethernet81 2 Eth21/2 21 25000 +Ethernet82 3 Eth21/3 21 25000 +Ethernet83 4 Eth21/4 21 25000 +Ethernet84 5 Eth22/1 22 25000 +Ethernet85 6 Eth22/2 22 25000 +Ethernet86 7 Eth22/3 22 25000 +Ethernet87 8 Eth22/4 22 25000 +Ethernet88 9 Eth23/1 23 25000 +Ethernet89 10 Eth23/2 23 25000 +Ethernet90 11 Eth23/3 23 25000 +Ethernet91 12 Eth23/4 23 25000 +Ethernet92 13 Eth24/1 24 25000 +Ethernet93 14 Eth24/2 24 25000 +Ethernet94 15 Eth24/3 24 25000 +Ethernet95 16 Eth24/4 24 25000 +Ethernet96 17,18 Eth25/1 25 50000 +Ethernet98 19,20 Eth25/2 25 50000 +Ethernet100 21,22 Eth26/1 26 50000 +Ethernet102 23,24 Eth26/2 26 50000 +Ethernet104 25,26 Eth27/1 27 50000 +Ethernet106 27,28 Eth27/2 27 50000 +Ethernet108 29,30 Eth28/1 28 50000 +Ethernet110 31,32 Eth28/2 28 50000 +Ethernet112 113,114 Eth29/1 29 50000 +Ethernet114 115,116 Eth29/2 29 50000 +Ethernet116 117,118 Eth30/1 30 50000 +Ethernet118 119,120 Eth30/2 30 50000 +Ethernet120 121,122 Eth31/1 31 50000 +Ethernet122 123,124 Eth31/2 31 50000 +Ethernet124 125,126 Eth32/1 32 50000 +Ethernet126 127,128 Eth32/2 32 50000 diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/sai.profile new file mode 100644 index 000000000000..7342ae8002e8 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-25-50/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/Seastone-DX010-50-40/hwsku.json b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-40/hwsku.json new file mode 100644 index 000000000000..3b1b8a97909a --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-40/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "2x50G" + }, + "Ethernet4": { + "default_brkout_mode": "2x50G" + }, + "Ethernet8": { + "default_brkout_mode": "2x50G" + }, + "Ethernet12": { + "default_brkout_mode": "2x50G" + }, + "Ethernet16": { + "default_brkout_mode": "2x50G" + }, + "Ethernet20": { + "default_brkout_mode": "2x50G" + }, + "Ethernet24": { + "default_brkout_mode": "2x50G" + }, + "Ethernet28": { + "default_brkout_mode": "2x50G" + }, + "Ethernet32": { + "default_brkout_mode": "2x50G" + }, + "Ethernet36": { + "default_brkout_mode": "2x50G" + }, + "Ethernet40": { + "default_brkout_mode": "2x50G" + }, + "Ethernet44": { + "default_brkout_mode": "2x50G" + }, + "Ethernet48": { + "default_brkout_mode": "2x50G" + }, + "Ethernet52": { + "default_brkout_mode": "2x50G" + }, + "Ethernet56": { + "default_brkout_mode": "2x50G" + }, + "Ethernet60": { + "default_brkout_mode": "2x50G" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[40G]" + } + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-40/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-40/port_config.ini new file mode 100644 index 000000000000..0fc9d317176b --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-40/port_config.ini @@ -0,0 +1,49 @@ +# 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,99,100 Eth17 17 40000 +Ethernet68 101,102,103,104 Eth18 18 40000 +Ethernet72 105,106,107,108 Eth19 19 40000 +Ethernet76 109,110,111,112 Eth20 20 40000 +Ethernet80 1,2,3,4 Eth21 21 40000 +Ethernet84 5,6,7,8 Eth22 22 40000 +Ethernet88 9,10,11,12 Eth23 23 40000 +Ethernet92 13,14,15,16 Eth24 24 40000 +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-40/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50-40/sai.profile new file mode 100644 index 000000000000..7342ae8002e8 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-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/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/Seastone-DX010-50/hwsku.json b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/hwsku.json new file mode 100644 index 000000000000..0b219eee39f7 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "2x50G" + }, + "Ethernet4": { + "default_brkout_mode": "2x50G" + }, + "Ethernet8": { + "default_brkout_mode": "2x50G" + }, + "Ethernet12": { + "default_brkout_mode": "2x50G" + }, + "Ethernet16": { + "default_brkout_mode": "2x50G" + }, + "Ethernet20": { + "default_brkout_mode": "2x50G" + }, + "Ethernet24": { + "default_brkout_mode": "2x50G" + }, + "Ethernet28": { + "default_brkout_mode": "2x50G" + }, + "Ethernet32": { + "default_brkout_mode": "2x50G" + }, + "Ethernet36": { + "default_brkout_mode": "2x50G" + }, + "Ethernet40": { + "default_brkout_mode": "2x50G" + }, + "Ethernet44": { + "default_brkout_mode": "2x50G" + }, + "Ethernet48": { + "default_brkout_mode": "2x50G" + }, + "Ethernet52": { + "default_brkout_mode": "2x50G" + }, + "Ethernet56": { + "default_brkout_mode": "2x50G" + }, + "Ethernet60": { + "default_brkout_mode": "2x50G" + }, + "Ethernet64": { + "default_brkout_mode": "2x50G" + }, + "Ethernet68": { + "default_brkout_mode": "2x50G" + }, + "Ethernet72": { + "default_brkout_mode": "2x50G" + }, + "Ethernet76": { + "default_brkout_mode": "2x50G" + }, + "Ethernet80": { + "default_brkout_mode": "2x50G" + }, + "Ethernet84": { + "default_brkout_mode": "2x50G" + }, + "Ethernet88": { + "default_brkout_mode": "2x50G" + }, + "Ethernet92": { + "default_brkout_mode": "2x50G" + }, + "Ethernet96": { + "default_brkout_mode": "2x50G" + }, + "Ethernet100": { + "default_brkout_mode": "2x50G" + }, + "Ethernet104": { + "default_brkout_mode": "2x50G" + }, + "Ethernet108": { + "default_brkout_mode": "2x50G" + }, + "Ethernet112": { + "default_brkout_mode": "2x50G" + }, + "Ethernet116": { + "default_brkout_mode": "2x50G" + }, + "Ethernet120": { + "default_brkout_mode": "2x50G" + }, + "Ethernet124": { + "default_brkout_mode": "2x50G" + } + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/port_config.ini new file mode 100644 index 000000000000..bed33e9ed0f5 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/port_config.ini @@ -0,0 +1,65 @@ +# 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 Eth25/1 25 50000 +Ethernet98 19,20 Eth25/2 25 50000 +Ethernet100 21,22 Eth26/1 26 50000 +Ethernet102 23,24 Eth26/2 26 50000 +Ethernet104 25,26 Eth27/1 27 50000 +Ethernet106 27,28 Eth27/2 27 50000 +Ethernet108 29,30 Eth28/1 28 50000 +Ethernet110 31,32 Eth28/2 28 50000 +Ethernet112 113,114 Eth29/1 29 50000 +Ethernet114 115,116 Eth29/2 29 50000 +Ethernet116 117,118 Eth30/1 30 50000 +Ethernet118 119,120 Eth30/2 30 50000 +Ethernet120 121,122 Eth31/1 31 50000 +Ethernet122 123,124 Eth31/2 31 50000 +Ethernet124 125,126 Eth32/1 32 50000 +Ethernet126 127,128 Eth32/2 32 50000 \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/sai.profile new file mode 100644 index 000000000000..7342ae8002e8 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010-50/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/Seastone-DX010/hwsku.json b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/hwsku.json new file mode 100644 index 000000000000..984ba3e4f15e --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[40G]" + } + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/port_config.ini b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/port_config.ini new file mode 100644 index 000000000000..91d2f91d41cc --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 65,66,67,68 Eth1 1 100000 +Ethernet4 69,70,71,72 Eth2 2 100000 +Ethernet8 73,74,75,76 Eth3 3 100000 +Ethernet12 77,78,79,80 Eth4 4 100000 +Ethernet16 33,34,35,36 Eth5 5 100000 +Ethernet20 37,38,39,40 Eth6 6 100000 +Ethernet24 41,42,43,44 Eth7 7 100000 +Ethernet28 45,46,47,48 Eth8 8 100000 +Ethernet32 49,50,51,52 Eth9 9 100000 +Ethernet36 53,54,55,56 Eth10 10 100000 +Ethernet40 57,58,59,60 Eth11 11 100000 +Ethernet44 61,62,63,64 Eth12 12 100000 +Ethernet48 81,82,83,84 Eth13 13 100000 +Ethernet52 85,86,87,88 Eth14 14 100000 +Ethernet56 89,90,91,92 Eth15 15 100000 +Ethernet60 93,94,95,96 Eth16 16 100000 +Ethernet64 97,98,99,100 Eth17 17 100000 +Ethernet68 101,102,103,104 Eth18 18 100000 +Ethernet72 105,106,107,108 Eth19 19 100000 +Ethernet76 109,110,111,112 Eth20 20 100000 +Ethernet80 1,2,3,4 Eth21 21 100000 +Ethernet84 5,6,7,8 Eth22 22 100000 +Ethernet88 9,10,11,12 Eth23 23 100000 +Ethernet92 13,14,15,16 Eth24 24 100000 +Ethernet96 17,18,19,20 Eth25 25 100000 +Ethernet100 21,22,23,24 Eth26 26 100000 +Ethernet104 25,26,27,28 Eth27 27 100000 +Ethernet108 29,30,31,32 Eth28 28 100000 +Ethernet112 113,114,115,116 Eth29 29 100000 +Ethernet116 117,118,119,120 Eth30 30 100000 +Ethernet120 121,122,123,124 Eth31 31 100000 +Ethernet124 125,126,127,128 Eth32 32 100000 \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/sai.profile b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/sai.profile new file mode 100644 index 000000000000..7342ae8002e8 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/Seastone-DX010/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/default_sku b/device/celestica/x86_64-cel_seastone-r0/default_sku new file mode 100644 index 000000000000..0c95475c8505 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/default_sku @@ -0,0 +1 @@ +Seastone-DX010 t1 diff --git a/device/celestica/x86_64-cel_seastone-r0/fancontrol-B2F b/device/celestica/x86_64-cel_seastone-r0/fancontrol-B2F new file mode 100644 index 000000000000..f3277db14df2 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/fancontrol-B2F @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=2 +FCTEMPS=13-002e/pwm1=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-002e/pwm2=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-002e/pwm3=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-002e/pwm4=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-002e/pwm5=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-004d/pwm1=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-004d/pwm2=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-004d/pwm3=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-004d/pwm4=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-004d/pwm5=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input +FCFANS=13-004d/pwm5=13-004d/fan5_input 13-004d/pwm4=13-004d/fan4_input 13-004d/pwm3=13-004d/fan3_input 13-004d/pwm2=13-004d/fan2_input 13-004d/pwm1=13-004d/fan1_input 13-002e/pwm5=13-002e/fan5_input 13-002e/pwm4=13-002e/fan4_input 13-002e/pwm3=13-002e/fan3_input 13-002e/pwm2=13-002e/fan2_input 13-002e/pwm1=13-002e/fan1_input +MINTEMP=13-002e/pwm1=27 13-002e/pwm2=27 13-002e/pwm3=27 13-002e/pwm4=27 13-002e/pwm5=27 13-004d/pwm1=27 13-004d/pwm2=27 13-004d/pwm3=27 13-004d/pwm4=27 13-004d/pwm5=27 +MAXTEMP=13-002e/pwm1=46 13-002e/pwm2=46 13-002e/pwm3=46 13-002e/pwm4=46 13-002e/pwm5=46 13-004d/pwm1=46 13-004d/pwm2=46 13-004d/pwm3=46 13-004d/pwm4=46 13-004d/pwm5=46 +MINSTART=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MINSTOP=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MINPWM=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MAXPWM=13-002e/pwm1=255 13-002e/pwm2=255 13-002e/pwm3=255 13-002e/pwm4=255 13-002e/pwm5=255 13-004d/pwm1=255 13-004d/pwm2=255 13-004d/pwm3=255 13-004d/pwm4=255 13-004d/pwm5=255 +THYST=13-002e/pwm1=3 13-002e/pwm2=3 13-002e/pwm3=3 13-002e/pwm4=3 13-002e/pwm5=3 13-004d/pwm1=3 13-004d/pwm2=3 13-004d/pwm3=3 13-004d/pwm4=3 13-004d/pwm5=3 + diff --git a/device/celestica/x86_64-cel_seastone-r0/fancontrol-F2B b/device/celestica/x86_64-cel_seastone-r0/fancontrol-F2B new file mode 100644 index 000000000000..dc67e2623cc2 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/fancontrol-F2B @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=2 +FCTEMPS=13-002e/pwm1=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-002e/pwm2=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-002e/pwm3=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-002e/pwm4=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-002e/pwm5=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-004d/pwm1=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-004d/pwm2=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-004d/pwm3=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-004d/pwm4=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-004d/pwm5=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input +FCFANS=13-004d/pwm5=13-004d/fan5_input 13-004d/pwm4=13-004d/fan4_input 13-004d/pwm3=13-004d/fan3_input 13-004d/pwm2=13-004d/fan2_input 13-004d/pwm1=13-004d/fan1_input 13-002e/pwm5=13-002e/fan5_input 13-002e/pwm4=13-002e/fan4_input 13-002e/pwm3=13-002e/fan3_input 13-002e/pwm2=13-002e/fan2_input 13-002e/pwm1=13-002e/fan1_input +MINTEMP=13-002e/pwm1=26 13-002e/pwm2=26 13-002e/pwm3=26 13-002e/pwm4=26 13-002e/pwm5=26 13-004d/pwm1=26 13-004d/pwm2=26 13-004d/pwm3=26 13-004d/pwm4=26 13-004d/pwm5=26 +MAXTEMP=13-002e/pwm1=45 13-002e/pwm2=45 13-002e/pwm3=45 13-002e/pwm4=45 13-002e/pwm5=45 13-004d/pwm1=45 13-004d/pwm2=45 13-004d/pwm3=45 13-004d/pwm4=45 13-004d/pwm5=45 +MINSTART=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MINSTOP=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MINPWM=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MAXPWM=13-002e/pwm1=255 13-002e/pwm2=255 13-002e/pwm3=255 13-002e/pwm4=255 13-002e/pwm5=255 13-004d/pwm1=255 13-004d/pwm2=255 13-004d/pwm3=255 13-004d/pwm4=255 13-004d/pwm5=255 +THYST=13-002e/pwm1=3 13-002e/pwm2=3 13-002e/pwm3=3 13-002e/pwm4=3 13-002e/pwm5=3 13-004d/pwm1=3 13-004d/pwm2=3 13-004d/pwm3=3 13-004d/pwm4=3 13-004d/pwm5=3 + diff --git a/device/celestica/x86_64-cel_seastone-r0/installer.conf b/device/celestica/x86_64-cel_seastone-r0/installer.conf new file mode 100644 index 000000000000..456a3ae8f4eb --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="module_blacklist=gpio_ich" \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode0 b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode0 new file mode 100755 index 000000000000..829087013a2a --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode0 @@ -0,0 +1,16 @@ + 02 20 28 67 2A 12 30 D1 74 02 02 00 28 67 2A 12 + 20 D1 74 0C 02 30 28 67 2A 12 40 D1 74 16 12 E0 + 85 05 D2 05 71 28 52 00 3A 80 67 7C 75 30 77 42 + 67 83 75 36 77 53 67 8A 75 3C 77 42 67 91 75 64 + 77 64 67 75 75 A9 28 67 9F 75 B4 16 E0 DA 04 74 + A9 77 B4 67 75 75 BF 28 67 9F 75 C6 16 E0 DA 04 + 74 BF 77 C6 67 75 75 CD 28 67 9F 75 D2 16 E0 DA + 04 74 CD 77 D2 12 A0 F8 15 1A 00 57 12 A0 F8 15 + 1A 01 57 12 A0 F8 15 1A 02 57 12 A0 F8 15 1A 03 + 57 12 A0 F8 15 1A 04 57 12 A0 F8 15 1A 05 57 28 + 32 00 32 01 B7 97 77 A8 57 67 D7 67 DE 67 DE 67 + DE F2 04 57 67 E5 67 DE 67 DE 67 DE F2 04 57 67 + D7 67 DE F2 02 57 67 E5 67 DE F2 02 57 67 D7 F2 + 01 57 67 E5 F2 01 57 32 0F 87 32 0F 87 57 32 0F + 87 32 0E 87 57 32 0E 87 32 0E 87 57 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode1 b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode1 new file mode 100755 index 000000000000..829087013a2a --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode1 @@ -0,0 +1,16 @@ + 02 20 28 67 2A 12 30 D1 74 02 02 00 28 67 2A 12 + 20 D1 74 0C 02 30 28 67 2A 12 40 D1 74 16 12 E0 + 85 05 D2 05 71 28 52 00 3A 80 67 7C 75 30 77 42 + 67 83 75 36 77 53 67 8A 75 3C 77 42 67 91 75 64 + 77 64 67 75 75 A9 28 67 9F 75 B4 16 E0 DA 04 74 + A9 77 B4 67 75 75 BF 28 67 9F 75 C6 16 E0 DA 04 + 74 BF 77 C6 67 75 75 CD 28 67 9F 75 D2 16 E0 DA + 04 74 CD 77 D2 12 A0 F8 15 1A 00 57 12 A0 F8 15 + 1A 01 57 12 A0 F8 15 1A 02 57 12 A0 F8 15 1A 03 + 57 12 A0 F8 15 1A 04 57 12 A0 F8 15 1A 05 57 28 + 32 00 32 01 B7 97 77 A8 57 67 D7 67 DE 67 DE 67 + DE F2 04 57 67 E5 67 DE 67 DE 67 DE F2 04 57 67 + D7 67 DE F2 02 57 67 E5 67 DE F2 02 57 67 D7 F2 + 01 57 67 E5 F2 01 57 32 0F 87 32 0F 87 57 32 0F + 87 32 0E 87 57 32 0E 87 32 0E 87 57 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode2 b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode2 new file mode 100755 index 000000000000..9e30d9d28fb6 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/led-code/ledcode2 @@ -0,0 +1,8 @@ +02 01 28 67 16 02 01 28 67 16 12 E0 85 05 D2 05 +71 14 52 00 3A 04 67 3C 75 54 77 1C 67 43 75 22 +77 2F 28 67 4A 75 57 16 E0 DA 04 74 54 77 57 28 +67 4A 75 57 16 E0 DA 04 74 54 77 57 12 A0 F8 15 +1A 00 57 12 A0 F8 15 1A 01 57 28 32 00 32 01 B7 +97 77 53 57 67 5D 57 67 6B 57 67 64 57 32 0F 87 +32 0F 87 57 32 0E 87 32 0F 87 57 32 0E 87 32 0E +87 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/device/celestica/x86_64-cel_seastone-r0/led_proc_init.soc b/device/celestica/x86_64-cel_seastone-r0/led_proc_init.soc new file mode 100755 index 000000000000..450533c0dc68 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/led_proc_init.soc @@ -0,0 +1,8 @@ +# Download LED code into LED processor and enable (if applicable). + +led 0 load /usr/share/sonic/platform/led-code/ledcode0; +led 0 auto on; led 0 start; +led 1 load /usr/share/sonic/platform/led-code/ledcode1; +led 1 auto on; led 1 start; +led 2 load /usr/share/sonic/platform/led-code/ledcode2; +led 2 auto on; led 2 start diff --git a/device/celestica/x86_64-cel_seastone-r0/pcie.yaml b/device/celestica/x86_64-cel_seastone-r0/pcie.yaml new file mode 100644 index 000000000000..18e52be96474 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/pcie.yaml @@ -0,0 +1,75 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 1f0c + name: 'Host bridge: Intel Corporation Atom processor C2000 SoC Transaction Router' +- bus: '00' + dev: '01' + fn: '0' + id: 1f10 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 1' +- bus: '00' + dev: '02' + fn: '0' + id: 1f11 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 2' +- bus: '00' + dev: '03' + fn: '0' + id: 1f12 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 3' +- bus: '00' + dev: 0e + fn: '0' + id: 1f14 + name: 'Host bridge: Intel Corporation Atom processor C2000 RAS' +- bus: '00' + dev: 0f + fn: '0' + id: 1f16 + name: 'IOMMU: Intel Corporation Atom processor C2000 RCEC' +- bus: '00' + dev: '13' + fn: '0' + id: 1f15 + name: 'System peripheral: Intel Corporation Atom processor C2000 SMBus 2.0' +- bus: '00' + dev: '14' + fn: '0' + id: 1f41 + name: 'Ethernet controller: Intel Corporation Ethernet Connection I354' +- bus: '00' + dev: '16' + fn: '0' + id: 1f2c + name: 'USB controller: Intel Corporation Atom processor C2000 USB Enhanced Host Controller' +- bus: '00' + dev: '17' + fn: '0' + id: 1f22 + name: 'SATA controller: Intel Corporation Atom processor C2000 AHCI SATA2 Controller' +- bus: '00' + dev: '18' + fn: '0' + id: 1f32 + name: 'SATA controller: Intel Corporation Atom processor C2000 AHCI SATA3 Controller' +- bus: '00' + dev: 1f + fn: '0' + id: 1f38 + name: 'ISA bridge: Intel Corporation Atom processor C2000 PCU' +- bus: '00' + dev: 1f + fn: '3' + id: 1f3c + name: 'SMBus: Intel Corporation Atom processor C2000 PCU SMBus' +- bus: '01' + dev: '00' + fn: '0' + id: b960 + name: 'Ethernet controller: Broadcom Limited Broadcom BCM56960 Switch ASIC' +- bus: '01' + dev: '00' + fn: '1' + id: b960 + name: 'Ethernet controller: Broadcom Limited Broadcom BCM56960 Switch ASIC' diff --git a/device/celestica/x86_64-cel_seastone-r0/platform.json b/device/celestica/x86_64-cel_seastone-r0/platform.json new file mode 100644 index 000000000000..aebb6ee0ac5c --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/platform.json @@ -0,0 +1,292 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "65,66,67,68", + "breakout_modes": { + "1x100G[40G]": ["Eth1"], + "2x50G": ["Eth1/1", "Eth1/2"], + "4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "69,70,71,72", + "breakout_modes": { + "1x100G[40G]": ["Eth2"], + "2x50G": ["Eth2/1", "Eth2/2"], + "4x25G[10G]": ["Eth2/1", "Eth2/2", "Eth2/3", "Eth2/4"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "73,74,75,76", + "breakout_modes": { + "1x100G[40G]": ["Eth3"], + "2x50G": ["Eth3/1", "Eth3/2"], + "4x25G[10G]": ["Eth3/1", "Eth3/2", "Eth3/3", "Eth3/4"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "77,78,79,80", + "breakout_modes": { + "1x100G[40G]": ["Eth4"], + "2x50G": ["Eth4/1", "Eth4/2"], + "4x25G[10G]": ["Eth4/1", "Eth4/2", "Eth4/3", "Eth4/4"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "33,34,35,36", + "breakout_modes": { + "1x100G[40G]": ["Eth5"], + "2x50G": ["Eth5/1", "Eth5/2"], + "4x25G[10G]": ["Eth5/1", "Eth5/2", "Eth5/3", "Eth5/4"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "37,38,39,40", + "breakout_modes": { + "1x100G[40G]": ["Eth6"], + "2x50G": ["Eth6/1", "Eth6/2"], + "4x25G[10G]": ["Eth6/1", "Eth6/2", "Eth6/3", "Eth6/4"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "41,42,43,44", + "breakout_modes": { + "1x100G[40G]": ["Eth7"], + "2x50G": ["Eth7/1", "Eth7/2"], + "4x25G[10G]": ["Eth7/1", "Eth7/2", "Eth7/3", "Eth7/4"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "45,46,47,48", + "breakout_modes": { + "1x100G[40G]": ["Eth8"], + "2x50G": ["Eth8/1", "Eth8/2"], + "4x25G[10G]": ["Eth8/1", "Eth8/2", "Eth8/3", "Eth8/4"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "49,50,51,52", + "breakout_modes": { + "1x100G[40G]": ["Eth9"], + "2x50G": ["Eth9/1", "Eth9/2"], + "4x25G[10G]": ["Eth9/1", "Eth9/2", "Eth9/3", "Eth9/4"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "53,54,55,56", + "breakout_modes": { + "1x100G[40G]": ["Eth10"], + "2x50G": ["Eth10/1", "Eth10/2"], + "4x25G[10G]": ["Eth10/1", "Eth10/2", "Eth10/3", "Eth10/4"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "57,58,59,60", + "breakout_modes": { + "1x100G[40G]": ["Eth11"], + "2x50G": ["Eth11/1", "Eth11/2"], + "4x25G[10G]": ["Eth11/1", "Eth11/2", "Eth11/3", "Eth11/4"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "61,62,63,64", + "breakout_modes": { + "1x100G[40G]": ["Eth12"], + "2x50G": ["Eth12/1", "Eth12/2"], + "4x25G[10G]": ["Eth12/1", "Eth12/2", "Eth12/3", "Eth12/4"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "81,82,83,84", + "breakout_modes": { + "1x100G[40G]": ["Eth13"], + "2x50G": ["Eth13/1", "Eth13/2"], + "4x25G[10G]": ["Eth13/1", "Eth13/2", "Eth13/3", "Eth13/4"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "85,86,87,88", + "breakout_modes": { + "1x100G[40G]": ["Eth14"], + "2x50G": ["Eth14/1", "Eth14/2"], + "4x25G[10G]": ["Eth14/1", "Eth14/2", "Eth14/3", "Eth14/4"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "89,90,91,92", + "breakout_modes": { + "1x100G[40G]": ["Eth15"], + "2x50G": ["Eth15/1", "Eth15/2"], + "4x25G[10G]": ["Eth15/1", "Eth15/2", "Eth15/3", "Eth15/4"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "93,94,95,96", + "breakout_modes": { + "1x100G[40G]": ["Eth16"], + "2x50G": ["Eth16/1", "Eth16/2"], + "4x25G[10G]": ["Eth16/1", "Eth16/2", "Eth16/3", "Eth16/4"] + } + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "97,98,99,100", + "breakout_modes": { + "1x100G[40G]": ["Eth17"], + "2x50G": ["Eth17/1", "Eth17/2"], + "4x25G[10G]": ["Eth17/1", "Eth17/2", "Eth17/3", "Eth17/4"] + } + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "101,102,103,104", + "breakout_modes": { + "1x100G[40G]": ["Eth18"], + "2x50G": ["Eth18/1", "Eth18/2"], + "4x25G[10G]": ["Eth18/1", "Eth18/2", "Eth18/3", "Eth18/4"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "105,106,107,108", + "breakout_modes": { + "1x100G[40G]": ["Eth19"], + "2x50G": ["Eth19/1", "Eth19/2"], + "4x25G[10G]": ["Eth19/1", "Eth19/2", "Eth19/3", "Eth19/4"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "109,110,111,112", + "breakout_modes": { + "1x100G[40G]": ["Eth20"], + "2x50G": ["Eth20/1", "Eth20/2"], + "4x25G[10G]": ["Eth20/1", "Eth20/2", "Eth20/3", "Eth20/4"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "1,2,3,4", + "breakout_modes": { + "1x100G[40G]": ["Eth21"], + "2x50G": ["Eth21/1", "Eth21/2"], + "4x25G[10G]": ["Eth21/1", "Eth21/2", "Eth21/3", "Eth21/4"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "5,6,7,8", + "breakout_modes": { + "1x100G[40G]": ["Eth22"], + "2x50G": ["Eth22/1", "Eth22/2"], + "4x25G[10G]": ["Eth22/1", "Eth22/2", "Eth22/3", "Eth22/4"] + } + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "9,10,11,12", + "breakout_modes": { + "1x100G[40G]": ["Eth23"], + "2x50G": ["Eth23/1", "Eth23/2"], + "4x25G[10G]": ["Eth23/1", "Eth23/2", "Eth23/3", "Eth23/4"] + } + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "13,14,15,16", + "breakout_modes": { + "1x100G[40G]": ["Eth24"], + "2x50G": ["Eth24/1", "Eth24/2"], + "4x25G[10G]": ["Eth24/1", "Eth24/2", "Eth24/3", "Eth24/4"] + } + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "17,18,19,20", + "breakout_modes": { + "1x100G[40G]": ["Eth25"], + "2x50G": ["Eth25/1", "Eth25/2"], + "4x25G[10G]": ["Eth25/1", "Eth25/2", "Eth25/3", "Eth25/4"] + } + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "21,22,23,24", + "breakout_modes": { + "1x100G[40G]": ["Eth26"], + "2x50G": ["Eth26/1", "Eth26/2"], + "4x25G[10G]": ["Eth26/1", "Eth26/2", "Eth26/3", "Eth26/4"] + } + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "25,26,27,28", + "breakout_modes": { + "1x100G[40G]": ["Eth27"], + "2x50G": ["Eth27/1", "Eth27/2"], + "4x25G[10G]": ["Eth27/1", "Eth27/2", "Eth27/3", "Eth27/4"] + } + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "29,30,31,32", + "breakout_modes": { + "1x100G[40G]": ["Eth28"], + "2x50G": ["Eth28/1", "Eth28/2"], + "4x25G[10G]": ["Eth28/1", "Eth28/2", "Eth28/3", "Eth28/4"] + } + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "113,114,115,116", + "breakout_modes": { + "1x100G[40G]": ["Eth29"], + "2x50G": ["Eth29/1", "Eth29/2"], + "4x25G[10G]": ["Eth29/1", "Eth29/2", "Eth29/3", "Eth29/4"] + } + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "117,118,119,120", + "breakout_modes": { + "1x100G[40G]": ["Eth30"], + "2x50G": ["Eth30/1", "Eth30/2"], + "4x25G[10G]": ["Eth30/1", "Eth30/2", "Eth30/3", "Eth30/4"] + } + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "121,122,123,124", + "breakout_modes": { + "1x100G[40G]": ["Eth31"], + "2x50G": ["Eth31/1", "Eth31/2"], + "4x25G[10G]": ["Eth31/1", "Eth31/2", "Eth31/3", "Eth31/4"] + } + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "125,126,127,128", + "breakout_modes": { + "1x100G[40G]": ["Eth32"], + "2x50G": ["Eth32/1", "Eth32/2"], + "4x25G[10G]": ["Eth32/1", "Eth32/2", "Eth32/3", "Eth32/4"] + } + } + } +} diff --git a/device/celestica/x86_64-cel_seastone-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_seastone-r0/plugins/eeprom.py new file mode 100644 index 000000000000..bba16943966a --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# 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 as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-12/12-0050/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/celestica/x86_64-cel_seastone-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_seastone-r0/plugins/psuutil.py new file mode 100644 index 000000000000..b2764b5b6ae0 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/plugins/psuutil.py @@ -0,0 +1,82 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + +import os + + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +GPIO_DIR = "/sys/class/gpio" +GPIO_LABEL = "pca9505" +DX010_MAX_PSUS = 2 + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + # DX010 PSU pin mapping + self.dx010_psu_gpio = [ + {'base': self.__get_gpio_base()}, + {'prs': 27, 'status': 22}, + {'prs': 28, 'status': 25} + ] + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __get_gpio_base(self): + for r in os.listdir(GPIO_DIR): + label_path = os.path.join(GPIO_DIR, r, "label") + if "gpiochip" in r and GPIO_LABEL in self.__read_txt_file(label_path): + return int(r[8:], 10) + return 216 # Reserve + + def __get_gpio_value(self, pinnum): + gpio_base = self.dx010_psu_gpio[0]['base'] + gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum) + gpio_file = gpio_dir + "/value" + retval = self.__read_txt_file(gpio_file) + return retval.rstrip('\r\n') + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + return DX010_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 + """ + raw = self.__get_gpio_value( + self.dx010_psu_gpio[index]['status']) + return int(raw, 10) == 1 + + 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 + """ + raw = self.__get_gpio_value(self.dx010_psu_gpio[index]['prs']) + return int(raw, 10) == 0 diff --git a/device/celestica/x86_64-cel_seastone-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_seastone-r0/plugins/sfputil.py new file mode 100644 index 000000000000..ca960dd8136d --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/plugins/sfputil.py @@ -0,0 +1,202 @@ +# 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 = 32 + PORTS_IN_BLOCK = 32 + + _port_to_eeprom_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 list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + 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): + if self.port_start == 1: + self.port_to_eeprom_mapping[x] = eeprom_path.format((x - 1) + 26) + else: + self.port_to_eeprom_mapping[x] = eeprom_path.format(x + 26) + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/dx010_cpld/qsfp_modprs", "r") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/dx010_cpld/qsfp_lpmode", "r") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/dx010_cpld/qsfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value).strip('L') + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/dx010_cpld/qsfp_reset", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the + # register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + if self.port_start == 1: + bit_index = port_num - 1 + else: + bit_index = port_num + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value).rstrip('L')) + 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("/sys/devices/platform/dx010_cpld/qsfp_reset", "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value).rstrip('L')) + reg_file.close() + + return True + + def get_transceiver_change_event(self, timeout=0): + raise NotImplementedError 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/sensors.conf b/device/celestica/x86_64-cel_seastone-r0/sensors.conf new file mode 100644 index 000000000000..d92d6534e764 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sensors.conf @@ -0,0 +1,73 @@ +# libsensors configuration file for Celestica DX010. +# The i2c bus portion is omit because adapter name +# changes every time when system boot up. + +chip "dps460-i2c-*-5a" + label temp1 "Power Supply 1 temp sensor 1" + label temp2 "Power Supply 1 temp sensor 2" + label temp3 "Power Supply 1 temp sensor 3" + ignore fan2 + ignore fan3 + ignore in2 + + set in1_max 240 + set in1_min 100 + set in1_crit 264 + set in1_lcrit 90 + set in3_max 12.6 + set in3_min 11.4 + set in3_crit 13.0 + set in3_lcrit 11.0 + +chip "dps460-i2c-*-5b" + label temp1 "Power Supply 2 temp sensor 1" + label temp2 "Power Supply 2 temp sensor 2" + label temp3 "Power Supply 2 temp sensor 3" + ignore fan2 + ignore fan3 + ignore in2 + + set in1_max 240 + set in1_min 100 + set in1_crit 264 + set in1_lcrit 90 + set in3_max 12.6 + set in3_min 11.4 + set in3_crit 13.0 + set in3_lcrit 11.0 + +# These sensors located on Main Switch Board. +chip "lm75b-i2c-*-48" + label temp1 "Front-panel temp sensor 1" + set temp1_max 50 + +chip "lm75b-i2c-*-49" + label temp1 "Front-panel temp sensor 2" + set temp1_max 50 + +chip "lm75b-i2c-*-4a" + label temp1 "ASIC temp sensor" + set temp1_max 70 + +# These sensors located on CPU Board. +chip "lm75b-i2c-*-48" + label temp1 "Rear-panel temp sensor 1" + set temp1_max 70 + +chip "lm75b-i2c-*-4e" + label temp1 "Rear-panel temp sensor 2" + set temp1_max 70 + +chip "emc2305-i2c-*-2e" + label fan2 "fan1" + label fan1 "fan2" + label fan4 "fan3" + label fan5 "fan4" + label fan3 "fan5" + +chip "emc2305-i2c-*-4d" + label fan2 "fan1" + label fan4 "fan2" + label fan5 "fan3" + label fan3 "fan4" + label fan1 "fan5" diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..db1748e44d2c --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +from . import chassis +from . import platform 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 new file mode 100644 index 000000000000..1b5c5773e27b --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/chassis.py @@ -0,0 +1,303 @@ +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +try: + import sys + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from sonic_py_common import device_info + from .event import SfpEvent + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +NUM_FAN_TRAY = 5 +NUM_FAN = 2 +NUM_PSU = 2 +NUM_THERMAL = 5 +NUM_SFP = 32 +NUM_COMPONENT = 5 +RESET_REGISTER = "0x103" +HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/" +REBOOT_CAUSE_FILE = "reboot-cause.txt" +PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt" +GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg" +HOST_CHK_CMD = "docker > /dev/null 2>&1" + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + def __init__(self): + ChassisBase.__init__(self) + self._api_helper = APIHelper() + self.sfp_module_initialized = False + self.__initialize_eeprom() + self.is_host = self._api_helper.is_host() + + if not self.is_host: + self.__initialize_fan() + self.__initialize_psu() + self.__initialize_thermals() + else: + self.__initialize_components() + + def __initialize_sfp(self): + sfputil_helper = SfpUtilHelper() + port_config_file_path = device_info.get_path_to_port_config_file() + sfputil_helper.read_porttab_mappings(port_config_file_path, 0) + + from sonic_platform.sfp import Sfp + for index in range(0, NUM_SFP): + name_idx = 0 if index+1 == NUM_SFP else index+1 + sfp = Sfp(index, sfputil_helper.logical[name_idx]) + self._sfp_list.append(sfp) + self.sfp_module_initialized = True + + def __initialize_psu(self): + from sonic_platform.psu import Psu + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + + def __initialize_fan(self): + from sonic_platform.fan import Fan + 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 __initialize_thermals(self): + from sonic_platform.thermal import Thermal + airflow = self.__get_air_flow() + for index in range(0, NUM_THERMAL): + thermal = Thermal(index, airflow) + self._thermal_list.append(thermal) + + def __initialize_eeprom(self): + from sonic_platform.eeprom import Tlv + self._eeprom = Tlv() + + def __initialize_components(self): + from sonic_platform.component import Component + for index in range(0, NUM_COMPONENT): + component = Component(index) + self._component_list.append(component) + + def __get_air_flow(self): + air_flow_path = '/usr/share/sonic/device/{}/fan_airflow'.format(self._api_helper.platform) if self.is_host else '/usr/share/sonic/platform/fan_airflow' + air_flow = self._api_helper.read_one_line_file(air_flow_path) + return air_flow or 'B2F' + + 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_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. + + REBOOT_CAUSE_POWER_LOSS = "Power Loss" + REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "Thermal Overload: CPU" + REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "Thermal Overload: ASIC" + REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "Thermal Overload: Other" + REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED = "Insufficient Fan Speed" + REBOOT_CAUSE_WATCHDOG = "Watchdog" + REBOOT_CAUSE_HARDWARE_OTHER = "Hardware - Other" + REBOOT_CAUSE_NON_HARDWARE = "Non-Hardware" + + """ + reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) + sw_reboot_cause = self._api_helper.read_txt_file( + reboot_cause_path) or "Unknown" + hw_reboot_cause = self._api_helper.get_cpld_reg_value( + GETREG_PATH, RESET_REGISTER) + + prev_reboot_cause = { + '0x11': (self.REBOOT_CAUSE_POWER_LOSS, 'Power on reset'), + '0x22': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'CPLD_WD_RESET'), + '0x33': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by CPU'), + '0x44': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by reset button'), + '0x55': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, ''), + '0x66': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC, ''), + '0x77': (self.REBOOT_CAUSE_WATCHDOG, '') + }.get(hw_reboot_cause, (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Unknown reason')) + + if sw_reboot_cause != 'Unknown' and hw_reboot_cause == '0x11': + prev_reboot_cause = ( + self.REBOOT_CAUSE_NON_HARDWARE, sw_reboot_cause) + + return prev_reboot_cause + + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + # SFP event + if not self.sfp_module_initialized: + self.__initialize_sfp() + + sfp_event = SfpEvent(self._sfp_list).get_sfp_event(timeout) + if sfp_event: + return True, {'sfp': sfp_event} + + return False, {'sfp': {}} + + ############################################################## + ######################## SFP methods ######################### + ############################################################## + + def get_num_sfps(self): + """ + Retrieves the number of sfps available on this chassis + Returns: + An integer, the number of sfps available on this chassis + """ + if not self.sfp_module_initialized: + self.__initialize_sfp() + + return len(self._sfp_list) + + def get_all_sfps(self): + """ + Retrieves all sfps available on this chassis + Returns: + A list of objects derived from SfpBase representing all sfps + available on this chassis + """ + if not self.sfp_module_initialized: + self.__initialize_sfp() + + return self._sfp_list + + 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, 1 for Ethernet0, 2 for Ethernet4 and so on. + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + if not self.sfp_module_initialized: + self.__initialize_sfp() + + try: + # The index will start from 1 + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + return sfp + + ############################################################## + ####################### Other methods ######################## + ############################################################## + + 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 + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self._api_helper.hwsku + + def get_presence(self): + """ + Retrieves the presence of the Chassis + Returns: + bool: True if Chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._eeprom.get_pn() + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return self._eeprom.get_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 True + + def get_thermal_manager(self): + from .thermal_manager import ThermalManager + return ThermalManager 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 new file mode 100644 index 000000000000..2833bf4d1cc5 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/component.py @@ -0,0 +1,130 @@ +############################################################################# +# Celestica +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +import os.path +import shutil +import subprocess + +try: + from sonic_platform_base.component_base import ComponentBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CPLD_ADDR_MAPPING = { + "CPLD1": "0x100", + "CPLD2": "0x200", + "CPLD3": "0x280", + "CPLD4": "0x300", + "CPLD5": "0x380" +} +GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg" +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" +COMPONENT_NAME_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "BIOS"] +COMPONENT_DES_LIST = ["Used for managing the CPU", + "Used for managing QSFP+ ports (1-10)", "Used for managing QSFP+ ports (11-20)", "Used for managing QSFP+ ports (22-32)", "Basic Input/Output System"] + + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index): + ComponentBase.__init__(self) + self.index = component_index + self._api_helper = APIHelper() + self.name = self.get_name() + + def __get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def get_register_value(self, register): + # Retrieves the cpld register value + cmd = "echo {1} > {0}; cat {0}".format(GETREG_PATH, register) + p = subprocess.Popen( + cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err is not '': + return None + return raw_data.strip() + + def __get_cpld_version(self): + # Retrieves the CPLD firmware version + cpld_version = dict() + for cpld_name in CPLD_ADDR_MAPPING: + try: + cpld_addr = CPLD_ADDR_MAPPING[cpld_name] + cpld_version_raw = self.get_register_value(cpld_addr) + cpld_version_str = "{}.{}".format(int(cpld_version_raw[2], 16), int( + cpld_version_raw[3], 16)) if cpld_version_raw is not None else 'None' + cpld_version[cpld_name] = cpld_version_str + except Exception as e: + cpld_version[cpld_name] = 'None' + return cpld_version + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return COMPONENT_NAME_LIST[self.index] + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return COMPONENT_DES_LIST[self.index] + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + fw_version = None + + if self.name == "BIOS": + fw_version = self.__get_bios_version() + elif "CPLD" in self.name: + cpld_version = self.__get_cpld_version() + fw_version = cpld_version.get(self.name) + + return fw_version + + def install_firmware(self, image_path): + """ + Install firmware to module + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install successfully, False if not + """ + if not os.path.isfile(image_path): + return False + + if "CPLD" in self.name: + img_name = os.path.basename(image_path) + root, ext = os.path.splitext(img_name) + ext = ".vme" if ext == "" else ext + 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 + + return self.__run_command(install_command) diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/eeprom.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/eeprom.py new file mode 100644 index 000000000000..b2b4a8122590 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/eeprom.py @@ -0,0 +1,114 @@ +############################################################################# +# Celestica Seastone-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: + import glob + import os + import sys + import re + from array import array + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + + +class Tlv(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + + def __init__(self): + self._eeprom_path = "/sys/class/i2c-adapter/i2c-12/12-0050/eeprom" + 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/device/celestica/x86_64-cel_seastone-r0/sonic_platform/event.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/event.py new file mode 100644 index 000000000000..351b2a5ac087 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/event.py @@ -0,0 +1,52 @@ +try: + import select + from .helper import APIHelper + from sonic_py_common.logger import Logger +except ImportError as e: + raise ImportError(repr(e) + " - required module not found") + + +class SfpEvent: + ''' Listen to insert/remove sfp events ''' + + QSFP_MODPRS_IRQ = '/sys/devices/platform/dx010_cpld/qsfp_modprs_irq' + GPIO_SUS6 = "/sys/devices/platform/slx-ich.0/sci_int_gpio_sus6" + + def __init__(self, sfp_list): + self._api_helper = APIHelper() + self._sfp_list = sfp_list + self._logger = Logger() + + def get_sfp_event(self, timeout): + epoll = select.epoll() + port_dict = {} + timeout_sec = timeout/1000 + + try: + # We get notified when there is an SCI interrupt from GPIO SUS6 + fd = open(self.GPIO_SUS6, "r") + fd.read() + + epoll.register(fd.fileno(), select.EPOLLIN & select.EPOLLET) + events = epoll.poll(timeout=timeout_sec if timeout != 0 else -1) + if events: + # Read the QSFP ABS interrupt & status registers + port_changes = self._api_helper.read_one_line_file( + self.QSFP_MODPRS_IRQ) + changes = int(port_changes, 16) + for sfp in self._sfp_list: + change = (changes >> sfp.port_num-1) & 1 + if change == 1: + port_dict[str(sfp.port_num)] = str( + int(sfp.get_presence())) + + return port_dict + except Exception as e: + self._logger.log_error("Failed to detect SfpEvent - " + repr(e)) + return False + + finally: + fd.close() + epoll.close() + + return False diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/fan.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/fan.py new file mode 100644 index 000000000000..bf2b27019b63 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/fan.py @@ -0,0 +1,323 @@ +############################################################################# +# 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") + +EMC2305_PATH = "/sys/bus/i2c/drivers/emc2305/" +GPIO_DIR = "/sys/class/gpio" +GPIO_LABEL = "pca9505" +EMC2305_MAX_PWM = 255 +EMC2305_FAN_PWM = "pwm{}" +EMC2305_FAN_TARGET = "fan{}_target" +EMC2305_FAN_INPUT = "pwm{}" +FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R", + "FAN-3F", "FAN-3R", "FAN-4F", "FAN-4R", "FAN-5F", "FAN-5R"] +PSU_FAN_MAX_RPM = 11000 +PSU_HWMON_PATH = "/sys/bus/i2c/devices/i2c-{0}/{0}-00{1}/hwmon" +PSU_I2C_MAPPING = { + 0: { + "num": 10, + "addr": "5a" + }, + 1: { + "num": 11, + "addr": "5b" + }, +} +NULL_VAL = "N/A" + + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0): + FanBase.__init__(self) + self.fan_index = fan_index + self._api_helper = APIHelper() + 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.psu_i2c_num = PSU_I2C_MAPPING[self.psu_index]["num"] + self.psu_i2c_addr = PSU_I2C_MAPPING[self.psu_index]["addr"] + self.psu_hwmon_path = PSU_HWMON_PATH.format( + self.psu_i2c_num, self.psu_i2c_addr) + + # dx010 fan attributes + # Two EMC2305s located at i2c-13-4d and i2c-13-2e + # to control a dual-fan module. + self.emc2305_chip_mapping = [ + { + 'device': "13-002e", + 'index_map': [2, 1, 4, 5, 3] + }, + { + 'device': "13-004d", + 'index_map': [2, 4, 5, 3, 1] + } + ] + self.dx010_fan_gpio = [ + {'base': self.__get_gpio_base()}, + {'prs': 11, 'dir': 16, 'color': {'red': 31, 'green': 32}}, # 1 + {'prs': 10, 'dir': 15, 'color': {'red': 29, 'green': 30}}, # 2 + {'prs': 13, 'dir': 18, 'color': {'red': 35, 'green': 36}}, # 3 + {'prs': 14, 'dir': 19, 'color': {'red': 37, 'green': 38}}, # 4 + {'prs': 12, 'dir': 17, 'color': {'red': 33, 'green': 34}}, # 5 + ] + + def __write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except: + return False + return True + + def __search_file_by_name(self, directory, file_name): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name in file_name: + return file_path + return None + + def __get_gpio_base(self): + for r in os.listdir(GPIO_DIR): + label_path = os.path.join(GPIO_DIR, r, "label") + if "gpiochip" in r and GPIO_LABEL in self._api_helper.read_txt_file(label_path): + return int(r[8:], 10) + return 216 # Reserve + + def __get_gpio_value(self, pinnum): + gpio_base = self.dx010_fan_gpio[0]['base'] + gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum) + gpio_file = gpio_dir + "/value" + retval = self._api_helper.read_txt_file(gpio_file) + return retval.rstrip('\r\n') + + def __set_gpio_value(self, pinnum, value=0): + gpio_base = self.dx010_fan_gpio[0]['base'] + gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum) + gpio_file = gpio_dir + "/value" + return self.__write_txt_file(gpio_file, value) + + 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 + if not self.is_psu_fan: + raw = self.__get_gpio_value( + self.dx010_fan_gpio[self.fan_tray_index+1]['dir']) + + direction = self.FAN_DIRECTION_INTAKE if int( + raw, 10) == 0 else self.FAN_DIRECTION_EXHAUST + + return direction + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + + Note: + speed = pwm_in/255*100 + """ + speed = 0 + if self.is_psu_fan: + fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1) + fan_speed_sysfs_path = self.__search_file_by_name( + self.psu_hwmon_path, fan_speed_sysfs_name) + fan_speed_rpm = self._api_helper.read_txt_file( + fan_speed_sysfs_path) or 0 + fan_speed_raw = float(fan_speed_rpm)/PSU_FAN_MAX_RPM * 100 + speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM) + elif self.get_presence(): + chip = self.emc2305_chip_mapping[self.fan_index] + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_PATH, device, EMC2305_FAN_INPUT) + sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index]) + raw = self._api_helper.read_txt_file(sysfs_path).strip('\r\n') + pwm = int(raw, 10) if raw else 0 + speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM)) + + return int(speed) + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + + Note: + speed_pc = pwm_target/255*100 + + 0 : when PWM mode is use + pwm : when pwm mode is not use + """ + return 'N/A' + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + return 10 + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + + Note: + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + """ + pwm = speed * 255 / 100 + if not self.is_psu_fan and self.get_presence(): + chip = self.emc2305_chip_mapping[self.fan_index] + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_PATH, device, EMC2305_FAN_PWM) + sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index]) + return self.__write_txt_file(sysfs_path, int(pwm)) + + return False + + 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 + """ + set_status_led = False + if not self.is_psu_fan: + s1, s2 = False, False + try: + if color == self.STATUS_LED_COLOR_GREEN: + s1 = self.__set_gpio_value( + self.dx010_fan_gpio[self.fan_tray_index+1]['color']['red'], 1) + s2 = self.__set_gpio_value( + self.dx010_fan_gpio[self.fan_tray_index+1]['color']['green'], 0) + + elif color == self.STATUS_LED_COLOR_RED: + s1 = self.__set_gpio_value( + self.dx010_fan_gpio[self.fan_tray_index+1]['color']['red'], 0) + s2 = self.__set_gpio_value( + self.dx010_fan_gpio[self.fan_tray_index+1]['color']['green'], 1) + + elif color == self.STATUS_LED_COLOR_OFF: + s1 = self.__set_gpio_value( + self.dx010_fan_gpio[self.fan_tray_index+1]['color']['red'], 1) + s2 = self.__set_gpio_value( + self.dx010_fan_gpio[self.fan_tray_index+1]['color']['green'], 1) + set_status_led = s1 and s2 + return set_status_led + except IOError: + return False + + return set_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 + """ + present_str = self.__get_gpio_value( + self.dx010_fan_gpio[self.fan_tray_index+1]['prs']) + + return int(present_str, 10) == 0 if not self.is_psu_fan else True + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + if self.is_psu_fan: + return NULL_VAL + + model = NULL_VAL + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + if self.is_psu_fan: + return NULL_VAL + + serial = NULL_VAL + 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 + """ + status = 1 + if self.is_psu_fan: + fan_fault_sysfs_name = "fan1_fault" + fan_fault_sysfs_path = self.__search_file_by_name( + self.psu_hwmon_path, fan_fault_sysfs_name) + status = self._api_helper.read_one_line_file(fan_fault_sysfs_path) + + elif self.get_presence(): + chip = self.emc2305_chip_mapping[self.fan_index] + device = chip['device'] + fan_index = chip['index_map'] + sysfs_path = "%s%s/%s" % ( + EMC2305_PATH, device, 'fan{}_fault') + sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index]) + status = self._api_helper.read_one_line_file(sysfs_path) + + return False if int(status) != 0 else True diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/helper.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/helper.py new file mode 100644 index 000000000000..140c62c08666 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/helper.py @@ -0,0 +1,133 @@ +import os +import struct +import subprocess +from mmap import * + +from sonic_py_common import device_info + +HOST_CHK_CMD = "docker > /dev/null 2>&1" +EMPTY_STRING = "" + + +class APIHelper(): + + def __init__(self): + (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() + + def is_host(self): + return os.system(HOST_CHK_CMD) == 0 + + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except: + status = False + return status, result + + def run_command(self, cmd): + status = True + result = "" + try: + p = subprocess.Popen( + cmd, shell=True, universal_newlines=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 run_interactive_command(self, cmd): + try: + os.system(cmd) + except: + return False + return True + + 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 read_one_line_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.readline() + return data.strip() + except IOError: + pass + return None + + def write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except Exception: + return False + return True + + def get_cpld_reg_value(self, getreg_path, register): + cmd = "echo {1} > {0}; cat {0}".format(getreg_path, register) + status, result = self.run_command(cmd) + return result if status else 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, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + result = raw_data.strip() + else: + status = False + 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, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + result = raw_data.strip() + else: + status = False + except: + status = False + return status, result + + def ipmi_set_ss_thres(self, id, threshold_key, value): + status = True + result = "" + try: + cmd = "ipmitool sensor thresh '{}' {} {}".format( + str(id), str(threshold_key), str(value)) + p = subprocess.Popen( + cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + result = raw_data.strip() + else: + status = False + except: + status = False + return status, result diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/platform.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/platform.py new file mode 100644 index 000000000000..7d98ec9f7cdf --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/platform.py @@ -0,0 +1,21 @@ +############################################################################# +# 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/device/celestica/x86_64-cel_seastone-r0/sonic_platform/psu.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/psu.py new file mode 100644 index 000000000000..f9a342953aeb --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/psu.py @@ -0,0 +1,223 @@ +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os +import sonic_platform + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +GREEN_LED_PATH = "/sys/devices/platform/leds_dx010/leds/dx010:green:p-{}/brightness" +HWMON_PATH = "/sys/bus/i2c/devices/i2c-{0}/{0}-00{1}/hwmon" +GPIO_DIR = "/sys/class/gpio" +GPIO_LABEL = "pca9505" +PSU_NAME_LIST = ["PSU-1", "PSU-2"] +PSU_NUM_FAN = [1, 1] +PSU_I2C_MAPPING = { + 0: { + "num": 10, + "addr": "5a" + }, + 1: { + "num": 11, + "addr": "5b" + }, +} + + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, psu_index): + PsuBase.__init__(self) + self.index = psu_index + self._api_helper = APIHelper() + self.green_led_path = GREEN_LED_PATH.format(self.index+1) + self.dx010_psu_gpio = [ + {'base': self.__get_gpio_base()}, + {'prs': 27, 'status': 22}, + {'prs': 28, 'status': 25} + ] + self.i2c_num = PSU_I2C_MAPPING[self.index]["num"] + self.i2c_addr = PSU_I2C_MAPPING[self.index]["addr"] + self.hwmon_path = HWMON_PATH.format(self.i2c_num, self.i2c_addr) + for fan_index in range(0, PSU_NUM_FAN[self.index]): + fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index) + self._fan_list.append(fan) + + def __search_file_by_contain(self, directory, search_str, file_start): + for dirpath, dirnames, files in os.walk(directory): + for name in files: + file_path = os.path.join(dirpath, name) + if name.startswith(file_start) and search_str in self._api_helper.read_txt_file(file_path): + return file_path + return None + + def __get_gpio_base(self): + for r in os.listdir(GPIO_DIR): + label_path = os.path.join(GPIO_DIR, r, "label") + if "gpiochip" in r and GPIO_LABEL in self._api_helper.read_txt_file(label_path): + return int(r[8:], 10) + return 216 # Reserve + + def __get_gpio_value(self, pinnum): + gpio_base = self.dx010_psu_gpio[0]['base'] + gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum) + gpio_file = gpio_dir + "/value" + retval = self._api_helper.read_txt_file(gpio_file) + return retval.rstrip('\r\n') + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + psu_voltage = 0.0 + voltage_name = "in{}_input" + voltage_label = "vout1" + + vout_label_path = self.__search_file_by_contain( + self.hwmon_path, voltage_label, "in") + if vout_label_path: + dir_name = os.path.dirname(vout_label_path) + basename = os.path.basename(vout_label_path) + in_num = ''.join(list(filter(str.isdigit, basename))) + vout_path = os.path.join( + dir_name, voltage_name.format(in_num)) + vout_val = self._api_helper.read_txt_file(vout_path) + psu_voltage = float(vout_val) / 1000 + + return psu_voltage + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + psu_current = 0.0 + current_name = "curr{}_input" + current_label = "iout1" + + curr_label_path = self.__search_file_by_contain( + self.hwmon_path, current_label, "cur") + if curr_label_path: + dir_name = os.path.dirname(curr_label_path) + basename = os.path.basename(curr_label_path) + cur_num = ''.join(list(filter(str.isdigit, basename))) + cur_path = os.path.join( + dir_name, current_name.format(cur_num)) + cur_val = self._api_helper.read_txt_file(cur_path) + psu_current = float(cur_val) / 1000 + + return psu_current + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + psu_power = 0.0 + current_name = "power{}_input" + current_label = "pout1" + + pw_label_path = self.__search_file_by_contain( + self.hwmon_path, current_label, "power") + if pw_label_path: + dir_name = os.path.dirname(pw_label_path) + basename = os.path.basename(pw_label_path) + pw_num = ''.join(list(filter(str.isdigit, basename))) + pw_path = os.path.join( + dir_name, current_name.format(pw_num)) + pw_val = self._api_helper.read_txt_file(pw_path) + psu_power = float(pw_val) / 1000000 + + return psu_power + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + return self.get_status() + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the PSU status LED + Note: Only support green and off + Returns: + bool: True if status LED state is set successfully, False if not + """ + + set_status_str = { + self.STATUS_LED_COLOR_GREEN: '1', + self.STATUS_LED_COLOR_OFF: '0' + }.get(color, None) + + if not set_status_str: + return False + + try: + with open(self.green_led_path, 'w') as file: + file.write(set_status_str) + except IOError: + return False + + return True + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + status = self._api_helper.read_txt_file(self.green_led_path) + status_str = { + '255': self.STATUS_LED_COLOR_GREEN, + '0': self.STATUS_LED_COLOR_OFF + }.get(status, None) + + return status_str + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return PSU_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + raw = self.__get_gpio_value(self.dx010_psu_gpio[self.index+1]['prs']) + return int(raw, 10) == 0 + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + raw = self.__get_gpio_value( + self.dx010_psu_gpio[self.index+1]['status']) + return int(raw, 10) == 1 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 new file mode 100644 index 000000000000..13ae4b8a47ad --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/sfp.py @@ -0,0 +1,1361 @@ +############################################################################# +# Celestica +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# + +import time +import subprocess +from ctypes import create_string_buffer + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.inf8628 import inf8628InterfaceId + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +INFO_OFFSET = 128 +DOM_OFFSET = 0 + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 + +XCVR_INTERFACE_DATA_START = 0 +XCVR_INTERFACE_DATA_SIZE = 92 + +QSFP_DOM_BULK_DATA_START = 22 +QSFP_DOM_BULK_DATA_SIZE = 36 +SFP_DOM_BULK_DATA_START = 96 +SFP_DOM_BULK_DATA_SIZE = 10 + +# definitions of the offset for values in OSFP info eeprom +OSFP_TYPE_OFFSET = 0 +OSFP_VENDOR_NAME_OFFSET = 129 +OSFP_VENDOR_PN_OFFSET = 148 +OSFP_HW_REV_OFFSET = 164 +OSFP_VENDOR_SN_OFFSET = 166 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_MODULE_MONITOR_OFFSET = 0 +QSFP_MODULE_MONITOR_WIDTH = 9 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_POWEROVERRIDE_BIT = 0 +QSFP_POWERSET_BIT = 1 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 +QSFP_MODULE_UPPER_PAGE3_START = 384 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNL_THRESHOLD_OFFSET = 176 +QSFP_CHANNL_THRESHOLD_WIDTH = 24 + +SFP_MODULE_ADDRA2_OFFSET = 256 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_CHANNL_STATUS_OFFSET = 110 +SFP_CHANNL_STATUS_WIDTH = 1 + + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" +OSFP_TYPE = "OSFP" + +PORT_START = 1 +PORT_END = 56 +QSFP_PORT_START = 1 +QSFP_PORT_END = 32 + +SFP_I2C_START = 26 + + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + + # Path to QSFP sysfs + RESET_PATH = "/sys/devices/platform/dx010_cpld/qsfp_reset" + LP_PATH = "/sys/devices/platform/dx010_cpld/qsfp_lpmode" + PRS_PATH = "/sys/devices/platform/dx010_cpld/qsfp_modprs" + + def __init__(self, sfp_index, sfp_name): + SfpBase.__init__(self) + # Init index + self.index = sfp_index + self.port_num = self.index + 1 + self.dom_supported = False + self.sfp_type, self.port_name = self.__get_sfp_info() + self._api_helper = APIHelper() + self.name = sfp_name + + # Init eeprom path + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' + self.port_to_eeprom_mapping = {} + self.port_to_i2c_mapping = {} + + for x in range(PORT_START, PORT_END + 1): + self.port_to_i2c_mapping[x] = (SFP_I2C_START + x) - 1 + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + + self.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + self._dom_capability_detect() + + def __get_sfp_info(self): + port_name = "Unknown" + sfp_type = "Unknown" + + if self.port_num >= QSFP_PORT_START and self.port_num <= QSFP_TYPE: + sfp_type = QSFP_TYPE + port_name = "QSFP" + str(self.port_num - QSFP_PORT_START + 1) + elif self.port_num >= SFP_PORT_START and self.port_num <= SFP_PORT_END: + sfp_type = SFP_TYPE + port_name = "SFP" + str(self.port_num - SFP_PORT_START + 1) + return sfp_type, port_name + + def __convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def _dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + return + + if self.sfp_type == "QSFP": + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # 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( + (offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self.__read_eeprom_specific_bytes( + QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH) + qsfp_version_compliance = int( + qsfp_version_compliance_raw[0], 16) + dom_capability = sfpi_obj.parse_dom_capability( + qsfp_dom_capability_raw, 0) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = dom_capability['data']['Temp_support']['value'] == 'On' + self.dom_volt_supported = dom_capability['data']['Voltage_support']['value'] == 'On' + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = dom_capability['data']['Tx_power_support']['value'] == 'On' + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = True + + self.dom_supported = True + self.calibration = 1 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + qsfp_option_value_raw = self.__read_eeprom_specific_bytes( + QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH) + if qsfp_option_value_raw is not None: + optional_capability = sfpd_obj.parse_option_params( + qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = optional_capability[ + 'data']['TxDisable']['value'] == 'On' + dom_status_indicator = sfpd_obj.parse_dom_status_indicator( + qsfp_version_compliance_raw, 1) + self.qsfp_page3_available = dom_status_indicator['data']['FlatMem']['value'] == 'Off' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.qsfp_page3_available = False + + elif self.sfp_type == "SFP": + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = ( + int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + if not self.get_presence(): + return transceiver_info_dict + + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + if self.sfp_type == OSFP_TYPE: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP + + sfpi_obj = inf8628InterfaceId() + if sfpi_obj is None: + return None + + sfp_type_raw = self.__read_eeprom_specific_bytes( + (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes( + (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes( + (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( + (offset + OSFP_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes( + (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_vendor_sn_raw, 0) + else: + return None + + transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = 'N/A' + transceiver_info_dict['vendor_date'] = 'N/A' + transceiver_info_dict['connector'] = 'N/A' + transceiver_info_dict['encoding'] = 'N/A' + transceiver_info_dict['ext_identifier'] = 'N/A' + transceiver_info_dict['ext_rateselect_compliance'] = 'N/A' + transceiver_info_dict['cable_type'] = 'N/A' + transceiver_info_dict['cable_length'] = 'N/A' + transceiver_info_dict['specification_compliance'] = '{}' + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + + else: + if self.sfp_type == QSFP_TYPE: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + # cable_length_width = XCVR_CABLE_LENGTH_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + # cable_length_width = XCVR_CABLE_LENGTH_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + offset + XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE) + if sfp_interface_bulk_raw is None: + return None + + start = XCVR_INTFACE_BULK_OFFSET - XCVR_INTERFACE_DATA_START + end = start + interface_info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_NAME_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_NAME_WIDTH + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_PN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_PN_WIDTH + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_HW_REV_OFFSET - XCVR_INTERFACE_DATA_START + end = start + vendor_rev_width + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_SN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_SN_WIDTH + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_OUI_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_OUI_WIDTH + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_DATE_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_DATE_WIDTH + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_interface_bulk_raw[start: end], 0) + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + + if self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_DOM_BULK_DATA_START), QSFP_DOM_BULK_DATA_SIZE) + if dom_data_raw is None: + return transceiver_dom_info_dict + + if self.dom_temp_supported: + start = QSFP_TEMPE_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + temp = self.__convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + if temp is not None: + transceiver_dom_info_dict['temperature'] = temp + + if self.dom_volt_supported: + start = QSFP_VOLT_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + volt = self.__convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + if volt is not None: + transceiver_dom_info_dict['voltage'] = volt + + start = QSFP_CHANNL_MON_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power( + dom_data_raw[start: end], 0) + + if self.dom_tx_power_supported: + transceiver_dom_info_dict['tx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX1Power']['value']) + transceiver_dom_info_dict['tx2power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX2Power']['value']) + transceiver_dom_info_dict['tx3power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX3Power']['value']) + transceiver_dom_info_dict['tx4power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX4Power']['value']) + + if self.dom_rx_power_supported: + transceiver_dom_info_dict['rx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX1Power']['value']) + transceiver_dom_info_dict['rx2power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX2Power']['value']) + transceiver_dom_info_dict['rx3power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX3Power']['value']) + transceiver_dom_info_dict['rx4power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX4Power']['value']) + + transceiver_dom_info_dict['tx1bias'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX1Bias']['value']) + transceiver_dom_info_dict['tx2bias'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX2Bias']['value']) + transceiver_dom_info_dict['tx3bias'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX3Bias']['value']) + transceiver_dom_info_dict['tx4bias'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX4Bias']['value']) + + else: + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_DOM_BULK_DATA_START), SFP_DOM_BULK_DATA_SIZE) + + start = SFP_TEMPE_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + + start = SFP_VOLT_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + + start = SFP_CHANNL_MON_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_CHANNL_MON_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_data_raw[start: end], 0) + + transceiver_dom_info_dict['temperature'] = self.__convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + transceiver_dom_info_dict['voltage'] = self.__convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + transceiver_dom_info_dict['rx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RXPower']['value']) + transceiver_dom_info_dict['tx1bias'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXBias']['value']) + transceiver_dom_info_dict['tx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXPower']['value']) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + transceiver_dom_threshold_info_dict = dict.fromkeys( + self.threshold_dict_keys, 'N/A') + + if self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + if not self.dom_supported or not self.qsfp_page3_available: + return transceiver_dom_threshold_info_dict + + # Dom Threshold data starts from offset 384 + # Revert offset back to 0 once data is retrieved + offset = QSFP_MODULE_UPPER_PAGE3_START + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values( + dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNL_THRESHOLD_OFFSET), + QSFP_CHANNL_THRESHOLD_WIDTH) + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values( + dom_channel_threshold_raw, 0) + + # 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'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + + else: + offset = SFP_MODULE_ADDRA2_OFFSET + + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = sff8472Dom(None, self.calibration) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((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 + + # 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'] + + for key in transceiver_dom_threshold_info_dict: + transceiver_dom_threshold_info_dict[key] = self.__convert_string_to_num( + transceiver_dom_threshold_info_dict[key]) + + return transceiver_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + reset_status_raw = self._api_helper.read_txt_file(self.RESET_PATH).rstrip() + if not reset_status_raw: + return False + + reg_value = int(reset_status_raw, 16) + bin_format = bin(reg_value)[2:].zfill(32) + return bin_format[::-1][self.index] == '0' + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + rx_los = False + if self.sfp_type == OSFP_TYPE: + return False + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx1_los = (rx_los_data & 0x01 != 0) + rx2_los = (rx_los_data & 0x02 != 0) + rx3_los = (rx_los_data & 0x04 != 0) + rx4_los = (rx_los_data & 0x08 != 0) + rx_los = (rx1_los and rx2_los and rx3_los and rx4_los) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los = (rx_los_data & 0x02 != 0) + + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + tx4_fault = False + + if self.sfp_type == OSFP_TYPE or not self.dom_supported: + return False + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx1_fault = (tx_fault_data & 0x01 != 0) + tx2_fault = (tx_fault_data & 0x02 != 0) + tx3_fault = (tx_fault_data & 0x04 != 0) + tx4_fault = (tx_fault_data & 0x08 != 0) + tx4_fault = ( + tx1_fault and tx2_fault and tx3_fault and tx4_fault) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx4_fault = (tx_fault_data & 0x04 != 0) + + return tx4_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + + tx_disable = False + + if self.sfp_type == OSFP_TYPE and not self.dom_supported: + return False + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_DISABLE_STATUS_OFFSET), QSFP_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx1_disable = (tx_disable_data & 0x01 != 0) + tx2_disable = (tx_disable_data & 0x02 != 0) + tx3_disable = (tx_disable_data & 0x04 != 0) + tx4_disable = (tx_disable_data & 0x08 != 0) + tx_disable = ( + tx1_disable and tx2_disable and tx3_disable and tx4_disable) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable = (tx_disable_data & 0xC0 != 0) + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_list = [False, False, False, False] + + if self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_DISABLE_STATUS_OFFSET), QSFP_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list[0] = (tx_disable_data & 0x01 != 0) + tx_disable_list[1] = (tx_disable_data & 0x02 != 0) + tx_disable_list[2] = (tx_disable_data & 0x04 != 0) + tx_disable_list[3] = (tx_disable_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list[0] = (tx_disable_data & 0xC0 != 0) + + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + try: + reg_file = open(self.LP_PATH, "r") + content = reg_file.readline().rstrip() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + bit_index = self.index + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + if self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes( + dom_control_raw, 0) + power_override = ( + 'On' == dom_control_data['data']['PowerOverride']['value']) + return power_override + else: + return False + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + transceiver_bulk_status = self.get_transceiver_bulk_status() + return transceiver_bulk_status.get("temperature", "N/A") + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + Returns: + An integer number of supply voltage in mV + """ + transceiver_bulk_status = self.get_transceiver_bulk_status() + return transceiver_bulk_status.get("voltage", "N/A") + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + transceiver_bulk_status = self.get_transceiver_bulk_status() + tx1_bs = transceiver_bulk_status.get("tx1bias", "N/A") + tx2_bs = transceiver_bulk_status.get("tx2bias", "N/A") + tx3_bs = transceiver_bulk_status.get("tx3bias", "N/A") + tx4_bs = transceiver_bulk_status.get("tx4bias", "N/A") + tx_bias_list = [tx1_bs, tx2_bs, tx3_bs, tx4_bs] + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + rx_power_list = [] + transceiver_bulk_status = self.get_transceiver_bulk_status() + rx1_p = transceiver_bulk_status.get("rx1power", "N/A") + rx2_p = transceiver_bulk_status.get("rx2power", "N/A") + rx3_p = transceiver_bulk_status.get("rx3power", "N/A") + rx4_p = transceiver_bulk_status.get("rx4power", "N/A") + rx_power_list = [rx1_p, rx2_p, rx3_p, rx4_p] + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + tx_power_list = [] + transceiver_bulk_status = self.get_transceiver_bulk_status() + tx1_p = transceiver_bulk_status.get("tx1power", "N/A") + tx2_p = transceiver_bulk_status.get("tx2power", "N/A") + tx3_p = transceiver_bulk_status.get("tx3power", "N/A") + tx4_p = transceiver_bulk_status.get("tx4power", "N/A") + tx_power_list = [tx1_p, tx2_p, tx3_p, tx4_p] + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + # Check for invalid port_num + + try: + reg_file = open(self.RESET_PATH, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the + # register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + bit_index = self.index + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value).rstrip('L')) + 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(self.RESET_PATH, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value).rstrip('L')) + reg_file.close() + + return True + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + if self.sfp_type == QSFP_TYPE: + sysfsfile_eeprom = None + try: + tx_disable_ctl = 0xf if tx_disable else 0x0 + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + #print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + Returns: + A boolean, True if successful, False if not + """ + if self.sfp_type == QSFP_TYPE: + sysfsfile_eeprom = None + try: + channel_state = self.get_tx_disable_channel() + tx_enable_mask = [0xe, 0xd, 0xb, 0x7] + tx_disable_mask = [0x1, 0x3, 0x7, 0xf] + tx_disable_ctl = channel_state | tx_disable_mask[ + channel] if disable else channel_state & tx_enable_mask[channel] + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + #print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + try: + reg_file = open(self.LP_PATH, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + bit_index = self.index + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + # LPMode is active high; set or clear the bit accordingly + reg_value = reg_value | mask if lpmode else reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value).strip('L') + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + if self.sfp_type == QSFP_TYPE: + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + #print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + ############################################################## + ###################### Device methods ######################## + ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self.name + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + presence_status_raw = self._api_helper.read_txt_file(self.PRS_PATH).rstrip() + if not presence_status_raw: + return False + + content = presence_status_raw.rstrip() + reg_value = int(content, 16) + + # Determind if port_num start from 1 or 0 + bit_index = self.index + + # Mask off the bit corresponding to our port + mask = (1 << bit_index) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("model", "N/A") + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("serial", "N/A") + + 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 not self.get_reset_status() diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal.py new file mode 100644 index 000000000000..2b38ef94d6c4 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal.py @@ -0,0 +1,235 @@ +############################################################################# +# Celestica +# +# Thermal contains an implementation of SONiC Platform Base API and +# provides the thermal device status which are available in the platform +# +############################################################################# + +import os +import re +import os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +THERMAL_INFO = { + 0: { + "F2B_max": 50, + "B2F_max": 55, + "postion": "asic", + "name": "Front-panel temp sensor 1", + "i2c_path": "i2c-5/5-0048/hwmon/hwmon1", # u4 system-inlet + }, + 1: { + "F2B_max": 50, + "B2F_max": 55, + "postion": "asic", + "name": "Front-panel temp sensor 2", + "i2c_path": "i2c-6/6-0049/hwmon/hwmon2", # u2 system-inlet + }, + 2: { + "F2B_max": 70, + "F2B_max_crit": 75, + "B2F_max": 60, + "B2F_max_crit": 65, + "postion": "asic", + "name": "ASIC temp sensor", + "i2c_path": "i2c-7/7-004a/hwmon/hwmon3", # u44 bmc56960-on-board + }, + 3: { + "F2B_max": 70, + "F2B_max_crit": 75, + "B2F_max": 70, + "B2F_max_crit": 75, + "postion": "cpu", + "name": "Rear-panel temp sensor 1", + "i2c_path": "i2c-14/14-0048/hwmon/hwmon4", # u9200 cpu-on-board + }, + 4: { + "F2B_max": 70, + "B2F_max": 55, + "postion": "cpu", + "name": "Rear-panel temp sensor 2", + "i2c_path": "i2c-15/15-004e/hwmon/hwmon5" # u9201 system-outlet + } +} +NULL_VAL = "N/A" +I2C_ADAPTER_PATH = "/sys/class/i2c-adapter" + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + SS_CONFIG_PATH = "/usr/share/sonic/device/x86_64-cel_seastone-r0/sensors.conf" + + def __init__(self, thermal_index, airflow): + self.index = thermal_index + self._api_helper = APIHelper() + self._airflow = airflow + self._thermal_info = THERMAL_INFO[self.index] + self._hwmon_path = "{}/{}".format(I2C_ADAPTER_PATH, + self._thermal_info["i2c_path"]) + self.name = self.get_name() + self.postion = self._thermal_info["postion"] + self.ss_index = 1 + + def __get_temp(self, temp_file): + temp_file_path = os.path.join(self._hwmon_path, temp_file) + raw_temp = self._api_helper.read_txt_file(temp_file_path) + temp = float(raw_temp)/1000 + return float("{:.3f}".format(temp)) + + def __set_threshold(self, file_name, temperature): + temp_file_path = os.path.join(self._hwmon_path, file_name) + try: + with open(temp_file_path, 'w') as fd: + fd.write(str(temperature)) + return True + except IOError: + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temp_file = "temp{}_input".format(self.ss_index) + return self.__get_temp(temp_file) + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + max_crit_key = '{}_max'.format(self._airflow) + return self._thermal_info.get(max_crit_key, None) + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return 0.0 + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if not + """ + temp_file = "temp{}_max".format(self.ss_index) + is_set = self.__set_threshold(temp_file, int(temperature*1000)) + file_set = False + if is_set: + try: + with open(self.SS_CONFIG_PATH, 'r+') as f: + content = f.readlines() + f.seek(0) + ss_found = False + for idx, val in enumerate(content): + if self.name in val: + ss_found = True + elif ss_found and temp_file in val: + content[idx] = " set {} {}\n".format( + temp_file, temperature) + f.writelines(content) + file_set = True + break + except IOError: + file_set = False + + return is_set & file_set + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if not + """ + return False + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + max_crit_key = '{}_max_crit'.format(self._airflow) + return self._thermal_info.get(max_crit_key, None) + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature of thermal + Returns: + A float number, the low critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return 0.0 + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self._thermal_info["name"] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + temp_file = "temp{}_input".format(self.ss_index) + temp_file_path = os.path.join(self._hwmon_path, temp_file) + return os.path.isfile(temp_file_path) + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return NULL_VAL + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return NULL_VAL + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + if not self.get_presence(): + return False + + fault_file = "temp{}_fault".format(self.ss_index) + fault_file_path = os.path.join(self._hwmon_path, fault_file) + if not os.path.isfile(fault_file_path): + return True + + raw_txt = self.__read_txt_file(fault_file_path) + return int(raw_txt) == 0 diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_actions.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_actions.py new file mode 100644 index 000000000000..545db861f683 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_actions.py @@ -0,0 +1,78 @@ + +from sonic_platform_base.sonic_thermal_control.thermal_action_base import ThermalPolicyActionBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object +from .thermal_infos import ChassisInfo +from .helper import APIHelper + + +@thermal_json_object('thermal_control.control') +class ControlThermalAlgoAction(ThermalPolicyActionBase): + """ + Action to control the thermal control algorithm + """ + # JSON field definition + JSON_FIELD_STATUS = 'status' + + def __init__(self): + self.status = True + + def load_from_json(self, json_obj): + """ + Construct ControlThermalAlgoAction via JSON. JSON example: + { + "type": "thermal_control.control" + "status": "true" + } + :param json_obj: A JSON object representing a ControlThermalAlgoAction action. + :return: + """ + if ControlThermalAlgoAction.JSON_FIELD_STATUS in json_obj: + status_str = json_obj[ControlThermalAlgoAction.JSON_FIELD_STATUS].lower() + if status_str == 'true': + self.status = True + elif status_str == 'false': + self.status = False + else: + raise ValueError('Invalid {} field value, please specify true of false'. + format(ControlThermalAlgoAction.JSON_FIELD_STATUS)) + else: + raise ValueError('ControlThermalAlgoAction ' + 'missing mandatory field {} in JSON policy file'. + format(ControlThermalAlgoAction.JSON_FIELD_STATUS)) + + def execute(self, thermal_info_dict): + """ + Disable thermal control algorithm + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + if ChassisInfo.INFO_NAME in thermal_info_dict: + chassis_info_obj = thermal_info_dict[ChassisInfo.INFO_NAME] + chassis = chassis_info_obj.get_chassis() + thermal_manager = chassis.get_thermal_manager() + if self.status: + thermal_manager.start_thermal_control_algorithm() + else: + thermal_manager.stop_thermal_control_algorithm() + + +@thermal_json_object('switch.power_cycling') +class SwitchPolicyAction(ThermalPolicyActionBase): + """ + Base class for thermal action. Once all thermal conditions in a thermal policy are matched, + all predefined thermal action will be executed. + """ + + def execute(self, thermal_info_dict): + """ + Take action when thermal condition matches. For example, power cycle the switch. + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + thermal_overload_position_path = '/tmp/thermal_overload_position' + thermal_overload_position = APIHelper().read_one_line_file( + thermal_overload_position_path) + + cmd = 'bash /usr/share/sonic/platform/thermal_overload_control.sh {}'.format( + thermal_overload_position) + APIHelper().run_command(cmd) diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_conditions.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_conditions.py new file mode 100644 index 000000000000..1eee8ea91ab5 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_conditions.py @@ -0,0 +1,77 @@ +from sonic_platform_base.sonic_thermal_control.thermal_condition_base import ThermalPolicyConditionBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object + + +class FanCondition(ThermalPolicyConditionBase): + def get_fan_info(self, thermal_info_dict): + from .thermal_infos import FanInfo + if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo): + return thermal_info_dict[FanInfo.INFO_NAME] + else: + return None + + +@thermal_json_object('fan.any.absence') +class AnyFanAbsenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fans()) > 0 if fan_info_obj else False + + +@thermal_json_object('fan.any.fault') +class AnyFanFaultCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_fault_fans()) > 0 if fan_info_obj else False + + +@thermal_json_object('fan.all.presence') +class AllFanPresenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fans()) == 0 if fan_info_obj else False + + +@thermal_json_object('fan.all.good') +class AllFanGoodCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_fault_fans()) == 0 if fan_info_obj else False + + +class ThermalCondition(ThermalPolicyConditionBase): + def get_thermal_info(self, thermal_info_dict): + from .thermal_infos import ThermalInfo + if ThermalInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[ThermalInfo.INFO_NAME], ThermalInfo): + return thermal_info_dict[ThermalInfo.INFO_NAME] + else: + return None + + +@thermal_json_object('thermal.over.high_threshold') +class ThermalOverHighCriticalCondition(ThermalCondition): + def is_match(self, thermal_info_dict): + thermal_info_obj = self.get_thermal_info(thermal_info_dict) + if thermal_info_obj: + return thermal_info_obj.is_over_high_threshold() + else: + return False + + +@thermal_json_object('thermal.over.high_critical_threshold') +class ThermalOverHighCriticalCondition(ThermalCondition): + def is_match(self, thermal_info_dict): + thermal_info_obj = self.get_thermal_info(thermal_info_dict) + if thermal_info_obj: + return thermal_info_obj.is_over_high_critical_threshold() + else: + return False + +@thermal_json_object('thermal.all.good') +class ThermalGoodCondition(ThermalCondition): + def is_match(self, thermal_info_dict): + thermal_info_obj = self.get_thermal_info(thermal_info_dict) + if thermal_info_obj: + return not thermal_info_obj.is_over_threshold() + else: + return False diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_infos.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_infos.py new file mode 100644 index 000000000000..a680b31b634f --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_infos.py @@ -0,0 +1,165 @@ +from sonic_platform_base.sonic_thermal_control.thermal_info_base import ThermalPolicyInfoBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object +from .helper import APIHelper +import time + + +@thermal_json_object('fan_info') +class FanInfo(ThermalPolicyInfoBase): + """ + Fan information needed by thermal policy + """ + + # Fan information name + INFO_NAME = 'fan_info' + + def __init__(self): + self._absence_fans = set() + self._presence_fans = set() + self._fault_fans = set() + self._status_changed = False + + def collect(self, chassis): + """ + Collect absence and presence fans. + :param chassis: The chassis object + :return: + """ + self._status_changed = False + for fan in chassis.get_all_fans(): + presence = fan.get_presence() + status = fan.get_status() + if presence and fan not in self._presence_fans: + self._presence_fans.add(fan) + self._status_changed = True + if fan in self._absence_fans: + self._absence_fans.remove(fan) + elif not presence and fan not in self._absence_fans: + self._absence_fans.add(fan) + self._status_changed = True + if fan in self._presence_fans: + self._presence_fans.remove(fan) + + if not status and fan not in self._fault_fans: + self._fault_fans.add(fan) + self._status_changed = True + + elif status and fan in self._fault_fans: + self._fault_fans.remove(fan) + self._status_changed = True + + def get_absence_fans(self): + """ + Retrieves absence fans + :return: A set of absence fans + """ + return self._absence_fans + + def get_presence_fans(self): + """ + Retrieves presence fans + :return: A set of presence fans + """ + return self._presence_fans + + def get_fault_fans(self): + """ + Retrieves fault fans + :return: A set of fault fans + """ + return self._fault_fans + + def is_status_changed(self): + """ + Retrieves if the status of fan information changed + :return: True if status changed else False + """ + return self._status_changed + + +@thermal_json_object('thermal_info') +class ThermalInfo(ThermalPolicyInfoBase): + """ + Thermal information needed by thermal policy + """ + + # Fan information name + INFO_NAME = 'thermal_info' + + def collect(self, chassis): + """ + Collect thermal sensor temperature change status + :param chassis: The chassis object + :return: + """ + self._over_high_threshold = False + self._over_high_critical_threshold = False + self._thermal_overload_position = 'cpu' + + # Calculate average temp within the device + temp = 0 + num_of_thermals = chassis.get_num_thermals() + for index in range(num_of_thermals): + thermal = chassis.get_thermal(index) + temp = thermal.get_temperature() + high_threshold = thermal.get_high_threshold() + high_critical_threshold = thermal.get_high_critical_threshold() + + if high_threshold and temp > high_threshold: + self._over_high_threshold = True + + if high_critical_threshold and temp > high_critical_threshold: + self._thermal_overload_position = thermal.postion + self._over_high_critical_threshold = True + + def is_over_threshold(self): + """ + Retrieves if the temperature is over any threshold + :return: True if the temperature is over any threshold else False + """ + return self._over_high_threshold or self._over_high_critical_threshold + + def is_over_high_critical_threshold(self): + """ + Retrieves if the temperature is over high critical threshold + :return: True if the temperature is over high critical threshold else False + """ + thermal_overload_position_path = '/tmp/thermal_overload_position' + if self._over_high_critical_threshold: + APIHelper().write_txt_file(thermal_overload_position_path, + self._thermal_overload_position) + time.sleep(1) + return self._over_high_critical_threshold + + def is_over_high_threshold(self): + """ + Retrieves if the temperature is over high threshold + :return: True if the temperature is over high threshold else False + """ + return self._over_high_threshold + + +@thermal_json_object('chassis_info') +class ChassisInfo(ThermalPolicyInfoBase): + """ + Chassis information needed by thermal policy + """ + INFO_NAME = 'chassis_info' + + def __init__(self): + self._chassis = None + + def collect(self, chassis): + """ + Collect platform chassis. + :param chassis: The chassis object + :return: + """ + self._chassis = chassis + + def get_chassis(self): + """ + Retrieves platform chassis object + :return: A platform chassis object. + """ + return self._chassis diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_manager.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_manager.py new file mode 100644 index 000000000000..9f057cf1f37f --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/thermal_manager.py @@ -0,0 +1,46 @@ +from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase +from .helper import APIHelper +from .thermal_actions import * +from .thermal_conditions import * +from .thermal_infos import * + +class ThermalManager(ThermalManagerBase): + FSC_ALGORITHM_CMD = 'service fancontrol {}' + + @classmethod + def start_thermal_control_algorithm(cls): + """ + Start vendor specific thermal control algorithm. The default behavior of this function is a no-op. + :return: + """ + return cls._enable_fancontrol_service(True) + + @classmethod + def stop_thermal_control_algorithm(cls): + """ + Stop thermal control algorithm + Returns: + bool: True if set success, False if fail. + """ + return cls._enable_fancontrol_service(False) + + @classmethod + def deinitialize(cls): + """ + Destroy thermal manager, including any vendor specific cleanup. The default behavior of this function + is a no-op. + :return: + """ + return cls._enable_fancontrol_service(True) + + @classmethod + def _enable_fancontrol_service(cls, enable): + """ + Control thermal by fcs algorithm + Args: + enable: Bool, indicate enable the algorithm or not + Returns: + bool: True if set success, False if fail. + """ + cmd = 'start' if enable else 'stop' + return APIHelper().run_command(cls.FSC_ALGORITHM_CMD.format(cmd)) diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/watchdog.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/watchdog.py new file mode 100644 index 000000000000..31bb911d2401 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/watchdog.py @@ -0,0 +1,189 @@ +############################################################################# +# Celestica +# +# Watchdog contains an implementation of SONiC Platform Base API +# +############################################################################# +import ctypes +import os +import subprocess +import time + +try: + from sonic_platform_base.watchdog_base import WatchdogBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PLATFORM_CPLD_PATH = '/sys/devices/platform/dx010_cpld' +GETREG_FILE = 'getreg' +SETREG_FILE = 'setreg' +WDT_ENABLE_REG = '0x141' +WDT_TIMER_L_BIT_REG = '0x142' +WDT_TIMER_M_BIT_REG = '0x143' +WDT_TIMER_H_BIT_REG = '0x144' +WDT_KEEP_ALVIVE_REG = '0x145' +ENABLE_CMD = '0x1' +DISABLE_CMD = '0x0' +WDT_COMMON_ERROR = -1 + + +class Watchdog(WatchdogBase): + + def __init__(self): + # Init helper + self._api_helper = APIHelper() + + # Init cpld reg path + self.setreg_path = os.path.join(PLATFORM_CPLD_PATH, SETREG_FILE) + self.getreg_path = os.path.join(PLATFORM_CPLD_PATH, GETREG_FILE) + + # Set default value + self._disable() + self.armed = False + self.timeout = self._gettimeout() + + def _enable(self): + """ + Turn on the watchdog timer + """ + # echo 0x141 0x1 > /sys/devices/platform/dx010_cpld/setreg + enable_val = '{} {}'.format(WDT_ENABLE_REG, ENABLE_CMD) + return self._api_helper.write_txt_file(self.setreg_path, enable_val) + + def _disable(self): + """ + Turn off the watchdog timer + """ + # echo 0x141 0x0 > /sys/devices/platform/dx010_cpld/setreg + disable_val = '{} {}'.format(WDT_ENABLE_REG, DISABLE_CMD) + return self._api_helper.write_txt_file(self.setreg_path, disable_val) + + def _keepalive(self): + """ + Keep alive watchdog timer + """ + # echo 0x145 0x1 > /sys/devices/platform/dx010_cpld/setreg + enable_val = '{} {}'.format(WDT_KEEP_ALVIVE_REG, ENABLE_CMD) + return self._api_helper.write_txt_file(self.setreg_path, enable_val) + + def _get_level_hex(self, sub_hex): + sub_hex_str = sub_hex.replace("x", "0") + return hex(int(sub_hex_str, 16)) + + def _seconds_to_lmh_hex(self, seconds): + ms = seconds*1000 # calculate timeout in ms format + hex_str = hex(ms) + l = self._get_level_hex(hex_str[-2:]) + m = self._get_level_hex(hex_str[-4:-2]) + h = self._get_level_hex(hex_str[-6:-4]) + return (l, m, h) + + def _settimeout(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + # max = 0xffffff = 16777.215 seconds + + (l, m, h) = self._seconds_to_lmh_hex(seconds) + set_h_val = '{} {}'.format(WDT_TIMER_H_BIT_REG, h) + set_m_val = '{} {}'.format(WDT_TIMER_M_BIT_REG, m) + set_l_val = '{} {}'.format(WDT_TIMER_L_BIT_REG, l) + + self._api_helper.write_txt_file(self.setreg_path, set_h_val) + self._api_helper.write_txt_file(self.setreg_path, set_m_val) + self._api_helper.write_txt_file(self.setreg_path, set_l_val) + + return seconds + + def _gettimeout(self): + """ + Get watchdog timeout + @return watchdog timeout + """ + + h_bit = self._api_helper.get_cpld_reg_value( + self.getreg_path, WDT_TIMER_H_BIT_REG) + m_bit = self._api_helper.get_cpld_reg_value( + self.getreg_path, WDT_TIMER_M_BIT_REG) + l_bit = self._api_helper.get_cpld_reg_value( + self.getreg_path, WDT_TIMER_L_BIT_REG) + + hex_time = '0x{}{}{}'.format(h_bit[2:], m_bit[2:], l_bit[2:]) + ms = int(hex_time, 16) + return int(float(ms)/1000) + + ################################################################# + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* available + value. + Returns: + An integer specifying the *actual* number of seconds the watchdog + was armed with. On failure returns -1. + """ + + ret = WDT_COMMON_ERROR + if seconds < 0: + return ret + + try: + if self.timeout != seconds: + self.timeout = self._settimeout(seconds) + + if self.armed: + self._keepalive() + else: + self._enable() + self.armed = True + + ret = self.timeout + self.arm_timestamp = time.time() + except IOError as e: + pass + + return ret + + def disarm(self): + """ + Disarm the hardware watchdog + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + disarmed = False + if self.is_armed(): + try: + self._disable() + self.armed = False + disarmed = True + except IOError: + pass + + return disarmed + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + Returns: + A boolean, True if watchdog is armed, False if not + """ + + return self.armed + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds remaining on + the watchdog timer + Returns: + An integer specifying the number of seconds remaining on thei + watchdog timer. If the watchdog is not armed, returns -1. + """ + + return int(self.timeout - (time.time() - self.arm_timestamp)) if self.armed else WDT_COMMON_ERROR diff --git a/device/celestica/x86_64-cel_seastone-r0/system_health_monitoring_config.json b/device/celestica/x86_64-cel_seastone-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..4dc38d035ab4 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/system_health_monitoring_config.json @@ -0,0 +1,16 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "asic", + "psu.temperature", + "PSU2 Fan", + "PSU1 Fan" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "orange", + "normal": "green", + "booting": "orange_blink" + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/th-seastone-dx010-config-flex-all.bcm b/device/celestica/x86_64-cel_seastone-r0/th-seastone-dx010-config-flex-all.bcm new file mode 100644 index 000000000000..dc2cdf1c200d --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/th-seastone-dx010-config-flex-all.bcm @@ -0,0 +1,1063 @@ +# Define default OS / SAL +os=unix + +# all XPORTs to XE ports +#pbmp_xport_xe=0x1fffffffe +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +pbmp_oversubscribe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe + +# Mode control to select L2 Table DMA mode aka L2MODE_POLL (0) or +# L2MOD_FIFO mechanism aka L2MODE_FIFO (1) for L2 table change notification. +l2xmsg_mode=1 + +# Memory table size configs, enable ALPM +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 + +#Use MMU lossy configuration +mmu_lossless=0 + +################################################################################### +# SeaStone customized configuration +################################################################################### + +#ext mdio frequency to 495/0x80/2(1.933Mhz) or 415/0x80/2(1.62MHz) +# default is 40 +# Set external MDIO freq to 6.19MHz (495MHz) or 5.19MHz (415MHz) +#* target_freq is core_clock_freq * DIVIDEND / DIVISOR / 2 +# +rate_ext_mdio_divisor=0x80 + +# use internal rom boot +phy_ext_rom_boot=0 + +# oversubscribe mode enabled, also allow 25G+50G in the same port macro +oversubscribe_mode=1 +oversubscribe_mixed_sister_25_50_enable = 1 + +# Map the physical ports to logical ports +dport_map_enable=1 + +dport_map_port_68=1 +dport_map_port_69=2 +dport_map_port_70=3 +dport_map_port_71=4 + +dport_map_port_72=5 +dport_map_port_73=6 +dport_map_port_74=7 +dport_map_port_75=8 + +dport_map_port_76=9 +dport_map_port_77=10 +dport_map_port_78=11 +dport_map_port_79=12 + +dport_map_port_80=13 +dport_map_port_81=14 +dport_map_port_82=15 +dport_map_port_83=16 + +dport_map_port_34=17 +dport_map_port_35=18 +dport_map_port_36=19 +dport_map_port_37=20 + +dport_map_port_38=21 +dport_map_port_39=22 +dport_map_port_40=23 +dport_map_port_41=24 + +dport_map_port_42=25 +dport_map_port_43=26 +dport_map_port_44=27 +dport_map_port_45=28 + +dport_map_port_46=29 +dport_map_port_47=30 +dport_map_port_48=31 +dport_map_port_49=32 + +dport_map_port_50=33 +dport_map_port_51=34 +dport_map_port_52=35 +dport_map_port_53=36 + +dport_map_port_54=37 +dport_map_port_55=38 +dport_map_port_56=39 +dport_map_port_57=40 + +dport_map_port_58=41 +dport_map_port_59=42 +dport_map_port_60=43 +dport_map_port_61=44 + +dport_map_port_62=45 +dport_map_port_63=46 +dport_map_port_64=47 +dport_map_port_65=48 + +dport_map_port_84=49 +dport_map_port_85=50 +dport_map_port_86=51 +dport_map_port_87=52 + +dport_map_port_88=53 +dport_map_port_89=54 +dport_map_port_90=55 +dport_map_port_91=56 + +dport_map_port_92=57 +dport_map_port_93=58 +dport_map_port_94=59 +dport_map_port_95=60 + +dport_map_port_96=61 +dport_map_port_97=62 +dport_map_port_98=63 +dport_map_port_99=64 + +dport_map_port_102=65 +dport_map_port_103=66 +dport_map_port_104=67 +dport_map_port_105=68 + +dport_map_port_106=69 +dport_map_port_107=70 +dport_map_port_108=71 +dport_map_port_109=72 + +dport_map_port_110=73 +dport_map_port_111=74 +dport_map_port_112=75 +dport_map_port_113=76 + +dport_map_port_114=77 +dport_map_port_115=78 +dport_map_port_116=79 +dport_map_port_117=80 + +dport_map_port_1=81 +dport_map_port_2=82 +dport_map_port_3=83 +dport_map_port_4=84 + +dport_map_port_5=85 +dport_map_port_6=86 +dport_map_port_7=87 +dport_map_port_8=88 + +dport_map_port_9=89 +dport_map_port_10=90 +dport_map_port_11=91 +dport_map_port_12=92 + +dport_map_port_13=93 +dport_map_port_14=94 +dport_map_port_15=95 +dport_map_port_16=96 + +dport_map_port_17=97 +dport_map_port_18=98 +dport_map_port_19=99 +dport_map_port_20=100 + +dport_map_port_21=101 +dport_map_port_22=102 +dport_map_port_23=103 +dport_map_port_24=104 + +dport_map_port_25=105 +dport_map_port_26=106 +dport_map_port_27=107 +dport_map_port_28=108 + +dport_map_port_29=109 +dport_map_port_30=110 +dport_map_port_31=111 +dport_map_port_32=112 + +dport_map_port_118=113 +dport_map_port_119=114 +dport_map_port_120=115 +dport_map_port_121=116 + +dport_map_port_122=117 +dport_map_port_123=118 +dport_map_port_124=119 +dport_map_port_125=120 + +dport_map_port_126=121 +dport_map_port_127=122 +dport_map_port_128=123 +dport_map_port_129=124 + +dport_map_port_130=125 +dport_map_port_131=126 +dport_map_port_132=127 +dport_map_port_133=128 + + +# port/lane mapping, 96x25G + 16x50G +portmap_68=65:100 +portmap_69=66:25:i +portmap_70=67:25:50:i +portmap_71=68:25:i + +portmap_72=69:100 +portmap_73=70:25:i +portmap_74=71:25:50:i +portmap_75=72:25:i + +portmap_76=73:100 +portmap_77=74:25:i +portmap_78=75:25:50:i +portmap_79=76:25:i + +portmap_80=77:100 +portmap_81=78:25:i +portmap_82=79:25:50:i +portmap_83=80:25:i + +portmap_34=33:100 +portmap_35=34:25:i +portmap_36=35:25:50:i +portmap_37=36:25:i + +portmap_38=37:100 +portmap_39=38:25:i +portmap_40=39:25:50:i +portmap_41=40:25:i + +portmap_42=41:100 +portmap_43=42:25:i +portmap_44=43:25:50:i +portmap_45=44:25:i + +portmap_46=45:100 +portmap_47=46:25:i +portmap_48=47:25:50:i +portmap_49=48:25:i + +portmap_50=49:100 +portmap_51=50:25:i +portmap_52=51:25:50:i +portmap_53=52:25:i + +portmap_54=53:100 +portmap_55=54:25:i +portmap_56=55:25:50:i +portmap_57=56:25:i + +portmap_58=57:100 +portmap_59=58:25:i +portmap_60=59:25:50:i +portmap_61=60:25:i + +portmap_62=61:100 +portmap_63=62:25:i +portmap_64=63:25:50:i +portmap_65=64:25:i + +portmap_84=81:100 +portmap_85=82:25:i +portmap_86=83:25:50:i +portmap_87=84:25:i + +portmap_88=85:100 +portmap_89=86:25:i +portmap_90=87:25:50:i +portmap_91=88:25:i + +portmap_92=89:100 +portmap_93=90:25:i +portmap_94=91:25:50:i +portmap_95=92:25:i + +portmap_96=93:100 +portmap_97=94:25:i +portmap_98=95:25:50:i +portmap_99=96:25:i + +portmap_102=97:100 +portmap_103=98:25:i +portmap_104=99:25:50:i +portmap_105=100:25:i + +portmap_106=101:100 +portmap_107=102:25:i +portmap_108=103:25:50:i +portmap_109=104:25:i + +portmap_110=105:100 +portmap_111=106:25:i +portmap_112=107:25:50:i +portmap_113=108:25:i + +portmap_114=109:100 +portmap_115=110:25:i +portmap_116=111:25:50:i +portmap_117=112:25:i + +portmap_1=1:100 +portmap_2=2:25:i +portmap_3=3:25:50:i +portmap_4=4:25:i + +portmap_5=5:100 +portmap_6=6:25:i +portmap_7=7:25:50:i +portmap_8=8:25:i + +portmap_9=9:100 +portmap_10=10:25:i +portmap_11=11:25:50:i +portmap_12=12:25:i + +portmap_13=13:100 +portmap_14=14:25:i +portmap_15=15:25:50:i +portmap_16=16:25:i + + +portmap_17=17:100 +portmap_18=18:25:i +portmap_19=19:25:50:i +portmap_20=20:25:i + +portmap_21=21:100 +portmap_22=22:25:i +portmap_23=23:25:50:i +portmap_24=24:25:i + +portmap_25=25:100 +portmap_26=26:25:i +portmap_27=27:25:50:i +portmap_28=28:25:i + +portmap_29=29:100 +portmap_30=30:25:i +portmap_31=31:25:50:i +portmap_32=32:25:i + +portmap_118=113:100 +portmap_119=114:25:i +portmap_120=115:25:50:i +portmap_121=116:25:i + +portmap_122=117:100 +portmap_123=118:25:i +portmap_124=119:25:50:i +portmap_125=120:25:i + +portmap_126=121:100 +portmap_127=122:25:i +portmap_128=123:25:50:i +portmap_129=124:25:i + +portmap_130=125:100 +portmap_131=126:25:i +portmap_132=127:25:50:i +portmap_133=128:25:i + +#portmap_66=129:10 +#portmap_100=131:10 + +#WC16 +xgxs_tx_lane_map_68=0x3201 +xgxs_rx_lane_map_68=0x2310 +xgxs_tx_lane_map_69=0x3201 +xgxs_rx_lane_map_69=0x2310 +xgxs_tx_lane_map_70=0x3201 +xgxs_rx_lane_map_70=0x2310 +xgxs_tx_lane_map_71=0x3201 +xgxs_rx_lane_map_71=0x2310 + + +#WC17 +xgxs_tx_lane_map_72=0x3201 +xgxs_rx_lane_map_72=0x2301 +xgxs_tx_lane_map_73=0x3201 +xgxs_rx_lane_map_73=0x2301 +xgxs_tx_lane_map_74=0x3201 +xgxs_rx_lane_map_74=0x2301 +xgxs_tx_lane_map_75=0x3201 +xgxs_rx_lane_map_75=0x2301 + +#WC18 +xgxs_tx_lane_map_76=0x0132 +xgxs_rx_lane_map_76=0x0123 +xgxs_tx_lane_map_77=0x0132 +xgxs_rx_lane_map_77=0x0123 +xgxs_tx_lane_map_78=0x0132 +xgxs_rx_lane_map_78=0x0123 +xgxs_tx_lane_map_79=0x0132 +xgxs_rx_lane_map_79=0x0123 + +#WC19 +xgxs_tx_lane_map_80=0x2031 +xgxs_rx_lane_map_80=0x1320 +xgxs_tx_lane_map_81=0x2031 +xgxs_rx_lane_map_81=0x1320 +xgxs_tx_lane_map_82=0x2031 +xgxs_rx_lane_map_82=0x1320 +xgxs_tx_lane_map_83=0x2031 +xgxs_rx_lane_map_83=0x1320 + +#WC8 +xgxs_tx_lane_map_34=0x3021 +xgxs_rx_lane_map_34=0x0213 +xgxs_tx_lane_map_35=0x3021 +xgxs_rx_lane_map_35=0x0213 +xgxs_tx_lane_map_36=0x3021 +xgxs_rx_lane_map_36=0x0213 +xgxs_tx_lane_map_37=0x3021 +xgxs_rx_lane_map_37=0x0213 + +#WC9 +xgxs_tx_lane_map_38=0x3210 +xgxs_rx_lane_map_38=0x1023 +xgxs_tx_lane_map_39=0x3210 +xgxs_rx_lane_map_39=0x1023 +xgxs_tx_lane_map_40=0x3210 +xgxs_rx_lane_map_40=0x1023 +xgxs_tx_lane_map_41=0x3210 +xgxs_rx_lane_map_41=0x1023 + +#WC10 +xgxs_tx_lane_map_42=0x2310 +xgxs_rx_lane_map_42=0x3210 +xgxs_tx_lane_map_43=0x2310 +xgxs_rx_lane_map_43=0x3210 +xgxs_tx_lane_map_44=0x2310 +xgxs_rx_lane_map_44=0x3210 +xgxs_tx_lane_map_45=0x2310 +xgxs_rx_lane_map_45=0x3210 + +#WC11 +xgxs_tx_lane_map_46=0x1032 +xgxs_rx_lane_map_46=0x1302 +xgxs_tx_lane_map_47=0x1032 +xgxs_rx_lane_map_47=0x1302 +xgxs_tx_lane_map_48=0x1032 +xgxs_rx_lane_map_48=0x1302 +xgxs_tx_lane_map_49=0x1032 +xgxs_rx_lane_map_49=0x1302 + +#WC12 +xgxs_tx_lane_map_50=0x3201 +xgxs_rx_lane_map_50=0x0213 +xgxs_tx_lane_map_51=0x3201 +xgxs_rx_lane_map_51=0x0213 +xgxs_tx_lane_map_52=0x3201 +xgxs_rx_lane_map_52=0x0213 +xgxs_tx_lane_map_53=0x3201 +xgxs_rx_lane_map_53=0x0213 + + +#WC13 +xgxs_tx_lane_map_54=0x2301 +xgxs_rx_lane_map_54=0x2310 +xgxs_tx_lane_map_55=0x2301 +xgxs_rx_lane_map_55=0x2310 +xgxs_tx_lane_map_56=0x2301 +xgxs_rx_lane_map_56=0x2310 +xgxs_tx_lane_map_57=0x2301 +xgxs_rx_lane_map_57=0x2310 + +#WC14 +xgxs_tx_lane_map_58=0x3201 +xgxs_rx_lane_map_58=0x0213 +xgxs_tx_lane_map_59=0x3201 +xgxs_rx_lane_map_59=0x0213 +xgxs_tx_lane_map_60=0x3201 +xgxs_rx_lane_map_60=0x0213 +xgxs_tx_lane_map_61=0x3201 +xgxs_rx_lane_map_61=0x0213 + +#WC15 +xgxs_tx_lane_map_62=0x1302 +xgxs_rx_lane_map_62=0x2310 +xgxs_tx_lane_map_63=0x1302 +xgxs_rx_lane_map_63=0x2310 +xgxs_tx_lane_map_64=0x1302 +xgxs_rx_lane_map_64=0x2310 +xgxs_tx_lane_map_65=0x1302 +xgxs_rx_lane_map_65=0x2310 + +#WC20 +xgxs_tx_lane_map_84=0x0213 +xgxs_rx_lane_map_84=0x2301 +xgxs_tx_lane_map_85=0x0213 +xgxs_rx_lane_map_85=0x2301 +xgxs_tx_lane_map_86=0x0213 +xgxs_rx_lane_map_86=0x2301 +xgxs_tx_lane_map_87=0x0213 +xgxs_rx_lane_map_87=0x2301 + +#WC21 +xgxs_tx_lane_map_88=0x0132 +xgxs_rx_lane_map_88=0x3210 +xgxs_tx_lane_map_89=0x0132 +xgxs_rx_lane_map_89=0x3210 +xgxs_tx_lane_map_90=0x0132 +xgxs_rx_lane_map_90=0x3210 +xgxs_tx_lane_map_91=0x0132 +xgxs_rx_lane_map_91=0x3210 + +#WC22 +xgxs_tx_lane_map_92=0x0132 +xgxs_rx_lane_map_92=0x2031 +xgxs_tx_lane_map_93=0x0132 +xgxs_rx_lane_map_93=0x2031 +xgxs_tx_lane_map_94=0x0132 +xgxs_rx_lane_map_94=0x2031 +xgxs_tx_lane_map_95=0x0132 +xgxs_rx_lane_map_95=0x2031 + +#WC23 +xgxs_tx_lane_map_96=0x2031 +xgxs_rx_lane_map_96=0x3201 +xgxs_tx_lane_map_97=0x2031 +xgxs_rx_lane_map_97=0x3201 +xgxs_tx_lane_map_98=0x2031 +xgxs_rx_lane_map_98=0x3201 +xgxs_tx_lane_map_99=0x2031 +xgxs_rx_lane_map_99=0x3201 + +#WC24 +xgxs_tx_lane_map_102=0x0132 +xgxs_rx_lane_map_102=0x2301 +xgxs_tx_lane_map_103=0x0132 +xgxs_rx_lane_map_103=0x2301 +xgxs_tx_lane_map_104=0x0132 +xgxs_rx_lane_map_104=0x2301 +xgxs_tx_lane_map_105=0x0132 +xgxs_rx_lane_map_105=0x2301 + +#WC25 +xgxs_tx_lane_map_106=0x0132 +xgxs_rx_lane_map_106=0x3201 +xgxs_tx_lane_map_107=0x0132 +xgxs_rx_lane_map_107=0x3201 +xgxs_tx_lane_map_108=0x0132 +xgxs_rx_lane_map_108=0x3201 +xgxs_tx_lane_map_109=0x0132 +xgxs_rx_lane_map_109=0x3201 + +#WC26 +xgxs_tx_lane_map_110=0x0132 +xgxs_rx_lane_map_110=0x2031 +xgxs_tx_lane_map_111=0x0132 +xgxs_rx_lane_map_111=0x2031 +xgxs_tx_lane_map_112=0x0132 +xgxs_rx_lane_map_112=0x2031 +xgxs_tx_lane_map_113=0x0132 +xgxs_rx_lane_map_113=0x2031 + +#WC27 +xgxs_tx_lane_map_114=0x2031 +xgxs_rx_lane_map_114=0x2301 +xgxs_tx_lane_map_115=0x2031 +xgxs_rx_lane_map_115=0x2301 +xgxs_tx_lane_map_116=0x2031 +xgxs_rx_lane_map_116=0x2301 +xgxs_tx_lane_map_117=0x2031 +xgxs_rx_lane_map_117=0x2301 + + +#WC0 +xgxs_tx_lane_map_1=0x3210 +xgxs_rx_lane_map_1=0x3120 +xgxs_tx_lane_map_2=0x3210 +xgxs_rx_lane_map_2=0x3120 +xgxs_tx_lane_map_3=0x3210 +xgxs_rx_lane_map_3=0x3120 +xgxs_tx_lane_map_4=0x3210 +xgxs_rx_lane_map_4=0x3120 + +#WC1 +xgxs_tx_lane_map_5=0x0132 +xgxs_rx_lane_map_5=0x1023 +xgxs_tx_lane_map_6=0x0132 +xgxs_rx_lane_map_6=0x1023 +xgxs_tx_lane_map_7=0x0132 +xgxs_rx_lane_map_7=0x1023 +xgxs_tx_lane_map_8=0x0132 +xgxs_rx_lane_map_8=0x1023 + +#WC2 +xgxs_tx_lane_map_9=0x3201 +xgxs_rx_lane_map_9=0x3120 +xgxs_tx_lane_map_10=0x3201 +xgxs_rx_lane_map_10=0x3120 +xgxs_tx_lane_map_11=0x3201 +xgxs_rx_lane_map_11=0x3120 +xgxs_tx_lane_map_12=0x3201 +xgxs_rx_lane_map_12=0x3120 + +#WC3 +xgxs_tx_lane_map_13=0x2031 +xgxs_rx_lane_map_13=0x1032 +xgxs_tx_lane_map_14=0x2031 +xgxs_rx_lane_map_14=0x1032 +xgxs_tx_lane_map_15=0x2031 +xgxs_rx_lane_map_15=0x1032 +xgxs_tx_lane_map_16=0x2031 +xgxs_rx_lane_map_16=0x1032 + +#WC4 +xgxs_tx_lane_map_17=0x2310 +xgxs_rx_lane_map_17=0x3210 +xgxs_tx_lane_map_18=0x2310 +xgxs_rx_lane_map_18=0x3210 +xgxs_tx_lane_map_19=0x2310 +xgxs_rx_lane_map_19=0x3210 +xgxs_tx_lane_map_20=0x2310 +xgxs_rx_lane_map_20=0x3210 + +#WC5 +xgxs_tx_lane_map_21=0x2301 +xgxs_rx_lane_map_21=0x3120 +xgxs_tx_lane_map_22=0x2301 +xgxs_rx_lane_map_22=0x3120 +xgxs_tx_lane_map_23=0x2301 +xgxs_rx_lane_map_23=0x3120 +xgxs_tx_lane_map_24=0x2301 +xgxs_rx_lane_map_25=0x3120 + +#WC6 +xgxs_tx_lane_map_25=0x3201 +xgxs_rx_lane_map_25=0x0213 +xgxs_tx_lane_map_26=0x3201 +xgxs_rx_lane_map_26=0x0213 +xgxs_tx_lane_map_27=0x3201 +xgxs_rx_lane_map_27=0x0213 +xgxs_tx_lane_map_28=0x3201 +xgxs_rx_lane_map_28=0x0213 + +#WC7 +xgxs_tx_lane_map_29=0x1302 +xgxs_rx_lane_map_29=0x1023 +xgxs_tx_lane_map_30=0x1302 +xgxs_rx_lane_map_30=0x1023 +xgxs_tx_lane_map_31=0x1302 +xgxs_rx_lane_map_31=0x1023 +xgxs_tx_lane_map_32=0x1302 +xgxs_rx_lane_map_32=0x1023 + +#WC28 +xgxs_tx_lane_map_118=0x1320 +xgxs_rx_lane_map_118=0x1302 +xgxs_tx_lane_map_119=0x1320 +xgxs_rx_lane_map_119=0x1302 +xgxs_tx_lane_map_120=0x1320 +xgxs_rx_lane_map_120=0x1302 +xgxs_tx_lane_map_121=0x1320 +xgxs_rx_lane_map_121=0x1302 + +#WC29 +xgxs_tx_lane_map_122=0x1032 +xgxs_rx_lane_map_122=0x1023 +xgxs_tx_lane_map_123=0x1032 +xgxs_rx_lane_map_123=0x1023 +xgxs_tx_lane_map_124=0x1032 +xgxs_rx_lane_map_124=0x1023 +xgxs_tx_lane_map_125=0x1032 +xgxs_rx_lane_map_125=0x1023 + +#WC30 +xgxs_tx_lane_map_126=0x3120 +xgxs_rx_lane_map_126=0x3120 +xgxs_tx_lane_map_127=0x3120 +xgxs_rx_lane_map_127=0x3120 +xgxs_tx_lane_map_128=0x3120 +xgxs_rx_lane_map_128=0x3120 +xgxs_tx_lane_map_129=0x3120 +xgxs_rx_lane_map_129=0x3120 + +#WC31 +xgxs_tx_lane_map_130=0x1302 +xgxs_rx_lane_map_130=0x2310 +xgxs_tx_lane_map_131=0x1302 +xgxs_rx_lane_map_131=0x2310 +xgxs_tx_lane_map_132=0x1302 +xgxs_rx_lane_map_132=0x2310 +xgxs_tx_lane_map_133=0x1302 +xgxs_rx_lane_map_133=0x2310 + + +#Polarity flip settings + +#WC16 +phy_xaui_tx_polarity_flip_68=0x0000 +phy_xaui_tx_polarity_flip_69=0x0000 +phy_xaui_tx_polarity_flip_70=0x0000 +phy_xaui_tx_polarity_flip_71=0x0000 + +phy_xaui_rx_polarity_flip_68=0x0000 +phy_xaui_rx_polarity_flip_69=0x0000 +phy_xaui_rx_polarity_flip_70=0x0000 +phy_xaui_rx_polarity_flip_71=0x0000 + +#WC17 +phy_xaui_tx_polarity_flip_72=0x000D +phy_xaui_tx_polarity_flip_73=0x0000 +phy_xaui_tx_polarity_flip_74=0x0003 +phy_xaui_tx_polarity_flip_75=0x0001 + +phy_xaui_rx_polarity_flip_72=0x0002 +phy_xaui_rx_polarity_flip_73=0x0001 +phy_xaui_rx_polarity_flip_74=0x0000 +phy_xaui_rx_polarity_flip_75=0x0000 + +#WC18 +phy_xaui_tx_polarity_flip_76=0x000F +phy_xaui_tx_polarity_flip_77=0x0001 +phy_xaui_tx_polarity_flip_78=0x0003 +phy_xaui_tx_polarity_flip_79=0x0001 + +phy_xaui_rx_polarity_flip_76=0x0000 +phy_xaui_rx_polarity_flip_77=0x0000 +phy_xaui_rx_polarity_flip_78=0x0000 +phy_xaui_rx_polarity_flip_79=0x0000 + +#WC19 +phy_xaui_tx_polarity_flip_80=0x000F +phy_xaui_tx_polarity_flip_81=0x0001 +phy_xaui_tx_polarity_flip_82=0x0003 +phy_xaui_tx_polarity_flip_83=0x0001 + +phy_xaui_rx_polarity_flip_80=0x000F +phy_xaui_rx_polarity_flip_81=0x0001 +phy_xaui_rx_polarity_flip_82=0x0003 +phy_xaui_rx_polarity_flip_83=0x0001 + +#WC8 +phy_xaui_tx_polarity_flip_34=0x000E +phy_xaui_tx_polarity_flip_35=0x0001 +phy_xaui_tx_polarity_flip_36=0x0003 +phy_xaui_tx_polarity_flip_37=0x0001 + +phy_xaui_rx_polarity_flip_34=0x0000 +phy_xaui_rx_polarity_flip_35=0x0000 +phy_xaui_rx_polarity_flip_36=0x0000 +phy_xaui_rx_polarity_flip_37=0x0000 + +#WC9 +phy_xaui_tx_polarity_flip_38=0x0008 +phy_xaui_tx_polarity_flip_39=0x0000 +phy_xaui_tx_polarity_flip_40=0x0002 +phy_xaui_tx_polarity_flip_41=0x0001 + +phy_xaui_rx_polarity_flip_38=0x0000 +phy_xaui_rx_polarity_flip_39=0x0000 +phy_xaui_rx_polarity_flip_40=0x0000 +phy_xaui_rx_polarity_flip_41=0x0000 + +#WC10 +phy_xaui_tx_polarity_flip_42=0x000D +phy_xaui_tx_polarity_flip_43=0x0000 +phy_xaui_tx_polarity_flip_44=0x0003 +phy_xaui_tx_polarity_flip_45=0x0001 + +phy_xaui_rx_polarity_flip_42=0x0000 +phy_xaui_rx_polarity_flip_43=0x0000 +phy_xaui_rx_polarity_flip_44=0x0000 +phy_xaui_rx_polarity_flip_45=0x0000 + +#WC11 +phy_xaui_tx_polarity_flip_46=0x0000 +phy_xaui_tx_polarity_flip_47=0x0000 +phy_xaui_tx_polarity_flip_48=0x0000 +phy_xaui_tx_polarity_flip_49=0x0000 + +phy_xaui_rx_polarity_flip_46=0x0000 +phy_xaui_rx_polarity_flip_47=0x0000 +phy_xaui_rx_polarity_flip_48=0x0000 +phy_xaui_rx_polarity_flip_49=0x0000 + +#WC12 +phy_xaui_tx_polarity_flip_50=0x0002 +phy_xaui_tx_polarity_flip_51=0x0001 +phy_xaui_tx_polarity_flip_52=0x0000 +phy_xaui_tx_polarity_flip_53=0x0000 + +phy_xaui_rx_polarity_flip_50=0x0000 +phy_xaui_rx_polarity_flip_51=0x0000 +phy_xaui_rx_polarity_flip_52=0x0000 +phy_xaui_rx_polarity_flip_53=0x0000 + +#WC13 +phy_xaui_tx_polarity_flip_54=0x0002 +phy_xaui_tx_polarity_flip_55=0x0001 +phy_xaui_tx_polarity_flip_56=0x0000 +phy_xaui_tx_polarity_flip_57=0x0000 + +phy_xaui_rx_polarity_flip_54=0x0000 +phy_xaui_rx_polarity_flip_55=0x0000 +phy_xaui_rx_polarity_flip_56=0x0000 +phy_xaui_rx_polarity_flip_57=0x0000 + +#WC14 +phy_xaui_tx_polarity_flip_58=0x0000 +phy_xaui_tx_polarity_flip_59=0x0000 +phy_xaui_tx_polarity_flip_60=0x0000 +phy_xaui_tx_polarity_flip_61=0x0000 + +phy_xaui_rx_polarity_flip_58=0x0000 +phy_xaui_rx_polarity_flip_59=0x0000 +phy_xaui_rx_polarity_flip_60=0x0000 +phy_xaui_rx_polarity_flip_61=0x0000 + +#WC15 +phy_xaui_tx_polarity_flip_62=0x000A +phy_xaui_tx_polarity_flip_63=0x0001 +phy_xaui_tx_polarity_flip_64=0x0002 +phy_xaui_tx_polarity_flip_65=0x0001 + +phy_xaui_rx_polarity_flip_62=0x000F +phy_xaui_rx_polarity_flip_63=0x0001 +phy_xaui_rx_polarity_flip_64=0x0003 +phy_xaui_rx_polarity_flip_65=0x0001 + +#WC20 +phy_xaui_tx_polarity_flip_84=0x0007 +phy_xaui_tx_polarity_flip_85=0x0001 +phy_xaui_tx_polarity_flip_86=0x0001 +phy_xaui_tx_polarity_flip_87=0x0000 + +phy_xaui_rx_polarity_flip_84=0x000E +phy_xaui_rx_polarity_flip_85=0x0001 +phy_xaui_rx_polarity_flip_86=0x0003 +phy_xaui_rx_polarity_flip_87=0x0001 + +#WC21 +phy_xaui_tx_polarity_flip_88=0x000D +phy_xaui_tx_polarity_flip_89=0x0000 +phy_xaui_tx_polarity_flip_90=0x0003 +phy_xaui_tx_polarity_flip_91=0x0001 + +phy_xaui_rx_polarity_flip_88=0x000D +phy_xaui_rx_polarity_flip_89=0x0000 +phy_xaui_rx_polarity_flip_90=0x0003 +phy_xaui_rx_polarity_flip_91=0x0001 + +#WC22 +phy_xaui_tx_polarity_flip_92=0x000F +phy_xaui_tx_polarity_flip_93=0x0001 +phy_xaui_tx_polarity_flip_94=0x0003 +phy_xaui_tx_polarity_flip_95=0x0001 + +phy_xaui_rx_polarity_flip_92=0x0008 +phy_xaui_rx_polarity_flip_93=0x0000 +phy_xaui_rx_polarity_flip_94=0x0002 +phy_xaui_rx_polarity_flip_95=0x0001 + +#WC23 +phy_xaui_tx_polarity_flip_96=0x0005 +phy_xaui_tx_polarity_flip_97=0x0000 +phy_xaui_tx_polarity_flip_98=0x0001 +phy_xaui_tx_polarity_flip_99=0x0000 + +phy_xaui_rx_polarity_flip_96=0x0000 +phy_xaui_rx_polarity_flip_97=0x0000 +phy_xaui_rx_polarity_flip_98=0x0000 +phy_xaui_rx_polarity_flip_99=0x0000 + +#WC24 +phy_xaui_tx_polarity_flip_102=0x0000 +phy_xaui_tx_polarity_flip_103=0x0000 +phy_xaui_tx_polarity_flip_104=0x0000 +phy_xaui_tx_polarity_flip_105=0x0000 + +phy_xaui_rx_polarity_flip_102=0x000F +phy_xaui_rx_polarity_flip_103=0x0001 +phy_xaui_rx_polarity_flip_104=0x0003 +phy_xaui_rx_polarity_flip_105=0x0001 + +#WC25 +phy_xaui_tx_polarity_flip_106=0x000F +phy_xaui_tx_polarity_flip_107=0x0001 +phy_xaui_tx_polarity_flip_108=0x0003 +phy_xaui_tx_polarity_flip_109=0x0001 + +phy_xaui_rx_polarity_flip_106=0x0000 +phy_xaui_rx_polarity_flip_107=0x0000 +phy_xaui_rx_polarity_flip_108=0x0000 +phy_xaui_rx_polarity_flip_109=0x0000 + +#WC26 +phy_xaui_tx_polarity_flip_110=0x000F +phy_xaui_tx_polarity_flip_111=0x0001 +phy_xaui_tx_polarity_flip_112=0x0003 +phy_xaui_tx_polarity_flip_113=0x0001 + +phy_xaui_rx_polarity_flip_110=0x000F +phy_xaui_rx_polarity_flip_111=0x0001 +phy_xaui_rx_polarity_flip_112=0x0003 +phy_xaui_rx_polarity_flip_113=0x0001 + +#WC27 +phy_xaui_tx_polarity_flip_114=0x000F +phy_xaui_tx_polarity_flip_115=0x0001 +phy_xaui_tx_polarity_flip_117=0x0003 +phy_xaui_tx_polarity_flip_116=0x0001 + +phy_xaui_rx_polarity_flip_114=0x0007 +phy_xaui_rx_polarity_flip_115=0x0001 +phy_xaui_rx_polarity_flip_116=0x0001 +phy_xaui_rx_polarity_flip_117=0x0000 + +#WC0 +phy_xaui_tx_polarity_flip_1=0x0003 +phy_xaui_tx_polarity_flip_2=0x0001 +phy_xaui_tx_polarity_flip_3=0x0000 +phy_xaui_tx_polarity_flip_4=0x0000 + +phy_xaui_rx_polarity_flip_1=0x000F +phy_xaui_rx_polarity_flip_2=0x0001 +phy_xaui_rx_polarity_flip_3=0x0003 +phy_xaui_rx_polarity_flip_4=0x0001 + +#WC1 +phy_xaui_tx_polarity_flip_5=0x0007 +phy_xaui_tx_polarity_flip_6=0x0001 +phy_xaui_tx_polarity_flip_7=0x0001 +phy_xaui_tx_polarity_flip_8=0x0000 + +phy_xaui_rx_polarity_flip_5=0x0000 +phy_xaui_rx_polarity_flip_6=0x0000 +phy_xaui_rx_polarity_flip_7=0x0000 +phy_xaui_rx_polarity_flip_8=0x0000 + +#WC2 +phy_xaui_tx_polarity_flip_9=0x0002 +phy_xaui_tx_polarity_flip_10=0x0001 +phy_xaui_tx_polarity_flip_11=0x0000 +phy_xaui_tx_polarity_flip_12=0x0000 + +phy_xaui_rx_polarity_flip_9=0x0008 +phy_xaui_rx_polarity_flip_10=0x0000 +phy_xaui_rx_polarity_flip_11=0x0002 +phy_xaui_rx_polarity_flip_12=0x0001 + +#WC3 +phy_xaui_tx_polarity_flip_13=0x000F +phy_xaui_tx_polarity_flip_14=0x0001 +phy_xaui_tx_polarity_flip_15=0x0003 +phy_xaui_tx_polarity_flip_16=0x0001 + +phy_xaui_rx_polarity_flip_13=0x0000 +phy_xaui_rx_polarity_flip_14=0x0000 +phy_xaui_rx_polarity_flip_15=0x0000 +phy_xaui_rx_polarity_flip_16=0x0000 + +#WC4 +phy_xaui_tx_polarity_flip_17=0x0007 +phy_xaui_tx_polarity_flip_18=0x0001 +phy_xaui_tx_polarity_flip_19=0x0001 +phy_xaui_tx_polarity_flip_20=0x0000 + + +phy_xaui_rx_polarity_flip_17=0x0000 +phy_xaui_rx_polarity_flip_18=0x0000 +phy_xaui_rx_polarity_flip_19=0x0000 +phy_xaui_rx_polarity_flip_20=0x0000 + + + +#WC5 +phy_xaui_tx_polarity_flip_21=0x0000 +phy_xaui_tx_polarity_flip_22=0x0000 +phy_xaui_tx_polarity_flip_23=0x0000 +phy_xaui_tx_polarity_flip_24=0x0000 + +phy_xaui_rx_polarity_flip_21=0x0000 +phy_xaui_rx_polarity_flip_22=0x0000 +phy_xaui_rx_polarity_flip_23=0x0000 +phy_xaui_rx_polarity_flip_24=0x0000 + + + +#WC6 +phy_xaui_tx_polarity_flip_25=0x0002 +phy_xaui_tx_polarity_flip_26=0x0001 +phy_xaui_tx_polarity_flip_27=0x0000 +phy_xaui_tx_polarity_flip_28=0x0000 + +phy_xaui_rx_polarity_flip_25=0x0005 +phy_xaui_rx_polarity_flip_26=0x0000 +phy_xaui_rx_polarity_flip_27=0x0001 +phy_xaui_rx_polarity_flip_28=0x0000 + + + +#WC7 +phy_xaui_tx_polarity_flip_29=0x0002 +phy_xaui_tx_polarity_flip_30=0x0001 +phy_xaui_tx_polarity_flip_31=0x0000 +phy_xaui_tx_polarity_flip_32=0x0000 + +phy_xaui_rx_polarity_flip_29=0x0000 +phy_xaui_rx_polarity_flip_30=0x0000 +phy_xaui_rx_polarity_flip_31=0x0000 +phy_xaui_rx_polarity_flip_32=0x0000 + + + +#WC28 +phy_xaui_tx_polarity_flip_118=0x000F +phy_xaui_tx_polarity_flip_119=0x0001 +phy_xaui_tx_polarity_flip_120=0x0003 +phy_xaui_tx_polarity_flip_121=0x0001 + +phy_xaui_rx_polarity_flip_118=0x000F +phy_xaui_rx_polarity_flip_119=0x0001 +phy_xaui_rx_polarity_flip_120=0x0003 +phy_xaui_rx_polarity_flip_121=0x0001 + + + +#WC29 +phy_xaui_tx_polarity_flip_122=0x0004 +phy_xaui_tx_polarity_flip_123=0x0000 +phy_xaui_tx_polarity_flip_124=0x0001 +phy_xaui_tx_polarity_flip_125=0x0000 + +phy_xaui_rx_polarity_flip_122=0x0000 +phy_xaui_rx_polarity_flip_123=0x0000 +phy_xaui_rx_polarity_flip_124=0x0000 +phy_xaui_rx_polarity_flip_125=0x0000 + + + +#WC30 +phy_xaui_tx_polarity_flip_126=0x000F +phy_xaui_tx_polarity_flip_127=0x0001 +phy_xaui_tx_polarity_flip_128=0x0003 +phy_xaui_tx_polarity_flip_129=0x0001 + +phy_xaui_rx_polarity_flip_126=0x0000 +phy_xaui_rx_polarity_flip_127=0x0000 +phy_xaui_rx_polarity_flip_128=0x0000 +phy_xaui_rx_polarity_flip_129=0x0000 + + + +#WC31 +phy_xaui_tx_polarity_flip_130=0x0006 +phy_xaui_tx_polarity_flip_131=0x0001 +phy_xaui_tx_polarity_flip_132=0x0001 +phy_xaui_tx_polarity_flip_133=0x0000 + +phy_xaui_rx_polarity_flip_130=0x0000 +phy_xaui_rx_polarity_flip_131=0x0000 +phy_xaui_rx_polarity_flip_132=0x0000 +phy_xaui_rx_polarity_flip_133=0x0000 + + + diff --git a/device/celestica/x86_64-cel_seastone-r0/thermal_overload_control.sh b/device/celestica/x86_64-cel_seastone-r0/thermal_overload_control.sh new file mode 100755 index 000000000000..57fd851f9cfb --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/thermal_overload_control.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# +# Copyright 2020-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 +SETREG_FILE=/sys/devices/platform/dx010_cpld/setreg +TOVERREG=0x140 +CPUOVER=0xa1 +ASICOVER=0xa2 + +prog="$0" +command="$1" + +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root" + exit 1 +fi + +usage() { + echo "Usage: thermal_overload_control.sh [option] " + echo + echo "Options:" + echo " -h, --help : to print this message." + echo + echo "Commands:" + echo + echo " cpu: To enabling CPU thermal overload handler" + echo + echo " asic : To enabling ASIC thermal overload handler" + echo +} + +cpu_overload() { + logger "Enable CPU thermal overload control" + set_reg=`echo ${TOVERREG} ${CPUOVER} > ${SETREG_FILE}` +} + +asic_overload() { + logger "Enable ASIC thermal overload control" + set_reg=`echo ${TOVERREG} ${ASICOVER} > ${SETREG_FILE}` +} + +if [ $# -lt 1 ]; then + usage + exit -1 +fi + +case "$command" in +-h | --help) + usage + ;; +cpu) + cpu_overload + ;; +asic) + asic_overload + ;; +*) + usage + exit -1 + ;; +esac + +exit $? diff --git a/device/celestica/x86_64-cel_seastone-r0/thermal_policy.json b/device/celestica/x86_64-cel_seastone-r0/thermal_policy.json new file mode 100644 index 000000000000..f937b6bd4456 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/thermal_policy.json @@ -0,0 +1,93 @@ +{ + "thermal_control_algorithm": { + "run_at_boot_up": "true" + }, + "info_types": [ + { + "type": "chassis_info" + }, + { + "type": "fan_info" + }, + { + "type": "thermal_info" + } + ], + "policies": [ + { + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + } + ] + }, + { + "name": "any fan broken", + "conditions": [ + { + "type": "fan.any.fault" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + } + ] + }, + { + "name": "any thermal over threshold", + "conditions": [ + { + "type": "thermal.over.high_threshold" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + } + ] + }, + { + "name": "temp over high critical threshold", + "conditions": [ + { + "type": "thermal.over.high_critical_threshold" + } + ], + "actions": [ + { + "type": "switch.power_cycling" + } + ] + }, + { + "name": "all fan presence / thermal no warning", + "conditions": [ + { + "type": "fan.all.presence" + }, + { + "type": "fan.all.good" + }, + { + "type": "thermal.all.good" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "true" + } + ] + } + ] +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/port_config.ini b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/port_config.ini new file mode 100644 index 000000000000..ed6bcff2331c --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias fec index speed +Ethernet0 1,2,3,4 QSFP1 rs 1 100000 +Ethernet4 5,6,7,8 QSFP2 rs 2 100000 +Ethernet8 9,10,11,12 QSFP3 rs 3 100000 +Ethernet12 13,14,15,16 QSFP4 rs 4 100000 +Ethernet16 17,18,19,20 QSFP5 rs 5 100000 +Ethernet20 21,22,23,24 QSFP6 rs 6 100000 +Ethernet24 25,26,27,28 QSFP7 rs 7 100000 +Ethernet28 29,30,31,32 QSFP8 rs 8 100000 +Ethernet32 33,34,35,36 QSFP9 rs 9 100000 +Ethernet36 37,38,39,40 QSFP10 rs 10 100000 +Ethernet40 41,42,43,44 QSFP11 rs 11 100000 +Ethernet44 45,46,47,48 QSFP12 rs 12 100000 +Ethernet48 49,50,51,52 QSFP13 rs 13 100000 +Ethernet52 53,54,55,56 QSFP14 rs 14 100000 +Ethernet56 57,58,59,60 QSFP15 rs 15 100000 +Ethernet60 61,62,63,64 QSFP16 rs 16 100000 +Ethernet64 65,66,67,68 QSFP17 rs 17 100000 +Ethernet68 69,70,71,72 QSFP18 rs 18 100000 +Ethernet72 73,74,75,76 QSFP19 rs 19 100000 +Ethernet76 77,78,79,80 QSFP20 rs 20 100000 +Ethernet80 81,82,83,84 QSFP21 rs 21 100000 +Ethernet84 85,86,87,88 QSFP22 rs 22 100000 +Ethernet88 89,90,91,92 QSFP23 rs 23 100000 +Ethernet92 93,94,95,96 QSFP24 rs 24 100000 +Ethernet96 97,98,99,100 QSFP25 rs 25 100000 +Ethernet100 101,102,103,104 QSFP26 rs 26 100000 +Ethernet104 105,106,107,108 QSFP27 rs 27 100000 +Ethernet108 109,110,111,112 QSFP28 rs 28 100000 +Ethernet112 113,114,115,116 QSFP29 rs 29 100000 +Ethernet116 117,118,119,120 QSFP30 rs 30 100000 +Ethernet120 121,122,123,124 QSFP31 rs 31 100000 +Ethernet124 125,126,127,128 QSFP32 rs 32 100000 \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile new file mode 100644 index 000000000000..b57101d114f0 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-seastone_2-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm new file mode 100644 index 000000000000..62bcdbc58840 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm @@ -0,0 +1,598 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +help_cli_enable=1 +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 +memlist_enable=1 +miim_intr_enable=0 +module_64ports=1 +oversubscribe_mode=1 +parity_enable=0 +serdes_lane_config_dfe=on +#serdes_fec_enable=1 +serdes_if_type_ce=14 +pbmp_gport_stack.0=0x0000000000000000000000000000000000000000000000000000000000000000 +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 + +reglist_enable=1 +scache_filename=/tmp/scache +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/custom.bin b/device/celestica/x86_64-cel_seastone_2-r0/custom.bin new file mode 100644 index 000000000000..a9597df309ab Binary files /dev/null and b/device/celestica/x86_64-cel_seastone_2-r0/custom.bin differ diff --git a/device/celestica/x86_64-cel_seastone_2-r0/default_sku b/device/celestica/x86_64-cel_seastone_2-r0/default_sku new file mode 100644 index 000000000000..5ed4cdc66166 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/default_sku @@ -0,0 +1 @@ +Seastone_2 t1 diff --git a/device/celestica/x86_64-cel_seastone_2-r0/installer.conf b/device/celestica/x86_64-cel_seastone_2-r0/installer.conf new file mode 100644 index 000000000000..3222a45fe1d4 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="earlycon=uart8250,mmio,0xdf37b000" \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/led_proc_init.soc b/device/celestica/x86_64-cel_seastone_2-r0/led_proc_init.soc new file mode 100644 index 000000000000..a47644c032e1 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-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/celestica/x86_64-cel_seastone_2-r0/linkscan_fw.bin b/device/celestica/x86_64-cel_seastone_2-r0/linkscan_fw.bin new file mode 100644 index 000000000000..a6a4794ecc2b Binary files /dev/null and b/device/celestica/x86_64-cel_seastone_2-r0/linkscan_fw.bin differ diff --git a/device/celestica/x86_64-cel_seastone_2-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_seastone_2-r0/plugins/eeprom.py new file mode 100644 index 000000000000..93290ebf82bf --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Celestica Seastone2 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/celestica/x86_64-cel_seastone_2-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_seastone_2-r0/plugins/psuutil.py new file mode 100644 index 000000000000..cc5461ccb5d4 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/plugins/psuutil.py @@ -0,0 +1,87 @@ +import os.path +import subprocess +import sys +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): + self.ipmi_sensor = "ipmitool sensor" + PsuBase.__init__(self) + + def run_command(self, command): + proc = subprocess.Popen(command, shell=True, universal_newlines=True, stdout=subprocess.PIPE) + (out, err) = proc.communicate() + + if proc.returncode != 0: + sys.exit(proc.returncode) + + return out + + def find_value(self, grep_string): + result = re.search(".+\| (0x\d{2})\d{2}\|.+", grep_string) + if result: + return result.group(1) + else: + return result + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + grep_key = "PSUL_Status" if index == 1 else "PSUR_Status" + grep_string = self.run_command(self.ipmi_sensor + ' | grep ' + grep_key) + status_byte = self.find_value(grep_string) + + if status_byte is None: + return False + + failure_detected = (int(status_byte, 16) >> 1) & 1 + input_lost = (int(status_byte, 16) >> 3) & 1 + if failure_detected or input_lost: + return False + else: + return True + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + grep_key = "PSUL_Status" if index == 1 else "PSUR_Status" + grep_string = self.run_command(self.ipmi_sensor + ' | grep ' + grep_key) + status_byte = self.find_value(grep_string) + + if status_byte is None: + return False + + presence = (int(status_byte, 16) >> 0) & 1 + if presence: + return True + else: + return False diff --git a/device/celestica/x86_64-cel_seastone_2-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_seastone_2-r0/plugins/sfputil.py new file mode 100755 index 000000000000..6f05527621fe --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/plugins/sfputil.py @@ -0,0 +1,179 @@ +# 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 = 33 + QSFP_PORT_START = 1 + QSFP_PORT_END = 32 + + EEPROM_OFFSET = 1 + PORT_INFO_PATH = '/sys/class/seastone2_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 list(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 list(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): + # 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 + + # Read status + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + # ModPrsL is active low + if reg_value == 0: + return False + + return True + + 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: When the feature request. + """ + raise NotImplementedError diff --git a/device/celestica/x86_64-cel_seastone_2-r0/pmon_daemon_control.json b/device/celestica/x86_64-cel_seastone_2-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..5e59513ef696 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/pmon_daemon_control.json @@ -0,0 +1,7 @@ +{ + "skip_ledd": true, + "skip_xcvrd": false, + "skip_psud": false, + "skip_syseepromd": false, + "skip_fancontrol": true +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/chassis.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/chassis.json new file mode 100644 index 000000000000..dfa1a1bddff8 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/chassis.json @@ -0,0 +1,45 @@ +{ + "eeprom": "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom", + "get_reboot_cause": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x3a 0x0c 0x0 0x2 0x06", + "output_translator": { + "00": "Hardware - Other", + "11": "Hardware - Other", + "22": "Non-Hardware", + "33": "Hardware - Other", + "44": "Non-Hardware", + "55": "Non-Hardware", + "77": "Watchdog", + "88": "Thermal Overload: CPU", + "99": "Thermal Overload: ASIC" + } + }, + "get_reboot_description": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x3a 0x0c 0x0 0x2 0x06", + "output_translator": { + "00": "The last reset is power cycle reset (set register 0xA164)", + "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", + "77": "The last reset is watchdog reset", + "88": "The last reset is CPU thermal overload", + "99": "The last reset is ASIC thermal overload" + } + }, + "get_watchdog": { + "output_source": "class", + "host_path": "/usr/share/sonic/device/x86_64-cel_seastone_2-r0/sonic_platform_config/watchdog.py", + "pmon_path": "/usr/share/sonic/platform/sonic_platform_config/watchdog.py", + "class": "Watchdog" + }, + "get_change_event": { + "output_source": "class", + "host_path": "/usr/share/sonic/device/x86_64-cel_seastone_2-r0/sonic_platform_config/event.py", + "pmon_path": "/usr/share/sonic/platform/sonic_platform_config/event.py", + "class": "SfpEvent" + } +} diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/component.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/component.json new file mode 100644 index 000000000000..96f646206f97 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/component.json @@ -0,0 +1,62 @@ +{ + "component_num": 5, + "get_name": { + "output_source": "value_list", + "value_list": [ + "BIOS", + "CPLD_BASEBOARD", + "CPLD_SWITCHBOARD", + "FPGA", + "BMC" + ] + }, + "get_description": { + "output_source": "value_list", + "value_list": [ + "Used to perform hardware initialization during the booting process", + "Used to control the system power & reset, Control FAN, UART Mux etc", + "Used for managing QSFP ports", + "Used for managing I2C, SPI, PCIe etc", + "Used for monitoring and managing whole system" + ] + }, + "get_firmware_version": { + "output_source": "function", + "function": [ + "_get_bios_ver", + "_get_base_cpld_ver", + "_get_sw_cpld_ver", + "_get_fpga_ver", + "_get_bmc_ver" + ] + }, + "_get_bmc_ver": { + "output_source": "ipmitool", + "command": "ipmitool mc info | grep 'Firmware Revision'", + "output_translator": "'{}'.split(':')[-1].strip()" + }, + "_get_bios_ver": { + "output_source": "txt_file", + "path": "/sys/class/dmi/id/bios_version" + }, + "_get_base_cpld_ver": { + "output_source": "hex_version_file", + "num_of_points": 1, + "num_of_bits": 8, + "path": "/sys/devices/platform/baseboard/version" + }, + "_get_sw_cpld_ver": { + "output_source": "hex_version_getreg", + "num_of_points": 1, + "num_of_bits": 8, + "reg_addr": "0x00", + "path": "/sys/devices/platform/switchboard/CPLD1/getreg" + }, + "_get_fpga_ver": { + "output_source": "hex_version_getreg", + "num_of_points": 1, + "num_of_bits": 32, + "reg_addr": "0x00", + "path": "/sys/devices/platform/switchboard/FPGA/getreg" + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/event.py b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/event.py new file mode 100644 index 000000000000..ed3b78cf7fd6 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/event.py @@ -0,0 +1,112 @@ +############################################################################# +# Celestica Seastone2 +# +# SfpEvent contains an implementation of SONiC Platform Base API +# +############################################################################# +try: + import time + import os + from sonic_platform.common import Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +PLATFORM_PATH = "/sys/devices/platform/" +SWITCH_BRD_PLATFORM = "switchboard" +POLL_INTERVAL = 1 + + +class SfpEvent: + ''' Listen to insert/remove sfp events ''' + + PORT_INFO_DIR = 'SFF' + PATH_INT_SYSFS = "{0}/{port_name}/{type_prefix}_isr_flags" + PATH_INTMASK_SYSFS = "{0}/{port_name}/{type_prefix}_isr_mask" + PATH_PRS_SYSFS = "{0}/{port_name}/{prs_file_name}" + PRESENT_EN = 0x01 + + def __init__(self, sfp_list): + self.num_sfp = len(sfp_list) + self._api_common = Common() + self._initialize_interrupts() + + def _initialize_interrupts(self): + sfp_info_obj = {} + port_info_path = os.path.join( + PLATFORM_PATH, SWITCH_BRD_PLATFORM, self.PORT_INFO_DIR) + + for index in range(self.num_sfp): + port_num = index + 1 + port_name = "QSFP{}".format(port_num) + port_type = "qsfp" + sysfs_prs_file = "{}_modprs".format(port_type) + + sfp_info_obj[index] = {} + sfp_info_obj[index]['intmask_sysfs'] = self.PATH_INTMASK_SYSFS.format( + port_info_path, + port_name=port_name, + type_prefix=port_type) + + sfp_info_obj[index]['int_sysfs'] = self.PATH_INT_SYSFS.format( + port_info_path, + port_name=port_name, + type_prefix=port_type) + + sfp_info_obj[index]['prs_sysfs'] = self.PATH_PRS_SYSFS.format( + port_info_path, + port_name=port_name, + prs_file_name=sysfs_prs_file) + + self._api_common.write_txt_file( + sfp_info_obj[index]["intmask_sysfs"], hex(self.PRESENT_EN)) + + self.sfp_info_obj = sfp_info_obj + + def _is_port_device_present(self, port_idx): + prs_path = self.sfp_info_obj[port_idx]["prs_sysfs"] + is_present = 1 - int(self._api_common.read_txt_file(prs_path)) + return is_present + + def _update_port_event_object(self, interrup_devices, port_dict): + for port_idx in interrup_devices: + device_id = str(port_idx + 1) + port_dict[device_id] = str(self._is_port_device_present(port_idx)) + return port_dict + + def _clear_event_flag(self, path): + self._api_common.write_txt_file(path, hex(0xff)) + time.sleep(0.1) + self._api_common.write_txt_file(path, hex(0x0)) + + def _check_all_port_interrupt_event(self): + interrupt_devices = {} + for i in range(self.num_sfp): + int_sysfs = self.sfp_info_obj[i]["int_sysfs"] + interrupt_flags = self._api_common.read_txt_file(int_sysfs) + if interrupt_flags != '0x00': + interrupt_devices[i] = 1 + self._clear_event_flag(int_sysfs) + return interrupt_devices + + def get_event(self, timeout): + sleep_time = min( + timeout, POLL_INTERVAL) if timeout != 0 else POLL_INTERVAL + start_milli_time = int(round(time.time() * 1000)) + int_sfp = {} + + while True: + chk_sfp = self._check_all_port_interrupt_event() + int_sfp = self._update_port_event_object( + chk_sfp, int_sfp) if chk_sfp else int_sfp + current_milli_time = int(round(time.time() * 1000)) + if (int_sfp) or \ + (timeout != 0 and current_milli_time - start_milli_time > timeout): + break + + time.sleep(sleep_time) + + change_dict = dict() + change_dict['sfp'] = int_sfp + + return True, change_dict diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/fan.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/fan.json new file mode 100644 index 000000000000..724f6edf53c1 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/fan.json @@ -0,0 +1,200 @@ +{ + "fan_num_per_drawer": 2, + "drawer_num": 4, + "get_name": { + "output_source": "value_list", + "value_list": [ + "Fan1-F", + "Fan1-R", + "Fan2-F", + "Fan2-R", + "Fan3-F", + "Fan3-R", + "Fan4-F", + "Fan4-R" + ] + }, + "get_presence": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x3a 0x03 0x03 {}", + "argument": [ + "0x00", + "0x00", + "0x01", + "0x01", + "0x02", + "0x02", + "0x03", + "0x03" + ], + "output_translator": "True if '00' in '{}' else False" + }, + "get_model": { + "output_source": "ipmitool", + "command": "ipmitool fru list {} | grep 'Board Part Number'", + "argument": [ + "5", + "5", + "6", + "6", + "7", + "7", + "8", + "8" + ], + "output_translator": "'{}'.split()[-1]" + }, + "get_serial": { + "output_source": "ipmitool", + "command": "ipmitool fru list {} | grep 'Board Serial'", + "argument": [ + "5", + "5", + "6", + "6", + "7", + "7", + "8", + "8" + ], + "output_translator": "'{}'.split()[-1]" + }, + "get_direction": { + "output_source": "ipmitool", + "command": "ipmitool fru list {} | grep 'F2B\\|B2F'", + "argument": [ + "5", + "5", + "6", + "6", + "7", + "7", + "8", + "8" + ], + "output_translator": "'intake' if 'B2F' in '{}' else 'exhaust'" + }, + "get_speed": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x04 0x2d {}", + "argument": [ + "0x81", + "0x80", + "0x83", + "0x82", + "0x85", + "0x84", + "0x87", + "0x86" + ], + "output_translator": "int('{}'.split()[0],16)*150", + "max_front": 23000, + "max_rear": 20500 + }, + "get_target_speed": { + "output_source": "value", + "value": "N/A" + }, + "get_speed_tolerance": { + "output_source": "value", + "value": 10 + }, + "set_speed": { + "set_method": "ipmitool", + "input_translator": "hex(int({} * 255 / 100.0))", + "command": "ipmitool raw 0x3a 0x0c 0x00 0x03 {}", + "argument": [ + "0x40 {}", + "0x40 {}", + "0x44 {}", + "0x44 {}", + "0x4c {}", + "0x4c {}", + "0x50 {}", + "0x50 {}" + ] + }, + "set_status_led": { + "set_method": "ipmitool", + "avaliable_input": [ + "off", + "amber", + "green" + ], + "input_translator": { + "off": "0x0", + "amber": "0x1", + "green": "0x2" + }, + "command": "ipmitool raw 0x3a 0x0a {}", + "argument": [ + "0x4 {}", + "0x4 {}", + "0x5 {}", + "0x5 {}", + "0x6 {}", + "0x6 {}", + "0x7 {}", + "0x7 {}" + ] + }, + "get_status_led": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x3a 0x0b {}", + "argument": [ + "0x4", + "0x4", + "0x5", + "0x5", + "0x6", + "0x6", + "0x7", + "0x7" + ], + "output_translator": { + "00": "off", + "01": "amber", + "02": "green" + } + }, + "psu_fan": [ + { + "num_of_fan": 1, + "get_name": { + "output_source": "value_list", + "value_list": [ + "PSU-R-Fan" + ] + }, + "get_speed": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x04 0x2d {}", + "argument": [ + "0x8b" + ], + "output_translator": "int('{}'.split()[0],16)*100", + "max_front": 22600, + "max_rear": 22600 + } + }, + { + "num_of_fan": 1, + "get_name": { + "output_source": "value_list", + "value_list": [ + "PSU-L-Fan" + ] + }, + "get_speed": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x04 0x2d {}", + "argument": [ + "0x8a" + ], + "output_translator": "int('{}'.split()[0],16)*100", + "max_front": 22600, + "max_rear": 22600 + } + } + ] +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/psu.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/psu.json new file mode 100644 index 000000000000..c3e953c082a7 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/psu.json @@ -0,0 +1,135 @@ +{ + "psu_num": 2, + "fan_per_psu_num": 1, + "get_name": { + "output_source": "value_list", + "value_list": [ + "PSU-R", + "PSU-L" + ] + }, + "get_power": { + "output_source": "ipmitool", + "command": "ipmitool sdr | grep {}", + "argument": [ + "PSUR_POut", + "PSUL_POut" + ], + "output_translator": "float('{}'.split()[2])" + }, + "get_current": { + "output_source": "ipmitool", + "command": "ipmitool sdr | grep {}", + "argument": [ + "PSUR_COut", + "PSUL_COut" + ], + "output_translator": "float('{}'.split()[2])" + }, + "get_voltage": { + "output_source": "ipmitool", + "command": "ipmitool sdr | grep {}", + "argument": [ + "PSUR_VOut", + "PSUL_VOut" + ], + "output_translator": "float('{}'.split()[2])" + }, + "get_voltage_high_threshold": { + "output_source": "ipmitool", + "command": "ipmitool sensor list | grep {}", + "argument": [ + "PSUR_Temp2", + "PSUL_Temp2" + ], + "output_translator": "float(0 if '{0}'.split()[-3]=='na' else '{0}'.split()[-3])" + }, + "get_voltage_low_threshold": { + "output_source": "ipmitool", + "command": "ipmitool sensor list | grep {}", + "argument": [ + "PSUR_Temp2", + "PSUL_Temp2" + ], + "output_translator": "float(0 if '{0}'.split()[-9]=='na' else '{0}'.split()[-9])" + }, + "get_presence": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x3a 0x0c 0x00 0x2 0x60", + "output_translator": [ + "True if (int('{}', 16) >> 4 & 1) == 0 else False", + "True if (int('{}', 16) >> 5 & 1) == 0 else False" + ] + }, + "get_model": { + "output_source": "ipmitool", + "command": "ipmitool fru list {} | grep 'Product Part Number'", + "argument": [ + "4", + "3" + ], + "output_translator": "'{}'.split()[-1]" + }, + "get_serial": { + "output_source": "ipmitool", + "command": "ipmitool fru list {} | grep 'Product Serial'", + "argument": [ + "4", + "3" + ], + "output_translator": "'{}'.split()[-1]" + }, + "get_powergood_status": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x3a 0x0c 0x0 0x2 0x60", + "output_translator": [ + "True if (int('{}', 16) >> 2 & 1) == 1 else False", + "True if (int('{}', 16) >> 3 & 1) == 1 else False" + ] + }, + "set_status_led": { + "set_method": "ipmitool", + "avaliable_input": [ + "amber" + ], + "input_translator": { + "amber": "0x1" + }, + "command": "ipmitool raw 0x3a 0x0a {}", + "argument": [ + "0x3 {}", + "0x2 {}" + ] + }, + "get_status_led": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x3a 0x0b {}", + "argument": [ + "0x3", + "0x2" + ], + "output_translator": { + "00": "green", + "01": "amber" + }, + "default_output": "off" + }, + "get_temperature": { + "output_source": "ipmitool", + "command": "ipmitool sdr | grep {}", + "argument": [ + "PSUR_Temp2", + "PSUL_Temp2" + ], + "output_translator": "float('{}'.split()[2])" + }, + "get_temperature_high_threshold": { + "output_source": "ipmitool", + "command": "ipmitool sensor list | grep {}", + "argument": [ + "PSUR_Temp2", + "PSUL_Temp2" + ], + "output_translator": "float(0 if '{0}'.split()[-3]=='na' else '{0}'.split()[-3])" + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json new file mode 100644 index 000000000000..d77e75e50e2f --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json @@ -0,0 +1,106 @@ +{ + "port_num": 32, + "eeprom_path": "/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom", + "port_i2c_mapping": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33 + ], + "get_presence": { + "output_source": "sysfs_value", + "sysfs_path": "/sys/devices/platform/switchboard/SFF/{}/qsfp_modprs", + "argument": "$ref:_port_name", + "output_translator": "False if '{}' == '1' else True" + }, + "get_lpmode": { + "output_source": "sysfs_value", + "sysfs_path": "/sys/devices/platform/switchboard/SFF/{}/qsfp_lpmode", + "argument": "$ref:_port_name", + "output_translator": "True if '{}' == '1' else False" + }, + "get_reset_status": { + "output_source": "sysfs_value", + "sysfs_path": "/sys/devices/platform/switchboard/SFF/{}/qsfp_reset", + "argument": "$ref:_port_name", + "output_translator": "False if '{}' == '1' else True" + }, + "reset": { + "set_method": "sysfs_value", + "write_offset": 0, + "sysfs_path": "/sys/devices/platform/switchboard/SFF/{}/qsfp_reset", + "argument": "$ref:_port_name" + }, + "set_lpmode": { + "set_method": "sysfs_value", + "input_translator": { + "True": "0x1", + "False": "0x0" + }, + "write_offset": 0, + "sysfs_path": "/sys/devices/platform/switchboard/SFF/{}/qsfp_lpmode", + "argument": "$ref:_port_name" + }, + "_port_name": [ + "QSFP1", + "QSFP2", + "QSFP3", + "QSFP4", + "QSFP5", + "QSFP6", + "QSFP7", + "QSFP8", + "QSFP9", + "QSFP10", + "QSFP11", + "QSFP12", + "QSFP13", + "QSFP14", + "QSFP15", + "QSFP16", + "QSFP17", + "QSFP18", + "QSFP19", + "QSFP20", + "QSFP21", + "QSFP22", + "QSFP23", + "QSFP24", + "QSFP25", + "QSFP26", + "QSFP27", + "QSFP28", + "QSFP29", + "QSFP30", + "QSFP31", + "QSFP32" + ] +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/thermal.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/thermal.json new file mode 100644 index 000000000000..e3dcb7fb9271 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/thermal.json @@ -0,0 +1,105 @@ +{ + "thermal_num": 9, + "get_name": { + "output_source": "value_list", + "value_list": [ + "Base_Temp_U5", + "Base_Temp_U7", + "CPU_Temp", + "Switch_Temp_U1", + "Switch_Temp_U18", + "Switch_Temp_U28", + "Switch_Temp_U29", + "Switch_U21_Temp", + "Switch_U33_Temp" + ] + }, + "get_temperature": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x04 0x2D {}", + "argument": [ + "0x1", + "0x2", + "0x7", + "0x3", + "0x4", + "0x5", + "0x6", + "0x56", + "0x4C" + ], + "output_translator": "int('{}'.split()[0],16)" + }, + "get_high_threshold": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x04 0x27 {}", + "argument": [ + "0x1", + "0x2", + "0x7", + "0x3", + "0x4", + "0x5", + "0x6", + "0x56", + "0x4c" + ], + "output_translator": "int('{}'.split()[4], 16)" + }, + "get_low_threshold": { + "output_source": "value", + "value": "N/A" + }, + "set_high_threshold": { + "set_method": "ipmitool", + "command": "ipmitool sensor thresh {}", + "input_translator": "{}", + "argument": [ + "Base_Temp_U5 unc {}", + "Base_Temp_U7 unc {}", + "CPU_Temp unc {}", + "Switch_Temp_U1 unc {}", + "Switch_Temp_U18 unc {}", + "Switch_Temp_U28 unc {}", + "Switch_Temp_U29 unc {}", + "Switch_U21_Temp unc {}", + "Switch_U33_Temp unc {}" + ] + }, + "set_low_threshold": { + "output_source": "ipmitool", + "command": "ipmitool sensor thresh {}", + "input_translator": "{}", + "argument": [ + "Base_Temp_U5 lnc {}", + "Base_Temp_U7 lnc {}", + "CPU_Temp lnc {}", + "Switch_Temp_U1 lnc {}", + "Switch_Temp_U18 lnc {}", + "Switch_Temp_U28 lnc {}", + "Switch_Temp_U29 lnc {}", + "Switch_U21_Temp lnc {}", + "Switch_U33_Temp lnc {}" + ] + }, + "get_high_critical_threshold": { + "output_source": "ipmitool", + "command": "ipmitool raw 0x04 0x27 {}", + "argument": [ + "0x1", + "0x2", + "0x7", + "0x3", + "0x4", + "0x5", + "0x6", + "0x56", + "0x4c" + ], + "output_translator": "int('{}'.split()[5], 16)" + }, + "get_low_critical_threshold": { + "output_source": "value", + "value": "N/A" + } +} \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/watchdog.py b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/watchdog.py new file mode 100644 index 000000000000..cc87c3d6b32a --- /dev/null +++ b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/watchdog.py @@ -0,0 +1,189 @@ +############################################################################# +# Celestica Seastone2 +# +# Watchdog contains an implementation of SONiC Platform Base API +# +############################################################################# +import os +import time + +try: + from sonic_platform_base.watchdog_base import WatchdogBase + from sonic_platform.common import Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PLATFORM_CPLD_PATH = '/sys/devices/platform/baseboard/' +GETREG_FILE = 'getreg' +SETREG_FILE = 'setreg' +WDT_ENABLE_REG = '0xA181' +WDT_TIMER_L_BIT_REG = '0xA182' +WDT_TIMER_M_BIT_REG = '0xA183' +WDT_TIMER_H_BIT_REG = '0xA184' +WDT_KEEP_ALVIVE_REG = '0xA185' +ENABLE_CMD = '0x1' +DISABLE_CMD = '0x0' +WDT_COMMON_ERROR = -1 + + +class Watchdog(WatchdogBase): + + def __init__(self): + self._api_common = Common() + + # Init cpld reg path + self.setreg_path = os.path.join(PLATFORM_CPLD_PATH, SETREG_FILE) + self.getreg_path = os.path.join(PLATFORM_CPLD_PATH, GETREG_FILE) + + # Set default value + self._disable() + self.armed = False + self.timeout = self._gettimeout() + + def _enable(self): + """ + Turn on the watchdog timer + """ + # echo 0xA181 0x1 > /sys/devices/platform/baseboard/setreg + enable_val = '{} {}'.format(WDT_ENABLE_REG, ENABLE_CMD) + return self._api_common.write_txt_file(self.setreg_path, enable_val) + + def _disable(self): + """ + Turn off the watchdog timer + """ + # echo 0xA181 0x0 > /sys/devices/platform/baseboard/setreg + disable_val = '{} {}'.format(WDT_ENABLE_REG, DISABLE_CMD) + return self._api_common.write_txt_file(self.setreg_path, disable_val) + + def _keepalive(self): + """ + Keep alive watchdog timer + """ + # echo 0xA185 0x1 > /sys/devices/platform/baseboard/setreg + enable_val = '{} {}'.format(WDT_KEEP_ALVIVE_REG, ENABLE_CMD) + return self._api_common.write_txt_file(self.setreg_path, enable_val) + + def _get_level_hex(self, sub_hex): + sub_hex_str = sub_hex.replace("x", "0") + return hex(int(sub_hex_str, 16)) + + def _seconds_to_lmh_hex(self, seconds): + ms = seconds*1000 # calculate timeout in ms format + hex_str = hex(ms) + l = self._get_level_hex(hex_str[-2:]) + m = self._get_level_hex(hex_str[-4:-2]) + h = self._get_level_hex(hex_str[-6:-4]) + return (l, m, h) + + def _settimeout(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + # max = 0xffffff = 16777.215 seconds + + (l, m, h) = self._seconds_to_lmh_hex(seconds) + set_h_val = '{} {}'.format(WDT_TIMER_H_BIT_REG, h) + set_m_val = '{} {}'.format(WDT_TIMER_M_BIT_REG, m) + set_l_val = '{} {}'.format(WDT_TIMER_L_BIT_REG, l) + + self._api_common.write_txt_file( + self.setreg_path, set_h_val) # set high bit + self._api_common.write_txt_file( + self.setreg_path, set_m_val) # set med bit + self._api_common.write_txt_file( + self.setreg_path, set_l_val) # set low bit + + return seconds + + def _gettimeout(self): + """ + Get watchdog timeout + @return watchdog timeout + """ + + h_bit = self._api_common.get_reg( + self.getreg_path, WDT_TIMER_H_BIT_REG) + m_bit = self._api_common.get_reg( + self.getreg_path, WDT_TIMER_M_BIT_REG) + l_bit = self._api_common.get_reg( + self.getreg_path, WDT_TIMER_L_BIT_REG) + + hex_time = '0x{}{}{}'.format(h_bit[2:], m_bit[2:], l_bit[2:]) + ms = int(hex_time, 16) + return int(float(ms)/1000) + + ################################################################# + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* available + value. + Returns: + An integer specifying the *actual* number of seconds the watchdog + was armed with. On failure returns -1. + """ + + ret = WDT_COMMON_ERROR + if seconds < 0: + return ret + + try: + if self.timeout != seconds: + self.timeout = self._settimeout(seconds) + + if self.armed: + self._keepalive() + else: + self._enable() + self.armed = True + + ret = self.timeout + self.arm_timestamp = time.time() + except IOError as e: + pass + + return ret + + def disarm(self): + """ + Disarm the hardware watchdog + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + disarmed = False + if self.is_armed(): + try: + self._disable() + self.armed = False + disarmed = True + except IOError: + pass + + return disarmed + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + Returns: + A boolean, True if watchdog is armed, False if not + """ + + return self.armed + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds remaining on + the watchdog timer + Returns: + An integer specifying the number of seconds remaining on thei + watchdog timer. If the watchdog is not armed, returns -1. + """ + + return int(self.timeout - (time.time() - self.arm_timestamp)) if self.armed else WDT_COMMON_ERROR diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/port_config.ini b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/port_config.ini new file mode 100644 index 000000000000..238c9fa4be79 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/port_config.ini @@ -0,0 +1,129 @@ +# name lanes alias index speed +Ethernet0 33,34 QSFP1/1 1 100000 +Ethernet1 35,36 QSFP1/2 1 100000 +Ethernet2 37,38 QSFP1/3 1 100000 +Ethernet3 39,40 QSFP1/4 1 100000 +Ethernet4 41,42 QSFP2/1 2 100000 +Ethernet5 43,44 QSFP2/2 2 100000 +Ethernet6 45,46 QSFP2/3 2 100000 +Ethernet7 47,48 QSFP2/4 2 100000 +Ethernet8 49,50 QSFP3/1 3 100000 +Ethernet9 51,52 QSFP3/2 3 100000 +Ethernet10 53,54 QSFP3/3 3 100000 +Ethernet11 55,56 QSFP3/4 3 100000 +Ethernet12 57,58 QSFP4/1 4 100000 +Ethernet13 59,60 QSFP4/2 4 100000 +Ethernet14 61,62 QSFP4/3 4 100000 +Ethernet15 63,64 QSFP4/4 4 100000 +Ethernet16 65,66 QSFP5/1 5 100000 +Ethernet17 67,68 QSFP5/2 5 100000 +Ethernet18 69,70 QSFP5/3 5 100000 +Ethernet19 71,72 QSFP5/4 5 100000 +Ethernet20 73,74 QSFP6/1 6 100000 +Ethernet21 75,76 QSFP6/2 6 100000 +Ethernet22 77,78 QSFP6/3 6 100000 +Ethernet23 79,80 QSFP6/4 6 100000 +Ethernet24 81,82 QSFP7/1 7 100000 +Ethernet25 83,84 QSFP7/2 7 100000 +Ethernet26 85,86 QSFP7/3 7 100000 +Ethernet27 87,88 QSFP7/4 7 100000 +Ethernet28 89,90 QSFP8/1 8 100000 +Ethernet29 91,92 QSFP8/2 8 100000 +Ethernet30 93,94 QSFP8/3 8 100000 +Ethernet31 95,96 QSFP8/4 8 100000 +Ethernet32 1,2 QSFP9/1 9 100000 +Ethernet33 3,4 QSFP9/2 9 100000 +Ethernet34 5,6 QSFP9/3 9 100000 +Ethernet35 7,8 QSFP9/4 9 100000 +Ethernet36 9,10 QSFP10/1 10 100000 +Ethernet37 11,12 QSFP10/2 10 100000 +Ethernet38 13,14 QSFP10/3 10 100000 +Ethernet39 15,16 QSFP10/4 10 100000 +Ethernet40 17,18 QSFP11/1 11 100000 +Ethernet41 19,20 QSFP11/2 11 100000 +Ethernet42 21,22 QSFP11/3 11 100000 +Ethernet43 23,24 QSFP11/4 11 100000 +Ethernet44 25,26 QSFP12/1 12 100000 +Ethernet45 27,28 QSFP12/2 12 100000 +Ethernet46 29,30 QSFP12/3 12 100000 +Ethernet47 31,32 QSFP12/4 12 100000 +Ethernet48 97,98 QSFP13/1 13 100000 +Ethernet49 99,100 QSFP13/2 13 100000 +Ethernet50 101,102 QSFP13/3 13 100000 +Ethernet51 103,104 QSFP13/4 13 100000 +Ethernet52 105,106 QSFP14/1 14 100000 +Ethernet53 107,108 QSFP14/2 14 100000 +Ethernet54 109,110 QSFP14/3 14 100000 +Ethernet55 111,112 QSFP14/4 14 100000 +Ethernet56 113,114 QSFP15/1 15 100000 +Ethernet57 115,116 QSFP15/2 15 100000 +Ethernet58 117,118 QSFP15/3 15 100000 +Ethernet59 119,120 QSFP15/4 15 100000 +Ethernet60 121,122 QSFP16/1 16 100000 +Ethernet61 123,124 QSFP16/2 16 100000 +Ethernet62 125,126 QSFP16/3 16 100000 +Ethernet63 127,128 QSFP16/4 16 100000 +Ethernet64 129,130 QSFP17/1 17 100000 +Ethernet65 131,132 QSFP17/2 17 100000 +Ethernet66 133,134 QSFP17/3 17 100000 +Ethernet67 135,136 QSFP17/4 17 100000 +Ethernet68 137,138 QSFP18/1 18 100000 +Ethernet69 139,140 QSFP18/2 18 100000 +Ethernet70 141,142 QSFP18/3 18 100000 +Ethernet71 143,144 QSFP18/4 18 100000 +Ethernet72 145,146 QSFP19/1 19 100000 +Ethernet73 147,148 QSFP19/2 19 100000 +Ethernet74 149,150 QSFP19/3 19 100000 +Ethernet75 151,152 QSFP19/4 19 100000 +Ethernet76 153,154 QSFP20/1 20 100000 +Ethernet77 155,156 QSFP20/2 20 100000 +Ethernet78 157,158 QSFP20/3 20 100000 +Ethernet79 159,160 QSFP20/4 20 100000 +Ethernet80 225,226 QSFP21/1 21 100000 +Ethernet81 227,228 QSFP21/2 21 100000 +Ethernet82 229,230 QSFP21/3 21 100000 +Ethernet83 231,232 QSFP21/4 21 100000 +Ethernet84 233,234 QSFP22/1 22 100000 +Ethernet85 235,236 QSFP22/2 22 100000 +Ethernet86 237,238 QSFP22/3 22 100000 +Ethernet87 239,240 QSFP22/4 22 100000 +Ethernet88 241,242 QSFP23/1 23 100000 +Ethernet89 243,244 QSFP23/2 23 100000 +Ethernet90 245,246 QSFP23/3 23 100000 +Ethernet91 247,248 QSFP23/4 23 100000 +Ethernet92 249,250 QSFP24/1 24 100000 +Ethernet93 251,252 QSFP24/2 24 100000 +Ethernet94 253,254 QSFP24/3 24 100000 +Ethernet95 255,256 QSFP24/4 24 100000 +Ethernet96 161,162 QSFP25/1 25 100000 +Ethernet97 163,164 QSFP25/2 25 100000 +Ethernet98 165,166 QSFP25/3 25 100000 +Ethernet99 167,168 QSFP25/4 25 100000 +Ethernet100 169,170 QSFP26/1 26 100000 +Ethernet101 171,172 QSFP26/2 26 100000 +Ethernet102 173,174 QSFP26/3 26 100000 +Ethernet103 175,176 QSFP26/4 26 100000 +Ethernet104 177,178 QSFP27/1 27 100000 +Ethernet105 179,180 QSFP27/2 27 100000 +Ethernet106 181,182 QSFP27/3 27 100000 +Ethernet107 183,184 QSFP27/4 27 100000 +Ethernet108 185,186 QSFP28/1 28 100000 +Ethernet109 187,188 QSFP28/2 28 100000 +Ethernet110 189,190 QSFP28/3 28 100000 +Ethernet111 191,192 QSFP28/4 28 100000 +Ethernet112 193,194 QSFP29/1 29 100000 +Ethernet113 195,196 QSFP29/2 29 100000 +Ethernet114 197,198 QSFP29/3 29 100000 +Ethernet115 199,200 QSFP29/4 29 100000 +Ethernet116 201,202 QSFP30/1 30 100000 +Ethernet117 203,204 QSFP30/2 30 100000 +Ethernet118 205,206 QSFP30/3 30 100000 +Ethernet119 207,208 QSFP30/4 30 100000 +Ethernet120 209,210 QSFP31/1 31 100000 +Ethernet121 211,212 QSFP31/2 31 100000 +Ethernet122 213,214 QSFP31/3 31 100000 +Ethernet123 215,216 QSFP31/4 31 100000 +Ethernet124 217,218 QSFP32/1 32 100000 +Ethernet125 219,220 QSFP32/2 32 100000 +Ethernet126 221,222 QSFP32/3 32 100000 +Ethernet127 223,224 QSFP32/4 32 100000 \ No newline at end of file diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/sai.profile b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/sai.profile new file mode 100644 index 000000000000..483e85c0c1fa --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-128x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/th3-128x100G.config.bcm b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/th3-128x100G.config.bcm new file mode 100644 index 000000000000..0b66c8b53814 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone-128x100/th3-128x100G.config.bcm @@ -0,0 +1,441 @@ +pbmp_xport_xe.0=0x8ffff8ffffcffff8ffff8ffff8ffffcffff9fffe +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 + +init_all_modules=0 + +portmap_20=33:100:2 +portmap_21=35:100:2 +portmap_22=37:100:2 +portmap_23=39:100:2 + +portmap_24=41:100:2 +portmap_25=43:100:2 +portmap_26=45:100:2 +portmap_27=47:100:2 + +portmap_28=49:100:2 +portmap_29=51:100:2 +portmap_30=53:100:2 +portmap_31=55:100:2 + +portmap_32=57:100:2 +portmap_33=59:100:2 +portmap_34=61:100:2 +portmap_35=63:100:2 + +portmap_40=65:100:2 +portmap_41=67:100:2 +portmap_42=69:100:2 +portmap_43=71:100:2 + +portmap_44=73:100:2 +portmap_45=75:100:2 +portmap_46=77:100:2 +portmap_47=79:100:2 + +portmap_48=81:100:2 +portmap_49=83:100:2 +portmap_50=85:100:2 +portmap_51=87:100:2 + +portmap_52=89:100:2 +portmap_53=91:100:2 +portmap_54=93:100:2 +portmap_55=95:100:2 + +portmap_1=1:100:2 +portmap_2=3:100:2 +portmap_3=5:100:2 +portmap_4=7:100:2 + +portmap_5=9:100:2 +portmap_6=11:100:2 +portmap_7=13:100:2 +portmap_8=15:100:2 + +portmap_9=17:100:2 +portmap_10=19:100:2 +portmap_11=21:100:2 +portmap_12=23:100:2 + +portmap_13=25:100:2 +portmap_14=27:100:2 +portmap_15=29:100:2 +portmap_16=31:100:2 + +portmap_60=97:100:2 +portmap_61=99:100:2 +portmap_62=101:100:2 +portmap_63=103:100:2 + +portmap_64=105:100:2 +portmap_65=107:100:2 +portmap_66=109:100:2 +portmap_67=111:100:2 + +portmap_68=113:100:2 +portmap_69=115:100:2 +portmap_70=117:100:2 +portmap_71=119:100:2 + +portmap_72=121:100:2 +portmap_73=123:100:2 +portmap_74=125:100:2 +portmap_75=127:100:2 + +portmap_80=129:100:2 +portmap_81=131:100:2 +portmap_82=133:100:2 +portmap_83=135:100:2 + +portmap_84=137:100:2 +portmap_85=139:100:2 +portmap_86=141:100:2 +portmap_87=143:100:2 + +portmap_88=145:100:2 +portmap_89=147:100:2 +portmap_90=149:100:2 +portmap_91=151:100:2 + +portmap_92=153:100:2 +portmap_93=155:100:2 +portmap_94=157:100:2 +portmap_95=159:100:2 + +portmap_140=225:100:2 +portmap_141=227:100:2 +portmap_142=229:100:2 +portmap_143=231:100:2 + +portmap_144=233:100:2 +portmap_145=235:100:2 +portmap_146=237:100:2 +portmap_147=239:100:2 + +portmap_148=241:100:2 +portmap_149=243:100:2 +portmap_150=245:100:2 +portmap_151=247:100:2 + +portmap_152=249:100:2 +portmap_153=251:100:2 +portmap_154=253:100:2 +portmap_155=255:100:2 + +portmap_100=161:100:2 +portmap_101=163:100:2 +portmap_102=165:100:2 +portmap_103=167:100:2 + +portmap_104=169:100:2 +portmap_105=171:100:2 +portmap_106=173:100:2 +portmap_107=175:100:2 + +portmap_108=177:100:2 +portmap_109=179:100:2 +portmap_110=181:100:2 +portmap_111=183:100:2 + +portmap_112=185:100:2 +portmap_113=187:100:2 +portmap_114=189:100:2 +portmap_115=191:100:2 + +portmap_120=193:100:2 +portmap_121=195:100:2 +portmap_122=197:100:2 +portmap_123=199:100:2 + +portmap_124=201:100:2 +portmap_125=203:100:2 +portmap_126=205:100:2 +portmap_127=207:100:2 + +portmap_128=209:100:2 +portmap_129=211:100:2 +portmap_130=213:100:2 +portmap_131=215:100:2 + +portmap_132=217:100:2 +portmap_133=219:100:2 +portmap_134=221:100:2 +portmap_135=223:100:2 + +phy_chain_rx_lane_map_physical{33.0}=0x65732041 +phy_chain_tx_lane_map_physical{33.0}=0x47206531 +phy_chain_rx_lane_map_physical{41.0}=0x07561243 +phy_chain_tx_lane_map_physical{41.0}=0x36207514 +phy_chain_rx_lane_map_physical{49.0}=0x54632071 +phy_chain_tx_lane_map_physical{49.0}=0x06241735 +phy_chain_rx_lane_map_physical{57.0}=0x07561243 +phy_chain_tx_lane_map_physical{57.0}=0x35207614 +phy_chain_rx_lane_map_physical{65.0}=0x45623170 +phy_chain_tx_lane_map_physical{65.0}=0x51260734 +phy_chain_rx_lane_map_physical{73.0}=0x07561243 +phy_chain_tx_lane_map_physical{73.0}=0x37245610 +phy_chain_rx_lane_map_physical{81.0}=0x45632071 +phy_chain_tx_lane_map_physical{81.0}=0x51260734 +phy_chain_rx_lane_map_physical{89.0}=0x07561243 +phy_chain_tx_lane_map_physical{89.0}=0x26437510 +phy_chain_rx_lane_map_physical{1.0}=0x30176524 +phy_chain_tx_lane_map_physical{1.0}=0x20615374 +phy_chain_rx_lane_map_physical{9.0}=0x37562041 +phy_chain_tx_lane_map_physical{9.0}=0x05176432 +phy_chain_rx_lane_map_physical{17.0}=0x43607251 +phy_chain_tx_lane_map_physical{17.0}=0x70261435 +phy_chain_rx_lane_map_physical{25.0}=0x60347125 +phy_chain_tx_lane_map_physical{25.0}=0x46357120 +phy_chain_rx_lane_map_physical{97.0}=0x47601352 +phy_chain_tx_lane_map_physical{97.0}=0x04265137 +phy_chain_rx_lane_map_physical{105.0}=0x73206415 +phy_chain_tx_lane_map_physical{105.0}=0x26374150 +phy_chain_rx_lane_map_physical{113.0}=0x47632051 +phy_chain_tx_lane_map_physical{113.0}=0x03254617 +phy_chain_rx_lane_map_physical{121.0}=0x63027415 +phy_chain_tx_lane_map_physical{121.0}=0x63721045 +phy_chain_rx_lane_map_physical{129.0}=0x30154627 +phy_chain_tx_lane_map_physical{129.0}=0x04735261 +phy_chain_rx_lane_map_physical{137.0}=0x24753061 +phy_chain_tx_lane_map_physical{137.0}=0x37614520 +phy_chain_rx_lane_map_physical{145.0}=0x47601352 +phy_chain_tx_lane_map_physical{145.0}=0x63274510 +phy_chain_rx_lane_map_physical{153.0}=0x07361524 +phy_chain_tx_lane_map_physical{153.0}=0x36527104 +phy_chain_rx_lane_map_physical{225.0}=0x56410273 +phy_chain_tx_lane_map_physical{225.0}=0x10274635 +phy_chain_rx_lane_map_physical{233.0}=0x15740263 +phy_chain_tx_lane_map_physical{233.0}=0x24351607 +phy_chain_rx_lane_map_physical{241.0}=0x74015263 +phy_chain_tx_lane_map_physical{241.0}=0x04152637 +phy_chain_rx_lane_map_physical{249.0}=0x62037514 +phy_chain_tx_lane_map_physical{249.0}=0x72453160 +phy_chain_rx_lane_map_physical{161.0}=0x46510273 +phy_chain_tx_lane_map_physical{161.0}=0x01653724 +phy_chain_rx_lane_map_physical{169.0}=0x25743160 +phy_chain_tx_lane_map_physical{169.0}=0x07216435 +phy_chain_rx_lane_map_physical{177.0}=0x46510273 +phy_chain_tx_lane_map_physical{177.0}=0x01652734 +phy_chain_rx_lane_map_physical{185.0}=0x25743160 +phy_chain_tx_lane_map_physical{185.0}=0x37016425 +phy_chain_rx_lane_map_physical{193.0}=0x46510372 +phy_chain_tx_lane_map_physical{193.0}=0x06153724 +phy_chain_rx_lane_map_physical{201.0}=0x25743160 +phy_chain_tx_lane_map_physical{201.0}=0x36017524 +phy_chain_rx_lane_map_physical{209.0}=0x47601352 +phy_chain_tx_lane_map_physical{209.0}=0x04152736 +phy_chain_rx_lane_map_physical{217.0}=0x26453170 +phy_chain_tx_lane_map_physical{217.0}=0x36027415 + +serdes_core_rx_polarity_flip_physical{33}=0x29 +serdes_core_tx_polarity_flip_physical{33}=0xfe +serdes_core_rx_polarity_flip_physical{41}=0xb1 +serdes_core_tx_polarity_flip_physical{41}=0xe8 +serdes_core_rx_polarity_flip_physical{49}=0xca +serdes_core_tx_polarity_flip_physical{49}=0xb6 +serdes_core_rx_polarity_flip_physical{57}=0x9b +serdes_core_tx_polarity_flip_physical{57}=0xdc +serdes_core_rx_polarity_flip_physical{65}=0x17 +serdes_core_tx_polarity_flip_physical{65}=0x86 +serdes_core_rx_polarity_flip_physical{73}=0x9b +serdes_core_tx_polarity_flip_physical{73}=0x55 +serdes_core_rx_polarity_flip_physical{81}=0xa +serdes_core_tx_polarity_flip_physical{81}=0x6 +serdes_core_rx_polarity_flip_physical{89}=0x9b +serdes_core_tx_polarity_flip_physical{89}=0x48 +serdes_core_rx_polarity_flip_physical{1}=0xec +serdes_core_tx_polarity_flip_physical{1}=0x56 +serdes_core_rx_polarity_flip_physical{9}=0x13 +serdes_core_tx_polarity_flip_physical{9}=0xa6 +serdes_core_rx_polarity_flip_physical{17}=0x5a +serdes_core_tx_polarity_flip_physical{17}=0xc6 +serdes_core_rx_polarity_flip_physical{25}=0xf +serdes_core_tx_polarity_flip_physical{25}=0x4e +serdes_core_rx_polarity_flip_physical{97}=0x17 +serdes_core_tx_polarity_flip_physical{97}=0x2e +serdes_core_rx_polarity_flip_physical{105}=0xce +serdes_core_tx_polarity_flip_physical{105}=0x7c +serdes_core_rx_polarity_flip_physical{113}=0xa +serdes_core_tx_polarity_flip_physical{113}=0x35 + +serdes_core_rx_polarity_flip_physical{121}=0xb9 +serdes_core_tx_polarity_flip_physical{121}=0xef +serdes_core_rx_polarity_flip_physical{129}=0xe8 +serdes_core_tx_polarity_flip_physical{129}=0xac +serdes_core_rx_polarity_flip_physical{137}=0xcb +serdes_core_tx_polarity_flip_physical{137}=0x9c +serdes_core_rx_polarity_flip_physical{145}=0x17 +serdes_core_tx_polarity_flip_physical{145}=0x32 +serdes_core_rx_polarity_flip_physical{153}=0xb9 +serdes_core_tx_polarity_flip_physical{153}=0xaf +serdes_core_rx_polarity_flip_physical{225}=0xaa +serdes_core_tx_polarity_flip_physical{225}=0x7 +serdes_core_rx_polarity_flip_physical{233}=0x31 +serdes_core_tx_polarity_flip_physical{233}=0x47 +serdes_core_rx_polarity_flip_physical{241}=0xe8 +serdes_core_tx_polarity_flip_physical{241}=0x9e +serdes_core_rx_polarity_flip_physical{249}=0xec +serdes_core_tx_polarity_flip_physical{249}=0x1f +serdes_core_rx_polarity_flip_physical{161}=0x6a +serdes_core_tx_polarity_flip_physical{161}=0xd4 +serdes_core_rx_polarity_flip_physical{169}=0x9e +serdes_core_tx_polarity_flip_physical{169}=0x7b +serdes_core_rx_polarity_flip_physical{177}=0x6a +serdes_core_tx_polarity_flip_physical{177}=0xcc +serdes_core_rx_polarity_flip_physical{185}=0x9e +serdes_core_tx_polarity_flip_physical{185}=0x58 +serdes_core_rx_polarity_flip_physical{193}=0x6f +serdes_core_tx_polarity_flip_physical{193}=0x24 +serdes_core_rx_polarity_flip_physical{201}=0x9e +serdes_core_tx_polarity_flip_physical{201}=0xdf +serdes_core_rx_polarity_flip_physical{209}=0x17 +serdes_core_tx_polarity_flip_physical{209}=0xe9 +serdes_core_rx_polarity_flip_physical{217}=0xec +serdes_core_tx_polarity_flip_physical{217}=0x68 + + +dport_map_port_20=1 +dport_map_port_21=2 +dport_map_port_22=3 +dport_map_port_23=4 +dport_map_port_24=5 +dport_map_port_25=6 +dport_map_port_26=7 +dport_map_port_27=8 +dport_map_port_28=9 +dport_map_port_29=10 +dport_map_port_30=11 +dport_map_port_31=12 +dport_map_port_32=13 +dport_map_port_33=14 +dport_map_port_34=15 +dport_map_port_35=16 +dport_map_port_40=17 +dport_map_port_41=18 +dport_map_port_42=19 +dport_map_port_43=20 +dport_map_port_44=21 +dport_map_port_45=22 +dport_map_port_46=23 +dport_map_port_47=24 +dport_map_port_48=25 +dport_map_port_49=26 +dport_map_port_50=27 +dport_map_port_51=28 +dport_map_port_52=29 +dport_map_port_53=30 +dport_map_port_54=31 +dport_map_port_55=32 +dport_map_port_1=33 +dport_map_port_2=34 +dport_map_port_3=35 +dport_map_port_4=36 +dport_map_port_5=37 +dport_map_port_6=38 +dport_map_port_7=39 +dport_map_port_8=40 +dport_map_port_9=41 +dport_map_port_10=42 +dport_map_port_11=43 +dport_map_port_12=44 +dport_map_port_13=45 +dport_map_port_14=46 +dport_map_port_15=47 +dport_map_port_16=48 +dport_map_port_60=49 +dport_map_port_61=50 +dport_map_port_62=51 +dport_map_port_63=52 +dport_map_port_64=53 +dport_map_port_65=54 +dport_map_port_66=55 +dport_map_port_67=56 +dport_map_port_68=57 +dport_map_port_69=58 +dport_map_port_70=59 +dport_map_port_71=60 +dport_map_port_72=61 +dport_map_port_73=62 +dport_map_port_74=63 +dport_map_port_75=64 +dport_map_port_80=65 +dport_map_port_81=66 +dport_map_port_82=67 +dport_map_port_83=68 +dport_map_port_84=69 +dport_map_port_85=70 +dport_map_port_86=71 +dport_map_port_87=72 +dport_map_port_88=73 +dport_map_port_89=74 +dport_map_port_90=75 +dport_map_port_91=76 +dport_map_port_92=77 +dport_map_port_93=78 +dport_map_port_94=79 +dport_map_port_95=80 +dport_map_port_140=81 +dport_map_port_141=82 +dport_map_port_142=83 +dport_map_port_143=84 +dport_map_port_144=85 +dport_map_port_145=86 +dport_map_port_146=87 +dport_map_port_147=88 +dport_map_port_148=89 +dport_map_port_149=90 +dport_map_port_150=91 +dport_map_port_151=92 +dport_map_port_152=93 +dport_map_port_153=94 +dport_map_port_154=95 +dport_map_port_155=96 +dport_map_port_100=97 +dport_map_port_101=98 +dport_map_port_102=99 +dport_map_port_103=100 +dport_map_port_104=101 +dport_map_port_105=102 +dport_map_port_106=103 +dport_map_port_107=104 +dport_map_port_108=105 +dport_map_port_109=106 +dport_map_port_110=107 +dport_map_port_111=108 +dport_map_port_112=109 +dport_map_port_113=110 +dport_map_port_114=111 +dport_map_port_115=112 +dport_map_port_120=113 +dport_map_port_121=114 +dport_map_port_122=115 +dport_map_port_123=116 +dport_map_port_124=117 +dport_map_port_125=118 +dport_map_port_126=119 +dport_map_port_127=120 +dport_map_port_128=121 +dport_map_port_129=122 +dport_map_port_130=123 +dport_map_port_131=124 +dport_map_port_132=125 +dport_map_port_133=126 +dport_map_port_134=127 +dport_map_port_135=128 + +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/celestica/x86_64-cel_silverstone-r0/Silverstone/port_config.ini b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/port_config.ini new file mode 100644 index 000000000000..9cd85ee34798 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 33,34,35,36,37,38,39,40 QSFPDD1 1 400000 +Ethernet4 41,42,43,44,45,46,47,48 QSFPDD2 2 400000 +Ethernet8 49,50,51,52,53,54,55,56 QSFPDD3 3 400000 +Ethernet12 57,58,59,60,61,62,63,64 QSFPDD4 4 400000 +Ethernet16 65,66,67,68,69,70,71,72 QSFPDD5 5 400000 +Ethernet20 73,74,75,76,77,78,79,80 QSFPDD6 6 400000 +Ethernet24 81,82,83,84,85,86,87,88 QSFPDD7 7 400000 +Ethernet28 89,90,91,92,93,94,95,96 QSFPDD8 8 400000 +Ethernet32 1,2,3,4,5,6,7,8 QSFPDD9 9 400000 +Ethernet36 9,10,11,12,13,14,15,16 QSFPDD10 10 400000 +Ethernet40 17,18,19,20,21,22,23,24 QSFPDD11 11 400000 +Ethernet44 25,26,27,28,29,30,31,32 QSFPDD12 12 400000 +Ethernet48 97,98,99,100,101,102,103,104 QSFPDD13 13 400000 +Ethernet52 105,106,107,108,109,110,111,112 QSFPDD14 14 400000 +Ethernet56 113,114,115,116,117,118,119,120 QSFPDD15 15 400000 +Ethernet60 121,122,123,124,125,126,127,128 QSFPDD16 16 400000 +Ethernet64 129,130,131,132,133,134,135,136 QSFPDD17 17 400000 +Ethernet68 137,138,139,140,141,142,143,144 QSFPDD18 18 400000 +Ethernet72 145,146,147,148,149,150,151,152 QSFPDD19 19 400000 +Ethernet76 153,154,155,156,157,158,159,160 QSFPDD20 20 400000 +Ethernet80 225,226,227,228,229,230,231,232 QSFPDD21 21 400000 +Ethernet84 233,234,235,236,237,238,239,240 QSFPDD22 22 400000 +Ethernet88 241,242,243,244,245,246,247,248 QSFPDD23 23 400000 +Ethernet92 249,250,251,252,253,254,255,256 QSFPDD24 24 400000 +Ethernet96 161,162,163,164,165,166,167,168 QSFPDD25 25 400000 +Ethernet100 169,170,171,172,173,174,175,176 QSFPDD26 26 400000 +Ethernet104 177,178,179,180,181,182,183,184 QSFPDD27 27 400000 +Ethernet108 185,186,187,188,189,190,191,192 QSFPDD28 28 400000 +Ethernet112 193,194,195,196,197,198,199,200 QSFPDD29 29 400000 +Ethernet116 201,202,203,204,205,206,207,208 QSFPDD30 30 400000 +Ethernet120 209,210,211,212,213,214,215,216 QSFPDD31 31 400000 +Ethernet124 217,218,219,220,221,222,223,224 QSFPDD32 32 400000 \ No newline at end of file diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/sai.profile b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/sai.profile new file mode 100644 index 000000000000..550bfe181df4 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-32x400G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/celestica/x86_64-cel_silverstone-r0/Silverstone/th3-32x400G.config.bcm b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/th3-32x400G.config.bcm new file mode 100644 index 000000000000..5e5fc82aeace --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/Silverstone/th3-32x400G.config.bcm @@ -0,0 +1,231 @@ + +pbmp_xport_xe.0=0x8111181111c1111811118111181111c111182222 +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 + +init_all_modules=0 + + + +#portmap_38=257:10 +#portmap_118=258:10 + + +portmap_20=33:400 +portmap_24=41:400 +portmap_28=49:400 +portmap_32=57:400 +portmap_40=65:400 +portmap_44=73:400 +portmap_48=81:400 +portmap_52=89:400 +portmap_1=1:400 +portmap_5=9:400 +portmap_9=17:400 +portmap_13=25:400 +portmap_60=97:400 +portmap_64=105:400 +portmap_68=113:400 +portmap_72=121:400 +portmap_80=129:400 +portmap_84=137:400 +portmap_88=145:400 +portmap_92=153:400 +portmap_140=225:400 +portmap_144=233:400 +portmap_148=241:400 +portmap_152=249:400 +portmap_100=161:400 +portmap_104=169:400 +portmap_108=177:400 +portmap_112=185:400 +portmap_120=193:400 +portmap_124=201:400 +portmap_128=209:400 +portmap_132=217:400 + +phy_chain_rx_lane_map_physical{33.0}=0x65732041 +phy_chain_tx_lane_map_physical{33.0}=0x47206531 +phy_chain_rx_lane_map_physical{41.0}=0x07561243 +phy_chain_tx_lane_map_physical{41.0}=0x36207514 +phy_chain_rx_lane_map_physical{49.0}=0x54632071 +phy_chain_tx_lane_map_physical{49.0}=0x06241735 +phy_chain_rx_lane_map_physical{57.0}=0x07561243 +phy_chain_tx_lane_map_physical{57.0}=0x35207614 +phy_chain_rx_lane_map_physical{65.0}=0x45623170 +phy_chain_tx_lane_map_physical{65.0}=0x51260734 +phy_chain_rx_lane_map_physical{73.0}=0x07561243 +phy_chain_tx_lane_map_physical{73.0}=0x37245610 +phy_chain_rx_lane_map_physical{81.0}=0x45632071 +phy_chain_tx_lane_map_physical{81.0}=0x51260734 +phy_chain_rx_lane_map_physical{89.0}=0x07561243 +phy_chain_tx_lane_map_physical{89.0}=0x26437510 +phy_chain_rx_lane_map_physical{1.0}=0x30176524 +phy_chain_tx_lane_map_physical{1.0}=0x20615374 +phy_chain_rx_lane_map_physical{9.0}=0x37562041 +phy_chain_tx_lane_map_physical{9.0}=0x05176432 +phy_chain_rx_lane_map_physical{17.0}=0x43607251 +phy_chain_tx_lane_map_physical{17.0}=0x70261435 +phy_chain_rx_lane_map_physical{25.0}=0x60347125 +phy_chain_tx_lane_map_physical{25.0}=0x46357120 +phy_chain_rx_lane_map_physical{97.0}=0x47601352 +phy_chain_tx_lane_map_physical{97.0}=0x04265137 +phy_chain_rx_lane_map_physical{105.0}=0x73206415 +phy_chain_tx_lane_map_physical{105.0}=0x26374150 +phy_chain_rx_lane_map_physical{113.0}=0x47632051 +phy_chain_tx_lane_map_physical{113.0}=0x03254617 +phy_chain_rx_lane_map_physical{121.0}=0x63027415 +phy_chain_tx_lane_map_physical{121.0}=0x63721045 +phy_chain_rx_lane_map_physical{129.0}=0x30154627 +phy_chain_tx_lane_map_physical{129.0}=0x04735261 +phy_chain_rx_lane_map_physical{137.0}=0x24753061 +phy_chain_tx_lane_map_physical{137.0}=0x37614520 +phy_chain_rx_lane_map_physical{145.0}=0x47601352 +phy_chain_tx_lane_map_physical{145.0}=0x63274510 +phy_chain_rx_lane_map_physical{153.0}=0x07361524 +phy_chain_tx_lane_map_physical{153.0}=0x36527104 +phy_chain_rx_lane_map_physical{225.0}=0x56410273 +phy_chain_tx_lane_map_physical{225.0}=0x10274635 +phy_chain_rx_lane_map_physical{233.0}=0x15740263 +phy_chain_tx_lane_map_physical{233.0}=0x24351607 +phy_chain_rx_lane_map_physical{241.0}=0x74015263 +phy_chain_tx_lane_map_physical{241.0}=0x04152637 +phy_chain_rx_lane_map_physical{249.0}=0x62037514 +phy_chain_tx_lane_map_physical{249.0}=0x72453160 +phy_chain_rx_lane_map_physical{161.0}=0x46510273 +phy_chain_tx_lane_map_physical{161.0}=0x01653724 +phy_chain_rx_lane_map_physical{169.0}=0x25743160 +phy_chain_tx_lane_map_physical{169.0}=0x07216435 +phy_chain_rx_lane_map_physical{177.0}=0x46510273 +phy_chain_tx_lane_map_physical{177.0}=0x01652734 +phy_chain_rx_lane_map_physical{185.0}=0x25743160 +phy_chain_tx_lane_map_physical{185.0}=0x37016425 +phy_chain_rx_lane_map_physical{193.0}=0x46510372 +phy_chain_tx_lane_map_physical{193.0}=0x06153724 +phy_chain_rx_lane_map_physical{201.0}=0x25743160 +phy_chain_tx_lane_map_physical{201.0}=0x36017524 +phy_chain_rx_lane_map_physical{209.0}=0x47601352 +phy_chain_tx_lane_map_physical{209.0}=0x04152736 +phy_chain_rx_lane_map_physical{217.0}=0x26453170 +phy_chain_tx_lane_map_physical{217.0}=0x36027415 + +serdes_core_rx_polarity_flip_physical{33}=0x29 +serdes_core_tx_polarity_flip_physical{33}=0xfe +serdes_core_rx_polarity_flip_physical{41}=0xb1 +serdes_core_tx_polarity_flip_physical{41}=0xe8 +serdes_core_rx_polarity_flip_physical{49}=0xca +serdes_core_tx_polarity_flip_physical{49}=0xb6 +serdes_core_rx_polarity_flip_physical{57}=0x9b +serdes_core_tx_polarity_flip_physical{57}=0xdc +serdes_core_rx_polarity_flip_physical{65}=0x17 +serdes_core_tx_polarity_flip_physical{65}=0x86 +serdes_core_rx_polarity_flip_physical{73}=0x9b +serdes_core_tx_polarity_flip_physical{73}=0x55 +serdes_core_rx_polarity_flip_physical{81}=0xa +serdes_core_tx_polarity_flip_physical{81}=0x6 +serdes_core_rx_polarity_flip_physical{89}=0x9b +serdes_core_tx_polarity_flip_physical{89}=0x48 +serdes_core_rx_polarity_flip_physical{1}=0xec +serdes_core_tx_polarity_flip_physical{1}=0x56 +serdes_core_rx_polarity_flip_physical{9}=0x13 +serdes_core_tx_polarity_flip_physical{9}=0xa6 +serdes_core_rx_polarity_flip_physical{17}=0x5a +serdes_core_tx_polarity_flip_physical{17}=0xc6 +serdes_core_rx_polarity_flip_physical{25}=0xf +serdes_core_tx_polarity_flip_physical{25}=0x4e +serdes_core_rx_polarity_flip_physical{97}=0x17 +serdes_core_tx_polarity_flip_physical{97}=0x2e +serdes_core_rx_polarity_flip_physical{105}=0xce +serdes_core_tx_polarity_flip_physical{105}=0x7c +serdes_core_rx_polarity_flip_physical{113}=0xa +serdes_core_tx_polarity_flip_physical{113}=0x35 + +serdes_core_rx_polarity_flip_physical{121}=0xb9 +serdes_core_tx_polarity_flip_physical{121}=0xef +serdes_core_rx_polarity_flip_physical{129}=0xe8 +serdes_core_tx_polarity_flip_physical{129}=0xac +serdes_core_rx_polarity_flip_physical{137}=0xcb +serdes_core_tx_polarity_flip_physical{137}=0x9c +serdes_core_rx_polarity_flip_physical{145}=0x17 +serdes_core_tx_polarity_flip_physical{145}=0x32 +serdes_core_rx_polarity_flip_physical{153}=0xb9 +serdes_core_tx_polarity_flip_physical{153}=0xaf +serdes_core_rx_polarity_flip_physical{225}=0xaa +serdes_core_tx_polarity_flip_physical{225}=0x7 +serdes_core_rx_polarity_flip_physical{233}=0x31 +serdes_core_tx_polarity_flip_physical{233}=0x47 +serdes_core_rx_polarity_flip_physical{241}=0xe8 +serdes_core_tx_polarity_flip_physical{241}=0x9e +serdes_core_rx_polarity_flip_physical{249}=0xec +serdes_core_tx_polarity_flip_physical{249}=0x1f +serdes_core_rx_polarity_flip_physical{161}=0x6a +serdes_core_tx_polarity_flip_physical{161}=0xd4 +serdes_core_rx_polarity_flip_physical{169}=0x9e +serdes_core_tx_polarity_flip_physical{169}=0x7b +serdes_core_rx_polarity_flip_physical{177}=0x6a +serdes_core_tx_polarity_flip_physical{177}=0xcc +serdes_core_rx_polarity_flip_physical{185}=0x9e +serdes_core_tx_polarity_flip_physical{185}=0x58 +serdes_core_rx_polarity_flip_physical{193}=0x6f +serdes_core_tx_polarity_flip_physical{193}=0x24 +serdes_core_rx_polarity_flip_physical{201}=0x9e +serdes_core_tx_polarity_flip_physical{201}=0xdf +serdes_core_rx_polarity_flip_physical{209}=0x17 +serdes_core_tx_polarity_flip_physical{209}=0xe9 +serdes_core_rx_polarity_flip_physical{217}=0xec +serdes_core_tx_polarity_flip_physical{217}=0x68 + +dport_map_port_20=1 +dport_map_port_24=2 +dport_map_port_28=3 +dport_map_port_32=4 +dport_map_port_40=5 +dport_map_port_44=6 +dport_map_port_48=7 +dport_map_port_52=8 +dport_map_port_1=9 +dport_map_port_5=10 +dport_map_port_9=11 +dport_map_port_13=12 +dport_map_port_60=13 +dport_map_port_64=14 +dport_map_port_68=15 +dport_map_port_72=16 +dport_map_port_80=17 +dport_map_port_84=18 +dport_map_port_88=19 +dport_map_port_92=20 +dport_map_port_140=21 +dport_map_port_144=22 +dport_map_port_148=23 +dport_map_port_152=24 +dport_map_port_100=25 +dport_map_port_104=26 +dport_map_port_108=27 +dport_map_port_112=28 +dport_map_port_120=29 +dport_map_port_124=30 +dport_map_port_128=31 +dport_map_port_132=32 + +#dport_map_port_38=33 +#dport_map_port_118=34 + + + +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/celestica/x86_64-cel_silverstone-r0/custom.bin b/device/celestica/x86_64-cel_silverstone-r0/custom.bin new file mode 100644 index 000000000000..a08ba6c06661 Binary files /dev/null and b/device/celestica/x86_64-cel_silverstone-r0/custom.bin differ diff --git a/device/celestica/x86_64-cel_silverstone-r0/default_sku b/device/celestica/x86_64-cel_silverstone-r0/default_sku new file mode 100644 index 000000000000..07d986a8431d --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/default_sku @@ -0,0 +1 @@ +Silverstone t1 diff --git a/device/celestica/x86_64-cel_silverstone-r0/installer.conf b/device/celestica/x86_64-cel_silverstone-r0/installer.conf new file mode 100644 index 000000000000..5e62742c11bf --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=115200 diff --git a/device/celestica/x86_64-cel_silverstone-r0/led_proc_init.soc b/device/celestica/x86_64-cel_silverstone-r0/led_proc_init.soc new file mode 100644 index 000000000000..3a8ac119076e --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/led_proc_init.soc @@ -0,0 +1,7 @@ +#The Port LED of Silverstone SONIC can't work well, after the issue is fixed by SAI, The led will start. +#led auto on; led start +linkscan off +m0 load 0 0x3800 /usr/share/sonic/platform/custom.bin +sleep 10 +led auto on; led start +linkscan on diff --git a/device/celestica/x86_64-cel_silverstone-r0/linkscan_fw.bin b/device/celestica/x86_64-cel_silverstone-r0/linkscan_fw.bin new file mode 100644 index 000000000000..e86cdc1ef647 Binary files /dev/null and b/device/celestica/x86_64-cel_silverstone-r0/linkscan_fw.bin differ diff --git a/device/celestica/x86_64-cel_silverstone-r0/plugins/eeprom.py b/device/celestica/x86_64-cel_silverstone-r0/plugins/eeprom.py new file mode 100644 index 000000000000..012196b0dd4c --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# 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: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/celestica/x86_64-cel_silverstone-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_silverstone-r0/plugins/psuutil.py new file mode 100644 index 000000000000..ca75ad98334c --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/plugins/psuutil.py @@ -0,0 +1,89 @@ +import os.path +import subprocess +import sys +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): + self.ipmi_raw = "docker exec -ti pmon ipmitool raw 0x4 0x2d" + self.psu1_id = "0x2f" + self.psu2_id = "0x39" + PsuBase.__init__(self) + + def run_command(self, command): + proc = subprocess.Popen(command, shell=True, universal_newlines=True, stdout=subprocess.PIPE) + (out, err) = proc.communicate() + + if proc.returncode != 0: + sys.exit(proc.returncode) + + return out + + def find_value(self, in_string): + result = re.search("^.+ ([0-9a-f]{2}) .+$", in_string) + if result: + return result.group(1) + else: + return result + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + psu_id = self.psu1_id if index == 1 else self.psu2_id + res_string = self.run_command(self.ipmi_raw + ' ' + psu_id) + status_byte = self.find_value(res_string) + + if status_byte is None: + return False + + failure_detected = (int(status_byte, 16) >> 1) & 1 + input_lost = (int(status_byte, 16) >> 3) & 1 + if failure_detected or input_lost: + return False + else: + return True + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + psu_id = self.psu1_id if index == 1 else self.psu2_id + res_string = self.run_command(self.ipmi_raw + ' ' + psu_id) + status_byte = self.find_value(res_string) + + if status_byte is None: + return False + + presence = (int(status_byte, 16) >> 0) & 1 + if presence: + return True + else: + return False diff --git a/device/celestica/x86_64-cel_silverstone-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_silverstone-r0/plugins/sfputil.py new file mode 100755 index 000000000000..c089b42c3638 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/plugins/sfputil.py @@ -0,0 +1,184 @@ +# Platform-specific SFP transceiver interface for SONiC +# This plugin supports QSFP-DD, QSFP and SFP. + +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 = 34 + OSFP_PORT_START = 1 + OSFP_PORT_END = 32 + SFP_PORT_START = 33 + SFP_PORT_END = 34 + + EEPROM_OFFSET = 9 + PORT_INFO_PATH = '/sys/class/silverstone_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 [] + + @property + def osfp_ports(self): + return list(range(self.OSFP_PORT_START, self.OSFP_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.osfp_ports: + self._port_name = "QSFP" + str(port_num - self.OSFP_PORT_START + 1) + else: + self._port_name = "SFP" + str(port_num - self.SFP_PORT_START + 1) + return self._port_name + + def get_eeprom_dom_raw(self, port_num): + if port_num in self.osfp_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 list(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.osfp_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): + # Check for invalid QSFP port_num + if port_num not in self.osfp_ports: + return False + + try: + port_name = self.get_port_name(port_num) + reg_file = open("/".join([self.PORT_INFO_PATH, + port_name, "qsfp_lpmode"])) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # Read status + content = reg_file.readline().rstrip() + reg_value = int(content) + # low power mode is active high + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid QSFP port_num + if port_num not in self.osfp_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.osfp_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 + """ + raise NotImplementedError 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/celestica/x86_64-cel_silverstone-r0/sonic_platform/__init__.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/__init__.py new file mode 100644 index 000000000000..d82f3749319c --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/chassis.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/chassis.py new file mode 100644 index 000000000000..b6f77cbd3dc9 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/chassis.py @@ -0,0 +1,131 @@ +############################################################################# +# 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.component import Component + from sonic_platform.eeprom import Tlv + from sonic_platform.fan import Fan + from sonic_platform.sfp import Sfp + from sonic_platform.psu import Psu + from sonic_platform.thermal import Thermal + 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 = 10 +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) + + for index in range(0, NUM_SFP): + sfp = Sfp(index) + self._sfp_list.append(sfp) + + for index in range(0, NUM_PSU): + psu = Psu(index) + self._psu_list.append(psu) + for index in range(0, NUM_COMPONENT): + component = Component(index) + self._component_list.append(component) + for index in range(0, NUM_THERMAL): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + 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(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 and len( + raw_cause.split()) > 0 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/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/component.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/component.py new file mode 100644 index 000000000000..bbbb9f1d458d --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/component.py @@ -0,0 +1,119 @@ +############################################################################# +# Celestica +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +import json +import os.path + +try: + from sonic_platform_base.component_base import ComponentBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +COMPONENT_LIST = [ + ("BIOS", "Basic Input/Output System"), + ("BMC", "Baseboard Management Controller"), + ("SWITCH_CPLD", "Switch board CPLD"), + ("BASE_CPLD", "Base board CPLD"), + ("FPGA", "Field-programmable gate array") +] +SW_CPLD_VER_PATH = "/sys/module/switch_cpld/version" +BASE_CPLD_VER_PATH = "/sys/module/baseboard_lpc/version" +CPLD_UPGRADE_OPT = 4 +BIOS_VER_PATH = "/sys/class/dmi/id/bios_version" +BIOS__UPGRADE_OPT = 2 +BMC_VER_CMD = "ipmitool mc info | grep 'Firmware Revision'" +BMC_UPGRADE_OPT = 1 +CFUFLASH_FW_UPGRADE_CMD = "CFUFLASH -cd -d {} -mse 3 {}" +MEM_PCI_RESOURCE = "/sys/bus/pci/devices/0000:09:00.0/resource0" +FPGA_VER_MEM_OFFSET = 0 + + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index): + ComponentBase.__init__(self) + self.index = component_index + self.name = self.get_name() + self._api_helper = APIHelper() + + def __get_bmc_ver(self): + bmc_ver = "Unknown" + status, raw_bmc_data = self._api_helper.run_command(BMC_VER_CMD) + if status: + bmc_ver_data = raw_bmc_data.split(":") + bmc_ver = bmc_ver_data[-1].strip() if len( + bmc_ver_data) > 1 else bmc_ver + return bmc_ver + + def __get_fpga_ver(self): + fpga_ver = "Unknown" + status, reg_val = self._api_helper.pci_get_value( + MEM_PCI_RESOURCE, FPGA_VER_MEM_OFFSET) + if status: + major = reg_val[0] >> 16 + minor = int(bin(reg_val[0])[16:32], 2) + fpga_ver = '{}.{}'.format(major, minor) + return fpga_ver + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return COMPONENT_LIST[self.index][0] + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return COMPONENT_LIST[self.index][1] + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + fw_version = { + "BIOS": self._api_helper.read_txt_file(BIOS_VER_PATH), + "BMC": self.__get_bmc_ver(), + "FPGA": self.__get_fpga_ver(), + "SWITCH_CPLD": self._api_helper.read_txt_file(SW_CPLD_VER_PATH), + "BASE_CPLD": self._api_helper.read_txt_file(BASE_CPLD_VER_PATH), + }.get(self.name, "Unknown") + + return fw_version + + def install_firmware(self, image_path): + """ + Install firmware to module + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install successfully, False if not + """ + install_command = { + "BMC": CFUFLASH_FW_UPGRADE_CMD.format(BMC_UPGRADE_OPT, image_path), + "BIOS": CFUFLASH_FW_UPGRADE_CMD.format(BIOS__UPGRADE_OPT, image_path), + "SWITCH_CPLD": CFUFLASH_FW_UPGRADE_CMD.format(CPLD_UPGRADE_OPT, image_path), + "BASE_CPLD": CFUFLASH_FW_UPGRADE_CMD.format(CPLD_UPGRADE_OPT, image_path) + }.get(self.name, None) + + if not os.path.isfile(image_path) or install_command is None: + return False + + # print(install_command) + status = self._api_helper.run_interactive_command(install_command) + return status diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/eeprom.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/eeprom.py new file mode 100644 index 000000000000..cf3f1a98de20 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/eeprom.py @@ -0,0 +1,117 @@ +############################################################################# +# 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 re + from array import array + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as 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/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/fan.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/fan.py new file mode 100644 index 000000000000..1055aee68fc7 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/fan.py @@ -0,0 +1,300 @@ +############################################################################# +# 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_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 + +NUM_OF_FAN_TRAY = 7 +PSU_FAN1_FRONT_SS_ID = "0x33" + + +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 + fan_direction_key = hex(self.fan_tray_index) if not self.is_psu_fan else hex( + self.psu_index + NUM_OF_FAN_TRAY) + status, raw_flow = self._api_helper.ipmi_raw( + IPMI_OEM_NETFN, IPMI_AIR_FLOW_CMD.format(fan_direction_key)) + 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 + """ + + 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) if not self.psu_index else hex( + int(PSU_FAN1_FRONT_SS_ID, 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 + + if self.is_psu_fan: + # TODO + return False + + 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 + """ + + if self.is_psu_fan: + # Not support + return False + + 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" + """ + if self.is_psu_fan: + # Not support + return self.STATUS_LED_COLOR_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 + """ + if self.is_psu_fan: + return True + + 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 + """ + if self.is_psu_fan: + return "Unknown" + + 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 + """ + if self.is_psu_fan: + return "Unknown" + + 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/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/helper.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/helper.py new file mode 100644 index 000000000000..144d9e154348 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/helper.py @@ -0,0 +1,108 @@ +import os +import struct +import subprocess +from mmap import * + +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 pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except: + status = False + return status, result + + def run_command(self, cmd): + status = True + result = "" + try: + p = subprocess.Popen( + cmd, shell=True, universal_newlines=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 run_interactive_command(self, cmd): + try: + os.system(cmd) + except: + return False + return True + + 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, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + result = raw_data.strip() + else: + status = False + 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, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + result = raw_data.strip() + else: + status = False + except: + status = False + return status, result + + def ipmi_set_ss_thres(self, id, threshold_key, value): + status = True + result = "" + try: + cmd = "ipmitool sensor thresh '{}' {} {}".format(str(id), str(threshold_key), str(value)) + p = subprocess.Popen( + cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + result = raw_data.strip() + else: + status = False + except: + status = False + return status, result diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/platform.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/platform.py new file mode 100644 index 000000000000..7d98ec9f7cdf --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/platform.py @@ -0,0 +1,21 @@ +############################################################################# +# 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/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/psu.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/psu.py new file mode 100644 index 000000000000..9ad0f1dc9392 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/psu.py @@ -0,0 +1,241 @@ +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os +import re +import math +import sonic_platform + +try: + from sonic_platform_base.psu_base import PsuBase + from .helper import APIHelper + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PSU_NAME_LIST = ["PSU-1", "PSU-2"] +PSU_NUM_FAN = [1, 1] + +IPMI_SENSOR_NETFN = "0x04" +IPMI_OEM_NETFN = "0x3A" +IPMI_SS_READ_CMD = "0x2D {}" +IPMI_SET_PSU_LED_CMD = "0x07 0x02 {}" +IPMI_GET_PSU_LED_CMD = "0x08 0x02" +IPMI_FRU_MODEL_KEY = "Board Part Number" +IPMI_FRU_SERIAL_KEY = "Board Serial" + +PSU_LED_OFF_CMD = "0x00" +PSU_LED_GREEN_CMD = "0x01" +PSU_LED_AMBER_CMD = "0x02" + +PSU1_VOUT_SS_ID = "0x36" +PSU1_COUT_SS_ID = "0x37" +PSU1_POUT_SS_ID = "0x38" +PSU1_STATUS_REG = "0x39" + +PSU2_VOUT_SS_ID = "0x40" +PSU2_COUT_SS_ID = "0x41" +PSU2_POUT_SS_ID = "0x42" +PSU2_STATUS_REG = "0x2f" + +PSU1_FRU_ID = 3 + +SS_READ_OFFSET = 0 + + +class Psu(PsuBase): + """Platform-specific Psu class""" + + def __init__(self, psu_index): + PsuBase.__init__(self) + self.index = psu_index + for fan_index in range(0, PSU_NUM_FAN[self.index]): + fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index) + self._fan_list.append(fan) + self._api_helper = APIHelper() + + def find_value(self, in_string): + result = re.search("^.+ ([0-9a-f]{2}) .+$", in_string) + return result.group(1) if result else result + + def get_voltage(self): + """ + Retrieves current PSU voltage output + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + psu_voltage = 0.0 + psu_vout_key = globals()['PSU{}_VOUT_SS_ID'.format(self.index+1)] + status, raw_ss_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_vout_key)) + ss_read = raw_ss_read.split()[SS_READ_OFFSET] + # Formula: Rx1x10^-1 + psu_voltage = int(ss_read, 16) * math.pow(10, -1) + + return psu_voltage + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + psu_current = 0.0 + psu_cout_key = globals()['PSU{}_COUT_SS_ID'.format(self.index+1)] + status, raw_ss_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_cout_key)) + ss_read = raw_ss_read.split()[SS_READ_OFFSET] + # Formula: Rx5x10^-1 + psu_current = int(ss_read, 16) * 5 * math.pow(10, -1) + + return psu_current + + def get_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, e.g. 302.6 + """ + psu_power = 0.0 + psu_pout_key = globals()['PSU{}_POUT_SS_ID'.format(self.index+1)] + status, raw_ss_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_pout_key)) + ss_read = raw_ss_read.split()[SS_READ_OFFSET] + # Formula: Rx6x10^0 + psu_power = int(ss_read, 16) * 6 + return psu_power + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + return self.get_status() + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the PSU status LED + Note: Only support green and off + Returns: + bool: True if status LED state is set successfully, False if not + Note + Set manual + ipmitool raw 0x3a 0x09 0x2 0x0 + """ + led_cmd = { + self.STATUS_LED_COLOR_GREEN: PSU_LED_GREEN_CMD, + self.STATUS_LED_COLOR_AMBER: PSU_LED_AMBER_CMD, + self.STATUS_LED_COLOR_OFF: PSU_LED_OFF_CMD + }.get(color) + + status, set_led = self._api_helper.ipmi_raw( + IPMI_OEM_NETFN, IPMI_SET_PSU_LED_CMD.format(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 PSU status LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + status, hx_color = self._api_helper.ipmi_raw( + IPMI_OEM_NETFN, IPMI_GET_PSU_LED_CMD) + + status_led = { + "00": self.STATUS_LED_COLOR_OFF, + "01": self.STATUS_LED_COLOR_GREEN, + "02": self.STATUS_LED_COLOR_AMBER, + }.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 + """ + return PSU_NAME_LIST[self.index] + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + psu_presence = False + psu_pstatus_key = globals()['PSU{}_STATUS_REG'.format(self.index+1)] + status, raw_status_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_pstatus_key)) + status_byte = self.find_value(raw_status_read) + + if status: + presence_int = (int(status_byte, 16) >> 0) & 1 + psu_presence = True if presence_int else False + + return psu_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.index + PSU1_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.index + PSU1_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 + """ + psu_status = False + psu_pstatus_key = globals()['PSU{}_STATUS_REG'.format(self.index+1)] + status, raw_status_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(psu_pstatus_key)) + status_byte = self.find_value(raw_status_read) + + if status: + failure_detected = (int(status_byte, 16) >> 1) & 1 + input_lost = (int(status_byte, 16) >> 3) & 1 + psu_status = False if (input_lost or failure_detected) else True + + return psu_status diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py new file mode 100644 index 000000000000..e909416e9081 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py @@ -0,0 +1,1464 @@ +############################################################################# +# Celestica +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# + +import os +import time +import subprocess +from ctypes import create_string_buffer + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.inf8628 import inf8628InterfaceId + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +INFO_OFFSET = 128 +DOM_OFFSET = 0 + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 + +XCVR_INTERFACE_DATA_START = 0 +XCVR_INTERFACE_DATA_SIZE = 92 + +QSFP_DOM_BULK_DATA_START = 22 +QSFP_DOM_BULK_DATA_SIZE = 36 +SFP_DOM_BULK_DATA_START = 96 +SFP_DOM_BULK_DATA_SIZE = 10 + +# definitions of the offset for values in OSFP info eeprom +OSFP_TYPE_OFFSET = 0 +OSFP_VENDOR_NAME_OFFSET = 129 +OSFP_VENDOR_PN_OFFSET = 148 +OSFP_HW_REV_OFFSET = 164 +OSFP_VENDOR_SN_OFFSET = 166 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_MODULE_MONITOR_OFFSET = 0 +QSFP_MODULE_MONITOR_WIDTH = 9 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_POWEROVERRIDE_BIT = 0 +QSFP_POWERSET_BIT = 1 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 +QSFP_MODULE_UPPER_PAGE3_START = 384 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNL_THRESHOLD_OFFSET = 176 +QSFP_CHANNL_THRESHOLD_WIDTH = 24 + +SFP_MODULE_ADDRA2_OFFSET = 256 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_CHANNL_STATUS_OFFSET = 110 +SFP_CHANNL_STATUS_WIDTH = 1 + + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" +OSFP_TYPE = "OSFP" + +PORT_START = 1 +PORT_END = 34 +OSFP_PORT_START = 1 +OSFP_PORT_END = 32 +SFP_PORT_START = 33 +SFP_PORT_END = 34 + +PORT_INFO_PATH = '/sys/devices/platform/cls-xcvr' + + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + + # Path to QSFP sysfs + PLATFORM_ROOT_PATH = "/usr/share/sonic/device" + PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" + HOST_CHK_CMD = "docker > /dev/null 2>&1" + + PLATFORM = "x86_64-cel_silverstone-r0" + HWSKU = "Silverstone" + + def __init__(self, sfp_index): + SfpBase.__init__(self) + # Init index + self.index = sfp_index + self.port_num = self.index + 1 + self.dom_supported = False + self.sfp_type, self.port_name = self.__get_sfp_info() + + # Init eeprom path + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' + self.port_to_eeprom_mapping = {} + self.port_to_i2c_mapping = { + 1: 10, + 2: 11, + 3: 12, + 4: 13, + 5: 14, + 6: 15, + 7: 16, + 8: 17, + 9: 18, + 10: 19, + 11: 20, + 12: 21, + 13: 22, + 14: 23, + 15: 24, + 16: 25, + 17: 26, + 18: 27, + 19: 28, + 20: 29, + 21: 30, + 22: 31, + 23: 32, + 24: 33, + 25: 34, + 26: 35, + 27: 36, + 28: 37, + 29: 38, + 30: 39, + 31: 40, + 32: 41, + 33: 1, + 34: 2 + } + + for x in range(PORT_START, 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.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + self._dom_capability_detect() + + def __get_sfp_info(self): + port_num = self.index + PORT_START + sfp_type = OSFP_PORT_START + port_name = "Unknown" + + if port_num >= OSFP_PORT_START and port_num <= OSFP_PORT_END: + sfp_type = OSFP_TYPE + port_name = "QSFP" + str(port_num - OSFP_PORT_START + 1) + elif port_num >= SFP_PORT_START and port_num <= SFP_PORT_END: + sfp_type = SFP_TYPE + port_name = "SFP" + str(port_num - SFP_PORT_START + 1) + return sfp_type, port_name + + def __convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def __is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) + hwsku_path = "/".join([platform_path, self.HWSKU] + ) if self.__is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def _dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + return + + if self.sfp_type == "QSFP": + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # 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( + (offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self.__read_eeprom_specific_bytes( + QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH) + qsfp_version_compliance = int( + qsfp_version_compliance_raw[0], 16) + dom_capability = sfpi_obj.parse_dom_capability( + qsfp_dom_capability_raw, 0) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = dom_capability['data']['Temp_support']['value'] == 'On' + self.dom_volt_supported = dom_capability['data']['Voltage_support']['value'] == 'On' + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = dom_capability['data']['Tx_power_support']['value'] == 'On' + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = True + + self.dom_supported = True + self.calibration = 1 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + qsfp_option_value_raw = self.__read_eeprom_specific_bytes( + QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH) + if qsfp_option_value_raw is not None: + optional_capability = sfpd_obj.parse_option_params( + qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = optional_capability[ + 'data']['TxDisable']['value'] == 'On' + dom_status_indicator = sfpd_obj.parse_dom_status_indicator( + qsfp_version_compliance_raw, 1) + self.qsfp_page3_available = dom_status_indicator['data']['FlatMem']['value'] == 'Off' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.qsfp_page3_available = False + + elif self.sfp_type == "SFP": + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = ( + int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + if not self.get_presence(): + return transceiver_info_dict + + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + if self.sfp_type == OSFP_TYPE: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP + + sfpi_obj = inf8628InterfaceId() + if sfpi_obj is None: + return None + + sfp_type_raw = self.__read_eeprom_specific_bytes( + (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes( + (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes( + (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( + (offset + OSFP_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes( + (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_vendor_sn_raw, 0) + else: + return None + + transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = 'N/A' + transceiver_info_dict['vendor_date'] = 'N/A' + transceiver_info_dict['connector'] = 'N/A' + transceiver_info_dict['encoding'] = 'N/A' + transceiver_info_dict['ext_identifier'] = 'N/A' + transceiver_info_dict['ext_rateselect_compliance'] = 'N/A' + transceiver_info_dict['cable_type'] = 'N/A' + transceiver_info_dict['cable_length'] = 'N/A' + transceiver_info_dict['specification_compliance'] = 'N/A' + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + + else: + if self.sfp_type == QSFP_TYPE: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + cable_length_width = XCVR_CABLE_LENGTH_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + sfp_type = 'QSFP' + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + cable_length_width = XCVR_CABLE_LENGTH_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + sfp_type = 'SFP' + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + offset + XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE) + if sfp_interface_bulk_raw is None: + return None + + start = XCVR_INTFACE_BULK_OFFSET - XCVR_INTERFACE_DATA_START + end = start + interface_info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_NAME_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_NAME_WIDTH + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_PN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_PN_WIDTH + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_HW_REV_OFFSET - XCVR_INTERFACE_DATA_START + end = start + vendor_rev_width + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_SN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_SN_WIDTH + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_OUI_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_OUI_WIDTH + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_DATE_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_DATE_WIDTH + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_interface_bulk_raw[start: end], 0) + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + + if self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_DOM_BULK_DATA_START), QSFP_DOM_BULK_DATA_SIZE) + if dom_data_raw is None: + return transceiver_dom_info_dict + + if self.dom_temp_supported: + start = QSFP_TEMPE_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + temp = self.__convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + if temp is not None: + transceiver_dom_info_dict['temperature'] = temp + + if self.dom_volt_supported: + start = QSFP_VOLT_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + volt = self.__convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + if volt is not None: + transceiver_dom_info_dict['voltage'] = volt + + start = QSFP_CHANNL_MON_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power( + dom_data_raw[start: end], 0) + + if self.dom_tx_power_supported: + transceiver_dom_info_dict['tx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX1Power']['value']) + transceiver_dom_info_dict['tx2power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX2Power']['value']) + transceiver_dom_info_dict['tx3power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX3Power']['value']) + transceiver_dom_info_dict['tx4power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX4Power']['value']) + + if self.dom_rx_power_supported: + transceiver_dom_info_dict['rx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX1Power']['value']) + transceiver_dom_info_dict['rx2power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX2Power']['value']) + transceiver_dom_info_dict['rx3power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX3Power']['value']) + transceiver_dom_info_dict['rx4power'] = self.__convert_string_to_num( + 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: + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_DOM_BULK_DATA_START), SFP_DOM_BULK_DATA_SIZE) + + start = SFP_TEMPE_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + + start = SFP_VOLT_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + + start = SFP_CHANNL_MON_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_CHANNL_MON_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_data_raw[start: end], 0) + + transceiver_dom_info_dict['temperature'] = self.__convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + transceiver_dom_info_dict['voltage'] = self.__convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + transceiver_dom_info_dict['rx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RXPower']['value']) + transceiver_dom_info_dict['tx1bias'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXBias']['value']) + transceiver_dom_info_dict['tx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXPower']['value']) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + transceiver_dom_threshold_info_dict = dict.fromkeys( + self.threshold_dict_keys, 'N/A') + + if self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + if not self.dom_supported or not self.qsfp_page3_available: + return transceiver_dom_threshold_info_dict + + # Dom Threshold data starts from offset 384 + # Revert offset back to 0 once data is retrieved + offset = QSFP_MODULE_UPPER_PAGE3_START + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values( + dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNL_THRESHOLD_OFFSET), + QSFP_CHANNL_THRESHOLD_WIDTH) + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values( + dom_channel_threshold_raw, 0) + + # 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'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + + else: + offset = SFP_MODULE_ADDRA2_OFFSET + + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = sff8472Dom(None, self.calibration) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((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 + + # 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 + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + if not self.dom_supported: + return False + + if self.sfp_type == OSFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + dom_module_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_MODULE_MONITOR_OFFSET), QSFP_MODULE_MONITOR_WIDTH) + + if dom_module_monitor_raw is not None: + return True + else: + return False + elif self.sfp_type == SFP_TYPE: + offset = 0 + sfpd_obj = sff8472Dom() + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + + if dom_channel_monitor_raw is not None: + return True + else: + return False + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + if not self.dom_supported: + return None + + rx_los_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x02 != 0) + else: + return None + return rx_los_list + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + if not self.dom_supported: + return None + + tx_fault_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + else: + return None + return tx_fault_list + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + if not self.dom_supported: + return None + + tx_disable_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_DISABLE_STATUS_OFFSET), QSFP_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0x01 != 0) + tx_disable_list.append(tx_disable_data & 0x02 != 0) + tx_disable_list.append(tx_disable_data & 0x04 != 0) + tx_disable_list.append(tx_disable_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0xC0 != 0) + else: + return None + return tx_disable_list + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + if self.sfp_type != OSFP_TYPE: + return False + + try: + reg_file = open( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_lpmode"])) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # Read status + content = reg_file.readline().rstrip() + reg_value = int(content) + # low power mode is active high + if reg_value == 0: + return False + + return True + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + if self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes( + dom_control_raw, 0) + power_override = ( + 'On' == dom_control_data['data']['PowerOverride']['value']) + else: + return False + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + transceiver_bulk_status = self.get_transceiver_bulk_status() + return transceiver_bulk_status.get("temperature", "N/A") + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + Returns: + An integer number of supply voltage in mV + """ + transceiver_bulk_status = self.get_transceiver_bulk_status() + return transceiver_bulk_status.get("voltage", "N/A") + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + transceiver_bulk_status = self.get_transceiver_bulk_status() + tx1_bs = transceiver_bulk_status.get("tx1bias", "N/A") + tx2_bs = transceiver_bulk_status.get("tx2bias", "N/A") + tx3_bs = transceiver_bulk_status.get("tx3bias", "N/A") + tx4_bs = transceiver_bulk_status.get("tx4bias", "N/A") + tx_bias_list = [tx1_bs, tx2_bs, tx3_bs, tx4_bs] + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + rx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (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) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX4Power']['value'])) + else: + return None + else: + return None + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RXPower']['value'])) + else: + return None + else: + return None + + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + tx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_tx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (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) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX4Power']['value'])) + else: + return None + else: + return None + else: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXPower']['value'])) + else: + return None + else: + return None + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + if self.sfp_type != OSFP_TYPE: + return False + + try: + reg_file = open( + "/".join([PORT_INFO_PATH, self.port_name, "qsfp_resetL"]), "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([PORT_INFO_PATH, self.port_name, "qsfp_resetL"]), "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 tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + if self.sfp_type == QSFP_TYPE: + sysfsfile_eeprom = None + try: + tx_disable_ctl = 0xf if tx_disable else 0x0 + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + Returns: + A boolean, True if successful, False if not + """ + if self.sfp_type == QSFP_TYPE: + sysfsfile_eeprom = None + try: + channel_state = self.get_tx_disable_channel() + tx_enable_mask = [0xe, 0xd, 0xb, 0x7] + tx_disable_mask = [0x1, 0x3, 0x7, 0xf] + tx_disable_ctl = channel_state | tx_disable_mask[ + channel] if disable else channel_state & tx_enable_mask[channel] + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if self.sfp_type != OSFP_TYPE: + return False + + try: + reg_file = open( + "/".join([PORT_INFO_PATH, self.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 set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + if self.sfp_type == QSFP_TYPE: + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + sysfs_filename = "sfp_modabs" if self.sfp_type == SFP_TYPE else "qsfp_modprsL" + reg_path = "/".join([PORT_INFO_PATH, self.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_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("model", "N/A") + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("serial", "N/A") + + 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() diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/thermal.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/thermal.py new file mode 100644 index 000000000000..9ecf12218d50 --- /dev/null +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/thermal.py @@ -0,0 +1,152 @@ +############################################################################# +# Celestica +# +# Thermal contains an implementation of SONiC Platform Base API and +# provides the thermal device status which are available in the platform +# +############################################################################# + +import os +import re +import os.path + +try: + from sonic_platform_base.thermal_base import ThermalBase + from .helper import APIHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +IPMI_SENSOR_NETFN = "0x04" +IPMI_SS_READ_CMD = "0x2D {}" +IPMI_SS_THRESHOLD_CMD = "0x27 {}" +DEFUALT_LOWER_TRESHOLD = 0.0 +HIGH_TRESHOLD_SET_KEY = "unc" + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + def __init__(self, thermal_index): + ThermalBase.__init__(self) + self._api_helper = APIHelper() + self.index = thermal_index + self.THERMAL_LIST = [ + ('TEMP_FAN_U52', 'Fan Tray Middle Temperature Sensor', '0x00'), + ('TEMP_FAN_U17', 'Fan Tray Right Temperature Sensor', '0x01'), + ('TEMP_SW_U52', 'Switchboard Left Inlet Temperature Sensor', '0x02'), + ('TEMP_SW_U16', 'Switchboard Right Inlet Temperature Sensor', '0x03'), + ('TEMP_BB_U3', 'Baseboard Temperature Sensor', '0x04'), + ('TEMP_CPU', 'CPU Internal Temperature Sensor', '0x05'), + ('TEMP_SW_Internal', 'ASIC Internal Temperature Sensor', '0x61'), + ('SW_U04_Temp', 'IR3595 Chip Left Temperature Sensor', '0x4F'), + ('SW_U14_Temp', 'IR3595 Chip Right Temperature Sensor', '0x56'), + ('SW_U4403_Temp', 'IR3584 Chip Temperature Sensor', '0x5D'), + ] + self.sensor_id = self.THERMAL_LIST[self.index][0] + self.sensor_des = self.THERMAL_LIST[self.index][1] + self.sensor_reading_addr = self.THERMAL_LIST[self.index][2] + + def __set_threshold(self, key, value): + print('{} {}'.format(key, value)) + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temperature = 0.0 + status, raw_ss_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_READ_CMD.format(self.sensor_reading_addr)) + if status and len(raw_ss_read.split()) > 0: + ss_read = raw_ss_read.split()[0] + temperature = float(int(ss_read, 16)) + return temperature + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + high_threshold = 0.0 + status, raw_up_thres_read = self._api_helper.ipmi_raw( + IPMI_SENSOR_NETFN, IPMI_SS_THRESHOLD_CMD.format(self.sensor_reading_addr)) + if status and len(raw_up_thres_read.split()) > 6: + ss_read = raw_up_thres_read.split()[4] + high_threshold = float(int(ss_read, 16)) + return high_threshold + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return DEFUALT_LOWER_TRESHOLD + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if not + """ + status, ret_txt = self._api_helper.ipmi_set_ss_thres(self.sensor_id, HIGH_TRESHOLD_SET_KEY, temperature) + return status + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if not + """ + return False + + def get_name(self): + """ + Retrieves the name of the thermal device + Returns: + string: The name of the thermal device + """ + return self.THERMAL_LIST[self.index][0] + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return True if self.get_temperature() > 0 else False + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self.sensor_des + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return "Unknown" + + 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() diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/buffers.json.j2 b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/pg_profile_lookup.ini b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/port_config.ini b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/port_config.ini new file mode 100644 index 000000000000..27d43a0abd0d --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/port_config.ini @@ -0,0 +1,27 @@ +# name lanes alias speed +Ethernet1 0 eth-0-1 10000 +Ethernet2 1 eth-0-2 10000 +Ethernet3 2 eth-0-3 10000 +Ethernet4 3 eth-0-4 10000 +Ethernet5 8 eth-0-5 10000 +Ethernet6 9 eth-0-6 10000 +Ethernet7 10 eth-0-7 10000 +Ethernet8 11 eth-0-8 10000 +Ethernet9 20 eth-0-9 10000 +Ethernet10 21 eth-0-10 10000 +Ethernet11 22 eth-0-11 10000 +Ethernet12 23 eth-0-12 10000 +Ethernet13 12 eth-0-13 10000 +Ethernet14 13 eth-0-14 10000 +Ethernet15 14 eth-0-15 10000 +Ethernet16 15 eth-0-16 10000 +Ethernet17 24 eth-0-17 10000 +Ethernet18 25 eth-0-18 10000 +Ethernet19 26 eth-0-19 10000 +Ethernet20 27 eth-0-20 10000 +Ethernet21 28 eth-0-21 10000 +Ethernet22 29 eth-0-22 10000 +Ethernet23 30 eth-0-23 10000 +Ethernet24 31 eth-0-24 10000 +Ethernet25 61,60,63,62 eth-0-25 100000 +Ethernet26 45,44,47,46 eth-0-26 100000 diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/qos.json.j2 b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/sai.profile b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/sai.profile new file mode 100644 index 000000000000..09efce07c613 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/E530-24x2c-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E530-24x2c-datapath-cfg.txt diff --git a/device/centec/arm64-centec_e530_24x2c-r0/default_sku b/device/centec/arm64-centec_e530_24x2c-r0/default_sku new file mode 100644 index 000000000000..c714e6c18dbb --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/default_sku @@ -0,0 +1 @@ +E530-24x2c l2 diff --git a/device/centec/arm64-centec_e530_24x2c-r0/fancontrol b/device/centec/arm64-centec_e530_24x2c-r0/fancontrol new file mode 100644 index 000000000000..e3775297128e --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/fancontrol @@ -0,0 +1 @@ +# Configuration file generated by pwmconfig, changes will be lost diff --git a/device/centec/arm64-centec_e530_24x2c-r0/installer.conf b/device/centec/arm64-centec_e530_24x2c-r0/installer.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/eeprom.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/eeprom.py new file mode 100644 index 000000000000..afea818be079 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Centec E550-24X8Y2C +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/dev/mtd3" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/led_control.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/led_control.py new file mode 100644 index 000000000000..627cf03ddad4 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/led_control.py @@ -0,0 +1,96 @@ +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import syslog + from socket import * + from select import * +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[0] if (port_idx < 25) else self.LED_MODE_UP[1] + else: + return self.LED_MODE_DOWN[0] if (port_idx < 25) else self.LED_MODE_DOWN[1] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + + def _initSystemLed(self): + try: + with open(self.f_led.format("system"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init system led to normal") + with open(self.f_led.format("idn"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for idx in range(1, 27): + defmode = self._port_state_to_mode(idx, "down") + with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + # Concrete implementation of port_link_state_change() method + + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) + + # Constructor + + def __init__(self): + self.SONIC_PORT_NAME_PREFIX = "Ethernet" + self.LED_MODE_UP = [11, 11] + self.LED_MODE_DOWN = [7, 7] + + self.f_led = "/sys/class/leds/{}/brightness" + self._initDefaultConfig() diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/psuutil.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/psuutil.py new file mode 100644 index 000000000000..3a83f406d990 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/psuutil.py @@ -0,0 +1,71 @@ +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/class/psu/psu{}/" + self.psu_presence = "psu_presence" + self.psu_oper_status = "psu_status" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/sfputil.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/sfputil.py new file mode 100644 index 000000000000..c5c0dc8e16e0 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/sfputil.py @@ -0,0 +1,163 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from socket import * + from select import * + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +def DBG_PRINT(str): + print(str + "\n") + + +SFP_STATUS_INSERTED = '1' +SFP_STATUS_REMOVED = '0' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def sfp_base(self): + return self.SFP_BASE + + @property + def qsfp_ports(self): + return list(range(25, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self.eeprom_mapping + + def is_logical_port(self, port_name): + return True + + def get_eeprom_data(self, port): + ret = None + port_num = self.get_logical_to_physical(port)[0] + if port_num < self.port_start or port_num > self.port_end: + return ret + if port_num < self.sfp_base: + return ret + try: + with open(self.eeprom_mapping[port_num], 'r') as eeprom_file: + ret = eeprom_file.read() + except IOError as e: + DBG_PRINT(str(e)) + + return ret + + # todo + # def _get_port_eeprom_path(self, port_num, devid): + # pass + + def __init__(self): + self.SONIC_PORT_NAME_PREFIX = "Ethernet" + self.PORT_START = 1 + self.PORT_END = 26 + self.SFP_BASE = 1 + self.PORTS_IN_BLOCK = 26 + self.logical = [] + self.physical_to_logical = {} + self.logical_to_physical = {} + + self.eeprom_mapping = {} + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + for x in range(self.port_start, self.sfp_base): + self.eeprom_mapping[x] = None + for x in range(self.sfp_base, self.port_end + 1): + self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format( + x - self.sfp_base + 1) + self.presence = {} + for x in range(self.sfp_base, self.port_end + 1): + self.presence[x] = False + + SfpUtilBase.__init__(self) + + for x in range(self.sfp_base, self.port_end + 1): + self.logical.append('Ethernet' + str(x)) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.sfp_base: + return False + try: + with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def read_porttab_mappings(self, porttabfile): + for x in range(self.sfp_base, self.port_end + 1): + self.logical_to_physical['Ethernet' + str(x)] = [x] + self.physical_to_logical[x] = ['Ethernet' + str(x)] + + data = {'valid': 0, 'last': 0} + + def get_transceiver_change_event(self, timeout=2000): + now = time.time() + port_dict = {} + + if timeout < 1000: + timeout = 1000 + timeout = (timeout) / float(1000) # Convert to secs + + if now < (self.data['last'] + timeout) and self.data['valid']: + return True, {} + + for x in range(self.sfp_base, self.port_end + 1): + presence = self.get_presence(x) + if presence != self.presence[x]: + self.presence[x] = presence + if presence: + port_dict[x] = SFP_STATUS_INSERTED + else: + port_dict[x] = SFP_STATUS_REMOVED + + if bool(port_dict): + self.data['last'] = now + self.data['valid'] = 1 + return True, port_dict + else: + time.sleep(0.5) + return True, {} diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/buffers.json.j2 b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/pg_profile_lookup.ini b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/port_config.ini b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/port_config.ini new file mode 100644 index 000000000000..c904ece72ea0 --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/port_config.ini @@ -0,0 +1,53 @@ +# name lanes alias speed +Ethernet1 1 eth-0-1 1000 +Ethernet2 0 eth-0-2 1000 +Ethernet3 3 eth-0-3 1000 +Ethernet4 2 eth-0-4 1000 +Ethernet5 5 eth-0-5 1000 +Ethernet6 4 eth-0-6 1000 +Ethernet7 7 eth-0-7 1000 +Ethernet8 6 eth-0-8 1000 +Ethernet9 17 eth-0-9 1000 +Ethernet10 16 eth-0-10 1000 +Ethernet11 19 eth-0-11 1000 +Ethernet12 18 eth-0-12 1000 +Ethernet13 21 eth-0-13 1000 +Ethernet14 20 eth-0-14 1000 +Ethernet15 23 eth-0-15 1000 +Ethernet16 22 eth-0-16 1000 +Ethernet17 9 eth-0-17 1000 +Ethernet18 8 eth-0-18 1000 +Ethernet19 11 eth-0-19 1000 +Ethernet20 10 eth-0-20 1000 +Ethernet21 33 eth-0-21 1000 +Ethernet22 32 eth-0-22 1000 +Ethernet23 35 eth-0-23 1000 +Ethernet24 34 eth-0-24 1000 +Ethernet25 37 eth-0-25 1000 +Ethernet26 36 eth-0-26 1000 +Ethernet27 39 eth-0-27 1000 +Ethernet28 38 eth-0-28 1000 +Ethernet29 41 eth-0-29 1000 +Ethernet30 40 eth-0-30 1000 +Ethernet31 43 eth-0-31 1000 +Ethernet32 42 eth-0-32 1000 +Ethernet33 25 eth-0-33 1000 +Ethernet34 24 eth-0-34 1000 +Ethernet35 27 eth-0-35 1000 +Ethernet36 26 eth-0-36 1000 +Ethernet37 49 eth-0-37 1000 +Ethernet38 48 eth-0-38 1000 +Ethernet39 51 eth-0-39 1000 +Ethernet40 50 eth-0-40 1000 +Ethernet41 53 eth-0-41 1000 +Ethernet42 52 eth-0-42 1000 +Ethernet43 55 eth-0-43 1000 +Ethernet44 54 eth-0-44 1000 +Ethernet45 57 eth-0-45 1000 +Ethernet46 56 eth-0-46 1000 +Ethernet47 59 eth-0-47 1000 +Ethernet48 58 eth-0-48 1000 +Ethernet49 13 eth-0-49 10000 +Ethernet50 12 eth-0-50 10000 +Ethernet51 15 eth-0-51 10000 +Ethernet52 14 eth-0-52 10000 diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/qos.json.j2 b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/sai.profile b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/sai.profile new file mode 100644 index 000000000000..e026761f7b8a --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/E530-48t4x-p-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E530-48t4x-p-datapath.txt diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/default_sku b/device/centec/arm64-centec_e530_48t4x_p-r0/default_sku new file mode 100644 index 000000000000..03b04aaf1b0d --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/default_sku @@ -0,0 +1 @@ +E530-48t4x-p l2 diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/fancontrol b/device/centec/arm64-centec_e530_48t4x_p-r0/fancontrol new file mode 100644 index 000000000000..e3775297128e --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/fancontrol @@ -0,0 +1 @@ +# Configuration file generated by pwmconfig, changes will be lost diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/installer.conf b/device/centec/arm64-centec_e530_48t4x_p-r0/installer.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/eeprom.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/eeprom.py new file mode 100644 index 000000000000..afea818be079 --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Centec E550-24X8Y2C +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/dev/mtd3" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/led_control.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/led_control.py new file mode 100644 index 000000000000..eb567de89c22 --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/led_control.py @@ -0,0 +1,95 @@ +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import syslog + from socket import * + from select import * +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[0] if (port_idx < 49) else self.LED_MODE_UP[1] + else: + return self.LED_MODE_DOWN[0] if (port_idx < 49) else self.LED_MODE_DOWN[1] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + + def _initSystemLed(self): + try: + with open(self.f_led.format("system"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init system led to normal") + with open(self.f_led.format("idn"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for idx in range(1, 53): + defmode = self._port_state_to_mode(idx, "down") + with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + # Concrete implementation of port_link_state_change() method + + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) + + # Constructor + + def __init__(self): + self.SONIC_PORT_NAME_PREFIX = "Ethernet" + self.LED_MODE_UP = [2, 11] + self.LED_MODE_DOWN = [1, 7] + + self.f_led = "/sys/class/leds/{}/brightness" + self._initDefaultConfig() diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/psuutil.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/psuutil.py new file mode 100644 index 000000000000..3a83f406d990 --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/psuutil.py @@ -0,0 +1,71 @@ +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/class/psu/psu{}/" + self.psu_presence = "psu_presence" + self.psu_oper_status = "psu_status" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py new file mode 100644 index 000000000000..f7094828eafb --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py @@ -0,0 +1,137 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from socket import * + from select import * + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +def DBG_PRINT(str): + print(str + "\n") + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def sfp_base(self): + return self.SFP_BASE + + @property + def qsfp_ports(self): + return () + + @property + def port_to_eeprom_mapping(self): + return self.eeprom_mapping + + def is_logical_port(self, port_name): + return True + + def get_logical_to_physical(self, port_name): + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return None + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + return [port_idx] + + def get_eeprom_data(self, port): + ret = None + port_num = self.get_logical_to_physical(port)[0] + if port_num < self.port_start or port_num > self.port_end: + return ret + if port_num < self.sfp_base: + return ret + try: + with open(self.eeprom_mapping[port_num], 'r') as eeprom_file: + ret = eeprom_file.read() + except IOError as e: + DBG_PRINT(str(e)) + + return ret + + # todo + # def _get_port_eeprom_path(self, port_num, devid): + # pass + + def __init__(self): + self.SONIC_PORT_NAME_PREFIX = "Ethernet" + self.PORT_START = 1 + self.PORT_END = 52 + self.SFP_BASE = 49 + self.PORTS_IN_BLOCK = 52 + + self.eeprom_mapping = {} + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + for x in range(self.port_start, self.sfp_base): + self.eeprom_mapping[x] = None + for x in range(self.sfp_base, self.port_end + 1): + self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format( + x - self.sfp_base + 1) + self.presence = {} + for x in range(self.sfp_base, self.port_end + 1): + self.presence[x] = False + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.sfp_base: + return False + try: + with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + while True: + for x in range(self.sfp_base, self.port_end + 1): + presence = self.get_presence(x) + if presence != self.presence[x]: + self.presence[x] = presence + port_dict[x] = presence + return True, port_dict + time.sleep(0.5) diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/buffers.json.j2 b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/pg_profile_lookup.ini b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/port_config.ini b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/port_config.ini new file mode 100644 index 000000000000..5b35cd7f5111 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias speed +Ethernet1 91 eth-0-1 10000 +Ethernet2 89 eth-0-2 10000 +Ethernet3 88 eth-0-3 10000 +Ethernet4 86 eth-0-4 10000 +Ethernet5 85 eth-0-5 10000 +Ethernet6 83 eth-0-6 10000 +Ethernet7 82 eth-0-7 10000 +Ethernet8 80 eth-0-8 10000 +Ethernet9 79 eth-0-9 10000 +Ethernet10 77 eth-0-10 10000 +Ethernet11 76 eth-0-11 10000 +Ethernet12 74 eth-0-12 10000 +Ethernet13 73 eth-0-13 10000 +Ethernet14 72 eth-0-14 10000 +Ethernet15 71 eth-0-15 10000 +Ethernet16 69 eth-0-16 10000 +Ethernet17 68 eth-0-17 10000 +Ethernet18 66 eth-0-18 10000 +Ethernet19 65 eth-0-19 10000 +Ethernet20 64 eth-0-20 10000 +Ethernet21 0 eth-0-21 10000 +Ethernet22 1 eth-0-22 10000 +Ethernet23 3 eth-0-23 10000 +Ethernet24 2 eth-0-24 10000 +Ethernet25 4 eth-0-25 10000 +Ethernet26 5 eth-0-26 10000 +Ethernet27 6 eth-0-27 10000 +Ethernet28 7 eth-0-28 10000 +Ethernet29 8 eth-0-29 10000 +Ethernet30 9 eth-0-30 10000 +Ethernet31 10 eth-0-31 10000 +Ethernet32 12 eth-0-32 10000 +Ethernet33 13 eth-0-33 10000 +Ethernet34 15 eth-0-34 10000 +Ethernet35 16 eth-0-35 10000 +Ethernet36 18 eth-0-36 10000 +Ethernet37 19 eth-0-37 10000 +Ethernet38 21 eth-0-38 10000 +Ethernet39 22 eth-0-39 10000 +Ethernet40 24 eth-0-40 10000 +Ethernet41 25 eth-0-41 10000 +Ethernet42 27 eth-0-42 10000 +Ethernet43 28 eth-0-43 10000 +Ethernet44 30 eth-0-44 10000 +Ethernet45 31 eth-0-45 10000 +Ethernet46 33 eth-0-46 10000 +Ethernet47 34 eth-0-47 10000 +Ethernet48 48 eth-0-48 10000 +Ethernet49 38,37,39,36 eth-0-49 100000 +Ethernet50 53,54,52,55 eth-0-50 100000 +Ethernet51 118,117,119,116 eth-0-51 100000 +Ethernet52 101,102,100,103 eth-0-52 100000 +Ethernet53 113,114,112,115 eth-0-53 40000 +Ethernet54 97,98,96,99 eth-0-54 40000 diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/qos.json.j2 b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/sai.profile b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/sai.profile new file mode 100644 index 000000000000..6139a61cf0cd --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/E582-48x2q4z/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/E582-48x2q4z-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E582-48x2q4z-datapath-cfg.txt diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/default_sku b/device/centec/x86_64-centec_e582_48x2q4z-r0/default_sku new file mode 100644 index 000000000000..332f7a2b4764 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/default_sku @@ -0,0 +1 @@ +E582-48x2q4z l2 diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/fancontrol b/device/centec/x86_64-centec_e582_48x2q4z-r0/fancontrol new file mode 100644 index 000000000000..5bcd0383896b --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/platform/coretemp.0 hwmon5=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-15/15-002f +DEVNAME=hwmon1=coretemp hwmon5=adt7470 +FCTEMPS=hwmon5/pwm4=hwmon1/temp1_input hwmon5/pwm3=hwmon1/temp1_input hwmon5/pwm2=hwmon1/temp1_input hwmon5/pwm1=hwmon1/temp1_input +FCFANS=hwmon5/pwm4=hwmon5/fan4_input hwmon5/pwm3=hwmon5/fan3_input hwmon5/pwm2=hwmon5/fan2_input hwmon5/pwm1=hwmon5/fan1_input +MINTEMP=hwmon5/pwm4=20 hwmon5/pwm3=20 hwmon5/pwm2=20 hwmon5/pwm1=20 +MAXTEMP=hwmon5/pwm4=60 hwmon5/pwm3=60 hwmon5/pwm2=60 hwmon5/pwm1=60 +MINSTART=hwmon5/pwm4=150 hwmon5/pwm3=150 hwmon5/pwm2=150 hwmon5/pwm1=150 +MINSTOP=hwmon5/pwm4=0 hwmon5/pwm3=0 hwmon5/pwm2=0 hwmon5/pwm1=100 diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/installer.conf b/device/centec/x86_64-centec_e582_48x2q4z-r0/installer.conf new file mode 100644 index 000000000000..7d60bf73d366 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=no" diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/eeprom.py b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/eeprom.py new file mode 100644 index 000000000000..63854d994cf1 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/eeprom.py @@ -0,0 +1,28 @@ +############################################################################# +# Centec E582-48X6Q +# +# 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 binascii + import time + import optparse + import warnings + import os + import sys + import subprocess + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/led_control.py b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/led_control.py new file mode 100644 index 000000000000..48a4d8d04eae --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/led_control.py @@ -0,0 +1,159 @@ +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import swsssdk + import threading + import os + import logging + import struct + import time + import syslog + from socket import * + from select import * +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + SONIC_PORT_NAME_PREFIX = "Ethernet" + LED_MODE_UP = [11, 1] + LED_MODE_DOWN = [7, 2] + + def _initSystemLed(self): + try: + with open(self.f_led.format("system"), 'w') as led_file: + led_file.write("5") + DBG_PRINT("init system led to normal") + with open(self.f_led.format("idn"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for (port, ctlid, defmode) in self.led_mapping[1:59]: + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, defmode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + + data = struct.pack('=HHHBB30B', 0, 3, 32, 30, 0, *[x[0] for x in self.led_mapping[21:51]]) + self.udpClient.sendto(data, ('localhost', 8101)) + data = struct.pack('=HHHBB28B', 0, 3, 30, 28, 1, *[x[0] + for x in (self.led_mapping[1:21]+self.led_mapping[51:59])]) + self.udpClient.sendto(data, ('localhost', 8101)) + + data = struct.pack('=HHHB', 0, 5, 1, 1) + self.udpClient.sendto(data, ('localhost', 8101)) + + for idx in range(1, 55): + (port, ctlid, defmode) = self.led_mapping[idx] + with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + for idx in range(1, 55): + (port, ctlid, defmode) = self.led_mapping[idx] + with open(self.f_led.format("port{}".format(idx)), 'r') as led_file: + defmode = int(led_file.read()) + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, defmode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + while True: + try: + r_sel = [self.udpClient] + echo_req = struct.pack('=HHH', 0, 1, 0) + self.udpClient.sendto(echo_req, ('localhost', 8101)) + result = select(r_sel, [], [], 1) + if self.udpClient in result[0]: + echo_rsp, srv_addr = self.udpClient.recvfrom(1024) + if echo_rsp: + break + DBG_PRINT("connect to sdk rpc server timeout, try again.") + except IOError as e: + DBG_PRINT(str(e)) + + DBG_PRINT("connect to sdk rpc server success.") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + # Helper method to map SONiC port name to index + + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[0] if (port_idx < 49) else self.LED_MODE_UP[1] + else: + return self.LED_MODE_DOWN[0] if (port_idx < 49) else self.LED_MODE_DOWN[1] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + (port, ctlid) = (self.led_mapping[port_idx][0], self.led_mapping[port_idx][1]) + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, ledMode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + + # Concrete implementation of port_link_state_change() method + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) + + # Constructor + def __init__(self): + # [macid, ctlid, defaultmode] + self.led_mapping = [(0, 0, 0)] # resv + self.led_mapping.extend([(27, 1, 7), (25, 1, 7), (24, 1, 7), (22, 1, 7), (21, 1, 7), + (19, 1, 7), (18, 1, 7), (16, 1, 7)]) # panel port 1~8 + self.led_mapping.extend([(15, 1, 7), (13, 1, 7), (12, 1, 7), (10, 1, 7), (9, 1, 7), + (8, 1, 7), (7, 1, 7), (5, 1, 7)]) # panel port 9~16 + self.led_mapping.extend([(4, 1, 7), (2, 1, 7), (1, 1, 7), (0, 1, 7), (0, 0, 7), + (1, 0, 7), (3, 0, 7), (2, 0, 7)]) # panel port 17~24 + self.led_mapping.extend([(4, 0, 7), (5, 0, 7), (6, 0, 7), (7, 0, 7), (8, 0, 7), + (9, 0, 7), (10, 0, 7), (12, 0, 7)]) # panel port 25~32 + self.led_mapping.extend([(13, 0, 7), (15, 0, 7), (16, 0, 7), (18, 0, 7), (19, 0, 7), + (21, 0, 7), (22, 0, 7), (24, 0, 7)]) # panel port 33~40 + self.led_mapping.extend([(25, 0, 7), (27, 0, 7), (28, 0, 7), (30, 0, 7), (31, 0, 7), + (33, 0, 7), (34, 0, 7), (48, 0, 7)]) # panel port 41~48 + self.led_mapping.extend([(36, 0, 2), (52, 0, 2), (52, 1, 2), (36, 1, 2), (48, 1, 2), + (32, 1, 2)]) # panel port 49~54 + self.led_mapping.extend([(11, 1, 2), (11, 1, 2), (11, 1, 2), (11, 1, 2), (11, 1, 2), (11, 1, 2)]) + + self.f_led = "/sys/class/leds/{}/brightness" + + self.udpClient = socket(AF_INET, SOCK_DGRAM) + + self._initDefaultConfig() diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/psuutil.py b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/psuutil.py new file mode 100644 index 000000000000..f38f0cdd0a2e --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/psuutil.py @@ -0,0 +1,73 @@ +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/class/psu/psu{}/" + self.psu_presence = "psu_presence" + self.psu_oper_status = "psu_status" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 0 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 0 diff --git a/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/sfputil.py b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/sfputil.py new file mode 100644 index 000000000000..4e94646db772 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x2q4z-r0/plugins/sfputil.py @@ -0,0 +1,166 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import logging + import struct + import syslog + from socket import * + from select import * + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +def DBG_PRINT(str): + print(str + "\n") + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + SONIC_PORT_NAME_PREFIX = "Ethernet" + PORT_START = 1 + PORT_END = 54 + PORTS_IN_BLOCK = 54 + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(49, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self.eeprom_mapping + + def is_logical_port(self, port_name): + return True + + def get_logical_to_physical(self, port_name): + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return None + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + return [port_idx] + + def get_eeprom_data(self, port): + (ctlid, devid) = self.fiber_mapping[port] + offset = (128 if port in self.qsfp_ports else 0) + r_sel = [self.udpClient] + req = struct.pack('=HHHBBHIBBBBI', + 0, 9, 16, # lchip/msgtype/msglen + ctlid, # uint8 ctl_id + devid, # uint8 slave_dev_id + 0x50, # uint16 dev_addr + (1 << devid), # uint32 slave_bitmap + offset, # uint8 offset + 95, # uint8 length + 0xf, # uint8 i2c_switch_id + 0, # uint8 access_switch + 95 # uint32 buf_length + ) + self.udpClient.sendto(req, ('localhost', 8101)) + result = select(r_sel, [], [], 1) + if self.udpClient in result[0]: + rsp, addr = self.udpClient.recvfrom(1024) + if rsp: + rsp_data = struct.unpack('=HHHBBHIBBBBIi512B', rsp) + if rsp_data[12] != 0: + return None + if port in self.qsfp_ports: + return buffer(bytearray([0]*128), 0, 128) + buffer(rsp, 26, 512) + return buffer(rsp, 26, 512) + return None + + def __init__(self): + """[ctlid, slavedevid]""" + self.fiber_mapping = [(0, 0)] # res + self.fiber_mapping.extend([(1, 7), (1, 6), (1, 5), (1, 4), (1, 3), + (1, 2), (1, 1), (1, 0)]) # panel port 1~8 + self.fiber_mapping.extend([(1, 15), (1, 14), (1, 13), (1, 12), (1, 11), + (1, 10), (1, 9), (1, 8)]) # panel port 9~16 + self.fiber_mapping.extend([(1, 19), (1, 17), (1, 16), (1, 18), (0, 7), + (0, 6), (0, 5), (0, 4)]) # panel port 17~24 + self.fiber_mapping.extend([(0, 3), (0, 2), (0, 1), (0, 0), (0, 15), + (0, 14), (0, 13), (0, 12)]) # panel port 25~32 + self.fiber_mapping.extend([(0, 11), (0, 10), (0, 9), (0, 8), (0, 23), + (0, 22), (0, 21), (0, 20)]) # panel port 33~40 + self.fiber_mapping.extend([(0, 19), (0, 18), (0, 17), (0, 16), (0, 31), + (0, 26), (0, 29), (0, 27)]) # panel port 41~48 + self.fiber_mapping.extend([(0, 24), (0, 25), (1, 23), (1, 22), (1, 21), (1, 20)] + ) # panel port 49~54 + + self.udpClient = socket(AF_INET, SOCK_DGRAM) + self.eeprom_mapping = {} + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + + for x in range(1, self.port_end + 1): + self.eeprom_mapping[x] = "/var/cache/sonic/sfp/sfp{}_eeprom".format(x) + + try: + if not os.path.exists("/var/cache/sonic/sfp"): + os.makedirs("/var/cache/sonic/sfp", 0o777) + for x in range(1, self.port_end + 1): + if not self.get_presence(x): + if os.path.exists(self.eeprom_mapping[x]): + os.remove(self.eeprom_mapping[x]) + continue + data = self.get_eeprom_data(x) + if data: + with open(self.eeprom_mapping[x], 'w') as sfp_eeprom: + sfp_eeprom.write(data) + else: + DBG_PRINT("get sfp{} eeprom data failed.".format(x)) + break + except IOError as e: + DBG_PRINT(str(e)) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + try: + with open(self.f_sfp_present.format(port_num), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def get_transceiver_change_event(self, timeout=0): + return False, {} diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/buffers.json.j2 b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/pg_profile_lookup.ini b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/port_config.ini b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/port_config.ini new file mode 100644 index 000000000000..5e370ab2f1a3 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias speed +Ethernet1 4 eth-0-1 10000 +Ethernet2 5 eth-0-2 10000 +Ethernet3 6 eth-0-3 10000 +Ethernet4 8 eth-0-4 10000 +Ethernet5 9 eth-0-5 10000 +Ethernet6 10 eth-0-6 10000 +Ethernet7 12 eth-0-7 10000 +Ethernet8 13 eth-0-8 10000 +Ethernet9 14 eth-0-9 10000 +Ethernet10 16 eth-0-10 10000 +Ethernet11 17 eth-0-11 10000 +Ethernet12 18 eth-0-12 10000 +Ethernet13 20 eth-0-13 10000 +Ethernet14 21 eth-0-14 10000 +Ethernet15 22 eth-0-15 10000 +Ethernet16 24 eth-0-16 10000 +Ethernet17 25 eth-0-17 10000 +Ethernet18 26 eth-0-18 10000 +Ethernet19 28 eth-0-19 10000 +Ethernet20 30 eth-0-20 10000 +Ethernet21 31 eth-0-21 10000 +Ethernet22 32 eth-0-22 10000 +Ethernet23 34 eth-0-23 10000 +Ethernet24 35 eth-0-24 10000 +Ethernet25 48 eth-0-25 10000 +Ethernet26 49 eth-0-26 10000 +Ethernet27 51 eth-0-27 10000 +Ethernet28 36 eth-0-28 10000 +Ethernet29 37 eth-0-29 10000 +Ethernet30 39 eth-0-30 10000 +Ethernet31 55 eth-0-31 10000 +Ethernet32 54 eth-0-32 10000 +Ethernet33 53 eth-0-33 10000 +Ethernet34 52 eth-0-34 10000 +Ethernet35 116 eth-0-35 10000 +Ethernet36 117 eth-0-36 10000 +Ethernet37 118 eth-0-37 10000 +Ethernet38 119 eth-0-38 10000 +Ethernet39 102 eth-0-39 10000 +Ethernet40 101 eth-0-40 10000 +Ethernet41 100 eth-0-41 10000 +Ethernet42 115 eth-0-42 10000 +Ethernet43 114 eth-0-43 10000 +Ethernet44 113 eth-0-44 10000 +Ethernet45 112 eth-0-45 10000 +Ethernet46 98 eth-0-46 10000 +Ethernet47 97 eth-0-47 10000 +Ethernet48 96 eth-0-48 10000 +Ethernet49 93,94,92,95 eth-0-49 40000 +Ethernet50 89,90,88,91 eth-0-50 40000 +Ethernet51 86,87,85,84 eth-0-51 40000 +Ethernet52 77,79,76,78 eth-0-52 40000 +Ethernet53 75,73,74,72 eth-0-53 40000 +Ethernet54 69,71,70,68 eth-0-54 40000 diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/qos.json.j2 b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/sai.profile b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/sai.profile new file mode 100644 index 000000000000..c03fcf630c5a --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/E582-48x6q/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/E582-48x6q-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E582-48x6q-datapath-cfg.txt diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/default_sku b/device/centec/x86_64-centec_e582_48x6q-r0/default_sku new file mode 100644 index 000000000000..bad98ce86f83 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/default_sku @@ -0,0 +1 @@ +E582-48x6q l2 diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/fancontrol b/device/centec/x86_64-centec_e582_48x6q-r0/fancontrol new file mode 100644 index 000000000000..5bcd0383896b --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/platform/coretemp.0 hwmon5=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-15/15-002f +DEVNAME=hwmon1=coretemp hwmon5=adt7470 +FCTEMPS=hwmon5/pwm4=hwmon1/temp1_input hwmon5/pwm3=hwmon1/temp1_input hwmon5/pwm2=hwmon1/temp1_input hwmon5/pwm1=hwmon1/temp1_input +FCFANS=hwmon5/pwm4=hwmon5/fan4_input hwmon5/pwm3=hwmon5/fan3_input hwmon5/pwm2=hwmon5/fan2_input hwmon5/pwm1=hwmon5/fan1_input +MINTEMP=hwmon5/pwm4=20 hwmon5/pwm3=20 hwmon5/pwm2=20 hwmon5/pwm1=20 +MAXTEMP=hwmon5/pwm4=60 hwmon5/pwm3=60 hwmon5/pwm2=60 hwmon5/pwm1=60 +MINSTART=hwmon5/pwm4=150 hwmon5/pwm3=150 hwmon5/pwm2=150 hwmon5/pwm1=150 +MINSTOP=hwmon5/pwm4=0 hwmon5/pwm3=0 hwmon5/pwm2=0 hwmon5/pwm1=100 diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/installer.conf b/device/centec/x86_64-centec_e582_48x6q-r0/installer.conf new file mode 100644 index 000000000000..7d60bf73d366 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=no" diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/plugins/eeprom.py b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/eeprom.py new file mode 100644 index 000000000000..63854d994cf1 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/eeprom.py @@ -0,0 +1,28 @@ +############################################################################# +# Centec E582-48X6Q +# +# 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 binascii + import time + import optparse + import warnings + import os + import sys + import subprocess + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/plugins/led_control.py b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/led_control.py new file mode 100644 index 000000000000..eb9e9143a9bf --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/led_control.py @@ -0,0 +1,158 @@ +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import swsssdk + import threading + import os + import logging + import struct + import time + import syslog + from socket import * + from select import * +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + SONIC_PORT_NAME_PREFIX = "Ethernet" + LED_MODE_UP = [11, 1] + LED_MODE_DOWN = [7, 2] + + def _initSystemLed(self): + try: + with open(self.f_led.format("system"), 'w') as led_file: + led_file.write("5") + DBG_PRINT("init system led to normal") + with open(self.f_led.format("idn"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for (port, ctlid, defmode) in self.led_mapping[1:59]: + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, defmode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + + data = struct.pack('=HHHBB34B', 0, 3, 36, 34, 0, *[x[0] for x in self.led_mapping[1:35]]) + self.udpClient.sendto(data, ('localhost', 8101)) + data = struct.pack('=HHHBB24B', 0, 3, 26, 24, 1, *[x[0] for x in self.led_mapping[35:59]]) + self.udpClient.sendto(data, ('localhost', 8101)) + + data = struct.pack('=HHHB', 0, 5, 1, 1) + self.udpClient.sendto(data, ('localhost', 8101)) + + for idx in range(1, 55): + (port, ctlid, defmode) = self.led_mapping[idx] + with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + for idx in range(1, 55): + (port, ctlid, defmode) = self.led_mapping[idx] + with open(self.f_led.format("port{}".format(idx)), 'r') as led_file: + defmode = int(led_file.read()) + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, defmode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + while True: + try: + r_sel = [self.udpClient] + echo_req = struct.pack('=HHH', 0, 1, 0) + self.udpClient.sendto(echo_req, ('localhost', 8101)) + result = select(r_sel, [], [], 1) + if self.udpClient in result[0]: + echo_rsp, srv_addr = self.udpClient.recvfrom(1024) + if echo_rsp: + break + DBG_PRINT("connect to sdk rpc server timeout, try again.") + except IOError as e: + DBG_PRINT(str(e)) + + DBG_PRINT("connect to sdk rpc server success.") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + # Helper method to map SONiC port name to index + + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[0] if (port_idx < 49) else self.LED_MODE_UP[1] + else: + return self.LED_MODE_DOWN[0] if (port_idx < 49) else self.LED_MODE_DOWN[1] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + (port, ctlid) = (self.led_mapping[port_idx][0], self.led_mapping[port_idx][1]) + data = struct.pack('=HHHBBH', 0, 7, 4, ctlid, ledMode, port) + self.udpClient.sendto(data, ('localhost', 8101)) + + # Concrete implementation of port_link_state_change() method + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) + + # Constructor + def __init__(self): + # [macid, ctlid, defaultmode] + self.led_mapping = [(0, 0, 0)] # resv + self.led_mapping.extend([(4, 0, 7), (5, 0, 7), (6, 0, 7), (8, 0, 7), (9, 0, 7), + (10, 0, 7), (12, 0, 7), (13, 0, 7)]) # panel port 1~8 + self.led_mapping.extend([(14, 0, 7), (16, 0, 7), (17, 0, 7), (18, 0, 7), (20, 0, 7), + (21, 0, 7), (22, 0, 7), (24, 0, 7)]) # panel port 9~16 + self.led_mapping.extend([(25, 0, 7), (26, 0, 7), (28, 0, 7), (30, 0, 7), (31, 0, 7), + (32, 0, 7), (34, 0, 7), (35, 0, 7)]) # panel port 17~24 + self.led_mapping.extend([(48, 0, 7), (49, 0, 7), (51, 0, 7), (36, 0, 7), (37, 0, 7), + (39, 0, 7), (55, 0, 7), (54, 0, 7)]) # panel port 25~32 + self.led_mapping.extend([(53, 0, 7), (52, 0, 7), (52, 1, 7), (53, 1, 7), (54, 1, 7), + (55, 1, 7), (38, 1, 7), (37, 1, 7)]) # panel port 33~40 + self.led_mapping.extend([(36, 1, 7), (51, 1, 7), (50, 1, 7), (49, 1, 7), (48, 1, 7), + (34, 1, 7), (33, 1, 7), (32, 1, 7)]) # panel port 41~48 + self.led_mapping.extend([(28, 1, 2), (24, 1, 2), (20, 1, 2), (12, 1, 2), (8, 1, 2), + (4, 1, 2)]) # panel port 49~54 + self.led_mapping.extend([(0, 1, 2), (0, 1, 2), (0, 1, 2), (0, 1, 2), (0, 1, 2), (0, 1, 2)]) + + self.f_led = "/sys/class/leds/{}/brightness" + + self.udpClient = socket(AF_INET, SOCK_DGRAM) + + self._initDefaultConfig() diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/plugins/psuutil.py b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/psuutil.py new file mode 100644 index 000000000000..f38f0cdd0a2e --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/psuutil.py @@ -0,0 +1,73 @@ +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/class/psu/psu{}/" + self.psu_presence = "psu_presence" + self.psu_oper_status = "psu_status" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 0 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 0 diff --git a/device/centec/x86_64-centec_e582_48x6q-r0/plugins/sfputil.py b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/sfputil.py new file mode 100644 index 000000000000..f19501e75106 --- /dev/null +++ b/device/centec/x86_64-centec_e582_48x6q-r0/plugins/sfputil.py @@ -0,0 +1,166 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import logging + import struct + import syslog + from socket import * + from select import * + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +def DBG_PRINT(str): + print(str + "\n") + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + SONIC_PORT_NAME_PREFIX = "Ethernet" + PORT_START = 1 + PORT_END = 54 + PORTS_IN_BLOCK = 54 + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(49, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self.eeprom_mapping + + def is_logical_port(self, port_name): + return True + + def get_logical_to_physical(self, port_name): + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return None + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + return [port_idx] + + def get_eeprom_data(self, port): + (ctlid, devid) = self.fiber_mapping[port] + offset = (128 if port in self.qsfp_ports else 0) + r_sel = [self.udpClient] + req = struct.pack('=HHHBBHIBBBBI', + 0, 9, 16, # lchip/msgtype/msglen + ctlid, # uint8 ctl_id + devid, # uint8 slave_dev_id + 0x50, # uint16 dev_addr + (1 << devid), # uint32 slave_bitmap + offset, # uint8 offset + 95, # uint8 length + 0xf, # uint8 i2c_switch_id + 0, # uint8 access_switch + 95 # uint32 buf_length + ) + self.udpClient.sendto(req, ('localhost', 8101)) + result = select(r_sel, [], [], 1) + if self.udpClient in result[0]: + rsp, addr = self.udpClient.recvfrom(1024) + if rsp: + rsp_data = struct.unpack('=HHHBBHIBBBBIi512B', rsp) + if rsp_data[12] != 0: + return None + if port in self.qsfp_ports: + return buffer(bytearray([0]*128), 0, 128) + buffer(rsp, 26, 512) + return buffer(rsp, 26, 512) + return None + + def __init__(self): + """[ctlid, slavedevid]""" + self.fiber_mapping = [(0, 0)] # res + self.fiber_mapping.extend([(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), + (0, 5), (0, 6), (0, 7)]) # panel port 1~8 + self.fiber_mapping.extend([(0, 14), (0, 13), (0, 15), (0, 12), (0, 8), + (0, 11), (0, 9), (0, 10)]) # panel port 9~16 + self.fiber_mapping.extend([(0, 22), (0, 21), (0, 23), (0, 20), (0, 16), + (0, 19), (0, 17), (0, 18)]) # panel port 17~24 + self.fiber_mapping.extend([(1, 4), (1, 3), (1, 5), (1, 2), (1, 6), + (1, 1), (1, 7), (1, 0)]) # panel port 25~32 + self.fiber_mapping.extend([(1, 8), (1, 15), (1, 9), (1, 14), (1, 10), + (1, 13), (1, 11), (1, 12)]) # panel port 33~40 + self.fiber_mapping.extend([(1, 22), (1, 21), (1, 23), (1, 20), (1, 16), + (1, 19), (1, 17), (1, 18)]) # panel port 41~48 + self.fiber_mapping.extend([(1, 28), (1, 29), (1, 26), (1, 27), (1, 24), (1, 25)] + ) # panel port 49~54 + + self.udpClient = socket(AF_INET, SOCK_DGRAM) + self.eeprom_mapping = {} + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + + for x in range(1, self.port_end + 1): + self.eeprom_mapping[x] = "/var/cache/sonic/sfp/sfp{}_eeprom".format(x) + + try: + if not os.path.exists("/var/cache/sonic/sfp"): + os.makedirs("/var/cache/sonic/sfp", 0o777) + for x in range(1, self.port_end + 1): + if not self.get_presence(x): + if os.path.exists(self.eeprom_mapping[x]): + os.remove(self.eeprom_mapping[x]) + continue + data = self.get_eeprom_data(x) + if data: + with open(self.eeprom_mapping[x], 'w') as sfp_eeprom: + sfp_eeprom.write(data) + else: + DBG_PRINT("get sfp{} eeprom data failed.".format(x)) + break + except IOError as e: + DBG_PRINT(str(e)) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + try: + with open(self.f_sfp_present.format(port_num), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def get_transceiver_change_event(self, timeout=0): + return False, {} diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/buffers.json.j2 b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/pg_profile_lookup.ini b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/port_config.ini b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/port_config.ini new file mode 100644 index 000000000000..5b35cd7f5111 --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias speed +Ethernet1 91 eth-0-1 10000 +Ethernet2 89 eth-0-2 10000 +Ethernet3 88 eth-0-3 10000 +Ethernet4 86 eth-0-4 10000 +Ethernet5 85 eth-0-5 10000 +Ethernet6 83 eth-0-6 10000 +Ethernet7 82 eth-0-7 10000 +Ethernet8 80 eth-0-8 10000 +Ethernet9 79 eth-0-9 10000 +Ethernet10 77 eth-0-10 10000 +Ethernet11 76 eth-0-11 10000 +Ethernet12 74 eth-0-12 10000 +Ethernet13 73 eth-0-13 10000 +Ethernet14 72 eth-0-14 10000 +Ethernet15 71 eth-0-15 10000 +Ethernet16 69 eth-0-16 10000 +Ethernet17 68 eth-0-17 10000 +Ethernet18 66 eth-0-18 10000 +Ethernet19 65 eth-0-19 10000 +Ethernet20 64 eth-0-20 10000 +Ethernet21 0 eth-0-21 10000 +Ethernet22 1 eth-0-22 10000 +Ethernet23 3 eth-0-23 10000 +Ethernet24 2 eth-0-24 10000 +Ethernet25 4 eth-0-25 10000 +Ethernet26 5 eth-0-26 10000 +Ethernet27 6 eth-0-27 10000 +Ethernet28 7 eth-0-28 10000 +Ethernet29 8 eth-0-29 10000 +Ethernet30 9 eth-0-30 10000 +Ethernet31 10 eth-0-31 10000 +Ethernet32 12 eth-0-32 10000 +Ethernet33 13 eth-0-33 10000 +Ethernet34 15 eth-0-34 10000 +Ethernet35 16 eth-0-35 10000 +Ethernet36 18 eth-0-36 10000 +Ethernet37 19 eth-0-37 10000 +Ethernet38 21 eth-0-38 10000 +Ethernet39 22 eth-0-39 10000 +Ethernet40 24 eth-0-40 10000 +Ethernet41 25 eth-0-41 10000 +Ethernet42 27 eth-0-42 10000 +Ethernet43 28 eth-0-43 10000 +Ethernet44 30 eth-0-44 10000 +Ethernet45 31 eth-0-45 10000 +Ethernet46 33 eth-0-46 10000 +Ethernet47 34 eth-0-47 10000 +Ethernet48 48 eth-0-48 10000 +Ethernet49 38,37,39,36 eth-0-49 100000 +Ethernet50 53,54,52,55 eth-0-50 100000 +Ethernet51 118,117,119,116 eth-0-51 100000 +Ethernet52 101,102,100,103 eth-0-52 100000 +Ethernet53 113,114,112,115 eth-0-53 40000 +Ethernet54 97,98,96,99 eth-0-54 40000 diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/qos.json b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/qos.json new file mode 100644 index 000000000000..b9dc80abb07f --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/qos.json @@ -0,0 +1,133 @@ +{ + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"0", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"1", + "10":"1", + "11":"1", + "12":"1", + "13":"1", + "14":"1", + "15":"1", + "16":"2", + "17":"2", + "18":"2", + "19":"2", + "20":"2", + "21":"2", + "22":"2", + "23":"2", + "24":"3", + "25":"3", + "26":"3", + "27":"3", + "28":"3", + "29":"3", + "30":"3", + "31":"3", + "32":"4", + "33":"4", + "34":"4", + "35":"4", + "36":"4", + "37":"4", + "38":"4", + "39":"4", + "40":"5", + "41":"5", + "42":"5", + "43":"5", + "44":"5", + "45":"5", + "46":"5", + "47":"5", + "48":"6", + "49":"6", + "50":"6", + "51":"6", + "52":"6", + "53":"6", + "54":"6", + "55":"6", + "56":"7", + "57":"7", + "58":"7", + "59":"7", + "60":"7", + "61":"7", + "62":"7", + "63":"7" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1": { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2": { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSY": { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "red_max_threshold":"32760", + "red_min_threshold":"4095", + "yellow_max_threshold":"32760", + "yellow_min_threshold":"4095", + "green_max_threshold": "32760", + "green_min_threshold": "4095" + }, + "AZURE_LOSSLESS": { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "red_max_threshold":"32760", + "red_min_threshold":"4095", + "yellow_max_threshold":"32760", + "yellow_min_threshold":"4095", + "green_max_threshold": "32760", + "green_min_threshold": "4095" + } + }, + "QUEUE": { + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|0-2": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|5-7": { + "scheduler" : "[SCHEDULER|scheduler.2]" + }, + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|0-2": { + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSY]" + }, + + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|5-7": { + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSY]" + }, + "Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet49,Ethernet50,Ethernet51,Ethernet52,Ethernet53,Ethernet54|3-4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + } + } +} + + diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/sai.profile b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/sai.profile new file mode 100644 index 000000000000..006512cb0bf9 --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/ES6428A-X48Q2H4/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/ES6428A-X48Q2H4-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/ES6428A-X48Q2H4-datapath-cfg.txt diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/default_sku b/device/centec/x86_64-ew_es6220_x48q2h4-r0/default_sku new file mode 100644 index 000000000000..6f0b38195095 --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/default_sku @@ -0,0 +1 @@ +ES6428A-X48Q2H4 l2 diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/installer.conf b/device/centec/x86_64-ew_es6220_x48q2h4-r0/installer.conf new file mode 100644 index 000000000000..5b03827200c5 --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_SPEED=115200 +CONSOLE_DEV=2 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=no" diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/eeprom.py b/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/eeprom.py new file mode 100644 index 000000000000..c3fce91c8bb6 --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/eeprom.py @@ -0,0 +1,31 @@ +############################################################################# +# EmbedWay +# +# 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 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 as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + #output = os.popen('i2cdetect -l | grep CP') + # a=output.read() + # b=a[4] + self.eeprom_path = "/home/admin/eeprom.bin" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/psuutil.py b/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/psuutil.py new file mode 100644 index 000000000000..d55f7115946c --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/psuutil.py @@ -0,0 +1,55 @@ +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/{}-0058/" + self.psu_oper_status = "in1_input" + self.psu_presence = "i2cget -y {} 0x50 0x00" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + if index is None: + return False + Base_bus_number = 39 + status = 0 + # index from 1, psu attribute bus from 40 + try: + with open(self.psu_path.format(index + Base_bus_number) + self.psu_oper_status, 'r') as power_status: + if int(power_status.read()) == 0: + return False + else: + status = 1 + except IOError: + return True + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + Base_bus_number = 39 + status = 0 + try: + p = os.popen(self.psu_presence.format(index + Base_bus_number) + "> /dev/null 2>&1") + if p.readline() != None: + status = 1 + p.close() + except IOError: + return False + return status == 1 diff --git a/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/sfputil.py b/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/sfputil.py new file mode 100644 index 000000000000..103b3cd5630b --- /dev/null +++ b/device/centec/x86_64-ew_es6220_x48q2h4-r0/plugins/sfputil.py @@ -0,0 +1,188 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + 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 = 0 + PORT_END = 53 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 20 + + _port_to_eeprom_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 list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + self._port_to_eeprom_mapping[x] = eeprom_path.format( + x + self.EEPROM_OFFSET) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_name): + # modify by zhw to get sfp presence + # Check for invalid port_num + port_num = int(port_name[8:]) + + if port_num < (self.port_start+1) or port_num > (self.port_end+1): + return False + + # cpld info from "CPLD Register for es5800A2.2(V1.1)" + cpld_map = {0: '0x82', 1: '0x83', 2: '0x84', + 3: '0x85', 4: '0x86', 5: '0x87', 6: '0x8E'} + cpld_key = (port_num - 1)/8 + cpld_mask = (1 << (port_num - 1) % 8) + + # use i2cget cmd to get cpld data + output = os.popen('i2cdetect -l | grep CP') + bus_num = output.read()[4] + cmd = "i2cget -y "+bus_num+" 0x5 "+cpld_map[cpld_key] + tmp = os.popen(cmd).read().replace("\n", "") + cpld_value = int(tmp, 16) + + if cpld_value & cpld_mask == 0: + return True + else: + return False + + def get_low_power_mode(self, port_num): + ''' + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high + if reg_value & mask == 0: + return False + ''' + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open( + "/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/dell-s6000-cpld.0/qsfp_reset" + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 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_cs5435_54p-r0/Cig-CS5435-54P/port_config.nps b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/port_config.nps new file mode 100644 index 000000000000..e7f4fc78221c --- /dev/null +++ b/device/cig/x86_64-cig_cs5435_54p-r0/Cig-CS5435-54P/port_config.nps @@ -0,0 +1,624 @@ +init start stage unit=0 low-level +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=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 +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=tx data=0x1 +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=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=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 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=rx data=0x1 +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=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=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 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=tx data=0x1 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=tx data=0x0.0.0.0 +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=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 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=rx data=0x0 +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.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=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 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c1 data=0x6.6.6.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=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 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c1 data=0x3 +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=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=129 speed=10g +port set property unit=0 portlist=130 speed=1g +port set property unit=0 portlist=0 medium-type=sr +port set property unit=0 portlist=1 medium-type=sr +port set property unit=0 portlist=2 medium-type=sr +port set property unit=0 portlist=3 medium-type=sr +port set property unit=0 portlist=4 medium-type=sr +port set property unit=0 portlist=5 medium-type=sr +port set property unit=0 portlist=6 medium-type=sr +port set property unit=0 portlist=7 medium-type=sr +port set property unit=0 portlist=8 medium-type=sr +port set property unit=0 portlist=9 medium-type=sr +port set property unit=0 portlist=10 medium-type=sr +port set property unit=0 portlist=11 medium-type=sr +port set property unit=0 portlist=12 medium-type=sr +port set property unit=0 portlist=13 medium-type=sr +port set property unit=0 portlist=14 medium-type=sr +port set property unit=0 portlist=15 medium-type=sr +port set property unit=0 portlist=16 medium-type=sr +port set property unit=0 portlist=17 medium-type=sr +port set property unit=0 portlist=18 medium-type=sr +port set property unit=0 portlist=19 medium-type=sr +port set property unit=0 portlist=20 medium-type=sr +port set property unit=0 portlist=21 medium-type=sr +port set property unit=0 portlist=22 medium-type=sr +port set property unit=0 portlist=23 medium-type=sr +port set property unit=0 portlist=24 medium-type=sr +port set property unit=0 portlist=25 medium-type=sr +port set property unit=0 portlist=26 medium-type=sr +port set property unit=0 portlist=27 medium-type=sr +port set property unit=0 portlist=28 medium-type=sr +port set property unit=0 portlist=29 medium-type=sr +port set property unit=0 portlist=30 medium-type=sr +port set property unit=0 portlist=31 medium-type=sr +port set property unit=0 portlist=32 medium-type=sr +port set property unit=0 portlist=33 medium-type=sr +port set property unit=0 portlist=34 medium-type=sr +port set property unit=0 portlist=35 medium-type=sr +port set property unit=0 portlist=36 medium-type=sr +port set property unit=0 portlist=37 medium-type=sr +port set property unit=0 portlist=38 medium-type=sr +port set property unit=0 portlist=39 medium-type=sr +port set property unit=0 portlist=40 medium-type=sr +port set property unit=0 portlist=41 medium-type=sr +port set property unit=0 portlist=42 medium-type=sr +port set property unit=0 portlist=43 medium-type=sr +port set property unit=0 portlist=44 medium-type=sr +port set property unit=0 portlist=45 medium-type=sr +port set property unit=0 portlist=46 medium-type=sr +port set property unit=0 portlist=47 medium-type=sr +port set property unit=0 portlist=48 medium-type=sr4 +port set property unit=0 portlist=49 medium-type=sr4 +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=129 medium-type=kr +port set property unit=0 portlist=130 medium-type=x +port advertise unit=0 portlist=129 speed-10g-kr +port set property unit=0 portlist=129 an=enable +port set property unit=0 portlist=0-53 admin=disable +port set property unit=0 portlist=129-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..ae5a8385d96c --- /dev/null +++ b/device/cig/x86_64-cig_cs5435_54p-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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..442026775a5e --- /dev/null +++ b/device/cig/x86_64-cig_cs5435_54p-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# 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..2d6827300457 --- /dev/null +++ b/device/cig/x86_64-cig_cs5435_54p-r0/plugins/sfputil.py @@ -0,0 +1,244 @@ +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as 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 = list(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_54p-r0/Cig-CS6436-54P/port_config.nps b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/port_config.nps new file mode 100644 index 000000000000..120b7f398871 --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_54p-r0/Cig-CS6436-54P/port_config.nps @@ -0,0 +1,624 @@ +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=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=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 +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=tx data=0x1 +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=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=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 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=rx data=0x1 +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=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=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 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=tx data=0x1 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=tx data=0x0.0.0.0 +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=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 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=rx data=0x0 +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.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=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 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c1 data=0x6.6.6.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=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 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c1 data=0x3 +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=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=129 speed=10g +port set property unit=0 portlist=130 speed=1g +port set property unit=0 portlist=0 medium-type=sr +port set property unit=0 portlist=1 medium-type=sr +port set property unit=0 portlist=2 medium-type=sr +port set property unit=0 portlist=3 medium-type=sr +port set property unit=0 portlist=4 medium-type=sr +port set property unit=0 portlist=5 medium-type=sr +port set property unit=0 portlist=6 medium-type=sr +port set property unit=0 portlist=7 medium-type=sr +port set property unit=0 portlist=8 medium-type=sr +port set property unit=0 portlist=9 medium-type=sr +port set property unit=0 portlist=10 medium-type=sr +port set property unit=0 portlist=11 medium-type=sr +port set property unit=0 portlist=12 medium-type=sr +port set property unit=0 portlist=13 medium-type=sr +port set property unit=0 portlist=14 medium-type=sr +port set property unit=0 portlist=15 medium-type=sr +port set property unit=0 portlist=16 medium-type=sr +port set property unit=0 portlist=17 medium-type=sr +port set property unit=0 portlist=18 medium-type=sr +port set property unit=0 portlist=19 medium-type=sr +port set property unit=0 portlist=20 medium-type=sr +port set property unit=0 portlist=21 medium-type=sr +port set property unit=0 portlist=22 medium-type=sr +port set property unit=0 portlist=23 medium-type=sr +port set property unit=0 portlist=24 medium-type=sr +port set property unit=0 portlist=25 medium-type=sr +port set property unit=0 portlist=26 medium-type=sr +port set property unit=0 portlist=27 medium-type=sr +port set property unit=0 portlist=28 medium-type=sr +port set property unit=0 portlist=29 medium-type=sr +port set property unit=0 portlist=30 medium-type=sr +port set property unit=0 portlist=31 medium-type=sr +port set property unit=0 portlist=32 medium-type=sr +port set property unit=0 portlist=33 medium-type=sr +port set property unit=0 portlist=34 medium-type=sr +port set property unit=0 portlist=35 medium-type=sr +port set property unit=0 portlist=36 medium-type=sr +port set property unit=0 portlist=37 medium-type=sr +port set property unit=0 portlist=38 medium-type=sr +port set property unit=0 portlist=39 medium-type=sr +port set property unit=0 portlist=40 medium-type=sr +port set property unit=0 portlist=41 medium-type=sr +port set property unit=0 portlist=42 medium-type=sr +port set property unit=0 portlist=43 medium-type=sr +port set property unit=0 portlist=44 medium-type=sr +port set property unit=0 portlist=45 medium-type=sr +port set property unit=0 portlist=46 medium-type=sr +port set property unit=0 portlist=47 medium-type=sr +port set property unit=0 portlist=48 medium-type=sr4 +port set property unit=0 portlist=49 medium-type=sr4 +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=129 medium-type=kr +port set property unit=0 portlist=130 medium-type=x +port advertise unit=0 portlist=129 speed-10g-kr +port set property unit=0 portlist=129 an=enable +port set property unit=0 portlist=0-53 admin=disable +port set property unit=0 portlist=129-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..c068c04dac6d --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_54p-r0/plugins/eeprom.py @@ -0,0 +1,19 @@ +try: + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError as 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..442026775a5e --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_54p-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# 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..2d6827300457 --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_54p-r0/plugins/sfputil.py @@ -0,0 +1,244 @@ +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as 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 = list(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 new file mode 100644 index 000000000000..2c391214fa65 --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/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_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 new file mode 100644 index 000000000000..d98b0eca6d19 --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/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_56p-r0/Cig-CS6436-56P/port_config.ini b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.ini new file mode 100644 index 000000000000..f7914a5c4ab0 --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.ini @@ -0,0 +1,57 @@ +# 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 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 new file mode 100644 index 000000000000..c0067a3b56af --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/port_config.nps @@ -0,0 +1,646 @@ +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=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=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 +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=tx data=0x1 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=tx data=0x2 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=tx data=0x3 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=tx data=0x0 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=tx data=0x1 +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=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 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=rx data=0x1 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=rx data=0x0 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=rx data=0x3 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=rx data=0x2 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=rx data=0x1 +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=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=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 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=tx data=0x1 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=tx data=0x0.0.0.0 +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 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=rx data=0x0 +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=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 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=cn1 data=0x1 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c0 data=0x1a +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c0 data=0x1b +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c1 data=0x7 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c2 data=0x2 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=cn1 data=0x0 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c0 data=0x1c +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c1 data=0x6 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c1 data=0x6.6.6.6 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c2 data=0x2.2.2.2 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=cn1 data=0x0.0.0.0 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c0 data=0x1b.1b.1b.1b +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c1 data=0x6.6.6.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 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c1 data=0x3 +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=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 +port set property unit=0 portlist=1 medium-type=sr +port set property unit=0 portlist=2 medium-type=sr +port set property unit=0 portlist=3 medium-type=sr +port set property unit=0 portlist=4 medium-type=sr +port set property unit=0 portlist=5 medium-type=sr +port set property unit=0 portlist=6 medium-type=sr +port set property unit=0 portlist=7 medium-type=sr +port set property unit=0 portlist=8 medium-type=sr +port set property unit=0 portlist=9 medium-type=sr +port set property unit=0 portlist=10 medium-type=sr +port set property unit=0 portlist=11 medium-type=sr +port set property unit=0 portlist=12 medium-type=sr +port set property unit=0 portlist=13 medium-type=sr +port set property unit=0 portlist=14 medium-type=sr +port set property unit=0 portlist=15 medium-type=sr +port set property unit=0 portlist=16 medium-type=sr +port set property unit=0 portlist=17 medium-type=sr +port set property unit=0 portlist=18 medium-type=sr +port set property unit=0 portlist=19 medium-type=sr +port set property unit=0 portlist=20 medium-type=sr +port set property unit=0 portlist=21 medium-type=sr +port set property unit=0 portlist=22 medium-type=sr +port set property unit=0 portlist=23 medium-type=sr +port set property unit=0 portlist=24 medium-type=sr +port set property unit=0 portlist=25 medium-type=sr +port set property unit=0 portlist=26 medium-type=sr +port set property unit=0 portlist=27 medium-type=sr +port set property unit=0 portlist=28 medium-type=sr +port set property unit=0 portlist=29 medium-type=sr +port set property unit=0 portlist=30 medium-type=sr +port set property unit=0 portlist=31 medium-type=sr +port set property unit=0 portlist=32 medium-type=sr +port set property unit=0 portlist=33 medium-type=sr +port set property unit=0 portlist=34 medium-type=sr +port set property unit=0 portlist=35 medium-type=sr +port set property unit=0 portlist=36 medium-type=sr +port set property unit=0 portlist=37 medium-type=sr +port set property unit=0 portlist=38 medium-type=sr +port set property unit=0 portlist=39 medium-type=sr +port set property unit=0 portlist=40 medium-type=sr +port set property unit=0 portlist=41 medium-type=sr +port set property unit=0 portlist=42 medium-type=sr +port set property unit=0 portlist=43 medium-type=sr +port set property unit=0 portlist=44 medium-type=sr +port set property unit=0 portlist=45 medium-type=sr +port set property unit=0 portlist=46 medium-type=sr +port set property unit=0 portlist=47 medium-type=sr +port set property unit=0 portlist=48 medium-type=sr4 +port set property unit=0 portlist=49 medium-type=sr4 +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 +port set property unit=0 portlist=129 an=enable +port set property unit=0 portlist=0-55 admin=disable +port set property unit=0 portlist=129-130 admin=disable diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/proc_init.nps b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/proc_init.nps new file mode 100644 index 000000000000..e55ceb0fda3f --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/proc_init.nps @@ -0,0 +1,10 @@ +#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 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 +0 NPS_CFG_TYPE_HASH_L2_FDB_REGION_ENTRY_NUM 0 0 49152 +0 NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM 0 0 32768 + 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 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} 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 new file mode 100644 index 000000000000..e7b5f90ac88a --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/Cig-CS6436-56P/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_56p-r0/default_sku b/device/cig/x86_64-cig_cs6436_56p-r0/default_sku new file mode 100644 index 000000000000..77eed7781071 --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/default_sku @@ -0,0 +1 @@ +Cig-CS6436-56P t1 diff --git a/device/cig/x86_64-cig_cs6436_56p-r0/installer.conf b/device/cig/x86_64-cig_cs6436_56p-r0/installer.conf new file mode 100644 index 000000000000..ea6b4f6ebe31 --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-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_56p-r0/plugins/eeprom.py b/device/cig/x86_64-cig_cs6436_56p-r0/plugins/eeprom.py new file mode 100755 index 000000000000..ae5a8385d96c --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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_56p-r0/plugins/psuutil.py b/device/cig/x86_64-cig_cs6436_56p-r0/plugins/psuutil.py new file mode 100755 index 000000000000..442026775a5e --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# 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_56p-r0/plugins/sfputil.py b/device/cig/x86_64-cig_cs6436_56p-r0/plugins/sfputil.py new file mode 100755 index 000000000000..9c31083f5c23 --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/plugins/sfputil.py @@ -0,0 +1,246 @@ +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _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 = { + 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 = list(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_56p-r0/sensors.conf b/device/cig/x86_64-cig_cs6436_56p-r0/sensors.conf new file mode 100644 index 000000000000..565186de2807 --- /dev/null +++ b/device/cig/x86_64-cig_cs6436_56p-r0/sensors.conf @@ -0,0 +1,13 @@ +# libsensors configuration file + +chip "cs6436_56p_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/common/pddf/plugins/eeprom.py b/device/common/pddf/plugins/eeprom.py new file mode 100755 index 000000000000..cf7215e0c9ac --- /dev/null +++ b/device/common/pddf/plugins/eeprom.py @@ -0,0 +1,25 @@ +try: + import os + import sys + import json + sys.path.append('/usr/share/sonic/platform/plugins') + import pddfparse + #from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError as 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): + global pddf_obj + global plugin_data + with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd: + plugin_data = json.load(pd) + + pddf_obj = pddfparse.PddfParse() + # system EEPROM always has device name EEPROM1 + self.eeprom_path = pddf_obj.get_path("EEPROM1", "eeprom") + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/common/pddf/plugins/fanutil.py b/device/common/pddf/plugins/fanutil.py new file mode 100755 index 000000000000..f34c260035e8 --- /dev/null +++ b/device/common/pddf/plugins/fanutil.py @@ -0,0 +1,199 @@ +# Sample pddf_fanutil file +# All the supported FAN SysFS aattributes are +#- fan_present +#- fan_direction +#- fan_input +#- fan_pwm +#- fan_fault +# where idx is in the range [1-12] +# + + +import os.path +import sys +sys.path.append('/usr/share/sonic/platform/plugins') +import pddfparse +import json + +try: + from sonic_fan.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanUtil(FanBase): + """PDDF generic FAN util class""" + + def __init__(self): + FanBase.__init__(self) + global pddf_obj + global plugin_data + with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd: + plugin_data = json.load(pd) + + pddf_obj = pddfparse.PddfParse() + self.platform = pddf_obj.get_platform() + + self.num_fans = (self.platform['num_fantrays'] * self.platform['num_fans_pertray']) + + def get_num_fans(self): + return self.num_fans + + def get_presence(self, idx): + # 1 based fan index + if idx < 1 or idx > self.num_fans: + print("Invalid fan index %d\n" % idx) + return False + + attr_name = "fan" + str(idx) + "_present" + output = pddf_obj.get_attr_name_output("FAN-CTRL", attr_name) + if not output: + return False + + mode = output['mode'] + presence = output['status'].rstrip() + + vmap = plugin_data['FAN']['present'][mode]['valmap'] + + if presence in vmap: + status = vmap[presence] + else: + status = False + + return status + + def get_status(self, idx): + # 1 based fan index + if idx < 1 or idx > self.num_fans: + print("Invalid fan index %d\n" % idx) + return False + + speed = self.get_speed(idx) + status = True if (speed != 0) else False + return status + + def get_direction(self, idx): + # 1 based fan index + if idx < 1 or idx > self.num_fans: + print("Invalid fan index %d\n" % idx) + return None + + attr = "fan" + str(idx) + "_direction" + output = pddf_obj.get_attr_name_output("FAN-CTRL", attr) + if not output: + return None + + mode = output['mode'] + val = output['status'] + + val = val.rstrip() + vmap = plugin_data['FAN']['direction'][mode]['valmap'] + + if val in vmap: + direction = vmap[val] + else: + direction = val + + return direction + + def get_directions(self): + num_fan = self.get_num_fan() + + for i in range(1, num_fan+1): + attr = "fan" + str(i) + "_direction" + output = pddf_obj.get_attr_name_output("FAN-CTRL", attr) + if not output: + return None + + mode = output['mode'] + val = output['status'] + + val = val.rstrip() + vmap = plugin_data['FAN']['direction'][mode]['valmap'] + + direction = vmap[str(val)] + + print("FAN-%d direction is %s" % (i, direction)) + + return 0 + + def get_speed(self, idx): + # 1 based fan index + if idx < 1 or idx > self.num_fans: + print("Invalid fan index %d\n" % idx) + return 0 + + attr = "fan" + str(idx) + "_input" + output = pddf_obj.get_attr_name_output("FAN-CTRL", attr) + if not output: + return 0 + + #mode = output['mode'] + val = output['status'].rstrip() + + if val.isalpha(): + return 0 + else: + rpm_speed = int(float(val)) + + return rpm_speed + + def get_speeds(self): + num_fan = self.get_num_fan() + ret = "FAN_INDEX\t\tRPM\n" + + for i in range(1, num_fan+1): + attr1 = "fan" + str(i) + "_input" + output = pddf_obj.get_attr_name_output("FAN-CTRL", attr1) + if not output: + return "" + + #mode = output['mode'] + val = output['status'].rstrip() + + if val.isalpha(): + frpm = 0 + else: + frpm = int(val) + + ret += "FAN-%d\t\t\t%d\n" % (i, frpm) + + return ret + + def set_speed(self, val): + if val < 0 or val > 100: + print("Error: Invalid speed %d. Please provide a valid speed percentage" % val) + return False + + num_fan = self.num_fans + if 'duty_cycle_to_pwm' not in plugin_data['FAN']: + print("Setting fan speed is not allowed !") + return False + else: + duty_cycle_to_pwm = eval(plugin_data['FAN']['duty_cycle_to_pwm']) + pwm = duty_cycle_to_pwm(val) + print("New Speed: %d%% - PWM value to be set is %d\n" % (val, pwm)) + + for i in range(1, num_fan+1): + attr = "fan" + str(i) + "_pwm" + node = pddf_obj.get_path("FAN-CTRL", attr) + if node is None: + return False + try: + with open(node, 'w') as f: + f.write(str(pwm)) + except IOError: + return False + + return True + + def dump_sysfs(self): + return pddf_obj.cli_dump_dsysfs('fan') + + def get_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring FAN(fand) + on this platform. + """ + raise NotImplementedError diff --git a/device/common/pddf/plugins/ledutil.py b/device/common/pddf/plugins/ledutil.py new file mode 100755 index 000000000000..5f9e2e99dbfa --- /dev/null +++ b/device/common/pddf/plugins/ledutil.py @@ -0,0 +1,59 @@ +import sys +sys.path.append('/usr/share/sonic/platform/plugins') +import pddfparse + + +class LedUtil: + color_map = { + "STATUS_LED_COLOR_GREEN": "on", + "STATUS_LED_COLOR_RED": "faulty", + "STATUS_LED_COLOR_OFF": "off" + } + + def __init__(self): + global pddf_obj + pddf_obj = pddfparse.PddfParse() + self.path = "pddf/devices/led" + self.cur_state_path = "pddf/devices/led/cur_state" + + def set_status_led(self, led_device_name, color, color_state="SOLID"): + if (not led_device_name in list(pddf_obj.data.keys())): + status = "ERROR: " + led_device_name + " is not configured" + return (status) + + if (not color in list(self.color_map.keys())): + status = "ERROR: Invalid color" + return (status) + + index = pddf_obj.data[led_device_name]['dev_attr']['index'] + pddf_obj.create_attr('device_name', led_device_name, self.path) + pddf_obj.create_attr('index', index, self.path) + pddf_obj.create_attr( + 'color', self.color_map[color], self.cur_state_path) + pddf_obj.create_attr('color_state', color_state, self.cur_state_path) + pddf_obj.create_attr('dev_ops', 'set_status', self.path) + return ("Executed") + + def get_status_led(self, led_device_name): + if (not led_device_name in list(pddf_obj.data.keys())): + status = "ERROR: " + led_device_name + " is not configured" + return (status) + + index = pddf_obj.data[led_device_name]['dev_attr']['index'] + pddf_obj.create_attr('device_name', led_device_name, self.path) + pddf_obj.create_attr('index', index, self.path) + pddf_obj.create_attr('dev_ops', 'get_status', self.path) + color_f = "/sys/kernel/" + self.cur_state_path + "/color" + color_state_f = "/sys/kernel/" + self.cur_state_path + "/color_state" + + try: + with open(color_f, 'r') as f: + color = f.read().strip("\r\n") + with open(color_state_f, 'r') as f: + color_state = f.read().strip("\r\n") + except IOError: + status = "ERROR :" + color_f + " open failed" + return (status) + status = "%s-%s:\t%s %s\n" % (led_device_name, + index, color, color_state) + return (status) diff --git a/device/common/pddf/plugins/psuutil.py b/device/common/pddf/plugins/psuutil.py new file mode 100755 index 000000000000..dccb1ac1a155 --- /dev/null +++ b/device/common/pddf/plugins/psuutil.py @@ -0,0 +1,270 @@ +# +# Sample pddf_psuutil file +# +# All the supported PSU SysFS aattributes are +#- psu_present +#- psu_model_name +#- psu_power_good +#- psu_mfr_id +#- psu_serial_num +#- psu_fan_dir +#- psu_v_out +#- psu_i_out +#- psu_p_out +#- psu_fan1_speed_rpm +# + +import os.path +import sys +sys.path.append('/usr/share/sonic/platform/plugins') +import pddfparse +import json + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """PDDF generic PSU util class""" + + def __init__(self): + PsuBase.__init__(self) + global pddf_obj + global plugin_data + with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd: + plugin_data = json.load(pd) + + pddf_obj = pddfparse.PddfParse() + self.platform = pddf_obj.get_platform() + + def get_num_psus(self): + return int(self.platform['num_psus']) + + def get_psu_status(self, index): + if index is None: + return False + + device = "PSU" + "%d" % index + output = pddf_obj.get_attr_name_output(device, "psu_power_good") + if not output: + return False + + mode = output['mode'] + val = output['status'] + + val = val.rstrip() + vmap = plugin_data['PSU']['psu_power_good'][mode]['valmap'] + + if val in vmap: + return vmap[val] + else: + return False + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + device = "PSU" + "%d" % index + output = pddf_obj.get_attr_name_output(device, "psu_present") + if not output: + return False + + mode = output['mode'] + status = output['status'] + + vmap = plugin_data['PSU']['psu_present'][mode]['valmap'] + + if status.rstrip('\n') in vmap: + return vmap[status.rstrip('\n')] + else: + return False + + def get_powergood_status(self, idx): + if idx is None: + return False + + if idx < 1 or idx > self.platform['num_psus']: + print("Invalid index %d\n" % idx) + return False + + device = "PSU"+"%d" % (idx) + output = pddf_obj.get_attr_name_output(device, "psu_power_good") + if not output: + return False + + mode = output['mode'] + status = output['status'] + + vmap = plugin_data['PSU']['psu_power_good'][mode]['valmap'] + + if status.rstrip('\n') in vmap: + return vmap[status.rstrip('\n')] + else: + return False + + def get_model(self, idx): + if idx is None: + return None + + if idx < 1 or idx > self.platform['num_psus']: + print("Invalid index %d\n" % idx) + return None + + device = "PSU"+"%d" % (idx) + output = pddf_obj.get_attr_name_output(device, "psu_model_name") + if not output: + return None + + model = output['status'] + + # strip_non_ascii + stripped = (c for c in model if 0 < ord(c) < 127) + model = ''.join(stripped) + + return model.rstrip('\n') + + def get_mfr_id(self, idx): + if idx is None: + return None + + if idx < 1 or idx > self.platform['num_psus']: + print("Invalid index %d\n" % idx) + return None + + device = "PSU"+"%d" % (idx) + output = pddf_obj.get_attr_name_output(device, "psu_mfr_id") + if not output: + return None + + mfr = output['status'] + + return mfr.rstrip('\n') + + def get_serial(self, idx): + if idx is None: + return None + + if idx < 1 or idx > self.platform['num_psus']: + print("Invalid index %d\n" % idx) + return None + + device = "PSU"+"%d" % (idx) + output = pddf_obj.get_attr_name_output(device, "psu_serial_num") + if not output: + return None + + serial = output['status'] + + return serial.rstrip('\n') + + def get_direction(self, idx): + if idx is None: + return None + + if idx < 1 or idx > self.platform['num_psus']: + print("Invalid index %d\n" % idx) + return None + + device = "PSU"+"%d" % (idx) + output = pddf_obj.get_attr_name_output(device, "psu_fan_dir") + if not output: + return None + + mode = output['mode'] + direction = output['status'].rstrip('\n') + + vmap = plugin_data['PSU']['psu_fan_dir'][mode]['valmap'] + if direction in vmap: + airflow_dir_real = vmap[direction] + else: + airflow_dir_real = direction + + return airflow_dir_real + + def get_output_voltage(self, idx): + if idx is None: + return 0.0 + + if idx < 1 or idx > self.platform['num_psus']: + print("Invalid index %d\n" % idx) + return 0.0 + + device = "PSU"+"%d" % (idx) + output = pddf_obj.get_attr_name_output(device, "psu_v_out") + if not output: + return 0.0 + + v_out = output['status'] + + # value returned by the psu driver is in mV + return float(v_out)/1000 + + def get_output_current(self, idx): + if idx is None: + return 0.0 + + if idx < 1 or idx > self.platform['num_psus']: + print("Invalid index %d\n" % idx) + return 0.0 + + device = "PSU"+"%d" % (idx) + output = pddf_obj.get_attr_name_output(device, "psu_i_out") + if not output: + return 0.0 + + i_out = output['status'] + + # current in mA + return float(i_out)/1000 + + def get_output_power(self, idx): + if idx is None: + return 0.0 + + if idx < 1 or idx > self.platform['num_psus']: + print("Invalid index %d\n" % idx) + return 0.0 + + device = "PSU"+"%d" % (idx) + output = pddf_obj.get_attr_name_output(device, "psu_p_out") + if not output: + return 0.0 + + p_out = output['status'] + + # power is returned in micro watts + return float(p_out)/1000000 + + def get_fan_rpm(self, idx, fan_idx): + if idx is None or fan_idx is None: + return 0 + + if idx < 1 or idx > self.platform['num_psus']: + print("Invalid index %d\n" % idx) + return 0 + + device = "PSU"+"%d" % (idx) + num_fans = pddf_obj.get_num_psu_fans(device) + + if fan_idx < 1 or fan_idx > num_fans: + print("Invalid PSU-fan index %d\n" % fan_idx) + return 0 + + output = pddf_obj.get_attr_name_output(device, "psu_fan"+str(fan_idx)+"_speed_rpm") + if not output: + return 0 + + #mode = output['mode'] + output['status'] = output['status'].rstrip() + if output['status'].isalpha(): + return 0 + else: + speed = int(output['status']) + + return speed + + def dump_sysfs(self): + return pddf_obj.cli_dump_dsysfs('psu') diff --git a/device/common/pddf/plugins/sfputil.py b/device/common/pddf/plugins/sfputil.py new file mode 100755 index 000000000000..1ca925610822 --- /dev/null +++ b/device/common/pddf/plugins/sfputil.py @@ -0,0 +1,236 @@ +import os.path +import sys +sys.path.append('/usr/share/sonic/platform/plugins') +import pddfparse +import json + +try: + import time + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform generic PDDF SfpUtil class""" + + _port_to_eeprom_mapping = {} + _port_start = 0 + _port_end = 0 + _port_to_type_mapping = {} + _qsfp_ports = [] + _sfp_ports = [] + + def __init__(self): + SfpUtilBase.__init__(self) + global pddf_obj + global plugin_data + with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd: + plugin_data = json.load(pd) + + pddf_obj = pddfparse.PddfParse() + self.platform = pddf_obj.get_platform() + self._port_start = 0 + self._port_end = self.get_num_ports() + + for port_num in range(self._port_start, self._port_end): + device = "PORT" + "%d" % (port_num+1) + port_eeprom_path = pddf_obj.get_path(device, "eeprom") + self._port_to_eeprom_mapping[port_num] = port_eeprom_path + port_type = pddf_obj.get_device_type(device) + self._port_to_type_mapping[port_num] = port_type + self.populate_port_type(port_num) + + def get_num_ports(self): + return int(self.platform['num_ports']) + + def is_valid_port(self, port_num): + if port_num < self._port_start or port_num > self._port_end: + return False + else: + return True + + def get_presence(self, port_num): + if port_num < self._port_start or port_num > self._port_end: + return False + + device = "PORT" + "%d" % (port_num+1) + output = pddf_obj.get_attr_name_output(device, 'xcvr_present') + if not output: + return False + + #mode = output['mode'] + modpres = output['status'].rstrip() + if 'XCVR' in plugin_data: + if 'xcvr_present' in plugin_data['XCVR']: + ptype = self._port_to_type_mapping[port_num] + vtype = 'valmap-'+ptype + if vtype in plugin_data['XCVR']['xcvr_present']: + vmap = plugin_data['XCVR']['xcvr_present'][vtype] + if modpres in vmap: + return vmap[modpres] + else: + return False + # if plugin_data doesn't specify anything regarding Transceivers + if modpres == '1': + return True + + return False + + def populate_port_type(self, port): + if self._port_to_type_mapping[port] == 'QSFP' or self._port_to_type_mapping[port] == 'QSFP28': + self._qsfp_ports.append(port) + elif self._port_to_type_mapping[port] == 'SFP' or self._port_to_type_mapping[port] == 'SFP28': + self._sfp_ports.append(port) + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return (self._port_end - 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def qsfp_ports(self): + return self._qsfp_ports + + def reset(self, port_num): + if port_num < self._port_start or port_num > self._port_end: + return False + + device = "PORT" + "%d" % (port_num+1) + port_ps = pddf_obj.get_path(device, "xcvr_reset") + if port_ps is None: + return False + + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + try: + reg_file.seek(0) + reg_file.write('1') + time.sleep(1) + reg_file.seek(0) + reg_file.write('0') + reg_file.close() + return True + except IOError as e: + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + if not self.get_presence(port_num): + return False + + device = "PORT" + "%d" % (port_num+1) + output = pddf_obj.get_attr_name_output(device, 'xcvr_lpmode') + if not output: + if port_num not in self.qsfp_ports: + return False # Read from eeprom only for QSFP ports + try: + eeprom = None + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + # check for valid connector type + eeprom.seek(2) + ctype = eeprom.read(1) + if ctype in ['21', '23']: + return False + + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + else: + #mode = output['mode'] + status = int(output['status'].rstrip()) + + if status == 1: + return True + else: + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + device = "PORT" + "%d" % (port_num+1) + port_ps = pddf_obj.get_path(device, "xcvr_lpmode") + if port_ps is None: + if port_num not in self.qsfp_ports: + return False # Write to eeprom only for QSFP ports + try: + eeprom = None + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + # check for valid connector type + eeprom.seek(2) + ctype = eeprom.read(1) + if ctype in ['21', '23']: + return False + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + else: + try: + f = open(port_ps, 'w') + if lpmode: + f.write('1') + else: + f.write('0') + f.close() + return True + except IOError as e: + 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 + + def dump_sysfs(self): + return pddf_obj.cli_dump_dsysfs('xcvr') diff --git a/device/common/pddf/plugins/sysstatutil.py b/device/common/pddf/plugins/sysstatutil.py new file mode 100755 index 000000000000..af4dd5915361 --- /dev/null +++ b/device/common/pddf/plugins/sysstatutil.py @@ -0,0 +1,82 @@ +import os.path +import sys +sys.path.append('/usr/share/sonic/platform/plugins') +import pddfparse +import json + + +class SYSStatusUtil(): + """Platform-specific SYSStatus class""" + + def __init__(self): + global pddf_obj + global plugin_data + with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd: + plugin_data = json.load(pd) + + pddf_obj = pddfparse.PddfParse() + + def get_board_info(self): + device = "SYSSTATUS" + node = pddf_obj.get_path(device, "board_info") + if node is None: + return False + try: + with open(node, 'r') as f: + status = f.read() + print("board_info : %s" % status) + except IOError: + return False + + def get_cpld_versio(self): + device = "SYSSTATUS" + node = pddf_obj.get_path(device, "cpld1_version") + if node is None: + return False + try: + with open(node, 'r') as f: + status = f.read() + print("cpld1_version : %s" % status) + except IOError: + return False + + def get_power_module_status(self): + device = "SYSSTATUS" + node = pddf_obj.get_path(device, "power_module_status") + if node is None: + return False + try: + with open(node, 'r') as f: + status = f.read() + print("power_module_status : %s" % status) + except IOError: + return False + + def get_system_reset_status(self): + device = "SYSSTATUS" + for i in range(1, 8): + node = pddf_obj.get_path(device, "system_reset"+str(i)) + if node is None: + return False + try: + with open(node, 'r') as f: + status = f.read() + print("system_reset%s : %s" % (i, status)) + except IOError: + print("system_reset%s not supported" % i) + + def get_misc_status(self): + device = "SYSSTATUS" + for i in range(1, 3): + node = pddf_obj.get_path(device, "misc"+str(i)) + if node is None: + return False + try: + with open(node, 'r') as f: + status = f.read() + print("misc%s : %s" % (i, status)) + except IOError: + print("system_reset%s not supported" % i) + + def dump_sysfs(self): + return pddf_obj.cli_dump_dsysfs('sys-status') diff --git a/device/common/pddf/plugins/thermalutil.py b/device/common/pddf/plugins/thermalutil.py new file mode 100755 index 000000000000..6aef47b7e924 --- /dev/null +++ b/device/common/pddf/plugins/thermalutil.py @@ -0,0 +1,75 @@ +import os.path +import sys +import json +sys.path.append('/usr/share/sonic/platform/plugins') +import pddfparse + + +class ThermalUtil: + def __init__(self): + global pddf_obj + global plugin_data + with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd: + plugin_data = json.load(pd) + + pddf_obj = pddfparse.PddfParse() + self.platform = pddf_obj.get_platform() + self.num_thermals = self.platform['num_temps'] + self.info = [] + + def get_num_thermals(self): + return (self.num_thermals) + + def get_thermal_info(self): + list = [] + pddf_obj.get_device_list(list, "TEMP_SENSOR") + list.sort() + for dev in list: + data = {} + device_name = dev['dev_info']['device_name'] + topo_info = dev['i2c']['topo_info'] + label = "%s-i2c-%d-%x" % (topo_info['dev_type'], + int(topo_info['parent_bus'], 0), int(topo_info['dev_addr'], 0)) + attr_list = dev['i2c']['attr_list'] + data['device_name'] = device_name + data['label'] = label + for attr in attr_list: + attr_name = attr['attr_name'] + node = pddf_obj.get_path(device_name, attr_name) + if node is None: + return False + try: + with open(node, 'r') as f: + attr_value = int(f.read()) + except IOError: + return False + data[attr_name] = attr_value/float(1000) + self.info.append(data) + + def show_thermal_temp_values(self, idx): + if idx < 1 or idx > self.num_thermals: + print("Invalid temperature sensor idx %d" % idx) + return None + self.get_thermal_info() + thermal_name = "TEMP"+"%d" % idx + label = "" + value = "" + for temp in self.info: + if thermal_name == temp['device_name']: + label = temp['label'] + value = "temp1\t %+.1f C (high = %+.1f C, hyst = %+.1f C)" % ( + temp['temp1_input'], temp['temp1_max'], temp['temp1_max_hyst']) + else: + continue + + return (label, value) + + def show_temp_values(self): + self.get_thermal_info() + for temp in self.info: + print(temp['label']) + print("temp1\t %+.1f C (high = %+.1f C, hyst = %+.1f C)" % + (temp['temp1_input'], temp['temp1_max'], temp['temp1_max_hyst'])) + + def dump_sysfs(self): + return pddf_obj.cli_dump_dsysfs('temp-sensors') diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/buffers.json.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/buffers.json.j2 new file mode 100755 index 000000000000..e6e9e844469b --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/buffers_defaults_t0.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/buffers_defaults_t0.j2 new file mode 100755 index 000000000000..8243498dd31c --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/buffers_defaults_t0.j2 @@ -0,0 +1,63 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,8) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(8,14) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(14,18) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(18,24) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(24,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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/buffers_defaults_t1.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/buffers_defaults_t1.j2 new file mode 100755 index 000000000000..8243498dd31c --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/buffers_defaults_t1.j2 @@ -0,0 +1,63 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,8) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(8,14) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(14,18) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(18,24) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(24,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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/pg_profile_lookup.ini b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/pg_profile_lookup.ini new file mode 100755 index 000000000000..9f2eacb6fc42 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/port_config.ini b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/port_config.ini new file mode 100755 index 000000000000..d999be87623e --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/port_config.ini @@ -0,0 +1,69 @@ +# name lanes alias index speed +Ethernet0 29,30,31,32 fortyGigE0/0 0 40000 +Ethernet4 25,26,27,28 fortyGigE0/4 1 40000 +Ethernet8 37,38,39,40 fortyGigE0/8 2 40000 +Ethernet12 33,34,35,36 fortyGigE0/12 3 40000 +Ethernet16 41,42,43,44 fortyGigE0/16 4 40000 +Ethernet20 45,46,47,48 fortyGigE0/20 5 40000 +Ethernet24 5,6,7,8 fortyGigE0/24 6 40000 +Ethernet28 1,2,3,4 fortyGigE0/28 7 40000 +Ethernet32 9 tenGigE0/32 8 10000 +Ethernet33 10 tenGigE0/33 8 10000 +Ethernet34 11 tenGigE0/34 8 10000 +Ethernet35 12 tenGigE0/35 8 10000 +Ethernet36 13 tenGigE0/36 9 10000 +Ethernet37 14 tenGigE0/37 9 10000 +Ethernet38 15 tenGigE0/38 9 10000 +Ethernet39 16 tenGigE0/39 9 10000 +Ethernet40 21 tenGigE0/40 10 10000 +Ethernet41 22 tenGigE0/41 10 10000 +Ethernet42 23 tenGigE0/42 10 10000 +Ethernet43 24 tenGigE0/43 10 10000 +Ethernet44 17 tenGigE0/44 11 10000 +Ethernet45 18 tenGigE0/45 11 10000 +Ethernet46 19 tenGigE0/46 11 10000 +Ethernet47 20 tenGigE0/47 11 10000 +Ethernet48 49 tenGigE0/48 12 10000 +Ethernet49 50 tenGigE0/49 12 10000 +Ethernet50 51 tenGigE0/50 12 10000 +Ethernet51 52 tenGigE0/51 12 10000 +Ethernet52 53 tenGigE0/52 13 10000 +Ethernet53 54 tenGigE0/53 13 10000 +Ethernet54 55 tenGigE0/54 13 10000 +Ethernet55 56 tenGigE0/55 13 10000 +Ethernet56 61,62,63,64 fortyGigE0/56 14 40000 +Ethernet60 57,58,59,60 fortyGigE0/60 15 40000 +Ethernet64 65,66,67,68 fortyGigE0/64 16 40000 +Ethernet68 69,70,71,72 fortyGigE0/68 17 40000 +Ethernet72 77 tenGigE0/72 18 10000 +Ethernet73 78 tenGigE0/73 18 10000 +Ethernet74 79 tenGigE0/74 18 10000 +Ethernet75 80 tenGigE0/75 18 10000 +Ethernet76 73 tenGigE0/76 19 10000 +Ethernet77 74 tenGigE0/77 19 10000 +Ethernet78 75 tenGigE0/78 19 10000 +Ethernet79 76 tenGigE0/79 19 10000 +Ethernet80 105 tenGigE0/80 20 10000 +Ethernet81 106 tenGigE0/81 20 10000 +Ethernet82 107 tenGigE0/82 20 10000 +Ethernet83 108 tenGigE0/83 20 10000 +Ethernet84 109 tenGigE0/84 21 10000 +Ethernet85 110 tenGigE0/85 21 10000 +Ethernet86 111 tenGigE0/86 21 10000 +Ethernet87 112 tenGigE0/87 21 10000 +Ethernet88 117 tenGigE0/88 22 10000 +Ethernet89 118 tenGigE0/89 22 10000 +Ethernet90 119 tenGigE0/90 22 10000 +Ethernet91 120 tenGigE0/91 22 10000 +Ethernet92 113 tenGigE0/92 23 10000 +Ethernet93 114 tenGigE0/93 23 10000 +Ethernet94 115 tenGigE0/94 23 10000 +Ethernet95 116 tenGigE0/95 23 10000 +Ethernet96 121,122,123,124 fortyGigE0/96 24 40000 +Ethernet100 125,126,127,128 fortyGigE0/100 25 40000 +Ethernet104 85,86,87,88 fortyGigE0/104 26 40000 +Ethernet108 81,82,83,84 fortyGigE0/108 27 40000 +Ethernet112 89,90,91,92 fortyGigE0/112 28 40000 +Ethernet116 93,94,95,96 fortyGigE0/116 29 40000 +Ethernet120 97,98,99,100 fortyGigE0/120 30 40000 +Ethernet124 101,102,103,104 fortyGigE0/124 31 40000 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/qos.json.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/qos.json.j2 new file mode 100755 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/sai.profile b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/sai.profile new file mode 100755 index 000000000000..22e114e6af26 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-s6000-20x40G-48x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/td2-s6000-20x40G-48x10G.config.bcm b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/td2-s6000-20x40G-48x10G.config.bcm new file mode 100755 index 000000000000..d63f589d4fc9 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q20S48/td2-s6000-20x40G-48x10G.config.bcm @@ -0,0 +1,755 @@ +# 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=10 +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=0x000000000000001fffffffffffffffff +pbmp_xport_xe=0x000000000000001fffffffffffffffff + +# Ports configuration +# xe0 (40G) +portmap_1=29:40 +xgxs_rx_lane_map_1=0x213 +xgxs_tx_lane_map_1=0x213 +phy_xaui_rx_polarity_flip_1=0xc +phy_xaui_tx_polarity_flip_1=0x9 +serdes_driver_current_lane0_1=0x6 +serdes_driver_current_lane1_1=0x7 +serdes_driver_current_lane2_1=0x6 +serdes_driver_current_lane3_1=0x6 +serdes_pre_driver_current_lane0_1=0x6 +serdes_pre_driver_current_lane1_1=0x7 +serdes_pre_driver_current_lane2_1=0x6 +serdes_pre_driver_current_lane3_1=0x6 +serdes_preemphasis_lane0_1=0xc2f0 +serdes_preemphasis_lane1_1=0xd2b0 +serdes_preemphasis_lane2_1=0xc6e0 +serdes_preemphasis_lane3_1=0xc2f0 + +# xe1 (40G) +portmap_2=25:40 +xgxs_rx_lane_map_2=0x213 +xgxs_tx_lane_map_2=0x2031 +phy_xaui_rx_polarity_flip_2=0xe +phy_xaui_tx_polarity_flip_2=0x2 +serdes_driver_current_lane0_2=0x5 +serdes_driver_current_lane1_2=0x5 +serdes_driver_current_lane2_2=0x5 +serdes_driver_current_lane3_2=0x5 +serdes_pre_driver_current_lane0_2=0x5 +serdes_pre_driver_current_lane1_2=0x5 +serdes_pre_driver_current_lane2_2=0x5 +serdes_pre_driver_current_lane3_2=0x5 +serdes_preemphasis_lane0_2=0xcad0 +serdes_preemphasis_lane1_2=0xc6e0 +serdes_preemphasis_lane2_2=0xc6e0 +serdes_preemphasis_lane3_2=0xd2b0 + +# xe2 (40G) +portmap_3=37:40 +xgxs_rx_lane_map_3=0x213 +xgxs_tx_lane_map_3=0x1203 +phy_xaui_rx_polarity_flip_3=0x3 +phy_xaui_tx_polarity_flip_3=0xe +serdes_driver_current_lane0_3=0x4 +serdes_driver_current_lane1_3=0x4 +serdes_driver_current_lane2_3=0x4 +serdes_driver_current_lane3_3=0x4 +serdes_pre_driver_current_lane0_3=0x4 +serdes_pre_driver_current_lane1_3=0x4 +serdes_pre_driver_current_lane2_3=0x4 +serdes_pre_driver_current_lane3_3=0x4 +serdes_preemphasis_lane0_3=0xcad0 +serdes_preemphasis_lane1_3=0xcad0 +serdes_preemphasis_lane2_3=0xc2f0 +serdes_preemphasis_lane3_3=0xc2f0 + +# xe3 (40G) +portmap_4=33:40 +xgxs_rx_lane_map_4=0x213 +xgxs_tx_lane_map_4=0x132 +phy_xaui_rx_polarity_flip_4=0xe +phy_xaui_tx_polarity_flip_4=0x2 +serdes_driver_current_lane0_4=0x4 +serdes_driver_current_lane1_4=0x4 +serdes_driver_current_lane2_4=0x4 +serdes_driver_current_lane3_4=0x4 +serdes_pre_driver_current_lane0_4=0x4 +serdes_pre_driver_current_lane1_4=0x4 +serdes_pre_driver_current_lane2_4=0x4 +serdes_pre_driver_current_lane3_4=0x4 +serdes_preemphasis_lane0_4=0xc6e0 +serdes_preemphasis_lane1_4=0xc6e0 +serdes_preemphasis_lane2_4=0xc6e0 +serdes_preemphasis_lane3_4=0xc6e0 + +# xe4 (40G) +portmap_5=41:40 +xgxs_rx_lane_map_5=0x213 +xgxs_tx_lane_map_5=0x3021 +phy_xaui_rx_polarity_flip_5=0x3 +phy_xaui_tx_polarity_flip_5=0xb +serdes_driver_current_lane0_5=0x4 +serdes_driver_current_lane1_5=0x4 +serdes_driver_current_lane2_5=0x4 +serdes_driver_current_lane3_5=0x4 +serdes_pre_driver_current_lane0_5=0x4 +serdes_pre_driver_current_lane1_5=0x4 +serdes_pre_driver_current_lane2_5=0x4 +serdes_pre_driver_current_lane3_5=0x4 +serdes_preemphasis_lane0_5=0xc6e0 +serdes_preemphasis_lane1_5=0xc2f0 +serdes_preemphasis_lane2_5=0xc2f0 +serdes_preemphasis_lane3_5=0xcad0 + +# xe5 (40G) +portmap_6=45:40 +xgxs_rx_lane_map_6=0x213 +xgxs_tx_lane_map_6=0x213 +phy_xaui_rx_polarity_flip_6=0xe +phy_xaui_tx_polarity_flip_6=0x8 +serdes_driver_current_lane0_6=0x4 +serdes_driver_current_lane1_6=0x4 +serdes_driver_current_lane2_6=0x4 +serdes_driver_current_lane3_6=0x4 +serdes_pre_driver_current_lane0_6=0x4 +serdes_pre_driver_current_lane1_6=0x4 +serdes_pre_driver_current_lane2_6=0x4 +serdes_pre_driver_current_lane3_6=0x4 +serdes_preemphasis_lane0_6=0xc2f0 +serdes_preemphasis_lane1_6=0xc2f0 +serdes_preemphasis_lane2_6=0xc2f0 +serdes_preemphasis_lane3_6=0xc2f0 + +# xe6 (40G) +portmap_7=5:40 +xgxs_rx_lane_map_7=0x213 +xgxs_tx_lane_map_7=0x1203 +phy_xaui_rx_polarity_flip_7=0xc +phy_xaui_tx_polarity_flip_7=0x1 +serdes_driver_current_lane0_7=0x4 +serdes_driver_current_lane1_7=0x4 +serdes_driver_current_lane2_7=0x4 +serdes_driver_current_lane3_7=0x4 +serdes_pre_driver_current_lane0_7=0x4 +serdes_pre_driver_current_lane1_7=0x4 +serdes_pre_driver_current_lane2_7=0x4 +serdes_pre_driver_current_lane3_7=0x4 +serdes_preemphasis_lane0_7=0xc6e0 +serdes_preemphasis_lane1_7=0xc6e0 +serdes_preemphasis_lane2_7=0xc6e0 +serdes_preemphasis_lane3_7=0xc6e0 + +# xe7 (40G) +portmap_8=1:40 +xgxs_rx_lane_map_8=0x213 +xgxs_tx_lane_map_8=0x2031 +phy_xaui_rx_polarity_flip_8=0xe +phy_xaui_tx_polarity_flip_8=0xd +serdes_driver_current_lane0_8=0x5 +serdes_driver_current_lane1_8=0x5 +serdes_driver_current_lane2_8=0x5 +serdes_driver_current_lane3_8=0x5 +serdes_pre_driver_current_lane0_8=0x5 +serdes_pre_driver_current_lane1_8=0x5 +serdes_pre_driver_current_lane2_8=0x5 +serdes_pre_driver_current_lane3_8=0x5 +serdes_preemphasis_lane0_8=0xc6e0 +serdes_preemphasis_lane1_8=0xcad0 +serdes_preemphasis_lane2_8=0xc6e0 +serdes_preemphasis_lane3_8=0xcad0 + +# xe8 (4x10G) +portmap_9=9:10 +portmap_10=10:10 +portmap_11=11:10 +portmap_12=12:10 +xgxs_rx_lane_map_9=0x3120 +xgxs_tx_lane_map_9=0x3021 +phy_xaui_rx_polarity_flip_9=0x0 +phy_xaui_tx_polarity_flip_9=0x4 +phy_xaui_rx_polarity_flip_10=0x0 +phy_xaui_tx_polarity_flip_10=0x0 +phy_xaui_rx_polarity_flip_11=0x0 +phy_xaui_tx_polarity_flip_11=0x1 +phy_xaui_rx_polarity_flip_12=0x0 +phy_xaui_tx_polarity_flip_12=0x0 +serdes_driver_current_lane0_9=0x3 +serdes_driver_current_lane1_9=0x3 +serdes_driver_current_lane2_9=0x3 +serdes_driver_current_lane3_9=0x3 +serdes_pre_driver_current_lane0_9=0x3 +serdes_pre_driver_current_lane1_9=0x3 +serdes_pre_driver_current_lane2_9=0x3 +serdes_pre_driver_current_lane3_9=0x3 +serdes_preemphasis_lane0_9=0xc2f0 +serdes_preemphasis_lane1_9=0xc6e0 +serdes_preemphasis_lane2_9=0xbf00 +serdes_preemphasis_lane3_9=0xc2f0 + +# xe9 (4x10G) +portmap_13=13:10 +portmap_14=14:10 +portmap_15=15:10 +portmap_16=16:10 +xgxs_rx_lane_map_13=0x213 +xgxs_tx_lane_map_13=0x132 +phy_xaui_rx_polarity_flip_13=0xe +phy_xaui_tx_polarity_flip_13=0x0 +phy_xaui_rx_polarity_flip_14=0x1 +phy_xaui_tx_polarity_flip_14=0x0 +phy_xaui_rx_polarity_flip_15=0x1 +phy_xaui_tx_polarity_flip_15=0x0 +phy_xaui_rx_polarity_flip_16=0x1 +phy_xaui_tx_polarity_flip_16=0x0 +serdes_driver_current_lane0_13=0x2 +serdes_driver_current_lane1_13=0x3 +serdes_driver_current_lane2_13=0x2 +serdes_driver_current_lane3_13=0x2 +serdes_pre_driver_current_lane0_13=0x2 +serdes_pre_driver_current_lane1_13=0x3 +serdes_pre_driver_current_lane2_13=0x2 +serdes_pre_driver_current_lane3_13=0x2 +serdes_preemphasis_lane0_13=0xb270 +serdes_preemphasis_lane1_13=0xbb10 +serdes_preemphasis_lane2_13=0xb720 +serdes_preemphasis_lane3_13=0xb720 + +# xe10 (4x10G) +portmap_17=21:10 +portmap_18=22:10 +portmap_19=23:10 +portmap_20=24:10 +xgxs_rx_lane_map_17=0x123 +xgxs_tx_lane_map_17=0x1203 +phy_xaui_rx_polarity_flip_17=0xc +phy_xaui_tx_polarity_flip_17=0xe +phy_xaui_rx_polarity_flip_18=0x0 +phy_xaui_tx_polarity_flip_18=0x1 +phy_xaui_rx_polarity_flip_19=0x1 +phy_xaui_tx_polarity_flip_19=0x1 +phy_xaui_rx_polarity_flip_20=0x1 +phy_xaui_tx_polarity_flip_20=0x1 +serdes_driver_current_lane0_17=0x2 +serdes_driver_current_lane1_17=0x2 +serdes_driver_current_lane2_17=0x2 +serdes_driver_current_lane3_17=0x2 +serdes_pre_driver_current_lane0_17=0x2 +serdes_pre_driver_current_lane1_17=0x2 +serdes_pre_driver_current_lane2_17=0x2 +serdes_pre_driver_current_lane3_17=0x2 +serdes_preemphasis_lane0_17=0xb330 +serdes_preemphasis_lane1_17=0xb330 +serdes_preemphasis_lane2_17=0xb330 +serdes_preemphasis_lane3_17=0xb330 + +# xe11 (4x10G) +portmap_21=17:10 +portmap_22=18:10 +portmap_23=19:10 +portmap_24=20:10 +xgxs_rx_lane_map_21=0x213 +xgxs_tx_lane_map_21=0x132 +phy_xaui_rx_polarity_flip_21=0xe +phy_xaui_tx_polarity_flip_21=0x0 +phy_xaui_rx_polarity_flip_22=0x1 +phy_xaui_tx_polarity_flip_22=0x0 +phy_xaui_rx_polarity_flip_23=0x1 +phy_xaui_tx_polarity_flip_23=0x0 +phy_xaui_rx_polarity_flip_24=0x1 +phy_xaui_tx_polarity_flip_24=0x0 +serdes_driver_current_lane0_21=0x2 +serdes_driver_current_lane1_21=0x2 +serdes_driver_current_lane2_21=0x2 +serdes_driver_current_lane3_21=0x2 +serdes_pre_driver_current_lane0_21=0x2 +serdes_pre_driver_current_lane1_21=0x2 +serdes_pre_driver_current_lane2_21=0x2 +serdes_pre_driver_current_lane3_21=0x2 +serdes_preemphasis_lane0_21=0xb330 +serdes_preemphasis_lane1_21=0xbb10 +serdes_preemphasis_lane2_21=0xbb10 +serdes_preemphasis_lane3_21=0xbb10 + +# xe12 (4x10G) +portmap_25=49:10 +portmap_26=50:10 +portmap_27=51:10 +portmap_28=52:10 +xgxs_rx_lane_map_25=0x1302 +xgxs_tx_lane_map_25=0x2031 +phy_xaui_rx_polarity_flip_25=0xb +phy_xaui_tx_polarity_flip_25=0x3 +phy_xaui_rx_polarity_flip_26=0x1 +phy_xaui_tx_polarity_flip_26=0x1 +phy_xaui_rx_polarity_flip_27=0x0 +phy_xaui_tx_polarity_flip_27=0x0 +phy_xaui_rx_polarity_flip_28=0x1 +phy_xaui_tx_polarity_flip_28=0x0 +serdes_driver_current_lane0_25=0x2 +serdes_driver_current_lane1_25=0x2 +serdes_driver_current_lane2_25=0x2 +serdes_driver_current_lane3_25=0x2 +serdes_pre_driver_current_lane0_25=0x2 +serdes_pre_driver_current_lane1_25=0x2 +serdes_pre_driver_current_lane2_25=0x2 +serdes_pre_driver_current_lane3_25=0x2 +serdes_preemphasis_lane0_25=0xa760 +serdes_preemphasis_lane1_25=0xa760 +serdes_preemphasis_lane2_25=0xa760 +serdes_preemphasis_lane3_25=0xa760 + +# xe13 (4x10G) +portmap_29=53:10 +portmap_30=54:10 +portmap_31=55:10 +portmap_32=56:10 +xgxs_rx_lane_map_29=0x213 +xgxs_tx_lane_map_29=0x231 +phy_xaui_rx_polarity_flip_29=0x1 +phy_xaui_tx_polarity_flip_29=0x0 +phy_xaui_rx_polarity_flip_30=0x0 +phy_xaui_tx_polarity_flip_30=0x0 +phy_xaui_rx_polarity_flip_31=0x0 +phy_xaui_tx_polarity_flip_31=0x0 +phy_xaui_rx_polarity_flip_32=0x0 +phy_xaui_tx_polarity_flip_32=0x0 +serdes_driver_current_lane0_29=0x2 +serdes_driver_current_lane1_29=0x2 +serdes_driver_current_lane2_29=0x2 +serdes_driver_current_lane3_29=0x2 +serdes_pre_driver_current_lane0_29=0x2 +serdes_pre_driver_current_lane1_29=0x2 +serdes_pre_driver_current_lane2_29=0x2 +serdes_pre_driver_current_lane3_29=0x2 +serdes_preemphasis_lane0_29=0xaf40 +serdes_preemphasis_lane1_29=0xaf40 +serdes_preemphasis_lane2_29=0xaf40 +serdes_preemphasis_lane3_29=0xaf40 + +# xe14 (40G) +portmap_33=61:40 +xgxs_rx_lane_map_33=0x132 +xgxs_tx_lane_map_33=0x213 +phy_xaui_rx_polarity_flip_33=0x0 +phy_xaui_tx_polarity_flip_33=0x0 +serdes_driver_current_lane0_33=0x2 +serdes_driver_current_lane1_33=0x2 +serdes_driver_current_lane2_33=0x2 +serdes_driver_current_lane3_33=0x2 +serdes_pre_driver_current_lane0_33=0x2 +serdes_pre_driver_current_lane1_33=0x2 +serdes_pre_driver_current_lane2_33=0x2 +serdes_pre_driver_current_lane3_33=0x2 +serdes_preemphasis_lane0_33=0xa760 +serdes_preemphasis_lane1_33=0xa760 +serdes_preemphasis_lane2_33=0xa760 +serdes_preemphasis_lane3_33=0xa760 + +# xe15 (40G) +portmap_34=57:40 +xgxs_rx_lane_map_34=0x213 +xgxs_tx_lane_map_34=0x2031 +phy_xaui_rx_polarity_flip_34=0x1 +phy_xaui_tx_polarity_flip_34=0x0 +serdes_driver_current_lane0_34=0x1 +serdes_driver_current_lane1_34=0x1 +serdes_driver_current_lane2_34=0x1 +serdes_driver_current_lane3_34=0x1 +serdes_pre_driver_current_lane0_34=0x1 +serdes_pre_driver_current_lane1_34=0x1 +serdes_pre_driver_current_lane2_34=0x1 +serdes_pre_driver_current_lane3_34=0x1 +serdes_preemphasis_lane0_34=0xa760 +serdes_preemphasis_lane1_34=0xa760 +serdes_preemphasis_lane2_34=0xa760 +serdes_preemphasis_lane3_34=0xa760 + +# xe16 (40G) +portmap_35=65:40 +xgxs_rx_lane_map_35=0x132 +xgxs_tx_lane_map_35=0x2031 +phy_xaui_rx_polarity_flip_35=0x3 +phy_xaui_tx_polarity_flip_35=0x9 +serdes_driver_current_lane0_35=0x1 +serdes_driver_current_lane1_35=0x1 +serdes_driver_current_lane2_35=0x1 +serdes_driver_current_lane3_35=0x1 +serdes_pre_driver_current_lane0_35=0x1 +serdes_pre_driver_current_lane1_35=0x1 +serdes_pre_driver_current_lane2_35=0x1 +serdes_pre_driver_current_lane3_35=0x1 +serdes_preemphasis_lane0_35=0xa370 +serdes_preemphasis_lane1_35=0xa370 +serdes_preemphasis_lane2_35=0xa370 +serdes_preemphasis_lane3_35=0xa370 + +# xe17 (40G) +portmap_36=69:40 +xgxs_rx_lane_map_36=0x213 +xgxs_tx_lane_map_36=0x2130 +phy_xaui_rx_polarity_flip_36=0x1 +phy_xaui_tx_polarity_flip_36=0xf +serdes_driver_current_lane0_36=0x1 +serdes_driver_current_lane1_36=0x1 +serdes_driver_current_lane2_36=0x1 +serdes_driver_current_lane3_36=0x1 +serdes_pre_driver_current_lane0_36=0x1 +serdes_pre_driver_current_lane1_36=0x1 +serdes_pre_driver_current_lane2_36=0x1 +serdes_pre_driver_current_lane3_36=0x1 +serdes_preemphasis_lane0_36=0xa760 +serdes_preemphasis_lane1_36=0xa760 +serdes_preemphasis_lane2_36=0xa760 +serdes_preemphasis_lane3_36=0xa760 + +# xe18 (4x10G) +portmap_37=77:10 +portmap_38=78:10 +portmap_39=79:10 +portmap_40=80:10 +xgxs_rx_lane_map_37=0x123 +xgxs_tx_lane_map_37=0x1203 +phy_xaui_rx_polarity_flip_37=0x3 +phy_xaui_tx_polarity_flip_37=0xe +phy_xaui_rx_polarity_flip_38=0x1 +phy_xaui_tx_polarity_flip_38=0x1 +phy_xaui_rx_polarity_flip_39=0x0 +phy_xaui_tx_polarity_flip_39=0x1 +phy_xaui_rx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_40=0x1 +serdes_driver_current_lane0_37=0x2 +serdes_driver_current_lane1_37=0x2 +serdes_driver_current_lane2_37=0x2 +serdes_driver_current_lane3_37=0x2 +serdes_pre_driver_current_lane0_37=0x2 +serdes_pre_driver_current_lane1_37=0x2 +serdes_pre_driver_current_lane2_37=0x2 +serdes_pre_driver_current_lane3_37=0x2 +serdes_preemphasis_lane0_37=0xaf40 +serdes_preemphasis_lane1_37=0xaf40 +serdes_preemphasis_lane2_37=0xaf40 +serdes_preemphasis_lane3_37=0xaf40 + +# xe19 (4x10G) +portmap_41=73:10 +portmap_42=74:10 +portmap_43=75:10 +portmap_44=76:10 +xgxs_rx_lane_map_41=0x213 +xgxs_tx_lane_map_41=0x2031 +phy_xaui_rx_polarity_flip_41=0x1 +phy_xaui_tx_polarity_flip_41=0x0 +phy_xaui_rx_polarity_flip_42=0x0 +phy_xaui_tx_polarity_flip_42=0x0 +phy_xaui_rx_polarity_flip_43=0x0 +phy_xaui_tx_polarity_flip_43=0x0 +phy_xaui_rx_polarity_flip_44=0x0 +phy_xaui_tx_polarity_flip_44=0x0 +serdes_driver_current_lane0_41=0x2 +serdes_driver_current_lane1_41=0x2 +serdes_driver_current_lane2_41=0x2 +serdes_driver_current_lane3_41=0x2 +serdes_pre_driver_current_lane0_41=0x2 +serdes_pre_driver_current_lane1_41=0x2 +serdes_pre_driver_current_lane2_41=0x2 +serdes_pre_driver_current_lane3_41=0x2 +serdes_preemphasis_lane0_41=0xa760 +serdes_preemphasis_lane1_41=0xa760 +serdes_preemphasis_lane2_41=0xa760 +serdes_preemphasis_lane3_41=0xa760 + +# xe20 (4x10G) +portmap_45=105:10 +portmap_46=106:10 +portmap_47=107:10 +portmap_48=108:10 +xgxs_rx_lane_map_45=0x1320 +xgxs_tx_lane_map_45=0x3021 +phy_xaui_rx_polarity_flip_45=0xd +phy_xaui_tx_polarity_flip_45=0xb +phy_xaui_rx_polarity_flip_46=0x0 +phy_xaui_tx_polarity_flip_46=0x1 +phy_xaui_rx_polarity_flip_47=0x1 +phy_xaui_tx_polarity_flip_47=0x0 +phy_xaui_rx_polarity_flip_48=0x1 +phy_xaui_tx_polarity_flip_48=0x1 +serdes_driver_current_lane0_45=0x1 +serdes_driver_current_lane1_45=0x1 +serdes_driver_current_lane2_45=0x1 +serdes_driver_current_lane3_45=0x1 +serdes_pre_driver_current_lane0_45=0x1 +serdes_pre_driver_current_lane1_45=0x1 +serdes_pre_driver_current_lane2_45=0x1 +serdes_pre_driver_current_lane3_45=0x1 +serdes_preemphasis_lane0_45=0xb330 +serdes_preemphasis_lane1_45=0xb330 +serdes_preemphasis_lane2_45=0xb330 +serdes_preemphasis_lane3_45=0xb330 + +# xe21 (4x10G) +portmap_49=109:10 +portmap_50=110:10 +portmap_51=111:10 +portmap_52=112:10 +xgxs_rx_lane_map_49=0x132 +xgxs_tx_lane_map_49=0x132 +phy_xaui_rx_polarity_flip_49=0x8 +phy_xaui_tx_polarity_flip_49=0x0 +phy_xaui_rx_polarity_flip_50=0x0 +phy_xaui_tx_polarity_flip_50=0x0 +phy_xaui_rx_polarity_flip_51=0x0 +phy_xaui_tx_polarity_flip_51=0x0 +phy_xaui_rx_polarity_flip_52=0x1 +phy_xaui_tx_polarity_flip_52=0x0 +serdes_driver_current_lane0_49=0x1 +serdes_driver_current_lane1_49=0x1 +serdes_driver_current_lane2_49=0x1 +serdes_driver_current_lane3_49=0x2 +serdes_pre_driver_current_lane0_49=0x1 +serdes_pre_driver_current_lane1_49=0x1 +serdes_pre_driver_current_lane2_49=0x1 +serdes_pre_driver_current_lane3_49=0x2 +serdes_preemphasis_lane0_49=0xb330 +serdes_preemphasis_lane1_49=0xb330 +serdes_preemphasis_lane2_49=0xb330 +serdes_preemphasis_lane3_49=0xbff0 + +# xe22 (4x10G) +portmap_53=117:10 +portmap_54=118:10 +portmap_55=119:10 +portmap_56=120:10 +xgxs_rx_lane_map_53=0x231 +xgxs_tx_lane_map_53=0x1203 +phy_xaui_rx_polarity_flip_53=0x3 +phy_xaui_tx_polarity_flip_53=0xe +phy_xaui_rx_polarity_flip_54=0x1 +phy_xaui_tx_polarity_flip_54=0x1 +phy_xaui_rx_polarity_flip_55=0x0 +phy_xaui_tx_polarity_flip_55=0x1 +phy_xaui_rx_polarity_flip_56=0x0 +phy_xaui_tx_polarity_flip_56=0x1 +serdes_driver_current_lane0_53=0x3 +serdes_driver_current_lane1_53=0x5 +serdes_driver_current_lane2_53=0x3 +serdes_driver_current_lane3_53=0x3 +serdes_pre_driver_current_lane0_53=0x3 +serdes_pre_driver_current_lane1_53=0x5 +serdes_pre_driver_current_lane2_53=0x3 +serdes_pre_driver_current_lane3_53=0x3 +serdes_preemphasis_lane0_53=0xc6e0 +serdes_preemphasis_lane1_53=0xc6e0 +serdes_preemphasis_lane2_53=0xc6e0 +serdes_preemphasis_lane3_53=0xc6e0 + +# xe23 (4x10G) +portmap_57=113:10 +portmap_58=114:10 +portmap_59=115:10 +portmap_60=116:10 +xgxs_rx_lane_map_57=0x132 +xgxs_tx_lane_map_57=0x132 +phy_xaui_rx_polarity_flip_57=0x8 +phy_xaui_tx_polarity_flip_57=0x0 +phy_xaui_rx_polarity_flip_58=0x0 +phy_xaui_tx_polarity_flip_58=0x0 +phy_xaui_rx_polarity_flip_59=0x0 +phy_xaui_tx_polarity_flip_59=0x0 +phy_xaui_rx_polarity_flip_60=0x1 +phy_xaui_tx_polarity_flip_60=0x0 +serdes_driver_current_lane0_57=0x1 +serdes_driver_current_lane1_57=0x1 +serdes_driver_current_lane2_57=0x1 +serdes_driver_current_lane3_57=0x1 +serdes_pre_driver_current_lane0_57=0x1 +serdes_pre_driver_current_lane1_57=0x1 +serdes_pre_driver_current_lane2_57=0x1 +serdes_pre_driver_current_lane3_57=0x1 +serdes_preemphasis_lane0_57=0xbb10 +serdes_preemphasis_lane1_57=0xbb10 +serdes_preemphasis_lane2_57=0xbb10 +serdes_preemphasis_lane3_57=0xc2f0 + +# xe24 (40G) +portmap_61=121:40 +xgxs_rx_lane_map_61=0x1320 +xgxs_tx_lane_map_61=0x3021 +phy_xaui_rx_polarity_flip_61=0xd +phy_xaui_tx_polarity_flip_61=0xb +serdes_driver_current_lane0_61=0x4 +serdes_driver_current_lane1_61=0x4 +serdes_driver_current_lane2_61=0x4 +serdes_driver_current_lane3_61=0x4 +serdes_pre_driver_current_lane0_61=0x4 +serdes_pre_driver_current_lane1_61=0x4 +serdes_pre_driver_current_lane2_61=0x4 +serdes_pre_driver_current_lane3_61=0x4 +serdes_preemphasis_lane0_61=0xc6e0 +serdes_preemphasis_lane1_61=0xc6e0 +serdes_preemphasis_lane2_61=0xc6e0 +serdes_preemphasis_lane3_61=0xc6e0 + +# xe25 (40G) +portmap_62=125:40 +xgxs_rx_lane_map_62=0x132 +xgxs_tx_lane_map_62=0x132 +phy_xaui_rx_polarity_flip_62=0x8 +phy_xaui_tx_polarity_flip_62=0x0 +serdes_driver_current_lane0_62=0x4 +serdes_driver_current_lane1_62=0x4 +serdes_driver_current_lane2_62=0x4 +serdes_driver_current_lane3_62=0x4 +serdes_pre_driver_current_lane0_62=0x4 +serdes_pre_driver_current_lane1_62=0x4 +serdes_pre_driver_current_lane2_62=0x4 +serdes_pre_driver_current_lane3_62=0x4 +serdes_preemphasis_lane0_62=0xc6e0 +serdes_preemphasis_lane1_62=0xc6e0 +serdes_preemphasis_lane2_62=0xc6e0 +serdes_preemphasis_lane3_62=0xcec0 + +# xe26 (40G) +portmap_63=85:40 +xgxs_rx_lane_map_63=0x213 +xgxs_tx_lane_map_63=0x1203 +phy_xaui_rx_polarity_flip_63=0xc +phy_xaui_tx_polarity_flip_63=0xe +serdes_driver_current_lane0_63=0x4 +serdes_driver_current_lane1_63=0x5 +serdes_driver_current_lane2_63=0x4 +serdes_driver_current_lane3_63=0x5 +serdes_pre_driver_current_lane0_63=0x4 +serdes_pre_driver_current_lane1_63=0x5 +serdes_pre_driver_current_lane2_63=0x4 +serdes_pre_driver_current_lane3_63=0x5 +serdes_preemphasis_lane0_63=0xc2f0 +serdes_preemphasis_lane1_63=0xc6e0 +serdes_preemphasis_lane2_63=0xc6e0 +serdes_preemphasis_lane3_63=0xc6e0 + +# xe27 (40G) +portmap_64=81:40 +xgxs_rx_lane_map_64=0x1320 +xgxs_tx_lane_map_64=0x2031 +phy_xaui_rx_polarity_flip_64=0x1 +phy_xaui_tx_polarity_flip_64=0x2 +serdes_driver_current_lane0_64=0x2 +serdes_driver_current_lane1_64=0x2 +serdes_driver_current_lane2_64=0x2 +serdes_driver_current_lane3_64=0x2 +serdes_pre_driver_current_lane0_64=0x2 +serdes_pre_driver_current_lane1_64=0x2 +serdes_pre_driver_current_lane2_64=0x2 +serdes_pre_driver_current_lane3_64=0x2 +serdes_preemphasis_lane0_64=0xbb10 +serdes_preemphasis_lane1_64=0xbb10 +serdes_preemphasis_lane2_64=0xbf00 +serdes_preemphasis_lane3_64=0xbb10 + +# xe28 (40G) +portmap_65=89:40 +xgxs_rx_lane_map_65=0x1320 +xgxs_tx_lane_map_65=0x3021 +phy_xaui_rx_polarity_flip_65=0x2 +phy_xaui_tx_polarity_flip_65=0xb +serdes_driver_current_lane0_65=0x4 +serdes_driver_current_lane1_65=0x4 +serdes_driver_current_lane2_65=0x4 +serdes_driver_current_lane3_65=0x4 +serdes_pre_driver_current_lane0_65=0x4 +serdes_pre_driver_current_lane1_65=0x4 +serdes_pre_driver_current_lane2_65=0x4 +serdes_pre_driver_current_lane3_65=0x4 +serdes_preemphasis_lane0_65=0xcad0 +serdes_preemphasis_lane1_65=0xc6e0 +serdes_preemphasis_lane2_65=0xc6e0 +serdes_preemphasis_lane3_65=0xc6e0 + +# xe29 (40G) +portmap_66=93:40 +xgxs_rx_lane_map_66=0x1320 +xgxs_tx_lane_map_66=0x2031 +phy_xaui_rx_polarity_flip_66=0x1 +phy_xaui_tx_polarity_flip_66=0x2 +serdes_driver_current_lane0_66=0x4 +serdes_driver_current_lane1_66=0x4 +serdes_driver_current_lane2_66=0x4 +serdes_driver_current_lane3_66=0x4 +serdes_pre_driver_current_lane0_66=0x4 +serdes_pre_driver_current_lane1_66=0x4 +serdes_pre_driver_current_lane2_66=0x4 +serdes_pre_driver_current_lane3_66=0x4 +serdes_preemphasis_lane0_66=0xc2f0 +serdes_preemphasis_lane1_66=0xc2f0 +serdes_preemphasis_lane2_66=0xc2f0 +serdes_preemphasis_lane3_66=0xc2f0 + +# xe30 (40G) +portmap_67=97:40 +xgxs_rx_lane_map_67=0x213 +xgxs_tx_lane_map_67=0x2031 +phy_xaui_rx_polarity_flip_67=0xc +phy_xaui_tx_polarity_flip_67=0x3 +serdes_driver_current_lane0_67=0x5 +serdes_driver_current_lane1_67=0x5 +serdes_driver_current_lane2_67=0x5 +serdes_driver_current_lane3_67=0x5 +serdes_pre_driver_current_lane0_67=0x5 +serdes_pre_driver_current_lane1_67=0x5 +serdes_pre_driver_current_lane2_67=0x5 +serdes_pre_driver_current_lane3_67=0x5 +serdes_preemphasis_lane0_67=0xcad0 +serdes_preemphasis_lane1_67=0xcad0 +serdes_preemphasis_lane2_67=0xcad0 +serdes_preemphasis_lane3_67=0xcad0 + +# xe31 (40G) +portmap_68=101:40 +xgxs_rx_lane_map_68=0x1320 +xgxs_tx_lane_map_68=0x1203 +phy_xaui_rx_polarity_flip_68=0x1 +phy_xaui_tx_polarity_flip_68=0x6 +serdes_driver_current_lane0_68=0x6 +serdes_driver_current_lane1_68=0x6 +serdes_driver_current_lane2_68=0x6 +serdes_driver_current_lane3_68=0x7 +serdes_pre_driver_current_lane0_68=0x6 +serdes_pre_driver_current_lane1_68=0x6 +serdes_pre_driver_current_lane2_68=0x6 +serdes_pre_driver_current_lane3_68=0x7 +serdes_preemphasis_lane0_68=0xcec0 +serdes_preemphasis_lane1_68=0xcec0 +serdes_preemphasis_lane2_68=0xcad0 +serdes_preemphasis_lane3_68=0xc6e0 + diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/buffers.json.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/buffers.json.j2 new file mode 100755 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/buffers_defaults_t0.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/buffers_defaults_t0.j2 new file mode 100755 index 000000000000..9d37f8a579db --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/buffers_defaults_t0.j2 @@ -0,0 +1,55 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,16) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(16,25) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + + {% endfor %} + {% for port_idx in range(25,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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/buffers_defaults_t1.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/buffers_defaults_t1.j2 new file mode 100755 index 000000000000..9d37f8a579db --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/buffers_defaults_t1.j2 @@ -0,0 +1,55 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,16) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(16,25) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + + {% endfor %} + {% for port_idx in range(25,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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/pg_profile_lookup.ini b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/pg_profile_lookup.ini new file mode 100755 index 000000000000..9f2eacb6fc42 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/port_config.ini b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/port_config.ini new file mode 100755 index 000000000000..b238104455f7 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 29,30,31,32 fortyGigE0/0 0 40000 +Ethernet4 25,26,27,28 fortyGigE0/4 1 40000 +Ethernet8 37,38,39,40 fortyGigE0/8 2 40000 +Ethernet12 33,34,35,36 fortyGigE0/12 3 40000 +Ethernet16 41,42,43,44 fortyGigE0/16 4 40000 +Ethernet20 45,46,47,48 fortyGigE0/20 5 40000 +Ethernet24 5,6,7,8 fortyGigE0/24 6 40000 +Ethernet28 1,2,3,4 fortyGigE0/28 7 40000 +Ethernet32 9,10,11,12 fortyGigE0/32 8 40000 +Ethernet36 13,14,15,16 fortyGigE0/36 9 40000 +Ethernet40 21,22,23,24 fortyGigE0/40 10 40000 +Ethernet44 17,18,19,20 fortyGigE0/44 11 40000 +Ethernet48 49,50,51,52 fortyGigE0/48 12 40000 +Ethernet52 53,54,55,56 fortyGigE0/52 13 40000 +Ethernet56 61,62,63,64 fortyGigE0/56 14 40000 +Ethernet60 57,58,59,60 fortyGigE0/60 15 40000 +Ethernet64 65 tenGigE0/64 16 10000 +Ethernet65 66 tenGigE0/65 16 10000 +Ethernet66 67 tenGigE0/66 16 10000 +Ethernet67 68 tenGigE0/67 16 10000 +Ethernet68 69 tenGigE0/68 17 10000 +Ethernet69 70 tenGigE0/69 17 10000 +Ethernet70 71 tenGigE0/70 17 10000 +Ethernet71 72 tenGigE0/71 17 10000 +Ethernet72 77 tenGigE0/72 18 10000 +Ethernet73 78 tenGigE0/73 18 10000 +Ethernet74 79 tenGigE0/74 18 10000 +Ethernet75 80 tenGigE0/75 18 10000 +Ethernet76 73 tenGigE0/76 19 10000 +Ethernet77 74 tenGigE0/77 19 10000 +Ethernet78 75 tenGigE0/78 19 10000 +Ethernet79 76 tenGigE0/79 19 10000 +Ethernet80 105 tenGigE0/80 20 10000 +Ethernet81 106 tenGigE0/81 20 10000 +Ethernet82 107 tenGigE0/82 20 10000 +Ethernet83 108 tenGigE0/83 20 10000 +Ethernet84 109 tenGigE0/84 21 10000 +Ethernet85 110 tenGigE0/85 21 10000 +Ethernet86 111 tenGigE0/86 21 10000 +Ethernet87 112 tenGigE0/87 21 10000 +Ethernet88 117 tenGigE0/88 22 10000 +Ethernet89 118 tenGigE0/89 22 10000 +Ethernet90 119 tenGigE0/90 22 10000 +Ethernet91 120 tenGigE0/91 22 10000 +Ethernet92 113 tenGigE0/92 23 10000 +Ethernet93 114 tenGigE0/93 23 10000 +Ethernet94 115 tenGigE0/94 23 10000 +Ethernet95 116 tenGigE0/95 23 10000 +Ethernet96 121,122,123,124 fortyGigE0/96 24 40000 +Ethernet100 125,126,127,128 fortyGigE0/100 25 40000 +Ethernet104 85,86,87,88 fortyGigE0/104 26 40000 +Ethernet108 81,82,83,84 fortyGigE0/108 27 40000 +Ethernet112 89,90,91,92 fortyGigE0/112 28 40000 +Ethernet116 93,94,95,96 fortyGigE0/116 29 40000 +Ethernet120 97,98,99,100 fortyGigE0/120 30 40000 +Ethernet124 101,102,103,104 fortyGigE0/124 31 40000 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/qos.json.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/qos.json.j2 new file mode 100755 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/sai.profile b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/sai.profile new file mode 100755 index 000000000000..3335af4b9bf5 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-s6000-24x40G-32x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/td2-s6000-24x40G-32x10G.config.bcm b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/td2-s6000-24x40G-32x10G.config.bcm new file mode 100755 index 000000000000..5734e9ee5b1d --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q24S32/td2-s6000-24x40G-32x10G.config.bcm @@ -0,0 +1,719 @@ +# 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=10 +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=0x000001fffffffffffffffffffff +pbmp_xport_xe=0x000001fffffffffffffffffffff + +# Ports configuration +# xe0 (40G) +portmap_1=29:40 +xgxs_rx_lane_map_1=0x213 +xgxs_tx_lane_map_1=0x213 +phy_xaui_rx_polarity_flip_1=0xc +phy_xaui_tx_polarity_flip_1=0x9 +serdes_driver_current_lane0_1=0x6 +serdes_driver_current_lane1_1=0x7 +serdes_driver_current_lane2_1=0x6 +serdes_driver_current_lane3_1=0x6 +serdes_pre_driver_current_lane0_1=0x6 +serdes_pre_driver_current_lane1_1=0x7 +serdes_pre_driver_current_lane2_1=0x6 +serdes_pre_driver_current_lane3_1=0x6 +serdes_preemphasis_lane0_1=0xc2f0 +serdes_preemphasis_lane1_1=0xd2b0 +serdes_preemphasis_lane2_1=0xc6e0 +serdes_preemphasis_lane3_1=0xc2f0 + +# xe1 (40G) +portmap_2=25:40 +xgxs_rx_lane_map_2=0x213 +xgxs_tx_lane_map_2=0x2031 +phy_xaui_rx_polarity_flip_2=0xe +phy_xaui_tx_polarity_flip_2=0x2 +serdes_driver_current_lane0_2=0x5 +serdes_driver_current_lane1_2=0x5 +serdes_driver_current_lane2_2=0x5 +serdes_driver_current_lane3_2=0x5 +serdes_pre_driver_current_lane0_2=0x5 +serdes_pre_driver_current_lane1_2=0x5 +serdes_pre_driver_current_lane2_2=0x5 +serdes_pre_driver_current_lane3_2=0x5 +serdes_preemphasis_lane0_2=0xcad0 +serdes_preemphasis_lane1_2=0xc6e0 +serdes_preemphasis_lane2_2=0xc6e0 +serdes_preemphasis_lane3_2=0xd2b0 + +# xe2 (40G) +portmap_3=37:40 +xgxs_rx_lane_map_3=0x213 +xgxs_tx_lane_map_3=0x1203 +phy_xaui_rx_polarity_flip_3=0x3 +phy_xaui_tx_polarity_flip_3=0xe +serdes_driver_current_lane0_3=0x4 +serdes_driver_current_lane1_3=0x4 +serdes_driver_current_lane2_3=0x4 +serdes_driver_current_lane3_3=0x4 +serdes_pre_driver_current_lane0_3=0x4 +serdes_pre_driver_current_lane1_3=0x4 +serdes_pre_driver_current_lane2_3=0x4 +serdes_pre_driver_current_lane3_3=0x4 +serdes_preemphasis_lane0_3=0xcad0 +serdes_preemphasis_lane1_3=0xcad0 +serdes_preemphasis_lane2_3=0xc2f0 +serdes_preemphasis_lane3_3=0xc2f0 + +# xe3 (40G) +portmap_4=33:40 +xgxs_rx_lane_map_4=0x213 +xgxs_tx_lane_map_4=0x132 +phy_xaui_rx_polarity_flip_4=0xe +phy_xaui_tx_polarity_flip_4=0x2 +serdes_driver_current_lane0_4=0x4 +serdes_driver_current_lane1_4=0x4 +serdes_driver_current_lane2_4=0x4 +serdes_driver_current_lane3_4=0x4 +serdes_pre_driver_current_lane0_4=0x4 +serdes_pre_driver_current_lane1_4=0x4 +serdes_pre_driver_current_lane2_4=0x4 +serdes_pre_driver_current_lane3_4=0x4 +serdes_preemphasis_lane0_4=0xc6e0 +serdes_preemphasis_lane1_4=0xc6e0 +serdes_preemphasis_lane2_4=0xc6e0 +serdes_preemphasis_lane3_4=0xc6e0 + +# xe4 (40G) +portmap_5=41:40 +xgxs_rx_lane_map_5=0x213 +xgxs_tx_lane_map_5=0x3021 +phy_xaui_rx_polarity_flip_5=0x3 +phy_xaui_tx_polarity_flip_5=0xb +serdes_driver_current_lane0_5=0x4 +serdes_driver_current_lane1_5=0x4 +serdes_driver_current_lane2_5=0x4 +serdes_driver_current_lane3_5=0x4 +serdes_pre_driver_current_lane0_5=0x4 +serdes_pre_driver_current_lane1_5=0x4 +serdes_pre_driver_current_lane2_5=0x4 +serdes_pre_driver_current_lane3_5=0x4 +serdes_preemphasis_lane0_5=0xc6e0 +serdes_preemphasis_lane1_5=0xc2f0 +serdes_preemphasis_lane2_5=0xc2f0 +serdes_preemphasis_lane3_5=0xcad0 + +# xe5 (40G) +portmap_6=45:40 +xgxs_rx_lane_map_6=0x213 +xgxs_tx_lane_map_6=0x213 +phy_xaui_rx_polarity_flip_6=0xe +phy_xaui_tx_polarity_flip_6=0x8 +serdes_driver_current_lane0_6=0x4 +serdes_driver_current_lane1_6=0x4 +serdes_driver_current_lane2_6=0x4 +serdes_driver_current_lane3_6=0x4 +serdes_pre_driver_current_lane0_6=0x4 +serdes_pre_driver_current_lane1_6=0x4 +serdes_pre_driver_current_lane2_6=0x4 +serdes_pre_driver_current_lane3_6=0x4 +serdes_preemphasis_lane0_6=0xc2f0 +serdes_preemphasis_lane1_6=0xc2f0 +serdes_preemphasis_lane2_6=0xc2f0 +serdes_preemphasis_lane3_6=0xc2f0 + +# xe6 (40G) +portmap_7=5:40 +xgxs_rx_lane_map_7=0x213 +xgxs_tx_lane_map_7=0x1203 +phy_xaui_rx_polarity_flip_7=0xc +phy_xaui_tx_polarity_flip_7=0x1 +serdes_driver_current_lane0_7=0x4 +serdes_driver_current_lane1_7=0x4 +serdes_driver_current_lane2_7=0x4 +serdes_driver_current_lane3_7=0x4 +serdes_pre_driver_current_lane0_7=0x4 +serdes_pre_driver_current_lane1_7=0x4 +serdes_pre_driver_current_lane2_7=0x4 +serdes_pre_driver_current_lane3_7=0x4 +serdes_preemphasis_lane0_7=0xc6e0 +serdes_preemphasis_lane1_7=0xc6e0 +serdes_preemphasis_lane2_7=0xc6e0 +serdes_preemphasis_lane3_7=0xc6e0 + +# xe7 (40G) +portmap_8=1:40 +xgxs_rx_lane_map_8=0x213 +xgxs_tx_lane_map_8=0x2031 +phy_xaui_rx_polarity_flip_8=0xe +phy_xaui_tx_polarity_flip_8=0xd +serdes_driver_current_lane0_8=0x5 +serdes_driver_current_lane1_8=0x5 +serdes_driver_current_lane2_8=0x5 +serdes_driver_current_lane3_8=0x5 +serdes_pre_driver_current_lane0_8=0x5 +serdes_pre_driver_current_lane1_8=0x5 +serdes_pre_driver_current_lane2_8=0x5 +serdes_pre_driver_current_lane3_8=0x5 +serdes_preemphasis_lane0_8=0xc6e0 +serdes_preemphasis_lane1_8=0xcad0 +serdes_preemphasis_lane2_8=0xc6e0 +serdes_preemphasis_lane3_8=0xcad0 + +# xe9 (40G) +portmap_9=9:40 +xgxs_rx_lane_map_9=0x3120 +xgxs_tx_lane_map_9=0x3021 +phy_xaui_rx_polarity_flip_9=0x0 +phy_xaui_tx_polarity_flip_9=0x4 +serdes_driver_current_lane0_9=0x3 +serdes_driver_current_lane1_9=0x3 +serdes_driver_current_lane2_9=0x3 +serdes_driver_current_lane3_9=0x3 +serdes_pre_driver_current_lane0_9=0x3 +serdes_pre_driver_current_lane1_9=0x3 +serdes_pre_driver_current_lane2_9=0x3 +serdes_pre_driver_current_lane3_9=0x3 +serdes_preemphasis_lane0_9=0xc2f0 +serdes_preemphasis_lane1_9=0xc6e0 +serdes_preemphasis_lane2_9=0xbf00 +serdes_preemphasis_lane3_9=0xc2f0 + +# xe9 (40G) +portmap_10=13:40 +xgxs_rx_lane_map_10=0x213 +xgxs_tx_lane_map_10=0x132 +phy_xaui_rx_polarity_flip_10=0xe +phy_xaui_tx_polarity_flip_10=0x0 +serdes_driver_current_lane0_10=0x2 +serdes_driver_current_lane1_10=0x3 +serdes_driver_current_lane2_10=0x2 +serdes_driver_current_lane3_10=0x2 +serdes_pre_driver_current_lane0_10=0x2 +serdes_pre_driver_current_lane1_10=0x3 +serdes_pre_driver_current_lane2_10=0x2 +serdes_pre_driver_current_lane3_10=0x2 +serdes_preemphasis_lane0_10=0xb270 +serdes_preemphasis_lane1_10=0xbb10 +serdes_preemphasis_lane2_10=0xb720 +serdes_preemphasis_lane3_10=0xb720 + +# xe10 (40G) +portmap_11=21:40 +xgxs_rx_lane_map_11=0x123 +xgxs_tx_lane_map_11=0x1203 +phy_xaui_rx_polarity_flip_11=0xc +phy_xaui_tx_polarity_flip_11=0xe +serdes_driver_current_lane0_11=0x2 +serdes_driver_current_lane1_11=0x2 +serdes_driver_current_lane2_11=0x2 +serdes_driver_current_lane3_11=0x2 +serdes_pre_driver_current_lane0_11=0x2 +serdes_pre_driver_current_lane1_11=0x2 +serdes_pre_driver_current_lane2_11=0x2 +serdes_pre_driver_current_lane3_11=0x2 +serdes_preemphasis_lane0_11=0xb330 +serdes_preemphasis_lane1_11=0xb330 +serdes_preemphasis_lane2_11=0xb330 +serdes_preemphasis_lane3_11=0xb330 + +# xe11 (40G) +portmap_12=17:40 +xgxs_rx_lane_map_12=0x213 +xgxs_tx_lane_map_12=0x132 +phy_xaui_rx_polarity_flip_12=0xe +phy_xaui_tx_polarity_flip_12=0x0 +serdes_driver_current_lane0_12=0x2 +serdes_driver_current_lane1_12=0x2 +serdes_driver_current_lane2_12=0x2 +serdes_driver_current_lane3_12=0x2 +serdes_pre_driver_current_lane0_12=0x2 +serdes_pre_driver_current_lane1_12=0x2 +serdes_pre_driver_current_lane2_12=0x2 +serdes_pre_driver_current_lane3_12=0x2 +serdes_preemphasis_lane0_12=0xb330 +serdes_preemphasis_lane1_12=0xbb10 +serdes_preemphasis_lane2_12=0xbb10 +serdes_preemphasis_lane3_12=0xbb10 + +# xe12 (40G) +portmap_13=49:40 +xgxs_rx_lane_map_13=0x1302 +xgxs_tx_lane_map_13=0x2031 +phy_xaui_rx_polarity_flip_13=0xb +phy_xaui_tx_polarity_flip_13=0x3 +serdes_driver_current_lane0_13=0x2 +serdes_driver_current_lane1_13=0x2 +serdes_driver_current_lane2_13=0x2 +serdes_driver_current_lane3_13=0x2 +serdes_pre_driver_current_lane0_13=0x2 +serdes_pre_driver_current_lane1_13=0x2 +serdes_pre_driver_current_lane2_13=0x2 +serdes_pre_driver_current_lane3_13=0x2 +serdes_preemphasis_lane0_13=0xa760 +serdes_preemphasis_lane1_13=0xa760 +serdes_preemphasis_lane2_13=0xa760 +serdes_preemphasis_lane3_13=0xa760 + +# xe13 (40G) +portmap_14=53:40 +xgxs_rx_lane_map_14=0x213 +xgxs_tx_lane_map_14=0x231 +phy_xaui_rx_polarity_flip_14=0x1 +phy_xaui_tx_polarity_flip_14=0x0 +serdes_driver_current_lane0_14=0x2 +serdes_driver_current_lane1_14=0x2 +serdes_driver_current_lane2_14=0x2 +serdes_driver_current_lane3_14=0x2 +serdes_pre_driver_current_lane0_14=0x2 +serdes_pre_driver_current_lane1_14=0x2 +serdes_pre_driver_current_lane2_14=0x2 +serdes_pre_driver_current_lane3_14=0x2 +serdes_preemphasis_lane0_14=0xaf40 +serdes_preemphasis_lane1_14=0xaf40 +serdes_preemphasis_lane2_14=0xaf40 +serdes_preemphasis_lane3_14=0xaf40 + +# xe14 (40G) +portmap_15=61:40 +xgxs_rx_lane_map_15=0x132 +xgxs_tx_lane_map_15=0x213 +phy_xaui_rx_polarity_flip_15=0x0 +phy_xaui_tx_polarity_flip_15=0x0 +serdes_driver_current_lane0_15=0x2 +serdes_driver_current_lane1_15=0x2 +serdes_driver_current_lane2_15=0x2 +serdes_driver_current_lane3_15=0x2 +serdes_pre_driver_current_lane0_15=0x2 +serdes_pre_driver_current_lane1_15=0x2 +serdes_pre_driver_current_lane2_15=0x2 +serdes_pre_driver_current_lane3_15=0x2 +serdes_preemphasis_lane0_15=0xa760 +serdes_preemphasis_lane1_15=0xa760 +serdes_preemphasis_lane2_15=0xa760 +serdes_preemphasis_lane3_15=0xa760 + +# xe15 (40G) +portmap_16=57:40 +xgxs_rx_lane_map_16=0x213 +xgxs_tx_lane_map_16=0x2031 +phy_xaui_rx_polarity_flip_16=0x1 +phy_xaui_tx_polarity_flip_16=0x0 +serdes_driver_current_lane0_16=0x1 +serdes_driver_current_lane1_16=0x1 +serdes_driver_current_lane2_16=0x1 +serdes_driver_current_lane3_16=0x1 +serdes_pre_driver_current_lane0_16=0x1 +serdes_pre_driver_current_lane1_16=0x1 +serdes_pre_driver_current_lane2_16=0x1 +serdes_pre_driver_current_lane3_16=0x1 +serdes_preemphasis_lane0_16=0xa760 +serdes_preemphasis_lane1_16=0xa760 +serdes_preemphasis_lane2_16=0xa760 +serdes_preemphasis_lane3_16=0xa760 + +# xe16 (4x10G) +portmap_17=65:10 +portmap_18=66:10 +portmap_19=67:10 +portmap_20=68:10 +xgxs_rx_lane_map_17=0x132 +xgxs_tx_lane_map_17=0x2031 +phy_xaui_rx_polarity_flip_17=0x3 +phy_xaui_tx_polarity_flip_17=0x9 +phy_xaui_rx_polarity_flip_18=0x1 +phy_xaui_tx_polarity_flip_18=0x0 +phy_xaui_rx_polarity_flip_19=0x0 +phy_xaui_tx_polarity_flip_19=0x0 +phy_xaui_rx_polarity_flip_20=0x0 +phy_xaui_tx_polarity_flip_20=0x1 +serdes_driver_current_lane0_17=0x1 +serdes_driver_current_lane1_17=0x1 +serdes_driver_current_lane2_17=0x1 +serdes_driver_current_lane3_17=0x1 +serdes_pre_driver_current_lane0_17=0x1 +serdes_pre_driver_current_lane1_17=0x1 +serdes_pre_driver_current_lane2_17=0x1 +serdes_pre_driver_current_lane3_17=0x1 +serdes_preemphasis_lane0_17=0xa370 +serdes_preemphasis_lane1_17=0xa370 +serdes_preemphasis_lane2_17=0xa370 +serdes_preemphasis_lane3_17=0xa370 + +# xe17 (4x10G) +portmap_21=69:10 +portmap_22=70:10 +portmap_23=71:10 +portmap_24=72:10 +xgxs_rx_lane_map_21=0x213 +xgxs_tx_lane_map_21=0x2130 +phy_xaui_rx_polarity_flip_21=0x1 +phy_xaui_tx_polarity_flip_21=0xf +phy_xaui_rx_polarity_flip_22=0x0 +phy_xaui_tx_polarity_flip_22=0x1 +phy_xaui_rx_polarity_flip_23=0x0 +phy_xaui_tx_polarity_flip_23=0x1 +phy_xaui_rx_polarity_flip_24=0x0 +phy_xaui_tx_polarity_flip_24=0x1 +serdes_driver_current_lane0_21=0x1 +serdes_driver_current_lane1_21=0x1 +serdes_driver_current_lane2_21=0x1 +serdes_driver_current_lane3_21=0x1 +serdes_pre_driver_current_lane0_21=0x1 +serdes_pre_driver_current_lane1_21=0x1 +serdes_pre_driver_current_lane2_21=0x1 +serdes_pre_driver_current_lane3_21=0x1 +serdes_preemphasis_lane0_21=0xa760 +serdes_preemphasis_lane1_21=0xa760 +serdes_preemphasis_lane2_21=0xa760 +serdes_preemphasis_lane3_21=0xa760 + +# xe18 (4x10G) +portmap_25=77:10 +portmap_26=78:10 +portmap_27=79:10 +portmap_28=80:10 +xgxs_rx_lane_map_25=0x123 +xgxs_tx_lane_map_25=0x1203 +phy_xaui_rx_polarity_flip_25=0x3 +phy_xaui_tx_polarity_flip_25=0xe +phy_xaui_rx_polarity_flip_26=0x1 +phy_xaui_tx_polarity_flip_26=0x1 +phy_xaui_rx_polarity_flip_27=0x0 +phy_xaui_tx_polarity_flip_27=0x1 +phy_xaui_rx_polarity_flip_28=0x0 +phy_xaui_tx_polarity_flip_28=0x1 +serdes_driver_current_lane0_25=0x2 +serdes_driver_current_lane1_25=0x2 +serdes_driver_current_lane2_25=0x2 +serdes_driver_current_lane3_25=0x2 +serdes_pre_driver_current_lane0_25=0x2 +serdes_pre_driver_current_lane1_25=0x2 +serdes_pre_driver_current_lane2_25=0x2 +serdes_pre_driver_current_lane3_25=0x2 +serdes_preemphasis_lane0_25=0xaf40 +serdes_preemphasis_lane1_25=0xaf40 +serdes_preemphasis_lane2_25=0xaf40 +serdes_preemphasis_lane3_25=0xaf40 + +# xe19 (4x10G) +portmap_29=73:10 +portmap_30=74:10 +portmap_31=75:10 +portmap_32=76:10 +xgxs_rx_lane_map_29=0x213 +xgxs_tx_lane_map_29=0x2031 +phy_xaui_rx_polarity_flip_29=0x1 +phy_xaui_tx_polarity_flip_29=0x0 +phy_xaui_rx_polarity_flip_30=0x0 +phy_xaui_tx_polarity_flip_30=0x0 +phy_xaui_rx_polarity_flip_31=0x0 +phy_xaui_tx_polarity_flip_31=0x0 +phy_xaui_rx_polarity_flip_32=0x0 +phy_xaui_tx_polarity_flip_32=0x0 +serdes_driver_current_lane0_29=0x2 +serdes_driver_current_lane1_29=0x2 +serdes_driver_current_lane2_29=0x2 +serdes_driver_current_lane3_29=0x2 +serdes_pre_driver_current_lane0_29=0x2 +serdes_pre_driver_current_lane1_29=0x2 +serdes_pre_driver_current_lane2_29=0x2 +serdes_pre_driver_current_lane3_29=0x2 +serdes_preemphasis_lane0_29=0xa760 +serdes_preemphasis_lane1_29=0xa760 +serdes_preemphasis_lane2_29=0xa760 +serdes_preemphasis_lane3_29=0xa760 + +# xe20 (4x10G) +portmap_33=105:10 +portmap_34=106:10 +portmap_35=107:10 +portmap_36=108:10 +xgxs_rx_lane_map_33=0x1320 +xgxs_tx_lane_map_33=0x3021 +phy_xaui_rx_polarity_flip_33=0xd +phy_xaui_tx_polarity_flip_33=0xb +phy_xaui_rx_polarity_flip_34=0x0 +phy_xaui_tx_polarity_flip_34=0x1 +phy_xaui_rx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_35=0x0 +phy_xaui_rx_polarity_flip_36=0x1 +phy_xaui_tx_polarity_flip_36=0x1 +serdes_driver_current_lane0_33=0x1 +serdes_driver_current_lane1_33=0x1 +serdes_driver_current_lane2_33=0x1 +serdes_driver_current_lane3_33=0x1 +serdes_pre_driver_current_lane0_33=0x1 +serdes_pre_driver_current_lane1_33=0x1 +serdes_pre_driver_current_lane2_33=0x1 +serdes_pre_driver_current_lane3_33=0x1 +serdes_preemphasis_lane0_33=0xb330 +serdes_preemphasis_lane1_33=0xb330 +serdes_preemphasis_lane2_33=0xb330 +serdes_preemphasis_lane3_33=0xb330 + +# xe21 (4x10G) +portmap_37=109:10 +portmap_38=110:10 +portmap_39=111:10 +portmap_40=112:10 +xgxs_rx_lane_map_37=0x132 +xgxs_tx_lane_map_37=0x132 +phy_xaui_rx_polarity_flip_37=0x8 +phy_xaui_tx_polarity_flip_37=0x0 +phy_xaui_rx_polarity_flip_38=0x0 +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_rx_polarity_flip_39=0x0 +phy_xaui_tx_polarity_flip_39=0x0 +phy_xaui_rx_polarity_flip_40=0x1 +phy_xaui_tx_polarity_flip_40=0x0 +serdes_driver_current_lane0_37=0x1 +serdes_driver_current_lane1_37=0x1 +serdes_driver_current_lane2_37=0x1 +serdes_driver_current_lane3_37=0x2 +serdes_pre_driver_current_lane0_37=0x1 +serdes_pre_driver_current_lane1_37=0x1 +serdes_pre_driver_current_lane2_37=0x1 +serdes_pre_driver_current_lane3_37=0x2 +serdes_preemphasis_lane0_37=0xb330 +serdes_preemphasis_lane1_37=0xb330 +serdes_preemphasis_lane2_37=0xb330 +serdes_preemphasis_lane3_37=0xbff0 + +# xe22 (4x10G) +portmap_41=117:10 +portmap_42=118:10 +portmap_43=119:10 +portmap_44=120:10 +xgxs_rx_lane_map_41=0x231 +xgxs_tx_lane_map_41=0x1203 +phy_xaui_rx_polarity_flip_41=0x3 +phy_xaui_tx_polarity_flip_41=0xe +phy_xaui_rx_polarity_flip_42=0x1 +phy_xaui_tx_polarity_flip_42=0x1 +phy_xaui_rx_polarity_flip_43=0x0 +phy_xaui_tx_polarity_flip_43=0x1 +phy_xaui_rx_polarity_flip_44=0x0 +phy_xaui_tx_polarity_flip_44=0x1 +serdes_driver_current_lane0_41=0x3 +serdes_driver_current_lane1_41=0x5 +serdes_driver_current_lane2_41=0x3 +serdes_driver_current_lane3_41=0x3 +serdes_pre_driver_current_lane0_41=0x3 +serdes_pre_driver_current_lane1_41=0x5 +serdes_pre_driver_current_lane2_41=0x3 +serdes_pre_driver_current_lane3_41=0x3 +serdes_preemphasis_lane0_41=0xc6e0 +serdes_preemphasis_lane1_41=0xc6e0 +serdes_preemphasis_lane2_41=0xc6e0 +serdes_preemphasis_lane3_41=0xc6e0 + +# xe23 (40x10G) +portmap_45=113:10 +portmap_46=114:10 +portmap_47=115:10 +portmap_48=116:10 +xgxs_rx_lane_map_45=0x132 +xgxs_tx_lane_map_45=0x132 +phy_xaui_rx_polarity_flip_45=0x8 +phy_xaui_tx_polarity_flip_45=0x0 +phy_xaui_rx_polarity_flip_46=0x0 +phy_xaui_tx_polarity_flip_46=0x0 +phy_xaui_rx_polarity_flip_47=0x0 +phy_xaui_tx_polarity_flip_47=0x0 +phy_xaui_rx_polarity_flip_48=0x1 +phy_xaui_tx_polarity_flip_48=0x0 +serdes_driver_current_lane0_45=0x1 +serdes_driver_current_lane1_45=0x1 +serdes_driver_current_lane2_45=0x1 +serdes_driver_current_lane3_45=0x1 +serdes_pre_driver_current_lane0_45=0x1 +serdes_pre_driver_current_lane1_45=0x1 +serdes_pre_driver_current_lane2_45=0x1 +serdes_pre_driver_current_lane3_45=0x1 +serdes_preemphasis_lane0_45=0xbb10 +serdes_preemphasis_lane1_45=0xbb10 +serdes_preemphasis_lane2_45=0xbb10 +serdes_preemphasis_lane3_45=0xc2f0 + +# xe24 (40G) +portmap_49=121:40 +xgxs_rx_lane_map_49=0x1320 +xgxs_tx_lane_map_49=0x3021 +phy_xaui_rx_polarity_flip_49=0xd +phy_xaui_tx_polarity_flip_49=0xb +serdes_driver_current_lane0_49=0x4 +serdes_driver_current_lane1_49=0x4 +serdes_driver_current_lane2_49=0x4 +serdes_driver_current_lane3_49=0x4 +serdes_pre_driver_current_lane0_49=0x4 +serdes_pre_driver_current_lane1_49=0x4 +serdes_pre_driver_current_lane2_49=0x4 +serdes_pre_driver_current_lane3_49=0x4 +serdes_preemphasis_lane0_49=0xc6e0 +serdes_preemphasis_lane1_49=0xc6e0 +serdes_preemphasis_lane2_49=0xc6e0 +serdes_preemphasis_lane3_49=0xc6e0 + +# xe25 (40G) +portmap_50=125:40 +xgxs_rx_lane_map_50=0x132 +xgxs_tx_lane_map_50=0x132 +phy_xaui_rx_polarity_flip_50=0x8 +phy_xaui_tx_polarity_flip_50=0x0 +serdes_driver_current_lane0_50=0x4 +serdes_driver_current_lane1_50=0x4 +serdes_driver_current_lane2_50=0x4 +serdes_driver_current_lane3_50=0x4 +serdes_pre_driver_current_lane0_50=0x4 +serdes_pre_driver_current_lane1_50=0x4 +serdes_pre_driver_current_lane2_50=0x4 +serdes_pre_driver_current_lane3_50=0x4 +serdes_preemphasis_lane0_50=0xc6e0 +serdes_preemphasis_lane1_50=0xc6e0 +serdes_preemphasis_lane2_50=0xc6e0 +serdes_preemphasis_lane3_50=0xcec0 + +# xe26 (40G) +portmap_51=85:40 +xgxs_rx_lane_map_51=0x213 +xgxs_tx_lane_map_51=0x1203 +phy_xaui_rx_polarity_flip_51=0xc +phy_xaui_tx_polarity_flip_51=0xe +serdes_driver_current_lane0_51=0x4 +serdes_driver_current_lane1_51=0x5 +serdes_driver_current_lane2_51=0x4 +serdes_driver_current_lane3_51=0x5 +serdes_pre_driver_current_lane0_51=0x4 +serdes_pre_driver_current_lane1_51=0x5 +serdes_pre_driver_current_lane2_51=0x4 +serdes_pre_driver_current_lane3_51=0x5 +serdes_preemphasis_lane0_51=0xc2f0 +serdes_preemphasis_lane1_51=0xc6e0 +serdes_preemphasis_lane2_51=0xc6e0 +serdes_preemphasis_lane3_51=0xc6e0 + +# xe27 (40G) +portmap_52=81:40 +xgxs_rx_lane_map_52=0x1320 +xgxs_tx_lane_map_52=0x2031 +phy_xaui_rx_polarity_flip_52=0x1 +phy_xaui_tx_polarity_flip_52=0x2 +serdes_driver_current_lane0_52=0x2 +serdes_driver_current_lane1_52=0x2 +serdes_driver_current_lane2_52=0x2 +serdes_driver_current_lane3_52=0x2 +serdes_pre_driver_current_lane0_52=0x2 +serdes_pre_driver_current_lane1_52=0x2 +serdes_pre_driver_current_lane2_52=0x2 +serdes_pre_driver_current_lane3_52=0x2 +serdes_preemphasis_lane0_52=0xbb10 +serdes_preemphasis_lane1_52=0xbb10 +serdes_preemphasis_lane2_52=0xbf00 +serdes_preemphasis_lane3_52=0xbb10 + +# xe28 (40G) +portmap_53=89:40 +xgxs_rx_lane_map_53=0x1320 +xgxs_tx_lane_map_53=0x3021 +phy_xaui_rx_polarity_flip_53=0x2 +phy_xaui_tx_polarity_flip_53=0xb +serdes_driver_current_lane0_53=0x4 +serdes_driver_current_lane1_53=0x4 +serdes_driver_current_lane2_53=0x4 +serdes_driver_current_lane3_53=0x4 +serdes_pre_driver_current_lane0_53=0x4 +serdes_pre_driver_current_lane1_53=0x4 +serdes_pre_driver_current_lane2_53=0x4 +serdes_pre_driver_current_lane3_53=0x4 +serdes_preemphasis_lane0_53=0xcad0 +serdes_preemphasis_lane1_53=0xc6e0 +serdes_preemphasis_lane2_53=0xc6e0 +serdes_preemphasis_lane3_53=0xc6e0 + +# xe29 (40G) +portmap_54=93:40 +xgxs_rx_lane_map_54=0x1320 +xgxs_tx_lane_map_54=0x2031 +phy_xaui_rx_polarity_flip_54=0x1 +phy_xaui_tx_polarity_flip_54=0x2 +serdes_driver_current_lane0_54=0x4 +serdes_driver_current_lane1_54=0x4 +serdes_driver_current_lane2_54=0x4 +serdes_driver_current_lane3_54=0x4 +serdes_pre_driver_current_lane0_54=0x4 +serdes_pre_driver_current_lane1_54=0x4 +serdes_pre_driver_current_lane2_54=0x4 +serdes_pre_driver_current_lane3_54=0x4 +serdes_preemphasis_lane0_54=0xc2f0 +serdes_preemphasis_lane1_54=0xc2f0 +serdes_preemphasis_lane2_54=0xc2f0 +serdes_preemphasis_lane3_54=0xc2f0 + +# xe30 (40G) +portmap_55=97:40 +xgxs_rx_lane_map_55=0x213 +xgxs_tx_lane_map_55=0x2031 +phy_xaui_rx_polarity_flip_55=0xc +phy_xaui_tx_polarity_flip_55=0x3 +serdes_driver_current_lane0_55=0x5 +serdes_driver_current_lane1_55=0x5 +serdes_driver_current_lane2_55=0x5 +serdes_driver_current_lane3_55=0x5 +serdes_pre_driver_current_lane0_55=0x5 +serdes_pre_driver_current_lane1_55=0x5 +serdes_pre_driver_current_lane2_55=0x5 +serdes_pre_driver_current_lane3_55=0x5 +serdes_preemphasis_lane0_55=0xcad0 +serdes_preemphasis_lane1_55=0xcad0 +serdes_preemphasis_lane2_55=0xcad0 +serdes_preemphasis_lane3_55=0xcad0 + +# xe31 (40G) +portmap_56=101:40 +xgxs_rx_lane_map_56=0x1320 +xgxs_tx_lane_map_56=0x1203 +phy_xaui_rx_polarity_flip_56=0x1 +phy_xaui_tx_polarity_flip_56=0x6 +serdes_driver_current_lane0_56=0x6 +serdes_driver_current_lane1_56=0x6 +serdes_driver_current_lane2_56=0x6 +serdes_driver_current_lane3_56=0x7 +serdes_pre_driver_current_lane0_56=0x6 +serdes_pre_driver_current_lane1_56=0x6 +serdes_pre_driver_current_lane2_56=0x6 +serdes_pre_driver_current_lane3_56=0x7 +serdes_preemphasis_lane0_56=0xcec0 +serdes_preemphasis_lane1_56=0xcec0 +serdes_preemphasis_lane2_56=0xcad0 +serdes_preemphasis_lane3_56=0xc6e0 + diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/buffers.json.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/buffers.json.j2 new file mode 100755 index 000000000000..e6e9e844469b --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/buffers_defaults_t0.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/buffers_defaults_t0.j2 new file mode 100755 index 000000000000..b5a7336e0511 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/buffers_defaults_t0.j2 @@ -0,0 +1,78 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,1) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(1,2) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(2,3) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(3,4) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(4,5) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(5,6) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(6,7) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(7,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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/buffers_defaults_t1.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/buffers_defaults_t1.j2 new file mode 100755 index 000000000000..b5a7336e0511 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/buffers_defaults_t1.j2 @@ -0,0 +1,78 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,1) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(1,2) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(2,3) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(3,4) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(4,5) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(5,6) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} + {% for port_idx in range(6,7) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 1)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{% endif %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 3)) %}{% endif %} + {% endfor %} + {% for port_idx in range(7,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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/pg_profile_lookup.ini b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/pg_profile_lookup.ini new file mode 100755 index 000000000000..9f2eacb6fc42 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/port_config.ini b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/port_config.ini new file mode 100755 index 000000000000..5cf518be64a1 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/port_config.ini @@ -0,0 +1,45 @@ +# name lanes alias index speed +Ethernet0 29 tenGigE0/0 0 10000 +Ethernet1 30 tenGigE0/1 0 10000 +Ethernet2 31 tenGigE0/2 0 10000 +Ethernet3 32 tenGigE0/3 0 10000 +Ethernet4 25,26,27,28 fortyGigE0/4 1 40000 +Ethernet8 37 tenGigE0/8 2 10000 +Ethernet9 38 tenGigE0/9 2 10000 +Ethernet10 39 tenGigE0/10 2 10000 +Ethernet11 40 tenGigE0/11 2 10000 +Ethernet12 33,34,35,36 fortyGigE0/12 3 40000 +Ethernet16 41 tenGigE0/16 4 10000 +Ethernet17 42 tenGigE0/17 4 10000 +Ethernet18 43 tenGigE0/18 4 10000 +Ethernet19 44 tenGigE0/19 4 10000 +Ethernet20 45,46,47,48 fortyGigE0/20 5 40000 +Ethernet24 5 tenGigE0/24 6 10000 +Ethernet25 6 tenGigE0/25 6 10000 +Ethernet26 7 tenGigE0/26 6 10000 +Ethernet27 8 tenGigE0/27 6 10000 +Ethernet28 1,2,3,4 fortyGigE0/28 7 40000 +Ethernet32 9,10,11,12 fortyGigE0/32 8 40000 +Ethernet36 13,14,15,16 fortyGigE0/36 9 40000 +Ethernet40 21,22,23,24 fortyGigE0/40 10 40000 +Ethernet44 17,18,19,20 fortyGigE0/44 11 40000 +Ethernet48 49,50,51,52 fortyGigE0/48 12 40000 +Ethernet52 53,54,55,56 fortyGigE0/52 13 40000 +Ethernet56 61,62,63,64 fortyGigE0/56 14 40000 +Ethernet60 57,58,59,60 fortyGigE0/60 15 40000 +Ethernet64 65,66,67,68 fortyGigE0/64 16 40000 +Ethernet68 69,70,71,72 fortyGigE0/68 17 40000 +Ethernet72 77,78,79,80 fortyGigE0/72 18 40000 +Ethernet76 73,74,75,76 fortyGigE0/76 19 40000 +Ethernet80 105,106,107,108 fortyGigE0/80 20 40000 +Ethernet84 109,110,111,112 fortyGigE0/84 21 40000 +Ethernet88 117,118,119,120 fortyGigE0/88 22 40000 +Ethernet92 113,114,115,116 fortyGigE0/92 23 40000 +Ethernet96 121,122,123,124 fortyGigE0/96 24 40000 +Ethernet100 125,126,127,128 fortyGigE0/100 25 40000 +Ethernet104 85,86,87,88 fortyGigE0/104 26 40000 +Ethernet108 81,82,83,84 fortyGigE0/108 27 40000 +Ethernet112 89,90,91,92 fortyGigE0/112 28 40000 +Ethernet116 93,94,95,96 fortyGigE0/116 29 40000 +Ethernet120 97,98,99,100 fortyGigE0/120 30 40000 +Ethernet124 101,102,103,104 fortyGigE0/124 31 40000 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/qos.json.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/qos.json.j2 new file mode 100755 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/sai.profile b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/sai.profile new file mode 100755 index 000000000000..394d163e30c3 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-s6000-28x40G-16x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/td2-s6000-28x40G-16x10G.config.bcm b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/td2-s6000-28x40G-16x10G.config.bcm new file mode 100755 index 000000000000..e0ebfd96f00b --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q28S16/td2-s6000-28x40G-16x10G.config.bcm @@ -0,0 +1,683 @@ +# 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=10 +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=0x0000000000000000000001fffffffffff +pbmp_xport_xe=0x0000000000000000000001fffffffffff + + +# Ports configuration +# xe0 (4x10G) +portmap_1=29:10 +portmap_2=30:10 +portmap_3=31:10 +portmap_4=32:10 +xgxs_rx_lane_map_1=0x213 +xgxs_tx_lane_map_1=0x213 +phy_xaui_rx_polarity_flip_1=0xc +phy_xaui_tx_polarity_flip_1=0x9 +phy_xaui_rx_polarity_flip_2=0x0 +phy_xaui_tx_polarity_flip_2=0x0 +phy_xaui_rx_polarity_flip_3=0x1 +phy_xaui_tx_polarity_flip_3=0x0 +phy_xaui_rx_polarity_flip_4=0x1 +phy_xaui_tx_polarity_flip_4=0x1 +serdes_driver_current_lane0_1=0x6 +serdes_driver_current_lane1_1=0x7 +serdes_driver_current_lane2_1=0x6 +serdes_driver_current_lane3_1=0x6 +serdes_pre_driver_current_lane0_1=0x6 +serdes_pre_driver_current_lane1_1=0x7 +serdes_pre_driver_current_lane2_1=0x6 +serdes_pre_driver_current_lane3_1=0x6 +serdes_preemphasis_lane0_1=0xc2f0 +serdes_preemphasis_lane1_1=0xd2b0 +serdes_preemphasis_lane2_1=0xc6e0 +serdes_preemphasis_lane3_1=0xc2f0 + +# xe1 (40G) +portmap_5=25:40 +xgxs_rx_lane_map_5=0x213 +xgxs_tx_lane_map_5=0x2031 +phy_xaui_rx_polarity_flip_5=0xe +phy_xaui_tx_polarity_flip_5=0x2 +serdes_driver_current_lane0_5=0x5 +serdes_driver_current_lane1_5=0x5 +serdes_driver_current_lane2_5=0x5 +serdes_driver_current_lane3_5=0x5 +serdes_pre_driver_current_lane0_5=0x5 +serdes_pre_driver_current_lane1_5=0x5 +serdes_pre_driver_current_lane2_5=0x5 +serdes_pre_driver_current_lane3_5=0x5 +serdes_preemphasis_lane0_5=0xcad0 +serdes_preemphasis_lane1_5=0xc6e0 +serdes_preemphasis_lane2_5=0xc6e0 +serdes_preemphasis_lane3_5=0xd2b0 + +# xe2 (4x10G) +portmap_6=37:10 +portmap_7=38:10 +portmap_8=39:10 +portmap_9=40:10 +xgxs_rx_lane_map_6=0x213 +xgxs_tx_lane_map_6=0x1203 +phy_xaui_rx_polarity_flip_6=0x3 +phy_xaui_tx_polarity_flip_6=0xe +phy_xaui_rx_polarity_flip_7=0x1 +phy_xaui_tx_polarity_flip_7=0x1 +phy_xaui_rx_polarity_flip_8=0x0 +phy_xaui_tx_polarity_flip_8=0x1 +phy_xaui_rx_polarity_flip_9=0x0 +phy_xaui_tx_polarity_flip_9=0x1 +serdes_driver_current_lane0_6=0x4 +serdes_driver_current_lane1_6=0x4 +serdes_driver_current_lane2_6=0x4 +serdes_driver_current_lane3_6=0x4 +serdes_pre_driver_current_lane0_6=0x4 +serdes_pre_driver_current_lane1_6=0x4 +serdes_pre_driver_current_lane2_6=0x4 +serdes_pre_driver_current_lane3_6=0x4 +serdes_preemphasis_lane0_6=0xcad0 +serdes_preemphasis_lane1_6=0xcad0 +serdes_preemphasis_lane2_6=0xc2f0 +serdes_preemphasis_lane3_6=0xc2f0 + +# xe3 (40G) +portmap_10=33:40 +xgxs_rx_lane_map_10=0x213 +xgxs_tx_lane_map_10=0x132 +phy_xaui_rx_polarity_flip_10=0xe +phy_xaui_tx_polarity_flip_10=0x2 +serdes_driver_current_lane0_10=0x4 +serdes_driver_current_lane1_10=0x4 +serdes_driver_current_lane2_10=0x4 +serdes_driver_current_lane3_10=0x4 +serdes_pre_driver_current_lane0_10=0x4 +serdes_pre_driver_current_lane1_10=0x4 +serdes_pre_driver_current_lane2_10=0x4 +serdes_pre_driver_current_lane3_10=0x4 +serdes_preemphasis_lane0_10=0xc6e0 +serdes_preemphasis_lane1_10=0xc6e0 +serdes_preemphasis_lane2_10=0xc6e0 +serdes_preemphasis_lane3_10=0xc6e0 + +# xe4 (4x10G) +portmap_11=41:10 +portmap_12=42:10 +portmap_13=43:10 +portmap_14=44:10 +xgxs_rx_lane_map_11=0x213 +xgxs_tx_lane_map_11=0x3021 +phy_xaui_rx_polarity_flip_11=0x3 +phy_xaui_tx_polarity_flip_11=0xb +phy_xaui_rx_polarity_flip_12=0x1 +phy_xaui_tx_polarity_flip_12=0x1 +phy_xaui_rx_polarity_flip_13=0x0 +phy_xaui_tx_polarity_flip_13=0x0 +phy_xaui_rx_polarity_flip_14=0x0 +phy_xaui_tx_polarity_flip_14=0x1 +serdes_driver_current_lane0_11=0x4 +serdes_driver_current_lane1_11=0x4 +serdes_driver_current_lane2_11=0x4 +serdes_driver_current_lane3_11=0x4 +serdes_pre_driver_current_lane0_11=0x4 +serdes_pre_driver_current_lane1_11=0x4 +serdes_pre_driver_current_lane2_11=0x4 +serdes_pre_driver_current_lane3_11=0x4 +serdes_preemphasis_lane0_11=0xc6e0 +serdes_preemphasis_lane1_11=0xc2f0 +serdes_preemphasis_lane2_11=0xc2f0 +serdes_preemphasis_lane3_11=0xcad0 + +# xe5 (40G) +portmap_15=45:40 +xgxs_rx_lane_map_15=0x213 +xgxs_tx_lane_map_15=0x213 +phy_xaui_rx_polarity_flip_15=0xe +phy_xaui_tx_polarity_flip_15=0x8 +serdes_driver_current_lane0_15=0x4 +serdes_driver_current_lane1_15=0x4 +serdes_driver_current_lane2_15=0x4 +serdes_driver_current_lane3_15=0x4 +serdes_pre_driver_current_lane0_15=0x4 +serdes_pre_driver_current_lane1_15=0x4 +serdes_pre_driver_current_lane2_15=0x4 +serdes_pre_driver_current_lane3_15=0x4 +serdes_preemphasis_lane0_15=0xc2f0 +serdes_preemphasis_lane1_15=0xc2f0 +serdes_preemphasis_lane2_15=0xc2f0 +serdes_preemphasis_lane3_15=0xc2f0 + +# xe6 (4x10G) +portmap_16=5:10 +portmap_17=6:10 +portmap_18=7:10 +portmap_19=8:10 +xgxs_rx_lane_map_16=0x213 +xgxs_tx_lane_map_16=0x1203 +phy_xaui_rx_polarity_flip_16=0xc +phy_xaui_tx_polarity_flip_16=0x1 +phy_xaui_rx_polarity_flip_17=0x0 +phy_xaui_tx_polarity_flip_17=0x0 +phy_xaui_rx_polarity_flip_18=0x1 +phy_xaui_tx_polarity_flip_18=0x0 +phy_xaui_rx_polarity_flip_19=0x1 +phy_xaui_tx_polarity_flip_19=0x0 +serdes_driver_current_lane0_16=0x4 +serdes_driver_current_lane1_16=0x4 +serdes_driver_current_lane2_16=0x4 +serdes_driver_current_lane3_16=0x4 +serdes_pre_driver_current_lane0_16=0x4 +serdes_pre_driver_current_lane1_16=0x4 +serdes_pre_driver_current_lane2_16=0x4 +serdes_pre_driver_current_lane3_16=0x4 +serdes_preemphasis_lane0_16=0xc6e0 +serdes_preemphasis_lane1_16=0xc6e0 +serdes_preemphasis_lane2_16=0xc6e0 +serdes_preemphasis_lane3_16=0xc6e0 + +# xe7 (40G) +portmap_20=1:40 +xgxs_rx_lane_map_20=0x213 +xgxs_tx_lane_map_20=0x2031 +phy_xaui_rx_polarity_flip_20=0xe +phy_xaui_tx_polarity_flip_20=0xd +serdes_driver_current_lane0_20=0x5 +serdes_driver_current_lane1_20=0x5 +serdes_driver_current_lane2_20=0x5 +serdes_driver_current_lane3_20=0x5 +serdes_pre_driver_current_lane0_20=0x5 +serdes_pre_driver_current_lane1_20=0x5 +serdes_pre_driver_current_lane2_20=0x5 +serdes_pre_driver_current_lane3_20=0x5 +serdes_preemphasis_lane0_20=0xc6e0 +serdes_preemphasis_lane1_20=0xcad0 +serdes_preemphasis_lane2_20=0xc6e0 +serdes_preemphasis_lane3_20=0xcad0 + +# xe8 (40G) +portmap_21=9:40 +xgxs_rx_lane_map_21=0x3120 +xgxs_tx_lane_map_21=0x3021 +phy_xaui_rx_polarity_flip_21=0x0 +phy_xaui_tx_polarity_flip_21=0x4 +serdes_driver_current_lane0_21=0x3 +serdes_driver_current_lane1_21=0x3 +serdes_driver_current_lane2_21=0x3 +serdes_driver_current_lane3_21=0x3 +serdes_pre_driver_current_lane0_21=0x3 +serdes_pre_driver_current_lane1_21=0x3 +serdes_pre_driver_current_lane2_21=0x3 +serdes_pre_driver_current_lane3_21=0x3 +serdes_preemphasis_lane0_21=0xc2f0 +serdes_preemphasis_lane1_21=0xc6e0 +serdes_preemphasis_lane2_21=0xbf00 +serdes_preemphasis_lane3_21=0xc2f0 + +# xe9 (40G) +portmap_22=13:40 +xgxs_rx_lane_map_22=0x213 +xgxs_tx_lane_map_22=0x132 +phy_xaui_rx_polarity_flip_22=0xe +phy_xaui_tx_polarity_flip_22=0x0 +serdes_driver_current_lane0_22=0x2 +serdes_driver_current_lane1_22=0x3 +serdes_driver_current_lane2_22=0x2 +serdes_driver_current_lane3_22=0x2 +serdes_pre_driver_current_lane0_22=0x2 +serdes_pre_driver_current_lane1_22=0x3 +serdes_pre_driver_current_lane2_22=0x2 +serdes_pre_driver_current_lane3_22=0x2 +serdes_preemphasis_lane0_22=0xb270 +serdes_preemphasis_lane1_22=0xbb10 +serdes_preemphasis_lane2_22=0xb720 +serdes_preemphasis_lane3_22=0xb720 + +# xe10 (40G) +portmap_23=21:40 +xgxs_rx_lane_map_23=0x123 +xgxs_tx_lane_map_23=0x1203 +phy_xaui_rx_polarity_flip_23=0xc +phy_xaui_tx_polarity_flip_23=0xe +serdes_driver_current_lane0_23=0x2 +serdes_driver_current_lane1_23=0x2 +serdes_driver_current_lane2_23=0x2 +serdes_driver_current_lane3_23=0x2 +serdes_pre_driver_current_lane0_23=0x2 +serdes_pre_driver_current_lane1_23=0x2 +serdes_pre_driver_current_lane2_23=0x2 +serdes_pre_driver_current_lane3_23=0x2 +serdes_preemphasis_lane0_23=0xb330 +serdes_preemphasis_lane1_23=0xb330 +serdes_preemphasis_lane2_23=0xb330 +serdes_preemphasis_lane3_23=0xb330 + +# xe11 (40G) +portmap_24=17:40 +xgxs_rx_lane_map_24=0x213 +xgxs_tx_lane_map_24=0x132 +phy_xaui_rx_polarity_flip_24=0xe +phy_xaui_tx_polarity_flip_24=0x0 +serdes_driver_current_lane0_24=0x2 +serdes_driver_current_lane1_24=0x2 +serdes_driver_current_lane2_24=0x2 +serdes_driver_current_lane3_24=0x2 +serdes_pre_driver_current_lane0_24=0x2 +serdes_pre_driver_current_lane1_24=0x2 +serdes_pre_driver_current_lane2_24=0x2 +serdes_pre_driver_current_lane3_24=0x2 +serdes_preemphasis_lane0_24=0xb330 +serdes_preemphasis_lane1_24=0xbb10 +serdes_preemphasis_lane2_24=0xbb10 +serdes_preemphasis_lane3_24=0xbb10 + +# xe12 (40G) +portmap_25=49:40 +xgxs_rx_lane_map_25=0x1302 +xgxs_tx_lane_map_25=0x2031 +phy_xaui_rx_polarity_flip_25=0xb +phy_xaui_tx_polarity_flip_25=0x3 +serdes_driver_current_lane0_25=0x2 +serdes_driver_current_lane1_25=0x2 +serdes_driver_current_lane2_25=0x2 +serdes_driver_current_lane3_25=0x2 +serdes_pre_driver_current_lane0_25=0x2 +serdes_pre_driver_current_lane1_25=0x2 +serdes_pre_driver_current_lane2_25=0x2 +serdes_pre_driver_current_lane3_25=0x2 +serdes_preemphasis_lane0_25=0xa760 +serdes_preemphasis_lane1_25=0xa760 +serdes_preemphasis_lane2_25=0xa760 +serdes_preemphasis_lane3_25=0xa760 + +# xe13 (40G) +portmap_26=53:40 +xgxs_rx_lane_map_26=0x213 +xgxs_tx_lane_map_26=0x231 +phy_xaui_rx_polarity_flip_26=0x1 +phy_xaui_tx_polarity_flip_26=0x0 +serdes_driver_current_lane0_26=0x2 +serdes_driver_current_lane1_26=0x2 +serdes_driver_current_lane2_26=0x2 +serdes_driver_current_lane3_26=0x2 +serdes_pre_driver_current_lane0_26=0x2 +serdes_pre_driver_current_lane1_26=0x2 +serdes_pre_driver_current_lane2_26=0x2 +serdes_pre_driver_current_lane3_26=0x2 +serdes_preemphasis_lane0_26=0xaf40 +serdes_preemphasis_lane1_26=0xaf40 +serdes_preemphasis_lane2_26=0xaf40 +serdes_preemphasis_lane3_26=0xaf40 + +# xe14 (40G) +portmap_27=61:40 +xgxs_rx_lane_map_27=0x132 +xgxs_tx_lane_map_27=0x213 +phy_xaui_rx_polarity_flip_27=0x0 +phy_xaui_tx_polarity_flip_27=0x0 +serdes_driver_current_lane0_27=0x2 +serdes_driver_current_lane1_27=0x2 +serdes_driver_current_lane2_27=0x2 +serdes_driver_current_lane3_27=0x2 +serdes_pre_driver_current_lane0_27=0x2 +serdes_pre_driver_current_lane1_27=0x2 +serdes_pre_driver_current_lane2_27=0x2 +serdes_pre_driver_current_lane3_27=0x2 +serdes_preemphasis_lane0_27=0xa760 +serdes_preemphasis_lane1_27=0xa760 +serdes_preemphasis_lane2_27=0xa760 +serdes_preemphasis_lane3_27=0xa760 + +# xe15 (40G) +portmap_28=57:40 +xgxs_rx_lane_map_28=0x213 +xgxs_tx_lane_map_28=0x2031 +phy_xaui_rx_polarity_flip_28=0x1 +phy_xaui_tx_polarity_flip_28=0x0 +serdes_driver_current_lane0_28=0x1 +serdes_driver_current_lane1_28=0x1 +serdes_driver_current_lane2_28=0x1 +serdes_driver_current_lane3_28=0x1 +serdes_pre_driver_current_lane0_28=0x1 +serdes_pre_driver_current_lane1_28=0x1 +serdes_pre_driver_current_lane2_28=0x1 +serdes_pre_driver_current_lane3_28=0x1 +serdes_preemphasis_lane0_28=0xa760 +serdes_preemphasis_lane1_28=0xa760 +serdes_preemphasis_lane2_28=0xa760 +serdes_preemphasis_lane3_28=0xa760 + +# xe16 (40G) +portmap_29=65:40 +xgxs_rx_lane_map_29=0x132 +xgxs_tx_lane_map_29=0x2031 +phy_xaui_rx_polarity_flip_29=0x3 +phy_xaui_tx_polarity_flip_29=0x9 +serdes_driver_current_lane0_29=0x1 +serdes_driver_current_lane1_29=0x1 +serdes_driver_current_lane2_29=0x1 +serdes_driver_current_lane3_29=0x1 +serdes_pre_driver_current_lane0_29=0x1 +serdes_pre_driver_current_lane1_29=0x1 +serdes_pre_driver_current_lane2_29=0x1 +serdes_pre_driver_current_lane3_29=0x1 +serdes_preemphasis_lane0_29=0xa370 +serdes_preemphasis_lane1_29=0xa370 +serdes_preemphasis_lane2_29=0xa370 +serdes_preemphasis_lane3_29=0xa370 + +# xe17 (40G) +portmap_30=69:40 +xgxs_rx_lane_map_30=0x213 +xgxs_tx_lane_map_30=0x2130 +phy_xaui_rx_polarity_flip_30=0x1 +phy_xaui_tx_polarity_flip_30=0xf +serdes_driver_current_lane0_30=0x1 +serdes_driver_current_lane1_30=0x1 +serdes_driver_current_lane2_30=0x1 +serdes_driver_current_lane3_30=0x1 +serdes_pre_driver_current_lane0_30=0x1 +serdes_pre_driver_current_lane1_30=0x1 +serdes_pre_driver_current_lane2_30=0x1 +serdes_pre_driver_current_lane3_30=0x1 +serdes_preemphasis_lane0_30=0xa760 +serdes_preemphasis_lane1_30=0xa760 +serdes_preemphasis_lane2_30=0xa760 +serdes_preemphasis_lane3_30=0xa760 + +# xe18 (40G) +portmap_31=77:40 +xgxs_rx_lane_map_31=0x123 +xgxs_tx_lane_map_31=0x1203 +phy_xaui_rx_polarity_flip_31=0x3 +phy_xaui_tx_polarity_flip_31=0xe +serdes_driver_current_lane0_31=0x2 +serdes_driver_current_lane1_31=0x2 +serdes_driver_current_lane2_31=0x2 +serdes_driver_current_lane3_31=0x2 +serdes_pre_driver_current_lane0_31=0x2 +serdes_pre_driver_current_lane1_31=0x2 +serdes_pre_driver_current_lane2_31=0x2 +serdes_pre_driver_current_lane3_31=0x2 +serdes_preemphasis_lane0_31=0xaf40 +serdes_preemphasis_lane1_31=0xaf40 +serdes_preemphasis_lane2_31=0xaf40 +serdes_preemphasis_lane3_31=0xaf40 + +# xe19 (40G) +portmap_32=73:40 +xgxs_rx_lane_map_32=0x213 +xgxs_tx_lane_map_32=0x2031 +phy_xaui_rx_polarity_flip_32=0x1 +phy_xaui_tx_polarity_flip_32=0x0 +serdes_driver_current_lane0_32=0x2 +serdes_driver_current_lane1_32=0x2 +serdes_driver_current_lane2_32=0x2 +serdes_driver_current_lane3_32=0x2 +serdes_pre_driver_current_lane0_32=0x2 +serdes_pre_driver_current_lane1_32=0x2 +serdes_pre_driver_current_lane2_32=0x2 +serdes_pre_driver_current_lane3_32=0x2 +serdes_preemphasis_lane0_32=0xa760 +serdes_preemphasis_lane1_32=0xa760 +serdes_preemphasis_lane2_32=0xa760 +serdes_preemphasis_lane3_32=0xa760 + +# xe20 (40G) +portmap_33=105:40 +xgxs_rx_lane_map_33=0x1320 +xgxs_tx_lane_map_33=0x3021 +phy_xaui_rx_polarity_flip_33=0xd +phy_xaui_tx_polarity_flip_33=0xb +serdes_driver_current_lane0_33=0x1 +serdes_driver_current_lane1_33=0x1 +serdes_driver_current_lane2_33=0x1 +serdes_driver_current_lane3_33=0x1 +serdes_pre_driver_current_lane0_33=0x1 +serdes_pre_driver_current_lane1_33=0x1 +serdes_pre_driver_current_lane2_33=0x1 +serdes_pre_driver_current_lane3_33=0x1 +serdes_preemphasis_lane0_33=0xb330 +serdes_preemphasis_lane1_33=0xb330 +serdes_preemphasis_lane2_33=0xb330 +serdes_preemphasis_lane3_33=0xb330 + +# xe21 (40G) +portmap_34=109:40 +xgxs_rx_lane_map_34=0x132 +xgxs_tx_lane_map_34=0x132 +phy_xaui_rx_polarity_flip_34=0x8 +phy_xaui_tx_polarity_flip_34=0x0 +serdes_driver_current_lane0_34=0x1 +serdes_driver_current_lane1_34=0x1 +serdes_driver_current_lane2_34=0x1 +serdes_driver_current_lane3_34=0x2 +serdes_pre_driver_current_lane0_34=0x1 +serdes_pre_driver_current_lane1_34=0x1 +serdes_pre_driver_current_lane2_34=0x1 +serdes_pre_driver_current_lane3_34=0x2 +serdes_preemphasis_lane0_34=0xb330 +serdes_preemphasis_lane1_34=0xb330 +serdes_preemphasis_lane2_34=0xb330 +serdes_preemphasis_lane3_34=0xbff0 + +# xe22 (40G) +portmap_35=117:40 +xgxs_rx_lane_map_35=0x231 +xgxs_tx_lane_map_35=0x1203 +phy_xaui_rx_polarity_flip_35=0x3 +phy_xaui_tx_polarity_flip_35=0xe +serdes_driver_current_lane0_35=0x3 +serdes_driver_current_lane1_35=0x5 +serdes_driver_current_lane2_35=0x3 +serdes_driver_current_lane3_35=0x3 +serdes_pre_driver_current_lane0_35=0x3 +serdes_pre_driver_current_lane1_35=0x5 +serdes_pre_driver_current_lane2_35=0x3 +serdes_pre_driver_current_lane3_35=0x3 +serdes_preemphasis_lane0_35=0xc6e0 +serdes_preemphasis_lane1_35=0xc6e0 +serdes_preemphasis_lane2_35=0xc6e0 +serdes_preemphasis_lane3_35=0xc6e0 + +# xe23 (40G) +portmap_36=113:40 +xgxs_rx_lane_map_36=0x132 +xgxs_tx_lane_map_36=0x132 +phy_xaui_rx_polarity_flip_36=0x8 +phy_xaui_tx_polarity_flip_36=0x0 +serdes_driver_current_lane0_36=0x1 +serdes_driver_current_lane1_36=0x1 +serdes_driver_current_lane2_36=0x1 +serdes_driver_current_lane3_36=0x1 +serdes_pre_driver_current_lane0_36=0x1 +serdes_pre_driver_current_lane1_36=0x1 +serdes_pre_driver_current_lane2_36=0x1 +serdes_pre_driver_current_lane3_36=0x1 +serdes_preemphasis_lane0_36=0xbb10 +serdes_preemphasis_lane1_36=0xbb10 +serdes_preemphasis_lane2_36=0xbb10 +serdes_preemphasis_lane3_36=0xc2f0 + +# xe24 (40G) +portmap_37=121:40 +xgxs_rx_lane_map_37=0x1320 +xgxs_tx_lane_map_37=0x3021 +phy_xaui_rx_polarity_flip_37=0xd +phy_xaui_tx_polarity_flip_37=0xb +serdes_driver_current_lane0_37=0x4 +serdes_driver_current_lane1_37=0x4 +serdes_driver_current_lane2_37=0x4 +serdes_driver_current_lane3_37=0x4 +serdes_pre_driver_current_lane0_37=0x4 +serdes_pre_driver_current_lane1_37=0x4 +serdes_pre_driver_current_lane2_37=0x4 +serdes_pre_driver_current_lane3_37=0x4 +serdes_preemphasis_lane0_37=0xc6e0 +serdes_preemphasis_lane1_37=0xc6e0 +serdes_preemphasis_lane2_37=0xc6e0 +serdes_preemphasis_lane3_37=0xc6e0 + +# xe25 (40G) +portmap_38=125:40 +xgxs_rx_lane_map_38=0x132 +xgxs_tx_lane_map_38=0x132 +phy_xaui_rx_polarity_flip_38=0x8 +phy_xaui_tx_polarity_flip_38=0x0 +serdes_driver_current_lane0_38=0x4 +serdes_driver_current_lane1_38=0x4 +serdes_driver_current_lane2_38=0x4 +serdes_driver_current_lane3_38=0x4 +serdes_pre_driver_current_lane0_38=0x4 +serdes_pre_driver_current_lane1_38=0x4 +serdes_pre_driver_current_lane2_38=0x4 +serdes_pre_driver_current_lane3_38=0x4 +serdes_preemphasis_lane0_38=0xc6e0 +serdes_preemphasis_lane1_38=0xc6e0 +serdes_preemphasis_lane2_38=0xc6e0 +serdes_preemphasis_lane3_38=0xcec0 + +# xe26 (40G) +portmap_39=85:40 +xgxs_rx_lane_map_39=0x213 +xgxs_tx_lane_map_39=0x1203 +phy_xaui_rx_polarity_flip_39=0xc +phy_xaui_tx_polarity_flip_39=0xe +serdes_driver_current_lane0_39=0x4 +serdes_driver_current_lane1_39=0x5 +serdes_driver_current_lane2_39=0x4 +serdes_driver_current_lane3_39=0x5 +serdes_pre_driver_current_lane0_39=0x4 +serdes_pre_driver_current_lane1_39=0x5 +serdes_pre_driver_current_lane2_39=0x4 +serdes_pre_driver_current_lane3_39=0x5 +serdes_preemphasis_lane0_39=0xc2f0 +serdes_preemphasis_lane1_39=0xc6e0 +serdes_preemphasis_lane2_39=0xc6e0 +serdes_preemphasis_lane3_39=0xc6e0 + +# xe27 (40G) +portmap_40=81:40 +xgxs_rx_lane_map_40=0x1320 +xgxs_tx_lane_map_40=0x2031 +phy_xaui_rx_polarity_flip_40=0x1 +phy_xaui_tx_polarity_flip_40=0x2 +serdes_driver_current_lane0_40=0x2 +serdes_driver_current_lane1_40=0x2 +serdes_driver_current_lane2_40=0x2 +serdes_driver_current_lane3_40=0x2 +serdes_pre_driver_current_lane0_40=0x2 +serdes_pre_driver_current_lane1_40=0x2 +serdes_pre_driver_current_lane2_40=0x2 +serdes_pre_driver_current_lane3_40=0x2 +serdes_preemphasis_lane0_40=0xbb10 +serdes_preemphasis_lane1_40=0xbb10 +serdes_preemphasis_lane2_40=0xbf00 +serdes_preemphasis_lane3_40=0xbb10 + +# xe28 (40G) +portmap_41=89:40 +xgxs_rx_lane_map_41=0x1320 +xgxs_tx_lane_map_41=0x3021 +phy_xaui_rx_polarity_flip_41=0x2 +phy_xaui_tx_polarity_flip_41=0xb +serdes_driver_current_lane0_41=0x4 +serdes_driver_current_lane1_41=0x4 +serdes_driver_current_lane2_41=0x4 +serdes_driver_current_lane3_41=0x4 +serdes_pre_driver_current_lane0_41=0x4 +serdes_pre_driver_current_lane1_41=0x4 +serdes_pre_driver_current_lane2_41=0x4 +serdes_pre_driver_current_lane3_41=0x4 +serdes_preemphasis_lane0_41=0xcad0 +serdes_preemphasis_lane1_41=0xc6e0 +serdes_preemphasis_lane2_41=0xc6e0 +serdes_preemphasis_lane3_41=0xc6e0 + +# xe29 (40G) +portmap_42=93:40 +xgxs_rx_lane_map_42=0x1320 +xgxs_tx_lane_map_42=0x2031 +phy_xaui_rx_polarity_flip_42=0x1 +phy_xaui_tx_polarity_flip_42=0x2 +serdes_driver_current_lane0_42=0x4 +serdes_driver_current_lane1_42=0x4 +serdes_driver_current_lane2_42=0x4 +serdes_driver_current_lane3_42=0x4 +serdes_pre_driver_current_lane0_42=0x4 +serdes_pre_driver_current_lane1_42=0x4 +serdes_pre_driver_current_lane2_42=0x4 +serdes_pre_driver_current_lane3_42=0x4 +serdes_preemphasis_lane0_42=0xc2f0 +serdes_preemphasis_lane1_42=0xc2f0 +serdes_preemphasis_lane2_42=0xc2f0 +serdes_preemphasis_lane3_42=0xc2f0 + +# xe30 (40G) +portmap_43=97:40 +xgxs_rx_lane_map_43=0x213 +xgxs_tx_lane_map_43=0x2031 +phy_xaui_rx_polarity_flip_43=0xc +phy_xaui_tx_polarity_flip_43=0x3 +serdes_driver_current_lane0_43=0x5 +serdes_driver_current_lane1_43=0x5 +serdes_driver_current_lane2_43=0x5 +serdes_driver_current_lane3_43=0x5 +serdes_pre_driver_current_lane0_43=0x5 +serdes_pre_driver_current_lane1_43=0x5 +serdes_pre_driver_current_lane2_43=0x5 +serdes_pre_driver_current_lane3_43=0x5 +serdes_preemphasis_lane0_43=0xcad0 +serdes_preemphasis_lane1_43=0xcad0 +serdes_preemphasis_lane2_43=0xcad0 +serdes_preemphasis_lane3_43=0xcad0 + +# xe31 (40G) +portmap_44=101:40 +xgxs_rx_lane_map_44=0x1320 +xgxs_tx_lane_map_44=0x1203 +phy_xaui_rx_polarity_flip_44=0x1 +phy_xaui_tx_polarity_flip_44=0x6 +serdes_driver_current_lane0_44=0x6 +serdes_driver_current_lane1_44=0x6 +serdes_driver_current_lane2_44=0x6 +serdes_driver_current_lane3_44=0x7 +serdes_pre_driver_current_lane0_44=0x6 +serdes_pre_driver_current_lane1_44=0x6 +serdes_pre_driver_current_lane2_44=0x6 +serdes_pre_driver_current_lane3_44=0x7 +serdes_preemphasis_lane0_44=0xcec0 +serdes_preemphasis_lane1_44=0xcec0 +serdes_preemphasis_lane2_44=0xcad0 +serdes_preemphasis_lane3_44=0xc6e0 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q32 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q32 new file mode 120000 index 000000000000..175db8c15394 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000-Q32 @@ -0,0 +1 @@ +Force10-S6000 \ No newline at end of file diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers.json.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} + diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers_defaults_def.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers_defaults_def.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers_defaults_t0.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers_defaults_t1.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/pg_profile_lookup.ini b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/pg_profile_lookup.ini new file mode 100644 index 000000000000..9f2eacb6fc42 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/port_config.ini b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/port_config.ini new file mode 100644 index 000000000000..95cf5eec9e4e --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/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/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/qos.json.j2 b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/sai.profile b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/sai.profile new file mode 100644 index 000000000000..52e2e289af60 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-s6000-32x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/td2-s6000-32x40G.config.bcm b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/td2-s6000-32x40G.config.bcm new file mode 100644 index 000000000000..0e25b4d4232d --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/Force10-S6000/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=10 +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/dell/x86_64-dell_s6000_s1220-r0/default_sku b/device/dell/x86_64-dell_s6000_s1220-r0/default_sku new file mode 100644 index 000000000000..493e1989b662 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/default_sku @@ -0,0 +1 @@ +Force10-S6000 t1 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/installer.conf b/device/dell/x86_64-dell_s6000_s1220-r0/installer.conf new file mode 100644 index 000000000000..45888b61d375 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/installer.conf @@ -0,0 +1,29 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="processor.max_cstate=1 intel_idle.max_cstate=0" + +if [ "$install_env" = "onie" ]; then + +echo "Replace ONIE reboot with Dell reset commands" + +# set I2C GPIO mux +[ -d /sys/class/gpio/gpio1 ] || echo 1 > /sys/class/gpio/export +[ -d /sys/class/gpio/gpio2 ] || echo 2 > /sys/class/gpio/export +[ -d /sys/class/gpio/gpio10 ] || echo 10 > /sys/class/gpio/export +echo out > /sys/class/gpio/gpio1/direction +echo out > /sys/class/gpio/gpio2/direction +echo out > /sys/class/gpio/gpio10/direction +echo 0 > /sys/class/gpio/gpio1/value +echo 0 > /sys/class/gpio/gpio2/value + +# replace the original reboot binary with the following command +# sync flushes file system buffers +# i2cset command triggers a hard system reboot, required by ASIC to operate correctly +rm /sbin/reboot +cat <> /sbin/reboot +#!/bin/sh +sync +i2cset -y 0 0x31 1 0xfd +EOF + +chmod a+x /sbin/reboot + +fi diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/led_proc_init.soc b/device/dell/x86_64-dell_s6000_s1220-r0/led_proc_init.soc new file mode 100644 index 000000000000..ddda7bdb639a --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/led_proc_init.soc @@ -0,0 +1,43 @@ +# LED microprocessor initialization for Dell s6000 + +led 0 stop +led 0 prog 02 31 60 F7 02 01 28 60 F6 D6 F7 70 28 67 44 06 F6 06 F6 80 D2 35 74 06 86 F8 3A 40 67 80 67 44 06 F6 67 80 67 80 67 3C D2 32 70 1C D2 34 70 1C 67 44 06 F6 67 80 67 80 67 80 67 3C 06 F7 F2 01 60 F7 77 11 32 08 97 71 4C 77 80 57 67 61 32 00 32 01 B7 97 71 5C 95 75 74 85 77 7C 02 0A 50 77 56 06 F6 D2 17 75 6C 12 88 FE F6 57 06 F6 E2 17 12 D4 F8 57 16 F8 CA 05 74 80 77 7C 22 0E 87 57 22 0F 87 57 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0x31 REMAP_PORT_2=0 REMAP_PORT_1=0 REMAP_PORT_0=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=0x32 REMAP_PORT_6=0 REMAP_PORT_5=0 REMAP_PORT_4=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=0 REMAP_PORT_8=0 REMAP_PORT_11=0x34 REMAP_PORT_10=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0x33 REMAP_PORT_14=0 REMAP_PORT_13=0 REMAP_PORT_12=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=0x16 REMAP_PORT_18=0x15 REMAP_PORT_17=0x18 REMAP_PORT_16=0x17 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0x11 REMAP_PORT_22=0x12 REMAP_PORT_21=0x13 REMAP_PORT_20=0x14 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=9 REMAP_PORT_26=0xa REMAP_PORT_25=0xb REMAP_PORT_24=0xc +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0xe REMAP_PORT_30=0xd REMAP_PORT_29=0x10 REMAP_PORT_28=0xf +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=0x2e REMAP_PORT_34=0x2d REMAP_PORT_33=0x30 REMAP_PORT_32=0x2f +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=0x29 REMAP_PORT_38=0x2a REMAP_PORT_37=0x2b REMAP_PORT_36=0x2c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=6 REMAP_PORT_42=5 REMAP_PORT_41=8 REMAP_PORT_40=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=1 REMAP_PORT_46=2 REMAP_PORT_45=3 REMAP_PORT_44=4 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=0x26 REMAP_PORT_50=0x25 REMAP_PORT_49=0x28 REMAP_PORT_48=0x27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0x21 REMAP_PORT_54=0x22 REMAP_PORT_53=0x23 REMAP_PORT_52=0x24 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=0x19 REMAP_PORT_58=0x1a REMAP_PORT_57=0x1b REMAP_PORT_56=0x1c +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0x1e REMAP_PORT_62=0x1d REMAP_PORT_61=0x20 REMAP_PORT_60=0x1f +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 02 31 60 F7 02 01 28 60 F6 D6 F7 70 28 67 44 06 F6 06 F6 80 D2 35 74 06 86 F8 3A 40 67 80 67 44 06 F6 67 80 67 80 67 3C D2 32 70 1C D2 34 70 1C 67 44 06 F6 67 80 67 80 67 80 67 3C 06 F7 F2 01 60 F7 77 11 32 08 97 71 4C 77 80 57 67 61 32 00 32 01 B7 97 71 5C 95 75 74 85 77 7C 02 0A 50 77 56 06 F6 D2 17 75 6C 12 88 FE F6 57 06 F6 E2 17 12 D4 F8 57 16 F8 CA 05 74 80 77 7C 22 0E 87 57 22 0F 87 57 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0x1e REMAP_PORT_2=0x1d REMAP_PORT_1=0x20 REMAP_PORT_0=0x1f +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=0x19 REMAP_PORT_6=0x1a REMAP_PORT_5=0x1b REMAP_PORT_4=0x1c +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=0x23 REMAP_PORT_8=0x24 REMAP_PORT_11=0x21 REMAP_PORT_10=0x22 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0x26 REMAP_PORT_14=0x25 REMAP_PORT_13=0x28 REMAP_PORT_12=0x27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=0x16 REMAP_PORT_18=0x15 REMAP_PORT_17=0x18 REMAP_PORT_16=0x17 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0x11 REMAP_PORT_22=0x12 REMAP_PORT_21=0x13 REMAP_PORT_20=0x14 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=0x34 REMAP_PORT_26=0 REMAP_PORT_25=0 REMAP_PORT_24=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0x33 REMAP_PORT_30=0 REMAP_PORT_29=0 REMAP_PORT_28=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=0x2e REMAP_PORT_34=0x2d REMAP_PORT_33=0x30 REMAP_PORT_32=0x2f +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=0x29 REMAP_PORT_38=0x2a REMAP_PORT_37=0x2b REMAP_PORT_36=0x2c +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=0x31 REMAP_PORT_42=0 REMAP_PORT_41=0 REMAP_PORT_40=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=0x32 REMAP_PORT_46=0 REMAP_PORT_45=0 REMAP_PORT_44=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=9 REMAP_PORT_50=0xa REMAP_PORT_49=0xb REMAP_PORT_48=0xc +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0xe REMAP_PORT_54=0xd REMAP_PORT_53=0x10 REMAP_PORT_52=0xf +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=6 REMAP_PORT_58=5 REMAP_PORT_57=8 REMAP_PORT_56=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=1 REMAP_PORT_62=2 REMAP_PORT_61=3 REMAP_PORT_60=4 +led 1 auto on +led 1 start diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/media_settings.json b/device/dell/x86_64-dell_s6000_s1220-r0/media_settings.json new file mode 100644 index 000000000000..9032a2e53b26 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/media_settings.json @@ -0,0 +1,1348 @@ +{ + "PORT_MEDIA_SETTINGS": { + "0": { + "Default": { + "preemphasis": { + "lane0":"0xcad0", + "lane1":"0xc6e0", + "lane2":"0xc6e0", + "lane3":"0xd2b0" + }, + "idriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + }, + "ipredriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + }, + "ipredriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + } + } + }, + "1": { + "Default": { + "preemphasis": { + "lane0":"0xc2f0", + "lane1":"0xd2b0", + "lane2":"0xc6e0", + "lane3":"0xc2f0" + }, + "idriver": { + "lane0":"0x6", + "lane1":"0x7", + "lane2":"0x6", + "lane3":"0x6" + }, + "ipredriver": { + "lane0":"0x6", + "lane1":"0x7", + "lane2":"0x6", + "lane3":"0x6" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x6", + "lane1":"0x7", + "lane2":"0x6", + "lane3":"0x6" + }, + "ipredriver": { + "lane0":"0x6", + "lane1":"0x7", + "lane2":"0x6", + "lane3":"0x6" + } + } + }, + "2": { + "Default": { + "preemphasis": { + "lane0":"0xc6e0", + "lane1":"0xc6e0", + "lane2":"0xc6e0", + "lane3":"0xc6e0" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + } + }, + "3": { + "Default": { + "preemphasis": { + "lane0":"0xcad0", + "lane1":"0xcad0", + "lane2":"0xc2f0", + "lane3":"0xc2f0" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + } + }, + "4": { + "Default": { + "preemphasis": { + "lane0":"0xc2f0", + "lane1":"0xc2f0", + "lane2":"0xc2f0", + "lane3":"0xc2f0" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + } + }, + "5": { + "Default": { + "preemphasis": { + "lane0":"0xc6e0", + "lane1":"0xc2f0", + "lane2":"0xc2f0", + "lane3":"0xcad0" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + } + }, + "6": { + "Default": { + "preemphasis": { + "lane0":"0xc6e0", + "lane1":"0xcad0", + "lane2":"0xc6e0", + "lane3":"0xcad0" + }, + "idriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + }, + "ipredriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + }, + "ipredriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + } + } + }, + "7": { + "Default": { + "preemphasis": { + "lane0":"0xc6e0", + "lane1":"0xc6e0", + "lane2":"0xc6e0", + "lane3":"0xc6e0" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + } + }, + "8": { + "Default": { + "preemphasis": { + "lane0":"0xb270", + "lane1":"0xbb10", + "lane2":"0xb720", + "lane3":"0xb720" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x3", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x3", + "lane2":"0x2", + "lane3":"0x2" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xea05", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x3", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x3", + "lane2":"0x2", + "lane3":"0x2" + } + } + }, + "9": { + "Default": { + "preemphasis": { + "lane0":"0xc2f0", + "lane1":"0xc6e0", + "lane2":"0xbf00", + "lane3":"0xc2f0" + }, + "idriver": { + "lane0":"0x3", + "lane1":"0x3", + "lane2":"0x3", + "lane3":"0x3" + }, + "ipredriver": { + "lane0":"0x3", + "lane1":"0x3", + "lane2":"0x3", + "lane3":"0x3" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x3", + "lane1":"0x3", + "lane2":"0x3", + "lane3":"0x3" + }, + "ipredriver": { + "lane0":"0x3", + "lane1":"0x3", + "lane2":"0x3", + "lane3":"0x3" + } + } + }, + "10": { + "Default": { + "preemphasis": { + "lane0":"0xb330", + "lane1":"0xbb10", + "lane2":"0xbb10", + "lane3":"0xbb10" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + } + }, + "11": { + "Default": { + "preemphasis": { + "lane0":"0xb330", + "lane1":"0xb330", + "lane2":"0xb330", + "lane3":"0xb330" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + } + }, + "12": { + "Default": { + "preemphasis": { + "lane0":"0xaf40", + "lane1":"0xaf40", + "lane2":"0xaf40", + "lane3":"0xaf40" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + } + }, + "13": { + "Default": { + "preemphasis": { + "lane0":"0xa760", + "lane1":"0xa760", + "lane2":"0xa760", + "lane3":"0xa760" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + } + }, + "14": { + "Default": { + "preemphasis": { + "lane0":"0xa760", + "lane1":"0xa760", + "lane2":"0xa760", + "lane3":"0xa760" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + } + } + }, + "15": { + "Default": { + "preemphasis": { + "lane0":"0xa760", + "lane1":"0xa760", + "lane2":"0xa760", + "lane3":"0xa760" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + } + }, + "16": { + "Default": { + "preemphasis": { + "lane0":"0xa760", + "lane1":"0xa760", + "lane2":"0xa760", + "lane3":"0xa760" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + } + } + }, + "17": { + "Default": { + "preemphasis": { + "lane0":"0xa370", + "lane1":"0xa370", + "lane2":"0xa370", + "lane3":"0xa370" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + } + } + }, + "18": { + "Default": { + "preemphasis": { + "lane0":"0xa760", + "lane1":"0xa760", + "lane2":"0xa760", + "lane3":"0xa760" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + } + }, + "19": { + "Default": { + "preemphasis": { + "lane0":"0xaf40", + "lane1":"0xaf40", + "lane2":"0xaf40", + "lane3":"0xaf40" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + } + }, + "20": { + "Default": { + "preemphasis": { + "lane0":"0xb330", + "lane1":"0xb330", + "lane2":"0xb330", + "lane3":"0xbff0" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x2" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x2" + } + } + }, + "21": { + "Default": { + "preemphasis": { + "lane0":"0xb330", + "lane1":"0xb330", + "lane2":"0xb330", + "lane3":"0xb330" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + } + } + }, + "22": { + "Default": { + "preemphasis": { + "lane0":"0xbb10", + "lane1":"0xbb10", + "lane2":"0xbb10", + "lane3":"0xc2f0" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + }, + "ipredriver": { + "lane0":"0x1", + "lane1":"0x1", + "lane2":"0x1", + "lane3":"0x1" + } + } + }, + "23": { + "Default": { + "preemphasis": { + "lane0":"0xc6e0", + "lane1":"0xc6e0", + "lane2":"0xc6e0", + "lane3":"0xc6e0" + }, + "idriver": { + "lane0":"0x3", + "lane1":"0x5", + "lane2":"0x3", + "lane3":"0x3" + }, + "ipredriver": { + "lane0":"0x3", + "lane1":"0x5", + "lane2":"0x3", + "lane3":"0x3" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x3", + "lane1":"0x5", + "lane2":"0x3", + "lane3":"0x3" + }, + "ipredriver": { + "lane0":"0x3", + "lane1":"0x5", + "lane2":"0x3", + "lane3":"0x3" + } + } + }, + "24": { + "Default": { + "preemphasis": { + "lane0":"0xc6e0", + "lane1":"0xc6e0", + "lane2":"0xc6e0", + "lane3":"0xcec0" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + } + }, + "25": { + "Default": { + "preemphasis": { + "lane0":"0xc6e0", + "lane1":"0xc6e0", + "lane2":"0xc6e0", + "lane3":"0xc6c0" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + } + }, + "26": { + "Default": { + "preemphasis": { + "lane0":"0xbb10", + "lane1":"0xbb10", + "lane2":"0xbf00", + "lane3":"0xbb10" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + }, + "ipredriver": { + "lane0":"0x2", + "lane1":"0x2", + "lane2":"0x2", + "lane3":"0x2" + } + } + }, + "27": { + "Default": { + "preemphasis": { + "lane0":"0xc2f0", + "lane1":"0xc6e0", + "lane2":"0xc6e0", + "lane3":"0xc6e0" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x5", + "lane2":"0x4", + "lane3":"0x5" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x5", + "lane2":"0x4", + "lane3":"0x5" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x5", + "lane2":"0x4", + "lane3":"0x5" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x5", + "lane2":"0x4", + "lane3":"0x5" + } + } + }, + "28": { + "Default": { + "preemphasis": { + "lane0":"0xc2f0", + "lane1":"0xc2f0", + "lane2":"0xc2f0", + "lane3":"0xc2f0" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xe225", + "lane1":"0xe225", + "lane2":"0xe225", + "lane3":"0xe225" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + } + }, + "29": { + "Default": { + "preemphasis": { + "lane0":"0xcad0", + "lane1":"0xc6e0", + "lane2":"0xc6e0", + "lane3":"0xc6e0" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + }, + "ipredriver": { + "lane0":"0x4", + "lane1":"0x4", + "lane2":"0x4", + "lane3":"0x4" + } + } + }, + "30": { + "Default": { + "preemphasis": { + "lane0":"0xcec0", + "lane1":"0xcec0", + "lane2":"0xcad0", + "lane3":"0xc6e0" + }, + "idriver": { + "lane0":"0x6", + "lane1":"0x6", + "lane2":"0x6", + "lane3":"0x7" + }, + "ipredriver": { + "lane0":"0x6", + "lane1":"0x6", + "lane2":"0x6", + "lane3":"0x7" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x6", + "lane1":"0x6", + "lane2":"0x6", + "lane3":"0x7" + }, + "ipredriver": { + "lane0":"0x6", + "lane1":"0x6", + "lane2":"0x6", + "lane3":"0x7" + } + } + }, + "31": { + "Default": { + "preemphasis": { + "lane0":"0xcad0", + "lane1":"0xcad0", + "lane2":"0xcad0", + "lane3":"0xcad0" + }, + "idriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + }, + "ipredriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0":"0xea05", + "lane1":"0xea05", + "lane2":"0xea05", + "lane3":"0xea05" + }, + "idriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + }, + "ipredriver": { + "lane0":"0x5", + "lane1":"0x5", + "lane2":"0x5", + "lane3":"0x5" + } + } + } + } +} diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/pcie.yaml b/device/dell/x86_64-dell_s6000_s1220-r0/pcie.yaml new file mode 100644 index 000000000000..9c4bea46730a --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/pcie.yaml @@ -0,0 +1,65 @@ +- bus: '00' + dev: '01' + fn: '0' + id: 0c46 + name: 'PCI bridge: Intel Corporation Atom Processor S1200 PCI Express Root Port 1' +- bus: '00' + dev: '02' + fn: '0' + id: 0c47 + name: 'PCI bridge: Intel Corporation Atom Processor S1200 PCI Express Root Port 2' +- bus: '00' + dev: '03' + fn: '0' + id: 0c48 + name: 'PCI bridge: Intel Corporation Atom Processor S1200 PCI Express Root Port 3' +- bus: '00' + dev: '04' + fn: '0' + id: 0c49 + name: 'PCI bridge: Intel Corporation Atom Processor S1200 PCI Express Root Port 4' +- bus: '00' + dev: 0e + fn: '0' + id: 0c54 + name: 'IOMMU: Intel Corporation Atom Processor S1200 Internal' +- bus: '00' + dev: '13' + fn: '0' + id: 0c59 + name: 'System peripheral: Intel Corporation Atom Processor S1200 SMBus 2.0 Controller 0' +- bus: '00' + dev: '13' + fn: '1' + id: 0c5a + name: 'System peripheral: Intel Corporation Atom Processor S1200 SMBus 2.0 Controller 1' +- bus: '01' + dev: '00' + fn: '0' + id: b850 + name: 'Ethernet controller: Broadcom Limited Broadcom BCM56850 Switch ASIC' +- bus: '02' + dev: '00' + fn: '0' + id: '9170' + name: 'SATA controller: Marvell Technology Group Ltd. Device 9170' +- bus: '03' + dev: '00' + fn: '0' + id: 400a + name: 'PCI bridge: Pericom Semiconductor PI7C9X442SL PCI Express Bridge Port' +- bus: '04' + dev: '01' + fn: '0' + id: 400a + name: 'PCI bridge: Pericom Semiconductor PI7C9X442SL PCI Express Bridge Port' +- bus: '04' + dev: '02' + fn: '0' + id: 400a + name: 'PCI bridge: Pericom Semiconductor PI7C9X442SL PCI Express Bridge Port' +- bus: 08 + dev: '00' + fn: '0' + id: 10d3 + name: 'Ethernet controller: Intel Corporation 82574L Gigabit Network Connection' diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/platform.json b/device/dell/x86_64-dell_s6000_s1220-r0/platform.json new file mode 100644 index 000000000000..62a53fe328fc --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/platform.json @@ -0,0 +1,228 @@ +{ + "chassis": { + "name": "S6000", + "components": [ + { + "name": "BIOS" + }, + { + "name": "System-CPLD" + }, + { + "name": "Master-CPLD" + }, + { + "name": "Slave-CPLD" + } + ], + "fans": [ + { + "name": "FanTray1-Fan1" + }, + { + "name": "FanTray1-Fan2" + }, + { + "name": "FanTray2-Fan1" + }, + { + "name": "FanTray2-Fan2" + }, + { + "name": "FanTray3-Fan1" + }, + { + "name": "FanTray3-Fan2" + } + ], + "fan_drawers":[ + { + "name": "FanTray1", + "fans": [ + { + "name": "FanTray1-Fan1" + }, + { + "name": "FanTray1-Fan2" + } + ] + }, + { + "name": "FanTray2", + "fans": [ + { + "name": "FanTray2-Fan1" + }, + { + "name": "FanTray2-Fan2" + } + ] + }, + { + "name": "FanTray3", + "fans": [ + { + "name": "FanTray3-Fan1" + }, + { + "name": "FanTray3-Fan2" + } + ] + } + ], + "psus": [ + { + "name": "PSU1", + "fans": [ + { + "name": "PSU1 Fan" + } + ], + "thermals": [ + { + "name": "PSU1-Sensor 1" + }, + { + "name": "PSU1-Sensor 2" + } + ] + }, + { + "name": "PSU2", + "fans": [ + { + "name": "PSU2 Fan" + } + ], + "thermals": [ + { + "name": "PSU2-Sensor 1" + }, + { + "name": "PSU2-Sensor 2" + } + ] + } + ], + "thermals": [ + { + "name": "ASIC On-board" + }, + { + "name": "NIC" + }, + { + "name": "System Front" + }, + { + "name": "DIMM" + }, + { + "name": "CPU Core 0" + }, + { + "name": "CPU Core 1" + } + ], + "modules": [], + "sfps": [ + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + } + ] + }, + "interfaces": {} +} diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/plugins/eeprom.py b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/eeprom.py new file mode 100644 index 000000000000..dc16fde7d770 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/eeprom.py @@ -0,0 +1,28 @@ +############################################################################# +# Dell S6000 +# +# 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.eeprom_tlvinfo import TlvInfoDecoder + from sonic_platform.eeprom import EepromS6000 +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(object): + + def __new__(cls, name, path, cpld_root, ro): + eeprom_path = "/sys/class/i2c-adapter/i2c-10/10-0053/eeprom" + + with open("/sys/class/dmi/id/product_name", "r") as fd: + board_type = fd.read() + + if 'S6000-ON' in board_type: + return TlvInfoDecoder(eeprom_path, 0, '', True) + else: + return EepromS6000(is_plugin=True) diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/plugins/psuutil.py b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/psuutil.py new file mode 100644 index 000000000000..16318bca8162 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/psuutil.py @@ -0,0 +1,74 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def get_cpld_register(self, reg_name): + cpld_dir = "/sys/devices/platform/dell-s6000-cpld.0" + retval = 'ERR' + reg_file = cpld_dir + '/' + reg_name + if (not os.path.isfile(reg_file)): + return retval + + try: + with open(reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", reg_file, "file !") + + 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 + """ + S6000_MAX_PSUS = 2 + return S6000_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 + psu_status = self.get_cpld_register('psu'+str(index - 1)+'_status') + if (psu_status != 'ERR'): + status = int(psu_status, 10) + + presence = self.get_psu_presence(index) + + return (status & presence) + + 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_presence = self.get_cpld_register('psu'+str(index - 1)+'_prs') + if (psu_presence != 'ERR'): + status = int(psu_presence, 10) + + return status diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/plugins/sfputil.py b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/sfputil.py new file mode 100644 index 000000000000..f03415cbc7ea --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/sfputil.py @@ -0,0 +1,255 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import datetime + 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 = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 20 + + _port_to_eeprom_mapping = {} + port_dict = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def get_transceiver_status(self): + + try: + reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_modprs") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + reg_file.close() + + return int(content, 16) + + def __init__(self): + + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + # Get Transceiver status + self.modprs_register = self.get_transceiver_status + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_modprs") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/dell-s6000-cpld.0/qsfp_reset" + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def get_transceiver_change_event(self, timeout=0): + + start_time = time.time() + port_dict = {} + port = self.port_start + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print('get_transceiver_change_event:' + 'time wrap / invalid timeout value', timeout) + + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + # Check for OIR events and return updated port_dict + reg_value = self.get_transceiver_status + if reg_value != self.modprs_register: + changed_ports = self.modprs_register ^ reg_value + while port >= self.port_start and port <= self.port_end: + + # Mask off the bit corresponding to our port + mask = (1 << port) + + if changed_ports & mask: + # ModPrsL is active low + if reg_value & mask == 0: + port_dict[port] = '1' + else: + port_dict[port] = '0' + + port += 1 + + # Update reg value + self.modprs_register = reg_value + return True, port_dict + + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + print("get_transceiver_change_event: Should not reach here.") + return False, {} diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json b/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..94592fa8cebc --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/sensors.conf b/device/dell/x86_64-dell_s6000_s1220-r0/sensors.conf new file mode 100644 index 000000000000..f74a2b3d40ac --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/sensors.conf @@ -0,0 +1,36 @@ +# libsensors configuration file +# -------------------------------------------------- +# + +# tmp75-i2c-11-4c has sensors close to Networking ASIC. +# tmp75-i2c-11-4d has sensors close to NIC. +# tmp75-i2c-11-4e is an ambient temperature sensor. + +chip "tmp75-*" + set temp1_max 80 + set temp1_max_hyst 70 + +# emc1403-i2c-10-4d has following temperature sensors: +# temp1: CPU0 external Temp Sensor +# temp2: CPU1 external Temp Sensor +# temp3: CPU Internal DTS (Internal die, max of all die readings) + +chip "emc1403-*" + set temp1_crit 85 + set temp1_max 50 + set temp2_crit 85 + set temp2_max 50 + set temp3_crit 85 + set temp3_max 50 + +chip "max6620-i2c-*-2a" + ignore fan3 + ignore fan4 + +chip "jc42-*" + set temp1_max 50 + set temp1_crit 85 + +chip "dni_dps460-*" + set temp1_max 80 + set temp2_max 80 diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/system_health_monitoring_config.json b/device/dell/x86_64-dell_s6000_s1220-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..bb8ffbcd2172 --- /dev/null +++ b/device/dell/x86_64-dell_s6000_s1220-r0/system_health_monitoring_config.json @@ -0,0 +1,11 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "amber", + "normal": "green", + "booting": "blinking green" + } +} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100-T1 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100-T1 new file mode 120000 index 000000000000..36b1b840b83e --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100-T1 @@ -0,0 +1 @@ +Force10-S6100 \ No newline at end of file diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers.json.j2 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t0.j2 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..8f55022973fb --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t0.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t1.j2 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..47a9c81f0796 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/buffers_defaults_t1.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/pg_profile_lookup.ini b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/pg_profile_lookup.ini new file mode 100644 index 000000000000..0b5d680edda7 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 0 2288 + 25000 5m 1248 2288 53248 0 2288 + 40000 5m 1248 2288 66560 0 2288 + 50000 5m 1248 2288 79872 0 2288 + 100000 5m 1248 2288 165568 0 2288 + 10000 40m 1248 2288 37024 0 2288 + 25000 40m 1248 2288 56160 0 2288 + 40000 40m 1248 2288 71552 0 2288 + 50000 40m 1248 2288 85696 0 2288 + 100000 40m 1248 2288 177632 0 2288 + 10000 300m 1248 2288 46176 0 2288 + 25000 300m 1248 2288 79040 0 2288 + 40000 300m 1248 2288 108160 0 2288 + 50000 300m 1248 2288 141856 0 2288 + 100000 300m 1248 2288 268736 0 2288 diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/port_config.ini b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/port_config.ini new file mode 100644 index 000000000000..1922a3e04b5a --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index speed +Ethernet0 101,102 fortyGigE1/1/1 0 40000 +Ethernet1 103,104 fortyGigE1/1/2 1 40000 +Ethernet2 97,98 fortyGigE1/1/3 2 40000 +Ethernet3 99,100 fortyGigE1/1/4 3 40000 +Ethernet4 69,70 fortyGigE1/1/5 4 40000 +Ethernet5 71,72 fortyGigE1/1/6 5 40000 +Ethernet6 65,66 fortyGigE1/1/7 6 40000 +Ethernet7 67,68 fortyGigE1/1/8 7 40000 +Ethernet8 53,54 fortyGigE1/1/9 8 40000 +Ethernet9 55,56 fortyGigE1/1/10 9 40000 +Ethernet10 49,50 fortyGigE1/1/11 10 40000 +Ethernet11 51,52 fortyGigE1/1/12 11 40000 +Ethernet12 21,22 fortyGigE1/1/13 12 40000 +Ethernet13 23,24 fortyGigE1/1/14 13 40000 +Ethernet14 17,18 fortyGigE1/1/15 14 40000 +Ethernet15 19,20 fortyGigE1/1/16 15 40000 +Ethernet16 25,26 fortyGigE1/2/1 16 40000 +Ethernet17 27,28 fortyGigE1/2/2 17 40000 +Ethernet18 29,30 fortyGigE1/2/3 18 40000 +Ethernet19 31,32 fortyGigE1/2/4 19 40000 +Ethernet20 57,58 fortyGigE1/2/5 20 40000 +Ethernet21 59,60 fortyGigE1/2/6 21 40000 +Ethernet22 61,62 fortyGigE1/2/7 22 40000 +Ethernet23 63,64 fortyGigE1/2/8 23 40000 +Ethernet24 73,74 fortyGigE1/2/9 24 40000 +Ethernet25 75,76 fortyGigE1/2/10 25 40000 +Ethernet26 77,78 fortyGigE1/2/11 26 40000 +Ethernet27 79,80 fortyGigE1/2/12 27 40000 +Ethernet28 105,106 fortyGigE1/2/13 28 40000 +Ethernet29 107,108 fortyGigE1/2/14 29 40000 +Ethernet30 109,110 fortyGigE1/2/15 30 40000 +Ethernet31 111,112 fortyGigE1/2/16 31 40000 +Ethernet32 13,14 fortyGigE1/3/1 32 40000 +Ethernet33 15,16 fortyGigE1/3/2 33 40000 +Ethernet34 9,10 fortyGigE1/3/3 34 40000 +Ethernet35 11,12 fortyGigE1/3/4 35 40000 +Ethernet36 125,126 fortyGigE1/3/5 36 40000 +Ethernet37 127,128 fortyGigE1/3/6 37 40000 +Ethernet38 121,122 fortyGigE1/3/7 38 40000 +Ethernet39 123,124 fortyGigE1/3/8 39 40000 +Ethernet40 93,94 fortyGigE1/3/9 40 40000 +Ethernet41 95,96 fortyGigE1/3/10 41 40000 +Ethernet42 89,90 fortyGigE1/3/11 42 40000 +Ethernet43 91,92 fortyGigE1/3/12 43 40000 +Ethernet44 45,46 fortyGigE1/3/13 44 40000 +Ethernet45 47,48 fortyGigE1/3/14 45 40000 +Ethernet46 41,42 fortyGigE1/3/15 46 40000 +Ethernet47 43,44 fortyGigE1/3/16 47 40000 +Ethernet48 113,114 fortyGigE1/4/1 48 40000 +Ethernet49 115,116 fortyGigE1/4/2 49 40000 +Ethernet50 117,118 fortyGigE1/4/3 50 40000 +Ethernet51 119,120 fortyGigE1/4/4 51 40000 +Ethernet52 1,2 fortyGigE1/4/5 52 40000 +Ethernet53 3,4 fortyGigE1/4/6 53 40000 +Ethernet54 5,6 fortyGigE1/4/7 54 40000 +Ethernet55 7,8 fortyGigE1/4/8 55 40000 +Ethernet56 33,34 fortyGigE1/4/9 56 40000 +Ethernet57 35,36 fortyGigE1/4/10 57 40000 +Ethernet58 37,38 fortyGigE1/4/11 58 40000 +Ethernet59 39,40 fortyGigE1/4/12 59 40000 +Ethernet60 81,82 fortyGigE1/4/13 60 40000 +Ethernet61 83,84 fortyGigE1/4/14 61 40000 +Ethernet62 85,86 fortyGigE1/4/15 62 40000 +Ethernet63 87,88 fortyGigE1/4/16 63 40000 diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/qos.json.j2 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/qos.json.j2 new file mode 100644 index 000000000000..34002048afdb --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/qos.json.j2 @@ -0,0 +1,21 @@ +{%- macro generate_wred_profiles() %} + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "250000", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, +{%- endmacro %} + +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/sai.profile.j2 b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/sai.profile.j2 new file mode 100644 index 000000000000..44992f92f45f --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/sai.profile.j2 @@ -0,0 +1,14 @@ +{# Get sai.profile based on switch_role #} +{%- if DEVICE_METADATA is defined -%} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] -%} +{%- if 'torrouter' in switch_role.lower() %} +{% set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s6100-64x40G-t0.config.bcm' -%} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s6100-64x40G-t1.config.bcm' -%} +{%- endif %} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s6100-64x40G-t1.config.bcm' -%} +{%- endif %} +{# Write the contents of sai_ profile_filename to sai.profile file #} +{{ sai_profile_contents }} +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t0.config.bcm b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t0.config.bcm new file mode 100644 index 000000000000..7fa577052635 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t0.config.bcm @@ -0,0 +1,410 @@ +#TH S6100 64x40 +l3_alpm_enable=2 +pfc_deadlock_seq_control=1 +bcm_stat_interval=2000000 +bcm_num_cos=10 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +oversubscribe_mode=1 +miim_intr_enable=0 + +phy_gearbox_enable=1 +phy_84752=1 +phy_ext_rom_boot=0 +rate_ext_mdio_divisor=0x80 + +serdes_fiber_pref_xe=0 +serdes_if_type_xe=14 + +fpem_mem_entries=32768 + +os=unix + +parity_correction=1 +parity_enable=1 + +xgxs_tx_lane_map_104=0x3210 +xgxs_rx_lane_map_104=0x0312 +phy_xaui_tx_polarity_flip_104=0x0 +phy_xaui_rx_polarity_flip_104=0x0 +port_phy_addr_104=0x1e +port_phy_addr_105=0x1e +dport_map_port_104=1 +dport_map_port_105=2 +xgxs_tx_lane_map_102=0x1032 +xgxs_rx_lane_map_102=0x0132 +phy_xaui_tx_polarity_flip_102=0x3 +phy_xaui_rx_polarity_flip_102=0x3 +phy_xaui_tx_polarity_flip_103=0x3 +phy_xaui_rx_polarity_flip_103=0x3 +port_phy_addr_102=0x1f +port_phy_addr_103=0x1f +dport_map_port_102=3 +dport_map_port_103=4 +xgxs_tx_lane_map_70=0x0123 +xgxs_rx_lane_map_70=0x3201 +phy_xaui_tx_polarity_flip_70=0x3 +phy_xaui_rx_polarity_flip_70=0x3 +phy_xaui_tx_polarity_flip_71=0x3 +phy_xaui_rx_polarity_flip_71=0x3 +port_phy_addr_70=0xE +port_phy_addr_71=0xE +dport_map_port_70=5 +dport_map_port_71=6 +xgxs_tx_lane_map_68=0x2301 +xgxs_rx_lane_map_68=0x1023 +phy_xaui_tx_polarity_flip_68=0x0 +phy_xaui_rx_polarity_flip_68=0x2 +phy_xaui_tx_polarity_flip_69=0x0 +phy_xaui_rx_polarity_flip_69=0x3 +port_phy_addr_68=0xF +port_phy_addr_69=0xF +dport_map_port_68=7 +dport_map_port_69=8 +xgxs_tx_lane_map_44=0x0123 +xgxs_rx_lane_map_44=0x3201 +phy_xaui_tx_polarity_flip_44=0x3 +phy_xaui_rx_polarity_flip_44=0x3 +phy_xaui_tx_polarity_flip_45=0x3 +phy_xaui_rx_polarity_flip_45=0x3 +port_phy_addr_44=0x3e +port_phy_addr_45=0x3e +dport_map_port_44=9 +dport_map_port_45=10 +xgxs_tx_lane_map_42=0x1032 +xgxs_rx_lane_map_42=0x2310 +phy_xaui_tx_polarity_flip_42=0x0 +phy_xaui_rx_polarity_flip_42=0x0 +phy_xaui_tx_polarity_flip_43=0x3 +phy_xaui_rx_polarity_flip_43=0x0 +port_phy_addr_42=0x3f +port_phy_addr_43=0x3f +dport_map_port_42=11 +dport_map_port_43=12 +xgxs_tx_lane_map_11=0x0123 +xgxs_rx_lane_map_11=0x3201 +phy_xaui_tx_polarity_flip_11=0x3 +phy_xaui_rx_polarity_flip_11=0x0 +phy_xaui_tx_polarity_flip_12=0x3 +phy_xaui_rx_polarity_flip_12=0x0 +port_phy_addr_11=0x2E +port_phy_addr_12=0x2E +dport_map_port_11=13 +dport_map_port_12=14 +xgxs_tx_lane_map_9=0x2310 +xgxs_rx_lane_map_9=0x1023 +phy_xaui_tx_polarity_flip_9=0x0 +phy_xaui_rx_polarity_flip_9=0x0 +phy_xaui_tx_polarity_flip_10=0x0 +phy_xaui_rx_polarity_flip_10=0x0 +port_phy_addr_9=0x2F +port_phy_addr_10=0x2F +dport_map_port_9=15 +dport_map_port_10=16 +xgxs_tx_lane_map_13=0x0123 +xgxs_rx_lane_map_13=0x0132 +phy_xaui_tx_polarity_flip_13=0x3 +phy_xaui_rx_polarity_flip_13=0x3 +phy_xaui_tx_polarity_flip_14=0x3 +phy_xaui_rx_polarity_flip_14=0x3 +port_phy_addr_13=0x11e +port_phy_addr_14=0x11e +dport_map_port_13=17 +dport_map_port_14=18 +xgxs_tx_lane_map_15=0x2301 +xgxs_rx_lane_map_15=0x2310 +phy_xaui_tx_polarity_flip_15=0x0 +phy_xaui_rx_polarity_flip_15=0x0 +port_phy_addr_15=0x11f +port_phy_addr_16=0x11f +dport_map_port_15=19 +dport_map_port_16=20 +xgxs_tx_lane_map_46=0x3210 +xgxs_rx_lane_map_46=0x0132 +phy_xaui_tx_polarity_flip_46=0x3 +phy_xaui_rx_polarity_flip_46=0x3 +phy_xaui_tx_polarity_flip_47=0x3 +phy_xaui_rx_polarity_flip_47=0x3 +port_phy_addr_46=0x10e +port_phy_addr_47=0x10e +dport_map_port_46=21 +dport_map_port_47=22 +xgxs_tx_lane_map_48=0x2301 +xgxs_rx_lane_map_48=0x1023 +phy_xaui_tx_polarity_flip_48=0x0 +phy_xaui_rx_polarity_flip_48=0x1 +port_phy_addr_48=0x10F +port_phy_addr_49=0x10F +dport_map_port_48=23 +dport_map_port_49=24 +xgxs_tx_lane_map_72=0x3210 +xgxs_rx_lane_map_72=0x0132 +phy_xaui_tx_polarity_flip_72=0x3 +phy_xaui_rx_polarity_flip_72=0x0 +phy_xaui_tx_polarity_flip_73=0x3 +phy_xaui_rx_polarity_flip_73=0x0 +port_phy_addr_72=0x13e +port_phy_addr_73=0x13e +dport_map_port_72=25 +dport_map_port_73=26 +xgxs_tx_lane_map_74=0x1320 +xgxs_rx_lane_map_74=0x2013 +phy_xaui_tx_polarity_flip_74=0x0 +phy_xaui_rx_polarity_flip_74=0x0 +phy_xaui_tx_polarity_flip_75=0x3 +phy_xaui_rx_polarity_flip_75=0x0 +port_phy_addr_74=0x13f +port_phy_addr_75=0x13f +dport_map_port_74=27 +dport_map_port_75=28 +xgxs_tx_lane_map_106=0x3210 +xgxs_rx_lane_map_106=0x2310 +phy_xaui_tx_polarity_flip_106=0x0 +phy_xaui_rx_polarity_flip_106=0x3 +phy_xaui_tx_polarity_flip_107=0x0 +phy_xaui_rx_polarity_flip_107=0x3 +port_phy_addr_106=0x12e +port_phy_addr_107=0x12e +dport_map_port_106=29 +dport_map_port_107=30 +xgxs_tx_lane_map_108=0x1032 +xgxs_rx_lane_map_108=0x0132 +phy_xaui_tx_polarity_flip_108=0x3 +phy_xaui_rx_polarity_flip_108=0x3 +phy_xaui_tx_polarity_flip_109=0x3 +phy_xaui_rx_polarity_flip_109=0x3 +port_phy_addr_108=0x12f +port_phy_addr_109=0x12f +dport_map_port_108=31 +dport_map_port_109=32 +port_phy_addr_7=0x5e +port_phy_addr_8=0x5e +xgxs_tx_lane_map_7=0x3210 +xgxs_rx_lane_map_7=0x0132 +phy_xaui_tx_polarity_flip_7=0x3 +phy_xaui_rx_polarity_flip_7=0x1 +phy_xaui_tx_polarity_flip_8=0x3 +phy_xaui_rx_polarity_flip_8=0x3 +dport_map_port_7=33 +dport_map_port_8=34 +port_phy_addr_5=0x5f +port_phy_addr_6=0x5f +xgxs_tx_lane_map_5=0x2301 +xgxs_rx_lane_map_5=0x1023 +phy_xaui_tx_polarity_flip_5=0x0 +phy_xaui_rx_polarity_flip_5=0x0 +phy_xaui_tx_polarity_flip_6=0x0 +phy_xaui_tx_polarity_flip_6=0x0 +dport_map_port_5=35 +dport_map_port_6=36 +port_phy_addr_116=0x4e +port_phy_addr_117=0x4e +phy_xaui_tx_polarity_flip_116=0x0 +phy_xaui_rx_polarity_flip_116=0x1 +phy_xaui_tx_polarity_flip_117=0x3 +phy_xaui_rx_polarity_flip_117=0x3 +xgxs_tx_lane_map_116=0x0123 +xgxs_rx_lane_map_116=0x3201 +dport_map_port_116=37 +dport_map_port_117=38 +port_phy_addr_114=0x4f +port_phy_addr_115=0x4f +phy_xaui_tx_polarity_flip_114=0x0 +phy_xaui_rx_polarity_flip_114=0x0 +phy_xaui_tx_polarity_flip_115=0x1 +phy_xaui_rx_polarity_flip_115=0x0 +xgxs_tx_lane_map_114=0x2301 +xgxs_rx_lane_map_114=0x1023 +dport_map_port_114=39 +dport_map_port_115=40 +port_phy_addr_82=0x7e +port_phy_addr_83=0x7e +xgxs_tx_lane_map_82=0x3210 +xgxs_rx_lane_map_82=0x2310 +phy_xaui_tx_polarity_flip_82=0x0 +phy_xaui_rx_polarity_flip_82=0x0 +dport_map_port_82=41 +dport_map_port_83=42 +port_phy_addr_80=0x7f +port_phy_addr_81=0x7f +xgxs_tx_lane_map_80=0x1032 +xgxs_rx_lane_map_80=0x0132 +phy_xaui_tx_polarity_flip_80=0x3 +phy_xaui_rx_polarity_flip_80=0x3 +phy_xaui_tx_polarity_flip_81=0x0 +phy_xaui_rx_polarity_flip_81=0x3 +dport_map_port_80=43 +dport_map_port_81=44 +xgxs_tx_lane_map_40=0x0123 +xgxs_rx_lane_map_40=0x0132 +port_phy_addr_40=0x6e +port_phy_addr_41=0x6e +phy_xaui_tx_polarity_flip_40=0x3 +phy_xaui_rx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0x3 +phy_xaui_rx_polarity_flip_41=0x0 +dport_map_port_40=45 +dport_map_port_41=46 +port_phy_addr_38=0x6f +port_phy_addr_39=0x6f +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_rx_polarity_flip_38=0x0 +xgxs_tx_lane_map_38=0x2301 +xgxs_rx_lane_map_38=0x2310 +dport_map_port_38=47 +dport_map_port_39=48 +xgxs_tx_lane_map_110=0x2013 +xgxs_rx_lane_map_110=0x3102 +phy_xaui_tx_polarity_flip_110=0x3 +phy_xaui_rx_polarity_flip_110=0x3 +phy_xaui_tx_polarity_flip_111=0x3 +phy_xaui_rx_polarity_flip_111=0x3 +port_phy_addr_110=0x15e +port_phy_addr_111=0x15e +dport_map_port_110=49 +dport_map_port_111=50 +xgxs_tx_lane_map_112=0x1032 +xgxs_rx_lane_map_112=0x2310 +phy_xaui_tx_polarity_flip_112=0x3 +phy_xaui_rx_polarity_flip_112=0x3 +phy_xaui_tx_polarity_flip_113=0x3 +phy_xaui_rx_polarity_flip_113=0x3 +port_phy_addr_112=0x15f +port_phy_addr_113=0x15f +dport_map_port_112=51 +dport_map_port_113=52 +port_phy_addr_1=0x14e +port_phy_addr_2=0x14e +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x3201 +phy_xaui_tx_polarity_flip_1=0x3 +phy_xaui_rx_polarity_flip_1=0x3 +phy_xaui_tx_polarity_flip_2=0x3 +phy_xaui_rx_polarity_flip_2=0x3 +dport_map_port_1=53 +dport_map_port_2=54 +xgxs_tx_lane_map_3=0x1023 +xgxs_rx_lane_map_3=0x2310 +port_phy_addr_3=0x14f +port_phy_addr_4=0x14f +phy_xaui_tx_polarity_flip_3=0x3 +phy_xaui_rx_polarity_flip_3=0x0 +phy_xaui_tx_polarity_flip_4=0x3 +phy_xaui_rx_polarity_flip_4=0x3 +dport_map_port_3=55 +dport_map_port_4=56 +port_phy_addr_34=0x17e +port_phy_addr_35=0x17e +xgxs_tx_lane_map_34=0x0123 +xgxs_rx_lane_map_34=0x0132 +phy_xaui_tx_polarity_flip_34=0x3 +phy_xaui_rx_polarity_flip_34=0x0 +phy_xaui_tx_polarity_flip_35=0x3 +phy_xaui_rx_polarity_flip_35=0x0 +dport_map_port_34=57 +dport_map_port_35=58 +port_phy_addr_36=0x17f +port_phy_addr_37=0x17f +xgxs_tx_lane_map_36=0x2301 +xgxs_rx_lane_map_36=0x2310 +phy_xaui_tx_polarity_flip_36=0x0 +phy_xaui_rx_polarity_flip_36=0x3 +phy_xaui_tx_polarity_flip_37=0x3 +phy_xaui_rx_polarity_flip_37=0x3 +dport_map_port_36=59 +dport_map_port_37=60 +port_phy_addr_76=0x16e +port_phy_addr_77=0x16e +xgxs_tx_lane_map_76=0x3210 +xgxs_rx_lane_map_76=0x2310 +phy_xaui_tx_polarity_flip_76=0x0 +phy_xaui_rx_polarity_flip_76=0x3 +phy_xaui_tx_polarity_flip_77=0x0 +phy_xaui_rx_polarity_flip_77=0x3 +dport_map_port_76=61 +dport_map_port_77=62 +port_phy_addr_78=0x16f +port_phy_addr_79=0x16f +xgxs_tx_lane_map_78=0x1032 +xgxs_rx_lane_map_78=0x0132 +phy_xaui_tx_polarity_flip_78=0x3 +phy_xaui_rx_polarity_flip_78=0x3 +phy_xaui_tx_polarity_flip_79=0x3 +phy_xaui_rx_polarity_flip_79=0x3 +dport_map_port_78=63 +dport_map_port_79=64 +pbmp_xport_xe=0x3fffd0000ffff40003fffc0001fffe +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 +portmap_1=1:40:2 +portmap_2=3:40:2 +portmap_3=5:40:2 +portmap_4=7:40:2 +portmap_5=9:40:2 +portmap_6=11:40:2 +portmap_7=13:40:2 +portmap_8=15:40:2 +portmap_9=17:40:2 +portmap_10=19:40:2 +portmap_11=21:40:2 +portmap_12=23:40:2 +portmap_13=25:40:2 +portmap_14=27:40:2 +portmap_15=29:40:2 +portmap_16=31:40:2 +portmap_34=33:40:2 +portmap_35=35:40:2 +portmap_36=37:40:2 +portmap_37=39:40:2 +portmap_38=41:40:2 +portmap_39=43:40:2 +portmap_40=45:40:2 +portmap_41=47:40:2 +portmap_42=49:40:2 +portmap_43=51:40:2 +portmap_44=53:40:2 +portmap_45=55:40:2 +portmap_46=57:40:2 +portmap_47=59:40:2 +portmap_48=61:40:2 +portmap_49=63:40:2 +portmap_68=65:40:2 +portmap_69=67:40:2 +portmap_70=69:40:2 +portmap_71=71:40:2 +portmap_72=73:40:2 +portmap_73=75:40:2 +portmap_74=77:40:2 +portmap_75=79:40:2 +portmap_76=81:40:2 +portmap_77=83:40:2 +portmap_78=85:40:2 +portmap_79=87:40:2 +portmap_80=89:40:2 +portmap_81=91:40:2 +portmap_82=93:40:2 +portmap_83=95:40:2 +portmap_102=97:40:2 +portmap_103=99:40:2 +portmap_104=101:40:2 +portmap_105=103:40:2 +portmap_106=105:40:2 +portmap_107=107:40:2 +portmap_108=109:40:2 +portmap_109=111:40:2 +portmap_110=113:40:2 +portmap_111=115:40:2 +portmap_112=117:40:2 +portmap_113=119:40:2 +portmap_114=121:40:2 +portmap_115=123:40:2 +portmap_116=125:40:2 +portmap_117=127:40:2 + +mmu_init_config="MSFT-TH-Tier0" diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t1.config.bcm b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t1.config.bcm new file mode 100644 index 000000000000..f55fb9d3ab51 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/Force10-S6100/th-s6100-64x40G-t1.config.bcm @@ -0,0 +1,410 @@ +#TH S6100 64x40 +l3_alpm_enable=2 +pfc_deadlock_seq_control=1 +bcm_stat_interval=2000000 +bcm_num_cos=10 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +oversubscribe_mode=1 +miim_intr_enable=0 + +phy_gearbox_enable=1 +phy_84752=1 +phy_ext_rom_boot=0 +rate_ext_mdio_divisor=0x80 + +serdes_fiber_pref_xe=0 +serdes_if_type_xe=14 + +fpem_mem_entries=32768 + +os=unix + +parity_correction=1 +parity_enable=1 + +xgxs_tx_lane_map_104=0x3210 +xgxs_rx_lane_map_104=0x0312 +phy_xaui_tx_polarity_flip_104=0x0 +phy_xaui_rx_polarity_flip_104=0x0 +port_phy_addr_104=0x1e +port_phy_addr_105=0x1e +dport_map_port_104=1 +dport_map_port_105=2 +xgxs_tx_lane_map_102=0x1032 +xgxs_rx_lane_map_102=0x0132 +phy_xaui_tx_polarity_flip_102=0x3 +phy_xaui_rx_polarity_flip_102=0x3 +phy_xaui_tx_polarity_flip_103=0x3 +phy_xaui_rx_polarity_flip_103=0x3 +port_phy_addr_102=0x1f +port_phy_addr_103=0x1f +dport_map_port_102=3 +dport_map_port_103=4 +xgxs_tx_lane_map_70=0x0123 +xgxs_rx_lane_map_70=0x3201 +phy_xaui_tx_polarity_flip_70=0x3 +phy_xaui_rx_polarity_flip_70=0x3 +phy_xaui_tx_polarity_flip_71=0x3 +phy_xaui_rx_polarity_flip_71=0x3 +port_phy_addr_70=0xE +port_phy_addr_71=0xE +dport_map_port_70=5 +dport_map_port_71=6 +xgxs_tx_lane_map_68=0x2301 +xgxs_rx_lane_map_68=0x1023 +phy_xaui_tx_polarity_flip_68=0x0 +phy_xaui_rx_polarity_flip_68=0x2 +phy_xaui_tx_polarity_flip_69=0x0 +phy_xaui_rx_polarity_flip_69=0x3 +port_phy_addr_68=0xF +port_phy_addr_69=0xF +dport_map_port_68=7 +dport_map_port_69=8 +xgxs_tx_lane_map_44=0x0123 +xgxs_rx_lane_map_44=0x3201 +phy_xaui_tx_polarity_flip_44=0x3 +phy_xaui_rx_polarity_flip_44=0x3 +phy_xaui_tx_polarity_flip_45=0x3 +phy_xaui_rx_polarity_flip_45=0x3 +port_phy_addr_44=0x3e +port_phy_addr_45=0x3e +dport_map_port_44=9 +dport_map_port_45=10 +xgxs_tx_lane_map_42=0x1032 +xgxs_rx_lane_map_42=0x2310 +phy_xaui_tx_polarity_flip_42=0x0 +phy_xaui_rx_polarity_flip_42=0x0 +phy_xaui_tx_polarity_flip_43=0x3 +phy_xaui_rx_polarity_flip_43=0x0 +port_phy_addr_42=0x3f +port_phy_addr_43=0x3f +dport_map_port_42=11 +dport_map_port_43=12 +xgxs_tx_lane_map_11=0x0123 +xgxs_rx_lane_map_11=0x3201 +phy_xaui_tx_polarity_flip_11=0x3 +phy_xaui_rx_polarity_flip_11=0x0 +phy_xaui_tx_polarity_flip_12=0x3 +phy_xaui_rx_polarity_flip_12=0x0 +port_phy_addr_11=0x2E +port_phy_addr_12=0x2E +dport_map_port_11=13 +dport_map_port_12=14 +xgxs_tx_lane_map_9=0x2310 +xgxs_rx_lane_map_9=0x1023 +phy_xaui_tx_polarity_flip_9=0x0 +phy_xaui_rx_polarity_flip_9=0x0 +phy_xaui_tx_polarity_flip_10=0x0 +phy_xaui_rx_polarity_flip_10=0x0 +port_phy_addr_9=0x2F +port_phy_addr_10=0x2F +dport_map_port_9=15 +dport_map_port_10=16 +xgxs_tx_lane_map_13=0x0123 +xgxs_rx_lane_map_13=0x0132 +phy_xaui_tx_polarity_flip_13=0x3 +phy_xaui_rx_polarity_flip_13=0x3 +phy_xaui_tx_polarity_flip_14=0x3 +phy_xaui_rx_polarity_flip_14=0x3 +port_phy_addr_13=0x11e +port_phy_addr_14=0x11e +dport_map_port_13=17 +dport_map_port_14=18 +xgxs_tx_lane_map_15=0x2301 +xgxs_rx_lane_map_15=0x2310 +phy_xaui_tx_polarity_flip_15=0x0 +phy_xaui_rx_polarity_flip_15=0x0 +port_phy_addr_15=0x11f +port_phy_addr_16=0x11f +dport_map_port_15=19 +dport_map_port_16=20 +xgxs_tx_lane_map_46=0x3210 +xgxs_rx_lane_map_46=0x0132 +phy_xaui_tx_polarity_flip_46=0x3 +phy_xaui_rx_polarity_flip_46=0x3 +phy_xaui_tx_polarity_flip_47=0x3 +phy_xaui_rx_polarity_flip_47=0x3 +port_phy_addr_46=0x10e +port_phy_addr_47=0x10e +dport_map_port_46=21 +dport_map_port_47=22 +xgxs_tx_lane_map_48=0x2301 +xgxs_rx_lane_map_48=0x1023 +phy_xaui_tx_polarity_flip_48=0x0 +phy_xaui_rx_polarity_flip_48=0x1 +port_phy_addr_48=0x10F +port_phy_addr_49=0x10F +dport_map_port_48=23 +dport_map_port_49=24 +xgxs_tx_lane_map_72=0x3210 +xgxs_rx_lane_map_72=0x0132 +phy_xaui_tx_polarity_flip_72=0x3 +phy_xaui_rx_polarity_flip_72=0x0 +phy_xaui_tx_polarity_flip_73=0x3 +phy_xaui_rx_polarity_flip_73=0x0 +port_phy_addr_72=0x13e +port_phy_addr_73=0x13e +dport_map_port_72=25 +dport_map_port_73=26 +xgxs_tx_lane_map_74=0x1320 +xgxs_rx_lane_map_74=0x2013 +phy_xaui_tx_polarity_flip_74=0x0 +phy_xaui_rx_polarity_flip_74=0x0 +phy_xaui_tx_polarity_flip_75=0x3 +phy_xaui_rx_polarity_flip_75=0x0 +port_phy_addr_74=0x13f +port_phy_addr_75=0x13f +dport_map_port_74=27 +dport_map_port_75=28 +xgxs_tx_lane_map_106=0x3210 +xgxs_rx_lane_map_106=0x2310 +phy_xaui_tx_polarity_flip_106=0x0 +phy_xaui_rx_polarity_flip_106=0x3 +phy_xaui_tx_polarity_flip_107=0x0 +phy_xaui_rx_polarity_flip_107=0x3 +port_phy_addr_106=0x12e +port_phy_addr_107=0x12e +dport_map_port_106=29 +dport_map_port_107=30 +xgxs_tx_lane_map_108=0x1032 +xgxs_rx_lane_map_108=0x0132 +phy_xaui_tx_polarity_flip_108=0x3 +phy_xaui_rx_polarity_flip_108=0x3 +phy_xaui_tx_polarity_flip_109=0x3 +phy_xaui_rx_polarity_flip_109=0x3 +port_phy_addr_108=0x12f +port_phy_addr_109=0x12f +dport_map_port_108=31 +dport_map_port_109=32 +port_phy_addr_7=0x5e +port_phy_addr_8=0x5e +xgxs_tx_lane_map_7=0x3210 +xgxs_rx_lane_map_7=0x0132 +phy_xaui_tx_polarity_flip_7=0x3 +phy_xaui_rx_polarity_flip_7=0x1 +phy_xaui_tx_polarity_flip_8=0x3 +phy_xaui_rx_polarity_flip_8=0x3 +dport_map_port_7=33 +dport_map_port_8=34 +port_phy_addr_5=0x5f +port_phy_addr_6=0x5f +xgxs_tx_lane_map_5=0x2301 +xgxs_rx_lane_map_5=0x1023 +phy_xaui_tx_polarity_flip_5=0x0 +phy_xaui_rx_polarity_flip_5=0x0 +phy_xaui_tx_polarity_flip_6=0x0 +phy_xaui_tx_polarity_flip_6=0x0 +dport_map_port_5=35 +dport_map_port_6=36 +port_phy_addr_116=0x4e +port_phy_addr_117=0x4e +phy_xaui_tx_polarity_flip_116=0x0 +phy_xaui_rx_polarity_flip_116=0x1 +phy_xaui_tx_polarity_flip_117=0x3 +phy_xaui_rx_polarity_flip_117=0x3 +xgxs_tx_lane_map_116=0x0123 +xgxs_rx_lane_map_116=0x3201 +dport_map_port_116=37 +dport_map_port_117=38 +port_phy_addr_114=0x4f +port_phy_addr_115=0x4f +phy_xaui_tx_polarity_flip_114=0x0 +phy_xaui_rx_polarity_flip_114=0x0 +phy_xaui_tx_polarity_flip_115=0x1 +phy_xaui_rx_polarity_flip_115=0x0 +xgxs_tx_lane_map_114=0x2301 +xgxs_rx_lane_map_114=0x1023 +dport_map_port_114=39 +dport_map_port_115=40 +port_phy_addr_82=0x7e +port_phy_addr_83=0x7e +xgxs_tx_lane_map_82=0x3210 +xgxs_rx_lane_map_82=0x2310 +phy_xaui_tx_polarity_flip_82=0x0 +phy_xaui_rx_polarity_flip_82=0x0 +dport_map_port_82=41 +dport_map_port_83=42 +port_phy_addr_80=0x7f +port_phy_addr_81=0x7f +xgxs_tx_lane_map_80=0x1032 +xgxs_rx_lane_map_80=0x0132 +phy_xaui_tx_polarity_flip_80=0x3 +phy_xaui_rx_polarity_flip_80=0x3 +phy_xaui_tx_polarity_flip_81=0x0 +phy_xaui_rx_polarity_flip_81=0x3 +dport_map_port_80=43 +dport_map_port_81=44 +xgxs_tx_lane_map_40=0x0123 +xgxs_rx_lane_map_40=0x0132 +port_phy_addr_40=0x6e +port_phy_addr_41=0x6e +phy_xaui_tx_polarity_flip_40=0x3 +phy_xaui_rx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0x3 +phy_xaui_rx_polarity_flip_41=0x0 +dport_map_port_40=45 +dport_map_port_41=46 +port_phy_addr_38=0x6f +port_phy_addr_39=0x6f +phy_xaui_tx_polarity_flip_38=0x0 +phy_xaui_rx_polarity_flip_38=0x0 +xgxs_tx_lane_map_38=0x2301 +xgxs_rx_lane_map_38=0x2310 +dport_map_port_38=47 +dport_map_port_39=48 +xgxs_tx_lane_map_110=0x2013 +xgxs_rx_lane_map_110=0x3102 +phy_xaui_tx_polarity_flip_110=0x3 +phy_xaui_rx_polarity_flip_110=0x3 +phy_xaui_tx_polarity_flip_111=0x3 +phy_xaui_rx_polarity_flip_111=0x3 +port_phy_addr_110=0x15e +port_phy_addr_111=0x15e +dport_map_port_110=49 +dport_map_port_111=50 +xgxs_tx_lane_map_112=0x1032 +xgxs_rx_lane_map_112=0x2310 +phy_xaui_tx_polarity_flip_112=0x3 +phy_xaui_rx_polarity_flip_112=0x3 +phy_xaui_tx_polarity_flip_113=0x3 +phy_xaui_rx_polarity_flip_113=0x3 +port_phy_addr_112=0x15f +port_phy_addr_113=0x15f +dport_map_port_112=51 +dport_map_port_113=52 +port_phy_addr_1=0x14e +port_phy_addr_2=0x14e +xgxs_tx_lane_map_1=0x0123 +xgxs_rx_lane_map_1=0x3201 +phy_xaui_tx_polarity_flip_1=0x3 +phy_xaui_rx_polarity_flip_1=0x3 +phy_xaui_tx_polarity_flip_2=0x3 +phy_xaui_rx_polarity_flip_2=0x3 +dport_map_port_1=53 +dport_map_port_2=54 +xgxs_tx_lane_map_3=0x1023 +xgxs_rx_lane_map_3=0x2310 +port_phy_addr_3=0x14f +port_phy_addr_4=0x14f +phy_xaui_tx_polarity_flip_3=0x3 +phy_xaui_rx_polarity_flip_3=0x0 +phy_xaui_tx_polarity_flip_4=0x3 +phy_xaui_rx_polarity_flip_4=0x3 +dport_map_port_3=55 +dport_map_port_4=56 +port_phy_addr_34=0x17e +port_phy_addr_35=0x17e +xgxs_tx_lane_map_34=0x0123 +xgxs_rx_lane_map_34=0x0132 +phy_xaui_tx_polarity_flip_34=0x3 +phy_xaui_rx_polarity_flip_34=0x0 +phy_xaui_tx_polarity_flip_35=0x3 +phy_xaui_rx_polarity_flip_35=0x0 +dport_map_port_34=57 +dport_map_port_35=58 +port_phy_addr_36=0x17f +port_phy_addr_37=0x17f +xgxs_tx_lane_map_36=0x2301 +xgxs_rx_lane_map_36=0x2310 +phy_xaui_tx_polarity_flip_36=0x0 +phy_xaui_rx_polarity_flip_36=0x3 +phy_xaui_tx_polarity_flip_37=0x3 +phy_xaui_rx_polarity_flip_37=0x3 +dport_map_port_36=59 +dport_map_port_37=60 +port_phy_addr_76=0x16e +port_phy_addr_77=0x16e +xgxs_tx_lane_map_76=0x3210 +xgxs_rx_lane_map_76=0x2310 +phy_xaui_tx_polarity_flip_76=0x0 +phy_xaui_rx_polarity_flip_76=0x3 +phy_xaui_tx_polarity_flip_77=0x0 +phy_xaui_rx_polarity_flip_77=0x3 +dport_map_port_76=61 +dport_map_port_77=62 +port_phy_addr_78=0x16f +port_phy_addr_79=0x16f +xgxs_tx_lane_map_78=0x1032 +xgxs_rx_lane_map_78=0x0132 +phy_xaui_tx_polarity_flip_78=0x3 +phy_xaui_rx_polarity_flip_78=0x3 +phy_xaui_tx_polarity_flip_79=0x3 +phy_xaui_rx_polarity_flip_79=0x3 +dport_map_port_78=63 +dport_map_port_79=64 +pbmp_xport_xe=0x3fffd0000ffff40003fffc0001fffe +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 +portmap_1=1:40:2 +portmap_2=3:40:2 +portmap_3=5:40:2 +portmap_4=7:40:2 +portmap_5=9:40:2 +portmap_6=11:40:2 +portmap_7=13:40:2 +portmap_8=15:40:2 +portmap_9=17:40:2 +portmap_10=19:40:2 +portmap_11=21:40:2 +portmap_12=23:40:2 +portmap_13=25:40:2 +portmap_14=27:40:2 +portmap_15=29:40:2 +portmap_16=31:40:2 +portmap_34=33:40:2 +portmap_35=35:40:2 +portmap_36=37:40:2 +portmap_37=39:40:2 +portmap_38=41:40:2 +portmap_39=43:40:2 +portmap_40=45:40:2 +portmap_41=47:40:2 +portmap_42=49:40:2 +portmap_43=51:40:2 +portmap_44=53:40:2 +portmap_45=55:40:2 +portmap_46=57:40:2 +portmap_47=59:40:2 +portmap_48=61:40:2 +portmap_49=63:40:2 +portmap_68=65:40:2 +portmap_69=67:40:2 +portmap_70=69:40:2 +portmap_71=71:40:2 +portmap_72=73:40:2 +portmap_73=75:40:2 +portmap_74=77:40:2 +portmap_75=79:40:2 +portmap_76=81:40:2 +portmap_77=83:40:2 +portmap_78=85:40:2 +portmap_79=87:40:2 +portmap_80=89:40:2 +portmap_81=91:40:2 +portmap_82=93:40:2 +portmap_83=95:40:2 +portmap_102=97:40:2 +portmap_103=99:40:2 +portmap_104=101:40:2 +portmap_105=103:40:2 +portmap_106=105:40:2 +portmap_107=107:40:2 +portmap_108=109:40:2 +portmap_109=111:40:2 +portmap_110=113:40:2 +portmap_111=115:40:2 +portmap_112=117:40:2 +portmap_113=119:40:2 +portmap_114=121:40:2 +portmap_115=123:40:2 +portmap_116=125:40:2 +portmap_117=127:40:2 + +mmu_init_config="MSFT-TH-Tier1" diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/bin/S6100-BIOS-3.25.0.2-7.bin b/device/dell/x86_64-dell_s6100_c2538-r0/bin/S6100-BIOS-3.25.0.2-7.bin new file mode 100644 index 000000000000..e6371a2602d6 Binary files /dev/null and b/device/dell/x86_64-dell_s6100_c2538-r0/bin/S6100-BIOS-3.25.0.2-7.bin differ diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/default_sku b/device/dell/x86_64-dell_s6100_c2538-r0/default_sku new file mode 100644 index 000000000000..0ab292005678 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/default_sku @@ -0,0 +1 @@ +Force10-S6100 t1 diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/installer.conf b/device/dell/x86_64-dell_s6100_c2538-r0/installer.conf new file mode 100644 index 000000000000..0932d0637760 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="module_blacklist=gpio_ich nos-config-part=/dev/sda12" diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/led_proc_init.soc b/device/dell/x86_64-dell_s6100_c2538-r0/led_proc_init.soc new file mode 100644 index 000000000000..a4a44f15bcf1 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/led_proc_init.soc @@ -0,0 +1,13 @@ +# LED microprocessor initialization for Dell S6100 + +led 0 stop +led 0 prog 02 00 60 FE 2E FE 67 2C 86 FE 67 5B 67 5B 67 5B 86 FE 2E FE 67 2C 86 FE 86 FE 06 FE D2 40 71 04 12 FF 85 05 D2 05 71 2A 52 00 3A A0 32 08 97 71 33 77 5B 32 00 32 01 B7 97 75 42 12 BC FE FE 02 0A 50 12 BC FE FE 95 75 4C 85 77 54 16 FF DA 02 71 5B 77 54 22 0E 87 22 0E 87 57 22 0F 87 22 0F 87 57 22 0F 87 22 0E 87 57 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 02 00 60 FE 2E FE 67 2C 86 FE 67 5B 67 5B 67 5B 86 FE 2E FE 67 2C 86 FE 86 FE 06 FE D2 40 71 04 12 FF 85 05 D2 05 71 2A 52 00 3A A0 32 08 97 71 33 77 5B 32 00 32 01 B7 97 75 42 12 BC FE FE 02 0A 50 12 BC FE FE 95 75 4C 85 77 54 16 FF DA 02 71 5B 77 54 22 0E 87 22 0E 87 57 22 0F 87 22 0F 87 57 22 0F 87 22 0E 87 57 +led 1 auto on +led 1 start + +led 2 stop diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/pcie.yaml b/device/dell/x86_64-dell_s6100_c2538-r0/pcie.yaml new file mode 100644 index 000000000000..650610c7b557 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/pcie.yaml @@ -0,0 +1,55 @@ +- bus: '00' + dev: '01' + fn: '0' + id: 1f10 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 1' +- bus: '00' + dev: '02' + fn: '0' + id: 1f11 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 2' +- bus: '00' + dev: '03' + fn: '0' + id: 1f12 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 3' +- bus: '00' + dev: '04' + fn: '0' + id: 1f13 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 4' +- bus: '00' + dev: 0f + fn: '0' + id: 1f16 + name: 'IOMMU: Intel Corporation Atom processor C2000 RCEC' +- bus: '00' + dev: '13' + fn: '0' + id: 1f15 + name: 'System peripheral: Intel Corporation Atom processor C2000 SMBus 2.0' +- bus: '00' + dev: '14' + fn: '0' + id: 1f41 + name: 'Ethernet controller: Intel Corporation Ethernet Connection I354' +- bus: '00' + dev: '14' + fn: '1' + id: 1f41 + name: 'Ethernet controller: Intel Corporation Ethernet Connection I354' +- bus: '00' + dev: '14' + fn: '2' + id: 1f41 + name: 'Ethernet controller: Intel Corporation Ethernet Connection I354' +- bus: '01' + dev: '00' + fn: '0' + id: b960 + name: 'Ethernet controller: Broadcom Limited Broadcom BCM56960 Switch ASIC' +- bus: '01' + dev: '00' + fn: '1' + id: b960 + name: 'Ethernet controller: Broadcom Limited Broadcom BCM56960 Switch ASIC' diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/platform.json b/device/dell/x86_64-dell_s6100_c2538-r0/platform.json new file mode 100644 index 000000000000..24e32b16bb15 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/platform.json @@ -0,0 +1,343 @@ +{ + "chassis": { + "name": "S6100-ON", + "components": [ + { + "name": "BIOS" + }, + { + "name": "CPLD" + }, + { + "name": "FPGA" + } + ], + "fans": [ + { + "name": "FanTray1-Fan1" + }, + { + "name": "FanTray2-Fan1" + }, + { + "name": "FanTray3-Fan1" + }, + { + "name": "FanTray4-Fan1" + } + ], + "fan_drawers":[ + { + "name": "FanTray1", + "fans": [ + { + "name": "FanTray1-Fan1" + } + ] + }, + { + "name": "FanTray2", + "fans": [ + { + "name": "FanTray2-Fan1" + } + ] + }, + { + "name": "FanTray3", + "fans": [ + { + "name": "FanTray3-Fan1" + } + ] + }, + { + "name": "FanTray4", + "fans": [ + { + "name": "FanTray4-Fan1" + } + ] + } + ], + "psus": [ + { + "name": "PSU1", + "fans": [ + { + "name": "PSU1 Fan" + } + ] + }, + { + "name": "PSU2", + "fans": [ + { + "name": "PSU2 Fan" + } + ] + } + ], + "thermals": [ + { + "name": "CPU On-board" + }, + { + "name": "ASIC On-board Front" + }, + { + "name": "System Front" + }, + { + "name": "ASIC On-board Rear" + }, + { + "name": "Front GE board" + }, + { + "name": "Front SFP+ board" + }, + { + "name": "CPU Core 0" + }, + { + "name": "CPU Core 1" + }, + { + "name": "CPU Core 2" + }, + { + "name": "CPU Core 3" + } + ], + "modules": [ + { + "name": "IOM1: 16x40G QSFP+ Module", + "components": [ + { + "name": "IOM1-CPLD" + } + ] + }, + { + "name": "IOM2: 16x40G QSFP+ Module", + "components": [ + { + "name": "IOM2-CPLD" + } + ] + }, + { + "name": "IOM3: 16x40G QSFP+ Module", + "components": [ + { + "name": "IOM3-CPLD" + } + ] + }, + { + "name": "IOM4: 16x40G QSFP+ Module", + "components": [ + { + "name": "IOM4-CPLD" + } + ] + } + ], + "sfps": [ + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + }, + { + "name": "QSFP+ or later" + } + ] + }, + "interfaces": {} +} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/plugins/eeprom.py b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/eeprom.py new file mode 100644 index 000000000000..12a318def38c --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/eeprom.py @@ -0,0 +1,31 @@ +############################################################################# +# Dell S6100 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0050/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) + + def serial_number_str(self, e): + """Return service tag instead of serial number""" + + (is_valid, results) = self.get_tlv_field(e, self._TLV_CODE_SERVICE_TAG) + if is_valid == False: + return "Bad service tag" + + # 'results' is a list containing 3 elements, type (int), length (int), + # and value (string) of the requested TLV + return results[2].decode('ascii') diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/plugins/psuutil.py b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/psuutil.py new file mode 100644 index 000000000000..a29d45f939bf --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/psuutil.py @@ -0,0 +1,83 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" +HWMON_NODE = os.listdir(HWMON_DIR)[0] + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + # Get a mailbox register + def get_pmc_register(self, reg_name): + mailbox_dir = HWMON_DIR + HWMON_NODE + retval = 'ERR' + mb_reg_file = mailbox_dir+'/' + reg_name + if (not os.path.isfile(mb_reg_file)): + logging.error(mb_reg_file + " not found !") + return retval + + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", mb_reg_file, "file !") + + 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 + """ + S6100_MAX_PSUS = 2 + return S6100_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 + psu_status = self.get_pmc_register('psu'+str(index)+'_presence') + if (psu_status != 'ERR'): + psu_status = int(psu_status, 16) + # Check for PSU statuse + if (~psu_status & 0b1000) or (psu_status & 0b0100): + 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_presence = self.get_pmc_register('psu'+str(index)+'_presence') + if (psu_presence != 'ERR'): + psu_presence = int(psu_presence, 16) + # Check for PSU presence + if (~psu_presence & 0b1): + status = 1 + + return status diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/plugins/sfputil.py b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/sfputil.py new file mode 100644 index 000000000000..a6a7cce72f56 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/plugins/sfputil.py @@ -0,0 +1,636 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# +# +-i2c----+--------+ +# | 6 | 7 | +# | +-------------+ | +# | |IOM1 | IOM3 | | +# | |IOM2 | IOM4 | | +# | +-------------+ | +# | 8 | 9 | +# +--------+--------+ + + +try: + import time + import os + import logging + import select + 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 = 0 + PORT_END = 63 + PORTS_IN_BLOCK = 64 + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 0: [6, 18, 34, 50, 66], + 1: [6, 19, 35, 51, 67], + 2: [6, 20, 36, 52, 68], + 3: [6, 21, 37, 53, 69], + 4: [6, 22, 38, 54, 70], + 5: [6, 23, 39, 55, 71], + 6: [6, 24, 40, 56, 72], + 7: [6, 25, 41, 57, 73], + 8: [6, 26, 42, 58, 74], + 9: [6, 27, 43, 59, 75], + 10: [6, 28, 44, 60, 76], + 11: [6, 29, 45, 61, 77], + 12: [6, 30, 46, 62, 78], + 13: [6, 31, 47, 63, 79], + 14: [6, 32, 48, 64, 80], + 15: [6, 33, 49, 65, 81], + 16: [8, 18, 34, 50, 66], + 17: [8, 19, 35, 51, 67], + 18: [8, 20, 36, 52, 68], + 19: [8, 21, 37, 53, 69], + 20: [8, 22, 38, 54, 70], + 21: [8, 23, 39, 55, 71], + 22: [8, 24, 40, 56, 72], + 23: [8, 25, 41, 57, 73], + 24: [8, 26, 42, 58, 74], + 25: [8, 27, 43, 59, 75], + 26: [8, 28, 44, 60, 76], + 27: [8, 29, 45, 61, 77], + 28: [8, 30, 46, 62, 78], + 29: [8, 31, 47, 63, 79], + 30: [8, 32, 48, 64, 80], + 31: [8, 33, 49, 65, 81], + 32: [7, 18, 34, 50, 66], + 33: [7, 19, 35, 51, 67], + 34: [7, 20, 36, 52, 68], + 35: [7, 21, 37, 53, 69], + 36: [7, 22, 38, 54, 70], + 37: [7, 23, 39, 55, 71], + 38: [7, 24, 40, 56, 72], + 39: [7, 25, 41, 57, 73], + 40: [7, 26, 42, 58, 74], + 41: [7, 27, 43, 59, 75], + 42: [7, 28, 44, 60, 76], + 43: [7, 29, 45, 61, 77], + 44: [7, 30, 46, 62, 78], + 45: [7, 31, 47, 63, 79], + 46: [7, 32, 48, 64, 80], + 47: [7, 33, 49, 65, 81], + 48: [9, 18, 34, 50, 66], + 49: [9, 19, 35, 51, 67], + 50: [9, 20, 36, 52, 68], + 51: [9, 21, 37, 53, 69], + 52: [9, 22, 38, 54, 70], + 53: [9, 23, 39, 55, 71], + 54: [9, 24, 40, 56, 72], + 55: [9, 25, 41, 57, 73], + 56: [9, 26, 42, 58, 74], + 57: [9, 27, 43, 59, 75], + 58: [9, 28, 44, 60, 76], + 59: [9, 29, 45, 61, 77], + 60: [9, 30, 46, 62, 78], + 61: [9, 31, 47, 63, 79], + 62: [9, 32, 48, 64, 80], + 63: [9, 33, 49, 65, 81] + } + + IOM_1_PORT_START = 0 + IOM_1_PORT_END = 15 + + IOM_2_PORT_START = 16 + IOM_2_PORT_END = 31 + + IOM_3_PORT_START = 32 + IOM_3_PORT_END = 47 + + IOM_4_PORT_START = 48 + IOM_4_PORT_END = 63 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/" + OIR_FD_PATH = "/sys/devices/platform/dell_ich.0/sci_int_gpio_sus6" + + oir_fd = -1 + epoll = -1 + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def iom1_port_start(self): + return self.IOM_1_PORT_START + + @property + def iom1_port_end(self): + return self.IOM_1_PORT_END + + @property + def iom2_port_start(self): + return self.IOM_2_PORT_START + + @property + def iom2_port_end(self): + return self.IOM_2_PORT_END + + @property + def iom3_port_start(self): + return self.IOM_3_PORT_START + + @property + def iom3_port_end(self): + return self.IOM_3_PORT_END + + @property + def iom4_port_start(self): + return self.IOM_4_PORT_START + + @property + def iom4_port_end(self): + return self.IOM_4_PORT_END + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def port_to_i2c_mapping(self): + return self._port_to_i2c_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom" + global port_to_eeprom_path + + for port_num in range(0, self.port_end + 1): + if port_num >= self.iom1_port_start and port_num <=\ + self.iom1_port_end: + assigned = 0 + # i2c-6 + for x in range(1, 5): + port_to_eeprom_path = eeprom_path.format( + self.port_to_i2c_mapping[port_num][0], + self.port_to_i2c_mapping[port_num][x]) + if (os.path.isfile(port_to_eeprom_path)): + self.port_to_eeprom_mapping[port_num] =\ + port_to_eeprom_path + assigned = 1 + elif (not assigned): + self.port_to_eeprom_mapping[port_num] =\ + "No IOM" + + elif(port_num >= self.iom2_port_start and + port_num <= self.iom2_port_end): + assigned = 0 + # i2c-8 + for x in range(1, 5): + port_to_eeprom_path = eeprom_path.format( + self.port_to_i2c_mapping[port_num][0], + self.port_to_i2c_mapping[port_num][x]) + if (os.path.isfile(port_to_eeprom_path)): + self.port_to_eeprom_mapping[port_num] =\ + port_to_eeprom_path + assigned = 1 + elif (not assigned): + self.port_to_eeprom_mapping[port_num] =\ + "No IOM" + + elif(port_num >= self.iom3_port_start and port_num <= + self.iom3_port_end): + assigned = 0 + # i2c-7 + for x in range(1, 5): + port_to_eeprom_path = eeprom_path.format( + self.port_to_i2c_mapping[port_num][0], + self.port_to_i2c_mapping[port_num][x]) + if (os.path.isfile(port_to_eeprom_path)): + self.port_to_eeprom_mapping[port_num] =\ + port_to_eeprom_path + assigned = 1 + elif (not assigned): + self.port_to_eeprom_mapping[port_num] =\ + "No IOM" + + elif(port_num >= self.iom4_port_start and port_num <= + self.iom4_port_end): + assigned = 0 + # i2c-9 + for x in range(1, 5): + port_to_eeprom_path = eeprom_path.format( + self.port_to_i2c_mapping[port_num][0], + self.port_to_i2c_mapping[port_num][x]) + if (os.path.isfile(port_to_eeprom_path)): + self.port_to_eeprom_mapping[port_num] =\ + port_to_eeprom_path + assigned = 1 + elif (not assigned): + self.port_to_eeprom_mapping[port_num] =\ + "No IOM" + + SfpUtilBase.__init__(self) + + def __del__(self): + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + + def get_presence(self, port_num): + + global i2c_line + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # port_num and i2c match + if(port_num >= self.iom1_port_start and port_num <= + self.iom1_port_end): + i2c_line = 14 + elif(port_num >= self.iom2_port_start and port_num <= + self.iom2_port_end): + i2c_line = 16 + elif(port_num >= self.iom3_port_start and port_num <= + self.iom3_port_end): + i2c_line = 15 + elif(port_num >= self.iom4_port_start and port_num <= + self.iom4_port_end): + i2c_line = 17 + + try: + qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_modprs" + reg_file = open(qsfp_path, "r") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # Absence of IOM throws read error + if (content == 'read error'): + return False + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Rationalize port settings + if port_num > 15: + port_num = port_num % 16 + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # port_num and i2c match + if(port_num >= self.iom1_port_start and port_num <= + self.iom1_port_end): + i2c_line = 14 + elif(port_num >= self.iom2_port_start and port_num <= + self.iom2_port_end): + i2c_line = 16 + elif(port_num >= self.iom3_port_start and port_num <= + self.iom3_port_end): + i2c_line = 15 + elif(port_num >= self.iom4_port_start and port_num <= + self.iom4_port_end): + i2c_line = 17 + + try: + qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" + reg_file = open(qsfp_path, "r") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # Absence of IOM throws read error + if (content == 'read error'): + return False + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Rationalize port settings + if port_num > 15: + port_num = port_num % 16 + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # port_num and i2c match + if(port_num >= self.iom1_port_start and port_num <= + self.iom1_port_end): + i2c_line = 14 + elif(port_num >= self.iom2_port_start and port_num <= + self.iom2_port_end): + i2c_line = 16 + elif(port_num >= self.iom3_port_start and port_num <= + self.iom3_port_end): + i2c_line = 15 + elif(port_num >= self.iom4_port_start and port_num <= + self.iom4_port_end): + i2c_line = 17 + + try: + qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" + reg_file = open(qsfp_path, "r+") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # Absence of IOM throws read error + if (content == 'read error'): + return False + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Rationalize port settings + if port_num > 15: + port_num = port_num % 16 + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + + global i2c_line + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # port_num and i2c match + if(port_num >= self.iom1_port_start and port_num <= + self.iom1_port_end): + i2c_line = 14 + elif(port_num >= self.iom2_port_start and port_num <= + self.iom2_port_end): + i2c_line = 16 + elif(port_num >= self.iom3_port_start and port_num <= + self.iom3_port_end): + i2c_line = 15 + elif(port_num >= self.iom4_port_start and port_num <= + self.iom4_port_end): + i2c_line = 17 + + try: + qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" + reg_file = open(qsfp_path, "r+") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # Absence of IOM throws read error + if (content == 'read error'): + print("it's empty") + return False + + # File content is a string containing the hex representation + # of the register + reg_value = int(content, 16) + + # Rationalize port settings + if port_num > 15: + port_num = port_num % 16 + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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: + qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" + reg_file = open(qsfp_path, "w") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def get_register(self, reg_file): + retval = 'ERR' + + if (not os.path.isfile(reg_file)): + print(reg_file + ' not found !') + return retval + + try: + with open(reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", reg_file, "file !") + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + + def check_interrupts(self, port_dict): + retval = 0 + is_port_dict_updated = False + + # Read the QSFP ABS interrupt & status registers + cpld2_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_int") + cpld2_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_sta") + cpld3_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_int") + cpld3_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_sta") + cpld4_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_int") + cpld4_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_sta") + cpld5_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_abs_int") + cpld5_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_abs_sta") + + if (cpld2_abs_int == 'ERR' or cpld2_abs_sta == 'ERR' or + cpld3_abs_int == 'ERR' or cpld3_abs_sta == 'ERR' or + cpld4_abs_int == 'ERR' or cpld4_abs_sta == 'ERR' or + cpld5_abs_int == 'ERR' or cpld5_abs_sta == 'ERR'): + return -1 + + # If IOM is not present, interrupt will return 'read error' + # Handle the scenario gracefully + if (cpld2_abs_int == 'read error'): + cpld2_abs_int = "0x0" + cpld2_abs_sta = "0x0" + if (cpld3_abs_int == 'read error'): + cpld3_abs_int = "0x0" + cpld3_abs_sta = "0x0" + if (cpld4_abs_int == 'read error'): + cpld4_abs_int = "0x0" + cpld4_abs_sta = "0x0" + if (cpld5_abs_int == 'read error'): + cpld5_abs_int = "0x0" + cpld5_abs_sta = "0x0" + + cpld2_abs_int = int(cpld2_abs_int, 16) + cpld2_abs_sta = int(cpld2_abs_sta, 16) + cpld3_abs_int = int(cpld3_abs_int, 16) + cpld3_abs_sta = int(cpld3_abs_sta, 16) + cpld4_abs_int = int(cpld4_abs_int, 16) + cpld4_abs_sta = int(cpld4_abs_sta, 16) + cpld5_abs_int = int(cpld5_abs_int, 16) + cpld5_abs_sta = int(cpld5_abs_sta, 16) + + # Make it contiguous + interrupt_reg = (cpld2_abs_int & 0xffff) | \ + ((cpld4_abs_int & 0xffff) << 16) | \ + ((cpld3_abs_int & 0xffff) << 32) | \ + ((cpld5_abs_int & 0xffff) << 48) + status_reg = (cpld2_abs_sta & 0xffff) | \ + ((cpld4_abs_sta & 0xffff) << 16) | \ + ((cpld3_abs_sta & 0xffff) << 32) | \ + ((cpld5_abs_sta & 0xffff) << 48) + + port = self.port_start + while port <= self.port_end: + if interrupt_reg & (1 << port): + # update only if atleast one port has generated + # interrupt + is_port_dict_updated = True + if status_reg & (1 << port): + # status reg 1 => optics is removed + port_dict[port] = '0' + else: + # status reg 0 => optics is inserted + port_dict[port] = '1' + port += 1 + return retval, is_port_dict_updated + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + try: + # We get notified when there is an SCI interrupt from GPIO SUS6 + # Open the sysfs file and register the epoll object + self.oir_fd = open(self.OIR_FD_PATH, "r") + if self.oir_fd != -1: + # Do a dummy read before epoll register + self.oir_fd.read() + self.epoll = select.epoll() + self.epoll.register(self.oir_fd.fileno(), + select.EPOLLIN & select.EPOLLET) + else: + print("get_transceiver_change_event : unable to create fd") + return False, {} + + # Check for missed interrupts by invoking self.check_interrupts + # which will update the port_dict. + while True: + interrupt_count_start = self.get_register(self.OIR_FD_PATH) + + retval, is_port_dict_updated = \ + self.check_interrupts(port_dict) + if ((retval == 0) and (is_port_dict_updated is True)): + return True, port_dict + + interrupt_count_end = self.get_register(self.OIR_FD_PATH) + + if (interrupt_count_start == 'ERR' or + interrupt_count_end == 'ERR'): + print("get_transceiver_change_event : \ + unable to retrive interrupt count") + break + + # check_interrupts() itself may take upto 100s of msecs. + # We detect a missed interrupt based on the count + if interrupt_count_start == interrupt_count_end: + break + + # Block until an xcvr is inserted or removed with timeout = -1 + events = self.epoll.poll( + timeout=timeout if timeout != 0 else -1) + if events: + # check interrupts and return the port_dict + retval, is_port_dict_updated = \ + self.check_interrupts(port_dict) + if (retval != 0): + return False, {} + + return True, port_dict + except: + return False, {} + finally: + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + self.oir_fd = -1 + self.epoll = -1 + + return False, {} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json b/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..94592fa8cebc --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/sensors.conf b/device/dell/x86_64-dell_s6100_c2538-r0/sensors.conf new file mode 100644 index 000000000000..dfb1aa7c92b1 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/sensors.conf @@ -0,0 +1,29 @@ +chip "SMF_S6100_ON-isa-0000" +label power1 "PSU1 Input Power" +label power2 "PSU1 Output Power" +label power3 "PSU2 Input Power" +label power4 "PSU2 Output Power" +label temp14 "PSU1 Temp" +label temp15 "PSU2 Temp" +label curr601 "PSU1 Input Current" +label curr602 "PSU1 Output Current" +label curr701 "PSU2 Input Current" +label curr702 "PSU2 Output Current" +ignore temp12 +ignore temp13 +ignore in101 +ignore in102 +ignore in103 +ignore in104 +ignore in201 +ignore in202 +ignore in203 +ignore in204 +ignore in301 +ignore in302 +ignore in303 +ignore in304 +ignore in401 +ignore in402 +ignore in403 +ignore in404 diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/system_health_monitoring_config.json b/device/dell/x86_64-dell_s6100_c2538-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..bb8ffbcd2172 --- /dev/null +++ b/device/dell/x86_64-dell_s6100_c2538-r0/system_health_monitoring_config.json @@ -0,0 +1,11 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "amber", + "normal": "green", + "booting": "blinking green" + } +} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers.json.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers_defaults_t1.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..fa78303b2468 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/buffers_defaults_t1.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,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": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/led_proc_init.soc b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/led_proc_init.soc new file mode 100644 index 000000000000..dd30163ddcf6 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/led_proc_init.soc @@ -0,0 +1,51 @@ +# LED microprocessor initialization for Dell Z9100 +# +# +#Led0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=19 REMAP_PORT_9=18 REMAP_PORT_10=17 REMAP_PORT_11=16 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=23 REMAP_PORT_13=22 REMAP_PORT_14=21 REMAP_PORT_15=20 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=27 REMAP_PORT_1=26 REMAP_PORT_2=25 REMAP_PORT_3=24 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=31 REMAP_PORT_5=30 REMAP_PORT_6=29 REMAP_PORT_7=28 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 REMAP_PORT_41=34 REMAP_PORT_42=33 REMAP_PORT_43=32 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=39 REMAP_PORT_45=38 REMAP_PORT_46=37 REMAP_PORT_47=36 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=43 REMAP_PORT_33=42 REMAP_PORT_34=41 REMAP_PORT_35=40 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=47 REMAP_PORT_37=46 REMAP_PORT_38=45 REMAP_PORT_39=44 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=51 REMAP_PORT_25=50 REMAP_PORT_26=49 REMAP_PORT_27=48 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=55 REMAP_PORT_29=54 REMAP_PORT_30=53 REMAP_PORT_31=52 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=59 REMAP_PORT_17=58 REMAP_PORT_18=57 REMAP_PORT_19=56 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=63 REMAP_PORT_21=62 REMAP_PORT_22=61 REMAP_PORT_23=60 + +#Led1 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=3 REMAP_PORT_17=2 REMAP_PORT_18=1 REMAP_PORT_19=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=7 REMAP_PORT_21=6 REMAP_PORT_22=5 REMAP_PORT_23=4 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=11 REMAP_PORT_25=10 REMAP_PORT_26=9 REMAP_PORT_27=8 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=15 REMAP_PORT_29=14 REMAP_PORT_30=13 REMAP_PORT_31=12 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 REMAP_PORT_33=18 REMAP_PORT_34=17 REMAP_PORT_35=16 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 REMAP_PORT_41=26 REMAP_PORT_42=25 REMAP_PORT_43=24 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 REMAP_PORT_45=30 REMAP_PORT_46=29 REMAP_PORT_47=28 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=35 REMAP_PORT_5=34 REMAP_PORT_6=33 REMAP_PORT_7=32 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=39 REMAP_PORT_1=38 REMAP_PORT_2=37 REMAP_PORT_3=36 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=43 REMAP_PORT_13=42 REMAP_PORT_14=41 REMAP_PORT_15=40 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=47 REMAP_PORT_9=46 REMAP_PORT_10=45 REMAP_PORT_11=44 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 stop +led 0 prog 02 A8 60 AA 02 00 60 A7 02 00 60 FE 02 00 60 AB 06 A7 D2 08 74 20 02 A9 60 AA 06 A7 E2 08 60 A7 06 FE 28 67 3D 86 FE 06 FE 86 AB 06 AB D2 04 71 10 86 A7 06 FE D2 40 71 0C 86 FF 3A 80 32 08 97 71 7C 77 4C 57 22 0E 87 22 0E 87 57 22 0F 87 22 0F 87 57 22 0F 87 22 0E 87 57 06 AA 61 A6 16 A7 49 27 16 A6 97 71 53 77 45 57 02 0A 50 95 75 74 85 75 5A 57 16 FF CA 05 74 4C 77 5A 06 FE 12 BC F8 32 00 32 01 B7 97 71 6A 77 5A +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 02 A8 60 AA 02 00 60 A7 02 00 60 FE 02 00 60 AB 06 A7 D2 08 74 20 02 A9 60 AA 06 A7 E2 08 60 A7 06 FE 28 67 3D 86 FE 06 FE 86 AB 06 AB D2 04 71 10 86 A7 06 FE D2 40 71 0C 86 FF 3A 80 32 08 97 71 7C 77 4C 57 22 0E 87 22 0E 87 57 22 0F 87 22 0F 87 57 22 0F 87 22 0E 87 57 06 AA 61 A6 16 A7 49 27 16 A6 97 71 53 77 45 57 02 0A 50 95 75 74 85 75 5A 57 16 FF CA 05 74 4C 77 5A 06 FE 12 BC F8 32 00 32 01 B7 97 71 6A 77 5A + +led 1 auto on +led 1 start + +led 2 stop diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/pg_profile_lookup.ini b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/pg_profile_lookup.ini new file mode 100644 index 000000000000..aedda37a8878 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -3 2288 + 25000 5m 1248 2288 53248 -3 2288 + 40000 5m 1248 2288 66560 -3 2288 + 50000 5m 1248 2288 90272 -3 2288 + 100000 5m 1248 2288 165568 -3 2288 + 10000 40m 1248 2288 37024 -3 2288 + 25000 40m 1248 2288 53248 -3 2288 + 40000 40m 1248 2288 71552 -3 2288 + 50000 40m 1248 2288 96096 -3 2288 + 100000 40m 1248 2288 177632 -3 2288 + 10000 300m 1248 2288 46176 -3 2288 + 25000 300m 1248 2288 79040 -3 2288 + 40000 300m 1248 2288 108160 -3 2288 + 50000 300m 1248 2288 141856 -3 2288 + 100000 300m 1248 2288 268736 -3 2288 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/port_config.ini b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/port_config.ini new file mode 100644 index 000000000000..6a8e8351f8b0 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 49,50,51,52 hundredGigE1/1 1 +Ethernet4 53,54,55,56 hundredGigE1/2 2 +Ethernet8 57,58,59,60 hundredGigE1/3 3 +Ethernet12 61,62,63,64 hundredGigE1/4 4 +Ethernet16 65,66,67,68 hundredGigE1/5 5 +Ethernet20 69,70,71,72 hundredGigE1/6 6 +Ethernet24 73,74,75,76 hundredGigE1/7 7 +Ethernet28 77,78,79,80 hundredGigE1/8 8 +Ethernet32 37,38,39,40 hundredGigE1/9 9 +Ethernet36 33,34,35,36 hundredGigE1/10 10 +Ethernet40 45,46,47,48 hundredGigE1/11 11 +Ethernet44 41,42,43,44 hundredGigE1/12 12 +Ethernet48 81,82,83,84 hundredGigE1/13 13 +Ethernet52 85,86,87,88 hundredGigE1/14 14 +Ethernet56 89,90,91,92 hundredGigE1/15 15 +Ethernet60 93,94,95,96 hundredGigE1/16 16 +Ethernet64 97,98,99,100 hundredGigE1/17 17 +Ethernet68 101,102,103,104 hundredGigE1/18 18 +Ethernet72 105,106,107,108 hundredGigE1/19 19 +Ethernet76 109,110,111,112 hundredGigE1/20 20 +Ethernet80 21,22,23,24 hundredGigE1/21 21 +Ethernet84 17,18,19,20 hundredGigE1/22 22 +Ethernet88 29,30,31,32 hundredGigE1/23 23 +Ethernet92 25,26,27,28 hundredGigE1/24 24 +Ethernet96 117,118,119,120 hundredGigE1/25 25 +Ethernet100 113,114,115,116 hundredGigE1/26 26 +Ethernet104 125,126,127,128 hundredGigE1/27 27 +Ethernet108 121,122,123,124 hundredGigE1/28 28 +Ethernet112 5,6,7,8 hundredGigE1/29 29 +Ethernet116 1,2,3,4 hundredGigE1/30 30 +Ethernet120 13,14,15,16 hundredGigE1/31 31 +Ethernet124 9,10,11,12 hundredGigE1/32 32 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/qos.json.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/sai.profile b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/sai.profile new file mode 100644 index 000000000000..1076ddfe28f4 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-z9100-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/th-z9100-32x100G.config.bcm b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/th-z9100-32x100G.config.bcm new file mode 100644 index 000000000000..48fa30d78111 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C32/th-z9100-32x100G.config.bcm @@ -0,0 +1,230 @@ +#TH Z9100 32x100 + +l3_alpm_enable=2 +pfc_deadlock_seq_control=1 +bcm_stat_interval=2000000 +bcm_num_cos=10 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +oversubscribe_mode=1 +os=unix + +pbmp_oversubscribe=0x3fd000000ff4000003fc000001fe +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + +serdes_if_type_xe=14 +serdes_if_type_ce=14 + +#Parity +parity_correction=1 +parity_enable=1 + +#Port configuration +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_35=37:100 +portmap_34=33:100 +portmap_37=45:100 +portmap_36=41:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_6=21:100 +portmap_5=17:100 +portmap_8=29:100 +portmap_7=25:100 +portmap_107=117:100 +portmap_106=113:100 +portmap_109=125:100 +portmap_108=121:100 +portmap_2=5:100 +portmap_1=1:100 +portmap_4=13:100 +portmap_3=9:100 +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +xgxs_tx_lane_map_ce0=0x0132 +xgxs_tx_lane_map_ce1=0x2301 +xgxs_tx_lane_map_ce2=0x0123 +xgxs_tx_lane_map_ce3=0x3201 +xgxs_tx_lane_map_ce4=0x3210 +xgxs_tx_lane_map_ce5=0x2301 +xgxs_tx_lane_map_ce6=0x0123 +xgxs_tx_lane_map_ce7=0x1320 +xgxs_tx_lane_map_ce8=0x1032 +xgxs_tx_lane_map_ce9=0x2031 +xgxs_tx_lane_map_ce10=0x1023 +xgxs_tx_lane_map_ce11=0x0132 +xgxs_tx_lane_map_ce12=0x0213 +xgxs_tx_lane_map_ce13=0x1032 +xgxs_tx_lane_map_ce14=0x0132 +xgxs_tx_lane_map_ce15=0x0123 +xgxs_tx_lane_map_ce16=0x0123 +xgxs_tx_lane_map_ce17=0x0123 +xgxs_tx_lane_map_ce18=0x1032 +xgxs_tx_lane_map_ce19=0x0123 +xgxs_tx_lane_map_ce20=0x2301 +xgxs_tx_lane_map_ce21=0x3102 +xgxs_tx_lane_map_ce22=0x1023 +xgxs_tx_lane_map_ce23=0x2130 +xgxs_tx_lane_map_ce24=0x2310 +xgxs_tx_lane_map_ce25=0x2013 +xgxs_tx_lane_map_ce26=0x0132 +xgxs_tx_lane_map_ce27=0x0123 +xgxs_tx_lane_map_ce28=0x0213 +xgxs_tx_lane_map_ce29=0x0123 +xgxs_tx_lane_map_ce30=0x2301 +xgxs_tx_lane_map_ce31=0x0123 + +xgxs_rx_lane_map_ce0=0x1023 +xgxs_rx_lane_map_ce1=0x1302 +xgxs_rx_lane_map_ce2=0x1203 +xgxs_rx_lane_map_ce3=0x1302 +xgxs_rx_lane_map_ce4=0x3201 +xgxs_rx_lane_map_ce5=0x1302 +xgxs_rx_lane_map_ce6=0x1203 +xgxs_rx_lane_map_ce7=0x2301 +xgxs_rx_lane_map_ce8=0x0312 +xgxs_rx_lane_map_ce9=0x1302 +xgxs_rx_lane_map_ce10=0x2103 +xgxs_rx_lane_map_ce11=0x3210 +xgxs_rx_lane_map_ce12=0x2301 +xgxs_rx_lane_map_ce13=0x0213 +xgxs_rx_lane_map_ce14=0x3210 +xgxs_rx_lane_map_ce15=0x3210 +xgxs_rx_lane_map_ce16=0x3201 +xgxs_rx_lane_map_ce17=0x0213 +xgxs_rx_lane_map_ce18=0x3210 +xgxs_rx_lane_map_ce19=0x3210 +xgxs_rx_lane_map_ce20=0x3102 +xgxs_rx_lane_map_ce21=0x2103 +xgxs_rx_lane_map_ce22=0x2301 +xgxs_rx_lane_map_ce23=0x2310 +xgxs_rx_lane_map_ce24=0x3201 +xgxs_rx_lane_map_ce25=0x0123 +xgxs_rx_lane_map_ce26=0x1023 +xgxs_rx_lane_map_ce27=0x0213 +xgxs_rx_lane_map_ce28=0x1203 +xgxs_rx_lane_map_ce29=0x0213 +xgxs_rx_lane_map_ce30=0x3201 +xgxs_rx_lane_map_ce31=0x0213 + +phy_xaui_tx_polarity_flip_ce0=0xe +phy_xaui_tx_polarity_flip_ce1=0x2 +phy_xaui_tx_polarity_flip_ce2=0xa +phy_xaui_tx_polarity_flip_ce3=0xb +phy_xaui_tx_polarity_flip_ce4=0x2 +phy_xaui_tx_polarity_flip_ce5=0x0 +phy_xaui_tx_polarity_flip_ce6=0x0 +phy_xaui_tx_polarity_flip_ce7=0xa +phy_xaui_tx_polarity_flip_ce8=0x0 +phy_xaui_tx_polarity_flip_ce9=0xb +phy_xaui_tx_polarity_flip_ce10=0xe +phy_xaui_tx_polarity_flip_ce11=0x6 +phy_xaui_tx_polarity_flip_ce12=0x6 +phy_xaui_tx_polarity_flip_ce13=0xf +phy_xaui_tx_polarity_flip_ce14=0x5 +phy_xaui_tx_polarity_flip_ce15=0x8 +phy_xaui_tx_polarity_flip_ce16=0xf +phy_xaui_tx_polarity_flip_ce17=0xf +phy_xaui_tx_polarity_flip_ce18=0xf +phy_xaui_tx_polarity_flip_ce19=0xf +phy_xaui_tx_polarity_flip_ce20=0xf +phy_xaui_tx_polarity_flip_ce21=0xf +phy_xaui_tx_polarity_flip_ce22=0xb +phy_xaui_tx_polarity_flip_ce23=0xa +phy_xaui_tx_polarity_flip_ce24=0xf +phy_xaui_tx_polarity_flip_ce25=0x0 +phy_xaui_tx_polarity_flip_ce26=0xb +phy_xaui_tx_polarity_flip_ce27=0x7 +phy_xaui_tx_polarity_flip_ce28=0x8 +phy_xaui_tx_polarity_flip_ce29=0x3 +phy_xaui_tx_polarity_flip_ce30=0xc +phy_xaui_tx_polarity_flip_ce31=0x3 + +phy_xaui_rx_polarity_flip_ce0=0xc +phy_xaui_rx_polarity_flip_ce1=0xd +phy_xaui_rx_polarity_flip_ce2=0x2 +phy_xaui_rx_polarity_flip_ce3=0xf +phy_xaui_rx_polarity_flip_ce4=0xc +phy_xaui_rx_polarity_flip_ce5=0x2 +phy_xaui_rx_polarity_flip_ce6=0x2 +phy_xaui_rx_polarity_flip_ce7=0xd +phy_xaui_rx_polarity_flip_ce8=0xd +phy_xaui_rx_polarity_flip_ce9=0xa +phy_xaui_rx_polarity_flip_ce10=0x7 +phy_xaui_rx_polarity_flip_ce11=0xf +phy_xaui_rx_polarity_flip_ce12=0xf +phy_xaui_rx_polarity_flip_ce13=0xd +phy_xaui_rx_polarity_flip_ce14=0x4 +phy_xaui_rx_polarity_flip_ce15=0xb +phy_xaui_rx_polarity_flip_ce16=0x2 +phy_xaui_rx_polarity_flip_ce17=0xd +phy_xaui_rx_polarity_flip_ce18=0xf +phy_xaui_rx_polarity_flip_ce19=0x0 +phy_xaui_rx_polarity_flip_ce20=0x0 +phy_xaui_rx_polarity_flip_ce21=0x5 +phy_xaui_rx_polarity_flip_ce22=0x0 +phy_xaui_rx_polarity_flip_ce23=0x2 +phy_xaui_rx_polarity_flip_ce24=0xc +phy_xaui_rx_polarity_flip_ce25=0x8 +phy_xaui_rx_polarity_flip_ce26=0x4 +phy_xaui_rx_polarity_flip_ce27=0x7 +phy_xaui_rx_polarity_flip_ce28=0x7 +phy_xaui_rx_polarity_flip_ce29=0x9 +phy_xaui_rx_polarity_flip_ce30=0xc +phy_xaui_rx_polarity_flip_ce31=0x8 + +dport_map_port_38=1 +dport_map_port_39=2 +dport_map_port_40=3 +dport_map_port_41=4 +dport_map_port_68=5 +dport_map_port_69=6 +dport_map_port_70=7 +dport_map_port_71=8 +dport_map_port_35=9 +dport_map_port_34=10 +dport_map_port_37=11 +dport_map_port_36=12 +dport_map_port_72=13 +dport_map_port_73=14 +dport_map_port_74=15 +dport_map_port_75=16 +dport_map_port_102=17 +dport_map_port_103=18 +dport_map_port_104=19 +dport_map_port_105=20 +dport_map_port_6=21 +dport_map_port_5=22 +dport_map_port_8=23 +dport_map_port_7=24 +dport_map_port_107=25 +dport_map_port_106=26 +dport_map_port_109=27 +dport_map_port_108=28 +dport_map_port_2=29 +dport_map_port_1=30 +dport_map_port_4=31 +dport_map_port_3=32 + +mmu_init_config="MSFT-TH-Tier1" diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers.json.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers_defaults_t0.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..fa5b0fc5a52b --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/buffers_defaults_t0.j2 @@ -0,0 +1,61 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,6) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(10,26) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(30,32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(6,10) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(26,30) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/led_proc_init.soc b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/led_proc_init.soc new file mode 100644 index 000000000000..487c9fb7dcd9 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/led_proc_init.soc @@ -0,0 +1,58 @@ +# LED microprocessor initialization for Dell Z9100 +# +# +#Led0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=19 REMAP_PORT_9=18 REMAP_PORT_10=17 REMAP_PORT_11=16 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=23 REMAP_PORT_13=22 REMAP_PORT_14=21 REMAP_PORT_15=20 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=27 REMAP_PORT_1=26 REMAP_PORT_2=25 REMAP_PORT_3=24 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=31 REMAP_PORT_5=30 REMAP_PORT_6=29 REMAP_PORT_7=28 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 REMAP_PORT_41=34 REMAP_PORT_42=33 REMAP_PORT_43=32 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=39 REMAP_PORT_45=38 REMAP_PORT_46=37 REMAP_PORT_47=36 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=43 REMAP_PORT_33=42 REMAP_PORT_34=41 REMAP_PORT_35=40 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=47 REMAP_PORT_37=46 REMAP_PORT_38=45 REMAP_PORT_39=44 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=51 REMAP_PORT_25=50 REMAP_PORT_26=49 REMAP_PORT_27=48 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=55 REMAP_PORT_29=54 REMAP_PORT_30=53 REMAP_PORT_31=52 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=59 REMAP_PORT_17=58 REMAP_PORT_18=57 REMAP_PORT_19=56 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=63 REMAP_PORT_21=62 REMAP_PORT_22=61 REMAP_PORT_23=60 + +#Led1 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=3 REMAP_PORT_17=2 REMAP_PORT_18=1 REMAP_PORT_19=0 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=7 REMAP_PORT_21=6 REMAP_PORT_22=5 REMAP_PORT_23=4 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=11 REMAP_PORT_25=10 REMAP_PORT_26=9 REMAP_PORT_27=8 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=15 REMAP_PORT_29=14 REMAP_PORT_30=13 REMAP_PORT_31=12 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 REMAP_PORT_33=18 REMAP_PORT_34=17 REMAP_PORT_35=16 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 REMAP_PORT_41=26 REMAP_PORT_42=25 REMAP_PORT_43=24 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 REMAP_PORT_45=30 REMAP_PORT_46=29 REMAP_PORT_47=28 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=35 REMAP_PORT_5=34 REMAP_PORT_6=33 REMAP_PORT_7=32 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=39 REMAP_PORT_1=38 REMAP_PORT_2=37 REMAP_PORT_3=36 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=43 REMAP_PORT_13=42 REMAP_PORT_14=41 REMAP_PORT_15=40 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=47 REMAP_PORT_9=46 REMAP_PORT_10=45 REMAP_PORT_11=44 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 stop +led 0 prog 02 A8 60 AA 02 00 60 A7 02 00 60 FE 02 00 60 AB 06 A7 D2 08 74 20 02 A9 60 AA 06 A7 E2 08 60 A7 06 FE 28 67 3D 86 FE 06 FE 86 AB 06 AB D2 04 71 10 86 A7 06 FE D2 40 71 0C 86 FF 3A 80 32 08 97 71 7C 77 4C 57 22 0E 87 22 0E 87 57 22 0F 87 22 0F 87 57 22 0F 87 22 0E 87 57 06 AA 61 A6 16 A7 49 27 16 A6 97 71 53 77 45 57 02 0A 50 95 75 74 85 75 5A 57 16 FF CA 05 74 4C 77 5A 06 FE 12 BC F8 32 00 32 01 B7 97 71 6A 77 5A +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 02 A8 60 AA 02 00 60 A7 02 00 60 FE 02 00 60 AB 06 A7 D2 08 74 20 02 A9 60 AA 06 A7 E2 08 60 A7 06 FE 28 67 3D 86 FE 06 FE 86 AB 06 AB D2 04 71 10 86 A7 06 FE D2 40 71 0C 86 FF 3A 80 32 08 97 71 7C 77 4C 57 22 0E 87 22 0E 87 57 22 0F 87 22 0F 87 57 22 0F 87 22 0E 87 57 06 AA 61 A6 16 A7 49 27 16 A6 97 71 53 77 45 57 02 0A 50 95 75 74 85 75 5A 57 16 FF CA 05 74 4C 77 5A 06 FE 12 BC F8 32 00 32 01 B7 97 71 6A 77 5A + +led 1 auto on +led 1 start + +led 2 stop + + +setreg CMIC_LEDUP1_DATA_RAM[0xa8] 0x3f +setreg CMIC_LEDUP1_DATA_RAM[0xa9] 0xFC +setreg CMIC_LEDUP0_DATA_RAM[0xa8] 0xff +setreg CMIC_LEDUP0_DATA_RAM[0xa9] 0xC3 + diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/pg_profile_lookup.ini b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/pg_profile_lookup.ini new file mode 100644 index 000000000000..aedda37a8878 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -3 2288 + 25000 5m 1248 2288 53248 -3 2288 + 40000 5m 1248 2288 66560 -3 2288 + 50000 5m 1248 2288 90272 -3 2288 + 100000 5m 1248 2288 165568 -3 2288 + 10000 40m 1248 2288 37024 -3 2288 + 25000 40m 1248 2288 53248 -3 2288 + 40000 40m 1248 2288 71552 -3 2288 + 50000 40m 1248 2288 96096 -3 2288 + 100000 40m 1248 2288 177632 -3 2288 + 10000 300m 1248 2288 46176 -3 2288 + 25000 300m 1248 2288 79040 -3 2288 + 40000 300m 1248 2288 108160 -3 2288 + 50000 300m 1248 2288 141856 -3 2288 + 100000 300m 1248 2288 268736 -3 2288 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/port_config.ini b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/port_config.ini new file mode 100644 index 000000000000..c1a086764854 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 49,50 fiftyGigE1/1/1 1 50000 +Ethernet2 51,52 fiftyGigE1/1/2 1 50000 +Ethernet4 53,54 fiftyGigE1/2/1 2 50000 +Ethernet6 55,56 fiftyGigE1/2/2 2 50000 +Ethernet8 57,58 fiftyGigE1/3/1 3 50000 +Ethernet10 59,60 fiftyGigE1/3/2 3 50000 +Ethernet12 61,62 fiftyGigE1/4/1 4 50000 +Ethernet14 63,64 fiftyGigE1/4/2 4 50000 +Ethernet16 65,66 fiftyGigE1/5/1 5 50000 +Ethernet18 67,68 fiftyGigE1/5/2 5 50000 +Ethernet20 69,70 fiftyGigE1/6/1 6 50000 +Ethernet22 71,72 fiftyGigE1/6/2 6 50000 +Ethernet24 73,74,75,76 hundredGigE1/7 7 100000 +Ethernet28 77,78,79,80 hundredGigE1/8 8 100000 +Ethernet32 37,38,39,40 hundredGigE1/9 9 100000 +Ethernet36 33,34,35,36 hundredGigE1/10 10 100000 +Ethernet40 45,46 fiftyGigE1/11/1 11 50000 +Ethernet42 47,48 fiftyGigE1/11/2 11 50000 +Ethernet44 41,42 fiftyGigE1/12/1 12 50000 +Ethernet46 43,44 fiftyGigE1/12/2 12 50000 +Ethernet48 81,82 fiftyGigE1/13/1 13 50000 +Ethernet50 83,84 fiftyGigE1/13/2 13 50000 +Ethernet52 85,86 fiftyGigE1/14/1 14 50000 +Ethernet54 87,88 fiftyGigE1/14/2 14 50000 +Ethernet56 89,90 fiftyGigE1/15/1 15 50000 +Ethernet58 91,92 fiftyGigE1/15/2 15 50000 +Ethernet60 93,94 fiftyGigE1/16/1 16 50000 +Ethernet62 95,96 fiftyGigE1/16/2 16 50000 +Ethernet64 97,98 fiftyGigE1/17/1 17 50000 +Ethernet66 99,100 fiftyGigE1/17/2 17 50000 +Ethernet68 101,102 fiftyGigE1/18/1 18 50000 +Ethernet70 103,104 fiftyGigE1/18/2 18 50000 +Ethernet72 105,106 fiftyGigE1/19/1 19 50000 +Ethernet74 107,108 fiftyGigE1/19/2 19 50000 +Ethernet76 109,110 fiftyGigE1/20/1 20 50000 +Ethernet78 111,112 fiftyGigE1/20/2 20 50000 +Ethernet80 21,22 fiftyGigE1/21/1 21 50000 +Ethernet82 23,24 fiftyGigE1/21/2 21 50000 +Ethernet84 17,18 fiftyGigE1/22/1 22 50000 +Ethernet86 19,20 fiftyGigE1/22/2 22 50000 +Ethernet88 29,30 fiftyGigE1/23/1 23 50000 +Ethernet90 31,32 fiftyGigE1/23/2 23 50000 +Ethernet92 25,26 fiftyGigE1/24/1 24 50000 +Ethernet94 27,28 fiftyGigE1/24/2 24 50000 +Ethernet96 117,118 fiftyGigE1/25/1 25 50000 +Ethernet98 119,120 fiftyGigE1/25/2 25 50000 +Ethernet100 113,114 fiftyGigE1/26/1 26 50000 +Ethernet102 115,116 fiftyGigE1/26/2 26 50000 +Ethernet104 125,126,127,128 hundredGigE1/27 27 100000 +Ethernet108 121,122,123,124 hundredGigE1/28 28 100000 +Ethernet112 5,6,7,8 hundredGigE1/29 29 100000 +Ethernet116 1,2,3,4 hundredGigE1/30 30 100000 +Ethernet120 13,14 fiftyGigE1/31/1 31 50000 +Ethernet122 15,16 fiftyGigE1/31/2 31 50000 +Ethernet124 9,10 fiftyGigE1/32/1 32 50000 +Ethernet126 11,12 fiftyGigE1/32/2 32 50000 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/qos.json.j2 b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/sai.profile b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/sai.profile new file mode 100644 index 000000000000..b277ae5f0bde --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-z9100-8x100G-48x50G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/th-z9100-8x100G-48x50G.config.bcm b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/th-z9100-8x100G-48x50G.config.bcm new file mode 100644 index 000000000000..3130c801a38f --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/Force10-Z9100-C8D48/th-z9100-8x100G-48x50G.config.bcm @@ -0,0 +1,368 @@ +#TH Z9100 T0 + +l3_alpm_enable=2 +pfc_deadlock_seq_control=1 +bcm_stat_interval=2000000 +bcm_num_cos=10 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +oversubscribe_mode=1 +os=unix + +pbmp_oversubscribe=0x3fffffffdffffffff7fffffffdfffffffe +pbmp_xport_xe=0x3fffffffdffffffff7fffffffdfffffffe + +serdes_if_type_xe=14 +serdes_if_type_ce=14 + +#Parity +parity_correction=1 +parity_enable=1 + +#Port configuration +dport_map_port_10.0=126 +dport_map_port_1.0=117 +dport_map_port_102.0=65 +dport_map_port_103.0=66 +dport_map_port_106.0=69 +dport_map_port_107.0=70 +dport_map_port_110.0=73 +dport_map_port_111.0=74 +dport_map_port_114.0=77 +dport_map_port_115.0=78 +dport_map_port_118.0=101 +dport_map_port_119.0=102 +dport_map_port_122.0=97 +dport_map_port_123.0=98 +dport_map_port_126.0=109 +dport_map_port_130.0=105 +dport_map_port_13.0=121 +dport_map_port_14.0=122 +dport_map_port_17.0=85 +dport_map_port_18.0=86 +dport_map_port_21.0=81 +dport_map_port_22.0=82 +dport_map_port_25.0=93 +dport_map_port_26.0=94 +dport_map_port_29.0=89 +dport_map_port_30.0=90 +dport_map_port_34.0=37 +dport_map_port_38.0=33 +dport_map_port_42.0=45 +dport_map_port_43.0=46 +dport_map_port_46.0=41 +dport_map_port_47.0=42 +dport_map_port_50.0=1 +dport_map_port_5.0=113 +dport_map_port_51.0=2 +dport_map_port_54.0=5 +dport_map_port_55.0=6 +dport_map_port_58.0=9 +dport_map_port_59.0=10 +dport_map_port_62.0=13 +dport_map_port_63.0=14 +dport_map_port_68.0=17 +dport_map_port_69.0=18 +dport_map_port_72.0=21 +dport_map_port_73.0=22 +dport_map_port_76.0=25 +dport_map_port_80.0=29 +dport_map_port_84.0=49 +dport_map_port_85.0=50 +dport_map_port_88.0=53 +dport_map_port_89.0=54 +dport_map_port_9.0=125 +dport_map_port_92.0=57 +dport_map_port_93.0=58 +dport_map_port_96.0=61 +dport_map_port_97.0=62 + +phy_xaui_rx_polarity_flip_10.0=0x2 +phy_xaui_rx_polarity_flip_1.0=0x9 +phy_xaui_rx_polarity_flip_102.0=0x2 +phy_xaui_rx_polarity_flip_103.0=0x0 +phy_xaui_rx_polarity_flip_106.0=0x1 +phy_xaui_rx_polarity_flip_107.0=0x3 +phy_xaui_rx_polarity_flip_110.0=0x3 +phy_xaui_rx_polarity_flip_111.0=0x3 +phy_xaui_rx_polarity_flip_114.0=0x0 +phy_xaui_rx_polarity_flip_115.0=0x0 +phy_xaui_rx_polarity_flip_118.0=0x0 +phy_xaui_rx_polarity_flip_119.0=0x2 +phy_xaui_rx_polarity_flip_122.0=0x0 +phy_xaui_rx_polarity_flip_123.0=0x3 +phy_xaui_rx_polarity_flip_126.0=0x7 +phy_xaui_rx_polarity_flip_130.0=0x4 +phy_xaui_rx_polarity_flip_13.0=0x0 +phy_xaui_rx_polarity_flip_14.0=0x3 +phy_xaui_rx_polarity_flip_17.0=0x1 +phy_xaui_rx_polarity_flip_18.0=0x1 +phy_xaui_rx_polarity_flip_21.0=0x0 +phy_xaui_rx_polarity_flip_22.0=0x0 +phy_xaui_rx_polarity_flip_25.0=0x2 +phy_xaui_rx_polarity_flip_26.0=0x0 +phy_xaui_rx_polarity_flip_29.0=0x0 +phy_xaui_rx_polarity_flip_30.0=0x0 +phy_xaui_rx_polarity_flip_34.0=0xa +phy_xaui_rx_polarity_flip_38.0=0xd +phy_xaui_rx_polarity_flip_42.0=0x3 +phy_xaui_rx_polarity_flip_43.0=0x3 +phy_xaui_rx_polarity_flip_46.0=0x3 +phy_xaui_rx_polarity_flip_47.0=0x1 +phy_xaui_rx_polarity_flip_50.0=0x0 +phy_xaui_rx_polarity_flip_5.0=0x7 +phy_xaui_rx_polarity_flip_51.0=0x3 +phy_xaui_rx_polarity_flip_54.0=0x1 +phy_xaui_rx_polarity_flip_55.0=0x3 +phy_xaui_rx_polarity_flip_58.0=0x2 +phy_xaui_rx_polarity_flip_59.0=0x0 +phy_xaui_rx_polarity_flip_62.0=0x3 +phy_xaui_rx_polarity_flip_63.0=0x3 +phy_xaui_rx_polarity_flip_68.0=0x0 +phy_xaui_rx_polarity_flip_69.0=0x3 +phy_xaui_rx_polarity_flip_72.0=0x2 +phy_xaui_rx_polarity_flip_73.0=0x0 +phy_xaui_rx_polarity_flip_76.0=0x2 +phy_xaui_rx_polarity_flip_80.0=0xd +phy_xaui_rx_polarity_flip_84.0=0x3 +phy_xaui_rx_polarity_flip_85.0=0x3 +phy_xaui_rx_polarity_flip_88.0=0x1 +phy_xaui_rx_polarity_flip_89.0=0x3 +phy_xaui_rx_polarity_flip_9.0=0x0 +phy_xaui_rx_polarity_flip_92.0=0x0 +phy_xaui_rx_polarity_flip_93.0=0x1 +phy_xaui_rx_polarity_flip_96.0=0x3 +phy_xaui_rx_polarity_flip_97.0=0x2 + +phy_xaui_tx_polarity_flip_10.0=0x0 +phy_xaui_tx_polarity_flip_1.0=0x3 +phy_xaui_tx_polarity_flip_102.0=0x3 +phy_xaui_tx_polarity_flip_103.0=0x3 +phy_xaui_tx_polarity_flip_106.0=0x3 +phy_xaui_tx_polarity_flip_107.0=0x3 +phy_xaui_tx_polarity_flip_110.0=0x3 +phy_xaui_tx_polarity_flip_111.0=0x3 +phy_xaui_tx_polarity_flip_114.0=0x3 +phy_xaui_tx_polarity_flip_115.0=0x3 +phy_xaui_tx_polarity_flip_118.0=0x0 +phy_xaui_tx_polarity_flip_119.0=0x0 +phy_xaui_tx_polarity_flip_122.0=0x3 +phy_xaui_tx_polarity_flip_123.0=0x3 +phy_xaui_tx_polarity_flip_126.0=0x7 +phy_xaui_tx_polarity_flip_130.0=0xb +phy_xaui_tx_polarity_flip_13.0=0x0 +phy_xaui_tx_polarity_flip_14.0=0x3 +phy_xaui_tx_polarity_flip_17.0=0x3 +phy_xaui_tx_polarity_flip_18.0=0x3 +phy_xaui_tx_polarity_flip_21.0=0x3 +phy_xaui_tx_polarity_flip_22.0=0x3 +phy_xaui_tx_polarity_flip_25.0=0x2 +phy_xaui_tx_polarity_flip_26.0=0x2 +phy_xaui_tx_polarity_flip_29.0=0x3 +phy_xaui_tx_polarity_flip_30.0=0x2 +phy_xaui_tx_polarity_flip_34.0=0xb +phy_xaui_tx_polarity_flip_38.0=0x0 +phy_xaui_tx_polarity_flip_42.0=0x2 +phy_xaui_tx_polarity_flip_43.0=0x1 +phy_xaui_tx_polarity_flip_46.0=0x2 +phy_xaui_tx_polarity_flip_47.0=0x3 +phy_xaui_tx_polarity_flip_50.0=0x2 +phy_xaui_tx_polarity_flip_5.0=0x8 +phy_xaui_tx_polarity_flip_51.0=0x3 +phy_xaui_tx_polarity_flip_54.0=0x2 +phy_xaui_tx_polarity_flip_55.0=0x0 +phy_xaui_tx_polarity_flip_58.0=0x2 +phy_xaui_tx_polarity_flip_59.0=0x2 +phy_xaui_tx_polarity_flip_62.0=0x3 +phy_xaui_tx_polarity_flip_63.0=0x2 +phy_xaui_tx_polarity_flip_68.0=0x2 +phy_xaui_tx_polarity_flip_69.0=0x0 +phy_xaui_tx_polarity_flip_72.0=0x0 +phy_xaui_tx_polarity_flip_73.0=0x0 +phy_xaui_tx_polarity_flip_76.0=0x0 +phy_xaui_tx_polarity_flip_80.0=0xa +phy_xaui_tx_polarity_flip_84.0=0x2 +phy_xaui_tx_polarity_flip_85.0=0x1 +phy_xaui_tx_polarity_flip_88.0=0x3 +phy_xaui_tx_polarity_flip_89.0=0x3 +phy_xaui_tx_polarity_flip_9.0=0x3 +phy_xaui_tx_polarity_flip_92.0=0x1 +phy_xaui_tx_polarity_flip_93.0=0x1 +phy_xaui_tx_polarity_flip_96.0=0x0 +phy_xaui_tx_polarity_flip_97.0=0x2 + +portmap_10.0=11:50:2 +portmap_1.0=1:100 +portmap_102.0=97:50:2 +portmap_103.0=99:50:2 +portmap_106.0=101:50:2 +portmap_107.0=103:50:2 +portmap_110.0=105:50:2 +portmap_111.0=107:50:2 +portmap_114.0=109:50:2 +portmap_115.0=111:50:2 +portmap_118.0=113:50:2 +portmap_119.0=115:50:2 +portmap_122.0=117:50:2 +portmap_123.0=119:50:2 +portmap_126.0=121:100 +portmap_130.0=125:100 +portmap_13.0=13:50:2 +portmap_14.0=15:50:2 +portmap_17.0=17:50:2 +portmap_18.0=19:50:2 +portmap_21.0=21:50:2 +portmap_22.0=23:50:2 +portmap_25.0=25:50:2 +portmap_26.0=27:50:2 +portmap_29.0=29:50:2 +portmap_30.0=31:50:2 +portmap_34.0=33:100 +portmap_38.0=37:100 +portmap_42.0=41:50:2 +portmap_43.0=43:50:2 +portmap_46.0=45:50:2 +portmap_47.0=47:50:2 +portmap_50.0=49:50:2 +portmap_5.0=5:100 +portmap_51.0=51:50:2 +portmap_54.0=53:50:2 +portmap_55.0=55:50:2 +portmap_58.0=57:50:2 +portmap_59.0=59:50:2 +portmap_62.0=61:50:2 +portmap_63.0=63:50:2 +portmap_68.0=65:50:2 +portmap_69.0=67:50:2 +portmap_72.0=69:50:2 +portmap_73.0=71:50:2 +portmap_76.0=73:100 +portmap_80.0=77:100 +portmap_84.0=81:50:2 +portmap_85.0=83:50:2 +portmap_88.0=85:50:2 +portmap_89.0=87:50:2 +portmap_9.0=9:50:2 +portmap_92.0=89:50:2 +portmap_93.0=91:50:2 +portmap_96.0=93:50:2 +portmap_97.0=95:50:2 + +xgxs_rx_lane_map_10.0=0x213 +xgxs_rx_lane_map_1.0=0x213 +xgxs_rx_lane_map_102.0=0x3201 +xgxs_rx_lane_map_103.0=0x3201 +xgxs_rx_lane_map_106.0=0x213 +xgxs_rx_lane_map_107.0=0x213 +xgxs_rx_lane_map_110.0=0x3210 +xgxs_rx_lane_map_111.0=0x3210 +xgxs_rx_lane_map_114.0=0x3210 +xgxs_rx_lane_map_115.0=0x3210 +xgxs_rx_lane_map_118.0=0x123 +xgxs_rx_lane_map_119.0=0x123 +xgxs_rx_lane_map_122.0=0x3201 +xgxs_rx_lane_map_123.0=0x3201 +xgxs_rx_lane_map_126.0=0x213 +xgxs_rx_lane_map_130.0=0x1023 +xgxs_rx_lane_map_13.0=0x3201 +xgxs_rx_lane_map_14.0=0x3201 +xgxs_rx_lane_map_17.0=0x2103 +xgxs_rx_lane_map_18.0=0x2103 +xgxs_rx_lane_map_21.0=0x3102 +xgxs_rx_lane_map_22.0=0x3102 +xgxs_rx_lane_map_25.0=0x2310 +xgxs_rx_lane_map_26.0=0x2310 +xgxs_rx_lane_map_29.0=0x2301 +xgxs_rx_lane_map_30.0=0x2301 +xgxs_rx_lane_map_34.0=0x1302 +xgxs_rx_lane_map_38.0=0x312 +xgxs_rx_lane_map_42.0=0x3210 +xgxs_rx_lane_map_43.0=0x3210 +xgxs_rx_lane_map_46.0=0x2103 +xgxs_rx_lane_map_47.0=0x2103 +xgxs_rx_lane_map_50.0=0x1023 +xgxs_rx_lane_map_5.0=0x1203 +xgxs_rx_lane_map_51.0=0x1023 +xgxs_rx_lane_map_54.0=0x1302 +xgxs_rx_lane_map_55.0=0x1302 +xgxs_rx_lane_map_58.0=0x1203 +xgxs_rx_lane_map_59.0=0x1203 +xgxs_rx_lane_map_62.0=0x1302 +xgxs_rx_lane_map_63.0=0x1302 +xgxs_rx_lane_map_68.0=0x3201 +xgxs_rx_lane_map_69.0=0x3201 +xgxs_rx_lane_map_72.0=0x1302 +xgxs_rx_lane_map_73.0=0x1302 +xgxs_rx_lane_map_76.0=0x1203 +xgxs_rx_lane_map_80.0=0x2301 +xgxs_rx_lane_map_84.0=0x2301 +xgxs_rx_lane_map_85.0=0x2301 +xgxs_rx_lane_map_88.0=0x213 +xgxs_rx_lane_map_89.0=0x213 +xgxs_rx_lane_map_9.0=0x213 +xgxs_rx_lane_map_92.0=0x3210 +xgxs_rx_lane_map_93.0=0x3210 +xgxs_rx_lane_map_96.0=0x3210 +xgxs_rx_lane_map_97.0=0x3210 +xgxs_tx_lane_map_10.0=0x123 +xgxs_tx_lane_map_1.0=0x123 +xgxs_tx_lane_map_102.0=0x123 +xgxs_tx_lane_map_103.0=0x123 +xgxs_tx_lane_map_106.0=0x123 +xgxs_tx_lane_map_107.0=0x123 +xgxs_tx_lane_map_110.0=0x132 +xgxs_tx_lane_map_111.0=0x132 +xgxs_tx_lane_map_114.0=0x123 +xgxs_tx_lane_map_115.0=0x123 +xgxs_tx_lane_map_118.0=0x2013 +xgxs_tx_lane_map_119.0=0x2013 +xgxs_tx_lane_map_122.0=0x2310 +xgxs_tx_lane_map_123.0=0x2310 +xgxs_tx_lane_map_126.0=0x123 +xgxs_tx_lane_map_130.0=0x132 +xgxs_tx_lane_map_13.0=0x2301 +xgxs_tx_lane_map_14.0=0x2301 +xgxs_tx_lane_map_17.0=0x3102 +xgxs_tx_lane_map_18.0=0x3102 +xgxs_tx_lane_map_21.0=0x132 +xgxs_tx_lane_map_22.0=0x132 +xgxs_tx_lane_map_25.0=0x2130 +xgxs_tx_lane_map_26.0=0x2130 +xgxs_tx_lane_map_29.0=0x1023 +xgxs_tx_lane_map_30.0=0x1023 +xgxs_tx_lane_map_34.0=0x2031 +xgxs_tx_lane_map_38.0=0x1032 +xgxs_tx_lane_map_42.0=0x132 +xgxs_tx_lane_map_43.0=0x132 +xgxs_tx_lane_map_46.0=0x1023 +xgxs_tx_lane_map_47.0=0x1023 +xgxs_tx_lane_map_50.0=0x132 +xgxs_tx_lane_map_5.0=0x213 +xgxs_tx_lane_map_51.0=0x132 +xgxs_tx_lane_map_54.0=0x2301 +xgxs_tx_lane_map_55.0=0x2301 +xgxs_tx_lane_map_58.0=0x123 +xgxs_tx_lane_map_59.0=0x123 +xgxs_tx_lane_map_62.0=0x3201 +xgxs_tx_lane_map_63.0=0x3201 +xgxs_tx_lane_map_68.0=0x3210 +xgxs_tx_lane_map_69.0=0x3210 +xgxs_tx_lane_map_72.0=0x2301 +xgxs_tx_lane_map_73.0=0x2301 +xgxs_tx_lane_map_76.0=0x123 +xgxs_tx_lane_map_80.0=0x1320 +xgxs_tx_lane_map_84.0=0x213 +xgxs_tx_lane_map_85.0=0x213 +xgxs_tx_lane_map_88.0=0x1032 +xgxs_tx_lane_map_89.0=0x1032 +xgxs_tx_lane_map_9.0=0x123 +xgxs_tx_lane_map_92.0=0x132 +xgxs_tx_lane_map_93.0=0x132 +xgxs_tx_lane_map_96.0=0x123 +xgxs_tx_lane_map_97.0=0x123 +mmu_init_config="MSFT-TH-Tier0" diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/default_sku b/device/dell/x86_64-dell_z9100_c2538-r0/default_sku new file mode 100644 index 000000000000..e09260239e96 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/default_sku @@ -0,0 +1 @@ +Force10-Z9100-C32 t1 diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/installer.conf b/device/dell/x86_64-dell_z9100_c2538-r0/installer.conf new file mode 100644 index 000000000000..0a9a3a639eb2 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="module_blacklist=gpio_ich" diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/media_settings.json b/device/dell/x86_64-dell_z9100_c2538-r0/media_settings.json new file mode 100644 index 000000000000..9bb0a7597876 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/media_settings.json @@ -0,0 +1,751 @@ +{ + "GLOBAL_MEDIA_SETTINGS": { + "1-32": { + "AMPHENOL-NDARHF-M201": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8" + } + }, + "AMPHENOL-NDAAFF-M201": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808", + "lane2":"0x006808", + "lane3":"0x006808" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "MOLEX-1003461101": { + "preemphasis": { + "lane0":"0x046804", + "lane1":"0x046804" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8" + } + }, + "AMPHENOL-NDARHF-M206": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xb" + } + }, + "AMPHENOL-NDAAFF-M206": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808", + "lane2":"0x006808", + "lane3":"0x006808" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xb", + "lane2":"0xb", + "lane3":"0xb" + } + }, + "AMPHENOL-NDARHJ-M206": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xb" + } + }, + "MOLEX-1003463151": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xb" + } + }, + "AMPHENOL-NDARHJ-M202": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xb" + } + }, + "AMPHENOL-NDAAFJ-M202": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808", + "lane2":"0x006808", + "lane3":"0x006808" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xb", + "lane2":"0xb", + "lane3":"0xb" + } + }, + "MOLEX-1003461201": { + "preemphasis": { + "lane0":"0x046408", + "lane1":"0x046408" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xb" + } + }, + "AMPHENOL-NDARHF-M205": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8" + } + }, + "AMPHENOL-NDAAFF-M205": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808", + "lane2":"0x006808", + "lane3":"0x006808" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AMPHENOL-NDARHJ-M203": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808" + }, + "idriver": { + "lane0":"0xe", + "lane1":"0xe" + } + }, + "AMPHENOL-NDAAFJ-M203": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808", + "lane2":"0x006808", + "lane3":"0x006808" + }, + "idriver": { + "lane0":"0xe", + "lane1":"0xe", + "lane2":"0xe", + "lane3":"0xe" + } + }, + "MOLEX-1002979024": { + "preemphasis": { + "lane0":"0x006808", + "lane1":"0x006808", + "lane2":"0x006808", + "lane3":"0x006808" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xb", + "lane2":"0xb", + "lane3":"0xb" + } + }, + "QSFP28-40GBASE-CR4-1M":{ + "preemphasis": { + "lane0":"0x32320c", + "lane1":"0x32320c", + "lane2":"0x32320c", + "lane3":"0x32320c" + }, + "idriver": { + "lane0":"0x9", + "lane1":"0x9", + "lane2":"0x9", + "lane3":"0x9" + } + }, + "QSFP28-40GBASE-CR4-2M":{ + "preemphasis": { + "lane0":"0x252f0c", + "lane1":"0x252f0c", + "lane2":"0x252f0c", + "lane3":"0x252f0c" + }, + "idriver": { + "lane0":"0xc", + "lane1":"0xc", + "lane2":"0xc", + "lane3":"0xc" + } + }, + "QSFP28-40GBASE-CR4-3M":{ + "preemphasis": { + "lane0":"0x252f0c", + "lane1":"0x252f0c", + "lane2":"0x252f0c", + "lane3":"0x252f0c" + }, + "idriver": { + "lane0":"0xe", + "lane1":"0xe", + "lane2":"0xe", + "lane3":"0xe" + } + }, + "QSFP28-40GBASE-CR4-5M":{ + "preemphasis": { + "lane0":"0x3d2f04", + "lane1":"0x3d2f04", + "lane2":"0x3d2f04", + "lane3":"0x3d2f04" + }, + "idriver": { + "lane0":"0xf", + "lane1":"0xf", + "lane2":"0xf", + "lane3":"0xf" + } + } + } + }, + "PORT_MEDIA_SETTINGS": { + "1": { + "Default": { + "preemphasis": { + "lane0":"0x2c4004", + "lane1":"0x2b4203", + "lane2":"0x2c4004", + "lane3":"0x2c4004" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xb", + "lane2":"0xb", + "lane3":"0xb" + } + } + }, + "2": { + "Default": { + "preemphasis": { + "lane0":"0x2b4203", + "lane1":"0x294403", + "lane2":"0x2b4203", + "lane3":"0x2b4203" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xa", + "lane2":"0xb", + "lane3":"0xb" + } + } + }, + "3": { + "Default": { + "preemphasis": { + "lane0":"0x294403", + "lane1":"0x294403", + "lane2":"0x294403", + "lane3":"0x294403" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "4": { + "Default": { + "preemphasis": { + "lane0":"0x284503", + "lane1":"0x284503", + "lane2":"0x284503", + "lane3":"0x294403" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xb", + "lane3":"0xa" + } + } + }, + "5": { + "Default": { + "preemphasis": { + "lane0":"0x284503", + "lane1":"0x284503", + "lane2":"0x264703", + "lane3":"0x284503" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "6": { + "Default": { + "preemphasis": { + "lane0":"0x264703", + "lane1":"0x244903", + "lane2":"0x284503", + "lane3":"0x264703" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "7": { + "Default": { + "preemphasis": { + "lane0":"0x244903", + "lane1":"0x244903", + "lane2":"0x264703", + "lane3":"0x244903" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0x9" + } + } + }, + "8": { + "Default": { + "preemphasis": { + "lane0":"0x234b02", + "lane1":"0x244903", + "lane2":"0x244903", + "lane3":"0x234b02" + }, + "idriver": { + "lane0":"0x9", + "lane1":"0xa", + "lane2":"0x9", + "lane3":"0x9" + } + } + }, + "9": { + "Default": { + "preemphasis": { + "lane0":"0x294403", + "lane1":"0x2c4004", + "lane2":"0x2b4203", + "lane3":"0x2e3e04" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xb", + "lane2":"0xb", + "lane3":"0xb" + } + } + }, + "10": { + "Default": { + "preemphasis": { + "lane0":"0x294403", + "lane1":"0x294403", + "lane2":"0x294403", + "lane3":"0x294403" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "11": { + "Default": { + "preemphasis": { + "lane0":"0x244903", + "lane1":"0x274603", + "lane2":"0x284503", + "lane3":"0x244903" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "12": { + "Default": { + "preemphasis": { + "lane0":"0x284503", + "lane1":"0x274603", + "lane2":"0x264703", + "lane3":"0x264703" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "13": { + "Default": { + "preemphasis": { + "lane0":"0x204e02", + "lane1":"0x204e02", + "lane2":"0x1f4f02", + "lane3":"0x1f4f02" + }, + "idriver": { + "lane0":"0x9", + "lane1":"0x9", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "14": { + "Default": { + "preemphasis": { + "lane0":"0x1e5002", + "lane1":"0x204e02", + "lane2":"0x1e5002", + "lane3":"0x204e02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x9", + "lane2":"0x8", + "lane3":"0x9" + } + } + }, + "15": { + "Default": { + "preemphasis": { + "lane0":"0x204e02", + "lane1":"0x1e5002", + "lane2":"0x1f4f02", + "lane3":"0x1f4f02" + }, + "idriver": { + "lane0":"0x9", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "16": { + "Default": { + "preemphasis": { + "lane0":"0x204e02", + "lane1":"0x1e5002", + "lane2":"0x204e02", + "lane3":"0x1e5002" + }, + "idriver": { + "lane0":"0x9", + "lane1":"0x8", + "lane2":"0x9", + "lane3":"0x8" + } + } + }, + "17": { + "Default": { + "preemphasis": { + "lane0":"0x204e02", + "lane1":"0x1e5002", + "lane2":"0x204e02", + "lane3":"0x1e5002" + }, + "idriver": { + "lane0":"0x9", + "lane1":"0x8", + "lane2":"0x9", + "lane3":"0x8" + } + } + }, + "18": { + "Default": { + "preemphasis": { + "lane0":"0x204e02", + "lane1":"0x1e5002", + "lane2":"0x204e02", + "lane3":"0x1e5002" + }, + "idriver": { + "lane0":"0x9", + "lane1":"0x8", + "lane2":"0x9", + "lane3":"0x8" + } + } + }, + "19": { + "Default": { + "preemphasis": { + "lane0":"0x1e5002", + "lane1":"0x204e02", + "lane2":"0x1e5002", + "lane3":"0x204e02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x9", + "lane2":"0x8", + "lane3":"0x9" + } + } + }, + "20": { + "Default": { + "preemphasis": { + "lane0":"0x204e02", + "lane1":"0x1f4f02", + "lane2":"0x204e02", + "lane3":"0x1f4f02" + }, + "idriver": { + "lane0":"0x9", + "lane1":"0x8", + "lane2":"0x9", + "lane3":"0x8" + } + } + }, + "21": { + "Default": { + "preemphasis": { + "lane0":"0x244903", + "lane1":"0x244903", + "lane2":"0x244903", + "lane3":"0x244903" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0x9", + "lane2":"0xa", + "lane3":"0x9" + } + } + }, + "22": { + "Default": { + "preemphasis": { + "lane0":"0x264703", + "lane1":"0x244903", + "lane2":"0x244903", + "lane3":"0x244903" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0x9", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "23": { + "Default": { + "preemphasis": { + "lane0":"0x294403", + "lane1":"0x244903", + "lane2":"0x244903", + "lane3":"0x284503" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "24": { + "Default": { + "preemphasis": { + "lane0":"0x294403", + "lane1":"0x2b4203", + "lane2":"0x2c4004", + "lane3":"0x2d3f04" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xb", + "lane2":"0xb", + "lane3":"0xb" + } + } + }, + "25": { + "Default": { + "preemphasis": { + "lane0":"0x234b02", + "lane1":"0x234b02", + "lane2":"0x234b02", + "lane3":"0x234b02" + }, + "idriver": { + "lane0":"0x9", + "lane1":"0x9", + "lane2":"0x9", + "lane3":"0x9" + } + } + }, + "26": { + "Default": { + "preemphasis": { + "lane0":"0x234b02", + "lane1":"0x244903", + "lane2":"0x244903", + "lane3":"0x244903" + }, + "idriver": { + "lane0":"0x9", + "lane1":"0x9", + "lane2":"0x9", + "lane3":"0x9" + } + } + }, + "27": { + "Default": { + "preemphasis": { + "lane0":"0x274603", + "lane1":"0x264703", + "lane2":"0x244903", + "lane3":"0x244903" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0x9", + "lane3":"0xa" + } + } + }, + "28": { + "Default": { + "preemphasis": { + "lane0":"0x264703", + "lane1":"0x244903", + "lane2":"0x284503", + "lane3":"0x274603" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "29": { + "Default": { + "preemphasis": { + "lane0":"0x294403", + "lane1":"0x294403", + "lane2":"0x294403", + "lane3":"0x284503" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "30": { + "Default": { + "preemphasis": { + "lane0":"0x294403", + "lane1":"0x284503", + "lane2":"0x294403", + "lane3":"0x294403" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + } + }, + "31": { + "Default": { + "preemphasis": { + "lane0":"0x2b4203", + "lane1":"0x294403", + "lane2":"0x2b4203", + "lane3":"0x2b4203" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xa", + "lane2":"0xb", + "lane3":"0xb" + } + } + }, + "32": { + "Default": { + "preemphasis": { + "lane0":"0x2b4203", + "lane1":"0x2b4203", + "lane2":"0x2c4004", + "lane3":"0x2c4004" + }, + "idriver": { + "lane0":"0xb", + "lane1":"0xb", + "lane2":"0xb", + "lane3":"0xb" + } + } + } + } +} + diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/plugins/eeprom.py b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/eeprom.py new file mode 100644 index 000000000000..eca797ee7637 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Dell Z9100 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0050/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/plugins/psuutil.py b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/psuutil.py new file mode 100644 index 000000000000..d6eed4a5a7c1 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/psuutil.py @@ -0,0 +1,83 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" +HWMON_NODE = os.listdir(HWMON_DIR)[0] + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + # Get a mailbox register + def get_pmc_register(self, reg_name): + mailbox_dir = HWMON_DIR + HWMON_NODE + retval = 'ERR' + mb_reg_file = mailbox_dir+'/' + reg_name + if (not os.path.isfile(mb_reg_file)): + logging.error(mb_reg_file + " not found !") + return retval + + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", mb_reg_file, "file !") + + 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 + """ + Z9100_MAX_PSUS = 2 + return Z9100_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 + psu_status = self.get_pmc_register('psu'+str(index)+'_presence') + if (psu_status != 'ERR'): + psu_status = int(psu_status, 16) + # Check for PSU statuse + if (~psu_status & 0b1000) or (psu_status & 0b0100): + 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_presence = self.get_pmc_register('psu'+str(index)+'_presence') + if (psu_presence != 'ERR'): + psu_presence = int(psu_presence, 16) + # Check for PSU presence + if (~psu_presence & 0b1): + status = 1 + + return status diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/plugins/sfputil.py b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/sfputil.py new file mode 100644 index 000000000000..16b5192522e3 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/plugins/sfputil.py @@ -0,0 +1,439 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import os + import logging + import time + import select + 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 = 32 + PORTS_IN_BLOCK = 32 + IOM_1_PORT_START = 1 + IOM_1_PORT_END = 12 + IOM_2_PORT_START = 13 + IOM_2_PORT_END = 22 + IOM_3_PORT_START = 23 + IOM_3_PORT_END = 32 + + BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/" + OIR_FD_PATH = "/sys/devices/platform/dell_ich.0/sci_int_gpio_sus6" + + oir_fd = -1 + epoll = -1 + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 0: [0, 00], # Dummy Entry + 1: [9, 18], + 2: [9, 19], + 3: [9, 20], + 4: [9, 21], + 5: [9, 22], + 6: [9, 23], + 7: [9, 24], + 8: [9, 25], + 9: [8, 26], + 10: [8, 27], + 11: [8, 28], + 12: [8, 29], + 13: [8, 31], # reordered + 14: [8, 30], + 15: [8, 33], # reordered + 16: [8, 32], + 17: [7, 34], + 18: [7, 35], + 19: [7, 36], + 20: [7, 37], + 21: [7, 38], + 22: [7, 39], + 23: [7, 40], + 24: [7, 41], + 25: [6, 42], + 26: [6, 43], + 27: [6, 44], + 28: [6, 45], + 29: [6, 46], + 30: [6, 47], + 31: [6, 48], + 32: [6, 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 list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def iom1_port_start(self): + return self.IOM_1_PORT_START + + @property + def iom1_port_end(self): + return self.IOM_1_PORT_END + + @property + def iom2_port_start(self): + return self.IOM_2_PORT_START + + @property + def iom2_port_end(self): + return self.IOM_2_PORT_END + + @property + def iom3_port_start(self): + return self.IOM_3_PORT_START + + @property + def iom3_port_end(self): + return self.IOM_3_PORT_END + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def port_to_i2c_mapping(self): + return self._port_to_i2c_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom" + + for x in range(0, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self.port_to_i2c_mapping[x][0], + self.port_to_i2c_mapping[x][1]) + + SfpUtilBase.__init__(self) + + def __del__(self): + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + + def normalize_port(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return -1, -1 + # port_num and i2c match + if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end: + i2c_line = 14 + elif (port_num >= self.iom2_port_start and + port_num <= self.iom2_port_end): + i2c_line = 15 + elif (port_num >= self.iom3_port_start and + port_num <= self.iom3_port_end): + i2c_line = 16 + + # Rationalize port settings + if port_num >= self.iom1_port_start and port_num <= self.iom1_port_end: + port_num = port_num - 1 + elif port_num >= self.iom2_port_start and port_num <= self.iom2_port_end: + port_num = (port_num - 1) % 12 + elif (port_num >= self.iom3_port_start and + port_num <= self.iom3_port_end): + port_num = (port_num - 1) % 22 + + return i2c_line, port_num + + def get_presence(self, port_num): + + i2c_line, port_num = self.normalize_port(port_num) + if port_num == -1: + return False + + try: + qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_modprs" + reg_file = open(qsfp_path, "r") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # Absence of IOM throws read error + if (content == 'read error'): + return False + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + + i2c_line, port_num = self.normalize_port(port_num) + if port_num == -1: + return False + + try: + qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" + reg_file = open(qsfp_path, "r") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # Absence of IOM throws read error + if (content == 'read error'): + return False + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + + i2c_line, port_num = self.normalize_port(port_num) + if port_num == -1: + return False + + try: + qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" + reg_file = open(qsfp_path, "r+") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # Absence of IOM throws read error + if (content == 'read error'): + return False + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + + i2c_line, port_num = self.normalize_port(port_num) + if port_num == -1: + return False + + try: + qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" + reg_file = open(qsfp_path, "r+") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of th + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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: + qsfp_path = self.BASE_VAL_PATH.format(i2c_line)+"qsfp_lpmode" + reg_file = open(qsfp_path, "w+") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def get_register(self, reg_file): + retval = 'ERR' + + if (not os.path.isfile(reg_file)): + print(reg_file + ' not found !') + return retval + + try: + with open(reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", reg_file, "file !") + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + + def check_interrupts(self, port_dict): + retval = 0 + is_port_dict_updated = False + # Read the QSFP ABS interrupt & status registers + cpld2_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_int") + cpld2_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_sta") + cpld3_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_int") + cpld3_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_sta") + cpld4_abs_int = self.get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_int") + cpld4_abs_sta = self.get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_sta") + + if (cpld2_abs_int == 'ERR' or cpld2_abs_sta == 'ERR' or + cpld3_abs_int == 'ERR' or cpld3_abs_sta == 'ERR' or + cpld4_abs_int == 'ERR' or cpld4_abs_sta == 'ERR'): + return -1 + + cpld2_abs_int = int(cpld2_abs_int, 16) + cpld2_abs_sta = int(cpld2_abs_sta, 16) + cpld3_abs_int = int(cpld3_abs_int, 16) + cpld3_abs_sta = int(cpld3_abs_sta, 16) + cpld4_abs_int = int(cpld4_abs_int, 16) + cpld4_abs_sta = int(cpld4_abs_sta, 16) + + # Make it contiguous (discard reserved bits) + interrupt_reg = (cpld2_abs_int & 0xfff) |\ + ((cpld3_abs_int & 0x3ff) << 12) |\ + ((cpld4_abs_int & 0x3ff) << 22) + status_reg = (cpld2_abs_sta & 0xfff) |\ + ((cpld3_abs_sta & 0x3ff) << 12) |\ + ((cpld4_abs_sta & 0x3ff) << 22) + + port = self.port_start + while port <= self.port_end: + if interrupt_reg & (1 << (port-1)): + # update only if atleast one port has generated + # interrupt + is_port_dict_updated = True + if status_reg & (1 << (port-1)): + # status reg 1 => optics is removed + port_dict[port] = '0' + else: + # status reg 0 => optics is inserted + port_dict[port] = '1' + port += 1 + return retval, is_port_dict_updated + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + try: + # We get notified when there is an SCI interrupt from GPIO SUS6 + # Open the sysfs file and register the epoll object + self.oir_fd = open(self.OIR_FD_PATH, "r") + if self.oir_fd != -1: + # Do a dummy read before epoll register + self.oir_fd.read() + self.epoll = select.epoll() + self.epoll.register(self.oir_fd.fileno(), + select.EPOLLIN & select.EPOLLET) + else: + print("get_transceiver_change_event : unable to create fd") + return False, {} + + # Check for missed interrupts by invoking self.check_interrupts + # which will update the port_dict. + while True: + interrupt_count_start = self.get_register(self.OIR_FD_PATH) + + retval, is_port_dict_updated = \ + self.check_interrupts(port_dict) + if ((retval == 0) and (is_port_dict_updated is True)): + return True, port_dict + + interrupt_count_end = self.get_register(self.OIR_FD_PATH) + + if (interrupt_count_start == 'ERR' or + interrupt_count_end == 'ERR'): + print("get_transceiver_change_event : \ + unable to retrive interrupt count") + break + + # check_interrupts() itself may take upto 100s of msecs. + # We detect a missed interrupt based on the count + if interrupt_count_start == interrupt_count_end: + break + + # Block until an xcvr is inserted or removed with timeout = -1 + events = self.epoll.poll( + timeout=timeout if timeout != 0 else -1) + if events: + # check interrupts and return the port_dict + retval, is_port_dict_updated = \ + self.check_interrupts(port_dict) + if (retval != 0): + return False, {} + + return True, port_dict + except: + return False, {} + finally: + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + self.oir_fd = -1 + self.epoll = -1 + + return False, {} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/pmon_daemon_control.json b/device/dell/x86_64-dell_z9100_c2538-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..44871c057e82 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/sensors.conf b/device/dell/x86_64-dell_z9100_c2538-r0/sensors.conf new file mode 100644 index 000000000000..e23891de6bf9 --- /dev/null +++ b/device/dell/x86_64-dell_z9100_c2538-r0/sensors.conf @@ -0,0 +1,32 @@ +chip "SMF_Z9100_ON-isa-0000" +label power1 "PSU1 Input Power" +label power2 "PSU1 Output Power" +label power3 "PSU2 Input Power" +label power4 "PSU2 Output Power" +label temp14 "PSU1 Temp" +label temp15 "PSU2 Temp" +label curr601 "PSU1 Input Current" +label curr602 "PSU1 Output Current" +label curr701 "PSU2 Input Current" +label curr702 "PSU2 Output Current" +ignore temp12 +ignore temp13 +ignore temp5 +ignore temp7 +ignore temp8 +ignore in101 +ignore in102 +ignore in103 +ignore in104 +ignore in201 +ignore in202 +ignore in203 +ignore in204 +ignore in301 +ignore in302 +ignore in303 +ignore in304 +ignore in401 +ignore in402 +ignore in403 +ignore in404 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/buffers.json.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..3369e2cc5e4d --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "26284032", + "type": "ingress", + "mode": "dynamic", + "xoff": "6291456" + }, + "egress_lossless_pool": { + "size": "32575488", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "static", + "static_th":"32575488" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..a1fa90d39779 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "26284032", + "type": "ingress", + "mode": "dynamic", + "xoff": "6291456" + }, + "egress_lossless_pool": { + "size": "32575488", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "static", + "static_th":"32575488" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/custom_led.bin b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/custom_led.bin new file mode 100755 index 000000000000..49e559cd9813 Binary files /dev/null and b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/pg_profile_lookup.ini b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/pg_profile_lookup.ini new file mode 100644 index 000000000000..aedda37a8878 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -3 2288 + 25000 5m 1248 2288 53248 -3 2288 + 40000 5m 1248 2288 66560 -3 2288 + 50000 5m 1248 2288 90272 -3 2288 + 100000 5m 1248 2288 165568 -3 2288 + 10000 40m 1248 2288 37024 -3 2288 + 25000 40m 1248 2288 53248 -3 2288 + 40000 40m 1248 2288 71552 -3 2288 + 50000 40m 1248 2288 96096 -3 2288 + 100000 40m 1248 2288 177632 -3 2288 + 10000 300m 1248 2288 46176 -3 2288 + 25000 300m 1248 2288 79040 -3 2288 + 40000 300m 1248 2288 108160 -3 2288 + 50000 300m 1248 2288 141856 -3 2288 + 100000 300m 1248 2288 268736 -3 2288 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 new file mode 100644 index 000000000000..2b24bea93107 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/port_config.ini @@ -0,0 +1,35 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4 hundredGigE1/1 1 100000 +Ethernet4 5,6,7,8 hundredGigE1/2 2 100000 +Ethernet8 9,10,11,12 hundredGigE1/3 3 100000 +Ethernet12 13,14,15,16 hundredGigE1/4 4 100000 +Ethernet16 17,18,19,20 hundredGigE1/5 5 100000 +Ethernet20 21,22,23,24 hundredGigE1/6 6 100000 +Ethernet24 25,26,27,28 hundredGigE1/7 7 100000 +Ethernet28 29,30,31,32 hundredGigE1/8 8 100000 +Ethernet32 33,34,35,36 hundredGigE1/9 9 100000 +Ethernet36 37,38,39,40 hundredGigE1/10 10 100000 +Ethernet40 41,42,43,44 hundredGigE1/11 11 100000 +Ethernet44 45,46,47,48 hundredGigE1/12 12 100000 +Ethernet48 49,50,51,52 hundredGigE1/13 13 100000 +Ethernet52 53,54,55,56 hundredGigE1/14 14 100000 +Ethernet56 57,58,59,60 hundredGigE1/15 15 100000 +Ethernet60 61,62,63,64 hundredGigE1/16 16 100000 +Ethernet64 65,66,67,68 hundredGigE1/17 17 100000 +Ethernet68 69,70,71,72 hundredGigE1/18 18 100000 +Ethernet72 73,74,75,76 hundredGigE1/19 19 100000 +Ethernet76 77,78,79,80 hundredGigE1/20 20 100000 +Ethernet80 81,82,83,84 hundredGigE1/21 21 100000 +Ethernet84 85,86,87,88 hundredGigE1/22 22 100000 +Ethernet88 89,90,91,92 hundredGigE1/23 23 100000 +Ethernet92 93,94,95,96 hundredGigE1/24 24 100000 +Ethernet96 97,98,99,100 hundredGigE1/25 25 100000 +Ethernet100 101,102,103,104 hundredGigE1/26 26 100000 +Ethernet104 105,106,107,108 hundredGigE1/27 27 100000 +Ethernet108 109,110,111,112 hundredGigE1/28 28 100000 +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 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/qos.json.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/sai.profile b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/sai.profile new file mode 100644 index 000000000000..3491c7700c24 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-s5232f-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 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 new file mode 100644 index 000000000000..bf15510bf49b --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/td3-s5232f-32x100G.config.bcm @@ -0,0 +1,547 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +os=unix + +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +parity_enable=1 +parity_correction=1 +tdma_intr_enable=1 +schan_intr_enable=0 +tdma_intr_enable=1 +miim_intr_enable=1 +stat_if_parity_enable=1 + +port_flex_enable=1 +port_flex_enable_66=0 +port_flex_enable_130=0 +phy_an_c73=3 +phy_an_c73_66=0 +phy_an_c73_130=0 + +module_64ports=0 +table_dma_enable=1 +tdma_timeout_usec=5000000 +mmu_lossless=0 +pdma_descriptor_prefetch_enable=1 +pktdma_poll_mode_channel_bitmap=1 + +l2xmsg_mode=1 +l2xmsg_hostbuf_size=8192 +ipv6_lpm_128b_enable=1 +max_vp_lags=0 + +l3_alpm_enable=2 +l2_mem_entries=32768 +l3_mem_entries=16384 +l3_max_ecmp_mode=1 + +bcm_tunnel_term_compatible_mode=1 +ifp_inports_support_enable=1 + +stable_size=0x5500000 + +oversubscribe_mode=1 +pbmp_oversubscribe=0x6fffffffffffffffdfffffffffffffffe +pbmp_xport_xe=0x6fffffffffffffffdfffffffffffffffe + + +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_130.0=128:10:m +portmap_66.0=129:10:m +phy_chain_tx_lane_map_physical{1.0}=0x0132 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_rx_lane_map_physical{5.0}=0x2031 +phy_chain_tx_lane_map_physical{9.0}=0x0132 +phy_chain_rx_lane_map_physical{9.0}=0x3210 +phy_chain_tx_lane_map_physical{13.0}=0x3201 +phy_chain_rx_lane_map_physical{13.0}=0x2031 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x3210 +phy_chain_tx_lane_map_physical{21.0}=0x2301 +phy_chain_rx_lane_map_physical{21.0}=0x2031 +phy_chain_tx_lane_map_physical{25.0}=0x0123 +phy_chain_rx_lane_map_physical{25.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x3201 +phy_chain_rx_lane_map_physical{29.0}=0x2031 +phy_chain_tx_lane_map_physical{33.0}=0x0213 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 +phy_chain_tx_lane_map_physical{41.0}=0x0231 +phy_chain_rx_lane_map_physical{41.0}=0x3120 +phy_chain_tx_lane_map_physical{45.0}=0x1302 +phy_chain_rx_lane_map_physical{45.0}=0x2031 +phy_chain_tx_lane_map_physical{49.0}=0x2103 +phy_chain_rx_lane_map_physical{49.0}=0x3120 +phy_chain_tx_lane_map_physical{53.0}=0x2301 +phy_chain_rx_lane_map_physical{53.0}=0x2031 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x2301 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x1023 +phy_chain_tx_lane_map_physical{69.0}=0x0123 +phy_chain_rx_lane_map_physical{69.0}=0x1302 +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_rx_lane_map_physical{73.0}=0x1032 +phy_chain_tx_lane_map_physical{77.0}=0x2013 +phy_chain_rx_lane_map_physical{77.0}=0x3120 +phy_chain_tx_lane_map_physical{81.0}=0x1302 +phy_chain_rx_lane_map_physical{81.0}=0x2031 +phy_chain_tx_lane_map_physical{85.0}=0x0123 +phy_chain_rx_lane_map_physical{85.0}=0x2130 +phy_chain_tx_lane_map_physical{89.0}=0x2301 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x0312 +phy_chain_rx_lane_map_physical{93.0}=0x2310 +phy_chain_tx_lane_map_physical{97.0}=0x2301 +phy_chain_rx_lane_map_physical{97.0}=0x1032 +phy_chain_tx_lane_map_physical{101.0}=0x0123 +phy_chain_rx_lane_map_physical{101.0}=0x3210 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_rx_lane_map_physical{105.0}=0x1032 +phy_chain_tx_lane_map_physical{109.0}=0x0123 +phy_chain_rx_lane_map_physical{109.0}=0x3210 +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{113.0}=0x2031 +phy_chain_tx_lane_map_physical{117.0}=0x0123 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_tx_lane_map_physical{121.0}=0x2301 +phy_chain_rx_lane_map_physical{121.0}=0x1032 +phy_chain_tx_lane_map_physical{125.0}=0x0123 +phy_chain_rx_lane_map_physical{125.0}=0x3210 +phy_chain_tx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{129.0}=0x0231 +phy_chain_tx_lane_map_physical{128.0}=0x3210 +phy_chain_rx_lane_map_physical{128.0}=0x0231 +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 +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 +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 +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 +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 +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 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x1 +dport_map_enable=1 +dport_map_port_1=1 +dport_map_port_2=2 +dport_map_port_3=3 +dport_map_port_4=4 +dport_map_port_5=5 +dport_map_port_6=6 +dport_map_port_7=7 +dport_map_port_8=8 +dport_map_port_9=9 +dport_map_port_10=10 +dport_map_port_11=11 +dport_map_port_12=12 +dport_map_port_13=13 +dport_map_port_14=14 +dport_map_port_15=15 +dport_map_port_16=16 +dport_map_port_17=17 +dport_map_port_18=18 +dport_map_port_19=19 +dport_map_port_20=20 +dport_map_port_21=21 +dport_map_port_22=22 +dport_map_port_23=23 +dport_map_port_24=24 +dport_map_port_25=25 +dport_map_port_26=26 +dport_map_port_27=27 +dport_map_port_28=28 +dport_map_port_29=29 +dport_map_port_30=30 +dport_map_port_31=31 +dport_map_port_32=32 +dport_map_port_33=33 +dport_map_port_34=34 +dport_map_port_35=35 +dport_map_port_36=36 +dport_map_port_37=37 +dport_map_port_38=38 +dport_map_port_39=39 +dport_map_port_40=40 +dport_map_port_41=41 +dport_map_port_42=42 +dport_map_port_43=43 +dport_map_port_44=44 +dport_map_port_45=45 +dport_map_port_46=46 +dport_map_port_47=47 +dport_map_port_48=48 +dport_map_port_49=49 +dport_map_port_50=50 +dport_map_port_51=51 +dport_map_port_52=52 +dport_map_port_53=53 +dport_map_port_54=54 +dport_map_port_55=55 +dport_map_port_56=56 +dport_map_port_57=57 +dport_map_port_58=58 +dport_map_port_59=59 +dport_map_port_60=60 +dport_map_port_61=61 +dport_map_port_62=62 +dport_map_port_63=63 +dport_map_port_64=64 +dport_map_port_67=65 +dport_map_port_68=66 +dport_map_port_69=67 +dport_map_port_70=68 +dport_map_port_71=69 +dport_map_port_72=70 +dport_map_port_73=71 +dport_map_port_74=72 +dport_map_port_75=73 +dport_map_port_76=74 +dport_map_port_77=75 +dport_map_port_78=76 +dport_map_port_79=77 +dport_map_port_80=78 +dport_map_port_81=79 +dport_map_port_82=80 +dport_map_port_83=81 +dport_map_port_84=82 +dport_map_port_85=83 +dport_map_port_86=84 +dport_map_port_87=85 +dport_map_port_88=86 +dport_map_port_89=87 +dport_map_port_90=88 +dport_map_port_91=89 +dport_map_port_92=90 +dport_map_port_93=91 +dport_map_port_94=92 +dport_map_port_95=93 +dport_map_port_96=94 +dport_map_port_97=95 +dport_map_port_98=96 +dport_map_port_99=97 +dport_map_port_100=98 +dport_map_port_101=99 +dport_map_port_102=100 +dport_map_port_103=101 +dport_map_port_104=102 +dport_map_port_105=103 +dport_map_port_106=104 +dport_map_port_107=105 +dport_map_port_108=106 +dport_map_port_109=107 +dport_map_port_110=108 +dport_map_port_111=109 +dport_map_port_112=110 +dport_map_port_113=111 +dport_map_port_114=112 +dport_map_port_115=113 +dport_map_port_116=114 +dport_map_port_117=115 +dport_map_port_118=116 +dport_map_port_119=117 +dport_map_port_120=118 +dport_map_port_121=119 +dport_map_port_122=120 +dport_map_port_123=121 +dport_map_port_124=122 +dport_map_port_125=123 +dport_map_port_126=124 +dport_map_port_127=125 +dport_map_port_129=126 +dport_map_port_66=127 +dport_map_port_130=128 + +mmu_init_config="TD3-DELL-lossless" +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-C8D48/buffers.json.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..3369e2cc5e4d --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "26284032", + "type": "ingress", + "mode": "dynamic", + "xoff": "6291456" + }, + "egress_lossless_pool": { + "size": "32575488", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "static", + "static_th":"32575488" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..3a8e9a92261a --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/buffers_defaults_t1.j2 @@ -0,0 +1,37 @@ +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "26284032", + "type": "ingress", + "mode": "dynamic", + "xoff": "6291456" + }, + "egress_lossless_pool": { + "size": "32575488", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "static", + "static_th":"32575488" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} + diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/custom_led.bin b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/custom_led.bin new file mode 100755 index 000000000000..49e559cd9813 Binary files /dev/null and b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/pg_profile_lookup.ini b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/pg_profile_lookup.ini new file mode 100644 index 000000000000..aedda37a8878 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -3 2288 + 25000 5m 1248 2288 53248 -3 2288 + 40000 5m 1248 2288 66560 -3 2288 + 50000 5m 1248 2288 90272 -3 2288 + 100000 5m 1248 2288 165568 -3 2288 + 10000 40m 1248 2288 37024 -3 2288 + 25000 40m 1248 2288 53248 -3 2288 + 40000 40m 1248 2288 71552 -3 2288 + 50000 40m 1248 2288 96096 -3 2288 + 100000 40m 1248 2288 177632 -3 2288 + 10000 300m 1248 2288 46176 -3 2288 + 25000 300m 1248 2288 79040 -3 2288 + 40000 300m 1248 2288 108160 -3 2288 + 50000 300m 1248 2288 141856 -3 2288 + 100000 300m 1248 2288 268736 -3 2288 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/port_config.ini b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/port_config.ini new file mode 100644 index 000000000000..3fc2ef699913 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/port_config.ini @@ -0,0 +1,59 @@ +# name lanes alias index speed +Ethernet0 1,2 fiftyGigE1/1/1 1 50000 +Ethernet2 3,4 fiftyGigE1/1/2 1 50000 +Ethernet4 5,6 fiftyGigE1/2/1 2 50000 +Ethernet6 7,8 fiftyGigE1/2/2 2 50000 +Ethernet8 9,10 fiftyGigE1/3/1 3 50000 +Ethernet10 11,12 fiftyGigE1/3/2 3 50000 +Ethernet12 13,14 fiftyGigE1/4/1 4 50000 +Ethernet14 15,16 fiftyGigE1/4/2 4 50000 +Ethernet16 17,18 fiftyGigE1/5/1 5 50000 +Ethernet18 19,20 fiftyGigE1/5/2 5 50000 +Ethernet20 21,22 fiftyGigE1/6/1 6 50000 +Ethernet22 23,24 fiftyGigE1/6/2 6 50000 +Ethernet24 25,26,27,28 hundredGigE1/7 7 100000 +Ethernet28 29,30,31,32 hundredGigE1/8 8 100000 +Ethernet32 33,34,35,36 hundredGigE1/9 9 100000 +Ethernet36 37,38,39,40 hundredGigE1/10 10 100000 +Ethernet40 41,42 fiftyGigE1/11/1 11 50000 +Ethernet42 43,44 fiftyGigE1/11/2 11 50000 +Ethernet44 45,46 fiftyGigE1/12/1 12 50000 +Ethernet46 47,48 fiftyGigE1/12/2 12 50000 +Ethernet48 49,50 fiftyGigE1/13/1 13 50000 +Ethernet50 51,52 fiftyGigE1/13/2 13 50000 +Ethernet52 53,54 fiftyGigE1/14/1 14 50000 +Ethernet54 55,56 fiftyGigE1/14/2 14 50000 +Ethernet56 57,58 fiftyGigE1/15/1 15 50000 +Ethernet58 59,60 fiftyGigE1/15/2 15 50000 +Ethernet60 61,62 fiftyGigE1/16/1 16 50000 +Ethernet62 63,64 fiftyGigE1/16/2 16 50000 +Ethernet64 65,66 fiftyGigE1/17/1 17 50000 +Ethernet66 67,68 fiftyGigE1/17/2 17 50000 +Ethernet68 69,70 fiftyGigE1/18/1 18 50000 +Ethernet70 71,72 fiftyGigE1/18/2 18 50000 +Ethernet72 73,74 fiftyGigE1/19/1 19 50000 +Ethernet74 75,76 fiftyGigE1/19/2 19 50000 +Ethernet76 77,78 fiftyGigE1/20/1 20 50000 +Ethernet78 79,80 fiftyGigE1/20/2 20 50000 +Ethernet80 81,82 fiftyGigE1/21/1 21 50000 +Ethernet82 83,84 fiftyGigE1/21/2 21 50000 +Ethernet84 85,86 fiftyGigE1/22/1 22 50000 +Ethernet86 87,88 fiftyGigE1/22/2 22 50000 +Ethernet88 89,90,91,92 hundredGigE1/23 23 100000 +Ethernet92 93,94,95,96 hundredGigE1/24 24 100000 +Ethernet96 97,98,99,100 hundredGigE1/25 25 100000 +Ethernet100 101,102,103,104 hundredGigE1/26 26 100000 +Ethernet104 105,106 fiftyGigE1/27/1 27 50000 +Ethernet106 107,108 fiftyGigE1/27/2 27 50000 +Ethernet108 109,110 fiftyGigE1/28/1 28 50000 +Ethernet110 111,112 fiftyGigE1/28/2 28 50000 +Ethernet112 113,114 fiftyGigE1/29/1 29 50000 +Ethernet114 115,116 fiftyGigE1/29/2 29 50000 +Ethernet116 117,118 fiftyGigE1/30/1 30 50000 +Ethernet118 119,120 fiftyGigE1/30/2 30 50000 +Ethernet120 121,122 fiftyGigE1/31/1 31 50000 +Ethernet122 123,124 fiftyGigE1/31/2 31 50000 +Ethernet124 125,126 fiftyGigE1/32/1 32 50000 +Ethernet126 127,128 fiftyGigE1/32/2 32 50000 +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-C8D48/qos.json.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/sai.profile b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/sai.profile new file mode 100644 index 000000000000..b9703d137bb9 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-s5232f-8x100G+48x50G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/sai_preinit_cmd.soc new file mode 100644 index 000000000000..4d62900f898f --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/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-C8D48/td3-s5232f-8x100G+48x50G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/td3-s5232f-8x100G+48x50G.config.bcm new file mode 100644 index 000000000000..68fb77a4219f --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/td3-s5232f-8x100G+48x50G.config.bcm @@ -0,0 +1,573 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +os=unix + +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +parity_enable=1 +parity_correction=1 +tdma_intr_enable=1 +schan_intr_enable=0 +tdma_intr_enable=1 +miim_intr_enable=1 +stat_if_parity_enable=1 + +port_flex_enable=1 +port_flex_enable_66=0 +port_flex_enable_130=0 +phy_an_c73=3 +phy_an_c73_66=0 +phy_an_c73_130=0 + +module_64ports=0 +table_dma_enable=1 +tdma_timeout_usec=5000000 +mmu_lossless=0 +pdma_descriptor_prefetch_enable=1 +pktdma_poll_mode_channel_bitmap=1 + +l2xmsg_mode=1 +l2xmsg_hostbuf_size=8192 +ipv6_lpm_128b_enable=1 +max_vp_lags=0 + +l3_alpm_enable=2 +l2_mem_entries=32768 +l3_mem_entries=16384 +l3_max_ecmp_mode=1 + +bcm_tunnel_term_compatible_mode=1 +ifp_inports_support_enable=1 + +stable_size=0x5500000 + +oversubscribe_mode=1 +pbmp_oversubscribe=0x6fffffffffffffffdfffffffffffffffe +pbmp_xport_xe=0x6fffffffffffffffdfffffffffffffffe + + +portmap_1.0=1:50:2 +portmap_3.0=3:50:2 +portmap_5.0=5:50:2 +portmap_7.0=7:50:2 +portmap_9.0=9:50:2 +portmap_11.0=11:50:2 +portmap_13.0=13:50:2 +portmap_15.0=15:50:2 +portmap_17.0=17:50:2 +portmap_19.0=19:50:2 +portmap_21.0=21:50:2 +portmap_23.0=23:50:2 +portmap_25.0=25:100 +portmap_29.0=29:100 +portmap_33.0=33:100 +portmap_37.0=37:100 +portmap_41.0=41:50:2 +portmap_43.0=43:50:2 +portmap_45.0=45:50:2 +portmap_47.0=47:50:2 +portmap_49.0=49:50:2 +portmap_51.0=51:50:2 +portmap_53.0=53:50:2 +portmap_55.0=55:50:2 +portmap_57.0=57:50:2 +portmap_59.0=59:50:2 +portmap_61.0=61:50:2 +portmap_63.0=63:50:2 +portmap_67.0=65:50:2 +portmap_69.0=67:50:2 +portmap_71.0=69:50:2 +portmap_73.0=71:50:2 +portmap_75.0=73:50:2 +portmap_77.0=75:50:2 +portmap_79.0=77:50:2 +portmap_81.0=79:50:2 +portmap_83.0=81:50:2 +portmap_85.0=83:50:2 +portmap_87.0=85:50:2 +portmap_89.0=87:50:2 +portmap_91.0=89:100 +portmap_95.0=93:100 +portmap_99.0=97:100 +portmap_103.0=101:100 +portmap_107.0=105:50:2 +portmap_109.0=107:50:2 +portmap_111.0=109:50:2 +portmap_113.0=111:50:2 +portmap_115.0=113:50:2 +portmap_117.0=115:50:2 +portmap_119.0=117:50:2 +portmap_121.0=119:50:2 +portmap_123.0=121:50:2 +portmap_125.0=123:50:2 +portmap_127.0=125:50:2 +portmap_129.0=127:50:2 +portmap_130.0=128:10:m +portmap_66.0=129:10:m + + +phy_chain_tx_lane_map_physical{1.0}=0x0132 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_rx_lane_map_physical{5.0}=0x2031 +phy_chain_tx_lane_map_physical{9.0}=0x0132 +phy_chain_rx_lane_map_physical{9.0}=0x3210 +phy_chain_tx_lane_map_physical{13.0}=0x3201 +phy_chain_rx_lane_map_physical{13.0}=0x2031 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x3210 +phy_chain_tx_lane_map_physical{21.0}=0x2301 +phy_chain_rx_lane_map_physical{21.0}=0x2031 +phy_chain_tx_lane_map_physical{25.0}=0x0123 +phy_chain_rx_lane_map_physical{25.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x3201 +phy_chain_rx_lane_map_physical{29.0}=0x2031 +phy_chain_tx_lane_map_physical{33.0}=0x0213 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 +phy_chain_tx_lane_map_physical{41.0}=0x0231 +phy_chain_rx_lane_map_physical{41.0}=0x3120 +phy_chain_tx_lane_map_physical{45.0}=0x1302 +phy_chain_rx_lane_map_physical{45.0}=0x2031 +phy_chain_tx_lane_map_physical{49.0}=0x2103 +phy_chain_rx_lane_map_physical{49.0}=0x3120 +phy_chain_tx_lane_map_physical{53.0}=0x2301 +phy_chain_rx_lane_map_physical{53.0}=0x2031 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x2301 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x1023 +phy_chain_tx_lane_map_physical{69.0}=0x0123 +phy_chain_rx_lane_map_physical{69.0}=0x1302 +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_rx_lane_map_physical{73.0}=0x1032 +phy_chain_tx_lane_map_physical{77.0}=0x2013 +phy_chain_rx_lane_map_physical{77.0}=0x3120 +phy_chain_tx_lane_map_physical{81.0}=0x1302 +phy_chain_rx_lane_map_physical{81.0}=0x2031 +phy_chain_tx_lane_map_physical{85.0}=0x0123 +phy_chain_rx_lane_map_physical{85.0}=0x2130 +phy_chain_tx_lane_map_physical{89.0}=0x2301 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x0312 +phy_chain_rx_lane_map_physical{93.0}=0x2310 +phy_chain_tx_lane_map_physical{97.0}=0x2301 +phy_chain_rx_lane_map_physical{97.0}=0x1032 +phy_chain_tx_lane_map_physical{101.0}=0x0123 +phy_chain_rx_lane_map_physical{101.0}=0x3210 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_rx_lane_map_physical{105.0}=0x1032 +phy_chain_tx_lane_map_physical{109.0}=0x0123 +phy_chain_rx_lane_map_physical{109.0}=0x3210 +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{113.0}=0x2031 +phy_chain_tx_lane_map_physical{117.0}=0x0123 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_tx_lane_map_physical{121.0}=0x2301 +phy_chain_rx_lane_map_physical{121.0}=0x1032 +phy_chain_tx_lane_map_physical{125.0}=0x0123 +phy_chain_rx_lane_map_physical{125.0}=0x3210 +phy_chain_tx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{129.0}=0x0231 +phy_chain_tx_lane_map_physical{128.0}=0x3210 +phy_chain_rx_lane_map_physical{128.0}=0x0231 +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 +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 +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 +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 +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 +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 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x1 +dport_map_enable=1 +dport_map_port_1=1 +dport_map_port_2=2 +dport_map_port_3=3 +dport_map_port_4=4 +dport_map_port_5=5 +dport_map_port_6=6 +dport_map_port_7=7 +dport_map_port_8=8 +dport_map_port_9=9 +dport_map_port_10=10 +dport_map_port_11=11 +dport_map_port_12=12 +dport_map_port_13=13 +dport_map_port_14=14 +dport_map_port_15=15 +dport_map_port_16=16 +dport_map_port_17=17 +dport_map_port_18=18 +dport_map_port_19=19 +dport_map_port_20=20 +dport_map_port_21=21 +dport_map_port_22=22 +dport_map_port_23=23 +dport_map_port_24=24 +dport_map_port_25=25 +dport_map_port_26=26 +dport_map_port_27=27 +dport_map_port_28=28 +dport_map_port_29=29 +dport_map_port_30=30 +dport_map_port_31=31 +dport_map_port_32=32 +dport_map_port_33=33 +dport_map_port_34=34 +dport_map_port_35=35 +dport_map_port_36=36 +dport_map_port_37=37 +dport_map_port_38=38 +dport_map_port_39=39 +dport_map_port_40=40 +dport_map_port_41=41 +dport_map_port_42=42 +dport_map_port_43=43 +dport_map_port_44=44 +dport_map_port_45=45 +dport_map_port_46=46 +dport_map_port_47=47 +dport_map_port_48=48 +dport_map_port_49=49 +dport_map_port_50=50 +dport_map_port_51=51 +dport_map_port_52=52 +dport_map_port_53=53 +dport_map_port_54=54 +dport_map_port_55=55 +dport_map_port_56=56 +dport_map_port_57=57 +dport_map_port_58=58 +dport_map_port_59=59 +dport_map_port_60=60 +dport_map_port_61=61 +dport_map_port_62=62 +dport_map_port_63=63 +dport_map_port_64=64 +dport_map_port_67=65 +dport_map_port_68=66 +dport_map_port_69=67 +dport_map_port_70=68 +dport_map_port_71=69 +dport_map_port_72=70 +dport_map_port_73=71 +dport_map_port_74=72 +dport_map_port_75=73 +dport_map_port_76=74 +dport_map_port_77=75 +dport_map_port_78=76 +dport_map_port_79=77 +dport_map_port_80=78 +dport_map_port_81=79 +dport_map_port_82=80 +dport_map_port_83=81 +dport_map_port_84=82 +dport_map_port_85=83 +dport_map_port_86=84 +dport_map_port_87=85 +dport_map_port_88=86 +dport_map_port_89=87 +dport_map_port_90=88 +dport_map_port_91=89 +dport_map_port_92=90 +dport_map_port_93=91 +dport_map_port_94=92 +dport_map_port_95=93 +dport_map_port_96=94 +dport_map_port_97=95 +dport_map_port_98=96 +dport_map_port_99=97 +dport_map_port_100=98 +dport_map_port_101=99 +dport_map_port_102=100 +dport_map_port_103=101 +dport_map_port_104=102 +dport_map_port_105=103 +dport_map_port_106=104 +dport_map_port_107=105 +dport_map_port_108=106 +dport_map_port_109=107 +dport_map_port_110=108 +dport_map_port_111=109 +dport_map_port_112=110 +dport_map_port_113=111 +dport_map_port_114=112 +dport_map_port_115=113 +dport_map_port_116=114 +dport_map_port_117=115 +dport_map_port_118=116 +dport_map_port_119=117 +dport_map_port_120=118 +dport_map_port_121=119 +dport_map_port_122=120 +dport_map_port_123=121 +dport_map_port_124=122 +dport_map_port_125=123 +dport_map_port_126=124 +dport_map_port_127=125 +dport_map_port_129=126 +dport_map_port_66=127 +dport_map_port_130=128 + +mmu_init_config="TD3-DELL-lossless" +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/buffers.json.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..3369e2cc5e4d --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "26284032", + "type": "ingress", + "mode": "dynamic", + "xoff": "6291456" + }, + "egress_lossless_pool": { + "size": "32575488", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "static", + "static_th":"32575488" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..a1fa90d39779 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "26284032", + "type": "ingress", + "mode": "dynamic", + "xoff": "6291456" + }, + "egress_lossless_pool": { + "size": "32575488", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "static", + "static_th":"32575488" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/custom_led.bin b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/custom_led.bin new file mode 100755 index 000000000000..49e559cd9813 Binary files /dev/null and b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/port_config.ini b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/port_config.ini new file mode 100644 index 000000000000..55c8fb3dcf64 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/port_config.ini @@ -0,0 +1,35 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4 hundredGigE1/1 1 100000 +Ethernet4 5,6,7,8 hundredGigE1/2 2 100000 +Ethernet8 9,10,11,12 hundredGigE1/3 3 100000 +Ethernet12 13,14,15,16 hundredGigE1/4 4 100000 +Ethernet16 17,18,19,20 hundredGigE1/5 5 100000 +Ethernet20 21,22,23,24 hundredGigE1/6 6 100000 +Ethernet24 25,26,27,28 hundredGigE1/7 7 100000 +Ethernet28 29,30,31,32 hundredGigE1/8 8 100000 +Ethernet32 33,34,35,36 hundredGigE1/9 9 100000 +Ethernet36 37,38,39,40 hundredGigE1/10 10 100000 +Ethernet40 41,42,43,44 hundredGigE1/11 11 100000 +Ethernet44 45,46,47,48 hundredGigE1/12 12 100000 +Ethernet48 49,50,51,52 hundredGigE1/13 13 100000 +Ethernet52 53,54,55,56 hundredGigE1/14 14 100000 +Ethernet56 57,58,59,60 hundredGigE1/15 15 100000 +Ethernet60 61,62,63,64 hundredGigE1/16 16 100000 +Ethernet64 65,66,67,68 hundredGigE1/17 17 100000 +Ethernet68 69,70,71,72 hundredGigE1/18 18 100000 +Ethernet72 73,74,75,76 hundredGigE1/19 19 100000 +Ethernet76 77,78,79,80 hundredGigE1/20 20 100000 +Ethernet80 81,82,83,84 hundredGigE1/21 21 100000 +Ethernet84 85,86,87,88 hundredGigE1/22 22 100000 +Ethernet88 89,90,91,92 hundredGigE1/23 23 100000 +Ethernet92 93,94,95,96 hundredGigE1/24 24 100000 +Ethernet96 97,98,99,100 hundredGigE1/25 25 100000 +Ethernet100 101,102,103,104 hundredGigE1/26 26 100000 +Ethernet104 105,106,107,108 hundredGigE1/27 27 100000 +Ethernet108 109,110,111,112 hundredGigE1/28 28 100000 +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 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/qos.json.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/qos.json.j2 new file mode 100644 index 000000000000..d2b3d2b0131c --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/qos.json.j2 @@ -0,0 +1,226 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "0", + "4": "0", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "DWRR", + "weight": "50" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/sai.profile b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/sai.profile new file mode 100644 index 000000000000..3491c7700c24 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-s5232f-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 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 new file mode 100644 index 000000000000..c44e4805c62a --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/td3-s5232f-32x100G.config.bcm @@ -0,0 +1,546 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +os=unix + +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +parity_enable=1 +parity_correction=1 +tdma_intr_enable=1 +schan_intr_enable=0 +tdma_intr_enable=1 +miim_intr_enable=1 +stat_if_parity_enable=1 + +port_flex_enable=1 +port_flex_enable_66=0 +port_flex_enable_130=0 +phy_an_c73=3 +phy_an_c73_66=0 +phy_an_c73_130=0 + +module_64ports=0 +table_dma_enable=1 +tdma_timeout_usec=5000000 +mmu_lossless=0 +pdma_descriptor_prefetch_enable=1 +pktdma_poll_mode_channel_bitmap=1 + +l2xmsg_mode=1 +l2xmsg_hostbuf_size=8192 +ipv6_lpm_128b_enable=1 +max_vp_lags=0 + +l3_alpm_enable=2 +l2_mem_entries=32768 +l3_mem_entries=16384 +l3_max_ecmp_mode=1 + +bcm_tunnel_term_compatible_mode=1 +ifp_inports_support_enable=1 + +stable_size=0x5500000 + +oversubscribe_mode=1 +pbmp_oversubscribe=0x6fffffffffffffffdfffffffffffffffe +pbmp_xport_xe=0x6fffffffffffffffdfffffffffffffffe + + +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_130.0=128:10:m +portmap_66.0=129:10:m +phy_chain_tx_lane_map_physical{1.0}=0x0132 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_rx_lane_map_physical{5.0}=0x2031 +phy_chain_tx_lane_map_physical{9.0}=0x0132 +phy_chain_rx_lane_map_physical{9.0}=0x3210 +phy_chain_tx_lane_map_physical{13.0}=0x3201 +phy_chain_rx_lane_map_physical{13.0}=0x2031 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x3210 +phy_chain_tx_lane_map_physical{21.0}=0x2301 +phy_chain_rx_lane_map_physical{21.0}=0x2031 +phy_chain_tx_lane_map_physical{25.0}=0x0123 +phy_chain_rx_lane_map_physical{25.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x3201 +phy_chain_rx_lane_map_physical{29.0}=0x2031 +phy_chain_tx_lane_map_physical{33.0}=0x0213 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 +phy_chain_tx_lane_map_physical{41.0}=0x0231 +phy_chain_rx_lane_map_physical{41.0}=0x3120 +phy_chain_tx_lane_map_physical{45.0}=0x1302 +phy_chain_rx_lane_map_physical{45.0}=0x2031 +phy_chain_tx_lane_map_physical{49.0}=0x2103 +phy_chain_rx_lane_map_physical{49.0}=0x3120 +phy_chain_tx_lane_map_physical{53.0}=0x2301 +phy_chain_rx_lane_map_physical{53.0}=0x2031 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x2301 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x1023 +phy_chain_tx_lane_map_physical{69.0}=0x0123 +phy_chain_rx_lane_map_physical{69.0}=0x1302 +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_rx_lane_map_physical{73.0}=0x1032 +phy_chain_tx_lane_map_physical{77.0}=0x2013 +phy_chain_rx_lane_map_physical{77.0}=0x3120 +phy_chain_tx_lane_map_physical{81.0}=0x1302 +phy_chain_rx_lane_map_physical{81.0}=0x2031 +phy_chain_tx_lane_map_physical{85.0}=0x0123 +phy_chain_rx_lane_map_physical{85.0}=0x2130 +phy_chain_tx_lane_map_physical{89.0}=0x2301 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x0312 +phy_chain_rx_lane_map_physical{93.0}=0x2310 +phy_chain_tx_lane_map_physical{97.0}=0x2301 +phy_chain_rx_lane_map_physical{97.0}=0x1032 +phy_chain_tx_lane_map_physical{101.0}=0x0123 +phy_chain_rx_lane_map_physical{101.0}=0x3210 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_rx_lane_map_physical{105.0}=0x1032 +phy_chain_tx_lane_map_physical{109.0}=0x0123 +phy_chain_rx_lane_map_physical{109.0}=0x3210 +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{113.0}=0x2031 +phy_chain_tx_lane_map_physical{117.0}=0x0123 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_tx_lane_map_physical{121.0}=0x2301 +phy_chain_rx_lane_map_physical{121.0}=0x1032 +phy_chain_tx_lane_map_physical{125.0}=0x0123 +phy_chain_rx_lane_map_physical{125.0}=0x3210 +phy_chain_tx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{129.0}=0x0231 +phy_chain_tx_lane_map_physical{128.0}=0x3210 +phy_chain_rx_lane_map_physical{128.0}=0x0231 +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 +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 +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 +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 +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 +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 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x1 +dport_map_enable=1 +dport_map_port_1=1 +dport_map_port_2=2 +dport_map_port_3=3 +dport_map_port_4=4 +dport_map_port_5=5 +dport_map_port_6=6 +dport_map_port_7=7 +dport_map_port_8=8 +dport_map_port_9=9 +dport_map_port_10=10 +dport_map_port_11=11 +dport_map_port_12=12 +dport_map_port_13=13 +dport_map_port_14=14 +dport_map_port_15=15 +dport_map_port_16=16 +dport_map_port_17=17 +dport_map_port_18=18 +dport_map_port_19=19 +dport_map_port_20=20 +dport_map_port_21=21 +dport_map_port_22=22 +dport_map_port_23=23 +dport_map_port_24=24 +dport_map_port_25=25 +dport_map_port_26=26 +dport_map_port_27=27 +dport_map_port_28=28 +dport_map_port_29=29 +dport_map_port_30=30 +dport_map_port_31=31 +dport_map_port_32=32 +dport_map_port_33=33 +dport_map_port_34=34 +dport_map_port_35=35 +dport_map_port_36=36 +dport_map_port_37=37 +dport_map_port_38=38 +dport_map_port_39=39 +dport_map_port_40=40 +dport_map_port_41=41 +dport_map_port_42=42 +dport_map_port_43=43 +dport_map_port_44=44 +dport_map_port_45=45 +dport_map_port_46=46 +dport_map_port_47=47 +dport_map_port_48=48 +dport_map_port_49=49 +dport_map_port_50=50 +dport_map_port_51=51 +dport_map_port_52=52 +dport_map_port_53=53 +dport_map_port_54=54 +dport_map_port_55=55 +dport_map_port_56=56 +dport_map_port_57=57 +dport_map_port_58=58 +dport_map_port_59=59 +dport_map_port_60=60 +dport_map_port_61=61 +dport_map_port_62=62 +dport_map_port_63=63 +dport_map_port_64=64 +dport_map_port_67=65 +dport_map_port_68=66 +dport_map_port_69=67 +dport_map_port_70=68 +dport_map_port_71=69 +dport_map_port_72=70 +dport_map_port_73=71 +dport_map_port_74=72 +dport_map_port_75=73 +dport_map_port_76=74 +dport_map_port_77=75 +dport_map_port_78=76 +dport_map_port_79=77 +dport_map_port_80=78 +dport_map_port_81=79 +dport_map_port_82=80 +dport_map_port_83=81 +dport_map_port_84=82 +dport_map_port_85=83 +dport_map_port_86=84 +dport_map_port_87=85 +dport_map_port_88=86 +dport_map_port_89=87 +dport_map_port_90=88 +dport_map_port_91=89 +dport_map_port_92=90 +dport_map_port_93=91 +dport_map_port_94=92 +dport_map_port_95=93 +dport_map_port_96=94 +dport_map_port_97=95 +dport_map_port_98=96 +dport_map_port_99=97 +dport_map_port_100=98 +dport_map_port_101=99 +dport_map_port_102=100 +dport_map_port_103=101 +dport_map_port_104=102 +dport_map_port_105=103 +dport_map_port_106=104 +dport_map_port_107=105 +dport_map_port_108=106 +dport_map_port_109=107 +dport_map_port_110=108 +dport_map_port_111=109 +dport_map_port_112=110 +dport_map_port_113=111 +dport_map_port_114=112 +dport_map_port_115=113 +dport_map_port_116=114 +dport_map_port_117=115 +dport_map_port_118=116 +dport_map_port_119=117 +dport_map_port_120=118 +dport_map_port_121=119 +dport_map_port_122=120 +dport_map_port_123=121 +dport_map_port_124=122 +dport_map_port_125=123 +dport_map_port_126=124 +dport_map_port_127=125 +dport_map_port_129=126 +dport_map_port_66=127 +dport_map_port_130=128 + +mmu_init_config="TD3-DELL-lossless" +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/buffers.json.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..3369e2cc5e4d --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "26284032", + "type": "ingress", + "mode": "dynamic", + "xoff": "6291456" + }, + "egress_lossless_pool": { + "size": "32575488", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "static", + "static_th":"32575488" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..a1fa90d39779 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "26284032", + "type": "ingress", + "mode": "dynamic", + "xoff": "6291456" + }, + "egress_lossless_pool": { + "size": "32575488", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "static", + "static_th":"32575488" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/custom_led.bin b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/custom_led.bin new file mode 100755 index 000000000000..49e559cd9813 Binary files /dev/null and b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/port_config.ini b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/port_config.ini new file mode 100644 index 000000000000..726427759c08 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/port_config.ini @@ -0,0 +1,107 @@ +# name lanes alias index speed +Ethernet0 1 tenGigE1/1/1 1 10000 +Ethernet1 2 tenGigE1/1/2 1 10000 +Ethernet2 3 tenGigE1/1/3 1 10000 +Ethernet3 4 tenGigE1/1/4 1 10000 +Ethernet4 5 tenGigE1/2/1 2 10000 +Ethernet5 6 tenGigE1/2/2 2 10000 +Ethernet6 7 tenGigE1/2/3 2 10000 +Ethernet7 8 tenGigE1/2/4 2 10000 +Ethernet8 9 tenGigE1/3/1 3 10000 +Ethernet9 10 tenGigE1/3/2 3 10000 +Ethernet10 11 tenGigE1/3/3 3 10000 +Ethernet11 12 tenGigE1/3/4 3 10000 +Ethernet12 13 tenGigE1/4/1 4 10000 +Ethernet13 14 tenGigE1/4/2 4 10000 +Ethernet14 15 tenGigE1/4/3 4 10000 +Ethernet15 16 tenGigE1/4/4 4 10000 +Ethernet16 17 tenGigE1/5/1 5 10000 +Ethernet17 18 tenGigE1/5/2 5 10000 +Ethernet18 19 tenGigE1/5/3 5 10000 +Ethernet19 20 tenGigE1/5/4 5 10000 +Ethernet20 21 tenGigE1/6/1 6 10000 +Ethernet21 22 tenGigE1/6/2 6 10000 +Ethernet22 23 tenGigE1/6/3 6 10000 +Ethernet23 24 tenGigE1/6/4 6 10000 +Ethernet24 25 tenGigE1/7/1 7 10000 +Ethernet25 26 tenGigE1/7/2 7 10000 +Ethernet26 27 tenGigE1/7/3 7 10000 +Ethernet27 28 tenGigE1/7/4 7 10000 +Ethernet28 29 tenGigE1/8/1 8 10000 +Ethernet29 30 tenGigE1/8/2 8 10000 +Ethernet30 31 tenGigE1/8/3 8 10000 +Ethernet31 32 tenGigE1/8/4 8 10000 +Ethernet32 33 tenGigE1/9/1 9 10000 +Ethernet33 34 tenGigE1/9/2 9 10000 +Ethernet34 35 tenGigE1/9/3 9 10000 +Ethernet35 36 tenGigE1/9/4 9 10000 +Ethernet36 37 tenGigE1/10/1 10 10000 +Ethernet37 38 tenGigE1/10/2 10 10000 +Ethernet38 39 tenGigE1/10/3 10 10000 +Ethernet39 40 tenGigE1/10/4 10 10000 +Ethernet40 41 tenGigE1/11/1 11 10000 +Ethernet41 42 tenGigE1/11/2 11 10000 +Ethernet42 43 tenGigE1/11/3 11 10000 +Ethernet43 44 tenGigE1/11/4 11 10000 +Ethernet44 45 tenGigE1/12/1 12 10000 +Ethernet45 46 tenGigE1/12/2 12 10000 +Ethernet46 47 tenGigE1/12/3 12 10000 +Ethernet47 48 tenGigE1/12/4 12 10000 +Ethernet48 49 tenGigE1/13/1 13 10000 +Ethernet49 50 tenGigE1/13/2 13 10000 +Ethernet50 51 tenGigE1/13/3 13 10000 +Ethernet51 52 tenGigE1/13/4 13 10000 +Ethernet52 53 tenGigE1/14/1 14 10000 +Ethernet53 54 tenGigE1/14/2 14 10000 +Ethernet54 55 tenGigE1/14/3 14 10000 +Ethernet55 56 tenGigE1/14/4 14 10000 +Ethernet56 57 tenGigE1/15/1 15 10000 +Ethernet57 58 tenGigE1/15/2 15 10000 +Ethernet58 59 tenGigE1/15/3 15 10000 +Ethernet59 60 tenGigE1/15/4 15 10000 +Ethernet60 61 tenGigE1/16/1 16 10000 +Ethernet61 62 tenGigE1/16/2 16 10000 +Ethernet62 63 tenGigE1/16/3 16 10000 +Ethernet63 64 tenGigE1/16/4 16 10000 +Ethernet64 65 tenGigE1/17/1 17 10000 +Ethernet65 66 tenGigE1/17/2 17 10000 +Ethernet66 67 tenGigE1/17/3 17 10000 +Ethernet67 68 tenGigE1/17/4 17 10000 +Ethernet68 69 tenGigE1/18/1 18 10000 +Ethernet69 70 tenGigE1/18/2 18 10000 +Ethernet70 71 tenGigE1/18/3 18 10000 +Ethernet71 72 tenGigE1/18/4 18 10000 +Ethernet72 73 tenGigE1/19/1 19 10000 +Ethernet73 74 tenGigE1/19/2 19 10000 +Ethernet74 75 tenGigE1/19/3 19 10000 +Ethernet75 76 tenGigE1/19/4 19 10000 +Ethernet76 77 tenGigE1/20/1 20 10000 +Ethernet77 78 tenGigE1/20/2 20 10000 +Ethernet78 79 tenGigE1/20/3 20 10000 +Ethernet79 80 tenGigE1/20/4 20 10000 +Ethernet80 81 tenGigE1/21/1 21 10000 +Ethernet81 82 tenGigE1/21/2 21 10000 +Ethernet82 83 tenGigE1/21/3 21 10000 +Ethernet83 84 tenGigE1/21/4 21 10000 +Ethernet84 85 tenGigE1/22/1 22 10000 +Ethernet85 86 tenGigE1/22/2 22 10000 +Ethernet86 87 tenGigE1/22/3 22 10000 +Ethernet87 88 tenGigE1/22/4 22 10000 +Ethernet88 89 tenGigE1/23/1 23 10000 +Ethernet89 90 tenGigE1/23/2 23 10000 +Ethernet90 91 tenGigE1/23/3 23 10000 +Ethernet91 92 tenGigE1/23/4 23 10000 +Ethernet92 93 tenGigE1/24/1 24 10000 +Ethernet93 94 tenGigE1/24/2 24 10000 +Ethernet94 95 tenGigE1/24/3 24 10000 +Ethernet95 96 tenGigE1/24/4 24 10000 +Ethernet96 97,98,99,100 hundredGigE1/25 25 100000 +Ethernet100 101,102,103,104 hundredGigE1/26 26 100000 +Ethernet104 105,106,107,108 hundredGigE1/27 27 100000 +Ethernet108 109,110,111,112 hundredGigE1/28 28 100000 +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 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/qos.json.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/qos.json.j2 new file mode 100644 index 000000000000..d2b3d2b0131c --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/qos.json.j2 @@ -0,0 +1,226 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "0", + "4": "0", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "DWRR", + "weight": "50" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/sai.profile b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/sai.profile new file mode 100644 index 000000000000..166a0fa8c8bc --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-s5232f-96x10G+8x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 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 new file mode 100644 index 000000000000..6f62b7209198 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/td3-s5232f-96x10G+8x100G.config.bcm @@ -0,0 +1,619 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +os=unix + +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +parity_enable=1 +parity_correction=1 +tdma_intr_enable=1 +schan_intr_enable=0 +tdma_intr_enable=1 +miim_intr_enable=1 +stat_if_parity_enable=1 + +port_flex_enable=1 +port_flex_enable_66=0 +port_flex_enable_130=0 +phy_an_c73=3 +phy_an_c73_66=0 +phy_an_c73_130=0 + +module_64ports=0 +table_dma_enable=1 +tdma_timeout_usec=5000000 +mmu_lossless=0 +pdma_descriptor_prefetch_enable=1 +pktdma_poll_mode_channel_bitmap=1 + +l2xmsg_mode=1 +l2xmsg_hostbuf_size=8192 +ipv6_lpm_128b_enable=1 +max_vp_lags=0 + +l3_alpm_enable=2 +l2_mem_entries=32768 +l3_mem_entries=16384 +l3_max_ecmp_mode=1 + +bcm_tunnel_term_compatible_mode=1 +ifp_inports_support_enable=1 + +stable_size=0x5500000 + +oversubscribe_mode=1 +pbmp_oversubscribe=0x6fffffffffffffffdfffffffffffffffe +pbmp_xport_xe=0x6fffffffffffffffdfffffffffffffffe + + +portmap_1.0=1:10:1 +portmap_2.0=2:10:1 +portmap_3.0=3:10:1 +portmap_4.0=4:10:1 +portmap_5.0=5:10:1 +portmap_6.0=6:10:1 +portmap_7.0=7:10:1 +portmap_8.0=8:10:1 +portmap_9.0=9:10:1 +portmap_10.0=10:10:1 +portmap_11.0=11:10:1 +portmap_12.0=12:10:1 +portmap_13.0=13:10:1 +portmap_14.0=14:10:1 +portmap_15.0=15:10:1 +portmap_16.0=16:10:1 +portmap_17.0=17:10:1 +portmap_18.0=18:10:1 +portmap_19.0=19:10:1 +portmap_20.0=20:10:1 +portmap_21.0=21:10:1 +portmap_22.0=22:10:1 +portmap_23.0=23:10:1 +portmap_24.0=24:10:1 +portmap_25.0=25:10:1 +portmap_26.0=26:10:1 +portmap_27.0=27:10:1 +portmap_28.0=28:10:1 +portmap_29.0=29:10:1 +portmap_30.0=30:10:1 +portmap_31.0=31:10:1 +portmap_32.0=32:10:1 +portmap_33.0=33:10:1 +portmap_34.0=34:10:1 +portmap_35.0=35:10:1 +portmap_36.0=36:10:1 +portmap_37.0=37:10:1 +portmap_38.0=38:10:1 +portmap_39.0=39:10:1 +portmap_40.0=40:10:1 +portmap_41.0=41:10:1 +portmap_42.0=42:10:1 +portmap_43.0=43:10:1 +portmap_44.0=44:10:1 +portmap_45.0=45:10:1 +portmap_46.0=46:10:1 +portmap_47.0=47:10:1 +portmap_48.0=48:10:1 +portmap_49.0=49:10:1 +portmap_50.0=50:10:1 +portmap_51.0=51:10:1 +portmap_52.0=52:10:1 +portmap_53.0=53:10:1 +portmap_54.0=54:10:1 +portmap_55.0=55:10:1 +portmap_56.0=56:10:1 +portmap_57.0=57:10:1 +portmap_58.0=58:10:1 +portmap_59.0=59:10:1 +portmap_60.0=60:10:1 +portmap_61.0=61:10:1 +portmap_62.0=62:10:1 +portmap_63.0=63:10:1 +portmap_64.0=64:10:1 + +portmap_67.0=65:10:1 +portmap_68.0=66:10:1 +portmap_69.0=67:10:1 +portmap_70.0=68:10:1 +portmap_71.0=69:10:1 +portmap_72.0=70:10:1 +portmap_73.0=71:10:1 +portmap_74.0=72:10:1 +portmap_75.0=73:10:1 +portmap_76.0=74:10:1 +portmap_77.0=75:10:1 +portmap_78.0=76:10:1 +portmap_79.0=77:10:1 +portmap_80.0=78:10:1 +portmap_81.0=79:10:1 +portmap_82.0=80:10:1 +portmap_83.0=81:10:1 +portmap_84.0=82:10:1 +portmap_85.0=83:10:1 +portmap_86.0=84:10:1 +portmap_87.0=85:10:1 +portmap_88.0=86:10:1 +portmap_89.0=87:10:1 +portmap_90.0=88:10:1 +portmap_91.0=89:10:1 +portmap_92.0=90:10:1 +portmap_93.0=91:10:1 +portmap_94.0=92:10:1 +portmap_95.0=93:10:1 +portmap_96.0=94:10:1 +portmap_97.0=95:10:1 +portmap_98.0=96:10:1 +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_130.0=128:10:m +portmap_66.0=129:10:m +phy_chain_tx_lane_map_physical{1.0}=0x0132 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_rx_lane_map_physical{5.0}=0x2031 +phy_chain_tx_lane_map_physical{9.0}=0x0132 +phy_chain_rx_lane_map_physical{9.0}=0x3210 +phy_chain_tx_lane_map_physical{13.0}=0x3201 +phy_chain_rx_lane_map_physical{13.0}=0x2031 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x3210 +phy_chain_tx_lane_map_physical{21.0}=0x2301 +phy_chain_rx_lane_map_physical{21.0}=0x2031 +phy_chain_tx_lane_map_physical{25.0}=0x0123 +phy_chain_rx_lane_map_physical{25.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x3201 +phy_chain_rx_lane_map_physical{29.0}=0x2031 +phy_chain_tx_lane_map_physical{33.0}=0x0213 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 +phy_chain_tx_lane_map_physical{41.0}=0x0231 +phy_chain_rx_lane_map_physical{41.0}=0x3120 +phy_chain_tx_lane_map_physical{45.0}=0x1302 +phy_chain_rx_lane_map_physical{45.0}=0x2031 +phy_chain_tx_lane_map_physical{49.0}=0x2103 +phy_chain_rx_lane_map_physical{49.0}=0x3120 +phy_chain_tx_lane_map_physical{53.0}=0x2301 +phy_chain_rx_lane_map_physical{53.0}=0x2031 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x2301 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x1023 +phy_chain_tx_lane_map_physical{69.0}=0x0123 +phy_chain_rx_lane_map_physical{69.0}=0x1302 +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_rx_lane_map_physical{73.0}=0x1032 +phy_chain_tx_lane_map_physical{77.0}=0x2013 +phy_chain_rx_lane_map_physical{77.0}=0x3120 +phy_chain_tx_lane_map_physical{81.0}=0x1302 +phy_chain_rx_lane_map_physical{81.0}=0x2031 +phy_chain_tx_lane_map_physical{85.0}=0x0123 +phy_chain_rx_lane_map_physical{85.0}=0x2130 +phy_chain_tx_lane_map_physical{89.0}=0x2301 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x0312 +phy_chain_rx_lane_map_physical{93.0}=0x2310 +phy_chain_tx_lane_map_physical{97.0}=0x2301 +phy_chain_rx_lane_map_physical{97.0}=0x1032 +phy_chain_tx_lane_map_physical{101.0}=0x0123 +phy_chain_rx_lane_map_physical{101.0}=0x3210 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_rx_lane_map_physical{105.0}=0x1032 +phy_chain_tx_lane_map_physical{109.0}=0x0123 +phy_chain_rx_lane_map_physical{109.0}=0x3210 +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{113.0}=0x2031 +phy_chain_tx_lane_map_physical{117.0}=0x0123 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_tx_lane_map_physical{121.0}=0x2301 +phy_chain_rx_lane_map_physical{121.0}=0x1032 +phy_chain_tx_lane_map_physical{125.0}=0x0123 +phy_chain_rx_lane_map_physical{125.0}=0x3210 +phy_chain_tx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{129.0}=0x0231 +phy_chain_tx_lane_map_physical{128.0}=0x3210 +phy_chain_rx_lane_map_physical{128.0}=0x0231 +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 +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 +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 +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 +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 +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 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x1 +dport_map_enable=1 +dport_map_port_1=1 +dport_map_port_2=2 +dport_map_port_3=3 +dport_map_port_4=4 +dport_map_port_5=5 +dport_map_port_6=6 +dport_map_port_7=7 +dport_map_port_8=8 +dport_map_port_9=9 +dport_map_port_10=10 +dport_map_port_11=11 +dport_map_port_12=12 +dport_map_port_13=13 +dport_map_port_14=14 +dport_map_port_15=15 +dport_map_port_16=16 +dport_map_port_17=17 +dport_map_port_18=18 +dport_map_port_19=19 +dport_map_port_20=20 +dport_map_port_21=21 +dport_map_port_22=22 +dport_map_port_23=23 +dport_map_port_24=24 +dport_map_port_25=25 +dport_map_port_26=26 +dport_map_port_27=27 +dport_map_port_28=28 +dport_map_port_29=29 +dport_map_port_30=30 +dport_map_port_31=31 +dport_map_port_32=32 +dport_map_port_33=33 +dport_map_port_34=34 +dport_map_port_35=35 +dport_map_port_36=36 +dport_map_port_37=37 +dport_map_port_38=38 +dport_map_port_39=39 +dport_map_port_40=40 +dport_map_port_41=41 +dport_map_port_42=42 +dport_map_port_43=43 +dport_map_port_44=44 +dport_map_port_45=45 +dport_map_port_46=46 +dport_map_port_47=47 +dport_map_port_48=48 +dport_map_port_49=49 +dport_map_port_50=50 +dport_map_port_51=51 +dport_map_port_52=52 +dport_map_port_53=53 +dport_map_port_54=54 +dport_map_port_55=55 +dport_map_port_56=56 +dport_map_port_57=57 +dport_map_port_58=58 +dport_map_port_59=59 +dport_map_port_60=60 +dport_map_port_61=61 +dport_map_port_62=62 +dport_map_port_63=63 +dport_map_port_64=64 +dport_map_port_67=65 +dport_map_port_68=66 +dport_map_port_69=67 +dport_map_port_70=68 +dport_map_port_71=69 +dport_map_port_72=70 +dport_map_port_73=71 +dport_map_port_74=72 +dport_map_port_75=73 +dport_map_port_76=74 +dport_map_port_77=75 +dport_map_port_78=76 +dport_map_port_79=77 +dport_map_port_80=78 +dport_map_port_81=79 +dport_map_port_82=80 +dport_map_port_83=81 +dport_map_port_84=82 +dport_map_port_85=83 +dport_map_port_86=84 +dport_map_port_87=85 +dport_map_port_88=86 +dport_map_port_89=87 +dport_map_port_90=88 +dport_map_port_91=89 +dport_map_port_92=90 +dport_map_port_93=91 +dport_map_port_94=92 +dport_map_port_95=93 +dport_map_port_96=94 +dport_map_port_97=95 +dport_map_port_98=96 +dport_map_port_99=97 +dport_map_port_100=98 +dport_map_port_101=99 +dport_map_port_102=100 +dport_map_port_103=101 +dport_map_port_104=102 +dport_map_port_105=103 +dport_map_port_106=104 +dport_map_port_107=105 +dport_map_port_108=106 +dport_map_port_109=107 +dport_map_port_110=108 +dport_map_port_111=109 +dport_map_port_112=110 +dport_map_port_113=111 +dport_map_port_114=112 +dport_map_port_115=113 +dport_map_port_116=114 +dport_map_port_117=115 +dport_map_port_118=116 +dport_map_port_119=117 +dport_map_port_120=118 +dport_map_port_121=119 +dport_map_port_122=120 +dport_map_port_123=121 +dport_map_port_124=122 +dport_map_port_125=123 +dport_map_port_126=124 +dport_map_port_127=125 +dport_map_port_129=126 +dport_map_port_66=127 +dport_map_port_130=128 + +mmu_init_config="TD3-DELL-lossless" +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/buffers.json.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..3369e2cc5e4d --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "26284032", + "type": "ingress", + "mode": "dynamic", + "xoff": "6291456" + }, + "egress_lossless_pool": { + "size": "32575488", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "static", + "static_th":"32575488" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..a1fa90d39779 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "26284032", + "type": "ingress", + "mode": "dynamic", + "xoff": "6291456" + }, + "egress_lossless_pool": { + "size": "32575488", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "static", + "static_th":"32575488" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/custom_led.bin b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/custom_led.bin new file mode 100755 index 000000000000..49e559cd9813 Binary files /dev/null and b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/port_config.ini b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/port_config.ini new file mode 100644 index 000000000000..7366a95cf8b8 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/port_config.ini @@ -0,0 +1,107 @@ +# name lanes alias index speed +Ethernet0 1 twentyfiveGigE1/1/1 1 25000 +Ethernet1 2 twentyfiveGigE1/1/2 1 25000 +Ethernet2 3 twentyfiveGigE1/1/3 1 25000 +Ethernet3 4 twentyfiveGigE1/1/4 1 25000 +Ethernet4 5 twentyfiveGigE1/2/1 2 25000 +Ethernet5 6 twentyfiveGigE1/2/2 2 25000 +Ethernet6 7 twentyfiveGigE1/2/3 2 25000 +Ethernet7 8 twentyfiveGigE1/2/4 2 25000 +Ethernet8 9 twentyfiveGigE1/3/1 3 25000 +Ethernet9 10 twentyfiveGigE1/3/2 3 25000 +Ethernet10 11 twentyfiveGigE1/3/3 3 25000 +Ethernet11 12 twentyfiveGigE1/3/4 3 25000 +Ethernet12 13 twentyfiveGigE1/4/1 4 25000 +Ethernet13 14 twentyfiveGigE1/4/2 4 25000 +Ethernet14 15 twentyfiveGigE1/4/3 4 25000 +Ethernet15 16 twentyfiveGigE1/4/4 4 25000 +Ethernet16 17 twentyfiveGigE1/5/1 5 25000 +Ethernet17 18 twentyfiveGigE1/5/2 5 25000 +Ethernet18 19 twentyfiveGigE1/5/3 5 25000 +Ethernet19 20 twentyfiveGigE1/5/4 5 25000 +Ethernet20 21 twentyfiveGigE1/6/1 6 25000 +Ethernet21 22 twentyfiveGigE1/6/2 6 25000 +Ethernet22 23 twentyfiveGigE1/6/3 6 25000 +Ethernet23 24 twentyfiveGigE1/6/4 6 25000 +Ethernet24 25 twentyfiveGigE1/7/1 7 25000 +Ethernet25 26 twentyfiveGigE1/7/2 7 25000 +Ethernet26 27 twentyfiveGigE1/7/3 7 25000 +Ethernet27 28 twentyfiveGigE1/7/4 7 25000 +Ethernet28 29 twentyfiveGigE1/8/1 8 25000 +Ethernet29 30 twentyfiveGigE1/8/2 8 25000 +Ethernet30 31 twentyfiveGigE1/8/3 8 25000 +Ethernet31 32 twentyfiveGigE1/8/4 8 25000 +Ethernet32 33 twentyfiveGigE1/9/1 9 25000 +Ethernet33 34 twentyfiveGigE1/9/2 9 25000 +Ethernet34 35 twentyfiveGigE1/9/3 9 25000 +Ethernet35 36 twentyfiveGigE1/9/4 9 25000 +Ethernet36 37 twentyfiveGigE1/10/1 10 25000 +Ethernet37 38 twentyfiveGigE1/10/2 10 25000 +Ethernet38 39 twentyfiveGigE1/10/3 10 25000 +Ethernet39 40 twentyfiveGigE1/10/4 10 25000 +Ethernet40 41 twentyfiveGigE1/11/1 11 25000 +Ethernet41 42 twentyfiveGigE1/11/2 11 25000 +Ethernet42 43 twentyfiveGigE1/11/3 11 25000 +Ethernet43 44 twentyfiveGigE1/11/4 11 25000 +Ethernet44 45 twentyfiveGigE1/12/1 12 25000 +Ethernet45 46 twentyfiveGigE1/12/2 12 25000 +Ethernet46 47 twentyfiveGigE1/12/3 12 25000 +Ethernet47 48 twentyfiveGigE1/12/4 12 25000 +Ethernet48 49 twentyfiveGigE1/13/1 13 25000 +Ethernet49 50 twentyfiveGigE1/13/2 13 25000 +Ethernet50 51 twentyfiveGigE1/13/3 13 25000 +Ethernet51 52 twentyfiveGigE1/13/4 13 25000 +Ethernet52 53 twentyfiveGigE1/14/1 14 25000 +Ethernet53 54 twentyfiveGigE1/14/2 14 25000 +Ethernet54 55 twentyfiveGigE1/14/3 14 25000 +Ethernet55 56 twentyfiveGigE1/14/4 14 25000 +Ethernet56 57 twentyfiveGigE1/15/1 15 25000 +Ethernet57 58 twentyfiveGigE1/15/2 15 25000 +Ethernet58 59 twentyfiveGigE1/15/3 15 25000 +Ethernet59 60 twentyfiveGigE1/15/4 15 25000 +Ethernet60 61 twentyfiveGigE1/16/1 16 25000 +Ethernet61 62 twentyfiveGigE1/16/2 16 25000 +Ethernet62 63 twentyfiveGigE1/16/3 16 25000 +Ethernet63 64 twentyfiveGigE1/16/4 16 25000 +Ethernet64 65 twentyfiveGigE1/17/1 17 25000 +Ethernet65 66 twentyfiveGigE1/17/2 17 25000 +Ethernet66 67 twentyfiveGigE1/17/3 17 25000 +Ethernet67 68 twentyfiveGigE1/17/4 17 25000 +Ethernet68 69 twentyfiveGigE1/18/1 18 25000 +Ethernet69 70 twentyfiveGigE1/18/2 18 25000 +Ethernet70 71 twentyfiveGigE1/18/3 18 25000 +Ethernet71 72 twentyfiveGigE1/18/4 18 25000 +Ethernet72 73 twentyfiveGigE1/19/1 19 25000 +Ethernet73 74 twentyfiveGigE1/19/2 19 25000 +Ethernet74 75 twentyfiveGigE1/19/3 19 25000 +Ethernet75 76 twentyfiveGigE1/19/4 19 25000 +Ethernet76 77 twentyfiveGigE1/20/1 20 25000 +Ethernet77 78 twentyfiveGigE1/20/2 20 25000 +Ethernet78 79 twentyfiveGigE1/20/3 20 25000 +Ethernet79 80 twentyfiveGigE1/20/4 20 25000 +Ethernet80 81 twentyfiveGigE1/21/1 21 25000 +Ethernet81 82 twentyfiveGigE1/21/2 21 25000 +Ethernet82 83 twentyfiveGigE1/21/3 21 25000 +Ethernet83 84 twentyfiveGigE1/21/4 21 25000 +Ethernet84 85 twentyfiveGigE1/22/1 22 25000 +Ethernet85 86 twentyfiveGigE1/22/2 22 25000 +Ethernet86 87 twentyfiveGigE1/22/3 22 25000 +Ethernet87 88 twentyfiveGigE1/22/4 22 25000 +Ethernet88 89 twentyfiveGigE1/23/1 23 25000 +Ethernet89 90 twentyfiveGigE1/23/2 23 25000 +Ethernet90 91 twentyfiveGigE1/23/3 23 25000 +Ethernet91 92 twentyfiveGigE1/23/4 23 25000 +Ethernet92 93 twentyfiveGigE1/24/1 24 25000 +Ethernet93 94 twentyfiveGigE1/24/2 24 25000 +Ethernet94 95 twentyfiveGigE1/24/3 24 25000 +Ethernet95 96 twentyfiveGigE1/24/4 24 25000 +Ethernet96 97,98,99,100 hundredGigE1/25 25 100000 +Ethernet100 101,102,103,104 hundredGigE1/26 26 100000 +Ethernet104 105,106,107,108 hundredGigE1/27 27 100000 +Ethernet108 109,110,111,112 hundredGigE1/28 28 100000 +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 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/qos.json.j2 b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/qos.json.j2 new file mode 100644 index 000000000000..d2b3d2b0131c --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/qos.json.j2 @@ -0,0 +1,226 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "0", + "4": "0", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "DWRR", + "weight": "50" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/sai.profile b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/sai.profile new file mode 100644 index 000000000000..0c5cf8ca671a --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-s5232f-96x25G+8x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 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 new file mode 100644 index 000000000000..a4fccde19686 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/td3-s5232f-96x25G+8x100G.config.bcm @@ -0,0 +1,619 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +os=unix + +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +parity_enable=1 +parity_correction=1 +tdma_intr_enable=1 +schan_intr_enable=0 +tdma_intr_enable=1 +miim_intr_enable=1 +stat_if_parity_enable=1 + +port_flex_enable=1 +port_flex_enable_66=0 +port_flex_enable_130=0 +phy_an_c73=3 +phy_an_c73_66=0 +phy_an_c73_130=0 + +module_64ports=0 +table_dma_enable=1 +tdma_timeout_usec=5000000 +mmu_lossless=0 +pdma_descriptor_prefetch_enable=1 +pktdma_poll_mode_channel_bitmap=1 + +l2xmsg_mode=1 +l2xmsg_hostbuf_size=8192 +ipv6_lpm_128b_enable=1 +max_vp_lags=0 + +l3_alpm_enable=2 +l2_mem_entries=32768 +l3_mem_entries=16384 +l3_max_ecmp_mode=1 + +bcm_tunnel_term_compatible_mode=1 +ifp_inports_support_enable=1 + +stable_size=0x5500000 + +oversubscribe_mode=1 +pbmp_oversubscribe=0x6fffffffffffffffdfffffffffffffffe +pbmp_xport_xe=0x6fffffffffffffffdfffffffffffffffe + + +portmap_1.0=1:25:1 +portmap_2.0=2:25:1 +portmap_3.0=3:25:1 +portmap_4.0=4:25:1 +portmap_5.0=5:25:1 +portmap_6.0=6:25:1 +portmap_7.0=7:25:1 +portmap_8.0=8:25:1 +portmap_9.0=9:25:1 +portmap_10.0=10:25:1 +portmap_11.0=11:25:1 +portmap_12.0=12:25:1 +portmap_13.0=13:25:1 +portmap_14.0=14:25:1 +portmap_15.0=15:25:1 +portmap_16.0=16:25:1 +portmap_17.0=17:25:1 +portmap_18.0=18:25:1 +portmap_19.0=19:25:1 +portmap_20.0=20:25:1 +portmap_21.0=21:25:1 +portmap_22.0=22:25:1 +portmap_23.0=23:25:1 +portmap_24.0=24:25:1 +portmap_25.0=25:25:1 +portmap_26.0=26:25:1 +portmap_27.0=27:25:1 +portmap_28.0=28:25:1 +portmap_29.0=29:25:1 +portmap_30.0=30:25:1 +portmap_31.0=31:25:1 +portmap_32.0=32:25:1 +portmap_33.0=33:25:1 +portmap_34.0=34:25:1 +portmap_35.0=35:25:1 +portmap_36.0=36:25:1 +portmap_37.0=37:25:1 +portmap_38.0=38:25:1 +portmap_39.0=39:25:1 +portmap_40.0=40:25:1 +portmap_41.0=41:25:1 +portmap_42.0=42:25:1 +portmap_43.0=43:25:1 +portmap_44.0=44:25:1 +portmap_45.0=45:25:1 +portmap_46.0=46:25:1 +portmap_47.0=47:25:1 +portmap_48.0=48:25:1 +portmap_49.0=49:25:1 +portmap_50.0=50:25:1 +portmap_51.0=51:25:1 +portmap_52.0=52:25:1 +portmap_53.0=53:25:1 +portmap_54.0=54:25:1 +portmap_55.0=55:25:1 +portmap_56.0=56:25:1 +portmap_57.0=57:25:1 +portmap_58.0=58:25:1 +portmap_59.0=59:25:1 +portmap_60.0=60:25:1 +portmap_61.0=61:25:1 +portmap_62.0=62:25:1 +portmap_63.0=63:25:1 +portmap_64.0=64:25:1 + +portmap_67.0=65:25:1 +portmap_68.0=66:25:1 +portmap_69.0=67:25:1 +portmap_70.0=68:25:1 +portmap_71.0=69:25:1 +portmap_72.0=70:25:1 +portmap_73.0=71:25:1 +portmap_74.0=72:25:1 +portmap_75.0=73:25:1 +portmap_76.0=74:25:1 +portmap_77.0=75:25:1 +portmap_78.0=76:25:1 +portmap_79.0=77:25:1 +portmap_80.0=78:25:1 +portmap_81.0=79:25:1 +portmap_82.0=80:25:1 +portmap_83.0=81:25:1 +portmap_84.0=82:25:1 +portmap_85.0=83:25:1 +portmap_86.0=84:25:1 +portmap_87.0=85:25:1 +portmap_88.0=86:25:1 +portmap_89.0=87:25:1 +portmap_90.0=88:25:1 +portmap_91.0=89:25:1 +portmap_92.0=90:25:1 +portmap_93.0=91:25:1 +portmap_94.0=92:25:1 +portmap_95.0=93:25:1 +portmap_96.0=94:25:1 +portmap_97.0=95:25:1 +portmap_98.0=96:25:1 +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_130.0=128:10:m +portmap_66.0=129:10:m +phy_chain_tx_lane_map_physical{1.0}=0x0132 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_rx_lane_map_physical{5.0}=0x2031 +phy_chain_tx_lane_map_physical{9.0}=0x0132 +phy_chain_rx_lane_map_physical{9.0}=0x3210 +phy_chain_tx_lane_map_physical{13.0}=0x3201 +phy_chain_rx_lane_map_physical{13.0}=0x2031 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x3210 +phy_chain_tx_lane_map_physical{21.0}=0x2301 +phy_chain_rx_lane_map_physical{21.0}=0x2031 +phy_chain_tx_lane_map_physical{25.0}=0x0123 +phy_chain_rx_lane_map_physical{25.0}=0x3210 +phy_chain_tx_lane_map_physical{29.0}=0x3201 +phy_chain_rx_lane_map_physical{29.0}=0x2031 +phy_chain_tx_lane_map_physical{33.0}=0x0213 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 +phy_chain_tx_lane_map_physical{41.0}=0x0231 +phy_chain_rx_lane_map_physical{41.0}=0x3120 +phy_chain_tx_lane_map_physical{45.0}=0x1302 +phy_chain_rx_lane_map_physical{45.0}=0x2031 +phy_chain_tx_lane_map_physical{49.0}=0x2103 +phy_chain_rx_lane_map_physical{49.0}=0x3120 +phy_chain_tx_lane_map_physical{53.0}=0x2301 +phy_chain_rx_lane_map_physical{53.0}=0x2031 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x2301 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x1023 +phy_chain_tx_lane_map_physical{69.0}=0x0123 +phy_chain_rx_lane_map_physical{69.0}=0x1302 +phy_chain_tx_lane_map_physical{73.0}=0x2301 +phy_chain_rx_lane_map_physical{73.0}=0x1032 +phy_chain_tx_lane_map_physical{77.0}=0x2013 +phy_chain_rx_lane_map_physical{77.0}=0x3120 +phy_chain_tx_lane_map_physical{81.0}=0x1302 +phy_chain_rx_lane_map_physical{81.0}=0x2031 +phy_chain_tx_lane_map_physical{85.0}=0x0123 +phy_chain_rx_lane_map_physical{85.0}=0x2130 +phy_chain_tx_lane_map_physical{89.0}=0x2301 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x0312 +phy_chain_rx_lane_map_physical{93.0}=0x2310 +phy_chain_tx_lane_map_physical{97.0}=0x2301 +phy_chain_rx_lane_map_physical{97.0}=0x1032 +phy_chain_tx_lane_map_physical{101.0}=0x0123 +phy_chain_rx_lane_map_physical{101.0}=0x3210 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_rx_lane_map_physical{105.0}=0x1032 +phy_chain_tx_lane_map_physical{109.0}=0x0123 +phy_chain_rx_lane_map_physical{109.0}=0x3210 +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{113.0}=0x2031 +phy_chain_tx_lane_map_physical{117.0}=0x0123 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_tx_lane_map_physical{121.0}=0x2301 +phy_chain_rx_lane_map_physical{121.0}=0x1032 +phy_chain_tx_lane_map_physical{125.0}=0x0123 +phy_chain_rx_lane_map_physical{125.0}=0x3210 +phy_chain_tx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{129.0}=0x0231 +phy_chain_tx_lane_map_physical{128.0}=0x3210 +phy_chain_rx_lane_map_physical{128.0}=0x0231 +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 +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 +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 +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 +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 +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 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x1 +dport_map_enable=1 +dport_map_port_1=1 +dport_map_port_2=2 +dport_map_port_3=3 +dport_map_port_4=4 +dport_map_port_5=5 +dport_map_port_6=6 +dport_map_port_7=7 +dport_map_port_8=8 +dport_map_port_9=9 +dport_map_port_10=10 +dport_map_port_11=11 +dport_map_port_12=12 +dport_map_port_13=13 +dport_map_port_14=14 +dport_map_port_15=15 +dport_map_port_16=16 +dport_map_port_17=17 +dport_map_port_18=18 +dport_map_port_19=19 +dport_map_port_20=20 +dport_map_port_21=21 +dport_map_port_22=22 +dport_map_port_23=23 +dport_map_port_24=24 +dport_map_port_25=25 +dport_map_port_26=26 +dport_map_port_27=27 +dport_map_port_28=28 +dport_map_port_29=29 +dport_map_port_30=30 +dport_map_port_31=31 +dport_map_port_32=32 +dport_map_port_33=33 +dport_map_port_34=34 +dport_map_port_35=35 +dport_map_port_36=36 +dport_map_port_37=37 +dport_map_port_38=38 +dport_map_port_39=39 +dport_map_port_40=40 +dport_map_port_41=41 +dport_map_port_42=42 +dport_map_port_43=43 +dport_map_port_44=44 +dport_map_port_45=45 +dport_map_port_46=46 +dport_map_port_47=47 +dport_map_port_48=48 +dport_map_port_49=49 +dport_map_port_50=50 +dport_map_port_51=51 +dport_map_port_52=52 +dport_map_port_53=53 +dport_map_port_54=54 +dport_map_port_55=55 +dport_map_port_56=56 +dport_map_port_57=57 +dport_map_port_58=58 +dport_map_port_59=59 +dport_map_port_60=60 +dport_map_port_61=61 +dport_map_port_62=62 +dport_map_port_63=63 +dport_map_port_64=64 +dport_map_port_67=65 +dport_map_port_68=66 +dport_map_port_69=67 +dport_map_port_70=68 +dport_map_port_71=69 +dport_map_port_72=70 +dport_map_port_73=71 +dport_map_port_74=72 +dport_map_port_75=73 +dport_map_port_76=74 +dport_map_port_77=75 +dport_map_port_78=76 +dport_map_port_79=77 +dport_map_port_80=78 +dport_map_port_81=79 +dport_map_port_82=80 +dport_map_port_83=81 +dport_map_port_84=82 +dport_map_port_85=83 +dport_map_port_86=84 +dport_map_port_87=85 +dport_map_port_88=86 +dport_map_port_89=87 +dport_map_port_90=88 +dport_map_port_91=89 +dport_map_port_92=90 +dport_map_port_93=91 +dport_map_port_94=92 +dport_map_port_95=93 +dport_map_port_96=94 +dport_map_port_97=95 +dport_map_port_98=96 +dport_map_port_99=97 +dport_map_port_100=98 +dport_map_port_101=99 +dport_map_port_102=100 +dport_map_port_103=101 +dport_map_port_104=102 +dport_map_port_105=103 +dport_map_port_106=104 +dport_map_port_107=105 +dport_map_port_108=106 +dport_map_port_109=107 +dport_map_port_110=108 +dport_map_port_111=109 +dport_map_port_112=110 +dport_map_port_113=111 +dport_map_port_114=112 +dport_map_port_115=113 +dport_map_port_116=114 +dport_map_port_117=115 +dport_map_port_118=116 +dport_map_port_119=117 +dport_map_port_120=118 +dport_map_port_121=119 +dport_map_port_122=120 +dport_map_port_123=121 +dport_map_port_124=122 +dport_map_port_125=123 +dport_map_port_126=124 +dport_map_port_127=125 +dport_map_port_129=126 +dport_map_port_66=127 +dport_map_port_130=128 + +mmu_init_config="TD3-DELL-lossless" +sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/default_sku b/device/dell/x86_64-dellemc_s5232f_c3538-r0/default_sku new file mode 100644 index 000000000000..f403451c018a --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/default_sku @@ -0,0 +1 @@ +DellEMC-S5232f-C32 t1 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/installer.conf b/device/dell/x86_64-dellemc_s5232f_c3538-r0/installer.conf new file mode 100644 index 000000000000..924e0fb81963 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 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 new file mode 100644 index 000000000000..098d5d4fd131 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/led_proc_init.soc @@ -0,0 +1,9 @@ +# LED microprocessor initialization for Dell S5232 +# +# +#Led0 +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/media_settings.json b/device/dell/x86_64-dellemc_s5232f_c3538-r0/media_settings.json new file mode 100644 index 000000000000..8bdc0e7aa984 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/media_settings.json @@ -0,0 +1,442 @@ +{ + "GLOBAL_MEDIA_SETTINGS": { + "1-32": { + "QSFP28-40GBASE-CR4-1M":{ + "preemphasis": { + "lane0":"0x16440A", + "lane1":"0x16440A", + "lane2":"0x16440A", + "lane3":"0x16440A" + } + }, + "QSFP28-40GBASE-CR4-2M":{ + "preemphasis": { + "lane0":"0x18420A", + "lane1":"0x18420A", + "lane2":"0x18420A", + "lane3":"0x18420A" + } + }, + "QSFP28-40GBASE-CR4-3M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-4M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-5M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-7M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-10M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-1M":{ + "preemphasis": { + "lane0":"0x16440A", + "lane1":"0x16440A", + "lane2":"0x16440A", + "lane3":"0x16440A" + } + }, + "QSFP+-40GBASE-CR4-2M":{ + "preemphasis": { + "lane0":"0x18420A", + "lane1":"0x18420A", + "lane2":"0x18420A", + "lane3":"0x18420A" + } + }, + "QSFP+-40GBASE-CR4-3M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-4M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-5M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-7M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-10M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + } + } + }, + + "PORT_MEDIA_SETTINGS": { + "1": { + "Default": { + "preemphasis": { + "lane0":"0x164509", + "lane1":"0x164509", + "lane2":"0x164509", + "lane3":"0x164509" + } + } + }, + "2": { + "Default": { + "preemphasis": { + "lane0":"0x164509", + "lane1":"0x164509", + "lane2":"0x164509", + "lane3":"0x164509" + } + } + }, + "3": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "4": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "5": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "6": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "7": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "8": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "9": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "10": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "11": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "12": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "13": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "14": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "15": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "16": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "17": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "18": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "19": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "20": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "21": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "22": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "23": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "24": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "25": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "26": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "27": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "28": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "29": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "30": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "31": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "32": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + } + } +} + diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/eeprom.py b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/eeprom.py new file mode 100644 index 000000000000..2374ceb790c5 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/eeprom.py @@ -0,0 +1,30 @@ +############################################################################# +# DellEMC S5232f +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + + +try: + import os.path + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = None + for b in (0, 1): + f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b) + if os.path.exists(f): + self.eeprom_path = f + break + if self.eeprom_path is None: + return + + super(board, self).__init__(self.eeprom_path, 0, '', True) 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 new file mode 100644 index 000000000000..27042e3122b4 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/psuutil.py @@ -0,0 +1,137 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path +import logging +import sys + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + + +S5232F_MAX_PSUS = 2 +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" + + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def isDockerEnv(self): + num_docker = open('/proc/self/cgroup', 'r').read().count(":/docker") + if num_docker > 0: + return True + else: + return False + + # Fetch a BMC register + def get_pmc_register(self, reg_name): + + status = 1 + ipmi_cmd_1 = IPMI_PSU1_DATA + ipmi_cmd_2 = IPMI_PSU1_DATA + dockerenv = self.isDockerEnv() + if dockerenv == True: + 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 ipmitool') + sys.exit(0) + + output = ipmi_sdr_list + + return output + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + S5232F_MAX_PSUS = 2 + return S5232F_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 + """ + # Until psu_status is implemented this is hardcoded temporarily + + 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): + """ + 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 + """ + 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 new file mode 100644 index 000000000000..b56fcc5aafd0 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py @@ -0,0 +1,591 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import struct + 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 sff8472InterfaceId + 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 = 34 + PORTS_IN_BLOCK = 32 + + BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" + + _port_to_eeprom_mapping = {} + + _global_port_pres_dict = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def pci_mem_read(self, mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + reg_val = struct.unpack('I', read_data_stream) + mem_val = str(reg_val)[1:-2] + # print "reg_val read:%x"%reg_val + return mem_val + + def pci_mem_write(self, mm, offset, data): + mm.seek(offset) + # print "data to write:%x"%data + mm.write(struct.pack('I', data)) + + def pci_set_value(self, resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_write(mm, offset, val) + mm.close() + close(fd) + return val + + def pci_get_value(self, resource, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_read(mm, offset) + mm.close() + close(fd) + return val + + def init_global_port_presence(self): + for port_num in range(self.port_start, (self.port_end + 1)): + presence = self.get_presence(port_num) + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(self.port_start, self.port_end + 1): + port_num = x + 1 + self.port_to_eeprom_mapping[x] = eeprom_path.format( + port_num) + port_num = 0 + self.init_global_port_presence() + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4004 + port_offset = 16388 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 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 + + return False + + def get_low_power_mode(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 6th bit for lpmode + mask = (1 << 6) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + def reset(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 4) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + # Sleep 1 second to allow it to settle + time.sleep(1) + + reg_value = reg_value | mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + 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) + 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): + 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_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'] + + 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 new file mode 100644 index 000000000000..e15132a189b1 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/buffers.json.j2 b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..c31728e46543 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/buffers_defaults_t0.j2 @@ -0,0 +1,46 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "32744448", + "type": "ingress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "32744448", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"32744448" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + "{{ port_names_active }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + "{{ port_names_active }}|0-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..c31728e46543 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "32744448", + "type": "ingress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "32744448", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"32744448" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + "{{ port_names_active }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + "{{ port_names_active }}|0-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/custom_led.bin b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/custom_led.bin new file mode 100755 index 000000000000..b3966e520c51 Binary files /dev/null and b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/port_config.ini b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/port_config.ini new file mode 100644 index 000000000000..3827e7acbe28 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 49 tenGigE1/1/1 1 10000 +Ethernet1 50 tenGigE1/1/2 2 10000 +Ethernet2 51 tenGigE1/1/3 3 10000 +Ethernet3 52 tenGigE1/1/4 4 10000 +Ethernet4 57 tenGigE1/2/1 5 10000 +Ethernet5 58 tenGigE1/2/2 6 10000 +Ethernet6 59 tenGigE1/2/3 7 10000 +Ethernet7 60 tenGigE1/2/4 8 10000 +Ethernet8 61 tenGigE1/3/1 9 10000 +Ethernet9 62 tenGigE1/3/2 10 10000 +Ethernet10 63 tenGigE1/3/3 11 10000 +Ethernet11 64 tenGigE1/3/4 12 10000 +Ethernet12 77 tenGigE1/4/1 13 10000 +Ethernet13 78 tenGigE1/4/2 14 10000 +Ethernet14 79 tenGigE1/4/3 15 10000 +Ethernet15 80 tenGigE1/4/4 16 10000 +Ethernet16 85 tenGigE1/5/1 17 10000 +Ethernet17 86 tenGigE1/5/2 18 10000 +Ethernet18 87 tenGigE1/5/3 19 10000 +Ethernet19 88 tenGigE1/5/4 20 10000 +Ethernet20 93 tenGigE1/6/1 21 10000 +Ethernet21 94 tenGigE1/6/2 22 10000 +Ethernet22 95 tenGigE1/6/3 23 10000 +Ethernet23 96 tenGigE1/6/4 24 10000 +Ethernet24 13 tenGigE1/7/1 25 10000 +Ethernet25 14 tenGigE1/7/2 26 10000 +Ethernet26 15 tenGigE1/7/3 27 10000 +Ethernet27 16 tenGigE1/7/4 28 10000 +Ethernet28 21 tenGigE1/8/1 29 10000 +Ethernet29 22 tenGigE1/8/2 30 10000 +Ethernet30 23 tenGigE1/8/3 31 10000 +Ethernet31 24 tenGigE1/8/4 32 10000 +Ethernet32 29 tenGigE1/9/1 33 10000 +Ethernet33 30 tenGigE1/9/2 34 10000 +Ethernet34 31 tenGigE1/9/3 35 10000 +Ethernet35 32 tenGigE1/9/4 36 10000 +Ethernet36 97 tenGigE1/10/1 37 10000 +Ethernet37 98 tenGigE1/10/2 38 10000 +Ethernet38 99 tenGigE1/10/3 39 10000 +Ethernet39 100 tenGigE1/10/4 40 10000 +Ethernet40 105 tenGigE1/11/1 41 10000 +Ethernet41 106 tenGigE1/11/2 42 10000 +Ethernet42 107 tenGigE1/11/3 43 10000 +Ethernet43 108 tenGigE1/11/4 44 10000 +Ethernet44 113 tenGigE1/12/1 45 10000 +Ethernet45 114 tenGigE1/12/2 46 10000 +Ethernet46 115 tenGigE1/12/3 47 10000 +Ethernet47 116 tenGigE1/12/4 48 10000 +Ethernet48 121,122,123,124 hundredGigE1/49 49 100000 +Ethernet49 125,126,127,128 hundredGigE1/50 50 100000 +Ethernet50 69,70,71,72 hundredGigE1/51 51 100000 +Ethernet51 65,66,67,68 hundredGigE1/52 52 100000 +Ethernet52 1,2,3,4 hundredGigE1/53 53 100000 +Ethernet53 33,34,35,36 hundredGigE1/54 54 100000 +Ethernet54 5,6,7,8 hundredGigE1/55 55 100000 +Ethernet55 41,42,43,44 hundredGigE1/56 56 100000 diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/qos.json.j2 b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/qos.json.j2 new file mode 100644 index 000000000000..d2b3d2b0131c --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/qos.json.j2 @@ -0,0 +1,226 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "0", + "4": "0", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "DWRR", + "weight": "50" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/sai.profile b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/sai.profile new file mode 100644 index 000000000000..72f420de5d40 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-s5248f-10g.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/sai_preinit_cmd.soc new file mode 100644 index 000000000000..4d62900f898f --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-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_s5248f_c3538-r0/DellEMC-S5248f-P-10G/td3-s5248f-10g.config.bcm b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/td3-s5248f-10g.config.bcm new file mode 100644 index 000000000000..021f94dc32f7 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/td3-s5248f-10g.config.bcm @@ -0,0 +1,354 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +os=unix +dpp_clock_ratio=2:3 +oversubscribe_mode=1 +core_clock_frequency=1525 +l2xmsg_mode=1 +pbmp_oversubscribe=0x7f878787f878787f9fe1e1e1fe1e1e1fe +pbmp_xport_xe=0x7f878787f878787f9fe1e1e1fe1e1e1fe +ifp_inports_support_enable=1 +port_flex_enable=1 +phy_an_c73=3 +l2xmsg_hostbuf_size=8192 +module_64ports=0 +tdma_intr_enable=1 +ipv6_lpm_128b_enable=1 +stat_if_parity_enable=1 +bcm_tunnel_term_compatible_mode=1 +table_dma_enable=1 +schan_intr_enable=0 +parity_enable=1 +parity_correction=1 +miim_intr_enable=1 +max_vp_lags=0 +tdma_intr_enable=1 +tdma_timeout_usec=5000000 +mmu_lossless=0 +pdma_descriptor_prefetch_enable=1 +pktdma_poll_mode_channel_bitmap=1 + +l3_alpm_enable=2 +l3_alpm_ipv6_128b_bkt_rsvd=1 +l2_mem_entries=40960 +l3_mem_entries=40960 +l3_max_ecmp_mode=1 + +stable_size=0x5500000 + +portmap_1.0=1:100 +portmap_5.0=5:100 +portmap_13.0=13:10 +portmap_14.0=14:10 +portmap_15.0=15:10 +portmap_16.0=16:10 +portmap_21.0=21:10 +portmap_22.0=22:10 +portmap_23.0=23:10 +portmap_24.0=24:10 +portmap_29.0=29:10 +portmap_30.0=30:10 +portmap_31.0=31:10 +portmap_32.0=32:10 +portmap_33.0=33:100 +portmap_41.0=41:100 +portmap_49.0=49:10 +portmap_50.0=50:10 +portmap_51.0=51:10 +portmap_52.0=52:10 +portmap_57.0=57:10 +portmap_58.0=58:10 +portmap_59.0=59:10 +portmap_60.0=60:10 +portmap_61.0=61:10 +portmap_62.0=62:10 +portmap_63.0=63:10 +portmap_64.0=64:10 +portmap_67.0=65:100 +portmap_71.0=69:100 +portmap_79.0=77:10 +portmap_80.0=78:10 +portmap_81.0=79:10 +portmap_82.0=80:10 +portmap_87.0=85:10 +portmap_88.0=86:10 +portmap_89.0=87:10 +portmap_90.0=88:10 +portmap_95.0=93:10 +portmap_96.0=94:10 +portmap_97.0=95:10 +portmap_98.0=96:10 +portmap_99.0=97:10 +portmap_100.0=98:10 +portmap_101.0=99:10 +portmap_102.0=100:10 +portmap_107.0=105:10 +portmap_108.0=106:10 +portmap_109.0=107:10 +portmap_110.0=108:10 +portmap_115.0=113:10 +portmap_116.0=114:10 +portmap_117.0=115:10 +portmap_118.0=116:10 +portmap_123.0=121:100 +portmap_127.0=125:100 +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{1.0}=0x1302 +phy_chain_tx_lane_map_physical{5.0}=0x1032 +phy_chain_rx_lane_map_physical{5.0}=0x1302 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x1032 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_tx_lane_map_physical{29.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x1302 +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x3120 +phy_chain_rx_lane_map_physical{41.0}=0x1032 +phy_chain_tx_lane_map_physical{49.0}=0x0123 +phy_chain_rx_lane_map_physical{49.0}=0x1032 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x1032 +phy_chain_tx_lane_map_physical{61.0}=0x0123 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{65.0}=0x0123 +phy_chain_rx_lane_map_physical{65.0}=0x2031 +phy_chain_tx_lane_map_physical{69.0}=0x3021 +phy_chain_rx_lane_map_physical{69.0}=0x2130 +phy_chain_tx_lane_map_physical{77.0}=0x3210 +phy_chain_rx_lane_map_physical{77.0}=0x2301 +phy_chain_tx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{85.0}=0x2301 +phy_chain_tx_lane_map_physical{93.0}=0x3210 +phy_chain_rx_lane_map_physical{93.0}=0x2301 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_rx_lane_map_physical{97.0}=0x2301 +phy_chain_tx_lane_map_physical{105.0}=0x3210 +phy_chain_rx_lane_map_physical{105.0}=0x2301 +phy_chain_tx_lane_map_physical{113.0}=0x3210 +phy_chain_rx_lane_map_physical{113.0}=0x2301 +phy_chain_tx_lane_map_physical{121.0}=0x0312 +phy_chain_rx_lane_map_physical{121.0}=0x1023 +phy_chain_tx_lane_map_physical{125.0}=0x2301 +phy_chain_rx_lane_map_physical{125.0}=0x3120 +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}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_tx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +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 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x1 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x1 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{77.0}=0x0 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x0 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x0 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{87.0}=0x1 +phy_chain_tx_polarity_flip_physical{88.0}=0x1 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{93.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 +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 +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 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_rx_polarity_flip_physical{113.0}=0x0 +phy_chain_tx_polarity_flip_physical{114.0}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_rx_polarity_flip_physical{125.0}=0x1 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x0 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 +dport_map_enable=1 +dport_map_port_49=1 +dport_map_port_50=2 +dport_map_port_51=3 +dport_map_port_52=4 +dport_map_port_57=5 +dport_map_port_58=6 +dport_map_port_59=7 +dport_map_port_60=8 +dport_map_port_61=9 +dport_map_port_62=10 +dport_map_port_63=11 +dport_map_port_64=12 +dport_map_port_79=13 +dport_map_port_80=14 +dport_map_port_81=15 +dport_map_port_82=16 +dport_map_port_87=17 +dport_map_port_88=18 +dport_map_port_89=19 +dport_map_port_90=20 +dport_map_port_95=21 +dport_map_port_96=22 +dport_map_port_97=23 +dport_map_port_98=24 +dport_map_port_13=25 +dport_map_port_14=26 +dport_map_port_15=27 +dport_map_port_16=28 +dport_map_port_21=29 +dport_map_port_22=30 +dport_map_port_23=31 +dport_map_port_24=32 +dport_map_port_29=33 +dport_map_port_30=34 +dport_map_port_31=35 +dport_map_port_32=36 +dport_map_port_99=37 +dport_map_port_100=38 +dport_map_port_101=39 +dport_map_port_102=40 +dport_map_port_107=41 +dport_map_port_108=42 +dport_map_port_109=43 +dport_map_port_110=44 +dport_map_port_115=45 +dport_map_port_116=46 +dport_map_port_117=47 +dport_map_port_118=48 +dport_map_port_123=49 +dport_map_port_127=50 +dport_map_port_71=51 +dport_map_port_67=52 +dport_map_port_1=53 +dport_map_port_33=54 +dport_map_port_5=55 +dport_map_port_41=56 + +mmu_init_config="TD3-DELL-lossless" +#sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc + diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/buffers.json.j2 b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..c31728e46543 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/buffers_defaults_t0.j2 @@ -0,0 +1,46 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "32744448", + "type": "ingress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "32744448", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"32744448" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + "{{ port_names_active }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + "{{ port_names_active }}|0-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..c31728e46543 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "32744448", + "type": "ingress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "32744448", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"32744448" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + "{{ port_names_active }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + "{{ port_names_active }}|0-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/custom_led.bin b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/custom_led.bin new file mode 100755 index 000000000000..b3966e520c51 Binary files /dev/null and b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/port_config.ini b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/port_config.ini new file mode 100644 index 000000000000..3dc16e2eb9b9 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 49 twentyfiveGigE1/1/1 1 25000 +Ethernet1 50 twentyfiveGigE1/1/2 2 25000 +Ethernet2 51 twentyfiveGigE1/1/3 3 25000 +Ethernet3 52 twentyfiveGigE1/1/4 4 25000 +Ethernet4 57 twentyfiveGigE1/2/1 5 25000 +Ethernet5 58 twentyfiveGigE1/2/2 6 25000 +Ethernet6 59 twentyfiveGigE1/2/3 7 25000 +Ethernet7 60 twentyfiveGigE1/2/4 8 25000 +Ethernet8 61 twentyfiveGigE1/3/1 9 25000 +Ethernet9 62 twentyfiveGigE1/3/2 10 25000 +Ethernet10 63 twentyfiveGigE1/3/3 11 25000 +Ethernet11 64 twentyfiveGigE1/3/4 12 25000 +Ethernet12 77 twentyfiveGigE1/4/1 13 25000 +Ethernet13 78 twentyfiveGigE1/4/2 14 25000 +Ethernet14 79 twentyfiveGigE1/4/3 15 25000 +Ethernet15 80 twentyfiveGigE1/4/4 16 25000 +Ethernet16 85 twentyfiveGigE1/5/1 17 25000 +Ethernet17 86 twentyfiveGigE1/5/2 18 25000 +Ethernet18 87 twentyfiveGigE1/5/3 19 25000 +Ethernet19 88 twentyfiveGigE1/5/4 20 25000 +Ethernet20 93 twentyfiveGigE1/6/1 21 25000 +Ethernet21 94 twentyfiveGigE1/6/2 22 25000 +Ethernet22 95 twentyfiveGigE1/6/3 23 25000 +Ethernet23 96 twentyfiveGigE1/6/4 24 25000 +Ethernet24 13 twentyfiveGigE1/7/1 25 25000 +Ethernet25 14 twentyfiveGigE1/7/2 26 25000 +Ethernet26 15 twentyfiveGigE1/7/3 27 25000 +Ethernet27 16 twentyfiveGigE1/7/4 28 25000 +Ethernet28 21 twentyfiveGigE1/8/1 29 25000 +Ethernet29 22 twentyfiveGigE1/8/2 30 25000 +Ethernet30 23 twentyfiveGigE1/8/3 31 25000 +Ethernet31 24 twentyfiveGigE1/8/4 32 25000 +Ethernet32 29 twentyfiveGigE1/9/1 33 25000 +Ethernet33 30 twentyfiveGigE1/9/2 34 25000 +Ethernet34 31 twentyfiveGigE1/9/3 35 25000 +Ethernet35 32 twentyfiveGigE1/9/4 36 25000 +Ethernet36 97 twentyfiveGigE1/10/1 37 25000 +Ethernet37 98 twentyfiveGigE1/10/2 38 25000 +Ethernet38 99 twentyfiveGigE1/10/3 39 25000 +Ethernet39 100 twentyfiveGigE1/10/4 40 25000 +Ethernet40 105 twentyfiveGigE1/11/1 41 25000 +Ethernet41 106 twentyfiveGigE1/11/2 42 25000 +Ethernet42 107 twentyfiveGigE1/11/3 43 25000 +Ethernet43 108 twentyfiveGigE1/11/4 44 25000 +Ethernet44 113 twentyfiveGigE1/12/1 45 25000 +Ethernet45 114 twentyfiveGigE1/12/2 46 25000 +Ethernet46 115 twentyfiveGigE1/12/3 47 25000 +Ethernet47 116 twentyfiveGigE1/12/4 48 25000 +Ethernet48 121,122,123,124 hundredGigE1/49 49 100000 +Ethernet49 125,126,127,128 hundredGigE1/50 50 100000 +Ethernet50 69,70,71,72 hundredGigE1/51 51 100000 +Ethernet51 65,66,67,68 hundredGigE1/52 52 100000 +Ethernet52 1,2,3,4 hundredGigE1/53 53 100000 +Ethernet53 33,34,35,36 hundredGigE1/54 54 100000 +Ethernet54 5,6,7,8 hundredGigE1/55 55 100000 +Ethernet55 41,42,43,44 hundredGigE1/56 56 100000 diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/qos.json.j2 b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/qos.json.j2 new file mode 100644 index 000000000000..d2b3d2b0131c --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/qos.json.j2 @@ -0,0 +1,226 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "0", + "4": "0", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "DWRR", + "weight": "50" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/sai.profile b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/sai.profile new file mode 100644 index 000000000000..eb9a3cb196fe --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-s5248f-25g.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/sai_preinit_cmd.soc new file mode 100644 index 000000000000..4d62900f898f --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-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_s5248f_c3538-r0/DellEMC-S5248f-P-25G/td3-s5248f-25g.config.bcm b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/td3-s5248f-25g.config.bcm new file mode 100644 index 000000000000..2630512df0ca --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/td3-s5248f-25g.config.bcm @@ -0,0 +1,356 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +os=unix + +dpp_clock_ratio=2:3 +oversubscribe_mode=1 +core_clock_frequency=1525 +l2xmsg_mode=1 +pbmp_oversubscribe=0x7f878787f878787f9fe1e1e1fe1e1e1fe +pbmp_xport_xe=0x7f878787f878787f9fe1e1e1fe1e1e1fe +ifp_inports_support_enable=1 +port_flex_enable=1 +phy_an_c73=3 +l2xmsg_hostbuf_size=8192 +module_64ports=0 +tdma_intr_enable=1 +ipv6_lpm_128b_enable=1 +stat_if_parity_enable=1 +bcm_tunnel_term_compatible_mode=1 +table_dma_enable=1 +schan_intr_enable=0 +parity_enable=1 +parity_correction=1 +miim_intr_enable=1 +max_vp_lags=0 +tdma_intr_enable=1 +tdma_timeout_usec=5000000 +mmu_lossless=0 +pdma_descriptor_prefetch_enable=1 +pktdma_poll_mode_channel_bitmap=1 + +l3_alpm_enable=2 +l3_alpm_ipv6_128b_bkt_rsvd=1 +l2_mem_entries=40960 +l3_mem_entries=40960 +l3_max_ecmp_mode=1 + + +stable_size=0x5500000 + +portmap_1.0=1:100 +portmap_5.0=5:100 +portmap_13.0=13:25 +portmap_14.0=14:25 +portmap_15.0=15:25 +portmap_16.0=16:25 +portmap_21.0=21:25 +portmap_22.0=22:25 +portmap_23.0=23:25 +portmap_24.0=24:25 +portmap_29.0=29:25 +portmap_30.0=30:25 +portmap_31.0=31:25 +portmap_32.0=32:25 +portmap_33.0=33:100 +portmap_41.0=41:100 +portmap_49.0=49:25 +portmap_50.0=50:25 +portmap_51.0=51:25 +portmap_52.0=52:25 +portmap_57.0=57:25 +portmap_58.0=58:25 +portmap_59.0=59:25 +portmap_60.0=60:25 +portmap_61.0=61:25 +portmap_62.0=62:25 +portmap_63.0=63:25 +portmap_64.0=64:25 +portmap_67.0=65:100 +portmap_71.0=69:100 +portmap_79.0=77:25 +portmap_80.0=78:25 +portmap_81.0=79:25 +portmap_82.0=80:25 +portmap_87.0=85:25 +portmap_88.0=86:25 +portmap_89.0=87:25 +portmap_90.0=88:25 +portmap_95.0=93:25 +portmap_96.0=94:25 +portmap_97.0=95:25 +portmap_98.0=96:25 +portmap_99.0=97:25 +portmap_100.0=98:25 +portmap_101.0=99:25 +portmap_102.0=100:25 +portmap_107.0=105:25 +portmap_108.0=106:25 +portmap_109.0=107:25 +portmap_110.0=108:25 +portmap_115.0=113:25 +portmap_116.0=114:25 +portmap_117.0=115:25 +portmap_118.0=116:25 +portmap_123.0=121:100 +portmap_127.0=125:100 +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{1.0}=0x1302 +phy_chain_tx_lane_map_physical{5.0}=0x1032 +phy_chain_rx_lane_map_physical{5.0}=0x1302 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x1032 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_tx_lane_map_physical{29.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x1302 +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x3120 +phy_chain_rx_lane_map_physical{41.0}=0x1032 +phy_chain_tx_lane_map_physical{49.0}=0x0123 +phy_chain_rx_lane_map_physical{49.0}=0x1032 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x1032 +phy_chain_tx_lane_map_physical{61.0}=0x0123 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{65.0}=0x0123 +phy_chain_rx_lane_map_physical{65.0}=0x2031 +phy_chain_tx_lane_map_physical{69.0}=0x3021 +phy_chain_rx_lane_map_physical{69.0}=0x2130 +phy_chain_tx_lane_map_physical{77.0}=0x3210 +phy_chain_rx_lane_map_physical{77.0}=0x2301 +phy_chain_tx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{85.0}=0x2301 +phy_chain_tx_lane_map_physical{93.0}=0x3210 +phy_chain_rx_lane_map_physical{93.0}=0x2301 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_rx_lane_map_physical{97.0}=0x2301 +phy_chain_tx_lane_map_physical{105.0}=0x3210 +phy_chain_rx_lane_map_physical{105.0}=0x2301 +phy_chain_tx_lane_map_physical{113.0}=0x3210 +phy_chain_rx_lane_map_physical{113.0}=0x2301 +phy_chain_tx_lane_map_physical{121.0}=0x0312 +phy_chain_rx_lane_map_physical{121.0}=0x1023 +phy_chain_tx_lane_map_physical{125.0}=0x2301 +phy_chain_rx_lane_map_physical{125.0}=0x3120 +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}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_tx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +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 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x1 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x1 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{77.0}=0x0 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x0 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x0 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{87.0}=0x1 +phy_chain_tx_polarity_flip_physical{88.0}=0x1 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{93.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 +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 +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 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_rx_polarity_flip_physical{113.0}=0x0 +phy_chain_tx_polarity_flip_physical{114.0}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_rx_polarity_flip_physical{125.0}=0x1 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x0 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 +dport_map_enable=1 +dport_map_port_49=1 +dport_map_port_50=2 +dport_map_port_51=3 +dport_map_port_52=4 +dport_map_port_57=5 +dport_map_port_58=6 +dport_map_port_59=7 +dport_map_port_60=8 +dport_map_port_61=9 +dport_map_port_62=10 +dport_map_port_63=11 +dport_map_port_64=12 +dport_map_port_79=13 +dport_map_port_80=14 +dport_map_port_81=15 +dport_map_port_82=16 +dport_map_port_87=17 +dport_map_port_88=18 +dport_map_port_89=19 +dport_map_port_90=20 +dport_map_port_95=21 +dport_map_port_96=22 +dport_map_port_97=23 +dport_map_port_98=24 +dport_map_port_13=25 +dport_map_port_14=26 +dport_map_port_15=27 +dport_map_port_16=28 +dport_map_port_21=29 +dport_map_port_22=30 +dport_map_port_23=31 +dport_map_port_24=32 +dport_map_port_29=33 +dport_map_port_30=34 +dport_map_port_31=35 +dport_map_port_32=36 +dport_map_port_99=37 +dport_map_port_100=38 +dport_map_port_101=39 +dport_map_port_102=40 +dport_map_port_107=41 +dport_map_port_108=42 +dport_map_port_109=43 +dport_map_port_110=44 +dport_map_port_115=45 +dport_map_port_116=46 +dport_map_port_117=47 +dport_map_port_118=48 +dport_map_port_123=49 +dport_map_port_127=50 +dport_map_port_71=51 +dport_map_port_67=52 +dport_map_port_1=53 +dport_map_port_33=54 +dport_map_port_5=55 +dport_map_port_41=56 + +mmu_init_config="TD3-DELL-lossless" +#sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc + diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/default_sku b/device/dell/x86_64-dellemc_s5248f_c3538-r0/default_sku new file mode 100644 index 000000000000..618471d5629d --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/default_sku @@ -0,0 +1 @@ +DellEMC-S5248f-P-25G t1 \ No newline at end of file diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/installer.conf b/device/dell/x86_64-dellemc_s5248f_c3538-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/led_proc_init.soc b/device/dell/x86_64-dellemc_s5248f_c3538-r0/led_proc_init.soc new file mode 100644 index 000000000000..69072c369a64 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/led_proc_init.soc @@ -0,0 +1,6 @@ +# LED microprocessor initialization for Dell S5232 +# +# +#Led0 +led auto on +led start diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/media_settings.json b/device/dell/x86_64-dellemc_s5248f_c3538-r0/media_settings.json new file mode 100644 index 000000000000..8bdc0e7aa984 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/media_settings.json @@ -0,0 +1,442 @@ +{ + "GLOBAL_MEDIA_SETTINGS": { + "1-32": { + "QSFP28-40GBASE-CR4-1M":{ + "preemphasis": { + "lane0":"0x16440A", + "lane1":"0x16440A", + "lane2":"0x16440A", + "lane3":"0x16440A" + } + }, + "QSFP28-40GBASE-CR4-2M":{ + "preemphasis": { + "lane0":"0x18420A", + "lane1":"0x18420A", + "lane2":"0x18420A", + "lane3":"0x18420A" + } + }, + "QSFP28-40GBASE-CR4-3M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-4M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-5M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-7M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-10M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-1M":{ + "preemphasis": { + "lane0":"0x16440A", + "lane1":"0x16440A", + "lane2":"0x16440A", + "lane3":"0x16440A" + } + }, + "QSFP+-40GBASE-CR4-2M":{ + "preemphasis": { + "lane0":"0x18420A", + "lane1":"0x18420A", + "lane2":"0x18420A", + "lane3":"0x18420A" + } + }, + "QSFP+-40GBASE-CR4-3M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-4M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-5M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-7M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-10M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + } + } + }, + + "PORT_MEDIA_SETTINGS": { + "1": { + "Default": { + "preemphasis": { + "lane0":"0x164509", + "lane1":"0x164509", + "lane2":"0x164509", + "lane3":"0x164509" + } + } + }, + "2": { + "Default": { + "preemphasis": { + "lane0":"0x164509", + "lane1":"0x164509", + "lane2":"0x164509", + "lane3":"0x164509" + } + } + }, + "3": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "4": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "5": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "6": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "7": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "8": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "9": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "10": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "11": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "12": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "13": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "14": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "15": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "16": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "17": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "18": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "19": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "20": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "21": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "22": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "23": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "24": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "25": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "26": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "27": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "28": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "29": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "30": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "31": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "32": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + } + } +} + diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/eeprom.py b/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/eeprom.py new file mode 100644 index 000000000000..dc7eeb330215 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/eeprom.py @@ -0,0 +1,30 @@ +############################################################################# +# DellEMC S5248f +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + + +try: + import os.path + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = None + for b in (0, 1): + f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b) + if os.path.exists(f): + self.eeprom_path = f + break + if self.eeprom_path is None: + return + + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/psuutil.py b/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/psuutil.py new file mode 100644 index 000000000000..9cd186611486 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/psuutil.py @@ -0,0 +1,110 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path +import logging +import sys + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + + +S5248F_MAX_PSUS = 2 +IPMI_PSU_DATA = "docker exec -it pmon ipmitool sdr list" +IPMI_PSU_DATA_DOCKER = "ipmitool sdr list" +PSU_PRESENCE = "PSU{0}_stat" +# Use this for older firmware +# PSU_PRESENCE="PSU{0}_prsnt" +ipmi_sdr_list = "" + + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def isDockerEnv(self): + num_docker = open('/proc/self/cgroup', 'r').read().count(":/docker") + if num_docker > 0: + return True + else: + return False + + # Fetch a BMC register + def get_pmc_register(self, reg_name): + + status = 1 + global ipmi_sdr_list + ipmi_dev_node = "/dev/pmi0" + ipmi_cmd = IPMI_PSU_DATA + dockerenv = self.isDockerEnv() + if dockerenv == True: + ipmi_cmd = IPMI_PSU_DATA_DOCKER + + status, ipmi_sdr_list = commands.getstatusoutput(ipmi_cmd) + + if status: + logging.error('Failed to execute:' + ipmi_sdr_list) + sys.exit(0) + + for item in ipmi_sdr_list.split("\n"): + if reg_name in item: + output = item.strip() + + if not output: + print('\nFailed to fetch: ' + reg_name + ' sensor ') + sys.exit(0) + + output = output.split('|')[1] + + logging.basicConfig(level=logging.DEBUG) + return output + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + S5248F_MAX_PSUS = 2 + return S5248F_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 + """ + # Until psu_status is implemented this is hardcoded temporarily + + status = 1 + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :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 diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py new file mode 100644 index 000000000000..dba21ed11bdb --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py @@ -0,0 +1,638 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# +# For S5248F-ON, hardware version X01 + +try: + import struct + 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 sff8472InterfaceId + from sonic_sfp.sff8472 import sff8472Dom + +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# definitions of the offset and width for values in DOM info eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNL_THRESHOLD_OFFSET = 176 +QSFP_CHANNL_THRESHOLD_WIDTH = 16 +QSFP_CHANNL_MON_MASK_OFFSET = 242 +QSFP_CHANNL_MON_MASK_WIDTH = 4 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 + +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 56 + PORTS_IN_BLOCK = 56 + + BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" + + _port_to_i2c_mapping = { + 1: 2, + 2: 3, + 3: 4, + 4: 5, + 5: 6, + 6: 7, + 7: 8, + 8: 9, + 9: 10, + 10: 11, + 11: 12, + 12: 13, + 13: 14, + 14: 15, + 15: 16, + 16: 17, + 17: 18, + 18: 19, + 19: 20, + 20: 21, + 21: 22, + 22: 23, + 23: 24, + 24: 25, + 25: 26, + 26: 27, + 27: 28, + 28: 29, + 29: 30, + 30: 31, + 31: 32, + 32: 33, + 33: 34, + 34: 35, + 35: 36, + 36: 37, + 37: 38, + 38: 39, + 39: 40, + 40: 41, + 41: 42, + 42: 43, + 43: 44, + 44: 45, + 45: 46, + 46: 47, + 47: 48, + 48: 49, + # DD + QSFP28 + 49: 50, + 50: 50, + 51: 51, + 52: 51, + 53: 52, + 54: 53, + 55: 54, + 56: 55, + } + + _port_to_eeprom_mapping = {} + + _global_port_pres_dict = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(49, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def pci_mem_read(self, mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + reg_val = struct.unpack('I', read_data_stream) + mem_val = str(reg_val)[1:-2] + # print "reg_val read:%x"%reg_val + return mem_val + + def pci_mem_write(self, mm, offset, data): + mm.seek(offset) + # print "data to write:%x"%data + mm.write(struct.pack('I', data)) + + def pci_set_value(self, resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_write(mm, offset, val) + mm.close() + close(fd) + return val + + def pci_get_value(self, resource, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_read(mm, offset) + mm.close() + close(fd) + return val + + def init_global_port_presence(self): + for port_num in range(self.port_start, (self.port_end + 1)): + presence = self.get_presence(port_num) + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(self.port_start, self.port_end + 1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + self.init_global_port_presence() + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4004 + port_offset = 16388 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off bit for presence + mask = (1 << 1) + if (port_num > 48): + mask = (1 << 4) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 6th bit for lpmode + mask = (1 << 6) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + def reset(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 4) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + # Sleep 1 second to allow it to settle + time.sleep(1) + + reg_value = reg_value | mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + while True: + for port_num in range(self.port_start, (self.port_end + 1)): + presence = self.get_presence(port_num) + if(presence and self._global_port_pres_dict[port_num] == '0'): + self._global_port_pres_dict[port_num] = '1' + port_dict[port_num] = '1' + elif(not presence and + self._global_port_pres_dict[port_num] == '1'): + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + + if(len(port_dict) > 0): + return True, port_dict + + time.sleep(0.5) + + def get_transceiver_dom_info_dict(self, port_num): + transceiver_dom_info_dict = {} + + dom_info_dict_keys = ['temperature', 'voltage', 'rx1power', + 'rx2power', 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', 'tx3bias', + 'tx4bias', 'tx1power', 'tx2power', + 'tx3power', 'tx4power', + ] + transceiver_dom_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') + + if port_num in self.qsfp_ports: + offset = 0 + offset_xcvr = 128 + file_path = self._get_port_eeprom_path( + port_num, self.IDENTITY_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = io.open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + return transceiver_dom_info_dict + + # QSFP capability byte parse, through this byte can know whether it support tx_power or not. + # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, + # need to add more code for determining the capability and version compliance + # in SFF-8636 dom capability definitions evolving with the versions. + qsfp_dom_capability_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qspf_dom_capability_data = sfpi_obj.parse_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'] + + 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_s5248f_c3538-r0/pmon_daemon_control.json b/device/dell/x86_64-dellemc_s5248f_c3538-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..94592fa8cebc --- /dev/null +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/buffers.json.j2 b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..c31728e46543 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/buffers_defaults_t0.j2 @@ -0,0 +1,46 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "32744448", + "type": "ingress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "32744448", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"32744448" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + "{{ port_names_active }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + "{{ port_names_active }}|0-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..c31728e46543 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "32744448", + "type": "ingress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "32744448", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"32744448" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + "{{ port_names_active }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + "{{ port_names_active }}|0-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/custom_led.bin b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/custom_led.bin new file mode 100755 index 000000000000..302a41d9789a Binary files /dev/null and b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/port_config.ini b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/port_config.ini new file mode 100644 index 000000000000..f16b3e656a18 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/port_config.ini @@ -0,0 +1,105 @@ +# name lanes alias index speed +Ethernet0 5 tenGigE1/1/1 1 10000 +Ethernet1 6 tenGigE1/1/2 2 10000 +Ethernet2 7 tenGigE1/1/3 3 10000 +Ethernet3 8 tenGigE1/1/4 4 10000 +Ethernet4 13 tenGigE1/2/1 5 10000 +Ethernet5 14 tenGigE1/2/2 6 10000 +Ethernet6 15 tenGigE1/2/3 7 10000 +Ethernet7 16 tenGigE1/2/4 8 10000 +Ethernet8 17 tenGigE1/3/1 9 10000 +Ethernet9 18 tenGigE1/3/2 10 10000 +Ethernet10 19 tenGigE1/3/3 11 10000 +Ethernet11 20 tenGigE1/3/4 12 10000 +Ethernet12 37 tenGigE1/4/1 13 10000 +Ethernet13 38 tenGigE1/4/2 14 10000 +Ethernet14 39 tenGigE1/4/3 15 10000 +Ethernet15 40 tenGigE1/4/4 16 10000 +Ethernet16 45 tenGigE1/5/1 17 10000 +Ethernet17 46 tenGigE1/5/2 18 10000 +Ethernet18 47 tenGigE1/5/3 19 10000 +Ethernet19 48 tenGigE1/5/4 20 10000 +Ethernet20 53 tenGigE1/6/1 21 10000 +Ethernet21 54 tenGigE1/6/2 22 10000 +Ethernet22 55 tenGigE1/6/3 23 10000 +Ethernet23 56 tenGigE1/6/4 24 10000 +Ethernet24 65 tenGigE1/7/1 25 10000 +Ethernet25 66 tenGigE1/7/2 26 10000 +Ethernet26 67 tenGigE1/7/3 27 10000 +Ethernet27 68 tenGigE1/7/4 28 10000 +Ethernet28 73 tenGigE1/8/1 29 10000 +Ethernet29 74 tenGigE1/8/2 30 10000 +Ethernet30 75 tenGigE1/8/3 31 10000 +Ethernet31 76 tenGigE1/8/4 32 10000 +Ethernet32 89 tenGigE1/9/1 33 10000 +Ethernet33 90 tenGigE1/9/2 34 10000 +Ethernet34 91 tenGigE1/9/3 35 10000 +Ethernet35 92 tenGigE1/9/4 36 10000 +Ethernet36 101 tenGigE1/10/1 37 10000 +Ethernet37 102 tenGigE1/10/2 38 10000 +Ethernet38 103 tenGigE1/10/3 39 10000 +Ethernet39 104 tenGigE1/10/4 40 10000 +Ethernet40 109 tenGigE1/11/1 41 10000 +Ethernet41 110 tenGigE1/11/2 42 10000 +Ethernet42 111 tenGigE1/11/3 43 10000 +Ethernet43 112 tenGigE1/11/4 44 10000 +Ethernet44 117 tenGigE1/12/1 45 10000 +Ethernet45 118 tenGigE1/12/2 46 10000 +Ethernet46 119 tenGigE1/12/3 47 10000 +Ethernet47 120 tenGigE1/12/4 48 10000 +Ethernet48 1 tenGigE1/13/1 49 10000 +Ethernet49 2 tenGigE1/13/2 50 10000 +Ethernet50 3 tenGigE1/13/3 51 10000 +Ethernet51 4 tenGigE1/13/4 52 10000 +Ethernet52 9 tenGigE1/14/1 53 10000 +Ethernet53 10 tenGigE1/14/2 54 10000 +Ethernet54 11 tenGigE1/14/3 55 10000 +Ethernet55 12 tenGigE1/14/4 56 10000 +Ethernet56 25 tenGigE1/15/1 57 10000 +Ethernet57 26 tenGigE1/15/2 58 10000 +Ethernet58 27 tenGigE1/15/3 59 10000 +Ethernet59 28 tenGigE1/15/4 60 10000 +Ethernet60 33 tenGigE1/16/1 61 10000 +Ethernet61 34 tenGigE1/16/2 62 10000 +Ethernet62 35 tenGigE1/16/3 63 10000 +Ethernet63 36 tenGigE1/16/4 64 10000 +Ethernet64 41 tenGigE1/17/1 65 10000 +Ethernet65 42 tenGigE1/17/2 66 10000 +Ethernet66 43 tenGigE1/17/3 67 10000 +Ethernet67 44 tenGigE1/17/4 68 10000 +Ethernet68 49 tenGigE1/18/1 69 10000 +Ethernet69 50 tenGigE1/18/2 70 10000 +Ethernet70 51 tenGigE1/18/3 71 10000 +Ethernet71 52 tenGigE1/18/4 72 10000 +Ethernet72 69 tenGigE1/19/1 73 10000 +Ethernet73 70 tenGigE1/19/2 74 10000 +Ethernet74 71 tenGigE1/19/3 75 10000 +Ethernet75 72 tenGigE1/19/4 76 10000 +Ethernet76 77 tenGigE1/20/1 77 10000 +Ethernet77 78 tenGigE1/20/2 78 10000 +Ethernet78 79 tenGigE1/20/3 79 10000 +Ethernet79 80 tenGigE1/20/4 80 10000 +Ethernet80 81 tenGigE1/21/1 81 10000 +Ethernet81 82 tenGigE1/21/2 82 10000 +Ethernet82 83 tenGigE1/21/3 83 10000 +Ethernet83 84 tenGigE1/21/4 84 10000 +Ethernet84 97 tenGigE1/22/1 85 10000 +Ethernet85 98 tenGigE1/22/2 86 10000 +Ethernet86 99 tenGigE1/22/3 87 10000 +Ethernet87 100 tenGigE1/22/4 88 10000 +Ethernet88 105 tenGigE1/23/1 89 10000 +Ethernet89 106 tenGigE1/23/2 90 10000 +Ethernet90 107 tenGigE1/23/3 91 10000 +Ethernet91 108 tenGigE1/23/4 92 10000 +Ethernet92 113 tenGigE1/24/1 93 10000 +Ethernet93 114 tenGigE1/24/2 94 10000 +Ethernet94 115 tenGigE1/24/3 95 10000 +Ethernet95 116 tenGigE1/24/4 96 10000 +Ethernet96 29,30,31,32 hundredGigE1/49 97 100000 +Ethernet97 21,22,23,24 hundredGigE1/50 98 100000 +Ethernet98 125,126,127,128 hundredGigE1/51 99 100000 +Ethernet99 85,86,87,88 hundredGigE1/52 100 100000 +Ethernet100 57,58,59,60 hundredGigE1/53 101 100000 +Ethernet101 61,62,63,64 hundredGigE1/54 102 100000 +Ethernet102 121,122,123,124 hundredGigE1/55 103 100000 +Ethernet103 93,94,95,96 hundredGigE1/56 104 100000 diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/qos.json.j2 b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/qos.json.j2 new file mode 100644 index 000000000000..d2b3d2b0131c --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/qos.json.j2 @@ -0,0 +1,226 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "0", + "4": "0", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "DWRR", + "weight": "50" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/sai.profile b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/sai.profile new file mode 100644 index 000000000000..f12601115339 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-s5296f-10g.config.bcm diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/sai_preinit_cmd.soc new file mode 100644 index 000000000000..4d62900f898f --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-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_s5296f_c3538-r0/DellEMC-S5296f-P-10G/td3-s5296f-10g.config.bcm b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/td3-s5296f-10g.config.bcm new file mode 100644 index 000000000000..ddc14d9363d3 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/td3-s5296f-10g.config.bcm @@ -0,0 +1,596 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +os=unix +portmap_5.0=5:10 +portmap_6.0=6:10 +portmap_7.0=7:10 +portmap_8.0=8:10 +portmap_13.0=13:10 +portmap_14.0=14:10 +portmap_15.0=15:10 +portmap_16.0=16:10 +portmap_17.0=17:10 +portmap_18.0=18:10 +portmap_19.0=19:10 +portmap_20.0=20:10 +portmap_37.0=37:10 +portmap_38.0=38:10 +portmap_39.0=39:10 +portmap_40.0=40:10 +portmap_45.0=45:10 +portmap_46.0=46:10 +portmap_47.0=47:10 +portmap_48.0=48:10 +portmap_53.0=53:10 +portmap_54.0=54:10 +portmap_55.0=55:10 +portmap_56.0=56:10 +portmap_67.0=65:10 +portmap_68.0=66:10 +portmap_69.0=67:10 +portmap_70.0=68:10 +portmap_75.0=73:10 +portmap_76.0=74:10 +portmap_77.0=75:10 +portmap_78.0=76:10 +portmap_91.0=89:10 +portmap_92.0=90:10 +portmap_93.0=91:10 +portmap_94.0=92:10 +portmap_103.0=101:10 +portmap_104.0=102:10 +portmap_105.0=103:10 +portmap_106.0=104:10 +portmap_111.0=109:10 +portmap_112.0=110:10 +portmap_113.0=111:10 +portmap_114.0=112:10 +portmap_119.0=117:10 +portmap_120.0=118:10 +portmap_121.0=119:10 +portmap_122.0=120:10 +portmap_1.0=1:10 +portmap_2.0=2:10 +portmap_3.0=3:10 +portmap_4.0=4:10 +portmap_9.0=9:10 +portmap_10.0=10:10 +portmap_11.0=11:10 +portmap_12.0=12:10 +portmap_25.0=25:10 +portmap_26.0=26:10 +portmap_27.0=27:10 +portmap_28.0=28:10 +portmap_33.0=33:10 +portmap_34.0=34:10 +portmap_35.0=35:10 +portmap_36.0=36:10 +portmap_41.0=41:10 +portmap_42.0=42:10 +portmap_43.0=43:10 +portmap_44.0=44:10 +portmap_49.0=49:10 +portmap_50.0=50:10 +portmap_51.0=51:10 +portmap_52.0=52:10 +portmap_71.0=69:10 +portmap_72.0=70:10 +portmap_73.0=71:10 +portmap_74.0=72:10 +portmap_79.0=77:10 +portmap_80.0=78:10 +portmap_81.0=79:10 +portmap_82.0=80:10 +portmap_83.0=81:10 +portmap_84.0=82:10 +portmap_85.0=83:10 +portmap_86.0=84:10 +portmap_99.0=97:10 +portmap_100.0=98:10 +portmap_101.0=99:10 +portmap_102.0=100:10 +portmap_107.0=105:10 +portmap_108.0=106:10 +portmap_109.0=107:10 +portmap_110.0=108:10 +portmap_115.0=113:10 +portmap_116.0=114:10 +portmap_117.0=115:10 +portmap_118.0=116:10 +portmap_29.0=29:100 +portmap_21.0=21:100 +portmap_127.0=125:100 +portmap_87.0=85:100 +portmap_57.0=57:100 +portmap_61.0=61:100 +portmap_123.0=121:100 +portmap_95.0=93:100 +phy_chain_tx_lane_map_physical{5.0}=0x0123 +phy_chain_rx_lane_map_physical{5.0}=0x0123 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x0123 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x0123 +phy_chain_tx_lane_map_physical{37.0}=0x0123 +phy_chain_rx_lane_map_physical{37.0}=0x0123 +phy_chain_tx_lane_map_physical{45.0}=0x0123 +phy_chain_rx_lane_map_physical{45.0}=0x0123 +phy_chain_tx_lane_map_physical{53.0}=0x0123 +phy_chain_rx_lane_map_physical{53.0}=0x0123 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{73.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_tx_lane_map_physical{89.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x3210 +phy_chain_tx_lane_map_physical{101.0}=0x3210 +phy_chain_rx_lane_map_physical{101.0}=0x3210 +phy_chain_tx_lane_map_physical{109.0}=0x3210 +phy_chain_rx_lane_map_physical{109.0}=0x3210 +phy_chain_tx_lane_map_physical{117.0}=0x3210 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_tx_lane_map_physical{1.0}=0x1032 +phy_chain_rx_lane_map_physical{1.0}=0x1032 +phy_chain_tx_lane_map_physical{9.0}=0x1032 +phy_chain_rx_lane_map_physical{9.0}=0x1032 +phy_chain_tx_lane_map_physical{25.0}=0x1032 +phy_chain_rx_lane_map_physical{25.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x1032 +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x1032 +phy_chain_rx_lane_map_physical{41.0}=0x1032 +phy_chain_tx_lane_map_physical{49.0}=0x2031 +phy_chain_rx_lane_map_physical{49.0}=0x2031 +phy_chain_tx_lane_map_physical{69.0}=0x2301 +phy_chain_rx_lane_map_physical{69.0}=0x2301 +phy_chain_tx_lane_map_physical{77.0}=0x1302 +phy_chain_rx_lane_map_physical{77.0}=0x1302 +phy_chain_tx_lane_map_physical{81.0}=0x2301 +phy_chain_rx_lane_map_physical{81.0}=0x2301 +phy_chain_tx_lane_map_physical{97.0}=0x2301 +phy_chain_rx_lane_map_physical{97.0}=0x2301 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_rx_lane_map_physical{105.0}=0x2301 +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{113.0}=0x2301 +phy_chain_tx_lane_map_physical{29.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x3201 +phy_chain_tx_lane_map_physical{21.0}=0x3021 +phy_chain_rx_lane_map_physical{21.0}=0x0312 +phy_chain_tx_lane_map_physical{125.0}=0x3210 +phy_chain_rx_lane_map_physical{125.0}=0x0132 +phy_chain_tx_lane_map_physical{85.0}=0x0312 +phy_chain_rx_lane_map_physical{85.0}=0x3021 +phy_chain_tx_lane_map_physical{57.0}=0x3021 +phy_chain_rx_lane_map_physical{57.0}=0x0312 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x1230 +phy_chain_tx_lane_map_physical{121.0}=0x0123 +phy_chain_rx_lane_map_physical{121.0}=0x2310 +phy_chain_tx_lane_map_physical{93.0}=0x0123 +phy_chain_rx_lane_map_physical{93.0}=0x2301 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +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}=0x1 +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 +phy_chain_tx_polarity_flip_physical{13.0}=0x1 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_tx_polarity_flip_physical{18.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 +phy_chain_rx_polarity_flip_physical{40.0}=0x1 +phy_chain_tx_polarity_flip_physical{45.0}=0x1 +phy_chain_rx_polarity_flip_physical{45.0}=0x1 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{46.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 +phy_chain_tx_polarity_flip_physical{53.0}=0x1 +phy_chain_rx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +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 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x1 +phy_chain_rx_polarity_flip_physical{66.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{68.0}=0x1 +phy_chain_tx_polarity_flip_physical{73.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{75.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x0 +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 +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}=0x1 +phy_chain_rx_polarity_flip_physical{102.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{112.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{118.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{120.0}=0x1 +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}=0x1 +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 +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}=0x1 +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 +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}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{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}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x1 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{82.0}=0x1 +phy_chain_tx_polarity_flip_physical{83.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x1 +phy_chain_rx_polarity_flip_physical{84.0}=0x1 +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x1 +phy_chain_rx_polarity_flip_physical{98.0}=0x1 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_tx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x1 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 +phy_chain_rx_polarity_flip_physical{108.0}=0x0 +phy_chain_tx_polarity_flip_physical{113.0}=0x0 +phy_chain_rx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x1 +phy_chain_rx_polarity_flip_physical{114.0}=0x0 +phy_chain_tx_polarity_flip_physical{115.0}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_tx_polarity_flip_physical{116.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +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 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 +phy_chain_tx_polarity_flip_physical{125.0}=0x1 +phy_chain_rx_polarity_flip_physical{125.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x1 +phy_chain_tx_polarity_flip_physical{85.0}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x0 +phy_chain_tx_polarity_flip_physical{86.0}=0x0 +phy_chain_rx_polarity_flip_physical{86.0}=0x0 +phy_chain_tx_polarity_flip_physical{87.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x1 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_tx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 +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}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x1 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 +phy_chain_tx_polarity_flip_physical{93.0}=0x0 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x0 +phy_chain_rx_polarity_flip_physical{94.0}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x1 +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 +dport_map_enable=1 +dport_map_port_5=1 +dport_map_port_6=2 +dport_map_port_7=3 +dport_map_port_8=4 +dport_map_port_13=5 +dport_map_port_14=6 +dport_map_port_15=7 +dport_map_port_16=8 +dport_map_port_17=9 +dport_map_port_18=10 +dport_map_port_19=11 +dport_map_port_20=12 +dport_map_port_37=13 +dport_map_port_38=14 +dport_map_port_39=15 +dport_map_port_40=16 +dport_map_port_45=17 +dport_map_port_46=18 +dport_map_port_47=19 +dport_map_port_48=20 +dport_map_port_53=21 +dport_map_port_54=22 +dport_map_port_55=23 +dport_map_port_56=24 +dport_map_port_67=25 +dport_map_port_68=26 +dport_map_port_69=27 +dport_map_port_70=28 +dport_map_port_75=29 +dport_map_port_76=30 +dport_map_port_77=31 +dport_map_port_78=32 +dport_map_port_91=33 +dport_map_port_92=34 +dport_map_port_93=35 +dport_map_port_94=36 +dport_map_port_103=37 +dport_map_port_104=38 +dport_map_port_105=39 +dport_map_port_106=40 +dport_map_port_111=41 +dport_map_port_112=42 +dport_map_port_113=43 +dport_map_port_114=44 +dport_map_port_119=45 +dport_map_port_120=46 +dport_map_port_121=47 +dport_map_port_122=48 +dport_map_port_1=49 +dport_map_port_2=50 +dport_map_port_3=51 +dport_map_port_4=52 +dport_map_port_9=53 +dport_map_port_10=54 +dport_map_port_11=55 +dport_map_port_12=56 +dport_map_port_25=57 +dport_map_port_26=58 +dport_map_port_27=59 +dport_map_port_28=60 +dport_map_port_33=61 +dport_map_port_34=62 +dport_map_port_35=63 +dport_map_port_36=64 +dport_map_port_41=65 +dport_map_port_42=66 +dport_map_port_43=67 +dport_map_port_44=68 +dport_map_port_49=69 +dport_map_port_50=70 +dport_map_port_51=71 +dport_map_port_52=72 +dport_map_port_71=73 +dport_map_port_72=74 +dport_map_port_73=75 +dport_map_port_74=76 +dport_map_port_79=77 +dport_map_port_80=78 +dport_map_port_81=79 +dport_map_port_82=80 +dport_map_port_83=81 +dport_map_port_84=82 +dport_map_port_85=83 +dport_map_port_86=84 +dport_map_port_99=85 +dport_map_port_100=86 +dport_map_port_101=87 +dport_map_port_102=88 +dport_map_port_107=89 +dport_map_port_108=90 +dport_map_port_109=91 +dport_map_port_110=92 +dport_map_port_115=93 +dport_map_port_116=94 +dport_map_port_117=95 +dport_map_port_118=96 +dport_map_port_29=97 +dport_map_port_30=98 +dport_map_port_31=99 +dport_map_port_32=100 +dport_map_port_21=101 +dport_map_port_22=102 +dport_map_port_23=103 +dport_map_port_24=104 +dport_map_port_127=105 +dport_map_port_128=106 +dport_map_port_129=107 +dport_map_port_130=108 +dport_map_port_87=109 +dport_map_port_88=110 +dport_map_port_89=111 +dport_map_port_90=112 +dport_map_port_57=113 +dport_map_port_58=114 +dport_map_port_59=115 +dport_map_port_60=116 +dport_map_port_61=117 +dport_map_port_62=118 +dport_map_port_63=119 +dport_map_port_64=120 +dport_map_port_123=121 +dport_map_port_124=122 +dport_map_port_125=123 +dport_map_port_126=124 +dport_map_port_95=125 +dport_map_port_96=126 +dport_map_port_97=127 +dport_map_port_98=128 + +dpp_clock_ratio=2:3 +oversubscribe_mode=1 +core_clock_frequency=1525 +l2xmsg_mode=1 +pbmp_oversubscribe=0x7fffffffffffffff9fffffffffffffffe +pbmp_xport_xe=0x7fffffffffffffff9fffffffffffffffe +ifp_inports_support_enable=1 +port_flex_enable=1 +phy_an_c73=3 +l2xmsg_hostbuf_size=8192 +module_64ports=0 +tdma_intr_enable=1 +ipv6_lpm_128b_enable=1 +stat_if_parity_enable=1 +bcm_tunnel_term_compatible_mode=1 +table_dma_enable=1 +schan_intr_enable=0 +parity_enable=1 +parity_correction=1 +miim_intr_enable=1 +tdma_timeout_usec=5000000 +max_vp_lags=0 +mmu_lossless=0 +pdma_descriptor_prefetch_enable=1 +pktdma_poll_mode_channel_bitmap=1 +l3_max_ecmp_mode.0=1 +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 + +l3_alpm_enable=2 +l3_alpm_ipv6_128b_bkt_rsvd=1 +l2_mem_entries=40960 +l3_mem_entries=40960 +l3_max_ecmp_mode=1 + +stable_size=0x5500000 + +mmu_init_config="TD3-DELL-lossless" +sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/buffers.json.j2 b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..c31728e46543 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/buffers_defaults_t0.j2 @@ -0,0 +1,46 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "32744448", + "type": "ingress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "32744448", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"32744448" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + "{{ port_names_active }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + "{{ port_names_active }}|0-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..c31728e46543 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "32744448", + "type": "ingress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "32744448", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"32744448" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + "{{ port_names_active }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + "{{ port_names_active }}|0-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/custom_led.bin b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/custom_led.bin new file mode 100755 index 000000000000..302a41d9789a Binary files /dev/null and b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/port_config.ini b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/port_config.ini new file mode 100644 index 000000000000..5b2f7ccd20fb --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/port_config.ini @@ -0,0 +1,105 @@ +# name lanes alias index speed +Ethernet0 5 twentyfiveGigE1/1/1 1 25000 +Ethernet1 6 twentyfiveGigE1/1/2 2 25000 +Ethernet2 7 twentyfiveGigE1/1/3 3 25000 +Ethernet3 8 twentyfiveGigE1/1/4 4 25000 +Ethernet4 13 twentyfiveGigE1/2/1 5 25000 +Ethernet5 14 twentyfiveGigE1/2/2 6 25000 +Ethernet6 15 twentyfiveGigE1/2/3 7 25000 +Ethernet7 16 twentyfiveGigE1/2/4 8 25000 +Ethernet8 17 twentyfiveGigE1/3/1 9 25000 +Ethernet9 18 twentyfiveGigE1/3/2 10 25000 +Ethernet10 19 twentyfiveGigE1/3/3 11 25000 +Ethernet11 20 twentyfiveGigE1/3/4 12 25000 +Ethernet12 37 twentyfiveGigE1/4/1 13 25000 +Ethernet13 38 twentyfiveGigE1/4/2 14 25000 +Ethernet14 39 twentyfiveGigE1/4/3 15 25000 +Ethernet15 40 twentyfiveGigE1/4/4 16 25000 +Ethernet16 45 twentyfiveGigE1/5/1 17 25000 +Ethernet17 46 twentyfiveGigE1/5/2 18 25000 +Ethernet18 47 twentyfiveGigE1/5/3 19 25000 +Ethernet19 48 twentyfiveGigE1/5/4 20 25000 +Ethernet20 53 twentyfiveGigE1/6/1 21 25000 +Ethernet21 54 twentyfiveGigE1/6/2 22 25000 +Ethernet22 55 twentyfiveGigE1/6/3 23 25000 +Ethernet23 56 twentyfiveGigE1/6/4 24 25000 +Ethernet24 65 twentyfiveGigE1/7/1 25 25000 +Ethernet25 66 twentyfiveGigE1/7/2 26 25000 +Ethernet26 67 twentyfiveGigE1/7/3 27 25000 +Ethernet27 68 twentyfiveGigE1/7/4 28 25000 +Ethernet28 73 twentyfiveGigE1/8/1 29 25000 +Ethernet29 74 twentyfiveGigE1/8/2 30 25000 +Ethernet30 75 twentyfiveGigE1/8/3 31 25000 +Ethernet31 76 twentyfiveGigE1/8/4 32 25000 +Ethernet32 89 twentyfiveGigE1/9/1 33 25000 +Ethernet33 90 twentyfiveGigE1/9/2 34 25000 +Ethernet34 91 twentyfiveGigE1/9/3 35 25000 +Ethernet35 92 twentyfiveGigE1/9/4 36 25000 +Ethernet36 101 twentyfiveGigE1/10/1 37 25000 +Ethernet37 102 twentyfiveGigE1/10/2 38 25000 +Ethernet38 103 twentyfiveGigE1/10/3 39 25000 +Ethernet39 104 twentyfiveGigE1/10/4 40 25000 +Ethernet40 109 twentyfiveGigE1/11/1 41 25000 +Ethernet41 110 twentyfiveGigE1/11/2 42 25000 +Ethernet42 111 twentyfiveGigE1/11/3 43 25000 +Ethernet43 112 twentyfiveGigE1/11/4 44 25000 +Ethernet44 117 twentyfiveGigE1/12/1 45 25000 +Ethernet45 118 twentyfiveGigE1/12/2 46 25000 +Ethernet46 119 twentyfiveGigE1/12/3 47 25000 +Ethernet47 120 twentyfiveGigE1/12/4 48 25000 +Ethernet48 1 twentyfiveGigE1/13/1 49 25000 +Ethernet49 2 twentyfiveGigE1/13/2 50 25000 +Ethernet50 3 twentyfiveGigE1/13/3 51 25000 +Ethernet51 4 twentyfiveGigE1/13/4 52 25000 +Ethernet52 9 twentyfiveGigE1/14/1 53 25000 +Ethernet53 10 twentyfiveGigE1/14/2 54 25000 +Ethernet54 11 twentyfiveGigE1/14/3 55 25000 +Ethernet55 12 twentyfiveGigE1/14/4 56 25000 +Ethernet56 25 twentyfiveGigE1/15/1 57 25000 +Ethernet57 26 twentyfiveGigE1/15/2 58 25000 +Ethernet58 27 twentyfiveGigE1/15/3 59 25000 +Ethernet59 28 twentyfiveGigE1/15/4 60 25000 +Ethernet60 33 twentyfiveGigE1/16/1 61 25000 +Ethernet61 34 twentyfiveGigE1/16/2 62 25000 +Ethernet62 35 twentyfiveGigE1/16/3 63 25000 +Ethernet63 36 twentyfiveGigE1/16/4 64 25000 +Ethernet64 41 twentyfiveGigE1/17/1 65 25000 +Ethernet65 42 twentyfiveGigE1/17/2 66 25000 +Ethernet66 43 twentyfiveGigE1/17/3 67 25000 +Ethernet67 44 twentyfiveGigE1/17/4 68 25000 +Ethernet68 49 twentyfiveGigE1/18/1 69 25000 +Ethernet69 50 twentyfiveGigE1/18/2 70 25000 +Ethernet70 51 twentyfiveGigE1/18/3 71 25000 +Ethernet71 52 twentyfiveGigE1/18/4 72 25000 +Ethernet72 69 twentyfiveGigE1/19/1 73 25000 +Ethernet73 70 twentyfiveGigE1/19/2 74 25000 +Ethernet74 71 twentyfiveGigE1/19/3 75 25000 +Ethernet75 72 twentyfiveGigE1/19/4 76 25000 +Ethernet76 77 twentyfiveGigE1/20/1 77 25000 +Ethernet77 78 twentyfiveGigE1/20/2 78 25000 +Ethernet78 79 twentyfiveGigE1/20/3 79 25000 +Ethernet79 80 twentyfiveGigE1/20/4 80 25000 +Ethernet80 81 twentyfiveGigE1/21/1 81 25000 +Ethernet81 82 twentyfiveGigE1/21/2 82 25000 +Ethernet82 83 twentyfiveGigE1/21/3 83 25000 +Ethernet83 84 twentyfiveGigE1/21/4 84 25000 +Ethernet84 97 twentyfiveGigE1/22/1 85 25000 +Ethernet85 98 twentyfiveGigE1/22/2 86 25000 +Ethernet86 99 twentyfiveGigE1/22/3 87 25000 +Ethernet87 100 twentyfiveGigE1/22/4 88 25000 +Ethernet88 105 twentyfiveGigE1/23/1 89 25000 +Ethernet89 106 twentyfiveGigE1/23/2 90 25000 +Ethernet90 107 twentyfiveGigE1/23/3 91 25000 +Ethernet91 108 twentyfiveGigE1/23/4 92 25000 +Ethernet92 113 twentyfiveGigE1/24/1 93 25000 +Ethernet93 114 twentyfiveGigE1/24/2 94 25000 +Ethernet94 115 twentyfiveGigE1/24/3 95 25000 +Ethernet95 116 twentyfiveGigE1/24/4 96 25000 +Ethernet96 29,30,31,32 hundredGigE1/49 97 100000 +Ethernet97 21,22,23,24 hundredGigE1/50 98 100000 +Ethernet98 125,126,127,128 hundredGigE1/51 99 100000 +Ethernet99 85,86,87,88 hundredGigE1/52 100 100000 +Ethernet100 57,58,59,60 hundredGigE1/53 101 100000 +Ethernet101 61,62,63,64 hundredGigE1/54 102 100000 +Ethernet102 121,122,123,124 hundredGigE1/55 103 100000 +Ethernet103 93,94,95,96 hundredGigE1/56 104 100000 diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/qos.json.j2 b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/qos.json.j2 new file mode 100644 index 000000000000..d2b3d2b0131c --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/qos.json.j2 @@ -0,0 +1,226 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "0", + "4": "0", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "DWRR", + "weight": "50" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/sai.profile b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/sai.profile new file mode 100644 index 000000000000..793e75fc4e45 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-s5296f-25g.config.bcm diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/sai_preinit_cmd.soc new file mode 100644 index 000000000000..4d62900f898f --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-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_s5296f_c3538-r0/DellEMC-S5296f-P-25G/td3-s5296f-25g.config.bcm b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/td3-s5296f-25g.config.bcm new file mode 100644 index 000000000000..dd0901f5d01f --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/td3-s5296f-25g.config.bcm @@ -0,0 +1,596 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +os=unix +portmap_5.0=5:25 +portmap_6.0=6:25 +portmap_7.0=7:25 +portmap_8.0=8:25 +portmap_13.0=13:25 +portmap_14.0=14:25 +portmap_15.0=15:25 +portmap_16.0=16:25 +portmap_17.0=17:25 +portmap_18.0=18:25 +portmap_19.0=19:25 +portmap_20.0=20:25 +portmap_37.0=37:25 +portmap_38.0=38:25 +portmap_39.0=39:25 +portmap_40.0=40:25 +portmap_45.0=45:25 +portmap_46.0=46:25 +portmap_47.0=47:25 +portmap_48.0=48:25 +portmap_53.0=53:25 +portmap_54.0=54:25 +portmap_55.0=55:25 +portmap_56.0=56:25 +portmap_67.0=65:25 +portmap_68.0=66:25 +portmap_69.0=67:25 +portmap_70.0=68:25 +portmap_75.0=73:25 +portmap_76.0=74:25 +portmap_77.0=75:25 +portmap_78.0=76:25 +portmap_91.0=89:25 +portmap_92.0=90:25 +portmap_93.0=91:25 +portmap_94.0=92:25 +portmap_103.0=101:25 +portmap_104.0=102:25 +portmap_105.0=103:25 +portmap_106.0=104:25 +portmap_111.0=109:25 +portmap_112.0=110:25 +portmap_113.0=111:25 +portmap_114.0=112:25 +portmap_119.0=117:25 +portmap_120.0=118:25 +portmap_121.0=119:25 +portmap_122.0=120:25 +portmap_1.0=1:25 +portmap_2.0=2:25 +portmap_3.0=3:25 +portmap_4.0=4:25 +portmap_9.0=9:25 +portmap_10.0=10:25 +portmap_11.0=11:25 +portmap_12.0=12:25 +portmap_25.0=25:25 +portmap_26.0=26:25 +portmap_27.0=27:25 +portmap_28.0=28:25 +portmap_33.0=33:25 +portmap_34.0=34:25 +portmap_35.0=35:25 +portmap_36.0=36:25 +portmap_41.0=41:25 +portmap_42.0=42:25 +portmap_43.0=43:25 +portmap_44.0=44:25 +portmap_49.0=49:25 +portmap_50.0=50:25 +portmap_51.0=51:25 +portmap_52.0=52:25 +portmap_71.0=69:25 +portmap_72.0=70:25 +portmap_73.0=71:25 +portmap_74.0=72:25 +portmap_79.0=77:25 +portmap_80.0=78:25 +portmap_81.0=79:25 +portmap_82.0=80:25 +portmap_83.0=81:25 +portmap_84.0=82:25 +portmap_85.0=83:25 +portmap_86.0=84:25 +portmap_99.0=97:25 +portmap_100.0=98:25 +portmap_101.0=99:25 +portmap_102.0=100:25 +portmap_107.0=105:25 +portmap_108.0=106:25 +portmap_109.0=107:25 +portmap_110.0=108:25 +portmap_115.0=113:25 +portmap_116.0=114:25 +portmap_117.0=115:25 +portmap_118.0=116:25 +portmap_29.0=29:100 +portmap_21.0=21:100 +portmap_127.0=125:100 +portmap_87.0=85:100 +portmap_57.0=57:100 +portmap_61.0=61:100 +portmap_123.0=121:100 +portmap_95.0=93:100 +phy_chain_tx_lane_map_physical{5.0}=0x0123 +phy_chain_rx_lane_map_physical{5.0}=0x0123 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x0123 +phy_chain_tx_lane_map_physical{17.0}=0x0123 +phy_chain_rx_lane_map_physical{17.0}=0x0123 +phy_chain_tx_lane_map_physical{37.0}=0x0123 +phy_chain_rx_lane_map_physical{37.0}=0x0123 +phy_chain_tx_lane_map_physical{45.0}=0x0123 +phy_chain_rx_lane_map_physical{45.0}=0x0123 +phy_chain_tx_lane_map_physical{53.0}=0x0123 +phy_chain_rx_lane_map_physical{53.0}=0x0123 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{73.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_tx_lane_map_physical{89.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x3210 +phy_chain_tx_lane_map_physical{101.0}=0x3210 +phy_chain_rx_lane_map_physical{101.0}=0x3210 +phy_chain_tx_lane_map_physical{109.0}=0x3210 +phy_chain_rx_lane_map_physical{109.0}=0x3210 +phy_chain_tx_lane_map_physical{117.0}=0x3210 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_tx_lane_map_physical{1.0}=0x1032 +phy_chain_rx_lane_map_physical{1.0}=0x1032 +phy_chain_tx_lane_map_physical{9.0}=0x1032 +phy_chain_rx_lane_map_physical{9.0}=0x1032 +phy_chain_tx_lane_map_physical{25.0}=0x1032 +phy_chain_rx_lane_map_physical{25.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x1032 +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x1032 +phy_chain_rx_lane_map_physical{41.0}=0x1032 +phy_chain_tx_lane_map_physical{49.0}=0x2031 +phy_chain_rx_lane_map_physical{49.0}=0x2031 +phy_chain_tx_lane_map_physical{69.0}=0x2301 +phy_chain_rx_lane_map_physical{69.0}=0x2301 +phy_chain_tx_lane_map_physical{77.0}=0x1302 +phy_chain_rx_lane_map_physical{77.0}=0x1302 +phy_chain_tx_lane_map_physical{81.0}=0x2301 +phy_chain_rx_lane_map_physical{81.0}=0x2301 +phy_chain_tx_lane_map_physical{97.0}=0x2301 +phy_chain_rx_lane_map_physical{97.0}=0x2301 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_rx_lane_map_physical{105.0}=0x2301 +phy_chain_tx_lane_map_physical{113.0}=0x2301 +phy_chain_rx_lane_map_physical{113.0}=0x2301 +phy_chain_tx_lane_map_physical{29.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x3201 +phy_chain_tx_lane_map_physical{21.0}=0x3021 +phy_chain_rx_lane_map_physical{21.0}=0x0312 +phy_chain_tx_lane_map_physical{125.0}=0x3210 +phy_chain_rx_lane_map_physical{125.0}=0x0132 +phy_chain_tx_lane_map_physical{85.0}=0x0312 +phy_chain_rx_lane_map_physical{85.0}=0x3021 +phy_chain_tx_lane_map_physical{57.0}=0x3021 +phy_chain_rx_lane_map_physical{57.0}=0x0312 +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x1230 +phy_chain_tx_lane_map_physical{121.0}=0x0123 +phy_chain_rx_lane_map_physical{121.0}=0x2310 +phy_chain_tx_lane_map_physical{93.0}=0x0123 +phy_chain_rx_lane_map_physical{93.0}=0x2301 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +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}=0x1 +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 +phy_chain_tx_polarity_flip_physical{13.0}=0x1 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_tx_polarity_flip_physical{18.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 +phy_chain_rx_polarity_flip_physical{40.0}=0x1 +phy_chain_tx_polarity_flip_physical{45.0}=0x1 +phy_chain_rx_polarity_flip_physical{45.0}=0x1 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{46.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{48.0}=0x1 +phy_chain_tx_polarity_flip_physical{53.0}=0x1 +phy_chain_rx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +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 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x1 +phy_chain_rx_polarity_flip_physical{66.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{68.0}=0x1 +phy_chain_tx_polarity_flip_physical{73.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{75.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x0 +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 +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}=0x1 +phy_chain_rx_polarity_flip_physical{102.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{112.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{118.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{120.0}=0x1 +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}=0x1 +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 +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}=0x1 +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 +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}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{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}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x1 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{82.0}=0x1 +phy_chain_tx_polarity_flip_physical{83.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x1 +phy_chain_rx_polarity_flip_physical{84.0}=0x1 +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x1 +phy_chain_rx_polarity_flip_physical{98.0}=0x1 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_tx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x1 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 +phy_chain_rx_polarity_flip_physical{108.0}=0x0 +phy_chain_tx_polarity_flip_physical{113.0}=0x0 +phy_chain_rx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x1 +phy_chain_rx_polarity_flip_physical{114.0}=0x0 +phy_chain_tx_polarity_flip_physical{115.0}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_tx_polarity_flip_physical{116.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +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 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 +phy_chain_tx_polarity_flip_physical{125.0}=0x1 +phy_chain_rx_polarity_flip_physical{125.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x1 +phy_chain_tx_polarity_flip_physical{85.0}=0x0 +phy_chain_rx_polarity_flip_physical{85.0}=0x0 +phy_chain_tx_polarity_flip_physical{86.0}=0x0 +phy_chain_rx_polarity_flip_physical{86.0}=0x0 +phy_chain_tx_polarity_flip_physical{87.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x1 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_tx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 +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}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x1 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 +phy_chain_tx_polarity_flip_physical{93.0}=0x0 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x0 +phy_chain_rx_polarity_flip_physical{94.0}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x1 +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 +dport_map_enable=1 +dport_map_port_5=1 +dport_map_port_6=2 +dport_map_port_7=3 +dport_map_port_8=4 +dport_map_port_13=5 +dport_map_port_14=6 +dport_map_port_15=7 +dport_map_port_16=8 +dport_map_port_17=9 +dport_map_port_18=10 +dport_map_port_19=11 +dport_map_port_20=12 +dport_map_port_37=13 +dport_map_port_38=14 +dport_map_port_39=15 +dport_map_port_40=16 +dport_map_port_45=17 +dport_map_port_46=18 +dport_map_port_47=19 +dport_map_port_48=20 +dport_map_port_53=21 +dport_map_port_54=22 +dport_map_port_55=23 +dport_map_port_56=24 +dport_map_port_67=25 +dport_map_port_68=26 +dport_map_port_69=27 +dport_map_port_70=28 +dport_map_port_75=29 +dport_map_port_76=30 +dport_map_port_77=31 +dport_map_port_78=32 +dport_map_port_91=33 +dport_map_port_92=34 +dport_map_port_93=35 +dport_map_port_94=36 +dport_map_port_103=37 +dport_map_port_104=38 +dport_map_port_105=39 +dport_map_port_106=40 +dport_map_port_111=41 +dport_map_port_112=42 +dport_map_port_113=43 +dport_map_port_114=44 +dport_map_port_119=45 +dport_map_port_120=46 +dport_map_port_121=47 +dport_map_port_122=48 +dport_map_port_1=49 +dport_map_port_2=50 +dport_map_port_3=51 +dport_map_port_4=52 +dport_map_port_9=53 +dport_map_port_10=54 +dport_map_port_11=55 +dport_map_port_12=56 +dport_map_port_25=57 +dport_map_port_26=58 +dport_map_port_27=59 +dport_map_port_28=60 +dport_map_port_33=61 +dport_map_port_34=62 +dport_map_port_35=63 +dport_map_port_36=64 +dport_map_port_41=65 +dport_map_port_42=66 +dport_map_port_43=67 +dport_map_port_44=68 +dport_map_port_49=69 +dport_map_port_50=70 +dport_map_port_51=71 +dport_map_port_52=72 +dport_map_port_71=73 +dport_map_port_72=74 +dport_map_port_73=75 +dport_map_port_74=76 +dport_map_port_79=77 +dport_map_port_80=78 +dport_map_port_81=79 +dport_map_port_82=80 +dport_map_port_83=81 +dport_map_port_84=82 +dport_map_port_85=83 +dport_map_port_86=84 +dport_map_port_99=85 +dport_map_port_100=86 +dport_map_port_101=87 +dport_map_port_102=88 +dport_map_port_107=89 +dport_map_port_108=90 +dport_map_port_109=91 +dport_map_port_110=92 +dport_map_port_115=93 +dport_map_port_116=94 +dport_map_port_117=95 +dport_map_port_118=96 +dport_map_port_29=97 +dport_map_port_30=98 +dport_map_port_31=99 +dport_map_port_32=100 +dport_map_port_21=101 +dport_map_port_22=102 +dport_map_port_23=103 +dport_map_port_24=104 +dport_map_port_127=105 +dport_map_port_128=106 +dport_map_port_129=107 +dport_map_port_130=108 +dport_map_port_87=109 +dport_map_port_88=110 +dport_map_port_89=111 +dport_map_port_90=112 +dport_map_port_57=113 +dport_map_port_58=114 +dport_map_port_59=115 +dport_map_port_60=116 +dport_map_port_61=117 +dport_map_port_62=118 +dport_map_port_63=119 +dport_map_port_64=120 +dport_map_port_123=121 +dport_map_port_124=122 +dport_map_port_125=123 +dport_map_port_126=124 +dport_map_port_95=125 +dport_map_port_96=126 +dport_map_port_97=127 +dport_map_port_98=128 + +dpp_clock_ratio=2:3 +oversubscribe_mode=1 +core_clock_frequency=1525 +l2xmsg_mode=1 +pbmp_oversubscribe=0x7fffffffffffffff9fffffffffffffffe +pbmp_xport_xe=0x7fffffffffffffff9fffffffffffffffe +ifp_inports_support_enable=1 +port_flex_enable=1 +phy_an_c73=3 +l2xmsg_hostbuf_size=8192 +module_64ports=0 +tdma_intr_enable=1 +ipv6_lpm_128b_enable=1 +stat_if_parity_enable=1 +bcm_tunnel_term_compatible_mode=1 +table_dma_enable=1 +schan_intr_enable=0 +parity_enable=1 +parity_correction=1 +miim_intr_enable=1 +tdma_timeout_usec=5000000 +max_vp_lags=0 +mmu_lossless=0 +pdma_descriptor_prefetch_enable=1 +pktdma_poll_mode_channel_bitmap=1 +l3_max_ecmp_mode.0=1 +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 + +l3_alpm_enable=2 +l3_alpm_ipv6_128b_bkt_rsvd=1 +l2_mem_entries=40960 +l3_mem_entries=40960 +l3_max_ecmp_mode=1 + +stable_size=0x5500000 + +mmu_init_config="TD3-DELL-lossless" +sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/default_sku b/device/dell/x86_64-dellemc_s5296f_c3538-r0/default_sku new file mode 100644 index 000000000000..622d32812f43 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/default_sku @@ -0,0 +1 @@ +DellEMC-S5296f-P-25G t1 \ No newline at end of file diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/installer.conf b/device/dell/x86_64-dellemc_s5296f_c3538-r0/installer.conf new file mode 100644 index 000000000000..924e0fb81963 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/led_proc_init.soc b/device/dell/x86_64-dellemc_s5296f_c3538-r0/led_proc_init.soc new file mode 100644 index 000000000000..69072c369a64 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/led_proc_init.soc @@ -0,0 +1,6 @@ +# LED microprocessor initialization for Dell S5232 +# +# +#Led0 +led auto on +led start diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/media_settings.json b/device/dell/x86_64-dellemc_s5296f_c3538-r0/media_settings.json new file mode 100644 index 000000000000..8bdc0e7aa984 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/media_settings.json @@ -0,0 +1,442 @@ +{ + "GLOBAL_MEDIA_SETTINGS": { + "1-32": { + "QSFP28-40GBASE-CR4-1M":{ + "preemphasis": { + "lane0":"0x16440A", + "lane1":"0x16440A", + "lane2":"0x16440A", + "lane3":"0x16440A" + } + }, + "QSFP28-40GBASE-CR4-2M":{ + "preemphasis": { + "lane0":"0x18420A", + "lane1":"0x18420A", + "lane2":"0x18420A", + "lane3":"0x18420A" + } + }, + "QSFP28-40GBASE-CR4-3M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-4M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-5M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-7M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP28-40GBASE-CR4-10M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-1M":{ + "preemphasis": { + "lane0":"0x16440A", + "lane1":"0x16440A", + "lane2":"0x16440A", + "lane3":"0x16440A" + } + }, + "QSFP+-40GBASE-CR4-2M":{ + "preemphasis": { + "lane0":"0x18420A", + "lane1":"0x18420A", + "lane2":"0x18420A", + "lane3":"0x18420A" + } + }, + "QSFP+-40GBASE-CR4-3M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-4M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-5M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-7M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + }, + "QSFP+-40GBASE-CR4-10M":{ + "preemphasis": { + "lane0":"0x1A400A", + "lane1":"0x1A400A", + "lane2":"0x1A400A", + "lane3":"0x1A400A" + } + } + } + }, + + "PORT_MEDIA_SETTINGS": { + "1": { + "Default": { + "preemphasis": { + "lane0":"0x164509", + "lane1":"0x164509", + "lane2":"0x164509", + "lane3":"0x164509" + } + } + }, + "2": { + "Default": { + "preemphasis": { + "lane0":"0x164509", + "lane1":"0x164509", + "lane2":"0x164509", + "lane3":"0x164509" + } + } + }, + "3": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "4": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "5": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "6": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "7": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "8": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "9": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "10": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "11": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "12": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "13": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "14": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "15": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "16": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "17": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "18": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "19": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "20": { + "Default": { + "preemphasis": { + "lane0":"0x0E4E08", + "lane1":"0x0E4E08", + "lane2":"0x0E4E08", + "lane3":"0x0E4E08" + } + } + }, + "21": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "22": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "23": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "24": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "25": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "26": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "27": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "28": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "29": { + "Default": { + "preemphasis": { + "lane0":"0x124A08", + "lane1":"0x124A08", + "lane2":"0x124A08", + "lane3":"0x124A08" + } + } + }, + "30": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "31": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + }, + "32": { + "Default": { + "preemphasis": { + "lane0":"0x144808", + "lane1":"0x144808", + "lane2":"0x144808", + "lane3":"0x144808" + } + } + } + } +} + diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/eeprom.py b/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/eeprom.py new file mode 100644 index 000000000000..e4ee56138a77 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/eeprom.py @@ -0,0 +1,30 @@ +############################################################################# +# DellEMC S5296f +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +import os.path + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = None + for b in (0, 1): + f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b) + if os.path.exists(f): + self.eeprom_path = f + break + if self.eeprom_path is None: + return + + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/psuutil.py b/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/psuutil.py new file mode 100644 index 000000000000..8a7b53a626bf --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/psuutil.py @@ -0,0 +1,102 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import logging +import sys + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + + +S5296F_MAX_PSUS = 2 +IPMI_PSU_DATA = "docker exec -it pmon ipmitool sdr list" +IPMI_PSU_DATA_DOCKER = "ipmitool sdr list" +PSU_PRESENCE = "PSU{0}_stat" +# Use this for older firmware +# PSU_PRESENCE="PSU{0}_prsnt" +ipmi_sdr_list = "" + + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def isDockerEnv(self): + num_docker = open('/proc/self/cgroup', 'r').read().count(":/docker") + if num_docker > 0: + return True + else: + return False + + # Fetch a BMC register + def get_pmc_register(self, reg_name): + + global ipmi_sdr_list + ipmi_cmd = IPMI_PSU_DATA + dockerenv = self.isDockerEnv() + if dockerenv == True: + ipmi_cmd = IPMI_PSU_DATA_DOCKER + + status, ipmi_sdr_list = commands.getstatusoutput(ipmi_cmd) + + if status: + logging.error('Failed to execute:' + ipmi_sdr_list) + sys.exit(0) + + for item in ipmi_sdr_list.split("\n"): + if reg_name in item: + output = item.strip() + + if not output: + print('\nFailed to fetch: ' + reg_name + ' sensor ') + sys.exit(0) + + output = output.split('|')[1] + + logging.basicConfig(level=logging.DEBUG) + return output + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + S5296F_MAX_PSUS = 2 + return S5296F_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 + """ + # Until psu_status is implemented this is hardcoded temporarily + + status = 1 + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + cmd_status, psu_status = commands.getstatusoutput( + 'ipmitool raw 0x04 0x2d ' + hex(0x30 + index) + " | awk '{print substr($0,9,1)}'") + return 1 if psu_status == '1' else 0 diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/sfputil.py new file mode 100644 index 000000000000..c270ef47f1e0 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/sfputil.py @@ -0,0 +1,556 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# +# For S5296F-ON, hardware version X01 + +try: + import struct + import time + from sonic_sfp.sfputilbase import SfpUtilBase + from os import * + from mmap import * + import io + from sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_sfp.sff8436 import sff8436Dom + from sonic_sfp.sff8472 import sff8472Dom + +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +# definitions of the offset and width for values in DOM info eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNL_THRESHOLD_OFFSET = 176 +QSFP_CHANNL_THRESHOLD_WIDTH = 16 +QSFP_CHANNL_MON_MASK_OFFSET = 242 +QSFP_CHANNL_MON_MASK_WIDTH = 4 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 + +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 104 + PORTS_IN_BLOCK = 104 + + BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" + + _port_to_eeprom_mapping = {} + + _global_port_pres_dict = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(97, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def pci_mem_read(self, mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + reg_val = struct.unpack('I', read_data_stream) + mem_val = str(reg_val)[1:-2] + # print "reg_val read:%x"%reg_val + return mem_val + + def pci_mem_write(self, mm, offset, data): + mm.seek(offset) + # print "data to write:%x"%data + mm.write(struct.pack('I', data)) + + def pci_set_value(self, resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_write(mm, offset, val) + mm.close() + close(fd) + return val + + def pci_get_value(self, resource, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_read(mm, offset) + mm.close() + close(fd) + return val + + def init_global_port_presence(self): + for port_num in range(self.port_start, (self.port_end + 1)): + presence = self.get_presence(port_num) + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(self.port_start, self.port_end + 1): + self.port_to_eeprom_mapping[x] = eeprom_path.format(x + 1) + self.init_global_port_presence() + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4004 + port_offset = 16388 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off bit for presence + mask = (1 << 1) + if (port_num > 96): + mask = (1 << 4) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + def reset(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + # Sleep 1 second to allow it to settle + time.sleep(1) + + reg_value = reg_value | mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + 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) + 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): + 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_dom_capability(qsfp_dom_capability_raw, 0) + else: + return transceiver_dom_info_dict + + dom_temperature_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + else: + return transceiver_dom_info_dict + + dom_voltage_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + else: + return transceiver_dom_info_dict + + qsfp_dom_rev_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH) + if qsfp_dom_rev_raw is not None: + qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0) + else: + return transceiver_dom_info_dict + + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + # The tx_power monitoring is only available on QSFP which compliant with SFF-8636 + # and claimed that it support tx_power with one indicator bit. + dom_channel_monitor_data = {} + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value'] + if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')): + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + else: + return transceiver_dom_info_dict + + transceiver_dom_info_dict['tx1power'] = 'N/A' + transceiver_dom_info_dict['tx2power'] = 'N/A' + transceiver_dom_info_dict['tx3power'] = 'N/A' + transceiver_dom_info_dict['tx4power'] = 'N/A' + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value'] + transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value'] + transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value'] + transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] + transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] + transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] + transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] + + else: + offset = 256 + file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = io.open(file_path, "rb", 0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8472Dom(None, 1) + if sfpd_obj is None: + return None + dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET), + SFP_TEMPE_WIDTH) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + else: + return transceiver_dom_info_dict + + dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VOLT_OFFSET), + SFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + else: + return transceiver_dom_info_dict + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_MODULE_THRESHOLD_OFFSET), + SFP_MODULE_THRESHOLD_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + else: + return transceiver_dom_info_dict + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value'] + transceiver_dom_info_dict['rx2power'] = 'N/A' + transceiver_dom_info_dict['rx3power'] = 'N/A' + transceiver_dom_info_dict['rx4power'] = 'N/A' + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + transceiver_dom_info_dict['tx2bias'] = 'N/A' + transceiver_dom_info_dict['tx3bias'] = 'N/A' + transceiver_dom_info_dict['tx4bias'] = 'N/A' + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + transceiver_dom_info_dict['tx2power'] = 'N/A' + transceiver_dom_info_dict['tx3power'] = 'N/A' + transceiver_dom_info_dict['tx4power'] = 'N/A' + + return transceiver_dom_info_dict + + def get_transceiver_dom_threshold_info_dict(self, port_num): + transceiver_dom_threshold_info_dict = {} + dom_info_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning' + ] + transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') + + if port_num in self.qsfp_ports: + file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = io.open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + # Dom Threshold data starts from offset 384 + # Revert offset back to 0 once data is retrieved + offset = 384 + dom_module_threshold_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, + (offset + QSFP_MODULE_THRESHOLD_OFFSET), + QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + dom_channel_threshold_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, + (offset + QSFP_CHANNL_THRESHOLD_OFFSET), + QSFP_CHANNL_THRESHOLD_WIDTH) + if dom_channel_threshold_raw is not None: + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + # Threshold Data + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] + + else: + offset = 256 + file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = io.open(file_path, "rb", 0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8472Dom(None, 1) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, + (offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH) + + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + # Threshold Data + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + + return transceiver_dom_threshold_info_dict diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/pmon_daemon_control.json b/device/dell/x86_64-dellemc_s5296f_c3538-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..72ef3c2210a2 --- /dev/null +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/pmon_daemon_control.json @@ -0,0 +1,8 @@ +{ + "skip_sensors": true, + "skip_fancontrol": true, + "skip_ledd": true, + "skip_psud": true, + "skip_syseepromd": true, + "skip_thermalctld": true +} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/buffers.json.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..d538ab1f650f --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/buffers_defaults_t1.j2 @@ -0,0 +1,43 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx*4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "35621248", + "type": "ingress", + "mode": "dynamic", + "xoff": "7847424" + }, + "egress_lossless_pool": { + "size": "43468672", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"43468672" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "mode":"dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/led_proc_init.soc b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/led_proc_init.soc new file mode 100644 index 000000000000..d38282b6508e --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/led_proc_init.soc @@ -0,0 +1,111 @@ +# LED microprocessor initialization for DellEMC-Z9264f + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=32 REMAP_PORT_2=33 REMAP_PORT_1=34 REMAP_PORT_0=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=36 REMAP_PORT_6=37 REMAP_PORT_5=38 REMAP_PORT_4=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=4 REMAP_PORT_10=5 REMAP_PORT_9=6 REMAP_PORT_8=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0 REMAP_PORT_14=1 REMAP_PORT_13=2 REMAP_PORT_12=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=56 REMAP_PORT_18=57 REMAP_PORT_17=58 REMAP_PORT_16=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=60 REMAP_PORT_22=61 REMAP_PORT_21=62 REMAP_PORT_20=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=28 REMAP_PORT_26=29 REMAP_PORT_25=30 REMAP_PORT_24=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 REMAP_PORT_30=25 REMAP_PORT_29=26 REMAP_PORT_28=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=48 REMAP_PORT_34=49 REMAP_PORT_33=50 REMAP_PORT_32=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=52 REMAP_PORT_38=53 REMAP_PORT_37=54 REMAP_PORT_36=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=20 REMAP_PORT_42=21 REMAP_PORT_41=22 REMAP_PORT_40=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=16 REMAP_PORT_46=17 REMAP_PORT_45=18 REMAP_PORT_44=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=40 REMAP_PORT_50=41 REMAP_PORT_49=42 REMAP_PORT_48=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=44 REMAP_PORT_54=45 REMAP_PORT_53=46 REMAP_PORT_52=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12 REMAP_PORT_58=13 REMAP_PORT_57=14 REMAP_PORT_56=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=8 REMAP_PORT_62=9 REMAP_PORT_61=10 REMAP_PORT_60=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=38 REMAP_PORT_8=39 REMAP_PORT_11=36 REMAP_PORT_10=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=32 REMAP_PORT_14=33 REMAP_PORT_13=34 REMAP_PORT_12=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=8 REMAP_PORT_18=9 REMAP_PORT_17=10 REMAP_PORT_16=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=12 REMAP_PORT_22=13 REMAP_PORT_21=14 REMAP_PORT_20=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44 REMAP_PORT_26=45 REMAP_PORT_25=46 REMAP_PORT_24=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=40 REMAP_PORT_30=41 REMAP_PORT_29=42 REMAP_PORT_28=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 REMAP_PORT_34=17 REMAP_PORT_33=18 REMAP_PORT_32=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 REMAP_PORT_38=21 REMAP_PORT_37=22 REMAP_PORT_36=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 REMAP_PORT_42=53 REMAP_PORT_41=54 REMAP_PORT_40=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 REMAP_PORT_46=49 REMAP_PORT_45=50 REMAP_PORT_44=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=24 REMAP_PORT_50=25 REMAP_PORT_49=26 REMAP_PORT_48=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=28 REMAP_PORT_54=29 REMAP_PORT_53=30 REMAP_PORT_52=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=60 REMAP_PORT_58=61 REMAP_PORT_57=62 REMAP_PORT_56=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 REMAP_PORT_62=57 REMAP_PORT_61=58 REMAP_PORT_60=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=60 REMAP_PORT_2=61 REMAP_PORT_1=62 REMAP_PORT_0=63 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=56 REMAP_PORT_6=57 REMAP_PORT_5=58 REMAP_PORT_4=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=24 REMAP_PORT_10=25 REMAP_PORT_9=26 REMAP_PORT_8=27 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=28 REMAP_PORT_14=29 REMAP_PORT_13=30 REMAP_PORT_12=31 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=52 REMAP_PORT_18=53 REMAP_PORT_17=54 REMAP_PORT_16=55 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=48 REMAP_PORT_22=49 REMAP_PORT_21=50 REMAP_PORT_20=51 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16 REMAP_PORT_26=17 REMAP_PORT_25=18 REMAP_PORT_24=19 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=20 REMAP_PORT_30=21 REMAP_PORT_29=22 REMAP_PORT_28=23 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=44 REMAP_PORT_34=45 REMAP_PORT_33=46 REMAP_PORT_32=47 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=40 REMAP_PORT_38=41 REMAP_PORT_37=42 REMAP_PORT_36=43 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=8 REMAP_PORT_42=9 REMAP_PORT_41=10 REMAP_PORT_40=11 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=12 REMAP_PORT_46=13 REMAP_PORT_45=14 REMAP_PORT_44=15 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=36 REMAP_PORT_50=37 REMAP_PORT_49=38 REMAP_PORT_48=39 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=32 REMAP_PORT_54=33 REMAP_PORT_53=34 REMAP_PORT_52=35 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=0 REMAP_PORT_58=1 REMAP_PORT_57=2 REMAP_PORT_56=3 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4 REMAP_PORT_62=5 REMAP_PORT_61=6 REMAP_PORT_60=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 REMAP_PORT_2=29 REMAP_PORT_1=30 REMAP_PORT_0=31 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 REMAP_PORT_6=25 REMAP_PORT_5=26 REMAP_PORT_4=27 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 REMAP_PORT_10=57 REMAP_PORT_9=58 REMAP_PORT_8=59 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 REMAP_PORT_14=61 REMAP_PORT_13=62 REMAP_PORT_12=63 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=4 REMAP_PORT_18=5 REMAP_PORT_17=6 REMAP_PORT_16=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0 REMAP_PORT_22=1 REMAP_PORT_21=2 REMAP_PORT_20=3 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=32 REMAP_PORT_26=33 REMAP_PORT_25=34 REMAP_PORT_24=35 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36 REMAP_PORT_30=37 REMAP_PORT_29=38 REMAP_PORT_28=39 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=12 REMAP_PORT_34=13 REMAP_PORT_33=14 REMAP_PORT_32=15 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=8 REMAP_PORT_38=9 REMAP_PORT_37=10 REMAP_PORT_36=11 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 REMAP_PORT_42=41 REMAP_PORT_41=42 REMAP_PORT_40=43 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 REMAP_PORT_46=45 REMAP_PORT_45=46 REMAP_PORT_44=47 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=20 REMAP_PORT_50=21 REMAP_PORT_49=22 REMAP_PORT_48=23 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=16 REMAP_PORT_54=17 REMAP_PORT_53=18 REMAP_PORT_52=19 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48 REMAP_PORT_58=49 REMAP_PORT_57=50 REMAP_PORT_56=51 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=52 REMAP_PORT_62=53 REMAP_PORT_61=54 REMAP_PORT_60=55 +m CMIC_LEDUP4_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=1 REMAP_PORT_1=0 + +led 0 stop +led 0 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 1 auto on +led 1 start + +led 2 stop +led 2 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 2 auto on +led 2 start + +led 3 stop +led 3 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 3 auto on +led 3 start diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/pg_profile_lookup.ini b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/pg_profile_lookup.ini new file mode 100644 index 000000000000..aedda37a8878 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -3 2288 + 25000 5m 1248 2288 53248 -3 2288 + 40000 5m 1248 2288 66560 -3 2288 + 50000 5m 1248 2288 90272 -3 2288 + 100000 5m 1248 2288 165568 -3 2288 + 10000 40m 1248 2288 37024 -3 2288 + 25000 40m 1248 2288 53248 -3 2288 + 40000 40m 1248 2288 71552 -3 2288 + 50000 40m 1248 2288 96096 -3 2288 + 100000 40m 1248 2288 177632 -3 2288 + 10000 300m 1248 2288 46176 -3 2288 + 25000 300m 1248 2288 79040 -3 2288 + 40000 300m 1248 2288 108160 -3 2288 + 50000 300m 1248 2288 141856 -3 2288 + 100000 300m 1248 2288 268736 -3 2288 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/port_config.ini b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/port_config.ini new file mode 100644 index 000000000000..2bd5931d7866 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 49,50,51,52 hundredGigE1/1 1 100000 +Ethernet4 53,54,55,56 hundredGigE1/2 2 100000 +Ethernet8 65,66,67,68 hundredGigE1/3 3 100000 +Ethernet12 69,70,71,72 hundredGigE1/4 4 100000 +Ethernet16 81,82,83,84 hundredGigE1/5 5 100000 +Ethernet20 85,86,87,88 hundredGigE1/6 6 100000 +Ethernet24 97,98,99,100 hundredGigE1/7 7 100000 +Ethernet28 101,102,103,104 hundredGigE1/8 8 100000 +Ethernet32 1,2,3,4 hundredGigE1/9 9 100000 +Ethernet36 5,6,7,8 hundredGigE1/10 10 100000 +Ethernet40 17,18,19,20 hundredGigE1/11 11 100000 +Ethernet44 21,22,23,24 hundredGigE1/12 12 100000 +Ethernet48 33,34,35,36 hundredGigE1/13 13 100000 +Ethernet52 37,38,39,40 hundredGigE1/14 14 100000 +Ethernet56 113,114,115,116 hundredGigE1/15 15 100000 +Ethernet60 117,118,119,120 hundredGigE1/16 16 100000 +Ethernet64 133,134,135,136 hundredGigE1/17 17 100000 +Ethernet68 129,130,131,132 hundredGigE1/18 18 100000 +Ethernet72 213,214,215,216 hundredGigE1/19 19 100000 +Ethernet76 209,210,211,212 hundredGigE1/20 20 100000 +Ethernet80 229,230,231,232 hundredGigE1/21 21 100000 +Ethernet84 225,226,227,228 hundredGigE1/22 22 100000 +Ethernet88 245,246,247,248 hundredGigE1/23 23 100000 +Ethernet92 241,242,243,244 hundredGigE1/24 24 100000 +Ethernet96 149,150,151,152 hundredGigE1/25 25 100000 +Ethernet100 145,146,147,148 hundredGigE1/26 26 100000 +Ethernet104 165,166,167,168 hundredGigE1/27 27 100000 +Ethernet108 161,162,163,164 hundredGigE1/28 28 100000 +Ethernet112 181,182,183,184 hundredGigE1/29 29 100000 +Ethernet116 177,178,179,180 hundredGigE1/30 30 100000 +Ethernet120 197,198,199,200 hundredGigE1/31 31 100000 +Ethernet124 193,194,195,196 hundredGigE1/32 32 100000 +Ethernet128 61,62,63,64 hundredGigE1/33 33 100000 +Ethernet132 57,58,59,60 hundredGigE1/34 34 100000 +Ethernet136 77,78,79,80 hundredGigE1/35 35 100000 +Ethernet140 73,74,75,76 hundredGigE1/36 36 100000 +Ethernet144 93,94,95,96 hundredGigE1/37 37 100000 +Ethernet148 89,90,91,92 hundredGigE1/38 38 100000 +Ethernet152 109,110,111,112 hundredGigE1/39 39 100000 +Ethernet156 105,106,107,108 hundredGigE1/40 40 100000 +Ethernet160 13,14,15,16 hundredGigE1/41 41 100000 +Ethernet164 9,10,11,12 hundredGigE1/42 42 100000 +Ethernet168 29,30,31,32 hundredGigE1/43 43 100000 +Ethernet172 25,26,27,28 hundredGigE1/44 44 100000 +Ethernet176 45,46,47,48 hundredGigE1/45 45 100000 +Ethernet180 41,42,43,44 hundredGigE1/46 46 100000 +Ethernet184 125,126,127,128 hundredGigE1/47 47 100000 +Ethernet188 121,122,123,124 hundredGigE1/48 48 100000 +Ethernet192 137,138,139,140 hundredGigE1/49 49 100000 +Ethernet196 141,142,143,144 hundredGigE1/50 50 100000 +Ethernet200 217,218,219,220 hundredGigE1/51 51 100000 +Ethernet204 221,222,223,224 hundredGigE1/52 52 100000 +Ethernet208 233,234,235,236 hundredGigE1/53 53 100000 +Ethernet212 237,238,239,240 hundredGigE1/54 54 100000 +Ethernet216 249,250,251,252 hundredGigE1/55 55 100000 +Ethernet220 253,254,255,256 hundredGigE1/56 56 100000 +Ethernet224 153,154,155,156 hundredGigE1/57 57 100000 +Ethernet228 157,158,159,160 hundredGigE1/58 58 100000 +Ethernet232 169,170,171,172 hundredGigE1/59 59 100000 +Ethernet236 173,174,175,176 hundredGigE1/60 60 100000 +Ethernet240 185,186,187,188 hundredGigE1/61 61 100000 +Ethernet244 189,190,191,192 hundredGigE1/62 62 100000 +Ethernet248 201,202,203,204 hundredGigE1/63 63 100000 +Ethernet252 205,206,207,208 hundredGigE1/64 64 100000 +Ethernet256 257 tenGigE1/65 65 10000 +Ethernet257 259 tenGigE1/66 66 10000 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/qos.json.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/sai.profile b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/sai.profile new file mode 100644 index 000000000000..c6e99b771db6 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-z9264f-64x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/th2-z9264f-64x100G.config.bcm b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/th2-z9264f-64x100G.config.bcm new file mode 100644 index 000000000000..2cc2d055f48d --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C64/th2-z9264f-64x100G.config.bcm @@ -0,0 +1,1006 @@ +#TH2 Z9264F 64x100G +os=unix +core_clock_frequency=1700 +dpp_clock_ratio=2:3 +pbmp_xport_xe=0x3FFFD0000FFFF40003FFFC0001FFFE +oversubscribe_mode=1 +fpem_mem_entries=65536 +l2xmsg_mode=1 + +l3_alpm_enable=2 +bcm_num_cos=10 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 + +parity_correction=1 +parity_enable=1 + +dport_map_enable=1 + +dport_map_enable=1 +dport_map_port_13=1 +dport_map_port_14=2 +dport_map_port_34=3 +dport_map_port_35=4 +dport_map_port_38=5 +dport_map_port_39=6 +dport_map_port_42=7 +dport_map_port_43=8 +dport_map_port_1=9 +dport_map_port_2=10 +dport_map_port_5=11 +dport_map_port_6=12 +dport_map_port_9=13 +dport_map_port_10=14 +dport_map_port_46=15 +dport_map_port_47=16 + +dport_map_port_69=17 +dport_map_port_68=18 +dport_map_port_107=19 +dport_map_port_106=20 +dport_map_port_111=21 +dport_map_port_110=22 +dport_map_port_115=23 +dport_map_port_114=24 +dport_map_port_73=25 +dport_map_port_72=26 +dport_map_port_77=27 +dport_map_port_76=28 +dport_map_port_81=29 +dport_map_port_80=30 +dport_map_port_103=31 +dport_map_port_102=32 + +dport_map_port_16=33 +dport_map_port_15=34 +dport_map_port_37=35 +dport_map_port_36=36 +dport_map_port_41=37 +dport_map_port_40=38 +dport_map_port_45=39 +dport_map_port_44=40 +dport_map_port_4=41 +dport_map_port_3=42 +dport_map_port_8=43 +dport_map_port_7=44 +dport_map_port_12=45 +dport_map_port_11=46 +dport_map_port_49=47 +dport_map_port_48=48 + +dport_map_port_70=49 +dport_map_port_71=50 +dport_map_port_108=51 +dport_map_port_109=52 +dport_map_port_112=53 +dport_map_port_113=54 +dport_map_port_116=55 +dport_map_port_117=56 +dport_map_port_74=57 +dport_map_port_75=58 +dport_map_port_78=59 +dport_map_port_79=60 +dport_map_port_82=61 +dport_map_port_83=62 +dport_map_port_104=63 +dport_map_port_105=64 + +# +# Tile-0 FC0~FC15 +# +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 +portmap_9=33:100 +portmap_10=37:100 +portmap_11=41:100 +portmap_12=45:100 +portmap_13=49:100 +portmap_14=53:100 +portmap_15=57:100 +portmap_16=61:100 + +# TX polarity +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 + +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 + +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 + +phy_chain_tx_polarity_flip_physical{13.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}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 + +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +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}=0x1 + +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 + +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +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}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 + +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 + +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}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 + +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 + +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 + +# RX polarity +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 + +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 + +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 + +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 + +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 + +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +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}=0x1 + +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x1 + +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 + +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}=0x1 + +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 + +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 + +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x0 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 + +# TX lane swap +phy_chain_tx_lane_map_physical{1.0}=0x3120 +phy_chain_tx_lane_map_physical{5.0}=0x2130 +phy_chain_tx_lane_map_physical{9.0}=0x0213 +phy_chain_tx_lane_map_physical{13.0}=0x3021 + +phy_chain_tx_lane_map_physical{17.0}=0x3201 +phy_chain_tx_lane_map_physical{21.0}=0x3210 +phy_chain_tx_lane_map_physical{25.0}=0x1023 +phy_chain_tx_lane_map_physical{29.0}=0x0231 + +phy_chain_tx_lane_map_physical{33.0}=0x3210 +phy_chain_tx_lane_map_physical{37.0}=0x3120 +phy_chain_tx_lane_map_physical{41.0}=0x2031 +phy_chain_tx_lane_map_physical{45.0}=0x2130 + +phy_chain_tx_lane_map_physical{49.0}=0x2130 +phy_chain_tx_lane_map_physical{53.0}=0x3012 +phy_chain_tx_lane_map_physical{57.0}=0x2031 +phy_chain_tx_lane_map_physical{61.0}=0x0231 + +# RX lane swap +phy_chain_rx_lane_map_physical{1.0}=0x1320 +phy_chain_rx_lane_map_physical{5.0}=0x0213 +phy_chain_rx_lane_map_physical{9.0}=0x2301 +phy_chain_rx_lane_map_physical{13.0}=0x0321 + +phy_chain_rx_lane_map_physical{17.0}=0x2031 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_rx_lane_map_physical{25.0}=0x2310 +phy_chain_rx_lane_map_physical{29.0}=0x2013 + +phy_chain_rx_lane_map_physical{33.0}=0x2103 +phy_chain_rx_lane_map_physical{37.0}=0x0132 +phy_chain_rx_lane_map_physical{41.0}=0x2031 +phy_chain_rx_lane_map_physical{45.0}=0x1032 + +phy_chain_rx_lane_map_physical{49.0}=0x3201 +phy_chain_rx_lane_map_physical{53.0}=0x0132 +phy_chain_rx_lane_map_physical{57.0}=0x2031 +phy_chain_rx_lane_map_physical{61.0}=0x1032 + +# +# Tile-1 FC16~FC31 +# +portmap_34=65:100 +portmap_35=69:100 +portmap_36=73:100 +portmap_37=77:100 +portmap_38=81:100 +portmap_39=85:100 +portmap_40=89:100 +portmap_41=93:100 +portmap_42=97:100 +portmap_43=101:100 +portmap_44=105:100 +portmap_45=109:100 +portmap_46=113:100 +portmap_47=117:100 +portmap_48=121:100 +portmap_49=125:100 + +#TX polarity +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}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 + +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.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}=0x0 + +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.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}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 + +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 + +phy_chain_tx_polarity_flip_physical{89.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 + +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 + +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +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}=0x1 +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}=0x0 +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{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 + +#RX polarity +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +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{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 + +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 + +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +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}=0x0 + +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 + +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x1 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 + +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +phy_chain_rx_polarity_flip_physical{102.0}=0x0 +phy_chain_rx_polarity_flip_physical{103.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 + +phy_chain_rx_polarity_flip_physical{109.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.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}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 + +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +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}=0x0 + +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}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{65.0}=0x2130 +phy_chain_tx_lane_map_physical{69.0}=0x3012 +phy_chain_tx_lane_map_physical{73.0}=0x2031 +phy_chain_tx_lane_map_physical{77.0}=0x0231 + +phy_chain_tx_lane_map_physical{81.0}=0x2130 +phy_chain_tx_lane_map_physical{85.0}=0x1032 +phy_chain_tx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x0231 + +phy_chain_tx_lane_map_physical{97.0}=0x0123 +phy_chain_tx_lane_map_physical{101.0}=0x1320 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_tx_lane_map_physical{109.0}=0x0213 + +phy_chain_tx_lane_map_physical{113.0}=0x0123 +phy_chain_tx_lane_map_physical{117.0}=0x1023 +phy_chain_tx_lane_map_physical{121.0}=0x2130 +phy_chain_tx_lane_map_physical{125.0}=0x1302 + +# RX lane swap +phy_chain_rx_lane_map_physical{65.0}=0x2103 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x2031 +phy_chain_rx_lane_map_physical{77.0}=0x1032 + +phy_chain_rx_lane_map_physical{81.0}=0x2103 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_rx_lane_map_physical{93.0}=0x1032 + +phy_chain_rx_lane_map_physical{97.0}=0x1023 +phy_chain_rx_lane_map_physical{101.0}=0x3120 +phy_chain_rx_lane_map_physical{105.0}=0x1023 +phy_chain_rx_lane_map_physical{109.0}=0x0231 + +phy_chain_rx_lane_map_physical{113.0}=0x1320 +phy_chain_rx_lane_map_physical{117.0}=0x3102 +phy_chain_rx_lane_map_physical{121.0}=0x0213 +phy_chain_rx_lane_map_physical{125.0}=0x0231 + +# +# Tile-2 FC32~FC47 +# +# port 66 is the first management port +portmap_66=257:10 +# port 67 is the second loopback port +#portmap_67=261:10 +portmap_68=129:100 +portmap_69=133:100 +portmap_70=137:100 +portmap_71=141:100 +portmap_72=145:100 +portmap_73=149:100 +portmap_74=153:100 +portmap_75=157:100 +portmap_76=161:100 +portmap_77=165:100 +portmap_78=169:100 +portmap_79=173:100 +portmap_80=177:100 +portmap_81=181:100 +portmap_82=185:100 +portmap_83=189:100 + +# TX polarity +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 + +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x1 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 + +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x0 + +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x0 +phy_chain_tx_polarity_flip_physical{143.0}=0x1 +phy_chain_tx_polarity_flip_physical{144.0}=0x1 + +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x1 + +phy_chain_tx_polarity_flip_physical{149.0}=0x0 +phy_chain_tx_polarity_flip_physical{150.0}=0x1 +phy_chain_tx_polarity_flip_physical{151.0}=0x1 +phy_chain_tx_polarity_flip_physical{152.0}=0x1 + +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 + +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x1 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 + +phy_chain_tx_polarity_flip_physical{161.0}=0x1 +phy_chain_tx_polarity_flip_physical{162.0}=0x0 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x1 + +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 + +phy_chain_tx_polarity_flip_physical{169.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x0 + +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x0 +phy_chain_tx_polarity_flip_physical{176.0}=0x1 + +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x0 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 + +phy_chain_tx_polarity_flip_physical{181.0}=0x1 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 + +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x0 + +phy_chain_tx_polarity_flip_physical{189.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x1 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 + +# RX polarity +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 + +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 + +phy_chain_rx_polarity_flip_physical{137.0}=0x1 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x1 + +phy_chain_rx_polarity_flip_physical{141.0}=0x0 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x1 + +phy_chain_rx_polarity_flip_physical{145.0}=0x0 +phy_chain_rx_polarity_flip_physical{146.0}=0x0 +phy_chain_rx_polarity_flip_physical{147.0}=0x1 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 + +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x1 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 + +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x0 + +phy_chain_rx_polarity_flip_physical{157.0}=0x1 +phy_chain_rx_polarity_flip_physical{158.0}=0x1 +phy_chain_rx_polarity_flip_physical{159.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 + +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 + +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x1 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x0 + +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x1 + +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x1 +phy_chain_rx_polarity_flip_physical{175.0}=0x0 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 + +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x1 + +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x1 + +phy_chain_rx_polarity_flip_physical{185.0}=0x1 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 + +phy_chain_rx_polarity_flip_physical{189.0}=0x1 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x0 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{129.0}=0x0312 +phy_chain_tx_lane_map_physical{133.0}=0x3120 +phy_chain_tx_lane_map_physical{137.0}=0x1203 +phy_chain_tx_lane_map_physical{141.0}=0x0132 + +phy_chain_tx_lane_map_physical{145.0}=0x0312 +phy_chain_tx_lane_map_physical{149.0}=0x2310 +phy_chain_tx_lane_map_physical{153.0}=0x1032 +phy_chain_tx_lane_map_physical{157.0}=0x3120 + +phy_chain_tx_lane_map_physical{161.0}=0x1023 +phy_chain_tx_lane_map_physical{165.0}=0x1203 +phy_chain_tx_lane_map_physical{169.0}=0x0213 +phy_chain_tx_lane_map_physical{173.0}=0x0123 + +phy_chain_tx_lane_map_physical{177.0}=0x2031 +phy_chain_tx_lane_map_physical{181.0}=0x1203 +phy_chain_tx_lane_map_physical{185.0}=0x0213 +phy_chain_tx_lane_map_physical{189.0}=0x3210 + +# RX lane swap +phy_chain_rx_lane_map_physical{129.0}=0x0321 +phy_chain_rx_lane_map_physical{133.0}=0x0312 +phy_chain_rx_lane_map_physical{137.0}=0x2103 +phy_chain_rx_lane_map_physical{141.0}=0x0231 + +phy_chain_rx_lane_map_physical{145.0}=0x0321 +phy_chain_rx_lane_map_physical{149.0}=0x0312 +phy_chain_rx_lane_map_physical{153.0}=0x3120 +phy_chain_rx_lane_map_physical{157.0}=0x2103 + +phy_chain_rx_lane_map_physical{161.0}=0x1032 +phy_chain_rx_lane_map_physical{165.0}=0x2031 +phy_chain_rx_lane_map_physical{169.0}=0x0132 +phy_chain_rx_lane_map_physical{173.0}=0x2103 + +phy_chain_rx_lane_map_physical{177.0}=0x1032 +phy_chain_rx_lane_map_physical{181.0}=0x1230 +phy_chain_rx_lane_map_physical{185.0}=0x0321 +phy_chain_rx_lane_map_physical{189.0}=0x3201 + +# +# Tile-3 FC48~FC63 +# portmap_0=x:xx // cpu port (not required, but included for illustration purposes) +# +# port 100 is the second management port +portmap_100=259:10 +# port 101 is the third loopback port +#portmap_101=262:10 +portmap_102=193:100 +portmap_103=197:100 +portmap_104=201:100 +portmap_105=205:100 +portmap_106=209:100 +portmap_107=213:100 +portmap_108=217:100 +portmap_109=221:100 +portmap_110=225:100 +portmap_111=229:100 +portmap_112=233:100 +portmap_113=237:100 +portmap_114=241:100 +portmap_115=245:100 +portmap_116=249:100 +portmap_117=253:100 +# port 135 is the fourth loopback port +portmap_135=263:10 + +# TX polarity +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x0 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 + +phy_chain_tx_polarity_flip_physical{197.0}=0x1 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 + +phy_chain_tx_polarity_flip_physical{201.0}=0x0 +phy_chain_tx_polarity_flip_physical{202.0}=0x0 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x0 + +phy_chain_tx_polarity_flip_physical{205.0}=0x1 +phy_chain_tx_polarity_flip_physical{206.0}=0x0 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 + +phy_chain_tx_polarity_flip_physical{209.0}=0x1 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x0 +phy_chain_tx_polarity_flip_physical{212.0}=0x1 + +phy_chain_tx_polarity_flip_physical{213.0}=0x1 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x0 + +phy_chain_tx_polarity_flip_physical{217.0}=0x0 +phy_chain_tx_polarity_flip_physical{218.0}=0x0 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 + +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x1 +phy_chain_tx_polarity_flip_physical{223.0}=0x1 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 + +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x0 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 + +phy_chain_tx_polarity_flip_physical{229.0}=0x1 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x1 + +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x1 + +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 + +phy_chain_tx_polarity_flip_physical{241.0}=0x0 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x0 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 + +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x0 +phy_chain_tx_polarity_flip_physical{248.0}=0x0 + +phy_chain_tx_polarity_flip_physical{249.0}=0x0 +phy_chain_tx_polarity_flip_physical{250.0}=0x0 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 + +phy_chain_tx_polarity_flip_physical{253.0}=0x1 +phy_chain_tx_polarity_flip_physical{254.0}=0x0 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 + +# RX polarity +phy_chain_rx_polarity_flip_physical{193.0}=0x1 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 + +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x1 + +phy_chain_rx_polarity_flip_physical{201.0}=0x1 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x1 + +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x0 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 + +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x1 + +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x1 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 + +phy_chain_rx_polarity_flip_physical{217.0}=0x1 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 + +phy_chain_rx_polarity_flip_physical{221.0}=0x1 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x0 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 + +phy_chain_rx_polarity_flip_physical{225.0}=0x1 +phy_chain_rx_polarity_flip_physical{226.0}=0x1 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x0 + +phy_chain_rx_polarity_flip_physical{229.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 + +phy_chain_rx_polarity_flip_physical{233.0}=0x1 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 + +phy_chain_rx_polarity_flip_physical{237.0}=0x0 +phy_chain_rx_polarity_flip_physical{238.0}=0x1 +phy_chain_rx_polarity_flip_physical{239.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 + +phy_chain_rx_polarity_flip_physical{241.0}=0x0 +phy_chain_rx_polarity_flip_physical{242.0}=0x1 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x1 + +phy_chain_rx_polarity_flip_physical{245.0}=0x1 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x0 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 + +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x0 +phy_chain_rx_polarity_flip_physical{251.0}=0x1 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 + +phy_chain_rx_polarity_flip_physical{253.0}=0x1 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{193.0}=0x2031 +phy_chain_tx_lane_map_physical{197.0}=0x1203 +phy_chain_tx_lane_map_physical{201.0}=0x0213 +phy_chain_tx_lane_map_physical{205.0}=0x3210 + +phy_chain_tx_lane_map_physical{209.0}=0x1023 +phy_chain_tx_lane_map_physical{213.0}=0x1203 +phy_chain_tx_lane_map_physical{217.0}=0x0213 +phy_chain_tx_lane_map_physical{221.0}=0x3102 + +phy_chain_tx_lane_map_physical{225.0}=0x2031 +phy_chain_tx_lane_map_physical{229.0}=0x1023 +phy_chain_tx_lane_map_physical{233.0}=0x1320 +phy_chain_tx_lane_map_physical{237.0}=0x2013 + +phy_chain_tx_lane_map_physical{241.0}=0x1023 +phy_chain_tx_lane_map_physical{245.0}=0x1203 +phy_chain_tx_lane_map_physical{249.0}=0x3120 +phy_chain_tx_lane_map_physical{253.0}=0x3210 + +# RX lane swap +phy_chain_rx_lane_map_physical{193.0}=0x1032 +phy_chain_rx_lane_map_physical{197.0}=0x1230 +phy_chain_rx_lane_map_physical{201.0}=0x0321 +phy_chain_rx_lane_map_physical{205.0}=0x3201 + +phy_chain_rx_lane_map_physical{209.0}=0x3201 +phy_chain_rx_lane_map_physical{213.0}=0x2031 +phy_chain_rx_lane_map_physical{217.0}=0x0321 +phy_chain_rx_lane_map_physical{221.0}=0x3201 + +phy_chain_rx_lane_map_physical{225.0}=0x2103 +phy_chain_rx_lane_map_physical{229.0}=0x2310 +phy_chain_rx_lane_map_physical{233.0}=0x0213 +phy_chain_rx_lane_map_physical{237.0}=0x1032 + +phy_chain_rx_lane_map_physical{241.0}=0x0321 +phy_chain_rx_lane_map_physical{245.0}=0x2301 +phy_chain_rx_lane_map_physical{249.0}=0x2103 +phy_chain_rx_lane_map_physical{253.0}=0x2013 + +physical_ports=64 +logical_ports=136 +uplink_ports=2 +dport_map_port_66=65 +dport_map_port_100=66 + +module_64ports=1 +mmu_init_config="MSFT-TH2-Tier1" diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/buffers.json.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..cbbae78d7596 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/buffers_defaults_t0.j2 @@ -0,0 +1,50 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,12) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(20,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4 + 2)) %}{%- endif %} + {%- endfor %} + {%- for port_idx in range(12,20) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "34369920", + "type": "ingress", + "mode": "dynamic", + "xoff": "9098752" + }, + "egress_lossless_pool": { + "size": "43468672", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"43468672" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "mode":"dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/led_proc_init.soc b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/led_proc_init.soc new file mode 100644 index 000000000000..d38282b6508e --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/led_proc_init.soc @@ -0,0 +1,111 @@ +# LED microprocessor initialization for DellEMC-Z9264f + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=32 REMAP_PORT_2=33 REMAP_PORT_1=34 REMAP_PORT_0=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=36 REMAP_PORT_6=37 REMAP_PORT_5=38 REMAP_PORT_4=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=4 REMAP_PORT_10=5 REMAP_PORT_9=6 REMAP_PORT_8=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0 REMAP_PORT_14=1 REMAP_PORT_13=2 REMAP_PORT_12=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=56 REMAP_PORT_18=57 REMAP_PORT_17=58 REMAP_PORT_16=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=60 REMAP_PORT_22=61 REMAP_PORT_21=62 REMAP_PORT_20=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=28 REMAP_PORT_26=29 REMAP_PORT_25=30 REMAP_PORT_24=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 REMAP_PORT_30=25 REMAP_PORT_29=26 REMAP_PORT_28=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=48 REMAP_PORT_34=49 REMAP_PORT_33=50 REMAP_PORT_32=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=52 REMAP_PORT_38=53 REMAP_PORT_37=54 REMAP_PORT_36=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=20 REMAP_PORT_42=21 REMAP_PORT_41=22 REMAP_PORT_40=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=16 REMAP_PORT_46=17 REMAP_PORT_45=18 REMAP_PORT_44=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=40 REMAP_PORT_50=41 REMAP_PORT_49=42 REMAP_PORT_48=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=44 REMAP_PORT_54=45 REMAP_PORT_53=46 REMAP_PORT_52=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12 REMAP_PORT_58=13 REMAP_PORT_57=14 REMAP_PORT_56=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=8 REMAP_PORT_62=9 REMAP_PORT_61=10 REMAP_PORT_60=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=38 REMAP_PORT_8=39 REMAP_PORT_11=36 REMAP_PORT_10=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=32 REMAP_PORT_14=33 REMAP_PORT_13=34 REMAP_PORT_12=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=8 REMAP_PORT_18=9 REMAP_PORT_17=10 REMAP_PORT_16=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=12 REMAP_PORT_22=13 REMAP_PORT_21=14 REMAP_PORT_20=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44 REMAP_PORT_26=45 REMAP_PORT_25=46 REMAP_PORT_24=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=40 REMAP_PORT_30=41 REMAP_PORT_29=42 REMAP_PORT_28=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 REMAP_PORT_34=17 REMAP_PORT_33=18 REMAP_PORT_32=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 REMAP_PORT_38=21 REMAP_PORT_37=22 REMAP_PORT_36=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 REMAP_PORT_42=53 REMAP_PORT_41=54 REMAP_PORT_40=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 REMAP_PORT_46=49 REMAP_PORT_45=50 REMAP_PORT_44=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=24 REMAP_PORT_50=25 REMAP_PORT_49=26 REMAP_PORT_48=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=28 REMAP_PORT_54=29 REMAP_PORT_53=30 REMAP_PORT_52=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=60 REMAP_PORT_58=61 REMAP_PORT_57=62 REMAP_PORT_56=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 REMAP_PORT_62=57 REMAP_PORT_61=58 REMAP_PORT_60=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=60 REMAP_PORT_2=61 REMAP_PORT_1=62 REMAP_PORT_0=63 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=56 REMAP_PORT_6=57 REMAP_PORT_5=58 REMAP_PORT_4=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=24 REMAP_PORT_10=25 REMAP_PORT_9=26 REMAP_PORT_8=27 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=28 REMAP_PORT_14=29 REMAP_PORT_13=30 REMAP_PORT_12=31 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=52 REMAP_PORT_18=53 REMAP_PORT_17=54 REMAP_PORT_16=55 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=48 REMAP_PORT_22=49 REMAP_PORT_21=50 REMAP_PORT_20=51 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16 REMAP_PORT_26=17 REMAP_PORT_25=18 REMAP_PORT_24=19 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=20 REMAP_PORT_30=21 REMAP_PORT_29=22 REMAP_PORT_28=23 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=44 REMAP_PORT_34=45 REMAP_PORT_33=46 REMAP_PORT_32=47 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=40 REMAP_PORT_38=41 REMAP_PORT_37=42 REMAP_PORT_36=43 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=8 REMAP_PORT_42=9 REMAP_PORT_41=10 REMAP_PORT_40=11 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=12 REMAP_PORT_46=13 REMAP_PORT_45=14 REMAP_PORT_44=15 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=36 REMAP_PORT_50=37 REMAP_PORT_49=38 REMAP_PORT_48=39 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=32 REMAP_PORT_54=33 REMAP_PORT_53=34 REMAP_PORT_52=35 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=0 REMAP_PORT_58=1 REMAP_PORT_57=2 REMAP_PORT_56=3 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4 REMAP_PORT_62=5 REMAP_PORT_61=6 REMAP_PORT_60=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 REMAP_PORT_2=29 REMAP_PORT_1=30 REMAP_PORT_0=31 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 REMAP_PORT_6=25 REMAP_PORT_5=26 REMAP_PORT_4=27 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 REMAP_PORT_10=57 REMAP_PORT_9=58 REMAP_PORT_8=59 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 REMAP_PORT_14=61 REMAP_PORT_13=62 REMAP_PORT_12=63 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=4 REMAP_PORT_18=5 REMAP_PORT_17=6 REMAP_PORT_16=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0 REMAP_PORT_22=1 REMAP_PORT_21=2 REMAP_PORT_20=3 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=32 REMAP_PORT_26=33 REMAP_PORT_25=34 REMAP_PORT_24=35 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36 REMAP_PORT_30=37 REMAP_PORT_29=38 REMAP_PORT_28=39 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=12 REMAP_PORT_34=13 REMAP_PORT_33=14 REMAP_PORT_32=15 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=8 REMAP_PORT_38=9 REMAP_PORT_37=10 REMAP_PORT_36=11 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 REMAP_PORT_42=41 REMAP_PORT_41=42 REMAP_PORT_40=43 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 REMAP_PORT_46=45 REMAP_PORT_45=46 REMAP_PORT_44=47 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=20 REMAP_PORT_50=21 REMAP_PORT_49=22 REMAP_PORT_48=23 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=16 REMAP_PORT_54=17 REMAP_PORT_53=18 REMAP_PORT_52=19 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48 REMAP_PORT_58=49 REMAP_PORT_57=50 REMAP_PORT_56=51 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=52 REMAP_PORT_62=53 REMAP_PORT_61=54 REMAP_PORT_60=55 +m CMIC_LEDUP4_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=1 REMAP_PORT_1=0 + +led 0 stop +led 0 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 1 auto on +led 1 start + +led 2 stop +led 2 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 2 auto on +led 2 start + +led 3 stop +led 3 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 3 auto on +led 3 start diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/pg_profile_lookup.ini b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/pg_profile_lookup.ini new file mode 100644 index 000000000000..aedda37a8878 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -3 2288 + 25000 5m 1248 2288 53248 -3 2288 + 40000 5m 1248 2288 66560 -3 2288 + 50000 5m 1248 2288 90272 -3 2288 + 100000 5m 1248 2288 165568 -3 2288 + 10000 40m 1248 2288 37024 -3 2288 + 25000 40m 1248 2288 53248 -3 2288 + 40000 40m 1248 2288 71552 -3 2288 + 50000 40m 1248 2288 96096 -3 2288 + 100000 40m 1248 2288 177632 -3 2288 + 10000 300m 1248 2288 46176 -3 2288 + 25000 300m 1248 2288 79040 -3 2288 + 40000 300m 1248 2288 108160 -3 2288 + 50000 300m 1248 2288 141856 -3 2288 + 100000 300m 1248 2288 268736 -3 2288 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/port_config.ini b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/port_config.ini new file mode 100644 index 000000000000..27c3906a9a49 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/port_config.ini @@ -0,0 +1,123 @@ +# name lanes alias index speed +Ethernet0 49,50 fiftyGigE1/1/1 1 50000 +Ethernet2 51,52 fiftyGigE1/1/2 1 50000 +Ethernet4 53,54 fiftyGigE1/2/1 2 50000 +Ethernet6 55,56 fiftyGigE1/2/2 2 50000 +Ethernet8 65,66 fiftyGigE1/3/1 3 50000 +Ethernet10 67,68 fiftyGigE1/3/2 3 50000 +Ethernet12 69,70 fiftyGigE1/4/1 4 50000 +Ethernet14 71,72 fiftyGigE1/4/2 4 50000 +Ethernet16 81,82 fiftyGigE1/5/1 5 50000 +Ethernet18 83,84 fiftyGigE1/5/2 5 50000 +Ethernet20 85,86 fiftyGigE1/6/1 6 50000 +Ethernet22 87,88 fiftyGigE1/6/2 6 50000 +Ethernet24 97,98 fiftyGigE1/7/1 7 50000 +Ethernet26 99,100 fiftyGigE1/7/2 7 50000 +Ethernet28 101,102 fiftyGigE1/8/1 8 50000 +Ethernet30 103,104 fiftyGigE1/8/2 8 50000 +Ethernet32 1,2 fiftyGigE1/9/1 9 50000 +Ethernet34 3,4 fiftyGigE1/9/2 9 50000 +Ethernet36 5,6 fiftyGigE1/10/1 10 50000 +Ethernet38 7,8 fiftyGigE1/10/2 10 50000 +Ethernet40 17,18 fiftyGigE1/11/1 11 50000 +Ethernet42 19,20 fiftyGigE1/11/2 11 50000 +Ethernet44 21,22 fiftyGigE1/12/1 12 50000 +Ethernet46 23,24 fiftyGigE1/12/2 12 50000 +Ethernet48 33,34,35,36 hundredGigE1/13 13 100000 +Ethernet52 37,38,39,40 hundredGigE1/14 14 100000 +Ethernet56 113,114,115,116 hundredGigE1/15 15 100000 +Ethernet60 117,118,119,120 hundredGigE1/16 16 100000 +Ethernet64 133,134,135,136 hundredGigE1/17 17 100000 +Ethernet68 129,130,131,132 hundredGigE1/18 18 100000 +Ethernet72 213,214,215,216 hundredGigE1/19 19 100000 +Ethernet76 209,210,211,212 hundredGigE1/20 20 100000 +Ethernet80 229,230 fiftyGigE1/21/1 21 50000 +Ethernet82 231,232 fiftyGigE1/21/2 21 50000 +Ethernet84 225,226 fiftyGigE1/22/1 22 50000 +Ethernet86 227,228 fiftyGigE1/22/2 22 50000 +Ethernet88 245,246 fiftyGigE1/23/1 23 50000 +Ethernet90 247,248 fiftyGigE1/23/2 23 50000 +Ethernet92 241,242 fiftyGigE1/24/1 24 50000 +Ethernet94 243,244 fiftyGigE1/24/2 24 50000 +Ethernet96 149,150 fiftyGigE1/25/1 25 50000 +Ethernet98 151,152 fiftyGigE1/25/2 25 50000 +Ethernet100 145,146 fiftyGigE1/26/1 26 50000 +Ethernet102 147,148 fiftyGigE1/26/2 26 50000 +Ethernet104 165,166 fiftyGigE1/27/1 27 50000 +Ethernet106 167,168 fiftyGigE1/27/2 27 50000 +Ethernet108 161,162 fiftyGigE1/28/1 28 50000 +Ethernet110 163,164 fiftyGigE1/28/2 28 50000 +Ethernet112 181,182 fiftyGigE1/29/1 29 50000 +Ethernet114 183,184 fiftyGigE1/29/2 29 50000 +Ethernet116 177,178 fiftyGigE1/30/1 30 50000 +Ethernet118 179,180 fiftyGigE1/30/2 30 50000 +Ethernet120 197,198 fiftyGigE1/31/1 31 50000 +Ethernet122 199,200 fiftyGigE1/31/2 31 50000 +Ethernet124 193,194 fiftyGigE1/32/1 32 50000 +Ethernet126 195,196 fiftyGigE1/32/2 32 50000 +Ethernet128 61,62 fiftyGigE1/33/1 33 50000 +Ethernet130 63,64 fiftyGigE1/33/2 33 50000 +Ethernet132 57,58 fiftyGigE1/34/1 34 50000 +Ethernet134 59,60 fiftyGigE1/34/2 34 50000 +Ethernet136 77,78 fiftyGigE1/35/1 35 50000 +Ethernet138 79,80 fiftyGigE1/35/2 35 50000 +Ethernet140 73,74 fiftyGigE1/36/1 36 50000 +Ethernet142 75,76 fiftyGigE1/36/2 36 50000 +Ethernet144 93,94 fiftyGigE1/37/1 37 50000 +Ethernet146 95,96 fiftyGigE1/37/2 37 50000 +Ethernet148 89,90 fiftyGigE1/38/1 38 50000 +Ethernet150 91,92 fiftyGigE1/38/2 38 50000 +Ethernet152 109,110 fiftyGigE1/39/1 39 50000 +Ethernet154 111,112 fiftyGigE1/39/2 39 50000 +Ethernet156 105,106 fiftyGigE1/40/1 40 50000 +Ethernet158 107,108 fiftyGigE1/40/2 40 50000 +Ethernet160 13,14 fiftyGigE1/41/1 41 50000 +Ethernet162 15,16 fiftyGigE1/41/2 41 50000 +Ethernet164 9,10 fiftyGigE1/42/1 42 50000 +Ethernet166 11,12 fiftyGigE1/42/2 42 50000 +Ethernet168 29,30 fiftyGigE1/43/1 43 50000 +Ethernet170 31,32 fiftyGigE1/43/2 43 50000 +Ethernet172 25,26 fiftyGigE1/44/1 44 50000 +Ethernet174 27,28 fiftyGigE1/44/2 44 50000 +Ethernet176 45,46 fiftyGigE1/45/1 45 50000 +Ethernet178 47,48 fiftyGigE1/45/2 45 50000 +Ethernet180 41,42 fiftyGigE1/46/1 46 50000 +Ethernet182 43,44 fiftyGigE1/46/2 46 50000 +Ethernet184 125,126 fiftyGigE1/47/1 47 50000 +Ethernet186 127,128 fiftyGigE1/47/2 47 50000 +Ethernet188 121,122 fiftyGigE1/48/1 48 50000 +Ethernet190 123,124 fiftyGigE1/48/2 48 50000 +Ethernet192 137,138 fiftyGigE1/49/1 49 50000 +Ethernet194 139,140 fiftyGigE1/49/2 49 50000 +Ethernet196 141,142 fiftyGigE1/50/1 50 50000 +Ethernet198 143,144 fiftyGigE1/50/2 50 50000 +Ethernet200 217,218 fiftyGigE1/51/1 51 50000 +Ethernet202 219,220 fiftyGigE1/51/2 51 50000 +Ethernet204 221,222 fiftyGigE1/52/1 52 50000 +Ethernet206 223,224 fiftyGigE1/52/2 52 50000 +Ethernet208 233,234 fiftyGigE1/53/1 53 50000 +Ethernet210 235,236 fiftyGigE1/53/2 53 50000 +Ethernet212 237,238 fiftyGigE1/54/1 54 50000 +Ethernet214 239,240 fiftyGigE1/54/2 54 50000 +Ethernet216 249,250 fiftyGigE1/55/1 55 50000 +Ethernet218 251,252 fiftyGigE1/55/2 55 50000 +Ethernet220 253,254 fiftyGigE1/56/1 56 50000 +Ethernet222 255,256 fiftyGigE1/56/2 56 50000 +Ethernet224 153,154 fiftyGigE1/57/1 57 50000 +Ethernet226 155,156 fiftyGigE1/57/2 57 50000 +Ethernet228 157,158 fiftyGigE1/58/1 58 50000 +Ethernet230 159,160 fiftyGigE1/58/2 58 50000 +Ethernet232 169,170 fiftyGigE1/59/1 59 50000 +Ethernet234 171,172 fiftyGigE1/59/2 59 50000 +Ethernet236 173,174 fiftyGigE1/60/1 60 50000 +Ethernet238 175,176 fiftyGigE1/60/2 60 50000 +Ethernet240 185,186 fiftyGigE1/61/1 61 50000 +Ethernet242 187,188 fiftyGigE1/61/2 61 50000 +Ethernet244 189,190 fiftyGigE1/62/1 62 50000 +Ethernet246 191,192 fiftyGigE1/62/2 62 50000 +Ethernet248 201,202 fiftyGigE1/63/1 63 50000 +Ethernet250 203,204 fiftyGigE1/63/2 63 50000 +Ethernet252 205,206 fiftyGigE1/64/1 64 50000 +Ethernet254 207,208 fiftyGigE1/64/2 64 50000 +Ethernet256 257 tenGigE1/65 65 10000 +Ethernet257 259 tenGigE1/66 66 10000 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/qos.json.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/sai.profile b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/sai.profile new file mode 100644 index 000000000000..a6a351387d56 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-z9264f-8x100G-112x50G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/th2-z9264f-8x100G-112x50G.config.bcm b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/th2-z9264f-8x100G-112x50G.config.bcm new file mode 100644 index 000000000000..0c1fabf7c6fe --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-C8D112/th2-z9264f-8x100G-112x50G.config.bcm @@ -0,0 +1,1119 @@ +#TH2 Z9264F 112x50G,8x100G +os=unix +core_clock_frequency=1700 +dpp_clock_ratio=2:3 +pbmp_xport_xe=0xfffffffd3fffffff4fffffffc7ffffffe +oversubscribe_mode=1 +fpem_mem_entries=65536 +l2xmsg_mode=1 + +l3_alpm_enable=2 +bcm_num_cos=10 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 + +parity_correction=1 +parity_enable=1 + +dport_map_enable=1 + +dport_map_port_23=1 +dport_map_port_24=2 +dport_map_port_25=3 +dport_map_port_26=4 +dport_map_port_34=5 +dport_map_port_35=6 +dport_map_port_36=7 +dport_map_port_37=8 +dport_map_port_42=9 +dport_map_port_43=10 +dport_map_port_44=11 +dport_map_port_45=12 +dport_map_port_50=13 +dport_map_port_51=14 +dport_map_port_52=15 +dport_map_port_53=16 +dport_map_port_1=17 +dport_map_port_2=18 +dport_map_port_3=19 +dport_map_port_4=20 +dport_map_port_9=21 +dport_map_port_10=22 +dport_map_port_11=23 +dport_map_port_12=24 + +dport_map_port_17=25 +dport_map_port_18=26 +dport_map_port_58=27 +dport_map_port_59=28 +dport_map_port_69=29 +dport_map_port_68=30 +dport_map_port_111=31 +dport_map_port_110=32 +dport_map_port_118=33 +dport_map_port_119=34 +dport_map_port_116=35 +dport_map_port_117=36 +dport_map_port_126=37 +dport_map_port_127=38 +dport_map_port_124=39 +dport_map_port_125=40 +dport_map_port_76=41 +dport_map_port_77=42 +dport_map_port_74=43 +dport_map_port_75=44 +dport_map_port_84=45 +dport_map_port_85=46 +dport_map_port_82=47 +dport_map_port_83=48 +dport_map_port_92=49 +dport_map_port_93=50 +dport_map_port_90=51 +dport_map_port_91=52 +dport_map_port_104=53 +dport_map_port_105=54 +dport_map_port_102=55 +dport_map_port_103=56 +dport_map_port_29=57 +dport_map_port_30=58 +dport_map_port_27=59 +dport_map_port_28=60 +dport_map_port_40=61 +dport_map_port_41=62 +dport_map_port_38=63 +dport_map_port_39=64 +dport_map_port_48=65 +dport_map_port_49=66 +dport_map_port_46=67 +dport_map_port_47=68 +dport_map_port_56=69 +dport_map_port_57=70 +dport_map_port_54=71 +dport_map_port_55=72 +dport_map_port_7=73 +dport_map_port_8=74 +dport_map_port_5=75 +dport_map_port_6=76 +dport_map_port_15=77 +dport_map_port_16=78 +dport_map_port_13=79 +dport_map_port_14=80 +dport_map_port_21=81 +dport_map_port_22=82 +dport_map_port_19=83 +dport_map_port_20=84 +dport_map_port_62=85 +dport_map_port_63=86 +dport_map_port_60=87 +dport_map_port_61=88 +dport_map_port_70=89 +dport_map_port_71=90 +dport_map_port_72=91 +dport_map_port_73=92 +dport_map_port_112=93 +dport_map_port_113=94 +dport_map_port_114=95 +dport_map_port_115=96 +dport_map_port_120=97 +dport_map_port_121=98 +dport_map_port_122=99 +dport_map_port_123=100 +dport_map_port_128=101 +dport_map_port_129=102 +dport_map_port_130=103 +dport_map_port_131=104 +dport_map_port_78=105 +dport_map_port_79=106 +dport_map_port_80=107 +dport_map_port_81=108 +dport_map_port_86=109 +dport_map_port_87=110 +dport_map_port_88=111 +dport_map_port_89=112 +dport_map_port_94=113 +dport_map_port_95=114 +dport_map_port_96=115 +dport_map_port_97=116 +dport_map_port_106=117 +dport_map_port_107=118 +dport_map_port_108=119 +dport_map_port_109=120 + +# +# Tile-0 FC0~FC15 +# +portmap_1=1:50:2 +portmap_2=3:50:2 +portmap_3=5:50:2 +portmap_4=7:50:2 +portmap_5=9:50:2 +portmap_6=11:50:2 +portmap_7=13:50:2 +portmap_8=15:50:2 +portmap_9=17:50:2 +portmap_10=19:50:2 +portmap_11=21:50:2 +portmap_12=23:50:2 +portmap_13=25:50:2 +portmap_14=27:50:2 +portmap_15=29:50:2 +portmap_16=31:50:2 +portmap_17=33:100 +portmap_18=37:100 +portmap_19=41:50:2 +portmap_20=43:50:2 +portmap_21=45:50:2 +portmap_22=47:50:2 +portmap_23=49:50:2 +portmap_24=51:50:2 +portmap_25=53:50:2 +portmap_26=55:50:2 +portmap_27=57:50:2 +portmap_28=59:50:2 +portmap_29=61:50:2 +portmap_30=63:50:2 + + +# TX polarity +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 + +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 + +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 + +phy_chain_tx_polarity_flip_physical{13.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}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 + +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +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}=0x1 + +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 + +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +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}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 + +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 + +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}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 + +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 + +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 + +# RX polarity +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 + +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 + +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 + +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 + +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 + +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +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}=0x1 + +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x1 + +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 + +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}=0x1 + +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 + +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 + +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x0 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 + +# TX lane swap +phy_chain_tx_lane_map_physical{1.0}=0x3120 +phy_chain_tx_lane_map_physical{5.0}=0x2130 +phy_chain_tx_lane_map_physical{9.0}=0x0213 +phy_chain_tx_lane_map_physical{13.0}=0x3021 + +phy_chain_tx_lane_map_physical{17.0}=0x3201 +phy_chain_tx_lane_map_physical{21.0}=0x3210 +phy_chain_tx_lane_map_physical{25.0}=0x1023 +phy_chain_tx_lane_map_physical{29.0}=0x0231 + +phy_chain_tx_lane_map_physical{33.0}=0x3210 +phy_chain_tx_lane_map_physical{37.0}=0x3120 +phy_chain_tx_lane_map_physical{41.0}=0x2031 +phy_chain_tx_lane_map_physical{45.0}=0x2130 + +phy_chain_tx_lane_map_physical{49.0}=0x2130 +phy_chain_tx_lane_map_physical{53.0}=0x3012 +phy_chain_tx_lane_map_physical{57.0}=0x2031 +phy_chain_tx_lane_map_physical{61.0}=0x0231 + +# RX lane swap +phy_chain_rx_lane_map_physical{1.0}=0x1320 +phy_chain_rx_lane_map_physical{5.0}=0x0213 +phy_chain_rx_lane_map_physical{9.0}=0x2301 +phy_chain_rx_lane_map_physical{13.0}=0x0321 + +phy_chain_rx_lane_map_physical{17.0}=0x2031 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_rx_lane_map_physical{25.0}=0x2310 +phy_chain_rx_lane_map_physical{29.0}=0x2013 + +phy_chain_rx_lane_map_physical{33.0}=0x2103 +phy_chain_rx_lane_map_physical{37.0}=0x0132 +phy_chain_rx_lane_map_physical{41.0}=0x2031 +phy_chain_rx_lane_map_physical{45.0}=0x1032 + +phy_chain_rx_lane_map_physical{49.0}=0x3201 +phy_chain_rx_lane_map_physical{53.0}=0x0132 +phy_chain_rx_lane_map_physical{57.0}=0x2031 +phy_chain_rx_lane_map_physical{61.0}=0x1032 + +# +# Tile-1 FC16~FC31 +# +portmap_34=65:50:2 +portmap_35=67:50:2 +portmap_36=69:50:2 +portmap_37=71:50:2 +portmap_38=73:50:2 +portmap_39=75:50:2 +portmap_40=77:50:2 +portmap_41=79:50:2 +portmap_42=81:50:2 +portmap_43=83:50:2 +portmap_44=85:50:2 +portmap_45=87:50:2 +portmap_46=89:50:2 +portmap_47=91:50:2 +portmap_48=93:50:2 +portmap_49=95:50:2 +portmap_50=97:50:2 +portmap_51=99:50:2 +portmap_52=101:50:2 +portmap_53=103:50:2 +portmap_54=105:50:2 +portmap_55=107:50:2 +portmap_56=109:50:2 +portmap_57=111:50:2 +portmap_58=113:100 +portmap_59=117:100 +portmap_60=121:50:2 +portmap_61=123:50:2 +portmap_62=125:50:2 +portmap_63=127:50:2 + +#TX polarity +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}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 + +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.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}=0x0 + +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.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}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 + +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 + +phy_chain_tx_polarity_flip_physical{89.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 + +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 + +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +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}=0x1 +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}=0x0 +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{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 + +#RX polarity +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +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{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 + +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 + +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +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}=0x0 + +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 + +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x1 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 + +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +phy_chain_rx_polarity_flip_physical{102.0}=0x0 +phy_chain_rx_polarity_flip_physical{103.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 + +phy_chain_rx_polarity_flip_physical{109.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.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}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 + +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +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}=0x0 + +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}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{65.0}=0x2130 +phy_chain_tx_lane_map_physical{69.0}=0x3012 +phy_chain_tx_lane_map_physical{73.0}=0x2031 +phy_chain_tx_lane_map_physical{77.0}=0x0231 + +phy_chain_tx_lane_map_physical{81.0}=0x2130 +phy_chain_tx_lane_map_physical{85.0}=0x1032 +phy_chain_tx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x0231 + +phy_chain_tx_lane_map_physical{97.0}=0x0123 +phy_chain_tx_lane_map_physical{101.0}=0x1320 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_tx_lane_map_physical{109.0}=0x0213 + +phy_chain_tx_lane_map_physical{113.0}=0x0123 +phy_chain_tx_lane_map_physical{117.0}=0x1023 +phy_chain_tx_lane_map_physical{121.0}=0x2130 +phy_chain_tx_lane_map_physical{125.0}=0x1302 + +# RX lane swap +phy_chain_rx_lane_map_physical{65.0}=0x2103 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x2031 +phy_chain_rx_lane_map_physical{77.0}=0x1032 + +phy_chain_rx_lane_map_physical{81.0}=0x2103 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_rx_lane_map_physical{93.0}=0x1032 + +phy_chain_rx_lane_map_physical{97.0}=0x1023 +phy_chain_rx_lane_map_physical{101.0}=0x3120 +phy_chain_rx_lane_map_physical{105.0}=0x1023 +phy_chain_rx_lane_map_physical{109.0}=0x0231 + +phy_chain_rx_lane_map_physical{113.0}=0x1320 +phy_chain_rx_lane_map_physical{117.0}=0x3102 +phy_chain_rx_lane_map_physical{121.0}=0x0213 +phy_chain_rx_lane_map_physical{125.0}=0x0231 + +# +# Tile-2 FC32~FC47 +# +# port 66 is the first management port +portmap_66=257:10 +# port 67 is the second loopback port +#portmap_67=261:10 +portmap_68=129:100 +portmap_69=133:100 +portmap_70=137:50:2 +portmap_71=139:50:2 +portmap_72=141:50:2 +portmap_73=143:50:2 +portmap_74=145:50:2 +portmap_75=147:50:2 +portmap_76=149:50:2 +portmap_77=151:50:2 +portmap_78=153:50:2 +portmap_79=155:50:2 +portmap_80=157:50:2 +portmap_81=159:50:2 +portmap_82=161:50:2 +portmap_83=163:50:2 +portmap_84=165:50:2 +portmap_85=167:50:2 +portmap_86=169:50:2 +portmap_87=171:50:2 +portmap_88=173:50:2 +portmap_89=175:50:2 +portmap_90=177:50:2 +portmap_91=179:50:2 +portmap_92=181:50:2 +portmap_93=183:50:2 +portmap_94=185:50:2 +portmap_95=187:50:2 +portmap_96=189:50:2 +portmap_97=191:50:2 + + +# TX polarity +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 + +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x1 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 + +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x0 + +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x0 +phy_chain_tx_polarity_flip_physical{143.0}=0x1 +phy_chain_tx_polarity_flip_physical{144.0}=0x1 + +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x1 + +phy_chain_tx_polarity_flip_physical{149.0}=0x0 +phy_chain_tx_polarity_flip_physical{150.0}=0x1 +phy_chain_tx_polarity_flip_physical{151.0}=0x1 +phy_chain_tx_polarity_flip_physical{152.0}=0x1 + +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 + +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x1 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 + +phy_chain_tx_polarity_flip_physical{161.0}=0x1 +phy_chain_tx_polarity_flip_physical{162.0}=0x0 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x1 + +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 + +phy_chain_tx_polarity_flip_physical{169.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x0 + +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x0 +phy_chain_tx_polarity_flip_physical{176.0}=0x1 + +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x0 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 + +phy_chain_tx_polarity_flip_physical{181.0}=0x1 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 + +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x0 + +phy_chain_tx_polarity_flip_physical{189.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x1 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 + +# RX polarity +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 + +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 + +phy_chain_rx_polarity_flip_physical{137.0}=0x1 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x1 + +phy_chain_rx_polarity_flip_physical{141.0}=0x0 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x1 + +phy_chain_rx_polarity_flip_physical{145.0}=0x0 +phy_chain_rx_polarity_flip_physical{146.0}=0x0 +phy_chain_rx_polarity_flip_physical{147.0}=0x1 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 + +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x1 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 + +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x0 + +phy_chain_rx_polarity_flip_physical{157.0}=0x1 +phy_chain_rx_polarity_flip_physical{158.0}=0x1 +phy_chain_rx_polarity_flip_physical{159.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 + +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 + +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x1 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x0 + +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x1 + +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x1 +phy_chain_rx_polarity_flip_physical{175.0}=0x0 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 + +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x1 + +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x1 + +phy_chain_rx_polarity_flip_physical{185.0}=0x1 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 + +phy_chain_rx_polarity_flip_physical{189.0}=0x1 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x0 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{129.0}=0x0312 +phy_chain_tx_lane_map_physical{133.0}=0x3120 +phy_chain_tx_lane_map_physical{137.0}=0x1203 +phy_chain_tx_lane_map_physical{141.0}=0x0132 + +phy_chain_tx_lane_map_physical{145.0}=0x0312 +phy_chain_tx_lane_map_physical{149.0}=0x2310 +phy_chain_tx_lane_map_physical{153.0}=0x1032 +phy_chain_tx_lane_map_physical{157.0}=0x3120 + +phy_chain_tx_lane_map_physical{161.0}=0x1023 +phy_chain_tx_lane_map_physical{165.0}=0x1203 +phy_chain_tx_lane_map_physical{169.0}=0x0213 +phy_chain_tx_lane_map_physical{173.0}=0x0123 + +phy_chain_tx_lane_map_physical{177.0}=0x2031 +phy_chain_tx_lane_map_physical{181.0}=0x1203 +phy_chain_tx_lane_map_physical{185.0}=0x0213 +phy_chain_tx_lane_map_physical{189.0}=0x3210 + +# RX lane swap +phy_chain_rx_lane_map_physical{129.0}=0x0321 +phy_chain_rx_lane_map_physical{133.0}=0x0312 +phy_chain_rx_lane_map_physical{137.0}=0x2103 +phy_chain_rx_lane_map_physical{141.0}=0x0231 + +phy_chain_rx_lane_map_physical{145.0}=0x0321 +phy_chain_rx_lane_map_physical{149.0}=0x0312 +phy_chain_rx_lane_map_physical{153.0}=0x3120 +phy_chain_rx_lane_map_physical{157.0}=0x2103 + +phy_chain_rx_lane_map_physical{161.0}=0x1032 +phy_chain_rx_lane_map_physical{165.0}=0x2031 +phy_chain_rx_lane_map_physical{169.0}=0x0132 +phy_chain_rx_lane_map_physical{173.0}=0x2103 + +phy_chain_rx_lane_map_physical{177.0}=0x1032 +phy_chain_rx_lane_map_physical{181.0}=0x1230 +phy_chain_rx_lane_map_physical{185.0}=0x0321 +phy_chain_rx_lane_map_physical{189.0}=0x3201 + +# +# Tile-3 FC48~FC63 +# portmap_0=x:xx // cpu port (not required, but included for illustration purposes) +# +# port 100 is the second management port +portmap_100=259:10 +# port 101 is the third loopback port +#portmap_101=262:10 +portmap_102=193:50:2 +portmap_103=195:50:2 +portmap_104=197:50:2 +portmap_105=199:50:2 +portmap_106=201:50:2 +portmap_107=203:50:2 +portmap_108=205:50:2 +portmap_109=207:50:2 +portmap_110=209:100 +portmap_111=213:100 +portmap_112=217:50:2 +portmap_113=219:50:2 +portmap_114=221:50:2 +portmap_115=223:50:2 +portmap_116=225:50:2 +portmap_117=227:50:2 +portmap_118=229:50:2 +portmap_119=231:50:2 +portmap_120=233:50:2 +portmap_121=235:50:2 +portmap_122=237:50:2 +portmap_123=239:50:2 +portmap_124=241:50:2 +portmap_125=243:50:2 +portmap_126=245:50:2 +portmap_127=247:50:2 +portmap_128=249:50:2 +portmap_129=251:50:2 +portmap_130=253:50:2 +portmap_131=255:50:2 + +# port 135 is the fourth loopback port +portmap_135=263:10 + +# TX polarity +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x0 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 + +phy_chain_tx_polarity_flip_physical{197.0}=0x1 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 + +phy_chain_tx_polarity_flip_physical{201.0}=0x0 +phy_chain_tx_polarity_flip_physical{202.0}=0x0 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x0 + +phy_chain_tx_polarity_flip_physical{205.0}=0x1 +phy_chain_tx_polarity_flip_physical{206.0}=0x0 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 + +phy_chain_tx_polarity_flip_physical{209.0}=0x1 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x0 +phy_chain_tx_polarity_flip_physical{212.0}=0x1 + +phy_chain_tx_polarity_flip_physical{213.0}=0x1 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x0 + +phy_chain_tx_polarity_flip_physical{217.0}=0x0 +phy_chain_tx_polarity_flip_physical{218.0}=0x0 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 + +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x1 +phy_chain_tx_polarity_flip_physical{223.0}=0x1 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 + +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x0 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 + +phy_chain_tx_polarity_flip_physical{229.0}=0x1 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x1 + +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x1 + +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 + +phy_chain_tx_polarity_flip_physical{241.0}=0x0 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x0 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 + +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x0 +phy_chain_tx_polarity_flip_physical{248.0}=0x0 + +phy_chain_tx_polarity_flip_physical{249.0}=0x0 +phy_chain_tx_polarity_flip_physical{250.0}=0x0 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 + +phy_chain_tx_polarity_flip_physical{253.0}=0x1 +phy_chain_tx_polarity_flip_physical{254.0}=0x0 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 + +# RX polarity +phy_chain_rx_polarity_flip_physical{193.0}=0x1 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 + +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x1 + +phy_chain_rx_polarity_flip_physical{201.0}=0x1 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x1 + +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x0 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 + +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x1 + +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x1 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 + +phy_chain_rx_polarity_flip_physical{217.0}=0x1 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 + +phy_chain_rx_polarity_flip_physical{221.0}=0x1 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x0 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 + +phy_chain_rx_polarity_flip_physical{225.0}=0x1 +phy_chain_rx_polarity_flip_physical{226.0}=0x1 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x0 + +phy_chain_rx_polarity_flip_physical{229.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 + +phy_chain_rx_polarity_flip_physical{233.0}=0x1 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 + +phy_chain_rx_polarity_flip_physical{237.0}=0x0 +phy_chain_rx_polarity_flip_physical{238.0}=0x1 +phy_chain_rx_polarity_flip_physical{239.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 + +phy_chain_rx_polarity_flip_physical{241.0}=0x0 +phy_chain_rx_polarity_flip_physical{242.0}=0x1 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x1 + +phy_chain_rx_polarity_flip_physical{245.0}=0x1 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x0 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 + +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x0 +phy_chain_rx_polarity_flip_physical{251.0}=0x1 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 + +phy_chain_rx_polarity_flip_physical{253.0}=0x1 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{193.0}=0x2031 +phy_chain_tx_lane_map_physical{197.0}=0x1203 +phy_chain_tx_lane_map_physical{201.0}=0x0213 +phy_chain_tx_lane_map_physical{205.0}=0x3210 + +phy_chain_tx_lane_map_physical{209.0}=0x1023 +phy_chain_tx_lane_map_physical{213.0}=0x1203 +phy_chain_tx_lane_map_physical{217.0}=0x0213 +phy_chain_tx_lane_map_physical{221.0}=0x3102 + +phy_chain_tx_lane_map_physical{225.0}=0x2031 +phy_chain_tx_lane_map_physical{229.0}=0x1023 +phy_chain_tx_lane_map_physical{233.0}=0x1320 +phy_chain_tx_lane_map_physical{237.0}=0x2013 + +phy_chain_tx_lane_map_physical{241.0}=0x1023 +phy_chain_tx_lane_map_physical{245.0}=0x1203 +phy_chain_tx_lane_map_physical{249.0}=0x3120 +phy_chain_tx_lane_map_physical{253.0}=0x3210 + +# RX lane swap +phy_chain_rx_lane_map_physical{193.0}=0x1032 +phy_chain_rx_lane_map_physical{197.0}=0x1230 +phy_chain_rx_lane_map_physical{201.0}=0x0321 +phy_chain_rx_lane_map_physical{205.0}=0x3201 + +phy_chain_rx_lane_map_physical{209.0}=0x3201 +phy_chain_rx_lane_map_physical{213.0}=0x2031 +phy_chain_rx_lane_map_physical{217.0}=0x0321 +phy_chain_rx_lane_map_physical{221.0}=0x3201 + +phy_chain_rx_lane_map_physical{225.0}=0x2103 +phy_chain_rx_lane_map_physical{229.0}=0x2310 +phy_chain_rx_lane_map_physical{233.0}=0x0213 +phy_chain_rx_lane_map_physical{237.0}=0x1032 + +phy_chain_rx_lane_map_physical{241.0}=0x0321 +phy_chain_rx_lane_map_physical{245.0}=0x2301 +phy_chain_rx_lane_map_physical{249.0}=0x2103 +phy_chain_rx_lane_map_physical{253.0}=0x2013 + +physical_ports=64 +logical_ports=136 +uplink_ports=2 +dport_map_port_66=121 +dport_map_port_100=122 + +module_64ports=1 +mmu_init_config="MSFT-TH2-Tier0" + diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/buffers.json.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..96c99e5800e9 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/buffers_defaults_t0.j2 @@ -0,0 +1,43 @@ + +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx*4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "35621248", + "type": "ingress", + "mode": "dynamic", + "xoff": "7847424" + }, + "egress_lossless_pool": { + "size": "43468672", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"43468672" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "mode":"dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..5710131e5287 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/buffers_defaults_t1.j2 @@ -0,0 +1,42 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx*4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "35621248", + "type": "ingress", + "mode": "dynamic", + "xoff": "7847424" + }, + "egress_lossless_pool": { + "size": "43468672", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"43468672" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/led_proc_init.soc b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/led_proc_init.soc new file mode 100644 index 000000000000..93806b33dbeb --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/led_proc_init.soc @@ -0,0 +1,115 @@ +# LED microprocessor initialization for DellEMC-Z9264f + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=32 REMAP_PORT_2=33 REMAP_PORT_1=34 REMAP_PORT_0=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=36 REMAP_PORT_6=37 REMAP_PORT_5=38 REMAP_PORT_4=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=4 REMAP_PORT_10=5 REMAP_PORT_9=6 REMAP_PORT_8=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0 REMAP_PORT_14=1 REMAP_PORT_13=2 REMAP_PORT_12=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=56 REMAP_PORT_18=57 REMAP_PORT_17=58 REMAP_PORT_16=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=60 REMAP_PORT_22=61 REMAP_PORT_21=62 REMAP_PORT_20=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=28 REMAP_PORT_26=29 REMAP_PORT_25=30 REMAP_PORT_24=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 REMAP_PORT_30=25 REMAP_PORT_29=26 REMAP_PORT_28=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=48 REMAP_PORT_34=49 REMAP_PORT_33=50 REMAP_PORT_32=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=52 REMAP_PORT_38=53 REMAP_PORT_37=54 REMAP_PORT_36=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=20 REMAP_PORT_42=21 REMAP_PORT_41=22 REMAP_PORT_40=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=16 REMAP_PORT_46=17 REMAP_PORT_45=18 REMAP_PORT_44=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=40 REMAP_PORT_50=41 REMAP_PORT_49=42 REMAP_PORT_48=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=44 REMAP_PORT_54=45 REMAP_PORT_53=46 REMAP_PORT_52=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12 REMAP_PORT_58=13 REMAP_PORT_57=14 REMAP_PORT_56=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=8 REMAP_PORT_62=9 REMAP_PORT_61=10 REMAP_PORT_60=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=38 REMAP_PORT_8=39 REMAP_PORT_11=36 REMAP_PORT_10=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=32 REMAP_PORT_14=33 REMAP_PORT_13=34 REMAP_PORT_12=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=8 REMAP_PORT_18=9 REMAP_PORT_17=10 REMAP_PORT_16=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=12 REMAP_PORT_22=13 REMAP_PORT_21=14 REMAP_PORT_20=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44 REMAP_PORT_26=45 REMAP_PORT_25=46 REMAP_PORT_24=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=40 REMAP_PORT_30=41 REMAP_PORT_29=42 REMAP_PORT_28=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 REMAP_PORT_34=17 REMAP_PORT_33=18 REMAP_PORT_32=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 REMAP_PORT_38=21 REMAP_PORT_37=22 REMAP_PORT_36=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 REMAP_PORT_42=53 REMAP_PORT_41=54 REMAP_PORT_40=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 REMAP_PORT_46=49 REMAP_PORT_45=50 REMAP_PORT_44=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=24 REMAP_PORT_50=25 REMAP_PORT_49=26 REMAP_PORT_48=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=28 REMAP_PORT_54=29 REMAP_PORT_53=30 REMAP_PORT_52=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=60 REMAP_PORT_58=61 REMAP_PORT_57=62 REMAP_PORT_56=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 REMAP_PORT_62=57 REMAP_PORT_61=58 REMAP_PORT_60=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=60 REMAP_PORT_2=61 REMAP_PORT_1=62 REMAP_PORT_0=63 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=56 REMAP_PORT_6=57 REMAP_PORT_5=58 REMAP_PORT_4=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=24 REMAP_PORT_10=25 REMAP_PORT_9=26 REMAP_PORT_8=27 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=28 REMAP_PORT_14=29 REMAP_PORT_13=30 REMAP_PORT_12=31 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=52 REMAP_PORT_18=53 REMAP_PORT_17=54 REMAP_PORT_16=55 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=48 REMAP_PORT_22=49 REMAP_PORT_21=50 REMAP_PORT_20=51 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16 REMAP_PORT_26=17 REMAP_PORT_25=18 REMAP_PORT_24=19 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=20 REMAP_PORT_30=21 REMAP_PORT_29=22 REMAP_PORT_28=23 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=44 REMAP_PORT_34=45 REMAP_PORT_33=46 REMAP_PORT_32=47 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=40 REMAP_PORT_38=41 REMAP_PORT_37=42 REMAP_PORT_36=43 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=8 REMAP_PORT_42=9 REMAP_PORT_41=10 REMAP_PORT_40=11 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=12 REMAP_PORT_46=13 REMAP_PORT_45=14 REMAP_PORT_44=15 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=36 REMAP_PORT_50=37 REMAP_PORT_49=38 REMAP_PORT_48=39 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=32 REMAP_PORT_54=33 REMAP_PORT_53=34 REMAP_PORT_52=35 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=0 REMAP_PORT_58=1 REMAP_PORT_57=2 REMAP_PORT_56=3 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4 REMAP_PORT_62=5 REMAP_PORT_61=6 REMAP_PORT_60=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 REMAP_PORT_2=29 REMAP_PORT_1=30 REMAP_PORT_0=31 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 REMAP_PORT_6=25 REMAP_PORT_5=26 REMAP_PORT_4=27 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 REMAP_PORT_10=57 REMAP_PORT_9=58 REMAP_PORT_8=59 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 REMAP_PORT_14=61 REMAP_PORT_13=62 REMAP_PORT_12=63 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=4 REMAP_PORT_18=5 REMAP_PORT_17=6 REMAP_PORT_16=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0 REMAP_PORT_22=1 REMAP_PORT_21=2 REMAP_PORT_20=3 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=32 REMAP_PORT_26=33 REMAP_PORT_25=34 REMAP_PORT_24=35 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36 REMAP_PORT_30=37 REMAP_PORT_29=38 REMAP_PORT_28=39 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=12 REMAP_PORT_34=13 REMAP_PORT_33=14 REMAP_PORT_32=15 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=8 REMAP_PORT_38=9 REMAP_PORT_37=10 REMAP_PORT_36=11 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 REMAP_PORT_42=41 REMAP_PORT_41=42 REMAP_PORT_40=43 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 REMAP_PORT_46=45 REMAP_PORT_45=46 REMAP_PORT_44=47 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=20 REMAP_PORT_50=21 REMAP_PORT_49=22 REMAP_PORT_48=23 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=16 REMAP_PORT_54=17 REMAP_PORT_53=18 REMAP_PORT_52=19 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48 REMAP_PORT_58=49 REMAP_PORT_57=50 REMAP_PORT_56=51 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=52 REMAP_PORT_62=53 REMAP_PORT_61=54 REMAP_PORT_60=55 +m CMIC_LEDUP4_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=1 REMAP_PORT_1=0 + +led 0 stop +led 0 prog \ + 02 00 28 60 FE 67 1B 06 FE 80 D2 40 74 02 86 FD \ + 3A 80 28 32 08 97 71 5A 77 4C 57 28 32 08 97 75 \ + 4C 28 32 00 32 01 B7 97 75 3C 16 FD DA 0A 74 36 \ + 12 00 61 FD CA 05 CA 05 74 3C 77 4C 12 96 F8 15 \ + 1A 00 75 53 77 5A 57 28 32 07 97 57 32 0E 87 32 \ + 0E 87 57 32 0E 87 32 0F 87 57 32 0F 87 32 0E 87 \ + 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog \ + 02 00 28 60 FE 67 1B 06 FE 80 D2 40 74 02 86 FD \ + 3A 80 28 32 08 97 71 5A 77 4C 57 28 32 08 97 75 \ + 4C 28 32 00 32 01 B7 97 75 3C 16 FD DA 0A 74 36 \ + 12 00 61 FD CA 05 CA 05 74 3C 77 4C 12 96 F8 15 \ + 1A 00 75 53 77 5A 57 28 32 07 97 57 32 0E 87 32 \ + 0E 87 57 32 0E 87 32 0F 87 57 32 0F 87 32 0E 87 \ + 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 1 auto on +led 1 start + +led 2 stop +led 2 prog \ + 02 00 28 60 FE 67 1B 06 FE 80 D2 40 74 02 86 FD \ + 3A 80 28 32 08 97 71 5A 77 4C 57 28 32 08 97 75 \ + 4C 28 32 00 32 01 B7 97 75 3C 16 FD DA 0A 74 36 \ + 12 00 61 FD CA 05 CA 05 74 3C 77 4C 12 96 F8 15 \ + 1A 00 75 53 77 5A 57 28 32 07 97 57 32 0E 87 32 \ + 0E 87 57 32 0E 87 32 0F 87 57 32 0F 87 32 0E 87 \ + 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 2 auto on +led 2 start + +led 3 stop +led 3 prog \ + 02 00 28 60 FE 67 1B 06 FE 80 D2 40 74 02 86 FD \ + 3A 80 28 32 08 97 71 5A 77 4C 57 28 32 08 97 75 \ + 4C 28 32 00 32 01 B7 97 75 3C 16 FD DA 0A 74 36 \ + 12 00 61 FD CA 05 CA 05 74 3C 77 4C 12 96 F8 15 \ + 1A 00 75 53 77 5A 57 28 32 07 97 57 32 0E 87 32 \ + 0E 87 57 32 0E 87 32 0F 87 57 32 0F 87 32 0E 87 \ + 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +led 3 auto on +led 3 start diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/pg_profile_lookup.ini b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/pg_profile_lookup.ini new file mode 100644 index 000000000000..aedda37a8878 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -3 2288 + 25000 5m 1248 2288 53248 -3 2288 + 40000 5m 1248 2288 66560 -3 2288 + 50000 5m 1248 2288 90272 -3 2288 + 100000 5m 1248 2288 165568 -3 2288 + 10000 40m 1248 2288 37024 -3 2288 + 25000 40m 1248 2288 53248 -3 2288 + 40000 40m 1248 2288 71552 -3 2288 + 50000 40m 1248 2288 96096 -3 2288 + 100000 40m 1248 2288 177632 -3 2288 + 10000 300m 1248 2288 46176 -3 2288 + 25000 300m 1248 2288 79040 -3 2288 + 40000 300m 1248 2288 108160 -3 2288 + 50000 300m 1248 2288 141856 -3 2288 + 100000 300m 1248 2288 268736 -3 2288 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/port_config.ini b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/port_config.ini new file mode 100644 index 000000000000..13c0d6600020 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/port_config.ini @@ -0,0 +1,67 @@ +# name lanes alias index speed +Ethernet0 49,50,51,52 fortyGigE1/1 1 40000 +Ethernet4 53,54,55,56 fortyGigE1/2 2 40000 +Ethernet8 65,66,67,68 fortyGigE1/3 3 40000 +Ethernet12 69,70,71,72 fortyGigE1/4 4 40000 +Ethernet16 81,82,83,84 fortyGigE1/5 5 40000 +Ethernet20 85,86,87,88 fortyGigE1/6 6 40000 +Ethernet24 97,98,99,100 fortyGigE1/7 7 40000 +Ethernet28 101,102,103,104 fortyGigE1/8 8 40000 +Ethernet32 1,2,3,4 fortyGigE1/9 9 40000 +Ethernet36 5,6,7,8 fortyGigE1/10 10 40000 +Ethernet40 17,18,19,20 fortyGigE1/11 11 40000 +Ethernet44 21,22,23,24 fortyGigE1/12 12 40000 +Ethernet48 33,34,35,36 fortyGigE1/13 13 40000 +Ethernet52 37,38,39,40 fortyGigE1/14 14 40000 +Ethernet56 113,114,115,116 fortyGigE1/15 15 40000 +Ethernet60 117,118,119,120 fortyGigE1/16 16 40000 +Ethernet64 133,134,135,136 fortyGigE1/17 17 40000 +Ethernet68 129,130,131,132 fortyGigE1/18 18 40000 +Ethernet72 213,214,215,216 fortyGigE1/19 19 40000 +Ethernet76 209,210,211,212 fortyGigE1/20 20 40000 +Ethernet80 229,230,231,232 fortyGigE1/21 21 40000 +Ethernet84 225,226,227,228 fortyGigE1/22 22 40000 +Ethernet88 245,246,247,248 fortyGigE1/23 23 40000 +Ethernet92 241,242,243,244 fortyGigE1/24 24 40000 +Ethernet96 149,150,151,152 fortyGigE1/25 25 40000 +Ethernet100 145,146,147,148 fortyGigE1/26 26 40000 +Ethernet104 165,166,167,168 fortyGigE1/27 27 40000 +Ethernet108 161,162,163,164 fortyGigE1/28 28 40000 +Ethernet112 181,182,183,184 fortyGigE1/29 29 40000 +Ethernet116 177,178,179,180 fortyGigE1/30 30 40000 +Ethernet120 197,198,199,200 fortyGigE1/31 31 40000 +Ethernet124 193,194,195,196 fortyGigE1/32 32 40000 +Ethernet128 61,62,63,64 fortyGigE1/33 33 40000 +Ethernet132 57,58,59,60 fortyGigE1/34 34 40000 +Ethernet136 77,78,79,80 fortyGigE1/35 35 40000 +Ethernet140 73,74,75,76 fortyGigE1/36 36 40000 +Ethernet144 93,94,95,96 fortyGigE1/37 37 40000 +Ethernet148 89,90,91,92 fortyGigE1/38 38 40000 +Ethernet152 109,110,111,112 fortyGigE1/39 39 40000 +Ethernet156 105,106,107,108 fortyGigE1/40 40 40000 +Ethernet160 13,14,15,16 fortyGigE1/41 41 40000 +Ethernet164 9,10,11,12 fortyGigE1/42 42 40000 +Ethernet168 29,30,31,32 fortyGigE1/43 43 40000 +Ethernet172 25,26,27,28 fortyGigE1/44 44 40000 +Ethernet176 45,46,47,48 fortyGigE1/45 45 40000 +Ethernet180 41,42,43,44 fortyGigE1/46 46 40000 +Ethernet184 125,126,127,128 fortyGigE1/47 47 40000 +Ethernet188 121,122,123,124 fortyGigE1/48 48 40000 +Ethernet192 137,138,139,140 fortyGigE1/49 49 40000 +Ethernet196 141,142,143,144 fortyGigE1/50 50 40000 +Ethernet200 217,218,219,220 fortyGigE1/51 51 40000 +Ethernet204 221,222,223,224 fortyGigE1/52 52 40000 +Ethernet208 233,234,235,236 fortyGigE1/53 53 40000 +Ethernet212 237,238,239,240 fortyGigE1/54 54 40000 +Ethernet216 249,250,251,252 fortyGigE1/55 55 40000 +Ethernet220 253,254,255,256 fortyGigE1/56 56 40000 +Ethernet224 153,154,155,156 fortyGigE1/57 57 40000 +Ethernet228 157,158,159,160 fortyGigE1/58 58 40000 +Ethernet232 169,170,171,172 fortyGigE1/59 59 40000 +Ethernet236 173,174,175,176 fortyGigE1/60 60 40000 +Ethernet240 185,186,187,188 fortyGigE1/61 61 40000 +Ethernet244 189,190,191,192 fortyGigE1/62 62 40000 +Ethernet248 201,202,203,204 fortyGigE1/63 63 40000 +Ethernet252 205,206,207,208 fortyGigE1/64 64 40000 +Ethernet256 257 tenGigE1/65 65 10000 +Ethernet257 259 tenGigE1/66 66 10000 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/qos.json.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/sai.profile.j2 b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/sai.profile.j2 new file mode 100644 index 000000000000..7c6d12b4b173 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/sai.profile.j2 @@ -0,0 +1,14 @@ +{# Get sai.profile based on switch_role #} +{%- if DEVICE_METADATA is defined -%} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] -%} +{%- if 'torrouter' in switch_role.lower() %} +{% set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-z9264f-64x40G-t0.config.bcm' -%} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-z9264f-64x40G-t1.config.bcm' -%} +{%- endif %} +{%- else %} +{%- set sai_profile_contents = 'SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-z9264f-64x40G-t1.config.bcm' -%} +{%- endif %} +{# Write the contents of sai_ profile_filename to sai.profile file #} +{{ sai_profile_contents }} +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/th2-z9264f-64x40G-t0.config.bcm b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/th2-z9264f-64x40G-t0.config.bcm new file mode 100644 index 000000000000..24990bbdb1e7 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/th2-z9264f-64x40G-t0.config.bcm @@ -0,0 +1,1006 @@ +#TH2 Z9264F 64x40G +os=unix +core_clock_frequency=1700 +dpp_clock_ratio=2:3 +pbmp_xport_xe=0x3FFFD0000FFFF40003FFFC0001FFFE +oversubscribe_mode=1 +fpem_mem_entries=65536 +l2xmsg_mode=1 + +l3_alpm_enable=2 +bcm_num_cos=10 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 + +parity_correction=1 +parity_enable=1 + +dport_map_enable=1 + +dport_map_enable=1 +dport_map_port_13=1 +dport_map_port_14=2 +dport_map_port_34=3 +dport_map_port_35=4 +dport_map_port_38=5 +dport_map_port_39=6 +dport_map_port_42=7 +dport_map_port_43=8 +dport_map_port_1=9 +dport_map_port_2=10 +dport_map_port_5=11 +dport_map_port_6=12 +dport_map_port_9=13 +dport_map_port_10=14 +dport_map_port_46=15 +dport_map_port_47=16 + +dport_map_port_69=17 +dport_map_port_68=18 +dport_map_port_107=19 +dport_map_port_106=20 +dport_map_port_111=21 +dport_map_port_110=22 +dport_map_port_115=23 +dport_map_port_114=24 +dport_map_port_73=25 +dport_map_port_72=26 +dport_map_port_77=27 +dport_map_port_76=28 +dport_map_port_81=29 +dport_map_port_80=30 +dport_map_port_103=31 +dport_map_port_102=32 + +dport_map_port_16=33 +dport_map_port_15=34 +dport_map_port_37=35 +dport_map_port_36=36 +dport_map_port_41=37 +dport_map_port_40=38 +dport_map_port_45=39 +dport_map_port_44=40 +dport_map_port_4=41 +dport_map_port_3=42 +dport_map_port_8=43 +dport_map_port_7=44 +dport_map_port_12=45 +dport_map_port_11=46 +dport_map_port_49=47 +dport_map_port_48=48 + +dport_map_port_70=49 +dport_map_port_71=50 +dport_map_port_108=51 +dport_map_port_109=52 +dport_map_port_112=53 +dport_map_port_113=54 +dport_map_port_116=55 +dport_map_port_117=56 +dport_map_port_74=57 +dport_map_port_75=58 +dport_map_port_78=59 +dport_map_port_79=60 +dport_map_port_82=61 +dport_map_port_83=62 +dport_map_port_104=63 +dport_map_port_105=64 + +# +# Tile-0 FC0~FC15 +# +portmap_1=1:40 +portmap_2=5:40 +portmap_3=9:40 +portmap_4=13:40 +portmap_5=17:40 +portmap_6=21:40 +portmap_7=25:40 +portmap_8=29:40 +portmap_9=33:40 +portmap_10=37:40 +portmap_11=41:40 +portmap_12=45:40 +portmap_13=49:40 +portmap_14=53:40 +portmap_15=57:40 +portmap_16=61:40 + +# TX polarity +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 + +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 + +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 + +phy_chain_tx_polarity_flip_physical{13.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}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 + +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +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}=0x1 + +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 + +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +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}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 + +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 + +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}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 + +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 + +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 + +# RX polarity +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 + +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 + +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 + +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 + +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 + +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +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}=0x1 + +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x1 + +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 + +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}=0x1 + +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 + +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 + +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x0 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 + +# TX lane swap +phy_chain_tx_lane_map_physical{1.0}=0x3120 +phy_chain_tx_lane_map_physical{5.0}=0x2130 +phy_chain_tx_lane_map_physical{9.0}=0x0213 +phy_chain_tx_lane_map_physical{13.0}=0x3021 + +phy_chain_tx_lane_map_physical{17.0}=0x3201 +phy_chain_tx_lane_map_physical{21.0}=0x3210 +phy_chain_tx_lane_map_physical{25.0}=0x1023 +phy_chain_tx_lane_map_physical{29.0}=0x0231 + +phy_chain_tx_lane_map_physical{33.0}=0x3210 +phy_chain_tx_lane_map_physical{37.0}=0x3120 +phy_chain_tx_lane_map_physical{41.0}=0x2031 +phy_chain_tx_lane_map_physical{45.0}=0x2130 + +phy_chain_tx_lane_map_physical{49.0}=0x2130 +phy_chain_tx_lane_map_physical{53.0}=0x3012 +phy_chain_tx_lane_map_physical{57.0}=0x2031 +phy_chain_tx_lane_map_physical{61.0}=0x0231 + +# RX lane swap +phy_chain_rx_lane_map_physical{1.0}=0x1320 +phy_chain_rx_lane_map_physical{5.0}=0x0213 +phy_chain_rx_lane_map_physical{9.0}=0x2301 +phy_chain_rx_lane_map_physical{13.0}=0x0321 + +phy_chain_rx_lane_map_physical{17.0}=0x2031 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_rx_lane_map_physical{25.0}=0x2310 +phy_chain_rx_lane_map_physical{29.0}=0x2013 + +phy_chain_rx_lane_map_physical{33.0}=0x2103 +phy_chain_rx_lane_map_physical{37.0}=0x0132 +phy_chain_rx_lane_map_physical{41.0}=0x2031 +phy_chain_rx_lane_map_physical{45.0}=0x1032 + +phy_chain_rx_lane_map_physical{49.0}=0x3201 +phy_chain_rx_lane_map_physical{53.0}=0x0132 +phy_chain_rx_lane_map_physical{57.0}=0x2031 +phy_chain_rx_lane_map_physical{61.0}=0x1032 + +# +# Tile-1 FC16~FC31 +# +portmap_34=65:40 +portmap_35=69:40 +portmap_36=73:40 +portmap_37=77:40 +portmap_38=81:40 +portmap_39=85:40 +portmap_40=89:40 +portmap_41=93:40 +portmap_42=97:40 +portmap_43=101:40 +portmap_44=105:40 +portmap_45=109:40 +portmap_46=113:40 +portmap_47=117:40 +portmap_48=121:40 +portmap_49=125:40 + +#TX polarity +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}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 + +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.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}=0x0 + +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.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}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 + +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 + +phy_chain_tx_polarity_flip_physical{89.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 + +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 + +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +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}=0x1 +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}=0x0 +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{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 + +#RX polarity +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +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{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 + +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 + +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +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}=0x0 + +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 + +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x1 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 + +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +phy_chain_rx_polarity_flip_physical{102.0}=0x0 +phy_chain_rx_polarity_flip_physical{103.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 + +phy_chain_rx_polarity_flip_physical{109.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.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}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 + +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +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}=0x0 + +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}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{65.0}=0x2130 +phy_chain_tx_lane_map_physical{69.0}=0x3012 +phy_chain_tx_lane_map_physical{73.0}=0x2031 +phy_chain_tx_lane_map_physical{77.0}=0x0231 + +phy_chain_tx_lane_map_physical{81.0}=0x2130 +phy_chain_tx_lane_map_physical{85.0}=0x1032 +phy_chain_tx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x0231 + +phy_chain_tx_lane_map_physical{97.0}=0x0123 +phy_chain_tx_lane_map_physical{101.0}=0x1320 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_tx_lane_map_physical{109.0}=0x0213 + +phy_chain_tx_lane_map_physical{113.0}=0x0123 +phy_chain_tx_lane_map_physical{117.0}=0x1023 +phy_chain_tx_lane_map_physical{121.0}=0x2130 +phy_chain_tx_lane_map_physical{125.0}=0x1302 + +# RX lane swap +phy_chain_rx_lane_map_physical{65.0}=0x2103 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x2031 +phy_chain_rx_lane_map_physical{77.0}=0x1032 + +phy_chain_rx_lane_map_physical{81.0}=0x2103 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_rx_lane_map_physical{93.0}=0x1032 + +phy_chain_rx_lane_map_physical{97.0}=0x1023 +phy_chain_rx_lane_map_physical{101.0}=0x3120 +phy_chain_rx_lane_map_physical{105.0}=0x1023 +phy_chain_rx_lane_map_physical{109.0}=0x0231 + +phy_chain_rx_lane_map_physical{113.0}=0x1320 +phy_chain_rx_lane_map_physical{117.0}=0x3102 +phy_chain_rx_lane_map_physical{121.0}=0x0213 +phy_chain_rx_lane_map_physical{125.0}=0x0231 + +# +# Tile-2 FC32~FC47 +# +# port 66 is the first management port +portmap_66=257:10 +# port 67 is the second loopback port +#portmap_67=261:10 +portmap_68=129:40 +portmap_69=133:40 +portmap_70=137:40 +portmap_71=141:40 +portmap_72=145:40 +portmap_73=149:40 +portmap_74=153:40 +portmap_75=157:40 +portmap_76=161:40 +portmap_77=165:40 +portmap_78=169:40 +portmap_79=173:40 +portmap_80=177:40 +portmap_81=181:40 +portmap_82=185:40 +portmap_83=189:40 + +# TX polarity +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 + +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x1 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 + +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x0 + +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x0 +phy_chain_tx_polarity_flip_physical{143.0}=0x1 +phy_chain_tx_polarity_flip_physical{144.0}=0x1 + +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x1 + +phy_chain_tx_polarity_flip_physical{149.0}=0x0 +phy_chain_tx_polarity_flip_physical{150.0}=0x1 +phy_chain_tx_polarity_flip_physical{151.0}=0x1 +phy_chain_tx_polarity_flip_physical{152.0}=0x1 + +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 + +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x1 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 + +phy_chain_tx_polarity_flip_physical{161.0}=0x1 +phy_chain_tx_polarity_flip_physical{162.0}=0x0 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x1 + +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 + +phy_chain_tx_polarity_flip_physical{169.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x0 + +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x0 +phy_chain_tx_polarity_flip_physical{176.0}=0x1 + +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x0 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 + +phy_chain_tx_polarity_flip_physical{181.0}=0x1 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 + +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x0 + +phy_chain_tx_polarity_flip_physical{189.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x1 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 + +# RX polarity +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 + +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 + +phy_chain_rx_polarity_flip_physical{137.0}=0x1 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x1 + +phy_chain_rx_polarity_flip_physical{141.0}=0x0 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x1 + +phy_chain_rx_polarity_flip_physical{145.0}=0x0 +phy_chain_rx_polarity_flip_physical{146.0}=0x0 +phy_chain_rx_polarity_flip_physical{147.0}=0x1 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 + +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x1 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 + +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x0 + +phy_chain_rx_polarity_flip_physical{157.0}=0x1 +phy_chain_rx_polarity_flip_physical{158.0}=0x1 +phy_chain_rx_polarity_flip_physical{159.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 + +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 + +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x1 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x0 + +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x1 + +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x1 +phy_chain_rx_polarity_flip_physical{175.0}=0x0 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 + +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x1 + +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x1 + +phy_chain_rx_polarity_flip_physical{185.0}=0x1 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 + +phy_chain_rx_polarity_flip_physical{189.0}=0x1 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x0 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{129.0}=0x0312 +phy_chain_tx_lane_map_physical{133.0}=0x3120 +phy_chain_tx_lane_map_physical{137.0}=0x1203 +phy_chain_tx_lane_map_physical{141.0}=0x0132 + +phy_chain_tx_lane_map_physical{145.0}=0x0312 +phy_chain_tx_lane_map_physical{149.0}=0x2310 +phy_chain_tx_lane_map_physical{153.0}=0x1032 +phy_chain_tx_lane_map_physical{157.0}=0x3120 + +phy_chain_tx_lane_map_physical{161.0}=0x1023 +phy_chain_tx_lane_map_physical{165.0}=0x1203 +phy_chain_tx_lane_map_physical{169.0}=0x0213 +phy_chain_tx_lane_map_physical{173.0}=0x0123 + +phy_chain_tx_lane_map_physical{177.0}=0x2031 +phy_chain_tx_lane_map_physical{181.0}=0x1203 +phy_chain_tx_lane_map_physical{185.0}=0x0213 +phy_chain_tx_lane_map_physical{189.0}=0x3210 + +# RX lane swap +phy_chain_rx_lane_map_physical{129.0}=0x0321 +phy_chain_rx_lane_map_physical{133.0}=0x0312 +phy_chain_rx_lane_map_physical{137.0}=0x2103 +phy_chain_rx_lane_map_physical{141.0}=0x0231 + +phy_chain_rx_lane_map_physical{145.0}=0x0321 +phy_chain_rx_lane_map_physical{149.0}=0x0312 +phy_chain_rx_lane_map_physical{153.0}=0x3120 +phy_chain_rx_lane_map_physical{157.0}=0x2103 + +phy_chain_rx_lane_map_physical{161.0}=0x1032 +phy_chain_rx_lane_map_physical{165.0}=0x2031 +phy_chain_rx_lane_map_physical{169.0}=0x0132 +phy_chain_rx_lane_map_physical{173.0}=0x2103 + +phy_chain_rx_lane_map_physical{177.0}=0x1032 +phy_chain_rx_lane_map_physical{181.0}=0x1230 +phy_chain_rx_lane_map_physical{185.0}=0x0321 +phy_chain_rx_lane_map_physical{189.0}=0x3201 + +# +# Tile-3 FC48~FC63 +# portmap_0=x:xx // cpu port (not required, but included for illustration purposes) +# +# port 100 is the second management port +portmap_100=259:10 +# port 101 is the third loopback port +#portmap_101=262:10 +portmap_102=193:40 +portmap_103=197:40 +portmap_104=201:40 +portmap_105=205:40 +portmap_106=209:40 +portmap_107=213:40 +portmap_108=217:40 +portmap_109=221:40 +portmap_110=225:40 +portmap_111=229:40 +portmap_112=233:40 +portmap_113=237:40 +portmap_114=241:40 +portmap_115=245:40 +portmap_116=249:40 +portmap_117=253:40 +# port 135 is the fourth loopback port +portmap_135=263:10 + +# TX polarity +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x0 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 + +phy_chain_tx_polarity_flip_physical{197.0}=0x1 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 + +phy_chain_tx_polarity_flip_physical{201.0}=0x0 +phy_chain_tx_polarity_flip_physical{202.0}=0x0 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x0 + +phy_chain_tx_polarity_flip_physical{205.0}=0x1 +phy_chain_tx_polarity_flip_physical{206.0}=0x0 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 + +phy_chain_tx_polarity_flip_physical{209.0}=0x1 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x0 +phy_chain_tx_polarity_flip_physical{212.0}=0x1 + +phy_chain_tx_polarity_flip_physical{213.0}=0x1 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x0 + +phy_chain_tx_polarity_flip_physical{217.0}=0x0 +phy_chain_tx_polarity_flip_physical{218.0}=0x0 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 + +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x1 +phy_chain_tx_polarity_flip_physical{223.0}=0x1 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 + +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x0 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 + +phy_chain_tx_polarity_flip_physical{229.0}=0x1 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x1 + +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x1 + +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 + +phy_chain_tx_polarity_flip_physical{241.0}=0x0 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x0 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 + +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x0 +phy_chain_tx_polarity_flip_physical{248.0}=0x0 + +phy_chain_tx_polarity_flip_physical{249.0}=0x0 +phy_chain_tx_polarity_flip_physical{250.0}=0x0 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 + +phy_chain_tx_polarity_flip_physical{253.0}=0x1 +phy_chain_tx_polarity_flip_physical{254.0}=0x0 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 + +# RX polarity +phy_chain_rx_polarity_flip_physical{193.0}=0x1 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 + +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x1 + +phy_chain_rx_polarity_flip_physical{201.0}=0x1 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x1 + +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x0 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 + +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x1 + +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x1 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 + +phy_chain_rx_polarity_flip_physical{217.0}=0x1 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 + +phy_chain_rx_polarity_flip_physical{221.0}=0x1 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x0 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 + +phy_chain_rx_polarity_flip_physical{225.0}=0x1 +phy_chain_rx_polarity_flip_physical{226.0}=0x1 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x0 + +phy_chain_rx_polarity_flip_physical{229.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 + +phy_chain_rx_polarity_flip_physical{233.0}=0x1 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 + +phy_chain_rx_polarity_flip_physical{237.0}=0x0 +phy_chain_rx_polarity_flip_physical{238.0}=0x1 +phy_chain_rx_polarity_flip_physical{239.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 + +phy_chain_rx_polarity_flip_physical{241.0}=0x0 +phy_chain_rx_polarity_flip_physical{242.0}=0x1 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x1 + +phy_chain_rx_polarity_flip_physical{245.0}=0x1 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x0 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 + +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x0 +phy_chain_rx_polarity_flip_physical{251.0}=0x1 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 + +phy_chain_rx_polarity_flip_physical{253.0}=0x1 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{193.0}=0x2031 +phy_chain_tx_lane_map_physical{197.0}=0x1203 +phy_chain_tx_lane_map_physical{201.0}=0x0213 +phy_chain_tx_lane_map_physical{205.0}=0x3210 + +phy_chain_tx_lane_map_physical{209.0}=0x1023 +phy_chain_tx_lane_map_physical{213.0}=0x1203 +phy_chain_tx_lane_map_physical{217.0}=0x0213 +phy_chain_tx_lane_map_physical{221.0}=0x3102 + +phy_chain_tx_lane_map_physical{225.0}=0x2031 +phy_chain_tx_lane_map_physical{229.0}=0x1023 +phy_chain_tx_lane_map_physical{233.0}=0x1320 +phy_chain_tx_lane_map_physical{237.0}=0x2013 + +phy_chain_tx_lane_map_physical{241.0}=0x1023 +phy_chain_tx_lane_map_physical{245.0}=0x1203 +phy_chain_tx_lane_map_physical{249.0}=0x3120 +phy_chain_tx_lane_map_physical{253.0}=0x3210 + +# RX lane swap +phy_chain_rx_lane_map_physical{193.0}=0x1032 +phy_chain_rx_lane_map_physical{197.0}=0x1230 +phy_chain_rx_lane_map_physical{201.0}=0x0321 +phy_chain_rx_lane_map_physical{205.0}=0x3201 + +phy_chain_rx_lane_map_physical{209.0}=0x3201 +phy_chain_rx_lane_map_physical{213.0}=0x2031 +phy_chain_rx_lane_map_physical{217.0}=0x0321 +phy_chain_rx_lane_map_physical{221.0}=0x3201 + +phy_chain_rx_lane_map_physical{225.0}=0x2103 +phy_chain_rx_lane_map_physical{229.0}=0x2310 +phy_chain_rx_lane_map_physical{233.0}=0x0213 +phy_chain_rx_lane_map_physical{237.0}=0x1032 + +phy_chain_rx_lane_map_physical{241.0}=0x0321 +phy_chain_rx_lane_map_physical{245.0}=0x2301 +phy_chain_rx_lane_map_physical{249.0}=0x2103 +phy_chain_rx_lane_map_physical{253.0}=0x2013 + +physical_ports=64 +logical_ports=136 +uplink_ports=2 +dport_map_port_66=65 +dport_map_port_100=66 + +module_64ports=1 +mmu_init_config="MSFT-TH2-Tier0" diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/th2-z9264f-64x40G-t1.config.bcm b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/th2-z9264f-64x40G-t1.config.bcm new file mode 100644 index 000000000000..b3920ebc6b8a --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/DellEMC-Z9264f-Q64/th2-z9264f-64x40G-t1.config.bcm @@ -0,0 +1,1007 @@ +#TH2 Z9264F 64x40G +os=unix +core_clock_frequency=1700 +dpp_clock_ratio=2:3 +pbmp_xport_xe=0x3FFFD0000FFFF40003FFFC0001FFFE +oversubscribe_mode=1 +fpem_mem_entries=65536 +l2xmsg_mode=1 + +l3_alpm_enable=2 +bcm_num_cos=10 +switch_bypass_mode=0 +mmu_lossless=0 +lpm_scaling_enable=0 +lpm_ipv6_128b_reserved=0 +ipv6_lpm_128b_enable=1 + +parity_correction=1 +parity_enable=1 + +dport_map_enable=1 + +dport_map_enable=1 +dport_map_port_13=1 +dport_map_port_14=2 +dport_map_port_34=3 +dport_map_port_35=4 +dport_map_port_38=5 +dport_map_port_39=6 +dport_map_port_42=7 +dport_map_port_43=8 +dport_map_port_1=9 +dport_map_port_2=10 +dport_map_port_5=11 +dport_map_port_6=12 +dport_map_port_9=13 +dport_map_port_10=14 +dport_map_port_46=15 +dport_map_port_47=16 + +dport_map_port_69=17 +dport_map_port_68=18 +dport_map_port_107=19 +dport_map_port_106=20 +dport_map_port_111=21 +dport_map_port_110=22 +dport_map_port_115=23 +dport_map_port_114=24 +dport_map_port_73=25 +dport_map_port_72=26 +dport_map_port_77=27 +dport_map_port_76=28 +dport_map_port_81=29 +dport_map_port_80=30 +dport_map_port_103=31 +dport_map_port_102=32 + +dport_map_port_16=33 +dport_map_port_15=34 +dport_map_port_37=35 +dport_map_port_36=36 +dport_map_port_41=37 +dport_map_port_40=38 +dport_map_port_45=39 +dport_map_port_44=40 +dport_map_port_4=41 +dport_map_port_3=42 +dport_map_port_8=43 +dport_map_port_7=44 +dport_map_port_12=45 +dport_map_port_11=46 +dport_map_port_49=47 +dport_map_port_48=48 + +dport_map_port_70=49 +dport_map_port_71=50 +dport_map_port_108=51 +dport_map_port_109=52 +dport_map_port_112=53 +dport_map_port_113=54 +dport_map_port_116=55 +dport_map_port_117=56 +dport_map_port_74=57 +dport_map_port_75=58 +dport_map_port_78=59 +dport_map_port_79=60 +dport_map_port_82=61 +dport_map_port_83=62 +dport_map_port_104=63 +dport_map_port_105=64 + +# +# Tile-0 FC0~FC15 +# +portmap_1=1:40 +portmap_2=5:40 +portmap_3=9:40 +portmap_4=13:40 +portmap_5=17:40 +portmap_6=21:40 +portmap_7=25:40 +portmap_8=29:40 +portmap_9=33:40 +portmap_10=37:40 +portmap_11=41:40 +portmap_12=45:40 +portmap_13=49:40 +portmap_14=53:40 +portmap_15=57:40 +portmap_16=61:40 + +# TX polarity +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 + +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 + +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 + +phy_chain_tx_polarity_flip_physical{13.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}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 + +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +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}=0x1 + +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 + +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +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}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 + +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x1 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 + +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}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 + +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 + +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 + +# RX polarity +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 + +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 + +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 + +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 + +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 + +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +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}=0x1 + +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x1 + +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 + +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}=0x1 + +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 + +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 + +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x0 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 + +# TX lane swap +phy_chain_tx_lane_map_physical{1.0}=0x3120 +phy_chain_tx_lane_map_physical{5.0}=0x2130 +phy_chain_tx_lane_map_physical{9.0}=0x0213 +phy_chain_tx_lane_map_physical{13.0}=0x3021 + +phy_chain_tx_lane_map_physical{17.0}=0x3201 +phy_chain_tx_lane_map_physical{21.0}=0x3210 +phy_chain_tx_lane_map_physical{25.0}=0x1023 +phy_chain_tx_lane_map_physical{29.0}=0x0231 + +phy_chain_tx_lane_map_physical{33.0}=0x3210 +phy_chain_tx_lane_map_physical{37.0}=0x3120 +phy_chain_tx_lane_map_physical{41.0}=0x2031 +phy_chain_tx_lane_map_physical{45.0}=0x2130 + +phy_chain_tx_lane_map_physical{49.0}=0x2130 +phy_chain_tx_lane_map_physical{53.0}=0x3012 +phy_chain_tx_lane_map_physical{57.0}=0x2031 +phy_chain_tx_lane_map_physical{61.0}=0x0231 + +# RX lane swap +phy_chain_rx_lane_map_physical{1.0}=0x1320 +phy_chain_rx_lane_map_physical{5.0}=0x0213 +phy_chain_rx_lane_map_physical{9.0}=0x2301 +phy_chain_rx_lane_map_physical{13.0}=0x0321 + +phy_chain_rx_lane_map_physical{17.0}=0x2031 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_rx_lane_map_physical{25.0}=0x2310 +phy_chain_rx_lane_map_physical{29.0}=0x2013 + +phy_chain_rx_lane_map_physical{33.0}=0x2103 +phy_chain_rx_lane_map_physical{37.0}=0x0132 +phy_chain_rx_lane_map_physical{41.0}=0x2031 +phy_chain_rx_lane_map_physical{45.0}=0x1032 + +phy_chain_rx_lane_map_physical{49.0}=0x3201 +phy_chain_rx_lane_map_physical{53.0}=0x0132 +phy_chain_rx_lane_map_physical{57.0}=0x2031 +phy_chain_rx_lane_map_physical{61.0}=0x1032 + +# +# Tile-1 FC16~FC31 +# +portmap_34=65:40 +portmap_35=69:40 +portmap_36=73:40 +portmap_37=77:40 +portmap_38=81:40 +portmap_39=85:40 +portmap_40=89:40 +portmap_41=93:40 +portmap_42=97:40 +portmap_43=101:40 +portmap_44=105:40 +portmap_45=109:40 +portmap_46=113:40 +portmap_47=117:40 +portmap_48=121:40 +portmap_49=125:40 + +#TX polarity +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}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 + +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.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}=0x0 + +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.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}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 + +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 + +phy_chain_tx_polarity_flip_physical{89.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 + +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 + +phy_chain_tx_polarity_flip_physical{101.0}=0x1 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +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}=0x1 +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}=0x0 +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{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 + +#RX polarity +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +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{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 + +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 + +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +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}=0x0 + +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 + +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x1 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 + +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +phy_chain_rx_polarity_flip_physical{102.0}=0x0 +phy_chain_rx_polarity_flip_physical{103.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 + +phy_chain_rx_polarity_flip_physical{109.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.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}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 + +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +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}=0x0 + +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}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{65.0}=0x2130 +phy_chain_tx_lane_map_physical{69.0}=0x3012 +phy_chain_tx_lane_map_physical{73.0}=0x2031 +phy_chain_tx_lane_map_physical{77.0}=0x0231 + +phy_chain_tx_lane_map_physical{81.0}=0x2130 +phy_chain_tx_lane_map_physical{85.0}=0x1032 +phy_chain_tx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x0231 + +phy_chain_tx_lane_map_physical{97.0}=0x0123 +phy_chain_tx_lane_map_physical{101.0}=0x1320 +phy_chain_tx_lane_map_physical{105.0}=0x2301 +phy_chain_tx_lane_map_physical{109.0}=0x0213 + +phy_chain_tx_lane_map_physical{113.0}=0x0123 +phy_chain_tx_lane_map_physical{117.0}=0x1023 +phy_chain_tx_lane_map_physical{121.0}=0x2130 +phy_chain_tx_lane_map_physical{125.0}=0x1302 + +# RX lane swap +phy_chain_rx_lane_map_physical{65.0}=0x2103 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x2031 +phy_chain_rx_lane_map_physical{77.0}=0x1032 + +phy_chain_rx_lane_map_physical{81.0}=0x2103 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_rx_lane_map_physical{93.0}=0x1032 + +phy_chain_rx_lane_map_physical{97.0}=0x1023 +phy_chain_rx_lane_map_physical{101.0}=0x3120 +phy_chain_rx_lane_map_physical{105.0}=0x1023 +phy_chain_rx_lane_map_physical{109.0}=0x0231 + +phy_chain_rx_lane_map_physical{113.0}=0x1320 +phy_chain_rx_lane_map_physical{117.0}=0x3102 +phy_chain_rx_lane_map_physical{121.0}=0x0213 +phy_chain_rx_lane_map_physical{125.0}=0x0231 + +# +# Tile-2 FC32~FC47 +# +# port 66 is the first management port +portmap_66=257:10 +# port 67 is the second loopback port +#portmap_67=261:10 +portmap_68=129:40 +portmap_69=133:40 +portmap_70=137:40 +portmap_71=141:40 +portmap_72=145:40 +portmap_73=149:40 +portmap_74=153:40 +portmap_75=157:40 +portmap_76=161:40 +portmap_77=165:40 +portmap_78=169:40 +portmap_79=173:40 +portmap_80=177:40 +portmap_81=181:40 +portmap_82=185:40 +portmap_83=189:40 + +# TX polarity +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 + +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x1 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 + +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x0 + +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x0 +phy_chain_tx_polarity_flip_physical{143.0}=0x1 +phy_chain_tx_polarity_flip_physical{144.0}=0x1 + +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x1 + +phy_chain_tx_polarity_flip_physical{149.0}=0x0 +phy_chain_tx_polarity_flip_physical{150.0}=0x1 +phy_chain_tx_polarity_flip_physical{151.0}=0x1 +phy_chain_tx_polarity_flip_physical{152.0}=0x1 + +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 + +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x1 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 + +phy_chain_tx_polarity_flip_physical{161.0}=0x1 +phy_chain_tx_polarity_flip_physical{162.0}=0x0 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x1 + +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 + +phy_chain_tx_polarity_flip_physical{169.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x0 + +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x0 +phy_chain_tx_polarity_flip_physical{176.0}=0x1 + +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x0 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 + +phy_chain_tx_polarity_flip_physical{181.0}=0x1 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 + +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x0 + +phy_chain_tx_polarity_flip_physical{189.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x1 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 + +# RX polarity +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x1 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 + +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 + +phy_chain_rx_polarity_flip_physical{137.0}=0x1 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x1 + +phy_chain_rx_polarity_flip_physical{141.0}=0x0 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x1 + +phy_chain_rx_polarity_flip_physical{145.0}=0x0 +phy_chain_rx_polarity_flip_physical{146.0}=0x0 +phy_chain_rx_polarity_flip_physical{147.0}=0x1 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 + +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x1 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 + +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x0 + +phy_chain_rx_polarity_flip_physical{157.0}=0x1 +phy_chain_rx_polarity_flip_physical{158.0}=0x1 +phy_chain_rx_polarity_flip_physical{159.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 + +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 + +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x1 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x0 + +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x1 + +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x1 +phy_chain_rx_polarity_flip_physical{175.0}=0x0 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 + +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x1 + +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x1 + +phy_chain_rx_polarity_flip_physical{185.0}=0x1 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 + +phy_chain_rx_polarity_flip_physical{189.0}=0x1 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x0 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{129.0}=0x0312 +phy_chain_tx_lane_map_physical{133.0}=0x3120 +phy_chain_tx_lane_map_physical{137.0}=0x1203 +phy_chain_tx_lane_map_physical{141.0}=0x0132 + +phy_chain_tx_lane_map_physical{145.0}=0x0312 +phy_chain_tx_lane_map_physical{149.0}=0x2310 +phy_chain_tx_lane_map_physical{153.0}=0x1032 +phy_chain_tx_lane_map_physical{157.0}=0x3120 + +phy_chain_tx_lane_map_physical{161.0}=0x1023 +phy_chain_tx_lane_map_physical{165.0}=0x1203 +phy_chain_tx_lane_map_physical{169.0}=0x0213 +phy_chain_tx_lane_map_physical{173.0}=0x0123 + +phy_chain_tx_lane_map_physical{177.0}=0x2031 +phy_chain_tx_lane_map_physical{181.0}=0x1203 +phy_chain_tx_lane_map_physical{185.0}=0x0213 +phy_chain_tx_lane_map_physical{189.0}=0x3210 + +# RX lane swap +phy_chain_rx_lane_map_physical{129.0}=0x0321 +phy_chain_rx_lane_map_physical{133.0}=0x0312 +phy_chain_rx_lane_map_physical{137.0}=0x2103 +phy_chain_rx_lane_map_physical{141.0}=0x0231 + +phy_chain_rx_lane_map_physical{145.0}=0x0321 +phy_chain_rx_lane_map_physical{149.0}=0x0312 +phy_chain_rx_lane_map_physical{153.0}=0x3120 +phy_chain_rx_lane_map_physical{157.0}=0x2103 + +phy_chain_rx_lane_map_physical{161.0}=0x1032 +phy_chain_rx_lane_map_physical{165.0}=0x2031 +phy_chain_rx_lane_map_physical{169.0}=0x0132 +phy_chain_rx_lane_map_physical{173.0}=0x2103 + +phy_chain_rx_lane_map_physical{177.0}=0x1032 +phy_chain_rx_lane_map_physical{181.0}=0x1230 +phy_chain_rx_lane_map_physical{185.0}=0x0321 +phy_chain_rx_lane_map_physical{189.0}=0x3201 + +# +# Tile-3 FC48~FC63 +# portmap_0=x:xx // cpu port (not required, but included for illustration purposes) +# +# port 100 is the second management port +portmap_100=259:10 +# port 101 is the third loopback port +#portmap_101=262:10 +portmap_102=193:40 +portmap_103=197:40 +portmap_104=201:40 +portmap_105=205:40 +portmap_106=209:40 +portmap_107=213:40 +portmap_108=217:40 +portmap_109=221:40 +portmap_110=225:40 +portmap_111=229:40 +portmap_112=233:40 +portmap_113=237:40 +portmap_114=241:40 +portmap_115=245:40 +portmap_116=249:40 +portmap_117=253:40 +# port 135 is the fourth loopback port +portmap_135=263:10 + +# TX polarity +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x0 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 + +phy_chain_tx_polarity_flip_physical{197.0}=0x1 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 + +phy_chain_tx_polarity_flip_physical{201.0}=0x0 +phy_chain_tx_polarity_flip_physical{202.0}=0x0 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x0 + +phy_chain_tx_polarity_flip_physical{205.0}=0x1 +phy_chain_tx_polarity_flip_physical{206.0}=0x0 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 + +phy_chain_tx_polarity_flip_physical{209.0}=0x1 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x0 +phy_chain_tx_polarity_flip_physical{212.0}=0x1 + +phy_chain_tx_polarity_flip_physical{213.0}=0x1 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x0 + +phy_chain_tx_polarity_flip_physical{217.0}=0x0 +phy_chain_tx_polarity_flip_physical{218.0}=0x0 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 + +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x1 +phy_chain_tx_polarity_flip_physical{223.0}=0x1 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 + +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x1 +phy_chain_tx_polarity_flip_physical{227.0}=0x0 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 + +phy_chain_tx_polarity_flip_physical{229.0}=0x1 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x1 + +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x1 + +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 + +phy_chain_tx_polarity_flip_physical{241.0}=0x0 +phy_chain_tx_polarity_flip_physical{242.0}=0x1 +phy_chain_tx_polarity_flip_physical{243.0}=0x0 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 + +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x0 +phy_chain_tx_polarity_flip_physical{248.0}=0x0 + +phy_chain_tx_polarity_flip_physical{249.0}=0x0 +phy_chain_tx_polarity_flip_physical{250.0}=0x0 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 + +phy_chain_tx_polarity_flip_physical{253.0}=0x1 +phy_chain_tx_polarity_flip_physical{254.0}=0x0 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 + +# RX polarity +phy_chain_rx_polarity_flip_physical{193.0}=0x1 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 + +phy_chain_rx_polarity_flip_physical{197.0}=0x1 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x1 + +phy_chain_rx_polarity_flip_physical{201.0}=0x1 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x1 + +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x0 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 + +phy_chain_rx_polarity_flip_physical{209.0}=0x1 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x1 + +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x1 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 + +phy_chain_rx_polarity_flip_physical{217.0}=0x1 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 + +phy_chain_rx_polarity_flip_physical{221.0}=0x1 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x0 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 + +phy_chain_rx_polarity_flip_physical{225.0}=0x1 +phy_chain_rx_polarity_flip_physical{226.0}=0x1 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x0 + +phy_chain_rx_polarity_flip_physical{229.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 + +phy_chain_rx_polarity_flip_physical{233.0}=0x1 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 + +phy_chain_rx_polarity_flip_physical{237.0}=0x0 +phy_chain_rx_polarity_flip_physical{238.0}=0x1 +phy_chain_rx_polarity_flip_physical{239.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 + +phy_chain_rx_polarity_flip_physical{241.0}=0x0 +phy_chain_rx_polarity_flip_physical{242.0}=0x1 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x1 + +phy_chain_rx_polarity_flip_physical{245.0}=0x1 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x0 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 + +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x0 +phy_chain_rx_polarity_flip_physical{251.0}=0x1 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 + +phy_chain_rx_polarity_flip_physical{253.0}=0x1 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x0 + +# TX lane swap +phy_chain_tx_lane_map_physical{193.0}=0x2031 +phy_chain_tx_lane_map_physical{197.0}=0x1203 +phy_chain_tx_lane_map_physical{201.0}=0x0213 +phy_chain_tx_lane_map_physical{205.0}=0x3210 + +phy_chain_tx_lane_map_physical{209.0}=0x1023 +phy_chain_tx_lane_map_physical{213.0}=0x1203 +phy_chain_tx_lane_map_physical{217.0}=0x0213 +phy_chain_tx_lane_map_physical{221.0}=0x3102 + +phy_chain_tx_lane_map_physical{225.0}=0x2031 +phy_chain_tx_lane_map_physical{229.0}=0x1023 +phy_chain_tx_lane_map_physical{233.0}=0x1320 +phy_chain_tx_lane_map_physical{237.0}=0x2013 + +phy_chain_tx_lane_map_physical{241.0}=0x1023 +phy_chain_tx_lane_map_physical{245.0}=0x1203 +phy_chain_tx_lane_map_physical{249.0}=0x3120 +phy_chain_tx_lane_map_physical{253.0}=0x3210 + +# RX lane swap +phy_chain_rx_lane_map_physical{193.0}=0x1032 +phy_chain_rx_lane_map_physical{197.0}=0x1230 +phy_chain_rx_lane_map_physical{201.0}=0x0321 +phy_chain_rx_lane_map_physical{205.0}=0x3201 + +phy_chain_rx_lane_map_physical{209.0}=0x3201 +phy_chain_rx_lane_map_physical{213.0}=0x2031 +phy_chain_rx_lane_map_physical{217.0}=0x0321 +phy_chain_rx_lane_map_physical{221.0}=0x3201 + +phy_chain_rx_lane_map_physical{225.0}=0x2103 +phy_chain_rx_lane_map_physical{229.0}=0x2310 +phy_chain_rx_lane_map_physical{233.0}=0x0213 +phy_chain_rx_lane_map_physical{237.0}=0x1032 + +phy_chain_rx_lane_map_physical{241.0}=0x0321 +phy_chain_rx_lane_map_physical{245.0}=0x2301 +phy_chain_rx_lane_map_physical{249.0}=0x2103 +phy_chain_rx_lane_map_physical{253.0}=0x2013 + +physical_ports=64 +logical_ports=136 +uplink_ports=2 +dport_map_port_66=65 +dport_map_port_100=66 + +module_64ports=1 + +mmu_init_config="MSFT-TH2-Tier1" diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/default_sku b/device/dell/x86_64-dellemc_z9264f_c3538-r0/default_sku new file mode 100644 index 000000000000..e110b267e200 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/default_sku @@ -0,0 +1 @@ +DellEMC-Z9264f-C64 t1 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/installer.conf b/device/dell/x86_64-dellemc_z9264f_c3538-r0/installer.conf new file mode 100644 index 000000000000..924e0fb81963 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/led_proc_init.soc b/device/dell/x86_64-dellemc_z9264f_c3538-r0/led_proc_init.soc new file mode 100644 index 000000000000..d38282b6508e --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/led_proc_init.soc @@ -0,0 +1,111 @@ +# LED microprocessor initialization for DellEMC-Z9264f + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=32 REMAP_PORT_2=33 REMAP_PORT_1=34 REMAP_PORT_0=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=36 REMAP_PORT_6=37 REMAP_PORT_5=38 REMAP_PORT_4=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=4 REMAP_PORT_10=5 REMAP_PORT_9=6 REMAP_PORT_8=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0 REMAP_PORT_14=1 REMAP_PORT_13=2 REMAP_PORT_12=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=56 REMAP_PORT_18=57 REMAP_PORT_17=58 REMAP_PORT_16=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=60 REMAP_PORT_22=61 REMAP_PORT_21=62 REMAP_PORT_20=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=28 REMAP_PORT_26=29 REMAP_PORT_25=30 REMAP_PORT_24=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 REMAP_PORT_30=25 REMAP_PORT_29=26 REMAP_PORT_28=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=48 REMAP_PORT_34=49 REMAP_PORT_33=50 REMAP_PORT_32=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=52 REMAP_PORT_38=53 REMAP_PORT_37=54 REMAP_PORT_36=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=20 REMAP_PORT_42=21 REMAP_PORT_41=22 REMAP_PORT_40=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=16 REMAP_PORT_46=17 REMAP_PORT_45=18 REMAP_PORT_44=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=40 REMAP_PORT_50=41 REMAP_PORT_49=42 REMAP_PORT_48=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=44 REMAP_PORT_54=45 REMAP_PORT_53=46 REMAP_PORT_52=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12 REMAP_PORT_58=13 REMAP_PORT_57=14 REMAP_PORT_56=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=8 REMAP_PORT_62=9 REMAP_PORT_61=10 REMAP_PORT_60=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=38 REMAP_PORT_8=39 REMAP_PORT_11=36 REMAP_PORT_10=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=32 REMAP_PORT_14=33 REMAP_PORT_13=34 REMAP_PORT_12=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=8 REMAP_PORT_18=9 REMAP_PORT_17=10 REMAP_PORT_16=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=12 REMAP_PORT_22=13 REMAP_PORT_21=14 REMAP_PORT_20=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44 REMAP_PORT_26=45 REMAP_PORT_25=46 REMAP_PORT_24=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=40 REMAP_PORT_30=41 REMAP_PORT_29=42 REMAP_PORT_28=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 REMAP_PORT_34=17 REMAP_PORT_33=18 REMAP_PORT_32=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 REMAP_PORT_38=21 REMAP_PORT_37=22 REMAP_PORT_36=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 REMAP_PORT_42=53 REMAP_PORT_41=54 REMAP_PORT_40=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 REMAP_PORT_46=49 REMAP_PORT_45=50 REMAP_PORT_44=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=24 REMAP_PORT_50=25 REMAP_PORT_49=26 REMAP_PORT_48=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=28 REMAP_PORT_54=29 REMAP_PORT_53=30 REMAP_PORT_52=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=60 REMAP_PORT_58=61 REMAP_PORT_57=62 REMAP_PORT_56=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 REMAP_PORT_62=57 REMAP_PORT_61=58 REMAP_PORT_60=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=60 REMAP_PORT_2=61 REMAP_PORT_1=62 REMAP_PORT_0=63 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=56 REMAP_PORT_6=57 REMAP_PORT_5=58 REMAP_PORT_4=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=24 REMAP_PORT_10=25 REMAP_PORT_9=26 REMAP_PORT_8=27 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=28 REMAP_PORT_14=29 REMAP_PORT_13=30 REMAP_PORT_12=31 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=52 REMAP_PORT_18=53 REMAP_PORT_17=54 REMAP_PORT_16=55 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=48 REMAP_PORT_22=49 REMAP_PORT_21=50 REMAP_PORT_20=51 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16 REMAP_PORT_26=17 REMAP_PORT_25=18 REMAP_PORT_24=19 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=20 REMAP_PORT_30=21 REMAP_PORT_29=22 REMAP_PORT_28=23 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=44 REMAP_PORT_34=45 REMAP_PORT_33=46 REMAP_PORT_32=47 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=40 REMAP_PORT_38=41 REMAP_PORT_37=42 REMAP_PORT_36=43 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=8 REMAP_PORT_42=9 REMAP_PORT_41=10 REMAP_PORT_40=11 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=12 REMAP_PORT_46=13 REMAP_PORT_45=14 REMAP_PORT_44=15 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=36 REMAP_PORT_50=37 REMAP_PORT_49=38 REMAP_PORT_48=39 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=32 REMAP_PORT_54=33 REMAP_PORT_53=34 REMAP_PORT_52=35 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=0 REMAP_PORT_58=1 REMAP_PORT_57=2 REMAP_PORT_56=3 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4 REMAP_PORT_62=5 REMAP_PORT_61=6 REMAP_PORT_60=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 REMAP_PORT_2=29 REMAP_PORT_1=30 REMAP_PORT_0=31 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 REMAP_PORT_6=25 REMAP_PORT_5=26 REMAP_PORT_4=27 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 REMAP_PORT_10=57 REMAP_PORT_9=58 REMAP_PORT_8=59 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 REMAP_PORT_14=61 REMAP_PORT_13=62 REMAP_PORT_12=63 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=4 REMAP_PORT_18=5 REMAP_PORT_17=6 REMAP_PORT_16=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0 REMAP_PORT_22=1 REMAP_PORT_21=2 REMAP_PORT_20=3 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=32 REMAP_PORT_26=33 REMAP_PORT_25=34 REMAP_PORT_24=35 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36 REMAP_PORT_30=37 REMAP_PORT_29=38 REMAP_PORT_28=39 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=12 REMAP_PORT_34=13 REMAP_PORT_33=14 REMAP_PORT_32=15 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=8 REMAP_PORT_38=9 REMAP_PORT_37=10 REMAP_PORT_36=11 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 REMAP_PORT_42=41 REMAP_PORT_41=42 REMAP_PORT_40=43 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 REMAP_PORT_46=45 REMAP_PORT_45=46 REMAP_PORT_44=47 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=20 REMAP_PORT_50=21 REMAP_PORT_49=22 REMAP_PORT_48=23 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=16 REMAP_PORT_54=17 REMAP_PORT_53=18 REMAP_PORT_52=19 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48 REMAP_PORT_58=49 REMAP_PORT_57=50 REMAP_PORT_56=51 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=52 REMAP_PORT_62=53 REMAP_PORT_61=54 REMAP_PORT_60=55 +m CMIC_LEDUP4_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=1 REMAP_PORT_1=0 + +led 0 stop +led 0 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 1 auto on +led 1 start + +led 2 stop +led 2 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 2 auto on +led 2 start + +led 3 stop +led 3 prog \ + 02 00 60 FE 2E FE 67 1C 86 FE 06 FE D2 40 71 04 \ + 12 FF 85 05 D2 05 71 1A 52 00 3A 80 32 08 97 71 \ + 23 77 4B 32 00 32 01 B7 97 75 32 12 BC FE FE 02 \ + 0A 50 12 BC FE FE 95 75 3C 85 77 44 16 FF DA 02 \ + 71 4B 77 44 22 0F 87 22 0E 87 57 22 0E 87 22 0E \ + 87 57 22 0E 87 22 0F 87 57 00 00 00 00 00 00 00 +led 3 auto on +led 3 start diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/media_settings.json b/device/dell/x86_64-dellemc_z9264f_c3538-r0/media_settings.json new file mode 100644 index 000000000000..e0d81f8146c0 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/media_settings.json @@ -0,0 +1,6276 @@ +{ + "PORT_MEDIA_SETTINGS": { + "1": { + "Default": { + "preemphasis": { + "lane0": "0x15450a", + "lane1": "0x14460a", + "lane2": "0x15450a", + "lane3": "0x16440a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3402", + "lane1": "0xa3401", + "lane2": "0xc3602", + "lane3": "0xa3602" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x54802", + "lane1": "0x54802", + "lane2": "0x54802", + "lane3": "0x54802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "2": { + "Default": { + "preemphasis": { + "lane0": "0x13470a", + "lane1": "0x15450a", + "lane2": "0x15450a", + "lane3": "0x15440b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3402", + "lane1": "0x93201", + "lane2": "0x83002", + "lane3": "0x93201" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x54802", + "lane1": "0x54802", + "lane2": "0x54802", + "lane3": "0x54802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "3": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x15450a", + "lane2": "0x15450a", + "lane3": "0x13470a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3202", + "lane1": "0xb3401", + "lane2": "0xa3202", + "lane3": "0x82d00" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x54802", + "lane1": "0x54802", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "4": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x16440a", + "lane2": "0x15450a", + "lane3": "0x14460a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x93202", + "lane1": "0x93202", + "lane2": "0x83002", + "lane3": "0x93202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x54802", + "lane1": "0x54802", + "lane2": "0x54802", + "lane3": "0x54802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "5": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x14460a", + "lane2": "0x14460a", + "lane3": "0x14460a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83001", + "lane1": "0xb3401", + "lane2": "0xb3502", + "lane3": "0x83000" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x54802", + "lane1": "0x54802", + "lane2": "0x54802", + "lane3": "0x54802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "6": { + "Default": { + "preemphasis": { + "lane0": "0x13470a", + "lane1": "0x14460a", + "lane2": "0x14460a", + "lane3": "0x14460a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83001", + "lane1": "0x83002", + "lane2": "0x83002", + "lane3": "0x83001" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "7": { + "Default": { + "preemphasis": { + "lane0": "0x13470a", + "lane1": "0x13470a", + "lane2": "0x13470a", + "lane3": "0x12480a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83001", + "lane1": "0x83001", + "lane2": "0x83001", + "lane3": "0x83000" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "8": { + "Default": { + "preemphasis": { + "lane0": "0x11490a", + "lane1": "0x12480a", + "lane2": "0x12480a", + "lane3": "0x12480a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72f01", + "lane1": "0x72f00", + "lane2": "0x83001", + "lane3": "0x93601" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "9": { + "Default": { + "preemphasis": { + "lane0": "0x14430d", + "lane1": "0x13440d", + "lane2": "0x14430d", + "lane3": "0x12450d" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4610", + "lane2": "0xE4511", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4610", + "lane2": "0xE4511", + "lane3": "0xE4610" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3302", + "lane1": "0xa3000", + "lane2": "0xb3203", + "lane3": "0xb3701" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x54802", + "lane1": "0x54802", + "lane2": "0x54802", + "lane3": "0x54802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "10": { + "Default": { + "preemphasis": { + "lane0": "0x14440c", + "lane1": "0x13450c", + "lane2": "0x13470a", + "lane3": "0x12460c" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83102", + "lane1": "0x82e00", + "lane2": "0x83102", + "lane3": "0x93200" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x54802", + "lane1": "0x54802", + "lane2": "0x54802", + "lane3": "0x54802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "11": { + "Default": { + "preemphasis": { + "lane0": "0x13440d", + "lane1": "0x13460b", + "lane2": "0x13470a", + "lane3": "0x12480a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0x104311", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xE4610", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xA4B0F", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xA4B0F", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x93202", + "lane1": "0xa3202", + "lane2": "0xa3202", + "lane3": "0xa3202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x53E02", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x54102", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x54302", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x54602", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44804", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "12": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x12470b", + "lane2": "0x13470a", + "lane3": "0x12480a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83102", + "lane1": "0xa3202", + "lane2": "0xa3202", + "lane3": "0xa3202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "13": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x13460b", + "lane2": "0x13470a", + "lane3": "0x11490a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4610", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4610", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x93202", + "lane1": "0x93202", + "lane2": "0xa3202", + "lane3": "0xa3401" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "14": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x12470b", + "lane2": "0x13470a", + "lane3": "0x11490a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72e02", + "lane1": "0x73100", + "lane2": "0x73000", + "lane3": "0x73100" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "15": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x10490b", + "lane2": "0x104a0a", + "lane3": "0xf4b0a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72d01", + "lane1": "0x72d01", + "lane2": "0x73000", + "lane3": "0x83000" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "16": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x10490b", + "lane2": "0x104a0a", + "lane3": "0xf4b0a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x62a01", + "lane1": "0x62d01", + "lane2": "0x52a01", + "lane3": "0x52a01" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "17": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0xf4a0b", + "lane2": "0x104a0a", + "lane3": "0xf4b0a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72d01", + "lane1": "0x72d01", + "lane2": "0x83200", + "lane3": "0x72d01" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "18": { + "Default": { + "preemphasis": { + "lane0": "0x104a0a", + "lane1": "0xf4a0b", + "lane2": "0x104a0a", + "lane3": "0xf4a0b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72d01", + "lane1": "0x52800", + "lane2": "0x52800", + "lane3": "0x62b01" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "19": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x11480b", + "lane2": "0x13460b", + "lane3": "0x13450c" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72d02", + "lane1": "0x72d02", + "lane2": "0x72f01", + "lane3": "0x93802" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "20": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x11480b", + "lane2": "0x10490b", + "lane3": "0x11480b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72d01", + "lane1": "0x72d01", + "lane2": "0x72a02", + "lane3": "0x92f02" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "21": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x12460c", + "lane2": "0x13460b", + "lane3": "0x16430b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72d01", + "lane1": "0x93001", + "lane2": "0x82e01", + "lane3": "0x93102" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "22": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x10480c", + "lane2": "0x12470b", + "lane3": "0x13460b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x93201", + "lane1": "0x72d01", + "lane2": "0x73201", + "lane3": "0x72d01" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "23": { + "Default": { + "preemphasis": { + "lane0": "0x15440b", + "lane1": "0x15440b", + "lane2": "0x13460b", + "lane3": "0x18400c" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3201", + "lane1": "0xa3201", + "lane2": "0xa3202", + "lane3": "0xa3202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x54802", + "lane1": "0x54802", + "lane2": "0x54802", + "lane3": "0x54802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "24": { + "Default": { + "preemphasis": { + "lane0": "0x13470a", + "lane1": "0x13460b", + "lane2": "0x13460b", + "lane3": "0x14450b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xC4612", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3201", + "lane1": "0xa3202", + "lane2": "0x83000", + "lane3": "0xa3202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x54802", + "lane1": "0x54802", + "lane2": "0x54802", + "lane3": "0x54802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "25": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x11480b", + "lane2": "0x10490b", + "lane3": "0x11480b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x82d01", + "lane1": "0x82d02", + "lane2": "0x93202", + "lane3": "0x82d02" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "26": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x11480b", + "lane2": "0x11480b", + "lane3": "0x11480b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72d01", + "lane1": "0x93101", + "lane2": "0x72a00", + "lane3": "0x93402" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "27": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x14450b", + "lane2": "0x13460b", + "lane3": "0x15440b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4610", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4610", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3201", + "lane1": "0xa3202", + "lane2": "0x83000", + "lane3": "0x93602" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "28": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x14450b", + "lane2": "0x13460b", + "lane3": "0x13460b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x93202", + "lane1": "0x83001", + "lane2": "0x93202", + "lane3": "0x83001" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "29": { + "Default": { + "preemphasis": { + "lane0": "0x14450b", + "lane1": "0x14440c", + "lane2": "0x13460b", + "lane3": "0x14440c" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4610", + "lane2": "0xA4B0F", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4610", + "lane2": "0xA4B0F", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3202", + "lane1": "0xa3202", + "lane2": "0xa3202", + "lane3": "0xa3602" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x44602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x55005" + } + } + }, + "30": { + "Default": { + "preemphasis": { + "lane0": "0x14450b", + "lane1": "0x13460b", + "lane2": "0x12470b", + "lane3": "0x14450b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0x104311", + "lane2": "0xF460F", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xE4610", + "lane2": "0xD480F", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4511", + "lane2": "0xA4B0F", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4511", + "lane2": "0xA4B0F", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x82d02", + "lane1": "0x83001", + "lane2": "0x83001", + "lane3": "0x83001" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x53E02", + "lane2": "0x43704", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x54102", + "lane2": "0x43A04", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x54302", + "lane2": "0x43c04", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x44602", + "lane2": "0x43f04", + "lane3": "0x44602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44802", + "lane2": "0x44404", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x55005", + "lane2": "0x54605", + "lane3": "0x55005" + } + } + }, + "31": { + "Default": { + "preemphasis": { + "lane0": "0x15440b", + "lane1": "0x15440b", + "lane2": "0x13460b", + "lane3": "0x14430d" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4610", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4610", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xb3502", + "lane1": "0xb3501", + "lane2": "0xb3502", + "lane3": "0xa3202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "32": { + "Default": { + "preemphasis": { + "lane0": "0x14450b", + "lane1": "0x14450b", + "lane2": "0x13460b", + "lane3": "0x15440b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4610", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4610", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3402", + "lane1": "0x83000", + "lane2": "0x83000", + "lane3": "0x83202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "33": { + "Default": { + "preemphasis": { + "lane0": "0x17430a", + "lane1": "0x16440a", + "lane2": "0x15450a", + "lane3": "0x17430a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83202", + "lane1": "0x83202", + "lane2": "0x83202", + "lane3": "0x83000" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "34": { + "Default": { + "preemphasis": { + "lane0": "0x17430a", + "lane1": "0x16440a", + "lane2": "0x15450a", + "lane3": "0x17430a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0x145000" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0x145000" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xd3701", + "lane1": "0xb3501", + "lane2": "0xa3402", + "lane3": "0x92402" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "35": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x14460a", + "lane2": "0x14460a", + "lane3": "0x14460a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83000", + "lane1": "0x73201", + "lane2": "0x83202", + "lane3": "0xa3703" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "36": { + "Default": { + "preemphasis": { + "lane0": "0x15450a", + "lane1": "0x15450a", + "lane2": "0x14460a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0x104311", + "lane2": "0xF460F", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xE4610", + "lane2": "0xD480F", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4511", + "lane2": "0xA4B0F", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4511", + "lane2": "0xA4B0F", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x93901", + "lane1": "0xa3200", + "lane2": "0x83202", + "lane3": "0x82d02" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x53E02", + "lane2": "0x43704", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x54102", + "lane2": "0x43A04", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x54302", + "lane2": "0x43c04", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x54602", + "lane2": "0x43f04", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44802", + "lane2": "0x44404", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x55005", + "lane2": "0x54605", + "lane3": "0x55005" + } + } + }, + "37": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x15450a", + "lane2": "0x14460a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83200", + "lane1": "0x83200", + "lane2": "0x83200", + "lane3": "0x83200" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "38": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x15450a", + "lane2": "0x15450a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83000", + "lane1": "0xa3202", + "lane2": "0xa3202", + "lane3": "0xa3202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "39": { + "Default": { + "preemphasis": { + "lane0": "0x13470a", + "lane1": "0x15450a", + "lane2": "0x15450a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72d01", + "lane1": "0x62b01", + "lane2": "0x62b01", + "lane3": "0x82d02" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "40": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x15450a", + "lane2": "0x15450a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3401", + "lane1": "0x83000", + "lane2": "0xa3301", + "lane3": "0xa3201" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "41": { + "Default": { + "preemphasis": { + "lane0": "0x15450a", + "lane1": "0x15450a", + "lane2": "0x16440a", + "lane3": "0x18420a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xc3c00", + "lane1": "0xa3202", + "lane2": "0x93101", + "lane3": "0x72d01" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54802" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "42": { + "Default": { + "preemphasis": { + "lane0": "0x15450a", + "lane1": "0x18420a", + "lane2": "0x16440a", + "lane3": "0x18420a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4610", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4610", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3401", + "lane1": "0xa3000", + "lane2": "0xa3301", + "lane3": "0xa3201" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "43": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x15450a", + "lane2": "0x13470a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3200", + "lane1": "0x72d01", + "lane2": "0x83000", + "lane3": "0x82d03" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "44": { + "Default": { + "preemphasis": { + "lane0": "0x14460a", + "lane1": "0x15450a", + "lane2": "0x13470a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xd3c00", + "lane1": "0xa3202", + "lane2": "0xa3202", + "lane3": "0xa3202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "45": { + "Default": { + "preemphasis": { + "lane0": "0x13470a", + "lane1": "0x12480a", + "lane2": "0x13470a", + "lane3": "0x13470a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x62b01", + "lane1": "0x62b01", + "lane2": "0x62b01", + "lane3": "0x62901" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "46": { + "Default": { + "preemphasis": { + "lane0": "0xd4d0a", + "lane1": "0x12480a", + "lane2": "0x12480a", + "lane3": "0x13470a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xb3500", + "lane1": "0x82e00", + "lane2": "0x144b05", + "lane3": "0x82d03" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "47": { + "Default": { + "preemphasis": { + "lane0": "0xf4b0a", + "lane1": "0xf4b0a", + "lane2": "0x104a0a", + "lane3": "0xf4b0a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x72b02", + "lane1": "0x72b02", + "lane2": "0x52b00", + "lane3": "0x52d02" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "48": { + "Default": { + "preemphasis": { + "lane0": "0xf4b0a", + "lane1": "0xf4b0a", + "lane2": "0x11490a", + "lane3": "0xf4b0a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x52a01", + "lane1": "0x62a00", + "lane2": "0x62d00", + "lane3": "0x83202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "49": { + "Default": { + "preemphasis": { + "lane0": "0xf4b0a", + "lane1": "0xf4b0a", + "lane2": "0xf4b0a", + "lane3": "0xf4b0a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3700", + "lane1": "0x62802", + "lane2": "0x62a00", + "lane3": "0x62a00" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "50": { + "Default": { + "preemphasis": { + "lane0": "0xf4b0a", + "lane1": "0xf4b0a", + "lane2": "0x13470a", + "lane3": "0xf4b0a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x62a00", + "lane1": "0x62a00", + "lane2": "0x62a00", + "lane3": "0x82b00" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "51": { + "Default": { + "preemphasis": { + "lane0": "0x15450a", + "lane1": "0x15450a", + "lane2": "0x13470a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83000", + "lane1": "0x83201", + "lane2": "0x83201", + "lane3": "0x83000" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "52": { + "Default": { + "preemphasis": { + "lane0": "0x15450a", + "lane1": "0x16440a", + "lane2": "0x13470a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83202", + "lane1": "0x83000", + "lane2": "0x83301", + "lane3": "0x83301" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "53": { + "Default": { + "preemphasis": { + "lane0": "0x15450a", + "lane1": "0x16440a", + "lane2": "0x13470a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x93401", + "lane1": "0x83201", + "lane2": "0x83301", + "lane3": "0xa3202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "54": { + "Default": { + "preemphasis": { + "lane0": "0x15450a", + "lane1": "0x16440a", + "lane2": "0x13470a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xA4B0F", + "lane2": "0xA4B0F", + "lane3": "0xA4B0F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3201", + "lane1": "0xa3201", + "lane2": "0xa3201", + "lane3": "0xa3401" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "55": { + "Default": { + "preemphasis": { + "lane0": "0x15450a", + "lane1": "0x16440a", + "lane2": "0x13470a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3401", + "lane1": "0x83000", + "lane2": "0xa3201", + "lane3": "0xc3402" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "56": { + "Default": { + "preemphasis": { + "lane0": "0x15450a", + "lane1": "0x16440a", + "lane2": "0x13470a", + "lane3": "0x15450a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4511", + "lane1": "0xE4511", + "lane2": "0xE4511", + "lane3": "0xE4511" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3401", + "lane1": "0xb3502", + "lane2": "0xa3201", + "lane3": "0xb3502" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "57": { + "Default": { + "preemphasis": { + "lane0": "0x13470a", + "lane1": "0x13470a", + "lane2": "0x124909", + "lane3": "0x12480a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4610", + "lane2": "0xA4B0F", + "lane3": "0xC490F" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xA4B0F", + "lane1": "0xE4610", + "lane2": "0xA4B0F", + "lane3": "0xC490F" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x83000", + "lane1": "0x73000", + "lane2": "0x73000", + "lane3": "0x73000" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "58": { + "Default": { + "preemphasis": { + "lane0": "0x13470a", + "lane1": "0x12480a", + "lane2": "0x124909", + "lane3": "0x12480a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x93101", + "lane1": "0x82e01", + "lane2": "0xa3201", + "lane3": "0xa2f00" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "59": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x12480a", + "lane2": "0x114a09", + "lane3": "0x11480b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x93101", + "lane1": "0x83000", + "lane2": "0x83000", + "lane3": "0x93101" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "60": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x104a0a", + "lane2": "0x114a09", + "lane3": "0x11480b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0xF460F", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xD480F", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3501", + "lane1": "0xa3501", + "lane2": "0x83000", + "lane3": "0xa3702" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x43704", + "lane2": "0x43704", + "lane3": "0x43704" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x43A04", + "lane2": "0x43A04", + "lane3": "0x43A04" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x43c04", + "lane2": "0x43c04", + "lane3": "0x43c04" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x43f04", + "lane2": "0x43f04", + "lane3": "0x43f04" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44404", + "lane2": "0x44404", + "lane3": "0x44404" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x54605", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "61": { + "Default": { + "preemphasis": { + "lane0": "0x12480a", + "lane1": "0x12480a", + "lane2": "0x114a09", + "lane3": "0x11480b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4511", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4511", + "lane3": "0xE4610" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x93201", + "lane1": "0x83000", + "lane2": "0x83000", + "lane3": "0xa3702" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "62": { + "Default": { + "preemphasis": { + "lane0": "0x154609", + "lane1": "0x144709", + "lane2": "0x114a09", + "lane3": "0x11480b" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0xF460F", + "lane1": "0x104311", + "lane2": "0xF460F", + "lane3": "0xF460F" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xD480F", + "lane1": "0xE4610", + "lane2": "0xD480F", + "lane3": "0xD480F" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xa3501", + "lane1": "0xa3501", + "lane2": "0xb3501", + "lane3": "0xa3500" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x43704", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x43A04", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x43c04", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x43f04", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44404", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x54605", + "lane1": "0x55005", + "lane2": "0x54605", + "lane3": "0x54605" + } + } + }, + "63": { + "Default": { + "preemphasis": { + "lane0": "0x164608", + "lane1": "0x144709", + "lane2": "0x144709", + "lane3": "0x14460a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0x82e00", + "lane1": "0x72d00", + "lane2": "0xa3001", + "lane3": "0xa3001" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + }, + "64": { + "Default": { + "preemphasis": { + "lane0": "0x194209", + "lane1": "0x14460a", + "lane2": "0x14460a", + "lane3": "0x16440a" + } + }, + "QSFP28-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x104311", + "lane1": "0x104311", + "lane2": "0x104311", + "lane3": "0x104311" + } + }, + "QSFP28-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP28-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0xE4610", + "lane1": "0xE4610", + "lane2": "0xE4610", + "lane3": "0xE4610" + } + }, + "QSFP+-40GBASE-SR4": { + "preemphasis": { + "lane0": "0xd3203", + "lane1": "0xa3301", + "lane2": "0xa3201", + "lane3": "0xc3202" + } + }, + "AMPHENOL-616750000": { + "preemphasis": { + "lane0": "0x53E02", + "lane1": "0x53E02", + "lane2": "0x53E02", + "lane3": "0x53E02" + } + }, + "QSFP+-40GBASE-CR4-1M": { + "preemphasis": { + "lane0": "0x54102", + "lane1": "0x54102", + "lane2": "0x54102", + "lane3": "0x54102" + } + }, + "QSFP+-40GBASE-CR4-2M": { + "preemphasis": { + "lane0": "0x54302", + "lane1": "0x54302", + "lane2": "0x54302", + "lane3": "0x54302" + } + }, + "QSFP+-40GBASE-CR4-3M": { + "preemphasis": { + "lane0": "0x54602", + "lane1": "0x54602", + "lane2": "0x54602", + "lane3": "0x54602" + } + }, + "QSFP+-40GBASE-CR4-5M": { + "preemphasis": { + "lane0": "0x44802", + "lane1": "0x44802", + "lane2": "0x44802", + "lane3": "0x44802" + } + }, + "QSFP+-40GBASE-CR4-7M": { + "preemphasis": { + "lane0": "0x55005", + "lane1": "0x55005", + "lane2": "0x55005", + "lane3": "0x55005" + } + } + } + } +} diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/eeprom.py b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/eeprom.py new file mode 100644 index 000000000000..a38a0395d5b3 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/eeprom.py @@ -0,0 +1,29 @@ +############################################################################# +# DellEMC Z9264f +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import os.path + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = None + for b in (0, 1): + f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b) + if os.path.exists(f): + self.eeprom_path = f + break + if self.eeprom_path is None: + return + + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/psuutil.py b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/psuutil.py new file mode 100644 index 000000000000..3a58afda8df4 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/psuutil.py @@ -0,0 +1,110 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path +import logging +import sys + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + + +Z9264F_MAX_PSUS = 2 +IPMI_PSU_DATA = "docker exec -it pmon ipmitool sdr list" +IPMI_PSU_DATA_DOCKER = "ipmitool sdr list" +PSU_PRESENCE = "PSU{0}_state" +# Use this for older firmware +# PSU_PRESENCE="PSU{0}_prsnt" +ipmi_sdr_list = "" + + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def isDockerEnv(self): + num_docker = open('/proc/self/cgroup', 'r').read().count(":/docker") + if num_docker > 0: + return True + else: + return False + + # Fetch a BMC register + def get_pmc_register(self, reg_name): + + status = 1 + global ipmi_sdr_list + ipmi_dev_node = "/dev/pmi0" + ipmi_cmd = IPMI_PSU_DATA + dockerenv = self.isDockerEnv() + if dockerenv == True: + ipmi_cmd = IPMI_PSU_DATA_DOCKER + + status, ipmi_sdr_list = commands.getstatusoutput(ipmi_cmd) + + if status: + logging.error('Failed to execute:' + ipmi_sdr_list) + sys.exit(0) + + for item in ipmi_sdr_list.split("\n"): + if reg_name in item: + output = item.strip() + + if not output: + print('\nFailed to fetch: ' + reg_name + ' sensor ') + sys.exit(0) + + output = output.split('|')[1] + + logging.basicConfig(level=logging.DEBUG) + return output + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + Z9264F_MAX_PSUS = 2 + return Z9264F_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 + """ + # Until psu_status is implemented this is hardcoded temporarily + + status = 1 + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :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): + status = 1 + return status diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/sfputil.py new file mode 100644 index 000000000000..48f722a5d964 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/sfputil.py @@ -0,0 +1,645 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import io + import struct + import sys + import getopt + import time + import select + 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 sff8472InterfaceId + from sonic_sfp.sff8472 import sff8472Dom + +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# definitions of the offset and width for values in DOM info eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNL_THRESHOLD_OFFSET = 176 +QSFP_CHANNL_THRESHOLD_WIDTH = 16 +QSFP_CHANNL_MON_MASK_OFFSET = 242 +QSFP_CHANNL_MON_MASK_WIDTH = 4 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 + +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 66 + PORTS_IN_BLOCK = 64 + + BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" + OIR_FD_PATH = "/sys/bus/pci/devices/0000:04:00.0/port_msi" + + oir_fd = -1 + epoll = -1 + + _port_to_eeprom_mapping = {} + + _global_port_pres_dict = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def pci_mem_read(self, mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + reg_val = struct.unpack('I', read_data_stream) + mem_val = str(reg_val)[1:-2] + # print "reg_val read:%x"%reg_val + return mem_val + + def pci_mem_write(self, mm, offset, data): + mm.seek(offset) + # print "data to write:%x"%data + mm.write(struct.pack('I', data)) + + def pci_set_value(self, resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_write(mm, offset, val) + mm.close() + close(fd) + return val + + def pci_get_value(self, resource, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_read(mm, offset) + mm.close() + close(fd) + return val + + def init_global_port_presence(self): + for port_num in range(self.port_start, (self.port_end + 1)): + presence = self.get_presence(port_num) + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(self.port_start, self.port_end + 1): + port_num = x + 1 + self.port_to_eeprom_mapping[x] = eeprom_path.format(port_num) + port_num = 0 + self.init_global_port_presence() + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4004 + port_offset = 16388 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 4) + + # Mask off 1st bit for presence 65,66 + if (port_num > 64): + mask = (1 << 0) + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + def reset(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for reset + mask = (1 << 4) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + # Sleep 1 second to allow it to settle + time.sleep(1) + + reg_value = reg_value | mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + def get_register(self, reg_file): + retval = 'ERR' + if (not path.isfile(reg_file)): + print(reg_file + ' not found !') + return retval + + try: + with fdopen(open(reg_file, O_RDONLY)) as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", reg_file, "file !") + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + + def check_interrupts(self, port_dict): + retval = 0 + is_port_dict_updated = False + 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'): + is_port_dict_updated = True + 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'): + is_port_dict_updated = True + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + return retval, is_port_dict_updated + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + try: + # We get notified when there is a MSI interrupt (vector 4/5)CVR + # Open the sysfs file and register the epoll object + self.oir_fd = fdopen(open(self.OIR_FD_PATH, O_RDONLY)) + if self.oir_fd != -1: + # Do a dummy read before epoll register + self.oir_fd.read() + self.epoll = select.epoll() + self.epoll.register( + self.oir_fd.fileno(), select.EPOLLIN & select.EPOLLET) + else: + print("get_transceiver_change_event : unable to create fd") + return False, {} + + # Check for missed interrupts by invoking self.check_interrupts + # which will update the port_dict. + while True: + interrupt_count_start = self.get_register(self.OIR_FD_PATH) + retval, is_port_dict_updated = \ + self.check_interrupts(port_dict) + if ((retval == 0) and (is_port_dict_updated is True)): + return True, port_dict + interrupt_count_end = self.get_register(self.OIR_FD_PATH) + if (interrupt_count_start == 'ERR' or + interrupt_count_end == 'ERR'): + print("get_transceiver_change_event : \ + unable to retrive interrupt count") + break + + # check_interrupts() itself may take upto 100s of msecs. + # We detect a missed interrupt based on the count + if interrupt_count_start == interrupt_count_end: + break + + # Block until an xcvr is inserted or removed with timeout = -1 + events = self.epoll.poll( + timeout=timeout if timeout != 0 else -1) + if events: + # check interrupts and return the port_dict + retval, is_port_dict_updated = \ + self.check_interrupts(port_dict) + if (retval != 0): + return False, {} + + return True, port_dict + except: + return False, {} + finally: + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + self.oir_fd = -1 + self.epoll = -1 + + return False, {} + + 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_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 None + dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET), + SFP_TEMPE_WIDTH) + + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + else: + return transceiver_dom_info_dict + + dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VOLT_OFFSET), + SFP_VOLT_WIDTH) + + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + else: + return transceiver_dom_info_dict + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_CHANNL_MON_OFFSET), + SFP_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 + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value'] + transceiver_dom_info_dict['rx2power'] = 'N/A' + transceiver_dom_info_dict['rx3power'] = 'N/A' + transceiver_dom_info_dict['rx4power'] = 'N/A' + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + transceiver_dom_info_dict['tx2bias'] = 'N/A' + transceiver_dom_info_dict['tx3bias'] = 'N/A' + transceiver_dom_info_dict['tx4bias'] = 'N/A' + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + transceiver_dom_info_dict['tx2power'] = 'N/A' + transceiver_dom_info_dict['tx3power'] = 'N/A' + transceiver_dom_info_dict['tx4power'] = 'N/A' + + return transceiver_dom_info_dict + + def get_transceiver_dom_threshold_info_dict(self, port_num): + transceiver_dom_threshold_info_dict = {} + dom_info_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning' + ] + transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') + + if port_num in self.qsfp_ports: + file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = io.open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + # Dom Threshold data starts from offset 384 + # Revert offset back to 0 once data is retrieved + offset = 384 + dom_module_threshold_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, + (offset + QSFP_MODULE_THRESHOLD_OFFSET), + QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + dom_channel_threshold_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, + (offset + QSFP_CHANNL_THRESHOLD_OFFSET), + QSFP_CHANNL_THRESHOLD_WIDTH) + if dom_channel_threshold_raw is not None: + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + # Threshold Data + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] + + else: + offset = 256 + file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = io.open(file_path, "rb", 0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8472Dom(None, 1) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, + (offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH) + + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + # Threshold Data + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + + return transceiver_dom_threshold_info_dict diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/pmon_daemon_control.json b/device/dell/x86_64-dellemc_z9264f_c3538-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..44871c057e82 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_ledd": true, + "skip_thermalctld": true +} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/buffers.json.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..77747f6403c8 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/buffers_defaults_t0.j2 @@ -0,0 +1,20 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + }, + "BUFFER_PROFILE": { + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..77747f6403c8 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/buffers_defaults_t1.j2 @@ -0,0 +1,20 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + }, + "BUFFER_PROFILE": { + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/custom_led.bin b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/custom_led.bin new file mode 100755 index 000000000000..3ee9545e28ae Binary files /dev/null and b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/port_config.ini b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/port_config.ini new file mode 100644 index 000000000000..d7d83ae21e76 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/port_config.ini @@ -0,0 +1,35 @@ +# name lanes alias index speed +Ethernet0 33,34,35,36 hundredGigE1/1 1 100000 +Ethernet8 41,42,43,44 hundredGigE1/2 2 100000 +Ethernet16 49,50,51,52 hundredGigE1/3 3 100000 +Ethernet24 57,58,59,60 hundredGigE1/4 4 100000 +Ethernet32 65,66,67,68 hundredGigE1/5 5 100000 +Ethernet40 73,74,75,76 hundredGigE1/6 6 100000 +Ethernet48 81,82,83,84 hundredGigE1/7 7 100000 +Ethernet56 89,90,91,92 hundredGigE1/8 8 100000 +Ethernet64 1,2,3,4 hundredGigE1/9 9 100000 +Ethernet72 9,10,11,12 hundredGigE1/10 10 100000 +Ethernet80 17,18,19,20 hundredGigE1/11 11 100000 +Ethernet88 25,26,27,28 hundredGigE1/12 12 100000 +Ethernet96 97,98,99,100 hundredGigE1/13 13 100000 +Ethernet104 105,106,107,108 hundredGigE1/14 14 100000 +Ethernet112 113,114,115,116 hundredGigE1/15 15 100000 +Ethernet120 121,122,123,124 hundredGigE1/16 16 100000 +Ethernet128 129,130,131,132 hundredGigE1/17 17 100000 +Ethernet136 137,138,139,140 hundredGigE1/18 18 100000 +Ethernet144 145,146,147,148 hundredGigE1/19 19 100000 +Ethernet152 153,154,155,156 hundredGigE1/20 20 100000 +Ethernet160 225,226,227,228 hundredGigE1/21 21 100000 +Ethernet168 233,234,235,236 hundredGigE1/22 22 100000 +Ethernet176 241,242,243,244 hundredGigE1/23 23 100000 +Ethernet184 249,250,251,252 hundredGigE1/24 24 100000 +Ethernet192 161,162,163,164 hundredGigE1/25 25 100000 +Ethernet200 169,170,171,172 hundredGigE1/26 26 100000 +Ethernet208 177,178,179,180 hundredGigE1/27 27 100000 +Ethernet216 185,186,187,188 hundredGigE1/28 28 100000 +Ethernet224 193,194,195,196 hundredGigE1/29 29 100000 +Ethernet232 201,202,203,204 hundredGigE1/30 30 100000 +Ethernet240 209,210,211,212 hundredGigE1/31 31 100000 +Ethernet248 217,218,219,220 hundredGigE1/32 32 100000 +Ethernet256 257 tenGigE1/33 33 10000 +Ethernet257 258 tenGigE1/34 34 10000 diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/qos.json.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/qos.json.j2 new file mode 100644 index 000000000000..f6b7ac977f7b --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/qos.json.j2 @@ -0,0 +1,225 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "0", + "4": "0", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "STRICT" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/qos.json.j2.pfc.reference b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/qos.json.j2.pfc.reference new file mode 100644 index 000000000000..1756f106cc71 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/qos.json.j2.pfc.reference @@ -0,0 +1,227 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "3", + "4": "4", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "STRICT" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "pfc_enable" : "3,4", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|DEFAULT]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/sai.profile b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/sai.profile new file mode 100644 index 000000000000..bdc55873e429 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-z9332f-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/sai_postinit_cmd.soc b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/sai_postinit_cmd.soc new file mode 100644 index 000000000000..52793ea0147f --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/sai_postinit_cmd.soc @@ -0,0 +1,995 @@ +delay 200 +link off +counter off +local port ce0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x46 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1EC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x48 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1EC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce1 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x46 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce2 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x48 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce3 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x36 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce4 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce5 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x36 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce6 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x38 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce7 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x36 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x42 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce8 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x48 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce9 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x46 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce10 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x46 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce11 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x3A +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce12 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x3A +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x36 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x3A +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce13 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x32 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x34 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x32 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce14 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x32 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x34 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x30 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x32 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce15 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x30 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x32 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x2C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x2C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce16 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x36 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x32 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x30 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x30 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce17 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x30 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x36 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x32 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x32 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce18 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x36 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x38 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x32 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x32 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce19 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x3A +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x3A +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x34 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x36 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce20 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x48 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + + +delay 10 +local port ce21 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x42 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce22 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x48 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1EC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x42 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce23 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x48 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce24 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x42 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x42 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x3A +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce25 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x42 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x38 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce26 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce27 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x3E +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce28 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x3C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce29 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce30 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x48 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1EC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x46 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F6 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +delay 10 +local port ce31 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x40 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x4E +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1EC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x44 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1FC +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x46 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 +link on +counter on diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/sai_preinit_cmd.soc new file mode 100644 index 000000000000..920cd33016b4 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/sai_preinit_cmd.soc @@ -0,0 +1,3 @@ +#Not supported in current SAI version +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_z9332f_d1508-r0/DellEMC-Z9332f-C32/th3-z9332f-32x100G.config.bcm b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/th3-z9332f-32x100G.config.bcm new file mode 100644 index 000000000000..67a24de577d4 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-C32/th3-z9332f-32x100G.config.bcm @@ -0,0 +1,519 @@ +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 + +ccm_dma_enable=0 +ccmdma_intr_enable=0 +mem_cache_enable=1 +phy_enable=0 +phy_null=1 + +dport_map_enable=1 + +module_64ports.0=0 +tdma_intr_enable.0=1 +ipv6_lpm_128b_enable.0=1 +stat_if_parity_enable.0=1 +oversubscribe_mode=0 +bcm_tunnel_term_compatible_mode.0=1 +table_dma_enable.0=1 +schan_intr_enable.0=0 +parity_enable.0=1 +tdma_timeout_usec=1000000 +lls_num_l2uc.0=10 +miim_intr_enable.0=0 +table_dma_enable=1 +max_vp_lags.0=0 +tdma_intr_enable=1 +tdma_timeout_usec.0=5000000 +parity_correction.0=1 +mmu_lossless.0=0 +bcm_num_cos=10 +default_cpu_tx_queue=7 +pktdma_poll_mode_channel_bitmap=1 +l3_max_ecmp_mode.0=1 +l3_alpm_enable=2 +l3_alpm_ipv6_128b_bkt_rsvd=1 +l2_mem_entries=40960 +l3_mem_entries=40960 + +l2xlrn_thread_interval=50000 +l2xlrn_intr_en=0 + +pbmp_xport_xe=0x1ffffffFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE + +phy_an_c73=3 + +portmap_1.0=1:100:4 +portmap_5.0=9:100:4 +portmap_10.0=17:100:4 +portmap_14.0=25:100:4 + +portmap_20.0=33:100:4 +portmap_24.0=41:100:4 +portmap_29.0=49:100:4 +portmap_33.0=57:100:4 + +portmap_40.0=65:100:4 +portmap_44.0=73:100:4 +portmap_49.0=81:100:4 +portmap_53.0=89:100:4 + +portmap_60.0=97:100:4 +portmap_64.0=105:100:4 +portmap_69.0=113:100:4 +portmap_73.0=121:100:4 + +portmap_80.0=129:100:4 +portmap_84.0=137:100:4 +portmap_89.0=145:100:4 +portmap_93.0=153:100:4 + +portmap_100.0=161:100:4 +portmap_104.0=169:100:4 +portmap_109.0=177:100:4 +portmap_113.0=185:100:4 + +portmap_120.0=193:100:4 +portmap_124.0=201:100:4 +portmap_129.0=209:100:4 +portmap_133.0=217:100:4 + +portmap_140.0=225:100:4 +portmap_144.0=233:100:4 +portmap_149.0=241:100:4 +portmap_153.0=249:100:4 + +portmap_38.0=257:10:1 +portmap_118.0=258:10:1 + +dport_map_port_20=1 +dport_map_port_21=2 +dport_map_port_22=3 +dport_map_port_23=4 +dport_map_port_24=5 +dport_map_port_25=6 +dport_map_port_26=7 +dport_map_port_27=8 +dport_map_port_28=9 +dport_map_port_29=10 +dport_map_port_30=11 +dport_map_port_31=12 +dport_map_port_32=13 +dport_map_port_33=14 +dport_map_port_34=15 +dport_map_port_35=16 +dport_map_port_36=17 +dport_map_port_37=18 +dport_map_port_40=19 +dport_map_port_41=20 +dport_map_port_42=21 +dport_map_port_43=22 +dport_map_port_44=23 +dport_map_port_45=24 +dport_map_port_46=25 +dport_map_port_47=26 +dport_map_port_48=27 +dport_map_port_49=28 +dport_map_port_50=29 +dport_map_port_51=30 +dport_map_port_52=31 +dport_map_port_53=32 +dport_map_port_54=33 +dport_map_port_55=34 +dport_map_port_56=35 +dport_map_port_57=36 +dport_map_port_1=37 +dport_map_port_2=38 +dport_map_port_3=39 +dport_map_port_4=40 +dport_map_port_5=41 +dport_map_port_6=42 +dport_map_port_7=43 +dport_map_port_8=44 +dport_map_port_9=45 +dport_map_port_10=46 +dport_map_port_11=47 +dport_map_port_12=48 +dport_map_port_13=49 +dport_map_port_14=50 +dport_map_port_15=51 +dport_map_port_16=52 +dport_map_port_17=53 +dport_map_port_18=54 +dport_map_port_60=55 +dport_map_port_61=56 +dport_map_port_62=57 +dport_map_port_63=58 +dport_map_port_64=59 +dport_map_port_65=60 +dport_map_port_66=61 +dport_map_port_67=62 +dport_map_port_68=63 +dport_map_port_69=64 +dport_map_port_70=65 +dport_map_port_71=66 +dport_map_port_72=67 +dport_map_port_73=68 +dport_map_port_74=69 +dport_map_port_75=70 +dport_map_port_76=71 +dport_map_port_77=72 +dport_map_port_80=73 +dport_map_port_81=74 +dport_map_port_82=75 +dport_map_port_83=76 +dport_map_port_84=77 +dport_map_port_85=78 +dport_map_port_86=79 +dport_map_port_87=80 +dport_map_port_88=81 +dport_map_port_89=82 +dport_map_port_90=83 +dport_map_port_91=84 +dport_map_port_92=85 +dport_map_port_93=86 +dport_map_port_94=87 +dport_map_port_95=88 +dport_map_port_96=89 +dport_map_port_97=90 +dport_map_port_140=91 +dport_map_port_141=92 +dport_map_port_142=93 +dport_map_port_143=94 +dport_map_port_144=95 +dport_map_port_145=96 +dport_map_port_146=97 +dport_map_port_147=98 +dport_map_port_148=99 +dport_map_port_149=100 +dport_map_port_150=101 +dport_map_port_151=102 +dport_map_port_152=103 +dport_map_port_153=104 +dport_map_port_154=105 +dport_map_port_155=106 +dport_map_port_156=107 +dport_map_port_157=108 +dport_map_port_100=109 +dport_map_port_101=110 +dport_map_port_102=111 +dport_map_port_103=112 +dport_map_port_104=113 +dport_map_port_105=114 +dport_map_port_106=115 +dport_map_port_107=116 +dport_map_port_108=117 +dport_map_port_109=118 +dport_map_port_110=119 +dport_map_port_111=120 +dport_map_port_112=121 +dport_map_port_113=122 +dport_map_port_114=123 +dport_map_port_115=124 +dport_map_port_116=125 +dport_map_port_117=126 +dport_map_port_120=127 +dport_map_port_121=128 +dport_map_port_122=129 +dport_map_port_123=130 +dport_map_port_124=131 +dport_map_port_125=132 +dport_map_port_126=133 +dport_map_port_127=134 +dport_map_port_128=135 +dport_map_port_129=136 +dport_map_port_130=137 +dport_map_port_131=138 +dport_map_port_132=139 +dport_map_port_133=140 +dport_map_port_134=141 +dport_map_port_135=142 +dport_map_port_136=143 +dport_map_port_137=144 +dport_map_port_38=145 +dport_map_port_118=146 + +phy_chain_rx_lane_map_physical{33.0}=0x65732041 +phy_chain_tx_lane_map_physical{33.0}=0x47206531 +phy_chain_rx_lane_map_physical{41.0}=0x07561243 +phy_chain_tx_lane_map_physical{41.0}=0x36207514 +phy_chain_rx_lane_map_physical{49.0}=0x54632071 +phy_chain_tx_lane_map_physical{49.0}=0x06241735 +phy_chain_rx_lane_map_physical{57.0}=0x07561243 +phy_chain_tx_lane_map_physical{57.0}=0x35207614 +phy_chain_rx_lane_map_physical{65.0}=0x45623170 +phy_chain_tx_lane_map_physical{65.0}=0x51260734 +phy_chain_rx_lane_map_physical{73.0}=0x07561243 +phy_chain_tx_lane_map_physical{73.0}=0x37245610 +phy_chain_rx_lane_map_physical{81.0}=0x45632071 +phy_chain_tx_lane_map_physical{81.0}=0x51260734 +phy_chain_rx_lane_map_physical{89.0}=0x07561243 +phy_chain_tx_lane_map_physical{89.0}=0x26437510 +phy_chain_rx_lane_map_physical{1.0}=0x30176524 +phy_chain_tx_lane_map_physical{1.0}=0x20615374 +phy_chain_rx_lane_map_physical{9.0}=0x37562041 +phy_chain_tx_lane_map_physical{9.0}=0x05176432 +phy_chain_rx_lane_map_physical{17.0}=0x43607251 +phy_chain_tx_lane_map_physical{17.0}=0x70261435 +phy_chain_rx_lane_map_physical{25.0}=0x60347125 +phy_chain_tx_lane_map_physical{25.0}=0x46357120 +phy_chain_rx_lane_map_physical{97.0}=0x47601352 +phy_chain_tx_lane_map_physical{97.0}=0x04265137 +phy_chain_rx_lane_map_physical{105.0}=0x73206415 +phy_chain_tx_lane_map_physical{105.0}=0x26374150 +phy_chain_rx_lane_map_physical{113.0}=0x47632051 +phy_chain_tx_lane_map_physical{113.0}=0x03254617 +phy_chain_rx_lane_map_physical{121.0}=0x63027415 +phy_chain_tx_lane_map_physical{121.0}=0x63721045 +phy_chain_rx_lane_map_physical{129.0}=0x30154627 +phy_chain_tx_lane_map_physical{129.0}=0x04735261 +phy_chain_rx_lane_map_physical{137.0}=0x24753061 +phy_chain_tx_lane_map_physical{137.0}=0x37614520 +phy_chain_rx_lane_map_physical{145.0}=0x47601352 +phy_chain_tx_lane_map_physical{145.0}=0x63274510 +phy_chain_rx_lane_map_physical{153.0}=0x07361524 +phy_chain_tx_lane_map_physical{153.0}=0x36527104 +phy_chain_rx_lane_map_physical{225.0}=0x56410273 +phy_chain_tx_lane_map_physical{225.0}=0x10274635 +phy_chain_rx_lane_map_physical{233.0}=0x15740263 +phy_chain_tx_lane_map_physical{233.0}=0x24351607 +phy_chain_rx_lane_map_physical{241.0}=0x74015263 +phy_chain_tx_lane_map_physical{241.0}=0x04152637 +phy_chain_rx_lane_map_physical{249.0}=0x62037514 +phy_chain_tx_lane_map_physical{249.0}=0x72453160 +phy_chain_rx_lane_map_physical{161.0}=0x46510273 +phy_chain_tx_lane_map_physical{161.0}=0x01653724 +phy_chain_rx_lane_map_physical{169.0}=0x25743160 +phy_chain_tx_lane_map_physical{169.0}=0x07216435 +phy_chain_rx_lane_map_physical{177.0}=0x46510273 +phy_chain_tx_lane_map_physical{177.0}=0x01652734 +phy_chain_rx_lane_map_physical{185.0}=0x25743160 +phy_chain_tx_lane_map_physical{185.0}=0x37016425 +phy_chain_rx_lane_map_physical{193.0}=0x46510372 +phy_chain_tx_lane_map_physical{193.0}=0x06153724 +phy_chain_rx_lane_map_physical{201.0}=0x25743160 +phy_chain_tx_lane_map_physical{201.0}=0x36017524 +phy_chain_rx_lane_map_physical{209.0}=0x47601352 +phy_chain_tx_lane_map_physical{209.0}=0x04152736 +phy_chain_rx_lane_map_physical{217.0}=0x26453170 +phy_chain_tx_lane_map_physical{217.0}=0x36027415 + +serdes_core_rx_polarity_flip_physical{33}=0x29 +serdes_core_tx_polarity_flip_physical{33}=0xfe +serdes_core_rx_polarity_flip_physical{41}=0xb1 +serdes_core_tx_polarity_flip_physical{41}=0xe8 +serdes_core_rx_polarity_flip_physical{49}=0xca +serdes_core_tx_polarity_flip_physical{49}=0xb6 +serdes_core_rx_polarity_flip_physical{57}=0x9b +serdes_core_tx_polarity_flip_physical{57}=0xdc +serdes_core_rx_polarity_flip_physical{65}=0x17 +serdes_core_tx_polarity_flip_physical{65}=0x86 +serdes_core_rx_polarity_flip_physical{73}=0x9b +serdes_core_tx_polarity_flip_physical{73}=0x55 +serdes_core_rx_polarity_flip_physical{81}=0xa +serdes_core_tx_polarity_flip_physical{81}=0x6 +serdes_core_rx_polarity_flip_physical{89}=0x9b +serdes_core_tx_polarity_flip_physical{89}=0x48 +serdes_core_rx_polarity_flip_physical{1}=0xec +serdes_core_tx_polarity_flip_physical{1}=0x56 +serdes_core_rx_polarity_flip_physical{9}=0x13 +serdes_core_tx_polarity_flip_physical{9}=0xa6 +serdes_core_rx_polarity_flip_physical{17}=0x5a +serdes_core_tx_polarity_flip_physical{17}=0xc6 +serdes_core_rx_polarity_flip_physical{25}=0xf +serdes_core_tx_polarity_flip_physical{25}=0x4e +serdes_core_rx_polarity_flip_physical{97}=0x17 +serdes_core_tx_polarity_flip_physical{97}=0x2e +serdes_core_rx_polarity_flip_physical{105}=0xce +serdes_core_tx_polarity_flip_physical{105}=0x7c +serdes_core_rx_polarity_flip_physical{113}=0xa +serdes_core_tx_polarity_flip_physical{113}=0x35 + +serdes_core_rx_polarity_flip_physical{121}=0xb9 +serdes_core_tx_polarity_flip_physical{121}=0xef +serdes_core_rx_polarity_flip_physical{129}=0xe8 +serdes_core_tx_polarity_flip_physical{129}=0xac +serdes_core_rx_polarity_flip_physical{137}=0xcb +serdes_core_tx_polarity_flip_physical{137}=0x9c +serdes_core_rx_polarity_flip_physical{145}=0x17 +serdes_core_tx_polarity_flip_physical{145}=0x32 +serdes_core_rx_polarity_flip_physical{153}=0xb9 +serdes_core_tx_polarity_flip_physical{153}=0xaf +serdes_core_rx_polarity_flip_physical{225}=0xaa +serdes_core_tx_polarity_flip_physical{225}=0x7 +serdes_core_rx_polarity_flip_physical{233}=0x31 +serdes_core_tx_polarity_flip_physical{233}=0x47 +serdes_core_rx_polarity_flip_physical{241}=0xe8 +serdes_core_tx_polarity_flip_physical{241}=0x9e +serdes_core_rx_polarity_flip_physical{249}=0xec +serdes_core_tx_polarity_flip_physical{249}=0x1f +serdes_core_rx_polarity_flip_physical{161}=0x6a +serdes_core_tx_polarity_flip_physical{161}=0xd4 +serdes_core_rx_polarity_flip_physical{169}=0x9e +serdes_core_tx_polarity_flip_physical{169}=0x7b +serdes_core_rx_polarity_flip_physical{177}=0x6a +serdes_core_tx_polarity_flip_physical{177}=0xcc +serdes_core_rx_polarity_flip_physical{185}=0x9e +serdes_core_tx_polarity_flip_physical{185}=0x58 +serdes_core_rx_polarity_flip_physical{193}=0x6f +serdes_core_tx_polarity_flip_physical{193}=0x24 +serdes_core_rx_polarity_flip_physical{201}=0x9e +serdes_core_tx_polarity_flip_physical{201}=0xdf +serdes_core_rx_polarity_flip_physical{209}=0x17 +serdes_core_tx_polarity_flip_physical{209}=0xe9 +serdes_core_rx_polarity_flip_physical{217}=0xec +serdes_core_tx_polarity_flip_physical{217}=0x68 + +serdes_lane_config_media_type_49=copper +serdes_lane_config_media_type_50=copper +serdes_lane_config_media_type_51=copper +serdes_lane_config_media_type_52=copper +serdes_lane_config_media_type_54=copper +serdes_lane_config_media_type_55=copper +serdes_lane_config_media_type_56=copper +serdes_lane_config_media_type_57=copper +serdes_lane_config_media_type_53=copper +serdes_lane_config_media_type_60=copper +serdes_lane_config_media_type_61=copper +serdes_lane_config_media_type_62=copper +serdes_lane_config_media_type_63=copper +serdes_lane_config_media_type_65=copper +serdes_lane_config_media_type_66=copper +serdes_lane_config_media_type_67=copper +serdes_lane_config_media_type_68=copper +serdes_lane_config_media_type_64=copper +serdes_lane_config_media_type_80=copper +serdes_lane_config_media_type_81=copper +serdes_lane_config_media_type_82=copper +serdes_lane_config_media_type_83=copper +serdes_lane_config_media_type_85=copper +serdes_lane_config_media_type_86=copper +serdes_lane_config_media_type_87=copper +serdes_lane_config_media_type_88=copper +serdes_lane_config_media_type_84=copper +serdes_lane_config_media_type_100=copper +serdes_lane_config_media_type_101=copper +serdes_lane_config_media_type_102=copper +serdes_lane_config_media_type_103=copper +serdes_lane_config_media_type_105=copper +serdes_lane_config_media_type_106=copper +serdes_lane_config_media_type_107=copper +serdes_lane_config_media_type_108=copper +serdes_lane_config_media_type_104=copper +serdes_lane_config_media_type_120=copper +serdes_lane_config_media_type_121=copper +serdes_lane_config_media_type_122=copper +serdes_lane_config_media_type_123=copper +serdes_lane_config_media_type_125=copper +serdes_lane_config_media_type_126=copper +serdes_lane_config_media_type_127=copper +serdes_lane_config_media_type_128=copper +serdes_lane_config_media_type_124=copper +serdes_lane_config_media_type_140=copper +serdes_lane_config_media_type_141=copper +serdes_lane_config_media_type_142=copper +serdes_lane_config_media_type_143=copper +serdes_lane_config_media_type_145=copper +serdes_lane_config_media_type_146=copper +serdes_lane_config_media_type_147=copper +serdes_lane_config_media_type_148=copper +serdes_lane_config_media_type_144=copper +serdes_lane_config_media_type_40=copper +serdes_lane_config_media_type_41=copper +serdes_lane_config_media_type_42=copper +serdes_lane_config_media_type_43=copper +serdes_lane_config_media_type_45=copper +serdes_lane_config_media_type_46=copper +serdes_lane_config_media_type_47=copper +serdes_lane_config_media_type_48=copper +serdes_lane_config_media_type_44=copper +serdes_lane_config_media_type_69=copper +serdes_lane_config_media_type_70=copper +serdes_lane_config_media_type_71=copper +serdes_lane_config_media_type_72=copper +serdes_lane_config_media_type_74=copper +serdes_lane_config_media_type_75=copper +serdes_lane_config_media_type_76=copper +serdes_lane_config_media_type_77=copper +serdes_lane_config_media_type_73=copper +serdes_lane_config_media_type_1=copper +serdes_lane_config_media_type_2=copper +serdes_lane_config_media_type_3=copper +serdes_lane_config_media_type_4=copper +serdes_lane_config_media_type_6=copper +serdes_lane_config_media_type_7=copper +serdes_lane_config_media_type_8=copper +serdes_lane_config_media_type_9=copper +serdes_lane_config_media_type_5=copper +serdes_lane_config_media_type_29=copper +serdes_lane_config_media_type_30=copper +serdes_lane_config_media_type_31=copper +serdes_lane_config_media_type_32=copper +serdes_lane_config_media_type_34=copper +serdes_lane_config_media_type_35=copper +serdes_lane_config_media_type_36=copper +serdes_lane_config_media_type_37=copper +serdes_lane_config_media_type_33=copper +serdes_lane_config_media_type_89=copper +serdes_lane_config_media_type_90=copper +serdes_lane_config_media_type_91=copper +serdes_lane_config_media_type_92=copper +serdes_lane_config_media_type_94=copper +serdes_lane_config_media_type_95=copper +serdes_lane_config_media_type_96=copper +serdes_lane_config_media_type_97=copper +serdes_lane_config_media_type_93=copper +serdes_lane_config_media_type_109=copper +serdes_lane_config_media_type_110=copper +serdes_lane_config_media_type_111=copper +serdes_lane_config_media_type_112=copper +serdes_lane_config_media_type_114=copper +serdes_lane_config_media_type_115=copper +serdes_lane_config_media_type_116=copper +serdes_lane_config_media_type_117=copper +serdes_lane_config_media_type_113=copper +serdes_lane_config_media_type_129=copper +serdes_lane_config_media_type_130=copper +serdes_lane_config_media_type_131=copper +serdes_lane_config_media_type_132=copper +serdes_lane_config_media_type_134=copper +serdes_lane_config_media_type_135=copper +serdes_lane_config_media_type_136=copper +serdes_lane_config_media_type_137=copper +serdes_lane_config_media_type_133=copper +serdes_lane_config_media_type_149=copper +serdes_lane_config_media_type_150=copper +serdes_lane_config_media_type_151=copper +serdes_lane_config_media_type_152=copper +serdes_lane_config_media_type_154=copper +serdes_lane_config_media_type_155=copper +serdes_lane_config_media_type_156=copper +serdes_lane_config_media_type_157=copper +serdes_lane_config_media_type_153=copper +serdes_lane_config_media_type_10=copper +serdes_lane_config_media_type_11=copper +serdes_lane_config_media_type_12=copper +serdes_lane_config_media_type_13=copper +serdes_lane_config_media_type_15=copper +serdes_lane_config_media_type_16=copper +serdes_lane_config_media_type_17=copper +serdes_lane_config_media_type_18=copper +serdes_lane_config_media_type_14=copper +serdes_lane_config_media_type_20=copper +serdes_lane_config_media_type_21=copper +serdes_lane_config_media_type_22=copper +serdes_lane_config_media_type_23=copper +serdes_lane_config_media_type_25=copper +serdes_lane_config_media_type_26=copper +serdes_lane_config_media_type_27=copper +serdes_lane_config_media_type_28=copper +serdes_lane_config_media_type_24=copper + +#sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc + diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers.json.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..77747f6403c8 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t0.j2 @@ -0,0 +1,20 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + }, + "BUFFER_PROFILE": { + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..77747f6403c8 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t1.j2 @@ -0,0 +1,20 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + }, + "BUFFER_PROFILE": { + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/custom_led.bin b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/custom_led.bin new file mode 100755 index 000000000000..3ee9545e28ae Binary files /dev/null and b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/pg_profile_lookup.ini b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/pg_profile_lookup.ini new file mode 100644 index 000000000000..a5f3286beef8 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/pg_profile_lookup.ini @@ -0,0 +1,23 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1270 0 190500 -2 2540 + 25000 5m 1270 0 190500 -2 2540 + 40000 5m 1270 0 190500 -2 2540 + 50000 5m 1270 0 190500 -2 2540 + 100000 5m 1270 0 190500 -2 2540 + 200000 5m 1270 0 190500 -2 2540 + 400000 5m 1270 0 190500 -2 2540 + 10000 40m 1270 0 190500 -2 2540 + 25000 40m 1270 0 190500 -2 2540 + 40000 40m 1270 0 190500 -2 2540 + 50000 40m 1270 0 190500 -2 2540 + 100000 40m 1270 0 190500 -2 2540 + 200000 40m 1270 0 190500 -2 2540 + 400000 40m 1270 0 190500 -2 2540 + 10000 300m 1270 0 190500 -2 2540 + 25000 300m 1270 0 190500 -2 2540 + 40000 300m 1270 0 190500 -2 2540 + 50000 300m 1270 0 190500 -2 2540 + 100000 300m 1270 0 190500 -2 2540 + 200000 300m 1270 0 190500 -2 2540 + 400000 300m 1270 0 190500 -2 2540 diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/port_config.ini b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/port_config.ini new file mode 100644 index 000000000000..542992d761a6 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/port_config.ini @@ -0,0 +1,83 @@ +# name lanes alias index speed +Ethernet0 33,34 hundredGigE1/1/1 1 100000 +Ethernet2 35,36 hundredGigE1/1/2 1 100000 +Ethernet4 37,38 hundredGigE1/1/3 1 100000 +Ethernet6 39,40 hundredGigE1/1/4 1 100000 +Ethernet8 41,42 hundredGigE1/2/1 2 100000 +Ethernet10 43,44 hundredGigE1/2/2 2 100000 +Ethernet12 45,46 hundredGigE1/2/3 2 100000 +Ethernet14 47,48 hundredGigE1/2/4 2 100000 +Ethernet16 49,50 hundredGigE1/3/1 3 100000 +Ethernet18 51,52 hundredGigE1/3/2 3 100000 +Ethernet20 53,54 hundredGigE1/3/3 3 100000 +Ethernet22 55,56 hundredGigE1/3/4 3 100000 +Ethernet24 57,58 hundredGigE1/4/1 4 100000 +Ethernet26 59,60 hundredGigE1/4/2 4 100000 +Ethernet28 61,62 hundredGigE1/4/3 4 100000 +Ethernet30 63,64 hundredGigE1/4/4 4 100000 +Ethernet32 65,66,67,68,69,70,71,72 fourhundredGigE1/5 5 400000 +Ethernet40 73,74,75,76,77,78,79,80 fourhundredGigE1/6 6 400000 +Ethernet48 81,82,83,84,85,86,87,88 fourhundredGigE1/7 7 400000 +Ethernet56 89,90,91,92,93,94,95,96 fourhundredGigE1/8 8 400000 +Ethernet64 1,2 hundredGigE1/9/1 9 100000 +Ethernet66 3,4 hundredGigE1/9/2 9 100000 +Ethernet68 5,6 hundredGigE1/9/3 9 100000 +Ethernet70 7,8 hundredGigE1/9/4 9 100000 +Ethernet72 9,10 hundredGigE1/10/1 10 100000 +Ethernet74 11,12 hundredGigE1/10/2 10 100000 +Ethernet76 13,14 hundredGigE1/10/3 10 100000 +Ethernet78 15,16 hundredGigE1/10/4 10 100000 +Ethernet80 17,18 hundredGigE1/11/1 11 100000 +Ethernet82 19,20 hundredGigE1/11/2 11 100000 +Ethernet84 21,22 hundredGigE1/11/3 11 100000 +Ethernet86 23,24 hundredGigE1/11/4 11 100000 +Ethernet88 25,26 hundredGigE1/12/1 12 100000 +Ethernet90 27,28 hundredGigE1/12/2 12 100000 +Ethernet92 29,30 hundredGigE1/12/3 12 100000 +Ethernet94 31,32 hundredGigE1/12/4 12 100000 +Ethernet96 97,98,99,100,101,102,103,104 fourhundredGigE1/13 13 400000 +Ethernet104 105,106,107,108,109,110,111,112 fourhundredGigE1/14 14 400000 +Ethernet112 113,114,115,116,117,118,119,120 fourhundredGigE1/15 15 400000 +Ethernet120 121,122,123,124,125,126,127,128 fourhundredGigE1/16 16 400000 +Ethernet128 129,130,131,132,133,134,135,136 fourhundredGigE1/17 17 400000 +Ethernet136 137,138,139,140,141,142,143,144 fourhundredGigE1/18 18 400000 +Ethernet144 145,146,147,148,149,150,151,152 fourhundredGigE1/19 19 400000 +Ethernet152 153,154,155,156,157,158,159,160 fourhundredGigE1/20 20 400000 +Ethernet160 225,226 hundredGigE1/21/1 21 100000 +Ethernet162 227,228 hundredGigE1/21/2 21 100000 +Ethernet164 229,230 hundredGigE1/21/3 21 100000 +Ethernet166 231,232 hundredGigE1/21/4 21 100000 +Ethernet168 233,234 hundredGigE1/22/1 22 100000 +Ethernet170 235,236 hundredGigE1/22/2 22 100000 +Ethernet172 237,238 hundredGigE1/22/3 22 100000 +Ethernet174 239,240 hundredGigE1/22/4 22 100000 +Ethernet176 241,242 hundredGigE1/23/1 23 100000 +Ethernet178 243,244 hundredGigE1/23/2 23 100000 +Ethernet180 245,246 hundredGigE1/23/3 23 100000 +Ethernet182 247,248 hundredGigE1/23/4 23 100000 +Ethernet184 249,250 hundredGigE1/24/1 24 100000 +Ethernet186 251,252 hundredGigE1/24/2 24 100000 +Ethernet188 253,254 hundredGigE1/24/3 24 100000 +Ethernet190 255,256 hundredGigE1/24/4 24 100000 +Ethernet192 161,162,163,164,165,166,167,168 fourhundredGigE1/25 25 400000 +Ethernet200 169,170,171,172,173,174,175,176 fourhundredGigE1/26 26 400000 +Ethernet208 177,178,179,180,181,182,183,184 fourhundredGigE1/27 27 400000 +Ethernet216 185,186,187,188,189,190,191,192 fourhundredGigE1/28 28 400000 +Ethernet224 193,194 hundredGigE1/29/1 29 100000 +Ethernet226 195,196 hundredGigE1/29/2 29 100000 +Ethernet228 197,198 hundredGigE1/29/3 29 100000 +Ethernet230 199,200 hundredGigE1/29/4 29 100000 +Ethernet232 201,202 hundredGigE1/30/1 30 100000 +Ethernet234 203,204 hundredGigE1/30/2 30 100000 +Ethernet236 205,206 hundredGigE1/30/3 30 100000 +Ethernet238 207,208 hundredGigE1/30/4 30 100000 +Ethernet240 209,210 hundredGigE1/31/1 31 100000 +Ethernet242 211,212 hundredGigE1/31/2 31 100000 +Ethernet244 213,214 hundredGigE1/31/3 31 100000 +Ethernet246 215,216 hundredGigE1/31/4 31 100000 +Ethernet248 217,218 hundredGigE1/32/1 32 100000 +Ethernet250 219,220 hundredGigE1/32/2 32 100000 +Ethernet252 221,222 hundredGigE1/32/3 32 100000 +Ethernet254 223,224 hundredGigE1/32/4 32 100000 +Ethernet256 257 tenGigE1/33 33 10000 +Ethernet257 258 tenGigE1/34 34 10000 diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/qos.json.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/qos.json.j2 new file mode 100644 index 000000000000..a48e1b56621c --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/qos.json.j2 @@ -0,0 +1,226 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "3", + "4": "4", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "STRICT" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "pfc_enable" : "3,4", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai.profile b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai.profile new file mode 100644 index 000000000000..26867a291b00 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-z9332f-32x400G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai_postinit_cmd.soc b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai_postinit_cmd.soc new file mode 100644 index 000000000000..9550e9c822c8 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai_postinit_cmd.soc @@ -0,0 +1,2530 @@ +delay 200 +link off +counter off + +#*** +#*** Port CD0 Preemphasis setting *** +#*** + +local port cd0 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD1 Preemphasis setting *** +#*** + +local port cd1 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD2 Preemphasis setting *** +#*** + +local port cd2 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD3 Preemphasis setting *** +#*** + +local port cd3 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD4 Preemphasis setting *** +#*** + +local port cd4 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD5 Preemphasis setting *** +#*** + +local port cd5 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD6 Preemphasis setting *** +#*** + +local port cd6 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD7 Preemphasis setting *** +#*** + +local port cd7 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD8 Preemphasis setting *** +#*** + +local port cd8 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD9 Preemphasis setting *** +#*** + +local port cd9 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD10 Preemphasis setting *** +#*** + +local port cd10 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x78 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1EC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD11 Preemphasis setting *** +#*** + +local port cd11 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD12 Preemphasis setting *** +#*** + +local port cd12 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD13 Preemphasis setting *** +#*** + +local port cd13 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD14 Preemphasis setting *** +#*** + +local port cd14 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD15 Preemphasis setting *** +#*** + +local port cd15 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD16 Preemphasis setting *** +#*** + +local port cd16 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD17 Preemphasis setting *** +#*** + +local port cd17 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD18 Preemphasis setting *** +#*** + +local port cd18 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD19 Preemphasis setting *** +#*** + +local port cd19 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD20 Preemphasis setting *** +#*** + +local port cd20 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD21 Preemphasis setting *** +#*** + +local port cd21 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD22 Preemphasis setting *** +#*** + +local port cd22 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD23 Preemphasis setting *** +#*** + +local port cd23 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD24 Preemphasis setting *** +#*** + +local port cd24 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD25 Preemphasis setting *** +#*** + +local port cd25 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD26 Preemphasis setting *** +#*** + +local port cd26 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD27 Preemphasis setting *** +#*** + +local port cd27 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD28 Preemphasis setting *** +#*** + +local port cd28 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD29 Preemphasis setting *** +#*** + +local port cd29 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD30 Preemphasis setting *** +#*** + +local port cd30 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD31 Preemphasis setting *** +#*** + +local port cd31 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +link on +counter on diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai_preinit_cmd.soc new file mode 100644 index 000000000000..e48c05b9f664 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai_preinit_cmd.soc @@ -0,0 +1,3 @@ +#Not supported Until SAI 3.6 +#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_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/th3-z9332f-32x400G.config.bcm b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/th3-z9332f-32x400G.config.bcm new file mode 100644 index 000000000000..fc6613601f52 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/th3-z9332f-32x400G.config.bcm @@ -0,0 +1,519 @@ +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 + +ccm_dma_enable=0 +ccmdma_intr_enable=0 +mem_cache_enable=1 +phy_enable=0 +phy_null=1 + +dport_map_enable=1 + +module_64ports.0=0 +tdma_intr_enable.0=1 +ipv6_lpm_128b_enable.0=1 +stat_if_parity_enable.0=1 +oversubscribe_mode=0 +bcm_tunnel_term_compatible_mode.0=1 +table_dma_enable.0=1 +schan_intr_enable.0=0 +parity_enable.0=1 +tdma_timeout_usec=1000000 +lls_num_l2uc.0=10 +miim_intr_enable.0=0 +table_dma_enable=1 +max_vp_lags.0=0 +tdma_intr_enable=1 +tdma_timeout_usec.0=5000000 +parity_correction.0=1 +mmu_lossless.0=0 +bcm_num_cos=10 +default_cpu_tx_queue=7 +pktdma_poll_mode_channel_bitmap=1 +l3_max_ecmp_mode.0=1 +l3_alpm_enable=2 +l3_alpm_ipv6_128b_bkt_rsvd=1 +l2_mem_entries=40960 +l3_mem_entries=40960 + +l2xlrn_thread_interval=50000 +l2xlrn_intr_en=0 + +pbmp_xport_xe=0xffffffFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE + +phy_an_c73=3 + +portmap_1.0=1:400 +portmap_5.0=9:400 +portmap_10.0=17:400 +portmap_14.0=25:400 + +portmap_20.0=33:400 +portmap_24.0=41:400 +portmap_29.0=49:400 +portmap_33.0=57:400 + +portmap_40.0=65:400 +portmap_44.0=73:400 +portmap_49.0=81:400 +portmap_53.0=89:400 + +portmap_60.0=97:400 +portmap_64.0=105:400 +portmap_69.0=113:400 +portmap_73.0=121:400 + +portmap_80.0=129:400 +portmap_84.0=137:400 +portmap_89.0=145:400 +portmap_93.0=153:400 + +portmap_100.0=161:400 +portmap_104.0=169:400 +portmap_109.0=177:400 +portmap_113.0=185:400 + +portmap_120.0=193:400 +portmap_124.0=201:400 +portmap_129.0=209:400 +portmap_133.0=217:400 + +portmap_140.0=225:400 +portmap_144.0=233:400 +portmap_149.0=241:400 +portmap_153.0=249:400 + +portmap_38.0=257:10:1 +portmap_118.0=258:10:1 + +dport_map_port_20=1 +dport_map_port_21=2 +dport_map_port_22=3 +dport_map_port_23=4 +dport_map_port_24=5 +dport_map_port_25=6 +dport_map_port_26=7 +dport_map_port_27=8 +dport_map_port_28=9 +dport_map_port_29=10 +dport_map_port_30=11 +dport_map_port_31=12 +dport_map_port_32=13 +dport_map_port_33=14 +dport_map_port_34=15 +dport_map_port_35=16 +dport_map_port_36=17 +dport_map_port_37=18 +dport_map_port_40=19 +dport_map_port_41=20 +dport_map_port_42=21 +dport_map_port_43=22 +dport_map_port_44=23 +dport_map_port_45=24 +dport_map_port_46=25 +dport_map_port_47=26 +dport_map_port_48=27 +dport_map_port_49=28 +dport_map_port_50=29 +dport_map_port_51=30 +dport_map_port_52=31 +dport_map_port_53=32 +dport_map_port_54=33 +dport_map_port_55=34 +dport_map_port_56=35 +dport_map_port_57=36 +dport_map_port_1=37 +dport_map_port_2=38 +dport_map_port_3=39 +dport_map_port_4=40 +dport_map_port_5=41 +dport_map_port_6=42 +dport_map_port_7=43 +dport_map_port_8=44 +dport_map_port_9=45 +dport_map_port_10=46 +dport_map_port_11=47 +dport_map_port_12=48 +dport_map_port_13=49 +dport_map_port_14=50 +dport_map_port_15=51 +dport_map_port_16=52 +dport_map_port_17=53 +dport_map_port_18=54 +dport_map_port_60=55 +dport_map_port_61=56 +dport_map_port_62=57 +dport_map_port_63=58 +dport_map_port_64=59 +dport_map_port_65=60 +dport_map_port_66=61 +dport_map_port_67=62 +dport_map_port_68=63 +dport_map_port_69=64 +dport_map_port_70=65 +dport_map_port_71=66 +dport_map_port_72=67 +dport_map_port_73=68 +dport_map_port_74=69 +dport_map_port_75=70 +dport_map_port_76=71 +dport_map_port_77=72 +dport_map_port_80=73 +dport_map_port_81=74 +dport_map_port_82=75 +dport_map_port_83=76 +dport_map_port_84=77 +dport_map_port_85=78 +dport_map_port_86=79 +dport_map_port_87=80 +dport_map_port_88=81 +dport_map_port_89=82 +dport_map_port_90=83 +dport_map_port_91=84 +dport_map_port_92=85 +dport_map_port_93=86 +dport_map_port_94=87 +dport_map_port_95=88 +dport_map_port_96=89 +dport_map_port_97=90 +dport_map_port_140=91 +dport_map_port_141=92 +dport_map_port_142=93 +dport_map_port_143=94 +dport_map_port_144=95 +dport_map_port_145=96 +dport_map_port_146=97 +dport_map_port_147=98 +dport_map_port_148=99 +dport_map_port_149=100 +dport_map_port_150=101 +dport_map_port_151=102 +dport_map_port_152=103 +dport_map_port_153=104 +dport_map_port_154=105 +dport_map_port_155=106 +dport_map_port_156=107 +dport_map_port_157=108 +dport_map_port_100=109 +dport_map_port_101=110 +dport_map_port_102=111 +dport_map_port_103=112 +dport_map_port_104=113 +dport_map_port_105=114 +dport_map_port_106=115 +dport_map_port_107=116 +dport_map_port_108=117 +dport_map_port_109=118 +dport_map_port_110=119 +dport_map_port_111=120 +dport_map_port_112=121 +dport_map_port_113=122 +dport_map_port_114=123 +dport_map_port_115=124 +dport_map_port_116=125 +dport_map_port_117=126 +dport_map_port_120=127 +dport_map_port_121=128 +dport_map_port_122=129 +dport_map_port_123=130 +dport_map_port_124=131 +dport_map_port_125=132 +dport_map_port_126=133 +dport_map_port_127=134 +dport_map_port_128=135 +dport_map_port_129=136 +dport_map_port_130=137 +dport_map_port_131=138 +dport_map_port_132=139 +dport_map_port_133=140 +dport_map_port_134=141 +dport_map_port_135=142 +dport_map_port_136=143 +dport_map_port_137=144 +dport_map_port_38=145 +dport_map_port_118=146 + +phy_chain_rx_lane_map_physical{33.0}=0x65732041 +phy_chain_tx_lane_map_physical{33.0}=0x47206531 +phy_chain_rx_lane_map_physical{41.0}=0x07561243 +phy_chain_tx_lane_map_physical{41.0}=0x36207514 +phy_chain_rx_lane_map_physical{49.0}=0x54632071 +phy_chain_tx_lane_map_physical{49.0}=0x06241735 +phy_chain_rx_lane_map_physical{57.0}=0x07561243 +phy_chain_tx_lane_map_physical{57.0}=0x35207614 +phy_chain_rx_lane_map_physical{65.0}=0x45623170 +phy_chain_tx_lane_map_physical{65.0}=0x51260734 +phy_chain_rx_lane_map_physical{73.0}=0x07561243 +phy_chain_tx_lane_map_physical{73.0}=0x37245610 +phy_chain_rx_lane_map_physical{81.0}=0x45632071 +phy_chain_tx_lane_map_physical{81.0}=0x51260734 +phy_chain_rx_lane_map_physical{89.0}=0x07561243 +phy_chain_tx_lane_map_physical{89.0}=0x26437510 +phy_chain_rx_lane_map_physical{1.0}=0x30176524 +phy_chain_tx_lane_map_physical{1.0}=0x20615374 +phy_chain_rx_lane_map_physical{9.0}=0x37562041 +phy_chain_tx_lane_map_physical{9.0}=0x05176432 +phy_chain_rx_lane_map_physical{17.0}=0x43607251 +phy_chain_tx_lane_map_physical{17.0}=0x70261435 +phy_chain_rx_lane_map_physical{25.0}=0x60347125 +phy_chain_tx_lane_map_physical{25.0}=0x46357120 +phy_chain_rx_lane_map_physical{97.0}=0x47601352 +phy_chain_tx_lane_map_physical{97.0}=0x04265137 +phy_chain_rx_lane_map_physical{105.0}=0x73206415 +phy_chain_tx_lane_map_physical{105.0}=0x26374150 +phy_chain_rx_lane_map_physical{113.0}=0x47632051 +phy_chain_tx_lane_map_physical{113.0}=0x03254617 +phy_chain_rx_lane_map_physical{121.0}=0x63027415 +phy_chain_tx_lane_map_physical{121.0}=0x63721045 +phy_chain_rx_lane_map_physical{129.0}=0x30154627 +phy_chain_tx_lane_map_physical{129.0}=0x04735261 +phy_chain_rx_lane_map_physical{137.0}=0x24753061 +phy_chain_tx_lane_map_physical{137.0}=0x37614520 +phy_chain_rx_lane_map_physical{145.0}=0x47601352 +phy_chain_tx_lane_map_physical{145.0}=0x63274510 +phy_chain_rx_lane_map_physical{153.0}=0x07361524 +phy_chain_tx_lane_map_physical{153.0}=0x36527104 +phy_chain_rx_lane_map_physical{225.0}=0x56410273 +phy_chain_tx_lane_map_physical{225.0}=0x10274635 +phy_chain_rx_lane_map_physical{233.0}=0x15740263 +phy_chain_tx_lane_map_physical{233.0}=0x24351607 +phy_chain_rx_lane_map_physical{241.0}=0x74015263 +phy_chain_tx_lane_map_physical{241.0}=0x04152637 +phy_chain_rx_lane_map_physical{249.0}=0x62037514 +phy_chain_tx_lane_map_physical{249.0}=0x72453160 +phy_chain_rx_lane_map_physical{161.0}=0x46510273 +phy_chain_tx_lane_map_physical{161.0}=0x01653724 +phy_chain_rx_lane_map_physical{169.0}=0x25743160 +phy_chain_tx_lane_map_physical{169.0}=0x07216435 +phy_chain_rx_lane_map_physical{177.0}=0x46510273 +phy_chain_tx_lane_map_physical{177.0}=0x01652734 +phy_chain_rx_lane_map_physical{185.0}=0x25743160 +phy_chain_tx_lane_map_physical{185.0}=0x37016425 +phy_chain_rx_lane_map_physical{193.0}=0x46510372 +phy_chain_tx_lane_map_physical{193.0}=0x06153724 +phy_chain_rx_lane_map_physical{201.0}=0x25743160 +phy_chain_tx_lane_map_physical{201.0}=0x36017524 +phy_chain_rx_lane_map_physical{209.0}=0x47601352 +phy_chain_tx_lane_map_physical{209.0}=0x04152736 +phy_chain_rx_lane_map_physical{217.0}=0x26453170 +phy_chain_tx_lane_map_physical{217.0}=0x36027415 + +serdes_core_rx_polarity_flip_physical{33}=0x29 +serdes_core_tx_polarity_flip_physical{33}=0xfe +serdes_core_rx_polarity_flip_physical{41}=0xb1 +serdes_core_tx_polarity_flip_physical{41}=0xe8 +serdes_core_rx_polarity_flip_physical{49}=0xca +serdes_core_tx_polarity_flip_physical{49}=0xb6 +serdes_core_rx_polarity_flip_physical{57}=0x9b +serdes_core_tx_polarity_flip_physical{57}=0xdc +serdes_core_rx_polarity_flip_physical{65}=0x17 +serdes_core_tx_polarity_flip_physical{65}=0x86 +serdes_core_rx_polarity_flip_physical{73}=0x9b +serdes_core_tx_polarity_flip_physical{73}=0x55 +serdes_core_rx_polarity_flip_physical{81}=0xa +serdes_core_tx_polarity_flip_physical{81}=0x6 +serdes_core_rx_polarity_flip_physical{89}=0x9b +serdes_core_tx_polarity_flip_physical{89}=0x48 +serdes_core_rx_polarity_flip_physical{1}=0xec +serdes_core_tx_polarity_flip_physical{1}=0x56 +serdes_core_rx_polarity_flip_physical{9}=0x13 +serdes_core_tx_polarity_flip_physical{9}=0xa6 +serdes_core_rx_polarity_flip_physical{17}=0x5a +serdes_core_tx_polarity_flip_physical{17}=0xc6 +serdes_core_rx_polarity_flip_physical{25}=0xf +serdes_core_tx_polarity_flip_physical{25}=0x4e +serdes_core_rx_polarity_flip_physical{97}=0x17 +serdes_core_tx_polarity_flip_physical{97}=0x2e +serdes_core_rx_polarity_flip_physical{105}=0xce +serdes_core_tx_polarity_flip_physical{105}=0x7c +serdes_core_rx_polarity_flip_physical{113}=0xa +serdes_core_tx_polarity_flip_physical{113}=0x35 + +serdes_core_rx_polarity_flip_physical{121}=0xb9 +serdes_core_tx_polarity_flip_physical{121}=0xef +serdes_core_rx_polarity_flip_physical{129}=0xe8 +serdes_core_tx_polarity_flip_physical{129}=0xac +serdes_core_rx_polarity_flip_physical{137}=0xcb +serdes_core_tx_polarity_flip_physical{137}=0x9c +serdes_core_rx_polarity_flip_physical{145}=0x17 +serdes_core_tx_polarity_flip_physical{145}=0x32 +serdes_core_rx_polarity_flip_physical{153}=0xb9 +serdes_core_tx_polarity_flip_physical{153}=0xaf +serdes_core_rx_polarity_flip_physical{225}=0xaa +serdes_core_tx_polarity_flip_physical{225}=0x7 +serdes_core_rx_polarity_flip_physical{233}=0x31 +serdes_core_tx_polarity_flip_physical{233}=0x47 +serdes_core_rx_polarity_flip_physical{241}=0xe8 +serdes_core_tx_polarity_flip_physical{241}=0x9e +serdes_core_rx_polarity_flip_physical{249}=0xec +serdes_core_tx_polarity_flip_physical{249}=0x1f +serdes_core_rx_polarity_flip_physical{161}=0x6a +serdes_core_tx_polarity_flip_physical{161}=0xd4 +serdes_core_rx_polarity_flip_physical{169}=0x9e +serdes_core_tx_polarity_flip_physical{169}=0x7b +serdes_core_rx_polarity_flip_physical{177}=0x6a +serdes_core_tx_polarity_flip_physical{177}=0xcc +serdes_core_rx_polarity_flip_physical{185}=0x9e +serdes_core_tx_polarity_flip_physical{185}=0x58 +serdes_core_rx_polarity_flip_physical{193}=0x6f +serdes_core_tx_polarity_flip_physical{193}=0x24 +serdes_core_rx_polarity_flip_physical{201}=0x9e +serdes_core_tx_polarity_flip_physical{201}=0xdf +serdes_core_rx_polarity_flip_physical{209}=0x17 +serdes_core_tx_polarity_flip_physical{209}=0xe9 +serdes_core_rx_polarity_flip_physical{217}=0xec +serdes_core_tx_polarity_flip_physical{217}=0x68 + +serdes_lane_config_media_type_49=copper +serdes_lane_config_media_type_50=copper +serdes_lane_config_media_type_51=copper +serdes_lane_config_media_type_52=copper +serdes_lane_config_media_type_54=copper +serdes_lane_config_media_type_55=copper +serdes_lane_config_media_type_56=copper +serdes_lane_config_media_type_57=copper +serdes_lane_config_media_type_53=copper +serdes_lane_config_media_type_60=copper +serdes_lane_config_media_type_61=copper +serdes_lane_config_media_type_62=copper +serdes_lane_config_media_type_63=copper +serdes_lane_config_media_type_65=copper +serdes_lane_config_media_type_66=copper +serdes_lane_config_media_type_67=copper +serdes_lane_config_media_type_68=copper +serdes_lane_config_media_type_64=copper +serdes_lane_config_media_type_80=copper +serdes_lane_config_media_type_81=copper +serdes_lane_config_media_type_82=copper +serdes_lane_config_media_type_83=copper +serdes_lane_config_media_type_85=copper +serdes_lane_config_media_type_86=copper +serdes_lane_config_media_type_87=copper +serdes_lane_config_media_type_88=copper +serdes_lane_config_media_type_84=copper +serdes_lane_config_media_type_100=copper +serdes_lane_config_media_type_101=copper +serdes_lane_config_media_type_102=copper +serdes_lane_config_media_type_103=copper +serdes_lane_config_media_type_105=copper +serdes_lane_config_media_type_106=copper +serdes_lane_config_media_type_107=copper +serdes_lane_config_media_type_108=copper +serdes_lane_config_media_type_104=copper +serdes_lane_config_media_type_120=copper +serdes_lane_config_media_type_121=copper +serdes_lane_config_media_type_122=copper +serdes_lane_config_media_type_123=copper +serdes_lane_config_media_type_125=copper +serdes_lane_config_media_type_126=copper +serdes_lane_config_media_type_127=copper +serdes_lane_config_media_type_128=copper +serdes_lane_config_media_type_124=copper +serdes_lane_config_media_type_140=copper +serdes_lane_config_media_type_141=copper +serdes_lane_config_media_type_142=copper +serdes_lane_config_media_type_143=copper +serdes_lane_config_media_type_145=copper +serdes_lane_config_media_type_146=copper +serdes_lane_config_media_type_147=copper +serdes_lane_config_media_type_148=copper +serdes_lane_config_media_type_144=copper +serdes_lane_config_media_type_40=copper +serdes_lane_config_media_type_41=copper +serdes_lane_config_media_type_42=copper +serdes_lane_config_media_type_43=copper +serdes_lane_config_media_type_45=copper +serdes_lane_config_media_type_46=copper +serdes_lane_config_media_type_47=copper +serdes_lane_config_media_type_48=copper +serdes_lane_config_media_type_44=copper +serdes_lane_config_media_type_69=copper +serdes_lane_config_media_type_70=copper +serdes_lane_config_media_type_71=copper +serdes_lane_config_media_type_72=copper +serdes_lane_config_media_type_74=copper +serdes_lane_config_media_type_75=copper +serdes_lane_config_media_type_76=copper +serdes_lane_config_media_type_77=copper +serdes_lane_config_media_type_73=copper +serdes_lane_config_media_type_1=copper +serdes_lane_config_media_type_2=copper +serdes_lane_config_media_type_3=copper +serdes_lane_config_media_type_4=copper +serdes_lane_config_media_type_6=copper +serdes_lane_config_media_type_7=copper +serdes_lane_config_media_type_8=copper +serdes_lane_config_media_type_9=copper +serdes_lane_config_media_type_5=copper +serdes_lane_config_media_type_29=copper +serdes_lane_config_media_type_30=copper +serdes_lane_config_media_type_31=copper +serdes_lane_config_media_type_32=copper +serdes_lane_config_media_type_34=copper +serdes_lane_config_media_type_35=copper +serdes_lane_config_media_type_36=copper +serdes_lane_config_media_type_37=copper +serdes_lane_config_media_type_33=copper +serdes_lane_config_media_type_89=copper +serdes_lane_config_media_type_90=copper +serdes_lane_config_media_type_91=copper +serdes_lane_config_media_type_92=copper +serdes_lane_config_media_type_94=copper +serdes_lane_config_media_type_95=copper +serdes_lane_config_media_type_96=copper +serdes_lane_config_media_type_97=copper +serdes_lane_config_media_type_93=copper +serdes_lane_config_media_type_109=copper +serdes_lane_config_media_type_110=copper +serdes_lane_config_media_type_111=copper +serdes_lane_config_media_type_112=copper +serdes_lane_config_media_type_114=copper +serdes_lane_config_media_type_115=copper +serdes_lane_config_media_type_116=copper +serdes_lane_config_media_type_117=copper +serdes_lane_config_media_type_113=copper +serdes_lane_config_media_type_129=copper +serdes_lane_config_media_type_130=copper +serdes_lane_config_media_type_131=copper +serdes_lane_config_media_type_132=copper +serdes_lane_config_media_type_134=copper +serdes_lane_config_media_type_135=copper +serdes_lane_config_media_type_136=copper +serdes_lane_config_media_type_137=copper +serdes_lane_config_media_type_133=copper +serdes_lane_config_media_type_149=copper +serdes_lane_config_media_type_150=copper +serdes_lane_config_media_type_151=copper +serdes_lane_config_media_type_152=copper +serdes_lane_config_media_type_154=copper +serdes_lane_config_media_type_155=copper +serdes_lane_config_media_type_156=copper +serdes_lane_config_media_type_157=copper +serdes_lane_config_media_type_153=copper +serdes_lane_config_media_type_10=copper +serdes_lane_config_media_type_11=copper +serdes_lane_config_media_type_12=copper +serdes_lane_config_media_type_13=copper +serdes_lane_config_media_type_15=copper +serdes_lane_config_media_type_16=copper +serdes_lane_config_media_type_17=copper +serdes_lane_config_media_type_18=copper +serdes_lane_config_media_type_14=copper +serdes_lane_config_media_type_20=copper +serdes_lane_config_media_type_21=copper +serdes_lane_config_media_type_22=copper +serdes_lane_config_media_type_23=copper +serdes_lane_config_media_type_25=copper +serdes_lane_config_media_type_26=copper +serdes_lane_config_media_type_27=copper +serdes_lane_config_media_type_28=copper +serdes_lane_config_media_type_24=copper + +#sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc + diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/buffers.json.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..77747f6403c8 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/buffers_defaults_t0.j2 @@ -0,0 +1,20 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + }, + "BUFFER_PROFILE": { + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..77747f6403c8 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/buffers_defaults_t1.j2 @@ -0,0 +1,20 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + }, + "BUFFER_PROFILE": { + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names_active) %} + "BUFFER_PG": { + }, +{%- endmacro %} + +{% macro generate_queue_buffers(port_names_active) %} + "BUFFER_QUEUE": { + } +{% endmacro %} + diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/custom_led.bin b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/custom_led.bin new file mode 100755 index 000000000000..3ee9545e28ae Binary files /dev/null and b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/linkscan_led_fw.bin new file mode 100755 index 000000000000..c2fa94a2d8cb Binary files /dev/null and b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/linkscan_led_fw.bin differ diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/pg_profile_lookup.ini b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/pg_profile_lookup.ini new file mode 100644 index 000000000000..a5f3286beef8 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/pg_profile_lookup.ini @@ -0,0 +1,23 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1270 0 190500 -2 2540 + 25000 5m 1270 0 190500 -2 2540 + 40000 5m 1270 0 190500 -2 2540 + 50000 5m 1270 0 190500 -2 2540 + 100000 5m 1270 0 190500 -2 2540 + 200000 5m 1270 0 190500 -2 2540 + 400000 5m 1270 0 190500 -2 2540 + 10000 40m 1270 0 190500 -2 2540 + 25000 40m 1270 0 190500 -2 2540 + 40000 40m 1270 0 190500 -2 2540 + 50000 40m 1270 0 190500 -2 2540 + 100000 40m 1270 0 190500 -2 2540 + 200000 40m 1270 0 190500 -2 2540 + 400000 40m 1270 0 190500 -2 2540 + 10000 300m 1270 0 190500 -2 2540 + 25000 300m 1270 0 190500 -2 2540 + 40000 300m 1270 0 190500 -2 2540 + 50000 300m 1270 0 190500 -2 2540 + 100000 300m 1270 0 190500 -2 2540 + 200000 300m 1270 0 190500 -2 2540 + 400000 300m 1270 0 190500 -2 2540 diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/port_config.ini b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/port_config.ini new file mode 100644 index 000000000000..790fb490cfe6 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/port_config.ini @@ -0,0 +1,35 @@ +# name lanes alias index speed +Ethernet0 33,34,35,36,37,38,39,40 fourhundredGigE1/1 1 400000 +Ethernet8 41,42,43,44,45,46,47,48 fourhundredGigE1/2 2 400000 +Ethernet16 49,50,51,52,53,54,55,56 fourhundredGigE1/3 3 400000 +Ethernet24 57,58,59,60,61,62,63,64 fourhundredGigE1/4 4 400000 +Ethernet32 65,66,67,68,69,70,71,72 fourhundredGigE1/5 5 400000 +Ethernet40 73,74,75,76,77,78,79,80 fourhundredGigE1/6 6 400000 +Ethernet48 81,82,83,84,85,86,87,88 fourhundredGigE1/7 7 400000 +Ethernet56 89,90,91,92,93,94,95,96 fourhundredGigE1/8 8 400000 +Ethernet64 1,2,3,4,5,6,7,8 fourhundredGigE1/9 9 400000 +Ethernet72 9,10,11,12,13,14,15,16 fourhundredGigE1/10 10 400000 +Ethernet80 17,18,19,20,21,22,23,24 fourhundredGigE1/11 11 400000 +Ethernet88 25,26,27,28,29,30,31,32 fourhundredGigE1/12 12 400000 +Ethernet96 97,98,99,100,101,102,103,104 fourhundredGigE1/13 13 400000 +Ethernet104 105,106,107,108,109,110,111,112 fourhundredGigE1/14 14 400000 +Ethernet112 113,114,115,116,117,118,119,120 fourhundredGigE1/15 15 400000 +Ethernet120 121,122,123,124,125,126,127,128 fourhundredGigE1/16 16 400000 +Ethernet128 129,130,131,132,133,134,135,136 fourhundredGigE1/17 17 400000 +Ethernet136 137,138,139,140,141,142,143,144 fourhundredGigE1/18 18 400000 +Ethernet144 145,146,147,148,149,150,151,152 fourhundredGigE1/19 19 400000 +Ethernet152 153,154,155,156,157,158,159,160 fourhundredGigE1/20 20 400000 +Ethernet160 225,226,227,228,229,230,231,232 fourhundredGigE1/21 21 400000 +Ethernet168 233,234,235,236,237,238,239,240 fourhundredGigE1/22 22 400000 +Ethernet176 241,242,243,244,245,246,247,248 fourhundredGigE1/23 23 400000 +Ethernet184 249,250,251,252,253,254,255,256 fourhundredGigE1/24 24 400000 +Ethernet192 161,162,163,164,165,166,167,168 fourhundredGigE1/25 25 400000 +Ethernet200 169,170,171,172,173,174,175,176 fourhundredGigE1/26 26 400000 +Ethernet208 177,178,179,180,181,182,183,184 fourhundredGigE1/27 27 400000 +Ethernet216 185,186,187,188,189,190,191,192 fourhundredGigE1/28 28 400000 +Ethernet224 193,194,195,196,197,198,199,200 fourhundredGigE1/29 29 400000 +Ethernet232 201,202,203,204,205,206,207,208 fourhundredGigE1/30 30 400000 +Ethernet240 209,210,211,212,213,214,215,216 fourhundredGigE1/31 31 400000 +Ethernet248 217,218,219,220,221,222,223,224 fourhundredGigE1/32 32 400000 +Ethernet256 257 tenGigE1/33 33 10000 +Ethernet257 258 tenGigE1/34 34 10000 diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/qos.json.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/qos.json.j2 new file mode 100644 index 000000000000..a48e1b56621c --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/qos.json.j2 @@ -0,0 +1,226 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "DEFAULT": { + "0": "0", + "1": "0", + "2": "0", + "3": "3", + "4": "4", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "DEFAULT": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "DEFAULT": { + "0" : "0", + "1" : "0", + "2" : "0", + "3" : "0", + "4" : "0", + "5" : "0", + "6" : "0", + "7" : "0", + "8" : "0", + "9" : "0", + "10": "0", + "11": "0", + "12": "0", + "13": "0", + "14": "0", + "15": "0", + "16": "0", + "17": "0", + "18": "0", + "19": "0", + "20": "0", + "21": "0", + "22": "0", + "23": "0", + "24": "0", + "25": "0", + "26": "0", + "27": "0", + "28": "0", + "29": "0", + "30": "0", + "31": "0", + "32": "0", + "33": "0", + "34": "0", + "35": "0", + "36": "0", + "37": "0", + "38": "0", + "39": "0", + "40": "0", + "41": "0", + "42": "0", + "43": "0", + "44": "0", + "45": "0", + "46": "0", + "47": "0", + "48": "0", + "49": "0", + "50": "0", + "51": "0", + "52": "0", + "53": "0", + "54": "0", + "55": "0", + "56": "0", + "57": "0", + "58": "0", + "59": "0", + "60": "0", + "61": "0", + "62": "0", + "63": "0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "1" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "2" + }, + "scheduler.2": { + "type" : "DWRR", + "weight": "3" + }, + "scheduler.3": { + "type" : "DWRR", + "weight": "4" + }, + "scheduler.4": { + "type" : "DWRR", + "weight": "5" + }, + "scheduler.5": { + "type" : "DWRR", + "weight": "10" + }, + "scheduler.6": { + "type" : "DWRR", + "weight": "25" + }, + "scheduler.7": { + "type" : "STRICT" + } + }, + "PORT_QOS_MAP": { + "{{ port_names_active }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]", + "pfc_enable" : "3,4", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]" + } + }, + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.2]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler": "[SCHEDULER|scheduler.3]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler": "[SCHEDULER|scheduler.4]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.5]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.6]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|7": { + "scheduler": "[SCHEDULER|scheduler.7]" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/sai.profile b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/sai.profile new file mode 100644 index 000000000000..26867a291b00 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-z9332f-32x400G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/sai_postinit_cmd.soc b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/sai_postinit_cmd.soc new file mode 100644 index 000000000000..9550e9c822c8 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/sai_postinit_cmd.soc @@ -0,0 +1,2530 @@ +delay 200 +link off +counter off + +#*** +#*** Port CD0 Preemphasis setting *** +#*** + +local port cd0 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD1 Preemphasis setting *** +#*** + +local port cd1 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD2 Preemphasis setting *** +#*** + +local port cd2 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD3 Preemphasis setting *** +#*** + +local port cd3 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD4 Preemphasis setting *** +#*** + +local port cd4 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD5 Preemphasis setting *** +#*** + +local port cd5 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD6 Preemphasis setting *** +#*** + +local port cd6 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD7 Preemphasis setting *** +#*** + +local port cd7 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD8 Preemphasis setting *** +#*** + +local port cd8 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD9 Preemphasis setting *** +#*** + +local port cd9 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD10 Preemphasis setting *** +#*** + +local port cd10 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x78 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1EC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD11 Preemphasis setting *** +#*** + +local port cd11 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD12 Preemphasis setting *** +#*** + +local port cd12 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD13 Preemphasis setting *** +#*** + +local port cd13 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD14 Preemphasis setting *** +#*** + +local port cd14 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD15 Preemphasis setting *** +#*** + +local port cd15 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD16 Preemphasis setting *** +#*** + +local port cd16 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD17 Preemphasis setting *** +#*** + +local port cd17 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD18 Preemphasis setting *** +#*** + +local port cd18 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD19 Preemphasis setting *** +#*** + +local port cd19 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD20 Preemphasis setting *** +#*** + +local port cd20 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD21 Preemphasis setting *** +#*** + +local port cd21 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD22 Preemphasis setting *** +#*** + +local port cd22 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD23 Preemphasis setting *** +#*** + +local port cd23 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD24 Preemphasis setting *** +#*** + +local port cd24 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD25 Preemphasis setting *** +#*** + +local port cd25 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD26 Preemphasis setting *** +#*** + +local port cd26 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD27 Preemphasis setting *** +#*** + +local port cd27 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD28 Preemphasis setting *** +#*** + +local port cd28 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x88 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F8 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD29 Preemphasis setting *** +#*** + +local port cd29 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD30 Preemphasis setting *** +#*** + +local port cd30 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x84 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1F4 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +delay 10 + +#*** +#*** Port CD31 Preemphasis setting *** +#*** + +local port cd31 +#*** lane 0 *** +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.0 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.0 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.0 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.0 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.0 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.0 TXFIR_TAP_LOAD=0x1 + +#*** lane 1 *** +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.1 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.1 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.1 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.1 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.1 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.1 TXFIR_TAP_LOAD=0x1 + +#*** lane 2 *** +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.2 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.2 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.2 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.2 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.2 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.2 TXFIR_TAP_LOAD=0x1 + +#*** lane 3 *** +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.3 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.3 TXFIR_TAP2_COEFF=0x90 +phy $port TXFIR_TAP_CTL3r.3 TXFIR_TAP3_COEFF=0 +phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 + +#*** lane 4 *** +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.4 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.4 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 + +#*** lane 5 *** +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=4 +phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E4 +phy $port TXFIR_TAP_CTL2r.5 TXFIR_TAP2_COEFF=0x70 +phy $port TXFIR_TAP_CTL3r.5 TXFIR_TAP3_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 + +#*** lane 6 *** +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.6 TXFIR_TAP2_COEFF=0x80 +phy $port TXFIR_TAP_CTL3r.6 TXFIR_TAP3_COEFF=0x1F0 +phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 + +#*** lane 7 *** +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=0 +phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E8 +phy $port TXFIR_TAP_CTL2r.7 TXFIR_TAP2_COEFF=0x8C +phy $port TXFIR_TAP_CTL3r.7 TXFIR_TAP3_COEFF=0x1FC +phy $port TXFIR_TAP_CTL4r.7 TXFIR_TAP4_COEFF=0 +phy $port TXFIR_TAP_CTL5r.7 TXFIR_TAP5_COEFF=0 +phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP_LOAD=0x1 + +link on +counter on diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/sai_preinit_cmd.soc new file mode 100644 index 000000000000..e48c05b9f664 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/sai_preinit_cmd.soc @@ -0,0 +1,3 @@ +#Not supported Until SAI 3.6 +#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_z9332f_d1508-r0/DellEMC-Z9332f-O32/th3-z9332f-32x400G.config.bcm b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/th3-z9332f-32x400G.config.bcm new file mode 100644 index 000000000000..fc6613601f52 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-O32/th3-z9332f-32x400G.config.bcm @@ -0,0 +1,519 @@ +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 + +ccm_dma_enable=0 +ccmdma_intr_enable=0 +mem_cache_enable=1 +phy_enable=0 +phy_null=1 + +dport_map_enable=1 + +module_64ports.0=0 +tdma_intr_enable.0=1 +ipv6_lpm_128b_enable.0=1 +stat_if_parity_enable.0=1 +oversubscribe_mode=0 +bcm_tunnel_term_compatible_mode.0=1 +table_dma_enable.0=1 +schan_intr_enable.0=0 +parity_enable.0=1 +tdma_timeout_usec=1000000 +lls_num_l2uc.0=10 +miim_intr_enable.0=0 +table_dma_enable=1 +max_vp_lags.0=0 +tdma_intr_enable=1 +tdma_timeout_usec.0=5000000 +parity_correction.0=1 +mmu_lossless.0=0 +bcm_num_cos=10 +default_cpu_tx_queue=7 +pktdma_poll_mode_channel_bitmap=1 +l3_max_ecmp_mode.0=1 +l3_alpm_enable=2 +l3_alpm_ipv6_128b_bkt_rsvd=1 +l2_mem_entries=40960 +l3_mem_entries=40960 + +l2xlrn_thread_interval=50000 +l2xlrn_intr_en=0 + +pbmp_xport_xe=0xffffffFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE + +phy_an_c73=3 + +portmap_1.0=1:400 +portmap_5.0=9:400 +portmap_10.0=17:400 +portmap_14.0=25:400 + +portmap_20.0=33:400 +portmap_24.0=41:400 +portmap_29.0=49:400 +portmap_33.0=57:400 + +portmap_40.0=65:400 +portmap_44.0=73:400 +portmap_49.0=81:400 +portmap_53.0=89:400 + +portmap_60.0=97:400 +portmap_64.0=105:400 +portmap_69.0=113:400 +portmap_73.0=121:400 + +portmap_80.0=129:400 +portmap_84.0=137:400 +portmap_89.0=145:400 +portmap_93.0=153:400 + +portmap_100.0=161:400 +portmap_104.0=169:400 +portmap_109.0=177:400 +portmap_113.0=185:400 + +portmap_120.0=193:400 +portmap_124.0=201:400 +portmap_129.0=209:400 +portmap_133.0=217:400 + +portmap_140.0=225:400 +portmap_144.0=233:400 +portmap_149.0=241:400 +portmap_153.0=249:400 + +portmap_38.0=257:10:1 +portmap_118.0=258:10:1 + +dport_map_port_20=1 +dport_map_port_21=2 +dport_map_port_22=3 +dport_map_port_23=4 +dport_map_port_24=5 +dport_map_port_25=6 +dport_map_port_26=7 +dport_map_port_27=8 +dport_map_port_28=9 +dport_map_port_29=10 +dport_map_port_30=11 +dport_map_port_31=12 +dport_map_port_32=13 +dport_map_port_33=14 +dport_map_port_34=15 +dport_map_port_35=16 +dport_map_port_36=17 +dport_map_port_37=18 +dport_map_port_40=19 +dport_map_port_41=20 +dport_map_port_42=21 +dport_map_port_43=22 +dport_map_port_44=23 +dport_map_port_45=24 +dport_map_port_46=25 +dport_map_port_47=26 +dport_map_port_48=27 +dport_map_port_49=28 +dport_map_port_50=29 +dport_map_port_51=30 +dport_map_port_52=31 +dport_map_port_53=32 +dport_map_port_54=33 +dport_map_port_55=34 +dport_map_port_56=35 +dport_map_port_57=36 +dport_map_port_1=37 +dport_map_port_2=38 +dport_map_port_3=39 +dport_map_port_4=40 +dport_map_port_5=41 +dport_map_port_6=42 +dport_map_port_7=43 +dport_map_port_8=44 +dport_map_port_9=45 +dport_map_port_10=46 +dport_map_port_11=47 +dport_map_port_12=48 +dport_map_port_13=49 +dport_map_port_14=50 +dport_map_port_15=51 +dport_map_port_16=52 +dport_map_port_17=53 +dport_map_port_18=54 +dport_map_port_60=55 +dport_map_port_61=56 +dport_map_port_62=57 +dport_map_port_63=58 +dport_map_port_64=59 +dport_map_port_65=60 +dport_map_port_66=61 +dport_map_port_67=62 +dport_map_port_68=63 +dport_map_port_69=64 +dport_map_port_70=65 +dport_map_port_71=66 +dport_map_port_72=67 +dport_map_port_73=68 +dport_map_port_74=69 +dport_map_port_75=70 +dport_map_port_76=71 +dport_map_port_77=72 +dport_map_port_80=73 +dport_map_port_81=74 +dport_map_port_82=75 +dport_map_port_83=76 +dport_map_port_84=77 +dport_map_port_85=78 +dport_map_port_86=79 +dport_map_port_87=80 +dport_map_port_88=81 +dport_map_port_89=82 +dport_map_port_90=83 +dport_map_port_91=84 +dport_map_port_92=85 +dport_map_port_93=86 +dport_map_port_94=87 +dport_map_port_95=88 +dport_map_port_96=89 +dport_map_port_97=90 +dport_map_port_140=91 +dport_map_port_141=92 +dport_map_port_142=93 +dport_map_port_143=94 +dport_map_port_144=95 +dport_map_port_145=96 +dport_map_port_146=97 +dport_map_port_147=98 +dport_map_port_148=99 +dport_map_port_149=100 +dport_map_port_150=101 +dport_map_port_151=102 +dport_map_port_152=103 +dport_map_port_153=104 +dport_map_port_154=105 +dport_map_port_155=106 +dport_map_port_156=107 +dport_map_port_157=108 +dport_map_port_100=109 +dport_map_port_101=110 +dport_map_port_102=111 +dport_map_port_103=112 +dport_map_port_104=113 +dport_map_port_105=114 +dport_map_port_106=115 +dport_map_port_107=116 +dport_map_port_108=117 +dport_map_port_109=118 +dport_map_port_110=119 +dport_map_port_111=120 +dport_map_port_112=121 +dport_map_port_113=122 +dport_map_port_114=123 +dport_map_port_115=124 +dport_map_port_116=125 +dport_map_port_117=126 +dport_map_port_120=127 +dport_map_port_121=128 +dport_map_port_122=129 +dport_map_port_123=130 +dport_map_port_124=131 +dport_map_port_125=132 +dport_map_port_126=133 +dport_map_port_127=134 +dport_map_port_128=135 +dport_map_port_129=136 +dport_map_port_130=137 +dport_map_port_131=138 +dport_map_port_132=139 +dport_map_port_133=140 +dport_map_port_134=141 +dport_map_port_135=142 +dport_map_port_136=143 +dport_map_port_137=144 +dport_map_port_38=145 +dport_map_port_118=146 + +phy_chain_rx_lane_map_physical{33.0}=0x65732041 +phy_chain_tx_lane_map_physical{33.0}=0x47206531 +phy_chain_rx_lane_map_physical{41.0}=0x07561243 +phy_chain_tx_lane_map_physical{41.0}=0x36207514 +phy_chain_rx_lane_map_physical{49.0}=0x54632071 +phy_chain_tx_lane_map_physical{49.0}=0x06241735 +phy_chain_rx_lane_map_physical{57.0}=0x07561243 +phy_chain_tx_lane_map_physical{57.0}=0x35207614 +phy_chain_rx_lane_map_physical{65.0}=0x45623170 +phy_chain_tx_lane_map_physical{65.0}=0x51260734 +phy_chain_rx_lane_map_physical{73.0}=0x07561243 +phy_chain_tx_lane_map_physical{73.0}=0x37245610 +phy_chain_rx_lane_map_physical{81.0}=0x45632071 +phy_chain_tx_lane_map_physical{81.0}=0x51260734 +phy_chain_rx_lane_map_physical{89.0}=0x07561243 +phy_chain_tx_lane_map_physical{89.0}=0x26437510 +phy_chain_rx_lane_map_physical{1.0}=0x30176524 +phy_chain_tx_lane_map_physical{1.0}=0x20615374 +phy_chain_rx_lane_map_physical{9.0}=0x37562041 +phy_chain_tx_lane_map_physical{9.0}=0x05176432 +phy_chain_rx_lane_map_physical{17.0}=0x43607251 +phy_chain_tx_lane_map_physical{17.0}=0x70261435 +phy_chain_rx_lane_map_physical{25.0}=0x60347125 +phy_chain_tx_lane_map_physical{25.0}=0x46357120 +phy_chain_rx_lane_map_physical{97.0}=0x47601352 +phy_chain_tx_lane_map_physical{97.0}=0x04265137 +phy_chain_rx_lane_map_physical{105.0}=0x73206415 +phy_chain_tx_lane_map_physical{105.0}=0x26374150 +phy_chain_rx_lane_map_physical{113.0}=0x47632051 +phy_chain_tx_lane_map_physical{113.0}=0x03254617 +phy_chain_rx_lane_map_physical{121.0}=0x63027415 +phy_chain_tx_lane_map_physical{121.0}=0x63721045 +phy_chain_rx_lane_map_physical{129.0}=0x30154627 +phy_chain_tx_lane_map_physical{129.0}=0x04735261 +phy_chain_rx_lane_map_physical{137.0}=0x24753061 +phy_chain_tx_lane_map_physical{137.0}=0x37614520 +phy_chain_rx_lane_map_physical{145.0}=0x47601352 +phy_chain_tx_lane_map_physical{145.0}=0x63274510 +phy_chain_rx_lane_map_physical{153.0}=0x07361524 +phy_chain_tx_lane_map_physical{153.0}=0x36527104 +phy_chain_rx_lane_map_physical{225.0}=0x56410273 +phy_chain_tx_lane_map_physical{225.0}=0x10274635 +phy_chain_rx_lane_map_physical{233.0}=0x15740263 +phy_chain_tx_lane_map_physical{233.0}=0x24351607 +phy_chain_rx_lane_map_physical{241.0}=0x74015263 +phy_chain_tx_lane_map_physical{241.0}=0x04152637 +phy_chain_rx_lane_map_physical{249.0}=0x62037514 +phy_chain_tx_lane_map_physical{249.0}=0x72453160 +phy_chain_rx_lane_map_physical{161.0}=0x46510273 +phy_chain_tx_lane_map_physical{161.0}=0x01653724 +phy_chain_rx_lane_map_physical{169.0}=0x25743160 +phy_chain_tx_lane_map_physical{169.0}=0x07216435 +phy_chain_rx_lane_map_physical{177.0}=0x46510273 +phy_chain_tx_lane_map_physical{177.0}=0x01652734 +phy_chain_rx_lane_map_physical{185.0}=0x25743160 +phy_chain_tx_lane_map_physical{185.0}=0x37016425 +phy_chain_rx_lane_map_physical{193.0}=0x46510372 +phy_chain_tx_lane_map_physical{193.0}=0x06153724 +phy_chain_rx_lane_map_physical{201.0}=0x25743160 +phy_chain_tx_lane_map_physical{201.0}=0x36017524 +phy_chain_rx_lane_map_physical{209.0}=0x47601352 +phy_chain_tx_lane_map_physical{209.0}=0x04152736 +phy_chain_rx_lane_map_physical{217.0}=0x26453170 +phy_chain_tx_lane_map_physical{217.0}=0x36027415 + +serdes_core_rx_polarity_flip_physical{33}=0x29 +serdes_core_tx_polarity_flip_physical{33}=0xfe +serdes_core_rx_polarity_flip_physical{41}=0xb1 +serdes_core_tx_polarity_flip_physical{41}=0xe8 +serdes_core_rx_polarity_flip_physical{49}=0xca +serdes_core_tx_polarity_flip_physical{49}=0xb6 +serdes_core_rx_polarity_flip_physical{57}=0x9b +serdes_core_tx_polarity_flip_physical{57}=0xdc +serdes_core_rx_polarity_flip_physical{65}=0x17 +serdes_core_tx_polarity_flip_physical{65}=0x86 +serdes_core_rx_polarity_flip_physical{73}=0x9b +serdes_core_tx_polarity_flip_physical{73}=0x55 +serdes_core_rx_polarity_flip_physical{81}=0xa +serdes_core_tx_polarity_flip_physical{81}=0x6 +serdes_core_rx_polarity_flip_physical{89}=0x9b +serdes_core_tx_polarity_flip_physical{89}=0x48 +serdes_core_rx_polarity_flip_physical{1}=0xec +serdes_core_tx_polarity_flip_physical{1}=0x56 +serdes_core_rx_polarity_flip_physical{9}=0x13 +serdes_core_tx_polarity_flip_physical{9}=0xa6 +serdes_core_rx_polarity_flip_physical{17}=0x5a +serdes_core_tx_polarity_flip_physical{17}=0xc6 +serdes_core_rx_polarity_flip_physical{25}=0xf +serdes_core_tx_polarity_flip_physical{25}=0x4e +serdes_core_rx_polarity_flip_physical{97}=0x17 +serdes_core_tx_polarity_flip_physical{97}=0x2e +serdes_core_rx_polarity_flip_physical{105}=0xce +serdes_core_tx_polarity_flip_physical{105}=0x7c +serdes_core_rx_polarity_flip_physical{113}=0xa +serdes_core_tx_polarity_flip_physical{113}=0x35 + +serdes_core_rx_polarity_flip_physical{121}=0xb9 +serdes_core_tx_polarity_flip_physical{121}=0xef +serdes_core_rx_polarity_flip_physical{129}=0xe8 +serdes_core_tx_polarity_flip_physical{129}=0xac +serdes_core_rx_polarity_flip_physical{137}=0xcb +serdes_core_tx_polarity_flip_physical{137}=0x9c +serdes_core_rx_polarity_flip_physical{145}=0x17 +serdes_core_tx_polarity_flip_physical{145}=0x32 +serdes_core_rx_polarity_flip_physical{153}=0xb9 +serdes_core_tx_polarity_flip_physical{153}=0xaf +serdes_core_rx_polarity_flip_physical{225}=0xaa +serdes_core_tx_polarity_flip_physical{225}=0x7 +serdes_core_rx_polarity_flip_physical{233}=0x31 +serdes_core_tx_polarity_flip_physical{233}=0x47 +serdes_core_rx_polarity_flip_physical{241}=0xe8 +serdes_core_tx_polarity_flip_physical{241}=0x9e +serdes_core_rx_polarity_flip_physical{249}=0xec +serdes_core_tx_polarity_flip_physical{249}=0x1f +serdes_core_rx_polarity_flip_physical{161}=0x6a +serdes_core_tx_polarity_flip_physical{161}=0xd4 +serdes_core_rx_polarity_flip_physical{169}=0x9e +serdes_core_tx_polarity_flip_physical{169}=0x7b +serdes_core_rx_polarity_flip_physical{177}=0x6a +serdes_core_tx_polarity_flip_physical{177}=0xcc +serdes_core_rx_polarity_flip_physical{185}=0x9e +serdes_core_tx_polarity_flip_physical{185}=0x58 +serdes_core_rx_polarity_flip_physical{193}=0x6f +serdes_core_tx_polarity_flip_physical{193}=0x24 +serdes_core_rx_polarity_flip_physical{201}=0x9e +serdes_core_tx_polarity_flip_physical{201}=0xdf +serdes_core_rx_polarity_flip_physical{209}=0x17 +serdes_core_tx_polarity_flip_physical{209}=0xe9 +serdes_core_rx_polarity_flip_physical{217}=0xec +serdes_core_tx_polarity_flip_physical{217}=0x68 + +serdes_lane_config_media_type_49=copper +serdes_lane_config_media_type_50=copper +serdes_lane_config_media_type_51=copper +serdes_lane_config_media_type_52=copper +serdes_lane_config_media_type_54=copper +serdes_lane_config_media_type_55=copper +serdes_lane_config_media_type_56=copper +serdes_lane_config_media_type_57=copper +serdes_lane_config_media_type_53=copper +serdes_lane_config_media_type_60=copper +serdes_lane_config_media_type_61=copper +serdes_lane_config_media_type_62=copper +serdes_lane_config_media_type_63=copper +serdes_lane_config_media_type_65=copper +serdes_lane_config_media_type_66=copper +serdes_lane_config_media_type_67=copper +serdes_lane_config_media_type_68=copper +serdes_lane_config_media_type_64=copper +serdes_lane_config_media_type_80=copper +serdes_lane_config_media_type_81=copper +serdes_lane_config_media_type_82=copper +serdes_lane_config_media_type_83=copper +serdes_lane_config_media_type_85=copper +serdes_lane_config_media_type_86=copper +serdes_lane_config_media_type_87=copper +serdes_lane_config_media_type_88=copper +serdes_lane_config_media_type_84=copper +serdes_lane_config_media_type_100=copper +serdes_lane_config_media_type_101=copper +serdes_lane_config_media_type_102=copper +serdes_lane_config_media_type_103=copper +serdes_lane_config_media_type_105=copper +serdes_lane_config_media_type_106=copper +serdes_lane_config_media_type_107=copper +serdes_lane_config_media_type_108=copper +serdes_lane_config_media_type_104=copper +serdes_lane_config_media_type_120=copper +serdes_lane_config_media_type_121=copper +serdes_lane_config_media_type_122=copper +serdes_lane_config_media_type_123=copper +serdes_lane_config_media_type_125=copper +serdes_lane_config_media_type_126=copper +serdes_lane_config_media_type_127=copper +serdes_lane_config_media_type_128=copper +serdes_lane_config_media_type_124=copper +serdes_lane_config_media_type_140=copper +serdes_lane_config_media_type_141=copper +serdes_lane_config_media_type_142=copper +serdes_lane_config_media_type_143=copper +serdes_lane_config_media_type_145=copper +serdes_lane_config_media_type_146=copper +serdes_lane_config_media_type_147=copper +serdes_lane_config_media_type_148=copper +serdes_lane_config_media_type_144=copper +serdes_lane_config_media_type_40=copper +serdes_lane_config_media_type_41=copper +serdes_lane_config_media_type_42=copper +serdes_lane_config_media_type_43=copper +serdes_lane_config_media_type_45=copper +serdes_lane_config_media_type_46=copper +serdes_lane_config_media_type_47=copper +serdes_lane_config_media_type_48=copper +serdes_lane_config_media_type_44=copper +serdes_lane_config_media_type_69=copper +serdes_lane_config_media_type_70=copper +serdes_lane_config_media_type_71=copper +serdes_lane_config_media_type_72=copper +serdes_lane_config_media_type_74=copper +serdes_lane_config_media_type_75=copper +serdes_lane_config_media_type_76=copper +serdes_lane_config_media_type_77=copper +serdes_lane_config_media_type_73=copper +serdes_lane_config_media_type_1=copper +serdes_lane_config_media_type_2=copper +serdes_lane_config_media_type_3=copper +serdes_lane_config_media_type_4=copper +serdes_lane_config_media_type_6=copper +serdes_lane_config_media_type_7=copper +serdes_lane_config_media_type_8=copper +serdes_lane_config_media_type_9=copper +serdes_lane_config_media_type_5=copper +serdes_lane_config_media_type_29=copper +serdes_lane_config_media_type_30=copper +serdes_lane_config_media_type_31=copper +serdes_lane_config_media_type_32=copper +serdes_lane_config_media_type_34=copper +serdes_lane_config_media_type_35=copper +serdes_lane_config_media_type_36=copper +serdes_lane_config_media_type_37=copper +serdes_lane_config_media_type_33=copper +serdes_lane_config_media_type_89=copper +serdes_lane_config_media_type_90=copper +serdes_lane_config_media_type_91=copper +serdes_lane_config_media_type_92=copper +serdes_lane_config_media_type_94=copper +serdes_lane_config_media_type_95=copper +serdes_lane_config_media_type_96=copper +serdes_lane_config_media_type_97=copper +serdes_lane_config_media_type_93=copper +serdes_lane_config_media_type_109=copper +serdes_lane_config_media_type_110=copper +serdes_lane_config_media_type_111=copper +serdes_lane_config_media_type_112=copper +serdes_lane_config_media_type_114=copper +serdes_lane_config_media_type_115=copper +serdes_lane_config_media_type_116=copper +serdes_lane_config_media_type_117=copper +serdes_lane_config_media_type_113=copper +serdes_lane_config_media_type_129=copper +serdes_lane_config_media_type_130=copper +serdes_lane_config_media_type_131=copper +serdes_lane_config_media_type_132=copper +serdes_lane_config_media_type_134=copper +serdes_lane_config_media_type_135=copper +serdes_lane_config_media_type_136=copper +serdes_lane_config_media_type_137=copper +serdes_lane_config_media_type_133=copper +serdes_lane_config_media_type_149=copper +serdes_lane_config_media_type_150=copper +serdes_lane_config_media_type_151=copper +serdes_lane_config_media_type_152=copper +serdes_lane_config_media_type_154=copper +serdes_lane_config_media_type_155=copper +serdes_lane_config_media_type_156=copper +serdes_lane_config_media_type_157=copper +serdes_lane_config_media_type_153=copper +serdes_lane_config_media_type_10=copper +serdes_lane_config_media_type_11=copper +serdes_lane_config_media_type_12=copper +serdes_lane_config_media_type_13=copper +serdes_lane_config_media_type_15=copper +serdes_lane_config_media_type_16=copper +serdes_lane_config_media_type_17=copper +serdes_lane_config_media_type_18=copper +serdes_lane_config_media_type_14=copper +serdes_lane_config_media_type_20=copper +serdes_lane_config_media_type_21=copper +serdes_lane_config_media_type_22=copper +serdes_lane_config_media_type_23=copper +serdes_lane_config_media_type_25=copper +serdes_lane_config_media_type_26=copper +serdes_lane_config_media_type_27=copper +serdes_lane_config_media_type_28=copper +serdes_lane_config_media_type_24=copper + +#sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc + diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/default_sku b/device/dell/x86_64-dellemc_z9332f_d1508-r0/default_sku new file mode 100644 index 000000000000..7716a7af3216 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/default_sku @@ -0,0 +1 @@ +DellEMC-Z9332f-O32 t1 diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/installer.conf b/device/dell/x86_64-dellemc_z9332f_d1508-r0/installer.conf new file mode 100644 index 000000000000..924e0fb81963 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/led_proc_init.soc b/device/dell/x86_64-dellemc_z9332f_d1508-r0/led_proc_init.soc new file mode 100644 index 000000000000..0c116f35f80b --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/led_proc_init.soc @@ -0,0 +1,7 @@ +# LED microprocessor initialization for Dell z9332f +# +# +#Led0 +#Support only after SAI 3.6 +#led auto on +#led start diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/plugins/eeprom.py b/device/dell/x86_64-dellemc_z9332f_d1508-r0/plugins/eeprom.py new file mode 100644 index 000000000000..a346f1957be4 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# DellEMC Z9332f +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/plugins/psuutil.py b/device/dell/x86_64-dellemc_z9332f_d1508-r0/plugins/psuutil.py new file mode 100644 index 000000000000..435f9b2929ec --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/plugins/psuutil.py @@ -0,0 +1,129 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path +import logging +import sys + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + + +Z9332F_MAX_PSUS = 2 +IPMI_PSU1_DATA = "docker exec -it pmon ipmitool raw 0x04 0x2d 0x2f | awk '{print substr($0,9,1)}'" +IPMI_PSU1_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x2f | awk '{print substr($0,9,1)}'" +IPMI_PSU2_DATA = "docker exec -it pmon ipmitool raw 0x04 0x2d 0x39 | awk '{print substr($0,9,1)}'" +IPMI_PSU2_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x39 | awk '{print substr($0,9,1)}'" +PSU_PRESENCE = "PSU{0}_Status" +# Use this for older firmware +# PSU_PRESENCE="PSU{0}_prsnt" +ipmi_sdr_list = "" + + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def isDockerEnv(self): + num_docker = open('/proc/self/cgroup', 'r').read().count(":/docker") + if num_docker > 0: + return True + else: + return False + + # Fetch a BMC register + def get_pmc_register(self, reg_name): + + status = 1 + global ipmi_sdr_list + ipmi_dev_node = "/dev/pmi0" + ipmi_cmd_1 = IPMI_PSU1_DATA + ipmi_cmd_2 = IPMI_PSU1_DATA + dockerenv = self.isDockerEnv() + if dockerenv == True: + 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 ipmitool') + sys.exit(0) + + output = ipmi_sdr_list + + return output + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + Z9332F_MAX_PSUS = 2 + return Z9332F_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 + """ + # Until psu_status is implemented this is hardcoded temporarily + + status = 1 + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :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 + global ipmi_sdr_list + ipmi_dev_node = "/dev/pmi0" + dockerenv = self.isDockerEnv() + if dockerenv == True: + 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: + ret_status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA) + + # if ret_status: + # print ipmi_sdr_list + # logging.error('Failed to execute ipmitool') + # sys.exit(0) + + psu_status = ipmi_sdr_list + + if psu_status == '1': + status = 1 + + return status diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_z9332f_d1508-r0/plugins/sfputil.py new file mode 100644 index 000000000000..d037fd9273dd --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/plugins/sfputil.py @@ -0,0 +1,301 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import struct + import sys + import getopt + import time + import select + from sonic_sfp.sfputilbase import SfpUtilBase + from os import * + from mmap import * + +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# from xcvrd +SFP_STATUS_REMOVED = '0' +SFP_STATUS_INSERTED = '1' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 34 + PORTS_IN_BLOCK = 34 + + BASE_RES_PATH = "/sys/bus/pci/devices/0000:09:00.0/resource0" + + _port_to_i2c_mapping = { + 1: 10, + 2: 11, + 3: 12, + 4: 13, + 5: 14, + 6: 15, + 7: 16, + 8: 17, + 9: 18, + 10: 19, + 11: 20, + 12: 21, + 13: 22, + 14: 23, + 15: 24, + 16: 25, + 17: 26, + 18: 27, + 19: 28, + 20: 29, + 21: 30, + 22: 31, + 23: 32, + 24: 33, + 25: 34, + 26: 35, + 27: 36, + 28: 37, + 29: 38, + 30: 39, + 31: 40, + 32: 41, + 33: 1, + 34: 2, + } + + _port_to_eeprom_mapping = {} + + _global_port_pres_dict = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def pci_mem_read(self, mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + reg_val = struct.unpack('I', read_data_stream) + mem_val = str(reg_val)[1:-2] + # print "reg_val read:%x"%reg_val + return mem_val + + def pci_mem_write(self, mm, offset, data): + mm.seek(offset) + # print "data to write:%x"%data + mm.write(struct.pack('I', data)) + + def pci_set_value(self, resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_write(mm, offset, val) + mm.close() + close(fd) + return val + + def pci_get_value(self, resource, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_read(mm, offset) + mm.close() + close(fd) + return val + + def init_global_port_presence(self): + for port_num in range(self.port_start, (self.port_end + 1)): + presence = self.get_presence(port_num) + if(presence): + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def mod_pres(self): + port_pres_mask = 0 + for port_num in range(self.port_start, (self.port_end + 1)): + presence = self.get_presence(port_num) + if(presence): + self._global_port_pres_dict[port_num] = '1' + port_val = (1 << (port_num - 1)) + port_pres_mask = (port_pres_mask | port_val) + else: + self._global_port_pres_dict[port_num] = '0' + port_val = ~(1 << (port_num - 1)) + port_pres_mask = (port_pres_mask & port_val) + + return port_pres_mask + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(self.port_start, self.port_end + 1): + self.port_to_eeprom_mapping[x] = eeprom_path.format( + self._port_to_i2c_mapping[x]) + self.init_global_port_presence() + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4004 + port_offset = 16388 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 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 + + return False + + def get_low_power_mode(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + def reset(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # Port offset starts with 0x4000 + port_offset = 16384 + ((port_num-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + mask = (1 << 6) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + # Sleep 1 second to allow it to settle + time.sleep(1) + + reg_value = reg_value | mask + + # Convert our register value back to a hex string and write back + status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + def get_register(self, reg_file): + retval = 'ERR' + if (not path.isfile(reg_file)): + print(reg_file + ' not found !') + return retval + + try: + with fdopen(open(reg_file, O_RDONLY)) as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", reg_file, "file !") + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + + 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) diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/pmon_daemon_control.json b/device/dell/x86_64-dellemc_z9332f_d1508-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..94592fa8cebc --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/system_health_monitoring_config.json b/device/dell/x86_64-dellemc_z9332f_d1508-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..d52b24cf905d --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/system_health_monitoring_config.json @@ -0,0 +1,11 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": ["asic","fan.speed"], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "yellow", + "normal": "green", + "booting": "flash_green" + } +} diff --git a/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/port_config.ini b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/port_config.ini new file mode 100644 index 000000000000..ace4228d861a --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias +Ethernet0 65 twentyfiveGigE1 +Ethernet4 66 twentyfiveGigE2 +Ethernet8 67 twentyfiveGigE3 +Ethernet12 68 twentyfiveGigE4 +Ethernet16 69 twentyfiveGigE5 +Ethernet20 70 twentyfiveGigE6 +Ethernet24 71 twentyfiveGigE7 +Ethernet28 72 twentyfiveGigE8 +Ethernet32 81 twentyfiveGigE9 +Ethernet36 82 twentyfiveGigE10 +Ethernet40 83 twentyfiveGigE11 +Ethernet44 84 twentyfiveGigE12 +Ethernet48 85 twentyfiveGigE13 +Ethernet52 86 twentyfiveGigE14 +Ethernet56 87 twentyfiveGigE15 +Ethernet60 88 twentyfiveGigE16 +Ethernet64 33 twentyfiveGigE17 +Ethernet68 34 twentyfiveGigE18 +Ethernet72 35 twentyfiveGigE19 +Ethernet76 36 twentyfiveGigE20 +Ethernet80 37 twentyfiveGigE21 +Ethernet84 38 twentyfiveGigE22 +Ethernet88 39 twentyfiveGigE23 +Ethernet92 40 twentyfiveGigE24 +Ethernet96 42 twentyfiveGigE25 +Ethernet100 41 twentyfiveGigE26 +Ethernet104 44 twentyfiveGigE27 +Ethernet108 43 twentyfiveGigE28 +Ethernet112 49 twentyfiveGigE29 +Ethernet116 50 twentyfiveGigE30 +Ethernet120 51 twentyfiveGigE31 +Ethernet124 52 twentyfiveGigE32 +Ethernet128 53 twentyfiveGigE33 +Ethernet132 54 twentyfiveGigE34 +Ethernet136 55 twentyfiveGigE35 +Ethernet140 56 twentyfiveGigE36 +Ethernet144 97 twentyfiveGigE37 +Ethernet148 98 twentyfiveGigE38 +Ethernet152 99 twentyfiveGigE39 +Ethernet156 100 twentyfiveGigE40 +Ethernet160 101 twentyfiveGigE41 +Ethernet164 102 twentyfiveGigE42 +Ethernet168 103 twentyfiveGigE43 +Ethernet172 104 twentyfiveGigE44 +Ethernet176 105 twentyfiveGigE45 +Ethernet180 106 twentyfiveGigE46 +Ethernet184 107 twentyfiveGigE47 +Ethernet188 108 twentyfiveGigE48 +Ethernet192 117,118,119,120 hundredGigE51 +Ethernet196 109,110,111,112 hundredGigE51 +Ethernet200 5,6,7,8 hundredGigE51 +Ethernet204 1,2,3,4 hundredGigE52 +Ethernet208 21,22,23,24 hundredGigE53 +Ethernet212 9,10,11,12 hundredGigE54 diff --git a/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/sai.profile b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/sai.profile new file mode 100644 index 000000000000..98876a9c2a39 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-ag5648-48x25G+6x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/th-ag5648-48x25G+6x100G.config.bcm b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/th-ag5648-48x25G+6x100G.config.bcm new file mode 100644 index 000000000000..86afb258fd1b --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/Delta-ag5648/th-ag5648-48x25G+6x100G.config.bcm @@ -0,0 +1,277 @@ +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +pbmp_oversubscribe=0x000fffc0000ffff0003ffffc0000001e +pbmp_xport_xe=0x000fffc0000ffff0003ffffc0000001e + +# Tile-0: 1, 5, 9, 21 +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=21:100 + +## TX lane swap +xgxs_tx_lane_map_1=0x0123 +xgxs_tx_lane_map_2=0x2301 +xgxs_tx_lane_map_3=0x0123 +xgxs_tx_lane_map_4=0x1302 + +## RX lane swap +xgxs_rx_lane_map_1=0x0123 +xgxs_rx_lane_map_2=0x2301 +xgxs_rx_lane_map_3=0x0123 +xgxs_rx_lane_map_4=0x2031 + +## TX polarity +phy_xaui_tx_polarity_flip_1=0x0 +phy_xaui_tx_polarity_flip_2=0xf +phy_xaui_tx_polarity_flip_3=0x0 +phy_xaui_tx_polarity_flip_4=0xf + +## RX polarity +phy_xaui_rx_polarity_flip_1=0x0 +phy_xaui_rx_polarity_flip_2=0xf +phy_xaui_rx_polarity_flip_3=0x0 +phy_xaui_rx_polarity_flip_4=0xf + + +# Tile-1: 8, 9, 11, 12, 13 +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 +portmap_46=49:25 +portmap_47=50:25 +portmap_48=51:25 +portmap_49=52:25 +portmap_50=53:25 +portmap_51=54:25 +portmap_52=55:25 +portmap_53=56:25 + + +## TX lane swap +xgxs_tx_lane_map_34=0x3210 +xgxs_tx_lane_map_38=0x0123 +xgxs_tx_lane_map_42=0x2031 +xgxs_tx_lane_map_46=0x0123 +xgxs_tx_lane_map_50=0x0123 + +## RX lane swap +xgxs_rx_lane_map_34=0x2301 +xgxs_rx_lane_map_38=0x1032 +xgxs_rx_lane_map_42=0x0213 +xgxs_rx_lane_map_46=0x2301 +xgxs_rx_lane_map_50=0x2301 + + +## TX polarity +phy_xaui_tx_polarity_flip_34=0x0 +phy_xaui_tx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_36=0x0 +phy_xaui_tx_polarity_flip_37=0x1 + +phy_xaui_tx_polarity_flip_38=0x1 +phy_xaui_tx_polarity_flip_39=0x0 +phy_xaui_tx_polarity_flip_40=0x1 +phy_xaui_tx_polarity_flip_41=0x0 + +phy_xaui_tx_polarity_flip_42=0x1 +phy_xaui_tx_polarity_flip_43=0x0 +phy_xaui_tx_polarity_flip_44=0x1 +phy_xaui_tx_polarity_flip_45=0x0 + +phy_xaui_tx_polarity_flip_46=0x0 +phy_xaui_tx_polarity_flip_47=0x1 +phy_xaui_tx_polarity_flip_48=0x0 +phy_xaui_tx_polarity_flip_49=0x1 + +phy_xaui_tx_polarity_flip_50=0x0 +phy_xaui_tx_polarity_flip_51=0x1 +phy_xaui_tx_polarity_flip_52=0x0 +phy_xaui_tx_polarity_flip_53=0x1 + + +## RX polarity +phy_xaui_rx_polarity_flip_34=0x0 +phy_xaui_rx_polarity_flip_35=0x1 +phy_xaui_rx_polarity_flip_36=0x0 +phy_xaui_rx_polarity_flip_37=0x1 + +phy_xaui_rx_polarity_flip_38=0x1 +phy_xaui_rx_polarity_flip_39=0x0 +phy_xaui_rx_polarity_flip_40=0x1 +phy_xaui_rx_polarity_flip_41=0x0 + +phy_xaui_rx_polarity_flip_42=0x1 +phy_xaui_rx_polarity_flip_43=0x0 +phy_xaui_rx_polarity_flip_44=0x1 +phy_xaui_rx_polarity_flip_45=0x0 + +phy_xaui_rx_polarity_flip_46=0x0 +phy_xaui_rx_polarity_flip_47=0x1 +phy_xaui_rx_polarity_flip_48=0x0 +phy_xaui_rx_polarity_flip_49=0x1 + +phy_xaui_rx_polarity_flip_50=0x0 +phy_xaui_rx_polarity_flip_51=0x1 +phy_xaui_rx_polarity_flip_52=0x0 +phy_xaui_rx_polarity_flip_53=0x1 + + +# Tile-2: 16, 17, 20, 21 +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 +portmap_76=81:25 +portmap_77=82:25 +portmap_78=83:25 +portmap_79=84:25 +portmap_80=85:25 +portmap_81=86:25 +portmap_82=87:25 +portmap_83=88:25 + + +## TX lane swap +xgxs_tx_lane_map_68=0x3210 +xgxs_tx_lane_map_72=0x0123 +xgxs_tx_lane_map_76=0x0123 +xgxs_tx_lane_map_80=0x3210 + +## RX lane swap +xgxs_rx_lane_map_68=0x1032 +xgxs_rx_lane_map_72=0x2301 +xgxs_rx_lane_map_76=0x0123 +xgxs_rx_lane_map_80=0x3210 + + +## TX polarity +phy_xaui_tx_polarity_flip_68=0x0 +phy_xaui_tx_polarity_flip_69=0x1 +phy_xaui_tx_polarity_flip_70=0x0 +phy_xaui_tx_polarity_flip_71=0x1 + +phy_xaui_tx_polarity_flip_72=0x0 +phy_xaui_tx_polarity_flip_73=0x1 +phy_xaui_tx_polarity_flip_74=0x0 +phy_xaui_tx_polarity_flip_75=0x1 + +phy_xaui_tx_polarity_flip_76=0x0 +phy_xaui_tx_polarity_flip_77=0x1 +phy_xaui_tx_polarity_flip_78=0x0 +phy_xaui_tx_polarity_flip_79=0x1 + +phy_xaui_tx_polarity_flip_80=0x1 +phy_xaui_tx_polarity_flip_81=0x0 +phy_xaui_tx_polarity_flip_82=0x1 +phy_xaui_tx_polarity_flip_83=0x0 + +## RX polarity +phy_xaui_rx_polarity_flip_68=0x0 +phy_xaui_rx_polarity_flip_69=0x1 +phy_xaui_rx_polarity_flip_70=0x0 +phy_xaui_rx_polarity_flip_71=0x1 + +phy_xaui_rx_polarity_flip_72=0x0 +phy_xaui_rx_polarity_flip_73=0x1 +phy_xaui_rx_polarity_flip_74=0x0 +phy_xaui_rx_polarity_flip_75=0x1 + +phy_xaui_rx_polarity_flip_76=0x0 +phy_xaui_rx_polarity_flip_77=0x1 +phy_xaui_rx_polarity_flip_78=0x0 +phy_xaui_rx_polarity_flip_79=0x1 + +phy_xaui_rx_polarity_flip_80=0x1 +phy_xaui_rx_polarity_flip_81=0x0 +phy_xaui_rx_polarity_flip_82=0x1 +phy_xaui_rx_polarity_flip_83=0x0 + + +# Tile-3: 24, 25, 26; 27, 29 +portmap_102=97:25 +portmap_103=98:25 +portmap_104=99:25 +portmap_105=100:25 +portmap_106=101:25 +portmap_107=102:25 +portmap_108=103:25 +portmap_109=104:25 +portmap_110=105:25 +portmap_111=106:25 +portmap_112=107:25 +portmap_113=108:25 +portmap_114=109:100 +portmap_115=117:100 + + +## TX lane swap +xgxs_tx_lane_map_102=0x0123 +xgxs_tx_lane_map_106=0x3210 +xgxs_tx_lane_map_110=0x0123 +xgxs_tx_lane_map_114=0x3120 +xgxs_tx_lane_map_115=0x2301 + +## RX lane swap +xgxs_rx_lane_map_102=0x0123 +xgxs_rx_lane_map_106=0x3210 +xgxs_rx_lane_map_110=0x0123 +xgxs_rx_lane_map_114=0x3120 +xgxs_rx_lane_map_115=0x2301 + +## TX polarity +phy_xaui_tx_polarity_flip_102=0 +phy_xaui_tx_polarity_flip_103=1 +phy_xaui_tx_polarity_flip_104=0 +phy_xaui_tx_polarity_flip_105=1 + +phy_xaui_tx_polarity_flip_106=1 +phy_xaui_tx_polarity_flip_107=0 +phy_xaui_tx_polarity_flip_108=1 +phy_xaui_tx_polarity_flip_109=0 + +phy_xaui_tx_polarity_flip_110=0 +phy_xaui_tx_polarity_flip_111=1 +phy_xaui_tx_polarity_flip_112=0 +phy_xaui_tx_polarity_flip_113=1 + +phy_xaui_tx_polarity_flip_114=0xf +phy_xaui_tx_polarity_flip_115=0xf + +## RX polarity +phy_xaui_rx_polarity_flip_102=0 +phy_xaui_rx_polarity_flip_103=1 +phy_xaui_rx_polarity_flip_104=0 +phy_xaui_rx_polarity_flip_105=1 + +phy_xaui_rx_polarity_flip_106=1 +phy_xaui_rx_polarity_flip_107=0 +phy_xaui_rx_polarity_flip_108=1 +phy_xaui_rx_polarity_flip_109=0 + +phy_xaui_rx_polarity_flip_110=0 +phy_xaui_rx_polarity_flip_111=1 +phy_xaui_rx_polarity_flip_112=0 +phy_xaui_rx_polarity_flip_113=1 + +phy_xaui_rx_polarity_flip_114=0xf +phy_xaui_rx_polarity_flip_115=0xf diff --git a/device/delta/x86_64-delta_ag5648-r0/default_sku b/device/delta/x86_64-delta_ag5648-r0/default_sku new file mode 100644 index 000000000000..c4ce98e35557 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/default_sku @@ -0,0 +1 @@ +Delta-ag5648 t1 diff --git a/device/delta/x86_64-delta_ag5648-r0/fancontrol b/device/delta/x86_64-delta_ag5648-r0/fancontrol new file mode 100644 index 000000000000..2666ad97d9ce --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=10 +DEVPATH=hwmon1=/sys/bus/i2c/devices +DEVNAME=hwmon1=emc2305 +FCTEMPS=DEVPATH/2-004d/hwmon/hwmon*/temp1_input DEVPATH/3-0049/hwmon/hwmon*/temp1_input DEVPATH/3-004b/hwmon/hwmon*/temp1_input DEVPATH/3-004c/hwmon/hwmon*/temp1_input DEVPATH/3-004e/hwmon/hwmon*/temp1_input DEVPATH/3-004f/hwmon/hwmon*/temp1_input DEVPATH/6-0059/temp1_input DEVPATH/6-0058/temp1_input + +FCFANS=DEVPATH/3-004d/fan1_input DEVPATH/3-004d/fan2_input DEVPATH/3-004d/fan3_input DEVPATH/3-004d/fan4_input DEVPATH/5-004d/fan1_input DEVPATH/5-004d/fan2_input DEVPATH/5-004d/fan3_input DEVPATH/5-004d/fan4_input +MINTEMP=20 +MAXTEMP=60 +MINSTART=75 +MINSTOP=22 diff --git a/device/delta/x86_64-delta_ag5648-r0/fancontrol.service b/device/delta/x86_64-delta_ag5648-r0/fancontrol.service new file mode 100755 index 000000000000..ace4392f436d --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/fancontrol.service @@ -0,0 +1,262 @@ +#!/bin/bash +# +# Simple script implementing a temperature dependent fan speed control +# Supported Linux kernel versions: 2.6.5 and later +# +# Version 0.70 +# +# Usage: fancontrol.service [CONFIGFILE] +# +# Dependencies: +# bash, egrep, sed, cut, sleep, readlink, lm_sensors :) +# +# Please send any questions, comments or success stories to +# marius.reiner@hdev.de +# Thanks! +# +# For configuration instructions and warnings please see fancontrol.txt, which +# can be found in the doc/ directory or at the website mentioned above. +# +# +# Copyright 2003 Marius Reiner +# Copyright (C) 2007-2009 Jean Delvare +# +# 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. +# +# 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 Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +# + +PIDFILE="/var/run/fancontrol.pid" + +#DEBUG=1 +MAX=255 + +function LoadConfig +{ + local fcvcount fcv + + echo "Loading configuration from $1 ..." + if [ ! -r "$1" ] + then + echo "Error: Can't read configuration file" >&2 + exit 1 + fi + + # grep configuration from file + INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'` + DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'` + DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'` + FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'` + MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'` + MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'` + MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'` + MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'` + HWMON=$( echo "$DEVPATH" | sed 's/=.*$//g') + FCDEVPATH=$( echo "$DEVPATH" | sed 's/^.*=//g') + FCMINTEMP=$MINTEMP + FCMAXTEMP=$MAXTEMP + FCMINSTART=$MINSTART + FCMINSTOP=$MINSTOP + + FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'` + + # Check whether all mandatory settings are set + if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]] + then + echo "Some mandatory settings missing, please check your config file!" >&2 + exit 1 + fi + if [ "$INTERVAL" -le 0 ] + then + echo "Error in configuration file:" >&2 + echo "INTERVAL must be at least 1" >&2 + exit 1 + fi + + # write settings to arrays for easier use and print them + echo "Common settings:" + + temp_string=$FCTEMPS + + let fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( echo "$temp_string" | cut -d" " -f $fcvcount ) + AFCTEMP[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP_PATH[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' ) + + #if [ $fcvcount -eq 5 ];then + #echo "0x00" > '/sys/bus/i2c/devices/6-0058/psu_select_member' + # AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + #elif [ $fcvcount -eq 6 ];then + #echo "0x20" > '/sys/bus/i2c/devices/6-0058/psu_select_member' + # AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + #else + # AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + #fi + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + echo "AFCTEMP[$fcvcount]=${AFCTEMP[$fcvcount]} (Celsius)" + done + + fan_string=$FCFANS + fcvcount=0 + zero=0 + for fcv in $FCFANS + do + fcvcount=$((fcvcount+1)) + AFCFAN[$fcvcount]=$( echo "$fan_string" | cut -d" " -f $fcvcount ) + AFCFAN_PATH[$fcvcount]=$( echo "${AFCFAN[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_PATH[$fcvcount]}" | sed 's/DEVPATH/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_TARGET[$fcvcount]}" | sed 's/$/_percentage/g') + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + echo "AFCFAN[$fcvcount]=${AFCFAN[$fcvcount]} (rpm)" + done + echo "INTERVAL=$INTERVAL" + echo "DEVPATH=$FCDEVPATH" + echo "MINTEMP=$FCMINTEMP" + echo "MAXTEMP=$FCMAXTEMP" + echo "MINSTART=$FCMINSTART" + echo "MINSTOP=$FCMINSTOP" +} + +# Check that all referenced sysfs files exist +function CheckFiles +{ + local outdated=0 fcvcount tsen fan + if [ $outdated -eq 1 ] + then + echo >&2 + echo "At least one referenced file is missing. Either some required kernel" >&2 + echo "modules haven't been loaded, or your configuration file is outdated." >&2 + echo "In the latter case, you should run pwmconfig again." >&2 + fi + return $outdated +} + +LoadConfig $1 + +# Detect path to sensors +if [ ! -d $DIR ] +then + echo $0: 'No sensors found! (did you load the necessary modules?)' >&2 + exit 1 +fi +cd $DIR + +# Check for configuration change +if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] +then + echo "Configuration is too old, please run pwmconfig again" >&2 + exit 1 +fi +if [ "$DIR" = "/" -a -n "$DEVPATH" ] +then + echo "Unneeded DEVPATH with absolute device paths" >&2 + exit 1 +fi +CheckFiles || exit 1 + +if [ -f "$PIDFILE" ] +then + echo "File $PIDFILE exists, is fancontrol already running?" >&2 + exit 1 +fi +echo $$ > "$PIDFILE" + + +# main function +function UpdateThermalSensors +{ + echo "" + TEMP_HIGHEST=0 + FAN_PERCENTAGE=0 + + for i in ${AFCTEMP_PATH[@]}; do + if (( $(cat $i) > $TEMP_HIGHEST )); then + TEMP_HIGHEST=$(cat $i); + fi; + done + TEMP_HIGHEST=$((TEMP_HIGHEST/1000)) + echo "The highest temperature of thermal sensors: $TEMP_HIGHEST C" + +} + +function UpdateFanSpeeds +{ + if [ $TEMP_HIGHEST -lt 51 ]; then #TEMP<=50 + FAN_PERCENTAGE=40 + elif [ $TEMP_HIGHEST -lt 56 -a $TEMP_HIGHEST -gt 50 ]; then #50 ${AFCFAN_TARGET[$fcvcount]} + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + echo "AFCFAN[$fcvcount]=${AFCFAN[$fcvcount]} (rpm)" + done + + if [ $TEMP_HIGHEST -lt 51 ]; then #TEMP<=50 + FAN_ON_PSU_PERCENTAGE=50 + elif [ $TEMP_HIGHEST -lt 100 -a $TEMP_HIGHEST -gt 50 ]; then #50 '/sys/bus/i2c/devices/4-0058/psu_select_member' + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/6-0059/fan1_set_percentage' + echo "PSU fan1 =$( cat '/sys/bus/i2c/devices/6-0059/fan1_input' ) (rpm)" + #Set speed to PSU_FAN2 + #echo "0x20" > '/sys/bus/i2c/devices/6-0058/psu_select_member' + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/6-0058/fan1_set_percentage' + echo "PSU fan2 =$( cat '/sys/bus/i2c/devices/6-0058/fan1_input' ) (rpm)" + + rm -f "$PIDFILE" +} +# main loop calling the main function at specified intervals +while true +do + UpdateThermalSensors + UpdateFanSpeeds + echo "Sleep $INTERVAL seconds ..." + # Sleep while still handling signals + sleep $INTERVAL & + wait $! +done diff --git a/device/delta/x86_64-delta_ag5648-r0/installer.conf b/device/delta/x86_64-delta_ag5648-r0/installer.conf new file mode 100644 index 000000000000..85ed43ab48ed --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_SPEED=115200 +CONSOLE_DEV=0 diff --git a/device/delta/x86_64-delta_ag5648-r0/led_proc_init.soc b/device/delta/x86_64-delta_ag5648-r0/led_proc_init.soc new file mode 100755 index 000000000000..a329017fbde8 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/led_proc_init.soc @@ -0,0 +1,67 @@ +#AG5648 LED + +led 0 stop +led 0 prog \ + 02 00 60 E0 02 A0 60 E2 86 ED 02 00 60 E1 67 EF \ + 71 1F 2E E0 32 08 97 02 00 0E 02 60 E3 77 2A 2E \ + E0 32 08 97 02 00 0E 03 60 E3 2E E0 32 00 32 01 \ + B7 97 02 00 0E 00 12 E7 FE E1 50 67 EF 71 49 86 \ + E0 86 E1 06 E1 D2 04 74 2A 02 00 60 E1 12 E7 FE \ + E1 05 60 EC 12 E3 FE E1 05 0A 03 71 61 67 EB 77 \ + 63 67 CB 67 EF 71 76 12 E3 FE E1 05 0A 02 71 74 \ + 67 EB 77 76 67 CB 12 E3 FE E1 05 0A 01 71 87 67 \ + EB 67 EF 71 97 77 8D 67 CB 67 EF 71 97 86 E1 06 \ + E1 D2 04 74 4D 77 A5 06 E0 28 32 08 97 71 A3 67 \ + EB 77 A5 67 D7 06 E2 67 EF 71 B1 F2 04 60 E2 77 \ + B7 F2 01 60 E2 86 E0 06 E0 D2 24 74 0A 67 EB 67 \ + EB 67 EB 67 EB 67 EB 67 EB 3A 72 67 EF 71 E7 06 \ + EC D2 00 70 E7 77 DD 06 EC D2 00 70 EB 16 ED 99 \ + 99 1A 00 71 E7 77 EB 32 0F 87 57 32 0E 87 57 16 \ + E0 DA 0C 57 00 00 00 00 00 00 00 00 00 00 00 00 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog \ + 02 00 60 E0 02 A0 60 E2 86 E6 02 00 60 E1 2E E0 \ + 32 08 97 02 00 0E 03 60 E3 2E E0 32 00 32 01 B7 \ + 97 02 00 0E 00 12 E4 FE E1 50 12 E4 05 60 E5 12 \ + E3 05 0A 03 71 3A 67 83 77 3C 67 7F 12 E3 05 0A \ + 01 71 47 67 83 77 49 67 7F 06 E0 28 32 08 97 71 \ + 55 67 83 77 57 67 6F 06 E2 F2 01 60 E2 86 E0 06 \ + E0 D2 24 74 0A 67 83 67 83 67 83 67 83 3A 70 06 \ + E5 D2 00 70 83 16 E6 99 99 1A 00 71 7F 77 83 32 \ + 0F 87 57 32 0E 87 57 00 00 00 00 00 00 00 00 00 +led 1 auto on +led 1 start + +# LED0 port order remap +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=47 REMAP_PORT_1=47 REMAP_PORT_2=47 REMAP_PORT_3=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=47 REMAP_PORT_5=47 REMAP_PORT_6=47 REMAP_PORT_7=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=31 REMAP_PORT_9=30 REMAP_PORT_10=29 REMAP_PORT_11=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=47 REMAP_PORT_14=47 REMAP_PORT_15=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 REMAP_PORT_17=47 REMAP_PORT_18=47 REMAP_PORT_19=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=35 REMAP_PORT_21=34 REMAP_PORT_22=33 REMAP_PORT_23=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=23 REMAP_PORT_25=22 REMAP_PORT_26=21 REMAP_PORT_27=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=27 REMAP_PORT_29=26 REMAP_PORT_30=25 REMAP_PORT_31=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=47 REMAP_PORT_33=47 REMAP_PORT_34=47 REMAP_PORT_35=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=15 REMAP_PORT_41=14 REMAP_PORT_42=13 REMAP_PORT_43=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=19 REMAP_PORT_49=18 REMAP_PORT_50=17 REMAP_PORT_51=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +# LED1 port order remap +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=19 REMAP_PORT_1=18 REMAP_PORT_2=17 REMAP_PORT_3=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=23 REMAP_PORT_5=22 REMAP_PORT_6=21 REMAP_PORT_7=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=26 REMAP_PORT_9=27 REMAP_PORT_10=24 REMAP_PORT_11=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 REMAP_PORT_13=63 REMAP_PORT_14=63 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=31 REMAP_PORT_17=30 REMAP_PORT_18=29 REMAP_PORT_19=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=35 REMAP_PORT_21=34 REMAP_PORT_22=33 REMAP_PORT_23=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 REMAP_PORT_25=63 REMAP_PORT_26=63 REMAP_PORT_27=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 REMAP_PORT_29=63 REMAP_PORT_30=63 REMAP_PORT_31=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=3 REMAP_PORT_33=2 REMAP_PORT_34=1 REMAP_PORT_35=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=7 REMAP_PORT_37=6 REMAP_PORT_38=5 REMAP_PORT_39=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11 REMAP_PORT_49=10 REMAP_PORT_50=9 REMAP_PORT_51=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=15 REMAP_PORT_53=14 REMAP_PORT_54=13 REMAP_PORT_55=12 + diff --git a/device/delta/x86_64-delta_ag5648-r0/plugins/eeprom.py b/device/delta/x86_64-delta_ag5648-r0/plugins/eeprom.py new file mode 100644 index 000000000000..bd9bbb755f39 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/plugins/eeprom.py @@ -0,0 +1,30 @@ +############################################################################# +# Mellanox +# +# 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 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 as 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/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-2/2-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_ag5648-r0/plugins/psuutil.py b/device/delta/x86_64-delta_ag5648-r0/plugins/psuutil.py new file mode 100644 index 000000000000..8aa080166f8a --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/plugins/psuutil.py @@ -0,0 +1,54 @@ +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/6-00{}/" + self.psu_oper_status = "in1_input" + self.psu_presence = "i2cget -y 6 0x{} 0x00" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + if index is None: + return False + Base_bus_number = 57 + status = 0 + try: + with open(self.psu_path.format(index + Base_bus_number) + self.psu_oper_status, 'r') as power_status: + if int(power_status.read()) == 0: + return False + else: + status = 1 + except IOError: + return False + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + Base_bus_number = 49 + status = 0 + try: + p = os.popen(self.psu_presence.format(index + Base_bus_number) + "> /dev/null 2>&1") + if p.readline() != None: + status = 1 + p.close() + except IOError: + return False + return status == 1 diff --git a/device/delta/x86_64-delta_ag5648-r0/plugins/sfputil.py b/device/delta/x86_64-delta_ag5648-r0/plugins/sfputil.py new file mode 100644 index 000000000000..5fc426340818 --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/plugins/sfputil.py @@ -0,0 +1,212 @@ +# sfputil.py +# +# 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 = 0 + PORT_START_QSFP = 48 + PORT_END = 53 + PORTS_IN_BLOCK = 54 + + EEPROM_OFFSET = 10 + + _port_to_eeprom_mapping = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_start_qsfp(self): + return self.PORT_START_QSFP + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + if x > self.port_start_qsfp - 1 and x < self.port_end + 1: + self.get_response(x) + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + SfpUtilBase.__init__(self) + + def get_response(self, port_num): + # Check for invalid port_num + if port_num < self.port_start_qsfp or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag5648-cpld.0/sfp_response", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # set the bit corresponding to our port + mask = (port_num + 1) % 8 - 1 + mask = 1 << mask + + # Convert our register value back to a hex string and write back + content = hex(mask) + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + 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 + + try: + reg_file = open("/sys/devices/platform/delta-ag5648-cpld.0/sfp_present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag5648-cpld.0/sfp_lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start_qsfp or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag5648-cpld.0/sfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/delta-ag5648-cpld.0/sfp_reset" + + # Check for invalid port_num + if port_num < self.port_start_qsfp or port_num > self.port_end: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/delta/x86_64-delta_ag5648-r0/sensors.conf b/device/delta/x86_64-delta_ag5648-r0/sensors.conf new file mode 100644 index 000000000000..ff71a21a747d --- /dev/null +++ b/device/delta/x86_64-delta_ag5648-r0/sensors.conf @@ -0,0 +1,91 @@ +# libsensors configuration file for AG5648 +# ------------------------------------------------ +# + +bus "i2c-2" "i2c-1-mux (chan_id 0)" +bus "i2c-3" "i2c-1-mux (chan_id 1)" +bus "i2c-4" "i2c-1-mux (chan_id 2)" +bus "i2c-5" "i2c-1-mux (chan_id 3)" +bus "i2c-6" "i2c-1-mux (chan_id 4)" +bus "i2c-7" "i2c-1-mux (chan_id 5)" + +# tmp75-i2c-2-4d board sensor near Left of front vents. +# tmp75-i2c-3-49 board sensor near MAC. +# tmp75-i2c-3-4b board sensor near Middle of front vents. +# tmp75-i2c-3-4c board sensor near Right of front vents. +# tmp75-i2c-3-4e board sensor near DC fan. +# tmp75-i2c-3-4f board sensor near CPU. + +chip "tmp75-i2c-2-4d" + label temp1 "board sensor near Left of front vents" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-3-49" + label temp1 "board sensor near MAC" + set temp1_max 85 + set temp1_max_hyst 80 + +chip "tmp75-i2c-3-4b" + label temp1 "board sensor near Middle of front vents" + set temp1_max 70 + set temp1_max_hyst 65 + +chip "tmp75-i2c-3-4c" + label temp1 "board sensor near Right of front vents" + set temp1_max 65 + set temp1_max_hyst 60 + +chip "tmp75-i2c-3-4e" + label temp1 "board sensor near DC fan" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-3-4f" + label temp1 "board sensor near CPU" + set temp1_max 80 + set temp1_max_hyst 75 + +chip "emc2305-i2c-3-4d" + label fan1 "FANTRAY 1 REAR" + label fan2 "FANTRAY 2 REAR" + label fan3 "FANTRAY 3 REAR" + label fan4 "FANTRAY 4 REAR" + +chip "emc2305-i2c-5-4d" + label fan1 "FANTRAY 1 FRONT" + label fan2 "FANTRAY 2 FRONT" + label fan3 "FANTRAY 3 FRONT" + label fan4 "FANTRAY 4 FRONT" + +chip "ltc4215-i2c-3-40" + label in1 "PSU Hot-Swap voltage 1" + label in2 "PSU Hot-Swap voltage 2" + label power1 "PSU Hot-Swap power" + label curr1 "PSU Hot-Swap current" + +chip "ltc4215-i2c-3-42" + label in1 "PSU Hot-Swap voltage 1" + label in2 "PSU Hot-Swap voltage 2" + label power1 "PSU Hot-Swap power" + label curr1 "PSU Hot-Swap current" + +chip "dni_ag5648_psu-i2c-6-59" + label in1 "PSU voltage 1" + label in2 "PSU voltage 2" + label fan1 "PSU fan" + label temp1 "PSU temperature" + label power1 "PSU power1" + label power2 "PSU power2" + label curr1 "PSU current1" + label curr2 "PSU current2" + +chip "dni_ag5648_psu-i2c-6-58" + label in1 "PSU voltage 1" + label in2 "PSU voltage 2" + label fan1 "PSU fan" + label temp1 "PSU temperature" + label power1 "PSU power1" + label power2 "PSU power2" + label curr1 "PSU current1" + label curr2 "PSU current2" \ No newline at end of file diff --git a/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/port_config.ini b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/port_config.ini new file mode 100644 index 000000000000..4fb783847b0a --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 41,42,43,44 hundredGigE1/1 +Ethernet4 45,46,47,48 hundredGigE1/2 +Ethernet8 49,50,51,52 hundredGigE1/3 +Ethernet12 37,38,39,40 hundredGigE1/4 +Ethernet16 33,34,35,36 hundredGigE1/5 +Ethernet20 53,54,55,56 hundredGigE1/6 +Ethernet24 57,58,59,60 hundredGigE1/7 +Ethernet28 61,62,63,64 hundredGigE1/8 +Ethernet32 65,66,67,68 hundredGigE1/9 +Ethernet36 69,70,71,72 hundredGigE1/10 +Ethernet40 73,74,75,76 hundredGigE1/11 +Ethernet44 77,78,79,80 hundredGigE1/12 +Ethernet48 81,82,83,84 hundredGigE1/13 +Ethernet52 85,86,87,88 hundredGigE1/14 +Ethernet56 89,90,91,92 hundredGigE1/15 +Ethernet60 93,94,95,96 hundredGigE1/16 +Ethernet64 97,98,99,100 hundredGigE1/17 +Ethernet68 101,102,103,104 hundredGigE1/18 +Ethernet72 105,106,107,108 hundredGigE1/19 +Ethernet76 109,110,111,112 hundredGigE1/20 +Ethernet80 121,122,123,124 hundredGigE1/21 +Ethernet84 113,114,115,116 hundredGigE1/22 +Ethernet88 1,2,3,4 hundredGigE1/23 +Ethernet92 117,118,119,120 hundredGigE1/24 +Ethernet96 5,6,7,8 hundredGigE1/25 +Ethernet100 125,126,127,128 hundredGigE1/26 +Ethernet104 29,30,31,32 hundredGigE1/27 +Ethernet108 9,10,11,12 hundredGigE1/28 +Ethernet112 13,14,15,16 hundredGigE1/29 +Ethernet116 25,26,27,28 hundredGigE1/30 +Ethernet120 17,18,19,20 hundredGigE1/31 +Ethernet124 21,22,23,24 hundredGigE1/32 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/sai.profile b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/sai.profile new file mode 100644 index 000000000000..a1ec3ca258df --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-ag9032v1-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/th-ag9032v1-32x100G.config.bcm b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/th-ag9032v1-32x100G.config.bcm new file mode 100644 index 000000000000..a088c8f7a6be --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/Delta-ag9032v1/th-ag9032v1-32x100G.config.bcm @@ -0,0 +1,523 @@ +os=unix +schan_intr_enable=0 +ctr_evict_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +pbmp_oversubscribe=0x00003fc000000ff0000003fc000001fe +pbmp_xport_xe=0x00003fc000000ff0000003fc000001fe +port_phy_clause_1=45 +port_phy_clause_2=45 +port_phy_clause_3=45 +port_phy_clause_4=45 +port_phy_clause_5=45 +port_phy_clause_6=45 +port_phy_clause_7=45 +port_phy_clause_8=45 + +port_phy_clause_34=45 +port_phy_clause_35=45 +port_phy_clause_36=45 +port_phy_clause_37=45 +port_phy_clause_38=45 +port_phy_clause_39=45 +port_phy_clause_40=45 +port_phy_clause_41=45 + +port_phy_clause_68=45 +port_phy_clause_69=45 +port_phy_clause_70=45 +port_phy_clause_71=45 +port_phy_clause_72=45 +port_phy_clause_73=45 +port_phy_clause_74=45 +port_phy_clause_75=45 + +port_phy_clause_102=45 +port_phy_clause_103=45 +port_phy_clause_104=45 +port_phy_clause_105=45 +port_phy_clause_106=45 +port_phy_clause_107=45 +port_phy_clause_108=45 +port_phy_clause_109=45 + +port_phy_addr_1=0xff +port_phy_addr_2=0xff +port_phy_addr_3=0xff +port_phy_addr_4=0xff +port_phy_addr_5=0xff +port_phy_addr_6=0xff +port_phy_addr_7=0xff +port_phy_addr_8=0xff + +port_phy_addr_34=0xff +port_phy_addr_35=0xff +port_phy_addr_36=0xff +port_phy_addr_37=0xff +port_phy_addr_38=0xff +port_phy_addr_39=0xff +port_phy_addr_40=0xff +port_phy_addr_41=0xff + +port_phy_addr_68=0xff +port_phy_addr_69=0xff +port_phy_addr_70=0xff +port_phy_addr_71=0xff +port_phy_addr_72=0xff +port_phy_addr_73=0xff +port_phy_addr_74=0xff +port_phy_addr_75=0xff + +port_phy_addr_102=0xff +port_phy_addr_103=0xff +port_phy_addr_104=0xff +port_phy_addr_105=0xff +port_phy_addr_106=0xff +port_phy_addr_107=0xff +port_phy_addr_108=0xff +port_phy_addr_109=0xff + +# Tile-0 +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 + +# Tile-1 +portmap_34=33:100 +portmap_35=37:100 +portmap_36=41:100 +portmap_37=45:100 +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 + +# Tile-2 +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 + +# Tile-3 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=113:100 +portmap_107=117:100 +portmap_108=121:100 +portmap_109=125:100 + +dport_map_enable=1 +dport_map_indexed=1 +dport_map_direct=0 + +dport_map_port_36=1 +dport_map_port_37=2 +dport_map_port_38=3 +dport_map_port_35=4 +dport_map_port_34=5 +dport_map_port_39=6 +dport_map_port_40=7 +dport_map_port_41=8 + +dport_map_port_68=34 +dport_map_port_69=35 +dport_map_port_70=36 +dport_map_port_71=37 +dport_map_port_72=38 +dport_map_port_73=39 +dport_map_port_74=40 +dport_map_port_75=41 + +dport_map_port_102=68 +dport_map_port_103=69 +dport_map_port_104=70 +dport_map_port_105=71 +dport_map_port_108=72 +dport_map_port_106=73 +dport_map_port_1=74 +dport_map_port_107=75 + +dport_map_port_2=102 +dport_map_port_109=103 +dport_map_port_8=104 +dport_map_port_3=105 +dport_map_port_4=106 +dport_map_port_7=107 +dport_map_port_5=108 +dport_map_port_6=109 + +# Tile-0 FC0~FC7 +# TX polarity +phy_xaui_tx_polarity_flip_1=0xF +phy_xaui_tx_polarity_flip_2=0xF +phy_xaui_tx_polarity_flip_3=0x0 +phy_xaui_tx_polarity_flip_4=0x0 +phy_xaui_tx_polarity_flip_5=0x0 +phy_xaui_tx_polarity_flip_6=0x0 +phy_xaui_tx_polarity_flip_7=0xF +phy_xaui_tx_polarity_flip_8=0xF + +# RX polarity +phy_xaui_rx_polarity_flip_1=0xF +phy_xaui_rx_polarity_flip_2=0xF +phy_xaui_rx_polarity_flip_3=0x0 +phy_xaui_rx_polarity_flip_4=0x0 +phy_xaui_rx_polarity_flip_5=0x0 +phy_xaui_rx_polarity_flip_6=0x0 +phy_xaui_rx_polarity_flip_7=0xF +phy_xaui_rx_polarity_flip_8=0xF + +# TX lane swap +xgxs_tx_lane_map_1=0x1302 +xgxs_tx_lane_map_2=0x1302 +xgxs_tx_lane_map_3=0x0213 +xgxs_tx_lane_map_4=0x1302 +xgxs_tx_lane_map_5=0x1032 +xgxs_tx_lane_map_6=0x0213 +xgxs_tx_lane_map_7=0x3120 +xgxs_tx_lane_map_8=0x1302 + +# RX lane swap +xgxs_rx_lane_map_1=0x1302 +xgxs_rx_lane_map_2=0x1302 +xgxs_rx_lane_map_3=0x0213 +xgxs_rx_lane_map_4=0x1302 +xgxs_rx_lane_map_5=0x0123 +xgxs_rx_lane_map_6=0x1032 +xgxs_rx_lane_map_7=0x0213 +xgxs_rx_lane_map_8=0x2031 + +# Tile-1 FC8~FC15 +#TX polarity +phy_xaui_tx_polarity_flip_34=0x0 +phy_xaui_tx_polarity_flip_35=0x1 +phy_xaui_tx_polarity_flip_36=0x0 +phy_xaui_tx_polarity_flip_37=0x1 +phy_xaui_tx_polarity_flip_38=0xF +phy_xaui_tx_polarity_flip_39=0xE +phy_xaui_tx_polarity_flip_40=0x0 +phy_xaui_tx_polarity_flip_41=0xE + +#RX polarity +phy_xaui_rx_polarity_flip_34=0x0 +phy_xaui_rx_polarity_flip_35=0x0 +phy_xaui_rx_polarity_flip_36=0x0 +phy_xaui_rx_polarity_flip_37=0x2 +phy_xaui_rx_polarity_flip_38=0xF +phy_xaui_rx_polarity_flip_39=0xF +phy_xaui_rx_polarity_flip_40=0x0 +phy_xaui_rx_polarity_flip_41=0xF + +# TX lane swap +xgxs_tx_lane_map_34=0x0213 +xgxs_tx_lane_map_35=0x2031 +xgxs_tx_lane_map_36=0x0123 +xgxs_tx_lane_map_37=0x1032 +xgxs_tx_lane_map_38=0x0213 +xgxs_tx_lane_map_39=0x1302 +xgxs_tx_lane_map_40=0x0213 +xgxs_tx_lane_map_41=0x1302 + +# RX lane swap +xgxs_rx_lane_map_34=0x3120 +xgxs_rx_lane_map_35=0x2301 +xgxs_rx_lane_map_36=0x1032 +xgxs_rx_lane_map_37=0x0123 +xgxs_rx_lane_map_38=0x0213 +xgxs_rx_lane_map_39=0x1302 +xgxs_rx_lane_map_40=0x0213 +xgxs_rx_lane_map_41=0x1302 + +# Tile-2 FC16~FC23 +# TX polarity +phy_xaui_tx_polarity_flip_68=0x0 +phy_xaui_tx_polarity_flip_69=0xE +phy_xaui_tx_polarity_flip_70=0x0 +phy_xaui_tx_polarity_flip_71=0xE +phy_xaui_tx_polarity_flip_72=0xF +phy_xaui_tx_polarity_flip_73=0xE +phy_xaui_tx_polarity_flip_74=0xF +phy_xaui_tx_polarity_flip_75=0xE + +# RX polarity +phy_xaui_rx_polarity_flip_68=0x0 +phy_xaui_rx_polarity_flip_69=0xD +phy_xaui_rx_polarity_flip_70=0x0 +phy_xaui_rx_polarity_flip_71=0xF +phy_xaui_rx_polarity_flip_72=0xF +phy_xaui_rx_polarity_flip_73=0xF +phy_xaui_rx_polarity_flip_74=0xF +phy_xaui_rx_polarity_flip_75=0xF + +# TX lane swap +xgxs_tx_lane_map_68=0x3120 +xgxs_tx_lane_map_69=0x1302 +xgxs_tx_lane_map_70=0x0213 +xgxs_tx_lane_map_71=0x0123 +xgxs_tx_lane_map_72=0x0213 +xgxs_tx_lane_map_73=0x2031 +xgxs_tx_lane_map_74=0x0213 +xgxs_tx_lane_map_75=0x2031 + +# RX lane swap +xgxs_rx_lane_map_68=0x3120 +xgxs_rx_lane_map_69=0x1302 +xgxs_rx_lane_map_70=0x0213 +xgxs_rx_lane_map_71=0x2103 +xgxs_rx_lane_map_72=0x2031 +xgxs_rx_lane_map_73=0x0213 +xgxs_rx_lane_map_74=0x3210 +xgxs_rx_lane_map_75=0x0213 + +# Tile-3 +# portmap_0=x:xx // cpu port (not required, but included for illustration purposes) +# TX polarity +phy_xaui_tx_polarity_flip_102=0x0 +phy_xaui_tx_polarity_flip_103=0xF +phy_xaui_tx_polarity_flip_104=0x0 +phy_xaui_tx_polarity_flip_105=0x0 +phy_xaui_tx_polarity_flip_106=0x0 +phy_xaui_tx_polarity_flip_107=0x0 +phy_xaui_tx_polarity_flip_108=0xF +phy_xaui_tx_polarity_flip_109=0x0 + +# RX polarity +phy_xaui_rx_polarity_flip_102=0x0 +phy_xaui_rx_polarity_flip_103=0x2 +phy_xaui_rx_polarity_flip_104=0x0 +phy_xaui_rx_polarity_flip_105=0xF +phy_xaui_rx_polarity_flip_106=0x0 +phy_xaui_rx_polarity_flip_107=0x0 +phy_xaui_rx_polarity_flip_108=0xF +phy_xaui_rx_polarity_flip_109=0x2 + +# TX lane swap +xgxs_tx_lane_map_102=0x2031 +xgxs_tx_lane_map_103=0x0213 +xgxs_tx_lane_map_104=0x2031 +xgxs_tx_lane_map_105=0x0213 +xgxs_tx_lane_map_106=0x0123 +xgxs_tx_lane_map_107=0x0213 +xgxs_tx_lane_map_108=0x0312 +xgxs_tx_lane_map_109=0x3120 + +# RX lane swap +xgxs_rx_lane_map_102=0x0213 +xgxs_rx_lane_map_103=0x2031 +xgxs_rx_lane_map_104=0x0213 +xgxs_rx_lane_map_105=0x2031 +xgxs_rx_lane_map_106=0x0123 +xgxs_rx_lane_map_107=0x0213 +xgxs_rx_lane_map_108=0x1302 +xgxs_rx_lane_map_109=0x3120 + +#serdes_preemphasis_lane0_1=0x(post)(main)(pre) +#ce0 +serdes_preemphasis_lane0_36=0x3c320f +serdes_preemphasis_lane1_36=0x3c320f +serdes_preemphasis_lane2_36=0x3c320c +serdes_preemphasis_lane3_36=0x3c320c + +#ce1 +serdes_preemphasis_lane0_37=0x3c320f +serdes_preemphasis_lane1_37=0x3c320f +serdes_preemphasis_lane2_37=0x3c320c +serdes_preemphasis_lane3_37=0x37320c + +#ce2 +serdes_preemphasis_lane0_38=0x3c3206 +serdes_preemphasis_lane1_38=0x373206 +serdes_preemphasis_lane2_38=0x373206 +serdes_preemphasis_lane3_38=0x373206 + +#ce3 +serdes_preemphasis_lane0_35=0x3c3206 +serdes_preemphasis_lane1_35=0x3c3206 +serdes_preemphasis_lane2_35=0x3c3206 +serdes_preemphasis_lane3_35=0x3c3206 + +#ce4 +serdes_preemphasis_lane0_34=0x3c3206 +serdes_preemphasis_lane1_34=0x3c3206 +serdes_preemphasis_lane2_34=0x3c3206 +serdes_preemphasis_lane3_34=0x373206 + +#ce5 +serdes_preemphasis_lane0_39=0x323206 +serdes_preemphasis_lane1_39=0x323206 +serdes_preemphasis_lane2_39=0x323206 +serdes_preemphasis_lane3_39=0x323206 + +#ce6 +serdes_preemphasis_lane0_40=0x323206 +serdes_preemphasis_lane1_40=0x2D3206 +serdes_preemphasis_lane2_40=0x2D3206 +serdes_preemphasis_lane3_40=0x2D3206 + +#ce7 +serdes_preemphasis_lane0_41=0x2D3206 +serdes_preemphasis_lane1_41=0x2D3206 +serdes_preemphasis_lane2_41=0x2D3206 +serdes_preemphasis_lane3_41=0x2D3206 + +#ce8 +serdes_preemphasis_lane0_68=0x283206 +serdes_preemphasis_lane1_68=0x283206 +serdes_preemphasis_lane2_68=0x283206 +serdes_preemphasis_lane3_68=0x283206 + +#ce9 +serdes_preemphasis_lane0_69=0x283206 +serdes_preemphasis_lane1_69=0x283206 +serdes_preemphasis_lane2_69=0x283206 +serdes_preemphasis_lane3_69=0x283206 + +#ce10 +serdes_preemphasis_lane0_70=0x2D3206 +serdes_preemphasis_lane1_70=0x2D3206 +serdes_preemphasis_lane2_70=0x2D3206 +serdes_preemphasis_lane3_70=0x2D3206 + +#ce11 +serdes_preemphasis_lane0_71=0x2D3206 +serdes_preemphasis_lane1_71=0x2D3206 +serdes_preemphasis_lane2_71=0x2D3206 +serdes_preemphasis_lane3_71=0x2D3206 + +#ce12 +serdes_preemphasis_lane0_72=0x2D3203 +serdes_preemphasis_lane1_72=0x2D3206 +serdes_preemphasis_lane2_72=0x2D3206 +serdes_preemphasis_lane3_73=0x2D3206 + +#ce13 +serdes_preemphasis_lane0_73=0x2D3206 +serdes_preemphasis_lane1_73=0x283206 +serdes_preemphasis_lane2_73=0x283206 +serdes_preemphasis_lane3_73=0x283206 + +#ce14 +serdes_preemphasis_lane0_74=0x2D3203 +serdes_preemphasis_lane1_74=0x2D3203 +serdes_preemphasis_lane2_74=0x2D3203 +serdes_preemphasis_lane3_74=0x283206 + +#ce15 +serdes_preemphasis_lane0_75=0x2D3206 +serdes_preemphasis_lane1_75=0x283206 +serdes_preemphasis_lane2_75=0x283206 +serdes_preemphasis_lane3_75=0x283206 + +#ce16 +serdes_preemphasis_lane0_102=0x2D3206 +serdes_preemphasis_lane1_102=0x2D3206 +serdes_preemphasis_lane2_102=0x2D3206 +serdes_preemphasis_lane3_102=0x2D3206 + +#ce17 +serdes_preemphasis_lane0_103=0x2D3206 +serdes_preemphasis_lane1_103=0x283206 +serdes_preemphasis_lane2_103=0x283206 +serdes_preemphasis_lane3_103=0x283206 + +#ce18 +serdes_preemphasis_lane0_104=0x2D3206 +serdes_preemphasis_lane1_104=0x283206 +serdes_preemphasis_lane2_104=0x283206 +serdes_preemphasis_lane3_104=0x283206 + +#ce19 +serdes_preemphasis_lane0_105=0x2D3206 +serdes_preemphasis_lane1_105=0x2D3206 +serdes_preemphasis_lane2_105=0x2D3206 +serdes_preemphasis_lane3_105=0x2D3206 + +#ce20 +serdes_preemphasis_lane0_108=0x323206 +serdes_preemphasis_lane1_108=0x283206 +serdes_preemphasis_lane2_108=0x283206 +serdes_preemphasis_lane3_108=0x283206 + +#ce21 +serdes_preemphasis_lane0_106=0x2D3206 +serdes_preemphasis_lane1_106=0x283206 +serdes_preemphasis_lane2_106=0x283206 +serdes_preemphasis_lane3_106=0x283206 + +#ce22 +serdes_preemphasis_lane0_1=0x323206 +serdes_preemphasis_lane1_1=0x283206 +serdes_preemphasis_lane2_1=0x283206 +serdes_preemphasis_lane3_1=0x283206 + +#ce23 +serdes_preemphasis_lane0_107=0x323206 +serdes_preemphasis_lane1_107=0x283206 +serdes_preemphasis_lane2_107=0x283206 +serdes_preemphasis_lane3_107=0x283206 + +#ce24 +serdes_preemphasis_lane0_2=0x2D3206 +serdes_preemphasis_lane1_2=0x2D3206 +serdes_preemphasis_lane2_2=0x323206 +serdes_preemphasis_lane3_3=0x2D3206 + +#ce25 +serdes_preemphasis_lane0_109=0x323203 +serdes_preemphasis_lane1_109=0x2D3206 +serdes_preemphasis_lane2_109=0x2D3206 +serdes_preemphasis_lane3_109=0x2D3206 + +#ce26 +serdes_preemphasis_lane0_8=0x373206 +serdes_preemphasis_lane1_8=0x373206 +serdes_preemphasis_lane2_8=0x373206 +serdes_preemphasis_lane3_8=0x373206 + +#ce27 +serdes_preemphasis_lane0_3=0x323203 +serdes_preemphasis_lane1_3=0x323203 +serdes_preemphasis_lane2_3=0x323203 +serdes_preemphasis_lane3_3=0x323203 + +#ce28 +serdes_preemphasis_lane0_4=0x373203 +serdes_preemphasis_lane1_4=0x323203 +serdes_preemphasis_lane2_4=0x323203 +serdes_preemphasis_lane3_4=0x323205 + +#ce29 +serdes_preemphasis_lane0_7=0x3c3203 +serdes_preemphasis_lane1_7=0x3c3203 +serdes_preemphasis_lane2_7=0x3c3203 +serdes_preemphasis_lane3_7=0x3c3205 + +#ce30 +serdes_preemphasis_lane0_5=0x3c320f +serdes_preemphasis_lane1_5=0x3c320f +serdes_preemphasis_lane2_5=0x3c320c +serdes_preemphasis_lane3_5=0x2c320c + +#ce31 +serdes_preemphasis_lane0_6=0x3c320f +serdes_preemphasis_lane1_6=0x3c320f +serdes_preemphasis_lane2_6=0x2c320c +serdes_preemphasis_lane3_6=0x2c320c + + + diff --git a/device/delta/x86_64-delta_ag9032v1-r0/default_sku b/device/delta/x86_64-delta_ag9032v1-r0/default_sku new file mode 100644 index 000000000000..f175f53b323e --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/default_sku @@ -0,0 +1 @@ +Delta-ag9032v1 t1 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/fancontrol b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol new file mode 100644 index 000000000000..4a1cde92478f --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=10 +DEVPATH=hwmon1=/sys/bus/i2c/devices +DEVNAME=hwmon1=emc2305 +FCTEMPS=hwmon1/2-004d/hwmon/hwmon*/temp1_input hwmon1/7-004c/hwmon/hwmon*/temp1_input hwmon1/7-004d/hwmon/hwmon*/temp1_input hwmon1/7-004e/hwmon/hwmon*/temp1_input hwmon1/30-004f/hwmon/hwmon*/temp1_input hwmon1/40-0058/temp1_input hwmon1/41-0058/temp1_input + +FCFANS=hwmon1/37-002c/fan1_input hwmon1/37-002c/fan2_input hwmon1/37-002c/fan3_input hwmon1/37-002c/fan4_input hwmon1/37-002c/fan5_input hwmon1/38-002d/fan1_input hwmon1/38-002d/fan2_input hwmon1/38-002d/fan3_input hwmon1/38-002d/fan4_input hwmon1/38-002d/fan5_input +MINTEMP=20 +MAXTEMP=60 +MINSTART=75 +MINSTOP=22 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/fancontrol.service b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol.service new file mode 100755 index 000000000000..83f14245d1bd --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/fancontrol.service @@ -0,0 +1,289 @@ +#!/bin/bash +# +# Simple script implementing a temperature dependent fan speed control +# Supported Linux kernel versions: 2.6.5 and later +# +# Version 0.70 +# +# Usage: fancontrol [CONFIGFILE] +# +# Dependencies: +# bash, egrep, sed, cut, sleep, readlink, lm_sensors :) +# +# Please send any questions, comments or success stories to +# marius.reiner@hdev.de +# Thanks! +# +# For configuration instructions and warnings please see fancontrol.txt, which +# can be found in the doc/ directory or at the website mentioned above. +# +# +# Copyright 2003 Marius Reiner +# Copyright (C) 2007-2009 Jean Delvare +# +# 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. +# +# 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 Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +# + +PIDFILE="/var/run/fancontrol.pid" + +#DEBUG=1 +MAX=255 + +function LoadConfig +{ + local fcvcount fcv + + echo "Loading configuration from $1 ..." + if [ ! -r "$1" ] + then + echo "Error: Can't read configuration file" >&2 + exit 1 + fi + + # grep configuration from file + INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'` + DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'` + DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'` + FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'` + MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'` + MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'` + MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'` + MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'` + HWMON=$( echo "$DEVPATH" | sed 's/=.*$//g') + FCDEVPATH=$( echo "$DEVPATH" | sed 's/^.*=//g') + FCMINTEMP=$MINTEMP + FCMAXTEMP=$MAXTEMP + FCMINSTART=$MINSTART + FCMINSTOP=$MINSTOP + AFCTEMP_1_LOWER=(00 39 36 41 46 55) + AFCTEMP_1_UPPER=(39 39 44 49 54 150) + AFCTEMP_2_LOWER=(00 61 65 69 73 82) + AFCTEMP_2_UPPER=(63 67 71 75 79 150) + AFCTEMP_3_LOWER=(00 51 55 59 63 71) + AFCTEMP_3_UPPER=(53 57 61 65 69 150) + AFCTEMP_4_LOWER=(00 46 50 54 58 65) + AFCTEMP_4_UPPER=(45 52 56 60 64 150) + AFCTEMP_5_LOWER=(00 46 50 54 58 65) + AFCTEMP_5_UPPER=(45 52 56 60 64 150) + + + FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'` + + # Check whether all mandatory settings are set + if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]] + then + echo "Some mandatory settings missing, please check your config file!" >&2 + exit 1 + fi + if [ "$INTERVAL" -le 0 ] + then + echo "Error in configuration file:" >&2 + echo "INTERVAL must be at least 1" >&2 + exit 1 + fi + + # write settings to arrays for easier use and print them + echo + echo "Common settings:" + + temp_string=$FCTEMPS + + let fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( echo "$temp_string" | cut -d" " -f $fcvcount ) + AFCTEMP[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP_PATH[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + done + + fan_string=$FCFANS + fcvcount=0 + zero=0 + for fcv in $FCFANS + do + fcvcount=$((fcvcount+1)) + AFCFAN[$fcvcount]=$( echo "$fan_string" | cut -d" " -f $fcvcount ) + AFCFAN_PATH[$fcvcount]=$( echo "${AFCFAN[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_PATH[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_TARGET[$fcvcount]}" | sed 's/$/_percentage/g') + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + done +} + +# Check that all referenced sysfs files exist +function CheckFiles +{ + local outdated=0 fcvcount tsen fan + if [ $outdated -eq 1 ] + then + echo >&2 + echo "At least one referenced file is missing. Either some required kernel" >&2 + echo "modules haven't been loaded, or your configuration file is outdated." >&2 + echo "In the latter case, you should run pwmconfig again." >&2 + fi + return $outdated +} + +LoadConfig $1 + +# Detect path to sensors +if [ ! -d $DIR ] +then + echo $0: 'No sensors found! (did you load the necessary modules?)' >&2 + exit 1 +fi +cd $DIR + +# Check for configuration change +if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] +then + echo "Configuration is too old, please run pwmconfig again" >&2 + exit 1 +fi +if [ "$DIR" = "/" -a -n "$DEVPATH" ] +then + echo "Unneeded DEVPATH with absolute device paths" >&2 + exit 1 +fi +CheckFiles || exit 1 + +if [ -f "$PIDFILE" ] +then + echo "File $PIDFILE exists, is fancontrol already running?" >&2 + exit 1 +fi +echo $$ > "$PIDFILE" + +# main function +function UpdateThermalSensors +{ + fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP_PATH[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + done +} + +function UpdateThermalLevel +{ + AFCTEMP_NUM=$((6-${AFCTEMP_LEVEL[$i]})) + AFCTEMP_UPPER_BUF=AFCTEMP_"$i"_UPPER["$AFCTEMP_NUM"] + AFCTEMP_LOWER_BUF=AFCTEMP_"$i"_LOWER["$AFCTEMP_NUM"] + + AFCTEMP_UPPER=${!AFCTEMP_UPPER_BUF} + AFCTEMP_LOWER=${!AFCTEMP_LOWER_BUF} + + + if (( ("${AFCTEMP[$i]}" <= "$AFCTEMP_UPPER") && ("${AFCTEMP[$i]}" >= "$AFCTEMP_LOWER") )) ; then + FLAG=2 + elif (( "${AFCTEMP[$i]}" > "$AFCTEMP_UPPER" )); then + AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} - 1)) + FLAG=1 + elif (( "${AFCTEMP[$i]}" < "$AFCTEMP_LOWER" )); then + AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} + 1)) + FLAG=1 + else + AFCTEMP_LEVEL[$i]=1 + FLAG=2 + fi +} + +function UpdateFanSpeeds +{ + #echo "num tmp lev F L H" + #Update level + for i in 1 2 3 4 5 + do + #echo "----------------------" + FLAG=0 + #FLAG=0 : initial flag + #FLAG=1 : update level + #FLAG=2 : final level + while [ $FLAG -ne 2 ] + do + UpdateThermalLevel + #echo " $i ${AFCTEMP[$i]} ${AFCTEMP_LEVEL[$i]} $FLAG $AFCTEMP_LOWER $AFCTEMP_UPPER " + done + done + + min=${AFCTEMP_LEVEL[0]} + for j in "${AFCTEMP_LEVEL[@]}"; do + (( j < min )) && min=$j + done + + if (($min == 1 || $min == 2)); then + FAN_PERCENTAGE=100 + elif (($min == 3)); then + FAN_PERCENTAGE=80 + elif (($min == 4)); then + FAN_PERCENTAGE=60 + elif (($min == 5)); then + FAN_PERCENTAGE=40 + elif (($min == 6)); then + FAN_PERCENTAGE=30 + else + FAN_PERCENTAGE=100 + fi + echo "The lowest level of thermal sensors: $min " + echo "Trying to set fan speed to $FAN_PERCENTAGE %" + #Set speed to fan1~fan10 + let fcvcount=0 + for fcv in $FCFANS + do + fcvcount=$(( fcvcount + 1 )) + echo $FAN_PERCENTAGE > ${AFCFAN_TARGET[$fcvcount]} + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + echo "FAN fan$fcvcount = ${AFCFAN[$fcvcount]} (rpm)" + done + + FAN_ON_PSU_PERCENTAGE=$FAN_PERCENTAGE + #Set speed to PSU_FAN1 + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/40-0058/fan1_set_percentage' + echo "PSU fan1 =$( cat '/sys/bus/i2c/devices/40-0058/fan1_input' ) (rpm)" + #Set speed to PSU_FAN2 + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/41-0058/fan1_set_percentage' + echo "PSU fan2 =$( cat '/sys/bus/i2c/devices/41-0058/fan1_input' ) (rpm)" + + rm -f "$PIDFILE" +} + +# main loop calling the main function at specified intervals +AFCTEMP_LEVEL=(9 4 4 4 4 4) #inttial level +while true +do + UpdateThermalSensors + UpdateFanSpeeds + echo "Sleep $INTERVAL seconds ..." + echo + # Sleep while still handling signals + sleep $INTERVAL & + wait $! +done diff --git a/device/delta/x86_64-delta_ag9032v1-r0/installer.conf b/device/delta/x86_64-delta_ag9032v1-r0/installer.conf new file mode 100644 index 000000000000..85ed43ab48ed --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_SPEED=115200 +CONSOLE_DEV=0 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/led_proc_init.soc b/device/delta/x86_64-delta_ag9032v1-r0/led_proc_init.soc new file mode 100644 index 000000000000..7f6789e90123 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/led_proc_init.soc @@ -0,0 +1,45 @@ +s CMIC_LEDUP0_PROGRAM_RAM 0 +s CMIC_LEDUP1_PROGRAM_RAM 0 + +led 0 stop +led 0 prog 02 00 60 E0 86 ED 2E E0 32 08 97 02 00 0E 00 60 E3 2E E0 32 00 32 01 B7 97 02 00 0E 00 12 E7 50 86 E0 86 E0 86 E0 86 E0 16 E7 61 EB 06 E3 67 4E 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 06 E0 D2 40 74 06 3A C0 D2 01 74 66 06 EB D2 00 70 62 16 ED 99 99 1A 00 71 62 77 66 32 0F 87 57 32 0E 87 57 +led 0 auto on +led 0 start +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15 REMAP_PORT_17=14 REMAP_PORT_18=13 REMAP_PORT_19=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 REMAP_PORT_21=10 REMAP_PORT_22=9 REMAP_PORT_23=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 REMAP_PORT_25=6 REMAP_PORT_26=5 REMAP_PORT_27=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 REMAP_PORT_29=2 REMAP_PORT_30=1 REMAP_PORT_31=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 REMAP_PORT_33=62 REMAP_PORT_34=61 REMAP_PORT_35=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59 REMAP_PORT_37=58 REMAP_PORT_38=57 REMAP_PORT_39=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55 REMAP_PORT_41=54 REMAP_PORT_42=53 REMAP_PORT_43=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51 REMAP_PORT_45=50 REMAP_PORT_46=49 REMAP_PORT_47=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47 REMAP_PORT_49=46 REMAP_PORT_50=45 REMAP_PORT_51=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43 REMAP_PORT_53=42 REMAP_PORT_54=41 REMAP_PORT_55=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39 REMAP_PORT_57=38 REMAP_PORT_58=37 REMAP_PORT_59=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35 REMAP_PORT_61=34 REMAP_PORT_62=33 REMAP_PORT_63=32 + +led 1 stop +led 1 prog 02 00 60 E0 86 ED 2E E0 32 08 97 02 00 0E 00 60 E3 2E E0 32 00 32 01 B7 97 02 00 0E 00 12 E7 50 86 E0 86 E0 86 E0 86 E0 16 E7 61 EB 06 E3 67 4E 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 67 66 06 E0 D2 40 74 06 3A C0 D2 01 74 66 06 EB D2 00 70 62 16 ED 99 99 1A 00 71 62 77 66 32 0F 87 57 32 0E 87 57 +led 1 auto on +led 1 start +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + diff --git a/device/delta/x86_64-delta_ag9032v1-r0/plugins/eeprom.py b/device/delta/x86_64-delta_ag9032v1-r0/plugins/eeprom.py new file mode 100644 index 000000000000..bd9bbb755f39 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/plugins/eeprom.py @@ -0,0 +1,30 @@ +############################################################################# +# Mellanox +# +# 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 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 as 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/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-2/2-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_ag9032v1-r0/plugins/psuutil.py b/device/delta/x86_64-delta_ag9032v1-r0/plugins/psuutil.py new file mode 100644 index 000000000000..391efbd2401f --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/plugins/psuutil.py @@ -0,0 +1,55 @@ +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/{}-0058/" + self.psu_oper_status = "in1_input" + self.psu_presence = "i2cget -y {} 0x50 0x00" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + if index is None: + return False + Base_bus_number = 39 + status = 0 + # index from 1, psu attribute bus from 40 + try: + with open(self.psu_path.format(index + Base_bus_number) + self.psu_oper_status, 'r') as power_status: + if int(power_status.read()) == 0: + return False + else: + status = 1 + except IOError: + return False + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + Base_bus_number = 39 + status = 0 + try: + p = os.popen(self.psu_presence.format(index + Base_bus_number) + "> /dev/null 2>&1") + if p.readline() != None: + status = 1 + p.close() + except IOError: + return False + return status == 1 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/plugins/sfputil.py b/device/delta/x86_64-delta_ag9032v1-r0/plugins/sfputil.py new file mode 100644 index 000000000000..c620540d2911 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/plugins/sfputil.py @@ -0,0 +1,183 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 50 + + _port_to_eeprom_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 list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + 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 < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v1-swpld.0/sfp_present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v1-swpld.0/sfp_lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v1-swpld.0/sfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/delta-ag9032v1-swpld.0/sfp_reset" + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/delta/x86_64-delta_ag9032v1-r0/sensors.conf b/device/delta/x86_64-delta_ag9032v1-r0/sensors.conf new file mode 100644 index 000000000000..d3b2aea2a5af --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v1-r0/sensors.conf @@ -0,0 +1,61 @@ +# libsensors configuration file for DCS-7060CX-32S +# ------------------------------------------------ +# + +bus "i2c-2" "i2c-1-mux (chan_id 0)" +bus "i2c-3" "i2c-1-mux (chan_id 1)" +bus "i2c-4" "i2c-1-mux (chan_id 2)" +bus "i2c-7" "i2c-1-mux (chan_id 5)" + + +# tmp75-i2c-2-4d CPU below side thermal sensor. +# tmp75-i2c-3-4f Wind thermal sensor. +# tmp75-i2c-7-4c MAC up side thermal sensor. +# tmp75-i2c-7-4d MAC down side thermal sensor. +# tmp75-i2c-7-4e Surroundings thermal sensor. + +chip "tmp75-i2c-2-4d" + label temp1 "CPU below side thermal sensor" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-*-4f" + label temp1 "Wind thermal sensor" + set temp1_max 65 + set temp1_max_hyst 60 +chip "tmp75-i2c-7-4c" + label temp1 "MAC up side thermal sensor" + set temp1_max 80 + set temp1_max_hyst 75 +chip "tmp75-i2c-7-4d" + label temp1 "MAC down side thermal sensor" + set temp1_max 75 + set temp1_max_hyst 70 +chip "tmp75-i2c-7-4e" + label temp1 "Surroundings thermal sensor" + set temp1_max 65 + set temp1_max_hyst 60 + + +chip "emc2305-i2c-3-2d" + label fan1 "FANTRAY 1 REAR" + label fan2 "FANTRAY 2 REAR" + label fan3 "FANTRAY 3 REAR" + label fan4 "FANTRAY 4 REAR" + label fan5 "FANTRAY 5 REAR" +chip "emc2305-i2c-3-2c" + label fan1 "FANTRAY 1 FRONT" + label fan2 "FANTRAY 2 FRONT" + label fan3 "FANTRAY 3 FRONT" + label fan4 "FANTRAY 4 FRONT" + label fan5 "FANTRAY 5 FRONT" +chip "pmbus-i2c-4-50" + label temp1 "Fan of power supply controller 1 sensor 1" + label temp2 "Fan of Power supply controller 1 sensor 2" + +chip "pmbus-i2c-4-40" + label temp1 "Power supply 1 hotspot sensor" + +chip "pmbus-i2c-4-40" + label temp1 "Power supply 2 hotspot sensor" + diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/custom_led.bin b/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/custom_led.bin new file mode 100755 index 000000000000..fca72410f8d7 Binary files /dev/null and b/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/custom_led.bin differ diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/port_config.ini b/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/port_config.ini new file mode 100644 index 000000000000..9eb4ac0c8a0c --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/port_config.ini @@ -0,0 +1,34 @@ +# name lanes alias index speed +Ethernet0 1,2,3,4 hundredGigE1/1 0 100000 +Ethernet4 5,6,7,8 hundredGigE1/2 1 100000 +Ethernet8 9,10,11,12 hundredGigE1/3 2 100000 +Ethernet12 13,14,15,16 hundredGigE1/4 3 100000 +Ethernet16 17,18,19,20 hundredGigE1/5 4 100000 +Ethernet20 21,22,23,24 hundredGigE1/6 5 100000 +Ethernet24 25,26,27,28 hundredGigE1/7 6 100000 +Ethernet28 29,30,31,32 hundredGigE1/8 7 100000 +Ethernet32 33,34,35,36 hundredGigE1/9 8 100000 +Ethernet36 37,38,39,40 hundredGigE1/10 9 100000 +Ethernet40 41,42,43,44 hundredGigE1/11 10 100000 +Ethernet44 45,46,47,48 hundredGigE1/12 11 100000 +Ethernet48 49,50,51,52 hundredGigE1/13 12 100000 +Ethernet52 53,54,55,56 hundredGigE1/14 13 100000 +Ethernet56 57,58,59,60 hundredGigE1/15 14 100000 +Ethernet60 61,62,63,64 hundredGigE1/16 15 100000 +Ethernet64 65,66,67,68 hundredGigE1/17 16 100000 +Ethernet68 69,70,71,72 hundredGigE1/18 17 100000 +Ethernet72 73,74,75,76 hundredGigE1/19 18 100000 +Ethernet76 77,78,79,80 hundredGigE1/20 19 100000 +Ethernet80 81,82,83,84 hundredGigE1/21 20 100000 +Ethernet84 85,86,87,88 hundredGigE1/22 21 100000 +Ethernet88 89,90,91,92 hundredGigE1/23 22 100000 +Ethernet92 93,94,95,96 hundredGigE1/24 23 100000 +Ethernet96 97,98,99,100 hundredGigE1/25 24 100000 +Ethernet100 101,102,103,104 hundredGigE1/26 25 100000 +Ethernet104 105,106,107,108 hundredGigE1/27 26 100000 +Ethernet108 109,110,111,112 hundredGigE1/28 27 100000 +Ethernet112 113,114,115,116 hundredGigE1/29 28 100000 +Ethernet116 117,118,119,120 hundredGigE1/30 29 100000 +Ethernet120 121,122,123,124 hundredGigE1/31 30 100000 +Ethernet124 125,126,127,128 hundredGigE1/32 31 100000 +Ethernet128 129 tenGigE1/33 32 10000 diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/sai.profile b/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/sai.profile new file mode 100644 index 000000000000..0d3c85f8f38a --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-ag9032v2a-32x100G+1x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/td3-ag9032v2a-32x100G+1x10G.config.bcm b/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/td3-ag9032v2a-32x100G+1x10G.config.bcm new file mode 100755 index 000000000000..07600e0b8a65 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/td3-ag9032v2a-32x100G+1x10G.config.bcm @@ -0,0 +1,390 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +pbmp_oversubscribe=0x00003fc000000ff0000003fc000001fe +pbmp_xport_xe=0xffffffffffffffffffffffffffffffffffff +core_clock_frequency=1525 +dpp_clock_ratio=2:3 +oversubscribe_mode=1 +parity_enable=0 +mem_cache_enable=0 +l2_mem_entries=32768 +l3_mem_entries=16384 +fpem_mem_entries=131072 +l2xmsg_mode=1 +bcm_num_cos=10 +bcm_stat_interval=2000000 +cdma_timeout_usec=3000000 +ipv6_lpm_128b_enable=0x1 +l3_max_ecmp_mode=1 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 +skip_L2_USER_ENTRY=0 +bcm_tunnel_term_compatible_mode=1 +phy_an_c73=1 +ifp_inports_support_enable=1 +port_flex_enable=1 + +phy_chain_rx_lane_map_physical{1.0}=0x3120 +phy_chain_rx_lane_map_physical{101.0}=0x3120 +phy_chain_rx_lane_map_physical{105.0}=0x1302 +phy_chain_rx_lane_map_physical{109.0}=0x3120 +phy_chain_rx_lane_map_physical{113.0}=0x3120 +phy_chain_rx_lane_map_physical{117.0}=0x1302 +phy_chain_rx_lane_map_physical{121.0}=0x3120 +phy_chain_rx_lane_map_physical{125.0}=0x1302 +phy_chain_rx_lane_map_physical{13.0}=0x2031 +phy_chain_rx_lane_map_physical{17.0}=0x3120 +phy_chain_rx_lane_map_physical{21.0}=0x2031 +phy_chain_rx_lane_map_physical{25.0}=0x3120 +phy_chain_rx_lane_map_physical{29.0}=0x2031 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_rx_lane_map_physical{37.0}=0x2031 +phy_chain_rx_lane_map_physical{41.0}=0x3120 +phy_chain_rx_lane_map_physical{45.0}=0x2031 +phy_chain_rx_lane_map_physical{49.0}=0x3120 +phy_chain_rx_lane_map_physical{5.0}=0x2031 +phy_chain_rx_lane_map_physical{53.0}=0x2031 +phy_chain_rx_lane_map_physical{57.0}=0x3120 +phy_chain_rx_lane_map_physical{61.0}=0x2031 +phy_chain_rx_lane_map_physical{65.0}=0x1302 +phy_chain_rx_lane_map_physical{69.0}=0x3120 +phy_chain_rx_lane_map_physical{73.0}=0x2031 +phy_chain_rx_lane_map_physical{77.0}=0x3120 +phy_chain_rx_lane_map_physical{81.0}=0x1302 +phy_chain_rx_lane_map_physical{85.0}=0x3120 +phy_chain_rx_lane_map_physical{89.0}=0x1302 +phy_chain_rx_lane_map_physical{9.0}=0x3120 +phy_chain_rx_lane_map_physical{93.0}=0x3120 +phy_chain_rx_lane_map_physical{97.0}=0x1302 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +phy_chain_rx_polarity_flip_physical{102.0}=0x0 +phy_chain_rx_polarity_flip_physical{103.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x0 +phy_chain_rx_polarity_flip_physical{109.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x0 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +phy_chain_rx_polarity_flip_physical{118.0}=0x1 +phy_chain_rx_polarity_flip_physical{119.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x0 +phy_chain_rx_polarity_flip_physical{125.0}=0x1 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{129.0}=0xf +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x1 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +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}=0x1 +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{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +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{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x1 +phy_chain_rx_polarity_flip_physical{53.0}=0x1 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x0 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x1 +phy_chain_rx_polarity_flip_physical{76.0}=0x1 +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{8.0}=0x1 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x1 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x1 +phy_chain_tx_lane_map_physical{1.0}=0x0213 +phy_chain_tx_lane_map_physical{101.0}=0x0213 +phy_chain_tx_lane_map_physical{105.0}=0x2031 +phy_chain_tx_lane_map_physical{109.0}=0x0213 +phy_chain_tx_lane_map_physical{113.0}=0x0213 +phy_chain_tx_lane_map_physical{117.0}=0x2031 +phy_chain_tx_lane_map_physical{121.0}=0x0213 +phy_chain_tx_lane_map_physical{125.0}=0x2031 +phy_chain_tx_lane_map_physical{13.0}=0x1302 +phy_chain_tx_lane_map_physical{17.0}=0x0213 +phy_chain_tx_lane_map_physical{21.0}=0x1302 +phy_chain_tx_lane_map_physical{25.0}=0x0213 +phy_chain_tx_lane_map_physical{29.0}=0x1302 +phy_chain_tx_lane_map_physical{33.0}=0x2031 +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_tx_lane_map_physical{41.0}=0x0231 +phy_chain_tx_lane_map_physical{45.0}=0x1302 +phy_chain_tx_lane_map_physical{49.0}=0x0213 +phy_chain_tx_lane_map_physical{5.0}=0x1302 +phy_chain_tx_lane_map_physical{53.0}=0x1302 +phy_chain_tx_lane_map_physical{57.0}=0x0213 +phy_chain_tx_lane_map_physical{61.0}=0x1302 +phy_chain_tx_lane_map_physical{65.0}=0x2031 +phy_chain_tx_lane_map_physical{69.0}=0x0213 +phy_chain_tx_lane_map_physical{73.0}=0x3210 +phy_chain_tx_lane_map_physical{77.0}=0x0213 +phy_chain_tx_lane_map_physical{81.0}=0x2031 +phy_chain_tx_lane_map_physical{85.0}=0x0213 +phy_chain_tx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{9.0}=0x0213 +phy_chain_tx_lane_map_physical{93.0}=0x0213 +phy_chain_tx_lane_map_physical{97.0}=0x2031 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_tx_polarity_flip_physical{101.0}=0x0 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +phy_chain_tx_polarity_flip_physical{103.0}=0x1 +phy_chain_tx_polarity_flip_physical{104.0}=0x1 +phy_chain_tx_polarity_flip_physical{105.0}=0x1 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{118.0}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_tx_polarity_flip_physical{120.0}=0x1 +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +phy_chain_tx_polarity_flip_physical{129.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_tx_polarity_flip_physical{21.0}=0x1 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.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}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x0 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +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}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +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}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x1 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 +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{8.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.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}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x0 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 +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}=0x0 +portmap_66.0=129:10:m +portmap_103=101:100 +portmap_107=105:100 +portmap_111=109:100 +portmap_115=113:100 +portmap_119=117:100 +portmap_123=121:100 +portmap_127=125:100 +portmap_13=13:100 +portmap_17=17:100 +portmap_1=1: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_57=57:100 +portmap_5=5:100 +portmap_61=61:100 +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_99=97:100 +portmap_9=9:100 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 +ptp_ts_pll_fref=50000000 + + diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/default_sku b/device/delta/x86_64-delta_ag9032v2a-r0/default_sku new file mode 100644 index 000000000000..2e67043ab05a --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v2a-r0/default_sku @@ -0,0 +1 @@ +Delta-ag9032v2a t1 diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/installer.conf b/device/delta/x86_64-delta_ag9032v2a-r0/installer.conf new file mode 100644 index 000000000000..85ed43ab48ed --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v2a-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_SPEED=115200 +CONSOLE_DEV=0 diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/led_proc_init.soc b/device/delta/x86_64-delta_ag9032v2a-r0/led_proc_init.soc new file mode 100644 index 000000000000..57ee7fedaf2b --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v2a-r0/led_proc_init.soc @@ -0,0 +1,3 @@ +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/plugins/eeprom.py b/device/delta/x86_64-delta_ag9032v2a-r0/plugins/eeprom.py new file mode 100644 index 000000000000..9d55c090d57b --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v2a-r0/plugins/eeprom.py @@ -0,0 +1,30 @@ +############################################################################# +# Mellanox +# +# 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 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 as 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/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-1/1-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/plugins/psuutil.py b/device/delta/x86_64-delta_ag9032v2a-r0/plugins/psuutil.py new file mode 100644 index 000000000000..06655c07a416 --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v2a-r0/plugins/psuutil.py @@ -0,0 +1,84 @@ +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# + +import os.path +import subprocess + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + status = 0 + try: + p = os.popen("ipmitool raw 0x38 0x2 3 0x6a 0x3 1") + content = p.readline().rstrip() + reg_value = int(content, 16) + if index == 1: + mask = (1 << 6) + else: + mask = (1 << 2) + if reg_value & mask == 0: + return False + status = 1 + p.close() + except IOError: + return False + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + p = os.popen("ipmitool raw 0x38 0x2 3 0x6a 0x3 1") + content = p.readline().rstrip() + reg_value = int(content, 16) + if index == 1: + mask = (1 << 7) + if reg_value & mask == 0x80: + return False + else: + mask = (1 << 3) + if reg_value & mask == 0x08: + return False + status = 1 + p.close() + except IOError: + return False + return status == 1 diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/plugins/sfputil.py b/device/delta/x86_64-delta_ag9032v2a-r0/plugins/sfputil.py new file mode 100644 index 000000000000..ace5d9f3736b --- /dev/null +++ b/device/delta/x86_64-delta_ag9032v2a-r0/plugins/sfputil.py @@ -0,0 +1,183 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 32 + PORTS_IN_BLOCK = 33 + + EEPROM_OFFSET = 20 + + _port_to_eeprom_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 list(range(0, self.PORT_END - self.PORT_START + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + 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 < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v2a-swpld1.0/sfp_is_present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (self.port_end - port_num + 7)) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end - 1: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v2a-swpld1.0/qsfp_lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (self.port_end - port_num) - 1) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end - 1: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9032v2a-swpld1.0/qsfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (self.port_end - port_num) - 1) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/delta-ag9032v2a-swpld1.0/qsfp_reset" + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end - 1: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (self.port_end - port_num) - 1) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/port_config.ini b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/port_config.ini new file mode 100644 index 000000000000..ee425d4ad4f6 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index speed +Ethernet0 49,50,51,52 hundredGigE1/1 0 100000 +Ethernet4 53,54,55,56 hundredGigE1/2 1 100000 +Ethernet8 65,66,67,68 hundredGigE1/3 2 100000 +Ethernet12 69,70,71,72 hundredGigE1/4 3 100000 +Ethernet16 81,82,83,84 hundredGigE1/5 4 100000 +Ethernet20 85,86,87,88 hundredGigE1/6 5 100000 +Ethernet24 1,2,3,4 hundredGigE1/7 6 100000 +Ethernet28 101,102,103,104 hundredGigE1/8 7 100000 +Ethernet32 5,6,7,8 hundredGigE1/9 8 100000 +Ethernet36 17,18,19,20 hundredGigE1/10 9 100000 +Ethernet40 21,22,23,24 hundredGigE1/11 10 100000 +Ethernet44 33,34,35,36 hundredGigE1/12 11 100000 +Ethernet48 37,38,39,40 hundredGigE1/13 12 100000 +Ethernet52 97,98,99,100 hundredGigE1/14 13 100000 +Ethernet56 113,114,115,116 hundredGigE1/15 14 100000 +Ethernet60 117,118,119,120 hundredGigE1/16 15 100000 +Ethernet64 129,130,131,132 hundredGigE1/17 16 100000 +Ethernet68 133,134,135,136 hundredGigE1/18 17 100000 +Ethernet72 145,146,147,148 hundredGigE1/19 18 100000 +Ethernet76 209,210,211,212 hundredGigE1/20 19 100000 +Ethernet80 213,214,215,216 hundredGigE1/21 20 100000 +Ethernet84 225,226,227,228 hundredGigE1/22 21 100000 +Ethernet88 229,230,231,232 hundredGigE1/23 22 100000 +Ethernet92 241,242,243,244 hundredGigE1/24 23 100000 +Ethernet96 245,246,247,248 hundredGigE1/25 24 100000 +Ethernet100 157,158,159,160 hundredGigE1/26 25 100000 +Ethernet104 161,162,163,164 hundredGigE1/27 26 100000 +Ethernet108 165,166,167,168 hundredGigE1/28 27 100000 +Ethernet112 177,178,179,180 hundredGigE1/29 28 100000 +Ethernet116 181,182,183,184 hundredGigE1/30 29 100000 +Ethernet120 193,194,195,196 hundredGigE1/31 30 100000 +Ethernet124 197,198,199,200 hundredGigE1/32 31 100000 +Ethernet128 61,62,63,64 hundredGigE1/33 32 100000 +Ethernet132 57,58,59,60 hundredGigE1/34 33 100000 +Ethernet136 77,78,79,80 hundredGigE1/35 34 100000 +Ethernet140 73,74,75,76 hundredGigE1/36 35 100000 +Ethernet144 93,94,95,96 hundredGigE1/37 36 100000 +Ethernet148 89,90,91,92 hundredGigE1/38 37 100000 +Ethernet152 105,106,107,108 hundredGigE1/39 38 100000 +Ethernet156 9,10,11,12 hundredGigE1/40 39 100000 +Ethernet160 25,26,27,28 hundredGigE1/41 40 100000 +Ethernet164 13,14,15,16 hundredGigE1/42 41 100000 +Ethernet168 41,42,43,44 hundredGigE1/43 42 100000 +Ethernet172 29,30,31,32 hundredGigE1/44 43 100000 +Ethernet176 45,46,47,48 hundredGigE1/45 44 100000 +Ethernet180 109,110,111,112 hundredGigE1/46 45 100000 +Ethernet184 125,126,127,128 hundredGigE1/47 46 100000 +Ethernet188 121,122,123,124 hundredGigE1/48 47 100000 +Ethernet192 141,142,143,144 hundredGigE1/49 48 100000 +Ethernet196 137,138,139,140 hundredGigE1/50 49 100000 +Ethernet200 217,218,219,220 hundredGigE1/51 50 100000 +Ethernet204 149,150,151,152 hundredGigE1/52 51 100000 +Ethernet208 233,234,235,236 hundredGigE1/53 52 100000 +Ethernet212 221,222,223,224 hundredGigE1/54 53 100000 +Ethernet216 249,250,251,252 hundredGigE1/55 54 100000 +Ethernet220 237,238,239,240 hundredGigE1/56 55 100000 +Ethernet224 153,154,155,156 hundredGigE1/57 56 100000 +Ethernet228 253,254,255,256 hundredGigE1/58 57 100000 +Ethernet232 173,174,175,176 hundredGigE1/59 58 100000 +Ethernet236 169,170,171,172 hundredGigE1/60 59 100000 +Ethernet240 189,190,191,192 hundredGigE1/61 60 100000 +Ethernet244 185,186,187,188 hundredGigE1/62 61 100000 +Ethernet248 205,206,207,208 hundredGigE1/63 62 100000 +Ethernet252 201,202,203,204 hundredGigE1/64 63 100000 diff --git a/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/sai.profile b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/sai.profile new file mode 100644 index 000000000000..2fc46808b555 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-ag9064-64x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/th2-ag9064-64x100G.config.bcm b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/th2-ag9064-64x100G.config.bcm new file mode 100644 index 000000000000..4aba9cc855a2 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/Delta-ag9064/th2-ag9064-64x100G.config.bcm @@ -0,0 +1,795 @@ +core_clock_frequency=1700 +dport_map_enable=1 +dport_map_port_102=31 +dport_map_port_103=32 +dport_map_port_104=64 +dport_map_port_105=63 +dport_map_port_106=20 +dport_map_port_107=21 +dport_map_port_108=51 +dport_map_port_109=54 +dport_map_port_10=13 +dport_map_port_110=22 +dport_map_port_111=23 +dport_map_port_112=53 +dport_map_port_113=56 +dport_map_port_114=24 +dport_map_port_115=25 +dport_map_port_116=55 +dport_map_port_117=58 +dport_map_port_11=43 +dport_map_port_12=45 +dport_map_port_13=1 +dport_map_port_14=2 +dport_map_port_15=34 +dport_map_port_16=33 +dport_map_port_1=7 +dport_map_port_2=9 +dport_map_port_34=3 +dport_map_port_35=4 +dport_map_port_36=36 +dport_map_port_37=35 +dport_map_port_38=5 +dport_map_port_39=6 +dport_map_port_3=40 +dport_map_port_40=38 +dport_map_port_41=37 +dport_map_port_42=14 +dport_map_port_43=8 +dport_map_port_44=39 +dport_map_port_45=46 +dport_map_port_46=15 +dport_map_port_47=16 +dport_map_port_48=48 +dport_map_port_49=47 +dport_map_port_4=42 +dport_map_port_5=10 +dport_map_port_68=17 +dport_map_port_69=18 +dport_map_port_6=11 +dport_map_port_70=50 +dport_map_port_71=49 +dport_map_port_72=19 +dport_map_port_73=52 +dport_map_port_74=57 +dport_map_port_75=26 +dport_map_port_76=27 +dport_map_port_77=28 +dport_map_port_78=60 +dport_map_port_79=59 +dport_map_port_7=41 +dport_map_port_80=29 +dport_map_port_81=30 +dport_map_port_82=62 +dport_map_port_83=61 +dport_map_port_8=44 +dport_map_port_9=12 +dpp_clock_ratio=2:3 +fpem_mem_entries=65536 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +mem_cache_enable=0 +os=unix +oversubscribe_mode=1 +parity_correction=0 +parity_enable=0 +pbmp_xport_xe=0x40003ffff0000ffffc0003fffe0001fffe +phy_chain_rx_lane_map_physical{1.0}=0x2130 +phy_chain_rx_lane_map_physical{101.0}=0x2310 +phy_chain_rx_lane_map_physical{105.0}=0x3021 +phy_chain_rx_lane_map_physical{109.0}=0x0213 +phy_chain_rx_lane_map_physical{113.0}=0x1302 +phy_chain_rx_lane_map_physical{117.0}=0x0312 +phy_chain_rx_lane_map_physical{121.0}=0x1203 +phy_chain_rx_lane_map_physical{125.0}=0x3021 +phy_chain_rx_lane_map_physical{129.0}=0x1302 +phy_chain_rx_lane_map_physical{13.0}=0x2310 +phy_chain_rx_lane_map_physical{133.0}=0x2310 +phy_chain_rx_lane_map_physical{137.0}=0x1023 +phy_chain_rx_lane_map_physical{141.0}=0x2031 +phy_chain_rx_lane_map_physical{145.0}=0x1032 +phy_chain_rx_lane_map_physical{149.0}=0x1203 +phy_chain_rx_lane_map_physical{153.0}=0x2310 +phy_chain_rx_lane_map_physical{157.0}=0x2013 +phy_chain_rx_lane_map_physical{161.0}=0x2103 +phy_chain_rx_lane_map_physical{165.0}=0x3012 +phy_chain_rx_lane_map_physical{169.0}=0x1320 +phy_chain_rx_lane_map_physical{17.0}=0x0213 +phy_chain_rx_lane_map_physical{173.0}=0x2301 +phy_chain_rx_lane_map_physical{177.0}=0x1032 +phy_chain_rx_lane_map_physical{181.0}=0x1032 +phy_chain_rx_lane_map_physical{185.0}=0x3210 +phy_chain_rx_lane_map_physical{189.0}=0x2103 +phy_chain_rx_lane_map_physical{193.0}=0x1032 +phy_chain_rx_lane_map_physical{197.0}=0x1032 +phy_chain_rx_lane_map_physical{201.0}=0x2301 +phy_chain_rx_lane_map_physical{205.0}=0x2301 +phy_chain_rx_lane_map_physical{209.0}=0x2103 +phy_chain_rx_lane_map_physical{21.0}=0x3120 +phy_chain_rx_lane_map_physical{213.0}=0x3201 +phy_chain_rx_lane_map_physical{217.0}=0x2301 +phy_chain_rx_lane_map_physical{221.0}=0x2301 +phy_chain_rx_lane_map_physical{225.0}=0x0123 +phy_chain_rx_lane_map_physical{229.0}=0x1302 +phy_chain_rx_lane_map_physical{233.0}=0x3120 +phy_chain_rx_lane_map_physical{237.0}=0x0123 +phy_chain_rx_lane_map_physical{241.0}=0x2310 +phy_chain_rx_lane_map_physical{245.0}=0x0312 +phy_chain_rx_lane_map_physical{249.0}=0x3021 +phy_chain_rx_lane_map_physical{25.0}=0x1203 +phy_chain_rx_lane_map_physical{253.0}=0x2013 +phy_chain_rx_lane_map_physical{29.0}=0x3012 +phy_chain_rx_lane_map_physical{33.0}=0x3210 +phy_chain_rx_lane_map_physical{37.0}=0x3210 +phy_chain_rx_lane_map_physical{41.0}=0x1230 +phy_chain_rx_lane_map_physical{45.0}=0x2013 +phy_chain_rx_lane_map_physical{49.0}=0x2301 +phy_chain_rx_lane_map_physical{5.0}=0x2031 +phy_chain_rx_lane_map_physical{53.0}=0x3210 +phy_chain_rx_lane_map_physical{57.0}=0x1203 +phy_chain_rx_lane_map_physical{61.0}=0x0231 +phy_chain_rx_lane_map_physical{65.0}=0x2301 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x2013 +phy_chain_rx_lane_map_physical{77.0}=0x3012 +phy_chain_rx_lane_map_physical{81.0}=0x2301 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x2013 +phy_chain_rx_lane_map_physical{9.0}=0x0312 +phy_chain_rx_lane_map_physical{93.0}=0x3012 +phy_chain_rx_lane_map_physical{97.0}=0x1320 +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 +phy_chain_rx_polarity_flip_physical{101.0}=0x1 +phy_chain_rx_polarity_flip_physical{102.0}=0x1 +phy_chain_rx_polarity_flip_physical{103.0}=0x0 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x0 +phy_chain_rx_polarity_flip_physical{109.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x1 +phy_chain_rx_polarity_flip_physical{110.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}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_rx_polarity_flip_physical{120.0}=0x1 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{123.0}=0x1 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 +phy_chain_rx_polarity_flip_physical{125.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x1 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x1 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x1 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_rx_polarity_flip_physical{141.0}=0x1 +phy_chain_rx_polarity_flip_physical{142.0}=0x1 +phy_chain_rx_polarity_flip_physical{143.0}=0x0 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x1 +phy_chain_rx_polarity_flip_physical{147.0}=0x0 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x0 +phy_chain_rx_polarity_flip_physical{152.0}=0x1 +phy_chain_rx_polarity_flip_physical{153.0}=0x1 +phy_chain_rx_polarity_flip_physical{154.0}=0x1 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x0 +phy_chain_rx_polarity_flip_physical{157.0}=0x1 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x0 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_rx_polarity_flip_physical{161.0}=0x0 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x1 +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x0 +phy_chain_rx_polarity_flip_physical{168.0}=0x1 +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{17.0}=0x1 +phy_chain_rx_polarity_flip_physical{170.0}=0x0 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x1 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x0 +phy_chain_rx_polarity_flip_physical{175.0}=0x1 +phy_chain_rx_polarity_flip_physical{176.0}=0x1 +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x1 +phy_chain_rx_polarity_flip_physical{18.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x1 +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x1 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_rx_polarity_flip_physical{185.0}=0x1 +phy_chain_rx_polarity_flip_physical{186.0}=0x1 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{190.0}=0x0 +phy_chain_rx_polarity_flip_physical{191.0}=0x0 +phy_chain_rx_polarity_flip_physical{192.0}=0x1 +phy_chain_rx_polarity_flip_physical{193.0}=0x1 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x1 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 +phy_chain_rx_polarity_flip_physical{197.0}=0x0 +phy_chain_rx_polarity_flip_physical{198.0}=0x1 +phy_chain_rx_polarity_flip_physical{199.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x1 +phy_chain_rx_polarity_flip_physical{203.0}=0x0 +phy_chain_rx_polarity_flip_physical{204.0}=0x1 +phy_chain_rx_polarity_flip_physical{205.0}=0x0 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x1 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_rx_polarity_flip_physical{209.0}=0x0 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{210.0}=0x1 +phy_chain_rx_polarity_flip_physical{211.0}=0x0 +phy_chain_rx_polarity_flip_physical{212.0}=0x1 +phy_chain_rx_polarity_flip_physical{213.0}=0x1 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x1 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 +phy_chain_rx_polarity_flip_physical{217.0}=0x0 +phy_chain_rx_polarity_flip_physical{218.0}=0x1 +phy_chain_rx_polarity_flip_physical{219.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{220.0}=0x0 +phy_chain_rx_polarity_flip_physical{221.0}=0x0 +phy_chain_rx_polarity_flip_physical{222.0}=0x0 +phy_chain_rx_polarity_flip_physical{223.0}=0x1 +phy_chain_rx_polarity_flip_physical{224.0}=0x1 +phy_chain_rx_polarity_flip_physical{225.0}=0x1 +phy_chain_rx_polarity_flip_physical{226.0}=0x1 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x1 +phy_chain_rx_polarity_flip_physical{229.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x1 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 +phy_chain_rx_polarity_flip_physical{233.0}=0x1 +phy_chain_rx_polarity_flip_physical{234.0}=0x0 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x1 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x1 +phy_chain_rx_polarity_flip_physical{239.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 +phy_chain_rx_polarity_flip_physical{241.0}=0x0 +phy_chain_rx_polarity_flip_physical{242.0}=0x1 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x0 +phy_chain_rx_polarity_flip_physical{245.0}=0x1 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 +phy_chain_rx_polarity_flip_physical{249.0}=0x1 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x0 +phy_chain_rx_polarity_flip_physical{251.0}=0x1 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 +phy_chain_rx_polarity_flip_physical{253.0}=0x1 +phy_chain_rx_polarity_flip_physical{254.0}=0x1 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +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}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x1 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 +phy_chain_rx_polarity_flip_physical{37.0}=0x0 +phy_chain_rx_polarity_flip_physical{38.0}=0x1 +phy_chain_rx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_polarity_flip_physical{40.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}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x1 +phy_chain_rx_polarity_flip_physical{47.0}=0x1 +phy_chain_rx_polarity_flip_physical{48.0}=0x0 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +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}=0x1 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{76.0}=0x1 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x0 +phy_chain_rx_polarity_flip_physical{84.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 +phy_chain_rx_polarity_flip_physical{93.0}=0x0 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +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}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_lane_map_physical{1.0}=0x2301 +phy_chain_tx_lane_map_physical{101.0}=0x2103 +phy_chain_tx_lane_map_physical{105.0}=0x2310 +phy_chain_tx_lane_map_physical{109.0}=0x2013 +phy_chain_tx_lane_map_physical{113.0}=0x0312 +phy_chain_tx_lane_map_physical{117.0}=0x1230 +phy_chain_tx_lane_map_physical{121.0}=0x1203 +phy_chain_tx_lane_map_physical{125.0}=0x1203 +phy_chain_tx_lane_map_physical{129.0}=0x1320 +phy_chain_tx_lane_map_physical{13.0}=0x0312 +phy_chain_tx_lane_map_physical{133.0}=0x3201 +phy_chain_tx_lane_map_physical{137.0}=0x2130 +phy_chain_tx_lane_map_physical{141.0}=0x1032 +phy_chain_tx_lane_map_physical{145.0}=0x1320 +phy_chain_tx_lane_map_physical{149.0}=0x0321 +phy_chain_tx_lane_map_physical{153.0}=0x1023 +phy_chain_tx_lane_map_physical{157.0}=0x3021 +phy_chain_tx_lane_map_physical{161.0}=0x0321 +phy_chain_tx_lane_map_physical{165.0}=0x2130 +phy_chain_tx_lane_map_physical{169.0}=0x1320 +phy_chain_tx_lane_map_physical{17.0}=0x0213 +phy_chain_tx_lane_map_physical{173.0}=0x2130 +phy_chain_tx_lane_map_physical{177.0}=0x0321 +phy_chain_tx_lane_map_physical{181.0}=0x2130 +phy_chain_tx_lane_map_physical{185.0}=0x0132 +phy_chain_tx_lane_map_physical{189.0}=0x1320 +phy_chain_tx_lane_map_physical{193.0}=0x3012 +phy_chain_tx_lane_map_physical{197.0}=0x2130 +phy_chain_tx_lane_map_physical{201.0}=0x1023 +phy_chain_tx_lane_map_physical{205.0}=0x1320 +phy_chain_tx_lane_map_physical{209.0}=0x0321 +phy_chain_tx_lane_map_physical{21.0}=0x2310 +phy_chain_tx_lane_map_physical{213.0}=0x2031 +phy_chain_tx_lane_map_physical{217.0}=0x1032 +phy_chain_tx_lane_map_physical{221.0}=0x3201 +phy_chain_tx_lane_map_physical{225.0}=0x0123 +phy_chain_tx_lane_map_physical{229.0}=0x0231 +phy_chain_tx_lane_map_physical{233.0}=0x1302 +phy_chain_tx_lane_map_physical{237.0}=0x3210 +phy_chain_tx_lane_map_physical{241.0}=0x0312 +phy_chain_tx_lane_map_physical{245.0}=0x2031 +phy_chain_tx_lane_map_physical{249.0}=0x3201 +phy_chain_tx_lane_map_physical{25.0}=0x0312 +phy_chain_tx_lane_map_physical{253.0}=0x3120 +phy_chain_tx_lane_map_physical{29.0}=0x1230 +phy_chain_tx_lane_map_physical{33.0}=0x3201 +phy_chain_tx_lane_map_physical{37.0}=0x3201 +phy_chain_tx_lane_map_physical{41.0}=0x3201 +phy_chain_tx_lane_map_physical{45.0}=0x2031 +phy_chain_tx_lane_map_physical{49.0}=0x0132 +phy_chain_tx_lane_map_physical{5.0}=0x2301 +phy_chain_tx_lane_map_physical{53.0}=0x3201 +phy_chain_tx_lane_map_physical{57.0}=0x3201 +phy_chain_tx_lane_map_physical{61.0}=0x2031 +phy_chain_tx_lane_map_physical{65.0}=0x0321 +phy_chain_tx_lane_map_physical{69.0}=0x3201 +phy_chain_tx_lane_map_physical{73.0}=0x3201 +phy_chain_tx_lane_map_physical{77.0}=0x1032 +phy_chain_tx_lane_map_physical{81.0}=0x0132 +phy_chain_tx_lane_map_physical{85.0}=0x1320 +phy_chain_tx_lane_map_physical{89.0}=0x3201 +phy_chain_tx_lane_map_physical{9.0}=0x2130 +phy_chain_tx_lane_map_physical{93.0}=0x0321 +phy_chain_tx_lane_map_physical{97.0}=0x1320 +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 +phy_chain_tx_polarity_flip_physical{101.0}=0x0 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +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}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +phy_chain_tx_polarity_flip_physical{114.0}=0x0 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +phy_chain_tx_polarity_flip_physical{116.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +phy_chain_tx_polarity_flip_physical{129.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x1 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x1 +phy_chain_tx_polarity_flip_physical{136.0}=0x0 +phy_chain_tx_polarity_flip_physical{137.0}=0x0 +phy_chain_tx_polarity_flip_physical{138.0}=0x1 +phy_chain_tx_polarity_flip_physical{139.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +phy_chain_tx_polarity_flip_physical{140.0}=0x1 +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x0 +phy_chain_tx_polarity_flip_physical{143.0}=0x1 +phy_chain_tx_polarity_flip_physical{144.0}=0x1 +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x1 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x1 +phy_chain_tx_polarity_flip_physical{152.0}=0x1 +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 +phy_chain_tx_polarity_flip_physical{157.0}=0x1 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +phy_chain_tx_polarity_flip_physical{160.0}=0x1 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x0 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x1 +phy_chain_tx_polarity_flip_physical{165.0}=0x0 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x1 +phy_chain_tx_polarity_flip_physical{169.0}=0x1 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x1 +phy_chain_tx_polarity_flip_physical{172.0}=0x1 +phy_chain_tx_polarity_flip_physical{173.0}=0x1 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x1 +phy_chain_tx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x1 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x0 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x1 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x1 +phy_chain_tx_polarity_flip_physical{185.0}=0x1 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x1 +phy_chain_tx_polarity_flip_physical{188.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x1 +phy_chain_tx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x1 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x1 +phy_chain_tx_polarity_flip_physical{197.0}=0x0 +phy_chain_tx_polarity_flip_physical{198.0}=0x1 +phy_chain_tx_polarity_flip_physical{199.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 +phy_chain_tx_polarity_flip_physical{201.0}=0x0 +phy_chain_tx_polarity_flip_physical{202.0}=0x1 +phy_chain_tx_polarity_flip_physical{203.0}=0x1 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x0 +phy_chain_tx_polarity_flip_physical{207.0}=0x1 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 +phy_chain_tx_polarity_flip_physical{209.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x1 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x0 +phy_chain_tx_polarity_flip_physical{212.0}=0x1 +phy_chain_tx_polarity_flip_physical{213.0}=0x1 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x1 +phy_chain_tx_polarity_flip_physical{217.0}=0x1 +phy_chain_tx_polarity_flip_physical{218.0}=0x1 +phy_chain_tx_polarity_flip_physical{219.0}=0x1 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x1 +phy_chain_tx_polarity_flip_physical{223.0}=0x1 +phy_chain_tx_polarity_flip_physical{224.0}=0x1 +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x0 +phy_chain_tx_polarity_flip_physical{227.0}=0x0 +phy_chain_tx_polarity_flip_physical{228.0}=0x1 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x0 +phy_chain_tx_polarity_flip_physical{231.0}=0x1 +phy_chain_tx_polarity_flip_physical{232.0}=0x0 +phy_chain_tx_polarity_flip_physical{233.0}=0x1 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x0 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x1 +phy_chain_tx_polarity_flip_physical{241.0}=0x1 +phy_chain_tx_polarity_flip_physical{242.0}=0x0 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x1 +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x0 +phy_chain_tx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{250.0}=0x1 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x1 +phy_chain_tx_polarity_flip_physical{253.0}=0x1 +phy_chain_tx_polarity_flip_physical{254.0}=0x1 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x1 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{47.0}=0x1 +phy_chain_tx_polarity_flip_physical{48.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +phy_chain_tx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +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{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 +phy_chain_tx_polarity_flip_physical{65.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x0 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.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}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{89.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +portmap_102=193:100 +portmap_103=197:100 +portmap_104=201:100 +portmap_105=205:100 +portmap_106=209:100 +portmap_107=213:100 +portmap_108=217:100 +portmap_109=221:100 +portmap_10=37:100 +portmap_110=225:100 +portmap_111=229:100 +portmap_112=233:100 +portmap_113=237:100 +portmap_114=241:100 +portmap_115=245:100 +portmap_116=249:100 +portmap_117=253:100 +portmap_11=41:100 +portmap_12=45:100 +portmap_13=49:100 +portmap_14=53:100 +portmap_15=57:100 +portmap_16=61:100 +portmap_1=1:100 +portmap_2=5:100 +portmap_34=65:100 +portmap_35=69:100 +portmap_36=73:100 +portmap_37=77:100 +portmap_38=81:100 +portmap_39=85:100 +portmap_3=9:100 +portmap_40=89:100 +portmap_41=93:100 +portmap_42=97:100 +portmap_43=101:100 +portmap_44=105:100 +portmap_45=109:100 +portmap_46=113:100 +portmap_47=117:100 +portmap_48=121:100 +portmap_49=125:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_68=129:100 +portmap_69=133:100 +portmap_6=21:100 +portmap_70=137:100 +portmap_71=141:100 +portmap_72=145:100 +portmap_73=149:100 +portmap_74=153:100 +portmap_75=157:100 +portmap_76=161:100 +portmap_77=165:100 +portmap_78=169:100 +portmap_79=173:100 +portmap_7=25:100 +portmap_80=177:100 +portmap_81=181:100 +portmap_82=185:100 +portmap_83=189:100 +portmap_8=29:100 +portmap_9=33:100 + +lpm_scaling_enable=0 +bcm_num_cos=10 +bcm_stat_jumbo=9236 +ipv6_lpm_128b_enable=1 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +phy_an_allow_pll_change_hg=0 +robust_hash_disable_egress_vlan=1 +robust_hash_disable_mpls=1 +robust_hash_disable_vlan=1 +stable_size=0x5500000 +mmu_lossless=1 diff --git a/device/delta/x86_64-delta_ag9064-r0/default_sku b/device/delta/x86_64-delta_ag9064-r0/default_sku new file mode 100644 index 000000000000..5de7fcd3733a --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/default_sku @@ -0,0 +1 @@ +Delta-ag9064 t1 diff --git a/device/delta/x86_64-delta_ag9064-r0/installer.conf b/device/delta/x86_64-delta_ag9064-r0/installer.conf new file mode 100644 index 000000000000..85ed43ab48ed --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_SPEED=115200 +CONSOLE_DEV=0 diff --git a/device/delta/x86_64-delta_ag9064-r0/led_proc_init.soc b/device/delta/x86_64-delta_ag9064-r0/led_proc_init.soc new file mode 100644 index 000000000000..2e6f394b1219 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/led_proc_init.soc @@ -0,0 +1,63 @@ +led 0 stop +led 0 prog \ + 02 00 60 E0 02 A0 60 E2 86 ED 02 00 60 E1 2E E0 \ + 32 08 97 02 00 0E 05 60 E3 2E E0 32 00 32 01 B7 \ + 97 02 00 0E 00 12 E7 FE E1 50 86 E0 86 E1 06 E1 \ + D2 04 74 19 16 E7 61 EB 06 E3 12 05 67 92 06 E3 \ + 12 04 67 92 06 E3 12 03 67 92 16 E9 61 EB 06 E5 \ + 12 03 67 92 02 02 60 EC 02 00 60 E1 77 66 02 01 \ + 60 EC 02 00 60 E1 12 E7 FE E1 05 60 EB 12 E3 FE \ + E1 05 16 EC 67 92 86 E1 06 E1 D2 04 74 66 06 EC \ + D2 02 70 5E 06 E2 F2 04 60 E2 06 E0 D2 40 74 0A \ + 3A C0 09 75 A9 06 EB D2 00 70 A5 16 ED 99 99 1A \ + 00 71 A5 77 A9 32 0F 87 57 32 0E 87 57 00 00 00 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog \ + 02 00 60 E0 02 A0 60 E2 86 ED 02 00 60 E1 2E E0 \ + 32 08 97 02 00 0E 05 60 E3 2E E0 32 00 32 01 B7 \ + 97 02 00 0E 00 12 E7 FE E1 50 86 E0 86 E1 06 E1 \ + D2 04 74 19 16 E7 61 EB 06 E3 12 05 67 92 06 E3 \ + 12 04 67 92 06 E3 12 03 67 92 16 E9 61 EB 06 E5 \ + 12 03 67 92 02 02 60 EC 02 00 60 E1 77 66 02 01 \ + 60 EC 02 00 60 E1 12 E7 FE E1 05 60 EB 12 E3 FE \ + E1 05 16 EC 67 92 86 E1 06 E1 D2 04 74 66 06 EC \ + D2 02 70 5E 06 E2 F2 04 60 E2 06 E0 D2 40 74 0A \ + 3A C0 09 75 A9 06 EB D2 00 70 A5 16 ED 99 99 1A \ + 00 71 A5 77 A9 32 0F 87 57 32 0E 87 57 00 00 00 +led 1 auto on +led 1 start + +led 2 stop +led 2 prog \ + 02 00 60 E0 02 A0 60 E2 86 ED 02 00 60 E1 2E E0 \ + 32 08 97 02 00 0E 05 60 E3 2E E0 32 00 32 01 B7 \ + 97 02 00 0E 00 12 E7 FE E1 50 86 E0 86 E1 06 E1 \ + D2 04 74 19 16 E7 61 EB 06 E3 12 05 67 92 06 E3 \ + 12 04 67 92 06 E3 12 03 67 92 16 E9 61 EB 06 E5 \ + 12 03 67 92 02 02 60 EC 02 00 60 E1 77 66 02 01 \ + 60 EC 02 00 60 E1 12 E7 FE E1 05 60 EB 12 E3 FE \ + E1 05 16 EC 67 92 86 E1 06 E1 D2 04 74 66 06 EC \ + D2 02 70 5E 06 E2 F2 04 60 E2 06 E0 D2 40 74 0A \ + 3A C0 09 75 A9 06 EB D2 00 70 A5 16 ED 99 99 1A \ + 00 71 A5 77 A9 32 0F 87 57 32 0E 87 57 00 00 00 +led 2 auto on +led 2 start + +led 3 stop +led 3 prog \ + 02 00 60 E0 02 A0 60 E2 86 ED 02 00 60 E1 2E E0 \ + 32 08 97 02 00 0E 05 60 E3 2E E0 32 00 32 01 B7 \ + 97 02 00 0E 00 12 E7 FE E1 50 86 E0 86 E1 06 E1 \ + D2 04 74 19 16 E7 61 EB 06 E3 12 05 67 92 06 E3 \ + 12 04 67 92 06 E3 12 03 67 92 16 E9 61 EB 06 E5 \ + 12 03 67 92 02 02 60 EC 02 00 60 E1 77 66 02 01 \ + 60 EC 02 00 60 E1 12 E7 FE E1 05 60 EB 12 E3 FE \ + E1 05 16 EC 67 92 86 E1 06 E1 D2 04 74 66 06 EC \ + D2 02 70 5E 06 E2 F2 04 60 E2 06 E0 D2 40 74 0A \ + 3A C0 09 75 A9 06 EB D2 00 70 A5 16 ED 99 99 1A \ + 00 71 A5 77 A9 32 0F 87 57 32 0E 87 57 00 00 00 +led 3 auto on +led 3 start diff --git a/device/delta/x86_64-delta_ag9064-r0/plugins/eeprom.py b/device/delta/x86_64-delta_ag9064-r0/plugins/eeprom.py new file mode 100644 index 000000000000..9a3ea5737684 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/plugins/eeprom.py @@ -0,0 +1,30 @@ +############################################################################# +# Mellanox +# +# 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 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 as 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/devices/pci0000:00/0000:00:1f.3/i2c-0/0-0056/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_ag9064-r0/plugins/psuutil.py b/device/delta/x86_64-delta_ag9064-r0/plugins/psuutil.py new file mode 100644 index 000000000000..43f7bb6acb3c --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/plugins/psuutil.py @@ -0,0 +1,76 @@ +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# + +import os.path +import subprocess + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + self.psu_presence = "cat /sys/devices/platform/delta-ag9064-cpld.0/psu{}_scan" + self.psu_status = "cat /sys/devices/platform/delta-ag9064-swpld1.0/psu{}_pwr_ok" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + p = os.popen(self.psu_status.format(index)) + content = p.readline().rstrip() + reg_value = int(content) + if reg_value != 0: + return False + status = 1 + p.close() + except IOError: + return False + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + status = 0 + try: + p = os.popen(self.psu_presence.format(index)) + content = p.readline().rstrip() + reg_value = int(content, 16) + if reg_value != 0: + return False + status = 1 + p.close() + except IOError: + return False + return status == 1 diff --git a/device/delta/x86_64-delta_ag9064-r0/plugins/sfputil.py b/device/delta/x86_64-delta_ag9064-r0/plugins/sfputil.py new file mode 100644 index 000000000000..f86fac5f2af2 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/plugins/sfputil.py @@ -0,0 +1,183 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 63 + PORTS_IN_BLOCK = 64 + + EEPROM_OFFSET = 1 + + _port_to_eeprom_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 list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/kernel/sfp/eeprom_sfp_{0}" + + for x in range(0, self.port_end + 1): + 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 < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9064-cpld.0/qsfp_present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9064-cpld.0/qsfp_lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-ag9064-cpld.0/qsfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value).rstrip("L") or "0" + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/delta-ag9064-cpld.0/qsfp_reset" + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/delta/x86_64-delta_ag9064-r0/sensors.conf b/device/delta/x86_64-delta_ag9064-r0/sensors.conf new file mode 100644 index 000000000000..1d8489248a51 --- /dev/null +++ b/device/delta/x86_64-delta_ag9064-r0/sensors.conf @@ -0,0 +1,14 @@ +# libsensors configuration file for DCS-7060CX-32S +# ------------------------------------------------ +# + +bus "i2c-1" "i2c-1-mux (chan_id 1)" + + +# tmp75-i2c-1-4d CPU below side thermal sensor. + +chip "tmp75-i2c-1-4d" + label temp1 "CPU below side thermal sensor" + set temp1_max 60 + set temp1_max_hyst 55 + diff --git a/device/delta/x86_64-delta_agc032-r0/Delta-agc032/port_config.ini b/device/delta/x86_64-delta_agc032-r0/Delta-agc032/port_config.ini new file mode 100644 index 000000000000..e081ee55aea7 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/Delta-agc032/port_config.ini @@ -0,0 +1,35 @@ +# name lanes alias speed index +Ethernet0 17,18,19,20,21,22,23,24 fourhundredGigE1/1 400000 0 +Ethernet4 25,26,27,28,29,30,31,32 fourhundredGigE1/2 400000 1 +Ethernet8 1,2,3,4,5,6,7,8, fourhundredGigE1/3 400000 2 +Ethernet12 9,10,11,12,13,14,15,16 fourhundredGigE1/4 400000 3 +Ethernet16 49,50,51,52,53,54,55,56 fourhundredGigE1/5 400000 4 +Ethernet20 57,58,59,60,61,62,63,64 fourhundredGigE1/6 400000 5 +Ethernet24 33,34,35,36,37,38,39,40 fourhundredGigE1/7 400000 6 +Ethernet28 41,42,43,44,45,46,47,48 fourhundredGigE1/8 400000 7 +Ethernet32 81,82,83,84,85,86,87,88 fourhundredGigE1/9 400000 8 +Ethernet36 89,90,91,92,93,94,95,96 fourhundredGigE1/10 400000 9 +Ethernet40 65,66,67,68,69,70,71,72 fourhundredGigE1/11 400000 10 +Ethernet44 73,74,75,76,77,78,79,80 fourhundredGigE1/12 400000 11 +Ethernet48 113,114,115,116,117,118,119,120 fourhundredGigE1/13 400000 12 +Ethernet52 121,122,123,124,125,126,127,128 fourhundredGigE1/14 400000 13 +Ethernet56 97,98,99,100,101,102,103,104 fourhundredGigE1/15 400000 14 +Ethernet60 105,106,107,108,109,110,111,112 fourhundredGigE1/16 400000 15 +Ethernet64 129,130,131,132,133,134,135,136 fourhundredGigE1/17 400000 16 +Ethernet68 137,138,139,140,141,142,143,144 fourhundredGigE1/18 400000 17 +Ethernet72 145,146,147,148,149,150,151,152 fourhundredGigE1/19 400000 18 +Ethernet76 153,154,155,156,157,158,159,160 fourhundredGigE1/20 400000 19 +Ethernet80 161,162,163,164,165,166,167,168 fourhundredGigE1/21 400000 20 +Ethernet84 169,170,171,172,173,174,175,176 fourhundredGigE1/22 400000 21 +Ethernet88 177,178,179,180,181,182,183,184 fourhundredGigE1/23 400000 22 +Ethernet92 185,186,187,188,189,190,191,192 fourhundredGigE1/24 400000 23 +Ethernet96 193,194,195,196,197,198,199,200 fourhundredGigE1/25 400000 24 +Ethernet100 201,202,203,204,205,206,207,208 fourhundredGigE1/26 400000 25 +Ethernet104 209,210,211,212,213,214,215,216 fourhundredGigE1/27 400000 26 +Ethernet108 217,218,219,220,221,222,223,224 fourhundredGigE1/28 400000 27 +Ethernet112 225,226,227,228,229,230,231,232 fourhundredGigE1/29 400000 28 +Ethernet116 233,234,235,236,237,238,239,240 fourhundredGigE1/30 400000 29 +Ethernet120 241,242,243,244,245,246,247,248 fourhundredGigE1/31 400000 30 +Ethernet124 249,250,251,252,253,254,255,256 fourhundredGigE1/32 400000 31 +Ethernet128 257 tenGigE1/33 10000 32 +Ethernet132 258 tenGigE1/34 10000 33 diff --git a/device/delta/x86_64-delta_agc032-r0/Delta-agc032/sai.profile b/device/delta/x86_64-delta_agc032-r0/Delta-agc032/sai.profile new file mode 100644 index 000000000000..2da82c5bffa5 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/Delta-agc032/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-agc032-32x400G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/delta/x86_64-delta_agc032-r0/Delta-agc032/th3-agc032-32x400G.config.bcm b/device/delta/x86_64-delta_agc032-r0/Delta-agc032/th3-agc032-32x400G.config.bcm new file mode 100644 index 000000000000..d3dfd269ff1b --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/Delta-agc032/th3-agc032-32x400G.config.bcm @@ -0,0 +1,280 @@ +######################################### +## cfg for AGC032 +######################################### +pbmp_xport_xe=0x8000f8000fc000f8000f8000f8000fc000f8001e +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 +init_all_modules=0 +################################################################################ +# Pipe 0 +portmap_1=1:400 +portmap_2=9:400 +portmap_3=17:400 +portmap_4=25:400 + +#loopback port +portmap_19=259:10 +################################################################################ +# Pipe 1 +portmap_20=33:400 +portmap_21=41:400 +portmap_22=49:400 +portmap_23=57:400 + +#management port +portmap_38=257:10 + +#loopback port +portmap_39=260:10 +################################################################################ +# Pipe 2 +portmap_40=65:400 +portmap_41=73:400 +portmap_42=81:400 +portmap_43=89:400 + +#loopback port +portmap_59=261:10 +################################################################################ +# Pipe 3 +portmap_60=97:400 +portmap_61=105:400 +portmap_62=113:400 +portmap_63=121:400 + +#loopback port +portmap_79=262:10 +################################################################################ +# Pipe 4 +portmap_80=129:400 +portmap_81=137:400 +portmap_82=145:400 +portmap_83=153:400 + +#loopback port +portmap_99=263:10 +################################################################################ +# Pipe 5 +portmap_100=161:400 +portmap_101=169:400 +portmap_102=177:400 +portmap_103=185:400 + +#management port +portmap_118=258:10 + +#loopback port +portmap_119=264:10 +################################################################################ +# Pipe 6 +portmap_120=193:400 +portmap_121=201:400 +portmap_122=209:400 +portmap_123=217:400 + +#loopback port +portmap_139=265:10 +################################################################################ +# Pipe 7 +portmap_140=225:400 +portmap_141=233:400 +portmap_142=241:400 +portmap_143=249:400 + +#loopback port +portmap_159=266:10 +################################################################################ +dport_map_enable=1 + +dport_map_port_1=3 +dport_map_port_2=4 +dport_map_port_3=1 +dport_map_port_4=2 +dport_map_port_20=7 +dport_map_port_21=8 +dport_map_port_22=5 +dport_map_port_23=6 +dport_map_port_40=11 +dport_map_port_41=12 +dport_map_port_42=9 +dport_map_port_43=10 +dport_map_port_60=15 +dport_map_port_61=16 +dport_map_port_62=13 +dport_map_port_63=14 +dport_map_port_80=17 +dport_map_port_81=18 +dport_map_port_82=19 +dport_map_port_83=20 +dport_map_port_100=21 +dport_map_port_101=22 +dport_map_port_102=23 +dport_map_port_103=24 +dport_map_port_120=25 +dport_map_port_121=26 +dport_map_port_122=27 +dport_map_port_123=28 +dport_map_port_140=29 +dport_map_port_141=30 +dport_map_port_142=31 +dport_map_port_143=32 + +dport_map_port_38=33 +dport_map_port_118=34 +################################################################################ +# tx_lane map +phy_chain_tx_lane_map_physical{1.0}=0x14762350 +phy_chain_tx_lane_map_physical{9.0}=0x36104527 +phy_chain_tx_lane_map_physical{17.0}=0x17053624 +phy_chain_tx_lane_map_physical{25.0}=0x57314602 +phy_chain_tx_lane_map_physical{33.0}=0x46302517 +phy_chain_tx_lane_map_physical{41.0}=0x76203514 +phy_chain_tx_lane_map_physical{49.0}=0x26143507 +phy_chain_tx_lane_map_physical{57.0}=0x74236510 +phy_chain_tx_lane_map_physical{65.0}=0x75021436 +phy_chain_tx_lane_map_physical{73.0}=0x67210435 +phy_chain_tx_lane_map_physical{81.0}=0x26143507 +phy_chain_tx_lane_map_physical{89.0}=0x75436120 +phy_chain_tx_lane_map_physical{97.0}=0x54621730 +phy_chain_tx_lane_map_physical{105.0}=0x64310725 +phy_chain_tx_lane_map_physical{113.0}=0x07352416 +phy_chain_tx_lane_map_physical{121.0}=0x13762054 +phy_chain_tx_lane_map_physical{129.0}=0x13427506 +phy_chain_tx_lane_map_physical{137.0}=0x54307612 +phy_chain_tx_lane_map_physical{145.0}=0x76103524 +phy_chain_tx_lane_map_physical{153.0}=0x67103425 +phy_chain_tx_lane_map_physical{161.0}=0x15402637 +phy_chain_tx_lane_map_physical{169.0}=0x76135420 +phy_chain_tx_lane_map_physical{177.0}=0x67052431 +phy_chain_tx_lane_map_physical{185.0}=0x57103624 +phy_chain_tx_lane_map_physical{193.0}=0x15402637 +phy_chain_tx_lane_map_physical{201.0}=0x54137620 +phy_chain_tx_lane_map_physical{209.0}=0x56012734 +phy_chain_tx_lane_map_physical{217.0}=0x57301426 +phy_chain_tx_lane_map_physical{225.0}=0x07352641 +phy_chain_tx_lane_map_physical{233.0}=0x57236401 +phy_chain_tx_lane_map_physical{241.0}=0x16543720 +phy_chain_tx_lane_map_physical{249.0}=0x50273416 + +# rx_lane_map +phy_chain_rx_lane_map_physical{1.0}=0x42305761 +phy_chain_rx_lane_map_physical{9.0}=0x13605472 +phy_chain_rx_lane_map_physical{17.0}=0x41730652 +phy_chain_rx_lane_map_physical{25.0}=0x71206534 +phy_chain_rx_lane_map_physical{33.0}=0x62170453 +phy_chain_rx_lane_map_physical{41.0}=0x27641305 +phy_chain_rx_lane_map_physical{49.0}=0x53604271 +phy_chain_rx_lane_map_physical{57.0}=0x31607425 +phy_chain_rx_lane_map_physical{65.0}=0x47612350 +phy_chain_rx_lane_map_physical{73.0}=0x23471605 +phy_chain_rx_lane_map_physical{81.0}=0x43710265 +phy_chain_rx_lane_map_physical{89.0}=0x31706425 +phy_chain_rx_lane_map_physical{97.0}=0x60317425 +phy_chain_rx_lane_map_physical{105.0}=0x40635172 +phy_chain_rx_lane_map_physical{113.0}=0x20573146 +phy_chain_rx_lane_map_physical{121.0}=0x51204637 +phy_chain_rx_lane_map_physical{129.0}=0x34102567 +phy_chain_rx_lane_map_physical{137.0}=0x70143526 +phy_chain_rx_lane_map_physical{145.0}=0x20316574 +phy_chain_rx_lane_map_physical{153.0}=0x13572046 +phy_chain_rx_lane_map_physical{161.0}=0x61253074 +phy_chain_rx_lane_map_physical{169.0}=0x61043527 +phy_chain_rx_lane_map_physical{177.0}=0x43617250 +phy_chain_rx_lane_map_physical{185.0}=0x31067425 +phy_chain_rx_lane_map_physical{193.0}=0x35162074 +phy_chain_rx_lane_map_physical{201.0}=0x30146527 +phy_chain_rx_lane_map_physical{209.0}=0x73506241 +phy_chain_rx_lane_map_physical{217.0}=0x73241605 +phy_chain_rx_lane_map_physical{225.0}=0x26573140 +phy_chain_rx_lane_map_physical{233.0}=0x46213750 +phy_chain_rx_lane_map_physical{241.0}=0x13650274 +phy_chain_rx_lane_map_physical{249.0}=0x42305167 + +# tx polarity +serdes_core_tx_polarity_flip_physical{1}=0x5d +serdes_core_tx_polarity_flip_physical{9}=0x9c +serdes_core_tx_polarity_flip_physical{17}=0x72 +serdes_core_tx_polarity_flip_physical{25}=0xad +serdes_core_tx_polarity_flip_physical{33}=0x38 +serdes_core_tx_polarity_flip_physical{41}=0x86 +serdes_core_tx_polarity_flip_physical{49}=0xaf +serdes_core_tx_polarity_flip_physical{57}=0xc6 +serdes_core_tx_polarity_flip_physical{65}=0x70 +serdes_core_tx_polarity_flip_physical{73}=0xc7 +serdes_core_tx_polarity_flip_physical{81}=0xae +serdes_core_tx_polarity_flip_physical{89}=0xe0 +serdes_core_tx_polarity_flip_physical{97}=0xf1 +serdes_core_tx_polarity_flip_physical{105}=0x0c +serdes_core_tx_polarity_flip_physical{113}=0xc8 +serdes_core_tx_polarity_flip_physical{121}=0x3f +serdes_core_tx_polarity_flip_physical{129}=0x8b +serdes_core_tx_polarity_flip_physical{137}=0x77 +serdes_core_tx_polarity_flip_physical{145}=0x39 +serdes_core_tx_polarity_flip_physical{153}=0xa5 +serdes_core_tx_polarity_flip_physical{161}=0xd8 +serdes_core_tx_polarity_flip_physical{169}=0x8b +serdes_core_tx_polarity_flip_physical{177}=0x29 +serdes_core_tx_polarity_flip_physical{185}=0x30 +serdes_core_tx_polarity_flip_physical{193}=0xf8 +serdes_core_tx_polarity_flip_physical{201}=0x8a +serdes_core_tx_polarity_flip_physical{209}=0xb8 +serdes_core_tx_polarity_flip_physical{217}=0x08 +serdes_core_tx_polarity_flip_physical{225}=0xb3 +serdes_core_tx_polarity_flip_physical{233}=0x62 +serdes_core_tx_polarity_flip_physical{241}=0x70 +serdes_core_tx_polarity_flip_physical{249}=0xd2 + +# rx poplarity +serdes_core_rx_polarity_flip_physical{1}=0x18 +serdes_core_rx_polarity_flip_physical{9}=0xa0 +serdes_core_rx_polarity_flip_physical{17}=0x9c +serdes_core_rx_polarity_flip_physical{25}=0x47 +serdes_core_rx_polarity_flip_physical{33}=0xf5 +serdes_core_rx_polarity_flip_physical{41}=0x38 +serdes_core_rx_polarity_flip_physical{49}=0x87 +serdes_core_rx_polarity_flip_physical{57}=0x1a +serdes_core_rx_polarity_flip_physical{65}=0xf0 +serdes_core_rx_polarity_flip_physical{73}=0x68 +serdes_core_rx_polarity_flip_physical{81}=0x96 +serdes_core_rx_polarity_flip_physical{89}=0x32 +serdes_core_rx_polarity_flip_physical{97}=0x5a +serdes_core_rx_polarity_flip_physical{105}=0xb4 +serdes_core_rx_polarity_flip_physical{113}=0xe1 +serdes_core_rx_polarity_flip_physical{121}=0x4a +serdes_core_rx_polarity_flip_physical{129}=0xf3 +serdes_core_rx_polarity_flip_physical{137}=0xc3 +serdes_core_rx_polarity_flip_physical{145}=0x12 +serdes_core_rx_polarity_flip_physical{153}=0xb4 +serdes_core_rx_polarity_flip_physical{161}=0xf0 +serdes_core_rx_polarity_flip_physical{169}=0xa7 +serdes_core_rx_polarity_flip_physical{177}=0xe1 +serdes_core_rx_polarity_flip_physical{185}=0x90 +serdes_core_rx_polarity_flip_physical{193}=0x0a +serdes_core_rx_polarity_flip_physical{201}=0x4e +serdes_core_rx_polarity_flip_physical{209}=0x5a +serdes_core_rx_polarity_flip_physical{217}=0x98 +serdes_core_rx_polarity_flip_physical{225}=0x2f +serdes_core_rx_polarity_flip_physical{233}=0x5b +serdes_core_rx_polarity_flip_physical{241}=0xf4 +serdes_core_rx_polarity_flip_physical{249}=0x1d +################################################################################ +#firmware load, use fast load +load_firmware=0x2 + +core_clock_frequency=1325 +dpr_clock_frequency=1000 +device_clock_frequency=1325 +port_flex_enable=1 + + +################################################################################ +serdes_tx_taps_cd=pam4:-36:118:0:8:6:0 + + diff --git a/device/delta/x86_64-delta_agc032-r0/custom_led.bin b/device/delta/x86_64-delta_agc032-r0/custom_led.bin new file mode 100644 index 000000000000..e91edee19815 Binary files /dev/null and b/device/delta/x86_64-delta_agc032-r0/custom_led.bin differ diff --git a/device/delta/x86_64-delta_agc032-r0/default_sku b/device/delta/x86_64-delta_agc032-r0/default_sku new file mode 100644 index 000000000000..afc35fa094b0 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/default_sku @@ -0,0 +1 @@ +Delta-agc032 t1 \ No newline at end of file diff --git a/device/delta/x86_64-delta_agc032-r0/fancontrol b/device/delta/x86_64-delta_agc032-r0/fancontrol new file mode 100644 index 000000000000..83805adc6804 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/fancontrol @@ -0,0 +1,10 @@ +INTERVAL=10 +DEVPATH=hwmon1=/sys/bus/i2c/devices +DEVNAME=hwmon1=emc2305 +FCTEMPS= hwmon1/i2c-4/4-004f/hwmon/hwmon*/temp1_input hwmon1/i2c-5/5-004a/hwmon/hwmon*/temp1_input hwmon1/i2c-5/5-004d/hwmon/hwmon*/temp1_input hwmon1/i2c-5/5-004b/hwmon/hwmon*/temp1_input hwmon1/i2c-5/5-0049/hwmon/hwmon*/temp1_input hwmon1/i2c-5/5-004e/hwmon/hwmon*/temp1_input + +FCFANS=hwmon1/4-004c/fan1_input hwmon1/4-004c/fan2_input hwmon1/4-004c/fan3_input hwmon1/4-004c/fan4_input hwmon1/4-004c/fan5_input hwmon1/4-002d/fan1_input hwmon1/4-002d/fan2_input hwmon1/4-002d/fan3_input hwmon1/4-002d/fan4_input hwmon1/4-002d/fan5_input hwmon1/4-002e/fan1_input hwmon1/4-002e/fan2_input +MINTEMP=20 +MAXTEMP=60 +MINSTART=75 +MINSTOP=22 diff --git a/device/delta/x86_64-delta_agc032-r0/fancontrol.service b/device/delta/x86_64-delta_agc032-r0/fancontrol.service new file mode 100755 index 000000000000..2052d1c34bb7 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/fancontrol.service @@ -0,0 +1,295 @@ +#!/bin/bash +# +# Simple script implementing a temperature dependent fan speed control +# Supported Linux kernel versions: 2.6.5 and later +# +# Version 0.70 +# +# Usage: fancontrol [CONFIGFILE] +# +# Dependencies: +# bash, egrep, sed, cut, sleep, readlink, lm_sensors :) +# +# Please send any questions, comments or success stories to +# marius.reiner@hdev.de +# Thanks! +# +# For configuration instructions and warnings please see fancontrol.txt, which +# can be found in the doc/ directory or at the website mentioned above. +# +# +# Copyright 2003 Marius Reiner +# Copyright (C) 2007-2009 Jean Delvare +# +# 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. +# +# 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 Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +# + +PIDFILE="/var/run/fancontrol.pid" + +#DEBUG=1 +MAX=255 + +function LoadConfig +{ + local fcvcount fcv + + echo "Loading configuration from $1 ..." + if [ ! -r "$1" ] + then + echo "Error: Can't read configuration file" >&2 + exit 1 + fi + + # grep configuration from file + INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'` + DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'` + DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'` + FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'` + MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'` + MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'` + MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'` + MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'` + HWMON=$( echo "$DEVPATH" | sed 's/=.*$//g') + FCDEVPATH=$( echo "$DEVPATH" | sed 's/^.*=//g') + FCMINTEMP=$MINTEMP + FCMAXTEMP=$MAXTEMP + FCMINSTART=$MINSTART + FCMINSTOP=$MINSTOP + AFCTEMP_1_LOWER=(00 39 36 41 46 55) + AFCTEMP_1_UPPER=(39 39 44 49 54 150) + AFCTEMP_2_LOWER=(00 61 65 69 73 82) + AFCTEMP_2_UPPER=(63 67 71 75 79 150) + AFCTEMP_3_LOWER=(00 51 55 59 63 71) + AFCTEMP_3_UPPER=(53 57 61 65 69 150) + AFCTEMP_4_LOWER=(00 46 50 54 58 65) + AFCTEMP_4_UPPER=(45 52 56 60 64 150) + AFCTEMP_5_LOWER=(00 46 50 54 58 65) + AFCTEMP_5_UPPER=(45 52 56 60 64 150) + + + FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'` + + # Check whether all mandatory settings are set + if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]] + then + echo "Some mandatory settings missing, please check your config file!" >&2 + exit 1 + fi + if [ "$INTERVAL" -le 0 ] + then + echo "Error in configuration file:" >&2 + echo "INTERVAL must be at least 1" >&2 + exit 1 + fi + + # write settings to arrays for easier use and print them + echo + echo "Common settings:" + + temp_string=$FCTEMPS + + let fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( echo "$temp_string" | cut -d" " -f $fcvcount ) + AFCTEMP[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP_PATH[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + done + + fan_string=$FCFANS + fcvcount=0 + zero=0 + for fcv in $FCFANS + do + fcvcount=$((fcvcount+1)) + AFCFAN[$fcvcount]=$( echo "$fan_string" | cut -d" " -f $fcvcount ) + AFCFAN_PATH[$fcvcount]=$( echo "${AFCFAN[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_PATH[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCFAN_TARGET[$fcvcount]}" | sed 's/$/_percentage/g') + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + done +} + +# Check that all referenced sysfs files exist +function CheckFiles +{ + local outdated=0 fcvcount tsen fan + if [ $outdated -eq 1 ] + then + echo >&2 + echo "At least one referenced file is missing. Either some required kernel" >&2 + echo "modules haven't been loaded, or your configuration file is outdated." >&2 + echo "In the latter case, you should run pwmconfig again." >&2 + fi + return $outdated +} + +#LoadConfig $1 +if [ -f "$1" ] +then + LoadConfig $1 +else + LoadConfig /etc/fancontrol +fi + +# Detect path to sensors +if [ ! -d $DIR ] +then + echo $0: 'No sensors found! (did you load the necessary modules?)' >&2 + exit 1 +fi +cd $DIR + +# Check for configuration change +if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] +then + echo "Configuration is too old, please run pwmconfig again" >&2 + exit 1 +fi +if [ "$DIR" = "/" -a -n "$DEVPATH" ] +then + echo "Unneeded DEVPATH with absolute device paths" >&2 + exit 1 +fi +CheckFiles || exit 1 + +if [ -f "$PIDFILE" ] +then + echo "File $PIDFILE exists, is fancontrol already running?" >&2 + exit 1 +fi +echo $$ > "$PIDFILE" + +# main function +function UpdateThermalSensors +{ + fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP_PATH[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + done +} + +function UpdateThermalLevel +{ + AFCTEMP_NUM=$((6-${AFCTEMP_LEVEL[$i]})) + AFCTEMP_UPPER_BUF=AFCTEMP_"$i"_UPPER["$AFCTEMP_NUM"] + AFCTEMP_LOWER_BUF=AFCTEMP_"$i"_LOWER["$AFCTEMP_NUM"] + + AFCTEMP_UPPER=${!AFCTEMP_UPPER_BUF} + AFCTEMP_LOWER=${!AFCTEMP_LOWER_BUF} + + + if (( ("${AFCTEMP[$i]}" <= "$AFCTEMP_UPPER") && ("${AFCTEMP[$i]}" >= "$AFCTEMP_LOWER") )) ; then + FLAG=2 + elif (( "${AFCTEMP[$i]}" > "$AFCTEMP_UPPER" )); then + AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} - 1)) + FLAG=1 + elif (( "${AFCTEMP[$i]}" < "$AFCTEMP_LOWER" )); then + AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} + 1)) + FLAG=1 + else + AFCTEMP_LEVEL[$i]=1 + FLAG=2 + fi +} + +function UpdateFanSpeeds +{ + #echo "num tmp lev F L H" + #Update level + for i in 1 2 3 4 5 + do + #echo "----------------------" + FLAG=0 + #FLAG=0 : initial flag + #FLAG=1 : update level + #FLAG=2 : final level + while [ $FLAG -ne 2 ] + do + UpdateThermalLevel + #echo " $i ${AFCTEMP[$i]} ${AFCTEMP_LEVEL[$i]} $FLAG $AFCTEMP_LOWER $AFCTEMP_UPPER " + done + done + + min=${AFCTEMP_LEVEL[0]} + for j in "${AFCTEMP_LEVEL[@]}"; do + (( j < min )) && min=$j + done + + if (($min == 1 || $min == 2)); then + FAN_PERCENTAGE=100 + elif (($min == 3)); then + FAN_PERCENTAGE=80 + elif (($min == 4)); then + FAN_PERCENTAGE=60 + elif (($min == 5)); then + FAN_PERCENTAGE=50 + elif (($min == 6)); then + FAN_PERCENTAGE=40 + else + FAN_PERCENTAGE=100 + fi + echo "The lowest level of thermal sensors: $min " + echo "Trying to set fan speed to $FAN_PERCENTAGE %" + #Set speed to fan1~fan10 + let fcvcount=0 + for fcv in $FCFANS + do + fcvcount=$(( fcvcount + 1 )) + echo $FAN_PERCENTAGE > ${AFCFAN_TARGET[$fcvcount]} + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + + if [ "${AFCFAN[$fcvcount]}" == 960 ] + then + AFCFAN[$fcvcount]=$zero + fi + echo "FAN fan$fcvcount = ${AFCFAN[$fcvcount]} (rpm)" + done + + FAN_ON_PSU_PERCENTAGE=$FAN_PERCENTAGE + #Set speed to PSU_FAN1 + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/1-0058/fan1_set_percentage' + echo "PSU fan1 =$( cat '/sys/bus/i2c/devices/1-0058/fan1_input' ) (rpm)" + #Set speed to PSU_FAN2 + echo "$FAN_ON_PSU_PERCENTAGE" > '/sys/bus/i2c/devices/2-0058/fan1_set_percentage' + echo "PSU fan2 =$( cat '/sys/bus/i2c/devices/2-0058/fan1_input' ) (rpm)" + + rm -f "$PIDFILE" +} + +# main loop calling the main function at specified intervals +AFCTEMP_LEVEL=(9 4 4 4 4 4) #inttial level +while true +do + UpdateThermalSensors + UpdateFanSpeeds + echo "Sleep $INTERVAL seconds ..." + echo + # Sleep while still handling signals + sleep $INTERVAL & + wait $! +done diff --git a/device/delta/x86_64-delta_agc032-r0/installer.conf b/device/delta/x86_64-delta_agc032-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/delta/x86_64-delta_agc032-r0/led_proc_init.soc b/device/delta/x86_64-delta_agc032-r0/led_proc_init.soc new file mode 100644 index 000000000000..5dcf85ea7956 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/led_proc_init.soc @@ -0,0 +1,5 @@ +led auto off +led stop +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/delta/x86_64-delta_agc032-r0/platform_env.conf b/device/delta/x86_64-delta_agc032-r0/platform_env.conf new file mode 100644 index 000000000000..283e1c0ce710 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/platform_env.conf @@ -0,0 +1 @@ +usemsi=1 diff --git a/device/delta/x86_64-delta_agc032-r0/plugins/eeprom.py b/device/delta/x86_64-delta_agc032-r0/plugins/eeprom.py new file mode 100644 index 000000000000..c252fd69f678 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/plugins/eeprom.py @@ -0,0 +1,12 @@ +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as 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/devices/pci0000:00/0000:00:1f.3/i2c-0/0-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_agc032-r0/plugins/psuutil.py b/device/delta/x86_64-delta_agc032-r0/plugins/psuutil.py new file mode 100644 index 000000000000..0cb47cad1bf9 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/{}-0058/" + self.psu_oper_status = "in1_input" + self.psu_oper_status2 = "in2_input" + self.psu_presence = "i2cget -y {} 0x50 0x00" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + if index is None: + return False + Base_bus_number = 0 + status = 0 + # index from 1, psu attribute bus from 40 + try: + with open(self.psu_path.format(index + Base_bus_number) + self.psu_oper_status, 'r') as power_status: + if int(power_status.read()) == 0: + return False + else: + with open(self.psu_path.format(index + Base_bus_number) + self.psu_oper_status2, 'r') as power_status2: + if int(power_status2.read()) == 0: + return False + else: + status = 1 + except IOError: + return False + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + Base_bus_number = 0 + status = 0 + try: + p = os.popen(self.psu_presence.format(index + Base_bus_number) + "> /dev/null 2>&1") + if p.readline() != None: + status = 1 + p.close() + except IOError: + return False + return status == 1 diff --git a/device/delta/x86_64-delta_agc032-r0/plugins/sfputil.py b/device/delta/x86_64-delta_agc032-r0/plugins/sfputil.py new file mode 100644 index 000000000000..e9b02c6c77c6 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/plugins/sfputil.py @@ -0,0 +1,242 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase + from sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_sfp.sff8436 import sff8436Dom +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 33 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 1 + + CPLD_SWITCH = 0 + + _port_to_eeprom_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 list(range(0, self.PORTS_IN_BLOCK)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + 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 < self.port_start or port_num > self.port_end: + return False + # Retrieve file path of presence + port = (str(port_num + 1)).zfill(2) + + # SWPLD2 for port 1~16, SWPLD3 for port 17~34 + if port_num < 16: + present_path = "SWPLD2/qsfp_p{}_modprs".format(port) + elif port_num < self.PORTS_IN_BLOCK: + present_path = "SWPLD3/qsfp_p{}_modprs".format(port) + else: + present_path = "SWPLD3/sfp_p{}_modprs".format(str(port_num - self.PORTS_IN_BLOCK)) + + try: + with open("/sys/devices/platform/delta-agc032-swpld.0/" + present_path, 'r') as present: + if int(present.readline()) == 0: + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num >= self.PORTS_IN_BLOCK: + return False + + # Retrieve file path of presence + port = (str(port_num + 1)).zfill(2) + + # SWPLD2 for port 1~16, SWPLD3 for port 17~32 + if port_num < 16: + lpmode_path = "SWPLD2/qsfp_p{}_lpmode".format(port) + else: + lpmode_path = "SWPLD3/qsfp_p{}_lpmode".format(port) + + try: + with open("/sys/devices/platform/delta-agc032-swpld.0/" + lpmode_path, 'r') as lpmode: + if int(lpmode.readline()) == 1: + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num >= self.PORTS_IN_BLOCK: + return False + + # Retrieve file path of presence + port = (str(port_num + 1)).zfill(2) + + # SWPLD2 for port 1~16, SWPLD3 for port 17~32 + if port_num < 16: + lpmode_path = "SWPLD2/qsfp_p{}_lpmode".format(port) + else: + lpmode_path = "SWPLD3/qsfp_p{}_lpmode".format(port) + + try: + file = open("/sys/devices/platform/delta-agc032-swpld.0/" + lpmode_path, 'r+') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + file.seek(0) + if lpmode is True: + # "1" for lpmode on + file.write('1') + else: + # "0" for lpmode off + file.write('0') + file.close() + + return True + + def reset(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num >= self.PORTS_IN_BLOCK: + return False + + # Retrieve file path of presence + port = (str(port_num + 1)).zfill(2) + + # SWPLD2 for port 1~16, SWPLD3 for port 17~32 + if port_num < 16: + reset_path = "SWPLD2/qsfp_p{}_rst".format(port) + else: + reset_path = "SWPLD3/qsfp_p{}_rst".format(port) + + try: + file = open("/sys/devices/platform/delta-agc032-swpld.0/" + reset_path, 'r+') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + file.seek(0) + file.write('0') + 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: + file = open("/sys/devices/platform/delta-agc032-swpld.0/" + reset_path, 'r+') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + file.seek(0) + file.write('1') + file.close() + + return True + + def get_eeprom_dict(self, port_num): + sfp_data = {} + + try: + file = open("/sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel", 'r+') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # Switch CPLD to FRONT-PORT EEPROM MUX + file.seek(0) + file.write('3') + file.close() + + eeprom_ifraw = self.get_eeprom_raw(port_num) + eeprom_domraw = self.get_eeprom_dom_raw(port_num) + + try: + file = open("/sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel", 'r+') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # Switch CPLD to FRONT-PORT EEPROM MUX + file.seek(0) + file.write('1') + file.close() + + if eeprom_ifraw is None: + return None + + if port_num in self.osfp_ports: + sfpi_obj = inf8628InterfaceId(eeprom_ifraw) + if sfpi_obj is not None: + sfp_data['interface'] = sfpi_obj.get_data_pretty() + return sfp_data + elif port_num in self.qsfp_ports: + sfpi_obj = sff8436InterfaceId(eeprom_ifraw) + if sfpi_obj is not None: + sfp_data['interface'] = sfpi_obj.get_data_pretty() + # For Qsfp's the dom data is part of eeprom_if_raw + # The first 128 bytes + + sfpd_obj = sff8436Dom(eeprom_ifraw) + if sfpd_obj is not None: + sfp_data['dom'] = sfpd_obj.get_data_pretty() + + return sfp_data + else: + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + if sfpi_obj is not None: + sfp_data['interface'] = sfpi_obj.get_data_pretty() + cal_type = sfpi_obj.get_calibration_type() + + if eeprom_domraw is not None: + sfpd_obj = sff8472Dom(eeprom_domraw, cal_type) + if sfpd_obj is not None: + sfp_data['dom'] = sfpd_obj.get_data_pretty() + + return sfp_data + + 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 diff --git a/device/delta/x86_64-delta_agc032-r0/pmon_daemon_control.json b/device/delta/x86_64-delta_agc032-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..d5784cc779f7 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/pmon_daemon_control.json @@ -0,0 +1,6 @@ +{ + "skip_thermalctld": true, + "skip_syseepromd": true, + "skip_fancontrol": true, + "skip_xcvrd": true +} diff --git a/device/delta/x86_64-delta_agc032-r0/sensors.conf b/device/delta/x86_64-delta_agc032-r0/sensors.conf new file mode 100644 index 000000000000..7df258da28c1 --- /dev/null +++ b/device/delta/x86_64-delta_agc032-r0/sensors.conf @@ -0,0 +1,47 @@ +# libsensors configuration file for DCS-7060CX-32S +# ------------------------------------------------ +# + +bus "i2c-4" "i2c-0-mux (chan_id 3)" +bus "i2c-5" "i2c-0-mux (chan_id 4)" + +chip "tmp75-i2c-4-4f" + label temp1 "Wind thermal sensor" + set temp1_max 65 + set temp1_max_hyst 60 +chip "tmp75-i2c-5-4d" + label temp1 "CPU below side thermal sensor" + set temp1_max 60 + set temp1_max_hyst 55 +chip "tmp75-i2c-5-49" + label temp1 "Surroundings thermal sensor1" + set temp1_max 65 + set temp1_max_hyst 60 +chip "tmp75-i2c-5-4a" + label temp1 "Surroundings thermal sensor2" + set temp1_max 65 + set temp1_max_hyst 60 +chip "tmp75-i2c-5-4b" + label temp1 "Surroundings thermal sensor3" + set temp1_max 65 + set temp1_max_hyst 60 +chip "tmp75-i2c-5-4d" + label temp1 "Surroundings thermal sensor4" + set temp1_max 65 + set temp1_max_hyst 60 + +chip "emc2305-i2c-4-4c" + label fan1 "FANTRAY 1 FRONT" + label fan2 "FANTRAY 2 REAR" + label fan3 "FANTRAY 3 FRONT" + label fan4 "FANTRAY 4 REAR" + label fan5 "FANTRAY 5 FRONT" +chip "emc2305-i2c-4-2d" + label fan1 "FANTRAY 1 REAR" + label fan2 "FANTRAY 2 FRONT" + label fan3 "FANTRAY 3 REAR" + label fan4 "FANTRAY 4 FRONT" + label fan5 "FANTRAY 5 REAR" +chip "emc2302-i2c-4-2e" + label fan1 "FANTRAY 1 FRONT" + label fan2 "FANTRAY 2 REAR" diff --git a/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/helix4-et-6248brb-48x1G+2x10G.config.bcm b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/helix4-et-6248brb-48x1G+2x10G.config.bcm new file mode 100644 index 000000000000..05d1c1e8820c --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/helix4-et-6248brb-48x1G+2x10G.config.bcm @@ -0,0 +1,158 @@ +# bcm56340 setting : +# Specifies the base port and phy index of a multi slice phy chip. +#phy_port_primary_and_offset_ value is 0xPPOO 0xPP is primary port number 0xOO is offset of the slice +# bcm56340 QG0 port setting +phy_port_primary_and_offset_1=0x0100 +phy_port_primary_and_offset_2=0x0101 +phy_port_primary_and_offset_3=0x0102 +phy_port_primary_and_offset_4=0x0103 +phy_port_primary_and_offset_5=0x0104 +phy_port_primary_and_offset_6=0x0105 +phy_port_primary_and_offset_7=0x0106 +phy_port_primary_and_offset_8=0x0107 + +# bcm56340 QG1 port setting +phy_port_primary_and_offset_9=0x0900 +phy_port_primary_and_offset_10=0x0901 +phy_port_primary_and_offset_11=0x0902 +phy_port_primary_and_offset_12=0x0903 +phy_port_primary_and_offset_13=0x0904 +phy_port_primary_and_offset_14=0x0905 +phy_port_primary_and_offset_15=0x0906 +phy_port_primary_and_offset_16=0x0907 + +# bcm56340 QG2 port setting +phy_port_primary_and_offset_17=0x1100 +phy_port_primary_and_offset_18=0x1101 +phy_port_primary_and_offset_19=0x1102 +phy_port_primary_and_offset_20=0x1103 +phy_port_primary_and_offset_21=0x1104 +phy_port_primary_and_offset_22=0x1105 +phy_port_primary_and_offset_23=0x1106 +phy_port_primary_and_offset_24=0x1107 + +# bcm56340 QG3 port setting +phy_port_primary_and_offset_25=0x1900 +phy_port_primary_and_offset_26=0x1901 +phy_port_primary_and_offset_27=0x1902 +phy_port_primary_and_offset_28=0x1903 +phy_port_primary_and_offset_29=0x1904 +phy_port_primary_and_offset_30=0x1905 +phy_port_primary_and_offset_31=0x1906 +phy_port_primary_and_offset_32=0x1907 + +# bcm56340 QG4 port setting +phy_port_primary_and_offset_33=0x2100 +phy_port_primary_and_offset_34=0x2101 +phy_port_primary_and_offset_35=0x2102 +phy_port_primary_and_offset_36=0x2103 +phy_port_primary_and_offset_37=0x2104 +phy_port_primary_and_offset_38=0x2105 +phy_port_primary_and_offset_39=0x2106 +phy_port_primary_and_offset_40=0x2107 + +# bcm56340 QG5 port setting +phy_port_primary_and_offset_41=0x2900 +phy_port_primary_and_offset_42=0x2901 +phy_port_primary_and_offset_43=0x2902 +phy_port_primary_and_offset_44=0x2903 +phy_port_primary_and_offset_45=0x2904 +phy_port_primary_and_offset_46=0x2905 +phy_port_primary_and_offset_47=0x2906 +phy_port_primary_and_offset_48=0x2907 + +# bcm56340 port group setting +bcm56340_4x10=1 +portgroup_0=1 +portgroup_1=1 +portgroup_2=1 +portgroup_3=1 +portgroup_4=1 +portgroup_5=1 +portgroup_6=1 +portgroup_7=1 +portgroup_8=1 +portgroup_9=1 +portgroup_10=1 +portgroup_11=1 +portgroup_12=1 + +# Port map +pbmp_xport_ge=0x0001FFFFFFFFFFFE +pbmp_xport_xe=0x3F000000000000 + +# phy addr setting for bcm54285-0 +port_phy_addr_1=0x1 +port_phy_addr_2=0x2 +port_phy_addr_3=0x3 +port_phy_addr_4=0x4 +port_phy_addr_5=0x5 +port_phy_addr_6=0x6 +port_phy_addr_7=0x7 +port_phy_addr_8=0x8 + +# phy addr setting for bcm54285-1 +port_phy_addr_9=0xa +port_phy_addr_10=0xb +port_phy_addr_11=0xc +port_phy_addr_12=0xd +port_phy_addr_13=0xe +port_phy_addr_14=0xf +port_phy_addr_15=0x10 +port_phy_addr_16=0x11 + +# phy addr setting for bcm54285-2 +port_phy_addr_17=0x13 +port_phy_addr_18=0x14 +port_phy_addr_19=0x15 +port_phy_addr_20=0x16 +port_phy_addr_21=0x17 +port_phy_addr_22=0x18 +port_phy_addr_23=0x19 +port_phy_addr_24=0x1a + +# phy addr setting for bcm54285-3 +port_phy_addr_25=0x21 +port_phy_addr_26=0x22 +port_phy_addr_27=0x23 +port_phy_addr_28=0x24 +port_phy_addr_29=0x25 +port_phy_addr_30=0x26 +port_phy_addr_31=0x27 +port_phy_addr_32=0x28 + +# phy addr setting for bcm54285-4 +port_phy_addr_33=0x2a +port_phy_addr_34=0x2b +port_phy_addr_35=0x2c +port_phy_addr_36=0x2d +port_phy_addr_37=0x2e +port_phy_addr_38=0x2f +port_phy_addr_39=0x30 +port_phy_addr_40=0x31 + +# phy addr setting for bcm54285-5 +port_phy_addr_41=0x33 +port_phy_addr_42=0x34 +port_phy_addr_43=0x35 +port_phy_addr_44=0x36 +port_phy_addr_45=0x37 +port_phy_addr_46=0x38 +port_phy_addr_47=0x39 +port_phy_addr_48=0x3a + +# phy addr setting for bcm84758 +port_phy_addr_50=0x40 +port_phy_addr_51=0x41 +port_phy_addr_52=0x42 +port_phy_addr_53=0x43 + +# Fiber prefer setting for bcm54285 +phy_automedium=1 +#phy_fiber_pref value is 1 +phy_ext_rom_boot=0 +phy_sgmii_autoneg_ge=1 + +os=unix +phy_null_port52=1 +phy_null_port53=1 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/port_config.ini b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/port_config.ini new file mode 100755 index 000000000000..3747a5c4989d --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/port_config.ini @@ -0,0 +1,51 @@ +# name lanes alias index +Ethernet0 1 1000 0 +Ethernet1 2 1000 1 +Ethernet2 3 1000 2 +Ethernet3 4 1000 3 +Ethernet4 5 1000 4 +Ethernet5 6 1000 5 +Ethernet6 7 1000 6 +Ethernet7 8 1000 7 +Ethernet8 9 1000 8 +Ethernet9 10 1000 9 +Ethernet10 11 1000 10 +Ethernet11 12 1000 11 +Ethernet12 13 1000 12 +Ethernet13 14 1000 13 +Ethernet14 15 1000 14 +Ethernet15 16 1000 15 +Ethernet16 17 1000 16 +Ethernet17 18 1000 17 +Ethernet18 19 1000 18 +Ethernet19 20 1000 19 +Ethernet20 21 1000 20 +Ethernet21 22 1000 21 +Ethernet22 23 1000 22 +Ethernet23 24 1000 23 +Ethernet24 25 1000 24 +Ethernet25 26 1000 25 +Ethernet26 27 1000 26 +Ethernet27 28 1000 27 +Ethernet28 29 1000 28 +Ethernet29 30 1000 29 +Ethernet30 31 1000 30 +Ethernet31 32 1000 31 +Ethernet32 33 1000 32 +Ethernet33 34 1000 33 +Ethernet34 35 1000 34 +Ethernet35 36 1000 35 +Ethernet36 37 1000 36 +Ethernet37 38 1000 37 +Ethernet38 39 1000 38 +Ethernet39 40 1000 39 +Ethernet40 41 1000 40 +Ethernet41 42 1000 41 +Ethernet42 43 1000 42 +Ethernet43 44 1000 43 +Ethernet44 45 1000 44 +Ethernet45 46 1000 45 +Ethernet46 47 1000 46 +Ethernet47 48 1000 47 +Ethernet48 54 10000 48 +Ethernet49 53 10000 49 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/sai.profile b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/sai.profile new file mode 100644 index 000000000000..20e067d8eda7 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/Delta-et-6248brb/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/bcm/helix4-et-6248brb-48x1G+2x10G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/default_sku b/device/delta/x86_64-delta_et-6248brb-r0/default_sku new file mode 100644 index 000000000000..ce1cdf6e4c69 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/default_sku @@ -0,0 +1 @@ +Delta-et-6248brb t1 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/fancontrol b/device/delta/x86_64-delta_et-6248brb-r0/fancontrol new file mode 100644 index 000000000000..0deef5b88ef8 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/fancontrol @@ -0,0 +1,12 @@ +INTERVAL=10 +DEVPATH=hwmon1=/sys/bus/i2c/devices +DEVNAME=hwmon1=adt7473 +FCTEMPS=hwmon1/0-0048/hwmon/hwmon*/temp1_input hwmon1/7-0049/hwmon/hwmon*/temp1_input hwmon1/8-004a/hwmon/hwmon*/temp1_input + +FCFANS=hwmon1/0-002e/fan1_input hwmon1/0-002e/fan2_input + +FCTARGETS=hwmon1/0-002e/pwm1 hwmon1/0-002e/pwm2 +MINTEMP=20 +MAXTEMP=60 +MINSTART=75 +MINSTOP=22 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/fancontrol.service b/device/delta/x86_64-delta_et-6248brb-r0/fancontrol.service new file mode 100755 index 000000000000..3864d6d99663 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/fancontrol.service @@ -0,0 +1,279 @@ +#!/bin/bash +# +# Simple script implementing a temperature dependent fan speed control +# Supported Linux kernel versions: 2.6.5 and later +# +# Version 0.70 +# +# Usage: fancontrol [CONFIGFILE] +# +# Dependencies: +# bash, egrep, sed, cut, sleep, readlink, lm_sensors :) +# +# Please send any questions, comments or success stories to +# marius.reiner@hdev.de +# Thanks! +# +# For configuration instructions and warnings please see fancontrol.txt, which +# can be found in the doc/ directory or at the website mentioned above. +# +# +# Copyright 2003 Marius Reiner +# Copyright (C) 2007-2009 Jean Delvare +# +# 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. +# +# 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 Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +# + +PIDFILE="/var/run/fancontrol.pid" + +#DEBUG=1 +MAX=255 + +function LoadConfig +{ + local fcvcount fcv + + echo "Loading configuration from $1 ..." + if [ ! -r "$1" ] + then + echo "Error: Can't read configuration file" >&2 + exit 1 + fi + + # grep configuration from file + INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'` + DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'` + DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'` + FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'` + MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'` + MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'` + MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'` + MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'` + HWMON=$( echo "$DEVPATH" | sed 's/=.*$//g') + FCDEVPATH=$( echo "$DEVPATH" | sed 's/^.*=//g') + FCMINTEMP=$MINTEMP + FCMAXTEMP=$MAXTEMP + FCMINSTART=$MINSTART + FCMINSTOP=$MINSTOP + AFCTEMP_1_LOWER=(00 39 36 41 46 55) + AFCTEMP_1_UPPER=(39 39 44 49 54 150) + AFCTEMP_2_LOWER=(00 61 65 69 73 82) + AFCTEMP_2_UPPER=(63 67 71 75 79 150) + AFCTEMP_3_LOWER=(00 51 55 59 63 71) + AFCTEMP_3_UPPER=(53 57 61 65 69 150) + + + FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'` + + FCTARGETS=`egrep '^FCTARGETS=.*$' $1 | sed -e 's/FCTARGETS=//g'` + + # Check whether all mandatory settings are set + if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]] + then + echo "Some mandatory settings missing, please check your config file!" >&2 + exit 1 + fi + if [ "$INTERVAL" -le 0 ] + then + echo "Error in configuration file:" >&2 + echo "INTERVAL must be at least 1" >&2 + exit 1 + fi + + # write settings to arrays for easier use and print them + echo + echo "Common settings:" + + temp_string=$FCTEMPS + + let fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( echo "$temp_string" | cut -d" " -f $fcvcount ) + AFCTEMP[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP_PATH[$fcvcount]=$( echo "${AFCTEMP[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + done + + fan_string=$FCFANS + fcvcount=0 + for fcv in $FCFANS + do + fcvcount=$((fcvcount+1)) + AFCFAN[$fcvcount]=$( echo "$fan_string" | cut -d" " -f $fcvcount ) + AFCFAN_PATH[$fcvcount]=$( echo "${AFCFAN[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + done + + target_string=$FCTARGETS + fcvcount=0 + for fcv in $FCTARGETS + do + fcvcount=$((fcvcount+1)) + AFCTARGET[$fcvcount]=$( echo "$target_string" | cut -d" " -f $fcvcount ) + AFCFAN_TARGET[$fcvcount]=$( echo "${AFCTARGET[$fcvcount]}" | sed 's/hwmon1/\/sys\/bus\/i2c\/devices/g' ) + done + +} + +# Check that all referenced sysfs files exist +function CheckFiles +{ + local outdated=0 fcvcount tsen fan + if [ $outdated -eq 1 ] + then + echo >&2 + echo "At least one referenced file is missing. Either some required kernel" >&2 + echo "modules haven't been loaded, or your configuration file is outdated." >&2 + echo "In the latter case, you should run pwmconfig again." >&2 + fi + return $outdated +} + +LoadConfig $1 + +# Detect path to sensors +if [ ! -d $DIR ] +then + echo $0: 'No sensors found! (did you load the necessary modules?)' >&2 + exit 1 +fi +cd $DIR + +# Check for configuration change +if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] +then + echo "Configuration is too old, please run pwmconfig again" >&2 + exit 1 +fi +if [ "$DIR" = "/" -a -n "$DEVPATH" ] +then + echo "Unneeded DEVPATH with absolute device paths" >&2 + exit 1 +fi +CheckFiles || exit 1 + +if [ -f "$PIDFILE" ] +then + echo "File $PIDFILE exists, is fancontrol already running?" >&2 + exit 1 +fi +echo $$ > "$PIDFILE" + +# main function +function UpdateThermalSensors +{ + fcvcount=0 + for fcv in $FCTEMPS + do + fcvcount=$((fcvcount+1)) + AFCTEMP[$fcvcount]=$( cat ${AFCTEMP_PATH[$fcvcount]} ) + AFCTEMP[$fcvcount]=$(( AFCTEMP[$fcvcount]/1000 )) + done +} + +function UpdateThermalLevel +{ + AFCTEMP_NUM=$((6-${AFCTEMP_LEVEL[$i]})) + AFCTEMP_UPPER_BUF=AFCTEMP_"$i"_UPPER["$AFCTEMP_NUM"] + AFCTEMP_LOWER_BUF=AFCTEMP_"$i"_LOWER["$AFCTEMP_NUM"] + + AFCTEMP_UPPER=${!AFCTEMP_UPPER_BUF} + AFCTEMP_LOWER=${!AFCTEMP_LOWER_BUF} + + + if (( ("${AFCTEMP[$i]}" <= "$AFCTEMP_UPPER") && ("${AFCTEMP[$i]}" >= "$AFCTEMP_LOWER") )) ; then + FLAG=2 + elif (( "${AFCTEMP[$i]}" > "$AFCTEMP_UPPER" )); then + AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} - 1)) + FLAG=1 + elif (( "${AFCTEMP[$i]}" < "$AFCTEMP_LOWER" )); then + AFCTEMP_LEVEL[$i]=$((${AFCTEMP_LEVEL[$i]} + 1)) + FLAG=1 + else + AFCTEMP_LEVEL[$i]=1 + FLAG=2 + fi +} + +function UpdateFanSpeeds +{ + #echo "num tmp lev F L H" + #Update level + for i in 1 2 3 + do + #echo "----------------------" + FLAG=0 + #FLAG=0 : initial flag + #FLAG=1 : update level + #FLAG=2 : final level + while [ $FLAG -ne 2 ] + do + UpdateThermalLevel + #echo " $i ${AFCTEMP[$i]} ${AFCTEMP_LEVEL[$i]} $FLAG $AFCTEMP_LOWER $AFCTEMP_UPPER " + done + done + + min=${AFCTEMP_LEVEL[0]} + for j in "${AFCTEMP_LEVEL[@]}"; do + (( j < min )) && min=$j + done + + if (($min == 1 || $min == 2)); then + FAN_PERCENTAGE=100 + elif (($min == 3)); then + FAN_PERCENTAGE=80 + elif (($min == 4)); then + FAN_PERCENTAGE=60 + elif (($min == 5)); then + FAN_PERCENTAGE=40 + elif (($min == 6)); then + FAN_PERCENTAGE=30 + else + FAN_PERCENTAGE=100 + fi + echo "The lowest level of thermal sensors: $min " + echo "Trying to set fan speed to $FAN_PERCENTAGE %" + #Set speed to fan1~fan10 + FAN_PERCENTAGE=`expr $FAN_PERCENTAGE \* 255 / 100` + let fcvcount=0 + for fcv in $FCFANS + do + fcvcount=$(( fcvcount + 1 )) + echo $FAN_PERCENTAGE > ${AFCFAN_TARGET[$fcvcount]} + AFCFAN[$fcvcount]=$( cat ${AFCFAN_PATH[$fcvcount]} ) + + echo "FAN fan$fcvcount = ${AFCFAN[$fcvcount]} (rpm)" + done + + rm -f "$PIDFILE" +} + +# main loop calling the main function at specified intervals +AFCTEMP_LEVEL=(9 4 4 4) #inttial level +while true +do + UpdateThermalSensors + UpdateFanSpeeds + echo "Sleep $INTERVAL seconds ..." + echo + # Sleep while still handling signals + sleep $INTERVAL & + wait $! +done diff --git a/device/delta/x86_64-delta_et-6248brb-r0/installer.conf b/device/delta/x86_64-delta_et-6248brb-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/delta/x86_64-delta_et-6248brb-r0/led_proc_init.soc b/device/delta/x86_64-delta_et-6248brb-r0/led_proc_init.soc new file mode 100644 index 000000000000..ebc8f238a332 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/led_proc_init.soc @@ -0,0 +1,46 @@ +#ET_6248BRB Port_Remap +# Vlan set and port enable +clear c +port ge en=1 +port hg en=1 + +# led0 port order remap +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=0 REMAP_PORT_1=1 REMAP_PORT_2=2 REMAP_PORT_3=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=4 REMAP_PORT_5=5 REMAP_PORT_6=6 REMAP_PORT_7=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=51 REMAP_PORT_9=50 REMAP_PORT_10=49 REMAP_PORT_11=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=46 REMAP_PORT_14=45 REMAP_PORT_15=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=43 REMAP_PORT_17=42 REMAP_PORT_18=41 REMAP_PORT_19=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=39 REMAP_PORT_21=38 REMAP_PORT_22=37 REMAP_PORT_23=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=35 REMAP_PORT_25=34 REMAP_PORT_26=33 REMAP_PORT_27=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=27 REMAP_PORT_33=26 REMAP_PORT_34=25 REMAP_PORT_35=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=19 REMAP_PORT_41=18 REMAP_PORT_42=17 REMAP_PORT_43=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=15 REMAP_PORT_45=14 REMAP_PORT_46=13 REMAP_PORT_47=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11 REMAP_PORT_49=10 REMAP_PORT_50=9 REMAP_PORT_51=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=7 REMAP_PORT_53=6 REMAP_PORT_54=5 REMAP_PORT_55=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=3 REMAP_PORT_57=2 REMAP_PORT_58=1 REMAP_PORT_59=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=60 REMAP_PORT_61=61 REMAP_PORT_62=62 REMAP_PORT_63=63 + +echo "ET_6248BRB LED Port Remap: Done." + +#ET_6248BRB_LED + +#-------------------------------------------------------------------------------------------------- +#LED Auto link/up + +led stop +led prog '\ + 02 00 60 E0 02 A0 60 E2 86 E6 02 00 60 E1 06 E0\ + D2 30 75 28 02 00 2E E0 32 08 97 71 1F 77 44 2E\ + E0 32 04 97 71 3C 77 40 02 00 2E E0 32 08 97 71\ + 33 77 44 2E E0 32 03 97 71 3C 77 40 02 02 77 44\ + 02 04 77 44 60 E3 2E E0 32 00 32 01 B7 97 02 00\ + 0E 00 12 E4 FE E1 50 12 E4 05 60 E5 12 E3 05 0A\ + 02 71 67 67 9A 77 69 67 86 12 E3 05 0A 01 71 74\ + 67 9A 77 76 67 86 06 E2 F2 01 60 E2 86 E0 06 E0\ + D2 34 74 0A 3A 68 06 E5 D2 00 70 96 16 E6 99 99\ + 1A 00 71 96 77 9A 32 0F 87 57 32 0E 87 57 00 00\ +' +led auto on +led start diff --git a/device/delta/x86_64-delta_et-6248brb-r0/plugins/eeprom.py b/device/delta/x86_64-delta_et-6248brb-r0/plugins/eeprom.py new file mode 100644 index 000000000000..3b4b15ee543b --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/plugins/eeprom.py @@ -0,0 +1,30 @@ +############################################################################# +# Mellanox +# +# 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 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 as 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/devices/pci0000:00/0000:00:13.0/i2c-1/1-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_et-6248brb-r0/plugins/psuutil.py b/device/delta/x86_64-delta_et-6248brb-r0/plugins/psuutil.py new file mode 100644 index 000000000000..c6ec180bfc06 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/plugins/psuutil.py @@ -0,0 +1,55 @@ +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/devices/platform/delta-et6248brb-gpio.0/PSU/psu{}_pg" + self.psu_oper_status = "in1_input" + self.psu_presence = "/sys/devices/platform/delta-et6248brb-gpio.0/PSU/psu{}_pres" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + if index is None: + return False + + try: + reg_file = open(self.psu_path.format(index)) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + if int(reg_file.readline()) == 1: + return True + + return False + + def get_psu_presence(self, index): + if index is None: + return False + + try: + reg_file = open(self.psu_presence.format(index)) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + if int(reg_file.readline()) == 0: + return True + + return False diff --git a/device/delta/x86_64-delta_et-6248brb-r0/plugins/sfputil.py b/device/delta/x86_64-delta_et-6248brb-r0/plugins/sfputil.py new file mode 100644 index 000000000000..c8d30d3beeeb --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/plugins/sfputil.py @@ -0,0 +1,96 @@ +# sfputil.py +# +# 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 = 48 + PORT_END = 49 + PORTS_IN_BLOCK = 1 + + EEPROM_OFFSET = 44 + + _port_to_eeprom_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 list(range(0)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + if x >= self.port_start and x <= self.port_end: + self._port_to_eeprom_mapping[x] = eeprom_path.format(x - self.EEPROM_OFFSET) + else: + self._port_to_eeprom_mapping[x] = eeprom_path.format(x - x) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + presence_path = "/sys/devices/platform/delta-et6248brb-gpio.0/SFP/sfp_mod_p{}" + + try: + reg_file = open(presence_path.format(port_num - 47)) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + if int(reg_file.readline()) == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def get_transceiver_change_event(self): + """ + TODO: This function need to be implemented + when decide to support monitoring SFP(Xcvrd) + on this platform. + """ + raise NotImplementedError diff --git a/device/delta/x86_64-delta_et-6248brb-r0/sensors.conf b/device/delta/x86_64-delta_et-6248brb-r0/sensors.conf new file mode 100644 index 000000000000..d5da19ffecd0 --- /dev/null +++ b/device/delta/x86_64-delta_et-6248brb-r0/sensors.conf @@ -0,0 +1,13 @@ +# libsensors configuration file for et-6248brb +# ------------------------------------------------ + +chip "tmp75-i2c-0-48" + label temp1 "0-0048 thermal sensor" +chip "tmp75-i2c-7-49" + label temp1 "7-0048 thermal sensor" +chip "tmp75-i2c-8-4a" + label temp1 "8-004a thermal sensor" + +chip "adt7473-i2c-0-2e" + label fan1 "FANTRAY 1" + label fan2 "FANTRAY 2" \ No newline at end of file diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/buffers.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/buffers.json.j2 new file mode 100644 index 000000000000..4fca9cbcd156 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 32 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/config_32x400G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/config_32x400G_Delta-et-c032if.yaml new file mode 100755 index 000000000000..2ba23d2a5a67 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/config_32x400G_Delta-et-c032if.yaml @@ -0,0 +1,429 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_A" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KPFEC" + id: "249" + lanes: "0:8" + serdes_group: "31" + speed: "400G" + sysport: "249" + type: "eth" + - fec: "KPFEC" + id: "241" + lanes: "0:8" + serdes_group: "30" + speed: "400G" + sysport: "241" + type: "eth" + - fec: "KPFEC" + id: "233" + lanes: "0:8" + serdes_group: "29" + speed: "400G" + sysport: "233" + type: "eth" + - fec: "KPFEC" + id: "225" + lanes: "0:8" + serdes_group: "28" + speed: "400G" + sysport: "225" + type: "eth" + - fec: "KPFEC" + id: "217" + lanes: "0:8" + serdes_group: "27" + speed: "400G" + sysport: "217" + type: "eth" + - fec: "KPFEC" + id: "209" + lanes: "0:8" + serdes_group: "26" + speed: "400G" + sysport: "209" + type: "eth" + - fec: "KPFEC" + id: "201" + lanes: "0:8" + serdes_group: "25" + speed: "400G" + sysport: "201" + type: "eth" + - fec: "KPFEC" + id: "193" + lanes: "0:8" + serdes_group: "24" + speed: "400G" + sysport: "193" + type: "eth" + - fec: "KPFEC" + id: "185" + lanes: "0:8" + serdes_group: "23" + speed: "400G" + sysport: "185" + type: "eth" + - fec: "KPFEC" + id: "177" + lanes: "0:8" + serdes_group: "22" + speed: "400G" + sysport: "177" + type: "eth" + - fec: "KPFEC" + id: "169" + lanes: "0:8" + serdes_group: "21" + speed: "400G" + sysport: "169" + type: "eth" + - fec: "KPFEC" + id: "161" + lanes: "0:8" + serdes_group: "20" + speed: "400G" + sysport: "161" + type: "eth" + - fec: "KPFEC" + id: "153" + lanes: "0:8" + serdes_group: "19" + speed: "400G" + sysport: "153" + type: "eth" + - fec: "KPFEC" + id: "145" + lanes: "0:8" + serdes_group: "18" + speed: "400G" + sysport: "145" + type: "eth" + - fec: "KPFEC" + id: "137" + lanes: "0:8" + serdes_group: "17" + speed: "400G" + sysport: "137" + type: "eth" + - fec: "KPFEC" + id: "129" + lanes: "0:8" + serdes_group: "16" + speed: "400G" + sysport: "129" + type: "eth" + - fec: "KPFEC" + id: "121" + lanes: "0:8" + serdes_group: "15" + speed: "400G" + sysport: "121" + type: "eth" + - fec: "KPFEC" + id: "113" + lanes: "0:8" + serdes_group: "14" + speed: "400G" + sysport: "113" + type: "eth" + - fec: "KPFEC" + id: "97" + lanes: "0:8" + serdes_group: "12" + speed: "400G" + sysport: "97" + type: "eth" + - fec: "KPFEC" + id: "105" + lanes: "0:8" + serdes_group: "13" + speed: "400G" + sysport: "105" + type: "eth" + - fec: "KPFEC" + id: "81" + lanes: "0:8" + serdes_group: "10" + speed: "400G" + sysport: "81" + type: "eth" + - fec: "KPFEC" + id: "89" + lanes: "0:8" + serdes_group: "11" + speed: "400G" + sysport: "89" + type: "eth" + - fec: "KPFEC" + id: "65" + lanes: "0:8" + serdes_group: "8" + speed: "400G" + sysport: "65" + type: "eth" + - fec: "KPFEC" + id: "73" + lanes: "0:8" + serdes_group: "9" + speed: "400G" + sysport: "73" + type: "eth" + - fec: "KPFEC" + id: "49" + lanes: "0:8" + serdes_group: "6" + speed: "400G" + sysport: "49" + type: "eth" + - fec: "KPFEC" + id: "57" + lanes: "0:8" + serdes_group: "7" + speed: "400G" + sysport: "57" + type: "eth" + - fec: "KPFEC" + id: "33" + lanes: "0:8" + serdes_group: "4" + speed: "400G" + sysport: "33" + type: "eth" + - fec: "KPFEC" + id: "41" + lanes: "0:8" + serdes_group: "5" + speed: "400G" + sysport: "41" + type: "eth" + - fec: "KPFEC" + id: "17" + lanes: "0:8" + serdes_group: "2" + speed: "400G" + sysport: "17" + type: "eth" + - fec: "KPFEC" + id: "25" + lanes: "0:8" + serdes_group: "3" + speed: "400G" + sysport: "25" + type: "eth" + - fec: "KPFEC" + id: "1" + lanes: "0:8" + serdes_group: "0" + speed: "400G" + sysport: "1" + type: "eth" + - fec: "KPFEC" + id: "9" + lanes: "0:8" + serdes_group: "1" + speed: "400G" + sysport: "9" + type: "eth" + - fec: "NONE" + id: "257" + lanes: "0:1" + serdes_group: "32" + speed: "10G" + sysport: "257" + type: "mgmt 0" + - fec: "NONE" + id: "258" + lanes: "1:1" + serdes_group: "32" + speed: "10G" + sysport: "258" + type: "mgmt 1" + isg: + - id: "0" + tx_polarity: "01010101" + rx_polarity: "01100000" + lane_swap: "23641075" + - id: "1" + tx_polarity: "10110000" + rx_polarity: "11111111" + lane_swap: "64317520" + - id: "2" + tx_polarity: "00000000" + rx_polarity: "00000011" + lane_swap: "63147520" + - id: "3" + tx_polarity: "01101000" + rx_polarity: "00001110" + lane_swap: "31572046" + - id: "4" + tx_polarity: "00111000" + rx_polarity: "00001000" + lane_swap: "46105732" + - id: "5" + tx_polarity: "10111111" + rx_polarity: "11101000" + lane_swap: "27153604" + - id: "6" + tx_polarity: "01101110" + rx_polarity: "00001101" + lane_swap: "46503721" + - id: "7" + tx_polarity: "01000100" + rx_polarity: "10000101" + lane_swap: "03671245" + - id: "8" + tx_polarity: "01110101" + rx_polarity: "00010000" + lane_swap: "12640375" + - id: "9" + tx_polarity: "01011100" + rx_polarity: "11001111" + lane_swap: "02561347" + - id: "10" + tx_polarity: "01110110" + rx_polarity: "11000000" + lane_swap: "12740365" + - id: "11" + tx_polarity: "00111000" + rx_polarity: "00010111" + lane_swap: "01572436" + - id: "12" + tx_polarity: "00001111" + rx_polarity: "10111001" + lane_swap: "54320176" + - id: "13" + tx_polarity: "10011101" + rx_polarity: "00111011" + lane_swap: "26153704" + - id: "14" + tx_polarity: "00110000" + rx_polarity: "11010000" + lane_swap: "37452601" + - id: "15" + tx_polarity: "11100010" + rx_polarity: "01110011" + lane_swap: "51370462" + - id: "16" + tx_polarity: "10111010" + rx_polarity: "11010011" + lane_swap: "36152704" + - id: "17" + tx_polarity: "01011101" + rx_polarity: "00110001" + lane_swap: "45621073" + - id: "18" + tx_polarity: "11011111" + rx_polarity: "11001011" + lane_swap: "26143705" + - id: "19" + tx_polarity: "00100110" + rx_polarity: "00001001" + lane_swap: "42730165" + - id: "20" + tx_polarity: "10011011" + rx_polarity: "01101101" + lane_swap: "54217603" + - id: "21" + tx_polarity: "00101110" + rx_polarity: "10111111" + lane_swap: "26031745" + - id: "22" + tx_polarity: "01001110" + rx_polarity: "00111001" + lane_swap: "36024715" + - id: "23" + tx_polarity: "10101101" + rx_polarity: "01010011" + lane_swap: "45621370" + - id: "24" + tx_polarity: "11001110" + rx_polarity: "00011111" + lane_swap: "65234701" + - id: "25" + tx_polarity: "01110001" + rx_polarity: "01010111" + lane_swap: "37601452" + - id: "26" + tx_polarity: "01000100" + rx_polarity: "00001111" + lane_swap: "65034721" + - id: "27" + tx_polarity: "10111101" + rx_polarity: "11000101" + lane_swap: "34501672" + - id: "28" + tx_polarity: "01111000" + rx_polarity: "01110110" + lane_swap: "43061275" + - id: "29" + tx_polarity: "11110111" + rx_polarity: "11100111" + lane_swap: "57304621" + - id: "30" + tx_polarity: "10000100" + rx_polarity: "00101111" + lane_swap: "47125603" + - id: "31" + tx_polarity: "11111111" + rx_polarity: "11100010" + lane_swap: "13460275" + - id: "32" + tx_polarity: "00000000" + rx_polarity: "00000000" + lane_swap: "01234567" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/inno.config.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/inno.config.yaml new file mode 100755 index 000000000000..360b5af8e602 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_32x400G_Delta-et-c032if.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_A" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/innovium.77700_A b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/innovium.77700_A new file mode 100644 index 000000000000..84aa41983606 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/innovium.77700_A @@ -0,0 +1,59 @@ +sku: innovium.77700_A + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 6, 5, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 8:0 + ib: 1 + pic_id: 5 + + isg 31: + mode: 8:0 + ib: 0 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/port_config.ini b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/port_config.ini new file mode 100755 index 000000000000..360e363f485b --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/port_config.ini @@ -0,0 +1,35 @@ +# name lanes speed index mtu fec +Ethernet0 249,250,251,252 400000 0 9126 rs +Ethernet8 241,242,243,244 400000 1 9126 rs +Ethernet16 233,234,235,236 400000 2 9126 rs +Ethernet24 225,226,227,228 400000 3 9126 rs +Ethernet32 217,218,219,220 400000 4 9126 rs +Ethernet40 209,210,211,212 400000 5 9126 rs +Ethernet48 201,202,203,204 400000 6 9126 rs +Ethernet56 193,194,195,196 400000 7 9126 rs +Ethernet64 185,186,187,188 400000 8 9126 rs +Ethernet72 177,178,179,180 400000 9 9126 rs +Ethernet80 169,170,171,172 400000 10 9126 rs +Ethernet88 161,162,163,164 400000 11 9126 rs +Ethernet96 153,154,155,156 400000 12 9126 rs +Ethernet104 145,146,147,148 400000 13 9126 rs +Ethernet112 137,138,139,140 400000 14 9126 rs +Ethernet120 129,130,131,132 400000 15 9126 rs +Ethernet128 121,122,123,124 400000 16 9126 rs +Ethernet136 113,114,115,116 400000 17 9126 rs +Ethernet144 97,98,99,100 400000 18 9126 rs +Ethernet152 105,106,107,108 400000 19 9126 rs +Ethernet160 81,82,83,84 400000 20 9126 rs +Ethernet168 89,90,91,92 400000 21 9126 rs +Ethernet176 65,66,67,68 400000 22 9126 rs +Ethernet184 73,74,75,76 400000 23 9126 rs +Ethernet192 49,50,51,52 400000 24 9126 rs +Ethernet200 57,58,59,60 400000 25 9126 rs +Ethernet208 33,34,35,36 400000 26 9126 rs +Ethernet216 41,42,43,44 400000 27 9126 rs +Ethernet224 17,18,19,20 400000 28 9126 rs +Ethernet232 25,26,27,28 400000 29 9126 rs +Ethernet240 1,2,3,4 400000 30 9126 rs +Ethernet248 9,10,11,12 400000 31 9126 rs +Ethernet256 257 10000 32 9126 none +Ethernet257 258 10000 33 9126 none diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/qos.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/qos.json.j2 new file mode 100755 index 000000000000..6c734d46ff2f --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 32 -%} +{# 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*4)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/sai.profile b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/buffers.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/buffers.json.j2 new file mode 100644 index 000000000000..9529fbf52fb5 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 128 -%} + +{# 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*2)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/config_128x100G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/config_128x100G_Delta-et-c032if.yaml new file mode 100755 index 000000000000..ad50fd04c2a0 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/config_128x100G_Delta-et-c032if.yaml @@ -0,0 +1,1102 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_B" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KPFEC" + id: "249" + lanes: "0:2" + serdes_group: "31" + speed: "100G" + sysport: "249" + type: "eth" + - fec: "KPFEC" + id: "251" + lanes: "2:2" + serdes_group: "31" + speed: "100G" + sysport: "251" + type: "eth" + - fec: "KPFEC" + id: "253" + lanes: "4:2" + serdes_group: "31" + speed: "100G" + sysport: "253" + type: "eth" + - fec: "KPFEC" + id: "255" + lanes: "6:2" + serdes_group: "31" + speed: "100G" + sysport: "255" + type: "eth" + - fec: "KPFEC" + id: "241" + lanes: "0:2" + serdes_group: "30" + speed: "100G" + sysport: "241" + type: "eth" + - fec: "KPFEC" + id: "243" + lanes: "2:2" + serdes_group: "30" + speed: "100G" + sysport: "243" + type: "eth" + - fec: "KPFEC" + id: "245" + lanes: "4:2" + serdes_group: "30" + speed: "100G" + sysport: "245" + type: "eth" + - fec: "KPFEC" + id: "247" + lanes: "6:2" + serdes_group: "30" + speed: "100G" + sysport: "247" + type: "eth" + - fec: "KPFEC" + id: "233" + lanes: "0:2" + serdes_group: "29" + speed: "100G" + sysport: "233" + type: "eth" + - fec: "KPFEC" + id: "235" + lanes: "2:2" + serdes_group: "29" + speed: "100G" + sysport: "235" + type: "eth" + - fec: "KPFEC" + id: "237" + lanes: "4:2" + serdes_group: "29" + speed: "100G" + sysport: "237" + type: "eth" + - fec: "KPFEC" + id: "239" + lanes: "6:2" + serdes_group: "29" + speed: "100G" + sysport: "239" + type: "eth" + - fec: "KPFEC" + id: "225" + lanes: "0:2" + serdes_group: "28" + speed: "100G" + sysport: "225" + type: "eth" + - fec: "KPFEC" + id: "227" + lanes: "2:2" + serdes_group: "28" + speed: "100G" + sysport: "227" + type: "eth" + - fec: "KPFEC" + id: "229" + lanes: "4:2" + serdes_group: "28" + speed: "100G" + sysport: "229" + type: "eth" + - fec: "KPFEC" + id: "231" + lanes: "6:2" + serdes_group: "28" + speed: "100G" + sysport: "231" + type: "eth" + - fec: "KPFEC" + id: "217" + lanes: "0:2" + serdes_group: "27" + speed: "100G" + sysport: "217" + type: "eth" + - fec: "KPFEC" + id: "219" + lanes: "2:2" + serdes_group: "27" + speed: "100G" + sysport: "219" + type: "eth" + - fec: "KPFEC" + id: "221" + lanes: "4:2" + serdes_group: "27" + speed: "100G" + sysport: "221" + type: "eth" + - fec: "KPFEC" + id: "223" + lanes: "6:2" + serdes_group: "27" + speed: "100G" + sysport: "223" + type: "eth" + - fec: "KPFEC" + id: "209" + lanes: "0:2" + serdes_group: "26" + speed: "100G" + sysport: "209" + type: "eth" + - fec: "KPFEC" + id: "211" + lanes: "2:2" + serdes_group: "26" + speed: "100G" + sysport: "211" + type: "eth" + - fec: "KPFEC" + id: "213" + lanes: "4:2" + serdes_group: "26" + speed: "100G" + sysport: "213" + type: "eth" + - fec: "KPFEC" + id: "215" + lanes: "6:2" + serdes_group: "26" + speed: "100G" + sysport: "215" + type: "eth" + - fec: "KPFEC" + id: "201" + lanes: "0:2" + serdes_group: "25" + speed: "100G" + sysport: "201" + type: "eth" + - fec: "KPFEC" + id: "203" + lanes: "2:2" + serdes_group: "25" + speed: "100G" + sysport: "203" + type: "eth" + - fec: "KPFEC" + id: "205" + lanes: "4:2" + serdes_group: "25" + speed: "100G" + sysport: "205" + type: "eth" + - fec: "KPFEC" + id: "207" + lanes: "6:2" + serdes_group: "25" + speed: "100G" + sysport: "207" + type: "eth" + - fec: "KPFEC" + id: "193" + lanes: "0:2" + serdes_group: "24" + speed: "100G" + sysport: "193" + type: "eth" + - fec: "KPFEC" + id: "195" + lanes: "2:2" + serdes_group: "24" + speed: "100G" + sysport: "195" + type: "eth" + - fec: "KPFEC" + id: "197" + lanes: "4:2" + serdes_group: "24" + speed: "100G" + sysport: "197" + type: "eth" + - fec: "KPFEC" + id: "199" + lanes: "6:2" + serdes_group: "24" + speed: "100G" + sysport: "199" + type: "eth" + - fec: "KPFEC" + id: "185" + lanes: "0:2" + serdes_group: "23" + speed: "100G" + sysport: "185" + type: "eth" + - fec: "KPFEC" + id: "187" + lanes: "2:2" + serdes_group: "23" + speed: "100G" + sysport: "187" + type: "eth" + - fec: "KPFEC" + id: "189" + lanes: "4:2" + serdes_group: "23" + speed: "100G" + sysport: "189" + type: "eth" + - fec: "KPFEC" + id: "191" + lanes: "6:2" + serdes_group: "23" + speed: "100G" + sysport: "191" + type: "eth" + - fec: "KPFEC" + id: "177" + lanes: "0:2" + serdes_group: "22" + speed: "100G" + sysport: "177" + type: "eth" + - fec: "KPFEC" + id: "179" + lanes: "2:2" + serdes_group: "22" + speed: "100G" + sysport: "179" + type: "eth" + - fec: "KPFEC" + id: "181" + lanes: "4:2" + serdes_group: "22" + speed: "100G" + sysport: "181" + type: "eth" + - fec: "KPFEC" + id: "183" + lanes: "6:2" + serdes_group: "22" + speed: "100G" + sysport: "183" + type: "eth" + - fec: "KPFEC" + id: "169" + lanes: "0:2" + serdes_group: "21" + speed: "100G" + sysport: "169" + type: "eth" + - fec: "KPFEC" + id: "171" + lanes: "2:2" + serdes_group: "21" + speed: "100G" + sysport: "171" + type: "eth" + - fec: "KPFEC" + id: "173" + lanes: "4:2" + serdes_group: "21" + speed: "100G" + sysport: "173" + type: "eth" + - fec: "KPFEC" + id: "175" + lanes: "6:2" + serdes_group: "21" + speed: "100G" + sysport: "175" + type: "eth" + - fec: "KPFEC" + id: "161" + lanes: "0:2" + serdes_group: "20" + speed: "100G" + sysport: "161" + type: "eth" + - fec: "KPFEC" + id: "163" + lanes: "2:2" + serdes_group: "20" + speed: "100G" + sysport: "163" + type: "eth" + - fec: "KPFEC" + id: "165" + lanes: "4:2" + serdes_group: "20" + speed: "100G" + sysport: "165" + type: "eth" + - fec: "KPFEC" + id: "167" + lanes: "6:2" + serdes_group: "20" + speed: "100G" + sysport: "167" + type: "eth" + - fec: "KPFEC" + id: "153" + lanes: "0:2" + serdes_group: "19" + speed: "100G" + sysport: "153" + type: "eth" + - fec: "KPFEC" + id: "155" + lanes: "2:2" + serdes_group: "19" + speed: "100G" + sysport: "155" + type: "eth" + - fec: "KPFEC" + id: "157" + lanes: "4:2" + serdes_group: "19" + speed: "100G" + sysport: "157" + type: "eth" + - fec: "KPFEC" + id: "159" + lanes: "6:2" + serdes_group: "19" + speed: "100G" + sysport: "159" + type: "eth" + - fec: "KPFEC" + id: "145" + lanes: "0:2" + serdes_group: "18" + speed: "100G" + sysport: "145" + type: "eth" + - fec: "KPFEC" + id: "147" + lanes: "2:2" + serdes_group: "18" + speed: "100G" + sysport: "147" + type: "eth" + - fec: "KPFEC" + id: "149" + lanes: "4:2" + serdes_group: "18" + speed: "100G" + sysport: "149" + type: "eth" + - fec: "KPFEC" + id: "151" + lanes: "6:2" + serdes_group: "18" + speed: "100G" + sysport: "151" + type: "eth" + - fec: "KPFEC" + id: "137" + lanes: "0:2" + serdes_group: "17" + speed: "100G" + sysport: "137" + type: "eth" + - fec: "KPFEC" + id: "139" + lanes: "2:2" + serdes_group: "17" + speed: "100G" + sysport: "139" + type: "eth" + - fec: "KPFEC" + id: "141" + lanes: "4:2" + serdes_group: "17" + speed: "100G" + sysport: "141" + type: "eth" + - fec: "KPFEC" + id: "143" + lanes: "6:2" + serdes_group: "17" + speed: "100G" + sysport: "143" + type: "eth" + - fec: "KPFEC" + id: "129" + lanes: "0:2" + serdes_group: "16" + speed: "100G" + sysport: "129" + type: "eth" + - fec: "KPFEC" + id: "131" + lanes: "2:2" + serdes_group: "16" + speed: "100G" + sysport: "131" + type: "eth" + - fec: "KPFEC" + id: "133" + lanes: "4:2" + serdes_group: "16" + speed: "100G" + sysport: "133" + type: "eth" + - fec: "KPFEC" + id: "135" + lanes: "6:2" + serdes_group: "16" + speed: "100G" + sysport: "135" + type: "eth" + - fec: "KPFEC" + id: "121" + lanes: "0:2" + serdes_group: "15" + speed: "100G" + sysport: "121" + type: "eth" + - fec: "KPFEC" + id: "123" + lanes: "2:2" + serdes_group: "15" + speed: "100G" + sysport: "123" + type: "eth" + - fec: "KPFEC" + id: "125" + lanes: "4:2" + serdes_group: "15" + speed: "100G" + sysport: "125" + type: "eth" + - fec: "KPFEC" + id: "127" + lanes: "6:2" + serdes_group: "15" + speed: "100G" + sysport: "127" + type: "eth" + - fec: "KPFEC" + id: "113" + lanes: "0:2" + serdes_group: "14" + speed: "100G" + sysport: "113" + type: "eth" + - fec: "KPFEC" + id: "115" + lanes: "2:2" + serdes_group: "14" + speed: "100G" + sysport: "115" + type: "eth" + - fec: "KPFEC" + id: "117" + lanes: "4:2" + serdes_group: "14" + speed: "100G" + sysport: "117" + type: "eth" + - fec: "KPFEC" + id: "119" + lanes: "6:2" + serdes_group: "14" + speed: "100G" + sysport: "119" + type: "eth" + - fec: "KPFEC" + id: "97" + lanes: "0:2" + serdes_group: "12" + speed: "100G" + sysport: "97" + type: "eth" + - fec: "KPFEC" + id: "99" + lanes: "2:2" + serdes_group: "12" + speed: "100G" + sysport: "99" + type: "eth" + - fec: "KPFEC" + id: "101" + lanes: "4:2" + serdes_group: "12" + speed: "100G" + sysport: "101" + type: "eth" + - fec: "KPFEC" + id: "103" + lanes: "6:2" + serdes_group: "12" + speed: "100G" + sysport: "103" + type: "eth" + - fec: "KPFEC" + id: "105" + lanes: "0:2" + serdes_group: "13" + speed: "100G" + sysport: "105" + type: "eth" + - fec: "KPFEC" + id: "107" + lanes: "2:2" + serdes_group: "13" + speed: "100G" + sysport: "107" + type: "eth" + - fec: "KPFEC" + id: "109" + lanes: "4:2" + serdes_group: "13" + speed: "100G" + sysport: "109" + type: "eth" + - fec: "KPFEC" + id: "111" + lanes: "6:2" + serdes_group: "13" + speed: "100G" + sysport: "111" + type: "eth" + - fec: "KPFEC" + id: "81" + lanes: "0:2" + serdes_group: "10" + speed: "100G" + sysport: "81" + type: "eth" + - fec: "KPFEC" + id: "83" + lanes: "2:2" + serdes_group: "10" + speed: "100G" + sysport: "83" + type: "eth" + - fec: "KPFEC" + id: "85" + lanes: "4:2" + serdes_group: "10" + speed: "100G" + sysport: "85" + type: "eth" + - fec: "KPFEC" + id: "87" + lanes: "6:2" + serdes_group: "10" + speed: "100G" + sysport: "87" + type: "eth" + - fec: "KPFEC" + id: "89" + lanes: "0:2" + serdes_group: "11" + speed: "100G" + sysport: "89" + type: "eth" + - fec: "KPFEC" + id: "91" + lanes: "2:2" + serdes_group: "11" + speed: "100G" + sysport: "91" + type: "eth" + - fec: "KPFEC" + id: "93" + lanes: "4:2" + serdes_group: "11" + speed: "100G" + sysport: "93" + type: "eth" + - fec: "KPFEC" + id: "95" + lanes: "6:2" + serdes_group: "11" + speed: "100G" + sysport: "95" + type: "eth" + - fec: "KPFEC" + id: "65" + lanes: "0:2" + serdes_group: "8" + speed: "100G" + sysport: "65" + type: "eth" + - fec: "KPFEC" + id: "67" + lanes: "2:2" + serdes_group: "8" + speed: "100G" + sysport: "67" + type: "eth" + - fec: "KPFEC" + id: "69" + lanes: "4:2" + serdes_group: "8" + speed: "100G" + sysport: "69" + type: "eth" + - fec: "KPFEC" + id: "71" + lanes: "6:2" + serdes_group: "8" + speed: "100G" + sysport: "71" + type: "eth" + - fec: "KPFEC" + id: "73" + lanes: "0:2" + serdes_group: "9" + speed: "100G" + sysport: "73" + type: "eth" + - fec: "KPFEC" + id: "75" + lanes: "2:2" + serdes_group: "9" + speed: "100G" + sysport: "75" + type: "eth" + - fec: "KPFEC" + id: "77" + lanes: "4:2" + serdes_group: "9" + speed: "100G" + sysport: "77" + type: "eth" + - fec: "KPFEC" + id: "79" + lanes: "6:2" + serdes_group: "9" + speed: "100G" + sysport: "79" + type: "eth" + - fec: "KPFEC" + id: "49" + lanes: "0:2" + serdes_group: "6" + speed: "100G" + sysport: "49" + type: "eth" + - fec: "KPFEC" + id: "51" + lanes: "2:2" + serdes_group: "6" + speed: "100G" + sysport: "51" + type: "eth" + - fec: "KPFEC" + id: "53" + lanes: "4:2" + serdes_group: "6" + speed: "100G" + sysport: "53" + type: "eth" + - fec: "KPFEC" + id: "55" + lanes: "6:2" + serdes_group: "6" + speed: "100G" + sysport: "55" + type: "eth" + - fec: "KPFEC" + id: "57" + lanes: "0:2" + serdes_group: "7" + speed: "100G" + sysport: "57" + type: "eth" + - fec: "KPFEC" + id: "59" + lanes: "2:2" + serdes_group: "7" + speed: "100G" + sysport: "59" + type: "eth" + - fec: "KPFEC" + id: "61" + lanes: "4:2" + serdes_group: "7" + speed: "100G" + sysport: "61" + type: "eth" + - fec: "KPFEC" + id: "63" + lanes: "6:2" + serdes_group: "7" + speed: "100G" + sysport: "63" + type: "eth" + - fec: "KPFEC" + id: "33" + lanes: "0:2" + serdes_group: "4" + speed: "100G" + sysport: "33" + type: "eth" + - fec: "KPFEC" + id: "35" + lanes: "2:2" + serdes_group: "4" + speed: "100G" + sysport: "35" + type: "eth" + - fec: "KPFEC" + id: "37" + lanes: "4:2" + serdes_group: "4" + speed: "100G" + sysport: "37" + type: "eth" + - fec: "KPFEC" + id: "39" + lanes: "6:2" + serdes_group: "4" + speed: "100G" + sysport: "39" + type: "eth" + - fec: "KPFEC" + id: "41" + lanes: "0:2" + serdes_group: "5" + speed: "100G" + sysport: "41" + type: "eth" + - fec: "KPFEC" + id: "43" + lanes: "2:2" + serdes_group: "5" + speed: "100G" + sysport: "43" + type: "eth" + - fec: "KPFEC" + id: "45" + lanes: "4:2" + serdes_group: "5" + speed: "100G" + sysport: "45" + type: "eth" + - fec: "KPFEC" + id: "47" + lanes: "6:2" + serdes_group: "5" + speed: "100G" + sysport: "47" + type: "eth" + - fec: "KPFEC" + id: "17" + lanes: "0:2" + serdes_group: "2" + speed: "100G" + sysport: "17" + type: "eth" + - fec: "KPFEC" + id: "19" + lanes: "2:2" + serdes_group: "2" + speed: "100G" + sysport: "19" + type: "eth" + - fec: "KPFEC" + id: "21" + lanes: "4:2" + serdes_group: "2" + speed: "100G" + sysport: "21" + type: "eth" + - fec: "KPFEC" + id: "23" + lanes: "6:2" + serdes_group: "2" + speed: "100G" + sysport: "23" + type: "eth" + - fec: "KPFEC" + id: "25" + lanes: "0:2" + serdes_group: "3" + speed: "100G" + sysport: "25" + type: "eth" + - fec: "KPFEC" + id: "27" + lanes: "2:2" + serdes_group: "3" + speed: "100G" + sysport: "27" + type: "eth" + - fec: "KPFEC" + id: "29" + lanes: "4:2" + serdes_group: "3" + speed: "100G" + sysport: "29" + type: "eth" + - fec: "KPFEC" + id: "31" + lanes: "6:2" + serdes_group: "3" + speed: "100G" + sysport: "31" + type: "eth" + - fec: "KPFEC" + id: "1" + lanes: "0:2" + serdes_group: "0" + speed: "100G" + sysport: "1" + type: "eth" + - fec: "KPFEC" + id: "3" + lanes: "2:2" + serdes_group: "0" + speed: "100G" + sysport: "3" + type: "eth" + - fec: "KPFEC" + id: "5" + lanes: "4:2" + serdes_group: "0" + speed: "100G" + sysport: "5" + type: "eth" + - fec: "KPFEC" + id: "7" + lanes: "6:2" + serdes_group: "0" + speed: "100G" + sysport: "7" + type: "eth" + - fec: "KPFEC" + id: "9" + lanes: "0:2" + serdes_group: "1" + speed: "100G" + sysport: "9" + type: "eth" + - fec: "KPFEC" + id: "11" + lanes: "2:2" + serdes_group: "1" + speed: "100G" + sysport: "11" + type: "eth" + - fec: "KPFEC" + id: "13" + lanes: "4:2" + serdes_group: "1" + speed: "100G" + sysport: "13" + type: "eth" + - fec: "KPFEC" + id: "15" + lanes: "6:2" + serdes_group: "1" + speed: "100G" + sysport: "15" + type: "eth" + - fec: "NONE" + id: "257" + lanes: "0:1" + serdes_group: "32" + speed: "10G" + sysport: "257" + type: "mgmt 0" + - fec: "NONE" + id: "258" + lanes: "1:1" + serdes_group: "32" + speed: "10G" + sysport: "258" + type: "mgmt 1" + + isg: + - id: "0" + tx_polarity: "01010101" + rx_polarity: "01100000" + lane_swap: "23641075" + - id: "1" + tx_polarity: "10110000" + rx_polarity: "11111111" + lane_swap: "64317520" + - id: "2" + tx_polarity: "00000000" + rx_polarity: "00000011" + lane_swap: "63147520" + - id: "3" + tx_polarity: "01101000" + rx_polarity: "00001110" + lane_swap: "31572046" + - id: "4" + tx_polarity: "00111000" + rx_polarity: "00001000" + lane_swap: "46105732" + - id: "5" + tx_polarity: "10111111" + rx_polarity: "11101000" + lane_swap: "27153604" + - id: "6" + tx_polarity: "01101110" + rx_polarity: "00001101" + lane_swap: "46503721" + - id: "7" + tx_polarity: "01000100" + rx_polarity: "10000101" + lane_swap: "03671245" + - id: "8" + tx_polarity: "01110101" + rx_polarity: "00010000" + lane_swap: "12640375" + - id: "9" + tx_polarity: "01011100" + rx_polarity: "11001111" + lane_swap: "02561347" + - id: "10" + tx_polarity: "01110110" + rx_polarity: "11000000" + lane_swap: "12740365" + - id: "11" + tx_polarity: "00111000" + rx_polarity: "00010111" + lane_swap: "01572436" + - id: "12" + tx_polarity: "00001111" + rx_polarity: "10111001" + lane_swap: "54320176" + - id: "13" + tx_polarity: "10011101" + rx_polarity: "00111011" + lane_swap: "26153704" + - id: "14" + tx_polarity: "00110000" + rx_polarity: "11010000" + lane_swap: "37452601" + - id: "15" + tx_polarity: "11100010" + rx_polarity: "01110011" + lane_swap: "51370462" + - id: "16" + tx_polarity: "10111010" + rx_polarity: "11010011" + lane_swap: "36152704" + - id: "17" + tx_polarity: "01011101" + rx_polarity: "00110001" + lane_swap: "45621073" + - id: "18" + tx_polarity: "11011111" + rx_polarity: "11001011" + lane_swap: "26143705" + - id: "19" + tx_polarity: "00100110" + rx_polarity: "00001001" + lane_swap: "42730165" + - id: "20" + tx_polarity: "10011011" + rx_polarity: "01101101" + lane_swap: "54217603" + - id: "21" + tx_polarity: "00101110" + rx_polarity: "10111111" + lane_swap: "26031745" + - id: "22" + tx_polarity: "01001110" + rx_polarity: "00111001" + lane_swap: "36024715" + - id: "23" + tx_polarity: "10101101" + rx_polarity: "01010011" + lane_swap: "45621370" + - id: "24" + tx_polarity: "11001110" + rx_polarity: "00011111" + lane_swap: "65234701" + - id: "25" + tx_polarity: "01110001" + rx_polarity: "01010111" + lane_swap: "37601452" + - id: "26" + tx_polarity: "01000100" + rx_polarity: "00001111" + lane_swap: "65034721" + - id: "27" + tx_polarity: "10111101" + rx_polarity: "11000101" + lane_swap: "34501672" + - id: "28" + tx_polarity: "01111000" + rx_polarity: "01110110" + lane_swap: "43061275" + - id: "29" + tx_polarity: "11110111" + rx_polarity: "11100111" + lane_swap: "57304621" + - id: "30" + tx_polarity: "10000100" + rx_polarity: "00101111" + lane_swap: "47125603" + - id: "31" + tx_polarity: "11111111" + rx_polarity: "11100010" + lane_swap: "13460275" + - id: "32" + tx_polarity: "00000000" + rx_polarity: "00000000" + lane_swap: "01234567" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/inno.config.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/inno.config.yaml new file mode 100755 index 000000000000..17f3e060d712 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_128x100G_Delta-et-c032if.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/innovium.77700_B b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/port_config.ini b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/port_config.ini new file mode 100644 index 000000000000..cd4dbc611ec1 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/port_config.ini @@ -0,0 +1,131 @@ +# name lanes speed index mtu +Ethernet0 249,250 100000 0 9126 +Ethernet2 251,252 100000 0 9126 +Ethernet4 253,254 100000 0 9126 +Ethernet6 255,256 100000 0 9126 +Ethernet8 241,242 100000 1 9126 +Ethernet10 243,244 100000 1 9126 +Ethernet12 245,246 100000 1 9126 +Ethernet14 247,248 100000 1 9126 +Ethernet16 233,234 100000 2 9126 +Ethernet18 235,236 100000 2 9126 +Ethernet20 237,238 100000 2 9126 +Ethernet22 239,240 100000 2 9126 +Ethernet24 225,226 100000 3 9126 +Ethernet26 227,228 100000 3 9126 +Ethernet28 229,230 100000 3 9126 +Ethernet30 231,232 100000 3 9126 +Ethernet32 217,218 100000 4 9126 +Ethernet34 219,220 100000 4 9126 +Ethernet36 221,222 100000 4 9126 +Ethernet38 223,224 100000 4 9126 +Ethernet40 209,210 100000 5 9126 +Ethernet42 211,212 100000 5 9126 +Ethernet44 213,214 100000 5 9126 +Ethernet46 215,216 100000 5 9126 +Ethernet48 201,202 100000 6 9126 +Ethernet50 203,204 100000 6 9126 +Ethernet52 205,206 100000 6 9126 +Ethernet54 207,208 100000 6 9126 +Ethernet56 193,194 100000 7 9126 +Ethernet58 195,196 100000 7 9126 +Ethernet60 197,198 100000 7 9126 +Ethernet62 199,200 100000 7 9126 +Ethernet64 185,186 100000 8 9126 +Ethernet66 187,188 100000 8 9126 +Ethernet68 189,190 100000 8 9126 +Ethernet70 191,192 100000 8 9126 +Ethernet72 177,178 100000 9 9126 +Ethernet74 179,180 100000 9 9126 +Ethernet76 181,182 100000 9 9126 +Ethernet78 183,184 100000 9 9126 +Ethernet80 169,170 100000 10 9126 +Ethernet82 171,172 100000 10 9126 +Ethernet84 173,174 100000 10 9126 +Ethernet86 175,176 100000 10 9126 +Ethernet88 161,162 100000 11 9126 +Ethernet90 163,164 100000 11 9126 +Ethernet92 165,166 100000 11 9126 +Ethernet94 167,168 100000 11 9126 +Ethernet96 153,154 100000 12 9126 +Ethernet98 155,156 100000 12 9126 +Ethernet100 157,158 100000 12 9126 +Ethernet102 159,160 100000 12 9126 +Ethernet104 145,146 100000 13 9126 +Ethernet106 147,148 100000 13 9126 +Ethernet108 149,150 100000 13 9126 +Ethernet110 151,152 100000 13 9126 +Ethernet112 137,138 100000 14 9126 +Ethernet114 139,140 100000 14 9126 +Ethernet116 141,142 100000 14 9126 +Ethernet118 143,144 100000 14 9126 +Ethernet120 129,130 100000 15 9126 +Ethernet122 131,132 100000 15 9126 +Ethernet124 133,134 100000 15 9126 +Ethernet126 135,136 100000 15 9126 +Ethernet128 121,122 100000 16 9126 +Ethernet130 123,124 100000 16 9126 +Ethernet132 125,126 100000 16 9126 +Ethernet134 127,128 100000 16 9126 +Ethernet136 113,114 100000 17 9126 +Ethernet138 115,116 100000 17 9126 +Ethernet140 117,118 100000 17 9126 +Ethernet142 119,120 100000 17 9126 +Ethernet144 97,98 100000 18 9126 +Ethernet146 99,100 100000 18 9126 +Ethernet148 101,102 100000 18 9126 +Ethernet150 103,104 100000 18 9126 +Ethernet152 105,106 100000 19 9126 +Ethernet154 107,108 100000 19 9126 +Ethernet156 109,110 100000 19 9126 +Ethernet158 111,112 100000 19 9126 +Ethernet160 81,82 100000 20 9126 +Ethernet162 83,84 100000 20 9126 +Ethernet164 85,86 100000 20 9126 +Ethernet166 87,88 100000 20 9126 +Ethernet168 89,90 100000 21 9126 +Ethernet170 91,92 100000 21 9126 +Ethernet172 93,94 100000 21 9126 +Ethernet174 95,96 100000 21 9126 +Ethernet176 65,66 100000 22 9126 +Ethernet178 67,68 100000 22 9126 +Ethernet180 69,70 100000 22 9126 +Ethernet182 71,72 100000 22 9126 +Ethernet184 73,74 100000 23 9126 +Ethernet186 75,76 100000 23 9126 +Ethernet188 77,78 100000 23 9126 +Ethernet190 79,80 100000 23 9126 +Ethernet192 49,50 100000 24 9126 +Ethernet194 51,52 100000 24 9126 +Ethernet196 53,54 100000 24 9126 +Ethernet198 55,56 100000 24 9126 +Ethernet200 57,58 100000 25 9126 +Ethernet202 59,60 100000 25 9126 +Ethernet204 61,62 100000 25 9126 +Ethernet206 63,64 100000 25 9126 +Ethernet208 33,34 100000 26 9126 +Ethernet210 35,36 100000 26 9126 +Ethernet212 37,38 100000 26 9126 +Ethernet214 39,40 100000 26 9126 +Ethernet216 41,42 100000 27 9126 +Ethernet218 43,44 100000 27 9126 +Ethernet220 45,46 100000 27 9126 +Ethernet222 47,48 100000 27 9126 +Ethernet224 17,18 100000 28 9126 +Ethernet226 19,20 100000 28 9126 +Ethernet228 21,22 100000 28 9126 +Ethernet230 23,24 100000 28 9126 +Ethernet232 25,26 100000 29 9126 +Ethernet234 27,28 100000 29 9126 +Ethernet236 29,30 100000 29 9126 +Ethernet238 31,32 100000 29 9126 +Ethernet240 1,2 100000 30 9126 +Ethernet242 3,4 100000 30 9126 +Ethernet244 5,6 100000 30 9126 +Ethernet246 7,8 100000 30 9126 +Ethernet248 9,10 100000 31 9126 +Ethernet250 11,12 100000 31 9126 +Ethernet252 13,14 100000 31 9126 +Ethernet254 15,16 100000 31 9126 +Ethernet256 257 10000 32 9126 +Ethernet257 258 10000 33 9126 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/qos.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/qos.json.j2 new file mode 100755 index 000000000000..733bd51dc86f --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 128 -%} +{# 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*2)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/sai.profile b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_128x100/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/buffers.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/buffers.json.j2 new file mode 100644 index 000000000000..4fca9cbcd156 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 32 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/config_32x100G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/config_32x100G_Delta-et-c032if.yaml new file mode 100755 index 000000000000..4b4f02da4895 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/config_32x100G_Delta-et-c032if.yaml @@ -0,0 +1,415 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_B" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KRFEC" + id: "249" + lanes: "0:4" + serdes_group: "31" + speed: "100G" + sysport: "249" + type: "eth" + - fec: "KRFEC" + id: "241" + lanes: "0:4" + serdes_group: "30" + speed: "100G" + sysport: "241" + type: "eth" + - fec: "KRFEC" + id: "233" + lanes: "0:4" + serdes_group: "29" + speed: "100G" + sysport: "233" + type: "eth" + - fec: "KRFEC" + id: "225" + lanes: "0:4" + serdes_group: "28" + speed: "100G" + sysport: "225" + type: "eth" + - fec: "KRFEC" + id: "217" + lanes: "0:4" + serdes_group: "27" + speed: "100G" + sysport: "217" + type: "eth" + - fec: "KRFEC" + id: "209" + lanes: "0:4" + serdes_group: "26" + speed: "100G" + sysport: "209" + type: "eth" + - fec: "KRFEC" + id: "201" + lanes: "0:4" + serdes_group: "25" + speed: "100G" + sysport: "201" + type: "eth" + - fec: "KRFEC" + id: "193" + lanes: "0:4" + serdes_group: "24" + speed: "100G" + sysport: "193" + type: "eth" + - fec: "KRFEC" + id: "185" + lanes: "0:4" + serdes_group: "23" + speed: "100G" + sysport: "185" + type: "eth" + - fec: "KRFEC" + id: "177" + lanes: "0:4" + serdes_group: "22" + speed: "100G" + sysport: "177" + type: "eth" + - fec: "KRFEC" + id: "169" + lanes: "0:4" + serdes_group: "21" + speed: "100G" + sysport: "169" + type: "eth" + - fec: "KRFEC" + id: "161" + lanes: "0:4" + serdes_group: "20" + speed: "100G" + sysport: "161" + type: "eth" + - fec: "KRFEC" + id: "153" + lanes: "0:4" + serdes_group: "19" + speed: "100G" + sysport: "153" + type: "eth" + - fec: "KRFEC" + id: "145" + lanes: "0:4" + serdes_group: "18" + speed: "100G" + sysport: "145" + type: "eth" + - fec: "KRFEC" + id: "137" + lanes: "0:4" + serdes_group: "17" + speed: "100G" + sysport: "137" + type: "eth" + - fec: "KRFEC" + id: "129" + lanes: "0:4" + serdes_group: "16" + speed: "100G" + sysport: "129" + type: "eth" + - fec: "KRFEC" + id: "121" + lanes: "0:4" + serdes_group: "15" + speed: "100G" + sysport: "121" + type: "eth" + - fec: "KRFEC" + id: "113" + lanes: "0:4" + serdes_group: "14" + speed: "100G" + sysport: "113" + type: "eth" + - fec: "KRFEC" + id: "97" + lanes: "0:4" + serdes_group: "12" + speed: "100G" + sysport: "97" + type: "eth" + - fec: "KRFEC" + id: "105" + lanes: "0:4" + serdes_group: "13" + speed: "100G" + sysport: "105" + type: "eth" + - fec: "KRFEC" + id: "81" + lanes: "0:4" + serdes_group: "10" + speed: "100G" + sysport: "81" + type: "eth" + - fec: "KRFEC" + id: "89" + lanes: "0:4" + serdes_group: "11" + speed: "100G" + sysport: "89" + type: "eth" + - fec: "KRFEC" + id: "65" + lanes: "0:4" + serdes_group: "8" + speed: "100G" + sysport: "65" + type: "eth" + - fec: "KRFEC" + id: "73" + lanes: "0:4" + serdes_group: "9" + speed: "100G" + sysport: "73" + type: "eth" + - fec: "KRFEC" + id: "49" + lanes: "0:4" + serdes_group: "6" + speed: "100G" + sysport: "49" + type: "eth" + - fec: "KRFEC" + id: "57" + lanes: "0:4" + serdes_group: "7" + speed: "100G" + sysport: "57" + type: "eth" + - fec: "KRFEC" + id: "33" + lanes: "0:4" + serdes_group: "4" + speed: "100G" + sysport: "33" + type: "eth" + - fec: "KRFEC" + id: "41" + lanes: "0:4" + serdes_group: "5" + speed: "100G" + sysport: "41" + type: "eth" + - fec: "KRFEC" + id: "17" + lanes: "0:4" + serdes_group: "2" + speed: "100G" + sysport: "17" + type: "eth" + - fec: "KRFEC" + id: "25" + lanes: "0:4" + serdes_group: "3" + speed: "100G" + sysport: "25" + type: "eth" + - fec: "KRFEC" + id: "1" + lanes: "0:4" + serdes_group: "0" + speed: "100G" + sysport: "1" + type: "eth" + - fec: "KRFEC" + id: "9" + lanes: "0:4" + serdes_group: "1" + speed: "100G" + sysport: "9" + type: "eth" + isg: + - id: "0" + tx_polarity: "01010101" + rx_polarity: "01100000" + lane_swap: "23641075" + - id: "1" + tx_polarity: "10110000" + rx_polarity: "11111111" + lane_swap: "64317520" + - id: "2" + tx_polarity: "00000000" + rx_polarity: "00000011" + lane_swap: "63147520" + - id: "3" + tx_polarity: "01101000" + rx_polarity: "00001110" + lane_swap: "31572046" + - id: "4" + tx_polarity: "00111000" + rx_polarity: "00001000" + lane_swap: "46105732" + - id: "5" + tx_polarity: "10111111" + rx_polarity: "11101000" + lane_swap: "27153604" + - id: "6" + tx_polarity: "01101110" + rx_polarity: "00001101" + lane_swap: "46503721" + - id: "7" + tx_polarity: "01000100" + rx_polarity: "10000101" + lane_swap: "03671245" + - id: "8" + tx_polarity: "01110101" + rx_polarity: "00010000" + lane_swap: "12640375" + - id: "9" + tx_polarity: "01011100" + rx_polarity: "11001111" + lane_swap: "02561347" + - id: "10" + tx_polarity: "01110110" + rx_polarity: "11000000" + lane_swap: "12740365" + - id: "11" + tx_polarity: "00111000" + rx_polarity: "00010111" + lane_swap: "01572436" + - id: "12" + tx_polarity: "00001111" + rx_polarity: "10111001" + lane_swap: "54320176" + - id: "13" + tx_polarity: "10011101" + rx_polarity: "00111011" + lane_swap: "26153704" + - id: "14" + tx_polarity: "00110000" + rx_polarity: "11010000" + lane_swap: "37452601" + - id: "15" + tx_polarity: "11100010" + rx_polarity: "01110011" + lane_swap: "51370462" + - id: "16" + tx_polarity: "10111010" + rx_polarity: "11010011" + lane_swap: "36152704" + - id: "17" + tx_polarity: "01011101" + rx_polarity: "00110001" + lane_swap: "45621073" + - id: "18" + tx_polarity: "11011111" + rx_polarity: "11001011" + lane_swap: "26143705" + - id: "19" + tx_polarity: "00100110" + rx_polarity: "00001001" + lane_swap: "42730165" + - id: "20" + tx_polarity: "10011011" + rx_polarity: "01101101" + lane_swap: "54217603" + - id: "21" + tx_polarity: "00101110" + rx_polarity: "10111111" + lane_swap: "26031745" + - id: "22" + tx_polarity: "01001110" + rx_polarity: "00111001" + lane_swap: "36024715" + - id: "23" + tx_polarity: "10101101" + rx_polarity: "01010011" + lane_swap: "45621370" + - id: "24" + tx_polarity: "11001110" + rx_polarity: "00011111" + lane_swap: "65234701" + - id: "25" + tx_polarity: "01110001" + rx_polarity: "01010111" + lane_swap: "37601452" + - id: "26" + tx_polarity: "01000100" + rx_polarity: "00001111" + lane_swap: "65034721" + - id: "27" + tx_polarity: "10111101" + rx_polarity: "11000101" + lane_swap: "34501672" + - id: "28" + tx_polarity: "01111000" + rx_polarity: "01110110" + lane_swap: "43061275" + - id: "29" + tx_polarity: "11110111" + rx_polarity: "11100111" + lane_swap: "57304621" + - id: "30" + tx_polarity: "10000100" + rx_polarity: "00101111" + lane_swap: "47125603" + - id: "31" + tx_polarity: "11111111" + rx_polarity: "11100010" + lane_swap: "13460275" + - id: "32" + tx_polarity: "00000000" + rx_polarity: "00000000" + lane_swap: "01234567" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/inno.config.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/inno.config.yaml new file mode 100755 index 000000000000..9350e166634e --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_32x100G_Delta-et-c032if.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/innovium.77700_A b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/innovium.77700_A new file mode 100644 index 000000000000..84aa41983606 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/innovium.77700_A @@ -0,0 +1,59 @@ +sku: innovium.77700_A + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 6, 5, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 8:0 + ib: 1 + pic_id: 5 + + isg 31: + mode: 8:0 + ib: 0 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/innovium.77700_B b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/port_config.ini b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/port_config.ini new file mode 100755 index 000000000000..45fbfd346c9f --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/port_config.ini @@ -0,0 +1,33 @@ +# name lanes speed index mtu fec +Ethernet0 249,250,251,252 100000 0 9126 rs +Ethernet8 241,242,243,244 100000 1 9126 rs +Ethernet16 233,234,235,236 100000 2 9126 rs +Ethernet24 225,226,227,228 100000 3 9126 rs +Ethernet32 217,218,219,220 100000 4 9126 rs +Ethernet40 209,210,211,212 100000 5 9126 rs +Ethernet48 201,202,203,204 100000 6 9126 rs +Ethernet56 193,194,195,196 100000 7 9126 rs +Ethernet64 185,186,187,188 100000 8 9126 rs +Ethernet72 177,178,179,180 100000 9 9126 rs +Ethernet80 169,170,171,172 100000 10 9126 rs +Ethernet88 161,162,163,164 100000 11 9126 rs +Ethernet96 153,154,155,156 100000 12 9126 rs +Ethernet104 145,146,147,148 100000 13 9126 rs +Ethernet112 137,138,139,140 100000 14 9126 rs +Ethernet120 129,130,131,132 100000 15 9126 rs +Ethernet128 121,122,123,124 100000 16 9126 rs +Ethernet136 113,114,115,116 100000 17 9126 rs +Ethernet144 97,98,99,100 100000 18 9126 rs +Ethernet152 105,106,107,108 100000 19 9126 rs +Ethernet160 81,82,83,84 100000 20 9126 rs +Ethernet168 89,90,91,92 100000 21 9126 rs +Ethernet176 65,66,67,68 100000 22 9126 rs +Ethernet184 73,74,75,76 100000 23 9126 rs +Ethernet192 49,50,51,52 100000 24 9126 rs +Ethernet200 57,58,59,60 100000 25 9126 rs +Ethernet208 33,34,35,36 100000 26 9126 rs +Ethernet216 41,42,43,44 100000 27 9126 rs +Ethernet224 17,18,19,20 100000 28 9126 rs +Ethernet232 25,26,27,28 100000 29 9126 rs +Ethernet240 1,2,3,4 100000 30 9126 rs +Ethernet248 9,10,11,12 100000 31 9126 rs diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/qos.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/qos.json.j2 new file mode 100755 index 000000000000..6c734d46ff2f --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 32 -%} +{# 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*4)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/sai.profile b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x100/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/buffers.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/buffers.json.j2 new file mode 100644 index 000000000000..4fca9cbcd156 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 32 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/config_32x200G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/config_32x200G_Delta-et-c032if.yaml new file mode 100755 index 000000000000..0a76811110e8 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/config_32x200G_Delta-et-c032if.yaml @@ -0,0 +1,429 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_B" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KPFEC" + id: "249" + lanes: "0:4" + serdes_group: "31" + speed: "200G" + sysport: "249" + type: "eth" + - fec: "KPFEC" + id: "241" + lanes: "0:4" + serdes_group: "30" + speed: "200G" + sysport: "241" + type: "eth" + - fec: "KPFEC" + id: "233" + lanes: "0:4" + serdes_group: "29" + speed: "200G" + sysport: "233" + type: "eth" + - fec: "KPFEC" + id: "225" + lanes: "0:4" + serdes_group: "28" + speed: "200G" + sysport: "225" + type: "eth" + - fec: "KPFEC" + id: "217" + lanes: "0:4" + serdes_group: "27" + speed: "200G" + sysport: "217" + type: "eth" + - fec: "KPFEC" + id: "209" + lanes: "0:4" + serdes_group: "26" + speed: "200G" + sysport: "209" + type: "eth" + - fec: "KPFEC" + id: "201" + lanes: "0:4" + serdes_group: "25" + speed: "200G" + sysport: "201" + type: "eth" + - fec: "KPFEC" + id: "193" + lanes: "0:4" + serdes_group: "24" + speed: "200G" + sysport: "193" + type: "eth" + - fec: "KPFEC" + id: "185" + lanes: "0:4" + serdes_group: "23" + speed: "200G" + sysport: "185" + type: "eth" + - fec: "KPFEC" + id: "177" + lanes: "0:4" + serdes_group: "22" + speed: "200G" + sysport: "177" + type: "eth" + - fec: "KPFEC" + id: "169" + lanes: "0:4" + serdes_group: "21" + speed: "200G" + sysport: "169" + type: "eth" + - fec: "KPFEC" + id: "161" + lanes: "0:4" + serdes_group: "20" + speed: "200G" + sysport: "161" + type: "eth" + - fec: "KPFEC" + id: "153" + lanes: "0:4" + serdes_group: "19" + speed: "200G" + sysport: "153" + type: "eth" + - fec: "KPFEC" + id: "145" + lanes: "0:4" + serdes_group: "18" + speed: "200G" + sysport: "145" + type: "eth" + - fec: "KPFEC" + id: "137" + lanes: "0:4" + serdes_group: "17" + speed: "200G" + sysport: "137" + type: "eth" + - fec: "KPFEC" + id: "129" + lanes: "0:4" + serdes_group: "16" + speed: "200G" + sysport: "129" + type: "eth" + - fec: "KPFEC" + id: "121" + lanes: "0:4" + serdes_group: "15" + speed: "200G" + sysport: "121" + type: "eth" + - fec: "KPFEC" + id: "113" + lanes: "0:4" + serdes_group: "14" + speed: "200G" + sysport: "113" + type: "eth" + - fec: "KPFEC" + id: "97" + lanes: "0:4" + serdes_group: "12" + speed: "200G" + sysport: "97" + type: "eth" + - fec: "KPFEC" + id: "105" + lanes: "0:4" + serdes_group: "13" + speed: "200G" + sysport: "105" + type: "eth" + - fec: "KPFEC" + id: "81" + lanes: "0:4" + serdes_group: "10" + speed: "200G" + sysport: "81" + type: "eth" + - fec: "KPFEC" + id: "89" + lanes: "0:4" + serdes_group: "11" + speed: "200G" + sysport: "89" + type: "eth" + - fec: "KPFEC" + id: "65" + lanes: "0:4" + serdes_group: "8" + speed: "200G" + sysport: "65" + type: "eth" + - fec: "KPFEC" + id: "73" + lanes: "0:4" + serdes_group: "9" + speed: "200G" + sysport: "73" + type: "eth" + - fec: "KPFEC" + id: "49" + lanes: "0:4" + serdes_group: "6" + speed: "200G" + sysport: "49" + type: "eth" + - fec: "KPFEC" + id: "57" + lanes: "0:4" + serdes_group: "7" + speed: "200G" + sysport: "57" + type: "eth" + - fec: "KPFEC" + id: "33" + lanes: "0:4" + serdes_group: "4" + speed: "200G" + sysport: "33" + type: "eth" + - fec: "KPFEC" + id: "41" + lanes: "0:4" + serdes_group: "5" + speed: "200G" + sysport: "41" + type: "eth" + - fec: "KPFEC" + id: "17" + lanes: "0:4" + serdes_group: "2" + speed: "200G" + sysport: "17" + type: "eth" + - fec: "KPFEC" + id: "25" + lanes: "0:4" + serdes_group: "3" + speed: "200G" + sysport: "25" + type: "eth" + - fec: "KPFEC" + id: "1" + lanes: "0:4" + serdes_group: "0" + speed: "200G" + sysport: "1" + type: "eth" + - fec: "KPFEC" + id: "9" + lanes: "0:4" + serdes_group: "1" + speed: "200G" + sysport: "9" + type: "eth" + - fec: "NONE" + id: "257" + lanes: "0:1" + serdes_group: "32" + speed: "10G" + sysport: "257" + type: "mgmt 0" + - fec: "NONE" + id: "258" + lanes: "1:1" + serdes_group: "32" + speed: "10G" + sysport: "258" + type: "mgmt 1" + isg: + - id: "0" + tx_polarity: "01010101" + rx_polarity: "01100000" + lane_swap: "23641075" + - id: "1" + tx_polarity: "10110000" + rx_polarity: "11111111" + lane_swap: "64317520" + - id: "2" + tx_polarity: "00000000" + rx_polarity: "00000011" + lane_swap: "63147520" + - id: "3" + tx_polarity: "01101000" + rx_polarity: "00001110" + lane_swap: "31572046" + - id: "4" + tx_polarity: "00111000" + rx_polarity: "00001000" + lane_swap: "46105732" + - id: "5" + tx_polarity: "10111111" + rx_polarity: "11101000" + lane_swap: "27153604" + - id: "6" + tx_polarity: "01101110" + rx_polarity: "00001101" + lane_swap: "46503721" + - id: "7" + tx_polarity: "01000100" + rx_polarity: "10000101" + lane_swap: "03671245" + - id: "8" + tx_polarity: "01110101" + rx_polarity: "00010000" + lane_swap: "12640375" + - id: "9" + tx_polarity: "01011100" + rx_polarity: "11001111" + lane_swap: "02561347" + - id: "10" + tx_polarity: "01110110" + rx_polarity: "11000000" + lane_swap: "12740365" + - id: "11" + tx_polarity: "00111000" + rx_polarity: "00010111" + lane_swap: "01572436" + - id: "12" + tx_polarity: "00001111" + rx_polarity: "10111001" + lane_swap: "54320176" + - id: "13" + tx_polarity: "10011101" + rx_polarity: "00111011" + lane_swap: "26153704" + - id: "14" + tx_polarity: "00110000" + rx_polarity: "11010000" + lane_swap: "37452601" + - id: "15" + tx_polarity: "11100010" + rx_polarity: "01110011" + lane_swap: "51370462" + - id: "16" + tx_polarity: "10111010" + rx_polarity: "11010011" + lane_swap: "36152704" + - id: "17" + tx_polarity: "01011101" + rx_polarity: "00110001" + lane_swap: "45621073" + - id: "18" + tx_polarity: "11011111" + rx_polarity: "11001011" + lane_swap: "26143705" + - id: "19" + tx_polarity: "00100110" + rx_polarity: "00001001" + lane_swap: "42730165" + - id: "20" + tx_polarity: "10011011" + rx_polarity: "01101101" + lane_swap: "54217603" + - id: "21" + tx_polarity: "00101110" + rx_polarity: "10111111" + lane_swap: "26031745" + - id: "22" + tx_polarity: "01001110" + rx_polarity: "00111001" + lane_swap: "36024715" + - id: "23" + tx_polarity: "10101101" + rx_polarity: "01010011" + lane_swap: "45621370" + - id: "24" + tx_polarity: "11001110" + rx_polarity: "00011111" + lane_swap: "65234701" + - id: "25" + tx_polarity: "01110001" + rx_polarity: "01010111" + lane_swap: "37601452" + - id: "26" + tx_polarity: "01000100" + rx_polarity: "00001111" + lane_swap: "65034721" + - id: "27" + tx_polarity: "10111101" + rx_polarity: "11000101" + lane_swap: "34501672" + - id: "28" + tx_polarity: "01111000" + rx_polarity: "01110110" + lane_swap: "43061275" + - id: "29" + tx_polarity: "11110111" + rx_polarity: "11100111" + lane_swap: "57304621" + - id: "30" + tx_polarity: "10000100" + rx_polarity: "00101111" + lane_swap: "47125603" + - id: "31" + tx_polarity: "11111111" + rx_polarity: "11100010" + lane_swap: "13460275" + - id: "32" + tx_polarity: "00000000" + rx_polarity: "00000000" + lane_swap: "01234567" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/inno.config.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/inno.config.yaml new file mode 100755 index 000000000000..9bc0114cf69b --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_32x200G_Delta-et-c032if.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/innovium.77700_B b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/port_config.ini b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/port_config.ini new file mode 100755 index 000000000000..48091f5e3674 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/port_config.ini @@ -0,0 +1,35 @@ +# name lanes speed index mtu fec +Ethernet0 249,250,251,252 200000 0 9126 rs +Ethernet8 241,242,243,244 200000 1 9126 rs +Ethernet16 233,234,235,236 200000 2 9126 rs +Ethernet24 225,226,227,228 200000 3 9126 rs +Ethernet32 217,218,219,220 200000 4 9126 rs +Ethernet40 209,210,211,212 200000 5 9126 rs +Ethernet48 201,202,203,204 200000 6 9126 rs +Ethernet56 193,194,195,196 200000 7 9126 rs +Ethernet64 185,186,187,188 200000 8 9126 rs +Ethernet72 177,178,179,180 200000 9 9126 rs +Ethernet80 169,170,171,172 200000 10 9126 rs +Ethernet88 161,162,163,164 200000 11 9126 rs +Ethernet96 153,154,155,156 200000 12 9126 rs +Ethernet104 145,146,147,148 200000 13 9126 rs +Ethernet112 137,138,139,140 200000 14 9126 rs +Ethernet120 129,130,131,132 200000 15 9126 rs +Ethernet128 121,122,123,124 200000 16 9126 rs +Ethernet136 113,114,115,116 200000 17 9126 rs +Ethernet144 97,98,99,100 200000 18 9126 rs +Ethernet152 105,106,107,108 200000 19 9126 rs +Ethernet160 81,82,83,84 200000 20 9126 rs +Ethernet168 89,90,91,92 200000 21 9126 rs +Ethernet176 65,66,67,68 200000 22 9126 rs +Ethernet184 73,74,75,76 200000 23 9126 rs +Ethernet192 49,50,51,52 200000 24 9126 rs +Ethernet200 57,58,59,60 200000 25 9126 rs +Ethernet208 33,34,35,36 200000 26 9126 rs +Ethernet216 41,42,43,44 200000 27 9126 rs +Ethernet224 17,18,19,20 200000 28 9126 rs +Ethernet232 25,26,27,28 200000 29 9126 rs +Ethernet240 1,2,3,4 200000 30 9126 rs +Ethernet248 9,10,11,12 200000 31 9126 rs +Ethernet256 257 10000 32 9126 none +Ethernet257 258 10000 33 9126 none diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/qos.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/qos.json.j2 new file mode 100755 index 000000000000..6c734d46ff2f --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 32 -%} +{# 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*4)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/sai.profile b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x200/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/buffers.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/buffers.json.j2 new file mode 100644 index 000000000000..4fca9cbcd156 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 32 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/config_32x400G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/config_32x400G_Delta-et-c032if.yaml new file mode 100755 index 000000000000..2ba23d2a5a67 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/config_32x400G_Delta-et-c032if.yaml @@ -0,0 +1,429 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_A" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KPFEC" + id: "249" + lanes: "0:8" + serdes_group: "31" + speed: "400G" + sysport: "249" + type: "eth" + - fec: "KPFEC" + id: "241" + lanes: "0:8" + serdes_group: "30" + speed: "400G" + sysport: "241" + type: "eth" + - fec: "KPFEC" + id: "233" + lanes: "0:8" + serdes_group: "29" + speed: "400G" + sysport: "233" + type: "eth" + - fec: "KPFEC" + id: "225" + lanes: "0:8" + serdes_group: "28" + speed: "400G" + sysport: "225" + type: "eth" + - fec: "KPFEC" + id: "217" + lanes: "0:8" + serdes_group: "27" + speed: "400G" + sysport: "217" + type: "eth" + - fec: "KPFEC" + id: "209" + lanes: "0:8" + serdes_group: "26" + speed: "400G" + sysport: "209" + type: "eth" + - fec: "KPFEC" + id: "201" + lanes: "0:8" + serdes_group: "25" + speed: "400G" + sysport: "201" + type: "eth" + - fec: "KPFEC" + id: "193" + lanes: "0:8" + serdes_group: "24" + speed: "400G" + sysport: "193" + type: "eth" + - fec: "KPFEC" + id: "185" + lanes: "0:8" + serdes_group: "23" + speed: "400G" + sysport: "185" + type: "eth" + - fec: "KPFEC" + id: "177" + lanes: "0:8" + serdes_group: "22" + speed: "400G" + sysport: "177" + type: "eth" + - fec: "KPFEC" + id: "169" + lanes: "0:8" + serdes_group: "21" + speed: "400G" + sysport: "169" + type: "eth" + - fec: "KPFEC" + id: "161" + lanes: "0:8" + serdes_group: "20" + speed: "400G" + sysport: "161" + type: "eth" + - fec: "KPFEC" + id: "153" + lanes: "0:8" + serdes_group: "19" + speed: "400G" + sysport: "153" + type: "eth" + - fec: "KPFEC" + id: "145" + lanes: "0:8" + serdes_group: "18" + speed: "400G" + sysport: "145" + type: "eth" + - fec: "KPFEC" + id: "137" + lanes: "0:8" + serdes_group: "17" + speed: "400G" + sysport: "137" + type: "eth" + - fec: "KPFEC" + id: "129" + lanes: "0:8" + serdes_group: "16" + speed: "400G" + sysport: "129" + type: "eth" + - fec: "KPFEC" + id: "121" + lanes: "0:8" + serdes_group: "15" + speed: "400G" + sysport: "121" + type: "eth" + - fec: "KPFEC" + id: "113" + lanes: "0:8" + serdes_group: "14" + speed: "400G" + sysport: "113" + type: "eth" + - fec: "KPFEC" + id: "97" + lanes: "0:8" + serdes_group: "12" + speed: "400G" + sysport: "97" + type: "eth" + - fec: "KPFEC" + id: "105" + lanes: "0:8" + serdes_group: "13" + speed: "400G" + sysport: "105" + type: "eth" + - fec: "KPFEC" + id: "81" + lanes: "0:8" + serdes_group: "10" + speed: "400G" + sysport: "81" + type: "eth" + - fec: "KPFEC" + id: "89" + lanes: "0:8" + serdes_group: "11" + speed: "400G" + sysport: "89" + type: "eth" + - fec: "KPFEC" + id: "65" + lanes: "0:8" + serdes_group: "8" + speed: "400G" + sysport: "65" + type: "eth" + - fec: "KPFEC" + id: "73" + lanes: "0:8" + serdes_group: "9" + speed: "400G" + sysport: "73" + type: "eth" + - fec: "KPFEC" + id: "49" + lanes: "0:8" + serdes_group: "6" + speed: "400G" + sysport: "49" + type: "eth" + - fec: "KPFEC" + id: "57" + lanes: "0:8" + serdes_group: "7" + speed: "400G" + sysport: "57" + type: "eth" + - fec: "KPFEC" + id: "33" + lanes: "0:8" + serdes_group: "4" + speed: "400G" + sysport: "33" + type: "eth" + - fec: "KPFEC" + id: "41" + lanes: "0:8" + serdes_group: "5" + speed: "400G" + sysport: "41" + type: "eth" + - fec: "KPFEC" + id: "17" + lanes: "0:8" + serdes_group: "2" + speed: "400G" + sysport: "17" + type: "eth" + - fec: "KPFEC" + id: "25" + lanes: "0:8" + serdes_group: "3" + speed: "400G" + sysport: "25" + type: "eth" + - fec: "KPFEC" + id: "1" + lanes: "0:8" + serdes_group: "0" + speed: "400G" + sysport: "1" + type: "eth" + - fec: "KPFEC" + id: "9" + lanes: "0:8" + serdes_group: "1" + speed: "400G" + sysport: "9" + type: "eth" + - fec: "NONE" + id: "257" + lanes: "0:1" + serdes_group: "32" + speed: "10G" + sysport: "257" + type: "mgmt 0" + - fec: "NONE" + id: "258" + lanes: "1:1" + serdes_group: "32" + speed: "10G" + sysport: "258" + type: "mgmt 1" + isg: + - id: "0" + tx_polarity: "01010101" + rx_polarity: "01100000" + lane_swap: "23641075" + - id: "1" + tx_polarity: "10110000" + rx_polarity: "11111111" + lane_swap: "64317520" + - id: "2" + tx_polarity: "00000000" + rx_polarity: "00000011" + lane_swap: "63147520" + - id: "3" + tx_polarity: "01101000" + rx_polarity: "00001110" + lane_swap: "31572046" + - id: "4" + tx_polarity: "00111000" + rx_polarity: "00001000" + lane_swap: "46105732" + - id: "5" + tx_polarity: "10111111" + rx_polarity: "11101000" + lane_swap: "27153604" + - id: "6" + tx_polarity: "01101110" + rx_polarity: "00001101" + lane_swap: "46503721" + - id: "7" + tx_polarity: "01000100" + rx_polarity: "10000101" + lane_swap: "03671245" + - id: "8" + tx_polarity: "01110101" + rx_polarity: "00010000" + lane_swap: "12640375" + - id: "9" + tx_polarity: "01011100" + rx_polarity: "11001111" + lane_swap: "02561347" + - id: "10" + tx_polarity: "01110110" + rx_polarity: "11000000" + lane_swap: "12740365" + - id: "11" + tx_polarity: "00111000" + rx_polarity: "00010111" + lane_swap: "01572436" + - id: "12" + tx_polarity: "00001111" + rx_polarity: "10111001" + lane_swap: "54320176" + - id: "13" + tx_polarity: "10011101" + rx_polarity: "00111011" + lane_swap: "26153704" + - id: "14" + tx_polarity: "00110000" + rx_polarity: "11010000" + lane_swap: "37452601" + - id: "15" + tx_polarity: "11100010" + rx_polarity: "01110011" + lane_swap: "51370462" + - id: "16" + tx_polarity: "10111010" + rx_polarity: "11010011" + lane_swap: "36152704" + - id: "17" + tx_polarity: "01011101" + rx_polarity: "00110001" + lane_swap: "45621073" + - id: "18" + tx_polarity: "11011111" + rx_polarity: "11001011" + lane_swap: "26143705" + - id: "19" + tx_polarity: "00100110" + rx_polarity: "00001001" + lane_swap: "42730165" + - id: "20" + tx_polarity: "10011011" + rx_polarity: "01101101" + lane_swap: "54217603" + - id: "21" + tx_polarity: "00101110" + rx_polarity: "10111111" + lane_swap: "26031745" + - id: "22" + tx_polarity: "01001110" + rx_polarity: "00111001" + lane_swap: "36024715" + - id: "23" + tx_polarity: "10101101" + rx_polarity: "01010011" + lane_swap: "45621370" + - id: "24" + tx_polarity: "11001110" + rx_polarity: "00011111" + lane_swap: "65234701" + - id: "25" + tx_polarity: "01110001" + rx_polarity: "01010111" + lane_swap: "37601452" + - id: "26" + tx_polarity: "01000100" + rx_polarity: "00001111" + lane_swap: "65034721" + - id: "27" + tx_polarity: "10111101" + rx_polarity: "11000101" + lane_swap: "34501672" + - id: "28" + tx_polarity: "01111000" + rx_polarity: "01110110" + lane_swap: "43061275" + - id: "29" + tx_polarity: "11110111" + rx_polarity: "11100111" + lane_swap: "57304621" + - id: "30" + tx_polarity: "10000100" + rx_polarity: "00101111" + lane_swap: "47125603" + - id: "31" + tx_polarity: "11111111" + rx_polarity: "11100010" + lane_swap: "13460275" + - id: "32" + tx_polarity: "00000000" + rx_polarity: "00000000" + lane_swap: "01234567" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/inno.config.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/inno.config.yaml new file mode 100755 index 000000000000..360b5af8e602 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_32x400G_Delta-et-c032if.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_A" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/innovium.77700_A b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/innovium.77700_A new file mode 100644 index 000000000000..84aa41983606 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/innovium.77700_A @@ -0,0 +1,59 @@ +sku: innovium.77700_A + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 6, 5, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 8:0 + ib: 1 + pic_id: 5 + + isg 31: + mode: 8:0 + ib: 0 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/innovium.77700_B b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/port_config.ini b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/port_config.ini new file mode 100755 index 000000000000..360e363f485b --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/port_config.ini @@ -0,0 +1,35 @@ +# name lanes speed index mtu fec +Ethernet0 249,250,251,252 400000 0 9126 rs +Ethernet8 241,242,243,244 400000 1 9126 rs +Ethernet16 233,234,235,236 400000 2 9126 rs +Ethernet24 225,226,227,228 400000 3 9126 rs +Ethernet32 217,218,219,220 400000 4 9126 rs +Ethernet40 209,210,211,212 400000 5 9126 rs +Ethernet48 201,202,203,204 400000 6 9126 rs +Ethernet56 193,194,195,196 400000 7 9126 rs +Ethernet64 185,186,187,188 400000 8 9126 rs +Ethernet72 177,178,179,180 400000 9 9126 rs +Ethernet80 169,170,171,172 400000 10 9126 rs +Ethernet88 161,162,163,164 400000 11 9126 rs +Ethernet96 153,154,155,156 400000 12 9126 rs +Ethernet104 145,146,147,148 400000 13 9126 rs +Ethernet112 137,138,139,140 400000 14 9126 rs +Ethernet120 129,130,131,132 400000 15 9126 rs +Ethernet128 121,122,123,124 400000 16 9126 rs +Ethernet136 113,114,115,116 400000 17 9126 rs +Ethernet144 97,98,99,100 400000 18 9126 rs +Ethernet152 105,106,107,108 400000 19 9126 rs +Ethernet160 81,82,83,84 400000 20 9126 rs +Ethernet168 89,90,91,92 400000 21 9126 rs +Ethernet176 65,66,67,68 400000 22 9126 rs +Ethernet184 73,74,75,76 400000 23 9126 rs +Ethernet192 49,50,51,52 400000 24 9126 rs +Ethernet200 57,58,59,60 400000 25 9126 rs +Ethernet208 33,34,35,36 400000 26 9126 rs +Ethernet216 41,42,43,44 400000 27 9126 rs +Ethernet224 17,18,19,20 400000 28 9126 rs +Ethernet232 25,26,27,28 400000 29 9126 rs +Ethernet240 1,2,3,4 400000 30 9126 rs +Ethernet248 9,10,11,12 400000 31 9126 rs +Ethernet256 257 10000 32 9126 none +Ethernet257 258 10000 33 9126 none diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/qos.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/qos.json.j2 new file mode 100755 index 000000000000..6c734d46ff2f --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 32 -%} +{# 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*4)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/sai.profile b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_32x400/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/buffers.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/buffers.json.j2 new file mode 100644 index 000000000000..45cebf3b7144 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 64 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/config_64x100G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/config_64x100G_Delta-et-c032if.yaml new file mode 100755 index 000000000000..e5fbcc93543d --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/config_64x100G_Delta-et-c032if.yaml @@ -0,0 +1,653 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_B" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KRFEC" + id: "249" + lanes: "0:4" + serdes_group: "31" + speed: "100G" + sysport: "249" + type: "eth" + - fec: "KRFEC" + id: "253" + lanes: "4:4" + serdes_group: "31" + speed: "100G" + sysport: "253" + type: "eth" + - fec: "KRFEC" + id: "241" + lanes: "0:4" + serdes_group: "30" + speed: "100G" + sysport: "241" + type: "eth" + - fec: "KRFEC" + id: "245" + lanes: "4:4" + serdes_group: "30" + speed: "100G" + sysport: "245" + type: "eth" + - fec: "KRFEC" + id: "233" + lanes: "0:4" + serdes_group: "29" + speed: "100G" + sysport: "233" + type: "eth" + - fec: "KRFEC" + id: "237" + lanes: "4:4" + serdes_group: "29" + speed: "100G" + sysport: "237" + type: "eth" + - fec: "KRFEC" + id: "225" + lanes: "0:4" + serdes_group: "28" + speed: "100G" + sysport: "225" + type: "eth" + - fec: "KRFEC" + id: "229" + lanes: "4:4" + serdes_group: "28" + speed: "100G" + sysport: "229" + type: "eth" + - fec: "KRFEC" + id: "217" + lanes: "0:4" + serdes_group: "27" + speed: "100G" + sysport: "217" + type: "eth" + - fec: "KRFEC" + id: "221" + lanes: "4:4" + serdes_group: "27" + speed: "100G" + sysport: "221" + type: "eth" + - fec: "KRFEC" + id: "209" + lanes: "0:4" + serdes_group: "26" + speed: "100G" + sysport: "209" + type: "eth" + - fec: "KRFEC" + id: "213" + lanes: "4:4" + serdes_group: "26" + speed: "100G" + sysport: "213" + type: "eth" + - fec: "KRFEC" + id: "201" + lanes: "0:4" + serdes_group: "25" + speed: "100G" + sysport: "201" + type: "eth" + - fec: "KRFEC" + id: "205" + lanes: "4:4" + serdes_group: "25" + speed: "100G" + sysport: "205" + type: "eth" + - fec: "KRFEC" + id: "193" + lanes: "0:4" + serdes_group: "24" + speed: "100G" + sysport: "193" + type: "eth" + - fec: "KRFEC" + id: "197" + lanes: "4:4" + serdes_group: "24" + speed: "100G" + sysport: "197" + type: "eth" + - fec: "KRFEC" + id: "185" + lanes: "0:4" + serdes_group: "23" + speed: "100G" + sysport: "185" + type: "eth" + - fec: "KRFEC" + id: "189" + lanes: "4:4" + serdes_group: "23" + speed: "100G" + sysport: "189" + type: "eth" + - fec: "KRFEC" + id: "177" + lanes: "0:4" + serdes_group: "22" + speed: "100G" + sysport: "177" + type: "eth" + - fec: "KRFEC" + id: "181" + lanes: "4:4" + serdes_group: "22" + speed: "100G" + sysport: "181" + type: "eth" + - fec: "KRFEC" + id: "169" + lanes: "0:4" + serdes_group: "21" + speed: "100G" + sysport: "169" + type: "eth" + - fec: "KRFEC" + id: "173" + lanes: "4:4" + serdes_group: "21" + speed: "100G" + sysport: "173" + type: "eth" + - fec: "KRFEC" + id: "161" + lanes: "0:4" + serdes_group: "20" + speed: "100G" + sysport: "161" + type: "eth" + - fec: "KRFEC" + id: "165" + lanes: "4:4" + serdes_group: "20" + speed: "100G" + sysport: "165" + type: "eth" + - fec: "KRFEC" + id: "153" + lanes: "0:4" + serdes_group: "19" + speed: "100G" + sysport: "153" + type: "eth" + - fec: "KRFEC" + id: "157" + lanes: "4:4" + serdes_group: "19" + speed: "100G" + sysport: "157" + type: "eth" + - fec: "KRFEC" + id: "145" + lanes: "0:4" + serdes_group: "18" + speed: "100G" + sysport: "145" + type: "eth" + - fec: "KRFEC" + id: "149" + lanes: "4:4" + serdes_group: "18" + speed: "100G" + sysport: "149" + type: "eth" + - fec: "KRFEC" + id: "137" + lanes: "0:4" + serdes_group: "17" + speed: "100G" + sysport: "137" + type: "eth" + - fec: "KRFEC" + id: "141" + lanes: "4:4" + serdes_group: "17" + speed: "100G" + sysport: "141" + type: "eth" + - fec: "KRFEC" + id: "129" + lanes: "0:4" + serdes_group: "16" + speed: "100G" + sysport: "129" + type: "eth" + - fec: "KRFEC" + id: "133" + lanes: "4:4" + serdes_group: "16" + speed: "100G" + sysport: "133" + type: "eth" + - fec: "KRFEC" + id: "121" + lanes: "0:4" + serdes_group: "15" + speed: "100G" + sysport: "121" + type: "eth" + - fec: "KRFEC" + id: "125" + lanes: "4:4" + serdes_group: "15" + speed: "100G" + sysport: "125" + type: "eth" + - fec: "KRFEC" + id: "113" + lanes: "0:4" + serdes_group: "14" + speed: "100G" + sysport: "113" + type: "eth" + - fec: "KRFEC" + id: "117" + lanes: "4:4" + serdes_group: "14" + speed: "100G" + sysport: "117" + type: "eth" + - fec: "KRFEC" + id: "97" + lanes: "0:4" + serdes_group: "12" + speed: "100G" + sysport: "97" + type: "eth" + - fec: "KRFEC" + id: "101" + lanes: "4:4" + serdes_group: "12" + speed: "100G" + sysport: "101" + type: "eth" + - fec: "KRFEC" + id: "105" + lanes: "0:4" + serdes_group: "13" + speed: "100G" + sysport: "105" + type: "eth" + - fec: "KRFEC" + id: "109" + lanes: "4:4" + serdes_group: "13" + speed: "100G" + sysport: "109" + type: "eth" + - fec: "KRFEC" + id: "81" + lanes: "0:4" + serdes_group: "10" + speed: "100G" + sysport: "81" + type: "eth" + - fec: "KRFEC" + id: "85" + lanes: "4:4" + serdes_group: "10" + speed: "100G" + sysport: "85" + type: "eth" + - fec: "KRFEC" + id: "89" + lanes: "0:4" + serdes_group: "11" + speed: "100G" + sysport: "89" + type: "eth" + - fec: "KRFEC" + id: "93" + lanes: "4:4" + serdes_group: "11" + speed: "100G" + sysport: "93" + type: "eth" + - fec: "KRFEC" + id: "65" + lanes: "0:4" + serdes_group: "8" + speed: "100G" + sysport: "65" + type: "eth" + - fec: "KRFEC" + id: "69" + lanes: "4:4" + serdes_group: "8" + speed: "100G" + sysport: "69" + type: "eth" + - fec: "KRFEC" + id: "73" + lanes: "0:4" + serdes_group: "9" + speed: "100G" + sysport: "73" + type: "eth" + - fec: "KRFEC" + id: "77" + lanes: "4:4" + serdes_group: "9" + speed: "100G" + sysport: "77" + type: "eth" + - fec: "KRFEC" + id: "49" + lanes: "0:4" + serdes_group: "6" + speed: "100G" + sysport: "49" + type: "eth" + - fec: "KRFEC" + id: "53" + lanes: "4:4" + serdes_group: "6" + speed: "100G" + sysport: "53" + type: "eth" + - fec: "KRFEC" + id: "57" + lanes: "0:4" + serdes_group: "7" + speed: "100G" + sysport: "57" + type: "eth" + - fec: "KRFEC" + id: "61" + lanes: "4:4" + serdes_group: "7" + speed: "100G" + sysport: "61" + type: "eth" + - fec: "KRFEC" + id: "33" + lanes: "0:4" + serdes_group: "4" + speed: "100G" + sysport: "33" + type: "eth" + - fec: "KRFEC" + id: "37" + lanes: "4:4" + serdes_group: "4" + speed: "100G" + sysport: "37" + type: "eth" + - fec: "KRFEC" + id: "41" + lanes: "0:4" + serdes_group: "5" + speed: "100G" + sysport: "41" + type: "eth" + - fec: "KRFEC" + id: "45" + lanes: "4:4" + serdes_group: "5" + speed: "100G" + sysport: "45" + type: "eth" + - fec: "KRFEC" + id: "17" + lanes: "0:4" + serdes_group: "2" + speed: "100G" + sysport: "17" + type: "eth" + - fec: "KRFEC" + id: "21" + lanes: "4:4" + serdes_group: "2" + speed: "100G" + sysport: "21" + type: "eth" + - fec: "KRFEC" + id: "25" + lanes: "0:4" + serdes_group: "3" + speed: "100G" + sysport: "25" + type: "eth" + - fec: "KRFEC" + id: "29" + lanes: "4:4" + serdes_group: "3" + speed: "100G" + sysport: "29" + type: "eth" + - fec: "KRFEC" + id: "1" + lanes: "0:4" + serdes_group: "0" + speed: "100G" + sysport: "1" + type: "eth" + - fec: "KRFEC" + id: "5" + lanes: "4:4" + serdes_group: "0" + speed: "100G" + sysport: "5" + type: "eth" + - fec: "KRFEC" + id: "9" + lanes: "0:4" + serdes_group: "1" + speed: "100G" + sysport: "9" + type: "eth" + - fec: "KRFEC" + id: "13" + lanes: "4:4" + serdes_group: "1" + speed: "100G" + sysport: "13" + type: "eth" + - fec: "NONE" + id: "257" + lanes: "0:1" + serdes_group: "32" + speed: "10G" + sysport: "257" + type: "mgmt 0" + - fec: "NONE" + id: "258" + lanes: "1:1" + serdes_group: "32" + speed: "10G" + sysport: "258" + type: "mgmt 1" + isg: + - id: "0" + tx_polarity: "01010101" + rx_polarity: "01100000" + lane_swap: "23641075" + - id: "1" + tx_polarity: "10110000" + rx_polarity: "11111111" + lane_swap: "64317520" + - id: "2" + tx_polarity: "00000000" + rx_polarity: "00000011" + lane_swap: "63147520" + - id: "3" + tx_polarity: "01101000" + rx_polarity: "00001110" + lane_swap: "31572046" + - id: "4" + tx_polarity: "00111000" + rx_polarity: "00001000" + lane_swap: "46105732" + - id: "5" + tx_polarity: "10111111" + rx_polarity: "11101000" + lane_swap: "27153604" + - id: "6" + tx_polarity: "01101110" + rx_polarity: "00001101" + lane_swap: "46503721" + - id: "7" + tx_polarity: "01000100" + rx_polarity: "10000101" + lane_swap: "03671245" + - id: "8" + tx_polarity: "01110101" + rx_polarity: "00010000" + lane_swap: "12640375" + - id: "9" + tx_polarity: "01011100" + rx_polarity: "11001111" + lane_swap: "02561347" + - id: "10" + tx_polarity: "01110110" + rx_polarity: "11000000" + lane_swap: "12740365" + - id: "11" + tx_polarity: "00111000" + rx_polarity: "00010111" + lane_swap: "01572436" + - id: "12" + tx_polarity: "00001111" + rx_polarity: "10111001" + lane_swap: "54320176" + - id: "13" + tx_polarity: "10011101" + rx_polarity: "00111011" + lane_swap: "26153704" + - id: "14" + tx_polarity: "00110000" + rx_polarity: "11010000" + lane_swap: "37452601" + - id: "15" + tx_polarity: "11100010" + rx_polarity: "01110011" + lane_swap: "51370462" + - id: "16" + tx_polarity: "10111010" + rx_polarity: "11010011" + lane_swap: "36152704" + - id: "17" + tx_polarity: "01011101" + rx_polarity: "00110001" + lane_swap: "45621073" + - id: "18" + tx_polarity: "11011111" + rx_polarity: "11001011" + lane_swap: "26143705" + - id: "19" + tx_polarity: "00100110" + rx_polarity: "00001001" + lane_swap: "42730165" + - id: "20" + tx_polarity: "10011011" + rx_polarity: "01101101" + lane_swap: "54217603" + - id: "21" + tx_polarity: "00101110" + rx_polarity: "10111111" + lane_swap: "26031745" + - id: "22" + tx_polarity: "01001110" + rx_polarity: "00111001" + lane_swap: "36024715" + - id: "23" + tx_polarity: "10101101" + rx_polarity: "01010011" + lane_swap: "45621370" + - id: "24" + tx_polarity: "11001110" + rx_polarity: "00011111" + lane_swap: "65234701" + - id: "25" + tx_polarity: "01110001" + rx_polarity: "01010111" + lane_swap: "37601452" + - id: "26" + tx_polarity: "01000100" + rx_polarity: "00001111" + lane_swap: "65034721" + - id: "27" + tx_polarity: "10111101" + rx_polarity: "11000101" + lane_swap: "34501672" + - id: "28" + tx_polarity: "01111000" + rx_polarity: "01110110" + lane_swap: "43061275" + - id: "29" + tx_polarity: "11110111" + rx_polarity: "11100111" + lane_swap: "57304621" + - id: "30" + tx_polarity: "10000100" + rx_polarity: "00101111" + lane_swap: "47125603" + - id: "31" + tx_polarity: "11111111" + rx_polarity: "11100010" + lane_swap: "13460275" + - id: "32" + tx_polarity: "00000000" + rx_polarity: "00000000" + lane_swap: "01234567" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/inno.config.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/inno.config.yaml new file mode 100755 index 000000000000..d44c7bc0bc28 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_64x100G_Delta-et-c032if.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/innovium.77700_B b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/port_config.ini b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/port_config.ini new file mode 100644 index 000000000000..9999a677da49 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/port_config.ini @@ -0,0 +1,67 @@ +# name lanes speed index mtu +Ethernet0 249,250,251,252 100000 0 9126 +Ethernet4 253,254,255,256 100000 0 9126 +Ethernet8 241,242,243,244 100000 1 9126 +Ethernet12 245,246,247,248 100000 1 9126 +Ethernet16 233,234,235,236 100000 2 9126 +Ethernet20 237,238,239,240 100000 2 9126 +Ethernet24 225,226,227,228 100000 3 9126 +Ethernet28 229,230,231,232 100000 3 9126 +Ethernet32 217,218,219,220 100000 4 9126 +Ethernet36 221,222,223,224 100000 4 9126 +Ethernet40 209,210,211,212 100000 5 9126 +Ethernet44 213,214,215,216 100000 5 9126 +Ethernet48 201,202,203,204 100000 6 9126 +Ethernet52 205,206,207,208 100000 6 9126 +Ethernet56 193,194,195,196 100000 7 9126 +Ethernet60 197,198,199,200 100000 7 9126 +Ethernet64 185,186,187,188 100000 8 9126 +Ethernet68 189,190,191,192 100000 8 9126 +Ethernet72 177,178,179,180 100000 9 9126 +Ethernet76 181,182,183,184 100000 9 9126 +Ethernet80 169,170,171,172 100000 10 9126 +Ethernet84 173,174,175,176 100000 10 9126 +Ethernet88 161,162,163,164 100000 11 9126 +Ethernet92 165,166,167,168 100000 11 9126 +Ethernet96 153,154,155,156 100000 12 9126 +Ethernet100 157,158,159,160 100000 12 9126 +Ethernet104 145,146,147,148 100000 13 9126 +Ethernet108 149,150,151,152 100000 13 9126 +Ethernet112 137,138,139,140 100000 14 9126 +Ethernet116 141,142,143,144 100000 14 9126 +Ethernet120 129,130,131,132 100000 15 9126 +Ethernet124 133,134,135,136 100000 15 9126 +Ethernet128 121,122,123,124 100000 16 9126 +Ethernet132 125,126,127,128 100000 16 9126 +Ethernet136 113,114,115,116 100000 17 9126 +Ethernet140 117,118,119,120 100000 17 9126 +Ethernet144 97,98,99,100 100000 18 9126 +Ethernet148 101,102,103,104 100000 18 9126 +Ethernet152 105,106,107,108 100000 19 9126 +Ethernet156 109,110,111,112 100000 19 9126 +Ethernet160 81,82,83,84 100000 20 9126 +Ethernet164 85,86,87,88 100000 20 9126 +Ethernet168 89,90,91,92 100000 21 9126 +Ethernet172 93,94,95,96 100000 21 9126 +Ethernet176 65,66,67,68 100000 22 9126 +Ethernet180 69,70,71,72 100000 22 9126 +Ethernet184 73,74,75,76 100000 23 9126 +Ethernet188 77,78,79,80 100000 23 9126 +Ethernet192 49,50,51,52 100000 24 9126 +Ethernet196 53,54,55,56 100000 24 9126 +Ethernet200 57,58,59,60 100000 25 9126 +Ethernet204 61,62,63,64 100000 25 9126 +Ethernet208 33,34,35,36 100000 26 9126 +Ethernet212 37,38,39,40 100000 26 9126 +Ethernet216 41,42,43,44 100000 27 9126 +Ethernet220 45,46,47,48 100000 27 9126 +Ethernet224 17,18,19,20 100000 28 9126 +Ethernet228 21,22,23,24 100000 28 9126 +Ethernet232 25,26,27,28 100000 29 9126 +Ethernet236 29,30,31,32 100000 29 9126 +Ethernet240 1,2,3,4 100000 30 9126 +Ethernet244 5,6,7,8 100000 30 9126 +Ethernet248 9,10,11,12 100000 31 9126 +Ethernet252 13,14,15,16 100000 31 9126 +Ethernet256 257 10000 32 9126 +Ethernet257 258 10000 33 9126 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/qos.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/qos.json.j2 new file mode 100755 index 000000000000..16f9b42a2166 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 64 -%} +{# 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*4)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/sai.profile b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x100/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/buffers.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/buffers.json.j2 new file mode 100644 index 000000000000..45cebf3b7144 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/buffers.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_ports_num = 64 -%} + +{# 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*4)) %}{% 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(',') -%} + +{ + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "47218432", + "type": "ingress", + "mode": "dynamic", + "xoff": "17708800" + }, + "egress_lossy_pool": { + "size": "18874368", + "type": "egress", + "mode": "dynamic", + "xoff": "0" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xoff":"1433600", + "size":"1518", + "dynamic_th":"-4", + "xon_offset":"6272" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "static_th":"9721600" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|4-5": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "{{ port_names }}|0-3": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "{{ port_names }}|6-7": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/config_64x200G_Delta-et-c032if.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/config_64x200G_Delta-et-c032if.yaml new file mode 100755 index 000000000000..4b75a205ab5c --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/config_64x200G_Delta-et-c032if.yaml @@ -0,0 +1,653 @@ +ifcs: + options: + log_level: "info" +nodes: +- node_id: "0" + options: + sku: "configs/sku/innovium.77700_B" + netdev: + - auto_create: "no" + multi_interface: "yes" + buffer_management_mode: "api_driven" + max_lossless_tc: "2" + txring: + - txring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + - txring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + rxring: + - rxring_id: "0" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44" + - rxring_id: "1" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45" + - rxring_id: "2" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46" + - rxring_id: "3" + desc_count: "1024" + prio: "1" + netdev: "true" + queues: "3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47" + sys_clk: "1720" + ifc_clk: "1200" + mac_clk: "1340" + + devports: + - id: "0" + sysport: "1000" + type: "cpu" + - fec: "KPFEC" + id: "249" + lanes: "0:4" + serdes_group: "31" + speed: "200G" + sysport: "249" + type: "eth" + - fec: "KPFEC" + id: "253" + lanes: "4:4" + serdes_group: "31" + speed: "200G" + sysport: "253" + type: "eth" + - fec: "KPFEC" + id: "241" + lanes: "0:4" + serdes_group: "30" + speed: "200G" + sysport: "241" + type: "eth" + - fec: "KPFEC" + id: "245" + lanes: "4:4" + serdes_group: "30" + speed: "200G" + sysport: "245" + type: "eth" + - fec: "KPFEC" + id: "233" + lanes: "0:4" + serdes_group: "29" + speed: "200G" + sysport: "233" + type: "eth" + - fec: "KPFEC" + id: "237" + lanes: "4:4" + serdes_group: "29" + speed: "200G" + sysport: "237" + type: "eth" + - fec: "KPFEC" + id: "225" + lanes: "0:4" + serdes_group: "28" + speed: "200G" + sysport: "225" + type: "eth" + - fec: "KPFEC" + id: "229" + lanes: "4:4" + serdes_group: "28" + speed: "200G" + sysport: "229" + type: "eth" + - fec: "KPFEC" + id: "217" + lanes: "0:4" + serdes_group: "27" + speed: "200G" + sysport: "217" + type: "eth" + - fec: "KPFEC" + id: "221" + lanes: "4:4" + serdes_group: "27" + speed: "200G" + sysport: "221" + type: "eth" + - fec: "KPFEC" + id: "209" + lanes: "0:4" + serdes_group: "26" + speed: "200G" + sysport: "209" + type: "eth" + - fec: "KPFEC" + id: "213" + lanes: "4:4" + serdes_group: "26" + speed: "200G" + sysport: "213" + type: "eth" + - fec: "KPFEC" + id: "201" + lanes: "0:4" + serdes_group: "25" + speed: "200G" + sysport: "201" + type: "eth" + - fec: "KPFEC" + id: "205" + lanes: "4:4" + serdes_group: "25" + speed: "200G" + sysport: "205" + type: "eth" + - fec: "KPFEC" + id: "193" + lanes: "0:4" + serdes_group: "24" + speed: "200G" + sysport: "193" + type: "eth" + - fec: "KPFEC" + id: "197" + lanes: "4:4" + serdes_group: "24" + speed: "200G" + sysport: "197" + type: "eth" + - fec: "KPFEC" + id: "185" + lanes: "0:4" + serdes_group: "23" + speed: "200G" + sysport: "185" + type: "eth" + - fec: "KPFEC" + id: "189" + lanes: "4:4" + serdes_group: "23" + speed: "200G" + sysport: "189" + type: "eth" + - fec: "KPFEC" + id: "177" + lanes: "0:4" + serdes_group: "22" + speed: "200G" + sysport: "177" + type: "eth" + - fec: "KPFEC" + id: "181" + lanes: "4:4" + serdes_group: "22" + speed: "200G" + sysport: "181" + type: "eth" + - fec: "KPFEC" + id: "169" + lanes: "0:4" + serdes_group: "21" + speed: "200G" + sysport: "169" + type: "eth" + - fec: "KPFEC" + id: "173" + lanes: "4:4" + serdes_group: "21" + speed: "200G" + sysport: "173" + type: "eth" + - fec: "KPFEC" + id: "161" + lanes: "0:4" + serdes_group: "20" + speed: "200G" + sysport: "161" + type: "eth" + - fec: "KPFEC" + id: "165" + lanes: "4:4" + serdes_group: "20" + speed: "200G" + sysport: "165" + type: "eth" + - fec: "KPFEC" + id: "153" + lanes: "0:4" + serdes_group: "19" + speed: "200G" + sysport: "153" + type: "eth" + - fec: "KPFEC" + id: "157" + lanes: "4:4" + serdes_group: "19" + speed: "200G" + sysport: "157" + type: "eth" + - fec: "KPFEC" + id: "145" + lanes: "0:4" + serdes_group: "18" + speed: "200G" + sysport: "145" + type: "eth" + - fec: "KPFEC" + id: "149" + lanes: "4:4" + serdes_group: "18" + speed: "200G" + sysport: "149" + type: "eth" + - fec: "KPFEC" + id: "137" + lanes: "0:4" + serdes_group: "17" + speed: "200G" + sysport: "137" + type: "eth" + - fec: "KPFEC" + id: "141" + lanes: "4:4" + serdes_group: "17" + speed: "200G" + sysport: "141" + type: "eth" + - fec: "KPFEC" + id: "129" + lanes: "0:4" + serdes_group: "16" + speed: "200G" + sysport: "129" + type: "eth" + - fec: "KPFEC" + id: "133" + lanes: "4:4" + serdes_group: "16" + speed: "200G" + sysport: "133" + type: "eth" + - fec: "KPFEC" + id: "121" + lanes: "0:4" + serdes_group: "15" + speed: "200G" + sysport: "121" + type: "eth" + - fec: "KPFEC" + id: "125" + lanes: "4:4" + serdes_group: "15" + speed: "200G" + sysport: "125" + type: "eth" + - fec: "KPFEC" + id: "113" + lanes: "0:4" + serdes_group: "14" + speed: "200G" + sysport: "113" + type: "eth" + - fec: "KPFEC" + id: "117" + lanes: "4:4" + serdes_group: "14" + speed: "200G" + sysport: "117" + type: "eth" + - fec: "KPFEC" + id: "97" + lanes: "0:4" + serdes_group: "12" + speed: "200G" + sysport: "97" + type: "eth" + - fec: "KPFEC" + id: "101" + lanes: "4:4" + serdes_group: "12" + speed: "200G" + sysport: "101" + type: "eth" + - fec: "KPFEC" + id: "105" + lanes: "0:4" + serdes_group: "13" + speed: "200G" + sysport: "105" + type: "eth" + - fec: "KPFEC" + id: "109" + lanes: "4:4" + serdes_group: "13" + speed: "200G" + sysport: "109" + type: "eth" + - fec: "KPFEC" + id: "81" + lanes: "0:4" + serdes_group: "10" + speed: "200G" + sysport: "81" + type: "eth" + - fec: "KPFEC" + id: "85" + lanes: "4:4" + serdes_group: "10" + speed: "200G" + sysport: "85" + type: "eth" + - fec: "KPFEC" + id: "89" + lanes: "0:4" + serdes_group: "11" + speed: "200G" + sysport: "89" + type: "eth" + - fec: "KPFEC" + id: "93" + lanes: "4:4" + serdes_group: "11" + speed: "200G" + sysport: "93" + type: "eth" + - fec: "KPFEC" + id: "65" + lanes: "0:4" + serdes_group: "8" + speed: "200G" + sysport: "65" + type: "eth" + - fec: "KPFEC" + id: "69" + lanes: "4:4" + serdes_group: "8" + speed: "200G" + sysport: "69" + type: "eth" + - fec: "KPFEC" + id: "73" + lanes: "0:4" + serdes_group: "9" + speed: "200G" + sysport: "73" + type: "eth" + - fec: "KPFEC" + id: "77" + lanes: "4:4" + serdes_group: "9" + speed: "200G" + sysport: "77" + type: "eth" + - fec: "KPFEC" + id: "49" + lanes: "0:4" + serdes_group: "6" + speed: "200G" + sysport: "49" + type: "eth" + - fec: "KPFEC" + id: "53" + lanes: "4:4" + serdes_group: "6" + speed: "200G" + sysport: "53" + type: "eth" + - fec: "KPFEC" + id: "57" + lanes: "0:4" + serdes_group: "7" + speed: "200G" + sysport: "57" + type: "eth" + - fec: "KPFEC" + id: "61" + lanes: "4:4" + serdes_group: "7" + speed: "200G" + sysport: "61" + type: "eth" + - fec: "KPFEC" + id: "33" + lanes: "0:4" + serdes_group: "4" + speed: "200G" + sysport: "33" + type: "eth" + - fec: "KPFEC" + id: "37" + lanes: "4:4" + serdes_group: "4" + speed: "200G" + sysport: "37" + type: "eth" + - fec: "KPFEC" + id: "41" + lanes: "0:4" + serdes_group: "5" + speed: "200G" + sysport: "41" + type: "eth" + - fec: "KPFEC" + id: "45" + lanes: "4:4" + serdes_group: "5" + speed: "200G" + sysport: "45" + type: "eth" + - fec: "KPFEC" + id: "17" + lanes: "0:4" + serdes_group: "2" + speed: "200G" + sysport: "17" + type: "eth" + - fec: "KPFEC" + id: "21" + lanes: "4:4" + serdes_group: "2" + speed: "200G" + sysport: "21" + type: "eth" + - fec: "KPFEC" + id: "25" + lanes: "0:4" + serdes_group: "3" + speed: "200G" + sysport: "25" + type: "eth" + - fec: "KPFEC" + id: "29" + lanes: "4:4" + serdes_group: "3" + speed: "200G" + sysport: "29" + type: "eth" + - fec: "KPFEC" + id: "1" + lanes: "0:4" + serdes_group: "0" + speed: "200G" + sysport: "1" + type: "eth" + - fec: "KPFEC" + id: "5" + lanes: "4:4" + serdes_group: "0" + speed: "200G" + sysport: "5" + type: "eth" + - fec: "KPFEC" + id: "9" + lanes: "0:4" + serdes_group: "1" + speed: "200G" + sysport: "9" + type: "eth" + - fec: "KPFEC" + id: "13" + lanes: "4:4" + serdes_group: "1" + speed: "200G" + sysport: "13" + type: "eth" + - fec: "NONE" + id: "257" + lanes: "0:1" + serdes_group: "32" + speed: "10G" + sysport: "257" + type: "mgmt 0" + - fec: "NONE" + id: "258" + lanes: "1:1" + serdes_group: "32" + speed: "10G" + sysport: "258" + type: "mgmt 1" + isg: + - id: "0" + tx_polarity: "01010101" + rx_polarity: "01100000" + lane_swap: "23641075" + - id: "1" + tx_polarity: "10110000" + rx_polarity: "11111111" + lane_swap: "64317520" + - id: "2" + tx_polarity: "00000000" + rx_polarity: "00000011" + lane_swap: "63147520" + - id: "3" + tx_polarity: "01101000" + rx_polarity: "00001110" + lane_swap: "31572046" + - id: "4" + tx_polarity: "00111000" + rx_polarity: "00001000" + lane_swap: "46105732" + - id: "5" + tx_polarity: "10111111" + rx_polarity: "11101000" + lane_swap: "27153604" + - id: "6" + tx_polarity: "01101110" + rx_polarity: "00001101" + lane_swap: "46503721" + - id: "7" + tx_polarity: "01000100" + rx_polarity: "10000101" + lane_swap: "03671245" + - id: "8" + tx_polarity: "01110101" + rx_polarity: "00010000" + lane_swap: "12640375" + - id: "9" + tx_polarity: "01011100" + rx_polarity: "11001111" + lane_swap: "02561347" + - id: "10" + tx_polarity: "01110110" + rx_polarity: "11000000" + lane_swap: "12740365" + - id: "11" + tx_polarity: "00111000" + rx_polarity: "00010111" + lane_swap: "01572436" + - id: "12" + tx_polarity: "00001111" + rx_polarity: "10111001" + lane_swap: "54320176" + - id: "13" + tx_polarity: "10011101" + rx_polarity: "00111011" + lane_swap: "26153704" + - id: "14" + tx_polarity: "00110000" + rx_polarity: "11010000" + lane_swap: "37452601" + - id: "15" + tx_polarity: "11100010" + rx_polarity: "01110011" + lane_swap: "51370462" + - id: "16" + tx_polarity: "10111010" + rx_polarity: "11010011" + lane_swap: "36152704" + - id: "17" + tx_polarity: "01011101" + rx_polarity: "00110001" + lane_swap: "45621073" + - id: "18" + tx_polarity: "11011111" + rx_polarity: "11001011" + lane_swap: "26143705" + - id: "19" + tx_polarity: "00100110" + rx_polarity: "00001001" + lane_swap: "42730165" + - id: "20" + tx_polarity: "10011011" + rx_polarity: "01101101" + lane_swap: "54217603" + - id: "21" + tx_polarity: "00101110" + rx_polarity: "10111111" + lane_swap: "26031745" + - id: "22" + tx_polarity: "01001110" + rx_polarity: "00111001" + lane_swap: "36024715" + - id: "23" + tx_polarity: "10101101" + rx_polarity: "01010011" + lane_swap: "45621370" + - id: "24" + tx_polarity: "11001110" + rx_polarity: "00011111" + lane_swap: "65234701" + - id: "25" + tx_polarity: "01110001" + rx_polarity: "01010111" + lane_swap: "37601452" + - id: "26" + tx_polarity: "01000100" + rx_polarity: "00001111" + lane_swap: "65034721" + - id: "27" + tx_polarity: "10111101" + rx_polarity: "11000101" + lane_swap: "34501672" + - id: "28" + tx_polarity: "01111000" + rx_polarity: "01110110" + lane_swap: "43061275" + - id: "29" + tx_polarity: "11110111" + rx_polarity: "11100111" + lane_swap: "57304621" + - id: "30" + tx_polarity: "10000100" + rx_polarity: "00101111" + lane_swap: "47125603" + - id: "31" + tx_polarity: "11111111" + rx_polarity: "11100010" + lane_swap: "13460275" + - id: "32" + tx_polarity: "00000000" + rx_polarity: "00000000" + lane_swap: "01234567" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/inno.config.yaml b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/inno.config.yaml new file mode 100755 index 000000000000..f68930c37ef4 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/inno.config.yaml @@ -0,0 +1,7 @@ +IFCS_INIT_FILE : "/usr/share/sonic/hwsku/config_64x200G_Delta-et-c032if.yaml" +IFCS_SKU_FILE : "/usr/share/sonic/hwsku/innovium.77700_B" +IFCS_INNO_CLI_PORT : "9999" +IFCS_TARGET : "device" +ULIMIT : "65536" +INNOVIUM_DIR : "/innovium" +PYTHONPATH : "$INNOVIUM_DIR:$INNOVIUM_DIR/cmds:$INNOVIUM_DIR/scripts:$INNOVIUM_DIR/test/:$INNOVIUM_DIR/test/utils:$INNOVIUM_DIR/utils:$INNOVIUM_DIR/pyctypes" diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/innovium.77700_B b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/innovium.77700_B new file mode 100644 index 000000000000..27297b313959 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/innovium.77700_B @@ -0,0 +1,59 @@ +sku: innovium.77700_B + +device_id: 0x1b58 + +# Hardware constraint information +hardware: + num_ibs: 6 + + ports_per_ib: 32, 32, 32, 32, 20, 20 + recirc_port_num: 32, 32, 32, 32, 32, 32 + cpu_port_num: 33 + cpu_port_ib: 0 + mgmt_port_num: 33 + mgmt_port_ibs: 1,2 + + pics_per_ib: 6, 7, 7, 6, 5, 5 + pic_ports_per_pic: 8 + max_serdes_speed: 50 + + num_shared_pics: 2 + + isg [0-4]: + ib: 0 + pic_id: [0-4] + + isg [5-9]: + ib: 5 + pic_id: [0-4] + + isg [10-14]: + ib: 1 + pic_id: [0-4] + + isg [16-20]: + ib: 3 + pic_id: [0-4] + + isg [21-25]: + ib: 4 + pic_id: [0-4] + + isg [26-30]: + ib: 2 + pic_id: [0-4] + + isg 15: + mode: 4:4 + ib: 1, 3 + pic_id: 5 + + isg 31: + mode: 4:4 + ib: 0, 2 + pic_id: 5 + + isg 32: + mode: 1:1 + ib: 1, 2 + pic_id: 6 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/port_config.ini b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/port_config.ini new file mode 100644 index 000000000000..726e1a377d83 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/port_config.ini @@ -0,0 +1,67 @@ +# name lanes speed index mtu +Ethernet0 249,250,251,252 200000 0 9126 +Ethernet4 253,254,255,256 200000 0 9126 +Ethernet8 241,242,243,244 200000 1 9126 +Ethernet12 245,246,247,248 200000 1 9126 +Ethernet16 233,234,235,236 200000 2 9126 +Ethernet20 237,238,239,240 200000 2 9126 +Ethernet24 225,226,227,228 200000 3 9126 +Ethernet28 229,230,231,232 200000 3 9126 +Ethernet32 217,218,219,220 200000 4 9126 +Ethernet36 221,222,223,224 200000 4 9126 +Ethernet40 209,210,211,212 200000 5 9126 +Ethernet44 213,214,215,216 200000 5 9126 +Ethernet48 201,202,203,204 200000 6 9126 +Ethernet52 205,206,207,208 200000 6 9126 +Ethernet56 193,194,195,196 200000 7 9126 +Ethernet60 197,198,199,200 200000 7 9126 +Ethernet64 185,186,187,188 200000 8 9126 +Ethernet68 189,190,191,192 200000 8 9126 +Ethernet72 177,178,179,180 200000 9 9126 +Ethernet76 181,182,183,184 200000 9 9126 +Ethernet80 169,170,171,172 200000 10 9126 +Ethernet84 173,174,175,176 200000 10 9126 +Ethernet88 161,162,163,164 200000 11 9126 +Ethernet92 165,166,167,168 200000 11 9126 +Ethernet96 153,154,155,156 200000 12 9126 +Ethernet100 157,158,159,160 200000 12 9126 +Ethernet104 145,146,147,148 200000 13 9126 +Ethernet108 149,150,151,152 200000 13 9126 +Ethernet112 137,138,139,140 200000 14 9126 +Ethernet116 141,142,143,144 200000 14 9126 +Ethernet120 129,130,131,132 200000 15 9126 +Ethernet124 133,134,135,136 200000 15 9126 +Ethernet128 121,122,123,124 200000 16 9126 +Ethernet132 125,126,127,128 200000 16 9126 +Ethernet136 113,114,115,116 200000 17 9126 +Ethernet140 117,118,119,120 200000 17 9126 +Ethernet144 97,98,99,100 200000 18 9126 +Ethernet148 101,102,103,104 200000 18 9126 +Ethernet152 105,106,107,108 200000 19 9126 +Ethernet156 109,110,111,112 200000 19 9126 +Ethernet160 81,82,83,84 200000 20 9126 +Ethernet164 85,86,87,88 200000 20 9126 +Ethernet168 89,90,91,92 200000 21 9126 +Ethernet172 93,94,95,96 200000 21 9126 +Ethernet176 65,66,67,68 200000 22 9126 +Ethernet180 69,70,71,72 200000 22 9126 +Ethernet184 73,74,75,76 200000 23 9126 +Ethernet188 77,78,79,80 200000 23 9126 +Ethernet192 49,50,51,52 200000 24 9126 +Ethernet196 53,54,55,56 200000 24 9126 +Ethernet200 57,58,59,60 200000 25 9126 +Ethernet204 61,62,63,64 200000 25 9126 +Ethernet208 33,34,35,36 200000 26 9126 +Ethernet212 37,38,39,40 200000 26 9126 +Ethernet216 41,42,43,44 200000 27 9126 +Ethernet220 45,46,47,48 200000 27 9126 +Ethernet224 17,18,19,20 200000 28 9126 +Ethernet228 21,22,23,24 200000 28 9126 +Ethernet232 25,26,27,28 200000 29 9126 +Ethernet236 29,30,31,32 200000 29 9126 +Ethernet240 1,2,3,4 200000 30 9126 +Ethernet244 5,6,7,8 200000 30 9126 +Ethernet248 9,10,11,12 200000 31 9126 +Ethernet252 13,14,15,16 200000 31 9126 +Ethernet256 257 10000 32 9126 +Ethernet257 258 10000 33 9126 diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/qos.json.j2 b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/qos.json.j2 new file mode 100755 index 000000000000..16f9b42a2166 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/qos.json.j2 @@ -0,0 +1,120 @@ +{# Default values which will be used if no actual configura available #} + +{% set default_ports_num = 64 -%} +{# 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*4)) %}{% 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(',') -%} + + +{ + "TC_TO_QUEUE_MAP":{ + "AZURE":{ + "1":"1", + "0":"0", + "3":"3", + "2":"2", + "5":"5", + "4":"4", + "7":"7", + "6":"6" + } + }, + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "1": "0", + "0": "0", + "3": "0", + "2": "0", + "4": "1", + "5": "2", + "6": "0", + "7": "0" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"0", + "4":"4", + "5":"5", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "PORT_QOS_MAP": { + "{{ port_names }}": { + "tc_to_pg_map": "[TC_TO_PRIORITY_GROUP_MAP:AZURE]", + "tc_to_queue_map": "[TC_TO_QUEUE_MAP:AZURE]", + "dscp_to_tc_map": "[DSCP_TO_TC_MAP:AZURE]", + "pfc_enable": "4,5" + } + } +} diff --git a/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/sai.profile b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/sai.profile new file mode 100755 index 000000000000..0769b3063a12 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/Delta-et-c032if_64x200/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/inno.config.yaml diff --git a/device/delta/x86_64-delta_et-c032if-r0/default_sku b/device/delta/x86_64-delta_et-c032if-r0/default_sku new file mode 100644 index 000000000000..92740942d0e9 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/default_sku @@ -0,0 +1 @@ +Delta-et-c032if t1 diff --git a/device/delta/x86_64-delta_et-c032if-r0/installer.conf b/device/delta/x86_64-delta_et-c032if-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/delta/x86_64-delta_et-c032if-r0/led_proc_init.soc b/device/delta/x86_64-delta_et-c032if-r0/led_proc_init.soc new file mode 100644 index 000000000000..4173de277f6b --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/led_proc_init.soc @@ -0,0 +1,10 @@ +#ET_C032IF Port_Remap +# Vlan set and port enable + +# led0 port order remap + +#ET_C032IF_LED + +#-------------------------------------------------------------------------------------------------- +#LED Auto link/up + diff --git a/device/delta/x86_64-delta_et-c032if-r0/plugins/eeprom.py b/device/delta/x86_64-delta_et-c032if-r0/plugins/eeprom.py new file mode 100644 index 000000000000..23376fcd7236 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/plugins/eeprom.py @@ -0,0 +1,30 @@ +############################################################################# +# Mellanox +# +# 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 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 as 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/devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-10/10-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/delta/x86_64-delta_et-c032if-r0/plugins/psuutil.py b/device/delta/x86_64-delta_et-c032if-r0/plugins/psuutil.py new file mode 100644 index 000000000000..4eb3bb87db80 --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/plugins/psuutil.py @@ -0,0 +1,76 @@ +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# + +import os.path +import subprocess + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + self.psu_status = "ipmitool raw 0x38 0x1 {} 0x50" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + p = os.popen("ipmitool raw 0x38 0x2 7 0x32 0x28 1") + content = p.readline().rstrip() + reg_value = int(content, 16) + mask = (1 << (8 - index)) + if reg_value & mask == 0: + return False + status = 1 + p.close() + except IOError: + return False + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + status = 0 + try: + p = os.popen(self.psu_status.format(index - 1)) + content = p.readline().rstrip() + reg_value = int(content, 16) + if reg_value != 0: + return False + status = 1 + p.close() + except IOError: + return False + return status == 1 diff --git a/device/delta/x86_64-delta_et-c032if-r0/plugins/sfputil.py b/device/delta/x86_64-delta_et-c032if-r0/plugins/sfputil.py new file mode 100644 index 000000000000..25b1ba3abdeb --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/plugins/sfputil.py @@ -0,0 +1,254 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import datetime + 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 = 0 + PORT_START_SFP = 32 + PORT_END = 33 + PORTS_IN_BLOCK = 34 + + EEPROM_OFFSET = 1 + + _port_to_eeprom_mapping = {} + port_dict = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_start_sfp(self): + return self.PORT_START_SFP + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def get_transceiver_status(self): + + try: + reg_file = open("/sys/devices/platform/delta-et-c032if-cpld.0/sfp_is_present") + + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + reg_file.close() + + return int(content, 16) + + def __init__(self): + eeprom_path = "/sys/kernel/sfp/eeprom_sfp_{0}" + + for x in range(0, self.port_end + 1): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + self.modprs_register = self.get_transceiver_status + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/delta-et-c032if-cpld.0/sfp_is_present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (self.port_end - port_num + 6)) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end - 2: + return False + + try: + reg_file = open("/sys/devices/platform/delta-et-c032if-cpld.0/sfp_lp_mode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (self.port_end - port_num) - 2) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end - 2: + return False + + try: + reg_file = open("/sys/devices/platform/delta-et-c032if-cpld.0/sfp_lp_mode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (self.port_end - port_num) - 2) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value).rstrip("L") or "0" + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/delta-et-c032if-cpld.0/sfp_reset" + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end - 2: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (self.port_end - port_num) - 2) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def get_transceiver_change_event(self, timeout=0): + start_time = time.time() + port_dict = {} + port = self.port_start + forever = False + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print('get_transceiver_change_event:' + 'time wrap / invalid timeout value', timeout) + + return False, {} # Time wrap or possibly incorrect timeout + while timeout >= 0: + # Check for OIR events and return updated port_dict + reg_value = self.get_transceiver_status + if reg_value != self.modprs_register: + changed_ports = self.modprs_register ^ reg_value + while port >= self.port_start and port <= self.port_end: + + # Mask off the bit corresponding to our port + mask = (1 << (self.port_end - port + 6)) + + if changed_ports & mask: + # ModPrsL is active low + if reg_value & mask == 0: + port_dict[port] = '1' + else: + port_dict[port] = '0' + + port += 1 + + # Update reg value + self.modprs_register = reg_value + return True, port_dict + + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + print("get_transceiver_change_event: Should not reach here.") + return False, {} diff --git a/device/delta/x86_64-delta_et-c032if-r0/sensors.conf b/device/delta/x86_64-delta_et-c032if-r0/sensors.conf new file mode 100644 index 000000000000..db34a541b26f --- /dev/null +++ b/device/delta/x86_64-delta_et-c032if-r0/sensors.conf @@ -0,0 +1,4 @@ +# libsensors configuration file for DELTA-ET-C032IF +# ------------------------------------------------ +# + diff --git a/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/port_config.ini b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/port_config.ini new file mode 100644 index 000000000000..973e47589aaa --- /dev/null +++ b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 117,118,119,120 +Ethernet4 113,114,115,116 +Ethernet8 125,126,127,128 +Ethernet12 121,122,123,124 +Ethernet16 5,6,7,8 +Ethernet20 1,2,3,4 +Ethernet24 13,14,15,16 +Ethernet28 9,10,11,12 +Ethernet32 21,22,23,24 +Ethernet36 17,18,19,20 +Ethernet40 29,30,31,32 +Ethernet44 25,26,27,28 +Ethernet48 37,38,39,40 +Ethernet52 33,34,35,36 +Ethernet56 45,46,47,48 +Ethernet60 41,42,43,44 +Ethernet64 53,54,55,56 +Ethernet68 49,50,51,52 +Ethernet72 61,62,63,64 +Ethernet76 57,58,59,60 +Ethernet80 69,70,71,72 +Ethernet84 65,66,67,68 +Ethernet88 77,78,79,80 +Ethernet92 73,74,75,76 +Ethernet96 85,86,87,88 +Ethernet100 81,82,83,84 +Ethernet104 93,94,95,96 +Ethernet108 89,90,91,92 +Ethernet112 101,102,103,104 +Ethernet116 97,98,99,100 +Ethernet120 109,110,111,112 +Ethernet124 105,106,107,108 diff --git a/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/sai.profile b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/sai.profile new file mode 100644 index 000000000000..426284150a0d --- /dev/null +++ b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-wedge100-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/th-wedge100-32x100G.config.bcm b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/th-wedge100-32x100G.config.bcm new file mode 100644 index 000000000000..afd1db4cbc02 --- /dev/null +++ b/device/facebook/x86_64-facebook_wedge100-r0/Facebook-W100-C32/th-wedge100-32x100G.config.bcm @@ -0,0 +1,433 @@ +ctr_evict_enable=0x0 +l2_mem_entries=0x8000 +l3_intf_vlan_split_egress=0x1 +l3_mem_entries=0x4000 +mdio_output_delay=0xb +mmu_lossless=0x0 +os=unix +oversubscribe_mode=0x1 +parity_enable=0x1 +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +phy_an_c37=0x3 +phy_an_c73=0x0 +portmap_1=5:100 +portmap_102=101:100 +portmap_106=97:100 +portmap_110=109:100 +portmap_114=105:100 +portmap_118=117:100 +portmap_122=113:100 +portmap_126=125:100 +portmap_13=9:100 +portmap_130=121:100 +portmap_17=21:100 +portmap_21=17:100 +portmap_25=29:100 +portmap_29=25:100 +portmap_34=37:100 +portmap_38=33:100 +portmap_42=45:100 +portmap_46=41:100 +portmap_5=1:100 +portmap_50=53:100 +portmap_54=49:100 +portmap_58=61:100 +portmap_62=57:100 +portmap_68=69:100 +portmap_72=65:100 +portmap_76=77:100 +portmap_80=73:100 +portmap_84=85:100 +portmap_88=81:100 +portmap_9=13:100 +portmap_92=93:100 +portmap_96=89:100 +rate_ext_mdio_divisor=0x65 +serdes_automedium=0x0 +serdes_fiber_pref=0x1 +serdes_firmware_mode_xe=0x2 +serdes_preemphasis_1=0x284008 +serdes_preemphasis_10=0x284008 +serdes_preemphasis_102=0x2c4004 +serdes_preemphasis_103=0x2c4004 +serdes_preemphasis_104=0x2c4004 +serdes_preemphasis_105=0x2c4004 +serdes_preemphasis_106=0x2c4004 +serdes_preemphasis_107=0x2c4004 +serdes_preemphasis_108=0x2c4004 +serdes_preemphasis_109=0x2c4004 +serdes_preemphasis_11=0x284008 +serdes_preemphasis_110=0x303c04 +serdes_preemphasis_111=0x303c04 +serdes_preemphasis_112=0x303c04 +serdes_preemphasis_113=0x303c04 +serdes_preemphasis_114=0x303c04 +serdes_preemphasis_115=0x303c04 +serdes_preemphasis_116=0x303c04 +serdes_preemphasis_117=0x303c04 +serdes_preemphasis_118=0x2c4004 +serdes_preemphasis_119=0x2c4004 +serdes_preemphasis_12=0x284008 +serdes_preemphasis_120=0x2c4004 +serdes_preemphasis_121=0x2c4004 +serdes_preemphasis_122=0x303c04 +serdes_preemphasis_123=0x303c04 +serdes_preemphasis_124=0x303c04 +serdes_preemphasis_125=0x303c04 +serdes_preemphasis_126=0x2c4004 +serdes_preemphasis_127=0x2c4004 +serdes_preemphasis_128=0x2c4004 +serdes_preemphasis_129=0x2c4004 +serdes_preemphasis_13=0x284008 +serdes_preemphasis_130=0x2c4004 +serdes_preemphasis_131=0x2c4004 +serdes_preemphasis_132=0x2c4004 +serdes_preemphasis_133=0x2c4004 +serdes_preemphasis_14=0x284008 +serdes_preemphasis_15=0x284008 +serdes_preemphasis_16=0x284008 +serdes_preemphasis_17=0x205000 +serdes_preemphasis_18=0x205000 +serdes_preemphasis_19=0x205000 +serdes_preemphasis_2=0x284008 +serdes_preemphasis_20=0x205000 +serdes_preemphasis_21=0x284800 +serdes_preemphasis_22=0x284800 +serdes_preemphasis_23=0x284800 +serdes_preemphasis_24=0x284800 +serdes_preemphasis_25=0x205000 +serdes_preemphasis_26=0x205000 +serdes_preemphasis_27=0x205000 +serdes_preemphasis_28=0x205000 +serdes_preemphasis_29=0x205000 +serdes_preemphasis_3=0x284008 +serdes_preemphasis_30=0x205000 +serdes_preemphasis_31=0x205000 +serdes_preemphasis_32=0x205000 +serdes_preemphasis_34=0x205000 +serdes_preemphasis_35=0x205000 +serdes_preemphasis_36=0x205000 +serdes_preemphasis_37=0x205000 +serdes_preemphasis_38=0x205000 +serdes_preemphasis_39=0x205000 +serdes_preemphasis_4=0x284008 +serdes_preemphasis_40=0x205000 +serdes_preemphasis_41=0x205000 +serdes_preemphasis_42=0x205000 +serdes_preemphasis_43=0x205000 +serdes_preemphasis_44=0x205000 +serdes_preemphasis_45=0x205000 +serdes_preemphasis_46=0x205000 +serdes_preemphasis_47=0x205000 +serdes_preemphasis_48=0x205000 +serdes_preemphasis_49=0x205000 +serdes_preemphasis_5=0x284008 +serdes_preemphasis_50=0x205000 +serdes_preemphasis_51=0x205000 +serdes_preemphasis_52=0x205000 +serdes_preemphasis_53=0x205000 +serdes_preemphasis_54=0x205000 +serdes_preemphasis_55=0x205000 +serdes_preemphasis_56=0x205000 +serdes_preemphasis_57=0x205000 +serdes_preemphasis_58=0x205000 +serdes_preemphasis_59=0x205000 +serdes_preemphasis_6=0x284008 +serdes_preemphasis_60=0x205000 +serdes_preemphasis_61=0x205000 +serdes_preemphasis_62=0x205000 +serdes_preemphasis_63=0x205000 +serdes_preemphasis_64=0x205000 +serdes_preemphasis_65=0x205000 +serdes_preemphasis_68=0x205000 +serdes_preemphasis_69=0x205000 +serdes_preemphasis_7=0x284008 +serdes_preemphasis_70=0x205000 +serdes_preemphasis_71=0x205000 +serdes_preemphasis_72=0x205000 +serdes_preemphasis_73=0x205000 +serdes_preemphasis_74=0x205000 +serdes_preemphasis_75=0x205000 +serdes_preemphasis_76=0x284800 +serdes_preemphasis_77=0x284800 +serdes_preemphasis_78=0x284800 +serdes_preemphasis_79=0x284800 +serdes_preemphasis_8=0x284008 +serdes_preemphasis_80=0x205000 +serdes_preemphasis_81=0x205000 +serdes_preemphasis_82=0x205000 +serdes_preemphasis_83=0x205000 +serdes_preemphasis_84=0x284800 +serdes_preemphasis_85=0x284800 +serdes_preemphasis_86=0x284800 +serdes_preemphasis_87=0x284800 +serdes_preemphasis_88=0x284800 +serdes_preemphasis_89=0x284800 +serdes_preemphasis_9=0x284008 +serdes_preemphasis_90=0x284800 +serdes_preemphasis_91=0x284800 +serdes_preemphasis_92=0x284800 +serdes_preemphasis_93=0x284800 +serdes_preemphasis_94=0x284800 +serdes_preemphasis_95=0x284800 +serdes_preemphasis_96=0x284800 +serdes_preemphasis_97=0x284800 +serdes_preemphasis_98=0x284800 +serdes_preemphasis_99=0x284800 +stable_size=0x6000000 +xgxs_rx_lane_map_1=0x3210 +xgxs_rx_lane_map_10=0x3210 +xgxs_rx_lane_map_102=0x123 +xgxs_rx_lane_map_103=0x123 +xgxs_rx_lane_map_104=0x123 +xgxs_rx_lane_map_105=0x123 +xgxs_rx_lane_map_106=0x3210 +xgxs_rx_lane_map_107=0x3210 +xgxs_rx_lane_map_108=0x3210 +xgxs_rx_lane_map_109=0x3210 +xgxs_rx_lane_map_11=0x3210 +xgxs_rx_lane_map_110=0x1032 +xgxs_rx_lane_map_111=0x1032 +xgxs_rx_lane_map_112=0x1032 +xgxs_rx_lane_map_113=0x1032 +xgxs_rx_lane_map_114=0x3210 +xgxs_rx_lane_map_115=0x3210 +xgxs_rx_lane_map_116=0x3210 +xgxs_rx_lane_map_117=0x3210 +xgxs_rx_lane_map_118=0x2301 +xgxs_rx_lane_map_119=0x2301 +xgxs_rx_lane_map_12=0x3210 +xgxs_rx_lane_map_120=0x2301 +xgxs_rx_lane_map_121=0x2301 +xgxs_rx_lane_map_122=0x3210 +xgxs_rx_lane_map_123=0x3210 +xgxs_rx_lane_map_124=0x3210 +xgxs_rx_lane_map_125=0x3210 +xgxs_rx_lane_map_126=0x1032 +xgxs_rx_lane_map_127=0x1032 +xgxs_rx_lane_map_128=0x1032 +xgxs_rx_lane_map_129=0x1032 +xgxs_rx_lane_map_13=0x3210 +xgxs_rx_lane_map_130=0x3210 +xgxs_rx_lane_map_131=0x3210 +xgxs_rx_lane_map_132=0x3210 +xgxs_rx_lane_map_133=0x3210 +xgxs_rx_lane_map_14=0x3210 +xgxs_rx_lane_map_15=0x3210 +xgxs_rx_lane_map_16=0x3210 +xgxs_rx_lane_map_17=0x2301 +xgxs_rx_lane_map_18=0x2301 +xgxs_rx_lane_map_19=0x2301 +xgxs_rx_lane_map_2=0x3210 +xgxs_rx_lane_map_20=0x2301 +xgxs_rx_lane_map_21=0x1032 +xgxs_rx_lane_map_22=0x1032 +xgxs_rx_lane_map_23=0x1032 +xgxs_rx_lane_map_24=0x1032 +xgxs_rx_lane_map_25=0x3210 +xgxs_rx_lane_map_26=0x3210 +xgxs_rx_lane_map_27=0x3210 +xgxs_rx_lane_map_28=0x3210 +xgxs_rx_lane_map_29=0x1032 +xgxs_rx_lane_map_3=0x3210 +xgxs_rx_lane_map_30=0x1032 +xgxs_rx_lane_map_31=0x1032 +xgxs_rx_lane_map_32=0x1032 +xgxs_rx_lane_map_34=0x2301 +xgxs_rx_lane_map_35=0x2301 +xgxs_rx_lane_map_36=0x2301 +xgxs_rx_lane_map_37=0x2301 +xgxs_rx_lane_map_38=0x1032 +xgxs_rx_lane_map_39=0x1032 +xgxs_rx_lane_map_4=0x3210 +xgxs_rx_lane_map_40=0x1032 +xgxs_rx_lane_map_41=0x1032 +xgxs_rx_lane_map_42=0x3210 +xgxs_rx_lane_map_43=0x3210 +xgxs_rx_lane_map_44=0x3210 +xgxs_rx_lane_map_45=0x3210 +xgxs_rx_lane_map_46=0x1032 +xgxs_rx_lane_map_47=0x1032 +xgxs_rx_lane_map_48=0x1032 +xgxs_rx_lane_map_49=0x1032 +xgxs_rx_lane_map_5=0x3210 +xgxs_rx_lane_map_50=0x1032 +xgxs_rx_lane_map_51=0x1032 +xgxs_rx_lane_map_52=0x1032 +xgxs_rx_lane_map_53=0x1032 +xgxs_rx_lane_map_54=0x1032 +xgxs_rx_lane_map_55=0x1032 +xgxs_rx_lane_map_56=0x1032 +xgxs_rx_lane_map_57=0x1032 +xgxs_rx_lane_map_58=0x1032 +xgxs_rx_lane_map_59=0x1032 +xgxs_rx_lane_map_6=0x3210 +xgxs_rx_lane_map_60=0x1032 +xgxs_rx_lane_map_61=0x1032 +xgxs_rx_lane_map_62=0x1032 +xgxs_rx_lane_map_63=0x1032 +xgxs_rx_lane_map_64=0x1032 +xgxs_rx_lane_map_65=0x1032 +xgxs_rx_lane_map_68=0x1032 +xgxs_rx_lane_map_69=0x1032 +xgxs_rx_lane_map_7=0x3210 +xgxs_rx_lane_map_70=0x1032 +xgxs_rx_lane_map_71=0x1032 +xgxs_rx_lane_map_72=0x3210 +xgxs_rx_lane_map_73=0x3210 +xgxs_rx_lane_map_74=0x3210 +xgxs_rx_lane_map_75=0x3210 +xgxs_rx_lane_map_76=0x213 +xgxs_rx_lane_map_77=0x213 +xgxs_rx_lane_map_78=0x213 +xgxs_rx_lane_map_79=0x213 +xgxs_rx_lane_map_8=0x3210 +xgxs_rx_lane_map_80=0x1032 +xgxs_rx_lane_map_81=0x1032 +xgxs_rx_lane_map_82=0x1032 +xgxs_rx_lane_map_83=0x1032 +xgxs_rx_lane_map_84=0x123 +xgxs_rx_lane_map_85=0x123 +xgxs_rx_lane_map_86=0x123 +xgxs_rx_lane_map_87=0x123 +xgxs_rx_lane_map_88=0x3210 +xgxs_rx_lane_map_89=0x3210 +xgxs_rx_lane_map_9=0x3210 +xgxs_rx_lane_map_90=0x3210 +xgxs_rx_lane_map_91=0x3210 +xgxs_rx_lane_map_92=0x1032 +xgxs_rx_lane_map_93=0x1032 +xgxs_rx_lane_map_94=0x1032 +xgxs_rx_lane_map_95=0x1032 +xgxs_rx_lane_map_96=0x3210 +xgxs_rx_lane_map_97=0x3210 +xgxs_rx_lane_map_98=0x3210 +xgxs_rx_lane_map_99=0x3210 +xgxs_tx_lane_map_1=0x3210 +xgxs_tx_lane_map_10=0x3210 +xgxs_tx_lane_map_102=0x3210 +xgxs_tx_lane_map_103=0x3210 +xgxs_tx_lane_map_104=0x3210 +xgxs_tx_lane_map_105=0x3210 +xgxs_tx_lane_map_106=0x1032 +xgxs_tx_lane_map_107=0x1032 +xgxs_tx_lane_map_108=0x1032 +xgxs_tx_lane_map_109=0x1032 +xgxs_tx_lane_map_11=0x3210 +xgxs_tx_lane_map_110=0x3210 +xgxs_tx_lane_map_111=0x3210 +xgxs_tx_lane_map_112=0x3210 +xgxs_tx_lane_map_113=0x3210 +xgxs_tx_lane_map_114=0x1032 +xgxs_tx_lane_map_115=0x1032 +xgxs_tx_lane_map_116=0x1032 +xgxs_tx_lane_map_117=0x1032 +xgxs_tx_lane_map_118=0x3210 +xgxs_tx_lane_map_119=0x3210 +xgxs_tx_lane_map_12=0x3210 +xgxs_tx_lane_map_120=0x3210 +xgxs_tx_lane_map_121=0x3210 +xgxs_tx_lane_map_122=0x1032 +xgxs_tx_lane_map_123=0x1032 +xgxs_tx_lane_map_124=0x1032 +xgxs_tx_lane_map_125=0x1032 +xgxs_tx_lane_map_126=0x1032 +xgxs_tx_lane_map_127=0x1032 +xgxs_tx_lane_map_128=0x1032 +xgxs_tx_lane_map_129=0x1032 +xgxs_tx_lane_map_13=0x3210 +xgxs_tx_lane_map_130=0x3210 +xgxs_tx_lane_map_131=0x3210 +xgxs_tx_lane_map_132=0x3210 +xgxs_tx_lane_map_133=0x3210 +xgxs_tx_lane_map_14=0x3210 +xgxs_tx_lane_map_15=0x3210 +xgxs_tx_lane_map_16=0x3210 +xgxs_tx_lane_map_17=0x1032 +xgxs_tx_lane_map_18=0x1032 +xgxs_tx_lane_map_19=0x1032 +xgxs_tx_lane_map_2=0x3210 +xgxs_tx_lane_map_20=0x1032 +xgxs_tx_lane_map_21=0x3210 +xgxs_tx_lane_map_22=0x3210 +xgxs_tx_lane_map_23=0x3210 +xgxs_tx_lane_map_24=0x3210 +xgxs_tx_lane_map_25=0x1032 +xgxs_tx_lane_map_26=0x1032 +xgxs_tx_lane_map_27=0x1032 +xgxs_tx_lane_map_28=0x1032 +xgxs_tx_lane_map_29=0x3210 +xgxs_tx_lane_map_3=0x3210 +xgxs_tx_lane_map_30=0x3210 +xgxs_tx_lane_map_31=0x3210 +xgxs_tx_lane_map_32=0x3210 +xgxs_tx_lane_map_34=0x1032 +xgxs_tx_lane_map_35=0x1032 +xgxs_tx_lane_map_36=0x1032 +xgxs_tx_lane_map_37=0x1032 +xgxs_tx_lane_map_38=0x3210 +xgxs_tx_lane_map_39=0x3210 +xgxs_tx_lane_map_4=0x3210 +xgxs_tx_lane_map_40=0x3210 +xgxs_tx_lane_map_41=0x3210 +xgxs_tx_lane_map_42=0x1032 +xgxs_tx_lane_map_43=0x1032 +xgxs_tx_lane_map_44=0x1032 +xgxs_tx_lane_map_45=0x1032 +xgxs_tx_lane_map_46=0x3210 +xgxs_tx_lane_map_47=0x3210 +xgxs_tx_lane_map_48=0x3210 +xgxs_tx_lane_map_49=0x3210 +xgxs_tx_lane_map_5=0x3210 +xgxs_tx_lane_map_50=0x1032 +xgxs_tx_lane_map_51=0x1032 +xgxs_tx_lane_map_52=0x1032 +xgxs_tx_lane_map_53=0x1032 +xgxs_tx_lane_map_54=0x1032 +xgxs_tx_lane_map_55=0x1032 +xgxs_tx_lane_map_56=0x1032 +xgxs_tx_lane_map_57=0x1032 +xgxs_tx_lane_map_58=0x1032 +xgxs_tx_lane_map_59=0x1032 +xgxs_tx_lane_map_6=0x3210 +xgxs_tx_lane_map_60=0x1032 +xgxs_tx_lane_map_61=0x1032 +xgxs_tx_lane_map_62=0x1032 +xgxs_tx_lane_map_63=0x1032 +xgxs_tx_lane_map_64=0x1032 +xgxs_tx_lane_map_65=0x1032 +xgxs_tx_lane_map_68=0x1032 +xgxs_tx_lane_map_69=0x1032 +xgxs_tx_lane_map_7=0x3210 +xgxs_tx_lane_map_70=0x1032 +xgxs_tx_lane_map_71=0x1032 +xgxs_tx_lane_map_72=0x3210 +xgxs_tx_lane_map_73=0x3210 +xgxs_tx_lane_map_74=0x3210 +xgxs_tx_lane_map_75=0x3210 +xgxs_tx_lane_map_76=0x3210 +xgxs_tx_lane_map_77=0x3210 +xgxs_tx_lane_map_78=0x3210 +xgxs_tx_lane_map_79=0x3210 +xgxs_tx_lane_map_8=0x3210 +xgxs_tx_lane_map_80=0x1032 +xgxs_tx_lane_map_81=0x1032 +xgxs_tx_lane_map_82=0x1032 +xgxs_tx_lane_map_83=0x1032 +xgxs_tx_lane_map_84=0x3210 +xgxs_tx_lane_map_85=0x3210 +xgxs_tx_lane_map_86=0x3210 +xgxs_tx_lane_map_87=0x3210 +xgxs_tx_lane_map_88=0x1032 +xgxs_tx_lane_map_89=0x1032 +xgxs_tx_lane_map_9=0x3210 +xgxs_tx_lane_map_90=0x1032 +xgxs_tx_lane_map_91=0x1032 +xgxs_tx_lane_map_92=0x3210 +xgxs_tx_lane_map_93=0x3210 +xgxs_tx_lane_map_94=0x3210 +xgxs_tx_lane_map_95=0x3210 +xgxs_tx_lane_map_96=0x1032 +xgxs_tx_lane_map_97=0x1032 +xgxs_tx_lane_map_98=0x1032 +xgxs_tx_lane_map_99=0x1032 diff --git a/device/facebook/x86_64-facebook_wedge100-r0/default_sku b/device/facebook/x86_64-facebook_wedge100-r0/default_sku new file mode 100644 index 000000000000..e8fafcb709da --- /dev/null +++ b/device/facebook/x86_64-facebook_wedge100-r0/default_sku @@ -0,0 +1 @@ +Facebook-W100-C32 t1 diff --git a/device/facebook/x86_64-facebook_wedge100-r0/installer.conf b/device/facebook/x86_64-facebook_wedge100-r0/installer.conf new file mode 100644 index 000000000000..3714ff053bb0 --- /dev/null +++ b/device/facebook/x86_64-facebook_wedge100-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=57600 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/port_config.ini b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/port_config.ini new file mode 100644 index 000000000000..bf87e1402ab1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 37,38,39,40 Ethernet1/1 0 +Ethernet4 33,34,35,36 Ethernet2/1 1 +Ethernet8 45,46,47,48 Ethernet3/1 2 +Ethernet12 41,42,43,44 Ethernet4/1 3 +Ethernet16 53,54,55,56 Ethernet5/1 4 +Ethernet20 49,50,51,52 Ethernet6/1 5 +Ethernet24 61,62,63,64 Ethernet7/1 6 +Ethernet28 57,58,59,60 Ethernet8/1 7 +Ethernet32 69,70,71,72 Ethernet9/1 8 +Ethernet36 65,66,67,68 Ethernet10/1 9 +Ethernet40 77,78,79,80 Ethernet11/1 10 +Ethernet44 73,74,75,76 Ethernet12/1 11 +Ethernet48 85,86,87,88 Ethernet13/1 12 +Ethernet52 81,82,83,84 Ethernet14/1 13 +Ethernet56 93,94,95,96 Ethernet15/1 14 +Ethernet60 89,90,91,92 Ethernet16/1 15 +Ethernet64 101,102,103,104 Ethernet17/1 16 +Ethernet68 97,98,99,100 Ethernet18/1 17 +Ethernet72 109,110,111,112 Ethernet19/1 18 +Ethernet76 105,106,107,108 Ethernet20/1 19 +Ethernet80 117,118,119,120 Ethernet21/1 20 +Ethernet84 113,114,115,116 Ethernet22/1 21 +Ethernet88 125,126,127,128 Ethernet23/1 22 +Ethernet92 121,122,123,124 Ethernet24/1 23 +Ethernet96 5,6,7,8 Ethernet25/1 24 +Ethernet100 1,2,3,4 Ethernet26/1 25 +Ethernet104 13,14,15,16 Ethernet27/1 26 +Ethernet108 9,10,11,12 Ethernet28/1 27 +Ethernet112 21,22,23,24 Ethernet29/1 28 +Ethernet116 17,18,19,20 Ethernet30/1 29 +Ethernet120 29,30,31,32 Ethernet31/1 30 +Ethernet124 25,26,27,28 Ethernet32/1 31 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/sai.profile b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/sai.profile new file mode 100644 index 000000000000..3205cd2d6ad9 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-s8810-32x40G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/td2-s8810-32x40G.config.bcm b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/td2-s8810-32x40G.config.bcm new file mode 100644 index 000000000000..894f60345a73 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/INGRASYS-S8810-32Q/td2-s8810-32x40G.config.bcm @@ -0,0 +1,473 @@ +#2017/09/12 +os=unix + +module_64ports=0 +schan_intr_enable=0 +stable_size=0x2000000 + +pbmp_xport_xe=0x000007fffffffffffffffffffffffffe +pbmp_oversubscribe=0x000007fffffffffffffffffffffffffe + +# ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l2_mem_entries=32768 +l3_mem_entries=16384 + +l2xmsg_mode=1 +mmu_lossless=0 + +#Parity +parity_correction=1 +parity_enable=1 + +portmap_1=37:40 +portmap_2=33:40 +portmap_3=45:40 +portmap_4=41:40 +portmap_5=53:40 +portmap_6=49:40 +portmap_7=61:40 +portmap_8=57:40 +portmap_9=69:40 +portmap_10=65:40 +portmap_11=77:40 +portmap_12=73:40 +portmap_13=85:40 +portmap_14=81:40 +portmap_15=93:40 +portmap_16=89:40 +portmap_17=101:40 +portmap_18=97:40 +portmap_19=109:40 +portmap_20=105:40 +portmap_21=117:40 +portmap_22=113:40 +portmap_23=125:40 +portmap_24=121:40 +portmap_25=5:40 +portmap_26=1:40 +portmap_27=13:40 +portmap_28=9:40 +portmap_29=21:40 +portmap_30=17:40 +portmap_31=29:40 +portmap_32=25:40 + +serdes_driver_current_lane0_xe0=0x6 +serdes_driver_current_lane1_xe0=0x6 +serdes_driver_current_lane2_xe0=0x6 +serdes_driver_current_lane3_xe0=0x7 +serdes_pre_driver_current_lane0_xe0=0x6 +serdes_pre_driver_current_lane1_xe0=0x6 +serdes_pre_driver_current_lane2_xe0=0x6 +serdes_pre_driver_current_lane3_xe0=0x7 +serdes_preemphasis_lane0_xe0=0xc2f0 +serdes_preemphasis_lane1_xe0=0xcf20 +serdes_preemphasis_lane2_xe0=0xc2f0 +serdes_preemphasis_lane3_xe0=0xc2f0 + +serdes_driver_current_lane0_xe1=0x8 +serdes_driver_current_lane1_xe1=0x8 +serdes_driver_current_lane2_xe1=0x8 +serdes_driver_current_lane3_xe1=0x8 +serdes_pre_driver_current_lane0_xe1=0x8 +serdes_pre_driver_current_lane1_xe1=0x8 +serdes_pre_driver_current_lane2_xe1=0x8 +serdes_pre_driver_current_lane3_xe1=0x8 +serdes_preemphasis_lane0_xe1=0xc6e0 +serdes_preemphasis_lane1_xe1=0xc6e0 +serdes_preemphasis_lane2_xe1=0xc6e0 +serdes_preemphasis_lane3_xe1=0xc6e0 + +serdes_driver_current_lane0_xe2=0x5 +serdes_driver_current_lane1_xe2=0x3 +serdes_driver_current_lane2_xe2=0x3 +serdes_driver_current_lane3_xe2=0x3 +serdes_pre_driver_current_lane0_xe2=0x5 +serdes_pre_driver_current_lane1_xe2=0x3 +serdes_pre_driver_current_lane2_xe2=0x3 +serdes_pre_driver_current_lane3_xe2=0x3 +serdes_preemphasis_lane0_xe2=0x9b90 +serdes_preemphasis_lane1_xe2=0x9f80 +serdes_preemphasis_lane2_xe2=0x9b90 +serdes_preemphasis_lane3_xe2=0x9b90 + +serdes_driver_current_lane0_xe3=0x5 +serdes_driver_current_lane1_xe3=0x5 +serdes_driver_current_lane2_xe3=0x5 +serdes_driver_current_lane3_xe3=0x5 +serdes_pre_driver_current_lane0_xe3=0x5 +serdes_pre_driver_current_lane1_xe3=0x5 +serdes_pre_driver_current_lane2_xe3=0x5 +serdes_pre_driver_current_lane3_xe3=0x5 +serdes_preemphasis_lane0_xe3=0x9b90 +serdes_preemphasis_lane1_xe3=0x9b90 +serdes_preemphasis_lane2_xe3=0x9b90 +serdes_preemphasis_lane3_xe3=0x9b90 + +serdes_driver_current_lane0_xe4=0x3 +serdes_driver_current_lane1_xe4=0x3 +serdes_driver_current_lane2_xe4=0x3 +serdes_driver_current_lane3_xe4=0x3 +serdes_pre_driver_current_lane0_xe4=0x3 +serdes_pre_driver_current_lane1_xe4=0x3 +serdes_pre_driver_current_lane2_xe4=0x3 +serdes_pre_driver_current_lane3_xe4=0x3 +serdes_preemphasis_lane0_xe4=0x93b0 +serdes_preemphasis_lane1_xe4=0x97a0 +serdes_preemphasis_lane2_xe4=0x9b90 +serdes_preemphasis_lane3_xe4=0x9b90 + +serdes_driver_current_lane0_xe5=0x3 +serdes_driver_current_lane1_xe5=0x3 +serdes_driver_current_lane2_xe5=0x3 +serdes_driver_current_lane3_xe5=0x3 +serdes_pre_driver_current_lane0_xe5=0x3 +serdes_pre_driver_current_lane1_xe5=0x3 +serdes_pre_driver_current_lane2_xe5=0x3 +serdes_pre_driver_current_lane3_xe5=0x3 +serdes_preemphasis_lane0_xe5=0x9b90 +serdes_preemphasis_lane1_xe5=0x9b90 +serdes_preemphasis_lane2_xe5=0x9b90 +serdes_preemphasis_lane3_xe5=0x9b90 + +serdes_driver_current_lane0_xe6=0x1 +serdes_driver_current_lane1_xe6=0x1 +serdes_driver_current_lane2_xe6=0x1 +serdes_driver_current_lane3_xe6=0x1 +serdes_pre_driver_current_lane0_xe6=0x1 +serdes_pre_driver_current_lane1_xe6=0x1 +serdes_pre_driver_current_lane2_xe6=0x1 +serdes_pre_driver_current_lane3_xe6=0x1 +serdes_preemphasis_lane0_xe6=0xa760 +serdes_preemphasis_lane1_xe6=0xc2f0 +serdes_preemphasis_lane2_xe6=0xa760 +serdes_preemphasis_lane3_xe6=0xa760 + +serdes_driver_current_lane0_xe7=0x1 +serdes_driver_current_lane1_xe7=0x1 +serdes_driver_current_lane2_xe7=0x1 +serdes_driver_current_lane3_xe7=0x1 +serdes_pre_driver_current_lane0_xe7=0x0 +serdes_pre_driver_current_lane1_xe7=0x0 +serdes_pre_driver_current_lane2_xe7=0x0 +serdes_pre_driver_current_lane3_xe7=0x0 +serdes_preemphasis_lane0_xe7=0xa760 +serdes_preemphasis_lane1_xe7=0xa760 +serdes_preemphasis_lane2_xe7=0xa760 +serdes_preemphasis_lane3_xe7=0xa760 + +serdes_driver_current_lane0_xe8=0x1 +serdes_driver_current_lane1_xe8=0x1 +serdes_driver_current_lane2_xe8=0x1 +serdes_driver_current_lane3_xe8=0x0 +serdes_pre_driver_current_lane0_xe8=0x0 +serdes_pre_driver_current_lane1_xe8=0x0 +serdes_pre_driver_current_lane2_xe8=0x0 +serdes_pre_driver_current_lane3_xe8=0x0 +serdes_preemphasis_lane0_xe8=0xa760 +serdes_preemphasis_lane1_xe8=0xa760 +serdes_preemphasis_lane2_xe8=0xa760 +serdes_preemphasis_lane3_xe8=0xa760 + +serdes_driver_current_lane0_xe9=0x1 +serdes_driver_current_lane1_xe9=0x1 +serdes_driver_current_lane2_xe9=0x1 +serdes_driver_current_lane3_xe9=0x1 +serdes_pre_driver_current_lane0_xe9=0x0 +serdes_pre_driver_current_lane1_xe9=0x0 +serdes_pre_driver_current_lane2_xe9=0x0 +serdes_pre_driver_current_lane3_xe9=0x0 +serdes_preemphasis_lane0_xe9=0xa760 +serdes_preemphasis_lane1_xe9=0xa760 +serdes_preemphasis_lane2_xe9=0xa760 +serdes_preemphasis_lane3_xe9=0xa760 + +serdes_driver_current_lane0_xe10=0x1 +serdes_driver_current_lane1_xe10=0x1 +serdes_driver_current_lane2_xe10=0x1 +serdes_driver_current_lane3_xe10=0x1 +serdes_pre_driver_current_lane0_xe10=0x0 +serdes_pre_driver_current_lane1_xe10=0x0 +serdes_pre_driver_current_lane2_xe10=0x0 +serdes_pre_driver_current_lane3_xe10=0x0 +serdes_preemphasis_lane0_xe10=0xa760 +serdes_preemphasis_lane1_xe10=0xa760 +serdes_preemphasis_lane2_xe10=0xa760 +serdes_preemphasis_lane3_xe10=0xa760 + +serdes_driver_current_lane0_xe11=0x1 +serdes_driver_current_lane1_xe11=0x1 +serdes_driver_current_lane2_xe11=0x1 +serdes_driver_current_lane3_xe11=0x1 +serdes_pre_driver_current_lane0_xe11=0x1 +serdes_pre_driver_current_lane1_xe11=0x0 +serdes_pre_driver_current_lane2_xe11=0x1 +serdes_pre_driver_current_lane3_xe11=0x0 +serdes_preemphasis_lane0_xe11=0xa760 +serdes_preemphasis_lane1_xe11=0xa760 +serdes_preemphasis_lane2_xe11=0xa760 +serdes_preemphasis_lane3_xe11=0xa760 + +serdes_driver_current_lane0_xe12=0x1 +serdes_driver_current_lane1_xe12=0x1 +serdes_driver_current_lane2_xe12=0x1 +serdes_driver_current_lane3_xe12=0x1 +serdes_pre_driver_current_lane0_xe12=0x0 +serdes_pre_driver_current_lane1_xe12=0x0 +serdes_pre_driver_current_lane2_xe12=0x0 +serdes_pre_driver_current_lane3_xe12=0x0 +serdes_preemphasis_lane0_xe12=0xa760 +serdes_preemphasis_lane1_xe12=0xa760 +serdes_preemphasis_lane2_xe12=0xa760 +serdes_preemphasis_lane3_xe12=0xa760 + +serdes_driver_current_lane0_xe13=0x1 +serdes_driver_current_lane1_xe13=0x1 +serdes_driver_current_lane2_xe13=0x1 +serdes_driver_current_lane3_xe13=0x1 +serdes_pre_driver_current_lane0_xe13=0x1 +serdes_pre_driver_current_lane1_xe13=0x1 +serdes_pre_driver_current_lane2_xe13=0x1 +serdes_pre_driver_current_lane3_xe13=0x0 +serdes_preemphasis_lane0_xe13=0xa760 +serdes_preemphasis_lane1_xe13=0xa760 +serdes_preemphasis_lane2_xe13=0xa760 +serdes_preemphasis_lane3_xe13=0xa760 + +serdes_driver_current_lane0_xe14=0x3 +serdes_driver_current_lane1_xe14=0x3 +serdes_driver_current_lane2_xe14=0x3 +serdes_driver_current_lane3_xe14=0x3 +serdes_pre_driver_current_lane0_xe14=0x3 +serdes_pre_driver_current_lane1_xe14=0x3 +serdes_pre_driver_current_lane2_xe14=0x3 +serdes_pre_driver_current_lane3_xe14=0x3 +serdes_preemphasis_lane0_xe14=0xaf40 +serdes_preemphasis_lane1_xe14=0xab50 +serdes_preemphasis_lane2_xe14=0xaf40 +serdes_preemphasis_lane3_xe14=0xaf40 + +serdes_driver_current_lane0_xe15=0x3 +serdes_driver_current_lane1_xe15=0x3 +serdes_driver_current_lane2_xe15=0x3 +serdes_driver_current_lane3_xe15=0x3 +serdes_pre_driver_current_lane0_xe15=0x3 +serdes_pre_driver_current_lane1_xe15=0x3 +serdes_pre_driver_current_lane2_xe15=0x3 +serdes_pre_driver_current_lane3_xe15=0x3 +serdes_preemphasis_lane0_xe15=0xaf40 +serdes_preemphasis_lane1_xe15=0xaf40 +serdes_preemphasis_lane2_xe15=0xab50 +serdes_preemphasis_lane3_xe15=0xab50 + +serdes_driver_current_lane0_xe16=0x0 +serdes_driver_current_lane1_xe16=0x1 +serdes_driver_current_lane2_xe16=0x1 +serdes_driver_current_lane3_xe16=0x1 +serdes_pre_driver_current_lane0_xe16=0x0 +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 + +serdes_driver_current_lane0_xe17=0x1 +serdes_driver_current_lane1_xe17=0x0 +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=0x0 +serdes_pre_driver_current_lane2_xe17=0x1 +serdes_pre_driver_current_lane3_xe17=0x1 +serdes_preemphasis_lane0_xe17=0xa760 +serdes_preemphasis_lane1_xe17=0x9b90 +serdes_preemphasis_lane2_xe17=0xa760 +serdes_preemphasis_lane3_xe17=0xa760 + +serdes_driver_current_lane0_xe18=0x1 +serdes_driver_current_lane1_xe18=0x1 +serdes_driver_current_lane2_xe18=0x1 +serdes_driver_current_lane3_xe18=0x1 +serdes_pre_driver_current_lane0_xe18=0x1 +serdes_pre_driver_current_lane1_xe18=0x1 +serdes_pre_driver_current_lane2_xe18=0x1 +serdes_pre_driver_current_lane3_xe18=0x1 +serdes_preemphasis_lane0_xe18=0xa760 +serdes_preemphasis_lane1_xe18=0xa760 +serdes_preemphasis_lane2_xe18=0xa760 +serdes_preemphasis_lane3_xe18=0xa760 + +serdes_driver_current_lane0_xe19=0x1 +serdes_driver_current_lane1_xe19=0x1 +serdes_driver_current_lane2_xe19=0x1 +serdes_driver_current_lane3_xe19=0x1 +serdes_pre_driver_current_lane0_xe19=0x1 +serdes_pre_driver_current_lane1_xe19=0x1 +serdes_pre_driver_current_lane2_xe19=0x0 +serdes_pre_driver_current_lane3_xe19=0x1 +serdes_preemphasis_lane0_xe19=0xa760 +serdes_preemphasis_lane1_xe19=0xa760 +serdes_preemphasis_lane2_xe19=0xa760 +serdes_preemphasis_lane3_xe19=0xa760 + +serdes_driver_current_lane0_xe20=0x1 +serdes_driver_current_lane1_xe20=0x2 +serdes_driver_current_lane2_xe20=0x1 +serdes_driver_current_lane3_xe20=0x1 +serdes_pre_driver_current_lane0_xe20=0x0 +serdes_pre_driver_current_lane1_xe20=0x2 +serdes_pre_driver_current_lane2_xe20=0x1 +serdes_pre_driver_current_lane3_xe20=0x1 +serdes_preemphasis_lane0_xe20=0xa760 +serdes_preemphasis_lane1_xe20=0xa670 +serdes_preemphasis_lane2_xe20=0xa760 +serdes_preemphasis_lane3_xe20=0xa760 + +serdes_driver_current_lane0_xe21=0x1 +serdes_driver_current_lane1_xe21=0x1 +serdes_driver_current_lane2_xe21=0x0 +serdes_driver_current_lane3_xe21=0x1 +serdes_pre_driver_current_lane0_xe21=0x0 +serdes_pre_driver_current_lane1_xe21=0x1 +serdes_pre_driver_current_lane2_xe21=0x0 +serdes_pre_driver_current_lane3_xe21=0x1 +serdes_preemphasis_lane0_xe21=0xa760 +serdes_preemphasis_lane1_xe21=0xa670 +serdes_preemphasis_lane2_xe21=0xa760 +serdes_preemphasis_lane3_xe21=0xa760 + +serdes_driver_current_lane0_xe22=0x1 +serdes_driver_current_lane1_xe22=0x4 +serdes_driver_current_lane2_xe22=0x2 +serdes_driver_current_lane3_xe22=0x2 +serdes_pre_driver_current_lane0_xe22=0x1 +serdes_pre_driver_current_lane1_xe22=0x4 +serdes_pre_driver_current_lane2_xe22=0x2 +serdes_pre_driver_current_lane3_xe22=0x2 +serdes_preemphasis_lane0_xe22=0xa760 +serdes_preemphasis_lane1_xe22=0x97a0 +serdes_preemphasis_lane2_xe22=0xa670 +serdes_preemphasis_lane3_xe22=0xa760 + +serdes_driver_current_lane0_xe23=0x3 +serdes_driver_current_lane1_xe23=0x3 +serdes_driver_current_lane2_xe23=0x1 +serdes_driver_current_lane3_xe23=0x1 +serdes_pre_driver_current_lane0_xe23=0x3 +serdes_pre_driver_current_lane1_xe23=0x3 +serdes_pre_driver_current_lane2_xe23=0x1 +serdes_pre_driver_current_lane3_xe23=0x1 +serdes_preemphasis_lane0_xe23=0xa760 +serdes_preemphasis_lane1_xe23=0x9b90 +serdes_preemphasis_lane2_xe23=0xab50 +serdes_preemphasis_lane3_xe23=0xa760 + +serdes_driver_current_lane0_xe24=0x1 +serdes_driver_current_lane1_xe24=0x4 +serdes_driver_current_lane2_xe24=0x4 +serdes_driver_current_lane3_xe24=0x3 +serdes_pre_driver_current_lane0_xe24=0x1 +serdes_pre_driver_current_lane1_xe24=0x4 +serdes_pre_driver_current_lane2_xe24=0x4 +serdes_pre_driver_current_lane3_xe24=0x3 +serdes_preemphasis_lane0_xe24=0xa760 +serdes_preemphasis_lane1_xe24=0x93b0 +serdes_preemphasis_lane2_xe24=0x9b90 +serdes_preemphasis_lane3_xe24=0xa760 + +serdes_driver_current_lane0_xe25=0x4 +serdes_driver_current_lane1_xe25=0x3 +serdes_driver_current_lane2_xe25=0x3 +serdes_driver_current_lane3_xe25=0x1 +serdes_pre_driver_current_lane0_xe25=0x4 +serdes_pre_driver_current_lane1_xe25=0x3 +serdes_pre_driver_current_lane2_xe25=0x3 +serdes_pre_driver_current_lane3_xe25=0x1 +serdes_preemphasis_lane0_xe25=0x93b0 +serdes_preemphasis_lane1_xe25=0x9b90 +serdes_preemphasis_lane2_xe25=0x9b90 +serdes_preemphasis_lane3_xe25=0xa760 + +serdes_driver_current_lane0_xe26=0x4 +serdes_driver_current_lane1_xe26=0x4 +serdes_driver_current_lane2_xe26=0x4 +serdes_driver_current_lane3_xe26=0x4 +serdes_pre_driver_current_lane0_xe26=0x4 +serdes_pre_driver_current_lane1_xe26=0x4 +serdes_pre_driver_current_lane2_xe26=0x4 +serdes_pre_driver_current_lane3_xe26=0x4 +serdes_preemphasis_lane0_xe26=0x9b90 +serdes_preemphasis_lane1_xe26=0x97a0 +serdes_preemphasis_lane2_xe26=0x9b90 +serdes_preemphasis_lane3_xe26=0x97a0 + +serdes_driver_current_lane0_xe27=0x4 +serdes_driver_current_lane1_xe27=0x3 +serdes_driver_current_lane2_xe27=0x3 +serdes_driver_current_lane3_xe27=0x3 +serdes_pre_driver_current_lane0_xe27=0x4 +serdes_pre_driver_current_lane1_xe27=0x3 +serdes_pre_driver_current_lane2_xe27=0x3 +serdes_pre_driver_current_lane3_xe27=0x3 +serdes_preemphasis_lane0_xe27=0x9b90 +serdes_preemphasis_lane1_xe27=0x9b90 +serdes_preemphasis_lane2_xe27=0x9b90 +serdes_preemphasis_lane3_xe27=0x9b90 + +serdes_driver_current_lane0_xe28=0x5 +serdes_driver_current_lane1_xe28=0x5 +serdes_driver_current_lane2_xe28=0x6 +serdes_driver_current_lane3_xe28=0x6 +serdes_pre_driver_current_lane0_xe28=0x5 +serdes_pre_driver_current_lane1_xe28=0x5 +serdes_pre_driver_current_lane2_xe28=0x6 +serdes_pre_driver_current_lane3_xe28=0x6 +serdes_preemphasis_lane0_xe28=0xbf00 +serdes_preemphasis_lane1_xe28=0xbf00 +serdes_preemphasis_lane2_xe28=0xbf00 +serdes_preemphasis_lane3_xe28=0xbf00 + +serdes_driver_current_lane0_xe29=0x7 +serdes_driver_current_lane1_xe29=0x6 +serdes_driver_current_lane2_xe29=0x6 +serdes_driver_current_lane3_xe29=0x6 +serdes_pre_driver_current_lane0_xe29=0x7 +serdes_pre_driver_current_lane1_xe29=0x6 +serdes_pre_driver_current_lane2_xe29=0x6 +serdes_pre_driver_current_lane3_xe29=0x6 +serdes_preemphasis_lane0_xe29=0xbb10 +serdes_preemphasis_lane1_xe29=0xbb10 +serdes_preemphasis_lane2_xe29=0xbb10 +serdes_preemphasis_lane3_xe29=0xbb10 + +serdes_driver_current_lane0_xe30=0x7 +serdes_driver_current_lane1_xe30=0x7 +serdes_driver_current_lane2_xe30=0x7 +serdes_driver_current_lane3_xe30=0x7 +serdes_pre_driver_current_lane0_xe30=0x7 +serdes_pre_driver_current_lane1_xe30=0x7 +serdes_pre_driver_current_lane2_xe30=0x7 +serdes_pre_driver_current_lane3_xe30=0x7 +serdes_preemphasis_lane0_xe30=0xc2f0 +serdes_preemphasis_lane1_xe30=0xc2f0 +serdes_preemphasis_lane2_xe30=0xc2f0 +serdes_preemphasis_lane3_xe30=0xc2f0 + +serdes_driver_current_lane0_xe31=0x7 +serdes_driver_current_lane1_xe31=0x7 +serdes_driver_current_lane2_xe31=0x7 +serdes_driver_current_lane3_xe31=0x7 +serdes_pre_driver_current_lane0_xe31=0x7 +serdes_pre_driver_current_lane1_xe31=0x7 +serdes_pre_driver_current_lane2_xe31=0x7 +serdes_pre_driver_current_lane3_xe31=0x7 +serdes_preemphasis_lane0_xe31=0xc2f0 +serdes_preemphasis_lane1_xe31=0xc2f0 +serdes_preemphasis_lane2_xe31=0xc2f0 +serdes_preemphasis_lane3_xe31=0xc2f0 + +serdes_if_type_xe=14 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/default_sku new file mode 100644 index 000000000000..fe68cd87d182 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S8810-32Q t1 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/fancontrol new file mode 100644 index 000000000000..8c378371a9a2 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/fancontrol @@ -0,0 +1,11 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/0-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon1/device/temp2_input hwmon1/device/pwm1=hwmon1/device/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm2=20 hwmon1/device/pwm1=20 +MAXTEMP=hwmon1/device/pwm2=60 hwmon1/device/pwm1=60 +MINSTART=hwmon1/device/pwm2=75 hwmon1/device/pwm1=75 +MINSTOP=hwmon1/device/pwm2=22 hwmon1/device/pwm1=22 + diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/led_proc_init.soc b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/led_proc_init.soc new file mode 100644 index 000000000000..8c1a18f6236b --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/led_proc_init.soc @@ -0,0 +1,45 @@ +#processor initialization for Ingrasys S8810-32Q + +led 0 stop +led 0 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48 REMAP_PORT_2=49 REMAP_PORT_1=50 REMAP_PORT_0=51 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52 REMAP_PORT_6=53 REMAP_PORT_5=54 REMAP_PORT_4=55 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 REMAP_PORT_10=57 REMAP_PORT_9=58 REMAP_PORT_8=59 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 REMAP_PORT_14=61 REMAP_PORT_13=62 REMAP_PORT_12=63 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44 REMAP_PORT_18=45 REMAP_PORT_17=46 REMAP_PORT_16=47 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40 REMAP_PORT_22=41 REMAP_PORT_21=42 REMAP_PORT_20=43 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 REMAP_PORT_26=37 REMAP_PORT_25=38 REMAP_PORT_24=39 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 REMAP_PORT_30=33 REMAP_PORT_29=34 REMAP_PORT_28=35 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 REMAP_PORT_34=17 REMAP_PORT_33=18 REMAP_PORT_32=19 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 REMAP_PORT_38=21 REMAP_PORT_37=22 REMAP_PORT_36=23 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24 REMAP_PORT_42=25 REMAP_PORT_41=26 REMAP_PORT_40=27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28 REMAP_PORT_46=29 REMAP_PORT_45=30 REMAP_PORT_44=31 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12 REMAP_PORT_50=13 REMAP_PORT_49=14 REMAP_PORT_48=15 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8 REMAP_PORT_54=9 REMAP_PORT_53=10 REMAP_PORT_52=11 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 REMAP_PORT_58=5 REMAP_PORT_57=6 REMAP_PORT_56=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 REMAP_PORT_62=1 REMAP_PORT_61=2 REMAP_PORT_60=3 + +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48 REMAP_PORT_2=49 REMAP_PORT_1=50 REMAP_PORT_0=51 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52 REMAP_PORT_6=53 REMAP_PORT_5=54 REMAP_PORT_4=55 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56 REMAP_PORT_10=57 REMAP_PORT_9=58 REMAP_PORT_8=59 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60 REMAP_PORT_14=61 REMAP_PORT_13=62 REMAP_PORT_12=63 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44 REMAP_PORT_18=45 REMAP_PORT_17=46 REMAP_PORT_16=47 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40 REMAP_PORT_22=41 REMAP_PORT_21=42 REMAP_PORT_20=43 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 REMAP_PORT_26=37 REMAP_PORT_25=38 REMAP_PORT_24=39 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 REMAP_PORT_30=33 REMAP_PORT_29=34 REMAP_PORT_28=35 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16 REMAP_PORT_34=17 REMAP_PORT_33=18 REMAP_PORT_32=19 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20 REMAP_PORT_38=21 REMAP_PORT_37=22 REMAP_PORT_36=23 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24 REMAP_PORT_42=25 REMAP_PORT_41=26 REMAP_PORT_40=27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28 REMAP_PORT_46=29 REMAP_PORT_45=30 REMAP_PORT_44=31 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12 REMAP_PORT_50=13 REMAP_PORT_49=14 REMAP_PORT_48=15 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8 REMAP_PORT_54=9 REMAP_PORT_53=10 REMAP_PORT_52=11 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 REMAP_PORT_58=5 REMAP_PORT_57=6 REMAP_PORT_56=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 REMAP_PORT_62=1 REMAP_PORT_61=2 REMAP_PORT_60=3 + +led 1 auto on +led 1 start diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/eeprom.py new file mode 100644 index 000000000000..8f9ee7d9989b --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +############################################################################# +# Ingrasys S8810-32Q +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + i2c_bus = "12" + i2c_addr = "0056" + self.eeprom_path = "/sys/class/i2c-adapter/i2c-" + i2c_bus + "/" + i2c_bus + "-" + i2c_addr + "/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/psuutil.py new file mode 100644 index 000000000000..fcf9136d25db --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/psuutil.py @@ -0,0 +1,91 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-3/3-0051", + "/sys/bus/i2c/devices/i2c-4/4-0051"] + + 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 ", attr_path, " file !") + + 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_pg' + 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_abs' + 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 == 0): + status = 1 + + return status diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/sfputil.py new file mode 100644 index 000000000000..c1afbdf0738d --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/plugins/sfputil.py @@ -0,0 +1,183 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +import os + +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 = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 18 + + ABS_GPIO_BASE = 224 + #INT_GPIO_BASE = 192 + LP_GPIO_BASE = 160 + RST_GPIO_BASE = 128 + GPIO_OFFSET = 0 + + BASE_DIR_PATH = "/sys/class/gpio/gpio{0}/direction" + BASE_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _port_to_eeprom_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 list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:], 10) + except ValueError as e: + print("Error: %s" % str(e)) + if gpiochip_no > 255: + self.GPIO_OFFSET = 256 + return True + return True + + def update_gpio_base(self): + self.ABS_GPIO_BASE = 224 + self.GPIO_OFFSET + self.LP_GPIO_BASE = 160 + self.GPIO_OFFSET + self.RST_GPIO_BASE = 128 + self.GPIO_OFFSET + return True + + def __init__(self): + # Update abs, lpmode, and reset gpio base + self.set_gpio_offset() + self.update_gpio_base() + + # Override port_to_eeprom_mapping for class initialization + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(self.port_start, self.port_end + 1): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + abs_device_file = self.BASE_VAL_PATH.format( + port_num + self.ABS_GPIO_BASE) + val_file = open(abs_device_file) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + port_num + self.LP_GPIO_BASE) + val_file = open(lpmode_val_device_file) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + port_num + self.LP_GPIO_BASE) + val_file = open(lpmode_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("1" if lpmode is True else "0") + val_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + port_num + self.RST_GPIO_BASE) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("1") + val_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + port_num + self.RST_GPIO_BASE) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("0") + val_file.close() + + return True + + 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 diff --git a/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/sensors.conf new file mode 100644 index 000000000000..8332fbdf9086 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8810_32q-r0/sensors.conf @@ -0,0 +1,47 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +chip "w83795adg-*" + label in0 "ROV" + set in0_min 1.025 * 0.98 + set in0_max 1.025 * 1.02 + ignore in1 + ignore in2 + label in3 "1.0V" + set in3_min 1 * 0.97 + set in3_max 1 * 1.03 + label in4 "1.8V" + set in4_min 1.8 * 0.95 + set in4_max 1.8 * 1.05 + ignore in5 + label in6 "5.0V" + compute in6 (4)*@, @/(4) + set in6_min 5 * 0.95 + set in6_max 5 * 1.05 + ignore in7 + label in12 "3.3V" + compute in6 (2)*@, @/(2) + set in12_min 3.3 * 0.97 + set in12_max 3.3 * 1.03 + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + label temp1 "MAC Temp" + label temp2 "SFP+ Port 1 Temp" + label temp3 "SFP+ Port 8 Temp" + ignore temp4 + ignore intrusion0 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/port_config.ini b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/port_config.ini new file mode 100644 index 000000000000..079bb63455f2 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index +Ethernet0 1 Ethernet1/1 0 +Ethernet1 2 Ethernet2/1 1 +Ethernet2 3 Ethernet3/1 2 +Ethernet3 4 Ethernet4/1 3 +Ethernet4 5 Ethernet5/1 4 +Ethernet5 6 Ethernet6/1 5 +Ethernet6 7 Ethernet7/1 6 +Ethernet7 8 Ethernet8/1 7 +Ethernet8 9 Ethernet9/1 8 +Ethernet9 10 Ethernet10/1 9 +Ethernet10 11 Ethernet11/1 10 +Ethernet11 12 Ethernet12/1 11 +Ethernet12 21 Ethernet13/1 12 +Ethernet13 22 Ethernet14/1 13 +Ethernet14 23 Ethernet15/1 14 +Ethernet15 24 Ethernet16/1 15 +Ethernet16 33 Ethernet17/1 16 +Ethernet17 34 Ethernet18/1 17 +Ethernet18 35 Ethernet19/1 18 +Ethernet19 36 Ethernet20/1 19 +Ethernet20 37 Ethernet21/1 20 +Ethernet21 38 Ethernet22/1 21 +Ethernet22 39 Ethernet23/1 22 +Ethernet23 40 Ethernet24/1 23 +Ethernet24 41 Ethernet25/1 24 +Ethernet25 42 Ethernet26/1 25 +Ethernet26 43 Ethernet27/1 26 +Ethernet27 44 Ethernet28/1 27 +Ethernet28 49 Ethernet29/1 28 +Ethernet29 50 Ethernet30/1 29 +Ethernet30 51 Ethernet31/1 30 +Ethernet31 52 Ethernet32/1 31 +Ethernet32 53 Ethernet33/1 32 +Ethernet33 54 Ethernet34/1 33 +Ethernet34 55 Ethernet35/1 34 +Ethernet35 56 Ethernet36/1 35 +Ethernet36 65 Ethernet37/1 36 +Ethernet37 66 Ethernet38/1 37 +Ethernet38 67 Ethernet39/1 38 +Ethernet39 68 Ethernet40/1 39 +Ethernet40 69 Ethernet41/1 40 +Ethernet41 70 Ethernet42/1 41 +Ethernet42 71 Ethernet43/1 42 +Ethernet43 72 Ethernet44/1 43 +Ethernet44 81 Ethernet45/1 44 +Ethernet45 82 Ethernet46/1 45 +Ethernet46 83 Ethernet47/1 46 +Ethernet47 84 Ethernet48/1 47 +Ethernet48 85,86,87,88 Ethernet52/1 48 +Ethernet52 97,98,99,100 Ethernet56/1 49 +Ethernet56 101,102,103,104 Ethernet60/1 50 +Ethernet60 105,106,107,108 Ethernet64/1 51 +Ethernet64 109,110,111,112 Ethernet68/1 52 +Ethernet68 117,118,119,120 Ethernet69/1 53 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/sai.profile b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/sai.profile new file mode 100644 index 000000000000..607f20f329a6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s8900-48x25G+6x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/th-s8900-48x25G+6x100G.config.bcm b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/th-s8900-48x25G+6x100G.config.bcm new file mode 100644 index 000000000000..4485a77af2d6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/INGRASYS-S8900-54XC/th-s8900-48x25G+6x100G.config.bcm @@ -0,0 +1,340 @@ +#2018/03/31 + +os=unix + +oversubscribe_mode=1 +pbmp_xport_xe=0x7f00001fff4003ffffc0001fffe + +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l3_mem_entries=40960 +l2_mem_entries=40960 + +l2xmsg_mode=1 +mmu_lossless=0 + +#Parity +parity_correction=1 +parity_enable=1 + +#PIPE0 +portmap_1=1:25 +portmap_2=2:25 +portmap_3=3:25 +portmap_4=4:25 +portmap_5=5:25 +portmap_6=6:25 +portmap_7=7:25 +portmap_8=8:25 +portmap_9=9:25 +portmap_10=10:25 +portmap_11=11:25 +portmap_12=12:25 +portmap_13=21:25 +portmap_14=22:25 +portmap_15=23:25 +portmap_16=24:25 + +#PIPE1 +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 +portmap_38=37:25 +portmap_39=38:25 +portmap_40=39:25 +portmap_41=40:25 +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 +portmap_46=49:25 +portmap_47=50:25 +portmap_48=51:25 +portmap_49=52:25 +portmap_50=53:25 +portmap_51=54:25 +portmap_52=55:25 +portmap_53=56:25 + +#PIPE2 +portmap_68=65:25 +portmap_69=66:25 +portmap_70=67:25 +portmap_71=68:25 +portmap_72=69:25 +portmap_73=70:25 +portmap_74=71:25 +portmap_75=72:25 +portmap_76=81:25 +portmap_77=82:25 +portmap_78=83:25 +portmap_79=84:25 +portmap_80=85:100 + +#PIPE3 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=117:100 + + +portmap_66=129:10 +portmap_100=131:10 +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +serdes_driver_current_xe0=0xF +serdes_preemphasis_xe0=0x3E3200 +serdes_if_type_xe0=14 + +serdes_driver_current_xe1=0xF +serdes_preemphasis_xe1=0x3A3600 +serdes_if_type_xe1=14 + +serdes_driver_current_xe2=0xF +serdes_preemphasis_xe2=0x3A3600 +serdes_if_type_xe2=14 + +serdes_driver_current_xe3=0xF +serdes_preemphasis_xe3=0x383800 +serdes_if_type_xe3=14 + +serdes_driver_current_xe4=0xF +serdes_preemphasis_xe4=0x373900 +serdes_if_type_xe4=14 + +serdes_driver_current_xe5=0xF +serdes_preemphasis_xe5=0x2E4200 +serdes_if_type_xe5=14 + +serdes_driver_current_xe6=0xF +serdes_preemphasis_xe6=0x333D00 +serdes_if_type_xe6=14 + +serdes_driver_current_xe7=0xC +serdes_preemphasis_xe7=0x304000 +serdes_if_type_xe7=14 + +serdes_driver_current_xe8=0xE +serdes_preemphasis_xe8=0x2F4300 +serdes_if_type_xe8=14 + +serdes_driver_current_xe9=0xC +serdes_preemphasis_xe9=0x2D4300 +serdes_if_type_xe9=14 + +serdes_driver_current_xe10=0xC +serdes_preemphasis_xe10=0x2C4400 +serdes_if_type_xe10=14 + +serdes_driver_current_xe11=0xC +serdes_preemphasis_xe11=0x2D4300 +serdes_if_type_xe11=14 + +serdes_driver_current_xe12=0xC +serdes_preemphasis_xe12=0x294700 +serdes_if_type_xe12=14 + +serdes_driver_current_xe13=0xC +serdes_preemphasis_xe13=0x284800 +serdes_if_type_xe13=14 + +serdes_driver_current_xe14=0xA +serdes_preemphasis_xe14=0x294700 +serdes_if_type_xe14=14 + +serdes_driver_current_xe15=0xF +serdes_preemphasis_xe15=0x294700 +serdes_if_type_xe15=14 + +serdes_driver_current_xe16=0x9 +serdes_preemphasis_xe16=0x185800 +serdes_if_type_xe16=14 + +serdes_driver_current_xe17=0x9 +serdes_preemphasis_xe17=0x1D5300 +serdes_if_type_xe17=14 + +serdes_driver_current_xe18=0x9 +serdes_preemphasis_xe18=0x1C5400 +serdes_if_type_xe18=14 + +serdes_driver_current_xe19=0x9 +serdes_preemphasis_xe19=0x1C5400 +serdes_if_type_xe19=14 + +serdes_driver_current_xe20=0x9 +serdes_preemphasis_xe20=0x1C5400 +serdes_if_type_xe20=14 + +serdes_driver_current_xe21=0x9 +serdes_preemphasis_xe21=0x1C5400 +serdes_if_type_xe21=14 + +serdes_driver_current_xe22=0x9 +serdes_preemphasis_xe22=0x1C5400 +serdes_if_type_xe22=14 + +serdes_driver_current_xe23=0x9 +serdes_preemphasis_xe23=0x1C5400 +serdes_if_type_xe23=14 + +serdes_driver_current_xe24=0x8 +serdes_preemphasis_xe24=0x1C5400 +serdes_if_type_xe24=14 + +serdes_driver_current_xe25=0x8 +serdes_preemphasis_xe25=0x1C5400 +serdes_if_type_xe25=14 + +serdes_driver_current_xe26=0x8 +serdes_preemphasis_xe26=0x185800 +serdes_if_type_xe26=14 + +serdes_driver_current_xe27=0x8 +serdes_preemphasis_xe27=0x185800 +serdes_if_type_xe27=14 + +serdes_driver_current_xe28=0x8 +serdes_preemphasis_xe28=0x145C00 +serdes_if_type_xe28=14 + +serdes_driver_current_xe29=0x8 +serdes_preemphasis_xe29=0x195700 +serdes_if_type_xe29=14 + +serdes_driver_current_xe30=0x8 +serdes_preemphasis_xe30=0x195700 +serdes_if_type_xe30=14 + +serdes_driver_current_xe31=0x8 +serdes_preemphasis_xe31=0x195700 +serdes_if_type_xe31=14 + +serdes_driver_current_xe32=0xC +serdes_preemphasis_xe32=0x195700 +serdes_if_type_xe32=14 + +serdes_driver_current_xe33=0x9 +serdes_preemphasis_xe33=0x205000 +serdes_if_type_xe33=14 + +serdes_driver_current_xe34=0xC +serdes_preemphasis_xe34=0x214F00 +serdes_if_type_xe34=14 + +serdes_driver_current_xe35=0xC +serdes_preemphasis_xe35=0x244C00 +serdes_if_type_xe35=14 + +serdes_driver_current_xe36=0xC +serdes_preemphasis_xe36=0x244C00 +serdes_if_type_xe36=14 + +serdes_driver_current_xe37=0xC +serdes_preemphasis_xe37=0x244C00 +serdes_if_type_xe37=14 + +serdes_driver_current_xe38=0xC +serdes_preemphasis_xe38=0x244C00 +serdes_if_type_xe38=14 + +serdes_driver_current_xe39=0xC +serdes_preemphasis_xe39=0x244C00 +serdes_if_type_xe39=14 + +serdes_driver_current_xe40=0xD +serdes_preemphasis_xe40=0x284800 +serdes_if_type_xe40=14 + +serdes_driver_current_xe41=0xC +serdes_preemphasis_xe41=0x284800 +serdes_if_type_xe41=14 + +serdes_driver_current_xe42=0xE +serdes_preemphasis_xe42=0x294700 +serdes_if_type_xe42=14 + +serdes_driver_current_xe43=0xE +serdes_preemphasis_xe43=0x294700 +serdes_if_type_xe43=14 + +serdes_driver_current_xe44=0xE +serdes_preemphasis_xe44=0x294700 +serdes_if_type_xe44=14 + +serdes_driver_current_xe45=0xF +serdes_preemphasis_xe45=0x284800 +serdes_if_type_xe45=14 + +serdes_driver_current_xe46=0xF +serdes_preemphasis_xe46=0x284800 +serdes_if_type_xe46=14 + +serdes_driver_current_xe47=0xF +serdes_preemphasis_xe47=0x304000 +serdes_if_type_xe47=14 + +serdes_driver_current_lane0_ce0=0xC +serdes_driver_current_lane1_ce0=0xC +serdes_driver_current_lane2_ce0=0xF +serdes_driver_current_lane3_ce0=0xC +serdes_preemphasis_lane0_ce0=0x284800 +serdes_preemphasis_lane1_ce0=0x294100 +serdes_preemphasis_lane2_ce0=0x294100 +serdes_preemphasis_lane3_ce0=0x294100 +serdes_if_type_ce0=14 + +serdes_driver_current_lane0_ce1=0xC +serdes_driver_current_lane1_ce1=0xF +serdes_driver_current_lane2_ce1=0xC +serdes_driver_current_lane3_ce1=0xC +serdes_preemphasis_lane0_ce1=0x284200 +serdes_preemphasis_lane1_ce1=0x3A3600 +serdes_preemphasis_lane2_ce1=0x2C4400 +serdes_preemphasis_lane3_ce1=0x2C4400 +serdes_if_type_ce1=14 + +serdes_driver_current_lane0_ce2=0xC +serdes_driver_current_lane1_ce2=0xC +serdes_driver_current_lane2_ce2=0xC +serdes_driver_current_lane3_ce2=0xC +serdes_preemphasis_lane0_ce2=0x2F4100 +serdes_preemphasis_lane1_ce2=0x383800 +serdes_preemphasis_lane2_ce2=0x2F4100 +serdes_preemphasis_lane3_ce2=0x304000 +serdes_if_type_ce2=14 + +serdes_driver_current_lane0_ce3=0xC +serdes_driver_current_lane1_ce3=0xF +serdes_driver_current_lane2_ce3=0xC +serdes_driver_current_lane3_ce3=0xA +serdes_preemphasis_lane0_ce3=0x304000 +serdes_preemphasis_lane1_ce3=0x3F3100 +serdes_preemphasis_lane2_ce3=0x313F00 +serdes_preemphasis_lane3_ce3=0x304000 +serdes_if_type_ce3=14 + +serdes_driver_current_lane0_ce4=0xC +serdes_driver_current_lane1_ce4=0xF +serdes_driver_current_lane2_ce4=0xC +serdes_driver_current_lane3_ce4=0xC +serdes_preemphasis_lane0_ce4=0x304000 +serdes_preemphasis_lane1_ce4=0x313F00 +serdes_preemphasis_lane2_ce4=0x2F4100 +serdes_preemphasis_lane3_ce4=0x2E4200 +serdes_if_type_ce4=14 + +serdes_driver_current_lane0_ce5=0xE +serdes_driver_current_lane1_ce5=0xF +serdes_driver_current_lane2_ce5=0xF +serdes_driver_current_lane3_ce5=0xF +serdes_preemphasis_lane0_ce5=0x304000 +serdes_preemphasis_lane1_ce5=0x3F3100 +serdes_preemphasis_lane2_ce5=0x383800 +serdes_preemphasis_lane3_ce5=0x3F3100 +serdes_if_type_ce5=14 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/default_sku new file mode 100644 index 000000000000..ba80569555d1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S8900-54XC t1 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/fancontrol new file mode 100644 index 000000000000..e1f88f6b79c5 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/0-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon1/device/temp2_input hwmon1/device/pwm1=hwmon1/device/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm2=20 hwmon1/device/pwm1=20 +MAXTEMP=hwmon1/device/pwm2=60 hwmon1/device/pwm1=60 +MINSTART=hwmon1/device/pwm2=75 hwmon1/device/pwm1=75 +MINSTOP=hwmon1/device/pwm2=22 hwmon1/device/pwm1=22 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/led_proc_init.soc b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/led_proc_init.soc new file mode 100644 index 000000000000..8eef1389abc8 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/led_proc_init.soc @@ -0,0 +1,43 @@ +# LED microprocessor initialization for Ingrasys S8900-54XC + +led 0 stop +led 0 prog 12 00 61 F1 12 10 61 F2 12 01 61 F3 12 01 61 F4 67 28 12 10 61 F1 12 05 61 F2 12 04 61 F3 12 04 61 F4 67 28 86 F0 77 86 96 F2 2E F1 67 3D 67 51 16 F3 FE F1 61 F1 12 00 DE F2 74 28 57 2E F1 32 00 32 01 B7 97 75 4C 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 6A 77 5A 06 FE D2 01 70 62 77 78 06 F0 C2 08 74 6A 77 78 16 F4 91 22 0E 87 22 0E 87 DA 00 74 6C 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 7A 57 02 48 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=36 REMAP_PORT_2=37 REMAP_PORT_1=38 REMAP_PORT_0=39 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=40 REMAP_PORT_6=41 REMAP_PORT_5=42 REMAP_PORT_4=43 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=12 REMAP_PORT_10=13 REMAP_PORT_9=14 REMAP_PORT_8=15 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=44 REMAP_PORT_14=45 REMAP_PORT_13=46 REMAP_PORT_12=47 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=48 REMAP_PORT_18=49 REMAP_PORT_17=50 REMAP_PORT_16=51 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8 REMAP_PORT_22=9 REMAP_PORT_21=10 REMAP_PORT_20=11 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4 REMAP_PORT_26=5 REMAP_PORT_25=6 REMAP_PORT_24=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 REMAP_PORT_30=1 REMAP_PORT_29=2 REMAP_PORT_28=3 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=52 REMAP_PORT_34=53 REMAP_PORT_33=54 REMAP_PORT_32=55 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56 REMAP_PORT_38=57 REMAP_PORT_37=58 REMAP_PORT_36=59 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=32 REMAP_PORT_42=33 REMAP_PORT_41=34 REMAP_PORT_40=35 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=59 REMAP_PORT_46=60 REMAP_PORT_45=61 REMAP_PORT_44=62 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=28 REMAP_PORT_50=29 REMAP_PORT_49=30 REMAP_PORT_48=31 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=24 REMAP_PORT_54=25 REMAP_PORT_53=26 REMAP_PORT_52=27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=20 REMAP_PORT_58=21 REMAP_PORT_57=22 REMAP_PORT_56=23 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=16 REMAP_PORT_62=17 REMAP_PORT_61=18 REMAP_PORT_60=19 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 12 00 61 F1 12 20 61 F2 12 01 61 F3 12 01 61 F4 67 28 12 20 61 F1 12 01 61 F2 12 04 61 F3 12 04 61 F4 67 28 86 F0 77 86 96 F2 2E F1 67 3D 67 51 16 F3 FE F1 61 F1 12 00 DE F2 74 28 57 2E F1 32 00 32 01 B7 97 75 4C 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 6A 77 5A 06 FE D2 01 70 62 77 78 06 F0 C2 08 74 6A 77 78 16 F4 91 22 0E 87 22 0E 87 DA 00 74 6C 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 7A 57 02 48 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8 REMAP_PORT_10=9 REMAP_PORT_9=10 REMAP_PORT_8=11 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=36 REMAP_PORT_14=37 REMAP_PORT_13=38 REMAP_PORT_12=39 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12 REMAP_PORT_18=13 REMAP_PORT_17=14 REMAP_PORT_16=15 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=16 REMAP_PORT_22=17 REMAP_PORT_21=18 REMAP_PORT_20=19 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=40 REMAP_PORT_26=41 REMAP_PORT_25=42 REMAP_PORT_24=43 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=44 REMAP_PORT_30=45 REMAP_PORT_29=46 REMAP_PORT_28=47 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=20 REMAP_PORT_34=21 REMAP_PORT_33=22 REMAP_PORT_32=23 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=24 REMAP_PORT_38=25 REMAP_PORT_37=26 REMAP_PORT_36=27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=48 REMAP_PORT_42=49 REMAP_PORT_41=50 REMAP_PORT_40=51 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=52 REMAP_PORT_46=53 REMAP_PORT_45=54 REMAP_PORT_44=55 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=28 REMAP_PORT_50=29 REMAP_PORT_49=30 REMAP_PORT_48=31 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=32 REMAP_PORT_54=33 REMAP_PORT_53=34 REMAP_PORT_52=35 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56 REMAP_PORT_58=57 REMAP_PORT_57=58 REMAP_PORT_56=59 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60 REMAP_PORT_62=61 REMAP_PORT_61=62 REMAP_PORT_60=63 +led 1 auto on +led 1 start diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/eeprom.py new file mode 100644 index 000000000000..fcfaf8a27947 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Dell Z9100 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-17/17-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/psuutil.py new file mode 100644 index 000000000000..ef45a0c91727 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/psuutil.py @@ -0,0 +1,91 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_CPLD_DIR = "/sys/bus/i2c/devices/0-0033" + + 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 ", attr_path, " file !") + + 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 + mask = [0x08, 0x10] + attr_file = 'cpld_pw_good' + attr_path = self.PSU_CPLD_DIR + '/' + 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 & mask[index-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 + mask = [0x01, 0x02] + attr_file = 'cpld_pw_abs' + attr_path = self.PSU_CPLD_DIR + '/' + 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 & mask[index-1]): + status = 1 + + return status diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/sfputil.py new file mode 100644 index 000000000000..c7a4dfa471b6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/plugins/sfputil.py @@ -0,0 +1,321 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +import os + +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 = 0 + PORT_END = 53 + QSFP_PORT_START = 48 + PORTS_IN_BLOCK = 54 + GPIO_OFFSET = 0 + + BASE_DIR_PATH = "/sys/class/gpio/gpio{0}/direction" + BASE_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 18, + 1: 19, + 2: 20, + 3: 21, + 4: 22, + 5: 23, + 6: 24, + 7: 25, + 8: 26, + 9: 27, + 10: 28, + 11: 29, + 12: 30, + 13: 31, + 14: 32, + 15: 33, + 16: 34, + 17: 35, + 18: 36, + 19: 37, + 20: 38, + 21: 39, + 22: 40, + 23: 41, + 24: 42, + 25: 43, + 26: 44, + 27: 45, + 28: 46, + 29: 47, + 30: 48, + 31: 49, + 32: 50, + 33: 51, + 34: 52, + 35: 53, + 36: 54, + 37: 55, + 38: 56, + 39: 57, + 40: 58, + 41: 59, + 42: 60, + 43: 61, + 44: 62, + 45: 63, + 46: 64, + 47: 65, + 48: 66, + 49: 67, + 50: 68, + 51: 69, + 52: 70, + 53: 71 + } + + abs_to_gpio_mapping = {} + lpmode_to_gpio_mapping = {} + reset_to_gpio_mapping = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:], 10) + except ValueError as e: + print("Error: %s" % str(e)) + if gpiochip_no > 255: + self.GPIO_OFFSET = 256 + return True + return True + + def init_abs_to_gpio_mapping(self): + self.abs_to_gpio_mapping = { + 0: 192+self.GPIO_OFFSET, + 1: 193+self.GPIO_OFFSET, + 2: 194+self.GPIO_OFFSET, + 3: 195+self.GPIO_OFFSET, + 4: 196+self.GPIO_OFFSET, + 5: 197+self.GPIO_OFFSET, + 6: 198+self.GPIO_OFFSET, + 7: 199+self.GPIO_OFFSET, + 8: 200+self.GPIO_OFFSET, + 9: 201+self.GPIO_OFFSET, + 10: 202+self.GPIO_OFFSET, + 11: 203+self.GPIO_OFFSET, + 12: 204+self.GPIO_OFFSET, + 13: 205+self.GPIO_OFFSET, + 14: 206+self.GPIO_OFFSET, + 15: 207+self.GPIO_OFFSET, + 16: 176+self.GPIO_OFFSET, + 17: 177+self.GPIO_OFFSET, + 18: 178+self.GPIO_OFFSET, + 19: 179+self.GPIO_OFFSET, + 20: 180+self.GPIO_OFFSET, + 21: 181+self.GPIO_OFFSET, + 22: 182+self.GPIO_OFFSET, + 23: 183+self.GPIO_OFFSET, + 24: 184+self.GPIO_OFFSET, + 25: 185+self.GPIO_OFFSET, + 26: 186+self.GPIO_OFFSET, + 27: 187+self.GPIO_OFFSET, + 28: 188+self.GPIO_OFFSET, + 29: 189+self.GPIO_OFFSET, + 30: 190+self.GPIO_OFFSET, + 31: 191+self.GPIO_OFFSET, + 32: 160+self.GPIO_OFFSET, + 33: 161+self.GPIO_OFFSET, + 34: 162+self.GPIO_OFFSET, + 35: 163+self.GPIO_OFFSET, + 36: 164+self.GPIO_OFFSET, + 37: 165+self.GPIO_OFFSET, + 38: 166+self.GPIO_OFFSET, + 39: 167+self.GPIO_OFFSET, + 40: 168+self.GPIO_OFFSET, + 41: 169+self.GPIO_OFFSET, + 42: 170+self.GPIO_OFFSET, + 43: 171+self.GPIO_OFFSET, + 44: 172+self.GPIO_OFFSET, + 45: 173+self.GPIO_OFFSET, + 46: 174+self.GPIO_OFFSET, + 47: 175+self.GPIO_OFFSET, + 48: 240+self.GPIO_OFFSET, + 49: 241+self.GPIO_OFFSET, + 50: 242+self.GPIO_OFFSET, + 51: 243+self.GPIO_OFFSET, + 52: 244+self.GPIO_OFFSET, + 53: 245+self.GPIO_OFFSET + } + return True + + def init_lpmode_to_gpio_mapping(self): + self.lpmode_to_gpio_mapping = { + 48: 224+self.GPIO_OFFSET, + 49: 225+self.GPIO_OFFSET, + 50: 226+self.GPIO_OFFSET, + 51: 227+self.GPIO_OFFSET, + 52: 228+self.GPIO_OFFSET, + 53: 229+self.GPIO_OFFSET + } + return True + + def init_reset_to_gpio_mapping(self): + self.reset_to_gpio_mapping = { + 48: 208+self.GPIO_OFFSET, + 49: 209+self.GPIO_OFFSET, + 50: 210+self.GPIO_OFFSET, + 51: 211+self.GPIO_OFFSET, + 52: 212+self.GPIO_OFFSET, + 53: 213+self.GPIO_OFFSET + } + return True + + def __init__(self): + # Init abs, lpmode, and reset to gpio mapping + self.set_gpio_offset() + self.init_abs_to_gpio_mapping() + self.init_lpmode_to_gpio_mapping() + self.init_reset_to_gpio_mapping() + + # Override port_to_eeprom_mapping for class initialization + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/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) + + 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 + + try: + abs_device_file = self.BASE_VAL_PATH.format( + self.abs_to_gpio_mapping[port_num]) + val_file = open(abs_device_file) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + 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 + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + 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 + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("1" if lpmode is True else "0") + val_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.port_end: + print("Error: unable to reset non-QSFP module: port %s" % str(port_num)) + return False + + try: + print("port %s" % str(port_num)) + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("1") + val_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("0") + val_file.close() + + return True + + 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 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/sensors.conf new file mode 100644 index 000000000000..88a474a06742 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_54xc-r0/sensors.conf @@ -0,0 +1,39 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +chip "w83795adg-*" + label in0 "1.0V" + label in1 "1.0V_ROV" + label in2 "1.25V" + label in3 "1.8V" + ignore in4 + ignore in5 + ignore in6 + ignore in7 + label in12 "+3.3V" + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + label temp1 "Front MAC Temp" + set temp1_max 70 + set temp1_crit 80 + label temp2 "Rear MAC Temp" + set temp1_max 70 + set temp1_crit 80 + ignore temp3 + ignore temp4 + ignore intrusion0 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/port_config.ini b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/port_config.ini new file mode 100644 index 000000000000..385056e6e8f0 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index +Ethernet0 17 Ethernet1/1 0 +Ethernet1 18 Ethernet2/1 1 +Ethernet2 19 Ethernet3/1 2 +Ethernet3 20 Ethernet4/1 3 +Ethernet4 24 Ethernet5/1 4 +Ethernet5 23 Ethernet6/1 5 +Ethernet6 22 Ethernet7/1 6 +Ethernet7 21 Ethernet8/1 7 +Ethernet8 28 Ethernet9/1 8 +Ethernet9 27 Ethernet10/1 9 +Ethernet10 26 Ethernet11/1 10 +Ethernet11 25 Ethernet12/1 11 +Ethernet12 32 Ethernet13/1 12 +Ethernet13 31 Ethernet14/1 13 +Ethernet14 30 Ethernet15/1 14 +Ethernet15 29 Ethernet16/1 15 +Ethernet16 1 Ethernet17/1 16 +Ethernet17 2 Ethernet18/1 17 +Ethernet18 3 Ethernet19/1 18 +Ethernet19 4 Ethernet20/1 19 +Ethernet20 8 Ethernet21/1 20 +Ethernet21 7 Ethernet22/1 21 +Ethernet22 6 Ethernet23/1 22 +Ethernet23 5 Ethernet24/1 23 +Ethernet24 12 Ethernet25/1 24 +Ethernet25 11 Ethernet26/1 25 +Ethernet26 10 Ethernet27/1 26 +Ethernet27 9 Ethernet28/1 27 +Ethernet28 13 Ethernet29/1 28 +Ethernet29 14 Ethernet30/1 29 +Ethernet30 15 Ethernet31/1 30 +Ethernet31 16 Ethernet32/1 31 +Ethernet32 33 Ethernet33/1 32 +Ethernet33 34 Ethernet34/1 33 +Ethernet34 35 Ethernet35/1 34 +Ethernet35 36 Ethernet36/1 35 +Ethernet36 38 Ethernet37/1 36 +Ethernet37 39 Ethernet38/1 37 +Ethernet38 40 Ethernet39/1 38 +Ethernet39 37 Ethernet40/1 39 +Ethernet40 41 Ethernet41/1 40 +Ethernet41 42 Ethernet42/1 41 +Ethernet42 43 Ethernet43/1 42 +Ethernet43 44 Ethernet44/1 43 +Ethernet44 48 Ethernet45/1 44 +Ethernet45 45 Ethernet46/1 45 +Ethernet46 46 Ethernet47/1 46 +Ethernet47 47 Ethernet48/1 47 +Ethernet48 49,50,51,52 Ethernet49/1 48 +Ethernet52 53,54,55,56 Ethernet50/1 49 +Ethernet56 57,58,59,60 Ethernet51/1 50 +Ethernet60 61,62,63,64 Ethernet52/1 51 +Ethernet64 65,66,67,68 Ethernet53/1 52 +Ethernet68 69,70,71,72 Ethernet54/1 53 +Ethernet72 73,74,75,76 Ethernet55/1 54 +Ethernet76 77,78,79,80 Ethernet56/1 55 +Ethernet80 81,82,83,84 Ethernet57/1 56 +Ethernet84 85,86,87,88 Ethernet58/1 57 +Ethernet88 89,90,91,92 Ethernet59/1 58 +Ethernet92 93,94,95,96 Ethernet60/1 59 +Ethernet96 97,98,99,100 Ethernet61/1 60 +Ethernet100 101,102,103,104 Ethernet62/1 61 +Ethernet104 105,106,107,108 Ethernet63/1 62 +Ethernet108 109,110,111,112 Ethernet64/1 63 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/sai.profile b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/sai.profile new file mode 100644 index 000000000000..1100f7199a3e --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s8900-48x25G+16x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/th-s8900-48x25G+16x100G.config.bcm b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/th-s8900-48x25G+16x100G.config.bcm new file mode 100644 index 000000000000..f30d4ea6dd34 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/INGRASYS-S8900-64XC/th-s8900-48x25G+16x100G.config.bcm @@ -0,0 +1,448 @@ +#2018/03/31 + +os=unix + +oversubscribe_mode=1 +pbmp_xport_xe=0x3c000000ff0003ffffdfffffffe + +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l3_mem_entries=40960 +l2_mem_entries=40960 + +l2xmsg_mode=1 +mmu_lossless=0 + +#Parity +parity_correction=1 +parity_enable=1 + +#PIPE0 +portmap_1=17:25 +portmap_2=18:25 +portmap_3=19:25 +portmap_4=20:25 +portmap_5=24:25 +portmap_6=23:25 +portmap_7=22:25 +portmap_8=21:25 +portmap_9=28:25 +portmap_10=27:25 +portmap_11=26:25 +portmap_12=25:25 +portmap_13=32:25 +portmap_14=31:25 +portmap_15=30:25 +portmap_16=29:25 +portmap_17=1:25 +portmap_18=2:25 +portmap_19=3:25 +portmap_20=4:25 +portmap_21=8:25 +portmap_22=7:25 +portmap_23=6:25 +portmap_24=5:25 +portmap_25=12:25 +portmap_26=11:25 +portmap_27=10:25 +portmap_28=9:25 +portmap_29=13:25 +portmap_30=14:25 +portmap_31=15:25 +portmap_32=16:25 + +#PIPE1 +portmap_34=33:25 +portmap_35=34:25 +portmap_36=35:25 +portmap_37=36:25 +portmap_38=38:25 +portmap_39=39:25 +portmap_40=40:25 +portmap_41=37:25 +portmap_42=41:25 +portmap_43=42:25 +portmap_44=43:25 +portmap_45=44:25 +portmap_46=48:25 +portmap_47=45:25 +portmap_48=46:25 +portmap_49=47:25 +portmap_50=49:100 +portmap_51=53:100 +portmap_52=57:100 +portmap_53=61:100 + +#PIPE2 +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 + +#PIPE3 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 + + +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +serdes_driver_current_xe0=0xf +serdes_preemphasis_xe0=0x003c14 +serdes_if_type_xe0=14 + +serdes_driver_current_xe1=0xf +serdes_preemphasis_xe1=0x003c1c +serdes_if_type_xe1=14 + +serdes_driver_current_xe2=0xf +serdes_preemphasis_xe2=0x003c08 +serdes_if_type_xe2=14 + +serdes_driver_current_xe3=0xf +serdes_preemphasis_xe3=0x003c08 +serdes_if_type_xe3=14 + +serdes_driver_current_xe4=0xf +serdes_preemphasis_xe4=0x003c08 +serdes_if_type_xe4=14 + +serdes_driver_current_xe5=0xf +serdes_preemphasis_xe5=0x003c10 +serdes_if_type_xe5=14 + +serdes_driver_current_xe6=0xf +serdes_preemphasis_xe6=0x083c08 +serdes_if_type_xe6=14 + +serdes_driver_current_xe7=0xf +serdes_preemphasis_xe7=0x043c10 +serdes_if_type_xe7=14 + +serdes_driver_current_xe8=0x9 +serdes_preemphasis_xe8=0x003c08 +serdes_if_type_xe8=14 + +serdes_driver_current_xe9=0x9 +serdes_preemphasis_xe9=0x003c08 +serdes_if_type_xe9=14 + +serdes_driver_current_xe10=0x9 +serdes_preemphasis_xe10=0x003c08 +serdes_if_type_xe10=14 + +serdes_driver_current_xe11=0x9 +serdes_preemphasis_xe11=0x003c08 +serdes_if_type_xe11=14 + +serdes_driver_current_xe12=0x9 +serdes_preemphasis_xe12=0x2c4408 +serdes_if_type_xe12=14 + +serdes_driver_current_xe13=0x9 +serdes_preemphasis_xe13=0x003c08 +serdes_if_type_xe13=14 + +serdes_driver_current_xe14=0x9 +serdes_preemphasis_xe14=0x003c08 +serdes_if_type_xe14=14 + +serdes_driver_current_xe15=0x9 +serdes_preemphasis_xe15=0x003c08 +serdes_if_type_xe15=14 + +serdes_driver_current_xe16=0xb +serdes_preemphasis_xe16=0x0c3c08 +serdes_if_type_xe16=14 + +serdes_driver_current_xe17=0xb +serdes_preemphasis_xe17=0x0c3c10 +serdes_if_type_xe17=14 + +serdes_driver_current_xe18=0xa +serdes_preemphasis_xe18=0x083c08 +serdes_if_type_xe18=14 + +serdes_driver_current_xe19=0x9 +serdes_preemphasis_xe19=0x0c3c10 +serdes_if_type_xe19=14 + +serdes_driver_current_xe20=0xc +serdes_preemphasis_xe20=0x043c08 +serdes_if_type_xe20=14 + +serdes_driver_current_xe21=0x9 +serdes_preemphasis_xe21=0x083c08 +serdes_if_type_xe21=14 + +serdes_driver_current_xe22=0xc +serdes_preemphasis_xe22=0x083c08 +serdes_if_type_xe22=14 + +serdes_driver_current_xe23=0xa +serdes_preemphasis_xe23=0x083c10 +serdes_if_type_xe23=14 + +serdes_driver_current_xe24=0x9 +serdes_preemphasis_xe24=0x083c08 +serdes_if_type_xe24=14 + +serdes_driver_current_xe25=0x9 +serdes_preemphasis_xe25=0x043c08 +serdes_if_type_xe25=14 + +serdes_driver_current_xe26=0x9 +serdes_preemphasis_xe26=0x003c08 +serdes_if_type_xe26=14 + +serdes_driver_current_xe27=0xc +serdes_preemphasis_xe27=0x083c08 +serdes_if_type_xe27=14 + +serdes_driver_current_xe28=0xa +serdes_preemphasis_xe28=0x003c10 +serdes_if_type_xe28=14 + +serdes_driver_current_xe29=0x9 +serdes_preemphasis_xe29=0x043c10 +serdes_if_type_xe29=14 + +serdes_driver_current_xe30=0x9 +serdes_preemphasis_xe30=0x003c14 +serdes_if_type_xe30=14 + +serdes_driver_current_xe31=0xa +serdes_preemphasis_xe31=0x003c14 +serdes_if_type_xe31=14 + +serdes_driver_current_xe32=0x9 +serdes_preemphasis_xe32=0x003c08 +serdes_if_type_xe32=14 + +serdes_driver_current_xe33=0x7 +serdes_preemphasis_xe33=0x003c08 +serdes_if_type_xe33=14 + +serdes_driver_current_xe34=0x9 +serdes_preemphasis_xe34=0x003c08 +serdes_if_type_xe34=14 + +serdes_driver_current_xe35=0x9 +serdes_preemphasis_xe35=0x003c08 +serdes_if_type_xe35=14 + +serdes_driver_current_xe36=0x9 +serdes_preemphasis_xe36=0x003c08 +serdes_if_type_xe36=14 + +serdes_driver_current_xe37=0x9 +serdes_preemphasis_xe37=0x003c0c +serdes_if_type_xe37=14 + +serdes_driver_current_xe38=0x9 +serdes_preemphasis_xe38=0x003c08 +serdes_if_type_xe38=14 + +serdes_driver_current_xe39=0x9 +serdes_preemphasis_xe39=0x003c08 +serdes_if_type_xe39=14 + +serdes_driver_current_xe40=0xa +serdes_preemphasis_xe40=0x003c10 +serdes_if_type_xe40=14 + +serdes_driver_current_xe41=0x9 +serdes_preemphasis_xe41=0x003c10 +serdes_if_type_xe41=14 + +serdes_driver_current_xe42=0xc +serdes_preemphasis_xe42=0x083c08 +serdes_if_type_xe42=14 + +serdes_driver_current_xe43=0xa +serdes_preemphasis_xe43=0x003c10 +serdes_if_type_xe43=14 + +serdes_driver_current_xe44=0xa +serdes_preemphasis_xe44=0x003c08 +serdes_if_type_xe44=14 + +serdes_driver_current_xe45=0x9 +serdes_preemphasis_xe45=0x003c10 +serdes_if_type_xe45=14 + +serdes_driver_current_xe46=0x9 +serdes_preemphasis_xe46=0x043c08 +serdes_if_type_xe46=14 + +serdes_driver_current_xe47=0xa +serdes_preemphasis_xe47=0x003c08 +serdes_if_type_xe47=14 + +serdes_driver_current_lane0_ce0=0x9 +serdes_driver_current_lane1_ce0=0xf +serdes_driver_current_lane2_ce0=0x9 +serdes_driver_current_lane3_ce0=0x9 +serdes_preemphasis_lane0_ce0=0x003c08 +serdes_preemphasis_lane1_ce0=0x003c08 +serdes_preemphasis_lane2_ce0=0x003c08 +serdes_preemphasis_lane3_ce0=0x003c08 +serdes_if_type_ce0=14 + +serdes_driver_current_lane0_ce1=0x9 +serdes_driver_current_lane1_ce1=0x9 +serdes_driver_current_lane2_ce1=0x9 +serdes_driver_current_lane3_ce1=0xe +serdes_preemphasis_lane0_ce1=0x003c08 +serdes_preemphasis_lane1_ce1=0x003c08 +serdes_preemphasis_lane2_ce1=0x003c08 +serdes_preemphasis_lane3_ce1=0x003c08 +serdes_if_type_ce1=14 + +serdes_driver_current_lane0_ce2=0x9 +serdes_driver_current_lane1_ce2=0xf +serdes_driver_current_lane2_ce2=0x9 +serdes_driver_current_lane3_ce2=0xd +serdes_preemphasis_lane0_ce2=0x003c08 +serdes_preemphasis_lane1_ce2=0x003c08 +serdes_preemphasis_lane2_ce2=0x003c08 +serdes_preemphasis_lane3_ce2=0x003c08 +serdes_if_type_ce2=14 + +serdes_driver_current_lane0_ce3=0x9 +serdes_driver_current_lane1_ce3=0xd +serdes_driver_current_lane2_ce3=0x9 +serdes_driver_current_lane3_ce3=0xd +serdes_preemphasis_lane0_ce3=0x003c08 +serdes_preemphasis_lane1_ce3=0x003c08 +serdes_preemphasis_lane2_ce3=0x003c08 +serdes_preemphasis_lane3_ce3=0x003c08 +serdes_if_type_ce3=14 + +serdes_driver_current_lane0_ce4=0x9 +serdes_driver_current_lane1_ce4=0x9 +serdes_driver_current_lane2_ce4=0x9 +serdes_driver_current_lane3_ce4=0xd +serdes_preemphasis_lane0_ce4=0x003c08 +serdes_preemphasis_lane1_ce4=0x003c08 +serdes_preemphasis_lane2_ce4=0x003c08 +serdes_preemphasis_lane3_ce4=0x003c08 +serdes_if_type_ce4=14 + +serdes_driver_current_lane0_ce5=0x9 +serdes_driver_current_lane1_ce5=0xf +serdes_driver_current_lane2_ce5=0x9 +serdes_driver_current_lane3_ce5=0x9 +serdes_preemphasis_lane0_ce5=0x003c08 +serdes_preemphasis_lane1_ce5=0x003c08 +serdes_preemphasis_lane2_ce5=0x003c08 +serdes_preemphasis_lane3_ce5=0x003c08 +serdes_if_type_ce5=14 + +serdes_driver_current_lane0_ce6=0x9 +serdes_driver_current_lane1_ce6=0x9 +serdes_driver_current_lane2_ce6=0x9 +serdes_driver_current_lane3_ce6=0xe +serdes_preemphasis_lane0_ce6=0x003c08 +serdes_preemphasis_lane1_ce6=0x003c08 +serdes_preemphasis_lane2_ce6=0x003c08 +serdes_preemphasis_lane3_ce6=0x003c08 +serdes_if_type_ce6=14 + +serdes_driver_current_lane0_ce7=0x9 +serdes_driver_current_lane1_ce7=0xa +serdes_driver_current_lane2_ce7=0x9 +serdes_driver_current_lane3_ce7=0Xe +serdes_preemphasis_lane0_ce7=0x003c08 +serdes_preemphasis_lane1_ce7=0x003c08 +serdes_preemphasis_lane2_ce7=0x003c08 +serdes_preemphasis_lane3_ce7=0x003c08 +serdes_if_type_ce7=14 + +serdes_driver_current_lane0_ce8=0xf +serdes_driver_current_lane1_ce8=0xf +serdes_driver_current_lane2_ce8=0xf +serdes_driver_current_lane3_ce8=0xf +serdes_preemphasis_lane0_ce8=0x043c08 +serdes_preemphasis_lane1_ce8=0x003c08 +serdes_preemphasis_lane2_ce8=0x043c08 +serdes_preemphasis_lane3_ce8=0x003c08 +serdes_if_type_ce8=14 + +serdes_driver_current_lane0_ce9=0xf +serdes_driver_current_lane1_ce9=0xf +serdes_driver_current_lane2_ce9=0xf +serdes_driver_current_lane3_ce9=0xf +serdes_preemphasis_lane0_ce9=0x043c08 +serdes_preemphasis_lane1_ce9=0x043c08 +serdes_preemphasis_lane2_ce9=0x043c08 +serdes_preemphasis_lane3_ce9=0x043c08 +serdes_if_type_ce9=14 + +serdes_driver_current_lane0_ce10=0xf +serdes_driver_current_lane1_ce10=0xf +serdes_driver_current_lane2_ce10=0xf +serdes_driver_current_lane3_ce10=0xf +serdes_preemphasis_lane0_ce10=0x043c08 +serdes_preemphasis_lane1_ce10=0x083c10 +serdes_preemphasis_lane2_ce10=0x043c08 +serdes_preemphasis_lane3_ce10=0x043c08 +serdes_if_type_ce10=14 + +serdes_driver_current_lane0_ce11=0xf +serdes_driver_current_lane1_ce11=0xf +serdes_driver_current_lane2_ce11=0xf +serdes_driver_current_lane3_ce11=0xf +serdes_preemphasis_lane0_ce11=0x083c08 +serdes_preemphasis_lane1_ce11=0x043c08 +serdes_preemphasis_lane2_ce11=0X043c08 +serdes_preemphasis_lane3_ce11=0X043c08 +serdes_if_type_ce11=14 + +serdes_driver_current_lane0_ce12=0xf +serdes_driver_current_lane1_ce12=0xf +serdes_driver_current_lane2_ce12=0xf +serdes_driver_current_lane3_ce12=0xf +serdes_preemphasis_lane0_ce12=0x0c3c08 +serdes_preemphasis_lane1_ce12=0x083c08 +serdes_preemphasis_lane2_ce12=0x0c3c08 +serdes_preemphasis_lane3_ce12=0x083c08 +serdes_if_type_ce12=14 + +serdes_driver_current_lane0_ce13=0xf +serdes_driver_current_lane1_ce13=0xf +serdes_driver_current_lane2_ce13=0xf +serdes_driver_current_lane3_ce13=0xf +serdes_preemphasis_lane0_ce13=0x083c08 +serdes_preemphasis_lane1_ce13=0x0c3c08 +serdes_preemphasis_lane2_ce13=0x083c08 +serdes_preemphasis_lane3_ce13=0x0c3c08 +serdes_if_type_ce13=14 + +serdes_driver_current_lane0_ce14=0xf +serdes_driver_current_lane1_ce14=0xf +serdes_driver_current_lane2_ce14=0xf +serdes_driver_current_lane3_ce14=0xf +serdes_preemphasis_lane0_ce14=0x103c10 +serdes_preemphasis_lane1_ce14=0x0c3c08 +serdes_preemphasis_lane2_ce14=0x0c3c08 +serdes_preemphasis_lane3_ce14=0x0c3c08 +serdes_if_type_ce14=14 + +serdes_driver_current_lane0_ce15=0xf +serdes_driver_current_lane1_ce15=0xf +serdes_driver_current_lane2_ce15=0xf +serdes_driver_current_lane3_ce15=0xf +serdes_preemphasis_lane0_ce15=0x143c08 +serdes_preemphasis_lane1_ce15=0x103c08 +serdes_preemphasis_lane2_ce15=0x103c08 +serdes_preemphasis_lane3_ce15=0x103c08 +serdes_if_type_ce15=14 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/default_sku new file mode 100644 index 000000000000..3002ec5856f3 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S8900-64XC t1 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/fancontrol new file mode 100644 index 000000000000..4819fe113172 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/0-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm1=hwmon1/device/temp2_input hwmon1/device/pwm2=hwmon1/device/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan10_input hwmon1/device/pwm2=hwmon1/device/fan9_input hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm1=20 hwmon1/device/pwm2=20 +MAXTEMP=hwmon1/device/pwm1=60 hwmon1/device/pwm2=60 +MINSTART=hwmon1/device/pwm1=150 hwmon1/device/pwm2=150 +MINSTOP=hwmon1/device/pwm1=0 hwmon1/device/pwm2=0 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/led_proc_init.soc b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/led_proc_init.soc new file mode 100644 index 000000000000..6a1f4f2c1ea6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/led_proc_init.soc @@ -0,0 +1,43 @@ +# LED microprocessor initialization for Ingrasys S8900-64XC + +led 0 stop +led 0 prog 12 00 61 F1 12 20 61 F2 12 01 61 F3 12 01 61 F4 67 28 12 20 61 F1 12 04 61 F2 12 04 61 F3 12 01 61 F4 67 28 86 F0 77 86 96 F2 2E F1 67 3D 67 51 16 F3 FE F1 61 F1 12 00 DE F2 74 28 57 2E F1 32 00 32 01 B7 97 75 4C 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 6A 77 5A 06 FE D2 01 70 62 77 78 06 F0 C2 08 74 6A 77 78 16 F4 91 22 0E 87 22 0E 87 DA 00 74 6C 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 7A 57 02 48 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 REMAP_PORT_2=29 REMAP_PORT_1=30 REMAP_PORT_0=31 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 REMAP_PORT_6=25 REMAP_PORT_5=26 REMAP_PORT_4=27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=20 REMAP_PORT_10=21 REMAP_PORT_9=22 REMAP_PORT_8=19 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=16 REMAP_PORT_14=17 REMAP_PORT_13=18 REMAP_PORT_12=23 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12 REMAP_PORT_18=13 REMAP_PORT_17=14 REMAP_PORT_16=15 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8 REMAP_PORT_22=9 REMAP_PORT_21=10 REMAP_PORT_20=11 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4 REMAP_PORT_26=5 REMAP_PORT_25=6 REMAP_PORT_24=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 REMAP_PORT_30=1 REMAP_PORT_29=2 REMAP_PORT_28=3 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=60 REMAP_PORT_34=61 REMAP_PORT_33=62 REMAP_PORT_32=63 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56 REMAP_PORT_38=57 REMAP_PORT_37=58 REMAP_PORT_36=59 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 REMAP_PORT_42=53 REMAP_PORT_41=54 REMAP_PORT_40=55 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 REMAP_PORT_46=49 REMAP_PORT_45=50 REMAP_PORT_44=51 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=44 REMAP_PORT_50=45 REMAP_PORT_49=46 REMAP_PORT_48=47 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=40 REMAP_PORT_54=41 REMAP_PORT_53=42 REMAP_PORT_52=43 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=36 REMAP_PORT_58=37 REMAP_PORT_57=38 REMAP_PORT_56=39 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=32 REMAP_PORT_62=33 REMAP_PORT_61=34 REMAP_PORT_60=35 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 12 00 61 F1 12 10 61 F2 12 01 61 F3 12 01 61 F4 67 28 12 10 61 F1 12 0C 61 F2 12 04 61 F3 12 01 61 F4 67 28 86 F0 77 86 96 F2 2E F1 67 3D 67 51 16 F3 FE F1 61 F1 12 00 DE F2 74 28 57 2E F1 32 00 32 01 B7 97 75 4C 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 6A 77 5A 06 FE D2 01 70 62 77 78 06 F0 C2 08 74 6A 77 78 16 F4 91 22 0E 87 22 0E 87 DA 00 74 6C 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 7A 57 02 38 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8 REMAP_PORT_10=9 REMAP_PORT_9=10 REMAP_PORT_8=11 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=12 REMAP_PORT_14=13 REMAP_PORT_13=14 REMAP_PORT_12=15 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 REMAP_PORT_18=17 REMAP_PORT_17=18 REMAP_PORT_16=19 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 REMAP_PORT_22=21 REMAP_PORT_21=22 REMAP_PORT_20=23 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=24 REMAP_PORT_26=25 REMAP_PORT_25=26 REMAP_PORT_24=27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=28 REMAP_PORT_30=29 REMAP_PORT_29=30 REMAP_PORT_28=31 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 REMAP_PORT_34=33 REMAP_PORT_33=34 REMAP_PORT_32=35 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 REMAP_PORT_38=37 REMAP_PORT_37=38 REMAP_PORT_36=39 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 REMAP_PORT_42=41 REMAP_PORT_41=42 REMAP_PORT_40=43 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 REMAP_PORT_46=45 REMAP_PORT_45=46 REMAP_PORT_44=47 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 REMAP_PORT_50=49 REMAP_PORT_49=50 REMAP_PORT_48=51 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 REMAP_PORT_54=53 REMAP_PORT_53=54 REMAP_PORT_52=55 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56 REMAP_PORT_58=57 REMAP_PORT_57=58 REMAP_PORT_56=59 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60 REMAP_PORT_62=61 REMAP_PORT_61=62 REMAP_PORT_60=63 +led 1 auto on +led 1 start diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/eeprom.py new file mode 100644 index 000000000000..1737549081a6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Ingrasys S8900-64XC +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-7/7-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/psuutil.py new file mode 100644 index 000000000000..e97e3193fd64 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/psuutil.py @@ -0,0 +1,91 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_CPLD_DIR = "/sys/bus/i2c/devices/0-0033" + + 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 ", attr_path, " file !") + + 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 + mask = [0x04, 0x08] + attr_file = 'cpld_pw_good' + attr_path = self.PSU_CPLD_DIR + '/' + 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 & mask[index-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 + mask = [0x01, 0x02] + attr_file = 'cpld_pw_abs' + attr_path = self.PSU_CPLD_DIR + '/' + 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 & mask[index-1]): + status = 1 + + return status diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/sfputil.py new file mode 100644 index 000000000000..cc2c01d3bd33 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/plugins/sfputil.py @@ -0,0 +1,265 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import subprocess + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +i2c_set = 'i2cset' +i2c_get = 'i2cget' +cpld_addr = '0x33' +mux_reg = '0x4A' + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 63 + QSFP_PORT_START = 48 + PORTS_IN_BLOCK = 64 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: [2, 1], + 1: [2, 2], + 2: [2, 3], + 3: [2, 4], + 4: [2, 5], + 5: [2, 6], + 6: [2, 7], + 7: [2, 8], + 8: [2, 9], + 9: [2, 10], + 10: [2, 11], + 11: [2, 12], + 12: [2, 13], + 13: [2, 14], + 14: [2, 15], + 15: [2, 16], + 16: [2, 17], + 17: [2, 18], + 18: [2, 19], + 19: [2, 20], + 20: [2, 21], + 21: [2, 22], + 22: [2, 23], + 23: [2, 24], + 24: [3, 25], + 25: [3, 26], + 26: [3, 27], + 27: [3, 28], + 28: [3, 29], + 29: [3, 30], + 30: [3, 31], + 31: [3, 32], + 32: [3, 33], + 33: [3, 34], + 34: [3, 35], + 35: [3, 36], + 36: [3, 37], + 37: [3, 38], + 38: [3, 39], + 39: [3, 40], + 40: [3, 41], + 41: [3, 42], + 42: [3, 43], + 43: [3, 44], + 44: [3, 45], + 45: [3, 46], + 46: [3, 47], + 47: [3, 48], + 48: [4, 49], + 49: [4, 50], + 50: [4, 51], + 51: [4, 52], + 52: [4, 53], + 53: [4, 54], + 54: [4, 55], + 55: [4, 56], + 56: [4, 57], + 57: [4, 58], + 58: [4, 59], + 59: [4, 60], + 60: [4, 61], + 61: [4, 62], + 62: [4, 63], + 63: [4, 64] + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + def __init__(self): + + sfp_eeprom_path = '/sys/bus/i2c/devices/{0[0]}-0050/sfp{0[1]}' + qsfp_eeprom_path = '/sys/bus/i2c/devices/{0[0]}-0050/qsfp{0[1]}' + for x in range(self.port_start, self.qsfp_port_start): + port_eeprom_path = sfp_eeprom_path.format(self.port_to_i2c_mapping[x]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + for x in range(self.qsfp_port_start, self.port_end + 1): + port_eeprom_path = qsfp_eeprom_path.format(self.port_to_i2c_mapping[x]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_modprs") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # content is a string, either "0" or "1" + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (port_num - self.qsfp_port_start)) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (port_num - self.qsfp_port_start)) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_reset" + + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.port_end: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << (port_num - self.qsfp_port_start)) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/sensors.conf new file mode 100644 index 000000000000..374bd3a64f04 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s8900_64xc-r0/sensors.conf @@ -0,0 +1,55 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +chip "w83795adg-*" + label in0 "1.0V" + label in1 "1.0V_ROV" + label in2 "1.25V" + label in3 "1.8V" + ignore in4 + ignore in5 + ignore in6 + ignore in7 + label in12 "+3.3V" + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + label fan9 "FANTRAY 5-A" + label fan10 "FANTRAY 5-B" + label temp1 "Front MAC Temp" + set temp1_max 60 + set temp1_crit 65 + label temp2 "Rear MAC Temp" + set temp2_max 60 + set temp2_crit 65 + label temp3 "Near Port 15" + set temp3_max 50 + set temp3_crit 70 + label temp4 "Near Port 56" + set temp4_max 50 + set temp4_crit 70 + ignore intrusion0 + +bus "i2c-5" "i2c-1-switch (chan_id 3)" +chip "tmp75-i2c-*-48" + label temp1 "FAN Temp1" + set temp1_max 50 + set temp1_crit 70 +chip "tmp75-i2c-*-49" + label temp1 "FAN Temp2" + set temp1_max 50 + set temp1_crit 70 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/port_config.ini new file mode 100644 index 000000000000..ab0202011576 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 5,6,7,8 Ethernet1/1 0 +Ethernet4 1,2,3,4 Ethernet2/1 1 +Ethernet8 13,14,15,16 Ethernet3/1 2 +Ethernet12 9,10,11,12 Ethernet4/1 3 +Ethernet16 21,22,23,24 Ethernet5/1 4 +Ethernet20 17,18,19,20 Ethernet6/1 5 +Ethernet24 29,30,31,32 Ethernet7/1 6 +Ethernet28 25,26,27,28 Ethernet8/1 7 +Ethernet32 37,38,39,40 Ethernet9/1 8 +Ethernet36 33,34,35,36 Ethernet10/1 9 +Ethernet40 45,46,47,48 Ethernet11/1 10 +Ethernet44 41,42,43,44 Ethernet12/1 11 +Ethernet48 53,54,55,56 Ethernet13/1 12 +Ethernet52 49,50,51,52 Ethernet14/1 13 +Ethernet56 61,62,63,64 Ethernet15/1 14 +Ethernet60 57,58,59,60 Ethernet16/1 15 +Ethernet64 69,70,71,72 Ethernet17/1 16 +Ethernet68 65,66,67,68 Ethernet18/1 17 +Ethernet72 77,78,79,80 Ethernet19/1 18 +Ethernet76 73,74,75,76 Ethernet20/1 19 +Ethernet80 85,86,87,88 Ethernet21/1 20 +Ethernet84 81,82,83,84 Ethernet22/1 21 +Ethernet88 93,94,95,96 Ethernet23/1 22 +Ethernet92 89,90,91,92 Ethernet24/1 23 +Ethernet96 101,102,103,104 Ethernet25/1 24 +Ethernet100 97,98,99,100 Ethernet26/1 25 +Ethernet104 109,110,111,112 Ethernet27/1 26 +Ethernet108 105,106,107,108 Ethernet28/1 27 +Ethernet112 117,118,119,120 Ethernet29/1 28 +Ethernet116 113,114,115,116 Ethernet30/1 29 +Ethernet120 125,126,127,128 Ethernet31/1 30 +Ethernet124 121,122,123,124 Ethernet32/1 31 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/sai.profile b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/sai.profile new file mode 100644 index 000000000000..11c0ae1ab636 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-s9100-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/th-s9100-32x100G.config.bcm b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/th-s9100-32x100G.config.bcm new file mode 100644 index 000000000000..46b8799efef2 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/INGRASYS-S9100-C32/th-s9100-32x100G.config.bcm @@ -0,0 +1,357 @@ +#2017/09/12 + +os=unix + +oversubscribe_mode=1 +pbmp_xport_xe=0x3fc000000ff0000003fc000001fe + +#ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l3_mem_entries=40960 +l2_mem_entries=40960 + +l2xmsg_mode=1 +mmu_lossless=0 + +#Parity +parity_correction=1 +parity_enable=1 + +#PIPE0 +portmap_1=5:100 +portmap_2=1:100 +portmap_3=13:100 +portmap_4=9:100 +portmap_5=21:100 +portmap_6=17:100 +portmap_7=29:100 +portmap_8=25:100 + +#PIPE1 +portmap_34=37:100 +portmap_35=33:100 +portmap_36=45:100 +portmap_37=41:100 +portmap_38=53:100 +portmap_39=49:100 +portmap_40=61:100 +portmap_41=57:100 + +#PIPE2 +portmap_68=69:100 +portmap_69=65:100 +portmap_70=77:100 +portmap_71=73:100 +portmap_72=85:100 +portmap_73=81:100 +portmap_74=93:100 +portmap_75=89:100 + +#PIPE3 +portmap_102=101:100 +portmap_103=97:100 +portmap_104=109:100 +portmap_105=105:100 +portmap_106=117:100 +portmap_107=113:100 +portmap_108=125:100 +portmap_109=121:100 + +#portmap_66=129:10 +#portmap_100=131:10 +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +serdes_driver_current_lane0_ce0=0xF +serdes_driver_current_lane1_ce0=0xF +serdes_driver_current_lane2_ce0=0xF +serdes_driver_current_lane3_ce0=0xF +serdes_preemphasis_lane0_ce0=0x153C1F +serdes_preemphasis_lane1_ce0=0x20341C +serdes_preemphasis_lane2_ce0=0x153C1F +serdes_preemphasis_lane3_ce0=0x243418 + +serdes_driver_current_lane0_ce1=0xF +serdes_driver_current_lane1_ce1=0xF +serdes_driver_current_lane2_ce1=0xF +serdes_driver_current_lane3_ce1=0xF +serdes_preemphasis_lane0_ce1=0x153C1F +serdes_preemphasis_lane1_ce1=0x20341C +serdes_preemphasis_lane2_ce1=0x153C1F +serdes_preemphasis_lane3_ce1=0x20341C + +serdes_driver_current_lane0_ce2=0xF +serdes_driver_current_lane1_ce2=0xD +serdes_driver_current_lane2_ce2=0xF +serdes_driver_current_lane3_ce2=0xD +serdes_preemphasis_lane0_ce2=0x153C1F +serdes_preemphasis_lane1_ce2=0x243418 +serdes_preemphasis_lane2_ce2=0x153C1F +serdes_preemphasis_lane3_ce2=0x203C14 + +serdes_driver_current_lane0_ce3=0xF +serdes_driver_current_lane1_ce3=0xD +serdes_driver_current_lane2_ce3=0xF +serdes_driver_current_lane3_ce3=0xD +serdes_preemphasis_lane0_ce3=0x153C1F +serdes_preemphasis_lane1_ce3=0x203C14 +serdes_preemphasis_lane2_ce3=0x153C1F +serdes_preemphasis_lane3_ce3=0x243418 + +serdes_driver_current_lane0_ce4=0xF +serdes_driver_current_lane1_ce4=0xB +serdes_driver_current_lane2_ce4=0xF +serdes_driver_current_lane3_ce4=0xA +serdes_preemphasis_lane0_ce4=0x153C1F +serdes_preemphasis_lane1_ce4=0x333D00 +serdes_preemphasis_lane2_ce4=0x153C1F +serdes_preemphasis_lane3_ce4=0x304000 + +serdes_driver_current_lane0_ce5=0xF +serdes_driver_current_lane1_ce5=0xB +serdes_driver_current_lane2_ce5=0xF +serdes_driver_current_lane3_ce5=0xA +serdes_preemphasis_lane0_ce5=0x153C1F +serdes_preemphasis_lane1_ce5=0x304000 +serdes_preemphasis_lane2_ce5=0x153C1F +serdes_preemphasis_lane3_ce5=0x304000 + +serdes_driver_current_lane0_ce6=0xF +serdes_driver_current_lane1_ce6=0xC +serdes_driver_current_lane2_ce6=0xF +serdes_driver_current_lane3_ce6=0xA +serdes_preemphasis_lane0_ce6=0x153C1F +serdes_preemphasis_lane1_ce6=0x363A00 +serdes_preemphasis_lane2_ce6=0x153C1F +serdes_preemphasis_lane3_ce6=0x304000 + +serdes_driver_current_lane0_ce7=0xF +serdes_driver_current_lane1_ce7=0x8 +serdes_driver_current_lane2_ce7=0xF +serdes_driver_current_lane3_ce7=0x8 +serdes_preemphasis_lane0_ce7=0x153C1F +serdes_preemphasis_lane1_ce7=0x304000 +serdes_preemphasis_lane2_ce7=0x153C1F +serdes_preemphasis_lane3_ce7=0x304000 + +serdes_driver_current_lane0_ce8=0x8 +serdes_driver_current_lane1_ce8=0x9 +serdes_driver_current_lane2_ce8=0x8 +serdes_driver_current_lane3_ce8=0x8 +serdes_preemphasis_lane0_ce8=0x254B00 +serdes_preemphasis_lane1_ce8=0x2C4400 +serdes_preemphasis_lane2_ce8=0x254B00 +serdes_preemphasis_lane3_ce8=0x254B00 + +serdes_driver_current_lane0_ce9=0x8 +serdes_driver_current_lane1_ce9=0x9 +serdes_driver_current_lane2_ce9=0x8 +serdes_driver_current_lane3_ce9=0x8 +serdes_preemphasis_lane0_ce9=0x254B00 +serdes_preemphasis_lane1_ce9=0x2B4500 +serdes_preemphasis_lane2_ce9=0x254B00 +serdes_preemphasis_lane3_ce9=0x254B00 + +serdes_driver_current_lane0_ce10=0x8 +serdes_driver_current_lane1_ce10=0x7 +serdes_driver_current_lane2_ce10=0x8 +serdes_driver_current_lane3_ce10=0x8 +serdes_preemphasis_lane0_ce10=0x254B00 +serdes_preemphasis_lane1_ce10=0x2B4500 +serdes_preemphasis_lane2_ce10=0x254B00 +serdes_preemphasis_lane3_ce10=0x254B00 + +serdes_driver_current_lane0_ce11=0x8 +serdes_driver_current_lane1_ce11=0x8 +serdes_driver_current_lane2_ce11=0x8 +serdes_driver_current_lane3_ce11=0x8 +serdes_preemphasis_lane0_ce11=0x254B00 +serdes_preemphasis_lane1_ce11=0x2C4400 +serdes_preemphasis_lane2_ce11=0x254B00 +serdes_preemphasis_lane3_ce11=0x254B00 + +serdes_driver_current_lane0_ce12=0x8 +serdes_driver_current_lane1_ce12=0x5 +serdes_driver_current_lane2_ce12=0x8 +serdes_driver_current_lane3_ce12=0x8 +serdes_preemphasis_lane0_ce12=0x254B00 +serdes_preemphasis_lane1_ce12=0x254B00 +serdes_preemphasis_lane2_ce12=0x254B00 +serdes_preemphasis_lane3_ce12=0x254B00 + +serdes_driver_current_lane0_ce13=0x8 +serdes_driver_current_lane1_ce13=0x8 +serdes_driver_current_lane2_ce13=0x8 +serdes_driver_current_lane3_ce13=0x8 +serdes_preemphasis_lane0_ce13=0x254B00 +serdes_preemphasis_lane1_ce13=0x254B00 +serdes_preemphasis_lane2_ce13=0x254B00 +serdes_preemphasis_lane3_ce13=0x254B00 + +serdes_driver_current_lane0_ce14=0x7 +serdes_driver_current_lane1_ce14=0x7 +serdes_driver_current_lane2_ce14=0x7 +serdes_driver_current_lane3_ce14=0x7 +serdes_preemphasis_lane0_ce14=0x254B00 +serdes_preemphasis_lane1_ce14=0x254B00 +serdes_preemphasis_lane2_ce14=0x254B00 +serdes_preemphasis_lane3_ce14=0x254B00 + +serdes_driver_current_lane0_ce15=0x7 +serdes_driver_current_lane1_ce15=0x5 +serdes_driver_current_lane2_ce15=0x7 +serdes_driver_current_lane3_ce15=0x7 +serdes_preemphasis_lane0_ce15=0x254B00 +serdes_preemphasis_lane1_ce15=0x254B00 +serdes_preemphasis_lane2_ce15=0x254B00 +serdes_preemphasis_lane3_ce15=0x254B00 + +serdes_driver_current_lane0_ce16=0x4 +serdes_driver_current_lane1_ce16=0x4 +serdes_driver_current_lane2_ce16=0x4 +serdes_driver_current_lane3_ce16=0x4 +serdes_preemphasis_lane0_ce16=0x274900 +serdes_preemphasis_lane1_ce16=0x274900 +serdes_preemphasis_lane2_ce16=0x274900 +serdes_preemphasis_lane3_ce16=0x274900 + +serdes_driver_current_lane0_ce17=0x8 +serdes_driver_current_lane1_ce17=0xF +serdes_driver_current_lane2_ce17=0xF +serdes_driver_current_lane3_ce17=0xF +serdes_preemphasis_lane0_ce17=0x254B00 +serdes_preemphasis_lane1_ce17=0x304000 +serdes_preemphasis_lane2_ce17=0x304000 +serdes_preemphasis_lane3_ce17=0x304000 + +serdes_driver_current_lane0_ce18=0x2 +serdes_driver_current_lane1_ce18=0x2 +serdes_driver_current_lane2_ce18=0x2 +serdes_driver_current_lane3_ce18=0x2 +serdes_preemphasis_lane0_ce18=0x205000 +serdes_preemphasis_lane1_ce18=0x205000 +serdes_preemphasis_lane2_ce18=0x205000 +serdes_preemphasis_lane3_ce18=0x205000 + +serdes_driver_current_lane0_ce19=0x2 +serdes_driver_current_lane1_ce19=0x2 +serdes_driver_current_lane2_ce19=0x2 +serdes_driver_current_lane3_ce19=0x2 +serdes_preemphasis_lane0_ce19=0x205000 +serdes_preemphasis_lane1_ce19=0x205000 +serdes_preemphasis_lane2_ce19=0x205000 +serdes_preemphasis_lane3_ce19=0x205000 + +serdes_driver_current_lane0_ce20=0x2 +serdes_driver_current_lane1_ce20=0x2 +serdes_driver_current_lane2_ce20=0x2 +serdes_driver_current_lane3_ce20=0x2 +serdes_preemphasis_lane0_ce20=0x205000 +serdes_preemphasis_lane1_ce20=0x205000 +serdes_preemphasis_lane2_ce20=0x205000 +serdes_preemphasis_lane3_ce20=0x205000 + +serdes_driver_current_lane0_ce21=0x4 +serdes_driver_current_lane1_ce21=0x2 +serdes_driver_current_lane2_ce21=0x2 +serdes_driver_current_lane3_ce21=0x2 +serdes_preemphasis_lane0_ce21=0x175900 +serdes_preemphasis_lane1_ce21=0x175900 +serdes_preemphasis_lane2_ce21=0x205000 +serdes_preemphasis_lane3_ce21=0x205000 + +serdes_driver_current_lane0_ce22=0x7 +serdes_driver_current_lane1_ce22=0x7 +serdes_driver_current_lane2_ce22=0x7 +serdes_driver_current_lane3_ce22=0x7 +serdes_preemphasis_lane0_ce22=0x254B00 +serdes_preemphasis_lane1_ce22=0x254B00 +serdes_preemphasis_lane2_ce22=0x254B00 +serdes_preemphasis_lane3_ce22=0x254B00 + +serdes_driver_current_lane0_ce23=0x7 +serdes_driver_current_lane1_ce23=0x7 +serdes_driver_current_lane2_ce23=0x7 +serdes_driver_current_lane3_ce23=0x7 +serdes_preemphasis_lane0_ce23=0x254B00 +serdes_preemphasis_lane1_ce23=0x254B00 +serdes_preemphasis_lane2_ce23=0x254B00 +serdes_preemphasis_lane3_ce23=0x254B00 + +serdes_driver_current_lane0_ce24=0xF +serdes_driver_current_lane1_ce24=0x8 +serdes_driver_current_lane2_ce24=0xF +serdes_driver_current_lane3_ce24=0x4 +serdes_preemphasis_lane0_ce24=0x153C1F +serdes_preemphasis_lane1_ce24=0x294700 +serdes_preemphasis_lane2_ce24=0x153C1F +serdes_preemphasis_lane3_ce24=0x294700 + +serdes_driver_current_lane0_ce25=0xF +serdes_driver_current_lane1_ce25=0x8 +serdes_driver_current_lane2_ce25=0xF +serdes_driver_current_lane3_ce25=0x4 +serdes_preemphasis_lane0_ce25=0x153C1F +serdes_preemphasis_lane1_ce25=0x294700 +serdes_preemphasis_lane2_ce25=0x153C1F +serdes_preemphasis_lane3_ce25=0x294700 + +serdes_driver_current_lane0_ce26=0xF +serdes_driver_current_lane1_ce26=0xA +serdes_driver_current_lane2_ce26=0xF +serdes_driver_current_lane3_ce26=0x9 +serdes_preemphasis_lane0_ce26=0x153C1F +serdes_preemphasis_lane1_ce26=0x304000 +serdes_preemphasis_lane2_ce26=0x153C1F +serdes_preemphasis_lane3_ce26=0x304000 + +serdes_driver_current_lane0_ce27=0xF +serdes_driver_current_lane1_ce27=0x9 +serdes_driver_current_lane2_ce27=0xF +serdes_driver_current_lane3_ce27=0x9 +serdes_preemphasis_lane0_ce27=0x153C1F +serdes_preemphasis_lane1_ce27=0x304000 +serdes_preemphasis_lane2_ce27=0x153C1F +serdes_preemphasis_lane3_ce27=0x304000 + +serdes_driver_current_lane0_ce28=0xF +serdes_driver_current_lane1_ce28=0xC +serdes_driver_current_lane2_ce28=0xF +serdes_driver_current_lane3_ce28=0xC +serdes_preemphasis_lane0_ce28=0x153C1F +serdes_preemphasis_lane1_ce28=0x183C10 +serdes_preemphasis_lane2_ce28=0x153C1F +serdes_preemphasis_lane3_ce28=0x1C3C10 + +serdes_driver_current_lane0_ce29=0xF +serdes_driver_current_lane1_ce29=0xC +serdes_driver_current_lane2_ce29=0xF +serdes_driver_current_lane3_ce29=0xC +serdes_preemphasis_lane0_ce29=0x153C1F +serdes_preemphasis_lane1_ce29=0x203C10 +serdes_preemphasis_lane2_ce29=0x153C1F +serdes_preemphasis_lane3_ce29=0x203C10 + +serdes_driver_current_lane0_ce30=0xF +serdes_driver_current_lane1_ce30=0xC +serdes_driver_current_lane2_ce30=0xF +serdes_driver_current_lane3_ce30=0xC +serdes_preemphasis_lane0_ce30=0x153C1F +serdes_preemphasis_lane1_ce30=0x243C10 +serdes_preemphasis_lane2_ce30=0x153C1F +serdes_preemphasis_lane3_ce30=0x243C08 + +serdes_driver_current_lane0_ce31=0xF +serdes_driver_current_lane1_ce31=0xC +serdes_driver_current_lane2_ce31=0xF +serdes_driver_current_lane3_ce31=0xE +serdes_preemphasis_lane0_ce31=0x153C1F +serdes_preemphasis_lane1_ce31=0x243C10 +serdes_preemphasis_lane2_ce31=0x153C1F +serdes_preemphasis_lane3_ce31=0x203C14 + +serdes_if_type_xe=14 +serdes_if_type_ce=14 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9100-r0/default_sku new file mode 100644 index 000000000000..1a78c849d5e5 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9100-C32 t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9100-r0/fancontrol new file mode 100644 index 000000000000..e1f88f6b79c5 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/fancontrol @@ -0,0 +1,10 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/0-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon1/device/temp2_input hwmon1/device/pwm1=hwmon1/device/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm2=20 hwmon1/device/pwm1=20 +MAXTEMP=hwmon1/device/pwm2=60 hwmon1/device/pwm1=60 +MINSTART=hwmon1/device/pwm2=75 hwmon1/device/pwm1=75 +MINSTOP=hwmon1/device/pwm2=22 hwmon1/device/pwm1=22 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9100-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/led_proc_init.soc b/device/ingrasys/x86_64-ingrasys_s9100-r0/led_proc_init.soc new file mode 100644 index 000000000000..492d3b897851 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/led_proc_init.soc @@ -0,0 +1,43 @@ +# LED microprocessor initialization for Ingrasys S9100-32X + +led 0 stop +led 0 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 REMAP_PORT_2=29 REMAP_PORT_1=30 REMAP_PORT_0=31 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 REMAP_PORT_6=25 REMAP_PORT_5=26 REMAP_PORT_4=27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=20 REMAP_PORT_10=21 REMAP_PORT_9=22 REMAP_PORT_8=23 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=16 REMAP_PORT_14=17 REMAP_PORT_13=18 REMAP_PORT_12=19 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12 REMAP_PORT_18=13 REMAP_PORT_17=14 REMAP_PORT_16=15 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8 REMAP_PORT_22=9 REMAP_PORT_21=10 REMAP_PORT_20=11 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4 REMAP_PORT_26=5 REMAP_PORT_25=6 REMAP_PORT_24=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 REMAP_PORT_30=1 REMAP_PORT_29=2 REMAP_PORT_28=3 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=60 REMAP_PORT_34=61 REMAP_PORT_33=62 REMAP_PORT_32=63 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56 REMAP_PORT_38=57 REMAP_PORT_37=58 REMAP_PORT_36=59 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 REMAP_PORT_42=53 REMAP_PORT_41=54 REMAP_PORT_40=55 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 REMAP_PORT_46=49 REMAP_PORT_45=50 REMAP_PORT_44=51 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=44 REMAP_PORT_50=45 REMAP_PORT_49=46 REMAP_PORT_48=47 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=40 REMAP_PORT_54=41 REMAP_PORT_53=42 REMAP_PORT_52=43 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=36 REMAP_PORT_58=37 REMAP_PORT_57=38 REMAP_PORT_56=39 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=32 REMAP_PORT_62=33 REMAP_PORT_61=34 REMAP_PORT_60=35 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0E 87 22 0F 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8 REMAP_PORT_10=9 REMAP_PORT_9=10 REMAP_PORT_8=11 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=12 REMAP_PORT_14=13 REMAP_PORT_13=14 REMAP_PORT_12=15 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 REMAP_PORT_18=17 REMAP_PORT_17=18 REMAP_PORT_16=19 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 REMAP_PORT_22=21 REMAP_PORT_21=22 REMAP_PORT_20=23 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=24 REMAP_PORT_26=25 REMAP_PORT_25=26 REMAP_PORT_24=27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=28 REMAP_PORT_30=29 REMAP_PORT_29=30 REMAP_PORT_28=31 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 REMAP_PORT_34=33 REMAP_PORT_33=34 REMAP_PORT_32=35 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 REMAP_PORT_38=37 REMAP_PORT_37=38 REMAP_PORT_36=39 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 REMAP_PORT_42=41 REMAP_PORT_41=42 REMAP_PORT_40=43 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 REMAP_PORT_46=45 REMAP_PORT_45=46 REMAP_PORT_44=47 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 REMAP_PORT_50=49 REMAP_PORT_49=50 REMAP_PORT_48=51 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 REMAP_PORT_54=53 REMAP_PORT_53=54 REMAP_PORT_52=55 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56 REMAP_PORT_58=57 REMAP_PORT_57=58 REMAP_PORT_56=59 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60 REMAP_PORT_62=61 REMAP_PORT_61=62 REMAP_PORT_60=63 +led 1 auto on +led 1 start diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/eeprom.py new file mode 100644 index 000000000000..1c23602fcb5a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Ingrasys S9100 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-9/9-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/psuutil.py new file mode 100644 index 000000000000..ef45a0c91727 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/psuutil.py @@ -0,0 +1,91 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_CPLD_DIR = "/sys/bus/i2c/devices/0-0033" + + 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 ", attr_path, " file !") + + 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 + mask = [0x08, 0x10] + attr_file = 'cpld_pw_good' + attr_path = self.PSU_CPLD_DIR + '/' + 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 & mask[index-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 + mask = [0x01, 0x02] + attr_file = 'cpld_pw_abs' + attr_path = self.PSU_CPLD_DIR + '/' + 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 & mask[index-1]): + status = 1 + + return status diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/sfputil.py new file mode 100644 index 000000000000..f2da8544202c --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/plugins/sfputil.py @@ -0,0 +1,324 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +import os + +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 = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + GPIO_OFFSET = 0 + + BASE_DIR_PATH = "/sys/class/gpio/gpio{0}/direction" + BASE_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 11, + 1: 10, + 2: 13, + 3: 12, + 4: 15, + 5: 14, + 6: 17, + 7: 16, + 8: 19, + 9: 18, + 10: 21, + 11: 20, + 12: 23, + 13: 22, + 14: 25, + 15: 24, + 16: 27, + 17: 26, + 18: 29, + 19: 28, + 20: 31, + 21: 30, + 22: 33, + 23: 32, + 24: 35, + 25: 34, + 26: 37, + 27: 36, + 28: 39, + 29: 38, + 30: 41, + 31: 40 + } + + abs_to_gpio_mapping = {} + lpmode_to_gpio_mapping = {} + reset_to_gpio_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 list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:], 10) + except ValueError as e: + print("Error: %s" % str(e)) + if gpiochip_no > 255: + self.GPIO_OFFSET = 256 + return True + return True + + def init_abs_to_gpio_mapping(self): + self.abs_to_gpio_mapping = { + 0: 241+self.GPIO_OFFSET, + 1: 240+self.GPIO_OFFSET, + 2: 243+self.GPIO_OFFSET, + 3: 242+self.GPIO_OFFSET, + 4: 245+self.GPIO_OFFSET, + 5: 244+self.GPIO_OFFSET, + 6: 247+self.GPIO_OFFSET, + 7: 246+self.GPIO_OFFSET, + 8: 249+self.GPIO_OFFSET, + 9: 248+self.GPIO_OFFSET, + 10: 251+self.GPIO_OFFSET, + 11: 250+self.GPIO_OFFSET, + 12: 253+self.GPIO_OFFSET, + 13: 252+self.GPIO_OFFSET, + 14: 255+self.GPIO_OFFSET, + 15: 254+self.GPIO_OFFSET, + 16: 225+self.GPIO_OFFSET, + 17: 224+self.GPIO_OFFSET, + 18: 227+self.GPIO_OFFSET, + 19: 226+self.GPIO_OFFSET, + 20: 229+self.GPIO_OFFSET, + 21: 228+self.GPIO_OFFSET, + 22: 231+self.GPIO_OFFSET, + 23: 230+self.GPIO_OFFSET, + 24: 233+self.GPIO_OFFSET, + 25: 232+self.GPIO_OFFSET, + 26: 235+self.GPIO_OFFSET, + 27: 234+self.GPIO_OFFSET, + 28: 237+self.GPIO_OFFSET, + 29: 236+self.GPIO_OFFSET, + 30: 239+self.GPIO_OFFSET, + 31: 238+self.GPIO_OFFSET + } + return True + + def init_lpmode_to_gpio_mapping(self): + self.lpmode_to_gpio_mapping = { + 0: 177+self.GPIO_OFFSET, + 1: 176+self.GPIO_OFFSET, + 2: 179+self.GPIO_OFFSET, + 3: 178+self.GPIO_OFFSET, + 4: 181+self.GPIO_OFFSET, + 5: 180+self.GPIO_OFFSET, + 6: 183+self.GPIO_OFFSET, + 7: 182+self.GPIO_OFFSET, + 8: 185+self.GPIO_OFFSET, + 9: 184+self.GPIO_OFFSET, + 10: 187+self.GPIO_OFFSET, + 11: 186+self.GPIO_OFFSET, + 12: 189+self.GPIO_OFFSET, + 13: 188+self.GPIO_OFFSET, + 14: 191+self.GPIO_OFFSET, + 15: 190+self.GPIO_OFFSET, + 16: 161+self.GPIO_OFFSET, + 17: 160+self.GPIO_OFFSET, + 18: 163+self.GPIO_OFFSET, + 19: 162+self.GPIO_OFFSET, + 20: 165+self.GPIO_OFFSET, + 21: 164+self.GPIO_OFFSET, + 22: 167+self.GPIO_OFFSET, + 23: 166+self.GPIO_OFFSET, + 24: 169+self.GPIO_OFFSET, + 25: 168+self.GPIO_OFFSET, + 26: 171+self.GPIO_OFFSET, + 27: 170+self.GPIO_OFFSET, + 28: 173+self.GPIO_OFFSET, + 29: 172+self.GPIO_OFFSET, + 30: 175+self.GPIO_OFFSET, + 31: 174+self.GPIO_OFFSET + } + return True + + def init_reset_to_gpio_mapping(self): + self.reset_to_gpio_mapping = { + 0: 145+self.GPIO_OFFSET, + 1: 144+self.GPIO_OFFSET, + 2: 147+self.GPIO_OFFSET, + 3: 146+self.GPIO_OFFSET, + 4: 149+self.GPIO_OFFSET, + 5: 148+self.GPIO_OFFSET, + 6: 151+self.GPIO_OFFSET, + 7: 150+self.GPIO_OFFSET, + 8: 153+self.GPIO_OFFSET, + 9: 152+self.GPIO_OFFSET, + 10: 155+self.GPIO_OFFSET, + 11: 154+self.GPIO_OFFSET, + 12: 157+self.GPIO_OFFSET, + 13: 156+self.GPIO_OFFSET, + 14: 159+self.GPIO_OFFSET, + 15: 158+self.GPIO_OFFSET, + 16: 129+self.GPIO_OFFSET, + 17: 128+self.GPIO_OFFSET, + 18: 131+self.GPIO_OFFSET, + 19: 130+self.GPIO_OFFSET, + 20: 133+self.GPIO_OFFSET, + 21: 132+self.GPIO_OFFSET, + 22: 135+self.GPIO_OFFSET, + 23: 134+self.GPIO_OFFSET, + 24: 137+self.GPIO_OFFSET, + 25: 136+self.GPIO_OFFSET, + 26: 139+self.GPIO_OFFSET, + 27: 138+self.GPIO_OFFSET, + 28: 141+self.GPIO_OFFSET, + 29: 140+self.GPIO_OFFSET, + 30: 143+self.GPIO_OFFSET, + 31: 142+self.GPIO_OFFSET + } + return True + + def __init__(self): + # Init abs, lpmode, and reset to gpio mapping + self.set_gpio_offset() + self.init_abs_to_gpio_mapping() + self.init_lpmode_to_gpio_mapping() + self.init_reset_to_gpio_mapping() + + # Override port_to_eeprom_mapping for class initialization + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/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) + + 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 + + try: + abs_device_file = self.BASE_VAL_PATH.format( + self.abs_to_gpio_mapping[port_num]) + val_file = open(abs_device_file) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("1" if lpmode is True else "0") + val_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("1") + val_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("0") + val_file.close() + + return True + + 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 diff --git a/device/ingrasys/x86_64-ingrasys_s9100-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9100-r0/sensors.conf new file mode 100644 index 000000000000..5535db7e7eb4 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9100-r0/sensors.conf @@ -0,0 +1,49 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +chip "w83795adg-*" + label in0 "1.0V" + set in0_min 1.00 * 0.97 + set in0_max 1.00 * 1.03 + label in1 "1.0V_ROV" + set in1_min 1.00 * 0.98 + set in1_max 1.00 * 1.02 + label in2 "1.25V" + set in2_min 1.25 * 0.97 + set in2_max 1.25 * 1.03 + label in3 "1.8V" + set in3_min 1.80 * 0.97 + set in3_max 1.80 * 1.03 + ignore in4 + ignore in5 + ignore in6 + ignore in7 + label in12 "+3.3V" + set in12_min 3.30 * 0.97 + set in12_max 3.30 * 1.03 + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + label temp1 "Front MAC Temp" + set temp1_max 70 + set temp1_crit 80 + label temp2 "Rear MAC Temp" + set temp2_max 70 + set temp2_crit 80 + ignore temp3 + ignore temp4 + ignore intrusion0 diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers.json.j2 b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers.json.j2 new file mode 100644 index 000000000000..9354b7ec5b59 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t0.j2 b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..b008aa892bc1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t0.j2 @@ -0,0 +1,69 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- 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": "{{ 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]", + "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" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t1.j2 b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..b008aa892bc1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/buffers_defaults_t1.j2 @@ -0,0 +1,69 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- 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": "{{ 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]", + "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" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/pg_profile_lookup.ini b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/pg_profile_lookup.ini new file mode 100644 index 000000000000..d98b0eca6d19 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/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/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.ini new file mode 100644 index 000000000000..bb26684cb7da --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 0,1,2,3 Ethernet1/1 0 +Ethernet4 4,5,6,7 Ethernet2/1 1 +Ethernet8 8,9,10,11 Ethernet3/1 2 +Ethernet12 12,13,14,15 Ethernet4/1 3 +Ethernet16 16,17,18,19 Ethernet5/1 4 +Ethernet20 20,21,22,23 Ethernet6/1 5 +Ethernet24 24,25,26,27 Ethernet7/1 6 +Ethernet28 28,29,30,31 Ethernet8/1 7 +Ethernet32 32,33,34,35 Ethernet9/1 8 +Ethernet36 36,37,38,39 Ethernet10/1 9 +Ethernet40 40,41,42,43 Ethernet11/1 10 +Ethernet44 44,45,46,47 Ethernet12/1 11 +Ethernet48 48,49,50,51 Ethernet13/1 12 +Ethernet52 52,53,54,55 Ethernet14/1 13 +Ethernet56 56,57,58,59 Ethernet15/1 14 +Ethernet60 60,61,62,63 Ethernet16/1 15 +Ethernet64 64,65,66,67 Ethernet17/1 16 +Ethernet68 68,69,70,71 Ethernet18/1 17 +Ethernet72 72,73,74,75 Ethernet19/1 18 +Ethernet76 76,77,78,79 Ethernet20/1 19 +Ethernet80 80,81,82,83 Ethernet21/1 20 +Ethernet84 84,85,86,87 Ethernet22/1 21 +Ethernet88 88,89,90,91 Ethernet23/1 22 +Ethernet92 92,93,94,95 Ethernet24/1 23 +Ethernet96 96,97,98,99 Ethernet25/1 24 +Ethernet100 100,101,102,103 Ethernet26/1 25 +Ethernet104 104,105,106,107 Ethernet27/1 26 +Ethernet108 108,109,110,111 Ethernet28/1 27 +Ethernet112 112,113,114,115 Ethernet29/1 28 +Ethernet116 116,117,118,119 Ethernet30/1 29 +Ethernet120 120,121,122,123 Ethernet31/1 30 +Ethernet124 124,125,126,127 Ethernet32/1 31 diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.nps b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.nps new file mode 100644 index 000000000000..6d49c6720882 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/port_config.nps @@ -0,0 +1,353 @@ +init start stage unit=0 low-level +init set port-map unit=0 port=0 eth-macro=0 lane=0 max-speed=100g active=true +init set port-map unit=0 port=1 eth-macro=1 lane=0 max-speed=100g active=true +init set port-map unit=0 port=2 eth-macro=2 lane=0 max-speed=100g active=true +init set port-map unit=0 port=3 eth-macro=3 lane=0 max-speed=100g active=true +init set port-map unit=0 port=4 eth-macro=4 lane=0 max-speed=100g active=true +init set port-map unit=0 port=5 eth-macro=5 lane=0 max-speed=100g active=true +init set port-map unit=0 port=6 eth-macro=6 lane=0 max-speed=100g active=true +init set port-map unit=0 port=7 eth-macro=7 lane=0 max-speed=100g active=true +init set port-map unit=0 port=8 eth-macro=8 lane=0 max-speed=100g active=true +init set port-map unit=0 port=9 eth-macro=9 lane=0 max-speed=100g active=true +init set port-map unit=0 port=10 eth-macro=10 lane=0 max-speed=100g active=true +init set port-map unit=0 port=11 eth-macro=11 lane=0 max-speed=100g active=true +init set port-map unit=0 port=12 eth-macro=12 lane=0 max-speed=100g active=true +init set port-map unit=0 port=13 eth-macro=13 lane=0 max-speed=100g active=true +init set port-map unit=0 port=14 eth-macro=14 lane=0 max-speed=100g active=true +init set port-map unit=0 port=15 eth-macro=15 lane=0 max-speed=100g active=true +init set port-map unit=0 port=16 eth-macro=16 lane=0 max-speed=100g active=true +init set port-map unit=0 port=17 eth-macro=17 lane=0 max-speed=100g active=true +init set port-map unit=0 port=18 eth-macro=18 lane=0 max-speed=100g active=true +init set port-map unit=0 port=19 eth-macro=19 lane=0 max-speed=100g active=true +init set port-map unit=0 port=20 eth-macro=20 lane=0 max-speed=100g active=true +init set port-map unit=0 port=21 eth-macro=21 lane=0 max-speed=100g active=true +init set port-map unit=0 port=22 eth-macro=22 lane=0 max-speed=100g active=true +init set port-map unit=0 port=23 eth-macro=23 lane=0 max-speed=100g active=true +init set port-map unit=0 port=24 eth-macro=24 lane=0 max-speed=100g active=true +init set port-map unit=0 port=25 eth-macro=25 lane=0 max-speed=100g active=true +init set port-map unit=0 port=26 eth-macro=26 lane=0 max-speed=100g active=true +init set port-map unit=0 port=27 eth-macro=27 lane=0 max-speed=100g active=true +init set port-map unit=0 port=28 eth-macro=28 lane=0 max-speed=100g active=true +init set port-map unit=0 port=29 eth-macro=29 lane=0 max-speed=100g active=true +init set port-map unit=0 port=30 eth-macro=30 lane=0 max-speed=100g active=true +init set port-map unit=0 port=31 eth-macro=31 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 +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap unit=0 portlist=0 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=1 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=2 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=3 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=4 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=5 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=6 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=7 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=8 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=9 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=10 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=11 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=12 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=13 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=14 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=15 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=16 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=17 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=18 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=19 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=20 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=21 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=22 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=23 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=24 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=25 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=26 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=27 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=28 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=29 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=30 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=31 lane-cnt=4 property=tx data=0x03.02.01.00 +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=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=1 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=2 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=3 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=4 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=5 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=6 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=7 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=8 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=9 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=10 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=11 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=12 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=13 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=14 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=15 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=16 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=17 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=18 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=19 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=20 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=21 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=22 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=23 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=24 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=25 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=26 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=27 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=28 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=29 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=30 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=31 lane-cnt=4 property=rx data=0x03.02.01.00 +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=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=1 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=6 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=31 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=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=1 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=2 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=3 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=4 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=5 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=6 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=7 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=8 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=9 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=10 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=11 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=12 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=13 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=14 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=15 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=16 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=17 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=18 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=19 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=20 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=21 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=22 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=23 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=24 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=25 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=26 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=27 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=28 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=29 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=30 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev unit=0 portlist=31 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=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=cn1 data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=c0 data=0x1A.1A.1A.1A +phy set pre-emphasis unit=0 portlist=0 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=4 property=c0 data=0x1A.1A.1A.1A +phy set pre-emphasis unit=0 portlist=1 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=4 property=cn1 data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=2 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=3 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=4 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=5 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=4 property=c2 data=0x03.03.03.03 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=6 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=7 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=8 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=9 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=10 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=4 property=cn1 data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=11 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=12 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=13 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=4 property=c0 data=0x1D.1D.1D.1D +phy set pre-emphasis unit=0 portlist=14 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=15 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=16 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=17 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=18 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=19 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=20 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=21 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=22 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=23 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=24 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=25 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=26 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=27 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=28 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=4 property=c0 data=0x1A.1A.1A.1A +phy set pre-emphasis unit=0 portlist=29 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=4 property=cn1 data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=4 property=c0 data=0x1A.1A.1A.1A +phy set pre-emphasis unit=0 portlist=30 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=4 property=c2 data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=4 property=cn1 data=0x03.03.03.03 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c2 data=0x01 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=cn1 data=0x01 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c0 data=0x02 +phy set pre-emphasis unit=0 portlist=129 lane-cnt=1 property=c1 data=0x03 +phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c2 data=0x01 +phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=cn1 data=0x01 +phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c0 data=0x02 +phy set pre-emphasis unit=0 portlist=130 lane-cnt=1 property=c1 data=0x03 +phy set mdio portlist=0 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=1 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=2 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=3 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=4 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=5 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=6 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=7 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=8 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=9 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=10 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=11 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=12 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=13 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=14 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=15 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=16 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=17 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=18 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=19 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=20 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=21 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=22 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=23 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=24 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=25 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=26 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=27 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=28 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=29 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=30 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=31 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=129 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=130 devad=0x1E addr=0x2 data=0x0000 +port set property unit=0 portlist=0-31 speed=100g +port set property unit=0 portlist=129-130 speed=10g +port set property unit=0 portlist=0-31 medium-type=sr4 +port set property unit=0 portlist=129-130 medium-type=kr +port set property unit=0 portlist=0-31 fec=disable +port set adver unit=0 portlist=129-130 speed-10g-kr +port set property unit=0 portlist=129-130 an=enable +port set property unit=0 portlist=129-130 admin=enable +port set property unit=0 portlist=0-31 admin=disable diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/qos.json.j2 b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/qos.json.j2 new file mode 100644 index 000000000000..42eef17c362b --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/qos.json.j2 @@ -0,0 +1,136 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"1", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + }, + "WRED_PROFILE": { + "AZURE_LOSSY" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184128", + "green_min_threshold": "184128" + }, + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184128", + "green_min_threshold": "184128" + } + }, + "QUEUE": { + } +} diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/sai.profile b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/sai.profile new file mode 100644 index 000000000000..880f47910ac1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/INGRASYS-S9130-32X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/led_proc_init.nps +SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/default_sku new file mode 100644 index 000000000000..2464f73308e3 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9130-32X t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/fancontrol new file mode 100644 index 000000000000..5ed165966b93 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/fancontrol @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon5=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-8/8-002f +DEVNAME=hwmon5=w83795adg +FCTEMPS=hwmon5/device/pwm2=hwmon1/temp1_input hwmon5/device/pwm1=hwmon1/temp1_input +FCFANS=hwmon5/device/pwm2=hwmon5/device/fan8_input hwmon5/device/pwm2=hwmon5/device/fan7_input hwmon5/device/pwm2=hwmon5/device/fan6_input hwmon5/device/pwm2=hwmon5/device/fan5_input hwmon5/device/pwm1=hwmon5/device/fan4_input hwmon5/device/pwm1=hwmon5/device/fan3_input hwmon5/device/pwm1=hwmon5/device/fan2_input hwmon5/device/pwm1=hwmon5/device/fan1_input +# TODO: check the temp value with HW after board ready +MINTEMP=hwmon5/device/pwm2=20 hwmon5/device/pwm1=20 +MAXTEMP=hwmon5/device/pwm2=60 hwmon5/device/pwm1=60 +MINSTART=hwmon5/device/pwm2=75 hwmon5/device/pwm1=75 +MINSTOP=hwmon5/device/pwm2=22 hwmon5/device/pwm1=22 + diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/led_proc_init.nps b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/led_proc_init.nps new file mode 100644 index 000000000000..d1695e36b59a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/led_proc_init.nps @@ -0,0 +1,9 @@ +#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 1 +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 +0 NPS_CFG_TYPE_HASH_L2_FDB_REGION_ENTRY_NUM 0 0 49152 +0 NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM 0 0 32768 diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..7496ebe21ada --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Ingrasys S9130-32X +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0051/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..37e2173aa9d2 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/psuutil.py @@ -0,0 +1,91 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-10/10-0050", + "/sys/bus/i2c/devices/i2c-9/9-0050"] + + 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 ", attr_path, " file !") + + 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_pg' + 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_abs' + 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 == 0): + status = 1 + + return status diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..260c759c7993 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/plugins/sfputil.py @@ -0,0 +1,220 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +import os + +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 = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + EEPROM_OFFSET = 21 + ABS_GPIO_BASE_0_15 = 240 + ABS_GPIO_BASE_16_31 = 224 + LP_MODE_GPIO_BASE_0_15 = 176 + LP_MODE_GPIO_BASE_16_31 = 160 + RST_GPIO_BASE_0_15 = 144 + RST_GPIO_BASE_16_31 = 128 + GPIO_OFFSET = 0 + + GPIO_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _port_to_eeprom_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 list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:], 10) + except ValueError as e: + print("Error: %s" % str(e)) + if gpiochip_no > 255: + self.GPIO_OFFSET = 256 + return True + return True + + def update_gpio_base(self): + self.ABS_GPIO_BASE_0_15 = 240 + self.GPIO_OFFSET + self.ABS_GPIO_BASE_16_31 = 224 + self.GPIO_OFFSET + self.LP_MODE_GPIO_BASE_0_15 = 176 + self.GPIO_OFFSET + self.LP_MODE_GPIO_BASE_16_31 = 160 + self.GPIO_OFFSET + self.RST_GPIO_BASE_0_15 = 144 + self.GPIO_OFFSET + self.RST_GPIO_BASE_16_31 = 128 + self.GPIO_OFFSET + return True + + def __init__(self): + # Update abs, lpmode, and reset gpio base + self.set_gpio_offset() + self.update_gpio_base() + + # Override port_to_eeprom_mapping for class initialization + eeprom_path = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end + 1): + port_eeprom_path = eeprom_path.format(x + self.EEPROM_OFFSET) + self.port_to_eeprom_mapping[x] = port_eeprom_path + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # open corrsponding gpio file + try: + if port_num <= 15: + gpio_base = self.ABS_GPIO_BASE_0_15 + else: + gpio_base = self.ABS_GPIO_BASE_16_31 + gpio_index = gpio_base + (port_num % 16) + gpio_file_path = self.GPIO_VAL_PATH.format(gpio_index) + gpio_file = open(gpio_file_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the gpio value + gpio_val = int(gpio_file.readline().rstrip()) + gpio_file.close() + + # the gpio pin is ACTIVE_LOW but reversed + if gpio_val == 0: + return False + + return True + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # open corrsponding gpio file + try: + if port_num <= 15: + gpio_base = self.LP_MODE_GPIO_BASE_0_15 + else: + gpio_base = self.LP_MODE_GPIO_BASE_16_31 + gpio_index = gpio_base + (port_num % 16) + gpio_file_path = self.GPIO_VAL_PATH.format(gpio_index) + gpio_file = open(gpio_file_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the gpio value + gpio_val = int(gpio_file.readline().rstrip()) + gpio_file.close() + + if gpio_val == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # open corrsponding gpio file + try: + if port_num <= 15: + gpio_base = self.LP_MODE_GPIO_BASE_0_15 + else: + gpio_base = self.LP_MODE_GPIO_BASE_16_31 + gpio_index = gpio_base + (port_num % 16) + gpio_file_path = self.GPIO_VAL_PATH.format(gpio_index) + gpio_file = open(gpio_file_path, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # the gpio pin is ACTIVE_HIGH + if lpmode is True: + gpio_val = "1" + else: + gpio_val = "0" + + # write value to gpio + gpio_file.seek(0) + gpio_file.write(gpio_val) + gpio_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # open corrsponding gpio file + try: + if port_num <= 15: + gpio_base = self.RST_GPIO_BASE_0_15 + else: + gpio_base = self.RST_GPIO_BASE_16_31 + gpio_index = gpio_base + (port_num % 16) + gpio_file_path = self.GPIO_VAL_PATH.format(gpio_index) + gpio_file = open(gpio_file_path, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # set the gpio to take port into reset + # the gpio pin is ACTIVE_LOW but reversed + gpio_val = "1" + # write value to gpio + gpio_file.seek(0) + gpio_file.write(gpio_val) + gpio_file.close() + + # Sleep 1 second to let it settle + time.sleep(1) + + # open corrsponding gpio file + try: + gpio_file = open(gpio_file_path, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # set gpio back low to take port out of reset + # the gpio pin is ACTIVE_LOW but reversed + gpio_val = "0" + # write value to gpio + gpio_file.seek(0) + gpio_file.write(gpio_val) + gpio_file.close() + + return True + + def get_transceiver_change_event(self, timeout=0): + raise NotImplementedError diff --git a/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/sensors.conf new file mode 100644 index 000000000000..9b55f73af2af --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9130_32x-r0/sensors.conf @@ -0,0 +1,69 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + +bus "i2c-8" "i2c-mux-0 (chan_id 7)" +chip "w83795adg-*" + label in0 "0.9V" + set in0_max 0.945 + set in0_min 0.855 + label in1 "VDD_CORE" + set in1_max 0.945 + set in1_min 0.855 + label in2 "1.2V" + set in2_max 1.26 + set in2_min 1.14 + label in3 "1.8V" + set in3_max 1.89 + set in3_min 1.71 + label in4 "1.01V" + set in4_max 1.0605 + set in4_min 0.9595 + ignore in5 + ignore in6 + ignore in7 + ignore in11 + label in12 "3.3VDD" + set in12_max 3.465 + set in12_min 3.135 + # in12 and in13 are the same source + ignore in13 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 + +chip "tmp75-i2c-*-4A" + label temp1 "BMC board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-0" "i2c-main" +chip "tmp75-i2c-*-4F" + label temp1 "x86 CPU board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-12" "i2c-mux-1 (chan_id 3)" +chip "tmp75-i2c-*-4C" + label temp1 "rear MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +chip "tmp75-i2c-*-49" + label temp1 "front MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/port_config.ini new file mode 100644 index 000000000000..8b25c1333a67 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias speed autoneg fec index +Ethernet0 0,1,2,3 Ethernet0 100000 0 none 0 +Ethernet4 4,5,6,7 Ethernet4 100000 0 none 1 +Ethernet8 8,9,10,11 Ethernet8 100000 0 none 2 +Ethernet12 12,13,14,15 Ethernet12 100000 0 none 3 +Ethernet16 16,17,18,19 Ethernet16 100000 0 none 4 +Ethernet20 20,21,22,23 Ethernet20 100000 0 none 5 +Ethernet24 24,25,26,27 Ethernet24 100000 0 none 6 +Ethernet28 28,29,30,31 Ethernet28 100000 0 none 7 +Ethernet32 32,33,34,35 Ethernet32 100000 0 none 8 +Ethernet36 36,37,38,39 Ethernet36 100000 0 none 9 +Ethernet40 40,41,42,43 Ethernet40 100000 0 none 10 +Ethernet44 44,45,46,47 Ethernet44 100000 0 none 11 +Ethernet48 48,49,50,51 Ethernet48 100000 0 none 12 +Ethernet52 52,53,54,55 Ethernet52 100000 0 none 13 +Ethernet56 56,57,58,59 Ethernet56 100000 0 none 14 +Ethernet60 60,61,62,63 Ethernet60 100000 0 none 15 +Ethernet64 64,65,66,67 Ethernet64 100000 0 none 16 +Ethernet68 68,69,70,71 Ethernet68 100000 0 none 17 +Ethernet72 72,73,74,75 Ethernet72 100000 0 none 18 +Ethernet76 76,77,78,79 Ethernet76 100000 0 none 19 +Ethernet80 80,81,82,83 Ethernet80 100000 0 none 20 +Ethernet84 84,85,86,87 Ethernet84 100000 0 none 21 +Ethernet88 88,89,90,91 Ethernet88 100000 0 none 22 +Ethernet92 92,93,94,95 Ethernet92 100000 0 none 23 +Ethernet96 96,97,98,99 Ethernet96 100000 0 none 24 +Ethernet100 100,101,102,103 Ethernet100 100000 0 none 25 +Ethernet104 104,105,106,107 Ethernet104 100000 0 none 26 +Ethernet108 108,109,110,111 Ethernet108 100000 0 none 27 +Ethernet112 112,113,114,115 Ethernet112 100000 0 none 28 +Ethernet116 116,117,118,119 Ethernet116 100000 0 none 29 +Ethernet120 120,121,122,123 Ethernet120 100000 0 none 30 +Ethernet124 124,125,126,127 Ethernet124 100000 0 none 31 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-sai.conf b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-sai.conf new file mode 100644 index 000000000000..bf15b40d0c58 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/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: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" + } + ], + "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", + "agent0": "lib/platform/x86_64-ingrasys_s9180_32x-r0/libpltfm_mgr.so", + "switchapi_port_add": false + } + ] +} diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-tna-sai.conf b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-tna-sai.conf new file mode 100644 index 000000000000..9fbf9d3cdb69 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-tna-sai.conf @@ -0,0 +1,40 @@ +{ + "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, + "agent0": "lib/platform/x86_64-ingrasys_s9180_32x-r0/libpltfm_mgr.so", + "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/ingrasys/x86_64-ingrasys_s9180_32x-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/default_sku new file mode 100644 index 000000000000..984f54a96e23 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9180-32X t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/fancontrol new file mode 100644 index 000000000000..dc303afac034 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/fancontrol @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-56/56-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon2/temp2_input hwmon1/device/pwm1=hwmon2/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +# TODO: check the temp value with HW after board ready +MINTEMP=hwmon1/device/pwm2=20 hwmon1/device/pwm1=20 +MAXTEMP=hwmon1/device/pwm2=60 hwmon1/device/pwm1=60 +MINSTART=hwmon1/device/pwm2=75 hwmon1/device/pwm1=75 +MINSTOP=hwmon1/device/pwm2=22 hwmon1/device/pwm1=22 + diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..f3fb959c2d01 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Ingrasys S9180-32X +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0055/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..3ac4fa48afd0 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/psuutil.py @@ -0,0 +1,106 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + GPIO_OFFSET = 0 + SYS_GPIO_DIR = "/sys/class/gpio/" + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:], 10) + except ValueError as e: + print("Error: %s" % str(e)) + if gpiochip_no > 255: + self.GPIO_OFFSET = 256 + return True + return True + + def __init__(self): + self.set_gpio_offset() + 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 ", attr_path, " file !") + + 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 + gpio_path = ['gpio'+str(99+self.GPIO_OFFSET)+'/value', 'gpio'+str(96+self.GPIO_OFFSET)+'/value'] + attr_path = self.SYS_GPIO_DIR + gpio_path[index-1] + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 10) + # 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 + gpio_path = ['gpio'+str(100+self.GPIO_OFFSET)+'/value', 'gpio'+str(97+self.GPIO_OFFSET)+'/value'] + attr_path = self.SYS_GPIO_DIR + gpio_path[index-1] + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 10) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..c061fcabd23a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/sfputil.py @@ -0,0 +1,333 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +import os + +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 = 0 + PORT_END = 33 + SFP_PORT_START = 32 + PORTS_IN_BLOCK = 34 + GPIO_OFFSET = 0 + + BASE_DIR_PATH = "/sys/class/gpio/gpio{0}/direction" + BASE_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 10, + 1: 9, + 2: 12, + 3: 11, + 4: 14, + 5: 13, + 6: 16, + 7: 15, + 8: 18, + 9: 17, + 10: 20, + 11: 19, + 12: 22, + 13: 21, + 14: 24, + 15: 23, + 16: 26, + 17: 25, + 18: 28, + 19: 27, + 20: 30, + 21: 29, + 22: 32, + 23: 31, + 24: 34, + 25: 33, + 26: 36, + 27: 35, + 28: 38, + 29: 37, + 30: 40, + 31: 39, + 32: 45, + 33: 46 + } + + abs_to_gpio_mapping = {} + lpmode_to_gpio_mapping = {} + reset_to_gpio_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 list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def sfp_port_start(self): + return self.SFP_PORT_START + + def set_gpio_offset(self): + sys_gpio_dir = "/sys/class/gpio" + self.GPIO_OFFSET = 0 + gpiochip_no = 0 + for d in os.listdir(sys_gpio_dir): + if "gpiochip" in d: + try: + gpiochip_no = int(d[8:], 10) + except ValueError as e: + print("Error: %s" % str(e)) + if gpiochip_no > 255: + self.GPIO_OFFSET = 256 + return True + return True + + def init_abs_to_gpio_mapping(self): + self.abs_to_gpio_mapping = { + 0: 241+self.GPIO_OFFSET, + 1: 240+self.GPIO_OFFSET, + 2: 243+self.GPIO_OFFSET, + 3: 242+self.GPIO_OFFSET, + 4: 245+self.GPIO_OFFSET, + 5: 244+self.GPIO_OFFSET, + 6: 247+self.GPIO_OFFSET, + 7: 246+self.GPIO_OFFSET, + 8: 249+self.GPIO_OFFSET, + 9: 248+self.GPIO_OFFSET, + 10: 251+self.GPIO_OFFSET, + 11: 250+self.GPIO_OFFSET, + 12: 253+self.GPIO_OFFSET, + 13: 252+self.GPIO_OFFSET, + 14: 255+self.GPIO_OFFSET, + 15: 254+self.GPIO_OFFSET, + 16: 225+self.GPIO_OFFSET, + 17: 224+self.GPIO_OFFSET, + 18: 227+self.GPIO_OFFSET, + 19: 226+self.GPIO_OFFSET, + 20: 229+self.GPIO_OFFSET, + 21: 228+self.GPIO_OFFSET, + 22: 231+self.GPIO_OFFSET, + 23: 230+self.GPIO_OFFSET, + 24: 233+self.GPIO_OFFSET, + 25: 232+self.GPIO_OFFSET, + 26: 235+self.GPIO_OFFSET, + 27: 234+self.GPIO_OFFSET, + 28: 237+self.GPIO_OFFSET, + 29: 236+self.GPIO_OFFSET, + 30: 239+self.GPIO_OFFSET, + 31: 238+self.GPIO_OFFSET, + 32: 177+self.GPIO_OFFSET, + 33: 176+self.GPIO_OFFSET + } + return True + + def init_lpmode_to_gpio_mapping(self): + self.lpmode_to_gpio_mapping = { + 0: 161+self.GPIO_OFFSET, + 1: 160+self.GPIO_OFFSET, + 2: 163+self.GPIO_OFFSET, + 3: 162+self.GPIO_OFFSET, + 4: 165+self.GPIO_OFFSET, + 5: 164+self.GPIO_OFFSET, + 6: 167+self.GPIO_OFFSET, + 7: 166+self.GPIO_OFFSET, + 8: 169+self.GPIO_OFFSET, + 9: 168+self.GPIO_OFFSET, + 10: 171+self.GPIO_OFFSET, + 11: 170+self.GPIO_OFFSET, + 12: 173+self.GPIO_OFFSET, + 13: 172+self.GPIO_OFFSET, + 14: 175+self.GPIO_OFFSET, + 15: 174+self.GPIO_OFFSET, + 16: 145+self.GPIO_OFFSET, + 17: 144+self.GPIO_OFFSET, + 18: 147+self.GPIO_OFFSET, + 19: 146+self.GPIO_OFFSET, + 20: 149+self.GPIO_OFFSET, + 21: 148+self.GPIO_OFFSET, + 22: 151+self.GPIO_OFFSET, + 23: 150+self.GPIO_OFFSET, + 24: 153+self.GPIO_OFFSET, + 25: 152+self.GPIO_OFFSET, + 26: 155+self.GPIO_OFFSET, + 27: 154+self.GPIO_OFFSET, + 28: 157+self.GPIO_OFFSET, + 29: 156+self.GPIO_OFFSET, + 30: 159+self.GPIO_OFFSET, + 31: 158+self.GPIO_OFFSET + } + return True + + def init_reset_to_gpio_mapping(self): + self.reset_to_gpio_mapping = { + 0: 129+self.GPIO_OFFSET, + 1: 128+self.GPIO_OFFSET, + 2: 131+self.GPIO_OFFSET, + 3: 130+self.GPIO_OFFSET, + 4: 133+self.GPIO_OFFSET, + 5: 132+self.GPIO_OFFSET, + 6: 135+self.GPIO_OFFSET, + 7: 134+self.GPIO_OFFSET, + 8: 137+self.GPIO_OFFSET, + 9: 136+self.GPIO_OFFSET, + 10: 139+self.GPIO_OFFSET, + 11: 138+self.GPIO_OFFSET, + 12: 141+self.GPIO_OFFSET, + 13: 140+self.GPIO_OFFSET, + 14: 143+self.GPIO_OFFSET, + 15: 142+self.GPIO_OFFSET, + 16: 113+self.GPIO_OFFSET, + 17: 112+self.GPIO_OFFSET, + 18: 115+self.GPIO_OFFSET, + 19: 114+self.GPIO_OFFSET, + 20: 117+self.GPIO_OFFSET, + 21: 116+self.GPIO_OFFSET, + 22: 119+self.GPIO_OFFSET, + 23: 118+self.GPIO_OFFSET, + 24: 121+self.GPIO_OFFSET, + 25: 120+self.GPIO_OFFSET, + 26: 123+self.GPIO_OFFSET, + 27: 122+self.GPIO_OFFSET, + 28: 125+self.GPIO_OFFSET, + 29: 124+self.GPIO_OFFSET, + 30: 127+self.GPIO_OFFSET, + 31: 126+self.GPIO_OFFSET + } + return True + + def __init__(self): + # Init abs, lpmode, and reset to gpio mapping + self.set_gpio_offset() + self.init_abs_to_gpio_mapping() + self.init_lpmode_to_gpio_mapping() + self.init_reset_to_gpio_mapping() + + # Override port_to_eeprom_mapping for class initialization + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/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) + + 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 + + try: + abs_device_file = self.BASE_VAL_PATH.format( + self.abs_to_gpio_mapping[port_num]) + val_file = open(abs_device_file) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.sfp_port_start: # TBD + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.sfp_port_start: # TBD + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("1" if lpmode is True else "0") + val_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.sfp_port_start: # TBD + return False + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("1") + val_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + val_file.write("0") + val_file.close() + + return True + + 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 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/sensors.conf new file mode 100644 index 000000000000..eb991d771d15 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/sensors.conf @@ -0,0 +1,76 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +bus "i2c-0" "I2C I801" +chip "tmp75-i2c-*-4f" + label temp1 "CPU Board Temp" + set temp1_max 50 + +bus "i2c-41" "i2c-7-switch (chan_id 0)" +chip "tmp75-i2c-*-48" + label temp1 "Near PSU1" + set temp1_max 50 +chip "tmp75-i2c-*-4a" + label temp1 "Rear MAC" + set temp1_max 50 +chip "tmp75-i2c-*-4b" + label temp1 "Near Port 32" + set temp1_max 50 +chip "tmp75-i2c-*-4d" + label temp1 "Near PSU2" + set temp1_max 50 +chip "lm86-i2c-*-4c" + label temp1 "Front MAC" + label temp2 "ASIC Core Temp" + set temp1_min 20 + set temp1_max 65 + set temp1_crit 70 + set temp2_min 20 + set temp2_max 70 + set temp2_crit 80 + +bus "i2c-56" "i2c-0-mux (chan_id 7)" +chip "w83795adg-*" + label in0 "0.9V" + set in0_max 0.927 + set in0_min 0.873 + label in1 "VDD" + set in1_max 0.962 + set in1_min 0.717 + ignore in2 + ignore in3 + ignore in4 + ignore in5 + ignore in6 + ignore in7 + label in12 "2.5V" + #compute in12 (2*4*@)/10, @-(2*4*@/10) + compute in12 @/(1+(3/10)), @*(1+(3/10)) + set in12_max 2.625 + set in12_min 2.375 + # in12 and in13 are the same source + ignore in13 + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/port_config.ini new file mode 100644 index 000000000000..c1d2642fab8e --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index +Ethernet0 49,50,51,52 Ethernet1/1 0 +Ethernet4 53,54,55,56 Ethernet2/1 1 +Ethernet8 65,66,67,68 Ethernet3/1 2 +Ethernet12 69,70,71,72 Ethernet4/1 3 +Ethernet16 81,82,83,84 Ethernet5/1 4 +Ethernet20 85,86,87,88 Ethernet6/1 5 +Ethernet24 1,2,3,4 Ethernet7/1 6 +Ethernet28 5,6,7,8 Ethernet8/1 7 +Ethernet32 17,18,19,20 Ethernet9/1 8 +Ethernet36 21,22,23,24 Ethernet10/1 9 +Ethernet40 33,34,35,36 Ethernet11/1 10 +Ethernet44 37,38,39,40 Ethernet12/1 11 +Ethernet48 97,98,99,100 Ethernet13/1 12 +Ethernet52 101,102,103,104 Ethernet14/1 13 +Ethernet56 113,114,115,116 Ethernet15/1 14 +Ethernet60 117,118,119,120 Ethernet16/1 15 +Ethernet64 129,130,131,132 Ethernet17/1 16 +Ethernet68 133,134,135,136 Ethernet18/1 17 +Ethernet72 145,146,147,148 Ethernet19/1 18 +Ethernet76 149,150,151,152 Ethernet20/1 19 +Ethernet80 209,210,211,212 Ethernet21/1 20 +Ethernet84 213,214,215,216 Ethernet22/1 21 +Ethernet88 225,226,227,228 Ethernet23/1 22 +Ethernet92 229,230,231,232 Ethernet24/1 23 +Ethernet96 241,242,243,244 Ethernet25/1 24 +Ethernet100 245,246,247,248 Ethernet26/1 25 +Ethernet104 161,162,163,164 Ethernet27/1 26 +Ethernet108 165,166,167,168 Ethernet28/1 27 +Ethernet112 177,178,179,180 Ethernet29/1 28 +Ethernet116 181,182,183,184 Ethernet30/1 29 +Ethernet120 193,194,195,196 Ethernet31/1 30 +Ethernet124 197,198,199,200 Ethernet32/1 31 +Ethernet128 57,58,59,60 Ethernet33/1 32 +Ethernet132 61,62,63,64 Ethernet34/1 33 +Ethernet136 73,74,75,76 Ethernet35/1 34 +Ethernet140 77,78,79,80 Ethernet36/1 35 +Ethernet144 89,90,91,92 Ethernet37/1 36 +Ethernet148 93,94,95,96 Ethernet38/1 37 +Ethernet152 9,10,11,12 Ethernet39/1 38 +Ethernet156 13,14,15,16 Ethernet40/1 39 +Ethernet160 25,26,27,28 Ethernet41/1 40 +Ethernet164 29,30,31,32 Ethernet42/1 41 +Ethernet168 41,42,43,44 Ethernet43/1 42 +Ethernet172 45,46,47,48 Ethernet44/1 43 +Ethernet176 105,106,107,108 Ethernet45/1 44 +Ethernet180 109,110,111,112 Ethernet46/1 45 +Ethernet184 121,122,123,124 Ethernet47/1 46 +Ethernet188 125,126,127,128 Ethernet48/1 47 +Ethernet192 137,138,139,140 Ethernet49/1 48 +Ethernet196 141,142,143,144 Ethernet50/1 49 +Ethernet200 153,154,155,156 Ethernet51/1 50 +Ethernet204 157,158,159,160 Ethernet52/1 51 +Ethernet208 217,218,219,220 Ethernet53/1 52 +Ethernet212 221,222,223,224 Ethernet54/1 53 +Ethernet216 233,234,235,236 Ethernet55/1 54 +Ethernet220 237,238,239,240 Ethernet56/1 55 +Ethernet224 249,250,251,252 Ethernet57/1 56 +Ethernet228 253,254,255,256 Ethernet58/1 57 +Ethernet232 169,170,171,172 Ethernet59/1 58 +Ethernet236 173,174,175,176 Ethernet60/1 59 +Ethernet240 185,186,187,188 Ethernet61/1 60 +Ethernet244 189,190,191,192 Ethernet62/1 61 +Ethernet248 201,202,203,204 Ethernet63/1 62 +Ethernet252 205,206,207,208 Ethernet64/1 63 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/sai.profile b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/sai.profile new file mode 100644 index 000000000000..d16307aa360d --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-s9200-64x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/th2-s9200-64x100G.config.bcm b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/th2-s9200-64x100G.config.bcm new file mode 100644 index 000000000000..b143fb425b92 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/INGRASYS-S9200-64X/th2-s9200-64x100G.config.bcm @@ -0,0 +1,873 @@ +#2018/3/6 + +os=unix + +oversubscribe_mode=1 +pbmp_xport_xe=0x3fffd0000ffff40003fffc0001fffe + +#ALPM enable +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 +l3_mem_entries=40960 +l2_mem_entries=40960 + +#Parity +parity_correction=1 +parity_enable=1 + +l2xmsg_mode=1 +mmu_lossless=0 + +# core_clock_frequency can be 1125, 850, 765, 672, 645 or 545 +#core_clock_frequency=1125 + + +#PIPE-0 +#FC 0 +portmap_1=1:100 +phy_chain_tx_polarity_flip_physical{1.0}=0 +phy_chain_tx_polarity_flip_physical{2.0}=1 +phy_chain_tx_polarity_flip_physical{3.0}=0 +phy_chain_tx_polarity_flip_physical{4.0}=0 +phy_chain_rx_polarity_flip_physical{1.0}=1 +phy_chain_rx_polarity_flip_physical{2.0}=1 +phy_chain_rx_polarity_flip_physical{3.0}=0 +phy_chain_rx_polarity_flip_physical{4.0}=1 +phy_chain_tx_lane_map_physical{1.0}=0x3210 +phy_chain_rx_lane_map_physical{1.0}=0x0312 + +#FC 1 +portmap_2=5:100 +phy_chain_tx_polarity_flip_physical{5.0}=1 +phy_chain_tx_polarity_flip_physical{6.0}=1 +phy_chain_tx_polarity_flip_physical{7.0}=0 +phy_chain_tx_polarity_flip_physical{8.0}=0 +phy_chain_rx_polarity_flip_physical{5.0}=1 +phy_chain_rx_polarity_flip_physical{6.0}=0 +phy_chain_rx_polarity_flip_physical{7.0}=1 +phy_chain_rx_polarity_flip_physical{8.0}=1 +phy_chain_tx_lane_map_physical{5.0}=0x1023 +phy_chain_rx_lane_map_physical{5.0}=0x2103 + +#FC 2 +portmap_3=9:100 +phy_chain_tx_polarity_flip_physical{9.0}=0 +phy_chain_tx_polarity_flip_physical{10.0}=0 +phy_chain_tx_polarity_flip_physical{11.0}=1 +phy_chain_tx_polarity_flip_physical{12.0}=1 +phy_chain_rx_polarity_flip_physical{9.0}=1 +phy_chain_rx_polarity_flip_physical{10.0}=1 +phy_chain_rx_polarity_flip_physical{11.0}=0 +phy_chain_rx_polarity_flip_physical{12.0}=1 +phy_chain_tx_lane_map_physical{9.0}=0x3201 +phy_chain_rx_lane_map_physical{9.0}=0x1320 + +#FC 3 +portmap_4=13:100 +phy_chain_tx_polarity_flip_physical{13.0}=0 +phy_chain_tx_polarity_flip_physical{14.0}=0 +phy_chain_tx_polarity_flip_physical{15.0}=0 +phy_chain_tx_polarity_flip_physical{16.0}=1 +phy_chain_rx_polarity_flip_physical{13.0}=0 +phy_chain_rx_polarity_flip_physical{14.0}=0 +phy_chain_rx_polarity_flip_physical{15.0}=0 +phy_chain_rx_polarity_flip_physical{16.0}=0 +phy_chain_tx_lane_map_physical{13.0}=0x2013 +phy_chain_rx_lane_map_physical{13.0}=0x2310 + +#FC 4 +portmap_5=17:100 +phy_chain_tx_polarity_flip_physical{17.0}=1 +phy_chain_tx_polarity_flip_physical{18.0}=0 +phy_chain_tx_polarity_flip_physical{19.0}=0 +phy_chain_tx_polarity_flip_physical{20.0}=0 +phy_chain_rx_polarity_flip_physical{17.0}=0 +phy_chain_rx_polarity_flip_physical{18.0}=1 +phy_chain_rx_polarity_flip_physical{19.0}=1 +phy_chain_rx_polarity_flip_physical{20.0}=1 +phy_chain_tx_lane_map_physical{17.0}=0x0213 +phy_chain_rx_lane_map_physical{17.0}=0x0132 + +#FC 5 +portmap_6=21:100 +phy_chain_tx_polarity_flip_physical{21.0}=1 +phy_chain_tx_polarity_flip_physical{22.0}=1 +phy_chain_tx_polarity_flip_physical{23.0}=0 +phy_chain_tx_polarity_flip_physical{24.0}=0 +phy_chain_rx_polarity_flip_physical{21.0}=1 +phy_chain_rx_polarity_flip_physical{22.0}=0 +phy_chain_rx_polarity_flip_physical{23.0}=0 +phy_chain_rx_polarity_flip_physical{24.0}=1 +phy_chain_tx_lane_map_physical{21.0}=0x3021 +phy_chain_rx_lane_map_physical{21.0}=0x0312 + +#FC 6 +portmap_7=25:100 +phy_chain_tx_polarity_flip_physical{25.0}=0 +phy_chain_tx_polarity_flip_physical{26.0}=0 +phy_chain_tx_polarity_flip_physical{27.0}=0 +phy_chain_tx_polarity_flip_physical{28.0}=0 +phy_chain_rx_polarity_flip_physical{25.0}=0 +phy_chain_rx_polarity_flip_physical{26.0}=0 +phy_chain_rx_polarity_flip_physical{27.0}=0 +phy_chain_rx_polarity_flip_physical{28.0}=0 +phy_chain_tx_lane_map_physical{25.0}=0x2310 +phy_chain_rx_lane_map_physical{25.0}=0x1302 + +#FC 7 +portmap_8=29:100 +phy_chain_tx_polarity_flip_physical{29.0}=0 +phy_chain_tx_polarity_flip_physical{30.0}=0 +phy_chain_tx_polarity_flip_physical{31.0}=0 +phy_chain_tx_polarity_flip_physical{32.0}=1 +phy_chain_rx_polarity_flip_physical{29.0}=0 +phy_chain_rx_polarity_flip_physical{30.0}=0 +phy_chain_rx_polarity_flip_physical{31.0}=1 +phy_chain_rx_polarity_flip_physical{32.0}=0 +phy_chain_tx_lane_map_physical{29.0}=0x2031 +phy_chain_rx_lane_map_physical{29.0}=0x2310 + +#FC 8 +portmap_9=33:100 +phy_chain_tx_polarity_flip_physical{33.0}=1 +phy_chain_tx_polarity_flip_physical{34.0}=1 +phy_chain_tx_polarity_flip_physical{35.0}=0 +phy_chain_tx_polarity_flip_physical{36.0}=1 +phy_chain_rx_polarity_flip_physical{33.0}=1 +phy_chain_rx_polarity_flip_physical{34.0}=0 +phy_chain_rx_polarity_flip_physical{35.0}=0 +phy_chain_rx_polarity_flip_physical{36.0}=0 +phy_chain_tx_lane_map_physical{33.0}=0x3120 +phy_chain_rx_lane_map_physical{33.0}=0x2130 + +#FC 9 +portmap_10=37:100 +phy_chain_tx_polarity_flip_physical{37.0}=1 +phy_chain_tx_polarity_flip_physical{38.0}=1 +phy_chain_tx_polarity_flip_physical{39.0}=1 +phy_chain_tx_polarity_flip_physical{40.0}=1 +phy_chain_rx_polarity_flip_physical{37.0}=0 +phy_chain_rx_polarity_flip_physical{38.0}=1 +phy_chain_rx_polarity_flip_physical{39.0}=0 +phy_chain_rx_polarity_flip_physical{40.0}=0 +phy_chain_tx_lane_map_physical{37.0}=0x0123 +phy_chain_rx_lane_map_physical{37.0}=0x1230 + +#FC 10 +portmap_11=41:100 +phy_chain_tx_polarity_flip_physical{41.0}=1 +phy_chain_tx_polarity_flip_physical{42.0}=1 +phy_chain_tx_polarity_flip_physical{43.0}=0 +phy_chain_tx_polarity_flip_physical{44.0}=0 +phy_chain_rx_polarity_flip_physical{41.0}=1 +phy_chain_rx_polarity_flip_physical{42.0}=0 +phy_chain_rx_polarity_flip_physical{43.0}=0 +phy_chain_rx_polarity_flip_physical{44.0}=0 +phy_chain_tx_lane_map_physical{41.0}=0x3021 +phy_chain_rx_lane_map_physical{41.0}=0x1230 + +#FC 11 +portmap_12=45:100 +phy_chain_tx_polarity_flip_physical{45.0}=0 +phy_chain_tx_polarity_flip_physical{46.0}=1 +phy_chain_tx_polarity_flip_physical{47.0}=1 +phy_chain_tx_polarity_flip_physical{48.0}=1 +phy_chain_rx_polarity_flip_physical{45.0}=0 +phy_chain_rx_polarity_flip_physical{46.0}=1 +phy_chain_rx_polarity_flip_physical{47.0}=1 +phy_chain_rx_polarity_flip_physical{48.0}=1 +phy_chain_tx_lane_map_physical{45.0}=0x0123 +phy_chain_rx_lane_map_physical{45.0}=0x0213 + +#FC 12 +portmap_13=49:100 +phy_chain_tx_polarity_flip_physical{49.0}=1 +phy_chain_tx_polarity_flip_physical{50.0}=0 +phy_chain_tx_polarity_flip_physical{51.0}=1 +phy_chain_tx_polarity_flip_physical{52.0}=0 +phy_chain_rx_polarity_flip_physical{49.0}=1 +phy_chain_rx_polarity_flip_physical{50.0}=1 +phy_chain_rx_polarity_flip_physical{51.0}=1 +phy_chain_rx_polarity_flip_physical{52.0}=0 +phy_chain_tx_lane_map_physical{49.0}=0x0213 +phy_chain_rx_lane_map_physical{49.0}=0x0123 + +#FC 13 +portmap_14=53:100 +phy_chain_tx_polarity_flip_physical{53.0}=1 +phy_chain_tx_polarity_flip_physical{54.0}=1 +phy_chain_tx_polarity_flip_physical{55.0}=0 +phy_chain_tx_polarity_flip_physical{56.0}=1 +phy_chain_rx_polarity_flip_physical{53.0}=0 +phy_chain_rx_polarity_flip_physical{54.0}=1 +phy_chain_rx_polarity_flip_physical{55.0}=1 +phy_chain_rx_polarity_flip_physical{56.0}=1 +phy_chain_tx_lane_map_physical{53.0}=0x2031 +phy_chain_rx_lane_map_physical{53.0}=0x0132 + +#FC 14 +portmap_15=57:100 +phy_chain_tx_polarity_flip_physical{57.0}=1 +phy_chain_tx_polarity_flip_physical{58.0}=0 +phy_chain_tx_polarity_flip_physical{59.0}=0 +phy_chain_tx_polarity_flip_physical{60.0}=0 +phy_chain_rx_polarity_flip_physical{57.0}=0 +phy_chain_rx_polarity_flip_physical{58.0}=0 +phy_chain_rx_polarity_flip_physical{59.0}=0 +phy_chain_rx_polarity_flip_physical{60.0}=0 +phy_chain_tx_lane_map_physical{57.0}=0x3021 +phy_chain_rx_lane_map_physical{57.0}=0x2103 + +#FC 15 +portmap_16=61:100 +phy_chain_tx_polarity_flip_physical{61.0}=0 +phy_chain_tx_polarity_flip_physical{62.0}=0 +phy_chain_tx_polarity_flip_physical{63.0}=0 +phy_chain_tx_polarity_flip_physical{64.0}=1 +phy_chain_rx_polarity_flip_physical{61.0}=0 +phy_chain_rx_polarity_flip_physical{62.0}=1 +phy_chain_rx_polarity_flip_physical{63.0}=1 +phy_chain_rx_polarity_flip_physical{64.0}=1 +phy_chain_tx_lane_map_physical{61.0}=0x0132 +phy_chain_rx_lane_map_physical{61.0}=0x1320 + +#PIPE-1 +#FC 16 +portmap_34=65:100 +phy_chain_tx_polarity_flip_physical{65.0}=1 +phy_chain_tx_polarity_flip_physical{66.0}=1 +phy_chain_tx_polarity_flip_physical{67.0}=1 +phy_chain_tx_polarity_flip_physical{68.0}=1 +phy_chain_rx_polarity_flip_physical{65.0}=0 +phy_chain_rx_polarity_flip_physical{66.0}=0 +phy_chain_rx_polarity_flip_physical{67.0}=1 +phy_chain_rx_polarity_flip_physical{68.0}=0 +phy_chain_tx_lane_map_physical{65.0}=0x2031 +phy_chain_rx_lane_map_physical{65.0}=0x2031 + +#FC 17 +portmap_35=69:100 +phy_chain_tx_polarity_flip_physical{69.0}=1 +phy_chain_tx_polarity_flip_physical{70.0}=0 +phy_chain_tx_polarity_flip_physical{71.0}=0 +phy_chain_tx_polarity_flip_physical{72.0}=1 +phy_chain_rx_polarity_flip_physical{69.0}=1 +phy_chain_rx_polarity_flip_physical{70.0}=0 +phy_chain_rx_polarity_flip_physical{71.0}=0 +phy_chain_rx_polarity_flip_physical{72.0}=1 +phy_chain_tx_lane_map_physical{69.0}=0x2031 +phy_chain_rx_lane_map_physical{69.0}=0x3201 + +#FC 18 +portmap_36=73:100 +phy_chain_tx_polarity_flip_physical{73.0}=0 +phy_chain_tx_polarity_flip_physical{74.0}=0 +phy_chain_tx_polarity_flip_physical{75.0}=1 +phy_chain_tx_polarity_flip_physical{76.0}=0 +phy_chain_rx_polarity_flip_physical{73.0}=1 +phy_chain_rx_polarity_flip_physical{74.0}=1 +phy_chain_rx_polarity_flip_physical{75.0}=0 +phy_chain_rx_polarity_flip_physical{76.0}=0 +phy_chain_tx_lane_map_physical{73.0}=0x3120 +phy_chain_rx_lane_map_physical{73.0}=0x3201 + +#FC 19 +portmap_37=77:100 +phy_chain_tx_polarity_flip_physical{77.0}=1 +phy_chain_tx_polarity_flip_physical{78.0}=0 +phy_chain_tx_polarity_flip_physical{79.0}=1 +phy_chain_tx_polarity_flip_physical{80.0}=0 +phy_chain_rx_polarity_flip_physical{77.0}=1 +phy_chain_rx_polarity_flip_physical{78.0}=0 +phy_chain_rx_polarity_flip_physical{79.0}=1 +phy_chain_rx_polarity_flip_physical{80.0}=0 +phy_chain_tx_lane_map_physical{77.0}=0x0132 +phy_chain_rx_lane_map_physical{77.0}=0x1032 + +#FC 20 +portmap_38=81:100 +phy_chain_tx_polarity_flip_physical{81.0}=1 +phy_chain_tx_polarity_flip_physical{82.0}=0 +phy_chain_tx_polarity_flip_physical{83.0}=1 +phy_chain_tx_polarity_flip_physical{84.0}=0 +phy_chain_rx_polarity_flip_physical{81.0}=0 +phy_chain_rx_polarity_flip_physical{82.0}=1 +phy_chain_rx_polarity_flip_physical{83.0}=1 +phy_chain_rx_polarity_flip_physical{84.0}=1 +phy_chain_tx_lane_map_physical{81.0}=0x0213 +phy_chain_rx_lane_map_physical{81.0}=0x1203 + +#FC 21 +portmap_39=85:100 +phy_chain_tx_polarity_flip_physical{85.0}=1 +phy_chain_tx_polarity_flip_physical{86.0}=1 +phy_chain_tx_polarity_flip_physical{87.0}=0 +phy_chain_tx_polarity_flip_physical{88.0}=0 +phy_chain_rx_polarity_flip_physical{85.0}=0 +phy_chain_rx_polarity_flip_physical{86.0}=1 +phy_chain_rx_polarity_flip_physical{87.0}=0 +phy_chain_rx_polarity_flip_physical{88.0}=1 +phy_chain_tx_lane_map_physical{85.0}=0x3021 +phy_chain_rx_lane_map_physical{85.0}=0x1230 + +#FC 22 +portmap_40=89:100 +phy_chain_tx_polarity_flip_physical{89.0}=1 +phy_chain_tx_polarity_flip_physical{90.0}=0 +phy_chain_tx_polarity_flip_physical{91.0}=0 +phy_chain_tx_polarity_flip_physical{92.0}=0 +phy_chain_rx_polarity_flip_physical{89.0}=1 +phy_chain_rx_polarity_flip_physical{90.0}=1 +phy_chain_rx_polarity_flip_physical{91.0}=0 +phy_chain_rx_polarity_flip_physical{92.0}=0 +phy_chain_tx_lane_map_physical{89.0}=0x3021 +phy_chain_rx_lane_map_physical{89.0}=0x3201 + +#FC 23 +portmap_41=93:100 +phy_chain_tx_polarity_flip_physical{93.0}=0 +phy_chain_tx_polarity_flip_physical{94.0}=0 +phy_chain_tx_polarity_flip_physical{95.0}=1 +phy_chain_tx_polarity_flip_physical{96.0}=0 +phy_chain_rx_polarity_flip_physical{93.0}=1 +phy_chain_rx_polarity_flip_physical{94.0}=0 +phy_chain_rx_polarity_flip_physical{95.0}=1 +phy_chain_rx_polarity_flip_physical{96.0}=0 +phy_chain_tx_lane_map_physical{93.0}=0x1023 +phy_chain_rx_lane_map_physical{93.0}=0x1032 + +#FC 24 +portmap_42=97:100 +phy_chain_tx_polarity_flip_physical{97.0}=0 +phy_chain_tx_polarity_flip_physical{98.0}=1 +phy_chain_tx_polarity_flip_physical{99.0}=1 +phy_chain_tx_polarity_flip_physical{100.0}=0 +phy_chain_rx_polarity_flip_physical{97.0}=0 +phy_chain_rx_polarity_flip_physical{98.0}=0 +phy_chain_rx_polarity_flip_physical{99.0}=0 +phy_chain_rx_polarity_flip_physical{100.0}=1 +phy_chain_tx_lane_map_physical{97.0}=0x0132 +phy_chain_rx_lane_map_physical{97.0}=0x1320 + +#FC 25 +portmap_43=101:100 +phy_chain_tx_polarity_flip_physical{101.0}=0 +phy_chain_tx_polarity_flip_physical{102.0}=1 +phy_chain_tx_polarity_flip_physical{103.0}=1 +phy_chain_tx_polarity_flip_physical{104.0}=1 +phy_chain_rx_polarity_flip_physical{101.0}=1 +phy_chain_rx_polarity_flip_physical{102.0}=1 +phy_chain_rx_polarity_flip_physical{103.0}=1 +phy_chain_rx_polarity_flip_physical{104.0}=1 +phy_chain_tx_lane_map_physical{101.0}=0x1023 +phy_chain_rx_lane_map_physical{101.0}=0x3120 + +#FC 26 +portmap_44=105:100 +phy_chain_tx_polarity_flip_physical{105.0}=1 +phy_chain_tx_polarity_flip_physical{106.0}=0 +phy_chain_tx_polarity_flip_physical{107.0}=1 +phy_chain_tx_polarity_flip_physical{108.0}=1 +phy_chain_rx_polarity_flip_physical{105.0}=1 +phy_chain_rx_polarity_flip_physical{106.0}=1 +phy_chain_rx_polarity_flip_physical{107.0}=0 +phy_chain_rx_polarity_flip_physical{108.0}=0 +phy_chain_tx_lane_map_physical{105.0}=0x2103 +phy_chain_rx_lane_map_physical{105.0}=0x1203 + +#FC 27 +portmap_45=109:100 +phy_chain_tx_polarity_flip_physical{109.0}=1 +phy_chain_tx_polarity_flip_physical{110.0}=1 +phy_chain_tx_polarity_flip_physical{111.0}=0 +phy_chain_tx_polarity_flip_physical{112.0}=1 +phy_chain_rx_polarity_flip_physical{109.0}=0 +phy_chain_rx_polarity_flip_physical{110.0}=0 +phy_chain_rx_polarity_flip_physical{111.0}=1 +phy_chain_rx_polarity_flip_physical{112.0}=0 +phy_chain_tx_lane_map_physical{109.0}=0x3201 +phy_chain_rx_lane_map_physical{109.0}=0x0123 + +#FC 28 +portmap_46=113:100 +phy_chain_tx_polarity_flip_physical{113.0}=0 +phy_chain_tx_polarity_flip_physical{114.0}=1 +phy_chain_tx_polarity_flip_physical{115.0}=1 +phy_chain_tx_polarity_flip_physical{116.0}=0 +phy_chain_rx_polarity_flip_physical{113.0}=1 +phy_chain_rx_polarity_flip_physical{114.0}=0 +phy_chain_rx_polarity_flip_physical{115.0}=0 +phy_chain_rx_polarity_flip_physical{116.0}=1 +phy_chain_tx_lane_map_physical{113.0}=0x3012 +phy_chain_rx_lane_map_physical{113.0}=0x1302 + +#FC 29 +portmap_47=117:100 +phy_chain_tx_polarity_flip_physical{117.0}=1 +phy_chain_tx_polarity_flip_physical{118.0}=1 +phy_chain_tx_polarity_flip_physical{119.0}=0 +phy_chain_tx_polarity_flip_physical{120.0}=0 +phy_chain_rx_polarity_flip_physical{117.0}=1 +phy_chain_rx_polarity_flip_physical{118.0}=0 +phy_chain_rx_polarity_flip_physical{119.0}=0 +phy_chain_rx_polarity_flip_physical{120.0}=1 +phy_chain_tx_lane_map_physical{117.0}=0x0312 +phy_chain_rx_lane_map_physical{117.0}=0x0132 + +#FC 30 +portmap_48=121:100 +phy_chain_tx_polarity_flip_physical{121.0}=1 +phy_chain_tx_polarity_flip_physical{122.0}=0 +phy_chain_tx_polarity_flip_physical{123.0}=0 +phy_chain_tx_polarity_flip_physical{124.0}=0 +phy_chain_rx_polarity_flip_physical{121.0}=1 +phy_chain_rx_polarity_flip_physical{122.0}=1 +phy_chain_rx_polarity_flip_physical{123.0}=0 +phy_chain_rx_polarity_flip_physical{124.0}=0 +phy_chain_tx_lane_map_physical{121.0}=0x1023 +phy_chain_rx_lane_map_physical{121.0}=0x1203 + +#FC 31 +portmap_49=125:100 +phy_chain_tx_polarity_flip_physical{125.0}=0 +phy_chain_tx_polarity_flip_physical{126.0}=1 +phy_chain_tx_polarity_flip_physical{127.0}=0 +phy_chain_tx_polarity_flip_physical{128.0}=1 +phy_chain_rx_polarity_flip_physical{125.0}=0 +phy_chain_rx_polarity_flip_physical{126.0}=0 +phy_chain_rx_polarity_flip_physical{127.0}=1 +phy_chain_rx_polarity_flip_physical{128.0}=0 +phy_chain_tx_lane_map_physical{125.0}=0x1320 +phy_chain_rx_lane_map_physical{125.0}=0x2103 + +#PIPE-2 +#FC 32 +portmap_68=129:100 +phy_chain_tx_polarity_flip_physical{129.0}=0 +phy_chain_tx_polarity_flip_physical{130.0}=1 +phy_chain_tx_polarity_flip_physical{131.0}=1 +phy_chain_tx_polarity_flip_physical{132.0}=0 +phy_chain_rx_polarity_flip_physical{129.0}=0 +phy_chain_rx_polarity_flip_physical{130.0}=1 +phy_chain_rx_polarity_flip_physical{131.0}=1 +phy_chain_rx_polarity_flip_physical{132.0}=1 +phy_chain_tx_lane_map_physical{129.0}=0x0321 +phy_chain_rx_lane_map_physical{129.0}=0x2310 + +#FC 33 +portmap_69=133:100 +phy_chain_tx_polarity_flip_physical{133.0}=1 +phy_chain_tx_polarity_flip_physical{134.0}=0 +phy_chain_tx_polarity_flip_physical{135.0}=0 +phy_chain_tx_polarity_flip_physical{136.0}=1 +phy_chain_rx_polarity_flip_physical{133.0}=1 +phy_chain_rx_polarity_flip_physical{134.0}=0 +phy_chain_rx_polarity_flip_physical{135.0}=0 +phy_chain_rx_polarity_flip_physical{136.0}=1 +phy_chain_tx_lane_map_physical{133.0}=0x2013 +phy_chain_rx_lane_map_physical{133.0}=0x1203 + +#FC 34 +portmap_70=137:100 +phy_chain_tx_polarity_flip_physical{137.0}=0 +phy_chain_tx_polarity_flip_physical{138.0}=1 +phy_chain_tx_polarity_flip_physical{139.0}=0 +phy_chain_tx_polarity_flip_physical{140.0}=0 +phy_chain_rx_polarity_flip_physical{137.0}=0 +phy_chain_rx_polarity_flip_physical{138.0}=1 +phy_chain_rx_polarity_flip_physical{139.0}=1 +phy_chain_rx_polarity_flip_physical{140.0}=0 +phy_chain_tx_lane_map_physical{137.0}=0x2301 +phy_chain_rx_lane_map_physical{137.0}=0x0213 + +#FC 35 +portmap_71=141:100 +phy_chain_tx_polarity_flip_physical{141.0}=0 +phy_chain_tx_polarity_flip_physical{142.0}=1 +phy_chain_tx_polarity_flip_physical{143.0}=0 +phy_chain_tx_polarity_flip_physical{144.0}=1 +phy_chain_rx_polarity_flip_physical{141.0}=0 +phy_chain_rx_polarity_flip_physical{142.0}=0 +phy_chain_rx_polarity_flip_physical{143.0}=0 +phy_chain_rx_polarity_flip_physical{144.0}=1 +phy_chain_tx_lane_map_physical{141.0}=0x2013 +phy_chain_rx_lane_map_physical{141.0}=0x2310 + +#FC 36 +portmap_72=145:100 +phy_chain_tx_polarity_flip_physical{145.0}=1 +phy_chain_tx_polarity_flip_physical{146.0}=0 +phy_chain_tx_polarity_flip_physical{147.0}=1 +phy_chain_tx_polarity_flip_physical{148.0}=0 +phy_chain_rx_polarity_flip_physical{145.0}=1 +phy_chain_rx_polarity_flip_physical{146.0}=0 +phy_chain_rx_polarity_flip_physical{147.0}=0 +phy_chain_rx_polarity_flip_physical{148.0}=1 +phy_chain_tx_lane_map_physical{145.0}=0x2310 +phy_chain_rx_lane_map_physical{145.0}=0x0231 + +#FC 37 +portmap_73=149:100 +phy_chain_tx_polarity_flip_physical{149.0}=1 +phy_chain_tx_polarity_flip_physical{150.0}=1 +phy_chain_tx_polarity_flip_physical{151.0}=0 +phy_chain_tx_polarity_flip_physical{152.0}=0 +phy_chain_rx_polarity_flip_physical{149.0}=1 +phy_chain_rx_polarity_flip_physical{150.0}=0 +phy_chain_rx_polarity_flip_physical{151.0}=0 +phy_chain_rx_polarity_flip_physical{152.0}=1 +phy_chain_tx_lane_map_physical{149.0}=0x3021 +phy_chain_rx_lane_map_physical{149.0}=0x1203 + +#FC 38 +portmap_74=153:100 +phy_chain_tx_polarity_flip_physical{153.0}=1 +phy_chain_tx_polarity_flip_physical{154.0}=0 +phy_chain_tx_polarity_flip_physical{155.0}=1 +phy_chain_tx_polarity_flip_physical{156.0}=1 +phy_chain_rx_polarity_flip_physical{153.0}=0 +phy_chain_rx_polarity_flip_physical{154.0}=0 +phy_chain_rx_polarity_flip_physical{155.0}=0 +phy_chain_rx_polarity_flip_physical{156.0}=0 +phy_chain_tx_lane_map_physical{153.0}=0x1230 +phy_chain_rx_lane_map_physical{153.0}=0x3120 + +#FC 39 +portmap_75=157:100 +phy_chain_tx_polarity_flip_physical{157.0}=1 +phy_chain_tx_polarity_flip_physical{158.0}=1 +phy_chain_tx_polarity_flip_physical{159.0}=1 +phy_chain_tx_polarity_flip_physical{160.0}=0 +phy_chain_rx_polarity_flip_physical{157.0}=0 +phy_chain_rx_polarity_flip_physical{158.0}=0 +phy_chain_rx_polarity_flip_physical{159.0}=1 +phy_chain_rx_polarity_flip_physical{160.0}=0 +phy_chain_tx_lane_map_physical{157.0}=0x3210 +phy_chain_rx_lane_map_physical{157.0}=0x3210 + +#FC 40 +portmap_76=161:100 +phy_chain_tx_polarity_flip_physical{161.0}=1 +phy_chain_tx_polarity_flip_physical{162.0}=1 +phy_chain_tx_polarity_flip_physical{163.0}=0 +phy_chain_tx_polarity_flip_physical{164.0}=1 +phy_chain_rx_polarity_flip_physical{161.0}=1 +phy_chain_rx_polarity_flip_physical{162.0}=1 +phy_chain_rx_polarity_flip_physical{163.0}=1 +phy_chain_rx_polarity_flip_physical{164.0}=1 +phy_chain_tx_lane_map_physical{161.0}=0x2031 +phy_chain_rx_lane_map_physical{161.0}=0x1032 + +#FC 41 +portmap_77=165:100 +phy_chain_tx_polarity_flip_physical{165.0}=0 +phy_chain_tx_polarity_flip_physical{166.0}=0 +phy_chain_tx_polarity_flip_physical{167.0}=1 +phy_chain_tx_polarity_flip_physical{168.0}=1 +phy_chain_rx_polarity_flip_physical{165.0}=0 +phy_chain_rx_polarity_flip_physical{166.0}=1 +phy_chain_rx_polarity_flip_physical{167.0}=0 +phy_chain_rx_polarity_flip_physical{168.0}=1 +phy_chain_tx_lane_map_physical{165.0}=0x2310 +phy_chain_rx_lane_map_physical{165.0}=0x1230 + +#FC 42 +portmap_78=169:100 +phy_chain_tx_polarity_flip_physical{169.0}=1 +phy_chain_tx_polarity_flip_physical{170.0}=0 +phy_chain_tx_polarity_flip_physical{171.0}=1 +phy_chain_tx_polarity_flip_physical{172.0}=0 +phy_chain_rx_polarity_flip_physical{169.0}=0 +phy_chain_rx_polarity_flip_physical{170.0}=0 +phy_chain_rx_polarity_flip_physical{171.0}=0 +phy_chain_rx_polarity_flip_physical{172.0}=0 +phy_chain_tx_lane_map_physical{169.0}=0x1302 +phy_chain_rx_lane_map_physical{169.0}=0x3210 + +#FC 43 +portmap_79=173:100 +phy_chain_tx_polarity_flip_physical{173.0}=1 +phy_chain_tx_polarity_flip_physical{174.0}=0 +phy_chain_tx_polarity_flip_physical{175.0}=0 +phy_chain_tx_polarity_flip_physical{176.0}=0 +phy_chain_rx_polarity_flip_physical{173.0}=0 +phy_chain_rx_polarity_flip_physical{174.0}=1 +phy_chain_rx_polarity_flip_physical{175.0}=0 +phy_chain_rx_polarity_flip_physical{176.0}=1 +phy_chain_tx_lane_map_physical{173.0}=0x0312 +phy_chain_rx_lane_map_physical{173.0}=0x3210 + +#FC 44 +portmap_80=177:100 +phy_chain_tx_polarity_flip_physical{177.0}=0 +phy_chain_tx_polarity_flip_physical{178.0}=1 +phy_chain_tx_polarity_flip_physical{179.0}=0 +phy_chain_tx_polarity_flip_physical{180.0}=1 +phy_chain_rx_polarity_flip_physical{177.0}=1 +phy_chain_rx_polarity_flip_physical{178.0}=1 +phy_chain_rx_polarity_flip_physical{179.0}=0 +phy_chain_rx_polarity_flip_physical{180.0}=1 +phy_chain_tx_lane_map_physical{177.0}=0x2031 +phy_chain_rx_lane_map_physical{177.0}=0x1302 + +#FC 45 +portmap_81=181:100 +phy_chain_tx_polarity_flip_physical{181.0}=0 +phy_chain_tx_polarity_flip_physical{182.0}=0 +phy_chain_tx_polarity_flip_physical{183.0}=0 +phy_chain_tx_polarity_flip_physical{184.0}=0 +phy_chain_rx_polarity_flip_physical{181.0}=0 +phy_chain_rx_polarity_flip_physical{182.0}=1 +phy_chain_rx_polarity_flip_physical{183.0}=0 +phy_chain_rx_polarity_flip_physical{184.0}=1 +phy_chain_tx_lane_map_physical{181.0}=0x1023 +phy_chain_rx_lane_map_physical{181.0}=0x2301 + +#FC 46 +portmap_82=185:100 +phy_chain_tx_polarity_flip_physical{185.0}=0 +phy_chain_tx_polarity_flip_physical{186.0}=0 +phy_chain_tx_polarity_flip_physical{187.0}=1 +phy_chain_tx_polarity_flip_physical{188.0}=0 +phy_chain_rx_polarity_flip_physical{185.0}=0 +phy_chain_rx_polarity_flip_physical{186.0}=0 +phy_chain_rx_polarity_flip_physical{187.0}=0 +phy_chain_rx_polarity_flip_physical{188.0}=0 +phy_chain_tx_lane_map_physical{185.0}=0x1320 +phy_chain_rx_lane_map_physical{185.0}=0x3210 + +#FC 47 +portmap_83=189:100 +phy_chain_tx_polarity_flip_physical{189.0}=1 +phy_chain_tx_polarity_flip_physical{190.0}=1 +phy_chain_tx_polarity_flip_physical{191.0}=0 +phy_chain_tx_polarity_flip_physical{192.0}=1 +phy_chain_rx_polarity_flip_physical{189.0}=0 +phy_chain_rx_polarity_flip_physical{190.0}=1 +phy_chain_rx_polarity_flip_physical{191.0}=0 +phy_chain_rx_polarity_flip_physical{192.0}=1 +phy_chain_tx_lane_map_physical{189.0}=0x3021 +phy_chain_rx_lane_map_physical{189.0}=0x3210 + +#PIPE-3 +#FC 48 +portmap_102=193:100 +phy_chain_tx_polarity_flip_physical{193.0}=1 +phy_chain_tx_polarity_flip_physical{194.0}=0 +phy_chain_tx_polarity_flip_physical{195.0}=1 +phy_chain_tx_polarity_flip_physical{196.0}=0 +phy_chain_rx_polarity_flip_physical{193.0}=1 +phy_chain_rx_polarity_flip_physical{194.0}=1 +phy_chain_rx_polarity_flip_physical{195.0}=0 +phy_chain_rx_polarity_flip_physical{196.0}=1 +phy_chain_tx_lane_map_physical{193.0}=0x3021 +phy_chain_rx_lane_map_physical{193.0}=0x1302 + +#FC 49 +portmap_103=197:100 +phy_chain_tx_polarity_flip_physical{197.0}=1 +phy_chain_tx_polarity_flip_physical{198.0}=0 +phy_chain_tx_polarity_flip_physical{199.0}=0 +phy_chain_tx_polarity_flip_physical{200.0}=1 +phy_chain_rx_polarity_flip_physical{197.0}=0 +phy_chain_rx_polarity_flip_physical{198.0}=1 +phy_chain_rx_polarity_flip_physical{199.0}=0 +phy_chain_rx_polarity_flip_physical{200.0}=1 +phy_chain_tx_lane_map_physical{197.0}=0x0132 +phy_chain_rx_lane_map_physical{197.0}=0x2301 + +#FC 50 +portmap_104=201:100 +phy_chain_tx_polarity_flip_physical{201.0}=1 +phy_chain_tx_polarity_flip_physical{202.0}=0 +phy_chain_tx_polarity_flip_physical{203.0}=1 +phy_chain_tx_polarity_flip_physical{204.0}=1 +phy_chain_rx_polarity_flip_physical{201.0}=0 +phy_chain_rx_polarity_flip_physical{202.0}=0 +phy_chain_rx_polarity_flip_physical{203.0}=0 +phy_chain_rx_polarity_flip_physical{204.0}=0 +phy_chain_tx_lane_map_physical{201.0}=0x2301 +phy_chain_rx_lane_map_physical{201.0}=0x1230 + +#FC 51 +portmap_105=205:100 +phy_chain_tx_polarity_flip_physical{205.0}=1 +phy_chain_tx_polarity_flip_physical{206.0}=1 +phy_chain_tx_polarity_flip_physical{207.0}=0 +phy_chain_tx_polarity_flip_physical{208.0}=0 +phy_chain_rx_polarity_flip_physical{205.0}=0 +phy_chain_rx_polarity_flip_physical{206.0}=0 +phy_chain_rx_polarity_flip_physical{207.0}=0 +phy_chain_rx_polarity_flip_physical{208.0}=1 +phy_chain_tx_lane_map_physical{205.0}=0x3021 +phy_chain_rx_lane_map_physical{205.0}=0x2130 + +#FC 52 +portmap_106=209:100 +phy_chain_tx_polarity_flip_physical{209.0}=1 +phy_chain_tx_polarity_flip_physical{210.0}=1 +phy_chain_tx_polarity_flip_physical{211.0}=0 +phy_chain_tx_polarity_flip_physical{212.0}=1 +phy_chain_rx_polarity_flip_physical{209.0}=0 +phy_chain_rx_polarity_flip_physical{210.0}=0 +phy_chain_rx_polarity_flip_physical{211.0}=1 +phy_chain_rx_polarity_flip_physical{212.0}=1 +phy_chain_tx_lane_map_physical{209.0}=0x2031 +phy_chain_rx_lane_map_physical{209.0}=0x3021 + +#FC 53 +portmap_107=213:100 +phy_chain_tx_polarity_flip_physical{213.0}=0 +phy_chain_tx_polarity_flip_physical{214.0}=1 +phy_chain_tx_polarity_flip_physical{215.0}=1 +phy_chain_tx_polarity_flip_physical{216.0}=0 +phy_chain_rx_polarity_flip_physical{213.0}=0 +phy_chain_rx_polarity_flip_physical{214.0}=1 +phy_chain_rx_polarity_flip_physical{215.0}=0 +phy_chain_rx_polarity_flip_physical{216.0}=1 +phy_chain_tx_lane_map_physical{213.0}=0x1302 +phy_chain_rx_lane_map_physical{213.0}=0x1032 + +#FC 54 +portmap_108=217:100 +phy_chain_tx_polarity_flip_physical{217.0}=1 +phy_chain_tx_polarity_flip_physical{218.0}=0 +phy_chain_tx_polarity_flip_physical{219.0}=1 +phy_chain_tx_polarity_flip_physical{220.0}=1 +phy_chain_rx_polarity_flip_physical{217.0}=0 +phy_chain_rx_polarity_flip_physical{218.0}=0 +phy_chain_rx_polarity_flip_physical{219.0}=0 +phy_chain_rx_polarity_flip_physical{220.0}=0 +phy_chain_tx_lane_map_physical{217.0}=0x2301 +phy_chain_rx_lane_map_physical{217.0}=0x1230 + +#FC 55 +portmap_109=221:100 +phy_chain_tx_polarity_flip_physical{221.0}=0 +phy_chain_tx_polarity_flip_physical{222.0}=0 +phy_chain_tx_polarity_flip_physical{223.0}=0 +phy_chain_tx_polarity_flip_physical{224.0}=0 +phy_chain_rx_polarity_flip_physical{221.0}=0 +phy_chain_rx_polarity_flip_physical{222.0}=1 +phy_chain_rx_polarity_flip_physical{223.0}=0 +phy_chain_rx_polarity_flip_physical{224.0}=1 +phy_chain_tx_lane_map_physical{221.0}=0x3210 +phy_chain_rx_lane_map_physical{221.0}=0x2310 + +#FC 56 +portmap_110=225:100 +phy_chain_tx_polarity_flip_physical{225.0}=0 +phy_chain_tx_polarity_flip_physical{226.0}=0 +phy_chain_tx_polarity_flip_physical{227.0}=1 +phy_chain_tx_polarity_flip_physical{228.0}=0 +phy_chain_rx_polarity_flip_physical{225.0}=0 +phy_chain_rx_polarity_flip_physical{226.0}=1 +phy_chain_rx_polarity_flip_physical{227.0}=1 +phy_chain_rx_polarity_flip_physical{228.0}=1 +phy_chain_tx_lane_map_physical{225.0}=0x3120 +phy_chain_rx_lane_map_physical{225.0}=0x3021 + +#FC 57 +portmap_111=229:100 +phy_chain_tx_polarity_flip_physical{229.0}=0 +phy_chain_tx_polarity_flip_physical{230.0}=0 +phy_chain_tx_polarity_flip_physical{231.0}=1 +phy_chain_tx_polarity_flip_physical{232.0}=0 +phy_chain_rx_polarity_flip_physical{229.0}=0 +phy_chain_rx_polarity_flip_physical{230.0}=0 +phy_chain_rx_polarity_flip_physical{231.0}=1 +phy_chain_rx_polarity_flip_physical{232.0}=1 +phy_chain_tx_lane_map_physical{229.0}=0x0231 +phy_chain_rx_lane_map_physical{229.0}=0x2031 + +#FC 58 +portmap_112=233:100 +phy_chain_tx_polarity_flip_physical{233.0}=1 +phy_chain_tx_polarity_flip_physical{234.0}=0 +phy_chain_tx_polarity_flip_physical{235.0}=0 +phy_chain_tx_polarity_flip_physical{236.0}=0 +phy_chain_rx_polarity_flip_physical{233.0}=0 +phy_chain_rx_polarity_flip_physical{234.0}=0 +phy_chain_rx_polarity_flip_physical{235.0}=1 +phy_chain_rx_polarity_flip_physical{236.0}=1 +phy_chain_tx_lane_map_physical{233.0}=0x1023 +phy_chain_rx_lane_map_physical{233.0}=0x1203 + +#FC 59 +portmap_113=237:100 +phy_chain_tx_polarity_flip_physical{237.0}=0 +phy_chain_tx_polarity_flip_physical{238.0}=0 +phy_chain_tx_polarity_flip_physical{239.0}=1 +phy_chain_tx_polarity_flip_physical{240.0}=0 +phy_chain_rx_polarity_flip_physical{237.0}=1 +phy_chain_rx_polarity_flip_physical{238.0}=0 +phy_chain_rx_polarity_flip_physical{239.0}=0 +phy_chain_rx_polarity_flip_physical{240.0}=0 +phy_chain_tx_lane_map_physical{237.0}=0x2013 +phy_chain_rx_lane_map_physical{237.0}=0x0213 + +#FC 60 +portmap_114=241:100 +phy_chain_tx_polarity_flip_physical{241.0}=0 +phy_chain_tx_polarity_flip_physical{242.0}=1 +phy_chain_tx_polarity_flip_physical{243.0}=0 +phy_chain_tx_polarity_flip_physical{244.0}=0 +phy_chain_rx_polarity_flip_physical{241.0}=0 +phy_chain_rx_polarity_flip_physical{242.0}=0 +phy_chain_rx_polarity_flip_physical{243.0}=0 +phy_chain_rx_polarity_flip_physical{244.0}=0 +phy_chain_tx_lane_map_physical{241.0}=0x1032 +phy_chain_rx_lane_map_physical{241.0}=0x2310 + +#FC 61 +portmap_115=245:100 +phy_chain_tx_polarity_flip_physical{245.0}=1 +phy_chain_tx_polarity_flip_physical{246.0}=0 +phy_chain_tx_polarity_flip_physical{247.0}=0 +phy_chain_tx_polarity_flip_physical{248.0}=1 +phy_chain_rx_polarity_flip_physical{245.0}=1 +phy_chain_rx_polarity_flip_physical{246.0}=1 +phy_chain_rx_polarity_flip_physical{247.0}=0 +phy_chain_rx_polarity_flip_physical{248.0}=1 +phy_chain_tx_lane_map_physical{245.0}=0x1302 +phy_chain_rx_lane_map_physical{245.0}=0x1302 + +#FC 62 +portmap_116=249:100 +phy_chain_tx_polarity_flip_physical{249.0}=0 +phy_chain_tx_polarity_flip_physical{250.0}=1 +phy_chain_tx_polarity_flip_physical{251.0}=0 +phy_chain_tx_polarity_flip_physical{252.0}=0 +phy_chain_rx_polarity_flip_physical{249.0}=1 +phy_chain_rx_polarity_flip_physical{250.0}=1 +phy_chain_rx_polarity_flip_physical{251.0}=0 +phy_chain_rx_polarity_flip_physical{252.0}=0 +phy_chain_tx_lane_map_physical{249.0}=0x1032 +phy_chain_rx_lane_map_physical{249.0}=0x1203 + +#FC 63 +portmap_117=253:100 +phy_chain_tx_polarity_flip_physical{253.0}=0 +phy_chain_tx_polarity_flip_physical{254.0}=0 +phy_chain_tx_polarity_flip_physical{255.0}=0 +phy_chain_tx_polarity_flip_physical{256.0}=1 +phy_chain_rx_polarity_flip_physical{253.0}=0 +phy_chain_rx_polarity_flip_physical{254.0}=1 +phy_chain_rx_polarity_flip_physical{255.0}=1 +phy_chain_rx_polarity_flip_physical{256.0}=0 +phy_chain_tx_lane_map_physical{253.0}=0x3210 +phy_chain_rx_lane_map_physical{253.0}=0x2103 + + + +#MGMT +portmap_66=257:10 +portmap_100=259:10 +#phy_chain_tx_lane_map_physical{257.0}=0x0123 +#phy_chain_rx_lane_map_physical{257.0}=0x0123 + +#LPBK +portmap_33=260:10 +portmap_67=261:10 +portmap_101=262:10 +portmap_135=263:10 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/default_sku new file mode 100644 index 000000000000..30331b0d9fc0 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9200-64X t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/fancontrol new file mode 100644 index 000000000000..489ebeaee95d --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +DEVPATH=hwmon5=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-002f hwmon2=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-7/7-004d +DEVNAME=hwmon5=w83795adg +FCTEMPS=hwmon5/device/pwm2=hwmon2/temp1_input +FCFANS=hwmon5/device/pwm2=hwmon5/device/fan7_input hwmon5/device/pwm2=hwmon5/device/fan5_input hwmon5/device/pwm2=hwmon5/device/fan3_input hwmon5/device/pwm2=hwmon5/device/fan1_input +MINTEMP=hwmon5/device/pwm2=20 +MAXTEMP=hwmon5/device/pwm2=60 +MINSTART=hwmon5/device/pwm2=75 +MINSTOP=hwmon5/device/pwm2=22 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/led_proc_init.soc b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/led_proc_init.soc new file mode 100644 index 000000000000..774923ff868d --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/led_proc_init.soc @@ -0,0 +1,111 @@ +#processor initialization for Ingrasys S9200-64X + +led 0 stop +led 0 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0F 87 22 0E 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=56 REMAP_PORT_2=57 REMAP_PORT_1=58 REMAP_PORT_0=59 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=60 REMAP_PORT_6=61 REMAP_PORT_5=62 REMAP_PORT_4=63 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=52 REMAP_PORT_10=53 REMAP_PORT_9=54 REMAP_PORT_8=55 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=48 REMAP_PORT_14=49 REMAP_PORT_13=50 REMAP_PORT_12=51 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=40 REMAP_PORT_18=41 REMAP_PORT_17=42 REMAP_PORT_16=43 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=44 REMAP_PORT_22=45 REMAP_PORT_21=46 REMAP_PORT_20=47 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 REMAP_PORT_26=37 REMAP_PORT_25=38 REMAP_PORT_24=39 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 REMAP_PORT_30=33 REMAP_PORT_29=34 REMAP_PORT_28=35 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=24 REMAP_PORT_34=25 REMAP_PORT_33=26 REMAP_PORT_32=27 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=28 REMAP_PORT_38=29 REMAP_PORT_37=30 REMAP_PORT_36=31 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=20 REMAP_PORT_42=21 REMAP_PORT_41=22 REMAP_PORT_40=23 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=16 REMAP_PORT_46=17 REMAP_PORT_45=18 REMAP_PORT_44=19 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=8 REMAP_PORT_50=9 REMAP_PORT_49=10 REMAP_PORT_48=11 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=12 REMAP_PORT_54=13 REMAP_PORT_53=14 REMAP_PORT_52=15 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 REMAP_PORT_58=5 REMAP_PORT_57=6 REMAP_PORT_56=7 +modreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 REMAP_PORT_62=1 REMAP_PORT_61=2 REMAP_PORT_60=3 + +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0F 87 22 0E 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=12 REMAP_PORT_10=13 REMAP_PORT_9=14 REMAP_PORT_8=15 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=8 REMAP_PORT_14=9 REMAP_PORT_13=10 REMAP_PORT_12=11 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 REMAP_PORT_18=17 REMAP_PORT_17=18 REMAP_PORT_16=19 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 REMAP_PORT_22=21 REMAP_PORT_21=22 REMAP_PORT_20=23 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=28 REMAP_PORT_26=29 REMAP_PORT_25=30 REMAP_PORT_24=31 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 REMAP_PORT_30=25 REMAP_PORT_29=26 REMAP_PORT_28=27 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 REMAP_PORT_34=33 REMAP_PORT_33=34 REMAP_PORT_32=35 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 REMAP_PORT_38=37 REMAP_PORT_37=38 REMAP_PORT_36=39 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=44 REMAP_PORT_42=45 REMAP_PORT_41=46 REMAP_PORT_40=47 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=40 REMAP_PORT_46=41 REMAP_PORT_45=42 REMAP_PORT_44=43 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 REMAP_PORT_50=49 REMAP_PORT_49=50 REMAP_PORT_48=51 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 REMAP_PORT_54=53 REMAP_PORT_53=54 REMAP_PORT_52=55 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=60 REMAP_PORT_58=61 REMAP_PORT_57=62 REMAP_PORT_56=63 +modreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 REMAP_PORT_62=57 REMAP_PORT_61=58 REMAP_PORT_60=59 + +led 1 auto on +led 1 start + +led 2 stop +led 2 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0F 87 22 0E 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=56 REMAP_PORT_2=57 REMAP_PORT_1=58 REMAP_PORT_0=59 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=60 REMAP_PORT_6=61 REMAP_PORT_5=62 REMAP_PORT_4=63 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=52 REMAP_PORT_10=53 REMAP_PORT_9=54 REMAP_PORT_8=55 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=48 REMAP_PORT_14=49 REMAP_PORT_13=50 REMAP_PORT_12=51 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=40 REMAP_PORT_18=41 REMAP_PORT_17=42 REMAP_PORT_16=43 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=44 REMAP_PORT_22=45 REMAP_PORT_21=46 REMAP_PORT_20=47 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36 REMAP_PORT_26=37 REMAP_PORT_25=38 REMAP_PORT_24=39 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32 REMAP_PORT_30=33 REMAP_PORT_29=34 REMAP_PORT_28=35 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=24 REMAP_PORT_34=25 REMAP_PORT_33=26 REMAP_PORT_32=27 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=28 REMAP_PORT_38=29 REMAP_PORT_37=30 REMAP_PORT_36=31 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=20 REMAP_PORT_42=21 REMAP_PORT_41=22 REMAP_PORT_40=23 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=16 REMAP_PORT_46=17 REMAP_PORT_45=18 REMAP_PORT_44=19 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=8 REMAP_PORT_50=9 REMAP_PORT_49=10 REMAP_PORT_48=11 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=12 REMAP_PORT_54=13 REMAP_PORT_53=14 REMAP_PORT_52=15 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4 REMAP_PORT_58=5 REMAP_PORT_57=6 REMAP_PORT_56=7 +modreg CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 REMAP_PORT_62=1 REMAP_PORT_61=2 REMAP_PORT_60=3 + +led 2 auto on +led 2 start + +led 3 stop +led 3 prog 12 00 61 F1 12 10 61 F2 12 04 61 F3 12 04 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0F 87 22 0E 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 REMAP_PORT_2=1 REMAP_PORT_1=2 REMAP_PORT_0=3 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 REMAP_PORT_6=5 REMAP_PORT_5=6 REMAP_PORT_4=7 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=12 REMAP_PORT_10=13 REMAP_PORT_9=14 REMAP_PORT_8=15 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=8 REMAP_PORT_14=9 REMAP_PORT_13=10 REMAP_PORT_12=11 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 REMAP_PORT_18=17 REMAP_PORT_17=18 REMAP_PORT_16=19 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 REMAP_PORT_22=21 REMAP_PORT_21=22 REMAP_PORT_20=23 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=28 REMAP_PORT_26=29 REMAP_PORT_25=30 REMAP_PORT_24=31 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 REMAP_PORT_30=25 REMAP_PORT_29=26 REMAP_PORT_28=27 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 REMAP_PORT_34=33 REMAP_PORT_33=34 REMAP_PORT_32=35 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 REMAP_PORT_38=37 REMAP_PORT_37=38 REMAP_PORT_36=39 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=44 REMAP_PORT_42=45 REMAP_PORT_41=46 REMAP_PORT_40=47 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=40 REMAP_PORT_46=41 REMAP_PORT_45=42 REMAP_PORT_44=43 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 REMAP_PORT_50=49 REMAP_PORT_49=50 REMAP_PORT_48=51 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 REMAP_PORT_54=53 REMAP_PORT_53=54 REMAP_PORT_52=55 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=60 REMAP_PORT_58=61 REMAP_PORT_57=62 REMAP_PORT_56=63 +modreg CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 REMAP_PORT_62=57 REMAP_PORT_61=58 REMAP_PORT_60=59 + +led 3 auto on +led 3 start + +led 4 stop +led 4 prog 12 00 61 F1 12 40 61 F2 12 01 61 F3 12 01 61 F4 67 16 86 F0 77 74 96 F2 2E F1 67 2B 67 3F 16 F3 FE F1 61 F1 12 00 DE F2 74 16 57 2E F1 32 00 32 01 B7 97 75 3A 02 01 60 FE 57 02 00 60 FE 57 2E F1 32 08 97 75 58 77 48 06 FE D2 01 70 50 77 66 06 F0 C2 08 74 58 77 66 16 F4 91 22 0E 87 22 0E 87 DA 00 74 5A 57 16 F4 91 22 0F 87 22 0E 87 DA 00 74 68 57 02 80 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=62 REMAP_PORT_2=0 REMAP_PORT_1=63 REMAP_PORT_0=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=0 REMAP_PORT_6=0 REMAP_PORT_5=0 REMAP_PORT_4=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=0 REMAP_PORT_10=0 REMAP_PORT_9=0 REMAP_PORT_8=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=0 REMAP_PORT_14=0 REMAP_PORT_13=0 REMAP_PORT_12=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=0 REMAP_PORT_18=0 REMAP_PORT_17=0 REMAP_PORT_16=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=0 REMAP_PORT_22=0 REMAP_PORT_21=0 REMAP_PORT_20=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=0 REMAP_PORT_26=0 REMAP_PORT_25=0 REMAP_PORT_24=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 REMAP_PORT_30=0 REMAP_PORT_29=0 REMAP_PORT_28=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=0 REMAP_PORT_34=0 REMAP_PORT_33=0 REMAP_PORT_32=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=0 REMAP_PORT_38=0 REMAP_PORT_37=0 REMAP_PORT_36=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=0 REMAP_PORT_42=0 REMAP_PORT_41=0 REMAP_PORT_40=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=0 REMAP_PORT_46=0 REMAP_PORT_45=0 REMAP_PORT_44=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=0 REMAP_PORT_50=0 REMAP_PORT_49=0 REMAP_PORT_48=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0 REMAP_PORT_54=0 REMAP_PORT_53=0 REMAP_PORT_52=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=0 REMAP_PORT_58=0 REMAP_PORT_57=0 REMAP_PORT_56=0 +modreg CMIC_LEDUP4_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0 REMAP_PORT_62=0 REMAP_PORT_61=0 REMAP_PORT_60=0 + +led 4 auto on +led 4 start diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..034c592c411e --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +############################################################################# +# Ingrasys S9200-64X +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + i2c_bus = "0" + i2c_addr = "0051" + self.eeprom_path = "/sys/class/i2c-adapter/i2c-" + i2c_bus + "/" + i2c_bus + "-" + i2c_addr + "/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..b2cdb9dca023 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/psuutil.py @@ -0,0 +1,91 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-18/18-0050", + "/sys/bus/i2c/devices/i2c-17/17-0050"] + + 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 ", attr_path, " file !") + + 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_pg' + 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_abs' + 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 == 0): + status = 1 + + return status diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..1066c78ba826 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/plugins/sfputil.py @@ -0,0 +1,267 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 63 + PORTS_IN_BLOCK = 64 + + EEPROM_OFFSET = 29 + + _port_to_eeprom_mapping = {} + + _logic_to_phy_port_mapping = { + 0: 0, + 1: 1, + 2: 4, + 3: 5, + 4: 8, + 5: 9, + 6: 12, + 7: 13, + 8: 16, + 9: 17, + 10: 20, + 11: 21, + 12: 24, + 13: 25, + 14: 28, + 15: 29, + 16: 32, + 17: 33, + 18: 36, + 19: 37, + 20: 40, + 21: 41, + 22: 44, + 23: 45, + 24: 48, + 25: 49, + 26: 52, + 27: 53, + 28: 56, + 29: 57, + 30: 60, + 31: 61, + 32: 2, + 33: 3, + 34: 6, + 35: 7, + 36: 10, + 37: 11, + 38: 14, + 39: 15, + 40: 18, + 41: 19, + 42: 22, + 43: 23, + 44: 26, + 45: 27, + 46: 30, + 47: 31, + 48: 34, + 49: 35, + 50: 38, + 51: 39, + 52: 42, + 53: 43, + 54: 46, + 55: 47, + 56: 50, + 57: 51, + 58: 54, + 59: 55, + 60: 58, + 61: 59, + 62: 62, + 63: 63 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + phy_port = self._logic_to_phy_port_mapping[x] + self._port_to_eeprom_mapping[x] = eeprom_path.format(phy_port + self.EEPROM_OFFSET) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + try: + reg_file = open("/sys/devices/platform/ingrasys-s9200-cpld.0/qsfp_modprs") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + try: + reg_file = open("/sys/devices/platform/ingrasys-s9200-cpld.0/qsfp_lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + try: + reg_file = open("/sys/devices/platform/ingrasys-s9200-cpld.0/qsfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = format(reg_value, 'x') + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/devices/platform/ingrasys-s9200-cpld.0/qsfp_reset" + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # File content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + content = format(reg_value, 'x') + + reg_file.seek(0) + reg_file.write(content) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + content = format(reg_value, 'x') + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + 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 diff --git a/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/sensors.conf new file mode 100644 index 000000000000..25ab494e1f87 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9200_64x-r0/sensors.conf @@ -0,0 +1,80 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +chip "w83795adg-*" + ignore in0 + label in1 "P0V9" + set in1_min 0.84 * 0.97 + set in1_max 0.96 * 1.03 + ignore in2 + label in3 "P1V8" + set in3_min 1.8 * 0.97 + set in3_max 1.8 * 1.03 + label in4 "P1V0" + set in4_min 1.0 * 0.97 + set in4_max 1.0 * 1.03 + label in5 "P0V8" + set in5_min 0.831 * 0.97 + set in5_max 0.831 * 1.03 + ignore in6 + ignore in7 + ignore in8 + ignore in9 + ignore in10 + ignore in11 + ignore in12 + ignore in13 + ignore in14 + ignore in15 + ignore in16 + ignore in17 + ignore in18 + ignore in19 + label fan1 "FANTRAY 1" + ignore fan2 + label fan3 "FANTRAY 2" + ignore fan4 + label fan5 "FANTRAY 3" + ignore fan6 + label fan7 "FANTRAY 4" + ignore fan8 + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 + +chip "tmp75-i2c-*-4A" + label temp1 "BMC Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +chip "tmp75-i2c-*-4F" + label temp1 "x86 CPU Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-6" "i2c-0-mux (chan_id 5)" +chip "lm75-i2c-6-4E" + label temp1 "MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +chip "lm75-i2c-6-4D" + label temp1 "REAR MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-7" "i2c-0-mux (chan_id 6)" +chip "lm75-i2c-7-4D" + label temp1 "Front MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers.json.j2 b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers.json.j2 new file mode 100644 index 000000000000..9354b7ec5b59 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t0.j2 b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..82194b2c3188 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t0.j2 @@ -0,0 +1,69 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx*4)) %}{%- 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]", + "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" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t1.j2 b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..82194b2c3188 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/buffers_defaults_t1.j2 @@ -0,0 +1,69 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20971328' %} +{% set ingress_lossy_pool_size = '20971328' %} +{% set egress_lossless_pool_size = '20971328' %} +{% set egress_lossy_pool_size = '20971328' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0, 64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx*4)) %}{%- 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]", + "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" + } + }, +{%- endmacro %} + +{# the typo of generate_pg_profils dued to buffers_config.j2 #} +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + } +{%- endmacro %} + +{# Default, we do not bind any buffer profiles. #} +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + } +{%- endmacro %} \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/pg_profile_lookup.ini b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/pg_profile_lookup.ini new file mode 100644 index 000000000000..d98b0eca6d19 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/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/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.ini new file mode 100644 index 000000000000..d57c1f350186 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index +Ethernet0 0,1,2,3 Ethernet1/1 0 +Ethernet4 4,5,6,7 Ethernet2/1 1 +Ethernet8 20,21,22,23 Ethernet3/1 2 +Ethernet12 16,17,18,19 Ethernet4/1 3 +Ethernet16 36,37,38,39 Ethernet5/1 4 +Ethernet20 32,33,34,35 Ethernet6/1 5 +Ethernet24 52,53,54,55 Ethernet7/1 6 +Ethernet28 48,49,50,51 Ethernet8/1 7 +Ethernet32 68,69,70,71 Ethernet9/1 8 +Ethernet36 64,65,66,67 Ethernet10/1 9 +Ethernet40 84,85,86,87 Ethernet11/1 10 +Ethernet44 80,81,82,83 Ethernet12/1 11 +Ethernet48 100,101,102,103 Ethernet13/1 12 +Ethernet52 96,97,98,99 Ethernet14/1 13 +Ethernet56 116,117,118,119 Ethernet15/1 14 +Ethernet60 112,113,114,115 Ethernet16/1 15 +Ethernet64 132,133,134,135 Ethernet17/1 16 +Ethernet68 128,129,130,131 Ethernet18/1 17 +Ethernet72 148,149,150,151 Ethernet19/1 18 +Ethernet76 144,145,146,147 Ethernet20/1 19 +Ethernet80 164,165,166,167 Ethernet21/1 20 +Ethernet84 160,161,162,163 Ethernet22/1 21 +Ethernet88 180,181,182,183 Ethernet23/1 22 +Ethernet92 176,177,178,179 Ethernet24/1 23 +Ethernet96 196,197,198,199 Ethernet25/1 24 +Ethernet100 192,193,194,195 Ethernet26/1 25 +Ethernet104 212,213,214,215 Ethernet27/1 26 +Ethernet108 208,209,210,211 Ethernet28/1 27 +Ethernet112 228,229,230,231 Ethernet29/1 28 +Ethernet116 224,225,226,227 Ethernet30/1 29 +Ethernet120 244,245,246,247 Ethernet31/1 30 +Ethernet124 240,241,242,243 Ethernet32/1 31 +Ethernet128 12,13,14,15 Ethernet33/1 32 +Ethernet132 8,9,10,11 Ethernet34/1 33 +Ethernet136 28,29,30,31 Ethernet35/1 34 +Ethernet140 24,25,26,27 Ethernet36/1 35 +Ethernet144 44,45,46,47 Ethernet37/1 36 +Ethernet148 40,41,42,43 Ethernet38/1 37 +Ethernet152 60,61,62,63 Ethernet39/1 38 +Ethernet156 56,57,58,59 Ethernet40/1 39 +Ethernet160 76,77,78,79 Ethernet41/1 40 +Ethernet164 72,73,74,75 Ethernet42/1 41 +Ethernet168 92,93,94,95 Ethernet43/1 42 +Ethernet172 88,89,90,91 Ethernet44/1 43 +Ethernet176 108,109,110,111 Ethernet45/1 44 +Ethernet180 104,105,106,107 Ethernet46/1 45 +Ethernet184 124,125,126,127 Ethernet47/1 46 +Ethernet188 120,121,122,123 Ethernet48/1 47 +Ethernet192 140,141,142,143 Ethernet49/1 48 +Ethernet196 136,137,138,139 Ethernet50/1 49 +Ethernet200 156,157,158,159 Ethernet51/1 50 +Ethernet204 152,153,154,155 Ethernet52/1 51 +Ethernet208 172,173,174,175 Ethernet53/1 52 +Ethernet212 168,169,170,171 Ethernet54/1 53 +Ethernet216 188,189,190,191 Ethernet55/1 54 +Ethernet220 184,185,186,187 Ethernet56/1 55 +Ethernet224 204,205,206,207 Ethernet57/1 56 +Ethernet228 200,201,202,203 Ethernet58/1 57 +Ethernet232 220,221,222,223 Ethernet59/1 58 +Ethernet236 216,217,218,219 Ethernet60/1 59 +Ethernet240 236,237,238,239 Ethernet61/1 60 +Ethernet244 232,233,234,235 Ethernet62/1 61 +Ethernet248 248,249,250,251 Ethernet63/1 62 +Ethernet252 252,253,254,255 Ethernet64/1 63 \ No newline at end of file diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.nps b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.nps new file mode 100644 index 000000000000..4f89209537f8 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/port_config.nps @@ -0,0 +1,682 @@ +init start stage low-level +init set port-map port=0 eth-macro=0 lane=0 max-speed=100g active=true +init set port-map port=1 eth-macro=1 lane=0 max-speed=100g active=true +init set port-map port=2 eth-macro=5 lane=0 max-speed=100g active=true +init set port-map port=3 eth-macro=4 lane=0 max-speed=100g active=true +init set port-map port=4 eth-macro=9 lane=0 max-speed=100g active=true +init set port-map port=5 eth-macro=8 lane=0 max-speed=100g active=true +init set port-map port=6 eth-macro=13 lane=0 max-speed=100g active=true +init set port-map port=7 eth-macro=12 lane=0 max-speed=100g active=true +init set port-map port=8 eth-macro=17 lane=0 max-speed=100g active=true +init set port-map port=9 eth-macro=16 lane=0 max-speed=100g active=true +init set port-map port=10 eth-macro=21 lane=0 max-speed=100g active=true +init set port-map port=11 eth-macro=20 lane=0 max-speed=100g active=true +init set port-map port=12 eth-macro=25 lane=0 max-speed=100g active=true +init set port-map port=13 eth-macro=24 lane=0 max-speed=100g active=true +init set port-map port=14 eth-macro=29 lane=0 max-speed=100g active=true +init set port-map port=15 eth-macro=28 lane=0 max-speed=100g active=true +init set port-map port=16 eth-macro=33 lane=0 max-speed=100g active=true +init set port-map port=17 eth-macro=32 lane=0 max-speed=100g active=true +init set port-map port=18 eth-macro=37 lane=0 max-speed=100g active=true +init set port-map port=19 eth-macro=36 lane=0 max-speed=100g active=true +init set port-map port=20 eth-macro=41 lane=0 max-speed=100g active=true +init set port-map port=21 eth-macro=40 lane=0 max-speed=100g active=true +init set port-map port=22 eth-macro=45 lane=0 max-speed=100g active=true +init set port-map port=23 eth-macro=44 lane=0 max-speed=100g active=true +init set port-map port=24 eth-macro=49 lane=0 max-speed=100g active=true +init set port-map port=25 eth-macro=48 lane=0 max-speed=100g active=true +init set port-map port=26 eth-macro=53 lane=0 max-speed=100g active=true +init set port-map port=27 eth-macro=52 lane=0 max-speed=100g active=true +init set port-map port=28 eth-macro=57 lane=0 max-speed=100g active=true +init set port-map port=29 eth-macro=56 lane=0 max-speed=100g active=true +init set port-map port=30 eth-macro=61 lane=0 max-speed=100g active=true +init set port-map port=31 eth-macro=60 lane=0 max-speed=100g active=true +init set port-map port=32 eth-macro=3 lane=0 max-speed=100g active=true +init set port-map port=33 eth-macro=2 lane=0 max-speed=100g active=true +init set port-map port=34 eth-macro=7 lane=0 max-speed=100g active=true +init set port-map port=35 eth-macro=6 lane=0 max-speed=100g active=true +init set port-map port=36 eth-macro=11 lane=0 max-speed=100g active=true +init set port-map port=37 eth-macro=10 lane=0 max-speed=100g active=true +init set port-map port=38 eth-macro=15 lane=0 max-speed=100g active=true +init set port-map port=39 eth-macro=14 lane=0 max-speed=100g active=true +init set port-map port=40 eth-macro=19 lane=0 max-speed=100g active=true +init set port-map port=41 eth-macro=18 lane=0 max-speed=100g active=true +init set port-map port=42 eth-macro=23 lane=0 max-speed=100g active=true +init set port-map port=43 eth-macro=22 lane=0 max-speed=100g active=true +init set port-map port=44 eth-macro=27 lane=0 max-speed=100g active=true +init set port-map port=45 eth-macro=26 lane=0 max-speed=100g active=true +init set port-map port=46 eth-macro=31 lane=0 max-speed=100g active=true +init set port-map port=47 eth-macro=30 lane=0 max-speed=100g active=true +init set port-map port=48 eth-macro=35 lane=0 max-speed=100g active=true +init set port-map port=49 eth-macro=34 lane=0 max-speed=100g active=true +init set port-map port=50 eth-macro=39 lane=0 max-speed=100g active=true +init set port-map port=51 eth-macro=38 lane=0 max-speed=100g active=true +init set port-map port=52 eth-macro=43 lane=0 max-speed=100g active=true +init set port-map port=53 eth-macro=42 lane=0 max-speed=100g active=true +init set port-map port=54 eth-macro=47 lane=0 max-speed=100g active=true +init set port-map port=55 eth-macro=46 lane=0 max-speed=100g active=true +init set port-map port=56 eth-macro=51 lane=0 max-speed=100g active=true +init set port-map port=57 eth-macro=50 lane=0 max-speed=100g active=true +init set port-map port=58 eth-macro=55 lane=0 max-speed=100g active=true +init set port-map port=59 eth-macro=54 lane=0 max-speed=100g active=true +init set port-map port=60 eth-macro=59 lane=0 max-speed=100g active=true +init set port-map port=61 eth-macro=58 lane=0 max-speed=100g active=true +init set port-map port=62 eth-macro=62 lane=0 max-speed=100g active=true +init set port-map port=63 eth-macro=63 lane=0 max-speed=100g active=true +init set port-map port=129 eth-macro=0 lane=1 max-speed=10g active=true guarantee=true cpi=true +init set port-map port=130 eth-macro=0 lane=0 max-speed=10g active=true guarantee=true cpi=true init-done=true + +init start stage task-rsrc +init start stage module +init start stage task + +phy set lane-swap portlist=0 lane-cnt=4 property=tx data=0x3.2.0.1 +phy set lane-swap portlist=1 lane-cnt=4 property=tx data=0x2.1.3.0 +phy set lane-swap portlist=2 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=3 lane-cnt=4 property=tx data=0x2.3.0.1 +phy set lane-swap portlist=4 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=5 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=6 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=7 lane-cnt=4 property=tx data=0x1.0.2.3 +phy set lane-swap portlist=8 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=9 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=10 lane-cnt=4 property=tx data=0x0.3.2.1 +phy set lane-swap portlist=11 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=12 lane-cnt=4 property=tx data=0x3.2.0.1 +phy set lane-swap portlist=13 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=14 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=15 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=16 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=17 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=18 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=19 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=20 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=21 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=22 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=23 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=24 lane-cnt=4 property=tx data=0x0.3.2.1 +phy set lane-swap portlist=25 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=26 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=27 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=28 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=29 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=30 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=31 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=32 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=33 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=34 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=35 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=36 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=37 lane-cnt=4 property=tx data=0x3.1.0.2 +phy set lane-swap portlist=38 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=39 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=40 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=41 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=42 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=43 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=44 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=45 lane-cnt=4 property=tx data=0x3.2.1.0 +phy set lane-swap portlist=46 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=47 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=48 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=49 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=50 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=51 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=52 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=53 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=54 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=55 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=56 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=57 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=58 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=59 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=60 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=61 lane-cnt=4 property=tx data=0x0.1.2.3 +phy set lane-swap portlist=62 lane-cnt=4 property=tx data=0x1.0.2.3 +phy set lane-swap portlist=63 lane-cnt=4 property=tx data=0x3.1.0.2 +phy set lane-swap portlist=129 lane-cnt=1 property=tx data=0x1 +phy set lane-swap portlist=130 lane-cnt=1 property=tx data=0x0 +phy set lane-swap portlist=0 lane-cnt=4 property=rx data=0x2.0.3.1 +phy set lane-swap portlist=1 lane-cnt=4 property=rx data=0x1.3.0.2 +phy set lane-swap portlist=2 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=3 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=4 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=5 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=6 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=7 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=8 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=9 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=10 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=11 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=12 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=13 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=14 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=15 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=16 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=17 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=18 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=19 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=20 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=21 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=22 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=23 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=24 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=25 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=26 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=27 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=28 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=29 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=30 lane-cnt=4 property=rx data=0x0.2.1.3 +phy set lane-swap portlist=31 lane-cnt=4 property=rx data=0x0.2.1.3 +phy set lane-swap portlist=32 lane-cnt=4 property=rx data=0x0.2.1.3 +phy set lane-swap portlist=33 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=34 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=35 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=36 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=37 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=38 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=39 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=40 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=41 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=42 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=43 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=44 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=45 lane-cnt=4 property=rx data=0x3.2.1.0 +phy set lane-swap portlist=46 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=47 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=48 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=49 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=50 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=51 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=52 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=53 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=54 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=55 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=56 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=57 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=58 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=59 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=60 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=61 lane-cnt=4 property=rx data=0x0.1.2.3 +phy set lane-swap portlist=62 lane-cnt=4 property=rx data=0x1.3.0.2 +phy set lane-swap portlist=63 lane-cnt=4 property=rx data=0x3.1.2.0 +phy set lane-swap portlist=129 lane-cnt=1 property=rx data=0x1 +phy set lane-swap portlist=130 lane-cnt=1 property=rx data=0x0 + +phy set polarity-rev portlist=0 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=1 lane-cnt=4 property=tx data=0x0.1.0.0 +phy set polarity-rev portlist=2 lane-cnt=4 property=tx data=0x1.0.0.1 +phy set polarity-rev portlist=3 lane-cnt=4 property=tx data=0x1.1.1.1 +phy set polarity-rev portlist=4 lane-cnt=4 property=tx data=0x0.1.0.1 +phy set polarity-rev portlist=5 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=6 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=7 lane-cnt=4 property=tx data=0x1.0.0.0 +phy set polarity-rev portlist=8 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=9 lane-cnt=4 property=tx data=0x0.1.0.0 +phy set polarity-rev portlist=10 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=11 lane-cnt=4 property=tx data=0x0.1.0.0 +phy set polarity-rev portlist=12 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=13 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=14 lane-cnt=4 property=tx data=0x1.0.0.0 +phy set polarity-rev portlist=15 lane-cnt=4 property=tx data=0x0.1.0.0 +phy set polarity-rev portlist=16 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=17 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=18 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=19 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=20 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=21 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=22 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=23 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=24 lane-cnt=4 property=tx data=0x0.0.1.0 +phy set polarity-rev portlist=25 lane-cnt=4 property=tx data=0x1.0.0.1 +phy set polarity-rev portlist=26 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=27 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=28 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=29 lane-cnt=4 property=tx data=0x0.1.0.0 +phy set polarity-rev portlist=30 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=31 lane-cnt=4 property=tx data=0x0.0.1.0 +phy set polarity-rev portlist=32 lane-cnt=4 property=tx data=0x0.1.1.1 +phy set polarity-rev portlist=33 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=34 lane-cnt=4 property=tx data=0x0.1.1.1 +phy set polarity-rev portlist=35 lane-cnt=4 property=tx data=0x1.0.0.0 +phy set polarity-rev portlist=36 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=37 lane-cnt=4 property=tx data=0x0.0.0.1 +phy set polarity-rev portlist=38 lane-cnt=4 property=tx data=0x0.1.1.0 +phy set polarity-rev portlist=39 lane-cnt=4 property=tx data=0x1.0.1.0 +phy set polarity-rev portlist=40 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=41 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=42 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=43 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=44 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=45 lane-cnt=4 property=tx data=0x0.0.1.0 +phy set polarity-rev portlist=46 lane-cnt=4 property=tx data=0x0.0.0.1 +phy set polarity-rev portlist=47 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=48 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=49 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=50 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=51 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=52 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=53 lane-cnt=4 property=tx data=0x0.0.1.0 +phy set polarity-rev portlist=54 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=55 lane-cnt=4 property=tx data=0x0.0.1.1 +phy set polarity-rev portlist=56 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=57 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=58 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=59 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=60 lane-cnt=4 property=tx data=0x0.1.0.1 +phy set polarity-rev portlist=61 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=62 lane-cnt=4 property=tx data=0x0.0.0.0 +phy set polarity-rev portlist=63 lane-cnt=4 property=tx data=0x0.0.1.0 +phy set polarity-rev portlist=129 lane-cnt=1 property=tx data=0x0 +phy set polarity-rev portlist=130 lane-cnt=1 property=tx data=0x0 + +phy set polarity-rev portlist=0 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=1 lane-cnt=4 property=rx data=0x1.0.0.0 +phy set polarity-rev portlist=2 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=3 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=4 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=5 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=6 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=7 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=8 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=9 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=10 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=11 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=12 lane-cnt=4 property=rx data=0x1.0.0.0 +phy set polarity-rev portlist=13 lane-cnt=4 property=rx data=0x0.0.1.0 +phy set polarity-rev portlist=14 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=15 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=16 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=17 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=18 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=19 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=20 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=21 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=22 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=23 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=24 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=25 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=26 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=27 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=28 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=29 lane-cnt=4 property=rx data=0x1.0.1.0 +phy set polarity-rev portlist=30 lane-cnt=4 property=rx data=0x0.0.1.0 +phy set polarity-rev portlist=31 lane-cnt=4 property=rx data=0x1.1.0.0 +phy set polarity-rev portlist=32 lane-cnt=4 property=rx data=0x0.1.1.1 +phy set polarity-rev portlist=33 lane-cnt=4 property=rx data=0x1.1.1.0 +phy set polarity-rev portlist=34 lane-cnt=4 property=rx data=0x0.0.1.1 +phy set polarity-rev portlist=35 lane-cnt=4 property=rx data=0x0.0.1.0 +phy set polarity-rev portlist=36 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=37 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=38 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=39 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=40 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=41 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=42 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=43 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=44 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=45 lane-cnt=4 property=rx data=0x0.1.0.1 +phy set polarity-rev portlist=46 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=47 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=48 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=49 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=50 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=51 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=52 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=53 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=54 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=55 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=56 lane-cnt=4 property=rx data=0x0.1.0.0 +phy set polarity-rev portlist=57 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=58 lane-cnt=4 property=rx data=0x0.1.0.0 +phy set polarity-rev portlist=59 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=60 lane-cnt=4 property=rx data=0x0.0.0.1 +phy set polarity-rev portlist=61 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=62 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=63 lane-cnt=4 property=rx data=0x0.0.0.0 +phy set polarity-rev portlist=129 lane-cnt=1 property=rx data=0x0 +phy set polarity-rev portlist=130 lane-cnt=1 property=rx data=0x0 + +phy set pre-emphasis portlist=0 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=0 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=0 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=0 lane-cnt=4 property=c0 data=0x19.19.18.19 +phy set pre-emphasis portlist=1 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=1 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=1 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=1 lane-cnt=4 property=c0 data=0x19.18.19.19 +phy set pre-emphasis portlist=2 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=2 lane-cnt=4 property=c1 data=0x08.08.09.09 +phy set pre-emphasis portlist=2 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=2 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=3 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=3 lane-cnt=4 property=c1 data=0x08.08.09.08 +phy set pre-emphasis portlist=3 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=3 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c1 data=0x06.07.07.08 +phy set pre-emphasis portlist=4 lane-cnt=4 property=cn1 data=0x03.02.02.02 +phy set pre-emphasis portlist=4 lane-cnt=4 property=c0 data=0x19.19.18.19 +phy set pre-emphasis portlist=5 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=5 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=5 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=5 lane-cnt=4 property=c0 data=0x19.19.18.18 +phy set pre-emphasis portlist=6 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=6 lane-cnt=4 property=c1 data=0x06.06.06.07 +phy set pre-emphasis portlist=6 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=6 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=7 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=7 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=7 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=7 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=8 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=8 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=9 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=9 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=9 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=9 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=10 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=10 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=10 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=10 lane-cnt=4 property=c0 data=0x16.17.17.17 +phy set pre-emphasis portlist=11 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=11 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=11 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=11 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=12 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=12 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=13 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=13 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=13 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=13 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=14 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=14 lane-cnt=4 property=c1 data=0x04.05.04.05 +phy set pre-emphasis portlist=14 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=14 lane-cnt=4 property=c0 data=0x18.17.18.17 +phy set pre-emphasis portlist=15 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=15 lane-cnt=4 property=c1 data=0x06.05.06.06 +phy set pre-emphasis portlist=15 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=15 lane-cnt=4 property=c0 data=0x16.17.16.16 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c1 data=0x05.06.06.06 +phy set pre-emphasis portlist=16 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=16 lane-cnt=4 property=c0 data=0x17.18.18.16 +phy set pre-emphasis portlist=17 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=17 lane-cnt=4 property=c1 data=0x04.04.04.04 +phy set pre-emphasis portlist=17 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=17 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=18 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=18 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=18 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=18 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=19 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=19 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=19 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=19 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=20 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=20 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=21 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=21 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=21 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=21 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=22 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=22 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=22 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=22 lane-cnt=4 property=c0 data=0x17.17.18.17 +phy set pre-emphasis portlist=23 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=23 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=23 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=23 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=24 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=24 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=25 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=25 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=25 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=25 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=26 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=26 lane-cnt=4 property=c1 data=0x08.08.07.07 +phy set pre-emphasis portlist=26 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=26 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=27 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=27 lane-cnt=4 property=c1 data=0x08.08.08.08 +phy set pre-emphasis portlist=27 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=27 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=28 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=28 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=29 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=29 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=29 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=29 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=30 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=30 lane-cnt=4 property=c1 data=0x08.09.09.09 +phy set pre-emphasis portlist=30 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=30 lane-cnt=4 property=c0 data=0x18.19.19.19 +phy set pre-emphasis portlist=31 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=31 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=31 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=31 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=32 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=32 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=33 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=33 lane-cnt=4 property=c1 data=0x08.09.09.09 +phy set pre-emphasis portlist=33 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=33 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=34 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=34 lane-cnt=4 property=c1 data=0x08.07.08.08 +phy set pre-emphasis portlist=34 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=34 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=35 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=35 lane-cnt=4 property=c1 data=0x08.08.07.08 +phy set pre-emphasis portlist=35 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=35 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=36 lane-cnt=4 property=cn1 data=0x01.02.02.02 +phy set pre-emphasis portlist=36 lane-cnt=4 property=c0 data=0x19.18.18.18 +phy set pre-emphasis portlist=37 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=37 lane-cnt=4 property=c1 data=0x06.06.06.07 +phy set pre-emphasis portlist=37 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=37 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=38 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=38 lane-cnt=4 property=c1 data=0x06.06.05.06 +phy set pre-emphasis portlist=38 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=38 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=39 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=39 lane-cnt=4 property=c1 data=0x06.07.06.06 +phy set pre-emphasis portlist=39 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=39 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=40 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=40 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=41 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=41 lane-cnt=4 property=c1 data=0x05.06.05.05 +phy set pre-emphasis portlist=41 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=41 lane-cnt=4 property=c0 data=0x16.17.18.18 +phy set pre-emphasis portlist=42 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=42 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=42 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=42 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=43 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=43 lane-cnt=4 property=c1 data=0x06.05.05.05 +phy set pre-emphasis portlist=43 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=43 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=44 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=44 lane-cnt=4 property=c0 data=0x17.17.17.17 +phy set pre-emphasis portlist=45 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=45 lane-cnt=4 property=c1 data=0x05.05.04.05 +phy set pre-emphasis portlist=45 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=45 lane-cnt=4 property=c0 data=0x17.17.18.17 +phy set pre-emphasis portlist=46 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=46 lane-cnt=4 property=c1 data=0x05.05.06.06 +phy set pre-emphasis portlist=46 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=46 lane-cnt=4 property=c0 data=0x17.17.16.16 +phy set pre-emphasis portlist=47 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=47 lane-cnt=4 property=c1 data=0x05.05.06.06 +phy set pre-emphasis portlist=47 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=47 lane-cnt=4 property=c0 data=0x17.17.16.16 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=48 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=48 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=49 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=49 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=50 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=50 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c1 data=0x05.05.05.05 +phy set pre-emphasis portlist=51 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=51 lane-cnt=4 property=c0 data=0x16.16.16.16 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c1 data=0x06.06.05.05 +phy set pre-emphasis portlist=52 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=52 lane-cnt=4 property=c0 data=0x16.17.17.17 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=53 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=53 lane-cnt=4 property=c0 data=0x16.17.17.17 +phy set pre-emphasis portlist=54 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=54 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=54 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=54 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=55 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=55 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis portlist=55 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=55 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=56 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=56 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=56 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=56 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=57 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=57 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis portlist=57 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=57 lane-cnt=4 property=c0 data=0x18.18.18.18 +phy set pre-emphasis portlist=58 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=58 lane-cnt=4 property=c1 data=0x08.08.08.08 +phy set pre-emphasis portlist=58 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=58 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=59 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=59 lane-cnt=4 property=c1 data=0x08.08.08.08 +phy set pre-emphasis portlist=59 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=59 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=60 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=60 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=60 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=60 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=61 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=61 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=61 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=61 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=62 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=62 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=62 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=62 lane-cnt=4 property=c0 data=0x19.19.19.19 +phy set pre-emphasis portlist=63 lane-cnt=4 property=c2 data=0x00.00.00.00 +phy set pre-emphasis portlist=63 lane-cnt=4 property=c1 data=0x09.09.09.09 +phy set pre-emphasis portlist=63 lane-cnt=4 property=cn1 data=0x02.02.02.02 +phy set pre-emphasis portlist=63 lane-cnt=4 property=c0 data=0x19.19.19.19 + +phy set pre-emphasis portlist=129 lane-cnt=1 property=c2 data=0x01 +phy set pre-emphasis portlist=129 lane-cnt=1 property=cn1 data=0x01 +phy set pre-emphasis portlist=129 lane-cnt=1 property=c0 data=0x02 +phy set pre-emphasis portlist=129 lane-cnt=1 property=c1 data=0x03 +phy set pre-emphasis portlist=130 lane-cnt=1 property=c2 data=0x01 +phy set pre-emphasis portlist=130 lane-cnt=1 property=cn1 data=0x01 +phy set pre-emphasis portlist=130 lane-cnt=1 property=c0 data=0x02 +phy set pre-emphasis portlist=130 lane-cnt=1 property=c1 data=0x03 + +phy set mdio portlist=0 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=1 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=2 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=3 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=4 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=5 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=6 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=7 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=8 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=9 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=10 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=11 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=12 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=13 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=14 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=15 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=16 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=17 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=18 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=19 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=20 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=21 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=22 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=23 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=24 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=25 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=26 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=27 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=28 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=29 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=30 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=31 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=32 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=33 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=34 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=35 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=36 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=37 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=38 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=39 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=40 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=41 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=42 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=43 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=44 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=45 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=46 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=47 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=48 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=49 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=50 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=51 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=52 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=53 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=54 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=55 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=56 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=57 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=58 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=59 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=60 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=61 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=62 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=63 devad=0x1E addr=0x2 data=0x8000 +phy set mdio portlist=129 devad=0x1E addr=0x2 data=0x0000 +phy set mdio portlist=130 devad=0x1E addr=0x2 data=0x0000 + +port set property portlist=0-63 speed=100g +port set property portlist=129-130 speed=10g +port set property portlist=0-63 medium-type=sr4 +port set property portlist=129-130 medium-type=kr +port set property portlist=0-63 fec=disable +port set adver portlist=129-130 speed-10g-kr +port set property portlist=129-130 an=enable + +port set property portlist=129-130 admin=enable +port set property portlist=0-63 admin=disable diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/qos.json.j2 b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/qos.json.j2 new file mode 100644 index 000000000000..42eef17c362b --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/qos.json.j2 @@ -0,0 +1,136 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "1", + "1": "0", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"1", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + }, + "WRED_PROFILE": { + "AZURE_LOSSY" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184128", + "green_min_threshold": "184128" + }, + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184128", + "green_min_threshold": "184128" + } + }, + "QUEUE": { + } +} diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/sai.profile b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/sai.profile new file mode 100644 index 000000000000..880f47910ac1 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/INGRASYS-S9230-64X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/led_proc_init.nps +SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/port_config.nps diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/default_sku new file mode 100644 index 000000000000..46ddac21550c --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9230-64X t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/fancontrol new file mode 100644 index 000000000000..86b4e636375f --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +DEVPATH=hwmon7=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-002f hwmon4=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-7/7-004e +DEVNAME=hwmon7=w83795adg +FCTEMPS=hwmon7/device/pwm2=hwmon4/temp1_input +FCFANS=hwmon7/device/pwm2=hwmon7/device/fan7_input hwmon7/device/pwm2=hwmon7/device/fan5_input hwmon7/device/pwm2=hwmon7/device/fan3_input hwmon7/device/pwm2=hwmon7/device/fan1_input +MINTEMP=hwmon7/device/pwm2=20 +MAXTEMP=hwmon7/device/pwm2=60 +MINSTART=hwmon7/device/pwm2=75 +MINSTOP=hwmon7/device/pwm2=22 diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/led_proc_init.nps b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/led_proc_init.nps new file mode 100644 index 000000000000..717d3303f172 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/led_proc_init.nps @@ -0,0 +1,9 @@ +#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 6 +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 +0 NPS_CFG_TYPE_HASH_L2_FDB_REGION_ENTRY_NUM 0 0 49152 +0 NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM 0 0 32768 diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..159e12d98f64 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Ingrasys S9230-64X +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0051/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..b2cdb9dca023 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/psuutil.py @@ -0,0 +1,91 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-18/18-0050", + "/sys/bus/i2c/devices/i2c-17/17-0050"] + + 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 ", attr_path, " file !") + + 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_pg' + 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_abs' + 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 == 0): + status = 1 + + return status diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..f3e1d49cd86b --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/plugins/sfputil.py @@ -0,0 +1,294 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 63 + PORTS_IN_BLOCK = 64 + # TODO: modify according to port map + EEPROM_OFFSET = 33 + CPLD1_PORTS = 12 + CPLDx_PORTS = 13 + CPLD_OFFSET = 1 + CPLD_PRES_BIT = 1 + CPLD_RESET_BIT = 0 + CPLD_LPMOD_BIT = 2 + CPLDx_I2C_ADDR = "33" + CPLD_PORT_STATUS_KEY = "cpld_qsfp_port_status" + CPLD_PORT_CONFIG_KEY = "cpld_qsfp_port_config" + CPLD_REG_PATH = "/sys/bus/i2c/devices/{0}-00{1}/{2}_{3}" + + _port_to_eeprom_mapping = {} + + _logic_to_phy_port_mapping = { + 0: 0, + 1: 1, + 2: 4, + 3: 5, + 4: 8, + 5: 9, + 6: 12, + 7: 13, + 8: 16, + 9: 17, + 10: 20, + 11: 21, + 12: 24, + 13: 25, + 14: 28, + 15: 29, + 16: 32, + 17: 33, + 18: 36, + 19: 37, + 20: 40, + 21: 41, + 22: 44, + 23: 45, + 24: 48, + 25: 49, + 26: 52, + 27: 53, + 28: 56, + 29: 57, + 30: 60, + 31: 61, + 32: 2, + 33: 3, + 34: 6, + 35: 7, + 36: 10, + 37: 11, + 38: 14, + 39: 15, + 40: 18, + 41: 19, + 42: 22, + 43: 23, + 44: 26, + 45: 27, + 46: 30, + 47: 31, + 48: 34, + 49: 35, + 50: 38, + 51: 39, + 52: 42, + 53: 43, + 54: 46, + 55: 47, + 56: 50, + 57: 51, + 58: 54, + 59: 55, + 60: 58, + 61: 59, + 62: 62, + 63: 63 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + for x in range(self.port_start, self.port_end + 1): + phy_port = self._logic_to_phy_port_mapping[x] + port_eeprom_path = eeprom_path.format(phy_port + self.EEPROM_OFFSET) + self.port_to_eeprom_mapping[x] = port_eeprom_path + + SfpUtilBase.__init__(self) + + def qsfp_to_cpld_index(self, port_num): + if port_num < self.CPLD1_PORTS: + cpld_id = 0 + cpld_port_index = port_num + 1 + else: + cpld_id = 1 + (port_num - self.CPLD1_PORTS) / self.CPLDx_PORTS + cpld_port_index = ((port_num - self.CPLD1_PORTS) % self.CPLDx_PORTS) + 1 + return cpld_id, cpld_port_index + + 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 + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, + self.CPLD_PORT_STATUS_KEY, cpld_port_index) + + try: + reg_file = open(reg_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_file.close() + + reg_value = int(content, 16) + # mask for presence bit (bit 1) + mask = (1 << self.CPLD_PRES_BIT) + + # 0 - presence, 1 - absence + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + try: + reg_file = open(reg_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_file.close() + + reg_value = int(content, 16) + # mask for lp_mod bit (bit 2) + mask = (1 << self.CPLD_LPMOD_BIT) + + # 0 - disable, 1 - low power mode + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + try: + reg_file = open(reg_path, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + # mask for lp_mod bit (bit 2) + mask = (1 << self.CPLD_LPMOD_BIT) + + # 1 - low power mode, 0 - high power mode + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # convert value to hex string + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self._logic_to_phy_port_mapping[port_num] + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + # reset the port + try: + reg_file = open(reg_path, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + # mask for reset bit (bit 0) + mask = (1 << self.CPLD_RESET_BIT) + + # 1 - out of reset, 0 - reset + reg_value = reg_value & ~mask + + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 1 second to reset done + time.sleep(1) + + # take the port out of reset + try: + reg_file = open(reg_path, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def get_transceiver_change_event(self, timeout=0): + raise NotImplementedError diff --git a/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/sensors.conf new file mode 100644 index 000000000000..84abfe88062b --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9230_64x-r0/sensors.conf @@ -0,0 +1,83 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + +bus "i2c-16" "i2c-mux-1 (chan_id 7)" +chip "w83795adg-*" + ignore in0 + label in1 "VDD_CORE" + set in1_min 0.90 * 0.98 + set in1_max 0.90 * 1.02 + ignore in2 + label in3 "1.8V" + set in3_min 1.8 * 0.97 + set in3_max 1.8 * 1.03 + label in4 "3.3V" + compute in4 @/(0.3052), (0.3052)*@ + set in4_min 3.3 * 0.95 + set in4_max 3.3 * 1.05 + label in5 "0.9V" + set in5_min 0.90 * 0.98 + set in5_max 0.90 * 1.02 + ignore in6 + ignore in7 + ignore in8 + ignore in9 + ignore in10 + ignore in11 + ignore in12 + ignore in13 + ignore in14 + ignore in15 + ignore in16 + ignore in17 + ignore in18 + ignore in19 + label fan1 "FANTRAY 1" + ignore fan2 + label fan3 "FANTRAY 2" + ignore fan4 + label fan5 "FANTRAY 3" + ignore fan6 + label fan7 "FANTRAY 4" + ignore fan8 + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 + +chip "tmp75-i2c-*-4A" + label temp1 "BMC Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-0" "SMBus I801 adapter at f000" +chip "tmp75-i2c-*-4F" + label temp1 "x86 CPU Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-6" "i2c-0-mux (chan_id 5)" +chip "lm75-i2c-6-4D" + label temp1 "Rear Panel Temp" + set temp1_max 50 + set temp1_max_hyst 45 +chip "lm75-i2c-6-4E" + label temp1 "Rear MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-7" "i2c-0-mux (chan_id 6)" +chip "lm75-i2c-7-4D" + label temp1 "Front Panel Temp" + set temp1_max 50 + set temp1_max_hyst 45 +chip "lm75-i2c-7-4E" + label temp1 "Front MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/port_config.ini new file mode 100644 index 000000000000..749f9f484a3d --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias speed autoneg fec index +Ethernet0 0,1,2,3 Ethernet0 100000 0 0 0 +Ethernet4 4,5,6,7 Ethernet4 100000 0 0 1 +Ethernet8 8,9,10,11 Ethernet8 100000 0 0 2 +Ethernet12 12,13,14,15 Ethernet12 100000 0 0 3 +Ethernet16 16,17,18,19 Ethernet16 100000 0 0 4 +Ethernet20 20,21,22,23 Ethernet20 100000 0 0 5 +Ethernet24 24,25,26,27 Ethernet24 100000 0 0 6 +Ethernet28 28,29,30,31 Ethernet28 100000 0 0 7 +Ethernet32 32,33,34,35 Ethernet32 100000 0 0 8 +Ethernet36 36,37,38,39 Ethernet36 100000 0 0 9 +Ethernet40 40,41,42,43 Ethernet40 100000 0 0 10 +Ethernet44 44,45,46,47 Ethernet44 100000 0 0 11 +Ethernet48 48,49,50,51 Ethernet48 100000 0 0 12 +Ethernet52 52,53,54,55 Ethernet52 100000 0 0 13 +Ethernet56 56,57,58,59 Ethernet56 100000 0 0 14 +Ethernet60 60,61,62,63 Ethernet60 100000 0 0 15 +Ethernet64 64,65,66,67 Ethernet64 100000 0 0 16 +Ethernet68 68,69,70,71 Ethernet68 100000 0 0 17 +Ethernet72 72,73,74,75 Ethernet72 100000 0 0 18 +Ethernet76 76,77,78,79 Ethernet76 100000 0 0 19 +Ethernet80 80,81,82,83 Ethernet80 100000 0 0 20 +Ethernet84 84,85,86,87 Ethernet84 100000 0 0 21 +Ethernet88 88,89,90,91 Ethernet88 100000 0 0 22 +Ethernet92 92,93,94,95 Ethernet92 100000 0 0 23 +Ethernet96 96,97,98,99 Ethernet96 100000 0 0 24 +Ethernet100 100,101,102,103 Ethernet100 100000 0 0 25 +Ethernet104 104,105,106,107 Ethernet104 100000 0 0 26 +Ethernet108 108,109,110,111 Ethernet108 100000 0 0 27 +Ethernet112 112,113,114,115 Ethernet112 100000 0 0 28 +Ethernet116 116,117,118,119 Ethernet116 100000 0 0 29 +Ethernet120 120,121,122,123 Ethernet120 100000 0 0 30 +Ethernet124 124,125,126,127 Ethernet124 100000 0 0 31 +Ethernet128 128,129,130,131 Ethernet128 100000 0 0 32 +Ethernet132 132,133,134,135 Ethernet132 100000 0 0 33 +Ethernet136 136,137,138,139 Ethernet136 100000 0 0 34 +Ethernet140 140,141,142,143 Ethernet140 100000 0 0 35 +Ethernet144 144,145,146,147 Ethernet144 100000 0 0 36 +Ethernet148 148,149,150,151 Ethernet148 100000 0 0 37 +Ethernet152 152,153,154,155 Ethernet152 100000 0 0 38 +Ethernet156 156,157,158,159 Ethernet156 100000 0 0 39 +Ethernet160 160,161,162,163 Ethernet160 100000 0 0 40 +Ethernet164 164,165,166,167 Ethernet164 100000 0 0 41 +Ethernet168 168,169,170,171 Ethernet168 100000 0 0 42 +Ethernet172 172,173,174,175 Ethernet172 100000 0 0 43 +Ethernet176 176,177,178,179 Ethernet176 100000 0 0 44 +Ethernet180 180,181,182,183 Ethernet180 100000 0 0 45 +Ethernet184 184,185,186,187 Ethernet184 100000 0 0 46 +Ethernet188 188,189,190,191 Ethernet188 100000 0 0 47 +Ethernet192 192,193,194,195 Ethernet192 100000 0 0 48 +Ethernet196 196,197,198,199 Ethernet196 100000 0 0 49 +Ethernet200 200,201,202,203 Ethernet200 100000 0 0 50 +Ethernet204 204,205,206,207 Ethernet204 100000 0 0 51 +Ethernet208 208,209,210,211 Ethernet208 100000 0 0 52 +Ethernet212 212,213,214,215 Ethernet212 100000 0 0 53 +Ethernet216 216,217,218,219 Ethernet216 100000 0 0 54 +Ethernet220 220,221,222,223 Ethernet220 100000 0 0 55 +Ethernet224 224,225,226,227 Ethernet224 100000 0 0 56 +Ethernet228 228,229,230,231 Ethernet228 100000 0 0 57 +Ethernet232 232,233,234,235 Ethernet232 100000 0 0 58 +Ethernet236 236,237,238,239 Ethernet236 100000 0 0 59 +Ethernet240 240,241,242,243 Ethernet240 100000 0 0 60 +Ethernet244 244,245,246,247 Ethernet244 100000 0 0 61 +Ethernet248 248,249,250,251 Ethernet248 100000 0 0 62 +Ethernet252 252,253,254,255 Ethernet252 100000 0 0 63 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/switch-sai.conf b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/switch-sai.conf new file mode 100644 index 000000000000..f1e9c0bc10da --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/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: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" + } + ], + "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", + "agent0": "lib/platform/x86_64-ingrasys_s9280_64x-r0/libpltfm_mgr.so", + "switchapi_port_add": false + } + ] +} diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/switch-tna-sai.conf b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/switch-tna-sai.conf new file mode 100644 index 000000000000..4895ac901ff6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/INGRASYS-S9280-64X/switch-tna-sai.conf @@ -0,0 +1,40 @@ +{ + "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, + "agent0": "lib/platform/x86_64-ingrasys_s9280_64x-r0/libpltfm_mgr.so", + "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/ingrasys/x86_64-ingrasys_s9280_64x-r0/default_sku b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/default_sku new file mode 100644 index 000000000000..68e0c87eb0a3 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/default_sku @@ -0,0 +1 @@ +INGRASYS-S9280-64X t1 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/fancontrol new file mode 100644 index 000000000000..427cc6561c50 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-16/16-002f hwmon3=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-6/6-004c +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon3/temp1_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm2=hwmon1/device/fan3_input hwmon1/device/pwm2=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm2=20 +MAXTEMP=hwmon1/device/pwm2=60 +MINSTART=hwmon1/device/pwm2=75 +MINSTOP=hwmon1/device/pwm2=22 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..3fc614fc2632 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Ingrasys S9280-64X +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0051/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..8c7d5cfa4174 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/psuutil.py @@ -0,0 +1,92 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + # TODO: need to check if the patch mapping correct + SYSFS_PSU_DIR = ["/sys/bus/i2c/devices/i2c-18/18-0050", + "/sys/bus/i2c/devices/i2c-17/17-0050"] + + 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 ", attr_path, " file !") + + 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_pg' + 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_abs' + 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 == 0): + status = 1 + + return status diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..689710cf3f4d --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/plugins/sfputil.py @@ -0,0 +1,306 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 63 + PORTS_IN_BLOCK = 64 + EEPROM_OFFSET = 41 + CPLD1_PORTS = 12 + CPLDx_PORTS = 13 + # TODO: check init sequence for CPLD i2c bus + CPLD_OFFSET = 1 + CPLD_PRES_BIT = 1 + CPLD_RESET_BIT = 0 + CPLD_LPMOD_BIT = 2 + CPLDx_I2C_ADDR = "33" + EEPROM_I2C_ADDR = "50" + CPLD_PORT_STATUS_KEY = "cpld_qsfp_port_status" + CPLD_PORT_CONFIG_KEY = "cpld_qsfp_port_config" + CPLD_REG_PATH = "/sys/bus/i2c/devices/{0}-00{1}/{2}_{3}" + + _port_to_eeprom_mapping = {} + + # TODO: check the fp port to phy port mapping + _fp2phy_port_mapping = { + 0: 0, + 1: 1, + 2: 4, + 3: 5, + 4: 8, + 5: 9, + 6: 12, + 7: 13, + 8: 16, + 9: 17, + 10: 20, + 11: 21, + 12: 24, + 13: 25, + 14: 28, + 15: 29, + 16: 32, + 17: 33, + 18: 36, + 19: 37, + 20: 40, + 21: 41, + 22: 44, + 23: 45, + 24: 48, + 25: 49, + 26: 52, + 27: 53, + 28: 56, + 29: 57, + 30: 60, + 31: 61, + 32: 2, + 33: 3, + 34: 6, + 35: 7, + 36: 10, + 37: 11, + 38: 14, + 39: 15, + 40: 18, + 41: 19, + 42: 22, + 43: 23, + 44: 26, + 45: 27, + 46: 30, + 47: 31, + 48: 34, + 49: 35, + 50: 38, + 51: 39, + 52: 42, + 53: 43, + 54: 46, + 55: 47, + 56: 50, + 57: 51, + 58: 54, + 59: 55, + 60: 58, + 61: 59, + 62: 62, + 63: 63 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-00{1}/eeprom" + for x in range(self.port_start, self.port_end + 1): + phy_port = self.fp2phy_port_num(x) + port_eeprom_path = eeprom_path.format(phy_port + self.EEPROM_OFFSET, self.EEPROM_I2C_ADDR) + self.port_to_eeprom_mapping[x] = port_eeprom_path + + SfpUtilBase.__init__(self) + + def qsfp_to_cpld_index(self, port_num): + if port_num < self.CPLD1_PORTS: + cpld_id = 0 + cpld_port_index = port_num + 1 + else: + cpld_id = 1 + (port_num - self.CPLD1_PORTS) / self.CPLDx_PORTS + cpld_port_index = ((port_num - self.CPLD1_PORTS) % self.CPLDx_PORTS) + 1 + return cpld_id, cpld_port_index + + def fp2phy_port_num(self, fp_port_num): + + phy_port_num = self._fp2phy_port_mapping[fp_port_num] + return phy_port_num + + 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 + + # logic port to physical port mapping + port_num = self.fp2phy_port_num(port_num) + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, + self.CPLD_PORT_STATUS_KEY, cpld_port_index) + + try: + reg_file = open(reg_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_file.close() + + reg_value = int(content, 16) + # mask for presence bit (bit 1) + mask = (1 << self.CPLD_PRES_BIT) + + # 0 - presence, 1 - absence + if reg_value & mask == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self.fp2phy_port_num(port_num) + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + try: + reg_file = open(reg_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_file.close() + + reg_value = int(content, 16) + # mask for lp_mod bit (bit 2) + mask = (1 << self.CPLD_LPMOD_BIT) + + # 0 - disable, 1 - low power mode + if reg_value & mask == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self.fp2phy_port_num(port_num) + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + try: + reg_file = open(reg_path, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + # mask for lp_mod bit (bit 2) + mask = (1 << self.CPLD_LPMOD_BIT) + + # 1 - low power mode, 0 - high power mode + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # convert value to hex string + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + # logic port to physical port mapping + port_num = self.fp2phy_port_num(port_num) + + cpld_id, cpld_port_index = self.qsfp_to_cpld_index(port_num) + i2c_id = self.CPLD_OFFSET + cpld_id + reg_path = self.CPLD_REG_PATH.format(i2c_id, self.CPLDx_I2C_ADDR, + self.CPLD_PORT_CONFIG_KEY, cpld_port_index) + + # reset the port + try: + reg_file = open(reg_path, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # content is a string containing the status register value + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + # mask for reset bit (bit 0) + mask = (1 << self.CPLD_RESET_BIT) + + # 1 - out of reset, 0 - reset + reg_value = reg_value & ~mask + + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 1 second to reset done + time.sleep(1) + + # take the port out of reset + try: + reg_file = open(reg_path, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | mask + + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/sensors.conf new file mode 100644 index 000000000000..0e9f5cd41ba8 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9280_64x-r0/sensors.conf @@ -0,0 +1,85 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + +bus "i2c-16" "i2c-mux-1 (chan_id 7)" +chip "w83795adg-*" + ignore in0 + label in1 "VDD_CORE" + set in1_min 0.717 + set in1_max 0.962 + ignore in2 + ignore in3 + label in4 "3.3V" + compute in4 @/(0.3052), (0.3052)*@ + set in4_min 3.3 * 0.95 + set in4_max 3.3 * 1.05 + label in5 "0.9V" + set in5_min 0.90 * 0.98 + set in5_max 0.90 * 1.02 + ignore in6 + ignore in7 + ignore in8 + ignore in9 + ignore in10 + ignore in11 + ignore in12 + ignore in13 + ignore in14 + ignore in15 + ignore in16 + ignore in17 + ignore in18 + ignore in19 + label fan1 "FANTRAY 1" + ignore fan2 + label fan3 "FANTRAY 2" + ignore fan4 + label fan5 "FANTRAY 3" + ignore fan6 + label fan7 "FANTRAY 4" + ignore fan8 + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 + +chip "tmp75-i2c-*-4A" + label temp1 "BMC Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-0" "SMBus I801 adapter at f000" +chip "tmp75-i2c-*-4F" + label temp1 "x86 CPU Board Temp" + set temp1_max 50 + set temp1_max_hyst 45 + +bus "i2c-6" "i2c-0-mux (chan_id 5)" +chip "lm75-i2c-6-4D" + label temp1 "Rear Panel Temp" + set temp1_max 50 + set temp1_max_hyst 45 +chip "lm75-i2c-6-4E" + label temp1 "Right Side MB Tetmp" + set temp1_max 50 + set temp1_max_hyst 45 +chip "lm86-i2c-6-4C" + label temp1 "Front Panel Temp" + set temp1_max 50 + label temp2 "Front MAC Temp" + set temp2_max 70 +bus "i2c-7" "i2c-0-mux (chan_id 6)" +chip "lm75-i2c-7-4D" + label temp1 "Left Side MB Temp" + set temp1_max 50 + set temp1_max_hyst 45 +chip "lm75-i2c-7-4E" + label temp1 "Left Side MAC Temp" + set temp1_max 50 + set temp1_max_hyst 45 diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/port_config.ini b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/port_config.ini new file mode 100644 index 000000000000..24823135f4ca --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/port_config.ini @@ -0,0 +1,74 @@ +# name lanes alias +Ethernet0 16 Ethernet0 +Ethernet4 15 Ethernet4 +Ethernet8 14 Ethernet8 +Ethernet12 13 Ethernet12 +Ethernet16 24 Ethernet16 +Ethernet20 23 Ethernet20 +Ethernet24 22 Ethernet24 +Ethernet28 21 Ethernet28 +Ethernet32 28 Ethernet32 +Ethernet36 27 Ethernet36 +Ethernet40 26 Ethernet40 +Ethernet44 25 Ethernet44 +Ethernet48 32 Ethernet48 +Ethernet52 31 Ethernet52 +Ethernet56 30 Ethernet56 +Ethernet60 29 Ethernet60 +Ethernet64 48 Ethernet64 +Ethernet68 47 Ethernet68 +Ethernet72 46 Ethernet72 +Ethernet76 45 Ethernet76 +Ethernet80 52 Ethernet80 +Ethernet84 51 Ethernet84 +Ethernet88 50 Ethernet88 +Ethernet92 49 Ethernet92 +Ethernet96 56 Ethernet96 +Ethernet100 55 Ethernet100 +Ethernet104 54 Ethernet104 +Ethernet108 53 Ethernet108 +Ethernet112 60 Ethernet112 +Ethernet116 59 Ethernet116 +Ethernet120 58 Ethernet120 +Ethernet124 57 Ethernet124 +Ethernet128 64 Ethernet128 +Ethernet132 63 Ethernet132 +Ethernet136 62 Ethernet136 +Ethernet140 61 Ethernet140 +Ethernet144 68 Ethernet144 +Ethernet148 67 Ethernet148 +Ethernet152 66 Ethernet152 +Ethernet156 65 Ethernet156 +Ethernet160 72 Ethernet160 +Ethernet164 71 Ethernet164 +Ethernet168 70 Ethernet168 +Ethernet172 69 Ethernet172 +Ethernet176 76 Ethernet176 +Ethernet180 75 Ethernet180 +Ethernet184 74 Ethernet184 +Ethernet188 73 Ethernet188 +Ethernet192 82 Ethernet192 +Ethernet196 84 Ethernet196 +Ethernet200 81 Ethernet200 +Ethernet204 83 Ethernet204 +Ethernet208 78 Ethernet208 +Ethernet212 80 Ethernet212 +Ethernet216 77 Ethernet216 +Ethernet220 79 Ethernet220 +Ethernet224 98 Ethernet224 +Ethernet228 100 Ethernet228 +Ethernet232 97 Ethernet232 +Ethernet236 99 Ethernet236 +Ethernet240 104 Ethernet240 +Ethernet244 102 Ethernet244 +Ethernet248 103 Ethernet248 +Ethernet252 101 Ethernet252 +Ethernet256 108 Ethernet256 +Ethernet260 106 Ethernet260 +Ethernet264 107 Ethernet264 +Ethernet268 105 Ethernet268 +Ethernet272 112 Ethernet272 +Ethernet276 110 Ethernet276 +Ethernet280 111 Ethernet280 +Ethernet284 109 Ethernet284 + diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/sai.profile b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/sai.profile new file mode 100644 index 000000000000..3f549dd63b40 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-d6254qs-72x10G.config +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/td2-d6254qs-72x10G.config.bcm b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/td2-d6254qs-72x10G.config.bcm new file mode 100644 index 000000000000..66b7172bce7c --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/td2-d6254qs-72x10G.config.bcm @@ -0,0 +1,160 @@ +os=unix +parity_enable=0 +pbmp_xport_xe.0=0x1fffffffffffffffffffffffffffffffe +miim_intr_enable=0 +schan_intr_enable=0 +bcm_stat_interval=2000000 +serdes_firmware_mode_xe=0x2 + +portmap_1=16:10 +portmap_2=15:10 +portmap_3=14:10 +portmap_4=13:10 +portmap_5=24:10 +portmap_6=23:10 +portmap_7=22:10 +portmap_8=21:10 +portmap_9=28:10 +portmap_10=27:10 +portmap_11=26:10 +portmap_12=25:10 +portmap_13=32:10 +portmap_14=31:10 +portmap_15=30:10 +portmap_16=29:10 +portmap_17=48:10 +portmap_18=47:10 +portmap_19=46:10 +portmap_20=45:10 +portmap_21=52:10 +portmap_22=51:10 +portmap_23=50:10 +portmap_24=49:10 +portmap_25=56:10 +portmap_26=55:10 +portmap_27=54:10 +portmap_28=53:10 +portmap_29=60:10 +portmap_30=59:10 +portmap_31=58:10 +portmap_32=57:10 +portmap_33=64:10 +portmap_34=63:10 +portmap_35=62:10 +portmap_36=61:10 +portmap_37=68:10 +portmap_38=67:10 +portmap_39=66:10 +portmap_40=65:10 +portmap_41=72:10 +portmap_42=71:10 +portmap_43=70:10 +portmap_44=69:10 +portmap_45=76:10 +portmap_46=75:10 +portmap_47=74:10 +portmap_48=73:10 + +portmap_49=82:10 +portmap_50=84:10 +portmap_51=81:10 +portmap_52=83:10 + +portmap_53=78:10 +portmap_54=80:10 +portmap_55=77:10 +portmap_56=79:10 + +portmap_57=98:10 +portmap_58=100:10 +portmap_59=97:10 +portmap_60=99:10 + +portmap_61=104:10 +portmap_62=102:10 +portmap_63=103:10 +portmap_64=101:10 + +portmap_65=108:10 +portmap_66=106:10 +portmap_67=107:10 +portmap_68=105:10 + +portmap_69=112:10 +portmap_70=110:10 +portmap_71=111:10 +portmap_72=109:10 + +xgxs_rx_lane_map_xe0=0x0123 +xgxs_rx_lane_map_xe1=0x0123 +xgxs_rx_lane_map_xe2=0x0123 +xgxs_rx_lane_map_xe3=0x0123 +xgxs_rx_lane_map_xe4=0x0123 +xgxs_rx_lane_map_xe5=0x0123 +xgxs_rx_lane_map_xe6=0x0123 +xgxs_rx_lane_map_xe7=0x0123 +xgxs_rx_lane_map_xe8=0x0123 +xgxs_rx_lane_map_xe9=0x0123 +xgxs_rx_lane_map_xe10=0x0123 +xgxs_rx_lane_map_xe11=0x0123 +xgxs_rx_lane_map_xe12=0x0123 +xgxs_rx_lane_map_xe13=0x0123 +xgxs_rx_lane_map_xe14=0x0123 +xgxs_rx_lane_map_xe15=0x0123 +xgxs_rx_lane_map_xe16=0x0123 +xgxs_rx_lane_map_xe17=0x0123 +xgxs_rx_lane_map_xe18=0x0123 +xgxs_rx_lane_map_xe19=0x0123 +xgxs_rx_lane_map_xe20=0x0123 +xgxs_rx_lane_map_xe21=0x0123 +xgxs_rx_lane_map_xe22=0x0123 +xgxs_rx_lane_map_xe23=0x0123 +xgxs_rx_lane_map_xe24=0x0123 +xgxs_rx_lane_map_xe25=0x0123 +xgxs_rx_lane_map_xe26=0x0123 +xgxs_rx_lane_map_xe27=0x0123 +xgxs_rx_lane_map_xe28=0x0123 +xgxs_rx_lane_map_xe29=0x0123 +xgxs_rx_lane_map_xe30=0x0123 +xgxs_rx_lane_map_xe31=0x0123 +xgxs_rx_lane_map_xe32=0x0123 +xgxs_rx_lane_map_xe33=0x0123 +xgxs_rx_lane_map_xe34=0x0123 +xgxs_rx_lane_map_xe35=0x0123 +xgxs_rx_lane_map_xe36=0x0123 +xgxs_rx_lane_map_xe37=0x0123 +xgxs_rx_lane_map_xe38=0x0123 +xgxs_rx_lane_map_xe39=0x0123 +xgxs_rx_lane_map_xe40=0x0123 +xgxs_rx_lane_map_xe41=0x0123 +xgxs_rx_lane_map_xe42=0x0123 +xgxs_rx_lane_map_xe43=0x0123 +xgxs_rx_lane_map_xe44=0x0123 +xgxs_rx_lane_map_xe45=0x0123 +xgxs_rx_lane_map_xe46=0x0123 +xgxs_rx_lane_map_xe47=0x0123 +xgxs_rx_lane_map_xe48=0x0123 +xgxs_rx_lane_map_xe49=0x0123 +xgxs_rx_lane_map_xe50=0x0123 +xgxs_rx_lane_map_xe51=0x0123 +xgxs_rx_lane_map_xe52=0x0123 +xgxs_rx_lane_map_xe53=0x0123 +xgxs_rx_lane_map_xe54=0x0123 +xgxs_rx_lane_map_xe55=0x0123 +xgxs_rx_lane_map_xe56=0x0123 +xgxs_rx_lane_map_xe57=0x0123 +xgxs_rx_lane_map_xe58=0x0123 +xgxs_rx_lane_map_xe59=0x0123 +xgxs_rx_lane_map_xe60=0x0123 +xgxs_rx_lane_map_xe61=0x0123 +xgxs_rx_lane_map_xe62=0x0123 +xgxs_rx_lane_map_xe63=0x0123 +xgxs_rx_lane_map_xe64=0x0123 +xgxs_rx_lane_map_xe65=0x0123 +xgxs_rx_lane_map_xe66=0x0123 +xgxs_rx_lane_map_xe67=0x0123 +xgxs_rx_lane_map_xe68=0x0123 +xgxs_rx_lane_map_xe69=0x0123 +xgxs_rx_lane_map_xe70=0x0123 +xgxs_rx_lane_map_xe71=0x0123 + diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/installer.conf b/device/inventec/x86_64-inventec_d6254qs-r0/installer.conf new file mode 100644 index 000000000000..6b489db6e16f --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 +VAR_LOG_SIZE=1024 diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d6254qs-r0/led_proc_init.soc new file mode 100644 index 000000000000..92423b234498 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/led_proc_init.soc @@ -0,0 +1,136 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=38 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=42 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=41 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=46 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=45 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=50 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=49 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=54 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=53 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=58 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=62 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=61 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60 + +led 0 stop +led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +led 0 start + +led 1 stop +led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +led 1 start diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/minigraph.xml b/device/inventec/x86_64-inventec_d6254qs-r0/minigraph.xml new file mode 100644 index 000000000000..e2368e171b58 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/minigraph.xml @@ -0,0 +1,144 @@ + + + + + + OCPSCH0104001MS + 10.10.1.26 + SONiC-Inventec-d6254qs + 10.10.1.25 + 1 + 10 + 3 + + + OCPSCH0104002MS + 10.10.2.26 + SONiC-Inventec-d6254qs + 10.10.2.25 + 1 + 10 + 3 + + + + + 64536 + SONiC-Inventec-d6254qs + + +
10.10.1.26
+ + +
+ +
10.10.2.26
+ + +
+
+ +
+ + 64542 + OCPSCH0104001MS + + + + 64543 + OCPSCH0104002MS + + +
+
+ + + + + + HostIP + Loopback0 + + 100.0.0.9/32 + + 100.0.0.9/32 + + + + + + + + SONiC-Inventec-d6254qs + + + + + + Ethernet0 + 10.10.1.25/30 + + + + Ethernet4 + 10.10.2.25/30 + + + + + + + + + + + + DeviceInterfaceLink + OCPSCH0104001MS + Ethernet24 + SONiC-Inventec-d6254qs + Ethernet0 + + + DeviceInterfaceLink + OCPSCH0104002MS + Ethernet24 + SONiC-Inventec-d6254qs + Ethernet4 + + + + + SONiC-Inventec-d6254qs + INVENTEC-D6254QS + + + + + + + SONiC-Inventec-d6254qs + + + DhcpResources + + + + + NtpResources + + 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org + + + SyslogResources + + + + + + + + + SONiC-Inventec-d6254qs + INVENTEC-D6254QS +
diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/eeprom.py new file mode 100644 index 000000000000..31f847614fb0 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Inventec d7032q28b +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/psuutil.py new file mode 100644 index 000000000000..162e240bae35 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/psuutil.py @@ -0,0 +1,84 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR = "/sys/bus/i2c/devices/0-0066" + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + 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 = 'psoc_psu' + str(index) + '_iout' + attr_path = self.PSU_DIR + '/' + attr_file + + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU status + if (attr_value != 0): + 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 + ind = index-1 + attr_file = 'psu' + str(ind) + attr_path = self.PSU_DIR + '/' + attr_file + normal_attr_value = '0 : normal' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/sfputil.py new file mode 100644 index 000000000000..62a67f72e1a4 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/sfputil.py @@ -0,0 +1,209 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 53 + PORTS_IN_BLOCK = 54 + QSFP_PORT_START = 48 + QSFP_PORT_END = 53 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 10, + 1: 11, + 2: 12, + 3: 13, + 4: 14, + 5: 15, + 6: 16, + 7: 17, + 8: 18, + 9: 19, + 10: 20, + 11: 21, + 12: 22, + 13: 23, + 14: 24, + 15: 25, + 16: 26, + 17: 27, + 18: 28, + 19: 29, + 20: 30, + 21: 31, + 22: 32, + 23: 33, + 24: 34, + 25: 35, + 26: 36, + 27: 37, + 28: 38, + 29: 39, + 30: 40, + 31: 41, + 32: 42, + 33: 43, + 34: 44, + 35: 45, + 36: 46, + 37: 47, + 38: 48, + 39: 49, + 40: 50, + 41: 51, + 42: 52, + 43: 53, + 44: 54, + 45: 55, + 46: 56, + 47: 57, + 48: 58, + 49: 59, + 50: 60, + 51: 61, + 52: 62, + 53: 63 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom" + + for x in range(0, 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) + + 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 + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + print("\nError:SFP's don't support this property") + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset" + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + print("\nError:SFP's don't support this property") + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/sensors.conf b/device/inventec/x86_64-inventec_d6254qs-r0/sensors.conf new file mode 100644 index 000000000000..653900cad36f --- /dev/null +++ b/device/inventec/x86_64-inventec_d6254qs-r0/sensors.conf @@ -0,0 +1,15 @@ +# libsensors configuration file +chip "inv_psoc-*" + ignore temp3 + ignore temp4 + label temp1 "CPU Board Temperature" + label temp2 "SW Board I Temperature" + label temp5 "SW Board II Temperature" + label temp6 "ASIC Temperature" + label in1 "PSU1 Voltage" + label in2 "PSU2 Voltage" + label curr1 "PSU1 Current" + label curr2 "PSU2 Current" + label power1 "PSU1 Power" + label power2 "PSU2 Power" + diff --git a/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/buffers.json.j2 b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/buffers_defaults_t1.j2 b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..f77839cddf87 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ + +{%- set default_cable = '40m' %} + +{%- set PORT_ALL = [] %} + +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{%- endif %} +{%- endfor %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "27678784", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "26045524", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "32786432", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} \ No newline at end of file diff --git a/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/pg_profile_lookup.ini b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/pg_profile_lookup.ini new file mode 100644 index 000000000000..7222f8014925 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -4 2288 + 25000 5m 1248 2288 53248 -4 2288 + 40000 5m 1248 2288 66560 -4 2288 + 50000 5m 1248 2288 79872 -4 2288 + 100000 5m 1248 2288 165568 -4 2288 + 10000 40m 1248 2288 37024 -4 2288 + 25000 40m 1248 2288 56160 -4 2288 + 40000 40m 1248 2288 71552 -4 2288 + 50000 40m 1248 2288 85696 -4 2288 + 100000 40m 1248 2288 177632 -4 2288 + 10000 300m 1248 2288 46176 -4 2288 + 25000 300m 1248 2288 79040 -4 2288 + 40000 300m 1248 2288 108160 -4 2288 + 50000 300m 1248 2288 131456 -4 2288 + 100000 300m 1248 2288 268736 -4 2288 diff --git a/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/port_config.ini b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/port_config.ini new file mode 100755 index 000000000000..d0ce46c7a8fe --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/port_config.ini @@ -0,0 +1,33 @@ +# name lanes index speed autoneg +Ethernet0 21,22,23,24 0 100000 0 +Ethernet4 17,18,19,20 1 100000 0 +Ethernet8 25,26,27,28 2 100000 0 +Ethernet12 29,30,31,32 3 100000 0 +Ethernet16 37,38,39,40 4 100000 0 +Ethernet20 33,34,35,36 5 100000 0 +Ethernet24 41,42,43,44 6 100000 0 +Ethernet28 45,46,47,48 7 100000 0 +Ethernet32 5,6,7,8 8 100000 0 +Ethernet36 1,2,3,4 9 100000 0 +Ethernet40 9,10,11,12 10 100000 0 +Ethernet44 13,14,15,16 11 100000 0 +Ethernet48 53,54,55,56 12 100000 0 +Ethernet52 49,50,51,52 13 100000 0 +Ethernet56 57,58,59,60 14 100000 0 +Ethernet60 61,62,63,64 15 100000 0 +Ethernet64 69,70,71,72 16 100000 0 +Ethernet68 65,66,67,68 17 100000 0 +Ethernet72 73,74,75,76 18 100000 0 +Ethernet76 77,78,79,80 19 100000 0 +Ethernet80 117,118,119,120 20 100000 0 +Ethernet84 113,114,115,116 21 100000 0 +Ethernet88 121,122,123,124 22 100000 0 +Ethernet92 125,126,127,128 23 100000 0 +Ethernet96 85,86,87,88 24 100000 0 +Ethernet100 81,82,83,84 25 100000 0 +Ethernet104 89,90,91,92 26 100000 0 +Ethernet108 93,94,95,96 27 100000 0 +Ethernet112 101,102,103,104 28 100000 0 +Ethernet116 97,98,99,100 29 100000 0 +Ethernet120 105,106,107,108 30 100000 0 +Ethernet124 109,110,111,112 31 100000 0 diff --git a/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/qos.json.j2 b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/qos.json.j2 new file mode 100644 index 000000000000..3b909e0adbbc --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/qos.json.j2 @@ -0,0 +1,161 @@ +{%- set PORT_ALL = [] %} + +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{%- endif %} +{%- endfor %} + +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "{{ PORT_ALL|join(',') }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"312000", + "red_min_threshold":"104000", + "yellow_max_threshold":"312000", + "yellow_min_threshold":"104000", + "green_max_threshold": "312000", + "green_min_threshold": "104000" + } + }, + "QUEUE": { + "{{ PORT_ALL|join(',') }}|3-4" : { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "{{ PORT_ALL|join(',') }}|0" : { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "{{ PORT_ALL|join(',') }}|1" : { + "scheduler" : "[SCHEDULER|scheduler.2]" + } + } +} diff --git a/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/sai.profile b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/sai.profile new file mode 100755 index 000000000000..51c00abc35f7 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-d6332-32x100G-SR4.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/td3-d6332-32x100G-SR4.config.bcm b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/td3-d6332-32x100G-SR4.config.bcm new file mode 100644 index 000000000000..8fe7622f4b8f --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/td3-d6332-32x100G-SR4.config.bcm @@ -0,0 +1,669 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +### fix for sonic +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 +ifp_inports_support_enable=1 +### end fix + +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +oversubscribe_mode=1 +pbmp_xport_xe=0xc888888888888888e2222222222222222 + +l2_mem_entries=32768 +l3_mem_entries=16384 +fpem_mem_entries=16384 +l2xmsg_mode=1 + +pdma_descriptor_prefetch_enable=1 + +port_flex_enable=1 +stable_size=0x5500000 + + +### Loopback port +#portmap_65=130:10 +#portmap_131=131:10 + +portmap_1=1:100 +portmap_5=5:100 +portmap_9=9:100 +portmap_13=13:100 +portmap_17=17:100 +portmap_21=21:100 +portmap_25=25:100 +portmap_29=29:100 + +### Pipeline0, halfpipe 1 (8x100G) +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_57=57:100 +portmap_61=61:100 + +### Pipeline 1 +### First management port +#portmap_66=129:10:m +### Second management port +#portmap_130=128:10:m + +### Pipeline 1, halfpipe 0 (8x100G) +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 + +### Pipeline 1, halfpipe 1 (8x100G) +portmap_99=97:100 +portmap_103=101:100 +portmap_107=105:100 +portmap_111=109:100 +portmap_115=113:100 +portmap_119=117:100 +portmap_123=121:100 +portmap_127=125:100 + + +#dport part +dport_map_port_21=1 +dport_map_port_17=2 +dport_map_port_25=3 +dport_map_port_29=4 +dport_map_port_37=5 +dport_map_port_33=6 +dport_map_port_41=7 +dport_map_port_45=8 +dport_map_port_5=9 +dport_map_port_1=10 +dport_map_port_9=11 +dport_map_port_13=12 +dport_map_port_53=13 +dport_map_port_49=14 +dport_map_port_57=15 +dport_map_port_61=16 +dport_map_port_71=17 +dport_map_port_67=18 +dport_map_port_75=19 +dport_map_port_79=20 +dport_map_port_119=21 +dport_map_port_115=22 +dport_map_port_123=23 +dport_map_port_127=24 +dport_map_port_87=25 +dport_map_port_83=26 +dport_map_port_91=27 +dport_map_port_95=28 +dport_map_port_103=29 +dport_map_port_99=30 +dport_map_port_107=31 +dport_map_port_111=32 + + + + +#Polarity flips +#FC0 +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 + +#FC1 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 + +#FC2 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x1 +phy_chain_rx_polarity_flip_physical{12.0}=0x1 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x1 + +#FC3 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +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_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 + +#FC4 +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}=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}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 + +#FC5 +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_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 + +#FC6 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x1 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 + +#FC7 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x1 + +#FC8 +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +phy_chain_tx_polarity_flip_physical{36.0}=0x1 + +#FC9 +phy_chain_rx_polarity_flip_physical{37.0}=0x0 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{40.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 + +#FC10 +phy_chain_rx_polarity_flip_physical{41.0}=0x1 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.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 + +#FC11 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x1 +phy_chain_rx_polarity_flip_physical{48.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 + +#FC12 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x1 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 + +#FC13 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x1 +phy_chain_tx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x0 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 + +#FC14 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x1 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 + +#FC15 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 + +#FC16 +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}=0x0 +phy_chain_tx_polarity_flip_physical{65.0}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x1 +phy_chain_tx_polarity_flip_physical{68.0}=0x1 + +#FC17 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x1 +phy_chain_tx_polarity_flip_physical{69.0}=0x1 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 + +#FC18 +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}=0x0 +phy_chain_rx_polarity_flip_physical{76.0}=0x0 +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 + +#FC19 +phy_chain_rx_polarity_flip_physical{77.0}=0x0 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.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 + +#FC20 +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x1 +phy_chain_rx_polarity_flip_physical{84.0}=0x1 +phy_chain_tx_polarity_flip_physical{81.0}=0x0 +phy_chain_tx_polarity_flip_physical{82.0}=0x0 +phy_chain_tx_polarity_flip_physical{83.0}=0x1 +phy_chain_tx_polarity_flip_physical{84.0}=0x1 + +#FC21 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +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 + +#FC22 +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x1 +phy_chain_rx_polarity_flip_physical{92.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{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x1 + +#FC23 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 +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 + +#FC24 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 + +#FC25 +phy_chain_rx_polarity_flip_physical{101.0}=0x1 +phy_chain_rx_polarity_flip_physical{102.0}=0x1 +phy_chain_rx_polarity_flip_physical{103.0}=0x0 +phy_chain_rx_polarity_flip_physical{104.0}=0x0 +phy_chain_tx_polarity_flip_physical{101.0}=0x0 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +phy_chain_tx_polarity_flip_physical{103.0}=0x1 +phy_chain_tx_polarity_flip_physical{104.0}=0x1 + +#FC26 +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}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x0 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 + +#FC27 +phy_chain_rx_polarity_flip_physical{109.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.0}=0x0 +phy_chain_rx_polarity_flip_physical{111.0}=0x1 +phy_chain_rx_polarity_flip_physical{112.0}=0x1 +phy_chain_tx_polarity_flip_physical{109.0}=0x0 +phy_chain_tx_polarity_flip_physical{110.0}=0x0 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 + +#FC28 +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}=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}=0x1 +phy_chain_tx_polarity_flip_physical{116.0}=0x1 + +#FC29 +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_tx_polarity_flip_physical{117.0}=0x0 +phy_chain_tx_polarity_flip_physical{118.0}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x1 +phy_chain_tx_polarity_flip_physical{120.0}=0x1 + +#FC30 +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}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x0 +phy_chain_tx_polarity_flip_physical{121.0}=0x0 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x1 + +#FC31 +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_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 + +#lanes swap +#FC0~FC7 +phy_chain_rx_lane_map_physical{1.0}=0x1302 +phy_chain_tx_lane_map_physical{1.0}=0x2031 +phy_chain_rx_lane_map_physical{5.0}=0x3120 +phy_chain_tx_lane_map_physical{5.0}=0x2031 +phy_chain_rx_lane_map_physical{9.0}=0x1302 +phy_chain_tx_lane_map_physical{9.0}=0x2031 +phy_chain_rx_lane_map_physical{13.0}=0x3120 +phy_chain_tx_lane_map_physical{13.0}=0x0213 +phy_chain_rx_lane_map_physical{17.0}=0x1302 +phy_chain_tx_lane_map_physical{17.0}=0x2031 +phy_chain_rx_lane_map_physical{21.0}=0x3120 +phy_chain_tx_lane_map_physical{21.0}=0x0213 +phy_chain_rx_lane_map_physical{25.0}=0x1302 +phy_chain_tx_lane_map_physical{25.0}=0x2031 +phy_chain_rx_lane_map_physical{29.0}=0x3120 +phy_chain_tx_lane_map_physical{29.0}=0x0213 + +#FC8~FC15 +phy_chain_rx_lane_map_physical{33.0}=0x1302 +phy_chain_tx_lane_map_physical{33.0}=0x2031 +phy_chain_rx_lane_map_physical{37.0}=0x3120 +phy_chain_tx_lane_map_physical{37.0}=0x0213 +phy_chain_rx_lane_map_physical{41.0}=0x1302 +phy_chain_tx_lane_map_physical{41.0}=0x2031 +phy_chain_rx_lane_map_physical{45.0}=0x3120 +phy_chain_tx_lane_map_physical{45.0}=0x0213 +phy_chain_rx_lane_map_physical{49.0}=0x2301 +phy_chain_tx_lane_map_physical{49.0}=0x2031 +phy_chain_rx_lane_map_physical{53.0}=0x3120 +phy_chain_tx_lane_map_physical{53.0}=0x2031 +phy_chain_rx_lane_map_physical{57.0}=0x1302 +phy_chain_tx_lane_map_physical{57.0}=0x2031 +phy_chain_rx_lane_map_physical{61.0}=0x3120 +phy_chain_tx_lane_map_physical{61.0}=0x0213 + +#FC16~FC23 +phy_chain_rx_lane_map_physical{65.0}=0x2031 +phy_chain_tx_lane_map_physical{65.0}=0x1302 +phy_chain_rx_lane_map_physical{69.0}=0x0213 +phy_chain_tx_lane_map_physical{69.0}=0x3201 +phy_chain_rx_lane_map_physical{73.0}=0x2031 +phy_chain_tx_lane_map_physical{73.0}=0x1302 +phy_chain_rx_lane_map_physical{77.0}=0x0123 +phy_chain_tx_lane_map_physical{77.0}=0x3120 +phy_chain_rx_lane_map_physical{81.0}=0x2031 +phy_chain_tx_lane_map_physical{81.0}=0x1302 +phy_chain_rx_lane_map_physical{85.0}=0x0213 +phy_chain_tx_lane_map_physical{85.0}=0x1302 +phy_chain_rx_lane_map_physical{89.0}=0x2031 +phy_chain_tx_lane_map_physical{89.0}=0x1302 +phy_chain_rx_lane_map_physical{93.0}=0x0213 +phy_chain_tx_lane_map_physical{93.0}=0x3120 + +#FC24~FC31 +phy_chain_rx_lane_map_physical{97.0}=0x2031 +phy_chain_tx_lane_map_physical{97.0}=0x1302 +phy_chain_rx_lane_map_physical{101.0}=0x2031 +phy_chain_tx_lane_map_physical{101.0}=0x1302 +phy_chain_rx_lane_map_physical{105.0}=0x2031 +phy_chain_tx_lane_map_physical{105.0}=0x1302 +phy_chain_rx_lane_map_physical{109.0}=0x0213 +phy_chain_tx_lane_map_physical{109.0}=0x3120 +phy_chain_rx_lane_map_physical{113.0}=0x2031 +phy_chain_tx_lane_map_physical{113.0}=0x1302 +phy_chain_rx_lane_map_physical{117.0}=0x0213 +phy_chain_tx_lane_map_physical{117.0}=0x1302 +phy_chain_rx_lane_map_physical{121.0}=0x2031 +phy_chain_tx_lane_map_physical{121.0}=0x1302 +phy_chain_rx_lane_map_physical{125.0}=0x0213 +phy_chain_tx_lane_map_physical{125.0}=0x3120 + + +serdes_preemphasis_lane0_21=0x11490A +serdes_preemphasis_lane1_21=0x11490A +serdes_preemphasis_lane2_21=0x11490A +serdes_preemphasis_lane3_21=0x11490A +serdes_preemphasis_lane0_17=0x12480A +serdes_preemphasis_lane1_17=0x12480A +serdes_preemphasis_lane2_17=0x12480A +serdes_preemphasis_lane3_17=0x12480A +serdes_preemphasis_lane0_25=0x104A0A +serdes_preemphasis_lane1_25=0x104A0A +serdes_preemphasis_lane2_25=0x104A0A +serdes_preemphasis_lane3_25=0x104A0A +serdes_preemphasis_lane0_29=0x104A0A +serdes_preemphasis_lane1_29=0x104A0A +serdes_preemphasis_lane2_29=0x104A0A +serdes_preemphasis_lane3_29=0x104A0A +serdes_preemphasis_lane0_37=0x0F4B0A +serdes_preemphasis_lane1_37=0x0F4B0A +serdes_preemphasis_lane2_37=0x0F4B0A +serdes_preemphasis_lane3_37=0x0F4B0A +serdes_preemphasis_lane0_33=0x0F4B0A +serdes_preemphasis_lane1_33=0x104A0A +serdes_preemphasis_lane2_33=0x0F4B0A +serdes_preemphasis_lane3_33=0x104A0A +serdes_preemphasis_lane0_41=0x0E4C0A +serdes_preemphasis_lane1_41=0x0F4B0A +serdes_preemphasis_lane2_41=0x0E4C0A +serdes_preemphasis_lane3_41=0x0F4B0A +serdes_preemphasis_lane0_45=0x0E4C0A +serdes_preemphasis_lane1_45=0x0E4C0A +serdes_preemphasis_lane2_45=0x0E4C0A +serdes_preemphasis_lane3_45=0x0E4C0A +serdes_preemphasis_lane0_5=0x0F4B0A +serdes_preemphasis_lane1_5=0x0F4B0A +serdes_preemphasis_lane2_5=0x0F4B0A +serdes_preemphasis_lane3_5=0x0F4B0A +serdes_preemphasis_lane0_1=0x0F4B0A +serdes_preemphasis_lane1_1=0x0F4B0A +serdes_preemphasis_lane2_1=0x0F4B0A +serdes_preemphasis_lane3_1=0x0F4B0A +serdes_preemphasis_lane0_9=0x0E4C0A +serdes_preemphasis_lane1_9=0x0F4B0A +serdes_preemphasis_lane2_9=0x0E4C0A +serdes_preemphasis_lane3_9=0x0F4B0A +serdes_preemphasis_lane0_13=0x0E4C0A +serdes_preemphasis_lane1_13=0x0F4B0A +serdes_preemphasis_lane2_13=0x0E4C0A +serdes_preemphasis_lane3_13=0x0F4B0A +serdes_preemphasis_lane0_53=0x05550A +serdes_preemphasis_lane1_53=0x07530A +serdes_preemphasis_lane2_53=0x05550A +serdes_preemphasis_lane3_53=0x07530A +serdes_preemphasis_lane0_49=0x07530A +serdes_preemphasis_lane1_49=0x0A500A +serdes_preemphasis_lane2_49=0x07530A +serdes_preemphasis_lane3_49=0x0A500A +serdes_preemphasis_lane0_57=0x05550A +serdes_preemphasis_lane1_57=0x05550A +serdes_preemphasis_lane2_57=0x05550A +serdes_preemphasis_lane3_57=0x07530A +serdes_preemphasis_lane0_61=0x07530A +serdes_preemphasis_lane1_61=0x07530A +serdes_preemphasis_lane2_61=0x07530A +serdes_preemphasis_lane3_61=0x0A500A +serdes_preemphasis_lane0_71=0x05550A +serdes_preemphasis_lane1_71=0x05550A +serdes_preemphasis_lane2_71=0x05550A +serdes_preemphasis_lane3_71=0x05550A +serdes_preemphasis_lane0_67=0x07530A +serdes_preemphasis_lane1_67=0x07530A +serdes_preemphasis_lane2_67=0x05550A +serdes_preemphasis_lane3_67=0x07530A +serdes_preemphasis_lane0_75=0x05550A +serdes_preemphasis_lane1_75=0x07530A +serdes_preemphasis_lane2_75=0x05550A +serdes_preemphasis_lane3_75=0x05550A +serdes_preemphasis_lane0_79=0x07530A +serdes_preemphasis_lane1_79=0x0A500A +serdes_preemphasis_lane2_79=0x07530A +serdes_preemphasis_lane3_79=0x0A500A +serdes_preemphasis_lane0_119=0x0E4C0A +serdes_preemphasis_lane1_119=0x0F4B0A +serdes_preemphasis_lane2_119=0x0E4C0A +serdes_preemphasis_lane3_119=0x0F4B0A +serdes_preemphasis_lane0_115=0x0E4C0A +serdes_preemphasis_lane1_115=0x0E4C0A +serdes_preemphasis_lane2_115=0x0F4B0A +serdes_preemphasis_lane3_115=0x0E4C0A +serdes_preemphasis_lane0_123=0x0F4B0A +serdes_preemphasis_lane1_123=0x0F4B0A +serdes_preemphasis_lane2_123=0x0F4B0A +serdes_preemphasis_lane3_123=0x0F4B0A +serdes_preemphasis_lane0_127=0x0F4B0A +serdes_preemphasis_lane1_127=0x0F4B0A +serdes_preemphasis_lane2_127=0x0F4B0A +serdes_preemphasis_lane3_127=0x0F4B0A +serdes_preemphasis_lane0_87=0x0E4C0A +serdes_preemphasis_lane1_87=0x0E4C0A +serdes_preemphasis_lane2_87=0x0E4C0A +serdes_preemphasis_lane3_87=0x0E4C0A +serdes_preemphasis_lane0_83=0x0F4B0A +serdes_preemphasis_lane1_83=0x0F4B0A +serdes_preemphasis_lane2_83=0x0F4B0A +serdes_preemphasis_lane3_83=0x0F4B0A +serdes_preemphasis_lane0_91=0x0F4B0A +serdes_preemphasis_lane1_91=0x0F4B0A +serdes_preemphasis_lane2_91=0x0F4B0A +serdes_preemphasis_lane3_91=0x0F4B0A +serdes_preemphasis_lane0_95=0x0F4B0A +serdes_preemphasis_lane1_95=0x104A0A +serdes_preemphasis_lane2_95=0x0F4B0A +serdes_preemphasis_lane3_95=0x104A0A +serdes_preemphasis_lane0_103=0x104A0A +serdes_preemphasis_lane1_103=0x104A0A +serdes_preemphasis_lane2_103=0x104A0A +serdes_preemphasis_lane3_103=0x104A0A +serdes_preemphasis_lane0_99=0x104A0A +serdes_preemphasis_lane1_99=0x104A0A +serdes_preemphasis_lane2_99=0x104A0A +serdes_preemphasis_lane3_99=0x104A0A +serdes_preemphasis_lane0_107=0x104A0A +serdes_preemphasis_lane1_107=0x11490A +serdes_preemphasis_lane2_107=0x104A0A +serdes_preemphasis_lane3_107=0x11490A +serdes_preemphasis_lane0_111=0x11490A +serdes_preemphasis_lane1_111=0x12480A +serdes_preemphasis_lane2_111=0x11490A +serdes_preemphasis_lane3_111=0x12480A + + +serdes_if_type_21=28 +serdes_if_type_17=28 +serdes_if_type_25=28 +serdes_if_type_29=28 +serdes_if_type_37=28 +serdes_if_type_33=28 +serdes_if_type_41=28 +serdes_if_type_45=28 +serdes_if_type_5=28 +serdes_if_type_1=28 +serdes_if_type_9=28 +serdes_if_type_13=28 +serdes_if_type_53=28 +serdes_if_type_49=28 +serdes_if_type_57=28 +serdes_if_type_61=28 +serdes_if_type_71=28 +serdes_if_type_67=28 +serdes_if_type_75=28 +serdes_if_type_79=28 +serdes_if_type_119=28 +serdes_if_type_115=28 +serdes_if_type_123=28 +serdes_if_type_127=28 +serdes_if_type_87=28 +serdes_if_type_83=28 +serdes_if_type_91=28 +serdes_if_type_95=28 +serdes_if_type_103=28 +serdes_if_type_99=28 +serdes_if_type_107=28 +serdes_if_type_111=28 diff --git a/device/inventec/x86_64-inventec_d6332-r0/custom_init.soc.j2 b/device/inventec/x86_64-inventec_d6332-r0/custom_init.soc.j2 new file mode 100644 index 000000000000..2149cb5a596e --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/custom_init.soc.j2 @@ -0,0 +1,3 @@ +phy xe AN_X4_LD_BASE_ABIL3r BASE_25G_CR1_EN=1 +phy ce AN_X4_LD_BASE_ABIL1r 0x01ff +setreg CLMAC_TX_MAC_SA 0x{{ DEVICE_METADATA.localhost.mac|replace(":","")}} diff --git a/device/inventec/x86_64-inventec_d6332-r0/custom_led.bin b/device/inventec/x86_64-inventec_d6332-r0/custom_led.bin new file mode 100644 index 000000000000..adaab507cb90 Binary files /dev/null and b/device/inventec/x86_64-inventec_d6332-r0/custom_led.bin differ diff --git a/device/inventec/x86_64-inventec_d6332-r0/default_sku b/device/inventec/x86_64-inventec_d6332-r0/default_sku new file mode 100644 index 000000000000..e07c80931dde --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/default_sku @@ -0,0 +1 @@ +INVENTEC-D6332 t1 diff --git a/device/inventec/x86_64-inventec_d6332-r0/installer.conf b/device/inventec/x86_64-inventec_d6332-r0/installer.conf new file mode 100644 index 000000000000..1db64ba02c38 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +VAR_LOG_SIZE=1024 diff --git a/device/inventec/x86_64-inventec_d6332-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d6332-r0/led_proc_init.soc new file mode 100644 index 000000000000..5dcf85ea7956 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/led_proc_init.soc @@ -0,0 +1,5 @@ +led auto off +led stop +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/inventec/x86_64-inventec_d6332-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d6332-r0/plugins/eeprom.py new file mode 100644 index 000000000000..96e27323aa44 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Inventec d6356j +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/0-0055/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/inventec/x86_64-inventec_d6332-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d6332-r0/plugins/psuutil.py new file mode 100755 index 000000000000..3ae6d5ddb355 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/plugins/psuutil.py @@ -0,0 +1,89 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + """CPLD address""" + PSU_DIR = "/sys/bus/i2c/devices/i2c-inv_cpld/" + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + 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' + str(index) + attr_path = self.PSU_DIR + '/' + attr_file + normal_attr_value = '1:normal' + unpower_attr_value = '0:unpowered' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + elif (attr_value == unpower_attr_value): + status = 0 + 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 + attr_file = 'psu' + str(index) + attr_path = self.PSU_DIR + '/' + attr_file + normal_attr_value = '1:normal' + unpower_attr_value = '0:unpowered' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + if (attr_value == unpower_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d6332-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d6332-r0/plugins/sfputil.py new file mode 100755 index 000000000000..7c3b78c1bc22 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/plugins/sfputil.py @@ -0,0 +1,354 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import re + import socket + from sonic_sfp.sfputilbase import SfpUtilBase + from collections import OrderedDict + from sonic_sfp.sff8472 import sff8472Dom +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VLOT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 + +NETLINK_KOBJECT_UEVENT = 15 +monitor = None + + +class SWPSEventMonitor(object): + + def __init__(self): + self.recieved_events = OrderedDict() + self.socket = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT) + + def start(self): + self.socket.bind((os.getpid(), -1)) + + def stop(self): + self.socket.close() + + def __enter__(self): + self.start() + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.stop() + + def __iter__(self): + global monitor + while True: + for item in monitor.next_events(): + yield item + + def next_events(self): + data = self.socket.recv(16384) + event = {} + for item in data.split(b'\x00'): + if not item: + # check if we have an event and if we already received it + if event and event['SEQNUM'] not in self.recieved_events: + self.recieved_events[event['SEQNUM']] = None + if (len(self.recieved_events) > 100): + self.recieved_events.popitem(last=False) + yield event + event = {} + else: + try: + k, v = item.split(b'=', 1) + event[k.decode('ascii')] = v.decode('ascii') + except ValueError: + pass + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + + _port_to_eeprom_mapping = {} + port_to_i2cbus_mapping = { + 0: 12, + 1: 13, + 2: 14, + 3: 15, + 4: 16, + 5: 17, + 6: 18, + 7: 19, + 8: 20, + 9: 21, + 10: 22, + 11: 23, + 12: 24, + 13: 25, + 14: 26, + 15: 27, + 16: 28, + 17: 29, + 18: 30, + 19: 31, + 20: 32, + 21: 33, + 22: 34, + 23: 35, + 24: 36, + 25: 37, + 26: 38, + 27: 39, + 28: 40, + 29: 41, + 30: 42, + 31: 43 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + port_eeprom_path = eeprom_path.format(self.port_to_i2cbus_mapping[x]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + self.phy_port_dict = {} + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + lpmode = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset" + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def _get_port_eeprom_path(self, port_num, devid): + sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" + if devid == self.IDENTITY_EEPROM_ADDR: + return SfpUtilBase._get_port_eeprom_path(self, port_num, devid) + else: + i2c_adapter_id = self._get_port_i2c_adapter_id(port_num) + if i2c_adapter_id is None: + print("Error getting i2c bus num") + return None + + # Get i2c virtual bus path for the sfp + sysfs_sfp_i2c_adapter_path = "%s/i2c-%s" % (sysfs_i2c_adapter_base_path, + str(i2c_adapter_id)) + + # If i2c bus for port does not exist + if not os.path.exists(sysfs_sfp_i2c_adapter_path): + print("Could not find i2c bus %s. Driver not loaded?" % sysfs_sfp_i2c_adapter_path) + return None + + sysfs_sfp_i2c_client_path = "%s/%s-00%s" % (sysfs_sfp_i2c_adapter_path, + str(i2c_adapter_id), + hex(devid)[-2:]) + + # If sfp device is not present on bus, Add it + if not os.path.exists(sysfs_sfp_i2c_client_path): + ret = self._add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid) + if ret != 0: + print("Error adding sfp device") + return None + + sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path + + return sysfs_sfp_i2c_client_eeprom_path + + def get_transceiver_dom_info_dict(self, port_num): + if port_num in self.qsfp_ports: + return SfpUtilBase.get_transceiver_dom_info_dict(self, port_num) + else: + transceiver_dom_info_dict = {} + + offset = 0 + 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 = open(file_path, "rb") + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8472Dom(None, 1) + if sfpd_obj is None: + return None + + dom_temperature_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) + if dom_temperature_raw is not None: + print(dom_temperature_raw) + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + print(dom_temperature_data) + else: + return None + + dom_voltage_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + SFP_VLOT_OFFSET), SFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + print(dom_voltage_raw) + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + else: + return None + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + SFP_CHANNL_MON_OFFSET), SFP_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 None + + 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_change_event(self, timeout=0): + global monitor + port_dict = {} + with SWPSEventMonitor() as monitor: + for event in monitor: + if event['SUBSYSTEM'] == 'swps': + #print('SWPS event. From %s, ACTION %s, IF_TYPE %s, IF_LANE %s' % (event['DEVPATH'], event['ACTION'], event['IF_TYPE'], event['IF_LANE'])) + portname = event['DEVPATH'].split("/")[-1] + rc = re.match(r"port(?P\d+)", portname) + if rc is not None: + if event['ACTION'] == "remove": + remove_num = int(rc.group("num")) + port_dict[remove_num] = "0" + #port_dict[rc.group("num")] = "0" + if event['ACTION'] == "add": + add_num = int(rc.group("num")) + port_dict[add_num] = "1" + #port_dict[rc.group("num")] = "1" + return True, port_dict + return False, {} diff --git a/device/inventec/x86_64-inventec_d6332-r0/pmon_daemon_control.json b/device/inventec/x86_64-inventec_d6332-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..94592fa8cebc --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/inventec/x86_64-inventec_d6332-r0/sensors.conf b/device/inventec/x86_64-inventec_d6332-r0/sensors.conf new file mode 100644 index 000000000000..ecd518a77af9 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6332-r0/sensors.conf @@ -0,0 +1,69 @@ +# libsensors configuration file +chip "ucd90160-*" + ignore temp1 + +chip "pch_haswell-*" + label temp1 "PCH Temperature" + +chip "tmp75-i2c-*-0048" + label temp1 "CPU Board Temperature" + +chip "tmp75-i2c-*-004a" + label temp1 "FrontSide Temperature" + +chip "tmp75-i2c-*-004e" + label temp1 "NearASIC Temperature" + +chip "tmp75-i2c-*-004d" + label temp1 "RearSide Temperature" + +chip "inv_cpld-i2c-*-77" + label fan1 "FanModule1 Front RPM" + label fan2 "FanModule1 Rear RPM" + label fan3 "FanModule2 Front RPM" + label fan4 "FanModule2 Rear RPM" + label fan5 "FanModule3 Front RPM" + label fan6 "FanModule3 Rear RPM" + label fan7 "FanModule4 Front RPM" + label fan8 "FanModule4 Rear RPM" + label fan9 "FanModule5 Front RPM" + label fan10 "FanModule5 Rear RPM" + label pwm1 "FanModule1 PWM (0-255)" + label pwm2 "FanModule2 PWM (0-255)" + label pwm3 "FanModule3 PWM (0-255)" + label pwm4 "FanModule4 PWM (0-255)" + label pwm5 "FanModule5 PWM (0-255)" + label temp1 "ASIC Temperature" + +chip "pmbus-i2c-*-005a" + ignore power3 + ignore curr3 + ignore fan2 + label fan1 "PSU1 Fan RPM" + label temp1 "PSU1 Temperature1" + label temp2 "PSU1 Temperature2" + label temp3 "PSU1 Temperature3" + label in1 "PSU1 Input Voltage" + label curr1 "PSU1 Input Current" + label power1 "PSU1 Input Power" + label in2 "PSU1 Output Voltage" + label curr2 "PSU1 Output Current" + label power2 "PSU1 Output Power" + label pwm1 "PSU1 PWM (0-100)" + +chip "pmbus-i2c-*-005b" + ignore power3 + ignore curr3 + ignore fan2 + label fan1 "PSU2 Fan RPM" + label temp1 "PSU2 Temperature1" + label temp2 "PSU2 Temperature2" + label temp3 "PSU2 Temperature3" + label in1 "PSU2 Input Voltage" + label curr1 "PSU2 Input Current" + label power1 "PSU2 Input Power" + label in2 "PSU2 Output Voltage" + label curr2 "PSU2 Output Current" + label power2 "PSU2 Output Power" + label pwm1 "PSU2 PWM (0-100)" + diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers.json.j2 b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t0.j2 b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..1587625a294e --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t0.j2 @@ -0,0 +1,50 @@ +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,47) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} + {% for port_idx in range(12,19) %} + {% if PORT.append("Ethernet%d" % (port_idx*4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10443264", + "type": "ingress", + "mode": "dynamic", + "xoff": "7335744" + }, + "egress_lossy_pool": { + "size": "8877440", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} + diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t1.j2 b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..1587625a294e --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t1.j2 @@ -0,0 +1,50 @@ +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,47) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} + {% for port_idx in range(12,19) %} + {% if PORT.append("Ethernet%d" % (port_idx*4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10443264", + "type": "ingress", + "mode": "dynamic", + "xoff": "7335744" + }, + "egress_lossy_pool": { + "size": "8877440", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} + diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/pg_profile_lookup.ini b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/pg_profile_lookup.ini new file mode 100644 index 000000000000..7222f8014925 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -4 2288 + 25000 5m 1248 2288 53248 -4 2288 + 40000 5m 1248 2288 66560 -4 2288 + 50000 5m 1248 2288 79872 -4 2288 + 100000 5m 1248 2288 165568 -4 2288 + 10000 40m 1248 2288 37024 -4 2288 + 25000 40m 1248 2288 56160 -4 2288 + 40000 40m 1248 2288 71552 -4 2288 + 50000 40m 1248 2288 85696 -4 2288 + 100000 40m 1248 2288 177632 -4 2288 + 10000 300m 1248 2288 46176 -4 2288 + 25000 300m 1248 2288 79040 -4 2288 + 40000 300m 1248 2288 108160 -4 2288 + 50000 300m 1248 2288 131456 -4 2288 + 100000 300m 1248 2288 268736 -4 2288 diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/port_config.ini b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/port_config.ini new file mode 100755 index 000000000000..aaac478ab8fd --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 1 Ethernet0 0 25000 +Ethernet1 2 Ethernet1 1 25000 +Ethernet2 3 Ethernet2 2 25000 +Ethernet3 4 Ethernet3 3 25000 +Ethernet4 5 Ethernet4 4 25000 +Ethernet5 6 Ethernet5 5 25000 +Ethernet6 7 Ethernet6 6 25000 +Ethernet7 8 Ethernet7 7 25000 +Ethernet8 13 Ethernet8 8 25000 +Ethernet9 14 Ethernet9 9 25000 +Ethernet10 15 Ethernet10 10 25000 +Ethernet11 16 Ethernet11 11 25000 +Ethernet12 21 Ethernet12 12 25000 +Ethernet13 22 Ethernet13 13 25000 +Ethernet14 23 Ethernet14 14 25000 +Ethernet15 24 Ethernet15 15 25000 +Ethernet16 29 Ethernet16 16 25000 +Ethernet17 30 Ethernet17 17 25000 +Ethernet18 31 Ethernet18 18 25000 +Ethernet19 32 Ethernet19 19 25000 +Ethernet20 33 Ethernet20 20 25000 +Ethernet21 34 Ethernet21 21 25000 +Ethernet22 35 Ethernet22 22 25000 +Ethernet23 36 Ethernet23 23 25000 +Ethernet24 41 Ethernet24 24 25000 +Ethernet25 42 Ethernet25 25 25000 +Ethernet26 43 Ethernet26 26 25000 +Ethernet27 44 Ethernet27 27 25000 +Ethernet28 49 Ethernet28 28 25000 +Ethernet29 50 Ethernet29 29 25000 +Ethernet30 51 Ethernet30 30 25000 +Ethernet31 52 Ethernet31 31 25000 +Ethernet32 57 Ethernet32 32 25000 +Ethernet33 58 Ethernet33 33 25000 +Ethernet34 59 Ethernet34 34 25000 +Ethernet35 60 Ethernet35 35 25000 +Ethernet36 61 Ethernet36 36 25000 +Ethernet37 62 Ethernet37 37 25000 +Ethernet38 63 Ethernet38 38 25000 +Ethernet39 64 Ethernet39 39 25000 +Ethernet40 65 Ethernet40 40 25000 +Ethernet41 66 Ethernet41 41 25000 +Ethernet42 67 Ethernet42 42 25000 +Ethernet43 68 Ethernet43 43 25000 +Ethernet44 69 Ethernet44 44 25000 +Ethernet45 70 Ethernet45 45 25000 +Ethernet46 71 Ethernet46 46 25000 +Ethernet47 72 Ethernet47 47 25000 +Ethernet48 85,86,87,88 Ethernet48 48 100000 +Ethernet52 77,78,79,80 Ethernet52 49 100000 +Ethernet56 93,94,95,96 Ethernet56 50 100000 +Ethernet60 97,98,99,100 Ethernet60 51 100000 +Ethernet64 113,114,115,116 Ethernet64 52 100000 +Ethernet68 105,106,107,108 Ethernet68 53 100000 +Ethernet72 121,122,123,124 Ethernet72 54 100000 +Ethernet76 125,126,127,128 Ethernet76 55 100000 diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/qos.json.j2 b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/qos.json.j2 new file mode 100644 index 000000000000..d3cac04f662a --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/qos.json.j2 @@ -0,0 +1,155 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"312000", + "red_min_threshold":"104000", + "yellow_max_threshold":"312000", + "yellow_min_threshold":"104000", + "green_max_threshold": "312000", + "green_min_threshold": "104000" + } + }, + "QUEUE": { + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76|3-4" : { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76|0" : { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76|1" : { + "scheduler" : "[SCHEDULER|scheduler.2]" + } + } +} diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/sai.profile b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/sai.profile new file mode 100755 index 000000000000..f147d44c0b34 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-d6356-48x25G-8x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm new file mode 100644 index 000000000000..089207abd136 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm @@ -0,0 +1,413 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +### fix for sonic +ptp_ts_pll_fref=50000000 +ptp_bs_fref_0=50000000 +ptp_bs_fref_1=50000000 +ifp_inports_support_enable=1 +### end fix + +stable_size=0x5500000 + +core_clock_frequency=1525 +dpp_clock_ratio=2:3 + +oversubscribe_mode=1 +pbmp_xport_xe=0x488787878808787fdfe1e1e1fe1e1e1fe + + +#portmap_65=130:10 + +### Pipeline0, halfpipe 0 (12x25G + 2x100G) +portmap_1=1:25 +portmap_2=2:25 +portmap_3=3:25 +portmap_4=4:25 +portmap_5=5:25 +portmap_6=6:25 +portmap_7=7:25 +portmap_8=8:25 +portmap_13=13:25 +portmap_14=14:25 +portmap_15=15:25 +portmap_16=16:25 +portmap_21=21:25 +portmap_22=22:25 +portmap_23=23:25 +portmap_24=24:25 +portmap_29=29:25 +portmap_30=30:25 +portmap_31=31:25 +portmap_32=32:25 + +### Pipeline0, halfpipe 1 (12x25G + 2x100G) +portmap_33=33:25 +portmap_34=34:25 +portmap_35=35:25 +portmap_36=36:25 +portmap_41=41:25 +portmap_42=42:25 +portmap_43=43:25 +portmap_44=44:25 +portmap_49=49:25 +portmap_50=50:25 +portmap_51=51:25 +portmap_52=52:25 +portmap_57=57:25 +portmap_58=58:25 +portmap_59=59:25 +portmap_60=60:25 +portmap_61=61:25 +portmap_62=62:25 +portmap_63=63:25 +portmap_64=64:25 + +### Pipeline 1 +### First management port +#portmap_66=129:10:m +### Second management port +#portmap_130=128:10:m +### Loopback port +#portmap_131=131:10 + +### Pipeline 1, halfpipe 0 (12x25G + 2x100G) +portmap_67=65:25 +portmap_68=66:25 +portmap_69=67:25 +portmap_70=68:25 +portmap_71=69:25 +portmap_72=70:25 +portmap_73=71:25 +portmap_74=72:25 +portmap_79=77:100 +portmap_87=85:100 +portmap_95=93:100 + +### Pipeline 1, halfpipe 1 (12x25G + 2x100G) +portmap_99=97:100 +portmap_107=105:100 +portmap_115=113:100 +portmap_123=121:100 +portmap_127=125:100 + +l2_mem_entries=32768 +l3_mem_entries=16384 +fpem_mem_entries=16384 +l2xmsg_mode=1 + + + +pdma_descriptor_prefetch_enable=1 + +port_flex_enable=1 + +#dport part +dport_map_port_79=87 +dport_map_port_87=79 +dport_map_port_107=115 +dport_map_port_115=107 + +#Polarity flips after lane swaps +#rx part +#FC1 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x1 + +#FC3 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x1 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 + +#FC5 +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}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x1 + +#FC8 +phy_chain_rx_polarity_flip_physical{33.0}=0x1 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x1 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 + +#FC10 +phy_chain_rx_polarity_flip_physical{41.0}=0x1 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x1 +phy_chain_rx_polarity_flip_physical{44.0}=0x1 + +#FC12 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_rx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x1 + +#FC14 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 + +#FC15 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x1 + +#FC16 +phy_chain_rx_polarity_flip_physical{65.0}=0x1 +phy_chain_rx_polarity_flip_physical{66.0}=0x1 + +#FC17 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x1 +phy_chain_rx_polarity_flip_physical{72.0}=0x1 + +#FC19 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 + +#FC21 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x1 + +#FC23 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 + +#FC24 +phy_chain_rx_polarity_flip_physical{99.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x1 + +#FC26 +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x1 + +#FC28 +phy_chain_rx_polarity_flip_physical{113.0}=0x1 +#phy_chain_rx_polarity_flip_physical{114.0}=0x1 + +#FC30 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{122.0}=0x1 + +#FC31 +phy_chain_rx_polarity_flip_physical{127.0}=0x1 +phy_chain_rx_polarity_flip_physical{128.0}=0x1 + +#tx part +#FC19 +phy_chain_tx_polarity_flip_physical{79.0}=0x1 +phy_chain_tx_polarity_flip_physical{80.0}=0x1 + +#FC21 +phy_chain_tx_polarity_flip_physical{87.0}=0x1 +phy_chain_tx_polarity_flip_physical{88.0}=0x1 + +#FC23 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +phy_chain_tx_polarity_flip_physical{95.0}=0x1 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 + +#FC24 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 + +#FC26 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 + +#FC28 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +phy_chain_tx_polarity_flip_physical{116.0}=0x1 + +#FC30 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x1 + +#FC31 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 + + +phy_chain_rx_lane_map_physical{1.0}=0x1032 +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{5.0}=0x1032 +phy_chain_tx_lane_map_physical{5.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x1032 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x1032 +phy_chain_tx_lane_map_physical{29.0}=0x0123 + +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x0123 +phy_chain_rx_lane_map_physical{41.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x0123 +phy_chain_rx_lane_map_physical{49.0}=0x1032 +phy_chain_tx_lane_map_physical{49.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x1032 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{61.0}=0x0123 + +phy_chain_rx_lane_map_physical{65.0}=0x2301 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{69.0}=0x2301 +phy_chain_tx_lane_map_physical{69.0}=0x3210 + +phy_chain_rx_lane_map_physical{85.0}=0x0213 +phy_chain_tx_lane_map_physical{85.0}=0x3120 +phy_chain_rx_lane_map_physical{77.0}=0x2031 +phy_chain_tx_lane_map_physical{77.0}=0x1302 + +phy_chain_rx_lane_map_physical{93.0}=0x2031 +phy_chain_tx_lane_map_physical{93.0}=0x1302 +phy_chain_rx_lane_map_physical{97.0}=0x0213 +phy_chain_tx_lane_map_physical{97.0}=0x3120 + +phy_chain_rx_lane_map_physical{113.0}=0x1203 +phy_chain_tx_lane_map_physical{113.0}=0x3120 +phy_chain_rx_lane_map_physical{105.0}=0x2031 +phy_chain_tx_lane_map_physical{105.0}=0x1302 + +phy_chain_rx_lane_map_physical{121.0}=0x2031 +phy_chain_tx_lane_map_physical{121.0}=0x1302 +phy_chain_rx_lane_map_physical{125.0}=0x0213 +phy_chain_tx_lane_map_physical{125.0}=0x3120 + +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 + +# EQ/IDriver +# 25G +serdes_preemphasis_1=0x0F4B0A +serdes_preemphasis_2=0x104A0A +serdes_preemphasis_3=0x0E4C0A +serdes_preemphasis_4=0x0E4C0A +serdes_preemphasis_5=0x0D4D0A +serdes_preemphasis_6=0x0D4D0A +serdes_preemphasis_7=0x0D4D0A +serdes_preemphasis_8=0x0D4D0A +serdes_preemphasis_13=0x0C4E0A +serdes_preemphasis_14=0x0D4D0A +serdes_preemphasis_15=0x0B4F0A +serdes_preemphasis_16=0x0C4E0A +serdes_preemphasis_21=0x0A500A +serdes_preemphasis_22=0x0A500A +serdes_preemphasis_23=0x09510A +serdes_preemphasis_24=0x09510A +serdes_preemphasis_29=0x08520A +serdes_preemphasis_30=0x08520A +serdes_preemphasis_31=0x07530A +serdes_preemphasis_32=0x07530A +serdes_preemphasis_33=0x06540A +serdes_preemphasis_34=0x07530A +serdes_preemphasis_35=0x05550A +serdes_preemphasis_36=0x06540A +serdes_preemphasis_41=0x05550A +serdes_preemphasis_42=0x06540A +serdes_preemphasis_43=0x05550A +serdes_preemphasis_44=0x05550A +serdes_preemphasis_49=0x04560A +serdes_preemphasis_50=0x05550A +serdes_preemphasis_51=0x05550A +serdes_preemphasis_52=0x06540A +serdes_preemphasis_57=0x06540A +serdes_preemphasis_58=0x07530A +serdes_preemphasis_59=0x06540A +serdes_preemphasis_60=0x07530A +serdes_preemphasis_61=0x06540A +serdes_preemphasis_62=0x08520A +serdes_preemphasis_63=0x08520A +serdes_preemphasis_64=0x09510A +serdes_preemphasis_67=0x06540A +serdes_preemphasis_68=0x06540A +serdes_preemphasis_69=0x06540A +serdes_preemphasis_70=0x08520A +serdes_preemphasis_71=0x09510A +serdes_preemphasis_72=0x09510A +serdes_preemphasis_73=0x09510A +serdes_preemphasis_74=0x0A500A +serdes_preemphasis_lane0_87=0x07530A +serdes_preemphasis_lane1_87=0x05550A +serdes_preemphasis_lane2_87=0x07530A +serdes_preemphasis_lane3_87=0x05550A +serdes_preemphasis_79=0x05550A +serdes_preemphasis_95=0x07530A +serdes_preemphasis_lane0_99=0x085309 +serdes_preemphasis_lane1_99=0x0B4F0A +serdes_preemphasis_lane2_99=0x085309 +serdes_preemphasis_lane3_99=0x0B4F0A +serdes_preemphasis_115=0x0B4F0A +serdes_preemphasis_107=0x0B4F0A +serdes_preemphasis_123=0x0B4F0A +serdes_preemphasis_127=0x0D4E09 +# 10G + +# interface type +serdes_if_type_1=16 +serdes_if_type_2=16 +serdes_if_type_3=16 +serdes_if_type_4=16 +serdes_if_type_5=16 +serdes_if_type_6=16 +serdes_if_type_7=16 +serdes_if_type_8=16 +serdes_if_type_13=16 +serdes_if_type_14=16 +serdes_if_type_15=16 +serdes_if_type_16=16 +serdes_if_type_21=16 +serdes_if_type_22=16 +serdes_if_type_23=16 +serdes_if_type_24=16 +serdes_if_type_29=16 +serdes_if_type_30=16 +serdes_if_type_31=16 +serdes_if_type_32=16 +serdes_if_type_33=16 +serdes_if_type_34=16 +serdes_if_type_35=16 +serdes_if_type_36=16 +serdes_if_type_41=16 +serdes_if_type_42=16 +serdes_if_type_43=16 +serdes_if_type_44=16 +serdes_if_type_49=16 +serdes_if_type_50=16 +serdes_if_type_51=16 +serdes_if_type_52=16 +serdes_if_type_57=16 +serdes_if_type_58=16 +serdes_if_type_59=16 +serdes_if_type_60=16 +serdes_if_type_61=16 +serdes_if_type_62=16 +serdes_if_type_63=16 +serdes_if_type_64=16 +serdes_if_type_67=16 +serdes_if_type_68=16 +serdes_if_type_69=16 +serdes_if_type_70=16 +serdes_if_type_71=16 +serdes_if_type_72=16 +serdes_if_type_73=16 +serdes_if_type_74=16 +serdes_if_type_87=28 +serdes_if_type_79=28 +serdes_if_type_95=28 +serdes_if_type_99=28 +serdes_if_type_115=28 +serdes_if_type_107=28 +serdes_if_type_123=28 +serdes_if_type_127=28 diff --git a/device/inventec/x86_64-inventec_d6356-r0/custom_led.bin b/device/inventec/x86_64-inventec_d6356-r0/custom_led.bin new file mode 100644 index 000000000000..237c2a1a4c32 Binary files /dev/null and b/device/inventec/x86_64-inventec_d6356-r0/custom_led.bin differ diff --git a/device/inventec/x86_64-inventec_d6356-r0/default_sku b/device/inventec/x86_64-inventec_d6356-r0/default_sku new file mode 100644 index 000000000000..f4c77ebd10f5 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/default_sku @@ -0,0 +1 @@ +INVENTEC-D6356 t1 diff --git a/device/inventec/x86_64-inventec_d6356-r0/installer.conf b/device/inventec/x86_64-inventec_d6356-r0/installer.conf new file mode 100644 index 000000000000..1db64ba02c38 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +VAR_LOG_SIZE=1024 diff --git a/device/inventec/x86_64-inventec_d6356-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d6356-r0/led_proc_init.soc new file mode 100644 index 000000000000..55c82d388da8 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/led_proc_init.soc @@ -0,0 +1,4 @@ +m0 load 0 0x0 /usr/share/sonic/platform/linkscan_led_fw.bin +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/inventec/x86_64-inventec_d6356-r0/linkscan_led_fw.bin b/device/inventec/x86_64-inventec_d6356-r0/linkscan_led_fw.bin new file mode 100644 index 000000000000..e9d763ad98b2 Binary files /dev/null and b/device/inventec/x86_64-inventec_d6356-r0/linkscan_led_fw.bin differ diff --git a/device/inventec/x86_64-inventec_d6356-r0/media_settings.json b/device/inventec/x86_64-inventec_d6356-r0/media_settings.json new file mode 100644 index 000000000000..f688fcb48a08 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/media_settings.json @@ -0,0 +1,707 @@ +{ + "PORT_MEDIA_SETTINGS": { + "0": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x0B3D01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0F4B0A" + } + } + }, + "1": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x0A3C01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x104A0A" + } + } + }, + "2": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x0B3D01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0E4C0A" + } + } + }, + "3": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x083200" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0E4C0A" + } + } + }, + "4": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x0A3D01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0D4D0A" + } + } + }, + "5": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x083400" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0D4D0A" + } + } + }, + "6": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x0A3801" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0D4D0A" + } + } + }, + "7": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x083400" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0D4D0A" + } + } + }, + "8": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x093801" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0C4E0A" + } + } + }, + "9": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x083400" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0D4D0A" + } + } + }, + "10": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x083601" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0B4F0A" + } + } + }, + "11": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x083400" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0C4E0A" + } + } + }, + "12": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x083401" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0A500A" + } + } + }, + "13": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x073200" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0A500A" + } + } + }, + "14": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x083401" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x09510A" + } + } + }, + "15": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x063101" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x09510A" + } + } + }, + "16": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x063401" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x08520A" + } + } + }, + "17": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x063201" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x08520A" + } + } + }, + "18": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x063001" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x07530A" + } + } + }, + "19": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052E00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x07530A" + } + } + }, + "20": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x063001" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x06540A" + } + } + }, + "21": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052E00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x07530A" + } + } + }, + "22": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052E01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x05550A" + } + } + }, + "23": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x062D01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x06540A" + } + } + }, + "24": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x063000" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x05550A" + } + } + }, + "25": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x062D01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x06540A" + } + } + }, + "26": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052C00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x05550A" + } + } + }, + "27": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052C01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x05550A" + } + } + }, + "28": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052C00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x04560A" + } + } + }, + "29": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052C00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x05550A" + } + } + }, + "30": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052C00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x05550A" + } + } + }, + "31": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x062E01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x06540A" + } + } + }, + "32": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052D00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x06540A" + } + } + }, + "33": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x062E01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x07530A" + } + } + }, + "34": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052D00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x06540A" + } + } + }, + "35": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052D00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x07530A" + } + } + }, + "36": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052E00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x06540A" + } + } + }, + "37": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052C01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x08520A" + } + } + }, + "38": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x082E00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x08520A" + } + } + }, + "39": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x062D01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x09510A" + } + } + }, + "40": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x072C01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x06540A" + } + } + }, + "41": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052D00" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x06540A" + } + } + }, + "42": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x063001" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x06540A" + } + } + }, + "43": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052D01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x08520A" + } + } + }, + "44": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x083401" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x09510A" + } + } + }, + "45": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x052D01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x09510A" + } + } + }, + "46": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x093901" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x09510A" + } + } + }, + "47": { + "FINISAR CORP.-FTLX8571D3BCL": { + "preemphasis": { + "lane0":"0x072D01" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0A500A" + } + } + }, + "48": { + "FINISAR CORP-FTL410QE2C": { + "preemphasis": { + "lane0":"0x083101", + "lane1":"0x083201", + "lane2":"0x083001", + "lane3":"0x093001" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x07530A", + "lane1":"0x05550A", + "lane2":"0x07530A", + "lane3":"0x05550A" + } + } + }, + "49": { + "FINISAR CORP-FTL410QE2C": { + "preemphasis": { + "lane0":"0x082E01", + "lane1":"0x083301", + "lane2":"0x083101", + "lane3":"0x093102" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x05550A" + } + } + }, + "50": { + "FINISAR CORP-FTL410QE2C": { + "preemphasis": { + "lane0":"0x082F01", + "lane1":"0x083001", + "lane2":"0x083201", + "lane3":"0x093202" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x07530A" + } + } + }, + "51": { + "FINISAR CORP-FTL410QE2C": { + "preemphasis": { + "lane0":"0x083001", + "lane1":"0x0A3101", + "lane2":"0x083301", + "lane3":"0x093302" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x085309", + "lane1":"0x0B4F0A", + "lane2":"0x085309", + "lane3":"0x0B4F0A" + } + } + }, + "52": { + "FINISAR CORP-FTL410QE2C": { + "preemphasis": { + "lane0":"0x093101", + "lane1":"0x0A3201", + "lane2":"0x0A3402", + "lane3":"0x093402" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0B4F0A" + } + } + }, + "53": { + "FINISAR CORP-FTL410QE2C": { + "preemphasis": { + "lane0":"0x093201", + "lane1":"0x0A3301", + "lane2":"0x093401", + "lane3":"0x093502" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0B4F0A" + } + } + }, + "54": { + "FINISAR CORP-FTL410QE2C": { + "preemphasis": { + "lane0":"0x093101", + "lane1":"0x0A3401", + "lane2":"0x0A3501", + "lane3":"0x093602" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0B4F0A" + } + } + }, + "55": { + "FINISAR CORP-FTL410QE2C": { + "preemphasis": { + "lane0":"0x093201", + "lane1":"0x0A3501", + "lane2":"0x0A3601", + "lane3":"0x093701" + } + }, + "Default": { + "preemphasis": { + "lane0":"0x0D4E09" + } + } + } + } +} + diff --git a/device/inventec/x86_64-inventec_d6356-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d6356-r0/plugins/eeprom.py new file mode 100644 index 000000000000..4c75d0918add --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Inventec d6356 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/2-0055/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/inventec/x86_64-inventec_d6356-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d6356-r0/plugins/psuutil.py new file mode 100755 index 000000000000..ce8d0b321928 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/plugins/psuutil.py @@ -0,0 +1,87 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR = "/sys/class/hwmon/hwmon2/device/" + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + 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 + + if index == 1: + attr_path = "/sys/class/hwmon/hwmon7/in1_input" + else: + attr_path = "/sys/class/hwmon/hwmon8/in1_input" + + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU status + if (attr_value != 0): + 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 + ind = index + attr_file = 'psu' + str(ind) + attr_path = self.PSU_DIR + '/' + attr_file + normal_attr_value = '1:normal' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d6356-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d6356-r0/plugins/sfputil.py new file mode 100755 index 000000000000..d58d1e96b766 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/plugins/sfputil.py @@ -0,0 +1,384 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +# +# INV_FIX-4037 +# (1) Support get_transceiver_change_event. +# Create the SWPSEventMonitor class to handle any kobject event from the SWPS driver. +# (2) Integrated with the optoe driver +# Due to installing the optoe driver to create the i2c topology, +# it needs to overwrite the followings functions which are declared in the sfputilbase.py. +# First, it needs to impore some SFP-related class object +# +try: + import time + import socket + import re + import os + from collections import OrderedDict + from sonic_sfp.sfputilbase import SfpUtilBase + from sonic_sfp.sff8472 import sff8472Dom +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VLOT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 + +NETLINK_KOBJECT_UEVENT = 15 +monitor = None + + +class SWPSEventMonitor(object): + + def __init__(self): + self.recieved_events = OrderedDict() + self.socket = socket.socket( + socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT) + + def start(self): + self.socket.bind((os.getpid(), -1)) + + def stop(self): + self.socket.close() + + def __enter__(self): + self.start() + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.stop() + + def __iter__(self): + global monitor + while True: + for item in monitor.next_events(): + yield item + + def next_events(self): + data = self.socket.recv(16384) + event = {} + for item in data.split(b'\x00'): + if not item: + # check if we have an event and if we already received it + if event and event['SEQNUM'] not in self.recieved_events: + self.recieved_events[event['SEQNUM']] = None + if (len(self.recieved_events) > 100): + self.recieved_events.popitem(last=False) + yield event + event = {} + else: + try: + k, v = item.split(b'=', 1) + event[k.decode('ascii')] = v.decode('ascii') + except ValueError: + pass + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 55 + PORTS_IN_BLOCK = 56 + QSFP_PORT_START = 48 + QSFP_PORT_END = 55 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 22, + 1: 23, + 2: 24, + 3: 25, + 4: 26, + 5: 27, + 6: 28, + 7: 29, + 8: 30, + 9: 31, + 10: 32, + 11: 33, + 12: 34, + 13: 35, + 14: 36, + 15: 37, + 16: 38, + 17: 39, + 18: 40, + 19: 41, + 20: 42, + 21: 43, + 22: 44, + 23: 45, + 24: 46, + 25: 47, + 26: 48, + 27: 49, + 28: 50, + 29: 51, + 30: 52, + 31: 53, + 32: 54, + 33: 55, + 34: 56, + 35: 57, + 36: 58, + 37: 59, + 38: 60, + 39: 61, + 40: 62, + 41: 63, + 42: 64, + 43: 65, + 44: 66, + 45: 67, + 46: 68, + 47: 69, + 48: 14, + 49: 15, + 50: 16, + 51: 17, + 52: 18, + 53: 19, + 54: 20, + 55: 21 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom" + + for x in range(0, 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) + + 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 + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + print("\nError:SFP's don't support this property") + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset" + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + print("\nError:SFP's don't support this property") + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + +# +# INV_FIX-4037 +# (1) Support get_transceiver_change_event. +# Modify get_transceiver_change_event() to listen the SWPS kobject event. +# (2) Integrated with the optoe driver +# Due to installing the optoe driver to create the i2c topology, +# it needs to overwrite the followings functions which are declared in the sfputilbase.py. +# It modified the get_eeprom_dom_raw() and get_transceiver_dom_info_dict(). +# + def get_transceiver_change_event(self): + global monitor + port_dict = {} + with SWPSEventMonitor() as monitor: + for event in monitor: + if event['SUBSYSTEM'] == 'swps': + #print('SWPS event. From %s, ACTION %s, IF_TYPE %s, IF_LANE %s' % (event['DEVPATH'], event['ACTION'], event['IF_TYPE'], event['IF_LANE'])) + portname = event['DEVPATH'].split("/")[-1] + rc = re.match(r"port(?P\d+)", portname) + if rc is not None: + if event['ACTION'] == "remove": + remove_num = int(rc.group("num")) + port_dict[remove_num] = "0" + #port_dict[rc.group("num")] = "0" + if event['ACTION'] == "add": + add_num = int(rc.group("num")) + port_dict[add_num] = "1" + #port_dict[rc.group("num")] = "1" + return True, port_dict + return False, {} + + 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 get_transceiver_dom_info_dict(self, port_num): + if port_num in self.qsfp_ports: + return SfpUtilBase.get_transceiver_dom_info_dict(self, port_num) + else: + transceiver_dom_info_dict = {} + + 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 = open(file_path, "rb") + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8472Dom(None, 1) + if sfpd_obj is None: + return None + + dom_temperature_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + else: + return None + + dom_voltage_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + SFP_VLOT_OFFSET), SFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + else: + return None + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + SFP_CHANNL_MON_OFFSET), SFP_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 None + + 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 diff --git a/device/inventec/x86_64-inventec_d6356-r0/pmon_daemon_control.json b/device/inventec/x86_64-inventec_d6356-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..44bad6494229 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_ledd": true +} + diff --git a/device/inventec/x86_64-inventec_d6356-r0/sensors.conf b/device/inventec/x86_64-inventec_d6356-r0/sensors.conf new file mode 100644 index 000000000000..3a056f7ca99f --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/sensors.conf @@ -0,0 +1,109 @@ +# libsensors configuration file +chip "ucd90160-*" + ignore temp1 + +chip "pch_haswell-*" + label temp1 "PCH Temperature" + +chip "tmp75-i2c-*-0048" + label temp1 "CPU Board Temperature" + +chip "tmp75-i2c-*-004a" + label temp1 "FrontSide Temperature" + +chip "tmp75-i2c-*-004e" + label temp1 "NearASIC Temperature" + +chip "tmp75-i2c-*-004d" + label temp1 "RearSide Temperature" + +chip "inv_cpld-i2c-*-77" + label fan1 "FanModule1 Front RPM" + label fan2 "FanModule1 Rear RPM" + label fan3 "FanModule2 Front RPM" + label fan4 "FanModule2 Rear RPM" + label fan5 "FanModule3 Front RPM" + label fan6 "FanModule3 Rear RPM" + label fan7 "FanModule4 Front RPM" + label fan8 "FanModule4 Rear RPM" + label fan9 "FanModule5 Front RPM" + label fan10 "FanModule5 Rear RPM" + label pwm1 "FanModule1 PWM (0-255)" + label pwm2 "FanModule2 PWM (0-255)" + label pwm3 "FanModule3 PWM (0-255)" + label pwm4 "FanModule4 PWM (0-255)" + label pwm5 "FanModule5 PWM (0-255)" + +chip "pmbus-i2c-*-005b" + ignore power3 + ignore curr3 + label fan1 "PSU1 Fan RPM" + label temp1 "PSU1 Temperature1" + label temp2 "PSU1 Temperature2" + label temp3 "PSU1 Temperature3" + label in1 "PSU1 Input Voltage" + label curr1 "PSU1 Input Current" + label power1 "PSU1 Input Power" + label in2 "PSU1 Output Voltage" + label curr2 "PSU1 Output Current" + label power2 "PSU1 Output Power" + label pwm1 "PSU1 PWM (0-100)" + +chip "pmbus-i2c-*-005a" + ignore power3 + ignore curr3 + label fan1 "PSU2 Fan RPM" + label temp1 "PSU2 Temperature1" + label temp2 "PSU2 Temperature2" + label temp3 "PSU2 Temperature3" + label in1 "PSU2 Input Voltage" + label curr1 "PSU2 Input Current" + label power1 "PSU2 Input Power" + label in2 "PSU2 Output Voltage" + label curr2 "PSU2 Output Current" + label power2 "PSU2 Output Power" + label pwm1 "PSU2 PWM (0-100)" + +chip "inv_psoc-*" + label temp1 "FrontSide Temperature" + label temp2 "FanBoard Temperature" + label temp3 "NearASIC Temperature" + label temp4 "Center Temperature" + + label temp5 "CPU Board Temperature" + label temp6 "ASIC Temperature" + label temp7 "PSU1 Temperature1" + label temp8 "PSU2 Temperature1" + label temp9 "PSU1 Temperature2" + label temp10 "PSU2 Temperature2" + label fan1 "FanModule1 Front RPM" + label fan2 "FanModule1 Rear RPM" + label fan3 "FanModule2 Front RPM" + label fan4 "FanModule2 Rear RPM" + label fan5 "FanModule3 Front RPM" + label fan6 "FanModule3 Rear RPM" + label fan7 "FanModule4 Front RPM" + label fan8 "FanModule4 Rear RPM" + label fan9 "FanModule5 Front RPM" + label fan10 "FanModule5 Rear RPM" + label pwm1 "FanModule1 PWM" + label pwm2 "FanModule2 PWM" + label pwm3 "FanModule3 PWM" + label pwm4 "FanModule4 PWM" + label pwm5 "FanModule5 PWM" + label pwm6 "PSU1 FAN PWM" + label pwm7 "PSU2 FAN PWM" + label fan11 "PSU1 FAN RPM" + label fan12 "PSU2 FAN RPM" + label in1 "PSU1 Input Voltage" + label in2 "PSU2 Input Voltage" + label curr1 "PSU1 Input Current" + label curr2 "PSU2 Input Current" + label power1 "PSU1 Input Power" + label power2 "PSU2 Input Power" + label in3 "PSU1 Output Voltage" + label in4 "PSU2 Output Voltage" + label curr3 "PSU1 Output Current" + label curr4 "PSU2 Output Current" + label power3 "PSU1 Output Power" + label power4 "PSU2 Output Power" diff --git a/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/port_config.ini b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/port_config.ini new file mode 100644 index 000000000000..4af8faabf676 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias +Ethernet0 1 Ethernet0 +Ethernet4 2 Ethernet4 +Ethernet8 3 Ethernet8 +Ethernet12 4 Ethernet12 +Ethernet16 5 Ethernet16 +Ethernet20 6 Ethernet20 +Ethernet24 7 Ethernet24 +Ethernet28 8 Ethernet28 +Ethernet32 13 Ethernet32 +Ethernet36 14 Ethernet36 +Ethernet40 15 Ethernet40 +Ethernet44 16 Ethernet44 +Ethernet48 21 Ethernet48 +Ethernet52 22 Ethernet52 +Ethernet56 23 Ethernet56 +Ethernet60 24 Ethernet60 +Ethernet64 29 Ethernet64 +Ethernet68 30 Ethernet68 +Ethernet72 31 Ethernet72 +Ethernet76 32 Ethernet76 +Ethernet80 33 Ethernet80 +Ethernet84 34 Ethernet84 +Ethernet88 35 Ethernet88 +Ethernet92 36 Ethernet92 +Ethernet96 41 Ethernet96 +Ethernet100 42 Ethernet100 +Ethernet104 43 Ethernet104 +Ethernet108 44 Ethernet108 +Ethernet112 49 Ethernet112 +Ethernet116 50 Ethernet116 +Ethernet120 51 Ethernet120 +Ethernet124 52 Ethernet124 +Ethernet128 57 Ethernet128 +Ethernet132 58 Ethernet132 +Ethernet136 59 Ethernet136 +Ethernet140 60 Ethernet140 +Ethernet144 61 Ethernet144 +Ethernet148 62 Ethernet148 +Ethernet152 63 Ethernet152 +Ethernet156 64 Ethernet156 +Ethernet160 65 Ethernet160 +Ethernet164 66 Ethernet164 +Ethernet168 67 Ethernet168 +Ethernet172 68 Ethernet172 +Ethernet176 69 Ethernet176 +Ethernet180 70 Ethernet180 +Ethernet184 71 Ethernet184 +Ethernet188 72 Ethernet188 +Ethernet192 77,78,79,80 Ethernet192 +Ethernet196 85,86,87,88 Ethernet196 +Ethernet200 93,94,95,96 Ethernet200 +Ethernet204 97,98,99,100 Ethernet204 +Ethernet208 105,106,107,108 Ethernet208 +Ethernet212 113,114,115,116 Ethernet212 +Ethernet216 121,122,123,124 Ethernet216 +Ethernet220 125,126,127,128 Ethernet220 diff --git a/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/sai.profile b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/sai.profile new file mode 100644 index 000000000000..6f0bf54024a7 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-d6556-48x25G-8x100G.config.bcm.inventec +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d6556-r0/installer.conf b/device/inventec/x86_64-inventec_d6556-r0/installer.conf new file mode 100644 index 000000000000..1db64ba02c38 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +VAR_LOG_SIZE=1024 diff --git a/device/inventec/x86_64-inventec_d6556-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d6556-r0/led_proc_init.soc new file mode 100644 index 000000000000..d4c2fde64f9c --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/led_proc_init.soc @@ -0,0 +1,6 @@ +led auto off +led stop +m0 load 0 0x0 /usr/share/sonic/platform/linkscan_led_fw.bin +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/inventec/x86_64-inventec_d6556-r0/minigraph.xml b/device/inventec/x86_64-inventec_d6556-r0/minigraph.xml new file mode 100644 index 000000000000..50b3a05cfcce --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/minigraph.xml @@ -0,0 +1,144 @@ + + + + + + OCPSCH0104001MS + 10.10.1.26 + SONiC-Inventec-d6556 + 10.10.1.25 + 1 + 10 + 3 + + + OCPSCH0104002MS + 10.10.2.26 + SONiC-Inventec-d6556 + 10.10.2.25 + 1 + 10 + 3 + + + + + 64536 + SONiC-Inventec-d6556 + + +
10.10.1.26
+ + +
+ +
10.10.2.26
+ + +
+
+ +
+ + 64542 + OCPSCH0104001MS + + + + 64543 + OCPSCH0104002MS + + +
+
+ + + + + + HostIP + Loopback0 + + 100.0.0.9/32 + + 100.0.0.9/32 + + + + + + + + SONiC-Inventec-d6556 + + + + + + Ethernet0 + 10.10.1.25/30 + + + + Ethernet4 + 10.10.2.25/30 + + + + + + + + + + + + DeviceInterfaceLink + OCPSCH0104001MS + Ethernet24 + SONiC-Inventec-d6556 + Ethernet0 + + + DeviceInterfaceLink + OCPSCH0104002MS + Ethernet24 + SONiC-Inventec-d6556 + Ethernet4 + + + + + SONiC-Inventec-d6556 + INVENTEC-D6556 + + + + + + + SONiC-Inventec-d6556 + + + DhcpResources + + + + + NtpResources + + 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org + + + SyslogResources + + + + + + + + + SONiC-Inventec-d6556 + INVENTEC-D6556 +
diff --git a/device/inventec/x86_64-inventec_d6556-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d6556-r0/plugins/eeprom.py new file mode 100644 index 000000000000..31f847614fb0 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Inventec d7032q28b +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/inventec/x86_64-inventec_d6556-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d6556-r0/plugins/psuutil.py new file mode 100644 index 000000000000..ced851d6c82a --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/plugins/psuutil.py @@ -0,0 +1,84 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR = "/sys/class/hwmon/hwmon1" + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + 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 = 'psoc_psu' + str(index) + '_iout' + attr_path = self.PSU_DIR + '/' + attr_file + + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU status + if (attr_value != 0): + 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 + ind = index-1 + attr_file = 'psu' + str(ind) + attr_path = self.PSU_DIR + '/' + attr_file + normal_attr_value = '0 : normal' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d6556-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d6556-r0/plugins/sfputil.py new file mode 100644 index 000000000000..3cd6c43d7cde --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/plugins/sfputil.py @@ -0,0 +1,211 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 55 + PORTS_IN_BLOCK = 56 + QSFP_PORT_START = 48 + QSFP_PORT_END = 55 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 18, + 1: 19, + 2: 20, + 3: 21, + 4: 22, + 5: 23, + 6: 24, + 7: 25, + 8: 26, + 9: 27, + 10: 28, + 11: 29, + 12: 30, + 13: 31, + 14: 32, + 15: 33, + 16: 34, + 17: 35, + 18: 36, + 19: 37, + 20: 38, + 21: 39, + 22: 40, + 23: 41, + 24: 42, + 25: 43, + 26: 44, + 27: 45, + 28: 46, + 29: 47, + 30: 48, + 31: 49, + 32: 50, + 33: 51, + 34: 52, + 35: 53, + 36: 54, + 37: 55, + 38: 56, + 39: 57, + 40: 58, + 41: 59, + 42: 60, + 43: 61, + 44: 62, + 45: 63, + 46: 64, + 47: 65, + 48: 10, + 49: 11, + 50: 12, + 51: 13, + 52: 14, + 53: 15, + 54: 16, + 55: 17 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom" + + for x in range(0, 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) + + 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 + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + print("\nError:SFP's don't support this property") + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset" + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + print("\nError:SFP's don't support this property") + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True diff --git a/device/inventec/x86_64-inventec_d6556-r0/sensors.conf b/device/inventec/x86_64-inventec_d6556-r0/sensors.conf new file mode 100644 index 000000000000..98a8e59b9158 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6556-r0/sensors.conf @@ -0,0 +1,44 @@ +# libsensors configuration file +chip "inv_psoc-*" + label temp1 "FrontSide Temperature" + label temp2 "FanBoard Temperature" + label temp3 "NearASIC Temperature" + label temp4 "Center Temperature" + + label temp5 "CPU Board Temperature" + label temp6 "ASIC Temperature" + label temp7 "PSU1 Temperature1" + label temp8 "PSU2 Temperature1" + label temp9 "PSU1 Temperature2" + label temp10 "PSU2 Temperature2" + label fan1 "FanModule1 Front RPM" + label fan2 "FanModule1 Rear RPM" + label fan3 "FanModule2 Front RPM" + label fan4 "FanModule2 Rear RPM" + label fan5 "FanModule3 Front RPM" + label fan6 "FanModule3 Rear RPM" + label fan7 "FanModule4 Front RPM" + label fan8 "FanModule4 Rear RPM" + label fan9 "FanModule5 Front RPM" + label fan10 "FanModule5 Rear RPM" + label pwm1 "FanModule1 PWM" + label pwm2 "FanModule2 PWM" + label pwm3 "FanModule3 PWM" + label pwm4 "FanModule4 PWM" + label pwm5 "FanModule5 PWM" + label pwm6 "PSU1 FAN PWM" + label pwm7 "PSU2 FAN PWM" + label fan11 "PSU1 FAN RPM" + label fan12 "PSU2 FAN RPM" + label in1 "PSU1 Input Voltage" + label in2 "PSU2 Input Voltage" + label curr1 "PSU1 Input Current" + label curr2 "PSU2 Input Current" + label power1 "PSU1 Input Power" + label power2 "PSU2 Input Power" + label in3 "PSU1 Output Voltage" + label in4 "PSU2 Output Voltage" + label curr3 "PSU1 Output Current" + label curr4 "PSU2 Output Current" + label power3 "PSU1 Output Power" + label power4 "PSU2 Output Power" diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/buffers.json.j2 b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/buffers.json.j2 new file mode 100644 index 000000000000..864e3bd9870d --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/buffers.json.j2 @@ -0,0 +1,128 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_speed = '100G' %} +{% set default_ports_num = 32 -%} + +{# 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*4)) %}{% 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": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "6000000", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "8072396", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"18432", + "xoff":"40560", + "size":"41808", + "dynamic_th":"-4", + "xon_offset":"2496" + }, + "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":"6000000" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/port_config.ini b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/port_config.ini new file mode 100644 index 000000000000..9b41dd7f6015 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 1,2,3,4 Ethernet0 +Ethernet4 5,6,7,8 Ethernet4 +Ethernet8 9,10,11,12 Ethernet8 +Ethernet12 13,14,15,16 Ethernet12 +Ethernet16 17,18,19,20 Ethernet16 +Ethernet20 21,22,23,24 Ethernet20 +Ethernet24 25,26,27,28 Ethernet24 +Ethernet28 29,30,31,32 Ethernet28 +Ethernet32 33,34,35,36 Ethernet32 +Ethernet36 37,38,39,40 Ethernet36 +Ethernet40 41,42,43,44 Ethernet40 +Ethernet44 45,46,47,48 Ethernet44 +Ethernet48 49,50,51,52 Ethernet48 +Ethernet52 53,54,55,56 Ethernet52 +Ethernet56 57,58,59,60 Ethernet56 +Ethernet60 61,62,63,64 Ethernet60 +Ethernet64 65,66,67,68 Ethernet64 +Ethernet68 69,70,71,72 Ethernet68 +Ethernet72 73,74,75,76 Ethernet72 +Ethernet76 77,78,79,80 Ethernet76 +Ethernet80 81,82,83,84 Ethernet80 +Ethernet84 85,86,87,88 Ethernet84 +Ethernet88 89,90,91,92 Ethernet88 +Ethernet92 93,94,95,96 Ethernet92 +Ethernet96 97,98,99,100 Ethernet96 +Ethernet100 101,102,103,104 Ethernet100 +Ethernet104 105,106,107,108 Ethernet104 +Ethernet108 109,110,111,112 Ethernet108 +Ethernet112 113,114,115,116 Ethernet112 +Ethernet116 117,118,119,120 Ethernet116 +Ethernet120 121,122,123,124 Ethernet120 +Ethernet124 125,126,127,128 Ethernet124 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/qos.json b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/qos.json new file mode 100644 index 000000000000..926911ab59d0 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/qos.json @@ -0,0 +1,143 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"312000", + "red_min_threshold":"104000", + "yellow_max_threshold":"312000", + "yellow_min_threshold":"104000", + "green_max_threshold":"312000", + "green_min_threshold":"104000" + } + }, + "QUEUE": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4" : { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0" : { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|1" : { + "scheduler" : "[SCHEDULER|scheduler.2]" + } + } +} diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/sai.profile b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/sai.profile new file mode 100644 index 000000000000..acd7f9034862 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-d7032q28b-32x100g.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x100g.config.bcm b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x100g.config.bcm new file mode 100644 index 000000000000..613158431634 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x100g.config.bcm @@ -0,0 +1,290 @@ +# Redwood BCM Shell config / all 100G 32 ports + +# Define default OS / SAL +os=unix + +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +#ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +# per Broadcom feedback, no more pbmp_oversubscribe +# pbmp_oversubscribe=0x00003fc000000ff0000003fc000001fe +oversubscribe_mode=1 +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + +# EagleCore ports +portmap_66=129:10 +portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 + +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=113:100 +portmap_107=117:100 +portmap_108=121:100 +portmap_109=125:100 + +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 + +portmap_34=33:100 +portmap_35=37:100 +portmap_36=41:100 +portmap_37=45:100 +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 + +phy_xaui_tx_polarity_flip_ce0=0x8 +phy_xaui_tx_polarity_flip_ce1=0x6 +phy_xaui_tx_polarity_flip_ce2=0x6 +phy_xaui_tx_polarity_flip_ce3=0x6 +phy_xaui_tx_polarity_flip_ce4=0x3 +phy_xaui_tx_polarity_flip_ce5=0x4 +phy_xaui_tx_polarity_flip_ce6=0xc +phy_xaui_tx_polarity_flip_ce7=0x6 +phy_xaui_tx_polarity_flip_ce8=0xc +phy_xaui_tx_polarity_flip_ce9=0x3 +phy_xaui_tx_polarity_flip_ce10=0x3 +phy_xaui_tx_polarity_flip_ce11=0x3 +phy_xaui_tx_polarity_flip_ce12=0x4 +phy_xaui_tx_polarity_flip_ce13=0x1 +phy_xaui_tx_polarity_flip_ce14=0x2 +phy_xaui_tx_polarity_flip_ce15=0x3 +phy_xaui_tx_polarity_flip_ce16=0x2 +phy_xaui_tx_polarity_flip_ce17=0x3 +phy_xaui_tx_polarity_flip_ce18=0x2 +phy_xaui_tx_polarity_flip_ce19=0x8 +phy_xaui_tx_polarity_flip_ce20=0x2 +phy_xaui_tx_polarity_flip_ce21=0x9 +phy_xaui_tx_polarity_flip_ce22=0x8 +phy_xaui_tx_polarity_flip_ce23=0x9 +phy_xaui_tx_polarity_flip_ce24=0x2 +phy_xaui_tx_polarity_flip_ce25=0x4 +phy_xaui_tx_polarity_flip_ce26=0xd +phy_xaui_tx_polarity_flip_ce27=0xc +phy_xaui_tx_polarity_flip_ce28=0x3 +phy_xaui_tx_polarity_flip_ce29=0xc +phy_xaui_tx_polarity_flip_ce30=0xc +phy_xaui_tx_polarity_flip_ce31=0x2 + +phy_xaui_rx_polarity_flip_ce0=0xb +phy_xaui_rx_polarity_flip_ce1=0xc +phy_xaui_rx_polarity_flip_ce2=0xc +phy_xaui_rx_polarity_flip_ce3=0xc +phy_xaui_rx_polarity_flip_ce4=0x1 +phy_xaui_rx_polarity_flip_ce5=0xc +phy_xaui_rx_polarity_flip_ce6=0x4 +phy_xaui_rx_polarity_flip_ce7=0xc +phy_xaui_rx_polarity_flip_ce8=0xb +phy_xaui_rx_polarity_flip_ce9=0x6 +phy_xaui_rx_polarity_flip_ce10=0x1 +phy_xaui_rx_polarity_flip_ce11=0x8 +phy_xaui_rx_polarity_flip_ce12=0xc +phy_xaui_rx_polarity_flip_ce13=0x6 +phy_xaui_rx_polarity_flip_ce14=0x4 +phy_xaui_rx_polarity_flip_ce15=0xe +phy_xaui_rx_polarity_flip_ce16=0xe +phy_xaui_rx_polarity_flip_ce17=0x2 +phy_xaui_rx_polarity_flip_ce18=0x4 +phy_xaui_rx_polarity_flip_ce19=0x6 +phy_xaui_rx_polarity_flip_ce20=0xe +phy_xaui_rx_polarity_flip_ce21=0x3 +phy_xaui_rx_polarity_flip_ce22=0x3 +phy_xaui_rx_polarity_flip_ce23=0x3 +phy_xaui_rx_polarity_flip_ce24=0xb +phy_xaui_rx_polarity_flip_ce25=0xc +phy_xaui_rx_polarity_flip_ce26=0xe +phy_xaui_rx_polarity_flip_ce27=0xc +phy_xaui_rx_polarity_flip_ce28=0xb +phy_xaui_rx_polarity_flip_ce29=0x9 +phy_xaui_rx_polarity_flip_ce30=0x6 +phy_xaui_rx_polarity_flip_ce31=0x9 + +# EQ/iDriver +serdes_preemphasis_1=0x323E00 +serdes_preemphasis_2=0x323E00 +serdes_preemphasis_3=0x323E00 +serdes_preemphasis_4=0x323E00 + +serdes_preemphasis_5=0x323E00 +serdes_preemphasis_6=0x323E00 +serdes_preemphasis_7=0x323E00 +serdes_preemphasis_8=0x323E00 + +serdes_preemphasis_9=0x343C00 +serdes_preemphasis_10=0x343C00 +serdes_preemphasis_11=0x343C00 +serdes_preemphasis_12=0x343C00 + +serdes_preemphasis_13=0x343C00 +serdes_preemphasis_14=0x343C00 +serdes_preemphasis_15=0x343C00 +serdes_preemphasis_16=0x343C00 + +serdes_preemphasis_17=0x323E00 +serdes_preemphasis_18=0x323E00 +serdes_preemphasis_19=0x323E00 +serdes_preemphasis_20=0x323E00 + +serdes_preemphasis_21=0x323E00 +serdes_preemphasis_22=0x323E00 +serdes_preemphasis_23=0x323E00 +serdes_preemphasis_24=0x323E00 + +serdes_preemphasis_25=0x304000 +serdes_preemphasis_26=0x304000 +serdes_preemphasis_27=0x304000 +serdes_preemphasis_28=0x304000 + +serdes_preemphasis_29=0x304000 +serdes_preemphasis_30=0x304000 +serdes_preemphasis_31=0x304000 +serdes_preemphasis_32=0x304000 + +serdes_preemphasis_34=0x2D4300 +serdes_preemphasis_35=0x2D4300 +serdes_preemphasis_36=0x2D4300 +serdes_preemphasis_37=0x2D4300 + +serdes_preemphasis_38=0x2D4300 +serdes_preemphasis_39=0x2D4300 +serdes_preemphasis_40=0x2D4300 +serdes_preemphasis_41=0x2D4300 + +serdes_preemphasis_42=0x2B4500 +serdes_preemphasis_43=0x2B4500 +serdes_preemphasis_44=0x2B4500 +serdes_preemphasis_45=0x2B4500 + +serdes_preemphasis_46=0x2B4500 +serdes_preemphasis_47=0x2B4500 +serdes_preemphasis_48=0x2B4500 +serdes_preemphasis_49=0x2B4500 + +serdes_preemphasis_50=0x2B4500 +serdes_preemphasis_51=0x2B4500 +serdes_preemphasis_52=0x2B4500 +serdes_preemphasis_53=0x2B4500 + +serdes_preemphasis_54=0x284800 +serdes_preemphasis_55=0x284800 +serdes_preemphasis_56=0x284800 +serdes_preemphasis_57=0x284800 + +serdes_preemphasis_58=0x2B4500 +serdes_preemphasis_59=0x2B4500 +serdes_preemphasis_60=0x2B4500 +serdes_preemphasis_61=0x2B4500 + +serdes_preemphasis_62=0x2B4500 +serdes_preemphasis_63=0x2B4500 +serdes_preemphasis_64=0x2B4500 +serdes_preemphasis_65=0x2B4500 + +serdes_preemphasis_68=0x284800 +serdes_preemphasis_69=0x284800 +serdes_preemphasis_70=0x284800 +serdes_preemphasis_71=0x284800 + +serdes_preemphasis_72=0x284800 +serdes_preemphasis_73=0x284800 +serdes_preemphasis_74=0x284800 +serdes_preemphasis_75=0x284800 + +serdes_preemphasis_76=0x284800 +serdes_preemphasis_77=0x284800 +serdes_preemphasis_78=0x284800 +serdes_preemphasis_79=0x284800 + +serdes_preemphasis_80=0x2A4600 +serdes_preemphasis_81=0x2A4600 +serdes_preemphasis_82=0x2A4600 +serdes_preemphasis_83=0x2A4600 + +serdes_preemphasis_84=0x2B4500 +serdes_preemphasis_85=0x2B4500 +serdes_preemphasis_86=0x2B4500 +serdes_preemphasis_87=0x2B4500 + +serdes_preemphasis_88=0x2A4600 +serdes_preemphasis_89=0x2A4600 +serdes_preemphasis_90=0x2A4600 +serdes_preemphasis_91=0x2A4600 + +serdes_preemphasis_92=0x2B4500 +serdes_preemphasis_93=0x2B4500 +serdes_preemphasis_94=0x2B4500 +serdes_preemphasis_95=0x2B4500 + +serdes_preemphasis_96=0x2B4500 +serdes_preemphasis_97=0x2B4500 +serdes_preemphasis_98=0x2B4500 +serdes_preemphasis_99=0x2B4500 + +serdes_preemphasis_102=0x2B4500 +serdes_preemphasis_103=0x2B4500 +serdes_preemphasis_104=0x2B4500 +serdes_preemphasis_105=0x2B4500 + +serdes_preemphasis_106=0x2B4500 +serdes_preemphasis_107=0x2B4500 +serdes_preemphasis_108=0x2B4500 +serdes_preemphasis_109=0x2B4500 + +serdes_preemphasis_110=0x2D4300 +serdes_preemphasis_111=0x2D4300 +serdes_preemphasis_112=0x2D4300 +serdes_preemphasis_113=0x2D4300 + +serdes_preemphasis_114=0x304000 +serdes_preemphasis_115=0x304000 +serdes_preemphasis_116=0x304000 +serdes_preemphasis_117=0x304000 + +serdes_preemphasis_118=0x304000 +serdes_preemphasis_119=0x304000 +serdes_preemphasis_120=0x304000 +serdes_preemphasis_121=0x304000 + +serdes_preemphasis_122=0x304000 +serdes_preemphasis_123=0x304000 +serdes_preemphasis_124=0x304000 +serdes_preemphasis_125=0x304000 + +serdes_preemphasis_126=0x343C00 +serdes_preemphasis_127=0x343C00 +serdes_preemphasis_128=0x343C00 +serdes_preemphasis_129=0x343C00 + +serdes_preemphasis_130=0x343C00 +serdes_preemphasis_131=0x343C00 +serdes_preemphasis_132=0x343C00 +serdes_preemphasis_133=0x343C00 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x40g.config.bcm b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x40g.config.bcm new file mode 100644 index 000000000000..03d0bb06cb06 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/th-d7032q28b-32x40g.config.bcm @@ -0,0 +1,427 @@ +# Redwood BCM Shell config / all 100G 32 ports + +# Define default OS / SAL +os=unix + +l2_mem_entries=8192 +l3_mem_entries=8192 +l3_alpm_enable=2 +#ipv6_lpm_128b_enable=1 +l2xmsg_mode=1 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 +# per Broadcom feedback, no more pbmp_oversubscribe +# pbmp_oversubscribe=0x00003fc000000ff0000003fc000001fe +oversubscribe_mode=1 +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe + +# EagleCore ports +portmap_66=129:10 +portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +portmap_68=65:40 +portmap_69=69:40 +portmap_70=73:40 +portmap_71=77:40 +portmap_72=81:40 +portmap_73=85:40 +portmap_74=89:40 +portmap_75=93:40 + +portmap_102=97:40 +portmap_103=101:40 +portmap_104=105:40 +portmap_105=109:40 +portmap_106=113:40 +portmap_107=117:40 +portmap_108=121:40 +portmap_109=125:40 + +portmap_1=1:40 +portmap_2=5:40 +portmap_3=9:40 +portmap_4=13:40 +portmap_5=17:40 +portmap_6=21:40 +portmap_7=25:40 +portmap_8=29:40 + +portmap_34=33:40 +portmap_35=37:40 +portmap_36=41:40 +portmap_37=45:40 +portmap_38=49:40 +portmap_39=53:40 +portmap_40=57:40 +portmap_41=61:40 + +phy_xaui_tx_polarity_flip_xe0=0x8 +phy_xaui_tx_polarity_flip_xe1=0x6 +phy_xaui_tx_polarity_flip_xe2=0x6 +phy_xaui_tx_polarity_flip_xe3=0x6 +phy_xaui_tx_polarity_flip_xe4=0x3 +phy_xaui_tx_polarity_flip_xe5=0x4 +phy_xaui_tx_polarity_flip_xe6=0xc +phy_xaui_tx_polarity_flip_xe7=0x6 +phy_xaui_tx_polarity_flip_xe8=0xc +phy_xaui_tx_polarity_flip_xe9=0x3 +phy_xaui_tx_polarity_flip_xe10=0x3 +phy_xaui_tx_polarity_flip_xe11=0x3 +phy_xaui_tx_polarity_flip_xe12=0x4 +phy_xaui_tx_polarity_flip_xe13=0x1 +phy_xaui_tx_polarity_flip_xe14=0x2 +phy_xaui_tx_polarity_flip_xe15=0x3 +phy_xaui_tx_polarity_flip_xe16=0x2 +phy_xaui_tx_polarity_flip_xe17=0x3 +phy_xaui_tx_polarity_flip_xe18=0x2 +phy_xaui_tx_polarity_flip_xe19=0x8 +phy_xaui_tx_polarity_flip_xe20=0x2 +phy_xaui_tx_polarity_flip_xe21=0x9 +phy_xaui_tx_polarity_flip_xe22=0x8 +phy_xaui_tx_polarity_flip_xe23=0x9 +phy_xaui_tx_polarity_flip_xe24=0x2 +phy_xaui_tx_polarity_flip_xe25=0x4 +phy_xaui_tx_polarity_flip_xe26=0xd +phy_xaui_tx_polarity_flip_xe27=0xc +phy_xaui_tx_polarity_flip_xe28=0x3 +phy_xaui_tx_polarity_flip_xe29=0xc +phy_xaui_tx_polarity_flip_xe30=0xc +phy_xaui_tx_polarity_flip_xe31=0x2 + +phy_xaui_rx_polarity_flip_xe0=0xb +phy_xaui_rx_polarity_flip_xe1=0xc +phy_xaui_rx_polarity_flip_xe2=0xc +phy_xaui_rx_polarity_flip_xe3=0xc +phy_xaui_rx_polarity_flip_xe4=0x1 +phy_xaui_rx_polarity_flip_xe5=0xc +phy_xaui_rx_polarity_flip_xe6=0x4 +phy_xaui_rx_polarity_flip_xe7=0xc +phy_xaui_rx_polarity_flip_xe8=0xb +phy_xaui_rx_polarity_flip_xe9=0x6 +phy_xaui_rx_polarity_flip_xe10=0x1 +phy_xaui_rx_polarity_flip_xe11=0x8 +phy_xaui_rx_polarity_flip_xe12=0xc +phy_xaui_rx_polarity_flip_xe13=0x6 +phy_xaui_rx_polarity_flip_xe14=0x4 +phy_xaui_rx_polarity_flip_xe15=0xe +phy_xaui_rx_polarity_flip_xe16=0xe +phy_xaui_rx_polarity_flip_xe17=0x2 +phy_xaui_rx_polarity_flip_xe18=0x4 +phy_xaui_rx_polarity_flip_xe19=0x6 +phy_xaui_rx_polarity_flip_xe20=0xe +phy_xaui_rx_polarity_flip_xe21=0x3 +phy_xaui_rx_polarity_flip_xe22=0x3 +phy_xaui_rx_polarity_flip_xe23=0x3 +phy_xaui_rx_polarity_flip_xe24=0xb +phy_xaui_rx_polarity_flip_xe25=0xc +phy_xaui_rx_polarity_flip_xe26=0xe +phy_xaui_rx_polarity_flip_xe27=0xc +phy_xaui_rx_polarity_flip_xe28=0xb +phy_xaui_rx_polarity_flip_xe29=0x9 +phy_xaui_rx_polarity_flip_xe30=0x6 +phy_xaui_rx_polarity_flip_xe31=0x9 + +# EQ/iDriver +# 0 ~ 5 +serdes_preemphasis_1=0x1E5200 +serdes_preemphasis_2=0x1E5200 +serdes_preemphasis_3=0x1E5200 +serdes_preemphasis_4=0x1E5200 +serdes_driver_current_1=0x000001 +serdes_driver_current_2=0x000001 +serdes_driver_current_3=0x000001 +serdes_driver_current_4=0x000001 + +serdes_preemphasis_5=0x1E5200 +serdes_preemphasis_6=0x1E5200 +serdes_preemphasis_7=0x1E5200 +serdes_preemphasis_8=0x1E5200 +serdes_driver_current_5=0x000001 +serdes_driver_current_6=0x000001 +serdes_driver_current_7=0x000001 +serdes_driver_current_8=0x000001 + +serdes_preemphasis_9=0x1E5200 +serdes_preemphasis_10=0x1E5200 +serdes_preemphasis_11=0x1E5200 +serdes_preemphasis_12=0x1E5200 +serdes_driver_current_9=0x000001 +serdes_driver_current_10=0x000001 +serdes_driver_current_11=0x000001 +serdes_driver_current_12=0x000001 + +serdes_preemphasis_13=0x1E5200 +serdes_preemphasis_14=0x1E5200 +serdes_preemphasis_15=0x1E5200 +serdes_preemphasis_16=0x1E5200 +serdes_driver_current_13=0x000001 +serdes_driver_current_14=0x000001 +serdes_driver_current_15=0x000001 +serdes_driver_current_16=0x000001 + +serdes_preemphasis_17=0x1E5200 +serdes_preemphasis_18=0x1E5200 +serdes_preemphasis_19=0x1E5200 +serdes_preemphasis_20=0x1E5200 +serdes_driver_current_17=0x000001 +serdes_driver_current_18=0x000001 +serdes_driver_current_19=0x000001 +serdes_driver_current_20=0x000001 + +serdes_preemphasis_21=0x1E5200 +serdes_preemphasis_22=0x1E5200 +serdes_preemphasis_23=0x1E5200 +serdes_preemphasis_24=0x1E5200 +serdes_driver_current_21=0x000001 +serdes_driver_current_22=0x000001 +serdes_driver_current_23=0x000001 +serdes_driver_current_24=0x000001 + +# 6 ~ 11 +serdes_preemphasis_25=0x1A5600 +serdes_preemphasis_26=0x1A5600 +serdes_preemphasis_27=0x1A5600 +serdes_preemphasis_28=0x1A5600 +serdes_driver_current_25=0x000001 +serdes_driver_current_26=0x000001 +serdes_driver_current_27=0x000001 +serdes_driver_current_28=0x000001 + +serdes_preemphasis_29=0x1A5600 +serdes_preemphasis_30=0x1A5600 +serdes_preemphasis_31=0x1A5600 +serdes_preemphasis_32=0x1A5600 +serdes_driver_current_29=0x000001 +serdes_driver_current_30=0x000001 +serdes_driver_current_31=0x000001 +serdes_driver_current_32=0x000001 + +serdes_preemphasis_34=0x1A5600 +serdes_preemphasis_35=0x1A5600 +serdes_preemphasis_36=0x1A5600 +serdes_preemphasis_37=0x1A5600 +serdes_driver_current_34=0x000001 +serdes_driver_current_35=0x000001 +serdes_driver_current_36=0x000001 +serdes_driver_current_37=0x000001 + +serdes_preemphasis_38=0x1A5600 +serdes_preemphasis_39=0x1A5600 +serdes_preemphasis_40=0x1A5600 +serdes_preemphasis_41=0x1A5600 +serdes_driver_current_38=0x000001 +serdes_driver_current_39=0x000001 +serdes_driver_current_40=0x000001 +serdes_driver_current_41=0x000001 + +serdes_preemphasis_42=0x1A5600 +serdes_preemphasis_43=0x1A5600 +serdes_preemphasis_44=0x1A5600 +serdes_preemphasis_45=0x1A5600 +serdes_driver_current_42=0x000001 +serdes_driver_current_43=0x000001 +serdes_driver_current_44=0x000001 +serdes_driver_current_45=0x000001 + +serdes_preemphasis_46=0x1A5600 +serdes_preemphasis_47=0x1A5600 +serdes_preemphasis_48=0x1A5600 +serdes_preemphasis_49=0x1A5600 +serdes_driver_current_46=0x000001 +serdes_driver_current_47=0x000001 +serdes_driver_current_48=0x000001 +serdes_driver_current_49=0x000001 + +# 12 ~ 13 +serdes_preemphasis_50=0x165A00 +serdes_preemphasis_51=0x165A00 +serdes_preemphasis_52=0x165A00 +serdes_preemphasis_53=0x165A00 +serdes_driver_current_50=0x000000 +serdes_driver_current_51=0x000000 +serdes_driver_current_52=0x000000 +serdes_driver_current_53=0x000000 + +serdes_preemphasis_54=0x165A00 +serdes_preemphasis_55=0x165A00 +serdes_preemphasis_56=0x165A00 +serdes_preemphasis_57=0x165A00 +serdes_driver_current_54=0x000000 +serdes_driver_current_55=0x000000 +serdes_driver_current_56=0x000000 +serdes_driver_current_57=0x000000 + +# 14 ~ 16 +serdes_preemphasis_58=0x125E00 +serdes_preemphasis_59=0x125E00 +serdes_preemphasis_60=0x125E00 +serdes_preemphasis_61=0x125E00 +serdes_driver_current_58=0x000100 +serdes_driver_current_59=0x000100 +serdes_driver_current_60=0x000100 +serdes_driver_current_61=0x000100 + +serdes_preemphasis_62=0x125E00 +serdes_preemphasis_63=0x125E00 +serdes_preemphasis_64=0x125E00 +serdes_preemphasis_65=0x125E00 +serdes_driver_current_62=0x000100 +serdes_driver_current_63=0x000100 +serdes_driver_current_64=0x000100 +serdes_driver_current_65=0x000100 + +serdes_preemphasis_68=0x125E00 +serdes_preemphasis_69=0x125E00 +serdes_preemphasis_70=0x125E00 +serdes_preemphasis_71=0x125E00 +serdes_driver_current_68=0x000100 +serdes_driver_current_69=0x000100 +serdes_driver_current_70=0x000100 +serdes_driver_current_71=0x000100 + +# 17 ~ 21 +serdes_preemphasis_72=0x106000 +serdes_preemphasis_73=0x106000 +serdes_preemphasis_74=0x106000 +serdes_preemphasis_75=0x106000 +serdes_driver_current_72=0x000100 +serdes_driver_current_73=0x000100 +serdes_driver_current_74=0x000100 +serdes_driver_current_75=0x000100 + +serdes_preemphasis_76=0x106000 +serdes_preemphasis_77=0x106000 +serdes_preemphasis_78=0x106000 +serdes_preemphasis_79=0x106000 +serdes_driver_current_76=0x000100 +serdes_driver_current_77=0x000100 +serdes_driver_current_78=0x000100 +serdes_driver_current_79=0x000100 + +serdes_preemphasis_80=0x106000 +serdes_preemphasis_81=0x106000 +serdes_preemphasis_82=0x106000 +serdes_preemphasis_83=0x106000 +serdes_driver_current_80=0x000100 +serdes_driver_current_81=0x000100 +serdes_driver_current_82=0x000100 +serdes_driver_current_83=0x000100 + +serdes_preemphasis_84=0x106000 +serdes_preemphasis_85=0x106000 +serdes_preemphasis_86=0x106000 +serdes_preemphasis_87=0x106000 +serdes_driver_current_84=0x000100 +serdes_driver_current_85=0x000100 +serdes_driver_current_86=0x000100 +serdes_driver_current_87=0x000100 + +serdes_preemphasis_88=0x106000 +serdes_preemphasis_89=0x106000 +serdes_preemphasis_90=0x106000 +serdes_preemphasis_91=0x106000 +serdes_driver_current_88=0x000100 +serdes_driver_current_89=0x000100 +serdes_driver_current_90=0x000100 +serdes_driver_current_91=0x000100 + +# 22 ~ 23 +serdes_preemphasis_92=0x125E00 +serdes_preemphasis_93=0x125E00 +serdes_preemphasis_94=0x125E00 +serdes_preemphasis_95=0x125E00 +serdes_driver_current_92=0x000100 +serdes_driver_current_93=0x000100 +serdes_driver_current_94=0x000100 +serdes_driver_current_95=0x000100 + +serdes_preemphasis_96=0x125E00 +serdes_preemphasis_97=0x125E00 +serdes_preemphasis_98=0x125E00 +serdes_preemphasis_99=0x125E00 +serdes_driver_current_96=0x000100 +serdes_driver_current_97=0x000100 +serdes_driver_current_98=0x000100 +serdes_driver_current_99=0x000100 + +# 24 ~ 25 +serdes_preemphasis_102=0x165A00 +serdes_preemphasis_103=0x165A00 +serdes_preemphasis_104=0x165A00 +serdes_preemphasis_105=0x165A00 +serdes_driver_current_102=0x000000 +serdes_driver_current_103=0x000000 +serdes_driver_current_104=0x000000 +serdes_driver_current_105=0x000000 + +serdes_preemphasis_106=0x165A00 +serdes_preemphasis_107=0x165A00 +serdes_preemphasis_108=0x165A00 +serdes_preemphasis_109=0x165A00 +serdes_driver_current_106=0x000000 +serdes_driver_current_107=0x000000 +serdes_driver_current_108=0x000000 +serdes_driver_current_109=0x000000 + +# 26 ~ 29 +serdes_preemphasis_110=0x1A5600 +serdes_preemphasis_111=0x1A5600 +serdes_preemphasis_112=0x1A5600 +serdes_preemphasis_113=0x1A5600 +serdes_driver_current_110=0x000001 +serdes_driver_current_111=0x000001 +serdes_driver_current_112=0x000001 +serdes_driver_current_113=0x000001 + +serdes_preemphasis_114=0x1A5600 +serdes_preemphasis_115=0x1A5600 +serdes_preemphasis_116=0x1A5600 +serdes_preemphasis_117=0x1A5600 +serdes_driver_current_114=0x000001 +serdes_driver_current_115=0x000001 +serdes_driver_current_116=0x000001 +serdes_driver_current_117=0x000001 + +serdes_preemphasis_118=0x1A5600 +serdes_preemphasis_119=0x1A5600 +serdes_preemphasis_120=0x1A5600 +serdes_preemphasis_121=0x1A5600 +serdes_driver_current_118=0x000001 +serdes_driver_current_119=0x000001 +serdes_driver_current_120=0x000001 +serdes_driver_current_121=0x000001 + +serdes_preemphasis_122=0x1A5600 +serdes_preemphasis_123=0x1A5600 +serdes_preemphasis_124=0x1A5600 +serdes_preemphasis_125=0x1A5600 +serdes_driver_current_122=0x000001 +serdes_driver_current_123=0x000001 +serdes_driver_current_124=0x000001 +serdes_driver_current_125=0x000001 + +# 30 ~ 31 +serdes_preemphasis_126=0x1E5200 +serdes_preemphasis_127=0x1E5200 +serdes_preemphasis_128=0x1E5200 +serdes_preemphasis_129=0x1E5200 +serdes_driver_current_126=0x000001 +serdes_driver_current_127=0x000001 +serdes_driver_current_128=0x000001 +serdes_driver_current_129=0x000001 + +serdes_preemphasis_130=0x1E5200 +serdes_preemphasis_131=0x1E5200 +serdes_preemphasis_132=0x1E5200 +serdes_preemphasis_133=0x1E5200 +serdes_driver_current_130=0x000001 +serdes_driver_current_131=0x000001 +serdes_driver_current_132=0x000001 +serdes_driver_current_133=0x000001 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/default_sku b/device/inventec/x86_64-inventec_d7032q28b-r0/default_sku new file mode 100644 index 000000000000..505f1765e6e5 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/default_sku @@ -0,0 +1 @@ +INVENTEC-D7032Q28B-C32 t1 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/installer.conf b/device/inventec/x86_64-inventec_d7032q28b-r0/installer.conf new file mode 100644 index 000000000000..6b489db6e16f --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 +VAR_LOG_SIZE=1024 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d7032q28b-r0/led_proc_init.soc new file mode 100644 index 000000000000..92423b234498 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/led_proc_init.soc @@ -0,0 +1,136 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=38 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=42 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=41 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=46 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=45 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=50 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=49 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=54 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=53 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=58 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=62 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=61 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60 + +led 0 stop +led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +led 0 start + +led 1 stop +led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +led 1 start diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/eeprom.py new file mode 100644 index 000000000000..31f847614fb0 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Inventec d7032q28b +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/psuutil.py new file mode 100644 index 000000000000..2e058a9e410e --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/psuutil.py @@ -0,0 +1,88 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR = "/sys/bus/i2c/devices/0-0066" + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + 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 + if (index == 1): + ind = 2 + if (index == 2): + ind = 1 + attr_file = 'psu' + str(ind) + '_iout' + attr_path = self.PSU_DIR + '/' + attr_file + + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU status + if (attr_value != 0): + 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 + ind = index-1 + attr_file = 'psu' + str(ind) + attr_path = self.PSU_DIR + '/' + attr_file + normal_attr_value = '0 : normal' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/sfputil.py new file mode 100644 index 000000000000..5321e0c072e8 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/plugins/sfputil.py @@ -0,0 +1,187 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + QSFP_PORT_START = 0 + QSFP_PORT_END = 31 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 22, + 1: 23, + 2: 24, + 3: 25, + 4: 26, + 5: 27, + 6: 28, + 7: 29, + 8: 30, + 9: 31, + 10: 32, + 11: 33, + 12: 34, + 13: 35, + 14: 36, + 15: 37, + 16: 6, + 17: 7, + 18: 8, + 19: 9, + 20: 10, + 21: 11, + 22: 12, + 23: 13, + 24: 14, + 25: 15, + 26: 16, + 27: 17, + 28: 18, + 29: 19, + 30: 20, + 31: 21 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, 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) + + 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 + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset" + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/sensors.conf b/device/inventec/x86_64-inventec_d7032q28b-r0/sensors.conf new file mode 100644 index 000000000000..653900cad36f --- /dev/null +++ b/device/inventec/x86_64-inventec_d7032q28b-r0/sensors.conf @@ -0,0 +1,15 @@ +# libsensors configuration file +chip "inv_psoc-*" + ignore temp3 + ignore temp4 + label temp1 "CPU Board Temperature" + label temp2 "SW Board I Temperature" + label temp5 "SW Board II Temperature" + label temp6 "ASIC Temperature" + label in1 "PSU1 Voltage" + label in2 "PSU2 Voltage" + label curr1 "PSU1 Current" + label curr2 "PSU2 Current" + label power1 "PSU1 Power" + label power2 "PSU2 Power" + diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/buffers.json.j2 b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/buffers.json.j2 new file mode 100644 index 000000000000..ccf463c40526 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/buffers.json.j2 @@ -0,0 +1,128 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '300m' %} +{% set default_speed = '100G' %} +{% 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*4)) %}{% 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": "12766208", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "6000000", + "type": "egress", + "mode": "static" + }, + "egress_lossy_pool": { + "size": "8072396", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "xon":"18432", + "xoff":"40560", + "size":"41808", + "dynamic_th":"-4", + "xon_offset":"2496" + }, + "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":"6000000" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/port_config.ini b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/port_config.ini new file mode 100644 index 000000000000..8b0addcada13 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias +Ethernet0 2 Ethernet0 +Ethernet4 1 Ethernet4 +Ethernet8 4 Ethernet8 +Ethernet12 3 Ethernet12 +Ethernet16 6 Ethernet16 +Ethernet20 5 Ethernet20 +Ethernet24 8 Ethernet24 +Ethernet28 7 Ethernet28 +Ethernet32 10 Ethernet32 +Ethernet36 9 Ethernet36 +Ethernet40 12 Ethernet40 +Ethernet44 11 Ethernet44 +Ethernet48 22 Ethernet48 +Ethernet52 21 Ethernet52 +Ethernet56 24 Ethernet56 +Ethernet60 23 Ethernet60 +Ethernet64 34 Ethernet64 +Ethernet68 33 Ethernet68 +Ethernet72 36 Ethernet72 +Ethernet76 35 Ethernet76 +Ethernet80 38 Ethernet80 +Ethernet84 37 Ethernet84 +Ethernet88 40 Ethernet88 +Ethernet92 39 Ethernet92 +Ethernet96 42 Ethernet96 +Ethernet100 41 Ethernet100 +Ethernet104 44 Ethernet104 +Ethernet108 43 Ethernet108 +Ethernet112 50 Ethernet112 +Ethernet116 49 Ethernet116 +Ethernet120 52 Ethernet120 +Ethernet124 51 Ethernet124 +Ethernet128 54 Ethernet128 +Ethernet132 53 Ethernet132 +Ethernet136 56 Ethernet136 +Ethernet140 55 Ethernet140 +Ethernet144 66 Ethernet144 +Ethernet148 65 Ethernet148 +Ethernet152 68 Ethernet152 +Ethernet156 67 Ethernet156 +Ethernet160 70 Ethernet160 +Ethernet164 69 Ethernet164 +Ethernet168 72 Ethernet168 +Ethernet172 71 Ethernet172 +Ethernet176 82 Ethernet176 +Ethernet180 81 Ethernet180 +Ethernet184 84 Ethernet184 +Ethernet188 83 Ethernet188 +Ethernet192 85,86,87,88 Ethernet192 +Ethernet196 97,98,99,100 Ethernet196 +Ethernet200 105,106,107,108 Ethernet200 +Ethernet204 101,102,103,104 Ethernet204 +Ethernet208 117,118,119,120 Ethernet208 +Ethernet212 109,110,111,112 Ethernet212 diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/qos.json b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/qos.json new file mode 100644 index 000000000000..9949a5903d8b --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/qos.json @@ -0,0 +1,143 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"312000", + "red_min_threshold":"104000", + "yellow_max_threshold":"312000", + "yellow_min_threshold":"104000", + "green_max_threshold":"312000", + "green_min_threshold":"104000" + } + }, + "QUEUE": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212|3-4" : { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212|0" : { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212|1" : { + "scheduler" : "[SCHEDULER|scheduler.2]" + } + } +} diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/sai.profile b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/sai.profile new file mode 100644 index 000000000000..73cbea239694 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-d7054q28b-48x25g-6x100g.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x10g-6x100g.config.bcm b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x10g-6x100g.config.bcm new file mode 100644 index 000000000000..b90ba92a97bc --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x10g-6x100g.config.bcm @@ -0,0 +1,465 @@ +# Cypress BCM Shell config / 10G * 48 ports; 100G * 6 ports + +# Define default OS / SAL +os=unix + +l2_mem_entries=40960 +l3_mem_entries=40960 +fpem_mem_entries=32768 +l2xmsg_mode=1 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 + +## update the hex string based on case ID: 925941 +## 1. type "phy info" then get each hg ports' number +## 2. Set these number as 1 in pbmp_xport_xe and pbmp_oversubscribe +## 130 xe ports, 4 * 32 + 2 +## no more pbmp_oversubscribe +oversubscribe_mode=1 +pbmp_xport_xe=0x3fffffffdffffffff7fffffffdfffffffe + + +# EagleCore ports: 36 & 49 +portmap_66=129:10 +portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +# First 12*4 48 ports config for 10G +# Second 6 ports config for 100G +# For Tomahawk FalconCore: +# Physical ports in FalconCore[0 - 7] must map to logical port[1 - 32] at any order +# Physical ports in FalconCore[8 - 15] must map to logical port[34 - 65] at any order +# Physical ports in FalconCore[16 - 23] must map to logical port[68 - 99] at any order +# Physical ports in FalconCore[24 - 31] must map to logical port[102 - 133] at any order + +## FalconCore[0,1,2,5] +portmap_1=2:10 +portmap_2=1:10 +portmap_3=4:10 +portmap_4=3:10 +portmap_5=6:10 +portmap_6=5:10 +portmap_7=8:10 +portmap_8=7:10 +portmap_9=10:10 +portmap_10=9:10 +portmap_11=12:10 +portmap_12=11:10 +# FC-05 +portmap_13=22:10 +portmap_14=21:10 +portmap_15=24:10 +portmap_16=23:10 + +## FalconCore[8, 9, 10, 12, 13] +portmap_34=34:10 +portmap_35=33:10 +portmap_36=36:10 +portmap_37=35:10 +portmap_38=38:10 +portmap_39=37:10 +portmap_40=40:10 +portmap_41=39:10 +portmap_42=42:10 +portmap_43=41:10 +portmap_44=44:10 +portmap_45=43:10 +# FC-12 & FC-13 +portmap_46=50:10 +portmap_47=49:10 +portmap_48=52:10 +portmap_49=51:10 +portmap_50=54:10 +portmap_51=53:10 +portmap_52=56:10 +portmap_53=55:10 + +## FalconCore[16, 17, 20] +portmap_68=66:10 +portmap_69=65:10 +portmap_70=68:10 +portmap_71=67:10 +portmap_72=70:10 +portmap_73=69:10 +portmap_74=72:10 +portmap_75=71:10 +# FC-20 +portmap_76=82:10 +portmap_77=81:10 +portmap_78=84:10 +portmap_79=83:10 + +# FC-21 (100G) +portmap_80=85:100 + +## FalconCore[24, 25, 26, 27, 29] (100G) +portmap_102=97:100 +portmap_103=105:100 +portmap_104=101:100 +portmap_105=117:100 +portmap_107=109:100 + + + +# FalconCore[0,1,2,5] ports TX polarity flip for 25G +# no polarity reversal + +# FalconCore[8, 9, 10, 12, 13] ports TX polarity flip for 25G +# For Baidu xe20 & xe22; for GA xe21 & xe23 +phy_xaui_tx_polarity_flip_xe20=1 +phy_xaui_tx_polarity_flip_xe22=1 + +# FalconCore[16, 17, 20] ports TX polarity flip for 25G +# no polarity reversal + +# FC-21 for 100G + +# FalconCore[24, 25, 26, 27, 29] ports TX polarity flip for 100G +phy_xaui_tx_polarity_flip_ce1=0xf +phy_xaui_tx_polarity_flip_ce2=0xf + + +# FalconCore[0,1,2,5] ports RX polarity flip for 25G +# no polarity reversal + +# FalconCore[8, 9, 10, 12, 13] ports RX polarity flip for 25G +# no polarity reversal + +# FalconCore[16, 17, 20] ports RX polarity flip for 25G +# no polarity reversal + +# FC-21 for 100G + +# FalconCore[24, 25, 26, 27, 29] ports RX polarity flip for 100G +phy_xaui_rx_polarity_flip_ce2=0xf + + +## Lane swapping +## The HEX value is connection of red line within Falconcore in "Fig 3-4 SFP28 port connection" +# TX - Config A. (FC 0/1/2/16) +# 0x3210 - port 0-11, 36-39 +xgxs_tx_lane_map_xe0=0x3210 +xgxs_tx_lane_map_xe1=0x3210 +xgxs_tx_lane_map_xe2=0x3210 +xgxs_tx_lane_map_xe3=0x3210 +xgxs_tx_lane_map_xe4=0x3210 +xgxs_tx_lane_map_xe5=0x3210 +xgxs_tx_lane_map_xe6=0x3210 +xgxs_tx_lane_map_xe7=0x3210 +xgxs_tx_lane_map_xe8=0x3210 +xgxs_tx_lane_map_xe9=0x3210 +xgxs_tx_lane_map_xe10=0x3210 +xgxs_tx_lane_map_xe11=0x3210 +xgxs_tx_lane_map_xe37=0x3210 +xgxs_tx_lane_map_xe38=0x3210 +xgxs_tx_lane_map_xe39=0x3210 +xgxs_tx_lane_map_xe40=0x3210 + + +# TX - Config B. (FC 5/9/20) +# 0x0123 - port 12-13, 20-23, 44-47 +xgxs_tx_lane_map_xe12=0x0123 +xgxs_tx_lane_map_xe13=0x0123 +xgxs_tx_lane_map_xe14=0x0123 +xgxs_tx_lane_map_xe15=0x0123 +xgxs_tx_lane_map_xe20=0x0123 +xgxs_tx_lane_map_xe21=0x0123 +xgxs_tx_lane_map_xe22=0x0123 +xgxs_tx_lane_map_xe23=0x0123 +xgxs_tx_lane_map_xe45=0x0123 +xgxs_tx_lane_map_xe46=0x0123 +xgxs_tx_lane_map_xe47=0x0123 +xgxs_tx_lane_map_xe48=0x0123 + + +# TX - Config C. (FC 8/10) +# 0x3210 - port 16-19, 24-27 +xgxs_tx_lane_map_xe16=0x3210 +xgxs_tx_lane_map_xe17=0x3210 +xgxs_tx_lane_map_xe18=0x3210 +xgxs_tx_lane_map_xe19=0x3210 +xgxs_tx_lane_map_xe24=0x3210 +xgxs_tx_lane_map_xe25=0x3210 +xgxs_tx_lane_map_xe26=0x3210 +xgxs_tx_lane_map_xe27=0x3210 + + +# TX - Config D. (FC 12/13/17) +# 0x0123 - port 28-35, 40-43 +xgxs_tx_lane_map_xe28=0x0123 +xgxs_tx_lane_map_xe29=0x0123 +xgxs_tx_lane_map_xe30=0x0123 +xgxs_tx_lane_map_xe31=0x0123 +xgxs_tx_lane_map_xe32=0x0123 +xgxs_tx_lane_map_xe33=0x0123 +xgxs_tx_lane_map_xe34=0x0123 +xgxs_tx_lane_map_xe35=0x0123 +xgxs_tx_lane_map_xe41=0x0123 +xgxs_tx_lane_map_xe42=0x0123 +xgxs_tx_lane_map_xe43=0x0123 +xgxs_tx_lane_map_xe44=0x0123 + + + + +# RX - Config A. (FC 0/1/2/16) +# 0x1032 - port 0-11, 36-39 +xgxs_rx_lane_map_xe0=0x1032 +xgxs_rx_lane_map_xe1=0x1032 +xgxs_rx_lane_map_xe2=0x1032 +xgxs_rx_lane_map_xe3=0x1032 +xgxs_rx_lane_map_xe4=0x1032 +xgxs_rx_lane_map_xe5=0x1032 +xgxs_rx_lane_map_xe6=0x1032 +xgxs_rx_lane_map_xe7=0x1032 +xgxs_rx_lane_map_xe8=0x1032 +xgxs_rx_lane_map_xe9=0x1032 +xgxs_rx_lane_map_xe10=0x1032 +xgxs_rx_lane_map_xe11=0x1032 +xgxs_rx_lane_map_xe37=0x1032 +xgxs_rx_lane_map_xe38=0x1032 +xgxs_rx_lane_map_xe39=0x1032 +xgxs_rx_lane_map_xe40=0x1032 + + + +# RX - Config B. (FC 5/9/20) +# 0x1032 - port 12-13, 20-23, 44-47 +xgxs_rx_lane_map_xe12=0x1032 +xgxs_rx_lane_map_xe13=0x1032 +xgxs_rx_lane_map_xe14=0x1032 +xgxs_rx_lane_map_xe15=0x1032 +xgxs_rx_lane_map_xe20=0x1032 +xgxs_rx_lane_map_xe21=0x1032 +xgxs_rx_lane_map_xe22=0x1032 +xgxs_rx_lane_map_xe23=0x1032 +xgxs_rx_lane_map_xe45=0x1032 +xgxs_rx_lane_map_xe46=0x1032 +xgxs_rx_lane_map_xe47=0x1032 +xgxs_rx_lane_map_xe48=0x1032 + + +# RX - Config C. (FC 8/10) +# 0x3210 - port 16-19, 24-27 +xgxs_rx_lane_map_xe16=0x3210 +xgxs_rx_lane_map_xe17=0x3210 +xgxs_rx_lane_map_xe18=0x3210 +xgxs_rx_lane_map_xe19=0x3210 +xgxs_rx_lane_map_xe24=0x3210 +xgxs_rx_lane_map_xe25=0x3210 +xgxs_rx_lane_map_xe26=0x3210 +xgxs_rx_lane_map_xe27=0x3210 + + +# RX - Config D. (FC 12/13/17) +# 0x3210 - port 28-35, 40-43 +xgxs_rx_lane_map_xe28=0x3210 +xgxs_rx_lane_map_xe29=0x3210 +xgxs_rx_lane_map_xe30=0x3210 +xgxs_rx_lane_map_xe31=0x3210 +xgxs_rx_lane_map_xe32=0x3210 +xgxs_rx_lane_map_xe33=0x3210 +xgxs_rx_lane_map_xe34=0x3210 +xgxs_rx_lane_map_xe35=0x3210 +xgxs_rx_lane_map_xe41=0x3210 +xgxs_rx_lane_map_xe42=0x3210 +xgxs_rx_lane_map_xe43=0x3210 +xgxs_rx_lane_map_xe44=0x3210 + + +## Lane swapping for QSFP28 (100G) +## The HEX value is connection of red line within Falconcore in "Fig 3-4 SFP28 port connection" +# TX - Config A. (FC 21/25) +# 0x3210 - port ce0, ce3 +xgxs_tx_lane_map_ce0=0x3210 +xgxs_tx_lane_map_ce3=0x3210 + + +# TX - Config B. (FC 24) +# 0x3210 - port ce1 +xgxs_tx_lane_map_ce1=0x3210 + + +# TX - Config C. (FC 26) +# 0x3210 - port ce2 +xgxs_tx_lane_map_ce2=0x3210 + + +# TX - Config D. (FC 27) +# 0x3210 - ce5 +xgxs_tx_lane_map_ce5=0x3210 + + +# TX - Config E. (FC 29) +# 0x3210 - ce4 +xgxs_tx_lane_map_ce4=0x3210 + + +# RX - Config A. (FC 21/25) +# 0x1032 - port ce0, ce3 +xgxs_rx_lane_map_ce0=0x1032 +xgxs_rx_lane_map_ce3=0x1032 + + +# RX - Config B. (FC 24) +# 0x1032 - port ce1 +xgxs_rx_lane_map_ce1=0x1032 + + +# RX - Config C. (FC 26) +# 0x2301 - port ce2 +xgxs_rx_lane_map_ce2=0x2301 + + +# RX - Config D. (FC 27) +# 0x2301 - ce5 +xgxs_rx_lane_map_ce5=0x2301 + + +# TX - Config E. (FC 29) +# 0x3210 - ce4 +xgxs_rx_lane_map_ce4=0x3210 + +# EQ/iDriver + +# The 1st 16 ports, xe0-xe15 +serdes_preemphasis_1=0x1A5600 +serdes_preemphasis_2=0x1A5600 +serdes_preemphasis_3=0x1A5600 +serdes_preemphasis_4=0x1A5600 +serdes_preemphasis_5=0x1A5600 +serdes_preemphasis_6=0x1A5600 +serdes_preemphasis_7=0x185800 +serdes_preemphasis_8=0x1A5600 +serdes_preemphasis_9=0x185800 +serdes_preemphasis_10=0x185800 +serdes_preemphasis_11=0x165A00 +serdes_preemphasis_12=0x185800 +serdes_preemphasis_13=0x105F01 +serdes_preemphasis_14=0x165A00 +serdes_preemphasis_15=0x105F01 +serdes_preemphasis_16=0x105F01 + +serdes_driver_current_1=0x000001 +serdes_driver_current_2=0x000001 +serdes_driver_current_3=0x000001 +serdes_driver_current_4=0x000001 +serdes_driver_current_5=0x000001 +serdes_driver_current_6=0x000001 +serdes_driver_current_7=0x000001 +serdes_driver_current_8=0x000001 +serdes_driver_current_9=0x000000 +serdes_driver_current_10=0x000001 +serdes_driver_current_11=0x000000 +serdes_driver_current_12=0x000000 +serdes_driver_current_13=0x000000 +serdes_driver_current_14=0x000000 +serdes_driver_current_15=0x000000 +serdes_driver_current_16=0x000000 + +# The 2nd 20 ports, xe16-xe35 +serdes_preemphasis_34=0x105F01 +serdes_preemphasis_35=0x105F01 +serdes_preemphasis_36=0x0E6002 +serdes_preemphasis_37=0x0E6002 +serdes_preemphasis_38=0x0E6002 +serdes_preemphasis_39=0x0E6002 +serdes_preemphasis_40=0x125B03 +serdes_preemphasis_41=0x0E6002 +serdes_preemphasis_42=0x125B03 +serdes_preemphasis_43=0x125B03 +serdes_preemphasis_44=0x125B03 +serdes_preemphasis_45=0x125B03 +serdes_preemphasis_46=0x125B03 +serdes_preemphasis_47=0x125B03 +serdes_preemphasis_48=0x125B03 +serdes_preemphasis_49=0x125B03 +serdes_preemphasis_50=0x125B03 +serdes_preemphasis_51=0x125B03 +serdes_preemphasis_52=0x125B03 +serdes_preemphasis_53=0x125B03 + +serdes_driver_current_34=0x000000 +serdes_driver_current_35=0x000000 +serdes_driver_current_36=0x000000 +serdes_driver_current_37=0x000000 +serdes_driver_current_38=0x000000 +serdes_driver_current_39=0x000000 +serdes_driver_current_40=0x000000 +serdes_driver_current_41=0x000000 +serdes_driver_current_42=0x000000 +serdes_driver_current_43=0x000000 +serdes_driver_current_44=0x000000 +serdes_driver_current_45=0x000000 +serdes_driver_current_46=0x000000 +serdes_driver_current_47=0x000000 +serdes_driver_current_48=0x000000 +serdes_driver_current_49=0x000000 +serdes_driver_current_50=0x000000 +serdes_driver_current_51=0x000000 +serdes_driver_current_52=0x000000 +serdes_driver_current_53=0x000000 + +# The 3rd 12 ports, xe36-xe47 +serdes_preemphasis_68=0x125B03 +serdes_preemphasis_69=0x125B03 +serdes_preemphasis_70=0x125B03 +serdes_preemphasis_71=0x125B03 +serdes_preemphasis_72=0x125B03 +serdes_preemphasis_73=0x125B03 +serdes_preemphasis_74=0x125B03 +serdes_preemphasis_75=0x125B03 +serdes_preemphasis_76=0x105F01 +serdes_preemphasis_77=0x105F01 +serdes_preemphasis_78=0x105F01 +serdes_preemphasis_79=0x105F01 + +serdes_driver_current_68=0x000000 +serdes_driver_current_69=0x000000 +serdes_driver_current_70=0x000000 +serdes_driver_current_71=0x000000 +serdes_driver_current_72=0x000000 +serdes_driver_current_73=0x000000 +serdes_driver_current_74=0x000000 +serdes_driver_current_75=0x000000 +serdes_driver_current_76=0x000000 +serdes_driver_current_77=0x000000 +serdes_driver_current_78=0x000000 +serdes_driver_current_79=0x000000 + +# 6 x 100G ports, expandable to 24 x 25G ports +serdes_preemphasis_80=0x2D4300 +serdes_preemphasis_81=0x2D4300 +serdes_preemphasis_82=0x2D4300 +serdes_preemphasis_83=0x2D4300 + +serdes_preemphasis_102=0x304000 +serdes_preemphasis_103=0x304000 +serdes_preemphasis_104=0x304000 +serdes_preemphasis_105=0x304000 + +serdes_preemphasis_106=0x304000 +serdes_preemphasis_107=0x304000 +serdes_preemphasis_108=0x304000 +serdes_preemphasis_109=0x304000 + +serdes_preemphasis_110=0x304000 +serdes_preemphasis_111=0x304000 +serdes_preemphasis_112=0x304000 +serdes_preemphasis_113=0x304000 + +serdes_preemphasis_114=0x2E360C +serdes_preemphasis_115=0x2E360C +serdes_preemphasis_116=0x2E360C +serdes_preemphasis_117=0x2E360C + +serdes_preemphasis_118=0x2E360C +serdes_preemphasis_119=0x2E360C +serdes_preemphasis_120=0x2E360C +serdes_preemphasis_121=0x2E360C diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x25g-6x100g.config.bcm b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x25g-6x100g.config.bcm new file mode 100644 index 000000000000..ff09305ccbff --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/th-d7054q28b-48x25g-6x100g.config.bcm @@ -0,0 +1,414 @@ +# Cypress BCM Shell config / 25G * 48 ports; 100G * 6 ports + +# Define default OS / SAL +os=unix + +l2_mem_entries=40960 +l3_mem_entries=40960 +fpem_mem_entries=32768 +l2xmsg_mode=1 +mem_cache_enable=0 +parity_correction=0 +parity_enable=0 + +## update the hex string based on case ID: 925941 +## 1. type "phy info" then get each hg ports' number +## 2. Set these number as 1 in pbmp_xport_xe and pbmp_oversubscribe +## 130 xe ports, 4 * 32 + 2 +## no more pbmp_oversubscribe +oversubscribe_mode=1 +pbmp_xport_xe=0x3fffffffdffffffff7fffffffdfffffffe + + +# EagleCore ports: 36 & 49 +portmap_66=129:10 +portmap_100=131:10 + +# Loopback ports +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + +# First 12*4 48 ports config for 25G +# Second 6 ports config for 100G +# For Tomahawk FalconCore: +# Physical ports in FalconCore[0 - 7] must map to logical port[1 - 32] at any order +# Physical ports in FalconCore[8 - 15] must map to logical port[34 - 65] at any order +# Physical ports in FalconCore[16 - 23] must map to logical port[68 - 99] at any order +# Physical ports in FalconCore[24 - 31] must map to logical port[102 - 133] at any order + +## FalconCore[0,1,2,5] +portmap_1=2:25 +portmap_2=1:25 +portmap_3=4:25 +portmap_4=3:25 +portmap_5=6:25 +portmap_6=5:25 +portmap_7=8:25 +portmap_8=7:25 +portmap_9=10:25 +portmap_10=9:25 +portmap_11=12:25 +portmap_12=11:25 +# FC-05 +portmap_13=22:25 +portmap_14=21:25 +portmap_15=24:25 +portmap_16=23:25 + +## FalconCore[8, 9, 10, 12, 13] +portmap_34=34:25 +portmap_35=33:25 +portmap_36=36:25 +portmap_37=35:25 +portmap_38=38:25 +portmap_39=37:25 +portmap_40=40:25 +portmap_41=39:25 +portmap_42=42:25 +portmap_43=41:25 +portmap_44=44:25 +portmap_45=43:25 +# FC-12 & FC-13 +portmap_46=50:25 +portmap_47=49:25 +portmap_48=52:25 +portmap_49=51:25 +portmap_50=54:25 +portmap_51=53:25 +portmap_52=56:25 +portmap_53=55:25 + +## FalconCore[16, 17, 20] +portmap_68=66:25 +portmap_69=65:25 +portmap_70=68:25 +portmap_71=67:25 +portmap_72=70:25 +portmap_73=69:25 +portmap_74=72:25 +portmap_75=71:25 +# FC-20 +portmap_76=82:25 +portmap_77=81:25 +portmap_78=84:25 +portmap_79=83:25 + +# FC-21 (100G) +portmap_80=85:100 + +## FalconCore[24, 25, 26, 27, 29] (100G) +portmap_102=97:100 +portmap_103=105:100 +portmap_104=101:100 +portmap_105=117:100 +portmap_107=109:100 + + + +# FalconCore[0,1,2,5] ports TX polarity flip for 25G +# no polarity reversal + +# FalconCore[8, 9, 10, 12, 13] ports TX polarity flip for 25G +# For Baidu xe20 & xe22; for GA xe21 & xe23 +phy_xaui_tx_polarity_flip_xe20=1 +phy_xaui_tx_polarity_flip_xe22=1 + +# FalconCore[16, 17, 20] ports TX polarity flip for 25G +# no polarity reversal + +# FC-21 for 100G + +# FalconCore[24, 25, 26, 27, 29] ports TX polarity flip for 100G +phy_xaui_tx_polarity_flip_ce1=0xf +phy_xaui_tx_polarity_flip_ce2=0xf + + +# FalconCore[0,1,2,5] ports RX polarity flip for 25G +# no polarity reversal + +# FalconCore[8, 9, 10, 12, 13] ports RX polarity flip for 25G +# no polarity reversal + +# FalconCore[16, 17, 20] ports RX polarity flip for 25G +# no polarity reversal + +# FC-21 for 100G + +# FalconCore[24, 25, 26, 27, 29] ports RX polarity flip for 100G +phy_xaui_rx_polarity_flip_ce2=0xf + + +## Lane swapping +## The HEX value is connection of red line within Falconcore in "Fig 3-4 SFP28 port connection" +# TX - Config A. (FC 0/1/2/16) +# 0x3210 - port 0-11, 36-39 +xgxs_tx_lane_map_xe0=0x3210 +xgxs_tx_lane_map_xe1=0x3210 +xgxs_tx_lane_map_xe2=0x3210 +xgxs_tx_lane_map_xe3=0x3210 +xgxs_tx_lane_map_xe4=0x3210 +xgxs_tx_lane_map_xe5=0x3210 +xgxs_tx_lane_map_xe6=0x3210 +xgxs_tx_lane_map_xe7=0x3210 +xgxs_tx_lane_map_xe8=0x3210 +xgxs_tx_lane_map_xe9=0x3210 +xgxs_tx_lane_map_xe10=0x3210 +xgxs_tx_lane_map_xe11=0x3210 +xgxs_tx_lane_map_xe37=0x3210 +xgxs_tx_lane_map_xe38=0x3210 +xgxs_tx_lane_map_xe39=0x3210 +xgxs_tx_lane_map_xe40=0x3210 + + +# TX - Config B. (FC 5/9/20) +# 0x0123 - port 12-13, 20-23, 44-47 +xgxs_tx_lane_map_xe12=0x0123 +xgxs_tx_lane_map_xe13=0x0123 +xgxs_tx_lane_map_xe14=0x0123 +xgxs_tx_lane_map_xe15=0x0123 +xgxs_tx_lane_map_xe20=0x0123 +xgxs_tx_lane_map_xe21=0x0123 +xgxs_tx_lane_map_xe22=0x0123 +xgxs_tx_lane_map_xe23=0x0123 +xgxs_tx_lane_map_xe45=0x0123 +xgxs_tx_lane_map_xe46=0x0123 +xgxs_tx_lane_map_xe47=0x0123 +xgxs_tx_lane_map_xe48=0x0123 + + +# TX - Config C. (FC 8/10) +# 0x3210 - port 16-19, 24-27 +xgxs_tx_lane_map_xe16=0x3210 +xgxs_tx_lane_map_xe17=0x3210 +xgxs_tx_lane_map_xe18=0x3210 +xgxs_tx_lane_map_xe19=0x3210 +xgxs_tx_lane_map_xe24=0x3210 +xgxs_tx_lane_map_xe25=0x3210 +xgxs_tx_lane_map_xe26=0x3210 +xgxs_tx_lane_map_xe27=0x3210 + + +# TX - Config D. (FC 12/13/17) +# 0x0123 - port 28-35, 40-43 +xgxs_tx_lane_map_xe28=0x0123 +xgxs_tx_lane_map_xe29=0x0123 +xgxs_tx_lane_map_xe30=0x0123 +xgxs_tx_lane_map_xe31=0x0123 +xgxs_tx_lane_map_xe32=0x0123 +xgxs_tx_lane_map_xe33=0x0123 +xgxs_tx_lane_map_xe34=0x0123 +xgxs_tx_lane_map_xe35=0x0123 +xgxs_tx_lane_map_xe41=0x0123 +xgxs_tx_lane_map_xe42=0x0123 +xgxs_tx_lane_map_xe43=0x0123 +xgxs_tx_lane_map_xe44=0x0123 + + + + +# RX - Config A. (FC 0/1/2/16) +# 0x1032 - port 0-11, 36-39 +xgxs_rx_lane_map_xe0=0x1032 +xgxs_rx_lane_map_xe1=0x1032 +xgxs_rx_lane_map_xe2=0x1032 +xgxs_rx_lane_map_xe3=0x1032 +xgxs_rx_lane_map_xe4=0x1032 +xgxs_rx_lane_map_xe5=0x1032 +xgxs_rx_lane_map_xe6=0x1032 +xgxs_rx_lane_map_xe7=0x1032 +xgxs_rx_lane_map_xe8=0x1032 +xgxs_rx_lane_map_xe9=0x1032 +xgxs_rx_lane_map_xe10=0x1032 +xgxs_rx_lane_map_xe11=0x1032 +xgxs_rx_lane_map_xe37=0x1032 +xgxs_rx_lane_map_xe38=0x1032 +xgxs_rx_lane_map_xe39=0x1032 +xgxs_rx_lane_map_xe40=0x1032 + + + +# RX - Config B. (FC 5/9/20) +# 0x1032 - port 12-13, 20-23, 44-47 +xgxs_rx_lane_map_xe12=0x1032 +xgxs_rx_lane_map_xe13=0x1032 +xgxs_rx_lane_map_xe14=0x1032 +xgxs_rx_lane_map_xe15=0x1032 +xgxs_rx_lane_map_xe20=0x1032 +xgxs_rx_lane_map_xe21=0x1032 +xgxs_rx_lane_map_xe22=0x1032 +xgxs_rx_lane_map_xe23=0x1032 +xgxs_rx_lane_map_xe45=0x1032 +xgxs_rx_lane_map_xe46=0x1032 +xgxs_rx_lane_map_xe47=0x1032 +xgxs_rx_lane_map_xe48=0x1032 + + +# RX - Config C. (FC 8/10) +# 0x3210 - port 16-19, 24-27 +xgxs_rx_lane_map_xe16=0x3210 +xgxs_rx_lane_map_xe17=0x3210 +xgxs_rx_lane_map_xe18=0x3210 +xgxs_rx_lane_map_xe19=0x3210 +xgxs_rx_lane_map_xe24=0x3210 +xgxs_rx_lane_map_xe25=0x3210 +xgxs_rx_lane_map_xe26=0x3210 +xgxs_rx_lane_map_xe27=0x3210 + + +# RX - Config D. (FC 12/13/17) +# 0x3210 - port 28-35, 40-43 +xgxs_rx_lane_map_xe28=0x3210 +xgxs_rx_lane_map_xe29=0x3210 +xgxs_rx_lane_map_xe30=0x3210 +xgxs_rx_lane_map_xe31=0x3210 +xgxs_rx_lane_map_xe32=0x3210 +xgxs_rx_lane_map_xe33=0x3210 +xgxs_rx_lane_map_xe34=0x3210 +xgxs_rx_lane_map_xe35=0x3210 +xgxs_rx_lane_map_xe41=0x3210 +xgxs_rx_lane_map_xe42=0x3210 +xgxs_rx_lane_map_xe43=0x3210 +xgxs_rx_lane_map_xe44=0x3210 + + +## Lane swapping for QSFP28 (100G) +## The HEX value is connection of red line within Falconcore in "Fig 3-4 SFP28 port connection" +# TX - Config A. (FC 21/25) +# 0x3210 - port ce0, ce3 +xgxs_tx_lane_map_ce0=0x3210 +xgxs_tx_lane_map_ce3=0x3210 + + +# TX - Config B. (FC 24) +# 0x3210 - port ce1 +xgxs_tx_lane_map_ce1=0x3210 + + +# TX - Config C. (FC 26) +# 0x3210 - port ce2 +xgxs_tx_lane_map_ce2=0x3210 + + +# TX - Config D. (FC 27) +# 0x3210 - ce5 +xgxs_tx_lane_map_ce5=0x3210 + + +# TX - Config E. (FC 29) +# 0x3210 - ce4 +xgxs_tx_lane_map_ce4=0x3210 + + +# RX - Config A. (FC 21/25) +# 0x1032 - port ce0, ce3 +xgxs_rx_lane_map_ce0=0x1032 +xgxs_rx_lane_map_ce3=0x1032 + + +# RX - Config B. (FC 24) +# 0x1032 - port ce1 +xgxs_rx_lane_map_ce1=0x1032 + + +# RX - Config C. (FC 26) +# 0x2301 - port ce2 +xgxs_rx_lane_map_ce2=0x2301 + + +# RX - Config D. (FC 27) +# 0x2301 - ce5 +xgxs_rx_lane_map_ce5=0x2301 + + +# TX - Config E. (FC 29) +# 0x3210 - ce4 +xgxs_rx_lane_map_ce4=0x3210 + +# EQ/iDriver + +# The first 16 ports, xe0-xe15 +serdes_preemphasis_1=0x2E380A +serdes_preemphasis_2=0x2E380A +serdes_preemphasis_3=0x2E380A +serdes_preemphasis_4=0x2E380A +serdes_preemphasis_5=0x2C3A0A +serdes_preemphasis_6=0x2C3A0A +serdes_preemphasis_7=0x2C3A0A +serdes_preemphasis_8=0x2C3A0A +serdes_preemphasis_9=0x323E00 +serdes_preemphasis_10=0x323E00 +serdes_preemphasis_11=0x304000 +serdes_preemphasis_12=0x304000 +serdes_preemphasis_13=0x2D4300 +serdes_preemphasis_14=0x304000 +serdes_preemphasis_15=0x2D4300 +serdes_preemphasis_16=0x2D4300 + +# The 2nd 20 ports, xe16-xe35 +serdes_preemphasis_34=0x2D4300 +serdes_preemphasis_35=0x2D4300 +serdes_preemphasis_36=0x2B4500 +serdes_preemphasis_37=0x2B4500 +serdes_preemphasis_38=0x2B4500 +serdes_preemphasis_39=0x2B4500 +serdes_preemphasis_40=0x2B4500 +serdes_preemphasis_41=0x2B4500 +serdes_preemphasis_42=0x2B4500 +serdes_preemphasis_43=0x2B4500 +serdes_preemphasis_44=0x284800 +serdes_preemphasis_45=0x284800 +serdes_preemphasis_46=0x284800 +serdes_preemphasis_47=0x284800 +serdes_preemphasis_48=0x284800 +serdes_preemphasis_49=0x284800 +serdes_preemphasis_50=0x2B4500 +serdes_preemphasis_51=0x2B4500 +serdes_preemphasis_52=0x284800 +serdes_preemphasis_53=0x284800 + +# The 3rd 12 ports, xe36-xe47 +serdes_preemphasis_68=0x284800 +serdes_preemphasis_69=0x2A4600 +serdes_preemphasis_70=0x2B4500 +serdes_preemphasis_71=0x2A4600 +serdes_preemphasis_72=0x2A4600 +serdes_preemphasis_73=0x2B4500 +serdes_preemphasis_74=0x2B4500 +serdes_preemphasis_75=0x2A4600 +serdes_preemphasis_76=0x2B4500 +serdes_preemphasis_77=0x2B4500 +serdes_preemphasis_78=0x2B4500 +serdes_preemphasis_79=0x2B4500 + +# 6 x 100G ports, expandable to 24 x 25G ports +serdes_preemphasis_80=0x2D4300 +serdes_preemphasis_81=0x2D4300 +serdes_preemphasis_82=0x2D4300 +serdes_preemphasis_83=0x2D4300 + +serdes_preemphasis_102=0x304000 +serdes_preemphasis_103=0x304000 +serdes_preemphasis_104=0x304000 +serdes_preemphasis_105=0x304000 + +serdes_preemphasis_106=0x304000 +serdes_preemphasis_107=0x304000 +serdes_preemphasis_108=0x304000 +serdes_preemphasis_109=0x304000 + +serdes_preemphasis_110=0x304000 +serdes_preemphasis_111=0x304000 +serdes_preemphasis_112=0x304000 +serdes_preemphasis_113=0x304000 + +serdes_preemphasis_114=0x2E360C +serdes_preemphasis_115=0x2E360C +serdes_preemphasis_116=0x2E360C +serdes_preemphasis_117=0x2E360C + +serdes_preemphasis_118=0x2E360C +serdes_preemphasis_119=0x2E360C +serdes_preemphasis_120=0x2E360C +serdes_preemphasis_121=0x2E360C diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/default_sku b/device/inventec/x86_64-inventec_d7054q28b-r0/default_sku new file mode 100644 index 000000000000..3b1520a5e174 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/default_sku @@ -0,0 +1 @@ +INVENTEC-D7054Q28B-S48-Q6 t1 diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/installer.conf b/device/inventec/x86_64-inventec_d7054q28b-r0/installer.conf new file mode 100644 index 000000000000..1db64ba02c38 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +VAR_LOG_SIZE=1024 diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d7054q28b-r0/led_proc_init.soc new file mode 100644 index 000000000000..ceaa9a8e6d5d --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/led_proc_init.soc @@ -0,0 +1,200 @@ +#LED processor initialization for Inventec d7054q28b platform + +led 0 stop +led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 61 67 5C 77 06 02 A0 60 F0 02 00 60 F2 12 00 06 F0 4A 01 71 38 4A 02 27 67 5C 06 F2 28 32 08 67 5C 06 F2 28 32 00 32 01 B7 67 5C 77 44 67 64 67 5C 67 64 67 5C 67 61 67 5C DA 6C 70 4E 86 F0 86 F2 77 1A 12 00 DA 03 70 5A 67 64 67 5C 77 50 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=16 +led 0 start + +led 1 stop +led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 61 67 5C 77 06 02 A0 60 F0 02 00 60 F2 12 00 06 F0 4A 01 71 38 4A 02 27 67 5C 06 F2 28 32 08 67 5C 06 F2 28 32 00 32 01 B7 67 5C 77 44 67 64 67 5C 67 64 67 5C 67 61 67 5C DA 6C 70 4E 86 F0 86 F2 77 1A 12 00 DA 03 70 5A 67 64 67 5C 77 50 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=63 +led 1 start + +# Set per port speed config of LED Color register +# For Invnetec Cypress platform, +# If we want to set 10G speed per port, We need to set amber color light, so use cmd "setreg CMIC_LEDUP0_DATA_RAM(160) 0x04". +# If we want to set 25G ( or up ) speed per port, we need to set green color light, so use cmd "setreg CMIC_LEDUP0_DATA_RAM(160) 0x00". + +setreg CMIC_LEDUP0_DATA_RAM(160) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(161) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(162) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(163) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(164) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(165) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(166) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(167) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(168) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(169) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(170) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(171) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(172) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(173) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(174) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(175) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(176) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(177) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(178) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(179) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(180) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(181) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(182) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(183) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(184) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(185) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(186) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(187) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(188) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(189) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(190) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(191) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(192) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(193) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(194) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(195) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(196) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(197) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(198) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(199) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(200) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(201) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(202) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(203) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(204) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(205) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(206) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(207) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(208) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(209) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(210) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(211) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(212) 0x00 +setreg CMIC_LEDUP0_DATA_RAM(213) 0x00 + +age 150 + diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/eeprom.py new file mode 100644 index 000000000000..31f847614fb0 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Inventec d7032q28b +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/psuutil.py new file mode 100644 index 000000000000..162e240bae35 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/psuutil.py @@ -0,0 +1,84 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR = "/sys/bus/i2c/devices/0-0066" + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + 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 = 'psoc_psu' + str(index) + '_iout' + attr_path = self.PSU_DIR + '/' + attr_file + + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU status + if (attr_value != 0): + 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 + ind = index-1 + attr_file = 'psu' + str(ind) + attr_path = self.PSU_DIR + '/' + attr_file + normal_attr_value = '0 : normal' + attr_value = self.get_attr_value(attr_path) + if (attr_value != 'ERR'): + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/sfputil.py new file mode 100755 index 000000000000..93baaa88ac3e --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/plugins/sfputil.py @@ -0,0 +1,217 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 53 + PORTS_IN_BLOCK = 54 + QSFP_PORT_START = 48 + QSFP_PORT_END = 53 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 11, + 1: 10, + 2: 13, + 3: 12, + 4: 15, + 5: 14, + 6: 17, + 7: 16, + 8: 19, + 9: 18, + 10: 21, + 11: 20, + 12: 23, + 13: 22, + 14: 25, + 15: 24, + 16: 27, + 17: 26, + 18: 29, + 19: 28, + 20: 31, + 21: 30, + 22: 33, + 23: 32, + 24: 35, + 25: 34, + 26: 37, + 27: 36, + 28: 39, + 29: 38, + 30: 41, + 31: 40, + 32: 43, + 33: 42, + 34: 45, + 35: 44, + 36: 47, + 37: 46, + 38: 49, + 39: 48, + 40: 51, + 41: 50, + 42: 53, + 43: 52, + 44: 55, + 45: 54, + 46: 57, + 47: 56, + 48: 59, + 49: 58, + 50: 61, + 51: 60, + 52: 63, + 53: 62 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom" + + for x in range(0, 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) + + 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 + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + print("\nError:SFP's don't support this property") + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset" + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + print("\nError:SFP's don't support this property") + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/sensors.conf b/device/inventec/x86_64-inventec_d7054q28b-r0/sensors.conf new file mode 100644 index 000000000000..b3fd61236c9e --- /dev/null +++ b/device/inventec/x86_64-inventec_d7054q28b-r0/sensors.conf @@ -0,0 +1,44 @@ +# libsensors configuration file +chip "inv_psoc-*" + label temp1 "FrontSide Temperature" + label temp2 "FanBoard Temperature" + label temp3 "NearASIC Temperature" + label temp4 "NearPSU Temperature" + label temp5 "CPU Board Temperature" + label temp6 "ASIC Temperature" + label temp7 "PSU1 Temperature1" + label temp8 "PSU2 Temperature1" + label temp9 "PSU1 Temperature2" + label temp10 "PSU2 Temperature2" + label fan1 "FanModule1 Front RPM" + label fan2 "FanModule1 Rear RPM" + label fan3 "FanModule2 Front RPM" + label fan4 "FanModule2 Rear RPM" + label fan5 "FanModule3 Front RPM" + label fan6 "FanModule3 Rear RPM" + label fan7 "FanModule4 Front RPM" + label fan8 "FanModule4 Rear RPM" + label fan9 "FanModule5 Front RPM" + label fan10 "FanModule5 Rear RPM" + label pwm1 "FanModule1 PWM" + label pwm2 "FanModule2 PWM" + label pwm3 "FanModule3 PWM" + label pwm4 "FanModule4 PWM" + label pwm5 "FanModule5 PWM" + label pwm6 "PSU1 FAN PWM" + label pwm7 "PSU2 FAN PWM" + label fan11 "PSU1 FAN RPM" + label fan12 "PSU2 FAN RPM" + label in1 "PSU1 Input Voltage" + label in2 "PSU2 Input Voltage" + label curr1 "PSU1 Input Current" + label curr2 "PSU2 Input Current" + label power1 "PSU1 Input Power" + label power2 "PSU2 Input Power" + label in3 "PSU1 Output Voltage" + label in4 "PSU2 Output Voltage" + label curr3 "PSU1 Output Current" + label curr4 "PSU2 Output Current" + label power3 "PSU1 Output Power" + label power4 "PSU2 Output Power" + diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/port_config.ini b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/port_config.ini new file mode 100644 index 000000000000..3fc6db4c8198 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias +Ethernet0 9,10,11,12 Ethernet0 +Ethernet4 1,2,3,4 Ethernet4 +Ethernet8 25,26,27,28 Ethernet8 +Ethernet12 17,18,19,20 Ethernet12 +Ethernet16 41,42,43,44 Ethernet16 +Ethernet20 33,34,35,36 Ethernet20 +Ethernet24 57,58,59,60 Ethernet24 +Ethernet28 49,50,51,52 Ethernet28 +Ethernet32 73,74,75,76 Ethernet32 +Ethernet36 65,66,67,68 Ethernet36 +Ethernet40 89,90,91,92 Ethernet40 +Ethernet44 81,82,83,84 Ethernet44 +Ethernet48 105,106,107,108 Ethernet48 +Ethernet52 97,98,99,100 Ethernet52 +Ethernet56 121,122,123,124 Ethernet56 +Ethernet60 113,114,115,116 Ethernet60 +Ethernet64 137,138,139,140 Ethernet64 +Ethernet68 129,130,131,132 Ethernet68 +Ethernet72 153,154,155,156 Ethernet72 +Ethernet76 145,146,147,148 Ethernet76 +Ethernet80 169,170,171,172 Ethernet80 +Ethernet84 161,162,163,164 Ethernet84 +Ethernet88 185,186,187,188 Ethernet88 +Ethernet92 177,178,179,180 Ethernet92 +Ethernet96 201,202,203,204 Ethernet96 +Ethernet100 193,194,195,196 Ethernet100 +Ethernet104 217,218,219,220 Ethernet104 +Ethernet108 209,210,211,212 Ethernet108 +Ethernet112 233,234,235,236 Ethernet112 +Ethernet116 225,226,227,228 Ethernet116 +Ethernet120 249,250,251,252 Ethernet120 +Ethernet124 241,242,243,244 Ethernet124 +Ethernet128 13,14,15,16 Ethernet128 +Ethernet132 5,6,7,8 Ethernet132 +Ethernet136 29,30,31,32 Ethernet136 +Ethernet140 21,22,23,24 Ethernet140 +Ethernet144 45,46,47,48 Ethernet144 +Ethernet148 37,38,39,40 Ethernet148 +Ethernet152 61,62,63,64 Ethernet152 +Ethernet156 53,54,55,56 Ethernet156 +Ethernet160 77,78,79,80 Ethernet160 +Ethernet164 69,70,71,72 Ethernet164 +Ethernet168 93,94,95,96 Ethernet168 +Ethernet172 85,86,87,88 Ethernet172 +Ethernet176 109,110,111,112 Ethernet176 +Ethernet180 101,102,103,104 Ethernet180 +Ethernet184 125,126,127,128 Ethernet184 +Ethernet188 117,118,119,120 Ethernet188 +Ethernet192 141,142,143,144 Ethernet192 +Ethernet196 133,134,135,136 Ethernet196 +Ethernet200 157,158,159,160 Ethernet200 +Ethernet204 149,150,151,152 Ethernet204 +Ethernet208 173,174,175,176 Ethernet208 +Ethernet212 165,166,167,168 Ethernet212 +Ethernet216 189,190,191,192 Ethernet216 +Ethernet220 181,182,183,184 Ethernet220 +Ethernet224 205,206,207,208 Ethernet224 +Ethernet228 197,198,199,200 Ethernet228 +Ethernet232 221,222,223,224 Ethernet232 +Ethernet236 213,214,215,216 Ethernet236 +Ethernet240 237,238,239,240 Ethernet240 +Ethernet244 229,230,231,232 Ethernet244 +Ethernet248 253,254,255,256 Ethernet248 +Ethernet252 245,246,247,248 Ethernet252 diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/sai.profile b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/sai.profile new file mode 100644 index 000000000000..74c0e88255c0 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-d7264q28b-64x100g.config.bcm +SAI_NUM_ECMP_MEMBERS=32 diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm new file mode 100644 index 000000000000..a7eaa1d6ac59 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm @@ -0,0 +1,910 @@ +# Sequoia BCM Shell config / 100G * 64 ports + +core_clock_frequency=1700 +dpp_clock_ratio=2:3 +load_firmware=1 +# EagleCore ports: xe0 & xe1 +portmap_66=257:10 +portmap_100=259:10 + +# Loopback ports +portmap_33=260:10 +portmap_67=261:10 +portmap_101=262:10 +portmap_135=263:10 + +# 64 ports config for 100G +# For Tomahawk FalconCore: +#Physical ports in FalconCore[0-15] must map to logical port[1-32] at any order +#Physical ports in FalconCore[16-31] must map to logical port[34-65] at any order +#Physical ports in FalconCore[32-47] must map to logical port[68-99] at any order +#Physical ports in FalconCore[48-63] must map to logical port[102-133] at any order + +## FalconCore[0-15] +portmap_1=9:100 +portmap_2=1:100 +portmap_3=13:100 +portmap_4=5:100 +portmap_5=25:100 +portmap_6=17:100 +portmap_7=29:100 +portmap_8=21:100 +portmap_9=41:100 +portmap_10=33:100 +portmap_11=45:100 +portmap_12=37:100 +portmap_13=57:100 +portmap_14=49:100 +portmap_15=61:100 +portmap_16=53:100 + +## FalconCore[16-31] +portmap_34=73:100 +portmap_35=65:100 +portmap_36=77:100 +portmap_37=69:100 +portmap_38=89:100 +portmap_39=81:100 +portmap_40=93:100 +portmap_41=85:100 +portmap_42=105:100 +portmap_43=97:100 +portmap_44=109:100 +portmap_45=101:100 +portmap_46=121:100 +portmap_47=113:100 +portmap_48=125:100 +portmap_49=117:100 + +## FalconCore[32-47] +portmap_68=137:100 +portmap_69=129:100 +portmap_70=141:100 +portmap_71=133:100 +portmap_72=153:100 +portmap_73=145:100 +portmap_74=157:100 +portmap_75=149:100 +portmap_76=169:100 +portmap_77=161:100 +portmap_78=173:100 +portmap_79=165:100 +portmap_80=185:100 +portmap_81=177:100 +portmap_82=189:100 +portmap_83=181:100 + +## FalconCore[48-63] +portmap_102=201:100 +portmap_103=193:100 +portmap_104=205:100 +portmap_105=197:100 +portmap_106=217:100 +portmap_107=209:100 +portmap_108=221:100 +portmap_109=213:100 +portmap_110=233:100 +portmap_111=225:100 +portmap_112=237:100 +portmap_113=229:100 +portmap_114=249:100 +portmap_115=241:100 +portmap_116=253:100 +portmap_117=245:100 + +pbmp_xport_xe=0x3FFFD0000FFFF40003FFFC0001FFFE +oversubscribe_mode=1 +l2_mem_entries=73728 +l3_mem_entries=73728 +fpem_mem_entries=65536 +l2xmsg_mode=1 + +## FalconCore [0-15] port TX Lane Swapping +phy_chain_tx_lane_map_physical{1.0}=0x3201 +phy_chain_tx_lane_map_physical{5.0}=0x3210 +phy_chain_tx_lane_map_physical{9.0}=0x2301 +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_tx_lane_map_physical{17.0}=0x3201 +phy_chain_tx_lane_map_physical{21.0}=0x3201 +phy_chain_tx_lane_map_physical{25.0}=0x3201 +phy_chain_tx_lane_map_physical{29.0}=0x3210 +phy_chain_tx_lane_map_physical{33.0}=0x3201 +phy_chain_tx_lane_map_physical{37.0}=0x3210 +phy_chain_tx_lane_map_physical{41.0}=0x3210 +phy_chain_tx_lane_map_physical{45.0}=0x3210 +phy_chain_tx_lane_map_physical{49.0}=0x3201 +phy_chain_tx_lane_map_physical{53.0}=0x3210 +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_lane_map_physical{61.0}=0x3210 + + +## FalconCore [16-31] port TX Lane Swapping +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{69.0}=0x3201 +phy_chain_tx_lane_map_physical{73.0}=0x3210 +phy_chain_tx_lane_map_physical{77.0}=0x3210 +phy_chain_tx_lane_map_physical{81.0}=0x3210 +phy_chain_tx_lane_map_physical{85.0}=0x3210 +phy_chain_tx_lane_map_physical{89.0}=0x3210 +phy_chain_tx_lane_map_physical{93.0}=0x3210 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_tx_lane_map_physical{101.0}=0x2310 +phy_chain_tx_lane_map_physical{105.0}=0x2310 +phy_chain_tx_lane_map_physical{109.0}=0x3210 +phy_chain_tx_lane_map_physical{113.0}=0x3210 +phy_chain_tx_lane_map_physical{117.0}=0x2310 +phy_chain_tx_lane_map_physical{121.0}=0x2310 +phy_chain_tx_lane_map_physical{125.0}=0x3210 + + +## FalconCore [32-47] port TX Lane Swapping +phy_chain_tx_lane_map_physical{129.0}=0x2301 +phy_chain_tx_lane_map_physical{133.0}=0x3210 +phy_chain_tx_lane_map_physical{137.0}=0x2301 +phy_chain_tx_lane_map_physical{141.0}=0x3210 +phy_chain_tx_lane_map_physical{145.0}=0x2301 +phy_chain_tx_lane_map_physical{149.0}=0x3210 +phy_chain_tx_lane_map_physical{153.0}=0x3210 +phy_chain_tx_lane_map_physical{157.0}=0x3210 +phy_chain_tx_lane_map_physical{161.0}=0x2310 +phy_chain_tx_lane_map_physical{165.0}=0x2310 +phy_chain_tx_lane_map_physical{169.0}=0x2310 +phy_chain_tx_lane_map_physical{173.0}=0x3210 +phy_chain_tx_lane_map_physical{177.0}=0x3210 +phy_chain_tx_lane_map_physical{181.0}=0x2310 +phy_chain_tx_lane_map_physical{185.0}=0x3210 +phy_chain_tx_lane_map_physical{189.0}=0x2310 + + +## FalconCore [48-63] port TX Lane Swapping +phy_chain_tx_lane_map_physical{193.0}=0x2310 +phy_chain_tx_lane_map_physical{197.0}=0x2310 +phy_chain_tx_lane_map_physical{201.0}=0x2310 +phy_chain_tx_lane_map_physical{205.0}=0x2310 +phy_chain_tx_lane_map_physical{209.0}=0x3210 +phy_chain_tx_lane_map_physical{213.0}=0x2310 +phy_chain_tx_lane_map_physical{217.0}=0x3210 +phy_chain_tx_lane_map_physical{221.0}=0x2301 +phy_chain_tx_lane_map_physical{225.0}=0x3210 +phy_chain_tx_lane_map_physical{229.0}=0x2310 +phy_chain_tx_lane_map_physical{233.0}=0x2310 +phy_chain_tx_lane_map_physical{237.0}=0x1023 +phy_chain_tx_lane_map_physical{241.0}=0x3210 +phy_chain_tx_lane_map_physical{245.0}=0x2310 +phy_chain_tx_lane_map_physical{249.0}=0x3210 +phy_chain_tx_lane_map_physical{253.0}=0x2310 + +## FalconCore [0-15] port RX Lane Swapping +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_rx_lane_map_physical{5.0}=0x3210 +phy_chain_rx_lane_map_physical{9.0}=0x3210 +phy_chain_rx_lane_map_physical{13.0}=0x3210 +phy_chain_rx_lane_map_physical{17.0}=0x2310 +phy_chain_rx_lane_map_physical{21.0}=0x0213 +phy_chain_rx_lane_map_physical{25.0}=0x2310 +phy_chain_rx_lane_map_physical{29.0}=0x3210 +phy_chain_rx_lane_map_physical{33.0}=0x3210 +phy_chain_rx_lane_map_physical{37.0}=0x3210 +phy_chain_rx_lane_map_physical{41.0}=0x3210 +phy_chain_rx_lane_map_physical{45.0}=0x3210 +phy_chain_rx_lane_map_physical{49.0}=0x3210 +phy_chain_rx_lane_map_physical{53.0}=0x3210 +phy_chain_rx_lane_map_physical{57.0}=0x3210 +phy_chain_rx_lane_map_physical{61.0}=0x3210 + + +## FalconCore [16-31] port RX Lane Swapping +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_rx_lane_map_physical{77.0}=0x3210 +phy_chain_rx_lane_map_physical{81.0}=0x3210 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{89.0}=0x3210 +phy_chain_rx_lane_map_physical{93.0}=0x3210 +phy_chain_rx_lane_map_physical{97.0}=0x3210 +phy_chain_rx_lane_map_physical{101.0}=0x3201 +phy_chain_rx_lane_map_physical{105.0}=0x3210 +phy_chain_rx_lane_map_physical{109.0}=0x3210 +phy_chain_rx_lane_map_physical{113.0}=0x3210 +phy_chain_rx_lane_map_physical{117.0}=0x3210 +phy_chain_rx_lane_map_physical{121.0}=0x3210 +phy_chain_rx_lane_map_physical{125.0}=0x3210 + + +## FalconCore [32-47] port RX Lane Swapping +phy_chain_rx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_lane_map_physical{133.0}=0x2301 +phy_chain_rx_lane_map_physical{137.0}=0x3210 +phy_chain_rx_lane_map_physical{141.0}=0x2310 +phy_chain_rx_lane_map_physical{145.0}=0x3210 +phy_chain_rx_lane_map_physical{149.0}=0x3210 +phy_chain_rx_lane_map_physical{153.0}=0x3210 +phy_chain_rx_lane_map_physical{157.0}=0x3210 +phy_chain_rx_lane_map_physical{161.0}=0x3210 +phy_chain_rx_lane_map_physical{165.0}=0x3210 +phy_chain_rx_lane_map_physical{169.0}=0x3210 +phy_chain_rx_lane_map_physical{173.0}=0x3210 +phy_chain_rx_lane_map_physical{177.0}=0x3210 +phy_chain_rx_lane_map_physical{181.0}=0x3210 +phy_chain_rx_lane_map_physical{185.0}=0x3210 +phy_chain_rx_lane_map_physical{189.0}=0x3210 + + +## FalconCore [48-63] port RX Lan Swapping +phy_chain_rx_lane_map_physical{193.0}=0x3210 +phy_chain_rx_lane_map_physical{197.0}=0x3210 +phy_chain_rx_lane_map_physical{201.0}=0x3210 +phy_chain_rx_lane_map_physical{205.0}=0x3210 +phy_chain_rx_lane_map_physical{209.0}=0x3210 +phy_chain_rx_lane_map_physical{213.0}=0x3210 +phy_chain_rx_lane_map_physical{217.0}=0x3210 +phy_chain_rx_lane_map_physical{221.0}=0x3210 +phy_chain_rx_lane_map_physical{225.0}=0x3210 +phy_chain_rx_lane_map_physical{229.0}=0x2301 +phy_chain_rx_lane_map_physical{233.0}=0x3210 +phy_chain_rx_lane_map_physical{237.0}=0x1023 +phy_chain_rx_lane_map_physical{241.0}=0x3210 +phy_chain_rx_lane_map_physical{245.0}=0x3210 +phy_chain_rx_lane_map_physical{249.0}=0x3210 +phy_chain_rx_lane_map_physical{253.0}=0x3210 + + +## FalconCore[0-15] ports TX polarity flip +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x0 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{17.0}=0x0 +phy_chain_tx_polarity_flip_physical{18.0}=0x1 +phy_chain_tx_polarity_flip_physical{19.0}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +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{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_tx_polarity_flip_physical{33.0}=0x1 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x1 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x1 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x1 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 + +## FalconCore[16-31] ports TX polarity flip +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x0 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +phy_chain_tx_polarity_flip_physical{81.0}=0x0 +phy_chain_tx_polarity_flip_physical{82.0}=0x0 +phy_chain_tx_polarity_flip_physical{83.0}=0x0 +phy_chain_tx_polarity_flip_physical{84.0}=0x0 +phy_chain_tx_polarity_flip_physical{85.0}=0x0 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{90.0}=0x0 +phy_chain_tx_polarity_flip_physical{91.0}=0x0 +phy_chain_tx_polarity_flip_physical{92.0}=0x0 +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x0 +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_tx_polarity_flip_physical{101.0}=0x0 +phy_chain_tx_polarity_flip_physical{102.0}=0x0 +phy_chain_tx_polarity_flip_physical{103.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{110.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}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{118.0}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x0 +phy_chain_tx_polarity_flip_physical{120.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}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x0 + +## FalconCore[32-47] ports TX polarity flip +phy_chain_tx_polarity_flip_physical{129.0}=0x0 +phy_chain_tx_polarity_flip_physical{130.0}=0x0 +phy_chain_tx_polarity_flip_physical{131.0}=0x0 +phy_chain_tx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x0 +phy_chain_tx_polarity_flip_physical{135.0}=0x0 +phy_chain_tx_polarity_flip_physical{136.0}=0x0 +phy_chain_tx_polarity_flip_physical{137.0}=0x0 +phy_chain_tx_polarity_flip_physical{138.0}=0x1 +phy_chain_tx_polarity_flip_physical{139.0}=0x0 +phy_chain_tx_polarity_flip_physical{140.0}=0x0 +phy_chain_tx_polarity_flip_physical{141.0}=0x0 +phy_chain_tx_polarity_flip_physical{142.0}=0x0 +phy_chain_tx_polarity_flip_physical{143.0}=0x0 +phy_chain_tx_polarity_flip_physical{144.0}=0x0 +phy_chain_tx_polarity_flip_physical{145.0}=0x1 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x0 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x0 +phy_chain_tx_polarity_flip_physical{159.0}=0x0 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x1 +phy_chain_tx_polarity_flip_physical{162.0}=0x0 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{165.0}=0x0 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x0 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x0 +phy_chain_tx_polarity_flip_physical{170.0}=0x1 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x0 +phy_chain_tx_polarity_flip_physical{173.0}=0x0 +phy_chain_tx_polarity_flip_physical{174.0}=0x0 +phy_chain_tx_polarity_flip_physical{175.0}=0x0 +phy_chain_tx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{177.0}=0x0 +phy_chain_tx_polarity_flip_physical{178.0}=0x1 +phy_chain_tx_polarity_flip_physical{179.0}=0x0 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x0 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x0 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x0 +phy_chain_tx_polarity_flip_physical{189.0}=0x0 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x0 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 + +## FalconCore[48-63] ports TX polarity flip +phy_chain_tx_polarity_flip_physical{193.0}=0x1 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x0 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x0 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x0 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 +phy_chain_tx_polarity_flip_physical{201.0}=0x0 +phy_chain_tx_polarity_flip_physical{202.0}=0x1 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x0 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x0 +phy_chain_tx_polarity_flip_physical{207.0}=0x0 +phy_chain_tx_polarity_flip_physical{208.0}=0x0 +phy_chain_tx_polarity_flip_physical{209.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x0 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x0 +phy_chain_tx_polarity_flip_physical{217.0}=0x1 +phy_chain_tx_polarity_flip_physical{218.0}=0x0 +phy_chain_tx_polarity_flip_physical{219.0}=0x0 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x0 +phy_chain_tx_polarity_flip_physical{223.0}=0x0 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x0 +phy_chain_tx_polarity_flip_physical{227.0}=0x0 +phy_chain_tx_polarity_flip_physical{228.0}=0x0 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x0 +phy_chain_tx_polarity_flip_physical{231.0}=0x0 +phy_chain_tx_polarity_flip_physical{232.0}=0x0 +phy_chain_tx_polarity_flip_physical{233.0}=0x1 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x0 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{237.0}=0x0 +phy_chain_tx_polarity_flip_physical{238.0}=0x0 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 +phy_chain_tx_polarity_flip_physical{241.0}=0x1 +phy_chain_tx_polarity_flip_physical{242.0}=0x0 +phy_chain_tx_polarity_flip_physical{243.0}=0x0 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 +phy_chain_tx_polarity_flip_physical{245.0}=0x0 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x0 +phy_chain_tx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x0 +phy_chain_tx_polarity_flip_physical{251.0}=0x0 +phy_chain_tx_polarity_flip_physical{252.0}=0x0 +phy_chain_tx_polarity_flip_physical{253.0}=0x0 +phy_chain_tx_polarity_flip_physical{254.0}=0x0 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x1 + +## FalconCore[0-15] ports RX polarity flip +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x0 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_rx_polarity_flip_physical{13.0}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x1 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.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}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +phy_chain_rx_polarity_flip_physical{37.0}=0x0 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +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{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x0 +phy_chain_rx_polarity_flip_physical{64.0}=0x0 + +## FalconCore [16-31] ports RX polarity flip +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x1 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x0 +phy_chain_rx_polarity_flip_physical{84.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{89.0}=0x0 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 +phy_chain_rx_polarity_flip_physical{101.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +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{111.0}=0x0 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 +phy_chain_rx_polarity_flip_physical{113.0}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x0 +phy_chain_rx_polarity_flip_physical{115.0}=0x0 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +## FalconCore [32-47] ports RX polarity flip +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x0 +phy_chain_rx_polarity_flip_physical{135.0}=0x0 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x0 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_rx_polarity_flip_physical{141.0}=0x0 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x0 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_rx_polarity_flip_physical{145.0}=0x0 +phy_chain_rx_polarity_flip_physical{146.0}=0x0 +phy_chain_rx_polarity_flip_physical{147.0}=0x0 +phy_chain_rx_polarity_flip_physical{148.0}=0x1 +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x0 +phy_chain_rx_polarity_flip_physical{151.0}=0x0 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_rx_polarity_flip_physical{153.0}=0x0 +phy_chain_rx_polarity_flip_physical{154.0}=0x0 +phy_chain_rx_polarity_flip_physical{155.0}=0x0 +phy_chain_rx_polarity_flip_physical{156.0}=0x1 +phy_chain_rx_polarity_flip_physical{157.0}=0x0 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x0 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_rx_polarity_flip_physical{161.0}=0x0 +phy_chain_rx_polarity_flip_physical{162.0}=0x0 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x0 +phy_chain_rx_polarity_flip_physical{165.0}=0x0 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x0 +phy_chain_rx_polarity_flip_physical{168.0}=0x0 +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x0 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x0 +phy_chain_rx_polarity_flip_physical{175.0}=0x0 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 +phy_chain_rx_polarity_flip_physical{177.0}=0x0 +phy_chain_rx_polarity_flip_physical{178.0}=0x0 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x0 +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x0 +phy_chain_rx_polarity_flip_physical{183.0}=0x0 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_rx_polarity_flip_physical{185.0}=0x0 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{190.0}=0x0 +phy_chain_rx_polarity_flip_physical{191.0}=0x0 +phy_chain_rx_polarity_flip_physical{192.0}=0x0 + +## FalconCore [48-63] ports RX polarity flip +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x0 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x0 +phy_chain_rx_polarity_flip_physical{197.0}=0x0 +phy_chain_rx_polarity_flip_physical{198.0}=0x0 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x0 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_rx_polarity_flip_physical{205.0}=0x0 +phy_chain_rx_polarity_flip_physical{206.0}=0x0 +phy_chain_rx_polarity_flip_physical{207.0}=0x0 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_rx_polarity_flip_physical{209.0}=0x0 +phy_chain_rx_polarity_flip_physical{210.0}=0x0 +phy_chain_rx_polarity_flip_physical{211.0}=0x1 +phy_chain_rx_polarity_flip_physical{212.0}=0x1 +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x0 +phy_chain_rx_polarity_flip_physical{215.0}=0x0 +phy_chain_rx_polarity_flip_physical{216.0}=0x0 +phy_chain_rx_polarity_flip_physical{217.0}=0x0 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x0 +phy_chain_rx_polarity_flip_physical{221.0}=0x0 +phy_chain_rx_polarity_flip_physical{222.0}=0x0 +phy_chain_rx_polarity_flip_physical{223.0}=0x0 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 +phy_chain_rx_polarity_flip_physical{225.0}=0x0 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x0 +phy_chain_rx_polarity_flip_physical{228.0}=0x0 +phy_chain_rx_polarity_flip_physical{229.0}=0x0 +phy_chain_rx_polarity_flip_physical{230.0}=0x0 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x0 +phy_chain_rx_polarity_flip_physical{233.0}=0x0 +phy_chain_rx_polarity_flip_physical{234.0}=0x0 +phy_chain_rx_polarity_flip_physical{235.0}=0x0 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_rx_polarity_flip_physical{237.0}=0x0 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x0 +phy_chain_rx_polarity_flip_physical{240.0}=0x0 +phy_chain_rx_polarity_flip_physical{241.0}=0x0 +phy_chain_rx_polarity_flip_physical{242.0}=0x0 +phy_chain_rx_polarity_flip_physical{243.0}=0x1 +phy_chain_rx_polarity_flip_physical{244.0}=0x0 +phy_chain_rx_polarity_flip_physical{245.0}=0x0 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x0 +phy_chain_rx_polarity_flip_physical{248.0}=0x0 +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x0 +phy_chain_rx_polarity_flip_physical{251.0}=0x1 +phy_chain_rx_polarity_flip_physical{252.0}=0x0 +phy_chain_rx_polarity_flip_physical{253.0}=0x0 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x0 + +dport_map_enable=1 +dport_map_port_3=68 +dport_map_port_4=69 +dport_map_port_5=3 +dport_map_port_6=4 +dport_map_port_7=70 +dport_map_port_8=71 +dport_map_port_9=5 +dport_map_port_10=6 +dport_map_port_11=72 +dport_map_port_12=73 +dport_map_port_13=7 +dport_map_port_14=8 +dport_map_port_15=74 +dport_map_port_16=75 +dport_map_port_34=9 +dport_map_port_35=10 +dport_map_port_36=76 +dport_map_port_37=77 +dport_map_port_38=11 +dport_map_port_39=12 +dport_map_port_40=78 +dport_map_port_41=79 +dport_map_port_42=13 +dport_map_port_43=14 +dport_map_port_44=80 +dport_map_port_45=81 +dport_map_port_46=15 +dport_map_port_47=16 +dport_map_port_48=82 +dport_map_port_49=83 +dport_map_port_68=34 +dport_map_port_69=35 +dport_map_port_70=102 +dport_map_port_71=103 +dport_map_port_72=36 +dport_map_port_73=37 +dport_map_port_74=104 +dport_map_port_75=105 +dport_map_port_76=38 +dport_map_port_77=39 +dport_map_port_78=106 +dport_map_port_79=107 +dport_map_port_80=40 +dport_map_port_81=41 +dport_map_port_82=108 +dport_map_port_83=109 +dport_map_port_102=42 +dport_map_port_103=43 +dport_map_port_104=110 +dport_map_port_105=111 +dport_map_port_106=44 +dport_map_port_107=45 +dport_map_port_108=112 +dport_map_port_109=113 +dport_map_port_110=46 +dport_map_port_111=47 +dport_map_port_112=114 +dport_map_port_113=115 +dport_map_port_114=48 +dport_map_port_115=49 + +## ce +## POST: 24(18) MAIN: 62(3E) PRE: 8(08) +serdes_preemphasis_1=0x183E08 +serdes_preemphasis_2=0x193E08 +serdes_preemphasis_5=0x173E08 +serdes_preemphasis_6=0x173E08 +serdes_preemphasis_9=0x163E07 +serdes_preemphasis_10=0x173E08 +serdes_preemphasis_13=0x154007 +serdes_preemphasis_14=0x154007 +serdes_preemphasis_34=0x134007 +serdes_preemphasis_35=0x144007 +serdes_preemphasis_38=0x133F07 +serdes_preemphasis_39=0x133F07 +serdes_preemphasis_42=0x133F07 +serdes_preemphasis_43=0x133F06 +serdes_preemphasis_46=0x113E06 +serdes_preemphasis_47=0x113E05 +serdes_preemphasis_68=0x103F06 +serdes_preemphasis_69=0x103F06 +serdes_preemphasis_72=0x113F06 +serdes_preemphasis_73=0x103F06 +serdes_preemphasis_76=0x124006 +serdes_preemphasis_77=0x124006 +serdes_preemphasis_80=0x144007 +serdes_preemphasis_81=0x144007 +serdes_preemphasis_102=0x144007 +serdes_preemphasis_103=0x144007 +serdes_preemphasis_106=0x153F08 +serdes_preemphasis_107=0x153F08 +serdes_preemphasis_110=0x164008 +serdes_preemphasis_111=0x164008 +serdes_preemphasis_114=0x184008 +serdes_preemphasis_115=0x184008 +serdes_preemphasis_3=0x184108 +serdes_preemphasis_4=0x184108 +serdes_preemphasis_7=0x173F08 +serdes_preemphasis_8=0x174108 +serdes_preemphasis_11=0x154007 +serdes_preemphasis_12=0x154007 +serdes_preemphasis_15=0x144007 +serdes_preemphasis_16=0x144007 +serdes_preemphasis_36=0x133F07 +serdes_preemphasis_37=0x133F07 +serdes_preemphasis_40=0x133F07 +serdes_preemphasis_41=0x123F07 +serdes_preemphasis_44=0x113F07 +serdes_preemphasis_45=0x113F07 +serdes_preemphasis_48=0x113F06 +serdes_preemphasis_49=0x103F06 +serdes_preemphasis_70=0x113F06 +serdes_preemphasis_71=0x103F06 +serdes_preemphasis_74=0x113F06 +serdes_preemphasis_75=0x113F06 +serdes_preemphasis_78=0x123F07 +serdes_preemphasis_79=0x134007 +serdes_preemphasis_82=0x144007 +serdes_preemphasis_83=0x144007 +serdes_preemphasis_104=0x164007 +serdes_preemphasis_105=0x154107 +serdes_preemphasis_108=0x174107 +serdes_preemphasis_109=0x163F07 +serdes_preemphasis_112=0x194107 +serdes_preemphasis_113=0x174107 +serdes_preemphasis_116=0x1B4108 +serdes_preemphasis_117=0x194108 + + diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/default_sku b/device/inventec/x86_64-inventec_d7264q28b-r0/default_sku new file mode 100644 index 000000000000..134ade2e2cd3 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/default_sku @@ -0,0 +1 @@ +INVENTEC-D7264Q28B t1 diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/installer.conf b/device/inventec/x86_64-inventec_d7264q28b-r0/installer.conf new file mode 100644 index 000000000000..1db64ba02c38 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +VAR_LOG_SIZE=1024 diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d7264q28b-r0/led_proc_init.soc new file mode 100644 index 000000000000..296f8746f101 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/led_proc_init.soc @@ -0,0 +1,273 @@ +#LED processor initialization for Inventec Sequoia platform + +led 0 stop +led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=59 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=57 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=58 +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=51 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=49 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=50 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=63 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=61 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=62 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=55 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=53 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=54 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=43 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=41 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=42 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=35 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=33 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=34 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=47 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=45 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=46 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=39 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=37 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=38 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=27 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=25 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=26 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=19 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=17 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=18 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=31 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=29 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=30 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=23 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=21 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=22 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=9 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=10 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=3 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=1 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=2 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=15 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=13 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=14 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=7 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=5 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=6 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4 +led 0 start + +led 1 stop +led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=7 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=5 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=6 +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=15 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=13 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=14 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=1 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=2 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=11 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=9 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=10 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=23 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=21 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=22 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=29 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=30 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=19 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=17 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=18 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=27 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=25 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=26 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=39 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=37 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=38 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=47 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=45 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=46 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=33 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=34 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=43 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=41 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=42 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=55 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=53 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=54 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=63 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=61 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=62 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=60 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=51 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=49 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=50 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=59 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=57 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=58 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 +led 1 start + +led 2 stop +led 2 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=59 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=57 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=58 +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=56 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=51 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=49 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=50 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=48 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=63 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=61 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=62 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=60 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=55 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=53 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=54 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=52 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=43 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=41 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=42 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=40 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=35 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=33 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=34 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=32 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=47 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=45 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=46 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=44 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=39 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=37 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=38 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=36 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=27 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=25 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=26 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=24 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=19 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=17 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=18 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=16 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=31 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=29 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=30 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=28 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=23 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=21 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=22 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=20 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=11 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=9 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=10 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=8 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=3 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=1 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=2 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=0 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=15 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=13 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=14 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=12 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=7 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=5 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=6 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=4 +led 2 start + +led 3 stop +led 3 prog 02 00 60 F1 12 00 DA 0F 70 10 67 72 67 6D 77 06 02 A0 60 F0 02 00 60 F2 12 00 02 00 60 F4 06 F0 4A 01 71 41 4A 03 27 67 6D 4A 02 27 67 6D 06 F2 28 32 08 67 6D 06 F2 28 32 00 32 01 B7 67 6D 77 4D 67 75 67 6D 67 75 67 6D 67 72 67 6D DA A0 70 5F 86 F0 86 F2 86 F4 06 F4 D2 04 74 2E 77 1A 12 00 DA 00 70 6B 67 75 67 6D 77 61 3E F1 87 86 F1 81 57 17 27 57 07 27 57 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=7 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=5 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=6 +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=4 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=15 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=13 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=14 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=12 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=3 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=1 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=2 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=0 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=11 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=9 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=10 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=8 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=23 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=21 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=22 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=20 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=31 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=29 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=30 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=28 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=19 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=17 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=18 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=16 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=27 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=25 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=26 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=24 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=39 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=37 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=38 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=36 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=47 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=45 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=46 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=44 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=35 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=33 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=34 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=32 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=43 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=41 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=42 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=40 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=55 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=53 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=54 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=52 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=63 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=61 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=62 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=60 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=51 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=49 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=50 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=48 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=59 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=57 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=58 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=56 +led 3 start diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/eeprom.py new file mode 100644 index 000000000000..31f847614fb0 --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +############################################################################# +# Inventec d7032q28b +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0053/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/psuutil.py new file mode 100755 index 000000000000..8e100d36405d --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/psuutil.py @@ -0,0 +1,93 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR1 = "/sys/class/hwmon/hwmon1/device" + PSU_DIR2 = "/sys/class/hwmon/hwmon3/device" + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + 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 = 'psoc_psu' + str(index) + '_iout' + attr_path = self.PSU_DIR1 + '/' + attr_file + + attr_value = self.get_attr_value(attr_path) + if (attr_value == 'ERR'): + attr_path = self.PSU_DIR2 + '/' + attr_file + attr_value = self.get_attr_value(attr_path) + # Check for PSU status + if (attr_value != 0): + status = 1 + if (attr_value != 0): + 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 + ind = index-1 + attr_file = 'psu' + str(ind) + normal_attr_value = '0 : normal' + attr_path = self.PSU_DIR1 + '/' + attr_file + attr_value = self.get_attr_value(attr_path) + if (attr_value == 'ERR'): + attr_path = self.PSU_DIR2 + '/' + attr_file + attr_value = self.get_attr_value(attr_path) + # Check for PSU presence + if (attr_value == normal_attr_value): + status = 1 + if (attr_value == normal_attr_value): + status = 1 + return status diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/sfputil.py new file mode 100755 index 000000000000..6591809194af --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/plugins/sfputil.py @@ -0,0 +1,227 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 63 + PORTS_IN_BLOCK = 64 + QSFP_PORT_START = 0 + QSFP_PORT_END = 63 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 10, + 1: 11, + 2: 12, + 3: 13, + 4: 14, + 5: 15, + 6: 16, + 7: 17, + 8: 18, + 9: 19, + 10: 20, + 11: 21, + 12: 22, + 13: 23, + 14: 24, + 15: 25, + 16: 26, + 17: 27, + 18: 28, + 19: 29, + 20: 30, + 21: 31, + 22: 32, + 23: 33, + 24: 34, + 25: 35, + 26: 36, + 27: 37, + 28: 38, + 29: 39, + 30: 40, + 31: 41, + 32: 45, + 33: 44, + 34: 43, + 35: 42, + 36: 49, + 37: 48, + 38: 47, + 39: 46, + 40: 53, + 41: 52, + 42: 51, + 43: 50, + 44: 57, + 45: 56, + 46: 55, + 47: 54, + 48: 61, + 49: 60, + 50: 59, + 51: 58, + 52: 65, + 53: 64, + 54: 63, + 55: 62, + 56: 69, + 57: 68, + 58: 67, + 59: 66, + 60: 73, + 61: 72, + 62: 71, + 63: 70 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom" + + for x in range(0, 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) + + 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 + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + print("\nError:SFP's don't support this property") + return False + + try: + reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset" + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + print("\nError:SFP's don't support this property") + return False + + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/sensors.conf b/device/inventec/x86_64-inventec_d7264q28b-r0/sensors.conf new file mode 100644 index 000000000000..38072557730e --- /dev/null +++ b/device/inventec/x86_64-inventec_d7264q28b-r0/sensors.conf @@ -0,0 +1,44 @@ +# libsensors configuration file +chip "inv_psoc-*" + label temp1 "FrontSide Temperature" + label temp2 "FanBoard Temperature" + label temp3 "NearASIC Temperature" + label temp4 "Center(U10) Temperature" + label temp5 "CPU Board Temperature" + label temp6 "ASIC Temperature" + label temp7 "PSU1 Temperature1" + label temp8 "PSU2 Temperature1" + label temp9 "PSU1 Temperature2" + label temp10 "PSU2 Temperature2" + label fan1 "FanModule1 Front RPM" + label fan2 "FanModule1 Rear RPM" + label fan3 "FanModule2 Front RPM" + label fan4 "FanModule2 Rear RPM" + label fan5 "FanModule3 Front RPM" + label fan6 "FanModule3 Rear RPM" + label fan7 "FanModule4 Front RPM" + label fan8 "FanModule4 Rear RPM" + label fan9 "FanModule5 Front RPM" + label fan10 "FanModule5 Rear RPM" + label pwm1 "FanModule1 PWM" + label pwm2 "FanModule2 PWM" + label pwm3 "FanModule3 PWM" + label pwm4 "FanModule4 PWM" + label pwm5 "FanModule5 PWM" + label pwm6 "PSU1 FAN PWM" + label pwm7 "PSU2 FAN PWM" + label fan11 "PSU1 FAN RPM" + label fan12 "PSU2 FAN RPM" + label in1 "PSU1 Input Voltage" + label in2 "PSU2 Input Voltage" + label curr1 "PSU1 Input Current" + label curr2 "PSU2 Input Current" + label power1 "PSU1 Input Power" + label power2 "PSU2 Input Power" + label in3 "PSU1 Output Voltage" + label in4 "PSU2 Output Voltage" + label curr3 "PSU1 Output Current" + label curr4 "PSU2 Output Current" + label power3 "PSU1 Output Power" + label power4 "PSU2 Output Power" + diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/buffers.json.j2 b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/buffers.json.j2 new file mode 100644 index 000000000000..a9a01d707ebf --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/buffers.json.j2 @@ -0,0 +1 @@ +{%- include 'buffers_config.j2' %} diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/buffers_defaults_t1.j2 b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..3442612f70b2 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "33329088", + "type": "ingress", + "mode": "dynamic", + "xoff": "7827456" + }, + "egress_lossy_pool": { + "size": "26663272", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "42349632", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"44302336" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"42349632" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1664", + "dynamic_th":"-1" + } + }, +{%- endmacro %} diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/port_config.ini b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/port_config.ini new file mode 100644 index 000000000000..a7ebdd116fc8 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 49,50,51,52 hundredGigE1/1 0 100000 +Ethernet4 53,54,55,56 hundredGigE1/2 1 100000 +Ethernet8 57,58,59,60 hundredGigE1/3 2 100000 +Ethernet12 61,62,63,64 hundredGigE1/4 3 100000 +Ethernet16 65,66,67,68 hundredGigE1/5 4 100000 +Ethernet20 69,70,71,72 hundredGigE1/6 5 100000 +Ethernet24 73,74,75,76 hundredGigE1/7 6 100000 +Ethernet28 77,78,79,80 hundredGigE1/8 7 100000 +Ethernet32 81,82,83,84 hundredGigE1/9 8 100000 +Ethernet36 85,86,87,88 hundredGigE1/10 9 100000 +Ethernet40 37,38,39,40 hundredGigE1/11 10 100000 +Ethernet44 33,34,35,36 hundredGigE1/12 11 100000 +Ethernet48 41,42,43,44 hundredGigE1/13 12 100000 +Ethernet52 45,46,47,48 hundredGigE1/14 13 100000 +Ethernet56 89,90,91,92 hundredGigE1/15 14 100000 +Ethernet60 93,94,95,96 hundredGigE1/16 15 100000 +Ethernet64 97,98,99,100 hundredGigE1/17 16 100000 +Ethernet68 101,102,103,104 hundredGigE1/18 17 100000 +Ethernet72 17,18,19,20 hundredGigE1/19 18 100000 +Ethernet76 21,22,23,24 hundredGigE1/20 19 100000 +Ethernet80 29,30,31,32 hundredGigE1/21 20 100000 +Ethernet84 25,26,27,28 hundredGigE1/22 21 100000 +Ethernet88 105,106,107,108 hundredGigE1/23 22 100000 +Ethernet92 109,110,111,112 hundredGigE1/24 23 100000 +Ethernet96 113,114,115,116 hundredGigE1/25 24 100000 +Ethernet100 117,118,119,120 hundredGigE1/26 25 100000 +Ethernet104 121,122,123,124 hundredGigE1/27 26 100000 +Ethernet108 125,126,127,128 hundredGigE1/28 27 100000 +Ethernet112 1,2,3,4 hundredGigE1/29 28 100000 +Ethernet116 5,6,7,8 hundredGigE1/30 29 100000 +Ethernet120 9,10,11,12 hundredGigE1/31 30 100000 +Ethernet124 13,14,15,16 hundredGigE1/32 31 100000 diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/qos.json.j2 b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/sai.profile b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/sai.profile new file mode 100644 index 000000000000..9852552d899e --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-qfx5200-32x100g.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/th-qfx5200-32x100g.config.bcm b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/th-qfx5200-32x100g.config.bcm new file mode 100644 index 000000000000..a0ed5ca2fa5c --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/Juniper-QFX5200-32C-S/th-qfx5200-32x100g.config.bcm @@ -0,0 +1,586 @@ +phy_xaui_tx_polarity_flip_99=0x01 +portmap_120=115:25:50:i +portmap_112=107:25:50:i +portmap_104=99:25:50:i +portmap_8=8:25:i +xgxs_rx_lane_map_20=0x3120 +xgxs_rx_lane_map_12=0x2301 +l2mod_dma_intr_enable=1 +xgxs_tx_lane_map_40=0x0123 +xgxs_tx_lane_map_32=0x0213 +xgxs_tx_lane_map_24=0x2310 +xgxs_tx_lane_map_16=0x1023 +port_phy_addr_99=0xff +rate_ext_mdio_divisor=0x80 +portmap_121=116:25:i +portmap_113=108:25:i +portmap_105=100:25:i +portmap_9=9:100 +xgxs_rx_lane_map_21=0x3120 +xgxs_rx_lane_map_13=0x0213 +tslam_timeout_usec=10000000 +xgxs_tx_lane_map_41=0x0123 +xgxs_tx_lane_map_25=0x0213 +xgxs_tx_lane_map_17=0x0213 +portmap_130=125:100 +portmap_122=117:100 +portmap_114=109:100 +xgxs_rx_lane_map_30=0x2301 +portmap_106=101:100 +xgxs_rx_lane_map_22=0x3120 +xgxs_rx_lane_map_14=0x0213 +xgxs_tx_lane_map_50=0x0213 +xgxs_tx_lane_map_42=0x2310 +xgxs_tx_lane_map_34=0x0123 +phy_xaui_rx_polarity_flip_20=0x01 +xgxs_tx_lane_map_26=0x0213 +xgxs_tx_lane_map_18=0x0213 +portmap_10=10:25:i +xgxs_tx_lane_map_1=0x3120 +portmap_131=126:25:i +portmap_123=118:25:i +portmap_115=110:25:i +xgxs_rx_lane_map_31=0x2301 +portmap_107=102:25:i +xgxs_rx_lane_map_23=0x3120 +xgxs_rx_lane_map_15=0x0213 +xgxs_tx_lane_map_51=0x0213 +xgxs_tx_lane_map_43=0x2310 +xgxs_tx_lane_map_35=0x0123 +phy_xaui_rx_polarity_flip_21=0x03 +xgxs_tx_lane_map_27=0x0213 +phy_xaui_rx_polarity_flip_13=0x0c +xgxs_tx_lane_map_19=0x0213 +portmap_11=11:25:50:i +xgxs_tx_lane_map_2=0x3120 +xgxs_tx_lane_map_110=0x1203 +xgxs_tx_lane_map_102=0x1203 +parity_correction=1 +portmap_132=127:25:50:i +portmap_124=119:25:50:i +portmap_116=111:25:50:i +xgxs_rx_lane_map_40=0x2310 +xgxs_rx_lane_map_32=0x2301 +portmap_108=103:25:50:i +xgxs_rx_lane_map_24=0x3120 +xgxs_rx_lane_map_16=0x0213 +xgxs_tx_lane_map_60=0x0213 +xgxs_tx_lane_map_52=0x0213 +xgxs_tx_lane_map_44=0x2310 +xgxs_tx_lane_map_36=0x0123 +phy_xaui_rx_polarity_flip_22=0x01 +xgxs_tx_lane_map_28=0x0213 +portmap_20=20:25:i +portmap_12=12:25:i +xgxs_tx_lane_map_3=0x3120 +xgxs_tx_lane_map_111=0x1203 +xgxs_tx_lane_map_103=0x1203 +portmap_133=128:25:i +portmap_125=120:25:i +portmap_117=112:25:i +xgxs_rx_lane_map_41=0x2310 +portmap_109=104:25:i +xgxs_rx_lane_map_25=0x3210 +xgxs_rx_lane_map_17=0x3120 +xgxs_tx_lane_map_61=0x0213 +xgxs_tx_lane_map_53=0x0213 +xgxs_tx_lane_map_45=0x2310 +xgxs_tx_lane_map_37=0x0123 +xgxs_tx_lane_map_29=0x0213 +phy_xaui_rx_polarity_flip_15=0x03 +portmap_21=21:100 +portmap_13=13:100 +xgxs_rx_lane_map_110=0x2301 +xgxs_rx_lane_map_102=0x2301 +xgxs_tx_lane_map_4=0x3120 +xgxs_tx_lane_map_120=0x1203 +xgxs_tx_lane_map_112=0x1203 +xgxs_tx_lane_map_104=0x1203 +bcm_stat_interval=500000 +l2xmsg_hostbuf_size=16384 +portmap_126=121:100 +xgxs_rx_lane_map_50=0x0231 +portmap_118=113:100 +xgxs_rx_lane_map_42=0x3201 +xgxs_rx_lane_map_34=0x3102 +xgxs_rx_lane_map_26=0x3210 +xgxs_rx_lane_map_18=0x3120 +xgxs_tx_lane_map_70=0x3120 +xgxs_tx_lane_map_62=0x2310 +xgxs_tx_lane_map_54=0x2310 +phy_xaui_rx_polarity_flip_40=0x01 +xgxs_tx_lane_map_46=0x2013 +xgxs_tx_lane_map_38=0x0123 +portmap_30=30:25:i +phy_xaui_rx_polarity_flip_16=0x01 +portmap_22=22:25:i +portmap_14=14:25:i +xgxs_rx_lane_map_111=0x2301 +xgxs_rx_lane_map_103=0x2301 +xgxs_tx_lane_map_5=0x1023 +xgxs_tx_lane_map_121=0x1203 +xgxs_tx_lane_map_113=0x1203 +xgxs_tx_lane_map_105=0x1203 +port_phy_addr_10=0xff +mem_check_nocache_override=1 +bcm_stat_flags=1 +portmap_127=122:25:i +xgxs_rx_lane_map_51=0x0231 +portmap_119=114:25:i +xgxs_rx_lane_map_43=0x3201 +xgxs_rx_lane_map_35=0x3102 +xgxs_rx_lane_map_27=0x3210 +xgxs_rx_lane_map_19=0x3120 +xgxs_tx_lane_map_71=0x3120 +xgxs_tx_lane_map_63=0x2310 +phy_xaui_tx_polarity_flip_11=0x02 +xgxs_tx_lane_map_55=0x2310 +xgxs_tx_lane_map_47=0x2013 +xgxs_tx_lane_map_39=0x0123 +phy_xaui_rx_polarity_flip_25=0x0c +portmap_31=31:25:50:i +phy_xaui_rx_polarity_flip_17=0x08 +portmap_23=23:25:50:i +portmap_15=15:25:50:i +xgxs_rx_lane_map_120=0x3120 +xgxs_rx_lane_map_112=0x2301 +xgxs_rx_lane_map_104=0x2301 +xgxs_tx_lane_map_6=0x1023 +xgxs_tx_lane_map_130=0x3201 +xgxs_tx_lane_map_122=0x1023 +xgxs_tx_lane_map_114=0x0132 +xgxs_tx_lane_map_106=0x0132 +port_phy_addr_11=0xff +xgxs_rx_lane_map_60=0x0231 +portmap_128=123:25:50:i +xgxs_rx_lane_map_52=0x0231 +xgxs_rx_lane_map_44=0x3201 +xgxs_rx_lane_map_36=0x3102 +xgxs_rx_lane_map_28=0x3210 +xgxs_tx_lane_map_80=0x3102 +xgxs_tx_lane_map_72=0x2310 +xgxs_tx_lane_map_64=0x2310 +phy_xaui_tx_polarity_flip_12=0x01 +xgxs_tx_lane_map_56=0x2310 +phy_xaui_rx_polarity_flip_42=0x04 +xgxs_tx_lane_map_48=0x2013 +phy_xaui_rx_polarity_flip_34=0x08 +portmap_40=39:25:50:i +xgxs_rx_lane_map_1=0x3201 +portmap_32=32:25:i +portmap_24=24:25:i +portmap_16=16:25:i +xgxs_rx_lane_map_121=0x3120 +xgxs_rx_lane_map_113=0x2301 +xgxs_rx_lane_map_105=0x2301 +xgxs_tx_lane_map_7=0x1023 +xgxs_tx_lane_map_131=0x3201 +xgxs_tx_lane_map_123=0x1023 +xgxs_tx_lane_map_115=0x0132 +xgxs_tx_lane_map_107=0x0132 +port_phy_addr_20=0xff +port_phy_addr_12=0xff +xgxs_rx_lane_map_61=0x0231 +portmap_129=124:25:i +xgxs_rx_lane_map_53=0x0231 +xgxs_rx_lane_map_45=0x3201 +xgxs_rx_lane_map_37=0x3102 +xgxs_rx_lane_map_29=0x2301 +xgxs_tx_lane_map_81=0x3102 +xgxs_tx_lane_map_73=0x2310 +phy_xaui_tx_polarity_flip_21=0x04 +xgxs_tx_lane_map_65=0x2310 +xgxs_tx_lane_map_57=0x2310 +xgxs_tx_lane_map_49=0x2013 +portmap_41=40:25:i +phy_xaui_rx_polarity_flip_27=0x03 +xgxs_rx_lane_map_2=0x3201 +phy_xaui_rx_polarity_flip_19=0x02 +portmap_25=25:100 +portmap_17=17:100 +xgxs_rx_lane_map_130=0x3210 +xgxs_rx_lane_map_122=0x1023 +xgxs_rx_lane_map_114=0x2301 +xgxs_rx_lane_map_106=0x2301 +xgxs_tx_lane_map_8=0x1023 +xgxs_tx_lane_map_132=0x3201 +xgxs_tx_lane_map_124=0x1023 +xgxs_tx_lane_map_116=0x0132 +xgxs_tx_lane_map_108=0x0132 +phy_xaui_rx_polarity_flip_114=0x07 +xgxs_rx_lane_map_70=0x0213 +xgxs_rx_lane_map_62=0x2310 +xgxs_rx_lane_map_54=0x2301 +xgxs_rx_lane_map_46=0x3012 +xgxs_rx_lane_map_38=0x2310 +xgxs_tx_lane_map_90=0x0123 +xgxs_tx_lane_map_82=0x3102 +xgxs_tx_lane_map_74=0x2310 +xgxs_tx_lane_map_58=0x0213 +phy_xaui_rx_polarity_flip_44=0x01 +portmap_50=49:100 +phy_xaui_rx_polarity_flip_36=0x02 +portmap_42=41:100 +phy_xaui_rx_polarity_flip_28=0x01 +xgxs_rx_lane_map_3=0x3201 +portmap_34=33:100 +portmap_26=26:25:i +portmap_18=18:25:i +xgxs_rx_lane_map_131=0x3210 +xgxs_rx_lane_map_123=0x1023 +xgxs_rx_lane_map_115=0x2301 +xgxs_rx_lane_map_107=0x2301 +xgxs_tx_lane_map_9=0x3120 +xgxs_tx_lane_map_133=0x3201 +xgxs_tx_lane_map_125=0x1023 +bcm_linkscan_interval=4000000 +xgxs_tx_lane_map_117=0x0132 +xgxs_tx_lane_map_109=0x0132 +phy_xaui_rx_polarity_flip_115=0x01 +port_phy_addr_30=0xff +port_phy_addr_22=0xff +port_phy_addr_14=0xff +xgxs_rx_lane_map_71=0x0213 +xgxs_rx_lane_map_63=0x2310 +xgxs_rx_lane_map_55=0x2301 +xgxs_rx_lane_map_47=0x3012 +xgxs_rx_lane_map_39=0x2310 +xgxs_tx_lane_map_91=0x0123 +xgxs_tx_lane_map_83=0x3102 +phy_xaui_tx_polarity_flip_31=0x02 +xgxs_tx_lane_map_75=0x2310 +phy_xaui_tx_polarity_flip_23=0x01 +xgxs_tx_lane_map_59=0x0213 +portmap_51=50:25:i +phy_xaui_rx_polarity_flip_37=0x01 +portmap_43=42:25:i +xgxs_rx_lane_map_4=0x3201 +portmap_35=34:25:i +portmap_27=27:25:50:i +portmap_19=19:25:50:i +xgxs_rx_lane_map_132=0x3210 +xgxs_rx_lane_map_124=0x1023 +xgxs_rx_lane_map_116=0x2301 +cdma_timeout_usec=4000000 +xgxs_rx_lane_map_108=0x2301 +xgxs_tx_lane_map_126=0x3120 +xgxs_tx_lane_map_118=0x1203 +phy_xaui_rx_polarity_flip_116=0x01 +port_phy_addr_31=0xff +port_phy_addr_23=0xff +port_phy_addr_15=0xff +xgxs_rx_lane_map_80=0x3210 +xgxs_rx_lane_map_72=0x2310 +xgxs_rx_lane_map_64=0x2310 +xgxs_rx_lane_map_56=0x2301 +xgxs_rx_lane_map_48=0x3012 +xgxs_tx_lane_map_92=0x0213 +phy_xaui_tx_polarity_flip_40=0x01 +xgxs_tx_lane_map_84=0x0213 +phy_xaui_tx_polarity_flip_32=0x01 +xgxs_tx_lane_map_76=0x0213 +xgxs_tx_lane_map_68=0x3120 +portmap_60=59:25:50:i +phy_xaui_rx_polarity_flip_46=0x08 +portmap_52=51:25:50:i +phy_xaui_rx_polarity_flip_38=0x04 +portmap_44=43:25:50:i +xgxs_rx_lane_map_5=0x1023 +portmap_36=35:25:50:i +portmap_28=28:25:i +mdio_output_delay=12 +xgxs_rx_lane_map_133=0x3210 +xgxs_rx_lane_map_125=0x1023 +xgxs_rx_lane_map_117=0x2301 +xgxs_rx_lane_map_109=0x2301 +xgxs_tx_lane_map_127=0x3120 +xgxs_tx_lane_map_119=0x1203 +port_phy_addr_40=0xff +port_phy_addr_32=0xff +port_phy_addr_24=0xff +port_phy_addr_16=0xff +xgxs_rx_lane_map_81=0x3210 +xgxs_rx_lane_map_73=0x2310 +tdma_timeout_usec=10000000 +xgxs_rx_lane_map_65=0x2310 +xgxs_rx_lane_map_57=0x2301 +xgxs_rx_lane_map_49=0x3012 +xgxs_tx_lane_map_93=0x0213 +xgxs_tx_lane_map_85=0x0213 +xgxs_tx_lane_map_77=0x0213 +phy_xaui_tx_polarity_flip_25=0x0d +xgxs_tx_lane_map_69=0x3120 +portmap_61=60:25:i +portmap_53=52:25:i +portmap_45=44:25:i +xgxs_rx_lane_map_6=0x1023 +portmap_37=36:25:i +portmap_29=29:100 +xgxs_rx_lane_map_126=0x2301 +xgxs_rx_lane_map_118=0x3120 +xgxs_tx_lane_map_128=0x3120 +port_phy_addr_41=0xff +ipv6_lpm_128b_enable=1 +xgxs_rx_lane_map_90=0x3210 +xgxs_rx_lane_map_82=0x3210 +xgxs_rx_lane_map_74=0x2310 +xgxs_rx_lane_map_58=0x0231 +fpem_mem_entries=0 +xgxs_tx_lane_map_94=0x0213 +phy_xaui_tx_polarity_flip_42=0x04 +xgxs_tx_lane_map_86=0x0213 +phy_xaui_tx_polarity_flip_34=0x08 +xgxs_tx_lane_map_78=0x0213 +portmap_70=67:25:50:i +portmap_62=61:100 +phy_xaui_rx_polarity_flip_48=0x02 +pbmp_xport_xe=0xfffffffffffffffffffffffffffffffffe +portmap_54=53:100 +portmap_46=45:100 +xgxs_rx_lane_map_7=0x1023 +portmap_38=37:100 +xgxs_rx_lane_map_127=0x2301 +xgxs_rx_lane_map_119=0x3120 +xgxs_tx_lane_map_129=0x3120 +l2_mem_entries=8192 +os=unix +port_phy_addr_26=0xff +port_phy_addr_18=0xff +xgxs_rx_lane_map_91=0x3210 +xgxs_rx_lane_map_83=0x3210 +xgxs_rx_lane_map_75=0x2310 +xgxs_rx_lane_map_59=0x0231 +xgxs_tx_lane_map_95=0x0213 +port_phy_addr_111=0xff +xgxs_tx_lane_map_87=0x0213 +port_phy_addr_103=0xff +xgxs_tx_lane_map_79=0x0213 +phy_xaui_tx_polarity_flip_27=0x03 +portmap_71=68:25:i +portmap_63=62:25:i +phy_xaui_rx_polarity_flip_49=0x01 +portmap_55=54:25:i +portmap_47=46:25:i +xgxs_rx_lane_map_8=0x1023 +portmap_39=38:25:i +xgxs_rx_lane_map_128=0x2301 +port_phy_addr_51=0xff +port_phy_addr_43=0xff +port_phy_addr_35=0xff +port_phy_addr_27=0xff +port_phy_addr_19=0xff +xgxs_rx_lane_map_92=0x2310 +xgxs_rx_lane_map_84=0x3210 +xgxs_rx_lane_map_76=0x0231 +xgxs_rx_lane_map_68=0x0213 +port_phy_addr_120=0xff +xgxs_tx_lane_map_96=0x0123 +phy_xaui_tx_polarity_flip_44=0x01 +port_phy_addr_112=0xff +xgxs_tx_lane_map_88=0x0123 +phy_xaui_tx_polarity_flip_36=0x02 +port_phy_addr_104=0xff +portmap_80=77:100 +phy_xaui_tx_polarity_flip_28=0x01 +portmap_72=69:100 +portmap_64=63:25:50:i +portmap_56=55:25:50:i +portmap_48=47:25:50:i +xgxs_rx_lane_map_9=0x2301 +phy_xaui_rx_polarity_flip_5=4 +xgxs_rx_lane_map_129=0x2301 +port_phy_addr_60=0xff +port_phy_addr_52=0xff +port_phy_addr_44=0xff +port_phy_addr_36=0xff +port_phy_addr_28=0xff +xgxs_rx_lane_map_93=0x2310 +xgxs_rx_lane_map_85=0x3210 +table_dma_enable=1 +xgxs_rx_lane_map_77=0x0231 +xgxs_rx_lane_map_69=0x0213 +port_phy_addr_121=0xff +xgxs_tx_lane_map_97=0x0123 +port_phy_addr_113=0xff +xgxs_tx_lane_map_89=0x0123 +phy_xaui_tx_polarity_flip_37=0x01 +port_phy_addr_105=0xff +portmap_81=78:25:i +phy_xaui_tx_polarity_flip_29=0x08 +portmap_73=70:25:i +portmap_65=64:25:i +portmap_57=56:25:i +portmap_49=48:25:i +port_phy_addr_61=0xff +port_phy_addr_53=0xff +port_phy_addr_45=0xff +port_phy_addr_37=0xff +xgxs_rx_lane_map_94=0x2310 +port_phy_addr_2=0xff +xgxs_rx_lane_map_86=0x3210 +xgxs_rx_lane_map_78=0x0231 +phy_xaui_rx_polarity_flip_92=0x0c +xgxs_tx_lane_map_98=0x0123 +phy_xaui_tx_polarity_flip_46=0x01 +portmap_90=87:25:50:i +phy_xaui_tx_polarity_flip_38=0x05 +portmap_82=79:25:50:i +portmap_74=71:25:50:i +portmap_66=129:1 +portmap_58=57:100 +phy_xaui_rx_polarity_flip_7=1 +port_phy_addr_70=0xff +xgxs_rx_lane_map_95=0x2310 +port_phy_addr_3=0xff +xgxs_rx_lane_map_87=0x3210 +xgxs_rx_lane_map_79=0x0231 +port_phy_addr_131=0xff +port_phy_addr_123=0xff +xgxs_tx_lane_map_99=0x0123 +phy_an_c37=3 +port_phy_addr_115=0xff +portmap_91=88:25:i +port_phy_addr_107=0xff +portmap_83=80:25:i +portmap_75=72:25:i +portmap_59=58:25:i +serdes_firmware_mode=0x1 +schan_intr_enable=0x00 +port_phy_addr_71=0xff +port_phy_addr_63=0xff +port_phy_addr_55=0xff +port_phy_addr_47=0xff +port_phy_addr_39=0xff +l2delete_chunks=128 +xgxs_rx_lane_map_96=0x2130 +port_phy_addr_4=0xff +xgxs_rx_lane_map_88=0x3210 +tslam_intr_enable=0 +port_phy_addr_132=0xff +phy_xaui_rx_polarity_flip_94=0x03 +port_phy_addr_124=0xff +port_phy_addr_116=0xff +portmap_92=89:100 +port_phy_addr_108=0xff +portmap_84=81:100 +portmap_76=73:100 +portmap_68=65:100 +port_phy_addr_64=0xff +mem_cache_enable=1 +port_phy_addr_56=0xff +port_phy_addr_48=0xff +parity_enable=1 +xgxs_rx_lane_map_97=0x2130 +xgxs_rx_lane_map_89=0x3210 +port_phy_addr_133=0xff +phy_xaui_rx_polarity_flip_95=0x01 +port_phy_addr_125=0xff +port_phy_addr_117=0xff +portmap_93=90:25:i +port_phy_addr_109=0xff +portmap_85=82:25:i +portmap_77=74:25:i +portmap_69=66:25:i +port_phy_addr_81=0xff +port_phy_addr_73=0xff +port_phy_addr_65=0xff +port_phy_addr_57=0xff +port_phy_addr_49=0xff +xgxs_rx_lane_map_98=0x2130 +port_phy_addr_6=0xff +phy_xaui_tx_polarity_flip_90=0x03 +phy_xaui_rx_polarity_flip_96=0x0c +portmap_94=91:25:50:i +portmap_86=83:25:50:i +portmap_78=75:25:50:i +port_phy_addr_90=0xff +port_phy_addr_82=0xff +port_phy_addr_74=0xff +load_firmware=0x102 +l2xmsg_mode=1 +xgxs_rx_lane_map_99=0x2130 +port_phy_addr_7=0xff +phy_xaui_tx_polarity_flip_91=0x01 +phy_an_c73=0 +port_phy_addr_127=0xff +port_phy_addr_119=0xff +portmap_95=92:25:i +portmap_87=84:25:i +portmap_79=76:25:i +port_phy_addr_91=0xff +port_phy_addr_83=0xff +port_phy_addr_75=0xff +port_phy_addr_59=0xff +mmu_lossless=0x01 +port_phy_addr_8=0xff +phy_xaui_tx_polarity_flip_92=0x04 +phy_xaui_tx_polarity_flip_84=0x04 +phy_xaui_rx_polarity_flip_98=0x03 +port_phy_addr_128=0xff +portmap_96=93:100 +portmap_1=1:100 +portmap_88=85:100 +phy_xaui_tx_polarity_flip_9=0x08 +phy_xaui_rx_polarity_flip_99=0x01 +port_phy_addr_129=0xff +portmap_97=94:25:i +portmap_2=2:25:i +portmap_89=86:25:i +xgxs_tx_lane_map_10=0x3120 +phy_an_c37_100=1 +port_phy_addr_93=0xff +port_phy_addr_85=0xff +port_phy_addr_77=0xff +port_phy_addr_69=0xff +phy_xaui_tx_polarity_flip_94=0x01 +phy_xaui_tx_polarity_flip_86=0x01 +max_vp_lags=0 +l3_max_ecmp_mode=1 +l3_alpm_enable=2 +portmap_98=95:25:50:i +portmap_3=3:25:50:i +miim_intr_enable=0x0 +xgxs_tx_lane_map_11=0x3120 +port_phy_addr_94=0xff +port_phy_addr_86=0xff +port_phy_addr_78=0xff +module_64ports=0 +tdma_intr_enable=0 +portmap_100=131:1 +portmap_99=96:25:i +pbmp_oversubscribe=0xC4444451111111144444444422222222 +portmap_4=4:25:i +l3_mem_entries=8192 +xgxs_tx_lane_map_20=0x0213 +xgxs_tx_lane_map_12=0x3120 +port_phy_addr_95=0xff +port_phy_addr_87=0xff +port_phy_addr_79=0xff +ptp_ts_pll_fref=0 +phy_xaui_tx_polarity_flip_96=0x08 +phy_xaui_tx_polarity_flip_88=0x0c +portmap_5=5:100 +xgxs_tx_lane_map_21=0x2310 +xgxs_tx_lane_map_13=0x1023 +tslam_dma_enable=1 +dport_map_direct=0x01 +portmap_110=105:100 +portmap_102=97:100 +portmap_6=6:25:i +xgxs_rx_lane_map_10=0x2301 +xgxs_tx_lane_map_30=0x0213 +xgxs_tx_lane_map_22=0x2310 +xgxs_tx_lane_map_14=0x1023 +phy_an_c73_100=0 +port_phy_addr_97=0xff +port_phy_addr_89=0xff +phy_xaui_tx_polarity_flip_98=0x02 +portmap_111=106:25:i +portmap_103=98:25:i +portmap_7=7:25:50:i +xgxs_rx_lane_map_11=0x2301 +xgxs_tx_lane_map_31=0x0213 +xgxs_tx_lane_map_23=0x2310 +xgxs_tx_lane_map_15=0x1023 +port_phy_addr_98=0xff + diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/default_sku b/device/juniper/x86_64-juniper_qfx5200-r0/default_sku new file mode 100644 index 000000000000..cf933bb4c87a --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/default_sku @@ -0,0 +1 @@ +Juniper-QFX5200-32C-S t1 diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/installer.conf b/device/juniper/x86_64-juniper_qfx5200-r0/installer.conf new file mode 100644 index 000000000000..e86aed7e522b --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=9600 +VAR_LOG_SIZE=1024 diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/led_proc_init.soc b/device/juniper/x86_64-juniper_qfx5200-r0/led_proc_init.soc new file mode 100644 index 000000000000..f2b749eeba03 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/led_proc_init.soc @@ -0,0 +1,49 @@ +# LED microprocessor initialization for Tomahawk + + + +setreg CMIC_LEDUP0_CLK_DIV 0x54 +setreg CMIC_LEDUP1_CLK_DIV 0x54 +setreg CMIC_LEDUP2_CLK_DIV 0x54 + +led 0 stop +led 0 prog 02 fd 42 80 02 ff 42 00 02 fe 42 00 02 fb 42 40 67 14 3a 40 06 fe 88 88 88 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 86 fe 06 fe d2 10 74 14 57 +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 0x411493 +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 0x515597 +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 0x30d38f +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 0x20928b +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 0xf3dfbf +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 0xe39ebb +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 0xd35db7 +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 0xc31cb3 +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 0xb2dbaf +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 0xa29aab +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 0x9259a7 +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 0x8218a3 +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 0x71d79f +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 0x61969b +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 0x105187 +setreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 0x1083 +led 0 auto on +led 0 start + +led 1 stop +led 1 prog 02 fd 42 80 02 ff 42 00 02 fe 42 00 02 fb 42 40 67 14 3a 40 06 fe 88 88 88 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 86 fe 06 fe d2 10 74 14 57 +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 0xb2dbaf +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 0xa29aab +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 0xc31cb3 +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 0xd35db7 +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 0x1083 +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 0x105187 +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 0x20928b +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 0x30d38f +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 0x411493 +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 0x515597 +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 0x61969b +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 0x71d79f +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 0x8218a3 +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 0x9259a7 +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 0xe39ebb +setreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 0xf3dfbf +led 1 auto on +led 1 start \ No newline at end of file diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/media_settings.json b/device/juniper/x86_64-juniper_qfx5200-r0/media_settings.json new file mode 100644 index 000000000000..c56f2457e411 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/media_settings.json @@ -0,0 +1,176 @@ +{ + "GLOBAL_MEDIA_SETTINGS": { + "0-31": { + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU2": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J3": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "JUNIPER-INNO-TR-FC13L-NJC": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "JUNIPER-INNO-TR-FC13R-NJC": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "JUNIPER-SOURCE-SPQCELRCDFAJ2": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x0c6400", + "lane1":"0x0c6400", + "lane2":"0x0c6400", + "lane3":"0x0c6400" + }, + "idriver": { + "lane0":"0xa", + "lane1":"0xa", + "lane2":"0xa", + "lane3":"0xa" + } + }, + "FINISAR CORP.-FTL4C1QE1C-J1": { + "preemphasis": { + "lane0":"0x115f00", + "lane1":"0x115f00", + "lane2":"0x115f00", + "lane3":"0x115f00" + }, + "idriver": { + "lane0":"0x0", + "lane1":"0x0", + "lane2":"0x0", + "lane3":"0x0" + } + } + } + }, + "PORT_MEDIA_SETTINGS": { + } +} diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/eeprom.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/eeprom.py new file mode 100644 index 000000000000..33898d83a0e9 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/eeprom.py @@ -0,0 +1,62 @@ +# +# Name: eeprom.py version: 1.0 +# +# Description: Platform-specific EEPROM interface for Juniper QFX5200 +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. + +try: + import os + from sonic_eeprom import eeprom_tlvinfo + import syslog + from array import * +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = "eeprom.py" +EEPROM_PATH = "/sys/bus/i2c/devices/0-0051/eeprom" + + +def log_error(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + + def __init__(self, name, path, cpld_root, ro): + + if not os.path.exists(EEPROM_PATH): + log_error("Cannot find system eeprom") + raise RuntimeError("No syseeprom found") + + self.eeprom_path = EEPROM_PATH + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/led_control.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/led_control.py new file mode 100644 index 000000000000..223c6dc8a289 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/led_control.py @@ -0,0 +1,184 @@ +# +# Name: led_control.py version: 1.0 +# +# Description: Platform-specific LED control functionality for Juniper QFX5200 +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. + +try: + from sonic_led.led_control_base import LedControlBase + import os + import syslog + import glob + from socket import * + from select import * +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("ledi_control") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + SONIC_PORT_NAME_PREFIX = "Ethernet" + LED_MODE_OFF = 0 + LED_MODE_GREEN = 1 + PORT_START = 0 + PORT_END = 127 + port_to_gpio_pin_mapping = {} + GPIO_SLAVE0_PORT_START = 0 + GPIO_SLAVE0_PORT_END = 63 + GPIO_SLAVE1_PORT_START = 64 + GPIO_SLAVE1_PORT_END = 127 + + GPIO_LANE0_PORT_LED_OFFSET = 64 + GPIO_LANE1_PORT_LED_OFFSET = 80 + GPIO_LANE2_PORT_LED_OFFSET = 96 + GPIO_LANE3_PORT_LED_OFFSET = 112 + + # Turn OFF all port leds during init + def gpio_create_file(self, gpio_pin): + gpio_export_path = "/sys/class/gpio/export" + gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin) + if not os.path.exists(gpio_pin_path): + try: + gpio_export_file = open(gpio_export_path, 'w') + gpio_export_file.write(str(gpio_pin)) + gpio_export_file.close() + except IOError as e: + print("Error: unable to open export file: %s" % str(e)) + return False + + return True + + def gpio_port_led_init(self, gpio_base, port): + port_led_pin = gpio_base + self.GPIO_LANE0_PORT_LED_OFFSET + 16*(port % 4) + ((port % 64)/4) + if self.gpio_create_file(port_led_pin): + self.port_to_gpio_pin_mapping[port] = port_led_pin + + def gpio_port_led_slave_init(self, gpio_base_path, gpio_port_start, gpio_port_end): + flist = glob.glob(gpio_base_path) + if len(flist) == 1: + try: + fp = open(flist[0] + "/base") + gpio_base = int(fp.readline().rstrip()) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return + for port in range(gpio_port_start, gpio_port_end + 1): + self.gpio_port_led_init(gpio_base, port) + + def gpio_port_led_base_init(self): + self.gpio_port_led_slave_init("/sys/bus/platform/drivers/gpioslave-tmc/gpioslave-tmc.22/gpio/gpio*", + self.GPIO_SLAVE0_PORT_START, self.GPIO_SLAVE0_PORT_END) + self.gpio_port_led_slave_init("/sys/bus/platform/drivers/gpioslave-tmc/gpioslave-tmc.21/gpio/gpio*", + self.GPIO_SLAVE1_PORT_START, self.GPIO_SLAVE1_PORT_END) + + # Write driver for port led + def gpio_led_write(self, gpio_pin, value): + success = False + gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin) + + try: + gpio_file = open(gpio_pin_path + "/value", 'w') + gpio_file.write(str(value)) + success = True + except IOError as e: + print("error: unable to open file: %s" % str(e)) + + return success + + # Read driver for port led + def gpio_led_read(self, gpio_pin): + gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin) + value = 0 + + try: + reg_file = open(gpio_pin_path + "/value") + value = int(reg_file.readline().rstrip()) + except IOError as e: + print("error: unable to open file: %s" % str(e)) + + return value + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + + for port in range(self.PORT_START, self.PORT_END): + self._port_led_mode_update(self.port_to_gpio_pin_mapping[port], self.LED_MODE_OFF) + + DBG_PRINT("init led done") + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + # Convert state up/down to Green/OFF which is 1/0 + def _port_state_to_mode(self, state): + if state == "up": + return self.LED_MODE_GREEN + else: + return self.LED_MODE_OFF + + # Set the port led mode to Green/OFF + + def _port_led_mode_update(self, gpio_pin, ledMode): + if ledMode == self.LED_MODE_GREEN: + self.gpio_led_write(gpio_pin, 1) + else: + self.gpio_led_write(gpio_pin, 0) + + # Concrete implementation of port_link_state_change() method + + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + gpio_pin = self.port_to_gpio_pin_mapping[port_idx] + + ledMode = self._port_state_to_mode(state) + saveMode = self.gpio_led_read(gpio_pin) + + if ledMode == saveMode: + return + + self._port_led_mode_update(gpio_pin, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) + + # Constructor + def __init__(self): + self.gpio_port_led_base_init() + self._initDefaultConfig() diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/psuutil.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/psuutil.py new file mode 100644 index 000000000000..7ee1d3c38a3d --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/psuutil.py @@ -0,0 +1,102 @@ +# +# Name: psuutil.py version: 1.0 +# +# Description: Platform-specific PSU status interface for Juniper QFX5200 +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + PSU_DIR = "/sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/psu-tmc.15" + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return int(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 (starts from 1) of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + attr_file = 'psu' + str(index-1) + '_' + 'present' + attr_path = self.PSU_DIR + '/' + attr_file + attr_value = self.get_attr_value(attr_path) + + return attr_value == 1 + + 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 + """ + attr_file = 'psu' + str(index-1) + '_' + 'present' + attr_path = self.PSU_DIR + '/' + attr_file + attr_value = self.get_attr_value(attr_path) + return attr_value == 1 diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/qfx5200_eeprom_data.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/qfx5200_eeprom_data.py new file mode 100644 index 000000000000..ea53f11e698d --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/qfx5200_eeprom_data.py @@ -0,0 +1,437 @@ +#!/usr/bin/env python3 +# +# Name: juniper_qfx5200_eepromconv.py version: 1.0 +# +# Description: This file contains the code to store the contents of Main Board EEPROM and CPU Board EEPROM in file +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. + +import binascii +import os +import sys +from sonic_eeprom import eeprom_tlvinfo + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + + +def fantype_detect(): + + refpgaTMC_path = "/sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15" + + AFO = "1" + AFI = "0" + + # default fan type is AFO + default_fantype = "0" + + for filename in os.listdir(refpgaTMC_path): + if filename.endswith('_type'): + fantype_path = os.path.join(refpgaTMC_path, filename) + cat_string = "cat " + fantype_string = cat_string + fantype_path + status, fan_type = commands.getstatusoutput(fantype_string) + if ((fan_type == AFO) or (fan_type == AFI)): + return fan_type + else: + pass + + return default_fantype + + +def main(): + AFO_value = "1" + + eeprom_qfx5200 = Eeprom() + + fan_type = fantype_detect() + + # creating the "/var/run/eeprom" file and storing values of CPU board EEPROM and MAIN Board EEPROM in this file. + eeprom_file = open("/var/run/eeprom", "a+") + eeprom_file.write("\n") + if fan_type == AFO_value: + eeprom_file.write("Fan Type=AFO\r\n") + else: + eeprom_file.write("Fan Type=AFI\r\n") + + eeprom_file.write("\n") + + # Write the contents of CPU Board EEPROM to file + eeprom_file.write("CPU board eeprom (0x51)\r\n") + eeprom_file.write("===============================\r\n") + eeprom_file.write("Product Name=%s\r\n" % eeprom_qfx5200.modelstr()) + eeprom_file.write("Part Number=%s\r\n" % eeprom_qfx5200.part_number_str()) + eeprom_file.write("Serial Number=%s\r\n" % eeprom_qfx5200.serial_number_str()) + eeprom_file.write("MAC Address=%s\r\n" % eeprom_qfx5200.base_mac_address()) + eeprom_file.write("Manufacture Date=%s\r\n" % eeprom_qfx5200.manuDate_str()) + eeprom_file.write("Platform Name=%s\r\n" % eeprom_qfx5200.platform_str()) + eeprom_file.write("Number of MAC Addresses=%s\r\n" % eeprom_qfx5200.MACsize_str()) + eeprom_file.write("Vendor Name=%s\r\n" % eeprom_qfx5200.vendor_name_str()) + eeprom_file.write("Manufacture Name=%s\r\n" % eeprom_qfx5200.manufacture_name_str()) + + eeprom_dict = eeprom_qfx5200.system_eeprom_info() + key = '0x29' + if key in list(eeprom_dict.keys()): + onie_version_str = eeprom_dict.get('0x29', None) + else: + onie_version_str = "N/A" + eeprom_file.write("ONIE Version=%s\r\n" % onie_version_str) + + vendor_value_formatted, vendor_value_hexvalue = eeprom_qfx5200.vendor_ext_str() + + eeprom_hex = '/etc/init.d/eeprom_qfx5200_hex' + + with open(eeprom_hex, 'wb+') as Hexfile: + Hexfile.write(vendor_value_hexvalue) + + # Assembly ID + ASMID_str = "0D83" + with open(eeprom_hex, 'rb+') as AsmID_Hexfile: + AsmID_Hexfile.seek(24, 0) + AsmID_Hexfile.write(ASMID_str) + AsmID_Hexfile.seek(0, 0) + vendorext_read = AsmID_Hexfile.read(58) + vendorext = "" + vendorext += "0x" + vendorext_read[0:2] + for i in range(2, 58, 2): + vendorext += " 0x" + vendorext_read[i:i+2] + eeprom_file.write("Vendor Extension=%s\r\n" % str(vendorext)) + + with open(eeprom_hex, 'rb') as eeprom_hexfile: + eeprom_hexfile.seek(0, 0) + IANA_position_read = eeprom_hexfile.read(8) + IANA_write = binascii.unhexlify(IANA_position_read) + eeprom_file.write("\t") + eeprom_file.write("IANA=0x%s\r\n" % IANA_write) + + eeprom_hexfile.seek(8, 0) + AssemblyPartRev_position_read = eeprom_hexfile.read(16) + AssemblyPartRev_write = binascii.unhexlify(AssemblyPartRev_position_read) + eeprom_file.write("\t") + eeprom_file.write("Assembly Part Number Revision=0x%s\r\n" % AssemblyPartRev_write) + + eeprom_hexfile.seek(24, 0) + AssemblyID_write = eeprom_hexfile.read(4) + eeprom_file.write("\t") + eeprom_file.write("Assembly ID=0x%s\r\n" % AssemblyID_write) + + eeprom_hexfile.seek(28, 0) + HWMajorRev_write = eeprom_hexfile.read(2) + eeprom_file.write("\t") + eeprom_file.write("HW Major Revision=0x%s\r\n" % HWMajorRev_write) + + eeprom_hexfile.seek(30, 0) + HWMinorRev_write = eeprom_hexfile.read(2) + eeprom_file.write("\t") + eeprom_file.write("HW Minor Revision=0x%s\r\n" % HWMinorRev_write) + + eeprom_hexfile.seek(32, 0) + Deviation_write = eeprom_hexfile.read(10) + eeprom_file.write("\t") + eeprom_file.write("Deviation=0x%s\r\n" % Deviation_write) + + eeprom_hexfile.seek(52, 0) + JEDC_write = eeprom_hexfile.read(4) + eeprom_file.write("\t") + eeprom_file.write("JEDC=0x%s\r\n" % JEDC_write) + + eeprom_hexfile.seek(56, 0) + EEPROM_version_write = eeprom_hexfile.read(2) + eeprom_file.write("\t") + eeprom_file.write("EEPROM version=0x%s\r\n" % EEPROM_version_write) + + crc_str = eeprom_dict.get('0xFE', None) + eeprom_file.write("CRC=%s\r\n" % crc_str) + + eeprom_file.write("\n") + eeprom_file.write("\n") + eeprom_file.write("Main board eeprom (0x57)\r\n") + eeprom_file.write("===============================\r\n") + + MainEepromCreate = 'sudo echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device' + # Write the contents of Main Board EEPROM to file + try: + os.system(MainEepromCreate) + except OSError: + print('Error: Execution of "%s" failed', MainEepromCreate) + return False + + MainEepromFileCmd = 'cat /sys/bus/i2c/devices/i2c-0/0-0057/eeprom > /etc/init.d/MainEeprom_qfx5200_ascii' + try: + os.system(MainEepromFileCmd) + except OSError: + print('Error: Execution of "%s" failed', MainEepromFileCmd) + return False + + maineeprom_ascii = '/etc/init.d/MainEeprom_qfx5200_ascii' + + # Read file contents in Hex format + with open(maineeprom_ascii, 'rb') as Hexformat: + content = Hexformat.read() + + Hexformatoutput = binascii.hexlify(content) + eeprom_hex = '/etc/init.d/MainEeprom_qfx5200_hex' + # Write contents of CPU EEPROM to new file in hexa format + with open(eeprom_hex, 'wb+') as Hexfile: + Hexfile.write(Hexformatoutput) + + with open(eeprom_hex, 'rb') as eeprom_hexfile: + eeprom_hexfile.seek(8, 0) + AssemblyID_read = eeprom_hexfile.read(4) + eeprom_file.write("Assembly ID=0x%s\r\n" % AssemblyID_read) + + eeprom_hexfile.seek(12, 0) + MajorHWRev_read = eeprom_hexfile.read(2) + eeprom_file.write("Assembly Major Revision=0x%s\r\n" % str(MajorHWRev_read)) + + eeprom_hexfile.seek(14, 0) + MinorHWRev_read = eeprom_hexfile.read(2) + eeprom_file.write("Assembly Minor Revision=0x%s\r\n" % str(MinorHWRev_read)) + + eeprom_hexfile.seek(24, 0) + AssemblyPNRev_read = eeprom_hexfile.read(16) + AssemblyPNRev_write = binascii.unhexlify(AssemblyPNRev_read) + eeprom_file.write("Assembly Part Number Revision=0x%s\r\n" % str(AssemblyPNRev_write)) + + eeprom_hexfile.seek(40, 0) + AssemblyPN_read = eeprom_hexfile.read(24) + AssemblyPN_write = binascii.unhexlify(AssemblyPN_read) + eeprom_file.write("Assembly Part Number=%s\r\n" % str(AssemblyPN_write)) + + eeprom_hexfile.seek(64, 0) + AssemblySN_read = eeprom_hexfile.read(24) + AssemblySN_write = binascii.unhexlify(AssemblySN_read) + eeprom_file.write("Assembly Serial Number=%s\r\n" % str(AssemblySN_write)) + + eeprom_hexfile.seek(90, 0) + AssemblyMFGDate_read = eeprom_hexfile.read(8) + eeprom_file.write("Manufacture Date=%s\r\n" % str(AssemblyMFGDate_read)) + + eeprom_hexfile.seek(138, 0) + CLEICode_read = eeprom_hexfile.read(20) + CLEI_name = binascii.unhexlify(CLEICode_read) + eeprom_file.write("CLEI Code=%s\r\n" % str(CLEI_name)) + + eeprom_hexfile.seek(158, 0) + FRUModelNumber_read = eeprom_hexfile.read(46) + FRUModelNumber_write = binascii.unhexlify(FRUModelNumber_read) + eeprom_file.write("FRU Model Number=%s\r\n" % str(FRUModelNumber_write)) + + eeprom_hexfile.seek(204, 0) + FRUModelMajorNumber_read = eeprom_hexfile.read(2) + eeprom_file.write("FRU Model Major Number=0x%s\r\n" % str(FRUModelMajorNumber_read)) + + eeprom_hexfile.seek(206, 0) + FRUModelMinorNumber_read = eeprom_hexfile.read(4) + eeprom_file.write("FRU Model Minor Number=0x%s\r\n" % str(FRUModelMinorNumber_read)) + + eeprom_hexfile.seek(210, 0) + Deviation_read = eeprom_hexfile.read(10) + eeprom_file.write("Deviation=0x%s\r\n" % str(Deviation_read)) + + eeprom_hexfile.seek(232, 0) + SerialNumber_read = eeprom_hexfile.read(24) + SerialNumber_write = binascii.unhexlify(SerialNumber_read) + eeprom_file.write("Chassis Serial Number=%s\r\n" % str(SerialNumber_write)) + eeprom_file.close() + return True + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + def __init__(self): + self.__eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0051/eeprom" + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + self.__eeprom_tlv_dict = dict() + try: + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + ord(eeprom[tlv_index + 1])] + code = "0x%02X" % (ord(tlv[0])) + + if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT: + value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) | + (ord(tlv[4]) << 8) | ord(tlv[5])) + value += str(tlv[6:6 + ord(tlv[1])]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32: + break + + tlv_index += ord(eeprom[tlv_index+1]) + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2] + + def base_mac_address(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(eeprom_tlvinfo.TlvInfoDecoder, self).switchaddrstr(self.__eeprom_data) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2] + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2] + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2] + + def manuDate_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MANUF_DATE) + if not is_valid: + return "N/A" + + return results[2] + + def platform_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PLATFORM_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def MACsize_str(self): + (is_valid, t) = self.get_tlv_field(self.__eeprom_data, self._TLV_CODE_MAC_SIZE) + + if not is_valid: + return "N/A" + + return str((ord(t[2][0]) << 8) | ord(t[2][1])) + + def vendor_name_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_VENDOR_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def manufacture_name_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MANUF_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def onie_version_str(self): + value = "" + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_ONIE_VERSION) + if not is_valid: + return "N/A" + + for c in results[2:2 + ord(results[1])]: + value += "0x%02X " % (ord(c),) + + return value + + def vendor_ext_str(self): + + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_VENDOR_EXT) + + if not is_valid: + return "N/A" + + vendor_value_formatted = ''.join([" 0x" + "%02X " % ord(x) for x in results[2]]).strip() + vendor_value_hexvalue = ''.join(["%02X" % ord(x) for x in results[2]]).strip() + + return vendor_value_formatted, vendor_value_hexvalue + + def crc_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_CRC_32) + if not is_valid: + return "N/A" + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.__eeprom_tlv_dict + + +if __name__ == "__main__": + main() diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/qfx5200_sfp_init.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/qfx5200_sfp_init.py new file mode 100644 index 000000000000..723a4073687e --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/qfx5200_sfp_init.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +# +# Name: juniper_sfp_init.py version: 1.0 +# +# Description: Platform-specific SFP Transceiver Initialization for Juniper QFX5200 +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. + +import time +import os.path +import sfputil as jnpr_sfp +from sonic_py_common.logger import Logger +from pprint import pprint + +SYSLOG_IDENTIFIER = "sfputil" + +# Global logger class instance +logger = Logger(SYSLOG_IDENTIFIER) + +DEBUG = False + + +def i2c_eeprom_dev_update(port, create_eeprom): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + i2c_path = "/sys/class/i2c-adapter/i2c-{0}" + i2c_port = port + jnpr_sfp.SFP_I2C_OFFSET + port_eeprom_path = eeprom_path.format(i2c_port) + port_i2c_path = i2c_path.format(i2c_port) + if create_eeprom: + if not os.path.exists(port_eeprom_path): + try: + i2c_file = open(port_i2c_path + "/new_device", "w") + i2c_file.write("optoe2 0x50") + except IOError as e: + print("Error: unable to write to i2c file: %s" % str(e)) + return + else: + if os.path.exists(port_eeprom_path): + try: + i2c_file = open(port_i2c_path + "/delete_device", "w") + i2c_file.write("0x50") + except IOError as e: + print("Error: unable to write to i2c file: %s" % str(e)) + return + + +def gpio_sfp_init(): + jnpr_sfp.gpio_sfp_base_init() + + time.sleep(2) + + # Reset all ports + for port in range(jnpr_sfp.GPIO_PORT_START, jnpr_sfp.GPIO_PORT_END + 1): + logger.log_debug("GPIO SFP port {}".format(port)) + + jnpr_sfp.gpio_sfp_reset_set(port, 0) + i2c_eeprom_dev_update(port, True) + + time.sleep(1) + + # Enable optics for all ports which have XCVRs present + for port in range(jnpr_sfp.GPIO_PORT_START, jnpr_sfp.GPIO_PORT_END + 1): + jnpr_sfp.gpio_sfp_lpmode_set(port, 1) + + +if __name__ == '__main__': + + if DEBUG == True: + print("Initializing Juniper SFP module") + + gpio_sfp_init() + if DEBUG == True: + print("Juniper GPIO presence pin mapping:") + pprint(jnpr_sfp.gpio_sfp_presence) + print("Juniper GPIO reset pin mapping:") + pprint(jnpr_sfp.gpio_sfp_reset) + print("Juniper GPIO lpmode pin mapping:") + pprint(jnpr_sfp.gpio_sfp_lpmode) diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/sfputil.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/sfputil.py new file mode 100644 index 000000000000..db85347be3f4 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/sfputil.py @@ -0,0 +1,1143 @@ +# Name: sfputil.py version: 1.0 +# +# Description: Platform-specific SFP transceiver interface for Juniper QFX5200 +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. + +try: + import time + import os.path + import glob + import io + from sonic_sfp.sfputilbase import SfpUtilBase + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_py_common.logger import Logger + from ctypes import create_string_buffer + +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +SYSLOG_IDENTIFIER = "sfputil" + +# Global Logger class instance +logger = Logger(SYSLOG_IDENTIFIER) + +qfx5200_qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +qfx5200_sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +qfx5200_sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +qfx5200_qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + + +GPIO_SLAVE0_PORT_START = 0 +GPIO_SLAVE0_PORT_END = 15 +GPIO_SLAVE1_PORT_START = 16 +GPIO_SLAVE1_PORT_END = 31 + +GPIO_PORT_START = 0 +GPIO_PORT_END = 31 + +GPIO_PRESENCE_OFFSET = 16 +GPIO_LPMODE_OFFSET = 48 +GPIO_RESET_OFFSET = 0 + +gpio_sfp_presence = {} +gpio_sfp_lpmode = {} +gpio_sfp_reset = {} + +SFP_I2C_OFFSET = 14 + + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_WIDTH = 1 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + + +# definitions of the offset for values in OSFP info eeprom +OSFP_TYPE_OFFSET = 0 +OSFP_VENDOR_NAME_OFFSET = 129 +OSFP_VENDOR_PN_OFFSET = 148 +OSFP_HW_REV_OFFSET = 164 +OSFP_VENDOR_SN_OFFSET = 166 + +# definitions of the offset and width for values in DOM info eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNL_THRESHOLD_OFFSET = 176 +QSFP_CHANNL_THRESHOLD_WIDTH = 16 + + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 + + +def gpio_create_file(gpio_pin): + gpio_export_path = "/sys/class/gpio/export" + gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin) + if not os.path.exists(gpio_pin_path): + try: + gpio_export_file = open(gpio_export_path, 'w') + gpio_export_file.write(str(gpio_pin)) + gpio_export_file.close() + except IOError as e: + print("Error: unable to open export file: %s" % str(e)) + return False + + return True + + +def gpio_sfp_port_init(gpio_base, port): + presence_pin = gpio_base + GPIO_PRESENCE_OFFSET + (port % 16) + if gpio_create_file(presence_pin): + gpio_sfp_presence[port] = presence_pin + reset_pin = gpio_base + GPIO_RESET_OFFSET + (port % 16) + if gpio_create_file(reset_pin): + gpio_sfp_reset[port] = reset_pin + lpmode_pin = gpio_base + GPIO_LPMODE_OFFSET + (port % 16) + if gpio_create_file(lpmode_pin): + gpio_sfp_lpmode[port] = lpmode_pin + + +def gpio_sfp_slave_init(gpio_base_path, gpio_port_start, gpio_port_end): + flist = glob.glob(gpio_base_path) + if len(flist) == 1: + try: + fp = open(flist[0]+"/base") + gpio_base = int(fp.readline().rstrip()) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return + + for port in range(gpio_port_start, gpio_port_end + 1): + gpio_sfp_port_init(gpio_base, port) + + +def gpio_sfp_base_init(): + gpio_sfp_slave_init("/sys/bus/platform/drivers/gpioslave-tmc/gpioslave-tmc.21/gpio/gpio*", + GPIO_SLAVE0_PORT_START, GPIO_SLAVE0_PORT_END) + gpio_sfp_slave_init("/sys/bus/platform/drivers/gpioslave-tmc/gpioslave-tmc.22/gpio/gpio*", + GPIO_SLAVE1_PORT_START, GPIO_SLAVE1_PORT_END) + + +def gpio_sfp_read(gpio_pin): + gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin) + value = 0 + + try: + reg_file = open(gpio_pin_path + "/value") + value = int(reg_file.readline().rstrip()) + except IOError as e: + print("error: unable to open file: %s" % str(e)) + + return value + + +def gpio_sfp_write(gpio_pin, value): + success = False + gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin) + + try: + gpio_file = open(gpio_pin_path + "/value", 'w') + gpio_file.write(str(value)) + success = True + except IOError as e: + print("error: unable to open file: %s" % str(e)) + + return success + + +def gpio_sfp_presence_get(port): + if port not in list(gpio_sfp_presence.keys()): + print("Port:" + str(port) + " not in sfp dict") + return 0 + + gpio_pin = gpio_sfp_presence[port] + return gpio_sfp_read(gpio_pin) + + +def gpio_sfp_lpmode_get(port): + if port not in list(gpio_sfp_lpmode.keys()): + return 0 + + gpio_pin = gpio_sfp_lpmode[port] + return gpio_sfp_read(gpio_pin) + + +def gpio_sfp_lpmode_set(port, value): + if port not in list(gpio_sfp_lpmode.keys()): + return False + + gpio_pin = gpio_sfp_lpmode[port] + return gpio_sfp_write(gpio_pin, value) + + +def gpio_sfp_reset_set(port, value): + if port not in list(gpio_sfp_reset.keys()): + return False + + gpio_pin = gpio_sfp_reset[port] + return gpio_sfp_write(gpio_pin, value) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + QSFP_PORT_START = 0 + QSFP_PORT_END = 31 + + cmd = '/var/run/sfppresence' + + _port_to_eeprom_mapping = {} + port_to_i2cbus_mapping = { + 0: 14, + 1: 15, + 2: 16, + 3: 17, + 4: 18, + 5: 19, + 6: 20, + 7: 21, + 8: 22, + 9: 23, + 10: 24, + 11: 25, + 12: 26, + 13: 27, + 14: 28, + 15: 29, + 16: 30, + 17: 31, + 18: 32, + 19: 33, + 20: 34, + 21: 35, + 22: 36, + 23: 37, + 24: 38, + 25: 39, + 26: 40, + 27: 41, + 28: 42, + 29: 43, + 30: 44, + 31: 45 + } + + port_ctle_settings = { + 0: 119, # 0x77 + 1: 102, # 0x66 + 2: 102, # 0x66 + 3: 102, # 0x66 + 4: 102, # 0x66 + 5: 85, # 0x55 + 6: 102, # 0x66 + 7: 85, # 0x55 + 8: 85, # 0x55 + 9: 85, # 0x55 + 10: 119, # 0x77 + 11: 119, # 0x77 + 12: 102, # 0x66 + 13: 85, # 0x55 + 14: 68, # 0x44 + 15: 51, # 0x33 + 16: 68, # 0x44 + 17: 85, # 0x55 + 18: 102, # 0x66 + 19: 102, # 0x66 + 20: 119, # 0X77 + 21: 102, # 0x66 + 22: 85, # 0X55 + 23: 85, # 0X55 + 24: 85, # 0x55 + 25: 85, # 0x55 + 26: 102, # 0x66 + 27: 85, # 0x55 + 28: 102, # 0x66 + 29: 102, # 0x66 + 30: 119, # 0x77 + 31: 119 # 0x77 + } + + optics_list_100g = { + "AFBR-89CDDZ-JU1", + "AFBR-89CDDZ-JU2", + "FTLC9551REPM-J1", + "FCBN425QE1C30-J1", + "FCBN425QE1C10-J1", + "FTLC9551REPM-J3", + "LUX42604CO", + "LUX42604BO", + "EOLQ-161HG-10-LJ1", + "FTLC1151RDPL-J1", + "TR-FC13R-NJC", + "TR-FC13L-NJC", + "TR-FC13R-NJ3", + "SPQ-CE-LR-CDFB-J2", + "1K1QAC", + "SPQCELRCDFAJ2" + } + + optics_list_40g = { + "FTL4C1QE1C-J1" + } + + def clear_bit(self, data, pos): + return (data & (~(1 << pos))) + + def check_bit(self, data, pos): + return (data & (1 << pos)) + + def set_bit(self, data, pos): + return (data | (1 << pos)) + + def is_100g_optics(self, part_num): + ret = part_num in self.optics_list_100g + return ret + + def is_40g_optics(self, part_num): + ret = part_num in self.optics_list_40g + return ret + + def is_optics(self, part_num): + if self.is_100g_optics(part_num): + return True + elif self.is_40g_optics(part_num): + return True + else: + return False + + def process_TxCTLE(self, eeprom, port_num, part_num): + if self.is_100g_optics(part_num): + logger.log_debug(" QFX5200: TxCTLE port {} and SFP PN NUM {} ".format(port_num, part_num)) + # Accessing page 3 of optics + regval = 3 + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + eeprom.seek(127) + eeprom.write(buffer[0]) + + regval = self.port_ctle_settings[port_num] + logger.log_debug("QFX5200: TxCTLE port {}, SFP PN NUM {}, regval {} ".format(port_num, part_num, regval)) + + eeprom.seek(234) + buffer[0] = chr(regval) + eeprom.write(buffer[0]) + eeprom.seek(235) + eeprom.write(buffer[0]) + # Moving back the optics page to 0 + regval = 0x0 + buffer[0] = chr(regval) + eeprom.seek(127) + eeprom.write(buffer[0]) + else: + pass + + def is_highpower_optics(self, data): + return (self.check_bit(data, 0) | self.check_bit(data, 1)) + + def is_cdr_present(self, data): + return (self.check_bit(data, 2) | self.check_bit(data, 3)) + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + gpio_sfp_base_init() + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + for x in range(0, self.port_end + 1): + self.port_to_eeprom_mapping[x] = eeprom_path.format(self.port_to_i2cbus_mapping[x]) + + logger.log_debug("QFX5200: SfpUtil __init__") + if os.path.isfile(self.cmd): + logger.log_debug("QFX5200: SfpUtil removing sfppresence file") + os.remove(self.cmd) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + reg_value = gpio_sfp_presence_get(port_num) + if reg_value == 1: + return True + + return False + + def get_low_power_mode(self, port_num): + reg_value = gpio_sfp_lpmode_get(port_num) + if reg_value == 0: + return True + + return False + + def set_low_power_mode(self, port_num, lpmode): + + if lpmode == False: + lpmode = 1 + else: + lpmode = 0 + + status = gpio_sfp_lpmode_set(port_num, lpmode) + return status + + def reset(self, port_num): + reset_val = 0 + status = gpio_sfp_reset_set(port_num, reset_val) + return status + + # Writing to a file from a list + def write_to_file(self, file_name, from_list): + try: + fp1 = open(file_name, 'w') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + for i in from_list: + fp1.write(i) + fp1.write('\n') + + fp1.close() + return True + + # Reading from a file to a list + + def read_from_file(self, file_name): + try: + fp = open(file_name, 'r') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + to_list = fp.readlines() + to_list = [x.rstrip() for x in to_list] + fp.close() + return to_list + + def sfp_detect(self): + port = 0 + ret_dict = {} + defl_dict = {} + current_sfp_values = [0] * 32 + previous_sfp_values = [0] * 32 + + logger.log_debug("QFX5200: sfp_detect Start") + if not os.path.isfile(self.cmd): + logger.log_debug("QFX5200: sfppresence file not created") + else: + if (self.read_from_file(self.cmd) == False): + logger.log_debug("QFX5200: sfp_detect not able to open sfppresence file") + return False, defl_dict + else: + previous_sfp_values = self.read_from_file(self.cmd) + logger.log_debug("QFX5200: sfp_detect sfppresence file present, previous_sfp_values populated") + + # Read the current values from sysfs + for port in range(GPIO_PORT_START, GPIO_PORT_END + 1): + sfp_present = gpio_sfp_presence_get(port) + current_sfp_values[port] = str(sfp_present) + ret_dict.update({port: current_sfp_values[port]}) + + prev_value = str(previous_sfp_values[port]) + + current_value = current_sfp_values[port] + if (prev_value != current_value): + ret_dict.update({port: current_sfp_values[port]}) + value = str(current_sfp_values[port]) + if (value): + offset = 128 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + return None + + file_path = self._get_port_eeprom_path(port, self.IDENTITY_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + print("Error, file not exist %s" % file_path) + return None + + try: + sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + sfp_pn_num = str(sfp_vendor_pn_data['data']['Vendor PN']['value']) + if self.is_optics(sfp_pn_num): + logger.log_debug( + "QFX5200: Port {} is connected with Optics with Part Number {}".format(port, sfp_pn_num)) + eeprom1 = open(self._port_to_eeprom_mapping[port], "r+b") + self.process_TxCTLE(eeprom1, port, sfp_pn_num) + eeprom1.close + # End of if(value) + # End of current_sfp_values != previous_sfp_vlalues + # End of for loop + + if(self.write_to_file(self.cmd, current_sfp_values) == True): + logger.log_debug("QFX5200: sfp_detect, current sfp values written successfully to sfppresence file") + logger.log_debug("QFX5200: sfp_detect ret_dict is {}".format(ret_dict)) + return True, ret_dict + else: + logger.log_debug("QFX5200: sfp_detect, current sfp values not written to sfppresence file") + logger.log_debug("QFX5200: sfp_detect ret_dict is {}".format(def1_dict)) + return False, defl_dict + + # Read out SFP type, vendor name, PN, REV, SN from eeprom. + def get_transceiver_info_dict(self, port_num): + transceiver_info_dict = {} + compliance_code_dict = {} + logger.log_debug("QFX5200: get_transceiver_info_dict Start") + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + if port_num in self.osfp_ports: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP + + sfpi_obj = inf8628InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + print("Error, file not exist %s" % file_path) + return None + + try: + sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfp_type_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + OSFP_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_type_data['data']['type_abbrv_name']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + # Below part is added to avoid fail the xcvrd, shall be implemented later + transceiver_info_dict['vendor_oui'] = 'N/A' + transceiver_info_dict['vendor_date'] = 'N/A' + transceiver_info_dict['connector'] = 'N/A' + transceiver_info_dict['encoding'] = 'N/A' + transceiver_info_dict['ext_identifier'] = 'N/A' + transceiver_info_dict['ext_rateselect_compliance'] = 'N/A' + transceiver_info_dict['cable_type'] = 'N/A' + transceiver_info_dict['cable_length'] = 'N/A' + transceiver_info_dict['specification_compliance'] = 'N/A' + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + + else: + if port_num in self.qsfp_ports: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + sfp_type = 'QSFP' + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + sfp_type = 'SFP' + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + print("Error, file not exist %s" % file_path) + return None + + try: + sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfp_interface_bulk_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_INTFACE_BULK_OFFSET), interface_info_bulk_width) + if sfp_interface_bulk_raw is not None: + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + sfp_vendor_oui_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + else: + return None + + sfp_vendor_date_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + if sfp_vendor_date_raw is not None: + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + else: + return None + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + if sfp_type == 'QSFP': + for key in qfx5200_qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + break + else: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = 'N/A' + + for key in qfx5200_qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + if 'Nominal Bit Rate(100Mbs)' in sfp_interface_bulk_data['data']: + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + else: + for key in qfx5200_sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + else: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = 'N/A' + + for key in qfx5200_sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + if 'NominalSignallingRate(UnitsOf100Mbd)' in sfp_interface_bulk_data['data']: + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + else: + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + + logger.log_debug("QFX5200: get_transceiver_info_dict End") + return transceiver_info_dict + + def get_transceiver_dom_info_dict(self, port_num): + transceiver_dom_info_dict = {} + + logger.log_debug("QFX5200: get_transceiver_dom_info_dict Start") + if port_num in self.osfp_ports: + # Below part is added to avoid fail xcvrd, shall be implemented later + transceiver_dom_info_dict['temperature'] = 'N/A' + transceiver_dom_info_dict['voltage'] = 'N/A' + transceiver_dom_info_dict['rx1power'] = 'N/A' + 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'] = 'N/A' + 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'] = 'N/A' + transceiver_dom_info_dict['tx2power'] = 'N/A' + transceiver_dom_info_dict['tx3power'] = 'N/A' + transceiver_dom_info_dict['tx4power'] = 'N/A' + + elif 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 = 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 None + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + return None + + # 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_dom_capability(qsfp_dom_capability_raw, 0) + else: + return None + + 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 None + + 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 None + + 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 None + + 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 None + + 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 = open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + dom_temperature_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + else: + return None + + 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 None + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + SFP_CHANNL_MON_OFFSET), SFP_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 None + + 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' + + logger.log_debug("QFX5200: get_transceiver_dom_info_dict End") + 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') + + logger.log_debug("QFX5200: get_transceiver_dom_threshold_info_dict Start") + if port_num in self.qsfp_ports: + file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = io.open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + # Dom Threshold data starts from offset 384 + # Revert offset back to 0 once data is retrieved + offset = 384 + dom_module_threshold_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, + (offset + QSFP_MODULE_THRESHOLD_OFFSET), + QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + dom_channel_threshold_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, + (offset + QSFP_CHANNL_THRESHOLD_OFFSET), + QSFP_CHANNL_THRESHOLD_WIDTH) + if dom_channel_threshold_raw is not None: + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + # Threshold Data + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] + + else: + offset = 256 + file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = io.open(file_path, "rb", 0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8472Dom(None, 1) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, + (offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH) + + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + # Threshold Data + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + + logger.log_debug("QFX5200: get_transceiver_dom_threshold_info_dict End") + return transceiver_dom_threshold_info_dict + + def get_transceiver_change_event(self, timeout=2000): + time.sleep(3) + return self.sfp_detect() diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/pmon_daemon_control.json b/device/juniper/x86_64-juniper_qfx5200-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..1863ee2e5190 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5200-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_thermalctld": true +} diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/buffers.json.j2 b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/buffers.json.j2 new file mode 100644 index 000000000000..a9a01d707ebf --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/buffers.json.j2 @@ -0,0 +1 @@ +{%- include 'buffers_config.j2' %} diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/buffers_defaults_t1.j2 b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..3442612f70b2 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/buffers_defaults_t1.j2 @@ -0,0 +1,46 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "33329088", + "type": "ingress", + "mode": "dynamic", + "xoff": "7827456" + }, + "egress_lossy_pool": { + "size": "26663272", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "42349632", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "static_th":"44302336" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"42349632" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1664", + "dynamic_th":"-1" + } + }, +{%- endmacro %} diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/port_config.ini b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/port_config.ini new file mode 100644 index 000000000000..da3321b55666 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index speed +Ethernet0 73,74,75,76 hundredGigE1 0 100000 +Ethernet4 65,66,67,68 hundredGigE2 1 100000 +Ethernet8 81,82,83,84 hundredGigE3 2 100000 +Ethernet12 89,90,91,92 hundredGigE4 3 100000 +Ethernet16 105,106,107,108 hundredGigE5 4 100000 +Ethernet20 97,98,99,100 hundredGigE6 5 100000 +Ethernet24 113,114,115,116 hundredGigE7 6 100000 +Ethernet28 121,122,123,124 hundredGigE8 7 100000 +Ethernet32 41,42,43,44 hundredGigE9 8 100000 +Ethernet36 33,34,35,36 hundredGigE10 9 100000 +Ethernet40 49,50,51,52 hundredGigE11 10 100000 +Ethernet44 57,58,59,60 hundredGigE12 11 100000 +Ethernet48 137,138,139,140 hundredGigE13 12 100000 +Ethernet52 129,130,131,132 hundredGigE14 13 100000 +Ethernet56 145,146,147,148 hundredGigE15 14 100000 +Ethernet60 153,154,155,156 hundredGigE16 15 100000 +Ethernet64 173,174,175,176 hundredGigE17 16 100000 +Ethernet68 165,166,167,168 hundredGigE18 17 100000 +Ethernet72 181,182,183,184 hundredGigE19 18 100000 +Ethernet76 189,190,191,192 hundredGigE20 19 100000 +Ethernet80 13,14,15,16 hundredGigE21 20 100000 +Ethernet84 5,6,7,8 hundredGigE22 21 100000 +Ethernet88 29,30,31,32 hundredGigE23 22 100000 +Ethernet92 21,22,23,24 hundredGigE24 23 100000 +Ethernet96 205,206,207,208 hundredGigE25 24 100000 +Ethernet100 197,198,199,200 hundredGigE26 25 100000 +Ethernet104 213,214,215,216 hundredGigE27 26 100000 +Ethernet108 221,222,223,224 hundredGigE28 27 100000 +Ethernet112 229,230,231,232 hundredGigE29 28 100000 +Ethernet116 237,238,239,240 hundredGigE30 29 100000 +Ethernet120 245,246,247,248 hundredGigE31 30 100000 +Ethernet124 253,254,255,256 hundredGigE32 31 100000 +Ethernet128 69,70,71,72 hundredGigE33 32 100000 +Ethernet132 77,78,79,80 hundredGigE34 33 100000 +Ethernet136 93,94,95,96 hundredGigE35 34 100000 +Ethernet140 85,86,87,88 hundredGigE36 35 100000 +Ethernet144 101,102,103,104 hundredGigE37 36 100000 +Ethernet148 109,110,111,112 hundredGigE38 37 100000 +Ethernet152 125,126,127,128 hundredGigE39 38 100000 +Ethernet156 117,118,119,120 hundredGigE40 39 100000 +Ethernet160 37,38,39,40 hundredGigE41 40 100000 +Ethernet164 45,46,47,48 hundredGigE42 41 100000 +Ethernet168 61,62,63,64 hundredGigE43 42 100000 +Ethernet172 53,54,55,56 hundredGigE44 43 100000 +Ethernet176 133,134,135,136 hundredGigE45 44 100000 +Ethernet180 141,142,143,144 hundredGigE46 45 100000 +Ethernet184 157,158,159,160 hundredGigE47 46 100000 +Ethernet188 149,150,151,152 hundredGigE48 47 100000 +Ethernet192 161,162,163,164 hundredGigE49 48 100000 +Ethernet196 169,170,171,172 hundredGigE50 49 100000 +Ethernet200 185,186,187,188 hundredGigE51 50 100000 +Ethernet204 177,178,179,180 hundredGigE52 51 100000 +Ethernet208 1,2,3,4 hundredGigE53 52 100000 +Ethernet212 9,10,11,12 hundredGigE54 53 100000 +Ethernet216 25,26,27,28 hundredGigE55 54 100000 +Ethernet220 17,18,19,20 hundredGigE56 55 100000 +Ethernet224 193,194,195,196 hundredGigE57 56 100000 +Ethernet228 201,202,203,204 hundredGigE58 57 100000 +Ethernet232 217,218,219,220 hundredGigE59 58 100000 +Ethernet236 209,210,211,212 hundredGigE60 59 100000 +Ethernet240 225,226,227,228 hundredGigE61 60 100000 +Ethernet244 233,234,235,236 hundredGigE62 61 100000 +Ethernet248 249,250,251,252 hundredGigE63 62 100000 +Ethernet252 241,242,243,244 hundredGigE64 63 100000 diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/qos.json.j2 b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/sai.profile b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/sai.profile new file mode 100644 index 000000000000..768a7fa47ad4 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-qfx5210-64x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/th2-qfx5210-64x100G.config.bcm b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/th2-qfx5210-64x100G.config.bcm new file mode 100644 index 000000000000..4d6e2f988c65 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/th2-qfx5210-64x100G.config.bcm @@ -0,0 +1,875 @@ +# Broadcom Tomahawk SDK configuration +os=unix +schan_intr_enable=0 +l2_mem_entries=40960 +l2xmsg_mode=1 +l3_mem_entries=40960 +parity_correction=0 +parity_enable=0 +mmu_lossless=1 + +pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +pbmp_oversubscribe=0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +# platform specific setting +arl_clean_timeout_usec=15000000 +asf_mem_profile=2 +bcm_num_cos=10 +bcm_stat_flags=1 +bcm_stat_jumbo=9236 +cdma_timeout_usec=15000000 +dma_desc_timeout_usec=15000000 +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 +max_vp_lags=0 +miim_intr_enable=0 +module_64ports=1 +oversubscribe_mode=1 + +#add loopback port +# port 33 is the first loopback port +# portmap_33=260:10 +# port 66 is the first management port +# portmap_66=257:10 +# port 67 is the second loopback port +# portmap_67=261:10 +# port 100 is the second management port +# portmap_100=259:10 +# port 101 is the third loopback port +# portmap_101=262:10 +# port 135 is the fourth loopback port +# portmap_135=263:10 + +#Port0 +#FC18 +portmap_36=73:100 +phy_chain_rx_lane_map_physical{73.0}=0x3210 +phy_chain_tx_lane_map_physical{73.0}=0x3021 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x0 +phy_chain_rx_polarity_flip_physical{76.0}=0x1 +phy_chain_tx_polarity_flip_physical{73.0}=0x0 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x1 +phy_chain_tx_polarity_flip_physical{76.0}=0x0 +#Port1 +#FC16 +portmap_34=65:100 +phy_chain_rx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x0 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 +phy_chain_tx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +phy_chain_tx_polarity_flip_physical{68.0}=0x0 +#Port2 +#FC20 +portmap_38=81:100 +phy_chain_rx_lane_map_physical{81.0}=0x1230 +phy_chain_tx_lane_map_physical{81.0}=0x1032 +phy_chain_rx_polarity_flip_physical{81.0}=0x1 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x1 +phy_chain_rx_polarity_flip_physical{84.0}=0x0 +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}=0x0 +#Port3 +#FC22 +portmap_40=89:100 +phy_chain_rx_lane_map_physical{89.0}=0x0132 +phy_chain_tx_lane_map_physical{89.0}=0x1203 +phy_chain_rx_polarity_flip_physical{89.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x0 +phy_chain_rx_polarity_flip_physical{92.0}=0x1 +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{90.0}=0x0 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x1 +#Port4 +#FC26 +portmap_44=105:100 +phy_chain_rx_lane_map_physical{105.0}=0x3210 +phy_chain_tx_lane_map_physical{105.0}=0x0231 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_tx_polarity_flip_physical{107.0}=0x0 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 +#Port5 +#FC24 +portmap_42=97:100 +phy_chain_rx_lane_map_physical{97.0}=0x0213 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_rx_polarity_flip_physical{97.0}=0x1 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.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}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +#Port6 +#FC 28 +portmap_46=113:100 +phy_chain_rx_lane_map_physical{113.0}=0x3021 +phy_chain_tx_lane_map_physical{113.0}=0x0312 +phy_chain_rx_polarity_flip_physical{113.0}=0x0 +phy_chain_rx_polarity_flip_physical{114.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +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}=0x1 +#Port7 +#FC30 +portmap_48=121:100 +phy_chain_rx_lane_map_physical{121.0}=0x3021 +phy_chain_tx_lane_map_physical{121.0}=0x2130 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +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_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +phy_chain_tx_polarity_flip_physical{123.0}=0x1 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 +#Port8 +#FC10 +portmap_11=41:100 +phy_chain_rx_lane_map_physical{41.0}=0x0132 +phy_chain_tx_lane_map_physical{41.0}=0x1302 +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}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x1 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +#Port9 +#FC8 +portmap_9=33:100 +phy_chain_rx_lane_map_physical{33.0}=0x2310 +phy_chain_tx_lane_map_physical{33.0}=0x0213 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +#Port10 +#FC12 +portmap_13=49:100 +phy_chain_rx_lane_map_physical{49.0}=0x3210 +phy_chain_tx_lane_map_physical{49.0}=0x3102 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +#Port11 +#FC14 +portmap_15=57:100 +phy_chain_rx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_lane_map_physical{57.0}=0x1302 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x1 +#Port12 +#FC34 +portmap_70=137:100 +phy_chain_rx_lane_map_physical{137.0}=0x3210 +phy_chain_tx_lane_map_physical{137.0}=0x0213 +phy_chain_rx_polarity_flip_physical{137.0}=0x0 +phy_chain_rx_polarity_flip_physical{138.0}=0x0 +phy_chain_rx_polarity_flip_physical{139.0}=0x1 +phy_chain_rx_polarity_flip_physical{140.0}=0x0 +phy_chain_tx_polarity_flip_physical{137.0}=0x1 +phy_chain_tx_polarity_flip_physical{138.0}=0x0 +phy_chain_tx_polarity_flip_physical{139.0}=0x0 +phy_chain_tx_polarity_flip_physical{140.0}=0x0 +#Port13 +#FC32 +portmap_68=129:100 +phy_chain_rx_lane_map_physical{129.0}=0x3021 +phy_chain_tx_lane_map_physical{129.0}=0x1203 +phy_chain_rx_polarity_flip_physical{129.0}=0x1 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 +phy_chain_tx_polarity_flip_physical{129.0}=0x1 +phy_chain_tx_polarity_flip_physical{130.0}=0x1 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 +#Port14 +#FC36 +portmap_72=145:100 +phy_chain_rx_lane_map_physical{145.0}=0x0213 +phy_chain_tx_lane_map_physical{145.0}=0x2301 +phy_chain_rx_polarity_flip_physical{145.0}=0x1 +phy_chain_rx_polarity_flip_physical{146.0}=0x1 +phy_chain_rx_polarity_flip_physical{147.0}=0x0 +phy_chain_rx_polarity_flip_physical{148.0}=0x0 +phy_chain_tx_polarity_flip_physical{145.0}=0x0 +phy_chain_tx_polarity_flip_physical{146.0}=0x0 +phy_chain_tx_polarity_flip_physical{147.0}=0x0 +phy_chain_tx_polarity_flip_physical{148.0}=0x1 +#Port15 +#FC38 +portmap_74=153:100 +phy_chain_rx_lane_map_physical{153.0}=0x0213 +phy_chain_tx_lane_map_physical{153.0}=0x1302 +phy_chain_rx_polarity_flip_physical{153.0}=0x1 +phy_chain_rx_polarity_flip_physical{154.0}=0x0 +phy_chain_rx_polarity_flip_physical{155.0}=0x1 +phy_chain_rx_polarity_flip_physical{156.0}=0x1 +phy_chain_tx_polarity_flip_physical{153.0}=0x0 +phy_chain_tx_polarity_flip_physical{154.0}=0x1 +phy_chain_tx_polarity_flip_physical{155.0}=0x0 +phy_chain_tx_polarity_flip_physical{156.0}=0x0 +#Port16 +#FC43 +portmap_79=173:100 +phy_chain_rx_lane_map_physical{173.0}=0x1032 +phy_chain_tx_lane_map_physical{173.0}=0x1203 +phy_chain_rx_polarity_flip_physical{173.0}=0x0 +phy_chain_rx_polarity_flip_physical{174.0}=0x0 +phy_chain_rx_polarity_flip_physical{175.0}=0x0 +phy_chain_rx_polarity_flip_physical{176.0}=0x0 +phy_chain_tx_polarity_flip_physical{173.0}=0x1 +phy_chain_tx_polarity_flip_physical{174.0}=0x1 +phy_chain_tx_polarity_flip_physical{175.0}=0x0 +phy_chain_tx_polarity_flip_physical{176.0}=0x1 +#Port17 +#FC41 +portmap_77=165:100 +phy_chain_rx_lane_map_physical{165.0}=0x1230 +phy_chain_tx_lane_map_physical{165.0}=0x2130 +phy_chain_rx_polarity_flip_physical{165.0}=0x1 +phy_chain_rx_polarity_flip_physical{166.0}=0x0 +phy_chain_rx_polarity_flip_physical{167.0}=0x1 +phy_chain_rx_polarity_flip_physical{168.0}=0x1 +phy_chain_tx_polarity_flip_physical{165.0}=0x1 +phy_chain_tx_polarity_flip_physical{166.0}=0x0 +phy_chain_tx_polarity_flip_physical{167.0}=0x1 +phy_chain_tx_polarity_flip_physical{168.0}=0x0 +#Port18 +#FC45 +portmap_81=181:100 +phy_chain_rx_lane_map_physical{181.0}=0x0312 +phy_chain_tx_lane_map_physical{181.0}=0x3120 +phy_chain_rx_polarity_flip_physical{181.0}=0x0 +phy_chain_rx_polarity_flip_physical{182.0}=0x1 +phy_chain_rx_polarity_flip_physical{183.0}=0x1 +phy_chain_rx_polarity_flip_physical{184.0}=0x0 +phy_chain_tx_polarity_flip_physical{181.0}=0x0 +phy_chain_tx_polarity_flip_physical{182.0}=0x0 +phy_chain_tx_polarity_flip_physical{183.0}=0x1 +phy_chain_tx_polarity_flip_physical{184.0}=0x0 +#Port19 +#FC47 +portmap_83=189:100 +phy_chain_rx_lane_map_physical{189.0}=0x0132 +phy_chain_tx_lane_map_physical{189.0}=0x3210 +phy_chain_rx_polarity_flip_physical{189.0}=0x0 +phy_chain_rx_polarity_flip_physical{190.0}=0x1 +phy_chain_rx_polarity_flip_physical{191.0}=0x1 +phy_chain_rx_polarity_flip_physical{192.0}=0x1 +phy_chain_tx_polarity_flip_physical{189.0}=0x1 +phy_chain_tx_polarity_flip_physical{190.0}=0x0 +phy_chain_tx_polarity_flip_physical{191.0}=0x0 +phy_chain_tx_polarity_flip_physical{192.0}=0x0 +#Port20 +#FC3 +portmap_4=13:100 +phy_chain_rx_lane_map_physical{13.0}=0x3120 +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +#Port21 +#FC1 +portmap_2=5:100 +phy_chain_rx_lane_map_physical{5.0}=0x0213 +phy_chain_tx_lane_map_physical{5.0}=0x0321 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +#Port22 +#FC7 +portmap_8=29:100 +phy_chain_rx_lane_map_physical{29.0}=0x3021 +phy_chain_tx_lane_map_physical{29.0}=0x2130 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +#Port23 +#FC5 +portmap_6=21:100 +phy_chain_rx_lane_map_physical{21.0}=0x0321 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x1 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 +#Port24 +#FC51 +portmap_105=205:100 +phy_chain_rx_lane_map_physical{205.0}=0x0132 +phy_chain_tx_lane_map_physical{205.0}=0x1230 +phy_chain_rx_polarity_flip_physical{205.0}=0x1 +phy_chain_rx_polarity_flip_physical{206.0}=0x1 +phy_chain_rx_polarity_flip_physical{207.0}=0x1 +phy_chain_rx_polarity_flip_physical{208.0}=0x0 +phy_chain_tx_polarity_flip_physical{205.0}=0x0 +phy_chain_tx_polarity_flip_physical{206.0}=0x1 +phy_chain_tx_polarity_flip_physical{207.0}=0x0 +phy_chain_tx_polarity_flip_physical{208.0}=0x1 +#Port25 +#FC49 +portmap_103=197:100 +phy_chain_rx_lane_map_physical{197.0}=0x1230 +phy_chain_tx_lane_map_physical{197.0}=0x3021 +phy_chain_rx_polarity_flip_physical{197.0}=0x0 +phy_chain_rx_polarity_flip_physical{198.0}=0x0 +phy_chain_rx_polarity_flip_physical{199.0}=0x0 +phy_chain_rx_polarity_flip_physical{200.0}=0x0 +phy_chain_tx_polarity_flip_physical{197.0}=0x1 +phy_chain_tx_polarity_flip_physical{198.0}=0x0 +phy_chain_tx_polarity_flip_physical{199.0}=0x1 +phy_chain_tx_polarity_flip_physical{200.0}=0x0 +#Port26 +#FC53 +portmap_107=213:100 +phy_chain_rx_lane_map_physical{213.0}=0x3210 +phy_chain_tx_lane_map_physical{213.0}=0x1230 +phy_chain_rx_polarity_flip_physical{213.0}=0x0 +phy_chain_rx_polarity_flip_physical{214.0}=0x1 +phy_chain_rx_polarity_flip_physical{215.0}=0x0 +phy_chain_rx_polarity_flip_physical{216.0}=0x1 +phy_chain_tx_polarity_flip_physical{213.0}=0x0 +phy_chain_tx_polarity_flip_physical{214.0}=0x0 +phy_chain_tx_polarity_flip_physical{215.0}=0x0 +phy_chain_tx_polarity_flip_physical{216.0}=0x1 +#Port27 +#FC55 +portmap_109=221:100 +phy_chain_rx_lane_map_physical{221.0}=0x3210 +phy_chain_tx_lane_map_physical{221.0}=0x3210 +phy_chain_rx_polarity_flip_physical{221.0}=0x1 +phy_chain_rx_polarity_flip_physical{222.0}=0x1 +phy_chain_rx_polarity_flip_physical{223.0}=0x0 +phy_chain_rx_polarity_flip_physical{224.0}=0x0 +phy_chain_tx_polarity_flip_physical{221.0}=0x0 +phy_chain_tx_polarity_flip_physical{222.0}=0x0 +phy_chain_tx_polarity_flip_physical{223.0}=0x0 +phy_chain_tx_polarity_flip_physical{224.0}=0x0 +#Port28 +#FC57 +portmap_111=229:100 +phy_chain_rx_lane_map_physical{229.0}=0x2301 +phy_chain_tx_lane_map_physical{229.0}=0x3210 +phy_chain_rx_polarity_flip_physical{229.0}=0x1 +phy_chain_rx_polarity_flip_physical{230.0}=0x1 +phy_chain_rx_polarity_flip_physical{231.0}=0x0 +phy_chain_rx_polarity_flip_physical{232.0}=0x1 +phy_chain_tx_polarity_flip_physical{229.0}=0x0 +phy_chain_tx_polarity_flip_physical{230.0}=0x1 +phy_chain_tx_polarity_flip_physical{231.0}=0x0 +phy_chain_tx_polarity_flip_physical{232.0}=0x0 +#Port29 +#FC59 +portmap_113=237:100 +phy_chain_rx_lane_map_physical{237.0}=0x0123 +phy_chain_tx_lane_map_physical{237.0}=0x3210 +phy_chain_rx_polarity_flip_physical{237.0}=0x1 +phy_chain_rx_polarity_flip_physical{238.0}=0x0 +phy_chain_rx_polarity_flip_physical{239.0}=0x1 +phy_chain_rx_polarity_flip_physical{240.0}=0x1 +phy_chain_tx_polarity_flip_physical{237.0}=0x1 +phy_chain_tx_polarity_flip_physical{238.0}=0x1 +phy_chain_tx_polarity_flip_physical{239.0}=0x0 +phy_chain_tx_polarity_flip_physical{240.0}=0x0 +#Port30 +#FC61 +portmap_115=245:100 +phy_chain_rx_lane_map_physical{245.0}=0x0213 +phy_chain_tx_lane_map_physical{245.0}=0x3210 +phy_chain_rx_polarity_flip_physical{245.0}=0x0 +phy_chain_rx_polarity_flip_physical{246.0}=0x0 +phy_chain_rx_polarity_flip_physical{247.0}=0x1 +phy_chain_rx_polarity_flip_physical{248.0}=0x1 +phy_chain_tx_polarity_flip_physical{245.0}=0x1 +phy_chain_tx_polarity_flip_physical{246.0}=0x0 +phy_chain_tx_polarity_flip_physical{247.0}=0x1 +phy_chain_tx_polarity_flip_physical{248.0}=0x0 +#Port31 +#FC63 +portmap_117=253:100 +phy_chain_rx_lane_map_physical{253.0}=0x0213 +phy_chain_tx_lane_map_physical{253.0}=0x0312 +phy_chain_rx_polarity_flip_physical{253.0}=0x0 +phy_chain_rx_polarity_flip_physical{254.0}=0x0 +phy_chain_rx_polarity_flip_physical{255.0}=0x0 +phy_chain_rx_polarity_flip_physical{256.0}=0x1 +phy_chain_tx_polarity_flip_physical{253.0}=0x0 +phy_chain_tx_polarity_flip_physical{254.0}=0x1 +phy_chain_tx_polarity_flip_physical{255.0}=0x0 +phy_chain_tx_polarity_flip_physical{256.0}=0x0 +#Port32 +#FC17 +portmap_35=69:100 +phy_chain_rx_lane_map_physical{69.0}=0x1032 +phy_chain_tx_lane_map_physical{69.0}=0x3102 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x1 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 +#Port33 +#FC19 +portmap_37=77:100 +phy_chain_rx_lane_map_physical{77.0}=0x1230 +phy_chain_tx_lane_map_physical{77.0}=0x3021 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +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}=0x0 +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}=0x0 +#Port34 +#FC23 +portmap_41=93:100 +phy_chain_rx_lane_map_physical{93.0}=0x1032 +phy_chain_tx_lane_map_physical{93.0}=0x0231 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 +phy_chain_tx_polarity_flip_physical{93.0}=0x0 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +phy_chain_tx_polarity_flip_physical{95.0}=0x1 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 +#Port35 +#FC21 +portmap_39=85:100 +phy_chain_rx_lane_map_physical{85.0}=0x0312 +phy_chain_tx_lane_map_physical{85.0}=0x1230 +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}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x1 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +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}=0x0 +#Port36 +#FC25 +portmap_43=101:100 +phy_chain_rx_lane_map_physical{101.0}=0x1302 +phy_chain_tx_lane_map_physical{101.0}=0x0213 +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}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{104.0}=0x1 +#Port37 +#FC27 +portmap_45=109:100 +phy_chain_rx_lane_map_physical{109.0}=0x0213 +phy_chain_tx_lane_map_physical{109.0}=0x1032 +phy_chain_rx_polarity_flip_physical{109.0}=0x1 +phy_chain_rx_polarity_flip_physical{110.0}=0x1 +phy_chain_rx_polarity_flip_physical{111.0}=0x0 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 +phy_chain_tx_polarity_flip_physical{109.0}=0x0 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 +#Port38 +#FC31 +portmap_49=125:100 +phy_chain_rx_lane_map_physical{125.0}=0x2130 +phy_chain_tx_lane_map_physical{125.0}=0x1203 +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_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x1 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +#Port39 +#FC29 +portmap_47=117:100 +phy_chain_rx_lane_map_physical{117.0}=0x3102 +phy_chain_tx_lane_map_physical{117.0}=0x2310 +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{117.0}=0x1 +phy_chain_tx_polarity_flip_physical{118.0}=0x0 +phy_chain_tx_polarity_flip_physical{119.0}=0x1 +phy_chain_tx_polarity_flip_physical{120.0}=0x0 +#Port40 +#FC9 +portmap_10=37:100 +phy_chain_rx_lane_map_physical{37.0}=0x3210 +phy_chain_tx_lane_map_physical{37.0}=0x1302 +phy_chain_rx_polarity_flip_physical{37.0}=0x1 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x0 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +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 +#Port41 +#FC11 +portmap_12=45:100 +phy_chain_rx_lane_map_physical{45.0}=0x3210 +phy_chain_tx_lane_map_physical{45.0}=0x0123 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x0 +phy_chain_rx_polarity_flip_physical{48.0}=0x0 +phy_chain_tx_polarity_flip_physical{45.0}=0x0 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_tx_polarity_flip_physical{47.0}=0x0 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 +#Port42 +#FC15 +portmap_16=61:100 +phy_chain_rx_lane_map_physical{61.0}=0x3210 +phy_chain_tx_lane_map_physical{61.0}=0x1230 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +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_tx_polarity_flip_physical{61.0}=0x0 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x0 +#Port43 +#FC13 +portmap_14=53:100 +phy_chain_rx_lane_map_physical{53.0}=0x3210 +phy_chain_tx_lane_map_physical{53.0}=0x3210 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x0 +phy_chain_tx_polarity_flip_physical{53.0}=0x1 +phy_chain_tx_polarity_flip_physical{54.0}=0x1 +phy_chain_tx_polarity_flip_physical{55.0}=0x1 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 +#Port44 +#FC33 +portmap_69=133:100 +phy_chain_rx_lane_map_physical{133.0}=0x0312 +phy_chain_tx_lane_map_physical{133.0}=0x2310 +phy_chain_rx_polarity_flip_physical{133.0}=0x0 +phy_chain_rx_polarity_flip_physical{134.0}=0x0 +phy_chain_rx_polarity_flip_physical{135.0}=0x1 +phy_chain_rx_polarity_flip_physical{136.0}=0x0 +phy_chain_tx_polarity_flip_physical{133.0}=0x0 +phy_chain_tx_polarity_flip_physical{134.0}=0x1 +phy_chain_tx_polarity_flip_physical{135.0}=0x0 +phy_chain_tx_polarity_flip_physical{136.0}=0x1 +#Port45 +#FC35 +portmap_71=141:100 +phy_chain_rx_lane_map_physical{141.0}=0x3012 +phy_chain_tx_lane_map_physical{141.0}=0x0123 +phy_chain_rx_polarity_flip_physical{141.0}=0x1 +phy_chain_rx_polarity_flip_physical{142.0}=0x0 +phy_chain_rx_polarity_flip_physical{143.0}=0x1 +phy_chain_rx_polarity_flip_physical{144.0}=0x0 +phy_chain_tx_polarity_flip_physical{141.0}=0x1 +phy_chain_tx_polarity_flip_physical{142.0}=0x1 +phy_chain_tx_polarity_flip_physical{143.0}=0x0 +phy_chain_tx_polarity_flip_physical{144.0}=0x0 +#Port46 +#FC39 +portmap_75=157:100 +phy_chain_rx_lane_map_physical{157.0}=0x2103 +phy_chain_tx_lane_map_physical{157.0}=0x0231 +phy_chain_rx_polarity_flip_physical{157.0}=0x0 +phy_chain_rx_polarity_flip_physical{158.0}=0x0 +phy_chain_rx_polarity_flip_physical{159.0}=0x1 +phy_chain_rx_polarity_flip_physical{160.0}=0x0 +phy_chain_tx_polarity_flip_physical{157.0}=0x0 +phy_chain_tx_polarity_flip_physical{158.0}=0x1 +phy_chain_tx_polarity_flip_physical{159.0}=0x0 +phy_chain_tx_polarity_flip_physical{160.0}=0x0 +#Port47 +#FC37 +portmap_73=149:100 +phy_chain_rx_lane_map_physical{149.0}=0x3120 +phy_chain_tx_lane_map_physical{149.0}=0x1023 +phy_chain_rx_polarity_flip_physical{149.0}=0x0 +phy_chain_rx_polarity_flip_physical{150.0}=0x1 +phy_chain_rx_polarity_flip_physical{151.0}=0x0 +phy_chain_rx_polarity_flip_physical{152.0}=0x0 +phy_chain_tx_polarity_flip_physical{149.0}=0x1 +phy_chain_tx_polarity_flip_physical{150.0}=0x0 +phy_chain_tx_polarity_flip_physical{151.0}=0x0 +phy_chain_tx_polarity_flip_physical{152.0}=0x1 +#Port48 +#FC40 +portmap_76=161:100 +phy_chain_rx_lane_map_physical{161.0}=0x3012 +phy_chain_tx_lane_map_physical{161.0}=0x1023 +phy_chain_rx_polarity_flip_physical{161.0}=0x1 +phy_chain_rx_polarity_flip_physical{162.0}=0x1 +phy_chain_rx_polarity_flip_physical{163.0}=0x0 +phy_chain_rx_polarity_flip_physical{164.0}=0x0 +phy_chain_tx_polarity_flip_physical{161.0}=0x0 +phy_chain_tx_polarity_flip_physical{162.0}=0x1 +phy_chain_tx_polarity_flip_physical{163.0}=0x0 +phy_chain_tx_polarity_flip_physical{164.0}=0x0 +#Port49 +#FC42 +portmap_78=169:100 +phy_chain_rx_lane_map_physical{169.0}=0x3210 +phy_chain_tx_lane_map_physical{169.0}=0x2031 +phy_chain_rx_polarity_flip_physical{169.0}=0x0 +phy_chain_rx_polarity_flip_physical{170.0}=0x1 +phy_chain_rx_polarity_flip_physical{171.0}=0x0 +phy_chain_rx_polarity_flip_physical{172.0}=0x0 +phy_chain_tx_polarity_flip_physical{169.0}=0x1 +phy_chain_tx_polarity_flip_physical{170.0}=0x0 +phy_chain_tx_polarity_flip_physical{171.0}=0x0 +phy_chain_tx_polarity_flip_physical{172.0}=0x0 +#Port50 +#FC46 +portmap_82=185:100 +phy_chain_rx_lane_map_physical{185.0}=0x2310 +phy_chain_tx_lane_map_physical{185.0}=0x3021 +phy_chain_rx_polarity_flip_physical{185.0}=0x1 +phy_chain_rx_polarity_flip_physical{186.0}=0x0 +phy_chain_rx_polarity_flip_physical{187.0}=0x1 +phy_chain_rx_polarity_flip_physical{188.0}=0x0 +phy_chain_tx_polarity_flip_physical{185.0}=0x0 +phy_chain_tx_polarity_flip_physical{186.0}=0x1 +phy_chain_tx_polarity_flip_physical{187.0}=0x0 +phy_chain_tx_polarity_flip_physical{188.0}=0x0 +#Port51 +#FC44 +portmap_80=177:100 +phy_chain_rx_lane_map_physical{177.0}=0x1032 +phy_chain_tx_lane_map_physical{177.0}=0x2301 +phy_chain_rx_polarity_flip_physical{177.0}=0x1 +phy_chain_rx_polarity_flip_physical{178.0}=0x1 +phy_chain_rx_polarity_flip_physical{179.0}=0x0 +phy_chain_rx_polarity_flip_physical{180.0}=0x1 +phy_chain_tx_polarity_flip_physical{177.0}=0x1 +phy_chain_tx_polarity_flip_physical{178.0}=0x1 +phy_chain_tx_polarity_flip_physical{179.0}=0x1 +phy_chain_tx_polarity_flip_physical{180.0}=0x0 +#Port52 +#FC6 +portmap_7=25:100 +phy_chain_rx_lane_map_physical{25.0}=0x3102 +phy_chain_tx_lane_map_physical{25.0}=0x0132 +phy_chain_rx_polarity_flip_physical{25.0}=0x0 +phy_chain_rx_polarity_flip_physical{26.0}=0x0 +phy_chain_rx_polarity_flip_physical{27.0}=0x1 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 +phy_chain_tx_polarity_flip_physical{25.0}=0x0 +phy_chain_tx_polarity_flip_physical{26.0}=0x1 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +#Port53 +#FC4 +portmap_5=17:100 +phy_chain_rx_lane_map_physical{17.0}=0x3120 +phy_chain_tx_lane_map_physical{17.0}=0x3021 +phy_chain_rx_polarity_flip_physical{17.0}=0x0 +phy_chain_rx_polarity_flip_physical{18.0}=0x1 +phy_chain_rx_polarity_flip_physical{19.0}=0x0 +phy_chain_rx_polarity_flip_physical{20.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x0 +#Port54 +#FC0 +portmap_1=1:100 +phy_chain_rx_lane_map_physical{1.0}=0x2130 +phy_chain_tx_lane_map_physical{1.0}=0x1203 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +#Port55 +#FC2 +portmap_3=9:100 +phy_chain_rx_lane_map_physical{9.0}=0x1203 +phy_chain_tx_lane_map_physical{9.0}=0x1230 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x0 +phy_chain_rx_polarity_flip_physical{12.0}=0x0 +phy_chain_tx_polarity_flip_physical{9.0}=0x1 +phy_chain_tx_polarity_flip_physical{10.0}=0x0 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +#Port56 +#FC48 +portmap_102=193:100 +phy_chain_rx_lane_map_physical{193.0}=0x2103 +phy_chain_tx_lane_map_physical{193.0}=0x1230 +phy_chain_rx_polarity_flip_physical{193.0}=0x0 +phy_chain_rx_polarity_flip_physical{194.0}=0x1 +phy_chain_rx_polarity_flip_physical{195.0}=0x0 +phy_chain_rx_polarity_flip_physical{196.0}=0x1 +phy_chain_tx_polarity_flip_physical{193.0}=0x0 +phy_chain_tx_polarity_flip_physical{194.0}=0x0 +phy_chain_tx_polarity_flip_physical{195.0}=0x1 +phy_chain_tx_polarity_flip_physical{196.0}=0x0 +#Port57 +#FC50 +portmap_104=201:100 +phy_chain_rx_lane_map_physical{201.0}=0x0321 +phy_chain_tx_lane_map_physical{201.0}=0x3021 +phy_chain_rx_polarity_flip_physical{201.0}=0x0 +phy_chain_rx_polarity_flip_physical{202.0}=0x0 +phy_chain_rx_polarity_flip_physical{203.0}=0x1 +phy_chain_rx_polarity_flip_physical{204.0}=0x0 +phy_chain_tx_polarity_flip_physical{201.0}=0x1 +phy_chain_tx_polarity_flip_physical{202.0}=0x1 +phy_chain_tx_polarity_flip_physical{203.0}=0x0 +phy_chain_tx_polarity_flip_physical{204.0}=0x1 +#Port58 +#FC54 +portmap_108=217:100 +phy_chain_rx_lane_map_physical{217.0}=0x1203 +phy_chain_tx_lane_map_physical{217.0}=0x2031 +phy_chain_rx_polarity_flip_physical{217.0}=0x1 +phy_chain_rx_polarity_flip_physical{218.0}=0x0 +phy_chain_rx_polarity_flip_physical{219.0}=0x1 +phy_chain_rx_polarity_flip_physical{220.0}=0x1 +phy_chain_tx_polarity_flip_physical{217.0}=0x1 +phy_chain_tx_polarity_flip_physical{218.0}=0x0 +phy_chain_tx_polarity_flip_physical{219.0}=0x1 +phy_chain_tx_polarity_flip_physical{220.0}=0x0 +#Port59 +#FC52 +portmap_106=209:100 +phy_chain_rx_lane_map_physical{209.0}=0x0321 +phy_chain_tx_lane_map_physical{209.0}=0x3102 +phy_chain_rx_polarity_flip_physical{209.0}=0x0 +phy_chain_rx_polarity_flip_physical{210.0}=0x0 +phy_chain_rx_polarity_flip_physical{211.0}=0x1 +phy_chain_rx_polarity_flip_physical{212.0}=0x0 +phy_chain_tx_polarity_flip_physical{209.0}=0x0 +phy_chain_tx_polarity_flip_physical{210.0}=0x0 +phy_chain_tx_polarity_flip_physical{211.0}=0x1 +phy_chain_tx_polarity_flip_physical{212.0}=0x0 +#Port60 +#FC56 +portmap_110=225:100 +phy_chain_rx_lane_map_physical{225.0}=0x2103 +phy_chain_tx_lane_map_physical{225.0}=0x2031 +phy_chain_rx_polarity_flip_physical{225.0}=0x0 +phy_chain_rx_polarity_flip_physical{226.0}=0x0 +phy_chain_rx_polarity_flip_physical{227.0}=0x1 +phy_chain_rx_polarity_flip_physical{228.0}=0x1 +phy_chain_tx_polarity_flip_physical{225.0}=0x1 +phy_chain_tx_polarity_flip_physical{226.0}=0x0 +phy_chain_tx_polarity_flip_physical{227.0}=0x1 +phy_chain_tx_polarity_flip_physical{228.0}=0x1 +#Port61 +#FC58 +portmap_112=233:100 +phy_chain_rx_lane_map_physical{233.0}=0x2130 +phy_chain_tx_lane_map_physical{233.0}=0x0312 +phy_chain_rx_polarity_flip_physical{233.0}=0x0 +phy_chain_rx_polarity_flip_physical{234.0}=0x1 +phy_chain_rx_polarity_flip_physical{235.0}=0x1 +phy_chain_rx_polarity_flip_physical{236.0}=0x0 +phy_chain_tx_polarity_flip_physical{233.0}=0x0 +phy_chain_tx_polarity_flip_physical{234.0}=0x0 +phy_chain_tx_polarity_flip_physical{235.0}=0x1 +phy_chain_tx_polarity_flip_physical{236.0}=0x0 +#Port62 +#FC62 +portmap_116=249:100 +phy_chain_rx_lane_map_physical{249.0}=0x1302 +phy_chain_tx_lane_map_physical{249.0}=0x1302 +phy_chain_rx_polarity_flip_physical{249.0}=0x0 +phy_chain_rx_polarity_flip_physical{250.0}=0x1 +phy_chain_rx_polarity_flip_physical{251.0}=0x0 +phy_chain_rx_polarity_flip_physical{252.0}=0x1 +phy_chain_tx_polarity_flip_physical{249.0}=0x1 +phy_chain_tx_polarity_flip_physical{250.0}=0x1 +phy_chain_tx_polarity_flip_physical{251.0}=0x1 +phy_chain_tx_polarity_flip_physical{252.0}=0x1 +#Port63 +#FC60 +portmap_114=241:100 +phy_chain_rx_lane_map_physical{241.0}=0x3012 +phy_chain_tx_lane_map_physical{241.0}=0x2301 +phy_chain_rx_polarity_flip_physical{241.0}=0x1 +phy_chain_rx_polarity_flip_physical{242.0}=0x1 +phy_chain_rx_polarity_flip_physical{243.0}=0x0 +phy_chain_rx_polarity_flip_physical{244.0}=0x1 +phy_chain_tx_polarity_flip_physical{241.0}=0x1 +phy_chain_tx_polarity_flip_physical{242.0}=0x0 +phy_chain_tx_polarity_flip_physical{243.0}=0x1 +phy_chain_tx_polarity_flip_physical{244.0}=0x0 diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/default_sku b/device/juniper/x86_64-juniper_qfx5210-r0/default_sku new file mode 100644 index 000000000000..869e1625da46 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/default_sku @@ -0,0 +1 @@ +Juniper-QFX5210-64C t1 diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/installer.conf b/device/juniper/x86_64-juniper_qfx5210-r0/installer.conf new file mode 100644 index 000000000000..5c03f5844baa --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/installer.conf @@ -0,0 +1,2 @@ +CONSOLE_SPEED=9600 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1" diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/led_proc_init.soc b/device/juniper/x86_64-juniper_qfx5210-r0/led_proc_init.soc new file mode 100644 index 000000000000..75a36c6f9c68 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/led_proc_init.soc @@ -0,0 +1,155 @@ +m CMIC_LEDUP0_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 +m CMIC_LEDUP1_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 +m CMIC_LEDUP2_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 +m CMIC_LEDUP3_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000 + +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=62 REMAP_PORT_2=61 REMAP_PORT_3=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=59 REMAP_PORT_5=58 REMAP_PORT_6=57 REMAP_PORT_7=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=55 REMAP_PORT_9=54 REMAP_PORT_10=53 REMAP_PORT_11=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=51 REMAP_PORT_13=50 REMAP_PORT_14=49 REMAP_PORT_15=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 REMAP_PORT_17=46 REMAP_PORT_18=45 REMAP_PORT_19=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 REMAP_PORT_21=42 REMAP_PORT_22=41 REMAP_PORT_23=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 REMAP_PORT_25=38 REMAP_PORT_26=37 REMAP_PORT_27=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 REMAP_PORT_29=34 REMAP_PORT_30=33 REMAP_PORT_31=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=31 REMAP_PORT_33=30 REMAP_PORT_34=29 REMAP_PORT_35=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=23 REMAP_PORT_41=22 REMAP_PORT_42=21 REMAP_PORT_43=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=19 REMAP_PORT_45=18 REMAP_PORT_46=17 REMAP_PORT_47=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=62 REMAP_PORT_2=61 REMAP_PORT_3=60 +m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=59 REMAP_PORT_5=58 REMAP_PORT_6=57 REMAP_PORT_7=56 +m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=55 REMAP_PORT_9=54 REMAP_PORT_10=53 REMAP_PORT_11=52 +m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=51 REMAP_PORT_13=50 REMAP_PORT_14=49 REMAP_PORT_15=48 +m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 REMAP_PORT_17=46 REMAP_PORT_18=45 REMAP_PORT_19=44 +m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 REMAP_PORT_21=42 REMAP_PORT_22=41 REMAP_PORT_23=40 +m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 REMAP_PORT_25=38 REMAP_PORT_26=37 REMAP_PORT_27=36 +m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 REMAP_PORT_29=34 REMAP_PORT_30=33 REMAP_PORT_31=32 +m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=31 REMAP_PORT_33=30 REMAP_PORT_34=29 REMAP_PORT_35=28 +m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24 +m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=23 REMAP_PORT_41=22 REMAP_PORT_42=21 REMAP_PORT_43=20 +m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=19 REMAP_PORT_45=18 REMAP_PORT_46=17 REMAP_PORT_47=16 +m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0 +m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4 +m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8 +m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12 +m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16 +m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20 +m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24 +m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28 +m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32 +m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36 +m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40 +m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44 +m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 stop +led 0 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +led 1 stop +led 1 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +led 2 stop +led 2 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +led 3 stop +led 3 prog \ + 02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \ + 02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \ + 67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \ + 86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \ + 3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \ + 98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \ + 4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \ + F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \ + 71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \ + 52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \ + 74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \ + 98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \ + 88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \ + 88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \ + 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +led auto on +led 0 start +led 1 start +led 2 start +led 3 start diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/media_settings.json b/device/juniper/x86_64-juniper_qfx5210-r0/media_settings.json new file mode 100644 index 000000000000..4a57e4b79e3a --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/media_settings.json @@ -0,0 +1,21640 @@ +{ + "GLOBAL_MEDIA_SETTINGS": { + }, + "PORT_MEDIA_SETTINGS": { + "0": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0x103f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0x103f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0x103f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0x103f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0x103f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "1": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0x113f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0x113f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0x113f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0x113f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0x113f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "2": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "3": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "4": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "5": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "6": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x174a03", + "lane1":"0x174a03", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "7": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x1b4603", + "lane2":"0x174a03", + "lane3":"0x174a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "8": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "9": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1d4403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xf3a04" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xf3a04" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xf3a04" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xf3a04" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xf3f02", + "lane2":"0xd3a02", + "lane3":"0xf3a04" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "10": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "11": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a02", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "12": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3402", + "lane1":"0xa3402", + "lane2":"0xa3402", + "lane3":"0xa3202" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3402", + "lane1":"0xa3402", + "lane2":"0xa3402", + "lane3":"0xa3202" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3402", + "lane1":"0xa3402", + "lane2":"0xa3402", + "lane3":"0xa3202" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3402", + "lane1":"0xa3402", + "lane2":"0xa3402", + "lane3":"0xa3202" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3402", + "lane1":"0xa3402", + "lane2":"0xa3402", + "lane3":"0xa3202" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "13": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3402", + "lane1":"0xb3402", + "lane2":"0xa3402", + "lane3":"0xa3202" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3402", + "lane1":"0xb3402", + "lane2":"0xa3402", + "lane3":"0xa3202" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3402", + "lane1":"0xb3402", + "lane2":"0xa3402", + "lane3":"0xa3202" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3402", + "lane1":"0xb3402", + "lane2":"0xa3402", + "lane3":"0xa3202" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3402", + "lane1":"0xb3402", + "lane2":"0xa3402", + "lane3":"0xa3202" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "14": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0x93002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0x93002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0x93002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0x93002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0x93002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "15": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154c03", + "lane1":"0x154c03", + "lane2":"0x154c03", + "lane3":"0x154c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "16": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154901", + "lane1":"0x124901", + "lane2":"0x124903", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0x82d02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0x82d02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0x82d02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0x82d02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0x82d02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "17": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124904", + "lane2":"0x124901", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "18": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x124900", + "lane2":"0x124903", + "lane3":"0x144902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "19": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x124904", + "lane2":"0x124904", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "20": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xc3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xc3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xc3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xc3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xc3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "21": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "22": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3402", + "lane1":"0xd3402", + "lane2":"0xd3403", + "lane3":"0xd3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3402", + "lane1":"0xd3402", + "lane2":"0xd3403", + "lane3":"0xd3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3402", + "lane1":"0xd3402", + "lane2":"0xd3403", + "lane3":"0xd3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3402", + "lane1":"0xd3402", + "lane2":"0xd3403", + "lane3":"0xd3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3402", + "lane1":"0xd3402", + "lane2":"0xd3403", + "lane3":"0xd3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "23": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1e4303", + "lane1":"0x1e4303", + "lane2":"0x1d4403", + "lane3":"0x1e4303" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xe3602", + "lane1":"0xf3a03", + "lane2":"0xf3d03", + "lane3":"0xf3d03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xe3602", + "lane1":"0xf3a03", + "lane2":"0xf3d03", + "lane3":"0xf3d03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xe3602", + "lane1":"0xf3a03", + "lane2":"0xf3d03", + "lane3":"0xf3d03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xe3602", + "lane1":"0xf3a03", + "lane2":"0xf3d03", + "lane3":"0xf3d03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xe3602", + "lane1":"0xf3a03", + "lane2":"0xf3d03", + "lane3":"0xf3d03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "24": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154906", + "lane1":"0x154904", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "25": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x174902", + "lane1":"0x174902", + "lane2":"0x174902", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "26": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3002", + "lane1":"0xa3002", + "lane2":"0xa3002", + "lane3":"0xa3002" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "27": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xb3203", + "lane1":"0xc3403", + "lane2":"0xc3403", + "lane3":"0xd3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3203", + "lane1":"0xc3403", + "lane2":"0xc3403", + "lane3":"0xd3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3203", + "lane1":"0xc3403", + "lane2":"0xc3403", + "lane3":"0xd3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xb3203", + "lane1":"0xc3403", + "lane2":"0xc3403", + "lane3":"0xd3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xb3203", + "lane1":"0xc3403", + "lane2":"0xc3403", + "lane3":"0xd3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "28": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4505", + "lane1":"0x1a4505", + "lane2":"0x1a4505", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xd3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xd3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xd3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xd3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xd3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "29": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xc3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xc3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xc3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xc3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xc3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "30": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4604", + "lane1":"0x1a4604", + "lane2":"0x1a4604", + "lane3":"0x1a4604" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xd3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xd3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xd3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xd3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xc3402", + "lane1":"0xd3402", + "lane2":"0xc3402", + "lane3":"0xc3402" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "31": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3602", + "lane1":"0xd3602", + "lane2":"0xd3602", + "lane3":"0xd3602" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3602", + "lane1":"0xd3602", + "lane2":"0xd3602", + "lane3":"0xd3602" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3602", + "lane1":"0xd3602", + "lane2":"0xd3602", + "lane3":"0xd3602" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3602", + "lane1":"0xd3602", + "lane2":"0xd3602", + "lane3":"0xd3602" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3602", + "lane1":"0xd3602", + "lane2":"0xd3602", + "lane3":"0xd3602" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "32": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4404", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xf3a02", + "lane1":"0x113c03", + "lane2":"0xf3a03", + "lane3":"0xf3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xf3a02", + "lane1":"0x113c03", + "lane2":"0xf3a03", + "lane3":"0xf3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xf3a02", + "lane1":"0x113c03", + "lane2":"0xf3a03", + "lane3":"0xf3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xf3a02", + "lane1":"0x113c03", + "lane2":"0xf3a03", + "lane3":"0xf3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xf3a02", + "lane1":"0x113c03", + "lane2":"0xf3a03", + "lane3":"0xf3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "33": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xf3a03", + "lane1":"0xf3a03", + "lane2":"0xf3a03", + "lane3":"0xf3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xf3a03", + "lane1":"0xf3a03", + "lane2":"0xf3a03", + "lane3":"0xf3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xf3a03", + "lane1":"0xf3a03", + "lane2":"0xf3a03", + "lane3":"0xf3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xf3a03", + "lane1":"0xf3a03", + "lane2":"0xf3a03", + "lane3":"0xf3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xf3a03", + "lane1":"0xf3a03", + "lane2":"0xf3a03", + "lane3":"0xf3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "34": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4604", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3803", + "lane1":"0xe3803", + "lane2":"0xd3803", + "lane3":"0xc3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3803", + "lane1":"0xe3803", + "lane2":"0xd3803", + "lane3":"0xc3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3803", + "lane1":"0xe3803", + "lane2":"0xd3803", + "lane3":"0xc3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3803", + "lane1":"0xe3803", + "lane2":"0xd3803", + "lane3":"0xc3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3803", + "lane1":"0xe3803", + "lane2":"0xd3803", + "lane3":"0xc3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "35": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xe3804", + "lane1":"0xe3803", + "lane2":"0xe3804", + "lane3":"0xe3804" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xe3804", + "lane1":"0xe3803", + "lane2":"0xe3804", + "lane3":"0xe3804" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xe3804", + "lane1":"0xe3803", + "lane2":"0xe3804", + "lane3":"0xe3804" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xe3804", + "lane1":"0xe3803", + "lane2":"0xe3804", + "lane3":"0xe3804" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xe3804", + "lane1":"0xe3803", + "lane2":"0xe3804", + "lane3":"0xe3804" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "36": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3803", + "lane1":"0xd3803", + "lane2":"0xb3203", + "lane3":"0xc3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3803", + "lane1":"0xd3803", + "lane2":"0xb3203", + "lane3":"0xc3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3803", + "lane1":"0xd3803", + "lane2":"0xb3203", + "lane3":"0xc3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3803", + "lane1":"0xd3803", + "lane2":"0xb3203", + "lane3":"0xc3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3803", + "lane1":"0xd3803", + "lane2":"0xb3203", + "lane3":"0xc3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "37": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xb3202", + "lane1":"0xb3202", + "lane2":"0xa3003", + "lane3":"0xb3003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3202", + "lane1":"0xb3202", + "lane2":"0xa3003", + "lane3":"0xb3003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3202", + "lane1":"0xb3202", + "lane2":"0xa3003", + "lane3":"0xb3003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xb3202", + "lane1":"0xb3202", + "lane2":"0xa3003", + "lane3":"0xb3003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xb3202", + "lane1":"0xb3202", + "lane2":"0xa3003", + "lane3":"0xb3003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "38": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x164903", + "lane1":"0x164903", + "lane2":"0x164903", + "lane3":"0x164903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3203", + "lane1":"0xa3203", + "lane2":"0xa3203", + "lane3":"0xa3203" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3203", + "lane1":"0xa3203", + "lane2":"0xa3203", + "lane3":"0xa3203" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3203", + "lane1":"0xa3203", + "lane2":"0xa3203", + "lane3":"0xa3203" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3203", + "lane1":"0xa3203", + "lane2":"0xa3203", + "lane3":"0xa3203" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3203", + "lane1":"0xa3203", + "lane2":"0xa3203", + "lane3":"0xa3203" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "39": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x164901", + "lane1":"0x184901", + "lane2":"0x184901", + "lane3":"0x184901" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3202", + "lane1":"0xa3202", + "lane2":"0xa3003", + "lane3":"0xa3003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3202", + "lane1":"0xa3202", + "lane2":"0xa3003", + "lane3":"0xa3003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3202", + "lane1":"0xa3202", + "lane2":"0xa3003", + "lane3":"0xa3003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3202", + "lane1":"0xa3202", + "lane2":"0xa3003", + "lane3":"0xa3003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3202", + "lane1":"0xa3202", + "lane2":"0xa3003", + "lane3":"0xa3003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "40": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1c4503", + "lane2":"0x1c4503", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "41": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1a4703", + "lane2":"0x1b4603", + "lane3":"0x1c4503" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "42": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xb3a03", + "lane3":"0xa3803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xb3a03", + "lane3":"0xa3803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xb3a03", + "lane3":"0xa3803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xb3a03", + "lane3":"0xa3803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xb3a03", + "lane3":"0xa3803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "43": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1a4703", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "44": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x184902", + "lane2":"0x154902", + "lane3":"0x184902" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x82f03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x82f03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x82f03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x82f03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x82f03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "45": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154900", + "lane1":"0x154900", + "lane2":"0x154900", + "lane3":"0x154900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0x72d03", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x83003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x72d03", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x83003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x72d03", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x83003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0x72d03", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x83003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0x72d03", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x83003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "46": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x174900", + "lane1":"0x174900", + "lane2":"0x154900", + "lane3":"0x174904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "47": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x154903", + "lane3":"0x154903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x82e03", + "lane3":"0x83003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x82e03", + "lane3":"0x83003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x82e03", + "lane3":"0x83003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x82e03", + "lane3":"0x83003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x82e03", + "lane3":"0x83003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "48": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x184902", + "lane1":"0x164902", + "lane2":"0x164902", + "lane3":"0x144900" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "49": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x174901", + "lane1":"0x144902", + "lane2":"0x144902", + "lane3":"0x144903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x93003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "50": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x184901", + "lane1":"0x174901", + "lane2":"0x164903", + "lane3":"0x154904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x83003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x83003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x83003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x83003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93003", + "lane2":"0x83003", + "lane3":"0x93003" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "51": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x154903", + "lane1":"0x154903", + "lane2":"0x134903", + "lane3":"0x144904" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93002", + "lane2":"0x82f03", + "lane3":"0x82f03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93002", + "lane2":"0x82f03", + "lane3":"0x82f03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93002", + "lane2":"0x82f03", + "lane3":"0x82f03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93002", + "lane2":"0x82f03", + "lane3":"0x82f03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0x93003", + "lane1":"0x93002", + "lane2":"0x82f03", + "lane3":"0x82f03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "52": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x194803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "53": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184803", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "54": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4503", + "lane1":"0x1e4204", + "lane2":"0x1c4503", + "lane3":"0x1d4304" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xf3d02", + "lane2":"0xd3a03", + "lane3":"0xf3c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xf3d02", + "lane2":"0xd3a03", + "lane3":"0xf3c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xf3d02", + "lane2":"0xd3a03", + "lane3":"0xf3c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xf3d02", + "lane2":"0xd3a03", + "lane3":"0xf3c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xf3d02", + "lane2":"0xd3a03", + "lane3":"0xf3c03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "55": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xb3a03", + "lane1":"0xc3a03", + "lane2":"0xa3403", + "lane3":"0xb3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3a03", + "lane1":"0xc3a03", + "lane2":"0xa3403", + "lane3":"0xb3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3a03", + "lane1":"0xc3a03", + "lane2":"0xa3403", + "lane3":"0xb3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xb3a03", + "lane1":"0xc3a03", + "lane2":"0xa3403", + "lane3":"0xb3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xb3a03", + "lane1":"0xc3a03", + "lane2":"0xa3403", + "lane3":"0xb3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "56": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x184903", + "lane1":"0x184903", + "lane2":"0x184903", + "lane3":"0x184903" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xa3403", + "lane1":"0xa3403", + "lane2":"0xa3403", + "lane3":"0xa3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "57": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x194803", + "lane1":"0x194803", + "lane2":"0x184903", + "lane3":"0x194803" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0x93203", + "lane1":"0xa3603", + "lane2":"0x93203", + "lane3":"0x93203" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93203", + "lane1":"0xa3603", + "lane2":"0x93203", + "lane3":"0x93203" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0x93203", + "lane1":"0xa3603", + "lane2":"0x93203", + "lane3":"0x93203" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0x93203", + "lane1":"0xa3603", + "lane2":"0x93203", + "lane3":"0x93203" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0x93203", + "lane1":"0xa3603", + "lane2":"0x93203", + "lane3":"0x93203" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "58": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604C0": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xb3403", + "lane3":"0xb3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xb3403", + "lane3":"0xb3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xb3403", + "lane3":"0xb3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xb3403", + "lane3":"0xb3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xb3403", + "lane3":"0xb3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "59": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4703" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xb3403", + "lane3":"0xb3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xb3403", + "lane3":"0xb3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xb3403", + "lane3":"0xb3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xb3403", + "lane3":"0xb3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xb3403", + "lane3":"0xb3403" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "60": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1a4703", + "lane1":"0x1a4703", + "lane2":"0x1a4703", + "lane3":"0x1a4505" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xc3603", + "lane3":"0xc3603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xc3603", + "lane3":"0xc3603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xc3603", + "lane3":"0xc3603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xc3603", + "lane3":"0xc3603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xb3403", + "lane1":"0xc3603", + "lane2":"0xc3603", + "lane3":"0xc3603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "61": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1b4603", + "lane1":"0x1b4603", + "lane2":"0x1b4603", + "lane3":"0x1b4603" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xc3603", + "lane1":"0xd3a03", + "lane2":"0xc3603", + "lane3":"0xc3602" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xc3603", + "lane1":"0xd3a03", + "lane2":"0xc3603", + "lane3":"0xc3602" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xc3603", + "lane1":"0xd3a03", + "lane2":"0xc3603", + "lane3":"0xc3602" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xc3603", + "lane1":"0xd3a03", + "lane2":"0xc3603", + "lane3":"0xc3602" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xc3603", + "lane1":"0xd3a03", + "lane2":"0xc3603", + "lane3":"0xc3602" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "62": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1c4404", + "lane1":"0x1c4404", + "lane2":"0x1b4504", + "lane3":"0x1c4404" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a03", + "lane1":"0xd3a03", + "lane2":"0xd3a03", + "lane3":"0xd3a03" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + }, + "63": { + "Default": { + "preemphasis": { + "lane0":"0x14410a", + "lane1":"0x14410a", + "lane2":"0x14410a", + "lane3":"0x14410a" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-AVAGO-AFBR-89CDDZ-JU1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604BO": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-LUXTERA-LUX42604CO": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-1F3-1F3QAA": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC030-NJC": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC020-NJC": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC010-NJC": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC001-NJC": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TF-FC003-NJC": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13R-NJ3": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-FC13T-NJ3": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC9551REPM-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTLC1151RDPL-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C01-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C03-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C10-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C20-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FCBN425QE1C30-J1": { + "preemphasis": { + "lane0":"0x1b4504", + "lane1":"0x1b4504", + "lane2":"0x1a4703", + "lane3":"0x1b4504" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "AVAGO-AFBR-79EQDZ-JU1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a03", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "FINISAR CORP-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a03", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-FINISAR-FTL410QE3C-J1": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a03", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ3": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a03", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + }, + "JUNIPER-INNO-TR-IQ13L-NJ5": { + "preemphasis": { + "lane0":"0xd3a02", + "lane1":"0xd3a02", + "lane2":"0xd3a03", + "lane3":"0xd3a02" + }, + "idriver": { + "lane0":"0x8", + "lane1":"0x8", + "lane2":"0x8", + "lane3":"0x8" + } + } + } + } +} + diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/plugins/eeprom.py b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/eeprom.py new file mode 100644 index 000000000000..4f087afc6eb0 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/eeprom.py @@ -0,0 +1,37 @@ +try: + 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 + import syslog + from struct import * + from array import * +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = "eeprom.py" +EEPROM_PATH = "/sys/bus/i2c/devices/0-0056/eeprom" + + +def log_error(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + + def __init__(self, name, path, cpld_root, ro): + + if not os.path.exists(EEPROM_PATH): + log_error("Cannot find system eeprom") + raise RuntimeError("No syseeprom found") + + self.eeprom_path = EEPROM_PATH + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/plugins/psuutil.py b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/psuutil.py new file mode 100644 index 000000000000..b05cf3e477ac --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/psuutil.py @@ -0,0 +1,60 @@ +############################################################################# +# Accton +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/sys/bus/i2c/devices/" + self.psu_presence = "/psu_present" + self.psu_oper_status = "/psu_power_good" + self.psu_mapping = { + 1: "10-0053", + 2: "9-0050", + } + + def get_num_psus(self): + return len(self.psu_mapping) + + def get_psu_status(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + if index is None: + return False + + status = 0 + node = self.psu_path + self.psu_mapping[index] + self.psu_presence + try: + with open(node, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/plugins/qfx5210_eeprom_data.py b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/qfx5210_eeprom_data.py new file mode 100644 index 000000000000..b0aef43ba273 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/qfx5210_eeprom_data.py @@ -0,0 +1,333 @@ +#!/usr/bin/env python3 +# +# Name: juniper_qfx5210_eepromconv.py version: 1.0 +# +# Description: This file contains the code to store the contents of Board EEPROM in file +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. + +import os +import binascii +from sonic_eeprom import eeprom_tlvinfo + + +def main(): + eeprom_qfx5210 = Eeprom() + + FANTYPE_PATH = '/sys/bus/i2c/devices/17-0068/fan1_direction' + isPlatformAFO = False + try: + fan_type_file = open(FANTYPE_PATH) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + fan_type = -1 + else: + fan_type = fan_type_file.read() + fan_type_file.close() + + if (int(fan_type) == -1 or int(fan_type) == 0): + if (int(fan_type) == -1): + print("unable to open sys file for fan handling, defaulting it to AFO") + + isPlatformAFO = True + else: + isPlatformAFO = False + + # creating the "/var/run/eeprom" file and storing values of CPU board EEPROM in this file. + eeprom_file = open("/var/run/eeprom", "a+") + eeprom_file.write("\n") + if isPlatformAFO == True: + eeprom_file.write("Fan Type=AFO\r\n") + else: + eeprom_file.write("Fan Type=AFI\r\n") + eeprom_file.write("\n") + + # Write the contents of CPU Board EEPROM to file + eeprom_file.write("CPU Board EEPROM (0x56)\r\n") + eeprom_file.write("===============================\r\n") + eeprom_file.write("Product Name=%s\r\n" % eeprom_qfx5210.modelstr()) + eeprom_file.write("Part Number=%s\r\n" % eeprom_qfx5210.part_number_str()) + eeprom_file.write("Serial Number=%s\r\n" % eeprom_qfx5210.serial_number_str()) + eeprom_file.write("MAC Address=%s\r\n" % eeprom_qfx5210.base_mac_address()) + eeprom_file.write("Manufacture Date=%s\r\n" % eeprom_qfx5210.manuDate_str()) + eeprom_file.write("Platform Name=%s\r\n" % eeprom_qfx5210.platform_str()) + eeprom_file.write("Number of MAC Addresses=%s\r\n" % eeprom_qfx5210.MACsize_str()) + eeprom_file.write("Vendor Name=%s\r\n" % eeprom_qfx5210.vendor_name_str()) + eeprom_file.write("Manufacture Name=%s\r\n" % eeprom_qfx5210.manufacture_name_str()) + + CPUeepromFileCmd = 'cat /sys/devices/pci0000:00/0000:00:1f.3/i2c-0/0-0056/eeprom > /etc/init.d/eeprom_qfx5210_ascii' + # Write the contents of CPU EEPROM to file + try: + os.system(CPUeepromFileCmd) + except OSError: + print('Error: Execution of "%s" failed', CPUeepromFileCmd) + return False + + eeprom_ascii = '/etc/init.d/eeprom_qfx5210_ascii' + # Read file contents in Hex format + with open(eeprom_ascii, 'rb') as Hexformat: + content = Hexformat.read() + Hexformatoutput = binascii.hexlify(content) + + eeprom_hex = '/etc/init.d/eeprom_qfx5210_hex' + with open(eeprom_hex, 'wb+') as Hexfile: + Hexfile.write(Hexformatoutput) + + # Write contents of CPU EEPROM to new file in hexa format + with open(eeprom_hex, 'rb') as eeprom_hexfile: + eeprom_hexfile.seek(350, 0) + vendorext_read = eeprom_hexfile.read(124) + vendorext = "" + vendorext += "0x" + vendorext_read[0:2] + for i in range(2, 124, 2): + vendorext += " 0x" + vendorext_read[i:i+2] + eeprom_file.write("Vendor Extension=%s\r\n" % str(vendorext)) + + eeprom_hexfile.seek(350, 0) + IANA_read = eeprom_hexfile.read(8) + IANAName = binascii.unhexlify(IANA_read) + eeprom_file.write("IANA=%s\r\n" % str(IANAName)) + + eeprom_hexfile.seek(358, 0) + ASMpartrev_read = eeprom_hexfile.read(4) + ASMpartrev = binascii.unhexlify(ASMpartrev_read) + eeprom_file.write("Assembly Part Number Rev=%s\r\n" % str(ASMpartrev)) + + eeprom_hexfile.seek(374, 0) + ASMpartnum_read = eeprom_hexfile.read(20) + ASMpartnum_read = binascii.unhexlify(ASMpartnum_read) + eeprom_file.write("Assembly Part Number=%s\r\n" % str(ASMpartnum_read)) + + eeprom_hexfile.seek(402, 0) + ASMID_read = eeprom_hexfile.read(4) + ASMID_read_upper = ASMID_read.upper() + eeprom_file.write("Assembly ID=0x%s\r\n" % str(ASMID_read_upper)) + + ASMHWMajRev_position = eeprom_hexfile.seek(410, 0) + ASMHWMajRev_read = eeprom_hexfile.read(2) + eeprom_file.write("Assembly Major Revision=0x%s\r\n" % str(ASMHWMajRev_read)) + + eeprom_hexfile.seek(416, 0) + ASMHWMinRev_read = eeprom_hexfile.read(2) + eeprom_file.write("Assembly Minor Revision=0x%s\r\n" % str(ASMHWMinRev_read)) + + eeprom_hexfile.seek(422, 0) + Deviation_read = eeprom_hexfile.read(28) + Deviation_read_upper = Deviation_read.upper() + eeprom_file.write("Deviation=0x%s\r\n" % str(Deviation_read_upper)) + + eeprom_hexfile.seek(450, 0) + CLEI_read = eeprom_hexfile.read(20) + CLEI_name = binascii.unhexlify(CLEI_read) + eeprom_file.write("CLEI code=%s\r\n" % str(CLEI_name)) + + eeprom_dict = eeprom_qfx5210.system_eeprom_info() + key = '0x29' + if key in list(eeprom_dict.keys()): + onie_version_str = eeprom_dict.get('0x29', None) + else: + onie_version_str = "N/A" + eeprom_file.write("ONIE Version=%s\r\n" % onie_version_str) + + crc_str = eeprom_dict.get('0xFE', None) + eeprom_file.write("CRC=%s\r\n" % crc_str) + eeprom_file.close() + return True + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + def __init__(self): + self.__eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/eeprom" + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + self.__eeprom_tlv_dict = dict() + try: + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + ord(eeprom[tlv_index + 1])] + code = "0x%02X" % (ord(tlv[0])) + + if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT: + value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) | + (ord(tlv[4]) << 8) | ord(tlv[5])) + value += str(tlv[6:6 + ord(tlv[1])]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32: + break + + tlv_index += ord(eeprom[tlv_index+1]) + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2] + + def base_mac_address(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(eeprom_tlvinfo.TlvInfoDecoder, self).switchaddrstr(self.__eeprom_data) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2] + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2] + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2] + + def manuDate_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MANUF_DATE) + if not is_valid: + return "N/A" + + return results[2] + + def platform_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PLATFORM_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def MACsize_str(self): + (is_valid, t) = self.get_tlv_field(self.__eeprom_data, self._TLV_CODE_MAC_SIZE) + + if not is_valid: + return "N/A" + + return str((ord(t[2][0]) << 8) | ord(t[2][1])) + + def vendor_name_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_VENDOR_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def manufacture_name_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MANUF_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def onie_version_str(self): + value = "" + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_ONIE_VERSION) + if not is_valid: + return "N/A" + + for c in results[2:2 + ord(results[1])]: + value += "0x%02X " % (ord(c),) + + return value + + def vendor_ext_str(self): + + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_VENDOR_EXT) + + if not is_valid: + return "N/A" + + vendor_value_formatted = ''.join([" 0x" + "%02X " % ord(x) for x in results[2]]).strip() + vendor_value_hexvalue = ''.join(["%02X" % ord(x) for x in results[2]]).strip() + + return vendor_value_formatted, vendor_value_hexvalue + + def crc_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_CRC_32) + if not is_valid: + return "N/A" + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.__eeprom_tlv_dict + + +if __name__ == "__main__": + main() diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py new file mode 100644 index 000000000000..673bb05ed107 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py @@ -0,0 +1,851 @@ +try: + import time + from sonic_sfp.sfputilbase import * + import sys + import os + import io + import string + from ctypes import create_string_buffer + from sonic_py_common.logger import Logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = "sfputil" +logger = Logger(SYSLOG_IDENTIFIER) + +qfx5210_qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +qfx5210_sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +qfx5210_sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +qfx5210_qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 0 + _port_end = 63 + ports_in_block = 64 + cmd = '/var/run/sfppresence' + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 60: 25, + 61: 26, + 62: 27, + 63: 28, + 54: 29, + 55: 30, + 52: 31, + 53: 32, + 8: 33, + 9: 34, + 10: 35, + 11: 36, + 0: 37, + 1: 38, + 2: 39, + 3: 40, + 5: 41, + 4: 42, + 7: 43, + 6: 44, + 12: 45, + 13: 46, + 14: 47, + 15: 48, + 16: 49, + 17: 50, + 18: 51, + 19: 52, + 24: 53, + 25: 54, + 26: 55, + 27: 56, + 28: 57, + 29: 58, + 30: 59, + 31: 60, + 20: 61, + 21: 62, + 22: 63, + 23: 64, + 40: 65, + 41: 66, + 42: 67, + 43: 68, + 32: 69, + 33: 70, + 34: 71, + 35: 72, + 44: 73, + 45: 74, + 46: 75, + 47: 76, + 36: 77, + 37: 78, + 38: 79, + 39: 80, + 56: 81, + 57: 82, + 58: 83, + 59: 84, + 48: 85, + 49: 86, + 50: 87, + 51: 88, } + + # sys.path.append('/usr/local/bin') + _qsfp_ports = list(range(0, ports_in_block + 1)) + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/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) + + 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/19-0060/module_reset_{0}" + port_ps = path.format(port_num+1) + + try: + reg_file = open(port_ps, 'w') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # HW will clear reset after set. + reg_file.seek(0) + reg_file.write('1') + reg_file.close() + return True + + 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/19-0060/module_present_{0}" + port_ps = path.format(port_num + 1) + + try: + reg_file = open(port_ps) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return list(range(0, self.ports_in_block + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + # Writing to a file from a list + def write_to_file(self, file_name, from_list): + try: + fp1 = open(file_name, 'w') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + for i in from_list: + fp1.write(i) + fp1.write('\n') + + fp1.close() + return True + + # Reading from a file to a list + + def read_from_file(self, file_name): + try: + fp = open(file_name, 'r') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + to_list = fp.readlines() + to_list = [x.rstrip() for x in to_list] + fp.close() + return to_list + + def sfp_detect(self): + x = 0 + ret_dict = {} + defl_dict = {} + current_sfp_values = [0] * 64 + previous_sfp_values = [0] * 64 + + path = "/sys/bus/i2c/devices/19-0060/module_present_{0}" + + if not os.path.isfile(self.cmd): + pass + else: + if (self.read_from_file(self.cmd) == False): + return False, defl_dict + else: + previous_sfp_values = self.read_from_file(self.cmd) + + # Read the current values from sysfs + for x in range(self._port_start, self._port_end + 1): + try: + new_path = path.format(x + 1) + reg_file = open(new_path, 'r') + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False, defl_dict + + sfp_present = reg_file.readline().rstrip() + reg_file.close() + current_sfp_values[x] = sfp_present + if (current_sfp_values[x] != previous_sfp_values[x]): + ret_dict.update({x: current_sfp_values[x]}) + + if(self.write_to_file(self.cmd, current_sfp_values) == True): + return True, ret_dict + else: + return False, defl_dict + + def get_transceiver_change_event(self, timeout=2000): + time.sleep(3) + return self.sfp_detect() + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False + + eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") + eeprom.seek(93) + lpmode = ord(eeprom.read(1)) + + if ((lpmode & 0x3) == 0x3): + return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + return False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self._port_start or port_num > self._port_end: + return False + + try: + eeprom = None + + if not self.get_presence(port_num): + return False # Port is not present, unable to set the eeprom + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") + eeprom.seek(93) + eeprom.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + # Read out SFP type, vendor name, PN, REV, SN from eeprom. + def get_transceiver_info_dict(self, port_num): + transceiver_info_dict = {} + compliance_code_dict = {} + + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + if port_num in self.osfp_ports: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP + + sfpi_obj = inf8628InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + print("Error, file not exist %s" % file_path) + return None + + try: + sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfp_type_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + OSFP_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_type_data['data']['type_abbrv_name']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + # Below part is added to avoid fail the xcvrd, shall be implemented later + transceiver_info_dict['vendor_oui'] = 'N/A' + transceiver_info_dict['vendor_date'] = 'N/A' + transceiver_info_dict['connector'] = 'N/A' + transceiver_info_dict['encoding'] = 'N/A' + transceiver_info_dict['ext_identifier'] = 'N/A' + transceiver_info_dict['ext_rateselect_compliance'] = 'N/A' + transceiver_info_dict['cable_type'] = 'N/A' + transceiver_info_dict['cable_length'] = 'N/A' + transceiver_info_dict['specification_compliance'] = 'N/A' + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + + else: + if port_num in self.qsfp_ports: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + cable_length_width = XCVR_CABLE_LENGTH_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + sfp_type = 'QSFP' + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + cable_length_width = XCVR_CABLE_LENGTH_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + sfp_type = 'SFP' + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + print("Error, file not exist %s" % file_path) + return None + + try: + sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfp_interface_bulk_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_INTFACE_BULK_OFFSET), interface_info_bulk_width) + if sfp_interface_bulk_raw is not None: + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + sfp_vendor_oui_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + else: + return None + + sfp_vendor_date_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + if sfp_vendor_date_raw is not None: + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + else: + return None + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + if sfp_type == 'QSFP': + for key in qfx5210_qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + break + else: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = 'N/A' + + for key in qfx5210_qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + if 'Nominal Bit Rate(100Mbs)' in sfp_interface_bulk_data['data']: + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + else: + for key in qfx5210_sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + else: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = 'N/A' + + for key in qfx5210_sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + if 'NominalSignallingRate(UnitsOf100Mbd)' in sfp_interface_bulk_data['data']: + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + else: + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + #transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_transceiver_dom_info_dict(self, port_num): + transceiver_dom_info_dict = {} + + if port_num in self.osfp_ports: + # Below part is added to avoid fail xcvrd, shall be implemented later + transceiver_dom_info_dict['temperature'] = 'N/A' + transceiver_dom_info_dict['voltage'] = 'N/A' + transceiver_dom_info_dict['rx1power'] = 'N/A' + 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'] = 'N/A' + 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'] = 'N/A' + transceiver_dom_info_dict['tx2power'] = 'N/A' + transceiver_dom_info_dict['tx3power'] = 'N/A' + transceiver_dom_info_dict['tx4power'] = 'N/A' + + elif 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 = 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 None + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + return None + + # 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_dom_capability(qsfp_dom_capability_raw, 0) + else: + return None + + 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 None + + 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 None + + 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 None + + 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 None + + 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 = open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + dom_temperature_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + else: + return None + + 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 None + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, (offset + SFP_CHANNL_MON_OFFSET), SFP_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 None + + 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') + + logger.log_debug("QFX5210: get_transceiver_dom_threshold_info_dict Start") + if port_num in self.qsfp_ports: + file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = io.open(file_path, mode="rb", buffering=0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + # Dom Threshold data starts from offset 384 + # Revert offset back to 0 once data is retrieved + offset = 384 + dom_module_threshold_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, + (offset + QSFP_MODULE_THRESHOLD_OFFSET), + QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + dom_channel_threshold_raw = self._read_eeprom_specific_bytes( + sysfsfile_eeprom, + (offset + QSFP_CHANNL_THRESHOLD_OFFSET), + QSFP_CHANNL_THRESHOLD_WIDTH) + if dom_channel_threshold_raw is not None: + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + # Threshold Data + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] + + else: + offset = 256 + file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = io.open(file_path, "rb", 0) + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8472Dom(None, 1) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, + (offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH) + + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + else: + return transceiver_dom_threshold_info_dict + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + # Threshold Data + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + + logger.log_debug("QFX5210: get_transceiver_dom_threshold_info_dict End") + return transceiver_dom_threshold_info_dict diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/pmon_daemon_control.json b/device/juniper/x86_64-juniper_qfx5210-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..a3ecea34bcc9 --- /dev/null +++ b/device/juniper/x86_64-juniper_qfx5210-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_thermalctld": true, + "skip_ledd": true +} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t0.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t1.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/port_config.ini b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/port_config.ini new file mode 100644 index 000000000000..074c0344c896 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/port_config.ini @@ -0,0 +1,19 @@ +# name lanes speed alias +Ethernet0 0 25000 twenty5GigE0 +Ethernet1 1 25000 twenty5GigE1 +Ethernet2 2 25000 twenty5GigE2 +Ethernet3 3 25000 twenty5GigE3 +Ethernet4 4 25000 twenty5GigE4 +Ethernet5 5 25000 twenty5GigE5 +Ethernet6 6 25000 twenty5GigE6 +Ethernet7 7 25000 twenty5GigE7 +Ethernet8 8 25000 twenty5GigE8 +Ethernet9 9 25000 twenty5GigE9 +Ethernet10 10 25000 twenty5GigE10 +Ethernet11 11 25000 twenty5GigE11 +Ethernet12 12 25000 twenty5GigE12 +Ethernet13 13 25000 twenty5GigE13 +Ethernet14 14 25000 twenty5GigE14 +Ethernet15 15 25000 twenty5GigE15 +Ethernet16 16 10000 tenGigE16 +Ethernet17 17 10000 tenGigE17 diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/profile.ini b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/profile.ini new file mode 100644 index 000000000000..aeaafc4e6e4d --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 001:1 002:1 003:1 004:1 005:1 006:1 007:1 008:1 009:1 010:1 011:1 012:1 013:1 014:1 015:1 diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/sai.profile b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/sai.profile new file mode 100644 index 000000000000..2c9623c91105 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16X25G/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON16X25G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t0.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t1.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/port_config.ini b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/port_config.ini new file mode 100644 index 000000000000..6a9bfda3fb8b --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/port_config.ini @@ -0,0 +1,19 @@ +# name lanes speed alias +Ethernet0 0,1,2,3,4,5,6,7 400000 four00GigE0 +Ethernet8 8,9,10,11,12,13,14,15 400000 four00GigE1 +Ethernet16 16,17,18,19,20,21,22,23 400000 four00GigE2 +Ethernet24 24,25,26,27,28,29,30,31 400000 four00GigE2 +Ethernet32 32,33,34,35,36,37,38,39 400000 four00GigE3 +Ethernet40 40,41,42,43,44,45,46,47 400000 four00GigE4 +Ethernet48 48,49,50,51,52,53,54,55 400000 four00GigE5 +Ethernet56 56,57,58,59,60,61,62,63 400000 four00GigE6 +Ethernet64 64,65,66,67,68,69,70,71 400000 four00GigE7 +Ethernet72 72,73,74,75,76,77,78,79 400000 four00GigE8 +Ethernet80 80,81,82,83,84,85,86,87 400000 four00GigE9 +Ethernet88 88,89,90,91,92,93,94,95 400000 four00GigE10 +Ethernet96 96,97,98,99,100,101,102,103 400000 four00GigE11 +Ethernet104 104,105,106,107,108,109,110,111 400000 four00GigE12 +Ethernet112 112,113,114,115,116,117,118,119 400000 four00GigE13 +Ethernet120 120,121,122,123,124,125,126,127 400000 four00GigE14 +Ethernet128 128 10000 tenGigE128 +Ethernet129 129 10000 tenGigE129 diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/profile.ini b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/profile.ini new file mode 100644 index 000000000000..16847ec03ae2 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 008:1 016:1 024:1 032:1 040:1 048:1 056:1 064:1 072:1 080:1 088:1 096:1 104:1 112:1 120:1 diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/sai.profile b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/sai.profile new file mode 100644 index 000000000000..6a2438f50180 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON16x400G/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON16x400G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t0.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..f9fb5482560d --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"170000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t1.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..f9fb5482560d --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"170000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/port_config.ini b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/port_config.ini new file mode 100644 index 000000000000..d0402fd44317 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/port_config.ini @@ -0,0 +1,35 @@ +# name lanes speed alias +Ethernet0 0 25000 twenty5GigE0 +Ethernet1 1 25000 twenty5GigE1 +Ethernet2 2 25000 twenty5GigE2 +Ethernet3 3 25000 twenty5GigE3 +Ethernet4 4 25000 twenty5GigE4 +Ethernet5 5 25000 twenty5GigE5 +Ethernet6 6 25000 twenty5GigE6 +Ethernet7 7 25000 twenty5GigE7 +Ethernet8 8 25000 twenty5GigE8 +Ethernet9 9 25000 twenty5GigE9 +Ethernet10 10 25000 twenty5GigE10 +Ethernet11 11 25000 twenty5GigE11 +Ethernet12 12 25000 twenty5GigE12 +Ethernet13 13 25000 twenty5GigE13 +Ethernet14 14 25000 twenty5GigE14 +Ethernet15 15 25000 twenty5GigE15 +Ethernet16 16 25000 twenty5GigE16 +Ethernet17 17 25000 twenty5GigE17 +Ethernet18 18 25000 twenty5GigE18 +Ethernet19 19 25000 twenty5GigE19 +Ethernet20 20 25000 twenty5GigE20 +Ethernet21 21 25000 twenty5GigE21 +Ethernet22 22 25000 twenty5GigE22 +Ethernet23 23 25000 twenty5GigE23 +Ethernet24 24 25000 twenty5GigE24 +Ethernet25 25 25000 twenty5GigE25 +Ethernet26 26 25000 twenty5GigE26 +Ethernet27 27 25000 twenty5GigE27 +Ethernet28 28 25000 twenty5GigE28 +Ethernet29 29 25000 twenty5GigE29 +Ethernet30 30 25000 twenty5GigE30 +Ethernet31 31 25000 twenty5GigE31 +Ethernet32 32 10000 tenGigE32 +Ethernet33 33 10000 tenGigE33 diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/profile.ini b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/profile.ini new file mode 100644 index 000000000000..0ffbefa05805 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 001:1 002:1 003:1 004:1 005:1 006:1 007:1 008:1 009:1 010:1 011:1 012:1 013:1 014:1 015:1 016:1 017:1 018:1 019:1 020:1 021:1 022:1 023:1 024:1 025:1 026:1 027:1 028:1 029:1 030:1 031:1 diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/sai.profile b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/sai.profile new file mode 100644 index 000000000000..fa9983612117 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/FALCON32X25G/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON32x25G64 +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers.json.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers.json.j2 new file mode 100644 index 000000000000..a9a01d707ebf --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers.json.j2 @@ -0,0 +1 @@ +{%- include 'buffers_config.j2' %} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_config.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_config.j2 new file mode 100644 index 000000000000..5431fbe72c1f --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_config.j2 @@ -0,0 +1,165 @@ +{%- macro set_default_topology() %} +{%- if default_topo is defined %} +{{ default_topo }} +{%- else %} +def +{%- endif %} +{%- endmacro -%} + +{# Determine device topology and filename postfix #} +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- if 'torrouter' in switch_role.lower() %} +{%- set filename_postfix = 't0' %} +{%- elif 'leafrouter' in switch_role.lower() %} +{%- set filename_postfix = 't1' %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- endif %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- set switch_role = '' %} +{%- endif -%} + +{# Import default values from device HWSKU folder #} +{%- import 'buffers_defaults_%s.j2' % filename_postfix as defs %} + +{%- set default_cable = defs.default_cable -%} + +{# 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 #} +{%- if defs.ports2cable is defined %} + {%- set ports2cable = defs.ports2cable %} +{%- else %} + {%- set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } + -%} +{%- endif %} + +{%- macro cable_length(port_name) %} + {%- set cable_len = [] %} + {%- for local_port in DEVICE_NEIGHBOR %} + {%- if local_port == port_name %} + {%- if DEVICE_NEIGHBOR_METADATA is defined and 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 %} + {%- if 'torrouter' in switch_role.lower() %} + {%- for local_port in VLAN_MEMBER %} + {%- if local_port[1] == port_name %} + {%- set roles3 = switch_role + '_' + 'server' %} + {%- set roles3 = roles3 | lower %} + {%- if roles3 in ports2cable %} + {%- if cable_len.append(ports2cable[roles3]) %}{% endif %} + {%- endif %} + {%- endif %} + {%- endfor %} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- endif %} +{%- endmacro %} + +{%- set PORT_ALL = [] %} + +{%- if PORT is not defined %} + {%- if defs.generate_port_lists(PORT_ALL) %} {% endif %} +{%- else %} + {%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') %} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT_ALL %} + {%- set cable = cable_length(port) %} + "{{ port }}": "{{ cable }}"{%- if not loop.last %},{% endif %} + + {% endfor %} + } + }, + +{% if defs.generate_buffer_pool_and_profiles is defined %} +{{ defs.generate_buffer_pool_and_profiles() }} +{% endif %} + +{%- if defs.generate_profile_lists is defined %} +{{ defs.generate_profile_lists(port_names_active) }}, +{% endif %} + +{%- if defs.generate_pg_profils is defined %} +{{ defs.generate_pg_profils(port_names_active) }} +{% else %} + "BUFFER_PG": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + }, +{% endif %} + +{% if defs.generate_queue_buffers is defined %} +{{ defs.generate_queue_buffers(port_names_active) }} +{% else %} + "BUFFER_QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + } +{% endif %} +} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t0.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t1.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/port_config.ini b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/port_config.ini new file mode 100644 index 000000000000..6a9bfda3fb8b --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/port_config.ini @@ -0,0 +1,19 @@ +# name lanes speed alias +Ethernet0 0,1,2,3,4,5,6,7 400000 four00GigE0 +Ethernet8 8,9,10,11,12,13,14,15 400000 four00GigE1 +Ethernet16 16,17,18,19,20,21,22,23 400000 four00GigE2 +Ethernet24 24,25,26,27,28,29,30,31 400000 four00GigE2 +Ethernet32 32,33,34,35,36,37,38,39 400000 four00GigE3 +Ethernet40 40,41,42,43,44,45,46,47 400000 four00GigE4 +Ethernet48 48,49,50,51,52,53,54,55 400000 four00GigE5 +Ethernet56 56,57,58,59,60,61,62,63 400000 four00GigE6 +Ethernet64 64,65,66,67,68,69,70,71 400000 four00GigE7 +Ethernet72 72,73,74,75,76,77,78,79 400000 four00GigE8 +Ethernet80 80,81,82,83,84,85,86,87 400000 four00GigE9 +Ethernet88 88,89,90,91,92,93,94,95 400000 four00GigE10 +Ethernet96 96,97,98,99,100,101,102,103 400000 four00GigE11 +Ethernet104 104,105,106,107,108,109,110,111 400000 four00GigE12 +Ethernet112 112,113,114,115,116,117,118,119 400000 four00GigE13 +Ethernet120 120,121,122,123,124,125,126,127 400000 four00GigE14 +Ethernet128 128 10000 tenGigE128 +Ethernet129 129 10000 tenGigE129 diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/profile.ini b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/profile.ini new file mode 100644 index 000000000000..16847ec03ae2 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 008:1 016:1 024:1 032:1 040:1 048:1 056:1 064:1 072:1 080:1 088:1 096:1 104:1 112:1 120:1 diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/qos.json.j2 b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/sai.profile b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/sai.profile new file mode 100644 index 000000000000..6a2438f50180 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON16x400G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/default_sku b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/default_sku new file mode 100644 index 000000000000..7908e555c02c --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/default_sku @@ -0,0 +1 @@ +db98cx8580_16cd t1 diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/plugins/eeprom.py b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/plugins/eeprom.py new file mode 100644 index 000000000000..71f05c5b70f5 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/plugins/eeprom.py @@ -0,0 +1,11 @@ +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/etc/sonic/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/plugins/sfputil.py b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/plugins/sfputil.py new file mode 100644 index 000000000000..4463e687e695 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/plugins/sfputil.py @@ -0,0 +1,251 @@ +try: + import os + import time + import sys + import re + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + +smbus_present = 1 + +try: + import smbus +except ImportError as e: + smbus_present = 0 + + +class SfpUtil(SfpUtilBase): + """Platform specific sfputil class""" + _port_start = 1 + _port_end = 132 + ports_in_block = 132 + + _port_to_eeprom_mapping = {} + + _qsfp_ports = list(range(_port_start, ports_in_block + 1)) + + def __init__(self): + os.system("modprobe i2c-dev") + if not os.path.exists("/sys/bus/i2c/devices/0-0050"): + os.system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-0/new_device") + + eeprom_path = '/sys/bus/i2c/devices/0-0050/eeprom' + # for x in range(self.port _start, self.port_end +1): + x = self.port_start + while(x < self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path + x = x + 1 + 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 + + port_ps = "/sys/bus/i2c/devices/0-0050/sfp_port_reset" + + 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): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def i2c_get(self, device_addr, offset): + status = 0 + if smbus_present == 0: + x = "i2cget -y 0 " + hex(device_addr) + " " + hex(offset) + cmdstatus, status = commands.getstatusoutput(x) + if cmdstatus != 0: + return cmdstatus + status = int(status, 16) + else: + bus = smbus.SMBus(0) + status = bus.read_byte_data(device_addr, offset) + return status + + def i2c_set(self, device_addr, offset, value): + if smbus_present == 0: + cmd = "i2cset -y 0 " + hex(device_addr) + " " + hex(offset) + " " + hex(value) + os.system(cmd) + else: + bus = smbus.SMBus(0) + bus.write_byte_data(device_addr, offset, value) + + 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 + else: + self.i2c_set(0x70, 0, 0) + self.i2c_set(0x71, 0, 0) + self.i2c_set(0x74, 0, 0) + reg = (port_num)/8 + offset = reg % 8 + if offset >= 4: + offset = offset-4 + elif offset < 4: + offset = offset+4 + bin_offset = 1 << offset + + if port_num >= 0 and port_num <= 63: + device_reg = 0x70 + elif port_num >= 64 and port_num <= 127: + device_reg = 0x71 + elif port_num >= 128 and port_num <= 131: + device_reg = 0x74 + + #print "i2c %d %x %x" % (port_num, device_reg, bin_offset) + self.i2c_set(device_reg, 0, bin_offset) + path = "/sys/bus/i2c/devices/0-0050/eeprom" + try: + reg_file = open(path) + reg_file.seek(0o1) + reg_file.read(0o2) + except IOError as e: + return False + + return True + + def read_porttab_mappings(self, porttabfile): + #print("I am in porttab_mappings") + logical = [] + logical_to_bcm = {} + logical_to_physical = {} + physical_to_logical = {} + last_fp_port_index = 0 + last_portname = "" + first = 1 + port_pos_in_file = 0 + parse_fmt_port_config_ini = False + + try: + f = open(porttabfile) + except: + raise + + parse_fmt_port_config_ini = (os.path.basename(porttabfile) == "port_config.ini") + # Read the porttab file and generate dicts + # with mapping for future reference. + # + # TODO: Refactor this to use the portconfig.py module that now + # exists as part of the sonic-config-engine package. + title = [] + for line in f: + line.strip() + if re.search("^#", line) is not None: + # The current format is: # name lanes alias index speed + # Where the ordering of the columns can vary + title = line.split()[1:] + continue + #print title + + # Parsing logic for 'port_config.ini' file + if (parse_fmt_port_config_ini): + # bcm_port is not explicitly listed in port_config.ini format + # Currently we assume ports are listed in numerical order according to bcm_port + # so we use the port's position in the file (zero-based) as bcm_port + portname = line.split()[0] + + bcm_port = str(port_pos_in_file) + + if "index" in title: + fp_port_index = int(line.split()[title.index("index")]) + # Leave the old code for backward compatibility + # if len(line.split()) >= 4: + # fp_port_index = (line.split()[3]) + # print(fp_port_index) + else: + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))+1 + else: # Parsing logic for older 'portmap.ini' file + (portname, bcm_port) = line.split("=")[1].split(",")[:2] + + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))+1 + + if ((len(self.sfp_ports) > 0) and (fp_port_index not in self.sfp_ports)): + continue + + if first == 1: + # Initialize last_[physical|logical]_port + # to the first valid port + last_fp_port_index = fp_port_index + last_portname = portname + first = 0 + + logical.append(portname) + + logical_to_bcm[portname] = "xe" + bcm_port + logical_to_physical[portname] = [fp_port_index] + if physical_to_logical.get(fp_port_index) is None: + physical_to_logical[fp_port_index] = [portname] + else: + physical_to_logical[fp_port_index].append( + portname) + + if (fp_port_index - last_fp_port_index) > 1: + # last port was a gang port + for p in range(last_fp_port_index+1, fp_port_index): + logical_to_physical[last_portname].append(p) + if physical_to_logical.get(p) is None: + physical_to_logical[p] = [last_portname] + else: + physical_to_logical[p].append(last_portname) + + last_fp_port_index = fp_port_index + last_portname = portname + + port_pos_in_file += 1 + + self.logical = logical + self.logical_to_bcm = logical_to_bcm + self.logical_to_physical = logical_to_physical + self.physical_to_logical = physical_to_logical + + # print(self.logical_to_physical) + '''print("logical: " + self.logical) + print("logical to bcm: " + self.logical_to_bcm) + print("logical to physical: " + self.logical_to_physical) + print("physical to logical: " + self.physical_to_logical)''' + #print("exiting port_tab_mappings") + + @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 + + @property + def get_transceiver_change_event(self): + raise NotImplementedError diff --git a/device/marvell/arm64-marvell_db98cx8580_16cd-r0/pmon_daemon_control.json b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..94592fa8cebc --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_16cd-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t0.j2 b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t1.j2 b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/port_config.ini b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/port_config.ini new file mode 100644 index 000000000000..6d8b5d0a13df --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/port_config.ini @@ -0,0 +1,34 @@ +# name lanes speed alias +Ethernet0 0 25000 twenty5GigE0 +Ethernet1 1 25000 twenty5GigE1 +Ethernet2 2 25000 twenty5GigE2 +Ethernet3 3 25000 twenty5GigE3 +Ethernet4 4 25000 twenty5GigE4 +Ethernet5 5 25000 twenty5GigE5 +Ethernet6 6 25000 twenty5GigE6 +Ethernet7 7 25000 twenty5GigE7 +Ethernet8 8 25000 twenty5GigE8 +Ethernet9 9 25000 twenty5GigE9 +Ethernet10 10 25000 twenty5GigE10 +Ethernet11 11 25000 twenty5GigE11 +Ethernet12 12 25000 twenty5GigE12 +Ethernet13 13 25000 twenty5GigE13 +Ethernet14 14 25000 twenty5GigE14 +Ethernet15 15 25000 twenty5GigE15 +Ethernet16 16 25000 twenty5GigE16 +Ethernet17 17 25000 twenty5GigE17 +Ethernet18 18 25000 twenty5GigE18 +Ethernet19 19 25000 twenty5GigE19 +Ethernet20 20 25000 twenty5GigE20 +Ethernet21 21 25000 twenty5GigE21 +Ethernet22 22 25000 twenty5GigE22 +Ethernet23 23 25000 twenty5GigE23 +Ethernet24 24 25000 twenty5GigE24 +Ethernet25 25 25000 twenty5GigE25 +Ethernet26 26 25000 twenty5GigE26 +Ethernet27 27 25000 twenty5GigE27 +Ethernet28 28 25000 twenty5GigE28 +Ethernet29 29 25000 twenty5GigE29 +Ethernet30 30 25000 twenty5GigE30 +Ethernet31 31 25000 twenty5GigE31 +Ethernet32 32 10000 tenGigE32 diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/profile.ini b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/profile.ini new file mode 100644 index 000000000000..487e80dcbd70 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 001:1 002:1 003:1 004:1 005:1 006:1 007:1 008:1 009:1 010:1 011:1 012:1 013:1 014:1 015:1 016:1 017:1 018:1 019:1 020:1 021:1 022:1 023:1 024:1 025:1 026:1 027:1 028:1 029:1 030:1 031:1 032:1 diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/sai.profile b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/sai.profile new file mode 100644 index 000000000000..dd6f707a81ab --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32X25G/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON32X25G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t0.j2 b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t1.j2 b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/port_config.ini b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/port_config.ini new file mode 100644 index 000000000000..62dd91ba8869 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/port_config.ini @@ -0,0 +1,34 @@ +# name lanes speed alias +Ethernet0 0,1,2,3,4,5,6,7 400000 four00GigE0 +Ethernet8 8,9,10,11,12,13,14,15 400000 four00GigE8 +Ethernet16 16,17,18,19,20,21,22,23 400000 four00GigE16 +Ethernet24 24,25,26,27,28,29,30,31 400000 four00GigE24 +Ethernet32 32,33,34,35,36,37,38,39 400000 four00GigE32 +Ethernet40 40,41,42,43,44,45,46,47 400000 four00GigE40 +Ethernet48 48,49,50,51,52,53,54,55 400000 four00GigE48 +Ethernet56 56,57,58,59,60,61,62,63 400000 four00GigE56 +Ethernet64 64,65,66,67,68,69,70,71 400000 four00GigE64 +Ethernet72 72,73,74,75,76,77,78,79 400000 four00GigE72 +Ethernet80 80,81,82,83,84,85,86,87 400000 four00GigE80 +Ethernet88 88,89,90,91,92,93,94,95 400000 four00GigE88 +Ethernet96 96,97,98,99,100,101,102,103 400000 four00GigE96 +Ethernet104 104,105,106,107,108,109,110,111 400000 four00GigE104 +Ethernet112 112,113,114,115,116,117,118,119 400000 four00GigE112 +Ethernet120 120,121,122,123,124,125,126,127 400000 four00GigE120 +Ethernet128 128,129,130,131,132,133,134,135 400000 four00GigE128 +Ethernet136 136,137,138,139,140,141,142,143 400000 four00GigE136 +Ethernet144 144,145,146,147,148,149,150,151 400000 four00GigE144 +Ethernet152 152,153,154,155,156,157,158,159 400000 four00GigE152 +Ethernet160 160,161,162,163,164,165,166,167 400000 four00GigE160 +Ethernet168 168,169,170,171,172,173,174,175 400000 four00GigE168 +Ethernet176 176,177,178,179,180,181,182,183 400000 four00GigE176 +Ethernet184 184,185,186,187,188,189,190,191 400000 four00GigE184 +Ethernet192 192,193,194,195,196,197,198,199 400000 four00GigE192 +Ethernet200 200,201,202,203,204,205,206,207 400000 four00GigE200 +Ethernet208 208,209,210,211,212,213,214,215 400000 four00GigE208 +Ethernet216 216,217,218,219,220,221,222,223 400000 four00GigE216 +Ethernet224 224,225,226,227,228,229,230,231 400000 four00GigE224 +Ethernet232 232,233,234,235,236,237,238,239 400000 four00GigE232 +Ethernet240 240,241,242,243,244,245,246,247 400000 four00GigE240 +Ethernet248 248,249,250,251,252,253,254,255 400000 four00GigE248 +Ethernet256 256 10000 tenGigE256 diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/profile.ini b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/profile.ini new file mode 100644 index 000000000000..2813bbd363f8 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 008:1 016:1 024:1 032:1 040:1 048:1 056:1 064:1 072:1 080:1 088:1 096:1 104:1 112:1 120:1 128:1 136:1 144:1 152:1 160:1 168:1 176:1 184:1 192:1 200:1 208:1 216:1 224:1 232:1 240:1 248:1 256:1 diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/sai.profile b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/sai.profile new file mode 100644 index 000000000000..6dc6f35fed4e --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/FALCON32x400G/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON32x400G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers.json.j2 b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers.json.j2 new file mode 100644 index 000000000000..a9a01d707ebf --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers.json.j2 @@ -0,0 +1 @@ +{%- include 'buffers_config.j2' %} diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_config.j2 b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_config.j2 new file mode 100644 index 000000000000..5431fbe72c1f --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_config.j2 @@ -0,0 +1,165 @@ +{%- macro set_default_topology() %} +{%- if default_topo is defined %} +{{ default_topo }} +{%- else %} +def +{%- endif %} +{%- endmacro -%} + +{# Determine device topology and filename postfix #} +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- if 'torrouter' in switch_role.lower() %} +{%- set filename_postfix = 't0' %} +{%- elif 'leafrouter' in switch_role.lower() %} +{%- set filename_postfix = 't1' %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- endif %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- set switch_role = '' %} +{%- endif -%} + +{# Import default values from device HWSKU folder #} +{%- import 'buffers_defaults_%s.j2' % filename_postfix as defs %} + +{%- set default_cable = defs.default_cable -%} + +{# 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 #} +{%- if defs.ports2cable is defined %} + {%- set ports2cable = defs.ports2cable %} +{%- else %} + {%- set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } + -%} +{%- endif %} + +{%- macro cable_length(port_name) %} + {%- set cable_len = [] %} + {%- for local_port in DEVICE_NEIGHBOR %} + {%- if local_port == port_name %} + {%- if DEVICE_NEIGHBOR_METADATA is defined and 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 %} + {%- if 'torrouter' in switch_role.lower() %} + {%- for local_port in VLAN_MEMBER %} + {%- if local_port[1] == port_name %} + {%- set roles3 = switch_role + '_' + 'server' %} + {%- set roles3 = roles3 | lower %} + {%- if roles3 in ports2cable %} + {%- if cable_len.append(ports2cable[roles3]) %}{% endif %} + {%- endif %} + {%- endif %} + {%- endfor %} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- endif %} +{%- endmacro %} + +{%- set PORT_ALL = [] %} + +{%- if PORT is not defined %} + {%- if defs.generate_port_lists(PORT_ALL) %} {% endif %} +{%- else %} + {%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') %} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT_ALL %} + {%- set cable = cable_length(port) %} + "{{ port }}": "{{ cable }}"{%- if not loop.last %},{% endif %} + + {% endfor %} + } + }, + +{% if defs.generate_buffer_pool_and_profiles is defined %} +{{ defs.generate_buffer_pool_and_profiles() }} +{% endif %} + +{%- if defs.generate_profile_lists is defined %} +{{ defs.generate_profile_lists(port_names_active) }}, +{% endif %} + +{%- if defs.generate_pg_profils is defined %} +{{ defs.generate_pg_profils(port_names_active) }} +{% else %} + "BUFFER_PG": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + }, +{% endif %} + +{% if defs.generate_queue_buffers is defined %} +{{ defs.generate_queue_buffers(port_names_active) }} +{% else %} + "BUFFER_QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + } +{% endif %} +} diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t0.j2 b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t1.j2 b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/port_config.ini b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/port_config.ini new file mode 100644 index 000000000000..62dd91ba8869 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/port_config.ini @@ -0,0 +1,34 @@ +# name lanes speed alias +Ethernet0 0,1,2,3,4,5,6,7 400000 four00GigE0 +Ethernet8 8,9,10,11,12,13,14,15 400000 four00GigE8 +Ethernet16 16,17,18,19,20,21,22,23 400000 four00GigE16 +Ethernet24 24,25,26,27,28,29,30,31 400000 four00GigE24 +Ethernet32 32,33,34,35,36,37,38,39 400000 four00GigE32 +Ethernet40 40,41,42,43,44,45,46,47 400000 four00GigE40 +Ethernet48 48,49,50,51,52,53,54,55 400000 four00GigE48 +Ethernet56 56,57,58,59,60,61,62,63 400000 four00GigE56 +Ethernet64 64,65,66,67,68,69,70,71 400000 four00GigE64 +Ethernet72 72,73,74,75,76,77,78,79 400000 four00GigE72 +Ethernet80 80,81,82,83,84,85,86,87 400000 four00GigE80 +Ethernet88 88,89,90,91,92,93,94,95 400000 four00GigE88 +Ethernet96 96,97,98,99,100,101,102,103 400000 four00GigE96 +Ethernet104 104,105,106,107,108,109,110,111 400000 four00GigE104 +Ethernet112 112,113,114,115,116,117,118,119 400000 four00GigE112 +Ethernet120 120,121,122,123,124,125,126,127 400000 four00GigE120 +Ethernet128 128,129,130,131,132,133,134,135 400000 four00GigE128 +Ethernet136 136,137,138,139,140,141,142,143 400000 four00GigE136 +Ethernet144 144,145,146,147,148,149,150,151 400000 four00GigE144 +Ethernet152 152,153,154,155,156,157,158,159 400000 four00GigE152 +Ethernet160 160,161,162,163,164,165,166,167 400000 four00GigE160 +Ethernet168 168,169,170,171,172,173,174,175 400000 four00GigE168 +Ethernet176 176,177,178,179,180,181,182,183 400000 four00GigE176 +Ethernet184 184,185,186,187,188,189,190,191 400000 four00GigE184 +Ethernet192 192,193,194,195,196,197,198,199 400000 four00GigE192 +Ethernet200 200,201,202,203,204,205,206,207 400000 four00GigE200 +Ethernet208 208,209,210,211,212,213,214,215 400000 four00GigE208 +Ethernet216 216,217,218,219,220,221,222,223 400000 four00GigE216 +Ethernet224 224,225,226,227,228,229,230,231 400000 four00GigE224 +Ethernet232 232,233,234,235,236,237,238,239 400000 four00GigE232 +Ethernet240 240,241,242,243,244,245,246,247 400000 four00GigE240 +Ethernet248 248,249,250,251,252,253,254,255 400000 four00GigE248 +Ethernet256 256 10000 tenGigE256 diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/profile.ini b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/profile.ini new file mode 100644 index 000000000000..2813bbd363f8 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 008:1 016:1 024:1 032:1 040:1 048:1 056:1 064:1 072:1 080:1 088:1 096:1 104:1 112:1 120:1 128:1 136:1 144:1 152:1 160:1 168:1 176:1 184:1 192:1 200:1 208:1 216:1 224:1 232:1 240:1 248:1 256:1 diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/qos.json.j2 b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/sai.profile b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/sai.profile new file mode 100644 index 000000000000..6dc6f35fed4e --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON32x400G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/default_sku b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/default_sku new file mode 100644 index 000000000000..563676854022 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/default_sku @@ -0,0 +1 @@ +db98cx8580_32cd t1 diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/plugins/eeprom.py b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/plugins/eeprom.py new file mode 100644 index 000000000000..71f05c5b70f5 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/plugins/eeprom.py @@ -0,0 +1,11 @@ +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/etc/sonic/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/plugins/sfputil.py b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/plugins/sfputil.py new file mode 100644 index 000000000000..b3d1ea371454 --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/plugins/sfputil.py @@ -0,0 +1,257 @@ +try: + import os + import time + import sys + import re + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + +smbus_present = 1 + +try: + import smbus +except ImportError as e: + smbus_present = 0 + + +class SfpUtil(SfpUtilBase): + """Platform specific sfputil class""" + _port_start = 1 + _port_end = 257 + ports_in_block = 257 + + _port_to_eeprom_mapping = {} + + _qsfp_ports = list(range(_port_start, ports_in_block + 1)) + + def __init__(self): + os.system("modprobe i2c-dev") + if not os.path.exists("/sys/bus/i2c/devices/0-0050"): + os.system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-0/new_device") + + eeprom_path = '/sys/bus/i2c/devices/0-0050/eeprom' + # for x in range(self.port _start, self.port_end +1): + x = self.port_start + while(x < self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path + x = x + 1 + 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 + + port_ps = "/sys/bus/i2c/devices/0-0050/sfp_port_reset" + + 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): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def i2c_get(self, device_addr, offset): + status = 0 + if smbus_present == 0: + x = "i2cget -y 0 " + hex(device_addr) + " " + hex(offset) + cmdstatus, status = commands.getstatusoutput(x) + if cmdstatus != 0: + return cmdstatus + status = int(status, 16) + else: + bus = smbus.SMBus(0) + status = bus.read_byte_data(device_addr, offset) + return status + + def i2c_set(self, device_addr, offset, value): + if smbus_present == 0: + cmd = "i2cset -y 0 " + hex(device_addr) + " " + hex(offset) + " " + hex(value) + os.system(cmd) + else: + bus = smbus.SMBus(0) + bus.write_byte_data(device_addr, offset, value) + + 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 + else: + self.i2c_set(0x70, 0, 0) + self.i2c_set(0x71, 0, 0) + self.i2c_set(0x72, 0, 0) + self.i2c_set(0x73, 0, 0) + self.i2c_set(0x74, 0, 0) + reg = (port_num)/8 + offset = reg % 8 + if offset >= 4: + offset = offset-4 + elif offset < 4: + offset = offset+4 + bin_offset = 1 << offset + + if port_num >= 0 and port_num <= 63: + device_reg = 0x70 + elif port_num >= 64 and port_num <= 127: + device_reg = 0x71 + elif port_num >= 128 and port_num <= 191: + device_reg = 0x72 + elif port_num >= 192 and port_num <= 255: + device_reg = 0x73 + elif port_num >= 256 and port_num <= 257: + device_reg = 0x74 + + #print "i2c %d %x %x" % (port_num, device_reg, bin_offset) + self.i2c_set(device_reg, 0, bin_offset) + path = "/sys/bus/i2c/devices/0-0050/eeprom" + try: + reg_file = open(path) + reg_file.seek(0o1) + reg_file.read(0o2) + except IOError as e: + return False + + return True + + def read_porttab_mappings(self, porttabfile): + #print("I am in porttab_mappings") + logical = [] + logical_to_bcm = {} + logical_to_physical = {} + physical_to_logical = {} + last_fp_port_index = 0 + last_portname = "" + first = 1 + port_pos_in_file = 0 + parse_fmt_port_config_ini = False + + try: + f = open(porttabfile) + except: + raise + + parse_fmt_port_config_ini = (os.path.basename(porttabfile) == "port_config.ini") + # Read the porttab file and generate dicts + # with mapping for future reference. + # + # TODO: Refactor this to use the portconfig.py module that now + # exists as part of the sonic-config-engine package. + title = [] + for line in f: + line.strip() + if re.search("^#", line) is not None: + # The current format is: # name lanes alias index speed + # Where the ordering of the columns can vary + title = line.split()[1:] + continue + #print title + + # Parsing logic for 'port_config.ini' file + if (parse_fmt_port_config_ini): + # bcm_port is not explicitly listed in port_config.ini format + # Currently we assume ports are listed in numerical order according to bcm_port + # so we use the port's position in the file (zero-based) as bcm_port + portname = line.split()[0] + + bcm_port = str(port_pos_in_file) + + if "index" in title: + fp_port_index = int(line.split()[title.index("index")]) + # Leave the old code for backward compatibility + # if len(line.split()) >= 4: + # fp_port_index = (line.split()[3]) + # print(fp_port_index) + else: + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))+1 + else: # Parsing logic for older 'portmap.ini' file + (portname, bcm_port) = line.split("=")[1].split(",")[:2] + + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))+1 + + if ((len(self.sfp_ports) > 0) and (fp_port_index not in self.sfp_ports)): + continue + + if first == 1: + # Initialize last_[physical|logical]_port + # to the first valid port + last_fp_port_index = fp_port_index + last_portname = portname + first = 0 + + logical.append(portname) + + logical_to_bcm[portname] = "xe" + bcm_port + logical_to_physical[portname] = [fp_port_index] + if physical_to_logical.get(fp_port_index) is None: + physical_to_logical[fp_port_index] = [portname] + else: + physical_to_logical[fp_port_index].append( + portname) + + if (fp_port_index - last_fp_port_index) > 1: + # last port was a gang port + for p in range(last_fp_port_index+1, fp_port_index): + logical_to_physical[last_portname].append(p) + if physical_to_logical.get(p) is None: + physical_to_logical[p] = [last_portname] + else: + physical_to_logical[p].append(last_portname) + + last_fp_port_index = fp_port_index + last_portname = portname + + port_pos_in_file += 1 + + self.logical = logical + self.logical_to_bcm = logical_to_bcm + self.logical_to_physical = logical_to_physical + self.physical_to_logical = physical_to_logical + + # print(self.logical_to_physical) + '''print("logical: " + self.logical) + print("logical to bcm: " + self.logical_to_bcm) + print("logical to physical: " + self.logical_to_physical) + print("physical to logical: " + self.physical_to_logical)''' + #print("exiting port_tab_mappings") + + @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 + + @property + def get_transceiver_change_event(self): + raise NotImplementedError diff --git a/device/marvell/arm64-marvell_db98cx8580_32cd-r0/pmon_daemon_control.json b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..94592fa8cebc --- /dev/null +++ b/device/marvell/arm64-marvell_db98cx8580_32cd-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/marvell/armhf-marvell_et6448m_52x-r0/default_sku b/device/marvell/armhf-marvell_et6448m_52x-r0/default_sku new file mode 100644 index 000000000000..4f0da7a26939 --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/default_sku @@ -0,0 +1 @@ +et6448m t1 diff --git a/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/buffers_defaults_t1.j2 b/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/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/marvell/armhf-marvell_et6448m_52x-r0/et6448m/port_config.ini b/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/port_config.ini new file mode 100644 index 000000000000..062c252ce195 --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/port_config.ini @@ -0,0 +1,53 @@ +# name lanes alias index speed +Ethernet0 1 Ethernet0 1 1000 +Ethernet1 2 Ethernet1 2 1000 +Ethernet2 3 Ethernet2 3 1000 +Ethernet3 4 Ethernet3 4 1000 +Ethernet4 5 Ethernet4 5 1000 +Ethernet5 6 Ethernet5 6 1000 +Ethernet6 7 Ethernet6 7 1000 +Ethernet7 8 Ethernet7 8 1000 +Ethernet8 9 Ethernet8 9 1000 +Ethernet9 10 Ethernet9 10 1000 +Ethernet10 11 Ethernet10 11 1000 +Ethernet11 12 Ethernet11 12 1000 +Ethernet12 13 Ethernet12 13 1000 +Ethernet13 14 Ethernet13 14 1000 +Ethernet14 15 Ethernet14 15 1000 +Ethernet15 16 Ethernet15 16 1000 +Ethernet16 17 Ethernet16 17 1000 +Ethernet17 18 Ethernet17 18 1000 +Ethernet18 19 Ethernet18 19 1000 +Ethernet19 20 Ethernet19 20 1000 +Ethernet20 21 Ethernet20 21 1000 +Ethernet21 22 Ethernet21 22 1000 +Ethernet22 23 Ethernet22 23 1000 +Ethernet23 24 Ethernet23 24 1000 +Ethernet24 25 Ethernet24 25 1000 +Ethernet25 26 Ethernet25 26 1000 +Ethernet26 27 Ethernet26 27 1000 +Ethernet27 28 Ethernet27 28 1000 +Ethernet28 29 Ethernet28 29 1000 +Ethernet29 30 Ethernet29 30 1000 +Ethernet30 31 Ethernet30 31 1000 +Ethernet31 32 Ethernet31 32 1000 +Ethernet32 33 Ethernet32 33 1000 +Ethernet33 34 Ethernet33 34 1000 +Ethernet34 35 Ethernet34 35 1000 +Ethernet35 36 Ethernet35 36 1000 +Ethernet36 37 Ethernet36 37 1000 +Ethernet37 38 Ethernet37 38 1000 +Ethernet38 39 Ethernet38 39 1000 +Ethernet39 40 Ethernet39 40 1000 +Ethernet40 41 Ethernet40 41 1000 +Ethernet41 42 Ethernet41 42 1000 +Ethernet42 43 Ethernet42 43 1000 +Ethernet43 44 Ethernet43 44 1000 +Ethernet44 45 Ethernet44 45 1000 +Ethernet45 46 Ethernet45 46 1000 +Ethernet46 47 Ethernet46 47 1000 +Ethernet47 48 Ethernet47 48 1000 +Ethernet48 49 Ethernet48 49 10000 +Ethernet49 50 Ethernet49 50 10000 +Ethernet50 51 Ethernet50 51 10000 +Ethernet51 52 Ethernet51 52 10000 diff --git a/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/profile.ini b/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/profile.ini new file mode 100644 index 000000000000..c81a156d58f9 --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/profile.ini @@ -0,0 +1 @@ +switchMacAddress=00:50:43:ee:ee:ee diff --git a/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/sai.profile b/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/sai.profile new file mode 100644 index 000000000000..10053fa935a1 --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/et6448m/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=et6448m +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/armhf-marvell_et6448m_52x-r0/fancontrol b/device/marvell/armhf-marvell_et6448m_52x-r0/fancontrol new file mode 100755 index 000000000000..050e2504626c --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/fancontrol @@ -0,0 +1,9 @@ +INTERVAL=10 +DEVPATH=hwmon1=devices/platform/soc/soc:internal-regs/f1011000.i2c/i2c-0/0-002e +DEVNAME=hwmon1=adt7473 +FCTEMPS=hwmon1/device/pwm1=hwmon1/device/temp1_input hwmon1/device/pwm2=hwmon1/device/temp2_input +FCFANS=hwmon1/device/pwm1= hwmon1/device/pwm2=hwmon1/device/fan1_input +MINTEMP=hwmon1/device/pwm1=20 hwmon1/device/pwm2=20 +MAXTEMP=hwmon1/device/pwm1=60 hwmon1/device/pwm2=60 +MINSTART=hwmon1/device/pwm1=150 hwmon1/device/pwm2=150 +MINSTOP=hwmon1/device/pwm1=0 hwmon1/device/pwm2=0 diff --git a/device/marvell/armhf-marvell_et6448m_52x-r0/plugins/eeprom.py b/device/marvell/armhf-marvell_et6448m_52x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..71f05c5b70f5 --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/plugins/eeprom.py @@ -0,0 +1,11 @@ +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/etc/sonic/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/marvell/armhf-marvell_et6448m_52x-r0/plugins/psuutil.py b/device/marvell/armhf-marvell_et6448m_52x-r0/plugins/psuutil.py new file mode 100755 index 000000000000..ab6aeff2b20b --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/plugins/psuutil.py @@ -0,0 +1,76 @@ +import sys +import os.path +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + +smbus_present = 1 +try: + import smbus +except ImportError as e: + smbus_present = 0 + +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) + MAX_PSUS = 2 + + def get_num_psus(self): + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + if index is None: + return False + if smbus_present == 0: + cmdstatus, psustatus = commands.getstatusoutput( + 'i2cget -y 0 0x41 0xa') # need to verify the cpld register logic + psustatus = int(psustatus, 16) + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0xa + psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + if index == 1: + psustatus = psustatus & 4 + if psustatus == 4: + return True + if index == 2: + psustatus = psustatus & 8 + if psustatus == 8: + return True + + return False + + def get_psu_presence(self, index): + if index is None: + return False + + if smbus_present == 0: + cmdstatus, psustatus = commands.getstatusoutput( + 'i2cget -y 0 0x41 0xa') # need to verify the cpld register logic + psustatus = int(psustatus, 16) + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0xa + psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + + if index == 1: + psustatus = psustatus & 1 + if psustatus == 1: + return True + if index == 2: + psustatus = psustatus & 2 + if psustatus == 2: + return True + return False diff --git a/device/marvell/armhf-marvell_et6448m_52x-r0/plugins/sfputil.py b/device/marvell/armhf-marvell_et6448m_52x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..39d5db4ce7f4 --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/plugins/sfputil.py @@ -0,0 +1,267 @@ +try: + import os + import time + import re + import sys + import glob + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + +smbus_present = 1 + +try: + import smbus +except ImportError as e: + smbus_present = 0 + + +class SfpUtil(SfpUtilBase): + """Platform specific sfputil class""" + + _port_start = 49 + _port_end = 52 + ports_in_block = 4 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 49: 2, + 50: 3, + 51: 4, + 52: 5 + } + + _qsfp_ports = list(range(_port_start, ports_in_block + 1)) + _changed_ports = [0, 0, 0, 0] + + def __init__(self): + + # Enable optical SFP Tx + if smbus_present == 0: + os.system("i2cset -y -m 0x0f 0 0x41 0x5 0x00") + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICEREG = 0x5 + OPTIC_E = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG) + OPTIC_E = OPTIC_E & 0xf0 + bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, OPTIC_E) + + # Mux Ordering + mux_dev = sorted(glob.glob("/sys/class/i2c-adapter/i2c-0/i2c-[0-9]")) + + # Enable optoe2 Driver + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + bus_path = "/sys/class/i2c-adapter/i2c-{0}/" + y = 0 + for x in range(self.port_start, self.port_end + 1): + mux_dev_num = mux_dev[y] + self.port_to_i2c_mapping[x] = mux_dev_num[-1] + y = y + 1 + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x]) + #print port_eeprom_path + if not os.path.exists(port_eeprom_path): + bus_dev_path = bus_path.format(self.port_to_i2c_mapping[x]) + os.system("echo optoe2 0x50 > " + bus_dev_path + "/new_device") + self.port_to_eeprom_mapping[x] = port_eeprom_path + self._port_to_eeprom_mapping[x] = port_eeprom_path + 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/class/i2c-adapter/i2c-{0}/{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): + 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 + prt = port_num % 49 + sel = "{0:02b}".format(prt) + p = sel[0] + q = sel[1] + + pos = [1, 2, 4, 8] + bit_pos = pos[prt] + if smbus_present == 0: + cmdstatus, sfpstatus = commands.getstatusoutput( + 'i2cget -y 0 0x41 0x3') # need to verify the cpld register logic + sfpstatus = int(sfpstatus, 16) + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0x3 + sfpstatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + sfpstatus = sfpstatus & (bit_pos) + if sfpstatus == 0: + #print("Port " + str(port_num) + "present") + return True + + return False + + def read_porttab_mappings(self, porttabfile): + logical = [] + logical_to_physical = {} + physical_to_logical = {} + last_fp_port_index = 0 + last_portname = "" + first = 1 + port_pos_in_file = 0 + parse_fmt_port_config_ini = False + + try: + f = open(porttabfile) + except: + raise + + parse_fmt_port_config_ini = (os.path.basename(porttabfile) == "port_config.ini") + + # Read the porttab file and generate dicts + # with mapping for future reference. + # + # TODO: Refactor this to use the portconfig.py module that now + # exists as part of the sonic-config-engine package. + title = [] + for line in f: + line.strip() + if re.search("^#", line) is not None: + # The current format is: # name lanes alias index speed + # Where the ordering of the columns can vary + title = line.split()[1:] + continue + + # Parsing logic for 'port_config.ini' file + if (parse_fmt_port_config_ini): + portname = line.split()[0] + + if "index" in title: + fp_port_index = int(line.split()[title.index("index")]) + # Leave the old code for backward compatibility + elif len(line.split()) >= 4: + fp_port_index = int(line.split()[3]) + else: + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))+1 + # print(fp_port_index) + else: # Parsing logic for older 'portmap.ini' file + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))+1 + + if ((len(self.sfp_ports) > 0) and (fp_port_index not in self.sfp_ports)): + continue + + if first == 1: + # Initialize last_[physical|logical]_port + # to the first valid port + last_fp_port_index = fp_port_index + last_portname = portname + first = 0 + + logical.append(portname) + + logical_to_physical[portname] = [fp_port_index] + if physical_to_logical.get(fp_port_index) is None: + physical_to_logical[fp_port_index] = [portname] + else: + physical_to_logical[fp_port_index].append( + portname) + + if (fp_port_index - last_fp_port_index) > 1: + # last port was a gang port + for p in range(last_fp_port_index+1, fp_port_index): + logical_to_physical[last_portname].append(p) + if physical_to_logical.get(p) is None: + physical_to_logical[p] = [last_portname] + else: + physical_to_logical[p].append(last_portname) + + last_fp_port_index = fp_port_index + last_portname = portname + + port_pos_in_file += 1 + + self.logical = logical + self.logical_to_physical = logical_to_physical + self.physical_to_logical = physical_to_logical + # print(self.logical_to_physical) + + @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 + + def get_transceiver_change_event(self, timeout): + port_dict = {} + port = 0 + + if timeout == 0: + cd_ms = sys.maxsize + else: + cd_ms = timeout + changed_port = 0 + # poll per second + while cd_ms > 0: + for port_num in range(49, 53): + prt = port_num % 49 + sfpstatus = self.get_presence(port_num) + if sfpstatus: + port_dict[str(port_num)] = '1' + if self._changed_ports[prt] == 0: + changed_port = 1 + self._changed_ports[prt] = 1 + else: + port_dict[str(port_num)] = '0' + if self._changed_ports[prt] == 1: + changed_port = 1 + self._changed_ports[prt] = 0 + + if changed_port != 0: + break + time.sleep(1) + cd_ms = cd_ms - 1000 + + if changed_port: + return True, port_dict + else: + return True, {} + return False, {} diff --git a/device/marvell/armhf-marvell_et6448m_52x-r0/pmon_daemon_control.json b/device/marvell/armhf-marvell_et6448m_52x-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..a3ecea34bcc9 --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_thermalctld": true, + "skip_ledd": true +} diff --git a/device/marvell/armhf-marvell_et6448m_52x-r0/sensors.conf b/device/marvell/armhf-marvell_et6448m_52x-r0/sensors.conf new file mode 100644 index 000000000000..5f9b97162ee2 --- /dev/null +++ b/device/marvell/armhf-marvell_et6448m_52x-r0/sensors.conf @@ -0,0 +1,18 @@ +chip "adt7473-*" + label fan1 "rear fan 1" + label fan2 "rear fan 2" + ignore fan3 + ignore fan4 + ignore in1 + +chip "lm75a-i2c-*-4a" + label temp1 "MAC temp sensor" + set temp1_max 65 + set temp1_crit 75 + +chip "lm75a-i2c-*-4b" + label temp1 "Board temp sensor" + set temp2_max 65 + set temp2_crit 75 +chip "armada_thermal-*" + ignore temp1 diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t0.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t1.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/port_config.ini b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/port_config.ini new file mode 100644 index 000000000000..074c0344c896 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/port_config.ini @@ -0,0 +1,19 @@ +# name lanes speed alias +Ethernet0 0 25000 twenty5GigE0 +Ethernet1 1 25000 twenty5GigE1 +Ethernet2 2 25000 twenty5GigE2 +Ethernet3 3 25000 twenty5GigE3 +Ethernet4 4 25000 twenty5GigE4 +Ethernet5 5 25000 twenty5GigE5 +Ethernet6 6 25000 twenty5GigE6 +Ethernet7 7 25000 twenty5GigE7 +Ethernet8 8 25000 twenty5GigE8 +Ethernet9 9 25000 twenty5GigE9 +Ethernet10 10 25000 twenty5GigE10 +Ethernet11 11 25000 twenty5GigE11 +Ethernet12 12 25000 twenty5GigE12 +Ethernet13 13 25000 twenty5GigE13 +Ethernet14 14 25000 twenty5GigE14 +Ethernet15 15 25000 twenty5GigE15 +Ethernet16 16 10000 tenGigE16 +Ethernet17 17 10000 tenGigE17 diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/profile.ini b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/profile.ini new file mode 100644 index 000000000000..aeaafc4e6e4d --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 001:1 002:1 003:1 004:1 005:1 006:1 007:1 008:1 009:1 010:1 011:1 012:1 013:1 014:1 015:1 diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/sai.profile b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/sai.profile new file mode 100644 index 000000000000..2c9623c91105 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16X25G/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON16X25G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t0.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t1.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/port_config.ini b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/port_config.ini new file mode 100644 index 000000000000..6a9bfda3fb8b --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/port_config.ini @@ -0,0 +1,19 @@ +# name lanes speed alias +Ethernet0 0,1,2,3,4,5,6,7 400000 four00GigE0 +Ethernet8 8,9,10,11,12,13,14,15 400000 four00GigE1 +Ethernet16 16,17,18,19,20,21,22,23 400000 four00GigE2 +Ethernet24 24,25,26,27,28,29,30,31 400000 four00GigE2 +Ethernet32 32,33,34,35,36,37,38,39 400000 four00GigE3 +Ethernet40 40,41,42,43,44,45,46,47 400000 four00GigE4 +Ethernet48 48,49,50,51,52,53,54,55 400000 four00GigE5 +Ethernet56 56,57,58,59,60,61,62,63 400000 four00GigE6 +Ethernet64 64,65,66,67,68,69,70,71 400000 four00GigE7 +Ethernet72 72,73,74,75,76,77,78,79 400000 four00GigE8 +Ethernet80 80,81,82,83,84,85,86,87 400000 four00GigE9 +Ethernet88 88,89,90,91,92,93,94,95 400000 four00GigE10 +Ethernet96 96,97,98,99,100,101,102,103 400000 four00GigE11 +Ethernet104 104,105,106,107,108,109,110,111 400000 four00GigE12 +Ethernet112 112,113,114,115,116,117,118,119 400000 four00GigE13 +Ethernet120 120,121,122,123,124,125,126,127 400000 four00GigE14 +Ethernet128 128 10000 tenGigE128 +Ethernet129 129 10000 tenGigE129 diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/profile.ini b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/profile.ini new file mode 100644 index 000000000000..16847ec03ae2 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 008:1 016:1 024:1 032:1 040:1 048:1 056:1 064:1 072:1 080:1 088:1 096:1 104:1 112:1 120:1 diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/sai.profile b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/sai.profile new file mode 100644 index 000000000000..6a2438f50180 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON16x400G/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON16x400G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t0.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..f9fb5482560d --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"170000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t1.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..f9fb5482560d --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"170000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/port_config.ini b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/port_config.ini new file mode 100644 index 000000000000..d0402fd44317 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/port_config.ini @@ -0,0 +1,35 @@ +# name lanes speed alias +Ethernet0 0 25000 twenty5GigE0 +Ethernet1 1 25000 twenty5GigE1 +Ethernet2 2 25000 twenty5GigE2 +Ethernet3 3 25000 twenty5GigE3 +Ethernet4 4 25000 twenty5GigE4 +Ethernet5 5 25000 twenty5GigE5 +Ethernet6 6 25000 twenty5GigE6 +Ethernet7 7 25000 twenty5GigE7 +Ethernet8 8 25000 twenty5GigE8 +Ethernet9 9 25000 twenty5GigE9 +Ethernet10 10 25000 twenty5GigE10 +Ethernet11 11 25000 twenty5GigE11 +Ethernet12 12 25000 twenty5GigE12 +Ethernet13 13 25000 twenty5GigE13 +Ethernet14 14 25000 twenty5GigE14 +Ethernet15 15 25000 twenty5GigE15 +Ethernet16 16 25000 twenty5GigE16 +Ethernet17 17 25000 twenty5GigE17 +Ethernet18 18 25000 twenty5GigE18 +Ethernet19 19 25000 twenty5GigE19 +Ethernet20 20 25000 twenty5GigE20 +Ethernet21 21 25000 twenty5GigE21 +Ethernet22 22 25000 twenty5GigE22 +Ethernet23 23 25000 twenty5GigE23 +Ethernet24 24 25000 twenty5GigE24 +Ethernet25 25 25000 twenty5GigE25 +Ethernet26 26 25000 twenty5GigE26 +Ethernet27 27 25000 twenty5GigE27 +Ethernet28 28 25000 twenty5GigE28 +Ethernet29 29 25000 twenty5GigE29 +Ethernet30 30 25000 twenty5GigE30 +Ethernet31 31 25000 twenty5GigE31 +Ethernet32 32 10000 tenGigE32 +Ethernet33 33 10000 tenGigE33 diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/profile.ini b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/profile.ini new file mode 100644 index 000000000000..0ffbefa05805 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 001:1 002:1 003:1 004:1 005:1 006:1 007:1 008:1 009:1 010:1 011:1 012:1 013:1 014:1 015:1 016:1 017:1 018:1 019:1 020:1 021:1 022:1 023:1 024:1 025:1 026:1 027:1 028:1 029:1 030:1 031:1 diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/sai.profile b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/sai.profile new file mode 100644 index 000000000000..fa9983612117 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/FALCON32X25G/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON32x25G64 +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers.json.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers.json.j2 new file mode 100644 index 000000000000..a9a01d707ebf --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers.json.j2 @@ -0,0 +1 @@ +{%- include 'buffers_config.j2' %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_config.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_config.j2 new file mode 100644 index 000000000000..5431fbe72c1f --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_config.j2 @@ -0,0 +1,165 @@ +{%- macro set_default_topology() %} +{%- if default_topo is defined %} +{{ default_topo }} +{%- else %} +def +{%- endif %} +{%- endmacro -%} + +{# Determine device topology and filename postfix #} +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- if 'torrouter' in switch_role.lower() %} +{%- set filename_postfix = 't0' %} +{%- elif 'leafrouter' in switch_role.lower() %} +{%- set filename_postfix = 't1' %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- endif %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- set switch_role = '' %} +{%- endif -%} + +{# Import default values from device HWSKU folder #} +{%- import 'buffers_defaults_%s.j2' % filename_postfix as defs %} + +{%- set default_cable = defs.default_cable -%} + +{# 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 #} +{%- if defs.ports2cable is defined %} + {%- set ports2cable = defs.ports2cable %} +{%- else %} + {%- set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } + -%} +{%- endif %} + +{%- macro cable_length(port_name) %} + {%- set cable_len = [] %} + {%- for local_port in DEVICE_NEIGHBOR %} + {%- if local_port == port_name %} + {%- if DEVICE_NEIGHBOR_METADATA is defined and 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 %} + {%- if 'torrouter' in switch_role.lower() %} + {%- for local_port in VLAN_MEMBER %} + {%- if local_port[1] == port_name %} + {%- set roles3 = switch_role + '_' + 'server' %} + {%- set roles3 = roles3 | lower %} + {%- if roles3 in ports2cable %} + {%- if cable_len.append(ports2cable[roles3]) %}{% endif %} + {%- endif %} + {%- endif %} + {%- endfor %} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- endif %} +{%- endmacro %} + +{%- set PORT_ALL = [] %} + +{%- if PORT is not defined %} + {%- if defs.generate_port_lists(PORT_ALL) %} {% endif %} +{%- else %} + {%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') %} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT_ALL %} + {%- set cable = cable_length(port) %} + "{{ port }}": "{{ cable }}"{%- if not loop.last %},{% endif %} + + {% endfor %} + } + }, + +{% if defs.generate_buffer_pool_and_profiles is defined %} +{{ defs.generate_buffer_pool_and_profiles() }} +{% endif %} + +{%- if defs.generate_profile_lists is defined %} +{{ defs.generate_profile_lists(port_names_active) }}, +{% endif %} + +{%- if defs.generate_pg_profils is defined %} +{{ defs.generate_pg_profils(port_names_active) }} +{% else %} + "BUFFER_PG": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + }, +{% endif %} + +{% if defs.generate_queue_buffers is defined %} +{{ defs.generate_queue_buffers(port_names_active) }} +{% else %} + "BUFFER_QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + } +{% endif %} +} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t0.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t1.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..b23ec5259b21 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11500000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "11500000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"330000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/port_config.ini b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/port_config.ini new file mode 100644 index 000000000000..6a9bfda3fb8b --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/port_config.ini @@ -0,0 +1,19 @@ +# name lanes speed alias +Ethernet0 0,1,2,3,4,5,6,7 400000 four00GigE0 +Ethernet8 8,9,10,11,12,13,14,15 400000 four00GigE1 +Ethernet16 16,17,18,19,20,21,22,23 400000 four00GigE2 +Ethernet24 24,25,26,27,28,29,30,31 400000 four00GigE2 +Ethernet32 32,33,34,35,36,37,38,39 400000 four00GigE3 +Ethernet40 40,41,42,43,44,45,46,47 400000 four00GigE4 +Ethernet48 48,49,50,51,52,53,54,55 400000 four00GigE5 +Ethernet56 56,57,58,59,60,61,62,63 400000 four00GigE6 +Ethernet64 64,65,66,67,68,69,70,71 400000 four00GigE7 +Ethernet72 72,73,74,75,76,77,78,79 400000 four00GigE8 +Ethernet80 80,81,82,83,84,85,86,87 400000 four00GigE9 +Ethernet88 88,89,90,91,92,93,94,95 400000 four00GigE10 +Ethernet96 96,97,98,99,100,101,102,103 400000 four00GigE11 +Ethernet104 104,105,106,107,108,109,110,111 400000 four00GigE12 +Ethernet112 112,113,114,115,116,117,118,119 400000 four00GigE13 +Ethernet120 120,121,122,123,124,125,126,127 400000 four00GigE14 +Ethernet128 128 10000 tenGigE128 +Ethernet129 129 10000 tenGigE129 diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/profile.ini b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/profile.ini new file mode 100644 index 000000000000..16847ec03ae2 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 008:1 016:1 024:1 032:1 040:1 048:1 056:1 064:1 072:1 080:1 088:1 096:1 104:1 112:1 120:1 diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/qos.json.j2 b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/sai.profile b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/sai.profile new file mode 100644 index 000000000000..6a2438f50180 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/db98cx8580_16cd/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON16x400G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/default_sku b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/default_sku new file mode 100644 index 000000000000..7908e555c02c --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/default_sku @@ -0,0 +1 @@ +db98cx8580_16cd t1 diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/plugins/eeprom.py b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/plugins/eeprom.py new file mode 100644 index 000000000000..71f05c5b70f5 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/plugins/eeprom.py @@ -0,0 +1,11 @@ +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/etc/sonic/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/plugins/sfputil.py b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/plugins/sfputil.py new file mode 100644 index 000000000000..4463e687e695 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/plugins/sfputil.py @@ -0,0 +1,251 @@ +try: + import os + import time + import sys + import re + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + +smbus_present = 1 + +try: + import smbus +except ImportError as e: + smbus_present = 0 + + +class SfpUtil(SfpUtilBase): + """Platform specific sfputil class""" + _port_start = 1 + _port_end = 132 + ports_in_block = 132 + + _port_to_eeprom_mapping = {} + + _qsfp_ports = list(range(_port_start, ports_in_block + 1)) + + def __init__(self): + os.system("modprobe i2c-dev") + if not os.path.exists("/sys/bus/i2c/devices/0-0050"): + os.system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-0/new_device") + + eeprom_path = '/sys/bus/i2c/devices/0-0050/eeprom' + # for x in range(self.port _start, self.port_end +1): + x = self.port_start + while(x < self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path + x = x + 1 + 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 + + port_ps = "/sys/bus/i2c/devices/0-0050/sfp_port_reset" + + 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): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def i2c_get(self, device_addr, offset): + status = 0 + if smbus_present == 0: + x = "i2cget -y 0 " + hex(device_addr) + " " + hex(offset) + cmdstatus, status = commands.getstatusoutput(x) + if cmdstatus != 0: + return cmdstatus + status = int(status, 16) + else: + bus = smbus.SMBus(0) + status = bus.read_byte_data(device_addr, offset) + return status + + def i2c_set(self, device_addr, offset, value): + if smbus_present == 0: + cmd = "i2cset -y 0 " + hex(device_addr) + " " + hex(offset) + " " + hex(value) + os.system(cmd) + else: + bus = smbus.SMBus(0) + bus.write_byte_data(device_addr, offset, value) + + 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 + else: + self.i2c_set(0x70, 0, 0) + self.i2c_set(0x71, 0, 0) + self.i2c_set(0x74, 0, 0) + reg = (port_num)/8 + offset = reg % 8 + if offset >= 4: + offset = offset-4 + elif offset < 4: + offset = offset+4 + bin_offset = 1 << offset + + if port_num >= 0 and port_num <= 63: + device_reg = 0x70 + elif port_num >= 64 and port_num <= 127: + device_reg = 0x71 + elif port_num >= 128 and port_num <= 131: + device_reg = 0x74 + + #print "i2c %d %x %x" % (port_num, device_reg, bin_offset) + self.i2c_set(device_reg, 0, bin_offset) + path = "/sys/bus/i2c/devices/0-0050/eeprom" + try: + reg_file = open(path) + reg_file.seek(0o1) + reg_file.read(0o2) + except IOError as e: + return False + + return True + + def read_porttab_mappings(self, porttabfile): + #print("I am in porttab_mappings") + logical = [] + logical_to_bcm = {} + logical_to_physical = {} + physical_to_logical = {} + last_fp_port_index = 0 + last_portname = "" + first = 1 + port_pos_in_file = 0 + parse_fmt_port_config_ini = False + + try: + f = open(porttabfile) + except: + raise + + parse_fmt_port_config_ini = (os.path.basename(porttabfile) == "port_config.ini") + # Read the porttab file and generate dicts + # with mapping for future reference. + # + # TODO: Refactor this to use the portconfig.py module that now + # exists as part of the sonic-config-engine package. + title = [] + for line in f: + line.strip() + if re.search("^#", line) is not None: + # The current format is: # name lanes alias index speed + # Where the ordering of the columns can vary + title = line.split()[1:] + continue + #print title + + # Parsing logic for 'port_config.ini' file + if (parse_fmt_port_config_ini): + # bcm_port is not explicitly listed in port_config.ini format + # Currently we assume ports are listed in numerical order according to bcm_port + # so we use the port's position in the file (zero-based) as bcm_port + portname = line.split()[0] + + bcm_port = str(port_pos_in_file) + + if "index" in title: + fp_port_index = int(line.split()[title.index("index")]) + # Leave the old code for backward compatibility + # if len(line.split()) >= 4: + # fp_port_index = (line.split()[3]) + # print(fp_port_index) + else: + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))+1 + else: # Parsing logic for older 'portmap.ini' file + (portname, bcm_port) = line.split("=")[1].split(",")[:2] + + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))+1 + + if ((len(self.sfp_ports) > 0) and (fp_port_index not in self.sfp_ports)): + continue + + if first == 1: + # Initialize last_[physical|logical]_port + # to the first valid port + last_fp_port_index = fp_port_index + last_portname = portname + first = 0 + + logical.append(portname) + + logical_to_bcm[portname] = "xe" + bcm_port + logical_to_physical[portname] = [fp_port_index] + if physical_to_logical.get(fp_port_index) is None: + physical_to_logical[fp_port_index] = [portname] + else: + physical_to_logical[fp_port_index].append( + portname) + + if (fp_port_index - last_fp_port_index) > 1: + # last port was a gang port + for p in range(last_fp_port_index+1, fp_port_index): + logical_to_physical[last_portname].append(p) + if physical_to_logical.get(p) is None: + physical_to_logical[p] = [last_portname] + else: + physical_to_logical[p].append(last_portname) + + last_fp_port_index = fp_port_index + last_portname = portname + + port_pos_in_file += 1 + + self.logical = logical + self.logical_to_bcm = logical_to_bcm + self.logical_to_physical = logical_to_physical + self.physical_to_logical = physical_to_logical + + # print(self.logical_to_physical) + '''print("logical: " + self.logical) + print("logical to bcm: " + self.logical_to_bcm) + print("logical to physical: " + self.logical_to_physical) + print("physical to logical: " + self.physical_to_logical)''' + #print("exiting port_tab_mappings") + + @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 + + @property + def get_transceiver_change_event(self): + raise NotImplementedError diff --git a/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/pmon_daemon_control.json b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..94592fa8cebc --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_16cd-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t0.j2 b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t1.j2 b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/port_config.ini b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/port_config.ini new file mode 100644 index 000000000000..6d8b5d0a13df --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/port_config.ini @@ -0,0 +1,34 @@ +# name lanes speed alias +Ethernet0 0 25000 twenty5GigE0 +Ethernet1 1 25000 twenty5GigE1 +Ethernet2 2 25000 twenty5GigE2 +Ethernet3 3 25000 twenty5GigE3 +Ethernet4 4 25000 twenty5GigE4 +Ethernet5 5 25000 twenty5GigE5 +Ethernet6 6 25000 twenty5GigE6 +Ethernet7 7 25000 twenty5GigE7 +Ethernet8 8 25000 twenty5GigE8 +Ethernet9 9 25000 twenty5GigE9 +Ethernet10 10 25000 twenty5GigE10 +Ethernet11 11 25000 twenty5GigE11 +Ethernet12 12 25000 twenty5GigE12 +Ethernet13 13 25000 twenty5GigE13 +Ethernet14 14 25000 twenty5GigE14 +Ethernet15 15 25000 twenty5GigE15 +Ethernet16 16 25000 twenty5GigE16 +Ethernet17 17 25000 twenty5GigE17 +Ethernet18 18 25000 twenty5GigE18 +Ethernet19 19 25000 twenty5GigE19 +Ethernet20 20 25000 twenty5GigE20 +Ethernet21 21 25000 twenty5GigE21 +Ethernet22 22 25000 twenty5GigE22 +Ethernet23 23 25000 twenty5GigE23 +Ethernet24 24 25000 twenty5GigE24 +Ethernet25 25 25000 twenty5GigE25 +Ethernet26 26 25000 twenty5GigE26 +Ethernet27 27 25000 twenty5GigE27 +Ethernet28 28 25000 twenty5GigE28 +Ethernet29 29 25000 twenty5GigE29 +Ethernet30 30 25000 twenty5GigE30 +Ethernet31 31 25000 twenty5GigE31 +Ethernet32 32 10000 tenGigE32 diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/profile.ini b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/profile.ini new file mode 100644 index 000000000000..487e80dcbd70 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 001:1 002:1 003:1 004:1 005:1 006:1 007:1 008:1 009:1 010:1 011:1 012:1 013:1 014:1 015:1 016:1 017:1 018:1 019:1 020:1 021:1 022:1 023:1 024:1 025:1 026:1 027:1 028:1 029:1 030:1 031:1 032:1 diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/sai.profile b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/sai.profile new file mode 100644 index 000000000000..dd6f707a81ab --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32X25G/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON32X25G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t0.j2 b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t1.j2 b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/port_config.ini b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/port_config.ini new file mode 100644 index 000000000000..62dd91ba8869 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/port_config.ini @@ -0,0 +1,34 @@ +# name lanes speed alias +Ethernet0 0,1,2,3,4,5,6,7 400000 four00GigE0 +Ethernet8 8,9,10,11,12,13,14,15 400000 four00GigE8 +Ethernet16 16,17,18,19,20,21,22,23 400000 four00GigE16 +Ethernet24 24,25,26,27,28,29,30,31 400000 four00GigE24 +Ethernet32 32,33,34,35,36,37,38,39 400000 four00GigE32 +Ethernet40 40,41,42,43,44,45,46,47 400000 four00GigE40 +Ethernet48 48,49,50,51,52,53,54,55 400000 four00GigE48 +Ethernet56 56,57,58,59,60,61,62,63 400000 four00GigE56 +Ethernet64 64,65,66,67,68,69,70,71 400000 four00GigE64 +Ethernet72 72,73,74,75,76,77,78,79 400000 four00GigE72 +Ethernet80 80,81,82,83,84,85,86,87 400000 four00GigE80 +Ethernet88 88,89,90,91,92,93,94,95 400000 four00GigE88 +Ethernet96 96,97,98,99,100,101,102,103 400000 four00GigE96 +Ethernet104 104,105,106,107,108,109,110,111 400000 four00GigE104 +Ethernet112 112,113,114,115,116,117,118,119 400000 four00GigE112 +Ethernet120 120,121,122,123,124,125,126,127 400000 four00GigE120 +Ethernet128 128,129,130,131,132,133,134,135 400000 four00GigE128 +Ethernet136 136,137,138,139,140,141,142,143 400000 four00GigE136 +Ethernet144 144,145,146,147,148,149,150,151 400000 four00GigE144 +Ethernet152 152,153,154,155,156,157,158,159 400000 four00GigE152 +Ethernet160 160,161,162,163,164,165,166,167 400000 four00GigE160 +Ethernet168 168,169,170,171,172,173,174,175 400000 four00GigE168 +Ethernet176 176,177,178,179,180,181,182,183 400000 four00GigE176 +Ethernet184 184,185,186,187,188,189,190,191 400000 four00GigE184 +Ethernet192 192,193,194,195,196,197,198,199 400000 four00GigE192 +Ethernet200 200,201,202,203,204,205,206,207 400000 four00GigE200 +Ethernet208 208,209,210,211,212,213,214,215 400000 four00GigE208 +Ethernet216 216,217,218,219,220,221,222,223 400000 four00GigE216 +Ethernet224 224,225,226,227,228,229,230,231 400000 four00GigE224 +Ethernet232 232,233,234,235,236,237,238,239 400000 four00GigE232 +Ethernet240 240,241,242,243,244,245,246,247 400000 four00GigE240 +Ethernet248 248,249,250,251,252,253,254,255 400000 four00GigE248 +Ethernet256 256 10000 tenGigE256 diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/profile.ini b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/profile.ini new file mode 100644 index 000000000000..2813bbd363f8 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 008:1 016:1 024:1 032:1 040:1 048:1 056:1 064:1 072:1 080:1 088:1 096:1 104:1 112:1 120:1 128:1 136:1 144:1 152:1 160:1 168:1 176:1 184:1 192:1 200:1 208:1 216:1 224:1 232:1 240:1 248:1 256:1 diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/sai.profile b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/sai.profile new file mode 100644 index 000000000000..6dc6f35fed4e --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/FALCON32x400G/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON32x400G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers.json.j2 b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers.json.j2 new file mode 100644 index 000000000000..a9a01d707ebf --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers.json.j2 @@ -0,0 +1 @@ +{%- include 'buffers_config.j2' %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_config.j2 b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_config.j2 new file mode 100644 index 000000000000..5431fbe72c1f --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_config.j2 @@ -0,0 +1,165 @@ +{%- macro set_default_topology() %} +{%- if default_topo is defined %} +{{ default_topo }} +{%- else %} +def +{%- endif %} +{%- endmacro -%} + +{# Determine device topology and filename postfix #} +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- if 'torrouter' in switch_role.lower() %} +{%- set filename_postfix = 't0' %} +{%- elif 'leafrouter' in switch_role.lower() %} +{%- set filename_postfix = 't1' %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- endif %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- set switch_role = '' %} +{%- endif -%} + +{# Import default values from device HWSKU folder #} +{%- import 'buffers_defaults_%s.j2' % filename_postfix as defs %} + +{%- set default_cable = defs.default_cable -%} + +{# 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 #} +{%- if defs.ports2cable is defined %} + {%- set ports2cable = defs.ports2cable %} +{%- else %} + {%- set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } + -%} +{%- endif %} + +{%- macro cable_length(port_name) %} + {%- set cable_len = [] %} + {%- for local_port in DEVICE_NEIGHBOR %} + {%- if local_port == port_name %} + {%- if DEVICE_NEIGHBOR_METADATA is defined and 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 %} + {%- if 'torrouter' in switch_role.lower() %} + {%- for local_port in VLAN_MEMBER %} + {%- if local_port[1] == port_name %} + {%- set roles3 = switch_role + '_' + 'server' %} + {%- set roles3 = roles3 | lower %} + {%- if roles3 in ports2cable %} + {%- if cable_len.append(ports2cable[roles3]) %}{% endif %} + {%- endif %} + {%- endif %} + {%- endfor %} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- endif %} +{%- endmacro %} + +{%- set PORT_ALL = [] %} + +{%- if PORT is not defined %} + {%- if defs.generate_port_lists(PORT_ALL) %} {% endif %} +{%- else %} + {%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') %} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT_ALL %} + {%- set cable = cable_length(port) %} + "{{ port }}": "{{ cable }}"{%- if not loop.last %},{% endif %} + + {% endfor %} + } + }, + +{% if defs.generate_buffer_pool_and_profiles is defined %} +{{ defs.generate_buffer_pool_and_profiles() }} +{% endif %} + +{%- if defs.generate_profile_lists is defined %} +{{ defs.generate_profile_lists(port_names_active) }}, +{% endif %} + +{%- if defs.generate_pg_profils is defined %} +{{ defs.generate_pg_profils(port_names_active) }} +{% else %} + "BUFFER_PG": { +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + }, +{% endif %} + +{% if defs.generate_queue_buffers is defined %} +{{ defs.generate_queue_buffers(port_names_active) }} +{% else %} + "BUFFER_QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + } +{% endif %} +} diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t0.j2 b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t0.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t1.j2 b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..19be04b5ca4d --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/buffers_defaults_t1.j2 @@ -0,0 +1,36 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "23000000", + "type": "ingress", + "mode": "dynamic" + }, + "egress_pool": { + "size": "23000000", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "mode": "static", + "size":"340000", + "static_th":"0" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_pool]", + "size":"0", + "mode": "dynamic", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/port_config.ini b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/port_config.ini new file mode 100644 index 000000000000..62dd91ba8869 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/port_config.ini @@ -0,0 +1,34 @@ +# name lanes speed alias +Ethernet0 0,1,2,3,4,5,6,7 400000 four00GigE0 +Ethernet8 8,9,10,11,12,13,14,15 400000 four00GigE8 +Ethernet16 16,17,18,19,20,21,22,23 400000 four00GigE16 +Ethernet24 24,25,26,27,28,29,30,31 400000 four00GigE24 +Ethernet32 32,33,34,35,36,37,38,39 400000 four00GigE32 +Ethernet40 40,41,42,43,44,45,46,47 400000 four00GigE40 +Ethernet48 48,49,50,51,52,53,54,55 400000 four00GigE48 +Ethernet56 56,57,58,59,60,61,62,63 400000 four00GigE56 +Ethernet64 64,65,66,67,68,69,70,71 400000 four00GigE64 +Ethernet72 72,73,74,75,76,77,78,79 400000 four00GigE72 +Ethernet80 80,81,82,83,84,85,86,87 400000 four00GigE80 +Ethernet88 88,89,90,91,92,93,94,95 400000 four00GigE88 +Ethernet96 96,97,98,99,100,101,102,103 400000 four00GigE96 +Ethernet104 104,105,106,107,108,109,110,111 400000 four00GigE104 +Ethernet112 112,113,114,115,116,117,118,119 400000 four00GigE112 +Ethernet120 120,121,122,123,124,125,126,127 400000 four00GigE120 +Ethernet128 128,129,130,131,132,133,134,135 400000 four00GigE128 +Ethernet136 136,137,138,139,140,141,142,143 400000 four00GigE136 +Ethernet144 144,145,146,147,148,149,150,151 400000 four00GigE144 +Ethernet152 152,153,154,155,156,157,158,159 400000 four00GigE152 +Ethernet160 160,161,162,163,164,165,166,167 400000 four00GigE160 +Ethernet168 168,169,170,171,172,173,174,175 400000 four00GigE168 +Ethernet176 176,177,178,179,180,181,182,183 400000 four00GigE176 +Ethernet184 184,185,186,187,188,189,190,191 400000 four00GigE184 +Ethernet192 192,193,194,195,196,197,198,199 400000 four00GigE192 +Ethernet200 200,201,202,203,204,205,206,207 400000 four00GigE200 +Ethernet208 208,209,210,211,212,213,214,215 400000 four00GigE208 +Ethernet216 216,217,218,219,220,221,222,223 400000 four00GigE216 +Ethernet224 224,225,226,227,228,229,230,231 400000 four00GigE224 +Ethernet232 232,233,234,235,236,237,238,239 400000 four00GigE232 +Ethernet240 240,241,242,243,244,245,246,247 400000 four00GigE240 +Ethernet248 248,249,250,251,252,253,254,255 400000 four00GigE248 +Ethernet256 256 10000 tenGigE256 diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/profile.ini b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/profile.ini new file mode 100644 index 000000000000..2813bbd363f8 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=00:01:02:03:04:05 +apPortListWithCableLen=000:1 008:1 016:1 024:1 032:1 040:1 048:1 056:1 064:1 072:1 080:1 088:1 096:1 104:1 112:1 120:1 128:1 136:1 144:1 152:1 160:1 168:1 176:1 184:1 192:1 200:1 208:1 216:1 224:1 232:1 240:1 248:1 256:1 diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/qos.json.j2 b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/sai.profile b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/sai.profile new file mode 100644 index 000000000000..6dc6f35fed4e --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/db98cx8580_32cd/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=FALCON32x400G +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/default_sku b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/default_sku new file mode 100644 index 000000000000..563676854022 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/default_sku @@ -0,0 +1 @@ +db98cx8580_32cd t1 diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/plugins/eeprom.py b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/plugins/eeprom.py new file mode 100644 index 000000000000..71f05c5b70f5 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/plugins/eeprom.py @@ -0,0 +1,11 @@ +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/etc/sonic/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/plugins/sfputil.py b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/plugins/sfputil.py new file mode 100644 index 000000000000..b3d1ea371454 --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/plugins/sfputil.py @@ -0,0 +1,257 @@ +try: + import os + import time + import sys + import re + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +if sys.version_info[0] < 3: + import commands +else: + import subprocess as commands + +smbus_present = 1 + +try: + import smbus +except ImportError as e: + smbus_present = 0 + + +class SfpUtil(SfpUtilBase): + """Platform specific sfputil class""" + _port_start = 1 + _port_end = 257 + ports_in_block = 257 + + _port_to_eeprom_mapping = {} + + _qsfp_ports = list(range(_port_start, ports_in_block + 1)) + + def __init__(self): + os.system("modprobe i2c-dev") + if not os.path.exists("/sys/bus/i2c/devices/0-0050"): + os.system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-0/new_device") + + eeprom_path = '/sys/bus/i2c/devices/0-0050/eeprom' + # for x in range(self.port _start, self.port_end +1): + x = self.port_start + while(x < self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path + x = x + 1 + 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 + + port_ps = "/sys/bus/i2c/devices/0-0050/sfp_port_reset" + + 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): + raise NotImplementedError + + def get_low_power_mode(self, port_num): + raise NotImplementedError + + def i2c_get(self, device_addr, offset): + status = 0 + if smbus_present == 0: + x = "i2cget -y 0 " + hex(device_addr) + " " + hex(offset) + cmdstatus, status = commands.getstatusoutput(x) + if cmdstatus != 0: + return cmdstatus + status = int(status, 16) + else: + bus = smbus.SMBus(0) + status = bus.read_byte_data(device_addr, offset) + return status + + def i2c_set(self, device_addr, offset, value): + if smbus_present == 0: + cmd = "i2cset -y 0 " + hex(device_addr) + " " + hex(offset) + " " + hex(value) + os.system(cmd) + else: + bus = smbus.SMBus(0) + bus.write_byte_data(device_addr, offset, value) + + 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 + else: + self.i2c_set(0x70, 0, 0) + self.i2c_set(0x71, 0, 0) + self.i2c_set(0x72, 0, 0) + self.i2c_set(0x73, 0, 0) + self.i2c_set(0x74, 0, 0) + reg = (port_num)/8 + offset = reg % 8 + if offset >= 4: + offset = offset-4 + elif offset < 4: + offset = offset+4 + bin_offset = 1 << offset + + if port_num >= 0 and port_num <= 63: + device_reg = 0x70 + elif port_num >= 64 and port_num <= 127: + device_reg = 0x71 + elif port_num >= 128 and port_num <= 191: + device_reg = 0x72 + elif port_num >= 192 and port_num <= 255: + device_reg = 0x73 + elif port_num >= 256 and port_num <= 257: + device_reg = 0x74 + + #print "i2c %d %x %x" % (port_num, device_reg, bin_offset) + self.i2c_set(device_reg, 0, bin_offset) + path = "/sys/bus/i2c/devices/0-0050/eeprom" + try: + reg_file = open(path) + reg_file.seek(0o1) + reg_file.read(0o2) + except IOError as e: + return False + + return True + + def read_porttab_mappings(self, porttabfile): + #print("I am in porttab_mappings") + logical = [] + logical_to_bcm = {} + logical_to_physical = {} + physical_to_logical = {} + last_fp_port_index = 0 + last_portname = "" + first = 1 + port_pos_in_file = 0 + parse_fmt_port_config_ini = False + + try: + f = open(porttabfile) + except: + raise + + parse_fmt_port_config_ini = (os.path.basename(porttabfile) == "port_config.ini") + # Read the porttab file and generate dicts + # with mapping for future reference. + # + # TODO: Refactor this to use the portconfig.py module that now + # exists as part of the sonic-config-engine package. + title = [] + for line in f: + line.strip() + if re.search("^#", line) is not None: + # The current format is: # name lanes alias index speed + # Where the ordering of the columns can vary + title = line.split()[1:] + continue + #print title + + # Parsing logic for 'port_config.ini' file + if (parse_fmt_port_config_ini): + # bcm_port is not explicitly listed in port_config.ini format + # Currently we assume ports are listed in numerical order according to bcm_port + # so we use the port's position in the file (zero-based) as bcm_port + portname = line.split()[0] + + bcm_port = str(port_pos_in_file) + + if "index" in title: + fp_port_index = int(line.split()[title.index("index")]) + # Leave the old code for backward compatibility + # if len(line.split()) >= 4: + # fp_port_index = (line.split()[3]) + # print(fp_port_index) + else: + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))+1 + else: # Parsing logic for older 'portmap.ini' file + (portname, bcm_port) = line.split("=")[1].split(",")[:2] + + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))+1 + + if ((len(self.sfp_ports) > 0) and (fp_port_index not in self.sfp_ports)): + continue + + if first == 1: + # Initialize last_[physical|logical]_port + # to the first valid port + last_fp_port_index = fp_port_index + last_portname = portname + first = 0 + + logical.append(portname) + + logical_to_bcm[portname] = "xe" + bcm_port + logical_to_physical[portname] = [fp_port_index] + if physical_to_logical.get(fp_port_index) is None: + physical_to_logical[fp_port_index] = [portname] + else: + physical_to_logical[fp_port_index].append( + portname) + + if (fp_port_index - last_fp_port_index) > 1: + # last port was a gang port + for p in range(last_fp_port_index+1, fp_port_index): + logical_to_physical[last_portname].append(p) + if physical_to_logical.get(p) is None: + physical_to_logical[p] = [last_portname] + else: + physical_to_logical[p].append(last_portname) + + last_fp_port_index = fp_port_index + last_portname = portname + + port_pos_in_file += 1 + + self.logical = logical + self.logical_to_bcm = logical_to_bcm + self.logical_to_physical = logical_to_physical + self.physical_to_logical = physical_to_logical + + # print(self.logical_to_physical) + '''print("logical: " + self.logical) + print("logical to bcm: " + self.logical_to_bcm) + print("logical to physical: " + self.logical_to_physical) + print("physical to logical: " + self.physical_to_logical)''' + #print("exiting port_tab_mappings") + + @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 + + @property + def get_transceiver_change_event(self): + raise NotImplementedError diff --git a/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/pmon_daemon_control.json b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..94592fa8cebc --- /dev/null +++ b/device/marvell/x86_64-marvell_db98cx8580_32cd-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/port_config.ini b/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/port_config.ini new file mode 100755 index 000000000000..74865956f61b --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/port_config.ini @@ -0,0 +1,55 @@ +# name lanes +Ethernet0 0 +Ethernet1 1 +Ethernet2 2 +Ethernet3 3 +Ethernet4 4 +Ethernet5 5 +Ethernet6 6 +Ethernet7 7 +Ethernet8 8 +Ethernet9 9 +Ethernet10 10 +Ethernet11 11 +Ethernet12 12 +Ethernet13 13 +Ethernet14 14 +Ethernet15 15 +Ethernet16 16 +Ethernet17 17 +Ethernet18 18 +Ethernet19 19 +Ethernet20 20 +Ethernet21 21 +Ethernet22 22 +Ethernet23 23 +Ethernet24 24 +Ethernet25 25 +Ethernet26 26 +Ethernet27 27 +Ethernet28 28 +Ethernet29 29 +Ethernet30 30 +Ethernet31 31 +Ethernet32 32 +Ethernet33 33 +Ethernet34 34 +Ethernet35 35 +Ethernet36 36 +Ethernet37 37 +Ethernet38 38 +Ethernet39 39 +Ethernet40 40 +Ethernet41 41 +Ethernet42 42 +Ethernet43 43 +Ethernet44 44 +Ethernet45 45 +Ethernet46 46 +Ethernet47 47 +Ethernet48 48 +Ethernet49 49 +Ethernet50 50 +Ethernet51 51 +Ethernet52 52 +Ethernet53 53 diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/sai.profile b/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/sai.profile new file mode 100755 index 000000000000..edba72ba4823 --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/SLM5401-54x/sai.profile @@ -0,0 +1,2 @@ +mode=1 +hwId=slm5401-54x diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/default_sku b/device/marvell/x86_64-marvell_slm5401_54x-r0/default_sku new file mode 100644 index 000000000000..8ace9a8abcef --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/default_sku @@ -0,0 +1 @@ +SLM5401-54x t1 diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/installer.conf b/device/marvell/x86_64-marvell_slm5401_54x-r0/installer.conf new file mode 100755 index 000000000000..14404194ef53 --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/eeprom.py b/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/eeprom.py new file mode 100755 index 000000000000..951384d5e37d --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/1-0057/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/sfputil.py b/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..b1d356e393ee --- /dev/null +++ b/device/marvell/x86_64-marvell_slm5401_54x-r0/plugins/sfputil.py @@ -0,0 +1,132 @@ +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class sfputil(SfpUtilBase): + """Platform specific sfputil class""" + + port_start = 0 + port_end = 31 + ports_in_block = 32 + + port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 9: 18, + 10: 19, + 11: 20, + 12: 21, + 1: 22, + 2: 23, + 3: 24, + 4: 25, + 6: 26, + 5: 27, + 8: 28, + 7: 29, + 13: 30, + 14: 31, + 15: 32, + 16: 33, + 17: 34, + 18: 35, + 19: 36, + 20: 37, + 25: 38, + 26: 39, + 27: 40, + 28: 41, + 29: 42, + 30: 43, + 31: 44, + 32: 45, + 21: 46, + 22: 47, + 23: 48, + 24: 49, + } + + _qsfp_ports = list(range(0, ports_in_block + 1)) + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + 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+1]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + 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+1]) + + 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): + raise NotImplementedErro + + def get_low_power_mode(self, port_num): + raise NotImplementedErro + + 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+1]) + + try: + reg_file = open(port_ps) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return list(range(0, self.ports_in_block + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + 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 diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/LS-SN2700 b/device/mellanox/x86_64-mlnx_lssn2700-r0/LS-SN2700 new file mode 120000 index 000000000000..dfed1bb2cfb5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/LS-SN2700 @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/ACS-MSN2700/ \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/default_sku b/device/mellanox/x86_64-mlnx_lssn2700-r0/default_sku new file mode 100644 index 000000000000..22e3116d2dbb --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/default_sku @@ -0,0 +1 @@ +LS-SN2700 t1 diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/installer.conf b/device/mellanox/x86_64-mlnx_lssn2700-r0/installer.conf new file mode 120000 index 000000000000..955db12ff425 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/installer.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/installer.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_lssn2700-r0/pcie.yaml new file mode 120000 index 000000000000..f739a7e8ec35 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/pcie.yaml @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/pcie.yaml \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/platform_reboot b/device/mellanox/x86_64-mlnx_lssn2700-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-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_lssn2700-r0/platform_wait b/device/mellanox/x86_64-mlnx_lssn2700-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-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_lssn2700-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_lssn2700-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-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_lssn2700-r0/sensors.conf b/device/mellanox/x86_64-mlnx_lssn2700-r0/sensors.conf new file mode 120000 index 000000000000..ea04d66d008c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/sensors.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/sensors.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_lssn2700-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..98df66c27ca5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_lssn2700-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/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_msn2010-r0/ACS-MSN2010/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..7bcae62336f6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..a437d613434d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/hwsku.json b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/hwsku.json new file mode 100644 index 000000000000..7597b2c9a924 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/hwsku.json @@ -0,0 +1,70 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/pg_profile_lookup.ini new file mode 120000 index 000000000000..3c97f3dcb16f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/port_config.ini b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/port_config.ini new file mode 100644 index 000000000000..f9fa81669a13 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/port_config.ini @@ -0,0 +1,23 @@ +# name lanes index +Ethernet0 0 1 +Ethernet4 4 2 +Ethernet8 8 3 +Ethernet12 12 4 +Ethernet16 16 5 +Ethernet20 20 6 +Ethernet24 24 7 +Ethernet28 28 8 +Ethernet32 32 9 +Ethernet36 36 10 +Ethernet40 40 11 +Ethernet44 44 12 +Ethernet48 48 13 +Ethernet52 52 14 +Ethernet56 56 15 +Ethernet60 60 16 +Ethernet64 64 17 +Ethernet68 68 18 +Ethernet72 72,73,74,75 19 +Ethernet76 76,77,78,79 20 +Ethernet80 80,81,82,83 21 +Ethernet84 84,85,86,87 22 diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/qos.json.j2 new file mode 120000 index 000000000000..eccf286dc879 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/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_msn2010-r0/ACS-MSN2010/sai.profile b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai.profile new file mode 100644 index 000000000000..c13ca373750d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2010.xml diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai_2010.xml b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai_2010.xml new file mode 100644 index 000000000000..34151a434a23 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/sai_2010.xml @@ -0,0 +1,176 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 22 + + + + + 1 + 1 + 14 + + + 0 + + + 939524096 + + + 2 + 1 + 15 + 0 + 939524096 + + + 3 + 1 + 16 + 0 + 939524096 + + + 4 + 1 + 17 + 0 + 939524096 + + + 5 + 4 + 19 + 3 + 11534336 + + + 9 + 4 + 18 + 3 + 11534336 + + + 13 + 4 + 21 + 3 + 11534336 + + + 17 + 4 + 20 + 3 + 11534336 + + + 33 + 1 + 10 + 0 + 939524096 + + + 34 + 1 + 11 + 0 + 939524096 + + + 35 + 1 + 12 + 0 + 939524096 + + + 36 + 1 + 13 + 0 + 939524096 + + + 37 + 1 + 6 + 0 + 939524096 + + + 38 + 1 + 7 + 0 + 939524096 + + + 39 + 1 + 8 + 0 + 939524096 + + + 40 + 1 + 9 + 0 + 939524096 + + + 41 + 1 + 2 + 0 + 939524096 + + + 42 + 1 + 3 + 0 + 939524096 + + + 43 + 1 + 4 + 0 + 939524096 + + + 44 + 1 + 5 + 0 + 939524096 + + + 45 + 1 + 0 + 0 + 939524096 + + + 46 + 1 + 1 + 0 + 939524096 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2010-r0/default_sku new file mode 100644 index 000000000000..558120a701d4 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN2010 t1 diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2010-r0/installer.conf new file mode 100644 index 000000000000..c9c9493a5404 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax acpi=noirq" diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn2010-r0/pcie.yaml new file mode 100644 index 000000000000..ca73122aaa81 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/pcie.yaml @@ -0,0 +1,83 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 1f0b + name: 'Host bridge: Intel Corporation Atom processor C2000 SoC Transaction Router + (rev 02)' +- bus: '00' + dev: '01' + fn: '0' + id: 1f10 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 1 (rev + 02)' +- bus: '00' + dev: '02' + fn: '0' + id: 1f11 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 2 (rev + 02)' +- bus: '00' + dev: '03' + fn: '0' + id: 1f12 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 3 (rev + 02)' +- bus: '00' + dev: 0b + fn: '0' + id: 1f18 + name: 'Co-processor: Intel Corporation Atom processor C2000 QAT (rev 02)' +- bus: '00' + dev: 0e + fn: '0' + id: 1f14 + name: 'Host bridge: Intel Corporation Atom processor C2000 RAS (rev 02)' +- bus: '00' + dev: 0f + fn: '0' + id: 1f16 + name: 'IOMMU: Intel Corporation Atom processor C2000 RCEC (rev 02)' +- bus: '00' + dev: '13' + fn: '0' + id: 1f15 + name: 'System peripheral: Intel Corporation Atom processor C2000 SMBus 2.0 (rev + 02)' +- bus: '00' + dev: '14' + fn: '0' + id: 1f41 + name: 'Ethernet controller: Intel Corporation Ethernet Connection I354 (rev 03)' +- bus: '00' + dev: '16' + fn: '0' + id: 1f2c + name: 'USB controller: Intel Corporation Atom processor C2000 USB Enhanced Host + Controller (rev 02)' +- bus: '00' + dev: '17' + fn: '0' + id: 1f22 + name: 'SATA controller: Intel Corporation Atom processor C2000 AHCI SATA2 Controller + (rev 02)' +- bus: '00' + dev: '18' + fn: '0' + id: 1f32 + name: 'SATA controller: Intel Corporation Atom processor C2000 AHCI SATA3 Controller + (rev 02)' +- bus: '00' + dev: 1f + fn: '0' + id: 1f38 + name: 'ISA bridge: Intel Corporation Atom processor C2000 PCU (rev 02)' +- bus: '00' + dev: 1f + fn: '3' + id: 1f3c + name: 'SMBus: Intel Corporation Atom processor C2000 PCU SMBus (rev 02)' +- bus: '01' + dev: '00' + fn: '0' + id: cb84 + name: 'Ethernet controller: Mellanox Technologies MT52100' diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/platform.json b/device/mellanox/x86_64-mlnx_msn2010-r0/platform.json new file mode 100644 index 000000000000..937ba5075c06 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/platform.json @@ -0,0 +1,166 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1", + "lanes": "0", + "breakout_modes": { + "1x25G[10G]" : ["etp1"] + } + }, + "Ethernet4": { + "index": "2", + "lanes": "4", + "breakout_modes": { + "1x25G[10G]" : ["etp2"] + } + }, + "Ethernet8": { + "index": "3", + "lanes": "8", + "breakout_modes": { + "1x25G[10G]" : ["etp3"] + } + }, + "Ethernet12": { + "index": "4", + "lanes": "12", + "breakout_modes": { + "1x25G[10G]" : ["etp4"] + } + }, + "Ethernet16": { + "index": "5", + "lanes": "16", + "breakout_modes": { + "1x25G[10G]" : ["etp5"] + } + }, + "Ethernet20": { + "index": "6", + "lanes": "20", + "breakout_modes": { + "1x25G[10G]" : ["etp6"] + } + }, + "Ethernet24": { + "index": "7", + "lanes": "24", + "breakout_modes": { + "1x25G[10G]" : ["etp7"] + } + }, + "Ethernet28": { + "index": "8", + "lanes": "28", + "breakout_modes": { + "1x25G[10G]" : ["etp8"] + } + }, + "Ethernet32": { + "index": "9", + "lanes": "32", + "breakout_modes": { + "1x25G[10G]" : ["etp9"] + } + }, + "Ethernet36": { + "index": "10", + "lanes": "36", + "breakout_modes": { + "1x25G[10G]" : ["etp10"] + } + }, + "Ethernet40": { + "index": "11", + "lanes": "40", + "breakout_modes": { + "1x25G[10G]" : ["etp11"] + } + }, + "Ethernet44": { + "index": "12", + "lanes": "44", + "breakout_modes": { + "1x25G[10G]" : ["etp12"] + } + }, + "Ethernet48": { + "index": "13", + "lanes": "48", + "breakout_modes": { + "1x25G[10G]" : ["etp13"] + } + }, + "Ethernet52": { + "index": "14", + "lanes": "52", + "breakout_modes": { + "1x25G[10G]" : ["etp14"] + } + }, + "Ethernet56": { + "index": "15", + "lanes": "56", + "breakout_modes": { + "1x25G[10G]" : ["etp15"] + } + }, + "Ethernet60": { + "index": "16", + "lanes": "60", + "breakout_modes": { + "1x25G[10G]" : ["etp16"] + } + }, + "Ethernet64": { + "index": "17", + "lanes": "64", + "breakout_modes": { + "1x25G[10G]" : ["etp17"] + } + }, + "Ethernet68": { + "index": "18", + "lanes": "68", + "breakout_modes": { + "1x25G[10G]" : ["etp18"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp19"], + "2x50G[40G,25G,10G]": ["etp19a", "etp19b"], + "4x25G[10G]": ["etp19a", "etp19b", "etp19c", "etp19d"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp20"], + "2x50G[40G,25G,10G]": ["etp20a", "etp20b"], + "4x25G[10G]": ["etp20a", "etp20b", "etp20c", "etp20d"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp21"], + "2x50G[40G,25G,10G]": ["etp21a", "etp21b"], + "4x25G[10G]": ["etp21a", "etp21b", "etp21c", "etp21d"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp22"], + "2x50G[40G,25G,10G]": ["etp22a", "etp22b"], + "4x25G[10G]": ["etp22a", "etp22b", "etp22c", "etp22d"] + } + } + } +} 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..a5cd5b152c46 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/platform_components.json @@ -0,0 +1,13 @@ +{ + "chassis": { + "MSN2010": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2010-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-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_msn2010-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn2010-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-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_msn2010-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-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_msn2010-r0/plugins/fanutil.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/fanutil.py new file mode 120000 index 000000000000..82ea06ef915f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/fanutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/fanutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/psuutil.py new file mode 100644 index 000000000000..0d864849dc48 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/psuutil.py @@ -0,0 +1,73 @@ +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/var/run/hw-management/thermal/" + self.psu_presence = "psu{}_pwr_status" + self.psu_oper_status = "psu{}_pwr_status" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_oper_status.format(index), 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_presence.format(index), 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-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_msn2010-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-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_msn2010-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-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_msn2010-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-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_msn2010-r0/plugins/thermalutil.py b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/thermalutil.py new file mode 120000 index 000000000000..cef21ffacccc --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/plugins/thermalutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/thermalutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn2010-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-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_msn2010-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn2010-r0/sensors.conf new file mode 100644 index 000000000000..7f5b023afec6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/sensors.conf @@ -0,0 +1,49 @@ +################################################################################ +# Copyright (c) 2020 Mellanox Technologies +# +# Platform specific sensors config for SN2010 +################################################################################ + +# 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 "lm75-i2c-*-4a" + label temp1 "Ambient Port Side Temp (air exhaust)" + chip "lm75-i2c-*-4b" + label temp1 "Ambient Fan Side Temp (air intake)" + +# Power supplies +bus "i2c-5" "i2c-1-mux (chan_id 4)" + chip "tps53679-i2c-*-70" + label in1 "PMIC-1 PSU 12V Rail (in1)" + label in2 "PMIC-1 PSU 12V Rail (in2)" + label in3 "PMIC-1 0.9V VCORE (out)" + label in4 "PMIC-1 1.2V Rail (out)" + label temp1 "PMIC-1 Temp 1" + label temp2 "PMIC-1 Temp 2" + label power1 "PMIC-1 0.9V VCORE Pwr (out)" + label power2 "PMIC-1 1.2V Rail Pwr (out)" + label curr1 "PMIC-1 0.9V VCORE Curr (out)" + label curr2 "PMIC-1 1.2V Rail Curr (out)" + chip "tps53679-i2c-*-71" + label in1 "PMIC-2 PSU 12V Rail (in1)" + label in2 "PMIC-2 PSU 12V Rail (in2)" + label in3 "PMIC-2 2.2V Rail (out)" + ignore in4 + label temp1 "PMIC-2 Temp 1" + label temp2 "PMIC-2 Temp 2" + label power1 "PMIC-2 2.2V Rail Pwr (out)" + ignore power2 + label curr1 "PMIC-2 2.2V Rail Curr (out)" + ignore curr2 + +# Chassis fans +bus "i2c-2" "i2c-1-mux (chan_id 1)" + chip "mlxsw-i2c-*-48" + label fan1 "Chassis Fan 1" + label fan2 "Chassis Fan 2" + label fan3 "Chassis Fan 3" + label fan4 "Chassis Fan 4" diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn2010-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..a4c9e9b44e02 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/system_health_monitoring_config.json @@ -0,0 +1,11 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": ["psu.voltage", "psu.temperature"], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "orange", + "normal": "green", + "booting": "orange_blink" + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2010-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/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_msn2100-r0/ACS-MSN2100/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..7bcae62336f6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..a437d613434d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/hwsku.json b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/hwsku.json new file mode 100644 index 000000000000..d77e2974f645 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/hwsku.json @@ -0,0 +1,52 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/pg_profile_lookup.ini new file mode 120000 index 000000000000..3c97f3dcb16f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/port_config.ini b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/port_config.ini new file mode 100644 index 000000000000..c7ea79bbdbee --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/port_config.ini @@ -0,0 +1,17 @@ +# name lanes index +Ethernet0 0,1,2,3 1 +Ethernet4 4,5,6,7 2 +Ethernet8 8,9,10,11 3 +Ethernet12 12,13,14,15 4 +Ethernet16 16,17,18,19 5 +Ethernet20 20,21,22,23 6 +Ethernet24 24,25,26,27 7 +Ethernet28 28,29,30,31 8 +Ethernet32 32,33,34,35 9 +Ethernet36 36,37,38,39 10 +Ethernet40 40,41,42,43 11 +Ethernet44 44,45,46,47 12 +Ethernet48 48,49,50,51 13 +Ethernet52 52,53,54,55 14 +Ethernet56 56,57,58,59 15 +Ethernet60 60,61,62,63 16 diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai.profile b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai.profile new file mode 100644 index 000000000000..5a381e4666ee --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2100.xml diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai_2100.xml b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai_2100.xml new file mode 100644 index 000000000000..92150596df64 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/sai_2100.xml @@ -0,0 +1,134 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 16 + + + + + 25 + 4 + 0 + + + 3 + + + 98368 + + + 29 + 4 + 1 + 3 + 98368 + + + 17 + 4 + 2 + 3 + 98368 + + + 21 + 4 + 3 + 3 + 98368 + + + 9 + 4 + 4 + 3 + 98368 + + + 13 + 4 + 5 + 3 + 98368 + + + 1 + 4 + 6 + 3 + 98368 + + + 5 + 4 + 7 + 3 + 98368 + + + 37 + 4 + 8 + 3 + 98368 + + + 33 + 4 + 9 + 3 + 98368 + + + 45 + 4 + 10 + 3 + 98368 + + + 41 + 4 + 11 + 3 + 98368 + + + 53 + 4 + 12 + 3 + 98368 + + + 49 + 4 + 13 + 3 + 98368 + + + 61 + 4 + 14 + 3 + 98368 + + + 57 + 4 + 15 + 3 + 98368 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2100-r0/default_sku new file mode 100644 index 000000000000..5d7c94c0bc8c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN2100 t1 diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2100-r0/installer.conf new file mode 120000 index 000000000000..955db12ff425 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/installer.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/installer.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn2100-r0/pcie.yaml new file mode 100644 index 000000000000..63f09eecde7c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/pcie.yaml @@ -0,0 +1,83 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 1f0b + name: 'Host bridge: Intel Corporation Atom processor C2000 SoC Transaction Router + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 1f10 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 1 (rev + 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 1f11 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 2 (rev + 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 1f12 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 3 (rev + 03)' +- bus: '00' + dev: 0b + fn: '0' + id: 1f18 + name: 'Co-processor: Intel Corporation Atom processor C2000 QAT (rev 03)' +- bus: '00' + dev: 0e + fn: '0' + id: 1f14 + name: 'Host bridge: Intel Corporation Atom processor C2000 RAS (rev 03)' +- bus: '00' + dev: 0f + fn: '0' + id: 1f16 + name: 'IOMMU: Intel Corporation Atom processor C2000 RCEC (rev 03)' +- bus: '00' + dev: '13' + fn: '0' + id: 1f15 + name: 'System peripheral: Intel Corporation Atom processor C2000 SMBus 2.0 (rev + 03)' +- bus: '00' + dev: '14' + fn: '0' + id: 1f41 + name: 'Ethernet controller: Intel Corporation Ethernet Connection I354 (rev 03)' +- bus: '00' + dev: '16' + fn: '0' + id: 1f2c + name: 'USB controller: Intel Corporation Atom processor C2000 USB Enhanced Host + Controller (rev 03)' +- bus: '00' + dev: '17' + fn: '0' + id: 1f22 + name: 'SATA controller: Intel Corporation Atom processor C2000 AHCI SATA2 Controller + (rev 03)' +- bus: '00' + dev: '18' + fn: '0' + id: 1f32 + name: 'SATA controller: Intel Corporation Atom processor C2000 AHCI SATA3 Controller + (rev 03)' +- bus: '00' + dev: 1f + fn: '0' + id: 1f38 + name: 'ISA bridge: Intel Corporation Atom processor C2000 PCU (rev 03)' +- bus: '00' + dev: 1f + fn: '3' + id: 1f3c + name: 'SMBus: Intel Corporation Atom processor C2000 PCU SMBus (rev 03)' +- bus: '01' + dev: '00' + fn: '0' + id: cb84 + name: 'Ethernet controller: Mellanox Technologies MT52100' diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/platform.json b/device/mellanox/x86_64-mlnx_msn2100-r0/platform.json new file mode 100644 index 000000000000..cf16b7de93c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/platform.json @@ -0,0 +1,148 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp1"], + "2x50G[40G,25G,10G]": ["etp1a", "etp1b"], + "4x25G[10G]": ["etp1a", "etp1b", "etp1c", "etp1d"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp2"], + "2x50G[40G,25G,10G]": ["etp2a", "etp2b"], + "4x25G[10G]": ["etp2a", "etp2b", "etp2c", "etp2d"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp3"], + "2x50G[40G,25G,10G]": ["etp3a", "etp3b"], + "4x25G[10G]": ["etp3a", "etp3b", "etp3c", "etp3d"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp4"], + "2x50G[40G,25G,10G]": ["etp4a", "etp4b"], + "4x25G[10G]": ["etp4a", "etp4b", "etp4c", "etp4d"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp5"], + "2x50G[40G,25G,10G]": ["etp5a", "etp5b"], + "4x25G[10G]": ["etp5a", "etp5b", "etp5c", "etp5d"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp6"], + "2x50G[40G,25G,10G]": ["etp6a", "etp6b"], + "4x25G[10G]": ["etp6a", "etp6b", "etp6c", "etp6d"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp7"], + "2x50G[40G,25G,10G]": ["etp7a", "etp7b"], + "4x25G[10G]": ["etp7a", "etp7b", "etp7c", "etp7d"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp8"], + "2x50G[40G,25G,10G]": ["etp8a", "etp8b"], + "4x25G[10G]": ["etp8a", "etp8b", "etp8c", "etp8d"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp9"], + "2x50G[40G,25G,10G]": ["etp9a", "etp9b"], + "4x25G[10G]": ["etp9a", "etp9b", "etp9c", "etp9d"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp10"], + "2x50G[40G,25G,10G]": ["etp10a", "etp10b"], + "4x25G[10G]": ["etp10a", "etp10b", "etp10c", "etp10d"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp11"], + "2x50G[40G,25G,10G]": ["etp11a", "etp11b"], + "4x25G[10G]": ["etp11a", "etp11b", "etp11c", "etp11d"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp12"], + "2x50G[40G,25G,10G]": ["etp12a", "etp12b"], + "4x25G[10G]": ["etp12a", "etp12b", "etp12c", "etp12d"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp13"], + "2x50G[40G,25G,10G]": ["etp13a", "etp13b"], + "4x25G[10G]": ["etp13a", "etp13b", "etp13c", "etp13d"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp14"], + "2x50G[40G,25G,10G]": ["etp14a", "etp14b"], + "4x25G[10G]": ["etp14a", "etp14b", "etp14c", "etp14d"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp15"], + "2x50G[40G,25G,10G]": ["etp15a", "etp15b"], + "4x25G[10G]": ["etp15a", "etp15b", "etp15c", "etp15d"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp16"], + "2x50G[40G,25G,10G]": ["etp16a", "etp16b"], + "4x25G[10G]": ["etp16a", "etp16b", "etp16c", "etp16d"] + } + } + } +} 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..b8936fa3ad43 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/platform_components.json @@ -0,0 +1,13 @@ +{ + "chassis": { + "MSN2100": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2100-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-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_msn2100-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn2100-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-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_msn2100-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-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_msn2100-r0/plugins/fanutil.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/fanutil.py new file mode 120000 index 000000000000..82ea06ef915f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/fanutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/fanutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/psuutil.py new file mode 100644 index 000000000000..2b4f87397bc4 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/psuutil.py @@ -0,0 +1,63 @@ +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_path = "/var/run/hw-management/thermal/" + self.psu_presence = "psu{}_status" + self.psu_oper_status = "psu{}_pwr_status" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path + self.psu_oper_status.format(index), 'r') as power_status: + status = int(power_status.read()) + except IOError: + return False + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :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 + """ + return isinstance(index, int) and index > 0 and index <= self.get_num_psus() diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-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_msn2100-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-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_msn2100-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-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_msn2100-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-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_msn2100-r0/plugins/thermalutil.py b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/thermalutil.py new file mode 120000 index 000000000000..cef21ffacccc --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/plugins/thermalutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/thermalutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn2100-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-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_msn2100-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn2100-r0/sensors.conf new file mode 100644 index 000000000000..e37dd25f03db --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/sensors.conf @@ -0,0 +1,51 @@ +################################################################################ +# Copyright (c) 2020 Mellanox Technologies +# +# Platform specific sensors config for SN2100 +################################################################################ + +# 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 "lm75-i2c-*-4a" + label temp1 "Ambient Port Side Temp (air exhaust)" + chip "lm75-i2c-*-4b" + label temp1 "Ambient Fan Side Temp (air intake)" + +# Power controllers +bus "i2c-5" "i2c-1-mux (chan_id 4)" + chip "pmbus-i2c-*-41" + label in1 "PMB-1 12V Rail (in)" + label in2 "PMB-1 0.9V Rail (out)" + label in3 "PMB-1 1.8V Rail (out)" + label temp1 "PMB-1 Temp 1" + label temp2 "PMB-1 Temp 2" + ignore power1 + label power2 "PMB-1 0.9V Rail Pwr (out)" + label power3 "PMB-1 1.8V Rail Pwr (out)" + ignore curr1 + label curr2 "PMB-1 0.9V Rail Curr (out)" + label curr3 "PMB-1 1.8V Rail Curr (out)" + chip "pmbus-i2c-*-27" + label in1 "PMB-2 12V Rail (in)" + label in2 "PMB-2 3.3V Rail (out)" + label in3 "PMB-2 1.2V Rail (out)" + label temp1 "PMB-2 Temp 1" + label temp2 "PMB-2 Temp 2" + ignore power1 + label power2 "PMB-2 3.3V Rail Pwr (out)" + label power3 "PMB-2 1.2V Rail Pwr (out)" + ignore curr1 + label curr2 "PMB-2 3.3V Rail Curr (out)" + label curr3 "PMB-2 1.2V Rail Curr (out)" + +# Chassis fans +bus "i2c-2" "i2c-1-mux (chan_id 1)" + chip "mlxsw-i2c-*-48" + label fan1 "Chassis Fan 1" + label fan2 "Chassis Fan 2" + label fan3 "Chassis Fan 3" + label fan4 "Chassis Fan 4" diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn2100-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..265e22a00257 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2010-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2100-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/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_msn2410-r0/ACS-MSN2410/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..7bcae62336f6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..a437d613434d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/hwsku.json b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/hwsku.json new file mode 100644 index 000000000000..abb5b2393ba5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/hwsku.json @@ -0,0 +1,172 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet132": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet136": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet140": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet148": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet152": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet156": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet160": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet164": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet168": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet172": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet176": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet180": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet184": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet188": { + "default_brkout_mode": "1x25G[10G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet196": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet204": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet208": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet212": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet216": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet220": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/pg_profile_lookup.ini new file mode 120000 index 000000000000..3c97f3dcb16f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/port_config.ini b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/port_config.ini new file mode 100644 index 000000000000..782949e5706a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/port_config.ini @@ -0,0 +1,57 @@ +# name lanes index +Ethernet0 0 1 +Ethernet4 4 2 +Ethernet8 8 3 +Ethernet12 12 4 +Ethernet16 16 5 +Ethernet20 20 6 +Ethernet24 24 7 +Ethernet28 28 8 +Ethernet32 32 9 +Ethernet36 36 10 +Ethernet40 40 11 +Ethernet44 44 12 +Ethernet48 48 13 +Ethernet52 52 14 +Ethernet56 56 15 +Ethernet60 60 16 +Ethernet64 64 17 +Ethernet68 68 18 +Ethernet72 72 19 +Ethernet76 76 20 +Ethernet80 80 21 +Ethernet84 84 22 +Ethernet88 88 23 +Ethernet92 92 24 +Ethernet96 96 25 +Ethernet100 100 26 +Ethernet104 104 27 +Ethernet108 108 28 +Ethernet112 112 29 +Ethernet116 116 30 +Ethernet120 120 31 +Ethernet124 124 32 +Ethernet128 128 33 +Ethernet132 132 34 +Ethernet136 136 35 +Ethernet140 140 36 +Ethernet144 144 37 +Ethernet148 148 38 +Ethernet152 152 39 +Ethernet156 156 40 +Ethernet160 160 41 +Ethernet164 164 42 +Ethernet168 168 43 +Ethernet172 172 44 +Ethernet176 176 45 +Ethernet180 180 46 +Ethernet184 184 47 +Ethernet188 188 48 +Ethernet192 192,193,194,195 49 +Ethernet196 196,197,198,199 50 +Ethernet200 200,201,202,203 51 +Ethernet204 204,205,206,207 52 +Ethernet208 208,209,210,211 53 +Ethernet212 212,213,214,215 54 +Ethernet216 216,217,218,219 55 +Ethernet220 220,221,222,223 56 diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai.profile b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai.profile new file mode 100644 index 000000000000..f7cb264c2287 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2410.xml diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai_2410.xml b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai_2410.xml new file mode 100644 index 000000000000..4884cd754a30 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/sai_2410.xml @@ -0,0 +1,414 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 56 + + + + + 1 + 32 + 1 + + + 0 + + + 939524096 + + + 2 + 33 + 1 + 0 + 939524096 + + + 3 + 34 + 1 + 0 + 939524096 + + + 4 + 35 + 1 + 0 + 939524096 + + + 5 + 36 + 1 + 0 + 939524096 + + + 6 + 37 + 1 + 0 + 939524096 + + + 7 + 38 + 1 + 0 + 939524096 + + + 8 + 39 + 1 + 0 + 939524096 + + + 9 + 40 + 1 + 0 + 939524096 + + + 10 + 41 + 1 + 0 + 939524096 + + + 11 + 42 + 1 + 0 + 939524096 + + + 12 + 43 + 1 + 0 + 939524096 + + + 13 + 44 + 1 + 0 + 939524096 + + + 14 + 45 + 1 + 0 + 939524096 + + + 15 + 46 + 1 + 0 + 939524096 + + + 16 + 47 + 1 + 0 + 939524096 + + + 17 + 48 + 4 + 3 + 11534336 + + + 19 + 49 + 4 + 1 + 11534336 + + + 21 + 50 + 4 + 3 + 11534336 + + + 23 + 51 + 4 + 1 + 11534336 + + + 25 + 52 + 4 + 3 + 11534336 + + + 27 + 53 + 4 + 1 + 11534336 + + + 29 + 54 + 4 + 3 + 11534336 + + + 31 + 55 + 4 + 1 + 11534336 + + + 33 + 28 + 1 + 0 + 939524096 + + + 34 + 29 + 1 + 0 + 939524096 + + + 35 + 30 + 1 + 0 + 939524096 + + + 36 + 31 + 1 + 0 + 939524096 + + + 37 + 24 + 1 + 0 + 939524096 + + + 38 + 25 + 1 + 0 + 939524096 + + + 39 + 26 + 1 + 0 + 939524096 + + + 40 + 27 + 1 + 0 + 939524096 + + + 41 + 20 + 1 + 0 + 939524096 + + + 42 + 21 + 1 + 0 + 939524096 + + + 43 + 22 + 1 + 0 + 939524096 + + + 44 + 23 + 1 + 0 + 939524096 + + + 45 + 16 + 1 + 0 + 939524096 + + + 46 + 17 + 1 + 0 + 939524096 + + + 47 + 18 + 1 + 0 + 939524096 + + + 48 + 19 + 1 + 0 + 939524096 + + + 49 + 12 + 1 + 0 + 939524096 + + + 50 + 13 + 1 + 0 + 939524096 + + + 51 + 14 + 1 + 0 + 939524096 + + + 52 + 15 + 1 + 0 + 939524096 + + + 53 + 8 + 1 + 0 + 939524096 + + + 54 + 9 + 1 + 0 + 939524096 + + + 55 + 10 + 1 + 0 + 939524096 + + + 56 + 11 + 1 + 0 + 939524096 + + + 57 + 4 + 1 + 0 + 939524096 + + + 58 + 5 + 1 + 0 + 939524096 + + + 59 + 6 + 1 + 0 + 939524096 + + + 60 + 7 + 1 + 0 + 939524096 + + + 61 + 0 + 1 + 0 + 939524096 + + + 62 + 1 + 1 + 0 + 939524096 + + + 63 + 2 + 1 + 0 + 939524096 + + + 64 + 3 + 1 + 0 + 939524096 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2410-r0/default_sku new file mode 100644 index 000000000000..ac04d6adf5f5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN2410 t1 diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2410-r0/installer.conf new file mode 120000 index 000000000000..955db12ff425 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/installer.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/installer.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn2410-r0/pcie.yaml new file mode 120000 index 000000000000..f739a7e8ec35 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/pcie.yaml @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/pcie.yaml \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/platform.json b/device/mellanox/x86_64-mlnx_msn2410-r0/platform.json new file mode 100644 index 000000000000..5624ef60d49a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/platform.json @@ -0,0 +1,404 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1", + "lanes": "0", + "breakout_modes": { + "1x25G[10G]" : ["etp1"] + } + }, + "Ethernet4": { + "index": "2", + "lanes": "4", + "breakout_modes": { + "1x25G[10G]" : ["etp2"] + } + }, + "Ethernet8": { + "index": "3", + "lanes": "8", + "breakout_modes": { + "1x25G[10G]" : ["etp3"] + } + }, + "Ethernet12": { + "index": "4", + "lanes": "12", + "breakout_modes": { + "1x25G[10G]" : ["etp4"] + } + }, + "Ethernet16": { + "index": "5", + "lanes": "16", + "breakout_modes": { + "1x25G[10G]" : ["etp5"] + } + }, + "Ethernet20": { + "index": "6", + "lanes": "20", + "breakout_modes": { + "1x25G[10G]" : ["etp6"] + } + }, + "Ethernet24": { + "index": "7", + "lanes": "24", + "breakout_modes": { + "1x25G[10G]" : ["etp7"] + } + }, + "Ethernet28": { + "index": "8", + "lanes": "28", + "breakout_modes": { + "1x25G[10G]" : ["etp8"] + } + }, + "Ethernet32": { + "index": "9", + "lanes": "32", + "breakout_modes": { + "1x25G[10G]" : ["etp9"] + } + }, + "Ethernet36": { + "index": "10", + "lanes": "36", + "breakout_modes": { + "1x25G[10G]" : ["etp10"] + } + }, + "Ethernet40": { + "index": "11", + "lanes": "40", + "breakout_modes": { + "1x25G[10G]" : ["etp11"] + } + }, + "Ethernet44": { + "index": "12", + "lanes": "44", + "breakout_modes": { + "1x25G[10G]" : ["etp12"] + } + }, + "Ethernet48": { + "index": "13", + "lanes": "48", + "breakout_modes": { + "1x25G[10G]" : ["etp13"] + } + }, + "Ethernet52": { + "index": "14", + "lanes": "52", + "breakout_modes": { + "1x25G[10G]" : ["etp14"] + } + }, + "Ethernet56": { + "index": "15", + "lanes": "56", + "breakout_modes": { + "1x25G[10G]" : ["etp15"] + } + }, + "Ethernet60": { + "index": "16", + "lanes": "60", + "breakout_modes": { + "1x25G[10G]" : ["etp16"] + } + }, + "Ethernet64": { + "index": "17", + "lanes": "64", + "breakout_modes": { + "1x25G[10G]" : ["etp17"] + } + }, + "Ethernet68": { + "index": "18", + "lanes": "68", + "breakout_modes": { + "1x25G[10G]" : ["etp18"] + } + }, + "Ethernet72": { + "index": "19", + "lanes": "72", + "breakout_modes": { + "1x25G[10G]" : ["etp19"] + } + }, + "Ethernet76": { + "index": "20", + "lanes": "76", + "breakout_modes": { + "1x25G[10G]" : ["etp20"] + } + }, + "Ethernet80": { + "index": "21", + "lanes": "80", + "breakout_modes": { + "1x25G[10G]" : ["etp21"] + } + }, + "Ethernet84": { + "index": "22", + "lanes": "84", + "breakout_modes": { + "1x25G[10G]" : ["etp22"] + } + }, + "Ethernet88": { + "index": "23", + "lanes": "88", + "breakout_modes": { + "1x25G[10G]" : ["etp23"] + } + }, + "Ethernet92": { + "index": "24", + "lanes": "92", + "breakout_modes": { + "1x25G[10G]" : ["etp24"] + } + }, + "Ethernet96": { + "index": "25", + "lanes": "96", + "breakout_modes": { + "1x25G[10G]" : ["etp25"] + } + }, + "Ethernet100": { + "index": "26", + "lanes": "100", + "breakout_modes": { + "1x25G[10G]" : ["etp26"] + } + }, + "Ethernet104": { + "index": "27", + "lanes": "104", + "breakout_modes": { + "1x25G[10G]" : ["etp27"] + } + }, + "Ethernet108": { + "index": "28", + "lanes": "108", + "breakout_modes": { + "1x25G[10G]" : ["etp28"] + } + }, + "Ethernet112": { + "index": "29", + "lanes": "112", + "breakout_modes": { + "1x25G[10G]" : ["etp29"] + } + }, + "Ethernet116": { + "index": "30", + "lanes": "116", + "breakout_modes": { + "1x25G[10G]" : ["etp30"] + } + }, + "Ethernet120": { + "index": "31", + "lanes": "120", + "breakout_modes": { + "1x25G[10G]" : ["etp31"] + } + }, + "Ethernet124": { + "index": "32", + "lanes": "124", + "breakout_modes": { + "1x25G[10G]" : ["etp32"] + } + }, + "Ethernet128": { + "index": "33", + "lanes": "128", + "breakout_modes": { + "1x25G[10G]" : ["etp33"] + } + }, + "Ethernet132": { + "index": "34", + "lanes": "132", + "breakout_modes": { + "1x25G[10G]" : ["etp34"] + } + }, + "Ethernet136": { + "index": "35", + "lanes": "136", + "breakout_modes": { + "1x25G[10G]" : ["etp35"] + } + }, + "Ethernet140": { + "index": "36", + "lanes": "140", + "breakout_modes": { + "1x25G[10G]" : ["etp36"] + } + }, + "Ethernet144": { + "index": "37", + "lanes": "144", + "breakout_modes": { + "1x25G[10G]" : ["etp37"] + } + }, + "Ethernet148": { + "index": "38", + "lanes": "148", + "breakout_modes": { + "1x25G[10G]" : ["etp38"] + } + }, + "Ethernet152": { + "index": "39", + "lanes": "152", + "breakout_modes": { + "1x25G[10G]" : ["etp39"] + } + }, + "Ethernet156": { + "index": "40", + "lanes": "156", + "breakout_modes": { + "1x25G[10G]" : ["etp40"] + } + }, + "Ethernet160": { + "index": "41", + "lanes": "160", + "breakout_modes": { + "1x25G[10G]" : ["etp41"] + } + }, + "Ethernet164": { + "index": "42", + "lanes": "164", + "breakout_modes": { + "1x25G[10G]" : ["etp42"] + } + }, + "Ethernet168": { + "index": "43", + "lanes": "168", + "breakout_modes": { + "1x25G[10G]" : ["etp43"] + } + }, + "Ethernet172": { + "index": "44", + "lanes": "172", + "breakout_modes": { + "1x25G[10G]" : ["etp44"] + } + }, + "Ethernet176": { + "index": "45", + "lanes": "176", + "breakout_modes": { + "1x25G[10G]" : ["etp45"] + } + }, + "Ethernet180": { + "index": "46", + "lanes": "180", + "breakout_modes": { + "1x25G[10G]" : ["etp46"] + } + }, + "Ethernet184": { + "index": "47", + "lanes": "184", + "breakout_modes": { + "1x25G[10G]" : ["etp47"] + } + }, + "Ethernet188": { + "index": "48", + "lanes": "188", + "breakout_modes": { + "1x25G[10G]" : ["etp48"] + } + }, + "Ethernet192": { + "index": "49,49,49,49", + "lanes": "192,193,194,195", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp49"], + "2x50G[40G,25G,10G]": ["etp49a", "etp49b"] + } + }, + "Ethernet196": { + "index": "50,50,50,50", + "lanes": "196,197,198,199", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp50"], + "2x50G[40G,25G,10G]": ["etp50a", "etp50b"] + } + }, + "Ethernet200": { + "index": "51,51,51,51", + "lanes": "200,201,202,203", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp51"], + "2x50G[40G,25G,10G]": ["etp51a", "etp51b"] + } + }, + "Ethernet204": { + "index": "52,52,52,52", + "lanes": "204,205,206,207", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp52"], + "2x50G[40G,25G,10G]": ["etp52a", "etp52b"] + } + }, + "Ethernet208": { + "index": "53,53,53,53", + "lanes": "208,209,210,211", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp53"], + "2x50G[40G,25G,10G]": ["etp53a", "etp53b"] + } + }, + "Ethernet212": { + "index": "54,54,54,54", + "lanes": "212,213,214,215", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp54"], + "2x50G[40G,25G,10G]": ["etp54a", "etp54b"] + } + }, + "Ethernet216": { + "index": "55,55,55,55", + "lanes": "216,217,218,219", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp55"], + "2x50G[40G,25G,10G]": ["etp55a", "etp55b"] + } + }, + "Ethernet220": { + "index": "56,56,56,56", + "lanes": "220,221,222,223", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp56"], + "2x50G[40G,25G,10G]": ["etp56a", "etp56b"] + } + } + } +} 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..52c09f4ea998 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/platform_components.json @@ -0,0 +1,14 @@ +{ + "chassis": { + "MSN2410": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2410-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-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_msn2410-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn2410-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-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_msn2410-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-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_msn2410-r0/plugins/fanutil.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/fanutil.py new file mode 120000 index 000000000000..82ea06ef915f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/fanutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/fanutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/psuutil.py new file mode 120000 index 000000000000..9f724238a8d5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-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_msn2410-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-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_msn2410-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-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_msn2410-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-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_msn2410-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-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_msn2410-r0/plugins/thermalutil.py b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/thermalutil.py new file mode 120000 index 000000000000..cef21ffacccc --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/plugins/thermalutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/thermalutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn2410-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-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_msn2410-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn2410-r0/sensors.conf new file mode 100644 index 000000000000..ede1fbe3c768 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/sensors.conf @@ -0,0 +1,81 @@ +################################################################################ +# Copyright (c) 2020 Mellanox Technologies +# +# Platform specific sensors config for SN2410 +################################################################################ + +# 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 7)" + chip "lm75-i2c-7-4a" + label temp1 "Ambient Port Temp" + +bus "i2c-17" "i2c-1-mux (chan_id 17)" + chip "lm75-i2c-17-49" + label temp1 "Ambient Fan Temp" + +chip "acpitz-virtual-0" + label temp1 "ACPI CPU Temp" + label temp2 "ACPI Board Temp" + +# Power controllers +bus "i2c-5" "i2c-1-mux (chan_id 5)" + chip "pmbus-i2c-*-41" + label in1 "PMB-1 PSU 12V Rail (in)" + label in2 "PMB-1 0.9V VCORE Rail (out)" + label temp1 "PMB-1 Temp 1" + label temp2 "PMB-1 Temp 2" + ignore power1 + label power2 "PMB-1 0.9V VCORE Rail Pwr (out)" + ignore curr1 + label curr2 "PMB-1 0.9V VCORE Rail Curr (out)" + chip "pmbus-i2c-*-27" + label in1 "PMB-2 PSU 12V Rail (in)" + label in2 "PMB-2 3.3V Rail (out)" + label in3 "PMB-2 1.2V Rail (out)" + label temp1 "PMB-2 Temp 1" + label temp2 "PMB-2 Temp 2" + ignore power1 + label power2 "PMB-2 3.3V Rail Pwr (out)" + label power3 "PMB-2 1.2V Rail Pwr (out)" + ignore curr1 + label curr2 "PMB-2 3.3V Rail Curr (out)" + label curr3 "PMB-2 1.2V Rail Curr (out)" + +# Power supplies +bus "i2c-10" "i2c-1-mux (chan_id 10)" + chip "dps460-i2c-*-58" + label in1 "PSU-2(R) 220V Rail (in)" + label in2 "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 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)" + chip "dps460-i2c-*-59" + label in1 "PSU-1(L) 220V Rail (in)" + label in2 "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 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)" + +# Chassis fans +bus "i2c-2" "i2c-1-mux (chan_id 1)" + chip "mlxsw-i2c-*-48" + label fan1 "Chassis Drawer-1 Fan-1" + label fan2 "Chassis Drawer-1 Fan-2" + label fan3 "Chassis Drawer-2 Fan-1" + label fan4 "Chassis Drawer-2 Fan-2" + label fan5 "Chassis Drawer-3 Fan-1" + label fan6 "Chassis Drawer-3 Fan-2" + label fan7 "Chassis Drawer-4 Fan-1" + label fan8 "Chassis Drawer-4 Fan-2" diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn2410-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..98df66c27ca5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2410-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} 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 new file mode 100644 index 000000000000..d0bce94ba51d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 @@ -0,0 +1,112 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '4580864' %} +{% set ingress_lossy_pool_size = '4580864' %} +{% set egress_lossless_pool_size = '13945824' %} +{% set egress_lossy_pool_size = '4580864' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossy_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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":"9216", + "dynamic_th":"7" + }, + "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_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..5514c47a4090 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 @@ -0,0 +1,112 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '3302912' %} +{% set ingress_lossy_pool_size = '3302912' %} +{% set egress_lossless_pool_size = '13945824' %} +{% set egress_lossy_pool_size = '3302912' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossy_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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":"9216", + "dynamic_th":"7" + }, + "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_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 new file mode 100644 index 000000000000..5954cc77c114 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 @@ -0,0 +1,3 @@ +{%- set default_topo = 't0' %} +{%- set dynamic_mode = 'true' %} +{%- include 'buffers_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/hwsku.json b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/hwsku.json new file mode 100644 index 000000000000..3edbff817895 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini new file mode 100644 index 000000000000..7abb2a058d1b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 49152 19456 29696 0 + 25000 5m 49152 19456 29696 0 + 40000 5m 49152 19456 29696 0 + 50000 5m 49152 19456 29696 0 + 100000 5m 50176 19456 30720 0 + 10000 40m 49152 19456 29696 0 + 25000 40m 51200 19456 31744 0 + 40000 40m 52224 19456 32768 0 + 50000 40m 53248 19456 33792 0 + 100000 40m 58368 19456 38912 0 + 10000 300m 56320 19456 36864 0 + 25000 300m 67584 19456 48128 0 + 40000 300m 78848 19456 59392 0 + 50000 300m 86016 19456 66560 0 + 100000 300m 123904 19456 104448 0 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini new file mode 100644 index 000000000000..c1e59909c0fb --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 0,1,2,3 etp1 1 +Ethernet4 4,5,6,7 etp2 2 +Ethernet8 8,9,10,11 etp3 3 +Ethernet12 12,13,14,15 etp4 4 +Ethernet16 16,17,18,19 etp5 5 +Ethernet20 20,21,22,23 etp6 6 +Ethernet24 24,25,26,27 etp7 7 +Ethernet28 28,29,30,31 etp8 8 +Ethernet32 32,33,34,35 etp9 9 +Ethernet36 36,37,38,39 etp10 10 +Ethernet40 40,41,42,43 etp11 11 +Ethernet44 44,45,46,47 etp12 12 +Ethernet48 48,49,50,51 etp13 13 +Ethernet52 52,53,54,55 etp14 14 +Ethernet56 56,57,58,59 etp15 15 +Ethernet60 60,61,62,63 etp16 16 +Ethernet64 64,65,66,67 etp17 17 +Ethernet68 68,69,70,71 etp18 18 +Ethernet72 72,73,74,75 etp19 19 +Ethernet76 76,77,78,79 etp20 20 +Ethernet80 80,81,82,83 etp21 21 +Ethernet84 84,85,86,87 etp22 22 +Ethernet88 88,89,90,91 etp23 23 +Ethernet92 92,93,94,95 etp24 24 +Ethernet96 96,97,98,99 etp25 25 +Ethernet100 100,101,102,103 etp26 26 +Ethernet104 104,105,106,107 etp27 27 +Ethernet108 108,109,110,111 etp28 28 +Ethernet112 112,113,114,115 etp29 29 +Ethernet116 116,117,118,119 etp30 30 +Ethernet120 120,121,122,123 etp31 31 +Ethernet124 124,125,126,127 etp32 32 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai.profile b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai.profile new file mode 100644 index 000000000000..696f3d8182f9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2700.xml diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai_2700.xml b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai_2700.xml new file mode 100644 index 000000000000..eedf359fb889 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/sai_2700.xml @@ -0,0 +1,246 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 32 + + + + + 1 + 4 + 16 + + + 3 + + + 98368 + + + 3 + 4 + 17 + 1 + 98368 + + + 5 + 4 + 18 + 3 + 98368 + + + 7 + 4 + 19 + 1 + 98368 + + + 9 + 4 + 20 + 3 + 98368 + + + 11 + 4 + 21 + 1 + 98368 + + + 13 + 4 + 22 + 3 + 98368 + + + 15 + 4 + 23 + 1 + 98368 + + + 17 + 4 + 24 + 3 + 98368 + + + 19 + 4 + 25 + 1 + 98368 + + + 21 + 4 + 26 + 3 + 98368 + + + 23 + 4 + 27 + 1 + 98368 + + + 25 + 4 + 28 + 3 + 98368 + + + 27 + 4 + 29 + 1 + 98368 + + + 29 + 4 + 30 + 3 + 98368 + + + 31 + 4 + 31 + 1 + 98368 + + + 33 + 4 + 14 + 3 + 98368 + + + 35 + 4 + 15 + 1 + 98368 + + + 37 + 4 + 12 + 3 + 98368 + + + 39 + 4 + 13 + 1 + 98368 + + + 41 + 4 + 10 + 3 + 98368 + + + 43 + 4 + 11 + 1 + 98368 + + + 45 + 4 + 8 + 3 + 98368 + + + 47 + 4 + 9 + 1 + 98368 + + + 49 + 4 + 6 + 3 + 98368 + + + 51 + 4 + 7 + 1 + 98368 + + + 53 + 4 + 4 + 3 + 98368 + + + 55 + 4 + 5 + 1 + 98368 + + + 57 + 4 + 2 + 3 + 98368 + + + 59 + 4 + 3 + 1 + 98368 + + + 61 + 4 + 0 + 3 + 98368 + + + 63 + 4 + 1 + 1 + 98368 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers.json.j2 new file mode 120000 index 000000000000..30c4e1d5bfdd --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers.json.j2 @@ -0,0 +1 @@ +../ACS-MSN2700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..a1d24c418b3e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../Mellanox-SN2700-D48C8/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..bef0c9d9531c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../Mellanox-SN2700-D48C8/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/hwsku.json b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/hwsku.json new file mode 100644 index 000000000000..8d3ad0dc0310 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/hwsku.json @@ -0,0 +1,112 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet112": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet114": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet116": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet118": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet120": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet122": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet124": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet126": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/pg_profile_lookup.ini new file mode 120000 index 000000000000..40ad66c7356a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/pg_profile_lookup.ini @@ -0,0 +1 @@ +../Mellanox-SN2700-D48C8/pg_profile_lookup.ini \ No newline at end of file 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 new file mode 100644 index 000000000000..653a61ecc23c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/port_config.ini @@ -0,0 +1,37 @@ +# name lanes alias index speed +Ethernet0 0,1,2,3 etp1 1 100000 +Ethernet4 4,5,6,7 etp2 2 100000 +Ethernet8 8,9,10,11 etp3 3 100000 +Ethernet12 12,13,14,15 etp4 4 100000 +Ethernet16 16,17,18,19 etp5 5 100000 +Ethernet20 20,21,22,23 etp6 6 100000 +Ethernet24 24,25,26,27 etp7 7 100000 +Ethernet28 28,29,30,31 etp8 8 100000 +Ethernet32 32,33,34,35 etp9 9 100000 +Ethernet36 36,37,38,39 etp10 10 100000 +Ethernet40 40,41,42,43 etp11 11 100000 +Ethernet44 44,45,46,47 etp12 12 100000 +Ethernet48 48,49,50,51 etp13 13 100000 +Ethernet52 52,53,54,55 etp14 14 100000 +Ethernet56 56,57,58,59 etp15 15 100000 +Ethernet60 60,61,62,63 etp16 16 100000 +Ethernet64 64,65,66,67 etp17 17 100000 +Ethernet68 68,69,70,71 etp18 18 100000 +Ethernet72 72,73,74,75 etp19 19 100000 +Ethernet76 76,77,78,79 etp20 20 100000 +Ethernet80 80,81,82,83 etp21 21 100000 +Ethernet84 84,85,86,87 etp22 22 100000 +Ethernet88 88,89,90,91 etp23 23 100000 +Ethernet92 92,93,94,95 etp24 24 100000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105,106,107 etp27 27 100000 +Ethernet108 108,109,110,111 etp28 28 100000 +Ethernet112 112,113 etp29a 29 50000 +Ethernet114 114,115 etp29b 29 50000 +Ethernet116 116,117 etp30a 30 50000 +Ethernet118 118,119 etp30b 30 50000 +Ethernet120 120,121 etp31a 31 50000 +Ethernet122 122,123 etp31b 31 50000 +Ethernet124 124,125 etp32a 32 50000 +Ethernet126 126,127 etp32b 32 50000 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/qos.json.j2 new file mode 120000 index 000000000000..8bd2d26567b8 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/qos.json.j2 @@ -0,0 +1 @@ +../ACS-MSN2700/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/sai.profile b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/sai.profile new file mode 100644 index 000000000000..cfeb4a5fa4ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2700_8x50g_28x100g.xml diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/sai_2700_8x50g_28x100g.xml b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/sai_2700_8x50g_28x100g.xml new file mode 100644 index 000000000000..ee20db3e5dde --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/sai_2700_8x50g_28x100g.xml @@ -0,0 +1,250 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 32 + + + + + 1 + 4 + 16 + + + 3 + + + 11534336 + + + 3 + 4 + 17 + 1 + 11534336 + + + 5 + 4 + 18 + 3 + 11534336 + + + 7 + 4 + 19 + 1 + 11534336 + + + 9 + 4 + 20 + 3 + 11534336 + + + 11 + 4 + 21 + 1 + 11534336 + + + 13 + 4 + 22 + 3 + 11534336 + + + 15 + 4 + 23 + 1 + 11534336 + + + 17 + 4 + 24 + 3 + 11534336 + + + 19 + 4 + 25 + 1 + 11534336 + + + 21 + 4 + 26 + 3 + 11534336 + + + 23 + 4 + 27 + 1 + 11534336 + + + 25 + 4 + 28 + 3 + 3221225472 + 2 + + + 27 + 4 + 29 + 1 + 3221225472 + 2 + + + 29 + 4 + 30 + 3 + 3221225472 + 2 + + + 31 + 4 + 31 + 1 + 3221225472 + 2 + + + 33 + 4 + 14 + 3 + 11534336 + + + 35 + 4 + 15 + 1 + 11534336 + + + 37 + 4 + 12 + 3 + 11534336 + + + 39 + 4 + 13 + 1 + 11534336 + + + 41 + 4 + 10 + 3 + 11534336 + + + 43 + 4 + 11 + 1 + 11534336 + + + 45 + 4 + 8 + 3 + 11534336 + + + 47 + 4 + 9 + 1 + 11534336 + + + 49 + 4 + 6 + 3 + 11534336 + + + 51 + 4 + 7 + 1 + 11534336 + + + 53 + 4 + 4 + 3 + 11534336 + + + 55 + 4 + 5 + 1 + 11534336 + + + 57 + 4 + 2 + 3 + 11534336 + + + 59 + 4 + 3 + 1 + 11534336 + + + 61 + 4 + 0 + 3 + 11534336 + + + 63 + 4 + 1 + 1 + 11534336 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/buffers.json.j2 new file mode 120000 index 000000000000..30c4e1d5bfdd --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/buffers.json.j2 @@ -0,0 +1 @@ +../ACS-MSN2700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..c2bdb607d5a7 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/buffers_defaults_t0.j2 @@ -0,0 +1,102 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '7719936' %} +{% set ingress_lossless_pool_xoff = '1032192' %} +{% set egress_lossless_pool_size = '13945824' %} +{% set egress_lossy_pool_size = '7719936' %} + +{%- 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 }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + "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":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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_msn2700-r0/Mellanox-SN2700-D40C8S8/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..6f444b61df43 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/buffers_defaults_t1.j2 @@ -0,0 +1,102 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '9686016' %} +{% set ingress_lossless_pool_xoff = '1179648' %} +{% set egress_lossless_pool_size = '13945824' %} +{% set egress_lossy_pool_size = '9686016' %} + +{%- 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 }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + "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":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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_msn2700-r0/Mellanox-SN2700-D40C8S8/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/pg_profile_lookup.ini new file mode 100644 index 000000000000..cdd674e4e715 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 19456 19456 22528 0 + 25000 5m 19456 19456 22528 0 + 40000 5m 19456 19456 22528 0 + 50000 5m 19456 19456 22528 0 + 100000 5m 19456 19456 23552 0 + 10000 40m 19456 19456 22528 0 + 25000 40m 19456 19456 24576 0 + 40000 40m 19456 19456 25600 0 + 50000 40m 19456 19456 25600 0 + 100000 40m 19456 19456 29696 0 + 10000 300m 19456 19456 27648 0 + 25000 300m 19456 19456 36864 0 + 40000 300m 19456 19456 45056 0 + 50000 300m 19456 19456 50176 0 + 100000 300m 19456 19456 78848 0 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/port_config.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/port_config.ini new file mode 100644 index 000000000000..b4072ceb32a1 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 0 etp1a 1 10000 +Ethernet1 1 etp1b 1 10000 +Ethernet2 2 etp1c 1 10000 +Ethernet3 3 etp1d 1 10000 +Ethernet8 8 etp3a 3 10000 +Ethernet9 9 etp3b 3 10000 +Ethernet10 10 etp3c 3 10000 +Ethernet11 11 etp3d 3 10000 +Ethernet16 16,17 etp5a 5 50000 +Ethernet18 18,19 etp5b 5 50000 +Ethernet20 20,21 etp6a 6 50000 +Ethernet22 22,23 etp6b 6 50000 +Ethernet24 24,25,26,27 etp7 7 100000 +Ethernet28 28,29,30,31 etp8 8 100000 +Ethernet32 32,33,34,35 etp9 9 100000 +Ethernet36 36,37,38,39 etp10 10 100000 +Ethernet40 40,41 etp11a 11 50000 +Ethernet42 42,43 etp11b 11 50000 +Ethernet44 44,45 etp12a 12 50000 +Ethernet46 46,47 etp12b 12 50000 +Ethernet48 48,49 etp13a 13 50000 +Ethernet50 50,51 etp13b 13 50000 +Ethernet52 52,53 etp14a 14 50000 +Ethernet54 54,55 etp14b 14 50000 +Ethernet56 56,57 etp15a 15 50000 +Ethernet58 58,59 etp15b 15 50000 +Ethernet60 60,61 etp16a 16 50000 +Ethernet62 62,63 etp16b 16 50000 +Ethernet64 64,65 etp17a 17 50000 +Ethernet66 66,67 etp17b 17 50000 +Ethernet68 68,69 etp18a 18 50000 +Ethernet70 70,71 etp18b 18 50000 +Ethernet72 72,73 etp19a 19 50000 +Ethernet74 74,75 etp19b 19 50000 +Ethernet76 76,77 etp20a 20 50000 +Ethernet78 78,79 etp20b 20 50000 +Ethernet80 80,81 etp21a 21 50000 +Ethernet82 82,83 etp21b 21 50000 +Ethernet84 84,85 etp22a 22 50000 +Ethernet86 86,87 etp22b 22 50000 +Ethernet88 88,89,90,91 etp23 23 100000 +Ethernet92 92,93,94,95 etp24 24 100000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105 etp27a 27 50000 +Ethernet106 106,107 etp27b 27 50000 +Ethernet108 108,109 etp28a 28 50000 +Ethernet110 110,111 etp28b 28 50000 +Ethernet112 112,113 etp29a 29 50000 +Ethernet114 114,115 etp29b 29 50000 +Ethernet116 116,117 etp30a 30 50000 +Ethernet118 118,119 etp30b 30 50000 +Ethernet120 120,121 etp31a 31 50000 +Ethernet122 122,123 etp31b 31 50000 +Ethernet124 124,125 etp32a 32 50000 +Ethernet126 126,127 etp32b 32 50000 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/sai.profile b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/sai.profile new file mode 100644 index 000000000000..a98e620cfa10 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2700_8x100g_40x50g_8x10g.xml diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/sai_2700_8x100g_40x50g_8x10g.xml b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/sai_2700_8x100g_40x50g_8x10g.xml new file mode 100644 index 000000000000..0376eb548d26 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D40C8S8/sai_2700_8x100g_40x50g_8x10g.xml @@ -0,0 +1,269 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 32 + + + + + 1 + 2 + 4 + 16 + + + 3 + + + 3221225472 + + + 3 + 2 + 4 + 17 + 1 + 3221225472 + + + 5 + 2 + 4 + 18 + 3 + 3221225472 + + + 7 + 2 + 4 + 19 + 1 + 3221225472 + + + 9 + 2 + 4 + 20 + 3 + 3221225472 + + + 11 + 2 + 4 + 21 + 1 + 3221225472 + + + 13 + 4 + 22 + 3 + 11534336 + + + 15 + 4 + 23 + 1 + 11534336 + + + 17 + 4 + 24 + 3 + 11534336 + + + 19 + 4 + 25 + 1 + 11534336 + + + 21 + 2 + 4 + 26 + 3 + 3221225472 + + + 23 + 2 + 4 + 27 + 1 + 3221225472 + + + 25 + 4 + 28 + 3 + 3221225472 + 2 + + + 27 + 2 + 4 + 29 + 1 + 3221225472 + + + 29 + 2 + 4 + 30 + 3 + 3221225472 + + + 31 + 2 + 4 + 31 + 1 + 3221225472 + + + 33 + 2 + 4 + 14 + 3 + 3221225472 + + + 35 + 2 + 4 + 15 + 1 + 3221225472 + + + 37 + 2 + 4 + 12 + 3 + 3221225472 + + + 39 + 2 + 4 + 13 + 1 + 3221225472 + + + 41 + 2 + 4 + 10 + 3 + 3221225472 + + + 43 + 2 + 4 + 11 + 1 + 3221225472 + + + 45 + 4 + 8 + 3 + 11534336 + + + 47 + 4 + 9 + 1 + 11534336 + + + 49 + 2 + 4 + 6 + 3 + 3221225472 + + + 51 + 4 + 7 + 1 + 11534336 + + + 53 + 2 + 4 + 4 + 3 + 3221225472 + + + 55 + 2 + 4 + 5 + 1 + 3221225472 + + + 57 + 4 + 4 + 2 + 3 + 4096 + + + 59 + 4 + 3 + 1 + 11534336 + + + 61 + 4 + 4 + 0 + 3 + 4096 + + + 63 + 4 + 1 + 1 + 11534336 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers.json.j2 new file mode 120000 index 000000000000..30c4e1d5bfdd --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers.json.j2 @@ -0,0 +1 @@ +../ACS-MSN2700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..6fc5efcf9b88 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t0.j2 @@ -0,0 +1,106 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '7719936' %} +{% set ingress_lossless_pool_xoff = '1032192' %} +{% set egress_lossless_pool_size = '13945824' %} +{% set egress_lossy_pool_size = '7719936' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..95d35539253e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_defaults_t1.j2 @@ -0,0 +1,106 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '9686016' %} +{% set ingress_lossless_pool_xoff = '1179648' %} +{% set egress_lossless_pool_size = '13945824' %} +{% set egress_lossy_pool_size = '9686016' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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_msn2700-r0/Mellanox-SN2700-D48C8/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/hwsku.json b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/hwsku.json new file mode 100644 index 000000000000..0e846d9b3874 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/hwsku.json @@ -0,0 +1,172 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet2": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet4": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet6": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet8": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet10": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet12": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet14": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet16": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet18": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet20": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet22": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet40": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet42": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet44": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet46": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet48": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet50": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet52": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet54": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet56": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet58": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet60": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet62": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet64": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet66": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet68": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet70": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet72": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet74": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet76": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet78": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet80": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet82": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet84": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet86": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet104": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet106": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet108": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet110": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet112": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet114": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet116": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet118": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet120": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet122": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet124": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet126": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/pg_profile_lookup.ini new file mode 100644 index 000000000000..cdd674e4e715 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 19456 19456 22528 0 + 25000 5m 19456 19456 22528 0 + 40000 5m 19456 19456 22528 0 + 50000 5m 19456 19456 22528 0 + 100000 5m 19456 19456 23552 0 + 10000 40m 19456 19456 22528 0 + 25000 40m 19456 19456 24576 0 + 40000 40m 19456 19456 25600 0 + 50000 40m 19456 19456 25600 0 + 100000 40m 19456 19456 29696 0 + 10000 300m 19456 19456 27648 0 + 25000 300m 19456 19456 36864 0 + 40000 300m 19456 19456 45056 0 + 50000 300m 19456 19456 50176 0 + 100000 300m 19456 19456 78848 0 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 new file mode 100644 index 000000000000..830f558fb383 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 0,1 etp1a 1 50000 +Ethernet2 2,3 etp1b 1 50000 +Ethernet4 4,5 etp2a 2 50000 +Ethernet6 6,7 etp2b 2 50000 +Ethernet8 8,9 etp3a 3 50000 +Ethernet10 10,11 etp3b 3 50000 +Ethernet12 12,13 etp4a 4 50000 +Ethernet14 14,15 etp4b 4 50000 +Ethernet16 16,17 etp5a 5 50000 +Ethernet18 18,19 etp5b 5 50000 +Ethernet20 20,21 etp6a 6 50000 +Ethernet22 22,23 etp6b 6 50000 +Ethernet24 24,25,26,27 etp7 7 100000 +Ethernet28 28,29,30,31 etp8 8 100000 +Ethernet32 32,33,34,35 etp9 9 100000 +Ethernet36 36,37,38,39 etp10 10 100000 +Ethernet40 40,41 etp11a 11 50000 +Ethernet42 42,43 etp11b 11 50000 +Ethernet44 44,45 etp12a 12 50000 +Ethernet46 46,47 etp12b 12 50000 +Ethernet48 48,49 etp13a 13 50000 +Ethernet50 50,51 etp13b 13 50000 +Ethernet52 52,53 etp14a 14 50000 +Ethernet54 54,55 etp14b 14 50000 +Ethernet56 56,57 etp15a 15 50000 +Ethernet58 58,59 etp15b 15 50000 +Ethernet60 60,61 etp16a 16 50000 +Ethernet62 62,63 etp16b 16 50000 +Ethernet64 64,65 etp17a 17 50000 +Ethernet66 66,67 etp17b 17 50000 +Ethernet68 68,69 etp18a 18 50000 +Ethernet70 70,71 etp18b 18 50000 +Ethernet72 72,73 etp19a 19 50000 +Ethernet74 74,75 etp19b 19 50000 +Ethernet76 76,77 etp20a 20 50000 +Ethernet78 78,79 etp20b 20 50000 +Ethernet80 80,81 etp21a 21 50000 +Ethernet82 82,83 etp21b 21 50000 +Ethernet84 84,85 etp22a 22 50000 +Ethernet86 86,87 etp22b 22 50000 +Ethernet88 88,89,90,91 etp23 23 100000 +Ethernet92 92,93,94,95 etp24 24 100000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105 etp27a 27 50000 +Ethernet106 106,107 etp27b 27 50000 +Ethernet108 108,109 etp28a 28 50000 +Ethernet110 110,111 etp28b 28 50000 +Ethernet112 112,113 etp29a 29 50000 +Ethernet114 114,115 etp29b 29 50000 +Ethernet116 116,117 etp30a 30 50000 +Ethernet118 118,119 etp30b 30 50000 +Ethernet120 120,121 etp31a 31 50000 +Ethernet122 122,123 etp31b 31 50000 +Ethernet124 124,125 etp32a 32 50000 +Ethernet126 126,127 etp32b 32 50000 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai.profile b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai.profile new file mode 100644 index 000000000000..bfbcb1e78f47 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2700_48x50g_8x100g.xml diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai_2700_48x50g_8x100g.xml b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai_2700_48x50g_8x100g.xml new file mode 100644 index 000000000000..dccb606f7435 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/sai_2700_48x50g_8x100g.xml @@ -0,0 +1,270 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 32 + + + + + 1 + 4 + 16 + + + 3 + + + 3221225472 + 2 + + + 3 + 4 + 17 + 1 + 3221225472 + 2 + + + 5 + 4 + 18 + 3 + 3221225472 + 2 + + + 7 + 4 + 19 + 1 + 3221225472 + 2 + + + 9 + 4 + 20 + 3 + 3221225472 + 2 + + + 11 + 4 + 21 + 1 + 3221225472 + 2 + + + 13 + 4 + 22 + 3 + 11534336 + + + 15 + 4 + 23 + 1 + 11534336 + + + 17 + 4 + 24 + 3 + 11534336 + + + 19 + 4 + 25 + 1 + 11534336 + + + 21 + 4 + 26 + 3 + 3221225472 + 2 + + + 23 + 4 + 27 + 1 + 3221225472 + 2> + + + 25 + 4 + 28 + 3 + 3221225472 + 2 + + + 27 + 4 + 29 + 1 + 3221225472 + 2 + + + 29 + 4 + 30 + 3 + 3221225472 + 2 + + + 31 + 4 + 31 + 1 + 3221225472 + 2 + + + 33 + 4 + 14 + 3 + 3221225472 + 2 + + + 35 + 4 + 15 + 1 + 3221225472 + 2 + + + 37 + 4 + 12 + 3 + 3221225472 + 2 + + + 39 + 4 + 13 + 1 + 3221225472 + 2 + + + 41 + 4 + 10 + 3 + 3221225472 + 2 + + + 43 + 4 + 11 + 1 + 3221225472 + 2 + + + 45 + 4 + 8 + 3 + 11534336 + + + 47 + 4 + 9 + 1 + 11534336 + + + 49 + 4 + 6 + 3 + 11534336 + + + 51 + 4 + 7 + 1 + 11534336 + + + 53 + 4 + 4 + 3 + 3221225472 + 2 + + + 55 + 4 + 5 + 1 + 3221225472 + 2 + + + 57 + 4 + 2 + 3 + 3221225472 + 2 + + + 59 + 4 + 3 + 1 + 3221225472 + 2 + + + 61 + 4 + 0 + 3 + 3221225472 + 2 + + + 63 + 4 + 1 + 1 + 3221225472 + 2 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/buffers.json.j2 new file mode 120000 index 000000000000..30c4e1d5bfdd --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/buffers.json.j2 @@ -0,0 +1 @@ +../ACS-MSN2700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..d2bf72b15f7c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/buffers_defaults_t0.j2 @@ -0,0 +1,106 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '10177536' %} +{% set ingress_lossless_pool_xoff = '688128' %} +{% set egress_lossless_pool_size = '13945824' %} +{% set egress_lossy_pool_size = '10177536' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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_msn2700-r0/Mellanox-SN2700/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..c4422556d87a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/buffers_defaults_t1.j2 @@ -0,0 +1,106 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '9292800' %} +{% set ingress_lossless_pool_xoff = '1572864' %} +{% set egress_lossless_pool_size = '13945824' %} +{% set egress_lossy_pool_size = '9292800' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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_msn2700-r0/Mellanox-SN2700/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/hwsku.json b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/hwsku.json new file mode 100644 index 000000000000..3edbff817895 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/pg_profile_lookup.ini new file mode 120000 index 000000000000..40ad66c7356a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/pg_profile_lookup.ini @@ -0,0 +1 @@ +../Mellanox-SN2700-D48C8/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/port_config.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/port_config.ini new file mode 120000 index 000000000000..75904c159253 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/port_config.ini @@ -0,0 +1 @@ +../ACS-MSN2700/port_config.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/qos.json.j2 new file mode 120000 index 000000000000..8bd2d26567b8 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/qos.json.j2 @@ -0,0 +1 @@ +../ACS-MSN2700/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/sai.profile b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/sai.profile new file mode 120000 index 000000000000..5d2c55d8bb44 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/sai.profile @@ -0,0 +1 @@ +../ACS-MSN2700/sai.profile \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/sai_2700.xml b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/sai_2700.xml new file mode 120000 index 000000000000..7f7b65fc6a21 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700/sai_2700.xml @@ -0,0 +1 @@ +../ACS-MSN2700/sai_2700.xml \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2700-r0/default_sku new file mode 100644 index 000000000000..bcce12890af1 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/default_sku @@ -0,0 +1 @@ +Mellanox-SN2700 t1 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2700-r0/installer.conf new file mode 100644 index 000000000000..c9c9493a5404 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax acpi=noirq" diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn2700-r0/pcie.yaml new file mode 100644 index 000000000000..8796390b73c6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/pcie.yaml @@ -0,0 +1,111 @@ +- bus: '00' + dev: '00' + fn: '0' + id: '0154' + name: 'Host bridge: Intel Corporation 3rd Gen Core processor DRAM Controller (rev + 09)' +- bus: '00' + dev: '01' + fn: '0' + id: '0151' + name: 'PCI bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor PCI + Express Root Port (rev 09)' +- bus: '00' + dev: '01' + fn: '1' + id: '0155' + name: 'PCI bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor PCI + Express Root Port (rev 09)' +- bus: '00' + dev: '01' + fn: '2' + id: 0159 + name: 'PCI bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor PCI + Express Root Port (rev 09)' +- bus: '00' + dev: '04' + fn: '0' + id: '0153' + name: 'Signal processing controller: Intel Corporation 3rd Gen Core Processor Thermal + Subsystem (rev 09)' +- bus: '00' + dev: '16' + fn: '0' + id: 1e3a + name: 'Communication controller: Intel Corporation 7 Series/C216 Chipset Family + MEI Controller #1 (rev 04)' +- bus: '00' + dev: '19' + fn: '0' + id: '1502' + name: 'Ethernet controller: Intel Corporation 82579LM Gigabit Network Connection + (rev 04)' +- bus: '00' + dev: 1a + fn: '0' + id: 1e2d + name: 'USB controller: Intel Corporation 7 Series/C216 Chipset Family USB Enhanced + Host Controller #2 (rev 04)' +- bus: '00' + dev: 1c + fn: '0' + id: 1e10 + name: 'PCI bridge: Intel Corporation 7 Series/C216 Chipset Family PCI Express Root + Port 1 (rev c4)' +- bus: '00' + dev: 1c + fn: '4' + id: 1e18 + name: 'PCI bridge: Intel Corporation 7 Series/C210 Series Chipset Family PCI Express + Root Port 5 (rev c4)' +- bus: '00' + dev: 1c + fn: '6' + id: 1e1c + name: 'PCI bridge: Intel Corporation 7 Series/C210 Series Chipset Family PCI Express + Root Port 7 (rev c4)' +- bus: '00' + dev: 1c + fn: '7' + id: 1e1e + name: 'PCI bridge: Intel Corporation 7 Series/C210 Series Chipset Family PCI Express + Root Port 8 (rev c4)' +- bus: '00' + dev: 1d + fn: '0' + id: 1e26 + name: 'USB controller: Intel Corporation 7 Series/C216 Chipset Family USB Enhanced + Host Controller #1 (rev 04)' +- bus: '00' + dev: 1f + fn: '0' + id: 1e55 + name: 'ISA bridge: Intel Corporation QM77 Express Chipset LPC Controller (rev 04)' +- bus: '00' + dev: 1f + fn: '2' + id: 1e03 + name: 'SATA controller: Intel Corporation 7 Series Chipset Family 6-port SATA Controller + [AHCI mode] (rev 04)' +- bus: '00' + dev: 1f + fn: '3' + id: 1e22 + name: 'SMBus: Intel Corporation 7 Series/C216 Chipset Family SMBus Controller (rev + 04)' +- bus: '00' + dev: 1f + fn: '6' + id: 1e24 + name: 'Signal processing controller: Intel Corporation 7 Series/C210 Series Chipset + Family Thermal Management Controller (rev 04)' +- bus: '03' + dev: '00' + fn: '0' + id: cb84 + name: 'Ethernet controller: Mellanox Technologies MT52100' +- bus: '06' + dev: '00' + fn: '0' + id: 150c + name: 'Ethernet controller: Intel Corporation 82583V Gigabit Network Connection' diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/platform.json b/device/mellanox/x86_64-mlnx_msn2700-r0/platform.json new file mode 100644 index 000000000000..e5ec0b2f3ca0 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/platform.json @@ -0,0 +1,636 @@ +{ + "chassis": { + "name": "MSN2700", + "components": [ + { + "name": "ONIE" + }, + { + "name": "SSD" + }, + { + "name": "BIOS" + }, + { + "name": "CPLD1" + }, + { + "name": "CPLD2" + }, + { + "name": "CPLD3" + } + ], + "fans": [], + "fan_drawers": [ + { + "name": "drawer1", + "fans": [ + { + "name": "fan1" + }, + { + "name": "fan2" + } + ] + }, + { + "name": "drawer2", + "fans": [ + { + "name": "fan3" + }, + { + "name": "fan4" + } + ] + }, + { + "name": "drawer3", + "fans": [ + { + "name": "fan5" + }, + { + "name": "fan6" + } + ] + }, + { + "name": "drawer4", + "fans": [ + { + "name": "fan7" + }, + { + "name": "fan8" + } + ] + } + ], + "psus": [ + { + "name": "PSU 1", + "fans": [ + { + "name": "psu_1_fan_1" + } + ], + "thermals": [ + { + "name": "PSU-1 Temp" + } + ] + }, + { + "name": "PSU 2", + "fans": [ + { + "name": "PSU-2 Temp" + } + ], + "thermals": [ + { + "name": "xSFP module 1 Temp" + } + ] + } + ], + "thermals": [ + { + "name": "ASIC" + }, + { + "name": "Ambient Fan Side Temp" + }, + { + "name": "Ambient Port Side Temp" + }, + { + "name": "CPU Core 0 Temp" + }, + { + "name": "CPU Core 1 Temp" + }, + { + "name": "CPU Pack Temp" + } + ], + "sfps": [ + { + "name": "sfp1", + "thermals": [ + { + "name": "xSFP module 1 Temp" + } + ] + }, + { + "name": "sfp2", + "thermals": [ + { + "name": "xSFP module 2 Temp" + } + ] + }, + { + "name": "sfp3", + "thermals": [ + { + "name": "xSFP module 3 Temp" + } + ] + }, + { + "name": "sfp4", + "thermals": [ + { + "name": "xSFP module 4 Temp" + } + ] + }, + { + "name": "sfp5", + "thermals": [ + { + "name": "xSFP module 5 Temp" + } + ] + }, + { + "name": "sfp6", + "thermals": [ + { + "name": "xSFP module 6 Temp" + } + ] + }, + { + "name": "sfp7", + "thermals": [ + { + "name": "xSFP module 7 Temp" + } + ] + }, + { + "name": "sfp8", + "thermals": [ + { + "name": "xSFP module 8 Temp" + } + ] + }, + { + "name": "sfp9", + "thermals": [ + { + "name": "xSFP module 9 Temp" + } + ] + }, + { + "name": "sfp10", + "thermals": [ + { + "name": "xSFP module 10 Temp" + } + ] + }, + { + "name": "sfp11", + "thermals": [ + { + "name": "xSFP module 11 Temp" + } + ] + }, + { + "name": "sfp12", + "thermals": [ + { + "name": "xSFP module 12 Temp" + } + ] + }, + { + "name": "sfp13", + "thermals": [ + { + "name": "xSFP module 13 Temp" + } + ] + }, + { + "name": "sfp14", + "thermals": [ + { + "name": "xSFP module 14 Temp" + } + ] + }, + { + "name": "sfp15", + "thermals": [ + { + "name": "xSFP module 15 Temp" + } + ] + }, + { + "name": "sfp16", + "thermals": [ + { + "name": "xSFP module 16 Temp" + } + ] + }, + { + "name": "sfp17", + "thermals": [ + { + "name": "xSFP module 17 Temp" + } + ] + }, + { + "name": "sfp18", + "thermals": [ + { + "name": "xSFP module 18 Temp" + } + ] + }, + { + "name": "sfp19", + "thermals": [ + { + "name": "xSFP module 19 Temp" + } + ] + }, + { + "name": "sfp20", + "thermals": [ + { + "name": "xSFP module 20 Temp" + } + ] + }, + { + "name": "sfp21", + "thermals": [ + { + "name": "xSFP module 21 Temp" + } + ] + }, + { + "name": "sfp22", + "thermals": [ + { + "name": "xSFP module 22 Temp" + } + ] + }, + { + "name": "sfp23", + "thermals": [ + { + "name": "xSFP module 23 Temp" + } + ] + }, + { + "name": "sfp24", + "thermals": [ + { + "name": "xSFP module 24 Temp" + } + ] + }, + { + "name": "sfp25", + "thermals": [ + { + "name": "xSFP module 25 Temp" + } + ] + }, + { + "name": "sfp26", + "thermals": [ + { + "name": "xSFP module 26 Temp" + } + ] + }, + { + "name": "sfp27", + "thermals": [ + { + "name": "xSFP module 27 Temp" + } + ] + }, + { + "name": "sfp28", + "thermals": [ + { + "name": "xSFP module 28 Temp" + } + ] + }, + { + "name": "sfp29", + "thermals": [ + { + "name": "xSFP module 29 Temp" + } + ] + }, + { + "name": "sfp30", + "thermals": [ + { + "name": "xSFP module 30 Temp" + } + ] + }, + { + "name": "sfp31", + "thermals": [ + { + "name": "xSFP module 31 Temp" + } + ] + }, + { + "name": "sfp32", + "thermals": [ + { + "name": "xSFP module 32 Temp" + } + ] + } + ] + }, + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp1"], + "2x50G[40G,25G,10G]": ["etp1a", "etp1b"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp2"], + "2x50G[40G,25G,10G]": ["etp2a", "etp2b"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp3"], + "2x50G[40G,25G,10G]": ["etp3a", "etp3b"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp4"], + "2x50G[40G,25G,10G]": ["etp4a", "etp4b"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp5"], + "2x50G[40G,25G,10G]": ["etp5a", "etp5b"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp6"], + "2x50G[40G,25G,10G]": ["etp6a", "etp6b"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp7"], + "2x50G[40G,25G,10G]": ["etp7a", "etp7b"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp8"], + "2x50G[40G,25G,10G]": ["etp8a", "etp8b"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp9"], + "2x50G[40G,25G,10G]": ["etp9a", "etp9b"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp10"], + "2x50G[40G,25G,10G]": ["etp10a", "etp10b"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp11"], + "2x50G[40G,25G,10G]": ["etp11a", "etp11b"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp12"], + "2x50G[40G,25G,10G]": ["etp12a", "etp12b"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp13"], + "2x50G[40G,25G,10G]": ["etp13a", "etp13b"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp14"], + "2x50G[40G,25G,10G]": ["etp14a", "etp14b"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp15"], + "2x50G[40G,25G,10G]": ["etp15a", "etp15b"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp16"], + "2x50G[40G,25G,10G]": ["etp16a", "etp16b"] + } + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "64,65,66,67", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp17"], + "2x50G[40G,25G,10G]": ["etp17a", "etp17b"] + } + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "68,69,70,71", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp18"], + "2x50G[40G,25G,10G]": ["etp18a", "etp18b"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp19"], + "2x50G[40G,25G,10G]": ["etp19a", "etp19b"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp20"], + "2x50G[40G,25G,10G]": ["etp20a", "etp20b"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp21"], + "2x50G[40G,25G,10G]": ["etp21a", "etp21b"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp22"], + "2x50G[40G,25G,10G]": ["etp22a", "etp22b"] + } + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "88,89,90,91", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp23"], + "2x50G[40G,25G,10G]": ["etp23a", "etp23b"] + } + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "92,93,94,95", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp24"], + "2x50G[40G,25G,10G]": ["etp24a", "etp24b"] + } + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "96,97,98,99", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp25"], + "2x50G[40G,25G,10G]": ["etp25a", "etp25b"] + } + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "100,101,102,103", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp26"], + "2x50G[40G,25G,10G]": ["etp26a", "etp26b"] + } + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "104,105,106,107", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp27"], + "2x50G[40G,25G,10G]": ["etp27a", "etp27b"] + } + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "108,109,110,111", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp28"], + "2x50G[40G,25G,10G]": ["etp28a", "etp28b"] + } + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "112,113,114,115", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp29"], + "2x50G[40G,25G,10G]": ["etp29a", "etp29b"] + } + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "116,117,118,119", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp30"], + "2x50G[40G,25G,10G]": ["etp30a", "etp30b"] + } + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "120,121,122,123", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp31"], + "2x50G[40G,25G,10G]": ["etp31a", "etp31b"] + } + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "124,125,126,127", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp32"], + "2x50G[40G,25G,10G]": ["etp32a", "etp32b"] + } + } + } +} 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..33a73547cc37 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_components.json @@ -0,0 +1,14 @@ +{ + "chassis": { + "MSN2700": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_reboot new file mode 100755 index 000000000000..28c5aedc4e32 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_reboot @@ -0,0 +1,43 @@ +#!/bin/bash + +declare -r EXIT_SUCCESS="0" +declare -r EXIT_ERROR="1" + +declare -r FW_UPGRADE_SCRIPT="/usr/bin/mlnx-fw-upgrade.sh" +declare -r SYSFS_PWR_CYCLE="/sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/pwr_cycle" + +FORCE_REBOOT="no" + +function ParseArguments() { + while [ $# -ge 1 ]; do + case "$1" in + -f|--force) + FORCE_REBOOT="yes" + ;; + esac + shift + done +} + +function SafePwrCycle() { + sync ; sync + umount -fa > /dev/null 2&>1 + echo 1 > $SYSFS_PWR_CYCLE + sleep 3 + echo 0 > $SYSFS_PWR_CYCLE +} + +ParseArguments "$@" + +${FW_UPGRADE_SCRIPT} --upgrade --verbose +EXIT_CODE="$?" +if [[ "${EXIT_CODE}" != "${EXIT_SUCCESS}" ]]; then + echo "Failed to burn MLNX FW: errno=${EXIT_CODE}" + + if [[ "${FORCE_REBOOT}" != "yes" ]]; then + echo "Reboot is interrupted: use -f|--force to override" + exit "${EXIT_ERROR}" + fi +fi + +SafePwrCycle diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_wait new file mode 100755 index 000000000000..a233eb41de42 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_wait @@ -0,0 +1,69 @@ +#!/bin/bash + +declare -r SYSLOG_LOGGER="/usr/bin/logger" +declare -r SYSLOG_IDENTIFIER="platform_wait" +declare -r SYSLOG_ERROR="error" +declare -r SYSLOG_NOTICE="notice" +declare -r SYSLOG_INFO="info" + +declare -r HW_MGMT_CONFIG="/var/run/hw-management/config" + +declare -r MODULE_COUNTER="${HW_MGMT_CONFIG}/module_counter" +declare -r SFP_COUNTER="${HW_MGMT_CONFIG}/sfp_counter" + +declare -r EXIT_SUCCESS="0" +declare -r EXIT_TIMEOUT="1" + +function log_error() { + eval "${SYSLOG_LOGGER} -t ${SYSLOG_IDENTIFIER} -p ${SYSLOG_ERROR} $@" +} + +function log_notice() { + eval "${SYSLOG_LOGGER} -t ${SYSLOG_IDENTIFIER} -p ${SYSLOG_NOTICE} $@" +} + +function log_info() { + eval "${SYSLOG_LOGGER} -t ${SYSLOG_IDENTIFIER} -p ${SYSLOG_INFO} $@" +} + +function wait_for_sfp() { + local -r _NUM_MATCH="^[0-9]+$" + local -r _NUM_ZERO="0" + + local _MODULE_CNT="0" + local _SFP_CNT="0" + + local -i _WDOG_CNT="1" + local -ir _WDOG_MAX="300" + + local -r _TIMEOUT="1s" + + while [[ "${_WDOG_CNT}" -le "${_WDOG_MAX}" ]]; do + _MODULE_CNT="$(cat ${MODULE_COUNTER} 2>&1)" + _SFP_CNT="$(cat ${SFP_COUNTER} 2>&1)" + + if [[ "${_MODULE_CNT}" =~ ${_NUM_MATCH} && "${_SFP_CNT}" =~ ${_NUM_MATCH} ]]; then + if [[ "${_SFP_CNT}" -gt "${_NUM_ZERO}" && "${_MODULE_CNT}" -eq "${_SFP_CNT}" ]]; then + return "${EXIT_SUCCESS}" + fi + fi + + let "_WDOG_CNT++" + sleep "${_TIMEOUT}" + done + + return "${EXIT_TIMEOUT}" +} + +log_info "Wait for SFP interfaces to be ready" + +wait_for_sfp +EXIT_CODE="$?" +if [[ "${EXIT_CODE}" != "${EXIT_SUCCESS}" ]]; then + log_error "SFP interfaces are not ready: timeout" + exit "${EXIT_CODE}" +fi + +log_info "SFP interfaces are ready" + +exit "${EXIT_SUCCESS}" diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/eeprom.py new file mode 100644 index 000000000000..0f20ffff3b53 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/eeprom.py @@ -0,0 +1,75 @@ +############################################################################# +# Mellanox +# +# 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 binascii + import time + import optparse + import warnings + import os + import sys + import syslog + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo + from sonic_py_common.device_info import get_machine_info + import subprocess +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = "eeprom.py" +EEPROM_SYMLINK = "/var/run/hw-management/eeprom/vpd_info" +CACHE_FILE = "/var/cache/sonic/decode-syseeprom/syseeprom_cache" + + +def log_error(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + 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 + RETRIES = 5 + + def __init__(self, name, path, cpld_root, ro): + for attempt in range(self.RETRIES): + if not os.path.islink(EEPROM_SYMLINK): + 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 if 'simx' not in onie_platform else CACHE_FILE + super(board, self).__init__(self.eeprom_path, 0, '', True) + + def decode_eeprom(self, e): + original_stdout = sys.stdout + sys.stdout = StringIO() + eeprom_tlvinfo.TlvInfoDecoder.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/fanutil.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/fanutil.py new file mode 100644 index 000000000000..ee6446e7c053 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/fanutil.py @@ -0,0 +1,202 @@ +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + + +try: + import os.path + import syslog + import subprocess + from glob import glob + from sonic_fan.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +def log_err(msg): + syslog.openlog("fanutil") + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + +class FanUtil(FanBase): + """Platform-specific FanUtil class""" + + PWM_MAX = 255 + MAX_FAN_PER_DRAWER = 2 + GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" + sku_without_fan_direction = ['ACS-MSN2010', 'ACS-MSN2100', 'ACS-MSN2410', + 'ACS-MSN2700', 'Mellanox-SN2700', 'Mellanox-SN2700-D48C8', 'LS-SN2700', 'ACS-MSN2740'] + sku_with_unpluggable_fan = ['ACS-MSN2010', 'ACS-MSN2100'] + + def __init__(self): + FanBase.__init__(self) + + self.sku_name = self._get_sku_name() + + self.fan_path = "/var/run/hw-management/" + if self.sku_name in self.sku_with_unpluggable_fan: + self.fan_status = None + self.unpluggable_fan = True + else: + self.fan_status = "thermal/fan{}_status" + self.unpluggable_fan = False + self.fan_get_speed = "thermal/fan{}_speed_get" + self.fan_set_speed = "thermal/fan{}_speed_set" + if self.sku_name in self.sku_without_fan_direction: + self.fan_direction = None + else: + self.fan_direction = "system/fan_dir" + + self.fan_led_green = "led/led_fan*_green" + self.num_of_fan, self.num_of_drawer = self._extract_num_of_fans_and_fan_drawers() + + def _get_sku_name(self): + p = subprocess.Popen(self.GET_HWSKU_CMD, shell=True, universal_newlines=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.rstrip('\n') + + def _extract_num_of_fans_and_fan_drawers(self): + # So far we don't have files representing the number of fans and drawers + # The only way to retrieve the number is to count files. + # for number of fans, we get it via couting the speed files. + # for number of draws, we get it via couting the green led files. + list_of_fan_speed = glob(self.fan_path + self.fan_get_speed.format("*")) + num_of_fan = len(list_of_fan_speed) + list_of_fan_leds = glob(self.fan_path + self.fan_led_green) + num_of_drawer = len(list_of_fan_leds) + + return num_of_fan, num_of_drawer + + def _convert_fan_index_to_drawer_index(self, index): + return (index + self.MAX_FAN_PER_DRAWER - 1) / self.MAX_FAN_PER_DRAWER + + def _read_file(self, file_pattern, index=0): + """ + Reads the file of the fan + + :param file_pattern: The filename convention + :param index: An integer, 1-based index of the fan of which to query status + :return: int + """ + return_value = 0 + try: + with open(os.path.join(self.fan_path, file_pattern.format(index)), 'r') as file_to_read: + return_value = int(file_to_read.read()) + except IOError: + log_err("Read file {} failed".format(self.fan_path + file_pattern.format(index))) + return return_value + + return return_value + + def get_num_fans(self): + """ + Retrieves the number of FANs supported on the device + + :return: An integer, the number of FANs supported on the device + """ + return self.num_of_fan + + def get_status(self, index): + """ + Retrieves the operational status of FAN defined + by index 1-based + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, + - True if FAN is running with some speed + - False if FAN has stopped running + """ + if not self.get_presence(index): + return False + + return self.get_speed(index) != 0 + + def get_presence(self, index): + """ + Retrieves the presence status of a FAN defined + by 1-based index + + :param index: An integer, 1-based index of the FAN of which to query status + :return: Boolean, True if FAN is plugged, False if not + """ + if index > self.num_of_fan: + raise RuntimeError( + "index ({}) shouldn't be greater than number of fans ({})".format(index, self.num_of_fan)) + + if self.unpluggable_fan: + return True + + draw_index = self._convert_fan_index_to_drawer_index(index) + presence = self._read_file(self.fan_status, draw_index) + + return presence != 0 + + def get_direction(self, index): + """ + Retrieves the airflow direction of a FAN defined + by 1-based index + + :param index: An integer, 1-based index of the FAN of which to query status + :return: string, denoting FAN airflow direction + Note: + What Mellanox calls forward: + Air flows from fans side to QSFP side, for example: MSN2700-CS2F + which means intake in community + What Mellanox calls reverse: + Air flow from QSFP side to fans side, for example: MSN2700-CS2R + which means exhaust in community + According to hw-mgmt: + 1 stands for forward, in other words intake + 0 stands for reverse, in other words exhaust + """ + if not self.fan_direction: + return self.FAN_DIRECTION_NOT_APPLICABLE + + if index > self.num_of_fan: + raise RuntimeError( + "index ({}) shouldn't be greater than number of fans ({})".format(index, self.num_of_fan)) + + drawer_index = self._convert_fan_index_to_drawer_index(index) + + fan_dir_bits = self._read_file(self.fan_direction) + fan_mask = 1 << drawer_index - 1 + if fan_dir_bits & fan_mask: + return self.FAN_DIRECTION_INTAKE + else: + return self.FAN_DIRECTION_EXHAUST + + def get_speed(self, index): + """ + Retrieves the speed of a Front FAN in the tray in revolutions per minute defined + by 1-based index + + :param index: An integer, 1-based index of the FAN of which to query speed + :return: integer, denoting front FAN speed + """ + speed = self._read_file(self.fan_get_speed, index) + + return speed + + def set_speed(self, val): + """ + Sets the speed of all the FANs to a value denoted by the duty-cycle percentage val + + :param val: An integer, <0-100> denoting FAN duty cycle percentage + :return: Boolean, True if operation is successful, False if not + """ + status = True + pwm = int(round(self.PWM_MAX*val/100.0)) + + try: + with open(os.path.join(self.fan_path, self.fan_set_speed.format(1)), 'w') as fan_pwm: + fan_pwm.write(str(pwm)) + except (ValueError, IOError): + log_err("Read file {} failed".format(self.fan_path + self.fan_set_speed.format(1))) + status = False + + return status diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/psuutil.py new file mode 100644 index 000000000000..6da5770c294f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/psuutil.py @@ -0,0 +1,184 @@ +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + import os.path + import syslog + import subprocess + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +def log_err(msg): + syslog.openlog("psuutil") + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + MAX_PSU_FAN = 1 + MAX_NUM_PSU = 2 + GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" + # for spectrum1 switches with plugable PSUs, the output voltage file is psuX_volt + # for spectrum2 switches the output voltage file is psuX_volt_out2 + sku_spectrum1_with_plugable_psu = ['ACS-MSN2410', 'ACS-MSN2700', + 'Mellanox-SN2700', 'Mellanox-SN2700-D48C8', 'LS-SN2700', 'ACS-MSN2740'] + + def __init__(self): + PsuBase.__init__(self) + + self.sku_name = self._get_sku_name() + + self.psu_path = "/var/run/hw-management/" + self.psu_presence = "thermal/psu{}_status" + self.psu_oper_status = "thermal/psu{}_pwr_status" + self.psu_current = "power/psu{}_curr" + self.psu_power = "power/psu{}_power" + if self.sku_name in self.sku_spectrum1_with_plugable_psu: + self.psu_voltage = "power/psu{}_volt" + else: + self.psu_voltage = "power/psu{}_volt_out2" + self.fan_speed = "thermal/psu{}_fan1_speed_get" + + def _get_sku_name(self): + p = subprocess.Popen(self.GET_HWSKU_CMD, shell=True, universal_newlines=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.rstrip('\n') + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + + :return: An integer, the number of PSUs available on the device + """ + return self.MAX_NUM_PSU + + def _read_file(self, file_pattern, index): + """ + Reads the file of the PSU + + :param file_pattern: The filename convention + :param index: An integer, 1-based index of the PSU of which to query status + :return: int + """ + return_value = 0 + try: + with open(self.psu_path + file_pattern.format(index), 'r') as file_to_read: + return_value = int(file_to_read.read()) + except IOError: + log_err("Read file {} failed".format(self.psu_path + file_pattern.format(index))) + return 0 + + return return_value + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + if index > self.MAX_NUM_PSU: + raise RuntimeError("index ({}) shouldn't be greater than {}".format(index, self.MAX_NUM_PSU)) + + status = self._read_file(self.psu_oper_status, index) + + return status == 1 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + raise RuntimeError("index shouldn't be None") + if index > self.MAX_NUM_PSU: + raise RuntimeError("index ({}) shouldn't be greater than {}".format(index, self.MAX_NUM_PSU)) + + status = self._read_file(self.psu_presence, index) + + return status == 1 + + def get_output_voltage(self, index): + """ + Retrieves the ouput volatage in milli volts of a power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query o/p volatge + :return: An integer, value of o/p voltage in mV if PSU is good, else zero + """ + if index is None: + raise RuntimeError("index shouldn't be None") + + if not self.get_psu_presence(index) or not self.get_psu_status(index): + return 0 + + voltage = self._read_file(self.psu_voltage, index) + + return voltage + + def get_output_current(self, index): + """ + Retrieves the output current in milli amperes of a power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query o/p current + :return: An integer, value of o/p current in mA if PSU is good, else zero + """ + if index is None: + raise RuntimeError("index shouldn't be None") + + if not self.get_psu_presence(index) or not self.get_psu_status(index): + return 0 + + current = self._read_file(self.psu_current, index) + + return current + + def get_output_power(self, index): + """ + Retrieves the output power in micro watts of a power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query o/p power + :return: An integer, value of o/p power in micro Watts if PSU is good, else zero + """ + if index is None: + raise RuntimeError("index shouldn't be None") + + if not self.get_psu_presence(index) or not self.get_psu_status(index): + return 0 + + power = self._read_file(self.psu_power, index) + + return power + + def get_fan_speed(self, index, fan_index): + """ + Retrieves the speed of fan, in rpm, denoted by 1-based of a power + supply unit (PSU) defined by 1-based index + :param index: An integer, 1-based index of the PSU of which to query fan speed + :param fan_index: An integer, 1-based index of the PSU-fan of which to query speed + :return: An integer, value of PSU-fan speed in rpm if PSU-fan is good, else zero + """ + if index is None: + raise RuntimeError("index shouldn't be None") + if fan_index > self.MAX_PSU_FAN: + raise RuntimeError("fan_index ({}) shouldn't be greater than {}".format(fan_index, self.MAX_PSU_FAN)) + if not self.get_psu_presence(index) or not self.get_psu_status(index): + return 0 + + fan_speed = self._read_file(self.fan_speed, index) + + return fan_speed diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py new file mode 100644 index 000000000000..ca16c3573d06 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +""" +This utility get the power mode of a given module. +""" + +import sys +import errno +from python_sdk_api.sx_api import * + + +def mgmt_phy_mod_pwr_attr_get(handle, module_id, power_attr_type): + sx_mgmt_phy_mod_pwr_attr_p = new_sx_mgmt_phy_mod_pwr_attr_t_p() + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t() + sx_mgmt_phy_mod_pwr_attr.power_attr_type = power_attr_type + sx_mgmt_phy_mod_pwr_attr_t_p_assign(sx_mgmt_phy_mod_pwr_attr_p, sx_mgmt_phy_mod_pwr_attr) + try: + rc = sx_mgmt_phy_mod_pwr_attr_get(handle, module_id, sx_mgmt_phy_mod_pwr_attr_p) + assert SX_STATUS_SUCCESS == rc, "sx_mgmt_phy_mod_pwr_attr_get failed" + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t_p_value(sx_mgmt_phy_mod_pwr_attr_p) + pwr_mode_attr = sx_mgmt_phy_mod_pwr_attr.pwr_mode_attr + return pwr_mode_attr.admin_pwr_mode_e, pwr_mode_attr.oper_pwr_mode_e + finally: + delete_sx_mgmt_phy_mod_pwr_attr_t_p(sx_mgmt_phy_mod_pwr_attr_p) + + +# Check if SFP port number is provided +if len(sys.argv) < 2: + print("SFP module number is missed.") + print("Usage: sfplpmget.py ") + sys.exit(errno.EINVAL) + +# Init SDK API +rc, handle = sx_api_open(None) +if (rc != SX_STATUS_SUCCESS): + print("Failed to open api handle.\nPlease check that SDK is running.") + sys.exit(errno.EACCES) + +# Get SFP module number +sfp_module = int(sys.argv[1]) - 1 + +admin_pwr_mode, oper_pwr_mode = mgmt_phy_mod_pwr_attr_get(handle, sfp_module, SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E) + +lpm_status = None +if oper_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_HIGH_E: + lpm_status = False +elif oper_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E: + lpm_status = True +else: + print("LPM UNKNOWN") + +print("LPM ON" if lpm_status else "LPM OFF") + +sx_api_close(handle) diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py new file mode 100644 index 000000000000..61423880ac71 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 + +""" +This utility set the power mode of a given module. +""" + +import sys +import errno +from python_sdk_api.sx_api import * + + +DEVICE_ID = 1 +SWITCH_ID = 0 +SX_PORT_ATTR_ARR_SIZE = 64 + +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() + module_state_p = new_sx_port_module_state_t_p() + rc = sx_api_port_state_get(handle, log_port, oper_state_p, admin_state_p, module_state_p) + assert rc == SX_STATUS_SUCCESS, "sx_api_port_state_get failed, rc = %d" % rc + + admin_state = sx_port_admin_state_t_p_value(admin_state_p) + if admin_state == SX_PORT_ADMIN_STATUS_UP: + return True + else: + return False + + +def set_port_admin_status_by_log_port(handle, log_port, admin_status): + rc = sx_api_port_state_set(handle, log_port, admin_status) + assert rc == SX_STATUS_SUCCESS, "sx_api_port_state_set failed, rc = %d" % rc + +# Get all the ports related to the sfp, if port admin status is up, put it to list + + +def get_log_ports(handle, sfp_module): + port_attributes_list = new_sx_port_attributes_t_arr(SX_PORT_ATTR_ARR_SIZE) + port_cnt_p = new_uint32_t_p() + uint32_t_p_assign(port_cnt_p, SX_PORT_ATTR_ARR_SIZE) + + rc = sx_api_port_device_get(handle, DEVICE_ID, SWITCH_ID, port_attributes_list, port_cnt_p) + assert rc == SX_STATUS_SUCCESS, "sx_api_port_device_get failed, rc = %d" % rc + + port_cnt = uint32_t_p_value(port_cnt_p) + log_port_list = [] + for i in range(0, port_cnt): + port_attributes = sx_port_attributes_t_arr_getitem(port_attributes_list, i) + if not is_nve(int(port_attributes.log_port)) \ + and not is_cpu(int(port_attributes.log_port)) \ + 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) + + return log_port_list + + +def mgmt_phy_mod_pwr_attr_set(handle, module_id, power_attr_type, admin_pwr_mode): + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t() + sx_mgmt_phy_mod_pwr_mode_attr = sx_mgmt_phy_mod_pwr_mode_attr_t() + sx_mgmt_phy_mod_pwr_attr.power_attr_type = power_attr_type + sx_mgmt_phy_mod_pwr_mode_attr.admin_pwr_mode_e = admin_pwr_mode + sx_mgmt_phy_mod_pwr_attr.pwr_mode_attr = sx_mgmt_phy_mod_pwr_mode_attr + sx_mgmt_phy_mod_pwr_attr_p = new_sx_mgmt_phy_mod_pwr_attr_t_p() + sx_mgmt_phy_mod_pwr_attr_t_p_assign(sx_mgmt_phy_mod_pwr_attr_p, sx_mgmt_phy_mod_pwr_attr) + try: + rc = sx_mgmt_phy_mod_pwr_attr_set(handle, SX_ACCESS_CMD_SET, module_id, sx_mgmt_phy_mod_pwr_attr_p) + assert SX_STATUS_SUCCESS == rc, "sx_mgmt_phy_mod_pwr_attr_set failed" + finally: + delete_sx_mgmt_phy_mod_pwr_attr_t_p(sx_mgmt_phy_mod_pwr_attr_p) + + +def mgmt_phy_mod_pwr_attr_get(handle, module_id, power_attr_type): + sx_mgmt_phy_mod_pwr_attr_p = new_sx_mgmt_phy_mod_pwr_attr_t_p() + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t() + sx_mgmt_phy_mod_pwr_attr.power_attr_type = power_attr_type + sx_mgmt_phy_mod_pwr_attr_t_p_assign(sx_mgmt_phy_mod_pwr_attr_p, sx_mgmt_phy_mod_pwr_attr) + try: + rc = sx_mgmt_phy_mod_pwr_attr_get(handle, module_id, sx_mgmt_phy_mod_pwr_attr_p) + assert SX_STATUS_SUCCESS == rc, "sx_mgmt_phy_mod_pwr_attr_get failed" + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t_p_value(sx_mgmt_phy_mod_pwr_attr_p) + pwr_mode_attr = sx_mgmt_phy_mod_pwr_attr.pwr_mode_attr + return pwr_mode_attr.admin_pwr_mode_e, pwr_mode_attr.oper_pwr_mode_e + finally: + delete_sx_mgmt_phy_mod_pwr_attr_t_p(sx_mgmt_phy_mod_pwr_attr_p) + + +def pwr_attr_set(handle, module_id, ports, attr_type, power_mode): + # Check if the module already works in the same mode + admin_pwr_mode, oper_pwr_mode = mgmt_phy_mod_pwr_attr_get(handle, module_id, attr_type) + if (power_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E and oper_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E) \ + or (power_mode == SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E and admin_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E): + return + try: + # Bring the port down + for port in ports: + set_port_admin_status_by_log_port(handle, port, SX_PORT_ADMIN_STATUS_DOWN) + # Set the desired power mode + mgmt_phy_mod_pwr_attr_set(handle, module_id, attr_type, power_mode) + # Bring the port up + finally: + for port in ports: + set_port_admin_status_by_log_port(handle, port, SX_PORT_ADMIN_STATUS_UP) + + +def set_lpmode(handle, cmd, module_id): + # Construct the port module map. + log_port_list = get_log_ports(handle, module_id) + + if cmd == "enable": + pwr_attr_set(handle, module_id, log_port_list, + SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E, SX_MGMT_PHY_MOD_PWR_MODE_LOW_E) + print("Enabled low power mode for module [%d]" % module_id) + elif cmd == "disable": + pwr_attr_set(handle, module_id, log_port_list, + SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E, SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E) + print("Disabled low power mode for module [%d]" % module_id) + else: + print("Error: Invalid command") + sys.exit(0) + + +if len(sys.argv) < 3: + print("SFP module number or LPM is missed.") + print("Usage: sfplpmset.py ") + sys.exit(errno.EINVAL) + +cmd = None +lpm_enable = None +if sys.argv[2] == 'on': + lpm_enable = True + cmd = 'enable' +elif sys.argv[2] == 'off': + lpm_enable = False + cmd = 'disable' +else: + print("Unrecognized LPM parameter. Please use or values") + sys.exit(errno.EINVAL) + +# Get SFP module +sfp_module = int(sys.argv[1]) - 1 + +print("[+] opening sdk") +rc, handle = sx_api_open(None) + +if (rc != SX_STATUS_SUCCESS): + print("Failed to open api handle.\nPlease check that SDK is running.") + sys.exit(errno.EACCES) + +# Set low power mode +set_lpmode(handle, cmd, sfp_module) + +sx_api_close(handle) diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py new file mode 100644 index 000000000000..af237b705e9f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +""" +This utility reset the given SFP module. +""" + +import sys +import errno +from python_sdk_api.sx_api import * + +# Check if SFP port number is provided +if len(sys.argv) < 2: + print("SFP module number or LPM is missed.") + print("Usage: sfpreset.py ") + sys.exit(errno.EINVAL) + +# Init SDK API +rc, handle = sx_api_open(None) +if rc != SX_STATUS_SUCCESS: + print("Failed to open api handle.\nPlease check that SDK is running.") + sys.exit(errno.EACCES) + +# Get SFP module number +sfp_module = int(sys.argv[1]) - 1 + +rc = sx_mgmt_phy_mod_reset(handle, sfp_module) +assert rc == SX_STATUS_SUCCESS, "sx_mgmt_phy_mod_reset failed, rc = %d" % rc + +sx_api_close(handle) diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py new file mode 100644 index 000000000000..df60c5256f2a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py @@ -0,0 +1,688 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import subprocess + from sonic_sfp.sfputilbase import * + import syslog +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# sfp supports dom +XCVR_DOM_CAPABILITY_DOM_SUPPORT_BIT = 0x40 + +# sfp module threshold offset and width +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 + +# I2C page size for sfp +SFP_I2C_PAGE_SIZE = 256 + +# parameters for DB connection +REDIS_TIMEOUT_USECS = 0 + +# parameters for SFP presence +SFP_STATUS_INSERTED = '1' + +# system level event/error +EVENT_ON_ALL_SFP = '-1' +SYSTEM_NOT_READY = 'system_not_ready' +SYSTEM_READY = 'system_become_ready' +SYSTEM_FAIL = 'system_fail' + +GET_PLATFORM_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.platform" + +# Ethernet <=> sfp +SFP_PORT_NAME_OFFSET = 0 +SFP_PORT_NAME_CONVENTION = "sfp{}" + +# magic code defnition for port number, qsfp port position of each platform +# port_position_tuple = (PORT_START, QSFP_PORT_START, PORT_END, PORT_IN_BLOCK, EEPROM_OFFSET) +platform_dict = {'x86_64-mlnx_msn2700-r0': 0, 'x86_64-mlnx_msn2740-r0': 0, 'x86_64-mlnx_msn2100-r0': 1, 'x86_64-mlnx_msn2410-r0': 2, 'x86_64-mlnx_msn2010-r0': 3, + 'x86_64-mlnx_msn3420-r0': 5, 'x86_64-mlnx_msn3700-r0': 0, 'x86_64-mlnx_msn3700c-r0': 0, 'x86_64-mlnx_msn3800-r0': 4, 'x86_64-mlnx_msn4600c': 4, 'x86_64-mlnx_msn4700-r0': 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), (0, 48, 59, 60, 1)] + + +def log_info(msg, also_print_to_console=False): + syslog.openlog("sfputil") + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + +def log_err(msg, also_print_to_console=False): + syslog.openlog("sfputil") + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + PORT_START = 0 + QSFP_PORT_START = 0 + PORT_END = 0 + PORTS_IN_BLOCK = 0 + EEPROM_OFFSET = 0 + + db_sel = None + db_sel_timeout = None + db_sel_object = None + db_sel_tbl = None + state_db = None + sfpd_status_tbl = None + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + print("dependency on sysfs has been removed") + raise Exception() + + def get_port_position_tuple_by_platform_name(self): + p = subprocess.Popen(GET_PLATFORM_CMD, shell=True, universal_newlines=True, stdout=subprocess.PIPE) + out, err = p.communicate() + position_tuple = port_position_tuple_list[platform_dict[out.rstrip('\n')]] + return position_tuple + + def __init__(self): + port_position_tuple = self.get_port_position_tuple_by_platform_name() + self.PORT_START = port_position_tuple[0] + 1 + self.QSFP_PORT_START = port_position_tuple[1] + 1 + self.PORT_END = port_position_tuple[2] + 1 + self.PORTS_IN_BLOCK = port_position_tuple[3] + self.EEPROM_OFFSET = port_position_tuple[4] + self.mlnx_sfpd_started = False + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + presence = False + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return presence + + port_num += SFP_PORT_NAME_OFFSET + sfpname = SFP_PORT_NAME_CONVENTION.format(port_num) + + ethtool_cmd = "ethtool -m {} 2>/dev/null".format(sfpname) + try: + proc = subprocess.Popen(ethtool_cmd, stdout=subprocess.PIPE, shell=True, universal_newlines=True, stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + if result != '': + presence = True + + except OSError as e: + return presence + + return presence + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + lpm_cmd = "docker exec syncd python /usr/share/sonic/platform/plugins/sfplpmget.py {}".format(port_num) + + try: + output = subprocess.check_output(lpm_cmd, shell=True, universal_newlines=True) + if 'LPM ON' in output: + return True + except subprocess.CalledProcessError as e: + print("Error! Unable to get LPM for {}, rc = {}, err msg: {}".format(port_num, e.returncode, e.output)) + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + curr_lpmode = self.get_low_power_mode(port_num) + if curr_lpmode == lpmode: + return True + + # Compose LPM command + lpm = 'on' if lpmode else 'off' + lpm_cmd = "docker exec syncd python /usr/share/sonic/platform/plugins/sfplpmset.py {} {}".format(port_num, lpm) + + # Set LPM + try: + subprocess.check_output(lpm_cmd, shell=True, universal_newlines=True) + except subprocess.CalledProcessError as e: + print("Error! Unable to set LPM for {}, rc = {}, err msg: {}".format(port_num, e.returncode, e.output)) + return False + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + lpm_cmd = "docker exec syncd python /usr/share/sonic/platform/plugins/sfpreset.py {}".format(port_num) + + try: + subprocess.check_output(lpm_cmd, shell=True, universal_newlines=True) + return True + except subprocess.CalledProcessError as e: + print("Error! Unable to set LPM for {}, rc = {}, err msg: {}".format(port_num, e.returncode, e.output)) + return False + + return False + + def get_transceiver_change_event(self, timeout=0): + phy_port_dict = {} + status = True + + if self.db_sel is None: + from swsscommon import swsscommon + self.state_db = swsscommon.DBConnector("STATE_DB", + REDIS_TIMEOUT_USECS, + True) + + # Subscribe to state table for SFP change notifications + self.db_sel = swsscommon.Select() + self.db_sel_tbl = swsscommon.NotificationConsumer(self.state_db, 'TRANSCEIVER_NOTIFY') + self.db_sel.addSelectable(self.db_sel_tbl) + self.db_sel_timeout = swsscommon.Select.TIMEOUT + self.db_sel_object = swsscommon.Select.OBJECT + self.sfpd_status_tbl = swsscommon.Table(self.state_db, 'MLNX_SFPD_TASK') + + # Check the liveness of mlnx-sfpd, if it failed, return system_fail event + # If mlnx-sfpd not started, return system_not_ready event + keys = self.sfpd_status_tbl.getKeys() + if 'LIVENESS' not in keys: + if self.mlnx_sfpd_started: + log_err("mlnx-sfpd exited, return false to notify xcvrd.") + phy_port_dict[EVENT_ON_ALL_SFP] = SYSTEM_FAIL + return False, phy_port_dict + else: + log_info("mlnx-sfpd not ready, return false to notify xcvrd.") + phy_port_dict[EVENT_ON_ALL_SFP] = SYSTEM_NOT_READY + return False, phy_port_dict + else: + if not self.mlnx_sfpd_started: + self.mlnx_sfpd_started = True + log_info("mlnx-sfpd is running") + phy_port_dict[EVENT_ON_ALL_SFP] = SYSTEM_READY + return False, phy_port_dict + + if timeout: + (state, c) = self.db_sel.select(timeout) + else: + (state, c) = self.db_sel.select() + + if state == self.db_sel_timeout: + status = True + elif state != self.db_sel_object: + status = False + else: + (key, op, fvp) = self.db_sel_tbl.pop() + phy_port_dict[key] = op + + return status, phy_port_dict + + def _read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes): + print("_read_eeprom_specific_bytes should not be called since the sysfs it dependents on will no longer exist.") + print("_read_eeprom_specific_bytes_via_ethtool should be called instead") + raise Exception() + + # Read out any bytes from any offset + def _read_eeprom_specific_bytes_via_ethtool(self, port_num, offset, num_bytes): + port_num += SFP_PORT_NAME_OFFSET + sfpname = SFP_PORT_NAME_CONVENTION.format(port_num) + + eeprom_raw = [] + ethtool_cmd = "ethtool -m {} hex on offset {} length {}".format(sfpname, offset, num_bytes) + try: + output = subprocess.check_output(ethtool_cmd, shell=True, universal_newlines=True) + output_lines = output.splitlines() + first_line_raw = output_lines[0] + if "Offset" in first_line_raw: + for line in output_lines[2:]: + line_split = line.split() + eeprom_raw = eeprom_raw + line_split[1:] + except subprocess.CalledProcessError as e: + return None + + return eeprom_raw + + # Read eeprom + def _read_eeprom_devid(self, port_num, devid, offset, num_bytes=512): + if port_num in self.osfp_ports: + pass + elif port_num in self.qsfp_ports: + pass + elif (self.DOM_EEPROM_ADDR == devid): + offset += 256 + + eeprom_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, offset, num_bytes) + + return eeprom_raw + + # Read out SFP type, vendor name, PN, REV, SN from eeprom. + def get_transceiver_info_dict(self, port_num): + transceiver_info_dict = {} + compliance_code_dict = {} + + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + if port_num in self.osfp_ports: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP + + sfpi_obj = inf8628InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + sfp_type_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + OSFP_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + # Below part is added to avoid fail the xcvrd, shall be implemented later + transceiver_info_dict['vendor_oui'] = 'N/A' + transceiver_info_dict['vendor_date'] = 'N/A' + transceiver_info_dict['connector'] = 'N/A' + transceiver_info_dict['encoding'] = 'N/A' + transceiver_info_dict['ext_identifier'] = 'N/A' + transceiver_info_dict['ext_rateselect_compliance'] = 'N/A' + transceiver_info_dict['cable_type'] = 'N/A' + transceiver_info_dict['cable_length'] = 'N/A' + transceiver_info_dict['specification_compliance'] = 'N/A' + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + + else: + if port_num in self.qsfp_ports: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + cable_length_width = XCVR_CABLE_LENGTH_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + sfp_type = 'QSFP' + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + cable_length_width = XCVR_CABLE_LENGTH_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + sfp_type = 'SFP' + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + sfp_interface_bulk_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + XCVR_INTFACE_BULK_OFFSET), interface_info_bulk_width) + if sfp_interface_bulk_raw is not None: + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + XCVR_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + sfp_vendor_oui_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + else: + return None + + sfp_vendor_date_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + if sfp_vendor_date_raw is not None: + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + else: + return None + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + if sfp_type == 'QSFP': + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_transceiver_dom_info_dict(self, port_num): + transceiver_dom_info_dict = {} + + # Below part is added to avoid failing xcvrd + # Currently, the way in which dom data is read has been changed from + # using sysfs to using ethtool. + # The ethtool returns None for ports without dom support, resulting in + # None being returned. However, this fails xcvrd to add the + # TRANSCEIVER_DOM_SENSOR table entry of associated port to CONFIG_DB + # and then causes SNMP fail. + # To address this issue a default dict is initialized with all data set to + # 'N/A' and is returned is the above case. + # BTW, in the original implementation which sysfs is used to read dom data, + # even though non-None data is returned for ports without dom support, + # it does not contain valid data. This can result in wrong data in + # TRANSCEIVER_DOM_SENSOR table. + transceiver_dom_info_dict['temperature'] = 'N/A' + transceiver_dom_info_dict['voltage'] = 'N/A' + transceiver_dom_info_dict['rx1power'] = 'N/A' + 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'] = 'N/A' + 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'] = 'N/A' + transceiver_dom_info_dict['tx2power'] = 'N/A' + transceiver_dom_info_dict['tx3power'] = 'N/A' + transceiver_dom_info_dict['tx4power'] = 'N/A' + + if port_num in self.osfp_ports: + pass + elif port_num in self.qsfp_ports: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + return None + + # 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_via_ethtool( + port_num, (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_dom_capability(qsfp_dom_capability_raw, 0) + else: + return transceiver_dom_info_dict + + dom_temperature_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (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_via_ethtool( + port_num, (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_via_ethtool( + port_num, (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_via_ethtool( + port_num, (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 + else: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes_via_ethtool( + port_num, (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 transceiver_dom_info_dict + + 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'] + + 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 = SFP_I2C_PAGE_SIZE + + eeprom_raw = ['0'] * SFP_I2C_PAGE_SIZE + eeprom_raw[XCVR_DOM_CAPABILITY_OFFSET: XCVR_DOM_CAPABILITY_OFFSET + XCVR_DOM_CAPABILITY_WIDTH] = \ + self._read_eeprom_specific_bytes_via_ethtool( + port_num, XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + sfp_obj = sff8472InterfaceId() + calibration_type = sfp_obj._get_calibration_type(eeprom_raw) + + dom_supported = (int(eeprom_raw[XCVR_DOM_CAPABILITY_OFFSET], 16) & XCVR_DOM_CAPABILITY_DOM_SUPPORT_BIT != 0) + if not dom_supported: + return transceiver_dom_info_dict + + eeprom_domraw = self._read_eeprom_specific_bytes_via_ethtool(port_num, offset, SFP_I2C_PAGE_SIZE) + if eeprom_domraw is None: + return transceiver_dom_info_dict + + sfpd_obj = sff8472Dom(None, calibration_type) + if sfpd_obj is None: + print("no sff8472Dom") + return None + + dom_temperature_raw = eeprom_domraw[SFP_TEMPE_OFFSET:SFP_TEMPE_OFFSET+SFP_TEMPE_WIDTH] + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + + dom_voltage_raw = eeprom_domraw[SFP_VOLT_OFFSET:SFP_VOLT_OFFSET+SFP_VOLT_WIDTH] + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + + dom_channel_monitor_raw = eeprom_domraw[SFP_CHANNL_MON_OFFSET:SFP_CHANNL_MON_OFFSET+SFP_CHANNL_MON_WIDTH] + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + + 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['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + + 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: + # current we don't support qsfp since threshold data is on page 3 and the way to read this page is under discussion. + return transceiver_dom_threshold_info_dict + else: + offset = SFP_I2C_PAGE_SIZE + + eeprom_raw = ['0'] * SFP_I2C_PAGE_SIZE + eeprom_raw[XCVR_DOM_CAPABILITY_OFFSET: XCVR_DOM_CAPABILITY_OFFSET + XCVR_DOM_CAPABILITY_WIDTH] = \ + self._read_eeprom_specific_bytes_via_ethtool( + port_num, XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + sfp_obj = sff8472InterfaceId() + calibration_type = sfp_obj._get_calibration_type(eeprom_raw) + + dom_supported = (int(eeprom_raw[XCVR_DOM_CAPABILITY_OFFSET], 16) & XCVR_DOM_CAPABILITY_DOM_SUPPORT_BIT != 0) + if not dom_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = sff8472Dom(None, calibration_type) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, + (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 + + # 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/mellanox/x86_64-mlnx_msn2700-r0/plugins/thermalutil.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/thermalutil.py new file mode 100644 index 000000000000..980ef8a9fc38 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/thermalutil.py @@ -0,0 +1,456 @@ +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC Thermal Base API and +# provides the thermal sensor status which are available in the platform +# +############################################################################# + +try: + from os.path import join + import syslog + import subprocess + from sonic_thermal.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +def log_info(msg): + syslog.openlog("thermalutil") + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + +THERMAL_DEV_CATEGORY_CPU_CORE = "cpu_core" +THERMAL_DEV_CATEGORY_CPU_PACK = "cpu_pack" +THERMAL_DEV_CATEGORY_MODULE = "module" +THERMAL_DEV_CATEGORY_PSU = "psu" +THERMAL_DEV_CATEGORY_GEARBOX = "gearbox" +THERMAL_DEV_CATEGORY_AMBIENT = "ambient" + +THERMAL_DEV_ASIC_AMBIENT = "asic_amb" +THERMAL_DEV_FAN_AMBIENT = "fan_amb" +THERMAL_DEV_PORT_AMBIENT = "port_amb" +THERMAL_DEV_COMEX_AMBIENT = "comex_amb" +THERMAL_DEV_BOARD_AMBIENT = "board_amb" + +THERMAL_API_GET_TEMPERATURE = "get_temperature" +THERMAL_API_GET_HIGH_THRESHOLD = "get_high_threshold" +THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD = "get_high_critical_threshold" + +THERMAL_API_INVALID_HIGH_THRESHOLD = 0.0 + +HW_MGMT_THERMAL_ROOT = "/var/run/hw-management/thermal/" + +thermal_api_handler_cpu_core = { + THERMAL_API_GET_TEMPERATURE: "cpu_core{}", + THERMAL_API_GET_HIGH_THRESHOLD: "cpu_core{}_max", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD: "cpu_core{}_crit" +} +thermal_api_handler_cpu_pack = { + THERMAL_API_GET_TEMPERATURE: "cpu_pack", + THERMAL_API_GET_HIGH_THRESHOLD: "cpu_pack_max", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD: "cpu_pack_crit" +} +thermal_api_handler_module = { + THERMAL_API_GET_TEMPERATURE: "module{}_temp_input", + THERMAL_API_GET_HIGH_THRESHOLD: "module{}_temp_crit", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD: "module{}_temp_emergency" +} +thermal_api_handler_psu = { + THERMAL_API_GET_TEMPERATURE: "psu{}_temp", + THERMAL_API_GET_HIGH_THRESHOLD: "psu{}_temp_max", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD: None +} +thermal_api_handler_gearbox = { + THERMAL_API_GET_TEMPERATURE: "gearbox{}_temp_input", + THERMAL_API_GET_HIGH_THRESHOLD: None, + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD: None +} +thermal_ambient_apis = { + THERMAL_DEV_ASIC_AMBIENT: "asic", + THERMAL_DEV_PORT_AMBIENT: "port_amb", + THERMAL_DEV_FAN_AMBIENT: "fan_amb", + THERMAL_DEV_COMEX_AMBIENT: "comex_amb", + THERMAL_DEV_BOARD_AMBIENT: "board_amb" +} +thermal_ambient_name = { + THERMAL_DEV_ASIC_AMBIENT: "Ambient ASIC Temp", + THERMAL_DEV_PORT_AMBIENT: "Ambient Port Side Temp", + THERMAL_DEV_FAN_AMBIENT: "Ambient Fan Side Temp", + THERMAL_DEV_COMEX_AMBIENT: "Ambient COMEX Temp", + THERMAL_DEV_BOARD_AMBIENT: "Ambient Board Temp" +} +thermal_api_handlers = { + THERMAL_DEV_CATEGORY_CPU_CORE: thermal_api_handler_cpu_core, + THERMAL_DEV_CATEGORY_CPU_PACK: thermal_api_handler_cpu_pack, + THERMAL_DEV_CATEGORY_MODULE: thermal_api_handler_module, + THERMAL_DEV_CATEGORY_PSU: thermal_api_handler_psu, + THERMAL_DEV_CATEGORY_GEARBOX: thermal_api_handler_gearbox +} +thermal_name = { + THERMAL_DEV_CATEGORY_CPU_CORE: "CPU Core {} Temp", + THERMAL_DEV_CATEGORY_CPU_PACK: "CPU Pack Temp", + THERMAL_DEV_CATEGORY_MODULE: "xSFP module {} Temp", + THERMAL_DEV_CATEGORY_PSU: "PSU-{} Temp", + THERMAL_DEV_CATEGORY_GEARBOX: "Gearbox {} Temp" +} + +thermal_device_categories_all = [ + THERMAL_DEV_CATEGORY_CPU_CORE, + THERMAL_DEV_CATEGORY_CPU_PACK, + THERMAL_DEV_CATEGORY_MODULE, + THERMAL_DEV_CATEGORY_PSU, + THERMAL_DEV_CATEGORY_AMBIENT, + THERMAL_DEV_CATEGORY_GEARBOX +] + +thermal_device_categories_singleton = [ + THERMAL_DEV_CATEGORY_CPU_PACK, + THERMAL_DEV_CATEGORY_AMBIENT +] +thermal_api_names = [ + THERMAL_API_GET_TEMPERATURE, + 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, 'Mellanox-SN3800-D112C8': 7} +thermal_profile_list = [ + # 2700 + { + THERMAL_DEV_CATEGORY_CPU_CORE: (0, 2), + 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_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT + ] + ) + }, + # 2100 + { + THERMAL_DEV_CATEGORY_CPU_CORE: (0, 4), + THERMAL_DEV_CATEGORY_MODULE: (1, 16), + THERMAL_DEV_CATEGORY_PSU: (0, 0), + THERMAL_DEV_CATEGORY_CPU_PACK: (0, 0), + THERMAL_DEV_CATEGORY_GEARBOX: (0, 0), + THERMAL_DEV_CATEGORY_AMBIENT: (0, + [ + THERMAL_DEV_ASIC_AMBIENT, + THERMAL_DEV_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT, + ] + ) + }, + # 2410 + { + THERMAL_DEV_CATEGORY_CPU_CORE: (0, 2), + THERMAL_DEV_CATEGORY_MODULE: (1, 56), + 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_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT, + ] + ) + }, + # 2740 + { + 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, 0), + THERMAL_DEV_CATEGORY_GEARBOX: (0, 0), + THERMAL_DEV_CATEGORY_AMBIENT: (0, + [ + THERMAL_DEV_ASIC_AMBIENT, + THERMAL_DEV_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT, + ] + ) + }, + # 2010 + { + THERMAL_DEV_CATEGORY_CPU_CORE: (0, 4), + THERMAL_DEV_CATEGORY_MODULE: (1, 22), + THERMAL_DEV_CATEGORY_PSU: (0, 0), + THERMAL_DEV_CATEGORY_CPU_PACK: (0, 0), + THERMAL_DEV_CATEGORY_GEARBOX: (0, 0), + THERMAL_DEV_CATEGORY_AMBIENT: (0, + [ + THERMAL_DEV_ASIC_AMBIENT, + THERMAL_DEV_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT, + ] + ) + }, + # 3700 + { + 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 + ] + ) + }, + # 3700c + { + THERMAL_DEV_CATEGORY_CPU_CORE: (0, 2), + 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 + ] + ) + }, + # 3800 + { + THERMAL_DEV_CATEGORY_CPU_CORE: (0, 4), + THERMAL_DEV_CATEGORY_MODULE: (1, 64), + THERMAL_DEV_CATEGORY_PSU: (1, 2), + THERMAL_DEV_CATEGORY_CPU_PACK: (0, 1), + THERMAL_DEV_CATEGORY_GEARBOX: (1, 32), + THERMAL_DEV_CATEGORY_AMBIENT: (0, + [ + THERMAL_DEV_ASIC_AMBIENT, + THERMAL_DEV_COMEX_AMBIENT, + THERMAL_DEV_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT + ] + ) + }, +] + + +class Thermal(object): + def __init__(self, category, index, has_index): + """ + index should be a string for category ambient and int for other categories + """ + if category == THERMAL_DEV_CATEGORY_AMBIENT: + self.name = thermal_ambient_name[index] + self.index = index + elif has_index: + self.name = thermal_name[category].format(index) + self.index = index + else: + self.name = thermal_name[category] + self.index = 0 + + self.category = category + self.temperature = self._get_file_from_api(THERMAL_API_GET_TEMPERATURE) + self.high_threshold = self._get_file_from_api(THERMAL_API_GET_HIGH_THRESHOLD) + self.high_critical_threshold = self._get_file_from_api(THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD) + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return self.name + + def _read_generic_file(self, filename, len): + """ + Read a generic file, returns the contents of the file + """ + result = None + try: + with open(filename, 'r') as fileobj: + result = fileobj.read() + except Exception as e: + log_info("Fail to read file {} due to {}".format(filename, repr(e))) + return result + + def _get_file_from_api(self, api_name): + if self.category == THERMAL_DEV_CATEGORY_AMBIENT: + if api_name == THERMAL_API_GET_TEMPERATURE: + filename = thermal_ambient_apis[self.index] + else: + return None + else: + handler = thermal_api_handlers[self.category][api_name] + if self.category in thermal_device_categories_singleton: + filename = handler + else: + if handler: + filename = handler.format(self.index) + else: + return None + return join(HW_MGMT_THERMAL_ROOT, filename) + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + value_str = self._read_generic_file(self.temperature, 0) + if value_str is None: + return None + value_float = float(value_str) + if self.category == THERMAL_DEV_CATEGORY_MODULE and value_float == THERMAL_API_INVALID_HIGH_THRESHOLD: + return None + return value_float / 1000.0 + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_threshold is None: + return None + value_str = self._read_generic_file(self.high_threshold, 0) + if value_str is None: + return None + value_float = float(value_str) + if self.category == THERMAL_DEV_CATEGORY_MODULE and value_float == THERMAL_API_INVALID_HIGH_THRESHOLD: + return None + return value_float / 1000.0 + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_critical_threshold is None: + return None + value_str = self._read_generic_file(self.high_critical_threshold, 0) + if value_str is None: + return None + value_float = float(value_str) + if self.category == THERMAL_DEV_CATEGORY_MODULE and value_float == THERMAL_API_INVALID_HIGH_THRESHOLD: + return None + return value_float / 1000.0 + + +class ThermalUtil(ThermalBase): + """Platform-specific Thermalutil class""" + + MAX_PSU_FAN = 1 + MAX_NUM_PSU = 2 + GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" + number_of_thermals = 0 + thermal_list = [] + + def _get_sku_name(self): + p = subprocess.Popen(self.GET_HWSKU_CMD, shell=True, universal_newlines=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.rstrip('\n') + + def __init__(self): + sku = self._get_sku_name() + # create thermal objects for all categories of sensors + tp_index = hwsku_dict_thermal[sku] + thermal_profile = thermal_profile_list[tp_index] + for category in thermal_device_categories_all: + if category == THERMAL_DEV_CATEGORY_AMBIENT: + count, ambient_list = thermal_profile[category] + for ambient in ambient_list: + thermal = Thermal(category, ambient, True) + self.thermal_list.append(thermal) + else: + start, count = 0, 0 + if category in thermal_profile: + start, count = thermal_profile[category] + if count == 0: + continue + if count == 1: + thermal = Thermal(category, 0, False) + self.thermal_list.append(thermal) + else: + for index in range(count): + thermal = Thermal(category, start + index, True) + self.thermal_list.append(thermal) + self.number_of_thermals = len(self.thermal_list) + + def get_num_thermals(self): + """ + Retrieves the number of thermal sensors supported on the device + + :return: An integer, the number of thermal sensors supported on the device + """ + return self.number_of_thermals + + def get_name(self, index): + """ + Retrieves the human-readable name of a thermal sensor by 1-based index + + Returns: + :param index: An integer, 1-based index of the thermal sensor of which to query status + :return: String, + A string representing the name of the thermal sensor. + """ + if index >= self.number_of_thermals: + raise RuntimeError("index ({}) shouldn't be greater than {}".format(index, self.number_of_thermals)) + return self.thermal_list[index].get_name() + + def get_temperature(self, index): + """ + Retrieves current temperature reading from thermal sensor by 1-based index + + :param index: An integer, 1-based index of the thermal sensor of which to query status + :return: Float, + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if index >= self.number_of_thermals: + raise RuntimeError("index ({}) shouldn't be greater than {}".format(index, self.number_of_thermals)) + return self.thermal_list[index].get_temperature() + + def get_high_threshold(self, index): + """ + Retrieves the high threshold temperature of thermal by 1-based index + Actions should be taken if the temperature becomes higher than the threshold. + + :param index: An integer, 1-based index of the thermal sensor of which to query status + :return: A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if index >= self.number_of_thermals: + raise RuntimeError("index ({}) shouldn't be greater than {}".format(index, self.number_of_thermals)) + return self.thermal_list[index].get_high_threshold() + + def get_high_critical_threshold(self, index): + """ + Retrieves the high critical threshold temperature of thermal by 1-based index + Actions should be taken immediately if the temperature becomes higher than the high critical + threshold otherwise the device will be damaged. + + :param index: An integer, 1-based index of the thermal sensor of which to query status + :return: A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if index >= self.number_of_thermals: + raise RuntimeError("index ({}) shouldn't be greater than {}".format(index, self.number_of_thermals)) + return self.thermal_list[index].get_high_critical_threshold() diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn2700-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..dec2ba6d7826 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/pmon_daemon_control.json @@ -0,0 +1,7 @@ +{ + "skip_ledd": true, + "skip_fancontrol": true, + "delay_xcvrd": true, + "python2_daemons": ["xcvrd"] +} + diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn2700-r0/sensors.conf new file mode 100644 index 000000000000..62f100d757e7 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/sensors.conf @@ -0,0 +1,81 @@ +################################################################################ +# Copyright (c) 2020 Mellanox Technologies +# +# Platform specific sensors config for SN2700 +################################################################################ + +# Temperature sensors +bus "i2c-2" "i2c-1-mux (chan_id 2)" + chip "mlxsw-i2c-*-48" + label temp1 "Ambient ASIC Temp" + +bus "i2c-7" "i2c-1-mux (chan_id 7)" + chip "lm75-i2c-7-4a" + label temp1 "Ambient Port Temp" + +bus "i2c-17" "i2c-1-mux (chan_id 17)" + chip "lm75-i2c-17-49" + label temp1 "Ambient Fan Temp" + +chip "acpitz-virtual-0" + label temp1 "ACPI CPU Temp" + label temp2 "ACPI Board Temp" + +# Power controllers +bus "i2c-5" "i2c-1-mux (chan_id 5)" + chip "pmbus-i2c-5-41" + label in1 "PMB-1 PSU 12V Rail (in)" + label in2 "PMB-1 0.9V VCORE Rail (out)" + label temp1 "PMB-1 Temp 1" + label temp2 "PMB-1 Temp 2" + ignore power1 + label power2 "PMB-1 0.9V VCORE Rail Pwr (out)" + ignore curr1 + label curr2 "PMB-1 0.9V VCORE Rail Curr (out)" + chip "pmbus-i2c-5-27" + label in1 "PMB-2 PSU 12V Rail (in)" + label in2 "PMB-2 3.3V Rail (out)" + label in3 "PMB-2 1.2V Rail (out)" + label temp1 "PMB-2 Temp 1" + label temp2 "PMB-2 Temp 2" + ignore power1 + label power2 "PMB-2 3.3V Rail Pwr (out)" + label power3 "PMB-2 1.2V Rail Pwr (out)" + ignore curr1 + label curr2 "PMB-2 3.3V Rail Curr (out)" + label curr3 "PMB-2 1.2V Rail Curr (out)" + +# Power supplies +bus "i2c-10" "i2c-1-mux (chan_id 10)" + chip "dps460-i2c-*-58" + label in1 "PSU-2(R) 220V Rail (in)" + label in2 "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 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)" + chip "dps460-i2c-*-59" + label in1 "PSU-1(L) 220V Rail (in)" + label in2 "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 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)" + +# Chassis fans +bus "i2c-2" "i2c-1-mux (chan_id 2)" + chip "mlxsw-i2c-*-48" + label fan1 "Chassis Drawer-1 Fan-1" + label fan2 "Chassis Drawer-1 Fan-2" + label fan3 "Chassis Drawer-2 Fan-1" + label fan4 "Chassis Drawer-2 Fan-2" + label fan5 "Chassis Drawer-3 Fan-1" + label fan6 "Chassis Drawer-3 Fan-2" + label fan7 "Chassis Drawer-4 Fan-1" + label fan8 "Chassis Drawer-4 Fan-2" diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..bff6ab4b38ee --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json @@ -0,0 +1,11 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": ["psu.voltage"], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "orange", + "normal": "green", + "booting": "orange_blink" + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2700-r0/thermal_policy.json new file mode 100644 index 000000000000..1e23d6c8b2bd --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/thermal_policy.json @@ -0,0 +1,80 @@ +{ + "thermal_control_algorithm": { + "run_at_boot_up": "true", + "fan_speed_when_suspend": "60" + }, + "info_types": [ + { + "type": "fan_info" + }, + { + "type": "psu_info" + }, + { + "type": "chassis_info" + } + ], + "policies": [ + { + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any psu absence", + "conditions": [ + { + "type": "psu.any.absence" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any fan broken", + "conditions": [ + { + "type": "fan.any.fault" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "all fan and psu presence", + "conditions": [ + { + "type": "fan.all.presence" + }, + { + "type": "psu.all.presence" + }, + { + "type": "fan.all.good" + } + ], + "actions": [ + { + "type": "thermal.recover" + } + ] + } + ] +} \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/ACS-MSN2700 b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/ACS-MSN2700 new file mode 120000 index 000000000000..929c10e08df3 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/ACS-MSN2700 @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/ACS-MSN2700 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/Mellanox-SN2700 b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/Mellanox-SN2700 new file mode 120000 index 000000000000..c547b85a6514 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/Mellanox-SN2700 @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/Mellanox-SN2700 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/Mellanox-SN2700-D48C8 b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/Mellanox-SN2700-D48C8 new file mode 120000 index 000000000000..0ecc644a629c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/Mellanox-SN2700-D48C8 @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/default_sku new file mode 120000 index 000000000000..4efa67e398fb --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/default_sku @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/default_sku \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/installer.conf new file mode 120000 index 000000000000..955db12ff425 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/installer.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/installer.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/platform_reboot new file mode 100755 index 000000000000..5b9809e10423 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/platform_reboot @@ -0,0 +1,21 @@ +#!/bin/bash + +declare -r EXIT_SUCCESS="0" +declare -r EXIT_ERROR="1" + +FORCE_REBOOT="no" + +function ParseArguments() { + while [ $# -ge 1 ]; do + case "$1" in + -f|--force) + FORCE_REBOOT="yes" + ;; + esac + shift + done +} + +ParseArguments "$@" + +exec /sbin/reboot $@ diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/plugins b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/plugins new file mode 120000 index 000000000000..2e583e688dcb --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/plugins @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/plugins \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..dd83c2db12c5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/pmon_daemon_control.json @@ -0,0 +1,7 @@ +{ + "skip_ledd": true, + "skip_xcvrd": true, + "skip_psud": true, + "skip_pcied": true, + "skip_thermalctld": true +} diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/syseeprom.hex b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/syseeprom.hex new file mode 100644 index 000000000000..3b1c3614173c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/syseeprom.hex @@ -0,0 +1,256 @@ +54 6c 76 49 6e 66 6f 00 01 02 0f 21 40 4d 53 4e +32 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 32 37 30 30 2d 43 53 32 46 4f 00 00 00 00 +00 00 00 23 18 4d 54 31 36 32 33 58 30 39 35 32 +32 00 00 00 00 00 00 00 00 00 00 00 00 24 06 7c +fe 90 f5 36 40 25 13 30 36 2f 31 30 2f 32 30 31 +36 20 30 31 3a 35 37 3a 33 31 26 01 00 2a 02 00 +80 2b 08 4d 65 6c 6c 61 6e 6f 78 fd 24 00 00 81 +19 00 16 01 01 03 6c 00 00 4d 4c 4e 58 02 01 0c +05 0e 02 10 06 00 00 00 00 00 00 00 00 00 00 00 +00 fd a4 00 00 81 19 00 92 00 03 01 62 00 00 4d +54 31 36 32 33 58 30 39 35 32 32 00 00 00 00 00 +00 00 00 00 00 00 00 4d 53 4e 32 37 30 30 2d 43 +53 32 46 4f 00 00 00 00 00 00 00 41 35 00 00 00 +79 0c a4 50 61 6e 74 68 65 72 20 45 74 68 20 31 +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 50 00 00 00 0a 8c 4d 53 4e 32 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 55 00 00 0d 00 00 00 00 +00 00 00 7c fe 90 f5 36 40 00 80 7c fe 90 03 00 +f5 36 40 fd 24 00 00 81 19 00 12 00 01 06 85 00 +00 00 46 00 00 08 00 05 05 05 05 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 28 12 78 38 36 5f 36 +34 2d 6d 6c 6e 78 5f 78 38 36 2d 72 30 29 15 32 +30 31 38 2e 30 35 2d 35 2e 32 2e 30 30 30 34 2d +39 36 30 30 fe 04 89 d7 4c 56 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 29 20 35 2e 30 +2e 31 34 30 34 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 fe 04 12 +8a 61 b2 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 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/mellanox/x86_64-mlnx_msn2700_simx-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..23cb74dd3f96 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/system_health_monitoring_config.json @@ -0,0 +1,11 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": ["psu","asic","fan"], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "orange", + "normal": "green", + "booting": "orange_blink" + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/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_msn2740-r0/ACS-MSN2740/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..7bcae62336f6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..a437d613434d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/pg_profile_lookup.ini new file mode 120000 index 000000000000..3c97f3dcb16f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/port_config.ini b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/port_config.ini new file mode 100644 index 000000000000..2ef052c68d52 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/port_config.ini @@ -0,0 +1,33 @@ +# name lanes index +Ethernet0 0,1,2,3 1 +Ethernet4 4,5,6,7 2 +Ethernet8 8,9,10,11 3 +Ethernet12 12,13,14,15 4 +Ethernet16 16,17,18,19 5 +Ethernet20 20,21,22,23 6 +Ethernet24 24,25,26,27 7 +Ethernet28 28,29,30,31 8 +Ethernet32 32,33,34,35 9 +Ethernet36 36,37,38,39 10 +Ethernet40 40,41,42,43 11 +Ethernet44 44,45,46,47 12 +Ethernet48 48,49,50,51 13 +Ethernet52 52,53,54,55 14 +Ethernet56 56,57,58,59 15 +Ethernet60 60,61,62,63 16 +Ethernet64 64,65,66,67 17 +Ethernet68 68,69,70,71 18 +Ethernet72 72,73,74,75 19 +Ethernet76 76,77,78,79 20 +Ethernet80 80,81,82,83 21 +Ethernet84 84,85,86,87 22 +Ethernet88 88,89,90,91 23 +Ethernet92 92,93,94,95 24 +Ethernet96 96,97,98,99 25 +Ethernet100 100,101,102,103 26 +Ethernet104 104,105,106,107 27 +Ethernet108 108,109,110,111 28 +Ethernet112 112,113,114,115 29 +Ethernet116 116,117,118,119 30 +Ethernet120 120,121,122,123 31 +Ethernet124 124,125,126,127 32 diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/qos.json.j2 new file mode 120000 index 000000000000..eccf286dc879 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/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_msn2740-r0/ACS-MSN2740/sai.profile b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai.profile new file mode 100644 index 000000000000..adaa280e6cd5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_2740.xml diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai_2740.xml b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai_2740.xml new file mode 100644 index 000000000000..955ea3f8b1b6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/sai_2740.xml @@ -0,0 +1,246 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 32 + + + + + 1 + 4 + 16 + + + 3 + + + 98368 + + + 3 + 4 + 17 + 1 + 98368 + + + 5 + 4 + 18 + 3 + 98368 + + + 7 + 4 + 19 + 1 + 98368 + + + 9 + 4 + 20 + 3 + 98368 + + + 11 + 4 + 21 + 1 + 98368 + + + 13 + 4 + 22 + 3 + 98368 + + + 15 + 4 + 23 + 1 + 98368 + + + 17 + 4 + 24 + 3 + 98368 + + + 19 + 4 + 25 + 1 + 98368 + + + 21 + 4 + 26 + 3 + 98368 + + + 23 + 4 + 27 + 1 + 98368 + + + 25 + 4 + 28 + 3 + 98368 + + + 27 + 4 + 29 + 1 + 98368 + + + 29 + 4 + 30 + 3 + 98368 + + + 31 + 4 + 31 + 1 + 98368 + + + 33 + 4 + 14 + 3 + 98368 + + + 35 + 4 + 15 + 1 + 98368 + + + 37 + 4 + 12 + 3 + 98368 + + + 39 + 4 + 13 + 1 + 98368 + + + 41 + 4 + 10 + 3 + 98368 + + + 43 + 4 + 11 + 1 + 98368 + + + 45 + 4 + 8 + 3 + 98368 + + + 47 + 4 + 9 + 1 + 98368 + + + 49 + 4 + 6 + 3 + 98368 + + + 51 + 4 + 7 + 1 + 98368 + + + 53 + 4 + 4 + 3 + 98368 + + + 55 + 4 + 5 + 1 + 98368 + + + 57 + 4 + 2 + 3 + 98368 + + + 59 + 4 + 3 + 1 + 98368 + + + 61 + 4 + 0 + 3 + 98368 + + + 63 + 4 + 1 + 1 + 98368 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/default_sku b/device/mellanox/x86_64-mlnx_msn2740-r0/default_sku new file mode 100644 index 000000000000..9641115a4946 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN2740 t1 diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/installer.conf b/device/mellanox/x86_64-mlnx_msn2740-r0/installer.conf new file mode 120000 index 000000000000..955db12ff425 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/installer.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/installer.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn2740-r0/pcie.yaml new file mode 100644 index 000000000000..ca73122aaa81 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/pcie.yaml @@ -0,0 +1,83 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 1f0b + name: 'Host bridge: Intel Corporation Atom processor C2000 SoC Transaction Router + (rev 02)' +- bus: '00' + dev: '01' + fn: '0' + id: 1f10 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 1 (rev + 02)' +- bus: '00' + dev: '02' + fn: '0' + id: 1f11 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 2 (rev + 02)' +- bus: '00' + dev: '03' + fn: '0' + id: 1f12 + name: 'PCI bridge: Intel Corporation Atom processor C2000 PCIe Root Port 3 (rev + 02)' +- bus: '00' + dev: 0b + fn: '0' + id: 1f18 + name: 'Co-processor: Intel Corporation Atom processor C2000 QAT (rev 02)' +- bus: '00' + dev: 0e + fn: '0' + id: 1f14 + name: 'Host bridge: Intel Corporation Atom processor C2000 RAS (rev 02)' +- bus: '00' + dev: 0f + fn: '0' + id: 1f16 + name: 'IOMMU: Intel Corporation Atom processor C2000 RCEC (rev 02)' +- bus: '00' + dev: '13' + fn: '0' + id: 1f15 + name: 'System peripheral: Intel Corporation Atom processor C2000 SMBus 2.0 (rev + 02)' +- bus: '00' + dev: '14' + fn: '0' + id: 1f41 + name: 'Ethernet controller: Intel Corporation Ethernet Connection I354 (rev 03)' +- bus: '00' + dev: '16' + fn: '0' + id: 1f2c + name: 'USB controller: Intel Corporation Atom processor C2000 USB Enhanced Host + Controller (rev 02)' +- bus: '00' + dev: '17' + fn: '0' + id: 1f22 + name: 'SATA controller: Intel Corporation Atom processor C2000 AHCI SATA2 Controller + (rev 02)' +- bus: '00' + dev: '18' + fn: '0' + id: 1f32 + name: 'SATA controller: Intel Corporation Atom processor C2000 AHCI SATA3 Controller + (rev 02)' +- bus: '00' + dev: 1f + fn: '0' + id: 1f38 + name: 'ISA bridge: Intel Corporation Atom processor C2000 PCU (rev 02)' +- bus: '00' + dev: 1f + fn: '3' + id: 1f3c + name: 'SMBus: Intel Corporation Atom processor C2000 PCU SMBus (rev 02)' +- bus: '01' + dev: '00' + fn: '0' + id: cb84 + name: 'Ethernet controller: Mellanox Technologies MT52100' 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..da85f2b5792e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/platform_components.json @@ -0,0 +1,13 @@ +{ + "chassis": { + "MSN2740": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn2740-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-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_msn2740-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn2740-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-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_msn2740-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-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_msn2740-r0/plugins/fanutil.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/fanutil.py new file mode 120000 index 000000000000..82ea06ef915f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/fanutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/fanutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/psuutil.py new file mode 120000 index 000000000000..9f724238a8d5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-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_msn2740-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-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_msn2740-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-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_msn2740-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-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_msn2740-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-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_msn2740-r0/plugins/thermalutil.py b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/thermalutil.py new file mode 120000 index 000000000000..cef21ffacccc --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/plugins/thermalutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/thermalutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn2740-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-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_msn2740-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn2740-r0/sensors.conf new file mode 100644 index 000000000000..ffc36fe2168c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/sensors.conf @@ -0,0 +1,76 @@ +################################################################################ +# Copyright (c) 2020 Mellanox Technologies +# +# Platform specific sensors config for SN2740 +################################################################################ + +# 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-*-48" + label temp1 "Ambient Port Temp" + +bus "i2c-6" "i2c-1-mux (chan_id 5)" + chip "tmp102-i2c-*-49" + label temp1 "Ambient Fan Temp" + +# Power controllers +bus "i2c-5" "i2c-1-mux (chan_id 4)" + chip "pmbus-i2c-*-41" + label in1 "PMB-1 PSU 12V Rail (in)" + label in2 "PMB-1 0.9V VCORE Rail (out)" + label in3 "PMB-1 1.8V VCORE Rail (out)" + label temp1 "PMB-1 Temp 1" + label temp2 "PMB-1 Temp 2" + ignore power1 + label power2 "PMB-1 0.9V VCORE Rail Pwr (out)" + label power3 "PMB-1 1.8V Rail Pwr (out)" + ignore curr1 + label curr2 "PMB-1 0.9V VCORE Rail Curr (out)" + label curr3 "PMB-1 1.8V Rail Curr (out)" + chip "pmbus-i2c-*-27" + label in1 "PMB-2 PSU 12V Rail (in)" + label in2 "PMB-2 3.3V Rail (out)" + label in3 "PMB-2 1.2V Rail (out)" + label temp1 "PMB-2 Temp 1" + label temp2 "PMB-2 Temp 2" + ignore power1 + label power2 "PMB-2 3.3V Rail Pwr (out)" + label power3 "PMB-2 1.2V Rail Pwr (out)" + ignore curr1 + label curr2 "PMB-2 3.3V Rail Curr (out)" + label curr3 "PMB-2 1.2V Rail Curr (out)" + +# Power supplies +bus "i2c-4" "i2c-1-mux (chan_id 3)" + chip "dps460-i2c-*-58" + label in1 "PSU-2(R) 220V Rail (in)" + label in2 "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 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)" + chip "dps460-i2c-*-59" + label in1 "PSU-1(L) 220V Rail (in)" + label in2 "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 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)" + +# Chassis fans +bus "i2c-2" "i2c-1-mux (chan_id 1)" + chip "mlxsw-i2c-*-48" + label fan1 "Chassis Fan Drawer-1" + label fan2 "Chassis Fan Drawer-2" + label fan3 "Chassis Fan Drawer-3" + label fan4 "Chassis Fan Drawer-4" diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn2740-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..98df66c27ca5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2740-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/buffers.json.j2 new file mode 120000 index 000000000000..7888381852d8 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/buffers.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..85f0b6b6b354 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../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_msn3420-r0/ACS-MSN3420/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..3bb496a5103b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../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_msn3420-r0/ACS-MSN3420/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/hwsku.json b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/hwsku.json new file mode 100644 index 000000000000..59c3aa2c968b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/hwsku.json @@ -0,0 +1,184 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet132": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet136": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet140": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet148": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet152": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet156": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet160": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet164": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet168": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet172": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet176": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet180": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet184": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet188": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet196": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet204": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet208": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet212": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet216": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet220": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet224": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet228": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet232": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet236": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/pg_profile_lookup.ini new file mode 120000 index 000000000000..252ae8d4149b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../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_msn3420-r0/ACS-MSN3420/port_config.ini b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/port_config.ini new file mode 100644 index 000000000000..38441f21f003 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/port_config.ini @@ -0,0 +1,61 @@ +# name lanes alias index +Ethernet0 0 etp1 1 +Ethernet4 4 etp2 2 +Ethernet8 8 etp3 3 +Ethernet12 12 etp4 4 +Ethernet16 16 etp5 5 +Ethernet20 20 etp6 6 +Ethernet24 24 etp7 7 +Ethernet28 28 etp8 8 +Ethernet32 32 etp9 9 +Ethernet36 36 etp10 10 +Ethernet40 40 etp11 11 +Ethernet44 44 etp12 12 +Ethernet48 48 etp13 13 +Ethernet52 52 etp14 14 +Ethernet56 56 etp15 15 +Ethernet60 60 etp16 16 +Ethernet64 64 etp17 17 +Ethernet68 68 etp18 18 +Ethernet72 72 etp19 19 +Ethernet76 76 etp20 20 +Ethernet80 80 etp21 21 +Ethernet84 84 etp22 22 +Ethernet88 88 etp23 23 +Ethernet92 92 etp24 24 +Ethernet96 96 etp25 25 +Ethernet100 100 etp26 26 +Ethernet104 104 etp27 27 +Ethernet108 108 etp28 28 +Ethernet112 112 etp29 29 +Ethernet116 116 etp30 30 +Ethernet120 120 etp31 31 +Ethernet124 124 etp32 32 +Ethernet128 128 etp33 33 +Ethernet132 132 etp34 34 +Ethernet136 136 etp35 35 +Ethernet140 140 etp36 36 +Ethernet144 144 etp37 37 +Ethernet148 148 etp38 38 +Ethernet152 152 etp39 39 +Ethernet156 156 etp40 40 +Ethernet160 160 etp41 41 +Ethernet164 164 etp42 42 +Ethernet168 168 etp43 43 +Ethernet172 172 etp44 44 +Ethernet176 176 etp45 45 +Ethernet180 180 etp46 46 +Ethernet184 184 etp47 47 +Ethernet188 188 etp48 48 +Ethernet192 192,193,194,195 etp49 49 +Ethernet196 196,197,198,199 etp50 50 +Ethernet200 200,201,202,203 etp51 51 +Ethernet204 204,205,206,207 etp52 52 +Ethernet208 208,209,210,211 etp53 53 +Ethernet212 212,213,214,215 etp54 54 +Ethernet216 216,217,218,219 etp55 55 +Ethernet220 220,221,222,223 etp56 56 +Ethernet224 224,225,226,227 etp57 57 +Ethernet228 228,229,230,231 etp58 58 +Ethernet232 232,233,234,235 etp59 59 +Ethernet236 236,237,238,239 etp60 60 diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/qos.json.j2 new file mode 120000 index 000000000000..379f542893f3 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/qos.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn3700-r0/ACS-MSN3700/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/sai.profile b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/sai.profile new file mode 100644 index 000000000000..a30106c8674d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_3420.xml diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/sai_3420.xml b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/sai_3420.xml new file mode 100644 index 000000000000..5064ee3ef81b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/sai_3420.xml @@ -0,0 +1,442 @@ + + + + + + 00:02:03:04:05:80 + + + 1 + + + 60 + + + + + 105 + 1 + 0 + + + 0 + + + 64 + + + 106 + 1 + 1 + 0 + 64 + + + 49 + 1 + 2 + 0 + 64 + + + 113 + 1 + 3 + 0 + 64 + + + 114 + 1 + 4 + 0 + 64 + + + 50 + 1 + 5 + 0 + 64 + + + 115 + 1 + 6 + 0 + 64 + + + 116 + 1 + 7 + 0 + 64 + + + 41 + 1 + 8 + 0 + 64 + + + 121 + 1 + 9 + 0 + 64 + + + 122 + 1 + 10 + 0 + 64 + + + 42 + 1 + 11 + 0 + 64 + + + 123 + 1 + 12 + 0 + 64 + + + 124 + 1 + 13 + 0 + 64 + + + 43 + 1 + 14 + 0 + 64 + + + 57 + 1 + 15 + 0 + 64 + + + 58 + 1 + 16 + 0 + 64 + + + 44 + 1 + 17 + 0 + 64 + + + 59 + 1 + 18 + 0 + 64 + + + 60 + 1 + 19 + 0 + 64 + + + 33 + 1 + 20 + 0 + 64 + + + 51 + 1 + 21 + 0 + 64 + + + 52 + 1 + 22 + 0 + 64 + + + 34 + 1 + 23 + 0 + 64 + + + 53 + 1 + 24 + 0 + 64 + + + 54 + 1 + 25 + 0 + 64 + + + 35 + 1 + 26 + 0 + 64 + + + 45 + 1 + 27 + 0 + 64 + + + 46 + 1 + 28 + 0 + 64 + + + 36 + 1 + 29 + 0 + 64 + + + 47 + 1 + 30 + 0 + 64 + + + 48 + 1 + 31 + 0 + 64 + + + 1 + 1 + 32 + 0 + 64 + + + 37 + 1 + 33 + 0 + 64 + + + 38 + 1 + 34 + 0 + 64 + + + 2 + 1 + 35 + 0 + 64 + + + 39 + 1 + 36 + 0 + 64 + + + 40 + 1 + 37 + 0 + 64 + + + 3 + 1 + 38 + 0 + 64 + + + 4 + 1 + 39 + 0 + 64 + + + 5 + 1 + 40 + 0 + 64 + + + 6 + 1 + 41 + 0 + 64 + + + 7 + 1 + 42 + 0 + 64 + + + 8 + 1 + 43 + 0 + 64 + + + 9 + 1 + 44 + 0 + 64 + + + 10 + 1 + 45 + 0 + 64 + + + 11 + 1 + 46 + 0 + 64 + + + 12 + 1 + 47 + 0 + 64 + + + 17 + 4 + 48 + 3 + 1536 + + + 21 + 4 + 49 + 3 + 1536 + + + 25 + 4 + 50 + 3 + 1536 + + + 29 + 4 + 51 + 3 + 1536 + + + 89 + 4 + 52 + 3 + 1536 + + + 93 + 4 + 53 + 3 + 1536 + + + 81 + 4 + 54 + 3 + 1536 + + + 85 + 4 + 55 + 3 + 1536 + + + 73 + 4 + 56 + 3 + 1536 + + + 77 + 4 + 57 + 3 + 1536 + + + 65 + 4 + 58 + 3 + 1536 + + + 69 + 4 + 59 + 3 + 1536 + + + + \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/default_sku b/device/mellanox/x86_64-mlnx_msn3420-r0/default_sku new file mode 100644 index 000000000000..a572bdce4e5e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN3420 t1 diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn3420-r0/pcie.yaml new file mode 120000 index 000000000000..3dc31739f7d9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/pcie.yaml @@ -0,0 +1 @@ +../x86_64-mlnx_msn3700c-r0/pcie.yaml \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/platform.json b/device/mellanox/x86_64-mlnx_msn3420-r0/platform.json new file mode 100644 index 000000000000..da8df3b25cb7 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/platform.json @@ -0,0 +1,448 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1", + "lanes": "0", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp1"] + } + }, + "Ethernet4": { + "index": "2", + "lanes": "4", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp2"] + } + }, + "Ethernet8": { + "index": "3", + "lanes": "8", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp3"] + } + }, + "Ethernet12": { + "index": "4", + "lanes": "12", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp4"] + } + }, + "Ethernet16": { + "index": "5", + "lanes": "16", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp5"] + } + }, + "Ethernet20": { + "index": "6", + "lanes": "20", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp6"] + } + }, + "Ethernet24": { + "index": "7", + "lanes": "24", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp7"] + } + }, + "Ethernet28": { + "index": "8", + "lanes": "28", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp8"] + } + }, + "Ethernet32": { + "index": "9", + "lanes": "32", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp9"] + } + }, + "Ethernet36": { + "index": "10", + "lanes": "36", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp10"] + } + }, + "Ethernet40": { + "index": "11", + "lanes": "40", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp11"] + } + }, + "Ethernet44": { + "index": "12", + "lanes": "44", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp12"] + } + }, + "Ethernet48": { + "index": "13", + "lanes": "48", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp13"] + } + }, + "Ethernet52": { + "index": "14", + "lanes": "52", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp14"] + } + }, + "Ethernet56": { + "index": "15", + "lanes": "56", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp15"] + } + }, + "Ethernet60": { + "index": "16", + "lanes": "60", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp16"] + } + }, + "Ethernet64": { + "index": "17", + "lanes": "64", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp17"] + } + }, + "Ethernet68": { + "index": "18", + "lanes": "68", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp18"] + } + }, + "Ethernet72": { + "index": "19", + "lanes": "72", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp19"] + } + }, + "Ethernet76": { + "index": "20", + "lanes": "76", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp20"] + } + }, + "Ethernet80": { + "index": "21", + "lanes": "80", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp21"] + } + }, + "Ethernet84": { + "index": "22", + "lanes": "84", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp22"] + } + }, + "Ethernet88": { + "index": "23", + "lanes": "88", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp23"] + } + }, + "Ethernet92": { + "index": "24", + "lanes": "92", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp24"] + } + }, + "Ethernet96": { + "index": "25", + "lanes": "96", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp25"] + } + }, + "Ethernet100": { + "index": "26", + "lanes": "100", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp26"] + } + }, + "Ethernet104": { + "index": "27", + "lanes": "104", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp27"] + } + }, + "Ethernet108": { + "index": "28", + "lanes": "108", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp28"] + } + }, + "Ethernet112": { + "index": "29", + "lanes": "112", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp29"] + } + }, + "Ethernet116": { + "index": "30", + "lanes": "116", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp30"] + } + }, + "Ethernet120": { + "index": "31", + "lanes": "120", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp31"] + } + }, + "Ethernet124": { + "index": "32", + "lanes": "124", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp32"] + } + }, + "Ethernet128": { + "index": "33", + "lanes": "128", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp33"] + } + }, + "Ethernet132": { + "index": "34", + "lanes": "132", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp34"] + } + }, + "Ethernet136": { + "index": "35", + "lanes": "136", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp35"] + } + }, + "Ethernet140": { + "index": "36", + "lanes": "140", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp36"] + } + }, + "Ethernet144": { + "index": "37", + "lanes": "144", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp37"] + } + }, + "Ethernet148": { + "index": "38", + "lanes": "148", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp38"] + } + }, + "Ethernet152": { + "index": "39", + "lanes": "152", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp39"] + } + }, + "Ethernet156": { + "index": "40", + "lanes": "156", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp40"] + } + }, + "Ethernet160": { + "index": "41", + "lanes": "160", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp41"] + } + }, + "Ethernet164": { + "index": "42", + "lanes": "164", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp42"] + } + }, + "Ethernet168": { + "index": "43", + "lanes": "168", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp43"] + } + }, + "Ethernet172": { + "index": "44", + "lanes": "172", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp44"] + } + }, + "Ethernet176": { + "index": "45", + "lanes": "176", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp45"] + } + }, + "Ethernet180": { + "index": "46", + "lanes": "180", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp46"] + } + }, + "Ethernet184": { + "index": "47", + "lanes": "184", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp47"] + } + }, + "Ethernet188": { + "index": "48", + "lanes": "188", + "breakout_modes": { + "1x25G[10G,1G]" : ["etp48"] + } + }, + "Ethernet192": { + "index": "49,49,49,49", + "lanes": "192,193,194,195", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp49"], + "2x50G[40G,25G,10G,1G]": ["etp49a", "etp49b"], + "4x25G[10G,1G]": ["etp49a", "etp49b", "etp49c", "etp49d"] + } + }, + "Ethernet196": { + "index": "50,50,50,50", + "lanes": "196,197,198,199", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp50"], + "2x50G[40G,25G,10G,1G]": ["etp50a", "etp50b"], + "4x25G[10G,1G]": ["etp50a", "etp50b", "etp50c", "etp50d"] + } + }, + "Ethernet200": { + "index": "51,51,51,51", + "lanes": "200,201,202,203", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp51"], + "2x50G[40G,25G,10G,1G]": ["etp51a", "etp51b"], + "4x25G[10G,1G]": ["etp51a", "etp51b", "etp51c", "etp51d"] + } + }, + "Ethernet204": { + "index": "52,52,52,52", + "lanes": "204,205,206,207", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp52"], + "2x50G[40G,25G,10G,1G]": ["etp52a", "etp52b"], + "4x25G[10G,1G]": ["etp52a", "etp52b", "etp52c", "etp52d"] + } + }, + "Ethernet208": { + "index": "53,53,53,53", + "lanes": "208,209,210,211", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp53"], + "2x50G[40G,25G,10G,1G]": ["etp53a", "etp53b"], + "4x25G[10G,1G]": ["etp53a", "etp53b", "etp53c", "etp53d"] + } + }, + "Ethernet212": { + "index": "54,54,54,54", + "lanes": "212,213,214,215", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp54"], + "2x50G[40G,25G,10G,1G]": ["etp54a", "etp54b"], + "4x25G[10G,1G]": ["etp54a", "etp54b", "etp54c", "etp54d"] + } + }, + "Ethernet216": { + "index": "55,55,55,55", + "lanes": "216,217,218,219", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp55"], + "2x50G[40G,25G,10G,1G]": ["etp55a", "etp55b"], + "4x25G[10G,1G]": ["etp55a", "etp55b", "etp55c", "etp55d"] + } + }, + "Ethernet220": { + "index": "56,56,56,56", + "lanes": "220,221,222,223", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp56"], + "2x50G[40G,25G,10G,1G]": ["etp56a", "etp56b"], + "4x25G[10G,1G]": ["etp56a", "etp56b", "etp56c", "etp56d"] + } + }, + "Ethernet224": { + "index": "57,57,57,57", + "lanes": "224,225,226,227", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp57"], + "2x50G[40G,25G,10G,1G]": ["etp57a", "etp57b"], + "4x25G[10G,1G]": ["etp57a", "etp57b", "etp57c", "etp57d"] + } + }, + "Ethernet228": { + "index": "58,58,58,58", + "lanes": "228,229,230,231", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp58"], + "2x50G[40G,25G,10G,1G]": ["etp58a", "etp58b"], + "4x25G[10G,1G]": ["etp58a", "etp58b", "etp58c", "etp58d"] + } + }, + "Ethernet232": { + "index": "59,59,59,59", + "lanes": "232,233,234,235", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp59"], + "2x50G[40G,25G,10G,1G]": ["etp59a", "etp59b"], + "4x25G[10G,1G]": ["etp59a", "etp59b", "etp59c", "etp59d"] + } + }, + "Ethernet236": { + "index": "60,60,60,60", + "lanes": "236,237,238,239", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp60"], + "2x50G[40G,25G,10G,1G]": ["etp60a", "etp60b"], + "4x25G[10G,1G]": ["etp60a", "etp60b", "etp60c", "etp60d"] + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn3420-r0/platform_components.json new file mode 100644 index 000000000000..9b5cceae9fc8 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/platform_components.json @@ -0,0 +1,14 @@ +{ + "chassis": { + "MSN3420": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn3420-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-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_msn3420-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn3420-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-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_msn3420-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn3420-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-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_msn3420-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn3420-r0/plugins/psuutil.py new file mode 120000 index 000000000000..9f724238a8d5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-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_msn3420-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn3420-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-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_msn3420-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn3420-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-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_msn3420-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn3420-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-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_msn3420-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn3420-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-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_msn3420-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn3420-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-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_msn3420-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn3420-r0/sensors.conf new file mode 100644 index 000000000000..f31cbe7adbc7 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/sensors.conf @@ -0,0 +1,121 @@ +################################################################################ +# Copyright (c) 2020 Mellanox Technologies +# +# Platform specific sensors config for SN3420 +################################################################################ + +# 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 "xdpe12284-i2c-*-62" + label in1 "PMIC-1 PSU 12V Rail (in1)" + label in2 "PMIC-1 PSU 12V Rail (in2)" + label in3 "PMIC-1 VCORE 0.8V Rail (out)" + label in4 "PMIC-1 COMEX 1.2V Rail (out)" + label temp1 "PMIC-1 Temp 1" + label temp2 "PMIC-1 Temp 2" + label power1 "PMIC-1 PSU 12V Rail Pwr (in1)" + label power2 "PMIC-1 PSU 12V Rail Pwr (in2)" + label power3 "PMIC-1 VCORE 0.8V Rail Pwr (out)" + label power4 "PMIC-1 COMEX 1.2V Rail Pwr (out)" + label curr1 "PMIC-1 PSU 12V Rail Curr (in1)" + label curr2 "PMIC-1 PSU 12V Rail Curr (in2)" + label curr3 "PMIC-1 VCORE 0.8V Rail Curr (out)" + label curr4 "PMIC-1 COMEX 1.2V Rail Curr (out)" + chip "xdpe12284-i2c-*-64" + label in1 "PMIC-2 PSU 12V Rail (in1)" + label in2 "PMIC-2 PSU 12V Rail (in2)" + label in3 "PMIC-2 1.8V Rail (out)" + ignore in4 + label temp1 "PMIC-2 Temp 1" + ignore temp2 + label power1 "PMIC-2 PSU 12V Rail Pwr (in1)" + label power2 "PMIC-2 PSU 12V Rail Pwr (in2)" + label power3 "PMIC-2 1.8V Rail Pwr (out)" + ignore power4 + label curr1 "PMIC-2 PSU 12V Rail Curr (in1)" + label curr2 "PMIC-2 PSU 12V Rail Curr (in2)" + label curr3 "PMIC-2 1.8V Rail Curr (out)" + ignore curr4 + +bus "i2c-15" "i2c-1-mux (chan_id 6)" + chip "tps53679-i2c-*-58" + label in1 "PMIC-3 PSU 12V Rail (in1)" + label in2 "PMIC-3 PSU 12V Rail (in2)" + label in3 "PMIC-3 COMEX 1.8V Rail (out)" + label in4 "PMIC-3 COMEX 1.05V Rail (out)" + label temp1 "PMIC-3 Temp 1" + label temp2 "PMIC-3 Temp 2" + label power1 "PMIC-3 COMEX 1.8V Rail Pwr (out)" + label power2 "PMIC-3 COMEX 1.05V Rail Pwr (out)" + label curr1 "PMIC-3 COMEX 1.8V Rail Curr (out)" + label curr2 "PMIC-3 COMEX 1.05V Rail Curr (out)" + chip "tps53679-i2c-*-61" + label in1 "PMIC-4 PSU 12V Rail (in1)" + label in2 "PMIC-4 PSU 12V Rail (in2)" + label in3 "PMIC-4 COMEX 1.2V Rail (out)" + ignore in4 + label temp1 "PMIC-4 Temp 1" + label temp2 "PMIC-4 Temp 2" + label power1 "PMIC-4 COMEX 1.2V Rail Pwr (out)" + ignore power2 + label curr1 "PMIC-4 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 220V Rail (in)" + label in2 "PSU-1 12V Rail (out)" + label fan1 "PSU-1 Fan 1" + label temp1 "PSU-1 Temp 1" + label temp2 "PSU-1 Temp 2" + label temp3 "PSU-1 Temp 3" + label power1 "PSU-1 220V Rail Pwr (in)" + label power2 "PSU-1 12V Rail Pwr (out)" + label curr1 "PSU-1 220V Rail Curr (in)" + label curr2 "PSU-1 12V Rail Curr (out)" + chip "dps460-i2c-*-59" + label in1 "PSU-2 220V Rail (in)" + label in2 "PSU-2 12V Rail (out)" + label fan1 "PSU-2 Fan 1" + label temp1 "PSU-2 Temp 1" + label temp2 "PSU-2 Temp 2" + label temp3 "PSU-2 Temp 3" + label power1 "PSU-2 220V Rail Pwr (in)" + label power2 "PSU-2 12V Rail Pwr (out)" + label curr1 "PSU-2 220V Rail Curr (in)" + label curr2 "PSU-2 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_msn3420-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn3420-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..98df66c27ca5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn3420-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/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_msn3700-r0/ACS-MSN3700/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..035a14177705 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t0.j2 @@ -0,0 +1,110 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '14542848' %} +{% set ingress_lossy_pool_size = '14542848' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '14542848' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossy_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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":"9216", + "dynamic_th":"7" + }, + "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_msn3700-r0/ACS-MSN3700/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..1032b455b8f1 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_defaults_t1.j2 @@ -0,0 +1,110 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '11622400' %} +{% set ingress_lossy_pool_size = '11622400' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '11622400' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossy_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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":"9216", + "dynamic_th":"7" + }, + "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_msn3700-r0/ACS-MSN3700/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/hwsku.json b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/hwsku.json new file mode 100644 index 000000000000..8d9471e141fb --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/pg_profile_lookup.ini new file mode 100644 index 000000000000..2e420e15871a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/pg_profile_lookup.ini @@ -0,0 +1,20 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 52224 19456 32768 0 + 25000 5m 52224 19456 32768 0 + 40000 5m 53248 19456 33792 0 + 50000 5m 53248 19456 33792 0 + 100000 5m 53248 19456 33792 0 + 200000 5m 55296 19456 35840 0 + 10000 40m 53248 19456 33792 0 + 25000 40m 55296 19456 35840 0 + 40000 40m 57344 19456 37888 0 + 50000 40m 58368 19456 38912 0 + 100000 40m 63488 19456 44032 0 + 200000 40m 74752 19456 55296 0 + 10000 300m 60416 19456 40960 0 + 25000 300m 73728 19456 54272 0 + 40000 300m 86016 19456 66560 0 + 50000 300m 95232 19456 75776 0 + 100000 300m 137216 19456 117760 0 + 200000 300m 223232 19456 203776 0 diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/port_config.ini b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/port_config.ini new file mode 120000 index 000000000000..73505f3a0baf --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/port_config.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/qos.json.j2 new file mode 120000 index 000000000000..eccf286dc879 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/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_msn3700-r0/ACS-MSN3700/sai.profile b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/sai.profile new file mode 100644 index 000000000000..4907e971a2dd --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_3700.xml 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 new file mode 100644 index 000000000000..a7ac42950668 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/ACS-MSN3700/sai_3700.xml @@ -0,0 +1,246 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 32 + + + + + 1 + 4 + 16 + + + 3 + + + 1536 + + + 5 + 4 + 17 + 3 + 1536 + + + 9 + 4 + 18 + 3 + 1536 + + + 13 + 4 + 19 + 3 + 1536 + + + 17 + 4 + 20 + 3 + 1536 + + + 21 + 4 + 21 + 3 + 1536 + + + 25 + 4 + 22 + 3 + 1536 + + + 29 + 4 + 23 + 3 + 1536 + + + 33 + 4 + 14 + 3 + 1536 + + + 37 + 4 + 15 + 3 + 1536 + + + 41 + 4 + 12 + 3 + 1536 + + + 45 + 4 + 13 + 3 + 1536 + + + 49 + 4 + 10 + 3 + 1536 + + + 53 + 4 + 11 + 3 + 1536 + + + 57 + 4 + 8 + 3 + 1536 + + + 61 + 4 + 9 + 3 + 1536 + + + 65 + 4 + 30 + 3 + 1536 + + + 69 + 4 + 31 + 3 + 1536 + + + 73 + 4 + 28 + 3 + 1536 + + + 77 + 4 + 29 + 3 + 1536 + + + 81 + 4 + 26 + 3 + 1536 + + + 85 + 4 + 27 + 3 + 1536 + + + 89 + 4 + 24 + 3 + 1536 + + + 93 + 4 + 25 + 3 + 1536 + + + 97 + 4 + 0 + 3 + 1536 + + + 101 + 4 + 1 + 3 + 1536 + + + 105 + 4 + 2 + 3 + 1536 + + + 109 + 4 + 3 + 3 + 1536 + + + 113 + 4 + 4 + 3 + 1536 + + + 117 + 4 + 5 + 3 + 1536 + + + 121 + 4 + 6 + 3 + 1536 + + + 125 + 4 + 7 + 3 + 1536 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/default_sku b/device/mellanox/x86_64-mlnx_msn3700-r0/default_sku new file mode 100644 index 000000000000..5385adf06aca --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN3700 t1 diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn3700-r0/pcie.yaml new file mode 100644 index 000000000000..947e9f43f8b3 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/pcie.yaml @@ -0,0 +1,420 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 6f00 + name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 6f02 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '01' + fn: '1' + id: 6f03 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 6f04 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '2' + id: 6f06 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 6f08 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '03' + fn: '2' + id: 6f0a + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '05' + fn: '0' + id: 6f28 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Map/VTd_Misc/System Management (rev 03)' +- bus: '00' + dev: '05' + fn: '1' + id: 6f29 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO Hot Plug (rev 03)' +- bus: '00' + dev: '05' + fn: '2' + id: 6f2a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO RAS/Control Status/Global Errors (rev 03)' +- bus: '00' + dev: '05' + fn: '4' + id: 6f2c + name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev + 03)' +- bus: '00' + dev: '14' + fn: '0' + id: 8c31 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + xHCI (rev 05)' +- bus: '00' + dev: 1c + fn: '0' + id: 8c10 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #1 (rev d5)' +- bus: '00' + dev: 1c + fn: '7' + id: 8c1e + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #8 (rev d5)' +- bus: '00' + dev: 1d + fn: '0' + id: 8c26 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + EHCI #1 (rev 05)' +- bus: '00' + dev: 1f + fn: '0' + id: 8c54 + name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard + SKU LPC Controller (rev 05)' +- bus: '00' + dev: 1f + fn: '2' + id: 8c02 + name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port + SATA Controller 1 [AHCI mode] (rev 05)' +- bus: '00' + dev: 1f + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller + (rev 05)' +- bus: '03' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '03' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '03' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '03' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '06' + dev: '00' + fn: '0' + id: cf6c + name: 'Ethernet controller: Mellanox Technologies MT53100 [Spectrum-2, 64 x 100GbE + switch]' +- bus: 08 + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: ff + dev: 0b + fn: '0' + id: 6f81 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '1' + id: 6f36 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '2' + id: 6f37 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '3' + id: 6f76 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link Debug (rev 03)' +- bus: ff + dev: 0c + fn: '0' + id: 6fe0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '1' + id: 6fe1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '2' + id: 6fe2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '3' + id: 6fe3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '0' + id: 6ff8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '4' + id: 6ffc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '5' + id: 6ffd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '6' + id: 6ffe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: '10' + fn: '0' + id: 6f1d + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '1' + id: 6f34 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '5' + id: 6f1e + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '6' + id: 6f7d + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '7' + id: 6f1f + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '12' + fn: '0' + id: 6fa0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '12' + fn: '1' + id: 6f30 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '13' + fn: '0' + id: 6fa8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '1' + id: 6f71 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '2' + id: 6faa + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '3' + id: 6fab + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '4' + id: 6fac + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '5' + id: 6fad + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '6' + id: 6fae + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Broadcast (rev 03)' +- bus: ff + dev: '13' + fn: '7' + id: 6faf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Global Broadcast (rev 03)' +- bus: ff + dev: '14' + fn: '0' + id: 6fb0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '1' + id: 6fb1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '2' + id: 6fb2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Error (rev 03)' +- bus: ff + dev: '14' + fn: '3' + id: 6fb3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Error (rev 03)' +- bus: ff + dev: '14' + fn: '4' + id: 6fbc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '5' + id: 6fbd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '6' + id: 6fbe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '7' + id: 6fbf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '15' + fn: '0' + id: 6fb4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '1' + id: 6fb5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '2' + id: 6fb6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Error (rev 03)' +- bus: ff + dev: '15' + fn: '3' + id: 6fb7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Error (rev 03)' +- bus: ff + dev: 1e + fn: '0' + id: 6f98 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '1' + id: 6f99 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '2' + id: 6f9a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '3' + id: 6fc0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '4' + id: 6f9c + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '0' + id: 6f88 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '2' + id: 6f8a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/platform.json b/device/mellanox/x86_64-mlnx_msn3700-r0/platform.json new file mode 100644 index 000000000000..1ab03932bb13 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/platform.json @@ -0,0 +1,292 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp1"], + "2x100G[50G,40G,25G,10G,1G]": ["etp1a", "etp1b"], + "4x50G[40G,25G,10G,1G]": ["etp1a", "etp1b", "etp1c", "etp1d"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp2"], + "2x100G[50G,40G,25G,10G,1G]": ["etp2a", "etp2b"], + "4x50G[40G,25G,10G,1G]": ["etp2a", "etp2b", "etp2c", "etp2d"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp3"], + "2x100G[50G,40G,25G,10G,1G]": ["etp3a", "etp3b"], + "4x50G[40G,25G,10G,1G]": ["etp3a", "etp3b", "etp3c", "etp3d"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp4"], + "2x100G[50G,40G,25G,10G,1G]": ["etp4a", "etp4b"], + "4x50G[40G,25G,10G,1G]": ["etp4a", "etp4b", "etp4c", "etp4d"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp5"], + "2x100G[50G,40G,25G,10G,1G]": ["etp5a", "etp5b"], + "4x50G[40G,25G,10G,1G]": ["etp5a", "etp5b", "etp5c", "etp5d"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp6"], + "2x100G[50G,40G,25G,10G,1G]": ["etp6a", "etp6b"], + "4x50G[40G,25G,10G,1G]": ["etp6a", "etp6b", "etp6c", "etp6d"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp7"], + "2x100G[50G,40G,25G,10G,1G]": ["etp7a", "etp7b"], + "4x50G[40G,25G,10G,1G]": ["etp7a", "etp7b", "etp7c", "etp7d"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp8"], + "2x100G[50G,40G,25G,10G,1G]": ["etp8a", "etp8b"], + "4x50G[40G,25G,10G,1G]": ["etp8a", "etp8b", "etp8c", "etp8d"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp9"], + "2x100G[50G,40G,25G,10G,1G]": ["etp9a", "etp9b"], + "4x50G[40G,25G,10G,1G]": ["etp9a", "etp9b", "etp9c", "etp9d"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp10"], + "2x100G[50G,40G,25G,10G,1G]": ["etp10a", "etp10b"], + "4x50G[40G,25G,10G,1G]": ["etp10a", "etp10b", "etp10c", "etp10d"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp11"], + "2x100G[50G,40G,25G,10G,1G]": ["etp11a", "etp11b"], + "4x50G[40G,25G,10G,1G]": ["etp11a", "etp11b", "etp11c", "etp11d"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp12"], + "2x100G[50G,40G,25G,10G,1G]": ["etp12a", "etp12b"], + "4x50G[40G,25G,10G,1G]": ["etp12a", "etp12b", "etp12c", "etp12d"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp13"], + "2x100G[50G,40G,25G,10G,1G]": ["etp13a", "etp13b"], + "4x50G[40G,25G,10G,1G]": ["etp13a", "etp13b", "etp13c", "etp13d"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp14"], + "2x100G[50G,40G,25G,10G,1G]": ["etp14a", "etp14b"], + "4x50G[40G,25G,10G,1G]": ["etp14a", "etp14b", "etp14c", "etp14d"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp15"], + "2x100G[50G,40G,25G,10G,1G]": ["etp15a", "etp15b"], + "4x50G[40G,25G,10G,1G]": ["etp15a", "etp15b", "etp15c", "etp15d"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp16"], + "2x100G[50G,40G,25G,10G,1G]": ["etp16a", "etp16b"], + "4x50G[40G,25G,10G,1G]": ["etp16a", "etp16b", "etp16c", "etp16d"] + } + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "64,65,66,67", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp17"], + "2x100G[50G,40G,25G,10G,1G]": ["etp17a", "etp17b"], + "4x50G[40G,25G,10G,1G]": ["etp17a", "etp17b", "etp17c", "etp17d"] + } + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "68,69,70,71", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp18"], + "2x100G[50G,40G,25G,10G,1G]": ["etp18a", "etp18b"], + "4x50G[40G,25G,10G,1G]": ["etp18a", "etp18b", "etp18c", "etp18d"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp19"], + "2x100G[50G,40G,25G,10G,1G]": ["etp19a", "etp19b"], + "4x50G[40G,25G,10G,1G]": ["etp19a", "etp19b", "etp19c", "etp19d"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp20"], + "2x100G[50G,40G,25G,10G,1G]": ["etp20a", "etp20b"], + "4x50G[40G,25G,10G,1G]": ["etp20a", "etp20b", "etp20c", "etp20d"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp21"], + "2x100G[50G,40G,25G,10G,1G]": ["etp21a", "etp21b"], + "4x50G[40G,25G,10G,1G]": ["etp21a", "etp21b", "etp21c", "etp21d"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp22"], + "2x100G[50G,40G,25G,10G,1G]": ["etp22a", "etp22b"], + "4x50G[40G,25G,10G,1G]": ["etp22a", "etp22b", "etp22c", "etp22d"] + } + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "88,89,90,91", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp23"], + "2x100G[50G,40G,25G,10G,1G]": ["etp23a", "etp23b"], + "4x50G[40G,25G,10G,1G]": ["etp23a", "etp23b", "etp23c", "etp23d"] + } + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "92,93,94,95", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp24"], + "2x100G[50G,40G,25G,10G,1G]": ["etp24a", "etp24b"], + "4x50G[40G,25G,10G,1G]": ["etp24a", "etp24b", "etp24c", "etp24d"] + } + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "96,97,98,99", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp25"], + "2x100G[50G,40G,25G,10G,1G]": ["etp25a", "etp25b"], + "4x50G[40G,25G,10G,1G]": ["etp25a", "etp25b", "etp25c", "etp25d"] + } + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "100,101,102,103", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp26"], + "2x100G[50G,40G,25G,10G,1G]": ["etp26a", "etp26b"], + "4x50G[40G,25G,10G,1G]": ["etp26a", "etp26b", "etp26c", "etp26d"] + } + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "104,105,106,107", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp27"], + "2x100G[50G,40G,25G,10G,1G]": ["etp27a", "etp27b"], + "4x50G[40G,25G,10G,1G]": ["etp27a", "etp27b", "etp27c", "etp27d"] + } + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "108,109,110,111", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp28"], + "2x100G[50G,40G,25G,10G,1G]": ["etp28a", "etp28b"], + "4x50G[40G,25G,10G,1G]": ["etp28a", "etp28b", "etp28c", "etp28d"] + } + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "112,113,114,115", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp29"], + "2x100G[50G,40G,25G,10G,1G]": ["etp29a", "etp29b"], + "4x50G[40G,25G,10G,1G]": ["etp29a", "etp29b", "etp29c", "etp29d"] + } + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "116,117,118,119", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp30"], + "2x100G[50G,40G,25G,10G,1G]": ["etp30a", "etp30b"], + "4x50G[40G,25G,10G,1G]": ["etp30a", "etp30b", "etp30c", "etp30d"] + } + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "120,121,122,123", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp31"], + "2x100G[50G,40G,25G,10G,1G]": ["etp31a", "etp31b"], + "4x50G[40G,25G,10G,1G]": ["etp31a", "etp31b", "etp31c", "etp31d"] + } + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "124,125,126,127", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp32"], + "2x100G[50G,40G,25G,10G,1G]": ["etp32a", "etp32b"], + "4x50G[40G,25G,10G,1G]": ["etp32a", "etp32b", "etp32c", "etp32d"] + } + } + } +} 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..6ca284d3f341 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/platform_components.json @@ -0,0 +1,14 @@ +{ + "chassis": { + "MSN3700": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn3700-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-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_msn3700-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn3700-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-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_msn3700-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn3700-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-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_msn3700-r0/plugins/fanutil.py b/device/mellanox/x86_64-mlnx_msn3700-r0/plugins/fanutil.py new file mode 120000 index 000000000000..82ea06ef915f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/plugins/fanutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/fanutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn3700-r0/plugins/psuutil.py new file mode 120000 index 000000000000..9f724238a8d5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-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_msn3700-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn3700-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-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_msn3700-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn3700-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-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_msn3700-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn3700-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-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_msn3700-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn3700-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-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_msn3700-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn3700-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-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_msn3700-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn3700-r0/sensors.conf new file mode 100644 index 000000000000..28a889aa27d2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/sensors.conf @@ -0,0 +1,120 @@ +################################################################################ +# Copyright (c) 2019 Mellanox Technologies +# +# Platform specific sensors config for SN3700 +################################################################################ + +# 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-*-70" + label in1 "PMIC-1 PSU 12V Rail (in1)" + label in2 "PMIC-1 PSU 12V Rail (in2)" + label in3 "PMIC-1 ASIC 0.8V VCORE Rail (out)" + label in4 "PMIC-1 ASIC 1.2V Rail (out)" + label temp1 "PMIC-1 Temp 1" + label temp2 "PMIC-1 Temp 2" + label power1 "PMIC-1 ASIC 0.8V VCORE Rail Pwr (out)" + label power2 "PMIC-1 ASIC 1.2V Rail Pwr (out)" + label curr1 "PMIC-1 ASIC 0.8V VCORE Rail Curr (out)" + label curr2 "PMIC-1 ASIC 1.2V Rail Curr (out)" + chip "tps53679-i2c-*-71" + label in1 "PMIC-2 PSU 12V Rail (in1)" + label in2 "PMIC-2 PSU 12V Rail (in2)" + label in3 "PMIC-2 ASIC 3.3V Rail (out)" + compute in3 (1.5)*@, @/(1.5) + label in4 "PMIC-2 ASIC 1.8V Rail (out)" + label temp1 "PMIC-2 Temp 1" + label temp2 "PMIC-2 Temp 2" + label power1 "PMIC-2 ASIC 3.3V Rail Pwr (out)" + label power2 "PMIC-2 ASIC 1.8V Rail Pwr (out)" + label curr1 "PMIC-2 ASIC 3.3V Rail Curr (out)" + label curr2 "PMIC-2 ASIC 1.8V Rail Curr (out)" + +bus "i2c-15" "i2c-1-mux (chan_id 6)" + chip "tps53679-i2c-*-58" + label in1 "PMIC-3 PSU 12V Rail (in1)" + label in2 "PMIC-3 PSU 12V Rail (in2)" + label in3 "PMIC-3 COMEX 1.8V Rail (out)" + label in4 "PMIC-3 COMEX 1.05V Rail (out)" + label temp1 "PMIC-3 Temp 1" + label temp2 "PMIC-3 Temp 2" + label power1 "PMIC-3 COMEX 1.8V Rail Pwr (out)" + label power2 "PMIC-3 COMEX 1.05V Rail Pwr (out)" + label curr1 "PMIC-3 COMEX 1.8V Rail Curr (out)" + label curr2 "PMIC-3 COMEX 1.05V Rail Curr (out)" + chip "tps53679-i2c-*-61" + label in1 "PMIC-4 PSU 12V Rail (in1)" + label in2 "PMIC-4 PSU 12V Rail (in2)" + label in3 "PMIC-4 COMEX 1.2V Rail (out)" + ignore in4 + label temp1 "PMIC-4 Temp 1" + label temp2 "PMIC-4 Temp 2" + label power1 "PMIC-4 COMEX 1.2V Rail Pwr (out)" + ignore power2 + label curr1 "PMIC-4 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 220V Rail (in)" + ignore in2 + label in3 "PSU-1 12V Rail (out)" + label fan1 "PSU-1 Fan 1" + ignore fan2 + ignore fan3 + label temp1 "PSU-1 Temp 1" + label temp2 "PSU-1 Temp 2" + label temp3 "PSU-1 Temp 3" + label power1 "PSU-1 220V Rail Pwr (in)" + label power2 "PSU-1 12V Rail Pwr (out)" + label curr1 "PSU-1 220V Rail Curr (in)" + label curr2 "PSU-1 12V Rail Curr (out)" + chip "dps460-i2c-*-59" + label in1 "PSU-2 220V Rail (in)" + ignore in2 + label in3 "PSU-2 12V Rail (out)" + label fan1 "PSU-2 Fan 1" + ignore fan2 + ignore fan3 + label temp1 "PSU-2 Temp 1" + label temp2 "PSU-2 Temp 2" + label temp3 "PSU-2 Temp 3" + label power1 "PSU-2 220V Rail Pwr (in)" + label power2 "PSU-2 12V Rail Pwr (out)" + label curr1 "PSU-2 220V Rail Curr (in)" + label curr2 "PSU-2 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_msn3700-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn3700-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..98df66c27ca5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn3700-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700_simx-r0/ACS-MSN3700 b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/ACS-MSN3700 new file mode 120000 index 000000000000..06a1a919f531 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/ACS-MSN3700 @@ -0,0 +1 @@ +../x86_64-mlnx_msn3700-r0/ACS-MSN3700 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700_simx-r0/default_sku b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/default_sku new file mode 120000 index 000000000000..e1d1f987772a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/default_sku @@ -0,0 +1 @@ +../x86_64-mlnx_msn3700-r0/default_sku \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700_simx-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/platform_reboot new file mode 120000 index 000000000000..dfaf53417665 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700_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_msn3700_simx-r0/plugins b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/plugins new file mode 120000 index 000000000000..f6f09c83f7d4 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/plugins @@ -0,0 +1 @@ +../x86_64-mlnx_msn3700-r0/plugins \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700_simx-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..dd83c2db12c5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/pmon_daemon_control.json @@ -0,0 +1,7 @@ +{ + "skip_ledd": true, + "skip_xcvrd": true, + "skip_psud": true, + "skip_pcied": true, + "skip_thermalctld": true +} diff --git a/device/mellanox/x86_64-mlnx_msn3700_simx-r0/syseeprom.hex b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/syseeprom.hex new file mode 100644 index 000000000000..b50ffa5a0231 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700_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/mellanox/x86_64-mlnx_msn3700_simx-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..42fe945344c9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700_simx-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700_simx-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/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_msn3700c-r0/ACS-MSN3700C/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..85f0b6b6b354 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../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_msn3700c-r0/ACS-MSN3700C/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..3bb496a5103b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../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_msn3700c-r0/ACS-MSN3700C/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/hwsku.json b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/hwsku.json new file mode 100644 index 000000000000..cac9d1d14da2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/pg_profile_lookup.ini new file mode 120000 index 000000000000..252ae8d4149b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../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_msn3700c-r0/ACS-MSN3700C/port_config.ini b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/port_config.ini new file mode 120000 index 000000000000..73505f3a0baf --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/port_config.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/qos.json.j2 new file mode 120000 index 000000000000..eccf286dc879 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/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_msn3700c-r0/ACS-MSN3700C/sai.profile b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/sai.profile new file mode 100644 index 000000000000..46750fb2e07b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_3700c.xml diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/sai_3700c.xml b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/sai_3700c.xml new file mode 120000 index 000000000000..58740b9776da --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/sai_3700c.xml @@ -0,0 +1 @@ +../../x86_64-mlnx_msn3700-r0/ACS-MSN3700/sai_3700.xml \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/default_sku b/device/mellanox/x86_64-mlnx_msn3700c-r0/default_sku new file mode 100644 index 000000000000..12f543e1cc80 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN3700C t1 diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn3700c-r0/pcie.yaml new file mode 100644 index 000000000000..21c48fe64008 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/pcie.yaml @@ -0,0 +1,408 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 6f00 + name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 6f02 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '01' + fn: '1' + id: 6f03 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 6f04 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '2' + id: 6f06 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 6f08 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '03' + fn: '2' + id: 6f0a + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '05' + fn: '0' + id: 6f28 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Map/VTd_Misc/System Management (rev 03)' +- bus: '00' + dev: '05' + fn: '1' + id: 6f29 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO Hot Plug (rev 03)' +- bus: '00' + dev: '05' + fn: '2' + id: 6f2a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO RAS/Control Status/Global Errors (rev 03)' +- bus: '00' + dev: '05' + fn: '4' + id: 6f2c + name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev + 03)' +- bus: '00' + dev: '14' + fn: '0' + id: 8c31 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + xHCI (rev 05)' +- bus: '00' + dev: 1c + fn: '0' + id: 8c10 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #1 (rev d5)' +- bus: '00' + dev: 1c + fn: '7' + id: 8c1e + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #8 (rev d5)' +- bus: '00' + dev: 1d + fn: '0' + id: 8c26 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + EHCI #1 (rev 05)' +- bus: '00' + dev: 1f + fn: '0' + id: 8c54 + name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard + SKU LPC Controller (rev 05)' +- bus: '00' + dev: 1f + fn: '2' + id: 8c02 + name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port + SATA Controller 1 [AHCI mode] (rev 05)' +- bus: '00' + dev: 1f + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller + (rev 05)' +- bus: '03' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '03' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '03' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '03' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '06' + dev: '00' + fn: '0' + id: cf6c + name: 'Ethernet controller: Mellanox Technologies MT53100 [Spectrum-2, 64 x 100GbE + switch]' +- bus: 08 + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: ff + dev: 0b + fn: '0' + id: 6f81 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '1' + id: 6f36 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '2' + id: 6f37 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '3' + id: 6f76 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link Debug (rev 03)' +- bus: ff + dev: 0c + fn: '0' + id: 6fe0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '1' + id: 6fe1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '0' + id: 6ff8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '4' + id: 6ffc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '5' + id: 6ffd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '6' + id: 6ffe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: '10' + fn: '0' + id: 6f1d + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '1' + id: 6f34 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '5' + id: 6f1e + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '6' + id: 6f7d + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '7' + id: 6f1f + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '12' + fn: '0' + id: 6fa0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '12' + fn: '1' + id: 6f30 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '13' + fn: '0' + id: 6fa8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '1' + id: 6f71 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '2' + id: 6faa + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '3' + id: 6fab + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '4' + id: 6fac + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '5' + id: 6fad + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '6' + id: 6fae + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Broadcast (rev 03)' +- bus: ff + dev: '13' + fn: '7' + id: 6faf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Global Broadcast (rev 03)' +- bus: ff + dev: '14' + fn: '0' + id: 6fb0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '1' + id: 6fb1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '2' + id: 6fb2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Error (rev 03)' +- bus: ff + dev: '14' + fn: '3' + id: 6fb3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Error (rev 03)' +- bus: ff + dev: '14' + fn: '4' + id: 6fbc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '5' + id: 6fbd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '6' + id: 6fbe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '7' + id: 6fbf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '15' + fn: '0' + id: 6fb4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '1' + id: 6fb5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '2' + id: 6fb6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Error (rev 03)' +- bus: ff + dev: '15' + fn: '3' + id: 6fb7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Error (rev 03)' +- bus: ff + dev: 1e + fn: '0' + id: 6f98 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '1' + id: 6f99 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '2' + id: 6f9a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '3' + id: 6fc0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '4' + id: 6f9c + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '0' + id: 6f88 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '2' + id: 6f8a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/platform.json b/device/mellanox/x86_64-mlnx_msn3700c-r0/platform.json new file mode 100644 index 000000000000..0a39adfa26a4 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/platform.json @@ -0,0 +1,292 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp1"], + "2x50G[40G,25G,10G,1G]": ["etp1a", "etp1b"], + "4x25G[10G,1G]": ["etp1a", "etp1b", "etp1c", "etp1d"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp2"], + "2x50G[40G,25G,10G,1G]": ["etp2a", "etp2b"], + "4x25G[10G,1G]": ["etp2a", "etp2b", "etp2c", "etp2d"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp3"], + "2x50G[40G,25G,10G,1G]": ["etp3a", "etp3b"], + "4x25G[10G,1G]": ["etp3a", "etp3b", "etp3c", "etp3d"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp4"], + "2x50G[40G,25G,10G,1G]": ["etp4a", "etp4b"], + "4x25G[10G,1G]": ["etp4a", "etp4b", "etp4c", "etp4d"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp5"], + "2x50G[40G,25G,10G,1G]": ["etp5a", "etp5b"], + "4x25G[10G,1G]": ["etp5a", "etp5b", "etp5c", "etp5d"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp6"], + "2x50G[40G,25G,10G,1G]": ["etp6a", "etp6b"], + "4x25G[10G,1G]": ["etp6a", "etp6b", "etp6c", "etp6d"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp7"], + "2x50G[40G,25G,10G,1G]": ["etp7a", "etp7b"], + "4x25G[10G,1G]": ["etp7a", "etp7b", "etp7c", "etp7d"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp8"], + "2x50G[40G,25G,10G,1G]": ["etp8a", "etp8b"], + "4x25G[10G,1G]": ["etp8a", "etp8b", "etp8c", "etp8d"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp9"], + "2x50G[40G,25G,10G,1G]": ["etp9a", "etp9b"], + "4x25G[10G,1G]": ["etp9a", "etp9b", "etp9c", "etp9d"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp10"], + "2x50G[40G,25G,10G,1G]": ["etp10a", "etp10b"], + "4x25G[10G,1G]": ["etp10a", "etp10b", "etp10c", "etp10d"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp11"], + "2x50G[40G,25G,10G,1G]": ["etp11a", "etp11b"], + "4x25G[10G,1G]": ["etp11a", "etp11b", "etp11c", "etp11d"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp12"], + "2x50G[40G,25G,10G,1G]": ["etp12a", "etp12b"], + "4x25G[10G,1G]": ["etp12a", "etp12b", "etp12c", "etp12d"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp13"], + "2x50G[40G,25G,10G,1G]": ["etp13a", "etp13b"], + "4x25G[10G,1G]": ["etp13a", "etp13b", "etp13c", "etp13d"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp14"], + "2x50G[40G,25G,10G,1G]": ["etp14a", "etp14b"], + "4x25G[10G,1G]": ["etp14a", "etp14b", "etp14c", "etp14d"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp15"], + "2x50G[40G,25G,10G,1G]": ["etp15a", "etp15b"], + "4x25G[10G,1G]": ["etp15a", "etp15b", "etp15c", "etp15d"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp16"], + "2x50G[40G,25G,10G,1G]": ["etp16a", "etp16b"], + "4x25G[10G,1G]": ["etp16a", "etp16b", "etp16c", "etp16d"] + } + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "64,65,66,67", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp17"], + "2x50G[40G,25G,10G,1G]": ["etp17a", "etp17b"], + "4x25G[10G,1G]": ["etp17a", "etp17b", "etp17c", "etp17d"] + } + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "68,69,70,71", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp18"], + "2x50G[40G,25G,10G,1G]": ["etp18a", "etp18b"], + "4x25G[10G,1G]": ["etp18a", "etp18b", "etp18c", "etp18d"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp19"], + "2x50G[40G,25G,10G,1G]": ["etp19a", "etp19b"], + "4x25G[10G,1G]": ["etp19a", "etp19b", "etp19c", "etp19d"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp20"], + "2x50G[40G,25G,10G,1G]": ["etp20a", "etp20b"], + "4x25G[10G,1G]": ["etp20a", "etp20b", "etp20c", "etp20d"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp21"], + "2x50G[40G,25G,10G,1G]": ["etp21a", "etp21b"], + "4x25G[10G,1G]": ["etp21a", "etp21b", "etp21c", "etp21d"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp22"], + "2x50G[40G,25G,10G,1G]": ["etp22a", "etp22b"], + "4x25G[10G,1G]": ["etp22a", "etp22b", "etp22c", "etp22d"] + } + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "88,89,90,91", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp23"], + "2x50G[40G,25G,10G,1G]": ["etp23a", "etp23b"], + "4x25G[10G,1G]": ["etp23a", "etp23b", "etp23c", "etp23d"] + } + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "92,93,94,95", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp24"], + "2x50G[40G,25G,10G,1G]": ["etp24a", "etp24b"], + "4x25G[10G,1G]": ["etp24a", "etp24b", "etp24c", "etp24d"] + } + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "96,97,98,99", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp25"], + "2x50G[40G,25G,10G,1G]": ["etp25a", "etp25b"], + "4x25G[10G,1G]": ["etp25a", "etp25b", "etp25c", "etp25d"] + } + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "100,101,102,103", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp26"], + "2x50G[40G,25G,10G,1G]": ["etp26a", "etp26b"], + "4x25G[10G,1G]": ["etp26a", "etp26b", "etp26c", "etp26d"] + } + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "104,105,106,107", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp27"], + "2x50G[40G,25G,10G,1G]": ["etp27a", "etp27b"], + "4x25G[10G,1G]": ["etp27a", "etp27b", "etp27c", "etp27d"] + } + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "108,109,110,111", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp28"], + "2x50G[40G,25G,10G,1G]": ["etp28a", "etp28b"], + "4x25G[10G,1G]": ["etp28a", "etp28b", "etp28c", "etp28d"] + } + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "112,113,114,115", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp29"], + "2x50G[40G,25G,10G,1G]": ["etp29a", "etp29b"], + "4x25G[10G,1G]": ["etp29a", "etp29b", "etp29c", "etp29d"] + } + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "116,117,118,119", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp30"], + "2x50G[40G,25G,10G,1G]": ["etp30a", "etp30b"], + "4x25G[10G,1G]": ["etp30a", "etp30b", "etp30c", "etp30d"] + } + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "120,121,122,123", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp31"], + "2x50G[40G,25G,10G,1G]": ["etp31a", "etp31b"], + "4x25G[10G,1G]": ["etp31a", "etp31b", "etp31c", "etp31d"] + } + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "124,125,126,127", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp32"], + "2x50G[40G,25G,10G,1G]": ["etp32a", "etp32b"], + "4x25G[10G,1G]": ["etp32a", "etp32b", "etp32c", "etp32d"] + } + } + } +} 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..807503fced45 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/platform_components.json @@ -0,0 +1,14 @@ +{ + "chassis": { + "MSN3700C": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn3700c-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-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_msn3700c-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn3700c-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-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_msn3700c-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-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_msn3700c-r0/plugins/fanutil.py b/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/fanutil.py new file mode 120000 index 000000000000..82ea06ef915f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/fanutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/fanutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/psuutil.py new file mode 120000 index 000000000000..9f724238a8d5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-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_msn3700c-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-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_msn3700c-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-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_msn3700c-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-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_msn3700c-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-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_msn3700c-r0/plugins/thermalutil.py b/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/thermalutil.py new file mode 120000 index 000000000000..cef21ffacccc --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/plugins/thermalutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/thermalutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn3700c-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-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_msn3700c-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn3700c-r0/sensors.conf new file mode 100644 index 000000000000..3c58e27f3e68 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/sensors.conf @@ -0,0 +1,116 @@ +################################################################################ +# Copyright (c) 2019 Mellanox Technologies +# +# Platform specific sensors config for SN3700C +################################################################################ + +# 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-*-70" + label in1 "PMIC-1 PSU 12V Rail (in1)" + label in2 "PMIC-1 PSU 12V Rail (in2)" + label in3 "PMIC-1 ASIC 0.8V VCORE Rail (out)" + label in4 "PMIC-1 ASIC 1.2V Rail (out)" + label temp1 "PMIC-1 Temp 1" + label temp2 "PMIC-1 Temp 2" + label power1 "PMIC-1 ASIC 0.8V VCORE Rail Pwr (out)" + label power2 "PMIC-1 ASIC 1.2V Rail Pwr (out)" + label curr1 "PMIC-1 ASIC 0.8V VCORE Rail Curr (out)" + label curr2 "PMIC-1 ASIC 1.2V Rail Curr (out)" + chip "tps53679-i2c-*-71" + label in1 "PMIC-2 PSU 12V Rail (in1)" + label in2 "PMIC-2 PSU 12V Rail (in2)" + label in3 "PMIC-2 ASIC 3.3V Rail (out)" + compute in3 (1.5)*@, @/(1.5) + label in4 "PMIC-2 ASIC 1.8V Rail (out)" + label temp1 "PMIC-2 Temp 1" + label temp2 "PMIC-2 Temp 2" + label power1 "PMIC-2 ASIC 3.3V Rail Pwr (out)" + label power2 "PMIC-2 ASIC 1.8V Rail Pwr (out)" + label curr1 "PMIC-2 ASIC 3.3V Rail Curr (out)" + label curr2 "PMIC-2 ASIC 1.8V Rail Curr (out)" + +bus "i2c-15" "i2c-1-mux (chan_id 6)" + chip "tps53679-i2c-*-58" + label in1 "PMIC-3 PSU 12V Rail (in1)" + label in2 "PMIC-3 PSU 12V Rail (in2)" + label in3 "PMIC-3 COMEX 1.8V Rail (out)" + label in4 "PMIC-3 COMEX 1.05V Rail (out)" + label temp1 "PMIC-3 Temp 1" + label temp2 "PMIC-3 Temp 2" + label power1 "PMIC-3 COMEX 1.8V Rail Pwr (out)" + label power2 "PMIC-3 COMEX 1.05V Rail Pwr (out)" + label curr1 "PMIC-3 COMEX 1.8V Rail Curr (out)" + label curr2 "PMIC-3 COMEX 1.05V Rail Curr (out)" + chip "tps53679-i2c-*-61" + label in1 "PMIC-4 PSU 12V Rail (in1)" + label in2 "PMIC-4 PSU 12V Rail (in2)" + label in3 "PMIC-4 COMEX 1.2V Rail (out)" + ignore in4 + label temp1 "PMIC-4 Temp 1" + label temp2 "PMIC-4 Temp 2" + label power1 "PMIC-4 COMEX 1.2V Rail Pwr (out)" + ignore power2 + label curr1 "PMIC-4 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 220V Rail (in)" + ignore in2 + label in3 "PSU-1 12V Rail (out)" + label fan1 "PSU-1 Fan 1" + ignore fan2 + ignore fan3 + label temp1 "PSU-1 Temp 1" + label temp2 "PSU-1 Temp 2" + label temp3 "PSU-1 Temp 3" + label power1 "PSU-1 220V Rail Pwr (in)" + label power2 "PSU-1 12V Rail Pwr (out)" + label curr1 "PSU-1 220V Rail Curr (in)" + label curr2 "PSU-1 12V Rail Curr (out)" + chip "dps460-i2c-*-59" + label in1 "PSU-2 220V Rail (in)" + ignore in2 + label in3 "PSU-2 12V Rail (out)" + label fan1 "PSU-2 Fan 1" + ignore fan2 + ignore fan3 + label temp1 "PSU-2 Temp 1" + label temp2 "PSU-2 Temp 2" + label temp3 "PSU-2 Temp 3" + label power1 "PSU-2 220V Rail Pwr (in)" + label power2 "PSU-2 12V Rail Pwr (out)" + label curr1 "PSU-2 220V Rail Curr (in)" + label curr2 "PSU-2 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" + +# Miscellaneous +chip "*-virtual-*" + ignore temp1 diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn3700c-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..98df66c27ca5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn3700c-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/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/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..b83e142448d6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t0.j2 @@ -0,0 +1,110 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '13924352' %} +{% set ingress_lossy_pool_size = '13924352' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '13924352' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossy_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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":"9216", + "dynamic_th":"7" + }, + "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 new file mode 100644 index 000000000000..abcab930c63e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_defaults_t1.j2 @@ -0,0 +1,110 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '12457984' %} +{% set ingress_lossy_pool_size = '12457984' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '12457984' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossy_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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":"9216", + "dynamic_th":"7" + }, + "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_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/hwsku.json b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/hwsku.json new file mode 100644 index 000000000000..33fe1cc94a7b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/hwsku.json @@ -0,0 +1,196 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet132": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet136": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet140": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet148": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet152": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet156": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet160": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet164": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet168": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet172": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet176": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet180": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet184": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet188": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet196": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet204": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet208": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet212": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet216": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet220": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet224": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet228": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet232": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet236": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet240": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet244": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet248": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet252": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + } + } +} 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..320daa45d29b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 54272 19456 34816 0 + 25000 5m 58368 19456 38912 0 + 40000 5m 61440 19456 41984 0 + 50000 5m 64512 19456 45056 0 + 100000 5m 75776 19456 56320 0 + 10000 40m 55296 19456 35840 0 + 25000 40m 60416 19456 40960 0 + 40000 40m 65536 19456 46080 0 + 50000 40m 69632 19456 50176 0 + 100000 40m 86016 19456 66560 0 + 10000 300m 63488 19456 44032 0 + 25000 300m 78848 19456 59392 0 + 40000 300m 95232 19456 75776 0 + 50000 300m 106496 19456 87040 0 + 100000 300m 159744 19456 140288 0 diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/port_config.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/port_config.ini new file mode 100644 index 000000000000..d43b11a22eb6 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index +Ethernet0 0,1,2,3 etp1 1 +Ethernet4 4,5,6,7 etp2 2 +Ethernet8 8,9,10,11 etp3 3 +Ethernet12 12,13,14,15 etp4 4 +Ethernet16 16,17,18,19 etp5 5 +Ethernet20 20,21,22,23 etp6 6 +Ethernet24 24,25,26,27 etp7 7 +Ethernet28 28,29,30,31 etp8 8 +Ethernet32 32,33,34,35 etp9 9 +Ethernet36 36,37,38,39 etp10 10 +Ethernet40 40,41,42,43 etp11 11 +Ethernet44 44,45,46,47 etp12 12 +Ethernet48 48,49,50,51 etp13 13 +Ethernet52 52,53,54,55 etp14 14 +Ethernet56 56,57,58,59 etp15 15 +Ethernet60 60,61,62,63 etp16 16 +Ethernet64 64,65,66,67 etp17 17 +Ethernet68 68,69,70,71 etp18 18 +Ethernet72 72,73,74,75 etp19 19 +Ethernet76 76,77,78,79 etp20 20 +Ethernet80 80,81,82,83 etp21 21 +Ethernet84 84,85,86,87 etp22 22 +Ethernet88 88,89,90,91 etp23 23 +Ethernet92 92,93,94,95 etp24 24 +Ethernet96 96,97,98,99 etp25 25 +Ethernet100 100,101,102,103 etp26 26 +Ethernet104 104,105,106,107 etp27 27 +Ethernet108 108,109,110,111 etp28 28 +Ethernet112 112,113,114,115 etp29 29 +Ethernet116 116,117,118,119 etp30 30 +Ethernet120 120,121,122,123 etp31 31 +Ethernet124 124,125,126,127 etp32 32 +Ethernet128 128,129,130,131 etp33 33 +Ethernet132 132,133,134,135 etp34 34 +Ethernet136 136,137,138,139 etp35 35 +Ethernet140 140,141,142,143 etp36 36 +Ethernet144 144,145,146,147 etp37 37 +Ethernet148 148,149,150,151 etp38 38 +Ethernet152 152,153,154,155 etp39 39 +Ethernet156 156,157,158,159 etp40 40 +Ethernet160 160,161,162,163 etp41 41 +Ethernet164 164,165,166,167 etp42 42 +Ethernet168 168,169,170,171 etp43 43 +Ethernet172 172,173,174,175 etp44 44 +Ethernet176 176,177,178,179 etp45 45 +Ethernet180 180,181,182,183 etp46 46 +Ethernet184 184,185,186,187 etp47 47 +Ethernet188 188,189,190,191 etp48 48 +Ethernet192 192,193,194,195 etp49 49 +Ethernet196 196,197,198,199 etp50 50 +Ethernet200 200,201,202,203 etp51 51 +Ethernet204 204,205,206,207 etp52 52 +Ethernet208 208,209,210,211 etp53 53 +Ethernet212 212,213,214,215 etp54 54 +Ethernet216 216,217,218,219 etp55 55 +Ethernet220 220,221,222,223 etp56 56 +Ethernet224 224,225,226,227 etp57 57 +Ethernet228 228,229,230,231 etp58 58 +Ethernet232 232,233,234,235 etp59 59 +Ethernet236 236,237,238,239 etp60 60 +Ethernet240 240,241,242,243 etp61 61 +Ethernet244 244,245,246,247 etp62 62 +Ethernet248 248,249,250,251 etp63 63 +Ethernet252 252,253,254,255 etp64 64 diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/qos.json.j2 new file mode 120000 index 000000000000..eccf286dc879 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/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/ACS-MSN3800/sai.profile b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/sai.profile new file mode 100644 index 000000000000..367f6c4e99c0 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_3800.xml 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 new file mode 100644 index 000000000000..4d9cc3cf7f8c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/sai_3800.xml @@ -0,0 +1,470 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 64 + + + + + 1 + 4 + 48 + + + 3 + + + 1536 + + + 3 + 4 + 49 + 3 + 1536 + + + 5 + 4 + 50 + 3 + 1536 + + + 7 + 4 + 51 + 3 + 1536 + + + 9 + 4 + 52 + 3 + 1536 + + + 11 + 4 + 53 + 3 + 1536 + + + 13 + 4 + 54 + 3 + 1536 + + + 15 + 4 + 55 + 3 + 1536 + + + 17 + 4 + 56 + 3 + 1536 + + + 19 + 4 + 57 + 3 + 1536 + + + 21 + 4 + 58 + 3 + 1536 + + + 23 + 4 + 59 + 3 + 1536 + + + 25 + 4 + 60 + 3 + 1536 + + + 27 + 4 + 61 + 3 + 1536 + + + 29 + 4 + 62 + 3 + 1536 + + + 31 + 4 + 63 + 3 + 1536 + + + 33 + 4 + 12 + 3 + 1536 + + + 35 + 4 + 13 + 3 + 1536 + + + 37 + 4 + 14 + 3 + 1536 + + + 39 + 4 + 15 + 3 + 1536 + + + 41 + 4 + 8 + 3 + 1536 + + + 43 + 4 + 9 + 3 + 1536 + + + 45 + 4 + 10 + 3 + 1536 + + + 47 + 4 + 11 + 3 + 1536 + + + 49 + 4 + 4 + 3 + 1536 + + + 51 + 4 + 5 + 3 + 1536 + + + 53 + 4 + 6 + 3 + 1536 + + + 55 + 4 + 7 + 3 + 1536 + + + 57 + 4 + 0 + 3 + 1536 + + + 59 + 4 + 1 + 3 + 1536 + + + 61 + 4 + 2 + 3 + 1536 + + + 63 + 4 + 3 + 3 + 1536 + + + 65 + 4 + 44 + 3 + 1536 + + + 67 + 4 + 45 + 3 + 1536 + + + 69 + 4 + 46 + 3 + 1536 + + + 71 + 4 + 47 + 3 + 1536 + + + 73 + 4 + 40 + 3 + 1536 + + + 75 + 4 + 41 + 3 + 1536 + + + 77 + 4 + 42 + 3 + 1536 + + + 79 + 4 + 43 + 3 + 1536 + + + 81 + 4 + 36 + 3 + 1536 + + + 83 + 4 + 37 + 3 + 1536 + + + 85 + 4 + 38 + 3 + 1536 + + + 87 + 4 + 39 + 3 + 1536 + + + 89 + 4 + 32 + 3 + 1536 + + + 91 + 4 + 33 + 3 + 1536 + + + 93 + 4 + 34 + 3 + 1536 + + + 95 + 4 + 35 + 3 + 1536 + + + 97 + 4 + 16 + 3 + 1536 + + + 99 + 4 + 17 + 3 + 1536 + + + 101 + 4 + 18 + 3 + 1536 + + + 103 + 4 + 19 + 3 + 1536 + + + 105 + 4 + 20 + 3 + 1536 + + + 107 + 4 + 21 + 3 + 1536 + + + 109 + 4 + 22 + 3 + 1536 + + + 111 + 4 + 23 + 3 + 1536 + + + 113 + 4 + 24 + 3 + 1536 + + + 115 + 4 + 25 + 3 + 1536 + + + 117 + 4 + 26 + 3 + 1536 + + + 119 + 4 + 27 + 3 + 1536 + + + 121 + 4 + 28 + 3 + 1536 + + + 123 + 4 + 29 + 3 + 1536 + + + 125 + 4 + 30 + 3 + 1536 + + + 127 + 4 + 31 + 3 + 1536 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/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-C64/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..a59beaeeb698 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/buffers_defaults_t0.j2 @@ -0,0 +1,104 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '25866240' %} +{% set ingress_lossless_pool_xoff = '2523136' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '25866240' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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/Mellanox-SN3800-C64/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..d610abeb4f26 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/buffers_defaults_t1.j2 @@ -0,0 +1,104 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '23900160' %} +{% set ingress_lossless_pool_xoff = '4489216' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '23900160' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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/Mellanox-SN3800-C64/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/hwsku.json b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/hwsku.json new file mode 100644 index 000000000000..33fe1cc94a7b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/hwsku.json @@ -0,0 +1,196 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet132": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet136": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet140": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet148": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet152": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet156": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet160": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet164": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet168": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet172": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet176": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet180": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet184": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet188": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet196": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet204": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet208": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet212": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet216": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet220": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet224": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet228": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet232": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet236": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet240": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet244": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet248": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet252": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/pg_profile_lookup.ini new file mode 120000 index 000000000000..ccbbfa44cd9c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/pg_profile_lookup.ini @@ -0,0 +1 @@ +../Mellanox-SN3800-D112C8/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/port_config.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/port_config.ini new file mode 120000 index 000000000000..3302c4ce12d8 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/port_config.ini @@ -0,0 +1 @@ +../ACS-MSN3800/port_config.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/qos.json.j2 new file mode 120000 index 000000000000..eccf286dc879 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/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-C64/sai.profile b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/sai.profile new file mode 120000 index 000000000000..f6fb0ccbfc97 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/sai.profile @@ -0,0 +1 @@ +../ACS-MSN3800/sai.profile \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/sai_3800.xml b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/sai_3800.xml new file mode 120000 index 000000000000..686d6298865c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64/sai_3800.xml @@ -0,0 +1 @@ +../ACS-MSN3800/sai_3800.xml \ No newline at end of file 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 100644 index 000000000000..63e5d5f3a85a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers_defaults_t0.j2 @@ -0,0 +1,104 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20017152' %} +{% set ingress_lossless_pool_xoff = '3440640' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '20017152' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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/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 100644 index 000000000000..d1ccce62bb14 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers_defaults_t1.j2 @@ -0,0 +1,104 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '19124224' %} +{% set ingress_lossless_pool_xoff = '4333568' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '19124224' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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/Mellanox-SN3800-D112C8/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/hwsku.json b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/hwsku.json new file mode 100644 index 000000000000..5901836014fe --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/hwsku.json @@ -0,0 +1,364 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet2": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet4": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet6": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet8": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet10": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet12": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet14": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet16": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet18": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet20": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet22": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet24": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet26": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet28": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet30": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet32": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet34": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet36": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet38": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet40": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet42": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet44": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet46": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet48": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet50": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet52": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet54": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet56": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet58": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet60": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet62": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet64": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet66": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet68": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet70": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet72": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet74": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet76": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet78": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet80": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet82": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet84": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet86": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet88": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet90": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet92": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet94": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet104": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet106": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet108": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet110": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet120": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet122": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet124": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet126": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet132": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet136": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet138": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet140": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet142": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet148": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet152": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet154": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet156": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet158": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet160": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet162": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet164": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet166": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet168": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet170": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet172": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet174": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet176": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet178": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet180": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet182": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet184": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet186": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet188": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet190": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet192": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet194": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet196": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet198": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet200": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet202": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet204": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet206": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet208": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet210": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet212": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet214": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet216": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet218": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet220": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet222": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet224": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet226": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet228": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet230": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet232": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet234": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet236": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet238": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet240": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet242": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet244": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet246": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet248": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet250": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet252": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet254": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + } + } +} 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 100644 index 000000000000..810d7e77e61f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 19456 19456 25600 0 + 25000 5m 19456 19456 28672 0 + 40000 5m 19456 19456 30720 0 + 50000 5m 19456 19456 32768 0 + 100000 5m 19456 19456 40960 0 + 10000 40m 19456 19456 26624 0 + 25000 40m 19456 19456 30720 0 + 40000 40m 19456 19456 33792 0 + 50000 40m 19456 19456 36864 0 + 100000 40m 19456 19456 48128 0 + 10000 300m 19456 19456 31744 0 + 25000 300m 19456 19456 44032 0 + 40000 300m 19456 19456 55296 0 + 50000 300m 19456 19456 63488 0 + 100000 300m 19456 19456 102400 0 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..8e40d6bd41ec --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/port_config.ini @@ -0,0 +1,121 @@ +# name lanes alias index speed +Ethernet0 0,1 etp1a 1 50000 +Ethernet2 2,3 etp1b 1 50000 +Ethernet4 4,5 etp2a 2 50000 +Ethernet6 6,7 etp2b 2 50000 +Ethernet8 8,9 etp3a 3 50000 +Ethernet10 10,11 etp3b 3 50000 +Ethernet12 12,13 etp4a 4 50000 +Ethernet14 14,15 etp4b 4 50000 +Ethernet16 16,17 etp5a 5 50000 +Ethernet18 18,19 etp5b 5 50000 +Ethernet20 20,21 etp6a 6 50000 +Ethernet22 22,23 etp6b 6 50000 +Ethernet24 24,25 etp7a 7 50000 +Ethernet26 26,27 etp7b 7 50000 +Ethernet28 28,29 etp8a 8 50000 +Ethernet30 30,31 etp8b 8 50000 +Ethernet32 32,33 etp9a 9 50000 +Ethernet34 34,35 etp9b 9 50000 +Ethernet36 36,37 etp10a 10 50000 +Ethernet38 38,39 etp10b 10 50000 +Ethernet40 40,41 etp11a 11 50000 +Ethernet42 42,43 etp11b 11 50000 +Ethernet44 44,45 etp12a 12 50000 +Ethernet46 46,47 etp12b 12 50000 +Ethernet48 48,49 etp13a 13 50000 +Ethernet50 50,51 etp13b 13 50000 +Ethernet52 52,53 etp14a 14 50000 +Ethernet54 54,55 etp14b 14 50000 +Ethernet56 56,57 etp15a 15 50000 +Ethernet58 58,59 etp15b 15 50000 +Ethernet60 60,61 etp16a 16 50000 +Ethernet62 62,63 etp16b 16 50000 +Ethernet64 64,65 etp17a 17 50000 +Ethernet66 66,67 etp17b 17 50000 +Ethernet68 68,69 etp18a 18 50000 +Ethernet70 70,71 etp18b 18 50000 +Ethernet72 72,73 etp19a 19 50000 +Ethernet74 74,75 etp19b 19 50000 +Ethernet76 76,77 etp20a 20 50000 +Ethernet78 78,79 etp20b 20 50000 +Ethernet80 80,81 etp21a 21 50000 +Ethernet82 82,83 etp21b 21 50000 +Ethernet84 84,85 etp22a 22 50000 +Ethernet86 86,87 etp22b 22 50000 +Ethernet88 88,89 etp23a 23 50000 +Ethernet90 90,91 etp23b 23 50000 +Ethernet92 92,93 etp24a 24 50000 +Ethernet94 94,95 etp24b 24 50000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105 etp27a 27 50000 +Ethernet106 106,107 etp27b 27 50000 +Ethernet108 108,109 etp28a 28 50000 +Ethernet110 110,111 etp28b 28 50000 +Ethernet112 112,113,114,115 etp29 29 100000 +Ethernet116 116,117,118,119 etp30 30 100000 +Ethernet120 120,121 etp31a 31 50000 +Ethernet122 122,123 etp31b 31 50000 +Ethernet124 124,125 etp32a 32 50000 +Ethernet126 126,127 etp32b 32 50000 +Ethernet128 128,129,130,131 etp33 33 100000 +Ethernet132 132,133,134,135 etp34 34 100000 +Ethernet136 136,137 etp35a 35 50000 +Ethernet138 138,139 etp35b 35 50000 +Ethernet140 140,141 etp36a 36 50000 +Ethernet142 142,143 etp36b 36 50000 +Ethernet144 144,145,146,147 etp37 37 100000 +Ethernet148 148,149,150,151 etp38 38 100000 +Ethernet152 152,153 etp39a 39 50000 +Ethernet154 154,155 etp39b 39 50000 +Ethernet156 156,157 etp40a 40 50000 +Ethernet158 158,159 etp40b 40 50000 +Ethernet160 160,161 etp41a 41 50000 +Ethernet162 162,163 etp41b 41 50000 +Ethernet164 164,165 etp42a 42 50000 +Ethernet166 166,167 etp42b 42 50000 +Ethernet168 168,169 etp43a 43 50000 +Ethernet170 170,171 etp43b 43 50000 +Ethernet172 172,173 etp44a 44 50000 +Ethernet174 174,175 etp44b 44 50000 +Ethernet176 176,177 etp45a 45 50000 +Ethernet178 178,179 etp45b 45 50000 +Ethernet180 180,181 etp46a 46 50000 +Ethernet182 182,183 etp46b 46 50000 +Ethernet184 184,185 etp47a 47 50000 +Ethernet186 186,187 etp47b 47 50000 +Ethernet188 188,189 etp48a 48 50000 +Ethernet190 190,191 etp48b 48 50000 +Ethernet192 192,193 etp49a 49 50000 +Ethernet194 194,195 etp49b 49 50000 +Ethernet196 196,197 etp50a 50 50000 +Ethernet198 198,199 etp50b 50 50000 +Ethernet200 200,201 etp51a 51 50000 +Ethernet202 202,203 etp51b 51 50000 +Ethernet204 204,205 etp52a 52 50000 +Ethernet206 206,207 etp52b 52 50000 +Ethernet208 208,209 etp53a 53 50000 +Ethernet210 210,211 etp53b 53 50000 +Ethernet212 212,213 etp54a 54 50000 +Ethernet214 214,215 etp54b 54 50000 +Ethernet216 216,217 etp55a 55 50000 +Ethernet218 218,219 etp55b 55 50000 +Ethernet220 220,221 etp56a 56 50000 +Ethernet222 222,223 etp56b 56 50000 +Ethernet224 224,225 etp57a 57 50000 +Ethernet226 226,227 etp57b 57 50000 +Ethernet228 228,229 etp58a 58 50000 +Ethernet230 230,231 etp58b 58 50000 +Ethernet232 232,233 etp59a 59 50000 +Ethernet234 234,235 etp59b 59 50000 +Ethernet236 236,237 etp60a 60 50000 +Ethernet238 238,239 etp60b 60 50000 +Ethernet240 240,241 etp61a 61 50000 +Ethernet242 242,243 etp61b 61 50000 +Ethernet244 244,245 etp62a 62 50000 +Ethernet246 246,247 etp62b 62 50000 +Ethernet248 248,249 etp63a 63 50000 +Ethernet250 250,251 etp63b 63 50000 +Ethernet252 252,253 etp64a 64 50000 +Ethernet254 254,255 etp64b 64 50000 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..a72edb85633d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/sai_3800_112x50g_8x100g.xml @@ -0,0 +1,510 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 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/Mellanox-SN3800-D24C52/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers.json.j2 new file mode 120000 index 000000000000..dc17caa0aa32 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers.json.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..0ff424a30a57 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t0.j2 @@ -0,0 +1,104 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '24576000' %} +{% set ingress_lossless_pool_xoff = '2756608' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '24576000' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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/Mellanox-SN3800-D24C52/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..49adf1331c1c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t1.j2 @@ -0,0 +1,104 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '22597632' %} +{% set ingress_lossless_pool_xoff = '4734976' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '22597632' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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/Mellanox-SN3800-D24C52/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/hwsku.json b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/hwsku.json new file mode 100644 index 000000000000..1c76295f197d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/hwsku.json @@ -0,0 +1,232 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet32": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet34": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet36": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet38": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet40": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet42": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet44": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet46": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet104": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet106": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet108": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet110": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet132": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet136": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet140": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet148": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet152": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet156": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet160": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet164": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet168": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet172": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet176": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet178": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet180": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet182": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet184": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet186": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet188": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet190": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet196": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet204": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet208": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet212": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet216": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet220": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet224": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet228": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet232": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet236": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet240": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet242": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet244": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet246": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet248": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet252": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/pg_profile_lookup.ini new file mode 120000 index 000000000000..ccbbfa44cd9c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/pg_profile_lookup.ini @@ -0,0 +1 @@ +../Mellanox-SN3800-D112C8/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/port_config.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/port_config.ini new file mode 100644 index 000000000000..87d4485963f7 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/port_config.ini @@ -0,0 +1,77 @@ +# name lanes alias index speed +Ethernet0 0,1,2,3 etp1 1 100000 +Ethernet4 4,5,6,7 etp2 2 100000 +Ethernet8 8,9,10,11 etp3 3 100000 +Ethernet12 12,13,14,15 etp4 4 100000 +Ethernet16 16,17,18,19 etp5 5 100000 +Ethernet20 20,21,22,23 etp6 6 100000 +Ethernet24 24,25,26,27 etp7 7 100000 +Ethernet28 28,29,30,31 etp8 8 100000 +Ethernet32 32,33 etp9a 9 50000 +Ethernet34 34,35 etp9b 9 50000 +Ethernet36 36,37 etp10a 10 50000 +Ethernet38 38,39 etp10b 10 50000 +Ethernet40 40,41 etp11a 11 50000 +Ethernet42 42,43 etp11b 11 50000 +Ethernet44 44,45 etp12a 12 50000 +Ethernet46 46,47 etp12b 12 50000 +Ethernet48 48,49,50,51 etp13 13 100000 +Ethernet52 52,53,54,55 etp14 14 100000 +Ethernet56 56,57,58,59 etp15 15 100000 +Ethernet60 60,61,62,63 etp16 16 100000 +Ethernet64 64,65,66,67 etp17 17 100000 +Ethernet68 68,69,70,71 etp18 18 100000 +Ethernet72 72,73,74,75 etp19 19 100000 +Ethernet76 76,77,78,79 etp20 20 100000 +Ethernet80 80,81,82,83 etp21 21 100000 +Ethernet84 84,85,86,87 etp22 22 100000 +Ethernet88 88,89,90,91 etp23 23 100000 +Ethernet92 92,93,94,95 etp24 24 100000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105 etp27a 27 50000 +Ethernet106 106,107 etp27b 27 50000 +Ethernet108 108,109 etp28a 28 50000 +Ethernet110 110,111 etp28b 28 50000 +Ethernet112 112,113,114,115 etp29 29 100000 +Ethernet116 116,117,118,119 etp30 30 100000 +Ethernet120 120,121,122,123 etp31 31 100000 +Ethernet124 124,125,126,127 etp32 32 100000 +Ethernet128 128,129,130,131 etp33 33 100000 +Ethernet132 132,133,134,135 etp34 34 100000 +Ethernet136 136,137,138,139 etp35 35 100000 +Ethernet140 140,141,142,143 etp36 36 100000 +Ethernet144 144,145,146,147 etp37 37 100000 +Ethernet148 148,149,150,151 etp38 38 100000 +Ethernet152 152,153,154,155 etp39 39 100000 +Ethernet156 156,157,158,159 etp40 40 100000 +Ethernet160 160,161,162,163 etp41 41 100000 +Ethernet164 164,165,166,167 etp42 42 100000 +Ethernet168 168,169,170,171 etp43 43 100000 +Ethernet172 172,173,174,175 etp44 44 100000 +Ethernet176 176,177 etp45a 45 50000 +Ethernet178 178,179 etp45b 45 50000 +Ethernet180 180,181 etp46a 46 50000 +Ethernet182 182,183 etp46b 46 50000 +Ethernet184 184,185 etp47a 47 50000 +Ethernet186 186,187 etp47b 47 50000 +Ethernet188 188,189 etp48a 48 50000 +Ethernet190 190,191 etp48b 48 50000 +Ethernet192 192,193,194,195 etp49 49 100000 +Ethernet196 196,197,198,199 etp50 50 100000 +Ethernet200 200,201,202,203 etp51 51 100000 +Ethernet204 204,205,206,207 etp52 52 100000 +Ethernet208 208,209,210,211 etp53 53 100000 +Ethernet212 212,213,214,215 etp54 54 100000 +Ethernet216 216,217,218,219 etp55 55 100000 +Ethernet220 220,221,222,223 etp56 56 100000 +Ethernet224 224,225,226,227 etp57 57 100000 +Ethernet228 228,229,230,231 etp58 58 100000 +Ethernet232 232,233,234,235 etp59 59 100000 +Ethernet236 236,237,238,239 etp60 60 100000 +Ethernet240 240,241 etp61a 61 50000 +Ethernet242 242,243 etp61b 61 50000 +Ethernet244 244,245 etp62a 62 50000 +Ethernet246 246,247 etp62b 62 50000 +Ethernet248 248,249,250,251 etp63 63 100000 +Ethernet252 252,253,254,255 etp64 64 100000 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/qos.json.j2 new file mode 120000 index 000000000000..26b0dac51846 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/qos.json.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai.profile b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai.profile new file mode 100644 index 000000000000..7c632389b58c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_3800_24x50g_52x100g.xml diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai_3800_24x50g_52x100g.xml b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai_3800_24x50g_52x100g.xml new file mode 100644 index 000000000000..1b3c77ce381c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai_3800_24x50g_52x100g.xml @@ -0,0 +1,470 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 64 + + + + + 1 + 4 + 48 + + + 3 + + + 1536 + + + 3 + 4 + 49 + 3 + 1536 + + + 5 + 4 + 50 + 3 + 1536 + + + 7 + 4 + 51 + 3 + 1536 + + + 9 + 4 + 52 + 3 + 1536 + + + 11 + 4 + 53 + 3 + 1536 + + + 13 + 4 + 54 + 3 + 1536 + + + 15 + 4 + 55 + 3 + 1536 + + + 17 + 4 + 56 + 3 + 1536 + + + 19 + 4 + 57 + 3 + 1536 + + + 21 + 4 + 58 + 3 + 1536 + + + 23 + 4 + 59 + 3 + 1536 + + + 25 + 4 + 60 + 3 + 1536 + + + 27 + 4 + 61 + 3 + 1536 + + + 29 + 4 + 62 + 3 + 1536 + + + 31 + 4 + 63 + 3 + 1536 + + + 33 + 4 + 12 + 3 + 1536 + + + 35 + 4 + 13 + 3 + 1536 + + + 37 + 4 + 14 + 3 + 1536 + + + 39 + 4 + 15 + 3 + 1536 + + + 41 + 4 + 8 + 3 + 1536 + + + 43 + 4 + 9 + 3 + 1536 + + + 45 + 4 + 10 + 3 + 1536 + + + 47 + 4 + 11 + 3 + 1536 + + + 49 + 4 + 4 + 3 + 1536 + + + 51 + 4 + 5 + 3 + 1536 + + + 53 + 4 + 6 + 3 + 1536 + + + 55 + 4 + 7 + 3 + 1536 + + + 57 + 4 + 0 + 3 + 1536 + + + 59 + 4 + 1 + 3 + 1536 + + + 61 + 4 + 2 + 3 + 1536 + + + 63 + 4 + 3 + 3 + 1536 + + + 65 + 4 + 44 + 3 + 1536 + + + 67 + 4 + 45 + 3 + 1536 + + + 69 + 4 + 46 + 3 + 1536 + + + 71 + 4 + 47 + 3 + 1536 + + + 73 + 4 + 40 + 3 + 1536 + + + 75 + 4 + 41 + 3 + 1536 + + + 77 + 4 + 42 + 3 + 1536 + + + 79 + 4 + 43 + 3 + 1536 + + + 81 + 4 + 36 + 3 + 1536 + + + 83 + 4 + 37 + 3 + 1536 + + + 85 + 4 + 38 + 3 + 1536 + + + 87 + 4 + 39 + 3 + 1536 + + + 89 + 4 + 32 + 3 + 1536 + + + 91 + 4 + 33 + 3 + 1536 + + + 93 + 4 + 34 + 3 + 1536 + + + 95 + 4 + 35 + 3 + 1536 + + + 97 + 4 + 16 + 3 + 1536 + + + 99 + 4 + 17 + 3 + 1536 + + + 101 + 4 + 18 + 3 + 1536 + + + 103 + 4 + 19 + 3 + 1536 + + + 105 + 4 + 20 + 3 + 1536 + + + 107 + 4 + 21 + 3 + 1536 + + + 109 + 4 + 22 + 3 + 1536 + + + 111 + 4 + 23 + 3 + 1536 + + + 113 + 4 + 24 + 3 + 1536 + + + 115 + 4 + 25 + 3 + 1536 + + + 117 + 4 + 26 + 3 + 1536 + + + 119 + 4 + 27 + 3 + 1536 + + + 121 + 4 + 28 + 3 + 1536 + + + 123 + 4 + 29 + 3 + 1536 + + + 125 + 4 + 30 + 3 + 1536 + + + 127 + 4 + 31 + 3 + 1536 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers.json.j2 new file mode 120000 index 000000000000..dc17caa0aa32 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers.json.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..c64f1c548631 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t0.j2 @@ -0,0 +1,104 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '24360960' %} +{% set ingress_lossless_pool_xoff = '2795520' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '24360960' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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/Mellanox-SN3800-D28C50/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..bbb51cc778b2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t1.j2 @@ -0,0 +1,104 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '22380544' %} +{% set ingress_lossless_pool_xoff = '4775936' %} +{% set egress_lossless_pool_size = '34287552' %} +{% set egress_lossy_pool_size = '22380544' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_pool_xoff }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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/Mellanox-SN3800-D28C50/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/hwsku.json b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/hwsku.json new file mode 100644 index 000000000000..fd7584babec5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/hwsku.json @@ -0,0 +1,238 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet32": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet34": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet36": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet38": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet40": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet42": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet44": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet46": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet104": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet106": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet108": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet110": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet132": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet136": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet140": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet148": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet152": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet156": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet160": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet164": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet168": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet172": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet176": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet178": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet180": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet182": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet184": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet186": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet188": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet190": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet196": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet204": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet208": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet212": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet216": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet220": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet224": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet228": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet232": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet236": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G]" + }, + "Ethernet240": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet242": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet244": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet246": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet248": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet250": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet252": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + }, + "Ethernet254": { + "default_brkout_mode": "2x50G[40G,25G,10G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/pg_profile_lookup.ini new file mode 120000 index 000000000000..ccbbfa44cd9c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/pg_profile_lookup.ini @@ -0,0 +1 @@ +../Mellanox-SN3800-D112C8/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/port_config.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/port_config.ini new file mode 100644 index 000000000000..4c169a5fb48f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/port_config.ini @@ -0,0 +1,79 @@ +# name lanes alias index speed +Ethernet0 0,1,2,3 etp1 1 100000 +Ethernet4 4,5,6,7 etp2 2 100000 +Ethernet8 8,9,10,11 etp3 3 100000 +Ethernet12 12,13,14,15 etp4 4 100000 +Ethernet16 16,17,18,19 etp5 5 100000 +Ethernet20 20,21,22,23 etp6 6 100000 +Ethernet24 24,25,26,27 etp7 7 100000 +Ethernet28 28,29,30,31 etp8 8 100000 +Ethernet32 32,33 etp9a 9 50000 +Ethernet34 34,35 etp9b 9 50000 +Ethernet36 36,37 etp10a 10 50000 +Ethernet38 38,39 etp10b 10 50000 +Ethernet40 40,41 etp11a 11 50000 +Ethernet42 42,43 etp11b 11 50000 +Ethernet44 44,45 etp12a 12 50000 +Ethernet46 46,47 etp12b 12 50000 +Ethernet48 48,49,50,51 etp13 13 100000 +Ethernet52 52,53,54,55 etp14 14 100000 +Ethernet56 56,57,58,59 etp15 15 100000 +Ethernet60 60,61,62,63 etp16 16 100000 +Ethernet64 64,65,66,67 etp17 17 100000 +Ethernet68 68,69,70,71 etp18 18 100000 +Ethernet72 72,73,74,75 etp19 19 100000 +Ethernet76 76,77,78,79 etp20 20 100000 +Ethernet80 80,81,82,83 etp21 21 100000 +Ethernet84 84,85,86,87 etp22 22 100000 +Ethernet88 88,89,90,91 etp23 23 100000 +Ethernet92 92,93,94,95 etp24 24 100000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105 etp27a 27 50000 +Ethernet106 106,107 etp27b 27 50000 +Ethernet108 108,109 etp28a 28 50000 +Ethernet110 110,111 etp28b 28 50000 +Ethernet112 112,113,114,115 etp29 29 100000 +Ethernet116 116,117,118,119 etp30 30 100000 +Ethernet120 120,121,122,123 etp31 31 100000 +Ethernet124 124,125,126,127 etp32 32 100000 +Ethernet128 128,129,130,131 etp33 33 100000 +Ethernet132 132,133,134,135 etp34 34 100000 +Ethernet136 136,137,138,139 etp35 35 100000 +Ethernet140 140,141,142,143 etp36 36 100000 +Ethernet144 144,145,146,147 etp37 37 100000 +Ethernet148 148,149,150,151 etp38 38 100000 +Ethernet152 152,153,154,155 etp39 38 100000 +Ethernet156 156,157,158,159 etp40 40 100000 +Ethernet160 160,161,162,163 etp41 41 100000 +Ethernet164 164,165,166,167 etp42 42 100000 +Ethernet168 168,169,170,171 etp43 43 100000 +Ethernet172 172,173,174,175 etp44 44 100000 +Ethernet176 176,177 etp45a 45 50000 +Ethernet178 178,179 etp45b 45 50000 +Ethernet180 180,181 etp46a 46 50000 +Ethernet182 182,183 etp46b 46 50000 +Ethernet184 184,185 etp47a 47 50000 +Ethernet186 186,187 etp47b 47 50000 +Ethernet188 188,189 etp48a 48 50000 +Ethernet190 190,191 etp48b 48 50000 +Ethernet192 192,193,194,195 etp49 49 100000 +Ethernet196 196,197,198,199 etp50 50 100000 +Ethernet200 200,201,202,203 etp51 51 100000 +Ethernet204 204,205,206,207 etp52 52 100000 +Ethernet208 208,209,210,211 etp53 53 100000 +Ethernet212 212,213,214,215 etp54 54 100000 +Ethernet216 216,217,218,219 etp55 55 100000 +Ethernet220 220,221,222,223 etp56 56 100000 +Ethernet224 224,225,226,227 etp57 57 100000 +Ethernet228 228,229,230,231 etp58 58 100000 +Ethernet232 232,233,234,235 etp59 59 100000 +Ethernet236 236,237,238,239 etp60 60 100000 +Ethernet240 240,241 etp61a 61 50000 +Ethernet242 242,243 etp61b 61 50000 +Ethernet244 244,245 etp62a 62 50000 +Ethernet246 246,247 etp62b 62 50000 +Ethernet248 248,249 etp63a 63 50000 +Ethernet250 250,251 etp63b 63 50000 +Ethernet252 252,253 etp64a 64 50000 +Ethernet254 254,255 etp64b 64 50000 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/qos.json.j2 new file mode 120000 index 000000000000..26b0dac51846 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/qos.json.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai.profile b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai.profile new file mode 100644 index 000000000000..aa37fb30dbd0 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_3800_28x50g_52x100g.xml diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai_3800_28x50g_52x100g.xml b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai_3800_28x50g_52x100g.xml new file mode 100644 index 000000000000..1b3c77ce381c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai_3800_28x50g_52x100g.xml @@ -0,0 +1,470 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 64 + + + + + 1 + 4 + 48 + + + 3 + + + 1536 + + + 3 + 4 + 49 + 3 + 1536 + + + 5 + 4 + 50 + 3 + 1536 + + + 7 + 4 + 51 + 3 + 1536 + + + 9 + 4 + 52 + 3 + 1536 + + + 11 + 4 + 53 + 3 + 1536 + + + 13 + 4 + 54 + 3 + 1536 + + + 15 + 4 + 55 + 3 + 1536 + + + 17 + 4 + 56 + 3 + 1536 + + + 19 + 4 + 57 + 3 + 1536 + + + 21 + 4 + 58 + 3 + 1536 + + + 23 + 4 + 59 + 3 + 1536 + + + 25 + 4 + 60 + 3 + 1536 + + + 27 + 4 + 61 + 3 + 1536 + + + 29 + 4 + 62 + 3 + 1536 + + + 31 + 4 + 63 + 3 + 1536 + + + 33 + 4 + 12 + 3 + 1536 + + + 35 + 4 + 13 + 3 + 1536 + + + 37 + 4 + 14 + 3 + 1536 + + + 39 + 4 + 15 + 3 + 1536 + + + 41 + 4 + 8 + 3 + 1536 + + + 43 + 4 + 9 + 3 + 1536 + + + 45 + 4 + 10 + 3 + 1536 + + + 47 + 4 + 11 + 3 + 1536 + + + 49 + 4 + 4 + 3 + 1536 + + + 51 + 4 + 5 + 3 + 1536 + + + 53 + 4 + 6 + 3 + 1536 + + + 55 + 4 + 7 + 3 + 1536 + + + 57 + 4 + 0 + 3 + 1536 + + + 59 + 4 + 1 + 3 + 1536 + + + 61 + 4 + 2 + 3 + 1536 + + + 63 + 4 + 3 + 3 + 1536 + + + 65 + 4 + 44 + 3 + 1536 + + + 67 + 4 + 45 + 3 + 1536 + + + 69 + 4 + 46 + 3 + 1536 + + + 71 + 4 + 47 + 3 + 1536 + + + 73 + 4 + 40 + 3 + 1536 + + + 75 + 4 + 41 + 3 + 1536 + + + 77 + 4 + 42 + 3 + 1536 + + + 79 + 4 + 43 + 3 + 1536 + + + 81 + 4 + 36 + 3 + 1536 + + + 83 + 4 + 37 + 3 + 1536 + + + 85 + 4 + 38 + 3 + 1536 + + + 87 + 4 + 39 + 3 + 1536 + + + 89 + 4 + 32 + 3 + 1536 + + + 91 + 4 + 33 + 3 + 1536 + + + 93 + 4 + 34 + 3 + 1536 + + + 95 + 4 + 35 + 3 + 1536 + + + 97 + 4 + 16 + 3 + 1536 + + + 99 + 4 + 17 + 3 + 1536 + + + 101 + 4 + 18 + 3 + 1536 + + + 103 + 4 + 19 + 3 + 1536 + + + 105 + 4 + 20 + 3 + 1536 + + + 107 + 4 + 21 + 3 + 1536 + + + 109 + 4 + 22 + 3 + 1536 + + + 111 + 4 + 23 + 3 + 1536 + + + 113 + 4 + 24 + 3 + 1536 + + + 115 + 4 + 25 + 3 + 1536 + + + 117 + 4 + 26 + 3 + 1536 + + + 119 + 4 + 27 + 3 + 1536 + + + 121 + 4 + 28 + 3 + 1536 + + + 123 + 4 + 29 + 3 + 1536 + + + 125 + 4 + 30 + 3 + 1536 + + + 127 + 4 + 31 + 3 + 1536 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/default_sku b/device/mellanox/x86_64-mlnx_msn3800-r0/default_sku new file mode 100644 index 000000000000..c5d9d513ad08 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN3800 t1 diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn3800-r0/pcie.yaml new file mode 120000 index 000000000000..d4a25d40bd54 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/pcie.yaml @@ -0,0 +1 @@ +../x86_64-mlnx_msn3700-r0/pcie.yaml \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/platform.json b/device/mellanox/x86_64-mlnx_msn3800-r0/platform.json new file mode 100644 index 000000000000..6564e7dfdaa1 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/platform.json @@ -0,0 +1,516 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp1"], + "2x50G[40G,25G,10G]": ["etp1a", "etp1b"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp2"], + "2x50G[40G,25G,10G]": ["etp2a", "etp2b"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp3"], + "2x50G[40G,25G,10G]": ["etp3a", "etp3b"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp4"], + "2x50G[40G,25G,10G]": ["etp4a", "etp4b"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp5"], + "2x50G[40G,25G,10G]": ["etp5a", "etp5b"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp6"], + "2x50G[40G,25G,10G]": ["etp6a", "etp6b"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp7"], + "2x50G[40G,25G,10G]": ["etp7a", "etp7b"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp8"], + "2x50G[40G,25G,10G]": ["etp8a", "etp8b"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp9"], + "2x50G[40G,25G,10G]": ["etp9a", "etp9b"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp10"], + "2x50G[40G,25G,10G]": ["etp10a", "etp10b"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp11"], + "2x50G[40G,25G,10G]": ["etp11a", "etp11b"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp12"], + "2x50G[40G,25G,10G]": ["etp12a", "etp12b"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp13"], + "2x50G[40G,25G,10G]": ["etp13a", "etp13b"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp14"], + "2x50G[40G,25G,10G]": ["etp14a", "etp14b"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp15"], + "2x50G[40G,25G,10G]": ["etp15a", "etp15b"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp16"], + "2x50G[40G,25G,10G]": ["etp16a", "etp16b"] + } + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "64,65,66,67", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp17"], + "2x50G[40G,25G,10G]": ["etp17a", "etp17b"] + } + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "68,69,70,71", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp18"], + "2x50G[40G,25G,10G]": ["etp18a", "etp18b"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp19"], + "2x50G[40G,25G,10G]": ["etp19a", "etp19b"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp20"], + "2x50G[40G,25G,10G]": ["etp20a", "etp20b"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp21"], + "2x50G[40G,25G,10G]": ["etp21a", "etp21b"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp22"], + "2x50G[40G,25G,10G]": ["etp22a", "etp22b"] + } + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "88,89,90,91", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp23"], + "2x50G[40G,25G,10G]": ["etp23a", "etp23b"] + } + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "92,93,94,95", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp24"], + "2x50G[40G,25G,10G]": ["etp24a", "etp24b"] + } + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "96,97,98,99", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp25"], + "2x50G[40G,25G,10G]": ["etp25a", "etp25b"] + } + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "100,101,102,103", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp26"], + "2x50G[40G,25G,10G]": ["etp26a", "etp26b"] + } + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "104,105,106,107", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp27"], + "2x50G[40G,25G,10G]": ["etp27a", "etp27b"] + } + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "108,109,110,111", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp28"], + "2x50G[40G,25G,10G]": ["etp28a", "etp28b"] + } + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "112,113,114,115", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp29"], + "2x50G[40G,25G,10G]": ["etp29a", "etp29b"] + } + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "116,117,118,119", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp30"], + "2x50G[40G,25G,10G]": ["etp30a", "etp30b"] + } + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "120,121,122,123", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp31"], + "2x50G[40G,25G,10G]": ["etp31a", "etp31b"] + } + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "124,125,126,127", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp32"], + "2x50G[40G,25G,10G]": ["etp32a", "etp32b"] + } + }, + "Ethernet128": { + "index": "33,33,33,33", + "lanes": "128,129,130,131", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp33"], + "2x50G[40G,25G,10G]": ["etp33a", "etp33b"] + } + }, + "Ethernet132": { + "index": "34,34,34,34", + "lanes": "132,133,134,135", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp34"], + "2x50G[40G,25G,10G]": ["etp34a", "etp34b"] + } + }, + "Ethernet136": { + "index": "35,35,35,35", + "lanes": "136,137,138,139", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp35"], + "2x50G[40G,25G,10G]": ["etp35a", "etp35b"] + } + }, + "Ethernet140": { + "index": "36,36,36,36", + "lanes": "140,141,142,143", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp36"], + "2x50G[40G,25G,10G]": ["etp36a", "etp36b"] + } + }, + "Ethernet144": { + "index": "37,37,37,37", + "lanes": "144,145,146,147", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp37"], + "2x50G[40G,25G,10G]": ["etp37a", "etp37b"] + } + }, + "Ethernet148": { + "index": "38,38,38,38", + "lanes": "148,149,150,151", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp38"], + "2x50G[40G,25G,10G]": ["etp38a", "etp38b"] + } + }, + "Ethernet152": { + "index": "39,39,39,39", + "lanes": "152,153,154,155", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp39"], + "2x50G[40G,25G,10G]": ["etp39a", "etp39b"] + } + }, + "Ethernet156": { + "index": "40,40,40,40", + "lanes": "156,157,158,159", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp40"], + "2x50G[40G,25G,10G]": ["etp40a", "etp40b"] + } + }, + "Ethernet160": { + "index": "41,41,41,41", + "lanes": "160,161,162,163", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp41"], + "2x50G[40G,25G,10G]": ["etp41a", "etp41b"] + } + }, + "Ethernet164": { + "index": "42,42,42,42", + "lanes": "164,165,166,167", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp42"], + "2x50G[40G,25G,10G]": ["etp42a", "etp42b"] + } + }, + "Ethernet168": { + "index": "43,43,43,43", + "lanes": "168,169,170,171", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp43"], + "2x50G[40G,25G,10G]": ["etp43a", "etp43b"] + } + }, + "Ethernet172": { + "index": "44,44,44,44", + "lanes": "172,173,174,175", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp44"], + "2x50G[40G,25G,10G]": ["etp44a", "etp44b"] + } + }, + "Ethernet176": { + "index": "45,45,45,45", + "lanes": "176,177,178,179", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp45"], + "2x50G[40G,25G,10G]": ["etp45a", "etp45b"] + } + }, + "Ethernet180": { + "index": "46,46,46,46", + "lanes": "180,181,182,183", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp46"], + "2x50G[40G,25G,10G]": ["etp46a", "etp46b"] + } + }, + "Ethernet184": { + "index": "47,47,47,47", + "lanes": "184,185,186,187", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp47"], + "2x50G[40G,25G,10G]": ["etp47a", "etp47b"] + } + }, + "Ethernet188": { + "index": "48,48,48,48", + "lanes": "188,189,190,191", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp48"], + "2x50G[40G,25G,10G]": ["etp48a", "etp48b"] + } + }, + "Ethernet192": { + "index": "49,49,49,49", + "lanes": "192,193,194,195", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp49"], + "2x50G[40G,25G,10G]": ["etp49a", "etp49b"] + } + }, + "Ethernet196": { + "index": "50,50,50,50", + "lanes": "196,197,198,199", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp50"], + "2x50G[40G,25G,10G]": ["etp50a", "etp50b"] + } + }, + "Ethernet200": { + "index": "51,51,51,51", + "lanes": "200,201,202,203", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp51"], + "2x50G[40G,25G,10G]": ["etp51a", "etp51b"] + } + }, + "Ethernet204": { + "index": "52,52,52,52", + "lanes": "204,205,206,207", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp52"], + "2x50G[40G,25G,10G]": ["etp52a", "etp52b"] + } + }, + "Ethernet208": { + "index": "53,53,53,53", + "lanes": "208,209,210,211", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp53"], + "2x50G[40G,25G,10G]": ["etp53a", "etp53b"] + } + }, + "Ethernet212": { + "index": "54,54,54,54", + "lanes": "212,213,214,215", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp54"], + "2x50G[40G,25G,10G]": ["etp54a", "etp54b"] + } + }, + "Ethernet216": { + "index": "55,55,55,55", + "lanes": "216,217,218,219", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp55"], + "2x50G[40G,25G,10G]": ["etp55a", "etp55b"] + } + }, + "Ethernet220": { + "index": "56,56,56,56", + "lanes": "220,221,222,223", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp56"], + "2x50G[40G,25G,10G]": ["etp56a", "etp56b"] + } + }, + "Ethernet224": { + "index": "57,57,57,57", + "lanes": "224,225,226,227", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp57"], + "2x50G[40G,25G,10G]": ["etp57a", "etp57b"] + } + }, + "Ethernet228": { + "index": "58,58,58,58", + "lanes": "228,229,230,231", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp58"], + "2x50G[40G,25G,10G]": ["etp58a", "etp58b"] + } + }, + "Ethernet232": { + "index": "59,59,59,59", + "lanes": "232,233,234,235", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp59"], + "2x50G[40G,25G,10G]": ["etp59a", "etp59b"] + } + }, + "Ethernet236": { + "index": "60,60,60,60", + "lanes": "236,237,238,239", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp60"], + "2x50G[40G,25G,10G]": ["etp60a", "etp60b"] + } + }, + "Ethernet240": { + "index": "61,61,61,61", + "lanes": "240,241,242,243", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp61"], + "2x50G[40G,25G,10G]": ["etp61a", "etp61b"] + } + }, + "Ethernet244": { + "index": "62,62,62,62", + "lanes": "244,245,246,247", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp62"], + "2x50G[40G,25G,10G]": ["etp62a", "etp62b"] + } + }, + "Ethernet248": { + "index": "63,63,63,63", + "lanes": "248,249,250,251", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp63"], + "2x50G[40G,25G,10G]": ["etp63a", "etp63b"] + } + }, + "Ethernet252": { + "index": "64,64,64,64", + "lanes": "252,253,254,255", + "breakout_modes": { + "1x100G[50G,40G,25G,10G]": ["etp64"], + "2x50G[40G,25G,10G]": ["etp64a", "etp64b"] + } + } + } +} 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..deddbcc04158 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/platform_components.json @@ -0,0 +1,15 @@ +{ + "chassis": { + "MSN3800": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { }, + "CPLD4": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn3800-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-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_msn3800-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn3800-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-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_msn3800-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-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_msn3800-r0/plugins/fanutil.py b/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/fanutil.py new file mode 120000 index 000000000000..82ea06ef915f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/fanutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/fanutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/psuutil.py new file mode 120000 index 000000000000..9f724238a8d5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-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_msn3800-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-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_msn3800-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-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_msn3800-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-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_msn3800-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-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_msn3800-r0/plugins/thermalutil.py b/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/thermalutil.py new file mode 120000 index 000000000000..cef21ffacccc --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/plugins/thermalutil.py @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/plugins/thermalutil.py \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn3800-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-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_msn3800-r0/port_peripheral_config.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/port_peripheral_config.j2 new file mode 100644 index 000000000000..1cad105ed1ee --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/port_peripheral_config.j2 @@ -0,0 +1,10 @@ +[ + {%- include 'peripheral_table.j2' %} + , + { + "PORT_PERIPHERAL_TABLE:global": { + "gearbox_model": "MELLANOX-GEARBOX-3800" + }, + "OP": "SET" + } +] diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn3800-r0/sensors.conf new file mode 100644 index 000000000000..9777c5e84398 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/sensors.conf @@ -0,0 +1,133 @@ +################################################################################ +# Copyright (c) 2019 Mellanox Technologies +# +# Platform specific sensors config for SN3800 +################################################################################ + +# 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-*-70" + label in1 "PMIC-1 PSU 12V Rail (in1)" + label in2 "PMIC-1 PSU 12V Rail (in2)" + label in3 "PMIC-1 ASIC 0.8V VCORE Rail (out)" + label in4 "PMIC-1 ASIC 1.2V Rail (out)" + label temp1 "PMIC-1 Temp 1" + label temp2 "PMIC-1 Temp 2" + label power1 "PMIC-1 ASIC 0.8V VCORE Rail Pwr (out)" + label power2 "PMIC-1 ASIC 1.2V Rail Pwr (out)" + label curr1 "PMIC-1 ASIC 0.8V VCORE Rail Curr (out)" + label curr2 "PMIC-1 ASIC 1.2V Rail Curr (out)" + chip "tps53679-i2c-*-71" + label in1 "PMIC-2 PSU 12V Rail (in1)" + label in2 "PMIC-2 PSU 12V Rail (in2)" + label in3 "PMIC-2 GB 0.8V Rail (out)" + label in4 "PMIC-2 GB 1.125V Rail (out)" + label temp1 "PMIC-2 Temp 1" + label temp2 "PMIC-2 Temp 2" + label power1 "PMIC-2 GB 0.8V Rail Pwr (out)" + label power2 "PMIC-2 GB 1.125V Rail Pwr (out)" + label curr1 "PMIC-2 GB 0.8V Rail Curr (out)" + label curr2 "PMIC-2 GB 1.125V Rail Curr (out)" + chip "tps53679-i2c-*-72" + label in1 "PMIC-3 PSU 12V Rail (in1)" + label in2 "PMIC-3 PSU 12V Rail (in2)" + label in3 "PMIC-3 ASIC 1.8V Rail (out)" + ignore in4 + label temp1 "PMIC-3 Temp 1" + label temp2 "PMIC-3 Temp 2" + label power1 "PMIC-3 ASIC 1.8V Rail Pwr (out)" + ignore power2 + label curr1 "PMIC-3 ASIC 1.8V Rail Curr (out)" + ignore curr2 + chip "tps53679-i2c-*-73" + label in1 "PMIC-4 PSU 12V Rail (in1)" + label in2 "PMIC-4 PSU 12V Rail (in2)" + label in3 "PMIC-4 GB 0.8V Rail (out)" + label in4 "PMIC-4 GB 1.125V Rail (out)" + label temp1 "PMIC-4 Temp 1" + label temp2 "PMIC-4 Temp 2" + label power1 "PMIC-4 GB 0.8V Rail Pwr (out)" + label power2 "PMIC-4 GB 1.125V Rail Pwr (out)" + label curr1 "PMIC-4 GB 0.8V Rail Curr (out)" + label curr2 "PMIC-4 GB 1.125V Rail Curr (out)" + +bus "i2c-15" "i2c-1-mux (chan_id 6)" + chip "tps53679-i2c-*-58" + label in1 "PMIC-5 PSU 12V Rail (in1)" + label in2 "PMIC-5 PSU 12V Rail (in2)" + label in3 "PMIC-5 COMEX 1.8V Rail (out)" + label in4 "PMIC-5 COMEX 1.05V Rail (out)" + label temp1 "PMIC-5 Temp 1" + label temp2 "PMIC-5 Temp 2" + label power1 "PMIC-5 COMEX 1.8V Rail Pwr (out)" + label power2 "PMIC-5 COMEX 1.05V Rail Pwr (out)" + label curr1 "PMIC-5 COMEX 1.8V Rail Curr (out)" + label curr2 "PMIC-5 COMEX 1.05V Rail Curr (out)" + chip "tps53679-i2c-*-61" + label in1 "PMIC-6 PSU 12V Rail (in1)" + label in2 "PMIC-6 PSU 12V Rail (in2)" + label in3 "PMIC-6 COMEX 1.2V Rail (out)" + ignore in4 + label temp1 "PMIC-6 Temp 1" + label temp2 "PMIC-6 Temp 2" + label power1 "PMIC-6 COMEX 1.2V Rail Pwr (out)" + ignore power2 + label curr1 "PMIC-6 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 220V Rail (in)" + ignore in2 + label in3 "PSU-1 12V Rail (out)" + label fan1 "PSU-1 Fan 1" + ignore fan2 + ignore fan3 + label temp1 "PSU-1 Temp 1" + label temp2 "PSU-1 Temp 2" + label temp3 "PSU-1 Temp 3" + label power1 "PSU-1 220V Rail Pwr (in)" + label power2 "PSU-1 12V Rail Pwr (out)" + label curr1 "PSU-1 220V Rail Curr (in)" + label curr2 "PSU-1 12V Rail Curr (out)" + chip "dps460-i2c-*-59" + label in1 "PSU-2 220V Rail (in)" + ignore in2 + label in3 "PSU-2 12V Rail (out)" + label fan1 "PSU-2 Fan 1" + ignore fan2 + ignore fan3 + label temp1 "PSU-2 Temp 1" + label temp2 "PSU-2 Temp 2" + label temp3 "PSU-2 Temp 3" + label power1 "PSU-2 220V Rail Pwr (in)" + label power2 "PSU-2 12V Rail Pwr (out)" + label curr1 "PSU-2 220V Rail Curr (in)" + label curr2 "PSU-2 12V Rail Curr (out)" + +# Chassis fans +chip "mlxreg_fan-isa-*" + label fan1 "Chassis Fan Drawer-1 Tach 1" + label fan2 "Chassis Fan Drawer-2 Tach 1" + label fan3 "Chassis Fan Drawer-3 Tach 1" + +# Miscellaneous +chip "*-virtual-*" + ignore temp1 + ignore temp2 diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn3800-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..98df66c27ca5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn3800-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/buffers.json.j2 new file mode 120000 index 000000000000..add8bf8bb7c2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/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_msn4410-r0/ACS-MSN4410/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..ddb883a1daa4 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..f8bbb6e631e7 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/hwsku.json b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/hwsku.json new file mode 100644 index 000000000000..f170ecd32b98 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet136": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet152": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet160": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet168": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet176": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet184": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet208": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet216": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet224": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet232": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet240": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet248": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/pg_profile_lookup.ini new file mode 120000 index 000000000000..88e51ceae044 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn4700-r0/ACS-MSN4700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/port_config.ini b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/port_config.ini new file mode 100644 index 000000000000..5b76c3a59d40 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 0,1,2,3 etp1 1 +Ethernet8 8,9,10,11 etp2 2 +Ethernet16 16,17,18,19 etp3 3 +Ethernet24 24,25,26,27 etp4 4 +Ethernet32 32,33,34,35 etp5 5 +Ethernet40 40,41,42,43 etp6 6 +Ethernet48 48,49,50,51 etp7 7 +Ethernet56 56,57,58,59 etp8 8 +Ethernet64 64,65,66,67 etp9 9 +Ethernet72 72,73,74,75 etp10 10 +Ethernet80 80,81,82,83 etp11 11 +Ethernet88 88,89,90,91 etp12 12 +Ethernet96 96,97,98,99 etp13 13 +Ethernet104 104,105,106,107 etp14 14 +Ethernet112 112,113,114,115 etp15 15 +Ethernet120 120,121,122,123 etp16 16 +Ethernet128 128,129,130,131 etp17 17 +Ethernet136 136,137,138,139 etp18 18 +Ethernet144 144,145,146,147 etp19 19 +Ethernet152 152,153,154,155 etp20 20 +Ethernet160 160,161,162,163 etp21 21 +Ethernet168 168,169,170,171 etp22 22 +Ethernet176 176,177,178,179 etp23 23 +Ethernet184 184,185,186,187 etp24 24 +Ethernet192 192,193,194,195,196,197,198,199 etp25 25 +Ethernet200 200,201,202,203,204,205,206,207 etp26 26 +Ethernet208 208,209,210,211,212,213,214,215 etp27 27 +Ethernet216 216,217,218,219,220,221,222,223 etp28 28 +Ethernet224 224,225,226,227,228,229,230,231 etp29 29 +Ethernet232 232,233,234,235,236,237,238,239 etp30 30 +Ethernet240 240,241,242,243,244,245,246,247 etp31 31 +Ethernet248 248,249,250,251,252,253,254,255 etp32 32 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/qos.json.j2 new file mode 120000 index 000000000000..eccf286dc879 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/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_msn4410-r0/ACS-MSN4410/sai.profile b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/sai.profile new file mode 100644 index 000000000000..be729cb4e06a --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_4410.xml diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/sai_4410.xml b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/sai_4410.xml new file mode 100644 index 000000000000..5e5b01cad626 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/ACS-MSN4410/sai_4410.xml @@ -0,0 +1,247 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 32 + + + + + 1 + 8 + 17 + 3 + 1536 + + + 5 + 8 + 16 + 3 + 1536 + + + 9 + 8 + 19 + 3 + 1536 + + + 13 + 8 + 18 + 3 + 1536 + + + 17 + 8 + 21 + 3 + 1536 + + + 21 + 8 + 20 + 3 + 1536 + + + 25 + 8 + 23 + 3 + 1536 + + + 29 + 8 + 22 + 3 + 1536 + + + 33 + 8 + 29 + 3 + 1536 + + + 37 + 8 + 28 + 3 + 1536 + + + 41 + 8 + 31 + 3 + 1536 + + + 45 + 8 + 30 + 3 + 1536 + + + 49 + 8 + 25 + 3 + 1536 + + + 53 + 8 + 24 + 3 + 1536 + + + 57 + 8 + 27 + 3 + 1536 + + + 61 + 8 + 26 + 3 + 1536 + + + 65 + 8 + 14 + 3 + 1536 + + + 69 + 8 + 15 + 3 + 1536 + + + 73 + 8 + 12 + 3 + 1536 + + + 77 + 8 + 13 + 3 + 1536 + + + 81 + 8 + 10 + 3 + 1536 + + + 85 + 8 + 11 + 3 + 1536 + + + 89 + 8 + 8 + 3 + 1536 + + + 93 + 8 + 9 + 3 + 1536 + + + 97 + 8 + 2 + 3 + 1536 + + + 101 + 8 + 3 + 3 + 1536 + + + 105 + 8 + 0 + + + 3 + + + 1536 + + + 109 + 8 + 1 + 3 + 1536 + + + 113 + 8 + 6 + 3 + 1536 + + + 117 + 8 + 7 + 3 + 1536 + + + 121 + 8 + 4 + 3 + 1536 + + + 125 + 8 + 5 + 3 + 1536 + + + + + diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/default_sku b/device/mellanox/x86_64-mlnx_msn4410-r0/default_sku new file mode 100644 index 000000000000..d175094cfe24 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN4410 t1 diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn4410-r0/pcie.yaml new file mode 120000 index 000000000000..187649f4b860 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/pcie.yaml @@ -0,0 +1 @@ +../x86_64-mlnx_msn4600c-r0/pcie.yaml \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/platform.json b/device/mellanox/x86_64-mlnx_msn4410-r0/platform.json new file mode 100644 index 000000000000..e1ea36676bd2 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/platform.json @@ -0,0 +1,292 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp1"], + "2x50G[40G,25G,10G,1G]": ["etp1a", "etp1b"], + "4x25G[10G,1G]": ["etp1a", "etp1b", "etp1c", "etp1d"] + } + }, + "Ethernet8": { + "index": "2,2,2,2", + "lanes": "8,9,10,11", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp2"], + "2x50G[40G,25G,10G,1G]": ["etp2a", "etp2b"], + "4x25G[10G,1G]": ["etp2a", "etp2b", "etp2c", "etp2d"] + } + }, + "Ethernet16": { + "index": "3,3,3,3", + "lanes": "16,17,18,19", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp3"], + "2x50G[40G,25G,10G,1G]": ["etp3a", "etp3b"], + "4x25G[10G,1G]": ["etp3a", "etp3b", "etp3c", "etp3d"] + } + }, + "Ethernet24": { + "index": "4,4,4,4", + "lanes": "24,25,26,27", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp4"], + "2x50G[40G,25G,10G,1G]": ["etp4a", "etp4b"], + "4x25G[10G,1G]": ["etp4a", "etp4b", "etp4c", "etp4d"] + } + }, + "Ethernet32": { + "index": "5,5,5,5", + "lanes": "32,33,34,35", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp5"], + "2x50G[40G,25G,10G,1G]": ["etp5a", "etp5b"], + "4x25G[10G,1G]": ["etp5a", "etp5b", "etp5c", "etp5d"] + } + }, + "Ethernet40": { + "index": "6,6,6,6", + "lanes": "40,41,42,43", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp6"], + "2x50G[40G,25G,10G,1G]": ["etp6a", "etp6b"], + "4x25G[10G,1G]": ["etp6a", "etp6b", "etp6c", "etp6d"] + } + }, + "Ethernet48": { + "index": "7,7,7,7", + "lanes": "48,49,50,51", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp7"], + "2x50G[40G,25G,10G,1G]": ["etp7a", "etp7b"], + "4x25G[10G,1G]": ["etp7a", "etp7b", "etp7c", "etp7d"] + } + }, + "Ethernet56": { + "index": "8,8,8,8", + "lanes": "56,57,58,59", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp8"], + "2x50G[40G,25G,10G,1G]": ["etp8a", "etp8b"], + "4x25G[10G,1G]": ["etp8a", "etp8b", "etp8c", "etp8d"] + } + }, + "Ethernet64": { + "index": "9,9,9,9", + "lanes": "64,65,66,67", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp9"], + "2x50G[40G,25G,10G,1G]": ["etp9a", "etp9b"], + "4x25G[10G,1G]": ["etp9a", "etp9b", "etp9c", "etp9d"] + } + }, + "Ethernet72": { + "index": "10,10,10,10", + "lanes": "72,73,74,75", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp10"], + "2x50G[40G,25G,10G,1G]": ["etp10a", "etp10b"], + "4x25G[10G,1G]": ["etp10a", "etp10b", "etp10c", "etp10d"] + } + }, + "Ethernet80": { + "index": "11,11,11,11", + "lanes": "80,81,82,83", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp11"], + "2x50G[40G,25G,10G,1G]": ["etp11a", "etp11b"], + "4x25G[10G,1G]": ["etp11a", "etp11b", "etp11c", "etp11d"] + } + }, + "Ethernet88": { + "index": "12,12,12,12", + "lanes": "88,89,90,91", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp12"], + "2x50G[40G,25G,10G,1G]": ["etp12a", "etp12b"], + "4x25G[10G,1G]": ["etp12a", "etp12b", "etp12c", "etp12d"] + } + }, + "Ethernet96": { + "index": "13,13,13,13", + "lanes": "96,97,98,99", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp13"], + "2x50G[40G,25G,10G,1G]": ["etp13a", "etp13b"], + "4x25G[10G,1G]": ["etp13a", "etp13b", "etp13c", "etp13d"] + } + }, + "Ethernet104": { + "index": "14,14,14,14", + "lanes": "104,105,106,107", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp14"], + "2x50G[40G,25G,10G,1G]": ["etp14a", "etp14b"], + "4x25G[10G,1G]": ["etp14a", "etp14b", "etp14c", "etp14d"] + } + }, + "Ethernet112": { + "index": "15,15,15,15", + "lanes": "112,113,114,115", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp15"], + "2x50G[40G,25G,10G,1G]": ["etp15a", "etp15b"], + "4x25G[10G,1G]": ["etp15a", "etp15b", "etp15c", "etp15d"] + } + }, + "Ethernet120": { + "index": "16,16,16,16", + "lanes": "120,121,122,123", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp16"], + "2x50G[40G,25G,10G,1G]": ["etp16a", "etp16b"], + "4x25G[10G,1G]": ["etp16a", "etp16b", "etp16c", "etp16d"] + } + }, + "Ethernet128": { + "index": "17,17,17,17", + "lanes": "128,129,130,131", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp17"], + "2x50G[40G,25G,10G,1G]": ["etp17a", "etp17b"], + "4x25G[10G,1G]": ["etp17a", "etp17b", "etp17c", "etp17d"] + } + }, + "Ethernet136": { + "index": "18,18,18,18", + "lanes": "136,137,138,139", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp18"], + "2x50G[40G,25G,10G,1G]": ["etp18a", "etp18b"], + "4x25G[10G,1G]": ["etp18a", "etp18b", "etp18c", "etp18d"] + } + }, + "Ethernet144": { + "index": "19,19,19,19", + "lanes": "144,145,146,147", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp19"], + "2x50G[40G,25G,10G,1G]": ["etp19a", "etp19b"], + "4x25G[10G,1G]": ["etp19a", "etp19b", "etp19c", "etp19d"] + } + }, + "Ethernet152": { + "index": "20,20,20,20", + "lanes": "152,153,154,155", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp20"], + "2x50G[40G,25G,10G,1G]": ["etp20a", "etp20b"], + "4x25G[10G,1G]": ["etp20a", "etp20b", "etp20c", "etp20d"] + } + }, + "Ethernet160": { + "index": "21,21,21,21", + "lanes": "160,161,162,163", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp21"], + "2x50G[40G,25G,10G,1G]": ["etp21a", "etp21b"], + "4x25G[10G,1G]": ["etp21a", "etp21b", "etp21c", "etp21d"] + } + }, + "Ethernet168": { + "index": "22,22,22,22", + "lanes": "168,169,170,171", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp22"], + "2x50G[40G,25G,10G,1G]": ["etp22a", "etp22b"], + "4x25G[10G,1G]": ["etp22a", "etp22b", "etp22c", "etp22d"] + } + }, + "Ethernet176": { + "index": "23,23,23,23", + "lanes": "176,177,178,179", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp23"], + "2x50G[40G,25G,10G,1G]": ["etp23a", "etp23b"], + "4x25G[10G,1G]": ["etp23a", "etp23b", "etp23c", "etp23d"] + } + }, + "Ethernet184": { + "index": "24,24,24,24", + "lanes": "184,185,186,187", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp24"], + "2x50G[40G,25G,10G,1G]": ["etp24a", "etp24b"], + "4x25G[10G,1G]": ["etp24a", "etp24b", "etp24c", "etp24d"] + } + }, + "Ethernet192": { + "index": "25,25,25,25,25,25,25,25", + "lanes": "192,193,194,195,196,197,198,199", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp25"], + "2x50G[40G,25G,10G,1G]": ["etp25a", "etp25b"], + "4x25G[10G,1G]": ["etp25a", "etp25b", "etp25c", "etp25d"] + } + }, + "Ethernet200": { + "index": "26,26,26,26,26,26,26,26", + "lanes": "200,201,202,203,204,205,206,207", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp26"], + "2x50G[40G,25G,10G,1G]": ["etp26a", "etp26b"], + "4x25G[10G,1G]": ["etp26a", "etp26b", "etp26c", "etp26d"] + } + }, + "Ethernet208": { + "index": "27,27,27,27,27,27,27,27", + "lanes": "208,209,210,211,212,213,214,215", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp27"], + "2x50G[40G,25G,10G,1G]": ["etp27a", "etp27b"], + "4x25G[10G,1G]": ["etp27a", "etp27b", "etp27c", "etp27d"] + } + }, + "Ethernet216": { + "index": "28,28,28,28,28,28,28,28", + "lanes": "216,217,218,219,220,221,222,223", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp28"], + "2x50G[40G,25G,10G,1G]": ["etp28a", "etp28b"], + "4x25G[10G,1G]": ["etp28a", "etp28b", "etp28c", "etp28d"] + } + }, + "Ethernet224": { + "index": "29,29,29,29,29,29,29,29", + "lanes": "224,225,226,227,228,229,230,231", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp29"], + "2x50G[40G,25G,10G,1G]": ["etp29a", "etp29b"], + "4x25G[10G,1G]": ["etp29a", "etp29b", "etp29c", "etp29d"] + } + }, + "Ethernet232": { + "index": "30,30,30,30,30,30,30,30", + "lanes": "232,233,234,235,236,237,238,239", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp30"], + "2x50G[40G,25G,10G,1G]": ["etp30a", "etp30b"], + "4x25G[10G,1G]": ["etp30a", "etp30b", "etp30c", "etp30d"] + } + }, + "Ethernet240": { + "index": "31,31,31,31,31,31,31,31", + "lanes": "240,241,242,243,244,245,246,247", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp31"], + "2x50G[40G,25G,10G,1G]": ["etp31a", "etp31b"], + "4x25G[10G,1G]": ["etp31a", "etp31b", "etp31c", "etp31d"] + } + }, + "Ethernet248": { + "index": "32,32,32,32,32,32,32,32", + "lanes": "248,249,250,251,252,253,254,255", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp32"], + "2x50G[40G,25G,10G,1G]": ["etp32a", "etp32b"], + "4x25G[10G,1G]": ["etp32a", "etp32b", "etp32c", "etp32d"] + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn4410-r0/platform_components.json new file mode 100644 index 000000000000..bb1afce80161 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/platform_components.json @@ -0,0 +1,14 @@ +{ + "chassis": { + "x86_64-mlnx_msn4410-r0": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn4410-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-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_msn4410-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn4410-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-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_msn4410-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-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_msn4410-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/psuutil.py new file mode 120000 index 000000000000..9f724238a8d5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-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_msn4410-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-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_msn4410-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-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_msn4410-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-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_msn4410-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/sfputil.py new file mode 100644 index 000000000000..c94b65881fe9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/sfputil.py @@ -0,0 +1,655 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import subprocess + from sonic_sfp.sfputilbase import * + import syslog +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# sfp supports dom +XCVR_DOM_CAPABILITY_DOM_SUPPORT_BIT = 0x40 + +# sfp module threshold offset and width +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 + +# I2C page size for sfp +SFP_I2C_PAGE_SIZE = 256 + +# parameters for DB connection +REDIS_TIMEOUT_USECS = 0 + +# parameters for SFP presence +SFP_STATUS_INSERTED = '1' + +# system level event/error +EVENT_ON_ALL_SFP = '-1' +SYSTEM_NOT_READY = 'system_not_ready' +SYSTEM_READY = 'system_become_ready' +SYSTEM_FAIL = 'system_fail' + +GET_PLATFORM_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.platform" + +# Ethernet <=> sfp +SFP_PORT_NAME_OFFSET = 0 +SFP_PORT_NAME_CONVENTION = "sfp{}" + +# magic code defnition for port number, qsfp port position of each platform +# port_position_tuple = (PORT_START, QSFP_PORT_START, PORT_END, PORT_IN_BLOCK, EEPROM_OFFSET) +platform_dict = {'x86_64-mlnx_msn2700-r0': 0, 'x86_64-mlnx_msn2740-r0': 0, 'x86_64-mlnx_msn2100-r0': 1, 'x86_64-mlnx_msn2410-r0': 2, 'x86_64-mlnx_msn2010-r0': 3, 'x86_64-mlnx_msn3420-r0':5, 'x86_64-mlnx_msn3700-r0': 0, 'x86_64-mlnx_msn3700c-r0': 0, 'x86_64-mlnx_msn3800-r0': 4, 'x86_64-mlnx_msn4410-r0': 0, 'x86_64-mlnx_msn4600c':4, 'x86_64-mlnx_msn4700-r0': 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), (0, 48, 59, 60, 1)] + +def log_info(msg, also_print_to_console=False): + syslog.openlog("sfputil") + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + +def log_err(msg, also_print_to_console=False): + syslog.openlog("sfputil") + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + PORT_START = 0 + QSFP_PORT_START = 0 + PORT_END = 0 + PORTS_IN_BLOCK = 0 + EEPROM_OFFSET = 0 + + db_sel = None + db_sel_timeout = None + db_sel_object = None + db_sel_tbl = None + state_db = None + sfpd_status_tbl = None + + @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.PORTS_IN_BLOCK + 1) + + @property + def port_to_eeprom_mapping(self): + print "dependency on sysfs has been removed" + raise Exception() + + def get_port_position_tuple_by_platform_name(self): + p = subprocess.Popen(GET_PLATFORM_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + position_tuple = port_position_tuple_list[platform_dict[out.rstrip('\n')]] + return position_tuple + + def __init__(self): + port_position_tuple = self.get_port_position_tuple_by_platform_name() + self.PORT_START = port_position_tuple[0] + 1 + self.QSFP_PORT_START = port_position_tuple[1] + 1 + self.PORT_END = port_position_tuple[2] + 1 + self.PORTS_IN_BLOCK = port_position_tuple[3] + self.EEPROM_OFFSET = port_position_tuple[4] + self.mlnx_sfpd_started = False + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + presence = False + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return presence + + port_num += SFP_PORT_NAME_OFFSET + sfpname = SFP_PORT_NAME_CONVENTION.format(port_num) + + ethtool_cmd = "ethtool -m {} 2>/dev/null".format(sfpname) + try: + proc = subprocess.Popen(ethtool_cmd, stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + if result != '': + presence = True + + except OSError, e: + return presence + + return presence + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + lpm_cmd = "docker exec syncd python /usr/share/sonic/platform/plugins/sfplpmget.py {}".format(port_num) + + try: + output = subprocess.check_output(lpm_cmd, shell=True) + if 'LPM ON' in output: + return True + except subprocess.CalledProcessError as e: + print "Error! Unable to get LPM for {}, rc = {}, err msg: {}".format(port_num, e.returncode, e.output) + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + curr_lpmode = self.get_low_power_mode(port_num) + if curr_lpmode == lpmode: + return True + + # Compose LPM command + lpm = 'on' if lpmode else 'off' + lpm_cmd = "docker exec syncd python /usr/share/sonic/platform/plugins/sfplpmset.py {} {}".format(port_num, lpm) + + # Set LPM + try: + subprocess.check_output(lpm_cmd, shell=True) + except subprocess.CalledProcessError as e: + print "Error! Unable to set LPM for {}, rc = {}, err msg: {}".format(port_num, e.returncode, e.output) + return False + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + lpm_cmd = "docker exec syncd python /usr/share/sonic/platform/plugins/sfpreset.py {}".format(port_num) + + try: + subprocess.check_output(lpm_cmd, shell=True) + return True + except subprocess.CalledProcessError as e: + print "Error! Unable to set LPM for {}, rc = {}, err msg: {}".format(port_num, e.returncode, e.output) + return False + + def get_transceiver_change_event(self, timeout=0): + phy_port_dict = {} + status = True + + if self.db_sel is None: + from swsscommon import swsscommon + self.state_db = swsscommon.DBConnector("STATE_DB", + REDIS_TIMEOUT_USECS, + True) + + # Subscribe to state table for SFP change notifications + self.db_sel = swsscommon.Select() + self.db_sel_tbl = swsscommon.NotificationConsumer(self.state_db, 'TRANSCEIVER_NOTIFY') + self.db_sel.addSelectable(self.db_sel_tbl) + self.db_sel_timeout = swsscommon.Select.TIMEOUT + self.db_sel_object = swsscommon.Select.OBJECT + self.sfpd_status_tbl = swsscommon.Table(self.state_db, 'MLNX_SFPD_TASK') + + # Check the liveness of mlnx-sfpd, if it failed, return system_fail event + # If mlnx-sfpd not started, return system_not_ready event + keys = self.sfpd_status_tbl.getKeys() + if 'LIVENESS' not in keys: + if self.mlnx_sfpd_started: + log_err("mlnx-sfpd exited, return false to notify xcvrd.") + phy_port_dict[EVENT_ON_ALL_SFP] = SYSTEM_FAIL + return False, phy_port_dict + else: + log_info("mlnx-sfpd not ready, return false to notify xcvrd.") + phy_port_dict[EVENT_ON_ALL_SFP] = SYSTEM_NOT_READY + return False, phy_port_dict + else: + if not self.mlnx_sfpd_started: + self.mlnx_sfpd_started = True + log_info("mlnx-sfpd is running") + phy_port_dict[EVENT_ON_ALL_SFP] = SYSTEM_READY + return False, phy_port_dict + + if timeout: + (state, c) = self.db_sel.select(timeout) + else: + (state, c) = self.db_sel.select() + + if state == self.db_sel_timeout: + status = True + elif state != self.db_sel_object: + status = False + else: + (key, op, fvp) = self.db_sel_tbl.pop() + phy_port_dict[key] = op + + return status, phy_port_dict + + def _read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes): + print("_read_eeprom_specific_bytes should not be called since the sysfs it dependents on will no longer exist.") + print("_read_eeprom_specific_bytes_via_ethtool should be called instead") + raise Exception() + + # Read out any bytes from any offset + def _read_eeprom_specific_bytes_via_ethtool(self, port_num, offset, num_bytes): + port_num += SFP_PORT_NAME_OFFSET + sfpname = SFP_PORT_NAME_CONVENTION.format(port_num) + + eeprom_raw = [] + ethtool_cmd = "ethtool -m {} hex on offset {} length {}".format(sfpname, offset, num_bytes) + try: + output = subprocess.check_output(ethtool_cmd, shell=True) + output_lines = output.splitlines() + first_line_raw = output_lines[0] + if "Offset" in first_line_raw: + for line in output_lines[2:]: + line_split = line.split() + eeprom_raw = eeprom_raw + line_split[1:] + except subprocess.CalledProcessError as e: + return None + + return eeprom_raw + + # Read eeprom + def _read_eeprom_devid(self, port_num, devid, offset, num_bytes = 512): + if port_num in self.osfp_ports: + pass + elif port_num in self.qsfp_ports: + pass + elif (self.DOM_EEPROM_ADDR == devid): + offset += 256 + + eeprom_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, offset, num_bytes) + + return eeprom_raw + + # Read out SFP type, vendor name, PN, REV, SN from eeprom. + def get_transceiver_info_dict(self, port_num): + transceiver_info_dict = {} + compliance_code_dict = {} + + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + if port_num in self.osfp_ports: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP + + sfpi_obj = inf8628InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + sfp_type_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + OSFP_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + # Below part is added to avoid fail the xcvrd, shall be implemented later + transceiver_info_dict['vendor_oui'] = 'N/A' + transceiver_info_dict['vendor_date'] = 'N/A' + transceiver_info_dict['connector'] = 'N/A' + transceiver_info_dict['encoding'] = 'N/A' + transceiver_info_dict['ext_identifier'] = 'N/A' + transceiver_info_dict['ext_rateselect_compliance'] = 'N/A' + transceiver_info_dict['cable_type'] = 'N/A' + transceiver_info_dict['cable_length'] = 'N/A' + transceiver_info_dict['specification_compliance'] = 'N/A' + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + + else: + if port_num in self.qsfp_ports: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + sfp_type = 'QSFP' + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + sfp_type = 'SFP' + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + sfp_interface_bulk_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + XCVR_INTFACE_BULK_OFFSET), interface_info_bulk_width) + if sfp_interface_bulk_raw is not None: + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + XCVR_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + sfp_vendor_oui_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + else: + return None + + sfp_vendor_date_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + if sfp_vendor_date_raw is not None: + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + else: + return None + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + if sfp_type == 'QSFP': + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_transceiver_dom_info_dict(self, port_num): + transceiver_dom_info_dict = {} + + # Below part is added to avoid failing xcvrd + # Currently, the way in which dom data is read has been changed from + # using sysfs to using ethtool. + # The ethtool returns None for ports without dom support, resulting in + # None being returned. However, this fails xcvrd to add the + # TRANSCEIVER_DOM_SENSOR table entry of associated port to CONFIG_DB + # and then causes SNMP fail. + # To address this issue a default dict is initialized with all data set to + # 'N/A' and is returned is the above case. + # BTW, in the original implementation which sysfs is used to read dom data, + # even though non-None data is returned for ports without dom support, + # it does not contain valid data. This can result in wrong data in + # TRANSCEIVER_DOM_SENSOR table. + transceiver_dom_info_dict['temperature'] = 'N/A' + transceiver_dom_info_dict['voltage'] = 'N/A' + transceiver_dom_info_dict['rx1power'] = 'N/A' + 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'] = 'N/A' + 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'] = 'N/A' + transceiver_dom_info_dict['tx2power'] = 'N/A' + transceiver_dom_info_dict['tx3power'] = 'N/A' + transceiver_dom_info_dict['tx4power'] = 'N/A' + + if port_num in self.osfp_ports: + pass + elif port_num in self.qsfp_ports: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + return None + + + # 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_via_ethtool(port_num, (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_dom_capability(qsfp_dom_capability_raw, 0) + else: + return transceiver_dom_info_dict + + dom_temperature_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (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_via_ethtool(port_num, (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_via_ethtool(port_num, (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_via_ethtool(port_num, (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 + else: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (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 transceiver_dom_info_dict + + 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'] + + 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 = SFP_I2C_PAGE_SIZE + + eeprom_raw = ['0'] * SFP_I2C_PAGE_SIZE + eeprom_raw[XCVR_DOM_CAPABILITY_OFFSET : XCVR_DOM_CAPABILITY_OFFSET + XCVR_DOM_CAPABILITY_WIDTH] = \ + self._read_eeprom_specific_bytes_via_ethtool(port_num, XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + sfp_obj = sff8472InterfaceId() + calibration_type = sfp_obj._get_calibration_type(eeprom_raw) + + dom_supported = (int(eeprom_raw[XCVR_DOM_CAPABILITY_OFFSET], 16) & XCVR_DOM_CAPABILITY_DOM_SUPPORT_BIT != 0) + if not dom_supported: + return transceiver_dom_info_dict + + eeprom_domraw = self._read_eeprom_specific_bytes_via_ethtool(port_num, offset, SFP_I2C_PAGE_SIZE) + if eeprom_domraw is None: + return transceiver_dom_info_dict + + sfpd_obj = sff8472Dom(None, calibration_type) + if sfpd_obj is None: + print "no sff8472Dom" + return None + + dom_temperature_raw = eeprom_domraw[SFP_TEMPE_OFFSET:SFP_TEMPE_OFFSET+SFP_TEMPE_WIDTH] + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + + dom_voltage_raw = eeprom_domraw[SFP_VOLT_OFFSET:SFP_VOLT_OFFSET+SFP_VOLT_WIDTH] + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + + dom_channel_monitor_raw = eeprom_domraw[SFP_CHANNL_MON_OFFSET:SFP_CHANNL_MON_OFFSET+SFP_CHANNL_MON_WIDTH] + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + + 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['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + + 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: + # current we don't support qsfp since threshold data is on page 3 and the way to read this page is under discussion. + return transceiver_dom_threshold_info_dict + else: + offset = SFP_I2C_PAGE_SIZE + + eeprom_raw = ['0'] * SFP_I2C_PAGE_SIZE + eeprom_raw[XCVR_DOM_CAPABILITY_OFFSET : XCVR_DOM_CAPABILITY_OFFSET + XCVR_DOM_CAPABILITY_WIDTH] = \ + self._read_eeprom_specific_bytes_via_ethtool(port_num, XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + sfp_obj = sff8472InterfaceId() + calibration_type = sfp_obj._get_calibration_type(eeprom_raw) + + dom_supported = (int(eeprom_raw[XCVR_DOM_CAPABILITY_OFFSET], 16) & XCVR_DOM_CAPABILITY_DOM_SUPPORT_BIT != 0) + if not dom_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = sff8472Dom(None, calibration_type) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, + (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 + + # 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/mellanox/x86_64-mlnx_msn4410-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn4410-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-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_msn4410-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn4410-r0/sensors.conf new file mode 120000 index 000000000000..e484524c164e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/sensors.conf @@ -0,0 +1 @@ +../x86_64-mlnx_msn4700-r0/sensors.conf \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn4410-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..98df66c27ca5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn4410-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers.json.j2 new file mode 120000 index 000000000000..f46e9600153b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..ddb883a1daa4 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..f8bbb6e631e7 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/hwsku.json b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/hwsku.json new file mode 100644 index 000000000000..b73944cba7a0 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/hwsku.json @@ -0,0 +1,196 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet136": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet152": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet160": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet168": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet176": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet184": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet208": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet216": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet224": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet232": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet240": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet248": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet256": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet264": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet272": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet280": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet288": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet296": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet304": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet312": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet320": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet328": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet336": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet344": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet352": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet360": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet368": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet376": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet384": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet392": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet400": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet408": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet416": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet424": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet432": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet440": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet448": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet456": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet464": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet472": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet480": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet488": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet496": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet504": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + } + } +} \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/pg_profile_lookup.ini new file mode 120000 index 000000000000..88e51ceae044 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/pg_profile_lookup.ini @@ -0,0 +1 @@ +../../x86_64-mlnx_msn4700-r0/ACS-MSN4700/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/port_config.ini b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/port_config.ini new file mode 100644 index 000000000000..a1ecf9aa3266 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/port_config.ini @@ -0,0 +1,65 @@ +# name lanes alias index +Ethernet0 0,1,2,3 etp1 1 +Ethernet8 8,9,10,11 etp2 2 +Ethernet16 16,17,18,19 etp3 3 +Ethernet24 24,25,26,27 etp4 4 +Ethernet32 32,33,34,35 etp5 5 +Ethernet40 40,41,42,43 etp6 6 +Ethernet48 48,49,50,51 etp7 7 +Ethernet56 56,57,58,59 etp8 8 +Ethernet64 64,65,66,67 etp9 9 +Ethernet72 72,73,74,75 etp10 10 +Ethernet80 80,81,82,83 etp11 11 +Ethernet88 88,89,90,91 etp12 12 +Ethernet96 96,97,98,99 etp13 13 +Ethernet104 104,105,106,107 etp14 14 +Ethernet112 112,113,114,115 etp15 15 +Ethernet120 120,121,122,123 etp16 16 +Ethernet128 128,129,130,131 etp17 17 +Ethernet136 136,137,138,139 etp18 18 +Ethernet144 144,145,146,147 etp19 19 +Ethernet152 152,153,154,155 etp20 20 +Ethernet160 160,161,162,163 etp21 21 +Ethernet168 168,169,170,171 etp22 22 +Ethernet176 176,177,178,179 etp23 23 +Ethernet184 184,185,186,187 etp24 24 +Ethernet192 192,193,194,195 etp25 25 +Ethernet200 200,201,202,203 etp26 26 +Ethernet208 208,209,210,211 etp27 27 +Ethernet216 216,217,218,219 etp28 28 +Ethernet224 224,225,226,227 etp29 29 +Ethernet232 232,233,234,235 etp30 30 +Ethernet240 240,241,242,243 etp31 31 +Ethernet248 248,249,250,251 etp32 32 +Ethernet256 256,257,258,259 etp33 33 +Ethernet264 264,265,266,267 etp34 34 +Ethernet272 272,273,274,275 etp35 35 +Ethernet280 280,281,282,283 etp36 36 +Ethernet288 288,289,290,291 etp37 37 +Ethernet296 296,297,298,299 etp38 38 +Ethernet304 304,305,306,307 etp39 39 +Ethernet312 312,313,314,315 etp40 40 +Ethernet320 320,321,322,323 etp41 41 +Ethernet328 328,329,330,331 etp42 42 +Ethernet336 336,337,338,339 etp43 43 +Ethernet344 344,345,346,347 etp44 44 +Ethernet352 352,353,354,355 etp45 45 +Ethernet360 360,361,362,363 etp46 46 +Ethernet368 368,369,370,371 etp47 47 +Ethernet376 376,377,378,379 etp48 48 +Ethernet384 384,385,386,387 etp49 49 +Ethernet392 392,393,394,395 etp50 50 +Ethernet400 400,401,402,403 etp51 51 +Ethernet408 408,409,410,411 etp52 52 +Ethernet416 416,417,418,419 etp53 53 +Ethernet424 424,425,426,427 etp54 54 +Ethernet432 432,433,434,435 etp55 55 +Ethernet440 440,441,442,443 etp56 56 +Ethernet448 448,449,450,451 etp57 57 +Ethernet456 456,457,458,459 etp58 58 +Ethernet464 464,465,466,467 etp59 59 +Ethernet472 472,473,474,475 etp60 60 +Ethernet480 480,481,482,483 etp61 61 +Ethernet488 488,489,490,491 etp62 62 +Ethernet496 496,497,498,499 etp63 63 +Ethernet504 504,505,506,507 etp64 64 diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/qos.json.j2 new file mode 120000 index 000000000000..8633303ece77 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/qos.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn4700-r0/ACS-MSN4700/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/sai.profile b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/sai.profile new file mode 100644 index 000000000000..e9d1e3e5f591 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_4600C.xml diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/sai_4600C.xml b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/sai_4600C.xml new file mode 100644 index 000000000000..02d0ed6ccd8e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/sai_4600C.xml @@ -0,0 +1,470 @@ + + + + + + 00:02:03:04:05:80 + + + 1 + + + 64 + + + + + 105 + 4 + 0 + + + 3 + + + 1536 + + + 107 + 4 + 1 + 3 + 1536 + + + 109 + 4 + 2 + 3 + 1536 + + + 111 + 4 + 3 + 3 + 1536 + + + 97 + 4 + 4 + 3 + 1536 + + + 99 + 4 + 5 + 3 + 1536 + + + 101 + 4 + 6 + 3 + 1536 + + + 103 + 4 + 7 + 3 + 1536 + + + 121 + 4 + 8 + 3 + 1536 + + + 123 + 4 + 9 + 3 + 1536 + + + 125 + 4 + 10 + 3 + 1536 + + + 127 + 4 + 11 + 3 + 1536 + + + 113 + 4 + 12 + 3 + 1536 + + + 115 + 4 + 13 + 3 + 1536 + + + 117 + 4 + 14 + 3 + 1536 + + + 119 + 4 + 15 + 3 + 1536 + + + 89 + 4 + 16 + 3 + 1536 + + + 91 + 4 + 17 + 3 + 1536 + + + 93 + 4 + 18 + 3 + 1536 + + + 95 + 4 + 19 + 3 + 1536 + + + 81 + 4 + 20 + 3 + 1536 + + + 83 + 4 + 21 + 3 + 1536 + + + 85 + 4 + 22 + 3 + 1536 + + + 87 + 4 + 23 + 3 + 1536 + + + 73 + 4 + 24 + 3 + 1536 + + + 75 + 4 + 25 + 3 + 1536 + + + 77 + 4 + 26 + 3 + 1536 + + + 79 + 4 + 27 + 3 + 1536 + + + 65 + 4 + 28 + 3 + 1536 + + + 67 + 4 + 29 + 3 + 1536 + + + 69 + 4 + 30 + 3 + 1536 + + + 71 + 4 + 31 + 3 + 1536 + + + 5 + 4 + 32 + 3 + 1536 + + + 7 + 4 + 33 + 3 + 1536 + + + 1 + 4 + 34 + 3 + 1536 + + + 3 + 4 + 35 + 3 + 1536 + + + 13 + 4 + 36 + 3 + 1536 + + + 15 + 4 + 37 + 3 + 1536 + + + 9 + 4 + 38 + 3 + 1536 + + + 11 + 4 + 39 + 3 + 1536 + + + 21 + 4 + 40 + 3 + 1536 + + + 23 + 4 + 41 + 3 + 1536 + + + 17 + 4 + 42 + 3 + 1536 + + + 19 + 4 + 43 + 3 + 1536 + + + 29 + 4 + 44 + 3 + 1536 + + + 31 + 4 + 45 + 3 + 1536 + + + 25 + 4 + 46 + 3 + 1536 + + + 27 + 4 + 47 + 3 + 1536 + + + 53 + 4 + 48 + 3 + 1536 + + + 55 + 4 + 49 + 3 + 1536 + + + 49 + 4 + 50 + 3 + 1536 + + + 51 + 4 + 51 + 3 + 1536 + + + 61 + 4 + 52 + 3 + 1536 + + + 63 + 4 + 53 + 3 + 1536 + + + 57 + 4 + 54 + 3 + 1536 + + + 59 + 4 + 55 + 3 + 1536 + + + 37 + 4 + 56 + 3 + 1536 + + + 39 + 4 + 57 + 3 + 1536 + + + 33 + 4 + 58 + 3 + 1536 + + + 35 + 4 + 59 + 3 + 1536 + + + 45 + 4 + 60 + 3 + 1536 + + + 47 + 4 + 61 + 3 + 1536 + + + 41 + 4 + 62 + 3 + 1536 + + + 43 + 4 + 63 + 3 + 1536 + + + + \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers.json.j2 new file mode 120000 index 000000000000..117d740b0f5b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers.json.j2 @@ -0,0 +1 @@ +../ACS-MSN4600C/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..aa74c4645678 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers_defaults_t0.j2 @@ -0,0 +1,104 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '47587328' %} +{% set ingress_lossless_xoff_size = '2400256' %} +{% set egress_lossless_pool_size = '60817392' %} +{% set egress_lossy_pool_size = '47587328' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_xoff_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..1cc727f8c85e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers_defaults_t1.j2 @@ -0,0 +1,104 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '46702592' %} +{% set ingress_lossless_xoff_size = '3284992' %} +{% set egress_lossless_pool_size = '60817392' %} +{% set egress_lossy_pool_size = '46702592' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + "xoff": "{{ ingress_lossless_xoff_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"9216", + "dynamic_th":"7" + }, + "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]" + }{% 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_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/hwsku.json b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/hwsku.json new file mode 100644 index 000000000000..03af6221121b --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/hwsku.json @@ -0,0 +1,364 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet2": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet8": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet10": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet16": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet18": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet24": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet26": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet32": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet34": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet40": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet42": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet48": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet50": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet56": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet58": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet64": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet66": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet72": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet74": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet80": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet82": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet88": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet90": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet96": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet98": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet104": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet106": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet112": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet114": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet120": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet122": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet128": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet130": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet136": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet138": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet144": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet146": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet152": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet154": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet160": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet162": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet168": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet170": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet176": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet178": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet184": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet186": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet208": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet210": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet216": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet218": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet224": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet232": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet240": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet242": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet248": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet250": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet256": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet264": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet272": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet274": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet280": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet282": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet288": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet296": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet304": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet306": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet312": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet314": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet320": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet322": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet328": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet330": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet336": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet338": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet344": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet346": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet352": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet354": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet360": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet362": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet368": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet370": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet376": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet378": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet384": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet386": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet392": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet394": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet400": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet402": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet408": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet410": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet416": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet418": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet424": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet426": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet432": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet434": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet440": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet442": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet448": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet450": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet456": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet458": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet464": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet466": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet472": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet474": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet480": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet482": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet488": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet490": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet496": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet498": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet504": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet506": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + } + } +} \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/pg_profile_lookup.ini new file mode 100644 index 000000000000..4931d4e1d7ae --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 19456 19456 24576 0 + 25000 5m 19456 19456 24576 0 + 40000 5m 19456 19456 24576 0 + 50000 5m 19456 19456 24576 0 + 100000 5m 19456 19456 25600 0 + 10000 40m 19456 19456 24576 0 + 25000 40m 19456 19456 26624 0 + 40000 40m 19456 19456 27648 0 + 50000 40m 19456 19456 28672 0 + 100000 40m 19456 19456 32768 0 + 10000 300m 19456 19456 30720 0 + 25000 300m 19456 19456 39936 0 + 40000 300m 19456 19456 49152 0 + 50000 300m 19456 19456 55296 0 + 100000 300m 19456 19456 86016 0 diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/port_config.ini b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/port_config.ini new file mode 100644 index 000000000000..27d933d886fa --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/port_config.ini @@ -0,0 +1,121 @@ +# name lanes alias index speed fec +Ethernet0 0,1 etp1a 1 50000 none +Ethernet2 2,3 etp1b 1 50000 none +Ethernet8 8,9 etp2a 2 50000 none +Ethernet10 10,11 etp2b 2 50000 none +Ethernet16 16,17 etp3a 3 50000 none +Ethernet18 18,19 etp3b 3 50000 none +Ethernet24 24,25 etp4a 4 50000 none +Ethernet26 26,27 etp4b 4 50000 none +Ethernet32 32,33 etp5a 5 50000 none +Ethernet34 34,35 etp5b 5 50000 none +Ethernet40 40,41 etp6a 6 50000 none +Ethernet42 42,43 etp6b 6 50000 none +Ethernet48 48,49 etp7a 7 50000 none +Ethernet50 50,51 etp7b 7 50000 none +Ethernet56 56,57 etp8a 8 50000 none +Ethernet58 58,59 etp8b 8 50000 none +Ethernet64 64,65 etp9a 9 50000 none +Ethernet66 66,67 etp9b 9 50000 none +Ethernet72 72,73 etp10a 10 50000 none +Ethernet74 74,75 etp10b 10 50000 none +Ethernet80 80,81 etp11a 11 50000 none +Ethernet82 82,83 etp11b 11 50000 none +Ethernet88 88,89 etp12a 12 50000 none +Ethernet90 90,91 etp12b 12 50000 none +Ethernet96 96,97 etp13a 13 50000 none +Ethernet98 98,99 etp13b 13 50000 none +Ethernet104 104,105 etp14a 14 50000 none +Ethernet106 106,107 etp14b 14 50000 none +Ethernet112 112,113 etp15a 15 50000 none +Ethernet114 114,115 etp15b 15 50000 none +Ethernet120 120,121 etp16a 16 50000 none +Ethernet122 122,123 etp16b 16 50000 none +Ethernet128 128,129 etp17a 17 50000 none +Ethernet130 130,131 etp17b 17 50000 none +Ethernet136 136,137 etp18a 18 50000 none +Ethernet138 138,139 etp18b 18 50000 none +Ethernet144 144,145 etp19a 19 50000 none +Ethernet146 146,147 etp19b 19 50000 none +Ethernet152 152,153 etp20a 20 50000 none +Ethernet154 154,155 etp20b 20 50000 none +Ethernet160 160,161 etp21a 21 50000 none +Ethernet162 162,163 etp21b 21 50000 none +Ethernet168 168,169 etp22a 22 50000 none +Ethernet170 170,171 etp22b 22 50000 none +Ethernet176 176,177 etp23a 23 50000 none +Ethernet178 178,179 etp23b 23 50000 none +Ethernet184 184,185 etp24a 24 50000 none +Ethernet186 186,187 etp24b 24 50000 none +Ethernet192 192,193,194,195 etp25 25 100000 rs +Ethernet200 200,201,202,203 etp26 26 100000 rs +Ethernet208 208,209 etp27a 27 50000 none +Ethernet210 210,211 etp27b 27 50000 none +Ethernet216 216,217 etp28a 28 50000 none +Ethernet218 218,219 etp28b 28 50000 none +Ethernet224 224,225,226,227 etp29 29 100000 rs +Ethernet232 232,233,234,235 etp30 30 100000 rs +Ethernet240 240,241 etp31a 31 50000 none +Ethernet242 242,243 etp31b 31 50000 none +Ethernet248 248,249 etp32a 32 50000 none +Ethernet250 250,251 etp32b 32 50000 none +Ethernet256 256,257,258,259 etp33 33 100000 rs +Ethernet264 264,265,266,267 etp34 34 100000 rs +Ethernet272 272,273 etp35a 35 50000 none +Ethernet274 274,275 etp35b 35 50000 none +Ethernet280 280,281 etp36a 36 50000 none +Ethernet282 282,283 etp36b 36 50000 none +Ethernet288 288,289,290,291 etp37 37 100000 rs +Ethernet296 296,297,298,299 etp38 38 100000 rs +Ethernet304 304,305 etp39a 39 50000 none +Ethernet306 306,307 etp39b 39 50000 none +Ethernet312 312,313 etp40a 40 50000 none +Ethernet314 314,315 etp40b 40 50000 none +Ethernet320 320,321 etp41a 41 50000 none +Ethernet322 322,323 etp41b 41 50000 none +Ethernet328 328,329 etp42a 42 50000 none +Ethernet330 330,331 etp42b 42 50000 none +Ethernet336 336,337 etp43a 43 50000 none +Ethernet338 338,339 etp43b 43 50000 none +Ethernet344 344,345 etp44a 44 50000 none +Ethernet346 346,347 etp44b 44 50000 none +Ethernet352 352,353 etp45a 45 50000 none +Ethernet354 354,355 etp45b 45 50000 none +Ethernet360 360,361 etp46a 46 50000 none +Ethernet362 362,363 etp46b 46 50000 none +Ethernet368 368,369 etp47a 47 50000 none +Ethernet370 370,371 etp47b 47 50000 none +Ethernet376 376,377 etp48a 48 50000 none +Ethernet378 378,379 etp48b 48 50000 none +Ethernet384 384,385 etp49a 49 50000 none +Ethernet386 386,387 etp49b 49 50000 none +Ethernet392 392,393 etp50a 50 50000 none +Ethernet394 394,395 etp50b 50 50000 none +Ethernet400 400,401 etp51a 51 50000 none +Ethernet402 402,403 etp51b 51 50000 none +Ethernet408 408,409 etp52a 52 50000 none +Ethernet410 410,411 etp52b 52 50000 none +Ethernet416 416,417 etp53a 53 50000 none +Ethernet418 418,419 etp53b 53 50000 none +Ethernet424 424,425 etp54a 54 50000 none +Ethernet426 426,427 etp54b 54 50000 none +Ethernet432 432,433 etp55a 55 50000 none +Ethernet434 434,435 etp55b 55 50000 none +Ethernet440 440,441 etp56a 56 50000 none +Ethernet442 442,443 etp56b 56 50000 none +Ethernet448 448,449 etp57a 57 50000 none +Ethernet450 450,451 etp57b 57 50000 none +Ethernet456 456,457 etp58a 58 50000 none +Ethernet458 458,459 etp58b 58 50000 none +Ethernet464 464,465 etp59a 59 50000 none +Ethernet466 466,467 etp59b 59 50000 none +Ethernet472 472,473 etp60a 60 50000 none +Ethernet474 474,475 etp60b 60 50000 none +Ethernet480 480,481 etp61a 61 50000 none +Ethernet482 482,483 etp61b 61 50000 none +Ethernet488 488,489 etp62a 62 50000 none +Ethernet490 490,491 etp62b 62 50000 none +Ethernet496 496,497 etp63a 63 50000 none +Ethernet498 498,499 etp63b 63 50000 none +Ethernet504 504,505 etp64a 64 50000 none +Ethernet506 506,507 etp64b 64 50000 none diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/qos.json.j2 new file mode 120000 index 000000000000..05394016a129 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/qos.json.j2 @@ -0,0 +1 @@ +../ACS-MSN4600C/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/sai.profile b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/sai.profile new file mode 100644 index 000000000000..15fccb416efd --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_4600c_112x50g_8x100g.xml diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/sai_4600c_112x50g_8x100g.xml b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/sai_4600c_112x50g_8x100g.xml new file mode 100644 index 000000000000..2016d0bdf297 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/Mellanox-SN4600C-D112C8/sai_4600c_112x50g_8x100g.xml @@ -0,0 +1,526 @@ + + + + + + 00:02:03:04:05:80 + + + 1 + + + 64 + + + + + 105 + 2 + 4 + 0 + + + 3 + + + 384 + + + 107 + 2 + 4 + 1 + 3 + 384 + + + 109 + 2 + 4 + 2 + 3 + 384 + + + 111 + 2 + 4 + 3 + 3 + 384 + + + 97 + 2 + 4 + 4 + 3 + 384 + + + 99 + 2 + 4 + 5 + 3 + 384 + + + 101 + 2 + 4 + 6 + 3 + 384 + + + 103 + 2 + 4 + 7 + 3 + 384 + + + 121 + 2 + 4 + 8 + 3 + 384 + + + 123 + 2 + 4 + 9 + 3 + 384 + + + 125 + 2 + 4 + 10 + 3 + 384 + + + 127 + 2 + 4 + 11 + 3 + 384 + + + 113 + 2 + 4 + 12 + 3 + 384 + + + 115 + 2 + 4 + 13 + 3 + 384 + + + 117 + 2 + 4 + 14 + 3 + 384 + + + 119 + 2 + 4 + 15 + 3 + 384 + + + 89 + 2 + 4 + 16 + 3 + 384 + + + 91 + 2 + 4 + 17 + 3 + 384 + + + 93 + 2 + 4 + 18 + 3 + 384 + + + 95 + 2 + 4 + 19 + 3 + 384 + + + 81 + 2 + 4 + 20 + 3 + 384 + + + 83 + 2 + 4 + 21 + 3 + 384 + + + 85 + 2 + 4 + 22 + 3 + 384 + + + 87 + 2 + 4 + 23 + 3 + 384 + + + 73 + 4 + 24 + 3 + 1536 + + + 75 + 4 + 25 + 3 + 1536 + + + 77 + 2 + 4 + 26 + 3 + 384 + + + 79 + 2 + 4 + 27 + 3 + 384 + + + 65 + 4 + 28 + 3 + 1536 + + + 67 + 4 + 29 + 3 + 1536 + + + 69 + 2 + 4 + 30 + 3 + 384 + + + 71 + 2 + 4 + 31 + 3 + 384 + + + 5 + 4 + 32 + 3 + 1536 + + + 7 + 4 + 33 + 3 + 1536 + + + 1 + 2 + 4 + 34 + 3 + 384 + + + 3 + 2 + 4 + 35 + 3 + 384 + + + 13 + 4 + 36 + 3 + 1536 + + + 15 + 4 + 37 + 3 + 1536 + + + 9 + 2 + 4 + 38 + 3 + 384 + + + 11 + 2 + 4 + 39 + 3 + 384 + + + 21 + 2 + 4 + 40 + 3 + 384 + + + 23 + 2 + 4 + 41 + 3 + 384 + + + 17 + 2 + 4 + 42 + 3 + 384 + + + 19 + 2 + 4 + 43 + 3 + 384 + + + 29 + 2 + 4 + 44 + 3 + 384 + + + 31 + 2 + 4 + 45 + 3 + 384 + + + 25 + 2 + 4 + 46 + 3 + 384 + + + 27 + 2 + 4 + 47 + 3 + 384 + + + 53 + 2 + 4 + 48 + 3 + 384 + + + 55 + 2 + 4 + 49 + 3 + 384 + + + 49 + 2 + 4 + 50 + 3 + 384 + + + 51 + 2 + 4 + 51 + 3 + 384 + + + 61 + 2 + 4 + 52 + 3 + 384 + + + 63 + 2 + 4 + 53 + 3 + 384 + + + 57 + 2 + 4 + 54 + 3 + 384 + + + 59 + 2 + 4 + 55 + 3 + 384 + + + 37 + 2 + 4 + 56 + 3 + 384 + + + 39 + 2 + 4 + 57 + 3 + 384 + + + 33 + 2 + 4 + 58 + 3 + 384 + + + 35 + 2 + 4 + 59 + 3 + 384 + + + 45 + 2 + 4 + 60 + 3 + 384 + + + 47 + 2 + 4 + 61 + 3 + 384 + + + 41 + 2 + 4 + 62 + 3 + 384 + + + 43 + 2 + 4 + 63 + 3 + 384 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/default_sku b/device/mellanox/x86_64-mlnx_msn4600c-r0/default_sku new file mode 100644 index 000000000000..451382f6d8b8 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/default_sku @@ -0,0 +1 @@ +ACS-MSN4600C t1 diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/pcie.yaml b/device/mellanox/x86_64-mlnx_msn4600c-r0/pcie.yaml new file mode 100644 index 000000000000..dcfdf1c9a59c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/pcie.yaml @@ -0,0 +1,419 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 6f00 + name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 6f02 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '01' + fn: '1' + id: 6f03 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 6f04 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '2' + id: 6f06 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 6f08 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '03' + fn: '2' + id: 6f0a + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '05' + fn: '0' + id: 6f28 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Map/VTd_Misc/System Management (rev 03)' +- bus: '00' + dev: '05' + fn: '1' + id: 6f29 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO Hot Plug (rev 03)' +- bus: '00' + dev: '05' + fn: '2' + id: 6f2a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO RAS/Control Status/Global Errors (rev 03)' +- bus: '00' + dev: '05' + fn: '4' + id: 6f2c + name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev + 03)' +- bus: '00' + dev: '14' + fn: '0' + id: 8c31 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + xHCI (rev 05)' +- bus: '00' + dev: 1c + fn: '0' + id: 8c10 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #1 (rev d5)' +- bus: '00' + dev: 1c + fn: '7' + id: 8c1e + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #8 (rev d5)' +- bus: '00' + dev: 1d + fn: '0' + id: 8c26 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + EHCI #1 (rev 05)' +- bus: '00' + dev: 1f + fn: '0' + id: 8c54 + name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard + SKU LPC Controller (rev 05)' +- bus: '00' + dev: 1f + fn: '2' + id: 8c02 + name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port + SATA Controller 1 [AHCI mode] (rev 05)' +- bus: '00' + dev: 1f + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller + (rev 05)' +- bus: '03' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '03' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '03' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '03' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '06' + dev: '00' + fn: '0' + id: cf70 + name: 'Ethernet controller: Mellanox Technologies Device cf70' +- bus: 08 + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: ff + dev: 0b + fn: '0' + id: 6f81 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '1' + id: 6f36 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '2' + id: 6f37 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '3' + id: 6f76 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link Debug (rev 03)' +- bus: ff + dev: 0c + fn: '0' + id: 6fe0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '1' + id: 6fe1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '2' + id: 6fe2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '3' + id: 6fe3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '0' + id: 6ff8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '4' + id: 6ffc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '5' + id: 6ffd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '6' + id: 6ffe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: '10' + fn: '0' + id: 6f1d + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '1' + id: 6f34 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '5' + id: 6f1e + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '6' + id: 6f7d + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '7' + id: 6f1f + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '12' + fn: '0' + id: 6fa0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '12' + fn: '1' + id: 6f30 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '13' + fn: '0' + id: 6fa8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '1' + id: 6f71 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '2' + id: 6faa + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '3' + id: 6fab + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '4' + id: 6fac + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '5' + id: 6fad + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '6' + id: 6fae + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Broadcast (rev 03)' +- bus: ff + dev: '13' + fn: '7' + id: 6faf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Global Broadcast (rev 03)' +- bus: ff + dev: '14' + fn: '0' + id: 6fb0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '1' + id: 6fb1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '2' + id: 6fb2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Error (rev 03)' +- bus: ff + dev: '14' + fn: '3' + id: 6fb3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Error (rev 03)' +- bus: ff + dev: '14' + fn: '4' + id: 6fbc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '5' + id: 6fbd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '6' + id: 6fbe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '7' + id: 6fbf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '15' + fn: '0' + id: 6fb4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '1' + id: 6fb5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '2' + id: 6fb6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Error (rev 03)' +- bus: ff + dev: '15' + fn: '3' + id: 6fb7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Error (rev 03)' +- bus: ff + dev: 1e + fn: '0' + id: 6f98 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '1' + id: 6f99 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '2' + id: 6f9a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '3' + id: 6fc0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '4' + id: 6f9c + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '0' + id: 6f88 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '2' + id: 6f8a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/platform.json b/device/mellanox/x86_64-mlnx_msn4600c-r0/platform.json new file mode 100644 index 000000000000..adf8e27478aa --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/platform.json @@ -0,0 +1,516 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp1"], + "2x50G[40G,25G,10G,1G]": ["etp1a", "etp1b"] + } + }, + "Ethernet8": { + "index": "2,2,2,2", + "lanes": "8,9,10,11", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp2"], + "2x50G[40G,25G,10G,1G]": ["etp2a", "etp2b"] + } + }, + "Ethernet16": { + "index": "3,3,3,3", + "lanes": "16,17,18,19", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp3"], + "2x50G[40G,25G,10G,1G]": ["etp3a", "etp3b"] + } + }, + "Ethernet24": { + "index": "4,4,4,4", + "lanes": "24,25,26,27", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp4"], + "2x50G[40G,25G,10G,1G]": ["etp4a", "etp4b"] + } + }, + "Ethernet32": { + "index": "5,5,5,5", + "lanes": "32,33,34,35", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp5"], + "2x50G[40G,25G,10G,1G]": ["etp5a", "etp5b"] + } + }, + "Ethernet40": { + "index": "6,6,6,6", + "lanes": "40,41,42,43", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp6"], + "2x50G[40G,25G,10G,1G]": ["etp6a", "etp6b"] + } + }, + "Ethernet48": { + "index": "7,7,7,7", + "lanes": "48,49,50,51", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp7"], + "2x50G[40G,25G,10G,1G]": ["etp7a", "etp7b"] + } + }, + "Ethernet56": { + "index": "8,8,8,8", + "lanes": "56,57,58,59", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp8"], + "2x50G[40G,25G,10G,1G]": ["etp8a", "etp8b"] + } + }, + "Ethernet64": { + "index": "9,9,9,9", + "lanes": "64,65,66,67", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp9"], + "2x50G[40G,25G,10G,1G]": ["etp9a", "etp9b"] + } + }, + "Ethernet72": { + "index": "10,10,10,10", + "lanes": "72,73,74,75", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp10"], + "2x50G[40G,25G,10G,1G]": ["etp10a", "etp10b"] + } + }, + "Ethernet80": { + "index": "11,11,11,11", + "lanes": "80,81,82,83", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp11"], + "2x50G[40G,25G,10G,1G]": ["etp11a", "etp11b"] + } + }, + "Ethernet88": { + "index": "12,12,12,12", + "lanes": "88,89,90,91", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp12"], + "2x50G[40G,25G,10G,1G]": ["etp12a", "etp12b"] + } + }, + "Ethernet96": { + "index": "13,13,13,13", + "lanes": "96,97,98,99", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp13"], + "2x50G[40G,25G,10G,1G]": ["etp13a", "etp13b"] + } + }, + "Ethernet104": { + "index": "14,14,14,14", + "lanes": "104,105,106,107", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp14"], + "2x50G[40G,25G,10G,1G]": ["etp14a", "etp14b"] + } + }, + "Ethernet112": { + "index": "15,15,15,15", + "lanes": "112,113,114,115", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp15"], + "2x50G[40G,25G,10G,1G]": ["etp15a", "etp15b"] + } + }, + "Ethernet120": { + "index": "16,16,16,16", + "lanes": "120,121,122,123", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp16"], + "2x50G[40G,25G,10G,1G]": ["etp16a", "etp16b"] + } + }, + "Ethernet128": { + "index": "17,17,17,17", + "lanes": "128,129,130,131", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp17"], + "2x50G[40G,25G,10G,1G]": ["etp17a", "etp17b"] + } + }, + "Ethernet136": { + "index": "18,18,18,18", + "lanes": "136,137,138,139", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp18"], + "2x50G[40G,25G,10G,1G]": ["etp18a", "etp18b"] + } + }, + "Ethernet144": { + "index": "19,19,19,19", + "lanes": "144,145,146,147", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp19"], + "2x50G[40G,25G,10G,1G]": ["etp19a", "etp19b"] + } + }, + "Ethernet152": { + "index": "20,20,20,20", + "lanes": "152,153,154,155", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp20"], + "2x50G[40G,25G,10G,1G]": ["etp20a", "etp20b"] + } + }, + "Ethernet160": { + "index": "21,21,21,21", + "lanes": "160,161,162,163", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp21"], + "2x50G[40G,25G,10G,1G]": ["etp21a", "etp21b"] + } + }, + "Ethernet168": { + "index": "22,22,22,22", + "lanes": "168,169,170,171", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp22"], + "2x50G[40G,25G,10G,1G]": ["etp22a", "etp22b"] + } + }, + "Ethernet176": { + "index": "23,23,23,23", + "lanes": "176,177,178,179", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp23"], + "2x50G[40G,25G,10G,1G]": ["etp23a", "etp23b"] + } + }, + "Ethernet184": { + "index": "24,24,24,24", + "lanes": "184,185,186,187", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp24"], + "2x50G[40G,25G,10G,1G]": ["etp24a", "etp24b"] + } + }, + "Ethernet192": { + "index": "25,25,25,25", + "lanes": "192,193,194,195", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp25"], + "2x50G[40G,25G,10G,1G]": ["etp25a", "etp25b"] + } + }, + "Ethernet200": { + "index": "26,26,26,26", + "lanes": "200,201,202,203", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp26"], + "2x50G[40G,25G,10G,1G]": ["etp26a", "etp26b"] + } + }, + "Ethernet208": { + "index": "27,27,27,27", + "lanes": "208,209,210,211", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp27"], + "2x50G[40G,25G,10G,1G]": ["etp27a", "etp27b"] + } + }, + "Ethernet216": { + "index": "28,28,28,28", + "lanes": "216,217,218,219", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp28"], + "2x50G[40G,25G,10G,1G]": ["etp28a", "etp28b"] + } + }, + "Ethernet224": { + "index": "29,29,29,29", + "lanes": "224,225,226,227", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp29"], + "2x50G[40G,25G,10G,1G]": ["etp29a", "etp29b"] + } + }, + "Ethernet232": { + "index": "30,30,30,30", + "lanes": "232,233,234,235", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp30"], + "2x50G[40G,25G,10G,1G]": ["etp30a", "etp30b"] + } + }, + "Ethernet240": { + "index": "31,31,31,31", + "lanes": "240,241,242,243", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp31"], + "2x50G[40G,25G,10G,1G]": ["etp31a", "etp31b"] + } + }, + "Ethernet248": { + "index": "32,32,32,32", + "lanes": "248,249,250,251", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp32"], + "2x50G[40G,25G,10G,1G]": ["etp32a", "etp32b"] + } + }, + "Ethernet256": { + "index": "33,33,33,33", + "lanes": "256,257,258,259", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp33"], + "2x50G[40G,25G,10G,1G]": ["etp33a", "etp33b"] + } + }, + "Ethernet264": { + "index": "34,34,34,34", + "lanes": "264,265,266,267", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp34"], + "2x50G[40G,25G,10G,1G]": ["etp34a", "etp34b"] + } + }, + "Ethernet272": { + "index": "35,35,35,35", + "lanes": "272,273,274,275", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp35"], + "2x50G[40G,25G,10G,1G]": ["etp35a", "etp35b"] + } + }, + "Ethernet280": { + "index": "36,36,36,36", + "lanes": "280,281,282,283", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp36"], + "2x50G[40G,25G,10G,1G]": ["etp36a", "etp36b"] + } + }, + "Ethernet288": { + "index": "37,37,37,37", + "lanes": "288,289,290,291", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp37"], + "2x50G[40G,25G,10G,1G]": ["etp37a", "etp37b"] + } + }, + "Ethernet296": { + "index": "38,38,38,38", + "lanes": "296,297,298,299", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp38"], + "2x50G[40G,25G,10G,1G]": ["etp38a", "etp38b"] + } + }, + "Ethernet304": { + "index": "39,39,39,39", + "lanes": "304,305,306,307", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp39"], + "2x50G[40G,25G,10G,1G]": ["etp39a", "etp39b"] + } + }, + "Ethernet312": { + "index": "40,40,40,40", + "lanes": "312,313,314,315", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp40"], + "2x50G[40G,25G,10G,1G]": ["etp40a", "etp40b"] + } + }, + "Ethernet320": { + "index": "41,41,41,41", + "lanes": "320,321,322,323", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp41"], + "2x50G[40G,25G,10G,1G]": ["etp42a", "etp42b"] + } + }, + "Ethernet328": { + "index": "42,42,42,42", + "lanes": "328,329,330,331", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp42"], + "2x50G[40G,25G,10G,1G]": ["etp42a", "etp42b"] + } + }, + "Ethernet336": { + "index": "43,43,43,43", + "lanes": "336,337,338,339", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp43"], + "2x50G[40G,25G,10G,1G]": ["etp43a", "etp43b"] + } + }, + "Ethernet344": { + "index": "44,44,44,44", + "lanes": "344,345,346,347", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp44"], + "2x50G[40G,25G,10G,1G]": ["etp44a", "etp44b"] + } + }, + "Ethernet352": { + "index": "45,45,45,45", + "lanes": "352,353,354,355", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp45"], + "2x50G[40G,25G,10G,1G]": ["etp45a", "etp45b"] + } + }, + "Ethernet360": { + "index": "46,46,46,46", + "lanes": "360,361,362,363", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp46"], + "2x50G[40G,25G,10G,1G]": ["etp46a", "etp46b"] + } + }, + "Ethernet368": { + "index": "47,47,47,47", + "lanes": "368,369,370,371", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp47"], + "2x50G[40G,25G,10G,1G]": ["etp47a", "etp47b"] + } + }, + "Ethernet376": { + "index": "48,48,48,48", + "lanes": "376,377,378,379", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp48"], + "2x50G[40G,25G,10G,1G]": ["etp48a", "etp48b"] + } + }, + "Ethernet384": { + "index": "49,49,49,49", + "lanes": "384,385,386,387", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp49"], + "2x50G[40G,25G,10G,1G]": ["etp49a", "etp49b"] + } + }, + "Ethernet392": { + "index": "50,50,50,50", + "lanes": "392,393,394,395", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp50"], + "2x50G[40G,25G,10G,1G]": ["etp50a", "etp50b"] + } + }, + "Ethernet400": { + "index": "51,51,51,51", + "lanes": "400,401,402,403", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp51"], + "2x50G[40G,25G,10G,1G]": ["etp51a", "etp51b"] + } + }, + "Ethernet408": { + "index": "52,52,52,52", + "lanes": "408,409,410,411", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp52"], + "2x50G[40G,25G,10G,1G]": ["etp52a", "etp52b"] + } + }, + "Ethernet416": { + "index": "53,53,53,53", + "lanes": "416,417,418,419", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp53"], + "2x50G[40G,25G,10G,1G]": ["etp53a", "etp53b"] + } + }, + "Ethernet424": { + "index": "54,54,54,54", + "lanes": "424,425,426,427", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp54"], + "2x50G[40G,25G,10G,1G]": ["etp54a", "etp54b"] + } + }, + "Ethernet432": { + "index": "55,55,55,55", + "lanes": "432,433,434,435", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp55"], + "2x50G[40G,25G,10G,1G]": ["etp55a", "etp55b"] + } + }, + "Ethernet440": { + "index": "56,56,56,56", + "lanes": "440,441,442,443", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp56"], + "2x50G[40G,25G,10G,1G]": ["etp56a", "etp56b"] + } + }, + "Ethernet448": { + "index": "57,57,57,57", + "lanes": "448,449,450,451", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp57"], + "2x50G[40G,25G,10G,1G]": ["etp57a", "etp57b"] + } + }, + "Ethernet456": { + "index": "58,58,58,58", + "lanes": "456,457,458,459", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp58"], + "2x50G[40G,25G,10G,1G]": ["etp58a", "etp58b"] + } + }, + "Ethernet464": { + "index": "59,59,59,59", + "lanes": "464,465,466,467", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp59"], + "2x50G[40G,25G,10G,1G]": ["etp59a", "etp59b"] + } + }, + "Ethernet472": { + "index": "60,60,60,60", + "lanes": "472,473,474,475", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp60"], + "2x50G[40G,25G,10G,1G]": ["etp60a", "etp60b"] + } + }, + "Ethernet480": { + "index": "61,61,61,61", + "lanes": "480,481,482,483", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp61"], + "2x50G[40G,25G,10G,1G]": ["etp61a", "etp61b"] + } + }, + "Ethernet488": { + "index": "62,62,62,62", + "lanes": "488,489,490,491", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp62"], + "2x50G[40G,25G,10G,1G]": ["etp62a", "etp62b"] + } + }, + "Ethernet496": { + "index": "63,63,63,63", + "lanes": "496,497,498,499", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp63"], + "2x50G[40G,25G,10G,1G]": ["etp63a", "etp63b"] + } + }, + "Ethernet504": { + "index": "64,64,64,64", + "lanes": "504,505,506,507", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["etp64"], + "2x50G[40G,25G,10G,1G]": ["etp64a", "etp64b"] + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/platform_components.json b/device/mellanox/x86_64-mlnx_msn4600c-r0/platform_components.json new file mode 100644 index 000000000000..22bcfcc29700 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/platform_components.json @@ -0,0 +1,14 @@ +{ + "chassis": { + "MSN4600C": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { } + } + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/platform_reboot b/device/mellanox/x86_64-mlnx_msn4600c-r0/platform_reboot new file mode 120000 index 000000000000..43c8ea567493 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-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_msn4600c-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn4600c-r0/platform_wait new file mode 120000 index 000000000000..4b30bd429854 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-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_msn4600c-r0/plugins/eeprom.py b/device/mellanox/x86_64-mlnx_msn4600c-r0/plugins/eeprom.py new file mode 120000 index 000000000000..b4e2a6a61671 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-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_msn4600c-r0/plugins/psuutil.py b/device/mellanox/x86_64-mlnx_msn4600c-r0/plugins/psuutil.py new file mode 120000 index 000000000000..9f724238a8d5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-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_msn4600c-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn4600c-r0/plugins/sfplpmget.py new file mode 120000 index 000000000000..2e84f435abd9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-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_msn4600c-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn4600c-r0/plugins/sfplpmset.py new file mode 120000 index 000000000000..6a88bac30467 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-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_msn4600c-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn4600c-r0/plugins/sfpreset.py new file mode 120000 index 000000000000..fef2063e3496 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-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_msn4600c-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn4600c-r0/plugins/sfputil.py new file mode 120000 index 000000000000..45909b880fc9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-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_msn4600c-r0/pmon_daemon_control.json b/device/mellanox/x86_64-mlnx_msn4600c-r0/pmon_daemon_control.json new file mode 120000 index 000000000000..435a2ce7c0ba --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-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_msn4600c-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn4600c-r0/sensors.conf new file mode 100644 index 000000000000..9c80350e19ad --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/sensors.conf @@ -0,0 +1,189 @@ +################################################################################ +# Copyright (c) 2020 Mellanox Technologies +# +# Platform specific sensors config for SN4600C +################################################################################ + +# 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 "xdpe12284-i2c-*-62" + label in1 "PMIC-1 PSU 12V Rail (in)" + ignore in2 + label in3 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail (out)" + ignore in4 + label temp1 "PMIC-1 Temp 1" + label temp2 "PMIC-1 Temp 2" + label power1 "PMIC-1 ASIC 12V VCORE_MAIN Rail Pwr (in)" + ignore power2 + label power3 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail Pwr (out)" + ignore power4 + label curr1 "PMIC-1 ASIC 12V VCORE_MAIN Rail Curr (in)" + ignore curr2 + label curr3 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail Curr (out)" + ignore curr4 + chip "xdpe12284-i2c-*-64" + label in1 "PMIC-2 PSU 12V Rail_1 (in)" + label in2 "PMIC-2 PSU 12V Rail_2 (in)" + label in3 "PMIC-2 ASIC 1.8V Rail_1 (out)" + label in4 "PMIC-2 ASIC 1.2V Rail_2 (out)" + label temp1 "PMIC-2 Temp 1" + label temp2 "PMIC-2 Temp 2" + label power1 "PMIC-2 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-2 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-2 ASIC 1.8V Rail_1 Pwr (out)" + label power4 "PMIC-2 ASIC 1.2V Rail_2 Pwr (out)" + label curr1 "PMIC-2 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-2 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-2 ASIC 1.8V Rail_1 Curr (out)" + label curr4 "PMIC-2 ASIC 1.2V Rail_2 Curr (out)" + chip "xdpe12284-i2c-*-66" + label in1 "PMIC-3 PSU 12V Rail_1 (in)" + label in2 "PMIC-3 PSU 12V Rail_2 (in)" + label in3 "PMIC-3 ASIC 0.85V Rail_1 T0_1 (out)" + label in4 "PMIC-3 ASIC 1.8V Rail_2 T0_1 (out)" + label temp1 "PMIC-3 Temp 1" + label temp2 "PMIC-3 Temp 2" + label power1 "PMIC-3 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-3 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-3 ASIC 0.85V Rail_1 T0_1 Pwr (out)" + label power4 "PMIC-3 ASIC 1.8V Rail_2 T0_1 Pwr (out)" + label curr1 "PMIC-3 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-3 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-3 ASIC 0.85V Rail_1 T0_1 Curr (out)" + label curr4 "PMIC-3 ASIC 1.8V Rail_2 T0_1 Curr (out)" + chip "xdpe12284-i2c-*-68" + label in1 "PMIC-4 PSU 12V Rail_1 (in)" + label in2 "PMIC-4 PSU 12V Rail_2 (in)" + label in3 "PMIC-4 ASIC 0.85V Rail_1 T2_3 (out)" + label in4 "PMIC-4 ASIC 1.8V Rail_2 T2_3 (out)" + label temp1 "PMIC-4 Temp 1" + label temp2 "PMIC-4 Temp 2" + label power1 "PMIC-4 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-4 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-4 ASIC 0.85V Rail_1 T2_3 Pwr (out)" + label power4 "PMIC-4 ASIC 1.8V Rail_2 T2_3 Pwr (out)" + label curr1 "PMIC-4 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-4 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-4 ASIC 0.85V Rail_1 T2_3 Curr (out)" + label curr4 "PMIC-4 ASIC 1.8V Rail_2 T2_3 Curr (out)" + chip "xdpe12284-i2c-*-6a" + label in1 "PMIC-5 PSU 12V Rail_1 (in)" + label in2 "PMIC-5 PSU 12V Rail_2 (in)" + label in3 "PMIC-5 ASIC 0.85V Rail_1 T4_5 (out)" + label in4 "PMIC-5 ASIC 1.8V Rail_2 T4_5 (out)" + label temp1 "PMIC-5 Temp 1" + label temp2 "PMIC-5 Temp 2" + label power1 "PMIC-5 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-5 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-5 ASIC 0.85V Rail_1 T4_5 Pwr (out)" + label power4 "PMIC-5 ASIC 1.8V Rail_2 T4_5 Pwr (out)" + label curr1 "PMIC-5 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-5 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-5 ASIC 0.85V Rail_1 T4_5 Curr (out)" + label curr4 "PMIC-5 ASIC 1.8V Rail_2 T4_5 Curr (out)" + chip "xdpe12284-i2c-*-6c" + label in1 "PMIC-6 PSU 12V Rail_1 (in)" + label in2 "PMIC-6 PSU 12V Rail_2 (in)" + label in3 "PMIC-6 ASIC 0.85V Rail_1 T6_7 (out)" + label in4 "PMIC-6 ASIC 1.8V Rail_2 T6_7 (out)" + label temp1 "PMIC-6 Temp 1" + label temp2 "PMIC-6 Temp 2" + label power1 "PMIC-6 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-6 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-6 ASIC 0.85V Rail_1 T6_7 Pwr (out)" + label power4 "PMIC-6 ASIC 1.8V Rail_2 T6_7 Pwr (out)" + label curr1 "PMIC-6 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-6 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-6 ASIC 0.85V Rail_1 T6_7 Curr (out)" + label curr4 "PMIC-6 ASIC 1.8V Rail_2 T6_7 Curr (out)" + chip "xdpe12284-i2c-*-6e" + label in1 "PMIC-7 PSU 12V Rail_1 (in)" + label in2 "PMIC-7 PSU 12V Rail_2 (in)" + label in3 "PMIC-7 ASIC 1.2V Rail_1 T0_3 (out)" + label in4 "PMIC-7 ASIC 1.2V Rail_2 T4_7 (out)" + label temp1 "PMIC-7 Temp 1" + label temp2 "PMIC-7 Temp 2" + label power1 "PMIC-7 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-7 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-7 ASIC 1.2V Rail_1 T0_3 Pwr (out)" + label power4 "PMIC-7 ASIC 1.2V Rail_2 T4_7 Pwr (out)" + label curr1 "PMIC-7 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-7 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-7 ASIC 1.2V Rail_1 T0_3 Curr (out)" + label curr4 "PMIC-7 ASIC 1.2V Rail_2 T4_7 Curr (out)" + +bus "i2c-15" "i2c-1-mux (chan_id 6)" + chip "tps53679-i2c-*-58" + label in1 "PMIC-8 PSU 12V Rail (in1)" + label in2 "PMIC-8 PSU 12V Rail (in2)" + label in3 "PMIC-8 COMEX 1.8V Rail (out)" + label in4 "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 (in1)" + label in2 "PMIC-9 PSU 12V Rail (in2)" + label in3 "PMIC-9 COMEX 1.2V Rail (out)" + ignore in4 + 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" + ignore fan2 + ignore fan3 + 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" + ignore fan2 + ignore fan3 + 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" + label fan2 "Chassis Fan Drawer-2" + label fan3 "Chassis Fan Drawer-3" diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn4600c-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..98df66c27ca5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn4600c-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file 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..c115d141e152 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t0.j2 @@ -0,0 +1,112 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '26451968' %} +{% set ingress_lossy_pool_size = '26451968' %} +{% set egress_lossless_pool_size = '60817392' %} +{% set egress_lossy_pool_size = '26451968' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossy_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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":"9216", + "dynamic_th":"7" + }, + "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..0550c6dd3103 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_defaults_t1.j2 @@ -0,0 +1,112 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '20627456' %} +{% set ingress_lossy_pool_size = '20627456' %} +{% set egress_lossless_pool_size = '60817392' %} +{% set egress_lossy_pool_size = '20627456' %} + +{%- 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": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossless_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ ingress_lossy_pool_size }}", + {%- endif %} + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + {%- if dynamic_mode is not defined %} + "size": "{{ egress_lossy_pool_size }}", + {%- endif %} + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "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":"9216", + "dynamic_th":"7" + }, + "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_dynamic.json.j2 b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_dynamic.json.j2 new file mode 120000 index 000000000000..8c4117c66214 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/buffers_dynamic.json.j2 @@ -0,0 +1 @@ +../../x86_64-mlnx_msn2700-r0/ACS-MSN2700/buffers_dynamic.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/hwsku.json b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/hwsku.json new file mode 100644 index 000000000000..c226252e525e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet136": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet152": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet160": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet168": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet176": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet184": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet208": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet216": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet224": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet232": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet240": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, + "Ethernet248": { + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + } + } +} 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..1fb3f9c328c9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/pg_profile_lookup.ini @@ -0,0 +1,23 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 52224 19456 32768 0 + 25000 5m 52224 19456 32768 0 + 40000 5m 53248 19456 33792 0 + 50000 5m 53248 19456 33792 0 + 100000 5m 53248 19456 33792 0 + 200000 5m 55296 19456 35840 0 + 400000 5m 86016 37888 38912 0 + 10000 40m 53248 19456 33792 0 + 25000 40m 55296 19456 35840 0 + 40000 40m 57344 19456 37888 0 + 50000 40m 58368 19456 38912 0 + 100000 40m 63488 19456 44032 0 + 200000 40m 74752 19456 55296 0 + 400000 40m 124928 37888 77824 0 + 10000 300m 60416 19456 40960 0 + 25000 300m 73728 19456 54272 0 + 40000 300m 86016 19456 66560 0 + 50000 300m 95232 19456 75776 0 + 100000 300m 137216 19456 117760 0 + 200000 300m 223232 19456 203776 0 + 400000 300m 420864 37888 373760 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..ea7219932624 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 0,1,2,3,4,5,6,7 etp1 1 +Ethernet8 8,9,10,11,12,13,14,15 etp2 2 +Ethernet16 16,17,18,19,20,21,22,23 etp3 3 +Ethernet24 24,25,26,27,28,29,30,31 etp4 4 +Ethernet32 32,33,34,35,36,37,38,39 etp5 5 +Ethernet40 40,41,42,43,44,45,46,47 etp6 6 +Ethernet48 48,49,50,51,52,53,54,55 etp7 7 +Ethernet56 56,57,58,59,60,61,62,63 etp8 8 +Ethernet64 64,65,66,67,68,69,70,71 etp9 9 +Ethernet72 72,73,74,75,76,77,78,79 etp10 10 +Ethernet80 80,81,82,83,84,85,86,87 etp11 11 +Ethernet88 88,89,90,91,92,93,94,95 etp12 12 +Ethernet96 96,97,98,99,100,101,102,103 etp13 13 +Ethernet104 104,105,106,107,108,109,110,111 etp14 14 +Ethernet112 112,113,114,115,116,117,118,119 etp15 15 +Ethernet120 120,121,122,123,124,125,126,127 etp16 16 +Ethernet128 128,129,130,131,132,133,134,135 etp17 17 +Ethernet136 136,137,138,139,140,141,142,143 etp18 18 +Ethernet144 144,145,146,147,148,149,150,151 etp19 19 +Ethernet152 152,153,154,155,156,157,158,159 etp20 20 +Ethernet160 160,161,162,163,164,165,166,167 etp21 21 +Ethernet168 168,169,170,171,172,173,174,175 etp22 22 +Ethernet176 176,177,178,179,180,181,182,183 etp23 23 +Ethernet184 184,185,186,187,188,189,190,191 etp24 24 +Ethernet192 192,193,194,195,196,197,198,199 etp25 25 +Ethernet200 200,201,202,203,204,205,206,207 etp26 26 +Ethernet208 208,209,210,211,212,213,214,215 etp27 27 +Ethernet216 216,217,218,219,220,221,222,223 etp28 28 +Ethernet224 224,225,226,227,228,229,230,231 etp29 29 +Ethernet232 232,233,234,235,236,237,238,239 etp30 30 +Ethernet240 240,241,242,243,244,245,246,247 etp31 31 +Ethernet248 248,249,250,251,252,253,254,255 etp32 32 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..d145093cab96 --- /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.xml diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/sai_4700.xml b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/sai_4700.xml new file mode 100644 index 000000000000..e3d0e4ea723d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/sai_4700.xml @@ -0,0 +1,247 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 32 + + + + + 1 + 8 + 17 + 3 + 1536 + + + 5 + 8 + 16 + 3 + 1536 + + + 9 + 8 + 19 + 3 + 1536 + + + 13 + 8 + 18 + 3 + 1536 + + + 17 + 8 + 21 + 3 + 1536 + + + 21 + 8 + 20 + 3 + 1536 + + + 25 + 8 + 23 + 3 + 1536 + + + 29 + 8 + 22 + 3 + 1536 + + + 33 + 8 + 29 + 3 + 1536 + + + 37 + 8 + 28 + 3 + 1536 + + + 41 + 8 + 31 + 3 + 1536 + + + 45 + 8 + 30 + 3 + 1536 + + + 49 + 8 + 25 + 3 + 1536 + + + 53 + 8 + 24 + 3 + 1536 + + + 57 + 8 + 27 + 3 + 1536 + + + 61 + 8 + 26 + 3 + 1536 + + + 65 + 8 + 14 + 3 + 1536 + + + 69 + 8 + 15 + 3 + 1536 + + + 73 + 8 + 12 + 3 + 1536 + + + 77 + 8 + 13 + 3 + 1536 + + + 81 + 8 + 10 + 3 + 1536 + + + 85 + 8 + 11 + 3 + 1536 + + + 89 + 8 + 8 + 3 + 1536 + + + 93 + 8 + 9 + 3 + 1536 + + + 97 + 8 + 2 + 3 + 1536 + + + 101 + 8 + 3 + 3 + 1536 + + + 105 + 8 + 0 + + + 3 + + + 1536 + + + 109 + 8 + 1 + 3 + 1536 + + + 113 + 8 + 6 + 3 + 1536 + + + 117 + 8 + 7 + 3 + 1536 + + + 121 + 8 + 4 + 3 + 1536 + + + 125 + 8 + 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/pcie.yaml b/device/mellanox/x86_64-mlnx_msn4700-r0/pcie.yaml new file mode 120000 index 000000000000..187649f4b860 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/pcie.yaml @@ -0,0 +1 @@ +../x86_64-mlnx_msn4600c-r0/pcie.yaml \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/platform.json b/device/mellanox/x86_64-mlnx_msn4700-r0/platform.json new file mode 100644 index 000000000000..5822631ab016 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/platform.json @@ -0,0 +1,292 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1,1,1,1,1", + "lanes": "0,1,2,3,4,5,6,7", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp1"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp1a", "etp1b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp1a", "etp1b", "etp1c", "etp1d"] + } + }, + "Ethernet8": { + "index": "2,2,2,2,2,2,2,2", + "lanes": "8,9,10,11,12,13,14,15", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp2"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp2a", "etp2b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp2a", "etp2b", "etp2c", "etp2d"] + } + }, + "Ethernet16": { + "index": "3,3,3,3,3,3,3,3", + "lanes": "16,17,18,19,20,21,22,23", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp3"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp3a", "etp3b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp3a", "etp3b", "etp3c", "etp3d"] + } + }, + "Ethernet24": { + "index": "4,4,4,4,4,4,4,4", + "lanes": "24,25,26,27,28,29,30,31", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp4"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp4a", "etp4b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp4a", "etp4b", "etp4c", "etp4d"] + } + }, + "Ethernet32": { + "index": "5,5,5,5,5,5,5,5", + "lanes": "32,33,34,35,36,37,38,39", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp5"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp5a", "etp5b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp5a", "etp5b", "etp5c", "etp5d"] + } + }, + "Ethernet40": { + "index": "6,6,6,6,6,6,6,6", + "lanes": "40,41,42,43,44,45,46,47", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp6"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp6a", "etp6b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp6a", "etp6b", "etp6c", "etp6d"] + } + }, + "Ethernet48": { + "index": "7,7,7,7,7,7,7,7", + "lanes": "48,49,50,51,52,53,54,55", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp7"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp7a", "etp7b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp7a", "etp7b", "etp7c", "etp7d"] + } + }, + "Ethernet56": { + "index": "8,8,8,8,8,8,8,8", + "lanes": "56,57,58,59,60,61,62,63", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp8"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp8a", "etp8b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp8a", "etp8b", "etp8c", "etp8d"] + } + }, + "Ethernet64": { + "index": "9,9,9,9,9,9,9,9", + "lanes": "64,65,66,67,68,69,70,71", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp9"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp9a", "etp9b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp9a", "etp9b", "etp9c", "etp9d"] + } + }, + "Ethernet72": { + "index": "10,10,10,10,10,10,10,10", + "lanes": "72,73,74,75,76,77,78,79", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp10"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp10a", "etp10b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp10a", "etp10b", "etp10c", "etp10d"] + } + }, + "Ethernet80": { + "index": "11,11,11,11,11,11,11,11", + "lanes": "80,81,82,83,84,85,86,87", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp11"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp11a", "etp11b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp11a", "etp11b", "etp11c", "etp11d"] + } + }, + "Ethernet88": { + "index": "12,12,12,12,12,12,12,12", + "lanes": "88,89,90,91,92,93,94,95", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp12"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp12a", "etp12b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp12a", "etp12b", "etp12c", "etp12d"] + } + }, + "Ethernet96": { + "index": "13,13,13,13,13,13,13,13", + "lanes": "96,97,98,99,100,101,102,103", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp13"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp13a", "etp13b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp13a", "etp13b", "etp13c", "etp13d"] + } + }, + "Ethernet104": { + "index": "14,14,14,14,14,14,14,14", + "lanes": "104,105,106,107,108,109,110,111", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp14"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp14a", "etp14b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp14a", "etp14b", "etp14c", "etp14d"] + } + }, + "Ethernet112": { + "index": "15,15,15,15,15,15,15,15", + "lanes": "112,113,114,115,116,117,118,119", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp15"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp15a", "etp15b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp15a", "etp15b", "etp15c", "etp15d"] + } + }, + "Ethernet120": { + "index": "16,16,16,16,16,16,16,16", + "lanes": "120,121,122,123,124,125,126,127", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp16"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp16a", "etp16b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp16a", "etp16b", "etp16c", "etp16d"] + } + }, + "Ethernet128": { + "index": "17,17,17,17,17,17,17,17", + "lanes": "128,129,130,131,132,133,134,135", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp17"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp17a", "etp17b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp17a", "etp17b", "etp17c", "etp17d"] + } + }, + "Ethernet136": { + "index": "18,18,18,18,18,18,18,18", + "lanes": "136,137,138,139,140,141,142,143", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp18"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp18a", "etp18b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp18a", "etp18b", "etp18c", "etp18d"] + } + }, + "Ethernet144": { + "index": "19,19,19,19,19,19,19,19", + "lanes": "144,145,146,147,148,149,150,151", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp19"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp19a", "etp19b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp19a", "etp19b", "etp19c", "etp19d"] + } + }, + "Ethernet152": { + "index": "20,20,20,20,20,20,20,20", + "lanes": "152,153,154,155,156,157,158,159", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp20"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp20a", "etp20b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp20a", "etp20b", "etp20c", "etp20d"] + } + }, + "Ethernet160": { + "index": "21,21,21,21,21,21,21,21", + "lanes": "160,161,162,163,164,165,166,167", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp21"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp21a", "etp21b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp21a", "etp21b", "etp21c", "etp21d"] + } + }, + "Ethernet168": { + "index": "22,22,22,22,22,22,22,22", + "lanes": "168,169,170,171,172,173,174,175", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp22"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp22a", "etp22b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp22a", "etp22b", "etp22c", "etp22d"] + } + }, + "Ethernet176": { + "index": "23,23,23,23,23,23,23,23", + "lanes": "176,177,178,179,180,181,182,183", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp23"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp23a", "etp23b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp23a", "etp23b", "etp23c", "etp23d"] + } + }, + "Ethernet184": { + "index": "24,24,24,24,24,24,24,24", + "lanes": "184,185,186,187,188,189,190,191", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp24"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp24a", "etp24b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp24a", "etp24b", "etp24c", "etp24d"] + } + }, + "Ethernet192": { + "index": "25,25,25,25,25,25,25,25", + "lanes": "192,193,194,195,196,197,198,199", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp25"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp25a", "etp25b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp25a", "etp25b", "etp25c", "etp25d"] + } + }, + "Ethernet200": { + "index": "26,26,26,26,26,26,26,26", + "lanes": "200,201,202,203,204,205,206,207", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp26"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp26a", "etp26b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp26a", "etp26b", "etp26c", "etp26d"] + } + }, + "Ethernet208": { + "index": "27,27,27,27,27,27,27,27", + "lanes": "208,209,210,211,212,213,214,215", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp27"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp27a", "etp27b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp27a", "etp27b", "etp27c", "etp27d"] + } + }, + "Ethernet216": { + "index": "28,28,28,28,28,28,28,28", + "lanes": "216,217,218,219,220,221,222,223", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp28"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp28a", "etp28b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp28a", "etp28b", "etp28c", "etp28d"] + } + }, + "Ethernet224": { + "index": "29,29,29,29,29,29,29,29", + "lanes": "224,225,226,227,228,229,230,231", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp29"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp29a", "etp29b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp29a", "etp29b", "etp29c", "etp29d"] + } + }, + "Ethernet232": { + "index": "30,30,30,30,30,30,30,30", + "lanes": "232,233,234,235,236,237,238,239", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp30"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp30a", "etp30b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp30a", "etp30b", "etp30c", "etp30d"] + } + }, + "Ethernet240": { + "index": "31,31,31,31,31,31,31,31", + "lanes": "240,241,242,243,244,245,246,247", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp31"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp31a", "etp31b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp31a", "etp31b", "etp31c", "etp31d"] + } + }, + "Ethernet248": { + "index": "32,32,32,32,32,32,32,32", + "lanes": "248,249,250,251,252,253,254,255", + "breakout_modes": { + "1x400G[200G,100G,50G,40G,25G,10G,1G]": ["etp32"], + "2x200G[100G,50G,40G,25G,10G,1G]": ["etp32a", "etp32b"], + "4x100G[50G,40G,25G,10G,1G]": ["etp32a", "etp32b", "etp32c", "etp32d"] + } + } + } +} 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..c663b782187e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/platform_components.json @@ -0,0 +1,14 @@ +{ + "chassis": { + "MSN4700": { + "component": { + "ONIE": { }, + "SSD": { }, + "BIOS": { }, + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { } + } + } + } +} 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..3b19dc80c6ce --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/sensors.conf @@ -0,0 +1,198 @@ +################################################################################ +# 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 "xdpe12284-i2c-*-62" + label in1 "PMIC-1 PSU 12V Rail (in1)" + label in2 "PMIC-1 PSU 12V Rail (in2)" + label in3 "PMIC-1 ASIC 0.8V VCORE MAIN Rail (out)" + ignore in4 + label temp1 "PMIC-1 Temp 1" + label temp2 "PMIC-1 Temp 2" + label power1 "PMIC-1 PSU 12V Rail Pwr (in1)" + label power2 "PMIC-1 PSU 12V Rail Pwr (in2)" + label power3 "PMIC-1 ASIC 0.8V VCORE MAIN Rail Pwr (out)" + ignore power4 + label curr1 "PMIC-1 PSU 12V Rail Curr (in1)" + label curr2 "PMIC-1 PSU 12V Rail Curr (in2)" + label curr3 "PMIC-1 ASIC 0.8V VCORE MAIN Rail Curr (out)" + ignore curr4 + chip "xdpe12284-i2c-*-64" + label in1 "PMIC-2 PSU 12V Rail (in1)" + label in2 "PMIC-2 PSU 12V Rail (in2)" + label in3 "PMIC-2 ASIC 1.8V VCORE MAIN Rail (out)" + label in4 "PMIC-2 ASIC 1.2V VCORE MAIN Rail (out)" + label temp1 "PMIC-2 Temp 1" + label temp2 "PMIC-2 Temp 2" + label power1 "PMIC-2 PSU 12V Rail Pwr (in1)" + label power2 "PMIC-2 PSU 12V Rail Pwr (in2)" + label power3 "PMIC-2 ASIC 1.8V VCORE MAIN Rail Pwr (out)" + label power4 "PMIC-2 ASIC 1.2V VCORE MAIN Rail Pwr (out)" + label curr1 "PMIC-2 PSU 12V Rail Curr (in1)" + label curr2 "PMIC-2 PSU 12V Rail Curr (in2)" + label curr3 "PMIC-2 ASIC 1.8V VCORE MAIN Rail Curr (out)" + label curr4 "PMIC-2 ASIC 1.2V VCORE MAIN Rail Curr (out)" + chip "xdpe12284-i2c-*-66" + label in1 "PMIC-3 PSU 12V Rail (in1)" + label in2 "PMIC-3 PSU 12V Rail (in2)" + label in3 "PMIC-3 ASIC 0.85V T0_1 Rail (out)" + label in4 "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 PSU 12V Rail Pwr (in1)" + label power2 "PMIC-3 PSU 12V Rail Pwr (in2)" + label power3 "PMIC-3 ASIC 0.85V T0_1 Rail Pwr (out)" + label power4 "PMIC-3 ASIC 1.8V T0_1 Rail Pwr (out)" + label curr1 "PMIC-3 PSU 12V Rail Curr (in1)" + label curr2 "PMIC-3 PSU 12V Rail Curr (in2)" + label curr3 "PMIC-3 ASIC 0.85V T0_1 Rail Curr (out)" + label curr4 "PMIC-3 ASIC 1.8V T0_1 Rail Curr (out)" + chip "xdpe12284-i2c-*-68" + label in1 "PMIC-4 PSU 12V Rail (in1)" + label in2 "PMIC-4 PSU 12V Rail (in2)" + label in3 "PMIC-4 ASIC 0.85V T2_3 Rail (out)" + label in4 "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 PSU 12V Rail Pwr (in1)" + label power2 "PMIC-4 PSU 12V Rail Pwr (in2)" + label power3 "PMIC-4 ASIC 0.85V T2_3 Rail Pwr (out)" + label power4 "PMIC-4 ASIC 1.8V T2_3 Rail Pwr (out)" + label curr1 "PMIC-4 PSU 12V Rail Curr (in1)" + label curr2 "PMIC-4 PSU 12V Rail Curr (in2)" + label curr3 "PMIC-4 ASIC 0.85V T2_3 Rail Curr (out)" + label curr4 "PMIC-4 ASIC 1.8V T2_3 Rail Curr (out)" + chip "xdpe12284-i2c-*-6a" + label in1 "PMIC-5 PSU 12V Rail (in1)" + label in2 "PMIC-5 PSU 12V Rail (in2)" + label in3 "PMIC-5 ASIC 0.85V T4_5 Rail (out)" + label in4 "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 PSU 12V Rail Pwr (in1)" + label power2 "PMIC-5 PSU 12V Rail Pwr (in2)" + label power3 "PMIC-5 ASIC 0.85V T4_5 Rail Pwr (out)" + label power4 "PMIC-5 ASIC 1.8V T4_5 Rail Pwr (out)" + label curr1 "PMIC-5 PSU 12V Rail Curr (in1)" + label curr2 "PMIC-5 PSU 12V Rail Curr (in2)" + label curr3 "PMIC-5 ASIC 0.85V T4_5 Rail Curr (out)" + label curr4 "PMIC-5 ASIC 1.8V T4_5 Rail Curr (out)" + chip "xdpe12284-i2c-*-6c" + label in1 "PMIC-6 PSU 12V Rail (in1)" + label in2 "PMIC-6 PSU 12V Rail (in2)" + label in3 "PMIC-6 ASIC 0.85V T6_7 Rail (out)" + label in4 "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 PSU 12V Rail Pwr (in1)" + label power2 "PMIC-6 PSU 12V Rail Pwr (in2)" + label power3 "PMIC-6 ASIC 0.85V T6_7 Rail Pwr (out)" + label power4 "PMIC-6 ASIC 1.8V T6_7 Rail Pwr (out)" + label curr1 "PMIC-6 PSU 12V Rail Curr (in1)" + label curr2 "PMIC-6 PSU 12V Rail Curr (in2)" + label curr3 "PMIC-6 ASIC 0.85V T6_7 Rail Curr (out)" + label curr4 "PMIC-6 ASIC 1.8V T6_7 Rail Curr (out)" + chip "xdpe12284-i2c-*-6e" + label in1 "PMIC-7 PSU 12V Rail (in1)" + label in2 "PMIC-7 PSU 12V Rail (in2)" + label in3 "PMIC-7 ASIC 1.2V T0_3 Rail_1 (out)" + label in4 "PMIC-7 ASIC 1.2V T4_7 Rail_2 (out)" + label temp1 "PMIC-7 Temp 1" + label temp2 "PMIC-7 Temp 2" + label power1 "PMIC-7 PSU 12V Rail Pwr (in1)" + label power2 "PMIC-7 PSU 12V Rail Pwr (in2)" + label power3 "PMIC-7 ASIC 1.2V T0_3 Rail_1 Pwr (out)" + label power4 "PMIC-7 ASIC 1.2V T4_7 Rail_2 Pwr (out)" + label curr1 "PMIC-7 PSU 12V Rail Curr (in1)" + label curr2 "PMIC-7 PSU 12V Rail Curr (in2)" + label curr3 "PMIC-7 ASIC 1.2V T0_3 Rail_1 Curr (out)" + label curr4 "PMIC-7 ASIC 1.2V T4_7 Rail_2 Curr (out)" + +bus "i2c-15" "i2c-1-mux (chan_id 6)" + chip "tps53679-i2c-*-58" + label in1 "PMIC-8 PSU 12V Rail (in1)" + label in2 "PMIC-8 PSU 12V Rail (in2)" + label in3 "PMIC-8 COMEX 1.8V Rail (out)" + label in4 "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 (in1)" + label in2 "PMIC-9 PSU 12V Rail (in2)" + label in3 "PMIC-9 COMEX 1.2V Rail (out)" + ignore in4 + 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-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn4700-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..98df66c27ca5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn4700-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file 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..dd83c2db12c5 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/pmon_daemon_control.json @@ -0,0 +1,7 @@ +{ + "skip_ledd": true, + "skip_xcvrd": true, + "skip_psud": true, + "skip_pcied": true, + "skip_thermalctld": 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/mellanox/x86_64-mlnx_msn4700_simx-r0/system_health_monitoring_config.json b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/system_health_monitoring_config.json new file mode 120000 index 000000000000..42fe945344c9 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700_simx-r0/system_health_monitoring_config.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700_simx-r0/system_health_monitoring_config.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_x86-r5.0.1400/default_sku b/device/mellanox/x86_64-mlnx_x86-r5.0.1400/default_sku new file mode 100644 index 000000000000..9641115a4946 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_x86-r5.0.1400/default_sku @@ -0,0 +1 @@ +ACS-MSN2740 t1 diff --git a/device/mellanox/x86_64-mlnx_x86-r5.0.1400/installer.conf b/device/mellanox/x86_64-mlnx_x86-r5.0.1400/installer.conf new file mode 100644 index 000000000000..c9c9493a5404 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_x86-r5.0.1400/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax acpi=noirq" diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/port_config.ini b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/port_config.ini new file mode 100644 index 000000000000..1fa6d21d9609 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 49,50,51,52 hundredGigE1 +Ethernet4 53,54,55,56 hundredGigE2 +Ethernet8 57,58,59,60 hundredGigE3 +Ethernet12 61,62,63,64 hundredGigE4 +Ethernet16 65,66,67,68 hundredGigE5 +Ethernet20 69,70,71,72 hundredGigE6 +Ethernet24 73,74,75,76 hundredGigE7 +Ethernet28 77,78,79,80 hundredGigE8 +Ethernet32 33,34,35,36 hundredGigE9 +Ethernet36 37,38,39,40 hundredGigE10 +Ethernet40 41,42,43,44 hundredGigE11 +Ethernet44 45,46,47,48 hundredGigE12 +Ethernet48 81,82,83,84 hundredGigE13 +Ethernet52 85,86,87,88 hundredGigE14 +Ethernet56 89,90,91,92 hundredGigE15 +Ethernet60 93,94,95,96 hundredGigE16 +Ethernet64 97,98,99,100 hundredGigE17 +Ethernet68 101,102,103,104 hundredGigE18 +Ethernet72 105,106,107,108 hundredGigE19 +Ethernet76 109,110,111,112 hundredGigE20 +Ethernet80 17,18,19,20 hundredGigE21 +Ethernet84 21,22,23,24 hundredGigE22 +Ethernet88 25,26,27,28 hundredGigE23 +Ethernet92 29,30,31,32 hundredGigE24 +Ethernet96 113,114,115,116 hundredGigE25 +Ethernet100 117,118,119,120 hundredGigE26 +Ethernet104 121,122,123,124 hundredGigE27 +Ethernet108 125,126,127,128 hundredGigE28 +Ethernet112 1,2,3,4 hundredGigE29 +Ethernet116 5,6,7,8 hundredGigE30 +Ethernet120 9,10,11,12 hundredGigE31 +Ethernet124 13,14,15,16 hundredGigE32 diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/sai.profile b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/sai.profile new file mode 100644 index 000000000000..c32774b9677c --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-ly1200-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/th-ly1200-32x100G.config.bcm b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/th-ly1200-32x100G.config.bcm new file mode 100644 index 000000000000..9bf869f16bcf --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/th-ly1200-32x100G.config.bcm @@ -0,0 +1,319 @@ +### BMS (start) +## Global settings +bcm_num_cos=10 +dport_map_indexed=0 + +## Switch settings +# Port number and bandwidth assignment. +portmap_1=1:100 +portmap_5=5:100 +portmap_9=9:100 +portmap_13=13:100 +portmap_17=17:100 +portmap_21=21:100 +portmap_25=25:100 +portmap_29=29:100 +portmap_34=33:100 +portmap_38=37:100 +portmap_42=41:100 +portmap_46=45:100 +portmap_50=49:100 +portmap_54=53:100 +portmap_58=57:100 +portmap_62=61:100 +portmap_68=65:100 +portmap_72=69:100 +portmap_76=73:100 +portmap_80=77:100 +portmap_84=81:100 +portmap_88=85:100 +portmap_92=89:100 +portmap_96=93:100 +portmap_102=97:100 +portmap_106=101:100 +portmap_110=105:100 +portmap_114=109:100 +portmap_118=113:100 +portmap_122=117:100 +portmap_126=121:100 +portmap_130=125:100 + +# pbmp_xport_xe is used to specify if a XPORT block is configured as xe port +# By default, an XPORT block is treated as HG port. +pbmp_xport_xe=0x0444444441111111104444444422222222 + +# Map dport number to internal port number . +dport_map_port_0=327 +dport_map_port_1=112 +dport_map_port_5=116 +dport_map_port_9=120 +dport_map_port_13=124 +dport_map_port_17=80 +dport_map_port_21=84 +dport_map_port_25=88 +dport_map_port_29=92 +dport_map_port_34=32 +dport_map_port_38=36 +dport_map_port_42=40 +dport_map_port_46=44 +dport_map_port_50=0 +dport_map_port_54=4 +dport_map_port_58=8 +dport_map_port_62=12 +dport_map_port_68=16 +dport_map_port_72=20 +dport_map_port_76=24 +dport_map_port_80=28 +dport_map_port_84=48 +dport_map_port_88=52 +dport_map_port_92=56 +dport_map_port_96=60 +dport_map_port_102=64 +dport_map_port_106=68 +dport_map_port_110=72 +dport_map_port_114=76 +dport_map_port_118=96 +dport_map_port_122=100 +dport_map_port_126=104 +dport_map_port_130=108 + +# Remap XGXS rx and tx lanes to desired mapping. Four bits were used for +# specifying each lane in the format of Lane 0 (bit 15-12), Lane 1 (bit 11-8), +# lane 2 (bit 7-4), and lane 3 (bit 3-0). +# For example, to reverse the tx lane mapping in 3, 2, 1, 0 order, +xgxs_tx_lane_map_ce0=0x3210 +xgxs_rx_lane_map_ce0=0x3210 +xgxs_tx_lane_map_ce4=0x3210 +xgxs_rx_lane_map_ce4=0x2103 +xgxs_tx_lane_map_ce8=0x3210 +xgxs_rx_lane_map_ce8=0x3210 +xgxs_tx_lane_map_ce12=0x3210 +xgxs_rx_lane_map_ce12=0x2103 +xgxs_tx_lane_map_ce16=0x0123 +xgxs_rx_lane_map_ce16=0x0123 +xgxs_tx_lane_map_ce20=0x3210 +xgxs_rx_lane_map_ce20=0x2103 +xgxs_tx_lane_map_ce24=0x3210 +xgxs_rx_lane_map_ce24=0x3210 +xgxs_tx_lane_map_ce28=0x0123 +xgxs_rx_lane_map_ce28=0x1203 +xgxs_tx_lane_map_ce32=0x3210 +xgxs_rx_lane_map_ce32=0x3210 +xgxs_tx_lane_map_ce36=0x2301 +xgxs_rx_lane_map_ce36=0x3120 +xgxs_tx_lane_map_ce40=0x3210 +xgxs_rx_lane_map_ce40=0x3210 +xgxs_tx_lane_map_ce44=0x3102 +xgxs_rx_lane_map_ce44=0x2301 +xgxs_tx_lane_map_ce48=0x3210 +xgxs_rx_lane_map_ce48=0x1203 +xgxs_tx_lane_map_ce52=0x0123 +xgxs_rx_lane_map_ce52=0x3210 +xgxs_tx_lane_map_ce56=0x3210 +xgxs_rx_lane_map_ce56=0x1203 +xgxs_tx_lane_map_ce60=0x0213 +xgxs_rx_lane_map_ce60=0x3210 +xgxs_tx_lane_map_ce64=0x3120 +xgxs_rx_lane_map_ce64=0x1032 +xgxs_tx_lane_map_ce68=0x0123 +xgxs_rx_lane_map_ce68=0x3012 +xgxs_tx_lane_map_ce72=0x1230 +xgxs_rx_lane_map_ce72=0x1032 +xgxs_tx_lane_map_ce76=0x0123 +xgxs_rx_lane_map_ce76=0x3012 +xgxs_tx_lane_map_ce80=0x0213 +xgxs_rx_lane_map_ce80=0x2031 +xgxs_tx_lane_map_ce84=0x2301 +xgxs_rx_lane_map_ce84=0x3120 +xgxs_tx_lane_map_ce88=0x3210 +xgxs_rx_lane_map_ce88=0x3210 +xgxs_tx_lane_map_ce92=0x2301 +xgxs_rx_lane_map_ce92=0x3120 +xgxs_tx_lane_map_ce96=0x3210 +xgxs_rx_lane_map_ce96=0x0321 +xgxs_tx_lane_map_ce100=0x0123 +xgxs_rx_lane_map_ce100=0x1032 +xgxs_tx_lane_map_ce104=0x0123 +xgxs_rx_lane_map_ce104=0x0123 +xgxs_tx_lane_map_ce108=0x3210 +xgxs_rx_lane_map_ce108=0x2103 +xgxs_tx_lane_map_ce112=0x0123 +xgxs_rx_lane_map_ce112=0x0123 +xgxs_tx_lane_map_ce116=0x0123 +xgxs_rx_lane_map_ce116=0x1230 +xgxs_tx_lane_map_ce120=0x0123 +xgxs_rx_lane_map_ce120=0x0123 +xgxs_tx_lane_map_ce124=0x0123 +xgxs_rx_lane_map_ce124=0x1230 + +# Config to describe the system Linerate or Oversubscribe mode. +# 0: Linerate only (default). +# 1: Oversubscribe mode (all ports will be oversub). +# 2: Mixed mode. Check device specification for applicability. Port bitmap specified via pbmp_oversubscribe. +oversubscribe_mode=1 + +# Set the default MMU lossless behavior. +mmu_lossless=0 + +# Set preemphasis +serdes_preemphasis_lane0_ce0=0x2c3c08 +serdes_preemphasis_lane1_ce0=0x2c3c08 +serdes_preemphasis_lane2_ce0=0x2c3c08 +serdes_preemphasis_lane3_ce0=0x2c3c08 + +serdes_preemphasis_lane0_ce4=0x2c3c08 +serdes_preemphasis_lane1_ce4=0x2c3c08 +serdes_preemphasis_lane2_ce4=0x2c3c08 +serdes_preemphasis_lane3_ce4=0x2c3c08 + +serdes_preemphasis_lane0_ce8=0x2c3c08 +serdes_preemphasis_lane1_ce8=0x2c3c08 +serdes_preemphasis_lane2_ce8=0x2c3c08 +serdes_preemphasis_lane3_ce8=0x2c3c08 + +serdes_preemphasis_lane0_ce12=0x2c3c08 +serdes_preemphasis_lane1_ce12=0x2c3c08 +serdes_preemphasis_lane2_ce12=0x2c3c08 +serdes_preemphasis_lane3_ce12=0x2c3c08 + +serdes_preemphasis_lane0_ce16=0x244408 +serdes_preemphasis_lane1_ce16=0x244408 +serdes_preemphasis_lane2_ce16=0x244408 +serdes_preemphasis_lane3_ce16=0x244408 + +serdes_preemphasis_lane0_ce20=0x244408 +serdes_preemphasis_lane1_ce20=0x244408 +serdes_preemphasis_lane2_ce20=0x244408 +serdes_preemphasis_lane3_ce20=0x244408 + +serdes_preemphasis_lane0_ce24=0x244408 +serdes_preemphasis_lane1_ce24=0x244408 +serdes_preemphasis_lane2_ce24=0x244408 +serdes_preemphasis_lane3_ce24=0x244408 + +serdes_preemphasis_lane0_ce28=0x244408 +serdes_preemphasis_lane1_ce28=0x244408 +serdes_preemphasis_lane2_ce28=0x244408 +serdes_preemphasis_lane3_ce28=0x244408 + +serdes_preemphasis_lane0_ce32=0x2c3c08 +serdes_preemphasis_lane1_ce32=0x2c3c08 +serdes_preemphasis_lane2_ce32=0x2c3c08 +serdes_preemphasis_lane3_ce32=0x2c3c08 + +serdes_preemphasis_lane0_ce36=0x2c3c08 +serdes_preemphasis_lane1_ce36=0x2c3c08 +serdes_preemphasis_lane2_ce36=0x2c3c08 +serdes_preemphasis_lane3_ce36=0x2c3c08 + +serdes_preemphasis_lane0_ce40=0x2c3c08 +serdes_preemphasis_lane1_ce40=0x2c3c08 +serdes_preemphasis_lane2_ce40=0x2c3c08 +serdes_preemphasis_lane3_ce40=0x2c3c08 + +serdes_preemphasis_lane0_ce44=0x244408 +serdes_preemphasis_lane1_ce44=0x244408 +serdes_preemphasis_lane2_ce44=0x244408 +serdes_preemphasis_lane3_ce44=0x244408 + +serdes_preemphasis_lane0_ce48=0x244408 +serdes_preemphasis_lane1_ce48=0x244408 +serdes_preemphasis_lane2_ce48=0x244408 +serdes_preemphasis_lane3_ce48=0x244408 + +serdes_preemphasis_lane0_ce52=0x244408 +serdes_preemphasis_lane1_ce52=0x244408 +serdes_preemphasis_lane2_ce52=0x244408 +serdes_preemphasis_lane3_ce52=0x244408 + +serdes_preemphasis_lane0_ce56=0x244408 +serdes_preemphasis_lane1_ce56=0x244408 +serdes_preemphasis_lane2_ce56=0x244408 +serdes_preemphasis_lane3_ce56=0x244408 + +serdes_preemphasis_lane0_ce60=0x244408 +serdes_preemphasis_lane1_ce60=0x244408 +serdes_preemphasis_lane2_ce60=0x244408 +serdes_preemphasis_lane3_ce60=0x244408 + +serdes_preemphasis_lane0_ce64=0x244408 +serdes_preemphasis_lane1_ce64=0x244408 +serdes_preemphasis_lane2_ce64=0x244408 +serdes_preemphasis_lane3_ce64=0x244408 + +serdes_preemphasis_lane0_ce68=0x244408 +serdes_preemphasis_lane1_ce68=0x244408 +serdes_preemphasis_lane2_ce68=0x244408 +serdes_preemphasis_lane3_ce68=0x244408 + +serdes_preemphasis_lane0_ce72=0x244408 +serdes_preemphasis_lane1_ce72=0x244408 +serdes_preemphasis_lane2_ce72=0x244408 +serdes_preemphasis_lane3_ce72=0x244408 + +serdes_preemphasis_lane0_ce76=0x244408 +serdes_preemphasis_lane1_ce76=0x244408 +serdes_preemphasis_lane2_ce76=0x244408 +serdes_preemphasis_lane3_ce76=0x244408 + +serdes_preemphasis_lane0_ce80=0x244408 +serdes_preemphasis_lane1_ce80=0x244408 +serdes_preemphasis_lane2_ce80=0x244408 +serdes_preemphasis_lane3_ce80=0x244408 + +serdes_preemphasis_lane0_ce84=0x2c3c08 +serdes_preemphasis_lane1_ce84=0x2c3c08 +serdes_preemphasis_lane2_ce84=0x2c3c08 +serdes_preemphasis_lane3_ce84=0x2c3c08 + +serdes_preemphasis_lane0_ce88=0x2c3c08 +serdes_preemphasis_lane1_ce88=0x2c3c08 +serdes_preemphasis_lane2_ce88=0x2c3c08 +serdes_preemphasis_lane3_ce88=0x2c3c08 + +serdes_preemphasis_lane0_ce92=0x2c3c08 +serdes_preemphasis_lane1_ce92=0x2c3c08 +serdes_preemphasis_lane2_ce92=0x2c3c08 +serdes_preemphasis_lane3_ce92=0x2c3c08 + +serdes_preemphasis_lane0_ce96=0x244408 +serdes_preemphasis_lane1_ce96=0x244408 +serdes_preemphasis_lane2_ce96=0x244408 +serdes_preemphasis_lane3_ce96=0x244408 + +serdes_preemphasis_lane0_ce100=0x244408 +serdes_preemphasis_lane1_ce100=0x244408 +serdes_preemphasis_lane2_ce100=0x244408 +serdes_preemphasis_lane3_ce100=0x244408 + +serdes_preemphasis_lane0_ce104=0x244408 +serdes_preemphasis_lane1_ce104=0x244408 +serdes_preemphasis_lane2_ce104=0x244408 +serdes_preemphasis_lane3_ce104=0x244408 + +serdes_preemphasis_lane0_ce108=0x244408 +serdes_preemphasis_lane1_ce108=0x244408 +serdes_preemphasis_lane2_ce108=0x244408 +serdes_preemphasis_lane3_ce108=0x244408 + +serdes_preemphasis_lane0_ce112=0x2c3c08 +serdes_preemphasis_lane1_ce112=0x2c3c08 +serdes_preemphasis_lane2_ce112=0x2c3c08 +serdes_preemphasis_lane3_ce112=0x2c3c08 + +serdes_preemphasis_lane0_ce116=0x2c3c08 +serdes_preemphasis_lane1_ce116=0x2c3c08 +serdes_preemphasis_lane2_ce116=0x2c3c08 +serdes_preemphasis_lane3_ce116=0x2c3c08 + +serdes_preemphasis_lane0_ce120=0x2c3c08 +serdes_preemphasis_lane1_ce120=0x2c3c08 +serdes_preemphasis_lane2_ce120=0x2c3c08 +serdes_preemphasis_lane3_ce120=0x2c3c08 + +serdes_preemphasis_lane0_ce124=0x2c3c08 +serdes_preemphasis_lane1_ce124=0x2c3c08 +serdes_preemphasis_lane2_ce124=0x2c3c08 +serdes_preemphasis_lane3_ce124=0x2c3c08 + +### BMS (end) \ No newline at end of file diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/default_sku b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/default_sku new file mode 100644 index 000000000000..b533cbe35c56 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/default_sku @@ -0,0 +1 @@ +MiTAC-LY1200-B32H0-C3 t1 diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf new file mode 100644 index 000000000000..8d4683add468 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf @@ -0,0 +1,4 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax pcie_aspm=off irqpoll" diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/led_proc_init.soc b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/led_proc_init.soc new file mode 100644 index 000000000000..867cd1b6fe37 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/led_proc_init.soc @@ -0,0 +1,43 @@ +m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31 REMAP_PORT_1=30 REMAP_PORT_2=29 REMAP_PORT_3=28 +m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27 REMAP_PORT_5=26 REMAP_PORT_6=25 REMAP_PORT_7=24 +m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23 REMAP_PORT_9=22 REMAP_PORT_10=21 REMAP_PORT_11=20 +m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19 REMAP_PORT_13=18 REMAP_PORT_14=17 REMAP_PORT_15=16 +m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=63 REMAP_PORT_17=62 REMAP_PORT_18=61 REMAP_PORT_19=60 +m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=59 REMAP_PORT_21=58 REMAP_PORT_22=57 REMAP_PORT_23=56 +m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=55 REMAP_PORT_25=54 REMAP_PORT_26=53 REMAP_PORT_27=52 +m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=51 REMAP_PORT_29=50 REMAP_PORT_30=49 REMAP_PORT_31=48 +m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=47 REMAP_PORT_33=46 REMAP_PORT_34=45 REMAP_PORT_35=44 +m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=43 REMAP_PORT_37=42 REMAP_PORT_38=41 REMAP_PORT_39=40 +m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=39 REMAP_PORT_41=38 REMAP_PORT_42=37 REMAP_PORT_43=36 +m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=35 REMAP_PORT_45=34 REMAP_PORT_46=33 REMAP_PORT_47=32 +m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12 +m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8 +m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4 +m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0 + +m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=35 REMAP_PORT_1=34 REMAP_PORT_2=33 REMAP_PORT_3=32 +m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=39 REMAP_PORT_5=38 REMAP_PORT_6=37 REMAP_PORT_7=36 +m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=43 REMAP_PORT_9=42 REMAP_PORT_10=41 REMAP_PORT_11=40 +m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=47 REMAP_PORT_13=46 REMAP_PORT_14=45 REMAP_PORT_15=44 +m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=3 REMAP_PORT_17=2 REMAP_PORT_18=1 REMAP_PORT_19=0 +m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=7 REMAP_PORT_21=6 REMAP_PORT_22=5 REMAP_PORT_23=4 +m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=11 REMAP_PORT_25=10 REMAP_PORT_26=9 REMAP_PORT_27=8 +m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=15 REMAP_PORT_29=14 REMAP_PORT_30=13 REMAP_PORT_31=12 +m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19 REMAP_PORT_33=18 REMAP_PORT_34=17 REMAP_PORT_35=16 +m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23 REMAP_PORT_37=22 REMAP_PORT_38=21 REMAP_PORT_39=20 +m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27 REMAP_PORT_41=26 REMAP_PORT_42=25 REMAP_PORT_43=24 +m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31 REMAP_PORT_45=30 REMAP_PORT_46=29 REMAP_PORT_47=28 +m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48 +m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52 +m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56 +m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60 + +led 0 prog 06 EE 80 D2 0A 71 08 E0 60 EE E9 D2 05 75 10 81 61 ED 02 00 12 A0 F8 15 67 22 F2 01 D2 40 74 14 3A 80 28 32 08 97 71 2A 77 65 1A 07 71 30 77 3C 1A 02 27 1A 03 27 C7 97 71 5E 77 4A 28 32 00 32 01 B7 26 ED C7 97 75 50 77 65 1A 02 71 50 77 57 32 0E 87 32 0F 87 57 32 0F 87 32 0E 87 57 32 0E 87 32 0E 87 57 32 0F 87 32 0F 87 57 + +led 0 start + +led 1 prog 06 EE 80 D2 0A 71 08 E0 60 EE E9 D2 05 75 10 81 61 ED 02 00 12 A0 F8 15 67 22 F2 01 D2 40 74 14 3A 80 28 32 08 97 71 2A 77 65 1A 07 71 30 77 3C 1A 02 27 1A 03 27 C7 97 71 5E 77 4A 28 32 00 32 01 B7 26 ED C7 97 75 50 77 65 1A 02 71 50 77 57 32 0E 87 32 0F 87 57 32 0F 87 32 0E 87 57 32 0E 87 32 0E 87 57 32 0F 87 32 0F 87 57 + +led 1 start + +led auto on diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/eeprom.py b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/eeprom.py new file mode 100644 index 000000000000..96dc19ad5b36 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/eeprom.py @@ -0,0 +1,23 @@ +try: + 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 as 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/2-0050/eeprom" + # Two i2c buses might get flipped order, check them both. + if not os.path.exists(self.eeprom_path): + self.eeprom_path = "/sys/bus/i2c/devices/2-0050/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/sfputil.py b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/sfputil.py new file mode 100644 index 000000000000..97c04f6d0d43 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/sfputil.py @@ -0,0 +1,192 @@ +# sfputil.py +# +# 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 = 0 + PORT_END = 31 + PORTS_IN_BLOCK = 32 + + EEPROM_OFFSET = 10 + + _port_to_eeprom_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 list(range(0, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + 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 < self.port_start or port_num > self.port_end: + return False + + if port_num > 16: + cpld_addr = 33 + else: + cpld_addr = 32 + + file_path = "/sys/bus/i2c/devices/1-00" + \ + str(cpld_addr) + "/port" + str(port_num) + "/port" + str(port_num) + "_present" + + try: + reg_file = open("file_path") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # ModPrsL is active low + if reg_value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + if port_num > 16: + cpld_addr = 33 + else: + cpld_addr = 32 + + file_path = "/sys/bus/i2c/devices/1-00" + \ + str(cpld_addr) + "/port" + str(port_num) + "/port" + str(port_num) + "_lpmode" + + try: + reg_file = open(file_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # LPMode is active high + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + if port_num > 16: + cpld_addr = 33 + else: + cpld_addr = 32 + + file_path = "/sys/bus/i2c/devices/1-00" + \ + str(cpld_num) + "/port" + str(port_num) + "/port" + str(port_num) + "_lpmode" + + try: + reg_file = open(file_path, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def reset(self, port_num): + + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + if port_num > 16: + cpld_addr = 33 + else: + cpld_addr = 32 + + file_path = "/sys/bus/i2c/devices/1-00" + \ + str(cpld_num) + "/port" + str(port_num) + "/port" + str(port_num) + "_rst" + + try: + reg_file = open(file_path, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + # ResetL is active low + reg_value = 0 + + # Convert our register value back to a hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(QSFP_RESET_REGISTER_DEVICE_FILE, "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/buffers.json.j2 b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/buffers.json.j2 new file mode 100644 index 000000000000..a38350a982bc --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/buffers.json.j2 @@ -0,0 +1,10 @@ +{# Default values placeholder M0- Marvell SAI TBD buffers configuration #} + +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{} + diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/buffers_defaults_t1.j2 b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/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/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/port_config.ini b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/port_config.ini new file mode 100644 index 000000000000..062c252ce195 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/port_config.ini @@ -0,0 +1,53 @@ +# name lanes alias index speed +Ethernet0 1 Ethernet0 1 1000 +Ethernet1 2 Ethernet1 2 1000 +Ethernet2 3 Ethernet2 3 1000 +Ethernet3 4 Ethernet3 4 1000 +Ethernet4 5 Ethernet4 5 1000 +Ethernet5 6 Ethernet5 6 1000 +Ethernet6 7 Ethernet6 7 1000 +Ethernet7 8 Ethernet7 8 1000 +Ethernet8 9 Ethernet8 9 1000 +Ethernet9 10 Ethernet9 10 1000 +Ethernet10 11 Ethernet10 11 1000 +Ethernet11 12 Ethernet11 12 1000 +Ethernet12 13 Ethernet12 13 1000 +Ethernet13 14 Ethernet13 14 1000 +Ethernet14 15 Ethernet14 15 1000 +Ethernet15 16 Ethernet15 16 1000 +Ethernet16 17 Ethernet16 17 1000 +Ethernet17 18 Ethernet17 18 1000 +Ethernet18 19 Ethernet18 19 1000 +Ethernet19 20 Ethernet19 20 1000 +Ethernet20 21 Ethernet20 21 1000 +Ethernet21 22 Ethernet21 22 1000 +Ethernet22 23 Ethernet22 23 1000 +Ethernet23 24 Ethernet23 24 1000 +Ethernet24 25 Ethernet24 25 1000 +Ethernet25 26 Ethernet25 26 1000 +Ethernet26 27 Ethernet26 27 1000 +Ethernet27 28 Ethernet27 28 1000 +Ethernet28 29 Ethernet28 29 1000 +Ethernet29 30 Ethernet29 30 1000 +Ethernet30 31 Ethernet30 31 1000 +Ethernet31 32 Ethernet31 32 1000 +Ethernet32 33 Ethernet32 33 1000 +Ethernet33 34 Ethernet33 34 1000 +Ethernet34 35 Ethernet34 35 1000 +Ethernet35 36 Ethernet35 36 1000 +Ethernet36 37 Ethernet36 37 1000 +Ethernet37 38 Ethernet37 38 1000 +Ethernet38 39 Ethernet38 39 1000 +Ethernet39 40 Ethernet39 40 1000 +Ethernet40 41 Ethernet40 41 1000 +Ethernet41 42 Ethernet41 42 1000 +Ethernet42 43 Ethernet42 43 1000 +Ethernet43 44 Ethernet43 44 1000 +Ethernet44 45 Ethernet44 45 1000 +Ethernet45 46 Ethernet45 46 1000 +Ethernet46 47 Ethernet46 47 1000 +Ethernet47 48 Ethernet47 48 1000 +Ethernet48 49 Ethernet48 49 10000 +Ethernet49 50 Ethernet49 50 10000 +Ethernet50 51 Ethernet50 51 10000 +Ethernet51 52 Ethernet51 52 10000 diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/port_config.ini.inband b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/port_config.ini.inband new file mode 100644 index 000000000000..556da9c62254 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/port_config.ini.inband @@ -0,0 +1,52 @@ +# name lanes alias index speed +Ethernet0 1 Ethernet0 1 1000 +Ethernet1 2 Ethernet1 2 1000 +Ethernet2 3 Ethernet2 3 1000 +Ethernet3 4 Ethernet3 4 1000 +Ethernet4 5 Ethernet4 5 1000 +Ethernet5 6 Ethernet5 6 1000 +Ethernet6 7 Ethernet6 7 1000 +Ethernet7 8 Ethernet7 8 1000 +Ethernet8 9 Ethernet8 9 1000 +Ethernet9 10 Ethernet9 10 1000 +Ethernet10 11 Ethernet10 11 1000 +Ethernet11 12 Ethernet11 12 1000 +Ethernet12 13 Ethernet12 13 1000 +Ethernet13 14 Ethernet13 14 1000 +Ethernet14 15 Ethernet14 15 1000 +Ethernet15 16 Ethernet15 16 1000 +Ethernet16 17 Ethernet16 17 1000 +Ethernet17 18 Ethernet17 18 1000 +Ethernet18 19 Ethernet18 19 1000 +Ethernet19 20 Ethernet19 20 1000 +Ethernet20 21 Ethernet20 21 1000 +Ethernet21 22 Ethernet21 22 1000 +Ethernet22 23 Ethernet22 23 1000 +Ethernet23 24 Ethernet23 24 1000 +Ethernet24 25 Ethernet24 25 1000 +Ethernet25 26 Ethernet25 26 1000 +Ethernet26 27 Ethernet26 27 1000 +Ethernet27 28 Ethernet27 28 1000 +Ethernet28 29 Ethernet28 29 1000 +Ethernet29 30 Ethernet29 30 1000 +Ethernet30 31 Ethernet30 31 1000 +Ethernet31 32 Ethernet31 32 1000 +Ethernet32 33 Ethernet32 33 1000 +Ethernet33 34 Ethernet33 34 1000 +Ethernet34 35 Ethernet34 35 1000 +Ethernet35 36 Ethernet35 36 1000 +Ethernet36 37 Ethernet36 37 1000 +Ethernet37 38 Ethernet37 38 1000 +Ethernet38 39 Ethernet38 39 1000 +Ethernet39 40 Ethernet39 40 1000 +Ethernet40 41 Ethernet40 41 1000 +Ethernet41 42 Ethernet41 42 1000 +Ethernet42 43 Ethernet42 43 1000 +Ethernet43 44 Ethernet43 44 1000 +Ethernet44 45 Ethernet44 45 1000 +Ethernet45 46 Ethernet45 46 1000 +Ethernet46 47 Ethernet46 47 1000 +Ethernet48 49 Ethernet48 49 10000 +Ethernet49 50 Ethernet49 50 10000 +Ethernet50 51 Ethernet50 51 10000 +Ethernet51 52 Ethernet51 52 10000 diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/port_config.ini.noinband b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/port_config.ini.noinband new file mode 100644 index 000000000000..062c252ce195 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/port_config.ini.noinband @@ -0,0 +1,53 @@ +# name lanes alias index speed +Ethernet0 1 Ethernet0 1 1000 +Ethernet1 2 Ethernet1 2 1000 +Ethernet2 3 Ethernet2 3 1000 +Ethernet3 4 Ethernet3 4 1000 +Ethernet4 5 Ethernet4 5 1000 +Ethernet5 6 Ethernet5 6 1000 +Ethernet6 7 Ethernet6 7 1000 +Ethernet7 8 Ethernet7 8 1000 +Ethernet8 9 Ethernet8 9 1000 +Ethernet9 10 Ethernet9 10 1000 +Ethernet10 11 Ethernet10 11 1000 +Ethernet11 12 Ethernet11 12 1000 +Ethernet12 13 Ethernet12 13 1000 +Ethernet13 14 Ethernet13 14 1000 +Ethernet14 15 Ethernet14 15 1000 +Ethernet15 16 Ethernet15 16 1000 +Ethernet16 17 Ethernet16 17 1000 +Ethernet17 18 Ethernet17 18 1000 +Ethernet18 19 Ethernet18 19 1000 +Ethernet19 20 Ethernet19 20 1000 +Ethernet20 21 Ethernet20 21 1000 +Ethernet21 22 Ethernet21 22 1000 +Ethernet22 23 Ethernet22 23 1000 +Ethernet23 24 Ethernet23 24 1000 +Ethernet24 25 Ethernet24 25 1000 +Ethernet25 26 Ethernet25 26 1000 +Ethernet26 27 Ethernet26 27 1000 +Ethernet27 28 Ethernet27 28 1000 +Ethernet28 29 Ethernet28 29 1000 +Ethernet29 30 Ethernet29 30 1000 +Ethernet30 31 Ethernet30 31 1000 +Ethernet31 32 Ethernet31 32 1000 +Ethernet32 33 Ethernet32 33 1000 +Ethernet33 34 Ethernet33 34 1000 +Ethernet34 35 Ethernet34 35 1000 +Ethernet35 36 Ethernet35 36 1000 +Ethernet36 37 Ethernet36 37 1000 +Ethernet37 38 Ethernet37 38 1000 +Ethernet38 39 Ethernet38 39 1000 +Ethernet39 40 Ethernet39 40 1000 +Ethernet40 41 Ethernet40 41 1000 +Ethernet41 42 Ethernet41 42 1000 +Ethernet42 43 Ethernet42 43 1000 +Ethernet43 44 Ethernet43 44 1000 +Ethernet44 45 Ethernet44 45 1000 +Ethernet45 46 Ethernet45 46 1000 +Ethernet46 47 Ethernet46 47 1000 +Ethernet47 48 Ethernet47 48 1000 +Ethernet48 49 Ethernet48 49 10000 +Ethernet49 50 Ethernet49 50 10000 +Ethernet50 51 Ethernet50 51 10000 +Ethernet51 52 Ethernet51 52 10000 diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/profile.ini b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/profile.ini new file mode 100644 index 000000000000..c908d9235215 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/profile.ini @@ -0,0 +1,2 @@ +switchMacAddress=XX:XX:XX:XX:XX:XX +ledMode=ac3x97bits diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/profile.ini.inband b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/profile.ini.inband new file mode 100644 index 000000000000..6a82d5939c3b --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/profile.ini.inband @@ -0,0 +1,3 @@ +switchMacAddress=XX:XX:XX:XX:XX:XX +inbandMgmtPortNum=48 +ledMode=ac3x97bits diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/profile.ini.noinband b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/profile.ini.noinband new file mode 100644 index 000000000000..c908d9235215 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/profile.ini.noinband @@ -0,0 +1,2 @@ +switchMacAddress=XX:XX:XX:XX:XX:XX +ledMode=ac3x97bits diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/qos.json.j2 b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/qos.json.j2 new file mode 100644 index 000000000000..c28e2e13e974 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/qos.json.j2 @@ -0,0 +1,2 @@ +{# this file empty temporarily until qos supported SAI Marvell #} +{} diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/sai.profile b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/sai.profile new file mode 100644 index 000000000000..10053fa935a1 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/Nokia-7215/sai.profile @@ -0,0 +1,3 @@ +mode=1 +hwId=et6448m +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/default_sku b/device/nokia/armhf-nokia_ixs7215_52x-r0/default_sku new file mode 100644 index 000000000000..5c41b116898d --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/default_sku @@ -0,0 +1 @@ +Nokia-7215 l2 diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/pcie.yaml b/device/nokia/armhf-nokia_ixs7215_52x-r0/pcie.yaml new file mode 100644 index 000000000000..f24086a2228b --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/pcie.yaml @@ -0,0 +1,20 @@ +- bus: '00' + dev: '01' + fn: '0' + id: '6820' + name: 'PCI bridge: Marvell Technology Group Ltd. Device 6820 (rev 0a)' +- bus: '00' + dev: '02' + fn: '0' + id: '6820' + name: 'PCI bridge: Marvell Technology Group Ltd. Device 6820 (rev 0a)' +- bus: '01' + dev: '00' + fn: '0' + id: c804 + name: 'Ethernet controller: Marvell Technology Group Ltd. Device c804' +- bus: '02' + dev: '00' + fn: '0' + id: c804 + name: 'Ethernet controller: Marvell Technology Group Ltd. Device c804' diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/platform.json b/device/nokia/armhf-nokia_ixs7215_52x-r0/platform.json new file mode 100644 index 000000000000..d6a28d19b026 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/platform.json @@ -0,0 +1,226 @@ +{ + "chassis": { + "name": "7215 IXS-T1", + "components": [ + { + "name": "System-CPLD" + }, + { + "name": "U-Boot" + } + ], + "fans": [ + { + "name": "Fan1" + }, + { + "name": "Fan2" + } + ], + "fan_drawers": [ + { + "name": "drawer1", + "fans": [ + { + "name": "Fan1" + } + ] + }, + { + "name": "drawer2", + "fans": [ + { + "name": "Fan2" + } + ] + } + ], + "psus": [ + { + "name": "PSU1" + }, + { + "name": "PSU2" + } + ], + "thermals": [ + { + "name": "PCB PHY" + }, + { + "name": "PCB MAC" + }, + { + "name": "ADT7473-CPU" + }, + { + "name": "ADT7473-LOC" + }, + { + "name": "ADT7473-MAC" + }, + { + "name": "CPU Core" + } + ], + "sfps": [ + { + "name": "Ethernet0" + }, + { + "name": "Ethernet1" + }, + { + "name": "Ethernet2" + }, + { + "name": "Ethernet3" + }, + { + "name": "Ethernet4" + }, + { + "name": "Ethernet5" + }, + { + "name": "Ethernet6" + }, + { + "name": "Ethernet7" + }, + { + "name": "Ethernet8" + }, + { + "name": "Ethernet9" + }, + { + "name": "Ethernet10" + }, + { + "name": "Ethernet11" + }, + { + "name": "Ethernet12" + }, + { + "name": "Ethernet13" + }, + { + "name": "Ethernet14" + }, + { + "name": "Ethernet15" + }, + { + "name": "Ethernet16" + }, + { + "name": "Ethernet17" + }, + { + "name": "Ethernet18" + }, + { + "name": "Ethernet19" + }, + { + "name": "Ethernet20" + }, + { + "name": "Ethernet21" + }, + { + "name": "Ethernet22" + }, + { + "name": "Ethernet23" + }, + { + "name": "Ethernet24" + }, + { + "name": "Ethernet25" + }, + { + "name": "Ethernet26" + }, + { + "name": "Ethernet27" + }, + { + "name": "Ethernet28" + }, + { + "name": "Ethernet29" + }, + { + "name": "Ethernet30" + }, + { + "name": "Ethernet31" + }, + { + "name": "Ethernet32" + }, + { + "name": "Ethernet33" + }, + { + "name": "Ethernet34" + }, + { + "name": "Ethernet35" + }, + { + "name": "Ethernet36" + }, + { + "name": "Ethernet37" + }, + { + "name": "Ethernet38" + }, + { + "name": "Ethernet39" + }, + { + "name": "Ethernet40" + }, + { + "name": "Ethernet41" + }, + { + "name": "Ethernet42" + }, + { + "name": "Ethernet43" + }, + { + "name": "Ethernet44" + }, + { + "name": "Ethernet45" + }, + { + "name": "Ethernet46" + }, + { + "name": "Ethernet47" + }, + { + "name": "Ethernet48" + }, + { + "name": "Ethernet49" + }, + { + "name": "Ethernet50" + }, + { + "name": "Ethernet51" + } + ] + }, + "interfaces": {} +} diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/platform_components.json b/device/nokia/armhf-nokia_ixs7215_52x-r0/platform_components.json new file mode 100644 index 000000000000..51dfea452f54 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/platform_components.json @@ -0,0 +1,10 @@ +{ + "chassis": { + "7215 IXS-T1": { + "component": { + "U-Boot": { }, + "System-CPLD": { } + } + } + } +} diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/platform_reboot b/device/nokia/armhf-nokia_ixs7215_52x-r0/platform_reboot new file mode 100644 index 000000000000..83fc5d8028f2 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/platform_reboot @@ -0,0 +1,11 @@ +#!/bin/bash + +function SafePwrCycle() { + sync ; sync + umount -fa > /dev/null 2&>1 + + # Write CPLD register to initiate cold reboot + sudo i2cset -f -y 0 0x41 0x10 0x00 +} + +SafePwrCycle diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/eeprom.py b/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..cbd48237cc10 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/eeprom.py @@ -0,0 +1,14 @@ +try: + import os + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0053/eeprom" + if not os.path.exists(self.eeprom_path): + os.system("echo 24c02 0x53 > /sys/class/i2c-adapter/i2c-0/new_device") + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/led_control.py b/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/led_control.py new file mode 100644 index 000000000000..935343a84ce1 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/led_control.py @@ -0,0 +1,132 @@ +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import os + import time + import syslog + import sonic_platform.platform + import sonic_platform.chassis +except ImportError as e: + raise ImportError(str(e) + " - required module not found") + +smbus_present = 1 + +try: + import smbus +except ImportError as e: + smbus_present = 0 + + +def DBG_PRINT(str): + syslog.openlog("nokia-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + + # Constructor + def __init__(self): + self.chassis = sonic_platform.platform.Platform().get_chassis() + self._initDefaultConfig() + + def _initDefaultConfig(self): + # The fan tray leds and system led managed by new chassis class API + # leaving only a couple other front panel leds to be done old style + DBG_PRINT("starting system leds") + self._initSystemLed() + DBG_PRINT(" led done") + + def _set_i2c_register(self, reg_file, value): + # On successful write, the value read will be written on + # reg_name and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(reg_file)): + return rv + try: + with open(reg_file, 'w') as fd: + rv = fd.write(str(value)) + except Exception as e: + rv = 'ERR' + + return rv + + def _initSystemLed(self): + # Front Panel System LEDs setting + oldfan = 0xf + oldpsu = 0xf + + # Write sys led + if smbus_present == 0: + DBG_PRINT(" PMON LED SET ERROR -> smbus present = 0 ") + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICEREG = 0x7 + bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, 0x02) + DBG_PRINT(" System LED set O.K. ") + + while True: + # Front Panel FAN Panel LED setting in register 0x08 + if (self.chassis.get_fan(0).get_status() == self.chassis.get_fan(1).get_status() == True): + if (os.path.isfile("/sys/class/gpio/fanLedAmber/value")): + if oldfan != 0x1: + self._set_i2c_register("/sys/class/gpio/fanLedAmber/value", 0) + self._set_i2c_register("/sys/class/gpio/fanLedGreen/value", 1) + oldfan = 0x1 + else: + oldfan = 0xf + else: + if (os.path.isfile("/sys/class/gpio/fanLedGreen/value")): + if oldfan != 0x0: + self._set_i2c_register("/sys/class/gpio/fanLedGreen/value", 0) + self._set_i2c_register("/sys/class/gpio/fanLedAmber/value", 1) + oldfan = 0x0 + else: + oldfan = 0xf + + # Front Panel PSU Panel LED setting in register 0x09 + if (self.chassis.get_psu(0).get_status() == self.chassis.get_psu(1).get_status() == True): + if (os.path.isfile("/sys/class/gpio/psuLedAmber/value")): + if oldpsu != 0x1: + self._set_i2c_register("/sys/class/gpio/psuLedAmber/value", 0) + self._set_i2c_register("/sys/class/gpio/psuLedGreen/value", 1) + oldpsu = 0x1 + else: + oldpsu = 0xf + else: + if (os.path.isfile("/sys/class/gpio/psuLedGreen/value")): + if oldpsu != 0x0: + self._set_i2c_register("/sys/class/gpio/psuLedGreen/value", 0) + self._set_i2c_register("/sys/class/gpio/psuLedAmber/value", 1) + oldpsu = 0x0 + else: + oldpsu = 0xf + time.sleep(6) + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + def _port_state_to_mode(self, port_idx, state): + DBG_PRINT("_port_state_to_mode") + + def _port_led_mode_update(self, port_idx, ledMode): + DBG_PRINT("_port_led_mode_update") + + # called when port states change- implementation of port_link_state_change() method if needed + def port_link_state_change(self, portname, state): + # DBG_PRINT("port_link_state_change ") + return diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/psuutil.py b/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/psuutil.py new file mode 100755 index 000000000000..513b3ae4085b --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/psuutil.py @@ -0,0 +1,32 @@ +try: + import sonic_platform.platform + import sonic_platform.chassis + 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.chassis = sonic_platform.platform.Platform().get_chassis() + + def get_num_psus(self): + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + # print " psuUtil redirect to PMON 2.0 " + if self.chassis is not None: + return self.chassis.get_psu(index-1).get_status() + else: + return False + + def get_psu_presence(self, index): + # print " psuUtil redirect to PMON 2.0 " + if self.chassis is not None: + return self.chassis.get_psu(index-1).get_presence() + else: + return False diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/sfputil.py b/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/sfputil.py new file mode 100755 index 000000000000..1ca3b9ec6f2d --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/plugins/sfputil.py @@ -0,0 +1,65 @@ +try: + import sonic_platform.platform + import sonic_platform.chassis + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific sfputil class""" + + _port_start = 49 + _port_end = 52 + ports_in_block = 4 + + _port_to_eeprom_mapping = {} + _changed_ports = [0, 0, 0, 0] + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return list(range(0, 0)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + # print " SfpUtil(SfpUtilBase) re-directed to chassis PMON 2.0 " + SfpUtilBase.__init__(self) + self.chassis = sonic_platform.platform.Platform().get_chassis() + + def reset(self, port_num): + # print " SfpUtil(SfpUtilBase) re-directed to chassis PMON 2.0 " + if self.chassis is not None: + return self.chassis.get_sfp(port_num).reset() + else: + return False + + def set_low_power_mode(self, port_nuM, lpmode): + # print " SfpUtil(SfpUtilBase) targeted for deprecation " + return False + + def get_low_power_mode(self, port_num): + # print " SfpUtil(SfpUtilBase) targeted for deprecation " + return False + + def get_presence(self, port_num): + # print " SfpUtil(SfpUtilBase) re-directed to chassis PMON 2.0 " + if self.chassis is not None: + return self.chassis.get_sfp(port_num).get_presence() + else: + return False + + def get_transceiver_change_event(self, timeout): + # print " SfpUtil(SfpUtilBase) targeted for deprecation " + + raise NotImplementedError diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/sensors.conf b/device/nokia/armhf-nokia_ixs7215_52x-r0/sensors.conf new file mode 100644 index 000000000000..de73eab6e987 --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/sensors.conf @@ -0,0 +1,19 @@ +chip "adt7473-*" + label fan1 "rear fan 1" + label fan2 "rear fan 2" + ignore fan3 + ignore fan4 + ignore in1 + +chip "lm75a-i2c-*-4a" + label temp1 "MAC temp sensor" + set temp1_max 65 + set temp1_crit 75 + +chip "lm75a-i2c-*-4b" + label temp1 "Board temp sensor" + set temp2_max 65 + set temp2_crit 75 + +chip "armada_thermal-*" + ignore temp1 diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/thermal_policy.json b/device/nokia/armhf-nokia_ixs7215_52x-r0/thermal_policy.json new file mode 100644 index 000000000000..fb6e044e266c --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/thermal_policy.json @@ -0,0 +1,65 @@ +{ + "thermal_control_algorithm": { + "run_at_boot_up": "false", + "fan_speed_when_suspend": "50" + }, + "info_types": [ + { + "type": "fan_info" + }, + { + "type": "thermal_info" + }, + { + "type": "chassis_info" + } + ], + "policies": [ + { + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "all fan presence", + "conditions": [ + { + "type": "fan.all.presence" + } + ], + "actions": [ + { + "type": "thermal.temp_check_and_set_all_fan_speed", + "default_speed": "50", + "hightemp_speed": "100" + } + ] + }, + { + "name": "temp over high critical threshold", + "conditions": [ + { + "type": "thermal.over.high_critical_threshold" + } + ], + "actions": [ + { + "type": "switch.shutdown" + } + ] + } + ] +} diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/default_sku b/device/pegatron/x86_64-pegatron_porsche-r0/default_sku new file mode 100644 index 000000000000..6b47d90d1cff --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/default_sku @@ -0,0 +1 @@ +porsche t1 diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/installer.conf b/device/pegatron/x86_64-pegatron_porsche-r0/installer.conf new file mode 100755 index 000000000000..14404194ef53 --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/plugins/eeprom.py b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/eeprom.py new file mode 100755 index 000000000000..5c2a90e81c2f --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/4-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/plugins/psuutil.py b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/psuutil.py new file mode 100755 index 000000000000..ce859cb70c77 --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/psuutil.py @@ -0,0 +1,91 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_DIR = "/sys/bus/i2c/devices/7-0075" + + 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 ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + + fd.close() + 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_'+str(index)+'_status' + attr_path = self.SYSFS_PSU_DIR + '/' + 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 + attr_file = 'psu_'+str(index)+'_present' + attr_path = self.SYSFS_PSU_DIR + '/' + 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 == 0): + status = 1 + + return status diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/plugins/sfputil.py b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/sfputil.py new file mode 100755 index 000000000000..3a757333cd2f --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/plugins/sfputil.py @@ -0,0 +1,231 @@ +try: + import os + import re + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific sfputil class""" + + port_start = 0 + port_end = 53 + ports_in_block = 54 + cplda_sfp_num = 24 + cpldb_sfp_num = 12 + cpldc_sfp_num = 18 + + port_to_eeprom_mapping = {} + port_to_i2c_mapping = {} + sfp_ports = list(range(0, ports_in_block)) + qsfp_ports = list(range(ports_in_block - 6, ports_in_block)) + + def __init__(self): + for x in range(self.port_start, self.port_end + 1): + if x < self.cpldb_sfp_num: + self.port_to_i2c_mapping.update({x: 7}) + elif x < self.cplda_sfp_num + self.cpldb_sfp_num: + self.port_to_i2c_mapping.update({x: 6}) + else: + self.port_to_i2c_mapping.update({x: 8}) + + for x in range(self.port_start, self.port_end+1): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp'+str(x+1)+'_eeprom' + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + if port_num < self.port_start or port_num > self.port_end: + return False + + if port_num < self.cpldb_sfp_num: + presence_path = '/sys/bus/i2c/devices/7-0075/sfp'+str(port_num+1)+'_present' + elif port_num < self.cpldb_sfp_num + self.cplda_sfp_num: + presence_path = '/sys/bus/i2c/devices/6-0074/sfp'+str(port_num+1)+'_present' + else: + presence_path = '/sys/bus/i2c/devices/8-0076/sfp'+str(port_num+1)+'_present' + + try: + file = open(presence_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + value = int(file.readline().rstrip()) + + file.close() + if value == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + if port_num not in self.qsfp_ports: + return False + + lowpower_path = '/sys/bus/i2c/devices/8-0076/sfp'+str(port_num+1)+'_lowpower' + + try: + file = open(lowpower_path) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + value = int(file.readline().rstrip()) + + file.close() + if value == 1: + return True + + return False + + def set_low_power_mode(self, port_num, lpmode): + if port_num not in self.qsfp_ports: + return False + + lowpower_path = '/sys/bus/i2c/devices/8-0076/sfp'+str(port_num+1)+'_lowpower' + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + value = 1 + else: + value = 0 + + try: + file = open(lowpower_path, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + file.seek(0) + file.write(str(value)) + file.close() + + return True + + def reset(self, port_num): + if port_num not in self.qsfp_ports: + return False + reset_path = '/sys/bus/i2c/devices/8-0076/sfp'+str(port_num+1)+'_reset' + + try: + file = open(reset_path, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + file.seek(0) + file.write(str(2)) + file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + file = open(reset_path, "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + file.seek(0) + file.write(str(1)) + file.close() + + return True + + def read_porttab_mappings(self, porttabfile): + logical = [] + logical_to_bcm = {} + logical_to_physical = {} + physical_to_logical = {} + last_fp_port_index = 0 + last_portname = "" + first = 1 + port_pos_in_file = 0 + parse_fmt_port_config_ini = False + + try: + f = open(porttabfile) + except: + raise + + parse_fmt_port_config_ini = (os.path.basename(porttabfile) == "port_config.ini") + + # Read the porttab file and generate dicts + # with mapping for future reference. + # XXX: move the porttab + # parsing stuff to a separate module, or reuse + # if something already exists + for line in f: + line.strip() + if re.search("^#", line) is not None: + continue + + # Parsing logic for 'port_config.ini' file + if (parse_fmt_port_config_ini): + # bcm_port is not explicitly listed in port_config.ini format + # Currently we assume ports are listed in numerical order according to bcm_port + # so we use the port's position in the file (zero-based) as bcm_port + portname = line.split()[0] + + bcm_port = str(port_pos_in_file) + + if len(line.split()) >= 4: + fp_port_index = int(line.split()[3]) + else: + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))/4 + else: # Parsing logic for older 'portmap.ini' file + (portname, bcm_port) = line.split("=")[1].split(",")[:2] + + fp_port_index = portname.split("Ethernet").pop() + fp_port_index = int(fp_port_index.split("s").pop(0))/4 + + if ((len(self.sfp_ports) > 0) and (fp_port_index not in self.sfp_ports)): + continue + + if first == 1: + # Initialize last_[physical|logical]_port + # to the first valid port + last_fp_port_index = fp_port_index + last_portname = portname + first = 0 + + logical.append(portname) + + logical_to_bcm[portname] = "xe" + bcm_port + logical_to_physical[portname] = [fp_port_index] + if physical_to_logical.get(fp_port_index) is None: + physical_to_logical[fp_port_index] = [portname] + else: + physical_to_logical[fp_port_index].append( + portname) + + if (fp_port_index - last_fp_port_index) > 1: + # last port was a gang port + for p in range(last_fp_port_index+1, fp_port_index): + logical_to_physical[last_portname].append(p) + if physical_to_logical.get(p) is None: + physical_to_logical[p] = [last_portname] + else: + physical_to_logical[p].append(last_portname) + + last_fp_port_index = fp_port_index + last_portname = portname + + port_pos_in_file += 1 + + self.logical = logical + self.logical_to_bcm = logical_to_bcm + self.logical_to_physical = logical_to_physical + self.physical_to_logical = physical_to_logical + + """ + print "logical: " + self.logical + print "logical to bcm: " + self.logical_to_bcm + print "logical to physical: " + self.logical_to_physical + print "physical to logical: " + self.physical_to_logical + """ diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/porsche/port_config.ini b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/port_config.ini new file mode 100755 index 000000000000..15fc60375941 --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/port_config.ini @@ -0,0 +1,55 @@ +#name lanes alias index speed +Ethernet0 8 Ethernet1/1 0 10000 +Ethernet1 9 Ethernet2/1 1 10000 +Ethernet2 10 Ethernet3/1 2 10000 +Ethernet3 11 Ethernet4/1 3 10000 +Ethernet4 12 Ethernet5/1 4 10000 +Ethernet5 13 Ethernet6/1 5 10000 +Ethernet6 14 Ethernet7/1 6 10000 +Ethernet7 15 Ethernet8/1 7 10000 +Ethernet8 16 Ethernet9/1 8 10000 +Ethernet9 17 Ethernet10/1 9 10000 +Ethernet10 18 Ethernet11/1 10 10000 +Ethernet11 19 Ethernet12/1 11 10000 +Ethernet12 20 Ethernet13/1 12 10000 +Ethernet13 21 Ethernet14/1 13 10000 +Ethernet14 22 Ethernet15/1 14 10000 +Ethernet15 23 Ethernet16/1 15 10000 +Ethernet16 32 Ethernet17/1 16 10000 +Ethernet17 33 Ethernet18/1 17 10000 +Ethernet18 34 Ethernet19/1 18 10000 +Ethernet19 35 Ethernet20/1 19 10000 +Ethernet20 40 Ethernet21/1 20 10000 +Ethernet21 41 Ethernet22/1 21 10000 +Ethernet22 42 Ethernet23/1 22 10000 +Ethernet23 43 Ethernet24/1 23 10000 +Ethernet24 48 Ethernet25/1 24 10000 +Ethernet25 49 Ethernet26/1 25 10000 +Ethernet26 50 Ethernet27/1 26 10000 +Ethernet27 51 Ethernet28/1 27 10000 +Ethernet28 56 Ethernet29/1 28 10000 +Ethernet29 57 Ethernet30/1 29 10000 +Ethernet30 58 Ethernet31/1 30 10000 +Ethernet31 59 Ethernet32/1 31 10000 +Ethernet32 64 Ethernet33/1 32 10000 +Ethernet33 65 Ethernet34/1 33 10000 +Ethernet34 66 Ethernet35/1 34 10000 +Ethernet35 67 Ethernet36/1 35 10000 +Ethernet36 68 Ethernet37/1 36 10000 +Ethernet37 69 Ethernet38/1 37 10000 +Ethernet38 70 Ethernet39/1 38 10000 +Ethernet39 71 Ethernet40/1 39 10000 +Ethernet40 72 Ethernet41/1 40 10000 +Ethernet41 73 Ethernet42/1 41 10000 +Ethernet42 74 Ethernet43/1 42 10000 +Ethernet43 75 Ethernet44/1 43 10000 +Ethernet44 76 Ethernet45/1 44 10000 +Ethernet45 77 Ethernet46/1 45 10000 +Ethernet46 78 Ethernet47/1 46 10000 +Ethernet47 79 Ethernet48/1 47 10000 +Ethernet48 80,81,82,83 Ethernet49/1 48 100000 +Ethernet49 84,85,86,87 Ethernet50/1 49 100000 +Ethernet50 104,105,106,107 Ethernet51/1 50 100000 +Ethernet51 108,109,110,111 Ethernet52/1 51 100000 +Ethernet52 112,113,114,115 Ethernet53/1 52 100000 +Ethernet53 116,117,118,119 Ethernet54/1 53 100000 diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/porsche/sai.profile b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/sai.profile new file mode 100755 index 000000000000..f19a366b1cac --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/platform/tau-porsche.cfg +SAI_DSH_CONFIG_FILE=/usr/share/sonic/hwsku/tau-porsche.dsh diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/porsche/tau-porsche.dsh b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/tau-porsche.dsh new file mode 100755 index 000000000000..b370fe83b837 --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/porsche/tau-porsche.dsh @@ -0,0 +1,497 @@ +init start stage unit=0 low-level +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=20 lane=0 max-speed=100g active=true +init set port-map unit=0 port=49 eth-macro=21 lane=0 max-speed=100g active=true +init set port-map unit=0 port=50 eth-macro=26 lane=0 max-speed=100g active=true +init set port-map unit=0 port=51 eth-macro=27 lane=0 max-speed=100g active=true +init set port-map unit=0 port=52 eth-macro=28 lane=0 max-speed=100g active=true +init set port-map unit=0 port=53 eth-macro=29 lane=0 max-speed=100g active=true init-done=true +init start stage unit=0 task-rsrc +init start stage unit=0 module +init start stage unit=0 task +phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=tx data=0x00 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=tx data=0x01 +phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=tx data=0x02 +phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=tx data=0x03 +phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=tx data=0x01.02.03.00 +phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=tx data=0x01.02.03.00 +phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=tx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=tx data=0x01.02.03.00 +phy set lane-swap unit=0 portlist=0 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=1 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=2 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=3 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=4 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=5 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=6 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=7 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=8 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=9 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=10 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=11 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=12 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=13 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=14 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=15 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=16 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=17 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=18 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=19 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=20 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=21 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=22 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=23 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=24 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=25 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=26 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=27 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=28 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=29 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=30 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=31 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=32 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=33 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=34 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=35 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=36 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=37 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=38 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=39 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=40 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=41 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=42 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=43 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=44 lane-cnt=1 property=rx data=0x02 +phy set lane-swap unit=0 portlist=45 lane-cnt=1 property=rx data=0x01 +phy set lane-swap unit=0 portlist=46 lane-cnt=1 property=rx data=0x00 +phy set lane-swap unit=0 portlist=47 lane-cnt=1 property=rx data=0x03 +phy set lane-swap unit=0 portlist=48 lane-cnt=4 property=rx data=0x03.00.01.02 +phy set lane-swap unit=0 portlist=49 lane-cnt=4 property=rx data=0x03.00.01.02 +phy set lane-swap unit=0 portlist=50 lane-cnt=4 property=rx data=0x03.01.02.00 +phy set lane-swap unit=0 portlist=51 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=52 lane-cnt=4 property=rx data=0x03.02.01.00 +phy set lane-swap unit=0 portlist=53 lane-cnt=4 property=rx data=0x00.01.02.03 +phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=tx data=0x00 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=tx data=0x01 +phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=tx data=0x00.01.00.00 +phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=tx data=0x00.00.01.00 +phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=tx data=0x01.00.01.01 +phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=tx data=0x01.01.01.01 +phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=tx data=0x01.00.00.00 +phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=tx data=0x00.00.01.00 +phy set polarity-rev unit=0 portlist=0 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=1 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=2 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=3 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=4 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=5 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=6 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=7 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=8 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=9 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=10 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=11 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=12 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=13 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=14 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=15 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=16 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=17 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=18 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=19 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=20 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=21 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=22 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=23 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=24 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=25 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=26 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=27 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=28 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=29 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=30 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=31 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=32 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=33 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=34 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=35 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=36 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=37 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=38 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=39 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=40 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=41 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=42 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=43 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=44 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=45 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=46 lane-cnt=1 property=rx data=0x01 +phy set polarity-rev unit=0 portlist=47 lane-cnt=1 property=rx data=0x00 +phy set polarity-rev unit=0 portlist=48 lane-cnt=4 property=rx data=0x00.01.00.00 +phy set polarity-rev unit=0 portlist=49 lane-cnt=4 property=rx data=0x00.00.01.00 +phy set polarity-rev unit=0 portlist=50 lane-cnt=4 property=rx data=0x00.00.01.01 +phy set polarity-rev unit=0 portlist=51 lane-cnt=4 property=rx data=0x00.01.00.01 +phy set polarity-rev unit=0 portlist=52 lane-cnt=4 property=rx data=0x00.01.00.01 +phy set polarity-rev unit=0 portlist=53 lane-cnt=4 property=rx data=0x01.01.01.01 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c2 data=0x00 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=cn1 data=0x04 +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c0 data=0x1E +phy set pre-emphasis unit=0 portlist=0 lane-cnt=1 property=c1 data=0x02 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c2 data=0x00 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=cn1 data=0x04 +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c0 data=0x1E +phy set pre-emphasis unit=0 portlist=1 lane-cnt=1 property=c1 data=0x02 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c2 data=0x00 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=cn1 data=0x04 +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c0 data=0x1E +phy set pre-emphasis unit=0 portlist=2 lane-cnt=1 property=c1 data=0x02 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c2 data=0x00 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=cn1 data=0x04 +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c0 data=0x1E +phy set pre-emphasis unit=0 portlist=3 lane-cnt=1 property=c1 data=0x02 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=4 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=5 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=6 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=7 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=8 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=9 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=10 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=11 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=12 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=13 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=14 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c0 data=0x1B +phy set pre-emphasis unit=0 portlist=15 lane-cnt=1 property=c1 data=0x07 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=16 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=17 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=18 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=19 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=20 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=21 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=22 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=23 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=24 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=25 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=26 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=27 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c0 data=0x1D +phy set pre-emphasis unit=0 portlist=28 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c0 data=0x1D +phy set pre-emphasis unit=0 portlist=29 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c0 data=0x1D +phy set pre-emphasis unit=0 portlist=30 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c0 data=0x1D +phy set pre-emphasis unit=0 portlist=31 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=32 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=33 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=34 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=35 lane-cnt=1 property=c1 data=0x05 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=36 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=37 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=38 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=39 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=40 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=41 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=42 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=43 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=44 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=45 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=46 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c2 data=0x02 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=cn1 data=0x00 +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c0 data=0x1C +phy set pre-emphasis unit=0 portlist=47 lane-cnt=1 property=c1 data=0x06 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c0 data=0x1C.1C.1C.1C +phy set pre-emphasis unit=0 portlist=48 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=49 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=50 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=51 lane-cnt=4 property=c1 data=0x06.06.06.06 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c0 data=0x1B.1B.1B.1B +phy set pre-emphasis unit=0 portlist=52 lane-cnt=4 property=c1 data=0x07.07.07.07 +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c2 data=0x02.02.02.02 +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=cn1 data=0x00.00.00.00 +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c0 data=0x1A.1A.1A.1A +phy set pre-emphasis unit=0 portlist=53 lane-cnt=4 property=c1 data=0x07.07.07.07 +port set property unit=0 portlist=0-47 speed=10g +port set property unit=0 portlist=0-47 medium-type=sr +port set property unit=0 portlist=48-53 speed=100g +port set property unit=0 portlist=48-53 medium-type=sr4 +port set property unit=0 portlist=0-53 fec=disable +port set property unit=0 portlist=0-53 an=disable +port set property unit=0 portlist=0-53 admin=enable \ No newline at end of file diff --git a/device/pegatron/x86_64-pegatron_porsche-r0/tau-porsche.cfg b/device/pegatron/x86_64-pegatron_porsche-r0/tau-porsche.cfg new file mode 100755 index 000000000000..bbd7c8f80ff5 --- /dev/null +++ b/device/pegatron/x86_64-pegatron_porsche-r0/tau-porsche.cfg @@ -0,0 +1,23 @@ +#This configuration file is for customer init value feature. Please refer to mtk_cfg.h/mtk_cfg.c for detail. +#1. The lines beginning with # are comment lines. The lines beginning with number are the setting lines. +#2. There are five parameters which can be set. +# 1) the first is unit. +# 2) the second is NPS_CFG_TYPE_XXX. Refer to NPS_CFG_TYPE_T. +# 3) the 3-5 are {param0, param1, value} pairs. Refer to NPS_CFG_VALUE_T. Support HEX format. +# 4) the (unit, NPS_CFG_TYPE_XXX, param0, param1) group is the key to get the correspingding value. +# There should be no same (unit, NPS_CFG_TYPE_XXX, param0, param1) group. +#3. User must follow correct format to apply the setting. Please refer to below commentted example(#0 NPS_CFG_TYPE_L2_ADDR_MODE 0 0 1); +#4. Usage under the linux shell: +# 1) ./image-path/image-name -c cfg-path/NPS_Ari_EVB_24.cfg : mamually specify directory path if they are not in current work dirctory. +# 2) ./image-name -c NPS_Ari_EVB_24.cfg : the image and the NPS_Ari_EVB_24.cfg are in the current work directory. + +#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 3 +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 +0 NPS_CFG_TYPE_HASH_L2_FDB_REGION_ENTRY_NUM 0 0 49152 +0 NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM 0 0 32768 + diff --git a/device/quanta/x86_64-quanta_ix1b_32x-r0/default_sku b/device/quanta/x86_64-quanta_ix1b_32x-r0/default_sku new file mode 100644 index 000000000000..68cbc0d6058d --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_32x-r0/default_sku @@ -0,0 +1 @@ +Quanta-IX1B-32X t1 diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/port_config.ini b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/port_config.ini new file mode 100755 index 000000000000..4f4f63925d8b --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 65,66,67,68 hundredGigE1 +Ethernet4 69,70,71,72 hundredGigE2 +Ethernet8 73,74,75,76 hundredGigE3 +Ethernet12 77,78,79,80 hundredGigE4 +Ethernet16 45,46,47,48 hundredGigE5 +Ethernet20 41,42,43,44 hundredGigE6 +Ethernet24 53,54,55,56 hundredGigE7 +Ethernet28 49,50,51,52 hundredGigE8 +Ethernet32 61,62,63,64 hundredGigE9 +Ethernet36 57,58,59,60 hundredGigE10 +Ethernet40 37,38,39,40 hundredGigE11 +Ethernet44 33,34,35,36 hundredGigE12 +Ethernet48 81,82,83,84 hundredGigE13 +Ethernet52 85,86,87,88 hundredGigE14 +Ethernet56 89,90,91,92 hundredGigE15 +Ethernet60 93,94,95,96 hundredGigE16 +Ethernet64 97,98,99,100 hundredGigE17 +Ethernet68 101,102,103,104 hundredGigE18 +Ethernet72 105,106,107,108 hundredGigE19 +Ethernet76 109,110,111,112 hundredGigE20 +Ethernet80 29,30,31,32 hundredGigE21 +Ethernet84 25,26,27,28 hundredGigE22 +Ethernet88 5,6,7,8 hundredGigE23 +Ethernet92 1,2,3,4 hundredGigE24 +Ethernet96 13,14,15,16 hundredGigE25 +Ethernet100 9,10,11,12 hundredGigE26 +Ethernet104 21,22,23,24 hundredGigE27 +Ethernet108 17,18,19,20 hundredGigE28 +Ethernet112 113,114,115,116 hundredGigE29 +Ethernet116 117,118,119,120 hundredGigE30 +Ethernet120 121,122,123,124 hundredGigE31 +Ethernet124 125,126,127,128 hundredGigE32 diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/sai.profile b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/sai.profile new file mode 100755 index 000000000000..219465108df8 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-ix1b-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/th-ix1b-32x100G.config.bcm b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/th-ix1b-32x100G.config.bcm new file mode 100644 index 000000000000..051b8ed71e8e --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/Quanta-IX1B-32X/th-ix1b-32x100G.config.bcm @@ -0,0 +1,256 @@ +os=unix + +pbmp_xport_xe=0x3fd000000ff4000003fc000001fe +pbmp_oversubscribe=0x3fd000000ff4000003fc000001fe +l2xmsg_mode=1 + +schan_intr_enable=0 + +# Control to disable parity messages +parity_enable=1 + +# Control to disable parity correction +parity_correction=1 + +ipv6_lpm_128b_enable=1 +l3_alpm_enable=2 + +l2_mem_entries=40960 +l3_mem_entries=40960 + +portmap_1=1:100 +portmap_2=5:100 +portmap_3=9:100 +portmap_4=13:100 +portmap_5=17:100 +portmap_6=21:100 +portmap_7=25:100 +portmap_8=29:100 +portmap_34=33:100 +portmap_35=37:100 +portmap_36=41:100 +portmap_37=45:100 +portmap_38=49:100 +portmap_39=53:100 +portmap_40=57:100 +portmap_41=61:100 +portmap_68=65:100 +portmap_69=69:100 +portmap_70=73:100 +portmap_71=77:100 +portmap_72=81:100 +portmap_73=85:100 +portmap_74=89:100 +portmap_75=93:100 +portmap_102=97:100 +portmap_103=101:100 +portmap_104=105:100 +portmap_105=109:100 +portmap_106=113:100 +portmap_107=117:100 +portmap_108=121:100 +portmap_109=125:100 + +portmap_66=129:10 +portmap_100=131:10 +portmap_33=132:10 +portmap_67=133:10 +portmap_101=134:10 +portmap_135=135:10 + + +mem_cache_enable=1 +ctr_evict_enable=0 + +#mdio setting +rate_ext_mdio_divisor=0x2f +mdio_output_delay=15 + +#lanes swap and polarity +xgxs_rx_lane_map_1=0x3120 +phy_xaui_rx_polarity_flip_1=0xa +xgxs_tx_lane_map_1=0x1230 +phy_xaui_tx_polarity_flip_1=0x7 + +xgxs_rx_lane_map_2=0x3120 +phy_xaui_rx_polarity_flip_2=0xc +xgxs_tx_lane_map_2=0x0213 +phy_xaui_tx_polarity_flip_2=0x5 + +xgxs_rx_lane_map_3=0x2013 +phy_xaui_rx_polarity_flip_3=0xb +xgxs_tx_lane_map_3=0x3120 +phy_xaui_tx_polarity_flip_3=0x6 + +xgxs_rx_lane_map_4=0x2103 +phy_xaui_rx_polarity_flip_4=0xf +xgxs_tx_lane_map_4=0x3201 +phy_xaui_tx_polarity_flip_4=0x5 + +xgxs_rx_lane_map_5=0x1032 +phy_xaui_rx_polarity_flip_5=0x7 +xgxs_tx_lane_map_5=0x1302 +phy_xaui_tx_polarity_flip_5=0x0 + +xgxs_rx_lane_map_6=0x2103 +phy_xaui_rx_polarity_flip_6=0x3 +xgxs_tx_lane_map_6=0x3120 +phy_xaui_tx_polarity_flip_6=0x2 + +xgxs_rx_lane_map_7=0x0123 +phy_xaui_rx_polarity_flip_7=0x5 +xgxs_tx_lane_map_7=0x3012 +phy_xaui_tx_polarity_flip_7=0x3 + +xgxs_rx_lane_map_8=0x1032 +phy_xaui_rx_polarity_flip_8=0xf +xgxs_tx_lane_map_8=0x3120 +phy_xaui_tx_polarity_flip_8=0x2 + +xgxs_rx_lane_map_34=0x3021 +phy_xaui_rx_polarity_flip_34=0xa +xgxs_tx_lane_map_34=0x3210 +phy_xaui_tx_polarity_flip_34=0xf + +xgxs_rx_lane_map_35=0x2103 +phy_xaui_rx_polarity_flip_35=0x6 +xgxs_tx_lane_map_35=0x3120 +phy_xaui_tx_polarity_flip_35=0x5 + +xgxs_rx_lane_map_36=0x0312 +phy_xaui_rx_polarity_flip_36=0x4 +xgxs_tx_lane_map_36=0x3210 +phy_xaui_tx_polarity_flip_36=0x2 + +xgxs_rx_lane_map_37=0x0231 +phy_xaui_rx_polarity_flip_37=0x4 +xgxs_tx_lane_map_37=0x1032 +phy_xaui_tx_polarity_flip_37=0x2 + +xgxs_rx_lane_map_38=0x3012 +phy_xaui_rx_polarity_flip_38=0xa +xgxs_tx_lane_map_38=0x2103 +phy_xaui_tx_polarity_flip_38=0xd + +xgxs_rx_lane_map_39=0x0123 +phy_xaui_rx_polarity_flip_39=0x9 +xgxs_tx_lane_map_39=0x3120 +phy_xaui_tx_polarity_flip_39=0xd + +xgxs_rx_lane_map_40=0x2310 +phy_xaui_rx_polarity_flip_40=0x6 +xgxs_tx_lane_map_40=0x0123 + +xgxs_rx_lane_map_41=0x1230 +phy_xaui_rx_polarity_flip_41=0xa +xgxs_tx_lane_map_41=0x0123 +phy_xaui_tx_polarity_flip_41=0xe + +xgxs_rx_lane_map_68=0x1230 +phy_xaui_rx_polarity_flip_68=0xb +xgxs_tx_lane_map_68=0x3012 +phy_xaui_tx_polarity_flip_68=0xa + +xgxs_rx_lane_map_69=0x2310 +phy_xaui_rx_polarity_flip_69=0xf +xgxs_tx_lane_map_69=0x3120 +phy_xaui_tx_polarity_flip_69=0x2 + +xgxs_rx_lane_map_70=0x2310 +phy_xaui_rx_polarity_flip_70=0xe +xgxs_tx_lane_map_70=0x0213 +phy_xaui_tx_polarity_flip_70=0x2 + +xgxs_rx_lane_map_71=0x2130 +phy_xaui_rx_polarity_flip_71=0x5 +xgxs_tx_lane_map_71=0x3210 + +phy_xaui_rx_polarity_flip_72=0xa +xgxs_tx_lane_map_72=0x1230 + +xgxs_rx_lane_map_73=0x0213 +phy_xaui_rx_polarity_flip_73=0x5 +xgxs_tx_lane_map_73=0x1320 +phy_xaui_tx_polarity_flip_73=0x3 + +xgxs_rx_lane_map_74=0x2310 +phy_xaui_rx_polarity_flip_74=0xe +xgxs_tx_lane_map_74=0x2310 +phy_xaui_tx_polarity_flip_74=0xc + +xgxs_rx_lane_map_75=0x0321 +xgxs_tx_lane_map_75=0x2130 +phy_xaui_tx_polarity_flip_75=0x6 + +xgxs_rx_lane_map_102=0x1302 +phy_xaui_rx_polarity_flip_102=0x4 +xgxs_tx_lane_map_102=0x0123 +phy_xaui_tx_polarity_flip_102=0xa + +xgxs_tx_lane_map_103=0x2130 +phy_xaui_tx_polarity_flip_103=0x8 + +xgxs_rx_lane_map_104=0x1302 +phy_xaui_rx_polarity_flip_104=0xd +xgxs_tx_lane_map_104=0x1302 +phy_xaui_tx_polarity_flip_104=0x2 + +xgxs_rx_lane_map_105=0x1230 +phy_xaui_rx_polarity_flip_105=0x8 +xgxs_tx_lane_map_105=0x1320 + +xgxs_rx_lane_map_106=0x3120 +phy_xaui_rx_polarity_flip_106=0xc +xgxs_tx_lane_map_106=0x3120 +phy_xaui_tx_polarity_flip_106=0x0 + +xgxs_rx_lane_map_107=0x0321 +phy_xaui_rx_polarity_flip_107=0xa +xgxs_tx_lane_map_107=0x1032 +phy_xaui_tx_polarity_flip_107=0xf + +xgxs_rx_lane_map_108=0x0321 +phy_xaui_rx_polarity_flip_108=0xf +xgxs_tx_lane_map_108=0x3210 +phy_xaui_tx_polarity_flip_108=0x0 + +xgxs_rx_lane_map_109=0x0321 +phy_xaui_rx_polarity_flip_109=0xa +xgxs_tx_lane_map_109=0x3021 +phy_xaui_tx_polarity_flip_109=0x3 + +dport_map_port_68=1 +dport_map_port_69=2 +dport_map_port_70=3 +dport_map_port_71=4 +dport_map_port_37=5 +dport_map_port_36=6 +dport_map_port_39=7 +dport_map_port_38=8 +dport_map_port_41=9 +dport_map_port_40=10 +dport_map_port_35=11 +dport_map_port_34=12 +dport_map_port_72=13 +dport_map_port_73=14 +dport_map_port_74=15 +dport_map_port_75=16 +dport_map_port_102=17 +dport_map_port_103=18 +dport_map_port_104=19 +dport_map_port_105=20 +dport_map_port_8=21 +dport_map_port_7=22 +dport_map_port_2=23 +dport_map_port_1=24 +dport_map_port_4=25 +dport_map_port_3=26 +dport_map_port_6=27 +dport_map_port_5=28 +dport_map_port_106=29 +dport_map_port_107=30 +dport_map_port_108=31 +dport_map_port_109=32 +dport_map_port_66=33 +dport_map_port_100=34 + diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/default_sku b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/default_sku new file mode 100755 index 000000000000..68cbc0d6058d --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/default_sku @@ -0,0 +1 @@ +Quanta-IX1B-32X t1 diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/installer.conf b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/installer.conf new file mode 100755 index 000000000000..14404194ef53 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/led_proc_init.soc b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/led_proc_init.soc new file mode 100755 index 000000000000..831f74df7557 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/led_proc_init.soc @@ -0,0 +1,10 @@ +led 0 stop +led 1 stop + +led 0 prog 02 00 60 E2 D2 40 71 12 12 F0 85 05 D2 0A 71 19 52 00 67 1B 06 E2 80 77 02 3A 80 67 20 67 2E 57 06 E2 12 00 F0 80 F8 15 1A 00 75 4E 77 52 06 E2 F0 12 00 F8 15 1A 00 75 3B 77 46 06 E2 F0 12 00 F8 15 1A 01 75 4E 16 F0 DA 05 75 4E 77 52 32 0F 87 57 32 0E 87 57 00 00 00 00 00 00 00 00 00 00 +led 1 prog 02 00 60 E2 D2 40 71 12 12 F0 85 05 D2 0A 71 19 52 00 67 1B 06 E2 80 77 02 3A 80 67 20 67 2E 57 06 E2 12 00 F0 80 F8 15 1A 00 75 4E 77 52 06 E2 F0 12 00 F8 15 1A 00 75 3B 77 46 06 E2 F0 12 00 F8 15 1A 01 75 4E 16 F0 DA 05 75 4E 77 52 32 0F 87 57 32 0E 87 57 00 00 00 00 00 00 00 00 00 00 + +led 0 auto on +led 1 auto on +led 0 start +led 1 start \ No newline at end of file diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/eeprom.py b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/eeprom.py new file mode 100755 index 000000000000..ddefcf8877fb --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/22-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/psuutil.py b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/psuutil.py new file mode 100755 index 000000000000..0b2027afdda4 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/psuutil.py @@ -0,0 +1,179 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path +import subprocess +import logging + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +DEBUG = False + + +def show_log(txt): + if DEBUG == True: + print("[IX2]"+txt) + return + + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + try: + output = subprocess.check_output(cmd, shell=True, universal_newlines=True) + show_log(cmd + "output:"+str(output)) + except subprocess.CalledProcessError as e: + logging.info("Failed :"+cmd) + if show: + print("Failed :"+cmd + "returncode = {}, err msg: {}".format(e.returncode, e.output)) + return output + + +def my_log(txt): + if DEBUG == True: + print("[QUANTA DBG]: "+txt) + return + + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + try: + output = subprocess.check_output(cmd, shell=True, universal_newlines=True) + my_log(cmd + "output:"+str(output)) + except subprocess.CalledProcessError as e: + logging.info('Failed :'+cmd) + if show: + print("Failed :"+cmd + "returncode = {}, err msg: {}".format(e.returncode, e.output)) + return output + + +def gpio16_exist(): + ls = log_os_system("ls /sys/class/gpio/ | grep gpio16", 0) + logging.info('mods:'+ls) + if len(ls) == 0: + return False + + +def gpio17_exist(): + ls = log_os_system("ls /sys/class/gpio/ | grep gpio17", 0) + logging.info('mods:'+ls) + if len(ls) == 0: + return False + + +def gpio19_exist(): + ls = log_os_system("ls /sys/class/gpio/ | grep gpio19", 0) + logging.info('mods:'+ls) + if len(ls) == 0: + return False + + +def gpio20_exist(): + ls = log_os_system("ls /sys/class/gpio/ | grep gpio20", 0) + logging.info('mods:'+ls) + if len(ls) == 0: + return False + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYSFS_PSU_PRESENT_DIR = ["/sys/class/gpio/gpio16", + "/sys/class/gpio/gpio19"] + + SYSFS_PSU_POWERGOOD_DIR = ["/sys/class/gpio/gpio17", + "/sys/class/gpio/gpio20"] + + def __init__(self): + PsuBase.__init__(self) + + if gpio16_exist() == False: + output = exec_cmd("echo 16 > /sys/class/gpio/export ", 1) + output = exec_cmd("echo in > /sys/class/gpio/gpio16/direction ", 1) + + if gpio17_exist() == False: + output = exec_cmd("echo 17 > /sys/class/gpio/export ", 1) + output = exec_cmd("echo in > /sys/class/gpio/gpio17/direction ", 1) + + if gpio19_exist() == False: + output = exec_cmd("echo 19 > /sys/class/gpio/export ", 1) + output = exec_cmd("echo in > /sys/class/gpio/gpio19/direction ", 1) + + if gpio20_exist() == False: + output = exec_cmd("echo 20 > /sys/class/gpio/export ", 1) + output = exec_cmd("echo in > /sys/class/gpio/gpio20/direction ", 1) + + # 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 ", attr_path, " file !") + + 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 = 'value' + attr_path = self.SYSFS_PSU_POWERGOOD_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 = 'value' + attr_path = self.SYSFS_PSU_PRESENT_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 == 0): + status = 1 + + return status diff --git a/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/sfputil.py b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/sfputil.py new file mode 100755 index 000000000000..cbaf8b71832f --- /dev/null +++ b/device/quanta/x86_64-quanta_ix1b_rglbmc-r0/plugins/sfputil.py @@ -0,0 +1,175 @@ +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 0 + _port_end = 31 + ports_in_block = 32 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 1: 32, + 2: 33, + 3: 34, + 4: 35, + 5: 36, + 6: 37, + 7: 38, + 8: 39, + 9: 40, + 10: 41, + 11: 42, + 12: 43, + 13: 44, + 14: 45, + 15: 46, + 16: 47, + 17: 48, + 18: 49, + 19: 50, + 20: 51, + 21: 52, + 22: 53, + 23: 54, + 24: 55, + 25: 56, + 26: 57, + 27: 58, + 28: 59, + 29: 60, + 30: 61, + 31: 62, + 32: 63, + } + + _qsfp_ports = list(range(0, ports_in_block + 1)) + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(0, self._port_end + 1): + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x+1]) + self._port_to_eeprom_mapping[x] = port_eeprom_path + 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 + + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num+1)+"/reset", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num+1)+"/reset", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num+1)+"/lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num+1)+"/lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + 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/class/cpld-qsfp28/port-{0}/module_present" + #port_ps = path.format(self.port_to_i2c_mapping[port_num+1]) + + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num+1)+"/module_present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return list(range(0, self.ports_in_block + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + 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 diff --git a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/port_config.ini b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/port_config.ini new file mode 100644 index 000000000000..14f4716d9091 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index speed +Ethernet0 29,30,31,32 hundredGigE1 1 100000 +Ethernet4 33,34,35,36 hundredGigE2 2 100000 +Ethernet8 41,42,43,44 hundredGigE3 3 100000 +Ethernet12 45,46,47,48 hundredGigE4 4 100000 +Ethernet16 1,2,3,4 hundredGigE5 5 100000 +Ethernet20 5,6,7,8 hundredGigE6 6 100000 +Ethernet24 9,10,11,12 hundredGigE7 7 100000 +Ethernet28 13,14,15,16 hundredGigE8 8 100000 +Ethernet32 17,18,19,20 hundredGigE9 9 100000 +Ethernet36 21,22,23,24 hundredGigE10 10 100000 +Ethernet40 25,26,27,28 hundredGigE11 11 100000 +Ethernet44 37,38,39,40 hundredGigE12 12 100000 +Ethernet48 49,50,51,52 hundredGigE13 13 100000 +Ethernet52 53,54,55,56 hundredGigE14 14 100000 +Ethernet56 57,58,59,60 hundredGigE15 15 100000 +Ethernet60 61,62,63,64 hundredGigE16 16 100000 +Ethernet64 65,66,67,68 hundredGigE17 17 100000 +Ethernet68 69,70,71,72 hundredGigE18 18 100000 +Ethernet72 73,74,75,76 hundredGigE19 19 100000 +Ethernet76 77,78,79,80 hundredGigE20 20 100000 +Ethernet80 93,94,95,96 hundredGigE21 21 100000 +Ethernet84 101,102,103,104 hundredGigE22 22 100000 +Ethernet88 105,106,107,108 hundredGigE23 23 100000 +Ethernet92 109,110,111,112 hundredGigE24 24 100000 +Ethernet96 113,114,115,116 hundredGigE25 25 100000 +Ethernet100 117,118,119,120 hundredGigE26 26 100000 +Ethernet104 121,122,123,124 hundredGigE27 27 100000 +Ethernet108 125,126,127,128 hundredGigE28 28 100000 +Ethernet112 81,82,83,84 hundredGigE29 29 100000 +Ethernet116 85,86,87,88 hundredGigE30 30 100000 +Ethernet120 89,90,91,92 hundredGigE31 31 100000 +Ethernet124 97,98,99,100 hundredGigE32 32 100000 diff --git a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/sai.profile b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/sai.profile new file mode 100644 index 000000000000..367f18e369fa --- /dev/null +++ b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-ix7-32x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/td3-ix7-32x100G.config.bcm b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/td3-ix7-32x100G.config.bcm new file mode 100644 index 000000000000..7361ad2f57f3 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/td3-ix7-32x100G.config.bcm @@ -0,0 +1,535 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +bcm_tunnel_term_compatible_mode=1 +core_clock_frequency=1525 +dpp_clock_ratio=2:3 +parity_enable=0 +mem_cache_enable=0 +l2_mem_entries=40960 +l3_mem_entries=40960 +fpem_mem_entries=16384 +l2xmsg_mode=1 + +bcm_num_cos=10 +bcm_stat_interval=2000000 +cdma_timeout_usec=3000000 + +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l3_max_ecmp_mode=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 + +miim_intr_enable=0 +module_64ports=1 + +schan_intr_enable=0 +skip_L2_USER_ENTRY=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 + +# portmap settings +oversubscribe_mode=1 +pbmp_xport_xe=0x4888888888888888c2222222222222222 + +port_flex_enable=1 + +portmap_1=1:100 +portmap_5=5:100 +portmap_9=9:100 +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_57=57:100 +portmap_61=61:100 + +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_99=97:100 +portmap_103=101:100 +portmap_107=105:100 +portmap_111=109:100 +portmap_115=113:100 +portmap_119=117:100 +portmap_123=121:100 +portmap_127=125:100 + +# datapath port -- merlin core +portmap_66=129:10:m +portmap_130=128:10:m + +# loopback port +portmap_65=130:10 +portmap_131=131:10 + +# port order remap +dport_map_port_29=1 +dport_map_port_33=2 +dport_map_port_41=3 +dport_map_port_45=4 +dport_map_port_1=5 +dport_map_port_5=6 +dport_map_port_9=7 +dport_map_port_13=8 +dport_map_port_17=9 +dport_map_port_21=10 +dport_map_port_25=11 +dport_map_port_37=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_95=21 +dport_map_port_103=22 +dport_map_port_107=23 +dport_map_port_111=24 +dport_map_port_115=25 +dport_map_port_119=26 +dport_map_port_123=27 +dport_map_port_127=28 +dport_map_port_83=29 +dport_map_port_87=30 +dport_map_port_91=31 +dport_map_port_99=32 + +dport_map_port_66=33 +dport_map_port_130=34 + +### interface setting +# TSCF / TSCE interface definition +# NULL 1 +# GMII 3 +# SGMII 4 +# XGMII 6 +# SFI 9 +# XFI 10 +# KR 11 +# KR4 12 +# CR 13 +# CR4 14 +# XLAUI 15 +# SR 16 +# ILKN 21 +# CAUI 25 +# LR 26 +# LR4 27 +# SR4 28 +# SR2 38 +# KR2 39 +# CR2 40 +# XLAUI2 42 +# LR2 55 +# CAUI4 62 +### + + +serdes_if_type_29=14 +serdes_if_type_33=14 +serdes_if_type_41=14 +serdes_if_type_45=14 +serdes_if_type_1=14 +serdes_if_type_5=14 +serdes_if_type_9=14 +serdes_if_type_13=14 +serdes_if_type_17=14 +serdes_if_type_21=14 +serdes_if_type_25=14 +serdes_if_type_37=14 +serdes_if_type_49=14 +serdes_if_type_53=14 +serdes_if_type_57=14 +serdes_if_type_61=14 + +serdes_if_type_67=14 +serdes_if_type_71=14 +serdes_if_type_75=14 +serdes_if_type_79=14 +serdes_if_type_95=14 +serdes_if_type_103=14 +serdes_if_type_107=14 +serdes_if_type_111=14 +serdes_if_type_115=14 +serdes_if_type_119=14 +serdes_if_type_123=14 +serdes_if_type_127=14 +serdes_if_type_83=14 +serdes_if_type_87=14 +serdes_if_type_91=14 +serdes_if_type_99=14 + +serdes_if_type_66=11 +serdes_if_type_130=11 + +### lane swap and polarity follow physical port +phy_chain_tx_lane_map_physical{29.0}=0x1230 +phy_chain_tx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x1 +phy_chain_rx_lane_map_physical{29.0}=0x1302 +phy_chain_rx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 + +phy_chain_tx_lane_map_physical{33.0}=0x3210 +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_rx_lane_map_physical{33.0}=0x0123 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 + +phy_chain_tx_lane_map_physical{41.0}=0x0213 +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}=0x0 +phy_chain_rx_lane_map_physical{41.0}=0x1302 +phy_chain_rx_polarity_flip_physical{41.0}=0x1 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 + +phy_chain_tx_lane_map_physical{45.0}=0x3210 +phy_chain_tx_polarity_flip_physical{45.0}=0x1 +phy_chain_tx_polarity_flip_physical{46.0}=0x1 +phy_chain_tx_polarity_flip_physical{47.0}=0x1 +phy_chain_tx_polarity_flip_physical{48.0}=0x1 +phy_chain_rx_lane_map_physical{45.0}=0x2103 +phy_chain_rx_polarity_flip_physical{45.0}=0x0 +phy_chain_rx_polarity_flip_physical{46.0}=0x0 +phy_chain_rx_polarity_flip_physical{47.0}=0x1 +phy_chain_rx_polarity_flip_physical{48.0}=0x0 + +phy_chain_tx_lane_map_physical{1.0}=0x0213 +phy_chain_tx_polarity_flip_physical{1.0}=0x0 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_lane_map_physical{1.0}=0x1302 +phy_chain_rx_polarity_flip_physical{1.0}=0x0 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x1 + +phy_chain_tx_lane_map_physical{5.0}=0x3210 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_tx_polarity_flip_physical{6.0}=0x1 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +phy_chain_rx_lane_map_physical{5.0}=0x2103 +phy_chain_rx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x1 + +phy_chain_tx_lane_map_physical{9.0}=0x0213 +phy_chain_tx_polarity_flip_physical{9.0}=0x0 +phy_chain_tx_polarity_flip_physical{10.0}=0x1 +phy_chain_tx_polarity_flip_physical{11.0}=0x1 +phy_chain_tx_polarity_flip_physical{12.0}=0x0 +phy_chain_rx_lane_map_physical{9.0}=0x1302 +phy_chain_rx_polarity_flip_physical{9.0}=0x0 +phy_chain_rx_polarity_flip_physical{10.0}=0x1 +phy_chain_rx_polarity_flip_physical{11.0}=0x1 +phy_chain_rx_polarity_flip_physical{12.0}=0x1 + +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_tx_polarity_flip_physical{13.0}=0x1 +phy_chain_tx_polarity_flip_physical{14.0}=0x1 +phy_chain_tx_polarity_flip_physical{15.0}=0x1 +phy_chain_tx_polarity_flip_physical{16.0}=0x1 +phy_chain_rx_lane_map_physical{13.0}=0x2031 +phy_chain_rx_polarity_flip_physical{13.0}=0x1 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x1 +phy_chain_rx_polarity_flip_physical{16.0}=0x1 + +phy_chain_tx_lane_map_physical{17.0}=0x0123 +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}=0x1 +phy_chain_tx_polarity_flip_physical{20.0}=0x1 +phy_chain_rx_lane_map_physical{17.0}=0x1302 +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}=0x1 + +phy_chain_tx_lane_map_physical{21.0}=0x3210 +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}=0x1 +phy_chain_tx_polarity_flip_physical{24.0}=0x1 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x1 +phy_chain_rx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 + +phy_chain_tx_lane_map_physical{25.0}=0x0213 +phy_chain_tx_polarity_flip_physical{25.0}=0x1 +phy_chain_tx_polarity_flip_physical{26.0}=0x0 +phy_chain_tx_polarity_flip_physical{27.0}=0x0 +phy_chain_tx_polarity_flip_physical{28.0}=0x1 +phy_chain_rx_lane_map_physical{25.0}=0x1302 +phy_chain_rx_polarity_flip_physical{25.0}=0x1 +phy_chain_rx_polarity_flip_physical{26.0}=0x1 +phy_chain_rx_polarity_flip_physical{27.0}=0x0 +phy_chain_rx_polarity_flip_physical{28.0}=0x0 + +phy_chain_tx_lane_map_physical{37.0}=0x3210 +phy_chain_tx_polarity_flip_physical{37.0}=0x1 +phy_chain_tx_polarity_flip_physical{38.0}=0x1 +phy_chain_tx_polarity_flip_physical{39.0}=0x1 +phy_chain_tx_polarity_flip_physical{40.0}=0x1 +phy_chain_rx_lane_map_physical{37.0}=0x2103 +phy_chain_rx_polarity_flip_physical{37.0}=0x0 +phy_chain_rx_polarity_flip_physical{38.0}=0x0 +phy_chain_rx_polarity_flip_physical{39.0}=0x1 +phy_chain_rx_polarity_flip_physical{40.0}=0x0 + +phy_chain_tx_lane_map_physical{49.0}=0x0213 +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +phy_chain_tx_polarity_flip_physical{51.0}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +phy_chain_rx_lane_map_physical{49.0}=0x1302 +phy_chain_rx_polarity_flip_physical{49.0}=0x1 +phy_chain_rx_polarity_flip_physical{50.0}=0x1 +phy_chain_rx_polarity_flip_physical{51.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 + +phy_chain_tx_lane_map_physical{53.0}=0x3210 +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}=0x0 +phy_chain_tx_polarity_flip_physical{56.0}=0x0 +phy_chain_rx_lane_map_physical{53.0}=0x2103 +phy_chain_rx_polarity_flip_physical{53.0}=0x0 +phy_chain_rx_polarity_flip_physical{54.0}=0x0 +phy_chain_rx_polarity_flip_physical{55.0}=0x1 +phy_chain_rx_polarity_flip_physical{56.0}=0x0 + +phy_chain_tx_lane_map_physical{57.0}=0x0213 +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}=0x0 +phy_chain_rx_lane_map_physical{57.0}=0x1302 +phy_chain_rx_polarity_flip_physical{57.0}=0x1 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 + +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 +phy_chain_rx_lane_map_physical{61.0}=0x2103 +phy_chain_rx_polarity_flip_physical{61.0}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x0 + +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_tx_polarity_flip_physical{65.0}=0x0 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_tx_polarity_flip_physical{67.0}=0x1 +phy_chain_tx_polarity_flip_physical{68.0}=0x1 +phy_chain_rx_lane_map_physical{65.0}=0x3120 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x1 +phy_chain_rx_polarity_flip_physical{68.0}=0x1 + +phy_chain_tx_lane_map_physical{69.0}=0x0123 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x0 +phy_chain_tx_polarity_flip_physical{71.0}=0x0 +phy_chain_tx_polarity_flip_physical{72.0}=0x0 +phy_chain_rx_lane_map_physical{69.0}=0x2301 +phy_chain_rx_polarity_flip_physical{69.0}=0x1 +phy_chain_rx_polarity_flip_physical{70.0}=0x0 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 + +phy_chain_tx_lane_map_physical{73.0}=0x3120 +phy_chain_tx_polarity_flip_physical{73.0}=0x1 +phy_chain_tx_polarity_flip_physical{74.0}=0x0 +phy_chain_tx_polarity_flip_physical{75.0}=0x0 +phy_chain_tx_polarity_flip_physical{76.0}=0x1 +phy_chain_rx_lane_map_physical{73.0}=0x3120 +phy_chain_rx_polarity_flip_physical{73.0}=0x0 +phy_chain_rx_polarity_flip_physical{74.0}=0x0 +phy_chain_rx_polarity_flip_physical{75.0}=0x1 +phy_chain_rx_polarity_flip_physical{76.0}=0x1 + +phy_chain_tx_lane_map_physical{77.0}=0x0213 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x0 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x1 +phy_chain_rx_lane_map_physical{77.0}=0x0321 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x1 + +phy_chain_tx_lane_map_physical{93.0}=0x3120 +phy_chain_tx_polarity_flip_physical{93.0}=0x1 +phy_chain_tx_polarity_flip_physical{94.0}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 +phy_chain_rx_lane_map_physical{93.0}=0x3120 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x0 +phy_chain_rx_polarity_flip_physical{96.0}=0x0 + +phy_chain_tx_lane_map_physical{101.0}=0x0321 +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}=0x1 +phy_chain_rx_lane_map_physical{101.0}=0x0321 +phy_chain_rx_polarity_flip_physical{101.0}=0x1 +phy_chain_rx_polarity_flip_physical{102.0}=0x1 +phy_chain_rx_polarity_flip_physical{103.0}=0x0 +phy_chain_rx_polarity_flip_physical{104.0}=0x1 + +phy_chain_tx_lane_map_physical{105.0}=0x3120 +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}=0x1 +phy_chain_rx_lane_map_physical{105.0}=0x3120 +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}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x0 + +phy_chain_tx_lane_map_physical{109.0}=0x0123 +phy_chain_tx_polarity_flip_physical{109.0}=0x1 +phy_chain_tx_polarity_flip_physical{110.0}=0x1 +phy_chain_tx_polarity_flip_physical{111.0}=0x1 +phy_chain_tx_polarity_flip_physical{112.0}=0x1 +phy_chain_rx_lane_map_physical{109.0}=0x0321 +phy_chain_rx_polarity_flip_physical{109.0}=0x0 +phy_chain_rx_polarity_flip_physical{110.0}=0x0 +phy_chain_rx_polarity_flip_physical{111.0}=0x1 +phy_chain_rx_polarity_flip_physical{112.0}=0x0 + +phy_chain_tx_lane_map_physical{113.0}=0x0312 +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}=0x1 +phy_chain_tx_polarity_flip_physical{116.0}=0x0 +phy_chain_rx_lane_map_physical{113.0}=0x3120 +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_tx_lane_map_physical{117.0}=0x0123 +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}=0x1 +phy_chain_tx_polarity_flip_physical{120.0}=0x1 +phy_chain_rx_lane_map_physical{117.0}=0x1320 +phy_chain_rx_polarity_flip_physical{117.0}=0x1 +phy_chain_rx_polarity_flip_physical{118.0}=0x1 +phy_chain_rx_polarity_flip_physical{119.0}=0x1 +phy_chain_rx_polarity_flip_physical{120.0}=0x0 + +phy_chain_tx_lane_map_physical{121.0}=0x3120 +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}=0x1 +phy_chain_rx_lane_map_physical{121.0}=0x0123 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x1 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 + +phy_chain_tx_lane_map_physical{125.0}=0x0123 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_lane_map_physical{125.0}=0x0321 +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}=0x0 + +phy_chain_tx_lane_map_physical{81.0}=0x3201 +phy_chain_tx_polarity_flip_physical{81.0}=0x0 +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_rx_lane_map_physical{81.0}=0x3120 +phy_chain_rx_polarity_flip_physical{81.0}=0x0 +phy_chain_rx_polarity_flip_physical{82.0}=0x0 +phy_chain_rx_polarity_flip_physical{83.0}=0x1 +phy_chain_rx_polarity_flip_physical{84.0}=0x0 + +phy_chain_tx_lane_map_physical{85.0}=0x0123 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x1 +phy_chain_tx_polarity_flip_physical{88.0}=0x1 +phy_chain_rx_lane_map_physical{85.0}=0x0321 +phy_chain_rx_polarity_flip_physical{85.0}=0x1 +phy_chain_rx_polarity_flip_physical{86.0}=0x1 +phy_chain_rx_polarity_flip_physical{87.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x1 + +phy_chain_tx_lane_map_physical{89.0}=0x3210 +phy_chain_tx_polarity_flip_physical{89.0}=0x1 +phy_chain_tx_polarity_flip_physical{90.0}=0x1 +phy_chain_tx_polarity_flip_physical{91.0}=0x1 +phy_chain_tx_polarity_flip_physical{92.0}=0x1 +phy_chain_rx_lane_map_physical{89.0}=0x0123 +phy_chain_rx_polarity_flip_physical{89.0}=0x1 +phy_chain_rx_polarity_flip_physical{90.0}=0x0 +phy_chain_rx_polarity_flip_physical{91.0}=0x1 +phy_chain_rx_polarity_flip_physical{92.0}=0x0 + +phy_chain_tx_lane_map_physical{97.0}=0x0312 +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 +phy_chain_rx_lane_map_physical{97.0}=0x0321 +phy_chain_rx_polarity_flip_physical{97.0}=0x1 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x1 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 + diff --git a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/default_sku b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/default_sku new file mode 100644 index 000000000000..e9066fe7299b --- /dev/null +++ b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/default_sku @@ -0,0 +1 @@ +Quanta-IX7-32X t1 diff --git a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/installer.conf b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/led_proc_init.soc b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/led_proc_init.soc new file mode 100755 index 000000000000..0861486660c3 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/led_proc_init.soc @@ -0,0 +1,6 @@ +sleep 10 +led stop +sleep 3 +led start +sleep 3 +led auto on \ No newline at end of file diff --git a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/plugins/eeprom.py b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/plugins/eeprom.py new file mode 100644 index 000000000000..fa34110c04ea --- /dev/null +++ b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/18-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/plugins/psuutil.py b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/plugins/psuutil.py new file mode 100644 index 000000000000..5cf06fb5d66a --- /dev/null +++ b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/plugins/psuutil.py @@ -0,0 +1,50 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + 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 = 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 = 1 + + return status diff --git a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/plugins/sfputil.py b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/plugins/sfputil.py new file mode 100644 index 000000000000..14b0ef6674be --- /dev/null +++ b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/plugins/sfputil.py @@ -0,0 +1,176 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + 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 = 32 + PORTS_IN_BLOCK = 32 + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 1: 32, + 2: 33, + 3: 34, + 4: 35, + 5: 36, + 6: 37, + 7: 38, + 8: 39, + 9: 40, + 10: 41, + 11: 42, + 12: 43, + 13: 44, + 14: 45, + 15: 46, + 16: 47, + 17: 48, + 18: 49, + 19: 50, + 20: 51, + 21: 52, + 22: 53, + 23: 54, + 24: 55, + 25: 56, + 26: 57, + 27: 58, + 28: 59, + 29: 60, + 30: 61, + 31: 62, + 32: 63, + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return list(range(self.PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format(self._port_to_i2c_mapping[x]) + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num)+"/module_present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num)+"/lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num)+"/lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num)+"/reset", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open("/sys/class/cpld-qsfp28/port-"+str(port_num)+"/reset", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/port_config.ini b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/port_config.ini new file mode 100644 index 000000000000..c9dd2fb999f9 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 60 twentyfiveGigE1 1 25000 +Ethernet1 59 twentyfiveGigE2 2 25000 +Ethernet2 58 twentyfiveGigE3 3 25000 +Ethernet3 57 twentyfiveGigE4 4 25000 +Ethernet4 64 twentyfiveGigE5 5 25000 +Ethernet5 63 twentyfiveGigE6 6 25000 +Ethernet6 62 twentyfiveGigE7 7 25000 +Ethernet7 61 twentyfiveGigE8 8 25000 +Ethernet8 49 twentyfiveGigE9 9 25000 +Ethernet9 50 twentyfiveGigE10 10 25000 +Ethernet10 51 twentyfiveGigE11 11 25000 +Ethernet11 52 twentyfiveGigE12 12 25000 +Ethernet12 4 twentyfiveGigE13 13 25000 +Ethernet13 3 twentyfiveGigE14 14 25000 +Ethernet14 2 twentyfiveGigE15 15 25000 +Ethernet15 1 twentyfiveGigE16 16 25000 +Ethernet16 8 twentyfiveGigE17 17 25000 +Ethernet17 7 twentyfiveGigE18 18 25000 +Ethernet18 6 twentyfiveGigE19 19 25000 +Ethernet19 5 twentyfiveGigE20 20 25000 +Ethernet20 16 twentyfiveGigE21 21 25000 +Ethernet21 15 twentyfiveGigE22 22 25000 +Ethernet22 14 twentyfiveGigE23 23 25000 +Ethernet23 13 twentyfiveGigE24 24 25000 +Ethernet24 24 twentyfiveGigE25 25 25000 +Ethernet25 23 twentyfiveGigE26 26 25000 +Ethernet26 22 twentyfiveGigE27 27 25000 +Ethernet27 21 twentyfiveGigE28 28 25000 +Ethernet28 32 twentyfiveGigE29 29 25000 +Ethernet29 31 twentyfiveGigE30 30 25000 +Ethernet30 30 twentyfiveGigE31 31 25000 +Ethernet31 29 twentyfiveGigE32 32 25000 +Ethernet32 36 twentyfiveGigE33 33 25000 +Ethernet33 35 twentyfiveGigE34 34 25000 +Ethernet34 34 twentyfiveGigE35 35 25000 +Ethernet35 33 twentyfiveGigE36 36 25000 +Ethernet36 44 twentyfiveGigE37 37 25000 +Ethernet37 43 twentyfiveGigE38 38 25000 +Ethernet38 42 twentyfiveGigE39 39 25000 +Ethernet39 41 twentyfiveGigE40 40 25000 +Ethernet40 86 twentyfiveGigE41 41 25000 +Ethernet41 85 twentyfiveGigE42 42 25000 +Ethernet42 88 twentyfiveGigE43 43 25000 +Ethernet43 87 twentyfiveGigE44 44 25000 +Ethernet44 94 twentyfiveGigE45 45 25000 +Ethernet45 93 twentyfiveGigE46 46 25000 +Ethernet46 96 twentyfiveGigE47 47 25000 +Ethernet47 95 twentyfiveGigE48 48 25000 +Ethernet48 97,98,99,100 hundredGigE49 49 100000 +Ethernet52 105,106,107,108 hundredGigE50 50 100000 +Ethernet56 113,114,115,116 hundredGigE51 51 100000 +Ethernet60 121,122,123,124 hundredGigE52 52 100000 +Ethernet64 77,78,79,80 hundredGigE53 53 100000 +Ethernet68 65,66,67,68 hundredGigE54 54 100000 +Ethernet72 69,70,71,72 hundredGigE55 55 100000 +Ethernet76 125,126,127,128 hundredGigE56 56 100000 diff --git a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/sai.profile b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/sai.profile new file mode 100644 index 000000000000..62ee26ea8c15 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-ix8-48x25G+8x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/td3-ix8-48x25G+8x100G.config.bcm b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/td3-ix8-48x25G+8x100G.config.bcm new file mode 100644 index 000000000000..94560fb7e86c --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/td3-ix8-48x25G+8x100G.config.bcm @@ -0,0 +1,481 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +bcm_tunnel_term_compatible_mode=1 +core_clock_frequency=1525 +dpp_clock_ratio=2:3 +parity_enable=0 +mem_cache_enable=0 +l2_mem_entries=40960 +l3_mem_entries=40960 +fpem_mem_entries=16384 +l2xmsg_mode=1 + +bcm_num_cos=10 +bcm_stat_interval=2000000 +cdma_timeout_usec=3000000 + +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l3_max_ecmp_mode=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 + +miim_intr_enable=0 +module_64ports=1 + +schan_intr_enable=0 +skip_L2_USER_ENTRY=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 + +# portmap settings +oversubscribe_mode=1 +pbmp_xport_xe=0x48808080f8780808dfe1e1e1fe1e1e1fe + +port_flex_enable=1 + +portmap_1=1:25 +portmap_2=2:25 +portmap_3=3:25 +portmap_4=4:25 +portmap_5=5:25 +portmap_6=6:25 +portmap_7=7:25 +portmap_8=8:25 +portmap_13=13:25 +portmap_14=14:25 +portmap_15=15:25 +portmap_16=16:25 +portmap_21=21:25 +portmap_22=22:25 +portmap_23=23:25 +portmap_24=24:25 +portmap_29=29:25 +portmap_30=30:25 +portmap_31=31:25 +portmap_32=32:25 +portmap_33=33:25 +portmap_34=34:25 +portmap_35=35:25 +portmap_36=36:25 +portmap_41=41:25 +portmap_42=42:25 +portmap_43=43:25 +portmap_44=44:25 +portmap_49=49:25 +portmap_50=50:25 +portmap_51=51:25 +portmap_52=52:25 +portmap_57=57:25 +portmap_58=58:25 +portmap_59=59:25 +portmap_60=60:25 +portmap_61=61:25 +portmap_62=62:25 +portmap_63=63:25 +portmap_64=64:25 +portmap_67=65:100 +portmap_71=69:100 +portmap_79=77:100 +portmap_87=85:25 +portmap_88=86:25 +portmap_89=87:25 +portmap_90=88:25 +portmap_95=93:25 +portmap_96=94:25 +portmap_97=95:25 +portmap_98=96:25 +portmap_99=97:100 +portmap_107=105:100 +portmap_115=113:100 +portmap_123=121:100 +portmap_127=125:100 + +# datapath port -- MerlinCore +portmap_66=129:10:m +portmap_130=128:10:m + +# loopback port +portmap_65=130:10 +portmap_131=131:10 + + +### interface setting +# TSCF / TSCE interface definition +# NULL 1 +# GMII 3 +# SGMII 4 +# XGMII 6 +# SFI 9 +# XFI 10 +# KR 11 +# KR4 12 +# CR 13 +# CR4 14 +# XLAUI 15 +# SR 16 +# ILKN 21 +# CAUI 25 +# LR 26 +# LR4 27 +# SR4 28 +# SR2 38 +# KR2 39 +# CR2 40 +# XLAUI2 42 +# LR2 55 +# CAUI4 62 +### + +serdes_if_type_1=13 +serdes_if_type_2=13 +serdes_if_type_3=13 +serdes_if_type_4=13 +serdes_if_type_5=13 +serdes_if_type_6=13 +serdes_if_type_7=13 +serdes_if_type_8=13 +serdes_if_type_13=13 +serdes_if_type_14=13 +serdes_if_type_15=13 +serdes_if_type_16=13 +serdes_if_type_21=13 +serdes_if_type_22=13 +serdes_if_type_23=13 +serdes_if_type_24=13 +serdes_if_type_29=13 +serdes_if_type_30=13 +serdes_if_type_31=13 +serdes_if_type_32=13 +serdes_if_type_33=13 +serdes_if_type_34=13 +serdes_if_type_35=13 +serdes_if_type_36=13 +serdes_if_type_41=13 +serdes_if_type_42=13 +serdes_if_type_43=13 +serdes_if_type_44=13 +serdes_if_type_49=13 +serdes_if_type_50=13 +serdes_if_type_51=13 +serdes_if_type_52=13 +serdes_if_type_57=13 +serdes_if_type_58=13 +serdes_if_type_59=13 +serdes_if_type_60=13 +serdes_if_type_61=13 +serdes_if_type_62=13 +serdes_if_type_63=13 +serdes_if_type_64=13 +serdes_if_type_67=14 +serdes_if_type_71=14 +serdes_if_type_79=14 +serdes_if_type_87=13 +serdes_if_type_88=13 +serdes_if_type_89=13 +serdes_if_type_90=13 +serdes_if_type_95=13 +serdes_if_type_96=13 +serdes_if_type_97=13 +serdes_if_type_98=13 +serdes_if_type_99=14 +serdes_if_type_107=14 +serdes_if_type_115=14 +serdes_if_type_123=14 +serdes_if_type_127=14 +serdes_if_type_66=11 +serdes_if_type_130=11 + + +dport_map_port_60=1 +dport_map_port_59=2 +dport_map_port_58=3 +dport_map_port_57=4 +dport_map_port_64=5 +dport_map_port_63=6 +dport_map_port_62=7 +dport_map_port_61=8 +dport_map_port_49=9 +dport_map_port_50=10 +dport_map_port_51=11 +dport_map_port_52=12 +dport_map_port_4=13 +dport_map_port_3=14 +dport_map_port_2=15 +dport_map_port_1=16 +dport_map_port_8=17 +dport_map_port_7=18 +dport_map_port_6=19 +dport_map_port_5=20 +dport_map_port_16=21 +dport_map_port_15=22 +dport_map_port_14=23 +dport_map_port_13=24 +dport_map_port_24=25 +dport_map_port_23=26 +dport_map_port_22=27 +dport_map_port_21=28 +dport_map_port_32=29 +dport_map_port_31=30 +dport_map_port_30=31 +dport_map_port_29=32 +dport_map_port_36=33 +dport_map_port_35=34 +dport_map_port_34=35 +dport_map_port_33=36 +dport_map_port_44=37 +dport_map_port_43=38 +dport_map_port_42=39 +dport_map_port_41=40 +dport_map_port_88=41 +dport_map_port_87=42 +dport_map_port_90=43 +dport_map_port_89=44 +dport_map_port_96=45 +dport_map_port_95=46 +dport_map_port_98=47 +dport_map_port_97=48 +dport_map_port_99=49 +dport_map_port_107=50 +dport_map_port_115=51 +dport_map_port_123=52 +dport_map_port_79=53 +dport_map_port_67=54 +dport_map_port_71=55 +dport_map_port_127=56 + +dport_map_port_66=57 +dport_map_port_130=58 + + +phy_chain_tx_lane_map_physical{1.0}=0x3210 +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x0 + +phy_chain_tx_lane_map_physical{5.0}=0x3210 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +phy_chain_rx_lane_map_physical{5.0}=0x3210 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x1 + +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_lane_map_physical{13.0}=0x3210 +phy_chain_rx_polarity_flip_physical{13.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}=0x1 + +phy_chain_tx_lane_map_physical{21.0}=0x3210 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_rx_lane_map_physical{21.0}=0x3210 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +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}=0x1 + +phy_chain_tx_lane_map_physical{29.0}=0x3210 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_lane_map_physical{29.0}=0x3210 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 + +phy_chain_tx_lane_map_physical{33.0}=0x3210 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +phy_chain_rx_lane_map_physical{33.0}=0x3210 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 + +phy_chain_tx_lane_map_physical{41.0}=0x3210 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_lane_map_physical{41.0}=0x3210 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x1 + +phy_chain_tx_lane_map_physical{49.0}=0x3210 +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x1 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +phy_chain_rx_lane_map_physical{49.0}=0x3210 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 + +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_polarity_flip_physical{57.0}=0x1 +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_rx_lane_map_physical{57.0}=0x3210 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 + +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 +phy_chain_rx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x0 + +phy_chain_tx_lane_map_physical{65.0}=0x0123 +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_rx_lane_map_physical{65.0}=0x0321 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x1 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 + +phy_chain_tx_lane_map_physical{69.0}=0x3120 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 +phy_chain_rx_lane_map_physical{69.0}=0x0123 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 + +phy_chain_tx_lane_map_physical{77.0}=0x2130 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +phy_chain_rx_lane_map_physical{77.0}=0x3102 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x0 + +phy_chain_tx_lane_map_physical{85.0}=0x3210 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x1 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +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_tx_lane_map_physical{93.0}=0x3210 +phy_chain_tx_polarity_flip_physical{93.0}=0x0 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +phy_chain_tx_polarity_flip_physical{95.0}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 +phy_chain_rx_lane_map_physical{93.0}=0x3210 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 + +phy_chain_tx_lane_map_physical{97.0}=0x0312 +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 +phy_chain_rx_lane_map_physical{97.0}=0x1023 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 + +phy_chain_tx_lane_map_physical{105.0}=0x0123 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +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_rx_lane_map_physical{105.0}=0x0321 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x1 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 + +phy_chain_tx_lane_map_physical{113.0}=0x3120 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +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_rx_lane_map_physical{113.0}=0x1023 +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}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 + +phy_chain_tx_lane_map_physical{121.0}=0x0132 +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +phy_chain_tx_polarity_flip_physical{123.0}=0x0 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 +phy_chain_rx_lane_map_physical{121.0}=0x0321 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x1 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 + +phy_chain_tx_lane_map_physical{125.0}=0x0213 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +phy_chain_rx_lane_map_physical{125.0}=0x0321 +phy_chain_rx_polarity_flip_physical{125.0}=0x1 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +### MerlinCore +phy_chain_tx_lane_map_physical{129.0}=0x3210 +phy_chain_tx_polarity_flip_physical{129.0}=0x0 +phy_chain_tx_polarity_flip_physical{130.0}=0x1 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 +phy_chain_rx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 + diff --git a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/default_sku b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/default_sku new file mode 100644 index 000000000000..b775ae4d3e67 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/default_sku @@ -0,0 +1 @@ +Quanta-IX8-56X t1 diff --git a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/installer.conf b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/installer.conf new file mode 100644 index 000000000000..14404194ef53 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=115200 diff --git a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/led_proc_init.soc b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/led_proc_init.soc new file mode 100755 index 000000000000..0861486660c3 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/led_proc_init.soc @@ -0,0 +1,6 @@ +sleep 10 +led stop +sleep 3 +led start +sleep 3 +led auto on \ No newline at end of file diff --git a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/plugins/eeprom.py b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/plugins/eeprom.py new file mode 100644 index 000000000000..fa34110c04ea --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/18-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/plugins/psuutil.py b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/plugins/psuutil.py new file mode 100644 index 000000000000..5cf06fb5d66a --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/plugins/psuutil.py @@ -0,0 +1,50 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + 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 = 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 = 1 + + return status diff --git a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/plugins/sfputil.py b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/plugins/sfputil.py new file mode 100644 index 000000000000..3067919795d5 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/plugins/sfputil.py @@ -0,0 +1,217 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + 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 = 56 + PORTS_IN_BLOCK = 56 + QSFP_PORT_START = 49 + QSFP_PORT_END = 56 + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 1: 32, + 2: 33, + 3: 34, + 4: 35, + 5: 36, + 6: 37, + 7: 38, + 8: 39, + 9: 40, + 10: 41, + 11: 42, + 12: 43, + 13: 44, + 14: 45, + 15: 46, + 16: 47, + 17: 48, + 18: 49, + 19: 50, + 20: 51, + 21: 52, + 22: 53, + 23: 54, + 24: 55, + 25: 56, + 26: 57, + 27: 58, + 28: 59, + 29: 60, + 30: 61, + 31: 62, + 32: 63, + 33: 64, + 34: 65, + 35: 66, + 36: 67, + 37: 68, + 38: 69, + 39: 70, + 40: 71, + 41: 72, + 42: 73, + 43: 74, + 44: 75, + 45: 76, + 46: 77, + 47: 78, + 48: 79, + 49: 80, # QSFP49 + 50: 81, # QSFP50 + 51: 82, # QSFP51 + 52: 83, # QSFP52 + 53: 84, # QSFP53 + 54: 85, # QSFP54 + 55: 86, # QSFP55 + 56: 87, # QSFP56 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format(self._port_to_i2c_mapping[x]) + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + if port_num < self.qsfp_port_start: + reg_file = open("/sys/class/cpld-sfp28/port-"+str(port_num)+"/pre_n") + else: + reg_file = open("/sys/class/gpio/gpio"+str((port_num-self.qsfp_port_start)*4+34)+"/value") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_file.readline().rstrip() + if port_num < self.qsfp_port_start: + if reg_value == '1': + return True + else: + if reg_value == '0': + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + reg_file = open("/sys/class/gpio/gpio"+str((port_num-self.qsfp_port_start)*4+35)+"/value") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + 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.qsfp_port_end: + return False + + try: + reg_file = open("/sys/class/gpio/gpio"+str((port_num-self.qsfp_port_start)*4+35)+"/value", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/gpio/gpio"+str((port_num-self.qsfp_port_start)*4+32)+"/value", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open("/sys/class/gpio/gpio"+str((port_num-self.qsfp_port_start)*4+32)+"/value", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/port_config.ini b/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/port_config.ini new file mode 100644 index 000000000000..c9dd2fb999f9 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed +Ethernet0 60 twentyfiveGigE1 1 25000 +Ethernet1 59 twentyfiveGigE2 2 25000 +Ethernet2 58 twentyfiveGigE3 3 25000 +Ethernet3 57 twentyfiveGigE4 4 25000 +Ethernet4 64 twentyfiveGigE5 5 25000 +Ethernet5 63 twentyfiveGigE6 6 25000 +Ethernet6 62 twentyfiveGigE7 7 25000 +Ethernet7 61 twentyfiveGigE8 8 25000 +Ethernet8 49 twentyfiveGigE9 9 25000 +Ethernet9 50 twentyfiveGigE10 10 25000 +Ethernet10 51 twentyfiveGigE11 11 25000 +Ethernet11 52 twentyfiveGigE12 12 25000 +Ethernet12 4 twentyfiveGigE13 13 25000 +Ethernet13 3 twentyfiveGigE14 14 25000 +Ethernet14 2 twentyfiveGigE15 15 25000 +Ethernet15 1 twentyfiveGigE16 16 25000 +Ethernet16 8 twentyfiveGigE17 17 25000 +Ethernet17 7 twentyfiveGigE18 18 25000 +Ethernet18 6 twentyfiveGigE19 19 25000 +Ethernet19 5 twentyfiveGigE20 20 25000 +Ethernet20 16 twentyfiveGigE21 21 25000 +Ethernet21 15 twentyfiveGigE22 22 25000 +Ethernet22 14 twentyfiveGigE23 23 25000 +Ethernet23 13 twentyfiveGigE24 24 25000 +Ethernet24 24 twentyfiveGigE25 25 25000 +Ethernet25 23 twentyfiveGigE26 26 25000 +Ethernet26 22 twentyfiveGigE27 27 25000 +Ethernet27 21 twentyfiveGigE28 28 25000 +Ethernet28 32 twentyfiveGigE29 29 25000 +Ethernet29 31 twentyfiveGigE30 30 25000 +Ethernet30 30 twentyfiveGigE31 31 25000 +Ethernet31 29 twentyfiveGigE32 32 25000 +Ethernet32 36 twentyfiveGigE33 33 25000 +Ethernet33 35 twentyfiveGigE34 34 25000 +Ethernet34 34 twentyfiveGigE35 35 25000 +Ethernet35 33 twentyfiveGigE36 36 25000 +Ethernet36 44 twentyfiveGigE37 37 25000 +Ethernet37 43 twentyfiveGigE38 38 25000 +Ethernet38 42 twentyfiveGigE39 39 25000 +Ethernet39 41 twentyfiveGigE40 40 25000 +Ethernet40 86 twentyfiveGigE41 41 25000 +Ethernet41 85 twentyfiveGigE42 42 25000 +Ethernet42 88 twentyfiveGigE43 43 25000 +Ethernet43 87 twentyfiveGigE44 44 25000 +Ethernet44 94 twentyfiveGigE45 45 25000 +Ethernet45 93 twentyfiveGigE46 46 25000 +Ethernet46 96 twentyfiveGigE47 47 25000 +Ethernet47 95 twentyfiveGigE48 48 25000 +Ethernet48 97,98,99,100 hundredGigE49 49 100000 +Ethernet52 105,106,107,108 hundredGigE50 50 100000 +Ethernet56 113,114,115,116 hundredGigE51 51 100000 +Ethernet60 121,122,123,124 hundredGigE52 52 100000 +Ethernet64 77,78,79,80 hundredGigE53 53 100000 +Ethernet68 65,66,67,68 hundredGigE54 54 100000 +Ethernet72 69,70,71,72 hundredGigE55 55 100000 +Ethernet76 125,126,127,128 hundredGigE56 56 100000 diff --git a/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/sai.profile b/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/sai.profile new file mode 100644 index 000000000000..936f0d0cddcf --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-ix8c-48x25G+8x100G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/td3-ix8c-48x25G+8x100G.config.bcm b/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/td3-ix8c-48x25G+8x100G.config.bcm new file mode 100644 index 000000000000..94560fb7e86c --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/td3-ix8c-48x25G+8x100G.config.bcm @@ -0,0 +1,481 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +bcm_tunnel_term_compatible_mode=1 +core_clock_frequency=1525 +dpp_clock_ratio=2:3 +parity_enable=0 +mem_cache_enable=0 +l2_mem_entries=40960 +l3_mem_entries=40960 +fpem_mem_entries=16384 +l2xmsg_mode=1 + +bcm_num_cos=10 +bcm_stat_interval=2000000 +cdma_timeout_usec=3000000 + +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l3_max_ecmp_mode=1 +l3_alpm_enable=2 +lpm_scaling_enable=0 + +miim_intr_enable=0 +module_64ports=1 + +schan_intr_enable=0 +skip_L2_USER_ENTRY=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 + +# portmap settings +oversubscribe_mode=1 +pbmp_xport_xe=0x48808080f8780808dfe1e1e1fe1e1e1fe + +port_flex_enable=1 + +portmap_1=1:25 +portmap_2=2:25 +portmap_3=3:25 +portmap_4=4:25 +portmap_5=5:25 +portmap_6=6:25 +portmap_7=7:25 +portmap_8=8:25 +portmap_13=13:25 +portmap_14=14:25 +portmap_15=15:25 +portmap_16=16:25 +portmap_21=21:25 +portmap_22=22:25 +portmap_23=23:25 +portmap_24=24:25 +portmap_29=29:25 +portmap_30=30:25 +portmap_31=31:25 +portmap_32=32:25 +portmap_33=33:25 +portmap_34=34:25 +portmap_35=35:25 +portmap_36=36:25 +portmap_41=41:25 +portmap_42=42:25 +portmap_43=43:25 +portmap_44=44:25 +portmap_49=49:25 +portmap_50=50:25 +portmap_51=51:25 +portmap_52=52:25 +portmap_57=57:25 +portmap_58=58:25 +portmap_59=59:25 +portmap_60=60:25 +portmap_61=61:25 +portmap_62=62:25 +portmap_63=63:25 +portmap_64=64:25 +portmap_67=65:100 +portmap_71=69:100 +portmap_79=77:100 +portmap_87=85:25 +portmap_88=86:25 +portmap_89=87:25 +portmap_90=88:25 +portmap_95=93:25 +portmap_96=94:25 +portmap_97=95:25 +portmap_98=96:25 +portmap_99=97:100 +portmap_107=105:100 +portmap_115=113:100 +portmap_123=121:100 +portmap_127=125:100 + +# datapath port -- MerlinCore +portmap_66=129:10:m +portmap_130=128:10:m + +# loopback port +portmap_65=130:10 +portmap_131=131:10 + + +### interface setting +# TSCF / TSCE interface definition +# NULL 1 +# GMII 3 +# SGMII 4 +# XGMII 6 +# SFI 9 +# XFI 10 +# KR 11 +# KR4 12 +# CR 13 +# CR4 14 +# XLAUI 15 +# SR 16 +# ILKN 21 +# CAUI 25 +# LR 26 +# LR4 27 +# SR4 28 +# SR2 38 +# KR2 39 +# CR2 40 +# XLAUI2 42 +# LR2 55 +# CAUI4 62 +### + +serdes_if_type_1=13 +serdes_if_type_2=13 +serdes_if_type_3=13 +serdes_if_type_4=13 +serdes_if_type_5=13 +serdes_if_type_6=13 +serdes_if_type_7=13 +serdes_if_type_8=13 +serdes_if_type_13=13 +serdes_if_type_14=13 +serdes_if_type_15=13 +serdes_if_type_16=13 +serdes_if_type_21=13 +serdes_if_type_22=13 +serdes_if_type_23=13 +serdes_if_type_24=13 +serdes_if_type_29=13 +serdes_if_type_30=13 +serdes_if_type_31=13 +serdes_if_type_32=13 +serdes_if_type_33=13 +serdes_if_type_34=13 +serdes_if_type_35=13 +serdes_if_type_36=13 +serdes_if_type_41=13 +serdes_if_type_42=13 +serdes_if_type_43=13 +serdes_if_type_44=13 +serdes_if_type_49=13 +serdes_if_type_50=13 +serdes_if_type_51=13 +serdes_if_type_52=13 +serdes_if_type_57=13 +serdes_if_type_58=13 +serdes_if_type_59=13 +serdes_if_type_60=13 +serdes_if_type_61=13 +serdes_if_type_62=13 +serdes_if_type_63=13 +serdes_if_type_64=13 +serdes_if_type_67=14 +serdes_if_type_71=14 +serdes_if_type_79=14 +serdes_if_type_87=13 +serdes_if_type_88=13 +serdes_if_type_89=13 +serdes_if_type_90=13 +serdes_if_type_95=13 +serdes_if_type_96=13 +serdes_if_type_97=13 +serdes_if_type_98=13 +serdes_if_type_99=14 +serdes_if_type_107=14 +serdes_if_type_115=14 +serdes_if_type_123=14 +serdes_if_type_127=14 +serdes_if_type_66=11 +serdes_if_type_130=11 + + +dport_map_port_60=1 +dport_map_port_59=2 +dport_map_port_58=3 +dport_map_port_57=4 +dport_map_port_64=5 +dport_map_port_63=6 +dport_map_port_62=7 +dport_map_port_61=8 +dport_map_port_49=9 +dport_map_port_50=10 +dport_map_port_51=11 +dport_map_port_52=12 +dport_map_port_4=13 +dport_map_port_3=14 +dport_map_port_2=15 +dport_map_port_1=16 +dport_map_port_8=17 +dport_map_port_7=18 +dport_map_port_6=19 +dport_map_port_5=20 +dport_map_port_16=21 +dport_map_port_15=22 +dport_map_port_14=23 +dport_map_port_13=24 +dport_map_port_24=25 +dport_map_port_23=26 +dport_map_port_22=27 +dport_map_port_21=28 +dport_map_port_32=29 +dport_map_port_31=30 +dport_map_port_30=31 +dport_map_port_29=32 +dport_map_port_36=33 +dport_map_port_35=34 +dport_map_port_34=35 +dport_map_port_33=36 +dport_map_port_44=37 +dport_map_port_43=38 +dport_map_port_42=39 +dport_map_port_41=40 +dport_map_port_88=41 +dport_map_port_87=42 +dport_map_port_90=43 +dport_map_port_89=44 +dport_map_port_96=45 +dport_map_port_95=46 +dport_map_port_98=47 +dport_map_port_97=48 +dport_map_port_99=49 +dport_map_port_107=50 +dport_map_port_115=51 +dport_map_port_123=52 +dport_map_port_79=53 +dport_map_port_67=54 +dport_map_port_71=55 +dport_map_port_127=56 + +dport_map_port_66=57 +dport_map_port_130=58 + + +phy_chain_tx_lane_map_physical{1.0}=0x3210 +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +phy_chain_tx_polarity_flip_physical{2.0}=0x1 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_tx_polarity_flip_physical{4.0}=0x1 +phy_chain_rx_lane_map_physical{1.0}=0x3210 +phy_chain_rx_polarity_flip_physical{1.0}=0x1 +phy_chain_rx_polarity_flip_physical{2.0}=0x0 +phy_chain_rx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{4.0}=0x0 + +phy_chain_tx_lane_map_physical{5.0}=0x3210 +phy_chain_tx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x1 +phy_chain_rx_lane_map_physical{5.0}=0x3210 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x1 + +phy_chain_tx_lane_map_physical{13.0}=0x3210 +phy_chain_tx_polarity_flip_physical{13.0}=0x0 +phy_chain_tx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_lane_map_physical{13.0}=0x3210 +phy_chain_rx_polarity_flip_physical{13.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}=0x1 + +phy_chain_tx_lane_map_physical{21.0}=0x3210 +phy_chain_tx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_rx_lane_map_physical{21.0}=0x3210 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +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}=0x1 + +phy_chain_tx_lane_map_physical{29.0}=0x3210 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_lane_map_physical{29.0}=0x3210 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_rx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_rx_polarity_flip_physical{32.0}=0x0 + +phy_chain_tx_lane_map_physical{33.0}=0x3210 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_tx_polarity_flip_physical{35.0}=0x0 +phy_chain_tx_polarity_flip_physical{36.0}=0x0 +phy_chain_rx_lane_map_physical{33.0}=0x3210 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=0x1 +phy_chain_rx_polarity_flip_physical{35.0}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x1 + +phy_chain_tx_lane_map_physical{41.0}=0x3210 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_lane_map_physical{41.0}=0x3210 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x1 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x1 + +phy_chain_tx_lane_map_physical{49.0}=0x3210 +phy_chain_tx_polarity_flip_physical{49.0}=0x1 +phy_chain_tx_polarity_flip_physical{50.0}=0x1 +phy_chain_tx_polarity_flip_physical{51.0}=0x1 +phy_chain_tx_polarity_flip_physical{52.0}=0x1 +phy_chain_rx_lane_map_physical{49.0}=0x3210 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{50.0}=0x0 +phy_chain_rx_polarity_flip_physical{51.0}=0x1 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 + +phy_chain_tx_lane_map_physical{57.0}=0x3210 +phy_chain_tx_polarity_flip_physical{57.0}=0x1 +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_rx_lane_map_physical{57.0}=0x3210 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x1 +phy_chain_rx_polarity_flip_physical{59.0}=0x1 +phy_chain_rx_polarity_flip_physical{60.0}=0x1 + +phy_chain_tx_lane_map_physical{61.0}=0x3210 +phy_chain_tx_polarity_flip_physical{61.0}=0x1 +phy_chain_tx_polarity_flip_physical{62.0}=0x1 +phy_chain_tx_polarity_flip_physical{63.0}=0x1 +phy_chain_tx_polarity_flip_physical{64.0}=0x1 +phy_chain_rx_lane_map_physical{61.0}=0x3210 +phy_chain_rx_polarity_flip_physical{61.0}=0x1 +phy_chain_rx_polarity_flip_physical{62.0}=0x0 +phy_chain_rx_polarity_flip_physical{63.0}=0x1 +phy_chain_rx_polarity_flip_physical{64.0}=0x0 + +phy_chain_tx_lane_map_physical{65.0}=0x0123 +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_rx_lane_map_physical{65.0}=0x0321 +phy_chain_rx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{67.0}=0x1 +phy_chain_rx_polarity_flip_physical{68.0}=0x0 + +phy_chain_tx_lane_map_physical{69.0}=0x3120 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_tx_polarity_flip_physical{70.0}=0x1 +phy_chain_tx_polarity_flip_physical{71.0}=0x1 +phy_chain_tx_polarity_flip_physical{72.0}=0x1 +phy_chain_rx_lane_map_physical{69.0}=0x0123 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{70.0}=0x1 +phy_chain_rx_polarity_flip_physical{71.0}=0x0 +phy_chain_rx_polarity_flip_physical{72.0}=0x0 + +phy_chain_tx_lane_map_physical{77.0}=0x2130 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +phy_chain_tx_polarity_flip_physical{79.0}=0x0 +phy_chain_tx_polarity_flip_physical{80.0}=0x0 +phy_chain_rx_lane_map_physical{77.0}=0x3102 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{78.0}=0x1 +phy_chain_rx_polarity_flip_physical{79.0}=0x0 +phy_chain_rx_polarity_flip_physical{80.0}=0x0 + +phy_chain_tx_lane_map_physical{85.0}=0x3210 +phy_chain_tx_polarity_flip_physical{85.0}=0x1 +phy_chain_tx_polarity_flip_physical{86.0}=0x1 +phy_chain_tx_polarity_flip_physical{87.0}=0x0 +phy_chain_tx_polarity_flip_physical{88.0}=0x1 +phy_chain_rx_lane_map_physical{85.0}=0x3210 +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_tx_lane_map_physical{93.0}=0x3210 +phy_chain_tx_polarity_flip_physical{93.0}=0x0 +phy_chain_tx_polarity_flip_physical{94.0}=0x1 +phy_chain_tx_polarity_flip_physical{95.0}=0x0 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 +phy_chain_rx_lane_map_physical{93.0}=0x3210 +phy_chain_rx_polarity_flip_physical{93.0}=0x1 +phy_chain_rx_polarity_flip_physical{94.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 + +phy_chain_tx_lane_map_physical{97.0}=0x0312 +phy_chain_tx_polarity_flip_physical{97.0}=0x0 +phy_chain_tx_polarity_flip_physical{98.0}=0x0 +phy_chain_tx_polarity_flip_physical{99.0}=0x1 +phy_chain_tx_polarity_flip_physical{100.0}=0x1 +phy_chain_rx_lane_map_physical{97.0}=0x1023 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +phy_chain_rx_polarity_flip_physical{98.0}=0x0 +phy_chain_rx_polarity_flip_physical{99.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 + +phy_chain_tx_lane_map_physical{105.0}=0x0123 +phy_chain_tx_polarity_flip_physical{105.0}=0x0 +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_rx_lane_map_physical{105.0}=0x0321 +phy_chain_rx_polarity_flip_physical{105.0}=0x0 +phy_chain_rx_polarity_flip_physical{106.0}=0x1 +phy_chain_rx_polarity_flip_physical{107.0}=0x0 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 + +phy_chain_tx_lane_map_physical{113.0}=0x3120 +phy_chain_tx_polarity_flip_physical{113.0}=0x1 +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_rx_lane_map_physical{113.0}=0x1023 +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}=0x1 +phy_chain_rx_polarity_flip_physical{116.0}=0x0 + +phy_chain_tx_lane_map_physical{121.0}=0x0132 +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x1 +phy_chain_tx_polarity_flip_physical{123.0}=0x0 +phy_chain_tx_polarity_flip_physical{124.0}=0x0 +phy_chain_rx_lane_map_physical{121.0}=0x0321 +phy_chain_rx_polarity_flip_physical{121.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x1 +phy_chain_rx_polarity_flip_physical{123.0}=0x0 +phy_chain_rx_polarity_flip_physical{124.0}=0x1 + +phy_chain_tx_lane_map_physical{125.0}=0x0213 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x0 +phy_chain_tx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x1 +phy_chain_rx_lane_map_physical{125.0}=0x0321 +phy_chain_rx_polarity_flip_physical{125.0}=0x1 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 + +### MerlinCore +phy_chain_tx_lane_map_physical{129.0}=0x3210 +phy_chain_tx_polarity_flip_physical{129.0}=0x0 +phy_chain_tx_polarity_flip_physical{130.0}=0x1 +phy_chain_tx_polarity_flip_physical{131.0}=0x1 +phy_chain_tx_polarity_flip_physical{132.0}=0x1 +phy_chain_rx_lane_map_physical{129.0}=0x3210 +phy_chain_rx_polarity_flip_physical{129.0}=0x0 +phy_chain_rx_polarity_flip_physical{130.0}=0x0 +phy_chain_rx_polarity_flip_physical{131.0}=0x0 +phy_chain_rx_polarity_flip_physical{132.0}=0x0 + diff --git a/device/quanta/x86_64-quanta_ix8c_bwde-r0/default_sku b/device/quanta/x86_64-quanta_ix8c_bwde-r0/default_sku new file mode 100644 index 000000000000..58415770bc61 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8c_bwde-r0/default_sku @@ -0,0 +1 @@ +Quanta-IX8C-56X t1 diff --git a/device/quanta/x86_64-quanta_ix8c_bwde-r0/installer.conf b/device/quanta/x86_64-quanta_ix8c_bwde-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8c_bwde-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/quanta/x86_64-quanta_ix8c_bwde-r0/led_proc_init.soc b/device/quanta/x86_64-quanta_ix8c_bwde-r0/led_proc_init.soc new file mode 100644 index 000000000000..0861486660c3 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8c_bwde-r0/led_proc_init.soc @@ -0,0 +1,6 @@ +sleep 10 +led stop +sleep 3 +led start +sleep 3 +led auto on \ No newline at end of file diff --git a/device/quanta/x86_64-quanta_ix8c_bwde-r0/plugins/eeprom.py b/device/quanta/x86_64-quanta_ix8c_bwde-r0/plugins/eeprom.py new file mode 100644 index 000000000000..fa34110c04ea --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8c_bwde-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/18-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/quanta/x86_64-quanta_ix8c_bwde-r0/plugins/psuutil.py b/device/quanta/x86_64-quanta_ix8c_bwde-r0/plugins/psuutil.py new file mode 100644 index 000000000000..319c35d490e4 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8c_bwde-r0/plugins/psuutil.py @@ -0,0 +1,50 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + 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 = 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 = 1 + + return status diff --git a/device/quanta/x86_64-quanta_ix8c_bwde-r0/plugins/sfputil.py b/device/quanta/x86_64-quanta_ix8c_bwde-r0/plugins/sfputil.py new file mode 100644 index 000000000000..3067919795d5 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix8c_bwde-r0/plugins/sfputil.py @@ -0,0 +1,217 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import string + from ctypes import create_string_buffer + 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 = 56 + PORTS_IN_BLOCK = 56 + QSFP_PORT_START = 49 + QSFP_PORT_END = 56 + + _port_to_eeprom_mapping = {} + _port_to_i2c_mapping = { + 1: 32, + 2: 33, + 3: 34, + 4: 35, + 5: 36, + 6: 37, + 7: 38, + 8: 39, + 9: 40, + 10: 41, + 11: 42, + 12: 43, + 13: 44, + 14: 45, + 15: 46, + 16: 47, + 17: 48, + 18: 49, + 19: 50, + 20: 51, + 21: 52, + 22: 53, + 23: 54, + 24: 55, + 25: 56, + 26: 57, + 27: 58, + 28: 59, + 29: 60, + 30: 61, + 31: 62, + 32: 63, + 33: 64, + 34: 65, + 35: 66, + 36: 67, + 37: 68, + 38: 69, + 39: 70, + 40: 71, + 41: 72, + 42: 73, + 43: 74, + 44: 75, + 45: 76, + 46: 77, + 47: 78, + 48: 79, + 49: 80, # QSFP49 + 50: 81, # QSFP50 + 51: 82, # QSFP51 + 52: 83, # QSFP52 + 53: 84, # QSFP53 + 54: 85, # QSFP54 + 55: 86, # QSFP55 + 56: 87, # QSFP56 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_port_start(self): + return self.QSFP_PORT_START + + @property + def qsfp_port_end(self): + return self.QSFP_PORT_END + + @property + def qsfp_ports(self): + return list(range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self.port_start, self.port_end+1): + self.port_to_eeprom_mapping[x] = eeprom_path.format(self._port_to_i2c_mapping[x]) + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + if port_num < self.qsfp_port_start: + reg_file = open("/sys/class/cpld-sfp28/port-"+str(port_num)+"/pre_n") + else: + reg_file = open("/sys/class/gpio/gpio"+str((port_num-self.qsfp_port_start)*4+34)+"/value") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_file.readline().rstrip() + if port_num < self.qsfp_port_start: + if reg_value == '1': + return True + else: + if reg_value == '0': + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end: + return False + + try: + reg_file = open("/sys/class/gpio/gpio"+str((port_num-self.qsfp_port_start)*4+35)+"/value") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + 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.qsfp_port_end: + return False + + try: + reg_file = open("/sys/class/gpio/gpio"+str((port_num-self.qsfp_port_start)*4+35)+"/value", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.qsfp_port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/gpio/gpio"+str((port_num-self.qsfp_port_start)*4+32)+"/value", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open("/sys/class/gpio/gpio"+str((port_num-self.qsfp_port_start)*4+32)+"/value", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + 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 diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/port_config.ini b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/port_config.ini new file mode 100644 index 000000000000..8f770329437f --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias index +Ethernet0 33,34,35,36,37,38,39,40 fourhundredGigE1 0 +Ethernet4 25,26,27,28,29,30,31,32 fourhundredGigE2 1 +Ethernet8 49,50,51,52,53,54,55,56 fourhundredGigE3 2 +Ethernet12 57,58,59,60,61,62,63,64 fourhundredGigE4 3 +Ethernet16 65,66,67,68,69,70,71,72 fourhundredGigE5 4 +Ethernet20 73,74,75,76,77,78,79,80 fourhundredGigE6 5 +Ethernet24 81,82,83,84,85,86,87,88 fourhundredGigE7 6 +Ethernet28 89,90,91,92,93,94,95,96 fourhundredGigE8 7 +Ethernet32 17,18,19,20,21,22,23,24 fourhundredGigE9 8 +Ethernet36 97,98,99,100,101,102,103,104 fourhundredGigE10 9 +Ethernet40 9,10,11,12,13,14,15,16 fourhundredGigE11 10 +Ethernet44 41,42,43,44,45,46,47,48 fourhundredGigE12 11 +Ethernet48 113,114,115,116,117,118,119,120 fourhundredGigE13 12 +Ethernet52 105,106,107,108,109,110,111,112 fourhundredGigE14 13 +Ethernet56 121,122,123,124,125,126,127,128 fourhundredGigE15 14 +Ethernet60 1,2,3,4,5,6,7,8 fourhundredGigE16 15 +Ethernet64 137,138,139,140,141,142,143,144 fourhundredGigE17 16 +Ethernet68 129,130,131,132,133,134,135,136 fourhundredGigE18 17 +Ethernet72 241,242,243,244,245,246,247,248 fourhundredGigE19 18 +Ethernet76 249,250,251,252,253,254,255,256 fourhundredGigE20 19 +Ethernet80 225,226,227,228,229,230,231,232 fourhundredGigE21 20 +Ethernet84 145,146,147,148,149,150,151,152 fourhundredGigE22 21 +Ethernet88 153,154,155,156,157,158,159,160 fourhundredGigE23 22 +Ethernet92 233,234,235,236,237,238,239,240 fourhundredGigE24 23 +Ethernet96 161,162,163,164,165,166,167,168 fourhundredGigE25 24 +Ethernet100 169,170,171,172,173,174,175,176 fourhundredGigE26 25 +Ethernet104 177,178,179,180,181,182,183,184 fourhundredGigE27 26 +Ethernet108 185,186,187,188,189,190,191,192 fourhundredGigE28 27 +Ethernet112 193,194,195,196,197,198,199,200 fourhundredGigE29 28 +Ethernet116 201,202,203,204,205,206,207,208 fourhundredGigE30 29 +Ethernet120 209,210,211,212,213,214,215,216 fourhundredGigE31 30 +Ethernet124 217,218,219,220,221,222,223,224 fourhundredGigE32 31 diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/sai.profile b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/sai.profile new file mode 100644 index 000000000000..70397851c909 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-ix9-32x400G.config.bcm +SAI_NUM_ECMP_MEMBERS=64 diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/th3-ix9-32x400G.config.bcm b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/th3-ix9-32x400G.config.bcm new file mode 100644 index 000000000000..704183e10924 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/Quanta-IX9-32X/th3-ix9-32x400G.config.bcm @@ -0,0 +1,341 @@ +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 + +init_all_modules=0 +core_clock_frequency=1325 +dpr_clock_frequency=1000 +device_clock_frequency=1325 + +load_firmware=0x2 +port_flex_enable=1 + +# portmap settings +pbmp_xport_xe=0x111101111411110111101111011114111102222 + +portmap_1=1:400 +portmap_5=9:400 +portmap_9=17:400 +portmap_13=25:400 +portmap_20=33:400 +portmap_24=41:400 +portmap_28=49:400 +portmap_32=57:400 + +portmap_40=65:400 +portmap_44=73:400 +portmap_48=81:400 +portmap_52=89:400 +portmap_60=97:400 +portmap_64=105:400 +portmap_68=113:400 +portmap_72=121:400 + +portmap_80=129:400 +portmap_84=137:400 +portmap_88=145:400 +portmap_92=153:400 +portmap_100=161:400 +portmap_104=169:400 +portmap_108=177:400 +portmap_112=185:400 + +portmap_120=193:400 +portmap_124=201:400 +portmap_128=209:400 +portmap_132=217:400 +portmap_140=225:400 +portmap_144=233:400 +portmap_148=241:400 +portmap_152=249:400 + +# datapath port +portmap_38=257:10 +portmap_118=258:10 + +# loopback port +portmap_19=260:10 +portmap_39=260:10 +portmap_59=261:10 +portmap_79=262:10 +portmap_99=263:10 +portmap_119=264:10 +portmap_139=265:10 +portmap_159=266:10 + +# port order remap +dport_map_port_20=1 +dport_map_port_13=2 +dport_map_port_28=3 +dport_map_port_32=4 +dport_map_port_40=5 +dport_map_port_44=6 +dport_map_port_48=7 +dport_map_port_52=8 +dport_map_port_9=9 +dport_map_port_60=10 +dport_map_port_5=11 +dport_map_port_24=12 +dport_map_port_68=13 +dport_map_port_64=14 +dport_map_port_72=15 +dport_map_port_1=16 + +dport_map_port_84=17 +dport_map_port_80=18 +dport_map_port_148=19 +dport_map_port_152=20 +dport_map_port_140=21 +dport_map_port_88=22 +dport_map_port_92=23 +dport_map_port_144=24 +dport_map_port_100=25 +dport_map_port_104=26 +dport_map_port_108=27 +dport_map_port_112=28 +dport_map_port_120=29 +dport_map_port_124=30 +dport_map_port_128=31 +dport_map_port_132=32 + +dport_map_port_38=33 +dport_map_port_118=34 + +### lane swap and polarity follow front port order ### +phy_chain_tx_lane_map_physical{33.0}=0x75206431 +serdes_core_tx_polarity_flip_physical{33}=0xdb +phy_chain_rx_lane_map_physical{33.0}=0x13572064 +serdes_core_rx_polarity_flip_physical{33}=0x69 + +phy_chain_tx_lane_map_physical{25.0}=0x75314206 +serdes_core_tx_polarity_flip_physical{25}=0xe8 +phy_chain_rx_lane_map_physical{25.0}=0x67103524 +serdes_core_rx_polarity_flip_physical{25}=0x7c + +phy_chain_tx_lane_map_physical{49.0}=0x57326014 +serdes_core_tx_polarity_flip_physical{49}=0x0e +phy_chain_rx_lane_map_physical{49.0}=0x21463057 +serdes_core_rx_polarity_flip_physical{49}=0xd2 + +phy_chain_tx_lane_map_physical{57.0}=0x12307564 +serdes_core_tx_polarity_flip_physical{57}=0xa6 +phy_chain_rx_lane_map_physical{57.0}=0x57460231 +serdes_core_rx_polarity_flip_physical{57}=0x99 + +phy_chain_tx_lane_map_physical{65.0}=0x60345721 +serdes_core_tx_polarity_flip_physical{65}=0xe2 +phy_chain_rx_lane_map_physical{65.0}=0x40675123 +serdes_core_rx_polarity_flip_physical{65}=0x0f + +phy_chain_tx_lane_map_physical{73.0}=0x21306574 +serdes_core_tx_polarity_flip_physical{73}=0xa4 +phy_chain_rx_lane_map_physical{73.0}=0x67451302 +serdes_core_rx_polarity_flip_physical{73}=0x06 + +phy_chain_tx_lane_map_physical{81.0}=0x65210347 +serdes_core_tx_polarity_flip_physical{81}=0xe2 +phy_chain_rx_lane_map_physical{81.0}=0x10675423 +serdes_core_rx_polarity_flip_physical{81}=0x0f + +phy_chain_tx_lane_map_physical{89.0}=0x41236570 +serdes_core_tx_polarity_flip_physical{89}=0x8d +phy_chain_rx_lane_map_physical{89.0}=0x45672031 +serdes_core_rx_polarity_flip_physical{89}=0x63 + +phy_chain_tx_lane_map_physical{17.0}=0x76312504 +serdes_core_tx_polarity_flip_physical{17}=0x8e +phy_chain_rx_lane_map_physical{17.0}=0x75126403 +serdes_core_rx_polarity_flip_physical{17}=0x2d + +phy_chain_tx_lane_map_physical{97.0}=0x31025764 +serdes_core_tx_polarity_flip_physical{97}=0x3c +phy_chain_rx_lane_map_physical{97.0}=0x52136470 +serdes_core_rx_polarity_flip_physical{97}=0x9c + +phy_chain_tx_lane_map_physical{9.0}=0x57326014 +serdes_core_tx_polarity_flip_physical{9}=0x3d +phy_chain_rx_lane_map_physical{9.0}=0x31452076 +serdes_core_rx_polarity_flip_physical{9}=0x1e + +phy_chain_tx_lane_map_physical{41.0}=0x03215764 +serdes_core_tx_polarity_flip_physical{41}=0x3c +phy_chain_rx_lane_map_physical{41.0}=0x54671302 +serdes_core_rx_polarity_flip_physical{41}=0x99 + +phy_chain_tx_lane_map_physical{113.0}=0x60175243 +serdes_core_tx_polarity_flip_physical{113}=0xcd +phy_chain_rx_lane_map_physical{113.0}=0x20473156 +serdes_core_rx_polarity_flip_physical{113}=0x87 + +phy_chain_tx_lane_map_physical{105.0}=0x65034721 +serdes_core_tx_polarity_flip_physical{105}=0xe6 +phy_chain_rx_lane_map_physical{105.0}=0x04157263 +serdes_core_rx_polarity_flip_physical{105}=0x4c + +phy_chain_tx_lane_map_physical{121.0}=0x16435072 +serdes_core_tx_polarity_flip_physical{121}=0xae +phy_chain_rx_lane_map_physical{121.0}=0x13560247 +serdes_core_rx_polarity_flip_physical{121}=0x2d + +phy_chain_tx_lane_map_physical{1.0}=0x34650172 +serdes_core_tx_polarity_flip_physical{1}=0xff +phy_chain_rx_lane_map_physical{1.0}=0x13026457 +serdes_core_rx_polarity_flip_physical{1}=0x99 + +phy_chain_tx_lane_map_physical{137.0}=0x02673451 +serdes_core_tx_polarity_flip_physical{137}=0x25 +phy_chain_rx_lane_map_physical{137.0}=0x14730562 +serdes_core_rx_polarity_flip_physical{137}=0x86 + +phy_chain_tx_lane_map_physical{129.0}=0x12304675 +serdes_core_tx_polarity_flip_physical{129}=0x49 +phy_chain_rx_lane_map_physical{129.0}=0x76453021 +serdes_core_rx_polarity_flip_physical{129}=0xc3 + +phy_chain_tx_lane_map_physical{241.0}=0x31462075 +serdes_core_tx_polarity_flip_physical{241}=0xf5 +phy_chain_rx_lane_map_physical{241.0}=0x47315602 +serdes_core_rx_polarity_flip_physical{241}=0xe1 + +phy_chain_tx_lane_map_physical{249.0}=0x13206547 +serdes_core_tx_polarity_flip_physical{249}=0x27 +phy_chain_rx_lane_map_physical{249.0}=0x64750312 +serdes_core_rx_polarity_flip_physical{249}=0xbd + +phy_chain_tx_lane_map_physical{225.0}=0x60315742 +serdes_core_tx_polarity_flip_physical{225}=0x44 +phy_chain_rx_lane_map_physical{225.0}=0x01546372 +serdes_core_rx_polarity_flip_physical{225}=0xc3 + +phy_chain_tx_lane_map_physical{145.0}=0x51374602 +serdes_core_tx_polarity_flip_physical{145}=0x5f +phy_chain_rx_lane_map_physical{145.0}=0x23106754 +serdes_core_rx_polarity_flip_physical{145}=0xbc + +phy_chain_tx_lane_map_physical{153.0}=0x05163742 +serdes_core_tx_polarity_flip_physical{153}=0x0f +phy_chain_rx_lane_map_physical{153.0}=0x67102354 +serdes_core_rx_polarity_flip_physical{153}=0xf0 + +phy_chain_tx_lane_map_physical{233.0}=0x20134576 +serdes_core_tx_polarity_flip_physical{233}=0x07 +phy_chain_rx_lane_map_physical{233.0}=0x23107465 +serdes_core_rx_polarity_flip_physical{233}=0xe6 + +phy_chain_tx_lane_map_physical{161.0}=0x53246710 +serdes_core_tx_polarity_flip_physical{161}=0x0f +phy_chain_rx_lane_map_physical{161.0}=0x03471265 +serdes_core_rx_polarity_flip_physical{161}=0xc0 + +phy_chain_tx_lane_map_physical{169.0}=0x20137654 +serdes_core_tx_polarity_flip_physical{169}=0x8a +phy_chain_rx_lane_map_physical{169.0}=0x27360415 +serdes_core_rx_polarity_flip_physical{169}=0x9c + +phy_chain_tx_lane_map_physical{177.0}=0x50346712 +serdes_core_tx_polarity_flip_physical{177}=0x4f +phy_chain_rx_lane_map_physical{177.0}=0x13460257 +serdes_core_rx_polarity_flip_physical{177}=0x5a + +phy_chain_tx_lane_map_physical{185.0}=0x12305674 +serdes_core_tx_polarity_flip_physical{185}=0xba +phy_chain_rx_lane_map_physical{185.0}=0x57460123 +serdes_core_rx_polarity_flip_physical{185}=0x9f + +phy_chain_tx_lane_map_physical{193.0}=0x50346712 +serdes_core_tx_polarity_flip_physical{193}=0x4f +phy_chain_rx_lane_map_physical{193.0}=0x13750264 +serdes_core_rx_polarity_flip_physical{193}=0x69 + +phy_chain_tx_lane_map_physical{201.0}=0x12305674 +serdes_core_tx_polarity_flip_physical{201}=0xba +phy_chain_rx_lane_map_physical{201.0}=0x57460123 +serdes_core_rx_polarity_flip_physical{201}=0x9f + +phy_chain_tx_lane_map_physical{209.0}=0x50346712 +serdes_core_tx_polarity_flip_physical{209}=0x4f +phy_chain_rx_lane_map_physical{209.0}=0x13460275 +serdes_core_rx_polarity_flip_physical{209}=0x5a + +phy_chain_tx_lane_map_physical{217.0}=0x31205674 +serdes_core_tx_polarity_flip_physical{217}=0x5a +phy_chain_rx_lane_map_physical{217.0}=0x67541203 +serdes_core_rx_polarity_flip_physical{217}=0x33 + + +port_fec_20=9 +port_fec_13=9 +port_fec_28=9 +port_fec_32=9 +port_fec_40=9 +port_fec_44=9 +port_fec_48=9 +port_fec_52=9 +port_fec_9=9 +port_fec_60=9 +port_fec_5=9 +port_fec_24=9 +port_fec_68=9 +port_fec_64=9 +port_fec_72=9 +port_fec_1=9 + +port_fec_84=9 +port_fec_80=9 +port_fec_148=9 +port_fec_152=9 +port_fec_140=9 +port_fec_88=9 +port_fec_92=9 +port_fec_144=9 +port_fec_100=9 +port_fec_104=9 +port_fec_108=9 +port_fec_112=9 +port_fec_120=9 +port_fec_124=9 +port_fec_128=9 +port_fec_132=9 + + +port_init_cl72_20=1 +port_init_cl72_13=1 +port_init_cl72_28=1 +port_init_cl72_32=1 +port_init_cl72_40=1 +port_init_cl72_44=1 +port_init_cl72_48=1 +port_init_cl72_52=1 +port_init_cl72_9=1 +port_init_cl72_60=1 +port_init_cl72_5=1 +port_init_cl72_24=1 +port_init_cl72_68=1 +port_init_cl72_64=1 +port_init_cl72_72=1 +port_init_cl72_1=1 + +port_init_cl72_84=1 +port_init_cl72_80=1 +port_init_cl72_148=1 +port_init_cl72_152=1 +port_init_cl72_140=1 +port_init_cl72_88=1 +port_init_cl72_92=1 +port_init_cl72_144=1 +port_init_cl72_100=1 +port_init_cl72_104=1 +port_init_cl72_108=1 +port_init_cl72_112=1 +port_init_cl72_120=1 +port_init_cl72_124=1 +port_init_cl72_128=1 +port_init_cl72_132=1 + + diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/default_sku b/device/quanta/x86_64-quanta_ix9_bwde-r0/default_sku new file mode 100644 index 000000000000..0ca35bb0074e --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/default_sku @@ -0,0 +1 @@ +Quanta-IX9-32X t1 diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/installer.conf b/device/quanta/x86_64-quanta_ix9_bwde-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/led_proc_init.soc b/device/quanta/x86_64-quanta_ix9_bwde-r0/led_proc_init.soc new file mode 100644 index 000000000000..adff95218e4f --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/led_proc_init.soc @@ -0,0 +1,2 @@ +sleep 10 +led auto on diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/eeprom.py b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/eeprom.py new file mode 100644 index 000000000000..fa34110c04ea --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/eeprom.py @@ -0,0 +1,20 @@ +try: + 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 as 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/18-0054/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/psuutil.py b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/psuutil.py new file mode 100644 index 000000000000..5cf06fb5d66a --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/psuutil.py @@ -0,0 +1,50 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + 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 = 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 = 1 + + return status diff --git a/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/sfputil.py b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/sfputil.py new file mode 100644 index 000000000000..832dac4e0570 --- /dev/null +++ b/device/quanta/x86_64-quanta_ix9_bwde-r0/plugins/sfputil.py @@ -0,0 +1,172 @@ +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class SfpUtil(SfpUtilBase): + """Platform specific SfpUtill class""" + + _port_start = 0 + _port_end = 31 + ports_in_block = 32 + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 1: 32, + 2: 33, + 3: 34, + 4: 35, + 5: 36, + 6: 37, + 7: 38, + 8: 39, + 9: 40, + 10: 41, + 11: 42, + 12: 43, + 13: 44, + 14: 45, + 15: 46, + 16: 47, + 17: 48, + 18: 49, + 19: 50, + 20: 51, + 21: 52, + 22: 53, + 23: 54, + 24: 55, + 25: 56, + 26: 57, + 27: 58, + 28: 59, + 29: 60, + 30: 61, + 31: 62, + 32: 63, + } + + _qsfp_ports = list(range(0, ports_in_block + 1)) + + def __init__(self): + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(0, self._port_end + 1): + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x+1]) + self._port_to_eeprom_mapping[x] = port_eeprom_path + 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 + + try: + reg_file = open("/sys/class/cpld-qsfpdd/port-"+str(port_num+1)+"/reset", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open("/sys/class/cpld-qsfpdd/port-"+str(port_num+1)+"/reset", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfpdd/port-"+str(port_num+1)+"/lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + reg_file = open("/sys/class/cpld-qsfpdd/port-"+str(port_num+1)+"/lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if reg_value == 0: + return False + + return True + + 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 + + try: + reg_file = open("/sys/class/cpld-qsfpdd/port-"+str(port_num+1)+"/module_present") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_file.readline().rstrip() + if reg_value == '1': + return True + + return False + + @property + def port_start(self): + return self._port_start + + @property + def port_end(self): + return self._port_end + + @property + def qsfp_ports(self): + return list(range(0, self.ports_in_block + 1)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + 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 diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/port_config.ini b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/port_config.ini new file mode 100755 index 000000000000..823f53160c33 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/port_config.ini @@ -0,0 +1,57 @@ +# name lanes alias index speed admin_status +Ethernet1 1 twentyfiveGigE0/1 0 25000 up +Ethernet2 2 twentyfiveGigE0/2 1 25000 up +Ethernet3 3 twentyfiveGigE0/3 2 25000 up +Ethernet4 4 twentyfiveGigE0/4 3 25000 up +Ethernet5 5 twentyfiveGigE0/5 4 25000 up +Ethernet6 6 twentyfiveGigE0/6 5 25000 up +Ethernet7 7 twentyfiveGigE0/7 6 25000 up +Ethernet8 8 twentyfiveGigE0/8 7 25000 up +Ethernet9 13 twentyfiveGigE0/9 8 25000 up +Ethernet10 14 twentyfiveGigE0/10 9 25000 up +Ethernet11 15 twentyfiveGigE0/11 10 25000 up +Ethernet12 16 twentyfiveGigE0/12 11 25000 up +Ethernet13 21 twentyfiveGigE0/13 12 25000 up +Ethernet14 22 twentyfiveGigE0/14 13 25000 up +Ethernet15 23 twentyfiveGigE0/15 14 25000 up +Ethernet16 24 twentyfiveGigE0/16 15 25000 up +Ethernet17 29 twentyfiveGigE0/17 16 25000 up +Ethernet18 30 twentyfiveGigE0/18 17 25000 up +Ethernet19 31 twentyfiveGigE0/19 18 25000 up +Ethernet20 32 twentyfiveGigE0/20 19 25000 up +Ethernet21 33 twentyfiveGigE0/21 20 25000 up +Ethernet22 34 twentyfiveGigE0/22 21 25000 up +Ethernet23 35 twentyfiveGigE0/23 22 25000 up +Ethernet24 36 twentyfiveGigE0/24 23 25000 up +Ethernet25 41 twentyfiveGigE0/25 24 25000 up +Ethernet26 42 twentyfiveGigE0/26 25 25000 up +Ethernet27 43 twentyfiveGigE0/27 26 25000 up +Ethernet28 44 twentyfiveGigE0/28 27 25000 up +Ethernet29 49 twentyfiveGigE0/29 28 25000 up +Ethernet30 50 twentyfiveGigE0/30 29 25000 up +Ethernet31 51 twentyfiveGigE0/31 30 25000 up +Ethernet32 52 twentyfiveGigE0/32 31 25000 up +Ethernet33 57 twentyfiveGigE0/33 32 25000 up +Ethernet34 58 twentyfiveGigE0/34 33 25000 up +Ethernet35 59 twentyfiveGigE0/35 34 25000 up +Ethernet36 60 twentyfiveGigE0/36 35 25000 up +Ethernet37 61 twentyfiveGigE0/37 36 25000 up +Ethernet38 62 twentyfiveGigE0/38 37 25000 up +Ethernet39 63 twentyfiveGigE0/39 38 25000 up +Ethernet40 64 twentyfiveGigE0/40 39 25000 up +Ethernet41 65 twentyfiveGigE0/41 40 25000 up +Ethernet42 66 twentyfiveGigE0/42 41 25000 up +Ethernet43 67 twentyfiveGigE0/43 42 25000 up +Ethernet44 68 twentyfiveGigE0/44 43 25000 up +Ethernet45 69 twentyfiveGigE0/45 44 25000 up +Ethernet46 70 twentyfiveGigE0/46 45 25000 up +Ethernet47 71 twentyfiveGigE0/47 46 25000 up +Ethernet48 72 twentyfiveGigE0/48 47 25000 up +Ethernet49 85,86,87,88 hundredGigE0/1 48 100000 up +Ethernet50 77,78,79,80 hundredGigE0/2 49 100000 up +Ethernet51 97,98,99,100 hundredGigE0/3 50 100000 up +Ethernet52 93,94,95,96 hundredGigE0/4 51 100000 up +Ethernet53 113,114,115,116 hundredGigE0/5 52 100000 up +Ethernet54 105,106,107,108 hundredGigE0/6 53 100000 up +Ethernet55 121,122,123,124 hundredGigE0/7 54 100000 up +Ethernet56 125,126,127,128 hundredGigE0/8 55 100000 up diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/sai.profile b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/sai.profile new file mode 100755 index 000000000000..042c8060d587 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-b6510-48vs8cq-48x25G+8x100G.config.bcm diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/td3-b6510-48vs8cq-48x25G+8x100G.config.bcm b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/td3-b6510-48vs8cq-48x25G+8x100G.config.bcm new file mode 100644 index 000000000000..69fd8c362987 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/B6510-48VS8CQ/td3-b6510-48vs8cq-48x25G+8x100G.config.bcm @@ -0,0 +1,569 @@ +l2_mem_entries=32768 +l2xmsg_mode=0 +l3_max_ecmp_mode=1 +l3_mem_entries=49152 +l3_alpm_enable=0 +bcm_num_cos=8 +bcm_stat_interval=2000000 +cdma_timeout_usec=3000000 +core_clock_frequency=1525 +dpp_clock_ratio=2:3 +help_cli_enable=1 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +#lpm_scaling_enable=1 +max_vp_lags=0 +mem_cache_enable=0 +memlist_enable=1 +miim_intr_enable=0 +module_64ports=1 +oversubscribe_mode=1 +parity_enable=1 +pbmp_gport_stack.0=0x0000000000000000000000000000000000000000000000000000000000000000 +#pbmp_xport_xe.0=0x00000000000000000000000000000000888ffffffffffff9fffffffffffffffe +pbmp_xport_xe=0x488080808808087f9fe1e1e1fe1e1e1fe +phy_chain_rx_lane_map_physical{1.0}=0x1032 +phy_chain_tx_lane_map_physical{1.0}=0x0123 +phy_chain_rx_lane_map_physical{5.0}=0x1032 +phy_chain_tx_lane_map_physical{5.0}=0x0123 +phy_chain_rx_lane_map_physical{13.0}=0x1032 +phy_chain_tx_lane_map_physical{13.0}=0x0123 +phy_chain_rx_lane_map_physical{21.0}=0x1032 +phy_chain_tx_lane_map_physical{21.0}=0x0123 +phy_chain_rx_lane_map_physical{29.0}=0x1032 +phy_chain_tx_lane_map_physical{29.0}=0x0123 +phy_chain_rx_lane_map_physical{33.0}=0x1032 +phy_chain_tx_lane_map_physical{33.0}=0x0123 +phy_chain_rx_lane_map_physical{41.0}=0x1032 +phy_chain_tx_lane_map_physical{41.0}=0x0123 +phy_chain_rx_lane_map_physical{49.0}=0x1032 +phy_chain_tx_lane_map_physical{49.0}=0x0123 +phy_chain_rx_lane_map_physical{57.0}=0x1032 +phy_chain_tx_lane_map_physical{57.0}=0x0123 +phy_chain_rx_lane_map_physical{61.0}=0x1032 +phy_chain_tx_lane_map_physical{61.0}=0x0123 +phy_chain_rx_lane_map_physical{65.0}=0x2301 +phy_chain_tx_lane_map_physical{65.0}=0x3210 +phy_chain_rx_lane_map_physical{69.0}=0x2301 +phy_chain_tx_lane_map_physical{69.0}=0x3210 +phy_chain_rx_lane_map_physical{77.0}=0x1032 +phy_chain_tx_lane_map_physical{77.0}=0x3210 +phy_chain_rx_lane_map_physical{85.0}=0x1032 +phy_chain_tx_lane_map_physical{85.0}=0x3210 +phy_chain_rx_lane_map_physical{93.0}=0x1032 +phy_chain_tx_lane_map_physical{93.0}=0x3210 +phy_chain_rx_lane_map_physical{97.0}=0x1032 +phy_chain_tx_lane_map_physical{97.0}=0x3210 +phy_chain_rx_lane_map_physical{105.0}=0x1032 +phy_chain_tx_lane_map_physical{105.0}=0x3210 +phy_chain_rx_lane_map_physical{113.0}=0x1032 +phy_chain_tx_lane_map_physical{113.0}=0x3210 +phy_chain_rx_lane_map_physical{121.0}=0x2031 +phy_chain_tx_lane_map_physical{121.0}=0x3210 +phy_chain_rx_lane_map_physical{125.0}=0x1032 +phy_chain_tx_lane_map_physical{125.0}=0x1203 +phy_chain_tx_polarity_flip_physical{1.0}=0x1 +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}=0x0 +phy_chain_tx_polarity_flip_physical{3.0}=0x1 +phy_chain_rx_polarity_flip_physical{3.0}=0x0 +phy_chain_tx_polarity_flip_physical{4.0}=0x0 +phy_chain_rx_polarity_flip_physical{4.0}=0x0 +phy_chain_tx_polarity_flip_physical{5.0}=0x1 +phy_chain_rx_polarity_flip_physical{5.0}=0x0 +phy_chain_tx_polarity_flip_physical{6.0}=0x0 +phy_chain_rx_polarity_flip_physical{6.0}=0x0 +phy_chain_tx_polarity_flip_physical{7.0}=0x1 +phy_chain_rx_polarity_flip_physical{7.0}=0x0 +phy_chain_tx_polarity_flip_physical{8.0}=0x0 +phy_chain_rx_polarity_flip_physical{8.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{14.0}=0x0 +phy_chain_tx_polarity_flip_physical{15.0}=0x0 +phy_chain_rx_polarity_flip_physical{15.0}=0x0 +phy_chain_tx_polarity_flip_physical{16.0}=0x0 +phy_chain_rx_polarity_flip_physical{16.0}=0x0 +phy_chain_tx_polarity_flip_physical{21.0}=0x1 +phy_chain_rx_polarity_flip_physical{21.0}=0x0 +phy_chain_tx_polarity_flip_physical{22.0}=0x0 +phy_chain_rx_polarity_flip_physical{22.0}=0x0 +phy_chain_tx_polarity_flip_physical{23.0}=0x1 +phy_chain_rx_polarity_flip_physical{23.0}=0x0 +phy_chain_tx_polarity_flip_physical{24.0}=0x0 +phy_chain_rx_polarity_flip_physical{24.0}=0x0 +phy_chain_tx_polarity_flip_physical{29.0}=0x0 +phy_chain_rx_polarity_flip_physical{29.0}=0x1 +phy_chain_tx_polarity_flip_physical{30.0}=0x0 +phy_chain_rx_polarity_flip_physical{30.0}=0x1 +phy_chain_tx_polarity_flip_physical{31.0}=0x0 +phy_chain_rx_polarity_flip_physical{31.0}=0x1 +phy_chain_tx_polarity_flip_physical{32.0}=0x0 +phy_chain_rx_polarity_flip_physical{32.0}=0x1 +phy_chain_tx_polarity_flip_physical{33.0}=0x0 +phy_chain_rx_polarity_flip_physical{33.0}=0x0 +phy_chain_tx_polarity_flip_physical{34.0}=0x0 +phy_chain_rx_polarity_flip_physical{34.0}=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}=0x0 +phy_chain_rx_polarity_flip_physical{36.0}=0x0 +phy_chain_tx_polarity_flip_physical{41.0}=0x0 +phy_chain_rx_polarity_flip_physical{41.0}=0x0 +phy_chain_tx_polarity_flip_physical{42.0}=0x0 +phy_chain_rx_polarity_flip_physical{42.0}=0x0 +phy_chain_tx_polarity_flip_physical{43.0}=0x0 +phy_chain_rx_polarity_flip_physical{43.0}=0x0 +phy_chain_tx_polarity_flip_physical{44.0}=0x0 +phy_chain_rx_polarity_flip_physical{44.0}=0x0 +phy_chain_tx_polarity_flip_physical{49.0}=0x0 +phy_chain_rx_polarity_flip_physical{49.0}=0x0 +phy_chain_tx_polarity_flip_physical{50.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{52.0}=0x0 +phy_chain_rx_polarity_flip_physical{52.0}=0x0 +phy_chain_tx_polarity_flip_physical{57.0}=0x0 +phy_chain_rx_polarity_flip_physical{57.0}=0x0 +phy_chain_tx_polarity_flip_physical{58.0}=0x0 +phy_chain_rx_polarity_flip_physical{58.0}=0x0 +phy_chain_tx_polarity_flip_physical{59.0}=0x0 +phy_chain_rx_polarity_flip_physical{59.0}=0x0 +phy_chain_tx_polarity_flip_physical{60.0}=0x0 +phy_chain_rx_polarity_flip_physical{60.0}=0x0 +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}=0x0 +phy_chain_rx_polarity_flip_physical{62.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{65.0}=0x0 +phy_chain_rx_polarity_flip_physical{65.0}=0x1 +phy_chain_tx_polarity_flip_physical{66.0}=0x0 +phy_chain_rx_polarity_flip_physical{66.0}=0x1 +phy_chain_tx_polarity_flip_physical{67.0}=0x0 +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}=0x1 +phy_chain_tx_polarity_flip_physical{69.0}=0x0 +phy_chain_rx_polarity_flip_physical{69.0}=0x0 +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}=0x0 +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 +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}=0x1 +phy_chain_tx_polarity_flip_physical{88.0}=0x0 +phy_chain_rx_polarity_flip_physical{88.0}=0x1 +phy_chain_tx_polarity_flip_physical{77.0}=0x1 +phy_chain_rx_polarity_flip_physical{77.0}=0x1 +phy_chain_tx_polarity_flip_physical{78.0}=0x1 +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 +phy_chain_tx_polarity_flip_physical{97.0}=0x1 +phy_chain_rx_polarity_flip_physical{97.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{100.0}=0x0 +phy_chain_rx_polarity_flip_physical{100.0}=0x0 +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}=0x0 +phy_chain_tx_polarity_flip_physical{95.0}=0x1 +phy_chain_rx_polarity_flip_physical{95.0}=0x1 +phy_chain_tx_polarity_flip_physical{96.0}=0x1 +phy_chain_rx_polarity_flip_physical{96.0}=0x1 +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}=0x1 +phy_chain_tx_polarity_flip_physical{115.0}=0x1 +phy_chain_rx_polarity_flip_physical{115.0}=0x1 +phy_chain_tx_polarity_flip_physical{116.0}=0x0 +phy_chain_rx_polarity_flip_physical{116.0}=0x1 +phy_chain_tx_polarity_flip_physical{105.0}=0x1 +phy_chain_rx_polarity_flip_physical{105.0}=0x1 +phy_chain_tx_polarity_flip_physical{106.0}=0x1 +phy_chain_rx_polarity_flip_physical{106.0}=0x0 +phy_chain_tx_polarity_flip_physical{107.0}=0x1 +phy_chain_rx_polarity_flip_physical{107.0}=0x1 +phy_chain_tx_polarity_flip_physical{108.0}=0x1 +phy_chain_rx_polarity_flip_physical{108.0}=0x1 +phy_chain_tx_polarity_flip_physical{121.0}=0x1 +phy_chain_rx_polarity_flip_physical{121.0}=0x1 +phy_chain_tx_polarity_flip_physical{122.0}=0x0 +phy_chain_rx_polarity_flip_physical{122.0}=0x0 +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 +phy_chain_tx_polarity_flip_physical{125.0}=0x0 +phy_chain_rx_polarity_flip_physical{125.0}=0x0 +phy_chain_tx_polarity_flip_physical{126.0}=0x1 +phy_chain_rx_polarity_flip_physical{126.0}=0x1 +phy_chain_tx_polarity_flip_physical{127.0}=0x0 +phy_chain_rx_polarity_flip_physical{127.0}=0x0 +phy_chain_tx_polarity_flip_physical{128.0}=0x0 +phy_chain_rx_polarity_flip_physical{128.0}=0x0 +port_flex_enable=1 +portmap_1=1:25 +portmap_2=2:25 +portmap_3=3:25 +portmap_4=4:25 +portmap_5=5:25 +portmap_6=6:25 +portmap_7=7:25 +portmap_8=8:25 +portmap_13=13:25 +portmap_14=14:25 +portmap_15=15:25 +portmap_16=16:25 +portmap_21=21:25 +portmap_22=22:25 +portmap_23=23:25 +portmap_24=24:25 +portmap_29=29:25 +portmap_30=30:25 +portmap_31=31:25 +portmap_32=32:25 +portmap_33=33:25 +portmap_34=34:25 +portmap_35=35:25 +portmap_36=36:25 +portmap_41=41:25 +portmap_42=42:25 +portmap_43=43:25 +portmap_44=44:25 +portmap_49=49:25 +portmap_50=50:25 +portmap_51=51:25 +portmap_52=52:25 +portmap_57=57:25 +portmap_58=58:25 +portmap_59=59:25 +portmap_60=60:25 +portmap_61=61:25 +portmap_62=62:25 +portmap_63=63:25 +portmap_64=64:25 +portmap_67=65:25 +portmap_68=66:25 +portmap_69=67:25 +portmap_70=68:25 +portmap_71=69:25 +portmap_72=70:25 +portmap_73=71:25 +portmap_74=72:25 +portmap_79=77:100 +portmap_87=85:100 +portmap_95=93:100 +portmap_99=97:100 +portmap_107=105:100 +portmap_115=113:100 +portmap_123=121:100 +portmap_127=125:100 + +dport_map_port_1=1 +dport_map_port_2=2 +dport_map_port_3=3 +dport_map_port_4=4 +dport_map_port_5=5 +dport_map_port_6=6 +dport_map_port_7=7 +dport_map_port_8=8 +dport_map_port_13=9 +dport_map_port_14=10 +dport_map_port_15=11 +dport_map_port_16=12 +dport_map_port_21=13 +dport_map_port_22=14 +dport_map_port_23=15 +dport_map_port_24=16 +dport_map_port_29=17 +dport_map_port_30=18 +dport_map_port_31=19 +dport_map_port_32=20 +dport_map_port_33=21 +dport_map_port_34=22 +dport_map_port_35=23 +dport_map_port_36=24 +dport_map_port_41=25 +dport_map_port_42=26 +dport_map_port_43=27 +dport_map_port_44=28 +dport_map_port_49=29 +dport_map_port_50=30 +dport_map_port_51=31 +dport_map_port_52=32 +dport_map_port_57=33 +dport_map_port_58=34 +dport_map_port_59=35 +dport_map_port_60=36 +dport_map_port_61=37 +dport_map_port_62=38 +dport_map_port_63=39 +dport_map_port_64=40 +dport_map_port_67=41 +dport_map_port_68=42 +dport_map_port_69=43 +dport_map_port_70=44 +dport_map_port_71=45 +dport_map_port_72=46 +dport_map_port_73=47 +dport_map_port_74=48 +dport_map_port_87=49 +dport_map_port_79=50 +dport_map_port_99=51 +dport_map_port_95=52 +dport_map_port_115=53 +dport_map_port_107=54 +dport_map_port_123=55 +dport_map_port_127=56 + +serdes_preemphasis_lane0_1=0x0f480d +serdes_preemphasis_lane1_1=0x0f480d +serdes_preemphasis_lane2_1=0x0f480d +serdes_preemphasis_lane3_1=0x0f480d +serdes_preemphasis_lane0_2=0x0f480d +serdes_preemphasis_lane1_2=0x0f480d +serdes_preemphasis_lane2_2=0x0f480d +serdes_preemphasis_lane3_2=0x0f480d +serdes_preemphasis_lane0_3=0x0f480d +serdes_preemphasis_lane1_3=0x0f480d +serdes_preemphasis_lane2_3=0x0f480d +serdes_preemphasis_lane3_3=0x0f480d +serdes_preemphasis_lane0_4=0x0f480d +serdes_preemphasis_lane1_4=0x0f480d +serdes_preemphasis_lane2_4=0x0f480d +serdes_preemphasis_lane3_4=0x0f480d +serdes_preemphasis_lane0_5=0x0f480d +serdes_preemphasis_lane1_5=0x0f480d +serdes_preemphasis_lane2_5=0x0f480d +serdes_preemphasis_lane3_5=0x0f480d +serdes_preemphasis_lane0_6=0x0f480d +serdes_preemphasis_lane1_6=0x0f480d +serdes_preemphasis_lane2_6=0x0f480d +serdes_preemphasis_lane3_6=0x0f480d +serdes_preemphasis_lane0_7=0x0d4b0c +serdes_preemphasis_lane1_7=0x0d4b0c +serdes_preemphasis_lane2_7=0x0d4b0c +serdes_preemphasis_lane3_7=0x0d4b0c +serdes_preemphasis_lane0_8=0x0d4b0c +serdes_preemphasis_lane1_8=0x0d4b0c +serdes_preemphasis_lane2_8=0x0d4b0c +serdes_preemphasis_lane3_8=0x0d4b0c +serdes_preemphasis_lane0_13=0x0d4b0c +serdes_preemphasis_lane1_13=0x0d4b0c +serdes_preemphasis_lane2_13=0x0d4b0c +serdes_preemphasis_lane3_13=0x0d4b0c +serdes_preemphasis_lane0_14=0x0d4b0c +serdes_preemphasis_lane1_14=0x0d4b0c +serdes_preemphasis_lane2_14=0x0d4b0c +serdes_preemphasis_lane3_14=0x0d4b0c +serdes_preemphasis_lane0_15=0x0d4b0c +serdes_preemphasis_lane1_15=0x0d4b0c +serdes_preemphasis_lane2_15=0x0d4b0c +serdes_preemphasis_lane3_15=0x0d4b0c +serdes_preemphasis_lane0_16=0x0d4b0c +serdes_preemphasis_lane1_16=0x0d4b0c +serdes_preemphasis_lane2_16=0x0d4b0c +serdes_preemphasis_lane3_16=0x0d4b0c +serdes_preemphasis_lane0_21=0x0d4b0c +serdes_preemphasis_lane1_21=0x0d4b0c +serdes_preemphasis_lane2_21=0x0d4b0c +serdes_preemphasis_lane3_21=0x0d4b0c +serdes_preemphasis_lane0_22=0x0d4b0c +serdes_preemphasis_lane1_22=0x0d4b0c +serdes_preemphasis_lane2_22=0x0d4b0c +serdes_preemphasis_lane3_22=0x0d4b0c +serdes_preemphasis_lane0_23=0x0d4b0c +serdes_preemphasis_lane1_23=0x0d4b0c +serdes_preemphasis_lane2_23=0x0d4b0c +serdes_preemphasis_lane3_23=0x0d4b0c +serdes_preemphasis_lane0_24=0x0d4b0c +serdes_preemphasis_lane1_24=0x0d4b0c +serdes_preemphasis_lane2_24=0x0d4b0c +serdes_preemphasis_lane3_24=0x0d4b0c +serdes_preemphasis_lane0_29=0x0d4b0c +serdes_preemphasis_lane1_29=0x0d4b0c +serdes_preemphasis_lane2_29=0x0d4b0c +serdes_preemphasis_lane3_29=0x0d4b0c +serdes_preemphasis_lane0_30=0x0d4b0c +serdes_preemphasis_lane1_30=0x0d4b0c +serdes_preemphasis_lane2_30=0x0d4b0c +serdes_preemphasis_lane3_30=0x0d4b0c +serdes_preemphasis_lane0_31=0x0d4b0c +serdes_preemphasis_lane1_31=0x0d4b0c +serdes_preemphasis_lane2_31=0x0d4b0c +serdes_preemphasis_lane3_31=0x0d4b0c +serdes_preemphasis_lane0_32=0x0d4b0c +serdes_preemphasis_lane1_32=0x0d4b0c +serdes_preemphasis_lane2_32=0x0d4b0c +serdes_preemphasis_lane3_32=0x0d4b0c +serdes_preemphasis_lane0_33=0x0d4b0c +serdes_preemphasis_lane1_33=0x0d4b0c +serdes_preemphasis_lane2_33=0x0d4b0c +serdes_preemphasis_lane3_33=0x0d4b0c +serdes_preemphasis_lane0_34=0x0d4b0c +serdes_preemphasis_lane1_34=0x0d4b0c +serdes_preemphasis_lane2_34=0x0d4b0c +serdes_preemphasis_lane3_34=0x0d4b0c +serdes_preemphasis_lane0_35=0x0d4b0c +serdes_preemphasis_lane1_35=0x0d4b0c +serdes_preemphasis_lane2_35=0x0d4b0c +serdes_preemphasis_lane3_35=0x0d4b0c +serdes_preemphasis_lane0_36=0x0d4b0c +serdes_preemphasis_lane1_36=0x0d4b0c +serdes_preemphasis_lane2_36=0x0d4b0c +serdes_preemphasis_lane3_36=0x0d4b0c +serdes_preemphasis_lane0_41=0x0d4b0c +serdes_preemphasis_lane1_41=0x0d4b0c +serdes_preemphasis_lane2_41=0x0d4b0c +serdes_preemphasis_lane3_41=0x0d4b0c +serdes_preemphasis_lane0_42=0x0d4b0c +serdes_preemphasis_lane1_42=0x0d4b0c +serdes_preemphasis_lane2_42=0x0d4b0c +serdes_preemphasis_lane3_42=0x0d4b0c +serdes_preemphasis_lane0_43=0x0d4b0c +serdes_preemphasis_lane1_43=0x0d4b0c +serdes_preemphasis_lane2_43=0x0d4b0c +serdes_preemphasis_lane3_43=0x0d4b0c +serdes_preemphasis_lane0_44=0x0d4b0c +serdes_preemphasis_lane1_44=0x0d4b0c +serdes_preemphasis_lane2_44=0x0d4b0c +serdes_preemphasis_lane3_44=0x0d4b0c +serdes_preemphasis_lane0_49=0x0d4b0c +serdes_preemphasis_lane1_49=0x0d4b0c +serdes_preemphasis_lane2_49=0x0d4b0c +serdes_preemphasis_lane3_49=0x0d4b0c +serdes_preemphasis_lane0_50=0x0d4b0c +serdes_preemphasis_lane1_50=0x0d4b0c +serdes_preemphasis_lane2_50=0x0d4b0c +serdes_preemphasis_lane3_50=0x0d4b0c +serdes_preemphasis_lane0_51=0x0d4b0c +serdes_preemphasis_lane1_51=0x0d4b0c +serdes_preemphasis_lane2_51=0x0d4b0c +serdes_preemphasis_lane3_51=0x0d4b0c +serdes_preemphasis_lane0_52=0x0d4b0c +serdes_preemphasis_lane1_52=0x0d4b0c +serdes_preemphasis_lane2_52=0x0d4b0c +serdes_preemphasis_lane3_52=0x0d4b0c +serdes_preemphasis_lane0_57=0x0d4b0c +serdes_preemphasis_lane1_57=0x0d4b0c +serdes_preemphasis_lane2_57=0x0d4b0c +serdes_preemphasis_lane3_57=0x0d4b0c +serdes_preemphasis_lane0_58=0x0d4b0c +serdes_preemphasis_lane1_58=0x0d4b0c +serdes_preemphasis_lane2_58=0x0d4b0c +serdes_preemphasis_lane3_58=0x0d4b0c +serdes_preemphasis_lane0_59=0x0d4b0c +serdes_preemphasis_lane1_59=0x0d4b0c +serdes_preemphasis_lane2_59=0x0d4b0c +serdes_preemphasis_lane3_59=0x0d4b0c +serdes_preemphasis_lane0_60=0x0d4b0c +serdes_preemphasis_lane1_60=0x0d4b0c +serdes_preemphasis_lane2_60=0x0d4b0c +serdes_preemphasis_lane3_60=0x0d4b0c +serdes_preemphasis_lane0_61=0x0d4b0c +serdes_preemphasis_lane1_61=0x0d4b0c +serdes_preemphasis_lane2_61=0x0d4b0c +serdes_preemphasis_lane3_61=0x0d4b0c +serdes_preemphasis_lane0_62=0x0d4b0c +serdes_preemphasis_lane1_62=0x0d4b0c +serdes_preemphasis_lane2_62=0x0d4b0c +serdes_preemphasis_lane3_62=0x0d4b0c +serdes_preemphasis_lane0_63=0x0d4b0c +serdes_preemphasis_lane1_63=0x0d4b0c +serdes_preemphasis_lane2_63=0x0d4b0c +serdes_preemphasis_lane3_63=0x0d4b0c +serdes_preemphasis_lane0_64=0x0d4b0c +serdes_preemphasis_lane1_64=0x0d4b0c +serdes_preemphasis_lane2_64=0x0d4b0c +serdes_preemphasis_lane3_64=0x0d4b0c +serdes_preemphasis_lane0_67=0x0d4b0c +serdes_preemphasis_lane1_67=0x0d4b0c +serdes_preemphasis_lane2_67=0x0d4b0c +serdes_preemphasis_lane3_67=0x0d4b0c +serdes_preemphasis_lane0_68=0x0d4b0c +serdes_preemphasis_lane1_68=0x0d4b0c +serdes_preemphasis_lane2_68=0x0d4b0c +serdes_preemphasis_lane3_68=0x0d4b0c +serdes_preemphasis_lane0_69=0x0d4b0c +serdes_preemphasis_lane1_69=0x0d4b0c +serdes_preemphasis_lane2_69=0x0d4b0c +serdes_preemphasis_lane3_69=0x0d4b0c +serdes_preemphasis_lane0_70=0x0d4b0c +serdes_preemphasis_lane1_70=0x0d4b0c +serdes_preemphasis_lane2_70=0x0d4b0c +serdes_preemphasis_lane3_70=0x0d4b0c +serdes_preemphasis_lane0_71=0x0d4b0c +serdes_preemphasis_lane1_71=0x0d4b0c +serdes_preemphasis_lane2_71=0x0d4b0c +serdes_preemphasis_lane3_71=0x0d4b0c +serdes_preemphasis_lane0_72=0x0d4b0c +serdes_preemphasis_lane1_72=0x0d4b0c +serdes_preemphasis_lane2_72=0x0d4b0c +serdes_preemphasis_lane3_72=0x0d4b0c +serdes_preemphasis_lane0_73=0x0d4b0c +serdes_preemphasis_lane1_73=0x0d4b0c +serdes_preemphasis_lane2_73=0x0d4b0c +serdes_preemphasis_lane3_73=0x0d4b0c +serdes_preemphasis_lane0_74=0x0d4b0c +serdes_preemphasis_lane1_74=0x0d4b0c +serdes_preemphasis_lane2_74=0x0d4b0c +serdes_preemphasis_lane3_74=0x0d4b0c +serdes_preemphasis_lane0_87=0x0d4b0c +serdes_preemphasis_lane1_87=0x0d4b0c +serdes_preemphasis_lane2_87=0x0d4b0c +serdes_preemphasis_lane3_87=0x0d4b0c +serdes_preemphasis_lane0_79=0x0d4b0c +serdes_preemphasis_lane1_79=0x0d4b0c +serdes_preemphasis_lane2_79=0x0d4b0c +serdes_preemphasis_lane3_79=0x0d4b0c +serdes_preemphasis_lane0_99=0x0d4b0c +serdes_preemphasis_lane1_99=0x0d4b0c +serdes_preemphasis_lane2_99=0x0d4b0c +serdes_preemphasis_lane3_99=0x0d4b0c +serdes_preemphasis_lane0_95=0x0d4b0c +serdes_preemphasis_lane1_95=0x0d4b0c +serdes_preemphasis_lane2_95=0x0d4b0c +serdes_preemphasis_lane3_95=0x0d4b0c +serdes_preemphasis_lane0_115=0x0f480d +serdes_preemphasis_lane1_115=0x0f480d +serdes_preemphasis_lane2_115=0x0f480d +serdes_preemphasis_lane3_115=0x0f480d +serdes_preemphasis_lane0_107=0x0f480d +serdes_preemphasis_lane1_107=0x0f480d +serdes_preemphasis_lane2_107=0x0f480d +serdes_preemphasis_lane3_107=0x0f480d +serdes_preemphasis_lane0_123=0x0f480d +serdes_preemphasis_lane1_123=0x0f480d +serdes_preemphasis_lane2_123=0x0f480d +serdes_preemphasis_lane3_123=0x0f480d +serdes_preemphasis_lane0_127=0x0f480d +serdes_preemphasis_lane1_127=0x0f480d +serdes_preemphasis_lane2_127=0x0f480d +serdes_preemphasis_lane3_127=0x0f480d + +reglist_enable=1 +scache_filename=/tmp/scache +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/custom_led.bin b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/custom_led.bin new file mode 100644 index 000000000000..1fe5585e0779 Binary files /dev/null and b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/custom_led.bin differ diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/default_sku b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/default_sku new file mode 100644 index 000000000000..3f0585c6e5b5 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/default_sku @@ -0,0 +1 @@ +B6510-48VS8CQ t1 diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/dev.xml b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/dev.xml new file mode 100755 index 000000000000..f5e871564350 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/dev.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/installer.conf b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/installer.conf new file mode 100755 index 000000000000..5e62742c11bf --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=115200 diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/led_proc_init.soc b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/led_proc_init.soc new file mode 100755 index 000000000000..59238f5cdc94 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/led_proc_init.soc @@ -0,0 +1,7 @@ +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin + +led auto on + +led start + +linkscan SwPortBitMap=xe,ce diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/monitor.py b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/monitor.py new file mode 100755 index 000000000000..f9cbb31be401 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/monitor.py @@ -0,0 +1,244 @@ +#!/usr/bin/python3 +# -*- coding: UTF-8 -*- +""" +* onboard temperature sensors +* FAN trays +* PSU +""" +import os +import xml.etree.ElementTree as ET +import glob + +MAILBOX_DIR = "/sys/bus/i2c/devices/" +PORTS_DIR = "/sys/class/net/" +CONFIG_NAME = "dev.xml" + + +def getPMCreg(location): + retval = "ERR" + if not os.path.isfile(location): + return "%s %s notfound" % (retval, location) + try: + with open(location, "r") as fd: + retval = fd.read() + except Exception: + pass + # logging.error("Unable to open ", location, "file !") + + retval = retval.rstrip("\r\n") + retval = retval.lstrip(" ") + return retval + + +# Get a mailbox register +def get_pmc_register(reg_name): + retval = "ERR" + if reg_name[0:4] == "/rif" or reg_name[0:4] == "/ma1" or reg_name[0:4] == "/eth": + mb_reg_file = PORTS_DIR + reg_name + else: + mb_reg_file = MAILBOX_DIR + reg_name + filepath = glob.glob(mb_reg_file) + if len(filepath) == 0: + return "%s %s notfound" % (retval, mb_reg_file) + mb_reg_file = filepath[0] # use first found patch + if not os.path.isfile(mb_reg_file): + return "%s %s notfound" % (retval, mb_reg_file) + try: + with open(mb_reg_file, "r") as fd: + retval = fd.read() + except Exception: + pass + # logging.error("Unable to open ", mb_reg_file, "file !") + + retval = retval.rstrip("\r\n") + retval = retval.lstrip(" ") + return retval + + +class checktype: + def __init__(self, test1): + self.test1 = test1 + + @staticmethod + def check(name, location, bit, value, tips, err1): + psu_status = int(get_pmc_register(location), 16) + val = (psu_status & (1 << bit)) >> bit + if val != value: + err1["errmsg"] = tips + err1["code"] = -1 + return -1 + else: + err1["errmsg"] = "none" + err1["code"] = 0 + return 0 + + @staticmethod + def getValue(location, bit, type): + value_t = get_pmc_register(location) + if value_t.startswith("ERR"): + return value_t + if type == 1: + return float(value_t) / 1000 + elif type == 2: + return float(value_t) / 100 + elif type == 3: + psu_status = int(value_t, 16) + return (psu_status & (1 << bit)) >> bit + elif type == 4: + return int(value_t, 10) + else: + return value_t + + # temperature + @staticmethod + def getTemp(self, name, location, ret_t): + ret2 = self.getValue(location + "temp1_input", " ", 1) + ret3 = self.getValue(location + "temp1_max", " ", 1) + ret4 = self.getValue(location + "temp1_max_hyst", " ", 1) + ret_t["temp1_input"] = ret2 + ret_t["temp1_max"] = ret3 + ret_t["temp1_max_hyst"] = ret4 + + @staticmethod + def getLM75(name, location, result): + c1 = checktype + r1 = {} + c1.getTemp(c1, name, location, r1) + result[name] = r1 + + +class status: + def __init__(self, productname): + self.productname = productname + + @staticmethod + def getETroot(filename): + tree = ET.parse(filename) + root = tree.getroot() + return root + + @staticmethod + def getDecodValue(collection, decode): + decodes = collection.find("decode") + testdecode = decodes.find(decode) + test = {} + for neighbor in testdecode.iter("code"): + test[neighbor.attrib["key"]] = neighbor.attrib["value"] + return test + + @staticmethod + def getfileValue(location): + return checktype.getValue(location, " ", " ") + + @staticmethod + def getETValue(a, filename, tagname): + root = status.getETroot(filename) + for neighbor in root.iter(tagname): + prob_t = {} + prob_t = neighbor.attrib + prob_t["errcode"] = 0 + prob_t["errmsg"] = "" + for pros in neighbor.iter("property"): + ret = dict(neighbor.attrib.items() + pros.attrib.items()) + if "type" not in ret.keys(): + val = "0" + else: + val = ret["type"] + if "bit" not in ret.keys(): + bit = "0" + else: + bit = ret["bit"] + s = checktype.getValue(ret["location"], int(bit), int(val)) + if isinstance(s, str) and s.startswith("ERR"): + prob_t["errcode"] = -1 + prob_t["errmsg"] = s + if "default" in ret.keys(): + rt = status.getDecodValue(root, ret["decode"]) + prob_t["errmsg"] = rt[str(s)] + if str(s) != ret["default"]: + prob_t["errcode"] = -1 + break + else: + if "decode" in ret.keys(): + rt = status.getDecodValue(root, ret["decode"]) + if ( + ret["decode"] == "psutype" + and s.replace("\x00", "").rstrip() not in rt.keys() + ): # PSU type detect + prob_t["errcode"] = -1 + prob_t["errmsg"] = "%s" % ("The power type does not match, please check whether the power is correct!") + else: + s = rt[str(s).replace("\x00", "").rstrip()] + name = ret["name"] + prob_t[name] = str(s) + a.append(prob_t) + + @staticmethod + def getCPUValue(a, filename, tagname): + root = status.getETroot(filename) + for neighbor in root.iter(tagname): + location = neighbor.attrib["location"] + L = [] + for dirpath, dirnames, filenames in os.walk(location): + for file in filenames: + if file.endswith("input"): + L.append(os.path.join(dirpath, file)) + L = sorted(L, reverse=False) + for i in range(len(L)): + prob_t = {} + prob_t["name"] = getPMCreg("%s/temp%d_label" % (location, i + 1)) + prob_t["temp"] = ( + float(getPMCreg("%s/temp%d_input" % (location, i + 1))) / 1000 + ) + prob_t["alarm"] = ( + float(getPMCreg("%s/temp%d_crit_alarm" % (location, i + 1))) / 1000 + ) + prob_t["crit"] = ( + float(getPMCreg("%s/temp%d_crit" % (location, i + 1))) / 1000 + ) + prob_t["max"] = float(getPMCreg("%s/temp%d_max" % (location, i + 1))) / 1000 + a.append(prob_t) + + @staticmethod + def getFileName(): + return os.path.dirname(os.path.realpath(__file__)) + "/" + CONFIG_NAME + + @staticmethod + def getFan(ret): + _filename = status.getFileName() + _tagname = "fan" + status.getvalue(ret, _filename, _tagname) + + @staticmethod + def checkFan(ret): + _filename = status.getFileName() + # _filename = "/usr/local/bin/" + status.getFileName() + _tagname = "fan" + status.getETValue(ret, _filename, _tagname) + + @staticmethod + def getTemp(ret): + _filename = status.getFileName() + # _filename = "/usr/local/bin/" + status.getFileName() + _tagname = "temp" + status.getETValue(ret, _filename, _tagname) + + @staticmethod + def getPsu(ret): + _filename = status.getFileName() + # _filename = "/usr/local/bin/" + status.getFileName() + _tagname = "psu" + status.getETValue(ret, _filename, _tagname) + + @staticmethod + def getcputemp(ret): + _filename = status.getFileName() + _tagname = "cpus" + status.getCPUValue(ret, _filename, _tagname) + + @staticmethod + def getMgmtRx(ret): + _filename = status.getFileName() + # _filename = "/usr/local/bin/" + status.getFileName() + _tagname = "mgmt_rx" + status.getETValue(ret, _filename, _tagname) diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pcie.yaml b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pcie.yaml new file mode 100644 index 000000000000..90ebf1740641 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pcie.yaml @@ -0,0 +1,429 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 6f00 + name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 6f02 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '01' + fn: '1' + id: 6f03 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 6f04 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '2' + id: 6f06 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 6f08 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '05' + fn: '0' + id: 6f28 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Map/VTd_Misc/System Management (rev 03)' +- bus: '00' + dev: '05' + fn: '1' + id: 6f29 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO Hot Plug (rev 03)' +- bus: '00' + dev: '05' + fn: '2' + id: 6f2a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO RAS/Control Status/Global Errors (rev 03)' +- bus: '00' + dev: '05' + fn: '4' + id: 6f2c + name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev + 03)' +- bus: '00' + dev: '14' + fn: '0' + id: 8c31 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + xHCI (rev 05)' +- bus: '00' + dev: '16' + fn: '0' + id: 8c3a + name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset + Family MEI Controller #1 (rev 04)' +- bus: '00' + dev: '16' + fn: '1' + id: 8c3b + name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset + Family MEI Controller #2 (rev 04)' +- bus: '00' + dev: 1c + fn: '0' + id: 8c10 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #1 (rev d5)' +- bus: '00' + dev: 1d + fn: '0' + id: 8c26 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + EHCI #1 (rev 05)' +- bus: '00' + dev: 1f + fn: '0' + id: 8c54 + name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard + SKU LPC Controller (rev 05)' +- bus: '00' + dev: 1f + fn: '2' + id: 8c02 + name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port + SATA Controller 1 [AHCI mode] (rev 05)' +- bus: '00' + dev: 1f + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller + (rev 05)' +- bus: '01' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '03' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '03' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '03' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '03' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '04' + dev: '00' + fn: '0' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '04' + dev: '00' + fn: '1' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '07' + dev: '00' + fn: '0' + id: b873 + name: 'Ethernet controller: Broadcom Limited Device b873 (rev 01)' +- bus: ff + dev: 0b + fn: '0' + id: 6f81 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '1' + id: 6f36 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '2' + id: 6f37 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '3' + id: 6f76 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link Debug (rev 03)' +- bus: ff + dev: 0c + fn: '0' + id: 6fe0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '1' + id: 6fe1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '2' + id: 6fe2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '3' + id: 6fe3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '0' + id: 6ff8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '4' + id: 6ffc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '5' + id: 6ffd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '6' + id: 6ffe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: '10' + fn: '0' + id: 6f1d + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '1' + id: 6f34 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '5' + id: 6f1e + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '6' + id: 6f7d + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '7' + id: 6f1f + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '12' + fn: '0' + id: 6fa0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '12' + fn: '1' + id: 6f30 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '13' + fn: '0' + id: 6fa8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '1' + id: 6f71 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '2' + id: 6faa + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '3' + id: 6fab + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '4' + id: 6fac + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '5' + id: 6fad + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '6' + id: 6fae + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Broadcast (rev 03)' +- bus: ff + dev: '13' + fn: '7' + id: 6faf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Global Broadcast (rev 03)' +- bus: ff + dev: '14' + fn: '0' + id: 6fb0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '1' + id: 6fb1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '2' + id: 6fb2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Error (rev 03)' +- bus: ff + dev: '14' + fn: '3' + id: 6fb3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Error (rev 03)' +- bus: ff + dev: '14' + fn: '4' + id: 6fbc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '5' + id: 6fbd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '6' + id: 6fbe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '7' + id: 6fbf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '15' + fn: '0' + id: 6fb4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '1' + id: 6fb5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '2' + id: 6fb6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Error (rev 03)' +- bus: ff + dev: '15' + fn: '3' + id: 6fb7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Error (rev 03)' +- bus: ff + dev: 1e + fn: '0' + id: 6f98 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '1' + id: 6f99 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '2' + id: 6f9a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '3' + id: 6fc0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '4' + id: 6f9c + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '0' + id: 6f88 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '2' + id: 6f8a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/platform_env.conf b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/platform_env.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/eeprom.py b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/eeprom.py new file mode 100755 index 000000000000..53f57c2a3625 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/eeprom.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/bus/i2c/devices/2-0057/eeprom" + super(board, self).__init__(self.eeprom_path, 0, "", True) diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/psuutil.py b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/psuutil.py new file mode 100755 index 000000000000..e1513d14c4b2 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/psuutil.py @@ -0,0 +1,63 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def get_num_psus(self): + return 2 + + def get_psu_status(self, index): + if index != 1 and index != 2: + return False + + psu_path = "/sys/bus/i2c/devices/2-0037/psu_status" + + try: + data = open(psu_path, "rb") + except IOError: + return False + + result = int(data.read(2), 16) + data.close() + + if index == 1 and (result & 0x2): + return True + + if index == 2 and (result & 0x20): + return True + + return False + + def get_psu_presence(self, index): + if index != 1 and index != 2: + return False + + psu_path = "/sys/bus/i2c/devices/2-0037/psu_status" + + try: + data = open(psu_path, "rb") + except IOError: + return False + + result = int(data.read(2), 16) + data.close() + + if index == 1 and (result & 0x1) == 0: + return True + + if index == 2 and (result & 0x10) == 0: + return True + + return False diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/sfputil.py b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/sfputil.py new file mode 100755 index 000000000000..cfc294972e5b --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/plugins/sfputil.py @@ -0,0 +1,359 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + from ctypes import create_string_buffer + from sonic_sfp.sfputilbase import SfpUtilBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 55 + PORTS_IN_BLOCK = 56 + + EEPROM_OFFSET = 11 + SFP_DEVICE_TYPE = "optoe2" + QSFP_DEVICE_TYPE = "optoe1" + I2C_MAX_ATTEMPT = 3 + + SFP_STATUS_INSERTED = '1' + SFP_STATUS_REMOVED = '0' + + QSFP_POWERMODE_OFFSET = 93 + QSFP_CONTROL_OFFSET = 86 + QSFP_CONTROL_WIDTH = 8 + + _port_to_eeprom_mapping = {} + port_to_i2cbus_mapping ={} + port_dict = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return range(48, self.PORTS_IN_BLOCK) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + for x in range(self.PORT_START, self.PORTS_IN_BLOCK): + self.port_to_i2cbus_mapping[x] = (x + self.EEPROM_OFFSET) + if self.get_presence(x): + self.port_dict[x] = self.SFP_STATUS_INSERTED + else: + self.port_dict[x] = self.SFP_STATUS_REMOVED + SfpUtilBase.__init__(self) + + def _sfp_read_file_path(self, file_path, offset, num_bytes): + attempts = 0 + while attempts < self.I2C_MAX_ATTEMPT: + try: + file_path.seek(offset) + read_buf = file_path.read(num_bytes) + except BaseException: + attempts += 1 + time.sleep(0.05) + else: + return True, read_buf + return False, None + + def _sfp_eeprom_present(self, sysfs_sfp_i2c_client_eeprompath, offset): + if not os.path.exists(sysfs_sfp_i2c_client_eeprompath): + return False + else: + with open(sysfs_sfp_i2c_client_eeprompath, "rb", buffering=0) as sysfsfile: + rv, buf = self._sfp_read_file_path(sysfsfile, offset, 1) + return rv + + def _add_new_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr, devtype): + try: + sysfs_nd_path = "%s/new_device" % sysfs_sfp_i2c_adapter_path + + # Write device address to new_device file + nd_file = open(sysfs_nd_path, "w") + nd_str = "%s %s" % (devtype, hex(devaddr)) + nd_file.write(nd_str) + nd_file.close() + + except Exception as err: + print("Error writing to new device file: %s" % str(err)) + return 1 + else: + return 0 + + def _get_port_eeprom_path(self, port_num, devid): + sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" + + if port_num in self.port_to_eeprom_mapping.keys(): + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[port_num] + else: + i2c_adapter_id = self._get_port_i2c_adapter_id(port_num) + if i2c_adapter_id is None: + print("Error getting i2c bus num") + return None + + # Get i2c virtual bus path for the sfp + sysfs_sfp_i2c_adapter_path = "%s/i2c-%s" % (sysfs_i2c_adapter_base_path, + str(i2c_adapter_id)) + + # If i2c bus for port does not exist + if not os.path.exists(sysfs_sfp_i2c_adapter_path): + print("Could not find i2c bus %s. Driver not loaded?" % sysfs_sfp_i2c_adapter_path) + return None + + sysfs_sfp_i2c_client_path = "%s/%s-00%s" % (sysfs_sfp_i2c_adapter_path, + str(i2c_adapter_id), + hex(devid)[-2:]) + + # If sfp device is not present on bus, Add it + if not os.path.exists(sysfs_sfp_i2c_client_path): + if port_num in self.qsfp_ports: + self._add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.QSFP_DEVICE_TYPE) + else: + ret = self._add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.SFP_DEVICE_TYPE) + if ret != 0: + print("Error adding sfp device") + return None + + sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path + + return sysfs_sfp_i2c_client_eeprom_path + + def _read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes): + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + rv, raw = self._sfp_read_file_path(sysfsfile_eeprom, offset, num_bytes) + if rv == False: + return None + + try: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except BaseException: + return None + + return eeprom_raw + + 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.IDENTITY_EEPROM_ADDR, 256) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + if port_num <= 7: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence1" + elif port_num >= 8 and port_num <= 15: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence2" + elif port_num >= 16 and port_num <= 23: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence3" + elif port_num >= 24 and port_num <= 31: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence4" + elif port_num >= 32 and port_num <= 39: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence5" + elif port_num >= 40 and port_num <= 47: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence6" + elif port_num >= 48 and port_num <= 55: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence7" + else: + return False + + try: + data = open(presence_path, "rb") + except IOError: + return False + + presence_data = data.read(2) + if presence_data == "": + return False + result = int(presence_data, 16) + data.close() + + # ModPrsL is active low + if result & (1 << (port_num % 8)) == 0: + return True + + return False + + def set_power_override(self, port_num, power_override, power_set): + if port_num < self.port_start or port_num > self.port_end: + return False + if self.get_presence(port_num) is False: + return False + if port_num in self.qsfp_ports: + offset = 0 + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(offset + self.QSFP_POWERMODE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + else: + # SFP doesn't support this feature + return False + + def get_low_power_mode(self, port_num): + """ + Not support LPMode pin to control lpmde. + This function is affected by the Power_over-ride and Power_set software control bits (byte 93 bits 0,1) + """ + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num in self.qsfp_ports: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + sysfs_sfp_i2c_client_eeprom_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) + with open(sysfs_sfp_i2c_client_eeprom_path, "rb", buffering=0) as sysfsfile: + dom_control_raw = self._read_eeprom_specific_bytes(sysfsfile, + offset + self.QSFP_CONTROL_OFFSET, self.QSFP_CONTROL_WIDTH) if self.get_presence(port_num) else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + lpmode = ('On' == dom_control_data['data']['PowerSet']['value']) + power_override = ('On' == dom_control_data['data']['PowerOverride']['value']) + if lpmode == power_override == True: + return True + else: + # SFP doesn't support this feature + return False + return False + + def set_low_power_mode(self, port_num, lpmode): + """ + Not support LPMode pin to control lpmde. + This function is affected by the Power_over-ride and Power_set software control bits (byte 93 bits 0,1) + """ + if port_num < self.port_start or port_num > self.port_end: + return False + if lpmode: + return self.set_power_override(port_num, True, lpmode) + else: + return self.set_power_override(port_num, False, lpmode) + + def reset(self, port_num): + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num in self.qsfp_ports: + reset_path = "/sys/bus/i2c/devices/1-0036/qsfp_reset" + try: + data = open(reset_path, "r+") + reset_data = data.read(2) + if reset_data == "": + return False + result = int(reset_data, 16) + result = result & (~(1 << (port_num % 8))) + data.seek(0) + sres = hex(result)[2:] + data.write(sres) + data.close() + + time.sleep(1) + + data = open(reset_path, "r+") + reset_data = data.read(2) + if reset_data == "": + return False + result = int(reset_data, 16) + data.seek(0) + result = result | (1 << (port_num % 8)) + sres = hex(result)[2:] + data.write(sres) + data.close() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + return True + else: + # SFP doesn't support this feature + return False + + def get_transceiver_change_event(self, timeout=0): + + start_time = time.time() + currernt_port_dict = {} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print("get_transceiver_change_event: time wrap / invalid timeout value", timeout) + + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + # Check for OIR events and return updated port_dict + for x in range(self.PORT_START, self.PORTS_IN_BLOCK): + if self.get_presence(x): + currernt_port_dict[x] = self.SFP_STATUS_INSERTED + else: + currernt_port_dict[x] = self.SFP_STATUS_REMOVED + if (currernt_port_dict == self.port_dict): + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + else: + # Update reg value + self.port_dict = currernt_port_dict + return True, self.port_dict + print("get_transceiver_change_event: Should not reach here.") + return False, {} diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pmon_daemon_control.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..590def37b276 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/pmon_daemon_control.json @@ -0,0 +1,5 @@ +{ + "skip_ledd": true, + "skip_xcvrd": false, + "skip_psud": false +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sensors.conf b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sensors.conf new file mode 100755 index 000000000000..9b0569d1541d --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sensors.conf @@ -0,0 +1,21 @@ +# libsensors configuration file +# ---------------------------------------------- +# + +bus "i2c-2" "i2c-0-mux (chan_id 0)" + +chip "lm75-i2c-2-48" + label temp1 "LM75_0 air_inlet" + set temp1_max 80 + set temp1_max_hyst 75 + +chip "lm75-i2c-2-49" + label temp1 "LM75_1 air_outlet" + set temp1_max 80 + set temp1_max_hyst 75 + +chip "lm75-i2c-2-4a" + label temp1 "LM75_2 hottest" + set temp1_max 80 + set temp1_max_hyst 75 + diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/chassis.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/chassis.json new file mode 100644 index 000000000000..c5ea46918ff2 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/chassis.json @@ -0,0 +1,3 @@ +{ + "eeprom": {"bus": 2, "loc": "0057"} +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/component.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/component.json new file mode 100644 index 000000000000..35f4b4586447 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/component.json @@ -0,0 +1,60 @@ +{ + "components": [ + { + "name": "CPLD1 (MAC Board A)", + "firmware_version": { + "bus": 2, + "addr": 51, + "offset": 0, + "size": 4, + "way": 1, + "format": 7, + "sep": "/" + }, + "desc": "Used for managing IO modules, SFP+ modules and system LEDs", + "slot": 0 + }, + { + "name": "CPLD2 (MAC Board B)", + "firmware_version": { + "bus": 2, + "addr": 53, + "offset": 0, + "size": 4, + "way": 1, + "format": 7, + "sep": "/" + }, + "desc": "Used for managing IO modules, SFP+ modules and system LEDs", + "slot": 0 + }, + { + "name": "CPLD3 (CONNECT Board A)", + "firmware_version": { + "bus": 2, + "addr": 55, + "offset": 0, + "size": 4, + "way": 1, + "format": 7, + "sep": "/" + }, + "desc": "Used for managing IO modules, SFP+ modules and system LEDs", + "slot": 0 + }, + { + "name": "CPLD4 (CPU Board)", + "firmware_version": { + "bus": 0, + "addr": 13, + "offset": 0, + "size": 4, + "way": 1, + "format": 7, + "sep": "/" + }, + "desc": "Used for managing IO modules, SFP+ modules and system LEDs", + "slot": 1 + } + ] +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/fan.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/fan.json new file mode 100644 index 000000000000..de7030ec1f90 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/fan.json @@ -0,0 +1,152 @@ +{ + "fans": [ + { + "name": "fan1", + "e2loc": {"bus": 3, "addr": 83, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": 2, + "bit": 0 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": 2, + "bit": 0 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/3-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/3-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan0_led", + "format": 6, + "mask": 11 + }, + "led_colors": { + "green": 9, + "red": 10, + "amber": 3 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan1_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": 23000 + } + ] + }, + { + "name": "fan2", + "e2loc": {"bus": 4, "addr": 83, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": 2, + "bit": 1 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": 2, + "bit": 1 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/4-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/4-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan1_led", + "format": 6, + "mask": 11 + }, + "led_colors": { + "green": 9, + "red": 10, + "amber": 3 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan2_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": 23000 + } + ] + }, + { + "name": "fan3", + "e2loc": {"bus": 3, "addr": 83, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": 2, + "bit": 2 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": 2, + "bit": 2 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/5-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/5-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan2_led", + "format": 6, + "mask": 11 + }, + "led_colors": { + "green": 9, + "red": 10, + "amber": 3 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan3_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": 23000 + } + ] + }, + { + "name": "fan4", + "e2loc": {"bus": 3, "addr": 83, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": 2, + "bit": 3 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": 2, + "bit": 3 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/6-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/6-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan3_led", + "format": 6, + "mask": 11 + }, + "led_colors":{ + "green": 9, + "red": 10, + "amber": 3 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan4_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": 23000 + } + ] + } + ] +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/psu.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/psu.json new file mode 100644 index 000000000000..c807b51fc4b6 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/psu.json @@ -0,0 +1,134 @@ +{ + "psus": [ + { + "name": "psu1", + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 0 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 1 + }, + "sn": {"loc": "/sys/bus/i2c/devices/7-0050/psu_sn"}, + "in_current": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/curr1_input", + "format": 4 + }, + "in_voltage": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/in1_input", + "format": 4 + }, + "out_voltage": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/in2_input", + "format": 4 + }, + "out_current": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/curr2_input", + "format": 4 + }, + "temperature": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/temp1_input", + "format": 4 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/7-0050/psu_hw"}, + "psu_type": {"loc": "/sys/bus/i2c/devices/7-0050/psu_type"}, + "fans": [ + { + "name": "psu_fan1", + "present": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/fan1_fault" + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 1 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/fan1_input" + }, + "speed_max": 28000 + } + ] + } + ], + "in_power": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/power1_input", + "format": 5 + }, + "out_power": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/power2_input", + "format": 5 + } + }, + { + "name": "psu2", + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 4 + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 5 + }, + "sn": {"loc": "/sys/bus/i2c/devices/8-0053/psu_sn"}, + "in_current": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/curr1_input", + "format": 4 + }, + "in_voltage": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/in1_input", + "format": 4 + }, + "out_voltage": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/in2_input", + "format": 4 + }, + "out_current": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/curr2_input", + "format": 4 + }, + "temperature": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/temp1_input", + "format": 4 + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/8-0053/psu_hw"}, + "psu_type": {"loc": "/sys/bus/i2c/devices/8-0053/psu_type"}, + "fans": [ + { + "name": "psu_fan1", + "present": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/fan1_fault" + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": 2, + "bit": 5 + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/fan1_input" + }, + "speed_max": 28000 + } + ] + } + ], + "in_power": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/power1_input", + "format": 5 + }, + "out_power": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/power2_input", + "format": 5 + } + } + ] +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/thermal.json b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/thermal.json new file mode 100644 index 000000000000..319336673534 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/sonic_platform_config/thermal.json @@ -0,0 +1,130 @@ +{"thermals": [ + { + "name": "INLET TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-0048/hwmon/*/temp1_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": null, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-0048/hwmon/*/temp1_input", + "format": 4 + } + }, + { + "name": "OUTLET TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-0049/hwmon/*/temp1_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": null, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-0049/hwmon/*/temp1_input", + "format": 4 + } + }, + { + "name": "BOARD TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-004a/hwmon/*/temp1_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": null, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-004a/hwmon/*/temp1_input", + "format": 4 + } + }, + { + "name": "PHYSICAL ID 0", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp1_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp1_crit", + "format": 4 + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp1_input", + "format": 4 + } + }, + { + "name": "CPU CORE 0", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp2_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp2_crit", + "format": 4 + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp2_input", + "format": 4 + } + }, + { + "name": "CPU CORE 1", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp3_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp3_crit", + "format": 4 + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp3_input", + "format": 4 + } + }, + { + "name": "CPU CORE 2", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp4_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp4_crit", + "format": 4 + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp4_input", + "format": 4 + } + }, + { + "name": "CPU CORE 3", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp5_max", + "format": 4 + }, + "low": null, + "crit_low": null, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp5_crit", + "format": 4 + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp5_input", + "format": 4 + } + } + ] +} \ No newline at end of file diff --git a/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/systest.py b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/systest.py new file mode 100644 index 000000000000..e1972959f951 --- /dev/null +++ b/device/ruijie/x86_64-ruijie_b6510-48vs8cq-r0/systest.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +""" +* onboard temperature sensors +* FAN trays +* PSU +""" +import time +import datetime +from monitor import status + +def doWork(): + a=[]; + ''' + return: [{'status': '1', 'hw_version': '1.00', 'errcode': 0, 'fan_type': 'M6510-FAN-F', 'errmsg': 'OK', 'Speed': '9778', 'id': 'fan1', 'present': '0', 'sn': '1000000000014'}, + {'id': 'fan2', 'errmsg': 'not present', 'errcode': -1}, + {'id': 'fan3', 'errmsg': 'not present', 'errcode': -1}, + {'id': 'fan4', 'errmsg': 'not present', 'errcode': -1} + ] + description: 1.get id + 2.errcode equal 0 : dev normal + not equal 0 : get errmsg + 3.other message add when all check success + ''' + status.checkFan(a) + #status.getTemp(a) + #status.getPsu(a) + + nowTime=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + print(nowTime) + print(a) +def run(interval): + while True: + try: + time_remaining = interval - time.time()%interval + time.sleep(time_remaining) + doWork() + except Exception as e: + print(e) + +if __name__ == '__main__': + interval = 1 + run(interval) diff --git a/device/virtual/x86_64-kvm_x86_64-r0/README.md b/device/virtual/x86_64-kvm_x86_64-r0/README.md new file mode 100644 index 000000000000..0347432d67b4 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/README.md @@ -0,0 +1,88 @@ +# Changing the virtual device + +You can control the hw sku and default factory configuration for the VS image +by modifying the content of the file default_sku in this directory. + +The format of default_sku is a single line: + +``` + +``` + +## Allowable values for hw_key + +| hw_key | Device | +| ------ | ------ | +| Force10-S6000 | Dell Force10 S6000| +| brcm_gearbox_vs | Similar to Force10-S6000, but implements a virtual BRCM81724 Gearbox Phy | + +## Allowable values for default_preset + +These include "t1", "l2", and "empty". See the file +sonic-buildimage/src/sonic-config-engine/config_samples.py for details on how +each default_preset value is interpreted. + +# Changing the hwsku of an existing VS switch + +To change the default hwsku for a VS image that has already been built and installed, follow these steps: + +- Edit /usr/share/sonic/device/x86_64-kvm_x86_64-r0/default_sku. For details, see the section below (Device Specific Documentation) +- Edit /etc/sonic/config_db.json, and change the "hwsku" key in DEVICE_METADATA:localhost to match the hw_key used in default_sku. Example: + + "DEVICE_METADATA": { + "localhost": { + ... + "hwsku": "brcm_gearbox_vs", + ... + } + }, + ... +- Reboot the switch +- Use "show platform summary" to verify, and follow any steps specific to the platform, as needed, such as those described below for the brcm_gearbox_vs hwsku. + +# Device Specific Documentation + +For general info on building, see https://github.com/Azure/sonic-buildimage/blob/master/README.md + +## Force-10-S6000 + +This is the default VS for SONiC. To enable, set contents of default_sku to: + +``` +Force10-S6000 t1 +``` + +To build: + +``` +make init +make configure PLATFORM=vs +make target/sonic-vs.img.gz +``` + +## brcm_gearbox_vs + +This sku simulates a device with a Broadcom BRCM81724 gearbox PHY. To enable, +set default_sku to: + + +``` +brcm_gearbox_vs t1 +``` + +To build (same as Force-10-S6000): + +``` +make init +make configure PLATFORM=vs +make target/sonic-vs.img.gz +``` + +To verify, install and bring up SONiC. There will be a new gbsyncd docker +which is designed to respond to configuration directed towards the gearbox phy +"switch". swss will create that gearbox switch on startup after detecting the +gearbox is present (this is done by a short lived gearsyncd that runs in the +swss docker). + +The commands "show gearbox interfaces status" and "show gearbox phys status" can be +used to verify the virtual gearbox phy has been created. See https://github.com/Azure/sonic-utilities/blob/master/doc/Command-Reference.md#gearbox for details. 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/brcm_gearbox_vs/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/buffers.json.j2 new file mode 100644 index 000000000000..b67cf577ab75 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/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/brcm_gearbox_vs/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/buffers_defaults_def.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/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/brcm_gearbox_vs/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/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/brcm_gearbox_vs/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..38e34eb571e8 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/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/brcm_gearbox_vs/context_config.json b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/context_config.json new file mode 100644 index 000000000000..9f9f80ba0d36 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/context_config.json @@ -0,0 +1,32 @@ +{ + "CONTEXTS": [ + { + "guid" : 0, + "name" : "sw0", + "dbAsic" : "ASIC_DB", + "dbCounters" : "COUNTERS_DB", + "dbFlex": "FLEX_COUNTER_DB", + "dbState" : "STATE_DB", + "switches": [ + { + "index" : 0, + "hwinfo" : "" + } + ] + }, + { + "guid" : 1, + "name" : "phy1", + "dbAsic" : "GB_ASIC_DB", + "dbCounters" : "GB_COUNTERS_DB", + "dbFlex": "GB_FLEX_COUNTER_DB", + "dbState" : "STATE_DB", + "switches": [ + { + "index" : 1, + "hwinfo" : "" + } + ] + } + ] +} diff --git a/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/gearbox_config.json b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/gearbox_config.json new file mode 100644 index 000000000000..2de95c4d806d --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/gearbox_config.json @@ -0,0 +1,38 @@ +{ + "phys": [ + { + "phy_id": 1, + "name": "sesto-1", + "address": "0x1000", + "lib_name": "libsai_phy_sesto-1.so", + "firmware_path": "/tmp/phy-sesto-1.bin", + "config_file": "/usr/share/sonic/hwsku/phy1_config_1.json", + "sai_init_config_file": "/usr/share/sonic/hwsku/sesto-1.bcm", + "phy_access": "mdio", + "bus_id": 0 + } + ], + "interfaces": [ + { + "name": "Ethernet0", + "index": 0, + "phy_id" : 1, + "system_lanes": [200,201], + "line_lanes": [206] + }, + { + "name": "Ethernet4", + "index": 1, + "phy_id" : 1, + "system_lanes": [202,203], + "line_lanes": [207] + }, + { + "name": "Ethernet8", + "index": 2, + "phy_id" : 1, + "system_lanes": [204,205], + "line_lanes": [208] + } + ] +} diff --git a/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/lanemap.ini new file mode 100644 index 000000000000..36278a01778c --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/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/brcm_gearbox_vs/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/pg_profile_lookup.ini new file mode 100644 index 000000000000..9f2eacb6fc42 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/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/brcm_gearbox_vs/phy1_config_1.json b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/phy1_config_1.json new file mode 100644 index 000000000000..1b81394e9936 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/phy1_config_1.json @@ -0,0 +1,168 @@ +{ + "lanes": [ + { + "index": 200, + "local_lane_id": 0, + "system_side": true, + "tx_polarity": 0, + "rx_polarity": 0, + "line_tx_lanemap": 0, + "line_rx_lanemap": 0, + "line_to_system_lanemap": 0, + "mdio_addr": "0x0200" + }, + { + "index": 201, + "local_lane_id": 0, + "system_side": true, + "tx_polarity": 0, + "rx_polarity": 0, + "line_tx_lanemap": 0, + "line_rx_lanemap": 0, + "line_to_system_lanemap": 0, + "mdio_addr": "0x0201" + }, + { + "index": 202, + "local_lane_id": 0, + "system_side": true, + "tx_polarity": 0, + "rx_polarity": 0, + "line_tx_lanemap": 0, + "line_rx_lanemap": 0, + "line_to_system_lanemap": 0, + "mdio_addr": "0x0202" + }, + { + "index": 203, + "local_lane_id": 0, + "system_side": true, + "tx_polarity": 0, + "rx_polarity": 0, + "line_tx_lanemap": 0, + "line_rx_lanemap": 0, + "line_to_system_lanemap": 0, + "mdio_addr": "0x0203" + }, + { + "index": 204, + "local_lane_id": 0, + "system_side": false, + "tx_polarity": 0, + "rx_polarity": 0, + "line_tx_lanemap": 0, + "line_rx_lanemap": 0, + "line_to_system_lanemap": 200, + "mdio_addr": "0x0204" + }, + { + "index": 205, + "local_lane_id": 0, + "system_side": false, + "tx_polarity": 0, + "rx_polarity": 0, + "line_tx_lanemap": 0, + "line_rx_lanemap": 0, + "line_to_system_lanemap": 202, + "mdio_addr": "0x0205" + }, + { + "index": 206, + "local_lane_id": 0, + "system_side": true, + "tx_polarity": 0, + "rx_polarity": 0, + "line_tx_lanemap": 0, + "line_rx_lanemap": 0, + "line_to_system_lanemap": 0, + "mdio_addr": "0x0206" + }, + { + "index": 207, + "local_lane_id": 0, + "system_side": false, + "tx_polarity": 0, + "rx_polarity": 0, + "line_tx_lanemap": 0, + "line_rx_lanemap": 0, + "line_to_system_lanemap": 0, + "mdio_addr": "0x0207" + }, + { + "index": 208, + "local_lane_id": 0, + "system_side": true, + "tx_polarity": 0, + "rx_polarity": 0, + "line_tx_lanemap": 0, + "line_rx_lanemap": 0, + "line_to_system_lanemap": 0, + "mdio_addr": "0x0208" + } + ], + "ports": [ + { + "index": 0, + "mdio_addr": "0x2000", + "system_speed": 20000, + "system_fec": "none", + "system_auto_neg": true, + "system_loopback": "none", + "system_training": false, + "line_speed": 40000, + "line_fec": "none", + "line_auto_neg": true, + "line_media_type": "fiber", + "line_intf_type": "none", + "line_loopback": "none", + "line_training": false, + "line_adver_speed": [], + "line_adver_fec": [], + "line_adver_auto_neg": false, + "line_adver_asym_pause": false, + "line_adver_media_type": "fiber" + }, + { + "index": 1, + "mdio_addr": "0x3000", + "system_speed": 20000, + "system_fec": "none", + "system_auto_neg": true, + "system_loopback": "none", + "system_training": false, + "line_speed": 40000, + "line_fec": "none", + "line_auto_neg": true, + "line_media_type": "fiber", + "line_intf_type": "none", + "line_loopback": "none", + "line_training": false, + "line_adver_speed": [], + "line_adver_fec": [], + "line_adver_auto_neg": false, + "line_adver_asym_pause": false, + "line_adver_media_type": "fiber" + }, + { + "index": 2, + "mdio_addr": "0x4000", + "system_speed": 20000, + "system_fec": "none", + "system_auto_neg": true, + "system_loopback": "none", + "system_training": false, + "line_speed": 40000, + "line_fec": "none", + "line_auto_neg": true, + "line_media_type": "fiber", + "line_intf_type": "none", + "line_loopback": "none", + "line_training": false, + "line_adver_speed": [], + "line_adver_fec": [], + "line_adver_auto_neg": false, + "line_adver_asym_pause": false, + "line_adver_media_type": "fiber" + } + ] +} diff --git a/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/port_config.ini new file mode 100644 index 000000000000..95cf5eec9e4e --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/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/brcm_gearbox_vs/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/sai.profile new file mode 100644 index 000000000000..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/sai.profile @@ -0,0 +1,3 @@ +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/brcm_gearbox_vs/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/td2-s6000-32x40G.config.bcm new file mode 100644 index 000000000000..4c94db7107c7 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/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/default_sku b/device/virtual/x86_64-kvm_x86_64-r0/default_sku new file mode 100644 index 000000000000..493e1989b662 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/default_sku @@ -0,0 +1 @@ +Force10-S6000 t1 diff --git a/device/virtual/x86_64-kvm_x86_64-r0/installer.conf b/device/virtual/x86_64-kvm_x86_64-r0/installer.conf new file mode 100644 index 000000000000..530ee964f330 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="swiotlb=65536" diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/0/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/0/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/0/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/0/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/0/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/0/lanemap.ini new file mode 100644 index 000000000000..d2b9e31ecadb --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/0/lanemap.ini @@ -0,0 +1,8 @@ +eth1:1,2,3,4 +eth2:5,6,7,8 +eth3:9,10,11,12 +eth4:13,14,15,16 +eth5:17,18,19,20 +eth6:21,22,23,24 +eth7:25,26,27,28 +eth8:29,30,31,32 diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/0/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/0/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/0/port_config.ini new file mode 100644 index 000000000000..8132f1c73dbf --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/0/port_config.ini @@ -0,0 +1,9 @@ +# name lanes alias index asic_port_name role +Ethernet0 1,2,3,4 Ethernet1/1 0 Eth0-ASIC0 Ext +Ethernet4 5,6,7,8 Ethernet1/2 1 Eth1-ASIC0 Ext +Ethernet8 9,10,11,12 Ethernet1/3 2 Eth2-ASIC0 Ext +Ethernet12 13,14,15,16 Ethernet1/4 3 Eth3-ASIC0 Ext +Ethernet-BP0 17,18,19,20 Eth4-ASIC0 0 Eth4-ASIC0 Int +Ethernet-BP4 21,22,23,24 Eth5-ASIC0 1 Eth5-ASIC0 Int +Ethernet-BP8 25,26,27,28 Eth6-ASIC0 2 Eth6-ASIC0 Int +Ethernet-BP12 29,30,31,32 Eth7-ASIC0 3 Eth7-ASIC0 Int diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/0/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/0/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/0/sai.profile new file mode 100644 index 000000000000..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/0/sai.profile @@ -0,0 +1,3 @@ +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_four_asic_vs/0/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/0/td2-s6000-32x40G.config.bcm new file mode 100644 index 000000000000..0e25b4d4232d --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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=10 +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_four_asic_vs/1/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/1/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/1/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/1/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/1/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/1/lanemap.ini new file mode 100644 index 000000000000..d2b9e31ecadb --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/1/lanemap.ini @@ -0,0 +1,8 @@ +eth1:1,2,3,4 +eth2:5,6,7,8 +eth3:9,10,11,12 +eth4:13,14,15,16 +eth5:17,18,19,20 +eth6:21,22,23,24 +eth7:25,26,27,28 +eth8:29,30,31,32 diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/1/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/1/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/1/port_config.ini new file mode 100644 index 000000000000..cf9982d91716 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/1/port_config.ini @@ -0,0 +1,9 @@ +# name lanes alias index asic_port_name role +Ethernet16 1,2,3,4 Ethernet1/5 4 Eth0-ASIC1 Ext +Ethernet20 5,6,7,8 Ethernet1/6 5 Eth1-ASIC1 Ext +Ethernet24 9,10,11,12 Ethernet1/7 6 Eth2-ASIC1 Ext +Ethernet28 13,14,15,16 Ethernet1/8 7 Eth3-ASIC1 Ext +Ethernet-BP16 17,18,19,20 Eth4-ASIC1 4 Eth4-ASIC1 Int +Ethernet-BP20 21,22,23,24 Eth5-ASIC1 5 Eth5-ASIC1 Int +Ethernet-BP24 25,26,27,28 Eth6-ASIC1 6 Eth6-ASIC1 Int +Ethernet-BP28 29,30,31,32 Eth7-ASIC1 7 Eth7-ASIC1 Int diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/1/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/1/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/1/sai.profile new file mode 100644 index 000000000000..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/1/sai.profile @@ -0,0 +1,3 @@ +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_four_asic_vs/1/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/1/td2-s6000-32x40G.config.bcm new file mode 100644 index 000000000000..0e25b4d4232d --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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=10 +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_four_asic_vs/2/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/2/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/2/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/2/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/2/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/2/lanemap.ini new file mode 100644 index 000000000000..d2b9e31ecadb --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/2/lanemap.ini @@ -0,0 +1,8 @@ +eth1:1,2,3,4 +eth2:5,6,7,8 +eth3:9,10,11,12 +eth4:13,14,15,16 +eth5:17,18,19,20 +eth6:21,22,23,24 +eth7:25,26,27,28 +eth8:29,30,31,32 diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/2/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/2/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/2/port_config.ini new file mode 100644 index 000000000000..a4361c7b78d6 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/2/port_config.ini @@ -0,0 +1,9 @@ +# name lanes alias index asic_port_name role +Ethernet-BP32 1,2,3,4 Eth0-ASIC2 8 Eth0-ASIC2 Int +Ethernet-BP36 5,6,7,8 Eth1-ASIC2 9 Eth1-ASIC2 Int +Ethernet-BP40 9,10,11,12 Eth2-ASIC2 10 Eth2-ASIC2 Int +Ethernet-BP44 13,14,15,16 Eth3-ASIC2 11 Eth3-ASIC2 Int +Ethernet-BP48 17,18,19,20 Eth4-ASIC2 12 Eth4-ASIC2 Int +Ethernet-BP52 21,22,23,24 Eth5-ASIC2 13 Eth5-ASIC2 Int +Ethernet-BP56 25,26,27,28 Eth6-ASIC2 14 Eth6-ASIC2 Int +Ethernet-BP60 29,30,31,32 Eth7-ASIC2 15 Eth7-ASIC2 Int diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/2/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/2/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/2/sai.profile new file mode 100644 index 000000000000..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/2/sai.profile @@ -0,0 +1,3 @@ +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_four_asic_vs/2/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/2/td2-s6000-32x40G.config.bcm new file mode 100644 index 000000000000..0e25b4d4232d --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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=10 +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_four_asic_vs/3/buffers.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/3/buffers_defaults_def.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/3/buffers_defaults_t0.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/3/buffers_defaults_t1.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/3/lanemap.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/3/lanemap.ini new file mode 100644 index 000000000000..d2b9e31ecadb --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/3/lanemap.ini @@ -0,0 +1,8 @@ +eth1:1,2,3,4 +eth2:5,6,7,8 +eth3:9,10,11,12 +eth4:13,14,15,16 +eth5:17,18,19,20 +eth6:21,22,23,24 +eth7:25,26,27,28 +eth8:29,30,31,32 diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/3/pg_profile_lookup.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/3/port_config.ini b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/3/port_config.ini new file mode 100644 index 000000000000..e97ded4527b3 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/3/port_config.ini @@ -0,0 +1,9 @@ +# name lanes alias index asic_port_name role +Ethernet-BP64 1,2,3,4 Eth0-ASIC3 16 Eth0-ASIC3 Int +Ethernet-BP68 5,6,7,8 Eth1-ASIC3 17 Eth1-ASIC3 Int +Ethernet-BP72 9,10,11,12 Eth2-ASIC3 18 Eth2-ASIC3 Int +Ethernet-BP76 13,14,15,16 Eth3-ASIC3 19 Eth3-ASIC3 Int +Ethernet-BP80 17,18,19,20 Eth4-ASIC3 20 Eth4-ASIC3 Int +Ethernet-BP84 21,22,23,24 Eth5-ASIC3 21 Eth5-ASIC3 Int +Ethernet-BP92 25,26,27,28 Eth6-ASIC3 22 Eth6-ASIC3 Int +Ethernet-BP96 29,30,31,32 Eth7-ASIC3 23 Eth7-ASIC3 Int diff --git a/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/3/qos.json.j2 b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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_four_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_four_asic_vs/3/sai.profile b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/3/sai.profile new file mode 100644 index 000000000000..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/3/sai.profile @@ -0,0 +1,3 @@ +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_four_asic_vs/3/td2-s6000-32x40G.config.bcm b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/3/td2-s6000-32x40G.config.bcm new file mode 100644 index 000000000000..0e25b4d4232d --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_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=10 +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_four_asic_vs/topology.sh b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/topology.sh new file mode 100755 index 000000000000..d7f370fdf39f --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_four_asic_vs/topology.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Topolgy script for 4 ASIC PLATFORM +# 2 frontend asic , 2 backend asic. +# 8 front-panel interfaces. +FIRST_FRONTEND_ASIC=0 +LAST_FRONTEND_ASIC=1 +FIRST_BACKEND_ASIC=2 +LAST_BACKEND_ASIC=3 +NUM_INTERFACES_PER_ASIC=8 + +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 4`; do + ORIG="eth$((4 * $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 too final interface name + sudo ip netns exec asic$ASIC ip link set dev $NEW mtu 9100 + 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 2`; do + FRONT_NAME="eth$((2 * $(($BACKEND - $FIRST_BACKEND_ASIC)) + $LINK + 4))" + BACK_NAME="eth$((2 * $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 dev $BACK_NAME mtu 9100 + sudo ip netns exec asic$BACKEND ip link set $BACK_NAME up + sudo ip netns exec asic$FRONTEND ip link set dev $FRONT_NAME mtu 9100 + 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 4`; do + TEMP="eth999" + OLD="eth$(($NUM))" + NAME="eth$((4 * $ASIC + $NUM))" + 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 4`; 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/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..3ec90708cc05 --- /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 asic_port_name role speed +Ethernet0 25,26,27,28 Ethernet1/1 0 Eth0-ASIC0 Ext 40000 +Ethernet4 29,30,31,32 Ethernet1/2 1 Eth1-ASIC0 Ext 40000 +Ethernet8 33,34,35,36 Ethernet1/3 2 Eth2-ASIC0 Ext 40000 +Ethernet12 37,38,39,40 Ethernet1/4 3 Eth3-ASIC0 Ext 40000 +Ethernet16 45,46,47,48 Ethernet1/5 4 Eth4-ASIC0 Ext 40000 +Ethernet20 41,42,43,44 Ethernet1/6 5 Eth5-ASIC0 Ext 40000 +Ethernet24 1,2,3,4 Ethernet1/7 6 Eth6-ASIC0 Ext 40000 +Ethernet28 5,6,7,8 Ethernet1/8 7 Eth7-ASIC0 Ext 40000 +Ethernet32 13,14,15,16 Ethernet1/9 8 Eth8-ASIC0 Ext 40000 +Ethernet36 9,10,11,12 Ethernet1/10 9 Eth9-ASIC0 Ext 40000 +Ethernet40 17,18,19,20 Ethernet1/11 10 Eth10-ASIC0 Ext 40000 +Ethernet44 21,22,23,24 Ethernet1/12 11 Eth11-ASIC0 Ext 40000 +Ethernet48 53,54,55,56 Ethernet1/13 12 Eth12-ASIC0 Ext 40000 +Ethernet52 49,50,51,52 Ethernet1/14 13 Eth13-ASIC0 Ext 40000 +Ethernet56 57,58,59,60 Ethernet1/15 14 Eth14-ASIC0 Ext 40000 +Ethernet60 61,62,63,64 Ethernet1/16 15 Eth15-ASIC0 Ext 40000 +Ethernet-BP0 69,70,71,72 Eth16-ASIC0 0 Eth16-ASIC0 Int 40000 +Ethernet-BP4 65,66,67,68 Eth17-ASIC0 1 Eth17-ASIC0 Int 40000 +Ethernet-BP8 73,74,75,76 Eth18-ASIC0 2 Eth18-ASIC0 Int 40000 +Ethernet-BP12 77,78,79,80 Eth19-ASIC0 3 Eth19-ASIC0 Int 40000 +Ethernet-BP16 109,110,111,112 Eth20-ASIC0 4 Eth20-ASIC0 Int 40000 +Ethernet-BP20 105,106,107,108 Eth21-ASIC0 5 Eth21-ASIC0 Int 40000 +Ethernet-BP24 113,114,115,116 Eth22-ASIC0 6 Eth22-ASIC0 Int 40000 +Ethernet-BP28 117,118,119,120 Eth23-ASIC0 7 Eth23-ASIC0 Int 40000 +Ethernet-BP32 125,126,127,128 Eth24-ASIC0 8 Eth24-ASIC0 Int 40000 +Ethernet-BP36 121,122,123,124 Eth25-ASIC0 9 Eth25-ASIC0 Int 40000 +Ethernet-BP40 81,82,83,84 Eth26-ASIC0 10 Eth26-ASIC0 Int 40000 +Ethernet-BP44 85,86,87,88 Eth27-ASIC0 11 Eth27-ASIC0 Int 40000 +Ethernet-BP48 93,94,95,96 Eth28-ASIC0 12 Eth28-ASIC0 Int 40000 +Ethernet-BP52 89,90,91,92 Eth29-ASIC0 13 Eth29-ASIC0 Int 40000 +Ethernet-BP56 101,102,103,104 Eth30-ASIC0 14 Eth30-ASIC0 Int 40000 +Ethernet-BP60 97,98,99,100 Eth31-ASIC0 15 Eth31-ASIC0 Int 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..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/0/sai.profile @@ -0,0 +1,3 @@ +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..0e25b4d4232d --- /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=10 +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..61d38693526e --- /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 asic_port_name role speed +Ethernet64 25,26,27,28 Ethernet1/17 16 Eth0-ASIC1 Ext 40000 +Ethernet68 29,30,31,32 Ethernet1/18 17 Eth1-ASIC1 Ext 40000 +Ethernet72 33,34,35,36 Ethernet1/19 18 Eth2-ASIC1 Ext 40000 +Ethernet76 37,38,39,40 Ethernet1/20 19 Eth3-ASIC1 Ext 40000 +Ethernet80 45,46,47,48 Ethernet1/21 20 Eth4-ASIC1 Ext 40000 +Ethernet84 41,42,43,44 Ethernet1/22 21 Eth5-ASIC1 Ext 40000 +Ethernet88 1,2,3,4 Ethernet1/23 22 Eth6-ASIC1 Ext 40000 +Ethernet92 5,6,7,8 Ethernet1/24 23 Eth7-ASIC1 Ext 40000 +Ethernet96 13,14,15,16 Ethernet1/25 24 Eth8-ASIC1 Ext 40000 +Ethernet100 9,10,11,12 Ethernet1/26 25 Eth9-ASIC1 Ext 40000 +Ethernet104 17,18,19,20 Ethernet1/27 26 Eth10-ASIC1 Ext 40000 +Ethernet108 21,22,23,24 Ethernet1/28 27 Eth11-ASIC1 Ext 40000 +Ethernet112 53,54,55,56 Ethernet1/29 28 Eth12-ASIC1 Ext 40000 +Ethernet116 49,50,51,52 Ethernet1/30 29 Eth13-ASIC1 Ext 40000 +Ethernet120 57,58,59,60 Ethernet1/31 30 Eth14-ASIC1 Ext 40000 +Ethernet124 61,62,63,64 Ethernet1/32 31 Eth15-ASIC1 Ext 40000 +Ethernet-BP64 69,70,71,72 Eth16-ASIC1 16 Eth16-ASIC1 Int 40000 +Ethernet-BP68 65,66,67,68 Eth17-ASIC1 17 Eth17-ASIC1 Int 40000 +Ethernet-BP72 73,74,75,76 Eth18-ASIC1 18 Eth18-ASIC1 Int 40000 +Ethernet-BP76 77,78,79,80 Eth19-ASIC1 19 Eth19-ASIC1 Int 40000 +Ethernet-BP80 109,110,111,112 Eth20-ASIC1 20 Eth20-ASIC1 Int 40000 +Ethernet-BP84 105,106,107,108 Eth21-ASIC1 21 Eth21-ASIC1 Int 40000 +Ethernet-BP88 113,114,115,116 Eth22-ASIC1 22 Eth22-ASIC1 Int 40000 +Ethernet-BP92 117,118,119,120 Eth23-ASIC1 23 Eth23-ASIC1 Int 40000 +Ethernet-BP96 125,126,127,128 Eth24-ASIC1 24 Eth24-ASIC1 Int 40000 +Ethernet-BP100 121,122,123,124 Eth25-ASIC1 25 Eth25-ASIC1 Int 40000 +Ethernet-BP104 81,82,83,84 Eth26-ASIC1 26 Eth26-ASIC1 Int 40000 +Ethernet-BP108 85,86,87,88 Eth27-ASIC1 27 Eth27-ASIC1 Int 40000 +Ethernet-BP112 93,94,95,96 Eth28-ASIC1 28 Eth28-ASIC1 Int 40000 +Ethernet-BP116 89,90,91,92 Eth29-ASIC1 29 Eth29-ASIC1 Int 40000 +Ethernet-BP120 101,102,103,104 Eth30-ASIC1 30 Eth30-ASIC1 Int 40000 +Ethernet-BP124 97,98,99,100 Eth31-ASIC1 31 Eth31-ASIC1 Int 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..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/1/sai.profile @@ -0,0 +1,3 @@ +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..0e25b4d4232d --- /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=10 +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..af8a37f09549 --- /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 asic_port_name role speed +Ethernet128 25,26,27,28 Ethernet1/33 32 Eth0-ASIC2 Ext 40000 +Ethernet132 29,30,31,32 Ethernet1/34 33 Eth1-ASIC2 Ext 40000 +Ethernet136 33,34,35,36 Ethernet1/35 34 Eth2-ASIC2 Ext 40000 +Ethernet140 37,38,39,40 Ethernet1/36 35 Eth3-ASIC2 Ext 40000 +Ethernet144 45,46,47,48 Ethernet1/37 36 Eth4-ASIC2 Ext 40000 +Ethernet148 41,42,43,44 Ethernet1/38 37 Eth5-ASIC2 Ext 40000 +Ethernet152 1,2,3,4 Ethernet1/39 38 Eth6-ASIC2 Ext 40000 +Ethernet156 5,6,7,8 Ethernet1/40 39 Eth7-ASIC2 Ext 40000 +Ethernet160 13,14,15,16 Ethernet1/41 40 Eth8-ASIC2 Ext 40000 +Ethernet164 9,10,11,12 Ethernet1/42 41 Eth9-ASIC2 Ext 40000 +Ethernet168 17,18,19,20 Ethernet1/43 42 Eth10-ASIC2 Ext 40000 +Ethernet172 21,22,23,24 Ethernet1/44 43 Eth11-ASIC2 Ext 40000 +Ethernet176 53,54,55,56 Ethernet1/45 44 Eth12-ASIC2 Ext 40000 +Ethernet180 49,50,51,52 Ethernet1/46 45 Eth13-ASIC2 Ext 40000 +Ethernet184 57,58,59,60 Ethernet1/47 46 Eth14-ASIC2 Ext 40000 +Ethernet188 61,62,63,64 Ethernet1/48 47 Eth15-ASIC2 Ext 40000 +Ethernet-BP128 69,70,71,72 Eth16-ASIC2 32 Eth16-ASIC2 Int 40000 +Ethernet-BP132 65,66,67,68 Eth17-ASIC2 33 Eth17-ASIC2 Int 40000 +Ethernet-BP136 73,74,75,76 Eth18-ASIC2 34 Eth18-ASIC2 Int 40000 +Ethernet-BP140 77,78,79,80 Eth19-ASIC2 35 Eth19-ASIC2 Int 40000 +Ethernet-BP144 109,110,111,112 Eth20-ASIC2 36 Eth20-ASIC2 Int 40000 +Ethernet-BP148 105,106,107,108 Eth21-ASIC2 37 Eth21-ASIC2 Int 40000 +Ethernet-BP152 113,114,115,116 Eth22-ASIC2 38 Eth22-ASIC2 Int 40000 +Ethernet-BP156 117,118,119,120 Eth23-ASIC2 39 Eth23-ASIC2 Int 40000 +Ethernet-BP160 125,126,127,128 Eth24-ASIC2 40 Eth24-ASIC2 Int 40000 +Ethernet-BP164 121,122,123,124 Eth25-ASIC2 41 Eth25-ASIC2 Int 40000 +Ethernet-BP168 81,82,83,84 Eth26-ASIC2 42 Eth26-ASIC2 Int 40000 +Ethernet-BP172 85,86,87,88 Eth27-ASIC2 43 Eth27-ASIC2 Int 40000 +Ethernet-BP176 93,94,95,96 Eth28-ASIC2 44 Eth28-ASIC2 Int 40000 +Ethernet-BP180 89,90,91,92 Eth29-ASIC2 45 Eth29-ASIC2 Int 40000 +Ethernet-BP184 101,102,103,104 Eth30-ASIC2 46 Eth30-ASIC2 Int 40000 +Ethernet-BP188 97,98,99,100 Eth31-ASIC2 47 Eth31-ASIC2 Int 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..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/2/sai.profile @@ -0,0 +1,3 @@ +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..0e25b4d4232d --- /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=10 +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..6e10b45cbc4c --- /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 asic_port_name role speed +Ethernet192 25,26,27,28 Ethernet1/49 48 Eth0-ASIC3 Ext 40000 +Ethernet196 29,30,31,32 Ethernet1/50 49 Eth1-ASIC3 Ext 40000 +Ethernet200 33,34,35,36 Ethernet1/51 50 Eth2-ASIC3 Ext 40000 +Ethernet204 37,38,39,40 Ethernet1/52 51 Eth3-ASIC3 Ext 40000 +Ethernet208 45,46,47,48 Ethernet1/53 52 Eth4-ASIC3 Ext 40000 +Ethernet212 41,42,43,44 Ethernet1/54 53 Eth5-ASIC3 Ext 40000 +Ethernet216 1,2,3,4 Ethernet1/55 54 Eth6-ASIC3 Ext 40000 +Ethernet220 5,6,7,8 Ethernet1/56 55 Eth7-ASIC3 Ext 40000 +Ethernet224 13,14,15,16 Ethernet1/57 56 Eth8-ASIC3 Ext 40000 +Ethernet228 9,10,11,12 Ethernet1/58 57 Eth9-ASIC3 Ext 40000 +Ethernet232 17,18,19,20 Ethernet1/59 58 Eth10-ASIC3 Ext 40000 +Ethernet236 21,22,23,24 Ethernet1/60 59 Eth11-ASIC3 Ext 40000 +Ethernet240 53,54,55,56 Ethernet1/61 60 Eth12-ASIC3 Ext 40000 +Ethernet244 49,50,51,52 Ethernet1/62 61 Eth13-ASIC3 Ext 40000 +Ethernet248 57,58,59,60 Ethernet1/63 62 Eth14-ASIC3 Ext 40000 +Ethernet252 61,62,63,64 Ethernet1/64 63 Eth15-ASIC3 Ext 40000 +Ethernet-BP192 69,70,71,72 Eth16-ASIC3 48 Eth16-ASIC3 Int 40000 +Ethernet-BP196 65,66,67,68 Eth17-ASIC3 49 Eth17-ASIC3 Int 40000 +Ethernet-BP200 73,74,75,76 Eth18-ASIC3 50 Eth18-ASIC3 Int 40000 +Ethernet-BP204 77,78,79,80 Eth19-ASIC3 51 Eth19-ASIC3 Int 40000 +Ethernet-BP208 109,110,111,112 Eth20-ASIC3 52 Eth20-ASIC3 Int 40000 +Ethernet-BP212 105,106,107,108 Eth21-ASIC3 53 Eth21-ASIC3 Int 40000 +Ethernet-BP216 113,114,115,116 Eth22-ASIC3 54 Eth22-ASIC3 Int 40000 +Ethernet-BP220 117,118,119,120 Eth23-ASIC3 55 Eth23-ASIC3 Int 40000 +Ethernet-BP224 125,126,127,128 Eth24-ASIC3 56 Eth24-ASIC3 Int 40000 +Ethernet-BP228 121,122,123,124 Eth25-ASIC3 57 Eth25-ASIC3 Int 40000 +Ethernet-BP232 81,82,83,84 Eth26-ASIC3 58 Eth26-ASIC3 Int 40000 +Ethernet-BP236 85,86,87,88 Eth27-ASIC3 59 Eth27-ASIC3 Int 40000 +Ethernet-BP240 93,94,95,96 Eth28-ASIC3 60 Eth28-ASIC3 Int 40000 +Ethernet-BP244 89,90,91,92 Eth29-ASIC3 61 Eth29-ASIC3 Int 40000 +Ethernet-BP248 101,102,103,104 Eth30-ASIC3 62 Eth30-ASIC3 Int 40000 +Ethernet-BP252 97,98,99,100 Eth31-ASIC3 63 Eth31-ASIC3 Int 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..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/3/sai.profile @@ -0,0 +1,3 @@ +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..0e25b4d4232d --- /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=10 +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..f6b9ccf3da98 --- /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 asic_port_name role speed +Ethernet-BP256 25,26,27,28 Eth0-ASIC4 64 Eth0-ASIC4 Int 40000 +Ethernet-BP260 29,30,31,32 Eth1-ASIC4 65 Eth1-ASIC4 Int 40000 +Ethernet-BP264 33,34,35,36 Eth2-ASIC4 66 Eth2-ASIC4 Int 40000 +Ethernet-BP268 37,38,39,40 Eth3-ASIC4 67 Eth3-ASIC4 Int 40000 +Ethernet-BP272 45,46,47,48 Eth4-ASIC4 68 Eth4-ASIC4 Int 40000 +Ethernet-BP276 41,42,43,44 Eth5-ASIC4 69 Eth5-ASIC4 Int 40000 +Ethernet-BP280 1,2,3,4 Eth6-ASIC4 70 Eth6-ASIC4 Int 40000 +Ethernet-BP284 5,6,7,8 Eth7-ASIC4 71 Eth7-ASIC4 Int 40000 +Ethernet-BP288 13,14,15,16 Eth8-ASIC4 72 Eth8-ASIC4 Int 40000 +Ethernet-BP292 9,10,11,12 Eth9-ASIC4 73 Eth9-ASIC4 Int 40000 +Ethernet-BP296 17,18,19,20 Eth10-ASIC4 74 Eth10-ASIC4 Int 40000 +Ethernet-BP300 21,22,23,24 Eth11-ASIC4 75 Eth11-ASIC4 Int 40000 +Ethernet-BP304 53,54,55,56 Eth12-ASIC4 76 Eth12-ASIC4 Int 40000 +Ethernet-BP308 49,50,51,52 Eth13-ASIC4 77 Eth13-ASIC4 Int 40000 +Ethernet-BP312 57,58,59,60 Eth14-ASIC4 78 Eth14-ASIC4 Int 40000 +Ethernet-BP316 61,62,63,64 Eth15-ASIC4 79 Eth15-ASIC4 Int 40000 +Ethernet-BP320 69,70,71,72 Eth16-ASIC4 80 Eth16-ASIC4 Int 40000 +Ethernet-BP324 65,66,67,68 Eth17-ASIC4 81 Eth17-ASIC4 Int 40000 +Ethernet-BP328 73,74,75,76 Eth18-ASIC4 82 Eth18-ASIC4 Int 40000 +Ethernet-BP332 77,78,79,80 Eth19-ASIC4 83 Eth19-ASIC4 Int 40000 +Ethernet-BP336 109,110,111,112 Eth20-ASIC4 84 Eth20-ASIC4 Int 40000 +Ethernet-BP340 105,106,107,108 Eth21-ASIC4 85 Eth21-ASIC4 Int 40000 +Ethernet-BP344 113,114,115,116 Eth22-ASIC4 86 Eth22-ASIC4 Int 40000 +Ethernet-BP348 117,118,119,120 Eth23-ASIC4 87 Eth23-ASIC4 Int 40000 +Ethernet-BP352 125,126,127,128 Eth24-ASIC4 88 Eth24-ASIC4 Int 40000 +Ethernet-BP356 121,122,123,124 Eth25-ASIC4 89 Eth25-ASIC4 Int 40000 +Ethernet-BP360 81,82,83,84 Eth26-ASIC4 90 Eth26-ASIC4 Int 40000 +Ethernet-BP364 85,86,87,88 Eth27-ASIC4 91 Eth27-ASIC4 Int 40000 +Ethernet-BP368 93,94,95,96 Eth28-ASIC4 92 Eth28-ASIC4 Int 40000 +Ethernet-BP372 89,90,91,92 Eth29-ASIC4 93 Eth29-ASIC4 Int 40000 +Ethernet-BP376 101,102,103,104 Eth30-ASIC4 94 Eth30-ASIC4 Int 40000 +Ethernet-BP380 97,98,99,100 Eth31-ASIC4 95 Eth31-ASIC4 Int 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..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/4/sai.profile @@ -0,0 +1,3 @@ +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..0e25b4d4232d --- /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=10 +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..96e863b87349 --- /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 asic_port_name role speed +Ethernet-BP384 25,26,27,28 Eth0-ASIC5 96 Eth0-ASIC5 Int 40000 +Ethernet-BP388 29,30,31,32 Eth1-ASIC5 97 Eth1-ASIC5 Int 40000 +Ethernet-BP392 33,34,35,36 Eth2-ASIC5 98 Eth2-ASIC5 Int 40000 +Ethernet-BP396 37,38,39,40 Eth3-ASIC5 99 Eth3-ASIC5 Int 40000 +Ethernet-BP400 45,46,47,48 Eth4-ASIC5 100 Eth4-ASIC5 Int 40000 +Ethernet-BP404 41,42,43,44 Eth5-ASIC5 101 Eth5-ASIC5 Int 40000 +Ethernet-BP408 1,2,3,4 Eth6-ASIC5 102 Eth6-ASIC5 Int 40000 +Ethernet-BP412 5,6,7,8 Eth7-ASIC5 103 Eth7-ASIC5 Int 40000 +Ethernet-BP416 13,14,15,16 Eth8-ASIC5 104 Eth8-ASIC5 Int 40000 +Ethernet-BP420 9,10,11,12 Eth9-ASIC5 105 Eth9-ASIC5 Int 40000 +Ethernet-BP424 17,18,19,20 Eth10-ASIC5 106 Eth10-ASIC5 Int 40000 +Ethernet-BP428 21,22,23,24 Eth11-ASIC5 107 Eth11-ASIC5 Int 40000 +Ethernet-BP432 53,54,55,56 Eth12-ASIC5 108 Eth12-ASIC5 Int 40000 +Ethernet-BP436 49,50,51,52 Eth13-ASIC5 109 Eth13-ASIC5 Int 40000 +Ethernet-BP440 57,58,59,60 Eth14-ASIC5 110 Eth14-ASIC5 Int 40000 +Ethernet-BP444 61,62,63,64 Eth15-ASIC5 111 Eth15-ASIC5 Int 40000 +Ethernet-BP448 69,70,71,72 Eth16-ASIC5 112 Eth16-ASIC5 Int 40000 +Ethernet-BP452 65,66,67,68 Eth17-ASIC5 113 Eth17-ASIC5 Int 40000 +Ethernet-BP456 73,74,75,76 Eth18-ASIC5 114 Eth18-ASIC5 Int 40000 +Ethernet-BP460 77,78,79,80 Eth19-ASIC5 115 Eth19-ASIC5 Int 40000 +Ethernet-BP464 109,110,111,112 Eth20-ASIC5 116 Eth20-ASIC5 Int 40000 +Ethernet-BP468 105,106,107,108 Eth21-ASIC5 117 Eth21-ASIC5 Int 40000 +Ethernet-BP472 113,114,115,116 Eth22-ASIC5 118 Eth22-ASIC5 Int 40000 +Ethernet-BP476 117,118,119,120 Eth23-ASIC5 119 Eth23-ASIC5 Int 40000 +Ethernet-BP480 125,126,127,128 Eth24-ASIC5 120 Eth24-ASIC5 Int 40000 +Ethernet-BP484 121,122,123,124 Eth25-ASIC5 121 Eth25-ASIC5 Int 40000 +Ethernet-BP488 81,82,83,84 Eth26-ASIC5 122 Eth26-ASIC5 Int 40000 +Ethernet-BP492 85,86,87,88 Eth27-ASIC5 123 Eth27-ASIC5 Int 40000 +Ethernet-BP496 93,94,95,96 Eth28-ASIC5 124 Eth28-ASIC5 Int 40000 +Ethernet-BP500 89,90,91,92 Eth29-ASIC5 125 Eth29-ASIC5 Int 40000 +Ethernet-BP504 101,102,103,104 Eth30-ASIC5 126 Eth30-ASIC5 Int 40000 +Ethernet-BP508 97,98,99,100 Eth31-ASIC5 127 Eth31-ASIC5 Int 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..0a2df177f1c5 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/5/sai.profile @@ -0,0 +1,3 @@ +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..0e25b4d4232d --- /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=10 +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..c4140ededb25 --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/msft_multi_asic_vs/topology.sh @@ -0,0 +1,85 @@ +#!/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 + # eth1 - eth16: asic0 + # eth17 - eth32: asic1 + # eth33 - eth48: asic2 + # eth49 - eth64: asic3 + 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 dev $NEW mtu 9100 + 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 dev $BACK_NAME mtu 9100 + sudo ip netns exec asic$BACKEND ip link set $BACK_NAME up + sudo ip netns exec asic$FRONTEND ip link set dev $FRONT_NAME mtu 9100 + 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$(($NUM))" + NAME="eth$((16 * $ASIC + $NUM))" + 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/device/virtual/x86_64-kvm_x86_64-r0/plugins/eeprom.py b/device/virtual/x86_64-kvm_x86_64-r0/plugins/eeprom.py new file mode 100644 index 000000000000..163c31ba20fc --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/plugins/eeprom.py @@ -0,0 +1,40 @@ +############################################################################# +# SONiC Virtual switch platform +# +############################################################################# + +class board(): + + def __init__(self, name, path, cpld_root, ro): + return + + def check_status(self): + return "ok" + + def is_checksum_valid(self, e): + return (True, 0) + + def read_eeprom(self): + return \ + """ +TLV Name Code Len Value +-------------------- ---- --- ----- +Product Name 0x21 5 SONiC +Part Number 0x22 6 000000 +Serial Number 0x23 20 0000000000000000000 +Base MAC Address 0x24 6 00:00:00:00:00:01 +Manufacture Date 0x25 19 10/19/2019 00:00:03 +Device Version 0x26 1 1 +Label Revision 0x27 3 A01 +Platform Name 0x28 20 x86_64-kvm_x86_64-r0 +ONIE Version 0x29 19 master-201811170418 +MAC Addresses 0x2A 2 16 +Vendor Name 0x2D 5 SONiC +""" + + def decode_eeprom(self, e): + print(e) + + def serial_number_str(self, e): + """Return service tag instead of serial number""" + return "000000" diff --git a/device/virtual/x86_64-kvm_x86_64-r0/pmon_daemon_control.json b/device/virtual/x86_64-kvm_x86_64-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..101db0ffea1a --- /dev/null +++ b/device/virtual/x86_64-kvm_x86_64-r0/pmon_daemon_control.json @@ -0,0 +1,8 @@ +{ + "skip_ledd": true, + "skip_xcvrd": true, + "skip_pcied": true, + "skip_psud": true, + "skip_syseepromd": true, + "skip_thermalctld": true +} diff --git a/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/port_config.ini b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/port_config.ini new file mode 100644 index 000000000000..578f59203d30 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias speed autoneg fec +Ethernet0 0 Ethernet0 25000 1 rs +Ethernet4 1 Ethernet4 25000 1 rs +Ethernet8 2 Ethernet8 25000 1 rs +Ethernet12 3 Ethernet12 25000 1 rs +Ethernet16 4 Ethernet16 25000 1 rs +Ethernet20 5 Ethernet20 25000 1 rs +Ethernet24 6 Ethernet24 25000 1 rs +Ethernet28 7 Ethernet28 25000 1 rs +Ethernet32 8 Ethernet32 25000 1 rs +Ethernet36 9 Ethernet36 25000 1 rs +Ethernet40 10 Ethernet40 25000 1 rs +Ethernet44 11 Ethernet44 25000 1 rs +Ethernet48 12 Ethernet48 25000 1 rs +Ethernet52 13 Ethernet52 25000 1 rs +Ethernet56 14 Ethernet56 25000 1 rs +Ethernet60 15 Ethernet60 25000 1 rs +Ethernet64 16 Ethernet64 25000 1 rs +Ethernet68 17 Ethernet68 25000 1 rs +Ethernet72 18 Ethernet72 25000 1 rs +Ethernet76 19 Ethernet76 25000 1 rs +Ethernet80 20 Ethernet80 25000 1 rs +Ethernet84 21 Ethernet84 25000 1 rs +Ethernet88 22 Ethernet88 25000 1 rs +Ethernet92 23 Ethernet92 25000 1 rs +Ethernet96 24 Ethernet96 25000 1 rs +Ethernet100 25 Ethernet100 25000 1 rs +Ethernet104 26 Ethernet104 25000 1 rs +Ethernet108 27 Ethernet108 25000 1 rs +Ethernet112 28 Ethernet112 25000 1 rs +Ethernet116 29 Ethernet116 25000 1 rs +Ethernet120 30 Ethernet120 25000 1 rs +Ethernet124 31 Ethernet124 25000 1 rs +Ethernet128 32 Ethernet128 25000 1 rs +Ethernet132 33 Ethernet132 25000 1 rs +Ethernet136 34 Ethernet136 25000 1 rs +Ethernet140 35 Ethernet140 25000 1 rs +Ethernet144 36 Ethernet144 25000 1 rs +Ethernet148 37 Ethernet148 25000 1 rs +Ethernet152 38 Ethernet152 25000 1 rs +Ethernet156 39 Ethernet156 25000 1 rs +Ethernet160 40 Ethernet160 25000 1 rs +Ethernet164 41 Ethernet164 25000 1 rs +Ethernet168 42 Ethernet168 25000 1 rs +Ethernet172 43 Ethernet172 25000 1 rs +Ethernet176 44 Ethernet176 25000 1 rs +Ethernet180 45 Ethernet180 25000 1 rs +Ethernet184 46 Ethernet184 25000 1 rs +Ethernet188 47 Ethernet188 25000 1 rs +Ethernet192 48,49,50,51 Ethernet192 100000 1 rs +Ethernet196 52,53,54,55 Ethernet196 100000 1 rs +Ethernet200 56,57,58,59 Ethernet200 100000 1 rs +Ethernet204 60,61,62,63 Ethernet204 100000 1 rs +Ethernet208 64,65,66,67 Ethernet208 100000 1 rs +Ethernet212 68,69,70,71 Ethernet212 100000 1 rs diff --git a/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-sai.conf b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-sai.conf new file mode 100644 index 000000000000..ae01f3ebe96a --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/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: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" + } + ], + "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", + "agent0": "lib/platform/x86_64-wnc_osw1800-r0/libpltfm_mgr.so", + "switchapi_port_add": false + } + ] +} diff --git a/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-tna-sai.conf b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-tna-sai.conf new file mode 100644 index 000000000000..7cb3ddc48fc9 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-tna-sai.conf @@ -0,0 +1,40 @@ +{ + "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, + "agent0": "lib/platform/x86_64-wnc_osw1800-r0/libpltfm_mgr.so", + "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/wnc/x86_64-wnc_osw1800-r0/default_sku b/device/wnc/x86_64-wnc_osw1800-r0/default_sku new file mode 100644 index 000000000000..0f663505d7a4 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/default_sku @@ -0,0 +1 @@ +OSW1800-48x6q t1 diff --git a/device/wnc/x86_64-wnc_osw1800-r0/fancontrol b/device/wnc/x86_64-wnc_osw1800-r0/fancontrol new file mode 100644 index 000000000000..d661bd11f1b2 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/fancontrol @@ -0,0 +1,11 @@ +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-5/5-0033 hwmon2=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-7/7-001e hwmon3=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-7/7-004e hwmon4=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-7/7-004f +DEVNAME=hwmon1=wnc_cpld3 hwmon2=tmp421 hwmon3=tmp75 hwmon4=tmp421 +FCTEMPS=hwmon1/pwm1=hwmon2/temp1_input hwmon1/pwm2=hwmon2/temp2_input hwmon1/pwm3=hwmon3/temp1_input hwmon1/pwm4=hwmon4/temp1_input hwmon1/pwm5=hwmon4/temp2_input +FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input hwmon1/pwm4=hwmon1/fan4_input hwmon1/pwm5=hwmon1/fan5_input +MINTEMP=hwmon1/pwm1=20 hwmon1/pwm2=20 hwmon1/pwm3=20 hwmon1/pwm4=20 hwmon1/pwm5=20 +MAXTEMP=hwmon1/pwm1=50 hwmon1/pwm2=50 hwmon1/pwm3=50 hwmon1/pwm4=50 hwmon1/pwm5=50 +MINSTART=hwmon1/pwm1=32 hwmon1/pwm2=32 hwmon1/pwm3=32 hwmon1/pwm4=32 hwmon1/pwm5=32 +MINSTOP=hwmon1/pwm1=22 hwmon1/pwm2=22 hwmon1/pwm3=22 hwmon1/pwm4=22 hwmon1/pwm5=22 +MINPWM=hwmon1/pwm1=10 hwmon1/pwm2=10 hwmon1/pwm3=10 hwmon1/pwm4=10 hwmon1/pwm5=10 +MAXPWM=hwmon1/pwm1=100 hwmon1/pwm2=100 hwmon1/pwm3=100 hwmon1/pwm4=100 hwmon1/pwm5=100 diff --git a/device/wnc/x86_64-wnc_osw1800-r0/installer.conf b/device/wnc/x86_64-wnc_osw1800-r0/installer.conf new file mode 100644 index 000000000000..dfa6df22689b --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=57600 diff --git a/device/wnc/x86_64-wnc_osw1800-r0/plugins/eeprom.py b/device/wnc/x86_64-wnc_osw1800-r0/plugins/eeprom.py new file mode 100644 index 000000000000..7c36371812ae --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/plugins/eeprom.py @@ -0,0 +1,18 @@ +try: + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-8/8-0052/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/wnc/x86_64-wnc_osw1800-r0/plugins/psuutil.py b/device/wnc/x86_64-wnc_osw1800-r0/plugins/psuutil.py new file mode 100644 index 000000000000..e62159c8a8cc --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/plugins/psuutil.py @@ -0,0 +1,64 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def get_num_psus(self): + return 2 + + def get_psu_status(self, index): + if index == 1: + psu_path = "/sys/bus/i2c/devices/6-0050/eeprom" + elif index == 2: + psu_path = "/sys/bus/i2c/devices/6-0051/eeprom" + else: + return False + + try: + data = open(psu_path, "rb") + except IOError: + return False + + result = int(data.read(1).encode("hex"), 16) + data.close() + + if result != 255 and result != 0: + return True + else: + return False + + def get_psu_presence(self, index): + if index == 1: + psu_path = "/sys/bus/i2c/devices/6-0050/eeprom" + elif index == 2: + psu_path = "/sys/bus/i2c/devices/6-0051/eeprom" + else: + return False + + try: + data = open(psu_path, "rb") + except IOError: + return False + + result = int(data.read(1).encode("hex"), 16) + data.close() + + if result != 255 and result != 0: + return True + else: + return False diff --git a/device/wnc/x86_64-wnc_osw1800-r0/plugins/sfputil.py b/device/wnc/x86_64-wnc_osw1800-r0/plugins/sfputil.py new file mode 100644 index 000000000000..ebb3d1c9bfa7 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/plugins/sfputil.py @@ -0,0 +1,213 @@ +#! /usr/bin/python +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase + import sys + sys.path.append('/usr/lib/python2.7/dist-packages/sonic_sfp/') + from sff8472 import sff8472InterfaceId + from sff8472 import sff8472Dom + from sff8436 import sff8436InterfaceId + from sff8436 import sff8436Dom +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 53 + PORTS_IN_BLOCK = 54 + + EEPROM_OFFSET = 11 + + _port_to_eeprom_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 list(range(self.PORT_START + 48, self.PORTS_IN_BLOCK)) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + bit_mask = port_num % 8 + + if port_num <= 7: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs1" + elif 8 <= port_num and port_num <= 15: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs2" + elif 16 <= port_num and port_num <= 23: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs3" + elif 24 <= port_num and port_num <= 27: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs4" + elif 28 <= port_num and port_num <= 31: + presence_path = "/sys/bus/i2c/devices/4-0032/sfp_mod_abs1" + bit_mask = bit_mask - 4 + elif 32 <= port_num and port_num <= 39: + presence_path = "/sys/bus/i2c/devices/4-0032/sfp_mod_abs2" + elif 40 <= port_num and port_num <= 47: + presence_path = "/sys/bus/i2c/devices/4-0032/sfp_mod_abs3" + elif 48 <= port_num and port_num <= 71: + presence_path = "/sys/bus/i2c/devices/4-0032/qsfp_modprs" + else: + return False + + try: + reg_file = open(presence_path, "rb") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + reg_file.close() + + if reg_value & (1 << bit_mask) == 0: + return True + else: + return False + + def get_low_power_mode(self, port_num): + if port_num in self.qsfp_ports: + bit_mask = port_num % 8 + else: + return False + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/qsfp_lpmode") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + reg_file.close() + + if reg_value & (1 << bit_mask) == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + if port_num in self.qsfp_ports: + bit_mask = port_num % 8 + else: + return False + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/qsfp_lpmode", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + + if lpmode is True: + reg_value = reg_value | (1 << bit_mask) + else: + reg_value = reg_value & ~(1 << bit_mask) + + reg_file.seek(0) + reg_file.write(str(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + if port_num in self.qsfp_ports: + bit_mask = (port_num % 8) + 2 + else: + return False + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/reset_control", "r+") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + reg_value = reg_value & ~(1 << bit_mask) + + reg_file.seek(0) + reg_file.write(str(reg_value)) + reg_file.close() + + time.sleep(1) + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/reset_control", "w") + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + reg_value = reg_value | (1 << bit_mask) + reg_file.seek(0) + reg_file.write(str(reg_value)) + reg_file.close() + + return True + + def get_eeprom_dict(self, port_num): + if not self.get_presence(port_num): + return None + + sfp_data = {} + + eeprom_ifraw = self.get_eeprom_raw(port_num) + eeprom_domraw = self.get_eeprom_dom_raw(port_num) + + if eeprom_ifraw is None: + return None + + if port_num in self.qsfp_ports: + sfpi_obj = sff8436InterfaceId(eeprom_ifraw) + if sfpi_obj is not None: + sfp_data['interface'] = sfpi_obj.get_data_pretty() + + sfpd_obj = sff8436Dom(eeprom_ifraw) + if sfpd_obj is not None: + sfp_data['dom'] = sfpd_obj.get_data_pretty() + return sfp_data + + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + if sfpi_obj is not None: + sfp_data['interface'] = sfpi_obj.get_data_pretty() + cal_type = sfpi_obj.get_calibration_type() + + if eeprom_domraw is not None: + sfpd_obj = sff8472Dom(eeprom_domraw, cal_type) + if sfpd_obj is not None: + sfp_data['dom'] = sfpd_obj.get_data_pretty() + + return sfp_data + + 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 diff --git a/device/wnc/x86_64-wnc_osw1800-r0/sensors.conf b/device/wnc/x86_64-wnc_osw1800-r0/sensors.conf new file mode 100644 index 000000000000..d91945ff722b --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/sensors.conf @@ -0,0 +1,33 @@ +# libsensors configuration filei +# -------------------------------------------------- +# + +bus "i2c-7" "i2c-2-mux" +chip "tmp421-i2c-7-1E" + label temp1 "ts1" + set temp1_max 50 + set temp1_max_hyst 25 + label temp2 "ts4" + set temp2_max 50 + set temp2_max_hyst 25 + +chip "tmp75-i2c-7-4E" + label temp1 "ts3" + set temp1_max 50 + set temp1_max_hyst 25 + +chip "tmp421-i2c-7-4F" + label temp1 "ts2" + set temp1_max 50 + set temp1_max_hyst 25 + label temp2 "ts5" + set temp2_max 50 + set temp2_max_hyst 25 + +bus "i2c-5" "i2c-2-mux" +chip "wnc_cpld3-i2c-5-33" + label fan1 "fan1" + label fan2 "fan2" + label fan3 "fan3" + label fan4 "fan4" + label fan5 "fan5" diff --git a/docker-bgp/Dockerfile b/docker-bgp/Dockerfile deleted file mode 100755 index 711e48fee206..000000000000 --- a/docker-bgp/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM debian:jessie - -## Set the apt source -COPY files/sources.list /etc/sources.list -RUN apt-get clean && apt-get update - -## Pre-install the fundamental packages -RUN apt-get -y install \ - rsyslog \ - python - -COPY deps /deps -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/quagga_*.deb - -ENTRYPOINT service rsyslog start \ - && service quagga start \ - && /bin/bash diff --git a/docker-database/Dockerfile b/docker-database/Dockerfile deleted file mode 100755 index e830385d4fb8..000000000000 --- a/docker-database/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM debian:jessie - -## Set the apt source -COPY files/sources.list /etc/sources.list -RUN apt-get clean && apt-get update - -## Pre-install the fundamental packages -RUN apt-get -y install \ - rsyslog \ - redis-server - -ENTRYPOINT service rsyslog start \ - && service redis-server start \ - && /bin/bash diff --git a/docker-lldp/Dockerfile b/docker-lldp/Dockerfile deleted file mode 100755 index 322a92f57ea3..000000000000 --- a/docker-lldp/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM debian:jessie - -## Set the apt source -COPY files/sources.list /etc/sources.list -RUN apt-get clean && apt-get update - -## Pre-install the fundamental packages -RUN apt-get -y install \ - rsyslog \ - lldpd - -COPY deps /deps - -## Install Python SSWSDK (lldpsyncd dependancy) -## Note: dpkg_apt function has the benefit to detect missing .deb file -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/python-sswsdk_*.deb -## Install LLDP Sync Daemon -## Note: dpkg_apt function has the benefit to detect missing .deb file -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/lldpsyncd_*.deb - -## Specify init as CMD to enable systemd -## Note: don't provide ENTRYPOINT at the same time -CMD ["/sbin/init"] diff --git a/docker-ptf/Dockerfile b/docker-ptf/Dockerfile deleted file mode 100644 index 6c35e524a91d..000000000000 --- a/docker-ptf/Dockerfile +++ /dev/null @@ -1,48 +0,0 @@ -FROM debian:jessie - -MAINTAINER Pavel Shirshov - -## Copy dependencies -COPY deps /root/deps - -## Make apt-get non-interactive -ENV DEBIAN_FRONTEND=noninteractive - -## Set the apt source, update package cache and install necessary packages -RUN echo "deb http://ftp.us.debian.org/debian/ jessie main contrib non-free" > /etc/apt/sources.list \ - && apt-get update \ - && apt-get upgrade -y \ - && apt-get dist-upgrade -y \ - && apt-get install -y --no-install-recommends \ - openssh-server \ - vim-tiny \ - python \ - python-scapy \ - net-tools \ - python-setuptools \ - supervisor \ - traceroute \ - lsof \ - tcpdump \ - && dpkg -i /root/deps/python-ptf_*.deb \ - && dpkg -i --force-depends /root/deps/libthrift-0.9.2_*.deb \ - && dpkg -i --force-depends /root/deps/python-thrift_*.deb \ - && apt-get -y install -f \ - && rm -rf /root/deps \ - && apt-get -y autoclean \ - && apt-get -y autoremove \ - && rm -rf /var/lib/apt/lists/* - -## Adjust sshd settings -RUN mkdir /var/run/sshd \ - && echo 'root:root' | chpasswd \ - && sed -ri 's/^PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config \ - && sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config \ - && sed -i '$aUseDNS no' /etc/ssh/sshd_config \ - && mkdir /root/deps - -COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf - -EXPOSE 22 - -ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/docker-snmp/Dockerfile b/docker-snmp/Dockerfile deleted file mode 100755 index 2afc5eddeee8..000000000000 --- a/docker-snmp/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM debian:jessie - -## Set the apt source -COPY files/sources.list /etc/sources.list -RUN apt-get clean && apt-get update - -## Pre-install the fundamental packages -RUN apt-get -y install \ - rsyslog \ - snmp \ - snmpd - -COPY deps /deps - -## Install Python SSWSDK (SNMP subagent dependancy) -## Note: dpkg_apt function has the benefit to detect missing .deb file -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/python-sswsdk_*.deb -## Install SNMP subagent -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/acs-snmp-subagent_*.deb - -## Specify init as CMD to enable systemd -## Note: don't provide ENTRYPOINT at the same time -CMD ["/sbin/init"] diff --git a/docker-sswsyncd/Dockerfile b/docker-sswsyncd/Dockerfile deleted file mode 100755 index d260f442b392..000000000000 --- a/docker-sswsyncd/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM debian:jessie - -## Set the apt source -COPY files/sources.list /etc/sources.list -RUN apt-get clean && apt-get update - -## Pre-install the fundamental packages -## TODO: sswsyncd depends on ifupdown -RUN apt-get -y install \ - ifupdown \ - rsyslog - -COPY deps /deps -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/libopennsl_*.deb -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/libsaibcm_*.deb -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/libsswsdk_*.deb -RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /deps/sswsyncd_*.deb - -ENTRYPOINT service rsyslog start \ - && service sswsyncd start \ - && /bin/bash diff --git a/dockers/docker-base-buster/Dockerfile.j2 b/dockers/docker-base-buster/Dockerfile.j2 new file mode 100644 index 000000000000..1f80775f11a4 --- /dev/null +++ b/dockers/docker-base-buster/Dockerfile.j2 @@ -0,0 +1,131 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +{% if CONFIGURED_ARCH == "armhf" %} +FROM multiarch/debian-debootstrap:armhf-buster +{% elif CONFIGURED_ARCH == "arm64" %} +FROM multiarch/debian-debootstrap:arm64-buster +{% else %} +FROM debian:buster +{% endif %} + +# Clean documentation in FROM image +RUN find /usr/share/doc -depth \( -type f -o -type l \) ! -name copyright | xargs rm || true + +# Clean doc directories that are empty or only contain empty directories +RUN while [ -n "$(find /usr/share/doc -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done && \ + rm -rf \ + /usr/share/man/* \ + /usr/share/groff/* \ + /usr/share/info/* \ + /usr/share/lintian/* \ + /usr/share/linda/* \ + /var/cache/man/* \ + /usr/share/locale/* + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Configure data sources for apt/dpkg +COPY ["dpkg_01_drop", "/etc/dpkg/dpkg.cfg.d/01_drop"] +{% if CONFIGURED_ARCH == "armhf" %} +COPY ["sources.list.armhf", "/etc/apt/sources.list"] +{% elif CONFIGURED_ARCH == "arm64" %} +COPY ["sources.list.arm64", "/etc/apt/sources.list"] +{% else %} +COPY ["sources.list", "/etc/apt/sources.list"] +{% endif %} +COPY ["no_install_recommend_suggest", "/etc/apt/apt.conf.d"] +COPY ["no-check-valid-until", "/etc/apt/apt.conf.d"] + +# Update apt cache and +# pre-install fundamental packages +RUN apt-get update && \ + apt-get -y install \ + curl \ + less \ + perl \ + procps \ + python3 \ + python3-distutils \ + python3-pip \ + rsyslog \ + vim-tiny \ +# Install dependencies of redis-tools + libatomic1 \ + libjemalloc2 \ + liblua5.1-0 \ + lua-bitop \ + lua-cjson \ +# common dependencies + libdaemon0 \ + libdbus-1-3 \ + libjansson4 \ +# ip and ifconfig utility missing in docker for arm arch + iproute2 \ + net-tools \ +# for processing/handling json files in bash environment + jq \ +# for sairedis zmq rpc channel + libzmq5 + +# Install redis-tools +{% if CONFIGURED_ARCH == "armhf" %} +RUN curl -k -o redis-tools_6.0.6-1~bpo10+1_armhf.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1_bpo10+1_armhf.deb?sv=2015-04-05&sr=b&sig=67vHAMxsl%2BS3X1KsqhdYhakJkGdg5FKSPgU8kUiw4as%3D&se=2030-10-24T04%3A22%3A40Z&sp=r" +RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_armhf.deb || apt-get install -f -y +RUN rm redis-tools_6.0.6-1~bpo10+1_armhf.deb +{% elif CONFIGURED_ARCH == "arm64" %} +RUN curl -o redis-tools_6.0.6-1~bpo10+1_arm64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1_bpo10+1_arm64.deb?sv=2015-04-05&sr=b&sig=GbkJV2wWln3hoz27zKi5erdk3NDKrAFrQriA97bcRCY%3D&se=2030-10-24T04%3A22%3A21Z&sp=r" +RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_arm64.deb || apt-get install -f -y +RUN rm redis-tools_6.0.6-1~bpo10+1_arm64.deb +{% else %} +RUN curl -o redis-tools_6.0.6-1~bpo10+1_amd64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1~bpo10+1_amd64.deb?sv=2015-04-05&sr=b&sig=73zbmjkf3pi%2Bn0R8Hy7CWT2EUvOAyzM5aLYJWCLySGM%3D&se=2030-09-06T19%3A44%3A59Z&sp=r" +RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_amd64.deb || apt-get install -f -y +RUN rm redis-tools_6.0.6-1~bpo10+1_amd64.deb +{% endif %} + +# Upgrade pip via PyPI and uninstall the Debian version +RUN pip3 install --upgrade pip +RUN apt-get purge -y python3-pip + +# setuptools and wheel are necessary for installing some Python wheel packages +RUN pip3 install --no-cache-dir setuptools==49.6.00 +RUN pip3 install --no-cache-dir wheel==0.35.1 + +# For templating +RUN pip3 install j2cli + +# Install supervisor +RUN pip3 install supervisor==4.2.1 + +# Add support for supervisord to handle startup dependencies +RUN pip3 install supervisord-dependent-startup==1.4.0 + +RUN mkdir -p /etc/supervisor /var/log/supervisor + +RUN apt-get -y purge \ + exim4 \ + exim4-base \ + exim4-config \ + exim4-daemon-light + +{% if docker_base_buster_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_base_buster_debs.split(' '), "/debs/") }} + +# Install built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_base_buster_debs.split(' ')) }} +{%- endif %} + +# Clean up apt +# Remove /var/lib/apt/lists/*, could be obsoleted for derived images +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /var/lib/apt/lists/* /tmp/* + +COPY ["etc/rsyslog.conf", "/etc/rsyslog.conf"] +COPY ["etc/rsyslog.d/*", "/etc/rsyslog.d/"] +COPY ["root/.vimrc", "/root/.vimrc"] + +RUN ln /usr/bin/vim.tiny /usr/bin/vim + +COPY ["etc/supervisor/supervisord.conf", "/etc/supervisor/"] diff --git a/dockers/docker-base-buster/LICENSE b/dockers/docker-base-buster/LICENSE new file mode 100644 index 000000000000..03d8f31e513c --- /dev/null +++ b/dockers/docker-base-buster/LICENSE @@ -0,0 +1,13 @@ +Copyright 2016 Microsoft, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +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. diff --git a/dockers/docker-base-buster/dpkg_01_drop b/dockers/docker-base-buster/dpkg_01_drop new file mode 100644 index 000000000000..d749943797d9 --- /dev/null +++ b/dockers/docker-base-buster/dpkg_01_drop @@ -0,0 +1,30 @@ +## Drop unnecessary files +## ref: https://wiki.ubuntu.com/ReducingDiskFootprint + +## Documentation +path-exclude /usr/share/doc/* +# we need to keep copyright files for legal reasons +path-include /usr/share/doc/*/copyright +path-exclude /usr/share/man/* +path-exclude /usr/share/groff/* +path-exclude /usr/share/info/* +# lintian stuff is small, but really unnecessary +path-exclude /usr/share/lintian/* +path-exclude /usr/share/linda/* + +## Translations +path-exclude /usr/share/locale/* + +## Landscape +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-buster/etc/rsyslog.conf b/dockers/docker-base-buster/etc/rsyslog.conf new file mode 100644 index 000000000000..ef249229ab1e --- /dev/null +++ b/dockers/docker-base-buster/etc/rsyslog.conf @@ -0,0 +1,76 @@ +# +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html + + +################# +#### MODULES #### +################# + +$ModLoad imuxsock # provides support for local system logging + +# +# Set a rate limit on messages from the container +# +$SystemLogRateLimitInterval 300 +$SystemLogRateLimitBurst 20000 + +#$ModLoad imklog # provides kernel logging support +#$ModLoad immark # provides --MARK-- message capability + +# provides UDP syslog reception +#$ModLoad imudp +#$UDPServerRun 514 + +# provides TCP syslog reception +#$ModLoad imtcp +#$InputTCPServerRun 514 + + +########################### +#### GLOBAL DIRECTIVES #### +########################### + +# Set remote syslog server +template (name="ForwardFormatInContainer" type="string" string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%") +*.* action(type="omfwd" target="127.0.0.1" port="514" protocol="udp" Template="ForwardFormatInContainer") + +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Define a custom template +$template SONiCFileFormat,"%TIMESTAMP%.%timestamp:::date-subseconds% %HOSTNAME% %syslogseverity-text:::uppercase% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" +$ActionFileDefaultTemplate SONiCFileFormat + +# +# Set the default permissions for all log files. +# +$FileOwner root +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 + +# +# Where to place spool and state files +# +$WorkDirectory /var/spool/rsyslog + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + +# +# Suppress duplicate messages and report "message repeated n times" +# +$RepeatedMsgReduction on + +############### +#### RULES #### +############### diff --git a/dockers/docker-base-buster/etc/rsyslog.d/supervisor.conf b/dockers/docker-base-buster/etc/rsyslog.d/supervisor.conf new file mode 100644 index 000000000000..fde8d8a6c994 --- /dev/null +++ b/dockers/docker-base-buster/etc/rsyslog.d/supervisor.conf @@ -0,0 +1,9 @@ +module(load="imfile" mode="inotify") # Ensure "inotify" mode is used +$WorkDirectory /var/log/supervisor +# Start Monitoring the file +input(type="imfile" + File="/var/log/supervisor/supervisord.log" + Tag="supervisord" + Severity="info" + Facility="local0" + PersistStateInterval="1") diff --git a/dockers/docker-base-buster/etc/supervisor/supervisord.conf b/dockers/docker-base-buster/etc/supervisor/supervisord.conf new file mode 100644 index 000000000000..6d7d7390e854 --- /dev/null +++ b/dockers/docker-base-buster/etc/supervisor/supervisord.conf @@ -0,0 +1,29 @@ +; supervisor config file + +[unix_http_server] +file=/var/run/supervisor.sock ; (the path to the socket file) +chmod=0700 ; socket file mode (default 0700) + +[supervisord] +logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) +pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) +childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) +user=root + +; the below section must remain in the config file for RPC +; (supervisorctl/web interface) to work, additional interfaces may be +; added by defining them in separate rpcinterface: sections +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket + +; The [include] section can just contain the "files" setting. This +; setting can list multiple files (separated by whitespace or +; newlines). It can also contain wildcards. The filenames are +; interpreted as relative to this file. Included files *cannot* +; include files themselves. + +[include] +files = /etc/supervisor/conf.d/*.conf diff --git a/dockers/docker-base-buster/no-check-valid-until b/dockers/docker-base-buster/no-check-valid-until new file mode 100644 index 000000000000..c7c25d017f7f --- /dev/null +++ b/dockers/docker-base-buster/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-buster/no_install_recommend_suggest b/dockers/docker-base-buster/no_install_recommend_suggest new file mode 100644 index 000000000000..b5bca577de1e --- /dev/null +++ b/dockers/docker-base-buster/no_install_recommend_suggest @@ -0,0 +1,5 @@ +# Instruct apt-get to NOT install "recommended" or "suggested" packages by +# default when installing a package. + +APT::Install-Recommends "false"; +APT::Install-Suggests "false"; diff --git a/dockers/docker-base-buster/root/.vimrc b/dockers/docker-base-buster/root/.vimrc new file mode 100644 index 000000000000..5c1ba8a04f47 --- /dev/null +++ b/dockers/docker-base-buster/root/.vimrc @@ -0,0 +1,2 @@ +" enable vim features +set nocompatible diff --git a/dockers/docker-base-buster/sources.list b/dockers/docker-base-buster/sources.list new file mode 100644 index 000000000000..0eef72d9fa2d --- /dev/null +++ b/dockers/docker-base-buster/sources.list @@ -0,0 +1,13 @@ +## Debian mirror on Microsoft Azure +## Ref: http://debian-archive.trafficmanager.net/ + +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ buster main contrib non-free +deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian/ buster main contrib non-free +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ buster/updates main contrib non-free +deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ buster/updates main contrib non-free +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ buster-backports main contrib non-free + +# Debian mirror supports multiple versions for a package +deb [arch=amd64] http://packages.trafficmanager.net/debian/debian buster main contrib non-free +deb [arch=amd64] http://packages.trafficmanager.net/debian/debian buster-updates main contrib non-free +deb [arch=amd64] http://packages.trafficmanager.net/debian/debian buster-backports main contrib non-free diff --git a/dockers/docker-base-buster/sources.list.arm64 b/dockers/docker-base-buster/sources.list.arm64 new file mode 100644 index 000000000000..6375734e99e6 --- /dev/null +++ b/dockers/docker-base-buster/sources.list.arm64 @@ -0,0 +1,11 @@ +## Debian mirror for ARM repo + +# ARM repo +deb [arch=arm64] http://deb.debian.org/debian buster main contrib non-free +deb-src [arch=arm64] http://deb.debian.org/debian buster main contrib non-free +deb [arch=arm64] http://security.debian.org buster/updates main contrib non-free +deb-src [arch=arm64] http://security.debian.org buster/updates main contrib non-free +deb [arch=arm64] http://deb.debian.org/debian/ buster-backports main contrib non-free +deb [arch=arm64] http://packages.trafficmanager.net/debian/debian buster main contrib non-free +deb [arch=arm64] http://packages.trafficmanager.net/debian/debian buster-updates main contrib non-free +deb [arch=arm64] http://packages.trafficmanager.net/debian/debian buster-backports main contrib non-free diff --git a/dockers/docker-base-buster/sources.list.armhf b/dockers/docker-base-buster/sources.list.armhf new file mode 100644 index 000000000000..a03af1a33ac0 --- /dev/null +++ b/dockers/docker-base-buster/sources.list.armhf @@ -0,0 +1,11 @@ +## Debian mirror for ARM repo + +# ARM repo +deb [arch=armhf] http://deb.debian.org/debian buster main contrib non-free +deb-src [arch=armhf] http://deb.debian.org/debian buster main contrib non-free +deb [arch=armhf] http://security.debian.org buster/updates main contrib non-free +deb-src [arch=armhf] http://security.debian.org buster/updates main contrib non-free +deb [arch=armhf] http://deb.debian.org/debian/ buster-backports main contrib non-free +deb [arch=armhf] http://packages.trafficmanager.net/debian/debian buster main contrib non-free +deb [arch=armhf] http://packages.trafficmanager.net/debian/debian buster-updates main contrib non-free +deb [arch=armhf] http://packages.trafficmanager.net/debian/debian buster-backports main contrib non-free diff --git a/dockers/docker-base-stretch/Dockerfile.j2 b/dockers/docker-base-stretch/Dockerfile.j2 new file mode 100644 index 000000000000..aa6eda8a955c --- /dev/null +++ b/dockers/docker-base-stretch/Dockerfile.j2 @@ -0,0 +1,127 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +{% if CONFIGURED_ARCH == "armhf" %} +FROM multiarch/debian-debootstrap:armhf-stretch +{% elif CONFIGURED_ARCH == "arm64" %} +FROM multiarch/debian-debootstrap:arm64-stretch +{% else %} +FROM debian:stretch +{% endif %} + +# Clean documentation in FROM image +RUN find /usr/share/doc -depth \( -type f -o -type l \) ! -name copyright | xargs rm || true + +# Clean doc directories that are empty or only contain empty directories +RUN while [ -n "$(find /usr/share/doc -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done && \ + rm -rf \ + /usr/share/man/* \ + /usr/share/groff/* \ + /usr/share/info/* \ + /usr/share/lintian/* \ + /usr/share/linda/* \ + /var/cache/man/* \ + /usr/share/locale/* + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Configure data sources for apt/dpkg +COPY ["dpkg_01_drop", "/etc/dpkg/dpkg.cfg.d/01_drop"] +{% if CONFIGURED_ARCH == "armhf" %} +COPY ["sources.list.armhf", "/etc/apt/sources.list"] +{% elif CONFIGURED_ARCH == "arm64" %} +COPY ["sources.list.arm64", "/etc/apt/sources.list"] +{% else %} +COPY ["sources.list", "/etc/apt/sources.list"] +{% endif %} +COPY ["no_install_recommend_suggest", "/etc/apt/apt.conf.d"] +COPY ["no-check-valid-until", "/etc/apt/apt.conf.d"] + +# Update apt cache and +# pre-install fundamental packages +RUN apt-get update && \ + apt-get -y install \ + curl \ + less \ + perl \ + procps \ + python \ + python-pip \ + vim-tiny \ +# Install redis-tools + redis-tools=5:5.0.3-3~bpo9+2 \ +# common dependencies + libpython2.7 \ + libdaemon0 \ + libdbus-1-3 \ + libjansson4 \ +# ip and ifconfig utility missing in docker for arm arch + iproute2 \ + net-tools \ +# for processing json files in bash environment + jq \ +# for sairedis zmq rpc channel + libzmq5 + +# Install a newer version of rsyslog from stretch-backports to support -iNONE +RUN apt-get -y -t stretch-backports install rsyslog + +# Install redis-tools + +{% if CONFIGURED_ARCH == "armhf" %} + RUN curl -o redis-tools_6.0.6-1~bpo10+1_armhf.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1_bpo10+1_armhf.deb?sv=2015-04-05&sr=b&sig=67vHAMxsl%2BS3X1KsqhdYhakJkGdg5FKSPgU8kUiw4as%3D&se=2030-10-24T04%3A22%3A40Z&sp=r" + RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_armhf.deb || apt-get install -f -y + RUN rm redis-tools_6.0.6-1~bpo10+1_armhf.deb +{% elif CONFIGURED_ARCH == "arm64" %} + RUN curl -o redis-tools_6.0.6-1~bpo10+1_arm64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1_bpo10+1_arm64.deb?sv=2015-04-05&sr=b&sig=GbkJV2wWln3hoz27zKi5erdk3NDKrAFrQriA97bcRCY%3D&se=2030-10-24T04%3A22%3A21Z&sp=r" + RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_arm64.deb || apt-get install -f -y + RUN rm redis-tools_6.0.6-1~bpo10+1_arm64.deb +{% else %} + RUN curl -o redis-tools_6.0.6-1~bpo10+1_amd64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1~bpo10+1_amd64.deb?sv=2015-04-05&sr=b&sig=73zbmjkf3pi%2Bn0R8Hy7CWT2EUvOAyzM5aLYJWCLySGM%3D&se=2030-09-06T19%3A44%3A59Z&sp=r" + RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_amd64.deb || apt-get install -f -y + RUN rm redis-tools_6.0.6-1~bpo10+1_amd64.deb +{% endif %} + +# Some Python packages require setuptools (or pkg_resources, which is supplied by setuptools) +# and some require wheel +RUN pip install setuptools==40.8.0 +RUN pip install wheel + +# For templating +RUN pip install j2cli + +# Install supervisor +RUN pip install supervisor>=3.4.0 + +# Add support for supervisord to handle startup dependencies +RUN pip install supervisord-dependent-startup==1.4.0 + +RUN mkdir -p /etc/supervisor /var/log/supervisor + +RUN apt-get -y purge \ + exim4 \ + exim4-base \ + exim4-config \ + exim4-daemon-light + +{% if docker_base_stretch_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_base_stretch_debs.split(' '), "/debs/") }} + +# Install built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_base_stretch_debs.split(' ')) }} +{%- endif %} + +# Clean up apt +# Remove /var/lib/apt/lists/*, could be obsoleted for derived images +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /var/lib/apt/lists/* /tmp/* + +COPY ["etc/rsyslog.conf", "/etc/rsyslog.conf"] +COPY ["etc/rsyslog.d/*", "/etc/rsyslog.d/"] +COPY ["root/.vimrc", "/root/.vimrc"] + +RUN ln /usr/bin/vim.tiny /usr/bin/vim + +COPY ["etc/supervisor/supervisord.conf", "/etc/supervisor/"] diff --git a/dockers/docker-base-stretch/LICENSE b/dockers/docker-base-stretch/LICENSE new file mode 100644 index 000000000000..03d8f31e513c --- /dev/null +++ b/dockers/docker-base-stretch/LICENSE @@ -0,0 +1,13 @@ +Copyright 2016 Microsoft, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +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. diff --git a/dockers/docker-base-stretch/dpkg_01_drop b/dockers/docker-base-stretch/dpkg_01_drop new file mode 100644 index 000000000000..d749943797d9 --- /dev/null +++ b/dockers/docker-base-stretch/dpkg_01_drop @@ -0,0 +1,30 @@ +## Drop unnecessary files +## ref: https://wiki.ubuntu.com/ReducingDiskFootprint + +## Documentation +path-exclude /usr/share/doc/* +# we need to keep copyright files for legal reasons +path-include /usr/share/doc/*/copyright +path-exclude /usr/share/man/* +path-exclude /usr/share/groff/* +path-exclude /usr/share/info/* +# lintian stuff is small, but really unnecessary +path-exclude /usr/share/lintian/* +path-exclude /usr/share/linda/* + +## Translations +path-exclude /usr/share/locale/* + +## Landscape +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/etc/rsyslog.conf b/dockers/docker-base-stretch/etc/rsyslog.conf new file mode 100644 index 000000000000..ef249229ab1e --- /dev/null +++ b/dockers/docker-base-stretch/etc/rsyslog.conf @@ -0,0 +1,76 @@ +# +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html + + +################# +#### MODULES #### +################# + +$ModLoad imuxsock # provides support for local system logging + +# +# Set a rate limit on messages from the container +# +$SystemLogRateLimitInterval 300 +$SystemLogRateLimitBurst 20000 + +#$ModLoad imklog # provides kernel logging support +#$ModLoad immark # provides --MARK-- message capability + +# provides UDP syslog reception +#$ModLoad imudp +#$UDPServerRun 514 + +# provides TCP syslog reception +#$ModLoad imtcp +#$InputTCPServerRun 514 + + +########################### +#### GLOBAL DIRECTIVES #### +########################### + +# Set remote syslog server +template (name="ForwardFormatInContainer" type="string" string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%") +*.* action(type="omfwd" target="127.0.0.1" port="514" protocol="udp" Template="ForwardFormatInContainer") + +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Define a custom template +$template SONiCFileFormat,"%TIMESTAMP%.%timestamp:::date-subseconds% %HOSTNAME% %syslogseverity-text:::uppercase% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" +$ActionFileDefaultTemplate SONiCFileFormat + +# +# Set the default permissions for all log files. +# +$FileOwner root +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 + +# +# Where to place spool and state files +# +$WorkDirectory /var/spool/rsyslog + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + +# +# Suppress duplicate messages and report "message repeated n times" +# +$RepeatedMsgReduction on + +############### +#### RULES #### +############### diff --git a/dockers/docker-base-stretch/etc/rsyslog.d/supervisor.conf b/dockers/docker-base-stretch/etc/rsyslog.d/supervisor.conf new file mode 100644 index 000000000000..fde8d8a6c994 --- /dev/null +++ b/dockers/docker-base-stretch/etc/rsyslog.d/supervisor.conf @@ -0,0 +1,9 @@ +module(load="imfile" mode="inotify") # Ensure "inotify" mode is used +$WorkDirectory /var/log/supervisor +# Start Monitoring the file +input(type="imfile" + File="/var/log/supervisor/supervisord.log" + Tag="supervisord" + Severity="info" + Facility="local0" + PersistStateInterval="1") diff --git a/dockers/docker-base-stretch/etc/supervisor/supervisord.conf b/dockers/docker-base-stretch/etc/supervisor/supervisord.conf new file mode 100644 index 000000000000..6d7d7390e854 --- /dev/null +++ b/dockers/docker-base-stretch/etc/supervisor/supervisord.conf @@ -0,0 +1,29 @@ +; supervisor config file + +[unix_http_server] +file=/var/run/supervisor.sock ; (the path to the socket file) +chmod=0700 ; socket file mode (default 0700) + +[supervisord] +logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) +pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) +childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) +user=root + +; the below section must remain in the config file for RPC +; (supervisorctl/web interface) to work, additional interfaces may be +; added by defining them in separate rpcinterface: sections +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket + +; The [include] section can just contain the "files" setting. This +; setting can list multiple files (separated by whitespace or +; newlines). It can also contain wildcards. The filenames are +; interpreted as relative to this file. Included files *cannot* +; include files themselves. + +[include] +files = /etc/supervisor/conf.d/*.conf 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-stretch/no_install_recommend_suggest b/dockers/docker-base-stretch/no_install_recommend_suggest new file mode 100644 index 000000000000..b5bca577de1e --- /dev/null +++ b/dockers/docker-base-stretch/no_install_recommend_suggest @@ -0,0 +1,5 @@ +# Instruct apt-get to NOT install "recommended" or "suggested" packages by +# default when installing a package. + +APT::Install-Recommends "false"; +APT::Install-Suggests "false"; diff --git a/dockers/docker-base-stretch/root/.vimrc b/dockers/docker-base-stretch/root/.vimrc new file mode 100644 index 000000000000..5c1ba8a04f47 --- /dev/null +++ b/dockers/docker-base-stretch/root/.vimrc @@ -0,0 +1,2 @@ +" enable vim features +set nocompatible diff --git a/dockers/docker-base-stretch/sources.list b/dockers/docker-base-stretch/sources.list new file mode 100644 index 000000000000..0c29b339bb87 --- /dev/null +++ b/dockers/docker-base-stretch/sources.list @@ -0,0 +1,11 @@ +## Debian mirror on Microsoft Azure +## Ref: http://debian-archive.trafficmanager.net/ + +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ stretch main contrib non-free +deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian/ stretch main contrib non-free +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ stretch/updates main contrib non-free +deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ stretch/updates main contrib non-free +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ stretch-backports main contrib non-free +deb [arch=amd64] http://packages.trafficmanager.net/debian/debian stretch main contrib non-free +deb [arch=amd64] http://packages.trafficmanager.net/debian/debian stretch-updates main contrib non-free +deb [arch=amd64] http://packages.trafficmanager.net/debian/debian stretch-backports main contrib non-free diff --git a/dockers/docker-base-stretch/sources.list.arm64 b/dockers/docker-base-stretch/sources.list.arm64 new file mode 100644 index 000000000000..520c46519919 --- /dev/null +++ b/dockers/docker-base-stretch/sources.list.arm64 @@ -0,0 +1,11 @@ +## Debian mirror for ARM repo + +# ARM repo +deb [arch=arm64] http://deb.debian.org/debian stretch main contrib non-free +deb-src [arch=arm64] http://deb.debian.org/debian stretch main contrib non-free +deb [arch=arm64] http://security.debian.org stretch/updates main contrib non-free +deb-src [arch=arm64] http://security.debian.org stretch/updates main contrib non-free +deb [arch=arm64] http://deb.debian.org/debian/ stretch-backports main contrib non-free +deb [arch=arm64] http://packages.trafficmanager.net/debian/debian stretch main contrib non-free +deb [arch=arm64] http://packages.trafficmanager.net/debian/debian stretch-updates main contrib non-free +deb [arch=arm64] http://packages.trafficmanager.net/debian/debian stretch-backports main contrib non-free diff --git a/dockers/docker-base-stretch/sources.list.armhf b/dockers/docker-base-stretch/sources.list.armhf new file mode 100644 index 000000000000..58077f310424 --- /dev/null +++ b/dockers/docker-base-stretch/sources.list.armhf @@ -0,0 +1,11 @@ +## Debian mirror for ARM repo + +# ARM repo +deb [arch=armhf] http://deb.debian.org/debian stretch main contrib non-free +deb-src [arch=armhf] http://deb.debian.org/debian stretch main contrib non-free +deb [arch=armhf] http://security.debian.org stretch/updates main contrib non-free +deb-src [arch=armhf] http://security.debian.org stretch/updates main contrib non-free +deb [arch=armhf] http://deb.debian.org/debian/ stretch-backports main contrib non-free +deb [arch=armhf] http://packages.trafficmanager.net/debian/debian stretch main contrib non-free +deb [arch=armhf] http://packages.trafficmanager.net/debian/debian stretch-updates main contrib non-free +deb [arch=armhf] http://packages.trafficmanager.net/debian/debian stretch-backports main contrib non-free diff --git a/dockers/docker-base/Dockerfile.j2 b/dockers/docker-base/Dockerfile.j2 new file mode 100644 index 000000000000..fc293da9da1e --- /dev/null +++ b/dockers/docker-base/Dockerfile.j2 @@ -0,0 +1,107 @@ +{% if CONFIGURED_ARCH == "armhf" %} +FROM multiarch/debian-debootstrap:armhf-jessie +{% elif CONFIGURED_ARCH == "arm64" %} +FROM multiarch/debian-debootstrap:arm64-jessie +{% else %} +FROM debian:jessie +{% endif %} + +## Remove retired jessie-updates repo +RUN sed -i '/http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + +# Clean documentation in FROM image +RUN find /usr/share/doc -depth \( -type f -o -type l \) ! -name copyright | xargs rm || true + +# Clean doc directories that are empty or only contain empty directories +RUN while [ -n "$(find /usr/share/doc -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done +RUN rm -rf \ + /usr/share/man/* \ + /usr/share/groff/* \ + /usr/share/info/* \ + /usr/share/lintian/* \ + /usr/share/linda/* \ + /var/cache/man/* \ + /usr/share/locale/* + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Configure data sources for apt/dpkg +COPY ["dpkg_01_drop", "/etc/dpkg/dpkg.cfg.d/01_drop"] +{% if CONFIGURED_ARCH == "armhf" %} +COPY ["sources.list.armhf", "/etc/apt/sources.list"] +{% elif CONFIGURED_ARCH == "arm64" %} +COPY ["sources.list.arm64", "/etc/apt/sources.list"] +COPY ["no-check-valid-until", "/etc/apt/apt.conf.d"] +{% else %} +COPY ["sources.list", "/etc/apt/sources.list"] +{% endif %} +COPY ["no_install_recommend_suggest", "/etc/apt/apt.conf.d"] +RUN apt-get update + +# Pre-install fundamental packages +RUN apt-get -y install \ + vim-tiny \ + perl \ + python \ + python-pip \ + rsyslog \ + less + +COPY ["etc/rsyslog.conf", "/etc/rsyslog.conf"] +COPY ["etc/rsyslog.d/*", "/etc/rsyslog.d/"] +COPY ["root/.vimrc", "/root/.vimrc"] + +RUN pip install --upgrade 'pip<21' +RUN apt-get purge -y python-pip + +# Some Python packages require setuptools (or pkg_resources, which is supplied by setuptools) +# and some require wheel +RUN pip install setuptools==40.8.0 +RUN pip install wheel + +# Install supervisor +RUN pip install supervisor>=3.4.0 + +RUN mkdir -p /etc/supervisor +RUN mkdir -p /var/log/supervisor + +COPY ["etc/supervisor/supervisord.conf", "/etc/supervisor/"] + +RUN apt-get -y purge \ + exim4 \ + exim4-base \ + exim4-config \ + exim4-daemon-light + +{% if docker_base_debs.strip() -%} +# Copy built Debian packages +{%- for deb in docker_base_debs.split(' ') %} +COPY debs/{{ deb }} debs/ +{%- endfor %} + +# Install built Debian packages and implicitly install their dependencies +{%- for deb in docker_base_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt debs/{{ deb }} +{%- endfor %} +{%- endif %} + +{% if docker_base_dbgs.strip() -%} +# Install common debug-packages +{%- for dbg_pkg in docker_base_dbgs.split(' ') %} +RUN apt-get -y install {{ dbg_pkg }} +{%- endfor %} +{% else %} +RUN ln /usr/bin/vim.tiny /usr/bin/vim +{%- endif %} + +# Remove python3.4 +# Note: if later python3 is required by more docker images, consider install homebrew python3 here instead of in SNMP image only +RUN apt-get purge -y libpython3.4-minimal + +# Clean up apt +# Remove /var/lib/apt/lists/*, could be obsoleted for derived images +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /var/lib/apt/lists/* + +RUN rm -rf /tmp/* diff --git a/dockers/docker-base/LICENSE b/dockers/docker-base/LICENSE new file mode 100644 index 000000000000..03d8f31e513c --- /dev/null +++ b/dockers/docker-base/LICENSE @@ -0,0 +1,13 @@ +Copyright 2016 Microsoft, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +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. diff --git a/dockers/docker-base/dpkg_01_drop b/dockers/docker-base/dpkg_01_drop new file mode 100644 index 000000000000..d749943797d9 --- /dev/null +++ b/dockers/docker-base/dpkg_01_drop @@ -0,0 +1,30 @@ +## Drop unnecessary files +## ref: https://wiki.ubuntu.com/ReducingDiskFootprint + +## Documentation +path-exclude /usr/share/doc/* +# we need to keep copyright files for legal reasons +path-include /usr/share/doc/*/copyright +path-exclude /usr/share/man/* +path-exclude /usr/share/groff/* +path-exclude /usr/share/info/* +# lintian stuff is small, but really unnecessary +path-exclude /usr/share/lintian/* +path-exclude /usr/share/linda/* + +## Translations +path-exclude /usr/share/locale/* + +## Landscape +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/etc/rsyslog.conf b/dockers/docker-base/etc/rsyslog.conf new file mode 100644 index 000000000000..4851ac784475 --- /dev/null +++ b/dockers/docker-base/etc/rsyslog.conf @@ -0,0 +1,80 @@ +############################################################################### +# Managed by Ansible +# file: ansible/roles/acs/templates/rsyslog.conf.j2 +############################################################################### +# +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html + + +################# +#### MODULES #### +################# + +$ModLoad imuxsock # provides support for local system logging + +# +# Set a rate limit on messages from the container +# +$SystemLogRateLimitInterval 300 +$SystemLogRateLimitBurst 20000 + +#$ModLoad imklog # provides kernel logging support +#$ModLoad immark # provides --MARK-- message capability + +# provides UDP syslog reception +#$ModLoad imudp +#$UDPServerRun 514 + +# provides TCP syslog reception +#$ModLoad imtcp +#$InputTCPServerRun 514 + + +########################### +#### GLOBAL DIRECTIVES #### +########################### + +# Set remote syslog server +template (name="ForwardFormatInContainer" type="string" string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%") +*.* action(type="omfwd" target="127.0.0.1" port="514" protocol="udp" Template="ForwardFormatInContainer") + +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Define a custom template +$template SONiCFileFormat,"%TIMESTAMP%.%timestamp:::date-subseconds% %HOSTNAME% %syslogseverity-text:::uppercase% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" +$ActionFileDefaultTemplate SONiCFileFormat + +# +# Set the default permissions for all log files. +# +$FileOwner root +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 + +# +# Where to place spool and state files +# +$WorkDirectory /var/spool/rsyslog + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + +# +# Suppress duplicate messages and report "message repeated n times" +# +$RepeatedMsgReduction on + +############### +#### RULES #### +############### diff --git a/dockers/docker-base/etc/rsyslog.d/supervisor.conf b/dockers/docker-base/etc/rsyslog.d/supervisor.conf new file mode 100644 index 000000000000..fde8d8a6c994 --- /dev/null +++ b/dockers/docker-base/etc/rsyslog.d/supervisor.conf @@ -0,0 +1,9 @@ +module(load="imfile" mode="inotify") # Ensure "inotify" mode is used +$WorkDirectory /var/log/supervisor +# Start Monitoring the file +input(type="imfile" + File="/var/log/supervisor/supervisord.log" + Tag="supervisord" + Severity="info" + Facility="local0" + PersistStateInterval="1") diff --git a/dockers/docker-base/etc/supervisor/supervisord.conf b/dockers/docker-base/etc/supervisor/supervisord.conf new file mode 100644 index 000000000000..5d1010e8fa4e --- /dev/null +++ b/dockers/docker-base/etc/supervisor/supervisord.conf @@ -0,0 +1,33 @@ +; supervisor config file + +[unix_http_server] +file=/var/run/supervisor.sock ; (the path to the socket file) +chmod=0700 ; socket file mode (default 0700) +username=dummy +password=dummy + +[supervisord] +logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) +pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) +childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) +user=root + +; the below section must remain in the config file for RPC +; (supervisorctl/web interface) to work, additional interfaces may be +; added by defining them in separate rpcinterface: sections +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket +username=dummy +password=dummy + +; The [include] section can just contain the "files" setting. This +; setting can list multiple files (separated by whitespace or +; newlines). It can also contain wildcards. The filenames are +; interpreted as relative to this file. Included files *cannot* +; include files themselves. + +[include] +files = /etc/supervisor/conf.d/*.conf 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-base/no_install_recommend_suggest b/dockers/docker-base/no_install_recommend_suggest new file mode 100644 index 000000000000..b5bca577de1e --- /dev/null +++ b/dockers/docker-base/no_install_recommend_suggest @@ -0,0 +1,5 @@ +# Instruct apt-get to NOT install "recommended" or "suggested" packages by +# default when installing a package. + +APT::Install-Recommends "false"; +APT::Install-Suggests "false"; diff --git a/dockers/docker-base/root/.vimrc b/dockers/docker-base/root/.vimrc new file mode 100644 index 000000000000..5c1ba8a04f47 --- /dev/null +++ b/dockers/docker-base/root/.vimrc @@ -0,0 +1,2 @@ +" enable vim features +set nocompatible diff --git a/dockers/docker-base/sources.list b/dockers/docker-base/sources.list new file mode 100644 index 000000000000..afdff92d3c72 --- /dev/null +++ b/dockers/docker-base/sources.list @@ -0,0 +1,7 @@ +## Debian mirror on Microsoft Azure +## Ref: http://debian-archive.trafficmanager.net/ + +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ jessie main contrib non-free +deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian/ jessie main contrib non-free +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ jessie/updates main contrib non-free +deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ jessie/updates main contrib non-free diff --git a/dockers/docker-base/sources.list.arm64 b/dockers/docker-base/sources.list.arm64 new file mode 100644 index 000000000000..a451be25fd73 --- /dev/null +++ b/dockers/docker-base/sources.list.arm64 @@ -0,0 +1,7 @@ +## Debian mirror for ARM repo + +# ARM64 repo +deb [arch=arm64] http://archive.debian.org/debian jessie main contrib non-free +deb-src [arch=arm64] http://archive.debian.org/debian jessie main contrib non-free +deb-src [arch=arm64] http://archive.debian.org/debian jessie-backports main contrib non-free +deb [arch=arm64] http://archive.debian.org/debian jessie-backports main contrib non-free diff --git a/dockers/docker-base/sources.list.armhf b/dockers/docker-base/sources.list.armhf new file mode 100644 index 000000000000..18f71fc31fcb --- /dev/null +++ b/dockers/docker-base/sources.list.armhf @@ -0,0 +1,7 @@ +## Debian mirror for ARM repo + +# ARMhf repo +deb [arch=armhf] http://deb.debian.org/debian jessie main contrib non-free +deb-src [arch=armhf] http://deb.debian.org/debian jessie main contrib non-free +deb [arch=armhf] http://security.debian.org jessie/updates main contrib non-free +deb-src [arch=armhf] http://security.debian.org jessie/updates main contrib non-free diff --git a/dockers/docker-basic_router/Dockerfile b/dockers/docker-basic_router/Dockerfile new file mode 100644 index 000000000000..5f579b53d6da --- /dev/null +++ b/dockers/docker-basic_router/Dockerfile @@ -0,0 +1,22 @@ +FROM docker-base + +MAINTAINER Xudong Wu + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +## Update apt's cache of available packages +RUN apt-get clean && apt-get update + +COPY deps /deps + +RUN dpkg -i /deps/libopennsl_*.deb; \ + dpkg -i /deps/libsaibcm_*.deb; \ + apt-get -y install -f + +RUN mv /deps/basic_router /usr/sbin/basic_router + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/dockers/docker-basic_router/start.sh b/dockers/docker-basic_router/start.sh new file mode 100755 index 000000000000..a4d378ef77d9 --- /dev/null +++ b/dockers/docker-basic_router/start.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd diff --git a/dockers/docker-basic_router/supervisord.conf b/dockers/docker-basic_router/supervisord.conf new file mode 100644 index 000000000000..bfa84fdcdfb5 --- /dev/null +++ b/dockers/docker-basic_router/supervisord.conf @@ -0,0 +1,20 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[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=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/dockers/docker-config-engine-buster/Dockerfile.j2 b/dockers/docker-config-engine-buster/Dockerfile.j2 new file mode 100644 index 000000000000..3022546a068c --- /dev/null +++ b/dockers/docker-config-engine-buster/Dockerfile.j2 @@ -0,0 +1,52 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-base-buster + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && \ + apt-get install -y \ + apt-utils \ + build-essential \ + python3-dev + +{%- if CONFIGURED_ARCH == "armhf" or CONFIGURED_ARCH == "arm64" %} +RUN apt-get install -y \ + libxslt-dev \ + libz-dev +{%- endif %} + +# For sonic-config-engine Python 3 package +# Explicitly install pyangbind here, as pyangbind causes enum34 to be installed. +# enum34 causes Python 're' package to not work properly as it redefines an incompatible enum.py module +# https://github.com/robshakir/pyangbind/issues/232 +RUN pip3 install pyangbind==0.8.1 +RUN pip3 uninstall -y enum34 + +{% if docker_config_engine_buster_debs.strip() %} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_config_engine_buster_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_config_engine_buster_debs.split(' ')) }} +{% endif %} + +{% if docker_config_engine_buster_whls.strip() %} +# Copy locally-built Python wheel dependencies +{{ copy_files("python-wheels/", docker_config_engine_buster_whls.split(' '), "/python-wheels/") }} + +# Install locally-built Python wheel dependencies +{{ install_python_wheels(docker_config_engine_buster_whls.split(' ')) }} +{% endif %} + +# Copy files +COPY ["files/swss_vars.j2", "/usr/share/sonic/templates/"] + +## Clean up +RUN apt-get purge -y \ + python3-dev \ + build-essential && \ + apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs /python-wheels diff --git a/dockers/docker-config-engine-stretch/Dockerfile.j2 b/dockers/docker-config-engine-stretch/Dockerfile.j2 new file mode 100644 index 000000000000..813f41bc296b --- /dev/null +++ b/dockers/docker-config-engine-stretch/Dockerfile.j2 @@ -0,0 +1,45 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-base-stretch + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && \ + apt-get install -y \ + # Dependencies for sonic-cfggen + build-essential \ + python-dev + +{%- if CONFIGURED_ARCH == "armhf" or CONFIGURED_ARCH == "arm64" %} +RUN apt-get install -y \ + libxslt-dev \ + libz-dev +{%- endif %} + +{% if docker_config_engine_stretch_debs.strip() %} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_config_engine_stretch_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_config_engine_stretch_debs.split(' ')) }} +{% endif %} + +{% if docker_config_engine_stretch_whls.strip() %} +# Copy locally-built Python wheel dependencies +{{ copy_files("python-wheels/", docker_config_engine_stretch_whls.split(' '), "/python-wheels/") }} + +# Install locally-built Python wheel dependencies +{{ install_python_wheels(docker_config_engine_stretch_whls.split(' ')) }} +{% endif %} + +# Copy files +COPY ["files/swss_vars.j2", "/usr/share/sonic/templates/"] + +## Clean up +RUN apt-get purge -y \ + build-essential \ + python-dev && \ + apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs /python-wheels diff --git a/dockers/docker-config-engine/Dockerfile.j2 b/dockers/docker-config-engine/Dockerfile.j2 new file mode 100644 index 000000000000..8790ba67d7f9 --- /dev/null +++ b/dockers/docker-config-engine/Dockerfile.j2 @@ -0,0 +1,46 @@ +FROM docker-base + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +# Dependencies for sonic-cfggen +RUN apt-get install -y build-essential python-dev + +{% if docker_config_engine_debs.strip() %} +COPY \ +{% for deb in docker_config_engine_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ +{%- endif -%} + +{% if docker_config_engine_debs.strip() %} +RUN dpkg -i \ +{% for deb in docker_config_engine_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} +{%- endif -%} + +{% if docker_config_engine_whls.strip() %} +COPY \ +{% for whl in docker_config_engine_whls.split(' ') -%} +python-wheels/{{ whl }}{{' '}} +{%- endfor -%} +python-wheels/ +{%- endif -%} + +{% if docker_config_engine_whls.strip() %} +RUN pip install \ +{% for whl in docker_config_engine_whls.split(' ') -%} +python-wheels/{{ whl }}{{' '}} +{%- endfor %} +{%- endif -%} + +# Copy files +COPY ["files/swss_vars.j2", "/usr/share/sonic/templates/"] + +## Clean up +RUN apt-get purge -y build-essential python-dev; apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs /python-wheels diff --git a/dockers/docker-database/Dockerfile.j2 b/dockers/docker-database/Dockerfile.j2 new file mode 100644 index 000000000000..aef22e24379c --- /dev/null +++ b/dockers/docker-database/Dockerfile.j2 @@ -0,0 +1,63 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +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 + +# Update apt's cache of available packages +RUN apt-get update + +# Install redis-server +{% if CONFIGURED_ARCH == "armhf" %} +RUN curl -k -o redis-tools_6.0.6-1~bpo10+1_armhf.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1_bpo10+1_armhf.deb?sv=2015-04-05&sr=b&sig=67vHAMxsl%2BS3X1KsqhdYhakJkGdg5FKSPgU8kUiw4as%3D&se=2030-10-24T04%3A22%3A40Z&sp=r" +RUN curl -k -o redis-server_6.0.6-1~bpo10+1_armhf.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-server_6.0.6-1_bpo10+1_armhf.deb?sv=2015-04-05&sr=b&sig=xTdayvm0RBguxi9suyv855jKRjU%2FmKQ8nHuct4WSX%2FA%3D&se=2030-10-24T04%3A22%3A05Z&sp=r" +RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_armhf.deb redis-server_6.0.6-1~bpo10+1_armhf.deb || apt-get install -f +RUN rm redis-tools_6.0.6-1~bpo10+1_armhf.deb redis-server_6.0.6-1~bpo10+1_armhf.deb +{% elif CONFIGURED_ARCH == "arm64" %} +RUN curl -o redis-tools_6.0.6-1~bpo10+1_arm64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1_bpo10+1_arm64.deb?sv=2015-04-05&sr=b&sig=GbkJV2wWln3hoz27zKi5erdk3NDKrAFrQriA97bcRCY%3D&se=2030-10-24T04%3A22%3A21Z&sp=r" +RUN curl -o redis-server_6.0.6-1~bpo10+1_arm64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-server_6.0.6-1_bpo10+1_arm64.deb?sv=2015-04-05&sr=b&sig=622w2KzIKIjAaaA0Bz12MzU%2BUBzY2AiXFIFfuKNoKSk%3D&se=2030-10-24T04%3A21%3A44Z&sp=r" +RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_arm64.deb redis-server_6.0.6-1~bpo10+1_arm64.deb || apt-get install -f +RUN rm redis-tools_6.0.6-1~bpo10+1_arm64.deb redis-server_6.0.6-1~bpo10+1_arm64.deb +{% else %} +RUN curl -o redis-tools_6.0.6-1~bpo10+1_amd64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1~bpo10+1_amd64.deb?sv=2015-04-05&sr=b&sig=73zbmjkf3pi%2Bn0R8Hy7CWT2EUvOAyzM5aLYJWCLySGM%3D&se=2030-09-06T19%3A44%3A59Z&sp=r" +RUN curl -o redis-server_6.0.6-1~bpo10+1_amd64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-server_6.0.6-1~bpo10+1_amd64.deb?sv=2015-04-05&sr=b&sig=2Ketg7BmkZEaTxR%2FgvAFVmhjn7ywdmkc7l2T2rsL57o%3D&se=2030-09-06T19%3A45%3A20Z&sp=r" +RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_amd64.deb redis-server_6.0.6-1~bpo10+1_amd64.deb || apt-get install -f +RUN rm redis-tools_6.0.6-1~bpo10+1_amd64.deb redis-server_6.0.6-1~bpo10+1_amd64.deb +{% endif %} + +{% if docker_database_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_database_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_database_debs.split(' ')) }} +{%- endif %} + +# Clean up +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs ~/.cache && \ + sed -ri 's/^(save .*$)/# \1/g; \ + s/^daemonize yes$/daemonize no/; \ + s/^logfile .*$/logfile ""/; \ + s/^# syslog-enabled no$/syslog-enabled no/; \ + s/^# unixsocket/unixsocket/; \ + s/redis-server.sock/redis.sock/g; \ + s/^client-output-buffer-limit pubsub [0-9]+mb [0-9]+mb [0-9]+/client-output-buffer-limit pubsub 0 0 0/ \ + ' /etc/redis/redis.conf + +COPY ["supervisord.conf.j2", "/usr/share/sonic/templates/"] +COPY ["docker-database-init.sh", "/usr/local/bin/"] +COPY ["database_config.json.j2", "/usr/share/sonic/templates/"] +COPY ["database_global.json.j2", "/usr/share/sonic/templates/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["files/sysctl-net.conf", "/etc/sysctl.d/"] +COPY ["critical_processes", "/etc/supervisor"] +COPY ["files/update_chassisdb_config", "/usr/local/bin/"] +COPY ["flush_unused_database", "/usr/local/bin/"] + +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..47c9d1b2d47f --- /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 program database|redis_server with path "/usr/bin/process_checker database /usr/bin/redis-server" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/dockers/docker-database/base_image_files/redis-cli b/dockers/docker-database/base_image_files/redis-cli new file mode 100755 index 000000000000..6ce1951cd4b9 --- /dev/null +++ b/dockers/docker-database/base_image_files/redis-cli @@ -0,0 +1,10 @@ +#!/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 database redis-cli "$@" diff --git a/dockers/docker-database/critical_processes b/dockers/docker-database/critical_processes new file mode 100644 index 000000000000..53a45931dfc9 --- /dev/null +++ b/dockers/docker-database/critical_processes @@ -0,0 +1 @@ +program:redis diff --git a/dockers/docker-database/database_config.json.j2 b/dockers/docker-database/database_config.json.j2 new file mode 100644 index 000000000000..5ad730f10015 --- /dev/null +++ b/dockers/docker-database/database_config.json.j2 @@ -0,0 +1,94 @@ +{ + "INSTANCES": { + "redis":{ + "hostname" : "{{HOST_IP}}", + "port" : 6379, + "unix_socket_path" : "/var/run/redis{{NAMESPACE_ID}}/redis.sock", + "persistence_for_warm_boot" : "yes" + }, + "redis_chassis":{ + "hostname" : "redis_chassis.server", + "port": 6380, + "unix_socket_path": "/var/run/redis-chassis/redis_chassis.sock", + "persistence_for_warm_boot" : "yes" + } + }, + "DATABASES" : { + "APPL_DB" : { + "id" : 0, + "separator": ":", + "instance" : "redis" + }, + "ASIC_DB" : { + "id" : 1, + "separator": ":", + "instance" : "redis" + }, + "COUNTERS_DB" : { + "id" : 2, + "separator": ":", + "instance" : "redis" + }, + "LOGLEVEL_DB" : { + "id" : 3, + "separator": ":", + "instance" : "redis" + }, + "CONFIG_DB" : { + "id" : 4, + "separator": "|", + "instance" : "redis" + }, + "PFC_WD_DB" : { + "id" : 5, + "separator": ":", + "instance" : "redis" + }, + "FLEX_COUNTER_DB" : { + "id" : 5, + "separator": ":", + "instance" : "redis" + }, + "STATE_DB" : { + "id" : 6, + "separator": "|", + "instance" : "redis" + }, + "SNMP_OVERLAY_DB" : { + "id" : 7, + "separator": "|", + "instance" : "redis" + }, + "RESTAPI_DB" : { + "id" : 8, + "separator": "|", + "instance" : "redis" + }, + "GB_ASIC_DB" : { + "id" : 9, + "separator": "|", + "instance" : "redis" + }, + "GB_COUNTERS_DB" : { + "id" : 10, + "separator": "|", + "instance" : "redis" + }, + "GB_FLEX_COUNTER_DB" : { + "id" : 11, + "separator": "|", + "instance" : "redis" + }, + "CHASSIS_APP_DB" : { + "id" : 12, + "separator": "|", + "instance" : "redis_chassis" + }, + "CHASSIS_STATE_DB" : { + "id" : 13, + "separator": "|", + "instance" : "redis_chassis" + } + }, + "VERSION" : "1.0" +} diff --git a/dockers/docker-database/database_global.json.j2 b/dockers/docker-database/database_global.json.j2 new file mode 100644 index 000000000000..777bce43b324 --- /dev/null +++ b/dockers/docker-database/database_global.json.j2 @@ -0,0 +1,21 @@ +{% set namespace_cnt = NAMESPACE_COUNT|int %} +{ + "INCLUDES" : [ + { + "include" : "../../redis/sonic-db/database_config.json" + }, +{% if namespace_cnt > 1 %} +{% for ns in range(namespace_cnt) %} + { + "namespace" : "{{NAMESPACE_PREFIX}}{{ns}}", + "include" : "../../redis{{ns}}/sonic-db/database_config.json" +{% if ns == namespace_cnt-1 %} + } +{% else %} + }, +{% endif %} +{% endfor %} + ], + "VERSION" : "1.0" +} +{% endif %} diff --git a/dockers/docker-database/docker-database-init.sh b/dockers/docker-database/docker-database-init.sh new file mode 100755 index 000000000000..413bbc0b20df --- /dev/null +++ b/dockers/docker-database/docker-database-init.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +# For linux host namespace, in both single and multi ASIC platform use the loopback interface +# For other namespaces, use eth0 interface which is connected to the docker0 bridge in the host. +if [[ $NAMESPACE_ID == "" ]] +then + INTFC=lo +else + INTFC=eth0 +fi + +# Get the ip address of the interface +# if the ip address was not retrieved correctly, put localhost(127.0.0.1) as the default. +host_ip=$(ip -4 -o addr show $INTFC | awk '{print $4}' | cut -d'/' -f1 | head -1) +if [[ $host_ip == "" ]] +then + host_ip=127.0.0.1 +fi + +REDIS_DIR=/var/run/redis$NAMESPACE_ID +mkdir -p $REDIS_DIR/sonic-db +mkdir -p /etc/supervisor/conf.d/ + +if [ -f /etc/sonic/database_config$NAMESPACE_ID.json ]; then + cp /etc/sonic/database_config$NAMESPACE_ID.json $REDIS_DIR/sonic-db/database_config.json +else + HOST_IP=$host_ip j2 /usr/share/sonic/templates/database_config.json.j2 > $REDIS_DIR/sonic-db/database_config.json +fi + +# on VoQ system, we only publish redis_chassis instance and CHASSIS_APP_DB when +# either chassisdb.conf indicates starts chassis_db or connect to chassis_db, +# and redis_chassis instance is started in different container. +# in order to do that, first we save original database config file, then +# call update_chasissdb_config to remove chassis_db config from +# the original database config file and use the modified config file to generate +# supervisord config, so that we won't start redis_chassis service. +# then we will decide to publish modified or original database config file based +# on the setting in chassisdb.conf +start_chassis_db=0 +chassis_db_address="" +chassis_db_port="" +chassisdb_config="/usr/share/sonic/platform/chassisdb.conf" +[ -f $chassisdb_config ] && source $chassisdb_config + +db_cfg_file="/var/run/redis/sonic-db/database_config.json" +db_cfg_file_tmp="/var/run/redis/sonic-db/database_config.json.tmp" +cp $db_cfg_file $db_cfg_file_tmp + +if [[ $DATABASE_TYPE == "chassisdb" ]]; then + # Docker init for database-chassis + echo "Init docker-database-chassis..." + update_chassisdb_config -j $db_cfg_file_tmp -k -p $chassis_db_port + # generate all redis server supervisord configuration file + sonic-cfggen -j $db_cfg_file_tmp -t /usr/share/sonic/templates/supervisord.conf.j2 > /etc/supervisor/conf.d/supervisord.conf + rm $db_cfg_file_tmp + exec /usr/local/bin/supervisord + exit 0 +fi + +# copy/generate the database_global.json file if this is global database service in multi asic platform. +if [[ $NAMESPACE_ID == "" ]] && [[ $NAMESPACE_COUNT -gt 1 ]] +then + if [ -f /etc/sonic/database_global.json ]; then + cp /etc/sonic/database_global.json $REDIS_DIR/sonic-db/database_global.json + else + j2 /usr/share/sonic/templates/database_global.json.j2 > $REDIS_DIR/sonic-db/database_global.json + fi +fi +# delete chassisdb config to generate supervisord config +update_chassisdb_config -j $db_cfg_file_tmp -d +sonic-cfggen -j $db_cfg_file_tmp -t /usr/share/sonic/templates/supervisord.conf.j2 > /etc/supervisor/conf.d/supervisord.conf + +if [[ "$start_chassis_db" != "1" ]] && [[ -z "$chassis_db_address" ]]; then + cp $db_cfg_file_tmp $db_cfg_file +else + update_chassisdb_config -j $db_cfg_file -p $chassis_db_port +fi +rm $db_cfg_file_tmp + +# copy dump.rdb file to each instance for restoration +DUMPFILE=/var/lib/redis/dump.rdb +redis_inst_list=`/usr/bin/python3 -c "import swsssdk; print(' '.join(swsssdk.SonicDBConfig.get_instancelist().keys()))"` +for inst in $redis_inst_list +do + mkdir -p /var/lib/$inst + if [[ -f $DUMPFILE ]]; then + # copy warmboot rdb file into each new instance location + if [[ "$DUMPFILE" != "/var/lib/$inst/dump.rdb" ]]; then + cp $DUMPFILE /var/lib/$inst/dump.rdb + fi + else + echo -n > /var/lib/$inst/dump.rdb + fi +done + +exec /usr/local/bin/supervisord diff --git a/dockers/docker-database/flush_unused_database b/dockers/docker-database/flush_unused_database new file mode 100755 index 000000000000..10cacb5e0b33 --- /dev/null +++ b/dockers/docker-database/flush_unused_database @@ -0,0 +1,28 @@ +#!/usr/bin/python +import swsssdk +import redis +import subprocess +import time + +while(True): + output = subprocess.Popen(['sonic-db-cli', 'PING'], stdout=subprocess.PIPE).communicate()[0] + if 'PONG' in output: + break + time.sleep(1) + +instlists = swsssdk.SonicDBConfig.get_instancelist() +for instname, v in instlists.items(): + insthost = v['hostname'] + instsocket = v['unix_socket_path'] + + dblists = swsssdk.SonicDBConfig.get_dblist() + for dbname in dblists: + dbid = swsssdk.SonicDBConfig.get_dbid(dbname) + dbinst = swsssdk.SonicDBConfig.get_instancename(dbname) + + # this DB is on current instance, skip flush + if dbinst == instname: + continue + + r = redis.Redis(host=insthost, unix_socket_path=instsocket, db=dbid) + r.flushdb() diff --git a/dockers/docker-database/supervisord.conf.j2 b/dockers/docker-database/supervisord.conf.j2 new file mode 100644 index 000000000000..616475fb07ce --- /dev/null +++ b/dockers/docker-database/supervisord.conf.j2 @@ -0,0 +1,43 @@ +[supervisord] +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,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=true +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +{% if INSTANCES %} +{% for redis_inst, redis_items in INSTANCES.items() %} +[program: {{ redis_inst }}] +{% if redis_items['hostname'] != '127.0.0.1' and redis_inst != 'redis_chassis' %} +{%- set LOOPBACK_IP = '127.0.0.1' -%} +{%- else -%} +{%- set LOOPBACK_IP = '' -%} +{%- endif -%} +command=/bin/bash -c "{ [[ -s /var/lib/{{ redis_inst }}/dump.rdb ]] || rm -f /var/lib/{{ redis_inst }}/dump.rdb; } && mkdir -p /var/lib/{{ redis_inst }} && exec /usr/bin/redis-server /etc/redis/redis.conf --bind {{ LOOPBACK_IP }} {{ redis_items['hostname'] }} --port {{ redis_items['port'] }} --unixsocket {{ redis_items['unix_socket_path'] }} --pidfile /var/run/redis/{{ redis_inst }}.pid --dir /var/lib/{{ redis_inst }}" +priority=2 +autostart=true +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +{% endfor %} +{% endif %} + +[program:flushdb] +command=/bin/bash -c "sleep 300 && /usr/local/bin/flush_unused_database" +priority=3 +autostart=true +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/dockers/docker-dhcp-relay/Dockerfile.j2 b/dockers/docker-dhcp-relay/Dockerfile.j2 new file mode 100644 index 000000000000..1100aa510742 --- /dev/null +++ b/dockers/docker-dhcp-relay/Dockerfile.j2 @@ -0,0 +1,36 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +ARG docker_container_name +ARG image_version +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 + +# Pass the image_version to container +ENV IMAGE_VERSION=$image_version + +# Update apt's cache of available packages +RUN apt-get update + +{% if docker_dhcp_relay_debs.strip() -%} +# Copy built Debian packages +{{ copy_files("debs/", docker_dhcp_relay_debs.split(' '), "/debs/") }} + +# Install built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_dhcp_relay_debs.split(' ')) }} +{%- endif %} + +# Clean up +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs + +COPY ["docker_init.sh", "start.sh", "/usr/bin/"] +COPY ["docker-dhcp-relay.supervisord.conf.j2", "port-name-alias-map.txt.j2", "wait_for_intf.sh.j2", "/usr/share/sonic/templates/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor"] + +ENTRYPOINT ["/usr/bin/docker_init.sh"] diff --git a/dockers/docker-dhcp-relay/critical_processes b/dockers/docker-dhcp-relay/critical_processes new file mode 100644 index 000000000000..855851bf2d68 --- /dev/null +++ b/dockers/docker-dhcp-relay/critical_processes @@ -0,0 +1 @@ +group:isc-dhcp-relay diff --git a/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 new file mode 100644 index 000000000000..19a6cc294f7f --- /dev/null +++ b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 @@ -0,0 +1,161 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=50 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name dhcp_relay +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +{# If our configuration has VLANs... #} +{% if VLAN_INTERFACE %} +{# Count how many VLANs require a DHCP relay agent... #} +{% set num_relays = { 'count': 0 } %} +{% for vlan_name in VLAN_INTERFACE %} +{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %} +{% set _dummy = num_relays.update({'count': num_relays.count + 1}) %} +{% endif %} +{% endfor %} +{# If one or more of the VLANs require a DHCP relay agent... #} +{% if num_relays.count > 0 %} +[group:isc-dhcp-relay] +programs= +{%- set add_preceding_comma = { 'flag': False } %} +{% for vlan_name in VLAN_INTERFACE %} +{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %} +{% if add_preceding_comma.flag %},{% endif %} +{% set _dummy = add_preceding_comma.update({'flag': True}) %} +isc-dhcp-relay-{{ vlan_name }} +{%- endif %} +{% endfor %} + + +{# Create a program entry for each DHCP relay agent instance #} +{% set relay_for_ipv4 = { 'flag': False } %} +{% for vlan_name in VLAN_INTERFACE %} +{% if VLAN and vlan_name in VLAN and 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:isc-dhcp-relay-{{ vlan_name }}] +{# We treat this VLAN as a downstream interface (-id), as we only want to listen for requests #} +command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id {{ vlan_name }} +{#- Dual ToR Option #} +{% if 'subtype' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['subtype'] == 'DualToR' %} -U Loopback0 -dt{% endif -%} +{#- 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 %} +{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %} +{%- if dhcp_server | ipv4 %} {{ dhcp_server }}{% endif -%} +{% endfor %} + +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + +{% endif %} +{% endif %} +{% endfor %} + +[group:dhcpmon] +programs= +{%- set add_preceding_comma = { 'flag': False } %} +{% for vlan_name in VLAN_INTERFACE %} +{% if VLAN and vlan_name in VLAN and 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_INTERFACE %} +{% if VLAN and vlan_name in VLAN and 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 %} +{% if MGMT_INTERFACE %} +{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %} +{% if prefix | ipv4 %} -im {{ name }}{% endif -%} +{% endfor %} +{% endif %} + +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=isc-dhcp-relay-{{ vlan_name }}:running + +{% endif %} +{% endif %} +{% endfor %} + +{% endif %} +{% endif %} diff --git a/dockers/docker-dhcp-relay/docker_init.sh b/dockers/docker-dhcp-relay/docker_init.sh new file mode 100755 index 000000000000..1ff0e936ff68 --- /dev/null +++ b/dockers/docker-dhcp-relay/docker_init.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Generate supervisord config file +mkdir -p /etc/supervisor/conf.d/ + +# Generate the following files from templates: +# 1. supervisord configuration +# 2. wait_for_intf.sh, which waits for all interfaces to come up +# 3. port-to-alias name map +CFGGEN_PARAMS=" \ + -d \ + -t /usr/share/sonic/templates/docker-dhcp-relay.supervisord.conf.j2,/etc/supervisor/conf.d/docker-dhcp-relay.supervisord.conf \ + -t /usr/share/sonic/templates/wait_for_intf.sh.j2,/usr/bin/wait_for_intf.sh \ + -t /usr/share/sonic/templates/port-name-alias-map.txt.j2,/tmp/port-name-alias-map.txt \ +" +sonic-cfggen $CFGGEN_PARAMS + +# Make the script that waits for all interfaces to come up executable +chmod +x /usr/bin/wait_for_intf.sh + +# The docker container should start this script as PID 1, so now that supervisord is +# properly configured, we exec /usr/local/bin/supervisord so that it runs as PID 1 for the +# duration of the container's lifetime +exec /usr/local/bin/supervisord diff --git a/dockers/docker-dhcp-relay/port-name-alias-map.txt.j2 b/dockers/docker-dhcp-relay/port-name-alias-map.txt.j2 new file mode 100644 index 000000000000..b2290a9ffbf2 --- /dev/null +++ b/dockers/docker-dhcp-relay/port-name-alias-map.txt.j2 @@ -0,0 +1,5 @@ +{# Generate port name-alias map for isc-dhcp-relay to parse. Each line contains one #} +{# name-alias pair of the form " " #} +{% for port, config in PORT.items() %} + {{- port }} {% if "alias" in config %}{{ config["alias"] }}{% else %}{{ port }}{% endif %} {{- "\n" -}} +{% endfor -%} diff --git a/dockers/docker-dhcp-relay/start.sh b/dockers/docker-dhcp-relay/start.sh new file mode 100755 index 000000000000..cb563eb003c3 --- /dev/null +++ b/dockers/docker-dhcp-relay/start.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +if [ "${RUNTIME_OWNER}" == "" ]; then + RUNTIME_OWNER="kube" +fi + +CTR_SCRIPT="/usr/share/sonic/scripts/container_startup.py" +if test -f ${CTR_SCRIPT} +then + ${CTR_SCRIPT} -f dhcp_relay -o ${RUNTIME_OWNER} -v ${IMAGE_VERSION} +fi + +# If our supervisor config has entries in the "isc-dhcp-relay" group... +if [ $(supervisorctl status | grep -c "^isc-dhcp-relay:") -gt 0 ]; then + # Wait for all interfaces to come up and be assigned IPv4 addresses before + # starting the DHCP relay agent(s). If an interface the relay should listen + # on is down, the relay agent will not start. If an interface the relay + # should listen on is up but does not have an IP address assigned when the + # relay agent starts, it will not listen or send on that interface for the + # lifetime of the process. + /usr/bin/wait_for_intf.sh +fi diff --git a/dockers/docker-dhcp-relay/wait_for_intf.sh.j2 b/dockers/docker-dhcp-relay/wait_for_intf.sh.j2 new file mode 100644 index 000000000000..568f128b3772 --- /dev/null +++ b/dockers/docker-dhcp-relay/wait_for_intf.sh.j2 @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +function wait_until_iface_ready +{ + IFACE_NAME=$1 + IFACE_CIDR=$2 + + echo "Waiting until interface ${IFACE_NAME} is ready..." + + # Wait for the interface to come up + # (i.e., interface is present in STATE_DB and state is "ok") + while true; do + 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 + + sleep 1 + done + + echo "Interface ${IFACE_NAME} is ready!" +} + + +# Wait for all interfaces with IPv4 addresses to be up and ready +{% for (name, prefix) in INTERFACE|pfx_filter %} +{% if prefix | ipv4 %} +wait_until_iface_ready {{ name }} {{ prefix }} +{% endif %} +{% endfor %} +{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %} +{% if prefix | ipv4 %} +wait_until_iface_ready {{ name }} {{ prefix }} +{% endif %} +{% endfor %} +{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %} +{% if prefix | ipv4 %} +wait_until_iface_ready {{ name }} {{ prefix }} +{% endif %} +{% endfor %} diff --git a/dockers/docker-fpm-frr/.dockerignore b/dockers/docker-fpm-frr/.dockerignore new file mode 100644 index 000000000000..bd5eecc5d798 --- /dev/null +++ b/dockers/docker-fpm-frr/.dockerignore @@ -0,0 +1 @@ +Dockerfile.j2 diff --git a/dockers/docker-fpm-frr/Dockerfile.j2 b/dockers/docker-fpm-frr/Dockerfile.j2 new file mode 100644 index 000000000000..42df1c6f38f8 --- /dev/null +++ b/dockers/docker-fpm-frr/Dockerfile.j2 @@ -0,0 +1,64 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +ARG docker_container_name +ARG frr_user_uid +ARG frr_user_gid + +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 + +# Update apt's cache of available packages +# Install required packages +RUN apt-get update && \ + apt-get install -y \ + libc-ares2 \ + iproute2 \ + libjson-c3 \ + logrotate \ + libunwind8 + +RUN groupadd -g ${frr_user_gid} frr +RUN useradd -u ${frr_user_uid} -g ${frr_user_gid} -M -s /bin/false frr + +{% if docker_fpm_frr_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_fpm_frr_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_fpm_frr_debs.split(' ')) }} +{%- endif %} + +{% if docker_fpm_frr_whls.strip() %} +# Copy locally-built Python wheel dependencies +{{ copy_files("python-wheels/", docker_fpm_frr_whls.split(' '), "/python-wheels/") }} + +# Install locally-built Python wheel dependencies +{{ install_python_wheels(docker_fpm_frr_whls.split(' ')) }} +{% endif %} + +RUN chown -R ${frr_user_uid}:${frr_user_gid} /etc/frr/ + +# Clean up +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs ~/.cache /python-wheels + +COPY ["frr", "/usr/share/sonic/templates"] +COPY ["docker_init.sh", "/usr/bin/"] +COPY ["snmp.conf", "/etc/snmp/frr.conf"] +COPY ["TSA", "/usr/bin/TSA"] +COPY ["TSB", "/usr/bin/TSB"] +COPY ["TSC", "/usr/bin/TSC"] +COPY ["TS", "/usr/bin/TS"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["zsocket.sh", "/usr/bin/"] +RUN chmod a+x /usr/bin/TSA && \ + chmod a+x /usr/bin/TSB && \ + chmod a+x /usr/bin/TSC && \ + chmod a+x /usr/bin/zsocket.sh + +ENTRYPOINT ["/usr/bin/docker_init.sh"] diff --git a/dockers/docker-fpm-frr/TS b/dockers/docker-fpm-frr/TS new file mode 100755 index 000000000000..78ba24d5db63 --- /dev/null +++ b/dockers/docker-fpm-frr/TS @@ -0,0 +1,40 @@ +#!/bin/bash + +# Check whether the routemap is for internal BGP sessions. +function is_internal_route_map() +{ + [[ "$1" =~ .*"_INTERNAL_".* ]] +} + +function check_not_installed() +{ + c=0 + config=$(vtysh -c "show run") + for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | egrep 'V4|V6'); + do + is_internal_route_map $route_map_name && continue + echo "$config" | egrep -q "^route-map $route_map_name permit 20$" + c=$((c+$?)) + echo "$config" | egrep -q "^route-map $route_map_name deny 30$" + c=$((c+$?)) + done + return $c +} + +function check_installed() +{ + c=0 + e=0 + config=$(vtysh -c "show run") + for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | egrep 'V4|V6'); + do + is_internal_route_map $route_map_name && continue + echo "$config" | egrep -q "^route-map $route_map_name permit 20$" + c=$((c+$?)) + e=$((e+1)) + echo "$config" | egrep -q "^route-map $route_map_name deny 30$" + c=$((c+$?)) + e=$((e+1)) + done + return $((e-c)) +} diff --git a/dockers/docker-fpm-frr/TSA b/dockers/docker-fpm-frr/TSA new file mode 100755 index 000000000000..6312bf0ba5e6 --- /dev/null +++ b/dockers/docker-fpm-frr/TSA @@ -0,0 +1,34 @@ +#!/bin/bash + +# Load the common functions +source /usr/bin/TS + +check_not_installed +not_installed=$? +if [[ $not_installed -ne 0 ]]; +then + TSA_FILE=$(mktemp) + for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p'); + do + is_internal_route_map $route_map_name && continue + case "$route_map_name" in + *V4*) + ip_version=V4 + ip_protocol=ip + ;; + *V6*) + ip_version=V6 + ip_protocol=ipv6 + ;; + *) + continue + ;; + esac + sonic-cfggen -d -a "{\"route_map_name\":\"$route_map_name\", \"ip_version\": \"$ip_version\", \"ip_protocol\": \"$ip_protocol\"}" -y /etc/sonic/constants.yml -t /usr/share/sonic/templates/bgpd/tsa/bgpd.tsa.isolate.conf.j2 > "$TSA_FILE" + vtysh -f "$TSA_FILE" + rm -f "$TSA_FILE" + done + echo "System Mode: Normal -> Maintenance" +else + echo "System is already in Maintenance mode" +fi diff --git a/dockers/docker-fpm-frr/TSB b/dockers/docker-fpm-frr/TSB new file mode 100755 index 000000000000..44f9b15aea27 --- /dev/null +++ b/dockers/docker-fpm-frr/TSB @@ -0,0 +1,30 @@ +#!/bin/bash + +# Load the common functions +source /usr/bin/TS + +check_installed +installed=$? +if [[ $installed -ne 0 ]]; +then + TSB_FILE=$(mktemp) + for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p'); + do + is_internal_route_map $route_map_name && continue + case "$route_map_name" in + *V4*) + ;; + *V6*) + ;; + *) + continue + ;; + esac + sonic-cfggen -d -a "{\"route_map_name\":\"$route_map_name\"}" -t /usr/share/sonic/templates/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 > "$TSB_FILE" + vtysh -f "$TSB_FILE" + rm -f "$TSB_FILE" + done + echo "System Mode: Maintenance -> Normal" +else + echo "System is already in Normal mode" +fi diff --git a/dockers/docker-fpm-frr/TSC b/dockers/docker-fpm-frr/TSC new file mode 100755 index 000000000000..a0e908439e41 --- /dev/null +++ b/dockers/docker-fpm-frr/TSC @@ -0,0 +1,20 @@ +#!/bin/bash + +# Load the common functions +source /usr/bin/TS + +check_not_installed +not_installed=$? + +check_installed +installed=$? + +if [[ $installed -eq 0 ]]; +then + echo "System Mode: Normal" +elif [[ $not_installed -eq 0 ]]; +then + echo "System Mode: Maintenance" +else + echo "System Mode: Not consistent" +fi diff --git a/dockers/docker-fpm-frr/base_image_files/TS b/dockers/docker-fpm-frr/base_image_files/TS new file mode 100755 index 000000000000..de1e50b7a306 --- /dev/null +++ b/dockers/docker-fpm-frr/base_image_files/TS @@ -0,0 +1,29 @@ +#!/bin/bash + +# read SONiC immutable variables +[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment + +PLATFORM=${PLATFORM:-`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`} + +# Parse the device specific asic conf file, if it exists +ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf +[ -f $ASIC_CONF ] && . $ASIC_CONF + +if [[ ($NUM_ASIC -gt 1) ]]; then + asic=0 + NAMESPACE_PREFIX='asic' + + while [ $asic -lt $NUM_ASIC ] + do + # Run TSA/TSB/TSC scripts in BGP instance for frontend ASICs. + sub_role=`sonic-cfggen -d -v "DEVICE_METADATA['localhost']['sub_role']" -n $NAMESPACE_PREFIX$asic` + if [ $sub_role == 'FrontEnd' ] + then + echo -e "BGP"$asic" : \c" + docker exec -i bgp$asic /usr/bin/$1 + fi + asic=$[$asic+1] + done +else + docker exec -i bgp /usr/bin/$1 +fi diff --git a/dockers/docker-fpm-frr/base_image_files/TSA b/dockers/docker-fpm-frr/base_image_files/TSA new file mode 100755 index 000000000000..e96c76dd67b2 --- /dev/null +++ b/dockers/docker-fpm-frr/base_image_files/TSA @@ -0,0 +1,3 @@ +#!/bin/bash + +/usr/bin/TS TSA diff --git a/dockers/docker-fpm-frr/base_image_files/TSB b/dockers/docker-fpm-frr/base_image_files/TSB new file mode 100755 index 000000000000..176b10c684c8 --- /dev/null +++ b/dockers/docker-fpm-frr/base_image_files/TSB @@ -0,0 +1,3 @@ +#!/bin/bash + +/usr/bin/TS TSB diff --git a/dockers/docker-fpm-frr/base_image_files/TSC b/dockers/docker-fpm-frr/base_image_files/TSC new file mode 100755 index 000000000000..09d1409c50c7 --- /dev/null +++ b/dockers/docker-fpm-frr/base_image_files/TSC @@ -0,0 +1,5 @@ +#!/bin/bash + +/usr/bin/TS TSC + +portstat -p 5 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..07705e84179d --- /dev/null +++ b/dockers/docker-fpm-frr/base_image_files/monit_bgp @@ -0,0 +1,27 @@ +############################################################################### +## Monit configuration for BGP container +## process list: +## zebra +## fpmsyncd +## bgpd +## staticd +## bgpcfgd +## bgpmon +############################################################################### +check program bgp|zebra with path "/usr/bin/process_checker bgp /usr/lib/frr/zebra" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program bgp|fpmsyncd with path "/usr/bin/process_checker bgp fpmsyncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program bgp|bgpd with path "/usr/bin/process_checker bgp /usr/lib/frr/bgpd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program bgp|staticd with path "/usr/bin/process_checker bgp /usr/lib/frr/staticd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program bgp|bgpcfgd with path "/usr/bin/process_checker bgp /usr/bin/python3 /usr/local/bin/bgpcfgd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program bgp|bgpmon with path "/usr/bin/process_checker bgp /usr/bin/python3 /usr/local/bin/bgpmon" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/dockers/docker-fpm-frr/base_image_files/vtysh b/dockers/docker-fpm-frr/base_image_files/vtysh new file mode 100755 index 000000000000..e4efeb454cb3 --- /dev/null +++ b/dockers/docker-fpm-frr/base_image_files/vtysh @@ -0,0 +1,49 @@ +#!/bin/bash +# read SONiC immutable variables +[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment + +function help() +{ + echo -e "Usage: $0 -n [0 to $(($NUM_ASIC-1))] [OPTION]... " 1>&2; exit 1; +} + +DEV="" +PLATFORM=${PLATFORM:-`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`} + +# Parse the device specific asic conf file, if it exists +ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf +[ -f $ASIC_CONF ] && . $ASIC_CONF + +if [[ ($NUM_ASIC -gt 1) ]]; then + while getopts ":n:h:" opt; do + case "${opt}" in + h) help + ;; + n) DEV=${OPTARG} + [ $DEV -lt $NUM_ASIC -a $DEV -ge 0 ] || help + ;; + esac + done + + if [ -z "${DEV}" ]; then + help + fi + + # Skip the arguments -n while passing to docker command + shift 2 +fi + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + # Prepare a function to send HUP signal to vtysh in the container + # we mark the new instance of vtysh with the current tty as a tag + TTY=$(tty) + function cleanup + { + docker exec -i bgp$DEV pkill -HUP -f "vtysh $TTY" + } + trap cleanup HUP + docker exec -ti bgp$DEV vtysh "$TTY" "$@" +else + docker exec -i bgp$DEV vtysh "$@" +fi diff --git a/dockers/docker-fpm-frr/docker_init.sh b/dockers/docker-fpm-frr/docker_init.sh new file mode 100755 index 000000000000..96149de4c379 --- /dev/null +++ b/dockers/docker-fpm-frr/docker_init.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +mkdir -p /etc/frr +mkdir -p /etc/supervisor/conf.d + +CFGGEN_PARAMS=" \ + -d \ + -y /etc/sonic/constants.yml \ + -t /usr/share/sonic/templates/frr_vars.j2 \ + -t /usr/share/sonic/templates/supervisord/supervisord.conf.j2,/etc/supervisor/conf.d/supervisord.conf \ + -t /usr/share/sonic/templates/bgpd/gen_bgpd.conf.j2,/etc/frr/bgpd.conf \ + -t /usr/share/sonic/templates/supervisord/critical_processes.j2,/etc/supervisor/critical_processes \ + -t /usr/share/sonic/templates/zebra/zebra.conf.j2,/etc/frr/zebra.conf \ + -t /usr/share/sonic/templates/staticd/gen_staticd.conf.j2,/etc/frr/staticd.conf \ + -t /usr/share/sonic/templates/gen_frr.conf.j2,/etc/frr/frr.conf \ + -t /usr/share/sonic/templates/isolate.j2,/usr/sbin/bgp-isolate \ + -t /usr/share/sonic/templates/unisolate.j2,/usr/sbin/bgp-unisolate \ + -t /usr/local/sonic/frrcfgd/bfdd.conf.j2,/etc/frr/bfdd.conf \ + -t /usr/local/sonic/frrcfgd/ospfd.conf.j2,/etc/frr/ospfd.conf \ +" + +FRR_VARS=$(sonic-cfggen $CFGGEN_PARAMS) +MGMT_FRAMEWORK_CONFIG=$(echo $FRR_VARS | jq -r '.frr_mgmt_framework_config') +CONFIG_TYPE=$(echo $FRR_VARS | jq -r '.docker_routing_config_mode') +if [ -z "$MGMT_FRAMEWORK_CONFIG" ] || [ "$MGMT_FRAMEWORK_CONFIG" == "false" ]; then + rm /etc/frr/bfdd.conf /etc/frr/ospfd.conf +fi + +update_default_gw() +{ + IP_VER=${1} + # FRR is not running in host namespace so we need to delete + # default gw kernel route added by docker network via eth0 and add it back + # with higher administrative distance so that default route learnt + # by FRR becomes best route if/when available + GATEWAY_IP=$(ip -${IP_VER} route show default dev eth0 | awk '{print $3}') + #Check if docker default route is there + if [[ ! -z "$GATEWAY_IP" ]]; then + ip -${IP_VER} route del default dev eth0 + #Make sure route is deleted + CHECK_GATEWAY_IP=$(ip -${IP_VER} route show default dev eth0 | awk '{print $3}') + if [[ -z "$CHECK_GATEWAY_IP" ]]; then + # Ref: http://docs.frrouting.org/en/latest/zebra.html#zebra-vrf + # Zebra does treat Kernel routes as special case for the purposes of Admin Distance. \ + # Upon learning about a route that is not originated by FRR we read the metric value as a uint32_t. + # The top byte of the value is interpreted as the Administrative Distance and + # the low three bytes are read in as the metric. + # so here we are programming administrative distance of 210 (210 << 24) > 200 (for routes learnt via IBGP) + ip -${IP_VER} route add default via $GATEWAY_IP dev eth0 metric 3523215360 + fi + fi +} + +if [[ ! -z "$NAMESPACE_ID" ]]; then + update_default_gw 4 + update_default_gw 6 +fi + +if [ -z "$CONFIG_TYPE" ] || [ "$CONFIG_TYPE" == "separated" ]; then + echo "no service integrated-vtysh-config" > /etc/frr/vtysh.conf + rm -f /etc/frr/frr.conf +elif [ "$CONFIG_TYPE" == "unified" ]; then + echo "service integrated-vtysh-config" > /etc/frr/vtysh.conf + rm -f /etc/frr/bgpd.conf /etc/frr/zebra.conf /etc/frr/staticd.conf \ + /etc/frr/bfdd.conf /etc/frr/ospfd.conf /etc/frr/pimd.conf +fi + +chown -R frr:frr /etc/frr/ + +chown root:root /usr/sbin/bgp-isolate +chmod 0755 /usr/sbin/bgp-isolate + +chown root:root /usr/sbin/bgp-unisolate +chmod 0755 /usr/sbin/bgp-unisolate + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +exec /usr/local/bin/supervisord diff --git a/dockers/docker-fpm-frr/frr/bgpd/bgpd.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/bgpd.conf.j2 new file mode 100644 index 000000000000..85182e5430e8 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/bgpd.conf.j2 @@ -0,0 +1,24 @@ +! +! template: bgpd/bgpd.conf.j2 +! +{% from "common/functions.conf.j2" import get_ipv4_loopback_address, get_ipv6_loopback_address %} +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +{% endblock banner %} +! +{% include "common/daemons.common.conf.j2" %} +! +agentx +! +{% if DEVICE_METADATA['localhost']['type'] == "SpineChassisFrontendRouter" %} +{% include "bgpd.spine_chassis_frontend_router.conf.j2" %} +{% endif %} +! +{% include "bgpd.main.conf.j2" %} +! +! end of template: bgpd/bgpd.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 new file mode 100644 index 000000000000..9568d4821547 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 @@ -0,0 +1,117 @@ +{% from "common/functions.conf.j2" import get_ipv4_loopback_address, get_ipv6_loopback_address, get_vnet_interfaces %} +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/32 +! +{% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") != 'None' %} +ipv6 prefix-list PL_LoopbackV6 permit {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | replace('/128', '/64') | ip_network }}/64 +{% endif %} +! +{% if VLAN_INTERFACE is defined %} +{% set vnet_intfs = get_vnet_interfaces(VLAN_INTERFACE) %} +{% endif %} +{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %} +{% if prefix | ipv4 and name not in vnet_intfs %} +ip prefix-list LOCAL_VLAN_IPV4_PREFIX seq {{ loop.index * 5 }} permit {{ prefix | ip_network }}/{{ prefix | prefixlen }} +! +{% endif %} +{% endfor %} +{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %} +{% if prefix | ipv6 and name not in vnet_intfs %} +ipv6 prefix-list LOCAL_VLAN_IPV6_PREFIX seq {{ loop.index * 5 }} permit {{ prefix | ip_network }}/{{ prefix | prefixlen }} +! +{% endif %} +{% endfor %} +! +{% if DEVICE_METADATA['localhost']['sub_role'] == 'FrontEnd' or DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %} +route-map HIDE_INTERNAL permit 10 + set community local-AS +! +{% endif %} +! +router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +! +{% block bgp_init %} + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! +{% if constants.bgp.multipath_relax.enabled is defined and constants.bgp.multipath_relax.enabled %} + bgp bestpath as-path multipath-relax +{% endif %} +! +{% if constants.bgp.graceful_restart.enabled is defined and constants.bgp.graceful_restart.enabled %} + bgp graceful-restart restart-time {{ constants.bgp.graceful_restart.restart_time | default(240) }} + bgp graceful-restart + bgp graceful-restart preserve-fw-state +{% endif %} +! +{# set router-id #} +{% if multi_asic() %} + bgp router-id {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") | ip }} +{% else %} + bgp router-id {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }} +{% endif %} +! +{# advertise loopback #} + network {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/32 +{% if multi_asic() %} + network {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") | ip }}/32 route-map HIDE_INTERNAL +{% endif %} +! +{% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") != 'None' %} + address-family ipv6 + network {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/64 + exit-address-family +{% endif %} +{% if multi_asic() %} +{% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") != 'None' %} + address-family ipv6 + network {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") | ip }}/64 route-map HIDE_INTERNAL + exit-address-family +{% endif %} +{% endif %} +{% endblock bgp_init %} +! +{% block vlan_advertisement %} +{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %} +{% if prefix | ipv4 and name not in vnet_intfs %} + network {{ prefix }} +{% elif prefix | ipv6 and name not in vnet_intfs %} + address-family ipv6 + network {{ prefix }} + exit-address-family +{% endif %} +{% endfor %} +{% endblock vlan_advertisement %} +! +! +{% if DEVICE_METADATA['localhost']['sub_role'] == 'FrontEnd' %} + address-family ipv4 + redistribute connected route-map HIDE_INTERNAL + exit-address-family + address-family ipv6 + redistribute connected route-map HIDE_INTERNAL + exit-address-family +{% endif %} +! +{% if constants.bgp.maximum_paths.enabled is defined and constants.bgp.maximum_paths.enabled %} +{% block maximum_paths %} + address-family ipv4 + maximum-paths {{ constants.bgp.maximum_paths.ipv4 | default(64) }} + exit-address-family + address-family ipv6 + maximum-paths {{ constants.bgp.maximum_paths.ipv6 | default(64) }} + exit-address-family +{% endblock maximum_paths %} +{% endif %} +! +! end of template: bgpd/bgpd.main.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/bgpd.spine_chassis_frontend_router.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/bgpd.spine_chassis_frontend_router.conf.j2 new file mode 100644 index 000000000000..94dacbc3af78 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/bgpd.spine_chassis_frontend_router.conf.j2 @@ -0,0 +1,63 @@ +! +{# VNET BGP Instance #} +! Vnet BGP instance +{% set interfaces_in_vnets = [] %} +{% block vnet_bgp_instance %} +{% for vnet_name, vnet_metadata in VNET.items() %} +router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} vrf {{ vnet_name }} + no bgp default ipv4-unicast + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart restart-time 240 + bgp graceful-restart +{# Router ID #} +{% for (name, prefix) in LOOPBACK_INTERFACE | pfx_filter %} +{% if prefix | ipv4 and name == 'Loopback0' %} + bgp router-id {{ prefix | ip }} +{% endif %} +{% endfor %} +{# Got interfaces that belong this vnet #} +{% set interfaces_in_vnet = [] %} +{% for (key, metadata) in INTERFACE.items() %} +{% if "vnet_name" in metadata and metadata["vnet_name"] == vnet_name %} +{% for (name_prefix_pair, metadata) in INTERFACE.items() %} +{% if key == name_prefix_pair[0] %} +{% if interfaces_in_vnet.append( name_prefix_pair[1] | ip ) %} +{% endif %} +{% if interfaces_in_vnets.append( name_prefix_pair[1] | ip ) %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{% endfor %} +{# Each bgp neighbors #} +{% for neighbor_addr, bgp_session in BGP_NEIGHBOR.items() %} +{% if "local_addr" in bgp_session and bgp_session["local_addr"] in interfaces_in_vnet %} +{% if bgp_session['asn'] | int != 0 %} + neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }} + neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }} +{# set the bgp neighbor timers if they have not default values #} +{% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60) + or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %} + neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }} +{% endif %} +{% if 'admin_status' in bgp_session and bgp_session['admin_status'] == 'down' or 'admin_status' not in bgp_session and 'default_bgp_status' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %} + neighbor {{ neighbor_addr }} shutdown +{% endif %} +{% if neighbor_addr | ipv4 %} + address-family ipv4 unicast + neighbor {{ neighbor_addr }} activate + neighbor {{ neighbor_addr }} soft-reconfiguration inbound + maximum-paths 64 + exit-address-family +{% endif %} + address-family l2vpn evpn + advertise ipv4 unicast + exit-address-family +{% endif %} +{% endif %} +{% endfor %} +{% endfor %} +{% endblock vnet_bgp_instance %} +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/gen_bgpd.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/gen_bgpd.conf.j2 new file mode 100644 index 000000000000..bb6d7f6a5a65 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/gen_bgpd.conf.j2 @@ -0,0 +1,5 @@ +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} + {% include "/usr/local/sonic/frrcfgd/bgpd.conf.j2" %} +{% else %} + {% include "/usr/share/sonic/templates/bgpd/bgpd.conf.j2" %} +{% endif %} diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/instance.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/instance.conf.j2 new file mode 100644 index 000000000000..5082b75005c2 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/instance.conf.j2 @@ -0,0 +1,38 @@ +! +! template: bgpd/templates/dynamic/instance.conf.j2 +! +{% from "common/functions.conf.j2" import get_ipv4_loopback_address %} +! + neighbor {{ bgp_session['name'] }} peer-group + neighbor {{ bgp_session['name'] }} passive + neighbor {{ bgp_session['name'] }} ebgp-multihop 255 + neighbor {{ bgp_session['name'] }} soft-reconfiguration inbound + neighbor {{ bgp_session['name'] }} route-map FROM_BGP_SPEAKER in + neighbor {{ bgp_session['name'] }} route-map TO_BGP_SPEAKER out +! +{% if bgp_session['peer_asn'] is defined %} + neighbor {{ bgp_session['name'] }} remote-as {{ bgp_session['peer_asn'] }} +{% else %} + neighbor {{ bgp_session['name'] }} remote-as {{ constants.deployment_id_asn_map[CONFIG_DB__DEVICE_METADATA['localhost']['deployment_id']] }} +{% endif %} +! +{# FIXME: bgp_session['ip_range'] check the type #} +{% for ip_range in bgp_session['ip_range'].split(',') %} + bgp listen range {{ ip_range }} peer-group {{ bgp_session['name'] }} +{% endfor %} +! +{% if bgp_session['src_address'] is defined %} + neighbor {{ bgp_session['name'] }} update-source {{ bgp_session['src_address'] | ip }} +{% else %} + neighbor {{ bgp_session['name'] }} update-source {{ get_ipv4_loopback_address(CONFIG_DB__LOOPBACK_INTERFACE, "Loopback1") | ip }} +{% endif %} +! + address-family ipv4 + neighbor {{ bgp_session['name'] }} activate + exit-address-family + address-family ipv6 + neighbor {{ bgp_session['name'] }} activate + exit-address-family +! +! end of template: bgpd/templates/dynamic/instance.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/peer-group.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/peer-group.conf.j2 new file mode 100644 index 000000000000..86d5c0297227 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/peer-group.conf.j2 @@ -0,0 +1,7 @@ +! +! template: bgpd/templates/BGP_SPEAKER/peer-group.conf.j2 +! +! nothing is here +! +! end of template: bgpd/templates/BGP_SPEAKER/peer-group.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/policies.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/policies.conf.j2 new file mode 100644 index 000000000000..17ca09ec2a36 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/policies.conf.j2 @@ -0,0 +1,9 @@ +! +! template: bgpd/templates/BGP_SPEAKER/policies.conf.j2 +! +route-map FROM_BGP_SPEAKER permit 10 +! +route-map TO_BGP_SPEAKER deny 1 +! +! end of template: bgpd/templates/BGP_SPEAKER/policies.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/general/instance.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/general/instance.conf.j2 new file mode 100644 index 000000000000..c8c9906bc98d --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/general/instance.conf.j2 @@ -0,0 +1,45 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }} + neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }} +{# set the bgp neighbor timers if they have not default values #} +{% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60) + or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %} + neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] | default("60") }} {{ bgp_session['holdtime'] | default("180") }} +{% endif %} +! +{% if 'admin_status' in bgp_session and bgp_session['admin_status'] == 'down' or 'admin_status' not in bgp_session and 'default_bgp_status' in CONFIG_DB__DEVICE_METADATA['localhost'] and CONFIG_DB__DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %} + neighbor {{ neighbor_addr }} shutdown +{% endif %} +! +{% if neighbor_addr | ipv4 %} + address-family ipv4 + neighbor {{ neighbor_addr }} peer-group PEER_V4 +! +{% elif neighbor_addr | ipv6 %} + address-family ipv6 + neighbor {{ neighbor_addr }} peer-group PEER_V6 +! +{% endif %} +! +{% if 'rrclient' in bgp_session and bgp_session['rrclient'] | int != 0 %} + neighbor {{ neighbor_addr }} route-reflector-client +{% endif %} +! +{% if 'nhopself' in bgp_session and bgp_session['nhopself'] | int != 0 %} + neighbor {{ neighbor_addr }} next-hop-self +{% endif %} +! + neighbor {{ neighbor_addr }} activate + exit-address-family +! +{% if bgp_session["asn"] == bgp_asn and CONFIG_DB__DEVICE_METADATA['localhost']['type'] == "SpineChassisFrontendRouter" %} + address-family l2vpn evpn + neighbor {{ neighbor_addr }} activate + advertise-all-vni + exit-address-family +{% endif %} +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/general/peer-group.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/general/peer-group.conf.j2 new file mode 100644 index 000000000000..2617cc94c2d2 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/general/peer-group.conf.j2 @@ -0,0 +1,32 @@ +! +! template: bgpd/templates/general/peer-group.conf.j2 +! + neighbor PEER_V4 peer-group + neighbor PEER_V6 peer-group + address-family ipv4 +{% if CONFIG_DB__DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %} + neighbor PEER_V4 allowas-in 1 +{% elif CONFIG_DB__DEVICE_METADATA['localhost']['type'] == 'LeafRouter' %} +{% if CONFIG_DB__BGP_BBR['status'] == 'enabled' %} + neighbor PEER_V4 allowas-in 1 +{% endif %} +{% endif %} + neighbor PEER_V4 soft-reconfiguration inbound + neighbor PEER_V4 route-map FROM_BGP_PEER_V4 in + neighbor PEER_V4 route-map TO_BGP_PEER_V4 out + exit-address-family + address-family ipv6 +{% if CONFIG_DB__DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %} + neighbor PEER_V6 allowas-in 1 +{% elif CONFIG_DB__DEVICE_METADATA['localhost']['type'] == 'LeafRouter' %} +{% if CONFIG_DB__BGP_BBR['status'] == 'enabled' %} + neighbor PEER_V6 allowas-in 1 +{% endif %} +{% endif %} + neighbor PEER_V6 soft-reconfiguration inbound + neighbor PEER_V6 route-map FROM_BGP_PEER_V6 in + neighbor PEER_V6 route-map TO_BGP_PEER_V6 out + exit-address-family +! +! end of template: bgpd/templates/general/peer-group.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/general/policies.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/general/policies.conf.j2 new file mode 100644 index 000000000000..7cf5e148f694 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/general/policies.conf.j2 @@ -0,0 +1,64 @@ +! +! template: bgpd/templates/general/policies.conf.j2 +! +! +! +{% if constants.bgp.allow_list is defined and constants.bgp.allow_list.enabled is defined and constants.bgp.allow_list.enabled and constants.bgp.allow_list.drop_community is defined %} +! +! +! please don't remove. 65535 entries are default rules +! which works when allow_list is enabled, but new configuration +! is not applied +! +{% if allow_list_default_action == 'deny' %} +! +route-map ALLOW_LIST_DEPLOYMENT_ID_0_V4 permit 65535 + set community no-export additive +! +route-map ALLOW_LIST_DEPLOYMENT_ID_0_V6 permit 65535 + set community no-export additive +{% else %} +! +route-map ALLOW_LIST_DEPLOYMENT_ID_0_V4 permit 65535 + set community {{ constants.bgp.allow_list.drop_community }} additive +! +route-map ALLOW_LIST_DEPLOYMENT_ID_0_V6 permit 65535 + set community {{ constants.bgp.allow_list.drop_community }} additive +{% endif %} +! +bgp community-list standard allow_list_default_community permit no-export +bgp community-list standard allow_list_default_community permit {{ constants.bgp.allow_list.drop_community }} +! +route-map FROM_BGP_PEER_V4 permit 10 + call ALLOW_LIST_DEPLOYMENT_ID_0_V4 + on-match next +! +route-map FROM_BGP_PEER_V4 permit 11 + match community allow_list_default_community +! +route-map FROM_BGP_PEER_V6 permit 10 + call ALLOW_LIST_DEPLOYMENT_ID_0_V6 + on-match next +! +route-map FROM_BGP_PEER_V6 permit 11 + match community allow_list_default_community +! +{% endif %} +! +! +! +route-map FROM_BGP_PEER_V4 permit 100 +! +route-map TO_BGP_PEER_V4 permit 100 +! +! +route-map FROM_BGP_PEER_V6 permit 1 + on-match next + set ipv6 next-hop prefer-global +! +route-map FROM_BGP_PEER_V6 permit 100 +! +route-map TO_BGP_PEER_V6 permit 100 +! +! end of template: bgpd/templates/general/policies.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/internal/instance.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/internal/instance.conf.j2 new file mode 100644 index 000000000000..e0e23b7f60c8 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/internal/instance.conf.j2 @@ -0,0 +1,35 @@ +! +! template: bgpd/templates/internal/instance.conf.j2 +! + neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }} + neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }} + neighbor {{ neighbor_addr }} timers 3 10 +! +{% if neighbor_addr | ipv4 %} + address-family ipv4 + neighbor {{ neighbor_addr }} peer-group INTERNAL_PEER_V4 +! +{% if CONFIG_DB__DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %} + neighbor {{ neighbor_addr }} route-map FROM_BGP_INTERNAL_PEER_V4 in +{% endif %} +! +{% elif neighbor_addr | ipv6 %} + address-family ipv6 + neighbor {{ neighbor_addr }} peer-group INTERNAL_PEER_V6 +! +{% if CONFIG_DB__DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %} + neighbor {{ neighbor_addr }} route-map FROM_BGP_INTERNAL_PEER_V6 in +{% endif %} +{% endif %} +! +{% if 'rrclient' in bgp_session and bgp_session['rrclient'] | int != 0 %} + neighbor {{ neighbor_addr }} route-reflector-client +{% endif %} +! + neighbor {{ neighbor_addr }} next-hop-self force +! + neighbor {{ neighbor_addr }} activate + exit-address-family +! +! end of template: bgpd/templates/internal/instance.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/internal/peer-group.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/internal/peer-group.conf.j2 new file mode 100644 index 000000000000..323c13447ed0 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/internal/peer-group.conf.j2 @@ -0,0 +1,24 @@ +! +! template: bgpd/templates/internal/peer-group.conf.j2 +! + neighbor INTERNAL_PEER_V4 peer-group + neighbor INTERNAL_PEER_V6 peer-group + address-family ipv4 +{% if CONFIG_DB__DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %} + neighbor INTERNAL_PEER_V4 route-reflector-client +{% endif %} + neighbor INTERNAL_PEER_V4 soft-reconfiguration inbound + neighbor INTERNAL_PEER_V4 route-map FROM_BGP_INTERNAL_PEER_V4 in + neighbor INTERNAL_PEER_V4 route-map TO_BGP_INTERNAL_PEER_V4 out + exit-address-family + address-family ipv6 +{% if CONFIG_DB__DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %} + neighbor INTERNAL_PEER_V6 route-reflector-client +{% endif %} + neighbor INTERNAL_PEER_V6 soft-reconfiguration inbound + neighbor INTERNAL_PEER_V6 route-map FROM_BGP_INTERNAL_PEER_V6 in + neighbor INTERNAL_PEER_V6 route-map TO_BGP_INTERNAL_PEER_V6 out + exit-address-family +! +! end of template: bgpd/templates/internal/peer-group.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/internal/policies.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/internal/policies.conf.j2 new file mode 100644 index 000000000000..81d3b0041179 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/internal/policies.conf.j2 @@ -0,0 +1,28 @@ +! +! template: bgpd/templates/internal/policies.conf.j2 +! +! +! +route-map FROM_BGP_INTERNAL_PEER_V4 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V4 permit 100 +! +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 1 + on-match next + set ipv6 next-hop prefer-global +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V6 permit 100 +! +{% if CONFIG_DB__DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %} +route-map FROM_BGP_INTERNAL_PEER_V4 permit 2 + set originator-id {{ loopback0_ipv4 | ip }} +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 2 + set originator-id {{ loopback0_ipv4 | ip }} +{% endif %} +! +! end of template: bgpd/templates/internal/policies.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/instance.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/instance.conf.j2 new file mode 100644 index 000000000000..0aa22a3a7f87 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/instance.conf.j2 @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/monitors/instance.conf.j2 +! + neighbor {{ neighbor_addr }} remote-as {{ bgp_asn }} + neighbor {{ neighbor_addr }} peer-group BGPMON + neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }} + neighbor {{ neighbor_addr }} activate + address-family ipv6 + neighbor {{ neighbor_addr }} activate + exit-address-family +! +! end of template: bgpd/templates/BGPMON/instance.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/peer-group.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/peer-group.conf.j2 new file mode 100644 index 000000000000..a36278619015 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/peer-group.conf.j2 @@ -0,0 +1,12 @@ +! +! template: bgpd/templates/BGPMON/peer-group.conf.j2 +! + neighbor BGPMON peer-group + neighbor BGPMON update-source {{ loopback0_ipv4 | ip }} + neighbor BGPMON route-map FROM_BGPMON in + neighbor BGPMON route-map TO_BGPMON out + neighbor BGPMON send-community + neighbor BGPMON maximum-prefix 1 +! +! end of template: bgpd/templates/BGPMON/peer-group.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/policies.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/policies.conf.j2 new file mode 100644 index 000000000000..8d53991064de --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/policies.conf.j2 @@ -0,0 +1,9 @@ +! +! template: bgpd/templates/BGPMON/policies.conf.j2 +! +route-map FROM_BGPMON deny 10 +! +route-map TO_BGPMON permit 10 +! +! end of template: bgpd/templates/BGPMON/policies.conf.j2 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.isolate.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.isolate.conf.j2 new file mode 100644 index 000000000000..1256d1cd4f96 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.isolate.conf.j2 @@ -0,0 +1,5 @@ +route-map {{ route_map_name }} permit 20 + match {{ ip_protocol }} address prefix-list PL_Loopback{{ ip_version }} + set community {{ constants.bgp.traffic_shift_community }} +route-map {{ route_map_name }} deny 30 +! diff --git a/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 new file mode 100644 index 000000000000..649f6d8e9db8 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 @@ -0,0 +1,3 @@ +no route-map {{ route_map_name }} permit 20 +no route-map {{ route_map_name }} deny 30 +! diff --git a/dockers/docker-fpm-frr/frr/common/daemons.common.conf.j2 b/dockers/docker-fpm-frr/frr/common/daemons.common.conf.j2 new file mode 100644 index 000000000000..1c3efdfa72fb --- /dev/null +++ b/dockers/docker-fpm-frr/frr/common/daemons.common.conf.j2 @@ -0,0 +1,14 @@ +! template: common/daemons.common.conf.j2 +! +{% block sys_init %} +hostname {{ DEVICE_METADATA['localhost']['hostname'] }} +password zebra +enable password zebra +{% endblock sys_init %} +! +{% block logging %} +log syslog informational +log facility local4 +{% endblock logging %} +! +! end of template: common/daemons.common.conf.j2 diff --git a/dockers/docker-fpm-frr/frr/common/functions.conf.j2 b/dockers/docker-fpm-frr/frr/common/functions.conf.j2 new file mode 100644 index 000000000000..34700db329ca --- /dev/null +++ b/dockers/docker-fpm-frr/frr/common/functions.conf.j2 @@ -0,0 +1,35 @@ +{% macro get_ipv4_loopback_address(interfaces, loopbackname) -%} +{% set L = namespace(ip=None) %} +{% for name, prefix in interfaces|pfx_filter %} +{% if name == loopbackname %} +{% if prefix | ipv4 %} +{% set L.ip = prefix %} +{% endif %} +{% endif %} +{% endfor %} +{{ L.ip }} +{%- endmacro %} + +{% macro get_ipv6_loopback_address(interfaces, loopbackname) -%} +{% set L = namespace(ip=None) %} +{% for name, prefix in interfaces|pfx_filter %} +{% if name == loopbackname %} +{% if prefix | ipv6 %} +{% set L.ip = prefix %} +{% endif %} +{% endif %} +{% endfor %} +{{ L.ip }} +{%- endmacro %} + +{% macro get_vnet_interfaces(interfaces) -%} +{% set L = namespace(intfs=[]) %} +{% set vnet_intfs = [] %} +{% for (key, metadata) in interfaces.items() %} +{% if "vnet_name" in metadata %} +{% set vnet_intfs = vnet_intfs.append(key) %} +{% endif %} +{% endfor %} +{% set L.intfs = vnet_intfs %} +{{ L.intfs }} +{%- endmacro %} diff --git a/dockers/docker-fpm-frr/frr/frr.conf.j2 b/dockers/docker-fpm-frr/frr/frr.conf.j2 new file mode 100644 index 000000000000..99900790366c --- /dev/null +++ b/dockers/docker-fpm-frr/frr/frr.conf.j2 @@ -0,0 +1,21 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr.conf.j2 with config DB data +! file: frr.conf +! +{% endblock banner %} +! +{% include "common/daemons.common.conf.j2" %} +{% from "common/functions.conf.j2" import get_ipv4_loopback_address, get_ipv6_loopback_address %} +! +agentx +! +{% include "zebra/zebra.interfaces.conf.j2" %} +! +{% include "staticd/staticd.default_route.conf.j2" %} +! +{% include "staticd/staticd.loopback_route.conf.j2" %} +! +{% include "bgpd/bgpd.main.conf.j2" %} +! diff --git a/dockers/docker-fpm-frr/frr/frr_vars.j2 b/dockers/docker-fpm-frr/frr/frr_vars.j2 new file mode 100644 index 000000000000..662608a1fd8b --- /dev/null +++ b/dockers/docker-fpm-frr/frr/frr_vars.j2 @@ -0,0 +1,14 @@ +{ + "frr_mgmt_framework_config": + {% if "frr_mgmt_framework_config" in DEVICE_METADATA["localhost"].keys() %} + "{{ DEVICE_METADATA["localhost"]["frr_mgmt_framework_config"] }}" + {% else %} + "" + {% endif %}, + "docker_routing_config_mode": + {% if "docker_routing_config_mode" in DEVICE_METADATA["localhost"].keys() %} + "{{ DEVICE_METADATA["localhost"]["docker_routing_config_mode"] }}" + {% else %} + "" + {% endif %} +} diff --git a/dockers/docker-fpm-frr/frr/gen_frr.conf.j2 b/dockers/docker-fpm-frr/frr/gen_frr.conf.j2 new file mode 100644 index 000000000000..181437da07a0 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/gen_frr.conf.j2 @@ -0,0 +1,5 @@ +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} + {% include "/usr/local/sonic/frrcfgd/frr.conf.j2" %} +{% else %} + {% include "/usr/share/sonic/templates/frr.conf.j2" %} +{% endif %} diff --git a/dockers/docker-fpm-frr/frr/isolate.j2 b/dockers/docker-fpm-frr/frr/isolate.j2 new file mode 100755 index 000000000000..9d19f9f40905 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/isolate.j2 @@ -0,0 +1,26 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? + +## vtysh script start from next line, which line number MUST equal in 'sed' command above + +configure terminal + router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% for neighbor_addr in BGP_NEIGHBOR %} +{% if neighbor_addr | ipv4 %} + neighbor {{ neighbor_addr }} route-map ISOLATE out +{% else %} + address-family ipv6 + neighbor {{ neighbor_addr }} route-map ISOLATE out + exit-address-family +{% endif %} +{% endfor %} + exit +exit + +{% for neighbor_addr in BGP_NEIGHBOR %} +clear ip bgp {{ neighbor_addr }} soft out +{% endfor %} diff --git a/dockers/docker-fpm-frr/frr/staticd/gen_staticd.conf.j2 b/dockers/docker-fpm-frr/frr/staticd/gen_staticd.conf.j2 new file mode 100644 index 000000000000..1346c9a4993b --- /dev/null +++ b/dockers/docker-fpm-frr/frr/staticd/gen_staticd.conf.j2 @@ -0,0 +1,5 @@ +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} + {% include "/usr/local/sonic/frrcfgd/staticd.conf.j2" %} +{% else %} + {% include "/usr/share/sonic/templates/staticd/staticd.conf.j2" %} +{% endif %} diff --git a/dockers/docker-fpm-frr/frr/staticd/staticd.conf.j2 b/dockers/docker-fpm-frr/frr/staticd/staticd.conf.j2 new file mode 100644 index 000000000000..4831325276c7 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/staticd/staticd.conf.j2 @@ -0,0 +1,14 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr/staticd.conf.j2 using config DB data +! file: staticd.conf +! +{% endblock banner %} +! +{% include "common/daemons.common.conf.j2" %} +! +{% include "staticd.default_route.conf.j2" %} +! +{% include "staticd.loopback_route.conf.j2" %} +! diff --git a/dockers/docker-fpm-frr/frr/staticd/staticd.default_route.conf.j2 b/dockers/docker-fpm-frr/frr/staticd/staticd.default_route.conf.j2 new file mode 100644 index 000000000000..22d61ebbd0ff --- /dev/null +++ b/dockers/docker-fpm-frr/frr/staticd/staticd.default_route.conf.j2 @@ -0,0 +1,10 @@ +! +{% block default_route %} +! set static default route to mgmt gateway as a backup to learned default +{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %} +{% if prefix | ipv4 %} +ip route 0.0.0.0/0 {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} 200 +{% endif %} +{% endfor %} +{% endblock default_route %} +! diff --git a/dockers/docker-fpm-frr/frr/staticd/staticd.loopback_route.conf.j2 b/dockers/docker-fpm-frr/frr/staticd/staticd.loopback_route.conf.j2 new file mode 100644 index 000000000000..95c2a901e4a3 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/staticd/staticd.loopback_route.conf.j2 @@ -0,0 +1,10 @@ +! +{% from "common/functions.conf.j2" import get_ipv4_loopback_address, get_ipv6_loopback_address, get_vnet_interfaces %} +! +{% block loopback_route %} +! add static ipv6 /64 loopback route to allow bgpd to advertise the loopback route prefix +{% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") != 'None' %} +ipv6 route {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | replace('/128', '/64') | ip_network }}/64 Loopback0 +{% endif %} +{% endblock loopback_route %} +! diff --git a/dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2 b/dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2 new file mode 100644 index 000000000000..69f4e8e6931e --- /dev/null +++ b/dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2 @@ -0,0 +1,12 @@ +program:zebra +program:staticd +program:bgpd +program:fpmsyncd +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} +program:bfdd +program:ospfd +program:pimd +program:frrcfgd +{%- else %} +program:bgpcfgd +{%- endif %} diff --git a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 new file mode 100644 index 000000000000..dd43e0cc4ec7 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 @@ -0,0 +1,179 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=50 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name bgp +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:zebra] +command=/usr/lib/frr/zebra -A 127.0.0.1 -s 90000000 -M fpm -M snmp +priority=4 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:zsocket] +command=/usr/bin/zsocket.sh +priority=4 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=zebra:running + +[program:staticd] +command=/usr/lib/frr/staticd -A 127.0.0.1 +priority=4 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=zsocket:exited + +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} +[program:bfdd] +command=/usr/lib/frr/bfdd -A 127.0.0.1 +priority=4 +stopsignal=KILL +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=zebra:running +{% endif %} + +[program:bgpd] +command=/usr/lib/frr/bgpd -A 127.0.0.1 -M snmp +priority=5 +stopsignal=KILL +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=zsocket:exited + +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} +[program:ospfd] +command=/usr/lib/frr/ospfd -A 127.0.0.1 -M snmp +priority=5 +stopsignal=KILL +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=zebra:running + +[program:pimd] +command=/usr/lib/frr/pimd -A 127.0.0.1 +priority=5 +stopsignal=KILL +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=zebra:running +{% endif %} + +[program:fpmsyncd] +command=fpmsyncd +priority=6 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=bgpd:running + +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} +[program:frrcfgd] +command=/usr/local/bin/frrcfgd +{% else %} +[program:bgpcfgd] +command=/usr/local/bin/bgpcfgd +{% endif %} +priority=6 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=bgpd:running + +[program:bgpmon] +command=/usr/local/bin/bgpmon +priority=6 +autostart=false +autorestart=true +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=bgpd:running + +{% if DEVICE_METADATA.localhost.docker_routing_config_mode is defined and DEVICE_METADATA.localhost.docker_routing_config_mode == "unified" %} +[program:vtysh_b] +command=/usr/bin/vtysh -b +priority=6 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=bgpd:running +{% endif %} + +{% if WARM_RESTART is defined and WARM_RESTART.bgp is defined and WARM_RESTART.bgp.bgp_eoiu is defined and WARM_RESTART.bgp.bgp_eoiu == "true" %} +[program:bgp_eoiu_marker] +command=/usr/bin/bgp_eoiu_marker.py +priority=7 +autostart=false +autorestart=false +startsecs=0 +startretries=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=bgpd:running +{% endif %} diff --git a/dockers/docker-fpm-frr/frr/unisolate.j2 b/dockers/docker-fpm-frr/frr/unisolate.j2 new file mode 100755 index 000000000000..abd6a912c0d5 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/unisolate.j2 @@ -0,0 +1,26 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? + +## vtysh script start from next line, which line number MUST equal in 'sed' command above + +configure terminal + router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% for neighbor_ip in BGP_NEIGHBOR %} +{% if neighbor_ip | ipv4 %} + no neighbor {{ neighbor_ip }} route-map ISOLATE out +{% else %} + address-family ipv6 + no neighbor {{ neighbor_ip }} route-map ISOLATE out + exit-address-family +{% endif %} +{% endfor %} + exit +exit + +{% for neighbor_ip in BGP_NEIGHBOR %} +clear ip bgp {{ neighbor_ip }} soft out +{% endfor %} diff --git a/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 b/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 new file mode 100644 index 000000000000..51d998e90d36 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/zebra/zebra.conf.j2 @@ -0,0 +1,12 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/zebra/zebra.conf.j2 using config DB data +! file: zebra.conf +! +{% endblock banner %} +! +{% include "common/daemons.common.conf.j2" %} +! +{% include "zebra.interfaces.conf.j2" %} +! diff --git a/dockers/docker-fpm-frr/frr/zebra/zebra.interfaces.conf.j2 b/dockers/docker-fpm-frr/frr/zebra/zebra.interfaces.conf.j2 new file mode 100644 index 000000000000..57d83163d67b --- /dev/null +++ b/dockers/docker-fpm-frr/frr/zebra/zebra.interfaces.conf.j2 @@ -0,0 +1,27 @@ +! +{% block vrf %} +{% if VNET is defined %} +{% for vnet_name, vnet_metadata in VNET.items() %} +vrf {{ vnet_name }} +vni {{ vnet_metadata['vni'] }} +! +{% endfor %} +{% endif %} +{% endblock vrf %} +! +{% block interfaces %} +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +{% for (name, prefix) in INTERFACE|pfx_filter %} +interface {{ name }} +link-detect +! +{% endfor %} +{% for pc in PORTCHANNEL %} +interface {{ pc }} +link-detect +! +{% endfor %} +{% endblock interfaces %} +! diff --git a/dockers/docker-fpm-frr/frr/zebra/zebra.set_src.conf.j2 b/dockers/docker-fpm-frr/frr/zebra/zebra.set_src.conf.j2 new file mode 100644 index 000000000000..4dce3250ed1b --- /dev/null +++ b/dockers/docker-fpm-frr/frr/zebra/zebra.set_src.conf.j2 @@ -0,0 +1,8 @@ +! +! Set ip source to loopback for bgp learned routes +! +route-map {{ rm_name }} permit 10 + set src {{ lo_ip }} +! +ip{{ ip_proto }} protocol bgp route-map {{ rm_name }} +! diff --git a/dockers/docker-fpm-frr/snmp.conf b/dockers/docker-fpm-frr/snmp.conf new file mode 100644 index 000000000000..0d875a61fe87 --- /dev/null +++ b/dockers/docker-fpm-frr/snmp.conf @@ -0,0 +1,7 @@ +# This line allows the FRR docker to speak with the snmp container +# Make sure this line matches the one in the snmp docker +# snmp:/etc/snmp/snmpd.conf +# To verify this works you need to have a valid bgp daemon running and configured +# Check that a snmpwalk to 1.3.6.1.2.1.15 gives an output +# Further verification: 1.3.6.1.2.1.15.2.0 = INTEGER: 65000 the returned value should be the confiugred ASN +agentXSocket tcp:localhost:3161 diff --git a/dockers/docker-fpm-frr/vtysh.conf b/dockers/docker-fpm-frr/vtysh.conf new file mode 100644 index 000000000000..e0ab9cb6f314 --- /dev/null +++ b/dockers/docker-fpm-frr/vtysh.conf @@ -0,0 +1 @@ +service integrated-vtysh-config diff --git a/dockers/docker-fpm-frr/zsocket.sh b/dockers/docker-fpm-frr/zsocket.sh new file mode 100755 index 000000000000..111492f960ed --- /dev/null +++ b/dockers/docker-fpm-frr/zsocket.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +addr="127.0.0.1" +port=2601 + +function help() +{ + echo "This script aims to ensure zebra is ready to accept connections" + echo "Usage: $0 [options]" + echo "Options:" + echo " -a Zebra address" + echo " -o Zebra port" + exit 1 +} + +while getopts ":a:o:h" opt; do + case "${opt}" in + h) help + ;; + a) addr=${OPTARG} + ;; + o) port=${OPTARG} + ;; + esac +done + +start=$(date +%s.%N) +timeout 5s bash -c -- "until =(yes|no|priority) +# 0, "no" = disabled +# 1, "yes" = highest priority +# 2 .. 10 = lower priorities +# Read /usr/share/doc/quagga/README.Debian for details. +# +# Sample configurations for these daemons can be found in +# /usr/share/doc/quagga/examples/. +# +# ATTENTION: +# +# When activation a daemon at the first time, a config file, even if it is +# empty, has to be present *and* be owned by the user and group "quagga", else +# the daemon will not be started by /etc/init.d/quagga. The permissions should +# be u=rw,g=r,o=. +# When using "vtysh" such a config file is also needed. It should be owned by +# group "quaggavty" and set to ug=rw,o= though. Check /etc/pam.d/quagga, too. +# +# The watchquagga daemon is always started. Per default in monitoring-only but +# that can be changed via /etc/quagga/debian.conf. +# +zebra=yes +bgpd=no +ospfd=no +ospf6d=no +ripd=no +ripngd=no +isisd=no +babeld=no diff --git a/dockers/docker-fpm-gobgp/gobgpd.conf.j2 b/dockers/docker-fpm-gobgp/gobgpd.conf.j2 new file mode 100644 index 000000000000..a4fb80bf11ca --- /dev/null +++ b/dockers/docker-fpm-gobgp/gobgpd.conf.j2 @@ -0,0 +1,28 @@ +[global.config] + as = {{ DEVICE_METADATA['localhost']['bgp_asn'] }} + router-id = "{{ LOOPBACK_INTERFACE.keys()[0][1] }}" +{% for neighbor_addr, bgp_session in BGP_NEIGHBOR.iteritems() %} +{% if bgp_session['asn'] | int != 0 %} +[[neighbors]] + [neighbors.config] + peer-as = {{ bgp_session['asn'] }} + neighbor-address = "{{ neighbor_addr }}" + [neighbors.graceful-restart.config] + enabled = true + [[neighbors.afi-safis]] + [neighbors.afi-safis.config] +{% if neighbor_addr | ipv6 %} + afi-safi-name = "ipv6-unicast" +{% else %} + afi-safi-name = "ipv4-unicast" +{% endif %} + [neighbors.afi-safis.mp-graceful-restart.config] + enabled = true +{% endif %} +{% endfor %} +[zebra] + [zebra.config] + enabled = true + url = "unix:/var/run/quagga/zserv.api" + redistribute-route-type-list = ["connect"] + diff --git a/dockers/docker-fpm-gobgp/isolate.j2 b/dockers/docker-fpm-gobgp/isolate.j2 new file mode 100755 index 000000000000..4502ff895777 --- /dev/null +++ b/dockers/docker-fpm-gobgp/isolate.j2 @@ -0,0 +1,4 @@ +#!/bin/bash + +echo Not implemented yet +exit diff --git a/dockers/docker-fpm-gobgp/start.sh b/dockers/docker-fpm-gobgp/start.sh new file mode 100755 index 000000000000..cdb0c6301686 --- /dev/null +++ b/dockers/docker-fpm-gobgp/start.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +mkdir -p /etc/quagga + +CFGGEN_PARAMS=" \ + -d \ + -t /usr/share/sonic/templates/gobgpd.conf.j2,/etc/gobgp/gobgpd.conf \ + -t /usr/share/sonic/templates/zebra.conf.j2,/etc/quagga/zebra.conf \ + -t /usr/share/sonic/templates/isolate.j2,/usr/sbin/bgp-isolate \ + -t /usr/share/sonic/templates/unisolate.j2,/usr/sbin/bgp-unisolate \ +" +sonic-cfggen $CFGGEN_PARAMS + +chown root:root /usr/sbin/bgp-isolate +chmod 0755 /usr/sbin/bgp-isolate + +chown root:root /usr/sbin/bgp-unisolate +chmod 0755 /usr/sbin/bgp-unisolate + +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 + +# Quagga has its own monitor process, 'watchquagga' +service quagga start + +supervisorctl start fpmsyncd diff --git a/dockers/docker-fpm-gobgp/supervisord.conf b/dockers/docker-fpm-gobgp/supervisord.conf new file mode 100644 index 000000000000..e7e3ee9f301a --- /dev/null +++ b/dockers/docker-fpm-gobgp/supervisord.conf @@ -0,0 +1,42 @@ +[supervisord] +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,PROCESS_STATE_RUNNING +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:gobgpd] +command=/usr/sbin/gobgpd -p -f /etc/gobgp/gobgpd.conf -r +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:fpmsyncd] +command=fpmsyncd +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/dockers/docker-fpm-gobgp/unisolate.j2 b/dockers/docker-fpm-gobgp/unisolate.j2 new file mode 100755 index 000000000000..69172744bae7 --- /dev/null +++ b/dockers/docker-fpm-gobgp/unisolate.j2 @@ -0,0 +1,5 @@ +#!/bin/bash + +echo Not implemented yet +exit + diff --git a/dockers/docker-fpm-gobgp/zebra.conf.j2 b/dockers/docker-fpm-gobgp/zebra.conf.j2 new file mode 100644 index 000000000000..2da0316ae500 --- /dev/null +++ b/dockers/docker-fpm-gobgp/zebra.conf.j2 @@ -0,0 +1,74 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/zebra.conf.j2 using config DB data +! file: zebra.conf +! +{% endblock banner %} +! +{% block sys_init %} +hostname {{ DEVICE_METADATA['localhost']['hostname'] }} +password zebra +enable password zebra +{% endblock sys_init %} +! +{% block interfaces %} +! Enable link-detect (default disabled) +{% for (name, prefix) in INTERFACE|pfx_filter %} +interface {{ name }} +link-detect +! +{% endfor %} +{% for pc in PORTCHANNEL %} +interface {{ pc }} +link-detect +! +{% endfor %} +{% endblock interfaces %} +! +{% block default_route %} +! set static default route to mgmt gateway as a backup to learned default +{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %} +{% if prefix | ipv4 %} +ip route 0.0.0.0/0 {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} 200 +{% endif %} +{% endfor %} +{% endblock default_route %} +! +{% block source_loopback %} +{% set lo_ipv4_addrs = [] %} +{% set lo_ipv6_addrs = [] %} +{% if LOOPBACK_INTERFACE %} +{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %} +{% if prefix | ipv6 %} +{% if lo_ipv6_addrs.append(prefix) %} +{% endif %} +{% else %} +{% if lo_ipv4_addrs.append(prefix) %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +! Set ip source to loopback for bgp learned routes +route-map RM_SET_SRC permit 10 + set src {{ lo_ipv4_addrs[0] | ip }} +! +{% if lo_ipv6_addrs|length > 0 %} +route-map RM_SET_SRC6 permit 10 + set src {{ lo_ipv6_addrs[0] | ip }} +! +{% endif %} +ip protocol bgp route-map RM_SET_SRC +! +{% if lo_ipv6_addrs|length > 0 %} +ipv6 protocol bgp route-map RM_SET_SRC6 +! +{% endif %} +{% endblock source_loopback %} +! +{% block logging %} +log syslog informational +log facility local4 +{% endblock logging %} +! + diff --git a/dockers/docker-fpm-quagga/Dockerfile.j2 b/dockers/docker-fpm-quagga/Dockerfile.j2 new file mode 100644 index 000000000000..ac382afbe5b2 --- /dev/null +++ b/dockers/docker-fpm-quagga/Dockerfile.j2 @@ -0,0 +1,39 @@ +FROM docker-config-engine + +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 + +# Update apt's cache of available packages +RUN apt-get update + +# Install required packages +RUN apt-get install -y libdbus-1-3 libdaemon0 libjansson4 libpython2.7 + +{% if docker_fpm_quagga_debs.strip() -%} +# Copy locally-built Debian package dependencies +{%- for deb in docker_fpm_quagga_debs.split(' ') %} +COPY debs/{{ deb }} /debs/ +{%- endfor %} + +# Install locally-built Debian packages and implicitly install their dependencies +{%- for deb in docker_fpm_quagga_debs.split(' ') %} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt /debs/{{ deb }} +{%- endfor %} +{%- endif %} + +# Clean up +RUN apt-get clean -y +RUN apt-get autoclean -y +RUN apt-get autoremove -y +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/local/bin/supervisord"] diff --git a/dockers/docker-fpm-quagga/base_image_files/vtysh b/dockers/docker-fpm-quagga/base_image_files/vtysh new file mode 100755 index 000000000000..24016bd96b2c --- /dev/null +++ b/dockers/docker-fpm-quagga/base_image_files/vtysh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + # Prepare a function to send HUP signal to vtysh in the container + # we mark the new instance of vtysh with the current tty as a tag + TTY=$(tty) + function cleanup + { + docker exec -i bgp pkill -HUP -f "vtysh $TTY" + } + trap cleanup HUP + docker exec -ti bgp vtysh "$TTY" "$@" +else + docker exec -i bgp vtysh "$@" +fi diff --git a/dockers/docker-fpm-quagga/bgpcfgd b/dockers/docker-fpm-quagga/bgpcfgd new file mode 100755 index 000000000000..ef936247cc2c --- /dev/null +++ b/dockers/docker-fpm-quagga/bgpcfgd @@ -0,0 +1,71 @@ +#!/usr/bin/env python + +import sys +import redis +import subprocess +import syslog +from swsssdk import ConfigDBConnector + + +class BGPConfigDaemon: + + def __init__(self): + self.config_db = ConfigDBConnector() + self.config_db.connect() + self.bgp_asn = self.config_db.get_entry('DEVICE_METADATA', 'localhost')['bgp_asn'] + self.bgp_neighbor = self.config_db.get_table('BGP_NEIGHBOR') + + def __run_command(self, command): + p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + stdout = p.communicate()[0] + p.wait() + if p.returncode != 0: + syslog.syslog(syslog.LOG_ERR, '[bgp cfgd] command execution returned {}. Command: "{}", stdout: "{}"'.format( + p.returncode, command, stdout)) + + def metadata_handler(self, key, data): + if key == 'localhost' and data.has_key('bgp_asn'): + if data['bgp_asn'] != self.bgp_asn: + syslog.syslog(syslog.LOG_INFO, '[bgp cfgd] ASN changed to {} from {}, restart BGP...'.format( + data['bgp_asn'], self.bgp_asn)) + self.__run_command("supervisorctl restart start.sh") + self.__run_command("service quagga restart") + self.bgp_asn = data['bgp_asn'] + + def bgp_handler(self, key, data): + syslog.syslog(syslog.LOG_INFO, '[bgp cfgd] value for {} changed to {}'.format(key, data)) + if not data: + # Neighbor is deleted + command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'no neighbor {}'".format(self.bgp_asn, key) + self.__run_command(command) + self.bgp_neighbor.pop(key) + else: + command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} remote-as {}'".format( + self.bgp_asn, key, data['asn']) + self.__run_command(command) + if data.has_key('name'): + command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} description {}'".format( + self.bgp_asn, key, data['name']) + self.__run_command(command) + if data.has_key('admin_status'): + command_mod = 'no ' if data['admin_status'] == 'up' else '' + command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c '{}neighbor {} shutdown'".format( + self.bgp_asn, command_mod, key) + self.__run_command(command) + self.bgp_neighbor[key] = data + + def start(self): + self.config_db.subscribe('BGP_NEIGHBOR', + lambda table, key, data: self.bgp_handler(key, data)) + self.config_db.subscribe('DEVICE_METADATA', + lambda table, key, data: self.metadata_handler(key, data)) + self.config_db.listen() + + +def main(): + daemon = BGPConfigDaemon() + daemon.start() + + +if __name__ == "__main__": + main() diff --git a/dockers/docker-fpm-quagga/bgpd.conf.j2 b/dockers/docker-fpm-quagga/bgpd.conf.j2 new file mode 100644 index 000000000000..8c838f8ffc9d --- /dev/null +++ b/dockers/docker-fpm-quagga/bgpd.conf.j2 @@ -0,0 +1,140 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +{% endblock banner %} +! +{% block system_init %} +hostname {{ DEVICE_METADATA['localhost']['hostname'] }} +password zebra +log syslog informational +log facility local4 +! enable password {# {{ en_passwd }} TODO: param needed #} +{% endblock system_init %} +! +{% if 'bgp_asn' in DEVICE_METADATA['localhost'] %} +{% block bgp_init %} +! +! bgp multiple-instance +! +route-map FROM_BGP_SPEAKER_V4 permit 10 +! +route-map TO_BGP_SPEAKER_V4 deny 10 +! +router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart restart-time 240 + bgp graceful-restart +{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %} +{% if prefix | ipv4 and name == 'Loopback0' %} + bgp router-id {{ prefix | ip }} +{% endif %} +{% endfor %} +{# advertise loopback #} +{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %} +{% if prefix | ipv4 and name == 'Loopback0' %} + network {{ prefix | ip }}/32 +{% elif prefix | ipv6 and name == 'Loopback0' %} + address-family ipv6 + network {{ prefix | ip }}/64 + exit-address-family +{% endif %} +{% endfor %} +{% endblock bgp_init %} +{% endif %} +{% block vlan_advertisement %} +{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %} +{% if prefix | ipv4 %} + network {{ prefix }} +{% elif prefix | ipv6 %} + address-family ipv6 + network {{ prefix }} + exit-address-family +{% endif %} +{% endfor %} +{% endblock vlan_advertisement %} +{% block bgp_sessions %} +{% for neighbor_addr, bgp_session in BGP_NEIGHBOR.items() %} +{% if bgp_session['asn'] | int != 0 %} + neighbor {{ neighbor_addr }} remote-as {{ bgp_session['asn'] }} + neighbor {{ neighbor_addr }} description {{ bgp_session['name'] }} +{# set the bgp neighbor timers if they have not default values #} +{% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60) + or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %} + neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }} +{% endif %} +{% if 'admin_status' in bgp_session and bgp_session['admin_status'] == 'down' or 'admin_status' not in bgp_session and 'default_bgp_status' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %} + neighbor {{ neighbor_addr }} shutdown +{% endif %} +{% if neighbor_addr | ipv4 %} + address-family ipv4 +{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %} + neighbor {{ neighbor_addr }} allowas-in 1 +{% endif %} + neighbor {{ neighbor_addr }} activate + neighbor {{ neighbor_addr }} soft-reconfiguration inbound + maximum-paths 64 + exit-address-family +{% endif %} +{% if neighbor_addr | ipv6 %} + address-family ipv6 +{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %} + neighbor {{ neighbor_addr }} allowas-in 1 +{% endif %} + neighbor {{ neighbor_addr }} activate + neighbor {{ neighbor_addr }} soft-reconfiguration inbound + maximum-paths 64 + exit-address-family +{% endif %} +{% endif %} +{% endfor %} +{% endblock bgp_sessions %} +{% block bgp_peers_with_range %} +{% if BGP_PEER_RANGE %} +{% for bgp_peer in BGP_PEER_RANGE.values() %} + neighbor {{ bgp_peer['name'] }} peer-group + neighbor {{ bgp_peer['name'] }} passive +{% if bgp_peer['peer_asn'] is defined %} + neighbor {{ bgp_peer['name'] }} remote-as {{ bgp_peer['peer_asn'] }} +{% else %} + neighbor {{ bgp_peer['name'] }} remote-as {{ constants.deployment_id_asn_map[DEVICE_METADATA['localhost']['deployment_id']] }} +{% endif %} + neighbor {{ bgp_peer['name'] }} ebgp-multihop 255 + neighbor {{ bgp_peer['name'] }} soft-reconfiguration inbound +{% if bgp_peer['src_address'] is defined %} + neighbor {{ bgp_peer['name'] }} update-source {{ bgp_peer['src_address'] | ip }} +{% else %} +{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %} +{% if name == 'Loopback1' %} + neighbor {{ bgp_peer['name'] }} update-source {{ prefix | ip }} +{% endif %} +{% endfor %} +{% endif %} + neighbor {{ bgp_peer['name'] }} route-map FROM_BGP_SPEAKER_V4 in + neighbor {{ bgp_peer['name'] }} route-map TO_BGP_SPEAKER_V4 out +{% for ip_range in bgp_peer['ip_range'] %} + bgp listen range {{ip_range}} peer-group {{ bgp_peer['name'] }} +{% endfor %} + address-family ipv4 + neighbor {{ bgp_peer['name'] }} activate + maximum-paths 64 + exit-address-family + address-family ipv6 + neighbor {{ bgp_peer['name'] }} activate + maximum-paths 64 + exit-address-family +{% endfor %} +{% endif %} +{% endblock bgp_peers_with_range %} +! +{% if 'bgp_asn' in DEVICE_METADATA['localhost'] %} +maximum-paths 64 +! +route-map ISOLATE permit 10 +set as-path prepend {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% endif %} +! diff --git a/dockers/docker-fpm-quagga/critical_processes b/dockers/docker-fpm-quagga/critical_processes new file mode 100644 index 000000000000..2dceb501e3e5 --- /dev/null +++ b/dockers/docker-fpm-quagga/critical_processes @@ -0,0 +1,4 @@ +program:zebra +program:bgpd +program:fpmsyncd +program:bgpcfgd diff --git a/dockers/docker-fpm-quagga/isolate.j2 b/dockers/docker-fpm-quagga/isolate.j2 new file mode 100755 index 000000000000..9d19f9f40905 --- /dev/null +++ b/dockers/docker-fpm-quagga/isolate.j2 @@ -0,0 +1,26 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? + +## vtysh script start from next line, which line number MUST equal in 'sed' command above + +configure terminal + router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% for neighbor_addr in BGP_NEIGHBOR %} +{% if neighbor_addr | ipv4 %} + neighbor {{ neighbor_addr }} route-map ISOLATE out +{% else %} + address-family ipv6 + neighbor {{ neighbor_addr }} route-map ISOLATE out + exit-address-family +{% endif %} +{% endfor %} + exit +exit + +{% for neighbor_addr in BGP_NEIGHBOR %} +clear ip bgp {{ neighbor_addr }} soft out +{% endfor %} diff --git a/dockers/docker-fpm-quagga/start.sh b/dockers/docker-fpm-quagga/start.sh new file mode 100755 index 000000000000..37d9c5072d9d --- /dev/null +++ b/dockers/docker-fpm-quagga/start.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +mkdir -p /etc/quagga + +CFGGEN_PARAMS=" \ + -d \ + -y /etc/sonic/constants.yml \ + -t /usr/share/sonic/templates/bgpd.conf.j2,/etc/quagga/bgpd.conf \ + -t /usr/share/sonic/templates/zebra.conf.j2,/etc/quagga/zebra.conf \ + -t /usr/share/sonic/templates/isolate.j2,/usr/sbin/bgp-isolate \ + -t /usr/share/sonic/templates/unisolate.j2,/usr/sbin/bgp-unisolate \ +" +sonic-cfggen $CFGGEN_PARAMS + +chown root:root /usr/sbin/bgp-isolate +chmod 0755 /usr/sbin/bgp-isolate + +chown root:root /usr/sbin/bgp-unisolate +chmod 0755 /usr/sbin/bgp-unisolate + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +rm -f /var/run/rsyslogd.pid + +supervisorctl start bgpcfgd + +supervisorctl start rsyslogd + +# Start Quagga processes +supervisorctl start zebra +supervisorctl start bgpd + +supervisorctl start fpmsyncd diff --git a/dockers/docker-fpm-quagga/supervisord.conf b/dockers/docker-fpm-quagga/supervisord.conf new file mode 100644 index 000000000000..470dea18a16d --- /dev/null +++ b/dockers/docker-fpm-quagga/supervisord.conf @@ -0,0 +1,65 @@ +[supervisord] +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,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bgpcfgd] +command=/usr/bin/bgpcfgd +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n +priority=3 +autostart=false +autorestart=unexpected +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:zebra] +command=/usr/lib/quagga/zebra -A 127.0.0.1 +priority=4 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bgpd] +command=/usr/lib/quagga/bgpd -A 127.0.0.1 -F +priority=5 +stopsignal=KILL +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:fpmsyncd] +command=fpmsyncd +priority=6 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/dockers/docker-fpm-quagga/unisolate.j2 b/dockers/docker-fpm-quagga/unisolate.j2 new file mode 100755 index 000000000000..abd6a912c0d5 --- /dev/null +++ b/dockers/docker-fpm-quagga/unisolate.j2 @@ -0,0 +1,26 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? + +## vtysh script start from next line, which line number MUST equal in 'sed' command above + +configure terminal + router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} +{% for neighbor_ip in BGP_NEIGHBOR %} +{% if neighbor_ip | ipv4 %} + no neighbor {{ neighbor_ip }} route-map ISOLATE out +{% else %} + address-family ipv6 + no neighbor {{ neighbor_ip }} route-map ISOLATE out + exit-address-family +{% endif %} +{% endfor %} + exit +exit + +{% for neighbor_ip in BGP_NEIGHBOR %} +clear ip bgp {{ neighbor_ip }} soft out +{% endfor %} diff --git a/dockers/docker-fpm-quagga/zebra.conf.j2 b/dockers/docker-fpm-quagga/zebra.conf.j2 new file mode 100644 index 000000000000..c0357eaed86a --- /dev/null +++ b/dockers/docker-fpm-quagga/zebra.conf.j2 @@ -0,0 +1,78 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/zebra.conf.j2 using config DB data +! file: zebra.conf +! +{% endblock banner %} +! +{% block sys_init %} +hostname {{ DEVICE_METADATA['localhost']['hostname'] }} +password zebra +enable password zebra +{% endblock sys_init %} +! +{% block interfaces %} +! Enable link-detect (default disabled) +{% for (name, prefix) in INTERFACE|pfx_filter %} +interface {{ name }} +link-detect +! +{% endfor %} +{% for pc in PORTCHANNEL %} +interface {{ pc }} +link-detect +! +{% endfor %} +{% endblock interfaces %} +! +{% block default_route %} +! set static default route to mgmt gateway as a backup to learned default +{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %} +{% if prefix | ipv4 %} +ip route 0.0.0.0/0 {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} 200 +{% endif %} +{% endfor %} +{% endblock default_route %} +! +{% block source_loopback %} +{% set lo_ipv4_addrs = [] %} +{% set lo_ipv6_addrs = [] %} +{% if LOOPBACK_INTERFACE %} +{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %} +{% if name == 'Loopback0' %} +{% if prefix | ipv6 %} +{% if lo_ipv6_addrs.append(prefix) %} +{% endif %} +{% else %} +{% if lo_ipv4_addrs.append(prefix) %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +! Set ip source to loopback for bgp learned routes +{% if lo_ipv4_addrs|length > 0 -%} +route-map RM_SET_SRC permit 10 + set src {{ lo_ipv4_addrs[0] | ip }} +! +{% endif %} +{% if lo_ipv6_addrs|length > 0 %} +route-map RM_SET_SRC6 permit 10 + set src {{ lo_ipv6_addrs[0] | ip }} +! +{% endif %} +ip protocol bgp route-map RM_SET_SRC +! +{% if lo_ipv6_addrs|length > 0 %} +ipv6 protocol bgp route-map RM_SET_SRC6 +! +{% endif %} +{% endblock source_loopback %} +! +{% block logging %} +log syslog informational +log facility local4 +{% endblock logging %} +! + diff --git a/dockers/docker-iccpd/Dockerfile.j2 b/dockers/docker-iccpd/Dockerfile.j2 new file mode 100644 index 000000000000..51cc306bdd55 --- /dev/null +++ b/dockers/docker-iccpd/Dockerfile.j2 @@ -0,0 +1,34 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +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 && \ + apt-get install -y ebtables + +COPY \ +{% for deb in docker_iccpd_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_iccpd_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "iccpd.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["iccpd.j2", "/usr/share/sonic/templates/"] + +RUN chmod +x /usr/bin/start.sh /usr/bin/iccpd.sh +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/dockers/docker-iccpd/base_image_files/mclagdctl b/dockers/docker-iccpd/base_image_files/mclagdctl new file mode 100755 index 000000000000..7c0b45dd0625 --- /dev/null +++ b/dockers/docker-iccpd/base_image_files/mclagdctl @@ -0,0 +1,10 @@ +#!/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 iccpd mclagdctl "$@" diff --git a/dockers/docker-iccpd/iccpd.j2 b/dockers/docker-iccpd/iccpd.j2 new file mode 100644 index 000000000000..6c6f9fab1afa --- /dev/null +++ b/dockers/docker-iccpd/iccpd.j2 @@ -0,0 +1,11 @@ +{% for mclag_id in MC_LAG %} +mclag_id:{{mclag_id}} + local_ip:{{MC_LAG[mclag_id]['local_ip']}} + peer_ip:{{MC_LAG[mclag_id]['peer_ip']}} +{% if MC_LAG[mclag_id].has_key('peer_link') %} + peer_link:{{MC_LAG[mclag_id]['peer_link']}} +{% endif %} + mclag_interface:{{MC_LAG[mclag_id]['mclag_interface']}} +{% endfor %} +system_mac:{{DEVICE_METADATA['localhost']['mac']}} + diff --git a/dockers/docker-iccpd/iccpd.sh b/dockers/docker-iccpd/iccpd.sh new file mode 100644 index 000000000000..d3b2888344ac --- /dev/null +++ b/dockers/docker-iccpd/iccpd.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +function start_app { + rm -f /var/run/iccpd/* + mclagsyncd & + iccpd +} + +function clean_up { + pkill -9 mclagsyncd + pkill -9 iccpd + exit +} + +trap clean_up SIGTERM SIGKILL +start_app +read diff --git a/dockers/docker-iccpd/start.sh b/dockers/docker-iccpd/start.sh new file mode 100644 index 000000000000..f2e9807f314f --- /dev/null +++ b/dockers/docker-iccpd/start.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + + +ICCPD_CONF_PATH=/etc/iccpd + +rm -rf $ICCPD_CONF_PATH +mkdir -p $ICCPD_CONF_PATH + +sonic-cfggen -d -t /usr/share/sonic/templates/iccpd.j2 > $ICCPD_CONF_PATH/iccpd.conf + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status diff --git a/dockers/docker-iccpd/supervisord.conf b/dockers/docker-iccpd/supervisord.conf new file mode 100644 index 000000000000..716ca96b40c8 --- /dev/null +++ b/dockers/docker-iccpd/supervisord.conf @@ -0,0 +1,42 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:iccpd] +command=/usr/bin/iccpd.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited diff --git a/dockers/docker-lldp/Dockerfile.j2 b/dockers/docker-lldp/Dockerfile.j2 new file mode 100644 index 000000000000..a1c7a1c1bee2 --- /dev/null +++ b/dockers/docker-lldp/Dockerfile.j2 @@ -0,0 +1,52 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +ARG docker_container_name +ARG image_version +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 + +# Pass the image_version to container +ENV IMAGE_VERSION=$image_version + +# Update apt's cache of available packages +RUN apt-get update + +{% if docker_lldp_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_lldp_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_lldp_debs.split(' ')) }} +{%- endif %} + +{% if docker_lldp_whls.strip() -%} +# Copy locally-built Python wheel dependencies +{{ copy_files("python-wheels/", docker_lldp_whls.split(' '), "/python-wheels/") }} + +# Install locally-built Python wheel dependencies +{{ install_python_wheels(docker_lldp_whls.split(' ')) }} +{% endif %} + +# Clean up +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs \ + /python-wheels \ + ~/.cache + +COPY ["docker-lldp-init.sh", "/usr/bin/"] +COPY ["start.sh", "/usr/bin/"] +COPY ["waitfor_lldp_ready.sh", "/usr/bin/"] +COPY ["supervisord.conf.j2", "/usr/share/sonic/templates/"] +COPY ["lldpd.conf.j2", "/usr/share/sonic/templates/"] +COPY ["lldpdSysDescr.conf.j2", "/usr/share/sonic/templates/"] +COPY ["lldpd", "/etc/default/"] +COPY ["lldpmgrd", "/usr/bin/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor"] + +ENTRYPOINT ["/usr/bin/docker-lldp-init.sh"] diff --git a/dockers/docker-lldp/base_image_files/lldpcli b/dockers/docker-lldp/base_image_files/lldpcli new file mode 100755 index 000000000000..3c8037862d4d --- /dev/null +++ b/dockers/docker-lldp/base_image_files/lldpcli @@ -0,0 +1,10 @@ +#!/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 lldp lldpcli "$@" diff --git a/dockers/docker-lldp/base_image_files/lldpctl b/dockers/docker-lldp/base_image_files/lldpctl new file mode 100755 index 000000000000..f5b6d8307ee9 --- /dev/null +++ b/dockers/docker-lldp/base_image_files/lldpctl @@ -0,0 +1,10 @@ +#!/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 lldp lldpctl "$@" diff --git a/dockers/docker-lldp/base_image_files/monit_lldp b/dockers/docker-lldp/base_image_files/monit_lldp new file mode 100644 index 000000000000..d470972ace30 --- /dev/null +++ b/dockers/docker-lldp/base_image_files/monit_lldp @@ -0,0 +1,15 @@ +############################################################################### +## Monit configuration for lldp container +## process list: +## lldpd +## lldp-syncd +## lldpmgrd +############################################################################### +check program lldp|lldpd_monitor with path "/usr/bin/process_checker lldp lldpd:" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program lldp|lldp_syncd with path "/usr/bin/process_checker lldp python3 -m lldp_syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program lldp|lldpmgrd with path "/usr/bin/process_checker lldp python3 /usr/bin/lldpmgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/dockers/docker-lldp/critical_processes b/dockers/docker-lldp/critical_processes new file mode 100644 index 000000000000..90586536a4f5 --- /dev/null +++ b/dockers/docker-lldp/critical_processes @@ -0,0 +1,3 @@ +program:lldpd +program:lldp-syncd +program:lldpmgrd diff --git a/dockers/docker-lldp/docker-lldp-init.sh b/dockers/docker-lldp/docker-lldp-init.sh new file mode 100755 index 000000000000..135ff48255d6 --- /dev/null +++ b/dockers/docker-lldp/docker-lldp-init.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +#Generate supervisord.conf based on device metadata +mkdir -p /etc/supervisor/conf.d/ +sonic-cfggen -d -t /usr/share/sonic/templates/supervisord.conf.j2 > /etc/supervisor/conf.d/supervisord.conf +exec /usr/local/bin/supervisord diff --git a/dockers/docker-lldp/lldpd b/dockers/docker-lldp/lldpd new file mode 100644 index 000000000000..ba22e49b9b47 --- /dev/null +++ b/dockers/docker-lldp/lldpd @@ -0,0 +1,6 @@ +############################################################################### +# Managed by sonic-cfggen +############################################################################### + +# Uncomment to start SNMP subagent and enable CDP, SONMP and EDP protocol +DAEMON_ARGS="" diff --git a/dockers/docker-lldp/lldpd.conf.j2 b/dockers/docker-lldp/lldpd.conf.j2 new file mode 100644 index 000000000000..904784ef67b1 --- /dev/null +++ b/dockers/docker-lldp/lldpd.conf.j2 @@ -0,0 +1,21 @@ +{% set mgmt_if = {} %} +{% if MGMT_INTERFACE %} +{% for (mgmt_name, mgmt_prefix) in MGMT_INTERFACE|pfx_filter %} +{% if mgmt_prefix|ipv4 %} +{% if mgmt_if.update({'port_name' : mgmt_name}) %} {% endif %} +{% if mgmt_if.update({'ipv4' : mgmt_prefix|ip}) %} {% endif %} +{% endif %} +{% endfor %} +{% endif %} +{% if mgmt_if %} +{# If MGMT port alias is available, use it for port ID subtype, otherwise use port name #} +{% if MGMT_PORT and MGMT_PORT[mgmt_if.port_name] and MGMT_PORT[mgmt_if.port_name].alias %} +configure ports eth0 lldp portidsubtype local {{ MGMT_PORT[mgmt_if.port_name].alias }} +{% else %} +configure ports eth0 lldp portidsubtype local {{ mgmt_if.port_name }} +{% endif %} +configure system ip management pattern {{ mgmt_if.ipv4 }} +{% endif %} +configure system hostname {{ DEVICE_METADATA['localhost']['hostname'] }} +{# pause lldpd operations until all interfaces are well configured, resume command will run in lldpmgrd #} +pause diff --git a/dockers/docker-lldp/lldpdSysDescr.conf.j2 b/dockers/docker-lldp/lldpdSysDescr.conf.j2 new file mode 100644 index 000000000000..047b3c68b34f --- /dev/null +++ b/dockers/docker-lldp/lldpdSysDescr.conf.j2 @@ -0,0 +1 @@ +configure system description "SONiC Software Version: SONiC.{{ build_version }} - HwSku: {{ DEVICE_METADATA['localhost']['hwsku'] }} - Distribution: Debian {{ debian_version }} - Kernel: {{ kernel_version }}" diff --git a/dockers/docker-lldp/lldpmgrd b/dockers/docker-lldp/lldpmgrd new file mode 100755 index 000000000000..61d6034faa15 --- /dev/null +++ b/dockers/docker-lldp/lldpmgrd @@ -0,0 +1,263 @@ +#!/usr/bin/env python3 + +""" + lldpmgrd + + LLDP manager daemon for SONiC + + Daemon which listens for changes in the PORT table of the State DB + and updates LLDP configuration accordingly for that port by calling + lldpcli. + + TODO: Also listen for changes in DEVICE_NEIGHBOR and PORT tables in + Config DB and update LLDP config upon changes. +""" + + +try: + import os + import subprocess + import sys + import time + + from sonic_py_common import daemon_base + from swsscommon import swsscommon +except ImportError as err: + raise ImportError("%s - required module not found" % str(err)) + +VERSION = "1.0" + +SYSLOG_IDENTIFIER = "lldpmgrd" +PORT_INIT_TIMEOUT = 300 + + +class LldpManager(daemon_base.DaemonBase): + """ + Class which subscribes to notifications of changes in the PORT table of + the Redis State database and updates LLDP configuration accordingly for + that port by calling lldpcli. + Attributes: + state_db: Handle to Redis State database via swsscommon lib + config_db: Handle to Redis Config database via swsscommon lib + pending_cmds: Dictionary where key is port name, value is pending + LLDP configuration command to run + """ + REDIS_TIMEOUT_MS = 0 + + def __init__(self, log_identifier): + super(LldpManager, self).__init__(log_identifier) + + # Open a handle to the Config database + self.config_db = swsscommon.DBConnector("CONFIG_DB", + self.REDIS_TIMEOUT_MS, + True) + + # Open a handle to the Application database + self.appl_db = swsscommon.DBConnector("APPL_DB", + self.REDIS_TIMEOUT_MS, + True) + + self.pending_cmds = {} + + def is_port_up(self, port_name): + """ + Determine if a port is up or down by looking into the oper-status for the port in + PORT TABLE in the Application DB + """ + # Retrieve all entires for this port from the Port table + port_table = swsscommon.Table(self.appl_db, swsscommon.APP_PORT_TABLE_NAME) + (status, fvp) = port_table.get(port_name) + if status: + # Convert list of tuples to a dictionary + port_table_dict = dict(fvp) + + # Get the oper-status for the port + if "oper_status" in port_table_dict: + port_oper_status = port_table_dict.get("oper_status") + self.log_info("Port name {} oper status: {}".format(port_name, port_oper_status)) + return port_oper_status == "up" + else: + return False + else: + # Retrieve PortInitDone entry from the Port table + (init_status, init_fvp) = port_table.get("PortInitDone") + # The initialization procedure is done, but don't have this port entry + if init_status: + self.log_error("Port '{}' not found in {} table in App DB".format( + port_name, swsscommon.APP_PORT_TABLE_NAME)) + return False + + def generate_pending_lldp_config_cmd_for_port(self, port_name): + """ + For port `port_name`, look up the description and alias in the Config database, + then form the appropriate lldpcli configuration command and run it. + """ + port_desc = None + + # Retrieve all entires for this port from the Port table + port_table = swsscommon.Table(self.config_db, swsscommon.CFG_PORT_TABLE_NAME) + (status, fvp) = port_table.get(port_name) + if status: + # Convert list of tuples to a dictionary + port_table_dict = dict(fvp) + + # Get the port alias. If None or empty string, use port name instead + port_alias = port_table_dict.get("alias") + if not port_alias: + self.log_info("Unable to retrieve port alias for port '{}'. Using port name instead.".format(port_name)) + port_alias = port_name + + # Get the port description. If None or empty string, we'll skip this configuration + port_desc = port_table_dict.get("description") + + else: + self.log_error("Port '{}' not found in {} table in Config DB. Using port name instead of port alias.".format( + port_name, swsscommon.CFG_PORT_TABLE_NAME)) + port_alias = port_name + + lldpcli_cmd = "lldpcli configure ports {0} lldp portidsubtype local {1}".format(port_name, port_alias) + + # if there is a description available, also configure that + if port_desc: + lldpcli_cmd += " description '{}'".format(port_desc) + else: + self.log_info("Unable to retrieve description for port '{}'. Not adding port description".format(port_name)) + + # Add the command to our dictionary of pending commands, overwriting any + # previous pending command for this port + self.pending_cmds[port_name] = lldpcli_cmd + + def process_pending_cmds(self): + # List of port names (keys of elements) to delete from self.pending_cmds + to_delete = [] + + for (port_name, cmd) in self.pending_cmds.items(): + self.log_debug("Running command: '{}'".format(cmd)) + + rc, stderr = run_cmd(self, cmd) + + # If the command succeeds, add the port name to our to_delete list. + # We will delete this command from self.pending_cmds below. + # If the command fails, log a message, but don't delete the command + # from self.pending_cmds, so that the command will be retried the + # next time this method is called. + if rc == 0: + to_delete.append(port_name) + else: + self.log_warning("Command failed '{}': {}".format(cmd, stderr)) + + # Delete all successful commands from self.pending_cmds + for port_name in to_delete: + self.pending_cmds.pop(port_name, None) + + def run(self): + """ + Subscribes to notifications of changes in the PORT table + of the Redis Config/Application database. + Subscribe to APP_DB - get port oper status + Subscribe to CONFIG_DB - get notified of port config changes + Update LLDP configuration accordingly. + """ + self.log_info("Starting up...") + + if not os.geteuid() == 0: + self.log_error("Must be root to run this daemon") + print("Error: Must be root to run this daemon") + sys.exit(1) + + # Set select timeout to 10 seconds + SELECT_TIMEOUT_MS = 1000 * 10 + + # Daemon is paused on the configuration file to avoid lldp packets with wrong information + # until all interfaces are well configured on lldpd + port_init_done = False + port_config_done = False + resume_lldp_sent = False + start_time = time.time() + + sel = swsscommon.Select() + + # Subscribe to PORT table notifications in the Config DB + sst_confdb = swsscommon.SubscriberStateTable(self.config_db, swsscommon.CFG_PORT_TABLE_NAME) + sel.addSelectable(sst_confdb) + + # Subscribe to PORT table notifications in the App DB + sst_appdb = swsscommon.SubscriberStateTable(self.appl_db, swsscommon.APP_PORT_TABLE_NAME) + sel.addSelectable(sst_appdb) + + # Listen for changes to the PORT table in the CONFIG_DB and APP_DB + while True: + (state, c) = sel.select(SELECT_TIMEOUT_MS) + + if state == swsscommon.Select.OBJECT: + (key, op, fvp) = sst_confdb.pop() + if fvp: + fvp_dict = dict(fvp) + + # handle config change + if ("alias" in fvp_dict or "description" in fvp_dict) and (op in ["SET", "DEL"]): + if self.is_port_up(key): + self.generate_pending_lldp_config_cmd_for_port(key) + else: + self.pending_cmds.pop(key, None) + + (key, op, fvp) = sst_appdb.pop() + if (key != "PortInitDone") and (key != "PortConfigDone"): + if fvp: + fvp_dict = dict(fvp) + + # handle port status change + if "oper_status" in fvp_dict: + if "up" in fvp_dict.get("oper_status"): + self.generate_pending_lldp_config_cmd_for_port(key) + else: + self.pending_cmds.pop(key, None) + + elif key == "PortInitDone": + port_init_done = True + elif key == "PortConfigDone": + port_config_done = True + + # Process all pending commands + self.process_pending_cmds() + + # Resume the daemon since all interfaces data updated and configured to the lldpd so no miss leading packets will be sent + if not resume_lldp_sent: + if check_timeout(self, start_time): + port_init_done = port_config_done = True + if port_init_done and port_config_done: + port_init_done = port_config_done = False + rc, stderr = run_cmd(self, "lldpcli resume") + if rc != 0: + self.log_error("Failed to resume lldpd with command: 'lldpcli resume': {}".format(stderr)) + sys.exit(1) + resume_lldp_sent = True + +# ============================= Functions ============================= + + +def main(): + # Instantiate a LldpManager object + lldpmgr = LldpManager(SYSLOG_IDENTIFIER) + + # Log all messages from INFO level and higher + lldpmgr.set_min_log_priority_info() + + lldpmgr.run() + + +def run_cmd(self, cmd): + proc = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (stdout, stderr) = proc.communicate() + return proc.returncode, stderr + + +def check_timeout(self, start_time): + if time.time() - start_time > PORT_INIT_TIMEOUT: + self.log_error("Port init timeout reached ({} seconds), resuming lldpd...".format(PORT_INIT_TIMEOUT)) + return True + return False + + +if __name__ == "__main__": + main() diff --git a/dockers/docker-lldp/start.sh b/dockers/docker-lldp/start.sh new file mode 100755 index 000000000000..5a489884aea9 --- /dev/null +++ b/dockers/docker-lldp/start.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +CFGGEN_PARAMS=" \ + -d \ + -t /usr/share/sonic/templates/lldpd.conf.j2 \ + -y /etc/sonic/sonic_version.yml \ + -t /usr/share/sonic/templates/lldpdSysDescr.conf.j2 \ +" + +if [ "${RUNTIME_OWNER}" == "" ]; then + RUNTIME_OWNER="kube" +fi + +CTR_SCRIPT="/usr/share/sonic/scripts/container_startup.py" +if test -f ${CTR_SCRIPT} +then + ${CTR_SCRIPT} -f lldp -o ${RUNTIME_OWNER} -v ${IMAGE_VERSION} +fi + +sonic-cfggen $CFGGEN_PARAMS > /etc/lldpd.conf + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +rm -f /var/run/lldpd.socket diff --git a/dockers/docker-lldp/supervisord.conf.j2 b/dockers/docker-lldp/supervisord.conf.j2 new file mode 100644 index 000000000000..3a84caee3040 --- /dev/null +++ b/dockers/docker-lldp/supervisord.conf.j2 @@ -0,0 +1,89 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name lldp +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:lldpd] +# https://github.com/vincentbernat/lldpd/commit/9856f2792c301116cc4a3fcfba91b9672ee5db1f +# - `-d` means to stay in foreground, log to syslog +# - `-dd` means to stay in foreground, log warnings to console +# - `-ddd` means to stay in foreground, log warnings and info to console +# - `-dddd` means to stay in foreground, log all to console +{% if DEVICE_METADATA['localhost']['sub_role'] is defined and DEVICE_METADATA['localhost']['sub_role']|length %} +command=/usr/sbin/lldpd -d -I Ethernet* -C Ethernet* +{% else %} +command=/usr/sbin/lldpd -d -I Ethernet*,eth0 -C eth0 +{% endif %} +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + +[program:waitfor_lldp_ready] +command=/usr/bin/waitfor_lldp_ready.sh +priority=3 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=lldpd:running + +[program:lldp-syncd] +command=/usr/bin/env python3 -m lldp_syncd +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=waitfor_lldp_ready:exited + +[program:lldpmgrd] +command=/usr/bin/lldpmgrd +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=lldp-syncd:running diff --git a/dockers/docker-lldp/waitfor_lldp_ready.sh b/dockers/docker-lldp/waitfor_lldp_ready.sh new file mode 100755 index 000000000000..ecb16dc2e5f0 --- /dev/null +++ b/dockers/docker-lldp/waitfor_lldp_ready.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Current lldpd version has a bug. +# When lldpd starts it is in the pause state by default +# But then it execute 'lldpcli resume' to configure and unpause itself. +# When lldpd execute lldpcli, it doesn't check the return code +# Sometimes lldpcli returns failure, but lldpd doesn't catch it +# and keeps working paused and unconfigured +# +# The fix below addresses the issue. +# + +# wait until lldpd started +until [[ -e /var/run/lldpd.socket ]]; +do + sleep 1; +done + +# Manually try to resume lldpd, until it's successful +while /bin/true; +do + lldpcli -u /var/run/lldpd.socket -c /etc/lldpd.conf -c /etc/lldpd.d resume > /dev/null && break + sleep 1 +done diff --git a/dockers/docker-macsec/Dockerfile.j2 b/dockers/docker-macsec/Dockerfile.j2 new file mode 100644 index 000000000000..9bbfd69e8d5b --- /dev/null +++ b/dockers/docker-macsec/Dockerfile.j2 @@ -0,0 +1,31 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +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_macsec_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_macsec_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_macsec_debs.split(' ')) }} +{%- endif %} + +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor"] +COPY ["etc/wpa_supplicant.conf", "/etc/wpa_supplicant.conf"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/dockers/docker-macsec/critical_processes b/dockers/docker-macsec/critical_processes new file mode 100644 index 000000000000..e11933a7547f --- /dev/null +++ b/dockers/docker-macsec/critical_processes @@ -0,0 +1 @@ +program:macsecmgrd diff --git a/dockers/docker-macsec/etc/wpa_supplicant.conf b/dockers/docker-macsec/etc/wpa_supplicant.conf new file mode 100644 index 000000000000..a49bf6767d8a --- /dev/null +++ b/dockers/docker-macsec/etc/wpa_supplicant.conf @@ -0,0 +1,3 @@ +eapol_version=3 +ap_scan=0 +fast_reauth=1 \ No newline at end of file diff --git a/dockers/docker-macsec/start.sh b/dockers/docker-macsec/start.sh new file mode 100644 index 000000000000..20d602bdd370 --- /dev/null +++ b/dockers/docker-macsec/start.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash + diff --git a/dockers/docker-macsec/supervisord.conf b/dockers/docker-macsec/supervisord.conf new file mode 100644 index 000000000000..5bd0af35887b --- /dev/null +++ b/dockers/docker-macsec/supervisord.conf @@ -0,0 +1,38 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name macsec +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:macsecmgrd] +command=/usr/bin/macsecmgrd +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running \ No newline at end of file diff --git a/dockers/docker-nat/Dockerfile.j2 b/dockers/docker-nat/Dockerfile.j2 new file mode 100644 index 000000000000..36a178a68af2 --- /dev/null +++ b/dockers/docker-nat/Dockerfile.j2 @@ -0,0 +1,38 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, copy_files %} +FROM docker-config-engine-buster + +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 \ + 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/local/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..5edc5eedc3d5 --- /dev/null +++ b/dockers/docker-nat/critical_processes @@ -0,0 +1,2 @@ +program:natmgrd +program: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..cf10d983ab98 --- /dev/null +++ b/dockers/docker-nat/restore_nat_entries.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 + +"""" +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 os +import re +import subprocess +import sys + +from sonic_py_common.logger import Logger +from swsscommon import swsscommon + +SYSLOG_IDENTIFIER = os.path.basename(__file__) + +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+)' + +# Global logger instance +logger = Logger(SYSLOG_IDENTIFIER) +logger.set_min_log_priority_info() + + +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 432000 --src ' + srcip + ' --sport ' + srcport + \ + ' --dst ' + dstip + ' --dport ' + dstport + ' -u ASSURED' + subprocess.call(ctcmd, shell=True) + logger.log_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("STATE_DB", 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.log_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.log_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.log_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.log_error(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.log_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..68603d007a51 --- /dev/null +++ b/dockers/docker-nat/start.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +rm -f /var/run/nat/* + +mkdir -p /var/warmboot/nat diff --git a/dockers/docker-nat/supervisord.conf b/dockers/docker-nat/supervisord.conf new file mode 100644 index 000000000000..f03b0b3772b8 --- /dev/null +++ b/dockers/docker-nat/supervisord.conf @@ -0,0 +1,71 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name nat +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:natmgrd] +command=/usr/bin/natmgrd +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + +[program:natsyncd] +command=/usr/bin/natsyncd +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=natmgrd:running + +[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 +dependent_startup=true +dependent_startup_wait_for=natsyncd:running diff --git a/dockers/docker-orchagent/Dockerfile.j2 b/dockers/docker-orchagent/Dockerfile.j2 new file mode 100755 index 000000000000..17c0983c58b2 --- /dev/null +++ b/dockers/docker-orchagent/Dockerfile.j2 @@ -0,0 +1,78 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +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 && \ + apt-get install -f -y \ + ifupdown \ + arping \ + iproute2 \ + ndisc6 \ + tcpdump \ + libelf1 \ + libmnl0 \ + bridge-utils \ + conntrack \ + ndppd \ + # Needed for installing netifaces Python package + build-essential \ + python3-dev + +{% if ( CONFIGURED_ARCH == "armhf" or CONFIGURED_ARCH == "arm64" ) %} +# Fix for gcc/python not found in arm docker +RUN apt-get install -f -y python2.7 python2.7-dev +RUN apt-get install -y gcc-8 +{% endif %} +{% if CONFIGURED_ARCH == "armhf" %} +RUN ln -s -f /usr/bin/gcc-8 /usr/bin/arm-linux-gnueabihf-gcc +{% endif %} +{% if CONFIGURED_ARCH == "arm64" %} +RUN ln -s -f /usr/bin/gcc-8 /usr/bin/aarch64-linux-gnu-gcc +{% endif %} + +# Dependencies of restore_neighbors.py +RUN pip3 install \ + scapy==2.4.4 \ + pyroute2==0.5.14 \ + netifaces==0.10.9 + +{% if ( CONFIGURED_ARCH == "armhf" or CONFIGURED_ARCH == "arm64" ) %} +# Remove installed gcc +RUN apt-get remove -y gcc-8 +{% endif %} + +{% if docker_orchagent_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_orchagent_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_orchagent_debs.split(' ')) }} +{%- endif %} + +# Clean up +RUN apt-get purge -y \ + build-essential \ + python3-dev && \ + apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs + +COPY ["files/arp_update", "/usr/bin"] +COPY ["arp_update.conf", "files/arp_update_vars.j2", "/usr/share/sonic/templates/"] +COPY ["ndppd.conf", "/usr/share/sonic/templates/"] +COPY ["enable_counters.py", "/usr/bin"] +COPY ["docker-init.sh", "orchagent.sh", "swssconfig.sh", "buffermgrd.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor/"] + +# Copy all Jinja2 template files into the templates folder +COPY ["*.j2", "/usr/share/sonic/templates/"] + +ENTRYPOINT ["/usr/bin/docker-init.sh"] diff --git a/dockers/docker-orchagent/arp_update.conf b/dockers/docker-orchagent/arp_update.conf new file mode 100644 index 000000000000..a27a3b391cd2 --- /dev/null +++ b/dockers/docker-orchagent/arp_update.conf @@ -0,0 +1,9 @@ +[program:arp_update] +command=/usr/bin/arp_update +priority=7 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited 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..1dcf4bf9b6d9 --- /dev/null +++ b/dockers/docker-orchagent/base_image_files/monit_swss @@ -0,0 +1,56 @@ +############################################################################### +## Monit configuration for swss container +## process list: +## orchagent +## portsyncd +## neighsyncd +## fdbsyncd +## vrfmgrd +## vlanmgrd +## intfmgrd +## portmgrd +## buffermgrd +## nbrmgrd +## vxlanmgrd +## coppmgrd +## tunnelmgrd + +############################################################################## +check program swss|orchagent with path "/usr/bin/process_checker swss /usr/bin/orchagent -d /var/log/swss" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|portsyncd with path "/usr/bin/process_checker swss /usr/bin/portsyncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|neighsyncd with path "/usr/bin/process_checker swss /usr/bin/neighsyncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|fdbsyncd with path "/usr/bin/process_checker swss /usr/bin/fdbsyncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|vrfmgrd with path "/usr/bin/process_checker swss /usr/bin/vrfmgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|vlanmgrd with path "/usr/bin/process_checker swss /usr/bin/vlanmgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|intfmgrd with path "/usr/bin/process_checker swss /usr/bin/intfmgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|portmgrd with path "/usr/bin/process_checker swss /usr/bin/portmgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|buffermgrd with path "/usr/bin/process_checker swss /usr/bin/buffermgrd -l" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|nbrmgrd with path "/usr/bin/process_checker swss /usr/bin/nbrmgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|vxlanmgrd with path "/usr/bin/process_checker swss /usr/bin/vxlanmgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|coppmgrd with path "/usr/bin/process_checker swss /usr/bin/coppmgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program swss|tunnelmgrd with path "/usr/bin/process_checker swss /usr/bin/tunnelmgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/dockers/docker-orchagent/base_image_files/swssloglevel b/dockers/docker-orchagent/base_image_files/swssloglevel new file mode 100755 index 000000000000..533bcb893a02 --- /dev/null +++ b/dockers/docker-orchagent/base_image_files/swssloglevel @@ -0,0 +1,44 @@ +#!/bin/bash + +# read SONiC immutable variables +[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment + +function help() +{ + echo -e "Usage: $0 -n [0 to $(($NUM_ASIC-1))] [OPTION]... " 1>&2; exit 1; +} + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +DEV="" +PLATFORM=${PLATFORM:-`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`} + +# Parse the device specific asic conf file, if it exists +ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf +[ -f $ASIC_CONF ] && . $ASIC_CONF + +if [[ ($NUM_ASIC -gt 1) ]]; then + while getopts ":n:h:" opt; do + case "${opt}" in + h) help + ;; + n) DEV=${OPTARG} + [ $DEV -lt $NUM_ASIC -a $DEV -ge 0 ] || help + ;; + esac + done + + if [ -z "${DEV}" ]; then + help + fi + + # Skip the arguments -n while passing to docker command + shift 2 +fi + +docker exec -$DOCKER_EXEC_FLAGS swss$DEV swssloglevel "$@" diff --git a/dockers/docker-orchagent/buffermgrd.sh b/dockers/docker-orchagent/buffermgrd.sh new file mode 100755 index 000000000000..1d09cfc7d6ee --- /dev/null +++ b/dockers/docker-orchagent/buffermgrd.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +BUFFER_CALCULATION_MODE=$(redis-cli -n 4 hget "DEVICE_METADATA|localhost" buffer_model) + +if [ "$BUFFER_CALCULATION_MODE" == "dynamic" ]; then + if [ -f /etc/sonic/peripheral_table.json ]; then + BUFFERMGRD_ARGS="-a /etc/sonic/asic_table.json -p /etc/sonic/peripheral_table.json" + else + BUFFERMGRD_ARGS="-a /etc/sonic/asic_table.json" + fi +else + # Should we use the fallback MAC in case it is not found in Device.Metadata + BUFFERMGRD_ARGS="-l /usr/share/sonic/hwsku/pg_profile_lookup.ini" +fi + +exec /usr/bin/buffermgrd ${BUFFERMGRD_ARGS} diff --git a/dockers/docker-orchagent/critical_processes b/dockers/docker-orchagent/critical_processes new file mode 100644 index 000000000000..a650bdca2a93 --- /dev/null +++ b/dockers/docker-orchagent/critical_processes @@ -0,0 +1,13 @@ +program:orchagent +program:portsyncd +program:neighsyncd +program:fdbsyncd +program:vlanmgrd +program:intfmgrd +program:portmgrd +program:buffermgrd +program:vrfmgrd +program:nbrmgrd +program:vxlanmgrd +program:coppmgrd +program:tunnelmgrd diff --git a/dockers/docker-orchagent/docker-init.sh b/dockers/docker-orchagent/docker-init.sh new file mode 100755 index 000000000000..5bf5bf2d06cf --- /dev/null +++ b/dockers/docker-orchagent/docker-init.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +mkdir -p /etc/swss/config.d/ + +CFGGEN_PARAMS=" \ + -d \ + -y /etc/sonic/constants.yml \ + -t /usr/share/sonic/templates/switch.json.j2,/etc/swss/config.d/switch.json \ + -t /usr/share/sonic/templates/ipinip.json.j2,/etc/swss/config.d/ipinip.json \ + -t /usr/share/sonic/templates/ports.json.j2,/etc/swss/config.d/ports.json \ + -t /usr/share/sonic/templates/vlan_vars.j2 \ + -t /usr/share/sonic/templates/ndppd.conf.j2,/etc/ndppd.conf \ +" +VLAN=$(sonic-cfggen $CFGGEN_PARAMS) + +# Executed HWSKU specific initialization tasks. +if [ -x /usr/share/sonic/hwsku/hwsku-init ]; then + /usr/share/sonic/hwsku/hwsku-init +fi + +# Start arp_update and NDP proxy daemon when VLAN exists +if [ "$VLAN" != "" ]; then + cp /usr/share/sonic/templates/arp_update.conf /etc/supervisor/conf.d/ + cp /usr/share/sonic/templates/ndppd.conf /etc/supervisor/conf.d/ +fi + +exec /usr/local/bin/supervisord diff --git a/dockers/docker-orchagent/enable_counters.py b/dockers/docker-orchagent/enable_counters.py new file mode 100755 index 000000000000..5455f5923571 --- /dev/null +++ b/dockers/docker-orchagent/enable_counters.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 + +import time +import swsssdk + +# ALPHA defines the size of the window over which we calculate the average value. ALPHA is 2/(N+1) where N is the interval(window size) +# In this case we configure the window to be 10s. This way if we have a huge 1s spike in traffic, +# the average rate value will show a curve descending from the spike to the usual rate over approximately 10s. +DEFAULT_SMOOTH_INTERVAL = '10' +DEFAULT_ALPHA = '0.18' + + +def enable_counter_group(db, name): + info = {} + info['FLEX_COUNTER_STATUS'] = 'enable' + db.mod_entry("FLEX_COUNTER_TABLE", name, info) + + +def enable_rates(): + # set the default interval for rates + counters_db = swsssdk.SonicV2Connector() + counters_db.connect('COUNTERS_DB') + counters_db.set('COUNTERS_DB', 'RATES:PORT', 'PORT_SMOOTH_INTERVAL', DEFAULT_SMOOTH_INTERVAL) + counters_db.set('COUNTERS_DB', 'RATES:PORT', 'PORT_ALPHA', DEFAULT_ALPHA) + counters_db.set('COUNTERS_DB', 'RATES:RIF', 'RIF_SMOOTH_INTERVAL', DEFAULT_SMOOTH_INTERVAL) + counters_db.set('COUNTERS_DB', 'RATES:RIF', 'RIF_ALPHA', DEFAULT_ALPHA) + + +def enable_counters(): + db = swsssdk.ConfigDBConnector() + db.connect() + enable_counter_group(db, 'PORT') + enable_counter_group(db, 'RIF') + enable_counter_group(db, 'QUEUE') + enable_counter_group(db, 'PFCWD') + enable_counter_group(db, 'PG_WATERMARK') + enable_counter_group(db, 'PG_DROP') + enable_counter_group(db, 'QUEUE_WATERMARK') + enable_counter_group(db, 'BUFFER_POOL_WATERMARK') + enable_counter_group(db, 'PORT_BUFFER_DROP') + enable_rates() + + +def get_uptime(): + with open('/proc/uptime') as fp: + return float(fp.read().split(' ')[0]) + + +def main(): + # If the switch was just started (uptime less than 5 minutes), + # wait for 3 minutes and enable counters + # otherwise wait for 60 seconds and enable counters + uptime = get_uptime() + if uptime < 300: + time.sleep(180) + else: + time.sleep(60) + enable_counters() + + +if __name__ == '__main__': + main() diff --git a/dockers/docker-orchagent/ipinip.json.j2 b/dockers/docker-orchagent/ipinip.json.j2 new file mode 100644 index 000000000000..cbfeb784b057 --- /dev/null +++ b/dockers/docker-orchagent/ipinip.json.j2 @@ -0,0 +1,81 @@ +{% set ipv4_addresses = [] %} +{% set ipv6_addresses = [] %} +{% set ipv4_loopback_addresses = [] %} +{% set ipv6_loopback_addresses = [] %} +{% if DEVICE_METADATA['localhost']['sub_role'] == 'FrontEnd' or DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd'%} +{% set loopback_intf_names = ['Loopback0', 'Loopback4096'] %} +{% else %} +{% set loopback_intf_names = ['Loopback0'] %} +{% endif %} +{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %} + {%- if prefix | ipv4 and name in loopback_intf_names %} + {%- set ipv4_addresses = ipv4_addresses.append(prefix) %} + {%- set ipv4_loopback_addresses = ipv4_loopback_addresses.append(prefix) %} + {%- endif %} + {%- if prefix | ipv6 and name in loopback_intf_names %} + {%- set ipv6_addresses = ipv6_addresses.append(prefix) %} + {%- set ipv6_loopback_addresses = ipv6_loopback_addresses.append(prefix) %} + {%- endif %} +{% endfor %} +{% for (name, prefix) in INTERFACE|pfx_filter %} + {%- if prefix | ipv4 %} + {%- set ipv4_addresses = ipv4_addresses.append(prefix) %} + {%- endif %} + {%- if prefix | ipv6 %} + {%- set ipv6_addresses = ipv6_addresses.append(prefix) %} + {%- endif %} +{% endfor %} +{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %} + {%- if prefix | ipv4 %} + {%- set ipv4_addresses = ipv4_addresses.append(prefix) %} + {%- endif %} + {%- if prefix | ipv6 %} + {%- set ipv6_addresses = ipv6_addresses.append(prefix) %} + {%- endif %} +{% endfor %} +{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %} + {%- if prefix | ipv4 %} + {%- set ipv4_addresses = ipv4_addresses.append(prefix) %} + {%- endif %} + {%- if prefix | ipv6 %} + {%- set ipv6_addresses = ipv6_addresses.append(prefix) %} + {%- endif %} +{% endfor %} +[ +{% if ipv4_loopback_addresses %} + { + "TUNNEL_DECAP_TABLE:IPINIP_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"{% for prefix in ipv4_addresses|sort %}{{ prefix | ip }}{% if not loop.last %},{% endif %}{% endfor %}", +{% if "mlnx" in DEVICE_METADATA.localhost.platform %} + "dscp_mode":"uniform", + "ecn_mode":"standard", +{% else %} + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", +{% endif %} + "ttl_mode":"pipe" + }, + "OP": "SET" + } +{% endif %} +{% if ipv4_loopback_addresses and ipv6_loopback_addresses %} , +{% endif %} +{% if ipv6_loopback_addresses %} + { + "TUNNEL_DECAP_TABLE:IPINIP_V6_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"{% for prefix in ipv6_addresses|sort %}{{ prefix | ip }}{% if not loop.last %},{% endif %}{% endfor %}", +{% if "mlnx" in DEVICE_METADATA.localhost.platform %} + "dscp_mode":"uniform", + "ecn_mode":"standard", +{% else %} + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", +{% endif %} + "ttl_mode":"pipe" + }, + "OP": "SET" + } +{% endif %} +] diff --git a/dockers/docker-orchagent/ndppd.conf b/dockers/docker-orchagent/ndppd.conf new file mode 100644 index 000000000000..1e97bf97e313 --- /dev/null +++ b/dockers/docker-orchagent/ndppd.conf @@ -0,0 +1,9 @@ +[program:ndppd] +command=bash -c "/usr/sbin/ndppd | /usr/bin/logger" +priority=7 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited \ No newline at end of file diff --git a/dockers/docker-orchagent/ndppd.conf.j2 b/dockers/docker-orchagent/ndppd.conf.j2 new file mode 100644 index 000000000000..bc375f3c4987 --- /dev/null +++ b/dockers/docker-orchagent/ndppd.conf.j2 @@ -0,0 +1,37 @@ +{% block banner %} +# =========== Managed by sonic-cfggen -- DO NOT edit manually! ==================== +# Generated by /usr/share/sonic/templates/ndppd.conf.j2 using config DB data +# File: /etc/ndppd.conf +# +{% endblock banner %} +# Config file for ndppd, the NDP Proxy Daemon +# See man page for ndppd.conf.5 for descriptions of all available options +{% if VLAN_INTERFACE and VLAN_INTERFACE|pfx_filter|length > 0%} +{# Get all VLAN interfaces that have proxy_arp enabled #} +{% set proxy_interfaces = {} %} +{% for intf in VLAN_INTERFACE %} +{% if "proxy_arp" in VLAN_INTERFACE[intf] and VLAN_INTERFACE[intf]["proxy_arp"] == "enabled" %} +{% set _x = proxy_interfaces.update({intf: []}) %} +{% endif %} +{% endfor -%} + +{# Add each IPv6 prefix from each proxy_arp interface #} +{% for (intf, prefix) in VLAN_INTERFACE|pfx_filter %} +{% if intf in proxy_interfaces and prefix | ipv6 %} +{% set _x = proxy_interfaces[intf].append(prefix) %} +{% endif %} +{% endfor -%} + +{% for intf, prefix_list in proxy_interfaces.items() %} +{% if prefix_list %} + +proxy {{ intf }} { +{% for prefix in prefix_list %} + rule {{ prefix | network }}/{{ prefix | prefixlen }} { + static + } +{% endfor %} +} +{% endif %} +{% endfor %} +{% endif %} \ No newline at end of file diff --git a/dockers/docker-orchagent/orchagent.sh b/dockers/docker-orchagent/orchagent.sh new file mode 100755 index 000000000000..aaa047a42036 --- /dev/null +++ b/dockers/docker-orchagent/orchagent.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +SWSS_VARS_FILE=/usr/share/sonic/templates/swss_vars.j2 + +# Retrieve SWSS vars from sonic-cfggen +SWSS_VARS=$(sonic-cfggen -d -y /etc/sonic/sonic_version.yml -t $SWSS_VARS_FILE) || exit 1 +export platform=$(echo $SWSS_VARS | jq -r '.asic_type') + +MAC_ADDRESS=$(echo $SWSS_VARS | jq -r '.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 +ORCHAGENT_ARGS="-d /var/log/swss " + +# Set orchagent pop batch size to 8192 +ORCHAGENT_ARGS+="-b 8192 " + +# Set synchronous mode if it is enabled in CONFIG_DB +SYNC_MODE=$(echo $SWSS_VARS | jq -r '.synchronous_mode') +if [ "$SYNC_MODE" == "enable" ]; then + ORCHAGENT_ARGS+="-s " +fi + +# Check if there is an "asic_id field" in the DEVICE_METADATA in configDB. +#"DEVICE_METADATA": { +# "localhost": { +# .... +# "asic_id": "0", +# } +#}, +# ID field could be integers just to denote the asic instance like 0,1,2... +# OR could be PCI device ID's which will be strings like "03:00.0" +# depending on what the SAI/SDK expects. +asic_id=$(echo $SWSS_VARS | jq -r '.asic_id') +if [ -n "$asic_id" ] +then + ORCHAGENT_ARGS+="-i $asic_id " +fi + +# for multi asic platforms add the asic name to the record file names +if [[ "$NAMESPACE_ID" ]]; then + ORCHAGENT_ARGS+="-f swss.asic$NAMESPACE_ID.rec -j sairedis.asic$NAMESPACE_ID.rec " +fi + +# Add platform specific arguments if necessary +if [ "$platform" == "broadcom" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "cavium" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "nephos" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "centec" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "barefoot" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "vs" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "mellanox" ]; then + ORCHAGENT_ARGS+="" +elif [ "$platform" == "innovium" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +else + # Should we use the fallback MAC in case it is not found in Device.Metadata + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +fi + +exec /usr/bin/orchagent ${ORCHAGENT_ARGS} diff --git a/dockers/docker-orchagent/ports.json.j2 b/dockers/docker-orchagent/ports.json.j2 new file mode 100644 index 000000000000..296d97cde07b --- /dev/null +++ b/dockers/docker-orchagent/ports.json.j2 @@ -0,0 +1,20 @@ +[ +{% set ports_with_speed_set=[] %} +{% if PORT %} +{% for port in PORT %} +{% if 'speed' in PORT[port] %} + {%- if ports_with_speed_set.append(port) -%}{%- endif -%} +{%- endif -%} +{% endfor %} +{% for port in ports_with_speed_set %} + { + "PORT_TABLE:{{ port }}": { + "speed": "{{ PORT[port]['speed'] }}", + "description": "{{ PORT[port]['description'] }}" + }, + "OP": "SET" + }{% if not loop.last %},{% endif %} + +{% endfor %} +{% endif %} +] diff --git a/dockers/docker-orchagent/supervisord.conf b/dockers/docker-orchagent/supervisord.conf new file mode 100644 index 000000000000..af68c8c38ab7 --- /dev/null +++ b/dockers/docker-orchagent/supervisord.conf @@ -0,0 +1,207 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=100 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name swss +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:gearsyncd] +command=/usr/bin/gearsyncd -p /usr/share/sonic/hwsku/gearbox_config.json +priority=3 +autostart=false +autorestart=false +startsecs=0 +startretries=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:portsyncd] +command=/usr/bin/portsyncd +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:orchagent] +command=/usr/bin/orchagent.sh +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=portsyncd:running + +[program:swssconfig] +command=/usr/bin/swssconfig.sh +priority=5 +autostart=false +autorestart=unexpected +startretries=0 +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=orchagent:running + +[program:restore_neighbors] +command=/usr/bin/restore_neighbors.py +priority=6 +autostart=false +autorestart=false +startsecs=0 +startretries=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:coppmgrd] +command=/usr/bin/coppmgrd +priority=6 +autostart=false +autorestart=false +startretries=0 +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=orchagent:running + +[program:neighsyncd] +command=/usr/bin/neighsyncd +priority=7 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:vlanmgrd] +command=/usr/bin/vlanmgrd +priority=8 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:intfmgrd] +command=/usr/bin/intfmgrd +priority=9 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:portmgrd] +command=/usr/bin/portmgrd +priority=10 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:buffermgrd] +command=/usr/bin/buffermgrd.sh +priority=11 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:vrfmgrd] +command=/usr/bin/vrfmgrd +priority=13 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:nbrmgrd] +command=/usr/bin/nbrmgrd +priority=15 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:vxlanmgrd] +command=/usr/bin/vxlanmgrd +priority=16 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:tunnelmgrd] +command=/usr/bin/tunnelmgrd +priority=17 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:enable_counters] +command=/usr/bin/enable_counters.py +priority=12 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + +[program:fdbsyncd] +command=/usr/bin/fdbsyncd +priority=17 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited + diff --git a/dockers/docker-orchagent/switch.json.j2 b/dockers/docker-orchagent/switch.json.j2 new file mode 100644 index 000000000000..4d2a0be1b051 --- /dev/null +++ b/dockers/docker-orchagent/switch.json.j2 @@ -0,0 +1,27 @@ +{# the range of hash_seed is 0-15 #} +{# set default hash seed to 0 #} +{% set hash_seed = 0 %} +{% set hash_seed_offset = 0 %} +{% if DEVICE_METADATA.localhost.type %} +{% if "ToRRouter" in DEVICE_METADATA.localhost.type %} +{% set hash_seed = 0 %} +{% elif "LeafRouter" in DEVICE_METADATA.localhost.type %} +{% set hash_seed = 10 %} +{% elif "SpineRouter" in DEVICE_METADATA.localhost.type %} +{% set hash_seed = 25 %} +{% endif %} +{% endif %} +{% if DEVICE_METADATA.localhost.namespace_id %} +{% set hash_seed_offset = DEVICE_METADATA.localhost.namespace_id | int %} +{% endif %} +{% set hash_seed_value = hash_seed_offset + hash_seed %} +[ + { + "SWITCH_TABLE:switch": { + "ecmp_hash_seed": "{{ hash_seed_value }}", + "lag_hash_seed": "{{ hash_seed_value }}", + "fdb_aging_time": "600" + }, + "OP": "SET" + } +] diff --git a/dockers/docker-orchagent/swssconfig.sh b/dockers/docker-orchagent/swssconfig.sh new file mode 100755 index 000000000000..0081d074ad60 --- /dev/null +++ b/dockers/docker-orchagent/swssconfig.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +set -e + +function fast_reboot { + case "$(cat /proc/cmdline)" in + *fast-reboot*) + if [[ -f /fdb.json ]]; + then + swssconfig /fdb.json + mv -f /fdb.json /fdb.json.1 + fi + + if [[ -f /arp.json ]]; + then + swssconfig /arp.json + mv -f /arp.json /arp.json.1 + fi + + if [[ -f /default_routes.json ]]; + then + swssconfig /default_routes.json + mv -f /default_routes.json /default_routes.json.1 + fi + + ;; + *) + ;; + esac +} + +# Wait until swss.sh in the host system create file swss:/ready +until [[ -e /ready ]]; do + sleep 0.1; +done + +rm -f /ready + +# Restore FDB and ARP table ASAP +fast_reboot + +# read SONiC immutable variables +[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment + +HWSKU=${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=`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 + exit 0 +fi + +SWSSCONFIG_ARGS="ipinip.json ports.json switch.json " + +for file in $SWSSCONFIG_ARGS; do + swssconfig /etc/swss/config.d/$file + sleep 1 +done diff --git a/dockers/docker-orchagent/vlan_vars.j2 b/dockers/docker-orchagent/vlan_vars.j2 new file mode 100644 index 000000000000..55db548043a3 --- /dev/null +++ b/dockers/docker-orchagent/vlan_vars.j2 @@ -0,0 +1 @@ +{%- if VLAN -%}{{- VLAN.keys() | join(' ') -}}{%- endif -%} diff --git a/dockers/docker-platform-monitor/Dockerfile.j2 b/dockers/docker-platform-monitor/Dockerfile.j2 new file mode 100755 index 000000000000..fc46dc6a52b9 --- /dev/null +++ b/dockers/docker-platform-monitor/Dockerfile.j2 @@ -0,0 +1,94 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +ARG docker_container_name +ARG image_version +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 + +# Pass the image_version to container +ENV IMAGE_VERSION=$image_version + +# Install required packages +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + python3-dev \ + ipmitool \ + librrd8 \ + librrd-dev \ + rrdtool \ + python-smbus \ + python3-smbus \ + ethtool \ + dmidecode \ + i2c-tools + +# TODO: Remove these lines once we no longer need Python 2 +RUN apt-get install -f -y python-dev python-pip +RUN pip2 install --upgrade 'pip<21' +RUN apt-get purge -y python-pip +RUN pip2 install 'setuptools==40.8.0' + +# On Arista devices, the sonic_platform wheel is not installed in the container. +# Instead, the installation directory is mounted from the host OS. However, this method +# doesn't ensure all dependencies are installed in the container. So here we +# install any dependencies required by the Arista sonic_platform package. +# TODO: eliminate the need to install these explicitly. +# NOTE: Only install enum34 for Python 2, as our version of Python 3 is 3.7, which +# contains 'enum' as part of the standard library. Installing enum34 there will +# cause conflicts. +RUN pip2 install enum34 + +# Barefoot platform vendors' sonic_platform packages import the Python 'thrift' library +RUN pip2 install thrift==0.13.0 +RUN pip3 install thrift==0.13.0 + +{% if docker_platform_monitor_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_platform_monitor_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_platform_monitor_debs.split(' ')) }} +{%- endif %} + +{% if docker_platform_monitor_pydebs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("python-debs/", docker_platform_monitor_pydebs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_platform_monitor_pydebs.split(' ')) }} +{%- endif %} + +{% if docker_platform_monitor_whls.strip() -%} +# Copy locally-built Python wheel dependencies +{{ copy_files("python-wheels/", docker_platform_monitor_whls.split(' '), "/python-wheels/") }} + +# Install locally-built Python wheel dependencies +{{ install_python_wheels(docker_platform_monitor_whls.split(' ')) }} +{% endif %} + + +# TODO: Remove this line once we no longer need Python 2 +RUN apt-get purge -y python-dev + +# Clean up +RUN apt-get purge -y \ + build-essential \ + python3-dev && \ + apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs \ + /python-wheels \ + ~/.cache + +COPY ["docker_init.sh", "lm-sensors.sh", "/usr/bin/"] +COPY ["docker-pmon.supervisord.conf.j2", "/usr/share/sonic/templates/"] +COPY ["ssd_tools/*", "/usr/bin/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor"] + +ENTRYPOINT ["/usr/bin/docker_init.sh"] diff --git a/dockers/docker-platform-monitor/base_image_files/cmd_wrapper b/dockers/docker-platform-monitor/base_image_files/cmd_wrapper new file mode 100755 index 000000000000..74e5dd7ab9cb --- /dev/null +++ b/dockers/docker-platform-monitor/base_image_files/cmd_wrapper @@ -0,0 +1,10 @@ +#!/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 $(basename $0) "$@" diff --git a/dockers/docker-platform-monitor/critical_processes b/dockers/docker-platform-monitor/critical_processes new file mode 100644 index 000000000000..3165d13ecdbc --- /dev/null +++ b/dockers/docker-platform-monitor/critical_processes @@ -0,0 +1,3 @@ +program:ledd +program:xcvrd +program:psud diff --git a/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2 b/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2 new file mode 100644 index 000000000000..c205d3cc25dc --- /dev/null +++ b/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2 @@ -0,0 +1,150 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=100 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name pmon +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +{% if not skip_chassisd and IS_MODULAR_CHASSIS == 1 %} +[program:chassisd] +command=/usr/local/bin/chassisd +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=0 +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running +{% endif %} + +{% if not skip_sensors and HAVE_SENSORS_CONF == 1 %} +[program:lm-sensors] +command=/usr/bin/lm-sensors.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=0 +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running +{% endif %} + +{% if not skip_fancontrol and HAVE_FANCONTROL_CONF == 1 %} +[program:fancontrol] +command=/usr/sbin/fancontrol +priority=4 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=10 +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running +{% endif %} + +{% if not skip_ledd %} +[program:ledd] +command={% if API_VERSION == 3 and 'ledd' not in python2_daemons %}python3 {% else %} python2 {% endif %}/usr/local/bin/ledd +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=0 +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running +{% endif %} + +{% if not skip_xcvrd %} +[program:xcvrd] +{% if delay_xcvrd %} +command=bash -c "sleep 30 && {% if API_VERSION == 3 and 'xcvrd' not in python2_daemons %}python3 {% else %} python2 {% endif %}/usr/local/bin/xcvrd" +{% else %} +command={% if API_VERSION == 3 and 'xcvrd' not in python2_daemons %}python3 {% else %} python2 {% endif %}/usr/local/bin/xcvrd +{% endif %} +priority=6 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=0 +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running +{% endif %} + +{% if not skip_psud %} +[program:psud] +command={% if API_VERSION == 3 and 'psud' not in python2_daemons %}python3 {% else %} python2 {% endif %}/usr/local/bin/psud +priority=7 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=0 +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running +{% endif %} + +{% if not skip_syseepromd %} +[program:syseepromd] +command={% if API_VERSION == 3 and 'syseepromd' not in python2_daemons %}python3 {% else %} python2 {% endif %}/usr/local/bin/syseepromd +priority=8 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=10 +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running +{% endif %} + +{% if not skip_thermalctld %} +[program:thermalctld] +command={% if API_VERSION == 3 and 'thermalctld' not in python2_daemons %}python3 {% else %} python2 {% endif %}/usr/local/bin/thermalctld +priority=9 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=10 +startretries=50 +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running +{% endif %} + +{% if not skip_pcied %} +[program:pcied] +command=/usr/local/bin/pcied +priority=10 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=10 +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running +{% endif %} diff --git a/dockers/docker-platform-monitor/docker_init.sh b/dockers/docker-platform-monitor/docker_init.sh new file mode 100755 index 000000000000..6fc7ffeb5114 --- /dev/null +++ b/dockers/docker-platform-monitor/docker_init.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash + +# Generate supervisord config file and the start.sh scripts +mkdir -p /etc/supervisor/conf.d/ + +SENSORS_CONF_FILE="/usr/share/sonic/platform/sensors.conf" +FANCONTROL_CONF_FILE="/usr/share/sonic/platform/fancontrol" + +SUPERVISOR_CONF_TEMPLATE="/usr/share/sonic/templates/docker-pmon.supervisord.conf.j2" +SUPERVISOR_CONF_FILE="/etc/supervisor/conf.d/supervisord.conf" +PMON_DAEMON_CONTROL_FILE="/usr/share/sonic/platform/pmon_daemon_control.json" +MODULAR_CHASSISDB_CONF_FILE="/usr/share/sonic/platform/chassisdb.conf" + +HAVE_SENSORS_CONF=0 +HAVE_FANCONTROL_CONF=0 +IS_MODULAR_CHASSIS=0 +# Default use python2 version +SONIC_PLATFORM_API_PYTHON_VERSION=2 + +declare -r EXIT_SUCCESS="0" + +if [ "${RUNTIME_OWNER}" == "" ]; then + RUNTIME_OWNER="kube" +fi + +CTR_SCRIPT="/usr/share/sonic/scripts/container_startup.py" +if test -f ${CTR_SCRIPT} +then + ${CTR_SCRIPT} -f pmon -o ${RUNTIME_OWNER} -v ${IMAGE_VERSION} +fi + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +# If this platform has synchronization script, run it +if [ -e /usr/share/sonic/platform/platform_wait ]; then + /usr/share/sonic/platform/platform_wait + EXIT_CODE="$?" + if [ "${EXIT_CODE}" != "${EXIT_SUCCESS}" ]; then + exit "${EXIT_CODE}" + fi +fi + +# If the Python 2 sonic-platform package is not installed, try to install it +python2 -c "import sonic_platform" > /dev/null 2>&1 || pip2 show sonic-platform > /dev/null 2>&1 +if [ $? -ne 0 ]; then + SONIC_PLATFORM_WHEEL="/usr/share/sonic/platform/sonic_platform-1.0-py2-none-any.whl" + echo "sonic-platform package not installed, attempting to install..." + if [ -e ${SONIC_PLATFORM_WHEEL} ]; then + pip2 install ${SONIC_PLATFORM_WHEEL} + if [ $? -eq 0 ]; then + echo "Successfully installed ${SONIC_PLATFORM_WHEEL}" + else + echo "Error: Failed to install ${SONIC_PLATFORM_WHEEL}" + fi + else + echo "Error: Unable to locate ${SONIC_PLATFORM_WHEEL}" + fi +fi + +# If the Python 3 sonic-platform package is not installed, try to install it +python3 -c "import sonic_platform" > /dev/null 2>&1 || pip3 show sonic-platform > /dev/null 2>&1 +if [ $? -ne 0 ]; then + SONIC_PLATFORM_WHEEL="/usr/share/sonic/platform/sonic_platform-1.0-py3-none-any.whl" + echo "sonic-platform package not installed, attempting to install..." + if [ -e ${SONIC_PLATFORM_WHEEL} ]; then + pip3 install ${SONIC_PLATFORM_WHEEL} + if [ $? -eq 0 ]; then + echo "Successfully installed ${SONIC_PLATFORM_WHEEL}" + SONIC_PLATFORM_API_PYTHON_VERSION=3 + else + echo "Error: Failed to install ${SONIC_PLATFORM_WHEEL}" + fi + else + echo "Error: Unable to locate ${SONIC_PLATFORM_WHEEL}" + fi +else + SONIC_PLATFORM_API_PYTHON_VERSION=3 +fi + +if [ -e $SENSORS_CONF_FILE ]; then + HAVE_SENSORS_CONF=1 + mkdir -p /etc/sensors.d + /bin/cp -f $SENSORS_CONF_FILE /etc/sensors.d/ +fi + +if [ -e $FANCONTROL_CONF_FILE ]; then + HAVE_FANCONTROL_CONF=1 + rm -f /var/run/fancontrol.pid + /bin/cp -f $FANCONTROL_CONF_FILE /etc/ +fi + +if [ -e $MODULAR_CHASSISDB_CONF_FILE ]; then + IS_MODULAR_CHASSIS=1 +fi + +confvar="{\"HAVE_SENSORS_CONF\":$HAVE_SENSORS_CONF, \"HAVE_FANCONTROL_CONF\":$HAVE_FANCONTROL_CONF, \"API_VERSION\":$SONIC_PLATFORM_API_PYTHON_VERSION, \"IS_MODULAR_CHASSIS\":$IS_MODULAR_CHASSIS}" + +if [ -e $PMON_DAEMON_CONTROL_FILE ]; +then + sonic-cfggen -j $PMON_DAEMON_CONTROL_FILE -a "$confvar" -t $SUPERVISOR_CONF_TEMPLATE > $SUPERVISOR_CONF_FILE +else + sonic-cfggen -a "$confvar" -t $SUPERVISOR_CONF_TEMPLATE > $SUPERVISOR_CONF_FILE +fi + +exec /usr/local/bin/supervisord diff --git a/dockers/docker-platform-monitor/lm-sensors.sh b/dockers/docker-platform-monitor/lm-sensors.sh new file mode 100755 index 000000000000..2f4768a8cdda --- /dev/null +++ b/dockers/docker-platform-monitor/lm-sensors.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# +# Based off /etc/init.d/lm-sensors +# + + +# NOTE: lm-sensors v3.3.5 appears to have a bug. If `sensors -s` is called, it +# will first load /etc/sensors.conf, then load all files in /etc/sensors.d/, +# overriding any values that may have already been specified in +# /etc/sensors.conf. However, it appears this overriding is not taking place. +# As a workaround, as long as a platform-specific sensors.conf has been copied +# to /etc/sensors.d/, we will ONLY load that file, otherwise we load the default. +if [ -e /etc/sensors.d/sensors.conf ]; then + /usr/bin/sensors -s -c /etc/sensors.d/sensors.conf > /dev/null 2>&1 +else + /usr/bin/sensors -s > /dev/null 2>&1 +fi + +/usr/bin/sensors > /dev/null 2>&1 + +# Currently, there is no way to run sensord in the foreground, so we +# can't use supervisord. Instead, we just start the service for now. +service sensord start diff --git a/dockers/docker-platform-monitor/ssd_tools/SmartCmd b/dockers/docker-platform-monitor/ssd_tools/SmartCmd new file mode 100755 index 000000000000..dae647e4697e Binary files /dev/null and b/dockers/docker-platform-monitor/ssd_tools/SmartCmd differ diff --git a/dockers/docker-platform-monitor/ssd_tools/iSmart b/dockers/docker-platform-monitor/ssd_tools/iSmart new file mode 100755 index 000000000000..c6bba0046024 Binary files /dev/null and b/dockers/docker-platform-monitor/ssd_tools/iSmart differ diff --git a/dockers/docker-ptf/Dockerfile.j2 b/dockers/docker-ptf/Dockerfile.j2 new file mode 100644 index 000000000000..43eefcd9eeff --- /dev/null +++ b/dockers/docker-ptf/Dockerfile.j2 @@ -0,0 +1,163 @@ +{% if CONFIGURED_ARCH == "armhf" %} +FROM multiarch/debian-debootstrap:armhf-stretch +{% elif CONFIGURED_ARCH == "arm64" %} +FROM multiarch/debian-debootstrap:arm64-stretch +{% else %} +FROM debian:stretch +{% endif %} + +MAINTAINER Pavel Shirshov + +## Remove retired jessie-updates repo +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + +## Copy dependencies +COPY \ +{% for deb in docker_ptf_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +## Set the apt source, update package cache and install necessary packages +## TODO: Clean up this step +RUN sed --in-place 's/httpredir.debian.org/debian-archive.trafficmanager.net/' /etc/apt/sources.list \ + && apt-get update \ + && apt-get upgrade -y \ + && apt-get dist-upgrade -y \ + && apt-get install -y \ + autoconf \ + openssh-server \ + vim \ + telnet \ + net-tools \ + traceroute \ + lsof \ + tcpdump \ + ethtool \ + unzip \ + pkg-config \ + binutils \ + build-essential \ + libssl-dev \ + libffi-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.62.0 \ + less \ + git \ + iputils-ping \ + hping3 \ + curl \ + tmux \ + python \ + python-dev \ + python-libpcap \ + python-scapy \ + python-six \ + tacacs+ \ + rsyslog \ + ntp \ + ntpstat \ + ntpdate \ + arping \ + bridge-utils + +RUN dpkg -i \ +{% for deb in docker_ptf_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +# Install all python modules from pypi. python-scapy is exception, ptf debian package requires python-scapy +# TODO: Clean up this step +RUN rm -rf /debs \ + && apt-get -y autoclean \ + && apt-get -y autoremove \ + && rm -rf /var/lib/apt/lists/* \ + && wget --https-only https://bootstrap.pypa.io/2.7/get-pip.py \ + && python get-pip.py \ + && rm -f get-pip.py \ + && pip install setuptools \ + && pip install supervisor \ + && pip install ipython==5.4.1 \ + && git clone https://github.com/p4lang/scapy-vxlan.git \ + && cd scapy-vxlan \ + && python setup.py install \ + && cd .. \ + && rm -fr scapy-vxlan \ + && git clone https://github.com/sflow/sflowtool \ + && cd sflowtool \ + && ./boot.sh \ + && ./configure \ + && make \ + && make install \ + && cd .. \ + && rm -fr sflowtool \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cd build \ + && cmake .. \ + && make install \ + && ldconfig \ + && cd ../.. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi \ + && pip install nnpy \ + && pip install dpkt \ + && pip install ipaddress \ + && pip install pysubnettree \ + && pip install paramiko \ + && pip install flask \ + && pip install exabgp==3.4.17\ + && pip install pyaml \ + && pip install pybrctl pyro4 rpyc yabgp \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py + +## Adjust sshd settings +RUN mkdir /var/run/sshd \ + && echo 'root:root' | chpasswd \ + && sed -ri '/^#?PermitRootLogin/c\PermitRootLogin yes' /etc/ssh/sshd_config \ + && sed -ri '/^#?UsePAM/c\UsePAM no' /etc/ssh/sshd_config \ + && sed -ri '/^#?UseDNS/c\UseDNS no' /etc/ssh/sshd_config + +COPY supervisord.conf /etc/supervisor/ +COPY conf.d/ /etc/supervisor/conf.d/ +COPY ptf_tgen.sh /ptf_tgen/ + +# Move tcpdump into /usr/bin Otherwise it's impossible to run tcpdump due to a docker bug +RUN mv /usr/sbin/tcpdump /usr/bin/tcpdump +RUN ln -s /usr/bin/tcpdump /usr/sbin/tcpdump + +RUN mkdir -p /var/log/supervisor + +# Install Python-based GNMI client +RUN git clone https://github.com/lguohan/gnxi.git \ + && cd gnxi \ + && git checkout 53901ab \ + && cd gnmi_cli_py \ + && pip install -r requirements.txt + +COPY \ +{% for deb in docker_ptf_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_ptf_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["*.ini", "/etc/ptf/"] +EXPOSE 22 8009 + +ENTRYPOINT ["/usr/local/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] diff --git a/dockers/docker-ptf/brcm_interface_to_front_map.ini b/dockers/docker-ptf/brcm_interface_to_front_map.ini new file mode 100644 index 000000000000..0db110025b8a --- /dev/null +++ b/dockers/docker-ptf/brcm_interface_to_front_map.ini @@ -0,0 +1,33 @@ +# ptf host interface @ switch front port name +0@Ethernet0 +1@Ethernet4 +2@Ethernet8 +3@Ethernet12 +4@Ethernet16 +5@Ethernet20 +6@Ethernet24 +7@Ethernet28 +8@Ethernet32 +9@Ethernet36 +10@Ethernet40 +11@Ethernet44 +12@Ethernet48 +13@Ethernet52 +14@Ethernet56 +15@Ethernet60 +16@Ethernet64 +17@Ethernet68 +18@Ethernet72 +19@Ethernet76 +20@Ethernet80 +21@Ethernet84 +22@Ethernet88 +23@Ethernet92 +24@Ethernet96 +25@Ethernet100 +26@Ethernet104 +27@Ethernet108 +28@Ethernet112 +29@Ethernet116 +30@Ethernet120 +31@Ethernet124 diff --git a/dockers/docker-ptf/conf.d/ptf_nn_agent.conf b/dockers/docker-ptf/conf.d/ptf_nn_agent.conf new file mode 100644 index 000000000000..6fb30d61d7c2 --- /dev/null +++ b/dockers/docker-ptf/conf.d/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 0@tcp://127.0.0.1:10900 -i 0-3@eth3 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/dockers/docker-ptf/conf.d/ptf_tgen.conf b/dockers/docker-ptf/conf.d/ptf_tgen.conf new file mode 100644 index 000000000000..8efd3f1c15f7 --- /dev/null +++ b/dockers/docker-ptf/conf.d/ptf_tgen.conf @@ -0,0 +1,10 @@ +[program:ptf_tgen] +command=/ptf_tgen/ptf_tgen.sh +process_name=ptf_tgen +stdout_logfile=/tmp/ptf_tgen.out.log +stderr_logfile=/tmp/ptf_tgen.err.log +redirect_stderr=false +autostart=false +autorestart=true +startsecs=1 +numprocs=1 diff --git a/docker-ptf/supervisord.conf b/dockers/docker-ptf/conf.d/sshd.conf similarity index 83% rename from docker-ptf/supervisord.conf rename to dockers/docker-ptf/conf.d/sshd.conf index 94559fd0785c..8238e7762fbf 100644 --- a/docker-ptf/supervisord.conf +++ b/dockers/docker-ptf/conf.d/sshd.conf @@ -1,6 +1,3 @@ -[supervisord] -nodaemon=true - [program:sshd] command=/usr/sbin/sshd -D process_name=sshd @@ -10,4 +7,4 @@ redirect_stderr=false autostart=true autorestart=true startsecs=1 -numprocs=1 \ No newline at end of file +numprocs=1 diff --git a/dockers/docker-ptf/conf.d/supervisord.conf b/dockers/docker-ptf/conf.d/supervisord.conf new file mode 100644 index 000000000000..54296b8b254e --- /dev/null +++ b/dockers/docker-ptf/conf.d/supervisord.conf @@ -0,0 +1,2 @@ +[supervisord] +nodaemon=true diff --git a/dockers/docker-ptf/msn_2700_interface_to_front_map.ini b/dockers/docker-ptf/msn_2700_interface_to_front_map.ini new file mode 100644 index 000000000000..4421812aeef9 --- /dev/null +++ b/dockers/docker-ptf/msn_2700_interface_to_front_map.ini @@ -0,0 +1,33 @@ +# ptf host interface @ switch front port name +0@Ethernet1 +1@Ethernet2 +2@Ethernet3 +3@Ethernet4 +4@Ethernet5 +5@Ethernet6 +6@Ethernet7 +7@Ethernet8 +8@Ethernet9 +9@Ethernet10 +10@Ethernet11 +11@Ethernet12 +12@Ethernet13 +13@Ethernet14 +14@Ethernet15 +15@Ethernet16 +16@Ethernet17 +17@Ethernet18 +18@Ethernet19 +19@Ethernet20 +20@Ethernet21 +21@Ethernet22 +22@Ethernet23 +23@Ethernet24 +24@Ethernet25 +25@Ethernet26 +26@Ethernet27 +27@Ethernet28 +28@Ethernet29 +29@Ethernet30 +30@Ethernet31 +31@Ethernet32 diff --git a/dockers/docker-ptf/ptf_tgen.sh b/dockers/docker-ptf/ptf_tgen.sh new file mode 100755 index 000000000000..03593276bdd9 --- /dev/null +++ b/dockers/docker-ptf/ptf_tgen.sh @@ -0,0 +1 @@ +# PLACEHOLDER - This file is intended to be overwritten by SPYTest. diff --git a/dockers/docker-ptf/supervisord.conf b/dockers/docker-ptf/supervisord.conf new file mode 100644 index 000000000000..be71d20a42d9 --- /dev/null +++ b/dockers/docker-ptf/supervisord.conf @@ -0,0 +1,28 @@ +; supervisor config file + +[unix_http_server] +file=/var/run/supervisor.sock ; (the path to the socket file) +chmod=0700 ; socket file mode (default 0700) + +[supervisord] +logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) +pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) +childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) + +; the below section must remain in the config file for RPC +; (supervisorctl/web interface) to work, additional interfaces may be +; added by defining them in separate rpcinterface: sections +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket + +; The [include] section can just contain the "files" setting. This +; setting can list multiple files (separated by whitespace or +; newlines). It can also contain wildcards. The filenames are +; interpreted as relative to this file. Included files *cannot* +; include files themselves. + +[include] +files = /etc/supervisor/conf.d/*.conf diff --git a/dockers/docker-router-advertiser/Dockerfile.j2 b/dockers/docker-router-advertiser/Dockerfile.j2 new file mode 100644 index 000000000000..7d225cbd4e79 --- /dev/null +++ b/dockers/docker-router-advertiser/Dockerfile.j2 @@ -0,0 +1,40 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +ARG docker_container_name +ARG image_version +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 + +# Pass the image_version to container +ENV IMAGE_VERSION=$image_version + +# Update apt's cache of available packages +RUN apt-get update + +# Install radvd Debian package +RUN apt-get -y install radvd=1:2.17-2 + +{% if docker_router_advertiser_debs.strip() -%} +# Copy built Debian packages +{{ copy_files("debs/", docker_router_advertiser_debs.split(' '), "/debs/") }} + +# Install built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_router_advertiser_debs.split(' ')) }} +{%- endif %} + +# Clean up +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs + +COPY ["start.sh", "/usr/bin/"] +COPY ["docker-init.sh", "/usr/bin/"] +COPY ["radvd.conf.j2", "wait_for_link.sh.j2", "docker-router-advertiser.supervisord.conf.j2", "/usr/share/sonic/templates/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor"] + +ENTRYPOINT ["/usr/bin/docker-init.sh"] diff --git a/dockers/docker-router-advertiser/critical_processes b/dockers/docker-router-advertiser/critical_processes new file mode 100644 index 000000000000..a343765f78e0 --- /dev/null +++ b/dockers/docker-router-advertiser/critical_processes @@ -0,0 +1 @@ +program:radvd diff --git a/dockers/docker-router-advertiser/docker-init.sh b/dockers/docker-router-advertiser/docker-init.sh new file mode 100755 index 000000000000..6e1bb5545f82 --- /dev/null +++ b/dockers/docker-router-advertiser/docker-init.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +mkdir -p /etc/supervisor/conf.d + +# Generate supervisord router advertiser config, /etc/radvd.conf config file, and +# the script that waits for pertinent interfaces to come up and make it executable +CFGGEN_PARAMS=" \ + -d \ + -t /usr/share/sonic/templates/docker-router-advertiser.supervisord.conf.j2,/etc/supervisor/conf.d/supervisord.conf \ + -t /usr/share/sonic/templates/radvd.conf.j2,/etc/radvd.conf \ + -t /usr/share/sonic/templates/wait_for_link.sh.j2,/usr/bin/wait_for_link.sh \ +" +sonic-cfggen $CFGGEN_PARAMS + +chmod +x /usr/bin/wait_for_link.sh + +exec /usr/local/bin/supervisord diff --git a/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf.j2 b/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf.j2 new file mode 100644 index 000000000000..9312a1a20c14 --- /dev/null +++ b/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf.j2 @@ -0,0 +1,79 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-script] +command=/usr/bin/supervisor-proc-exit-listener --container-name radv +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +{# Router advertiser should only run on ToR (T0) devices which have #} +{# at least one VLAN interface which has an IPv6 address asigned #} +{# But not for specific deployment_id #} +{%- set vlan_v6 = namespace(count=0) -%} +{%- if DEVICE_METADATA.localhost.deployment_id != "8" -%} + {%- if "ToRRouter" in DEVICE_METADATA.localhost.type and DEVICE_METADATA.localhost.type != "MgmtToRRouter" -%} + {%- if VLAN_INTERFACE -%} + {%- for (name, prefix) in VLAN_INTERFACE|pfx_filter -%} + {# If this VLAN has an IPv6 address... #} + {%- if prefix | ipv6 -%} + {%- set vlan_v6.count = vlan_v6.count + 1 -%} + {%- endif -%} + {%- endfor -%} + {%- endif -%} + {%- endif -%} +{%- endif -%} + +{%- if vlan_v6.count > 0 %} +[program:wait_for_link] +command=/usr/bin/wait_for_link.sh +priority=3 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + +[program:radvd] +command=/usr/sbin/radvd -n +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=wait_for_link:exited +{% endif -%} diff --git a/dockers/docker-router-advertiser/radvd.conf.j2 b/dockers/docker-router-advertiser/radvd.conf.j2 new file mode 100644 index 000000000000..bc323977b134 --- /dev/null +++ b/dockers/docker-router-advertiser/radvd.conf.j2 @@ -0,0 +1,37 @@ +{% block banner %} +# =========== Managed by sonic-cfggen -- DO NOT edit manually! ==================== +# Generated by /usr/share/sonic/templates/radvd.conf.j2 using config DB data +# File: /etc/radvd.conf +# +{% endblock banner %} +# Config file for radvd, the router advertisement daemon +# See man page for radvd.conf for descriptions of all available options +# + +{# If our configuration has VLAN interfaces... #} +{% if VLAN_INTERFACE %} +{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %} +{# If this VLAN has an IPv6 address... #} +{% if prefix | ipv6 %} +interface {{ name }} +{ + IgnoreIfMissing on; + AdvSendAdvert on; + MinRtrAdvInterval 200; + MaxRtrAdvInterval 600; + AdvManagedFlag on; + AdvOtherConfigFlag off; + AdvLinkMTU 9100; + AdvHomeAgentFlag off; + prefix {{ prefix | network }}/{{ prefix | prefixlen }} { + AdvOnLink on; + AdvAutonomous off; + AdvRouterAddr off; + AdvValidLifetime infinity; + AdvPreferredLifetime infinity; + }; +}; + +{% endif %} +{% endfor %} +{% endif %} diff --git a/dockers/docker-router-advertiser/start.sh b/dockers/docker-router-advertiser/start.sh new file mode 100755 index 000000000000..561cd5d7cee1 --- /dev/null +++ b/dockers/docker-router-advertiser/start.sh @@ -0,0 +1,12 @@ +#! /bin/bash + +if [ "${RUNTIME_OWNER}" == "" ]; then + RUNTIME_OWNER="kube" +fi + +CTR_SCRIPT="/usr/share/sonic/scripts/container_startup.py" +if test -f ${CTR_SCRIPT} +then + ${CTR_SCRIPT} -f radv -o ${RUNTIME_OWNER} -v ${IMAGE_VERSION} +fi + diff --git a/dockers/docker-router-advertiser/wait_for_link.sh.j2 b/dockers/docker-router-advertiser/wait_for_link.sh.j2 new file mode 100644 index 000000000000..980b472b3e0a --- /dev/null +++ b/dockers/docker-router-advertiser/wait_for_link.sh.j2 @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +VLAN_TABLE_PREFIX="VLAN_TABLE" + +function wait_until_iface_ready +{ + TABLE_PREFIX=$1 + IFACE=$2 + + echo "Waiting until interface $IFACE is ready..." + + # Wait for the interface to come up + # (i.e., interface is present in STATE_DB and state is "ok") + while true; do + RESULT=$(sonic-db-cli STATE_DB HGET "${TABLE_PREFIX}|${IFACE}" "state" 2> /dev/null) + if [ x"$RESULT" == x"ok" ]; then + break + fi + + sleep 1 + done + + echo "Interface ${IFACE} is ready!" +} + + +# Wait for all interfaces to be up and ready +{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %} +wait_until_iface_ready ${VLAN_TABLE_PREFIX} {{ name }} +{% endfor %} diff --git a/dockers/docker-sflow/Dockerfile.j2 b/dockers/docker-sflow/Dockerfile.j2 new file mode 100644 index 000000000000..476ff3514ace --- /dev/null +++ b/dockers/docker-sflow/Dockerfile.j2 @@ -0,0 +1,35 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +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 && \ + apt-get install -f -y \ + dmidecode \ + libmnl0=1.0.4-2 + +{% if docker_sflow_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_sflow_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_sflow_debs.split(' ')) }} +{%- endif %} + +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs + +RUN sed -ri '/^DAEMON_ARGS=""/c DAEMON_ARGS="-c /var/log/hsflowd.crash"' /etc/init.d/hsflowd + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor"] +COPY ["port_index_mapper.py", "/usr/bin"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] 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..84b36b18ce65 --- /dev/null +++ b/dockers/docker-sflow/base_image_files/monit_sflow @@ -0,0 +1,7 @@ +############################################################################### +## Monit configuration for sflow container +## process list: +## sflowmgrd +############################################################################### +check program sflow|sflowmgrd with path "/usr/bin/process_checker sflow /usr/bin/sflowmgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/dockers/docker-sflow/base_image_files/psample b/dockers/docker-sflow/base_image_files/psample new file mode 100755 index 000000000000..0269eb6e5d09 --- /dev/null +++ b/dockers/docker-sflow/base_image_files/psample @@ -0,0 +1,10 @@ +#!/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 sflow psample "$@" diff --git a/dockers/docker-sflow/base_image_files/sflowtool b/dockers/docker-sflow/base_image_files/sflowtool new file mode 100755 index 000000000000..26e5c7d967cf --- /dev/null +++ b/dockers/docker-sflow/base_image_files/sflowtool @@ -0,0 +1,10 @@ +#!/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 sflow sflowtool "$@" diff --git a/dockers/docker-sflow/critical_processes b/dockers/docker-sflow/critical_processes new file mode 100644 index 000000000000..8180f8ad1c37 --- /dev/null +++ b/dockers/docker-sflow/critical_processes @@ -0,0 +1 @@ +program:sflowmgrd diff --git a/dockers/docker-sflow/port_index_mapper.py b/dockers/docker-sflow/port_index_mapper.py new file mode 100755 index 000000000000..3ee73181a5b4 --- /dev/null +++ b/dockers/docker-sflow/port_index_mapper.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 + +import signal +import sys +import traceback +from sonic_py_common.logger import Logger +from socket import if_nametoindex +from swsssdk import SonicV2Connector, port_util +from swsscommon import swsscommon + +SYSLOG_IDENTIFIER = 'port_index_mapper' + +# Global logger instance +logger = Logger(SYSLOG_IDENTIFIER) +logger.set_min_log_priority_info() + + +class PortIndexMapper(object): + + def __init__(self): + REDIS_TIMEOUT_MS = 0 + # Update this list to support more interfaces + tbl_lst = [swsscommon.STATE_PORT_TABLE_NAME, + swsscommon.STATE_VLAN_TABLE_NAME] + self.appl_db = swsscommon.DBConnector("STATE_DB", + REDIS_TIMEOUT_MS, + True) + + self.state_db = SonicV2Connector(host='127.0.0.1', decode_responses=True) + self.state_db.connect(self.state_db.STATE_DB, False) + self.sel = swsscommon.Select() + self.tbls = [swsscommon.SubscriberStateTable(self.appl_db, t) + for t in tbl_lst] + + self.cur_interfaces = {} + + for t in self.tbls: + self.sel.addSelectable(t) + + def set_port_index_table_entry(self, key, index, ifindex): + self.state_db.set(self.state_db.STATE_DB, key, 'index', index) + self.state_db.set(self.state_db.STATE_DB, key, 'ifindex', ifindex) + + def update_db(self, ifname, op): + index = port_util.get_index_from_str(ifname) + if op == 'SET' and index is None: + return + ifindex = if_nametoindex(ifname) + if op == 'SET' and ifindex is None: + return + + # Check if ifname already exist or if index/ifindex changed due to + # syncd restart + if (ifname in self.cur_interfaces and + self.cur_interfaces[ifname] == (index, ifindex)): + return + + _hash = '{}|{}'.format('PORT_INDEX_TABLE', ifname) + + if op == 'SET': + self.cur_interfaces[ifname] = (index, ifindex) + self.set_port_index_table_entry(_hash, str(index), str(ifindex)) + elif op == 'DEL': + del self.cur_interfaces[ifname] + self.state_db.delete(self.state_db.STATE_DB, _hash) + + def listen(self): + SELECT_TIMEOUT_MS = -1 # Infinite wait + + while True: + (state, c) = self.sel.select(SELECT_TIMEOUT_MS) + if state == swsscommon.Select.OBJECT: + for t in self.tbls: + (key, op, cfvs) = t.pop() + if op == 'DEL' and key in self.cur_interfaces: + self.update_db(key, op) + elif (op == 'SET' and key != 'PortInitDone' and + key != 'PortConfigDone' and + key not in self.cur_interfaces): + self.update_db(key, op) + elif state == swsscomm.Select.ERROR: + logger.log_error("Receieved error from select()") + break + + def populate(self): + SELECT_TIMEOUT_MS = 0 + + while True: + (state, c) = self.sel.select(SELECT_TIMEOUT_MS) + if state == swsscommon.Select.OBJECT: + for t in self.tbls: + (key, op, cfvs) = t.pop() + if (key and key != 'PortInitDone' and + key != 'PortConfigDone'): + self.update_db(key, op) + else: + break + + +def signal_handler(signum, frame): + logger.log_notice("got signal {}".format(signum)) + sys.exit(0) + + +def main(): + port_mapper = PortIndexMapper() + port_mapper.populate() + port_mapper.listen() + + +if __name__ == '__main__': + rc = 0 + try: + signal.signal(signal.SIGTERM, signal_handler) + signal.signal(signal.SIGINT, signal_handler) + main() + except Exception as e: + tb = sys.exc_info()[2] + traceback.print_tb(tb) + logger.log_error("%s" % str(e)) + rc = -1 + finally: + sys.exit(rc) diff --git a/dockers/docker-sflow/supervisord.conf b/dockers/docker-sflow/supervisord.conf new file mode 100644 index 000000000000..3ff5ff564544 --- /dev/null +++ b/dockers/docker-sflow/supervisord.conf @@ -0,0 +1,48 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name sflow +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:sflowmgrd] +command=/usr/bin/sflowmgrd +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:port_index_mapper] +command=/usr/bin/port_index_mapper.py +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running diff --git a/dockers/docker-snmp/Dockerfile.j2 b/dockers/docker-snmp/Dockerfile.j2 new file mode 100644 index 000000000000..528189c2014f --- /dev/null +++ b/dockers/docker-snmp/Dockerfile.j2 @@ -0,0 +1,80 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python3_wheels, copy_files %} +FROM docker-config-engine-buster + +ARG docker_container_name +ARG image_version +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +# Enable -O for all Python calls +ENV PYTHONOPTIMIZE 1 + +# Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +# Pass the image_version to container +ENV IMAGE_VERSION=$image_version + +# Update apt's cache of available packages +# Install make/gcc which is required for installing hiredis +RUN apt-get update && \ + apt-get install -y \ + python3-dev \ + gcc \ + make \ + ipmitool + +{% if docker_snmp_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_snmp_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_snmp_debs.split(' ')) }} +{%- endif %} + +# Fix for hiredis compilation issues for ARM +# python will throw for missing locale +RUN apt-get install -y locales +RUN locale-gen "en_US.UTF-8" +RUN dpkg-reconfigure --frontend noninteractive locales +ENV LC_CTYPE=en_US.UTF-8 +RUN sed -i '/^#.* en_US.* /s/^#//' /etc/locale.gen +RUN locale-gen + +# Install dependencies used by some plugins +RUN pip3 install --no-cache-dir \ + hiredis \ + pyyaml \ + smbus + +{% if docker_snmp_whls.strip() -%} +# Copy locally-built Python wheel dependencies +{{ copy_files("python-wheels/", docker_snmp_whls.split(' '), "/python-wheels/") }} + +# Install locally-built Python wheel dependencies +{{ install_python3_wheels(docker_snmp_whls.split(' ')) }} +{% endif %} + +RUN python3 -m sonic_ax_impl install + +# Clean up +RUN apt-get -y purge \ + python3-dev \ + gcc \ + make && \ + apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y --purge && \ + find / | grep -E "__pycache__" | xargs rm -rf && \ + rm -rf /debs /python-wheels ~/.cache + +COPY ["start.sh", "/usr/bin/"] +COPY ["snmp_yml_to_configdb.py", "/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"] + +# Although exposing ports is not needed for host net mode, keep it for possible bridge mode +EXPOSE 161/udp 162/udp + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/dockers/docker-snmp/base_image_files/monit_snmp b/dockers/docker-snmp/base_image_files/monit_snmp new file mode 100644 index 000000000000..6a368a9b6035 --- /dev/null +++ b/dockers/docker-snmp/base_image_files/monit_snmp @@ -0,0 +1,11 @@ +############################################################################### +## Monit configuration for snmp container +## process list: +## snmpd +## snmpd_subagent +############################################################################### +check program snmp|snmpd with path "/usr/bin/process_checker snmp /usr/sbin/snmpd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program snmp|snmp_subagent with path "/usr/bin/process_checker snmp python3 -m sonic_ax_impl" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/dockers/docker-snmp/critical_processes b/dockers/docker-snmp/critical_processes new file mode 100644 index 000000000000..cff479d7fa11 --- /dev/null +++ b/dockers/docker-snmp/critical_processes @@ -0,0 +1,2 @@ +program:snmpd +program:snmp-subagent diff --git a/dockers/docker-snmp/snmp_yml_to_configdb.py b/dockers/docker-snmp/snmp_yml_to_configdb.py new file mode 100755 index 000000000000..7d4289926240 --- /dev/null +++ b/dockers/docker-snmp/snmp_yml_to_configdb.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +import os +import sys + +import yaml +from sonic_py_common.logger import Logger +from swsssdk import ConfigDBConnector + +db = ConfigDBConnector() +db.connect() + + +SYSLOG_IDENTIFIER = 'snmp_yml_to_configdb.py' +logger = Logger(SYSLOG_IDENTIFIER) +logger.set_min_log_priority_info() + +snmp_comm_config_db = db.get_table('SNMP_COMMUNITY') +snmp_config_db_communities = snmp_comm_config_db.keys() +snmp_general_config_db = db.get_table('SNMP') +snmp_general_keys = snmp_general_config_db.keys() + +full_snmp_comm_list = ['snmp_rocommunity', 'snmp_rocommunities', 'snmp_rwcommunity', 'snmp_rwcommunities'] + +if not os.path.exists('/etc/sonic/snmp.yml'): + logger.log_info('/etc/sonic/snmp.yml does not exist') + sys.exit(1) + +with open('/etc/sonic/snmp.yml', 'r') as yaml_file: + yaml_snmp_info = yaml.load(yaml_file, Loader=yaml.FullLoader) + +for comm_type in full_snmp_comm_list: + if comm_type in yaml_snmp_info.keys(): + if comm_type.startswith('snmp_rocommunities'): + for community in yaml_snmp_info[comm_type]: + if community not in snmp_config_db_communities: + db.set_entry('SNMP_COMMUNITY', community, {"TYPE": "RO"}) + elif comm_type.startswith('snmp_rocommunity'): + community = yaml_snmp_info['snmp_rocommunity'] + if community not in snmp_config_db_communities: + db.set_entry('SNMP_COMMUNITY', community, {"TYPE": "RO"}) + elif comm_type.startswith('snmp_rwcommunities'): + for community in yaml_snmp_info[comm_type]: + if community not in snmp_config_db_communities: + db.set_entry('SNMP_COMMUNITY', community, {"TYPE": "RW"}) + elif comm_type.startswith('snmp_rwcommunity'): + community = yaml_snmp_info['snmp_rwcommunity'] + if community not in snmp_config_db_communities: + db.set_entry('SNMP_COMMUNITY', community, {"TYPE": "RW"}) + +if yaml_snmp_info.get('snmp_location'): + if 'LOCATION' not in snmp_general_keys: + db.set_entry('SNMP', 'LOCATION', {'Location': yaml_snmp_info['snmp_location']}) +else: + logger.log_info('snmp_location does not exist in snmp.yml file') + sys.exit(1) diff --git a/dockers/docker-snmp/snmpd.conf.j2 b/dockers/docker-snmp/snmpd.conf.j2 new file mode 100644 index 000000000000..b83fbffda025 --- /dev/null +++ b/dockers/docker-snmp/snmpd.conf.j2 @@ -0,0 +1,201 @@ +############################################################################### +# Managed by sonic-config-engine +############################################################################### +# +# EXAMPLE.conf: +# An example configuration file for configuring the Net-SNMP agent ('snmpd') +# See the 'snmpd.conf(5)' man page for details +# +# Some entries are deliberately commented out, and will need to be explicitly activated +# +############################################################################### +# +# AGENT BEHAVIOUR +# + +# Listen for connections on all ip addresses, including eth0, ipv4 lo +# +{% 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 +{% endif %} + +############################################################################### +# +# ACCESS CONTROL +# + + # system + hrSystem groups only +view systemonly included .1.3.6.1.2.1.1 +view systemonly included .1.3.6.1.2.1.25.1 + + # Default access to basic system info + + +{% if SNMP_COMMUNITY is defined %} +{% for community in SNMP_COMMUNITY %} +{% if SNMP_COMMUNITY[community]['TYPE'] == 'RO' %} +rocommunity {{ community }} +rocommunity6 {{ community }} +{% endif %} +{% endfor %} +{% endif %} + +{% if SNMP_COMMUNITY is defined %} +{% for community in SNMP_COMMUNITY %} +{% if SNMP_COMMUNITY[community]['TYPE'] == 'RW' %} +rwcommunity {{ community }} +rwcommunity6 {{ community }} +{% endif %} +{% endfor %} +{% endif %} + +{% if SNMP_USER is defined %} +{% for user in SNMP_USER %} +{% if SNMP_USER[user]['SNMP_USER_PERMISSION'] == 'RO' %} +rouser {{ user }} {{ SNMP_USER[user]['SNMP_USER_TYPE'] }} +CreateUser {{ user }} {{ SNMP_USER[user]['SNMP_USER_AUTH_TYPE'] }} {{ SNMP_USER[user]['SNMP_USER_AUTH_PASSWORD'] }} {{ SNMP_USER[user]['SNMP_USER_ENCRYPTION_TYPE'] }} {{ SNMP_USER[user]['SNMP_USER_ENCRYPTION_PASSWORD'] }} +{% elif SNMP_USER[user]['SNMP_USER_PERMISSION'] == 'RW' %} +rwuser {{ user }} {{ SNMP_USER[user]['SNMP_USER_TYPE'] }} +CreateUser {{ user }} {{ SNMP_USER[user]['SNMP_USER_AUTH_TYPE'] }} {{ SNMP_USER[user]['SNMP_USER_AUTH_PASSWORD'] }} {{ SNMP_USER[user]['SNMP_USER_ENCRYPTION_TYPE'] }} {{ SNMP_USER[user]['SNMP_USER_ENCRYPTION_PASSWORD'] }} +{% endif %} +{% endfor %} +{% else %} +{% endif %} + + +############################################################################### +# +# SYSTEM INFORMATION +# + +# Note that setting these values here, results in the corresponding MIB objects being 'read-only' +# See snmpd.conf(5) for more details + +{% if SNMP is defined and SNMP.LOCATION is defined %} +sysLocation {{ SNMP.LOCATION.Location }} +{% else %} +sysLocation public +{% endif %} +{% if SNMP is defined and SNMP.CONTACT is defined %} +sysContact {{ SNMP.CONTACT.keys()[0] }} {{ SNMP.CONTACT.values()[0] }} +{% else %} +sysContact Azure Cloud Switch vteam +{% endif %} + + # Application + End-to-End layers +sysServices 72 + + +# +# Process Monitoring +# +# todo: should we enable snmp based monitoring of sswsyncd and other processes? + +# At least one 'sendmail' process, but no more than 10 +#proc sendmail 10 1 + +# Walk the UCD-SNMP-MIB::prTable to see the resulting output +# Note that this table will be empty if there are no "proc" entries in the snmpd.conf file + + +# +# Disk Monitoring +# + # 10MBs required on root disk, 5% free on /var, 10% free on all other disks +disk / 10000 +disk /var 5% +includeAllDisks 10% + +# Walk the UCD-SNMP-MIB::dskTable to see the resulting output +# Note that this table will be empty if there are no "disk" entries in the snmpd.conf file + + +# +# System Load +# + # Unacceptable 1-, 5-, and 15-minute load averages +load 12 10 5 + +# Walk the UCD-SNMP-MIB::laTable to see the resulting output +# Note that this table *will* be populated, even without a "load" entry in the snmpd.conf file + + + +############################################################################### +# +# ACTIVE MONITORING +# +# Note: disabled snmp traps due to side effect of causing snmpd to listen on all ports (0.0.0.0) +# +# send SNMPv1 traps +{% 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 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 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 %} + +# Note that you typically only want *one* of these three lines +# Uncommenting two (or all three) will result in multiple copies of each notification. + + +# +# Event MIB - automatically generate alerts +# +# Remember to activate the 'createUser' lines above +#iquerySecName internalUser +#rouser internalUser +# generate traps on UCD error conditions +#defaultMonitors yes +#note, this release of snmpd does not support linkUpDownNotifications +# generate traps on linkUp/Down +#linkUpDownNotifications yes + + +# +# AgentX Sub-agents +# + # Run as an AgentX master agent +master agentx +# internal socket to allow extension to other docker containers +# Currently the other container using this is docker-fpm-frr +# make sure this line matches bgp:/etc/snmp/frr.conf +# please see testing procedure in the same file to verify this works +# to verify the SNMP docker side look for the following string in the log file: +# INFO snmp-subagent [ax_interface] INFO: Using agentx socket type tcp with path tcp:localhost:3161 +# INFO supervisord snmp-subagent INFO:ax_interface:Using agentx socket type tcp with path tcp:localhost:3161 +agentxsocket tcp:localhost:3161 + +# +# SysDescription pass-through +# + +pass -p 10 .1.3.6.1.2.1.1.1 /usr/share/snmp/sysDescr_pass.py diff --git a/dockers/docker-snmp/start.sh b/dockers/docker-snmp/start.sh new file mode 100755 index 000000000000..aefd0bfc3db6 --- /dev/null +++ b/dockers/docker-snmp/start.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + + +if [ "${RUNTIME_OWNER}" == "" ]; then + RUNTIME_OWNER="kube" +fi + +CTR_SCRIPT="/usr/share/sonic/scripts/container_startup.py" +if test -f ${CTR_SCRIPT} +then + ${CTR_SCRIPT} -f snmp -o ${RUNTIME_OWNER} -v ${IMAGE_VERSION} +fi + +mkdir -p /etc/ssw /etc/snmp + +# Parse snmp.yml and insert the data in Config DB +/usr/bin/snmp_yml_to_configdb.py + +SONIC_CFGGEN_ARGS=" \ + -d \ + -y /etc/sonic/sonic_version.yml \ + -t /usr/share/sonic/templates/sysDescription.j2,/etc/ssw/sysDescription \ + -t /usr/share/sonic/templates/snmpd.conf.j2,/etc/snmp/snmpd.conf \ +" + +sonic-cfggen $SONIC_CFGGEN_ARGS + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status diff --git a/dockers/docker-snmp/supervisord.conf b/dockers/docker-snmp/supervisord.conf new file mode 100644 index 000000000000..414445fdd6d6 --- /dev/null +++ b/dockers/docker-snmp/supervisord.conf @@ -0,0 +1,59 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=50 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name snmp +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:snmpd] +command=/usr/sbin/snmpd -f -LS4d -u Debian-snmp -g Debian-snmp -I -smux,mteTrigger,mteTriggerConf,ifTable,ifXTable,inetCidrRouteTable,ipCidrRouteTable,ip,disk_hw -p /run/snmpd.pid +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + +[program:snmp-subagent] +command=/usr/bin/env python3 -m sonic_ax_impl +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=snmpd:running diff --git a/dockers/docker-snmp/sysDescription.j2 b/dockers/docker-snmp/sysDescription.j2 new file mode 100644 index 000000000000..207a8bf7de9a --- /dev/null +++ b/dockers/docker-snmp/sysDescription.j2 @@ -0,0 +1 @@ +SONiC Software Version: SONiC.{{ build_version }} - HwSku: {{ DEVICE_METADATA['localhost']['hwsku'] }} - Distribution: Debian {{ debian_version }} - Kernel: {{ kernel_version }} diff --git a/dockers/docker-sonic-mgmt-framework/Dockerfile.j2 b/dockers/docker-sonic-mgmt-framework/Dockerfile.j2 new file mode 100644 index 000000000000..5ee8cae84466 --- /dev/null +++ b/dockers/docker-sonic-mgmt-framework/Dockerfile.j2 @@ -0,0 +1,56 @@ +FROM docker-config-engine-buster + +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 && \ + apt-get install -y g++ python3-dev libxml2 + +# TODO: Remove these lines once we no longer need Python 2 +RUN apt-get install -f -y python-dev python-pip +RUN pip2 install --upgrade 'pip<21' +RUN apt-get purge -y python-pip +RUN pip2 install setuptools==40.8.0 +RUN pip2 install wheel==0.35.1 +RUN pip2 install connexion==1.1.15 \ + setuptools==21.0.0 \ + grpcio-tools==1.20.0 \ + certifi==2017.4.17 \ + python-dateutil==2.6.0 \ + six==1.11.0 \ + urllib3==1.21.1 + +RUN pip3 install connexion==2.7.0 \ + setuptools==21.0.0 \ + grpcio-tools==1.20.0 \ + certifi==2017.4.17 \ + python-dateutil==2.6.0 \ + six==1.11.0 \ + urllib3==1.21.1 + +COPY \ +{% for deb in docker_sonic_mgmt_framework_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_sonic_mgmt_framework_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "rest-server.sh", "/usr/bin/"] +COPY ["mgmt_vars.j2", "/usr/share/sonic/templates/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +# TODO: Remove this line once we no longer need Python 2 +RUN apt-get purge -y python-dev + +RUN apt-get remove -y g++ python3-dev +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/dockers/docker-sonic-mgmt-framework/base_image_files/sonic-cli b/dockers/docker-sonic-mgmt-framework/base_image_files/sonic-cli new file mode 100755 index 000000000000..6675e3badbaf --- /dev/null +++ b/dockers/docker-sonic-mgmt-framework/base_image_files/sonic-cli @@ -0,0 +1,4 @@ +#!/bin/bash + +docker exec -it mgmt-framework /usr/sbin/cli/clish_start "$@" + diff --git a/dockers/docker-sonic-mgmt-framework/mgmt_vars.j2 b/dockers/docker-sonic-mgmt-framework/mgmt_vars.j2 new file mode 100644 index 000000000000..f43b11ba4199 --- /dev/null +++ b/dockers/docker-sonic-mgmt-framework/mgmt_vars.j2 @@ -0,0 +1,4 @@ +{ + "rest_server": {% if REST_SERVER is defined and "default" in RESET_SERVER.keys() %}{{ REST_SERVER['default'] }}{% else %}""{% endif %}, + "x509" : {% if "x509" in DEVICE_METADATA.keys() %}{{ DEVICE_METADATA["x509"] }}{% else %}""{% endif %} +} diff --git a/dockers/docker-sonic-mgmt-framework/rest-server.sh b/dockers/docker-sonic-mgmt-framework/rest-server.sh new file mode 100755 index 000000000000..56a7e2999402 --- /dev/null +++ b/dockers/docker-sonic-mgmt-framework/rest-server.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# Startup script for SONiC Management REST Server +EXIT_MGMT_VARS_FILE_NOT_FOUND=1 +MGMT_VARS_FILE=/usr/share/sonic/templates/mgmt_vars.j2 + +if [ ! -f "$MGMT_VARS_FILE" ]; then + echo "Mgmt vars template file not found" + exit $EXIT_MGMT_VARS_FILE_NOT_FOUND +fi + +# Read basic server settings from mgmt vars entries +MGMT_VARS=$(sonic-cfggen -d -t $MGMT_VARS_FILE) +MGMT_VARS=${MGMT_VARS//[\']/\"} + +REST_SERVER=$(echo $MGMT_VARS | jq -r '.rest_server') + +if [ -n "$REST_SERVER" ]; then + SERVER_PORT=$(echo $REST_SERVER | jq -r '.port') + CLIENT_AUTH=$(echo $REST_SERVER | jq -r '.client_auth') + LOG_LEVEL=$(echo $REST_SERVER | jq -r '.log_level') + + SERVER_CRT=$(echo $REST_SERVER | jq -r '.server_crt') + SERVER_KEY=$(echo $REST_SERVER | jq -r '.server_key') + CA_CRT=$(echo $REST_SERVER | jq -r '.ca_crt') +fi + +if [[ -z $SERVER_CRT ]] && [[ -z $SERVER_KEY ]] && [[ -z $CA_CRT ]]; then + X509=$(echo $MGMT_VARS | jq -r '.x509') +fi + +# Read certificate file paths from DEVICE_METADATA|x509 entry. +if [ -n "$X509" ]; then + SERVER_CRT=$(echo $X509 | jq -r '.server_crt') + SERVER_KEY=$(echo $X509 | jq -r '.server_key') + CA_CRT=$(echo $X509 | jq -r '.ca_crt') +fi + +# Create temporary server certificate if they not configured in ConfigDB +if [ -z $SERVER_CRT ] && [ -z $SERVER_KEY ]; then + echo "Generating temporary TLS server certificate ..." + (cd /tmp && /usr/sbin/generate_cert --host="localhost,127.0.0.1") + SERVER_CRT=/tmp/cert.pem + SERVER_KEY=/tmp/key.pem +fi + + +REST_SERVER_ARGS="-ui /rest_ui -logtostderr" +[ ! -z $SERVER_PORT ] && REST_SERVER_ARGS+=" -port $SERVER_PORT" +[ ! -z $LOG_LEVEL ] && REST_SERVER_ARGS+=" -v $LOG_LEVEL" +[ ! -z $CLIENT_AUTH ] && REST_SERVER_ARGS+=" -client_auth $CLIENT_AUTH" +[ ! -z $SERVER_CRT ] && REST_SERVER_ARGS+=" -cert $SERVER_CRT" +[ ! -z $SERVER_KEY ] && REST_SERVER_ARGS+=" -key $SERVER_KEY" +[ ! -z $CA_CRT ] && REST_SERVER_ARGS+=" -cacert $CA_CRT" + +echo "REST_SERVER_ARGS = $REST_SERVER_ARGS" + + +export CVL_SCHEMA_PATH=/usr/sbin/schema + +exec /usr/sbin/rest_server ${REST_SERVER_ARGS} diff --git a/dockers/docker-sonic-mgmt-framework/start.sh b/dockers/docker-sonic-mgmt-framework/start.sh new file mode 100755 index 000000000000..d6722a27fc77 --- /dev/null +++ b/dockers/docker-sonic-mgmt-framework/start.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status diff --git a/dockers/docker-sonic-mgmt-framework/supervisord.conf b/dockers/docker-sonic-mgmt-framework/supervisord.conf new file mode 100644 index 000000000000..f3060fb95d57 --- /dev/null +++ b/dockers/docker-sonic-mgmt-framework/supervisord.conf @@ -0,0 +1,43 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=true +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:rest-server] +command=/usr/bin/rest-server.sh +priority=3 +autostart=false +autorestart=true +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited diff --git a/dockers/docker-sonic-mgmt/Dockerfile.j2 b/dockers/docker-sonic-mgmt/Dockerfile.j2 new file mode 100644 index 000000000000..b6abdb8d9363 --- /dev/null +++ b/dockers/docker-sonic-mgmt/Dockerfile.j2 @@ -0,0 +1,177 @@ +FROM ubuntu:18.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y build-essential \ + cmake \ + curl \ + default-jre \ + gcc \ + git \ + inetutils-ping \ + iproute2 \ + isc-dhcp-client \ + libffi-dev \ + libssl-dev \ + libxml2 \ + libxslt1-dev \ + make \ + openssh-server \ + psmisc \ + python \ + python-dev \ + python-scapy \ + python-setuptools \ + python-pip \ + python3-pip \ + python3-venv \ + rsyslog \ + snmp \ + sshpass \ + sudo \ + tcpdump \ + telnet \ + vim + +RUN pip install cffi==1.10.0 \ + "cryptography>=2.5" \ + "future>=0.16.0" \ + gitpython \ + ipaddr \ + ipython==5.4.1 \ + ixnetwork-restpy==1.0.52 \ + ixnetwork-open-traffic-generator==0.0.70 \ + jinja2==2.7.2 \ + jsonpatch \ + lxml \ + natsort \ + netaddr \ + netmiko==2.4.2 \ + paramiko==2.7.1 \ + passlib \ + pexpect \ + prettytable \ + psutil \ + pyasn1==0.1.9 \ + pyfiglet \ + pylint==1.8.1 \ + pyro4 \ + pysnmp==4.2.5 \ + pytest-repeat \ + pytest-html \ + pytest-xdist==1.28.0 \ + pytest==4.6.5 \ + redis \ + requests \ + rpyc \ + six \ + tabulate \ + textfsm \ + virtualenv \ + && git clone https://github.com/p4lang/scapy-vxlan.git \ + && cd scapy-vxlan \ + && python setup.py install \ + && cd .. \ + && rm -fr scapy-vxlan \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cd build \ + && cmake .. \ + && make install \ + && ldconfig \ + && cd ../.. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install nnpy \ + && pip install dpkt + +# Install docker-ce-cli +RUN apt-get update \ + && apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg-agent \ + software-properties-common \ + && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - \ + && add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \ + && apt-get update \ + && apt-get install -y docker-ce-cli + +# Install Azure CLI +RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash + +# Install Microsoft Azure Kusto Library for Python +RUN pip install azure-kusto-data==0.0.13 \ + azure-kusto-ingest==0.0.13 + +RUN pip install wheel==0.33.6 + +## Copy and install sonic-mgmt docker dependencies +COPY \ +{% for deb in docker_sonic_mgmt_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_sonic_mgmt_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +RUN pip install ansible==2.8.12 + +RUN pip install pysubnettree + +# Install pytest-ansible module with 'become', 'become_user' parameters support +RUN git clone https://github.com/ansible/pytest-ansible.git \ + && cd pytest-ansible \ + && git checkout d33c025f070a9c870220a157cc5a999fda68de44 \ + && python setup.py install \ + && cd .. \ + && rm -fr pytest-ansible + +RUN mkdir /var/run/sshd +EXPOSE 22 + +# Add user +ARG user +ARG uid +ARG guid +ARG hostname + +ENV BUILD_HOSTNAME $hostname +ENV USER $user +ENV CC=gcc CPP=cpp CXX=c++ LDSHARED="gcc -pthread -shared" PYMSSQL_BUILD_WITH_BUNDLED_FREETDS=1 + +RUN groupadd -f -r -g $guid g$user + +RUN useradd $user -l -u $uid -g $guid -d /var/$user -m -s /bin/bash + +COPY sonic-jenkins.pub /var/$user/.ssh/authorized_keys2 + +RUN echo "Host *\n\tStrictHostKeyChecking no\n" > /var/$user/.ssh/config +RUN chown $user /var/$user/.ssh -R +RUN chmod go= /var/$user/.ssh -R + +# Add user to sudoers +RUN echo "$user ALL=(ALL) NOPASSWD:ALL" >>/etc/sudoers + +USER $user +WORKDIR /var/$user + +# Add az symlink for backwards compatibility +RUN mkdir bin && ln -s /usr/bin/az bin/az + +# Install Virtual Environments +RUN python -m virtualenv --system-site-packages env-201811 +RUN env-201811/bin/pip install ansible==2.0.0.2 + +RUN python3 -m venv env-python3 +RUN env-python3/bin/pip3 install azure-kusto-data azure-kusto-ingest defusedxml pytest + +# NOTE: There is an ordering dependency for pycryptodome. Leaving this at +# the end until we figure that out. +RUN pip install pycryptodome==3.9.8 diff --git a/dockers/docker-sonic-mgmt/sonic-jenkins.pub b/dockers/docker-sonic-mgmt/sonic-jenkins.pub new file mode 100644 index 000000000000..8cbd97ce8c57 --- /dev/null +++ b/dockers/docker-sonic-mgmt/sonic-jenkins.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEJhhzQtlgNkBWxWXNm/qxZC26pFC16uOdGMx7BfMP9KxpKB46sFO5nkZXh8CiyjHitks2BYjbrK2IYubiyQhHaKh+4mnCnO58GLRRAiCUzeaC1jSrmqseBN8ZN7UV7gZUWQOxHErUHVhTbujUR0eZLymwPV0bNO9/bAWR5a+l5l/kf3VMREHF5Z6KyIuA9fT9XUJz8wLEUZCC8Id9RGwmKHS4FYuwtvcYm1MKb+ULXlri5o25G/X3I1pBpU/xUPBDUu+g3cIavrl7wVVGbIXYcYoH5qrTycMY0Y3rLBxu9SECUCqIxhnKQsiv+iXZSibnUXT4r6HcLMej5e+o1Jx3 lgh@jenkins-master-phx diff --git a/dockers/docker-sonic-restapi/Dockerfile.j2 b/dockers/docker-sonic-restapi/Dockerfile.j2 new file mode 100644 index 000000000000..837796e66d82 --- /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/local/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..6752100b84f2 --- /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 program restapi|restapi with path "/usr/bin/process_checker restapi /usr/sbin/go-server-server" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/dockers/docker-sonic-restapi/critical_processes b/dockers/docker-sonic-restapi/critical_processes new file mode 100644 index 000000000000..455b7fb2fa46 --- /dev/null +++ b/dockers/docker-sonic-restapi/critical_processes @@ -0,0 +1 @@ +program:restapi diff --git a/dockers/docker-sonic-restapi/restapi.sh b/dockers/docker-sonic-restapi/restapi.sh new file mode 100755 index 000000000000..3a0997a2e66a --- /dev/null +++ b/dockers/docker-sonic-restapi/restapi.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +RESTAPI_ARGS="" +while true +do + has_client_auth=$(sonic-cfggen -d -v "1 if RESTAPI and RESTAPI['config']") + if [ "$has_client_auth" == "1" ]; then + client_auth=$(sonic-cfggen -d -v "RESTAPI['config']['client_auth']") + fi + 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']"` + CA_CRT=`sonic-cfggen -d -v "RESTAPI['certs']['ca_crt']"` + CLIENT_CRT_CNAME=`sonic-cfggen -d -v "RESTAPI['certs']['client_crt_cname']"` + if [[ -f $SERVER_CRT && -f $SERVER_KEY && -f $CA_CRT ]]; then + RESTAPI_ARGS+=" -enablehttps=true -servercert=$SERVER_CRT -serverkey=$SERVER_KEY -clientcert=$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..d6722a27fc77 --- /dev/null +++ b/dockers/docker-sonic-restapi/start.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status diff --git a/dockers/docker-sonic-restapi/supervisord.conf b/dockers/docker-sonic-restapi/supervisord.conf new file mode 100644 index 000000000000..44508ce88138 --- /dev/null +++ b/dockers/docker-sonic-restapi/supervisord.conf @@ -0,0 +1,51 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name restapi +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=false + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=true +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:restapi] +command=/usr/bin/restapi.sh +priority=1 +autostart=false +autorestart=true +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + + diff --git a/dockers/docker-sonic-telemetry/Dockerfile.j2 b/dockers/docker-sonic-telemetry/Dockerfile.j2 new file mode 100644 index 000000000000..88ff94318208 --- /dev/null +++ b/dockers/docker-sonic-telemetry/Dockerfile.j2 @@ -0,0 +1,35 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +ARG docker_container_name +ARG image_version +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 + +# Pass the image_version to container +ENV IMAGE_VERSION=$image_version + +RUN apt-get update + +{% if docker_sonic_telemetry_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_sonic_telemetry_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_sonic_telemetry_debs.split(' ')) }} +{%- endif %} + +RUN apt-get clean -y && \ + apt-get autoclean - && \ + apt-get autoremove -y && \ + rm -rf /debs + +COPY ["start.sh", "telemetry.sh", "dialout.sh", "/usr/bin/"] +COPY ["telemetry_vars.j2", "/usr/share/sonic/templates/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] 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..3680bbe6cf9a --- /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 program telemetry|telemetry with path "/usr/bin/process_checker telemetry /usr/sbin/telemetry" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program telemetry|dialout_client with path "/usr/bin/process_checker telemetry /usr/sbin/dialout_client_cli" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/dockers/docker-sonic-telemetry/critical_processes b/dockers/docker-sonic-telemetry/critical_processes new file mode 100644 index 000000000000..612a94d9edac --- /dev/null +++ b/dockers/docker-sonic-telemetry/critical_processes @@ -0,0 +1,2 @@ +program:telemetry +program:dialout diff --git a/dockers/docker-sonic-telemetry/dialout.sh b/dockers/docker-sonic-telemetry/dialout.sh new file mode 100755 index 000000000000..485c3292d0df --- /dev/null +++ b/dockers/docker-sonic-telemetry/dialout.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Start with default config +export CVL_SCHEMA_PATH=/usr/sbin/schema +exec /usr/sbin/dialout_client_cli -insecure -logtostderr -v 2 + diff --git a/dockers/docker-sonic-telemetry/start.sh b/dockers/docker-sonic-telemetry/start.sh new file mode 100755 index 000000000000..08f7292f55ba --- /dev/null +++ b/dockers/docker-sonic-telemetry/start.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +if [ "${RUNTIME_OWNER}" == "" ]; then + RUNTIME_OWNER="kube" +fi + +CTR_SCRIPT="/usr/share/sonic/scripts/container_startup.py" +if test -f ${CTR_SCRIPT} +then + ${CTR_SCRIPT} -f telemetry -o ${RUNTIME_OWNER} -v ${IMAGE_VERSION} +fi + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status diff --git a/dockers/docker-sonic-telemetry/supervisord.conf b/dockers/docker-sonic-telemetry/supervisord.conf new file mode 100644 index 000000000000..fa8c86f597c7 --- /dev/null +++ b/dockers/docker-sonic-telemetry/supervisord.conf @@ -0,0 +1,59 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=50 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name telemetry +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=false + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=true +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:telemetry] +command=/usr/bin/telemetry.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + +[program:dialout] +command=/usr/bin/dialout.sh +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=telemetry:running diff --git a/dockers/docker-sonic-telemetry/telemetry.sh b/dockers/docker-sonic-telemetry/telemetry.sh new file mode 100755 index 000000000000..1f92657e3b8f --- /dev/null +++ b/dockers/docker-sonic-telemetry/telemetry.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +EXIT_TELEMETRY_VARS_FILE_NOT_FOUND=1 +TELEMETRY_VARS_FILE=/usr/share/sonic/templates/telemetry_vars.j2 + +if [ ! -f "$TELEMETRY_VARS_FILE" ]; then + echo "Telemetry vars template file not found" + exit $EXIT_TELEMETRY_VARS_FILE_NOT_FOUND +fi + +# Try to read telemetry and certs config from ConfigDB. +# Use default value if no valid config exists +TELEMETRY_VARS=$(sonic-cfggen -d -t $TELEMETRY_VARS_FILE) +TELEMETRY_VARS=${TELEMETRY_VARS//[\']/\"} +X509=$(echo $TELEMETRY_VARS | jq -r '.x509') +GNMI=$(echo $TELEMETRY_VARS | jq -r '.gnmi') +CERTS=$(echo $TELEMETRY_VARS | jq -r '.certs') + +TELEMETRY_ARGS=" -logtostderr" +export CVL_SCHEMA_PATH=/usr/sbin/schema + +if [ -n "$CERTS" ]; then + SERVER_CRT=$(echo $CERTS | jq -r '.server_crt') + SERVER_KEY=$(echo $CERTS | jq -r '.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=$(echo $CERTS | jq -r '.ca_crt') + if [ ! -z $CA_CRT ]; then + TELEMETRY_ARGS+=" --ca_crt $CA_CRT" + fi +elif [ -n "$X509" ]; then + SERVER_CRT=$(echo $X509 | jq -r '.server_crt') + SERVER_KEY=$(echo $X509 | jq -r '.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=$(echo $X509 | jq -r '.ca_crt') + if [ ! -z $CA_CRT ]; then + TELEMETRY_ARGS+=" --ca_crt $CA_CRT" + fi +else + TELEMETRY_ARGS+=" --noTLS" +fi + +# If no configuration entry exists for TELEMETRY, create one default port +if [ -z "$GNMI" ]; then + PORT=8080 +else + PORT=$(echo $GNMI | jq -r '.port') +fi +TELEMETRY_ARGS+=" --port $PORT" + +CLIENT_AUTH=$(echo $GNMI | jq -r '.client_auth') +if [ -z $CLIENT_AUTH ] || [ $CLIENT_AUTH == "false" ]; then + TELEMETRY_ARGS+=" --allow_no_client_auth" +fi + +LOG_LEVEL=$(echo $GNMI | jq -r '.log_level') +if [ ! -z $LOG_LEVEL ]; then + TELEMETRY_ARGS+=" -v=$LOG_LEVEL" +else + TELEMETRY_ARGS+=" -v=2" +fi + +exec /usr/sbin/telemetry ${TELEMETRY_ARGS} diff --git a/dockers/docker-sonic-telemetry/telemetry_vars.j2 b/dockers/docker-sonic-telemetry/telemetry_vars.j2 new file mode 100644 index 000000000000..d1d2d8977f1f --- /dev/null +++ b/dockers/docker-sonic-telemetry/telemetry_vars.j2 @@ -0,0 +1,5 @@ +{ + "certs": {% if "certs" in TELEMETRY.keys() %}{{ TELEMETRY["certs"] }}{% else %}""{% endif %}, + "gnmi" : {% if "gnmi" in TELEMETRY.keys() %}{{ TELEMETRY["gnmi"] }}{% else %}""{% endif %}, + "x509" : {% if "x509" in DEVICE_METADATA.keys() %}{{ DEVICE_METADATA["x509"] }}{% else %}""{% endif %} +} diff --git a/dockers/docker-teamd/Dockerfile.j2 b/dockers/docker-teamd/Dockerfile.j2 new file mode 100644 index 000000000000..7f4db2936857 --- /dev/null +++ b/dockers/docker-teamd/Dockerfile.j2 @@ -0,0 +1,30 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +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_teamd_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_teamd_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_teamd_debs.split(' ')) }} +{%- endif %} + +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs + +COPY ["start.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/local/bin/supervisord"] diff --git a/dockers/docker-teamd/base_image_files/monit_teamd b/dockers/docker-teamd/base_image_files/monit_teamd new file mode 100644 index 000000000000..626a6145604e --- /dev/null +++ b/dockers/docker-teamd/base_image_files/monit_teamd @@ -0,0 +1,11 @@ +############################################################################### +## Monit configuration for teamd container +## process list: +## teamsyncd +## teammgrd +############################################################################### +check program teamd|teamsyncd with path "/usr/bin/process_checker teamd /usr/bin/teamsyncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program teamd|teammgrd with path "/usr/bin/process_checker teamd /usr/bin/teammgrd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/dockers/docker-teamd/base_image_files/teamdctl b/dockers/docker-teamd/base_image_files/teamdctl new file mode 100755 index 000000000000..d4e02ccd707d --- /dev/null +++ b/dockers/docker-teamd/base_image_files/teamdctl @@ -0,0 +1,43 @@ +#!/bin/bash + +[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment + +function help() +{ + echo -e "Usage: $0 -n [0 to $(($NUM_ASIC-1))] [OPTION]... " 1>&2; exit 1; +} + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +DEV="" +PLATFORM=${PLATFORM:-`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`} + +# Parse the device specific asic conf file, if it exists +ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf +[ -f $ASIC_CONF ] && . $ASIC_CONF + +if [[ ($NUM_ASIC -gt 1) ]]; then + while getopts ":n:h:" opt; do + case "${opt}" in + h) help + ;; + n) DEV=${OPTARG} + [ $DEV -lt $NUM_ASIC -a $DEV -ge 0 ] || help + ;; + esac + done + + if [ -z "${DEV}" ]; then + help + fi + + # Skip the arguments -n while passing to docker command + shift 2 +fi + +docker exec -$DOCKER_EXEC_FLAGS teamd$DEV teamdctl "$@" diff --git a/dockers/docker-teamd/critical_processes b/dockers/docker-teamd/critical_processes new file mode 100644 index 000000000000..bb7d3c4b0810 --- /dev/null +++ b/dockers/docker-teamd/critical_processes @@ -0,0 +1,3 @@ +program:teammgrd +program:teamsyncd +program:tlm_teamd \ No newline at end of file diff --git a/dockers/docker-teamd/start.sh b/dockers/docker-teamd/start.sh new file mode 100755 index 000000000000..d67bc4e925c8 --- /dev/null +++ b/dockers/docker-teamd/start.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +rm -f /var/run/teamd/* + +mkdir -p /var/warmboot/teamd diff --git a/dockers/docker-teamd/supervisord.conf b/dockers/docker-teamd/supervisord.conf new file mode 100644 index 000000000000..04432a31239a --- /dev/null +++ b/dockers/docker-teamd/supervisord.conf @@ -0,0 +1,71 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=50 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name teamd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=true +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:teammgrd] +command=/usr/bin/teammgrd +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + +[program:teamsyncd] +command=/usr/bin/teamsyncd +priority=4 +startsecs=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=teammgrd:running + +[program:tlm_teamd] +command=/usr/bin/tlm_teamd +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + diff --git a/dockers/dockerfile-macros.j2 b/dockers/dockerfile-macros.j2 new file mode 100644 index 000000000000..9917cb17aba2 --- /dev/null +++ b/dockers/dockerfile-macros.j2 @@ -0,0 +1,39 @@ +{% macro install_debian_packages(packages) -%} +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; \ + {%- for deb in packages %} + dpkg_apt /debs/{{ deb }} {%- if not loop.last %} && \ {%- endif %} + {%- endfor %} +{%- endmacro %} + +{% macro install_python2_wheels(packages) -%} +RUN cd /python-wheels/ && pip2 install {{ packages | join(' ') }} +{%- endmacro %} + +{% macro install_python3_wheels(packages) -%} +RUN cd /python-wheels/ && pip3 install {{ packages | join(' ') }} +{%- endmacro %} + +{% macro install_python_wheels(packages) -%} +{%- set py2_pkgs, py3_pkgs = [], [] %} +{%- for pkg in packages %} + {%- if 'py3' in pkg %} + {{- py3_pkgs.append(pkg) or '' }} + {%- else %} + {{- py2_pkgs.append(pkg) or '' }} + {%- endif %} +{%- endfor %} +{%- if py3_pkgs | length %} +{{ install_python3_wheels(py3_pkgs) }} +{%- endif %} +{%- if py2_pkgs | length %} +{{ install_python2_wheels(py2_pkgs) }} +{%- endif %} +{%- endmacro %} + +{% macro copy_files(prefix, files, dest) -%} +COPY \ + {%- for file in files %} + {{ prefix }}/{{ file }} \ + {%- endfor %} + {{ dest }} +{%- endmacro %} diff --git a/files/Aboot/boot0 b/files/Aboot/boot0 deleted file mode 100644 index 98522bdfe647..000000000000 --- a/files/Aboot/boot0 +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (C) 2016 Arista Networks, Inc. -# -# 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 3 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. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Aboot stage 0 boot - -set -x - -bootconfigvars="SWI SWI_COPY POST_LEVEL CONSOLESPEED PASSWORD NETDEV NETAUTO NETIP NETMASK NETGW NETDOMAIN NETDNS NETHW memtest" - -parseenvironmentconfig() { - for n in ${bootconfigvars}; do - eval v="\$$n" - if [ "$v" ]; then - echo "$n=$v" - fi - done -} - -kernel=boot/vmlinuz-3.16.0-4-amd64 -initrd=boot/initrd.img-3.16.0-4-amd64 - -TARGET_PATH=/mnt/flash -if [ -d "${swipath}" ]; then - # Not expect a directory name for swipath - exit 1 -fi - -## Determine whether installing by hash file in the image -GIT_REVISION=$(unzip -p ${swipath} .imagehash) -LOCAL_IMAGEHASH=$(cat $TARGET_PATH/.imagehash 2>/dev/null || true) -if [ "$GIT_REVISION" != "$LOCAL_IMAGEHASH" ]; then - unzip -oq ${swipath} -x boot0 -d ${TARGET_PATH} -fi - -echo "${append}" >/tmp/append -parseenvironmentconfig >>/tmp/append -cat /etc/cmdline | sed "/^\(${bootconfigvars// /\|}\|crashkernel\|loglevel\|ignore_loglevel\)\(\$\|=\)/d;/^\$/d" >>/tmp/append - -echo "root=/dev/sda1 rw loop=fs.squashfs loopfstype=squashfs apparmor=1 security=apparmor quiet" >>/tmp/append - -kexec --load --initrd=${TARGET_PATH}/${initrd} --append="$(tr '\n' ' ' . + +# Aboot stage 0 boot script +# +# This boot0 script can be used in different scenario +# - Installation and boot from Aboot (manual or reboot on a new image) +# - EOS to SONiC fast-reboot (installation and kexec in EOS) +# - SONiC to SONiC fast-reboot (installation and kexec in SONiC) +# +# Use it this way: +# - swipath=path/to/swi install=true boot0 +# - swipath=path/to/swi install=true force=true boot0 +# - swipath=path/to/swi kexec=true boot0 +# +# The logic defaults to the first scenario but providing extra environment variable +# will affect the behavior of the script. +# The list of variables is maintained here +# - KERNEL : relative path to the kernel to execute +# - INITRD : relative path to the initrd to load +# - CMDLINE : place to find the default kernel cmdline to use for the platform +# - VERBOSE : setting it to 1 will enable debug traces +# +# By default the boot0 script will behave for an Aboot based behavior. +# Options can be provided to only run some features of this script. +# +# Extra kernel parameters can be provided at runtime by the user by adding them +# into the kernel-params file. +# +# Secureboot of SONiC SWI images is also supported. +# In such cases, there will only be a partial install on the flash. +# SONiC will be mostly booting in RAM as a live operating system. + +# All templated variables should be declared here +image_name="image-%%IMAGE_VERSION%%" +dockerfs="{{ FILESYSTEM_DOCKERFS }}" +boot_image="{{ ABOOT_BOOT_IMAGE }}" +installer_image="sonic.swi" +docker_dir="{{ DOCKERFS_DIR }}" + +do_not_clean="do-not-clean" +kernel_params="kernel-params" + +aboot_machine="arista_unknown" + +info() { printf "%04.2f: $@\n" "$(cut -f1 -d' ' /proc/uptime)"; } +err() { info "Error: $@"; } +warn() { info "Warning: $@"; } + +if [ $# -ne 0 ]; then + echo "usage: $0 (see code)" + exit 1 +fi + +mountpoint_for_file() { + local file="$1" + df "$file" | tail -1 | tr -s " " | cut -d ' ' -f6 +} + +# extract mount point from the swi path, e.g., /mnt/flash/sonic.swi --> /mnt/flash +if [ -z "$target_path" ]; then + if [ -z "$swipath" ]; then + err "target_path= is required when swipath= is not provided" + exit 1 + fi + target_path=$(mountpoint_for_file "$swipath") +fi +image_path="$target_path/$image_name" +hook_path="$image_path/platform/hooks" +data_path="$image_path/platform/data" +boot_image_path="$image_path/$boot_image" +installer_image_path="$image_path/$installer_image" + +boot_config="$target_path/boot-config" + +cmdline_allowlist="crashkernel hwaddr_ma1" + +# for backward compatibility with the sonic_upgrade= behavior +install="${install:-${sonic_upgrade:-}}" + +is_secureboot_enabled() { + if $in_aboot; then + if [ -x /bin/securebootctl ] && securebootctl sb -display | grep -q "Secure Boot enabled"; then + return 0 + fi + return 1 + else + if grep -q aboot.secureboot /proc/cmdline; then + return 0 + fi + # FIXME: EOS is not handled here + return 1 + fi +} + +clean_flash() { + ## Remove all the other unnecssary files except swi file, boot-config + for f in $(ls -A $target_path); do + if [ $f != "${swipath##*/}" ] && + [ $f != "boot-config" ] && + [ $f != "preserve-installer" ] && + [ $f != "$kernel_params" ] && + [ $f != "aquota.user" ] && + [ $f != "old_config" ] && + [ $f != "minigraph.xml" ] && + [ $f != "snmp.yml" ] && + [ $f != "acl.json" ] + then + rm -rf "$target_path/$f" + fi + done +} + +in_array() { + local value="$1" + shift + + for other in $@; do + if [ "$value" = "$other" ]; then + return 0 + fi + done + + return 1 +} + +update_boot_config() { + local key="$1" + local value="$2" + + if grep "$key" "$boot_config" 2>&1 > /dev/null; then + sed -i "s#^$key=.*\$#$key=$value#" "$boot_config" + else + echo "$key=$value" >> "$boot_config" + fi +} + +get_boot_config() { + local key="$1" + + sed -n "s#^$key=##p" "$boot_config" || : +} + +update_next_boot() { + local default="$(get_boot_config SWI_DEFAULT)" + + if [ -z "$default" ]; then + warn "boot-config has no variable SWI_DEFAULT" + else + info "Next reboot will use $default" + update_boot_config SWI "$default" + fi +} + +get_sorted_hooks() { + echo $(find "$1" -name '[0-9][0-9]-*' -type f) +} + +run_hooks() { + if [ -d "$hook_path/$1" ]; then + for hook in $(get_sorted_hooks "$hook_path/$1"); do + if [ ! -z "$hook" ]; then + info "Running hook $(basename $hook)" + . "$hook" + fi + done + fi +} + +get_uuid_for() { + local dev="$1" + + if type lsblk 2>&1 > /dev/null; then + lsblk "$dev" -n --output UUID + elif type blkid 2>&1 > /dev/null; then + blkid | grep "^$dev" | sed -n 's/^.* UUID="//p' | sed 's/".*$//' + fi +} + +cmdline_append() { + cat >> /tmp/append +} + +cmdline_clear() { + echo -n > /tmp/append +} + +cmdline_add() { + echo "$@" >> /tmp/append +} + +cmdline_has() { + grep -q "$1" /tmp/append +} + +cmdline_echo() { + # echo trims and remove whitespace duplicates + echo $(cat /tmp/append | tr '\n' ' ') +} + +cmdline_get() { + # extract last matching value for key + sed -nr "s/.*$1=([^ ]+).*/\1/p" /tmp/append | tail -n 1 +} + +find_first_kernel_under() { + local path="$1" + find "$path" -name 'vmlinuz-*' -type f | head -n 1 +} + +find_first_initrd_under() { + local path="$1" + find "$path" -name 'initrd.img-*' -type f | head -n 1 +} + +is_file_in_memory() { + local file="$1" + local filemnt=$(mountpoint_for_file "$file") + local filemntfs=$(mount | grep " $filemnt " | cut -f5 -d' ') + + case "$filemntfs" in + tmpfs|ramfs) return 0;; + *) return 1;; + esac +} + +get_tmpfs() { + local tmpfs="$(mktemp -d)" + + mkdir -p "$tmpfs" + if ! $in_aboot && ! mount | grep -q ' /tmp type tmpfs'; then + # mount a real tmpfs on /tmp/xxx if /tmp is not one already. + mount -t tmpfs "$(dirname $tmpfs)" "$tmpfs" + fi + echo "$tmpfs" +} + +clean_tmpfs() { + local tmpfs="$1" + + case "$tmpfs" in + /tmp) return 0;; + /tmp/*);; # only cleanup tmpfs created by this script + *) return 0;; + esac + + if mount | grep -q "$tmpfs"; then + umount "$tmpfs" || : + fi +} + +move_swi_to_tmpfs() { + local oldswi="$1" + + if is_file_in_memory "$oldswi"; then + echo "$oldswi" + return 0 + fi + + local tmpfs="$(get_tmpfs)" + local newswi="$tmpfs/$(basename "$oldswi")" + + mv "$oldswi" "$newswi" + echo "$newswi" +} + +cleanup_swi_tmpfs() { + rm -f "$swipath" + clean_tmpfs "$(mountpoint_for_file "$swipath")" +} + +mount_relpath() { + local abspath="$1" + local mountpath="$(df "$abspath" | sed -nr '/\//s/^.* ([^ ]+)$/\1/p')" + + echo "$abspath" | sed "s#^$mountpath/##" +} + +zip_file_offset() { + local zipfile="$1" + local filename="$2" + + if $in_aboot; then + unzip -qqf "$zipfile" "$filename" + else + local hexoffset="$(zipdetails "$zipfile" | sed -En "/Filename +'$filename'/,/^$/p" | sed -En 's/^([^ ]+) PAYLOAD$/\1/p')" + echo "$((0x$hexoffset))" + fi +} + +SWI_ALREADY_INSTALLED=0 +SWI_NOT_INSTALLED=1 +SWI_VERSION_MISMATCH=2 +SWI_OTHER_VARIANT_INSTALLED=3 + +is_swi_installed() { + local swi_path="$1" + local swi_version="$(unzip -qp "$swi_path" .imagehash)" + local local_version="$(cat $image_path/.imagehash 2>/dev/null || :)" + + if [ -z "$local_version" ]; then + # no image installed for this version + return $SWI_NOT_INSTALLED + fi + + if [ "$swi_version" != "$local_version" ]; then + warn "Installed image has a different version than $swipath" + return $SWI_VERSION_MISMATCH + fi + + if $secureboot; then + if [ -s "$installer_image_path" ]; then + # secureboot image already installed + return $SWI_ALREADY_INSTALLED + else + # regular image of the same version already installed + return $SWI_OTHER_VARIANT_INSTALLED + fi + else + if [ -s "$boot_image_path" ]; then + # regular image already installed + return $SWI_ALREADY_INSTALLED + else + # secureboot image of the same version already installed + return $SWI_OTHER_VARIANT_INSTALLED + fi + fi +} + +extract_image() { + info "Moving swi to a tmpfs" + ## Avoid problematic flash usage spike on older systems, also improves I/O + swipath="$(move_swi_to_tmpfs "$swipath")" + + info "Extracting swi content" + ## Unzip the image except boot0 and dockerfs archive + unzip -oq "$swipath" -x boot0 "$dockerfs" -d "$image_path" + + ## detect rootfs type + rootfs_type=`grep " $target_path " /proc/mounts | cut -d' ' -f3` + + info "Extracting $dockerfs from swi" + ## Unpacking dockerfs delayed + ## 1. when disk is vfat as it does not support symbolic link + ## 2. when disk is small, expand it into ramfs during initrd + if [ "$rootfs_type" != "vfat" ] && ! cmdline_has docker_inram=on; then + mkdir -p "$image_path/$docker_dir" + + if [ -n "$install" ]; then + TAR_EXTRA_OPTION="--numeric-owner --warning=no-timestamp" + fi + + ## extract docker archive + unzip -oqp "$swipath" "$dockerfs" | tar xzf - -C "$image_path/$docker_dir" $TAR_EXTRA_OPTION + else + ## save dockerfs archive in the image directory + unzip -oq "$swipath" "$dockerfs" -d "$image_path" + info "Unpacking $dockerfs delayed to initrd because $target_path is $rootfs_type or docker_inram is on" + fi + + ## remove installer since it's not needed anymore + if $preserve_installer; then + info "Preserving installer under $installer_image_path" + mv "$swipath" "$installer_image_path" + chmod a+r "$installer_image_path" + else + info "Remove installer" + cleanup_swi_tmpfs "$swipath" + fi + + ## use new reduced-size boot swi + local swi_boot_path="flash:$image_name/$boot_image" + update_boot_config SWI "$swi_boot_path" + update_boot_config SWI_DEFAULT "$swi_boot_path" + + ## sync disk operations + sync +} + +extract_image_secureboot() { + info "Extracting necessary swi content" + # NOTE: boot/ is not used by the boot process but only extracted for kdump + unzip -oq "$swipath" 'boot/*' platform/firsttime .imagehash -d "$image_path" + + info "Installing image as $installer_image_path" + mv "$swipath" "$installer_image_path" + chmod a+r "$installer_image_path" + swipath="$installer_image_path" + + local swi_boot_path="flash:$image_name/$installer_image" + update_boot_config SWI "$swi_boot_path" + update_boot_config SWI_DEFAULT "$swi_boot_path" + + sync +} + +prepare_image_secureboot() { + local boot_tmpfs="$(get_tmpfs)" + + info "Extracting boot content in tmpfs" + unzip -oq "$swipath" 'boot/*' -d "$boot_tmpfs" + + info "Generating machine.conf and cmdline" + write_secureboot_configs + + sync + + # override environment variables preventing external tamper on kernel execution + CMDLINE="$(cmdline_echo) $ENV_EXTRA_CMDLINE" + KERNEL="$(find_first_kernel_under "$boot_tmpfs")" + INITRD="$(find_first_initrd_under "$boot_tmpfs")" +} + +write_machine_config() { + ## Detect SKU and create a hardware description file + aboot_version=$(cmdline_get Aboot | sed 's/^.*norcal.-//') + if [ -x /bin/sysinit ]; then + aboot_build_date=$(stat -c %y /bin/sysinit | sed 's/ /T/') + else + aboot_build_date="unknown" + fi + cat < ${target_path}/machine.conf +aboot_version=$aboot_version +aboot_vendor=arista +aboot_platform=x86_64-$aboot_machine +aboot_machine=$aboot_machine +aboot_arch=x86_64 +aboot_build_date=$aboot_build_date +EOF + chmod a+r "${target_path}/machine.conf" +} + +read_system_eeprom() { + if [ -x /bin/readprefdl ] && [ -f /tmp/.system-prefdl ]; 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 +} + +write_platform_specific_cmdline() { + local platform="$(cmdline_get platform)" + local sid="$(cmdline_get sid | sed 's/Ssd$//')" + + # set varlog size to 100MB + local varlog_size=100 + + # sonic_mode is set to fixed by default. + sonic_mode="fixed" + supervisor_mode="supervisor" + linecard_mode="linecard" + + # detect the size of the flash partition from name in Aboot/EOS/SONiC + local flash_size=$(($(df "$target_path" | tail -1 | tr -s ' ' | cut -f2 -d' ') / 1000)) + + if [ "$platform" = "raven" ]; then + # Assuming sid=Cloverdale + aboot_machine=arista_7050_qx32 + flash_size=2000 + cmdline_add modprobe.blacklist=radeon,sp5100_tco + cmdline_add acpi=off + fi + if [ "$platform" = "crow" ]; then + # Assuming sid=Clearlake + aboot_machine=arista_7050_qx32s + flash_size=3700 + cmdline_add modprobe.blacklist=radeon,sp5100_tco + fi + if [ "$sid" = "Upperlake" ] || [ "$sid" = "UpperlakeES" ]; then + aboot_machine=arista_7060_cx32s + flash_size=3700 + fi + 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" ]; then + aboot_machine=arista_7170_64c + flash_size=28000 + cmdline_add hugepages=128 + fi + if [ "$sid" = "Mineral" ]; then + aboot_machine=arista_7170_32c + flash_size=28000 + cmdline_add hugepages=128 + fi + if [ "$sid" = "MineralD" ]; then + aboot_machine=arista_7170_32cd + flash_size=28000 + cmdline_add hugepages=128 + fi + if [ "$sid" = "Lodoga" ]; then + aboot_machine=arista_7050cx3_32s + flash_size=3700 + fi + if [ "$sid" = "Marysville" ]; then + aboot_machine=arista_7050sx3_48yc8 + flash_size=7382 + fi + if [ "$sid" = "Marysville10" ]; then + aboot_machine=arista_7050sx3_48c8 + flash_size=7382 + fi + if [ "$sid" = "BlackhawkO" ]; then + aboot_machine=arista_7060px4_32 + flash_size=28000 + fi + if [ "$sid" = "BlackhawkDD" ] || [ "$sid" = "BlackhawkDDM" ]; then + aboot_machine=arista_7060dx4_32 + flash_size=28000 + fi + if [ "$sid" = "Smartsville" ]; then + aboot_machine=arista_7280cr3_32p4 + fi + if [ "$sid" = "SmartsvilleBK" ]; then + aboot_machine=arista_7280cr3k_32p4 + fi + if [ "$sid" = "SmartsvilleBkMs" ] || [ "$sid" = "SmartsvilleBkMsTpm" ]; then + aboot_machine=arista_7280cr3mk_32p4 + fi + if [ "$sid" = "SmartsvilleDD" ]; then + aboot_machine=arista_7280cr3_32d4 + fi + if [ "$sid" = "SmartsvilleDDBK" ]; then + aboot_machine=arista_7280cr3k_32d4 + fi + if [ "$sid" = "SmartsvilleDDBkMs" ] || [ "$sid" = "SmartsvilleDDBkMsTpm" ]; then + aboot_machine=arista_7280cr3mk_32d4 + fi + if [ "$sid" = "Clearwater2" ]; then + aboot_machine=arista_7800r3_48cq2_lc + sonic_mode="$linecard_mode" + fi + if [ "$sid" = "Clearwater2Ms" ]; then + aboot_machine=arista_7800r3_48cqm2_lc + sonic_mode="$linecard_mode" + fi + if [ "$sid" = "OtterLake" ]; then + aboot_machine=arista_7800_sup + flash_size=30000 + sonic_mode=$supervisor_mode + fi + if [ "$sid" = "SmartsvilleBkMs" ]; then + aboot_machine=arista_7280cr3mk_32p4 + flash_size=7382 + fi + if in_array "$platform" "rook" "magpie" "woodpecker" "sprucefish"; then + cmdline_add tsc=reliable + cmdline_add pcie_ports=native + cmdline_add rhash_entries=1 + cmdline_add usb-storage.delay_use=0 + cmdline_add reassign_prefmem + fi + if in_array "$platform" "rook" "sprucefish"; then + cmdline_add iommu=on + cmdline_add intel_iommu=on + cmdline_add intel_idle.max_cstate=0 + read_system_eeprom + fi + if in_array "$platform" "crow" "magpie"; then + cmdline_add amd_iommu=off + cmdline_add modprobe.blacklist=snd_hda_intel,hdaudio + read_system_eeprom + fi + if in_array "$platform" "woodpecker"; then + cmdline_add modprobe.blacklist=snd_hda_intel,hdaudio + read_system_eeprom + fi + if in_array "$platform" "lorikeet" "hedgehog"; then + cmdline_add processor.max_cstate=1 + read_system_eeprom + fi + + if [ $flash_size -ge 28000 ]; then + varlog_size=4096 + elif [ $flash_size -ge 3700 ]; then + varlog_size=400 + elif [ $flash_size -le 2000 ]; then + # enable docker_inram for switches with less than 2G of flash + cmdline_add docker_inram=on + cmdline_add logs_inram=on + fi + + cmdline_add "varlog_size=$varlog_size" + + cmdline_add "sonic.mode=$sonic_mode" +} + +write_image_specific_cmdline() { + # security + cmdline_add security=apparmor + cmdline_add apparmor=1 + + # fs configuration + cmdline_add rw + + # disable deterministic interface naming + cmdline_add net.ifnames=0 + + # verbosity + cmdline_add quiet + # Start showing systemd information from the first failing unit if any. + # systemd.show_status=false or quiet can be used to silence systemd entierly + cmdline_add systemd.show_status=auto + + # Pass the MAC address to the new kernel as a command line parameter. This makes it + # possible to restore the MAC address in the new kernel without requiring driver modifications. + if [ -f /sys/class/net/ma1/address ]; then + cmdline_add "hwaddr_ma1=$(cat /sys/class/net/ma1/address)" + elif [ -f /sys/class/net/eth0/address ]; then + cmdline_add "hwaddr_ma1=$(cat /sys/class/net/eth0/address)" + else + err "Management port not found." + fi + + # Obtain root partition uuid + local mountstr="$(mount | grep " $target_path ")" + local rootdev="$(echo $mountstr | cut -f1 -d' ')" + local rootfstype="$(echo $mountstr | cut -f5 -d' ')" + local rootuuid="$(get_uuid_for $rootdev)" + if [ -z "$rootuuid" ] || [ "$rootfstype" = "vfat" ] ; then + cmdline_add "root=$rootdev" + else + cmdline_add "root=UUID=$rootuuid" + fi +} + +write_default_cmdline() { + local delimiter="cmdline-aboot-end" + + cmdline_clear + + if $in_aboot; then + # generate the default kernel parameters for the platform + cat /etc/cmdline | sed "/^\(${bootconfigvars// /\|}\|crashkernel\|loglevel\|ignore_loglevel\)\(\$\|=\)/d;/^\$/d" | cmdline_append + elif grep -q "$delimiter" /proc/cmdline; then + # we are on a recent sonic image using delimiter. extracting the part of the + # cmdline coming from aboot is trivial. + cat /proc/cmdline | sed -E "s/^(.*) $delimiter .*$/\1/" | tr ' ' '\n' | cmdline_append + else + # we are either on SONiC or EOS and the commandline doesn't have a delimiter + # for the Aboot part. Take an educated guess at a right delimiter. + # Subject to breakage if EOS or SONiC cmdline change. + cat /proc/cmdline | sed -E 's/^(.*) rw .*$/\1/' | tr ' ' '\n' | cmdline_append + fi + + cmdline_add "$delimiter" +} + +write_cmdline() { + # use extra parameters from kernel-params hook if the file exists + if [ -f "$target_path/$kernel_params" ] && ! $secureboot; then + info "Loading extra kernel parameters from $kernel_params" + cat "$target_path/$kernel_params" | cmdline_append + fi + + # FIXME: sonic sometimes adds extra kernel parameters from user space + # this is unsafe but some will be kept as part of the regular boot + if [ -f "$image_path/kernel-cmdline" ]; then + for field in $cmdline_allowlist; do + cat "$image_path/kernel-cmdline" | tr ' ' '\n' | grep -E "$field" | tail -n 1 | cmdline_append + done + fi + + # FIXME: legacy configuration files used by fast-reboot and eos2sonic + # these should be deprecated over time. + cmdline_echo > "$image_path/kernel-cmdline" + cmdline_echo | sed 's/ cmdline-aboot-end.*$//' > "$target_path/kernel-params-base" +} + +write_common_configs() { + write_default_cmdline + write_platform_specific_cmdline + write_image_specific_cmdline + write_machine_config +} + +write_secureboot_configs() { + write_common_configs + cmdline_add "loop=$(mount_relpath "$installer_image_path")" + cmdline_add loopfstype=squashfs + cmdline_add "loopoffset=$(zip_file_offset "$installer_image_path" fs.squashfs)" + cmdline_add docker_inram=on + cmdline_add secure_boot_enable=y + cmdline_add aboot.secureboot=enabled + # setting panic= has the side effect of disabling the initrd shell on error + cmdline_add panic=0 + write_cmdline +} + +write_regular_configs() { + write_common_configs + cmdline_add "loop=$image_name/fs.squashfs" + cmdline_add loopfstype=squashfs + write_cmdline +} + +run_kexec() { + local cmdline="${CMDLINE:-$(cmdline_echo) $ENV_EXTRA_CMDLINE}" + local kernel="${KERNEL:-$(find_first_kernel_under "$image_path/boot")}" + local initrd="${INITRD:-$(find_first_initrd_under "$image_path/boot")}" + + if $verbose; then + # show systemd showdown sequence when verbose is set + cmdline="$(echo "$cmdline" | sed 's/systemd.show_status=auto/systemd.show_status=true/')" + fi + + if $debug; then + # enable initrd debug as well as kernel verbose output + cmdline="$(echo "$cmdline" | sed 's/ quiet//')" + cmdline="$cmdline debug loglevel=7 log_buf_len=8M printk.devmsg=on" + fi + + sync + kexec --load --initrd="$initrd" --append="$cmdline" "$kernel" + + ( [ -z "$testonly" ] && [ -z "$loadonly" ] ) || exit 0 + info "Kexecing..." + kexec --exec +} + +secureboot_install() { + if [ -e "$image_path" ]; then + warn "Image folder $image_path already exist (likely regular install)" + fi + + mkdir -p "$image_path" + + info "Installing image as $installer_image_path" + extract_image_secureboot +} + +regular_install() { + if [ -e "$image_path" ]; then + warn "Image folder $image_path already exist (likely secureboot install)" + fi + + mkdir -p $image_path + + info "Generating boot-config, machine.conf and cmdline" + write_regular_configs "$image_path" + + info "Installing image under $image_path" + extract_image + + run_hooks post-install +} + +secureboot_boot() { + # boot material is extracted and generated in RAM. + # SONiC starts as a live OS. + info "Preparing image for secureboot" + prepare_image_secureboot + update_next_boot + run_kexec +} + +regular_boot() { + # boot uses the image installed on the flash + write_regular_configs "$image_path" + run_hooks pre-kexec + update_next_boot + run_kexec +} + + +# In Aboot no option will be provided therefore these are the default values to use +in_aboot=true +do_clean=true +do_install=true +do_kexec=true + +# prevent the flash from being cleaned if the do-not-clean file exists +if [ -f "$target_path/$do_not_clean" ]; then + do_clean=false +fi + +# Parse the cmdline options (used from EOS or from SONiC) +if [ ! -z "$install" ]; then + # install from SONiC or EOS + in_aboot=false + do_clean=false + do_kexec=false +elif [ ! -z "$kexec" ]; then + # kexec from SONiC or EOS + in_aboot=false + do_install=false + do_clean=false +fi + +# Make sure boot-config exists to avoid noise +touch "$boot_config" + +# Verbosity can be defined by the caller, default to false otherwise +verbose=${verbose:-false} +debug=${debug:-false} +if [ -f "$target_path/verbose-boot" ] || + [ "$(get_boot_config VERBOSE)" = "1" ] || + ! $in_aboot; then + verbose=true +fi +if [ -f "$target_path/debug-boot" ] || [ "$(get_boot_config DEBUG)" = "1" ]; then + verbose=true + debug=true +fi + +# behavioral configuration for secureboot +# can be overidden by passing secureboot=true via env +if [ -z "$secureboot" ]; then + if is_secureboot_enabled; then + secureboot=true + else + secureboot=false + fi +fi + +# preserve original installer during regular install when set +preserve_installer=false +if [ -f "$target_path/preserve-installer" ] || + [ "$(get_boot_config PRESERVE_INSTALLER)" = "1" ]; then + preserve_installer=true +fi + +# enable shell debug mode to get the most verbosity +if $verbose; then + set -x +fi + +# install the image if newer +if $do_install; then + if ! unzip -ql "$swipath" 2>&1 > /dev/null; then + err "The swipath= environment variable does not point to a valid SWI" + exit 1 + fi + + swi_installed=0 + is_swi_installed "$swipath" || swi_installed=$? + + if [ "$swi_installed" -ne $SWI_ALREADY_INSTALLED ] || [ -n "$force" ]; then + if [ "$swi_installed" -eq $SWI_VERSION_MISMATCH ] || [ -n "$force" ]; then + warn "Removing existing installation folder $image_path" + rm -rf $image_path + fi + if [ "$swi_installed" -ne $SWI_OTHER_VARIANT_INSTALLED ] && $do_clean; then + info "Cleaning flash content $target_path" + clean_flash + fi + if $secureboot; then + secureboot_install + else + regular_install + fi + else + info "Using previously installed image" + fi +fi + +# chainloading using kexec +if $do_kexec; then + if $secureboot; then + secureboot_boot + else + regular_boot + fi +fi diff --git a/files/apt/apt.conf.d/81norecommends b/files/apt/apt.conf.d/81norecommends new file mode 100644 index 000000000000..d868eb45e228 --- /dev/null +++ b/files/apt/apt.conf.d/81norecommends @@ -0,0 +1,3 @@ +APT::Install-Recommends "false"; +APT::AutoRemove::RecommendsImportant "false"; +APT::AutoRemove::SuggestsImportant "false"; diff --git a/files/apt/apt.conf.d/apt-clean b/files/apt/apt.conf.d/apt-clean new file mode 100644 index 000000000000..886c6d829a3b --- /dev/null +++ b/files/apt/apt.conf.d/apt-clean @@ -0,0 +1,19 @@ +# Since for most Docker users, package installs happen in "docker build" steps, +# they essentially become individual layers due to the way Docker handles +# layering, especially using CoW filesystems. What this means for us is that +# the caches that APT keeps end up just wasting space in those layers, making +# our layers unnecessarily large (especially since we'll normally never use +# these caches again and will instead just "docker build" again and make a brand +# new image). + +# Ideally, these would just be invoking "apt-get clean", but in our testing, +# that ended up being cyclic and we got stuck on APT's lock, so we get this fun +# creation that's essentially just "apt-get clean". +DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; }; +APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; }; + +Dir::Cache::pkgcache ""; +Dir::Cache::srcpkgcache ""; + +# Note that we do realize this isn't the ideal way to do this, and are always +# open to better suggestions (https://github.com/docker/docker/issues). diff --git a/files/apt/apt.conf.d/apt-gzip-indexes b/files/apt/apt.conf.d/apt-gzip-indexes new file mode 100644 index 000000000000..6d29ac4474de --- /dev/null +++ b/files/apt/apt.conf.d/apt-gzip-indexes @@ -0,0 +1,11 @@ +# Since Docker users using "RUN apt-get update && apt-get install -y ..." in +# their Dockerfiles don't go delete the lists files afterwards, we want them to +# be as small as possible on-disk, so we explicitly request "gz" versions and +# tell Apt to keep them gzipped on-disk. + +# For comparison, an "apt-get update" layer without this on a pristine +# "debian:wheezy" base image was "29.88 MB", where with this it was only +# "8.273 MB". + +Acquire::GzipIndexes "true"; +Acquire::CompressionTypes::Order:: "gz"; diff --git a/files/apt/apt.conf.d/apt-no-languages b/files/apt/apt.conf.d/apt-no-languages new file mode 100644 index 000000000000..964d83d6c5b9 --- /dev/null +++ b/files/apt/apt.conf.d/apt-no-languages @@ -0,0 +1,5 @@ +# In Docker, we don't often need the "Translations" files, so we're just wasting +# time and space by downloading them, and this inhibits that. For users that do +# need them, it's a simple matter to delete this file and "apt-get update". :) + +Acquire::Languages "none"; diff --git a/files/apt/apt.conf.d/no-check-valid-until b/files/apt/apt.conf.d/no-check-valid-until new file mode 100644 index 000000000000..c7c25d017f7f --- /dev/null +++ b/files/apt/apt.conf.d/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/files/apt/sources.list.amd64 b/files/apt/sources.list.amd64 new file mode 100644 index 000000000000..45902be1078c --- /dev/null +++ b/files/apt/sources.list.amd64 @@ -0,0 +1,13 @@ +## Debian mirror on Microsoft Azure +## Ref: http://debian-archive.trafficmanager.net/ + +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ buster main contrib non-free +deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian/ buster main contrib non-free +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ buster/updates main contrib non-free +deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ buster/updates main contrib non-free +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ buster-backports main contrib non-free +deb [arch=amd64] http://packages.trafficmanager.net/debian/debian buster main contrib non-free +deb-src [arch=amd64] http://packages.trafficmanager.net/debian/debian buster main contrib non-free +deb [arch=amd64] http://packages.trafficmanager.net/debian/debian-security/ buster_updates main contrib non-free +deb-src [arch=amd64] http://packages.trafficmanager.net/debian/debian-security/ buster_updates main contrib non-free +deb [arch=amd64] http://packages.trafficmanager.net/debian/debian buster-backports main contrib non-free diff --git a/files/apt/sources.list.arm64 b/files/apt/sources.list.arm64 new file mode 100644 index 000000000000..58b84978d023 --- /dev/null +++ b/files/apt/sources.list.arm64 @@ -0,0 +1,13 @@ +## Debian mirror for ARM +## Not the repo mirror site can change in future, and needs to be updated to be in sync + +deb [arch=arm64] http://deb.debian.org/debian buster main contrib non-free +deb-src [arch=arm64] http://deb.debian.org/debian buster main contrib non-free +deb [arch=arm64] http://deb.debian.org/debian buster-updates main contrib non-free +deb-src [arch=arm64] http://deb.debian.org/debian buster-updates main contrib non-free +deb [arch=arm64] http://ftp.debian.org/debian buster-backports main +deb [arch=arm64] http://packages.trafficmanager.net/debian/debian buster main contrib non-free +deb-src [arch=arm64] http://packages.trafficmanager.net/debian/debian buster main contrib non-free +deb [arch=arm64] http://packages.trafficmanager.net/debian/debian buster-updates main contrib non-free +deb-src [arch=arm64] http://packages.trafficmanager.net/debian/debian buster-updates main contrib non-free +deb [arch=arm64] http://packages.trafficmanager.net/debian/debian buster-backports main diff --git a/files/apt/sources.list.armhf b/files/apt/sources.list.armhf new file mode 100644 index 000000000000..eb6fe3be6889 --- /dev/null +++ b/files/apt/sources.list.armhf @@ -0,0 +1,13 @@ +## Debian mirror for ARM +## Not the repo mirror site can change in future, and needs to be updated to be in sync + +deb [arch=armhf] http://deb.debian.org/debian buster main contrib non-free +deb-src [arch=armhf] http://deb.debian.org/debian buster main contrib non-free +deb [arch=armhf] http://deb.debian.org/debian buster-updates main contrib non-free +deb-src [arch=armhf] http://deb.debian.org/debian buster-updates main contrib non-free +deb [arch=armhf] http://ftp.debian.org/debian buster-backports main +deb [arch=armhf] http://packages.trafficmanager.net/debian/debian buster main contrib non-free +deb-src [arch=armhf] http://packages.trafficmanager.net/debian/debian buster main contrib non-free +deb [arch=armhf] http://packages.trafficmanager.net/debian/debian buster-updates main contrib non-free +deb-src [arch=armhf] http://packages.trafficmanager.net/debian/debian buster-updates main contrib non-free +deb [arch=armhf] http://packages.trafficmanager.net/debian/debian buster-backports main diff --git a/files/build_scripts/generate_asic_config_checksum.py b/files/build_scripts/generate_asic_config_checksum.py new file mode 100755 index 000000000000..546cf5c7f58e --- /dev/null +++ b/files/build_scripts/generate_asic_config_checksum.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +import hashlib +import os +import syslog + +SYSLOG_IDENTIFIER = 'asic_config_checksum' + +CHUNK_SIZE = 8192 + +CONFIG_FILES = { + os.path.abspath('./src/sonic-swss/swssconfig/sample/'): ['netbouncer.json'] +} + +OUTPUT_FILE = os.path.abspath('./asic_config_checksum') + + +def log_info(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + + +def log_error(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_ERR, msg) + syslog.closelog() + + +def get_config_files(config_file_map): + ''' + Generates a list of absolute paths to ASIC config files. + ''' + config_files = [] + for path, files in config_file_map.items(): + for config_file in files: + config_files.append(os.path.join(path, config_file)) + return config_files + + +def generate_checksum(checksum_files): + ''' + Generates a checksum for a given list of files. Returns None if an error + occurs while reading the files. + + NOTE: The checksum is performed in the order provided. This function does + NOT do any re-ordering of the files before creating the checksum. + ''' + checksum = hashlib.sha1() + for checksum_file in checksum_files: + try: + with open(checksum_file, 'rb') as f: + for chunk in iter(lambda: f.read(CHUNK_SIZE), b""): + checksum.update(chunk) + except IOError as e: + log_error('Error processing ASIC config file ' + checksum_file + ':' + e.strerror) + return None + + return checksum.hexdigest() + + +def main(): + config_files = sorted(get_config_files(CONFIG_FILES)) + checksum = generate_checksum(config_files) + if checksum is None: + exit(1) + + with open(OUTPUT_FILE, 'w') as output: + output.write(checksum + '\n') + + +if __name__ == '__main__': + main() diff --git a/files/build_scripts/mask_disabled_services.py b/files/build_scripts/mask_disabled_services.py new file mode 100755 index 000000000000..f3a1d76bf102 --- /dev/null +++ b/files/build_scripts/mask_disabled_services.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import json +import subprocess + +INIT_CFG_FILE_PATH = '/etc/sonic/init_cfg.json' + +with open(INIT_CFG_FILE_PATH) as init_cfg_file: + init_cfg = json.load(init_cfg_file) + if 'FEATURE' in init_cfg: + for feature_name, feature_props in init_cfg['FEATURE'].items(): + if 'state' in feature_props and feature_props['state'] == 'disabled': + subprocess.run(['systemctl', 'mask', '{}.service'.format(feature_name)]) diff --git a/files/build_templates/arp_update_vars.j2 b/files/build_templates/arp_update_vars.j2 new file mode 100644 index 000000000000..b9315b5ebe50 --- /dev/null +++ b/files/build_templates/arp_update_vars.j2 @@ -0,0 +1,5 @@ +{ + "interface": "{% for (name, prefix) in INTERFACE|pfx_filter %}{% if prefix|ipv6 %}{{ name }} {% endif %}{% endfor %}", + "pc_interface" : "{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %}{% if prefix|ipv6 %}{{ name }} {% endif %}{% endfor %}", + "vlan" : "{% if VLAN %}{{ VLAN.keys() | join(' ') }}{% endif %}" +} diff --git a/files/build_templates/buffers_config.j2 b/files/build_templates/buffers_config.j2 new file mode 100644 index 000000000000..3b11b406c738 --- /dev/null +++ b/files/build_templates/buffers_config.j2 @@ -0,0 +1,194 @@ +{%- macro set_default_topology() %} +{%- if default_topo is defined %} +{{ default_topo }} +{%- else %} +def +{%- endif %} +{%- endmacro -%} + +{# Determine device topology and filename postfix #} +{%- if DEVICE_METADATA is defined and DEVICE_METADATA['localhost']['type'] is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- if 'torrouter' in switch_role.lower() and 'mgmt' not in switch_role.lower()%} +{%- set filename_postfix = 't0' %} +{%- elif 'leafrouter' in switch_role.lower() and 'mgmt' not in switch_role.lower()%} +{%- set filename_postfix = 't1' %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- endif %} +{%- else %} +{%- set filename_postfix = set_default_topology() %} +{%- set switch_role = '' %} +{%- endif -%} + +{# Import default values from device HWSKU folder #} +{%- import 'buffers_defaults_%s.j2' % filename_postfix as defs with context %} + +{%- set default_cable = defs.default_cable -%} + +{# 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 #} +{%- if defs.ports2cable is defined %} + {%- set ports2cable = defs.ports2cable %} +{%- else %} + {%- set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } + -%} +{%- endif %} + +{%- macro cable_length(port_name) %} + {%- set cable_len = [] %} + {%- for local_port in DEVICE_NEIGHBOR %} + {%- if local_port == port_name %} + {%- if DEVICE_NEIGHBOR_METADATA is defined and DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] %} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] %} + {%- set neighbor_role = neighbor.type %} + {%- if 'asic' == neighbor_role | lower %} + {%- set roles1 = 'internal' %} + {%- if 'internal' not in ports2cable %} + {%- set _ = ports2cable.update({'internal': '5m'}) %} + {%- endif -%} + {%- else %} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role %} + {%- set roles1 = roles1 | lower %} + {%- set roles2 = roles2 | lower %} + {%- set roles1 = roles1.replace('backend', '') %} + {%- set roles2 = roles2.replace('backend', '') %} + {%- endif %} + {%- 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 %} + {%- if 'torrouter' in switch_role.lower() and 'mgmt' not in switch_role.lower()%} + {%- for local_port in VLAN_MEMBER %} + {%- if local_port[1] == port_name %} + {%- set roles3 = switch_role + '_' + 'server' %} + {%- set roles3 = roles3 | lower %} + {%- set roles3 = roles3.replace('backend', '') %} + {%- if roles3 in ports2cable %} + {%- if cable_len.append(ports2cable[roles3]) %}{% endif %} + {%- endif %} + {%- endif %} + {%- endfor %} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- else -%} + {{ default_cable }} + {%- endif %} + {%- endif %} +{%- endmacro %} + +{%- set PORT_ALL = [] %} + +{%- if PORT is not defined %} + {%- if defs.generate_port_lists(PORT_ALL) %} {% endif %} +{%- else %} + {%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') %} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT_ALL %} + {%- set cable = cable_length(port) %} + "{{ port }}": "{{ cable }}"{%- if not loop.last %},{% endif %} + + {% endfor %} + } + }, + +{% if defs.generate_buffer_pool_and_profiles is defined %} +{{ defs.generate_buffer_pool_and_profiles() }} +{% endif %} + +{%- if defs.generate_profile_lists is defined %} +{{ defs.generate_profile_lists(port_names_active) }}, +{% endif %} + +{%- if defs.generate_pg_profils is defined %} +{{ defs.generate_pg_profils(port_names_active) }} +{% else %} + "BUFFER_PG": { +{% for port in PORT_ACTIVE %} +{% if dynamic_mode is defined %} + "{{ port }}|3-4": { + "profile" : "NULL" + }, +{% endif %} + "{{ port }}|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + }, +{% endif %} + +{% if defs.generate_queue_buffers is defined %} +{{ defs.generate_queue_buffers(port_names_active) }} +{% else %} + "BUFFER_QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + } +{% endif %} +{% if dynamic_mode is defined %} + , + "DEFAULT_LOSSLESS_BUFFER_PARAMETER": { + "AZURE": { + "default_dynamic_th": "0" + } + }, + "LOSSLESS_TRAFFIC_PATTERN": { + "AZURE": { + "mtu": "1024", + "small_packet_percentage": "100" + } + } +{% endif %} +} diff --git a/files/build_templates/config-chassisdb.service.j2 b/files/build_templates/config-chassisdb.service.j2 new file mode 100644 index 000000000000..a50d0de72fb1 --- /dev/null +++ b/files/build_templates/config-chassisdb.service.j2 @@ -0,0 +1,12 @@ +[Unit] +Description=Config chassis_db +After=rc-local.service +Requires=rc-local.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/config-chassisdb +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target 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 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/dhcp_relay.service.j2 b/files/build_templates/dhcp_relay.service.j2 new file mode 100644 index 000000000000..d501a663feba --- /dev/null +++ b/files/build_templates/dhcp_relay.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=DHCP relay container +Requires=updategraph.service +After=updategraph.service swss.service syncd.service teamd.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/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 new file mode 100644 index 000000000000..388451fe720c --- /dev/null +++ b/files/build_templates/docker_image_ctl.j2 @@ -0,0 +1,483 @@ +#!/bin/bash + +# 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 + + +{%- 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}}'"}} "${DOCKERNAME}")" + + 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 + + ln -s /proc/$PID/ns/net /var/run/netns/$NET_NS +} +{%- endif %} + +function updateSyslogConf() +{ + # On multiNPU platforms, change the syslog target ip to docker0 ip to allow logs from containers + # running on the namespace to reach the rsyslog service running on the host + # Also update the container name + if [[ ($NUM_ASIC -gt 1) ]]; then + TARGET_IP=$(docker network inspect bridge --format={{ "'{{(index .IPAM.Config 0).Gateway}}'" }}) + CONTAINER_NAME="$DOCKERNAME" + TMP_FILE="/tmp/rsyslog.$CONTAINER_NAME.conf" + + sonic-cfggen -t /usr/share/sonic/templates/rsyslog-container.conf.j2 -a "{\"target_ip\": \"$TARGET_IP\", \"container_name\": \"$CONTAINER_NAME\" }" > $TMP_FILE + docker cp $TMP_FILE ${DOCKERNAME}:/etc/rsyslog.conf + rm -rf $TMP_FILE + fi +} +function ebtables_config() +{ + if [ "$DEV" ]; then + # Install ebtables filter in namespaces on multi-asic. + ip netns exec $NET_NS ebtables-restore < /etc/ebtables.filter.cfg + else + if [[ ! ($NUM_ASIC -gt 1) ]]; then + # Install ebtables filter in host for single asic. + ebtables-restore < /etc/ebtables.filter.cfg + fi + fi +} + +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.abspath(mnts[0]['Source'])" 2>/dev/null +} + +function getBootType() +{ + # same code snippet in files/scripts/syncd.sh + case "$(cat /proc/cmdline)" in + *SONIC_BOOT_TYPE=warm*) + TYPE='warm' + ;; + *SONIC_BOOT_TYPE=fastfast*) + TYPE='fastfast' + ;; + *SONIC_BOOT_TYPE=fast*|*fast-reboot*) + TYPE='fast' + ;; + *) + TYPE='cold' + esac + echo "${TYPE}" +} + +function preStartAction() +{ +{%- if docker_container_name == "database" %} + WARM_DIR=/host/warmboot + if [ "$DATABASE_TYPE" != "chassisdb" ]; then + 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$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$DEV:/var/lib/redis/ + fi + fi +{%- elif docker_container_name == "snmp" %} + $SONIC_DB_CLI STATE_DB HSET 'DEVICE_METADATA|localhost' chassis_serial_number $(decode-syseeprom -s) +{%- else %} + : # nothing +{%- endif %} + updateSyslogConf +} + +function postStartAction() +{ +{%- if docker_container_name == "database" %} + if [ "$DEV" ]; then + # Enable the forwarding on eth0 interface in namespace. + SYSCTL_NET_CONFIG="/etc/sysctl.d/sysctl-net.conf" + docker exec -i database$DEV sed -i -e "s/^net.ipv4.conf.eth0.forwarding=0/net.ipv4.conf.eth0.forwarding=1/; + s/^net.ipv6.conf.eth0.forwarding=0/net.ipv6.conf.eth0.forwarding=1/" $SYSCTL_NET_CONFIG + docker exec -i database$DEV sysctl --system -e + link_namespace $DEV + fi + # Setup ebtables configuration + ebtables_config + + # chassisdb starts before database starts, bypass the PING check since other + # databases are not availbale until database container is ready. + # also chassisdb doesn't support warm/fast reboot, its dump.rdb is deleted + # at service startup time, nothing need to be done here. + if [ "$DATABASE_TYPE" != "chassisdb" ]; then + # Wait until supervisord and redis starts. This change is needed + # because now database_config.json is jinja2 templated based + # and by the time file gets generated if we do redis ping + # then we catch python exception of file not valid + # that comes to syslog which is unwanted so wait till database + # config is ready and then ping + until [[ ($(docker exec -i database$DEV pgrep -x -c supervisord) -gt 0) && ($($SONIC_DB_CLI PING | grep -c PONG) -gt 0) ]]; do + sleep 1; + done + 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.json dump file, load it. + if [ -r /etc/sonic/config_db$DEV.json ]; then + if [ -r /etc/sonic/init_cfg.json ]; then + $SONIC_CFGGEN -j /etc/sonic/init_cfg.json -j /etc/sonic/config_db$DEV.json --write-to-db + else + $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 + $SONIC_DB_CLI STATE_DB SET "FAST_REBOOT|system" "1" "EX" "180" + fi + + $SONIC_DB_CLI CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1" + fi + + if [[ -x /usr/local/bin/db_migrator.py ]]; then + # Migrate the DB to the latest schema version if needed + if [ -z "$DEV" ]; then + /usr/local/bin/db_migrator.py -o migrate + fi + fi + # Add redis UDS to the redis group and give read/write access to the group + REDIS_SOCK="/var/run/redis${DEV}/redis.sock" + else + until [[ ($(docker exec -i ${DOCKERNAME} pgrep -x -c supervisord) -gt 0) && + ($(docker exec -i ${DOCKERNAME} $SONIC_DB_CLI CHASSIS_APP_DB PING | grep -c True) -gt 0) ]]; do + sleep 1 + done + REDIS_SOCK="/var/run/redis-chassis/redis_chassis.sock" + fi + chgrp -f redis $REDIS_SOCK && chmod -f 0760 $REDIS_SOCK +{%- elif docker_container_name == "swss" %} + 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$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$DEV touch /ready # signal swssconfig.sh to go +{%- elif docker_container_name == "pmon" %} + + DEVPATH="/usr/share/sonic/device" + REBOOT="platform_reboot" + PSENSOR="/usr/local/bin/platform_sensors.py" + if [ -d ${DEVPATH}/${PLATFORM} ] && [ -f $PSENSOR ]; then + exist=`docker exec -i pmon ls /usr/bin/platform_sensors.py "$@" 2>/dev/null` + if [ -z "$exist" ]; then + docker cp $PSENSOR pmon:/usr/bin/ + fi + fi +{%- else %} + : # nothing +{%- endif %} +} + +start() { + # Obtain boot type from kernel arguments + BOOT_TYPE=`getBootType` + + # Obtain our platform as we will mount directories with these names in each docker + PLATFORM=${PLATFORM:-`$SONIC_CFGGEN -H -v DEVICE_METADATA.localhost.platform`} + + + # Parse the device specific asic conf file, if it exists + ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf + if [ -f "$ASIC_CONF" ]; then + source $ASIC_CONF + fi + + {%- if docker_container_name == "database" %} + # Don't mount HWSKU in {{docker_container_name}} container. + HWSKU="" + MOUNTPATH="" + {%- else %} + # Obtain our HWSKU as we will mount directories with these names in each docker + HWSKU=${HWSKU:-`$SONIC_CFGGEN -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`} + MOUNTPATH="/usr/share/sonic/device/$PLATFORM/$HWSKU" + if [ "$DEV" ]; then + MOUNTPATH="$MOUNTPATH/$DEV" + fi + {%- endif %} + DOCKERCHECK=`docker inspect --type container ${DOCKERNAME} 2>/dev/null` + if [ "$?" -eq "0" ]; then + {%- if docker_container_name == "database" %} + DOCKERMOUNT="" + {%- else %} + DOCKERMOUNT=`getMountPoint "$DOCKERCHECK"` + {%- endif %} + if [ x"$DOCKERMOUNT" == x"$MOUNTPATH" ]; then + preStartAction + {%- if docker_container_name == "database" %} + echo "Starting existing ${DOCKERNAME} container" + docker start ${DOCKERNAME} + {%- else %} + echo "Starting existing ${DOCKERNAME} container with HWSKU $HWSKU" + /usr/local/bin/container start ${DOCKERNAME} + {%- endif %} + postStartAction + exit $? + fi + + # docker created with a different HWSKU, remove and recreate + echo "Removing obsolete ${DOCKERNAME} container with HWSKU $DOCKERMOUNT" + docker rm -f ${DOCKERNAME} + fi + + {%- if docker_container_name == "database" %} + + echo "Creating new ${DOCKERNAME} container" + if [ "$DATABASE_TYPE" != "chassisdb" ]; then + if [ -z "$DEV" ]; then + # if database_global exists in old_config, use it; otherwise use the default one in new image + if [ -f /etc/sonic/old_config/database_global.json ]; then + echo "Use database_global.json from old system..." + mv /etc/sonic/old_config/database_global.json /etc/sonic/ + fi + fi + # 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$DEV.json ]; then + echo "Use database_config.json from old system..." + mv /etc/sonic/old_config/database_config$DEV.json /etc/sonic/ + fi + fi + {%- else %} + echo "Creating new ${DOCKERNAME} container with HWSKU $HWSKU" + {%- endif %} + + {%- if docker_container_name == "swss" %} + # Obtain the vendor name + ASIC_VENDOR=`$SONIC_CFGGEN -y /etc/sonic/sonic_version.yml -v asic_type` + + # Generate the asic_table.json and peripheral_table.json + if [ ! -f /etc/sonic/asic_table.json ] && [ -f /usr/share/sonic/templates/asic_table.j2 ]; then + sonic-cfggen -d -t /usr/share/sonic/templates/asic_table.j2 > /etc/sonic/asic_table.json + fi + if [ ! -f /etc/sonic/peripheral_table.json ] && [ -f /usr/share/sonic/device/$PLATFORM/port_peripheral_config.j2 ]; then + sonic-cfggen -d -t /usr/share/sonic/device/$PLATFORM/port_peripheral_config.j2 > /etc/sonic/peripheral_table.json + fi + {%- endif %} + + # In Multi ASIC platforms the global database config file database_global.json will exist. + # Parse the file and get the include path for the database_config.json files used in + # various namesapces. The database_config paths are relative to the DIR of SONIC_DB_GLOBAL_JSON. + SONIC_DB_GLOBAL_JSON="/var/run/redis/sonic-db/database_global.json" + if [ -f "$SONIC_DB_GLOBAL_JSON" ]; then + # TODO Create a separate python script with the below logic and invoke it here. + redis_dir_list=`/usr/bin/python -c "import sys; import os; import json; f=open(sys.argv[1]); \ + global_db_dir = os.path.dirname(sys.argv[1]); data=json.load(f); \ + print(\" \".join([os.path.normpath(global_db_dir+'/'+elem['include']).partition('sonic-db')[0]\ + for elem in data['INCLUDES'] if 'namespace' in elem])); f.close()" $SONIC_DB_GLOBAL_JSON` + fi + + {%- if docker_container_name == "database" %} + start_chassis_db=0 + chassis_db_address="" + chassisdb_config="/usr/share/sonic/device/$PLATFORM/chassisdb.conf" + [ -f $chassisdb_config ] && source $chassisdb_config + DB_OPT=" -v /var/run/redis-chassis:/var/run/redis-chassis:ro " + if [[ "$start_chassis_db" != "1" ]] && [[ -z "$chassis_db_address" ]]; then + DB_OPT="" + else + DB_OPT=$DB_OPT" --add-host=redis_chassis.server:$chassis_db_address " + fi + {%- endif %} + + if [ -z "$DEV" ]; then + NET="host" + + # For Multi-ASIC platform we have to mount the redis paths for database instances running in different + # namespaces, into the single instance dockers like snmp, pmon on linux host. These global dockers + # will need to get/set tables from databases in different namespaces. + # /var/run/redis0 ---> mounted as --> /var/run/redis0 + # /var/run/redis1 ---> mounted as --> /var/run/redis1 .. etc + # The below logic extracts the base DIR's where database_config.json's for various namespaces exist. + # redis_dir_list is a string of form "/var/run/redis0/ /var/run/redis1/ /var/run/redis2/" + + {%- if docker_container_name != "database" %} + if [ -n "$redis_dir_list" ]; then + for redis_dir in $redis_dir_list + do + REDIS_MNT=$REDIS_MNT" -v $redis_dir:$redis_dir:rw " + done + fi + {%- else %} + if [ "$DATABASE_TYPE" == "chassisdb" ]; then + DB_OPT=${DB_OPT/redis-chassis:ro/redis-chassis:rw} + DB_OPT=$DB_OPT" -v /var/run/redis-chassis:/var/run/redis:rw " + DB_OPT=$DB_OPT" --env DATABASE_TYPE=$DATABASE_TYPE" + else + DB_OPT=$DB_OPT" -v /var/run/redis$DEV:/var/run/redis:rw " + fi + {%- endif %} + else + # This part of code is applicable for Multi-ASIC platforms. Here we mount the namespace specific + # redis directory into the docker running in that namespace. Below eg: is for namespace "asic1" + # /var/run/redis1 ---> mounted as --> /var/run/redis1 + # redis_dir_list is a string of form "/var/run/redis0/ /var/run/redis1/ /var/run/redis2/" + if [ -n "$redis_dir_list" ]; then + id=`expr $DEV + 1` + redis_dir=`echo $redis_dir_list | cut -d " " -f $id` + REDIS_MNT=" -v $redis_dir:$redis_dir:rw " + fi + + {%- if docker_container_name == "database" %} + DB_OPT=$DB_OPT" -v /var/run/redis$DEV:/var/run/redis:rw " + {%- else %} + NET="container:database$DEV" + DB_OPT="" + {%- 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 \ + -e RUNTIME_OWNER=local \ + --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 %} +{%- if '--log-driver=json-file' in docker_image_run_opt or '--log-driver' not in docker_image_run_opt %} + --log-opt max-size=2M --log-opt max-file=5 \ +{%- endif %} +{%- if sonic_asic_platform == "mellanox" %} +{%- if docker_container_name == "syncd" %} + -v /var/log/mellanox/sniffer:/var/log/mellanox/sniffer:rw \ + -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:/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 %} +{%- if sonic_asic_platform == "broadcom" %} +{%- if docker_container_name == "syncd" %} + -v /var/run/docker-syncd$DEV:/var/run/sswsyncd \ +{%- endif %} +{%- endif %} +{%- if docker_container_name == "swss" %} + -e ASIC_VENDOR=$ASIC_VENDOR \ +{%- endif -%} +{%- if docker_container_name == "bgp" %} + -v /etc/sonic/frr/$DEV:/etc/frr:rw \ +{%- endif %} +{%- if docker_container_name == "database" %} + $DB_OPT \ +{%- else %} + -v /var/run/redis$DEV:/var/run/redis:rw \ + -v /var/run/redis-chassis:/var/run/redis-chassis:ro \ + -v /usr/share/sonic/device/$PLATFORM/$HWSKU/$DEV:/usr/share/sonic/hwsku:ro \ +{%- endif %} + $REDIS_MNT \ + -v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \ +{%- if sonic_asic_platform != "mellanox" %} + --tmpfs /tmp \ +{%- endif %} + --tmpfs /var/tmp \ + --env "NAMESPACE_ID"="$DEV" \ + --env "NAMESPACE_PREFIX"="$NAMESPACE_PREFIX" \ + --env "NAMESPACE_COUNT"=$NUM_ASIC \ + --name=$DOCKERNAME {{docker_image_name}}:latest || { + echo "Failed to docker run" >&1 + exit 4 + } + + preStartAction + {%- if docker_container_name == "database" %} + docker start $DOCKERNAME + {%- else %} + /usr/local/bin/container start ${DOCKERNAME} + {%- endif %} + postStartAction +} + +wait() { + {%- if docker_container_name == "database" %} + docker wait $DOCKERNAME + {%- else %} + /usr/local/bin/container wait $DOCKERNAME + {%- endif %} +} + +stop() { + {%- if docker_container_name == "database" %} + docker stop $DOCKERNAME + if [ "$DEV" ]; then + ip netns delete "$NET_NS" + fi + {%- elif docker_container_name == "teamd" %} + # Longer timeout of 60 sec to wait for Portchannels to be cleaned. + /usr/local/bin/container stop -t 60 $DOCKERNAME + {%- else %} + /usr/local/bin/container stop $DOCKERNAME + {%- endif %} +} + +DOCKERNAME={{docker_container_name}} +OP=$1 +DEV=$2 # namespace/device number to operate on +{%- if docker_container_name == "database" %} +if [ "$DEV" == "chassisdb" ]; then + DATABASE_TYPE="chassisdb" + DOCKERNAME=$DOCKERNAME"-chassis" + unset DEV +fi +{%- endif %} +NAMESPACE_PREFIX="asic" +DOCKERNAME=$DOCKERNAME$DEV +if [ "$DEV" ]; then + NET_NS="$NAMESPACE_PREFIX$DEV" #name of the network namespace + + SONIC_CFGGEN="sonic-cfggen -n $NET_NS" + SONIC_DB_CLI="sonic-db-cli -n $NET_NS" + else + NET_NS="" + SONIC_CFGGEN="sonic-cfggen" + SONIC_DB_CLI="sonic-db-cli" +fi + +# read SONiC immutable variables +[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment + +case "$1" in + start|wait|stop) + $1 + ;; + *) + echo "Usage: $0 {start namespace(optional)|wait namespace(optional)|stop namespace(optional)}" + exit 1 + ;; +esac diff --git a/files/build_templates/gbsyncd.service.j2 b/files/build_templates/gbsyncd.service.j2 new file mode 100644 index 000000000000..e1080ae7d526 --- /dev/null +++ b/files/build_templates/gbsyncd.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=gbsyncd service +Requires=database.service updategraph.service +ConditionPathExists=!/usr/share/sonic/hwsku/gearbox_config.json +After=database.service updategraph.service +After=interfaces-config.service +After=swss.service +Before=ntp-config.service + +[Service] +User=root +Environment=sonic_asic_platform={{ sonic_asic_platform }} +ExecStartPre=/usr/local/bin/gbsyncd.sh start +ExecStart=/usr/local/bin/gbsyncd.sh wait +ExecStop=/usr/local/bin/gbsyncd.sh stop + +[Install] +WantedBy=multi-user.target diff --git a/files/build_templates/iccpd.service.j2 b/files/build_templates/iccpd.service.j2 new file mode 100644 index 000000000000..979c45de72c5 --- /dev/null +++ b/files/build_templates/iccpd.service.j2 @@ -0,0 +1,13 @@ +[Unit] +Description=ICCPD container +Requires=updategraph.service swss.service +After=updategraph.service swss.service + +[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 + +[Install] +WantedBy=multi-user.target swss.service diff --git a/files/build_templates/init_cfg.json.j2 b/files/build_templates/init_cfg.json.j2 new file mode 100644 index 000000000000..b8ed7c1453e7 --- /dev/null +++ b/files/build_templates/init_cfg.json.j2 @@ -0,0 +1,56 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "buffer_model": {% if default_buffer_model == "dynamic" %}"dynamic"{% else %}"traditional"{% endif %}, + "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", "snat_entry", "dnat_entry", "ipmc_entry"] %} + "{{crm_res}}_threshold_type": "percentage", + "{{crm_res}}_low_threshold": "70", + "{{crm_res}}_high_threshold": "85"{% if not loop.last %},{% endif -%} +{% endfor %} + } + }, +{%- set features = [("bgp", "enabled", false, "enabled"), + ("database", "always_enabled", false, "always_enabled"), + ("dhcp_relay", "enabled", false, "enabled"), + ("lldp", "enabled", false, "enabled"), + ("pmon", "enabled", false, "enabled"), + ("radv", "enabled", false, "enabled"), + ("snmp", "enabled", true, "enabled"), + ("swss", "enabled", false, "enabled"), + ("syncd", "enabled", false, "enabled"), + ("teamd", "enabled", false, "enabled")] %} +{%- if sonic_asic_platform == "vs" %}{% do features.append(("gbsyncd", "enabled", false, "enabled")) %}{% endif %} +{%- if include_iccpd == "y" %}{% do features.append(("iccpd", "disabled", false, "enabled")) %}{% endif %} +{%- if include_mgmt_framework == "y" %}{% do features.append(("mgmt-framework", "enabled", true, "enabled")) %}{% endif %} +{%- if include_nat == "y" %}{% do features.append(("nat", "disabled", false, "enabled")) %}{% endif %} +{%- if include_restapi == "y" %}{% do features.append(("restapi", "enabled", false, "enabled")) %}{% endif %} +{%- if include_sflow == "y" %}{% do features.append(("sflow", "disabled", false, "enabled")) %}{% endif %} +{%- if include_macsec == "y" %}{% do features.append(("macsec", "disabled", false, "enabled")) %}{% endif %} +{%- if include_system_telemetry == "y" %}{% do features.append(("telemetry", "enabled", true, "enabled")) %}{% endif %} + "FEATURE": { +{# has_timer field if set, will start the feature systemd .timer unit instead of .service unit #} +{%- for feature, state, has_timer, autorestart in features %} + "{{feature}}": { + "state": "{{state}}", + "has_timer" : {{has_timer | lower()}}, + "has_global_scope": {% if feature + '.service' in installer_services.split(' ') %}true{% else %}false{% endif %}, + "has_per_asic_scope": {% if feature + '@.service' in installer_services.split(' ') %}true{% else %}false{% endif %}, + "auto_restart": "{{autorestart}}", +{%- if include_kubernetes == "y" %} +{%- if feature in ["dhcp_relay", "lldp", "pmon", "radv", "snmp", "telemetry"] %} + "set_owner": "kube", {% else %} + "set_owner": "local", {% endif %} {% endif %} + "high_mem_alert": "disabled" + }{% if not loop.last %},{% endif -%} +{% endfor %} + } +} diff --git a/files/build_templates/kube_cni.10-flannel.conflist b/files/build_templates/kube_cni.10-flannel.conflist new file mode 100644 index 000000000000..17b50fda1214 --- /dev/null +++ b/files/build_templates/kube_cni.10-flannel.conflist @@ -0,0 +1,21 @@ +{ + "_comment": "This is a dummy file to simulate flannel so that node status will show as Ready", + "name": "cbr0", + "cniVersion": "0.3.1", + "plugins": [ + { + "type": "flannel", + "delegate": { + "hairpinMode": true, + "isDefaultGateway": true + } + }, + { + "type": "portmap", + "capabilities": { + "portMappings": true + } + } + ] +} + diff --git a/files/build_templates/lldp.service.j2 b/files/build_templates/lldp.service.j2 new file mode 120000 index 000000000000..1adb318b9154 --- /dev/null +++ b/files/build_templates/lldp.service.j2 @@ -0,0 +1 @@ +per_namespace/lldp.service.j2 \ No newline at end of file diff --git a/files/build_templates/macsec.service.j2 b/files/build_templates/macsec.service.j2 new file mode 100644 index 000000000000..85229d1aea10 --- /dev/null +++ b/files/build_templates/macsec.service.j2 @@ -0,0 +1,17 @@ +[Unit] +Description=MACsec container +Requires=swss.service +After=swss.service syncd.service +StartLimitIntervalSec=1200 +StartLimitBurst=3 + +[Service] +User=root +ExecStartPre=/usr/bin/macsec.sh start +ExecStart=/usr/bin/macsec.sh wait +ExecStop=/usr/bin/macsec.sh stop +Restart=always +RestartSec=30 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/files/build_templates/mgmt-framework.service.j2 b/files/build_templates/mgmt-framework.service.j2 new file mode 100644 index 000000000000..883711aa82eb --- /dev/null +++ b/files/build_templates/mgmt-framework.service.j2 @@ -0,0 +1,12 @@ +[Unit] +Description=Management Framework container +Requires=database.service +After=database.service swss.service syncd.service +Before=ntp-config.service + +[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 + diff --git a/files/build_templates/mgmt-framework.timer b/files/build_templates/mgmt-framework.timer new file mode 100644 index 000000000000..62ab8ef1bd58 --- /dev/null +++ b/files/build_templates/mgmt-framework.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Delays management framework container until SONiC has started + +[Timer] +OnBootSec=3min 30 sec +Unit=mgmt-framework.service + +[Install] +WantedBy=timers.target diff --git a/files/build_templates/nat.service.j2 b/files/build_templates/nat.service.j2 new file mode 100644 index 000000000000..1d267cfe9302 --- /dev/null +++ b/files/build_templates/nat.service.j2 @@ -0,0 +1,19 @@ +[Unit] +Description=NAT container +Requires=updategraph.service +After=updategraph.service swss.service syncd.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/organization_extensions.sh b/files/build_templates/organization_extensions.sh new file mode 100755 index 000000000000..db05a4e3f59d --- /dev/null +++ b/files/build_templates/organization_extensions.sh @@ -0,0 +1,52 @@ +#!/bin/bash +######################################################################### +## This script is to automate Orignaization specific extensions # +## such as Configuration & Scripts for features like AAA, ZTP, etc. # +## to include in ONIE installer image # +## # +## USAGE: # +## ./organization_extensions.sh -f -n # +## ./organization_extensions.sh \ # +## --fsroot \ # +## --hostname # +## PARAMETERS: # +## -f FILESYSTEM_ROOT # +## The location of the root file system # +## -h HOSTNAME # +## The hostname of the target system # +######################################################################### + +## Initialize the arguments to default values. +## The values get updated to user provided value, if supplied +FILESYSTEM_ROOT=./fsroot +HOSTNAME=sonic + +# read the options +TEMP=`getopt -o f:h: --long fsroot:,hostname: -- "$@"` +eval set -- "$TEMP" + +# extract options and their arguments into variables. +while true ; do + case "$1" in + -f|--fsroot) + case "$2" in + "") shift 2 ;; + *) FILESYSTEM_ROOT=$2 ; shift 2 ;; + esac ;; + -h|--hostname) + case "$2" in + "") shift 2 ;; + *) HOSTNAME=$2 ; shift 2 ;; + esac ;; + --) shift ; break ;; + *) echo "Internal error!" ; exit 1 ;; + esac +done + +echo "Executing SONIC Organization Extensions" + +## Place your Organization specific code / scipts here ... + + +echo "SONIC Organization Extensions - Done" + 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..9f3c72e20db5 --- /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/local/bin/{{docker_container_name}}.sh start{% if multi_instance == 'true' %} %i{% endif %} +ExecStart=/usr/local/bin/{{docker_container_name}}.sh wait{% if multi_instance == 'true' %} %i{% endif %} +ExecStop=/usr/local/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..c8a59ab25bbd --- /dev/null +++ b/files/build_templates/per_namespace/database.service.j2 @@ -0,0 +1,24 @@ +[Unit] +Description=Database container +{% if multi_instance == 'true' %} +Requires=database.service +After=database.service +{% endif %} +Wants=database-chassis.service +After=database-chassis.service +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..8ac19037ffe7 --- /dev/null +++ b/files/build_templates/per_namespace/swss.service.j2 @@ -0,0 +1,29 @@ +[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 +{% endif %} +Requires=updategraph.service +After=updategraph.service +After=interfaces-config.service +Before=ntp-config.service pmon.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..8e0029a29421 --- /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.service +After=nps-modules.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=480 +{% 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..f5936baa6a79 --- /dev/null +++ b/files/build_templates/per_namespace/teamd.service.j2 @@ -0,0 +1,23 @@ +[Unit] +Description=TEAMD container +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 %} +Requires=updategraph.service +After=updategraph.service +Before=ntp-config.service +StartLimitIntervalSec=1200 +StartLimitBurst=3 + +[Service] +User={{ sonicadmin_user }} +ExecStartPre=/usr/local/bin/{{docker_container_name}}.sh start{% if multi_instance == 'true' %} %i{% endif %} +ExecStart=/usr/local/bin/{{docker_container_name}}.sh wait{% if multi_instance == 'true' %} %i{% endif %} +ExecStop=/usr/local/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/pmon.service.j2 b/files/build_templates/pmon.service.j2 new file mode 100644 index 000000000000..9195b4d38ad6 --- /dev/null +++ b/files/build_templates/pmon.service.j2 @@ -0,0 +1,21 @@ +[Unit] +Description=Platform monitor container +Requires=database.service updategraph.service +After=database.service updategraph.service +{% if sonic_asic_platform == 'mellanox' %} +After=syncd.service +{% endif %} +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/qos_config.j2 b/files/build_templates/qos_config.j2 new file mode 100644 index 000000000000..a7c361d69fa5 --- /dev/null +++ b/files/build_templates/qos_config.j2 @@ -0,0 +1,257 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} +{%- set backend_device_types = ['BackEndToRRouter', 'BackEndLeafRouter'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "0", + "2": "0", + "3": "3", + "4": "4", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, +{% if 'type' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['type'] in backend_device_types and 'storage_device' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['storage_device'] == 'true' %} + "DOT1P_TO_TC_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, +{% else %} + "DSCP_TO_TC_MAP": { + "AZURE": { + "0" : "1", + "1" : "1", + "2" : "1", + "3" : "3", + "4" : "4", + "5" : "2", + "6" : "1", + "7" : "1", + "8" : "0", + "9" : "1", + "10": "1", + "11": "1", + "12": "1", + "13": "1", + "14": "1", + "15": "1", + "16": "1", + "17": "1", + "18": "1", + "19": "1", + "20": "1", + "21": "1", + "22": "1", + "23": "1", + "24": "1", + "25": "1", + "26": "1", + "27": "1", + "28": "1", + "29": "1", + "30": "1", + "31": "1", + "32": "1", + "33": "1", + "34": "1", + "35": "1", + "36": "1", + "37": "1", + "38": "1", + "39": "1", + "40": "1", + "41": "1", + "42": "1", + "43": "1", + "44": "1", + "45": "1", + "46": "5", + "47": "1", + "48": "6", + "49": "1", + "50": "1", + "51": "1", + "52": "1", + "53": "1", + "54": "1", + "55": "1", + "56": "1", + "57": "1", + "58": "1", + "59": "1", + "60": "1", + "61": "1", + "62": "1", + "63": "1" + } + }, +{% endif %} + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "14" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "15" + } + }, +{% if asic_type in pfc_to_pg_map_supported_asics %} + "PFC_PRIORITY_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, +{% endif %} + "PORT_QOS_MAP": { +{% for port in PORT_ACTIVE %} + "{{ port }}": { +{% if 'type' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['type'] in backend_device_types and 'storage_device' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['storage_device'] == 'true' %} + "dot1p_to_tc_map" : "[DOT1P_TO_TC_MAP|AZURE]", +{% else %} + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", +{% endif %} + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", +{% if asic_type in pfc_to_pg_map_supported_asics %} + "pfc_to_pg_map" : "[PFC_PRIORITY_TO_PRIORITY_GROUP_MAP|AZURE]", +{% endif %} + "pfc_enable" : "3,4" + }{% if not loop.last %},{% endif %} + +{% endfor %} + }, +{% if generate_wred_profiles is defined %} + {{- generate_wred_profiles() }} +{% else %} + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "1048576", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, +{% endif %} + "QUEUE": { +{% for port in PORT_ACTIVE %} + "{{ port }}|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, +{% endfor %} +{% for port in PORT_ACTIVE %} + "{{ port }}|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }{% if not loop.last %},{% endif %} + +{% endfor %} + } +} diff --git a/files/build_templates/radv.service.j2 b/files/build_templates/radv.service.j2 new file mode 100644 index 000000000000..5cf25a21046d --- /dev/null +++ b/files/build_templates/radv.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=Router advertiser container +Requires=updategraph.service +After=updategraph.service swss.service syncd.service +Before=ntp-config.service +StartLimitIntervalSec=1200 +StartLimitBurst=3 + +[Service] +User={{ sonicadmin_user }} +ExecStartPre=/usr/local/bin/{{ docker_container_name }}.sh start +ExecStart=/usr/local/bin/{{ docker_container_name }}.sh wait +ExecStop=/usr/local/bin/{{ docker_container_name }}.sh stop +Restart=always +RestartSec=30 + +[Install] +WantedBy=multi-user.target diff --git a/files/build_templates/restapi.service.j2 b/files/build_templates/restapi.service.j2 new file mode 100644 index 000000000000..df1a50eb56c7 --- /dev/null +++ b/files/build_templates/restapi.service.j2 @@ -0,0 +1,16 @@ +[Unit] +Description=RestAPI container +Requires=updategraph.service +After=updategraph.service +Before=ntp-config.service + +[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 \ No newline at end of file diff --git a/files/build_templates/sflow.service.j2 b/files/build_templates/sflow.service.j2 new file mode 100644 index 000000000000..e9d5a871432d --- /dev/null +++ b/files/build_templates/sflow.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=sFlow container +Requisite=swss.service +After=swss.service syncd.service hostcfgd.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/share_image/database.service.j2 b/files/build_templates/share_image/database.service.j2 new file mode 100644 index 000000000000..cc3f1b0a4364 --- /dev/null +++ b/files/build_templates/share_image/database.service.j2 @@ -0,0 +1,20 @@ +[Unit] +Description=database-chassis container +Requires=docker.service +ConditionPathExists=/etc/sonic/chassisdb.conf +After=docker.service +After=config-chassisdb.service +Requires=config-chassisdb.service +StartLimitIntervalSec=1200 +StartLimitBurst=3 + +[Service] +User=root +ExecStartPre=/usr/bin/{{docker_container_name}}.sh start chassisdb +ExecStart=/usr/bin/{{docker_container_name}}.sh wait chassisdb +ExecStop=/usr/bin/{{docker_container_name}}.sh stop chassisdb +Restart=always +RestartSec=30 + +[Install] +WantedBy=multi-user.target diff --git a/files/build_templates/snmp.service.j2 b/files/build_templates/snmp.service.j2 new file mode 100644 index 000000000000..4997ab737e37 --- /dev/null +++ b/files/build_templates/snmp.service.j2 @@ -0,0 +1,17 @@ +[Unit] +Description=SNMP container +Requires=updategraph.service +Requisite=swss.service +After=updategraph.service swss.service syncd.service +Before=ntp-config.service +Conflicts=snmp.timer +StartLimitIntervalSec=1200 +StartLimitBurst=3 + +[Service] +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 + diff --git a/files/build_templates/snmp.timer b/files/build_templates/snmp.timer new file mode 100644 index 000000000000..1b3ccf633ce4 --- /dev/null +++ b/files/build_templates/snmp.timer @@ -0,0 +1,12 @@ +[Unit] +Description=Delays snmp container until SONiC has started +Conflicts=snmp.service +After=swss.service + +[Timer] +OnUnitActiveSec=0 sec +OnBootSec=3min 30 sec +Unit=snmp.service + +[Install] +WantedBy=timers.target swss.service diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 new file mode 100644 index 000000000000..2802cd525e3a --- /dev/null +++ b/files/build_templates/sonic_debian_extension.j2 @@ -0,0 +1,737 @@ +#!/bin/bash +## This script is to automate loading of vendor specific docker images +## and installation of configuration files and vendor specific packages +## to debian file system. +## +## USAGE: +## ./sonic_debian_extension.sh FILESYSTEM_ROOT PLATFORM_DIR +## PARAMETERS: +## FILESYSTEM_ROOT +## Path to debian file system root directory + +FILESYSTEM_ROOT=$1 +[ -n "$FILESYSTEM_ROOT" ] || { + echo "Error: no or empty FILESYSTEM_ROOT argument" + exit 1 +} + +PLATFORM_DIR=$2 +[ -n "$PLATFORM_DIR" ] || { + echo "Error: no or empty PLATFORM_DIR argument" + exit 1 +} + +## Enable debug output for script +set -x -e + +CONFIGURED_ARCH=$([ -f .arch ] && cat .arch || echo amd64) + +. functions.sh +BUILD_SCRIPTS_DIR=files/build_scripts +BUILD_TEMPLATES=files/build_templates +IMAGE_CONFIGS=files/image_config +SCRIPTS_DIR=files/scripts + +# Define target fold macro +FILESYSTEM_ROOT_USR="$FILESYSTEM_ROOT/usr" +FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM="$FILESYSTEM_ROOT/usr/lib/systemd/system" +FILESYSTEM_ROOT_USR_SHARE="$FILESYSTEM_ROOT_USR/share" +FILESYSTEM_ROOT_USR_SHARE_SONIC="$FILESYSTEM_ROOT_USR_SHARE/sonic" +FILESYSTEM_ROOT_USR_SHARE_SONIC_SCRIPTS="$FILESYSTEM_ROOT_USR_SHARE_SONIC/scripts" +FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES="$FILESYSTEM_ROOT_USR_SHARE_SONIC/templates" +FILESYSTEM_ROOT_ETC="$FILESYSTEM_ROOT/etc" +FILESYSTEM_ROOT_ETC_SONIC="$FILESYSTEM_ROOT_ETC/sonic" + +GENERATED_SERVICE_FILE="$FILESYSTEM_ROOT/etc/sonic/generated_services.conf" + +clean_sys() { + sudo chroot $FILESYSTEM_ROOT umount /sys/fs/cgroup/* \ + /sys/fs/cgroup \ + /sys || true +} +trap_push clean_sys +sudo LANG=C chroot $FILESYSTEM_ROOT mount sysfs /sys -t sysfs + +sudo bash -c "echo \"DOCKER_OPTS=\"--storage-driver=overlay2\"\" >> $FILESYSTEM_ROOT/etc/default/docker" +sudo cp files/docker/docker $FILESYSTEM_ROOT/etc/init.d/ +if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then + SONIC_NATIVE_DOCKERD_FOR_DOCKERFS=" -H unix:///dockerfs/var/run/docker.sock " + SONIC_NATIVE_DOCKERD_FOR_DOCKERFS_PID="cat `pwd`/dockerfs/var/run/docker.pid" +else + sudo chroot $FILESYSTEM_ROOT service docker start +fi + +# Apply apt configuration files +sudo cp $IMAGE_CONFIGS/apt/sources.list $FILESYSTEM_ROOT/etc/apt/ +sudo mkdir -p $FILESYSTEM_ROOT/etc/apt/sources.list.d/ +sudo cp -R $IMAGE_CONFIGS/apt/sources.list.d/${CONFIGURED_ARCH}/* $FILESYSTEM_ROOT/etc/apt/sources.list.d/ +cat $IMAGE_CONFIGS/apt/sonic-dev.gpg.key | sudo LANG=C chroot $FILESYSTEM_ROOT apt-key add - + +# Update apt's snapshot of its repos +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get update + +# Apply environtment configuration files +sudo cp $IMAGE_CONFIGS/environment/environment $FILESYSTEM_ROOT/etc/ +sudo cp $IMAGE_CONFIGS/environment/motd $FILESYSTEM_ROOT/etc/ + +# Create all needed directories +sudo mkdir -p $FILESYSTEM_ROOT/etc/sonic/ +sudo mkdir -p $FILESYSTEM_ROOT/etc/modprobe.d/ +sudo mkdir -p $FILESYSTEM_ROOT/var/cache/sonic/ +sudo mkdir -p $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ +# This is needed for Stretch and might not be needed for Buster where Linux create this directory by default. +# Keeping it generic. It should not harm anyways. +sudo mkdir -p $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM + +# Install a more recent version of ifupdown2 (and its dependencies via 'apt-get -y install -f') +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 a more recent version of ntp (and its dependencies via 'apt-get -y install -f') +sudo dpkg --root=$FILESYSTEM_ROOT --force-confdef --force-confold -i $debs_path/ntp_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y \ + -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install -f + +# Install dependencies for SONiC config engine +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install \ + python-dev \ + python3-dev + +# Install Python client for Redis +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install "redis==3.5.3" +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install "redis==3.5.3" + +# Install redis-dump-load Python 3 package +# Note: the scripts will be overwritten by corresponding Python 2 package +REDIS_DUMP_LOAD_PY3_WHEEL_NAME=$(basename {{redis_dump_load_py3_wheel_path}}) +sudo cp {{redis_dump_load_py3_wheel_path}} $FILESYSTEM_ROOT/$REDIS_DUMP_LOAD_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $REDIS_DUMP_LOAD_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$REDIS_DUMP_LOAD_PY3_WHEEL_NAME + +# Install redis-dump-load Python 2 package +REDIS_DUMP_LOAD_PY2_WHEEL_NAME=$(basename {{redis_dump_load_py2_wheel_path}}) +sudo cp {{redis_dump_load_py2_wheel_path}} $FILESYSTEM_ROOT/$REDIS_DUMP_LOAD_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install $REDIS_DUMP_LOAD_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$REDIS_DUMP_LOAD_PY2_WHEEL_NAME + +# Install Python module for psutil +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install psutil + +# Install SwSS SDK Python 3 package +# Note: the scripts will be overwritten by corresponding Python 2 package +SWSSSDK_PY3_WHEEL_NAME=$(basename {{swsssdk_py3_wheel_path}}) +sudo cp {{swsssdk_py3_wheel_path}} $FILESYSTEM_ROOT/$SWSSSDK_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $SWSSSDK_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SWSSSDK_PY3_WHEEL_NAME + +# Install SwSS SDK Python 2 package +SWSSSDK_PY2_WHEEL_NAME=$(basename {{swsssdk_py2_wheel_path}}) +sudo cp {{swsssdk_py2_wheel_path}} $FILESYSTEM_ROOT/$SWSSSDK_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install $SWSSSDK_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SWSSSDK_PY2_WHEEL_NAME + +# Install sonic-py-common Python 2 package +SONIC_PY_COMMON_PY2_WHEEL_NAME=$(basename {{sonic_py_common_py2_wheel_path}}) +sudo cp {{sonic_py_common_py2_wheel_path}} $FILESYSTEM_ROOT/$SONIC_PY_COMMON_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install $SONIC_PY_COMMON_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SONIC_PY_COMMON_PY2_WHEEL_NAME + +# Install sonic-py-common Python 3 package +SONIC_PY_COMMON_PY3_WHEEL_NAME=$(basename {{sonic_py_common_py3_wheel_path}}) +sudo cp {{sonic_py_common_py3_wheel_path}} $FILESYSTEM_ROOT/$SONIC_PY_COMMON_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $SONIC_PY_COMMON_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SONIC_PY_COMMON_PY3_WHEEL_NAME + +# Install dependency pkgs for SONiC config engine Python 2 package +if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install libxslt-dev libz-dev +fi + +# Install SONiC config engine Python 2 package +CONFIG_ENGINE_PY2_WHEEL_NAME=$(basename {{config_engine_py2_wheel_path}}) +sudo cp {{config_engine_py2_wheel_path}} $FILESYSTEM_ROOT/$CONFIG_ENGINE_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install $CONFIG_ENGINE_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$CONFIG_ENGINE_PY2_WHEEL_NAME + +# For sonic-config-engine Python 3 package +# Install pyangbind here, outside sonic-config-engine dependencies, as pyangbind causes enum34 to be installed. +# Then immediately uninstall enum34, as enum34 should not be installed for Python >= 3.4, as it causes a +# conflict with the new 'enum' module in the standard library +# https://github.com/robshakir/pyangbind/issues/232 +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install pyangbind==0.8.1 +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 uninstall -y enum34 + +# Install SONiC config engine Python 3 package +CONFIG_ENGINE_PY3_WHEEL_NAME=$(basename {{config_engine_py3_wheel_path}}) +sudo cp {{config_engine_py3_wheel_path}} $FILESYSTEM_ROOT/$CONFIG_ENGINE_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $CONFIG_ENGINE_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$CONFIG_ENGINE_PY3_WHEEL_NAME + +# Install sonic-yang-models py3 package, install dependencies +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/libyang_*.deb +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/libyang-cpp_*.deb +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/python2-yang_*.deb +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/python3-yang_*.deb +SONIC_YANG_MODEL_PY3_WHEEL_NAME=$(basename {{sonic_yang_models_py3_wheel_path}}) +sudo cp {{sonic_yang_models_py3_wheel_path}} $FILESYSTEM_ROOT/$SONIC_YANG_MODEL_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $SONIC_YANG_MODEL_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SONIC_YANG_MODEL_PY3_WHEEL_NAME + +# Install sonic-yang-mgmt Python3 package +SONIC_YANG_MGMT_PY3_WHEEL_NAME=$(basename {{sonic_yang_mgmt_py3_wheel_path}}) +sudo cp {{sonic_yang_mgmt_py3_wheel_path}} $FILESYSTEM_ROOT/$SONIC_YANG_MGMT_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $SONIC_YANG_MGMT_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SONIC_YANG_MGMT_PY3_WHEEL_NAME + +# Install sonic-platform-common Python 2 package +PLATFORM_COMMON_PY2_WHEEL_NAME=$(basename {{platform_common_py2_wheel_path}}) +sudo cp {{platform_common_py2_wheel_path}} $FILESYSTEM_ROOT/$PLATFORM_COMMON_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install $PLATFORM_COMMON_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$PLATFORM_COMMON_PY2_WHEEL_NAME + +# Install sonic-platform-common Python 3 package +PLATFORM_COMMON_PY3_WHEEL_NAME=$(basename {{platform_common_py3_wheel_path}}) +sudo cp {{platform_common_py3_wheel_path}} $FILESYSTEM_ROOT/$PLATFORM_COMMON_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $PLATFORM_COMMON_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$PLATFORM_COMMON_PY3_WHEEL_NAME + +{% if pddf_support == "y" %} +# Install pddf-platform-api-base Python 2 package +PLATFORM_PDDF_COMMON_PY2_WHEEL_NAME=$(basename {{pddf_platform_api_base_py2_wheel_path}}) +sudo cp {{pddf_platform_api_base_py2_wheel_path}} $FILESYSTEM_ROOT/$PLATFORM_PDDF_COMMON_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install $PLATFORM_PDDF_COMMON_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$PLATFORM_PDDF_COMMON_PY2_WHEEL_NAME + +# Install pddf-platform-api-base Python 3 package +PLATFORM_PDDF_COMMON_PY3_WHEEL_NAME=$(basename {{pddf_platform_api_base_py3_wheel_path}}) +sudo cp {{pddf_platform_api_base_py3_wheel_path}} $FILESYSTEM_ROOT/$PLATFORM_PDDF_COMMON_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $PLATFORM_PDDF_COMMON_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$PLATFORM_PDDF_COMMON_PY3_WHEEL_NAME +{% endif %} + +{# Barefoot platform vendors' sonic_platform packages import the Python 'thrift' library #} +{% if sonic_asic_platform == "barefoot" %} +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install thrift==0.13.0 +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install thrift==0.13.0 +{% endif %} + +# Install system-health Python 3 package +SYSTEM_HEALTH_PY3_WHEEL_NAME=$(basename {{system_health_py3_wheel_path}}) +sudo cp {{system_health_py3_wheel_path}} $FILESYSTEM_ROOT/$SYSTEM_HEALTH_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $SYSTEM_HEALTH_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SYSTEM_HEALTH_PY3_WHEEL_NAME + +# Install prerequisites needed for installing the Python m2crypto package, used by sonic-utilities +# These packages can be uninstalled after intallation +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install build-essential libssl-dev swig + +# Install prerequisites needed for using the Python m2crypto package, used by sonic-utilities +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install openssl + +# Install SONiC Utilities Python package +SONIC_UTILITIES_PY3_WHEEL_NAME=$(basename {{sonic_utilities_py3_wheel_path}}) +sudo cp {{sonic_utilities_py3_wheel_path}} $FILESYSTEM_ROOT/$SONIC_UTILITIES_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $SONIC_UTILITIES_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SONIC_UTILITIES_PY3_WHEEL_NAME + +# Install sonic-utilities data files (and any dependencies via 'apt-get -y install -f') +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/sonic-utilities-data_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f + +# sonic-utilities-data 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/ + +# Install prerequisites needed for installing the dependent Python packages of sonic-host-services +# These packages can be uninstalled after installation +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install libcairo2-dev libdbus-1-dev libgirepository1.0-dev libsystemd-dev pkg-config + +# Manually install runtime dependencies to avoid them being auto-removed while uninstalling build dependencies +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install gir1.2-glib-2.0 libdbus-1-3 libgirepository-1.0-1 libsystemd0 + +# Install SONiC host services package +SONIC_HOST_SERVICES_PY3_WHEEL_NAME=$(basename {{sonic_host_services_py3_wheel_path}}) +sudo cp {{sonic_host_services_py3_wheel_path}} $FILESYSTEM_ROOT/$SONIC_HOST_SERVICES_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $SONIC_HOST_SERVICES_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SONIC_HOST_SERVICES_PY3_WHEEL_NAME + +# Install SONiC host services data files (and any dependencies via 'apt-get -y install -f') +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/sonic-host-services-data_*.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 %} + +# Install SONiC Device Data (and its dependencies via 'apt-get -y install -f') +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/sonic-device-data_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f + +# Install pam-tacplus and nss-tacplus +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/libtac2_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/libpam-tacplus_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/libnss-tacplus_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +# Disable tacplus by default +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=true chroot $FILESYSTEM_ROOT apt-get -q --no-install-suggests --no-install-recommends --force-no install + cat $IMAGE_CONFIGS/kdump/kdump-tools | sudo tee -a $FILESYSTEM_ROOT/etc/default/kdump-tools > /dev/null +fi + +# Install python-swss-common package and all its dependent packages +{% if python_swss_debs.strip() -%} +{% for deb in python_swss_debs.strip().split(' ') -%} +sudo dpkg --root=$FILESYSTEM_ROOT -i {{deb}} || sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +{% endfor %} +{% endif %} + +# Install custom-built monit package and SONiC configuration files +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/monit_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +sudo cp $IMAGE_CONFIGS/monit/monitrc $FILESYSTEM_ROOT/etc/monit/ +sudo chmod 600 $FILESYSTEM_ROOT/etc/monit/monitrc +sudo cp $IMAGE_CONFIGS/monit/conf.d/* $FILESYSTEM_ROOT/etc/monit/conf.d/ +sudo chmod 600 $FILESYSTEM_ROOT/etc/monit/conf.d/* +sudo cp $IMAGE_CONFIGS/monit/process_checker $FILESYSTEM_ROOT/usr/bin/ +sudo chmod 755 $FILESYSTEM_ROOT/usr/bin/process_checker +sudo cp $IMAGE_CONFIGS/monit/container_checker $FILESYSTEM_ROOT/usr/bin/ +sudo chmod 755 $FILESYSTEM_ROOT/usr/bin/container_checker + + +# Install custom-built openssh sshd +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/openssh-server_*.deb + +# Copy crontabs +sudo cp -f $IMAGE_CONFIGS/cron.d/* $FILESYSTEM_ROOT/etc/cron.d/ + +# Copy NTP configuration files and templates +sudo cp $IMAGE_CONFIGS/ntp/ntp-config.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "ntp-config.service" | sudo tee -a $GENERATED_SERVICE_FILE +sudo cp $IMAGE_CONFIGS/ntp/ntp-config.sh $FILESYSTEM_ROOT/usr/bin/ +sudo cp $IMAGE_CONFIGS/ntp/ntp.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ +sudo cp $IMAGE_CONFIGS/ntp/ntp-systemd-wrapper $FILESYSTEM_ROOT/usr/lib/ntp/ +sudo cp $IMAGE_CONFIGS/ntp/ntp.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "ntp.service" | sudo tee -a $GENERATED_SERVICE_FILE + +# Copy warmboot-finalizer files +sudo LANG=C cp $IMAGE_CONFIGS/warmboot-finalizer/finalize-warmboot.sh $FILESYSTEM_ROOT/usr/local/bin/finalize-warmboot.sh +sudo LANG=C cp $IMAGE_CONFIGS/warmboot-finalizer/warmboot-finalizer.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "warmboot-finalizer.service" | sudo tee -a $GENERATED_SERVICE_FILE + +# Copy watchdog-control files +sudo LANG=C cp $IMAGE_CONFIGS/watchdog-control/watchdog-control.sh $FILESYSTEM_ROOT/usr/local/bin/watchdog-control.sh +sudo LANG=C cp $IMAGE_CONFIGS/watchdog-control/watchdog-control.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "watchdog-control.service" | sudo tee -a $GENERATED_SERVICE_FILE + +# Copy rsyslog configuration files and templates +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-config.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-config.sh $FILESYSTEM_ROOT/usr/bin/ +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-container.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog.d/* $FILESYSTEM_ROOT/etc/rsyslog.d/ +echo "rsyslog-config.service" | sudo tee -a $GENERATED_SERVICE_FILE + +# Copy syslog override files +sudo mkdir -p $FILESYSTEM_ROOT/etc/systemd/system/syslog.socket.d +sudo cp $IMAGE_CONFIGS/syslog/override.conf $FILESYSTEM_ROOT/etc/systemd/system/syslog.socket.d/override.conf +sudo cp $IMAGE_CONFIGS/syslog/host_umount.sh $FILESYSTEM_ROOT/usr/bin/ + +# Copy system-health files +sudo LANG=C cp $IMAGE_CONFIGS/system-health/system-health.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "system-health.service" | sudo tee -a $GENERATED_SERVICE_FILE + +# Copy logrotate.d configuration files +sudo cp -f $IMAGE_CONFIGS/logrotate/logrotate.d/* $FILESYSTEM_ROOT/etc/logrotate.d/ + +# Copy systemd-journald configuration files +sudo cp -f $IMAGE_CONFIGS/systemd/journald.conf $FILESYSTEM_ROOT/etc/systemd/ + +# Copy interfaces configuration files and templates +sudo cp $IMAGE_CONFIGS/interfaces/interfaces-config.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +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 CoPP configuration files and templates +sudo cp $IMAGE_CONFIGS/copp/copp-config.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +sudo cp $IMAGE_CONFIGS/copp/copp-config.sh $FILESYSTEM_ROOT/usr/bin/ +sudo cp $IMAGE_CONFIGS/copp/copp_cfg.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ +echo "copp-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 + +# copy core file uploader files +sudo cp $IMAGE_CONFIGS/corefile_uploader/core_uploader.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +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 LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install libffi-dev libssl-dev + +if [[ $CONFIGURED_ARCH == armhf ]]; then + # The azure-storage package depends on the cryptography package. Newer + # versions of cryptography require the rust compiler, the correct version + # for which is not readily available in buster. Hence we pre-install an + # older version here to satisfy the azure-storage dependency. + # Note: This is not a problem for other architectures as pre-built versions + # of cryptography are available for those. This sequence can be removed + # after upgrading to debian bullseye. + sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install cryptography==3.3.1 +fi +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install azure-storage==0.36.0 +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install watchdog==0.10.3 + +{% if include_kubernetes == "y" %} +# Install remote Container mgmt package +# Required even if include_kubernetes != y, as it contains the +# the container wrapper for docker start/stop/wait commands. +# +SONIC_CTRMGMT_WHEEL_NAME=$(basename {{sonic_ctrmgmt_py3_wheel_path}}) +sudo cp {{sonic_ctrmgmt_py3_wheel_path}} $FILESYSTEM_ROOT/$SONIC_CTRMGMT_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $SONIC_CTRMGMT_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SONIC_CTRMGMT_WHEEL_NAME + +# Copy remote container mangement files +# File called from each container upon start/stop to record the state +sudo mkdir -p ${FILESYSTEM_ROOT_USR_SHARE_SONIC_SCRIPTS} +sudo cp ${files_path}/container_startup.py ${FILESYSTEM_ROOT_USR_SHARE_SONIC_SCRIPTS}/ +sudo chmod a+x ${FILESYSTEM_ROOT_USR_SHARE_SONIC_SCRIPTS}/container_startup.py + +# Config file used by container mgmt scripts/service +sudo cp ${files_path}/remote_ctr.config.json ${FILESYSTEM_ROOT_ETC_SONIC}/ + +# Remote container management service files +sudo cp ${files_path}/ctrmgrd.service ${FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM}/ +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable ctrmgrd.service + +# kubelet service is controlled by ctrmgrd daemon. +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl disable kubelet.service +{% else %} +# container script for docker commands, which is required as +# all docker commands are replaced with container commands. +# So just copy that file only. +# +sudo cp ${files_path}/container $FILESYSTEM_ROOT/usr/local/bin/ +{% endif %} + +# Copy the buffer configuration template +sudo cp $BUILD_TEMPLATES/buffers_config.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ + +# Copy the qos configuration template +sudo cp $BUILD_TEMPLATES/qos_config.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ + +# Copy the templates for dynamically buffer calculation +{% if sonic_asic_platform == "mellanox" or sonic_asic_platform == "vs" %} +if [ -f platform/{{ sonic_asic_platform }}/asic_table.j2 ] +then + sudo cp platform/{{ sonic_asic_platform }}/asic_table.j2 $FILESYSTEM_ROOT/usr/share/sonic/templates/asic_table.j2 +fi + +if [ -f platform/{{ sonic_asic_platform }}/peripheral_table.j2 ] +then + sudo cp platform/{{ sonic_asic_platform }}/peripheral_table.j2 $FILESYSTEM_ROOT/usr/share/sonic/templates/peripheral_table.j2 +fi +{% endif %} + +# Copy hostname configuration scripts +sudo cp $IMAGE_CONFIGS/hostname/hostname-config.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "hostname-config.service" | sudo tee -a $GENERATED_SERVICE_FILE +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_USR_LIB_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_USR_LIB_SYSTEMD_SYSTEM/updategraph.service +sudo cp $IMAGE_CONFIGS/updategraph/updategraph $FILESYSTEM_ROOT/usr/bin/ +echo "updategraph.service" | sudo tee -a $GENERATED_SERVICE_FILE +{% if enable_dhcp_graph_service == "y" %} +sudo bash -c "echo enabled=true > $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" +sudo bash -c "echo src=dhcp >> $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" +sudo bash -c "echo dhcp_as_static=true >> $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" +{% else %} +sudo bash -c "echo enabled=false > $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" +{% endif %} + +# 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_USR_LIB_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 config-chassisdb script and service file +j2 files/build_templates/config-chassisdb.service.j2 | sudo tee $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/config-chassisdb.service +sudo cp $IMAGE_CONFIGS/config-chassisdb/config-chassisdb $FILESYSTEM_ROOT/usr/bin/config-chassisdb +echo "config-chassisdb.service" | sudo tee -a $GENERATED_SERVICE_FILE +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable config-chassisdb.service + +# Copy SNMP configuration files +sudo cp $IMAGE_CONFIGS/snmp/snmp.yml $FILESYSTEM_ROOT/etc/sonic/ + +# Copy ASN configuration files +sudo cp $IMAGE_CONFIGS/constants/constants.yml $FILESYSTEM_ROOT/etc/sonic/ + +# Copy sudoers configuration file +sudo cp $IMAGE_CONFIGS/sudoers/sudoers $FILESYSTEM_ROOT/etc/ +sudo cp $IMAGE_CONFIGS/sudoers/sudoers.lecture $FILESYSTEM_ROOT/etc/ + +# Copy pcie-check service files +sudo cp $IMAGE_CONFIGS/pcie-check/pcie-check.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "pcie-check.service" | sudo tee -a $GENERATED_SERVICE_FILE +sudo cp $IMAGE_CONFIGS/pcie-check/pcie-check.sh $FILESYSTEM_ROOT/usr/bin/ + +## Install package without starting service +## ref: https://wiki.debian.org/chroot +sudo tee -a $FILESYSTEM_ROOT/usr/sbin/policy-rc.d > /dev/null < /dev/null < $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ctr_image_names.json" +{% for entry in feature_vs_image_names.split(' ') -%} +{% if entry|length %} +{% set lst = entry.split(':') %} +{% set lst1 = lst[1].split('.') %} + sudo bash -c "echo -n -e \"\x22{{ lst[0] }}\x22 : \x22{{ lst1[0] }}\x22\" >> $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ctr_image_names.json" +{% if not loop.last %} + sudo bash -c "echo \",\" >> $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ctr_image_names.json" +{% else %} + sudo bash -c "echo \"\" >> $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ctr_image_names.json" +{% endif %} +{% endif %} +{% endfor %} +sudo bash -c "echo } >> $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ctr_image_names.json" + +{% for script in installer_start_scripts.split(' ') -%} +sudo cp {{script}} $FILESYSTEM_ROOT/usr/bin/ +{% endfor %} +{% for service in installer_services.split(' ') -%} +if [ -f {{service}} ]; then + sudo cp {{service}} $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM + + {% if "@" in service %} + MULTI_INSTANCE="{{service}}" + SINGLE_INSTANCE=${MULTI_INSTANCE/"@"} + sudo cp $SINGLE_INSTANCE $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM + {% endif %} + + echo "{{service}}" | sudo tee -a $GENERATED_SERVICE_FILE +fi +{% endfor %} +if [ -f iccpd.service ]; then + sudo LANG=C chroot $FILESYSTEM_ROOT systemctl disable iccpd.service +fi +sudo LANG=C chroot $FILESYSTEM_ROOT fuser -km /sys || true +sudo LANG=C chroot $FILESYSTEM_ROOT umount -lf /sys +{% endif %} + +# Copy service scripts (swss, syncd, bgp, teamd, radv) +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 +sudo LANG=C cp $SCRIPTS_DIR/syncd_common.sh $FILESYSTEM_ROOT/usr/local/bin/syncd_common.sh +sudo LANG=C cp $SCRIPTS_DIR/gbsyncd.sh $FILESYSTEM_ROOT/usr/local/bin/gbsyncd.sh +sudo LANG=C cp $SCRIPTS_DIR/bgp.sh $FILESYSTEM_ROOT/usr/local/bin/bgp.sh +sudo LANG=C cp $SCRIPTS_DIR/teamd.sh $FILESYSTEM_ROOT/usr/local/bin/teamd.sh +sudo LANG=C cp $SCRIPTS_DIR/radv.sh $FILESYSTEM_ROOT/usr/local/bin/radv.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_USR_LIB_SYSTEMD_SYSTEM +echo "snmp.timer" | sudo tee -a $GENERATED_SERVICE_FILE + +{% if include_system_telemetry == 'y' %} +sudo cp $BUILD_TEMPLATES/telemetry.timer $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "telemetry.timer" | sudo tee -a $GENERATED_SERVICE_FILE +{% endif %} + +{% if include_mgmt_framework == 'y' %} +sudo cp $BUILD_TEMPLATES/mgmt-framework.timer $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "mgmt-framework.timer" | sudo tee -a $GENERATED_SERVICE_FILE +{% endif %} + +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get purge -y python-dev python3-dev +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get purge -y build-essential libssl-dev swig +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get purge -y libcairo2-dev libdbus-1-dev libgirepository1.0-dev libsystemd-dev pkg-config +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get clean -y +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get autoremove -y + +{% for file in installer_extra_files.split(' ') -%} +{% if file.strip() -%} +{% set src = file.split(':')[0] -%} +{% set dst = file.split(':')[1] -%} +sudo cp {{src}} $FILESYSTEM_ROOT/{{dst}} +{% endif -%} +{% endfor -%} + +{% if sonic_asic_platform == "mellanox" %} +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 + +# Install mlnx-sonic-platform Python 2 package +MLNX_SONIC_PLATFORM_PY2_WHEEL_NAME=$(basename {{mlnx_platform_api_py2_wheel_path}}) +sudo cp {{mlnx_platform_api_py2_wheel_path}} $FILESYSTEM_ROOT/$MLNX_SONIC_PLATFORM_PY2_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install $MLNX_SONIC_PLATFORM_PY2_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$MLNX_SONIC_PLATFORM_PY2_WHEEL_NAME + +# Install mlnx-sonic-platform Python 3 package +MLNX_SONIC_PLATFORM_PY3_WHEEL_NAME=$(basename {{mlnx_platform_api_py3_wheel_path}}) +sudo cp {{mlnx_platform_api_py3_wheel_path}} $FILESYSTEM_ROOT/$MLNX_SONIC_PLATFORM_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $MLNX_SONIC_PLATFORM_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$MLNX_SONIC_PLATFORM_PY3_WHEEL_NAME +{% endif %} + +{%- if SONIC_ROUTING_STACK == "frr" %} +sudo mkdir $FILESYSTEM_ROOT/etc/sonic/frr +sudo touch $FILESYSTEM_ROOT/etc/sonic/frr/frr.conf +sudo touch $FILESYSTEM_ROOT/etc/sonic/frr/vtysh.conf +sudo chown -R $FRR_USER_UID:$FRR_USER_GID $FILESYSTEM_ROOT/etc/sonic/frr +sudo chmod -R 640 $FILESYSTEM_ROOT/etc/sonic/frr/ +sudo chmod 750 $FILESYSTEM_ROOT/etc/sonic/frr +{%- endif %} + +# Mask services which are disabled by default +sudo cp $BUILD_SCRIPTS_DIR/mask_disabled_services.py $FILESYSTEM_ROOT/tmp/ +sudo chmod a+x $FILESYSTEM_ROOT/tmp/mask_disabled_services.py +sudo LANG=C chroot $FILESYSTEM_ROOT /tmp/mask_disabled_services.py +sudo rm -rf $FILESYSTEM_ROOT/tmp/mask_disabled_services.py diff --git a/files/build_templates/swss_vars.j2 b/files/build_templates/swss_vars.j2 new file mode 100644 index 000000000000..a9bd01565c89 --- /dev/null +++ b/files/build_templates/swss_vars.j2 @@ -0,0 +1,6 @@ +{ + "asic_type": "{{ asic_type }}", + "asic_id": "{{ DEVICE_METADATA.localhost.asic_id }}", + "mac": "{{ DEVICE_METADATA.localhost.mac }}", + "synchronous_mode": {% if DEVICE_METADATA.localhost.synchronous_mode == "disable" %}"disable"{% else %}"enable"{% endif %} +} diff --git a/files/build_templates/telemetry.service.j2 b/files/build_templates/telemetry.service.j2 new file mode 100644 index 000000000000..43fa039156d7 --- /dev/null +++ b/files/build_templates/telemetry.service.j2 @@ -0,0 +1,16 @@ +[Unit] +Description=Telemetry container +Requires=database.service +After=database.service swss.service syncd.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 + diff --git a/files/build_templates/telemetry.timer b/files/build_templates/telemetry.timer new file mode 100644 index 000000000000..e08f1c09eac6 --- /dev/null +++ b/files/build_templates/telemetry.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Delays telemetry container until SONiC has started + +[Timer] +OnBootSec=3min 30 sec +Unit=telemetry.service + +[Install] +WantedBy=timers.target diff --git a/files/build_templates/updategraph.service.j2 b/files/build_templates/updategraph.service.j2 new file mode 100644 index 000000000000..0e05cbf147d6 --- /dev/null +++ b/files/build_templates/updategraph.service.j2 @@ -0,0 +1,12 @@ +[Unit] +Description=Update minigraph and set configuration based on minigraph +After=config-setup.service +Requires=config-setup.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/updategraph +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target 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.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 new file mode 100644 index 000000000000..9bd5fded4b8f --- /dev/null +++ b/files/dhcp/graphserviceurl @@ -0,0 +1,14 @@ +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 new file mode 100644 index 000000000000..797a0d24429f --- /dev/null +++ b/files/dhcp/rfc3442-classless-routes @@ -0,0 +1,68 @@ +# set classless routes based on the format specified in RFC3442 +# e.g.: +# new_rfc3442_classless_static_routes='24 192 168 10 192 168 1 1 8 10 10 17 66 41' +# specifies the routes: +# 192.168.10.0/24 via 192.168.1.1 +# 10.0.0.0/8 via 10.10.17.66.41 + +RUN="yes" + + +if [ "$RUN" = "yes" ]; then + if [ -n "$new_rfc3442_classless_static_routes" ]; then + if [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then + + set -- $new_rfc3442_classless_static_routes + + while [ $# -gt 0 ]; do + net_length=$1 + via_arg='' + + case $net_length in + 32|31|30|29|28|27|26|25) + net_address="${2}.${3}.${4}.${5}" + gateway="${6}.${7}.${8}.${9}" + shift 9 + ;; + 24|23|22|21|20|19|18|17) + net_address="${2}.${3}.${4}.0" + gateway="${5}.${6}.${7}.${8}" + shift 8 + ;; + 16|15|14|13|12|11|10|9) + net_address="${2}.${3}.0.0" + gateway="${4}.${5}.${6}.${7}" + shift 7 + ;; + 8|7|6|5|4|3|2|1) + net_address="${2}.0.0.0" + gateway="${3}.${4}.${5}.${6}" + shift 6 + ;; + 0) # default route + net_address="0.0.0.0" + gateway="${2}.${3}.${4}.${5}" + shift 5 + ;; + *) # error + return 1 + ;; + esac + + # take care of link-local routes + if [ "${gateway}" != '0.0.0.0' ]; then + via_arg="via ${gateway}" + fi + + # set route (ip detects host routes automatically) + 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 +fi diff --git a/files/dhcp/sethostname b/files/dhcp/sethostname new file mode 100644 index 000000000000..8cef73239455 --- /dev/null +++ b/files/dhcp/sethostname @@ -0,0 +1,12 @@ +case $reason in + BOUND|RENEW|REBIND|REBOOT) + current_host_name=`hostname -s` + if [ "$current_host_name" != "$new_host_name" ] && [ -n "$new_host_name" ] + then + echo $new_host_name > /etc/hostname + hostname -F /etc/hostname + sed -i "/\s$current_host_name$/d" /etc/hosts + echo "127.0.0.1 $new_host_name" >> /etc/hosts + fi + ;; +esac 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/dhcp/snmpcommunity b/files/dhcp/snmpcommunity new file mode 100644 index 000000000000..63924e01fc5f --- /dev/null +++ b/files/dhcp/snmpcommunity @@ -0,0 +1,11 @@ +case $reason in + BOUND|RENEW|REBIND|REBOOT) + if [ -n "${new_snmp_community}" ]; then + if [ -f /etc/sonic/snmp.yml ]; then + sed -i "s/^snmp_rocommunity:.*/snmp_rocommunity: $new_snmp_community/g" /etc/sonic/snmp.yml + else + echo "snmp_rocommunity: "$new_snmp_community > /etc/sonic/snmp.yml + fi + fi + ;; +esac diff --git a/files/dhcp/vrf b/files/dhcp/vrf new file mode 100644 index 000000000000..b64a57c2b2cd --- /dev/null +++ b/files/dhcp/vrf @@ -0,0 +1,234 @@ +# +# DHCLIENT exit hook for vrf support. +# +# Code ported from https://github.com/CumulusNetworks/vrf under GPLv2 license +# (see https://github.com/CumulusNetworks/vrf/blob/master/debian/copyright). +# + +# Get table_id for device enslaved to a vrf. +vrf_get_table_dev() +{ + local table_id + + # If vrf_slave is not in the output, device is not enslaved. + table_id=$(ip -o -d link show dev ${1} 2>/dev/null |\ + egrep ' vrf_slave table [0-9]*' |\ + sed -e 's/.*vrf_slave table \([0-9]*\) .*/\1/') + + [ -z "${table_id}" ] && return 1 + + echo ${table_id} + + return 0 +} + +# Get table_id for vrf device. +vrf_get_table() +{ + local table_id + + table_id=$(ip -o -d link show dev ${1} 2>/dev/null |\ + egrep ' vrf table [0-9]*' |\ + sed -e 's/.*vrf table \([0-9]*\) .*/\1/') + + [ -z "${table_id}" ] && return 1 + + echo ${table_id} + + return 0 +} + +vrf_exists() +{ + local vrf=${1} + local n + + [ "$vrf" = "default" ] && return 0 + + # ip link show dev type vrf happily returns 0 even though + # is not of type vrf. Hence the wc -l. + n=$(ip -br link show dev ${vrf} type vrf 2>/dev/null | wc -l) + [ ${n} -eq 1 ] && return 0 + + return $? +} + +# Check vrf device contains only alphanumeric characters. +get_vrf_arg() +{ + local vrf + + vrf=$(echo $1 | tr -cd [:alnum:]) + if [ "$vrf" != "$1" ]; then + echo "Invalid VRF" >&2 + return 1 + fi + + echo $vrf +} + +vrf_table() +{ + local table_id + local vrf + + vrf=$(get_vrf_arg ${1}) + [ $? -ne 0 ] && return 1 + + vrf_exists $vrf + if [ $? -eq 0 ]; then + vrf_get_table $vrf + return 0 + fi + + # Maybe this is a device, not a vrf. + table_id=$(vrf_get_table_dev $vrf) + if [ $? -eq 0 ]; then + echo ${table_id} + return 0 + fi + + return 1 +} + +table_id=$(vrf_table ${interface}) + +if [ -n "${table_id}" ]; then + +case "$reason" in + BOUND|RENEW|REBIND|REBOOT) + if [ -z "$old_ip_address" ] || + [ "$old_ip_address" != "$new_ip_address" ] || + [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then + # If we have $new_rfc3442_classless_static_routes then we have to + # ignore $new_routers entirely. + if [ ! "$new_rfc3442_classless_static_routes" ]; then + # Set if_metric if IF_METRIC is set or there's more than one router. + if_metric="$IF_METRIC" + if [ "${new_routers%% *}" != "${new_routers}" ]; then + if_metric=${if_metric:-1} + fi + + for router in $new_routers; do + if [ "$new_subnet_mask" = "255.255.255.255" ]; then + # Set explicit route for p2p connection. + ip -4 route add table ${table_id} ${router} dev $interface >/dev/null 2>&1 + fi + + # Remove old default route should it remain from dhclient-script. + ip -4 route del default via ${router} dev ${interface} \ + ${if_metric:+metric $if_metric} >/dev/null 2>&1 + + # Set default route. + ip -4 route add table ${table_id} default via ${router} dev ${interface} \ + ${if_metric:+metric $if_metric} >/dev/null 2>&1 + + if [ -n "$if_metric" ]; then + if_metric=$((if_metric+1)) + fi + done + else + set -- $new_rfc3442_classless_static_routes + + while [ $# -gt 0 ]; do + net_length=$1 + via_arg='' + + case $net_length in + 32|31|30|29|28|27|26|25) + if [ $# -lt 9 ]; then + return 1 + fi + net_address="${2}.${3}.${4}.${5}" + gateway="${6}.${7}.${8}.${9}" + shift 9 + ;; + 24|23|22|21|20|19|18|17) + if [ $# -lt 8 ]; then + return 1 + fi + net_address="${2}.${3}.${4}.0" + gateway="${5}.${6}.${7}.${8}" + shift 8 + ;; + 16|15|14|13|12|11|10|9) + if [ $# -lt 7 ]; then + return 1 + fi + net_address="${2}.${3}.0.0" + gateway="${4}.${5}.${6}.${7}" + shift 7 + ;; + 8|7|6|5|4|3|2|1) + if [ $# -lt 6 ]; then + return 1 + fi + net_address="${2}.0.0.0" + gateway="${3}.${4}.${5}.${6}" + shift 6 + ;; + 0) # default route + if [ $# -lt 5 ]; then + return 1 + fi + net_address="0.0.0.0" + gateway="${2}.${3}.${4}.${5}" + shift 5 + ;; + *) # error + return 1 + ;; + esac + + # Take care of link-local routes. + if [ "${gateway}" != '0.0.0.0' ]; then + via_arg="via ${gateway}" + fi + + # Set route (ip detects host routes automatically). + ip -4 route add table ${table_id} "${net_address}/${net_length}" \ + ${via_arg} dev "${interface}" >/dev/null 2>&1 + done + fi + fi + + if [ -n "$alias_ip_address" ] && + [ "$new_ip_address" != "$alias_ip_address" ]; then + ip -4 route add table ${table_id} ${alias_ip_address} dev ${interface} >/dev/null 2>&1 + fi + ;; + + EXPIRE|FAIL|RELEASE|STOP) + if [ -n "$alias_ip_address" ]; then + ip -4 route add table ${table_id} ${alias_ip_address} dev ${interface} >/dev/null 2>&1 + fi + + ;; + + TIMEOUT) + # If there is no router recorded in the lease or the 1st router answers pings. + if [ -z "$new_routers" ] || ping -q -c 1 "${new_routers%% *}"; then + # If we have $new_rfc3442_classless_static_routes then we have to + # ignore $new_routers entirely. + if [ ! "$new_rfc3442_classless_static_routes" ]; then + if [ -n "$alias_ip_address" ] && + [ "$new_ip_address" != "$alias_ip_address" ]; then + ip -4 route add table ${table_id} ${alias_ip_address} dev ${interface} >/dev/null 2>&1 + fi + + # Set default route. + for router in $new_routers; do + ip -4 route add table ${table_id} default via ${router} dev ${interface} \ + ${if_metric:+metric $if_metric} >/dev/null 2>&1 + + if [ -n "$if_metric" ]; then + if_metric=$((if_metric+1)) + fi + done + fi + fi + + ;; +esac + +fi diff --git a/files/docker/README b/files/docker/README new file mode 100644 index 000000000000..d6a1ef008c2a --- /dev/null +++ b/files/docker/README @@ -0,0 +1,2 @@ +docker file is extracted from docker-ce 17.03.0~ce-0~debian-stretch to +enable 'service docker start' in the build chroot env. diff --git a/files/docker/docker b/files/docker/docker new file mode 100755 index 000000000000..4f9d38dda5c6 --- /dev/null +++ b/files/docker/docker @@ -0,0 +1,152 @@ +#!/bin/sh +set -e + +### BEGIN INIT INFO +# Provides: docker +# Required-Start: $syslog $remote_fs +# Required-Stop: $syslog $remote_fs +# Should-Start: cgroupfs-mount cgroup-lite +# Should-Stop: cgroupfs-mount cgroup-lite +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Create lightweight, portable, self-sufficient containers. +# Description: +# Docker is an open-source project to easily create lightweight, portable, +# self-sufficient containers from any application. The same container that a +# developer builds and tests on a laptop can run at scale, in production, on +# VMs, bare metal, OpenStack clusters, public clouds and more. +### END INIT INFO + +export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin + +BASE=docker + +# modify these in /etc/default/$BASE (/etc/default/docker) +DOCKERD=/usr/bin/dockerd +# This is the pid file managed by docker itself +DOCKER_PIDFILE=/var/run/$BASE.pid +# This is the pid file created/managed by start-stop-daemon +DOCKER_SSD_PIDFILE=/var/run/$BASE-ssd.pid +DOCKER_LOGFILE=/var/log/$BASE.log +DOCKER_OPTS= +DOCKER_DESC="Docker" + +# Get lsb functions +. /lib/lsb/init-functions + +if [ -f /etc/default/$BASE ]; then + . /etc/default/$BASE +fi + +# Check docker is present +if [ ! -x $DOCKERD ]; then + log_failure_msg "$DOCKERD not present or not executable" + exit 1 +fi + +check_init() { + # see also init_is_upstart in /lib/lsb/init-functions (which isn't available in Ubuntu 12.04, or we'd use it directly) + if [ -x /sbin/initctl ] && /sbin/initctl version 2>/dev/null | grep -q upstart; then + log_failure_msg "$DOCKER_DESC is managed via upstart, try using service $BASE $1" + exit 1 + fi +} + +fail_unless_root() { + if [ "$(id -u)" != '0' ]; then + log_failure_msg "$DOCKER_DESC must be run as root" + exit 1 + fi +} + +cgroupfs_mount() { + # see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount + if grep -v '^#' /etc/fstab | grep -q cgroup \ + || [ ! -e /proc/cgroups ] \ + || [ ! -d /sys/fs/cgroup ]; then + return + fi + if ! mountpoint -q /sys/fs/cgroup; then + mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup + fi + ( + cd /sys/fs/cgroup + for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do + mkdir -p $sys + if ! mountpoint -q $sys; then + if ! mount -n -t cgroup -o $sys cgroup $sys; then + rmdir $sys || true + fi + fi + done + ) +} + +case "$1" in + start) + check_init + + fail_unless_root + + cgroupfs_mount + + touch "$DOCKER_LOGFILE" + chgrp docker "$DOCKER_LOGFILE" + + ulimit -n 1048576 + + # Having non-zero limits causes performance problems due to accounting overhead + # in the kernel. We recommend using cgroups to do container-local accounting. + if [ "$BASH" ]; then + ulimit -u unlimited + else + ulimit -p unlimited + fi + + log_begin_msg "Starting $DOCKER_DESC: $BASE" + start-stop-daemon --start --background \ + --no-close \ + --exec "$DOCKERD" \ + --pidfile "$DOCKER_SSD_PIDFILE" \ + --make-pidfile \ + -- \ + -p "$DOCKER_PIDFILE" \ + $DOCKER_OPTS \ + >> "$DOCKER_LOGFILE" 2>&1 + log_end_msg $? + ;; + + stop) + check_init + fail_unless_root + log_begin_msg "Stopping $DOCKER_DESC: $BASE" + start-stop-daemon --stop --pidfile "$DOCKER_SSD_PIDFILE" --retry 10 + log_end_msg $? + ;; + + restart) + check_init + fail_unless_root + docker_pid=`cat "$DOCKER_SSD_PIDFILE" 2>/dev/null` + [ -n "$docker_pid" ] \ + && ps -p $docker_pid > /dev/null 2>&1 \ + && $0 stop + $0 start + ;; + + force-reload) + check_init + fail_unless_root + $0 restart + ;; + + status) + check_init + status_of_proc -p "$DOCKER_SSD_PIDFILE" "$DOCKERD" "$DOCKER_DESC" + ;; + + *) + echo "Usage: service docker {start|stop|restart|status}" + exit 1 + ;; +esac diff --git a/files/docker/docker.service.conf b/files/docker/docker.service.conf index 2d6d3cfaa6fb..7debd85a50ac 100644 --- a/files/docker/docker.service.conf +++ b/files/docker/docker.service.conf @@ -1,3 +1,3 @@ [Service] ExecStart= -ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=aufs +ExecStart=/usr/bin/dockerd -H unix:// --storage-driver=overlay2 --bip=240.127.1.1/24 --iptables=false --ipv6=true --fixed-cidr-v6=fd00::/80 diff --git a/files/image_config/apt/sonic-dev.gpg.key b/files/image_config/apt/sonic-dev.gpg.key new file mode 100644 index 000000000000..fb9a37901bc7 --- /dev/null +++ b/files/image_config/apt/sonic-dev.gpg.key @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQENBFQ1bTIBCAC7oGfkv/ck0XsLuG8cdcSB2ISqxFAcBvH9BitEtxmpW2uhykKk +xY4rVD/4Uys1s3PF1/64QfPR+hYcewueOwz0ZAcLyFXXk4McICXaPq3NrLiWYKKX +UZLnrPzcrGZoW/kHDDp4OmBiDmT1PGvZlpuimwkMCusUzIr7Cbbp2dIy8MERL5tA +LcgLu3KL6clJ+aTW2jgepI1D7sTepOeGd7eRSb5njKg2M7k/93v/7MipZxiVtyXH +B74YiK6jSbst5JpuYsLa/Dqryvx7Xq3n53oif892pv3euTduo1fYw8Hgh/OOYdeT +c9WCj03KA1jCSFURjdrug0kR8BPlfjqtRLXFABEBAAG0JE1TIE9wZW4gVGVjaCA8 +aW50ZXJvcEBtaWNyb3NvZnQuY29tPokBOAQTAQIAIgUCVDVtMgIbAwYLCQgHAwIG +FQgCCQoLBBYCAwECHgECF4AACgkQsCxG30F6CJO1uAf/cmL68bM8YgF/61hkaY56 +LqrppUTJH/w4fKq47Pf6KfgSLvxfNU6soi2KHYRjIvTRx3tV4vUM5n2plaQg2s8V +/Epg4FeIRTk75YwiHAzLhLnp5cdUaTvC4j4mwxoB6j9Ty+fXJwQ0MvpDhIZb9vM4 +GXw/fEQHCT4f3gx4nReeqE+FB2wVHleX9+Lpodu98JyJTKJRBRHYLqy6S+/lyp2W +aBlsI1LOqBcx1uRK24U7duIpbYwIyrx0cafSruqR2GjVdu+imkhHyUn52VbzYhq1 +af0rqYiZ1VOamVOG0By8+hVyNa1MLc1K2uWGs0o5fDe9F5/swbvLHVXI+M50Vs+m +J7kBDQRUNW0yAQgAu7DkTVj0ZQC4F7bFivAwrdby8gCakTXOl1kcK622hjRJ8nam +aZeW+eADfLRsTmdUmXgZu1YWS5Gn2ZVngC8SGPUBT071+oRETCz4uNB7IimB9QfP +++orI6o2vmnVVsq5wWCbEdNU+TCVv1zjrYev5lwckkKpjHt6o8MNoX2DFuQymSyR +eZKaqhdKmcji4Ke7OIYqwgPjch3wxzE1b5gNOR/iwxWyjjOffZPLr/VhIfIJRs86 +dSXrwjHtEh810SKDLghHM0VAdY34nyC5ZZ61yhts5HtQDFK+9mNpH1mkc4gDBlgG +266pVvknumK6lPNm/osF/cpjWmEw24ypcQIvOQARAQABiQEfBBgBAgAJBQJUNW0y +AhsMAAoJELAsRt9BegiTMBUH/0sZ6gZy7mCTSAYT+NSXLFtGC2zNUVL80SWvfgYm +k9XPVI22MrefZfQ6M01RylyxtWXjRM8UoN8SDKWPpXumzJf831f/7om5zwutaG7b +tjDPYqRKJSbAIFZu2mN+uLrNQ2SV6XK7FoV0dtcrEX9S7RICb6i19D+70+Oh/qgU +R04H1jqS29XBzqAlIzdBoA+sYAwbOIJsSL3YyNQcUv3B5+5yR/bo/L8pnUJt6iuL +nWW+mi7r8gWPHDSrcdYq1TmmlOM7CwZPgWRZzkQPSeZz52Tt7IP47eyGJ09U4PIf +FtMH1ElL2UgHoA/F9Q88e7LkztaTqE59uXWbIYyuSMJVvRU= +=sb3d +-----END PGP PUBLIC KEY BLOCK----- diff --git a/files/image_config/apt/sources.list b/files/image_config/apt/sources.list new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/files/image_config/apt/sources.list.d/amd64/debian_archive_trafficmanager_net_debian.list b/files/image_config/apt/sources.list.d/amd64/debian_archive_trafficmanager_net_debian.list new file mode 100644 index 000000000000..d35c618112bb --- /dev/null +++ b/files/image_config/apt/sources.list.d/amd64/debian_archive_trafficmanager_net_debian.list @@ -0,0 +1,3 @@ +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ buster main contrib non-free +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ buster/updates main contrib non-free +deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ buster-backports main contrib non-free diff --git a/files/image_config/apt/sources.list.d/arm64/debian_mirror_arm64.list b/files/image_config/apt/sources.list.d/arm64/debian_mirror_arm64.list new file mode 100644 index 000000000000..9e7dec92d39e --- /dev/null +++ b/files/image_config/apt/sources.list.d/arm64/debian_mirror_arm64.list @@ -0,0 +1,9 @@ +deb [arch=arm64] http://deb.debian.org/debian buster main contrib non-free +deb-src [arch=arm64] http://deb.debian.org/debian buster main contrib non-free +deb [arch=arm64] http://deb.debian.org/debian buster-updates main contrib non-free +deb-src [arch=arm64] http://deb.debian.org/debian buster-updates main contrib non-free +deb [arch=arm64] http://security.debian.org buster/updates main contrib non-free +deb-src [arch=arm64] http://security.debian.org buster/updates main contrib non-free +deb [arch=arm64] https://download.docker.com/linux/debian buster stable +deb [arch=arm64] http://ftp.debian.org/debian buster-backports main + diff --git a/files/image_config/apt/sources.list.d/armhf/debian_mirror_armhf.list b/files/image_config/apt/sources.list.d/armhf/debian_mirror_armhf.list new file mode 100644 index 000000000000..a7b831ef301c --- /dev/null +++ b/files/image_config/apt/sources.list.d/armhf/debian_mirror_armhf.list @@ -0,0 +1,9 @@ +deb [arch=armhf] http://deb.debian.org/debian buster main contrib non-free +deb-src [arch=armhf] http://deb.debian.org/debian buster main contrib non-free +deb [arch=armhf] http://deb.debian.org/debian buster-updates main contrib non-free +deb-src [arch=armhf] http://deb.debian.org/debian buster-updates main contrib non-free +deb [arch=armhf] http://security.debian.org buster/updates main contrib non-free +deb-src [arch=armhf] http://security.debian.org buster/updates main contrib non-free +deb [arch=armhf] https://download.docker.com/linux/debian buster stable +deb [arch=armhf] http://ftp.debian.org/debian buster-backports main + diff --git a/files/image_config/bash/bash.bashrc b/files/image_config/bash/bash.bashrc new file mode 100644 index 000000000000..0f19263ae04a --- /dev/null +++ b/files/image_config/bash/bash.bashrc @@ -0,0 +1,75 @@ +# System-wide .bashrc file for interactive bash(1) shells. + +# To enable the settings / commands in this file for login shells as well, +# this file has to be sourced in /etc/profile. + +# If not running interactively, don't do anything +[ -z "$PS1" ] && return + +# check the window size after each command and, if necessary, +# update the values of LINES and COLUMNS. +shopt -s checkwinsize + +# set variable identifying the chroot you work in (used in the prompt below) +if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then + debian_chroot=$(cat /etc/debian_chroot) +fi + +# set a fancy prompt (non-color, overwrite the one in /etc/profile) +PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' + +# Commented out, don't overwrite xterm -T "title" -n "icontitle" by default. +# If this is an xterm set the title to user@host:dir +#case "$TERM" in +#xterm*|rxvt*) +# PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"' +# ;; +#*) +# ;; +#esac + +# enable bash completion in interactive shells +if ! shopt -oq posix; then + if [ -f /usr/share/bash-completion/bash_completion ]; then + . /usr/share/bash-completion/bash_completion + elif [ -f /etc/bash_completion ]; then + . /etc/bash_completion + fi +fi + +# if the command-not-found package is installed, use it +if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then + function command_not_found_handle { + # check because c-n-f could've been removed in the meantime + if [ -x /usr/lib/command-not-found ]; then + /usr/lib/command-not-found -- "$1" + return $? + elif [ -x /usr/share/command-not-found/command-not-found ]; then + /usr/share/command-not-found/command-not-found -- "$1" + return $? + else + printf "%s: command not found\n" "$1" >&2 + return 127 + fi + } +fi + +# Automatically log out console ttyS* sessions after 15 minutes of inactivity +tty | grep ttyS >/dev/null && TMOUT=900 + +# if SSH_TARGET_CONSOLE_LINE was set, attach to console line interactive cli directly +if [ -n "$SSH_TARGET_CONSOLE_LINE" ]; then + if [ $SSH_TARGET_CONSOLE_LINE -eq $SSH_TARGET_CONSOLE_LINE 2>/dev/null ]; then + # enter the interactive cli + connect line $SSH_TARGET_CONSOLE_LINE + + # test exit code, 1 means the console switch feature not enabled + if [ $? -ne 1 ]; then + # exit after console session ended + exit + fi + else + # exit directly when target console line variable is invalid + exit + fi +fi diff --git a/files/image_config/config-chassisdb/config-chassisdb b/files/image_config/config-chassisdb/config-chassisdb new file mode 100755 index 000000000000..3bdcf0a0fbe2 --- /dev/null +++ b/files/image_config/config-chassisdb/config-chassisdb @@ -0,0 +1,59 @@ +#!/bin/bash +########################################################################### +# Copyright 2020 Arista. The term "Arista" refers to Arista 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 chassis_db configuration # +# # +# This script is used to add chassis_db address in local hosts and # +# indicate to start database-chassis service. It should be excuted before # +# database-chassis.service started. # +# # +########################################################################### + +config_chassis_db() { + startdb_file="/etc/sonic/chassisdb.conf" + [ ! -e $startdb_file ] || rm $startdb_file + platform=$(sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + # database-chassis services will start when $chassis_config file exists + chassis_config="/usr/share/sonic/device/$platform/chassisdb.conf" + if [ ! -e $chassis_config ]; then + echo "no chassisdb.conf found, bypass config-chassisdb service" + exit 0 + fi + start_chassis_db=0 + chassis_db_address="" + source $chassis_config + if [[ "$start_chassis_db" == "1" ]]; then + cp $chassis_config $startdb_file + echo "start chassisdb" + fi + if [[ "$start_chassis_db" == "1" ]] || [[ -n "$chassis_db_address" ]]; then + if [ -z "$chassis_db_address" ]; then + echo "no user configured chassisdb address" + else + grep redis_chassis /etc/hosts + if [ $? -ne 0 ]; then + echo "$chassis_db_address redis_chassis.server" >> /etc/hosts + echo "update chassis db address to $chassis_db_address" + fi + fi + fi +} + +config_chassis_db + +exit 0 diff --git a/files/image_config/config-setup/config-setup b/files/image_config/config-setup/config-setup new file mode 100755 index 000000000000..9bb7b33b6be6 --- /dev/null +++ b/files/image_config/config-setup/config-setup @@ -0,0 +1,424 @@ +#!/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 +INIT_CFG_JSON=/etc/sonic/init_cfg.json +CONFIG_DB_JSON=/etc/sonic/config_db.json +CONFIG_DB_PATH=/etc/sonic/ +CONFIG_DB_PREFIX=config_db +CONFIG_DB_SUFFIX=.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 + +TACACS_JSON_BACKUP=tacacs.json + +# 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..." + config load_minigraph -y -n + if [ -r /etc/sonic/old_config/${TACACS_JSON_BACKUP} ]; then + sonic-cfggen -j /etc/sonic/old_config/${TACACS_JSON_BACKUP} --write-to-db + else + echo "Missing tacacs json to restore tacacs credentials" + fi + config save -y +} + +# Reload exisitng config db file on disk +# Usage: reload_configdb +reload_configdb() +{ + CONFIG_FILE=${1} + + echo "Reloading existing config db..." + config reload ${CONFIG_FILE} -y -n +} +# 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 +} + +# 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=${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} + reload_configdb ${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} + reload_configdb ${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 +} + +# Get the list of config db for both +# single and multi-npu platforms +get_config_db_file_list() +{ + config_db_file_list=${CONFIG_DB_PREFIX}${CONFIG_DB_SUFFIX} + asic_num=0 + while [[ ($asic_num -lt $NUM_ASIC) && ($NUM_ASIC -gt 1) ]]; do + config_db_file_list+=' '${CONFIG_DB_PREFIX}$asic_num${CONFIG_DB_SUFFIX} + ((asic_num = asic_num + 1)) + done + + echo $config_db_file_list +} +# Check if all needed config db are prsesnt for both +# single and multi-npu platforms +check_all_config_db_present() +{ + if [[ ! -r ${CONFIG_DB_JSON} ]]; then + return 1 + fi + asic_num=0 + while [[ ($asic_num -lt $NUM_ASIC) && ($NUM_ASIC -gt 1) ]]; do + if [[ ! -r ${CONFIG_DB_PATH}${CONFIG_DB_PREFIX}$asic_num${CONFIG_DB_SUFFIX} ]]; then + return 1 + fi + ((asic_num = asic_num + 1)) + done + + return 0 +} + +# 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 frr telemetry" + + # Migrate all configuration files from old to new + copy_config_files_and_directories $copy_list + + # Migrate all config_db from old to new + copy_config_files_and_directories $(get_config_db_file_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 check_all_config_db_present; then + echo "Use config_db.json from old system..." + reload_configdb + # Disable updategraph + disable_updategraph + elif [ -r ${MINGRAPH_FILE} ]; then + echo "Use minigraph.xml from old system..." + reload_minigraph + # 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 + + # For multi-npu platfrom we don't support config initlaiztion. Assumption + # is there should be existing minigraph or config_db from previous image + # file system to trigger. pending_config_initialization will remain set + # for multi-npu platforms if we reach this case. + if [[ ($NUM_ASIC -gt 1) ]]; then + return 0 + 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 +} + +# read SONiC immutable variables +[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment + +### Execution starts here ### +PLATFORM=${PLATFORM:-`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`} +# Parse the device specific asic conf file, if it exists +ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf +if [[ -f "$ASIC_CONF" ]]; then + source $ASIC_CONF +fi + + +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/constants/constants.yml b/files/image_config/constants/constants.yml new file mode 100644 index 000000000000..86179aee430e --- /dev/null +++ b/files/image_config/constants/constants.yml @@ -0,0 +1,56 @@ +constants: + deployment_id_asn_map: + "1" : 65432 + "2" : 65433 + bgp: + traffic_shift_community: 12345:12345 + families: + - ipv4 + - ipv6 + use_deployment_id: false + use_neighbors_meta: false + graceful_restart: + enabled: true + restart_time: 240 + multipath_relax: + enabled: true + maximum_paths: + enabled: true + ipv4: 64 + ipv6: 64 + allow_list: + enabled: true + default_action: "permit" # or "deny" + drop_community: 5060:12345 # value of the community to identify a prefix to drop. Make sense only with allow_list_default_action equal to 'permit' + default_pl_rules: + v4: + - "deny 0.0.0.0/0 le 17" + - "permit 127.0.0.1/32" + v6: + - "deny 0::/0 le 59" + - "deny 0::/0 ge 65" + bbr: + enabled: true + default_state: "disabled" + peers: + general: # peer_type + db_table: "BGP_NEIGHBOR" + template_dir: "general" + bbr: + PEER_V4: + - ipv4 + PEER_V6: + - ipv6 + internal: # peer_type + db_table: "BGP_INTERNAL_NEIGHBOR" + template_dir: "internal" + monitors: # peer_type + enabled: true + db_table: "BGP_MONITORS" + peer_group: "BGPMON" + template_dir: "monitors" + dynamic: # peer_type + enabled: true + db_table: "BGP_PEER_RANGE" + peer_group: "BGP_SPEAKER" + template_dir: "dynamic" diff --git a/files/image_config/copp/copp-config.service b/files/image_config/copp/copp-config.service new file mode 100755 index 000000000000..8eed2353eddf --- /dev/null +++ b/files/image_config/copp/copp-config.service @@ -0,0 +1,11 @@ +[Unit] +Description=Update CoPP configuration +Requires=updategraph.service +After=updategraph.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/copp-config.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/copp/copp-config.sh b/files/image_config/copp/copp-config.sh new file mode 100755 index 000000000000..0660528a54da --- /dev/null +++ b/files/image_config/copp/copp-config.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +sonic-cfggen -d -t /usr/share/sonic/templates/copp_cfg.j2 > /etc/sonic/copp_cfg.json diff --git a/files/image_config/copp/copp_cfg.j2 b/files/image_config/copp/copp_cfg.j2 new file mode 100755 index 000000000000..61f051f43de8 --- /dev/null +++ b/files/image_config/copp/copp_cfg.j2 @@ -0,0 +1,105 @@ +{ + "COPP_GROUP": { + "default": { + "queue": "0", + "meter_type":"packets", + "mode":"sr_tcm", + "cir":"600", + "cbs":"600", + "red_action":"drop" + }, + "queue4_group1": { + "trap_action":"trap", + "trap_priority":"4", + "queue": "4" + }, + "queue4_group2": { + "trap_action":"copy", + "trap_priority":"4", + "queue": "4", + "meter_type":"packets", + "mode":"sr_tcm", + "cir":"600", + "cbs":"600", + "red_action":"drop" + }, + "queue4_group3": { + "trap_action":"trap", + "trap_priority":"4", + "queue": "4" + }, + "queue1_group1": { + "trap_action":"trap", + "trap_priority":"1", + "queue": "1", + "meter_type":"packets", + "mode":"sr_tcm", + "cir":"6000", + "cbs":"6000", + "red_action":"drop" + }, + "queue1_group2": { + "trap_action":"trap", + "trap_priority":"1", + "queue": "1", + "meter_type":"packets", + "mode":"sr_tcm", + "cir":"600", + "cbs":"600", + "red_action":"drop" + }, + "queue2_group1": { + "cbs": "1000", + "cir": "1000", + "genetlink_mcgrp_name": "packets", + "genetlink_name": "psample", + "meter_type": "packets", + "mode": "sr_tcm", + "queue": "2", + "red_action": "drop", + "trap_action": "trap", + "trap_priority": "1" + + } + }, + "COPP_TRAP": { + "bgp": { + "trap_ids": "bgp,bgpv6", + "trap_group": "queue4_group1" + }, + "lacp": { + "trap_ids": "lacp", + "trap_group": "queue4_group1" + }, + "arp": { + "trap_ids": "arp_req,arp_resp,neigh_discovery", + "trap_group": "queue4_group2" + }, + "lldp": { + "trap_ids": "lldp", + "trap_group": "queue4_group3" + }, +{% if not (DEVICE_METADATA is defined and DEVICE_METADATA['localhost'] is defined and DEVICE_METADATA['localhost']['type'] is defined and DEVICE_METADATA['localhost']['type'] != "ToRRouter") %} + "dhcp": { + "trap_ids": "dhcp,dhcpv6", + "trap_group": "queue4_group3" + }, +{% endif %} + "udld": { + "trap_ids": "udld", + "trap_group": "queue4_group3" + }, + "ip2me": { + "trap_ids": "ip2me", + "trap_group": "queue1_group1" + }, + "nat": { + "trap_ids": "src_nat_miss,dest_nat_miss", + "trap_group": "queue1_group2" + }, + "sflow": { + "trap_group": "queue2_group1", + "trap_ids": "sample_packet" + } + } +} diff --git a/files/image_config/corefile_uploader/core_analyzer.rc.json b/files/image_config/corefile_uploader/core_analyzer.rc.json new file mode 100644 index 000000000000..3ffa33fd1e1d --- /dev/null +++ b/files/image_config/corefile_uploader/core_analyzer.rc.json @@ -0,0 +1,17 @@ +{ + "local_work": { + "core_upload": "/tmp/core_upload/" + }, + "azure_sonic_core_storage": { + "account_name": "corefilecollection", + "account_key": "", + "share_name": "corefiles-root" + }, + "metadata_files_in_archive": { + "version": "/etc/sonic/sonic_version.yml", + "core_info": "core_info.json" + }, + "env": { + "https_proxy": "" + } +} diff --git a/files/image_config/corefile_uploader/core_uploader.py b/files/image_config/corefile_uploader/core_uploader.py new file mode 100755 index 000000000000..aba78618307c --- /dev/null +++ b/files/image_config/corefile_uploader/core_uploader.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python3 + +import json +import os +import socket +import tarfile +import time + +import yaml +from azure.storage.file import FileService +from sonic_py_common.logger import Logger +from watchdog.observers import Observer +from watchdog.events import FileSystemEventHandler + +SYSLOG_IDENTIFIER = os.path.basename(__file__) + +cfg = "" + +CORE_FILE_PATH = "/var/core/" +RC_FILE = "/etc/sonic/core_analyzer.rc.json" +INIT_CWD = "/tmp" + +hostname = "" +sonicversion = "" +asicname = "" +acctname = "" +acctkey = "" +sharename = "" +cwd = [] + +HOURS_4 = (4 * 60 * 60) +PAUSE_ON_FAIL = (60 * 60) +WAIT_FILE_WRITE1 = (10 * 60) +WAIT_FILE_WRITE2 = (5 * 60) +POLL_SLEEP = (60 * 60) +MAX_RETRIES = 5 +UPLOAD_PREFIX = "UPLOADED_" + +# Global logger instance +logger = Logger(SYSLOG_IDENTIFIER) +logger.set_min_log_priority_info() + + +def make_new_dir(p): + os.system("rm -rf " + p) + os.system("mkdir -p " + p) + + +def parse_a_json(data, prefix, val): + for i in data: + if type(data[i]) == dict: + parse_a_json(data[i], prefix + (i,), val) + else: + val[prefix + (i,)] = data[i] + + +class config: + parsed_data = {} + cfg_data = {} + + def __init__(self): + while not os.path.exists(RC_FILE): + # Wait here until service restart + logger.log_error("Unable to retrieve Azure storage credentials") + time.sleep(HOURS_4) + + with open(RC_FILE, 'r') as f: + self.parsed_data = json.load(f) + parse_a_json(self.parsed_data, (), self.cfg_data) + + def get_data(self, k): + return self.cfg_data[k] if k in self.cfg_data else "" + + def get_dict(self): + return self.parsed_data + + def get_core_info(self, corepath, devicename): + info = {} + info["corefname"] = os.path.basename(corepath) + info["tstamp"] = str(os.stat(corepath).st_ctime) + info["devicename"] = devicename + + lpath = self.get_data(("metadata_files_in_archive", "core_info")) + f = open(lpath, "w+") + f.write(json.dumps(info, indent=4)) + f.close() + + return lpath + + +class Watcher: + + def __init__(self): + self.observer = Observer() + + def run(self): + event_handler = Handler() + self.observer.schedule(event_handler, CORE_FILE_PATH) + self.observer.start() + try: + while True: + time.sleep(POLL_SLEEP) + except: + self.observer.stop() + logger.log_error("Error in watcher") + + self.observer.join() + + +def set_env(lst): + for k in lst: + if lst[k]: + os.environ[k] = lst[k] + logger.log_debug("set env {} = {}".format(k, lst[k])) + + +class Handler(FileSystemEventHandler): + + @staticmethod + def init(): + global hostname, sonicversion, asicname, acctname, acctkey, sharename + global cwd, cfg + + cfg = config() + + set_env(cfg.get_dict()["env"]) + + hostname = socket.gethostname() + if not hostname: + raise Exception("Failed to read hostname") + + acctname = cfg.get_data(("azure_sonic_core_storage", "account_name")) + acctkey = cfg.get_data(("azure_sonic_core_storage", "account_key")) + sharename = cfg.get_data(("azure_sonic_core_storage", "share_name")) + + if not acctname or not acctkey or not sharename: + while True: + # Wait here until service restart + logger.log_error("Unable to retrieve Azure storage credentials") + time.sleep(HOURS_4) + + with open("/etc/sonic/sonic_version.yml", 'r') as stream: + l = yaml.safe_load(stream) + sonicversion = l['build_version'] + asicname = l['asic_type'] + + if not sonicversion: + raise Exception("Failed to read build_version from /etc/sonic/sonic_version.yml") + + if not asicname: + raise Exception("Failed to read asic_type from /etc/sonic/sonic_version.yml") + + cwd = cfg.get_data(("local_work", "core_upload")).split("/") + if not len(cwd) > 2: + raise Exception("Invalid path for core_upload. Expect a min of two elements in path") + + os.chdir(INIT_CWD) + + @staticmethod + def on_any_event(event): + if event.is_directory: + return None + + elif event.event_type == 'created': + # Take any action here when a file is first created. + logger.log_debug("Received create event - " + event.src_path) + Handler.wait_for_file_write_complete(event.src_path) + Handler.handle_file(event.src_path) + + @staticmethod + def wait_for_file_write_complete(path): + mtime = 0 + + # Sleep for ample time enough for file dump to complete. + time.sleep(WAIT_FILE_WRITE1) + + # Give another chance & poll until mtime stabilizes + while mtime != os.stat(path).st_mtime: + mtime = os.stat(path).st_mtime + time.sleep(10) + + # A safety pause for double confirmation + time.sleep(WAIT_FILE_WRITE2) + if mtime != os.stat(path).st_mtime: + raise Exception("Dump file creation is too slow: " + path) + # Give up as something is terribly wrong with this file. + + logger.log_debug("File write complete - " + path) + + @staticmethod + def handle_file(path): + lpath = "/".join(cwd) + make_new_dir(lpath) + os.chdir(lpath) + + # Create a new archive with core & more. + metafiles = cfg.get_dict()["metadata_files_in_archive"] + + fname = os.path.basename(path) + tarf_name = fname + ".tar.gz" + + cfg.get_core_info(path, hostname) + + tar = tarfile.open(tarf_name, "w:gz") + for e in metafiles: + tar.add(metafiles[e]) + tar.add(path) + tar.close() + logger.log_debug("Tar file for upload created: " + tarf_name) + + Handler.upload_file(tarf_name, tarf_name, path) + + logger.log_debug("File uploaded - " + path) + os.chdir(INIT_CWD) + + @staticmethod + def upload_file(fname, fpath, coref): + daemonname = fname.split(".")[0] + i = 0 + + while True: + try: + svc = FileService(account_name=acctname, account_key=acctkey) + + l = [sonicversion, asicname, daemonname, hostname] + e = [] + while len(e) != len(l): + e.append(l[len(e)]) + svc.create_directory(sharename, "/".join(e)) + + logger.log_debug("Remote dir created: " + "/".join(e)) + + svc.create_file_from_path(sharename, "/".join(l), fname, fpath) + logger.log_debug("Remote file created: name{} path{}".format(fname, fpath)) + newcoref = os.path.dirname(coref) + "/" + UPLOAD_PREFIX + os.path.basename(coref) + os.rename(coref, newcoref) + break + + except Exception as ex: + logger.log_error("core uploader failed: Failed during upload (" + + coref + ") err: (" + str(ex) + ") retry:" + str(i)) + if not os.path.exists(fpath): + break + i += 1 + time.sleep(PAUSE_ON_FAIL) + + @staticmethod + def scan(): + for e in os.listdir(CORE_FILE_PATH): + fl = CORE_FILE_PATH + e + if os.path.isfile(fl) and not e.startswith(UPLOAD_PREFIX): + Handler.handle_file(fl) + + +if __name__ == '__main__': + try: + Handler.init() + w = Watcher() + Handler.scan() + w.run() + except Exception as e: + logger.log_err("core uploader failed: " + str(e) + " Exiting ...") diff --git a/files/image_config/corefile_uploader/core_uploader.service b/files/image_config/corefile_uploader/core_uploader.service new file mode 100644 index 000000000000..09ac1bd5191f --- /dev/null +++ b/files/image_config/corefile_uploader/core_uploader.service @@ -0,0 +1,13 @@ +[Unit] +Description=Host core file uploader daemon +Requires=syslog.service +After=syslog.service + +[Service] +Type=simple +ExecStart=/usr/bin/core_uploader.py +StandardOutput=null +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/cron.d/core_cleanup b/files/image_config/cron.d/core_cleanup new file mode 100644 index 000000000000..8db064ea57d6 --- /dev/null +++ b/files/image_config/cron.d/core_cleanup @@ -0,0 +1,3 @@ +# Attempts to clean up core files every 2 hours +0 */2 * * * root /usr/bin/core_cleanup.py > /dev/null 2>&1 + diff --git a/files/image_config/cron.d/logrotate b/files/image_config/cron.d/logrotate new file mode 100644 index 000000000000..173a2abe2bd2 --- /dev/null +++ b/files/image_config/cron.d/logrotate @@ -0,0 +1,3 @@ +# Attempt to rotate system logs once every 10 minutes. +# First kill any logrotate process(es) if they are still running, as they're most likely hung +*/10 * * * * root /usr/bin/pkill -9 logrotate > /dev/null 2>&1; /usr/sbin/logrotate /etc/logrotate.conf > /dev/null 2>&1 diff --git a/files/image_config/ebtables/ebtables.filter.cfg b/files/image_config/ebtables/ebtables.filter.cfg new file mode 100644 index 000000000000..7a2dc5c8b6ec --- /dev/null +++ b/files/image_config/ebtables/ebtables.filter.cfg @@ -0,0 +1,11 @@ +# SONiC ebtables filter table configuration +# Generated using ebtables-save + +*filter +:INPUT ACCEPT +:FORWARD ACCEPT +:OUTPUT ACCEPT +-A FORWARD -d BGA -j DROP +-A FORWARD -p ARP -j DROP +-A FORWARD -p 802_1Q --vlan-encap ARP -j DROP + diff --git a/files/image_config/environment/environment b/files/image_config/environment/environment new file mode 100644 index 000000000000..6c85276371bf --- /dev/null +++ b/files/image_config/environment/environment @@ -0,0 +1 @@ +VTYSH_PAGER=more diff --git a/files/image_config/environment/motd b/files/image_config/environment/motd new file mode 100644 index 000000000000..8562e330fe2c --- /dev/null +++ b/files/image_config/environment/motd @@ -0,0 +1,14 @@ +You are on + ____ ___ _ _ _ ____ + / ___| / _ \| \ | (_)/ ___| + \___ \| | | | \| | | | + ___) | |_| | |\ | | |___ + |____/ \___/|_| \_|_|\____| + +-- Software for Open Networking in the Cloud -- + +Unauthorized access and/or use are prohibited. +All access and/or use are subject to monitoring. + +Help: http://azure.github.io/SONiC/ + diff --git a/files/image_config/fstrim/fstrim.service b/files/image_config/fstrim/fstrim.service new file mode 100644 index 000000000000..c61683400831 --- /dev/null +++ b/files/image_config/fstrim/fstrim.service @@ -0,0 +1,7 @@ +[Unit] +Description=Discard unused blocks + +[Service] +Type=oneshot +ExecStartPre=/usr/local/bin/log_ssd_health +ExecStart=/sbin/fstrim -av diff --git a/files/image_config/fstrim/fstrim.timer b/files/image_config/fstrim/fstrim.timer new file mode 100644 index 000000000000..c6142dd94826 --- /dev/null +++ b/files/image_config/fstrim/fstrim.timer @@ -0,0 +1,12 @@ +[Unit] +Description=Discard unused blocks once a week +Documentation=man:fstrim + +[Timer] +OnCalendar=weekly +OnBootSec=10min +AccuracySec=1h +Persistent=true + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/hostname/hostname-config.service b/files/image_config/hostname/hostname-config.service new file mode 100644 index 000000000000..c23ae10227a4 --- /dev/null +++ b/files/image_config/hostname/hostname-config.service @@ -0,0 +1,11 @@ +[Unit] +Description=Update hostname based on configdb +Requires=updategraph.service +After=updategraph.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/hostname-config.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/hostname/hostname-config.sh b/files/image_config/hostname/hostname-config.sh new file mode 100755 index 000000000000..e9f7fc122709 --- /dev/null +++ b/files/image_config/hostname/hostname-config.sh @@ -0,0 +1,22 @@ +#!/bin/bash -e + +CURRENT_HOSTNAME=`hostname` +HOSTNAME=`sonic-cfggen -d -v DEVICE_METADATA[\'localhost\'][\'hostname\']` + +echo $HOSTNAME > /etc/hostname +hostname -F /etc/hostname + +# Remove the old hostname entry from hosts file. +# But, 'localhost' entry is used by multiple applications. Don't remove it altogether. +# Edit contents of /etc/hosts and put in /etc/hosts.new +if [ $CURRENT_HOSTNAME != "localhost" ] || [ $CURRENT_HOSTNAME == $HOSTNAME ] ; then + sed "/\s$CURRENT_HOSTNAME$/d" /etc/hosts > /etc/hosts.new +else + cp -f /etc/hosts /etc/hosts.new +fi + +echo "127.0.0.1 $HOSTNAME" >> /etc/hosts.new + +# Swap file: hosts.new and hosts +mv -f /etc/hosts /etc/hosts.old +mv -f /etc/hosts.new /etc/hosts diff --git a/files/image_config/interfaces/init_interfaces b/files/image_config/interfaces/init_interfaces new file mode 100644 index 000000000000..9d251045b5eb --- /dev/null +++ b/files/image_config/interfaces/init_interfaces @@ -0,0 +1,8 @@ +# Initial /etc/network/interface file for first boot +# Will be overwritten based on minigraph information by interfaces-config service + +# The loopback network interface +auto lo +iface lo inet loopback +# +# Disable the management network interface during boot up diff --git a/files/image_config/interfaces/interfaces-config.service b/files/image_config/interfaces/interfaces-config.service new file mode 100644 index 000000000000..71178affdee8 --- /dev/null +++ b/files/image_config/interfaces/interfaces-config.service @@ -0,0 +1,11 @@ +[Unit] +Description=Update interfaces configuration +Requires=updategraph.service +After=updategraph.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/interfaces-config.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/interfaces/interfaces-config.sh b/files/image_config/interfaces/interfaces-config.sh new file mode 100755 index 000000000000..688b2f8433a5 --- /dev/null +++ b/files/image_config/interfaces/interfaces-config.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +ifdown --force eth0 + +# 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, dhcp6 sytcl.conf and dhclient.conf +CFGGEN_PARAMS=" \ + -d -j /tmp/ztp_input.json \ + -t /usr/share/sonic/templates/interfaces.j2,/etc/network/interfaces \ + -t /usr/share/sonic/templates/90-dhcp6-systcl.conf.j2,/etc/sysctl.d/90-dhcp6-systcl.conf \ + -t /usr/share/sonic/templates/dhclient.conf.j2,/etc/dhcp/dhclient.conf \ +" +sonic-cfggen $CFGGEN_PARAMS + +[ -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 + +# Read sysctl conf files again +sysctl -p /etc/sysctl.d/90-dhcp6-systcl.conf + +systemctl restart networking + +# 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 new file mode 100644 index 000000000000..98e43dd13be4 --- /dev/null +++ b/files/image_config/interfaces/interfaces.j2 @@ -0,0 +1,108 @@ +# +{% block banner %} +# =============== Managed by SONiC Config Engine DO NOT EDIT! =============== +# generated from /usr/share/sonic/templates/interfaces.j2 using sonic-cfggen +# 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 +# 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/16 dev lo-m + up ip link set lo-m up + down ip link delete dev lo-m +{% endif %} +{% endblock mgmt_vrf %} +{% block loopback %} +# The loopback network interface +auto lo +iface lo inet loopback + address 127.0.0.1 + netmask 255.255.0.0 + post-up ip addr del 127.0.0.1/8 dev lo +{% 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 + address {{ prefix | ip }} + netmask {{ prefix | netmask if prefix | ipv4 else prefix | prefixlen }} + network {{ prefix | network }} + broadcast {{ prefix | broadcast }} +{% set vrf_table = 'default' %} +{% if (MGMT_VRF_CONFIG) and (MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == "true") %} +{% set vrf_table = '5000' %} + vrf mgmt +{% endif %} + ########## management network policy routing rules + # management port up rules + up ip {{ '-4' if prefix | ipv4 else '-6' }} route add default via {{ MGMT_INTERFACE[(name, prefix)]['gwaddr'] }} dev eth0 table {{ vrf_table }} metric 201 + up ip {{ '-4' if prefix | ipv4 else '-6' }} route add {{ prefix | network }}/{{ prefix | prefixlen }} dev eth0 table {{ vrf_table }} + up ip {{ '-4' if prefix | ipv4 else '-6' }} rule add pref 32765 from {{ prefix | ip }}/{{ '32' if prefix | ipv4 else '128' }} table {{ vrf_table }} +{% for route in MGMT_INTERFACE[(name, prefix)]['forced_mgmt_routes'] %} + up ip rule add pref 32764 to {{ route }} table {{ vrf_table }} +{% endfor %} + # management port down rules + 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 pref 32765 from {{ prefix | ip }}/{{ '32' if prefix | ipv4 else '128' }} table {{ vrf_table }} +{% for route in MGMT_INTERFACE[(name, prefix)]['forced_mgmt_routes'] %} + pre-down ip rule delete pref 32764 to {{ route }} table {{ vrf_table }} +{% endfor %} +{# TODO: COPP policy type rules #} +{% endfor %} +{% else %} +iface eth0 inet dhcp + metric 202 +{% if (MGMT_VRF_CONFIG) and (MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == "true") %} + vrf 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/* +# +{% endblock mgmt_interface %} diff --git a/files/image_config/kdump/kdump-tools b/files/image_config/kdump/kdump-tools new file mode 100644 index 000000000000..61a41eb31902 --- /dev/null +++ b/files/image_config/kdump/kdump-tools @@ -0,0 +1,16 @@ +# Default configuration +KDUMP_CMDLINE_APPEND="irqpoll nr_cpus=1 nousb systemd.unit=kdump-tools.service ata_piix.prefer_ms_hyperv=0" + +# --------------------------------------------------------------------------- +# Additional Kdump environment settings used in SONiC +# + +# Reboot crash kernel on panic +# Enable debug level logging of crash kernel for better visibility +# Disable advanced pcie features +# Disable high precision event timer as on some platforms it is interfering with the kdump operation +# Pass platform identifier string as part of crash kernel command line to be used by the reboot script during kdump +KDUMP_CMDLINE_APPEND+=" panic=10 debug hpet=disable pcie_port=compat pci=nommconf sonic_platform=__PLATFORM__" + +# Use SONiC reboot wrapper script present in /usr/local/bin post kdump +PATH=/usr/local/bin:$PATH diff --git a/files/image_config/kdump/vmcore-sysctl.conf b/files/image_config/kdump/vmcore-sysctl.conf new file mode 100755 index 000000000000..9a4016197cbd --- /dev/null +++ b/files/image_config/kdump/vmcore-sysctl.conf @@ -0,0 +1,7 @@ +kernel.panic_on_oops=1 +kernel.panic_on_unrecovered_nmi=1 +kernel.panic_on_io_nmi=1 +kernel.panic_on_stackoverflow=1 +kernel.hung_task_panic=1 +kernel.unknown_nmi_panic=1 +vm.panic_on_oom=1 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/logrotate/logrotate.conf b/files/image_config/logrotate/logrotate.conf new file mode 100644 index 000000000000..6f107e209837 --- /dev/null +++ b/files/image_config/logrotate/logrotate.conf @@ -0,0 +1,32 @@ +# see "man logrotate" for details +# Rotate log files daily by default +daily + +# Keep 4 days worth of backlogs by default +rotate 4 + +# create new (empty) log files after rotating old ones +create + +# uncomment this if you want your log files compressed +#compress + +# packages drop log rotation information into this directory +include /etc/logrotate.d + +# no packages own wtmp, or btmp -- we'll rotate them here +/var/log/wtmp { + missingok + size 100k + create 0664 root utmp + rotate 1 +} + +/var/log/btmp { + missingok + size 100k + create 0660 root utmp + rotate 1 +} + +# system-specific logs may be configured here diff --git a/files/image_config/logrotate/logrotate.d/alternatives b/files/image_config/logrotate/logrotate.d/alternatives new file mode 100644 index 000000000000..7c4c93c85834 --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/alternatives @@ -0,0 +1,9 @@ +/var/log/alternatives.log { + size 100k + rotate 1 + compress + delaycompress + missingok + notifempty + create 644 root root +} diff --git a/files/image_config/logrotate/logrotate.d/apt b/files/image_config/logrotate/logrotate.d/apt new file mode 100644 index 000000000000..7584dcacc881 --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/apt @@ -0,0 +1,15 @@ +/var/log/apt/term.log { + size 100k + rotate 1 + compress + missingok + notifempty +} + +/var/log/apt/history.log { + size 100k + rotate 1 + compress + missingok + notifempty +} diff --git a/files/image_config/logrotate/logrotate.d/dpkg b/files/image_config/logrotate/logrotate.d/dpkg new file mode 100644 index 000000000000..51b8f46fe105 --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/dpkg @@ -0,0 +1,9 @@ +/var/log/dpkg.log { + size 100k + rotate 1 + compress + delaycompress + missingok + notifempty + create 644 root root +} diff --git a/files/image_config/logrotate/logrotate.d/monit b/files/image_config/logrotate/logrotate.d/monit new file mode 100644 index 000000000000..7846dfadb77c --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/monit @@ -0,0 +1,12 @@ +/var/log/monit.log { + size 100k + rotate 1 + missingok + create 640 root adm + notifempty + compress + delaycompress + postrotate + invoke-rc.d monit reload > /dev/null + endscript +} diff --git a/files/image_config/logrotate/logrotate.d/rsyslog b/files/image_config/logrotate/logrotate.d/rsyslog new file mode 100644 index 000000000000..cbf6e722eb90 --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/rsyslog @@ -0,0 +1,108 @@ +# These logs should no longer get created. However, in case they do get created, +# we should keep them to a small size and rotate them also. +/var/log/mail.info +/var/log/mail.warn +/var/log/mail.err +/var/log/mail.log +/var/log/daemon.log +/var/log/kern.log +/var/log/user.log +/var/log/lpr.log +/var/log/debug +/var/log/messages +{ + size 10k + rotate 1 + missingok + notifempty + compress + delaycompress + sharedscripts + postrotate + /bin/kill -HUP $(cat /var/run/rsyslogd.pid) + endscript +} + +/var/log/auth.log +/var/log/cron.log +/var/log/syslog +/var/log/teamd.log +/var/log/telemetry.log +/var/log/frr/bgpd.log +/var/log/frr/zebra.log +/var/log/swss/sairedis*.rec +/var/log/swss/swss*.rec +{ + size 1M + rotate 5000 + missingok + notifempty + compress + delaycompress + nosharedscripts + firstaction + # Adjust NUM_LOGS_TO_ROTATE to reflect number of log files that trigger this block specified above + NUM_LOGS_TO_ROTATE=8 + + # Adjust LOG_FILE_ROTATE_SIZE_KB to reflect the "size" parameter specified above, in kB + LOG_FILE_ROTATE_SIZE_KB=1024 + + # Reserve space for btmp, wtmp, dpkg.log, monit.log, etc., as well as logs that + # should be disabled, just in case they get created and rotated + RESERVED_SPACE_KB=4096 + + VAR_LOG_SIZE_KB=$(df -k /var/log | sed -n 2p | awk '{ print $2 }') + + # Limit usable space to 90% of the partition minus the reserved space for other logs + USABLE_SPACE_KB=$(( (VAR_LOG_SIZE_KB * 90 / 100) - RESERVED_SPACE_KB)) + + # Set our threshold so as to maintain enough space to write all logs from empty to full + # Most likely, some logs will have non-zero size when this is called, so this errs on the side + # of caution, giving us a bit of a cushion if a log grows quickly and passes its rotation size + THRESHOLD_KB=$((USABLE_SPACE_KB - (NUM_LOGS_TO_ROTATE * LOG_FILE_ROTATE_SIZE_KB * 2))) + + # First, delete any *.1.gz files that might be left around from a prior incomplete + # logrotate execution, otherwise logrotate will fail to do its job + find /var/log/ -name '*.1.gz' -type f -exec rm -f {} + + + while true; do + USED_KB=$(du -s /var/log | awk '{ print $1; }') + + if [ $USED_KB -lt $THRESHOLD_KB ]; then + break + else + OLDEST_ARCHIVE_FILE=$(find /var/log -type f -printf '%T+ %p\n' | grep -E '.+\.[0-9]+(\.gz)?$' | sort | head -n 1 | awk '{ print $2; }') + + if [ -z "$OLDEST_ARCHIVE_FILE" ]; then + logger -p syslog.err -t "logrotate" "No archive file to delete -- potential for filling up /var/log partition!" + break + fi + + logger -p syslog.info -t "logrotate" "Deleting archive file $OLDEST_ARCHIVE_FILE to free up space" + rm -rf "$OLDEST_ARCHIVE_FILE" + fi + done + endscript + postrotate + if [ $(echo $1 | grep -c "/var/log/swss/") -gt 0 ]; then + # for multi asic platforms, there are multiple orchagents + # send the SIGHUP only to the orchagent the which needs log file rotation + PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf + if [ -f "$ASIC_CONF" ]; then + . $ASIC_CONF + fi + if [ $NUM_ASIC -gt 1 ]; then + log_file=$1 + log_file_name=${log_file#/var/log/swss/} + logger -p syslog.info -t "logrotate" "Sending SIGHUP to OA log_file_name: $log_file_name" + pgrep -xa orchagent | grep $log_file_name | awk '{ print $1; }' | xargs /bin/kill -HUP 2>/dev/null || true + else + logger -p syslog.info -t "logrotate" "Sending SIGHUP to OA log_file_name: $1" + pgrep -x orchagent | xargs /bin/kill -HUP 2>/dev/null || true + fi + else + /bin/kill -HUP $(cat /var/run/rsyslogd.pid) + fi + endscript +} diff --git a/files/image_config/misc/docker-wait-any b/files/image_config/misc/docker-wait-any new file mode 100755 index 000000000000..4200bb43c87f --- /dev/null +++ b/files/image_config/misc/docker-wait-any @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 + +""" + docker-wait-any + This script takes one or more Docker container names as arguments, + [-s] argument is for the service which invokes this script + [-d] argument is to list the dependent services for the above service. + It will block indefinitely while all of the specified containers + are running.If any of the specified containers stop, the script will + exit. + + This script was created because the 'docker wait' command is lacking + this functionality. It will block until ALL specified containers have + stopped running. Here, we spawn multiple threads and wait on one + container per thread. If any of the threads exit, the entire + application will exit, unless we are in a scenario where the following + conditions are met. + (i) the container is a dependent service + (ii) warm restart is enabled at system level or for that container OR + fast reboot is enabled system level + In this scenario, the g_thread_exit_event won't be propogated to the parent, + instead the thread will continue to do docker_client.wait again.This help's + cases where we need the dependent container to be warm-restarted without + affecting other services (eg: warm restart of teamd service) + + NOTE: This script is written against docker Python package 4.3.1. Newer + versions of docker may have a different API. +""" +import argparse +import sys +import threading +import time + +from docker import APIClient +from sonic_py_common import logger, device_info + +SYSLOG_IDENTIFIER = 'docker-wait-any' + +# Global logger instance +log = logger.Logger(SYSLOG_IDENTIFIER) + +# Instantiate a global event to share among our threads +g_thread_exit_event = threading.Event() +g_service = [] +g_dep_services = [] + + +def wait_for_container(docker_client, container_name): + while True: + while docker_client.inspect_container(container_name)['State']['Status'] != "running": + time.sleep(1) + + docker_client.wait(container_name) + + log.log_info("No longer waiting on container '{}'".format(container_name)) + + # If this is a dependent service and warm restart is enabled for the system/container, + # OR if the system is going through a fast-reboot, DON'T signal main thread to exit + if (container_name in g_dep_services and + (device_info.is_warm_restart_enabled(container_name) or device_info.is_fast_reboot_enabled())): + continue + + # Signal the main thread to exit + g_thread_exit_event.set() + + +def main(): + thread_list = [] + + docker_client = APIClient(base_url='unix://var/run/docker.sock') + + parser = argparse.ArgumentParser(description='Wait for dependent docker services', + formatter_class=argparse.RawTextHelpFormatter, + epilog=""" +Examples: + docker-wait-any -s swss -d syncd teamd +""") + + parser.add_argument('-s', '--service', nargs='+', default=None, help='name of the service') + parser.add_argument('-d', '--dependent', nargs='*', default=None, help='other dependent services') + args = parser.parse_args() + + global g_service + global g_dep_services + + if args.service is not None: + g_service = args.service + if args.dependent is not None: + g_dep_services = args.dependent + + container_names = g_service + g_dep_services + + # If the service and dependents passed as args is empty, then exit + if container_names == []: + sys.exit(0) + + for container_name in container_names: + t = threading.Thread(target=wait_for_container, args=[docker_client, container_name]) + t.daemon = True + t.start() + thread_list.append(t) + + # Wait until we receive an event signifying one of the containers has stopped + g_thread_exit_event.wait() + sys.exit(0) + + +if __name__ == '__main__': + main() diff --git a/files/image_config/monit/conf.d/sonic-host b/files/image_config/monit/conf.d/sonic-host new file mode 100644 index 000000000000..17d7c64af7e2 --- /dev/null +++ b/files/image_config/monit/conf.d/sonic-host @@ -0,0 +1,35 @@ +############################################################################### +## Monit configuration for SONiC host OS +## +## This includes system-level monitoring as well as processes which +## run in the host OS (i.e., not inside a Docker container) +############################################################################### + +check filesystem root-overlay with path / + if space usage > 90% for 10 times within 20 cycles then alert repeat every 1 cycles + +check filesystem var-log with path /var/log + if space usage > 90% for 10 times within 20 cycles then alert repeat every 1 cycles + +check system $HOST + if memory usage > 90% for 10 times within 20 cycles then alert repeat every 1 cycles + if cpu usage (user) > 90% for 10 times within 20 cycles then alert repeat every 1 cycles + if cpu usage (system) > 90% for 10 times within 20 cycles then alert repeat every 1 cycles + +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 10 times within 20 cycles then restart + +# route_check.py Verify routes between APPL-DB & ASIC-DB are in sync. +# For any discrepancy, details are logged and a non-zero code is returned +# which would trigger a monit alert. +# Hence for any discrepancy, there will be log messages for "ERR" level +# from both route_check.py & monit. +# +check program routeCheck with path "/usr/local/bin/route_check.py" + every 5 cycles + if status != 0 for 3 cycle then alert repeat every 1 cycles + +check program container_checker with path "/usr/bin/container_checker" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/files/image_config/monit/container_checker b/files/image_config/monit/container_checker new file mode 100755 index 000000000000..abfbb34430bb --- /dev/null +++ b/files/image_config/monit/container_checker @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +""" +container_checker + +This script is intended to be run by Monit. It will write an alerting message into +syslog if it found containers which were expected to run but were not running. At +the same time, if some containers were unexpected to run, it also writes an alerting +syslog message. Note that if print(...) statement in this script was executed, the +string in it will be appended to Monit syslog messages. + +The following is an example in Monit configuration file to show how Monit will run +this script: + +check program container_checker with path "/usr/bin/container_checker" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles +""" + +import subprocess +import sys + +import swsssdk +from sonic_py_common import multi_asic + + +def get_command_result(command): + """ + @summary: This function will execute the command and return the resulting output. + @return: A string which contains the output of command. + """ + command_stdout = "" + + try: + proc_instance = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + shell=True, universal_newlines=True) + command_stdout, command_stderr = proc_instance.communicate() + if proc_instance.returncode != 0: + print("Failed to execute the command '{}'. Return code: '{}'".format( + command, proc_instance.returncode)) + sys.exit(1) + except (OSError, ValueError) as err: + print("Failed to execute the command '{}'. Error: '{}'".format(command, err)) + sys.exit(2) + + return command_stdout.rstrip().split("\n") + + +def get_expected_running_containers(): + """ + @summary: This function will get the expected running containers by following the rule: + The 'state' field of container in 'FEATURE' table should not be 'disabled'. Then + if the device has Multi-ASIC, this function will get container list by determining the + value of field 'has_global_scope', the number of ASICs and the value of field + 'has_per_asic_scope'. If the device has single ASIC, the container name was put into + the list. + @return: A set which contains the expected running containers. + """ + config_db = swsssdk.ConfigDBConnector() + config_db.connect() + feature_table = config_db.get_table("FEATURE") + + expected_running_containers = set() + + for container_name in feature_table.keys(): + if feature_table[container_name]["state"] != "disabled": + if multi_asic.is_multi_asic(): + if feature_table[container_name]["has_global_scope"] == "True": + expected_running_containers.add(container_name) + if feature_table[container_name]["has_per_asic_scope"] == "True": + num_asics = multi_asic.get_num_asics() + for asic_id in range(num_asics): + expected_running_containers.add(container_name + str(asic_id)) + else: + expected_running_containers.add(container_name) + + return expected_running_containers + + +def get_current_running_containers(): + """ + @summary: This function will get the current running container list by analyzing the + output of command `docker ps`. + @return: A set which contains the current running contianers. + """ + running_containers = set() + + command = "docker ps" + command_stdout = get_command_result(command) + for line in command_stdout[1:]: + running_containers.add(line.split()[-1].strip()) + + return running_containers + + +def main(): + """ + @summary: This function will compare the difference between the current running containers + and the containers which were expected to run. If containers which were exepcted + to run were not running, then an alerting message will be written into syslog. + """ + expected_running_containers = get_expected_running_containers() + current_running_containers = get_current_running_containers() + + not_running_containers = expected_running_containers.difference(current_running_containers) + if not_running_containers: + print("Expected containers not running: " + ", ".join(not_running_containers)) + sys.exit(3) + + unexpected_running_containers = current_running_containers.difference(expected_running_containers) + if unexpected_running_containers: + print("Unexpected running containers: " + ", ".join(unexpected_running_containers)) + sys.exit(4) + + +if __name__ == "__main__": + main() diff --git a/files/image_config/monit/monitrc b/files/image_config/monit/monitrc new file mode 100644 index 000000000000..74068f12d3f8 --- /dev/null +++ b/files/image_config/monit/monitrc @@ -0,0 +1,296 @@ +############################################################################### +## Monit control file +############################################################################### +## +## Comments begin with a '#' and extend through the end of the line. Keywords +## are case insensitive. All path's MUST BE FULLY QUALIFIED, starting with '/'. +## +## Below you will find examples of some frequently used statements. For +## information about the control file and a complete list of statements and +## options, please have a look in the Monit manual. +## +## +############################################################################### +## Global section +############################################################################### +## +## Start Monit in the background (run as a daemon): +# + 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, +## specify the full path to the log file +# + set logfile syslog +# +# +## Set the location of the Monit lock file which stores the process id of the +## running Monit instance. By default this file is stored in $HOME/.monit.pid +# +# set pidfile /var/run/monit.pid +# +## Set the location of the Monit id file which stores the unique id for the +## Monit instance. The id is generated and stored on first Monit start. By +## default the file is placed in $HOME/.monit.id. +# +# set idfile /var/.monit.id + set idfile /var/lib/monit/id +# +## Set the location of the Monit state file which saves monitoring states +## on each cycle. By default the file is placed in $HOME/.monit.state. If +## the state file is stored on a persistent filesystem, Monit will recover +## the monitoring state across reboots. If it is on temporary filesystem, the +## state will be lost on reboot which may be convenient in some situations. +# + set statefile /var/lib/monit/state +# +# + +## Set limits for various tests. The following example shows the default values: +## +# set limits { +# programOutput: 512 B, # check program's output truncate limit +# sendExpectBuffer: 256 B, # limit for send/expect protocol test +# fileContentBuffer: 512 B, # limit for file content test +# httpContentBuffer: 1 MB, # limit for HTTP content test +# networkTimeout: 5 seconds # timeout for network I/O +# programTimeout: 300 seconds # timeout for check program +# stopTimeout: 30 seconds # timeout for service stop +# startTimeout: 30 seconds # timeout for service start +# restartTimeout: 30 seconds # timeout for service restart +# } + +## Set global SSL options (just most common options showed, see manual for +## full list). +# +# set ssl { +# verify : enable, # verify SSL certificates (disabled by default but STRONGLY RECOMMENDED) +# selfsigned : allow # allow self signed SSL certificates (reject by default) +# } +# +# +## Set the list of mail servers for alert delivery. Multiple servers may be +## specified using a comma separator. If the first mail server fails, Monit +# will use the second mail server in the list and so on. By default Monit uses +# port 25 - it is possible to override this with the PORT option. +# +# set mailserver mail.bar.baz, # primary mailserver +# backup.bar.baz port 10025, # backup mailserver on port 10025 +# localhost # fallback relay +# +# +## By default Monit will drop alert events if no mail servers are available. +## If you want to keep the alerts for later delivery retry, you can use the +## EVENTQUEUE statement. The base directory where undelivered alerts will be +## stored is specified by the BASEDIR option. You can limit the queue size +## by using the SLOTS option (if omitted, the queue is limited by space +## available in the back end filesystem). +# + set eventqueue + basedir /var/lib/monit/events # set the base directory where events will be stored + slots 100 # optionally limit the queue size +# +# +## Send status and events to M/Monit (for more informations about M/Monit +## see https://mmonit.com/). By default Monit registers credentials with +## M/Monit so M/Monit can smoothly communicate back to Monit and you don't +## have to register Monit credentials manually in M/Monit. It is possible to +## disable credential registration using the commented out option below. +## Though, if safety is a concern we recommend instead using https when +## communicating with M/Monit and send credentials encrypted. The password +## should be URL encoded if it contains URL-significant characters like +## ":", "?", "@". +# +# set mmonit http://monit:monit@192.168.1.10:8080/collector +# # and register without credentials # Don't register credentials +# +# +## Monit by default uses the following format for alerts if the the mail-format +## statement is missing:: +## --8<-- +## set mail-format { +## from: Monit +## subject: monit alert -- $EVENT $SERVICE +## message: $EVENT Service $SERVICE +## Date: $DATE +## Action: $ACTION +## Host: $HOST +## Description: $DESCRIPTION +## +## Your faithful employee, +## Monit +## } +## --8<-- +## +## You can override this message format or parts of it, such as subject +## or sender using the MAIL-FORMAT statement. Macros such as $DATE, etc. +## are expanded at runtime. For example, to override the sender, use: +# +# set mail-format { from: monit@foo.bar } +# +# +## You can set alert recipients whom will receive alerts if/when a +## service defined in this file has errors. Alerts may be restricted on +## events by using a filter as in the second example below. +# +# set alert sysadm@foo.bar # receive all alerts +# +## Do not alert when Monit starts, stops or performs a user initiated action. +## This filter is recommended to avoid getting alerts for trivial cases. +# +# set alert your-name@your.domain not on { instance, action } +# +# +## Monit has an embedded HTTP interface which can be used to view status of +## services monitored and manage services from a web interface. The HTTP +## interface is also required if you want to issue Monit commands from the +## command line, such as 'monit status' or 'monit restart service' The reason +## for this is that the Monit client uses the HTTP interface to send these +## commands to a running Monit daemon. See the Monit Wiki if you want to +## enable SSL for the HTTP interface. +# + set httpd unixsocket /var/run/monit.sock and + allow localhost # allow localhost to connect to the server +# +############################################################################### +## Services +############################################################################### +## +## Check general system resources such as load average, cpu and memory +## usage. Each test specifies a resource, conditions and the action to be +## performed should a test fail. +# +# check system $HOST +# if loadavg (1min) > 4 then alert +# if loadavg (5min) > 2 then alert +# if cpu usage > 95% for 10 cycles then alert +# if memory usage > 75% then alert +# if swap usage > 25% then alert +# +# +## Check if a file exists, checksum, permissions, uid and gid. In addition +## to alert recipients in the global section, customized alert can be sent to +## additional recipients by specifying a local alert handler. The service may +## be grouped using the GROUP option. More than one group can be specified by +## repeating the 'group name' statement. +# +# check file apache_bin with path /usr/local/apache/bin/httpd +# if failed checksum and +# expect the sum 8f7f419955cefa0b33a2ba316cba3659 then unmonitor +# if failed permission 755 then unmonitor +# if failed uid root then unmonitor +# if failed gid root then unmonitor +# alert security@foo.bar on { +# checksum, permission, uid, gid, unmonitor +# } with the mail-format { subject: Alarm! } +# group server +# +# +## Check that a process is running, in this case Apache, and that it respond +## to HTTP and HTTPS requests. Check its resource usage such as cpu and memory, +## and number of children. If the process is not running, Monit will restart +## it by default. In case the service is restarted very often and the +## problem remains, it is possible to disable monitoring using the TIMEOUT +## statement. This service depends on another service (apache_bin) which +## is defined above. +# +# check process apache with pidfile /usr/local/apache/logs/httpd.pid +# start program = "/etc/init.d/httpd start" with timeout 60 seconds +# stop program = "/etc/init.d/httpd stop" +# if cpu > 60% for 2 cycles then alert +# if cpu > 80% for 5 cycles then restart +# if totalmem > 200.0 MB for 5 cycles then restart +# if children > 250 then restart +# if loadavg(5min) greater than 10 for 8 cycles then stop +# if failed host www.tildeslash.com port 80 protocol http +# and request "/somefile.html" +# then restart +# if failed port 443 protocol https with timeout 15 seconds then restart +# if 3 restarts within 5 cycles then unmonitor +# depends on apache_bin +# group server +# +# +## Check filesystem permissions, uid, gid, space and inode usage. Other services, +## such as databases, may depend on this resource and an automatically graceful +## stop may be cascaded to them before the filesystem will become full and data +## lost. +# +# check filesystem datafs with path /dev/sdb1 +# start program = "/bin/mount /data" +# stop program = "/bin/umount /data" +# if failed permission 660 then unmonitor +# if failed uid root then unmonitor +# if failed gid disk then unmonitor +# if space usage > 80% for 5 times within 15 cycles then alert +# if space usage > 99% then stop +# if inode usage > 30000 then alert +# if inode usage > 99% then stop +# group server +# +# +## Check a file's timestamp. In this example, we test if a file is older +## than 15 minutes and assume something is wrong if its not updated. Also, +## if the file size exceed a given limit, execute a script +# +# check file database with path /data/mydatabase.db +# if failed permission 700 then alert +# if failed uid data then alert +# if failed gid data then alert +# if timestamp > 15 minutes then alert +# if size > 100 MB then exec "/my/cleanup/script" as uid dba and gid dba +# +# +## Check directory permission, uid and gid. An event is triggered if the +## directory does not belong to the user with uid 0 and gid 0. In addition, +## the permissions have to match the octal description of 755 (see chmod(1)). +# +# check directory bin with path /bin +# if failed permission 755 then unmonitor +# if failed uid 0 then unmonitor +# if failed gid 0 then unmonitor +# +# +## Check a remote host availability by issuing a ping test and check the +## content of a response from a web server. Up to three pings are sent and +## connection to a port and an application level network check is performed. +# +# check host myserver with address 192.168.1.1 +# if failed ping then alert +# if failed port 3306 protocol mysql with timeout 15 seconds then alert +# if failed port 80 protocol http +# and request /some/path with content = "a string" +# then alert +# +# +## Check a network link status (up/down), link capacity changes, saturation +## and bandwidth usage. +# +# check network public with interface eth0 +# if failed link then alert +# if changed link then alert +# if saturation > 90% then alert +# if download > 10 MB/s then alert +# if total uploaded > 1 GB in last hour then alert +# +# +## Check custom program status output. +# +# check program myscript with path /usr/local/bin/myscript.sh +# if status != 0 then alert +# +# +############################################################################### +## Includes +############################################################################### +## +## It is possible to include additional configuration parts from other files or +## directories. +# + include /etc/monit/conf.d/* + include /etc/monit/conf-enabled/* +# diff --git a/files/image_config/monit/process_checker b/files/image_config/monit/process_checker new file mode 100755 index 000000000000..68c8f3e945fd --- /dev/null +++ b/files/image_config/monit/process_checker @@ -0,0 +1,98 @@ +#!/usr/bin/python3 + +import argparse +import ast +import sys +import syslog + +import psutil +from sonic_py_common import multi_asic +import swsssdk + + +def check_process_existence(container_name, process_cmdline): + """ + @summary: Check whether the process in the specified container is running or not and + an alerting message will written into syslog if it failed to run. + """ + config_db = swsssdk.ConfigDBConnector() + config_db.connect() + feature_table = config_db.get_table("FEATURE") + + if container_name in feature_table: + # We look into the 'FEATURE' table to verify whether the container is disabled or not. + # If the container is diabled, we exit. + if ("state" in feature_table[container_name] + and feature_table[container_name]["state"] == "disabled"): + sys.exit(0) + else: + # We leveraged the psutil library to help us check whether the process is running or not. + # If the process entity is found in process tree and it is also in the 'running' or 'sleeping' + # state, then it will be marked as 'running'. + + # For given feature we get the host and network namespace instances it's processes should be running + # based on it's scope and add it to expected set. + + # From psutil we get number of running instances of the processes and add it to the the actual set + + # Difference bwetween expected and actual set provides instances where the processes are not running + # and will be logged as syslog message by monit + + process_namespace_expected_set = set() + process_namespace_found_set = set() + + has_global_scope = ast.literal_eval(feature_table[container_name].get('has_global_scope', 'True')) + has_per_asic_scope = ast.literal_eval(feature_table[container_name].get('has_per_asic_scope', 'False')) + + if has_global_scope: + process_namespace_expected_set.add(multi_asic.DEFAULT_NAMESPACE) + + if has_per_asic_scope: + process_namespace_expected_set.update(multi_asic.get_namespace_list()) + + for process in psutil.process_iter(["cmdline", "status", "pid"]): + try: + if ((' '.join(process.cmdline())).startswith(process_cmdline) and process.status() in ["running", "sleeping"]): + process_namespace_found_set.add(multi_asic.get_current_namespace(process.info['pid'])) + except psutil.NoSuchProcess: + pass + + process_namespace_diff_set = process_namespace_expected_set.difference(process_namespace_found_set) + + if process_namespace_diff_set: + host_display_str = "" + namespace_display_str = "" + + for ns in process_namespace_diff_set: + if ns == multi_asic.DEFAULT_NAMESPACE: + host_display_str = " in host" + else: + if not namespace_display_str: + namespace_display_str = " in namespace " + ns + else: + namespace_display_str += ", " + ns + + join_str = " and" if host_display_str and namespace_display_str else "" + + # If this script is run by Monit, then the following output will be appended to + # Monit's syslog message. + print("'{}' is not running{}{}{}".format(process_cmdline, host_display_str, join_str, namespace_display_str)) + sys.exit(1) + else: + syslog.syslog(syslog.LOG_ERR, "container '{}' is not included in SONiC image or the given container name is invalid!" + .format(container_name)) + + +def main(): + parser = argparse.ArgumentParser(description="Check whether the process in the specified \ + container is running and an alerting message will be written into syslog if it \ + failed to run.", usage="/usr/bin/process_checker ") + parser.add_argument("container_name", help="container name") + parser.add_argument("process_cmdline", nargs=argparse.REMAINDER, help="process command line") + args = parser.parse_args() + + check_process_existence(args.container_name, ' '.join(args.process_cmdline)) + + +if __name__ == '__main__': + main() diff --git a/files/image_config/ntp/ntp b/files/image_config/ntp/ntp new file mode 100755 index 000000000000..f0ca500fb8f3 --- /dev/null +++ b/files/image_config/ntp/ntp @@ -0,0 +1,100 @@ +#!/bin/sh + +# This file was originally created automatically as part of default NTP application installation from debian package. +# This is now manually modified for supporting NTP in management VRF. +# When management VRF is enabled, the NTP application should be started using "cgexec -g l3mdev:mgmt". +# Check has been added to verify the management VRF enabled status and use cgexec when it is enabled. +# This file will be copied on top of the etc/init.d/ntp file that gets created during build process. + +### BEGIN INIT INFO +# Provides: ntp +# Required-Start: $network $remote_fs $syslog +# Required-Stop: $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: +# Short-Description: Start NTP daemon +### END INIT INFO + +PATH=/sbin:/bin:/usr/sbin:/usr/bin + +. /lib/lsb/init-functions + +DAEMON=/usr/sbin/ntpd +PIDFILE=/var/run/ntpd.pid + +test -x $DAEMON || exit 5 + +if [ -r /etc/default/ntp ]; then + . /etc/default/ntp +fi + +if [ -e /run/ntp.conf.dhcp ]; then + NTPD_OPTS="$NTPD_OPTS -c /run/ntp.conf.dhcp" +fi + + +LOCKFILE=/run/lock/ntpdate + +RUNASUSER=ntp +UGID=$(getent passwd $RUNASUSER | cut -f 3,4 -d:) || true +if test "$(uname -s)" = "Linux"; then + NTPD_OPTS="$NTPD_OPTS -u $UGID" +fi + +case $1 in + start) + log_daemon_msg "Starting NTP server" "ntpd" + if [ -z "$UGID" ]; then + log_failure_msg "user \"$RUNASUSER\" does not exist" + exit 1 + fi + ( + flock -w 180 9 + + # when mgmt vrf is configured, ntp starts in mgmt vrf by default unless user configures otherwise + vrfEnabled=$(/usr/local/bin/sonic-cfggen -d -v 'MGMT_VRF_CONFIG["vrf_global"]["mgmtVrfEnabled"]' 2> /dev/null) + vrfConfigured=$(/usr/local/bin/sonic-cfggen -d -v 'NTP["global"]["vrf"]' 2> /dev/null) + if [ "$vrfEnabled" = "true" ] + then + if [ "$vrfConfigured" = "default" ] + then + log_daemon_msg "Starting NTP server in default-vrf for default set as NTP vrf" "ntpd" + start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE $NTPD_OPTS + else + log_daemon_msg "Starting NTP server in mgmt-vrf" "ntpd" + cgexec -g l3mdev:mgmt start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE $NTPD_OPTS + fi + else + log_daemon_msg "Starting NTP server in default-vrf" "ntpd" + start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE $NTPD_OPTS + fi + ) 9>$LOCKFILE + log_end_msg $? + ;; + stop) + log_daemon_msg "Stopping NTP server" "ntpd" + start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE --retry=TERM/30/KILL/5 --exec $DAEMON + log_end_msg $? + rm -f $PIDFILE + ;; + restart|force-reload) + $0 stop && sleep 2 && $0 start + ;; + try-restart) + if $0 status >/dev/null; then + $0 restart + else + exit 0 + fi + ;; + reload) + exit 3 + ;; + status) + status_of_proc $DAEMON "NTP server" + ;; + *) + echo "Usage: $0 {start|stop|restart|try-restart|force-reload|status}" + exit 2 + ;; +esac diff --git a/files/image_config/ntp/ntp-apparmor b/files/image_config/ntp/ntp-apparmor new file mode 100644 index 000000000000..78edef66a51f --- /dev/null +++ b/files/image_config/ntp/ntp-apparmor @@ -0,0 +1,9 @@ +# Apparmor configuration +# /etc/apparmor.d/local/usr.sbin.ntpd + + # Allow read access to "rw" mount path of fs.squashfs + # Eg: /host/image-HEAD-sonic.../rw/usr/sbin + /**/{,s}bin/ r, + /**/usr/{,s}bin/ r, + /**/usr/local/{,s}bin/ r, + diff --git a/files/image_config/ntp/ntp-config.service b/files/image_config/ntp/ntp-config.service new file mode 100644 index 000000000000..a22a0331045d --- /dev/null +++ b/files/image_config/ntp/ntp-config.service @@ -0,0 +1,13 @@ +[Unit] +Description=Update NTP configuration +Requires=updategraph.service +After=updategraph.service +Before=ntp.service +StartLimitIntervalSec=0 + +[Service] +Type=oneshot +ExecStart=/usr/bin/ntp-config.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/ntp/ntp-config.sh b/files/image_config/ntp/ntp-config.sh new file mode 100755 index 000000000000..9b982d8707b6 --- /dev/null +++ b/files/image_config/ntp/ntp-config.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +ntp_default_file='/etc/default/ntp' +ntp_temp_file='/tmp/ntp.orig' + +reboot_type='cold' + +function get_database_reboot_type() +{ + SYSTEM_WARM_START=`sonic-db-cli STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable` + SYSTEM_FAST_START=`sonic-db-cli STATE_DB get "FAST_REBOOT|system"` + + if [[ x"${SYSTEM_WARM_START}" == x"true" ]]; then + reboot_type='warm' + elif [[ x"${SYSTEM_FAST_START}" == x"1" ]]; then + reboot_type='fast' + fi +} + +function modify_ntp_default +{ + cp ${ntp_default_file} ${ntp_temp_file} + sed -e "$1" ${ntp_temp_file} >${ntp_default_file} +} + +sonic-cfggen -d -t /usr/share/sonic/templates/ntp.conf.j2 >/etc/ntp.conf + +get_database_reboot_type +echo "Disabling NTP long jump for reboot type ${reboot_type} ..." +modify_ntp_default "s/NTPD_OPTS='-g'/NTPD_OPTS='-x'/" + +systemctl --no-block restart ntp diff --git a/files/image_config/ntp/ntp-systemd-wrapper b/files/image_config/ntp/ntp-systemd-wrapper new file mode 100644 index 000000000000..1e646f39369d --- /dev/null +++ b/files/image_config/ntp/ntp-systemd-wrapper @@ -0,0 +1,48 @@ +#!/bin/sh + +# This file was originally created automatically as part of default NTP application installation from debian package. +# This is now manually modified for supporting NTP in management VRF. +# When management VRF is enabled, the NTP application should be started using "ip vrf exec mgmt". +# Check has been added to verify the management VRF enabled status and use "ip vrf exec mgmt" when it is enabled. +# This file will be copied to /usr/lib/ntp/ntp-systemd-wrapper file that gets created during build process. + +DAEMON=/usr/sbin/ntpd +PIDFILE=/var/run/ntpd.pid + +if [ -r /etc/default/ntp ]; then + . /etc/default/ntp +fi + +if [ -e /run/ntp.conf.dhcp ]; then + NTPD_OPTS="$NTPD_OPTS -c /run/ntp.conf.dhcp" +fi + +LOCKFILE=/run/lock/ntpdate + +RUNASUSER=ntp +UGID=$(getent passwd $RUNASUSER | cut -f 3,4 -d:) || true +if test "$(uname -s)" = "Linux"; then + NTPD_OPTS="$NTPD_OPTS -u $UGID" +fi + +( + flock -w 180 9 + # when mgmt vrf is configured, ntp starts in mgmt vrf by default unless user configures otherwise + vrfEnabled=$(/usr/local/bin/sonic-cfggen -d -v 'MGMT_VRF_CONFIG["vrf_global"]["mgmtVrfEnabled"]' 2> /dev/null) + vrfConfigured=$(/usr/local/bin/sonic-cfggen -d -v 'NTP["global"]["vrf"]' 2> /dev/null) + if [ "$vrfEnabled" = "true" ] + then + if [ "$vrfConfigured" = "default" ] + then + log_daemon_msg "Starting NTP server in default-vrf for default set as NTP vrf" "ntpd" + start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE $NTPD_OPTS + else + log_daemon_msg "Starting NTP server in mgmt-vrf" "ntpd" + ip vrf exec mgmt start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE $NTPD_OPTS + fi + else + log_daemon_msg "Starting NTP server in default-vrf" "ntpd" + start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE $NTPD_OPTS + fi +) 9>$LOCKFILE + diff --git a/files/image_config/ntp/ntp.conf.j2 b/files/image_config/ntp/ntp.conf.j2 new file mode 100644 index 000000000000..4b763219325c --- /dev/null +++ b/files/image_config/ntp/ntp.conf.j2 @@ -0,0 +1,119 @@ +############################################################################### +# Managed by Ansible +# file: ansible/roles/acs/templates/ntp.conf.j2 +############################################################################### + +# /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 + + +# Enable this if you want statistics to be logged. +#statsdir /var/log/ntpstats/ + +statistics loopstats peerstats clockstats +filegen loopstats file loopstats type day enable +filegen peerstats file peerstats type day enable +filegen clockstats file clockstats type day enable + + +# You do need to talk to an NTP server or two (or three). +#server ntp.your-provider.example + +# pool.ntp.org maps to about 1000 low-stratum NTP servers. Your server will +# pick a different set every time it starts up. Please consider joining the +# pool: +{% for ntp_server in NTP_SERVER %} +server {{ ntp_server }} iburst +{% endfor %} + +#listen on source interface if configured, else +#only listen on MGMT_INTERFACE, LOOPBACK_INTERFACE ip when MGMT_INTERFACE is not defined, or eth0 +# if we don't have both of them (default is to listen on all ip addresses) +interface ignore wildcard + +# set global variable for configured source interface name +# set global boolean to indicate if the ip of the configured source interface is configured +# if the source interface is configured but no ip on that interface, then listen on another +# interface based on existing logic +{%- macro check_ip_on_interface(interface_name, table_name) %} + {%- if table_name %} + {%- for (name, source_prefix) in table_name|pfx_filter %} + {%- if source_prefix and name == interface_name %} +true + {%- endif %} + {%- endfor %} + {%- endif %} +{%- endmacro %} + +{% set ns = namespace(source_intf = "") %} +{% set ns = namespace(source_intf_ip = 'false') %} +{% if (NTP) and (NTP['global']['src_intf']) %} + {% set ns.source_intf = (NTP['global']['src_intf']) %} + {% if ns.source_intf != "" %} + {% if ns.source_intf == "eth0" %} + {% set ns.source_intf_ip = 'true' %} + {% elif ns.source_intf.startswith('Vlan') %} + {% set ns.source_intf_ip = check_ip_on_interface(ns.source_intf, VLAN_INTERFACE) %} + {% elif ns.source_intf.startswith('Ethernet') %} + {% set ns.source_intf_ip = check_ip_on_interface(ns.source_intf, INTERFACE) %} + {% elif ns.source_intf.startswith('PortChannel') %} + {% set ns.source_intf_ip = check_ip_on_interface(ns.source_intf, PORTCHANNEL_INTERFACE) %} + {% elif ns.source_intf.startswith('Loopback') %} + {% set ns.source_intf_ip = check_ip_on_interface(ns.source_intf, LOOPBACK_INTERFACE) %} + {% endif %} + {% endif %} +{% endif %} + +{% if ns.source_intf_ip == 'true' %} +interface listen {{ns.source_intf}} +{% elif (NTP) and NTP['global']['vrf'] == 'mgmt' %} +interface listen eth0 +{% elif MGMT_INTERFACE %} +{% for (mgmt_intf, mgmt_prefix) in MGMT_INTERFACE|pfx_filter %} +interface listen {{ mgmt_prefix | ip }} +{% endfor %} +{% elif LOOPBACK_INTERFACE %} +{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %} +{% if prefix | ipv4 and name == 'Loopback0' %} +interface listen {{ prefix | ip }} +{% endif %} +{% endfor %} +{% else %} +interface listen eth0 +{% endif %} +interface listen 127.0.0.1 + +# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for +# details. The web page +# might also be helpful. +# +# Note that "restrict" applies to both servers and clients, so a configuration +# that might be intended to block requests from certain clients could also end +# up blocking replies from your own upstream servers. + +# By default, exchange time with everybody, but don't allow configuration. +restrict -4 default kod notrap nomodify nopeer noquery +restrict -6 default kod notrap nomodify nopeer noquery + +# Local users may interrogate the ntp server more closely. +restrict 127.0.0.1 +restrict ::1 + +# Clients from this (example!) subnet have unlimited access, but only if +# cryptographically authenticated. +#restrict 192.168.123.0 mask 255.255.255.0 notrust + + +# If you want to provide time to your local subnet, change the next line. +# (Again, the address is an example only.) +#broadcast 192.168.123.255 + +# If you want to listen to time broadcasts on your local subnet, de-comment the +# next lines. Please do this only if you trust everybody on the network! +#disable auth +#broadcastclient diff --git a/files/image_config/ntp/ntp.service b/files/image_config/ntp/ntp.service new file mode 100644 index 000000000000..acfd7e17266a --- /dev/null +++ b/files/image_config/ntp/ntp.service @@ -0,0 +1,16 @@ +[Unit] +Description=Network Time Service +Documentation=man:ntpd(8) +After=network.target +Conflicts=systemd-timesyncd.service +StartLimitIntervalSec=0 + +[Service] +Type=forking +# Debian uses a shell wrapper to process /etc/default/ntp +# and select DHCP-provided NTP servers if available +ExecStart=/usr/lib/ntp/ntp-systemd-wrapper +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/pcie-check/pcie-check.service b/files/image_config/pcie-check/pcie-check.service new file mode 100644 index 000000000000..9df04ea840bc --- /dev/null +++ b/files/image_config/pcie-check/pcie-check.service @@ -0,0 +1,10 @@ +[Unit] +Description=Check the PCIe device presence and status +After=rc.local.service database.service + +[Service] +Type=simple +ExecStart=/usr/bin/pcie-check.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/pcie-check/pcie-check.sh b/files/image_config/pcie-check/pcie-check.sh new file mode 100755 index 000000000000..01a952d01374 --- /dev/null +++ b/files/image_config/pcie-check/pcie-check.sh @@ -0,0 +1,59 @@ +#! /bin/bash +## Check the platform PCIe device presence and status + +VERBOSE="no" +RESULTS="PCIe Device Checking All Test" +EXPECTED="PCIe Device Checking All Test ----------->>> PASSED" +MAX_WAIT_SECONDS=15 + +function debug() +{ + /usr/bin/logger "$0 : $1" + if [[ x"${VERBOSE}" == x"yes" ]]; then + echo "$(date) $0: $1" + fi +} + +function check_and_rescan_pcie_devices() +{ + PCIE_CHK_CMD='sudo pcieutil check | grep "$RESULTS"' + PLATFORM=$(sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + if [ ! -f /usr/share/sonic/device/$PLATFORM/pcie.yaml ]; then + debug "pcie.yaml does not exist! Can't check PCIe status!" + exit + fi + + begin=$SECONDS + end=$((begin + MAX_WAIT_SECONDS)) + rescan_time=$((MAX_WAIT_SECONDS/2)) + rescan_time=$((begin + rescan_time)) + + while true + do + now=$SECONDS + if [[ $now -gt $end ]]; then + break + fi + + if [ "$(eval $PCIE_CHK_CMD)" = "$EXPECTED" ]; then + redis-cli -n 6 HSET "PCIE_DEVICES" "status" "PASSED" + debug "PCIe check passed" + exit + else + debug "sleep 0.1 seconds" + sleep 0.1 + fi + + if [ $now -gt $rescan_time ]; then + debug "PCIe check failed, try pci bus rescan" + echo 1 > /sys/bus/pci/rescan + rescan_time=$end + fi + + done + debug "PCIe check failed" + redis-cli -n 6 HSET "PCIE_DEVICES" "status" "FAILED" +} + +check_and_rescan_pcie_devices diff --git a/files/image_config/platform/linux_kernel_bde.conf b/files/image_config/platform/linux_kernel_bde.conf new file mode 100644 index 000000000000..5f2b1c4e644d --- /dev/null +++ b/files/image_config/platform/linux_kernel_bde.conf @@ -0,0 +1 @@ +blacklist linux_kernel_bde diff --git a/files/image_config/platform/rc.local b/files/image_config/platform/rc.local new file mode 100755 index 000000000000..b299f9fe2bba --- /dev/null +++ b/files/image_config/platform/rc.local @@ -0,0 +1,371 @@ +#!/bin/sh -x +# +# rc.local +# +# This script is executed at the end of each multiuser runlevel. +# Make sure that the script will "exit 0" on success or any other +# value on error. +# +# In order to enable or disable this script just change the execution +# bits. +# +# By default this script does nothing. + +SONIC_VERSION=$(cat /etc/sonic/sonic_version.yml | grep "build_version" | sed -e "s/build_version: //g;s/'//g") +FIRST_BOOT_FILE="/host/image-${SONIC_VERSION}/platform/firsttime" + +# Move sonic-environment to /etc/sonic +SONIC_CONFIG_DIR="/host/image-${SONIC_VERSION}/sonic-config" +SONIC_ENV_FILE=${SONIC_CONFIG_DIR}/sonic-environment +if [ -d ${SONIC_CONFIG_DIR} -a -f ${SONIC_ENV_FILE} ]; then + echo "moving file ${SONIC_ENV_FILE} to /etc/sonic" 1>&2 + mv ${SONIC_ENV_FILE} /etc/sonic +fi + +# In case the unit is migrating from another NOS, save the logs +log_migration() { + echo $1 >> /host/migration/migration.log +} + +# Import files from another NOS's partition onto SONiC +nos_migration_import() { + [ -f $1 ] && cp $1 $2 || log_migration "ERROR: $1 not found!" +} + +# While migrating form another NOS, we need to preserve the MAC addresses +# of eth0 (and eventually switchports). +# Update the eth0 mac and also the EEPROM using ethtool so that subsequent +# reboots use the NOS's mac. +# Input : mgmt_interface.cfg file imported from the previous NOS. +update_mgmt_interface_macaddr() { + mgmt_config=$1 + if [ ! -f "$mgmt_config" ]; then + log_migration "ERROR : unable update eth0 MAC : $mgmt_config not found!" + return + fi + + # Save the previous NOS's mac + old_mac=`ip link show eth0 | grep ether | awk '{print $2}'` + [ -z "$old_mac" ] && log_migration "Unable to retrieve old mac address !" && return + + # Extract, validate and set the eth0's mac address for the current session + new_mac=$(grep "macaddr" $mgmt_config | awk -F'=' '{print $2}') + log_migration "Setting eth0 mac as $new_mac." + if [ `echo $new_mac | egrep "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$"` ]; then + ip link set eth0 down + ip link set eth0 address $new_mac + ip link set eth0 up + else + log_migration "ERROR: mac imported from NOS is invalid : $new_mac !" + return + fi + + # Get the ethtool magic and offset for changing the mac address in the EEPROM + ethtool_magic=$(grep "ethtool_magic" $mgmt_config | awk -F'=' '{print $2}') + ethtool_offset=$(grep "ethtool_offset" $mgmt_config | awk -F'=' '{print $2}') + if [ -z "$ethtool_magic" ] || [ -z "$ethtool_offset" ]; then + log_migration "Unable to retrieve ethtool params ($ethtool_magic,$ethtool_offset)" + return + fi + + log_migration "eth0 mac in EEPROM before update:" + ethtool -e eth0 offset $ethtool_offset length 6 >> /host/migration/migration.log + + # Update the mac address in the EEPROM for subsequent reboots + # Write only changed octets + for i in 1 2 3 4 5 6; do + offset=$(($ethtool_offset+$i-1)) + old_mac_octet="$(echo $old_mac | cut -d":" -f$i)" + new_mac_octet="$(echo $new_mac | cut -d":" -f$i)" + + if [ "$old_mac_octet" != "$new_mac_octet" ]; then + ethtool -E eth0 magic $ethtool_magic offset $offset value 0x$new_mac_octet + if [ $? != 0 ]; then + log_migration "ERROR: unable to update eth0 EEPROM!" + log_migration "index $i, magic $ethtool_magic offset $offset, value $new_mac_octet" + return + fi + fi + done + + log_migration "eth0 mac in EEPROM after update:" + ethtool -e eth0 offset $ethtool_offset length 6 >> /host/migration/migration.log +} + +migrate_nos_configuration() +{ + rm -rf /host/migration + mkdir -p /host/migration + + # Extract the previous NOS's partition that contains the migration artifacts + set -- $(cat /proc/cmdline) + for x in "$@"; do + case "$x" in + nos-config-part=*) + nos_dev="${x#nos-config-part=}" + ;; + SONIC_BOOT_TYPE=fast*) + sonic_fast_reboot=true + ;; + esac + done + + if [ -n "$nos_dev" ]; then + # remove nos-config-part from cmdline + sed -r -i.bak "s/nos-config-part=[^[:space:]]+//" /host/grub/grub.cfg + + # Mount the previous NOS's partition + NOS_DIR=/mnt/nos_migration + MG_GZFILE=$NOS_DIR/minigraph.xml.gz.base64.txt + MG_FILE=$NOS_DIR/minigraph.xml + ACL_GZFILE=$NOS_DIR/acl.json.gz.base64.txt + ACL_FILE=$NOS_DIR/acl.json + SNMP_FILE=$NOS_DIR/snmp.yml + mkdir -p $NOS_DIR + + mount $nos_dev $NOS_DIR + if [ $? != 0 ]; then + log_migration "ERROR: cannot mount $nos_dev" + else + + # decode & unzip minigraph.xml.gz.base64.txt + [ -f $MG_GZFILE ] && /usr/bin/base64 -d $MG_GZFILE | /bin/gunzip > $MG_FILE + [ -f $ACL_GZFILE ] && /usr/bin/base64 -d $ACL_GZFILE | /bin/gunzip > $ACL_FILE + + # Copy relevant files + nos_migration_import $NOS_DIR/mgmt_interface.cfg /host/migration + nos_migration_import $MG_FILE /host/migration + nos_migration_import $ACL_FILE /host/migration + nos_migration_import $SNMP_FILE /host/migration + + if [ "$sonic_fast_reboot" == true ]; then + mkdir -p /host/fast-reboot + nos_migration_import $NOS_DIR/arp.json /host/fast-reboot + nos_migration_import $NOS_DIR/fdb.json /host/fast-reboot + nos_migration_import $NOS_DIR/default_routes.json /host/fast-reboot + fi + + umount $NOS_DIR + rmdir $NOS_DIR + fi + + [ -f /host/migration/mgmt_interface.cfg ] && update_mgmt_interface_macaddr /host/migration/mgmt_interface.cfg + + migration="TRUE" + fi +} + +firsttime_exit() { + rm -rf $FIRST_BOOT_FILE + exit 0 +} + +# Given a string of tuples of the form field=value, extract the value for a field +# In : $string, $field +# Out: $value +value_extract() { + set -- $string + for x in "$@"; do + case "$x" in + $field=*) + value="${x#$field=}" + esac + done +} + +program_console_speed() +{ + speed=$(cat /proc/cmdline | grep -Eo 'console=ttyS[0-9]+,[0-9]+' | cut -d "," -f2) + if [ -z "$speed" ]; then + CONSOLE_SPEED=9600 + else + CONSOLE_SPEED=$speed + fi + + sed -i "s|\-\-keep\-baud .* %I| $CONSOLE_SPEED %I|g" /lib/systemd/system/serial-getty@.service + systemctl daemon-reload +} + + +#### Begin Main Body #### + +logger "SONiC version ${SONIC_VERSION} starting up..." + +# If the machine.conf is absent, it indicates that the unit booted +# into SONiC from another NOS. Extract the machine.conf from ONIE. +grub_installation_needed="" +if [ ! -e /host/machine.conf ]; then + onie_dev=$(blkid | grep ONIE-BOOT | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//') + mkdir -p /mnt/onie-boot + mount $onie_dev /mnt/onie-boot + onie_grub_cfg=/mnt/onie-boot/onie/grub/grub-machine.cfg + + if [ ! -e $onie_grub_cfg ]; then + log_migration "$onie_grub_cfg not found" + else + . ./$onie_grub_cfg + grep = $onie_grub_cfg | sed -e 's/onie_//' -e 's/=.*$//' | while read var ; do + eval val='$'onie_$var + echo "onie_${var}=${val}" >> /host/machine.conf + done + grub_installation_needed="TRUE" + fi + + umount /mnt/onie-boot +fi + +migrate_nos_configuration + +. /host/machine.conf + +program_console_speed + +if [ -f $FIRST_BOOT_FILE ]; then + + echo "First boot detected. Performing first boot tasks..." + + if [ -n "$aboot_platform" ]; then + platform=$aboot_platform + elif [ -n "$onie_platform" ]; then + platform=$onie_platform + else + echo "Unknown SONiC platform" + firsttime_exit + fi + + # Try to take old configuration saved during installation + # and create a flag in /tmp/ to let updategraph service know + if [ -d /host/old_config ]; then + mv -f /host/old_config /etc/sonic/ + rm -rf /etc/sonic/old_config/old_config + touch /tmp/pending_config_migration + elif [ -f /host/minigraph.xml ]; then + mkdir -p /etc/sonic/old_config + mv /host/minigraph.xml /etc/sonic/old_config/ + [ -f /host/acl.json ] && mv /host/acl.json /etc/sonic/old_config/ + [ -f /host/snmp.yml ] && mv /host/snmp.yml /etc/sonic/old_config/ + touch /tmp/pending_config_migration + elif [ -n "$migration" ] && [ -f /host/migration/minigraph.xml ]; then + mkdir -p /etc/sonic/old_config + mv /host/migration/minigraph.xml /etc/sonic/old_config/ + [ -f /host/migration/acl.json ] && mv /host/migration/acl.json /etc/sonic/old_config/ + [ -f /host/migration/snmp.yml ] && mv /host/migration/snmp.yml /etc/sonic/old_config/ + touch /tmp/pending_config_migration + [ -f /etc/sonic/updategraph.conf ] && sed -i -e "s/enabled=false/enabled=true/g" /etc/sonic/updategraph.conf + else + touch /tmp/pending_config_initialization + fi + + # Notify firstboot to Platform, to use it for reboot-cause + touch /tmp/notify_firstboot_to_platform + + # Create /host/reboot-cause/platform/ directory + # can be used to track last reboot reason by some platforms + if [ ! -d /host/reboot-cause/platform ]; then + mkdir -p /host/reboot-cause/platform + fi + + if [ -d /host/image-$SONIC_VERSION/platform/$platform ]; then + dpkg -i /host/image-$SONIC_VERSION/platform/$platform/*.deb + fi + + sync + + # If the unit booted into SONiC from another NOS's grub, + # we now install a grub for SONiC. + if [ -n "$onie_platform" ] && [ -n "$grub_installation_needed" ]; then + + grub_bin=$(ls /host/image-$SONIC_VERSION/platform/x86_64-grub/grub-pc-bin*.deb 2> /dev/null) + if [ -z "$grub_bin" ]; then + log_migration "Unable to locate grub package !" + firsttime_exit + fi + + dpkg -i $grub_bin > /dev/null 2>&1 + if [ $? != 0 ]; then + log_migration "Unable to install grub package !" + firsttime_exit + fi + + # Determine the block device to install grub + sonic_dev=$(blkid | grep SONiC-OS | head -n 1 | awk '{print $1}' | sed -e 's/[0-9]:.*$//') + if [ -z "$sonic_dev" ]; then + log_migration "Unable to determine sonic partition !" + firsttime_exit + fi + + grub-install --boot-directory=/host --recheck $sonic_dev 2>/dev/null + if [ $? != 0 ]; then + log_migration "grub install failed !" + firsttime_exit + fi + + # The SONiC "raw" build mode has already generated a proto grub.cfg + # as part of the migration. Platform specific constants need to be + # retrieved from installer.conf (if present) and assigned. + . /usr/share/sonic/device/$platform/installer.conf + + if [ ! -z "$CONSOLE_PORT" ]; then + field="\-\-port" + string=$(grep $field /host/grub.cfg) + value_extract $string $field + console_port=$value + if [ ! -z "$console_port" ] && [ "$console_port" != "$CONSOLE_PORT" ]; then + sed -i -e "s/\-\-port=$console_port/\-\-port=$CONSOLE_PORT/g" /host/grub.cfg + fi + log_migration "grub.cfg console port=$console_port & installer.conf CONSOLE_PORT=$CONSOLE_PORT" + fi + + if [ ! -z "$CONSOLE_DEV" ]; then + field="console" + string=$(grep $field /host/grub.cfg) + value_extract $string $field + console_dev_name=$(echo $value | sed -e "s/^.*=//" -e "s/,.*//") + console_dev="${console_dev_name#ttyS}" + if [ "$console_dev" != "$CONSOLE_DEV" ]; then + sed -i -e "s/console=ttyS$console_dev/console=ttyS$CONSOLE_DEV/g" /host/grub.cfg + fi + log_migration "grub.cfg console dev=$console_dev & installer.conf CONSOLE_DEV=$CONSOLE_DEV" + fi + + if [ ! -z "$VAR_LOG_SIZE" ]; then + field="var_log_size" + string=$(grep $field /host/grub.cfg) + value_extract $string $field + var_log_size=$value + if [ ! -z "$var_log_size" ] && [ "$var_log_size" != "$VAR_LOG_SIZE" ]; then + sed -i -e "s/var_log_size=$var_log_size/var_log_size=$VAR_LOG_SIZE/g" /host/grub.cfg + fi + log_migration "grub.cfg var_log_size=$var_log_size & installer.conf VAR_LOG_SIZE=$VAR_LOG_SIZE" + fi + + # Set the root based on the label + sonic_root=$(blkid | grep SONiC-OS | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//') + sonic_root=$(echo "$sonic_root" | sed 's/\//\\\//g') + sed -i -e "s/%%SONIC_ROOT%%/$sonic_root/g" /host/grub.cfg + + # Add the Diag and ONIE entries + mount $onie_dev /mnt/onie-boot + . /mnt/onie-boot/onie/grub.d/50_onie_grub >> /host/grub.cfg + umount /mnt/onie-boot + + # Initialize the SONiC's grub config + mv /host/grub.cfg /host/grub/grub.cfg + fi + + # Create dir where following scripts put their output files + mkdir -p /var/platform + + # Kdump tools configuration + sed -i -e "s/__PLATFORM__/$platform/g" /etc/default/kdump-tools + + firsttime_exit +fi + +# Copy the fsck log into syslog +if [ -f /var/log/fsck.log.gz ]; then + gunzip -d -c /var/log/fsck.log.gz | logger -t "FSCK" + rm -f /var/log/fsck.log.gz +fi + +exit 0 diff --git a/files/image_config/rsyslog/rsyslog-config.service b/files/image_config/rsyslog/rsyslog-config.service new file mode 100644 index 000000000000..ee62a36ccf2d --- /dev/null +++ b/files/image_config/rsyslog/rsyslog-config.service @@ -0,0 +1,11 @@ +[Unit] +Description=Update rsyslog configuration +Requires=updategraph.service +After=updategraph.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/rsyslog-config.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/rsyslog/rsyslog-config.sh b/files/image_config/rsyslog/rsyslog-config.sh new file mode 100755 index 000000000000..26767d84fbe0 --- /dev/null +++ b/files/image_config/rsyslog/rsyslog-config.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + +# Parse the device specific asic conf file, if it exists +ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf +if [ -f "$ASIC_CONF" ]; then + source $ASIC_CONF +fi + +# On Multi NPU platforms we need to start the rsyslog server on the docker0 ip address +# for the syslogs from the containers in the namespaces to work. +# on Single NPU platforms we continue to use loopback adddres + +if [[ ($NUM_ASIC -gt 1) ]]; then + udp_server_ip=$(ip -o -4 addr list docker0 | awk '{print $4}' | cut -d/ -f1) +else + udp_server_ip=$(ip -o -4 addr list lo scope host | awk '{print $4}' | cut -d/ -f1) +fi + +sonic-cfggen -d -t /usr/share/sonic/templates/rsyslog.conf.j2 -a "{\"udp_server_ip\": \"$udp_server_ip\"}" >/etc/rsyslog.conf + +systemctl restart rsyslog diff --git a/files/image_config/rsyslog/rsyslog-container.conf.j2 b/files/image_config/rsyslog/rsyslog-container.conf.j2 new file mode 100644 index 000000000000..d17fbb6767ba --- /dev/null +++ b/files/image_config/rsyslog/rsyslog-container.conf.j2 @@ -0,0 +1,76 @@ +# +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html + + +################# +#### MODULES #### +################# + +$ModLoad imuxsock # provides support for local system logging + +# +# Set a rate limit on messages from the container +# +$SystemLogRateLimitInterval 300 +$SystemLogRateLimitBurst 20000 + +#$ModLoad imklog # provides kernel logging support +#$ModLoad immark # provides --MARK-- message capability + +# provides UDP syslog reception +#$ModLoad imudp +#$UDPServerRun 514 + +# provides TCP syslog reception +#$ModLoad imtcp +#$InputTCPServerRun 514 + + +########################### +#### GLOBAL DIRECTIVES #### +########################### + +# Set remote syslog server +template (name="ForwardFormatInContainer" type="string" string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% {{container_name}}#%syslogtag%%msg:::sp-if-no-1st-sp%%msg%") +*.* action(type="omfwd" target="{{target_ip}}" port="514" protocol="udp" Template="ForwardFormatInContainer") + +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Define a custom template +$template SONiCFileFormat,"%TIMESTAMP%.%timestamp:::date-subseconds% %HOSTNAME% %syslogseverity-text:::uppercase% {{container_name}}#%syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" +$ActionFileDefaultTemplate SONiCFileFormat + +# +# Set the default permissions for all log files. +# +$FileOwner root +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 + +# +# Where to place spool and state files +# +$WorkDirectory /var/spool/rsyslog + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + +# +# Suppress duplicate messages and report "message repeated n times" +# +$RepeatedMsgReduction on + +############### +#### RULES #### +############### diff --git a/files/image_config/rsyslog/rsyslog.conf.j2 b/files/image_config/rsyslog/rsyslog.conf.j2 new file mode 100644 index 000000000000..37410293a45f --- /dev/null +++ b/files/image_config/rsyslog/rsyslog.conf.j2 @@ -0,0 +1,74 @@ +############################################################################### +# Managed by Ansible +# file: ansible/roles/acs/templates/rsyslog.conf.j2 +############################################################################### +# +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html + + +################# +#### MODULES #### +################# + +$ModLoad imuxsock # provides support for local system logging +$ModLoad imklog # provides kernel logging support +#$ModLoad immark # provides --MARK-- message capability + +# provides UDP syslog reception +$ModLoad imudp +$UDPServerAddress {{udp_server_ip}} #bind to localhost before udp server run +$UDPServerRun 514 + +# provides TCP syslog reception +#$ModLoad imtcp +#$InputTCPServerRun 514 + + +########################### +#### GLOBAL DIRECTIVES #### +########################### +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Define a custom template +$template SONiCFileFormat,"%timegenerated%.%timegenerated:::date-subseconds% %HOSTNAME% %syslogseverity-text:::uppercase% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" +$ActionFileDefaultTemplate SONiCFileFormat + +#Set remote syslog server +{% for server in SYSLOG_SERVER %} +*.* @[{{ server }}]:514;SONiCFileFormat +{% endfor %} + +# +# Set the default permissions for all log files. +# +$FileOwner root +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 + +# +# Where to place spool and state files +# +$WorkDirectory /var/spool/rsyslog + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + +# +# Suppress duplicate messages and report "message repeated n times" +# +$RepeatedMsgReduction on + +############### +#### RULES #### +############### diff --git a/files/image_config/rsyslog/rsyslog.d/00-sonic.conf b/files/image_config/rsyslog/rsyslog.d/00-sonic.conf new file mode 100644 index 000000000000..bc69af74b8b3 --- /dev/null +++ b/files/image_config/rsyslog/rsyslog.d/00-sonic.conf @@ -0,0 +1,24 @@ +## Quagga rules + +if re_match($programname, "bgp[0-9]*#(frr|zebra|staticd|watchfrr)") then { + /var/log/frr/zebra.log + stop +} + +if re_match($programname, "bgp[0-9]*#bgpd") then { + /var/log/frr/bgpd.log + stop +} + +## Teamd rules + +if $programname contains "teamd_" then { + /var/log/teamd.log + stop +} + +## telemetry rules +if $msg startswith " telemetry" or ($msg startswith " dialout" )then { + /var/log/telemetry.log + stop +} diff --git a/files/image_config/rsyslog/rsyslog.d/99-default.conf b/files/image_config/rsyslog/rsyslog.d/99-default.conf new file mode 100644 index 000000000000..77609410c57a --- /dev/null +++ b/files/image_config/rsyslog/rsyslog.d/99-default.conf @@ -0,0 +1,27 @@ +# +# First some standard log files. Log by facility. +# + +# Log all facilities to /var/log/syslog except cron, auth +# and authpriv. They are noisy - log them to their own files +*.*;cron,auth,authpriv.none -/var/log/syslog +auth,authpriv.* /var/log/auth.log +cron.* /var/log/cron.log + +# +# Emergencies are sent to everybody logged in. +# +*.emerg :omusrmsg:* + +# The named pipe /dev/xconsole is for the `xconsole' utility. To use it, +# you must invoke `xconsole' with the `-file' option: +# +# $ xconsole -file /dev/xconsole [...] +# +# NOTE: adjust the list below, or you'll go crazy if you have a reasonably +# busy site.. +# +#daemon.*;mail.*;\ +# news.err;\ +# *.=debug;*.=info;\ +# *.=notice;*.=warn |/dev/xconsole diff --git a/files/image_config/secureboot/allowlist_paths.conf b/files/image_config/secureboot/allowlist_paths.conf new file mode 100644 index 000000000000..f1021f5c13e9 --- /dev/null +++ b/files/image_config/secureboot/allowlist_paths.conf @@ -0,0 +1,37 @@ +home/.* +var/core/.* +var/crash/.* +var/log/.* +etc/adjtime +etc/default/ntp +etc/dhcp/dhclient.conf +etc/ebtables.filter +etc/group +etc/gshadow +etc/hostname +etc/hosts +etc/machine-id +etc/network/interfaces +etc/nsswitch.conf +etc/ntp.conf +etc/pam.d/common-auth-sonic +etc/pam.d/sshd +etc/pam.d/login +etc/pam.d/sshd.old +etc/passwd +etc/rsyslog.conf +etc/shadow +etc/sonic/acl.json +etc/sonic/config_db.json +etc/sonic/minigraph.xml +etc/sonic/old_config/.* +etc/sonic/snmp.yml +etc/sonic/sonic-environment +etc/sonic/updategraph.conf +etc/ssh/ssh_host_rsa_key.pub +etc/ssh/ssh_host_rsa_key +etc/subgid +etc/subuid +etc/tacplus_nss.conf +etc/tacplus_user +lib/systemd/system/serial-getty@.service diff --git a/files/image_config/secureboot/allowlist_paths.md b/files/image_config/secureboot/allowlist_paths.md new file mode 100644 index 000000000000..7ce86b9bc90c --- /dev/null +++ b/files/image_config/secureboot/allowlist_paths.md @@ -0,0 +1,11 @@ +# Configuration Guide +It is the patterns of the relative paths in /host/image-{{hash}}/rw folder. +The patterns will not be used if the Sonic Secure Boot feature is not enabled. +The files that are not in the allowlist will be removed when the Sonic System cold reboot. + +### Example config to add all the files in a folder to allowlist +home/.* + +### Example config to add a file to allowlist +etc/nsswitch.conf + diff --git a/files/image_config/snmp/snmp.yml b/files/image_config/snmp/snmp.yml new file mode 100644 index 000000000000..117619975fbb --- /dev/null +++ b/files/image_config/snmp/snmp.yml @@ -0,0 +1,2 @@ +snmp_rocommunity: public +snmp_location: public diff --git a/files/image_config/sudoers/sudoers b/files/image_config/sudoers/sudoers new file mode 100644 index 000000000000..fbe4cf1f7f91 --- /dev/null +++ b/files/image_config/sudoers/sudoers @@ -0,0 +1,63 @@ +# +# This file MUST be edited with the 'visudo' command as root. +# +# Please consider adding local content in /etc/sudoers.d/ instead of +# directly modifying this file. +# +# See the man page for details on how to write a sudoers file. +# +Defaults env_reset +#Defaults mail_badpass +Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +Defaults env_keep += "SONIC_CLI_IFACE_MODE" +Defaults env_keep += "VTYSH_PAGER" +Defaults lecture_file = /etc/sudoers.lecture + +# Host alias specification + +# User alias specification + +# Cmnd alias specification +# Note: bcmcmd is dangerous for users in read only netgroups because it may operate ASIC +Cmnd_Alias READ_ONLY_CMDS = /bin/cat /var/log/syslog*, \ + /bin/ip netns identify [0-9]*, \ + /sbin/brctl show, \ + /usr/bin/docker exec snmp cat /etc/snmp/snmpd.conf, \ + /usr/bin/docker exec bgp cat /etc/quagga/bgpd.conf, \ + /usr/bin/docker images *, \ + /usr/bin/docker ps *, \ + /usr/bin/docker ps, \ + /usr/bin/lldpctl, \ + /usr/bin/sensors, \ + /usr/bin/tail -F /var/log/syslog, \ + /usr/bin/vtysh -c show *, \ + /usr/bin/vtysh -n [0-9] -c show *, \ + /usr/local/bin/decode-syseeprom, \ + /usr/local/bin/generate_dump, \ + /usr/local/bin/ipintutil, \ + /usr/local/bin/lldpshow, \ + /usr/local/bin/pcieutil *, \ + /usr/local/bin/psuutil *, \ + /usr/local/bin/sonic-installer list, \ + /usr/local/bin/sfputil show * + + +Cmnd_Alias PASSWD_CMDS = /usr/local/bin/config tacacs passkey *, \ + /usr/sbin/chpasswd * + +# User privilege specification +root ALL=(ALL:ALL) ALL + +# Allow all users to execute read only commands +ALL ALL=NOPASSWD: READ_ONLY_CMDS + +# Allow members of group sudo to execute any command +%sudo ALL=(ALL:ALL) NOPASSWD: ALL + +# Prevent password related command into syslog +Defaults!PASSWD_CMDS !syslog + +# See sudoers(5) for more information on "#include" directives: + +#includedir /etc/sudoers.d + diff --git a/files/image_config/sudoers/sudoers.lecture b/files/image_config/sudoers/sudoers.lecture new file mode 100644 index 000000000000..e89340092c70 --- /dev/null +++ b/files/image_config/sudoers/sudoers.lecture @@ -0,0 +1,4 @@ + +Make sure your account has RW permission to current device. +Otherwise sudo requests will be rejected. + diff --git a/files/image_config/sysctl/sysctl-net.conf b/files/image_config/sysctl/sysctl-net.conf new file mode 100644 index 000000000000..84c24c8b0a8a --- /dev/null +++ b/files/image_config/sysctl/sysctl-net.conf @@ -0,0 +1,39 @@ +# All the sysctl for ipv4/ipv6 network. +# Same will be used in host or docker namespace +# It should be provided as key=value format for parsing +net.ipv6.conf.all.disable_ipv6=0 +net.ipv4.conf.default.forwarding=1 +net.ipv4.conf.all.forwarding=1 +net.ipv4.conf.eth0.forwarding=0 +net.ipv4.conf.default.arp_accept=0 +net.ipv4.conf.default.arp_announce=0 +net.ipv4.conf.default.arp_filter=0 +net.ipv4.conf.default.arp_notify=0 +net.ipv4.conf.default.arp_ignore=0 +net.ipv4.conf.all.arp_accept=0 +net.ipv4.conf.all.arp_announce=1 +net.ipv4.conf.all.arp_filter=0 +net.ipv4.conf.all.arp_notify=1 +net.ipv4.conf.all.arp_ignore=2 +net.ipv4.neigh.default.base_reachable_time_ms=1800000 +net.ipv6.neigh.default.base_reachable_time_ms=1800000 +net.ipv4.neigh.default.gc_thresh1=1024 +net.ipv6.neigh.default.gc_thresh1=1024 +net.ipv4.neigh.default.gc_thresh2=2048 +net.ipv6.neigh.default.gc_thresh2=2048 +net.ipv4.neigh.default.gc_thresh3=4096 +net.ipv6.neigh.default.gc_thresh3=4096 +net.ipv6.conf.default.forwarding=1 +net.ipv6.conf.all.forwarding=1 +net.ipv6.conf.eth0.forwarding=0 +net.ipv6.conf.default.accept_dad=0 +net.ipv6.conf.all.accept_dad=0 +net.ipv6.conf.eth0.accept_dad=0 +net.ipv6.conf.default.keep_addr_on_down=1 +net.ipv6.conf.all.keep_addr_on_down=1 +net.ipv6.conf.eth0.keep_addr_on_down=1 +net.ipv4.tcp_l3mdev_accept=1 +net.ipv4.udp_l3mdev_accept=1 +net.core.rmem_max=3145728 +net.core.wmem_max=3145728 +net.core.somaxconn=512 diff --git a/files/image_config/syslog/host_umount.sh b/files/image_config/syslog/host_umount.sh new file mode 100755 index 000000000000..6a057f16d582 --- /dev/null +++ b/files/image_config/syslog/host_umount.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# This script is invoked at the closure of syslog socket during reboot +# This will stop journal services, unmount /var/log and delete loop device +# associated to /host to ensure proper unmount of /host + +journal_stop() { + systemctl stop systemd-journald.service +} + +delete_loop_device() { + umount /var/log + if [[ $? -ne 0 ]] + then + exit 0 + fi + loop_exist=$(losetup -a | grep loop1 | wc -l) + if [ $loop_exist -ne 0 ]; then + losetup -d /dev/loop1 + fi +} + +case "$1" in + journal_stop|delete_loop_device) + $1 + ;; + *) + echo "Usage: $0 {journal_stop|delete_loop_device}" >&2 + exit 1 + ;; +esac + diff --git a/files/image_config/syslog/override.conf b/files/image_config/syslog/override.conf new file mode 100644 index 000000000000..5806cce0ecdc --- /dev/null +++ b/files/image_config/syslog/override.conf @@ -0,0 +1,6 @@ +[Unit] +After=var-log.mount host.mount local-fs.target + +[Socket] +ExecStopPre=/usr/bin/host_umount.sh journal_stop +ExecStopPost=/usr/bin/host_umount.sh delete_loop_device diff --git a/files/image_config/system-health/system-health.service b/files/image_config/system-health/system-health.service new file mode 100644 index 000000000000..3de6a51584cb --- /dev/null +++ b/files/image_config/system-health/system-health.service @@ -0,0 +1,11 @@ +[Unit] +Description=SONiC system health monitor +Requires=database.service updategraph.service +After=database.service updategraph.service + +[Service] +ExecStart=/usr/local/bin/healthd +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/systemd/journald.conf b/files/image_config/systemd/journald.conf new file mode 100644 index 000000000000..214bd099a285 --- /dev/null +++ b/files/image_config/systemd/journald.conf @@ -0,0 +1,35 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# See journald.conf(5) for details + +[Journal] +#Storage=auto +#Compress=yes +#Seal=yes +#SplitMode=uid +#SyncIntervalSec=5m +#RateLimitIntervalSec=30s +#RateLimitBurst=1000 +SystemMaxUse=50M +#SystemKeepFree= +#SystemMaxFileSize= +RuntimeMaxUse=50M +#RuntimeKeepFree= +#RuntimeMaxFileSize= +#MaxRetentionSec= +#MaxFileSec=1month +#ForwardToSyslog=yes +#ForwardToKMsg=no +#ForwardToConsole=no +#ForwardToWall=yes +#TTYPath=/dev/console +#MaxLevelStore=debug +#MaxLevelSyslog=debug +#MaxLevelKMsg=notice +#MaxLevelConsole=info +#MaxLevelWall=emerg 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..2f038095be62 --- /dev/null +++ b/files/image_config/topology/topology.sh @@ -0,0 +1,59 @@ +#!/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. +# + +get_hwsku() { + # Get HWSKU from config_db. If HWSKU is not available in config_db + # get HWSKU from minigraph.xml if minigraph file exists. + HWSKU=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hwsku"]' 2>&1` + if [[ $? -ne 0 || $HWSKU == "" ]]; then + if [[ -f "/etc/sonic/minigraph.xml" ]]; then + HWSKU=`sonic-cfggen -m /etc/sonic/minigraph.xml -v "DEVICE_METADATA['localhost']['hwsku']" 2>&1` + if [[ $? -ne 0 || $HWSKU == "" ]]; then + HWSKU="" + fi + else + HWSKU="" + fi + fi + echo "${HWSKU}" +} + +start() { + TOPOLOGY_SCRIPT="topology.sh" + PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + HWSKU=`get_hwsku` + if [[ $HWSKU != "" ]]; then + /usr/share/sonic/device/$PLATFORM/$HWSKU/$TOPOLOGY_SCRIPT start + else + echo "Failed to get HWSKU" + exit 1 + fi +} + +stop() { + TOPOLOGY_SCRIPT="topology.sh" + PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + HWSKU=`get_hwsku` + if [[ $HWSKU != "" ]]; then + /usr/share/sonic/device/$PLATFORM/$HWSKU/$TOPOLOGY_SCRIPT stop + else + echo "Failed to get HWSKU" + exit 1 + fi +} + +# read SONiC immutable variables +[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment + +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 new file mode 100755 index 000000000000..5c767b83d95c --- /dev/null +++ b/files/image_config/updategraph/updategraph @@ -0,0 +1,134 @@ +#!/bin/bash + +reload_minigraph() +{ + echo "Reloading minigraph..." + config load_minigraph -y -n + config save -y +} + +# read SONiC immutable variables +[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment + +if [ ! -f /etc/sonic/updategraph.conf ]; then + echo "No updategraph.conf found, generating a default one." + echo "enabled=false" >/etc/sonic/updategraph.conf +fi + +. /etc/sonic/updategraph.conf + +if [ "$enabled" = "reload_only" ]; then + reload_minigraph + sed -i "/enabled=/d" /etc/sonic/updategraph.conf + echo "enabled=false" >> /etc/sonic/updategraph.conf + exit 0 +fi + +if [ "$enabled" != "true" ]; then + echo "Disabled in updategraph.conf. Skipping graph update." + 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 + # Enable dhcp client on management port eth0 + /sbin/dhclient -4 -v -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases -I -df /var/lib/dhcp/dhclient6.eth0.leases eth0 & + disown + + while [ ! -f /tmp/dhcp_graph_url ]; do + echo "Waiting for DHCP response..." + sleep 1 + done + + if [ "`cat /tmp/dhcp_graph_url`" = "N/A" ]; then + echo "No graph_url option in DHCP response. Skipping graph update and generating an empty configuration." + PLATFORM=${PLATFORM:-`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform`} + if [ -f /etc/sonic/minigraph.xml ]; then + sonic-cfggen -H -m /etc/sonic/minigraph.xml --preset empty > /tmp/device_meta.json + else + PRESET=(`head -n 1 /usr/share/sonic/device/$PLATFORM/default_sku`) + sonic-cfggen -H -k ${PRESET[0]} --preset empty > /tmp/device_meta.json + fi + if [ -f /etc/sonic/init_cfg.json ]; then + sonic-cfggen -j /tmp/device_meta.json -j /etc/sonic/init_cfg.json --print-data > /etc/sonic/config_db.json + else + cp -f /tmp/device_meta.json /etc/sonic/config_db.json + fi + sonic-db-cli CONFIG_DB FLUSHDB + sonic-cfggen -j /etc/sonic/config_db.json --write-to-db + 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 + fi + exit 0 + fi + + + HOSTNAME=`hostname -s` + GRAPH_URL=`sonic-cfggen -t /tmp/dhcp_graph_url -a "{\"hostname\": \"$HOSTNAME\"}"` + URL_REGEX='^(https?|ftp|file)://[-A-Za-z0-9\+&@#/%?=~_|!:,.;]*[-A-Za-z0-9\+&@#/%=~_|]$' + if [[ ! $GRAPH_URL =~ $URL_REGEX ]]; then + echo "\"$GRAPH_URL\" is not a valid url. Skipping graph update." + exit 0 + fi + if [ "$dhcp_as_static" = "true" ]; then + sed -i "/src=/d" /etc/sonic/updategraph.conf + echo "src=\"$GRAPH_URL\"" >> /etc/sonic/updategraph.conf + fi + + if [ -f /tmp/dhcp_acl_url ]; then + ACL_URL=`sonic-cfggen -t /tmp/dhcp_acl_url -a "{\"hostname\": \"$HOSTNAME\"}"` + if [[ ! $ACL_URL =~ $URL_REGEX ]]; then + echo "\"$ACL_URL\" is not a valid url. Skipping acl update." + ACL_URL="" + fi + if [ "$dhcp_as_static" = "true" ]; then + sed -i "/acl_src=/d" /etc/sonic/updategraph.conf + echo "acl_src=\"$ACL_URL\"" >> /etc/sonic/updategraph.conf + fi + fi +else + GRAPH_URL=$src +fi + +if [ -f /etc/sonic/minigraph.xml ]; then + echo "Renaming minigraph.xml to minigraph.old" + mv /etc/sonic/minigraph.xml /etc/sonic/minigraph.old +fi + +echo "Getting minigraph from $GRAPH_URL" + +while true; do + curl -f $GRAPH_URL -o /etc/sonic/minigraph.xml --connect-timeout 15 && break + sleep 5 +done + +if [ -n "$ACL_URL" ]; then + if [ -f /etc/sonic/acl.json ]; then + echo "Renaming acl.json to acl.json.old" + mv /etc/sonic/acl.json /etc/sonic/acl.json.old + fi + echo "Getting ACL config from $ACL_URL" + + while true; do + curl -f $ACL_URL -o /etc/sonic/acl.json --connect-timeout 15 && break + sleep 5 + done +else + echo "Skip ACL config download." +fi + +reload_minigraph + +# Mark as disabled after graph is successfully downloaded +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 new file mode 100755 index 000000000000..172fd95ab2e9 --- /dev/null +++ b/files/image_config/warmboot-finalizer/finalize-warmboot.sh @@ -0,0 +1,151 @@ +#! /bin/bash + +VERBOSE=no + +# Define components that needs to reconcile during warm +# boot: +# The key is the name of the service that the components belong to. +# The value is list of component names that will reconcile. +declare -A RECONCILE_COMPONENTS=( \ + ["swss"]="orchagent neighsyncd" \ + ["bgp"]="bgp" \ + ["nat"]="natsyncd" \ + ) +EXP_STATE="reconciled" + +ASSISTANT_SCRIPT="/usr/local/bin/neighbor_advertiser" + + +function debug() +{ + /usr/bin/logger "WARMBOOT_FINALIZER : $1" + if [[ x"${VERBOSE}" == x"yes" ]]; then + echo `date` "- $1" + fi +} + + +function get_component_list() +{ + SVC_LIST=${!RECONCILE_COMPONENTS[@]} + COMPONENT_LIST="" + for service in ${SVC_LIST}; do + components=${RECONCILE_COMPONENTS[${service}]} + status=$(sonic-db-cli CONFIG_DB HGET "FEATURE|${service}" state) + if [[ x"${status}" == x"enabled" || x"${status}" == x"always_enabled" ]]; then + COMPONENT_LIST="${COMPONENT_LIST} ${components}" + fi + done +} + + +function check_warm_boot() +{ + WARM_BOOT=`sonic-db-cli STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable` +} + + +function wait_for_database_service() +{ + debug "Wait for database to become ready..." + + # Wait for redis server start before database clean + until [[ $(sonic-db-cli PING | grep -c PONG) -gt 0 ]]; do + sleep 1; + done + + # Wait for configDB initialization + until [[ $(sonic-db-cli CONFIG_DB GET "CONFIG_DB_INITIALIZED") ]]; + do sleep 1; + done + + debug "Database is ready..." +} + + +function get_component_state() +{ + sonic-db-cli STATE_DB hget "WARM_RESTART_TABLE|$1" state +} + + +function check_list() +{ + RET_LIST='' + for comp in $@; do + state=`get_component_state ${comp}` + if [[ x"${state}" != x"${EXP_STATE}" ]]; then + RET_LIST="${RET_LIST} ${comp}" + fi + done + + echo ${RET_LIST} +} + + +function finalize_warm_boot() +{ + debug "Finalizing warmboot..." + sudo config warm_restart disable +} + +function stop_control_plane_assistant() +{ + if [[ -x ${ASSISTANT_SCRIPT} ]]; then + debug "Tearing down control plane assistant ..." + ${ASSISTANT_SCRIPT} -m reset + fi +} + +function restore_counters_folder() +{ + debug "Restoring counters folder after warmboot..." + + modules=("portstat-0" "dropstat" "pfcstat-0" "queuestat-0" "intfstat-0") + for module in ${modules[@]} + do + statfile="/host/counters/$module" + if [[ -d $statfile ]]; then + mv $statfile /tmp/ + fi + done +} + + +wait_for_database_service + +check_warm_boot + +if [[ x"${WARM_BOOT}" != x"true" ]]; then + debug "warmboot is not enabled ..." + exit 0 +fi + +restore_counters_folder + +get_component_list + +debug "Waiting for components: '${COMPONENT_LIST}' to reconcile ..." + +list=${COMPONENT_LIST} + +# Wait up to 5 minutes +for i in `seq 60`; do + list=`check_list ${list}` + if [[ -z "${list}" ]]; then + break + fi + sleep 5 +done + +stop_control_plane_assistant + +# Save DB after stopped control plane assistant to avoid extra entries +debug "Save in-memory database after warm reboot ..." +config save -y + +if [[ -n "${list}" ]]; then + debug "Some components didn't finish reconcile: ${list} ..." +fi + +finalize_warm_boot diff --git a/files/image_config/warmboot-finalizer/warmboot-finalizer.service b/files/image_config/warmboot-finalizer/warmboot-finalizer.service new file mode 100644 index 000000000000..72cc6e338982 --- /dev/null +++ b/files/image_config/warmboot-finalizer/warmboot-finalizer.service @@ -0,0 +1,11 @@ +[Unit] +Description=Monitor warm recovery and disable warmboot when done +Requires=database.service +After=database.service + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/finalize-warmboot.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/watchdog-control/watchdog-control.service b/files/image_config/watchdog-control/watchdog-control.service new file mode 100644 index 000000000000..579e645e248d --- /dev/null +++ b/files/image_config/watchdog-control/watchdog-control.service @@ -0,0 +1,10 @@ +[Unit] +Description=watchdog control service +After=swss.service + +[Service] +Type=simple +ExecStart=/usr/local/bin/watchdog-control.sh + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/watchdog-control/watchdog-control.sh b/files/image_config/watchdog-control/watchdog-control.sh new file mode 100755 index 000000000000..892039964620 --- /dev/null +++ b/files/image_config/watchdog-control/watchdog-control.sh @@ -0,0 +1,44 @@ +#! /bin/bash + +VERBOSE=no +WATCHDOG_UTIL="/usr/local/bin/watchdogutil" + +function debug() +{ + /usr/bin/logger "$0 : $1" + if [[ x"${VERBOSE}" == x"yes" ]]; then + echo "$(date) $0: $1" + fi +} + + +function getBootType() +{ + # same code snippet in files/scripts/syncd.sh + case "$(cat /proc/cmdline)" in + *SONIC_BOOT_TYPE=warm*) + TYPE='warm' + ;; + *SONIC_BOOT_TYPE=fastfast*) + TYPE='fastfast' + ;; + *SONIC_BOOT_TYPE=fast*|*fast-reboot*) + TYPE='fast' + ;; + *) + TYPE='cold' + esac + echo "${TYPE}" +} + +function disable_watchdog() +{ + # Obtain boot type from kernel arguments + BOOT_TYPE=`getBootType` + if [[ -x ${WATCHDOG_UTIL} ]]; then + debug "Disabling Watchdog during bootup after $BOOT_TYPE" + ${WATCHDOG_UTIL} disarm + fi +} + +disable_watchdog diff --git a/files/initramfs-tools/arista-convertfs.j2 b/files/initramfs-tools/arista-convertfs.j2 new file mode 100644 index 000000000000..9af44f221fe9 --- /dev/null +++ b/files/initramfs-tools/arista-convertfs.j2 @@ -0,0 +1,254 @@ +#!/bin/sh + +case $1 in + prereqs) + exit 0 + ;; +esac + +set -e +# set -x +total_mem=$(free | awk '/^Mem:/{print $2}') +tmpfs_size=$(( $total_mem / 20 * 17 )) +free_mem_thres=$(( $total_mem / 20 * 18 )) +tmp_mnt='/mnt/ramdisk-convfs' +root_mnt='/mnt/root-convfs' +root_dev='' +flash_dev='' +block_flash='' +aboot_flag='' +backup_file='' +prev_os='' +sonic_fast_reboot=false +in_kdump=false + +# Wait until get the fullpath of flash device, e.g., /dev/sda +wait_get_flash_dev() { + local try_rounds=30 + while [ $try_rounds -gt 0 ]; do + for dev in $(ls /sys/block); do + local is_mmc=$(echo "$dev" | grep 'mmcblk.*boot.*' | cat) + if [ -n "$is_mmc" ]; then + continue + fi + local devid=$(realpath "/sys/block/$dev/device") + local is_device=$(echo "$devid" | grep '^/sys/devices/' | cat) + local is_flash=$(echo "$devid" | grep "$block_flash" | cat) + if [ -n "$is_device" -a -n "$is_flash" ]; then + flash_dev="/dev/$dev" + return 0 + fi + done + sleep 1 + try_rounds=$(( $try_rounds - 1 )) + done + return 1 +} + +# Wait for root_dev to be ready +wait_for_root_dev() { + local try_rounds=30 + while [ $try_rounds -gt 0 ]; do + if blkid | sed 's/"//g' | grep -q "$root_dev"; then + return 0 + fi + if [ -e "$root_dev" ]; then + return 0 + fi + sleep 1 + try_rounds=$(( $try_rounds - 1 )) + done + return 1 +} + +# Alway run cleanup before exit +cleanup() { + if grep -q "$root_mnt" /proc/mounts; then + umount "$root_mnt" + fi + if grep -q "$tmp_mnt" /proc/mounts; then + umount "$tmp_mnt" + fi + [ -e "$root_mnt" ] && rmdir "$root_mnt" + [ -e "$tmp_mnt" ] && rmdir "$tmp_mnt" +} +trap cleanup EXIT + +notification() { +cat << EOF +A failure happend in modifying the root file system which stopped the upgrade. Manual interventions are needed to fix the issue. Note that: +1) files in the old root file system may have been lost and the old partition table may have been corrupted; +2) The files in the old root file system were copied to $tmp_mnt; +3) The old partition table was dumped to the file $tmp_mnt/$backup_file by sfdisk; +4) Quitting the current shell will lose all files mentioned above permanently. +EOF +} + +run_cmd() { + if ! eval "$1"; then + echo "$2" + notification + sh + exit 1 + fi +} + +fixup_flash_permissions() { + # properly set flash permissions for others + # this allows the sonic admin user to have read access on the flash + local flash_mnt="$1" + chmod o+rx "$flash_mnt" + + # remove all the filesystem acls from the flash + setfacl -Rb "$flash_mnt" +} + +# Update ROOT device referring to the path under block_flash +# This is for the occasional name swap between /dev/sda and /dev/sdb +update_root() { + # Check that root=/dev/*, ignoring any cases like root=UUID=* + [ "${ROOT#/dev}" = "${ROOT}" ] && return 0 + + # Replace the beginning chars of ROOT by the ones of flash_dev with same index +{% raw %} + prefix_length="${#flash_dev}" +{% endraw %} + part_id="${ROOT:$prefix_length}" + ROOT="$flash_dev$part_id" + + echo "ROOT=$ROOT" > /conf/param.conf +} + +# Extract kernel parameters +set -- $(cat /proc/cmdline) +for x in "$@"; do + case "$x" in + block_flash=*) + block_flash="${x#block_flash=}" + ;; + Aboot=*) + aboot_flag="${x#Aboot=}" + ;; + loop=*) + x1="${x#loop=}" + image_dir="${x1%/*}" + ;; + docker_inram=*) + docker_inram="${x#docker_inram=}" + ;; + prev_os=*) + prev_os="${x#prev_os=}" + ;; + SONIC_BOOT_TYPE=warm*|SONIC_BOOT_TYPE=fast*) + sonic_fast_reboot=true + ;; + systemd.unit=kdump-tools.service) + in_kdump=true + ;; + esac +done + +# Check aboot +[ -z "$aboot_flag" ] && exit 0 + +# Check kdump +[ "$in_kdump" = true ] && 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" + exit 1 +fi +if ! wait_get_flash_dev; then + echo "Error: flash device is not found" + exit 1 +fi + +# If root=/dev/*, update ROOT to the device under block_flash +update_root + +root_dev="$ROOT" +if [ -z "$root_dev" ]; then + echo "Error: root device name is not provided" + exit 1 +fi +if ! wait_for_root_dev; then + echo "Error: timeout in waiting for $root_dev" + exit 1 +fi + +# exit when the root is ext4 +if ! blkid | grep "$root_dev.*vfat" -q; then + mkdir -p "$root_mnt" + mount -t ext4 "$root_dev" "$root_mnt" + fixup_flash_permissions "$root_mnt" + umount "$root_mnt" + rmdir "$root_mnt" + exit 0 +fi + +# Check memory size for tmpfs +free_mem=$(free | awk '/^Mem:/{print $4}') +if [ "$free_mem" -lt "$free_mem_thres" ]; then + echo "Error: memory is not enough" + exit 1 +fi + +# Backup partition table +mkdir -p "$root_mnt" +mount "$root_dev" "$root_mnt" +backup_file=backup.$(date +%Y-%m-%d.%H-%M-%S) +sfdisk -d "$flash_dev" > "$root_mnt/$backup_file" + +# Check total size of files in root +total_file_size=$(du -s "$root_mnt" | awk '{print $1}') +if [ "$total_file_size" -gt "$tmpfs_size" ]; then + echo "Error: total file size is too large" + exit 1 +fi + +# Create tmpfs, and copy files to tmpfs +mkdir -p "$tmp_mnt" +mount -t tmpfs -o size="${tmpfs_size}k" tmpfs "$tmp_mnt" +cp -a "$root_mnt/." "$tmp_mnt/" +umount "$root_mnt" + +#### Lines below will modify the root file system, so any failure will be trapped to shell for manual interventions. + +if [ $(echo -n "$root_dev" | tail -c 1) == "1" ]; then + # Create a new partition table (content in flash_dev will be deleted) + err_msg="Error: Failed to zero out first MB" + cmd="dd if=/dev/zero of=$flash_dev bs=512 count=2048" + run_cmd "$cmd" "$err_msg" + err_msg="Error: repartitioning $flash_dev failed" + cmd="echo '2048' | sfdisk $flash_dev || (sleep 3; blockdev --rereadpt $flash_dev && fdisk -l $flash_dev | grep -q ${root_dev}.*Linux)" + run_cmd "$cmd" "$err_msg" +fi + +sleep 2 +err_msg="Error: timeout in waiting for $root_dev after repartition" +cmd="wait_for_root_dev" +run_cmd "$cmd" "$err_msg" + +err_msg="Error: formatting to ext4 failed" +cmd="/usr/local/sbin/mke2fs -t ext4 -F -O '^huge_file,^metadata_csum' $root_dev" +run_cmd "$cmd" "$err_msg" + +err_msg="Error: mounting $root_dev to $root_mnt failed" +cmd="mount -t ext4 $root_dev $root_mnt" +run_cmd "$cmd" "$err_msg" + +if [ x"$docker_inram" != x"on" ]; then + err_msg="Error: extract docker directory" + cmd="[ -f $tmp_mnt/$image_dir/{{ FILESYSTEM_DOCKERFS }} ] && rm -rf $root_mnt/$image_dir/{{ DOCKERFS_DIR }} && mkdir -p $root_mnt/$image_dir/{{ DOCKERFS_DIR }} && tar xzf $tmp_mnt/$image_dir/{{ FILESYSTEM_DOCKERFS }} -C $root_mnt/$image_dir/{{ DOCKERFS_DIR }} && rm -f $tmp_mnt/$image_dir/{{ FILESYSTEM_DOCKERFS }}" + run_cmd "$cmd" "$err_msg" +fi + +err_msg="Error: copying files form $tmp_mnt to $root_mnt failed" +cmd="cp -a $tmp_mnt/. $root_mnt/" +run_cmd "$cmd" "$err_msg" + +fixup_flash_permissions "$root_mnt" diff --git a/files/initramfs-tools/arista-hook b/files/initramfs-tools/arista-hook new file mode 100644 index 000000000000..868521b0db9d --- /dev/null +++ b/files/initramfs-tools/arista-hook @@ -0,0 +1,82 @@ +#!/bin/sh + +PREREQS="arista-convertfs" + +prereqs() { echo "$PREREQS"; } + +case $1 in + prereqs) + prereqs + exit 0 + ;; +esac + +info() { printf "%04.2f: $@\n" "$(cut -f1 -d' ' /proc/uptime)"; } +err() { info "Error: $@"; } +warn() { info "Warning: $@"; } + +set -e + +root_mnt='/mnt/arista-firmware' +root_dev='' +aboot_flag='' + +# Alway run cleanup before exit +cleanup() { + if grep -q "$root_mnt" /proc/mounts; then + umount "$root_mnt" + fi + [ -e "$root_mnt" ] && rmdir "$root_mnt" +} +trap cleanup EXIT + +# Extract kernel parameters +set -- $(cat /proc/cmdline) +for x in "$@"; do + case "$x" in + Aboot=*) + aboot_flag="${x#Aboot=}" + ;; + loop=*) + x1="${x#loop=}" + image_dir="${x1%/*}" + ;; + SONIC_BOOT_TYPE=warm*|SONIC_BOOT_TYPE=fast*) + # Skip this script for warm-reboot and fast-reboot + exit 0 + ;; + systemd.unit=kdump-tools.service) + # In kdump environment, skip hooks + exit 0 + ;; + esac +done + +[ -z "$aboot_flag" ] && exit 0 + +root_dev="$ROOT" +if [ -z "$root_dev" ]; then + err "Error: root device name is not provided" + exit 1 +fi + +mkdir -p "$root_mnt" +mount -t ext4 "$root_dev" "$root_mnt" + +get_sorted_hooks() { + echo $(find "$1" -name '[0-9][0-9]-*' -type f | sort) +} + +if [ -d "$root_mnt/$image_dir/platform/hooks/boot1" ]; then + for hook in $(get_sorted_hooks "$root_mnt/$image_dir/platform/hooks/boot1"); do + if [ ! -z "$hook" ]; then + cp "$hook" /tmp/ + hook="/tmp/`basename $hook`" + info "Running hook $(basename $hook)" + . "$hook" + fi + done +fi + +umount "$root_mnt" +rmdir "$root_mnt" diff --git a/files/initramfs-tools/arista-net b/files/initramfs-tools/arista-net new file mode 100644 index 000000000000..8759746458d6 --- /dev/null +++ b/files/initramfs-tools/arista-net @@ -0,0 +1,113 @@ +#!/bin/sh + +case $1 in + prereqs) + exit 0 + ;; +esac + +set -e + +# Extract kernel parameters +set -- $(cat /proc/cmdline) +items="" +for x in "$@"; do + case "$x" in + Aboot=*) + aboot_flag="${x#Aboot=}" + ;; + net_*) + item="${x#net_}" + items="$items $item" + ;; + platform=*) + platform_flag="${x#platform=}" + ;; + esac +done + +random() { + echo $(od -vAn -N1 -tu1 < /dev/urandom) +} + +arista_net_devname() { + local pciaddr="$1" + local devname_prefix="$2" + for path in $(ls -d /sys/class/net/${devname_prefix}* 2>/dev/null); do + local devid="$(realpath "$path/device")" + if echo "$devid" | grep -q "$pciaddr"; then + echo "${path##*/}" + return + fi + done +} + +arista_net_rename() { + local device_path="$1" + local new_name="$2" + local from_name="$3" + devname=$(arista_net_devname "$device_path" "$from_name") + [ -n "$devname" ] && ip link set "$devname" name "$new_name" +} + +# Sets the MAC address to the value passed by Aboot through /proc/cmdline +tg3fixhwaddr() +{ + local default_tg3_hwaddr="00:10:18:00:00:00" + local pciaddr="$1" + local hwaddr="$2" + + devname=$(arista_net_devname "$pciaddr") + if [ -z "$devname" ]; then + return + fi + + driver=$(basename $(readlink "/sys/class/net/$devname/device/driver")) + if [ "$driver" != "tg3" ]; then + return 0 + fi + + if [ "$hwaddr" = "$default_tg3_hwaddr" ]; then + hwaddr=$(cat /sys/class/net/$devname/address) + fi + + if [ "$hwaddr" = "$default_tg3_hwaddr" ]; then + hwaddr=$(printf "%02x" "$(($(random) & 0xfe | 0x02))") + for i in 1 2 3 4 5; do + hwaddr=$(printf "$hwaddr:%02x" "$(($(random) & 0xfe | 0x02))") + done + fi + + ip link set dev "$devname" addr "$hwaddr" +} + +if [ -n "$aboot_flag" ]; then + for item in $items; do + key="${item%=*}" + value="${item#*=}" + hwaddr=$(eval echo \${hwaddr_${key}}) + if [ -n "$hwaddr" ]; then + tg3fixhwaddr "$value" "$hwaddr" + fi + done +fi + +# Iterate over all the net_maX items found in the cmdline two times. +# First time renaming the interfaces to maX. +# The second time renaming them to their final name ethX. +if [ -n "$aboot_flag" -a "$platform_flag" == 'rook' ]; then + for item in $items; do + key="${item%=*}" + value="${item#*=}" + arista_net_rename "$value" "$key" eth + done + for item in $items; do + key="${item%=*}" + value="${item#*=}" + index="${key#ma}" + index="$(( $index - 1 ))" + newKey="eth$index" + arista_net_rename "$value" "$newKey" ma + done +fi + diff --git a/files/initramfs-tools/fsck-rootfs b/files/initramfs-tools/fsck-rootfs new file mode 100644 index 000000000000..25b1c096aa5b --- /dev/null +++ b/files/initramfs-tools/fsck-rootfs @@ -0,0 +1,34 @@ +#!/bin/sh + +case $1 in + prereqs) + exit 0 + ;; +esac + +# Extract kernel parameters +root_val="" +set -- $(cat /proc/cmdline) +for x in "$@"; do + case "$x" in + root=*) + root_val="${x#root=}" + ;; + esac +done + +# Check the filesystem we are using +if [ ! -z $root_val ]; then + fstype=$(blkid -o value -s TYPE $root_val) + case "$fstype" in + ext4) + cmd="fsck.ext4 -v -p" + ;; + ext3) + cmd="fsck.ext3 -v -p" + ;; + esac + if [ ! -z "$cmd" ]; then + $cmd $root_val 2>&1 | gzip -c > /tmp/fsck.log.gz + fi +fi diff --git a/files/initramfs-tools/mke2fs b/files/initramfs-tools/mke2fs new file mode 100644 index 000000000000..1f98f20c23c4 --- /dev/null +++ b/files/initramfs-tools/mke2fs @@ -0,0 +1,52 @@ +#!/bin/sh +#Part of the code is revised based on initramfs-tools/hooks/fsck and initramfs-tool is under GPL v2. + +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/hook-functions + +copy_exec /usr/sbin/mke2fs /usr/local/sbin/ +copy_exec /sbin/sfdisk +copy_exec /sbin/fdisk +copy_exec /sbin/resize2fs +copy_exec /sbin/findfs + +fstypes="ext4 ext3" + +for type in $fstypes; do + prog="/sbin/mkfs.${type}" + if [ -h "$prog" ]; then + link=$(readlink -f "$prog") + copy_exec "$link" + ln -s "/usr/local/sbin/$(basename $link)" "${DESTDIR}/$prog" + elif [ -x "$prog" ] ; then + copy_exec "$prog" + else + echo "Warning: /sbin/mkfs.${type} doesn't exist, can't install to initramfs, ignoring." + fi +done + +for type in $fstypes; do + prog="/sbin/fsck.${type}" + if [ -h "$prog" ]; then + link=$(readlink -f "$prog") + copy_exec "$link" + ln -s "$link" "${DESTDIR}/$prog" + elif [ -x "$prog" ] ; then + copy_exec "$prog" + else + echo "Warning: /sbin/fsck.${type} doesn't exist, can't install to initramfs, ignoring." + fi +done diff --git a/files/initramfs-tools/modules b/files/initramfs-tools/modules index 86a1fcf20bd7..349bf37619e4 100644 --- a/files/initramfs-tools/modules +++ b/files/initramfs-tools/modules @@ -1,2 +1,7 @@ squashfs -aufs +overlay +vfat +nls_ascii +nls_cp437 +nls_utf8 +nvme diff --git a/files/initramfs-tools/modules.arm b/files/initramfs-tools/modules.arm new file mode 100644 index 000000000000..0741051950c4 --- /dev/null +++ b/files/initramfs-tools/modules.arm @@ -0,0 +1,14 @@ +crc16 +deflate +zlib_deflate +m25p80 +ubi +ubifs +squashfs +marvell_nand +i2c_mv64xxx +ar7part +ofpart +mtdswap +mtd_blkdevs +adt7475 diff --git a/files/initramfs-tools/resize-rootfs b/files/initramfs-tools/resize-rootfs new file mode 100644 index 000000000000..17ffcb94e693 --- /dev/null +++ b/files/initramfs-tools/resize-rootfs @@ -0,0 +1,39 @@ +#!/bin/sh + +case $1 in + prereqs) + exit 0 + ;; +esac + +# Extract kernel parameters +set -- $(cat /proc/cmdline) +for x in "$@"; do + case "$x" in + root=*) + root_val="${x#root=}" + ;; + resize-rootfs) + need_resize=1 + ;; + esac +done + +if [ -n "$need_resize" ]; then + if [ -z "$root_val" ]; then + echo "ERROR: resize required but unable to get root location from command line" + exit 1 + fi + + root_dev=$(findfs $root_val) + if [ $? != 0 ]; then + echo "ERROR: resize required but findfs failed" + exit 1 + fi + + resize2fs -f $root_dev + if [ $? != 0 ]; then + echo "ERROR: Unable to resize the root file system. Manual intervention needed to fix the issue." + exit 1 + fi +fi diff --git a/files/initramfs-tools/setfacl b/files/initramfs-tools/setfacl new file mode 100644 index 000000000000..96564e06b245 --- /dev/null +++ b/files/initramfs-tools/setfacl @@ -0,0 +1,20 @@ +#!/bin/sh +#Part of the code is revised based on initramfs-tools/hooks/fsck and initramfs-tool is under GPL v2. + +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/hook-functions + +copy_exec /usr/bin/setfacl /sbin/setfacl diff --git a/files/initramfs-tools/uboot-utils b/files/initramfs-tools/uboot-utils new file mode 100644 index 000000000000..a9255a37eacf --- /dev/null +++ b/files/initramfs-tools/uboot-utils @@ -0,0 +1,21 @@ +#!/bin/sh +#Part of the code is revised based on initramfs-tool is under GPL v2. + +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/hook-functions + +copy_exec /usr/sbin/ubiattach /sbin/ubiattach +copy_exec /usr/sbin/mtdinfo /sbin/mtdinfo diff --git a/files/initramfs-tools/udev.patch b/files/initramfs-tools/udev.patch new file mode 100644 index 000000000000..38c43dc27d69 --- /dev/null +++ b/files/initramfs-tools/udev.patch @@ -0,0 +1,10 @@ +--- a/udev 2017-09-02 23:13:45.078773236 +0000 ++++ b/udev 2017-09-02 22:40:08.502773236 +0000 +@@ -1,6 +1,6 @@ + #!/bin/sh -e + +-PREREQS="" ++PREREQS="union-mount" + + prereqs() { echo "$PREREQS"; } + diff --git a/files/initramfs-tools/union-mount b/files/initramfs-tools/union-mount deleted file mode 100644 index 85fba9df3a0a..000000000000 --- a/files/initramfs-tools/union-mount +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -e -case $1 in - prereqs) - exit 0 - ;; -esac -mkdir -p ${rootmnt}/host/rw -mount -n -o dirs=${rootmnt}/host/rw:${rootmnt}=ro -t aufs root-aufs ${rootmnt} -mount ${ROOT} ${rootmnt}/host -mkdir -p /root/var/lib/docker -mount --bind /root/host/var/lib/docker /root/var/lib/docker -mkdir -p /root/boot -mount --bind /root/host/boot /root/boot diff --git a/files/initramfs-tools/union-mount.j2 b/files/initramfs-tools/union-mount.j2 new file mode 100644 index 000000000000..a97137a00c2f --- /dev/null +++ b/files/initramfs-tools/union-mount.j2 @@ -0,0 +1,169 @@ +#!/bin/sh -e + +PREREQS="varlog" + +prereqs() { echo "$PREREQS"; } + +case $1 in + prereqs) + prereqs + exit 0 + ;; +esac + +docker_inram=false +logs_inram=false +secureboot=false +bootloader=generic +in_kdump=false + +# Extract kernel parameters +for x in $(cat /proc/cmdline); do + case "$x" in + Aboot=*) + bootloader=aboot + ;; + docker_inram=on) + docker_inram=true + ;; + logs_inram=on) + logs_inram=true + ;; + secure_boot_enable=[y1]) + secureboot=true + docker_inram=true + ;; + platform=*) + platform_flag="${x#platform=}" + ;; + systemd.unit=kdump-tools.service) + in_kdump=true + ;; + esac +done + +set_tmpfs_log_partition_size() +{ + varlogsize=128 + + # set varlogsize to existing var-log.ext4 size + if [ -f ${rootmnt}/host/disk-img/var-log.ext4 ]; then + varlogsize=$(ls -l ${rootmnt}/host/disk-img/var-log.ext4 | awk '{print $5}') + varlogsize=$(($varlogsize/1024/1024)) + fi + + # make sure varlogsize is between 5% to 10% of total memory size + memkb=$(grep MemTotal /proc/meminfo | awk '{print $2}') + memmb=$(($memkb/1024)) + minsize=$(($memmb*5/100)) + maxsize=$(($memmb*10/100)) + + [ $minsize -ge $varlogsize ] && varlogsize=$minsize + [ $maxsize -le $varlogsize ] && varlogsize=$maxsize +} + +remove_not_in_allowlist_files() +{ + local allowlist_file="$1" + local targeted_dir="$2" + local allowlist_pattern_file=/tmp/allowlist_paths.pattern + + # Return if the allowlist file does not exist + if ! test -f "${allowlist_file}"; then + echo "The file ${allowlist_file} is missing, failed to mount rw folder." 1>&2 + exit 1 + fi + + # Set the grep pattern file, remove the blank line in config file + awk -v rw_dir="$targeted_dir" 'NF {print rw_dir"/"$0"$"}' ${allowlist_file} > $allowlist_pattern_file + + # Find the files in the rw folder, and remove the files not in the allowlist + find ${targeted_dir} -type f | grep -v -f $allowlist_pattern_file | xargs /bin/rm -f + rm -f $allowlist_pattern_file +} + +## Mount the overlay file system: rw layer over squashfs +image_dir=$(cat /proc/cmdline | sed -e 's/.*loop=\(\S*\)\/.*/\1/') +rw_dir=${rootmnt}/host/$image_dir/rw +work_dir=${rootmnt}/host/$image_dir/work +mkdir -p "$rw_dir" +mkdir -p "$work_dir" + +## Remove the files not in allowlist in the rw folder +if [ "$secureboot" = true ] && [ "$in_kdump" = false ]; then + if [ "$bootloader" = "aboot" ]; then + swi_path="${rootmnt}/host/$(sed -E 's/.*loop=([^ ]+).*/\1/' /proc/cmdline)" + unzip -q "$swi_path" allowlist_paths.conf -d /tmp + allowlist_file=/tmp/allowlist_paths.conf + else + allowlist_file=${rootmnt}/host/$image_dir/allowlist_paths.conf + fi + + remove_not_in_allowlist_files "$allowlist_file" "$rw_dir" + + ## Remove the executable permission for all the files in rw folder except home folder + find ${rw_dir} -type f -not -path ${rw_dir}/home -exec chmod a-x {} + +fi + +mount -n -o lowerdir=${rootmnt},upperdir=${rw_dir},workdir=${work_dir} -t overlay root-overlay ${rootmnt} + +## Check if the root block device is still there +[ -b ${ROOT} ] || mdev -s +case "${ROOT}" in + ubi*) + mtd=$(cat /proc/cmdline | sed -e 's/.*ubi.mtd=\([0-9]\) .*/\1/') + if [ ! -f /dev/${ROOT}_0 ]; then + ubiattach /dev/ubi_ctrl -m $mtd 2>dev/null || true + fi + mount -t ubifs /dev/${ROOT}_0 ${rootmnt}/host + ;; + *) + ## Mount the raw partition again + mount ${ROOT} ${rootmnt}/host + ;; +esac + +mkdir -p ${rootmnt}/var/lib/docker +if [ "$in_kdump" = false ]; then + if [ "$secureboot" = true ]; then + mount -t tmpfs -o rw,nodev,size={{ DOCKER_RAMFS_SIZE }} tmpfs ${rootmnt}/var/lib/docker + if [ "$bootloader" = "aboot" ]; then + unzip -qp "$swi_path" dockerfs.tar.gz | tar xz --numeric-owner -C ${rootmnt}/var/lib/docker + ## Boot folder is not extracted during secureboot since content would inherently become unsafe + mkdir -p ${rootmnt}/host/$image_dir/boot + else + echo "secureboot unsupported for bootloader $bootloader" 1>&2 + exit 1 + fi + elif [ -f ${rootmnt}/host/$image_dir/{{ FILESYSTEM_DOCKERFS }} ]; then + ## mount tmpfs and extract docker into it + mount -t tmpfs -o rw,nodev,size={{ DOCKER_RAMFS_SIZE }} tmpfs ${rootmnt}/var/lib/docker + tar xz --numeric-owner -f ${rootmnt}/host/$image_dir/{{ FILESYSTEM_DOCKERFS }} -C ${rootmnt}/var/lib/docker + else + ## Mount the working directory of docker engine in the raw partition, bypass the overlay + mount --bind ${rootmnt}/host/$image_dir/{{ DOCKERFS_DIR }} ${rootmnt}/var/lib/docker + fi +fi + +## Mount the boot directory in the raw partition, bypass the overlay +mkdir -p ${rootmnt}/boot +mount --bind ${rootmnt}/host/$image_dir/boot ${rootmnt}/boot + +## Mount loop device or tmpfs for /var/log +if $logs_inram; then + # NOTE: some platforms, when reaching initramfs stage, have a small + # limit of mounting tmpfs partition, potentially due to amount + # of RAM available in this stage. e.g. Arista 7050-qx32[s] and 7060-cx32s + set_tmpfs_log_partition_size + mount -t tmpfs -o rw,nosuid,nodev,size=${varlogsize}M tmpfs ${rootmnt}/var/log + [ -f ${rootmnt}/host/disk-img/var-log.ext4 ] && rm -rf ${rootmnt}/host/disk-img/var-log.ext4 +else + [ -f ${rootmnt}/host/disk-img/var-log.ext4 ] && fsck.ext4 -v -p ${rootmnt}/host/disk-img/var-log.ext4 2>&1 \ + | gzip -c >> /tmp/fsck.log.gz + [ -f ${rootmnt}/host/disk-img/var-log.ext4 ] && mount -t ext4 -o loop,rw ${rootmnt}/host/disk-img/var-log.ext4 ${rootmnt}/var/log +fi + +## fscklog file: /tmp will be lost when overlayfs is mounted +if [ -f /tmp/fsck.log.gz ]; then + mv /tmp/fsck.log.gz ${rootmnt}/var/log +fi diff --git a/files/initramfs-tools/varlog b/files/initramfs-tools/varlog new file mode 100644 index 000000000000..e8063e41a59c --- /dev/null +++ b/files/initramfs-tools/varlog @@ -0,0 +1,44 @@ +#!/bin/sh -e + +PREREQS="" + +prereqs() { echo "$PREREQS"; } + +case $1 in + prereqs) + prereqs + exit 0 + ;; +esac + +# Extract kernel parameters +set -- $(cat /proc/cmdline) +for x in "$@"; do + case "$x" in + varlog_size=*) + varlog_size="${x#varlog_size=}" + esac +done + +[ -z "$varlog_size" ] && exit 0 + +# exit when the var_log.ext4 exists and the size matches +if [ -e "${rootmnt}/host/disk-img/var-log.ext4" ]; then + cur_varlog_size=$(ls -l ${rootmnt}/host/disk-img/var-log.ext4 | awk '{print $5}') + if [ $cur_varlog_size == $((1024*1024*$varlog_size)) ]; then + exit 0 + else + rm -rf ${rootmnt}/host/disk-img + fi +fi + +# create varlog disk +case "${ROOT}" in + ubi*) + # sys_fallocate is NOT supported over UBIFS + mkdir -p ${rootmnt}/host/disk-img && ${rootmnt}/usr/bin/truncate -s "$varlog_size"M ${rootmnt}/host/disk-img/var-log.ext4 && mkfs.ext4 -q -F ${rootmnt}/host/disk-img/var-log.ext4 + ;; + *) + mkdir -p ${rootmnt}/host/disk-img && ${rootmnt}/usr/bin/fallocate -l "$varlog_size"M ${rootmnt}/host/disk-img/var-log.ext4 && mkfs.ext4 -q -F ${rootmnt}/host/disk-img/var-log.ext4 + ;; +esac diff --git a/files/scripts/arp_update b/files/scripts/arp_update new file mode 100755 index 000000000000..2fec40c14beb --- /dev/null +++ b/files/scripts/arp_update @@ -0,0 +1,74 @@ +#!/bin/bash +# +# usage: +# arp_update: +# Send ipv6 multicast pings to all "UP" L3 interfaces including vlan interfaces to +# refresh link-local addresses from neighbors. +# Send gratuitous ARP/NDP requests to VLAN member neighbors to refresh +# the ipv4/ipv6 neighbors state. + +ARP_UPDATE_VARS_FILE="/usr/share/sonic/templates/arp_update_vars.j2" + +while /bin/true; do + # find L3 interfaces which are UP, send ipv6 multicast pings + ARP_UPDATE_VARS=$(sonic-cfggen -d -t ${ARP_UPDATE_VARS_FILE}) + INTERFACE=$(echo $ARP_UPDATE_VARS | jq -r '.interface') + PC_INTERFACE=$(echo $ARP_UPDATE_VARS | jq -r '.pc_interface') + + ALL_INTERFACE="$INTERFACE $PC_INTERFACE" + for intf in $ALL_INTERFACE; do + ping6cmd="ping6 -I $intf -n -q -i 0 -c 1 -W 0 ff02::1 >/dev/null" + intf_up=$(ip link show $intf | grep "state UP") + if [[ -n "$intf_up" ]]; then + eval $ping6cmd + fi + done + + VLAN=$(echo $ARP_UPDATE_VARS | jq -r '.vlan') + for vlan in $VLAN; do + # generate a list of arping commands: + # arping -q -w 0 -c 1 -i ; + # arping -q -w 0 -c 1 -i ; + # ... + arpingcmd="sed -e 's/ / -i /' -e 's/^/arping -q -w 0 -c 1 /' -e 's/$/;/'" + ipcmd="ip -4 neigh show | grep $vlan | cut -d ' ' -f 1,3 | $arpingcmd" + + eval `eval $ipcmd` + + # send ipv6 multicast pings to Vlan interfaces to get/refresh link-local addrs + ping6cmd="ping6 -I $vlan -n -q -i 0 -c 1 -W 0 ff02::1 >/dev/null" + eval $ping6cmd + + # generate a list of ndisc6 commands (exclude link-local addrs since it is done above): + # ndisc6 -q -w 0 -1 ; + # ndisc6 -q -w 0 -1 ; + # ... + ndisc6cmd="sed -e 's/^/ndisc6 -q -w 0 -1 /' -e 's/$/;/'" + 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/bgp.sh b/files/scripts/bgp.sh new file mode 100755 index 000000000000..b7a383ebbdd7 --- /dev/null +++ b/files/scripts/bgp.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +function debug() +{ + /usr/bin/logger $1 + /bin/echo `date` "- $1" >> ${DEBUGLOG} +} + +function check_warm_boot() +{ + SYSTEM_WARM_START=`$SONIC_DB_CLI STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable` + SERVICE_WARM_START=`$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 + WARM_BOOT="false" + fi +} + +function validate_restore_count() +{ + if [[ x"$WARM_BOOT" == x"true" ]]; then + RESTORE_COUNT=`$SONIC_DB_CLI STATE_DB hget "WARM_RESTART_TABLE|bgp" restore_count` + # We have to make sure db data has not been flushed. + if [[ -z "$RESTORE_COUNT" ]]; then + WARM_BOOT="false" + fi + fi +} + +function check_fast_boot () +{ + if [[ $($SONIC_DB_CLI STATE_DB GET "FAST_REBOOT|system") == "1" ]]; then + FAST_BOOT="true" + else + FAST_BOOT="false" + fi +} + +start() { + debug "Starting ${SERVICE}$DEV service..." + + check_warm_boot + validate_restore_count + + check_fast_boot + + debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}." + debug "Fast boot flag: ${SERVICE}$DEV ${Fast_BOOT}." + + # start service docker + /usr/bin/${SERVICE}.sh start $DEV + debug "Started ${SERVICE}$DEV service..." + +} + +wait() { + /usr/bin/${SERVICE}.sh wait $DEV +} + +stop() { + debug "Stopping ${SERVICE}$DEV service..." + + check_warm_boot + check_fast_boot + debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}." + debug "Fast boot flag: ${SERVICE}$DEV ${FAST_BOOT}." + + # Kill bgpd to start the bgp graceful restart procedure + if [[ x"$WARM_BOOT" == x"true" ]] || [[ x"$FAST_BOOT" == x"true" ]]; then + debug "Kill zebra first" + /usr/bin/docker exec -i bgp pkill -9 zebra || [ $? == 1 ] + /usr/bin/docker exec -i bgp pkill -9 bgpd || [ $? == 1 ] + fi + + /usr/bin/${SERVICE}.sh stop $DEV + debug "Stopped ${SERVICE}$DEV service..." + +} + +DEV=$2 + +SERVICE="bgp" +DEBUGLOG="/tmp/bgp-debug$DEV.log" +NAMESPACE_PREFIX="asic" +if [ "$DEV" ]; then + NET_NS="$NAMESPACE_PREFIX$DEV" #name of the network namespace + SONIC_DB_CLI="sonic-db-cli -n $NET_NS" +else + NET_NS="" + SONIC_DB_CLI="sonic-db-cli" +fi + +case "$1" in + start|wait|stop) + $1 + ;; + *) + echo "Usage: $0 {start|wait|stop}" + exit 1 + ;; +esac diff --git a/files/scripts/configdb-load.sh b/files/scripts/configdb-load.sh new file mode 100755 index 000000000000..fde2de5c6f2b --- /dev/null +++ b/files/scripts/configdb-load.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# Wait until redis starts +until [[ $(sonic-db-cli PING | grep -c PONG) -gt 0 ]]; do + sleep 1; +done + +# If there is a config_db.json dump file, load it. +if [ -r /etc/sonic/config_db.json ]; then + 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 + +sonic-db-cli CONFIG_DB SET "CONFIG_DB_INITIALIZED" "1" diff --git a/files/scripts/core_cleanup.py b/files/scripts/core_cleanup.py new file mode 100755 index 000000000000..bf68416c7009 --- /dev/null +++ b/files/scripts/core_cleanup.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +import os +from collections import defaultdict +from datetime import datetime + +from sonic_py_common.logger import Logger + +SYSLOG_IDENTIFIER = 'core_cleanup.py' +CORE_FILE_DIR = '/var/core/' +MAX_CORE_FILES = 4 + + +def main(): + logger = Logger(SYSLOG_IDENTIFIER) + logger.set_min_log_priority_info() + + if os.getuid() != 0: + logger.log_error('Root required to clean up core files') + return + + logger.log_info('Cleaning up core files') + core_files = [f for f in os.listdir(CORE_FILE_DIR) if os.path.isfile(os.path.join(CORE_FILE_DIR, f))] + + core_files_by_process = defaultdict(list) + for f in core_files: + process = f.split('.')[0] + curr_files = core_files_by_process[process] + curr_files.append(f) + + if len(curr_files) > MAX_CORE_FILES: + curr_files.sort(reverse=True, key=lambda x: datetime.utcfromtimestamp(int(x.split('.')[1]))) + oldest_core = curr_files[MAX_CORE_FILES] + logger.log_info('Deleting {}'.format(oldest_core)) + try: + os.remove(os.path.join(CORE_FILE_DIR, oldest_core)) + except: + logger.log_error('Unexpected error occured trying to delete {}'.format(oldest_core)) + core_files_by_process[process] = curr_files[0:MAX_CORE_FILES] + + logger.log_info('Finished cleaning up core files') + + +if __name__ == '__main__': + main() diff --git a/files/scripts/gbsyncd.sh b/files/scripts/gbsyncd.sh new file mode 100755 index 000000000000..996fbf8cdf31 --- /dev/null +++ b/files/scripts/gbsyncd.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +. /usr/local/bin/syncd_common.sh + +function startplatform() { + : +} + +function waitplatform() { + : +} + +function stopplatform1() { + : +} + +function stopplatform2() { + : +} + +OP=$1 +DEV=$2 + +SERVICE="gbsyncd" +PEER="swss" +DEBUGLOG="/tmp/swss-gbsyncd-debug$DEV.log" +LOCKFILE="/tmp/swss-gbsyncd-lock$DEV" +NAMESPACE_PREFIX="asic" +if [ "$DEV" ]; then + NET_NS="$NAMESPACE_PREFIX$DEV" #name of the network namespace + SONIC_DB_CLI="sonic-db-cli -n $NET_NS" +else + NET_NS="" + SONIC_DB_CLI="sonic-db-cli" +fi + +case "$1" in + start|wait|stop) + $1 + ;; + *) + echo "Usage: $0 {start|wait|stop}" + exit 1 + ;; +esac diff --git a/files/scripts/radv.sh b/files/scripts/radv.sh new file mode 100755 index 000000000000..1047808e4e44 --- /dev/null +++ b/files/scripts/radv.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +function debug() +{ + /usr/bin/logger $1 + /bin/echo `date` "- $1" >> ${DEBUGLOG} +} + +function check_warm_boot() +{ + SYSTEM_WARM_START=`$SONIC_DB_CLI STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable` + SERVICE_WARM_START=`$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 + WARM_BOOT="false" + fi +} + +function check_fast_boot () +{ + if [[ $($SONIC_DB_CLI STATE_DB GET "FAST_REBOOT|system") == "1" ]]; then + FAST_BOOT="true" + else + FAST_BOOT="false" + fi +} + +start() { + debug "Starting ${SERVICE}$DEV service..." + + check_warm_boot + check_fast_boot + debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}." + debug "Fast boot flag: ${SERVICE}$DEV ${FAST_BOOT}." + + # start service docker + /usr/bin/${SERVICE}.sh start $DEV + debug "Started ${SERVICE}$DEV service..." +} + +wait() { + /usr/bin/${SERVICE}.sh wait $DEV +} + +stop() { + debug "Stopping ${SERVICE}$DEV service..." + + check_warm_boot + check_fast_boot + debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}." + debug "Fast boot flag: ${SERVICE}$DEV ${FAST_BOOT}." + + # For WARM/FAST boot do not perform service stop + if [[ x"$WARM_BOOT" != x"true" ]] && [[ x"$FAST_BOOT" != x"true" ]]; then + /usr/bin/${SERVICE}.sh stop $DEV + debug "Stopped ${SERVICE}$DEV service..." + else + debug "Killing Docker radv..." + /usr/bin/docker kill radv &> /dev/null || debug "Docker radv is not running ($?) ..." + fi +} + +DEV=$2 + +SERVICE="radv" +DEBUGLOG="/tmp/radv-debug$DEV.log" +NAMESPACE_PREFIX="asic" +if [ "$DEV" ]; then + NET_NS="$NAMESPACE_PREFIX$DEV" #name of the network namespace + SONIC_DB_CLI="sonic-db-cli -n $NET_NS" +else + SONIC_DB_CLI="sonic-db-cli" +fi + +case "$1" in + start|wait|stop) + $1 + ;; + *) + echo "Usage: $0 {start|wait|stop}" + exit 1 + ;; +esac 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 new file mode 100755 index 000000000000..e8565b4d52f2 --- /dev/null +++ b/files/scripts/supervisor-proc-exit-listener @@ -0,0 +1,173 @@ +#!/usr/bin/env python3 + +import getopt +import os +import re +import select +import signal +import sys +import syslog +import time + +import swsssdk + +from supervisor import childutils + +# Each line of this file should specify either one critical process or one +# critical process group, (as defined in supervisord.conf file), in the +# following format: +# +# program: +# group: +CRITICAL_PROCESSES_FILE = '/etc/supervisor/critical_processes' + +# The FEATURE table in config db contains auto-restart field +FEATURE_TABLE_NAME = 'FEATURE' + +# Value of parameter 'timeout' in select(...) method +SELECT_TIMEOUT_SECS = 1.0 + +# Alerting message will be written into syslog in the following interval +ALERTING_INTERVAL_SECS = 60 + + +def get_critical_group_and_process_list(): + """ + @summary: Read the critical processes/group names from CRITICAL_PROCESSES_FILE. + @return: Two lists which contain critical processes and group names respectively. + """ + critical_group_list = [] + critical_process_list = [] + + with open(CRITICAL_PROCESSES_FILE, 'r') as file: + for line in file: + # ignore blank lines + if re.match(r"^\s*$", line): + continue + line_info = line.strip(' \n').split(':') + if len(line_info) != 2: + syslog.syslog(syslog.LOG_ERR, + "Syntax of the line {} in critical_processes file is incorrect. Exiting...".format(line)) + sys.exit(5) + + identifier_key = line_info[0].strip() + identifier_value = line_info[1].strip() + if identifier_key == "group" and identifier_value: + critical_group_list.append(identifier_value) + elif identifier_key == "program" and identifier_value: + critical_process_list.append(identifier_value) + else: + syslog.syslog(syslog.LOG_ERR, + "Syntax of the line {} in critical_processes file is incorrect. Exiting...".format(line)) + sys.exit(6) + + return critical_group_list, critical_process_list + + +def generate_alerting_message(process_name): + """ + @summary: If a critical process was not running, this function will determine it resides in host + or in a specific namespace. Then an alerting message will be written into syslog. + """ + namespace_prefix = os.environ.get("NAMESPACE_PREFIX") + namespace_id = os.environ.get("NAMESPACE_ID") + + if not namespace_prefix or not namespace_id: + namespace = "host" + else: + namespace = namespace_prefix + namespace_id + + syslog.syslog(syslog.LOG_ERR, "Process '{}' is not running in namespace '{}'.".format(process_name, namespace)) + + +def get_autorestart_state(container_name): + """ + @summary: Read the status of auto-restart feature from Config_DB. + @return: Return the status of auto-restart feature. + """ + config_db = swsssdk.ConfigDBConnector() + config_db.connect() + features_table = config_db.get_table(FEATURE_TABLE_NAME) + if not features_table: + syslog.syslog(syslog.LOG_ERR, "Unable to retrieve features table from Config DB. Exiting...") + sys.exit(2) + + if container_name not in features_table: + syslog.syslog(syslog.LOG_ERR, "Unable to retrieve feature '{}'. Exiting...".format(container_name)) + sys.exit(3) + + is_auto_restart = features_table[container_name].get('auto_restart') + if not is_auto_restart: + syslog.syslog( + syslog.LOG_ERR, "Unable to determine auto-restart feature status for '{}'. Exiting...".format(container_name)) + sys.exit(4) + + return is_auto_restart + + +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) + + critical_group_list, critical_process_list = get_critical_group_and_process_list() + + process_under_alerting = {} + # Transition from ACKNOWLEDGED to READY + childutils.listener.ready() + + while True: + file_descriptor_list = select.select([sys.stdin], [], [], SELECT_TIMEOUT_SECS)[0] + if len(file_descriptor_list) > 0: + line = file_descriptor_list[0].readline() + headers = childutils.get_headers(line) + payload = sys.stdin.read(int(headers['len'])) + + # Handle the PROCESS_STATE_EXITED event + if headers['eventname'] == 'PROCESS_STATE_EXITED': + payload_headers, payload_data = childutils.eventdata(payload + '\n') + + expected = int(payload_headers['expected']) + process_name = payload_headers['processname'] + group_name = payload_headers['groupname'] + + if (process_name in critical_process_list or group_name in critical_group_list) and expected == 0: + is_auto_restart = get_autorestart_state(container_name) + if is_auto_restart != "disabled": + MSG_FORMAT_STR = "Process '{}' exited unexpectedly. Terminating supervisor '{}'" + msg = MSG_FORMAT_STR.format(payload_headers['processname'], container_name) + syslog.syslog(syslog.LOG_INFO, msg) + os.kill(os.getppid(), signal.SIGTERM) + else: + process_under_alerting[process_name] = time.time() + + # Handle the PROCESS_STATE_RUNNING event + elif headers['eventname'] == 'PROCESS_STATE_RUNNING': + payload_headers, payload_data = childutils.eventdata(payload + '\n') + process_name = payload_headers['processname'] + + if process_name in process_under_alerting: + process_under_alerting.pop(process_name) + + # Transition from BUSY to ACKNOWLEDGED + childutils.listener.ok() + + # Transition from ACKNOWLEDGED to READY + childutils.listener.ready() + + # Check whether we need write alerting messages into syslog + for process in process_under_alerting.keys(): + epoch_time = time.time() + if epoch_time - process_under_alerting[process] >= ALERTING_INTERVAL_SECS: + process_under_alerting[process] = epoch_time + generate_alerting_message(process) + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/files/scripts/swss.sh b/files/scripts/swss.sh new file mode 100755 index 000000000000..97e50cb975e7 --- /dev/null +++ b/files/scripts/swss.sh @@ -0,0 +1,266 @@ +#!/bin/bash + +DEPENDENT="radv dhcp_relay" +MULTI_INST_DEPENDENT="teamd" + +function debug() +{ + /usr/bin/logger $1 + /bin/echo `date` "- $1" >> ${DEBUGLOG} +} + +function lock_service_state_change() +{ + 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}$DEV service" +} + +function unlock_service_state_change() +{ + debug "Unlocking ${LOCKFILE} (${LOCKFD}) from ${SERVICE}$DEV service" + /usr/bin/flock -u ${LOCKFD} +} + +function check_warm_boot() +{ + SYSTEM_WARM_START=`$SONIC_DB_CLI STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable` + SERVICE_WARM_START=`$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 + WARM_BOOT="false" + fi +} + +function check_fast_boot() +{ + if [[ $($SONIC_DB_CLI STATE_DB GET "FAST_REBOOT|system") == "1" ]]; then + FAST_BOOT="true" + else + FAST_BOOT="false" + fi +} + +function validate_restore_count() +{ + if [[ x"$WARM_BOOT" == x"true" ]]; then + RESTORE_COUNT=`$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" + fi + fi +} + +function wait_for_database_service() +{ + # Wait for redis server start before database clean + until [[ $($SONIC_DB_CLI PING | grep -c PONG) -gt 0 ]]; do + sleep 1; + done + + # Wait for configDB initialization + until [[ $($SONIC_DB_CLI CONFIG_DB GET "CONFIG_DB_INITIALIZED") ]]; + do sleep 1; + done +} + +# This function cleans up the tables with specific prefixes from the database +# $1 the index of the database +# $2 the string of a list of table prefixes +function clean_up_tables() +{ + $SONIC_DB_CLI $1 EVAL " + local tables = {$2} + for i = 1, table.getn(tables) do + local matches = redis.call('KEYS', tables[i]) + for j,name in ipairs(matches) do + redis.call('DEL', name) + end + end" 0 +} + +start_peer_and_dependent_services() { + check_warm_boot + + if [[ x"$WARM_BOOT" != x"true" ]]; then + 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/fast start enabled or peer lock exists, don't stop peer service docker + if [[ x"$WARM_BOOT" != x"true" ]] && [[ x"$FAST_BOOT" != x"true" ]]; then + for dep in ${MULTI_INST_DEPENDENT}; do + if [[ ! -z $DEV ]]; then + /bin/systemctl stop ${dep}@$DEV + else + /bin/systemctl stop ${dep} + fi + done + for dep in ${DEPENDENT}; do + /bin/systemctl stop ${dep} + done + if [[ ! -z $DEV ]]; then + /bin/systemctl stop ${PEER}@$DEV + else + /bin/systemctl stop ${PEER} + fi + fi +} + +start() { + debug "Starting ${SERVICE}$DEV service..." + + lock_service_state_change + + wait_for_database_service + check_warm_boot + validate_restore_count + + 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 ..." + $SONIC_DB_CLI APPL_DB FLUSHDB + $SONIC_DB_CLI ASIC_DB FLUSHDB + $SONIC_DB_CLI COUNTERS_DB FLUSHDB + $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*', 'FG_ROUTE_TABLE*', 'BUFFER_POOL*', 'BUFFER_PROFILE*', '*MUX_CABLE_TABLE*'" + fi + + # start service docker + /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 +} + +wait() { + start_peer_and_dependent_services + + # Allow some time for peer container to start + # NOTE: This assumes Docker containers share the same names as their + # corresponding services + for SECS in {1..60}; do + if [[ ! -z $DEV ]]; then + RUNNING=$(docker inspect -f '{{.State.Running}}' ${PEER}$DEV) + else + RUNNING=$(docker inspect -f '{{.State.Running}}' ${PEER}) + fi + ALL_DEPS_RUNNING=true + for dep in ${MULTI_INST_DEPENDENT}; do + if [[ ! -z $DEV ]]; then + DEP_RUNNING=$(docker inspect -f '{{.State.Running}}' ${dep}$DEV) + else + DEP_RUNNING=$(docker inspect -f '{{.State.Running}}' ${dep}) + fi + if [[ x"$DEP_RUNNING" != x"true" ]]; then + ALL_DEPS_RUNNING=false + break + fi + done + + if [[ x"$RUNNING" == x"true" && x"$ALL_DEPS_RUNNING" == x"true" ]]; then + break + else + sleep 1 + fi + done + + # NOTE: This assumes Docker containers share the same names as their + # corresponding services + for dep in ${MULTI_INST_DEPENDENT}; do + if [[ ! -z $DEV ]]; then + ALL_DEPS="$ALL_DEPS ${dep}$DEV" + else + ALL_DEPS="$ALL_DEPS ${dep}" + fi + done + + if [[ ! -z $DEV ]]; then + /usr/bin/docker-wait-any -s ${SERVICE}$DEV -d ${PEER}$DEV ${ALL_DEPS} + else + /usr/bin/docker-wait-any -s ${SERVICE} -d ${PEER} ${ALL_DEPS} + fi +} + +stop() { + debug "Stopping ${SERVICE}$DEV service..." + + [[ -f ${LOCKFILE} ]] || /usr/bin/touch ${LOCKFILE} + + lock_service_state_change + check_warm_boot + debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}." + check_fast_boot + debug "Fast boot flag: ${SERVICE}$DEV ${FAST_BOOT}." + + # For WARM/FAST boot do not perform service stop + if [[ x"$WARM_BOOT" != x"true" ]] && [[ x"$FAST_BOOT" != x"true" ]]; then + /usr/bin/${SERVICE}.sh stop $DEV + debug "Stopped ${SERVICE}$DEV service..." + else + debug "Killing Docker swss..." + /usr/bin/docker kill swss &> /dev/null || debug "Docker swss is not running ($?) ..." + fi + + # 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. + if [[ x"$FAST_BOOT" != x"true" ]]; then + debug "Clearing FAST_REBOOT flag..." + clean_up_tables STATE_DB "'FAST_REBOOT*'" + fi + # Unlock has to happen before reaching out to peer service + unlock_service_state_change + + stop_peer_and_dependent_services +} + +DEV=$2 + +SERVICE="swss" +PEER="syncd" +DEBUGLOG="/tmp/swss-syncd-debug$DEV.log" +LOCKFILE="/tmp/swss-syncd-lock$DEV" +NAMESPACE_PREFIX="asic" +if [ "$DEV" ]; then + NET_NS="$NAMESPACE_PREFIX$DEV" #name of the network namespace + SONIC_DB_CLI="sonic-db-cli -n $NET_NS" +else + NET_NS="" + SONIC_DB_CLI="sonic-db-cli" +fi + +case "$1" in + start|wait|stop) + $1 + ;; + *) + echo "Usage: $0 {start|wait|stop}" + exit 1 + ;; +esac diff --git a/files/scripts/syncd.sh b/files/scripts/syncd.sh new file mode 100755 index 000000000000..95c3e3841ba8 --- /dev/null +++ b/files/scripts/syncd.sh @@ -0,0 +1,117 @@ +#!/bin/bash + +. /usr/local/bin/syncd_common.sh + +function startplatform() { + + # platform specific tasks + + # start mellanox drivers regardless of + # boot type + if [[ x"$sonic_asic_platform" == x"mellanox" ]]; then + BOOT_TYPE=`getBootType` + if [[ x"$WARM_BOOT" == x"true" || x"$BOOT_TYPE" == x"fast" ]]; then + export FAST_BOOT=1 + fi + + if [[ x"$WARM_BOOT" != x"true" ]]; then + if [[ x"$(/bin/systemctl is-active pmon)" == x"active" ]]; then + /bin/systemctl stop pmon + debug "pmon is active while syncd starting, stop it first" + fi + fi + + debug "Starting Firmware update procedure" + /usr/bin/mst start --with_i2cdev + /usr/bin/mlnx-fw-upgrade.sh + /etc/init.d/sxdkernel start + debug "Firmware update procedure ended" + fi + + if [[ x"$WARM_BOOT" != x"true" ]]; then + if [ x$sonic_asic_platform == x'cavium' ]; then + /etc/init.d/xpnet.sh start + fi + fi +} + +function waitplatform() { + + if [[ x"$sonic_asic_platform" == x"mellanox" ]]; then + debug "Starting pmon service..." + /bin/systemctl start pmon + debug "Started pmon service" + fi +} + +function stopplatform1() { + + if [[ x$sonic_asic_platform == x"mellanox" ]] && [[ x$TYPE == x"cold" ]]; then + debug "Stopping pmon service ahead of syncd..." + /bin/systemctl stop pmon + debug "Stopped pmon service" + fi + + if [[ x$sonic_asic_platform != x"mellanox" ]] || [[ x$TYPE != x"cold" ]]; then + debug "${TYPE} shutdown syncd process ..." + /usr/bin/docker exec -i syncd$DEV /usr/bin/syncd_request_shutdown --${TYPE} + + # wait until syncd quits gracefully or force syncd to exit after + # waiting for 20 seconds + start_in_secs=${SECONDS} + end_in_secs=${SECONDS} + timer_threshold=20 + while docker top syncd$DEV | grep -q /usr/bin/syncd \ + && [[ $((end_in_secs - start_in_secs)) -le $timer_threshold ]]; do + sleep 0.1 + end_in_secs=${SECONDS} + done + + if [[ $((end_in_secs - start_in_secs)) -gt $timer_threshold ]]; then + debug "syncd process in container syncd$DEV did not exit gracefully" + fi + + /usr/bin/docker exec -i syncd$DEV /bin/sync + debug "Finished ${TYPE} shutdown syncd process ..." + fi +} + +function stopplatform2() { + # platform specific tasks + + if [[ x"$WARM_BOOT" != x"true" ]]; then + if [ x$sonic_asic_platform == x'mellanox' ]; then + /etc/init.d/sxdkernel stop + /usr/bin/mst stop + elif [ x$sonic_asic_platform == x'cavium' ]; then + /etc/init.d/xpnet.sh stop + /etc/init.d/xpnet.sh start + fi + fi +} + +OP=$1 +DEV=$2 + +SERVICE="syncd" +PEER="swss" +DEBUGLOG="/tmp/swss-syncd-debug$DEV.log" +LOCKFILE="/tmp/swss-syncd-lock$DEV" +NAMESPACE_PREFIX="asic" +if [ "$DEV" ]; then + NET_NS="$NAMESPACE_PREFIX$DEV" #name of the network namespace + SONIC_DB_CLI="sonic-db-cli -n $NET_NS" +else + NET_NS="" + SONIC_DB_CLI="sonic-db-cli" +fi + +case "$1" in + start|wait|stop) + $1 + ;; + *) + echo "Usage: $0 {start|wait|stop}" + exit 1 + ;; +esac diff --git a/files/scripts/syncd_common.sh b/files/scripts/syncd_common.sh new file mode 100755 index 000000000000..0e9fc8ac2d7a --- /dev/null +++ b/files/scripts/syncd_common.sh @@ -0,0 +1,141 @@ +#!/bin/bash + +# +# common functions used by "syncd" scipts (syncd.sh, gbsyncd.sh, etc..) +# scripts using this must provide implementations of the following functions: +# +# startplatform +# waitplatform +# stopplatform1 and stopplatform2 +# +# For examples of these, see gbsyncd.sh and syncd.sh. +# + +function debug() +{ + /usr/bin/logger $1 + /bin/echo `date` "- $1" >> ${DEBUGLOG} +} + +function lock_service_state_change() +{ + 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}$DEV service" +} + +function unlock_service_state_change() +{ + debug "Unlocking ${LOCKFILE} (${LOCKFD}) from ${SERVICE}$DEV service" + /usr/bin/flock -u ${LOCKFD} +} + +function check_warm_boot() +{ + SYSTEM_WARM_START=`$SONIC_DB_CLI STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable` + SERVICE_WARM_START=`$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" + else + WARM_BOOT="false" + fi +} + +function wait_for_database_service() +{ + # Wait for redis server start before database clean + until [[ $($SONIC_DB_CLI PING | grep -c PONG) -gt 0 ]]; do + sleep 1; + done + + # Wait for configDB initialization + until [[ $($SONIC_DB_CLI CONFIG_DB GET "CONFIG_DB_INITIALIZED") ]]; + do sleep 1; + done +} + +function getBootType() +{ + # same code snippet in files/build_templates/docker_image_ctl.j2 + case "$(cat /proc/cmdline)" in + *SONIC_BOOT_TYPE=warm*) + TYPE='warm' + ;; + *SONIC_BOOT_TYPE=fastfast*) + TYPE='fastfast' + ;; + *SONIC_BOOT_TYPE=fast*|*fast-reboot*) + # check that the key exists + if [[ $($SONIC_DB_CLI STATE_DB GET "FAST_REBOOT|system") == "1" ]]; then + TYPE='fast' + else + TYPE='cold' + fi + ;; + *) + TYPE='cold' + esac + echo "${TYPE}" +} + +start() { + debug "Starting ${SERVICE}$DEV service..." + + lock_service_state_change + + mkdir -p /host/warmboot + + wait_for_database_service + check_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. + touch /host/warmboot/warm-starting + else + rm -f /host/warmboot/warm-starting + fi + + startplatform + + # start service docker + /usr/bin/${SERVICE}.sh start $DEV + debug "Started ${SERVICE} service..." + + unlock_service_state_change +} + +wait() { + waitplatform + + /usr/bin/${SERVICE}.sh wait $DEV +} + +stop() { + debug "Stopping ${SERVICE}$DEV service..." + + lock_service_state_change + check_warm_boot + debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}." + + if [[ x"$WARM_BOOT" == x"true" ]]; then + TYPE=warm + else + TYPE=cold + fi + + stopplatform1 + + /usr/bin/${SERVICE}.sh stop $DEV + debug "Stopped ${SERVICE}$DEV service..." + + stopplatform2 + + unlock_service_state_change +} diff --git a/files/scripts/teamd.sh b/files/scripts/teamd.sh new file mode 100755 index 000000000000..626bb5186ca0 --- /dev/null +++ b/files/scripts/teamd.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +function debug() +{ + /usr/bin/logger $1 + /bin/echo `date` "- $1" >> ${DEBUGLOG} +} + +function check_warm_boot() +{ + SYSTEM_WARM_START=`$SONIC_DB_CLI STATE_DB hget "WARM_RESTART_ENABLE_TABLE|system" enable` + SERVICE_WARM_START=`$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 + WARM_BOOT="false" + fi +} + +function validate_restore_count() +{ + if [[ x"$WARM_BOOT" == x"true" ]]; then + RESTORE_COUNT=`$SONIC_DB_CLI STATE_DB hget "WARM_RESTART_TABLE|${SERVICE}" restore_count` + # We have to make sure db data has not been flushed. + if [[ -z "$RESTORE_COUNT" ]]; then + WARM_BOOT="false" + fi + fi +} + +function check_fast_boot () +{ + if [[ $($SONIC_DB_CLI STATE_DB GET "FAST_REBOOT|system") == "1" ]]; then + FAST_BOOT="true" + else + FAST_BOOT="false" + fi +} + +start() { + debug "Starting ${SERVICE}$DEV service..." + + check_warm_boot + validate_restore_count + + check_fast_boot + + debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}." + debug "Fast boot flag: ${SERVICE}$DEV ${Fast_BOOT}." + + # start service docker + /usr/bin/${SERVICE}.sh start $DEV + debug "Started ${SERVICE}$DEV service..." +} + +wait() { + /usr/bin/${SERVICE}.sh wait $DEV +} + +stop() { + debug "Stopping ${SERVICE}$DEV service..." + + check_warm_boot + check_fast_boot + debug "Warm boot flag: ${SERVICE}$DEV ${WARM_BOOT}." + debug "Fast boot flag: ${SERVICE}$DEV ${FAST_BOOT}." + + if [[ x"$WARM_BOOT" == x"true" ]]; then + # Send USR1 signal to all teamd instances to stop them + # It will prepare teamd for warm-reboot + # Note: We must send USR1 signal before syncd, because it will send the last packet through CPU port + docker exec -i ${SERVICE}$DEV pkill -USR1 ${SERVICE} > /dev/null || [ $? == 1 ] + elif [[ x"$FAST_BOOT" == x"true" ]]; then + # Kill teamd processes inside of teamd container with SIGUSR2 to allow them to send last LACP frames + # We call `docker kill teamd` to ensure the container stops as quickly as possible, + # Note: teamd must be killed before syncd, because it will send the last packet through CPU port + docker exec -i ${SERVICE}$DEV pkill -USR2 ${SERVICE} || [ $? == 1 ] + while docker exec -i ${SERVICE}$DEV pgrep ${SERVICE} > /dev/null; do + sleep 0.05 + done + docker kill ${SERVICE}$DEV &> /dev/null || debug "Docker ${SERVICE}$DEV is not running ($?) ..." + fi + + /usr/bin/${SERVICE}.sh stop $DEV + debug "Stopped ${SERVICE}$DEV service..." +} + +DEV=$2 + +SERVICE="teamd" +DEBUGLOG="/tmp/teamd-debug$DEV.log" +NAMESPACE_PREFIX="asic" +if [ "$DEV" ]; then + NET_NS="$NAMESPACE_PREFIX$DEV" #name of the network namespace + SONIC_DB_CLI="sonic-db-cli -n $NET_NS" +else + SONIC_DB_CLI="sonic-db-cli" +fi + +case "$1" in + start|wait|stop) + $1 + ;; + *) + echo "Usage: $0 {start|wait|stop}" + exit 1 + ;; +esac diff --git a/files/scripts/update_chassisdb_config b/files/scripts/update_chassisdb_config new file mode 100755 index 000000000000..292b1df719d9 --- /dev/null +++ b/files/scripts/update_chassisdb_config @@ -0,0 +1,71 @@ +#!/usr/bin/python3 + +import argparse +import json +import os +import syslog + +database_config_file = "/var/run/redis/sonic-db/database_config.json" +redis_chassis = 'redis_chassis' +chassis_db_list = ['CHASSIS_APP_DB', 'CHASSIS_STATE_DB'] + + +def main(): + parser = argparse.ArgumentParser(description="Update chassis_db config from database-config.json") + parser.add_argument("-j", "--json", help="databse-config json file", nargs='?', + const=database_config_file) + parser.add_argument("-p", "--port", help="update port number", nargs='?') + group = parser.add_mutually_exclusive_group() + group.add_argument("-k", "--keep", help="keep configuration", action='store_true') + group.add_argument("-d", "--delete", help="delete configuration", action='store_true') + + args = parser.parse_args() + jsonfile = "" + if args.json != None: + jsonfile = args.json + else: + return + if args.port != None: + port_number = args.port + else: + port_number = "" + if args.keep: + keep_config = True + else: + keep_config = False + if args.delete: + delete_config = True + else: + delete_config = False + data = {} + data_keep = {} + if os.path.isfile(jsonfile): + with open(jsonfile, "r") as read_file: + data = json.load(read_file) + else: + syslog.syslog(syslog.LOG_ERR, + 'config file {} does notexist'.format(jsonfile)) + return + if 'INSTANCES' in data and redis_chassis in data['INSTANCES']: + data_keep['INSTANCES'] = {} + data_keep['INSTANCES'][redis_chassis] = data['INSTANCES'][redis_chassis] + if delete_config: + del data['INSTANCES'][redis_chassis] + for chassis_db in chassis_db_list: + if 'DATABASES' in data and chassis_db in data['DATABASES']: + data_keep['DATABASES'] = {} + data_keep['DATABASES'][chassis_db] = data['DATABASES'][chassis_db] + if delete_config: + del data['DATABASES'][chassis_db] + + with open(jsonfile, "w") as write_file: + data_publish = data_keep if keep_config else data + if port_number: + data_publish['INSTANCES']['redis_chassis']['port'] = int(port_number) + json.dump(data_publish, write_file, indent=4, separators=(',', ': ')) + syslog.syslog(syslog.LOG_INFO, + 'remove chassis_db from config file {}'.format(jsonfile)) + + +if __name__ == "__main__": + main() diff --git a/files/sources.list b/files/sources.list deleted file mode 100644 index d2aaf4251bb3..000000000000 --- a/files/sources.list +++ /dev/null @@ -1,8 +0,0 @@ -deb http://httpredir.debian.org/debian jessie main contrib non-free -deb-src http://httpredir.debian.org/debian jessie main contrib non-free - -deb http://httpredir.debian.org/debian jessie-updates main contrib non-free -deb-src http://httpredir.debian.org/debian jessie-updates main contrib non-free - -deb http://security.debian.org/ jessie/updates main contrib non-free -deb-src http://security.debian.org/ jessie/updates main contrib non-free diff --git a/files/sshd/host-ssh-keygen.sh b/files/sshd/host-ssh-keygen.sh new file mode 100755 index 000000000000..d4ea5bd431c1 --- /dev/null +++ b/files/sshd/host-ssh-keygen.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e + +[ -r /etc/ssh/ssh_host_rsa_key ] || { + rm -f /etc/ssh/ssh_host_*_key* + /usr/bin/ssh-keygen -t rsa -N '' -f /etc/ssh/ssh_host_rsa_key +} diff --git a/files/sshd/sshd.service b/files/sshd/sshd.service new file mode 100644 index 000000000000..25d524171c6f --- /dev/null +++ b/files/sshd/sshd.service @@ -0,0 +1,18 @@ +[Unit] +Description=OpenBSD Secure Shell server +After=network.target auditd.service +ConditionPathExists=!/etc/ssh/sshd_not_to_be_run + +[Service] +EnvironmentFile=-/etc/default/ssh +ExecStartPre=-/usr/local/bin/host-ssh-keygen.sh +ExecStart=/usr/sbin/sshd -D $SSHD_OPTS +ExecReload=/bin/kill -HUP $MAINPID +KillMode=process +Restart=on-failure +RuntimeDirectory=sshd +RuntimeDirectoryMode=0755 + +[Install] +WantedBy=multi-user.target +Alias=sshd.service diff --git a/functions.sh b/functions.sh index b9e7ee0b55e6..6015704d58dd 100644 --- a/functions.sh +++ b/functions.sh @@ -36,3 +36,33 @@ die() { warn "$message" exit 1 } + +docker_try_rmi() { + local image_name="$1" + ## Note: inspect output has quotation characters, so sed to remove it as an argument + local image_id=$(docker inspect --format="{{json .Id}}" $image_name | sed -e 's/^"//' -e 's/"$//') + [ -z "$image_id" ] || { + ## Remove all the exited containers from this image + docker ps -a -q -f "status=exited" -f "ancestor=$1" | xargs --no-run-if-empty docker rm + ## Note: If there are running containers from this image, the build system is in an + ## unexpected state. The 'rmi' will fail and we need investigate the build environment. + docker rmi $image_name + } +} + +sonic_get_version() { + local describe=$(git describe --tags) + local latest_tag=$(git describe --tags --abbrev=0) + local branch_name=$(git rev-parse --abbrev-ref HEAD) + if [ -n "$(git status --untracked-files=no -s --ignore-submodules)" ]; then + local dirty="-dirty-$BUILD_TIMESTAMP" + fi + BUILD_NUMBER=${BUILD_NUMBER:-0} + ## Check if we are on tagged commit + ## Note: escape the version string by sed: / -> _ + if [ -n "$latest_tag" ] && [ "$describe" == "$latest_tag" ]; then + echo "${latest_tag}${dirty}" | sed 's/\//_/g' + else + echo "${branch_name}.${BUILD_NUMBER}${dirty:--$(git rev-parse --short HEAD)}" | sed 's/\//_/g' + fi +} diff --git a/get_deps.sh b/get_deps.sh deleted file mode 100755 index 145caf620af9..000000000000 --- a/get_deps.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -## This script is to build the dependencies of an ONIE installer image -## -## USAGE: -## ./get_deps.sh - -# Obtaining the initramfs-tools -rm -rf deps/initramfs-tools -git clone --branch v0.120 https://anonscm.debian.org/git/kernel/initramfs-tools.git deps/initramfs-tools - -# Patch -pushd deps/initramfs-tools -patch -p1 < $OLDPWD/patch/initramfs-tools/loopback-file-system-support.patch - -# Build the package -fakeroot debian/rules clean -fakeroot debian/rules binary - -popd diff --git a/get_docker-base.sh b/get_docker-base.sh new file mode 100755 index 000000000000..ff2bdeaff02b --- /dev/null +++ b/get_docker-base.sh @@ -0,0 +1,21 @@ +#!/bin/bash +## This script is to retrieve and import the docker-base image from +## local folder where the image is built on the local machine +## +## USAGE: +## ./get_docker-base.sh + +set -x -e + +. ./functions.sh + +TARGET_PATH=$(sed -n 's/TARGET_PATH\s*=\s*//p' slave.mk) + +## [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Read-only link of Azure Blob storage with shared access signature (SAS)")] +BASE_URL="https://sonicstorage.blob.core.windows.net/packages/docker-base.ea507753d98b0769e2a15be13003331f8ad38d1c15b40a683e05fc53b1463b10.gz?sv=2015-04-05&sr=b&sig=YNN6eYVMEFndUaiHIRnqcZFdDZwIG%2BaAuVj0IoyDWPw%3D&se=2026-10-27T20%3A46%3A18Z&sp=r" + +base_image_name=docker-base +docker_try_rmi $base_image_name +mkdir -p $TARGET_PATH +wget --no-use-server-timestamps -O $TARGET_PATH/$base_image_name.gz "$BASE_URL" +docker load < $TARGET_PATH/$base_image_name.gz diff --git a/installer/arm64/install.sh b/installer/arm64/install.sh new file mode 100755 index 000000000000..280d9f200af9 --- /dev/null +++ b/installer/arm64/install.sh @@ -0,0 +1,164 @@ +#!/bin/sh + +# Copyright (C) Marvell Inc +# + +_trap_push() { + local next="$1" + eval "trap_push() { + local oldcmd='$(echo "$next" | sed -e s/\'/\'\\\\\'\'/g)' + local newcmd=\"\$1; \$oldcmd\" + trap -- \"\$newcmd\" EXIT INT TERM HUP + _trap_push \"\$newcmd\" + }" +} +_trap_push true + +set -e + +if [ -d "/etc/sonic" ]; then + echo "Installing SONiC in SONiC" + install_env="sonic" +elif grep -Fxqs "DISTRIB_ID=onie" /etc/lsb-release > /dev/null +then + echo "Installing SONiC in ONIE" + install_env="onie" +else + echo "Installing SONiC in BUILD" + install_env="build" +fi + +cd $(dirname $0) +if [ -r ./machine.conf ]; then + . ./machine.conf +fi + +if [ -r ./onie-image-arm64.conf ]; then + . ./onie-image-arm64.conf +fi + +echo "ONIE Installer: platform: $platform" + +# Make sure run as root or under 'sudo' +if [ $(id -u) -ne 0 ] + then echo "Please run as root" + exit 1 +fi + +if [ -r /etc/machine.conf ]; then + . /etc/machine.conf +elif [ -r /host/machine.conf ]; then + . /host/machine.conf +elif [ "$install_env" != "build" ]; then + echo "cannot find machine.conf" + exit 1 +fi + +echo "onie_platform: $onie_platform" + +# Get platform specific linux kernel command line arguments +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="" + +# Default var/log device size in MB +VAR_LOG_SIZE=4096 + +[ -r platforms/$onie_platform ] && . platforms/$onie_platform + + +# If running in ONIE +if [ "$install_env" = "onie" ]; then + # The onie bin tool prefix + onie_bin= + # The persistent ONIE directory location + onie_root_dir=/mnt/onie-boot/onie + # The onie file system root + onie_initrd_tmp=/ +fi + +# The build system prepares this script by replacing %%DEMO-TYPE%% +# with "OS" or "DIAG". +demo_type="%%DEMO_TYPE%%" + +# The build system prepares this script by replacing %%IMAGE_VERSION%% +# with git revision hash as a version identifier +image_version="%%IMAGE_VERSION%%" +timestamp="$(date -u +%Y%m%d)" + +demo_volume_label="SONiC-${demo_type}" +demo_volume_revision_label="SONiC-${demo_type}-${image_version}" + + +. ./platform.conf + +image_dir="image-$image_version" + +if [ "$install_env" = "onie" ]; then + # Create/format the flash + create_partition + mount_partition +elif [ "$install_env" = "sonic" ]; then + demo_mnt="/host" + eval running_sonic_revision=$(cat /etc/sonic/sonic_version.yml | grep build_version | cut -f2 -d" ") + # Prevent installing existing SONiC if it is running + if [ "$image_dir" = "image-$running_sonic_revision" ]; then + echo "Not installing SONiC version $running_sonic_revision, as current running SONiC has the same version" + exit 0 + fi + # Remove extra SONiC images if any + for f in $demo_mnt/image-* ; do + if [ -d $f ] && [ "$f" != "$demo_mnt/image-$running_sonic_revision" ] && [ "$f" != "$demo_mnt/$image_dir" ]; then + echo "Removing old SONiC installation $f" + rm -rf $f + fi + done +fi + +# Create target directory or clean it up if exists +if [ -d $demo_mnt/$image_dir ]; then + echo "Directory $demo_mnt/$image_dir/ already exists. Cleaning up..." + rm -rf $demo_mnt/$image_dir/* +else + mkdir $demo_mnt/$image_dir || { + echo "Error: Unable to create SONiC directory" + exit 1 + } +fi + +# Decompress the file for the file system directly to the partition +if [ x"$docker_inram" = x"on" ]; then + # when disk is small, keep dockerfs.tar.gz in disk, expand it into ramfs during initrd + unzip -o $ONIE_INSTALLER_PAYLOAD -d $demo_mnt/$image_dir +else + unzip -o $ONIE_INSTALLER_PAYLOAD -x "$FILESYSTEM_DOCKERFS" -d $demo_mnt/$image_dir + + if [ "$install_env" = "onie" ]; then + TAR_EXTRA_OPTION="--numeric-owner" + else + TAR_EXTRA_OPTION="--numeric-owner --warning=no-timestamp" + fi + mkdir -p $demo_mnt/$image_dir/$DOCKERFS_DIR + unzip -op $ONIE_INSTALLER_PAYLOAD "$FILESYSTEM_DOCKERFS" | tar xz $TAR_EXTRA_OPTION -f - -C $demo_mnt/$image_dir/$DOCKERFS_DIR +fi + + +if [ "$install_env" = "onie" ]; then + # Store machine description in target file system + if [ -f /etc/machine-build.conf ]; then + # onie_ variable are generate at runtime. + # they are no longer hardcoded in /etc/machine.conf + # also remove single quotes around the value + set | grep ^onie | sed -e "s/='/=/" -e "s/'$//" > $demo_mnt/machine.conf + else + cp /etc/machine.conf $demo_mnt + fi +fi + +# Update Bootloader Menu with installed image +bootloader_menu_config + +# Set NOS mode if available. For manufacturing diag installers, you +# probably want to skip this step so that the system remains in ONIE +# "installer" mode for installing a true NOS later. +if [ -x /bin/onie-nos-mode ] ; then + /bin/onie-nos-mode -s +fi diff --git a/installer/armhf/install.sh b/installer/armhf/install.sh new file mode 100755 index 000000000000..53f2fdf99661 --- /dev/null +++ b/installer/armhf/install.sh @@ -0,0 +1,164 @@ +#!/bin/sh + +# Copyright (C) Marvell Inc +# + +_trap_push() { + local next="$1" + eval "trap_push() { + local oldcmd='$(echo "$next" | sed -e s/\'/\'\\\\\'\'/g)' + local newcmd=\"\$1; \$oldcmd\" + trap -- \"\$newcmd\" EXIT INT TERM HUP + _trap_push \"\$newcmd\" + }" +} +_trap_push true + +set -e + +if [ -d "/etc/sonic" ]; then + echo "Installing SONiC in SONiC" + install_env="sonic" +elif grep -Fxqs "DISTRIB_ID=onie" /etc/lsb-release > /dev/null +then + echo "Installing SONiC in ONIE" + install_env="onie" +else + echo "Installing SONiC in BUILD" + install_env="build" +fi + +cd $(dirname $0) +if [ -r ./machine.conf ]; then + . ./machine.conf +fi + +if [ -r ./onie-image-armhf.conf ]; then + . ./onie-image-armhf.conf +fi + +echo "ONIE Installer: platform: $platform" + +# Make sure run as root or under 'sudo' +if [ $(id -u) -ne 0 ] + then echo "Please run as root" + exit 1 +fi + +if [ -r /etc/machine.conf ]; then + . /etc/machine.conf +elif [ -r /host/machine.conf ]; then + . /host/machine.conf +elif [ "$install_env" != "build" ]; then + echo "cannot find machine.conf" + exit 1 +fi + +echo "onie_platform: $onie_platform" + +# Get platform specific linux kernel command line arguments +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="" + +# Default var/log device size in MB +VAR_LOG_SIZE=4096 + +[ -r platforms/$onie_platform ] && . platforms/$onie_platform + + +# If running in ONIE +if [ "$install_env" = "onie" ]; then + # The onie bin tool prefix + onie_bin= + # The persistent ONIE directory location + onie_root_dir=/mnt/onie-boot/onie + # The onie file system root + onie_initrd_tmp=/ +fi + +# The build system prepares this script by replacing %%DEMO-TYPE%% +# with "OS" or "DIAG". +demo_type="%%DEMO_TYPE%%" + +# The build system prepares this script by replacing %%IMAGE_VERSION%% +# with git revision hash as a version identifier +image_version="%%IMAGE_VERSION%%" +timestamp="$(date -u +%Y%m%d)" + +demo_volume_label="SONiC-${demo_type}" +demo_volume_revision_label="SONiC-${demo_type}-${image_version}" + + +. ./platform.conf + +image_dir="image-$image_version" + +if [ "$install_env" = "onie" ]; then + # Create/format the flash + create_partition + mount_partition +elif [ "$install_env" = "sonic" ]; then + demo_mnt="/host" + eval running_sonic_revision=$(cat /etc/sonic/sonic_version.yml | grep build_version | cut -f2 -d" ") + # Prevent installing existing SONiC if it is running + if [ "$image_dir" = "image-$running_sonic_revision" ]; then + echo "Not installing SONiC version $running_sonic_revision, as current running SONiC has the same version" + exit 0 + fi + # Remove extra SONiC images if any + for f in $demo_mnt/image-* ; do + if [ -d $f ] && [ "$f" != "$demo_mnt/image-$running_sonic_revision" ] && [ "$f" != "$demo_mnt/$image_dir" ]; then + echo "Removing old SONiC installation $f" + rm -rf $f + fi + done +fi + +# Create target directory or clean it up if exists +if [ -d $demo_mnt/$image_dir ]; then + echo "Directory $demo_mnt/$image_dir/ already exists. Cleaning up..." + rm -rf $demo_mnt/$image_dir/* +else + mkdir $demo_mnt/$image_dir || { + echo "Error: Unable to create SONiC directory" + exit 1 + } +fi + +# Decompress the file for the file system directly to the partition +if [ x"$docker_inram" = x"on" ]; then + # when disk is small, keep dockerfs.tar.gz in disk, expand it into ramfs during initrd + unzip -o $ONIE_INSTALLER_PAYLOAD -d $demo_mnt/$image_dir +else + unzip -o $ONIE_INSTALLER_PAYLOAD -x "$FILESYSTEM_DOCKERFS" -d $demo_mnt/$image_dir + + if [ "$install_env" = "onie" ]; then + TAR_EXTRA_OPTION="--numeric-owner" + else + TAR_EXTRA_OPTION="--numeric-owner --warning=no-timestamp" + fi + mkdir -p $demo_mnt/$image_dir/$DOCKERFS_DIR + unzip -op $ONIE_INSTALLER_PAYLOAD "$FILESYSTEM_DOCKERFS" | tar xz $TAR_EXTRA_OPTION -f - -C $demo_mnt/$image_dir/$DOCKERFS_DIR +fi + + +if [ "$install_env" = "onie" ]; then + # Store machine description in target file system + if [ -f /etc/machine-build.conf ]; then + # onie_ variable are generate at runtime. + # they are no longer hardcoded in /etc/machine.conf + # also remove single quotes around the value + set | grep ^onie | sed -e "s/='/=/" -e "s/'$//" > $demo_mnt/machine.conf + else + cp /etc/machine.conf $demo_mnt + fi +fi + +# Update Bootloader Menu with installed image +bootloader_menu_config + +# Set NOS mode if available. For manufacturing diag installers, you +# probably want to skip this step so that the system remains in ONIE +# "installer" mode for installing a true NOS later. +if [ -x /bin/onie-nos-mode ] ; then + /bin/onie-nos-mode -s +fi diff --git a/installer/sharch_body.sh b/installer/sharch_body.sh index 8260d0fd00e6..d22fe26b6998 100644 --- a/installer/sharch_body.sh +++ b/installer/sharch_body.sh @@ -27,6 +27,7 @@ echo " OK." # Untar and launch install script in a tmpfs cur_wd=$(pwd) +export cur_wd archive_path=$(realpath "$0") tmp_dir=$(mktemp -d) if [ "$(id -u)" = "0" ] ; then diff --git a/installer/x86_64/install.sh b/installer/x86_64/install.sh index 528c14727280..a21054db3689 100755 --- a/installer/x86_64/install.sh +++ b/installer/x86_64/install.sh @@ -5,10 +5,6 @@ # # SPDX-License-Identifier: GPL-2.0 -# Function definitions -# wc -l -line_count() { return $(echo $1 | wc -l); } - # Appends a command to a trap, which is needed because default trap behavior is to replace # previous trap for the same signal # - 1st arg: code to add @@ -24,12 +20,49 @@ _trap_push() { } _trap_push true +read_conf_file() { + local conf_file=$1 + while IFS='=' read -r var value || [ -n "$var" ] + do + # remove newline character + var=$(echo $var | tr -d '\r\n') + value=$(echo $value | tr -d '\r\n') + # remove comment string + var=${var%#*} + value=${value%#*} + # skip blank line + [ -z "$var" ] && continue + # remove double quote in the beginning + tmp_val=${value#\"} + # remove double quote in the end + value=${tmp_val%\"} + eval "$var=\"$value\"" + done < "$conf_file" +} + # Main set -e cd $(dirname $0) -. ./machine.conf +if [ -d "/etc/sonic" ]; then + echo "Installing SONiC in SONiC" + install_env="sonic" +elif grep -Fxqs "DISTRIB_ID=onie" /etc/lsb-release > /dev/null +then + echo "Installing SONiC in ONIE" + install_env="onie" +else + echo "Installing SONiC in BUILD" + install_env="build" +fi + +if [ -r ./machine.conf ]; then + read_conf_file "./machine.conf" +fi + +if [ -r ./onie-image.conf ]; then . ./onie-image.conf +fi echo "ONIE Installer: platform: $platform" @@ -39,59 +72,95 @@ if [ $(id -u) -ne 0 ] exit 1 fi +# get running machine from conf file +if [ -r /etc/machine.conf ]; then + read_conf_file "/etc/machine.conf" +elif [ -r /host/machine.conf ]; then + read_conf_file "/host/machine.conf" +elif [ "$install_env" != "build" ]; then + echo "cannot find machine.conf" + exit 1 +fi + +echo "onie_platform: $onie_platform" + +# Get platform specific linux kernel command line arguments +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="" + +# Default var/log device size in MB +VAR_LOG_SIZE=4096 + +[ -r platforms/$onie_platform ] && . platforms/$onie_platform + +# Pick up console port and speed from install enviroment if not defined yet. +# Console port and speed setting in cmdline is like "console=ttyS0,9600n", +# so we can use pattern 'console=ttyS[0-9]+,[0-9]+' to match it. +# If failed to get the speed and ttyS from cmdline then set them to default: ttyS0 and 9600 +if [ -z "$CONSOLE_PORT" ]; then + console_ttys=$(cat /proc/cmdline | grep -Eo 'console=ttyS[0-9]+' | cut -d "=" -f2) + if [ -z "$console_ttys" -o "$console_ttys" = "ttyS0" ]; then + CONSOLE_PORT=0x3f8 + CONSOLE_DEV=0 + elif [ "$console_ttys" = "ttyS1" ]; then + CONSOLE_PORT=0x2f8 + CONSOLE_DEV=1 + elif [ "$console_ttys" = "ttyS2" ]; then + CONSOLE_PORT=0x3e8 + CONSOLE_DEV=2 + elif [ "$console_ttys" = "ttyS3" ]; then + CONSOLE_PORT=0x2e8 + CONSOLE_DEV=3 + fi +fi + +if [ -z "$CONSOLE_SPEED" ]; then + speed=$(cat /proc/cmdline | grep -Eo 'console=ttyS[0-9]+,[0-9]+' | cut -d "," -f2) + if [ -z "$speed" ]; then + CONSOLE_SPEED=9600 + else + CONSOLE_SPEED=$speed + fi +fi + # Install demo on same block device as ONIE -onie_dev=$(blkid | grep ONIE-BOOT | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//') -blk_dev=$(echo $onie_dev | sed -e 's/[1-9][0-9]*$//' | sed -e 's/\([0-9]\)\(p\)/\1/') -# Note: ONIE has no mount setting for / with device node, so below will be empty string -cur_part=$(cat /proc/mounts | awk "{ if(\$2==\"/\") print \$1 }" | grep $blk_dev || true) +if [ "$install_env" != "build" ]; then + onie_dev=$(blkid | grep ONIE-BOOT | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//') + blk_dev=$(echo $onie_dev | sed -e 's/[1-9][0-9]*$//' | sed -e 's/\([0-9]\)\(p\)/\1/') -[ -b "$blk_dev" ] || { - echo "Error: Unable to determine block device of ONIE install" - exit 1 -} + # check if we have an nvme device + blk_suffix= + echo $blk_dev | grep -q nvme0 && blk_suffix="p" + + # Note: ONIE has no mount setting for / with device node, so below will be empty string + cur_part=$(cat /proc/mounts | awk "{ if(\$2==\"/\") print \$1 }" | grep $blk_dev || true) + + [ -b "$blk_dev" ] || { + echo "Error: Unable to determine block device of ONIE install" + exit 1 + } +fi # If running in ONIE -if [ "$onie_dev" = "$cur_part" ] || [ -z "$cur_part" ]; then +if [ "$install_env" = "onie" ]; then # The onie bin tool prefix onie_bin= # The persistent ONIE directory location onie_root_dir=/mnt/onie-boot/onie # The onie file system root onie_initrd_tmp=/ -# Else running in normal Linux -else - # Mount ONIE-BOOT partition - onie_mnt=$(mktemp -d) || { - echo "Error: Unable to create file system mount point" - exit 1 - } - trap_push "fuser -km $onie_mnt || umount $onie_mnt || rmdir $onie_mnt || true" - mount $onie_dev $onie_mnt - onie_root_dir=$onie_mnt/onie - - # Mount initrd inside ONIE-BOOT partition - onie_initrd_tmp=$(mktemp -d) || { - echo "Error: Unable to create file system mount point" - exit 1 - } - trap_push "rm -rf $onie_initrd_tmp || true" - cd $onie_initrd_tmp - # Note: use wildcard in filename below to prevent hard-code version - cat $onie_mnt/onie/initrd.img-*-onie | unxz | cpio -id - cd - - onie_bin="chroot $onie_initrd_tmp" fi # The build system prepares this script by replacing %%DEMO-TYPE%% # with "OS" or "DIAG". demo_type="%%DEMO_TYPE%%" -# The build system prepares this script by replacing %%GIT_REVISION%% +# The build system prepares this script by replacing %%IMAGE_VERSION%% # with git revision hash as a version identifier -git_revision="%%GIT_REVISION%%" +image_version="%%IMAGE_VERSION%%" +timestamp="$(date -u +%Y%m%d)" -demo_volume_label="ACS-${demo_type}" -demo_volume_revision_label="ACS-${demo_type}-${git_revision}" +demo_volume_label="SONiC-${demo_type}" +demo_volume_revision_label="SONiC-${demo_type}-${image_version}" # auto-detect whether BIOS or UEFI if [ -d "/sys/firmware/efi/efivars" ] ; then @@ -100,27 +169,31 @@ else firmware="bios" fi -# determine ONIE partition type -onie_partition_type=$(${onie_bin} onie-sysinfo -t) -# demo partition size in MB -demo_part_size="%%ONIE_IMAGE_PART_SIZE%%" -if [ "$firmware" = "uefi" ] ; then - create_demo_partition="create_demo_uefi_partition" -elif [ "$onie_partition_type" = "gpt" ] ; then - create_demo_partition="create_demo_gpt_partition" -elif [ "$onie_partition_type" = "msdos" ] ; then - create_demo_partition="create_demo_msdos_partition" -else - echo "ERROR: Unsupported partition type: $onie_partition_type" - exit 1 +if [ "$install_env" = "onie" ]; then + # determine ONIE partition type + onie_partition_type=$(${onie_bin} onie-sysinfo -t) + # demo partition size in MB + demo_part_size="%%ONIE_IMAGE_PART_SIZE%%" + if [ "$firmware" = "uefi" ] ; then + create_demo_partition="create_demo_uefi_partition" + elif [ "$onie_partition_type" = "gpt" ] ; then + create_demo_partition="create_demo_gpt_partition" + elif [ "$onie_partition_type" = "msdos" ] ; then + create_demo_partition="create_demo_msdos_partition" + else + echo "ERROR: Unsupported partition type: $onie_partition_type" + exit 1 + fi fi # Creates a new partition for the DEMO OS. -# +# # arg $1 -- base block device # # Returns the created partition number in $demo_part demo_part="" +# TODO: remove reference to "ACS-OS" after all baseimages are upgraded +legacy_volume_label="ACS-OS" create_demo_gpt_partition() { blk_dev="$1" @@ -129,9 +202,9 @@ create_demo_gpt_partition() tmpfifo=$(mktemp -u) trap_push "rm $tmpfifo || true" mkfifo -m 600 "$tmpfifo" - + # See if demo partition already exists - demo_part=$(sgdisk -p $blk_dev | grep "$demo_volume_label" | awk '{print $1}') + demo_part=$(sgdisk -p $blk_dev | grep -e "$demo_volume_label" -e "$legacy_volume_label" | awk '{print $1}') if [ -n "$demo_part" ] ; then # delete existing partitions # if there are multiple partitions matched, we should delete each one, except the current OS's @@ -140,11 +213,21 @@ create_demo_gpt_partition() while read -r part_index; do if [ "$blk_dev$part_index" = "$cur_part" ]; then continue; fi echo "deleting partition $part_index ..." + # if the partition is already mounted, umount first + df $blk_dev$part_index 2>/dev/null && { + umount $blk_dev$part_index || { + echo "Error: Unable to umount $blk_dev$part_index" + exit 1 + } + } sgdisk -d $part_index $blk_dev || { echo "Error: Unable to delete partition $part_index on $blk_dev" exit 1 } - partprobe + partprobe || { + echo "Error: Unable to partprobe" + exit 1 + } done < $tmpfifo fi @@ -167,7 +250,7 @@ create_demo_gpt_partition() echo "Partition #$demo_part is available" # Create new partition - echo "Creating new $demo_volume_label partition ${blk_dev}$demo_part ..." + echo "Creating new $demo_volume_label partition ${blk_dev}${blk_suffix}$demo_part ..." if [ "$demo_type" = "DIAG" ] ; then # set the GPT 'system partition' attribute bit for the DIAG @@ -178,13 +261,14 @@ create_demo_gpt_partition() fi sgdisk --new=${demo_part}::+${demo_part_size}MB \ --attributes=${demo_part}:=:$attr_bitmask \ - --change-name=${demo_part}:$demo_volume_revision_label $blk_dev \ + --change-name=${demo_part}:$demo_volume_label $blk_dev \ || { + echo "Warning: The first trial of creating partition failed, trying the largest aligned available block of sectors on the disk" begin=$(sgdisk -F $blk_dev) end=$(sgdisk -E $blk_dev) sgdisk --new=${demo_part}:$begin:$end \ --attributes=${demo_part}:=:$attr_bitmask \ - --change-name=${demo_part}:$demo_volume_revision_label $blk_dev + --change-name=${demo_part}:$demo_volume_label $blk_dev } || { echo "Error: Unable to create partition $demo_part on $blk_dev" exit 1 @@ -202,7 +286,7 @@ create_demo_msdos_partition() # See if demo partition already exists -- look for the filesystem # label. - part_info="$(blkid | grep $demo_volume_label | awk -F: '{print $1}')" + part_info="$(blkid | grep -e "$demo_volume_label" -e "$legacy_volume_label" | awk -F: '{print $1}')" if [ -n "$part_info" ] ; then # delete existing partition demo_part="$(echo -n $part_info | sed -e s#${blk_dev}##)" @@ -245,7 +329,7 @@ create_demo_uefi_partition() create_demo_gpt_partition "$1" # erase any related EFI BootOrder variables from NVRAM. - for b in $(efibootmgr | grep "$demo_volume_label" | awk '{ print $1 }') ; do + for b in $(efibootmgr | grep -e "$demo_volume_label" -e "$legacy_volume_label" | awk '{ print $1 }') ; do local num=${b#Boot} # Remove trailing '*' num=${num%\*} @@ -297,6 +381,7 @@ demo_install_grub() cat $grub_install_log && rm -f $grub_install_log exit 1 } + rm -f $grub_install_log # restore immutable flag on the core.img file as discussed @@ -336,7 +421,7 @@ demo_install_uefi_grub() grub_install_log=$(mktemp) grub-install \ --no-nvram \ - --bootloader-id="$onie_initrd_tmp/$demo_volume_label" \ + --bootloader-id="$demo_volume_label" \ --efi-directory="/boot/efi" \ --boot-directory="$demo_mnt" \ --recheck \ @@ -359,35 +444,103 @@ demo_install_uefi_grub() } -eval $create_demo_partition $blk_dev -demo_dev=$(echo $blk_dev | sed -e 's/\(mmcblk[0-9]\)/\1p/')$demo_part +image_dir="image-$image_version" -# Make filesystem -mkfs.ext4 -L $demo_volume_revision_label $demo_dev +if [ "$install_env" = "onie" ]; then + eval $create_demo_partition $blk_dev + demo_dev=$(echo $blk_dev | sed -e 's/\(mmcblk[0-9]\)/\1p/')$demo_part + echo $blk_dev | grep -q nvme0 && demo_dev=$(echo $blk_dev | sed -e 's/\(nvme[0-9]n[0-9]\)/\1p/')$demo_part -# Mount demo filesystem -demo_mnt=$(${onie_bin} mktemp -d) || { - echo "Error: Unable to create file system mount point" - exit 1 -} -trap_push "${onie_bin} fuser -km $demo_mnt || ${onie_bin} umount $demo_mnt || ${onie_bin} rmdir $demo_mnt || true" -${onie_bin} mount -t ext4 -o defaults,rw $demo_dev $demo_mnt || { - echo "Error: Unable to mount $demo_dev on $demo_mnt" - exit 1 -} + # Make filesystem + mkfs.ext4 -L $demo_volume_label $demo_dev -# Decompress the file for the file system directly to the partition -unzip $ONIE_INSTALLER_PAYLOAD -d $demo_mnt + # Mount demo filesystem + demo_mnt=$(${onie_bin} mktemp -d) || { + echo "Error: Unable to create file system mount point" + exit 1 + } + trap_push "${onie_bin} fuser -km $demo_mnt || ${onie_bin} umount $demo_mnt || ${onie_bin} rmdir $demo_mnt || true" + ${onie_bin} mount -t ext4 -o defaults,rw $demo_dev $demo_mnt || { + echo "Error: Unable to mount $demo_dev on $demo_mnt" + exit 1 + } + +elif [ "$install_env" = "sonic" ]; then + demo_mnt="/host" + eval running_sonic_revision=$(cat /etc/sonic/sonic_version.yml | grep build_version | cut -f2 -d" ") + # Prevent installing existing SONiC if it is running + if [ "$image_dir" = "image-$running_sonic_revision" ]; then + echo "Not installing SONiC version $running_sonic_revision, as current running SONiC has the same version" + exit 0 + fi + # Remove extra SONiC images if any + for f in $demo_mnt/image-* ; do + if [ -d $f ] && [ "$f" != "$demo_mnt/image-$running_sonic_revision" ] && [ "$f" != "$demo_mnt/$image_dir" ]; then + echo "Removing old SONiC installation $f" + rm -rf $f + fi + done +else + demo_mnt="build_raw_image_mnt" + demo_dev=$cur_wd/"%%OUTPUT_RAW_IMAGE%%" + + mkfs.ext4 -L $demo_volume_label $demo_dev -# store installation log in demo file system -rm -f $onie_initrd_tmp/tmp/onie-support.tar.bz2 -${onie_bin} onie-support /tmp -mv $onie_initrd_tmp/tmp/onie-support.tar.bz2 $demo_mnt + echo "Mounting $demo_dev on $demo_mnt..." + mkdir $demo_mnt + mount -t auto -o loop $demo_dev $demo_mnt +fi + +echo "Installing SONiC to $demo_mnt/$image_dir" + +# Create target directory or clean it up if exists +if [ -d $demo_mnt/$image_dir ]; then + echo "Directory $demo_mnt/$image_dir/ already exists. Cleaning up..." + rm -rf $demo_mnt/$image_dir/* +else + mkdir $demo_mnt/$image_dir || { + echo "Error: Unable to create SONiC directory" + exit 1 + } +fi -if [ "$firmware" = "uefi" ] ; then - demo_install_uefi_grub "$demo_mnt" "$blk_dev" +# Decompress the file for the file system directly to the partition +if [ x"$docker_inram" = x"on" ]; then + # when disk is small, keep dockerfs.tar.gz in disk, expand it into ramfs during initrd + unzip -o $ONIE_INSTALLER_PAYLOAD -d $demo_mnt/$image_dir else - demo_install_grub "$demo_mnt" "$blk_dev" + unzip -o $ONIE_INSTALLER_PAYLOAD -x "$FILESYSTEM_DOCKERFS" -d $demo_mnt/$image_dir + + if [ "$install_env" = "onie" ]; then + TAR_EXTRA_OPTION="--numeric-owner" + else + TAR_EXTRA_OPTION="--numeric-owner --warning=no-timestamp" + fi + mkdir -p $demo_mnt/$image_dir/$DOCKERFS_DIR + unzip -op $ONIE_INSTALLER_PAYLOAD "$FILESYSTEM_DOCKERFS" | tar xz $TAR_EXTRA_OPTION -f - -C $demo_mnt/$image_dir/$DOCKERFS_DIR +fi + +if [ "$install_env" = "onie" ]; then + # Store machine description in target file system + if [ -f /etc/machine-build.conf ]; then + # onie_ variable are generate at runtime. + # they are no longer hardcoded in /etc/machine.conf + # also remove single quotes around the value + set | grep ^onie | sed -e "s/='/=/" -e "s/'$//" > $demo_mnt/machine.conf + else + cp /etc/machine.conf $demo_mnt + fi + + # Store installation log in target file system + rm -f $onie_initrd_tmp/tmp/onie-support*.tar.bz2 + ${onie_bin} onie-support /tmp + mv $onie_initrd_tmp/tmp/onie-support*.tar.bz2 $demo_mnt/$image_dir/ + + if [ "$firmware" = "uefi" ] ; then + demo_install_uefi_grub "$demo_mnt" "$blk_dev" + else + demo_install_grub "$demo_mnt" "$blk_dev" + fi fi # Create a minimal grub.cfg that allows for: @@ -408,8 +561,17 @@ trap_push "rm $grub_cfg || true" [ -r ./platform.conf ] && . ./platform.conf -DEFAULT_GRUB_SERIAL_COMMAND="serial --port=%%CONSOLE_PORT%% --speed=%%CONSOLE_SPEED%% --word=8 --parity=no --stop=1" -DEFAULT_GRUB_CMDLINE_LINUX="console=tty0 console=ttyS%%CONSOLE_DEV%%,%%CONSOLE_SPEED%%n8 quiet" +# Check if the CPU vendor is 'Intel' and disable c-states if True +CPUVENDOR=$(cat /proc/cpuinfo | grep -m 1 vendor_id | awk '{print $3}') +echo "Switch CPU vendor is: $CPUVENDOR" +if [[ $(echo $CPUVENDOR | grep -i "Intel") ]] ; then + CSTATES="intel_idle.max_cstate=0" +else + CSTATES="" +fi + +DEFAULT_GRUB_SERIAL_COMMAND="serial --port=${CONSOLE_PORT} --speed=${CONSOLE_SPEED} --word=8 --parity=no --stop=1" +DEFAULT_GRUB_CMDLINE_LINUX="console=tty0 console=ttyS${CONSOLE_DEV},${CONSOLE_SPEED}n8 quiet $CSTATES" GRUB_SERIAL_COMMAND=${GRUB_SERIAL_COMMAND:-"$DEFAULT_GRUB_SERIAL_COMMAND"} GRUB_CMDLINE_LINUX=${GRUB_CMDLINE_LINUX:-"$DEFAULT_GRUB_CMDLINE_LINUX"} export GRUB_SERIAL_COMMAND @@ -418,22 +580,31 @@ export GRUB_CMDLINE_LINUX # Add common configuration, like the timeout and serial console. cat < $grub_cfg $GRUB_SERIAL_COMMAND -terminal_input serial -terminal_output serial +terminal_input console serial +terminal_output console serial set timeout=5 EOF -# Add the logic to support grub-reboot +# 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}" +fi +if [ "\${next_entry}" ]; then + set default="\${next_entry}" + unset next_entry + save_env next_entry fi -if [ "\${next_entry}" ] ; then - set default="\${next_entry}" - set next_entry= - save_env next_entry +if [ "\${onie_entry}" ]; then + set next_entry="\${default}" + set default="\${onie_entry}" + unset onie_entry + save_env onie_entry next_entry fi EOF @@ -447,30 +618,60 @@ 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") + grub_cfg_root=$(echo $old_sonic_menuentry | sed -e "s/.*root\=\(.*\)rw.*/\1/") + onie_menuentry=$(cat /host/grub/grub.cfg | sed "/menuentry ONIE/,/}/!d") +elif [ "$install_env" = "build" ]; then + grub_cfg_root=%%SONIC_ROOT%% +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 menuentry '$demo_grub_entry' { - search --no-floppy --label --set=root $demo_volume_revision_label - echo 'Loading $demo_volume_revision_label $demo_type kernel ...' + search --no-floppy --label --set=root $demo_volume_label + echo 'Loading $demo_volume_label $demo_type kernel ...' insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_msdos insmod ext2 - linux /boot/vmlinuz-3.16.0-4-amd64 root=$demo_dev rw $GRUB_CMDLINE_LINUX \ - loop=$FILESYSTEM_SQUASHFS loopfstype=squashfs \ - apparmor=1 security=apparmor - echo 'Loading $demo_volume_revision_label $demo_type initial ramdisk ...' - initrd /boot/initrd.img-3.16.0-4-amd64 + linux /$image_dir/boot/vmlinuz-4.19.0-12-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.19.0-12-2-amd64 } EOF -# Add menu entries for ONIE -- use the grub fragment provided by the -# ONIE distribution. -$onie_root_dir/grub.d/50_onie_grub >> $grub_cfg +if [ "$install_env" = "onie" ]; then + # Add menu entries for ONIE -- use the grub fragment provided by the + # ONIE distribution. + $onie_root_dir/grub.d/50_onie_grub >> $grub_cfg + mkdir -p $onie_initrd_tmp/$demo_mnt/grub +else +cat <> $grub_cfg +$old_sonic_menuentry +$onie_menuentry +EOF +fi -mkdir -p $onie_initrd_tmp/$demo_mnt/grub -cp $grub_cfg $onie_initrd_tmp/$demo_mnt/grub/grub.cfg +if [ "$install_env" = "build" ]; then + cp $grub_cfg $demo_mnt/grub.cfg + umount $demo_mnt +else + cp $grub_cfg $onie_initrd_tmp/$demo_mnt/grub/grub.cfg +fi cd / + +echo "Installed SONiC base image $demo_volume_label successfully" diff --git a/installer/x86_64/tests/sample_machine.conf b/installer/x86_64/tests/sample_machine.conf new file mode 100644 index 000000000000..a8028cc6d8d2 --- /dev/null +++ b/installer/x86_64/tests/sample_machine.conf @@ -0,0 +1,16 @@ +# sample_machine.conf for onie + # A space in front of comment line +# One blank line below + +onie_machine_rev=0 +onie_arch=x86_64# some comment after declaration +# no value declaration +onie_config_version= +onie_build_date="2021-02-03T01:50+0800" +onie_partition_type=gpt +onie_disco_ntpsrv=192.168.0.1 192.168.0.2 +onie_firmware=auto +# another blank line below + +onie_skip_ethmgmt_macs=no +onie_grub_image_name=grubx64.efi \ No newline at end of file diff --git a/installer/x86_64/tests/test_read_conf.sh b/installer/x86_64/tests/test_read_conf.sh new file mode 100644 index 000000000000..06b7fc145eab --- /dev/null +++ b/installer/x86_64/tests/test_read_conf.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# This is a standalone test file to test read_conf_file function for +# some types of machine.conf file. +# The read_conf_file function is copy from the install.sh + +MACHINE_CONF="sample_machine.conf" + +read_conf_file() { + local conf_file=$1 + while IFS='=' read -r var value || [ -n "$var" ] + do + # remove newline character + var=$(echo $var | tr -d '\r\n') + value=$(echo $value | tr -d '\r\n') + # remove comment string + var=${var%#*} + value=${value%#*} + # skip blank line + [ -z "$var" ] && continue + # remove double quote in the beginning + tmp_val=${value#\"} + # remove double quote in the end + value=${tmp_val%\"} + eval "$var=\"$value\"" + done < "$conf_file" +} + +TEST_CONF() { + input_value=$1 + exp_value=$2 + if [ "$input_value" != "$exp_value" ]; then + echo "[ERR] Expect value($exp_value) is not equal to input value($input_value)" + exit 1 + fi +} + +# define the expected variable value +exp_onie_machine_rev="0" +exp_onie_arch="x86_64" +exp_onie_build_date="2021-02-03T01:50+0800" +exp_onie_partition_type="gpt" +exp_onie_disco_ntpsrv="192.168.0.1 192.168.0.2" +exp_onie_firmware="auto" +exp_onie_skip_ethmgmt_macs="no" +exp_onie_grub_image_name="grubx64.efi" + +# read the sample conf file +read_conf_file $MACHINE_CONF + +# check each variable and its expected value +TEST_CONF "$onie_machine_rev" "$exp_onie_machine_rev" +TEST_CONF "$onie_arch" "$exp_onie_arch" +TEST_CONF "$onie_build_date" "$exp_onie_build_date" +TEST_CONF "$onie_partition_type" "$exp_onie_partition_type" +TEST_CONF "$onie_disco_ntpsrv" "$exp_onie_disco_ntpsrv" +TEST_CONF "$onie_firmware" "$exp_onie_firmware" +TEST_CONF "$onie_skip_ethmgmt_macs" "$exp_onie_skip_ethmgmt_macs" +TEST_CONF "$onie_grub_image_name" "$exp_onie_grub_image_name" + +echo "PASS!!" +exit 0 \ No newline at end of file diff --git a/onie-image-arm64.conf b/onie-image-arm64.conf new file mode 100644 index 000000000000..ff280207e192 --- /dev/null +++ b/onie-image-arm64.conf @@ -0,0 +1,49 @@ +## DESCRIPTION: +## config for ONIE image +## + +## Partition size in MB +## The default size is 32GB +: ${ONIE_IMAGE_PART_SIZE:=32768} + +## Target hardware information +: ${TARGET_PLATFORM:=arm64} +: ${TARGET_MACHINE:=generic} + +ONIEIMAGE_VERSION=r0 + +## Filename for squashfs file system +FILESYSTEM_SQUASHFS=fs.squashfs + +## Filename for onie installer payload, will be the main part of onie installer +ONIE_INSTALLER_PAYLOAD=fs.zip + +## Filename for docker file system +FILESYSTEM_DOCKERFS=dockerfs.tar.gz + +## docker directory on the root filesystem +DOCKERFS_DIR=docker + +## docker ramfs disk space +DOCKER_RAMFS_SIZE=1500M + +## Output file name for onie installer +OUTPUT_ONIE_IMAGE=target/sonic-$TARGET_MACHINE.bin + +## Output file name for raw image +OUTPUT_RAW_IMAGE=target/sonic-$TARGET_MACHINE.raw + +## Raw image size in MB +RAW_IMAGE_DISK_SIZE=3072 + +## Output file name for kvm image +OUTPUT_KVM_IMAGE=target/sonic-$TARGET_MACHINE.img + +## Kvm image size in GB +KVM_IMAGE_DISK_SIZE=16 + +## Output file name for aboot installer +OUTPUT_ABOOT_IMAGE=target/sonic-aboot-$TARGET_MACHINE.swi + +## Aboot boot image name +ABOOT_BOOT_IMAGE=.sonic-boot.swi diff --git a/onie-image-armhf.conf b/onie-image-armhf.conf new file mode 100644 index 000000000000..48fe793c768c --- /dev/null +++ b/onie-image-armhf.conf @@ -0,0 +1,49 @@ +## DESCRIPTION: +## config for ONIE image +## + +## Partition size in MB +## The default size is 32GB +: ${ONIE_IMAGE_PART_SIZE:=32768} + +## Target hardware information +: ${TARGET_PLATFORM:=armhf} +: ${TARGET_MACHINE:=generic} + +ONIEIMAGE_VERSION=r0 + +## Filename for squashfs file system +FILESYSTEM_SQUASHFS=fs.squashfs + +## Filename for onie installer payload, will be the main part of onie installer +ONIE_INSTALLER_PAYLOAD=fs.zip + +## Filename for docker file system +FILESYSTEM_DOCKERFS=dockerfs.tar.gz + +## docker directory on the root filesystem +DOCKERFS_DIR=docker + +## docker ramfs disk space +DOCKER_RAMFS_SIZE=1500M + +## Output file name for onie installer +OUTPUT_ONIE_IMAGE=target/sonic-$TARGET_MACHINE.bin + +## Output file name for raw image +OUTPUT_RAW_IMAGE=target/sonic-$TARGET_MACHINE.raw + +## Raw image size in MB +RAW_IMAGE_DISK_SIZE=3072 + +## Output file name for kvm image +OUTPUT_KVM_IMAGE=target/sonic-$TARGET_MACHINE.img + +## Kvm image size in GB +KVM_IMAGE_DISK_SIZE=16 + +## Output file name for aboot installer +OUTPUT_ABOOT_IMAGE=target/sonic-aboot-$TARGET_MACHINE.swi + +## Aboot boot image name +ABOOT_BOOT_IMAGE=.sonic-boot.swi diff --git a/onie-image.conf b/onie-image.conf index 25c631563cd9..419095b24470 100644 --- a/onie-image.conf +++ b/onie-image.conf @@ -1,5 +1,5 @@ ## DESCRIPTION: -## partition related config +## config for ONIE image ## ## Partition size in MB @@ -18,5 +18,32 @@ FILESYSTEM_SQUASHFS=fs.squashfs ## Filename for onie installer payload, will be the main part of onie installer ONIE_INSTALLER_PAYLOAD=fs.zip +## Filename for docker file system +FILESYSTEM_DOCKERFS=dockerfs.tar.gz + +## docker directory on the root filesystem +DOCKERFS_DIR=docker + +## docker ramfs disk space +DOCKER_RAMFS_SIZE=1500M + ## Output file name for onie installer -OUTPUT_ONIE_IMAGE=acs-$TARGET_MACHINE.bin +OUTPUT_ONIE_IMAGE=target/sonic-$TARGET_MACHINE.bin + +## Output file name for raw image +OUTPUT_RAW_IMAGE=target/sonic-$TARGET_MACHINE.raw + +## Raw image size in MB +RAW_IMAGE_DISK_SIZE=3072 + +## Output file name for kvm image +OUTPUT_KVM_IMAGE=target/sonic-$TARGET_MACHINE.img + +## Kvm image size in GB +KVM_IMAGE_DISK_SIZE=16 + +## Output file name for aboot installer +OUTPUT_ABOOT_IMAGE=target/sonic-aboot-$TARGET_MACHINE.swi + +## Aboot boot image name +ABOOT_BOOT_IMAGE=.sonic-boot.swi diff --git a/onie-mk-demo.sh b/onie-mk-demo.sh index 3dd81b876fd6..845348d860f1 100755 --- a/onie-mk-demo.sh +++ b/onie-mk-demo.sh @@ -12,7 +12,7 @@ installer_dir=$4 platform_conf=$5 output_file=$6 demo_type=$7 -git_revision=$8 +image_version=$8 onie_image_part_size=$9 shift 9 @@ -29,7 +29,7 @@ if [ ! -d $installer_dir/$arch ] || \ exit 1 fi -[ -n "$git_revision" ] || { +[ -n "$image_version" ] || { echo "Error: Invalid git revisions" exit 1 } @@ -39,11 +39,6 @@ fi exit 1 } -[ -n "$CONSOLE_SPEED" ] || { - echo "Error: Invalid CONSOLE_SPEED" - exit 1 -} - [ -r "$platform_conf" ] || { echo "Error: Unable to read installer platform configuration file: $platform_conf" exit 1 @@ -81,22 +76,24 @@ tmp_dir=$(mktemp --directory) tmp_installdir="$tmp_dir/installer" mkdir $tmp_installdir || clean_up 1 -cp $installer_dir/$arch/install.sh $tmp_installdir || clean_up 1 +cp -r $installer_dir/$arch/* $tmp_installdir || clean_up 1 cp onie-image.conf $tmp_installdir +cp onie-image-*.conf $tmp_installdir # Escape special chars in the user provide kernel cmdline string for use in # sed. Special chars are: \ / & EXTRA_CMDLINE_LINUX=`echo $EXTRA_CMDLINE_LINUX | sed -e 's/[\/&]/\\\&/g'` +output_raw_image=$(cat onie-image.conf | grep OUTPUT_RAW_IMAGE | cut -f2 -d"=") +[ -z "$TARGET_MACHINE" ] && output_raw_image=$(echo $output_raw_image | sed -e 's/$TARGET_MACHINE/$machine/g') +output_raw_image=$(eval echo $output_raw_image) + # Tailor the demo installer for OS mode or DIAG mode sed -i -e "s/%%DEMO_TYPE%%/$demo_type/g" \ - -e "s/%%GIT_REVISION%%/$git_revision/g" \ + -e "s/%%IMAGE_VERSION%%/$image_version/g" \ -e "s/%%ONIE_IMAGE_PART_SIZE%%/$onie_image_part_size/" \ - -e "s/%%CONSOLE_SPEED%%/$CONSOLE_SPEED/g" \ - -e "s/%%CONSOLE_DEV%%/$CONSOLE_DEV/g" \ - -e "s/%%CONSOLE_FLAG%%/$CONSOLE_FLAG/g" \ - -e "s/%%CONSOLE_PORT%%/$CONSOLE_PORT/g" \ -e "s/%%EXTRA_CMDLINE_LINUX%%/$EXTRA_CMDLINE_LINUX/" \ + -e "s@%%OUTPUT_RAW_IMAGE%%@$output_raw_image@" \ $tmp_installdir/install.sh || clean_up 1 echo -n "." cp -r $* $tmp_installdir || clean_up 1 diff --git a/platform/barefoot/bfn-modules.mk b/platform/barefoot/bfn-modules.mk new file mode 100644 index 000000000000..46d504f56812 --- /dev/null +++ b/platform/barefoot/bfn-modules.mk @@ -0,0 +1,8 @@ +# BFN Platform modules + +VERSION = 1.0 + +BFN_MODULE = bfn-modules_$(VERSION)_amd64.deb +$(BFN_MODULE)_SRC_PATH = $(PLATFORM_PATH)/bfn-modules +$(BFN_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_DPKG_DEBS += $(BFN_MODULE) diff --git a/platform/barefoot/bfn-modules/LICENSE b/platform/barefoot/bfn-modules/LICENSE new file mode 100644 index 000000000000..e9d73a1c63cc --- /dev/null +++ b/platform/barefoot/bfn-modules/LICENSE @@ -0,0 +1,37 @@ +BAREFOOT NETWORKS CONFIDENTIAL & PROPRIETARY + + Copyright (c) 2015-2016 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. + + +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... + + diff --git a/platform/barefoot/bfn-modules/MAINTAINERS b/platform/barefoot/bfn-modules/MAINTAINERS new file mode 100644 index 000000000000..b9c62ce01546 --- /dev/null +++ b/platform/barefoot/bfn-modules/MAINTAINERS @@ -0,0 +1,4 @@ +# This file describes the maintainers for sonic-platform-modules-bfn +# See the SONiC project governance document for more information + +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/barefoot/bfn-modules/README.md b/platform/barefoot/bfn-modules/README.md new file mode 100644 index 000000000000..6c47cbed2a5d --- /dev/null +++ b/platform/barefoot/bfn-modules/README.md @@ -0,0 +1,2 @@ +# bfn-modules +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/bfn-modules/debian/changelog b/platform/barefoot/bfn-modules/debian/changelog new file mode 100644 index 000000000000..85ab933da304 --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/changelog @@ -0,0 +1,5 @@ +bfn-modules (1.0) unstable; urgency=low + + * Initial release + + -- Support Mon, 22 Oct 2018 11:11:11 -0800 diff --git a/platform/barefoot/bfn-modules/debian/compat b/platform/barefoot/bfn-modules/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/barefoot/bfn-modules/debian/control b/platform/barefoot/bfn-modules/debian/control new file mode 100644 index 000000000000..be1f6cc0443a --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/control @@ -0,0 +1,12 @@ +Source: bfn-modules +Section: main +Priority: extra +Maintainer: support +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: bfn-modules +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for bfn asic for mmap + diff --git a/platform/barefoot/bfn-modules/debian/copyright b/platform/barefoot/bfn-modules/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/bfn-modules/debian/files b/platform/barefoot/bfn-modules/debian/files new file mode 100644 index 000000000000..cffeb8a7d9c9 --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/files @@ -0,0 +1 @@ +bfn-modules_1.0_amd64.deb main extra diff --git a/platform/barefoot/bfn-modules/debian/rules b/platform/barefoot/bfn-modules/debian/rules new file mode 100755 index 000000000000..c588b075e5e7 --- /dev/null +++ b/platform/barefoot/bfn-modules/debian/rules @@ -0,0 +1,30 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_NAME := bfn-modules +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MODULE_SRC := $(shell pwd)/modules + +%: + dh $@ + +override_dh_auto_build: + make -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR) + cp $(MODULE_SRC)/*.ko debian/$(PACKAGE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + rm -f $(MODULE_SRC)/*.o $(MODULE_SRC)/*.ko $(MODULE_SRC)/*.mod.c $(MODULE_SRC)/.*.cmd + rm -f $(MODULE_SRC)/Module.markers $(MODULE_SRC)/Module.symvers $(MODULE_SRC)/modules.order + rm -rf $(MODULE_SRC)/.tmp_versions + diff --git a/platform/barefoot/bfn-modules/modules/Makefile b/platform/barefoot/bfn-modules/modules/Makefile new file mode 100644 index 000000000000..d180b29f6ae2 --- /dev/null +++ b/platform/barefoot/bfn-modules/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := bf_kdrv.o +obj-m += bf_tun.o diff --git a/platform/barefoot/bfn-modules/modules/bf_ioctl.h b/platform/barefoot/bfn-modules/modules/bf_ioctl.h new file mode 100644 index 000000000000..0644feb7c8c1 --- /dev/null +++ b/platform/barefoot/bfn-modules/modules/bf_ioctl.h @@ -0,0 +1,72 @@ +/******************************************************************************* + 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_ + +#ifdef __KERNEL__ +#include +#else +#include + +#ifndef phys_addr_t +typedef uint64_t phys_addr_t; +#endif + +#endif /* __KERNEL__ */ + +#define BF_IOC_MAGIC 'b' +#define BF_TBUS_MSIX_INDICES_MAX 3 + +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, 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 new file mode 100644 index 000000000000..d4c786c56b75 --- /dev/null +++ b/platform/barefoot/bfn-modules/modules/bf_kdrv.c @@ -0,0 +1,1478 @@ +/******************************************************************************* + 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 + +*******************************************************************************/ +/* bf_drv kernel module + * + * This is kernel mode driver for Tofino chip. + * Provides user space mmap service and user space "wait for interrupt" + * and "enable interrupt" services. + */ + +#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 +#endif +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) +//#error unsupported linux kernel version +#endif + +#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 + +/* 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 cdev *bf_cdev; + struct fasync_struct *async_queue; +}; + +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 **cur_listener = &bfdev->listener_head; + + if (!listener) { + return; + } + spin_lock(&bf_nonisr_lock); + + while (*cur_listener) { + cur_listener = &((*cur_listener)->next); + } + *cur_listener = listener; + listener->next = NULL; + + spin_unlock(&bf_nonisr_lock); +} + +static void bf_remove_listener(struct bf_pci_dev *bfdev, + 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() + */ + if (!bfdev || !listener) { + return; + } + spin_lock(&bf_nonisr_lock); + + if (*cur_listener == listener) { + *cur_listener = listener->next; + } else { + while (*cur_listener) { + if ((*cur_listener)->next == listener) { + (*cur_listener)->next = listener->next; + break; + } + cur_listener = &((*cur_listener)->next); + } + listener->next = NULL; + } + + spin_unlock(&bf_nonisr_lock); +} + +/* a pool of minor numbers is maintained */ +/* return the first available minor number */ +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++) { + if (bf_minor[i] == 0) { + *minor = i; + bf_minor[i] = 1; /* mark it as taken */ + spin_unlock(&bf_nonisr_lock); + return 0; + } + } + *minor = -1; + spin_unlock(&bf_nonisr_lock); + return -1; +} + +/* return a minor number back to the pool for recycling */ +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 */ + } else { + bf_minor[minor] = 0; /* mark it as available */ + err = 0; + } + spin_unlock(&bf_nonisr_lock); + 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); +} + +/* + * 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; + } +} + +/** + * irqcontrol can be used to disable/enable interrupt from user space processes. + * + * @param bf_dev + * pointer to bf_pci_dev + * @param irq_state + * state value. 1 to enable interrupt, 0 to disable interrupt. + * + * @return + * - 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); +#else + for_each_pci_msi_entry(desc, pdev) bf_msix_mask_irq(desc, irq_state); +#endif + } + pci_cfg_access_unlock(pdev); + + 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. + */ +#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; +} + +/* Unmap previously ioremap'd resources */ +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); + } + } +} + +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) { + 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) { + atomic_inc(&(bfdev->info.event[vect_off])); + } + return ret; +} + +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) { + 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])) { + return POLLIN | POLLRDNORM; + } + } + return 0; +} + +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) { + 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, +#endif +}; + +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) { + return -EINVAL; + } + + mem = bfdev->info.mem + bar; + + if (mem->addr & ~PAGE_MASK) { + return -ENODEV; + } + 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); + + /* + * We cannot use the vm_iomap_memory() helper here, + * because vma->vm_pgoff is the map index we looked + * up above in bf_find_mem_index(), rather than an + * actual page offset into the mmap. + * + * 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); +} + +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) { + return -EINVAL; + } + + vma->vm_private_data = bfdev; + + bar = bf_find_mem_index(vma); + 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) { + return -EINVAL; + } + + return bf_mmap_physical(vma); +} + +static int bf_fasync(int fd, struct file *filep, int mode) { + int minor; + + if (!filep->private_data) { + return (-EINVAL); + } + minor = ((struct bf_listener *)filep->private_data)->minor; + if (minor >= BF_MAX_DEVICE_CNT) { + return (-EINVAL); + } + if (mode == 0 && &bf_global[minor].async_queue == NULL) { + return 0; /* nothing to do */ + } + return (fasync_helper(fd, filep, mode, &bf_global[minor].async_queue)); +} + +static int bf_open(struct inode *inode, struct file *filep) { + struct bf_pci_dev *bfdev; + struct bf_listener *listener; + int i; + + bfdev = bf_global[iminor(inode)].bfdev; + listener = kmalloc(sizeof(*listener), GFP_KERNEL); + if (listener) { + listener->bfdev = bfdev; + listener->minor = bfdev->info.minor; + listener->next = NULL; + bf_add_listener(bfdev, listener); + 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); + } +} + +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 */ + if (listener->bfdev) { + bf_remove_listener(listener->bfdev, listener); + } + kfree(listener); + return 0; +} + +/* 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) { + 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 */ + 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) { + 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) { + return -EINVAL; + } + count = sizeof(s32) * BF_MSIX_ENTRY_CNT; + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + if (count < sizeof(s32) * BF_MSI_ENTRY_CNT) { + return -EINVAL; + } + count = sizeof(s32) * BF_MSI_ENTRY_CNT; + } else { + if (count < sizeof(s32)) { + return -EINVAL; + } + count = sizeof(s32); + } + + do { + set_current_state(TASK_INTERRUPTIBLE); + + 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; + cnt_match[i] = 1; + } else { + event_count[i] = 0; + cnt_match[i] = 0; + } + } + if (mismatch_found) { + __set_current_state(TASK_RUNNING); + if (copy_to_user(buf, &event_count, count)) { + retval = -EFAULT; + } 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]; + } + } + retval = count; + } + break; + } + + if (filep->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + break; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } while (1); + + __set_current_state(TASK_RUNNING); + + return retval; +} + +/* 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) { + 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) { + return -EIO; + } + + if (count != sizeof(s32)) { + return -EINVAL; + } + + if (copy_from_user(&int_en, buf, count)) { + return -EFAULT; + } + + /* clear pci_error_state */ + bfdev->info.pci_error_state = 0; + + ret = bf_pci_irqcontrol(bfdev, int_en); + + return ret ? ret : sizeof(s32); +} + +static long bf_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + bf_dma_bus_map_t dma_map; + void *addr = (void __user *)arg; + dma_addr_t dma_hndl; + + if (!bfdev || !addr) { + return EFAULT; + } + 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; + } + if (!dma_map.phy_addr || !dma_map.size) { + return EFAULT; + } + dma_hndl = dma_map_single(&bfdev->pdev->dev, phys_to_virt(dma_map.phy_addr), dma_map.size, DMA_BIDIRECTIONAL); + if (dma_mapping_error(&bfdev->pdev->dev, dma_hndl)) { + return EFAULT; + } + dma_map.dma_addr = (void *)(uintptr_t)dma_hndl; + if (copy_to_user(addr, &dma_map, sizeof(bf_dma_bus_map_t))) { + return EFAULT; + } + } else { + return EFAULT; + } + 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)(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; + } + return 0; +} + +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, +}; + +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) { + return result; + } + + result = -ENOMEM; + cdev = cdev_alloc(); + if (!cdev) { + goto fail_dev_add; + } + cdev->ops = &bf_fops; + cdev->owner = THIS_MODULE; + kobject_set_name(&cdev->kobj, "%s", name); + result = cdev_add(cdev, bf_dev, BF_MAX_DEVICE_CNT); + + if (result) { + goto fail_dev_add; + } + + bf_major = MAJOR(bf_dev); + bf_global[minor].bf_cdev = cdev; + return 0; + +fail_dev_add: + unregister_chrdev_region(bf_dev, BF_MAX_DEVICE_CNT); + return result; +} + +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) { + int ret; + ret = bf_major_init(bfdev, minor); + 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"); + ret = -ENODEV; + goto err_class_register; + } + return 0; + +err_class_register: + bf_major_cleanup(bfdev, minor); + return ret; +} + +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 + * + * returns zero on success or a negative error code. + */ +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) { + return -EINVAL; + } + + init_waitqueue_head(&info->wait); + + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + atomic_set(&info->event[i], 0); + } + + if (bf_get_next_minor_no(&minor)) { + return -EINVAL; + } + + ret = bf_init_cdev(bfdev, minor); + if (ret) { + printk(KERN_ERR "BF: device cdev creation failed\n"); + return ret; + } + + 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; + } + + info->minor = minor; + + /* bind ISRs and request interrupts */ + if (info->irq && (bfdev->mode != BF_INTR_MODE_NONE)) { + /* + * Note that we deliberately don't use devm_request_irq + * here. The parent module can unregister the UIO device + * and call pci_disable_msi, which requires that this + * irq has been freed. However, the device may have open + * FDs at the time of unregister and therefore may not be + * freed until they are released. + */ + if (bfdev->mode == BF_INTR_MODE_LEGACY) { + 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); + 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, + (void *)&(bfdev->bf_int_vec[i])); + if (ret) { + /* undo all other previous bindings */ + printk(KERN_ERR "bf failed to request MSIX ret %d itr %d\n", ret, i); + for (j = i - 1; j >= 0; j--) { + free_irq(info->msix_entries[j].vector, + (void *)&(bfdev->bf_int_vec[j])); + } + return ret; + } + } + printk(KERN_NOTICE "BF allocating %d MSIx vectors from %ld\n", + 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, + (void *)&(bfdev->bf_int_vec[i])); + if (ret) { + /* undo all other previous bindings */ + printk(KERN_ERR "bf failed to request MSI ret %d itr %d\n", ret, i); + for (j = i - 1; j >= 0; j--) { + 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); + } + } + return 0; +} + +/** + * bf_unregister_device - register a new userspace mem device + * @bfdev: bf pci device + * + * returns none + */ +void bf_unregister_device(struct bf_pci_dev *bfdev) { + struct bf_dev_info *info = &bfdev->info; + int i; + + if (info->irq) { + if (bfdev->mode == BF_INTR_MODE_LEGACY) { + free_irq(info->irq, (void *)&(bfdev->bf_int_vec[0])); + } else if (bfdev->mode == BF_INTR_MODE_MSIX) { + for (i = 0; i < info->num_irq; i++) { + free_irq(info->msix_entries[i].vector, (void *)&(bfdev->bf_int_vec[i])); + } + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + for (i = 0; i < info->num_irq; i++) { + free_irq(info->irq + i, (void *)&(bfdev->bf_int_vec[i])); + } + } + } + device_destroy(bf_class, MKDEV(bf_major, info->minor)); + bf_remove_cdev(bfdev); + bf_return_minor_no(info->minor); + return; +} + +static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) { + return &pdev->dev; +} + +static void bf_disable_int_dma(struct bf_pci_dev *bfdev) { + u8 *bf_base_addr, i; + u32 *bf_addr; + volatile u32 val; + + /* maskinterrupts and DMA */ + bf_base_addr = (bfdev->info.mem[0].internal_addr); + /* return if called before mmap */ + if (!bf_base_addr) { + return; + } + /* mask interrupt at shadow level */ + bf_addr = (u32 *)((u8 *)bf_base_addr + 0xc0); + for (i = 0; i < 16; i++) { + *bf_addr = 0xffffffffUL; + bf_addr++; + } + /* mask DMA */ + bf_addr = (u32 *)((u8 *)bf_base_addr + 0x14); + val = *bf_addr; + val &= 0xfffffffeUL; + *bf_addr = val; +} + +static int bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { + struct bf_pci_dev *bfdev; + 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) { + return -ENOMEM; + } + + /* init the cookies to be passed to ISRs */ + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + bfdev->bf_int_vec[i].int_vec_offset = i; + bfdev->bf_int_vec[i].bf_dev = bfdev; + } + + /* initialize intr_mode to none */ + bfdev->mode = BF_INTR_MODE_NONE; + + /* 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) { + printk(KERN_ERR "bf cannot enable PCI device\n"); + goto fail_free; + } + + /* + * reserve device's PCI memory regions for use by this + * module + */ + err = pci_request_regions(pdev, "bf_umem"); + if (err != 0) { + 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) { + 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)); + if (err) { + printk(KERN_ERR "bf no usable DMA configuration, aborting\n"); + goto fail_release_iomem; + } + } + pci_use_highmem = 0; + } + + /* enable pci error reporting */ + /* for the current kernel version, kernel config must have set the followings: + * CONFIG_PCIEPORTBUS=y and CONFIG_PCIEAER = y + * we have pci_error_handlers defined that gets invoked by kernel AER module + * upon detecting the pcie error on this device's addresses. + * However, there seems no way that AER would pass the offending addresses + * to the callback functions. AER logs the error messages on the console. + * This driver's calback function send the SIGIO signal to the user space + * to indicate the error condition. + */ + pci_enable_pcie_error_reporting(pdev); + + bf_disable_int_dma(bfdev); + + /* enable bus mastering on the device */ + pci_set_master(pdev); + + /* fill in bfdev info */ + bfdev->info.version = "0.2"; + bfdev->info.owner = THIS_MODULE; + bfdev->pdev = pdev; + + 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; + } +#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) { + 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) { + 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: +#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) { + 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; + } +#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) { + 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) { + 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; + } +#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)) { + 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; + + 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) { + 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); + 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: + pci_set_drvdata(pdev, NULL); + if (bfdev->mode == BF_INTR_MODE_MSIX) { + pci_disable_msix(bfdev->pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + pci_disable_msi(bfdev->pdev); + } +fail_clear_pci_master: + pci_clear_master(pdev); +fail_release_iomem: + bf_pci_release_iomem(&bfdev->info); + pci_release_regions(pdev); +fail_pci_disable: + pci_disable_device(pdev); +fail_free: + kfree(bfdev); + + printk(KERN_ERR "bf probe not ok\n"); + return err; +} + +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) { + pci_disable_msi(pdev); + } + pci_clear_master(pdev); + bf_pci_release_iomem(&bfdev->info); + pci_release_regions(pdev); + pci_disable_pcie_error_reporting(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + bf_global[bfdev->info.minor].bfdev = NULL; + /* existing filep structures in open file(s) must be informed that + * bf_pci_dev is no longer valid */ + spin_lock(&bf_nonisr_lock); + cur_listener = bfdev->listener_head; + while (cur_listener) { + cur_listener->bfdev = NULL; + cur_listener = cur_listener->next; + } + spin_unlock(&bf_nonisr_lock); + 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 + * @state: The current pci connection state + * + * 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) { + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + + if (!bfdev) { + return PCI_ERS_RESULT_NONE; + } + 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 */ + 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_RECOVERED; +} + +/** + * bf_pci_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. + */ +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. Not expected to be invoked. + * TBD: fill in this function if tofino can recover after an error + */ + printk(KERN_ERR "BF pci_slot_reset invoked after pci error\n"); + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * bf_pci_resume - called when kernel thinks the device is up on PCIe. + * @pdev: Pointer to PCI device + * + * 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) { + printk(KERN_ERR "BF io_resume invoked after pci error\n"); +} + +static int bf_config_intr_mode(char *intr_str) { + if (!intr_str) { + pr_info("Use MSI interrupt by default\n"); + return 0; + } + + if (!strcmp(intr_str, BF_INTR_MODE_MSIX_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_MSIX; + pr_info("Use MSIX interrupt\n"); + } else if (!strcmp(intr_str, BF_INTR_MODE_MSI_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_MSI; + pr_info("Use MSI interrupt\n"); + } 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 if (!strcmp(intr_str, BF_INTR_MODE_NONE_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_NONE; + 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}, + {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, + .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 int __init bfdrv_init(void) { + int ret; + + ret = bf_config_intr_mode(intr_mode); + /* 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) { + 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" + " " BF_INTR_MODE_NONE_NAME + " Use no interrupt\n" + "\n"); + +MODULE_DEVICE_TABLE(pci, bf_pci_tbl); +MODULE_DESCRIPTION("Barefoot Tofino PCI device"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Barefoot Networks"); 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-modules/modules/bf_tun.c b/platform/barefoot/bfn-modules/modules/bf_tun.c new file mode 100644 index 000000000000..a20f5e4db585 --- /dev/null +++ b/platform/barefoot/bfn-modules/modules/bf_tun.c @@ -0,0 +1,3569 @@ +/* + * TUN - Universal TUN/TAP device driver. + * Copyright (C) 1999-2002 Maxim Krasnyansky + * + * 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. + * + * $Id: tun.c,v 1.15 2002/03/01 02:44:24 maxk Exp $ + */ + +/* + * Changes: + * + * Mike Kershaw 2005/08/14 + * Add TUNSETLINK ioctl to set the link encapsulation + * + * Mark Smith + * Use eth_random_addr() for tap MAC address. + * + * Harald Roelle 2004/04/20 + * Fixes in packet dropping, queue length setting and queue wakeup. + * Increased default tx queue length. + * Added ethtool API. + * Minor cleanups + * + * Daniel Podlejski + * Modifications for 2.3.99-pre5 kernel. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#define DRV_NAME "bf_tun" +#define DRV_VERSION "1.6" +#define DRV_DESCRIPTION "Universal TUN/TAP device driver" +#define DRV_COPYRIGHT "(C) 1999-2004 Max Krasnyansky " + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define BF_TUN_MINOR 201 + +static void tun_default_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd); + +/* Uncomment to enable debugging */ +/* #define TUN_DEBUG 1 */ + +#ifdef TUN_DEBUG +static int debug; + +#define tun_debug(level, tun, fmt, args...) \ +do { \ + if (tun->debug) \ + netdev_printk(level, tun->dev, fmt, ##args); \ +} while (0) +#define DBG1(level, fmt, args...) \ +do { \ + if (debug == 2) \ + printk(level fmt, ##args); \ +} while (0) +#else +#define tun_debug(level, tun, fmt, args...) \ +do { \ + if (0) \ + netdev_printk(level, tun->dev, fmt, ##args); \ +} while (0) +#define DBG1(level, fmt, args...) \ +do { \ + if (0) \ + printk(level fmt, ##args); \ +} while (0) +#endif + +#define TUN_HEADROOM 256 +#define TUN_RX_PAD (NET_IP_ALIGN + NET_SKB_PAD) + +/* TUN device flags */ + +/* IFF_ATTACH_QUEUE is never stored in device flags, + * overload it to mean fasync when stored there. + */ +#define TUN_FASYNC IFF_ATTACH_QUEUE +/* High bits in flags field are unused. */ +#define TUN_VNET_LE 0x80000000 +#define TUN_VNET_BE 0x40000000 + +#define TUN_FEATURES (IFF_NO_PI | IFF_ONE_QUEUE | IFF_VNET_HDR | \ + IFF_MULTI_QUEUE | IFF_NAPI | IFF_NAPI_FRAGS) + +#define GOODCOPY_LEN 128 + +#define FLT_EXACT_COUNT 8 +struct tap_filter { + unsigned int count; /* Number of addrs. Zero means disabled */ + u32 mask[2]; /* Mask of the hashed addrs */ + unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; +}; + +/* MAX_TAP_QUEUES 256 is chosen to allow rx/tx queues to be equal + * to max number of VCPUs in guest. */ +#define MAX_TAP_QUEUES 256 +#define MAX_TAP_FLOWS 4096 + +#define TUN_FLOW_EXPIRE (3 * HZ) + +struct tun_pcpu_stats { + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; + struct u64_stats_sync syncp; + u32 rx_dropped; + u32 tx_dropped; + u32 rx_frame_errors; +}; + +/* A tun_file connects an open character device to a tuntap netdevice. It + * also contains all socket related structures (except sock_fprog and tap_filter) + * to serve as one transmit queue for tuntap device. The sock_fprog and + * tap_filter were kept in tun_struct since they were used for filtering for the + * netdevice not for a specific queue (at least I didn't see the requirement for + * this). + * + * RCU usage: + * The tun_file and tun_struct are loosely coupled, the pointer from one to the + * other can only be read while rcu_read_lock or rtnl_lock is held. + */ +struct tun_file { + struct sock sk; + struct socket socket; + struct socket_wq wq; + struct tun_struct __rcu *tun; + struct fasync_struct *fasync; + /* only used for fasnyc */ + unsigned int flags; + union { + u16 queue_index; + unsigned int ifindex; + }; + struct napi_struct napi; + bool napi_enabled; + bool napi_frags_enabled; + struct mutex napi_mutex; /* Protects access to the above napi */ + struct list_head next; + struct tun_struct *detached; + struct ptr_ring tx_ring; + struct xdp_rxq_info xdp_rxq; +}; + +struct tun_flow_entry { + struct hlist_node hash_link; + struct rcu_head rcu; + struct tun_struct *tun; + + u32 rxhash; + u32 rps_rxhash; + int queue_index; + unsigned long updated; +}; + +#define TUN_NUM_FLOW_ENTRIES 1024 +#define TUN_MASK_FLOW_ENTRIES (TUN_NUM_FLOW_ENTRIES - 1) + +struct tun_prog { + struct rcu_head rcu; + struct bpf_prog *prog; +}; + +/* Since the socket were moved to tun_file, to preserve the behavior of persist + * device, socket filter, sndbuf and vnet header size were restore when the + * file were attached to a persist device. + */ +struct tun_struct { + struct tun_file __rcu *tfiles[MAX_TAP_QUEUES]; + unsigned int numqueues; + unsigned int flags; + kuid_t owner; + kgid_t group; + + struct net_device *dev; + netdev_features_t set_features; +#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ + NETIF_F_TSO6) + + int align; + int vnet_hdr_sz; + int sndbuf; + struct tap_filter txflt; + struct sock_fprog fprog; + /* protected by rtnl lock */ + bool filter_attached; +#ifdef TUN_DEBUG + int debug; +#endif + spinlock_t lock; + struct hlist_head flows[TUN_NUM_FLOW_ENTRIES]; + struct timer_list flow_gc_timer; + unsigned long ageing_time; + unsigned int numdisabled; + struct list_head disabled; + void *security; + u32 flow_count; + u32 rx_batched; + struct tun_pcpu_stats __percpu *pcpu_stats; + struct bpf_prog __rcu *xdp_prog; + struct tun_prog __rcu *steering_prog; + struct tun_prog __rcu *filter_prog; + struct ethtool_link_ksettings link_ksettings; +}; + +struct veth { + __be16 h_vlan_proto; + __be16 h_vlan_TCI; +}; + +bool tun_is_xdp_frame(void *ptr) +{ + return (unsigned long)ptr & TUN_XDP_FLAG; +} +EXPORT_SYMBOL(tun_is_xdp_frame); + +void *tun_xdp_to_ptr(void *ptr) +{ + return (void *)((unsigned long)ptr | TUN_XDP_FLAG); +} +EXPORT_SYMBOL(tun_xdp_to_ptr); + +void *tun_ptr_to_xdp(void *ptr) +{ + return (void *)((unsigned long)ptr & ~TUN_XDP_FLAG); +} +EXPORT_SYMBOL(tun_ptr_to_xdp); + +static int tun_napi_receive(struct napi_struct *napi, int budget) +{ + struct tun_file *tfile = container_of(napi, struct tun_file, napi); + struct sk_buff_head *queue = &tfile->sk.sk_write_queue; + struct sk_buff_head process_queue; + struct sk_buff *skb; + int received = 0; + + __skb_queue_head_init(&process_queue); + + spin_lock(&queue->lock); + skb_queue_splice_tail_init(queue, &process_queue); + spin_unlock(&queue->lock); + + while (received < budget && (skb = __skb_dequeue(&process_queue))) { + napi_gro_receive(napi, skb); + ++received; + } + + if (!skb_queue_empty(&process_queue)) { + spin_lock(&queue->lock); + skb_queue_splice(&process_queue, queue); + spin_unlock(&queue->lock); + } + + return received; +} + +static int tun_napi_poll(struct napi_struct *napi, int budget) +{ + unsigned int received; + + received = tun_napi_receive(napi, budget); + + if (received < budget) + napi_complete_done(napi, received); + + return received; +} + +static void tun_napi_init(struct tun_struct *tun, struct tun_file *tfile, + bool napi_en, bool napi_frags) +{ + tfile->napi_enabled = napi_en; + tfile->napi_frags_enabled = napi_en && napi_frags; + if (napi_en) { + netif_napi_add(tun->dev, &tfile->napi, tun_napi_poll, + NAPI_POLL_WEIGHT); + napi_enable(&tfile->napi); + } +} + +static void tun_napi_disable(struct tun_file *tfile) +{ + if (tfile->napi_enabled) + napi_disable(&tfile->napi); +} + +static void tun_napi_del(struct tun_file *tfile) +{ + if (tfile->napi_enabled) + netif_napi_del(&tfile->napi); +} + +static bool tun_napi_frags_enabled(const struct tun_file *tfile) +{ + return tfile->napi_frags_enabled; +} + +#ifdef CONFIG_TUN_VNET_CROSS_LE +static inline bool tun_legacy_is_little_endian(struct tun_struct *tun) +{ + return tun->flags & TUN_VNET_BE ? false : + virtio_legacy_is_little_endian(); +} + +static long tun_get_vnet_be(struct tun_struct *tun, int __user *argp) +{ + int be = !!(tun->flags & TUN_VNET_BE); + + if (put_user(be, argp)) + return -EFAULT; + + return 0; +} + +static long tun_set_vnet_be(struct tun_struct *tun, int __user *argp) +{ + int be; + + if (get_user(be, argp)) + return -EFAULT; + + if (be) + tun->flags |= TUN_VNET_BE; + else + tun->flags &= ~TUN_VNET_BE; + + return 0; +} +#else +static inline bool tun_legacy_is_little_endian(struct tun_struct *tun) +{ + return virtio_legacy_is_little_endian(); +} + +static long tun_get_vnet_be(struct tun_struct *tun, int __user *argp) +{ + return -EINVAL; +} + +static long tun_set_vnet_be(struct tun_struct *tun, int __user *argp) +{ + return -EINVAL; +} +#endif /* CONFIG_TUN_VNET_CROSS_LE */ + +static inline bool tun_is_little_endian(struct tun_struct *tun) +{ + return tun->flags & TUN_VNET_LE || + tun_legacy_is_little_endian(tun); +} + +static inline u16 tun16_to_cpu(struct tun_struct *tun, __virtio16 val) +{ + return __virtio16_to_cpu(tun_is_little_endian(tun), val); +} + +static inline __virtio16 cpu_to_tun16(struct tun_struct *tun, u16 val) +{ + return __cpu_to_virtio16(tun_is_little_endian(tun), val); +} + +static inline u32 tun_hashfn(u32 rxhash) +{ + return rxhash & TUN_MASK_FLOW_ENTRIES; +} + +static struct tun_flow_entry *tun_flow_find(struct hlist_head *head, u32 rxhash) +{ + struct tun_flow_entry *e; + + hlist_for_each_entry_rcu(e, head, hash_link) { + if (e->rxhash == rxhash) + return e; + } + return NULL; +} + +static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun, + struct hlist_head *head, + u32 rxhash, u16 queue_index) +{ + struct tun_flow_entry *e = kmalloc(sizeof(*e), GFP_ATOMIC); + + if (e) { + tun_debug(KERN_INFO, tun, "create flow: hash %u index %u\n", + rxhash, queue_index); + e->updated = jiffies; + e->rxhash = rxhash; + e->rps_rxhash = 0; + e->queue_index = queue_index; + e->tun = tun; + hlist_add_head_rcu(&e->hash_link, head); + ++tun->flow_count; + } + return e; +} + +static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e) +{ + tun_debug(KERN_INFO, tun, "delete flow: hash %u index %u\n", + e->rxhash, e->queue_index); + hlist_del_rcu(&e->hash_link); + kfree_rcu(e, rcu); + --tun->flow_count; +} + +static void tun_flow_flush(struct tun_struct *tun) +{ + int i; + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) + tun_flow_delete(tun, e); + } + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_delete_by_queue(struct tun_struct *tun, u16 queue_index) +{ + int i; + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) { + if (e->queue_index == queue_index) + tun_flow_delete(tun, e); + } + } + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_cleanup(struct timer_list *t) +{ + struct tun_struct *tun = from_timer(tun, t, flow_gc_timer); + unsigned long delay = tun->ageing_time; + unsigned long next_timer = jiffies + delay; + unsigned long count = 0; + int i; + + tun_debug(KERN_INFO, tun, "tun_flow_cleanup\n"); + + spin_lock(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) { + unsigned long this_timer; + + this_timer = e->updated + delay; + if (time_before_eq(this_timer, jiffies)) { + tun_flow_delete(tun, e); + continue; + } + count++; + if (time_before(this_timer, next_timer)) + next_timer = this_timer; + } + } + + if (count) + mod_timer(&tun->flow_gc_timer, round_jiffies_up(next_timer)); + spin_unlock(&tun->lock); +} + +static void tun_flow_update(struct tun_struct *tun, u32 rxhash, + struct tun_file *tfile) +{ + struct hlist_head *head; + struct tun_flow_entry *e; + unsigned long delay = tun->ageing_time; + u16 queue_index = tfile->queue_index; + + if (!rxhash) + return; + else + head = &tun->flows[tun_hashfn(rxhash)]; + + rcu_read_lock(); + + e = tun_flow_find(head, rxhash); + if (likely(e)) { + /* TODO: keep queueing to old queue until it's empty? */ + e->queue_index = queue_index; + e->updated = jiffies; + sock_rps_record_flow_hash(e->rps_rxhash); + } else { + spin_lock_bh(&tun->lock); + if (!tun_flow_find(head, rxhash) && + tun->flow_count < MAX_TAP_FLOWS) + tun_flow_create(tun, head, rxhash, queue_index); + + if (!timer_pending(&tun->flow_gc_timer)) + mod_timer(&tun->flow_gc_timer, + round_jiffies_up(jiffies + delay)); + spin_unlock_bh(&tun->lock); + } + + rcu_read_unlock(); +} + +/** + * Save the hash received in the stack receive path and update the + * flow_hash table accordingly. + */ +static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash) +{ + if (unlikely(e->rps_rxhash != hash)) + e->rps_rxhash = hash; +} + +/* We try to identify a flow through its rxhash first. The reason that + * we do not check rxq no. is because some cards(e.g 82599), chooses + * the rxq based on the txq where the last packet of the flow comes. As + * the userspace application move between processors, we may get a + * different rxq no. here. If we could not get rxhash, then we would + * hope the rxq no. may help here. + */ +static u16 tun_automq_select_queue(struct tun_struct *tun, struct sk_buff *skb) +{ + struct tun_flow_entry *e; + u32 txq = 0; + u32 numqueues = 0; + + numqueues = READ_ONCE(tun->numqueues); + + txq = __skb_get_hash_symmetric(skb); + if (txq) { + e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq); + if (e) { + tun_flow_save_rps_rxhash(e, txq); + txq = e->queue_index; + } else + /* use multiply and shift instead of expensive divide */ + txq = ((u64)txq * numqueues) >> 32; + } else if (likely(skb_rx_queue_recorded(skb))) { + txq = skb_get_rx_queue(skb); + while (unlikely(txq >= numqueues)) + txq -= numqueues; + } + + return txq; +} + +static u16 tun_ebpf_select_queue(struct tun_struct *tun, struct sk_buff *skb) +{ + struct tun_prog *prog; + u32 numqueues; + u16 ret = 0; + + numqueues = READ_ONCE(tun->numqueues); + if (!numqueues) + return 0; + + prog = rcu_dereference(tun->steering_prog); + if (prog) + ret = bpf_prog_run_clear_cb(prog->prog, skb); + + return ret % numqueues; +} + +static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb, + struct net_device *sb_dev, + select_queue_fallback_t fallback) +{ + struct tun_struct *tun = netdev_priv(dev); + u16 ret; + + rcu_read_lock(); + if (rcu_dereference(tun->steering_prog)) + ret = tun_ebpf_select_queue(tun, skb); + else + ret = tun_automq_select_queue(tun, skb); + rcu_read_unlock(); + + return ret; +} + +static inline bool tun_not_capable(struct tun_struct *tun) +{ + const struct cred *cred = current_cred(); + struct net *net = dev_net(tun->dev); + + return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) || + (gid_valid(tun->group) && !in_egroup_p(tun->group))) && + !ns_capable(net->user_ns, CAP_NET_ADMIN); +} + +static void tun_set_real_num_queues(struct tun_struct *tun) +{ + netif_set_real_num_tx_queues(tun->dev, tun->numqueues); + netif_set_real_num_rx_queues(tun->dev, tun->numqueues); +} + +static void tun_disable_queue(struct tun_struct *tun, struct tun_file *tfile) +{ + tfile->detached = tun; + list_add_tail(&tfile->next, &tun->disabled); + ++tun->numdisabled; +} + +static struct tun_struct *tun_enable_queue(struct tun_file *tfile) +{ + struct tun_struct *tun = tfile->detached; + + tfile->detached = NULL; + list_del_init(&tfile->next); + --tun->numdisabled; + return tun; +} + +void tun_ptr_free(void *ptr) +{ + if (!ptr) + return; + if (tun_is_xdp_frame(ptr)) { + struct xdp_frame *xdpf = tun_ptr_to_xdp(ptr); + + xdp_return_frame(xdpf); + } else { + __skb_array_destroy_skb(ptr); + } +} +EXPORT_SYMBOL_GPL(tun_ptr_free); + +static void tun_queue_purge(struct tun_file *tfile) +{ + void *ptr; + + while ((ptr = ptr_ring_consume(&tfile->tx_ring)) != NULL) + tun_ptr_free(ptr); + + skb_queue_purge(&tfile->sk.sk_write_queue); + skb_queue_purge(&tfile->sk.sk_error_queue); +} + +static void __tun_detach(struct tun_file *tfile, bool clean) +{ + struct tun_file *ntfile; + struct tun_struct *tun; + + tun = rtnl_dereference(tfile->tun); + + if (tun && clean) { + tun_napi_disable(tfile); + tun_napi_del(tfile); + } + + if (tun && !tfile->detached) { + u16 index = tfile->queue_index; + BUG_ON(index >= tun->numqueues); + + rcu_assign_pointer(tun->tfiles[index], + tun->tfiles[tun->numqueues - 1]); + ntfile = rtnl_dereference(tun->tfiles[index]); + ntfile->queue_index = index; + rcu_assign_pointer(tun->tfiles[tun->numqueues - 1], + NULL); + + --tun->numqueues; + if (clean) { + RCU_INIT_POINTER(tfile->tun, NULL); + sock_put(&tfile->sk); + } else + tun_disable_queue(tun, tfile); + + synchronize_net(); + tun_flow_delete_by_queue(tun, tun->numqueues + 1); + /* Drop read queue */ + tun_queue_purge(tfile); + tun_set_real_num_queues(tun); + } else if (tfile->detached && clean) { + tun = tun_enable_queue(tfile); + sock_put(&tfile->sk); + } + + if (clean) { + if (tun && tun->numqueues == 0 && tun->numdisabled == 0) { + netif_carrier_off(tun->dev); + + if (!(tun->flags & IFF_PERSIST) && + tun->dev->reg_state == NETREG_REGISTERED) + unregister_netdevice(tun->dev); + } + if (tun) + xdp_rxq_info_unreg(&tfile->xdp_rxq); + ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free); + sock_put(&tfile->sk); + } +} + +static void tun_detach(struct tun_file *tfile, bool clean) +{ + struct tun_struct *tun; + struct net_device *dev; + + rtnl_lock(); + tun = rtnl_dereference(tfile->tun); + dev = tun ? tun->dev : NULL; + __tun_detach(tfile, clean); + if (dev) + netdev_state_change(dev); + rtnl_unlock(); +} + +static void tun_detach_all(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + struct tun_file *tfile, *tmp; + int i, n = tun->numqueues; + + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + BUG_ON(!tfile); + tun_napi_disable(tfile); + tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN; + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + RCU_INIT_POINTER(tfile->tun, NULL); + --tun->numqueues; + } + list_for_each_entry(tfile, &tun->disabled, next) { + tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN; + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + RCU_INIT_POINTER(tfile->tun, NULL); + } + BUG_ON(tun->numqueues != 0); + + synchronize_net(); + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + tun_napi_del(tfile); + /* Drop read queue */ + tun_queue_purge(tfile); + xdp_rxq_info_unreg(&tfile->xdp_rxq); + sock_put(&tfile->sk); + } + list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) { + tun_enable_queue(tfile); + tun_queue_purge(tfile); + xdp_rxq_info_unreg(&tfile->xdp_rxq); + sock_put(&tfile->sk); + } + BUG_ON(tun->numdisabled != 0); + + if (tun->flags & IFF_PERSIST) + module_put(THIS_MODULE); +} + +static int tun_attach(struct tun_struct *tun, struct file *file, + bool skip_filter, bool napi, bool napi_frags) +{ + struct tun_file *tfile = file->private_data; + struct net_device *dev = tun->dev; + int err; + + err = security_tun_dev_attach(tfile->socket.sk, tun->security); + if (err < 0) + goto out; + + err = -EINVAL; + if (rtnl_dereference(tfile->tun) && !tfile->detached) + goto out; + + err = -EBUSY; + if (!(tun->flags & IFF_MULTI_QUEUE) && tun->numqueues == 1) + goto out; + + err = -E2BIG; + if (!tfile->detached && + tun->numqueues + tun->numdisabled == MAX_TAP_QUEUES) + goto out; + + err = 0; + + /* Re-attach the filter to persist device */ + if (!skip_filter && (tun->filter_attached == true)) { + lock_sock(tfile->socket.sk); + err = sk_attach_filter(&tun->fprog, tfile->socket.sk); + release_sock(tfile->socket.sk); + if (!err) + goto out; + } + + if (!tfile->detached && + ptr_ring_resize(&tfile->tx_ring, dev->tx_queue_len, + GFP_KERNEL, tun_ptr_free)) { + err = -ENOMEM; + goto out; + } + + tfile->queue_index = tun->numqueues; + tfile->socket.sk->sk_shutdown &= ~RCV_SHUTDOWN; + + if (tfile->detached) { + /* Re-attach detached tfile, updating XDP queue_index */ + WARN_ON(!xdp_rxq_info_is_reg(&tfile->xdp_rxq)); + + if (tfile->xdp_rxq.queue_index != tfile->queue_index) + tfile->xdp_rxq.queue_index = tfile->queue_index; + } else { + /* Setup XDP RX-queue info, for new tfile getting attached */ + err = xdp_rxq_info_reg(&tfile->xdp_rxq, + tun->dev, tfile->queue_index); + if (err < 0) + goto out; + err = xdp_rxq_info_reg_mem_model(&tfile->xdp_rxq, + MEM_TYPE_PAGE_SHARED, NULL); + if (err < 0) { + xdp_rxq_info_unreg(&tfile->xdp_rxq); + goto out; + } + err = 0; + } + + if (tfile->detached) { + tun_enable_queue(tfile); + } else { + sock_hold(&tfile->sk); + tun_napi_init(tun, tfile, napi, napi_frags); + } + + /* device is allowed to go away first, so no need to hold extra + * refcnt. + */ + + /* Publish tfile->tun and tun->tfiles only after we've fully + * initialized tfile; otherwise we risk using half-initialized + * object. + */ + rcu_assign_pointer(tfile->tun, tun); + rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile); + tun->numqueues++; + tun_set_real_num_queues(tun); +out: + return err; +} + +static struct tun_struct *tun_get(struct tun_file *tfile) +{ + struct tun_struct *tun; + + rcu_read_lock(); + tun = rcu_dereference(tfile->tun); + if (tun) + dev_hold(tun->dev); + rcu_read_unlock(); + + return tun; +} + +static void tun_put(struct tun_struct *tun) +{ + dev_put(tun->dev); +} + +/* TAP filtering */ +static void addr_hash_set(u32 *mask, const u8 *addr) +{ + int n = ether_crc(ETH_ALEN, addr) >> 26; + mask[n >> 5] |= (1 << (n & 31)); +} + +static unsigned int addr_hash_test(const u32 *mask, const u8 *addr) +{ + int n = ether_crc(ETH_ALEN, addr) >> 26; + return mask[n >> 5] & (1 << (n & 31)); +} + +static int update_filter(struct tap_filter *filter, void __user *arg) +{ + struct { u8 u[ETH_ALEN]; } *addr; + struct tun_filter uf; + int err, alen, n, nexact; + + if (copy_from_user(&uf, arg, sizeof(uf))) + return -EFAULT; + + if (!uf.count) { + /* Disabled */ + filter->count = 0; + return 0; + } + + alen = ETH_ALEN * uf.count; + addr = memdup_user(arg + sizeof(uf), alen); + if (IS_ERR(addr)) + return PTR_ERR(addr); + + /* The filter is updated without holding any locks. Which is + * perfectly safe. We disable it first and in the worst + * case we'll accept a few undesired packets. */ + filter->count = 0; + wmb(); + + /* Use first set of addresses as an exact filter */ + for (n = 0; n < uf.count && n < FLT_EXACT_COUNT; n++) + memcpy(filter->addr[n], addr[n].u, ETH_ALEN); + + nexact = n; + + /* Remaining multicast addresses are hashed, + * unicast will leave the filter disabled. */ + memset(filter->mask, 0, sizeof(filter->mask)); + for (; n < uf.count; n++) { + if (!is_multicast_ether_addr(addr[n].u)) { + err = 0; /* no filter */ + goto free_addr; + } + addr_hash_set(filter->mask, addr[n].u); + } + + /* For ALLMULTI just set the mask to all ones. + * This overrides the mask populated above. */ + if ((uf.flags & TUN_FLT_ALLMULTI)) + memset(filter->mask, ~0, sizeof(filter->mask)); + + /* Now enable the filter */ + wmb(); + filter->count = nexact; + + /* Return the number of exact filters */ + err = nexact; +free_addr: + kfree(addr); + return err; +} + +/* Returns: 0 - drop, !=0 - accept */ +static int run_filter(struct tap_filter *filter, const struct sk_buff *skb) +{ + /* Cannot use eth_hdr(skb) here because skb_mac_hdr() is incorrect + * at this point. */ + struct ethhdr *eh = (struct ethhdr *) skb->data; + int i; + + /* Exact match */ + for (i = 0; i < filter->count; i++) + if (ether_addr_equal(eh->h_dest, filter->addr[i])) + return 1; + + /* Inexact match (multicast only) */ + if (is_multicast_ether_addr(eh->h_dest)) + return addr_hash_test(filter->mask, eh->h_dest); + + return 0; +} + +/* + * Checks whether the packet is accepted or not. + * Returns: 0 - drop, !=0 - accept + */ +static int check_filter(struct tap_filter *filter, const struct sk_buff *skb) +{ + if (!filter->count) + return 1; + + return run_filter(filter, skb); +} + +/* Network device part of the driver */ + +static const struct ethtool_ops tun_ethtool_ops; + +/* Net device detach from fd. */ +static void tun_net_uninit(struct net_device *dev) +{ + tun_detach_all(dev); +} + +/* Net device open. */ +static int tun_net_open(struct net_device *dev) +{ + netif_tx_start_all_queues(dev); + + return 0; +} + +/* Net device close. */ +static int tun_net_close(struct net_device *dev) +{ + netif_tx_stop_all_queues(dev); + return 0; +} + +/* Net device start xmit */ +static void tun_automq_xmit(struct tun_struct *tun, struct sk_buff *skb) +{ +#ifdef CONFIG_RPS + if (tun->numqueues == 1 && static_key_false(&rps_needed)) { + /* Select queue was not called for the skbuff, so we extract the + * RPS hash and save it into the flow_table here. + */ + __u32 rxhash; + + rxhash = __skb_get_hash_symmetric(skb); + if (rxhash) { + struct tun_flow_entry *e; + e = tun_flow_find(&tun->flows[tun_hashfn(rxhash)], + rxhash); + if (e) + tun_flow_save_rps_rxhash(e, rxhash); + } + } +#endif +} + +static unsigned int run_ebpf_filter(struct tun_struct *tun, + struct sk_buff *skb, + int len) +{ + struct tun_prog *prog = rcu_dereference(tun->filter_prog); + + if (prog) + len = bpf_prog_run_clear_cb(prog->prog, skb); + + return len; +} + +/* Net device start xmit */ +static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + int txq = skb->queue_mapping; + struct tun_file *tfile; + int len = skb->len; + + rcu_read_lock(); + tfile = rcu_dereference(tun->tfiles[txq]); + + /* Drop packet if interface is not attached */ + if (!tfile) + goto drop; + + if (!rcu_dereference(tun->steering_prog)) + tun_automq_xmit(tun, skb); + + tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len); + + BUG_ON(!tfile); + + /* Drop if the filter does not like it. + * This is a noop if the filter is disabled. + * Filter can be enabled only for the TAP devices. */ + if (!check_filter(&tun->txflt, skb)) + goto drop; + + if (tfile->socket.sk->sk_filter && + sk_filter(tfile->socket.sk, skb)) + goto drop; + + len = run_ebpf_filter(tun, skb, len); + if (len == 0 || pskb_trim(skb, len)) + goto drop; + + if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC))) + goto drop; + + skb_tx_timestamp(skb); + + /* Orphan the skb - required as we might hang on to it + * for indefinite time. + */ + skb_orphan(skb); + + nf_reset(skb); + + if (ptr_ring_produce(&tfile->tx_ring, skb)) + goto drop; + + /* Notify and wake up reader process */ + if (tfile->flags & TUN_FASYNC) + kill_fasync(&tfile->fasync, SIGIO, POLL_IN); + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + + rcu_read_unlock(); + return NETDEV_TX_OK; + +drop: + this_cpu_inc(tun->pcpu_stats->tx_dropped); + skb_tx_error(skb); + kfree_skb(skb); + rcu_read_unlock(); + return NET_XMIT_DROP; +} + +static void tun_net_mclist(struct net_device *dev) +{ + /* + * This callback is supposed to deal with mc filter in + * _rx_ path and has nothing to do with the _tx_ path. + * In rx path we always accept everything userspace gives us. + */ +} + +static netdev_features_t tun_net_fix_features(struct net_device *dev, + netdev_features_t features) +{ + struct tun_struct *tun = netdev_priv(dev); + + return (features & tun->set_features) | (features & ~TUN_USER_FEATURES); +} + +static void tun_set_headroom(struct net_device *dev, int new_hr) +{ + struct tun_struct *tun = netdev_priv(dev); + + if (new_hr < NET_SKB_PAD) + new_hr = NET_SKB_PAD; + + tun->align = new_hr; +} + +static void +tun_net_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +{ + u32 rx_dropped = 0, tx_dropped = 0, rx_frame_errors = 0; + struct tun_struct *tun = netdev_priv(dev); + struct tun_pcpu_stats *p; + int i; + + for_each_possible_cpu(i) { + u64 rxpackets, rxbytes, txpackets, txbytes; + unsigned int start; + + p = per_cpu_ptr(tun->pcpu_stats, i); + do { + start = u64_stats_fetch_begin(&p->syncp); + rxpackets = p->rx_packets; + rxbytes = p->rx_bytes; + txpackets = p->tx_packets; + txbytes = p->tx_bytes; + } while (u64_stats_fetch_retry(&p->syncp, start)); + + stats->rx_packets += rxpackets; + stats->rx_bytes += rxbytes; + stats->tx_packets += txpackets; + stats->tx_bytes += txbytes; + + /* u32 counters */ + rx_dropped += p->rx_dropped; + rx_frame_errors += p->rx_frame_errors; + tx_dropped += p->tx_dropped; + } + stats->rx_dropped = rx_dropped; + stats->rx_frame_errors = rx_frame_errors; + stats->tx_dropped = tx_dropped; +} + +static int tun_xdp_set(struct net_device *dev, struct bpf_prog *prog, + struct netlink_ext_ack *extack) +{ + struct tun_struct *tun = netdev_priv(dev); + struct bpf_prog *old_prog; + + old_prog = rtnl_dereference(tun->xdp_prog); + rcu_assign_pointer(tun->xdp_prog, prog); + if (old_prog) + bpf_prog_put(old_prog); + + return 0; +} + +static u32 tun_xdp_query(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + const struct bpf_prog *xdp_prog; + + xdp_prog = rtnl_dereference(tun->xdp_prog); + if (xdp_prog) + return xdp_prog->aux->id; + + return 0; +} + +static int tun_xdp(struct net_device *dev, struct netdev_bpf *xdp) +{ + switch (xdp->command) { + case XDP_SETUP_PROG: + return tun_xdp_set(dev, xdp->prog, xdp->extack); + case XDP_QUERY_PROG: + xdp->prog_id = tun_xdp_query(dev); + return 0; + default: + return -EINVAL; + } +} + +static int tun_net_change_carrier(struct net_device *dev, bool new_carrier) +{ + if (new_carrier) { + netif_carrier_on(dev); + } else { + netif_carrier_off(dev); + } + return 0; +} + +#define MIN_MTU 68 +#define MAX_MTU 65535 + +static int tun_net_change_mtu(struct net_device *dev, int new_mtu) +{ + if (new_mtu < MIN_MTU || new_mtu + dev->hard_header_len > MAX_MTU) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +static const struct net_device_ops tun_netdev_ops = { + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, + .ndo_stop = tun_net_close, + .ndo_start_xmit = tun_net_xmit, + .ndo_fix_features = tun_net_fix_features, + .ndo_select_queue = tun_select_queue, + .ndo_set_rx_headroom = tun_set_headroom, + .ndo_get_stats64 = tun_net_get_stats64, + .ndo_change_carrier = tun_net_change_carrier, + .ndo_change_mtu = tun_net_change_mtu, +}; + +static void __tun_xdp_flush_tfile(struct tun_file *tfile) +{ + /* Notify and wake up reader process */ + if (tfile->flags & TUN_FASYNC) + kill_fasync(&tfile->fasync, SIGIO, POLL_IN); + tfile->socket.sk->sk_data_ready(tfile->socket.sk); +} + +static int tun_xdp_xmit(struct net_device *dev, int n, + struct xdp_frame **frames, u32 flags) +{ + struct tun_struct *tun = netdev_priv(dev); + struct tun_file *tfile; + u32 numqueues; + int drops = 0; + int cnt = n; + int i; + + if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) + return -EINVAL; + + rcu_read_lock(); + +resample: + numqueues = READ_ONCE(tun->numqueues); + if (!numqueues) { + rcu_read_unlock(); + return -ENXIO; /* Caller will free/return all frames */ + } + + tfile = rcu_dereference(tun->tfiles[smp_processor_id() % + numqueues]); + if (unlikely(!tfile)) + goto resample; + + spin_lock(&tfile->tx_ring.producer_lock); + for (i = 0; i < n; i++) { + struct xdp_frame *xdp = frames[i]; + /* Encode the XDP flag into lowest bit for consumer to differ + * XDP buffer from sk_buff. + */ + void *frame = tun_xdp_to_ptr(xdp); + + if (__ptr_ring_produce(&tfile->tx_ring, frame)) { + this_cpu_inc(tun->pcpu_stats->tx_dropped); + xdp_return_frame_rx_napi(xdp); + drops++; + } + } + spin_unlock(&tfile->tx_ring.producer_lock); + + if (flags & XDP_XMIT_FLUSH) + __tun_xdp_flush_tfile(tfile); + + rcu_read_unlock(); + return cnt - drops; +} + +static int tun_xdp_tx(struct net_device *dev, struct xdp_buff *xdp) +{ + struct xdp_frame *frame = convert_to_xdp_frame(xdp); + + if (unlikely(!frame)) + return -EOVERFLOW; + + return tun_xdp_xmit(dev, 1, &frame, XDP_XMIT_FLUSH); +} + +static const struct net_device_ops tap_netdev_ops = { + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, + .ndo_stop = tun_net_close, + .ndo_start_xmit = tun_net_xmit, + .ndo_fix_features = tun_net_fix_features, + .ndo_set_rx_mode = tun_net_mclist, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_select_queue = tun_select_queue, + .ndo_features_check = passthru_features_check, + .ndo_set_rx_headroom = tun_set_headroom, + .ndo_get_stats64 = tun_net_get_stats64, + .ndo_bpf = tun_xdp, + .ndo_xdp_xmit = tun_xdp_xmit, + .ndo_change_carrier = tun_net_change_carrier, + .ndo_change_mtu = tun_net_change_mtu, +}; + +static void tun_flow_init(struct tun_struct *tun) +{ + int i; + + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) + INIT_HLIST_HEAD(&tun->flows[i]); + + tun->ageing_time = TUN_FLOW_EXPIRE; + timer_setup(&tun->flow_gc_timer, tun_flow_cleanup, 0); + mod_timer(&tun->flow_gc_timer, + round_jiffies_up(jiffies + tun->ageing_time)); +} + +static void tun_flow_uninit(struct tun_struct *tun) +{ + del_timer_sync(&tun->flow_gc_timer); + tun_flow_flush(tun); +} + +#define MIN_MTU 68 +#define MAX_MTU 65535 + +/* Initialize net device. */ +static void tun_net_init(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + switch (tun->flags & TUN_TYPE_MASK) { + case IFF_TUN: + dev->netdev_ops = &tun_netdev_ops; + + /* Point-to-Point TUN Device */ + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->mtu = 1500; + + /* Zero header length */ + dev->type = ARPHRD_NONE; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + break; + + case IFF_TAP: + dev->netdev_ops = &tap_netdev_ops; + /* Ethernet TAP Device */ + ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + + eth_hw_addr_random(dev); + + break; + } + + dev->min_mtu = MIN_MTU; + dev->max_mtu = MAX_MTU - dev->hard_header_len; +} + +static bool tun_sock_writeable(struct tun_struct *tun, struct tun_file *tfile) +{ + struct sock *sk = tfile->socket.sk; + + return (tun->dev->flags & IFF_UP) && sock_writeable(sk); +} + +/* Character device part */ + +/* Poll */ +static __poll_t tun_chr_poll(struct file *file, poll_table *wait) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = tun_get(tfile); + struct sock *sk; + __poll_t mask = 0; + + if (!tun) + return EPOLLERR; + + sk = tfile->socket.sk; + + tun_debug(KERN_INFO, tun, "tun_chr_poll\n"); + + poll_wait(file, sk_sleep(sk), wait); + + if (!ptr_ring_empty(&tfile->tx_ring)) + mask |= EPOLLIN | EPOLLRDNORM; + + /* Make sure SOCKWQ_ASYNC_NOSPACE is set if not writable to + * guarantee EPOLLOUT to be raised by either here or + * tun_sock_write_space(). Then process could get notification + * after it writes to a down device and meets -EIO. + */ + if (tun_sock_writeable(tun, tfile) || + (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) && + tun_sock_writeable(tun, tfile))) + mask |= EPOLLOUT | EPOLLWRNORM; + + if (tun->dev->reg_state != NETREG_REGISTERED) + mask = EPOLLERR; + + tun_put(tun); + return mask; +} + +static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile, + size_t len, + const struct iov_iter *it) +{ + struct sk_buff *skb; + size_t linear; + int err; + int i; + + if (it->nr_segs > MAX_SKB_FRAGS + 1) + return ERR_PTR(-ENOMEM); + + local_bh_disable(); + skb = napi_get_frags(&tfile->napi); + local_bh_enable(); + if (!skb) + return ERR_PTR(-ENOMEM); + + linear = iov_iter_single_seg_count(it); + err = __skb_grow(skb, linear); + if (err) + goto free; + + skb->len = len; + skb->data_len = len - linear; + skb->truesize += skb->data_len; + + for (i = 1; i < it->nr_segs; i++) { + struct page_frag *pfrag = ¤t->task_frag; + size_t fragsz = it->iov[i].iov_len; + + if (fragsz == 0 || fragsz > PAGE_SIZE) { + err = -EINVAL; + goto free; + } + + if (!skb_page_frag_refill(fragsz, pfrag, GFP_KERNEL)) { + err = -ENOMEM; + goto free; + } + + skb_fill_page_desc(skb, i - 1, pfrag->page, + pfrag->offset, fragsz); + page_ref_inc(pfrag->page); + pfrag->offset += fragsz; + } + + return skb; +free: + /* frees skb and all frags allocated with napi_alloc_frag() */ + napi_free_frags(&tfile->napi); + return ERR_PTR(err); +} + +/* prepad is the amount to reserve at front. len is length after that. + * linear is a hint as to how much to copy (usually headers). */ +static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, + size_t prepad, size_t len, + size_t linear, int noblock) +{ + struct sock *sk = tfile->socket.sk; + struct sk_buff *skb; + int err; + + /* Under a page? Don't bother with paged skb. */ + if (prepad + len < PAGE_SIZE || !linear) + linear = len; + + skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, + &err, 0); + if (!skb) + return ERR_PTR(err); + + skb_reserve(skb, prepad); + skb_put(skb, linear); + skb->data_len = len - linear; + skb->len += len - linear; + + return skb; +} + +static void tun_rx_batched(struct tun_struct *tun, struct tun_file *tfile, + struct sk_buff *skb, int more) +{ + struct sk_buff_head *queue = &tfile->sk.sk_write_queue; + struct sk_buff_head process_queue; + u32 rx_batched = tun->rx_batched; + bool rcv = false; + + if (!rx_batched || (!more && skb_queue_empty(queue))) { + local_bh_disable(); + skb_record_rx_queue(skb, tfile->queue_index); + netif_receive_skb(skb); + local_bh_enable(); + return; + } + + spin_lock(&queue->lock); + if (!more || skb_queue_len(queue) == rx_batched) { + __skb_queue_head_init(&process_queue); + skb_queue_splice_tail_init(queue, &process_queue); + rcv = true; + } else { + __skb_queue_tail(queue, skb); + } + spin_unlock(&queue->lock); + + if (rcv) { + struct sk_buff *nskb; + + local_bh_disable(); + while ((nskb = __skb_dequeue(&process_queue))) { + skb_record_rx_queue(nskb, tfile->queue_index); + netif_receive_skb(nskb); + } + skb_record_rx_queue(skb, tfile->queue_index); + netif_receive_skb(skb); + local_bh_enable(); + } +} + +static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile, + int len, int noblock, bool zerocopy) +{ + if ((tun->flags & TUN_TYPE_MASK) != IFF_TAP) + return false; + + if (tfile->socket.sk->sk_sndbuf != INT_MAX) + return false; + + if (!noblock) + return false; + + if (zerocopy) + return false; + + if (SKB_DATA_ALIGN(len + TUN_RX_PAD) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) > PAGE_SIZE) + return false; + + return true; +} + +static struct sk_buff *tun_build_skb(struct tun_struct *tun, + struct tun_file *tfile, + struct iov_iter *from, + struct virtio_net_hdr *hdr, + int len, int *skb_xdp) +{ + struct page_frag *alloc_frag = ¤t->task_frag; + struct sk_buff *skb; + struct bpf_prog *xdp_prog; + int buflen = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + unsigned int delta = 0; + char *buf; + size_t copied; + int err, pad = TUN_RX_PAD; + + rcu_read_lock(); + xdp_prog = rcu_dereference(tun->xdp_prog); + if (xdp_prog) + pad += TUN_HEADROOM; + buflen += SKB_DATA_ALIGN(len + pad); + rcu_read_unlock(); + + alloc_frag->offset = ALIGN((u64)alloc_frag->offset, SMP_CACHE_BYTES); + if (unlikely(!skb_page_frag_refill(buflen, alloc_frag, GFP_KERNEL))) + return ERR_PTR(-ENOMEM); + + buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; + copied = copy_page_from_iter(alloc_frag->page, + alloc_frag->offset + pad, + len, from); + if (copied != len) + return ERR_PTR(-EFAULT); + + /* There's a small window that XDP may be set after the check + * of xdp_prog above, this should be rare and for simplicity + * we do XDP on skb in case the headroom is not enough. + */ + if (hdr->gso_type || !xdp_prog) + *skb_xdp = 1; + else + *skb_xdp = 0; + + local_bh_disable(); + rcu_read_lock(); + xdp_prog = rcu_dereference(tun->xdp_prog); + if (xdp_prog && !*skb_xdp) { + struct xdp_buff xdp; + void *orig_data; + u32 act; + + xdp.data_hard_start = buf; + xdp.data = buf + pad; + xdp_set_data_meta_invalid(&xdp); + xdp.data_end = xdp.data + len; + xdp.rxq = &tfile->xdp_rxq; + orig_data = xdp.data; + act = bpf_prog_run_xdp(xdp_prog, &xdp); + + switch (act) { + case XDP_REDIRECT: + get_page(alloc_frag->page); + alloc_frag->offset += buflen; + err = xdp_do_redirect(tun->dev, &xdp, xdp_prog); + xdp_do_flush_map(); + if (err) + goto err_redirect; + rcu_read_unlock(); + local_bh_enable(); + return NULL; + case XDP_TX: + get_page(alloc_frag->page); + alloc_frag->offset += buflen; + if (tun_xdp_tx(tun->dev, &xdp) < 0) + goto err_redirect; + rcu_read_unlock(); + local_bh_enable(); + return NULL; + case XDP_PASS: + delta = orig_data - xdp.data; + len = xdp.data_end - xdp.data; + break; + default: + bpf_warn_invalid_xdp_action(act); + /* fall through */ + case XDP_ABORTED: + trace_xdp_exception(tun->dev, xdp_prog, act); + /* fall through */ + case XDP_DROP: + goto err_xdp; + } + } + + skb = build_skb(buf, buflen); + if (!skb) { + rcu_read_unlock(); + local_bh_enable(); + return ERR_PTR(-ENOMEM); + } + + skb_reserve(skb, pad - delta); + skb_put(skb, len); + skb_set_owner_w(skb, tfile->socket.sk); + get_page(alloc_frag->page); + alloc_frag->offset += buflen; + + rcu_read_unlock(); + local_bh_enable(); + + return skb; + +err_redirect: + put_page(alloc_frag->page); +err_xdp: + rcu_read_unlock(); + local_bh_enable(); + this_cpu_inc(tun->pcpu_stats->rx_dropped); + return NULL; +} + +/* Get packet from user space buffer */ +static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + void *msg_control, struct iov_iter *from, + int noblock, bool more) +{ + struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; + struct sk_buff *skb; + size_t total_len = iov_iter_count(from); + size_t len = total_len, align = tun->align, linear; + struct virtio_net_hdr gso = { 0 }; + struct tun_pcpu_stats *stats; + int good_linear; + int copylen; + bool zerocopy = false; + int err; + u32 rxhash = 0; + int skb_xdp = 1; + bool frags = tun_napi_frags_enabled(tfile); + + if (!(tun->flags & IFF_NO_PI)) { + if (len < sizeof(pi)) + return -EINVAL; + len -= sizeof(pi); + + if (!copy_from_iter_full(&pi, sizeof(pi), from)) + return -EFAULT; + } + + if (tun->flags & IFF_VNET_HDR) { + int vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz); + + if (len < vnet_hdr_sz) + return -EINVAL; + len -= vnet_hdr_sz; + + if (!copy_from_iter_full(&gso, sizeof(gso), from)) + return -EFAULT; + + if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && + tun16_to_cpu(tun, gso.csum_start) + tun16_to_cpu(tun, gso.csum_offset) + 2 > tun16_to_cpu(tun, gso.hdr_len)) + gso.hdr_len = cpu_to_tun16(tun, tun16_to_cpu(tun, gso.csum_start) + tun16_to_cpu(tun, gso.csum_offset) + 2); + + if (tun16_to_cpu(tun, gso.hdr_len) > len) + return -EINVAL; + iov_iter_advance(from, vnet_hdr_sz - sizeof(gso)); + } + + if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP) { + align += NET_IP_ALIGN; + if (unlikely(len < ETH_HLEN || + (gso.hdr_len && tun16_to_cpu(tun, gso.hdr_len) < ETH_HLEN))) + return -EINVAL; + } + + good_linear = SKB_MAX_HEAD(align); + + if (msg_control) { + struct iov_iter i = *from; + + /* There are 256 bytes to be copied in skb, so there is + * enough room for skb expand head in case it is used. + * The rest of the buffer is mapped from userspace. + */ + copylen = gso.hdr_len ? tun16_to_cpu(tun, gso.hdr_len) : GOODCOPY_LEN; + if (copylen > good_linear) + copylen = good_linear; + linear = copylen; + iov_iter_advance(&i, copylen); + if (iov_iter_npages(&i, INT_MAX) <= MAX_SKB_FRAGS) + zerocopy = true; + } + + if (!frags && tun_can_build_skb(tun, tfile, len, noblock, zerocopy)) { + /* For the packet that is not easy to be processed + * (e.g gso or jumbo packet), we will do it at after + * skb was created with generic XDP routine. + */ + skb = tun_build_skb(tun, tfile, from, &gso, len, &skb_xdp); + if (IS_ERR(skb)) { + this_cpu_inc(tun->pcpu_stats->rx_dropped); + return PTR_ERR(skb); + } + if (!skb) + return total_len; + } else { + if (!zerocopy) { + copylen = len; + if (tun16_to_cpu(tun, gso.hdr_len) > good_linear) + linear = good_linear; + else + linear = tun16_to_cpu(tun, gso.hdr_len); + } + + if (frags) { + mutex_lock(&tfile->napi_mutex); + skb = tun_napi_alloc_frags(tfile, copylen, from); + /* tun_napi_alloc_frags() enforces a layout for the skb. + * If zerocopy is enabled, then this layout will be + * overwritten by zerocopy_sg_from_iter(). + */ + zerocopy = false; + } else { + skb = tun_alloc_skb(tfile, align, copylen, linear, + noblock); + } + + if (IS_ERR(skb)) { + if (PTR_ERR(skb) != -EAGAIN) + this_cpu_inc(tun->pcpu_stats->rx_dropped); + if (frags) + mutex_unlock(&tfile->napi_mutex); + return PTR_ERR(skb); + } + + if (zerocopy) + err = zerocopy_sg_from_iter(skb, from); + else + err = skb_copy_datagram_from_iter(skb, 0, from, len); + + if (err) { + err = -EFAULT; +drop: + this_cpu_inc(tun->pcpu_stats->rx_dropped); + kfree_skb(skb); + if (frags) { + tfile->napi.skb = NULL; + mutex_unlock(&tfile->napi_mutex); + } + + return err; + } + } + + if (virtio_net_hdr_to_skb(skb, &gso, tun_is_little_endian(tun))) { + this_cpu_inc(tun->pcpu_stats->rx_frame_errors); + kfree_skb(skb); + if (frags) { + tfile->napi.skb = NULL; + mutex_unlock(&tfile->napi_mutex); + } + + return -EINVAL; + } + + switch (tun->flags & TUN_TYPE_MASK) { + case IFF_TUN: + if (tun->flags & IFF_NO_PI) { + u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0; + + switch (ip_version) { + case 4: + pi.proto = htons(ETH_P_IP); + break; + case 6: + pi.proto = htons(ETH_P_IPV6); + break; + default: + this_cpu_inc(tun->pcpu_stats->rx_dropped); + kfree_skb(skb); + return -EINVAL; + } + } + + skb_reset_mac_header(skb); + skb->protocol = pi.proto; + skb->dev = tun->dev; + break; + case IFF_TAP: + if (!frags) + skb->protocol = eth_type_trans(skb, tun->dev); + break; + } + + /* copy skb_ubuf_info for callback when skb has no error */ + if (zerocopy) { + skb_shinfo(skb)->destructor_arg = msg_control; + skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; + } else if (msg_control) { + struct ubuf_info *uarg = msg_control; + uarg->callback(uarg, false); + } + + skb_reset_network_header(skb); + skb_probe_transport_header(skb, 0); + + if (skb_xdp) { + struct bpf_prog *xdp_prog; + int ret; + + local_bh_disable(); + rcu_read_lock(); + xdp_prog = rcu_dereference(tun->xdp_prog); + if (xdp_prog) { + ret = do_xdp_generic(xdp_prog, skb); + if (ret != XDP_PASS) { + rcu_read_unlock(); + local_bh_enable(); + return total_len; + } + } + rcu_read_unlock(); + local_bh_enable(); + } + + /* Compute the costly rx hash only if needed for flow updates. + * We may get a very small possibility of OOO during switching, not + * worth to optimize. + */ + if (!rcu_access_pointer(tun->steering_prog) && tun->numqueues > 1 && + !tfile->detached) + rxhash = __skb_get_hash_symmetric(skb); + + rcu_read_lock(); + if (unlikely(!(tun->dev->flags & IFF_UP))) { + err = -EIO; + rcu_read_unlock(); + goto drop; + } + + if (frags) { + /* Exercise flow dissector code path. */ + u32 headlen = eth_get_headlen(skb->data, skb_headlen(skb)); + + if (unlikely(headlen > skb_headlen(skb))) { + this_cpu_inc(tun->pcpu_stats->rx_dropped); + napi_free_frags(&tfile->napi); + rcu_read_unlock(); + mutex_unlock(&tfile->napi_mutex); + WARN_ON(1); + return -ENOMEM; + } + + local_bh_disable(); + napi_gro_frags(&tfile->napi); + local_bh_enable(); + mutex_unlock(&tfile->napi_mutex); + } else if (tfile->napi_enabled) { + struct sk_buff_head *queue = &tfile->sk.sk_write_queue; + int queue_len; + + spin_lock_bh(&queue->lock); + __skb_queue_tail(queue, skb); + queue_len = skb_queue_len(queue); + spin_unlock(&queue->lock); + + if (!more || queue_len > NAPI_POLL_WEIGHT) + napi_schedule(&tfile->napi); + + local_bh_enable(); + } else if (!IS_ENABLED(CONFIG_4KSTACKS)) { + tun_rx_batched(tun, tfile, skb, more); + } else { + netif_rx_ni(skb); + } + rcu_read_unlock(); + + stats = get_cpu_ptr(tun->pcpu_stats); + u64_stats_update_begin(&stats->syncp); + stats->rx_packets++; + stats->rx_bytes += len; + u64_stats_update_end(&stats->syncp); + put_cpu_ptr(stats); + + if (rxhash) + tun_flow_update(tun, rxhash, tfile); + + return total_len; +} + +static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + struct file *file = iocb->ki_filp; + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = tun_get(tfile); + ssize_t result; + + if (!tun) + return -EBADFD; + + result = tun_get_user(tun, tfile, NULL, from, + file->f_flags & O_NONBLOCK, false); + + tun_put(tun); + return result; +} + +static ssize_t tun_put_user_xdp(struct tun_struct *tun, + struct tun_file *tfile, + struct xdp_frame *xdp_frame, + struct iov_iter *iter) +{ + int vnet_hdr_sz = 0; + size_t size = xdp_frame->len; + struct tun_pcpu_stats *stats; + size_t ret; + + if (tun->flags & IFF_VNET_HDR) { + struct virtio_net_hdr gso = { 0 }; + + vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz); + if (unlikely(iov_iter_count(iter) < vnet_hdr_sz)) + return -EINVAL; + if (unlikely(copy_to_iter(&gso, sizeof(gso), iter) != + sizeof(gso))) + return -EFAULT; + iov_iter_advance(iter, vnet_hdr_sz - sizeof(gso)); + } + + ret = copy_to_iter(xdp_frame->data, size, iter) + vnet_hdr_sz; + + stats = get_cpu_ptr(tun->pcpu_stats); + u64_stats_update_begin(&stats->syncp); + stats->tx_packets++; + stats->tx_bytes += ret; + u64_stats_update_end(&stats->syncp); + put_cpu_ptr(tun->pcpu_stats); + + return ret; +} + +/* Put packet to the user space buffer */ +static ssize_t tun_put_user(struct tun_struct *tun, + struct tun_file *tfile, + struct sk_buff *skb, + struct iov_iter *iter) +{ + struct tun_pi pi = { 0, skb->protocol }; + struct tun_pcpu_stats *stats; + ssize_t total; + int vlan_offset = 0; + int vlan_hlen = 0; + int vnet_hdr_sz = 0; + + if (skb_vlan_tag_present(skb)) + vlan_hlen = VLAN_HLEN; + + if (tun->flags & IFF_VNET_HDR) + vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz); + + total = skb->len + vlan_hlen + vnet_hdr_sz; + + if (!(tun->flags & IFF_NO_PI)) { + if (iov_iter_count(iter) < sizeof(pi)) + return -EINVAL; + + total += sizeof(pi); + if (iov_iter_count(iter) < total) { + /* Packet will be striped */ + pi.flags |= TUN_PKT_STRIP; + } + + if (copy_to_iter(&pi, sizeof(pi), iter) != sizeof(pi)) + return -EFAULT; + } + + if (vnet_hdr_sz) { + struct virtio_net_hdr gso; + + if (iov_iter_count(iter) < vnet_hdr_sz) + return -EINVAL; + + if (virtio_net_hdr_from_skb(skb, &gso, + tun_is_little_endian(tun), true, + vlan_hlen)) { + struct skb_shared_info *sinfo = skb_shinfo(skb); + pr_err("unexpected GSO type: " + "0x%x, gso_size %d, hdr_len %d\n", + sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size), + tun16_to_cpu(tun, gso.hdr_len)); + print_hex_dump(KERN_ERR, "tun: ", + DUMP_PREFIX_NONE, + 16, 1, skb->head, + min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true); + WARN_ON_ONCE(1); + return -EINVAL; + } + + if (copy_to_iter(&gso, sizeof(gso), iter) != sizeof(gso)) + return -EFAULT; + + iov_iter_advance(iter, vnet_hdr_sz - sizeof(gso)); + } + + if (vlan_hlen) { + int ret; + struct veth veth; + + veth.h_vlan_proto = skb->vlan_proto; + veth.h_vlan_TCI = htons(skb_vlan_tag_get(skb)); + + vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); + + ret = skb_copy_datagram_iter(skb, 0, iter, vlan_offset); + if (ret || !iov_iter_count(iter)) + goto done; + + ret = copy_to_iter(&veth, sizeof(veth), iter); + if (ret != sizeof(veth) || !iov_iter_count(iter)) + goto done; + } + + skb_copy_datagram_iter(skb, vlan_offset, iter, skb->len - vlan_offset); + +done: + /* caller is in process context, */ + stats = get_cpu_ptr(tun->pcpu_stats); + u64_stats_update_begin(&stats->syncp); + stats->tx_packets++; + stats->tx_bytes += skb->len + vlan_hlen; + u64_stats_update_end(&stats->syncp); + put_cpu_ptr(tun->pcpu_stats); + + return total; +} + +static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err) +{ + DECLARE_WAITQUEUE(wait, current); + void *ptr = NULL; + int error = 0; + + ptr = ptr_ring_consume(&tfile->tx_ring); + if (ptr) + goto out; + if (noblock) { + error = -EAGAIN; + goto out; + } + + add_wait_queue(&tfile->wq.wait, &wait); + + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + ptr = ptr_ring_consume(&tfile->tx_ring); + if (ptr) + break; + if (signal_pending(current)) { + error = -ERESTARTSYS; + break; + } + if (tfile->socket.sk->sk_shutdown & RCV_SHUTDOWN) { + error = -EFAULT; + break; + } + + schedule(); + } + + __set_current_state(TASK_RUNNING); + remove_wait_queue(&tfile->wq.wait, &wait); + +out: + *err = error; + return ptr; +} + +static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile, + struct iov_iter *to, + int noblock, void *ptr) +{ + ssize_t ret; + int err; + + tun_debug(KERN_INFO, tun, "tun_do_read\n"); + + if (!iov_iter_count(to)) { + tun_ptr_free(ptr); + return 0; + } + + if (!ptr) { + /* Read frames from ring */ + ptr = tun_ring_recv(tfile, noblock, &err); + if (!ptr) + return err; + } + + if (tun_is_xdp_frame(ptr)) { + struct xdp_frame *xdpf = tun_ptr_to_xdp(ptr); + + ret = tun_put_user_xdp(tun, tfile, xdpf, to); + xdp_return_frame(xdpf); + } else { + struct sk_buff *skb = ptr; + + ret = tun_put_user(tun, tfile, skb, to); + if (unlikely(ret < 0)) + kfree_skb(skb); + else + consume_skb(skb); + } + + return ret; +} + +static ssize_t tun_chr_read_iter(struct kiocb *iocb, struct iov_iter *to) +{ + struct file *file = iocb->ki_filp; + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = tun_get(tfile); + ssize_t len = iov_iter_count(to), ret; + + if (!tun) + return -EBADFD; + ret = tun_do_read(tun, tfile, to, file->f_flags & O_NONBLOCK, NULL); + ret = min_t(ssize_t, ret, len); + if (ret > 0) + iocb->ki_pos = ret; + tun_put(tun); + return ret; +} + +static void tun_prog_free(struct rcu_head *rcu) +{ + struct tun_prog *prog = container_of(rcu, struct tun_prog, rcu); + + bpf_prog_destroy(prog->prog); + kfree(prog); +} + +static int __tun_set_ebpf(struct tun_struct *tun, + struct tun_prog __rcu **prog_p, + struct bpf_prog *prog) +{ + struct tun_prog *old, *new = NULL; + + if (prog) { + new = kmalloc(sizeof(*new), GFP_KERNEL); + if (!new) + return -ENOMEM; + new->prog = prog; + } + + spin_lock_bh(&tun->lock); + old = rcu_dereference_protected(*prog_p, + lockdep_is_held(&tun->lock)); + rcu_assign_pointer(*prog_p, new); + spin_unlock_bh(&tun->lock); + + if (old) + call_rcu(&old->rcu, tun_prog_free); + + return 0; +} + +static void tun_free_netdev(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + BUG_ON(!(list_empty(&tun->disabled))); + free_percpu(tun->pcpu_stats); + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); + __tun_set_ebpf(tun, &tun->steering_prog, NULL); + __tun_set_ebpf(tun, &tun->filter_prog, NULL); +} + +static void tun_setup(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + tun->owner = INVALID_UID; + tun->group = INVALID_GID; + tun_default_link_ksettings(dev, &tun->link_ksettings); + + dev->ethtool_ops = &tun_ethtool_ops; + dev->needs_free_netdev = true; + dev->priv_destructor = tun_free_netdev; + /* We prefer our own queue length */ + dev->tx_queue_len = TUN_READQ_SIZE; +} + +/* Trivial set of netlink ops to allow deleting tun or tap + * device with netlink. + */ +static int tun_validate(struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +{ + NL_SET_ERR_MSG(extack, + "tun/tap creation via rtnetlink is not supported."); + return -EOPNOTSUPP; +} + +static size_t tun_get_size(const struct net_device *dev) +{ + BUILD_BUG_ON(sizeof(u32) != sizeof(uid_t)); + BUILD_BUG_ON(sizeof(u32) != sizeof(gid_t)); + + return nla_total_size(sizeof(uid_t)) + /* OWNER */ + nla_total_size(sizeof(gid_t)) + /* GROUP */ + nla_total_size(sizeof(u8)) + /* TYPE */ + nla_total_size(sizeof(u8)) + /* PI */ + nla_total_size(sizeof(u8)) + /* VNET_HDR */ + nla_total_size(sizeof(u8)) + /* PERSIST */ + nla_total_size(sizeof(u8)) + /* MULTI_QUEUE */ + nla_total_size(sizeof(u32)) + /* NUM_QUEUES */ + nla_total_size(sizeof(u32)) + /* NUM_DISABLED_QUEUES */ + 0; +} + +static int tun_fill_info(struct sk_buff *skb, const struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + if (nla_put_u8(skb, IFLA_TUN_TYPE, tun->flags & TUN_TYPE_MASK)) + goto nla_put_failure; + if (uid_valid(tun->owner) && + nla_put_u32(skb, IFLA_TUN_OWNER, + from_kuid_munged(current_user_ns(), tun->owner))) + goto nla_put_failure; + if (gid_valid(tun->group) && + nla_put_u32(skb, IFLA_TUN_GROUP, + from_kgid_munged(current_user_ns(), tun->group))) + goto nla_put_failure; + if (nla_put_u8(skb, IFLA_TUN_PI, !(tun->flags & IFF_NO_PI))) + goto nla_put_failure; + if (nla_put_u8(skb, IFLA_TUN_VNET_HDR, !!(tun->flags & IFF_VNET_HDR))) + goto nla_put_failure; + if (nla_put_u8(skb, IFLA_TUN_PERSIST, !!(tun->flags & IFF_PERSIST))) + goto nla_put_failure; + if (nla_put_u8(skb, IFLA_TUN_MULTI_QUEUE, + !!(tun->flags & IFF_MULTI_QUEUE))) + goto nla_put_failure; + if (tun->flags & IFF_MULTI_QUEUE) { + if (nla_put_u32(skb, IFLA_TUN_NUM_QUEUES, tun->numqueues)) + goto nla_put_failure; + if (nla_put_u32(skb, IFLA_TUN_NUM_DISABLED_QUEUES, + tun->numdisabled)) + goto nla_put_failure; + } + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + +static struct rtnl_link_ops tun_link_ops __read_mostly = { + .kind = DRV_NAME, + .priv_size = sizeof(struct tun_struct), + .setup = tun_setup, + .validate = tun_validate, + .get_size = tun_get_size, + .fill_info = tun_fill_info, +}; + +static void tun_sock_write_space(struct sock *sk) +{ + struct tun_file *tfile; + wait_queue_head_t *wqueue; + + if (!sock_writeable(sk)) + return; + + if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags)) + return; + + wqueue = sk_sleep(sk); + if (wqueue && waitqueue_active(wqueue)) + wake_up_interruptible_sync_poll(wqueue, EPOLLOUT | + EPOLLWRNORM | EPOLLWRBAND); + + tfile = container_of(sk, struct tun_file, sk); + kill_fasync(&tfile->fasync, SIGIO, POLL_OUT); +} + +static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len) +{ + int ret; + struct tun_file *tfile = container_of(sock, struct tun_file, socket); + struct tun_struct *tun = tun_get(tfile); + + if (!tun) + return -EBADFD; + + ret = tun_get_user(tun, tfile, m->msg_control, &m->msg_iter, + m->msg_flags & MSG_DONTWAIT, + m->msg_flags & MSG_MORE); + tun_put(tun); + return ret; +} + +static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len, + int flags) +{ + struct tun_file *tfile = container_of(sock, struct tun_file, socket); + struct tun_struct *tun = tun_get(tfile); + void *ptr = m->msg_control; + int ret; + + if (!tun) { + ret = -EBADFD; + goto out_free; + } + + if (flags & ~(MSG_DONTWAIT|MSG_TRUNC|MSG_ERRQUEUE)) { + ret = -EINVAL; + goto out_put_tun; + } + if (flags & MSG_ERRQUEUE) { + ret = sock_recv_errqueue(sock->sk, m, total_len, + SOL_PACKET, TUN_TX_TIMESTAMP); + goto out; + } + ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT, ptr); + if (ret > (ssize_t)total_len) { + m->msg_flags |= MSG_TRUNC; + ret = flags & MSG_TRUNC ? ret : total_len; + } +out: + tun_put(tun); + return ret; + +out_put_tun: + tun_put(tun); +out_free: + tun_ptr_free(ptr); + return ret; +} + +static int tun_ptr_peek_len(void *ptr) +{ + if (likely(ptr)) { + if (tun_is_xdp_frame(ptr)) { + struct xdp_frame *xdpf = tun_ptr_to_xdp(ptr); + + return xdpf->len; + } + return __skb_array_len_with_tag(ptr); + } else { + return 0; + } +} + +static int tun_peek_len(struct socket *sock) +{ + struct tun_file *tfile = container_of(sock, struct tun_file, socket); + struct tun_struct *tun; + int ret = 0; + + tun = tun_get(tfile); + if (!tun) + return 0; + + ret = PTR_RING_PEEK_CALL(&tfile->tx_ring, tun_ptr_peek_len); + tun_put(tun); + + return ret; +} + +/* Ops structure to mimic raw sockets with tun */ +static const struct proto_ops tun_socket_ops = { + .peek_len = tun_peek_len, + .sendmsg = tun_sendmsg, + .recvmsg = tun_recvmsg, +}; + +static struct proto tun_proto = { + .name = "tun", + .owner = THIS_MODULE, + .obj_size = sizeof(struct tun_file), +}; + +static int tun_flags(struct tun_struct *tun) +{ + return tun->flags & (TUN_FEATURES | IFF_PERSIST | IFF_TUN | IFF_TAP); +} + +static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return sprintf(buf, "0x%x\n", tun_flags(tun)); +} + +static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return uid_valid(tun->owner)? + sprintf(buf, "%u\n", + from_kuid_munged(current_user_ns(), tun->owner)): + sprintf(buf, "-1\n"); +} + +static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return gid_valid(tun->group) ? + sprintf(buf, "%u\n", + from_kgid_munged(current_user_ns(), tun->group)): + sprintf(buf, "-1\n"); +} + +static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); +static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL); +static DEVICE_ATTR(group, 0444, tun_show_group, NULL); + +static struct attribute *tun_dev_attrs[] = { + &dev_attr_tun_flags.attr, + &dev_attr_owner.attr, + &dev_attr_group.attr, + NULL +}; + +static const struct attribute_group tun_attr_group = { + .attrs = tun_dev_attrs +}; + +static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) +{ + struct tun_struct *tun; + struct tun_file *tfile = file->private_data; + struct net_device *dev; + int err; + + if (tfile->detached) + return -EINVAL; + + if ((ifr->ifr_flags & IFF_NAPI_FRAGS)) { + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!(ifr->ifr_flags & IFF_NAPI) || + (ifr->ifr_flags & TUN_TYPE_MASK) != IFF_TAP) + return -EINVAL; + } + + dev = __dev_get_by_name(net, ifr->ifr_name); + if (dev) { + if (ifr->ifr_flags & IFF_TUN_EXCL) + return -EBUSY; + if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) + tun = netdev_priv(dev); + else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops) + tun = netdev_priv(dev); + else + return -EINVAL; + + if (!!(ifr->ifr_flags & IFF_MULTI_QUEUE) != + !!(tun->flags & IFF_MULTI_QUEUE)) + return -EINVAL; + + if (tun_not_capable(tun)) + return -EPERM; + err = security_tun_dev_open(tun->security); + if (err < 0) + return err; + + err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER, + ifr->ifr_flags & IFF_NAPI, + ifr->ifr_flags & IFF_NAPI_FRAGS); + if (err < 0) + return err; + + if (tun->flags & IFF_MULTI_QUEUE && + (tun->numqueues + tun->numdisabled > 1)) { + /* One or more queue has already been attached, no need + * to initialize the device again. + */ + netdev_state_change(dev); + return 0; + } + + tun->flags = (tun->flags & ~TUN_FEATURES) | + (ifr->ifr_flags & TUN_FEATURES); + + netdev_state_change(dev); + } else { + char *name; + unsigned long flags = 0; + int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ? + MAX_TAP_QUEUES : 1; + + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + return -EPERM; + err = security_tun_dev_create(); + if (err < 0) + return err; + + /* Set dev type */ + if (ifr->ifr_flags & IFF_TUN) { + /* TUN device */ + flags |= IFF_TUN; + name = "tun%d"; + } else if (ifr->ifr_flags & IFF_TAP) { + /* TAP device */ + flags |= IFF_TAP; + name = "tap%d"; + } else + return -EINVAL; + + if (*ifr->ifr_name) + name = ifr->ifr_name; + + dev = alloc_netdev_mqs(sizeof(struct tun_struct), name, + NET_NAME_UNKNOWN, tun_setup, queues, + queues); + + if (!dev) + return -ENOMEM; + err = dev_get_valid_name(net, dev, name); + if (err < 0) + goto err_free_dev; + + dev_net_set(dev, net); + dev->rtnl_link_ops = &tun_link_ops; + dev->ifindex = tfile->ifindex; + dev->sysfs_groups[0] = &tun_attr_group; + + tun = netdev_priv(dev); + tun->dev = dev; + tun->flags = flags; + tun->txflt.count = 0; + tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr); + + tun->align = NET_SKB_PAD; + tun->filter_attached = false; + tun->sndbuf = tfile->socket.sk->sk_sndbuf; + tun->rx_batched = 0; + RCU_INIT_POINTER(tun->steering_prog, NULL); + + tun->pcpu_stats = netdev_alloc_pcpu_stats(struct tun_pcpu_stats); + if (!tun->pcpu_stats) { + err = -ENOMEM; + goto err_free_dev; + } + + spin_lock_init(&tun->lock); + + err = security_tun_dev_alloc_security(&tun->security); + if (err < 0) + goto err_free_stat; + + tun_net_init(dev); + tun_flow_init(tun); + + dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | + TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX; + dev->features = dev->hw_features | NETIF_F_LLTX; + dev->vlan_features = dev->features & + ~(NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX); + + tun->flags = (tun->flags & ~TUN_FEATURES) | + (ifr->ifr_flags & TUN_FEATURES); + + INIT_LIST_HEAD(&tun->disabled); + err = tun_attach(tun, file, false, ifr->ifr_flags & IFF_NAPI, + ifr->ifr_flags & IFF_NAPI_FRAGS); + if (err < 0) + goto err_free_flow; + + err = register_netdevice(tun->dev); + if (err < 0) + goto err_detach; + } + + netif_carrier_on(tun->dev); + + tun_debug(KERN_INFO, tun, "tun_set_iff\n"); + + /* Make sure persistent devices do not get stuck in + * xoff state. + */ + if (netif_running(tun->dev)) + netif_tx_wake_all_queues(tun->dev); + + strcpy(ifr->ifr_name, tun->dev->name); + return 0; + +err_detach: + tun_detach_all(dev); + /* register_netdevice() already called tun_free_netdev() */ + goto err_free_dev; + +err_free_flow: + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); +err_free_stat: + free_percpu(tun->pcpu_stats); +err_free_dev: + free_netdev(dev); + return err; +} + +static void tun_get_iff(struct net *net, struct tun_struct *tun, + struct ifreq *ifr) +{ + tun_debug(KERN_INFO, tun, "tun_get_iff\n"); + + strcpy(ifr->ifr_name, tun->dev->name); + + ifr->ifr_flags = tun_flags(tun); + +} + +/* This is like a cut-down ethtool ops, except done via tun fd so no + * privs required. */ +static int set_offload(struct tun_struct *tun, unsigned long arg) +{ + netdev_features_t features = 0; + + if (arg & TUN_F_CSUM) { + features |= NETIF_F_HW_CSUM; + arg &= ~TUN_F_CSUM; + + if (arg & (TUN_F_TSO4|TUN_F_TSO6)) { + if (arg & TUN_F_TSO_ECN) { + features |= NETIF_F_TSO_ECN; + arg &= ~TUN_F_TSO_ECN; + } + if (arg & TUN_F_TSO4) + features |= NETIF_F_TSO; + if (arg & TUN_F_TSO6) + features |= NETIF_F_TSO6; + arg &= ~(TUN_F_TSO4|TUN_F_TSO6); + } + + arg &= ~TUN_F_UFO; + } + + /* This gives the user a way to test for new features in future by + * trying to set them. */ + if (arg) + return -EINVAL; + + tun->set_features = features; + tun->dev->wanted_features &= ~TUN_USER_FEATURES; + tun->dev->wanted_features |= features; + netdev_update_features(tun->dev); + + return 0; +} + +static void tun_detach_filter(struct tun_struct *tun, int n) +{ + int i; + struct tun_file *tfile; + + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + lock_sock(tfile->socket.sk); + sk_detach_filter(tfile->socket.sk); + release_sock(tfile->socket.sk); + } + + tun->filter_attached = false; +} + +static int tun_attach_filter(struct tun_struct *tun) +{ + int i, ret = 0; + struct tun_file *tfile; + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + lock_sock(tfile->socket.sk); + ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); + release_sock(tfile->socket.sk); + if (ret) { + tun_detach_filter(tun, i); + return ret; + } + } + + tun->filter_attached = true; + return ret; +} + +static void tun_set_sndbuf(struct tun_struct *tun) +{ + struct tun_file *tfile; + int i; + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + tfile->socket.sk->sk_sndbuf = tun->sndbuf; + } +} + +static int tun_set_queue(struct file *file, struct ifreq *ifr) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun; + int ret = 0; + + rtnl_lock(); + + if (ifr->ifr_flags & IFF_ATTACH_QUEUE) { + tun = tfile->detached; + if (!tun) { + ret = -EINVAL; + goto unlock; + } + ret = security_tun_dev_attach_queue(tun->security); + if (ret < 0) + goto unlock; + ret = tun_attach(tun, file, false, tun->flags & IFF_NAPI, + tun->flags & IFF_NAPI_FRAGS); + } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { + tun = rtnl_dereference(tfile->tun); + if (!tun || !(tun->flags & IFF_MULTI_QUEUE) || tfile->detached) + ret = -EINVAL; + else + __tun_detach(tfile, false); + } else + ret = -EINVAL; + + if (ret >= 0) + netdev_state_change(tun->dev); + +unlock: + rtnl_unlock(); + return ret; +} + +static int tun_set_ebpf(struct tun_struct *tun, struct tun_prog **prog_p, + void __user *data) +{ + struct bpf_prog *prog; + int fd; + + if (copy_from_user(&fd, data, sizeof(fd))) + return -EFAULT; + + if (fd == -1) { + prog = NULL; + } else { + prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_SOCKET_FILTER); + if (IS_ERR(prog)) + return PTR_ERR(prog); + } + + return __tun_set_ebpf(tun, prog_p, prog); +} + +static long __tun_chr_ioctl(struct file *file, unsigned int cmd, + unsigned long arg, int ifreq_len) +{ + struct tun_file *tfile = file->private_data; + struct net *net = sock_net(&tfile->sk); + struct tun_struct *tun; + void __user* argp = (void __user*)arg; + struct ifreq ifr; + kuid_t owner; + kgid_t group; + int sndbuf; + int vnet_hdr_sz; + unsigned int ifindex; + int le; + int ret; + bool do_notify = false; + + if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || + (_IOC_TYPE(cmd) == SOCK_IOC_TYPE && cmd != SIOCGSKNS)) { + if (copy_from_user(&ifr, argp, ifreq_len)) + return -EFAULT; + } else { + memset(&ifr, 0, sizeof(ifr)); + } + if (cmd == TUNGETFEATURES) { + /* Currently this just means: "what IFF flags are valid?". + * This is needed because we never checked for invalid flags on + * TUNSETIFF. + */ + return put_user(IFF_TUN | IFF_TAP | TUN_FEATURES, + (unsigned int __user*)argp); + } else if (cmd == TUNSETQUEUE) { + return tun_set_queue(file, &ifr); + } else if (cmd == SIOCGSKNS) { + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + return -EPERM; + return open_related_ns(&net->ns, get_net_ns); + } + + ret = 0; + rtnl_lock(); + + tun = tun_get(tfile); + if (cmd == TUNSETIFF) { + ret = -EEXIST; + if (tun) + goto unlock; + + ifr.ifr_name[IFNAMSIZ-1] = '\0'; + + ret = tun_set_iff(net, file, &ifr); + + if (ret) + goto unlock; + + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + goto unlock; + } + if (cmd == TUNSETIFINDEX) { + ret = -EPERM; + if (tun) + goto unlock; + + ret = -EFAULT; + if (copy_from_user(&ifindex, argp, sizeof(ifindex))) + goto unlock; + + ret = 0; + tfile->ifindex = ifindex; + goto unlock; + } + + ret = -EBADFD; + if (!tun) + goto unlock; + + tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %u\n", cmd); + + ret = 0; + switch (cmd) { + case TUNGETIFF: + tun_get_iff(current->nsproxy->net_ns, tun, &ifr); + + if (tfile->detached) + ifr.ifr_flags |= IFF_DETACH_QUEUE; + if (!tfile->socket.sk->sk_filter) + ifr.ifr_flags |= IFF_NOFILTER; + + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + break; + + case TUNSETNOCSUM: + /* Disable/Enable checksum */ + + /* [unimplemented] */ + tun_debug(KERN_INFO, tun, "ignored: set checksum %s\n", + arg ? "disabled" : "enabled"); + break; + + case TUNSETPERSIST: + /* Disable/Enable persist mode. Keep an extra reference to the + * module to prevent the module being unprobed. + */ + if (arg && !(tun->flags & IFF_PERSIST)) { + tun->flags |= IFF_PERSIST; + __module_get(THIS_MODULE); + do_notify = true; + } + if (!arg && (tun->flags & IFF_PERSIST)) { + tun->flags &= ~IFF_PERSIST; + module_put(THIS_MODULE); + do_notify = true; + } + + tun_debug(KERN_INFO, tun, "persist %s\n", + arg ? "enabled" : "disabled"); + break; + + case TUNSETOWNER: + /* Set owner of the device */ + owner = make_kuid(current_user_ns(), arg); + if (!uid_valid(owner)) { + ret = -EINVAL; + break; + } + tun->owner = owner; + do_notify = true; + tun_debug(KERN_INFO, tun, "owner set to %u\n", + from_kuid(&init_user_ns, tun->owner)); + break; + + case TUNSETGROUP: + /* Set group of the device */ + group = make_kgid(current_user_ns(), arg); + if (!gid_valid(group)) { + ret = -EINVAL; + break; + } + tun->group = group; + do_notify = true; + tun_debug(KERN_INFO, tun, "group set to %u\n", + from_kgid(&init_user_ns, tun->group)); + break; + + case TUNSETLINK: + /* Only allow setting the type when the interface is down */ + if (tun->dev->flags & IFF_UP) { + tun_debug(KERN_INFO, tun, + "Linktype set failed because interface is up\n"); + ret = -EBUSY; + } else { + tun->dev->type = (int) arg; + tun_debug(KERN_INFO, tun, "linktype set to %d\n", + tun->dev->type); + ret = 0; + } + break; + +#ifdef TUN_DEBUG + case TUNSETDEBUG: + tun->debug = arg; + break; +#endif + case TUNSETOFFLOAD: + ret = set_offload(tun, arg); + break; + + case TUNSETTXFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != IFF_TAP) + break; + ret = update_filter(&tun->txflt, (void __user *)arg); + break; + + case SIOCGIFHWADDR: + /* Get hw address */ + memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); + ifr.ifr_hwaddr.sa_family = tun->dev->type; + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + break; + + case SIOCSIFHWADDR: + /* Set hw address */ + tun_debug(KERN_DEBUG, tun, "set hw address: %pM\n", + ifr.ifr_hwaddr.sa_data); + + ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); + break; + + case TUNGETSNDBUF: + sndbuf = tfile->socket.sk->sk_sndbuf; + if (copy_to_user(argp, &sndbuf, sizeof(sndbuf))) + ret = -EFAULT; + break; + + case TUNSETSNDBUF: + if (copy_from_user(&sndbuf, argp, sizeof(sndbuf))) { + ret = -EFAULT; + break; + } + if (sndbuf <= 0) { + ret = -EINVAL; + break; + } + + tun->sndbuf = sndbuf; + tun_set_sndbuf(tun); + break; + + case TUNGETVNETHDRSZ: + vnet_hdr_sz = tun->vnet_hdr_sz; + if (copy_to_user(argp, &vnet_hdr_sz, sizeof(vnet_hdr_sz))) + ret = -EFAULT; + break; + + case TUNSETVNETHDRSZ: + if (copy_from_user(&vnet_hdr_sz, argp, sizeof(vnet_hdr_sz))) { + ret = -EFAULT; + break; + } + if (vnet_hdr_sz < (int)sizeof(struct virtio_net_hdr)) { + ret = -EINVAL; + break; + } + + tun->vnet_hdr_sz = vnet_hdr_sz; + break; + + case TUNGETVNETLE: + le = !!(tun->flags & TUN_VNET_LE); + if (put_user(le, (int __user *)argp)) + ret = -EFAULT; + break; + + case TUNSETVNETLE: + if (get_user(le, (int __user *)argp)) { + ret = -EFAULT; + break; + } + if (le) + tun->flags |= TUN_VNET_LE; + else + tun->flags &= ~TUN_VNET_LE; + break; + + case TUNGETVNETBE: + ret = tun_get_vnet_be(tun, argp); + break; + + case TUNSETVNETBE: + ret = tun_set_vnet_be(tun, argp); + break; + + case TUNATTACHFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != IFF_TAP) + break; + ret = -EFAULT; + if (copy_from_user(&tun->fprog, argp, sizeof(tun->fprog))) + break; + + ret = tun_attach_filter(tun); + break; + + case TUNDETACHFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != IFF_TAP) + break; + ret = 0; + tun_detach_filter(tun, tun->numqueues); + break; + + case TUNGETFILTER: + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != IFF_TAP) + break; + ret = -EFAULT; + if (copy_to_user(argp, &tun->fprog, sizeof(tun->fprog))) + break; + ret = 0; + break; + + case TUNSETSTEERINGEBPF: + ret = tun_set_ebpf(tun, &tun->steering_prog, argp); + break; + + case TUNSETFILTEREBPF: + ret = tun_set_ebpf(tun, &tun->filter_prog, argp); + break; + + default: + ret = -EINVAL; + break; + } + + if (do_notify) + netdev_state_change(tun->dev); + +unlock: + rtnl_unlock(); + if (tun) + tun_put(tun); + return ret; +} + +static long tun_chr_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return __tun_chr_ioctl(file, cmd, arg, sizeof (struct ifreq)); +} + +#ifdef CONFIG_COMPAT +static long tun_chr_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case TUNSETIFF: + case TUNGETIFF: + case TUNSETTXFILTER: + case TUNGETSNDBUF: + case TUNSETSNDBUF: + case SIOCGIFHWADDR: + case SIOCSIFHWADDR: + arg = (unsigned long)compat_ptr(arg); + break; + default: + arg = (compat_ulong_t)arg; + break; + } + + /* + * compat_ifreq is shorter than ifreq, so we must not access beyond + * the end of that structure. All fields that are used in this + * driver are compatible though, we don't need to convert the + * contents. + */ + return __tun_chr_ioctl(file, cmd, arg, sizeof(struct compat_ifreq)); +} +#endif /* CONFIG_COMPAT */ + +static int tun_chr_fasync(int fd, struct file *file, int on) +{ + struct tun_file *tfile = file->private_data; + int ret; + + if ((ret = fasync_helper(fd, file, on, &tfile->fasync)) < 0) + goto out; + + if (on) { + __f_setown(file, task_pid(current), PIDTYPE_TGID, 0); + tfile->flags |= TUN_FASYNC; + } else + tfile->flags &= ~TUN_FASYNC; + ret = 0; +out: + return ret; +} + +static int tun_chr_open(struct inode *inode, struct file * file) +{ + struct net *net = current->nsproxy->net_ns; + struct tun_file *tfile; + + DBG1(KERN_INFO, "tunX: tun_chr_open\n"); + + tfile = (struct tun_file *)sk_alloc(net, AF_UNSPEC, GFP_KERNEL, + &tun_proto, 0); + if (!tfile) + return -ENOMEM; + if (ptr_ring_init(&tfile->tx_ring, 0, GFP_KERNEL)) { + sk_free(&tfile->sk); + return -ENOMEM; + } + + mutex_init(&tfile->napi_mutex); + RCU_INIT_POINTER(tfile->tun, NULL); + tfile->flags = 0; + tfile->ifindex = 0; + + init_waitqueue_head(&tfile->wq.wait); + RCU_INIT_POINTER(tfile->socket.wq, &tfile->wq); + + tfile->socket.file = file; + tfile->socket.ops = &tun_socket_ops; + + sock_init_data(&tfile->socket, &tfile->sk); + + tfile->sk.sk_write_space = tun_sock_write_space; + tfile->sk.sk_sndbuf = INT_MAX; + + file->private_data = tfile; + INIT_LIST_HEAD(&tfile->next); + + sock_set_flag(&tfile->sk, SOCK_ZEROCOPY); + + return 0; +} + +static int tun_chr_close(struct inode *inode, struct file *file) +{ + struct tun_file *tfile = file->private_data; + + tun_detach(tfile, true); + + return 0; +} + +#ifdef CONFIG_PROC_FS +static void tun_chr_show_fdinfo(struct seq_file *m, struct file *file) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun; + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + + rtnl_lock(); + tun = tun_get(tfile); + if (tun) + tun_get_iff(current->nsproxy->net_ns, tun, &ifr); + rtnl_unlock(); + + if (tun) + tun_put(tun); + + seq_printf(m, "iff:\t%s\n", ifr.ifr_name); +} +#endif + +static const struct file_operations tun_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read_iter = tun_chr_read_iter, + .write_iter = tun_chr_write_iter, + .poll = tun_chr_poll, + .unlocked_ioctl = tun_chr_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tun_chr_compat_ioctl, +#endif + .open = tun_chr_open, + .release = tun_chr_close, + .fasync = tun_chr_fasync, +#ifdef CONFIG_PROC_FS + .show_fdinfo = tun_chr_show_fdinfo, +#endif +}; + +static struct miscdevice tun_miscdev = { + .minor = BF_TUN_MINOR, + .name = "bf_tun", + .nodename = "net/bf_tun", + .fops = &tun_fops, +}; + +/* ethtool interface */ + +static void tun_default_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) +{ + ethtool_link_ksettings_zero_link_mode(cmd, supported); + ethtool_link_ksettings_zero_link_mode(cmd, advertising); + cmd->base.speed = SPEED_10; + cmd->base.duplex = DUPLEX_FULL; + cmd->base.port = PORT_TP; + cmd->base.phy_address = 0; + cmd->base.autoneg = AUTONEG_DISABLE; +} + +static int tun_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) +{ + struct tun_struct *tun = netdev_priv(dev); + + memcpy(cmd, &tun->link_ksettings, sizeof(*cmd)); + return 0; +} + +static int tun_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) +{ + struct tun_struct *tun = netdev_priv(dev); + + memcpy(&tun->link_ksettings, cmd, sizeof(*cmd)); + return 0; +} + +static void tun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct tun_struct *tun = netdev_priv(dev); + + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + + switch (tun->flags & TUN_TYPE_MASK) { + case IFF_TUN: + strlcpy(info->bus_info, "tun", sizeof(info->bus_info)); + break; + case IFF_TAP: + strlcpy(info->bus_info, "tap", sizeof(info->bus_info)); + break; + } +} + +static u32 tun_get_msglevel(struct net_device *dev) +{ +#ifdef TUN_DEBUG + struct tun_struct *tun = netdev_priv(dev); + return tun->debug; +#else + return -EOPNOTSUPP; +#endif +} + +static void tun_set_msglevel(struct net_device *dev, u32 value) +{ +#ifdef TUN_DEBUG + struct tun_struct *tun = netdev_priv(dev); + tun->debug = value; +#endif +} + +static int tun_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *ec) +{ + struct tun_struct *tun = netdev_priv(dev); + + ec->rx_max_coalesced_frames = tun->rx_batched; + + return 0; +} + +static int tun_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *ec) +{ + struct tun_struct *tun = netdev_priv(dev); + + if (ec->rx_max_coalesced_frames > NAPI_POLL_WEIGHT) + tun->rx_batched = NAPI_POLL_WEIGHT; + else + tun->rx_batched = ec->rx_max_coalesced_frames; + + return 0; +} + +static const struct ethtool_ops tun_ethtool_ops = { + .get_drvinfo = tun_get_drvinfo, + .get_msglevel = tun_get_msglevel, + .set_msglevel = tun_set_msglevel, + .get_link = ethtool_op_get_link, + .get_ts_info = ethtool_op_get_ts_info, + .get_coalesce = tun_get_coalesce, + .set_coalesce = tun_set_coalesce, + .get_link_ksettings = tun_get_link_ksettings, + .set_link_ksettings = tun_set_link_ksettings, +}; + +static int tun_queue_resize(struct tun_struct *tun) +{ + struct net_device *dev = tun->dev; + struct tun_file *tfile; + struct ptr_ring **rings; + int n = tun->numqueues + tun->numdisabled; + int ret, i; + + rings = kmalloc_array(n, sizeof(*rings), GFP_KERNEL); + if (!rings) + return -ENOMEM; + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + rings[i] = &tfile->tx_ring; + } + list_for_each_entry(tfile, &tun->disabled, next) + rings[i++] = &tfile->tx_ring; + + ret = ptr_ring_resize_multiple(rings, n, + dev->tx_queue_len, GFP_KERNEL, + tun_ptr_free); + + kfree(rings); + return ret; +} + +static int tun_device_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct tun_struct *tun = netdev_priv(dev); + int i; + + if (dev->rtnl_link_ops != &tun_link_ops) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_CHANGE_TX_QUEUE_LEN: + if (tun_queue_resize(tun)) + return NOTIFY_BAD; + break; + case NETDEV_UP: + for (i = 0; i < tun->numqueues; i++) { + struct tun_file *tfile; + + tfile = rtnl_dereference(tun->tfiles[i]); + tfile->socket.sk->sk_write_space(tfile->socket.sk); + } + break; + default: + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block tun_notifier_block __read_mostly = { + .notifier_call = tun_device_event, +}; + +static int __init tun_init(void) +{ + int ret = 0; + + pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); + + ret = rtnl_link_register(&tun_link_ops); + if (ret) { + pr_err("Can't register link_ops\n"); + goto err_linkops; + } + + ret = misc_register(&tun_miscdev); + if (ret) { + pr_err("Can't register misc device %d\n", BF_TUN_MINOR); + goto err_misc; + } + + ret = register_netdevice_notifier(&tun_notifier_block); + if (ret) { + pr_err("Can't register netdevice notifier\n"); + goto err_notifier; + } + + return 0; + +err_notifier: + misc_deregister(&tun_miscdev); +err_misc: + rtnl_link_unregister(&tun_link_ops); +err_linkops: + return ret; +} + +static void tun_cleanup(void) +{ + misc_deregister(&tun_miscdev); + rtnl_link_unregister(&tun_link_ops); + unregister_netdevice_notifier(&tun_notifier_block); +} + +/* Get an underlying socket object from tun file. Returns error unless file is + * attached to a device. The returned object works like a packet socket, it + * can be used for sock_sendmsg/sock_recvmsg. The caller is responsible for + * holding a reference to the file for as long as the socket is in use. */ +struct socket *tun_get_socket(struct file *file) +{ + struct tun_file *tfile; + if (file->f_op != &tun_fops) + return ERR_PTR(-EINVAL); + tfile = file->private_data; + if (!tfile) + return ERR_PTR(-EBADFD); + return &tfile->socket; +} +EXPORT_SYMBOL_GPL(tun_get_socket); + +struct ptr_ring *tun_get_tx_ring(struct file *file) +{ + struct tun_file *tfile; + + if (file->f_op != &tun_fops) + return ERR_PTR(-EINVAL); + tfile = file->private_data; + if (!tfile) + return ERR_PTR(-EBADFD); + return &tfile->tx_ring; +} +EXPORT_SYMBOL_GPL(tun_get_tx_ring); + +module_init(tun_init); +module_exit(tun_cleanup); +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_COPYRIGHT); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(BF_TUN_MINOR); +MODULE_ALIAS("devname:net/bf_tun"); diff --git a/platform/barefoot/bfn-platform-ingrasys.mk b/platform/barefoot/bfn-platform-ingrasys.mk new file mode 100644 index 000000000000..20dc5f866f38 --- /dev/null +++ b/platform/barefoot/bfn-platform-ingrasys.mk @@ -0,0 +1,5 @@ +BFN_INGRASYS_PLATFORM = bfnplatform-ingrasys_8.2.0_amd64.deb +$(BFN_INGRASYS_PLATFORM)_URL = "https://github.com/Ingrasys-sonic/packages/raw/master/lib/bfnplatform-ingrasys_8.4.0_8.5.0_amd64.deb" + +SONIC_ONLINE_DEBS += $(BFN_INGRASYS_PLATFORM) # $(BFN_SAI_DEV) +$(BFN_SAI_DEV)_DEPENDS += $(BFN_INGRASYS_PLATFORM) diff --git a/platform/barefoot/bfn-platform-wnc.mk b/platform/barefoot/bfn-platform-wnc.mk new file mode 100644 index 000000000000..e2f45d35b2b8 --- /dev/null +++ b/platform/barefoot/bfn-platform-wnc.mk @@ -0,0 +1,5 @@ +WNC_OSW1800_PLATFORM = bfnplatformwnc_1.0.0_amd64.deb +$(WNC_OSW1800_PLATFORM)_URL = "https://github.com/YaoTien/download/raw/master/sonic/sde/7_0_0_18/bfnplatformwnc_1.0.0_amd64.deb" + +SONIC_ONLINE_DEBS += $(WNC_OSW1800_PLATFORM) # $(BFN_SAI_DEV) +$(BFN_SAI_DEV)_DEPENDS += $(WNC_OSW1800_PLATFORM) diff --git a/platform/barefoot/bfn-platform.mk b/platform/barefoot/bfn-platform.mk new file mode 100644 index 000000000000..5abcd3fe4655 --- /dev/null +++ b/platform/barefoot/bfn-platform.mk @@ -0,0 +1,5 @@ +BFN_PLATFORM = bfnplatform_20210219_deb10.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 new file mode 100644 index 000000000000..54285aa32cd9 --- /dev/null +++ b/platform/barefoot/bfn-sai.mk @@ -0,0 +1,9 @@ +BFN_SAI = bfnsdk_20210219_deb10.deb +$(BFN_SAI)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/dev/$(BFN_SAI)" + +$(BFN_SAI)_DEPENDS += $(LIBNL_GENL3_DEV) +$(eval $(call add_conflict_package,$(BFN_SAI),$(LIBSAIVS_DEV))) +$(BFN_SAI)_RDEPENDS += $(LIBNL_GENL3) + +SONIC_ONLINE_DEBS += $(BFN_SAI) +$(BFN_SAI_DEV)_DEPENDS += $(BFN_SAI) diff --git a/platform/barefoot/docker-saiserver-bfn/Dockerfile b/platform/barefoot/docker-saiserver-bfn/Dockerfile new file mode 100755 index 000000000000..6fa5b1818a18 --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/Dockerfile @@ -0,0 +1,37 @@ +FROM docker-base + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY ["deps/applibs_*.deb", "/deps/applibs-dev_*.deb", "/deps/sx-complib_*.deb", "/deps/sxd-libs_*.deb", "/deps/sx-scew_*.deb", "/deps/sx-examples_*.deb", "/deps/sx-gen-utils_*.deb", "/deps/python-sdk-api_*.deb", "/deps/iproute2_*.deb", "/deps/mlnx-sai_*.deb", "/deps/libthrift-0.9.3_*.deb", "/deps/libnl-3-200_*.deb", "/deps/libnl-genl-3-200_*.deb", "/deps/libnl-route-3-200_*.deb", "/deps/"] + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; \ + dpkg_apt /deps/applibs_*.deb \ + && dpkg_apt /deps/applibs-dev_*.deb \ + && dpkg_apt /deps/sx-complib_*.deb \ + && dpkg_apt /deps/sxd-libs_*.deb \ + && dpkg_apt /deps/sx-scew_*.deb \ + && dpkg_apt /deps/sx-examples_*.deb \ + && dpkg_apt /deps/sx-gen-utils_*.deb \ + && dpkg_apt /deps/python-sdk-api_*.deb \ + && dpkg_apt /deps/iproute2_*.deb \ + && dpkg_apt /deps/mlnx-sai_*.deb \ + && dpkg_apt /deps/libthrift-0.9.3_*.deb \ + && dpkg_apt /deps/libnl-3-200_*.deb \ + && dpkg_apt /deps/libnl-genl-3-200_*.deb \ + && dpkg_apt /deps/libnl-route-3-200_*.deb + +COPY ["deps/saiserver", "start.sh", "/usr/bin/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +COPY ["profile.ini", "portmap.ini", "/etc/sai/"] + + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /deps + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/barefoot/docker-saiserver-bfn/portmap.ini b/platform/barefoot/docker-saiserver-bfn/portmap.ini new file mode 100644 index 000000000000..4d3be08ce5f8 --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/portmap.ini @@ -0,0 +1,33 @@ +# alias lanes +Ethernet1 0,1,2,3 +Ethernet2 4,5,6,7 +Ethernet3 8,9,10,11 +Ethernet4 12,13,14,15 +Ethernet5 16,17,18,19 +Ethernet6 20,21,22,23 +Ethernet7 24,25,26,27 +Ethernet8 28,29,30,31 +Ethernet9 32,33,34,35 +Ethernet10 36,37,38,39 +Ethernet11 40,41,42,43 +Ethernet12 44,45,46,47 +Ethernet13 48,49,50,51 +Ethernet14 52,53,54,55 +Ethernet15 56,57,58,59 +Ethernet16 60,61,62,63 +Ethernet17 64,65,66,67 +Ethernet18 68,69,70,71 +Ethernet19 72,73,74,75 +Ethernet20 76,77,78,79 +Ethernet21 80,81,82,83 +Ethernet22 84,85,86,87 +Ethernet23 88,89,90,91 +Ethernet24 92,93,94,95 +Ethernet25 96,97,98,99 +Ethernet26 100,101,102,103 +Ethernet27 104,105,106,107 +Ethernet28 108,109,110,111 +Ethernet29 112,113,114,115 +Ethernet30 116,117,118,119 +Ethernet31 120,121,122,123 +Ethernet32 124,125,126,127 \ No newline at end of file diff --git a/platform/barefoot/docker-saiserver-bfn/profile.ini b/platform/barefoot/docker-saiserver-bfn/profile.ini new file mode 100644 index 000000000000..b20b2c6f0e06 --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/profile.ini @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sai_tofino.xml diff --git a/platform/barefoot/docker-saiserver-bfn/sai_tofino.xml b/platform/barefoot/docker-saiserver-bfn/sai_tofino.xml new file mode 100644 index 000000000000..139597f9cb07 --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/sai_tofino.xml @@ -0,0 +1,2 @@ + + diff --git a/platform/barefoot/docker-saiserver-bfn/start.sh b/platform/barefoot/docker-saiserver-bfn/start.sh new file mode 100755 index 000000000000..16457d13e03a --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/start.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start saiserver + diff --git a/platform/barefoot/docker-saiserver-bfn/supervisord.conf b/platform/barefoot/docker-saiserver-bfn/supervisord.conf new file mode 100644 index 000000000000..e09ac3cbb449 --- /dev/null +++ b/platform/barefoot/docker-saiserver-bfn/supervisord.conf @@ -0,0 +1,29 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[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=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:saiserver] +command=/usr/bin/saiserver -p /etc/sai/profile.ini -f /etc/sai/portmap.ini +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + diff --git a/platform/barefoot/docker-syncd-bfn-rpc.mk b/platform/barefoot/docker-syncd-bfn-rpc.mk new file mode 100644 index 000000000000..aee465151d84 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn-rpc.mk @@ -0,0 +1,23 @@ +# docker image for syncd with rpc + +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) $(PTF) +$(DOCKER_SYNCD_BFN_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_BFN_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_BFN_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_BFN_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_BFN_RPC) +endif + +$(DOCKER_SYNCD_BFN_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_BFN_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_BFN_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_BFN_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_BFN_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 b/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..5e5f5f166e5e --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 @@ -0,0 +1,57 @@ +FROM docker-syncd-bfn + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_bfn_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get purge -y syncd + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + python-setuptools \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_bfn_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip2 install cffi==1.7.0 \ + && pip2 install --upgrade cffi==1.7.0 \ + && pip2 install wheel \ + && pip2 install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/barefoot/docker-syncd-bfn-rpc/ptf_nn_agent.conf b/platform/barefoot/docker-syncd-bfn-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/barefoot/docker-syncd-bfn.mk b/platform/barefoot/docker-syncd-bfn.mk new file mode 100644 index 000000000000..3a5c693e2fa8 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn.mk @@ -0,0 +1,14 @@ +# docker image for syncd + +DOCKER_SYNCD_PLATFORM_CODE = bfn +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_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/Dockerfile.j2 b/platform/barefoot/docker-syncd-bfn/Dockerfile.j2 new file mode 100755 index 000000000000..b9dbad963665 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn/Dockerfile.j2 @@ -0,0 +1,39 @@ +FROM docker-config-engine-buster + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_bfn_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get install -y \ + libxml2 \ + libpcap-dev \ + libusb-1.0-0-dev \ + libcurl4 \ + libcurl4-gnutls-dev \ + libunwind8-dev \ + libpython3.4 \ + libc-ares2 \ + libgoogle-perftools4 + +RUN dpkg -i \ +{% for deb in docker_syncd_bfn_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] 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..61e290e3189e --- /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 program syncd|syncd with path "/usr/bin/process_checker syncd /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/platform/barefoot/docker-syncd-bfn/critical_processes b/platform/barefoot/docker-syncd-bfn/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/platform/barefoot/docker-syncd-bfn/start.sh b/platform/barefoot/docker-syncd-bfn/start.sh new file mode 100755 index 000000000000..0fcdef4a961e --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn/start.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +. /opt/bfn/install/bin/dma_setup.sh +# . /opt/bfn/install/bin/bf_kdrv_mod_load /opt/bfn/install diff --git a/platform/barefoot/docker-syncd-bfn/supervisord.conf b/platform/barefoot/docker-syncd-bfn/supervisord.conf new file mode 100644 index 000000000000..c83484e5e93b --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn/supervisord.conf @@ -0,0 +1,50 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:syncd] +environment=LD_LIBRARY_PATH="/opt/bfn/install/lib" +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited diff --git a/platform/barefoot/libsaithrift-dev.mk b/platform/barefoot/libsaithrift-dev.mk new file mode 100644 index 000000000000..0289a41b2910 --- /dev/null +++ b/platform/barefoot/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_amd64.deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(BFN_SAI) $(BFN_SAI_DEV) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(BFN_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_amd64.deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_amd64.deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(BRCM_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_amd64.deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/barefoot/one-aboot.mk b/platform/barefoot/one-aboot.mk new file mode 100644 index 000000000000..a2cdf2ac0391 --- /dev/null +++ b/platform/barefoot/one-aboot.mk @@ -0,0 +1,20 @@ +# sonic one aboot installer + +SONIC_ONE_ABOOT_IMAGE = sonic-aboot-barefoot.swi +$(SONIC_ONE_ABOOT_IMAGE)_MACHINE = barefoot +$(SONIC_ONE_ABOOT_IMAGE)_IMAGE_TYPE = aboot +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(BFN_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_ABOOT_IMAGE)_LAZY_INSTALLS += $(BFN_PLATFORM_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_LAZY_INSTALLS += $(BFN_MONTARA_PLATFORM_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(ARISTA_PLATFORM_MODULE_DRIVERS) \ + $(ARISTA_PLATFORM_MODULE_PYTHON2) \ + $(ARISTA_PLATFORM_MODULE_PYTHON3) \ + $(ARISTA_PLATFORM_MODULE) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_ABOOT_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_ABOOT_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_ABOOT_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_ABOOT_IMAGE) diff --git a/platform/barefoot/one-image.mk b/platform/barefoot/one-image.mk new file mode 100644 index 000000000000..8ed212c6f7a8 --- /dev/null +++ b/platform/barefoot/one-image.mk @@ -0,0 +1,21 @@ +# sonic one image installer + +SONIC_ONE_IMAGE = sonic-barefoot.bin +$(SONIC_ONE_IMAGE)_MACHINE = barefoot +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(BFN_MODULE) +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_MONTARA_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_NEWPORT_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_NEWPORT_BF_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(WNC_OSW1800_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9180_32X_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9280_64X_PLATFORM_MODULE) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/barefoot/platform-modules-arista.mk b/platform/barefoot/platform-modules-arista.mk new file mode 100644 index 000000000000..298bc93d9250 --- /dev/null +++ b/platform/barefoot/platform-modules-arista.mk @@ -0,0 +1,23 @@ +# Arista Platform modules + +ARISTA_PLATFORM_MODULE_VERSION = 1.0 + +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_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))) + +ARISTA_PLATFORM_MODULE_PYTHON3 = python3-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_all.deb +$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_PYTHON3))) + +ARISTA_PLATFORM_MODULE_DRIVERS = drivers-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_amd64.deb +$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_DRIVERS))) + +export ARISTA_PLATFORM_MODULE ARISTA_PLATFORM_MODULE_PYTHON2 ARISTA_PLATFORM_MODULE_PYTHON3 ARISTA_PLATFORM_MODULE_DRIVERS + +export ARISTA_SCD_DRIVER_CONFIG=m diff --git a/platform/barefoot/platform-modules-bfn-montara.mk b/platform/barefoot/platform-modules-bfn-montara.mk new file mode 100644 index 000000000000..375f100475cf --- /dev/null +++ b/platform/barefoot/platform-modules-bfn-montara.mk @@ -0,0 +1,11 @@ +# BFN Platform modules + +BFN_MONTARA_PLATFORM_MODULE_VERSION = 1.1 + +export BFN_MONTARA_PLATFORM_MODULE_VERSION + +BFN_MONTARA_PLATFORM_MODULE = sonic-platform-modules-bfn-montara_$(BFN_MONTARA_PLATFORM_MODULE_VERSION)_amd64.deb +$(BFN_MONTARA_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-bfn-montara +$(BFN_MONTARA_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(BFN_MONTARA_PLATFORM_MODULE)_PLATFORM = x86_64-accton_wedge100bf_32x-r0 +SONIC_DPKG_DEBS += $(BFN_MONTARA_PLATFORM_MODULE) diff --git a/platform/barefoot/platform-modules-bfn-newport.mk b/platform/barefoot/platform-modules-bfn-newport.mk new file mode 100644 index 000000000000..151d8d0e58c2 --- /dev/null +++ b/platform/barefoot/platform-modules-bfn-newport.mk @@ -0,0 +1,15 @@ +# BFN Platform modules + +BFN_NEWPORT_PLATFORM_MODULE_VERSION = 1.0 + +export BFN_NEWPORT_PLATFORM_MODULE_VERSION + +BFN_NEWPORT_PLATFORM_MODULE = sonic-platform-modules-bfn-newport-as9516_$(BFN_NEWPORT_PLATFORM_MODULE_VERSION)_amd64.deb +$(BFN_NEWPORT_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-bfn-newport +$(BFN_NEWPORT_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(BFN_NEWPORT_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9516_32d-r0 +SONIC_DPKG_DEBS += $(BFN_NEWPORT_PLATFORM_MODULE) + +BFN_NEWPORT_BF_PLATFORM_MODULE = sonic-platform-modules-bfn-newport-as9516bf_$(BFN_NEWPORT_PLATFORM_MODULE_VERSION)_amd64.deb +$(BFN_NEWPORT_BF_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9516bf_32d-r0 +$(eval $(call add_extra_package,$(BFN_NEWPORT_PLATFORM_MODULE),$(BFN_NEWPORT_BF_PLATFORM_MODULE))) diff --git a/platform/barefoot/platform-modules-bfn.mk b/platform/barefoot/platform-modules-bfn.mk new file mode 100644 index 000000000000..28b6ec112788 --- /dev/null +++ b/platform/barefoot/platform-modules-bfn.mk @@ -0,0 +1,12 @@ +# BFN Platform modules + +BFN_PLATFORM_MODULE_VERSION = 1.1 + +export BFN_PLATFORM_MODULE_VERSION + +BFN_PLATFORM_MODULE = sonic-platform-modules-bfn_$(BFN_PLATFORM_MODULE_VERSION)_amd64.deb +$(BFN_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-bfn +$(BFN_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(BFN_PLATFORM_MODULE)_PLATFORM = x86_64-accton_wedge100bf_65x-r0 +SONIC_DPKG_DEBS += $(BFN_PLATFORM_MODULE) + diff --git a/platform/barefoot/platform-modules-ingrasys.mk b/platform/barefoot/platform-modules-ingrasys.mk new file mode 100644 index 000000000000..60153e5dee75 --- /dev/null +++ b/platform/barefoot/platform-modules-ingrasys.mk @@ -0,0 +1,19 @@ +# Ingrasys S9180-32X Platform modules + +INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION = 1.1.0 +INGRASYS_S9280_64X_PLATFORM_MODULE_VERSION = 1.1.0 + +export INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION +export INGRASYS_S9280_64X_PLATFORM_MODULE_VERSION + +INGRASYS_S9180_32X_PLATFORM_MODULE = sonic-platform-ingrasys-s9180-32x_$(INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9180_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ingrasys +$(INGRASYS_S9180_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(INGRASYS_S9180_32X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9180_32x-r0 +SONIC_DPKG_DEBS += $(INGRASYS_S9180_32X_PLATFORM_MODULE) + +INGRASYS_S9280_64X_PLATFORM_MODULE = sonic-platform-ingrasys-s9280-64x_$(INGRASYS_S9280_64X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9280_64X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9280_64x-r0 + +$(eval $(call add_extra_package,$(INGRASYS_S9180_32X_PLATFORM_MODULE),$(INGRASYS_S9280_64X_PLATFORM_MODULE))) + diff --git a/platform/barefoot/platform-modules-wnc-osw1800.mk b/platform/barefoot/platform-modules-wnc-osw1800.mk new file mode 100644 index 000000000000..a203aa93f7ec --- /dev/null +++ b/platform/barefoot/platform-modules-wnc-osw1800.mk @@ -0,0 +1,12 @@ +# BFN Platform modules + +WNC_OSW1800_PLATFORM_MODULE_VERSION = 1.0 + +export WNC_OSW1800_PLATFORM_MODULE_VERSION + +WNC_OSW1800_PLATFORM_MODULE = platform-modules-wnc-osw1800_$(WNC_OSW1800_PLATFORM_MODULE_VERSION)_amd64.deb +$(WNC_OSW1800_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-wnc-osw1800 +$(WNC_OSW1800_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(WNC_OSW1800_PLATFORM_MODULE)_PLATFORM = x86_64-wnc_osw1800-r0 +SONIC_DPKG_DEBS += $(WNC_OSW1800_PLATFORM_MODULE) + diff --git a/platform/barefoot/platform.conf b/platform/barefoot/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/barefoot/rules.mk b/platform/barefoot/rules.mk new file mode 100644 index 000000000000..98dcef0f7b8a --- /dev/null +++ b/platform/barefoot/rules.mk @@ -0,0 +1,32 @@ +include $(PLATFORM_PATH)/platform-modules-arista.mk +include $(PLATFORM_PATH)/platform-modules-bfn.mk +include $(PLATFORM_PATH)/platform-modules-bfn-montara.mk +include $(PLATFORM_PATH)/platform-modules-bfn-newport.mk +include $(PLATFORM_PATH)/platform-modules-wnc-osw1800.mk +include $(PLATFORM_PATH)/platform-modules-ingrasys.mk +include $(PLATFORM_PATH)/bfn-sai.mk +include $(PLATFORM_PATH)/docker-syncd-bfn.mk +include $(PLATFORM_PATH)/docker-syncd-bfn-rpc.mk +include $(PLATFORM_PATH)/one-aboot.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/bfn-platform.mk +#include $(PLATFORM_PATH)/bfn-platform-wnc.mk +#include $(PLATFORM_PATH)/bfn-platform-ingrasys.mk +include $(PLATFORM_PATH)/bfn-modules.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) $(SONIC_ONE_ABOOT) \ + $(DOCKER_FPM) + +# Inject sai into syncd +#$(SYNCD)_DEPENDS += $(BFN_SAI) $(WNC_OSW1800_PLATFORM) $(BFN_INGRASYS_PLATFORM) $(BFN_PLATFORM) +$(SYNCD)_DEPENDS += $(BFN_SAI) $(BFN_INGRASYS_PLATFORM) $(BFN_PLATFORM) +$(SYNCD)_UNINSTALLS += $(BFN_SAI) + +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV) +endif + +# Runtime dependency on sai is set only for syncd +#$(SYNCD)_RDEPENDS += $(BFN_SAI) $(WNC_OSW1800_PLATFORM) $(BFN_INGRASYS_PLATFORM) $(BFN_PLATFORM) +$(SYNCD)_RDEPENDS += $(BFN_SAI) $(BFN_INGRASYS_PLATFORM) $(BFN_PLATFORM) diff --git a/platform/barefoot/sonic-platform-modules-arista b/platform/barefoot/sonic-platform-modules-arista new file mode 160000 index 000000000000..86f7b81834a1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-arista @@ -0,0 +1 @@ +Subproject commit 86f7b81834a1093d1df644b09232ddacb40784ef diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/LICENSE b/platform/barefoot/sonic-platform-modules-bfn-montara/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/MAINTAINERS b/platform/barefoot/sonic-platform-modules-bfn-montara/MAINTAINERS new file mode 100644 index 000000000000..6396065f4ab0 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/MAINTAINERS @@ -0,0 +1,3 @@ +# This file describes the maintainers for sonic-platform-modules-bfn-montara +# See the SONiC project governance document for more information +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/README.md b/platform/barefoot/sonic-platform-modules-bfn-montara/README.md new file mode 100644 index 000000000000..ac1fffb7dc43 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-bfn-montara +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/configs/network/interfaces.d/usb0 b/platform/barefoot/sonic-platform-modules-bfn-montara/configs/network/interfaces.d/usb0 new file mode 100644 index 000000000000..f1dd054cc6f6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/configs/network/interfaces.d/usb0 @@ -0,0 +1,5 @@ +# BMC interface +auto usb0 +allow-hotplug usb0 +iface usb0 inet6 +up ifconfig usb0 txqueuelen 64 diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/changelog b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/changelog new file mode 100644 index 000000000000..07fbc7081419 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/changelog @@ -0,0 +1,11 @@ +sonic-platform-modules-bfn-montara (1.1) unstable; urgency=low + + * Remove bfn asic kernel modules from platform package + + -- Support Mon, 22 Oct 2018 15:40:00 -0800 + +sonic-platform-modules-bfn-montara (1.0) unstable; urgency=low + + * Initial release + + -- Support Mon, 11 Nov 2015 11:11:11 -0800 diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/compat b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control new file mode 100644 index 000000000000..a3ea06992dc4 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control @@ -0,0 +1,12 @@ +Source: sonic-platform-modules-bfn-montara +Section: main +Priority: extra +Maintainer: Support +Build-Depends: debhelper (>= 9.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-modules-bfn-montara +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/copyright b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/postinst b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/postinst new file mode 100755 index 000000000000..a218d59e2652 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/postinst @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +PLATFORM_NAME=x86_64-accton_wedge100bf_32x-r0 +SONIC_PLATFORM_WHEEL_PY2="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py2-none-any.whl" +python2 -m pip install ${SONIC_PLATFORM_WHEEL_PY2} +SONIC_PLATFORM_WHEEL_PY3="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py3-none-any.whl" +python3 -m pip install ${SONIC_PLATFORM_WHEEL_PY3} + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/prerm b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/prerm new file mode 100755 index 000000000000..ee19dbb1db98 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/prerm @@ -0,0 +1,6 @@ +#!/bin/sh + +python2 -m pip uninstall -y sonic-platform +python3 -m pip uninstall -y sonic-platform + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules new file mode 100755 index 000000000000..4070b66dfdac --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f + +PLATFORM_NAME := x86_64-accton_wedge100bf_32x-r0 +PACKAGE_NAME := sonic-platform-modules-bfn-montara +SCRIPT_SRC := $(shell pwd)/scripts +CONFIGS_SRC := $(shell pwd)/configs +BUILD_DIR := $(shell pwd)/build +WHEEL_BUILD_DIR := $(BUILD_DIR)/wheel + +%: + dh $@ + +override_dh_auto_build: + set -e + python2.7 setup.py bdist_wheel -d $(WHEEL_BUILD_DIR) + python3 setup.py bdist_wheel -d $(WHEEL_BUILD_DIR) + set +e + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin + dh_installdirs -p$(PACKAGE_NAME) etc/network/interfaces.d/ + cp -r $(CONFIGS_SRC)/network/interfaces.d/* debian/$(PACKAGE_NAME)/etc/network/interfaces.d/ + dh_installdirs -p$(PACKAGE_NAME) usr/share/sonic/device/$(PLATFORM_NAME)/ + cp -r $(WHEEL_BUILD_DIR)/* debian/$(PACKAGE_NAME)/usr/share/sonic/device/$(PLATFORM_NAME)/ + +override_dh_usrlocal: + +override_dh_clean: + rm -fr $(WHEEL_BUILD_DIR) + rm -fr *.egg-info + rm -fr $(BUILD) + dh_clean diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/bf-fancontrol b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/bf-fancontrol new file mode 100755 index 000000000000..7407c2d7241d --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/bf-fancontrol @@ -0,0 +1,3 @@ +#!/bin/bash + +python3 -m sonic_platform.bfn_extensions.platform_fancontrol "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sensors b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sensors new file mode 100755 index 000000000000..5f06a9c99b05 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/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 + +python3 -m sonic_platform.bfn_extensions.platform_sensors "$@" +docker exec -$DOCKER_EXEC_FLAGS pmon sensors "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/setup.py b/platform/barefoot/sonic-platform-modules-bfn-montara/setup.py new file mode 100755 index 000000000000..14e1bb6b6c02 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/setup.py @@ -0,0 +1,32 @@ +from setuptools import setup + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation', + license='Apache 2.0', + author='SONiC Team', + author_email='', + url='https://github.com/Azure/sonic-buildimage', + maintainer='Barefoot', + maintainer_email='', + packages=[ + 'sonic_platform', + 'sonic_platform/pltfm_mgr_rpc', + 'sonic_platform/bfn_extensions', + ], + package_data = {'sonic_platform':['logging.conf']}, + 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/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/__init__.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/__init__.py new file mode 100644 index 000000000000..d5f19f74f4c6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ['chassis', 'eeprom', 'platform', 'psu', 'sfp'] +from . import platform diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/bfn_extensions/__init__.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/bfn_extensions/__init__.py new file mode 100644 index 000000000000..67517a64e886 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/bfn_extensions/__init__.py @@ -0,0 +1,4 @@ +__all__ = [ + 'platform_sensors', + 'platform_fancontrol', +] diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/bfn_extensions/platform_fancontrol.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/bfn_extensions/platform_fancontrol.py new file mode 100644 index 000000000000..43a700c21dcb --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/bfn_extensions/platform_fancontrol.py @@ -0,0 +1,59 @@ +import sys + +from sonic_platform.platform_thrift_client import thrift_try + +_MAX_FAN = 10 + +def fan_speed_set(fan, percent): + def set_fan_speed(client): + return client.pltfm_mgr.pltfm_mgr_fan_speed_set(fan, percent) + return thrift_try(set_fan_speed) + +def fan_speed_info_get(): + for fan_num in range(1, _MAX_FAN + 1): + def get_data(client, fan_num=fan_num): + return client.pltfm_mgr.pltfm_mgr_fan_info_get(fan_num) + fan_info = thrift_try(get_data) + if fan_info.fan_num == fan_num: + yield fan_info + +if __name__ == '__main__': + def print_usage(): + print("Usage: platform_fancontrol.py ", file=sys.stderr) + print(" function: fan_speed_set ", file=sys.stderr) + print(" fan_speed_info_get ", file=sys.stderr) + + argc = len(sys.argv) + if argc == 1: + print_usage() + exit(0) + + if sys.argv[1] == "fan_speed_set": + if argc != 4: + print_usage() + exit(0) + + fan = int(sys.argv[2]) + percent = int(sys.argv[3]) + + if (fan > _MAX_FAN) | (fan < 0): + print("Invalid value for fan #.\n", file=sys.stderr) + print_usage() + exit(0) + + if (percent > 100) | (percent < 0): + print("Invalid value for precent\n", file=sys.stderr) + print_usage() + exit(0) + + fan_speed_set(fan, percent) + exit(0) + + if sys.argv[1] == "fan_speed_info_get": + for fan_info in fan_speed_info_get(): + print("fan number: %d front rpm: %d rear rpm: %d percent: %d%% " % + (fan_info.fan_num, fan_info.front_rpm, fan_info.rear_rpm, fan_info.percent)) + + exit(0) + + print_usage() diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/bfn_extensions/platform_sensors.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/bfn_extensions/platform_sensors.py new file mode 100644 index 000000000000..330884ca733b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/bfn_extensions/platform_sensors.py @@ -0,0 +1,26 @@ +import sys +import codecs +import urllib + +from sonic_platform.platform_thrift_client import thrift_try + +def platform_sensors_get(args): + options = "" + if len(args)!=0: + options = urllib.quote(" ".join(args)) + def get_data(client): + return client.pltfm_mgr.pltfm_mgr_sensor_info_get(options) + raw_out = thrift_try(get_data) + raw_list = raw_out.split('\"') + if len(raw_list) >= 2: + sensors_out = raw_list[1] + sensors_out = codecs.decode(sensors_out, "unicode_escape") + return sensors_out + return None + +if __name__ == '__main__': + data = platform_sensors_get(sys.argv[1:]) + if data: + print(data) + else: + print("No sensors info available", file=sys.stderr) diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/chassis.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/chassis.py new file mode 100644 index 000000000000..fad16cbdb8a2 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/chassis.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +try: + import sys + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.psu import Psu + from eeprom import Eeprom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Chassis(ChassisBase): + """ + Platform-specific Chassis class + """ + def __init__(self): + ChassisBase.__init__(self) + + self._eeprom = Eeprom() + + for index in range(Sfp.port_start(), Sfp.port_end() + 1): + sfp_node = Sfp(index) + self._sfp_list.append(sfp_node) + + for i in range(1, Psu.get_num_psus() + 1): + psu = Psu(i) + self._psu_list.append(psu) + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_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): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_change_event(self, timeout=0): + ready, event_sfp = Sfp.get_transceiver_change_event(timeout) + return ready, { 'sfp': event_sfp } if ready else {} diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py new file mode 100644 index 000000000000..587f57826fb5 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py @@ -0,0 +1,155 @@ +try: + import os + import sys + import errno + import datetime + import logging + import logging.config + import yaml + import re + + sys.path.append(os.path.dirname(__file__)) + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_base + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo + + from platform_thrift_client import thrift_try +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +_platform_eeprom_map = { + "prod_name" : ("Product Name", "0x21", 12), + "odm_pcba_part_num" : ("Part Number", "0x22", 13), + "prod_ser_num" : ("Serial Number", "0x23", 12), + "ext_mac_addr" : ("Extended MAC Address Base", "0x24", 12), + "sys_mfg_date" : ("System Manufacturing Date", "0x25", 4), + "prod_ver" : ("Product Version", "0x26", 1), + "ext_mac_addr_size" : ("Extende MAC Address Size", "0x2A", 2), + "sys_mfger" : ("Manufacturer", "0x2B", 8) +} + +_product_dict = { "Montara" : "Wedge100BF-32X-O-AC-F-BF", + "Lower MAV" : "Wedge100BF-65X-O-AC-F-BF", + "Upper MAV" : "Wedge100BF-65X-O-AC-F-BF" + } + +_EEPROM_SYMLINK = "/var/run/platform/eeprom/syseeprom" +_EEPROM_STATUS = "/var/run/platform/eeprom/status" + +try: + _str_type = basestring +except NameError: + _str_type = str + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + def __init__(self): + with open(os.path.dirname(__file__) + "/logging.conf", 'r') as f: + config_dict = yaml.load(f, yaml.SafeLoader) + logging.config.dictConfig(config_dict) + + if not os.path.exists(os.path.dirname(_EEPROM_SYMLINK)): + try: + os.makedirs(os.path.dirname(_EEPROM_SYMLINK)) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + open(_EEPROM_SYMLINK, 'a').close() + with open(_EEPROM_STATUS, 'w') as f: + f.write("initializing..") + + self.eeprom_path = _EEPROM_SYMLINK + super(Eeprom, self).__init__(self.eeprom_path, 0, _EEPROM_STATUS, True) + + def sys_eeprom_get(client): + return client.pltfm_mgr.pltfm_mgr_sys_eeprom_get() + try: + platform_eeprom = thrift_try(sys_eeprom_get) + except Exception: + raise RuntimeError("eeprom.py: Initialization failed") + + self.__eeprom_init(platform_eeprom) + + def __eeprom_init(self, platform_eeprom): + with open(_EEPROM_STATUS, 'w') as f: + f.write("ok") + + eeprom_params = "" + for attr, val in platform_eeprom.__dict__.items(): + if val is None: + continue + + elem = _platform_eeprom_map.get(attr) + if elem is None: + continue + + if isinstance(val, _str_type): + value = val.replace('\0', '') + else: + value = str(val) + + if attr == "sys_mfg_date": + value = datetime.datetime.strptime(value, '%m-%d-%y').strftime('%m/%d/%Y 00:00:00') + + product = _product_dict.get(value) + if product is not None: + value = product + if len(eeprom_params) > 0: + eeprom_params += "," + eeprom_params += "{0:s}={1:s}".format(elem[1], value) + + orig_stdout = sys.stdout + sys.stdout = StringIO() + try: + eeprom_data = eeprom_tlvinfo.TlvInfoDecoder.set_eeprom(self, "", [eeprom_params]) + finally: + decode_output = sys.stdout.getvalue() + sys.stdout = orig_stdout + + eeprom_base.EepromDecoder.write_eeprom(self, eeprom_data) + self.__eeprom_tlv_dict = self.__parse_output(decode_output) + + def __parse_output(self, decode_output): + EEPROM_DECODE_HEADLINES = 6 + lines = decode_output.replace('\0', '').split('\n') + lines = lines[EEPROM_DECODE_HEADLINES:] + res = dict() + + for line in lines: + try: + # match whitespace-separated tag hex, length and value (value is mathced with its whitespaces) + match = re.search('(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+[\s]*[\S]*)', line) + if match is not None: + code = match.group(1) + value = match.group(3).rstrip('\0') + res[code] = value + except Exception: + pass + return res + + def __tlv_get(self, code): + return self.__eeprom_tlv_dict.get("0x{:X}".format(code), 'N/A') + + def system_eeprom_info(self): + return self.__eeprom_tlv_dict + + def serial_number_str(self): + return self.__tlv_get(self._TLV_CODE_SERIAL_NUMBER) + + def serial_str(self): + return self.serial_number_str() + + def base_mac_addr(self): + return self.__tlv_get(self._TLV_CODE_MAC_BASE) + + def part_number_str(self): + return self.__tlv_get(self._TLV_CODE_PART_NUMBER) + + def modelstr(self): + return self.__tlv_get(self._TLV_CODE_PRODUCT_NAME) diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/logging.conf b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/logging.conf new file mode 100644 index 000000000000..d7fd84773404 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/logging.conf @@ -0,0 +1,17 @@ +version: 1 +disable_existing_loggers: False + +formatters: + simple: + format: '%(asctime)s %(name)-30s %(levelname)-7s %(message)s' + +handlers: + file: + class: logging.handlers.RotatingFileHandler + formatter: simple + filename: /var/log/platform.log + +root: + level: ERROR + handlers: + - file diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform.py new file mode 100644 index 000000000000..ebc68a895362 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +############################################################################# +# +# 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): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform_thrift_client.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform_thrift_client.py new file mode 100644 index 000000000000..96c0e09ba1c0 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform_thrift_client.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +try: + import os + import sys + import time + import importlib + + sys.path.append(os.path.dirname(__file__)) + + from thrift.transport import TSocket + from thrift.transport import TTransport + from thrift.protocol import TBinaryProtocol + from thrift.protocol import TMultiplexedProtocol + from thrift.Thrift import TException +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +THRIFT_SERVER = 'localhost' + +class ThriftClient(object): + def open(self): + self.transport = TSocket.TSocket(THRIFT_SERVER, 9090) + + self.transport = TTransport.TBufferedTransport(self.transport) + bprotocol = TBinaryProtocol.TBinaryProtocol(self.transport) + + pltfm_mgr_client_module = importlib.import_module(".".join(["pltfm_mgr_rpc", "pltfm_mgr_rpc"])) + pltfm_mgr_protocol = TMultiplexedProtocol.TMultiplexedProtocol(bprotocol, "pltfm_mgr_rpc") + self.pltfm_mgr = pltfm_mgr_client_module.Client(pltfm_mgr_protocol) + + self.transport.open() + return self + def close(self): + self.transport.close() + def __enter__(self): + return self.open() + def __exit__(self, exc_type, exc_value, tb): + self.close() + +def thrift_try(func, attempts=35): + for attempt in range(attempts): + try: + with ThriftClient() as client: + return func(client) + except TException as e: + if attempt + 1 == attempts: + raise e + time.sleep(1) diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/pltfm_mgr_rpc/__init__.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/pltfm_mgr_rpc/__init__.py new file mode 100644 index 000000000000..414c3d6389c5 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/pltfm_mgr_rpc/__init__.py @@ -0,0 +1 @@ +__all__ = ['ttypes', 'pltfm_mgr_rpc'] diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/pltfm_mgr_rpc/pltfm_mgr_rpc.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/pltfm_mgr_rpc/pltfm_mgr_rpc.py new file mode 100644 index 000000000000..b256b6285fc3 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/pltfm_mgr_rpc/pltfm_mgr_rpc.py @@ -0,0 +1,2924 @@ +# +# Autogenerated by Thrift Compiler (0.10.0) +# +# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING +# +# options string: py +# + +from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException +from thrift.protocol.TProtocol import TProtocolException +import sys +import logging +from .ttypes import * +from thrift.Thrift import TProcessor +from thrift.transport import TTransport + + +class Iface(object): + def pltfm_mgr_dummy(self, device): + """ + Parameters: + - device + """ + pass + + def pltfm_mgr_sys_tmp_get(self): + pass + + def pltfm_mgr_sys_eeprom_get(self): + pass + + def pltfm_mgr_pwr_supply_present_get(self, ps_num): + """ + Parameters: + - ps_num + """ + pass + + def pltfm_mgr_pwr_supply_info_get(self, ps_num): + """ + Parameters: + - ps_num + """ + pass + + def pltfm_mgr_pwr_rail_info_get(self, ps_num): + """ + Parameters: + - ps_num + """ + pass + + def pltfm_mgr_fan_speed_set(self, fan_num, percent): + """ + Parameters: + - fan_num + - percent + """ + pass + + def pltfm_mgr_fan_info_get(self, fan_num): + """ + Parameters: + - fan_num + """ + pass + + def pltfm_mgr_qsfp_presence_get(self, port_num): + """ + Parameters: + - port_num + """ + pass + + def pltfm_mgr_qsfp_info_get(self, port_num): + """ + Parameters: + - port_num + """ + pass + + def pltfm_mgr_qsfp_get_max_port(self): + pass + + def pltfm_mgr_qsfp_reset(self, port_num, reset): + """ + Parameters: + - port_num + - reset + """ + pass + + def pltfm_mgr_qsfp_lpmode_get(self, port_num): + """ + Parameters: + - port_num + """ + pass + + def pltfm_mgr_qsfp_lpmode_set(self, port_num, lpmode): + """ + Parameters: + - port_num + - lpmode + """ + pass + + def pltfm_mgr_sensor_info_get(self, options): + """ + Parameters: + - options + """ + pass + + +class Client(Iface): + def __init__(self, iprot, oprot=None): + self._iprot = self._oprot = iprot + if oprot is not None: + self._oprot = oprot + self._seqid = 0 + + def pltfm_mgr_dummy(self, device): + """ + Parameters: + - device + """ + self.send_pltfm_mgr_dummy(device) + return self.recv_pltfm_mgr_dummy() + + def send_pltfm_mgr_dummy(self, device): + self._oprot.writeMessageBegin('pltfm_mgr_dummy', TMessageType.CALL, self._seqid) + args = pltfm_mgr_dummy_args() + args.device = device + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_dummy(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_dummy_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_dummy failed: unknown result") + + def pltfm_mgr_sys_tmp_get(self): + self.send_pltfm_mgr_sys_tmp_get() + return self.recv_pltfm_mgr_sys_tmp_get() + + def send_pltfm_mgr_sys_tmp_get(self): + self._oprot.writeMessageBegin('pltfm_mgr_sys_tmp_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_sys_tmp_get_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_sys_tmp_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_sys_tmp_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_sys_tmp_get failed: unknown result") + + def pltfm_mgr_sys_eeprom_get(self): + self.send_pltfm_mgr_sys_eeprom_get() + return self.recv_pltfm_mgr_sys_eeprom_get() + + def send_pltfm_mgr_sys_eeprom_get(self): + self._oprot.writeMessageBegin('pltfm_mgr_sys_eeprom_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_sys_eeprom_get_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_sys_eeprom_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_sys_eeprom_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_sys_eeprom_get failed: unknown result") + + def pltfm_mgr_pwr_supply_present_get(self, ps_num): + """ + Parameters: + - ps_num + """ + self.send_pltfm_mgr_pwr_supply_present_get(ps_num) + return self.recv_pltfm_mgr_pwr_supply_present_get() + + def send_pltfm_mgr_pwr_supply_present_get(self, ps_num): + self._oprot.writeMessageBegin('pltfm_mgr_pwr_supply_present_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_pwr_supply_present_get_args() + args.ps_num = ps_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_pwr_supply_present_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_pwr_supply_present_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_pwr_supply_present_get failed: unknown result") + + def pltfm_mgr_pwr_supply_info_get(self, ps_num): + """ + Parameters: + - ps_num + """ + self.send_pltfm_mgr_pwr_supply_info_get(ps_num) + return self.recv_pltfm_mgr_pwr_supply_info_get() + + def send_pltfm_mgr_pwr_supply_info_get(self, ps_num): + self._oprot.writeMessageBegin('pltfm_mgr_pwr_supply_info_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_pwr_supply_info_get_args() + args.ps_num = ps_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_pwr_supply_info_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_pwr_supply_info_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_pwr_supply_info_get failed: unknown result") + + def pltfm_mgr_pwr_rail_info_get(self, ps_num): + """ + Parameters: + - ps_num + """ + self.send_pltfm_mgr_pwr_rail_info_get(ps_num) + return self.recv_pltfm_mgr_pwr_rail_info_get() + + def send_pltfm_mgr_pwr_rail_info_get(self, ps_num): + self._oprot.writeMessageBegin('pltfm_mgr_pwr_rail_info_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_pwr_rail_info_get_args() + args.ps_num = ps_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_pwr_rail_info_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_pwr_rail_info_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_pwr_rail_info_get failed: unknown result") + + def pltfm_mgr_fan_speed_set(self, fan_num, percent): + """ + Parameters: + - fan_num + - percent + """ + self.send_pltfm_mgr_fan_speed_set(fan_num, percent) + return self.recv_pltfm_mgr_fan_speed_set() + + def send_pltfm_mgr_fan_speed_set(self, fan_num, percent): + self._oprot.writeMessageBegin('pltfm_mgr_fan_speed_set', TMessageType.CALL, self._seqid) + args = pltfm_mgr_fan_speed_set_args() + args.fan_num = fan_num + args.percent = percent + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_fan_speed_set(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_fan_speed_set_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_fan_speed_set failed: unknown result") + + def pltfm_mgr_fan_info_get(self, fan_num): + """ + Parameters: + - fan_num + """ + self.send_pltfm_mgr_fan_info_get(fan_num) + return self.recv_pltfm_mgr_fan_info_get() + + def send_pltfm_mgr_fan_info_get(self, fan_num): + self._oprot.writeMessageBegin('pltfm_mgr_fan_info_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_fan_info_get_args() + args.fan_num = fan_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_fan_info_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_fan_info_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_fan_info_get failed: unknown result") + + def pltfm_mgr_qsfp_presence_get(self, port_num): + """ + Parameters: + - port_num + """ + self.send_pltfm_mgr_qsfp_presence_get(port_num) + return self.recv_pltfm_mgr_qsfp_presence_get() + + def send_pltfm_mgr_qsfp_presence_get(self, port_num): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_presence_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_presence_get_args() + args.port_num = port_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_presence_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_presence_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_qsfp_presence_get failed: unknown result") + + def pltfm_mgr_qsfp_info_get(self, port_num): + """ + Parameters: + - port_num + """ + self.send_pltfm_mgr_qsfp_info_get(port_num) + return self.recv_pltfm_mgr_qsfp_info_get() + + def send_pltfm_mgr_qsfp_info_get(self, port_num): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_info_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_info_get_args() + args.port_num = port_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_info_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_info_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_qsfp_info_get failed: unknown result") + + def pltfm_mgr_qsfp_get_max_port(self): + self.send_pltfm_mgr_qsfp_get_max_port() + return self.recv_pltfm_mgr_qsfp_get_max_port() + + def send_pltfm_mgr_qsfp_get_max_port(self): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_get_max_port', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_get_max_port_args() + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_get_max_port(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_get_max_port_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_qsfp_get_max_port failed: unknown result") + + def pltfm_mgr_qsfp_reset(self, port_num, reset): + """ + Parameters: + - port_num + - reset + """ + self.send_pltfm_mgr_qsfp_reset(port_num, reset) + return self.recv_pltfm_mgr_qsfp_reset() + + def send_pltfm_mgr_qsfp_reset(self, port_num, reset): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_reset', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_reset_args() + args.port_num = port_num + args.reset = reset + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_reset(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_reset_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_qsfp_reset failed: unknown result") + + def pltfm_mgr_qsfp_lpmode_get(self, port_num): + """ + Parameters: + - port_num + """ + self.send_pltfm_mgr_qsfp_lpmode_get(port_num) + return self.recv_pltfm_mgr_qsfp_lpmode_get() + + def send_pltfm_mgr_qsfp_lpmode_get(self, port_num): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_lpmode_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_lpmode_get_args() + args.port_num = port_num + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_lpmode_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_lpmode_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_qsfp_lpmode_get failed: unknown result") + + def pltfm_mgr_qsfp_lpmode_set(self, port_num, lpmode): + """ + Parameters: + - port_num + - lpmode + """ + self.send_pltfm_mgr_qsfp_lpmode_set(port_num, lpmode) + return self.recv_pltfm_mgr_qsfp_lpmode_set() + + def send_pltfm_mgr_qsfp_lpmode_set(self, port_num, lpmode): + self._oprot.writeMessageBegin('pltfm_mgr_qsfp_lpmode_set', TMessageType.CALL, self._seqid) + args = pltfm_mgr_qsfp_lpmode_set_args() + args.port_num = port_num + args.lpmode = lpmode + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_qsfp_lpmode_set(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_qsfp_lpmode_set_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_qsfp_lpmode_set failed: unknown result") + + def pltfm_mgr_sensor_info_get(self, options): + """ + Parameters: + - options + """ + self.send_pltfm_mgr_sensor_info_get(options) + return self.recv_pltfm_mgr_sensor_info_get() + + def send_pltfm_mgr_sensor_info_get(self, options): + self._oprot.writeMessageBegin('pltfm_mgr_sensor_info_get', TMessageType.CALL, self._seqid) + args = pltfm_mgr_sensor_info_get_args() + args.options = options + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_pltfm_mgr_sensor_info_get(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = pltfm_mgr_sensor_info_get_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.ouch is not None: + raise result.ouch + raise TApplicationException(TApplicationException.MISSING_RESULT, "pltfm_mgr_sensor_info_get failed: unknown result") + + +class Processor(Iface, TProcessor): + def __init__(self, handler): + self._handler = handler + self._processMap = {} + self._processMap["pltfm_mgr_dummy"] = Processor.process_pltfm_mgr_dummy + self._processMap["pltfm_mgr_sys_tmp_get"] = Processor.process_pltfm_mgr_sys_tmp_get + self._processMap["pltfm_mgr_sys_eeprom_get"] = Processor.process_pltfm_mgr_sys_eeprom_get + self._processMap["pltfm_mgr_pwr_supply_present_get"] = Processor.process_pltfm_mgr_pwr_supply_present_get + self._processMap["pltfm_mgr_pwr_supply_info_get"] = Processor.process_pltfm_mgr_pwr_supply_info_get + self._processMap["pltfm_mgr_pwr_rail_info_get"] = Processor.process_pltfm_mgr_pwr_rail_info_get + self._processMap["pltfm_mgr_fan_speed_set"] = Processor.process_pltfm_mgr_fan_speed_set + self._processMap["pltfm_mgr_fan_info_get"] = Processor.process_pltfm_mgr_fan_info_get + self._processMap["pltfm_mgr_qsfp_presence_get"] = Processor.process_pltfm_mgr_qsfp_presence_get + self._processMap["pltfm_mgr_qsfp_info_get"] = Processor.process_pltfm_mgr_qsfp_info_get + self._processMap["pltfm_mgr_qsfp_get_max_port"] = Processor.process_pltfm_mgr_qsfp_get_max_port + self._processMap["pltfm_mgr_qsfp_reset"] = Processor.process_pltfm_mgr_qsfp_reset + self._processMap["pltfm_mgr_qsfp_lpmode_get"] = Processor.process_pltfm_mgr_qsfp_lpmode_get + self._processMap["pltfm_mgr_qsfp_lpmode_set"] = Processor.process_pltfm_mgr_qsfp_lpmode_set + self._processMap["pltfm_mgr_sensor_info_get"] = Processor.process_pltfm_mgr_sensor_info_get + + def process(self, iprot, oprot): + (name, type, seqid) = iprot.readMessageBegin() + if name not in self._processMap: + iprot.skip(TType.STRUCT) + iprot.readMessageEnd() + x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) + oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) + x.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + return + else: + self._processMap[name](self, seqid, iprot, oprot) + return True + + def process_pltfm_mgr_dummy(self, seqid, iprot, oprot): + args = pltfm_mgr_dummy_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_dummy_result() + try: + result.success = self._handler.pltfm_mgr_dummy(args.device) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_dummy", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_sys_tmp_get(self, seqid, iprot, oprot): + args = pltfm_mgr_sys_tmp_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_sys_tmp_get_result() + try: + result.success = self._handler.pltfm_mgr_sys_tmp_get() + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_sys_tmp_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_sys_eeprom_get(self, seqid, iprot, oprot): + args = pltfm_mgr_sys_eeprom_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_sys_eeprom_get_result() + try: + result.success = self._handler.pltfm_mgr_sys_eeprom_get() + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_sys_eeprom_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_pwr_supply_present_get(self, seqid, iprot, oprot): + args = pltfm_mgr_pwr_supply_present_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_pwr_supply_present_get_result() + try: + result.success = self._handler.pltfm_mgr_pwr_supply_present_get(args.ps_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_pwr_supply_present_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_pwr_supply_info_get(self, seqid, iprot, oprot): + args = pltfm_mgr_pwr_supply_info_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_pwr_supply_info_get_result() + try: + result.success = self._handler.pltfm_mgr_pwr_supply_info_get(args.ps_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_pwr_supply_info_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_pwr_rail_info_get(self, seqid, iprot, oprot): + args = pltfm_mgr_pwr_rail_info_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_pwr_rail_info_get_result() + try: + result.success = self._handler.pltfm_mgr_pwr_rail_info_get(args.ps_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_pwr_rail_info_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_fan_speed_set(self, seqid, iprot, oprot): + args = pltfm_mgr_fan_speed_set_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_fan_speed_set_result() + try: + result.success = self._handler.pltfm_mgr_fan_speed_set(args.fan_num, args.percent) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_fan_speed_set", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_fan_info_get(self, seqid, iprot, oprot): + args = pltfm_mgr_fan_info_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_fan_info_get_result() + try: + result.success = self._handler.pltfm_mgr_fan_info_get(args.fan_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_fan_info_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_presence_get(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_presence_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_presence_get_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_presence_get(args.port_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_presence_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_info_get(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_info_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_info_get_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_info_get(args.port_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_info_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_get_max_port(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_get_max_port_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_get_max_port_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_get_max_port() + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_get_max_port", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_reset(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_reset_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_reset_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_reset(args.port_num, args.reset) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_reset", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_lpmode_get(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_lpmode_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_lpmode_get_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_lpmode_get(args.port_num) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_lpmode_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_qsfp_lpmode_set(self, seqid, iprot, oprot): + args = pltfm_mgr_qsfp_lpmode_set_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_qsfp_lpmode_set_result() + try: + result.success = self._handler.pltfm_mgr_qsfp_lpmode_set(args.port_num, args.lpmode) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_qsfp_lpmode_set", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + + def process_pltfm_mgr_sensor_info_get(self, seqid, iprot, oprot): + args = pltfm_mgr_sensor_info_get_args() + args.read(iprot) + iprot.readMessageEnd() + result = pltfm_mgr_sensor_info_get_result() + try: + result.success = self._handler.pltfm_mgr_sensor_info_get(args.options) + msg_type = TMessageType.REPLY + except (TTransport.TTransportException, KeyboardInterrupt, SystemExit): + raise + except InvalidPltfmMgrOperation as ouch: + msg_type = TMessageType.REPLY + result.ouch = ouch + except Exception as ex: + msg_type = TMessageType.EXCEPTION + logging.exception(ex) + result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') + oprot.writeMessageBegin("pltfm_mgr_sensor_info_get", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + +# HELPER FUNCTIONS AND STRUCTURES + + +class pltfm_mgr_dummy_args(object): + """ + Attributes: + - device + """ + + thrift_spec = ( + None, # 0 + (1, TType.BYTE, 'device', None, None, ), # 1 + ) + + def __init__(self, device=None,): + self.device = device + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.BYTE: + self.device = iprot.readByte() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_dummy_args') + if self.device is not None: + oprot.writeFieldBegin('device', TType.BYTE, 1) + oprot.writeByte(self.device) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_dummy_result(object): + """ + Attributes: + - success + """ + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + ) + + def __init__(self, success=None,): + self.success = success + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.I32: + self.success = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_dummy_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.I32, 0) + oprot.writeI32(self.success) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sys_tmp_get_args(object): + + thrift_spec = ( + ) + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sys_tmp_get_args') + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sys_tmp_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (pltfm_mgr_sys_tmp_t, pltfm_mgr_sys_tmp_t.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = pltfm_mgr_sys_tmp_t() + self.success.read(iprot) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sys_tmp_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sys_eeprom_get_args(object): + + thrift_spec = ( + ) + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sys_eeprom_get_args') + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sys_eeprom_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (pltfm_mgr_eeprom_t, pltfm_mgr_eeprom_t.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = pltfm_mgr_eeprom_t() + self.success.read(iprot) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sys_eeprom_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_supply_present_get_args(object): + """ + Attributes: + - ps_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I16, 'ps_num', None, None, ), # 1 + ) + + def __init__(self, ps_num=None,): + self.ps_num = ps_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I16: + self.ps_num = iprot.readI16() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_supply_present_get_args') + if self.ps_num is not None: + oprot.writeFieldBegin('ps_num', TType.I16, 1) + oprot.writeI16(self.ps_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_supply_present_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.BOOL: + self.success = iprot.readBool() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_supply_present_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.BOOL, 0) + oprot.writeBool(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_supply_info_get_args(object): + """ + Attributes: + - ps_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I16, 'ps_num', None, None, ), # 1 + ) + + def __init__(self, ps_num=None,): + self.ps_num = ps_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I16: + self.ps_num = iprot.readI16() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_supply_info_get_args') + if self.ps_num is not None: + oprot.writeFieldBegin('ps_num', TType.I16, 1) + oprot.writeI16(self.ps_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_supply_info_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (pltfm_mgr_pwr_supply_info_t, pltfm_mgr_pwr_supply_info_t.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = pltfm_mgr_pwr_supply_info_t() + self.success.read(iprot) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_supply_info_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_rail_info_get_args(object): + """ + Attributes: + - ps_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I16, 'ps_num', None, None, ), # 1 + ) + + def __init__(self, ps_num=None,): + self.ps_num = ps_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I16: + self.ps_num = iprot.readI16() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_rail_info_get_args') + if self.ps_num is not None: + oprot.writeFieldBegin('ps_num', TType.I16, 1) + oprot.writeI16(self.ps_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_rail_info_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (pltfm_mgr_pwr_rail_info_t, pltfm_mgr_pwr_rail_info_t.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = pltfm_mgr_pwr_rail_info_t() + self.success.read(iprot) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_rail_info_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_fan_speed_set_args(object): + """ + Attributes: + - fan_num + - percent + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'fan_num', None, None, ), # 1 + (2, TType.I32, 'percent', None, None, ), # 2 + ) + + def __init__(self, fan_num=None, percent=None,): + self.fan_num = fan_num + self.percent = percent + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.fan_num = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.I32: + self.percent = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_fan_speed_set_args') + if self.fan_num is not None: + oprot.writeFieldBegin('fan_num', TType.I32, 1) + oprot.writeI32(self.fan_num) + oprot.writeFieldEnd() + if self.percent is not None: + oprot.writeFieldBegin('percent', TType.I32, 2) + oprot.writeI32(self.percent) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_fan_speed_set_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.I32: + self.success = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_fan_speed_set_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.I32, 0) + oprot.writeI32(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_fan_info_get_args(object): + """ + Attributes: + - fan_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'fan_num', None, None, ), # 1 + ) + + def __init__(self, fan_num=None,): + self.fan_num = fan_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.fan_num = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_fan_info_get_args') + if self.fan_num is not None: + oprot.writeFieldBegin('fan_num', TType.I32, 1) + oprot.writeI32(self.fan_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_fan_info_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRUCT, 'success', (pltfm_mgr_fan_info_t, pltfm_mgr_fan_info_t.thrift_spec), None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRUCT: + self.success = pltfm_mgr_fan_info_t() + self.success.read(iprot) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_fan_info_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRUCT, 0) + self.success.write(oprot) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_presence_get_args(object): + """ + Attributes: + - port_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'port_num', None, None, ), # 1 + ) + + def __init__(self, port_num=None,): + self.port_num = port_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.port_num = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_presence_get_args') + if self.port_num is not None: + oprot.writeFieldBegin('port_num', TType.I32, 1) + oprot.writeI32(self.port_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_presence_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.BOOL: + self.success = iprot.readBool() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_presence_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.BOOL, 0) + oprot.writeBool(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_info_get_args(object): + """ + Attributes: + - port_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'port_num', None, None, ), # 1 + ) + + def __init__(self, port_num=None,): + self.port_num = port_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.port_num = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_info_get_args') + if self.port_num is not None: + oprot.writeFieldBegin('port_num', TType.I32, 1) + oprot.writeI32(self.port_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_info_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRING, 'success', 'UTF8', None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRING: + self.success = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_info_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRING, 0) + oprot.writeString(self.success.encode('utf-8') if sys.version_info[0] == 2 else self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_get_max_port_args(object): + + thrift_spec = ( + ) + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_get_max_port_args') + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_get_max_port_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.I32: + self.success = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_get_max_port_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.I32, 0) + oprot.writeI32(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_reset_args(object): + """ + Attributes: + - port_num + - reset + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'port_num', None, None, ), # 1 + (2, TType.BOOL, 'reset', None, None, ), # 2 + ) + + def __init__(self, port_num=None, reset=None,): + self.port_num = port_num + self.reset = reset + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.port_num = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.BOOL: + self.reset = iprot.readBool() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_reset_args') + if self.port_num is not None: + oprot.writeFieldBegin('port_num', TType.I32, 1) + oprot.writeI32(self.port_num) + oprot.writeFieldEnd() + if self.reset is not None: + oprot.writeFieldBegin('reset', TType.BOOL, 2) + oprot.writeBool(self.reset) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_reset_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.I32: + self.success = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_reset_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.I32, 0) + oprot.writeI32(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_lpmode_get_args(object): + """ + Attributes: + - port_num + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'port_num', None, None, ), # 1 + ) + + def __init__(self, port_num=None,): + self.port_num = port_num + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.port_num = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_lpmode_get_args') + if self.port_num is not None: + oprot.writeFieldBegin('port_num', TType.I32, 1) + oprot.writeI32(self.port_num) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_lpmode_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.BOOL, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.BOOL: + self.success = iprot.readBool() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_lpmode_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.BOOL, 0) + oprot.writeBool(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_lpmode_set_args(object): + """ + Attributes: + - port_num + - lpmode + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'port_num', None, None, ), # 1 + (2, TType.BOOL, 'lpmode', None, None, ), # 2 + ) + + def __init__(self, port_num=None, lpmode=None,): + self.port_num = port_num + self.lpmode = lpmode + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.port_num = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.BOOL: + self.lpmode = iprot.readBool() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_lpmode_set_args') + if self.port_num is not None: + oprot.writeFieldBegin('port_num', TType.I32, 1) + oprot.writeI32(self.port_num) + oprot.writeFieldEnd() + if self.lpmode is not None: + oprot.writeFieldBegin('lpmode', TType.BOOL, 2) + oprot.writeBool(self.lpmode) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_qsfp_lpmode_set_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.I32, 'success', None, None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.I32: + self.success = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_qsfp_lpmode_set_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.I32, 0) + oprot.writeI32(self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sensor_info_get_args(object): + """ + Attributes: + - options + """ + + thrift_spec = ( + None, # 0 + (1, TType.STRING, 'options', 'UTF8', None, ), # 1 + ) + + def __init__(self, options=None,): + self.options = options + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRING: + self.options = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sensor_info_get_args') + if self.options is not None: + oprot.writeFieldBegin('options', TType.STRING, 1) + oprot.writeString(self.options.encode('utf-8') if sys.version_info[0] == 2 else self.options) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_sensor_info_get_result(object): + """ + Attributes: + - success + - ouch + """ + + thrift_spec = ( + (0, TType.STRING, 'success', 'UTF8', None, ), # 0 + (1, TType.STRUCT, 'ouch', (InvalidPltfmMgrOperation, InvalidPltfmMgrOperation.thrift_spec), None, ), # 1 + ) + + def __init__(self, success=None, ouch=None,): + self.success = success + self.ouch = ouch + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRING: + self.success = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.ouch = InvalidPltfmMgrOperation() + self.ouch.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sensor_info_get_result') + if self.success is not None: + oprot.writeFieldBegin('success', TType.STRING, 0) + oprot.writeString(self.success.encode('utf-8') if sys.version_info[0] == 2 else self.success) + oprot.writeFieldEnd() + if self.ouch is not None: + oprot.writeFieldBegin('ouch', TType.STRUCT, 1) + self.ouch.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/pltfm_mgr_rpc/ttypes.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/pltfm_mgr_rpc/ttypes.py new file mode 100644 index 000000000000..ce03e14f8691 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/pltfm_mgr_rpc/ttypes.py @@ -0,0 +1,1060 @@ +# +# Autogenerated by Thrift Compiler (0.10.0) +# +# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING +# +# options string: py +# + +from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException +from thrift.protocol.TProtocol import TProtocolException +import sys + +from thrift.transport import TTransport + + +class pltfm_mgr_sys_tmp_t(object): + """ + Attributes: + - tmp1 + - tmp2 + - tmp3 + - tmp4 + - tmp5 + - tmp6 + - tmp7 + - tmp8 + - tmp9 + - tmp10 + """ + + thrift_spec = ( + None, # 0 + (1, TType.DOUBLE, 'tmp1', None, None, ), # 1 + (2, TType.DOUBLE, 'tmp2', None, None, ), # 2 + (3, TType.DOUBLE, 'tmp3', None, None, ), # 3 + (4, TType.DOUBLE, 'tmp4', None, None, ), # 4 + (5, TType.DOUBLE, 'tmp5', None, None, ), # 5 + (6, TType.DOUBLE, 'tmp6', None, None, ), # 6 + (7, TType.DOUBLE, 'tmp7', None, None, ), # 7 + (8, TType.DOUBLE, 'tmp8', None, None, ), # 8 + (9, TType.DOUBLE, 'tmp9', None, None, ), # 9 + (10, TType.DOUBLE, 'tmp10', None, None, ), # 10 + ) + + def __init__(self, tmp1=None, tmp2=None, tmp3=None, tmp4=None, tmp5=None, tmp6=None, tmp7=None, tmp8=None, tmp9=None, tmp10=None,): + self.tmp1 = tmp1 + self.tmp2 = tmp2 + self.tmp3 = tmp3 + self.tmp4 = tmp4 + self.tmp5 = tmp5 + self.tmp6 = tmp6 + self.tmp7 = tmp7 + self.tmp8 = tmp8 + self.tmp9 = tmp9 + self.tmp10 = tmp10 + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.DOUBLE: + self.tmp1 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.DOUBLE: + self.tmp2 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.DOUBLE: + self.tmp3 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.DOUBLE: + self.tmp4 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 5: + if ftype == TType.DOUBLE: + self.tmp5 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 6: + if ftype == TType.DOUBLE: + self.tmp6 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 7: + if ftype == TType.DOUBLE: + self.tmp7 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 8: + if ftype == TType.DOUBLE: + self.tmp8 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 9: + if ftype == TType.DOUBLE: + self.tmp9 = iprot.readDouble() + else: + iprot.skip(ftype) + elif fid == 10: + if ftype == TType.DOUBLE: + self.tmp10 = iprot.readDouble() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_sys_tmp_t') + if self.tmp1 is not None: + oprot.writeFieldBegin('tmp1', TType.DOUBLE, 1) + oprot.writeDouble(self.tmp1) + oprot.writeFieldEnd() + if self.tmp2 is not None: + oprot.writeFieldBegin('tmp2', TType.DOUBLE, 2) + oprot.writeDouble(self.tmp2) + oprot.writeFieldEnd() + if self.tmp3 is not None: + oprot.writeFieldBegin('tmp3', TType.DOUBLE, 3) + oprot.writeDouble(self.tmp3) + oprot.writeFieldEnd() + if self.tmp4 is not None: + oprot.writeFieldBegin('tmp4', TType.DOUBLE, 4) + oprot.writeDouble(self.tmp4) + oprot.writeFieldEnd() + if self.tmp5 is not None: + oprot.writeFieldBegin('tmp5', TType.DOUBLE, 5) + oprot.writeDouble(self.tmp5) + oprot.writeFieldEnd() + if self.tmp6 is not None: + oprot.writeFieldBegin('tmp6', TType.DOUBLE, 6) + oprot.writeDouble(self.tmp6) + oprot.writeFieldEnd() + if self.tmp7 is not None: + oprot.writeFieldBegin('tmp7', TType.DOUBLE, 7) + oprot.writeDouble(self.tmp7) + oprot.writeFieldEnd() + if self.tmp8 is not None: + oprot.writeFieldBegin('tmp8', TType.DOUBLE, 8) + oprot.writeDouble(self.tmp8) + oprot.writeFieldEnd() + if self.tmp9 is not None: + oprot.writeFieldBegin('tmp9', TType.DOUBLE, 9) + oprot.writeDouble(self.tmp9) + oprot.writeFieldEnd() + if self.tmp10 is not None: + oprot.writeFieldBegin('tmp10', TType.DOUBLE, 10) + oprot.writeDouble(self.tmp10) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_eeprom_t(object): + """ + Attributes: + - version + - prod_name + - prod_part_num + - sys_asm_part_num + - bfn_pcba_part_num + - bfn_pcbb_part_num + - odm_pcba_part_num + - odm_pcba_ser_num + - prod_state + - prod_ver + - prod_sub_ver + - prod_ser_num + - prod_ast_tag + - sys_mfger + - sys_mfg_date + - pcb_mfger + - assembled_at + - loc_mac_addr + - ext_mac_addr + - ext_mac_addr_size + - location + - crc8 + """ + + thrift_spec = ( + None, # 0 + (1, TType.I16, 'version', None, None, ), # 1 + (2, TType.STRING, 'prod_name', 'UTF8', None, ), # 2 + (3, TType.STRING, 'prod_part_num', 'UTF8', None, ), # 3 + (4, TType.STRING, 'sys_asm_part_num', 'UTF8', None, ), # 4 + (5, TType.STRING, 'bfn_pcba_part_num', 'UTF8', None, ), # 5 + (6, TType.STRING, 'bfn_pcbb_part_num', 'UTF8', None, ), # 6 + (7, TType.STRING, 'odm_pcba_part_num', 'UTF8', None, ), # 7 + (8, TType.STRING, 'odm_pcba_ser_num', 'UTF8', None, ), # 8 + (9, TType.I16, 'prod_state', None, None, ), # 9 + (10, TType.I16, 'prod_ver', None, None, ), # 10 + (11, TType.I16, 'prod_sub_ver', None, None, ), # 11 + (12, TType.STRING, 'prod_ser_num', 'UTF8', None, ), # 12 + (13, TType.STRING, 'prod_ast_tag', 'UTF8', None, ), # 13 + (14, TType.STRING, 'sys_mfger', 'UTF8', None, ), # 14 + (15, TType.STRING, 'sys_mfg_date', 'UTF8', None, ), # 15 + (16, TType.STRING, 'pcb_mfger', 'UTF8', None, ), # 16 + (17, TType.STRING, 'assembled_at', 'UTF8', None, ), # 17 + (18, TType.STRING, 'loc_mac_addr', 'UTF8', None, ), # 18 + (19, TType.STRING, 'ext_mac_addr', 'UTF8', None, ), # 19 + (20, TType.I32, 'ext_mac_addr_size', None, None, ), # 20 + (21, TType.STRING, 'location', 'UTF8', None, ), # 21 + (22, TType.I16, 'crc8', None, None, ), # 22 + ) + + def __init__(self, version=None, prod_name=None, prod_part_num=None, sys_asm_part_num=None, bfn_pcba_part_num=None, bfn_pcbb_part_num=None, odm_pcba_part_num=None, odm_pcba_ser_num=None, prod_state=None, prod_ver=None, prod_sub_ver=None, prod_ser_num=None, prod_ast_tag=None, sys_mfger=None, sys_mfg_date=None, pcb_mfger=None, assembled_at=None, loc_mac_addr=None, ext_mac_addr=None, ext_mac_addr_size=None, location=None, crc8=None,): + self.version = version + self.prod_name = prod_name + self.prod_part_num = prod_part_num + self.sys_asm_part_num = sys_asm_part_num + self.bfn_pcba_part_num = bfn_pcba_part_num + self.bfn_pcbb_part_num = bfn_pcbb_part_num + self.odm_pcba_part_num = odm_pcba_part_num + self.odm_pcba_ser_num = odm_pcba_ser_num + self.prod_state = prod_state + self.prod_ver = prod_ver + self.prod_sub_ver = prod_sub_ver + self.prod_ser_num = prod_ser_num + self.prod_ast_tag = prod_ast_tag + self.sys_mfger = sys_mfger + self.sys_mfg_date = sys_mfg_date + self.pcb_mfger = pcb_mfger + self.assembled_at = assembled_at + self.loc_mac_addr = loc_mac_addr + self.ext_mac_addr = ext_mac_addr + self.ext_mac_addr_size = ext_mac_addr_size + self.location = location + self.crc8 = crc8 + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I16: + self.version = iprot.readI16() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.STRING: + self.prod_name = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.STRING: + self.prod_part_num = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.STRING: + self.sys_asm_part_num = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 5: + if ftype == TType.STRING: + self.bfn_pcba_part_num = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 6: + if ftype == TType.STRING: + self.bfn_pcbb_part_num = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 7: + if ftype == TType.STRING: + self.odm_pcba_part_num = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 8: + if ftype == TType.STRING: + self.odm_pcba_ser_num = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 9: + if ftype == TType.I16: + self.prod_state = iprot.readI16() + else: + iprot.skip(ftype) + elif fid == 10: + if ftype == TType.I16: + self.prod_ver = iprot.readI16() + else: + iprot.skip(ftype) + elif fid == 11: + if ftype == TType.I16: + self.prod_sub_ver = iprot.readI16() + else: + iprot.skip(ftype) + elif fid == 12: + if ftype == TType.STRING: + self.prod_ser_num = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 13: + if ftype == TType.STRING: + self.prod_ast_tag = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 14: + if ftype == TType.STRING: + self.sys_mfger = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 15: + if ftype == TType.STRING: + self.sys_mfg_date = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 16: + if ftype == TType.STRING: + self.pcb_mfger = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 17: + if ftype == TType.STRING: + self.assembled_at = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 18: + if ftype == TType.STRING: + self.loc_mac_addr = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 19: + if ftype == TType.STRING: + self.ext_mac_addr = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 20: + if ftype == TType.I32: + self.ext_mac_addr_size = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 21: + if ftype == TType.STRING: + self.location = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 22: + if ftype == TType.I16: + self.crc8 = iprot.readI16() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_eeprom_t') + if self.version is not None: + oprot.writeFieldBegin('version', TType.I16, 1) + oprot.writeI16(self.version) + oprot.writeFieldEnd() + if self.prod_name is not None: + oprot.writeFieldBegin('prod_name', TType.STRING, 2) + oprot.writeString(self.prod_name.encode('utf-8') if sys.version_info[0] == 2 else self.prod_name) + oprot.writeFieldEnd() + if self.prod_part_num is not None: + oprot.writeFieldBegin('prod_part_num', TType.STRING, 3) + oprot.writeString(self.prod_part_num.encode('utf-8') if sys.version_info[0] == 2 else self.prod_part_num) + oprot.writeFieldEnd() + if self.sys_asm_part_num is not None: + oprot.writeFieldBegin('sys_asm_part_num', TType.STRING, 4) + oprot.writeString(self.sys_asm_part_num.encode('utf-8') if sys.version_info[0] == 2 else self.sys_asm_part_num) + oprot.writeFieldEnd() + if self.bfn_pcba_part_num is not None: + oprot.writeFieldBegin('bfn_pcba_part_num', TType.STRING, 5) + oprot.writeString(self.bfn_pcba_part_num.encode('utf-8') if sys.version_info[0] == 2 else self.bfn_pcba_part_num) + oprot.writeFieldEnd() + if self.bfn_pcbb_part_num is not None: + oprot.writeFieldBegin('bfn_pcbb_part_num', TType.STRING, 6) + oprot.writeString(self.bfn_pcbb_part_num.encode('utf-8') if sys.version_info[0] == 2 else self.bfn_pcbb_part_num) + oprot.writeFieldEnd() + if self.odm_pcba_part_num is not None: + oprot.writeFieldBegin('odm_pcba_part_num', TType.STRING, 7) + oprot.writeString(self.odm_pcba_part_num.encode('utf-8') if sys.version_info[0] == 2 else self.odm_pcba_part_num) + oprot.writeFieldEnd() + if self.odm_pcba_ser_num is not None: + oprot.writeFieldBegin('odm_pcba_ser_num', TType.STRING, 8) + oprot.writeString(self.odm_pcba_ser_num.encode('utf-8') if sys.version_info[0] == 2 else self.odm_pcba_ser_num) + oprot.writeFieldEnd() + if self.prod_state is not None: + oprot.writeFieldBegin('prod_state', TType.I16, 9) + oprot.writeI16(self.prod_state) + oprot.writeFieldEnd() + if self.prod_ver is not None: + oprot.writeFieldBegin('prod_ver', TType.I16, 10) + oprot.writeI16(self.prod_ver) + oprot.writeFieldEnd() + if self.prod_sub_ver is not None: + oprot.writeFieldBegin('prod_sub_ver', TType.I16, 11) + oprot.writeI16(self.prod_sub_ver) + oprot.writeFieldEnd() + if self.prod_ser_num is not None: + oprot.writeFieldBegin('prod_ser_num', TType.STRING, 12) + oprot.writeString(self.prod_ser_num.encode('utf-8') if sys.version_info[0] == 2 else self.prod_ser_num) + oprot.writeFieldEnd() + if self.prod_ast_tag is not None: + oprot.writeFieldBegin('prod_ast_tag', TType.STRING, 13) + oprot.writeString(self.prod_ast_tag.encode('utf-8') if sys.version_info[0] == 2 else self.prod_ast_tag) + oprot.writeFieldEnd() + if self.sys_mfger is not None: + oprot.writeFieldBegin('sys_mfger', TType.STRING, 14) + oprot.writeString(self.sys_mfger.encode('utf-8') if sys.version_info[0] == 2 else self.sys_mfger) + oprot.writeFieldEnd() + if self.sys_mfg_date is not None: + oprot.writeFieldBegin('sys_mfg_date', TType.STRING, 15) + oprot.writeString(self.sys_mfg_date.encode('utf-8') if sys.version_info[0] == 2 else self.sys_mfg_date) + oprot.writeFieldEnd() + if self.pcb_mfger is not None: + oprot.writeFieldBegin('pcb_mfger', TType.STRING, 16) + oprot.writeString(self.pcb_mfger.encode('utf-8') if sys.version_info[0] == 2 else self.pcb_mfger) + oprot.writeFieldEnd() + if self.assembled_at is not None: + oprot.writeFieldBegin('assembled_at', TType.STRING, 17) + oprot.writeString(self.assembled_at.encode('utf-8') if sys.version_info[0] == 2 else self.assembled_at) + oprot.writeFieldEnd() + if self.loc_mac_addr is not None: + oprot.writeFieldBegin('loc_mac_addr', TType.STRING, 18) + oprot.writeString(self.loc_mac_addr.encode('utf-8') if sys.version_info[0] == 2 else self.loc_mac_addr) + oprot.writeFieldEnd() + if self.ext_mac_addr is not None: + oprot.writeFieldBegin('ext_mac_addr', TType.STRING, 19) + oprot.writeString(self.ext_mac_addr.encode('utf-8') if sys.version_info[0] == 2 else self.ext_mac_addr) + oprot.writeFieldEnd() + if self.ext_mac_addr_size is not None: + oprot.writeFieldBegin('ext_mac_addr_size', TType.I32, 20) + oprot.writeI32(self.ext_mac_addr_size) + oprot.writeFieldEnd() + if self.location is not None: + oprot.writeFieldBegin('location', TType.STRING, 21) + oprot.writeString(self.location.encode('utf-8') if sys.version_info[0] == 2 else self.location) + oprot.writeFieldEnd() + if self.crc8 is not None: + oprot.writeFieldBegin('crc8', TType.I16, 22) + oprot.writeI16(self.crc8) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_supply_info_t(object): + """ + Attributes: + - vin + - vout + - iout + - pwr_out + - fspeed + - ffault + - load_sharing + - model + - serial + - rev + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'vin', None, None, ), # 1 + (2, TType.I32, 'vout', None, None, ), # 2 + (3, TType.I32, 'iout', None, None, ), # 3 + (4, TType.I32, 'pwr_out', None, None, ), # 4 + (5, TType.I32, 'fspeed', None, None, ), # 5 + (6, TType.BOOL, 'ffault', None, None, ), # 6 + (7, TType.BOOL, 'load_sharing', None, None, ), # 7 + (8, TType.STRING, 'model', 'UTF8', None, ), # 8 + (9, TType.STRING, 'serial', 'UTF8', None, ), # 9 + (10, TType.STRING, 'rev', 'UTF8', None, ), # 10 + ) + + def __init__(self, vin=None, vout=None, iout=None, pwr_out=None, fspeed=None, ffault=None, load_sharing=None, model=None, serial=None, rev=None,): + self.vin = vin + self.vout = vout + self.iout = iout + self.pwr_out = pwr_out + self.fspeed = fspeed + self.ffault = ffault + self.load_sharing = load_sharing + self.model = model + self.serial = serial + self.rev = rev + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.vin = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.I32: + self.vout = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.I32: + self.iout = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.I32: + self.pwr_out = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 5: + if ftype == TType.I32: + self.fspeed = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 6: + if ftype == TType.BOOL: + self.ffault = iprot.readBool() + else: + iprot.skip(ftype) + elif fid == 7: + if ftype == TType.BOOL: + self.load_sharing = iprot.readBool() + else: + iprot.skip(ftype) + elif fid == 8: + if ftype == TType.STRING: + self.model = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 9: + if ftype == TType.STRING: + self.serial = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + elif fid == 10: + if ftype == TType.STRING: + self.rev = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_supply_info_t') + if self.vin is not None: + oprot.writeFieldBegin('vin', TType.I32, 1) + oprot.writeI32(self.vin) + oprot.writeFieldEnd() + if self.vout is not None: + oprot.writeFieldBegin('vout', TType.I32, 2) + oprot.writeI32(self.vout) + oprot.writeFieldEnd() + if self.iout is not None: + oprot.writeFieldBegin('iout', TType.I32, 3) + oprot.writeI32(self.iout) + oprot.writeFieldEnd() + if self.pwr_out is not None: + oprot.writeFieldBegin('pwr_out', TType.I32, 4) + oprot.writeI32(self.pwr_out) + oprot.writeFieldEnd() + if self.fspeed is not None: + oprot.writeFieldBegin('fspeed', TType.I32, 5) + oprot.writeI32(self.fspeed) + oprot.writeFieldEnd() + if self.ffault is not None: + oprot.writeFieldBegin('ffault', TType.BOOL, 6) + oprot.writeBool(self.ffault) + oprot.writeFieldEnd() + if self.load_sharing is not None: + oprot.writeFieldBegin('load_sharing', TType.BOOL, 7) + oprot.writeBool(self.load_sharing) + oprot.writeFieldEnd() + if self.model is not None: + oprot.writeFieldBegin('model', TType.STRING, 8) + oprot.writeString(self.model.encode('utf-8') if sys.version_info[0] == 2 else self.model) + oprot.writeFieldEnd() + if self.serial is not None: + oprot.writeFieldBegin('serial', TType.STRING, 9) + oprot.writeString(self.serial.encode('utf-8') if sys.version_info[0] == 2 else self.serial) + oprot.writeFieldEnd() + if self.rev is not None: + oprot.writeFieldBegin('rev', TType.STRING, 10) + oprot.writeString(self.rev.encode('utf-8') if sys.version_info[0] == 2 else self.rev) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_pwr_rail_info_t(object): + """ + Attributes: + - vrail1 + - vrail2 + - vrail3 + - vrail4 + - vrail5 + - vrail6 + - vrail7 + - vrail8 + - vrail9 + - vrail10 + - vrail11 + - vrail12 + - vrail13 + - vrail14 + - vrail15 + - vrail16 + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'vrail1', None, None, ), # 1 + (2, TType.I32, 'vrail2', None, None, ), # 2 + (3, TType.I32, 'vrail3', None, None, ), # 3 + (4, TType.I32, 'vrail4', None, None, ), # 4 + (5, TType.I32, 'vrail5', None, None, ), # 5 + (6, TType.I32, 'vrail6', None, None, ), # 6 + (7, TType.I32, 'vrail7', None, None, ), # 7 + (8, TType.I32, 'vrail8', None, None, ), # 8 + (9, TType.I32, 'vrail9', None, None, ), # 9 + (10, TType.I32, 'vrail10', None, None, ), # 10 + (11, TType.I32, 'vrail11', None, None, ), # 11 + (12, TType.I32, 'vrail12', None, None, ), # 12 + (13, TType.I32, 'vrail13', None, None, ), # 13 + (14, TType.I32, 'vrail14', None, None, ), # 14 + (15, TType.I32, 'vrail15', None, None, ), # 15 + (16, TType.I32, 'vrail16', None, None, ), # 16 + ) + + def __init__(self, vrail1=None, vrail2=None, vrail3=None, vrail4=None, vrail5=None, vrail6=None, vrail7=None, vrail8=None, vrail9=None, vrail10=None, vrail11=None, vrail12=None, vrail13=None, vrail14=None, vrail15=None, vrail16=None,): + self.vrail1 = vrail1 + self.vrail2 = vrail2 + self.vrail3 = vrail3 + self.vrail4 = vrail4 + self.vrail5 = vrail5 + self.vrail6 = vrail6 + self.vrail7 = vrail7 + self.vrail8 = vrail8 + self.vrail9 = vrail9 + self.vrail10 = vrail10 + self.vrail11 = vrail11 + self.vrail12 = vrail12 + self.vrail13 = vrail13 + self.vrail14 = vrail14 + self.vrail15 = vrail15 + self.vrail16 = vrail16 + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.vrail1 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.I32: + self.vrail2 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.I32: + self.vrail3 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.I32: + self.vrail4 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 5: + if ftype == TType.I32: + self.vrail5 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 6: + if ftype == TType.I32: + self.vrail6 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 7: + if ftype == TType.I32: + self.vrail7 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 8: + if ftype == TType.I32: + self.vrail8 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 9: + if ftype == TType.I32: + self.vrail9 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 10: + if ftype == TType.I32: + self.vrail10 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 11: + if ftype == TType.I32: + self.vrail11 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 12: + if ftype == TType.I32: + self.vrail12 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 13: + if ftype == TType.I32: + self.vrail13 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 14: + if ftype == TType.I32: + self.vrail14 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 15: + if ftype == TType.I32: + self.vrail15 = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 16: + if ftype == TType.I32: + self.vrail16 = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_pwr_rail_info_t') + if self.vrail1 is not None: + oprot.writeFieldBegin('vrail1', TType.I32, 1) + oprot.writeI32(self.vrail1) + oprot.writeFieldEnd() + if self.vrail2 is not None: + oprot.writeFieldBegin('vrail2', TType.I32, 2) + oprot.writeI32(self.vrail2) + oprot.writeFieldEnd() + if self.vrail3 is not None: + oprot.writeFieldBegin('vrail3', TType.I32, 3) + oprot.writeI32(self.vrail3) + oprot.writeFieldEnd() + if self.vrail4 is not None: + oprot.writeFieldBegin('vrail4', TType.I32, 4) + oprot.writeI32(self.vrail4) + oprot.writeFieldEnd() + if self.vrail5 is not None: + oprot.writeFieldBegin('vrail5', TType.I32, 5) + oprot.writeI32(self.vrail5) + oprot.writeFieldEnd() + if self.vrail6 is not None: + oprot.writeFieldBegin('vrail6', TType.I32, 6) + oprot.writeI32(self.vrail6) + oprot.writeFieldEnd() + if self.vrail7 is not None: + oprot.writeFieldBegin('vrail7', TType.I32, 7) + oprot.writeI32(self.vrail7) + oprot.writeFieldEnd() + if self.vrail8 is not None: + oprot.writeFieldBegin('vrail8', TType.I32, 8) + oprot.writeI32(self.vrail8) + oprot.writeFieldEnd() + if self.vrail9 is not None: + oprot.writeFieldBegin('vrail9', TType.I32, 9) + oprot.writeI32(self.vrail9) + oprot.writeFieldEnd() + if self.vrail10 is not None: + oprot.writeFieldBegin('vrail10', TType.I32, 10) + oprot.writeI32(self.vrail10) + oprot.writeFieldEnd() + if self.vrail11 is not None: + oprot.writeFieldBegin('vrail11', TType.I32, 11) + oprot.writeI32(self.vrail11) + oprot.writeFieldEnd() + if self.vrail12 is not None: + oprot.writeFieldBegin('vrail12', TType.I32, 12) + oprot.writeI32(self.vrail12) + oprot.writeFieldEnd() + if self.vrail13 is not None: + oprot.writeFieldBegin('vrail13', TType.I32, 13) + oprot.writeI32(self.vrail13) + oprot.writeFieldEnd() + if self.vrail14 is not None: + oprot.writeFieldBegin('vrail14', TType.I32, 14) + oprot.writeI32(self.vrail14) + oprot.writeFieldEnd() + if self.vrail15 is not None: + oprot.writeFieldBegin('vrail15', TType.I32, 15) + oprot.writeI32(self.vrail15) + oprot.writeFieldEnd() + if self.vrail16 is not None: + oprot.writeFieldBegin('vrail16', TType.I32, 16) + oprot.writeI32(self.vrail16) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class pltfm_mgr_fan_info_t(object): + """ + Attributes: + - fan_num + - front_rpm + - rear_rpm + - percent + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'fan_num', None, None, ), # 1 + (2, TType.I32, 'front_rpm', None, None, ), # 2 + (3, TType.I32, 'rear_rpm', None, None, ), # 3 + (4, TType.I32, 'percent', None, None, ), # 4 + ) + + def __init__(self, fan_num=None, front_rpm=None, rear_rpm=None, percent=None,): + self.fan_num = fan_num + self.front_rpm = front_rpm + self.rear_rpm = rear_rpm + self.percent = percent + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.fan_num = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 2: + if ftype == TType.I32: + self.front_rpm = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 3: + if ftype == TType.I32: + self.rear_rpm = iprot.readI32() + else: + iprot.skip(ftype) + elif fid == 4: + if ftype == TType.I32: + self.percent = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('pltfm_mgr_fan_info_t') + if self.fan_num is not None: + oprot.writeFieldBegin('fan_num', TType.I32, 1) + oprot.writeI32(self.fan_num) + oprot.writeFieldEnd() + if self.front_rpm is not None: + oprot.writeFieldBegin('front_rpm', TType.I32, 2) + oprot.writeI32(self.front_rpm) + oprot.writeFieldEnd() + if self.rear_rpm is not None: + oprot.writeFieldBegin('rear_rpm', TType.I32, 3) + oprot.writeI32(self.rear_rpm) + oprot.writeFieldEnd() + if self.percent is not None: + oprot.writeFieldBegin('percent', TType.I32, 4) + oprot.writeI32(self.percent) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +class InvalidPltfmMgrOperation(TException): + """ + Attributes: + - code + """ + + thrift_spec = ( + None, # 0 + (1, TType.I32, 'code', None, None, ), # 1 + ) + + def __init__(self, code=None,): + self.code = code + + def read(self, iprot): + if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: + iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec)) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.I32: + self.code = iprot.readI32() + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec))) + return + oprot.writeStructBegin('InvalidPltfmMgrOperation') + if self.code is not None: + oprot.writeFieldBegin('code', TType.I32, 1) + oprot.writeI32(self.code) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __str__(self): + return repr(self) + + def __repr__(self): + L = ['%s=%r' % (key, value) + for key, value in self.__dict__.items()] + return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/psu.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/psu.py new file mode 100644 index 000000000000..7e7e4403ad5c --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/psu.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +try: + import os + import sys + + sys.path.append(os.path.dirname(__file__)) + + from .platform_thrift_client import thrift_try + + from sonic_platform_base.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class Psu(PsuBase): + """Platform-specific PSU class""" + + def __init__(self, index): + PsuBase.__init__(self) + self.index = index + + @staticmethod + def get_num_psus(): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + return 2 + + def get_powergood_status(self): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based self.index + :param self.index: An integer, 1-based self.index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + def psu_info_get(client): + return client.pltfm_mgr.pltfm_mgr_pwr_supply_info_get(self.index) + + try: + psu_info = thrift_try(psu_info_get) + except Exception: + return False + + return (psu_info.ffault == False) + + def get_presence(self): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based self.index + :param self.index: An integer, 1-based self.index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + def psu_present_get(client): + return client.pltfm_mgr.pltfm_mgr_pwr_supply_present_get(self.index) + + try: + status = thrift_try(psu_present_get) + except Exception: + return False + + return status diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/sfp.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/sfp.py new file mode 100644 index 000000000000..739a48a8f1eb --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/sfp.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python + +try: + import os + import sys + import time + + import tempfile + from contextlib import contextmanager + from copy import copy + + sys.path.append(os.path.dirname(__file__)) + + from .platform_thrift_client import ThriftClient + from .platform_thrift_client import thrift_try + + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 0 + PORTS_IN_BLOCK = 0 + QSFP_PORT_START = 1 + QSFP_PORT_END = 0 + EEPROM_OFFSET = 0 + QSFP_CHECK_INTERVAL = 4 + + @property + def port_start(self): + self.update_port_info() + return self.PORT_START + + @property + def port_end(self): + self.update_port_info() + return self.PORT_END + + @property + def qsfp_ports(self): + self.update_port_info() + return range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1) + + @property + def port_to_eeprom_mapping(self): + print("dependency on sysfs has been removed") + raise Exception() + + def __init__(self): + self.ready = False + self.phy_port_dict = {'-1': 'system_not_ready'} + self.phy_port_cur_state = {} + self.qsfp_interval = self.QSFP_CHECK_INTERVAL + + SfpUtilBase.__init__(self) + + def update_port_info(self): + def qsfp_max_port_get(client): + return client.pltfm_mgr.pltfm_mgr_qsfp_get_max_port(); + + if self.QSFP_PORT_END == 0: + self.QSFP_PORT_END = thrift_try(qsfp_max_port_get) + self.PORT_END = self.QSFP_PORT_END + self.PORTS_IN_BLOCK = self.QSFP_PORT_END + + 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 + + presence = False + + def qsfp_presence_get(client): + return client.pltfm_mgr.pltfm_mgr_qsfp_presence_get(port_num) + + try: + presence = thrift_try(qsfp_presence_get) + except Exception as e: + print( e.__doc__) + print(e.message) + + return presence + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + def qsfp_lpmode_get(client): + return client.pltfm_mgr.pltfm_mgr_qsfp_lpmode_get(port_num) + + lpmode = thrift_try(qsfp_lpmode_get) + + return lpmode + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + def qsfp_lpmode_set(client): + return client.pltfm_mgr.pltfm_mgr_qsfp_lpmode_set(port_num, lpmode) + + status = thrift_try(qsfp_lpmode_set) + + return (status == 0) + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + def qsfp_reset(client): + client.pltfm_mgr.pltfm_mgr_qsfp_reset(port_num, True) + return client.pltfm_mgr.pltfm_mgr_qsfp_reset(port_num, False) + + err = thrift_try(qsfp_reset) + + return not err + + def check_transceiver_change(self): + if not self.ready: + return + + self.phy_port_dict = {} + + try: + client = ThriftClient().open() + except Exception: + return + + # Get presence of each SFP + for port in range(self.port_start, self.port_end + 1): + try: + sfp_resent = client.pltfm_mgr.pltfm_mgr_qsfp_presence_get(port) + except Exception: + sfp_resent = False + sfp_state = '1' if sfp_resent else '0' + + if port in self.phy_port_cur_state: + if self.phy_port_cur_state[port] != sfp_state: + self.phy_port_dict[port] = sfp_state + else: + self.phy_port_dict[port] = sfp_state + + # Update port current state + self.phy_port_cur_state[port] = sfp_state + + client.close() + + def get_transceiver_change_event(self, timeout=0): + forever = False + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + while forever or timeout > 0: + if not self.ready: + try: + with ThriftClient(): pass + except Exception: + pass + else: + self.ready = True + self.phy_port_dict = {} + break + elif self.qsfp_interval == 0: + self.qsfp_interval = self.QSFP_CHECK_INTERVAL + + # Process transceiver plug-in/out event + self.check_transceiver_change() + + # Break if tranceiver state has changed + if bool(self.phy_port_dict): + break + + if timeout: + timeout -= 1 + + if self.qsfp_interval: + self.qsfp_interval -= 1 + + time.sleep(1) + + return self.ready, self.phy_port_dict + + @contextmanager + def eeprom_action(self): + u = copy(self) + with tempfile.NamedTemporaryFile() as f: + u.eeprom_path = f.name + yield u + + def _sfp_eeprom_present(self, client_eeprompath, offset): + return client_eeprompath and super(SfpUtil, self)._sfp_eeprom_present(client_eeprompath, offset) + + def _get_port_eeprom_path(self, port_num, devid): + def qsfp_info_get(client): + return client.pltfm_mgr.pltfm_mgr_qsfp_info_get(port_num) + + if self.get_presence(port_num): + eeprom_hex = thrift_try(qsfp_info_get) + eeprom_raw = bytearray.fromhex(eeprom_hex) + with open(self.eeprom_path, 'wb') as eeprom_cache: + eeprom_cache.write(eeprom_raw) + return self.eeprom_path + + return None + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + + sfputil = SfpUtil() + + @staticmethod + def port_start(): + return Sfp.sfputil.port_start + + @staticmethod + def port_end(): + return Sfp.sfputil.port_end + + @staticmethod + def qsfp_ports(): + return Sfp.sfputil.qsfp_ports() + + @staticmethod + def get_transceiver_change_event(timeout=0): + return Sfp.sfputil.get_transceiver_change_event() + + def __init__(self, port_num): + self.port_num = port_num + SfpBase.__init__(self) + + def get_presence(self): + with Sfp.sfputil.eeprom_action() as u: + return u.get_presence(self.port_num) + + def get_lpmode(self): + with Sfp.sfputil.eeprom_action() as u: + return u.get_low_power_mode(self.port_num) + + def set_lpmode(self, lpmode): + with Sfp.sfputil.eeprom_action() as u: + return u.set_low_power_mode(self.port_num, lpmode) + + def reset(self): + return Sfp.sfputil.reset(self.port_num) + + def get_transceiver_info(self): + with Sfp.sfputil.eeprom_action() as u: + return u.get_transceiver_info_dict(self.port_num) + + def get_transceiver_bulk_status(self): + with Sfp.sfputil.eeprom_action() as u: + return u.get_transceiver_dom_info_dict(self.port_num) + + def get_transceiver_threshold_info(self): + with Sfp.sfputil.eeprom_action() as u: + return u.get_transceiver_dom_threshold_info_dict(self.port_num) + + def get_change_event(self, timeout=0): + return Sfp.get_transceiver_change_event(timeout) diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/LICENSE b/platform/barefoot/sonic-platform-modules-bfn-newport/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/MAINTAINERS b/platform/barefoot/sonic-platform-modules-bfn-newport/MAINTAINERS new file mode 100644 index 000000000000..85aa0cd77d72 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/MAINTAINERS @@ -0,0 +1,3 @@ +# This file describes the maintainers for sonic-platform-modules-bfn-newport +# See the SONiC project governance document for more information +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/README.md b/platform/barefoot/sonic-platform-modules-bfn-newport/README.md new file mode 100644 index 000000000000..028adef715f3 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-bfn-newport +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/configs/network/interfaces.d/eth2 b/platform/barefoot/sonic-platform-modules-bfn-newport/configs/network/interfaces.d/eth2 new file mode 100644 index 000000000000..aded25af63b7 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/configs/network/interfaces.d/eth2 @@ -0,0 +1,4 @@ +# eth cpu port +auto eth2 +iface eth2 inet +up ifconfig eth2 promisc mtu 9216 diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/configs/network/interfaces.d/usb0 b/platform/barefoot/sonic-platform-modules-bfn-newport/configs/network/interfaces.d/usb0 new file mode 100644 index 000000000000..f1dd054cc6f6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/configs/network/interfaces.d/usb0 @@ -0,0 +1,5 @@ +# BMC interface +auto usb0 +allow-hotplug usb0 +iface usb0 inet6 +up ifconfig usb0 txqueuelen 64 diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/configs/systemd/system/bfn-newport.service b/platform/barefoot/sonic-platform-modules-bfn-newport/configs/systemd/system/bfn-newport.service new file mode 100644 index 000000000000..9d6ca1271e85 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/configs/systemd/system/bfn-newport.service @@ -0,0 +1,14 @@ +[Unit] +Description=Barefoot Newport FPGA driver +Before=syncd.service + +[Service] +User=root +ExecStartPre=/sbin/depmod -a +ExecStart=/sbin/modprobe bf_fpga +ExecStartPost=/sbin/modprobe bf_tun +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target + diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/changelog b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/changelog new file mode 100644 index 000000000000..98ecad42ac90 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/changelog @@ -0,0 +1,5 @@ +sonic-platform-modules-bfn-newport (1.0) unstable; urgency=low + + * Initial release + + -- Support Mon, 27 Sep 2019 18:00:00 -0800 diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/compat b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control new file mode 100644 index 000000000000..d2c37fe8d2b9 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control @@ -0,0 +1,17 @@ +Source: sonic-platform-modules-bfn-newport +Section: main +Priority: extra +Maintainer: Support +Build-Depends: debhelper (>= 9.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-modules-bfn-newport-as9516 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel module for bfn platform fpga and scripts for the devices such as fan, led, sfp + +Package: sonic-platform-modules-bfn-newport-as9516bf +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +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-newport/debian/copyright b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/install b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/install new file mode 100644 index 000000000000..7cb6ed7fe336 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/install @@ -0,0 +1 @@ +configs/systemd/system/bfn-newport.service etc/systemd/system diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/postinst b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/postinst new file mode 100644 index 000000000000..90d772ef89df --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/postinst @@ -0,0 +1,27 @@ +#!/bin/sh +set -e +depmod -a +systemctl enable bfn-newport.service +systemctl start bfn-newport.service + +PLATFORM_NAME=x86_64-accton_as9516bf_32d-r0 +SONIC_PLATFORM_WHEEL_PY2="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py2-none-any.whl" +if [ -e ${SONIC_PLATFORM_WHEEL_PY2} ]; then + python2 -m pip install ${SONIC_PLATFORM_WHEEL_PY2} +fi +SONIC_PLATFORM_WHEEL_PY3="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py3-none-any.whl" +if [ -e ${SONIC_PLATFORM_WHEEL_PY3} ]; then + python3 -m pip install ${SONIC_PLATFORM_WHEEL_PY3} +fi + +PLATFORM_NAME=x86_64-accton_as9516_32d-r0 +SONIC_PLATFORM_WHEEL_PY2="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py2-none-any.whl" +if [ -e ${SONIC_PLATFORM_WHEEL_PY2} ]; then + python2 -m pip install ${SONIC_PLATFORM_WHEEL_PY2} +fi +SONIC_PLATFORM_WHEEL_PY3="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py3-none-any.whl" +if [ -e ${SONIC_PLATFORM_WHEEL_PY3} ]; then + python3 -m pip install ${SONIC_PLATFORM_WHEEL_PY3} +fi + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/prerm b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/prerm new file mode 100644 index 000000000000..ee19dbb1db98 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/prerm @@ -0,0 +1,6 @@ +#!/bin/sh + +python2 -m pip uninstall -y sonic-platform +python3 -m pip uninstall -y sonic-platform + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/rules b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/rules new file mode 100755 index 000000000000..da70905cb239 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/rules @@ -0,0 +1,49 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_PRE_NAME := sonic-platform-modules-bfn-newport +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MODULE_SRC := $(shell pwd)/modules +SCRIPT_SRC := $(shell pwd)/scripts +CONFIGS_SRC := $(shell pwd)/configs +BUILD_DIR := $(shell pwd)/build +WHEEL_BUILD_DIR := $(BUILD_DIR)/wheel +MODULE_NAMES := as9516 as9516bf + +%: + dh $@ + +override_dh_auto_build: + make -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + set -e + python2.7 setup.py bdist_wheel -d $(WHEEL_BUILD_DIR) + python3 setup.py bdist_wheel -d $(WHEEL_BUILD_DIR) + set +e + +override_dh_auto_install: + (for mod in $(MODULE_NAMES); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MODULE_SRC)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/local/bin; \ + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} etc/network/interfaces.d/; \ + cp -r $(CONFIGS_SRC)/network/interfaces.d/* debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/network/interfaces.d/; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/share/sonic/device/x86_64-accton_$${mod}_32d-r0/; \ + cp -r $(WHEEL_BUILD_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/share/sonic/device/x86_64-accton_$${mod}_32d-r0/; \ + done) + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + rm -fr $(WHEEL_BUILD_DIR) + rm -fr *.egg-info + rm -fr $(BUILD) + rm -f $(MODULE_SRC)/*.o $(MODULE_SRC)/*.ko $(MODULE_SRC)/*.mod.c $(MODULE_SRC)/.*.cmd + rm -f $(MODULE_SRC)/Module.markers $(MODULE_SRC)/Module.symvers $(MODULE_SRC)/modules.order + rm -rf $(MODULE_SRC)/.tmp_versions + diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/Makefile b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/Makefile new file mode 100644 index 000000000000..732ffb1f3f6c --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := bf_fpga.o +bf_fpga-y := bf_fpga_main.o bf_fpga_ioctl.o bf_fpga_sysfs.o i2c/bf_fpga_i2c.o i2c/bf_fpga_i2c_ctrl.o i2c/bf_fpga_i2c_porting.o diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_ioctl.c b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_ioctl.c new file mode 100644 index 000000000000..b0792556caf6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_ioctl.c @@ -0,0 +1,196 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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 + +*******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "bf_fpga_priv.h" +#include "bf_fpga_ioctl.h" +#include "i2c/bf_fpga_i2c.h" + +int bf_fpga_ioctl(struct bf_pci_dev *bfdev, + unsigned int cmd, + unsigned long arg) { + void *addr = (void __user *)arg; + int ret = -1; + + if (!bfdev || !addr) { + return -EFAULT; + } + + switch (cmd) { + case BF_FPGA_IOCTL_I2C_CTL: { + bf_fpga_i2c_ctl_t i2c_ctl; + bool busy; + + if (copy_from_user(&i2c_ctl, addr, sizeof(bf_fpga_i2c_ctl_t))) { + return -EFAULT; + } + switch (i2c_ctl.control_type) { + case BF_FPGA_I2C_START: + ret = fpga_i2c_start(i2c_ctl.inst_hndl.bus_id); + break; + case BF_FPGA_I2C_STOP: + ret = fpga_i2c_stop(i2c_ctl.inst_hndl.bus_id); + break; + case BF_FPGA_I2C_RESET: + ret = fpga_i2c_reset(i2c_ctl.inst_hndl.bus_id); + break; + case BF_FPGA_I2C_BUSY: + ret = fpga_i2c_is_busy(i2c_ctl.inst_hndl.bus_id, &busy); + if (ret == 0) { + if (copy_to_user(&(((bf_fpga_i2c_ctl_t *)addr)->is_busy), + &busy, + sizeof(busy))) { + return -EFAULT; + } + } + break; + case BF_FPGA_I2C_INST_EN: + ret = fpga_i2c_inst_en( + i2c_ctl.inst_hndl.bus_id, i2c_ctl.inst_hndl.inst_id, true); + break; + case BF_FPGA_I2C_INST_DIS: + ret = fpga_i2c_inst_en( + i2c_ctl.inst_hndl.bus_id, i2c_ctl.inst_hndl.inst_id, false); + break; + case BF_FPGA_I2C_INST_PMT: + break; + case BF_FPGA_I2C_INST_STOP_ON_ERR: + break; + case BF_FPGA_I2C_INST_INT_EN: + break; + default: + break; + } + break; + } + case BF_FPGA_IOCTL_I2C_SET_CLK: { + bf_fpga_i2c_set_clk_t i2c_clk; + if (copy_from_user(&i2c_clk, addr, sizeof(bf_fpga_i2c_set_clk_t))) { + return -EFAULT; + } + ret = fpga_i2c_set_clk(i2c_clk.bus_id, i2c_clk.clock_div); + break; + } + case BF_FPGA_IOCTL_I2C_ONETIME: { + bf_fpga_i2c_t i2c_op; + int i; + + if (copy_from_user(&i2c_op, addr, sizeof(bf_fpga_i2c_t))) { + return -EFAULT; + } + ret = fpga_i2c_oneshot(&i2c_op); + if (ret == 0) { + /* copy read data to user area */ + for (i = 0; i < i2c_op.num_i2c; i++) { + if (i2c_op.i2c_inst[i].rd_cnt) { + if (copy_to_user(&(((bf_fpga_i2c_t *)addr)->i2c_inst[i].rd_buf), + &i2c_op.i2c_inst[i].rd_buf, + i2c_op.i2c_inst[i].rd_cnt)) { + return -EFAULT; + } + } + } + } else { + printk(KERN_ERR + "fpga i2c ioctl oneshot bus %d error %d i2c_addr 0x%hhx:0x%hhx " + "i2c_status 0x%hhx:0x%hhx\n", + i2c_op.inst_hndl.bus_id, + ret, + i2c_op.i2c_inst[0].i2c_addr, + i2c_op.i2c_inst[1].i2c_addr, + i2c_op.i2c_inst[0].status, + i2c_op.i2c_inst[1].status); + } + break; + } + case BF_FPGA_IOCTL_I2C_ADD_PR: { + bf_fpga_i2c_t i2c_op; + if (copy_from_user(&i2c_op, addr, sizeof(bf_fpga_i2c_t))) { + return -EFAULT; + } + ret = fpga_i2c_pr_add(&i2c_op); + if (ret == 0) { + /* copy read data to user area */ + if (copy_to_user(&((bf_fpga_i2c_t *)addr)->inst_hndl.inst_id, + &i2c_op.inst_hndl.inst_id, + sizeof(i2c_op.inst_hndl.inst_id))) { + return -EFAULT; + } + } else { + printk(KERN_ERR "fpga i2c ioctl add-pr error %d on bus %d\n", + ret, + i2c_op.inst_hndl.bus_id); + } + break; + } + case BF_FPGA_IOCTL_I2C_DEL_PR: { + bf_fpga_i2c_t i2c_op; + if (copy_from_user(&i2c_op, addr, sizeof(bf_fpga_i2c_t))) { + return -EFAULT; + } + ret = fpga_i2c_del(&i2c_op); + if (ret != 0) { + printk(KERN_ERR "fpga i2c ioctl del-pr error %d on bus %d\n", + ret, + i2c_op.inst_hndl.bus_id); + } + break; + } + case BF_FPGA_IOCTL_I2C_RD_DATA: { + bf_fpga_i2c_rd_data_t i2c_rd_data; + /* get user supplied offset and rd_cnt */ + if (copy_from_user( + &i2c_rd_data, addr, offsetof(bf_fpga_i2c_rd_data_t, rd_buf))) { + return -EFAULT; + } + ret = fpga_i2c_data_read(i2c_rd_data.inst_hndl.bus_id, + i2c_rd_data.inst_hndl.inst_id, + i2c_rd_data.offset, + i2c_rd_data.rd_cnt, + i2c_rd_data.rd_buf); + if (ret == 0) { + if (copy_to_user(&(((bf_fpga_i2c_rd_data_t *)addr)->rd_buf), + &i2c_rd_data.rd_buf, + i2c_rd_data.rd_cnt)) { + return -EFAULT; + } + } else { + printk(KERN_ERR "fpga i2c ioctl rd-data error %d on bus %d inst %d\n", + ret, + i2c_rd_data.inst_hndl.bus_id, + i2c_rd_data.inst_hndl.inst_id); + } + break; + } + default: + return -EINVAL; + } + return ret; +} diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_ioctl.h b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_ioctl.h new file mode 100644 index 000000000000..4c5eb7bf0386 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_ioctl.h @@ -0,0 +1,131 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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_FPGA_IOCTL_H_ +#define _BF_FPGA_IOCTL_H_ + +#ifdef __KERNEL__ +#include +#else +#include + +#endif /* __KERNEL__ */ + +#define BF_FPGA_IOC_MAGIC 'f' +#define BF_I2C_FPGA_NUM_CTRL 34 +#define BF_FPGA_MAX_I2C_RD_DATA 128 +#define BF_FPGA_MAX_I2C_WR_DATA 129 + +/* i2c control types */ +#define BF_FPGA_I2C_START 1 +#define BF_FPGA_I2C_STOP 2 +#define BF_FPGA_I2C_BUSY 3 +#define BF_FPGA_I2C_INST_EN 4 +#define BF_FPGA_I2C_INST_DIS 5 +#define BF_FPGA_I2C_INST_PMT 6 +#define BF_FPGA_I2C_INST_STOP_ON_ERR 7 +#define BF_FPGA_I2C_INST_INT_EN 8 +#define BF_FPGA_I2C_RESET 9 + +/* i2c operation types */ +#define BF_FPGA_I2C_NOP 0 +#define BF_FPGA_I2C_WRITE \ + 1 /* / ..[max 129 bytes] */ +#define BF_FPGA_I2C_READ \ + 2 /* / ..[max 128 bytes] */ +#define BF_FPGA_I2C_ADDR_READ \ + 3 /* / / \ + */ + +#define FPGA_I2c_ONESHOT_BEGIN_INDEX 0 +#define FPGA_I2C_ONESHOT_NUM_INST 15 +#define FPGA_I2C_PERIODIC_BEGIN_INDEX (FPGA_I2C_ONESHOT_NUM_INST) +#define FPGA_I2C_PERIODIC_NUM_INST 16 +#define FPGA_I2C_NUM_INST \ + (FPGA_I2C_ONESHOT_NUM_INST + FPGA_I2C_PERIODIC_NUM_INST) +/* maximum i2c instructions that can be handled in one system call */ +#define BF_FPGA_I2C_MAX_NUM_INST 3 + +typedef struct bf_fpga_i2c_set_clk_s { + /* 0:100k, 1:400k, 2:1M, or: 125e6//3 */ + int clock_div; /* clock divider */ + unsigned char bus_id; /* controller index */ +} bf_fpga_i2c_set_clk_t; + +typedef struct bf_fpga_inst_hndl_s { + int inst_id; /* instruction index within the controller memory space */ + unsigned char bus_id; /* controller index */ + unsigned char status; +} bf_fpga_inst_hndl_t; + +typedef struct bf_fpga_i2c_inst_s { + bool preemt; + bool en; + unsigned char i2c_addr; /* i2c device address in 7 bit format */ + unsigned char i2c_type; /* type of i2c cycle */ + unsigned char delay; /* delay in TBD - microseconds before i2c transaction */ + unsigned char ctrl; + unsigned char wr_cnt; /* number of bytes to write (after i2c address) */ + unsigned char rd_cnt; /* number of bytes to read */ + union { + unsigned char + wr_buf[BF_FPGA_MAX_I2C_WR_DATA]; /* write data source buffer */ + unsigned char rd_buf[BF_FPGA_MAX_I2C_RD_DATA]; /* read data dest buffer */ + }; + unsigned char status; + unsigned char retry_cnt; /* if fpga maintains retry count */ + unsigned char mux; /* if fpga maintains internal MUX */ +} bf_fpga_i2c_inst_t; + +typedef struct bf_fpga_i2c_s { + unsigned char num_i2c; /* number of i2c operations */ + unsigned char one_time; /* one time or periodic */ + bf_fpga_inst_hndl_t inst_hndl; + bf_fpga_i2c_inst_t i2c_inst[BF_FPGA_I2C_MAX_NUM_INST]; +} bf_fpga_i2c_t; + +typedef struct bf_fpga_i2c_rd_data_s { + bf_fpga_inst_hndl_t inst_hndl; + unsigned char offset; + unsigned char rd_cnt; + unsigned char rd_buf[BF_FPGA_MAX_I2C_RD_DATA]; +} bf_fpga_i2c_rd_data_t; + +typedef struct bf_fpga_i2c_ctl_s { + bf_fpga_inst_hndl_t inst_hndl; + unsigned char control_type; /* start, stop, reset, enable, disable or busy */ + bool is_busy; +} bf_fpga_i2c_ctl_t; + +#define BF_FPGA_IOCTL_I2C_CTL _IOWR(BF_FPGA_IOC_MAGIC, 0, bf_fpga_i2c_ctl_t) +#define BF_FPGA_IOCTL_I2C_ONETIME _IOWR(BF_FPGA_IOC_MAGIC, 1, bf_fpga_i2c_t) +#define BF_FPGA_IOCTL_I2C_ADD_PR _IOWR(BF_FPGA_IOC_MAGIC, 2, bf_fpga_i2c_t) +#define BF_FPGA_IOCTL_I2C_DEL_PR _IOWR(BF_FPGA_IOC_MAGIC, 3, bf_fpga_i2c_t) +#define BF_FPGA_IOCTL_I2C_RD_DATA \ + _IOWR(BF_FPGA_IOC_MAGIC, 4, bf_fpga_i2c_rd_data_t) +#define BF_FPGA_IOCTL_I2C_SET_CLK \ + _IOW(BF_FPGA_IOC_MAGIC, 5, bf_fpga_i2c_set_clk_t) + +#endif /* _BF_FPGA_IOCTL_H_ */ diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_main.c b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_main.c new file mode 100644 index 000000000000..563cc5120df1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_main.c @@ -0,0 +1,1294 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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 + +*******************************************************************************/ +/* bf_fpga kernel module + * + * This is kernel mode driver for BF FPGA chip. + * Provides user space mmap service and user space "wait for interrupt", + * "enable interrupt" and i2c services + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bf_fpga_ioctl.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) +#include +#else +#include +#endif +#include +#include +#include +#include "bf_fpga_priv.h" +#include "i2c/bf_fpga_i2c_reg.h" +#include "i2c/bf_fpga_i2c.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) +//#error unsupported linux kernel version +#endif + +/* 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 + +/* 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 cdev *bf_cdev; + struct fasync_struct *async_queue; +}; + +static int bf_major; +static int bf_minor[BF_FPGA_MAX_DEVICE_CNT] = {0}; +static struct class *bf_class = NULL; +static char *intr_mode = NULL; + +static enum bf_intr_mode bf_intr_mode_default = BF_INTR_MODE_NONE; +static spinlock_t bf_nonisr_lock; + +/* dev->minor should index into this array */ +static struct bf_global bf_global[BF_FPGA_MAX_DEVICE_CNT]; + +static void bf_add_listener(struct bf_pci_dev *bfdev, + struct bf_listener *listener) { + struct bf_listener **cur_listener = &bfdev->listener_head; + + if (!listener) { + return; + } + spin_lock(&bf_nonisr_lock); + + while (*cur_listener) { + cur_listener = &((*cur_listener)->next); + } + *cur_listener = listener; + listener->next = NULL; + + spin_unlock(&bf_nonisr_lock); +} + +static void bf_remove_listener(struct bf_pci_dev *bfdev, + 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() + */ + if (!bfdev || !listener) { + return; + } + spin_lock(&bf_nonisr_lock); + + if (*cur_listener == listener) { + *cur_listener = listener->next; + } else { + while (*cur_listener) { + if ((*cur_listener)->next == listener) { + (*cur_listener)->next = listener->next; + break; + } + cur_listener = &((*cur_listener)->next); + } + listener->next = NULL; + } + + spin_unlock(&bf_nonisr_lock); +} + +/* a pool of minor numbers is maintained */ +/* return the first available minor number */ +static int bf_get_next_minor_no(int *minor) { + int i; + + spin_lock(&bf_nonisr_lock); + for (i = 0; i < BF_FPGA_MAX_DEVICE_CNT; i++) { + if (bf_minor[i] == 0) { + *minor = i; + bf_minor[i] = 1; /* mark it as taken */ + spin_unlock(&bf_nonisr_lock); + return 0; + } + } + *minor = -1; + spin_unlock(&bf_nonisr_lock); + return -1; +} + +/* return a minor number back to the pool for recycling */ +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 */ + } else { + bf_minor[minor] = 0; /* mark it as available */ + err = 0; + } + spin_unlock(&bf_nonisr_lock); + 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); +} + +/* + * 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; + } +} + +/** + * irqcontrol can be used to disable/enable interrupt from user space processes. + * + * @param bf_dev + * pointer to bf_pci_dev + * @param irq_state + * state value. 1 to enable interrupt, 0 to disable interrupt. + * + * @return + * - 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); +#else + for_each_pci_msi_entry(desc, pdev) bf_msix_mask_irq(desc, irq_state); +#endif + } + pci_cfg_access_unlock(pdev); + + return 0; +} + +/** + * 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. + */ + 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; +} + +/* Unmap previously ioremap'd resources */ +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); + } + } +} + +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) { + 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) { + atomic_inc(&(bfdev->info.event[vect_off])); + } + return ret; +} + +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) { + 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])) { + return POLLIN | POLLRDNORM; + } + } + return 0; +} + +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) { + 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, +#endif +}; + +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) { + return -EINVAL; + } + + mem = bfdev->info.mem + bar; + + if (mem->addr & ~PAGE_MASK) { + return -ENODEV; + } + 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); + + /* + * We cannot use the vm_iomap_memory() helper here, + * because vma->vm_pgoff is the map index we looked + * up above in bf_find_mem_index(), rather than an + * actual page offset into the mmap. + * + * 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); +} + +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) { + return -EINVAL; + } + + vma->vm_private_data = bfdev; + + bar = bf_find_mem_index(vma); + 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) { + return -EINVAL; + } + + return bf_mmap_physical(vma); +} + +static int bf_fasync(int fd, struct file *filep, int mode) { + int minor; + + if (!filep->private_data) { + return (-EINVAL); + } + minor = ((struct bf_listener *)filep->private_data)->minor; + if (minor >= BF_FPGA_MAX_DEVICE_CNT) { + return (-EINVAL); + } + if (mode == 0 && &bf_global[minor].async_queue == NULL) { + return 0; /* nothing to do */ + } + return (fasync_helper(fd, filep, mode, &bf_global[minor].async_queue)); +} + +static int bf_open(struct inode *inode, struct file *filep) { + struct bf_pci_dev *bfdev; + struct bf_listener *listener; + int i; + + bfdev = bf_global[iminor(inode)].bfdev; + listener = kmalloc(sizeof(*listener), GFP_KERNEL); + if (listener) { + listener->bfdev = bfdev; + listener->minor = bfdev->info.minor; + listener->next = NULL; + bf_add_listener(bfdev, listener); + 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); + } +} + +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 */ + if (listener->bfdev) { + bf_remove_listener(listener->bfdev, listener); + } + kfree(listener); + return 0; +} + +/* 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) { + 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 */ + 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) { + 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) { + return -EINVAL; + } + count = sizeof(s32) * BF_MSIX_ENTRY_CNT; + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + if (count < sizeof(s32) * BF_MSI_ENTRY_CNT) { + return -EINVAL; + } + count = sizeof(s32) * BF_MSI_ENTRY_CNT; + } else { + if (count < sizeof(s32)) { + return -EINVAL; + } + count = sizeof(s32); + } + + do { + set_current_state(TASK_INTERRUPTIBLE); + + 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; + cnt_match[i] = 1; + } else { + event_count[i] = 0; + cnt_match[i] = 0; + } + } + if (mismatch_found) { + __set_current_state(TASK_RUNNING); + if (copy_to_user(buf, &event_count, count)) { + retval = -EFAULT; + } 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]; + } + } + retval = count; + } + break; + } + + if (filep->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + break; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } while (1); + + __set_current_state(TASK_RUNNING); + + return retval; +} + +/* 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) { + 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) { + return -EIO; + } + + if (count != sizeof(s32)) { + return -EINVAL; + } + + if (copy_from_user(&int_en, buf, count)) { + return -EFAULT; + } + + /* clear pci_error_state */ + bfdev->info.pci_error_state = 0; + + ret = bf_pci_irqcontrol(bfdev, int_en); + + return ret ? ret : sizeof(s32); +} + +static long bf_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + + return (bf_fpga_ioctl(bfdev, cmd, 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, +}; + +static int bf_major_init(struct bf_pci_dev *bfdev, int minor) { + struct cdev *cdev; + static const char name[] = "bf_fpga"; + dev_t bf_dev = 0; + int result; + + result = alloc_chrdev_region(&bf_dev, 0, BF_FPGA_MAX_DEVICE_CNT, name); + if (result) { + return result; + } + + result = -ENOMEM; + cdev = cdev_alloc(); + if (!cdev) { + goto fail_dev_add; + } + cdev->ops = &bf_fops; + cdev->owner = THIS_MODULE; + kobject_set_name(&cdev->kobj, "%s", name); + result = cdev_add(cdev, bf_dev, BF_FPGA_MAX_DEVICE_CNT); + + if (result) { + goto fail_dev_add; + } + + bf_major = MAJOR(bf_dev); + bf_global[minor].bf_cdev = cdev; + return 0; + +fail_dev_add: + unregister_chrdev_region(bf_dev, BF_FPGA_MAX_DEVICE_CNT); + return result; +} + +static void bf_major_cleanup(struct bf_pci_dev *bfdev, int minor) { + unregister_chrdev_region(MKDEV(bf_major, 0), BF_FPGA_MAX_DEVICE_CNT); + cdev_del(bf_global[minor].bf_cdev); +} + +static int bf_init_cdev(struct bf_pci_dev *bfdev, int minor) { + int ret; + ret = bf_major_init(bfdev, minor); + if (ret) return ret; + + bf_class = class_create(THIS_MODULE, BF_CLASS_NAME); + if (!bf_class) { + printk(KERN_ERR "create_class failed for bf_fpga_dev\n"); + ret = -ENODEV; + goto err_class_register; + } + return 0; + +err_class_register: + bf_major_cleanup(bfdev, minor); + return ret; +} + +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 + * + * returns zero on success or a negative error code. + */ +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) { + return -EINVAL; + } + + init_waitqueue_head(&info->wait); + + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + atomic_set(&info->event[i], 0); + } + + if (bf_get_next_minor_no(&minor)) { + return -EINVAL; + } + + ret = bf_init_cdev(bfdev, minor); + if (ret) { + printk(KERN_ERR "BFi_FPGA: device cdev creation failed\n"); + return ret; + } + + info->dev = device_create( + bf_class, parent, MKDEV(bf_major, minor), bfdev, "bf_fpga_%d", minor); + if (!info->dev) { + printk(KERN_ERR "BF_FPGA: device creation failed\n"); + return -ENODEV; + } + + info->minor = minor; + + /* bind ISRs and request interrupts */ + if (info->irq && (bfdev->mode != BF_INTR_MODE_NONE)) { + /* + * Note that we deliberately don't use devm_request_irq + * here. The parent module can unregister the UIO device + * and call pci_disable_msi, which requires that this + * irq has been freed. However, the device may have open + * FDs at the time of unregister and therefore may not be + * freed until they are released. + */ + if (bfdev->mode == BF_INTR_MODE_LEGACY) { + ret = request_irq(info->irq, + bf_interrupt, + info->irq_flags, + bfdev->name, + (void *)&(bfdev->bf_int_vec[0])); + if (ret) { + printk(KERN_ERR "bf_fpga failed to request legacy irq %ld error %d\n", + info->irq, + ret); + return ret; + } + printk(KERN_NOTICE "BF_FPGA 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, + (void *)&(bfdev->bf_int_vec[i])); + if (ret) { + /* undo all other previous bindings */ + printk(KERN_ERR "bf_fpga failed to request MSIX ret %d itr %d\n", + ret, + i); + for (j = i - 1; j >= 0; j--) { + free_irq(info->msix_entries[j].vector, + (void *)&(bfdev->bf_int_vec[j])); + } + return ret; + } + } + printk(KERN_NOTICE "BF_FPGA allocating %d MSIx vectors from %ld\n", + 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, + (void *)&(bfdev->bf_int_vec[i])); + if (ret) { + /* undo all other previous bindings */ + printk( + KERN_ERR "bf_fpga failed to request MSI ret %d itr %d\n", ret, i); + for (j = i - 1; j >= 0; j--) { + free_irq(info->irq + j, (void *)&(bfdev->bf_int_vec[j])); + } + return ret; + } + } + printk(KERN_NOTICE "BF_FPGA allocating %d MSI vectors from %ld\n", + info->num_irq, + info->irq); + } + } + return 0; +} + +/** + * bf_unregister_device - register a new userspace mem device + * @bfdev: bf pci device + * + * returns none + */ +void bf_unregister_device(struct bf_pci_dev *bfdev) { + struct bf_dev_info *info = &bfdev->info; + int i; + + if (info->irq) { + if (bfdev->mode == BF_INTR_MODE_LEGACY) { + free_irq(info->irq, (void *)&(bfdev->bf_int_vec[0])); + } else if (bfdev->mode == BF_INTR_MODE_MSIX) { + for (i = 0; i < info->num_irq; i++) { + free_irq(info->msix_entries[i].vector, (void *)&(bfdev->bf_int_vec[i])); + } + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + for (i = 0; i < info->num_irq; i++) { + free_irq(info->irq + i, (void *)&(bfdev->bf_int_vec[i])); + } + } + } + device_destroy(bf_class, MKDEV(bf_major, info->minor)); + bf_remove_cdev(bfdev); + bf_return_minor_no(info->minor); + return; +} + +static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) { + return &pdev->dev; +} + +static void bf_fpga_disable_int_dma(struct bf_pci_dev *bfdev) { + u8 *bf_base_addr; + + /* maskinterrupts and DMA */ + bf_base_addr = (bfdev->info.mem[0].internal_addr); + /* return if called before mmap */ + if (!bf_base_addr) { + return; + } + /* mask interrupt at shadow level */ + /* TBD */ +} + +static void fpga_print_build_date(u32 build_date) { + char day, month, year, hr, min, sec; + + sec = (char)(build_date & 0x3f); + build_date >>= 6; + min = (char)(build_date & 0x3f); + build_date >>= 6; + hr = (char)(build_date & 0x1f); + build_date >>= 5; + year = (char)(build_date & 0x3f); + build_date >>= 6; + month = (char)(build_date & 0x0f); + build_date >>= 4; + day = (char)(build_date & 0x1f); + printk(KERN_ALERT "fpga version %02d/%02d/%2d %02d:%02d:%02d", + month, + day, + year, + hr, + min, + sec); +} + +static int bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { + struct bf_pci_dev *bfdev; + int err, pci_use_highmem; + int i, num_irq; + u32 build_date, build_ver; + + memset(bf_global, 0, sizeof(bf_global)); + + bfdev = kzalloc(sizeof(struct bf_pci_dev), GFP_KERNEL); + if (!bfdev) { + return -ENOMEM; + } + + /* init the cookies to be passed to ISRs */ + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + bfdev->bf_int_vec[i].int_vec_offset = i; + bfdev->bf_int_vec[i].bf_dev = bfdev; + } + + /* initialize intr_mode to none */ + bfdev->mode = BF_INTR_MODE_NONE; + + /* clear pci_error_state */ + bfdev->info.pci_error_state = 0; + + /* + * enable device + */ + err = pci_enable_device(pdev); + if (err != 0) { + printk(KERN_ERR "bf_fpga cannot enable PCI device\n"); + goto fail_free; + } + + /* + * reserve device's PCI memory regions for use by this + * module + */ + err = pci_request_regions(pdev, "bf_fpga_umem"); + if (err != 0) { + printk(KERN_ERR "bf_fpga Cannot request regions\n"); + goto fail_pci_disable; + } + /* remap IO memory */ + err = bf_setup_bars(pdev, &bfdev->info); + if (err != 0) { + printk(KERN_ERR "bf_fpga 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)); + if (err) { + printk(KERN_ERR "bf_fpga no usable DMA configuration, aborting\n"); + goto fail_release_iomem; + } + } + pci_use_highmem = 0; + } + + /* enable pci error reporting */ + /* for the current kernel version, kernel config must have set the followings: + * CONFIG_PCIEPORTBUS=y and CONFIG_PCIEAER = y + * we have pci_error_handlers defined that gets invoked by kernel AER module + * upon detecting the pcie error on this device's addresses. + * However, there seems no way that AER would pass the offending addresses + * to the callback functions. AER logs the error messages on the console. + * This driver's calback function send the SIGIO signal to the user space + * to indicate the error condition. + */ + pci_enable_pcie_error_reporting(pdev); + + bf_fpga_disable_int_dma(bfdev); + + /* enable bus mastering on the device */ + pci_set_master(pdev); + + /* fill in bfdev info */ + bfdev->info.version = "0.1"; + bfdev->info.owner = THIS_MODULE; + bfdev->pdev = pdev; + + 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; + } +#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) { + 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_fpga 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) { + 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_fpga 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_fpga error allocating MSIX vectors. Trying MSI...\n"); + /* and, fall back to MSI */ + } +#endif /* LINUX_VERSION_CODE */ + /* ** intentional no-break */ + 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) { + bfdev->info.num_irq = BF_MSI_ENTRY_CNT; + bfdev->info.irq = pdev->irq; + bfdev->mode = BF_INTR_MODE_MSI; + printk(KERN_DEBUG "bf_fpga using %d MSI irq from %ld\n", + bfdev->info.num_irq, + bfdev->info.irq); + 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) { + bfdev->info.num_irq = num_irq; + bfdev->info.irq = pdev->irq; + bfdev->mode = BF_INTR_MODE_MSI; + printk(KERN_DEBUG "bf_fpga 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) { + bfdev->info.num_irq = num_irq; + bfdev->info.irq = pci_irq_vector(pdev, 0); + bfdev->mode = BF_INTR_MODE_MSI; + printk(KERN_DEBUG "bf_fpga using %d MSI irq from %ld\n", + bfdev->info.num_irq, + bfdev->info.irq); + 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)) { + bfdev->info.irq_flags = IRQF_SHARED; + bfdev->info.irq = pdev->irq; + bfdev->mode = BF_INTR_MODE_LEGACY; + printk(KERN_DEBUG "bf_fpga using LEGACY irq %ld\n", bfdev->info.irq); + break; + } + printk(KERN_NOTICE "bf_fpga 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; + + default: + printk(KERN_DEBUG "bf_fpga invalid IRQ mode %u", bf_intr_mode_default); + err = -EINVAL; + goto fail_clear_pci_master; + } + + pci_set_drvdata(pdev, bfdev); + sprintf(bfdev->name, "bf_fpga%d", bfdev->info.minor); + /* register bf driver */ + err = bf_register_device(&pdev->dev, bfdev); + 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_fpga device %d registered with irq %ld\n", + bfdev->instance, + bfdev->info.irq); + if (fpga_i2c_init(bfdev->info.mem[0].internal_addr)) { + printk(KERN_ERR "bf_fpga i2c initialization failed\n"); + goto fail_register_device; + } + if (bf_fpga_sysfs_add(bfdev)) { + printk(KERN_ERR "bf_fpga stsfs initialization failed\n"); + goto fail_i2c_init; + } + build_ver = + *((u32 *)(bfdev->info.mem[0].internal_addr) + (BF_FPGA_VER_REG / 4)); + build_date = + *((u32 *)(bfdev->info.mem[0].internal_addr) + (BF_FPGA_BUILD_DATE / 4)); + fpga_print_build_date(build_date); + printk(KERN_ALERT "bf_fpga version %hu:%hu probe ok\n", + (u16)(build_ver >> 16), + (u16)(build_ver)); + return 0; + +fail_i2c_init: + fpga_i2c_deinit(); +fail_register_device: + bf_unregister_device(bfdev); +fail_release_irq: + pci_set_drvdata(pdev, NULL); + if (bfdev->mode == BF_INTR_MODE_MSIX) { + pci_disable_msix(bfdev->pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + pci_disable_msi(bfdev->pdev); + } +fail_clear_pci_master: + pci_clear_master(pdev); +fail_release_iomem: + bf_pci_release_iomem(&bfdev->info); + pci_release_regions(pdev); +fail_pci_disable: + pci_disable_device(pdev); +fail_free: + kfree(bfdev); + + printk(KERN_ERR "bf_fpga probe failed\n"); + return err; +} + +static void bf_pci_remove(struct pci_dev *pdev) { + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + struct bf_listener *cur_listener; + + bf_fpga_disable_int_dma(bfdev); + bf_fpga_sysfs_del(bfdev); + fpga_i2c_deinit(); + 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) { + pci_disable_msi(pdev); + } + pci_clear_master(pdev); + bf_pci_release_iomem(&bfdev->info); + pci_release_regions(pdev); + pci_disable_pcie_error_reporting(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + bf_global[bfdev->info.minor].bfdev = NULL; + /* existing filep structures in open file(s) must be informed that + * bf_pci_dev is no longer valid */ + spin_lock(&bf_nonisr_lock); + cur_listener = bfdev->listener_head; + while (cur_listener) { + cur_listener->bfdev = NULL; + cur_listener = cur_listener->next; + } + spin_unlock(&bf_nonisr_lock); + kfree(bfdev); + printk(KERN_ALERT "bf_fpga removed\n"); +} + +/** + * bf_pci_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current pci connection state + * + * 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) { + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + int minor; + + if (!bfdev) { + return PCI_ERS_RESULT_NONE; + } + printk(KERN_ERR "bf_fpga 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; + /* send a signal to the user space program of the error */ + minor = bfdev->info.minor; + if (minor < BF_FPGA_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; + } +} + +/** + * bf_pci_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. + */ +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 + * TBD: fill in this function if tofino can recover after an error + */ + return PCI_ERS_RESULT_DISCONNECT; +} + +/** + * bf_pci_resume - called when kernel thinks the device is up on PCIe. + * @pdev: Pointer to PCI device + * + * 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 BF FPGA */ + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + + printk(KERN_ERR "BF_FPGA io_resume invoked after pci error\n"); + if (bfdev) { + bfdev->info.pci_error_state = 0; + } +} + +static int bf_config_intr_mode(char *intr_str) { + if (!intr_str) { + pr_info("BF_FPGA Use MSI interrupt by default\n"); + return 0; + } + + if (!strcmp(intr_str, BF_INTR_MODE_MSIX_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_MSIX; + pr_info("BF_FPGA Use MSIX interrupt\n"); + } else if (!strcmp(intr_str, BF_INTR_MODE_MSI_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_MSI; + pr_info("BF_FPGA Use MSI interrupt\n"); + } else if (!strcmp(intr_str, BF_INTR_MODE_LEGACY_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_LEGACY; + pr_info("BF_FPGA Use legacy interrupt\n"); + } else if (!strcmp(intr_str, BF_INTR_MODE_NONE_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_NONE; + pr_info("BF_FPGA interrupt disabled\n"); + } else { + pr_info("Error: BF_FPGA bad intr_mode parameter - %s\n", intr_str); + return -EINVAL; + } + + return 0; +} + +static const struct pci_device_id bf_pci_tbl[] = { + {PCI_VDEVICE(BF, BF_FPGA_DEV_ID_JBAY_0), 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, +}; + +static struct pci_driver bf_pci_driver = {.name = "bf_fpga", + .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) { + int ret; + + ret = bf_config_intr_mode(intr_mode); + if (ret < 0) { + return ret; + } + spin_lock_init(&bf_nonisr_lock); + return pci_register_driver(&bf_pci_driver); +} + +static void __exit bfdrv_exit(void) { + pci_unregister_driver(&bf_pci_driver); + intr_mode = NULL; +} + +module_init(bfdrv_init); +module_exit(bfdrv_exit); + +module_param(intr_mode, charp, S_IRUGO); +MODULE_PARM_DESC(intr_mode, + "bf-fpga interrupt mode (default=none):\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 FPGA PCI-I2C device"); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION("0.1"); +MODULE_AUTHOR("Barefoot Networks"); diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_priv.h b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_priv.h new file mode 100644 index 000000000000..7515bde7458d --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_priv.h @@ -0,0 +1,141 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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_FPGA_H_ +#define _BF_FPGA_H_ + +#define PCI_VENDOR_ID_BF 0x1d1c +#define BF_FPGA_DEV_ID_JBAY_0 0x01F0 + +#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_fpga" +#define BF_FPGA_MAX_DEVICE_CNT 1 +#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 1 +#define BF_MSI_ENTRY_CNT 1 + +/* sysfs codes */ +#define BF_SYSFS_NEW_DEVICE 1 +#define BF_SYSFS_RM_DEVICE 0 +#define BF_SYSFS_I2C_START 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; +}; + +/* sysfs related structs */ +#define BF_FPGA_SYSFS_CNT 64 +#define BF_FPGA_SYSFS_NAME_SIZE 32 + +struct bf_fpga_sysfs_buff { + struct device_attribute dev_attr; + char name[BF_FPGA_SYSFS_NAME_SIZE]; + int bus_id; + unsigned char i2c_addr; + size_t i2c_rd_size; /* bytes to read from the device */ + int sysfs_code; /* unique code for each sysfs file */ + struct bf_pci_dev *fpgadev; /* back pointer */ + bool in_use; +}; + +/** + * 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 */ + struct bf_fpga_sysfs_buff fpga_sysfs_buff[BF_FPGA_SYSFS_CNT]; + struct bf_fpga_sysfs_buff fpga_sysfs_new_device; + struct bf_fpga_sysfs_buff fpga_sysfs_rm_device; + struct bf_fpga_sysfs_buff fpga_sysfs_st_i2c; + spinlock_t sysfs_slock; +}; + +int bf_fpga_ioctl(struct bf_pci_dev *bfdev, + unsigned int cmd, + unsigned long arg); +int bf_fpga_sysfs_add(struct bf_pci_dev *fpgadev); +void bf_fpga_sysfs_del(struct bf_pci_dev *fpgadev); + +#endif /* _BF_FPGA_H_ */ diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_sysfs.c b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_sysfs.c new file mode 100644 index 000000000000..6970a7a95985 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/bf_fpga_sysfs.c @@ -0,0 +1,335 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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 + +*******************************************************************************/ +#include +#include +#include +#include +#include +#include "bf_fpga_priv.h" +#include "bf_fpga_ioctl.h" +#include "i2c/bf_fpga_i2c.h" + +/* reads 1 byte from the i2c device */ +static ssize_t bf_fpga_sysfs_i2c_get(struct device *dev, + struct device_attribute *attr, + char *buf) { + bf_fpga_i2c_t i2c_op; + ssize_t size, cur_size; + struct bf_fpga_sysfs_buff *sysfs_buf = + container_of(attr, struct bf_fpga_sysfs_buff, dev_attr); + + if (!sysfs_buf) { + printk(KERN_ERR "fpga-i2c bad attr pointer in sysfs_read\n"); + return -ENXIO; /* something not quite right here; but, don't panic */ + } + i2c_op.num_i2c = 1; + i2c_op.one_time = 1; + i2c_op.inst_hndl.bus_id = sysfs_buf->bus_id; + i2c_op.i2c_inst[0].preemt = false; + i2c_op.i2c_inst[0].en = true; + i2c_op.i2c_inst[0].i2c_addr = sysfs_buf->i2c_addr; + i2c_op.i2c_inst[0].i2c_type = BF_FPGA_I2C_READ; + i2c_op.i2c_inst[0].delay = 0; + i2c_op.i2c_inst[0].wr_cnt = 0; + cur_size = sysfs_buf->i2c_rd_size; + /* limit to PAGE_SIZE per the sysfs contract */ + if (cur_size >= PAGE_SIZE) { + cur_size = PAGE_SIZE; + } + size = 0; + while (cur_size > 0) { + unsigned char cur_cnt; + if (cur_size > 64) { + cur_cnt = 64; + } else { + cur_cnt = (unsigned char)cur_size; + } + i2c_op.i2c_inst[0].rd_cnt = cur_cnt; + if (fpga_i2c_oneshot(&i2c_op)) { + printk(KERN_ERR + "fpga-i2c read one-shot error bus %d addr 0x%hhx status 0x%hhx\n", + i2c_op.inst_hndl.bus_id, + i2c_op.i2c_inst[0].i2c_addr, + i2c_op.i2c_inst[0].status); + return -EIO; + } + memcpy(buf, i2c_op.i2c_inst[0].rd_buf, cur_cnt); + buf += cur_cnt; + size += cur_cnt; + cur_size -= cur_cnt; + } + return size; +} + +/* write the number of bytes supplied to the i2c device, 1st byte has to be + the count(max 8) */ +static ssize_t bf_fpga_sysfs_i2c_set(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) { + bf_fpga_i2c_t i2c_op; + size_t size, cur_cnt; + struct bf_fpga_sysfs_buff *sysfs_buf = + container_of(attr, struct bf_fpga_sysfs_buff, dev_attr); + + if (!sysfs_buf || (count == 0)) { + printk(KERN_ERR "fpga-i2c bad attr pointer in sysfs_write\n"); + return -ENXIO; /* something not quite right here; but, don't panic */ + } + size = 0; + while (count > 0) { + if (count > 64) { + cur_cnt = 64; + } else { + cur_cnt = count; + } + i2c_op.i2c_inst[0].wr_cnt = cur_cnt; + i2c_op.i2c_inst[0].rd_cnt = 0; + memcpy(i2c_op.i2c_inst[0].wr_buf, buf, cur_cnt); + i2c_op.num_i2c = 1; + i2c_op.one_time = 1; + i2c_op.inst_hndl.bus_id = sysfs_buf->bus_id; + i2c_op.i2c_inst[0].preemt = false; + i2c_op.i2c_inst[0].en = true; + i2c_op.i2c_inst[0].i2c_addr = sysfs_buf->i2c_addr; + i2c_op.i2c_inst[0].i2c_type = BF_FPGA_I2C_WRITE; + i2c_op.i2c_inst[0].delay = 0; + if (fpga_i2c_oneshot(&i2c_op)) { + printk( + KERN_ERR + "fpga-i2c write one-shot error bus %d addr 0x%hhx status 0x%hhx\n", + i2c_op.inst_hndl.bus_id, + i2c_op.i2c_inst[0].i2c_addr, + i2c_op.i2c_inst[0].status); + return -EIO; + } + buf += cur_cnt; + size += cur_cnt; + count -= cur_cnt; + } + return size; +} + +static int find_matching_sysfs_buf(struct bf_pci_dev *fpgadev, + int bus_id, + unsigned char i2c_addr) { + int i; + + /* check if a sysfs entry already exists */ + for (i = 0; i < BF_FPGA_SYSFS_CNT; i++) { + if (fpgadev->fpga_sysfs_buff[i].bus_id == bus_id && + fpgadev->fpga_sysfs_buff[i].i2c_addr == i2c_addr) { + return i; + } + } + /* could not find a matching sysfs buffer */ + return -1; +} + +static ssize_t bf_fpga_sysfs_fixed_get(struct device *dev, + struct device_attribute *attr, + char *buf) { + (void)dev; + (void)attr; + (void)buf; + return -ENOSYS; +} + +static ssize_t bf_fpga_sysfs_fixed_set(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) { + struct bf_pci_dev *fpgadev; + int i, en, bus_id, ret, rd_size; + char fname[BF_FPGA_SYSFS_NAME_SIZE]; + unsigned char i2c_addr; + struct bf_fpga_sysfs_buff *new_buf; + struct bf_fpga_sysfs_buff *sysfs_buf = + container_of(attr, struct bf_fpga_sysfs_buff, dev_attr); + + if (!sysfs_buf || (count == 0)) { + printk(KERN_ERR "fpga i2c bad attr pointer in fixed_sysfs_write\n"); + return -ENXIO; /* something not quite right here; but, don't panic */ + } + fpgadev = sysfs_buf->fpgadev; + + switch (sysfs_buf->sysfs_code) { + case BF_SYSFS_NEW_DEVICE: /* new_device request */ + ret = sscanf(buf, "%s %d %hhx %d", fname, &bus_id, &i2c_addr, &rd_size); + /* default rd_size to 1 if not supplied or invalid */ + if (ret < 3) { + return -EINVAL; + } + if (ret < 4 || rd_size > PAGE_SIZE) { + rd_size = 1; + } + if (bus_id >= BF_I2C_FPGA_NUM_CTRL || i2c_addr >= 0x80) { + return -EINVAL; + } + /* find out the free sysfs_buffer to use */ + spin_lock(&fpgadev->sysfs_slock); + if (find_matching_sysfs_buf(fpgadev, bus_id, i2c_addr) != -1) { + /* there is already an matching entry */ + spin_unlock(&fpgadev->sysfs_slock); + return -ENOSPC; + } + for (i = 0; i < BF_FPGA_SYSFS_CNT; i++) { + if (!fpgadev->fpga_sysfs_buff[i].in_use) { + fpgadev->fpga_sysfs_buff[i].in_use = true; + new_buf = &fpgadev->fpga_sysfs_buff[i]; + new_buf->i2c_addr = i2c_addr; + new_buf->i2c_rd_size = (size_t)rd_size; + new_buf->bus_id = bus_id; + break; + } + } + spin_unlock(&fpgadev->sysfs_slock); + if (i >= BF_FPGA_SYSFS_CNT) { + /* no free buffer available, return with ERROR */ + return -ENOSPC; + } + /* create a new sysfs entry now */ + new_buf->dev_attr.show = bf_fpga_sysfs_i2c_get; + new_buf->dev_attr.store = bf_fpga_sysfs_i2c_set; + new_buf->fpgadev = fpgadev; + new_buf->dev_attr.attr.mode = S_IWUSR | S_IRUGO; + new_buf->sysfs_code = 0; + snprintf(new_buf->name, BF_FPGA_SYSFS_NAME_SIZE, "%s", fname); + new_buf->dev_attr.attr.name = new_buf->name; + ret = device_create_file(&(fpgadev->pdev->dev), &new_buf->dev_attr); + break; + + case BF_SYSFS_RM_DEVICE: /* remove device request */ + ret = sscanf(buf, "%d %hhx", &bus_id, &i2c_addr); + if (ret < 2) { + return -EINVAL; + } + if (bus_id >= BF_I2C_FPGA_NUM_CTRL || i2c_addr >= 0x80) { + return -EINVAL; + } + /* delete the sysfs file corresponding to the i2c address */ + spin_lock(&fpgadev->sysfs_slock); + i = find_matching_sysfs_buf(fpgadev, bus_id, i2c_addr); + if (i == -1) { + /* there is no matching entry */ + spin_unlock(&fpgadev->sysfs_slock); + return -EINVAL; + } + /* must invalidate bus_id and i2c_addr when marking the buffer + * not-in-use + */ + new_buf = &fpgadev->fpga_sysfs_buff[i]; + new_buf->i2c_addr = 0xff; + new_buf->bus_id = -1; + fpgadev->fpga_sysfs_buff[i].in_use = false; + spin_unlock(&fpgadev->sysfs_slock); + device_remove_file(&fpgadev->pdev->dev, &new_buf->dev_attr); + new_buf->name[0] = 0; /* nullify the name */ + ret = 0; + break; + + case BF_SYSFS_I2C_START: /* start-stop i2c request */ + ret = sscanf(buf, "%d %d", &bus_id, &en); + if (ret < 2) { + return -EINVAL; + } + if (bus_id >= BF_I2C_FPGA_NUM_CTRL) { + return -EINVAL; + } + if (en) { + ret = fpga_i2c_start(bus_id); + } else { + ret = fpga_i2c_stop(bus_id); + } + break; + + default: + ret = -EINVAL; + } + return ((ret == 0) ? count : ret); +} + +int bf_fpga_sysfs_add(struct bf_pci_dev *fpgadev) { + int rc = 0; + u8 *name; + + spin_lock_init(&fpgadev->sysfs_slock); + /* Add two sysfs files statically, new_device and remove_device. + * Handlers of these two fles can dynamically add more sysfs + * files (or remove files) based on the platform. + */ + fpgadev->fpga_sysfs_new_device.dev_attr.show = bf_fpga_sysfs_fixed_get; + fpgadev->fpga_sysfs_new_device.dev_attr.store = bf_fpga_sysfs_fixed_set; + fpgadev->fpga_sysfs_new_device.fpgadev = fpgadev; + fpgadev->fpga_sysfs_new_device.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + fpgadev->fpga_sysfs_new_device.sysfs_code = BF_SYSFS_NEW_DEVICE; + name = fpgadev->fpga_sysfs_new_device.name; + snprintf(name, BF_FPGA_SYSFS_NAME_SIZE, "new_device"); + fpgadev->fpga_sysfs_new_device.dev_attr.attr.name = name; + rc |= device_create_file(&(fpgadev->pdev->dev), + &fpgadev->fpga_sysfs_new_device.dev_attr); + + fpgadev->fpga_sysfs_rm_device.dev_attr.show = bf_fpga_sysfs_fixed_get; + fpgadev->fpga_sysfs_rm_device.dev_attr.store = bf_fpga_sysfs_fixed_set; + fpgadev->fpga_sysfs_rm_device.fpgadev = fpgadev; + fpgadev->fpga_sysfs_rm_device.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + fpgadev->fpga_sysfs_rm_device.sysfs_code = BF_SYSFS_RM_DEVICE; + name = fpgadev->fpga_sysfs_rm_device.name; + snprintf(name, BF_FPGA_SYSFS_NAME_SIZE, "remove_device"); + fpgadev->fpga_sysfs_rm_device.dev_attr.attr.name = name; + rc |= device_create_file(&(fpgadev->pdev->dev), + &fpgadev->fpga_sysfs_rm_device.dev_attr); + + /* sysfs for i2c start-stop control */ + fpgadev->fpga_sysfs_st_i2c.dev_attr.show = bf_fpga_sysfs_fixed_get; + fpgadev->fpga_sysfs_st_i2c.dev_attr.store = bf_fpga_sysfs_fixed_set; + fpgadev->fpga_sysfs_st_i2c.fpgadev = fpgadev; + fpgadev->fpga_sysfs_st_i2c.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + fpgadev->fpga_sysfs_st_i2c.sysfs_code = BF_SYSFS_I2C_START; + name = fpgadev->fpga_sysfs_st_i2c.name; + snprintf(name, BF_FPGA_SYSFS_NAME_SIZE, "i2c_start"); + fpgadev->fpga_sysfs_st_i2c.dev_attr.attr.name = name; + rc |= device_create_file(&(fpgadev->pdev->dev), + &fpgadev->fpga_sysfs_st_i2c.dev_attr); + + return rc; +} + +void bf_fpga_sysfs_del(struct bf_pci_dev *fpgadev) { + int i; + + device_remove_file(&fpgadev->pdev->dev, + &fpgadev->fpga_sysfs_new_device.dev_attr); + device_remove_file(&fpgadev->pdev->dev, + &fpgadev->fpga_sysfs_rm_device.dev_attr); + device_remove_file(&fpgadev->pdev->dev, &fpgadev->fpga_sysfs_st_i2c.dev_attr); + for (i = 0; i < BF_FPGA_SYSFS_CNT; i++) { + if (fpgadev->fpga_sysfs_buff[i].in_use) { + device_remove_file(&fpgadev->pdev->dev, + &fpgadev->fpga_sysfs_buff[i].dev_attr); + } + } +} diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c.c b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c.c new file mode 100644 index 000000000000..1a622e5392d6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c.c @@ -0,0 +1,516 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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 + +*******************************************************************************/ +#include +#include "bf_fpga_i2c_priv_porting.h" +#include +#include "bf_fpga_i2c_priv.h" +#include "bf_fpga_i2c.h" +#include "bf_fpga_i2c_reg.h" + +/* allocate find physically contiguous free blocks of instructions in one time + * or periodic area and mark them "in-use" */ +static int get_next_free_index(fpga_i2c_controller_t *i2c_ctrl, + int cnt, + bool pr) { + int i, j, begin, end; + + if (pr) { + begin = FPGA_I2C_PERIODIC_BEGIN_INDEX; + end = FPGA_I2C_NUM_INST; + } else { + begin = FPGA_I2c_ONESHOT_BEGIN_INDEX; + end = FPGA_I2C_ONESHOT_NUM_INST; + } + + bf_fpga_fast_lock(&i2c_ctrl->spinlock); + for (i = begin; i < end;) { + /* check if there are cnt number of free slots here */ + for (j = 0; j < cnt; j++) { + if (i2c_ctrl->i2c_inst[i + j].in_use) { + break; + } + } + if (j == cnt) { + /* we found enough free slots, so, return i */ + break; + } else { + /* we did not find enough free slots, continue searching */ + i += (j + 1); + continue; + } + } + if (i < end) { + for (j = 0; j < cnt; j++) { + i2c_ctrl->i2c_inst[i + j].in_use = true; + } + } else { + i = -1; + } + bf_fpga_fast_unlock(&i2c_ctrl->spinlock); + return i; +} + +/* free physically contiguous in-use blocks of instructions */ +static void release_index(fpga_i2c_controller_t *i2c_ctrl, + int inst_id, + int cnt) { + int i; + + if (inst_id < 0 || (inst_id + cnt) >= FPGA_I2C_NUM_INST) { + return; /* invalid id */ + } + bf_fpga_fast_lock(&i2c_ctrl->spinlock); + for (i = inst_id; i < (inst_id + cnt); i++) { + i2c_ctrl->i2c_inst[i].in_use = false; + } + bf_fpga_fast_unlock(&i2c_ctrl->spinlock); +} + +/* convert miroseconds to i2c-instruction delay parameter */ +static int us_to_fpga_delay(int microsec) { + int delay; + + if (microsec < 10) { + delay = 0; + } else if (microsec < 100) { + delay = 1; + } else if (microsec < 1000) { + delay = 2; + } else if (microsec < 10000) { + delay = 3; + } else if (microsec < 100000) { + delay = 4; + } else if (microsec < 1000000) { + delay = 5; + } else { + delay = 6; + } + return delay; +} + +/* populate single i2c_instruction at the given instruction slot */ +static int fpga_i2c_enqueue(int bus_id, + int inst_id, + bf_fpga_i2c_inst_t *i2c_inst) { + fpga_i2c_controller_t *i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + int delay = us_to_fpga_delay(i2c_inst->delay); + uint32_t wd0 = 0, wd1 = 0; + uint32_t i2c_data[2]; + uint8_t i2c_addr, num_wr, num_rd; + + i2c_addr = i2c_inst->i2c_addr; + num_wr = i2c_inst->wr_cnt; + num_rd = i2c_inst->rd_cnt; + if (i2c_addr > 0x7F || num_wr > 129 || num_rd > 128) { + return BF_FPGA_EINVAL; + } + if (i2c_inst->preemt) { + wd0 |= I2C_INST_PMT; + } + if (i2c_inst->en) { + wd0 |= I2C_INST_EN; + } + i2c_data[0] = i2c_data[1] = 0; /* clear on init */ + switch (i2c_inst->i2c_type) { + case BF_FPGA_I2C_NOP: + /* add delay + enable */ + wd0 |= (I2C_NOP | (delay << I2C_DELAY_SHF)); + break; + case BF_FPGA_I2C_WRITE: + if (num_wr == 0) { + return BF_FPGA_EINVAL; + } + wd0 |= (I2C_WR_ADDR_DATA | (delay << I2C_DELAY_SHF)); + wd1 |= (i2c_inst->i2c_addr << I2C_DEV_ADDR_SHF); + /* copy the first byte into register address */ + wd1 |= ((i2c_inst->wr_buf[0]) << I2C_CMD_OFFSET); + wd1 |= ((num_wr - 1) << I2C_WR_CNT_SHF); + if (num_wr <= 9) { + /* copy data into instruction area */ + memcpy(i2c_data, &i2c_inst->wr_buf[1], (num_wr - 1)); + bf_fpga_i2c_reg_write32( + i2c_ctrl, Bf_FPGA_I2C_INST_DATA_LO(inst_id), i2c_data[0]); + bf_fpga_i2c_reg_write32( + i2c_ctrl, Bf_FPGA_I2C_INST_DATA_HI(inst_id), i2c_data[1]); + } else { + /* copy the data in data area */ + int len = num_wr - 1; + uint32_t addr; + uint8_t *val = (uint8_t *)(&i2c_inst->wr_buf[1]); + /* store the data pointer Note the indexing required by FPGA specs */ + i2c_data[0] = BF_FPGA_I2C_DATA_AREA(inst_id); + addr = i2c_data[0]; + bf_fpga_i2c_reg_write32( + i2c_ctrl, Bf_FPGA_I2C_INST_DATA_LO(inst_id), i2c_data[0] / 4); + /* do byte write to avoid endianness mismatch */ + while (len--) { + bf_fpga_i2c_reg_write8(i2c_ctrl, addr, *val); + addr++; + val++; + } + } + break; + case BF_FPGA_I2C_READ: + if (num_rd == 0) { + return BF_FPGA_EINVAL; + } + wd0 |= (I2C_RD_DATA | (delay << I2C_DELAY_SHF)); + wd1 |= (i2c_inst->i2c_addr << I2C_DEV_ADDR_SHF); + wd1 |= ((num_rd) << I2C_RD_CNT_SHF); + if (num_rd > 8) { + /* store the data area pointer */ + i2c_data[0] = BF_FPGA_I2C_DATA_AREA(inst_id); + bf_fpga_i2c_reg_write32( + i2c_ctrl, Bf_FPGA_I2C_INST_DATA_LO(inst_id), i2c_data[0] / 4); + } + break; + case BF_FPGA_I2C_ADDR_READ: + if (num_wr == 0 || num_rd == 0) { + return BF_FPGA_EINVAL; + } + wd0 |= (I2C_RD_ADDR_DATA_BURST | (delay << I2C_DELAY_SHF)); + wd1 |= (i2c_inst->i2c_addr << I2C_DEV_ADDR_SHF); + /* 1st byte of the write buf goes into "register address" field */ + wd1 |= ((num_wr - 1) << I2C_WR_CNT_SHF); + wd1 |= ((i2c_inst->wr_buf[0]) << I2C_CMD_OFFSET); + wd1 |= ((num_rd) << I2C_RD_CNT_SHF); + /* less than 8 bytes data goes to the instruction area */ + if ((num_wr - 1 + num_rd) <= 8) { + memcpy(i2c_data, &i2c_inst->wr_buf[1], (num_wr - 1)); + bf_fpga_i2c_reg_write32( + i2c_ctrl, Bf_FPGA_I2C_INST_DATA_LO(inst_id), i2c_data[0]); + bf_fpga_i2c_reg_write32( + i2c_ctrl, Bf_FPGA_I2C_INST_DATA_HI(inst_id), i2c_data[1]); + } else { + int len = num_wr - 1; + uint32_t addr; + uint8_t *val = (uint8_t *)(&i2c_inst->wr_buf[1]); + /* store the data area pointer */ + i2c_data[0] = BF_FPGA_I2C_DATA_AREA(inst_id); + addr = i2c_data[0]; + bf_fpga_i2c_reg_write32( + i2c_ctrl, Bf_FPGA_I2C_INST_DATA_LO(inst_id), i2c_data[0] / 4); + /* copy the data in data area */ + while (len--) { + bf_fpga_i2c_reg_write8(i2c_ctrl, addr, *val); + addr++; + val++; + } + } + break; + default: + return BF_FPGA_EINVAL; + } + bf_fpga_i2c_reg_write32(i2c_ctrl, Bf_FPGA_I2C_INST_PARAM(inst_id), wd1); + bf_fpga_i2c_reg_write32(i2c_ctrl, Bf_FPGA_I2C_INST_CTRL(inst_id), wd0); + return BF_FPGA_OK; +} + +/* get the i2c completion status of a particular instruction */ +static uint32_t fpga_i2c_get_status(int bus_id, int inst_id) { + fpga_i2c_controller_t *i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + uint32_t addr = Bf_FPGA_I2C_INST_CTRL(inst_id); + return (bf_fpga_i2c_reg_read32(i2c_ctrl, addr) & I2C_STATUS_MASK); +} + +/** FPGA I2C data read (assumes locked by caller and no need to stop i2c) + * + * read the data following a read type i2c operation + * + * @param bus_id + * i2c controller id + * @param inst_id + * instruction id within this controller space + * @param offset + * offset in the data-area where read-data is available + * @param num_rd + * number of bytes to read + * @param rd_buf + * buffer to read into + * @return + * 0 on success and <0 on error + */ +static int fpga_i2c_data_read_locked(fpga_i2c_controller_t *i2c_ctrl, + int inst_id, + uint8_t offset, + uint8_t num_rd, + uint8_t *rd_buf) { + uint8_t i; + uint32_t addr, data_cnt; + + if (!i2c_ctrl || !rd_buf || !num_rd || inst_id < 0 || + inst_id >= FPGA_I2C_NUM_INST) { + return BF_FPGA_EINVAL; + } + /* find out the wr_cnt + rd_cnt from the already executed instruction field */ + data_cnt = bf_fpga_i2c_reg_read32(i2c_ctrl, Bf_FPGA_I2C_INST_PARAM(inst_id)); + /* point to data area if the (wr_cnt + rd_cnt) > 8 */ + data_cnt &= 0xffff; /* retain only the length fields */ + if (((data_cnt & 0xff) + (data_cnt >> 8)) <= 8) { + addr = Bf_FPGA_I2C_INST_DATA_LO(inst_id) + offset; + } else { + addr = BF_FPGA_I2C_DATA_AREA(inst_id) + offset; + } + for (i = 0; i < num_rd; i++) { + *rd_buf = bf_fpga_i2c_reg_read8(i2c_ctrl, addr); + addr++; + rd_buf++; + } + return BF_FPGA_OK; +} + +/** FPGA I2C data read + * + * read the data following a read type i2c operation + * + * @param bus_id + * i2c controller id + * @param inst_id + * instruction id within this controller space + * @param offset + * offset in the data-area where read-data is available + * @param num_rd + * number of bytes to read + * @param rd_buf + * buffer to read into + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_data_read( + int bus_id, int inst_id, uint8_t offset, uint8_t num_rd, uint8_t *rd_buf) { + fpga_i2c_controller_t *i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + int ret; + bool i2c_running; + uint8_t val; + + if (!i2c_ctrl || !rd_buf || !num_rd || inst_id < 0 || + inst_id >= FPGA_I2C_NUM_INST) { + return BF_FPGA_EINVAL; + } + + /* aligned (upto) 4 bytes can be read without stopping the ongoing i2c, + * this is guaranteed by FPGA design. i2c has to be stopped, in all other + * cases, to read a consistent set of read-data. + */ + if ((offset % 4 == 0) && (num_rd <= 4)) { + return ( + fpga_i2c_data_read_locked(i2c_ctrl, inst_id, offset, num_rd, rd_buf)); + } + + /* non-aligned case; stop i2c if running, read data and restart i2c */ + if (bf_fpga_i2c_lock(i2c_ctrl)) { + return BF_FPGA_EAGAIN; + } + /* check if i2c_controller is running */ + val = bf_fpga_i2c_reg_read8(i2c_ctrl, Bf_FPGA_TOP_I2C_STATUS); + i2c_running = ((val & I2C_STS_BUSY) ? true : false); + if (i2c_running) { + /* stop ongoing i2c operations */ + fpga_i2c_stop_locked(i2c_ctrl); + } + ret = fpga_i2c_data_read_locked(i2c_ctrl, inst_id, offset, num_rd, rd_buf); + if (i2c_running) { + /* restart ongoing i2c operations */ + fpga_i2c_start_locked(i2c_ctrl); + } + bf_fpga_i2c_unlock(i2c_ctrl); + return ret; +} + +/** FPGA I2C onetime i2c operation + * + * @param i2c_op + * bf_fpga_i2c_t parameters * + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_oneshot(bf_fpga_i2c_t *i2c_op) { + int i, ret; + uint32_t val; + int bus_id; + fpga_i2c_controller_t *i2c_ctrl; + + if (!i2c_op) { + return BF_FPGA_EINVAL; + } + + bus_id = i2c_op->inst_hndl.bus_id; + i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + + if (i2c_op->num_i2c == 0 || i2c_op->num_i2c >= FPGA_I2C_ONESHOT_NUM_INST || + i2c_op->one_time == 0 || bus_id >= BF_I2C_FPGA_NUM_CTRL || !i2c_ctrl) { + return BF_FPGA_EINVAL; + } + if (bf_fpga_i2c_lock(i2c_ctrl)) { + return BF_FPGA_EAGAIN; + } + /* stop ongoing i2c operations */ + ret = fpga_i2c_stop_locked(i2c_ctrl); + if (ret) { + bf_fpga_i2c_unlock(i2c_ctrl); + return ret; + } + /* populate one time i2c operation instruction(s) from offset zero */ + for (i = 0; i < i2c_op->num_i2c; i++) { + ret = fpga_i2c_enqueue(bus_id, i, &i2c_op->i2c_inst[i]); + if (ret) { + goto oneshot_error_exit; + } + } + /* start i2c operations */ + ret = fpga_i2c_start_locked(i2c_ctrl); + if (ret) { + goto oneshot_error_exit; + } + + /* wait until complete and read the data if necessary */ + for (i = 0; i < i2c_op->num_i2c; i++) { + int cnt; + val = 0; + /* cnt is roughly the number of bytes of this i2c cycle + * overhead of 100 bytes for for worst case timeout, one + * should not hit that in normal working case + */ + cnt = i2c_op->i2c_inst[i].wr_cnt + i2c_op->i2c_inst[i].rd_cnt; + /* bump up the cnt for an i2c transaction containing some data + * for computing worst case timeout */ + if (cnt > 0) { + cnt = cnt + 100; + } + while (!(val & I2C_STATUS_COMPLETED) && (cnt-- > 0)) { + /* 1 byte ~= 10 bits takes 25 microsec on i2c cycle at 400khz */ + bf_fpga_us_delay(50); + val = fpga_i2c_get_status(bus_id, i); + } + i2c_op->i2c_inst[i].status = val; /* store the h/w status */ + if (val & I2C_STATUS_ERR_MASK) { + ret = BF_FPGA_EIO; + goto oneshot_error_exit; + } + if (i2c_op->i2c_inst[i].rd_cnt) { + uint8_t offset = 0; + if (i2c_op->i2c_inst[i].wr_cnt > 1) { + offset = i2c_op->i2c_inst[i].wr_cnt - 1; + } + if (fpga_i2c_data_read_locked(i2c_ctrl, + i, + offset, + i2c_op->i2c_inst[i].rd_cnt, + i2c_op->i2c_inst[i].rd_buf)) { + ret = BF_FPGA_EIO; + goto oneshot_error_exit; + } + } + } + ret = BF_FPGA_OK; + +oneshot_error_exit: + for (i = 0; i < i2c_op->num_i2c; i++) { + /* cleanup the enable bit */ + val = bf_fpga_i2c_reg_read32(i2c_ctrl, Bf_FPGA_I2C_INST_CTRL(i)); + val &= (~I2C_INST_EN); + bf_fpga_i2c_reg_write32(i2c_ctrl, Bf_FPGA_I2C_INST_CTRL(i), val); + } + bf_fpga_i2c_unlock(i2c_ctrl); + return ret; +} + +/** FPGA I2C insert periodic i2c operation + * + * @param i2c_op + * bf_fpga_i2c_t parameters * + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_pr_add(bf_fpga_i2c_t *i2c_op) { + fpga_i2c_controller_t *i2c_ctrl; + int i, ret, next_id; + bool preemt; + + if (!i2c_op) { + return BF_FPGA_EINVAL; + } + i2c_ctrl = fpga_i2c_ctrl_get(i2c_op->inst_hndl.bus_id); + if (!i2c_ctrl) { + return BF_FPGA_EINVAL; + } + if (bf_fpga_i2c_lock(i2c_ctrl)) { + return BF_FPGA_EAGAIN; + } + /* get the next available free slot */ + next_id = get_next_free_index(i2c_ctrl, i2c_op->num_i2c, true); + if (next_id < 0) { + bf_fpga_i2c_unlock(i2c_ctrl); + return BF_FPGA_EBUSY; + } + /* populate periodic i2c operation instruction(s) */ + for (i = 0; i < i2c_op->num_i2c; i++) { + preemt = ((i == (i2c_op->num_i2c - 1)) ? false : true); + i2c_op->i2c_inst[i].preemt = preemt; + ret = fpga_i2c_enqueue( + i2c_op->inst_hndl.bus_id, next_id + i, &i2c_op->i2c_inst[i]); + + if (ret) { + bf_fpga_i2c_unlock(i2c_ctrl); + return ret; + } + } + bf_fpga_i2c_unlock(i2c_ctrl); + i2c_op->inst_hndl.inst_id = next_id; + return BF_FPGA_OK; +} + +/** FPGA I2C remove periodic i2c operation(s) from instruction memory + * + * @param i2c_op + * bf_fpga_i2c_t parameters * + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_del(bf_fpga_i2c_t *i2c_op) { + fpga_i2c_controller_t *i2c_ctrl; + int i, inst_id; + + if (!i2c_op) { + return BF_FPGA_EINVAL; + } + i2c_ctrl = fpga_i2c_ctrl_get(i2c_op->inst_hndl.bus_id); + if (!i2c_ctrl) { + return BF_FPGA_EINVAL; + } + inst_id = i2c_op->inst_hndl.inst_id; + if (bf_fpga_i2c_lock(i2c_ctrl)) { + return BF_FPGA_EAGAIN; + } + for (i = 0; i < i2c_op->num_i2c; i++) { + /* nullify the instruction */ + bf_fpga_i2c_reg_write32(i2c_ctrl, Bf_FPGA_I2C_INST_CTRL(inst_id + i), 0); + } + /* reset the in_use flag */ + release_index(i2c_ctrl, inst_id, i2c_op->num_i2c); + bf_fpga_i2c_unlock(i2c_ctrl); + return BF_FPGA_OK; +} diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c.h b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c.h new file mode 100644 index 000000000000..6f56ed270bdd --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c.h @@ -0,0 +1,55 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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_FPGA_I2C_H +#define _BF_FPGA_I2C_H + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" { +#endif + +int fpga_i2c_start(int bus_id); +int fpga_i2c_stop(int bus_id); +int fpga_i2c_reset(int bus_id); +int fpga_i2c_is_busy(int bus_id, bool *is_busy); +int fpga_i2c_inst_en(int bus_id, int inst_id, bool en); +int fpga_i2c_set_clk(int bus_id, int clock_div); +int fpga_i2c_controller_init(int bus_id); +int fpga_i2c_controller_cleanup(int bus_id); +int fpga_i2c_init(uint8_t *base_addr); +void fpga_i2c_deinit(void); +int fpga_i2c_oneshot(bf_fpga_i2c_t *i2c_op); +int fpga_i2c_pr_add(bf_fpga_i2c_t *i2c_op); +int fpga_i2c_del(bf_fpga_i2c_t *i2c_op); +int fpga_i2c_data_read( + int bus_id, int inst_id, uint8_t offset, uint8_t len, uint8_t *buf); +bool fpga_i2c_is_inited(void); + +#ifdef __cplusplus +} +#endif /* C++ */ + +#endif /* _BF_FPGA_I2C_H */ diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_ctrl.c b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_ctrl.c new file mode 100644 index 000000000000..a8837ba3b60c --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_ctrl.c @@ -0,0 +1,397 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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 + +*******************************************************************************/ +#include +#include "bf_fpga_i2c_priv_porting.h" +#include +#include "bf_fpga_i2c.h" +#include "bf_fpga_i2c_priv.h" +#include "bf_fpga_i2c_reg.h" + +/* static i2c controller contents */ +static fpga_i2c_controller_t fpga_i2c_ctrl[BF_I2C_FPGA_NUM_CTRL]; +static bool fpga_i2c_inited = false; + +/* fpga memory space access APIs */ +/* 32 bit write into fpga BAR0 */ +void bf_fpga_reg_write(fpga_i2c_controller_t *i2c_ctrl, + uint32_t offset, + uint32_t val) { + uint8_t *ptr = i2c_ctrl->fpga_base_addr + offset; + bf_fpga_write32(ptr, val); +} + +/* 32 bit read into fpga BAR0 */ +uint32_t bf_fpga_reg_read(fpga_i2c_controller_t *i2c_ctrl, uint32_t offset) { + uint8_t *ptr = i2c_ctrl->fpga_base_addr + offset; + return (bf_fpga_read32(ptr)); +} + +/* 32 bit write into fpga i2c space */ +void bf_fpga_i2c_reg_write32(fpga_i2c_controller_t *i2c_ctrl, + uint32_t offset, + uint32_t val) { + uint8_t *ptr = i2c_ctrl->i2c_base_addr + offset; + bf_fpga_write32(ptr, val); +} + +/* 32 bit read into fpga i2c space */ +uint32_t bf_fpga_i2c_reg_read32(fpga_i2c_controller_t *i2c_ctrl, + uint32_t offset) { + uint8_t *ptr = i2c_ctrl->i2c_base_addr + offset; + return (bf_fpga_read32(ptr)); +} + +/* 8 bit write into fpga i2c space */ +void bf_fpga_i2c_reg_write8(fpga_i2c_controller_t *i2c_ctrl, + uint32_t offset, + uint8_t val) { + uint8_t *ptr = i2c_ctrl->i2c_base_addr + offset; + bf_fpga_write8(ptr, val); +} + +/* 8 bit read into fpga i2c space */ +uint8_t bf_fpga_i2c_reg_read8(fpga_i2c_controller_t *i2c_ctrl, + uint32_t offset) { + uint8_t *ptr = i2c_ctrl->i2c_base_addr + offset; + return (bf_fpga_read8(ptr)); +} + +int bf_fpga_i2c_lock(fpga_i2c_controller_t *i2c_ctrl) { + return (bf_fpga_cr_enter(&i2c_ctrl->fpga_ctrl_lock)); +} + +void bf_fpga_i2c_unlock(fpga_i2c_controller_t *i2c_ctrl) { + return (bf_fpga_cr_leave(&i2c_ctrl->fpga_ctrl_lock)); +} + +/** FPGA return pointer to i2c_controller struct + * + * @param bus_id + * i2c controller id + * @return + * pointer to i2c_controller struct of + */ +fpga_i2c_controller_t *fpga_i2c_ctrl_get(int bus_id) { + if (bus_id >= BF_I2C_FPGA_NUM_CTRL) { + return NULL; + } else { + return &fpga_i2c_ctrl[bus_id]; + } +} + +/* is fpga module is soft inited */ +bool fpga_i2c_is_inited() { return fpga_i2c_inited; } + +/** FPGA I2C set clock: sets clock of i2c operations + * + * controller must be stopped before, if applicable. + * + * @param bus_id + * i2c controller id + * @param clk_div + * clock divider value as per fpga specs + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_set_clk(int bus_id, int clk_div) { + uint32_t val; + fpga_i2c_controller_t *i2c_ctrl; + + if (bus_id >= BF_I2C_FPGA_NUM_CTRL) { + return BF_FPGA_EINVAL; + } + i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + if (bf_fpga_i2c_lock(i2c_ctrl)) { + return BF_FPGA_EAGAIN; + } + clk_div = (clk_div & I2C_CTRL_CLK_DIV_MASK) << I2C_CTRL_CLK_DIV_SHF; + val = bf_fpga_i2c_reg_read32(i2c_ctrl, Bf_FPGA_I2C_CTRL_TOP); + val &= ~(I2C_CTRL_CLK_DIV_MASK << I2C_CTRL_CLK_DIV_SHF); + val |= clk_div; + bf_fpga_i2c_reg_write32(i2c_ctrl, Bf_FPGA_I2C_CTRL_TOP, val); + bf_fpga_i2c_unlock(i2c_ctrl); + return BF_FPGA_OK; +} + +/** FPGA I2C stop : stops ongoing i2c operations without mutex locking + * + * internal function + * + * @param bus_id + * i2c controller struct + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_stop_locked(fpga_i2c_controller_t *i2c_ctrl) { + int to_ms, ret; + uint8_t val; + + val = bf_fpga_i2c_reg_read8(i2c_ctrl, Bf_FPGA_I2C_CTRL_TOP); + val &= ~I2C_CTRL_START; + bf_fpga_i2c_reg_write8(i2c_ctrl, Bf_FPGA_I2C_CTRL_TOP, val); + + to_ms = 100; /* 5 msec converted to multiple of 50 micro sec */ + val = bf_fpga_i2c_reg_read8(i2c_ctrl, Bf_FPGA_TOP_I2C_STATUS); + while ((val & I2C_STS_BUSY) && to_ms) { + bf_fpga_us_delay(50); + to_ms--; + val = bf_fpga_i2c_reg_read8(i2c_ctrl, Bf_FPGA_TOP_I2C_STATUS); + } + if (to_ms > 0) { + ret = BF_FPGA_OK; + } else { + ret = BF_FPGA_EIO; + } + return ret; +} + +/** FPGA I2C start : starts i2c operations without mutex locking + * + * internal function + * + * @param bus_id + * i2c controller struct + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_start_locked(fpga_i2c_controller_t *i2c_ctrl) { + uint8_t val; + val = bf_fpga_i2c_reg_read8(i2c_ctrl, Bf_FPGA_I2C_CTRL_TOP); + bf_fpga_i2c_reg_write8(i2c_ctrl, Bf_FPGA_I2C_CTRL_TOP, val | I2C_CTRL_START); + return BF_FPGA_OK; +} + +/** FPGA I2C stop : stops ongoing i2c operations + * + * @param bus_id + * i2c controller id + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_stop(int bus_id) { + fpga_i2c_controller_t *i2c_ctrl; + int ret; + + if (bus_id >= BF_I2C_FPGA_NUM_CTRL || !fpga_i2c_is_inited()) { + return BF_FPGA_EINVAL; + } + i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + if (bf_fpga_i2c_lock(i2c_ctrl)) { + return BF_FPGA_EAGAIN; + } + ret = fpga_i2c_stop_locked(i2c_ctrl); + bf_fpga_i2c_unlock(i2c_ctrl); + return ret; +} + +/** FPGA I2C start : starts i2c operations + * + * @param bus_id + * i2c controller id + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_start(int bus_id) { + fpga_i2c_controller_t *i2c_ctrl; + int ret; + + if (bus_id >= BF_I2C_FPGA_NUM_CTRL || !fpga_i2c_is_inited()) { + return BF_FPGA_EINVAL; + } + i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + if (bf_fpga_i2c_lock(i2c_ctrl)) { + return BF_FPGA_EAGAIN; + } + ret = fpga_i2c_start_locked(i2c_ctrl); + bf_fpga_i2c_unlock(i2c_ctrl); + return ret; +} + +/** FPGA I2C reset: reset i2c by issuing 9 clocks in a specific way + * + * @param bus_id + * i2c controller id + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_reset(int bus_id) { + fpga_i2c_controller_t *i2c_ctrl; + + if (bus_id >= BF_I2C_FPGA_NUM_CTRL || !fpga_i2c_is_inited()) { + return BF_FPGA_EINVAL; + } + i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + if (bf_fpga_i2c_lock(i2c_ctrl)) { + return BF_FPGA_EAGAIN; + } + bf_fpga_i2c_reg_write8(i2c_ctrl, Bf_FPGA_I2C_CTRL_TOP, I2C_CTRL_RESET); + bf_fpga_i2c_unlock(i2c_ctrl); + return BF_FPGA_OK; +} + +/** FPGA I2C is running? + * + * @param bus_id + * i2c controller id + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_is_busy(int bus_id, bool *busy) { + uint8_t val; + fpga_i2c_controller_t *i2c_ctrl; + + if (bus_id >= BF_I2C_FPGA_NUM_CTRL || !fpga_i2c_is_inited()) { + return BF_FPGA_EINVAL; + } + i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + if (bf_fpga_i2c_lock(i2c_ctrl)) { + return BF_FPGA_EAGAIN; + } + val = bf_fpga_i2c_reg_read8(i2c_ctrl, Bf_FPGA_TOP_I2C_STATUS); + *busy = ((val & I2C_STS_BUSY) ? true : false); + bf_fpga_i2c_unlock(i2c_ctrl); + return BF_FPGA_OK; +} + +/** FPGA I2C instruction enable/disable + * + * enable or disable a particular instruction in i2c instruction memory + * @param bus_id + * i2c controller id + * @param inst_id + * instruction id within this controller space + * @param en + * true for enable, false for disable + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_inst_en(int bus_id, int inst_id, bool en) { + uint32_t val; + fpga_i2c_controller_t *i2c_ctrl; + + if (bus_id >= BF_I2C_FPGA_NUM_CTRL || !fpga_i2c_is_inited()) { + return BF_FPGA_EINVAL; + } + if (inst_id < 0 || inst_id >= FPGA_I2C_NUM_INST) { + return BF_FPGA_EINVAL; + } + i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + if (bf_fpga_i2c_lock(i2c_ctrl)) { + return BF_FPGA_EAGAIN; + } + val = bf_fpga_i2c_reg_read32(i2c_ctrl, Bf_FPGA_I2C_INST_CTRL(inst_id)); + if (en) { + val |= I2C_INST_EN; + } else { + val &= ~I2C_INST_EN; + } + bf_fpga_i2c_reg_write32(i2c_ctrl, Bf_FPGA_I2C_INST_CTRL(inst_id), val); + fpga_i2c_ctrl[bus_id].i2c_inst[inst_id].en = en; + bf_fpga_i2c_unlock(i2c_ctrl); + return BF_FPGA_OK; +} + +/** FPGA I2C controller initialization + * + * @param bus_id + * i2c controller id + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_controller_init(int bus_id) { + fpga_i2c_controller_t *i2c_ctrl; + int i, ret; + + if (bus_id >= BF_I2C_FPGA_NUM_CTRL) { + return BF_FPGA_EINVAL; + } + i2c_ctrl = fpga_i2c_ctrl_get(bus_id); + if (!i2c_ctrl) { + return BF_FPGA_EINVAL; + } + bf_fpga_fast_lock_init(&i2c_ctrl->spinlock, 0); + bf_fpga_cr_init(&i2c_ctrl->fpga_ctrl_lock); + bf_fpga_cr_enter(&i2c_ctrl->fpga_ctrl_lock); + for (i = 0; i < FPGA_I2C_NUM_INST; i++) { + fpga_i2c_ctrl[bus_id].i2c_inst[i].inst = (uint32_t)i; + bf_fpga_i2c_reg_write32(i2c_ctrl, Bf_FPGA_I2C_INST_CTRL(i), 0); + } + bf_fpga_cr_leave(&i2c_ctrl->fpga_ctrl_lock); + ret = fpga_i2c_set_clk(bus_id, 1); /* 400 khz default */ + ret |= fpga_i2c_stop(bus_id); /* just in case */ + return ret; +} + +/** FPGA I2C controller de initialization + * + * @param bus_id + * i2c controller id + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_controller_cleanup(int bus_id) { + int i; + + fpga_i2c_stop(bus_id); + for (i = 0; i < FPGA_I2C_NUM_INST; i++) { + fpga_i2c_ctrl[bus_id].i2c_inst[i].en = false; + } + bf_fpga_cr_destroy(&fpga_i2c_ctrl[bus_id].fpga_ctrl_lock); + bf_fpga_fast_lock_destroy(&fpga_i2c_ctrl[bus_id].spinlock); + return BF_FPGA_OK; +} + +/** FPGA I2C global initialization + * + * @param base_addr + * virtual address of i2c memory relative to BAR0 base + * @return + * 0 on success and <0 on error + */ +int fpga_i2c_init(uint8_t *base_addr) { + int i; + + memset(fpga_i2c_ctrl, 0, sizeof(fpga_i2c_ctrl)); + for (i = 0; i < BF_I2C_FPGA_NUM_CTRL; i++) { + fpga_i2c_ctrl[i].i2c_base_addr = base_addr + BF_FPGA_I2C_CTRL_BASE_ADDR(i); + fpga_i2c_ctrl[i].fpga_base_addr = base_addr; + fpga_i2c_controller_init(i); + } + fpga_i2c_inited = true; + return BF_FPGA_OK; +} + +/** FPGA I2C global de initialization + * + */ +void fpga_i2c_deinit(void) { + int i; + + for (i = 0; i < BF_I2C_FPGA_NUM_CTRL; i++) { + fpga_i2c_controller_cleanup(i); + } + fpga_i2c_inited = false; +} diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_porting.c b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_porting.c new file mode 100644 index 000000000000..8b126c2e6dce --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_porting.c @@ -0,0 +1,150 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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 + +*******************************************************************************/ +#include +#include +#include +#include +#include +#include "bf_fpga_i2c_priv_porting.h" +#include +#include "bf_fpga_i2c.h" +#include "bf_fpga_i2c_priv.h" + +/* This file contains OS and system specific porting functions for i2c APIs. + * Implementation in this file is for porting to linux kernel. + */ +/* mutex APIs are for mutual exclusion with capability to sleep while in + * exclusion mode + */ + +/* sleepable virtual exclusion region */ +typedef struct { + atomic_t lock_state; /* 1: in exclusion mode, 0: not in exclusion mode */ +} sleepable_v_mutex_t; + +int bf_fpga_cr_init(bf_fpga_mutex_t *lock) { + sleepable_v_mutex_t *mtx; + + if (!lock) { + return -1; + } + mtx = vzalloc(sizeof(sleepable_v_mutex_t)); + + if (mtx) { + atomic_set(&mtx->lock_state, 0); + *lock = (bf_fpga_mutex_t *)mtx; + return 0; + } else { + *lock = NULL; + return -1; + } +} + +void bf_fpga_cr_destroy(bf_fpga_mutex_t *lock) { + if (lock && *lock) { + vfree(*lock); + *lock = NULL; + } +} + +void bf_fpga_cr_leave(bf_fpga_mutex_t *lock) { + sleepable_v_mutex_t *mtx; + + if (lock && *lock) { + mtx = (sleepable_v_mutex_t *)*lock; + atomic_xchg(&mtx->lock_state, 0); + } +} + +int bf_fpga_cr_enter(bf_fpga_mutex_t *lock) { + sleepable_v_mutex_t *mtx; + + /* All we do here is: test and set */ + if (lock && *lock) { + int cnt = 10000; /* This will provide maximum of 500-1000 ms timeout */ + mtx = (sleepable_v_mutex_t *)*lock; + while (atomic_cmpxchg(&mtx->lock_state, 0, 1) != 0) { + if (cnt-- <= 0) { + return -1; /* this is a worst case timeout situation */ + } + usleep_range(50, 100); /* 50 us = about 2 bytes at 400Kbs i2c */ + } + return 0; + } else { + return -1; + } +} + +/* **** not implemented in current mode of locking */ +int bf_fpga_mutex_trylock(bf_fpga_mutex_t *lock) { + if (lock && *lock) { + return -1; + } else { + return -1; + } +} + +/* fast lock is a non-blocking busy lock, implemented with spinlock */ +int bf_fpga_fast_lock_init(bf_fpga_fast_lock_t *sl, unsigned int initial) { + spinlock_t *slock; + + (void)initial; + if (!sl) { + return -1; + } + slock = vzalloc(sizeof(spinlock_t)); + + if (slock) { + spin_lock_init(slock); + *sl = (bf_fpga_fast_lock_t *)slock; + return 0; + } else { + *sl = NULL; + return -1; + } +} + +void bf_fpga_fast_lock_destroy(bf_fpga_fast_lock_t *sl) { + if (sl && *sl) { + vfree(*sl); + *sl = NULL; + } +} + +int bf_fpga_fast_lock(bf_fpga_fast_lock_t *sl) { + if (sl && *sl) { + spin_lock(*sl); + return 0; + } else { + return -1; + } +} + +void bf_fpga_fast_unlock(bf_fpga_fast_lock_t *sl) { + if (sl && *sl) { + spin_unlock(*sl); + } +} diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_priv.h b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_priv.h new file mode 100644 index 000000000000..0b3b1e47b015 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_priv.h @@ -0,0 +1,104 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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_FPGA_I2C_PRIV_H +#define _BF_FPGA_I2C_PRIV_H + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" { +#endif + +#define FPGA_I2C_INST_OFFSET(idx) (0x10 + (16 * idx)) + +typedef enum { + FGPA_I2C_NOP = 0x0, + FGPA_I2C_WR_ADDR_DATA = 0x1, /* wr: reg_addr, wr: data */ + FGPA_I2C_WR_ADDR_RD_DATA = 0x2, /* wr: reg_addrss, r/s, rd: data */ + FGPA_I2C_WR_ADDR = 0x3, /* wr: reg_addr */ + FGPA_I2C_RD_DATA = 0x4, /* rd: data */ + FGPA_I2C_MULTI_WR_RD = 0x5 /* wr: n bytes, r/s, rd: m bytes */ +} i2c_cmd_type; + +/* contents of each instruction instance */ +typedef struct i2c_inst_cmd_s { + i2c_cmd_type i2c_cmd; /* i2x cycle type */ + uint32_t data_lo; /* lower 4 bytes of data associated with this inst */ + uint32_t data_hi; /* upper 4 bytes of data associated with this inst */ + uint32_t us_delay; /* delay before i2c cycle */ + uint8_t i2c_addr; /* i2c device address, in 7 bit format */ + uint8_t reg_addr; /* 1st write byte, if present in i2c cycle */ + uint8_t num_read; /* number of bytes to write excluding reg_addr */ + uint8_t num_write; /* number of bytes to read */ +} i2c_inst_cmd_t; + +/* attributes of each instruction instance */ +typedef struct i2c_inst_s { + uint32_t inst; /* index of the instruction within the controller memory */ + bool en; /* is instruction enabled */ + bool preemt; /* atomically execute next instruction */ + bool int_en; /* enable interrupt after execution */ + bool in_use; /* is this instruction currently used */ +} i2c_inst_t; + +typedef struct fpga_i2c_controller_s { + bf_fpga_mutex_t fpga_ctrl_lock; + bf_fpga_fast_lock_t spinlock; + uint8_t *fpga_base_addr; /* virtual address of start of fpga memory */ + uint8_t *i2c_base_addr; /* virtual address of i2c controller memory */ + uint32_t start; /* offset of start of i2c instruction memory */ + uint32_t len; /* number of i2c instructions belonging to this i2c engine */ + uint32_t clk_div; /* clock divider used by this i2c engine */ + bool int_en; + i2c_inst_t i2c_inst[FPGA_I2C_NUM_INST]; +} fpga_i2c_controller_t; + +fpga_i2c_controller_t *fpga_i2c_ctrl_get(int bus_id); +void bf_fpga_reg_write(fpga_i2c_controller_t *i2c_ctrl, + uint32_t offset, + uint32_t val); +uint32_t bf_fpga_reg_read(fpga_i2c_controller_t *i2c_ctrl, uint32_t offset); +void bf_fpga_i2c_reg_write32(fpga_i2c_controller_t *i2c_ctrl, + uint32_t offset, + uint32_t val); +uint32_t bf_fpga_i2c_reg_read32(fpga_i2c_controller_t *i2c_ctrl, + uint32_t offset); +void bf_fpga_i2c_reg_write8(fpga_i2c_controller_t *i2c_ctrl, + uint32_t offset, + uint8_t val); +uint8_t bf_fpga_i2c_reg_read8(fpga_i2c_controller_t *i2c_ctrl, uint32_t offset); + +int bf_fpga_i2c_lock(fpga_i2c_controller_t *i2c_ctrl); + +void bf_fpga_i2c_unlock(fpga_i2c_controller_t *i2c_ctrl); + +int fpga_i2c_start_locked(fpga_i2c_controller_t *i2c_ctrl); +int fpga_i2c_stop_locked(fpga_i2c_controller_t *i2c_ctrl); + +#ifdef __cplusplus +} +#endif /* C++ */ + +#endif /* _BF_FPGA_I2C_PRIV_H */ diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_priv_porting.h b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_priv_porting.h new file mode 100644 index 000000000000..adea5c9311fa --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_priv_porting.h @@ -0,0 +1,93 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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_FPGA_I2C_PRIV_PORTING_H +#define _BF_FPGA_I2C_PRIV_PORTING_H + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* This file contains OS and system specific porting functions declarations. + */ +/* return status compliant with linux system calls */ +#define BF_FPGA_OK 0 +#define BF_FPGA_EINVAL (-EINVAL) +#define BF_FPGA_EIO (-EIO) +#define BF_FPGA_EBUSY (-EBUSY) +#define BF_FPGA_EAGAIN (-EAGAIN) + +/* pci memory access functions */ +static inline void bf_fpga_write32(uint8_t *addr, uint32_t val) { + u8 __iomem *reg_addr = addr; + writel(val, reg_addr); +} + +static inline uint32_t bf_fpga_read32(uint8_t *addr) { + u8 __iomem *reg_addr = addr; + return (readl(reg_addr)); +} + +static inline void bf_fpga_write8(uint8_t *addr, uint8_t val) { + u8 __iomem *reg_addr = addr; + writeb(val, reg_addr); +} + +static inline uint8_t bf_fpga_read8(uint8_t *addr) { + u8 __iomem *reg_addr = addr; + return (readb(reg_addr)); +} + +static inline void bf_fpga_us_delay(unsigned long usecs) { + usleep_range(usecs, usecs + 10); +} + +/* general purpose mutual exclusion lock */ +typedef void *bf_fpga_mutex_t; + +/* fast_lock for locking only non-blocking and quick operations */ +typedef void *bf_fpga_fast_lock_t; + +/* APIs to init/enter/leave critical (exclusive access) regions */ +int bf_fpga_cr_init(bf_fpga_mutex_t *lock); +void bf_fpga_cr_destroy(bf_fpga_mutex_t *lock); +int bf_fpga_cr_enter(bf_fpga_mutex_t *lock); +void bf_fpga_cr_leave(bf_fpga_mutex_t *lock); + +int bf_fpga_fast_lock_init(bf_fpga_fast_lock_t *sl, unsigned int initial); +void bf_fpga_fast_lock_destroy(bf_fpga_fast_lock_t *sl); +int bf_fpga_fast_lock(bf_fpga_fast_lock_t *sl); +void bf_fpga_fast_unlock(bf_fpga_fast_lock_t *sl); + +#ifdef __cplusplus +} +#endif /* C++ */ + +#endif /* _BF_FPGA_I2C_PRIV_PORTING_H */ diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_reg.h b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_reg.h new file mode 100644 index 000000000000..9ad9b31b3b3f --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/modules/i2c/bf_fpga_i2c_reg.h @@ -0,0 +1,116 @@ +/******************************************************************************* + Barefoot Networks FPGA Linux driver + Copyright(c) 2018 - 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_FPGA_I2C_REG_H +#define _BF_FPGA_I2C_REG_H + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" { +#endif + +/* registers outsize of all i2c controller register space */ +#define BF_FPGA_I2C_BASE_ADDR 0x0 +#define BF_FPGA_I2C_CTRL_BASE_ADDR(i) (BF_FPGA_I2C_BASE_ADDR + (i * 4096)) + +/* per i2c controller register offset relative to BF_FPGA_I2C_CTRL_BASE_ADDR */ +#define Bf_FPGA_I2C_CTRL_TOP 0 +#define I2C_CTRL_START (1 << 0) +#define I2C_CTRL_RESET (1 << 1) +#define I2C_CTRL_CLK_DIV_SHF (8) +#define I2C_CTRL_CLK_DIV_MASK (0x1FF) + +#define Bf_FPGA_TOP_I2C_STATUS 4 +#define I2C_STS_BUSY (1 << 0) +#define I2C_STS_ERR (1 << 3) + +#define Bf_FPGA_I2C_INST_CTRL(i) (0x10 + (16 * i)) +#define I2C_INST_EN (1 << 31) +#define I2C_INST_PMT (1 << 30) +#define I2C_TYPE_SHF (26) +#define I2C_DELAY_SHF (23) +#define I2C_STOP_ON_ERROR (22) +/* various status values */ +#define I2C_STATUS_MASK 0x3F +#define I2C_STATUS_ERR_MASK 0x3C +#define I2C_STATUS_RUNNING 0x1 +#define I2C_STATUS_COMPLETED 0x2 +#define I2C_STATUS_NACK_ADDR 0x4 +#define I2C_STATUS_NACK_CMD 0x8 +#define I2C_STATUS_NACK_WR_DATA 0x10 +#define I2C_STATUS_TOUT 0x20 + +/* i2c instruction types */ +#define I2C_WR_ADDR_DATA (0 << I2C_TYPE_SHF) +#define I2C_RD_DATA (3 << I2C_TYPE_SHF) +#define I2C_WR_ADDR (2 << I2C_TYPE_SHF) +#define I2C_RD_ADDR_DATA (1 << I2C_TYPE_SHF) +#define I2C_RD_ADDR_DATA_BURST (4 << I2C_TYPE_SHF) +#define I2C_NOP (6 << I2C_TYPE_SHF) + +#define Bf_FPGA_I2C_INST_PARAM(i) (0x14 + (16 * i)) +#define I2C_DEV_ADDR_SHF (24) +#define I2C_CMD_OFFSET (16) +#define I2C_WR_CNT_SHF (8) +#define I2C_RD_CNT_SHF (0) + +#define Bf_FPGA_I2C_INST_DATA_LO(i) (0x18 + (16 * i)) +#define Bf_FPGA_I2C_INST_DATA_HI(i) (0x1C + (16 * i)) +/****************** +#define Bf_FPGA_I2C_PR_CTRL(i) (0x100 + (16 * i)) +#define Bf_FPGA_I2C_PR_PARM(i) (0x104 + (16 * i)) +#define Bf_FPGA_I2C_PR_LO(i) (0x108 + (16 * i)) +#define Bf_FPGA_I2C_PR_HI(i) (0x10C + (16 * i)) +******************/ + +/* data area pointers */ +/* the driver makes fixed static allocation of the available memory + * on per instruction basis + * allocate 128 bytes per one time instruction = total 0x780 bytes + * allocate 64 bytes per one periodic instruction = total 0x400 bytes + * FPGA_I2C_ONESHOT_NUM_INST -> comes from a header file that must be included + * before this file. + */ +#define BF_FPGA_ONE_MAX_BURST 128 +#define BF_FPGA_PR_MAX_BURST 64 +#define BF_FPGA_I2C_DATA_AREA(i) \ + ((i < FPGA_I2C_ONESHOT_NUM_INST) \ + ? (0x200 + (i * BF_FPGA_ONE_MAX_BURST)) \ + : (0x980 + ((i - FPGA_I2C_ONESHOT_NUM_INST) * BF_FPGA_PR_MAX_BURST))) + +#if BF_FPGA_I2C_DATA_AREA(FPGA_I2C_PERIODIC_NUM_INST) > 0x1000 +#error erroneous allocation of FPGA memory to i2c data area. Fix it! +#endif + +#define BF_FPGA_VER_REG 0x3F000 +#define BF_FPGA_BUILD_DATE 0x3F004 +#define BF_FPGA_RESET_CTRL_1 0x3F008 +#define BF_FPGA_RESET_CTRL_2 0x3F00C + +#ifdef __cplusplus +} +#endif /* C++ */ + +#endif /* _BF_FPGA_I2C_REG_H */ diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/scripts b/platform/barefoot/sonic-platform-modules-bfn-newport/scripts new file mode 120000 index 000000000000..14008f061862 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/scripts @@ -0,0 +1 @@ +../sonic-platform-modules-bfn-montara/scripts \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/setup.py b/platform/barefoot/sonic-platform-modules-bfn-newport/setup.py new file mode 120000 index 000000000000..a68e2eec6762 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/setup.py @@ -0,0 +1 @@ +../sonic-platform-modules-bfn-montara/setup.py \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/sonic_platform b/platform/barefoot/sonic-platform-modules-bfn-newport/sonic_platform new file mode 120000 index 000000000000..b2918418aad1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/sonic_platform @@ -0,0 +1 @@ +../sonic-platform-modules-bfn-montara/sonic_platform \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-bfn/LICENSE b/platform/barefoot/sonic-platform-modules-bfn/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn/MAINTAINERS b/platform/barefoot/sonic-platform-modules-bfn/MAINTAINERS new file mode 100644 index 000000000000..b9c62ce01546 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/MAINTAINERS @@ -0,0 +1,4 @@ +# This file describes the maintainers for sonic-platform-modules-bfn +# See the SONiC project governance document for more information + +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/barefoot/sonic-platform-modules-bfn/README.md b/platform/barefoot/sonic-platform-modules-bfn/README.md new file mode 100644 index 000000000000..5dc055a1d9c3 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-bfn +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/sonic-platform-modules-bfn/configs/network/interfaces.d/usb0 b/platform/barefoot/sonic-platform-modules-bfn/configs/network/interfaces.d/usb0 new file mode 100644 index 000000000000..f1dd054cc6f6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/configs/network/interfaces.d/usb0 @@ -0,0 +1,5 @@ +# BMC interface +auto usb0 +allow-hotplug usb0 +iface usb0 inet6 +up ifconfig usb0 txqueuelen 64 diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/changelog b/platform/barefoot/sonic-platform-modules-bfn/debian/changelog new file mode 100644 index 000000000000..984cc0dbfb69 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/changelog @@ -0,0 +1,11 @@ +sonic-platform-modules-bfn (1.1) unstable; urgency=low + + * Remove bfn asic kernel modules from platform package + + -- Support Mon, 22 Oct 2018 15:40:00 -0800 + +sonic-platform-modules-bfn (1.0) unstable; urgency=low + + * Initial release + + -- Support Mon, 11 Nov 2015 11:11:11 -0800 diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/compat b/platform/barefoot/sonic-platform-modules-bfn/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/control b/platform/barefoot/sonic-platform-modules-bfn/debian/control new file mode 100644 index 000000000000..89c597303a78 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/control @@ -0,0 +1,12 @@ +Source: sonic-platform-modules-bfn +Section: main +Priority: extra +Maintainer: support +Build-Depends: debhelper (>= 9.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-modules-bfn +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/copyright b/platform/barefoot/sonic-platform-modules-bfn/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/files b/platform/barefoot/sonic-platform-modules-bfn/debian/files new file mode 100644 index 000000000000..1cfb92c60ae1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/files @@ -0,0 +1 @@ +platform-modules-bfn_1.0_amd64.deb main extra diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/postinst b/platform/barefoot/sonic-platform-modules-bfn/debian/postinst new file mode 100644 index 000000000000..bd24c078778a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/postinst @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +PLATFORM_NAME=x86_64-accton_wedge100bf_65x-r0 +SONIC_PLATFORM_WHEEL_PY2="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py2-none-any.whl" +python2 -m pip install ${SONIC_PLATFORM_WHEEL_PY2} +SONIC_PLATFORM_WHEEL_PY3="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py3-none-any.whl" +python3 -m pip install ${SONIC_PLATFORM_WHEEL_PY3} + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/prerm b/platform/barefoot/sonic-platform-modules-bfn/debian/prerm new file mode 100755 index 000000000000..ee19dbb1db98 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/prerm @@ -0,0 +1,6 @@ +#!/bin/sh + +python2 -m pip uninstall -y sonic-platform +python3 -m pip uninstall -y sonic-platform + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/rules b/platform/barefoot/sonic-platform-modules-bfn/debian/rules new file mode 100755 index 000000000000..0ee3dcfaf0e2 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/rules @@ -0,0 +1,36 @@ +#!/usr/bin/make -f + +PLATFORM_NAME := x86_64-accton_wedge100bf_65x-r0 +PACKAGE_NAME := sonic-platform-modules-bfn +SCRIPT_SRC := $(shell pwd)/scripts +CONFIGS_SRC := $(shell pwd)/configs +BUILD_DIR := $(shell pwd)/build +WHEEL_BUILD_DIR := $(BUILD_DIR)/wheel + +%: + dh $@ + +override_dh_auto_build: + set -e + python2.7 setup.py bdist_wheel -d $(WHEEL_BUILD_DIR) + python3 setup.py bdist_wheel -d $(WHEEL_BUILD_DIR) + set +e + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin + dh_installdirs -p$(PACKAGE_NAME) etc/network/interfaces.d/ + cp -r $(CONFIGS_SRC)/network/interfaces.d/* debian/$(PACKAGE_NAME)/etc/network/interfaces.d/ + dh_installdirs -p$(PACKAGE_NAME) usr/share/sonic/device/$(PLATFORM_NAME)/ + cp -r $(WHEEL_BUILD_DIR)/* debian/$(PACKAGE_NAME)/usr/share/sonic/device/$(PLATFORM_NAME)/ + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + rm -fr $(WHEEL_BUILD_DIR) + rm -fr *.egg-info + rm -fr $(BUILD) + dh_clean + diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts b/platform/barefoot/sonic-platform-modules-bfn/scripts new file mode 120000 index 000000000000..14008f061862 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts @@ -0,0 +1 @@ +../sonic-platform-modules-bfn-montara/scripts \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-bfn/setup.py b/platform/barefoot/sonic-platform-modules-bfn/setup.py new file mode 120000 index 000000000000..a68e2eec6762 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/setup.py @@ -0,0 +1 @@ +../sonic-platform-modules-bfn-montara/setup.py \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-bfn/sonic_platform b/platform/barefoot/sonic-platform-modules-bfn/sonic_platform new file mode 120000 index 000000000000..b2918418aad1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/sonic_platform @@ -0,0 +1 @@ +../sonic-platform-modules-bfn-montara/sonic_platform \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/.gitignore b/platform/barefoot/sonic-platform-modules-ingrasys/.gitignore new file mode 100644 index 000000000000..c6127b38c1aa --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/.gitignore @@ -0,0 +1,52 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/LICENSE b/platform/barefoot/sonic-platform-modules-ingrasys/LICENSE new file mode 100644 index 000000000000..9cecc1d4669e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/changelog b/platform/barefoot/sonic-platform-modules-ingrasys/debian/changelog new file mode 100644 index 000000000000..cfbeb17d018a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/changelog @@ -0,0 +1,11 @@ +platform-driver (1.1.0) unstable; urgency=low + + * Add support for s9180-32x s9280-64x + + -- developer Fri, 26 May 2017 11:00:00 +0800 + +platform-driver (1.0.0) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- developer Wed, 05 Oct 2016 16:30:45 +0800 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/compat b/platform/barefoot/sonic-platform-modules-ingrasys/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/control b/platform/barefoot/sonic-platform-modules-ingrasys/debian/control new file mode 100644 index 000000000000..a912ed8ace2e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/control @@ -0,0 +1,14 @@ +Source: platform-driver +Section: unknown +Priority: optional +Maintainer: Wade He +Build-Depends: debhelper (>= 9), dh-systemd +Standards-Version: 1.0.0 + +Package: sonic-platform-ingrasys-s9180-32x +Architecture: amd64 +Description: This package contains S9180-32X platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s9280-64x +Architecture: amd64 +Description: This package contains S9280-64X platform driver utility for SONiC project. diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/rules b/platform/barefoot/sonic-platform-modules-ingrasys/debian/rules new file mode 100755 index 000000000000..428b4731eb75 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/rules @@ -0,0 +1,42 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_PRE_NAME := sonic-platform-ingrasys +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= s9180-32x s9280-64x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CONF_DIR := conf + +%: + dh $@ --with systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/sbin; \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.sh \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/sbin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + done) + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.init b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.init new file mode 100644 index 000000000000..9479fa354949 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9180-32X board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9180-32x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9280-64x.init b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9280-64x.init new file mode 100644 index 000000000000..545ec8e9987a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9280-64x.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9280-64X board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9280-64x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/README.md b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/README.md new file mode 100644 index 000000000000..fa3760ab9ab7 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/README.md @@ -0,0 +1,185 @@ +# Ingrasys S9180-32X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9180-32X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9180-32X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9180-32X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S9180-32X. + +### I2C iSMT + +The I2C iSMT module on S9180-32X can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S9180-32X. + +### I2C PCA9548 +The PCA9548 module on S9180-32X can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9180-32X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9180-32X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9180 package is installed on the S9180-32X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon3/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon3/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/Makefile b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/Makefile new file mode 100644 index 000000000000..df7bfd3e770e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m := eeprom_mb.o +obj-m+= cpld_wdt.o + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/cpld_wdt.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/cpld_wdt.c new file mode 100644 index 000000000000..4cf70b4b80ab --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/cpld_wdt.c @@ -0,0 +1,296 @@ +/* + * CPLD Watchdog Driver + * + * Copyright (c) 2018 Ingrasys Corp. + * + * Author: Wade He + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Includes, defines, variables, module parameters, ... + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +/* Module and version information */ +#define DRV_NAME "cpld_wdt" +#define DRV_VERSION "1.0" + +/* Includes */ +#include /* For module specific items */ +#include /* For new moduleparam's */ +#include /* For standard types (like size_t) */ +#include /* For the -ENODEV/... values */ +#include /* For printk/panic/... */ +#include /* For the watchdog specific items */ +#include /* For __init/__exit/... */ +#include /* For file operations */ +#include /* For platform_driver framework */ +#include /* For pci functions */ +#include /* For io-port access */ +#include /* For spin_lock/spin_unlock/... */ +#include /* For copy_to_user/put_user/... */ +#include /* For inb/outb/... */ +#include +#include +#include +#include + + +/* Address definitions for the CPLD */ +/* CPLD base address */ +#define TCOBASE 0x600 +/* SMI Control and Enable Register */ + +#define TCO_RLD (TCOBASE + 0x00) /* TCO Timer Reload and Curr. Value */ +#define TCOv1_TMR (TCOBASE + 0x01) /* TCOv1 Timer Initial Value */ +#define TCO_DAT_IN (TCOBASE + 0x02) /* TCO Data In Register */ +#define TCO_DAT_OUT (TCOBASE + 0x03) /* TCO Data Out Register */ +#define TCO1_STS (TCOBASE + 0x04) /* Control Watchdog Register */ +#define TCO2_STS (TCOBASE + 0x06) /* TCO2 Status Register */ +#define TCO1_CNT (TCOBASE + 0x08) /* TCO1 Control Register */ +#define TCO2_CNT (TCOBASE + 0x0a) /* TCO2 Control Register */ +#define TCOv2_TMR (TCOBASE + 0x12) /* TCOv2 Timer Initial Value */ + +#define DEBUG +#ifdef DEBUG + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define ERROR_MSG(fmt, args...) \ + printk(KERN_ERR "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) + + + +/* internal variables */ +static struct { /* this is private data for the cpld_wdt device */ + /* the lock for io operations */ + spinlock_t io_lock; + struct platform_device *dev; +} cpld_wdt_private; + +static struct task_struct *cpld_wdt_tsk; +static int data; + +static void device_release(struct device *dev) +{ + return; +} + +static struct platform_device cpld_wdt = { + .name = DRV_NAME, + .id = 0, + .dev = { + .platform_data = NULL, + .release = device_release + }, +}; + +/* module parameters */ +#define WATCHDOG_TIMEOUT 15 /* 15 sec default heartbeat */ +static int heartbeat = WATCHDOG_TIMEOUT; /* in seconds */ +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog ping period in seconds. " + "5..20, default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + + +static int cpld_wdt_check_timeout_range(unsigned int tmrval) +{ + if (tmrval < 5 || tmrval > 20) { + DEBUG_PRINT("heartbeat out of range, using default=%d\n", WATCHDOG_TIMEOUT); + heartbeat = WATCHDOG_TIMEOUT; + } else { + DEBUG_PRINT("heartbeat using %d seconds\n", heartbeat); + } + + return 0; +} + +/* + * Some TCO specific functions + */ + +static int cpld_wdt_stop(void *arg) +{ + + spin_lock(&cpld_wdt_private.io_lock); + + outb(0x1, TCO1_STS); + + DEBUG_PRINT("cpld_wdt_stop done"); + + spin_unlock(&cpld_wdt_private.io_lock); + + return 0; +} + +static int cpld_wdt_ping(void *arg) +{ + spin_lock(&cpld_wdt_private.io_lock); + + /* Reload the timer by writing to the TCO Timer Counter register */ + outb(0x1, TCO1_STS); /* write 1 to clear bit */ + udelay(100); + outb(0x3, TCO1_STS); + + DEBUG_PRINT("cpld_wdt_ping done"); + + spin_unlock(&cpld_wdt_private.io_lock); + return 0; +} + +static int kthread_wdt_ping_loop(void *arg) +{ + int i; + + set_current_state(TASK_INTERRUPTIBLE); + + while(!kthread_should_stop()) { + DEBUG_PRINT("ping start"); + cpld_wdt_ping(NULL); + set_current_state(TASK_INTERRUPTIBLE); + for (i=0;i"); +MODULE_DESCRIPTION("CPLD Watchdog Timer Kernel Driver"); +MODULE_VERSION(DRV_VERSION); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/eeprom_mb.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/eeprom_mb.c new file mode 100644 index 000000000000..61f0caf96130 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/eeprom_mb.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/qsfp-monitor.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/qsfp-monitor.service new file mode 100644 index 000000000000..fde9dcf9f50a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9180-32x-monitor.service +After=s9180-32x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/s9180-32x-monitor.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/s9180-32x-monitor.service new file mode 100644 index 000000000000..884284b241ad --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/s9180-32x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9180_32x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/i2c_utils.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/i2c_utils.sh new file mode 100755 index 000000000000..d8e5778f4b0e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/i2c_utils.sh @@ -0,0 +1,1721 @@ +#!/bin/bash + +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.1.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +QSFP_PORT=${2} +QSFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +COLOR_PORT_LED=${3} +ONOFF_LED=${3} +COLOR_SYS_LED=${2} +BLINK_LED=${4} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 # Main I2C +NUM_MUX1_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) # zQSFP I/O 0-7 +NUM_MUX1_CHAN1_DEVICE=$(( ${NUM_MUX1_CHAN0_DEVICE} + 1 )) # zQSFP I/O 8-15 +NUM_MUX1_CHAN2_DEVICE=$(( ${NUM_MUX1_CHAN1_DEVICE} + 1 )) # zQSFP I/O 16-23 +NUM_MUX1_CHAN3_DEVICE=$(( ${NUM_MUX1_CHAN2_DEVICE} + 1 )) # zQSFP I/O 24-31 +NUM_MUX1_CHAN4_DEVICE=$(( ${NUM_MUX1_CHAN3_DEVICE} + 1 )) # zQSFP I/O ABS#, INT +NUM_MUX1_CHAN5_DEVICE=$(( ${NUM_MUX1_CHAN4_DEVICE} + 1 )) # zQSFP I/O LPMODE, RST, MODSEL +NUM_MUX1_CHAN6_DEVICE=$(( ${NUM_MUX1_CHAN5_DEVICE} + 1 )) # MAC CLK CPLD +NUM_MUX1_CHAN7_DEVICE=$(( ${NUM_MUX1_CHAN6_DEVICE} + 1 )) # P1V0 PWR +NUM_MUX3_CHAN0_DEVICE=$(( ${NUM_MUX1_CHAN7_DEVICE} + 1 )) # zQSFP I/O 0-7 +NUM_MUX4_CHAN0_DEVICE=$(( ${NUM_MUX3_CHAN0_DEVICE} + 8 )) # zQSFP I/O 8-15 +NUM_MUX5_CHAN0_DEVICE=$(( ${NUM_MUX4_CHAN0_DEVICE} + 8 )) # zQSFP I/O 16-23 +NUM_MUX6_CHAN0_DEVICE=$(( ${NUM_MUX5_CHAN0_DEVICE} + 8 )) # zQSFP I/O 24-31 +NUM_MUX7_CHAN0_DEVICE=$(( ${NUM_MUX6_CHAN0_DEVICE} + 8 )) # Temp Sensor 0x48-0x4D +NUM_MAIN_MUX_CHAN0_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 8 )) # System LED HWMON +NUM_MAIN_MUX_CHAN1_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 1 )) # System LED +NUM_MAIN_MUX_CHAN2_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 2 )) # Board ID +NUM_MAIN_MUX_CHAN3_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 3 )) # MAX_Slave +NUM_MAIN_MUX_CHAN4_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 4 )) # TEMP Sensor +NUM_MAIN_MUX_CHAN5_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 5 )) # CLK GEN +NUM_MAIN_MUX_CHAN6_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 6 )) # VDD CORE +NUM_MAIN_MUX_CHAN7_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 7 )) # HWMON +NUM_FRU_MUX_CHAN0_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 8 )) # PSU2 +NUM_FRU_MUX_CHAN1_DEVICE=$(( ${NUM_FRU_MUX_CHAN0_DEVICE} + 1 )) # PSU1 +NUM_FRU_MUX_CHAN2_DEVICE=$(( ${NUM_FRU_MUX_CHAN0_DEVICE} + 2 )) # FAN +NUM_CPLD_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 3 )) # CPLD +NUM_SFP1_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 4 )) # CPLD +NUM_SFP2_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 5 )) # CPLD +NUM_ROV_DEVICE=${NUM_MAIN_MUX_CHAN6_DEVICE} + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +PATH_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" +PATH_MUX_CHAN1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN1_DEVICE}" +PATH_MUX_CHAN2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN2_DEVICE}" +PATH_MUX_CHAN3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}" +PATH_MUX_CHAN4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN4_DEVICE}" +PATH_MUX_CHAN5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN5_DEVICE}" +PATH_MUX_CHAN6_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}" +PATH_MUX_CHAN7_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}" +PATH_MUX7_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX7_CHAN0_DEVICE}" +PATH_MAIN_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN0_DEVICE}" + +# i2c address for deviecs +CPLD_I2C_ADDR=0x33 +ROV_I2C_ADDR=0x22 + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# vdd value for mac +rov_val_array=( 0.85 0.82 0.77 0.87 0.74 0.84 0.79 0.89 ) +rov_reg_array=( 0x24 0x21 0x1c 0x26 0x19 0x23 0x1e 0x28 ) + +#GPIO Offset +GPIO_OFFSET=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "# Version : ${VERSION}" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cpu_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-34]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_sfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_psu_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-34]" + echo " : ${0} i2c_qsfp_type_get [1-34]" + echo " : ${0} i2c_qsfp_ddm_get [1-34]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_port_led_set [1-34] green|yellow|off blink|noblink" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber" + echo " : ${0} i2c_psu2_led green|amber" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod eeprom + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + #modprobe cpld_wdt + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x70' > ${PATH_I801_DEVICE}/new_device" + else + echo "${PATH_I801_DEVICE} 0x70 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX3_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN0_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN0_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX4_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN1_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN1_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX5_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN2_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN2_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX6_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN3_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN3_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX7_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN6_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN6_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x76' > ${PATH_I801_DEVICE}/new_device" + else + echo "${PATH_MAIN_MUX_CHAN0_DEVICE} 0x76 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9545 0x72' > ${PATH_I801_DEVICE}/new_device" + else + echo "${PATH_MAIN_MUX_CHAN0_DEVICE} 0x72 already init." + fi + + rmmod coretemp + rmmod jc42 + rmmod w83795 + rmmod lm75 + rmmod lm90 + rmmod eeprom + modprobe coretemp + modprobe w83795 + modprobe lm75 + modprobe lm90 + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_io_exp_init + _i2c_fan_init + _i2c_volmon_init + _i2c_fan_speed_init + _i2c_temp_init + modprobe jc42 + rmmod gpio_ich + _i2c_gpio_init + modprobe gpio_ich + _i2c_mb_eeprom_init "new" + _i2c_qsfp_eeprom_init "new" + _i2c_sfp_eeprom_init "new" + _i2c_psu_eeprom_init "new" + _i2c_led_psu_status_set + _i2c_led_fan_status_set + _i2c_led_fan_tray_status_set + + # rov for mac init + _mac_vdd_init + + #SYS LED set green + COLOR_SYS_LED="green" + _i2c_sys_led + +} + +function _mac_vdd_init { + # read mac vid register value from CPLD + val=`i2cget -y ${NUM_CPLD_DEVICE} ${CPLD_I2C_ADDR} 0x42 2>/dev/null` + + # get vid form register value [0:2] + vid=$(($val & 0x7)) + + # get rov val and reg according to vid + rov_val=${rov_val_array[$vid]} + rov_reg=${rov_reg_array[$vid]} + echo "vid=${vid}, rov_val=${rov_val}, rov_reg=${rov_reg}" + + # write the rov reg to rov + i2cset -y -r ${NUM_ROV_DEVICE} ${ROV_I2C_ADDR} 0x21 ${rov_reg} w + + if [ $? -eq 0 ]; then + echo "set ROV for mac vdd done" + else + echo "set ROV for mac vdd fail" + fi +} + +#I2C Deinit +function _i2c_deinit { + _i2c_gpio_deinit + for mod in coretemp jc42 w83795 lm75 lm90 eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_ismt i2c_i801; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done +} + +#FAN Init +function _i2c_fan_speed_init { + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi + +} + +#VOLMON Init +function _i2c_volmon_init { + echo "VOLMON INIT..." + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x01 0x1C + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x02 0xFF + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x03 0x50 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x04 0x0A + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x01 0x1D + + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MAIN_MUX_CHAN7_DEVICE}-0x2f" + if ! [ -L ${dev_path} ]; then + echo "w83795adg 0x2f" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN7_DEVICE}/new_device #hwmon + else + echo "${dev_path} already exist" + fi + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + + #Golden Finger to active CPLD + i2cget -y ${NUM_CPLD_DEVICE} 0x74 2 + #BMC dummy board reset + echo "BMC dummy board reset" + i2cset -y -r ${NUM_I801_DEVICE} 0x26 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x26 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x26 2 0x3F + i2cset -y -r ${NUM_I801_DEVICE} 0x26 3 0x1F + i2cset -y -r ${NUM_I801_DEVICE} 0x26 6 0xD0 + i2cset -y -r ${NUM_I801_DEVICE} 0x26 7 0x00 + + #CPU Baord + i2cset -y -r ${NUM_I801_DEVICE} 0x77 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x77 7 0xFF + + #SMBUS1 + #ABS + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 7 0xFF + + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 7 0xFF + + #Transcevior INT + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 7 0xFF + + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 2 0xCF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 3 0xF0 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 6 0xCF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 7 0xF0 + + #SFP+ PRES, TX FAULT, TX DIS, RX LOS, RS, TS + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 6 0xCF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 7 0xF0 + + + echo "Init ZQSFP IO Expender" + echo "set ZQSFP LP_MODE = 0" + #set ZQSFP LP_MODE = 0 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 7 0x00 + + echo "set ZQSFP RST = 1" + #set ZQSFP RST = 1 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 3 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 3 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 7 0x00 + + #0.0: TH_RST_L - 0:Reset + #0.1: TH_PCIE_RST_L - 0:Reset + #0.2: LED_CLR - 0: Off, 1:On + #0.3: Host to BMC + #0.4: UART_SEL - 0:Host + #0.5: USB_SEL - 0: Host + #0.[7:6]: TH_CLK_FSEL (00) + #1.0: TH_INT_L + #1.1: QSFP0_INT_L - 0:Interrupt + #1.2: QSFP1_INT_L - 0:Interrupt + #1.3: QSFP2_INT_L - 0:Interrupt + #1.4: QSFP3_INT_L - 0:Interrupt + #1.5: TH_CLK_SEL (0) + #1.6: I210_RST_L - 0:Reset + #1.6: I210_PE_RST_L - 0:Reset + echo "Init HOST GPIO" + i2cset -y -r ${NUM_I801_DEVICE} 0x74 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x74 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x74 2 0x0F + i2cset -y -r ${NUM_I801_DEVICE} 0x74 3 0xDF + i2cset -y -r ${NUM_I801_DEVICE} 0x74 6 0x08 + i2cset -y -r ${NUM_I801_DEVICE} 0x74 7 0x1F + + + #LED board after PVT (BAREFOOT_IO_EXP_LED_ID) + echo "Init LED IO Expender" + echo "LED_CHANNEL=${NUM_MAIN_MUX_CHAN1_DEVICE}" + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 4 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 5 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 6 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 7 0xFF + + #Board ID + echo "Init Board ID" + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 6 0xFF + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 7 0xFF + + #Board ID of dummy card + echo "Init Board ID of dummy card" + i2cset -y -r ${NUM_I801_DEVICE} 0x24 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x24 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x24 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x24 7 0xFF + + #PSU I/O (BAREFOOT_IO_EXP_PSU_ID) + echo "Init PSU IO Expender" + i2cset -y -r ${NUM_I801_DEVICE} 0x25 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x25 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x25 2 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x25 3 0x1D + i2cset -y -r ${NUM_I801_DEVICE} 0x25 6 0xDB + i2cset -y -r ${NUM_I801_DEVICE} 0x25 7 0x03 + + #FAN I/O (BAREFOOT_IO_EXP_FAN_ID) + echo "Init FAN IO Expender" + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 2 0x11 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 3 0x11 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 6 0xCC + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 7 0xCC + +} + +#FANIN Init +function _i2c_fan_init { + echo "FANIN INIT..." + # enable fan monitor on w83795 + # 4 fantray with 8 FANIN + # select bank0 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + # enable FANIN1~8 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x06 0xFF + # disable FANIN9~14 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x07 0x00 + + # select bank 2 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x82 + # set PWM mode in FOMC + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x0F 0x00 + + echo "Done" +} + +# To set the global variable GPIO_OFFSET +function _set_gpio_offset { + GPIO_OFFSET=0 + for d in `ls /sys/class/gpio/ | grep gpiochip` + do + gpiochip_no=${d##gpiochip} + if [ $gpiochip_no -gt 255 ]; then + GPIO_OFFSET=256 + break + fi + done + #echo "set GPIO_OFFSET=${GPIO_OFFSET}" +} + +#GPIO Init +function _i2c_gpio_init { + local i=0 + #ABS Port 0-15 + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + _set_gpio_offset + #for i in {240..255}; + for((i=${GPIO_OFFSET}+240;i<=${GPIO_OFFSET}+255;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #ABS Port 16-31 + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + #for i in {224..239}; + for((i=${GPIO_OFFSET}+224;i<=${GPIO_OFFSET}+239;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #INT Port 0-15 + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + #for i in {208..223}; + for((i=${GPIO_OFFSET}+208;i<=${GPIO_OFFSET}+223;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #INT Port 16-31 + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + #for i in {192..207}; + for((i=${GPIO_OFFSET}+192;i<=${GPIO_OFFSET}+207;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #SFP+ + echo "pca9535 0x27" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + #for i in {176..191}; + for((i=${GPIO_OFFSET}+176;i<=${GPIO_OFFSET}+191;i++)); + do + echo $i > /sys/class/gpio/export + case ${i} in + #176|177|178|179|182|183|188|189|190|191) + $((${GPIO_OFFSET}+176)) | \ + $((${GPIO_OFFSET}+177)) | \ + $((${GPIO_OFFSET}+178)) | \ + $((${GPIO_OFFSET}+179)) | \ + $((${GPIO_OFFSET}+182)) | \ + $((${GPIO_OFFSET}+183)) | \ + $((${GPIO_OFFSET}+188)) | \ + $((${GPIO_OFFSET}+189)) | \ + $((${GPIO_OFFSET}+190)) | \ + $((${GPIO_OFFSET}+191)) ) + echo 1 > /sys/class/gpio/gpio${i}/active_low + ;; + #180|181|184|185|186|187) + $((${GPIO_OFFSET}+180)) | \ + $((${GPIO_OFFSET}+181)) | \ + $((${GPIO_OFFSET}+184)) | \ + $((${GPIO_OFFSET}+185)) | \ + $((${GPIO_OFFSET}+186)) | \ + $((${GPIO_OFFSET}+187)) ) + echo out > /sys/class/gpio/gpio${i}/direction + ;; + esac + + done + #echo 176 > /sys/class/gpio/export + #echo 177 > /sys/class/gpio/export + #echo 178 > /sys/class/gpio/export + #echo 179 > /sys/class/gpio/export + #echo 180 > /sys/class/gpio/export + #echo 181 > /sys/class/gpio/export + #echo 182 > /sys/class/gpio/export + #echo 183 > /sys/class/gpio/export + #echo 184 > /sys/class/gpio/export + #echo 185 > /sys/class/gpio/export + #echo 186 > /sys/class/gpio/export + #echo 187 > /sys/class/gpio/export + #echo 188 > /sys/class/gpio/export + #echo 189 > /sys/class/gpio/export + #echo 190 > /sys/class/gpio/export + #echo 191 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio176/active_low #SFP+0 ABS + #echo 1 > /sys/class/gpio/gpio177/active_low #SFP+1 ABS + #echo 1 > /sys/class/gpio/gpio178/active_low #SFP+0 TX_FAULT + #echo 1 > /sys/class/gpio/gpio179/active_low #SFP+1 TX_FAULT + #echo out > /sys/class/gpio/gpio180/direction #SFP+0 TX_DIS + #echo out > /sys/class/gpio/gpio181/direction #SFP+1 TX_DIS + #echo 1 > /sys/class/gpio/gpio182/active_low #SFP+0 RX_LOS + #echo 1 > /sys/class/gpio/gpio183/active_low #SFP+1 RX_LOS + #echo out > /sys/class/gpio/gpio184/direction #SFP+0 RS + #echo out > /sys/class/gpio/gpio185/direction #SFP+1 RS + #echo out > /sys/class/gpio/gpio186/direction #SFP+0 TS + #echo out > /sys/class/gpio/gpio187/direction #SFP+1 TS + #echo 1 > /sys/class/gpio/gpio188/active_low #N/A + #echo 1 > /sys/class/gpio/gpio189/active_low #N/A + #echo 1 > /sys/class/gpio/gpio190/active_low #N/A + #echo 1 > /sys/class/gpio/gpio191/active_low #N/A + + #LP Mode Port 0-15 + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + #for i in {160..175}; + for((i=${GPIO_OFFSET}+160;i<=${GPIO_OFFSET}+175;i++)); + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #LP Mode Port 16-31 + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + #for i in {144..159}; + for((i=${GPIO_OFFSET}+144;i<=${GPIO_OFFSET}+159;i++)); + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #RST Port 0-15 + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + #for i in {128..143}; + for((i=${GPIO_OFFSET}+128;i<=${GPIO_OFFSET}+143;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo low > /sys/class/gpio/gpio${i}/direction + #echo out > /sys/class/gpio/gpio${i}/direction + #echo 0 > /sys/class/gpio/gpio${i}/value + done + + #RST Port 16-31 + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + #for i in {112..127}; + for((i=${GPIO_OFFSET}+112;i<=${GPIO_OFFSET}+127;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo low > /sys/class/gpio/gpio${i}/direction + #echo out > /sys/class/gpio/gpio${i}/direction + #echo 0 > /sys/class/gpio/gpio${i}/value + done + + #PSU I/O on Dummy Board 0x25 + echo "pca9535 0x25" > /sys/bus/i2c/devices/i2c-${NUM_I801_DEVICE}/new_device + #for i in {96..111}; + for((i=${GPIO_OFFSET}+96;i<=${GPIO_OFFSET}+111;i++)); + do + echo $i > /sys/class/gpio/export + case ${i} in + #97|98|100|101|102|105|106|108) + $((${GPIO_OFFSET}+97)) | \ + $((${GPIO_OFFSET}+98)) | \ + $((${GPIO_OFFSET}+100)) | \ + $((${GPIO_OFFSET}+101)) | \ + $((${GPIO_OFFSET}+102)) | \ + $((${GPIO_OFFSET}+105)) | \ + $((${GPIO_OFFSET}+106)) | \ + $((${GPIO_OFFSET}+108)) ) + echo 1 > /sys/class/gpio/gpio${i}/active_low + ;; + #98|101|106|107|108) + $((${GPIO_OFFSET}+98)) | \ + $((${GPIO_OFFSET}+101)) | \ + $((${GPIO_OFFSET}+106)) | \ + $((${GPIO_OFFSET}+107)) | \ + $((${GPIO_OFFSET}+108)) ) + echo out > /sys/class/gpio/gpio${i}/direction + ;; + esac + done +} + +#GPIO DeInit +function _i2c_gpio_deinit { + for((i=${GPIO_OFFSET}+96;i<=${GPIO_OFFSET}+255;i++)); + do + if [ -e "/sys/class/gpio/gpio${i}" ]; then + echo ${i} > /sys/class/gpio/unexport + fi + done + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x27" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x25" > /sys/bus/i2c/devices/i2c-${NUM_I801_DEVICE}/delete_device +} + +#TMP75 Init +function _i2c_temp_init { + echo "lm86 0x4c" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # ASIC Coretemp and Front MAC + echo "tmp75 0x4f" > ${PATH_I801_DEVICE}/new_device #CPU Board + echo "tmp75 0x48" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Near PSU1 + echo "tmp75 0x4a" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Rear MAC + echo "tmp75 0x4b" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Near Port 32 + echo "tmp75 0x4d" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Near PSU2 +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + # check if io expander for fan tray exist + #i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x33 + result=`i2cget -y ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 0 2>/dev/null` + err_code=$? + if [ "$err_code" != "0" ]; then + echo "fan tray not exist!" + return + fi + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + echo "led_fan setup..." + # all fan ok + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_led + # all fan fail + elif [ "${FAN1_ALARM}" == "1" ] && [ "${FAN2_ALARM}" == "1" ] \ + && [ "${FAN3_ALARM}" == "1" ] && [ "${FAN4_ALARM}" == "1" ] \ + && [ "${FAN5_ALARM}" == "1" ] && [ "${FAN6_ALARM}" == "1" ] \ + && [ "${FAN7_ALARM}" == "1" ] && [ "${FAN8_ALARM}" == "1" ]; then + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_led + # partial fan fail + else + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x20 + dataAddr=0 + eeprombusbase=${NUM_MUX3_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x20 + dataAddr=1 + eeprombusbase=${NUM_MUX4_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x21 + dataAddr=0 + eeprombusbase=${NUM_MUX5_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+224-16)) + #gpioBase=$((224 - 16)) + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x21 + dataAddr=1 + eeprombusbase=${NUM_MUX6_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+224-16)) + #gpioBase=$((224 - 16)) + ;; + 33) + i2cbus=${NUM_MUX1_CHAN7_DEVICE} + regAddr=0x27 + dataAddr=0 + gpioBase=$((${GPIO_OFFSET}+145)) + #gpioBase=145 + ;; + 34) + i2cbus=${NUM_MUX1_CHAN7_DEVICE} + regAddr=0x27 + dataAddr=1 + gpioBase=$((${GPIO_OFFSET}+143)) + #gpioBase=143 + ;; + *) + echo "Please input 1~34" + exit + ;; + esac +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + local port=$1 + if [ ${port} -lt 33 ]; then + eeprombusidx=$(( ${port} % 8)) + case $eeprombusidx in + 1) + eeprombus=$(( $eeprombusbase + 1 )) + eepromAddr=0x50 + ;; + 2) + eeprombus=$(( $eeprombusbase + 0 )) + eepromAddr=0x50 + ;; + 3) + eeprombus=$(( $eeprombusbase + 3 )) + eepromAddr=0x50 + ;; + 4) + eeprombus=$(( $eeprombusbase + 2 )) + eepromAddr=0x50 + ;; + 5) + eeprombus=$(( $eeprombusbase + 5 )) + eepromAddr=0x50 + ;; + 6) + eeprombus=$(( $eeprombusbase + 4 )) + eepromAddr=0x50 + ;; + 7) + eeprombus=$(( $eeprombusbase + 7 )) + eepromAddr=0x50 + ;; + 0) + eeprombus=$(( $eeprombusbase + 6 )) + eepromAddr=0x50 + ;; + esac + else + case $port in + 33) + eeprombus=${NUM_SFP1_DEVICE} + eepromAddr=0x50 + ;; + 34) + eeprombus=${NUM_SFP2_DEVICE} + eepromAddr=0x50 + ;; + esac + fi +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo -n "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + local i + for i in {1..32}; + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "optoe1 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done + echo "DONE" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init CPU EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0051 ]; then + echo "mb_eeprom 0x51" > ${PATH_I801_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0051 ]; then + echo "0x51" > ${PATH_I801_DEVICE}/delete_device + fi + #Init MB EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0055 ]; then + echo "mb_eeprom 0x55" > ${PATH_I801_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0055 ]; then + echo "0x55" > ${PATH_I801_DEVICE}/delete_device + fi + echo "DONE" +} + +#Init PSU EEPROM +function _i2c_psu_eeprom_init { + echo -n "PSU EEPROM INIT..." + + ## modprobe eeprom + modprobe eeprom + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init PSU EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN1_DEVICE}-0050 ] || \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN0_DEVICE}-0050 ]; then + ## PUS(0) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN1_DEVICE}/new_device + ## PUS(1) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN0_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN1_DEVICE}-0050 ] || \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN0_DEVICE}-0050 ]; then + ## PUS(0) EEPROM + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN1_DEVICE}/delete_device + ## PUS(1) EEPROM + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN0_DEVICE}/delete_device + fi + echo "DONE" +} + +#Init SFP EEPROM +function _i2c_sfp_eeprom_init { + echo -n "SFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 33-34 ports EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP1_DEVICE}-0050 ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP2_DEVICE}-0050 ]; then + #echo "sff8436 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP1_DEVICE}/new_device + #echo "sff8436 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP2_DEVICE}/new_device + echo "optoe1 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP1_DEVICE}/new_device + echo "optoe1 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP2_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP1_DEVICE}-0050 ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP2_DEVICE}-0050 ]; then + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP1_DEVICE}/delete_device + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP2_DEVICE}/delete_device + fi + echo "DONE" +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0055/eeprom | hexdump -C + echo "done..." +} + +#Get CPU EEPROM Information +function _i2c_cpu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0051/eeprom | hexdump -C + echo "done..." +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + _qsfp_eeprom_var_set ${QSFP_PORT} + + #Get QSFP EEPROM info + local size=255 + eeprom_path="${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom" + #echo "get ${eeprom_path}" + qsfp_info=$(dd if=${eeprom_path} bs=${size} count=1 2>/dev/null | base64) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get Board Version and Type +function _i2c_board_type_get { + boardType=`i2cget -y ${NUM_CPLD_DEVICE} 0x33 0x00` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev + +} + +#Get CPLD Version +function _i2c_cpld_version { + cpldRev=`i2cget -y ${NUM_CPLD_DEVICE} 0x33 0x01` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Set Port LED behavior +function _i2c_port_led_set { + local gy_offset=0x0 + local bl_offset=0x0 + local mask=0x0 + if [ "${QSFP_PORT}" == "" ]; then + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + case ${QSFP_PORT} in + 1|2|3|4) + gy_offset=0x80 + bl_offset=0x90 + ;; + 5|6|7|8) + gy_offset=0x81 + bl_offset=0x90 + ;; + 9|10|11|12) + gy_offset=0x82 + bl_offset=0x91 + ;; + 13|14|15|16) + gy_offset=0x83 + bl_offset=0x91 + ;; + 17|18|19|20) + gy_offset=0x84 + bl_offset=0x92 + ;; + 21|22|23|24) + gy_offset=0x85 + bl_offset=0x92 + ;; + 25|26|27|28) + gy_offset=0x86 + bl_offset=0x93 + ;; + 29|30|31|32) + gy_offset=0x87 + bl_offset=0x93 + ;; + 33) + gy_offset=0x88 + bl_offset=0x94 + mask=0x01 + ;; + 34) + gy_offset=0x88 + bl_offset=0x94 + mask=0x02 + ;; + *) + echo "Please input 1~34" + exit + ;; + esac + + #Set green/yellow/off + if [ ${QSFP_PORT} -lt 33 ]; then + mask=$(( 0x3 << $(( $((${QSFP_PORT} - 0x1)) % 0x4 )) * 0x2 )) + elif [ ${QSFP_PORT} = 33 ]; then + value=1 + elif [ ${QSFP_PORT} = 34 ]; then + value=2 + fi + + if [ ${QSFP_PORT} -lt 33 ]; then + if [ "${COLOR_PORT_LED}" == "green" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} 0x55 + elif [ "${COLOR_PORT_LED}" == "yellow" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} 0xaa + elif [ "${COLOR_PORT_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} 0x00 + return + fi + elif [ ${QSFP_PORT} -ge 33 ]; then + if [ "${COLOR_PORT_LED}" == "green" ] || + [ "${COLOR_PORT_LED}" == "yellow" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} $value + elif [ "${COLOR_PORT_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} $((! ${value} )) + return + fi + fi + + #Set Blink/Unblink + if [ ${QSFP_PORT} -lt 33 ]; then + mask=$(( 0x1 << $(( $((${QSFP_PORT} - 0x1)) % 0x8 )) )) + elif [ ${QSFP_PORT} = 33 ]; then + value=1 + elif [ ${QSFP_PORT} = 34 ]; then + value=2 + fi + + if [ "${BLINK_LED}" == "blink" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${bl_offset} 0x00 + elif [ "${BLINK_LED}" == "noblink" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${bl_offset} 0xff + fi + +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + ## PUS(0) EEPROM + echo "========PSU1=========" + cat ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN1_DEVICE}-0050/eeprom | hexdump -C + + ## PUS(1) EEPROM + echo "========PSU2=========" + cat ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN0_DEVICE}-0050/eeprom | hexdump -C + + echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + + if [ "${COLOR_SYS_LED}" == "green" ]; then + # set sys_led_g (0.0) = 1 + output_reg=2 + mask=0x01 + value=0x01 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + # set sys_led_g (0.0) = 0 + output_reg=2 + mask=0x01 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + i2cset -m ${mask} -y ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 ${value} + echo "Done" + +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + case ${FAN_TRAY} in + 1) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x02 + elif [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x00 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x06 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU1 LED +function _i2c_psu1_led { + local value=0 + local mask=8 + + if [ "${COLOR_SYS_LED}" == "green" ]; then + value=0x00 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + value=0xFF + else + echo "Invalid Parameters ${COLOR_SYS_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + i2cset -m ${mask} -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 ${value} +} + +#Set PSU2 LED +function _i2c_psu2_led { + local value=0 + local mask=16 + + if [ "${COLOR_SYS_LED}" == "green" ]; then + value=0x00 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + value=0xFF + else + echo "Invalid Parameters ${COLOR_SYS_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + i2cset -m ${mask} -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 ${value} +} + +#Get PSU Status +function _i2c_psu_status { + psu1_pwgood_gpio=$((${GPIO_OFFSET}+99)) + psu1_exist_gpio=$((${GPIO_OFFSET}+100)) + psu2_pwdgood_gpio=$((${GPIO_OFFSET}+96)) + psu2_exist_gpio=$((${GPIO_OFFSET}+97)) + + psu2PwGood=`cat /sys/class/gpio/gpio${psu2_pwdgood_gpio}/value` # PSU0_PWROK (0.0) + psu2Exist=`cat /sys/class/gpio/gpio${psu2_exist_gpio}/value` # PSU0_PRSNT_L (0.1) + + psu1PwGood=`cat /sys/class/gpio/gpio${psu1_pwgood_gpio}/value` # PSU1_PWROK (0.3) + psu1Exist=`cat /sys/class/gpio/gpio${psu1_exist_gpio}/value` # PSU1_PRSNT_L (0.4) + printf "PSU1 Exist:%d PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +# util function to get logx value +function logx { + v=$1 + n=$2 + logx_res=$(echo "${v} ${n}" | awk '{printf "%f\n",log($1)/log($2)}') +} + +#Set PSU LED on LED Board +function _i2c_led_psu_status_set { + + echo "=========================================================" + echo "# Description: PSU LED Status Setup" + echo "=========================================================" + + #Get PSU Status + _i2c_psu_status + + #PSU1 Status + echo "------------------------------" + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_SYS_LED="green" + _i2c_psu1_led + else + COLOR_SYS_LED="amber" + _i2c_psu1_led + fi + else + COLOR_SYS_LED="amber" + _i2c_psu1_led + fi + echo "set [PSU1 LED] = ${COLOR_SYS_LED}" + + #PSU2 Status + echo "------------------------------" + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_SYS_LED="green" + _i2c_psu2_led + else + COLOR_SYS_LED="amber" + #ONOFF_LED="on" + _i2c_psu2_led + fi + else + COLOR_SYS_LED="amber" + _i2c_psu2_led + fi + echo "set [PSU2 LED] = ${COLOR_SYS_LED}" +} + +# get qsfp ddm data +function _i2c_qsfp_ddm_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + # check if port presence + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + if [ "${status}" == "0" ]; then + echo "port ${QSFP_PORT} not presence" + return + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + # Get QSFP EEPROM info + # only need first 128 bytes (page0) for ddm parsing + local size=128 + eeprom_path="${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom" + #echo "get ${eeprom_path}" + qsfp_info=$(dd if=${eeprom_path} bs=${size} count=1 2>/dev/null | base64) + + # temperature + temp_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s 22 -n 1 -e '"%d"') + temp_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s 23 -n 1 -e '"%d"') + temp=$(echo "$temp_val1 $temp_val2" | awk '{printf "%f\n", $1 + $2/256.0}') + #temp=$(( ${temp_val1} + ${temp_val2}/256.0 )) + echo "temp=$temp" + # voltage + volt_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s 26 -n 1 -e '"%d"') + volt_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s 27 -n 1 -e '"%d"') + #volt=$(((($volt_val1 << 8) | volt_val2) / 10000)) + volt_val3=$(( ($volt_val1 << 8) | $volt_val2 )) + volt=$(echo "$volt_val3" | awk '{printf "%f\n", $1/10000.0}') + echo "volt=$volt" + + # 4 channels + for i in {0..3}; + do + echo "channel $i:" + # txBias + offset=$(( 42 + $i*2 )) + txBias_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 43 + $i*2 )) + txBias_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + txBias_val3=$(( ($txBias_val1 << 8) | $txBias_val2 )) + txBias=$(echo "$txBias_val3" | awk '{printf "%f\n", (131.0*$1)/65535}') + echo " txBias=$txBias" + # txPower + offset=$(( 50 + $i*2 )) + txPower_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 51 + $i*2 )) + txPower_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + txPower_val3=$(( ($txPower_val1 << 8) | $txPower_val2 )) + txPower_val4=$(echo "$txPower_val3" | awk '{printf "%f\n", $1*0.0001}') + logx $txPower_val4 10 + txPower=$(echo "$logx_res" | awk '{printf "%f\n", $1*10}') + echo " txPower=$txPower" + # rxPower + offset=$(( 34 + $i*2 )) + rxPower_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 35 + $i*2 )) + rxPower_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + rxPower_val3=$(( ($rxPower_val1 << 8) | $rxPower_val2 )) + rxPower_val4=$(echo "$rxPower_val3" | awk '{printf "%f\n", $1*0.0001}') + logx $rxPower_val4 10 + rxPower=$(echo "$logx_res" | awk '{printf "%f\n", $1*10}') + echo " rxPower=$rxPower" + done +} + +#Main Function +function _main { + start_time_str=`date` + start_time_sec=$(date +%s) + + _set_gpio_offset + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cpu_eeprom_get" ]; then + _i2c_cpu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_init" ]; then + _i2c_sfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_init" ]; then + _i2c_psu_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_qsfp_ddm_get" ]; then + _i2c_qsfp_ddm_get + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_port_led_set" ]; then + _i2c_port_led_set + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_temp_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cpu_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main 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 new file mode 100755 index 000000000000..7776493bc20a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..31}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`sonic-db-cli ASIC_DB HLEN HIDDEN` + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/s9180_32x_monitor.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/s9180_32x_monitor.sh new file mode 100755 index 000000000000..eedf685b290b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/s9180_32x_monitor.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# TBD: LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + #PSU controlled by dummy board, + #but fan LED and fan tray LED must controlled by this service + _led_monitor + + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/README.md b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/README.md new file mode 100644 index 000000000000..7411603ba608 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/README.md @@ -0,0 +1,175 @@ +# Ingrasys S9280-64X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9280-64X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9280-64X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9280-64X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S9280-64X. + +### I2C PCA9548 +The PCA9548 module on S9280-64X can be found in +`/sys/bus/i2c/devices/i2c-0/` , `/sys/bus/i2c/devices/i2c-17/`, +`/sys/bus/i2c/devices/i2c-18/` , `/sys/bus/i2c/devices/i2c-19/`, +`/sys/bus/i2c/devices/i2c-20/`, `/sys/bus/i2c/devices/i2c-21/`, +`/sys/bus/i2c/devices/i2c-22/`, `/sys/bus/i2c/devices/i2c-23/`, +`/sys/bus/i2c/devices/i2c-24/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9280-64X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9280-64X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9280 package is installed on the S9280-64X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x55" > /sys/bus/i2c/devices/i2c-0/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/0-0055/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon2/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon3/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-64] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_status_get [1-64] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/Makefile b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/Makefile new file mode 100644 index 000000000000..af1a5abe1d12 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m := eeprom_mb.o +obj-m += ingrasys_s9280_64x_i2c_cpld.o +obj-m += ingrasys_s9280_64x_psu.o diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/eeprom_mb.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/eeprom_mb.c new file mode 100644 index 000000000000..528864d93382 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/eeprom_mb.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +/* enable dev_dbg print out */ +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { /*0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57,*/ I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 512 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, (u8)((addr >> 8) & 0xFF), (u8)(addr & 0xFF)); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static ssize_t mb_eeprom_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + int ret; + int i; + u8 cmd; + u16 value16; + + dev_dbg(&client->dev, "mb_eeprom_write off=%d, count=%d\n", (int)off, (int)count); + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + mutex_lock(&data->update_lock); + + for(i=0; i < count; i++) { + /* write command */ + cmd = (off >> 8) & 0xff; + value16 = off & 0xff; + value16 |= buf[i] << 8; + ret = i2c_smbus_write_word_data(client, cmd, value16); + + if (ret < 0) { + dev_err(&client->dev, "write address failed at %d \n", (int)off); + goto exit; + } + + off++; + + /* need to wait for write complete */ + udelay(10000); + } +exit: + mutex_unlock(&data->update_lock); + /* force to update client when reading */ + for(i=0; i < SLICE_NUM; i++) { + data->last_updated[i] = 0; + } + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUSR, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, + .write = mb_eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x51 and 0x55. So decline + attaching to addresses >= 0x56 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.c new file mode 100644 index 000000000000..912060cc93e5 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.c @@ -0,0 +1,1618 @@ +/* + * A i2c cpld driver for the ingrasys_s9280_64x + * + * Copyright (C) 2017 Ingrasys Technology Corporation. + * Leo Lin + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9280_64x_i2c_cpld.h" + +#ifdef DEBUG +#define DEBUG_PRINT(fmt, args...) \ + printk(KERN_INFO "%s:%s[%d]: " fmt "\r\n", \ + __FILE__, __func__, __LINE__, ##args) +#else +#define DEBUG_PRINT(fmt, args...) +#endif + +#define I2C_READ_BYTE_DATA(ret, lock, i2c_client, reg) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_read_byte_data(i2c_client, reg); \ + mutex_unlock(lock); \ +} +#define I2C_WRITE_BYTE_DATA(ret, lock, i2c_client, reg, val) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_write_byte_data(i2c_client, reg, val); \ + mutex_unlock(lock); \ +} + +/* CPLD sysfs attributes index */ +enum s9280_64x_cpld_sysfs_attributes { + CPLD_ACCESS_REG, + CPLD_REGISTER_VAL, + CPLD_PORT_START, + CPLD_PORTS, + CPLD_VERSION, + CPLD_ID, + CPLD_BOARD_TYPE, + CPLD_EXT_BOARD_TYPE, + CPLD_QSFP_PORT_STATUS_1, + CPLD_QSFP_PORT_STATUS_2, + CPLD_QSFP_PORT_STATUS_3, + CPLD_QSFP_PORT_STATUS_4, + CPLD_QSFP_PORT_STATUS_5, + CPLD_QSFP_PORT_STATUS_6, + CPLD_QSFP_PORT_STATUS_7, + CPLD_QSFP_PORT_STATUS_8, + CPLD_QSFP_PORT_STATUS_9, + CPLD_QSFP_PORT_STATUS_10, + CPLD_QSFP_PORT_STATUS_11, + CPLD_QSFP_PORT_STATUS_12, + CPLD_QSFP_PORT_STATUS_13, + CPLD_QSFP_PORT_CONFIG_1, + CPLD_QSFP_PORT_CONFIG_2, + CPLD_QSFP_PORT_CONFIG_3, + CPLD_QSFP_PORT_CONFIG_4, + CPLD_QSFP_PORT_CONFIG_5, + CPLD_QSFP_PORT_CONFIG_6, + CPLD_QSFP_PORT_CONFIG_7, + CPLD_QSFP_PORT_CONFIG_8, + CPLD_QSFP_PORT_CONFIG_9, + CPLD_QSFP_PORT_CONFIG_10, + CPLD_QSFP_PORT_CONFIG_11, + CPLD_QSFP_PORT_CONFIG_12, + CPLD_QSFP_PORT_CONFIG_13, + CPLD_QSFP_PORT_INTERRUPT, + CPLD_SFP_PORT_STATUS, + CPLD_SFP_PORT_CONFIG, + CPLD_10GMUX_CONFIG, + CPLD_BMC_STATUS, + CPLD_BMC_WATCHDOG, + CPLD_USB_STATUS, + CPLD_RESET_CONTROL, + CPLD_SFP_LED, + CPLD_SFP_LED_BLINK, + CPLD_QSFP_LED_1, + CPLD_QSFP_LED_2, + CPLD_QSFP_LED_3, + CPLD_QSFP_LED_4, + CPLD_QSFP_LED_5, + CPLD_QSFP_LED_6, + CPLD_QSFP_LED_7, + CPLD_QSFP_LED_8, + CPLD_QSFP_LED_9, + CPLD_QSFP_LED_10, + CPLD_QSFP_LED_11, + CPLD_QSFP_LED_12, + CPLD_QSFP_LED_13, + CPLD_QSFP_LED_14, + CPLD_QSFP_LED_15, + CPLD_QSFP_LED_16, + CPLD_QSFP_LED_BLINK, + CPLD_RTMR_RESET, + CPLD_ROV_STATUS, + +}; + +/* CPLD sysfs attributes hook functions */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t get_qsfp_port_start(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t get_qsfp_ports(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_cpld_id(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_qsfp_port_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_qsfp_port_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_qsfp_port_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_qsfp_port_interrupt(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_sfp_port_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_sfp_port_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_sfp_port_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_10gmux_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_10gmux_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_bmc_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_bmc_watchdog(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_bmc_watchdog(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_usb_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_reset_control(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_reset_control(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_sfp_led(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_sfp_led(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_sfp_led_blink(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_sfp_led_blink(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_qsfp_led(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_qsfp_led(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_qsfp_led_blink(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_qsfp_led_blink(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_rtmr_reset(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_rtmr_reset(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_rov_status(struct device *dev, + struct device_attribute *da, char *buf); + +static LIST_HEAD(cpld_client_list); /* client list for cpld */ +static struct mutex list_lock; /* mutex for client list */ + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +struct cpld_data { + int index; /* CPLD index */ + struct mutex access_lock; /* mutex for cpld access */ + u8 access_reg; /* register to access */ +}; + +/* CPLD device id and data */ +static const struct i2c_device_id ingrasys_i2c_cpld_id[] = { + { "ingrasys_cpld1", cpld1 }, + { "ingrasys_cpld2", cpld2 }, + { "ingrasys_cpld3", cpld3 }, + { "ingrasys_cpld4", cpld4 }, + { "ingrasys_cpld5", cpld5 }, + {} +}; + +/* Addresses scanned for ingrasys_i2c_cpld */ +static const unsigned short cpld_i2c_addr[] = { 0x33, I2C_CLIENT_END }; + +/* define all support register access of cpld in attribute */ +static SENSOR_DEVICE_ATTR(cpld_access_register, S_IWUSR | S_IRUGO, + read_access_register, write_access_register, CPLD_ACCESS_REG); +static SENSOR_DEVICE_ATTR(cpld_register_value, S_IWUSR | S_IRUGO, + read_register_value, write_register_value, CPLD_REGISTER_VAL); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_start, S_IRUGO, + get_qsfp_port_start, NULL, CPLD_PORT_START); +static SENSOR_DEVICE_ATTR(cpld_qsfp_ports, S_IRUGO, + get_qsfp_ports, NULL, CPLD_PORTS); +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, + read_cpld_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(cpld_id, S_IRUGO, read_cpld_id, NULL, CPLD_ID); +static SENSOR_DEVICE_ATTR(cpld_board_type, S_IRUGO, + read_board_type, NULL, CPLD_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_ext_board_type, S_IRUGO, + read_ext_board_type, NULL, CPLD_EXT_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_1, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_1); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_2, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_2); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_3, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_3); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_4, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_4); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_5, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_5); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_6, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_6); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_7, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_7); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_8, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_8); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_9, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_9); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_10, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_10); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_11, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_11); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_12, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_12); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_13, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_13); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_1, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_1); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_2, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_2); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_3, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_3); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_4, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_4); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_5, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_5); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_6, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_6); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_7, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_7); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_8, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_8); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_9, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_9); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_10, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_10); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_11, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_11); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_12, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_12); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_13, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_13); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_interrupt, S_IRUGO, + read_qsfp_port_interrupt, NULL, CPLD_QSFP_PORT_INTERRUPT); +static SENSOR_DEVICE_ATTR(cpld_sfp_port_status, S_IRUGO, + read_sfp_port_status, NULL, CPLD_SFP_PORT_STATUS); +static SENSOR_DEVICE_ATTR(cpld_sfp_port_config, S_IWUSR | S_IRUGO, + read_sfp_port_config, write_sfp_port_config, CPLD_SFP_PORT_CONFIG); +static SENSOR_DEVICE_ATTR(cpld_10gmux_config, S_IWUSR | S_IRUGO, + read_10gmux_config, write_10gmux_config, + CPLD_10GMUX_CONFIG); +static SENSOR_DEVICE_ATTR(cpld_bmc_status, S_IRUGO, + read_bmc_status, NULL, CPLD_BMC_STATUS); +static SENSOR_DEVICE_ATTR(cpld_bmc_watchdog, S_IWUSR | S_IRUGO, + read_bmc_watchdog, write_bmc_watchdog, + CPLD_BMC_WATCHDOG); +static SENSOR_DEVICE_ATTR(cpld_usb_status, S_IRUGO, + read_usb_status, NULL, CPLD_USB_STATUS); +static SENSOR_DEVICE_ATTR(cpld_reset_control, S_IWUSR | S_IRUGO, + read_reset_control, write_reset_control, + CPLD_BMC_WATCHDOG); +static SENSOR_DEVICE_ATTR(cpld_sfp_led, S_IWUSR | S_IRUGO, + read_sfp_led, write_sfp_led, CPLD_SFP_LED); +static SENSOR_DEVICE_ATTR(cpld_sfp_led_blink, S_IWUSR | S_IRUGO, + read_sfp_led_blink, write_sfp_led_blink, CPLD_SFP_LED_BLINK); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_1, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_1); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_2, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_2); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_3, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_3); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_4, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_4); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_5, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_5); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_6, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_6); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_7, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_7); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_8, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_8); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_9, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_9); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_10, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_10); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_11, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_11); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_12, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_12); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_13, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_13); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_14, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_14); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_15, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_15); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_16, S_IWUSR | S_IRUGO, + read_qsfp_led, write_qsfp_led, CPLD_QSFP_LED_16); +static SENSOR_DEVICE_ATTR(cpld_qsfp_led_blink, S_IWUSR | S_IRUGO, + read_qsfp_led_blink, write_qsfp_led_blink, CPLD_QSFP_LED_BLINK); +static SENSOR_DEVICE_ATTR(cpld_rtmr_reset, S_IWUSR | S_IRUGO, + read_rtmr_reset, write_rtmr_reset, CPLD_RTMR_RESET); +static SENSOR_DEVICE_ATTR(cpld_rov_status, S_IRUGO, + read_rov_status, NULL, CPLD_ROV_STATUS); + +/* define support attributes of cpldx , total 5 */ +/* cpld 1 */ +static struct attribute *s9280_64x_cpld1_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_start.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_ports.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_id.dev_attr.attr, + &sensor_dev_attr_cpld_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_ext_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_interrupt.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_status.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_config.dev_attr.attr, + &sensor_dev_attr_cpld_10gmux_config.dev_attr.attr, + &sensor_dev_attr_cpld_bmc_status.dev_attr.attr, + &sensor_dev_attr_cpld_bmc_watchdog.dev_attr.attr, + &sensor_dev_attr_cpld_usb_status.dev_attr.attr, + &sensor_dev_attr_cpld_reset_control.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_led.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_led_blink.dev_attr.attr, + &sensor_dev_attr_cpld_rtmr_reset.dev_attr.attr, + &sensor_dev_attr_cpld_rov_status.dev_attr.attr, + NULL +}; + +/* cpld 2 / cpld 3 / cpld 4 / cpld 5 */ +static struct attribute *s9280_64x_cpld2345_attributes[] = { +&sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_start.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_ports.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_id.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_interrupt.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_14.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_15.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_16.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_led_blink.dev_attr.attr, + NULL +}; + +/* cpld 1 attributes group */ +static const struct attribute_group s9280_64x_cpld1_group = { + .attrs = s9280_64x_cpld1_attributes, +}; +/* cpld 2/3/4/5 attributes group */ +static const struct attribute_group s9280_64x_cpld2345_group = { + .attrs = s9280_64x_cpld2345_attributes, +}; + +/* read access register from cpld data */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + + return sprintf(buf, "0x%x\n", reg); +} + +/* write access register to cpld data */ +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + + if (kstrtou8(buf, 0, ®) < 0) + return -EINVAL; + + data->access_reg = reg; + return count; +} + +/* read the value of access register in cpld data */ +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + int reg_val; + + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + + if (reg_val < 0) + return -1; + + return sprintf(buf, "0x%x\n", reg_val); +} + +/* wrtie the value to access register in cpld data */ +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ret = -EIO; + u8 reg = data->access_reg; + u8 reg_val; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, client, reg, reg_val); + + return count; +} + +/* get qsfp port start number of the cpld device */ +/* the start number use to tranlate qsfp port to cpld port */ +/* the cpld port use to access the qsfp port register in cpld */ +static ssize_t get_qsfp_port_start(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int port_base_num; + + if (attr->index == CPLD_PORT_START) { + if (data->index == cpld1) { + port_base_num = 1; + } else { + port_base_num = CPLD_1_PORT_NUM + + CPLD_2_PORT_NUM*(data->index - 1) + 1; + } + return sprintf(buf, "%d\n", port_base_num); + } + return -1; +} + +/* get total qsfp port which contain register in the cpld device */ +static ssize_t get_qsfp_ports(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ports; + + if (attr->index == CPLD_PORTS) { + if (data->index == cpld1) + ports = CPLD_1_PORT_NUM; + else + ports = CPLD_2_PORT_NUM; + return sprintf(buf, "%d\n", ports); + } + return -1; +} + +/* get cpdl version register value */ +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_VERSION) { + reg = CPLD_VERSION_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get cpdl id register value */ +static ssize_t read_cpld_id(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_ID) { + reg = CPLD_ID_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get board type register value */ +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BOARD_TYPE) { + reg = CPLD_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_EXT_BOARD_TYPE) { + reg = CPLD_EXT_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get qsfp port status register value */ +static ssize_t read_qsfp_port_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index >= CPLD_QSFP_PORT_STATUS_1 && + attr->index <= CPLD_QSFP_PORT_STATUS_13) { + reg = CPLD_QSFP_PORT_STATUS_BASE_REG + + (attr->index - CPLD_QSFP_PORT_STATUS_1); + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get qsfp port config register value */ +static ssize_t read_qsfp_port_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index >= CPLD_QSFP_PORT_CONFIG_1 && + attr->index <= CPLD_QSFP_PORT_CONFIG_13) { + reg = CPLD_QSFP_PORT_CONFIG_BASE_REG + + (attr->index - CPLD_QSFP_PORT_CONFIG_1); + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to qsfp port config register */ +static ssize_t write_qsfp_port_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index >= CPLD_QSFP_PORT_CONFIG_1 && + attr->index <= CPLD_QSFP_PORT_CONFIG_13) { + reg = CPLD_QSFP_PORT_CONFIG_BASE_REG + + (attr->index - CPLD_QSFP_PORT_CONFIG_1); + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get qsfp port interrupt register value */ +static ssize_t read_qsfp_port_interrupt(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_QSFP_PORT_INTERRUPT) { + reg = CPLD_QSFP_PORT_INTERRUPT_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get sfp port status register value */ +static ssize_t read_sfp_port_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_PORT_STATUS) { + reg = CPLD_SFP_PORT_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get sfp port config register value */ +static ssize_t read_sfp_port_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_PORT_CONFIG) { + reg = CPLD_SFP_PORT_CONFIG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to sfp port config register */ +static ssize_t write_sfp_port_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_SFP_PORT_CONFIG) { + reg = CPLD_SFP_PORT_CONFIG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get 10g mux config register value */ +static ssize_t read_10gmux_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_10GMUX_CONFIG) { + reg = CPLD_10GMUX_CONFIG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to 10g mux config register */ +static ssize_t write_10gmux_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_10GMUX_CONFIG) { + reg = CPLD_10GMUX_CONFIG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get bmc status register value */ +static ssize_t read_bmc_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BMC_STATUS) { + reg = CPLD_BMC_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get bmc watchdog register value */ +static ssize_t read_bmc_watchdog(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BMC_WATCHDOG) { + reg = CPLD_BMC_WATCHDOG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to bmc watchdog register */ +static ssize_t write_bmc_watchdog(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_BMC_WATCHDOG) { + reg = CPLD_BMC_WATCHDOG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get usb status register value */ +static ssize_t read_usb_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_USB_STATUS) { + reg = CPLD_USB_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get reset control register value */ +static ssize_t read_reset_control(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_RESET_CONTROL) { + reg = CPLD_RESET_CONTROL_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to reset control register */ +static ssize_t write_reset_control(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_RESET_CONTROL) { + reg = CPLD_RESET_CONTROL_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get sfp port 0/1 led register */ +static ssize_t read_sfp_led(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_LED) { + reg = CPLD_SFP_LED_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to sfp 0/1 port led register */ +static ssize_t write_sfp_led(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_SFP_LED) { + reg = CPLD_SFP_LED_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get sfp port 0/1 led blink register */ +static ssize_t read_sfp_led_blink(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_LED_BLINK) { + reg = CPLD_SFP_LED_BLINK_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to sfp port 0/1 led blink register */ +static ssize_t write_sfp_led_blink(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_SFP_LED_BLINK) { + reg = CPLD_SFP_LED_BLINK_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get qsfp port led register */ +static ssize_t read_qsfp_led(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index >= CPLD_QSFP_LED_1 && + attr->index <= CPLD_QSFP_LED_16) { + reg = CPLD_QSFP_LED_BASE_REG + (attr->index - CPLD_QSFP_LED_1); + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to qsfp port led register */ +static ssize_t write_qsfp_led(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index >= CPLD_QSFP_LED_1 && + attr->index <= CPLD_QSFP_LED_16) { + reg = CPLD_QSFP_LED_BASE_REG + (attr->index - CPLD_QSFP_LED_1); + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get qsfp 16 port led blink register value in 64 bit map */ +/* + each register for 2 port, each port has 4 channel for led blink + bit 64 56 48 40 32 24 16 8 0 + port 16/15 14/13 12/11 10/9 8/7 6/5 4/3 2/1 + */ +static ssize_t read_qsfp_led_blink(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val, i; + u64 bitmap = 0; + + if (attr->index == CPLD_QSFP_LED_BLINK) { + for (i = 0; i <= 7; i++) { + reg = CPLD_QSFP_LED_BLINK_BASE_REG + i; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + reg_val = reg_val & 0xff; + bitmap = bitmap | (reg_val<<(i*8)); + } + return sprintf(buf, "0x%llx\n", bitmap); + } + return -1; +} + +/* set 64 bit map value to qsfp port led blink register */ +/* + each register for 2 port, each port has 4 channel for led blink + bit 63 56 48 40 32 24 16 8 0 + port 16/15 14/13 12/11 10/9 8/7 6/5 4/3 2/1 + */ +static ssize_t write_qsfp_led_blink(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val, i; + int ret; + u64 bitmap = 0; + + if (kstrtou64(buf, 0, &bitmap) < 0) + return -EINVAL; + + if (attr->index == CPLD_QSFP_LED_BLINK) { + for (i = 0; i <= 7; i++) { + reg = CPLD_QSFP_LED_BLINK_BASE_REG + i; + reg_val = (u8)((bitmap >> i*8) & 0xFF); + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + } + return count; +} + +/* get retimer reset register */ +static ssize_t read_rtmr_reset(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_RTMR_RESET) { + reg = CPLD_RTMR_RESET_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to retimer reset register */ +static ssize_t write_rtmr_reset(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_RTMR_RESET) { + reg = CPLD_RTMR_RESET_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get rov status register */ +static ssize_t read_rov_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_ROV_STATUS) { + reg = CPLD_ROV_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* add valid cpld client to list */ +static void ingrasys_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = NULL; + + node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + if (!node) { + dev_info(&client->dev, + "Can't allocate cpld_client_node for index %d\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +/* remove exist cpld client in list */ +static void ingrasys_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + mutex_unlock(&list_lock); +} + +/* cpld drvier probe */ +static int ingrasys_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + int ret = -EPERM; + int idx; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* init cpld data for client */ + i2c_set_clientdata(client, data); + mutex_init(&data->access_lock); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_info(&client->dev, + "i2c_check_functionality failed (0x%x)\n", + client->addr); + status = -EIO; + goto exit; + } + + /* get cpld id from device */ + ret = i2c_smbus_read_byte_data(client, CPLD_ID_REG); + + if (ret < 0) { + dev_info(&client->dev, + "fail to get cpld id (0x%x) at addr (0x%x)\n", + CPLD_ID_REG, client->addr); + status = -EIO; + goto exit; + } + + CPLD_ID_ID_GET(ret, idx); + + if (INVALID(idx, cpld1, cpld5)) { + dev_info(&client->dev, + "cpld id %d(device) not valid\n", idx); + //status = -EPERM; + //goto exit; + } + +#if 0 + /* change client name for each cpld with index */ + snprintf(client->name, sizeof(client->name), "%s_%d", client->name, + data->index); +#endif + + data->index = dev_id->driver_data; + + /* register sysfs hooks for different cpld group */ + dev_info(&client->dev, "probe cpld with index %d\n", data->index); + switch (data->index) { + case cpld1: + status = sysfs_create_group(&client->dev.kobj, + &s9280_64x_cpld1_group); + break; + case cpld2: + case cpld3: + case cpld4: + case cpld5: + status = sysfs_create_group(&client->dev.kobj, + &s9280_64x_cpld2345_group); + break; + default: + status = -EINVAL; + } + + if (status) + goto exit; + + dev_info(&client->dev, "chip found\n"); + + /* add probe chip to client list */ + ingrasys_i2c_cpld_add_client(client); + + return 0; +exit: + sysfs_remove_group(&client->dev.kobj, &s9280_64x_cpld2345_group); + return status; +} + +/* cpld drvier remove */ +static int ingrasys_i2c_cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + switch (data->index) { + case cpld1: + sysfs_remove_group(&client->dev.kobj, &s9280_64x_cpld1_group); + break; + case cpld2: + case cpld3: + case cpld4: + case cpld5: + sysfs_remove_group(&client->dev.kobj, + &s9280_64x_cpld2345_group); + break; + } + + ingrasys_i2c_cpld_remove_client(client); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, ingrasys_i2c_cpld_id); + +static struct i2c_driver ingrasys_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ingrasys_i2c_cpld", + }, + .probe = ingrasys_i2c_cpld_probe, + .remove = ingrasys_i2c_cpld_remove, + .id_table = ingrasys_i2c_cpld_id, + .address_list = cpld_i2c_addr, +}; + +/* provid cpld register read */ +/* cpld_idx indicate the index of cpld device */ +int ingrasys_i2c_cpld_read(u8 cpld_idx, + u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + struct cpld_data *data; + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + data = i2c_get_clientdata(cpld_node->client); + if (data->index == cpld_idx) { + DEBUG_PRINT("cpld_idx=%d, read reg 0x%02x", + cpld_idx, reg); + I2C_READ_BYTE_DATA(ret, &data->access_lock, + cpld_node->client, reg); + DEBUG_PRINT("cpld_idx=%d, read reg 0x%02x = 0x%02x", + cpld_idx, reg, ret); + break; + } + } + + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_read); + +/* provid cpld register write */ +/* cpld_idx indicate the index of cpld device */ +int ingrasys_i2c_cpld_write(u8 cpld_idx, + u8 reg, + u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + struct cpld_data *data; + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + data = i2c_get_clientdata(cpld_node->client); + + if (data->index == cpld_idx) { + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + cpld_node->client, + reg, value); + DEBUG_PRINT("cpld_idx=%d, write reg 0x%02x val 0x%02x, ret=%d", + cpld_idx, reg, value, ret); + break; + } + } + + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_write); + +/* provid qsfp port status register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_qsfp_port_status_val(u8 port_num) +{ + u8 cpld_idx, cpld_port, reg; + int reg_val; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_STATUS_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_qsfp_port_status_val); + +/* provid qsfp port config register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_qsfp_port_config_val(u8 port_num) +{ + u8 cpld_idx, cpld_port, reg; + int reg_val; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_CONFIG_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_qsfp_port_config_val); + +/* provid qsfp port config register write */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_set_qsfp_port_config_val(u8 port_num, + u8 reg_val) +{ + u8 cpld_idx, cpld_port, reg, ret; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_CONFIG_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + ret = ingrasys_i2c_cpld_write(cpld_idx, reg, reg_val); + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_set_qsfp_port_config_val); + +/* provid sfp port 0/1 status register read */ +int ingrasys_i2c_cpld_get_sfp_port_status_val(void) +{ + u8 cpld_idx, reg; + int reg_val; + + cpld_idx = cpld1; + reg = CPLD_SFP_PORT_STATUS_REG; + DEBUG_PRINT("cpld_idx=%d, reg=0x%x", + cpld_idx, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_sfp_port_status_val); + +/* provid qsfp port config register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_sfp_port_config_val(void) +{ + u8 cpld_idx, reg; + int reg_val; + + cpld_idx = cpld1; + reg = CPLD_SFP_PORT_CONFIG_REG; + DEBUG_PRINT("cpld_idx=%d, reg=0x%x", + cpld_idx, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_sfp_port_config_val); + +/* provid qsfp port config register write */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_set_sfp_port_config_val(u8 reg_val) +{ + u8 cpld_idx, reg, ret; + + cpld_idx = cpld1; + reg = CPLD_SFP_PORT_CONFIG_REG; + DEBUG_PRINT("cpld_idx=%d, reg=0x%x", + cpld_idx, reg); + ret = ingrasys_i2c_cpld_write(cpld_idx, reg, reg_val); + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_set_sfp_port_config_val); + +static int __init ingrasys_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&ingrasys_i2c_cpld_driver); +} + +static void __exit ingrasys_i2c_cpld_exit(void) +{ + i2c_del_driver(&ingrasys_i2c_cpld_driver); +} + +MODULE_AUTHOR("Leo Lin "); +MODULE_DESCRIPTION("ingrasys_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(ingrasys_i2c_cpld_init); +module_exit(ingrasys_i2c_cpld_exit); + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.h b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.h new file mode 100644 index 000000000000..8d1df5dee49d --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_i2c_cpld.h @@ -0,0 +1,338 @@ +/* header file for i2c cpld driver of ingrasys_s9280_64x + * + * Copyright (C) 2017 Ingrasys Technology Corporation. + * Leo Lin + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef INGRASYS_S9280_64X_I2C_CPLD_H +#define INGRASYS_S9280_64X_I2C_CPLD_H + +/* CPLD device index value */ +enum cpld_id { + cpld1, + cpld2, + cpld3, + cpld4, + cpld5 +}; + +enum LED_BLINK { + BLINK, + NOBLINK, +}; + +enum LED_YELLOW { + YELLOW_OFF, + YELLOW_ON, +}; + +enum LED_GREEN { + GREEN_OFF, + GREEN_ON, +}; + +/* port number on CPLD */ +#define CPLD_1_PORT_NUM 12 +#define CPLD_2_PORT_NUM 13 + +/* QSFP port number */ +#define QSFP_MAX_PORT_NUM 64 +#define QSFP_MIN_PORT_NUM 1 + +/* SFP+ port number */ +#define SFP_MAX_PORT_NUM 2 +#define SFP_MIN_PORT_NUM 1 + + +/* CPLD registers */ +#define CPLD_BOARD_TYPE_REG 0x0 +#define CPLD_EXT_BOARD_TYPE_REG 0x7 +#define CPLD_VERSION_REG 0x1 +#define CPLD_ID_REG 0x2 +#define CPLD_QSFP_PORT_STATUS_BASE_REG 0x20 +#define CPLD_QSFP_PORT_CONFIG_BASE_REG 0x30 +#define CPLD_QSFP_PORT_INTERRUPT_REG 0x40 +#define CPLD_SFP_PORT_STATUS_REG 0x2F +#define CPLD_SFP_PORT_CONFIG_REG 0x3F +#define CPLD_QSFP_PORT_INTERRUPT_REG 0x40 +#define CPLD_10GMUX_CONFIG_REG 0x41 +#define CPLD_BMC_STATUS_REG 0x42 +#define CPLD_BMC_WATCHDOG_REG 0x43 +#define CPLD_USB_STATUS_REG 0x44 +#define CPLD_RESET_CONTROL_REG 0x4A +#define CPLD_SFP_LED_REG 0x80 +#define CPLD_SFP_LED_BLINK_REG 0x90 +#define CPLD_QSFP_LED_BASE_REG 0x80 +#define CPLD_QSFP_LED_BLINK_BASE_REG 0x90 +#define CPLD_RTMR_RESET_REG 0x4B +#define CPLD_ROV_STATUS_REG 0x4C + +/* bit definition for register value */ +enum CPLD_QSFP_PORT_STATUS_BITS { + CPLD_QSFP_PORT_STATUS_INT_BIT, + CPLD_QSFP_PORT_STATUS_ABS_BIT, +}; +enum CPLD_QSFP_PORT_CONFIG_BITS { + CPLD_QSFP_PORT_CONFIG_RESET_BIT, + CPLD_QSFP_PORT_CONFIG_RESERVE_BIT, + CPLD_QSFP_PORT_CONFIG_LPMODE_BIT, +}; +enum CPLD_SFP_PORT_STATUS_BITS { + CPLD_SFP0_PORT_STATUS_PRESENT_BIT, + CPLD_SFP0_PORT_STATUS_TXFAULT_BIT, + CPLD_SFP0_PORT_STATUS_RXLOS_BIT, + CPLD_SFP_PORT_STATUS_DUMMY, + CPLD_SFP1_PORT_STATUS_PRESENT_BIT, + CPLD_SFP1_PORT_STATUS_TXFAULT_BIT, + CPLD_SFP1_PORT_STATUS_RXLOS_BIT, +}; +enum CPLD_SFP_PORT_CONFIG_BITS { + CPLD_SFP0_PORT_CONFIG_TXDIS_BIT, + CPLD_SFP0_PORT_CONFIG_RS_BIT, + CPLD_SFP0_PORT_CONFIG_TS_BIT, + CPLD_SFP_PORT_CONFIG_DUMMY, + CPLD_SFP1_PORT_CONFIG_TXDIS_BIT, + CPLD_SFP1_PORT_CONFIG_RS_BIT, + CPLD_SFP1_PORT_CONFIG_TS_BIT, + +}; +enum CPLD_10GMUX_CONFIG_BITS { + CPLD_10GMUX_CONFIG_ENSMB_BIT, + CPLD_10GMUX_CONFIG_ENINPUT_BIT, + CPLD_10GMUX_CONFIG_SEL1_BIT, + CPLD_10GMUX_CONFIG_SEL0_BIT, +}; +enum CPLD_BMC_WATCHDOG_BITS { + CPLD_10GMUX_CONFIG_ENTIMER_BIT, + CPLD_10GMUX_CONFIG_TIMEOUT_BIT, +}; +enum CPLD_RESET_CONTROL_BITS { + CPLD_RESET_CONTROL_SWRST_BIT, + CPLD_RESET_CONTROL_CP2104RST_BIT, + CPLD_RESET_CONTROL_82P33814RST_BIT, + CPLD_RESET_CONTROL_BMCRST_BIT, +}; +enum CPLD_SFP_LED_BITS { + CPLD_SFP_LED_SFP0_GREEN_BIT, + CPLD_SFP_LED_SFP0_YELLOW_BIT, + CPLD_SFP_LED_SFP1_GREEN_BIT, + CPLD_SFP_LED_SFP1_YELLOW_BIT, +}; +enum CPLD_SFP_LED_BLINK_BITS { + CPLD_SFP_LED_BLINK_SFP0_BIT, + CPLD_SFP_LED_BLINK_SFP1_BIT, +}; +enum CPLD_QSFP_LED_BITS { + CPLD_QSFP_LED_CHAN_0_GREEN_BIT, + CPLD_QSFP_LED_CHAN_0_YELLOW_BIT, + CPLD_QSFP_LED_CHAN_1_GREEN_BIT, + CPLD_QSFP_LED_CHAN_1_YELLOW_BIT, + CPLD_QSFP_LED_CHAN_2_GREEN_BIT, + CPLD_QSFP_LED_CHAN_2_YELLOW_BIT, + CPLD_QSFP_LED_CHAN_3_GREEN_BIT, + CPLD_QSFP_LED_CHAN_3_YELLOW_BIT, + +}; +enum CPLD_QSFP_LED_BLINK_BITS { + CPLD_QSFP_LED_BLINK_X_CHAN0_BIT, + CPLD_QSFP_LED_BLINK_X_CHAN1_BIT, + CPLD_QSFP_LED_BLINK_X_CHAN2_BIT, + CPLD_QSFP_LED_BLINK_X_CHAN3_BIT, + CPLD_QSFP_LED_BLINK_XPLUS_CHAN0_BIT, + CPLD_QSFP_LED_BLINK_XPLUS_CHAN1_BIT, + CPLD_QSFP_LED_BLINK_XPLUS_CHAN2_BIT, + CPLD_QSFP_LED_BLINK_XPLUS_CHAN3_BIT, +}; + +/* bit field structure for register value */ +struct cpld_reg_board_type_t { + u8 build_rev:2; + u8 hw_rev:2; + u8 board_id:4; +}; + +struct cpld_reg_version_t { + u8 revision:6; + u8 release:1; + u8 reserve:1; +}; + +struct cpld_reg_id_t { + u8 id:3; + u8 release:5; +}; + +/* common manipulation */ +#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u) +#define READ_BIT(val, bit) ((0u == (val & (1<bf_name) +#define READ_BF_1(bf_struct, val, bf_name, bf_value) \ + bf_struct bf; \ + bf.data = val; \ + bf_value = bf.bf_name +#define BOARD_TYPE_BUILD_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, build_rev, res) +#define BOARD_TYPE_HW_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, hw_rev, res) +#define BOARD_TYPE_BOARD_ID_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, board_id, res) +#define CPLD_VERSION_REV_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, revision, res) +#define CPLD_VERSION_REL_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, release, res) +#define CPLD_ID_ID_GET(val, res) \ + READ_BF(cpld_reg_id_t, val, id, res) +#define CPLD_ID_REL_GET(val, res) \ + READ_BF(cpld_reg_id_t, val, release, res) +/* SFP/QSFP port led registers manipulation */ +#define SFP_LED_TO_CPLD_IDX(sfp_port) cpld1 +#define SFP_LED_REG(sfp_port) CPLD_SFP_LED_REG +#define SFP_LED_BLINK_REG(sfp_port) CPLD_SFP_LED_BLINK_REG +#define QSFP_LED_TO_CPLD_IDX(qsfp_port) \ + ((qsfp_port - 1) / 16 + 2) +#define QSFP_LED_REG(qsfp_port) \ + ((qsfp_port - 1) % 16 + CPLD_QSFP_LED_BASE_REG) +#define QSFP_LED_BLINK_REG(qsfp_port) \ + (((qsfp_port - 1) % 16) / 2 + CPLD_QSFP_LED_BLINK_BASE_REG) +/* QSFP/SFP port status registers manipulation */ +#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \ +{ \ + if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \ + cpld_index = cpld1; \ + cpld_port = qsfp_port - 1; \ + } else if (CPLD_1_PORT_NUM < qsfp_port \ + && qsfp_port <= QSFP_MAX_PORT_NUM) { \ + cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \ + / CPLD_2_PORT_NUM; \ + cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \ + CPLD_2_PORT_NUM; \ + } else { \ + cpld_index = 0; \ + cpld_port = 0; \ + } \ +} +#define QSFP_PORT_STATUS_REG(cpld_port) \ + (CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port) +#define QSFP_PORT_CONFIG_REG(cpld_port) \ + (CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port) +#define QSFP_PORT_INT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT) +#define QSFP_PORT_ABS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT) +#define QSFP_PORT_RESET_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_RESET_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define SFP_PORT_PRESENT_BIT_GET(sfp_port, port_status_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_status_value, CPLD_SFP0_PORT_STATUS_PRESENT_BIT); \ + } else { \ + READ_BIT(port_status_value, CPLD_SFP1_PORT_STATUS_PRESENT_BIT); \ + } +#define SFP_PORT_TXFAULT_BIT_GET(sfp_port, port_status_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_status_value, CPLD_SFP0_PORT_STATUS_TXFAULT_BIT); \ + } else { \ + READ_BIT(port_status_value, CPLD_SFP1_PORT_STATUS_TXFAULT_BIT); \ + } +#define SFP_PORT_RXLOS_BIT_GET(sfp_port, port_status_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_status_value, CPLD_SFP0_PORT_STATUS_RXLOS_BIT); \ + } else { \ + READ_BIT(port_status_value, CPLD_SFP1_PORT_STATUS_RXLOS_BIT); \ + } +#define SFP_PORT_TXDIS_BIT_GET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TXDIS_BIT); \ + } else { \ + READ_BIT(port_config_value, CPLD_SFP1_PORT_STATUS_RXLOS_BIT); \ + } +#define SFP_PORT_RS_BIT_GET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_RS_BIT); \ + } else { \ + READ_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_RS_BIT); \ + } +#define SFP_PORT_TS_BIT_GET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \ + } else { \ + READ_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \ + } +#define SFP_PORT_TXDIS_BIT_SET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + SET_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TXDIS_BIT); \ + } else { \ + SET_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TXDIS_BIT); \ + } +#define SFP_PORT_TXDIS_BIT_CLEAR(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + CLEAR_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TXDIS_BIT); \ + } else { \ + CLEAR_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TXDIS_BIT); \ + } +#define SFP_PORT_RS_BIT_SET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + SET_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_RS_BIT); \ + } else { \ + SET_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_RS_BIT); \ + } +#define SFP_PORT_RS_BIT_CLEAR(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + CLEAR_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_RS_BIT); \ + } else { \ + CLEAR_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_RS_BIT); \ + } +#define SFP_PORT_TS_BIT_SET(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + SET_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \ + } else { \ + SET_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TS_BIT); \ + } +#define SFP_PORT_TS_BIT_CLEAR(sfp_port, port_config_value) \ + if (sfp_port == SFP_MIN_PORT_NUM) { \ + CLEAR_BIT(port_config_value, CPLD_SFP0_PORT_CONFIG_TS_BIT); \ + } else { \ + CLEAR_BIT(port_config_value, CPLD_SFP1_PORT_CONFIG_TS_BIT); \ + } + +/* CPLD access functions */ +extern int ingrasys_i2c_cpld_get_qsfp_port_status_val(u8 port_num); +extern int ingrasys_i2c_cpld_get_qsfp_port_config_val(u8 port_num); +extern int ingrasys_i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val); +extern int ingrasys_i2c_cpld_get_sfp_port_status_val(void); +extern int ingrasys_i2c_cpld_get_sfp_port_config_val(void); +extern int ingrasys_i2c_cpld_set_sfp_port_config_val(u8 reg_val); +extern u8 fp_port_to_phy_port(u8 fp_port); +#endif + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_platform.h b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_platform.h new file mode 100644 index 000000000000..08f14c0bd96b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_platform.h @@ -0,0 +1,158 @@ +#ifndef _S9230_64X_PLATFORM_H +#define _S9230_64X_PLATFORM_H + +#include + +// remove debug before release +#define DEBUG + +enum bus_order { + I2C_BUS_MAIN, + MUX_9548_0_CH0, + MUX_9548_0_CH1, + MUX_9548_0_CH2, + MUX_9548_0_CH3, + MUX_9548_0_CH4, + MUX_9548_0_CH5, + MUX_9548_0_CH6, + MUX_9548_0_CH7, + MUX_9548_1_CH0, + MUX_9548_1_CH1, + MUX_9548_1_CH2, + MUX_9548_1_CH3, + MUX_9548_1_CH4, + MUX_9548_1_CH5, + MUX_9548_1_CH6, + MUX_9548_1_CH7, + MUX_9548_2_CH0, + MUX_9548_2_CH1, + MUX_9548_2_CH2, + MUX_9548_2_CH3, + MUX_9548_2_CH4, + MUX_9548_2_CH5, + MUX_9548_2_CH6, + MUX_9548_2_CH7, + MUX_9546_0_CH0, + MUX_9546_0_CH1, + MUX_9546_0_CH2, + MUX_9546_0_CH3, + MUX_9546_1_CH0, + MUX_9546_1_CH1, + MUX_9546_1_CH2, + MUX_9546_1_CH3, + MUX_9548_11_CH0, + MUX_9548_11_CH1, + MUX_9548_11_CH2, + MUX_9548_11_CH3, + MUX_9548_11_CH4, + MUX_9548_11_CH5, + MUX_9548_11_CH6, + MUX_9548_11_CH7, + MUX_9548_3_CH0, + MUX_9548_3_CH1, + MUX_9548_3_CH2, + MUX_9548_3_CH3, + MUX_9548_3_CH4, + MUX_9548_3_CH5, + MUX_9548_3_CH6, + MUX_9548_3_CH7, + MUX_9548_4_CH0, + MUX_9548_4_CH1, + MUX_9548_4_CH2, + MUX_9548_4_CH3, + MUX_9548_4_CH4, + MUX_9548_4_CH5, + MUX_9548_4_CH6, + MUX_9548_4_CH7, + MUX_9548_5_CH0, + MUX_9548_5_CH1, + MUX_9548_5_CH2, + MUX_9548_5_CH3, + MUX_9548_5_CH4, + MUX_9548_5_CH5, + MUX_9548_5_CH6, + MUX_9548_5_CH7, + MUX_9548_6_CH0, + MUX_9548_6_CH1, + MUX_9548_6_CH2, + MUX_9548_6_CH3, + MUX_9548_6_CH4, + MUX_9548_6_CH5, + MUX_9548_6_CH6, + MUX_9548_6_CH7, + MUX_9548_7_CH0, + MUX_9548_7_CH1, + MUX_9548_7_CH2, + MUX_9548_7_CH3, + MUX_9548_7_CH4, + MUX_9548_7_CH5, + MUX_9548_7_CH6, + MUX_9548_7_CH7, + MUX_9548_8_CH0, + MUX_9548_8_CH1, + MUX_9548_8_CH2, + MUX_9548_8_CH3, + MUX_9548_8_CH4, + MUX_9548_8_CH5, + MUX_9548_8_CH6, + MUX_9548_8_CH7, + MUX_9548_9_CH0, + MUX_9548_9_CH1, + MUX_9548_9_CH2, + MUX_9548_9_CH3, + MUX_9548_9_CH4, + MUX_9548_9_CH5, + MUX_9548_9_CH6, + MUX_9548_9_CH7, + MUX_9548_10_CH0, + MUX_9548_10_CH1, + MUX_9548_10_CH2, + MUX_9548_10_CH3, + MUX_9548_10_CH4, + MUX_9548_10_CH5, + MUX_9548_10_CH6, + MUX_9548_10_CH7, +}; + +#define I2C_ADDR_MUX_9555_0 (0x20) +#define I2C_ADDR_MUX_9555_1 (0x24) +#define I2C_ADDR_MUX_9555_2 (0x25) +#define I2C_ADDR_MUX_9555_3 (0x26) +#define I2C_ADDR_MUX_9539_0 (0x76) +#define I2C_ADDR_MUX_9539_1 (0x76) +#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN) +#define I2C_BUS_SYS_LED (MUX_9548_1_CH1) +#define I2C_BUS_PSU_STATUS (I2C_BUS_MAIN) +#define I2C_ADDR_PSU_STATUS (I2C_ADDR_MUX_9555_2) + +#define NUM_OF_I2C_MUX (11) +#define NUM_OF_CPLD (5) +#define NUM_OF_QSFP_PORT (64) +#define NUM_OF_SFP_PORT (2) +#define QSFP_EEPROM_I2C_ADDR (0x50) + +enum gpio_reg { + REG_PORT0_IN, + REG_PORT1_IN, + REG_PORT0_OUT, + REG_PORT1_OUT, + REG_PORT0_POL, + REG_PORT1_POL, + REG_PORT0_DIR, + REG_PORT1_DIR, +}; + +struct ing_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +struct i2c_init_data { + __u16 ch; + __u16 addr; + __u8 reg; + __u8 value; +}; + +#endif diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_psu.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_psu.c new file mode 100644 index 000000000000..c2537bf40858 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/modules/ingrasys_s9280_64x_psu.c @@ -0,0 +1,394 @@ +/* + * S9280-64x PSU driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9280_64x_platform.h" + +static ssize_t show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf); +static struct s9280_psu_data *s9280_psu_update_status(struct device *dev); +static struct s9280_psu_data *s9280_psu_update_eeprom(struct device *dev); +static int s9280_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len); + + +#define DRIVER_NAME "psu" + +// Addresses scanned +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* PSU EEPROM SIZE */ +#define EEPROM_SZ 256 +#define READ_EEPROM 1 +#define NREAD_EEPROM 0 + +static struct i2c_client pca9555_client; + +/* pca9555 gpio pin mapping */ +#define PSU2_PWROK 0 +#define PSU2_PRSNT_L 1 +#define PSU2_PWRON_L 2 +#define PSU1_PWROK 3 +#define PSU1_PRSNT_L 4 +#define PSU1_PWRON_L 5 +#define TMP_75_INT_L 6 + +/* Driver Private Data */ +struct s9280_psu_data { + struct mutex lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + s32 status; /* IO expander value */ + char eeprom[EEPROM_SZ]; /* psu eeprom data */ + char psuABS; /* PSU absent */ + char psuPG; /* PSU power good */ +}; + +enum psu_index +{ + s9280_psu1, + s9280_psu2 +}; + +/* + * display power good attribute + */ +static ssize_t +show_psu_pg(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9280_psu_data *data = s9280_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuPG; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + +/* + * display power absent attribute + */ +static ssize_t +show_psu_abs(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9280_psu_data *data = s9280_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuABS; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + + +/* + * sysfs attributes for psu + */ +static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL); +static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL); +static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL); + +static struct attribute *s9280_psu_attributes[] = { + &dev_attr_psu_pg.attr, + &dev_attr_psu_abs.attr, + &dev_attr_psu_eeprom.attr, + NULL +}; + +/* + * display psu eeprom content + */ +static ssize_t +show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct s9280_psu_data *data = s9280_psu_update_eeprom(dev); + + memcpy(buf, (char *)data->eeprom, EEPROM_SZ); + return EEPROM_SZ; +} + +static const struct attribute_group s9280_psu_group = { + .attrs = s9280_psu_attributes, +}; + +/* + * check gpio expander is accessible + */ +static int +pca9555_detect(struct i2c_client *client) +{ + if (i2c_smbus_read_byte_data(client, REG_PORT0_DIR) < 0) { + return -ENODEV; + } + + return 0; +} + +/* + * client init + */ +static void +i2c_devices_client_address_init(struct i2c_client *client) +{ + pca9555_client = *client; + + /* get i2c adapter for the target */ + pca9555_client.adapter = i2c_get_adapter(I2C_BUS_PSU_STATUS); + + /* get the i2c addr for the target */ + pca9555_client.addr = I2C_ADDR_PSU_STATUS; +} + +static int +s9280_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct s9280_psu_data *data; + int status, err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct s9280_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct s9280_psu_data)); + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + i2c_devices_client_address_init(client); + + err = pca9555_detect(&pca9555_client); + if (err) { + return err; + } + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &s9280_psu_group); + if (status) { + goto exit_free; + } + + return 0; + +exit_free: + kfree(data); +exit: + + return status; +} + +static int +s9280_psu_remove(struct i2c_client *client) +{ + struct s9280_psu_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &s9280_psu_group); + kfree(data); + + /* free i2c adapter */ + i2c_put_adapter(pca9555_client.adapter); + + return 0; +} + + +/* + * psu eeprom read utility + */ +static int +s9280_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len) +{ + int i=0, ret=0; + int blk_max = 32; //max block read size + + /* read eeprom, 32 * 8 = 256 bytes */ + for (i=0; i < EEPROM_SZ/blk_max; i++) { + ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max, + data + (i*blk_max)); + if (ret < 0) { + return ret; + } + } + return ret; +} + +/* + * update eeprom content + */ +static struct s9280_psu_data +*s9280_psu_update_eeprom(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9280_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->last_updated + 300 * HZ) + || !data->valid) { + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9280_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + /* Read eeprom */ + if (!data->psuABS) { + //clear local eeprom data + memset(data->eeprom, 0, EEPROM_SZ); + + //read eeprom + status = s9280_psu_read_block(client, 0, data->eeprom, + ARRAY_SIZE(data->eeprom)); + + if (status < 0) { + memset(data->eeprom, 0, EEPROM_SZ); + dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status); + } else { + data->valid = 1; + } + } else { + memset(data->eeprom, 0, EEPROM_SZ); + } + data->last_updated = jiffies; + } + + mutex_unlock(&data->lock); + + return data; +} + +/* + * update psu status + */ +static struct s9280_psu_data +*s9280_psu_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9280_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9280_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + mutex_unlock(&data->lock); + + return data; +} + +static const struct i2c_device_id s9280_psu_id[] = { + { "psu1", s9280_psu1 }, + { "psu2", s9280_psu2 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, s9280_psu_id); + +static struct i2c_driver s9280_psu_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = s9280_psu_probe, + .remove = s9280_psu_remove, + .id_table = s9280_psu_id, + .address_list = normal_i2c, +}; + +static int __init s9280_psu_init(void) +{ + return i2c_add_driver(&s9280_psu_driver); +} + +static void __exit s9280_psu_exit(void) +{ + i2c_del_driver(&s9280_psu_driver); +} + +module_init(s9280_psu_init); +module_exit(s9280_psu_exit); + +MODULE_AUTHOR("Leo Lin "); +MODULE_DESCRIPTION("S9280-64X psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/qsfp-monitor.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/qsfp-monitor.service new file mode 100644 index 000000000000..c801ad68966d --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9280-64x-monitor.service +After=s9280-64x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/s9280-64x-monitor.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/s9280-64x-monitor.service new file mode 100644 index 000000000000..5f22b6164dd0 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/service/s9280-64x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9280_64x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/i2c_utils.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/i2c_utils.sh new file mode 100755 index 000000000000..dcd7bf717339 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/i2c_utils.sh @@ -0,0 +1,1928 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +SFP_PORT=${2} +QSFP_ACTION=${2} +SFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 + +# PCA9548#0 0x70 +NUM_MUX_9548_0_CH0=$(( ${NUM_I801_DEVICE} + 1 )) # CPLD1 +NUM_MUX_9548_0_CH1=$(( ${NUM_I801_DEVICE} + 2 )) # CPLD2 +NUM_MUX_9548_0_CH2=$(( ${NUM_I801_DEVICE} + 3 )) # CPLD3 +NUM_MUX_9548_0_CH3=$(( ${NUM_I801_DEVICE} + 4 )) # CPLD4 +NUM_MUX_9548_0_CH4=$(( ${NUM_I801_DEVICE} + 5 )) # CPLD5 +NUM_MUX_9548_0_CH5=$(( ${NUM_I801_DEVICE} + 6 )) # LM75_1 LM75_2 LM86 +NUM_MUX_9548_0_CH6=$(( ${NUM_I801_DEVICE} + 7 )) # LM75_3 LM75_4 + +# PCA9548#1 0x73 +NUM_MUX_9548_1_CH0=$(( ${NUM_I801_DEVICE} + 9 )) # UCD9090 +NUM_MUX_9548_1_CH1=$(( ${NUM_I801_DEVICE} + 10 )) # PCA9539#0 0x76 for FP LED & HW ID +NUM_MUX_9548_1_CH2=$(( ${NUM_I801_DEVICE} + 11 )) # NONE +NUM_MUX_9548_1_CH3=$(( ${NUM_I801_DEVICE} + 12 )) # EEPROM for debug 0x57 +#NUM_MUX_9548_1_CH4=$(( ${NUM_I801_DEVICE} + 13 )) # NONE +NUM_MUX_9548_1_CH5=$(( ${NUM_I801_DEVICE} + 14 )) # CLK gen +NUM_MUX_9548_1_CH6=$(( ${NUM_I801_DEVICE} + 15 )) # ROV +NUM_MUX_9548_1_CH7=$(( ${NUM_I801_DEVICE} + 16 )) # HWM on BMC + +# PCA9546#0 0X72 +NUM_MUX_9546_0_CH0=$(( ${NUM_I801_DEVICE} + 17 )) # PSU1 0x58 +NUM_MUX_9546_0_CH1=$(( ${NUM_I801_DEVICE} + 18 )) # PSU2 0x58 +NUM_MUX_9546_0_CH2=$(( ${NUM_I801_DEVICE} + 19 )) # NONE +NUM_MUX_9546_0_CH3=$(( ${NUM_I801_DEVICE} + 20 )) # NONE + +# PCA9548#2 0X71 +NUM_MUX_9548_2_CH0=$(( ${NUM_I801_DEVICE} + 21 )) # PCA9548#3 0x74 +NUM_MUX_9548_2_CH1=$(( ${NUM_I801_DEVICE} + 22 )) # PCA9548#4 0x74 +NUM_MUX_9548_2_CH2=$(( ${NUM_I801_DEVICE} + 23 )) # PCA9548#5 0x74 +NUM_MUX_9548_2_CH3=$(( ${NUM_I801_DEVICE} + 24 )) # PCA9548#6 0x74 +NUM_MUX_9548_2_CH4=$(( ${NUM_I801_DEVICE} + 25 )) # PCA9548#7 0x74 +NUM_MUX_9548_2_CH5=$(( ${NUM_I801_DEVICE} + 26 )) # PCA9548#8 0x74 +NUM_MUX_9548_2_CH6=$(( ${NUM_I801_DEVICE} + 27 )) # PCA9548#9 0x74 +NUM_MUX_9548_2_CH7=$(( ${NUM_I801_DEVICE} + 28 )) # PCA9548#10 0x74 + + + +# PCA9546#1 0X77 +NUM_MUX_9546_1_CH0=$(( ${NUM_I801_DEVICE} + 29 )) # SFP0 EEPROM 0x50 +NUM_MUX_9546_1_CH1=$(( ${NUM_I801_DEVICE} + 30 )) # SFP1 EEPROM 0x50 +NUM_MUX_9546_1_CH2=$(( ${NUM_I801_DEVICE} + 31 )) # NONE +NUM_MUX_9546_1_CH3=$(( ${NUM_I801_DEVICE} + 32 )) # PCA9539#1 0x76 for sys control + +# PCA9548#11 0X75 +NUM_MUX_9548_11_CH0=$(( ${NUM_I801_DEVICE} + 33 )) # SW upgrade for CPLD1 +NUM_MUX_9548_11_CH1=$(( ${NUM_I801_DEVICE} + 34 )) # SW upgrade for CPLD2 +NUM_MUX_9548_11_CH2=$(( ${NUM_I801_DEVICE} + 35 )) # SW upgrade for CPLD3 +NUM_MUX_9548_11_CH3=$(( ${NUM_I801_DEVICE} + 36 )) # SW upgrade for CPLD4 +NUM_MUX_9548_11_CH4=$(( ${NUM_I801_DEVICE} + 37 )) # SW upgrade for CPLD5 +NUM_MUX_9548_11_CH5=$(( ${NUM_I801_DEVICE} + 38 )) # EEPROM for debug 0x57 +NUM_MUX_9548_11_CH6=$(( ${NUM_I801_DEVICE} + 39 )) # Retimer#0~3 +NUM_MUX_9548_11_CH7=$(( ${NUM_I801_DEVICE} + 40 )) # Retimer#4~7 + +# PCA9548#3~10 0X74 +NUM_MUX_9548_3_CH0=$(( ${NUM_I801_DEVICE} + 41 )) # QSFP 0 EEPROM +NUM_MUX_9548_4_CH0=$(( ${NUM_I801_DEVICE} + 49 )) # QSFP 8 EEPROM +NUM_MUX_9548_5_CH0=$(( ${NUM_I801_DEVICE} + 57 )) # QSFP 16 EEPROM +NUM_MUX_9548_6_CH0=$(( ${NUM_I801_DEVICE} + 65 )) # QSFP 24 EEPROM +NUM_MUX_9548_7_CH0=$(( ${NUM_I801_DEVICE} + 73 )) # QSFP 32 EEPROM +NUM_MUX_9548_8_CH0=$(( ${NUM_I801_DEVICE} + 81 )) # QSFP 40 EEPROM +NUM_MUX_9548_9_CH0=$(( ${NUM_I801_DEVICE} + 89 )) # QSFP 48 EEPROM +NUM_MUX_9548_10_CH0=$(( ${NUM_I801_DEVICE} + 97 )) # QSFP 56 EEPROM + +# MUX Alias +I2C_BUS_MAIN=${NUM_I801_DEVICE} +I2C_BUS_HWM=${NUM_MUX_9548_1_CH7} +I2C_BUS_FAN_STATUS=${I2C_BUS_MAIN} +I2C_BUS_SYS_LED=${NUM_MUX_9548_1_CH1} +I2C_BUS_HW_ID=${NUM_MUX_9548_1_CH1} +I2C_BUS_BMC_HW_ID=${I2C_BUS_MAIN} +I2C_BUS_PSU_STAT=${I2C_BUS_MAIN} +I2C_BUS_FANTRAY_LED=${I2C_BUS_MAIN} +I2C_BUS_MB_EEPROM=${I2C_BUS_MAIN} +I2C_BUS_CB_EEPROM=${I2C_BUS_MAIN} +# TODO: check i2c channel of PSU1/PSU2, it swap in s9230 +I2C_BUS_PSU1_EEPROM=${NUM_MUX_9546_0_CH1} +I2C_BUS_PSU2_EEPROM=${NUM_MUX_9546_0_CH0} +I2C_BUS_CPLD1=${NUM_MUX_9548_0_CH0} +I2C_BUS_CPLD2=${NUM_MUX_9548_0_CH1} +I2C_BUS_CPLD3=${NUM_MUX_9548_0_CH2} +I2C_BUS_CPLD4=${NUM_MUX_9548_0_CH3} +I2C_BUS_CPLD5=${NUM_MUX_9548_0_CH4} +I2C_BUS_ROV=${NUM_MUX_9548_1_CH6} + +# I2C BUS path +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +# TODO: need to verify HWM deivce path after board ready +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_MUX_9548_0_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH0}" +PATH_MUX_9548_0_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH1}" +PATH_MUX_9548_0_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH2}" +PATH_MUX_9548_0_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH3}" +PATH_MUX_9548_0_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH4}" +PATH_MUX_9548_0_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH5}" +PATH_MUX_9548_0_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH6}" +PATH_MUX_9548_0_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH7}" +PATH_MUX_9548_1_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH0}" +PATH_MUX_9548_1_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH1}" +PATH_MUX_9548_1_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH2}" +PATH_MUX_9548_1_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH3}" +PATH_MUX_9548_1_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH4}" +PATH_MUX_9548_1_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH5}" +PATH_MUX_9548_1_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH6}" +PATH_MUX_9548_1_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH7}" +PATH_MUX_9548_2_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH0}" +PATH_MUX_9548_2_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH1}" +PATH_MUX_9548_2_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH2}" +PATH_MUX_9548_2_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH3}" +PATH_MUX_9548_2_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH4}" +PATH_MUX_9548_2_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH5}" +PATH_MUX_9548_2_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH6}" +PATH_MUX_9548_2_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH7}" +PATH_MUX_9546_0_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH0}" +PATH_MUX_9546_0_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH1}" +PATH_MUX_9546_0_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH2}" +PATH_MUX_9546_0_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH3}" +PATH_MUX_9546_1_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH0}" +PATH_MUX_9546_1_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH1}" +PATH_MUX_9546_1_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH2}" +PATH_MUX_9546_1_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH3}" +PATH_MUX_9548_11_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_11_CH0}" +PATH_MUX_9548_3_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_3_CH0}" +PATH_MUX_9548_4_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_4_CH0}" +PATH_MUX_9548_5_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_5_CH0}" +PATH_MUX_9548_6_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_6_CH0}" +PATH_MUX_9548_7_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_7_CH0}" +PATH_MUX_9548_8_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_8_CH0}" +PATH_MUX_9548_9_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_9_CH0}" +PATH_MUX_9548_10_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_10_CH0}" +PATH_CPLD1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD1}" +PATH_CPLD2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD2}" +PATH_CPLD3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD3}" +PATH_CPLD4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD4}" +PATH_CPLD5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD5}" + + +# I2C Address +### I2C MUX +I2C_ADDR_MUX_9548_0=0x70 +I2C_ADDR_MUX_9548_1=0x73 +I2C_ADDR_MUX_9548_2=0x71 +I2C_ADDR_MUX_9546_0=0x72 +I2C_ADDR_MUX_9546_1=0x71 +I2C_ADDR_MUX_9548_11=0x75 +I2C_ADDR_MUX_9548_3=0x74 +I2C_ADDR_MUX_9548_4=0x74 +I2C_ADDR_MUX_9548_5=0x74 +I2C_ADDR_MUX_9548_6=0x74 +I2C_ADDR_MUX_9548_7=0x74 +I2C_ADDR_MUX_9548_8=0x74 +I2C_ADDR_MUX_9548_9=0x74 +I2C_ADDR_MUX_9548_10=0x74 + +### GPIO Expander +I2C_ADDR_MUX_9539_0=0x76 # LED & HW ID +I2C_ADDR_MUX_9539_1=0x76 # SYS config +I2C_ADDR_MUX_9539_2=0x76 # on CPU board, STATUS and ERR from CPLD +I2C_ADDR_MUX_9555_0=0x20 # on FAN board, fan status and led config +I2C_ADDR_MUX_9555_1=0x24 # on BMC board, INT and HW ID +I2C_ADDR_MUX_9555_2=0x25 # on BMC board, PSU status +I2C_ADDR_MUX_9555_3=0x26 # on BMC board, RST and SEL + + +### peripheral +I2C_ADDR_MB_EEPROM=0x55 # on main board +I2C_ADDR_CB_EEPROM=0x51 # on cpu board +I2C_ADDR_UCD9090=0x34 +I2C_ADDR_W83795=0x2F +I2C_ADDR_PSU1_EEPROM=0x50 +I2C_ADDR_PSU2_EEPROM=0x50 +I2C_ADDR_LM75_1=0x4D # Rear Panel +I2C_ADDR_LM75_2=0x4E # Rear MAC +I2C_ADDR_LM86=0x4C # TBD +I2C_ADDR_LM75_3=0x4D # Front Panel +I2C_ADDR_LM75_4=0x4E # Front MAC +I2C_ADDR_TMP75_CB=0x4F # on cpu board +I2C_ADDR_TMP75_BB=0x4A # on bmc board +I2C_ADDR_QSFP_EEPROM=0x50 +I2C_ADDR_SFP_EEPROM=0x50 +I2C_ADDR_CPLD=0x33 +I2C_ADDR_ROV=0x76 + +#sysfs +PATH_SYSFS_PSU1="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU1_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU1_EEPROM)" +PATH_SYSFS_PSU2="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU2_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU2_EEPROM)" + +#ACTIVE LOW enable flag +ACTIVE_LOW_EN=1 +ACTIVE_HIGH_EN=0 +#GPIO Direction In/Out +DIR_IN=in +DIR_OUT=out + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# IO expander register +# direction +REG_PORT0_DIR=6 +REG_PORT1_DIR=7 +# polarity +REG_PORT0_POL=4 +REG_PORT1_POL=5 +# output +REG_PORT0_OUT=2 +REG_PORT1_OUT=3 +# input +REG_PORT0_IN=0 +REG_PORT1_IN=1 + +# qsfp port number range +MIN_QSFP_PORT_NUM=1 +MAX_QSFP_PORT_NUM=64 + +# sfp+ port number range +MIN_SFP_PORT_NUM=1 +MAX_SFP_PORT_NUM=2 + +# CPLD access +# ROV status +CPLD_ROV_STATUS_KEY=cpld_rov_status +# port status +CPLD_QSFP_STATUS_KEY=cpld_qsfp_port_status +CPLD_SFP_STATUS_KEY=cpld_sfp_port_status +# bit define +CPLD_QSFP_STATUS_ABS_BIT=1 +CPLD_SFP0_STATUS_PRES_BIT=0 +CPLD_SFP1_STATUS_PRES_BIT=4 + +# fp port to phy port mapping +fp2phy_array=( 0 1 4 5 8 9 12 13 16 17 20 21 24 25 28 29 + 32 33 36 37 40 41 44 45 48 49 52 53 56 57 60 61 + 2 3 6 7 10 11 14 15 18 19 22 23 26 27 30 31 + 34 35 38 39 42 43 46 47 50 51 54 55 58 59 62 63) +# fp port to led port mapping +fp2led_array=( 1 2 5 6 9 10 13 14 1 2 5 6 9 10 13 14 + 1 2 5 6 9 10 13 14 1 2 5 6 9 10 13 14 + 3 4 7 8 11 12 15 16 3 4 7 8 11 12 15 16 + 3 4 7 8 11 12 15 16 3 4 7 8 11 12 15 16) +# vdd value for mac +rov_val_array=( 0.85 0.82 0.77 0.87 0.74 0.84 0.79 0.89 ) +rov_reg_array=( 0x79 0x73 0x69 0x7D 0x63 0x77 0x6D 0x81 ) + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_fan_speed_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cb_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_eeprom_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_sfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_cb_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_status_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_qsfp_type_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_type_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_qsfp_ddm_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_bmc_board_type_get" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber|off" + echo " : ${0} i2c_psu1_led green|amber|off" + echo " : ${0} i2c_psu2_led green|amber|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + echo "${*}" + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +# front panel port to physical port mapping +function _port_fp2phy { + + local fp_port=$1 + local phy_port=0 + local index=$((${fp_port} - 1)) + # change to 1 base index for internal use + phy_port=$((${fp2phy_array[$index]} + 1)) + #phy_port=${fp2phy_array[$index]} + + echo $phy_port +} + +#front panel port to led port mapping +function _port_fp2led { + + local logic_port=$1 + local led_port=0 + led_port=${fp2led_array[$logic_port]} + + echo $led_port +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + #remove optoe module + rmmod optoe + + #rmmod i2c_ismt + _util_rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + # add MUX PCA9548#0 on I801, assume to be i2c-1~8 + if [ ! -e ${PATH_MUX_9548_0_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_0}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_0} already init." + fi + + # add MUX PCA9548#1 on I801, assume to be i2c-9~16 + if [ ! -e ${PATH_MUX_9548_1_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_1}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_1} already init." + fi + + # add MUX PCA9546#0 on I801, assume to be i2c-17~20 + if [ ! -e ${PATH_MUX_9546_0_CH0} ]; then + _retry "echo 'pca9546 ${I2C_ADDR_MUX_9546_0}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9546 ${I2C_ADDR_MUX_9546_0} already init." + fi + + # add MUX PCA9548#2 on I801, assume to be i2c-21~28 + if [ ! -e ${PATH_MUX_9548_2_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_2}' > ${PATH_MUX_9546_0_CH2}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_2} already init." + fi + + # add MUX PCA9546#1 on I801, assume to be i2c-29~32 + if [ ! -e ${PATH_MUX_9546_1_CH0} ]; then + _retry "echo 'pca9546 ${I2C_ADDR_MUX_9546_1}' > ${PATH_MUX_9546_0_CH3}/new_device" + else + echo "pca9546 ${I2C_ADDR_MUX_9546_1} already init." + fi + + # add MUX PCA9548#11 on I801, assume to be i2c-33~40 + if [ ! -e ${PATH_MUX_9548_11_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_11}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_11} already init." + fi + + # add MUX PCA9548#3 on PCA9548#2 CH0, assume to be i2c-41~48 + if [ ! -e ${PATH_MUX_9548_3_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_3}' > ${PATH_MUX_9548_2_CH0}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_4} already init." + fi + + # add MUX PCA9548#4 on PCA9548#2 CH1, assume to be i2c-49~56 + if [ ! -e ${PATH_MUX_9548_4_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_4}' > ${PATH_MUX_9548_2_CH1}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_4} already init." + fi + + # add MUX PCA9548#5 on PCA9548#2 CH2, assume to be i2c-57~64 + if [ ! -e ${PATH_MUX_9548_5_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_5}' > ${PATH_MUX_9548_2_CH2}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_5} already init." + fi + + # add MUX PCA9548#6 on PCA9548#2 CH3, assume to be i2c-65~72 + if [ ! -e ${PATH_MUX_9548_6_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_6}' > ${PATH_MUX_9548_2_CH3}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_6} already init." + fi + + # add MUX PCA9548#7 on PCA9548#2 CH4, assume to be i2c-73~80 + if [ ! -e ${PATH_MUX_9548_7_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_7}' > ${PATH_MUX_9548_2_CH4}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_7} already init." + fi + + # add MUX PCA9548#8 on PCA9548#2 CH5, assume to be i2c-81~88 + if [ ! -e ${PATH_MUX_9548_8_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_8}' > ${PATH_MUX_9548_2_CH5}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_8} already init." + fi + + # add MUX PCA9548#9 on PCA9548#2 CH6, assume to be i2c-89~96 + if [ ! -e ${PATH_MUX_9548_9_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_9}' > ${PATH_MUX_9548_2_CH6}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_9} already init." + fi + + # add MUX PCA9548#10 on PCA9548#2 CH7, assume to be i2c-97~104 + if [ ! -e ${PATH_MUX_9548_10_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_10}' > ${PATH_MUX_9548_2_CH7}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_10} already init." + fi + + _i2c_hwm_init + _util_rmmod eeprom + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_io_exp_init + _i2c_sensors_init + _i2c_cpld_init + _i2c_psu_init + + _i2c_qsfp_eeprom_init "new" + _i2c_sfp_eeprom_init "new" + _i2c_mb_eeprom_init "new" + _i2c_cb_eeprom_init "new" + _i2c_fan_speed_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + + # clear port led + _util_port_led_clear + + # rov for mac init + _mac_vdd_init + + # trun on sys led + echo "led_sys setup..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + + _config_rmem +} + +function _mac_vdd_init { + # read mac vid register value from CPLD + cpld_index=1 + _i2c_cpld_reg_read ${cpld_index} ${CPLD_ROV_STATUS_KEY} + # get vid form register value [0:2] + vid=$(($cpld_reg_val & 0x7)) + # get rov val and reg according to vid + rov_val=${rov_val_array[$vid]} + rov_reg=${rov_reg_array[$vid]} + echo "vid=${vid}, rov_val=${rov_val}, rov_reg=${rov_reg}" + + # write the rov reg to rov + i2cset -y -r ${I2C_BUS_ROV} ${I2C_ADDR_ROV} 0x21 ${rov_reg} w + + if [ $? -eq 0 ]; then + echo "set ROV for mac vdd done" + else + echo "set ROV for mac vdd fail" + fi +} + +#I2C Deinit +function _i2c_deinit { + echo "i2c deinit..." + for mod in coretemp jc42 w83795 ingrasys_s9280_64x_psu ingrasys_s9280_64x_i2c_cpld eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_i801; + do + _util_rmmod $mod + done + echo "Done" +} + +function _i2c_cpld_init { + echo "CPLD init..." + _util_rmmod ingrasys_s9280_64x_i2c_cpld + modprobe ingrasys_s9280_64x_i2c_cpld + + # add cpld 1~5 to sysfs + for i in {1..5}; + do + local cpld_bus="I2C_BUS_CPLD${i}" + local cpld_path="PATH_CPLD${i}_DEVICE" + dev_path="${PATH_SYS_I2C_DEVICES}/${!cpld_bus}-$(printf "%04x" ${I2C_ADDR_CPLD})" + if ! [ -L ${dev_path} ]; then + echo "ingrasys_cpld${i} ${I2C_ADDR_CPLD}" > ${!cpld_path}/new_device + else + echo "${dev_path} already exist" + fi + done + + echo "Done" +} + +function _i2c_sensors_init { + echo "SENSORS init..." + local dev_path + # to make sure hwmon index in sysfs as expected, + # need to remove kernel module and then probe them in expected order + # remove all sensors kernel module + _util_rmmod coretemp + _util_rmmod jc42 + _util_rmmod w83795 + # probe coretemp kernel module + modprobe coretemp #hwmon0 + # probe hwmon kernel module + modprobe w83795 + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_1_CH7}-$(printf "%04x" ${I2C_ADDR_W83795})" + if ! [ -L ${dev_path} ]; then + echo "w83795adg ${I2C_ADDR_W83795}" > ${PATH_MUX_9548_1_CH7}/new_device #hwmon1 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + # add lm75/lm86 to sysfs + ####Main board thermal + ####lm75_1 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH5}-$(printf "%04x" ${I2C_ADDR_LM75_1})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_1}" > ${PATH_MUX_9548_0_CH5}/new_device # hwmon2 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####lm75_2 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH5}-$(printf "%04x" ${I2C_ADDR_LM75_2})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_2}" > ${PATH_MUX_9548_0_CH5}/new_device #hwmon3 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####lm86 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH5}-$(printf "%04x" ${I2C_ADDR_LM86})" + if ! [ -L ${dev_path} ]; then + echo "lm86 ${I2C_ADDR_LM86}" > ${PATH_MUX_9548_0_CH5}/new_device #hwmon4 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####lm75_3 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH6}-$(printf "%04x" ${I2C_ADDR_LM75_3})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_3}" > ${PATH_MUX_9548_0_CH6}/new_device # hwmon5 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####lm75_4 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH6}-$(printf "%04x" ${I2C_ADDR_LM75_4})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_4}" > ${PATH_MUX_9548_0_CH6}/new_device #hwmon6 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####BMC board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_1_CH7}-$(printf "%04x" ${I2C_ADDR_TMP75_BB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_BB}" > ${PATH_MUX_9548_1_CH7}/new_device #hwmon7 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + ####CPU board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MAIN}-$(printf "%04x" ${I2C_ADDR_TMP75_CB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_CB}" > ${PATH_I801_DEVICE}/new_device #hwmon8 + sleep 0.1 + else + echo "${dev_path} already exist" + fi + + # probe jc42 kernel module + modprobe jc42 #hwmon9 + + echo "Done" +} + +#FAN Speed Init +function _i2c_fan_speed_init { + echo -n "FAN SPEED INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + # init fan speed + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi +} + +# HWM init +function _i2c_hwm_init { + echo "HWM INIT..." + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # SW reset, Disable monitor + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x9C + # disable TR5/TR6 DTS + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x04 0x0 + # enable FANIN1~8 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x06 0xFF + # disable FANIN9~14 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x07 0x00 + # CLKIN clock frequency set as 48Mhz + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x1C + # select bank 2 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x82 + # set PWM mode in FOMC + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x0F 0x00 + # set 25KHz fan output frequency in F1OPFP&F2OPFP + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x18 0x84 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x19 0x84 +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + + # need to init BMC io expander first due to some io expander are reset default + echo "Init BMC INT & HW ID IO Expander" + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT1_POL} 0x00 + + echo "Init BMC PSU status IO Expander" + # PWRON default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_OUT} 0x00 + # default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_OUT} 0x00 + # I/O 0.2 0.5 output(PWRON), rest input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_DIR} 0xDB + # I/O 1.0~1.1 input, 1.2~1.4 output (1.5~1.7 not enable) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_DIR} 0xE3 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_POL} 0x00 + + echo "Init BMC RST and SEL IO Expander" + # RST default is 1 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_OUT} 0x3F + # SEL default is 0 (HOST), EN default is 1 (ACTIVE_HIGH) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_OUT} 0x1F + # I/O 0.0~0.5 output, 0.6~0.7 not use + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_DIR} 0xD0 + # all output + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_POL} 0x00 + + echo "Init System LED & HW ID IO Expander" + # I/O_0.x for System LED default 0, I/O_1.x for HW ID + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_OUT} 0x00 + # System LED => all output + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_DIR} 0x00 + # HW ID => all input + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_POL} 0x00 + + echo "Init FAN Board Status IO Expander" + # LED_G_H set to 1, LED_Y_G set to 0 (ACTIVE_HIGH) + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_OUT} 0x11 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_OUT} 0x11 + # DIR/ABS is input, LED_Y/LED_G is output + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_POL} 0x00 + + echo "Init System SEL and RST IO Expander" + # default 0 (ACTIVE high) + # 0.4~0.5 SEL set to value 0 (host) + # 0.2 LED_CLR set to 0 will clear all switch LED bitmap, set to 1 here + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_OUT} 0x04 + # RST 1.6~1.7 default 1 (ACTIVE low), INT 1.0~1.4 default 1 (ACTIVE low) + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_OUT} 0xDF + # all output, but ISO_TF_CORE_RST_N 0.0 need to set as input to prevent reboot issue + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_DIR} 0x09 + # RST 1.6~1.7 output, rest are input + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_DIR} 0x3F + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_POL} 0x00 + + echo "Init CPU CPLD IO Expander (FIXME)" + # all input + #echo "NUM_MUX_9546_1_CH3=${NUM_MUX_9546_1_CH3}, I2C_ADDR_MUX_9539_2=${I2C_ADDR_MUX_9539_2}" + #_util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_DIR} 0xFF + # all input + #_util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_DIR} 0xFF + #_util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_POL} 0x00 + #_util_i2cset -y -r ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_POL} 0x00 +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + # check if io expander for fan tray exist + result=`i2cget -y ${I2C_BUS_FANTRAY_LED} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_IN} 2>/dev/null` + err_code=$? + if [ "$err_code" != "0" ]; then + echo "fan tray not exist!" + return + fi + + for FAN_TRAY in {1..4}; + do + FAN_ALARM="FAN${FAN_TRAY}_ALARM" + if [ "${!FAN_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY ${FAN_TRAY}] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY ${FAN_TRAY}] [Green]=off [Amber]=on" + fi + done +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + echo "led_fan setup..." + # all fan ok + if [ "${FAN1_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_fan_led + # all fan fail + elif [ "${FAN1_ALARM}" == "1" ] \ + && [ "${FAN3_ALARM}" == "1" ] \ + && [ "${FAN5_ALARM}" == "1" ] \ + && [ "${FAN7_ALARM}" == "1" ] ; then + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_fan_led + # partial fan fail + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_fan_led + fi + # if fan not present, no led need to be set +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + echo "led_psu1 setup..." + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_psu1_led + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="off" + echo "${COLOR_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + echo "led_psu2 setup..." + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_psu2_led + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="off" + echo "${COLOR_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C SYSTEM LED TEST..." + echo "=========================================================" + + #sys led (green) + COLOR_LED="green" + _i2c_sys_led + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + COLOR_LED="amber" + _i2c_sys_led + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + COLOR_LED="green" + _i2c_fan_led + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + COLOR_LED="amber" + _i2c_fan_led + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + COLOR_LED="green" + _i2c_psu1_led + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + COLOR_LED="amber" + _i2c_psu1_led + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + COLOR_LED="green" + _i2c_psu2_led + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + COLOR_LED="amber" + _i2c_psu2_led + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED (can't trun off system led) + COLOR_LED="off" + #_i2c_sys_led + _i2c_fan_led + _i2c_psu1_led + _i2c_psu2_led + _pause 'Check turn off all LEDs (exclude SYS LED) and Press [Enter] key to continue...' + + # restore sys led + COLOR_LED="green" + _i2c_sys_led +} + +#Set QSFP Port cpld variable +function _qsfp_cpld_var_set { + local port=$1 + local reg_port_base + local reg_port_shift + + if [[ $1 -le 12 && $1 -ge 1 ]]; then + cpld_index=1 + reg_port_base=0 + elif [[ $1 -le 25 && $1 -ge 13 ]]; then + cpld_index=2 + reg_port_base=12 + elif [[ $1 -le 38 && $1 -ge 26 ]]; then + cpld_index=3 + reg_port_base=25 + elif [[ $1 -le 51 && $1 -ge 39 ]]; then + cpld_index=4 + reg_port_base=38 + elif [[ $1 -le 64 && $1 -ge 52 ]]; then + cpld_index=5 + reg_port_base=51 + else + echo "invalid port number" + fi + + cpld_port_index=$(( $port - $reg_port_base )) +} + +#Set QSFP Port eeporm variable +function _qsfp_eeprom_var_set { + local port=$1 + local eeprombusbase + local eeprombusshift + # port 1 => zqsfp0 + # port 2 => zqsfp1 + # ... + local port_group=$(( ($port - 1) / 8 )) + + case ${port_group} in + 0) + eeprombusbase=${NUM_MUX_9548_3_CH0} + ;; + 1) + eeprombusbase=${NUM_MUX_9548_4_CH0} + ;; + 2) + eeprombusbase=${NUM_MUX_9548_5_CH0} + ;; + 3) + eeprombusbase=${NUM_MUX_9548_6_CH0} + ;; + 4) + eeprombusbase=${NUM_MUX_9548_7_CH0} + ;; + 5) + eeprombusbase=${NUM_MUX_9548_8_CH0} + ;; + 6) + eeprombusbase=${NUM_MUX_9548_9_CH0} + ;; + 7) + eeprombusbase=${NUM_MUX_9548_10_CH0} + ;; + *) + ;; + esac + + eeprombusshift=$(( (${port} - 1) % 8)) + eepromBus=$(( ${eeprombusbase} + ${eeprombusshift} )) + eepromAddr=${I2C_ADDR_QSFP_EEPROM} +} + + +#Set SFP Port cpld variable +function _sfp_cpld_var_set { + local port=$1 + case ${port} in + 1) + cpld_index=1 + ;; + 2) + cpld_index=1 + ;; + *) + ;; + esac +} + +#Set QSFP Port eeporm variable +function _sfp_eeprom_var_set { + local port=$1 + + case ${port} in + 1) + eepromBus=${NUM_MUX_9546_1_CH0} + ;; + 2) + eepromBus=${NUM_MUX_9546_1_CH1} + ;; + *) + ;; + esac + + eepromAddr=${I2C_ADDR_SFP_EEPROM} +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + local phy_port=0 + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + #get physical port + phy_port=$(_port_fp2phy $QSFP_PORT) + + _qsfp_eeprom_var_set ${phy_port} + + _util_get_qsfp_abs + + if [ $status = 0 ]; then + exit + fi + + # debug + echo "${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf '%04x' $eepromAddr)/eeprom | hexdump -C" + cat ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-64 ports EEPROM + local i + for i in {1..64}; + do + + #get physical port + phy_port=$(_port_fp2phy $i) + + _qsfp_eeprom_var_set ${phy_port} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + #echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + echo "optoe1 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/delete_device + fi + done + echo "Done" +} + +#Get SFP EEPROM Information +function _i2c_sfp_eeprom_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + _util_get_sfp_pres + + if [ $status = 0 ]; then + exit + fi + + _sfp_eeprom_var_set ${SFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init SFP EEPROM +function _i2c_sfp_eeprom_init { + echo "SFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-2 sfp+ EEPROM + local i + for i in {1..2}; + do + _sfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + #echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + echo "optoe1 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/delete_device + fi + done + echo "Done" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init mb EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_MB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "$I2C_ADDR_MB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/delete_device + fi + echo "Done" +} + +#Init CPU Board EEPROM +function _i2c_cb_eeprom_init { + echo -n "CPU Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init cpu EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_CB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "$I2C_ADDR_CB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/delete_device + fi + echo "Done" +} + +#Init PSU Kernel Module +function _i2c_psu_init { + echo "=========================================================" + echo "# Description: I2C PSU Init" + echo "=========================================================" + modprobe ingrasys_s9280_64x_psu + + echo "psu1 ${I2C_ADDR_PSU1_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/new_device + echo "psu2 ${I2C_ADDR_PSU2_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/new_device +} + +#Deinit PSU Kernel Module +function _i2c_psu_deinit { + echo "${I2C_ADDR_PSU1_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/delete_device + echo "${I2C_ADDR_PSU2_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/delete_device + _util_rmmod ingrasys_s9280_64x_psu +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + local stat + _util_get_qsfp_abs + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + local phy_port=0 + + phy_port=$(_port_fp2phy ${QSFP_PORT}) + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + _qsfp_eeprom_var_set ${phy_port} + + #Get QSFP EEPROM info + local size=255 + eeprom_path="${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom" + #echo "get ${eeprom_path}" + qsfp_info=$(dd if=${eeprom_path} bs=${size} count=1 2>/dev/null | base64) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +function _i2c_sfp_status_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + + local stat + _util_get_sfp_pres + #status: 0 -> Down, 1 -> Up + if [ $status = 0 ]; then + stat="down" + else + stat="up" + fi + echo "status is $stat" +} + +#get SFP Type +function _i2c_sfp_type_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + + _sfp_eeprom_var_set ${SFP_PORT} + + #Get QSFP EEPROM info + sfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $sfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $sfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $sfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + local eeprom_psu1="" + local eeprom_psu2="" + + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + eeprom_psu1="${PATH_SYSFS_PSU1}/psu_eeprom" + cat ${eeprom_psu1} | hexdump -C + + eeprom_psu2="${PATH_SYSFS_PSU2}/psu_eeprom" + cat ${eeprom_psu2} | hexdump -C +} + +#Get Main Board EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get mb +} + +#Get CPU Board EEPROM Information +function _i2c_cb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C CB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get cb +} + +#Get system EEPROM Information +##input: "cb" for cpu board, "mb" for main board +function _i2c_sys_eeprom_get { + local eeprom_dev + + if [ "$1" == "cb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + elif [ "$1" == "mb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + else + echo "wrong eeprom type" + return + fi + + # check if eeprom device exist in sysfs + if [ ! -f ${eeprom_dev} ]; then + echo "eeprom device not init" + return + fi + + cat ${eeprom_dev} | hexdump -C + echo "Done" +} + +#sync eeprom content between mb and cb eeprom +function _i2c_eeprom_sync { + echo "=========================================================" + echo "# Description: EEPROM sync..." + echo "=========================================================" + + local mb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + local cb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + + # check if eeprom device exist in sysfs + if [[ ! -f ${mb_eeprom_dev} || ! -f ${cb_eeprom_dev} ]]; then + echo "eeprom device not init" + return + fi + + ## check if MB eeprom is empty + if [ ! -z "$(cat ${mb_eeprom_dev} | hexdump -n2 | grep ffff)" ]; then + echo "copy cb eeprom to mb eeprom..." + cat ${cb_eeprom_dev} > ${mb_eeprom_dev} + else + echo "no need to sync" + fi + + echo "Done" +} + +#Set System Status LED +function _i2c_sys_led { + # only green/amber, on/off can't control + if [ "${COLOR_LED}" == "green" ]; then + # set sys_led_g (0.7) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x80 + elif [ "${COLOR_LED}" == "amber" ]; then + # set sys_led_g (0.7) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x40 + elif [ "${COLOR_LED}" == "amber" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x60 + elif [ "${COLOR_LED}" == "off" ]; then + # set fan_led_en (0.6) = 0 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x18 + elif [ "${COLOR_LED}" == "off" ]; then + # set psu1_pwr_ok_oe (0.4) = 0 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x04 + elif [ "${COLOR_LED}" == "amber" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x06 + elif [ "${COLOR_LED}" == "off" ]; then + # set psu0_pwr_ok_oe (0.2) = 0 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + + i2cAddr=${I2C_ADDR_MUX_9555_0} + output_reg=${REG_PORT0_OUT} + + case ${FAN_TRAY} in + 1) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + # LED PIN value is ACTIVE HIGH + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0xff + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0xff + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "Done" +} + +#Get Board Version and Type +function _i2c_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_HW_ID} ${I2C_ADDR_MUX_9539_0} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "MAIN_BOARD BOARD_ID is 0x%02x, HW Rev 0x%02x, Build Rev 0x%02x\n" $boardId $boardHwRev $boardBuildRev +} + +#Get BMC Board Version and Type +function _i2c_bmc_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_BMC_HW_ID} ${I2C_ADDR_MUX_9555_1} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BMC_BOARD BOARD_ID is 0x%02x, HW Rev 0x%02x, Build Rev 0x%02x\n" $boardId $boardHwRev $boardBuildRev +} + +#Get CPLD Version +function _i2c_cpld_version { + echo "=========================================================" + echo "# Description: CPLD Version" + echo "=========================================================" + + for i in {1..5}; + do + local cpld_bus="I2C_BUS_CPLD${i}" + local cpld_path="PATH_CPLD${i}_DEVICE" + local file_path="${PATH_SYS_I2C_DEVICES}/${!cpld_bus}-$(printf "%04x" ${I2C_ADDR_CPLD})/cpld_version" + printf "[CPLD %d] %s\n" ${i} $(cat ${file_path}) + done +} + +#Get PSU Status +function _i2c_psu_status { + local psu_abs="" + + psu1PwGood=`cat ${PATH_SYSFS_PSU1}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU1}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu1Exist=1 + else + psu1Exist=0 + fi + + psu2PwGood=`cat ${PATH_SYSFS_PSU2}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU2}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu2Exist=1 + else + psu2Exist=0 + fi + + printf "PSU1 Exist:%x PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Get register value from CPLD +function _i2c_cpld_reg_read { + local idx=$1 + local file_name=$2 + local cpld_i2c_addr=${I2C_ADDR_CPLD} + local reg_file_path + + case ${idx} in + 1) + cpld_i2c_bus=${I2C_BUS_CPLD1} + ;; + 2) + cpld_i2c_bus=${I2C_BUS_CPLD2} + ;; + 3) + cpld_i2c_bus=${I2C_BUS_CPLD3} + ;; + 4) + cpld_i2c_bus=${I2C_BUS_CPLD4} + ;; + 5) + cpld_i2c_bus=${I2C_BUS_CPLD5} + ;; + *) + echo "invalid cpld index" + exit + ;; + esac + + reg_file_path="${PATH_SYS_I2C_DEVICES}/${cpld_i2c_bus}-$(printf "%04x" ${cpld_i2c_addr})/${file_name}" + cpld_reg_val=`cat ${reg_file_path}` +} + +#util functions +function _util_i2cset { + if [ "$DEBUG" == "on" ]; then + i2cset $@ + else + i2cset $@ 1>/dev/null + fi +} + +function _i2c_set { + local i2c_bus=$1 + local i2c_addr=$2 + local reg=$3 + local mask=$4 + local value=$5 + + echo `i2cset -m $mask -y -r ${i2c_bus} ${i2c_addr} ${reg} ${value}` +} + +function _util_rmmod { + local mod=$1 + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod +} + +# get qsfp presence +function _util_get_qsfp_abs { + local phy_port=0 + + #get physical port + phy_port=$(_port_fp2phy $QSFP_PORT) + + # read status from cpld + _qsfp_cpld_var_set ${phy_port} + cpld_reg_file_name="${CPLD_QSFP_STATUS_KEY}_${cpld_port_index}" + _i2c_cpld_reg_read ${cpld_index} ${cpld_reg_file_name} + #status: 0 -> Down, 1 -> Up (ACTIVE_LOW in ABS_BIT) + status=$(( $(( $((${cpld_reg_val})) & (1 << ($CPLD_QSFP_STATUS_ABS_BIT)) ))?0:1 )) +} + +# get sfp presence +function _util_get_sfp_pres { + local pres_bit + # read status from cpld + _sfp_cpld_var_set ${SFP_PORT} + cpld_reg_file_name="${CPLD_SFP_STATUS_KEY}" + _i2c_cpld_reg_read ${cpld_index} ${cpld_reg_file_name} + if [ "${SFP_PORT}" == "1" ]; then + pres_bit=${CPLD_SFP0_STATUS_PRES_BIT} + else + pres_bit=${CPLD_SFP1_STATUS_PRES_BIT} + fi + #status: 0 -> Down, 1 -> Up (ACTIVE_LOW in PRES_BIT) + status=$(( $(( $((${cpld_reg_val})) & (1 << ($pres_bit)) ))?0:1 )) +} + +# valid input number +function _util_input_check { + # input parameter validation + if [[ $1 -lt $2 || $1 -gt $3 ]]; then + echo "Please input number $2~$3" + exit + fi +} + +# clear all switch port led bitmap +function _util_port_led_clear { + echo "port led clear..." + # gpio pin on GPIO MUX PCA9539#1 I/O 0.2 + # pull low to reset bitamp + output_reg=${REG_PORT0_OUT} + mask=0x04 + value=0x00 + _util_i2cset -m ${mask} -y ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_1} ${output_reg} ${value} + sleep 1 + # pull high to out of reset + value=0xFF + _util_i2cset -m ${mask} -y ${NUM_MUX_9546_1_CH3} ${I2C_ADDR_MUX_9539_1} ${output_reg} ${value} + echo "Done" +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +# util function to get logx value +function logx { + v=$1 + n=$2 + logx_res=$(echo "${v} ${n}" | awk '{printf "%f\n",log($1)/log($2)}') +} + +# get qsfp ddm data +function _i2c_qsfp_ddm_get { + local phy_port=0 + + phy_port=$(_port_fp2phy ${QSFP_PORT}) + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + # check if port presence + #status: 0 -> Down, 1 -> Up + _util_get_qsfp_abs + if [ "${status}" == "0" ]; then + echo "port ${QSFP_PORT} not presence" + return + fi + + _qsfp_eeprom_var_set ${phy_port} + + # Get QSFP EEPROM info + # only need first 128 bytes (page0) for ddm parsing + local size=128 + eeprom_path="${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom" + #echo "get ${eeprom_path}" + qsfp_info=$(dd if=${eeprom_path} bs=${size} count=1 2>/dev/null | base64) + + # temperature + temp_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s 22 -n 1 -e '"%d"') + temp_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s 23 -n 1 -e '"%d"') + temp=$(echo "$temp_val1 $temp_val2" | awk '{printf "%f\n", $1 + $2/256.0}') + #temp=$(( ${temp_val1} + ${temp_val2}/256.0 )) + echo "temp=$temp" + # voltage + volt_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s 26 -n 1 -e '"%d"') + volt_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s 27 -n 1 -e '"%d"') + #volt=$(((($volt_val1 << 8) | volt_val2) / 10000)) + volt_val3=$(( ($volt_val1 << 8) | $volt_val2 )) + volt=$(echo "$volt_val3" | awk '{printf "%f\n", $1/10000.0}') + echo "volt=$volt" + + # 4 channels + for i in {0..3}; + do + echo "channel $i:" + # txBias + offset=$(( 42 + $i*2 )) + txBias_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 43 + $i*2 )) + txBias_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + txBias_val3=$(( ($txBias_val1 << 8) | $txBias_val2 )) + txBias=$(echo "$txBias_val3" | awk '{printf "%f\n", (131.0*$1)/65535}') + echo " txBias=$txBias" + # txPower + offset=$(( 50 + $i*2 )) + txPower_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 51 + $i*2 )) + txPower_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + txPower_val3=$(( ($txPower_val1 << 8) | $txPower_val2 )) + txPower_val4=$(echo "$txPower_val3" | awk '{printf "%f\n", $1*0.0001}') + logx $txPower_val4 10 + txPower=$(echo "$logx_res" | awk '{printf "%f\n", $1*10}') + echo " txPower=$txPower" + # rxPower + offset=$(( 34 + $i*2 )) + rxPower_val1=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + offset=$(( 35 + $i*2 )) + rxPower_val2=$(echo $qsfp_info | base64 -d -i | hexdump -s $offset -n 1 -e '"%d"') + rxPower_val3=$(( ($rxPower_val1 << 8) | $rxPower_val2 )) + rxPower_val4=$(echo "$rxPower_val3" | awk '{printf "%f\n", $1*0.0001}') + logx $rxPower_val4 10 + rxPower=$(echo "$logx_res" | awk '{printf "%f\n", $1*10}') + echo " rxPower=$rxPower" + done +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_fan_speed_init" ]; then + _i2c_fan_speed_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_get" ]; then + _i2c_cb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_eeprom_sync" ]; then + _i2c_eeprom_sync + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_get" ]; then + _i2c_sfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_init" ]; then + _i2c_sfp_eeprom_init ${SFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_init" ]; then + _i2c_cb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_status_get" ]; then + _i2c_sfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_type_get" ]; then + _i2c_sfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_ddm_get" ]; then + _i2c_qsfp_ddm_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_bmc_board_type_get" ]; then + _i2c_bmc_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cb_eeprom_get + _i2c_board_type_get + _i2c_bmc_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main 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 new file mode 100755 index 000000000000..9213d115f656 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/qsfp_monitor.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..63}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`sonic-db-cli ASIC_DB HLEN HIDDEN` + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/s9280_64x_monitor.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/s9280_64x_monitor.sh new file mode 100755 index 000000000000..eedf685b290b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9280-64x/utils/s9280_64x_monitor.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# TBD: LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + #PSU controlled by dummy board, + #but fan LED and fan tray LED must controlled by this service + _led_monitor + + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/LICENSE b/platform/barefoot/sonic-platform-modules-wnc-osw1800/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/MAINTAINERS b/platform/barefoot/sonic-platform-modules-wnc-osw1800/MAINTAINERS new file mode 100644 index 000000000000..a578b60e24de --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/MAINTAINERS @@ -0,0 +1,7 @@ +# This file describes the maintainers for sonic-platform-modules-wnc-osw1800 +# See the SONiC project governance document for more information + +Name = "WNC" +Email = "wnc@wnc.com.tw" +Github = barefootnetworks +Mailinglist = wnc@wnc.com.tw diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/README.md b/platform/barefoot/sonic-platform-modules-wnc-osw1800/README.md new file mode 100644 index 000000000000..707c1068d6e6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-wnc-osw1800 +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/changelog b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/changelog new file mode 100644 index 000000000000..466378b892d1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/changelog @@ -0,0 +1,5 @@ +platform-modules-wnc-osw1800 (1.0) unstable; urgency=low + + * Initial release + + -- WNC Mon, 11 Nov 2015 11:11:11 -0800 diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/compat b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control new file mode 100644 index 000000000000..eab1adcadecd --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control @@ -0,0 +1,12 @@ +Source: platform-modules-wnc-osw1800 +Section: main +Priority: extra +Maintainer: WNC +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-wnc-osw1800 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/copyright b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/rules b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/rules new file mode 100755 index 000000000000..644ab1ade433 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/rules @@ -0,0 +1,38 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_NAME := platform-modules-wnc-osw1800 +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MODULE_SRC := $(shell pwd)/modules +SCRIPT_SRC := $(shell pwd)/scripts +SERVICE_SRC := $(shell pwd)/service + +%: + dh $@ + +override_dh_auto_build: + make -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR) + cp $(MODULE_SRC)/*.ko debian/$(PACKAGE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin + dh_installdirs -p$(PACKAGE_NAME) /etc/systemd/system + cp -r $(SERVICE_SRC)/* debian/$(PACKAGE_NAME)/etc/systemd/system + dh_installdirs -p$(PACKAGE_NAME) /etc/systemd/system/multi-user.target.wants + ln -s ../device_node.service debian/$(PACKAGE_NAME)/etc/systemd/system/multi-user.target.wants/device_node.service + ln -s ../driver_load.service debian/$(PACKAGE_NAME)/etc/systemd/system/multi-user.target.wants/driver_load.service + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + rm -f $(MODULE_SRC)/*.o $(MODULE_SRC)/*.ko $(MODULE_SRC)/*.mod.c $(MODULE_SRC)/.*.cmd + rm -f $(MODULE_SRC)/Module.markers $(MODULE_SRC)/Module.symvers $(MODULE_SRC)/modules.order + rm -rf $(MODULE_SRC)/.tmp_versions + diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/Makefile b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/Makefile new file mode 100644 index 000000000000..f01694d73eaf --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/Makefile @@ -0,0 +1,4 @@ +obj-m += i2c-mcp2221.o +obj-m += wnc_cpld.o +obj-m += wnc_cpld3.o +obj-m += wnc_eeprom.o diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/i2c-mcp2221.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/i2c-mcp2221.c new file mode 100644 index 000000000000..fcaa57fbafac --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/i2c-mcp2221.c @@ -0,0 +1,611 @@ +/* + * i2c bus driver for MCP2221 + * + * Derived from: + * i2c-tiny-usb.c + * i2c-diolan-u2c.c + * usb-serial.c + * onetouch.c + * usb-skeleton.c + * + * Copyright (C) 2014 Microchip Technology Inc. + * + * Author: Bogdan Bolocan http://www.microchip.com/support + * + * 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. + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "i2c-mcp2221" + +#define USB_VENDOR_ID_MCP2221 0x04d8 +#define USB_DEVICE_ID_MCP2221 0x00dd + +#define MCP2221_OUTBUF_LEN 64 /* USB write packet length */ +#define MCP2221_INBUF_LEN 64 /* USB read packet length */ + +#define MCP2221_MAX_I2C_DATA_LEN 60 + +//#define MCP2221_FREQ_STD 100000 +#define MCP2221_FREQ_STD 400000 +//#define MCP2221_FREQ_STD 50000 +#define MCP2221_FREQ_MAX 500000 + +#define MCP2221_RETRY_MAX 50 +#define MCP2221_STD_DELAY_MS 1 +//#define MCP2221_STD_DELAY_MS 2 + +#define RESP_ERR_NOERR 0x00 +#define RESP_ADDR_NACK 0x25 +#define RESP_READ_ERR 0x7F +#define RESP_READ_COMPL 0x55 +#define RESP_I2C_IDLE 0x00 +#define RESP_I2C_START_TOUT 0x12 +#define RESP_I2C_RSTART_TOUT 0x17 +#define RESP_I2C_WRADDRL_TOUT 0x23 +#define RESP_I2C_WRADDRL_WSEND 0x21 +#define RESP_I2C_WRADDRL_NACK 0x25 +#define RESP_I2C_WRDATA_TOUT 0x44 +#define RESP_I2C_RDDATA_TOUT 0x52 +#define RESP_I2C_STOP_TOUT 0x62 + +#define CMD_MCP2221_STATUS 0x10 +#define SUBCMD_STATUS_CANCEL 0x10 +#define SUBCMD_STATUS_SPEED 0x20 +#define MASK_ADDR_NACK 0x40 + +#define CMD_MCP2221_RDDATA7 0x91 +#define CMD_MCP2221_GET_RDDATA 0x40 + +#define CMD_MCP2221_WRDATA7 0x90 + +/* Structure to hold all of our device specific stuff */ +struct i2c_mcp2221 { + u8 obuffer[MCP2221_OUTBUF_LEN]; /* USB write buffer */ + u8 ibuffer[MCP2221_INBUF_LEN]; /* USB read buffer */ + /* I2C/SMBus data buffer */ + u8 user_data_buffer[MCP2221_MAX_I2C_DATA_LEN]; + int ep_in, ep_out; /* Endpoints */ + struct usb_device *usb_dev; /* the usb device for this device */ + struct usb_interface *interface;/* the interface for this device */ + struct i2c_adapter adapter; /* i2c related things */ + uint frequency; /* I2C/SMBus communication frequency */ + /* Mutex for low-level USB transactions */ + struct mutex mcp2221_usb_op_lock; + /* wq to wait for an ongoing read/write */ + wait_queue_head_t usb_urb_completion_wait; + bool ongoing_usb_ll_op; /* a ll is in progress */ + + struct urb *interrupt_in_urb; + struct urb *interrupt_out_urb; +}; + +static uint frequency = MCP2221_FREQ_STD; /* I2C clock frequency in Hz */ + +module_param(frequency, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(frequency, "I2C clock frequency in hertz"); + +/* usb layer */ + + +/* + * Return list of supported functionality. + */ +static u32 mcp2221_usb_func(struct i2c_adapter *a) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL; +} + +static void mcp2221_usb_cmpl_cbk(struct urb *urb) +{ + struct i2c_mcp2221 *dev = urb->context; + int status = urb->status; + int retval; + + switch (status) { + case 0: /* success */ + break; + case -ECONNRESET: /* unlink */ + case -ENOENT: + case -ESHUTDOWN: + return; + /* -EPIPE: should clear the halt */ + default: /* error */ + goto resubmit; + } + + /* wake up the waitting function + modify the flag indicating the ll status */ + dev->ongoing_usb_ll_op = 0; + wake_up_interruptible(&dev->usb_urb_completion_wait); + return; + +resubmit: + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) { + dev_err(&dev->interface->dev, + "mcp2221(irq): can't resubmit intrerrupt urb, retval %d\n", + retval); + } +} + +static int mcp2221_ll_cmd(struct i2c_mcp2221 *dev) +{ + int rv; + + /* tell everybody to leave the URB alone */ + dev->ongoing_usb_ll_op = 1; + + /* submit the interrupt out ep packet */ + if (usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL)) { + dev_err(&dev->interface->dev, + "mcp2221(ll): usb_submit_urb intr out failed\n"); + dev->ongoing_usb_ll_op = 0; + return -EIO; + } + + /* wait for its completion */ + rv = wait_event_interruptible(dev->usb_urb_completion_wait, + (!dev->ongoing_usb_ll_op)); + if (rv < 0) { + dev_err(&dev->interface->dev, "mcp2221(ll): wait interrupted\n"); + goto ll_exit_clear_flag; + } + + /* tell everybody to leave the URB alone */ + dev->ongoing_usb_ll_op = 1; + + /* submit the interrupt in ep packet */ + if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL)) { + dev_err(&dev->interface->dev, "mcp2221(ll): usb_submit_urb intr in failed\n"); + dev->ongoing_usb_ll_op = 0; + return -EIO; + } + + /* wait for its completion */ + rv = wait_event_interruptible(dev->usb_urb_completion_wait, + (!dev->ongoing_usb_ll_op)); + if (rv < 0) { + dev_err(&dev->interface->dev, "mcp2221(ll): wait interrupted\n"); + goto ll_exit_clear_flag; + } + +ll_exit_clear_flag: + dev->ongoing_usb_ll_op = 0; + return rv; +} + +static int mcp2221_init(struct i2c_mcp2221 *dev) +{ + int ret; + + ret = 0; + if (frequency > MCP2221_FREQ_MAX) + frequency = MCP2221_FREQ_MAX; + + /* initialize the MCP2221 and bring it to "idle/ready" state */ + dev_info(&dev->interface->dev, + "MCP2221 at USB bus %03d address %03d Freq=%dKhz-- mcp2221_init()\n", + dev->usb_dev->bus->busnum, dev->usb_dev->devnum, frequency/1000); + + /* initialize unlocked mutex */ + mutex_init(&dev->mcp2221_usb_op_lock); + + dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->interrupt_out_urb) + goto init_error; + + usb_fill_int_urb(dev->interrupt_out_urb, dev->usb_dev, + usb_sndintpipe(dev->usb_dev, + dev->ep_out), + (void *)&dev->obuffer, MCP2221_OUTBUF_LEN, + mcp2221_usb_cmpl_cbk, dev, + 1); + + dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->interrupt_in_urb) + goto init_error; + + usb_fill_int_urb(dev->interrupt_in_urb, dev->usb_dev, + usb_rcvintpipe(dev->usb_dev, + dev->ep_in), + (void *)&dev->ibuffer, MCP2221_INBUF_LEN, + mcp2221_usb_cmpl_cbk, dev, + 1); + ret = 0; + goto init_no_error; + +init_error: + dev_err(&dev->interface->dev, "mcp2221_init: Error = %d\n", ret); + ret = -ENODEV; + +init_no_error: + dev_info(&dev->interface->dev, "mcp2221_init: Success\n"); + return ret; +} + +static int mcp2221_i2c_readwrite(struct i2c_mcp2221 *dev, + struct i2c_msg *pmsg) +{ + u8 ucI2cDiv, ucCancelXfer, ucXferLen; + int rv, retries; + unsigned int sleepCmd; + u8 *pSrc, *pDst, usbCmdStatus; + + retries = 0; + ucCancelXfer = 0; + /* clock divider for I2C operations */ + ucI2cDiv = (u8)((12000000/frequency) - 3); + + /* determine the best delay value here */ + /* (MCP2221_STD_DELAY_MS * MCP2221_FREQ_MAX)/frequency; */ + sleepCmd = MCP2221_STD_DELAY_MS; + + if (pmsg->len > MCP2221_MAX_I2C_DATA_LEN) + return -EINVAL; + +readwrite_reinit: + dev->obuffer[0] = CMD_MCP2221_STATUS; /* code for STATUS cmd */ + dev->obuffer[1] = 0x00; + dev->obuffer[2] = ucCancelXfer; /* cancel subcmd */ + dev->obuffer[3] = SUBCMD_STATUS_SPEED; /* set the xfer speed */ + dev->obuffer[4] = ucI2cDiv; + dev->obuffer[5] = 0x00; + dev->obuffer[6] = 0x00; + dev->obuffer[7] = 0x00; + + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + if (dev->ibuffer[3] != SUBCMD_STATUS_SPEED) { + /* the speed could not be set - wait a while and retry */ + if (retries < MCP2221_RETRY_MAX) { + /* wait a while and retry the operation */ + retries++; + msleep(MCP2221_STD_DELAY_MS); + ucCancelXfer = SUBCMD_STATUS_CANCEL; + goto readwrite_reinit; + } else { + /* max number of retries was reached - return error */ + dev_err(&dev->interface->dev, + "mcp2221 CANCEL ERROR:retries = %d\n", retries); + return -EFAULT; + } + } + + if (pmsg->flags & I2C_M_RD) { + /* I2C read */ + ucXferLen = (u8)pmsg->len; + dev->obuffer[0] = CMD_MCP2221_RDDATA7; + dev->obuffer[1] = ucXferLen; /* LSB of the xfer length */ + dev->obuffer[2] = 0; /* no MSB for the xfer length */ + /* address in 8-bit format */ + dev->obuffer[3] = (u8)((pmsg->addr) << 1); + + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + retries = 0; + dev->obuffer[0] = CMD_MCP2221_GET_RDDATA; + dev->obuffer[1] = 0x00; + dev->obuffer[2] = 0x00; + dev->obuffer[3] = 0x00; + + while (retries < MCP2221_RETRY_MAX) { + msleep(sleepCmd); + + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + if (dev->ibuffer[2] == RESP_ADDR_NACK) + return -EFAULT; + + /* break the loop - cmd ended ok - used for bus scan */ + if ((dev->ibuffer[3] == 0x00) && + (dev->ibuffer[2] == 0x00)) + break; + + if (dev->ibuffer[3] == RESP_READ_ERR) { + retries++; + continue; + } + + if ((dev->ibuffer[2] == RESP_READ_COMPL) && + (dev->ibuffer[3] == ucXferLen)) { + /* we got the data - copy it */ + pSrc = (u8 *)&dev->ibuffer[4]; + pDst = (u8 *)&pmsg->buf[0]; + memcpy(pDst, pSrc, ucXferLen); + + if (pmsg->flags & I2C_M_RECV_LEN) + pmsg->len = ucXferLen; + + break; + } + + } + if (retries >= MCP2221_RETRY_MAX) + return -EFAULT; + } else { + /* I2C write */ + ucXferLen = (u8)pmsg->len; + dev->obuffer[0] = CMD_MCP2221_WRDATA7; + dev->obuffer[1] = ucXferLen; /* LSB of the xfer length */ + dev->obuffer[2] = 0; /* no MSB for the xfer length */ + /* address in 8-bit format */ + dev->obuffer[3] = (u8)((pmsg->addr) << 1); + /* copy the data we've read back */ + pSrc = (u8 *)&pmsg->buf[0]; + pDst = (u8 *)&dev->obuffer[4]; + memcpy(pDst, pSrc, ucXferLen); + + retries = 0; + + while (retries < MCP2221_RETRY_MAX) { + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) { + usbCmdStatus = dev->ibuffer[2]; + if (usbCmdStatus == RESP_I2C_START_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_NACK) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRDATA_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_STOP_TOUT) + return -EFAULT; + + msleep(sleepCmd); + retries++; + continue; + } else { /* command completed successfully */ + break; + } + } + if (retries >= MCP2221_RETRY_MAX) + return -EFAULT; + + /* now, prepare for the STATUS stage */ + retries = 0; + dev->obuffer[0] = CMD_MCP2221_STATUS; /* code for STATUS cmd */ + dev->obuffer[1] = 0x00; + dev->obuffer[2] = 0x00; + dev->obuffer[3] = 0x00; + dev->obuffer[4] = 0x00; + dev->obuffer[5] = 0x00; + dev->obuffer[6] = 0x00; + dev->obuffer[7] = 0x00; + + while (retries < MCP2221_RETRY_MAX) { + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + /* i2c slave address was nack-ed */ + if (dev->ibuffer[20] & MASK_ADDR_NACK) + return -EFAULT; + + usbCmdStatus = dev->ibuffer[8]; + if (usbCmdStatus == RESP_I2C_IDLE) + break; + + if (usbCmdStatus == RESP_I2C_START_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_WSEND) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_NACK) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRDATA_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_STOP_TOUT) + return -EFAULT; + + msleep(sleepCmd); + retries++; + } + if (retries >= MCP2221_RETRY_MAX) + return -EFAULT; + } + + return 0; +} + +/* device layer */ +static int mcp2221_usb_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct i2c_mcp2221 *dev = i2c_get_adapdata(adap); + struct i2c_msg *pmsg; + int ret, count; + + for (count = 0; count < num; count++) { + pmsg = &msgs[count]; + /* no concurrent users of the mcp2221 i2c xfer */ + ret = mutex_lock_interruptible(&dev->mcp2221_usb_op_lock); + if (ret < 0) + goto abort; + + ret = mcp2221_i2c_readwrite(dev, pmsg); + mutex_unlock(&dev->mcp2221_usb_op_lock); + if (ret < 0) + goto abort; + } + + /* if all the messages were transferred ok, return "num" */ + ret = num; + +abort: + return ret; +} + +static const struct i2c_algorithm mcp2221_usb_algorithm = { + .master_xfer = mcp2221_usb_i2c_xfer, + .functionality = mcp2221_usb_func, +}; + +static const struct usb_device_id mcp2221_table[] = { + { USB_DEVICE(USB_VENDOR_ID_MCP2221, USB_DEVICE_ID_MCP2221) }, + { } +}; + +MODULE_DEVICE_TABLE(usb, mcp2221_table); + +static void mcp2221_free(struct i2c_mcp2221 *dev) +{ + usb_put_dev(dev->usb_dev); + kfree(dev); +} + +static int mcp2221_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_host_interface *hostif = interface->cur_altsetting; + struct i2c_mcp2221 *dev; + int ret; + + if ((hostif->desc.bInterfaceNumber != 2) + || (hostif->desc.bInterfaceClass != 3)) { + pr_info("i2c-mcp2221(probe): Interface doesn't match the MCP2221 HID\n"); + return -ENODEV; + } + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + pr_info("i2c-mcp2221(probe): no memory for device state\n"); + ret = -ENOMEM; + goto error; + } + + dev->ep_in = hostif->endpoint[0].desc.bEndpointAddress; + dev->ep_out = hostif->endpoint[1].desc.bEndpointAddress; + + dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; + + init_waitqueue_head(&dev->usb_urb_completion_wait); + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* setup i2c adapter description */ + dev->adapter.owner = THIS_MODULE; + dev->adapter.class = I2C_CLASS_HWMON; + dev->adapter.algo = &mcp2221_usb_algorithm; + i2c_set_adapdata(&dev->adapter, dev); + + snprintf(dev->adapter.name, sizeof(dev->adapter.name), + DRIVER_NAME " at bus %03d device %03d", + dev->usb_dev->bus->busnum, dev->usb_dev->devnum); + + dev->adapter.dev.parent = &dev->interface->dev; + + /* initialize mcp2221 i2c interface */ + ret = mcp2221_init(dev); + if (ret < 0) { + dev_err(&interface->dev, "failed to initialize adapter\n"); + goto error_free; + } + + /* and finally attach to i2c layer */ + ret = i2c_add_adapter(&dev->adapter); + if (ret < 0) { + dev_err(&interface->dev, "failed to add I2C adapter\n"); + goto error_free; + } + + dev_info(&dev->interface->dev, + "mcp2221_probe() -> chip connected -> Success\n"); + return 0; + +error_free: + usb_set_intfdata(interface, NULL); + mcp2221_free(dev); +error: + return ret; +} + +static void mcp2221_disconnect(struct usb_interface *interface) +{ + struct i2c_mcp2221 *dev = usb_get_intfdata(interface); + + i2c_del_adapter(&dev->adapter); + + usb_kill_urb(dev->interrupt_in_urb); + usb_kill_urb(dev->interrupt_out_urb); + usb_free_urb(dev->interrupt_in_urb); + usb_free_urb(dev->interrupt_out_urb); + + usb_set_intfdata(interface, NULL); + mcp2221_free(dev); + + pr_info("i2c-mcp2221(disconnect) -> chip disconnected"); +} + +static struct usb_driver mcp2221_driver = { + .name = DRIVER_NAME, + .probe = mcp2221_probe, + .disconnect = mcp2221_disconnect, + .id_table = mcp2221_table, +}; + +module_usb_driver(mcp2221_driver); + +MODULE_AUTHOR("Bogdan Bolocan"); +MODULE_DESCRIPTION(DRIVER_NAME "I2C MCP2221"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld.c new file mode 100644 index 000000000000..3a7d40ba9177 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld.c @@ -0,0 +1,198 @@ +/* + * wnc_cpld.c - A driver for control wnc_cpld base on lm75.c + * + * Copyright (c) 1998, 1999 Frodo Looijaard + * Copyright (c) 2017 WNC + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x31, 0x32, I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define CPLD_SIZE 3 + +/* Each client has this additional data */ +struct cpld_data { + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[CPLD_SIZE]; /* Register value */ +}; + +static ssize_t show_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + data->data[0] = i2c_smbus_read_byte_data(client, attr->index); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%02x\n", data->data[0]); +} + +static ssize_t set_value(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 temp; + int error; + + error = kstrtou8(buf, 10, &temp); + if (error) + return error; + + mutex_lock(&data->update_lock); + i2c_smbus_write_byte_data(client, attr->index, temp); + mutex_unlock(&data->update_lock); + + return count; +} + +static SENSOR_DEVICE_ATTR(reset_control, S_IWUSR | S_IRUGO, show_value, set_value, 2); +static SENSOR_DEVICE_ATTR(sfp_mod_abs1, S_IRUGO, show_value, NULL, 3); +static SENSOR_DEVICE_ATTR(sfp_mod_abs2, S_IRUGO, show_value, NULL, 4); +static SENSOR_DEVICE_ATTR(sfp_mod_abs3, S_IRUGO, show_value, NULL, 5); +static SENSOR_DEVICE_ATTR(sfp_mod_abs4, S_IRUGO, show_value, NULL, 6); +static SENSOR_DEVICE_ATTR(qsfp_modprs, S_IRUGO, show_value, NULL, 22); +static SENSOR_DEVICE_ATTR(qsfp_lpmode, S_IWUSR | S_IRUGO, show_value, set_value, 24); + +static struct attribute *cpld2_attributes[] = { + &sensor_dev_attr_reset_control.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs1.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs2.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs3.dev_attr.attr, + &sensor_dev_attr_qsfp_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_lpmode.dev_attr.attr, + NULL +}; + +static struct attribute *cpld1_attributes[] = { + &sensor_dev_attr_sfp_mod_abs1.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs2.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs3.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs4.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld2_group = { + .attrs = cpld2_attributes, +}; + +static const struct attribute_group cpld1_group = { + .attrs = cpld1_attributes, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int cpld_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int conf; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + /* Unused bits */ + conf = i2c_smbus_read_byte_data(new_client, 0); + if (!conf) + return -ENODEV; + + return 0; +} + + +static int cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; +#if 1 + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); +#endif + + if (client->addr == 49) /* 0x31 */ + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld1_group); + else if (client->addr == 50) /* 0x32 */ + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld2_group); + else + status = 1; + + if (status) + return status; + + dev_info(&client->dev, "cpld 0x%x found\n", client->addr); + + return 0; +} + +static int cpld_remove(struct i2c_client *client) +{ + if (client->addr == 49) /* 0x31 */ + sysfs_remove_group(&client->dev.kobj, &cpld1_group); + else if (client->addr == 50) /* 0x32 */ + sysfs_remove_group(&client->dev.kobj, &cpld2_group); + else + return 1; + + return 0; +} + +static const struct i2c_device_id cpld_id[] = { + { "wnc_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "wnc_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, + .detect = cpld_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("WNC "); +MODULE_DESCRIPTION("WNC CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld3.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld3.c new file mode 100644 index 000000000000..a24698aa9cef --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld3.c @@ -0,0 +1,200 @@ +/* + * wnc_cpld.c - A driver for control wnc_cpld3 base on lm75.c + * + * Copyright (c) 1998, 1999 Frodo Looijaard + * Copyright (c) 2017 WNC + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x33, I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define CPLD_SIZE 3 + +/* Each client has this additional data */ +struct cpld_data { + struct i2c_client *client; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[CPLD_SIZE]; /* Register value */ +}; + +static ssize_t show_hwmon_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int index = to_sensor_dev_attr_2(da)->index; + + mutex_lock(&data->update_lock); + data->data[0] = i2c_smbus_read_byte_data(client, index); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", data->data[0]); +} + +static ssize_t show_sysfs_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + data->data[0] = i2c_smbus_read_byte_data(client, attr->index); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%02x\n", data->data[0]); +} + +static ssize_t set_hwmon_value(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int index = to_sensor_dev_attr_2(da)->index; + u8 temp; + int error; + + error = kstrtou8(buf, 10, &temp); + if (error) + return error; + + mutex_lock(&data->update_lock); + i2c_smbus_write_byte_data(client, index, temp); + mutex_unlock(&data->update_lock); + + return count; +} + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_hwmon_value, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_hwmon_value, NULL, 7); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_hwmon_value, NULL, 8); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_hwmon_value, NULL, 9); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_hwmon_value, NULL, 10); +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 6); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 7); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 8); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 9); +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 10); + +static struct attribute *cpld3_hwmon_attrs[] = { + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm5.dev_attr.attr, + NULL +}; + +ATTRIBUTE_GROUPS(cpld3_hwmon); + +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, show_sysfs_value, NULL, 1); +static SENSOR_DEVICE_ATTR(power_good, S_IRUGO, show_sysfs_value, NULL, 4); + +static struct attribute *cpld3_sysfs_attrs[] = { + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_power_good.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld3_sysfs_group = { + .attrs = cpld3_sysfs_attrs, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int cpld_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int conf; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + /* Unused bits */ + conf = i2c_smbus_read_byte_data(new_client, 0); + if (!conf) + return -ENODEV; + + return 0; +} + + +static int cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct device *hwmon_dev; + struct cpld_data *data; + int status; + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + status = sysfs_create_group(&client->dev.kobj, &cpld3_sysfs_group); + hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, client->name, data, cpld3_hwmon_groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static int cpld_remove(struct i2c_client *client) +{ + devm_hwmon_device_unregister(&client->dev); + sysfs_remove_group(&client->dev.kobj, &cpld3_sysfs_group); + return 0; +} + +static const struct i2c_device_id cpld_id[] = { + { "wnc_cpld3", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "wnc_cpld3", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, + .detect = cpld_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("WNC "); +MODULE_DESCRIPTION("WNC CPLD3 driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_eeprom.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_eeprom.c new file mode 100644 index 000000000000..8f05e5c09ada --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_eeprom.c @@ -0,0 +1,268 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +/* possible types of eeprom devices */ +enum eeprom_nature { + UNKNOWN, + VAIO, +}; + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[8]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ + enum eeprom_nature nature; +}; + + +static void eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + for (i = slice << 5; i < (slice + 1) << 5; i += 24) + if (i2c_smbus_read_i2c_block_data(client, i, + 24, data->data + i) + != 24) + goto exit; + } else { + for (i = slice << 5; i < (slice + 1) << 5; i += 2) { + int word = i2c_smbus_read_word_data(client, i); + if (word < 0) + goto exit; + data->data[i] = word & 0xff; + data->data[i + 1] = word >> 8; + } + } + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(kobj_to_dev(kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++) + eeprom_update_client(client, slice); + + /* Hide Vaio private settings to regular users: + - BIOS passwords: bytes 0x00 to 0x0f + - UUID: bytes 0x10 to 0x1f + - Serial number: 0xc0 to 0xdf */ + if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) { + int i; + + for (i = 0; i < count; i++) { + if ((off + i <= 0x1f) || + (off + i >= 0xc0 && off + i <= 0xdf)) + buf[i] = 0; + else + buf[i] = data->data[off + i]; + } + } else { + memcpy(buf, &data->data[off], count); + } + + return count; +} + +static ssize_t eeprom_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(kobj_to_dev(kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 temp; + int error, reg; + + mutex_lock(&data->update_lock); + + error = kstrtou8(buf, 10, &temp); + if (error) + return error; + + if (client->addr == 0x51) { /* SFP AOC cable, page selection byte is 126 */ + reg = 126; + } + else if (client->addr == 0x50) { /* QSFP, page selection byte is 127 */ + data->data[0] = i2c_smbus_read_byte_data(client, 0); + + /* Base on SFF-8024, determine this module is SFP or QSFP by byte 0 (Identifier) */ + switch (data->data[0]){ + case 12: + case 13: + case 17: + case 24: + reg = 127; + break; + + default: + goto exit; + } + } + else + goto exit; + + i2c_smbus_write_byte_data(client, reg, temp); + +exit: + mutex_unlock(&data->update_lock); + + return count; +} + +static struct bin_attribute eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IWUSR | S_IRUGO | S_IWGRP | S_IWOTH, + }, + .size = EEPROM_SIZE, + .read = eeprom_read, + .write = eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) + return -ENODEV; + + /* There are four ways we can read the EEPROM data: + (1) I2C block reads (faster, but unsupported by most adapters) + (2) Word reads (128% overhead) + (3) Consecutive byte reads (88% overhead, unsafe) + (4) Regular byte data reads (265% overhead) + The third and fourth methods are not implemented by this driver + because all known adapters support one of the first two. */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) + return -ENODEV; + + strlcpy(info->type, "wnc_eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct eeprom_data *data; + + data = devm_kzalloc(&client->dev, sizeof(struct eeprom_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->nature = UNKNOWN; + + /* Detect the Vaio nature of EEPROMs. + We use the "PCG-" or "VGN-" prefix as the signature. */ + if (client->addr == 0x57 + && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + char name[4]; + + name[0] = i2c_smbus_read_byte_data(client, 0x80); + name[1] = i2c_smbus_read_byte_data(client, 0x81); + name[2] = i2c_smbus_read_byte_data(client, 0x82); + name[3] = i2c_smbus_read_byte_data(client, 0x83); + + if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { + dev_info(&client->dev, "Vaio EEPROM detected, " + "enabling privacy protection\n"); + data->nature = VAIO; + } + } + + /* create the sysfs eeprom file */ + return sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr); +} + +static int eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); + + return 0; +} + +static const struct i2c_device_id eeprom_id[] = { + { "wnc_eeprom", 0 }, + { } +}; + +static struct i2c_driver eeprom_driver = { + .driver = { + .name = "wnc_eeprom", + }, + .probe = eeprom_probe, + .remove = eeprom_remove, + .id_table = eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(eeprom_driver); + +MODULE_AUTHOR("Frodo Looijaard and " + "Philip Edelbrock and " + "Greg Kroah-Hartman "); +MODULE_DESCRIPTION("I2C EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/device_node.sh b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/device_node.sh new file mode 100644 index 000000000000..7e1c7c45a725 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/device_node.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +SEARCH_I2C_BUS=$(ls /sys/bus/i2c/devices) +I2C_BUS=-1 + +for i in $SEARCH_I2C_BUS +do + if [[ -n $(cat /sys/bus/i2c/devices/$i/name | grep i2c-mcp2221) ]]; then + I2C_BUS=$(echo $i | sed 's/i2c-//g') + break + fi +done + +if [[ $I2C_BUS == -1 ]]; then + echo "Can't find i2c-mcp2221" + exit +fi + +TOTAL_MUX=8 +START_NODE_NUM=$((I2C_BUS+1)) + +modprobe i2c_mux_pca954x force_deselect_on_exit=1 + +echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device + +sleep 5 + +/sbin/modprobe wnc_cpld +/sbin/modprobe wnc_cpld3 +/sbin/modprobe wnc_eeprom +/sbin/modprobe eeprom + +# MUX0: i2c-3~i2c-10 +# MUX1: i2c-11~i2c-18 +# MUX2: i2c-19~i2c-26 +# MUX3: i2c-27~i2c-34 +# MUX4: i2c-35~i2c-42 +# MUX5: i2c-43~i2c-50 +# MUX6: i2c-51~i2c-58 +# MUX7: i2c-59~i2c-66 + +# MUX0 channel0 +CHANNEL=0 +echo wnc_cpld 0x31 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel1 +CHANNEL=1 +echo wnc_cpld 0x32 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel2 +CHANNEL=2 +echo wnc_cpld3 0x33 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +echo wnc_eeprom 0x53 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel3 +CHANNEL=3 +echo wnc_eeprom 0x50 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +echo wnc_eeprom 0x51 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel4 +CHANNEL=4 +echo wnc_eeprom 0x54 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +echo tmp421 0x1E > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +sleep 1 +echo tmp75 0x4E > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +sleep 1 +echo tmp421 0x4F > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel5 +CHANNEL=5 +echo wnc_eeprom 0x52 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel7 +CHANNEL=7 +#echo wnc_eeprom 0x5B > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +START_PORT_NUM=$((START_NODE_NUM+8)) +END_PORT_NUM=$((TOTAL_MUX*8+1)) + +for i in $(seq $START_PORT_NUM $END_PORT_NUM) +do + echo wnc_eeprom 0x50 > /sys/bus/i2c/devices/i2c-$i/new_device + echo wnc_eeprom 0x51 > /sys/bus/i2c/devices/i2c-$i/new_device +done diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/driver_load.sh b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/driver_load.sh new file mode 100644 index 000000000000..81cee0383ff2 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/driver_load.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +vid=04d8 +pid=00dd + +#check to see if sysfs is mounted +sysfs_path=`awk '/^sysfs/{ print $2 }' < /proc/mounts` +curr_path=`pwd` + +#if variable is empty, we should exit. No SYSFS found +if [[ -z $sysfs_path ]]; then + echo "No sysfs in this system! Exiting..." + exit 1 +fi + +function load_drivers +{ + modprobe i2c-dev + if [[ $? -ne 0 ]]; then + echo "Cannot load the \"i2c-dev\" driver! Exiting..." + exit 1 + fi + modprobe i2c-mcp2221 + if [[ $? -ne 0 ]]; then + echo "Cannot load the \"i2c-mcp2221\" driver! Exiting..." + exit 1 + fi + echo "I2C related drivers are loaded" +} + +usb_device_path=${sysfs_path}/bus/usb/devices + +cd $usb_device_path + +for usbdev in *; do + idvendor=${usb_device_path}/${usbdev}/idVendor + idproduct=${usb_device_path}/${usbdev}/idProduct + usb_driver=${usb_device_path}/${usbdev}/${usbdev}:1.2/driver + if [[ -f $idvendor ]]; then + dev_vid=`grep -i $vid < $idvendor` + dev_pid=`grep -i $pid < $idproduct` + if [[ -n $dev_vid ]] && [[ -n $dev_pid ]]; then + echo "I found the requested VID/PID: $dev_vid, $dev_pid" + load_drivers + echo -n "${usbdev}:1.2" > ${usb_driver}/unbind + echo -n "${usbdev}:1.2" > ${sysfs_path}/bus/usb/drivers/i2c-mcp2221/bind + fi + fi +done + diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/test b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/test new file mode 100644 index 000000000000..38327722c91f --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/test @@ -0,0 +1 @@ +echo "test" diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/device_node.service b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/device_node.service new file mode 100644 index 000000000000..fd1bd9b15648 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/device_node.service @@ -0,0 +1,11 @@ +[Unit] +Description=Create device nodes for i2c devices. +Requires=driver_load.service +After=driver_load.service + +[Service] +Type=oneshot +ExecStart=/bin/bash /usr/local/bin/device_node.sh + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/driver_load.service b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/driver_load.service new file mode 100644 index 000000000000..52ce4d2f4442 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/driver_load.service @@ -0,0 +1,10 @@ +[Unit] +Description=Initialize i2c-mcp2221 driver. +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=/bin/bash /usr/local/bin/driver_load.sh + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/docker-saiserver-brcm.dep b/platform/broadcom/docker-saiserver-brcm.dep new file mode 100644 index 000000000000..7d18f0809d52 --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_SAISERVER_BRCM)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/docker-saiserver-brcm.mk platform/broadcom/docker-saiserver-brcm.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_SAISERVER_BRCM)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SAISERVER_BRCM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SAISERVER_BRCM)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/docker-saiserver-brcm.mk b/platform/broadcom/docker-saiserver-brcm.mk new file mode 100644 index 000000000000..bb8499eab1fb --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm.mk @@ -0,0 +1,18 @@ +# docker image for brcm saiserver + +DOCKER_SAISERVER_BRCM = docker-saiserver-brcm.gz +$(DOCKER_SAISERVER_BRCM)_PATH = $(PLATFORM_PATH)/docker-saiserver-brcm +$(DOCKER_SAISERVER_BRCM)_DEPENDS += $(SAISERVER) +$(DOCKER_SAISERVER_BRCM)_FILES += $(DSSERVE) $(BCMCMD) +$(DOCKER_SAISERVER_BRCM)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) +SONIC_DOCKER_IMAGES += $(DOCKER_SAISERVER_BRCM) + +$(DOCKER_SAISERVER_BRCM)_CONTAINER_NAME = saiserver +$(DOCKER_SAISERVER_BRCM)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SAISERVER_BRCM)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SAISERVER_BRCM)_RUN_OPT += -v /var/run/docker-saiserver:/var/run/sswsyncd +$(DOCKER_SAISERVER_BRCM)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SAISERVER_BRCM)_RUN_OPT += -v /host/warmboot:/var/warmboot + +$(DOCKER_SAISERVER_BRCM)_BASE_IMAGE_FILES += bcmcmd:/usr/bin/bcmcmd +$(DOCKER_SAISERVER_BRCM)_BASE_IMAGE_FILES += bcmsh:/usr/bin/bcmsh diff --git a/platform/broadcom/docker-saiserver-brcm/Dockerfile.j2 b/platform/broadcom/docker-saiserver-brcm/Dockerfile.j2 new file mode 100644 index 000000000000..a4b4fedd39ad --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/Dockerfile.j2 @@ -0,0 +1,36 @@ +FROM docker-config-engine-buster + +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 + +COPY \ +{% for deb in docker_saiserver_brcm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_saiserver_brcm_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## TODO: add kmod into Depends +RUN apt-get install -yf kmod + +COPY ["files/dsserve", "files/bcmcmd", "start.sh", "bcmsh", "/usr/bin/"] +RUN chmod +x /usr/bin/dsserve /usr/bin/bcmcmd + +COPY ["profile.ini", "portmap.ini", "/etc/sai/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/broadcom/docker-saiserver-brcm/bcmsh b/platform/broadcom/docker-saiserver-brcm/bcmsh new file mode 100755 index 000000000000..7488e63c64fd --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/bcmsh @@ -0,0 +1,40 @@ +#!/bin/bash +usage="$(basename "$0") [-h] [-q] [-t timeout] -- interactive shell for bcm service + +where: + -h show this help text + -t inactivity timeout in seconds (default 300 seconds, 0 for no timeout) + -q quite, no banner (default: verbose)" + +banner="Press Enter to show prompt. +Press Ctrl+C to exit. +NOTICE: Only one bcmsh or bcmcmd can connect to the shell at same time. +" + +# Default verbose +quiet=false +timeout=300 + +while getopts 'hqt:' option; do + case "$option" in + h) echo "$usage" + exit + ;; + q) quiet=true + ;; + t) timeout=$OPTARG + ;; + \?) printf "illegal option: -%s\n" "$OPTARG" >&2 + echo "$usage" >&2 + exit 1 + ;; + esac +done +shift $((OPTIND - 1)) + +if [ "$quiet" = false ]; then + echo "$banner" +fi + +/usr/bin/socat -T$timeout readline UNIX-CONNECT:/var/run/sswsyncd/sswsyncd.socket + diff --git a/platform/broadcom/docker-saiserver-brcm/portmap.ini b/platform/broadcom/docker-saiserver-brcm/portmap.ini new file mode 100644 index 000000000000..7161416e4d4c --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/portmap.ini @@ -0,0 +1,33 @@ +# alias lanes +Ethernet0 29,30,31,32 +Ethernet4 25,26,27,28 +Ethernet8 37,38,39,40 +Ethernet12 33,34,35,36 +Ethernet16 41,42,43,44 +Ethernet20 45,46,47,48 +Ethernet24 5,6,7,8 +Ethernet28 1,2,3,4 +Ethernet32 9,10,11,12 +Ethernet36 13,14,15,16 +Ethernet40 21,22,23,24 +Ethernet44 17,18,19,20 +Ethernet48 49,50,51,52 +Ethernet52 53,54,55,56 +Ethernet56 61,62,63,64 +Ethernet60 57,58,59,60 +Ethernet64 65,66,67,68 +Ethernet68 69,70,71,72 +Ethernet72 77,78,79,80 +Ethernet76 73,74,75,76 +Ethernet80 105,106,107,108 +Ethernet84 109,110,111,112 +Ethernet88 117,118,119,120 +Ethernet92 113,114,115,116 +Ethernet96 121,122,123,124 +Ethernet100 125,126,127,128 +Ethernet104 85,86,87,88 +Ethernet108 81,82,83,84 +Ethernet112 89,90,91,92 +Ethernet116 93,94,95,96 +Ethernet120 97,98,99,100 +Ethernet124 101,102,103,104 diff --git a/platform/broadcom/docker-saiserver-brcm/profile.ini b/platform/broadcom/docker-saiserver-brcm/profile.ini new file mode 100644 index 000000000000..b64d997fb451 --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/profile.ini @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/etc/bcm/td2-s6000-32x40G.config.bcm diff --git a/platform/broadcom/docker-saiserver-brcm/start.sh b/platform/broadcom/docker-saiserver-brcm/start.sh new file mode 100755 index 000000000000..494c0e9126c2 --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/start.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +start_bcm() +{ + [ -e /dev/linux-bcm-knet ] || mknod /dev/linux-bcm-knet c 122 0 + [ -e /dev/linux-user-bde ] || mknod /dev/linux-user-bde c 126 0 + [ -e /dev/linux-kernel-bde ] || mknod /dev/linux-kernel-bde c 127 0 +} + + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +start_bcm + +supervisorctl start saiserver diff --git a/platform/broadcom/docker-saiserver-brcm/supervisord.conf b/platform/broadcom/docker-saiserver-brcm/supervisord.conf new file mode 100644 index 000000000000..cb67a0fc9a47 --- /dev/null +++ b/platform/broadcom/docker-saiserver-brcm/supervisord.conf @@ -0,0 +1,28 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[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=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:saiserver] +command=/usr/bin/saiserver -p /etc/sai/profile.ini -f /etc/sai/portmap.ini +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/broadcom/docker-syncd-brcm-rpc.dep b/platform/broadcom/docker-syncd-brcm-rpc.dep new file mode 100644 index 000000000000..4427b0a957a6 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm-rpc.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_SYNCD_BRCM_RPC)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/docker-syncd-brcm-rpc.mk $(PLATFORM_PATH)/docker-syncd-brcm-rpc.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_SYNCD_BRCM_RPC)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SYNCD_BRCM_RPC)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SYNCD_BRCM_RPC)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/docker-syncd-brcm-rpc.mk b/platform/broadcom/docker-syncd-brcm-rpc.mk new file mode 100644 index 000000000000..27a041d95016 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm-rpc.mk @@ -0,0 +1,28 @@ +# docker image for brcm syncd with rpc + +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) $(PTF) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_BRCM_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_BRCM_RPC)_FILES += $(DSSERVE) $(BCMCMD) $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +$(DOCKER_SYNCD_BRCM_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_BRCM_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_BRCM_RPC) +endif + +$(DOCKER_SYNCD_BRCM_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += --privileged -t +$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot +$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_SYNCD_BRCM_RPC)_BASE_IMAGE_FILES += bcmcmd:/usr/bin/bcmcmd +$(DOCKER_SYNCD_BRCM_RPC)_BASE_IMAGE_FILES += bcmsh:/usr/bin/bcmsh + diff --git a/platform/broadcom/docker-syncd-brcm-rpc/Dockerfile.j2 b/platform/broadcom/docker-syncd-brcm-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..b832fd58864f --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm-rpc/Dockerfile.j2 @@ -0,0 +1,57 @@ +FROM docker-syncd-brcm + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_brcm_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get purge -y syncd + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + python-setuptools \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_brcm_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip2 install cffi==1.7.0 \ + && pip2 install --upgrade cffi==1.7.0 \ + && pip2 install wheel \ + && pip2 install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/broadcom/docker-syncd-brcm-rpc/base_image_files/bcmcmd b/platform/broadcom/docker-syncd-brcm-rpc/base_image_files/bcmcmd new file mode 100755 index 000000000000..7903db6ed6a3 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm-rpc/base_image_files/bcmcmd @@ -0,0 +1,3 @@ +#!/bin/bash + +docker exec -i syncd bcmcmd "$@" diff --git a/platform/broadcom/docker-syncd-brcm-rpc/base_image_files/bcmsh b/platform/broadcom/docker-syncd-brcm-rpc/base_image_files/bcmsh new file mode 100755 index 000000000000..3bb78b0da796 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm-rpc/base_image_files/bcmsh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker exec -it syncd bcmsh "$@" diff --git a/platform/broadcom/docker-syncd-brcm-rpc/ptf_nn_agent.conf b/platform/broadcom/docker-syncd-brcm-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/broadcom/docker-syncd-brcm.dep b/platform/broadcom/docker-syncd-brcm.dep new file mode 100644 index 000000000000..c020a72f2a08 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm.dep @@ -0,0 +1,11 @@ +#DPKG FRK +DPATH := $($(DOCKER_SYNCD_BASE)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/docker-syncd-brcm.mk platform/broadcom/docker-syncd-brcm.dep platform/broadcom/sai.mk +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_SYNCD_BASE)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SYNCD_BASE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SYNCD_BASE)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_SYNCD_BASE),$(DOCKER_SYNCD_BASE_DBG))) diff --git a/platform/broadcom/docker-syncd-brcm.mk b/platform/broadcom/docker-syncd-brcm.mk new file mode 100644 index 000000000000..d23141481915 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm.mk @@ -0,0 +1,19 @@ +# docker image for brcm syncd + +DOCKER_SYNCD_PLATFORM_CODE = brcm +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) +$(DOCKER_SYNCD_BASE)_FILES += $(DSSERVE) $(BCMCMD) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) + +$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot + +$(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 += bcm_common:/usr/bin/bcm_common +$(DOCKER_SYNCD_BASE)_BASE_IMAGE_FILES += monit_syncd:/etc/monit/conf.d diff --git a/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 b/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 new file mode 100755 index 000000000000..0ba71bb5d780 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 @@ -0,0 +1,38 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages %} +FROM docker-config-engine-buster + +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 + +COPY \ +{% for deb in docker_syncd_brcm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_syncd_brcm_debs.split(' ')) }} + +## TODO: add kmod into Depends +RUN apt-get install -yf kmod + +## BRCM uses ethtool to set host interface speed +RUN apt-get install -y ethtool + +COPY ["files/dsserve", "files/bcmcmd", "start.sh", "start_led.sh", "bcmsh", "/usr/bin/"] +RUN chmod +x /usr/bin/dsserve /usr/bin/bcmcmd + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/broadcom/docker-syncd-brcm/base_image_files/bcm_common b/platform/broadcom/docker-syncd-brcm/base_image_files/bcm_common new file mode 100644 index 000000000000..1b560a1a1522 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/base_image_files/bcm_common @@ -0,0 +1,40 @@ +#!/bin/bash + +function help() +{ + echo "Usage: $0 -n [0 to $(($NUM_ASIC-1))]" 1>&2; exit 1; + +} + + +DEV="" + +PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + +# Parse the device specific asic conf file, if it exists + +ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf +if [ -f "$ASIC_CONF" ]; then + source $ASIC_CONF +fi + + +if [[ ($NUM_ASIC -gt 1) ]]; then + OPTIND=1 + + while getopts ":n:h:" opt; do + case "${opt}" in + h) help + exit 0 + ;; + n) DEV=${OPTARG} + [ $DEV -lt $NUM_ASIC -a $DEV -ge 0 ] || help + ;; + esac + done + shift "$((OPTIND-1))" + + if [ -z "${DEV}" ]; then + help + fi +fi diff --git a/platform/broadcom/docker-syncd-brcm/base_image_files/bcmcmd b/platform/broadcom/docker-syncd-brcm/base_image_files/bcmcmd new file mode 100755 index 000000000000..76362fc64804 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/base_image_files/bcmcmd @@ -0,0 +1,8 @@ +#!/bin/bash + +BCM_COMMON=/usr/bin/bcm_common +if [ -f "$BCM_COMMON" ]; then + source $BCM_COMMON +fi +docker exec -i syncd$DEV bcmcmd "$@" + diff --git a/platform/broadcom/docker-syncd-brcm/base_image_files/bcmsh b/platform/broadcom/docker-syncd-brcm/base_image_files/bcmsh new file mode 100755 index 000000000000..3cb2aad7afb6 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/base_image_files/bcmsh @@ -0,0 +1,8 @@ +#!/bin/bash + +BCM_COMMON=/usr/bin/bcm_common +if [ -f "$BCM_COMMON" ]; then + source $BCM_COMMON +fi + +docker exec -it syncd$DEV bcmsh "$@" 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..d63346d9ee20 --- /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 program syncd|syncd with path "/usr/bin/process_checker syncd /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program syncd|dsserve with path "/usr/bin/process_checker syncd /usr/bin/dsserve /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/platform/broadcom/docker-syncd-brcm/bcmsh b/platform/broadcom/docker-syncd-brcm/bcmsh new file mode 100755 index 000000000000..7488e63c64fd --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/bcmsh @@ -0,0 +1,40 @@ +#!/bin/bash +usage="$(basename "$0") [-h] [-q] [-t timeout] -- interactive shell for bcm service + +where: + -h show this help text + -t inactivity timeout in seconds (default 300 seconds, 0 for no timeout) + -q quite, no banner (default: verbose)" + +banner="Press Enter to show prompt. +Press Ctrl+C to exit. +NOTICE: Only one bcmsh or bcmcmd can connect to the shell at same time. +" + +# Default verbose +quiet=false +timeout=300 + +while getopts 'hqt:' option; do + case "$option" in + h) echo "$usage" + exit + ;; + q) quiet=true + ;; + t) timeout=$OPTARG + ;; + \?) printf "illegal option: -%s\n" "$OPTARG" >&2 + echo "$usage" >&2 + exit 1 + ;; + esac +done +shift $((OPTIND - 1)) + +if [ "$quiet" = false ]; then + echo "$banner" +fi + +/usr/bin/socat -T$timeout readline UNIX-CONNECT:/var/run/sswsyncd/sswsyncd.socket + diff --git a/platform/broadcom/docker-syncd-brcm/critical_processes b/platform/broadcom/docker-syncd-brcm/critical_processes new file mode 100644 index 000000000000..d1163a9c3046 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/critical_processes @@ -0,0 +1,2 @@ +program:dsserve +program:syncd diff --git a/platform/broadcom/docker-syncd-brcm/start.sh b/platform/broadcom/docker-syncd-brcm/start.sh new file mode 100755 index 000000000000..9927b877a619 --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/start.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +HWSKU_DIR=/usr/share/sonic/hwsku + +SYNCD_SOCKET_FILE=/var/run/sswsyncd/sswsyncd.socket + +# Remove stale files if they exist +rm -f ${SYNCD_SOCKET_FILE} + +mkdir -p /etc/sai.d/ + +# Create/Copy the sai.profile to /etc/sai.d/sai.profile +if [ -f $HWSKU_DIR/sai.profile.j2 ]; then + sonic-cfggen -d -t $HWSKU_DIR/sai.profile.j2 > /etc/sai.d/sai.profile +else + if [ -f $HWSKU_DIR/sai.profile ]; then + cp $HWSKU_DIR/sai.profile /etc/sai.d/sai.profile + fi +fi diff --git a/platform/broadcom/docker-syncd-brcm/start_led.sh b/platform/broadcom/docker-syncd-brcm/start_led.sh new file mode 100755 index 000000000000..964aa23eb04f --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/start_led.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +PLATFORM_DIR=/usr/share/sonic/platform +SYNCD_SOCKET_FILE=/var/run/sswsyncd/sswsyncd.socket +LED_PROC_INIT_SOC=${PLATFORM_DIR}/led_proc_init.soc + +if [ ! -f "$LED_PROC_INIT_SOC" ]; then + echo "No soc led configuration found under $LED_SOC_INIT_SOC" + exit 0 +fi + +# Function: wait until syncd has created the socket for bcmcmd to connect to +wait_syncd() { + while true; do + if [ -e ${SYNCD_SOCKET_FILE} ]; then + break + fi + sleep 1 + done + + # wait until bcm sdk is ready to get a request + counter=0 + while true; do + /usr/bin/bcmcmd -t 1 "show unit" | grep BCM >/dev/null 2>&1 + rv=$? + if [ $rv -eq 0 ]; then + break + fi + counter=$((counter+1)) + if [ $counter -ge 60 ]; then + echo "syncd is not ready to take commands after $counter re-tries; Exiting!" + break + fi + sleep 1 + done +} + +# If this platform has an initialization file for the Broadcom LED microprocessor, load it +if [[ -r "$LED_PROC_INIT_SOC" && ! -f /var/warmboot/warm-starting ]]; then + wait_syncd +fi + +/usr/bin/bcmcmd -t 60 "rcload $LED_PROC_INIT_SOC" diff --git a/platform/broadcom/docker-syncd-brcm/supervisord.conf b/platform/broadcom/docker-syncd-brcm/supervisord.conf new file mode 100644 index 000000000000..5e801106972f --- /dev/null +++ b/platform/broadcom/docker-syncd-brcm/supervisord.conf @@ -0,0 +1,60 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + +[program:ledinit] +command=/usr/bin/start_led.sh +priority=4 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=syncd:running diff --git a/platform/broadcom/libsaithrift-dev.dep b/platform/broadcom/libsaithrift-dev.dep new file mode 100644 index 000000000000..2ae0106247e4 --- /dev/null +++ b/platform/broadcom/libsaithrift-dev.dep @@ -0,0 +1,13 @@ +#DPKG FRK +SPATH := $($(LIBSAITHRIFT_DEV)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/libsaithrift-dev.mk platform/broadcom/libsaithrift-dev.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_PATHS := $(SPATH) $(SPATH)/bm/behavioral-model $(SPATH)/test/ptf $(SPATH)/test/saithrift/ctypesgen +$(foreach path, $(SMDEP_PATHS), $(eval $(path) :=$(filter-out $(SMDEP_PATHS),$(addprefix $(path)/, $(shell cd $(path) && git ls-files | grep -Ev " " ))))) + +$(LIBSAITHRIFT_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBSAITHRIFT_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBSAITHRIFT_DEV)_DEP_FILES := $(DEP_FILES) +$(LIBSAITHRIFT_DEV)_SMDEP_FILES := $(foreach path, $(SMDEP_PATHS), $($(path))) +$(LIBSAITHRIFT_DEV)_SMDEP_PATHS := $(SMDEP_PATHS) + diff --git a/platform/broadcom/libsaithrift-dev.mk b/platform/broadcom/libsaithrift-dev.mk new file mode 100644 index 000000000000..543ea63e7f4e --- /dev/null +++ b/platform/broadcom/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_amd64.deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(BRCM_SAI) $(BRCM_SAI_DEV) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(BRCM_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_amd64.deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_amd64.deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(BRCM_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_amd64.deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/broadcom/one-aboot.dep b/platform/broadcom/one-aboot.dep new file mode 100644 index 000000000000..a3b49cea460d --- /dev/null +++ b/platform/broadcom/one-aboot.dep @@ -0,0 +1,2 @@ +#DPKG FRK +$(SONIC_ONE_ABOOT_IMAGE)_CACHE_MODE := none diff --git a/platform/broadcom/one-aboot.mk b/platform/broadcom/one-aboot.mk new file mode 100644 index 000000000000..959cda20907e --- /dev/null +++ b/platform/broadcom/one-aboot.mk @@ -0,0 +1,15 @@ +# sonic broadcom one image installer + +SONIC_ONE_ABOOT_IMAGE = sonic-aboot-broadcom.swi +$(SONIC_ONE_ABOOT_IMAGE)_MACHINE = broadcom +$(SONIC_ONE_ABOOT_IMAGE)_IMAGE_TYPE = aboot +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(BRCM_OPENNSL_KERNEL) $(ARISTA_PLATFORM_MODULE_DRIVERS) $(ARISTA_PLATFORM_MODULE_PYTHON2) $(ARISTA_PLATFORM_MODULE_PYTHON3) $(ARISTA_PLATFORM_MODULE) +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(PHY_CREDO) +$(SONIC_ONE_ABOOT_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_ABOOT_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_ABOOT_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_ABOOT_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_ABOOT_IMAGE) diff --git a/platform/broadcom/one-image.dep b/platform/broadcom/one-image.dep new file mode 100644 index 000000000000..c5399d808172 --- /dev/null +++ b/platform/broadcom/one-image.dep @@ -0,0 +1,2 @@ +#DPKG FRK +$(SONIC_ONE_IMAGE)_CACHE_MODE := none diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk new file mode 100644 index 000000000000..b9813256ffee --- /dev/null +++ b/platform/broadcom/one-image.mk @@ -0,0 +1,74 @@ +# sonic broadcom one image installer + +SONIC_ONE_IMAGE = sonic-broadcom.bin +$(SONIC_ONE_IMAGE)_MACHINE = broadcom +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(BRCM_OPENNSL_KERNEL) +$(SONIC_ONE_IMAGE)_INSTALLS += $(PDDF_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ + $(DELL_Z9264F_PLATFORM_MODULE) \ + $(DELL_S5232F_PLATFORM_MODULE) \ + $(DELL_S5248F_PLATFORM_MODULE) \ + $(DELL_Z9332F_PLATFORM_MODULE) \ + $(DELL_S5296F_PLATFORM_MODULE) \ + $(DELL_Z9100_PLATFORM_MODULE) \ + $(DELL_S6100_PLATFORM_MODULE) \ + $(INGRASYS_S8900_54XC_PLATFORM_MODULE) \ + $(INGRASYS_S8900_64XC_PLATFORM_MODULE) \ + $(INGRASYS_S9100_PLATFORM_MODULE) \ + $(INGRASYS_S8810_32Q_PLATFORM_MODULE) \ + $(INGRASYS_S9200_64X_PLATFORM_MODULE) \ + $(ACCTON_AS7712_32X_PLATFORM_MODULE) \ + $(ACCTON_AS5712_54X_PLATFORM_MODULE) \ + $(ACCTON_AS7816_64X_PLATFORM_MODULE) \ + $(ACCTON_AS7716_32X_PLATFORM_MODULE) \ + $(ACCTON_AS7312_54X_PLATFORM_MODULE) \ + $(ACCTON_AS7326_56X_PLATFORM_MODULE) \ + $(ACCTON_AS7716_32XB_PLATFORM_MODULE) \ + $(ACCTON_AS6712_32X_PLATFORM_MODULE) \ + $(ACCTON_AS7726_32X_PLATFORM_MODULE) \ + $(ACCTON_AS4630_54PE_PLATFORM_MODULE) \ + $(ACCTON_MINIPACK_PLATFORM_MODULE) \ + $(ACCTON_AS5812_54X_PLATFORM_MODULE) \ + $(ACCTON_AS5812_54T_PLATFORM_MODULE) \ + $(ACCTON_AS5835_54X_PLATFORM_MODULE) \ + $(ACCTON_AS9716_32D_PLATFORM_MODULE) \ + $(ACCTON_AS5835_54T_PLATFORM_MODULE) \ + $(ACCTON_AS7312_54XS_PLATFORM_MODULE) \ + $(ACCTON_AS7315_27XB_PLATFORM_MODULE) \ + $(INVENTEC_D7032Q28B_PLATFORM_MODULE) \ + $(INVENTEC_D7054Q28B_PLATFORM_MODULE) \ + $(INVENTEC_D7264Q28B_PLATFORM_MODULE) \ + $(INVENTEC_D6356_PLATFORM_MODULE) \ + $(INVENTEC_D6332_PLATFORM_MODULE) \ + $(CEL_DX010_PLATFORM_MODULE) \ + $(CEL_HALIBURTON_PLATFORM_MODULE) \ + $(CEL_SEASTONE2_PLATFORM_MODULE) \ + $(DELTA_AG9032V1_PLATFORM_MODULE) \ + $(DELTA_AG9064_PLATFORM_MODULE) \ + $(DELTA_AG5648_PLATFORM_MODULE) \ + $(DELTA_ET6248BRB_PLATFORM_MODULE) \ + $(QUANTA_IX1B_32X_PLATFORM_MODULE) \ + $(QUANTA_IX7_32X_PLATFORM_MODULE) \ + $(QUANTA_IX8_56X_PLATFORM_MODULE) \ + $(QUANTA_IX8C_56X_PLATFORM_MODULE) \ + $(QUANTA_IX9_32X_PLATFORM_MODULE) \ + $(MITAC_LY1200_32X_PLATFORM_MODULE) \ + $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) \ + $(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE) \ + $(BRCM_XLR_GTS_PLATFORM_MODULE) \ + $(DELTA_AG9032V2A_PLATFORM_MODULE) \ + $(JUNIPER_QFX5210_PLATFORM_MODULE) \ + $(CEL_SILVERSTONE_PLATFORM_MODULE) \ + $(JUNIPER_QFX5200_PLATFORM_MODULE) \ + $(DELTA_AGC032_PLATFORM_MODULE) \ + $(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif + +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/broadcom/one-pde-image.dep b/platform/broadcom/one-pde-image.dep new file mode 100644 index 000000000000..2abc8cad736f --- /dev/null +++ b/platform/broadcom/one-pde-image.dep @@ -0,0 +1,2 @@ +#DPKG FRK +$(SONIC_ONE_PDE_IMAGE)_CACHE_MODE := none diff --git a/platform/broadcom/platform-modules-accton.dep b/platform/broadcom/platform-modules-accton.dep new file mode 100644 index 000000000000..1ca57ec29e80 --- /dev/null +++ b/platform/broadcom/platform-modules-accton.dep @@ -0,0 +1,10 @@ + +MPATH := $($(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-accton.mk platform/broadcom/platform-modules-accton.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(ACCTON_AS7712_32X_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(ACCTON_AS7712_32X_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(ACCTON_AS7712_32X_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk new file mode 100755 index 000000000000..395040d7561d --- /dev/null +++ b/platform/broadcom/platform-modules-accton.mk @@ -0,0 +1,113 @@ +# Accton Platform modules + +ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7816_64X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7716_32X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7312_54X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7326_56X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7716_32XB_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS6712_32X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_MINIPACK_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS5812_54T_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7312_54XS_PLATFORM_MODULE_VERSION = 1.1 +ACCTON_AS7315_27XB_PLATFORM_MODULE_VERSION = 1.1 + +export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION +export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION +export ACCTON_AS7816_64X_PLATFORM_MODULE_VERSION +export ACCTON_AS7716_32X_PLATFORM_MODULE_VERSION +export ACCTON_AS7312_54X_PLATFORM_MODULE_VERSION +export ACCTON_AS7326_56X_PLATFORM_MODULE_VERSION +export ACCTON_AS7716_32XB_PLATFORM_MODULE_VERSION +export ACCTON_AS6712_32X_PLATFORM_MODULE_VERSION +export ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION +export ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION +export ACCTON_MINIPACK_PLATFORM_MODULE_VERSION +export ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION +export ACCTON_AS5812_54T_PLATFORM_MODULE_VERSION +export ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION +export ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION +export ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION +export ACCTON_AS7312_54XS_PLATFORM_MODULE_VERSION +export ACCTON_AS7315_27XB_PLATFORM_MODULE_VERSION + +ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton +$(ACCTON_AS7712_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(ACCTON_AS7712_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7712_32x-r0 +SONIC_DPKG_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE) + +ACCTON_AS5712_54X_PLATFORM_MODULE = sonic-platform-accton-as5712-54x_$(ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS5712_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5712_54x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5712_54X_PLATFORM_MODULE))) + +ACCTON_AS7816_64X_PLATFORM_MODULE = sonic-platform-accton-as7816-64x_$(ACCTON_AS7816_64X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7816_64X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7816_64x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7816_64X_PLATFORM_MODULE))) + +ACCTON_AS7716_32X_PLATFORM_MODULE = sonic-platform-accton-as7716-32x_$(ACCTON_AS7716_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7716_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7716_32x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7716_32X_PLATFORM_MODULE))) + +ACCTON_AS7312_54X_PLATFORM_MODULE = sonic-platform-accton-as7312-54x_$(ACCTON_AS7312_54X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7312_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7312_54x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7312_54X_PLATFORM_MODULE))) + +ACCTON_AS7312_54XS_PLATFORM_MODULE = sonic-platform-accton-as7312-54xs_$(ACCTON_AS7312_54XS_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7312_54XS_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7312_54xs-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7312_54XS_PLATFORM_MODULE))) + +ACCTON_AS7326_56X_PLATFORM_MODULE = sonic-platform-accton-as7326-56x_$(ACCTON_AS7326_56X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7326_56X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7326_56x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7326_56X_PLATFORM_MODULE))) + +ACCTON_AS7716_32XB_PLATFORM_MODULE = sonic-platform-accton-as7716-32xb_$(ACCTON_AS7716_32XB_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7716_32XB_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7716_32xb-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7716_32XB_PLATFORM_MODULE))) + +ACCTON_AS6712_32X_PLATFORM_MODULE = sonic-platform-accton-as6712-32x_$(ACCTON_AS6712_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS6712_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as6712_32x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS6712_32X_PLATFORM_MODULE))) + +ACCTON_AS7726_32X_PLATFORM_MODULE = sonic-platform-accton-as7726-32x_$(ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7726_32X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7726_32x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7726_32X_PLATFORM_MODULE))) + +ACCTON_AS4630_54PE_PLATFORM_MODULE = sonic-platform-accton-as4630-54pe_$(ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS4630_54PE_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as4630_54pe-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS4630_54PE_PLATFORM_MODULE))) + +ACCTON_MINIPACK_PLATFORM_MODULE = sonic-platform-accton-minipack_$(ACCTON_MINIPACK_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_MINIPACK_PLATFORM_MODULE)_PLATFORM = x86_64-accton_minipack-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_MINIPACK_PLATFORM_MODULE))) + +ACCTON_AS5812_54X_PLATFORM_MODULE = sonic-platform-accton-as5812-54x_$(ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS5812_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5812_54x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5812_54X_PLATFORM_MODULE))) + +ACCTON_AS5812_54T_PLATFORM_MODULE = sonic-platform-accton-as5812-54t_$(ACCTON_AS5812_54T_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS5812_54T_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5812_54t-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5812_54T_PLATFORM_MODULE))) + +ACCTON_AS5835_54X_PLATFORM_MODULE = sonic-platform-accton-as5835-54x_$(ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS5835_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54x-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54X_PLATFORM_MODULE))) + +ACCTON_AS9716_32D_PLATFORM_MODULE = sonic-platform-accton-as9716-32d_$(ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS9716_32D_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9716_32d-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS9716_32D_PLATFORM_MODULE))) + +ACCTON_AS5835_54T_PLATFORM_MODULE = sonic-platform-accton-as5835-54t_$(ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS5835_54T_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54t-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54T_PLATFORM_MODULE))) + +ACCTON_AS7315_27XB_PLATFORM_MODULE = sonic-platform-accton-as7315-27xb_$(ACCTON_AS7315_27XB_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7315_27XB_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7315_27xb-r0 +$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS7315_27XB_PLATFORM_MODULE))) diff --git a/platform/broadcom/platform-modules-alphanetworks.dep b/platform/broadcom/platform-modules-alphanetworks.dep new file mode 100644 index 000000000000..6538525303fd --- /dev/null +++ b/platform/broadcom/platform-modules-alphanetworks.dep @@ -0,0 +1,10 @@ + +MPATH := $($(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-alphanetworks.mk platform/broadcom/platform-modules-alphanetworks.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-alphanetworks.mk b/platform/broadcom/platform-modules-alphanetworks.mk new file mode 100644 index 000000000000..13e5fc4ff9e2 --- /dev/null +++ b/platform/broadcom/platform-modules-alphanetworks.mk @@ -0,0 +1,20 @@ +# Alphanetworks Platform modules + +ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION = 1.0 +ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE_VERSION = 1.0 + +export ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION +export ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE_VERSION + +ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE = sonic-platform-alphanetworks-snh60a0-320fv2_$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE_VERSION)_amd64.deb +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-alphanetworks +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE)_PLATFORM = x86_64-alphanetworks_snh60a0_320fv2-r0 +SONIC_DPKG_DEBS += $(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) + +ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE = sonic-platform-alphanetworks-snh60b0-640f_$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE_VERSION)_amd64.deb +$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE)_PLATFORM = x86_64-alphanetworks_snh60b0_640f-r0 +$(eval $(call add_extra_package,$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE),$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE))) + + + diff --git a/platform/broadcom/platform-modules-arista.dep b/platform/broadcom/platform-modules-arista.dep new file mode 100644 index 000000000000..c42d529b7280 --- /dev/null +++ b/platform/broadcom/platform-modules-arista.dep @@ -0,0 +1,13 @@ + +MPATH := $($(ARISTA_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-arista.mk platform/broadcom/platform-modules-arista.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(MPATH)/,$(shell cd $(MPATH) && git ls-files)) + + +$(ARISTA_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(ARISTA_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(ARISTA_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) +$(ARISTA_PLATFORM_MODULE)_SMDEP_FILES := $(SMDEP_FILES) +$(ARISTA_PLATFORM_MODULE)_SMDEP_PATHS := $(MPATH) + diff --git a/platform/broadcom/platform-modules-arista.mk b/platform/broadcom/platform-modules-arista.mk new file mode 100644 index 000000000000..ac2c65fdf3c5 --- /dev/null +++ b/platform/broadcom/platform-modules-arista.mk @@ -0,0 +1,24 @@ +# Arista Platform modules + +ARISTA_PLATFORM_MODULE_VERSION = 1.0 + +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_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))) + +ARISTA_PLATFORM_MODULE_PYTHON3 = python3-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_all.deb +$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_PYTHON3))) + +ARISTA_PLATFORM_MODULE_DRIVERS = drivers-sonic-platform-arista_$(ARISTA_PLATFORM_MODULE_VERSION)_amd64.deb +$(eval $(call add_extra_package,$(ARISTA_PLATFORM_MODULE),$(ARISTA_PLATFORM_MODULE_DRIVERS))) + +export ARISTA_PLATFORM_MODULE ARISTA_PLATFORM_MODULE_PYTHON2 ARISTA_PLATFORM_MODULE_PYTHON3 ARISTA_PLATFORM_MODULE_DRIVERS + +export ARISTA_SCD_DRIVER_CONFIG=m + diff --git a/platform/broadcom/platform-modules-brcm-xlr-gts.dep b/platform/broadcom/platform-modules-brcm-xlr-gts.dep new file mode 100644 index 000000000000..09e81d735481 --- /dev/null +++ b/platform/broadcom/platform-modules-brcm-xlr-gts.dep @@ -0,0 +1,10 @@ + +MPATH := $($(BRCM_XLR_GTS_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-brcm-xlr-gts.mk platform/broadcom/platform-modules-brcm-xlr-gts.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(BRCM_XLR_GTS_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(BRCM_XLR_GTS_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(BRCM_XLR_GTS_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-brcm-xlr-gts.mk b/platform/broadcom/platform-modules-brcm-xlr-gts.mk new file mode 100644 index 000000000000..28abe890acbd --- /dev/null +++ b/platform/broadcom/platform-modules-brcm-xlr-gts.mk @@ -0,0 +1,14 @@ +# Broadcom XLR/GTS Platform modules + +BRCM_XLR_GTS_PLATFORM_MODULE_VERSION = 1.0 + +export BRCM_XLR_GTS_PLATFORM_MODULE_VERSION + +BRCM_XLR_GTS_PLATFORM_MODULE = sonic-platform-brcm-xlr-gts_$(BRCM_XLR_GTS_PLATFORM_MODULE_VERSION)_amd64.deb +$(BRCM_XLR_GTS_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-brcm-xlr-gts +$(BRCM_XLR_GTS_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(BRCM_XLR_GTS_PLATFORM_MODULE)_PLATFORM = x86_64-bcm_xlr-r0 +SONIC_MAKE_DEBS += $(BRCM_XLR_GTS_PLATFORM_MODULE) + +export BRCM_XLR_GTS_PLATFORM_MODULE + diff --git a/platform/broadcom/platform-modules-cel.dep b/platform/broadcom/platform-modules-cel.dep new file mode 100644 index 000000000000..f49d8ef8abbb --- /dev/null +++ b/platform/broadcom/platform-modules-cel.dep @@ -0,0 +1,10 @@ + +MPATH := $($(CEL_DX010_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-cel.mk platform/broadcom/platform-modules-cel.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(CEL_DX010_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(CEL_DX010_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(CEL_DX010_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-cel.mk b/platform/broadcom/platform-modules-cel.mk new file mode 100644 index 000000000000..de021df7e4db --- /dev/null +++ b/platform/broadcom/platform-modules-cel.mk @@ -0,0 +1,30 @@ +# Celestica DX010 and Haliburton Platform modules + +CEL_DX010_PLATFORM_MODULE_VERSION = 0.9 +CEL_HALIBURTON_PLATFORM_MODULE_VERSION = 0.9 +CEL_SEASTONE2_PLATFORM_MODULE_VERSION = 0.9 +CEL_SILVERSTONE_PLATFORM_MODULE_VERSION = 0.9 + +export CEL_DX010_PLATFORM_MODULE_VERSION +export CEL_HALIBURTON_PLATFORM_MODULE_VERSION +export CEL_SEASTONE2_PLATFORM_MODULE_VERSION +export CEL_SILVERSTONE_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 +$(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_SEASTONE2_PLATFORM_MODULE = platform-modules-seastone2_$(CEL_SEASTONE2_PLATFORM_MODULE_VERSION)_amd64.deb +$(CEL_SEASTONE2_PLATFORM_MODULE)_PLATFORM = x86_64-cel_seastone_2-r0 +$(eval $(call add_extra_package,$(CEL_DX010_PLATFORM_MODULE),$(CEL_SEASTONE2_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))) + diff --git a/platform/broadcom/platform-modules-dell.dep b/platform/broadcom/platform-modules-dell.dep new file mode 100644 index 000000000000..32f5d39d0312 --- /dev/null +++ b/platform/broadcom/platform-modules-dell.dep @@ -0,0 +1,10 @@ + +MPATH := $($(DELL_Z9100_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-dell.mk platform/broadcom/platform-modules-dell.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(DELL_Z9100_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(DELL_Z9100_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DELL_Z9100_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-dell.mk b/platform/broadcom/platform-modules-dell.mk new file mode 100644 index 000000000000..e4d4f56c53aa --- /dev/null +++ b/platform/broadcom/platform-modules-dell.mk @@ -0,0 +1,57 @@ +# Dell S6000,Z9100, S6100, Z9264F , S5232F,Z9332F Platform modules + +DELL_S6000_PLATFORM_MODULE_VERSION = 1.1 +DELL_Z9100_PLATFORM_MODULE_VERSION = 1.1 +DELL_S6100_PLATFORM_MODULE_VERSION = 1.1 +DELL_Z9264F_PLATFORM_MODULE_VERSION = 1.1 +DELL_S5232F_PLATFORM_MODULE_VERSION = 1.1 +DELL_Z9332F_PLATFORM_MODULE_VERSION = 1.1 +DELL_S5248F_PLATFORM_MODULE_VERSION = 1.1 +DELL_S5296F_PLATFORM_MODULE_VERSION = 1.1 + +export DELL_S6000_PLATFORM_MODULE_VERSION +export DELL_Z9100_PLATFORM_MODULE_VERSION +export DELL_S6100_PLATFORM_MODULE_VERSION +export DELL_Z9264F_PLATFORM_MODULE_VERSION +export DELL_S5232F_PLATFORM_MODULE_VERSION +export DELL_Z9332F_PLATFORM_MODULE_VERSION +export DELL_S5248F_PLATFORM_MODULE_VERSION +export DELL_S5296F_PLATFORM_MODULE_VERSION + +DELL_Z9100_PLATFORM_MODULE = platform-modules-z9100_$(DELL_Z9100_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_Z9100_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-dell +$(DELL_Z9100_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(DELL_Z9100_PLATFORM_MODULE)_PLATFORM = x86_64-dell_z9100_c2538-r0 +SONIC_DPKG_DEBS += $(DELL_Z9100_PLATFORM_MODULE) + +DELL_S6100_PLATFORM_MODULE = platform-modules-s6100_$(DELL_S6100_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_S6100_PLATFORM_MODULE)_PLATFORM = x86_64-dell_s6100_c2538-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S6100_PLATFORM_MODULE))) + +DELL_Z9264F_PLATFORM_MODULE = platform-modules-z9264f_$(DELL_Z9264F_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_Z9264F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_z9264f_c3538-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_Z9264F_PLATFORM_MODULE))) + +# Dell S6000 Platform modules +DELL_S6000_PLATFORM_MODULE = platform-modules-s6000_$(DELL_S6000_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_S6000_PLATFORM_MODULE)_PLATFORM = x86_64-dell_s6000_s1220-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S6000_PLATFORM_MODULE))) + +DELL_S5232F_PLATFORM_MODULE = platform-modules-s5232f_$(DELL_S5232F_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_S5232F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5232f_c3538-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5232F_PLATFORM_MODULE))) + +DELL_Z9332F_PLATFORM_MODULE = platform-modules-z9332f_$(DELL_Z9332F_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_Z9332F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_z9332f_d1508-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_Z9332F_PLATFORM_MODULE))) + +DELL_S5248F_PLATFORM_MODULE = platform-modules-s5248f_$(DELL_S5248F_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_S5248F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5248f_c3538-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5248F_PLATFORM_MODULE))) + +DELL_S5296F_PLATFORM_MODULE = platform-modules-s5296f_$(DELL_S5296F_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_S5296F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5296f_c3538-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5296F_PLATFORM_MODULE))) + +#flashrom tool +$(shell ./$(PLATFORM_PATH)/sonic-platform-modules-dell/tools/flashrom.sh > /dev/null 2>&1) diff --git a/platform/broadcom/platform-modules-delta.dep b/platform/broadcom/platform-modules-delta.dep new file mode 100644 index 000000000000..d6d25aed0751 --- /dev/null +++ b/platform/broadcom/platform-modules-delta.dep @@ -0,0 +1,10 @@ + +MPATH := $($(DELTA_AG9032V1_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-delta.mk platform/broadcom/platform-modules-delta.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(DELTA_AG9032V1_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(DELTA_AG9032V1_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DELTA_AG9032V1_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-delta.mk b/platform/broadcom/platform-modules-delta.mk new file mode 100644 index 000000000000..a524f2592fa8 --- /dev/null +++ b/platform/broadcom/platform-modules-delta.mk @@ -0,0 +1,43 @@ +# Delta AG9032v1 Platform modules + +DELTA_AG9032V1_PLATFORM_MODULE_VERSION = 1.1 +DELTA_AG9064_PLATFORM_MODULE_VERSION = 1.1 +DELTA_AG5648_PLATFORM_MODULE_VERSION = 1.1 +DELTA_ET6248BRB_PLATFORM_MODULE_VERSION = 1.1 +DELTA_AG9032V2A_PLATFORM_MODULE_VERSION = 1.1 +DELTA_AGC032_PLATFORM_MODULE_VERSION = 1.1 + +export DELTA_AG9032V1_PLATFORM_MODULE_VERSION +export DELTA_AG9064_PLATFORM_MODULE_VERSION +export DELTA_AG5648_PLATFORM_MODULE_VERSION +export DELTA_ET6248BRB_PLATFORM_MODULE_VERSION +export DELTA_AG9032V2A_PLATFORM_MODULE_VERSION +export DELTA_AGC032_PLATFORM_MODULE_VERSION + +DELTA_AG9032V1_PLATFORM_MODULE = platform-modules-ag9032v1_$(DELTA_AG9032V1_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELTA_AG9032V1_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-delta +$(DELTA_AG9032V1_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(DELTA_AG9032V1_PLATFORM_MODULE)_PLATFORM = x86_64-delta_ag9032v1-r0 +SONIC_DPKG_DEBS += $(DELTA_AG9032V1_PLATFORM_MODULE) + +DELTA_AG9064_PLATFORM_MODULE = platform-modules-ag9064_$(DELTA_AG9064_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELTA_AG9064_PLATFORM_MODULE)_PLATFORM = x86_64-delta_ag9064-r0 +$(eval $(call add_extra_package,$(DELTA_AG9032V1_PLATFORM_MODULE),$(DELTA_AG9064_PLATFORM_MODULE))) + +DELTA_AG5648_PLATFORM_MODULE = platform-modules-ag5648_$(DELTA_AG5648_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELTA_AG5648_PLATFORM_MODULE)_PLATFORM = x86_64-delta_ag5648-r0 +$(eval $(call add_extra_package,$(DELTA_AG9032V1_PLATFORM_MODULE),$(DELTA_AG5648_PLATFORM_MODULE))) + +DELTA_ET6248BRB_PLATFORM_MODULE = platform-modules-et-6248brb_$(DELTA_ET6248BRB_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELTA_ET6248BRB_PLATFORM_MODULE)_PLATFORM = x86_64-delta_et-6248brb-r0 +$(eval $(call add_extra_package,$(DELTA_AG9032V1_PLATFORM_MODULE),$(DELTA_ET6248BRB_PLATFORM_MODULE))) + +DELTA_AG9032V2A_PLATFORM_MODULE = platform-modules-ag9032v2a_$(DELTA_AG9032V2A_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELTA_AG9032V2A_PLATFORM_MODULE)_PLATFORM = x86_64-delta_ag9032v2a-r0 +$(eval $(call add_extra_package,$(DELTA_AG9032V1_PLATFORM_MODULE),$(DELTA_AG9032V2A_PLATFORM_MODULE))) + +DELTA_AGC032_PLATFORM_MODULE = platform-modules-agc032_$(DELTA_AGC032_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELTA_AGC032_PLATFORM_MODULE)_PLATFORM = x86_64-delta_agc032-r0 +$(eval $(call add_extra_package,$(DELTA_AG9032V1_PLATFORM_MODULE),$(DELTA_AGC032_PLATFORM_MODULE))) + +SONIC_STRETCH_DEBS += $(DELTA_AG9032V1_PLATFORM_MODULE) diff --git a/platform/broadcom/platform-modules-ingrasys.dep b/platform/broadcom/platform-modules-ingrasys.dep new file mode 100644 index 000000000000..5582caf09c86 --- /dev/null +++ b/platform/broadcom/platform-modules-ingrasys.dep @@ -0,0 +1,10 @@ + +MPATH := $($(INGRASYS_S9100_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-ingrasys.mk platform/broadcom/platform-modules-ingrasys.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(INGRASYS_S9100_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(INGRASYS_S9100_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(INGRASYS_S9100_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-ingrasys.mk b/platform/broadcom/platform-modules-ingrasys.mk new file mode 100644 index 000000000000..9ce7cdb26487 --- /dev/null +++ b/platform/broadcom/platform-modules-ingrasys.mk @@ -0,0 +1,37 @@ +# Ingrasys S9100, S8900-64XC, S8900-54XC and S8810-32Q Platform modules + +INGRASYS_S9100_PLATFORM_MODULE_VERSION = 1.1.0 +INGRASYS_S8900_64XC_PLATFORM_MODULE_VERSION = 1.1.0 +INGRASYS_S8900_54XC_PLATFORM_MODULE_VERSION = 1.1.0 +INGRASYS_S8810_32Q_PLATFORM_MODULE_VERSION = 1.1.0 +INGRASYS_S9200_64X_PLATFORM_MODULE_VERSION = 1.1.0 + +export INGRASYS_S9100_PLATFORM_MODULE_VERSION +export INGRASYS_S8900_64XC_PLATFORM_MODULE_VERSION +export INGRASYS_S8900_54XC_PLATFORM_MODULE_VERSION +export INGRASYS_S8810_32Q_PLATFORM_MODULE_VERSION +export INGRASYS_S9200_64X_PLATFORM_MODULE_VERSION + +INGRASYS_S9100_PLATFORM_MODULE = sonic-platform-ingrasys-s9100_$(INGRASYS_S9100_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9100_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ingrasys +$(INGRASYS_S9100_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(INGRASYS_S9100_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9100-r0 +SONIC_DPKG_DEBS += $(INGRASYS_S9100_PLATFORM_MODULE) + +INGRASYS_S8900_64XC_PLATFORM_MODULE = sonic-platform-ingrasys-s8900-64xc_$(INGRASYS_S8900_64XC_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S8900_64XC_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s8900_64xc-r0 + +INGRASYS_S8900_54XC_PLATFORM_MODULE = sonic-platform-ingrasys-s8900-54xc_$(INGRASYS_S8900_54XC_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S8900_54XC_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s8900_54xc-r0 + +INGRASYS_S8810_32Q_PLATFORM_MODULE = sonic-platform-ingrasys-s8810-32q_$(INGRASYS_S8810_32Q_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S8810_32Q_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s8810_32q-r0 + +INGRASYS_S9200_64X_PLATFORM_MODULE = sonic-platform-ingrasys-s9200-64x_$(INGRASYS_S9200_64X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9200_64X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9200_64x-r0 + +$(eval $(call add_extra_package,$(INGRASYS_S9100_PLATFORM_MODULE),$(INGRASYS_S8900_64XC_PLATFORM_MODULE))) +$(eval $(call add_extra_package,$(INGRASYS_S9100_PLATFORM_MODULE),$(INGRASYS_S8900_54XC_PLATFORM_MODULE))) +$(eval $(call add_extra_package,$(INGRASYS_S9100_PLATFORM_MODULE),$(INGRASYS_S8810_32Q_PLATFORM_MODULE))) +$(eval $(call add_extra_package,$(INGRASYS_S9100_PLATFORM_MODULE),$(INGRASYS_S9200_64X_PLATFORM_MODULE))) + diff --git a/platform/broadcom/platform-modules-inventec.dep b/platform/broadcom/platform-modules-inventec.dep new file mode 100644 index 000000000000..1f4003caa1b8 --- /dev/null +++ b/platform/broadcom/platform-modules-inventec.dep @@ -0,0 +1,10 @@ + +MPATH := $($(INVENTEC_D7032Q28B_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-inventec.mk platform/broadcom/platform-modules-inventec.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-inventec.mk b/platform/broadcom/platform-modules-inventec.mk new file mode 100644 index 000000000000..4f88f5b92163 --- /dev/null +++ b/platform/broadcom/platform-modules-inventec.mk @@ -0,0 +1,48 @@ +# Inventec platform modules + +INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION = 1.1.0 +INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION = 1.1.0 +INVENTEC_D6254QS_PLATFORM_MODULE_VERSION = 1.1.0 +INVENTEC_D6556_PLATFORM_MODULE_VERSION = 1.1.0 +INVENTEC_D6356_PLATFORM_MODULE_VERSION = 1.1.0 +INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION = 1.1.0 +INVENTEC_D6332_PLATFORM_MODULE_VERSION = 1.1.0 + +export INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION +export INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION +export INVENTEC_D6254QS_PLATFORM_MODULE_VERSION +export INVENTEC_D6556_PLATFORM_MODULE_VERSION +export INVENTEC_D6356_PLATFORM_MODULE_VERSION +export INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION +export INVENTEC_D6332_PLATFORM_MODULE_VERSION + +INVENTEC_D7032Q28B_PLATFORM_MODULE = platform-modules-d7032q28b_$(INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION)_amd64.deb +$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-inventec +$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7032q28b-r0 +SONIC_DPKG_DEBS += $(INVENTEC_D7032Q28B_PLATFORM_MODULE) + +INVENTEC_D7054Q28B_PLATFORM_MODULE = platform-modules-d7054q28b_$(INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION)_amd64.deb +$(INVENTEC_D7054Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7054q28b-r0 +$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D7054Q28B_PLATFORM_MODULE))) + +INVENTEC_D6254QS_PLATFORM_MODULE = platform-modules-d6254qs_$(INVENTEC_D6254QS_PLATFORM_MODULE_VERSION)_amd64.deb +$(INVENTEC_D6254QS_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6254qs-r0 +$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6254QS_PLATFORM_MODULE))) + +INVENTEC_D6556_PLATFORM_MODULE = platform-modules-d6556_$(INVENTEC_D6556_PLATFORM_MODULE_VERSION)_amd64.deb +$(INVENTEC_D6556_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6556-r0 +$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6556_PLATFORM_MODULE))) + +INVENTEC_D6356_PLATFORM_MODULE = platform-modules-d6356_$(INVENTEC_D6356_PLATFORM_MODULE_VERSION)_amd64.deb +$(INVENTEC_D6356_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6356-r0 +$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6356_PLATFORM_MODULE))) + +INVENTEC_D7264Q28B_PLATFORM_MODULE = platform-modules-d7264q28b_$(INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION)_amd64.deb +$(INVENTEC_D7264Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7264q28b-r0 +$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D7264Q28B_PLATFORM_MODULE))) + +INVENTEC_D6332_PLATFORM_MODULE = platform-modules-d6332_$(INVENTEC_D6332_PLATFORM_MODULE_VERSION)_amd64.deb +$(INVENTEC_D6332_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6332-r0 +$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6332_PLATFORM_MODULE))) + diff --git a/platform/broadcom/platform-modules-juniper.dep b/platform/broadcom/platform-modules-juniper.dep new file mode 100644 index 000000000000..0301480e31cf --- /dev/null +++ b/platform/broadcom/platform-modules-juniper.dep @@ -0,0 +1,10 @@ + +SPATH := $($(JUNIPER_QFX5210_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-juniper.mk platform/broadcom/platform-modules-juniper.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(JUNIPER_QFX5210_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(JUNIPER_QFX5210_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(JUNIPER_QFX5210_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-juniper.mk b/platform/broadcom/platform-modules-juniper.mk new file mode 100755 index 000000000000..f6a9b68d70de --- /dev/null +++ b/platform/broadcom/platform-modules-juniper.mk @@ -0,0 +1,18 @@ +# Juniper Platform modules + +JUNIPER_QFX5210_PLATFORM_MODULE_VERSION = 1.1 +JUNIPER_QFX5200_PLATFORM_MODULE_VERSION = 1.1 + +export JUNIPER_QFX5210_PLATFORM_MODULE_VERSION +export JUNIPER_QFX5200_PLATFORM_MODULE_VERSION + +JUNIPER_QFX5210_PLATFORM_MODULE = sonic-platform-juniper-qfx5210_$(JUNIPER_QFX5210_PLATFORM_MODULE_VERSION)_amd64.deb +$(JUNIPER_QFX5210_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-juniper +$(JUNIPER_QFX5210_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(JUNIPER_QFX5210_PLATFORM_MODULE)_PLATFORM = x86_64-juniper_qfx5210-r0 +SONIC_DPKG_DEBS += $(JUNIPER_QFX5210_PLATFORM_MODULE) + +JUNIPER_QFX5200_PLATFORM_MODULE = sonic-platform-juniper-qfx5200_$(JUNIPER_QFX5200_PLATFORM_MODULE_VERSION)_amd64.deb +$(JUNIPER_QFX5200_PLATFORM_MODULE)_PLATFORM = x86_64-juniper_qfx5200-r0 + +$(eval $(call add_extra_package,$(JUNIPER_QFX5210_PLATFORM_MODULE),$(JUNIPER_QFX5200_PLATFORM_MODULE))) diff --git a/platform/broadcom/platform-modules-mitac.dep b/platform/broadcom/platform-modules-mitac.dep new file mode 100644 index 000000000000..cbeeec81ad56 --- /dev/null +++ b/platform/broadcom/platform-modules-mitac.dep @@ -0,0 +1,10 @@ + +MPATH := $($(MITAC_LY1200_32X_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-mitac.mk platform/broadcom/platform-modules-mitac.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(MITAC_LY1200_32X_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(MITAC_LY1200_32X_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MITAC_LY1200_32X_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-mitac.mk b/platform/broadcom/platform-modules-mitac.mk new file mode 100644 index 000000000000..5a0c303f19d4 --- /dev/null +++ b/platform/broadcom/platform-modules-mitac.mk @@ -0,0 +1,12 @@ +# MiTAC Platform modules + +MITAC_LY1200_32X_PLATFORM_MODULE_VERSION = 1.0 + +export MITAC_LY1200_32X_PLATFORM_MODULE_VERSION + +MITAC_LY1200_32X_PLATFORM_MODULE = sonic-platform-mitac-ly1200-32x_$(MITAC_LY1200_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(MITAC_LY1200_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-mitac +$(MITAC_LY1200_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(MITAC_LY1200_32X_PLATFORM_MODULE)_PLATFORM = x86_64-mitac_ly1200_b32h0_c3-r0 +SONIC_DPKG_DEBS += $(MITAC_LY1200_32X_PLATFORM_MODULE) + diff --git a/platform/broadcom/platform-modules-quanta.dep b/platform/broadcom/platform-modules-quanta.dep new file mode 100644 index 000000000000..f4167a66d758 --- /dev/null +++ b/platform/broadcom/platform-modules-quanta.dep @@ -0,0 +1,10 @@ + +MPATH := $($(QUANTA_IX1B_32X_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-quanta.mk platform/broadcom/platform-modules-quanta.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(QUANTA_IX1B_32X_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(QUANTA_IX1B_32X_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(QUANTA_IX1B_32X_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform-modules-quanta.mk b/platform/broadcom/platform-modules-quanta.mk new file mode 100644 index 000000000000..267d3d9e7378 --- /dev/null +++ b/platform/broadcom/platform-modules-quanta.mk @@ -0,0 +1,36 @@ +# Quanta Platform modules + +QUANTA_IX1B_32X_PLATFORM_MODULE_VERSION = 1.0 +QUANTA_IX7_32X_PLATFORM_MODULE_VERSION = 1.0 +QUANTA_IX8_56X_PLATFORM_MODULE_VERSION = 1.0 +QUANTA_IX8C_56X_PLATFORM_MODULE_VERSION = 1.0 +QUANTA_IX9_32X_PLATFORM_MODULE_VERSION = 1.0 + +export QUANTA_IX1B_32X_PLATFORM_MODULE_VERSION +export QUANTA_IX7_32X_PLATFORM_MODULE_VERSION +export QUANTA_IX8_56X_PLATFORM_MODULE_VERSION +export QUANTA_IX8C_56X_PLATFORM_MODULE_VERSION +export QUANTA_IX9_32X_PLATFORM_MODULE_VERSION + +QUANTA_IX1B_32X_PLATFORM_MODULE = sonic-platform-quanta-ix1b-32x_$(QUANTA_IX1B_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(QUANTA_IX1B_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-quanta +$(QUANTA_IX1B_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(QUANTA_IX1B_32X_PLATFORM_MODULE)_PLATFORM = x86_64-quanta_ix1b_rglbmc-r0 +SONIC_DPKG_DEBS += $(QUANTA_IX1B_32X_PLATFORM_MODULE) + +QUANTA_IX7_32X_PLATFORM_MODULE = sonic-platform-quanta-ix7-32x_$(QUANTA_IX7_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(QUANTA_IX7_32X_PLATFORM_MODULE)_PLATFORM = x86_64-quanta_ix7_rglbmc-r0 +$(eval $(call add_extra_package,$(QUANTA_IX1B_32X_PLATFORM_MODULE),$(QUANTA_IX7_32X_PLATFORM_MODULE))) + +QUANTA_IX8_56X_PLATFORM_MODULE = sonic-platform-quanta-ix8-56x_$(QUANTA_IX8_56X_PLATFORM_MODULE_VERSION)_amd64.deb +$(QUANTA_IX8_56X_PLATFORM_MODULE)_PLATFORM = x86_64-quanta_ix8_rglbmc-r0 +$(eval $(call add_extra_package,$(QUANTA_IX1B_32X_PLATFORM_MODULE),$(QUANTA_IX8_56X_PLATFORM_MODULE))) + +QUANTA_IX8C_56X_PLATFORM_MODULE = sonic-platform-quanta-ix8c-56x_$(QUANTA_IX8C_56X_PLATFORM_MODULE_VERSION)_amd64.deb +$(QUANTA_IX8C_56X_PLATFORM_MODULE)_PLATFORM = x86_64-quanta_ix8c_bwde-r0 +$(eval $(call add_extra_package,$(QUANTA_IX1B_32X_PLATFORM_MODULE),$(QUANTA_IX8C_56X_PLATFORM_MODULE))) + +QUANTA_IX9_32X_PLATFORM_MODULE = sonic-platform-quanta-ix9-32x_$(QUANTA_IX9_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(QUANTA_IX9_32X_PLATFORM_MODULE)_PLATFORM = x86_64-quanta_ix9_bwde-r0 +$(eval $(call add_extra_package,$(QUANTA_IX1B_32X_PLATFORM_MODULE),$(QUANTA_IX9_32X_PLATFORM_MODULE))) + diff --git a/platform/broadcom/platform-modules-ruijie.dep b/platform/broadcom/platform-modules-ruijie.dep new file mode 100644 index 000000000000..8910bfcf2e82 --- /dev/null +++ b/platform/broadcom/platform-modules-ruijie.dep @@ -0,0 +1,8 @@ +MPATH := $($(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-ruijie.mk platform/broadcom/platform-modules-ruijie.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) diff --git a/platform/broadcom/platform-modules-ruijie.mk b/platform/broadcom/platform-modules-ruijie.mk new file mode 100644 index 000000000000..b712f67fec89 --- /dev/null +++ b/platform/broadcom/platform-modules-ruijie.mk @@ -0,0 +1,10 @@ +# Ruijie platform modules +RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE_VERSION = 1.0 +export RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE_VERSION + +RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE = platform-modules-ruijie-b6510-48vs8cq_$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE_VERSION)_amd64.deb +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ruijie +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE)_PLATFORM = x86_64-ruijie_b6510-48vs8cq-r0 +SONIC_DPKG_DEBS += $(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE) +SONIC_STRETCH_DEBS += $(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE) diff --git a/platform/broadcom/platform-modules-s6000.dep b/platform/broadcom/platform-modules-s6000.dep new file mode 100644 index 000000000000..fff2d52dd753 --- /dev/null +++ b/platform/broadcom/platform-modules-s6000.dep @@ -0,0 +1,10 @@ + +MPATH := $($(DELL_S6000_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-s6000.mk platform/broadcom/platform-modules-s6000.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(DELL_S6000_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(DELL_S6000_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DELL_S6000_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/platform.conf b/platform/broadcom/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/raw-image.dep b/platform/broadcom/raw-image.dep new file mode 100644 index 000000000000..500ba2a70fef --- /dev/null +++ b/platform/broadcom/raw-image.dep @@ -0,0 +1,2 @@ +#DPKG FRK +$(SONIC_RAW_IMAGE)_CACHE_MODE := none diff --git a/platform/broadcom/raw-image.mk b/platform/broadcom/raw-image.mk new file mode 100644 index 000000000000..15534e893937 --- /dev/null +++ b/platform/broadcom/raw-image.mk @@ -0,0 +1,10 @@ +# sonic broadcom raw image installer + +SONIC_RAW_IMAGE = sonic-broadcom.raw +$(SONIC_RAW_IMAGE)_MACHINE = broadcom +$(SONIC_RAW_IMAGE)_IMAGE_TYPE = raw +$(SONIC_RAW_IMAGE)_INSTALLS += $(BRCM_OPENNSL_KERNEL) +$(SONIC_RAW_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_RAW_IMAGE)_LAZY_INSTALLS += $($(SONIC_ONE_IMAGE)_LAZY_INSTALLS) +$(SONIC_RAW_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_RAW_IMAGE) diff --git a/platform/broadcom/rules.dep b/platform/broadcom/rules.dep new file mode 100644 index 000000000000..2e2d44ed018a --- /dev/null +++ b/platform/broadcom/rules.dep @@ -0,0 +1,24 @@ +#DPKG FRK +include $(PLATFORM_PATH)/sai-modules.dep +include $(PLATFORM_PATH)/sai.dep +include $(PLATFORM_PATH)/platform-modules-s6000.dep +include $(PLATFORM_PATH)/platform-modules-dell.dep +include $(PLATFORM_PATH)/platform-modules-arista.dep +include $(PLATFORM_PATH)/platform-modules-ingrasys.dep +include $(PLATFORM_PATH)/platform-modules-accton.dep +include $(PLATFORM_PATH)/platform-modules-alphanetworks.dep +include $(PLATFORM_PATH)/platform-modules-inventec.dep +include $(PLATFORM_PATH)/platform-modules-cel.dep +include $(PLATFORM_PATH)/platform-modules-delta.dep +include $(PLATFORM_PATH)/platform-modules-quanta.dep +#include $(PLATFORM_PATH)/platform-modules-mitac.dep +include $(PLATFORM_PATH)/platform-modules-juniper.dep +include $(PLATFORM_PATH)/platform-modules-brcm-xlr-gts.dep +include $(PLATFORM_PATH)/docker-syncd-brcm.dep +include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.dep +include $(PLATFORM_PATH)/docker-saiserver-brcm.dep +include $(PLATFORM_PATH)/one-image.dep +include $(PLATFORM_PATH)/one-pde-image.dep +include $(PLATFORM_PATH)/raw-image.dep +include $(PLATFORM_PATH)/one-aboot.dep +include $(PLATFORM_PATH)/libsaithrift-dev.dep diff --git a/platform/broadcom/rules.mk b/platform/broadcom/rules.mk new file mode 100644 index 000000000000..73bf93c3d7f4 --- /dev/null +++ b/platform/broadcom/rules.mk @@ -0,0 +1,44 @@ +include $(PLATFORM_PATH)/sai-modules.mk +include $(PLATFORM_PATH)/sai.mk +include $(PLATFORM_PATH)/platform-modules-dell.mk +include $(PLATFORM_PATH)/platform-modules-arista.mk +include $(PLATFORM_PATH)/platform-modules-ingrasys.mk +include $(PLATFORM_PATH)/platform-modules-accton.mk +include $(PLATFORM_PATH)/platform-modules-alphanetworks.mk +include $(PLATFORM_PATH)/platform-modules-inventec.mk +include $(PLATFORM_PATH)/platform-modules-cel.mk +include $(PLATFORM_PATH)/platform-modules-delta.mk +include $(PLATFORM_PATH)/platform-modules-quanta.mk +#include $(PLATFORM_PATH)/platform-modules-mitac.mk +include $(PLATFORM_PATH)/platform-modules-juniper.mk +include $(PLATFORM_PATH)/platform-modules-brcm-xlr-gts.mk +include $(PLATFORM_PATH)/platform-modules-ruijie.mk +include $(PLATFORM_PATH)/docker-syncd-brcm.mk +include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.mk +include $(PLATFORM_PATH)/docker-saiserver-brcm.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/raw-image.mk +include $(PLATFORM_PATH)/one-aboot.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk + +BCMCMD = bcmcmd +$(BCMCMD)_URL = "https://sonicstorage.blob.core.windows.net/packages/20190307/bcmcmd?sv=2015-04-05&sr=b&sig=sUdbU7oVbh5exbXXHVL5TDFBTWDDBASHeJ8Cp0B0TIc%3D&se=2038-05-06T22%3A34%3A19Z&sp=r" + +DSSERVE = dsserve +$(DSSERVE)_URL = "https://sonicstorage.blob.core.windows.net/packages/20190307/dsserve?sv=2015-04-05&sr=b&sig=lk7BH3DtW%2F5ehc0Rkqfga%2BUCABI0UzQmDamBsZH9K6w%3D&se=2038-05-06T22%3A34%3A45Z&sp=r" + +SONIC_ONLINE_FILES += $(BCMCMD) $(DSSERVE) + +SONIC_ALL += $(SONIC_ONE_IMAGE) $(SONIC_ONE_ABOOT_IMAGE) \ + $(DOCKER_FPM) + +# Inject brcm sai into syncd +$(SYNCD)_DEPENDS += $(BRCM_SAI) $(BRCM_SAI_DEV) +$(SYNCD)_UNINSTALLS += $(BRCM_SAI_DEV) + +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV) +endif + +# Runtime dependency on brcm sai is set only for syncd +$(SYNCD)_RDEPENDS += $(BRCM_SAI) diff --git a/platform/broadcom/sai-modules.dep b/platform/broadcom/sai-modules.dep new file mode 100644 index 000000000000..040a7d75d4c7 --- /dev/null +++ b/platform/broadcom/sai-modules.dep @@ -0,0 +1,10 @@ + +MPATH := $($(BRCM_OPENNSL_KERNEL)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/sai-modules.mk platform/broadcom/sai-modules.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(BRCM_OPENNSL_KERNEL)_CACHE_MODE := GIT_CONTENT_SHA +$(BRCM_OPENNSL_KERNEL)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(BRCM_OPENNSL_KERNEL)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/sai-modules.mk b/platform/broadcom/sai-modules.mk new file mode 100644 index 000000000000..2d4262518c68 --- /dev/null +++ b/platform/broadcom/sai-modules.mk @@ -0,0 +1,8 @@ +# Broadcom SAI modules + +BRCM_OPENNSL_KERNEL_VERSION = 4.3.0.10-2 + +BRCM_OPENNSL_KERNEL = opennsl-modules_$(BRCM_OPENNSL_KERNEL_VERSION)_amd64.deb +$(BRCM_OPENNSL_KERNEL)_SRC_PATH = $(PLATFORM_PATH)/saibcm-modules +$(BRCM_OPENNSL_KERNEL)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_DPKG_DEBS += $(BRCM_OPENNSL_KERNEL) diff --git a/platform/broadcom/sai.dep b/platform/broadcom/sai.dep new file mode 100644 index 000000000000..c5b10a4e93a3 --- /dev/null +++ b/platform/broadcom/sai.dep @@ -0,0 +1,18 @@ + +#DPKG FRK +SPATH := $($(BRCM_SAI)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/sai.mk platform/broadcom/sai.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +# Get the Latest HTTP Header and calculate the SHA value as it is a softlink that always points to LATEST_INT_OCP_SAI_X.X.X +SAI_FLAGS := $(shell wget --spider --server-response $($(BRCM_SAI)_URL) $($(BRCM_SAI_DEV)_URL) 2>&1 \ + | grep -Ev -- '--|Date:|x-ms-request-id'|sha256sum|awk '{print $$1}' ) + +$(BRCM_SAI)_CACHE_MODE := GIT_CONTENT_SHA +$(BRCM_SAI)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) $(SAI_FLAGS) +$(BRCM_SAI)_DEP_FILES := $(DEP_FILES) + + +$(BRCM_SAI_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(BRCM_SAI_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) $(SAI_FLAGS) +$(BRCM_SAI_DEV)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/broadcom/sai.mk b/platform/broadcom/sai.mk new file mode 100644 index 000000000000..046aca2af658 --- /dev/null +++ b/platform/broadcom/sai.mk @@ -0,0 +1,9 @@ +BRCM_SAI = libsaibcm_4.3.0.13-1_amd64.deb +$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/4.3/master/libsaibcm_4.3.0.13-1_amd64.deb?sv=2015-04-05&sr=b&sig=e%2BBucofzEwCC%2BclqK1OeCi5YFpQAD4ID4FfODzszsuM%3D&se=2034-10-22T06%3A00%3A14Z&sp=r" +BRCM_SAI_DEV = libsaibcm-dev_4.3.0.13-1_amd64.deb +$(eval $(call add_derived_package,$(BRCM_SAI),$(BRCM_SAI_DEV))) +$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/4.3/master/libsaibcm-dev_4.3.0.13-1_amd64.deb?sv=2015-04-05&sr=b&sig=twfshldM6GQEphfU%2BQ4xmJlGJkv2Sy7KU1F72RYYM0A%3D&se=2034-10-22T06%3A00%3A45Z&sp=r" + +SONIC_ONLINE_DEBS += $(BRCM_SAI) +$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI) +$(eval $(call add_conflict_package,$(BRCM_SAI_DEV),$(LIBSAIVS_DEV))) diff --git a/platform/broadcom/saibcm-modules/.gitignore b/platform/broadcom/saibcm-modules/.gitignore new file mode 100644 index 000000000000..f2e54da55c5f --- /dev/null +++ b/platform/broadcom/saibcm-modules/.gitignore @@ -0,0 +1,10 @@ +*.debhelper.log +*.debhelper +*.substvars +*.ko + +build-arch-stamp +build/ +configure-stamp +debian/files +debian/opennsl-modules/ diff --git a/platform/broadcom/saibcm-modules/debian/changelog b/platform/broadcom/saibcm-modules/debian/changelog new file mode 100644 index 000000000000..87d659d21a61 --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/changelog @@ -0,0 +1,82 @@ +opennsl (4.3.0.10-2) unstable; urgency=medium + + * Update to Broadcom SAI 4.3.0.10 + * Added SDKLT modules 4.3.0.10-2 + + -- Mahesh Maddikayala Thu, 21 Jan 2021 18:36:38 +0000 + +opennsl (4.2.1.3-1) unstable; urgency=medium + + * Update to Broadcom SAI 4.2.1.3 + + -- Mahesh Maddikayala Fri, 18 Sep 2029 10:57:47 +0000 + +opennsl (3.7.3.3-1) unstable; urgency=medium + + * Port Broadcom SAI 3.7.3.3 + * Cherry-pick change from master branch, 3.7.3.3-1 + + -- Judy Joseph Fri, 2 Dec 2019 15:32:47 +0000 + +opennsl (3.7.3.2-1) unstable; urgency=medium + + * Port Broadcom SAI 3.7.3.2 + * Cherry-pick change from master branch, 3.7.3.2-1 + + -- Judy Joseph Fri, 12 Nov 2019 15:22:47 +0000 + +opennsl (3.7.3.1-1) unstable; urgency=medium + + * Port Broadcom SAI 3.7.3.1 + * Cherry-pick change from master branch, 3.7.3.1-1 + + -- Judy Joseph Fri, 19 Sep 2019 13:11:47 +0000 + +opennsl (3.4.1.11-1) unstable; urgency=medium + + * Port Broadcom SAI 3.4.1.11 + * Cherry-pick change from master branch, 3.4.1.11-1 + + -- Ying Xie Fri, 05 Jan 2018 23:21:47 +0000 + +opennsl (3.4.1.10-1) unstable; urgency=medium + + * Upgrade to 3.4.1.10-1 + + -- Ying Xie Tue, 19 Dec 2017 21:33:48 +0000 + +opennsl (3.4.1.9-1) unstable; urgency=medium + + * Upgrade to 3.4.1.9-1 + + -- Ying Xie Thu, 14 Dec 2017 22:04:11 +0000 + +opennsl (3.4.1.7-2) unstable; urgency=medium + + * Add Arista 7260cx3 Rev2 hardware support + + -- Ying Xie Mon, 27 Nov 2017 18:13:50 +0000 + +opennsl (3.4.1.7-1) unstable; urgency=medium + + * Importing opennsl 3.4.1.7 + + -- Ying Xie Mon, 23 Oct 2017 23:47:25 +0000 + +opennsl (3.4.1.5-2) unstable; urgency=medium + + * Importing TD2 changes from opennsl 3.2.2.2 + + -- Ying Xie Tue, 26 Sep 2017 01:28:44 +0000 + +opennsl (3.4.1.5-1) unstable; urgency=medium + + * Importing opennsl 3.4.1.5 + + -- Ying Xie Wed, 20 Sep 2017 16:42:12 +0000 + +opennsl (3.4.1.3-1) unstable; urgency=low + + * Initial release + + -- Guohan Lu Fri, 17 Jul 2015 04:46:01 -0700 diff --git a/platform/broadcom/saibcm-modules/debian/compat b/platform/broadcom/saibcm-modules/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/broadcom/saibcm-modules/debian/control b/platform/broadcom/saibcm-modules/debian/control new file mode 100644 index 000000000000..60bcbafb1b1a --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/control @@ -0,0 +1,14 @@ +Source: opennsl +Section: main +Priority: extra +Maintainer: Guohan Lu +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 +#Vcs-Git: git://git.debian.org/collab-maint/bcmsdk.git +#Vcs-Browser: http://git.debian.org/?p=collab-maint/bcmsdk.git;a=summary + +Package: opennsl-modules +Architecture: amd64 +Section: main +Depends: linux-image-4.19.0-12-2-amd64-unsigned +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 new file mode 100644 index 000000000000..140d1186059e --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules.dirs @@ -0,0 +1 @@ +lib/modules/4.19.0-12-2-amd64/extra diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules.init b/platform/broadcom/saibcm-modules/debian/opennsl-modules.init new file mode 100755 index 000000000000..09112f5331ce --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules.init @@ -0,0 +1,106 @@ +#!/bin/bash +# This script load/unload opennsl kernel modules + +### BEGIN INIT INFO +# Provides: load-opennsl-modules +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load OpenNSL kernel modules +### END INIT INFO + +function create_devices() +{ + rm -f /dev/linux-knet-cb + rm -f /dev/linux-bcm-knet + rm -f /dev/linux-bcm-bde + rm -f /dev/linux-kernel-bde + rm -f /dev/linux_ngbde + + mknod /dev/linux_ngbde c 120 0 + mknod /dev/linux-knet-cb c 121 0 + mknod /dev/linux-bcm-knet c 122 0 + mknod /dev/linux-bcm-bde c 126 0 + mknod /dev/linux-kernel-bde c 127 0 +} + +# linux-kernel-bde debug=4 ==> Verbose level debug +# dma_debug=1 ==> Enable DMA debug +# linux-bcm-knet debug=0x5020 ==> Enable KNET Warning(0x1000), +# Events(0x20) and Instance(0x4000) +# level logs +function load_kernel_modules() +{ + . /host/machine.conf + + if [ -n "$aboot_platform" ]; then + platform=$aboot_platform + elif [ -n "$onie_platform" ]; then + platform=$onie_platform + else + platform="unknown" + fi + + # Set the default configuration for dmasize and usemsi parameters + dmasize=32M + usemsi=0 + + # Source the platform env file + env_file="/usr/share/sonic/device/$platform/platform_env.conf" + source $env_file + + modprobe linux-kernel-bde dmasize=$dmasize maxpayload=128 debug=4 dma_debug=1 usemsi=$usemsi + modprobe linux-user-bde + + # Using insmod with absolute path for psample to make sure bcm psample is loaded. + # There is a different psample.ko module getting created at net/psample/psample.ko + insmod /lib/modules/$(uname -r)/extra/psample.ko + + modprobe linux-bcm-knet use_rx_skb=1 rx_buffer_size=9238 debug=0x5020 default_mtu=9100 + modprobe linux-knet-cb + modprobe linux_ngbde +} + +function remove_kernel_modules() +{ + rmmod psample.ko + rmmod linux-knet-cb + rmmod linux-bcm-knet + rmmod linux-user-bde + rmmod linux-kernel-bde + rmmod linux_ngbde +} + +case "$1" in +start) + echo -n "Load OpenNSL kernel modules... " + + create_devices + load_kernel_modules + + echo "done." + ;; + +stop) + echo -n "Unload OpenNSL kernel modules... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/opennsl-modules.init {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules.install b/platform/broadcom/saibcm-modules/debian/opennsl-modules.install new file mode 100644 index 000000000000..5e8e70bb189f --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules.install @@ -0,0 +1,8 @@ +systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-knet.ko lib/modules/4.19.0-12-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-kernel-bde.ko lib/modules/4.19.0-12-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-user-bde.ko lib/modules/4.19.0-12-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-knet-cb.ko lib/modules/4.19.0-12-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/psample.ko lib/modules/4.19.0-12-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-ptp-clock.ko lib/modules/4.19.0-12-2-amd64/extra +systemd/opennsl-modules.service lib/systemd/system +sdklt/linux/bde/linux_ngbde.ko lib/modules/4.19.0-12-2-amd64/extra diff --git a/platform/broadcom/saibcm-modules/debian/rules b/platform/broadcom/saibcm-modules/debian/rules new file mode 100755 index 000000000000..572471027c87 --- /dev/null +++ b/platform/broadcom/saibcm-modules/debian/rules @@ -0,0 +1,217 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. +# +# This version is for a hypothetical package that can build a kernel modules +# architecture-dependant package via make-kpkg, as well as an +# architecture-independent module source package, and other packages +# either dep/indep for things like common files or userspace components +# needed for the kernel modules. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + + + +# some default definitions, important! +# +# Name of the source package +psource:=opennsl-source + +# The short upstream name, used for the module source directory +sname:=opennsl + +### KERNEL SETUP +### Setup the stuff needed for making kernel module packages +### taken from /usr/share/kernel-package/sample.module.rules + +# prefix of the target package name +PACKAGE=opennsl-modules +# modifieable for experiments or debugging m-a +MA_DIR ?= /usr/share/modass +KVERSION ?= 4.19.0-12-2-amd64 +KERNVERSION ?= 4.19.0-12-2 + +# load generic variable handling +-include $(MA_DIR)/include/generic.make +# load default rules, including kdist, kdist_image, ... +-include $(MA_DIR)/include/common-rules.make + + + +# module assistant calculates all needed things for us and sets +# following variables: +# KSRC (kernel source directory), KVERS (kernel version string), KDREV +# (revision of the Debian kernel-image package), CC (the correct +# compiler), VERSION (the final package version string), PKGNAME (full +# package name with KVERS included), DEB_DESTDIR (path to store DEBs) + +# The kdist_config target is called by make-kpkg modules_config and +# by kdist* rules by dependency. It should configure the module so it is +# ready for compilation (mostly useful for calling configure). +# prep-deb-files from module-assistant creates the neccessary debian/ files +kdist_config: prep-deb-files + +# the kdist_clean target is called by make-kpkg modules_clean and from +# kdist* rules. It is responsible for cleaning up any changes that have +# been made by the other kdist_commands (except for the .deb files created) +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-$(KERNVERSION)-common \ + KERNEL_SRC=/usr/src/linux-headers-$(KERNVERSION)-amd64 \ + $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean + SDK=$(realpath .) BUILD_KNET_CB=1 BUILD_PSAMPLE=1 \ + KDIR=/usr/src/linux-headers-$(KERNVERSION)-common \ + $(MAKE) -C sdklt/ clean +# rm -f driver/*.o driver/*.ko +# +### end KERNEL SETUP + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + + touch configure-stamp + + +build-arch: configure-stamp build-arch-stamp +build-arch-stamp: + dh_testdir + + # create links + cd /; sudo mkdir -p /lib/modules/$(KERNVERSION)-amd64 + cd /; sudo rm /lib/modules/$(KERNVERSION)-amd64/build + cd /; sudo rm /lib/modules/$(KERNVERSION)-amd64/source + cd /; sudo ln -s /usr/src/linux-headers-$(KERNVERSION)-common/ /lib/modules/$(KERNVERSION)-amd64/source + cd /; sudo ln -s /usr/src/linux-headers-$(KERNVERSION)-amd64/ /lib/modules/$(KERNVERSION)-amd64/build + cd /; sudo ln -s /usr/src/linux-headers-$(KERNVERSION)-amd64/include/generated/ /usr/src/linux-headers-$(KERNVERSION)-common/include/generated + cd /; sudo ln -s /usr/src/linux-headers-$(KERNVERSION)-amd64/arch/x86/include/generated/ /usr/src/linux-headers-$(KERNVERSION)-common/arch/x86/include/generated + cd /; sudo ln -s /usr/src/linux-headers-$(KERNVERSION)-amd64/include/config/ /usr/src/linux-headers-$(KERNVERSION)-common/include/config + cd /; sudo cp /usr/src/linux-headers-$(KERNVERSION)-amd64/Module.symvers /usr/src/linux-headers-$(KERNVERSION)-common/Module.symvers + + # 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-$(KERNVERSION)-common \ + KERNEL_SRC=/usr/src/linux-headers-$(KERNVERSION)-amd64 \ + $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 + + SDK=$(realpath .) BUILD_KNET_CB=1 BUILD_PSAMPLE=1 \ + KDIR=/usr/src/linux-headers-$(KERNVERSION)-common \ + $(MAKE) -C sdklt/ kmod + + touch $@ + +#k = $(shell echo $(KVERS) | grep -q ^2.6 && echo k) + +build-indep: configure-stamp build-indep-stamp +build-indep-stamp: + dh_testdir + + # Add here command to compile/build the arch indep package. + # It's ok not to do anything here, if you don't need to build + # anything for this package. + #docbook-to-man debian/opennsl.sgml > opennsl.1 + + touch $@ + +build: build-arch + +clean: + dh_testdir + #dh_testroot + 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-$(KERNVERSION)-common \ + KERNEL_SRC=/usr/src/linux-headers-$(KERNVERSION)-amd64 \ + $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean + + SDK=$(realpath .) BUILD_KNET_CB=1 BUILD_PSAMPLE=1 \ + KDIR=/usr/src/linux-headers-$(KERNVERSION)-common \ + $(MAKE) -C sdklt/ clean + + dh_clean + +install: DH_OPTIONS= +install: build + dh_testdir + dh_testroot + dh_prep + dh_installdirs + dh_install + +# Build architecture-independent files here. +# Pass -i to all debhelper commands in this target to reduce clutter. +binary-indep: build install + dh_testdir -i + dh_testroot -i + dh_installchangelogs -i + dh_installdocs -i + dh_installexamples -i +# dh_install -i +# dh_installmenu -i +# dh_installdebconf -i +# dh_installlogrotate -i +# dh_installemacsen -i +# dh_installpam -i +# dh_installmime -i +# dh_installinit -i +# dh_installcron -i +# dh_installinfo -i + dh_installman -i + dh_link -i + dh_compress -i + dh_fixperms -i + dh_installdeb -i +# dh_perl -i +# dh_makeshlibs -i + dh_installdeb -i + dh_shlibdeps -i + dh_gencontrol -i + dh_md5sums -i + dh_builddeb -i + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir -s + dh_testroot -s +# dh_installdebconf -s + + dh_installdocs -s + dh_installexamples -s + dh_installmenu -s +# dh_installlogrotate -s +# dh_installemacsen -s +# dh_installpam -s +# dh_installmime -s + dh_installmodules -s + dh_systemd_enable -s + dh_installinit -s + dh_systemd_start -s + dh_installcron -s +# dh_installman -s + dh_installinfo -s + dh_installchangelogs -s + dh_strip -s + dh_link -s + dh_compress -s + dh_fixperms -s + dh_makeshlibs -s + dh_installdeb -s +# dh_perl -s + dh_shlibdeps -s + dh_gencontrol -s + dh_md5sums -s + dh_builddeb -s + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure binary-modules kdist kdist_configure kdist_image kdist_clean diff --git a/platform/broadcom/saibcm-modules/include/ibde.h b/platform/broadcom/saibcm-modules/include/ibde.h new file mode 100644 index 000000000000..fb9d13d1d5fe --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/ibde.h @@ -0,0 +1,189 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: ibde.h,v 1.27 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef __IBDE_H__ +#define __IBDE_H__ + +#include + +/* + * Represents a collection of devices + */ + +typedef struct ibde_dev_s { + uint16 device; + uint8 rev; + sal_vaddr_t base_address; + sal_vaddr_t base_address1; + sal_vaddr_t base_address2; + /* a unique number representing the specific device. + * Must be different for different devices. + * May be used to identify specific devices in the system. + * May be implemented as a full PCIe address, a persistent configurable user value, ... + * Possible implementation value stores in QSPI flash memory of the device. */ + uint32 dev_unique_id; +} ibde_dev_t; + + +typedef struct ibde_s { + + const char *(*name)(void); + + /* Returns the number of devices available */ + /* Each device is is accessed through a handle */ + /* Handles are assumed to index the array of devices */ + + /* Support SWITCH or ETHERNET or CPU devices */ + int (*num_devices)(int type); +#define BDE_ALL_DEVICES 0 +#define BDE_SWITCH_DEVICES 1 +#define BDE_ETHER_DEVICES 2 +#define BDE_CPU_DEVICES 3 + + const ibde_dev_t *(*get_dev)(int d); + + /* + * Get types of underlaying devices. + * A combination of bus type and functional type is returned. + * In case of bus type, support PCI and SPI device types. + * In case of functional type, specify if underlaying device is + * a switching or ethernet device. + */ + uint32 (*get_dev_type)(int d); +#define BDE_PCI_DEV_TYPE SAL_PCI_DEV_TYPE /* PCI device */ +#define BDE_SPI_DEV_TYPE SAL_SPI_DEV_TYPE /* SPI device */ +#define BDE_EB_DEV_TYPE SAL_EB_DEV_TYPE /* EB device */ +#define BDE_ICS_DEV_TYPE SAL_ICS_DEV_TYPE /* ICS device */ +#define BDE_MII_DEV_TYPE SAL_MII_DEV_TYPE /* MII device */ +#define BDE_I2C_DEV_TYPE SAL_I2C_DEV_TYPE /* I2C device */ +#define BDE_AXI_DEV_TYPE SAL_AXI_DEV_TYPE /* AXI device */ +#define BDE_EMMI_DEV_TYPE SAL_EMMI_DEV_TYPE /* EMMI device */ +#define BDE_DEV_BUS_ALT SAL_DEV_BUS_ALT /* Alternate Access */ +#define BDE_DEV_BUS_MSI SAL_DEV_BUS_MSI /* Message-signaled interrupts */ + +#define BDE_DEV_BUS_TYPE_MASK SAL_DEV_BUS_TYPE_MASK + +#define BDE_SWITCH_DEV_TYPE SAL_SWITCH_DEV_TYPE /* Switch device */ +#define BDE_ETHER_DEV_TYPE SAL_ETHER_DEV_TYPE /* Ethernet device */ +#define BDE_CPU_DEV_TYPE SAL_CPU_DEV_TYPE /* CPU device */ + +#define BDE_BYTE_SWAP 0x01000000 /* SW byte swap */ +#define BDE_NO_IPROC 0x02000000 /* Device uses two BARs, but is not iProc */ + +#define BDE_8MB_REG_SPACE 0x10000000 /* 8MB sized CMIC BAR */ +#define BDE_256K_REG_SPACE 0x20000000 /* Map 256K (v 64K) */ +#define BDE_128K_REG_SPACE 0x40000000 /* Map 128K (v 64K) */ +#define BDE_320K_REG_SPACE 0x80000000 /* Map 256K+64K */ + +/* Bus supports only 16bit reads */ +#define BDE_DEV_BUS_RD_16BIT SAL_DEV_BUS_RD_16BIT + +/* Bus supports only 16bit writes */ +#define BDE_DEV_BUS_WR_16BIT SAL_DEV_BUS_WR_16BIT + +/* Backward compatibility */ +#define BDE_ET_DEV_TYPE BDE_MII_DEV_TYPE + +#define BDE_DEV_MEM_MAPPED(_d) \ + ((_d) & (BDE_PCI_DEV_TYPE | BDE_ICS_DEV_TYPE | BDE_EB_DEV_TYPE |\ + BDE_EMMI_DEV_TYPE | BDE_AXI_DEV_TYPE)) + + /* + * PCI Bus Access + */ + uint32 (*pci_conf_read)(int d, uint32 addr); + int (*pci_conf_write)(int d, uint32 addr, uint32 data); + void (*pci_bus_features)(int d, int *be_pio, int *be_packet, + int *be_other); + + uint32 (*read)(int d, uint32 addr); + int (*write)(int d, uint32 addr, uint32 data); + + uint32* (*salloc)(int d, int size, const char *name); + void (*sfree)(int d, void *ptr); + int (*sflush)(int d, void *addr, int length); + int (*sinval)(int d, void *addr, int length); + + int (*interrupt_connect)(int d, void (*)(void*), void *data); + int (*interrupt_disconnect)(int d); + + sal_paddr_t (*l2p)(int d, void *laddr); + void* (*p2l)(int d, sal_paddr_t paddr); + + /* + * SPI Access via SMP + */ + int (*spi_read)(int d, uint32 addr, uint8 *buf, int len); + int (*spi_write)(int d, uint32 addr, uint8 *buf, int len); + /* Special SPI access addresses */ +#define BDE_DEV_OP_EMMI_INIT SAL_DEV_OP_EMMI_INIT + + /* + * iProc register access + */ + uint32 (*iproc_read)(int d, uint32 addr); + int (*iproc_write)(int d, uint32 addr, uint32 data); + + /* + * Shared memory access + */ + uint32 (*shmem_read)(int dev, uint32 addr, uint8 *buf, uint32 len); + void (*shmem_write)(int dev, uint32 addr, uint8 *buf, uint32 len); + sal_vaddr_t (*shmem_map)(int dev, uint32 addr, uint32 size); + + /* + * cmic + */ + int (*get_cmic_ver)(int d, uint32 *ver); + + /* + * I2C operations on the Device, assuming it is connected by I2C to the CPU. + */ + /* Read from the internal device Address space using I2C */ + int (*i2c_device_read)( + int dev, /* The device ID to access */ + uint32 addr, /* The address to access in the internal device address space */ + uint32 *value);/* the value to be read. */ + /* Write to the internal device Address space using I2C */ + int (*i2c_device_write)( + int dev, /* The device ID to access */ + uint32 addr, /* The address to access in the internal device address space */ + uint32 value); /* the value to be written. */ + +} ibde_t; + + +/* System BDE */ +extern ibde_t *bde; + + +#endif /* __IBDE_H__ */ diff --git a/platform/broadcom/saibcm-modules/include/kcom.h b/platform/broadcom/saibcm-modules/include/kcom.h new file mode 100644 index 000000000000..5129400ca8cd --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/kcom.h @@ -0,0 +1,611 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: kcom.h,v 1.9 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * File: kcom.h + * Purpose: User/Kernel message definitions + */ + +#ifndef _KCOM_H +#define _KCOM_H + +#include + +#define KCOM_CHAN_KNET "KCOM_KNET" + +/* + * Message types + */ +#define KCOM_MSG_TYPE_CMD 1 /* Command */ +#define KCOM_MSG_TYPE_RSP 2 /* Command response */ +#define KCOM_MSG_TYPE_EVT 3 /* Unsolicited event */ + +/* + * Message opcodes + */ +#define KCOM_M_NONE 0 /* Should not be used */ +#define KCOM_M_VERSION 1 /* Protocol version */ +#define KCOM_M_STRING 2 /* For debug messages */ +#define KCOM_M_HW_RESET 3 /* H/W not ready */ +#define KCOM_M_HW_INIT 4 /* H/W initialized */ +#define KCOM_M_ETH_HW_CONFIG 5 /* ETH HW config*/ +#define KCOM_M_DETACH 6 /* Detach kernel module */ +#define KCOM_M_REPROBE 7 /* Reprobe device */ +#define KCOM_M_NETIF_CREATE 11 /* Create network interface */ +#define KCOM_M_NETIF_DESTROY 12 /* Destroy network interface */ +#define KCOM_M_NETIF_LIST 13 /* Get list of network interface IDs */ +#define KCOM_M_NETIF_GET 14 /* Get network interface info */ +#define KCOM_M_FILTER_CREATE 21 /* Create Rx filter */ +#define KCOM_M_FILTER_DESTROY 22 /* Destroy Rx filter */ +#define KCOM_M_FILTER_LIST 23 /* Get list of Rx filter IDs */ +#define KCOM_M_FILTER_GET 24 /* Get Rx filter info */ +#define KCOM_M_DMA_INFO 31 /* Tx/Rx DMA info */ +#define KCOM_M_DBGPKT_SET 41 /* Enbale debug packet function */ +#define KCOM_M_DBGPKT_GET 42 /* Get debug packet function info */ +#define KCOM_M_WB_CLEANUP 51 /* Clean up for warmbooting */ +#define KCOM_M_CLOCK_CMD 52 /* Clock Commands */ + +#define KCOM_VERSION 12 /* Protocol version */ + +/* + * Message status codes + */ +#define KCOM_E_NONE 0 /* No errors */ +#define KCOM_E_PARAM 1 /* Invalid/unsupported parameter */ +#define KCOM_E_RESOURCE 2 /* Out of memory or other resource */ +#define KCOM_E_NOT_FOUND 3 /* Requested object not found */ + +typedef struct kcom_msg_hdr_s { + uint8 type; + uint8 opcode; + uint8 seqno; + uint8 status; + uint8 unit; + uint8 reserved; + uint16 id; +} kcom_msg_hdr_t; + +/* + * Object types + */ + +/* + * System network interface + * + * Network interface types: + * + * KCOM_NETIF_T_VLAN + * Transmits to this interface will go to ingress PIPE of switch + * CPU port using specified VLAN ID. Packet will be switched. + * + * KCOM_NETIF_T_PORT + * Transmits to this interface will go to unmodified to specified + * physical switch port. All switching logic is bypassed. + * + * KCOM_NETIF_T_META + * Transmits to this interface will be done using raw meta data + * as DMA descriptors. Currently used for RCPU mode only. + * + * Network interface flags: + * + * KCOM_NETIF_F_ADD_TAG + * Add VLAN tag to packets sent directly to physical port. + * + * KCOM_NETIF_F_RCPU_ENCAP + * Use RCPU encapsulation for packets that enter and exit this + * interface. + */ +#define KCOM_NETIF_T_VLAN 0 +#define KCOM_NETIF_T_PORT 1 +#define KCOM_NETIF_T_META 2 + +#define KCOM_NETIF_F_ADD_TAG (1U << 0) +#define KCOM_NETIF_F_RCPU_ENCAP (1U << 1) +/* If a netif has this flag, the packet sent to the netif can't be stripped tag or added tag */ +#define KCOM_NETIF_F_KEEP_RX_TAG (1U << 2) + +#define KCOM_NETIF_NAME_MAX 16 + +/* + * Max size of Sand System Headers + * For DNX, Module Header(20B) + PTCH(2B) + ITMH(5B) + * For DPP, PTCH(2B) + ITMH(4B) + */ +#define KCOM_NETIF_SYSTEM_HEADERS_SIZE_MAX 27 + +typedef struct kcom_netif_s { + uint16 id; + uint8 type; + uint8 flags; + uint32 cb_user_data; + uint8 port; + uint8 reserved; + uint16 vlan; + uint16 qnum; + uint8 macaddr[6]; + uint8 system_headers[KCOM_NETIF_SYSTEM_HEADERS_SIZE_MAX]; + uint8 system_headers_size; + char name[KCOM_NETIF_NAME_MAX]; + uint8 phys_port; +} kcom_netif_t; + +/* + * Packet filters + * + * Filters work like software TCAMs where a mask is applied to the + * source data, and the result is then compared to the filter data. + * + * Filters are checked in priority order with the lowest priority + * values being checked first (i.e. 0 is the highest priority). + * + * Filter types: + * + * KCOM_FILTER_T_RX_PKT + * Filter data and mask are applied to the Rx DMA control block + * as well as to the Rx packet contents. + * + * Destination types: + * + * KCOM_DEST_T_NULL + * Packet is dropped. + * + * KCOM_DEST_T_NETIF + * Packet is sent to network interface with ID . + * + * KCOM_DEST_T_API + * Packet is sent to Rx API through queue . + * + * KCOM_DEST_T_CB + * Packet destination is obtained from kernel call-back function. + * + * Filter flags: + * + * KCOM_FILTER_F_ANY_DATA + * When this flags is set the filter will match any packet on + * the associated unit. + * + * KCOM_FILTER_F_STRIP_TAG + * Strip VLAN tag before packet is sent to destination. + * This flag only applies to KCOM_DEST_T_NETIF. + * + */ +#define KCOM_FILTER_BYTES_MAX 256 +#define KCOM_FILTER_WORDS_MAX BYTES2WORDS(KCOM_FILTER_BYTES_MAX) + +#define KCOM_FILTER_T_RX_PKT 1 + +#define KCOM_DEST_T_NULL 0 +#define KCOM_DEST_T_NETIF 1 +#define KCOM_DEST_T_API 2 +#define KCOM_DEST_T_CB 3 + +#define KCOM_FILTER_F_ANY_DATA (1U << 0) +#define KCOM_FILTER_F_STRIP_TAG (1U << 1) + +#define KCOM_FILTER_DESC_MAX 32 + +typedef struct kcom_filter_s { + uint16 id; + uint8 type; + uint8 priority; + char desc[KCOM_FILTER_DESC_MAX]; + uint32 flags; + uint32 cb_user_data; + uint16 dest_type; + uint16 dest_id; + uint16 dest_proto; + uint16 mirror_type; + uint16 mirror_id; + uint16 mirror_proto; + uint16 oob_data_offset; + uint16 oob_data_size; + uint16 pkt_data_offset; + uint16 pkt_data_size; + union { + uint8 b[KCOM_FILTER_BYTES_MAX]; + uint32 w[KCOM_FILTER_WORDS_MAX]; + } data; + union { + uint8 b[KCOM_FILTER_BYTES_MAX]; + uint32 w[KCOM_FILTER_WORDS_MAX]; + } mask; + /** Mark to match source modid and modport */ + uint8 is_src_modport; + uint8 spa_unit; +} kcom_filter_t; + +/* + * DMA buffer information + * + * Cookie field is reserved use by application (32/64-bit pointer). + * + * For Tx operation the application will submit the start address of + * the Tx DCB chain which is queued for transfer by the kernel module. + * Once DMA is done a DMA event is returned to the application with an + * optional sequence number. + * + * For Rx operation the application will submit the start address of + * the Rx DCB chain which should be use for packet reception by the + * kernel module. Once DMA is done a DMA event is returned to the + * application with an optional sequence number. + * + * Cookie field is reserved use by application (32/64-bit pointer). + * + * Packet info types: + * + * KCOM_DMA_INFO_T_TX_DCB + * Data is physical start address of Tx DCB chain. + * + * KCOM_DMA_INFO_T_RX_DCB + * Data is physical start address of Rx DCB chain. + * + * Packet info flags: + * + * KCOM_DMA_INFO_F_TX_DONE + * This flag is set by the kernel module and means that one or more + * packets have been sent. + * + * KCOM_DMA_INFO_F_RX_DONE + * This flag is set by the kernel module and means that one or more + * Rx buffers contain valid packet data. + */ +#define KCOM_DMA_INFO_T_TX_DCB 1 +#define KCOM_DMA_INFO_T_RX_DCB 2 + +#define KCOM_DMA_INFO_F_TX_DONE (1U << 0) +#define KCOM_DMA_INFO_F_RX_DONE (1U << 1) + +typedef struct kcom_dma_info_s { + uint8 type; + uint8 cnt; + uint16 size; + uint16 chan; + uint16 flags; + union { + uint64 dcb_start; + struct { + uint32 tx; + uint32 rx; + } seqno; + } data; + union { + void *p; + uint8 b[8]; + } cookie; + } kcom_dma_info_t; + +/* Default channel configuration */ +#define KCOM_DMA_TX_CHAN 0 +#define KCOM_DMA_RX_CHAN 1 + + +#define KCOM_ETH_HW_T_RESET 1 +#define KCOM_ETH_HW_T_INIT 2 +#define KCOM_ETH_HW_T_OTHER 3 + +#define KCOM_ETH_HW_C_ALL 0xff + +#define KCOM_ETH_HW_RESET_F_TX (1U << 0) +#define KCOM_ETH_HW_RESET_F_RX (1U << 1) +#define KCOM_ETH_HW_RESET_F_TX_RECLAIM (1U << 2) +#define KCOM_ETH_HW_RESET_F_RX_RECLAIM (1U << 3) + +#define KCOM_ETH_HW_INIT_F_TX (1U << 0) +#define KCOM_ETH_HW_INIT_F_RX (1U << 1) +#define KCOM_ETH_HW_INIT_F_RX_FILL (1U << 2) + +#define KCOM_ETH_HW_OTHER_F_FIFO_LOOPBACK (1U << 0) +#define KCOM_ETH_HW_OTHER_F_INTERRUPT (1U << 1) + +typedef struct kcom_eth_hw_config_s { + uint8 type; + uint8 chan; + uint32 flags; + uint32 value; +} kcom_eth_hw_config_t; + +/* + * Message types + */ + +/* + * Request KCOM interface version of kernel module. + */ +typedef struct kcom_msg_version_s { + kcom_msg_hdr_t hdr; + uint32 version; + uint32 netif_max; + uint32 filter_max; +} kcom_msg_version_t; + +/* + * Request KCOM interface clock info. + */ +#define KSYNC_M_HW_INIT 0 +#define KSYNC_M_HW_DEINIT 1 +#define KSYNC_M_VERSION 2 +#define KSYNC_M_HW_TS_DISABLE 3 +#define KSYNC_M_MTP_TS_UPDATE_ENABLE 4 +#define KSYNC_M_MTP_TS_UPDATE_DISABLE 5 + +typedef struct kcom_clock_info_s { + uint8 cmd; + int32 data[8]; +} kcom_clock_info_t; + +/* + * Send literal string to/from kernel module. + * Mainly for debugging purposes. + */ +#define KCOM_MSG_STRING_MAX 128 + +typedef struct kcom_msg_string_s { + kcom_msg_hdr_t hdr; + uint32 len; + char val[KCOM_MSG_STRING_MAX]; +} kcom_msg_string_t; + +/* + * Indicate that eth hardware is about to be reset. Active + * DMA operations should be aborted and DMA and interrupts + * should be disabled. + */ +/* + * Indicate that eth hardware has been properly initialized + * for DMA operation to commence. + */ +typedef struct kcom_msg_eth_hw_config_s { + kcom_msg_hdr_t hdr; + kcom_eth_hw_config_t config; +} kcom_msg_eth_hw_config_t; + +/* + * Indicate that switch hardware is about to be reset. Active + * DMA operations should be aborted and DMA and interrupts + * should be disabled. + */ +typedef struct kcom_msg_hw_reset_s { + kcom_msg_hdr_t hdr; + uint32 channels; +} kcom_msg_hw_reset_t; + +/* + * Indicate that switch hardware has been properly initialized + * for DMA operation to commence. + */ +typedef struct kcom_msg_hw_init_s { + kcom_msg_hdr_t hdr; + uint8 cmic_type; + uint8 dcb_type; + uint8 dcb_size; + uint8 pkt_hdr_size; + uint32 dma_hi; + uint32 cdma_channels; + /* + * Information to parse Dune system headers + */ + uint32 ftmh_lb_key_ext_size; + uint32 ftmh_stacking_ext_size; + uint32 pph_base_size; + uint32 pph_lif_ext_size[8]; + uint32 udh_length_type[4]; + uint32 udh_size; + uint32 oamp_punted; + uint8 no_skip_udh_check; + uint8 system_headers_mode; + uint8 udh_enable; +} kcom_msg_hw_init_t; + +/* + * Release blocked IOCTL threads and clean up as necessary. + */ +typedef struct kcom_msg_detach_s { + kcom_msg_hdr_t hdr; + uint32 flags; +} kcom_msg_detach_t; + +/* + * Reprobe switch device. + */ +typedef struct kcom_msg_reprobe_s { + kcom_msg_hdr_t hdr; + uint32 flags; +} kcom_msg_reprobe_t; + +/* + * Enable/Disable debugging packet function. + */ +typedef struct kcom_msg_dbg_pkt_set_s { + kcom_msg_hdr_t hdr; + int enable; +} kcom_msg_dbg_pkt_set_t; + +/* + * Get debugging packet function info. + */ +typedef struct kcom_msg_dbg_pkt_get_s { + kcom_msg_hdr_t hdr; + int value; +} kcom_msg_dbg_pkt_get_t; + +/* + * Clean up warmboot-related resources. + */ +typedef struct kcom_msg_wb_cleanup_s { + kcom_msg_hdr_t hdr; + uint32 flags; +} kcom_msg_wb_cleanup_t; + +/* + * Create new system network interface. The network interface will + * be associated with the specified switch unit number. + * The interface id and name will be assigned by the kernel module. + */ +typedef struct kcom_msg_netif_create_s { + kcom_msg_hdr_t hdr; + kcom_netif_t netif; +} kcom_msg_netif_create_t; + +/* + * Destroy system network interface. + */ +typedef struct kcom_msg_netif_destroy_s { + kcom_msg_hdr_t hdr; +} kcom_msg_netif_destroy_t; + +/* + * Destroy system network interface. + */ +typedef struct kcom_msg_clock_s{ + kcom_msg_hdr_t hdr; + kcom_clock_info_t clock_info; +} kcom_msg_clock_cmd_t; + +/* + * Get list of currently defined system network interfaces. + */ +#ifndef KCOM_NETIF_MAX +#define KCOM_NETIF_MAX 128 +#endif + +typedef struct kcom_msg_netif_list_s { + kcom_msg_hdr_t hdr; + uint32 ifcnt; + uint16 id[KCOM_NETIF_MAX]; +} kcom_msg_netif_list_t; + +/* + * Get detailed network interface information. + */ +typedef struct kcom_msg_netif_get_s { + kcom_msg_hdr_t hdr; + kcom_netif_t netif; +} kcom_msg_netif_get_t; + +/* + * Create new packet filter. + * The filter id will be assigned by the kernel module. + */ +typedef struct kcom_msg_filter_create_s { + kcom_msg_hdr_t hdr; + kcom_filter_t filter; +} kcom_msg_filter_create_t; + +/* + * Destroy packet filter. + */ +typedef struct kcom_msg_filter_destroy_s { + kcom_msg_hdr_t hdr; +} kcom_msg_filter_destroy_t; + +/* + * Get list of currently defined packet filters. + */ +#ifndef KCOM_FILTER_MAX +#define KCOM_FILTER_MAX 128 +#endif + +typedef struct kcom_msg_filter_list_s { + kcom_msg_hdr_t hdr; + uint32 fcnt; + uint16 id[KCOM_FILTER_MAX]; +} kcom_msg_filter_list_t; + +/* + * Get detailed packet filter information. + */ +typedef struct kcom_msg_filter_get_s { + kcom_msg_hdr_t hdr; + kcom_filter_t filter; +} kcom_msg_filter_get_t; + +/* + * DMA info + */ +typedef struct kcom_msg_dma_info_s { + kcom_msg_hdr_t hdr; + kcom_dma_info_t dma_info; +} kcom_msg_dma_info_t; + +/* + * All messages (e.g. for generic receive) + */ +typedef union kcom_msg_s { + kcom_msg_hdr_t hdr; + kcom_msg_version_t version; + kcom_msg_string_t string; + kcom_msg_hw_reset_t hw_reset; + kcom_msg_hw_init_t hw_init; + kcom_msg_eth_hw_config_t eth_hw_config; + kcom_msg_detach_t detach; + kcom_msg_reprobe_t reprobe; + kcom_msg_netif_create_t netif_create; + kcom_msg_netif_destroy_t netif_destroy; + kcom_msg_netif_list_t netif_list; + kcom_msg_netif_get_t netif_get; + kcom_msg_filter_create_t filter_create; + kcom_msg_filter_destroy_t filter_destroy; + kcom_msg_filter_list_t filter_list; + kcom_msg_filter_get_t filter_get; + kcom_msg_dma_info_t dma_info; + kcom_msg_dbg_pkt_set_t dbg_pkt_set; + kcom_msg_dbg_pkt_get_t dbg_pkt_get; + kcom_msg_wb_cleanup_t wb_cleanup; + kcom_msg_clock_cmd_t clock_cmd; +} kcom_msg_t; + +/* + * KCOM communication channel vectors + * + * open + * Open KCOM channel. + * + * close + * Close KCOM channel. + * + * send + * Send KCOM message. If bufsz is non-zero, a synchronous send will be + * performed (if supported) and the function will return the number of + * bytes in the response. + * + * recv + * Receive KCOM message. This function is used t oreceive unsolicited + * messages from the kernel. If synchronous send is not supported, this + * function is also used to retrieve responses to command messages. + */ + +typedef struct kcom_chan_s { + void *(*open)(char *name); + int (*close)(void *handle); + int (*send)(void *handle, void *msg, unsigned int len, unsigned int bufsz); + int (*recv)(void *handle, void *msg, unsigned int bufsz); +} kcom_chan_t; + +#endif /* _KCOM_H */ diff --git a/platform/broadcom/saibcm-modules/include/sal/core/sync.h b/platform/broadcom/saibcm-modules/include/sal/core/sync.h new file mode 100644 index 000000000000..03fd2facc907 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/sal/core/sync.h @@ -0,0 +1,49 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: sync.h,v 1.1 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef _SAL_SYNC_H +#define _SAL_SYNC_H + +typedef struct sal_sem_s{ + char sal_opaque_type; +} *sal_sem_t; + +#define sal_sem_FOREVER (-1) +#define sal_sem_BINARY 1 +#define sal_sem_COUNTING 0 + +sal_sem_t sal_sem_create(char *desc, int binary, int initial_count); +void sal_sem_destroy(sal_sem_t b); +int sal_sem_take(sal_sem_t b, int usec); +int sal_sem_give(sal_sem_t b); + +#endif /* !_SAL_SYNC_H */ diff --git a/platform/broadcom/saibcm-modules/include/sal/core/thread.h b/platform/broadcom/saibcm-modules/include/sal/core/thread.h new file mode 100644 index 000000000000..86713d1e0742 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/sal/core/thread.h @@ -0,0 +1,41 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: thread.h,v 1.1 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef _SAL_THREAD_H +#define _SAL_THREAD_H + +#include + +void sal_usleep(uint32 usec); +void sal_udelay(uint32 usec); + +#endif /* !_SAL_THREAD_H */ diff --git a/platform/broadcom/saibcm-modules/include/sal/types.h b/platform/broadcom/saibcm-modules/include/sal/types.h new file mode 100644 index 000000000000..43d64dbcc6b9 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/sal/types.h @@ -0,0 +1,175 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: types.h,v 1.3 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * File: types.h + * Purpose: SAL type definitions + */ + +#ifndef _SAL_TYPES_H +#define _SAL_TYPES_H + +/* + * Define platform-independent types + */ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef DONT_CARE +#define DONT_CARE 0 +#endif + +#define VOL volatile + +/* + * 64-bit type + */ + +#ifdef LONGS_ARE_64BITS + +#define COMPILER_64BIT +#define COMPILER_UINT64 unsigned long +#define u64_H(v) (((uint32 *) &(v))[u64_MSW]) +#define u64_L(v) (((uint32 *) &(v))[u64_LSW]) + +#else /* !LONGS_ARE_64BITS */ + +#define COMPILER_64BIT +#define COMPILER_UINT64 unsigned long long +#define u64_H(v) (((uint32 *) &(v))[u64_MSW]) +#define u64_L(v) (((uint32 *) &(v))[u64_LSW]) + +#endif /* LONGS_ARE_64BITS */ + +/* + * Define unsigned and signed integers with guaranteed sizes. + * Adjust if your compiler uses different sizes for short or int. + */ + +typedef unsigned char uint8; /* 8-bit quantity */ +typedef unsigned short uint16; /* 16-bit quantity */ +typedef unsigned int uint32; /* 32-bit quantity */ +typedef COMPILER_UINT64 uint64; /* 64-bit quantity */ + +typedef signed char int8; /* 8-bit quantity */ +typedef signed short int16; /* 16-bit quantity */ +typedef signed int int32; /* 32-bit quantity */ + +#define BITS2BYTES(x) (((x) + 7) / 8) +#define BITS2WORDS(x) (((x) + 31) / 32) + +#define BYTES2BITS(x) ((x) * 8) +#define BYTES2WORDS(x) (((x) + 3) / 4) + +#define WORDS2BITS(x) ((x) * 32) +#define WORDS2BYTES(x) ((x) * 4) + +#define COUNTOF(ary) ((int) (sizeof (ary) / sizeof ((ary)[0]))) + +#ifdef PTRS_ARE_64BITS +typedef uint64 sal_vaddr_t; /* Virtual address (Host address) */ +typedef uint64 sal_paddr_t; /* Physical address (PCI address) */ +#define PTR_TO_INT(x) ((uint32)(((sal_vaddr_t)(x))&0xFFFFFFFF)) +#define PTR_HI_TO_INT(x) ((uint32)((((sal_vaddr_t)(x))>>32)&0xFFFFFFFF)) +#else +typedef uint32 sal_vaddr_t; /* Virtual address (Host address) */ +/* Physical address (PCI address) */ +#ifdef PHYS_ADDRS_ARE_64BITS +typedef uint64 sal_paddr_t; +#define PTR_HI_TO_INT(x) ((uint32)((((uint64)(x))>>32)&0xFFFFFFFF)) +#else +typedef uint32 sal_paddr_t; +#define PTR_HI_TO_INT(x) (0) +#endif +#define PTR_TO_INT(x) ((uint32)(x)) +#endif + +#define INT_TO_PTR(x) ((void *)((sal_vaddr_t)(x))) + +#define PTR_TO_UINTPTR(x) ((sal_vaddr_t)(x)) +#define UINTPTR_TO_PTR(x) ((void *)(x)) + +typedef union +{ + uint8 u8; + uint16 u16; + uint32 u32; + uint64 u64; + sal_paddr_t paddr; + sal_vaddr_t vaddr; + void *ptr; +} any_t; + +/* Device bus types */ +#define SAL_PCI_DEV_TYPE 0x00001 /* PCI device */ +#define SAL_SPI_DEV_TYPE 0x00002 /* SPI device */ +#define SAL_EB_DEV_TYPE 0x00004 /* EB device */ +#define SAL_ICS_DEV_TYPE 0x00008 /* ICS device */ +#define SAL_MII_DEV_TYPE 0x00010 /* MII device */ +#define SAL_RCPU_DEV_TYPE 0x00020 /* RCPU device */ +#define SAL_I2C_DEV_TYPE 0x00040 /* I2C device */ +#define SAL_AXI_DEV_TYPE 0x00080 /* AXI device */ +#define SAL_EMMI_DEV_TYPE 0x10000 /* EMMI device */ +#define SAL_COMPOSITE_DEV_TYPE 0x20000 /* Composite device, composed of sub-devices with buses */ +#define SAL_DEV_BUS_TYPE_MASK 0xf00ff /* Odd for historical reasons */ + +/* Device types */ +#define SAL_SWITCH_DEV_TYPE 0x00100 /* Switch device */ +#define SAL_ETHER_DEV_TYPE 0x00200 /* Ethernet device */ +#define SAL_CPU_DEV_TYPE 0x00400 /* CPU device */ +#define SAL_DEV_TYPE_MASK 0x00f00 + +/* Access types */ +#define SAL_DEV_BUS_RD_16BIT 0x01000 /* 16 bit reads on bus */ +#define SAL_DEV_BUS_WR_16BIT 0x02000 /* 16 bit writes on bus */ +#define SAL_DEV_BUS_ALT 0x04000 /* Alternate access */ +#define SAL_DEV_BUS_MSI 0x08000 /* Message-signaled interrupts */ +#define SAL_DEV_FLAG_MASK 0x0f000 + +/* BDE reserved mask (cannot be used by SAL) */ +#define SAL_DEV_BDE_MASK 0xff000000 + +/* Backward compatibility */ +#define SAL_ET_DEV_TYPE SAL_MII_DEV_TYPE + +/* Special access addresses */ +#define SAL_DEV_OP_EMMI_INIT 0x0fff1000 + +#endif /* !_SAL_TYPES_H */ diff --git a/platform/broadcom/saibcm-modules/include/sdk_config.h b/platform/broadcom/saibcm-modules/include/sdk_config.h new file mode 100644 index 000000000000..6ce7d77d52d0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/sdk_config.h @@ -0,0 +1,56 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: sdk_config.h,v 1.5 Broadcom SDK $ + * $Copyright: (c) 2006 Broadcom Corp. + * All Rights Reserved.$ + * + * + */ + +#ifndef __SDK_CONFIG_H__ +#define __SDK_CONFIG_H__ + +/* + * Include custom overrides + */ +#ifdef SDK_INCLUDE_CUSTOM_CONFIG +#include +#endif + + +/* + * Memory Barrier operation if required. + * Defaults to nothing. + */ +#ifndef SDK_CONFIG_MEMORY_BARRIER +#define SDK_CONFIG_MEMORY_BARRIER +#endif + + + +#endif /* __SDK_CONFIG_H__ */ diff --git a/platform/broadcom/saibcm-modules/include/soc/cmic.h b/platform/broadcom/saibcm-modules/include/soc/cmic.h new file mode 100644 index 000000000000..5bf6130237a2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/soc/cmic.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: cmic.h,v 1.1 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * File: cmic.h + * Purpose: Maps out structures used for CMIC operations and + * exports routines and constants. + */ + +#ifndef _SOC_CMIC_H +#define _SOC_CMIC_H + +/* IRQ Register (RO) */ +#define CMIC_IRQ_STAT 0x00000144 + +/* IRQ Mask Registers (R/W) */ +#define CMIC_IRQ_MASK 0x00000148 +#define CMIC_IRQ_MASK_1 0x0000006C +#define CMIC_IRQ_MASK_2 0x00000070 + +#endif /* !_SOC_CMIC_H */ diff --git a/platform/broadcom/saibcm-modules/include/soc/devids.h b/platform/broadcom/saibcm-modules/include/soc/devids.h new file mode 100644 index 000000000000..89fabac44537 --- /dev/null +++ b/platform/broadcom/saibcm-modules/include/soc/devids.h @@ -0,0 +1,2011 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * Copyright: (c) 2020 Broadcom. + * All Rights Reserved. + */ + +#ifndef _SOC_DEVIDS_H +#define _SOC_DEVIDS_H + + +#define BROADCOM_VENDOR_ID 0x14e4 + +#define BCM5690_DEVICE_ID 0x5690 +#define BCM5690_A0_REV_ID 1 +#define BCM5690_A1_REV_ID 2 +#define BCM5690_A2_REV_ID 3 + +#define BCM5691_DEVICE_ID 0x5691 +#define BCM5691_A0_REV_ID 1 +#define BCM5691_A1_REV_ID 2 +#define BCM5691_A2_REV_ID 3 + +#define BCM5692_DEVICE_ID 0x5692 +#define BCM5692_A0_REV_ID 1 +#define BCM5692_A1_REV_ID 2 +#define BCM5692_A2_REV_ID 3 + +#define BCM5693_DEVICE_ID 0x5693 +#define BCM5693_A0_REV_ID 1 +#define BCM5693_A1_REV_ID 2 +#define BCM5693_A2_REV_ID 3 + +#define BCM5695_DEVICE_ID 0x5695 +#define BCM5695_A0_REV_ID 1 +#define BCM5695_A1_REV_ID 2 +#define BCM5695_B0_REV_ID 0x11 + +#define BCM5696_DEVICE_ID 0x5696 +#define BCM5696_A0_REV_ID 1 +#define BCM5696_A1_REV_ID 2 +#define BCM5696_B0_REV_ID 0x11 + +#define BCM5697_DEVICE_ID 0x5697 +#define BCM5697_A0_REV_ID 1 +#define BCM5697_A1_REV_ID 2 +#define BCM5697_B0_REV_ID 0x11 + +#define BCM5698_DEVICE_ID 0x5698 +#define BCM5698_A0_REV_ID 1 +#define BCM5698_A1_REV_ID 2 +#define BCM5698_B0_REV_ID 0x11 + +#define BCM5670_DEVICE_ID 0x5670 +#define BCM5670_A0_REV_ID 1 +#define BCM5670_A1_REV_ID 2 + +#define BCM5671_DEVICE_ID 0x5671 +#define BCM5671_A0_REV_ID 1 +#define BCM5671_A1_REV_ID 2 +#define BCM5671_A2_REV_ID 3 + +#define BCM5675_DEVICE_ID 0x5675 +#define BCM5675_A0_REV_ID 1 +#define BCM5675_A1_REV_ID 2 + +#define BCM5676_DEVICE_ID 0x5676 +#define BCM5676_A0_REV_ID 1 +#define BCM5676_A1_REV_ID 2 + +#define BCM5673_DEVICE_ID 0x5673 +#define BCM5673_A0_REV_ID 1 +#define BCM5673_A1_REV_ID 2 +#define BCM5673_A2_REV_ID 3 + +#define BCM5674_DEVICE_ID 0x5674 +#define BCM5674_A0_REV_ID 1 + +#define BCM56100_DEVICE_ID 0xb100 +#define BCM56100_A0_REV_ID 1 +#define BCM56100_A1_REV_ID 2 +#define BCM56101_DEVICE_ID 0xb101 +#define BCM56101_A0_REV_ID 1 +#define BCM56101_A1_REV_ID 2 +#define BCM56102_DEVICE_ID 0xb102 +#define BCM56102_A0_REV_ID 1 +#define BCM56102_A1_REV_ID 2 +#define BCM56105_DEVICE_ID 0xb105 +#define BCM56105_A0_REV_ID 1 +#define BCM56105_A1_REV_ID 2 +#define BCM56106_DEVICE_ID 0xb106 +#define BCM56106_A0_REV_ID 1 +#define BCM56106_A1_REV_ID 2 +#define BCM56107_DEVICE_ID 0xb107 +#define BCM56107_A0_REV_ID 1 +#define BCM56107_A1_REV_ID 2 + +#define BCM56110_DEVICE_ID 0xb110 +#define BCM56110_A0_REV_ID 1 +#define BCM56111_DEVICE_ID 0xb111 +#define BCM56111_A0_REV_ID 1 +#define BCM56112_DEVICE_ID 0xb112 +#define BCM56112_A0_REV_ID 1 +#define BCM56115_DEVICE_ID 0xb115 +#define BCM56115_A0_REV_ID 1 +#define BCM56116_DEVICE_ID 0xb116 +#define BCM56116_A0_REV_ID 1 +#define BCM56117_DEVICE_ID 0xb117 +#define BCM56117_A0_REV_ID 1 + +#define BCM56300_DEVICE_ID 0xb300 +#define BCM56300_A0_REV_ID 1 +#define BCM56300_A1_REV_ID 2 +#define BCM56300_B0_REV_ID 0x11 +#define BCM56300_B1_REV_ID 0x12 +#define BCM56301_DEVICE_ID 0xb301 +#define BCM56301_A0_REV_ID 1 +#define BCM56301_A1_REV_ID 2 +#define BCM56301_B0_REV_ID 0x11 +#define BCM56301_B1_REV_ID 0x12 +#define BCM56302_DEVICE_ID 0xb302 +#define BCM56302_A0_REV_ID 1 +#define BCM56302_A1_REV_ID 2 +#define BCM56302_B0_REV_ID 0x11 +#define BCM56302_B1_REV_ID 0x12 +#define BCM56303_DEVICE_ID 0xb303 +#define BCM56303_A1_REV_ID 2 +#define BCM56303_A0_REV_ID 1 +#define BCM56303_B0_REV_ID 0x11 +#define BCM56303_B1_REV_ID 0x12 +#define BCM56304_DEVICE_ID 0xb304 +#define BCM56304_A0_REV_ID 1 +#define BCM56304_A1_REV_ID 2 +#define BCM56304_B0_REV_ID 0x11 +#define BCM56304_B1_REV_ID 0x12 +#define BCM56404_DEVICE_ID 0xb404 +#define BCM56404_A0_REV_ID 1 +#define BCM56404_A1_REV_ID 2 +#define BCM56305_DEVICE_ID 0xb305 +#define BCM56305_A0_REV_ID 1 +#define BCM56305_A1_REV_ID 2 +#define BCM56305_B0_REV_ID 0x11 +#define BCM56305_B1_REV_ID 0x12 +#define BCM56306_DEVICE_ID 0xb306 +#define BCM56306_A0_REV_ID 1 +#define BCM56306_A1_REV_ID 2 +#define BCM56306_B0_REV_ID 0x11 +#define BCM56306_B1_REV_ID 0x12 +#define BCM56307_DEVICE_ID 0xb307 +#define BCM56307_A0_REV_ID 1 +#define BCM56307_A1_REV_ID 2 +#define BCM56307_B0_REV_ID 0x11 +#define BCM56307_B1_REV_ID 0x12 +#define BCM56308_DEVICE_ID 0xb308 +#define BCM56308_A0_REV_ID 1 +#define BCM56308_A1_REV_ID 2 +#define BCM56308_B0_REV_ID 0x11 +#define BCM56308_B1_REV_ID 0x12 +#define BCM56309_DEVICE_ID 0xb309 +#define BCM56309_A0_REV_ID 1 +#define BCM56309_A1_REV_ID 2 +#define BCM56309_B0_REV_ID 0x11 +#define BCM56309_B1_REV_ID 0x12 + +#define BCM56310_DEVICE_ID 0xb310 +#define BCM56310_A0_REV_ID 1 +#define BCM56311_DEVICE_ID 0xb311 +#define BCM56311_A0_REV_ID 1 +#define BCM56312_DEVICE_ID 0xb312 +#define BCM56312_A0_REV_ID 1 +#define BCM56313_DEVICE_ID 0xb313 +#define BCM56313_A0_REV_ID 1 +#define BCM56314_DEVICE_ID 0xb314 +#define BCM56314_A0_REV_ID 1 +#define BCM56315_DEVICE_ID 0xb315 +#define BCM56315_A0_REV_ID 1 +#define BCM56316_DEVICE_ID 0xb316 +#define BCM56316_A0_REV_ID 1 +#define BCM56317_DEVICE_ID 0xb317 +#define BCM56317_A0_REV_ID 1 +#define BCM56318_DEVICE_ID 0xb318 +#define BCM56318_A0_REV_ID 1 +#define BCM56319_DEVICE_ID 0xb319 +#define BCM56319_A0_REV_ID 1 + +#ifndef EXCLUDE_BCM56324 +#define BCM56322_DEVICE_ID 0xb322 +#define BCM56322_A0_REV_ID 1 +#define BCM56324_DEVICE_ID 0xb324 +#define BCM56324_A0_REV_ID 1 +#endif + +#define BCM53300_DEVICE_ID 0xb006 +#define BCM53300_A0_REV_ID 0x11 +#define BCM53300_A1_REV_ID 0x12 +#define BCM53301_DEVICE_ID 0xb206 +#define BCM53301_A0_REV_ID 0x11 +#define BCM53301_A1_REV_ID 0x12 +#define BCM53302_DEVICE_ID 0xb008 +#define BCM53302_A0_REV_ID 0x11 +#define BCM53302_A1_REV_ID 0x12 + +#define BCM56500_DEVICE_ID 0xb500 +#define BCM56500_A0_REV_ID 1 +#define BCM56500_A1_REV_ID 2 +#define BCM56500_B0_REV_ID 0x11 +#define BCM56500_B1_REV_ID 0x12 +#define BCM56500_B2_REV_ID 0x13 +#define BCM56501_DEVICE_ID 0xb501 +#define BCM56501_A0_REV_ID 1 +#define BCM56501_A1_REV_ID 2 +#define BCM56501_B0_REV_ID 0x11 +#define BCM56501_B1_REV_ID 0x12 +#define BCM56501_B2_REV_ID 0x13 +#define BCM56502_DEVICE_ID 0xb502 +#define BCM56502_A0_REV_ID 1 +#define BCM56502_A1_REV_ID 2 +#define BCM56502_B0_REV_ID 0x11 +#define BCM56502_B1_REV_ID 0x12 +#define BCM56502_B2_REV_ID 0x13 +#define BCM56503_DEVICE_ID 0xb503 +#define BCM56503_A0_REV_ID 1 +#define BCM56503_A1_REV_ID 2 +#define BCM56503_B0_REV_ID 0x11 +#define BCM56503_B1_REV_ID 0x12 +#define BCM56503_B2_REV_ID 0x13 +#define BCM56504_DEVICE_ID 0xb504 +#define BCM56504_A0_REV_ID 1 +#define BCM56504_A1_REV_ID 2 +#define BCM56504_B0_REV_ID 0x11 +#define BCM56504_B1_REV_ID 0x12 +#define BCM56504_B2_REV_ID 0x13 +#define BCM56505_DEVICE_ID 0xb505 +#define BCM56505_A0_REV_ID 1 +#define BCM56505_A1_REV_ID 2 +#define BCM56505_B0_REV_ID 0x11 +#define BCM56505_B1_REV_ID 0x12 +#define BCM56505_B2_REV_ID 0x13 +#define BCM56506_DEVICE_ID 0xb506 +#define BCM56506_A0_REV_ID 1 +#define BCM56506_A1_REV_ID 2 +#define BCM56506_B0_REV_ID 0x11 +#define BCM56506_B1_REV_ID 0x12 +#define BCM56506_B2_REV_ID 0x13 +#define BCM56507_DEVICE_ID 0xb507 +#define BCM56507_A0_REV_ID 1 +#define BCM56507_A1_REV_ID 2 +#define BCM56507_B0_REV_ID 0x11 +#define BCM56507_B1_REV_ID 0x12 +#define BCM56507_B2_REV_ID 0x13 +#define BCM56508_DEVICE_ID 0xb508 +#define BCM56508_A0_REV_ID 1 +#define BCM56508_A1_REV_ID 2 +#define BCM56508_B0_REV_ID 0x11 +#define BCM56508_B1_REV_ID 0x12 +#define BCM56508_B2_REV_ID 0x13 +#define BCM56509_DEVICE_ID 0xb509 +#define BCM56509_A0_REV_ID 1 +#define BCM56509_A1_REV_ID 2 +#define BCM56509_B0_REV_ID 0x11 +#define BCM56509_B1_REV_ID 0x12 +#define BCM56509_B2_REV_ID 0x13 + +#define BCM56600_DEVICE_ID 0xb600 +#define BCM56600_A0_REV_ID 1 +#define BCM56600_B0_REV_ID 0x11 +#define BCM56600_C0_REV_ID 0x21 +#define BCM56601_DEVICE_ID 0xb601 +#define BCM56601_A0_REV_ID 1 +#define BCM56601_B0_REV_ID 0x11 +#define BCM56601_C0_REV_ID 0x21 +#define BCM56602_DEVICE_ID 0xb602 +#define BCM56602_A0_REV_ID 1 +#define BCM56602_B0_REV_ID 0x11 +#define BCM56602_C0_REV_ID 0x21 +#define BCM56603_DEVICE_ID 0xb603 +#define BCM56603_A0_REV_ID 1 +#define BCM56603_B0_REV_ID 0x11 +#define BCM56603_C0_REV_ID 0x21 +#define BCM56605_DEVICE_ID 0xb605 +#define BCM56605_A0_REV_ID 1 +#define BCM56605_B0_REV_ID 0x11 +#define BCM56605_C0_REV_ID 0x21 +#define BCM56606_DEVICE_ID 0xb606 +#define BCM56606_A0_REV_ID 1 +#define BCM56606_B0_REV_ID 0x11 +#define BCM56606_C0_REV_ID 0x21 +#define BCM56607_DEVICE_ID 0xb607 +#define BCM56607_A0_REV_ID 1 +#define BCM56607_B0_REV_ID 0x11 +#define BCM56607_C0_REV_ID 0x21 +#define BCM56608_DEVICE_ID 0xb608 +#define BCM56608_A0_REV_ID 1 +#define BCM56608_B0_REV_ID 0x11 +#define BCM56608_C0_REV_ID 0x21 + +#define BCM56580_DEVICE_ID 0xb580 +#define BCM56580_A0_REV_ID 1 + +#define BCM56700_DEVICE_ID 0xb700 +#define BCM56700_A0_REV_ID 1 +#define BCM56701_DEVICE_ID 0xb701 +#define BCM56701_A0_REV_ID 1 + +#define BCM56800_DEVICE_ID 0xb800 +#define BCM56800_A0_REV_ID 1 +#define BCM56801_DEVICE_ID 0xb801 +#define BCM56801_A0_REV_ID 1 +#define BCM56802_DEVICE_ID 0xb802 +#define BCM56802_A0_REV_ID 1 +#define BCM56803_DEVICE_ID 0xb803 +#define BCM56803_A0_REV_ID 1 + +#define BCM56224_DEVICE_ID 0xb224 +#define BCM56224_A0_REV_ID 1 +#define BCM56224_B0_REV_ID 0x11 +#define BCM56225_DEVICE_ID 0xb225 +#define BCM56225_A0_REV_ID 1 +#define BCM56225_B0_REV_ID 0x11 +#define BCM56226_DEVICE_ID 0xb226 +#define BCM56226_A0_REV_ID 1 +#define BCM56226_B0_REV_ID 0x11 +#define BCM56227_DEVICE_ID 0xb227 +#define BCM56227_A0_REV_ID 1 +#define BCM56227_B0_REV_ID 0x11 +#define BCM56228_DEVICE_ID 0xb228 +#define BCM56228_A0_REV_ID 1 +#define BCM56228_B0_REV_ID 0x11 +#define BCM56229_DEVICE_ID 0xb229 +#define BCM56229_A0_REV_ID 1 +#define BCM56229_B0_REV_ID 0x11 +#define BCM56024_DEVICE_ID 0xb024 +#define BCM56024_A0_REV_ID 1 +#define BCM56024_B0_REV_ID 0x11 +#define BCM56025_DEVICE_ID 0xb025 +#define BCM56025_A0_REV_ID 1 +#define BCM56025_B0_REV_ID 0x11 +#define BCM53724_DEVICE_ID 0xc724 +#define BCM53724_A0_REV_ID 1 +#define BCM53724_B0_REV_ID 0x11 +#define BCM53726_DEVICE_ID 0xc726 +#define BCM53726_A0_REV_ID 1 +#define BCM53726_B0_REV_ID 0x11 + +#define BCM53312_DEVICE_ID 0xc312 +#define BCM53312_A0_REV_ID 1 +#define BCM53312_B0_REV_ID 0x11 +#define BCM53313_DEVICE_ID 0xc313 +#define BCM53313_A0_REV_ID 1 +#define BCM53313_B0_REV_ID 0x11 +#define BCM53314_DEVICE_ID 0xc314 +#define BCM53314_A0_REV_ID 1 +#define BCM53314_B0_REV_ID 0x11 + +#define BCM53322_DEVICE_ID 0xc322 +#define BCM53322_A0_REV_ID 1 +#define BCM53323_DEVICE_ID 0xc323 +#define BCM53323_A0_REV_ID 1 +#define BCM53324_DEVICE_ID 0xc324 +#define BCM53324_A0_REV_ID 1 + + +#define BCM56218_DEVICE_ID 0xB218 +#define BCM56218_A0_REV_ID 1 +#define BCM56218_A1_REV_ID 2 +#define BCM56218_A2_REV_ID 3 +#define BCM56218X_DEVICE_ID 0xc710 +#define BCM56218X_A0_REV_ID 1 +#define BCM56218X_A1_REV_ID 2 +#define BCM56218X_A2_REV_ID 3 +#define BCM56219_DEVICE_ID 0xB219 +#define BCM56219_A0_REV_ID 1 +#define BCM56219_A1_REV_ID 2 +#define BCM56219_A2_REV_ID 3 +#define BCM56218R_DEVICE_ID 0xB21A +#define BCM56218R_A0_REV_ID 1 +#define BCM56218R_A1_REV_ID 2 +#define BCM56218R_A2_REV_ID 3 +#define BCM56219R_DEVICE_ID 0xB21B +#define BCM56219R_A0_REV_ID 1 +#define BCM56219R_A1_REV_ID 2 +#define BCM56219R_A2_REV_ID 3 +#define BCM56214_DEVICE_ID 0xB214 +#define BCM56214_A0_REV_ID 1 +#define BCM56214_A1_REV_ID 2 +#define BCM56214_A2_REV_ID 3 +#define BCM56215_DEVICE_ID 0xB215 +#define BCM56215_A0_REV_ID 1 +#define BCM56215_A1_REV_ID 2 +#define BCM56215_A2_REV_ID 3 +#define BCM56214R_DEVICE_ID 0xB21C +#define BCM56214R_A0_REV_ID 1 +#define BCM56214R_A1_REV_ID 2 +#define BCM56214R_A2_REV_ID 3 +#define BCM56215R_DEVICE_ID 0xB21D +#define BCM56215R_A0_REV_ID 1 +#define BCM56215R_A1_REV_ID 2 +#define BCM56215R_A2_REV_ID 3 +#define BCM56216_DEVICE_ID 0xB216 +#define BCM56216_A0_REV_ID 1 +#define BCM56216_A1_REV_ID 2 +#define BCM56216_A2_REV_ID 3 +#define BCM56217_DEVICE_ID 0xB217 +#define BCM56217_A0_REV_ID 1 +#define BCM56217_A1_REV_ID 2 +#define BCM56217_A2_REV_ID 3 +#define BCM56212_DEVICE_ID 0xB212 +#define BCM56212_A0_REV_ID 1 +#define BCM56212_A1_REV_ID 2 +#define BCM56212_A2_REV_ID 3 +#define BCM56213_DEVICE_ID 0xB213 +#define BCM56213_A0_REV_ID 1 +#define BCM56213_A1_REV_ID 2 +#define BCM56213_A2_REV_ID 3 +#define BCM53718_DEVICE_ID 0xC71A +#define BCM53718_A0_REV_ID 1 +#define BCM53718_A1_REV_ID 2 +#define BCM53718_A2_REV_ID 3 +#define BCM53714_DEVICE_ID 0xC71B +#define BCM53714_A0_REV_ID 1 +#define BCM53714_A1_REV_ID 2 +#define BCM53714_A2_REV_ID 3 +#define BCM53716_DEVICE_ID 0xC716 +#define BCM53716_A0_REV_ID 1 +#define BCM53716_A1_REV_ID 2 +#define BCM53716_A2_REV_ID 3 +#define BCM56018_DEVICE_ID 0xB018 +#define BCM56018_A0_REV_ID 1 +#define BCM56018_A1_REV_ID 2 +#define BCM56018_A2_REV_ID 3 +#define BCM56014_DEVICE_ID 0xB014 +#define BCM56014_A0_REV_ID 1 +#define BCM56014_A1_REV_ID 2 +#define BCM56014_A2_REV_ID 3 + +#define BCM56510_DEVICE_ID 0xb510 +#define BCM56510_A0_REV_ID 1 +#define BCM56511_DEVICE_ID 0xb511 +#define BCM56511_A0_REV_ID 1 +#define BCM56512_DEVICE_ID 0xb512 +#define BCM56512_A0_REV_ID 1 +#define BCM56513_DEVICE_ID 0xb513 +#define BCM56513_A0_REV_ID 1 +#define BCM56514_DEVICE_ID 0xb514 +#define BCM56514_A0_REV_ID 1 +#define BCM56516_DEVICE_ID 0xb516 +#define BCM56516_A0_REV_ID 1 +#define BCM56517_DEVICE_ID 0xb517 +#define BCM56517_A0_REV_ID 1 +#define BCM56518_DEVICE_ID 0xb518 +#define BCM56518_A0_REV_ID 1 +#define BCM56519_DEVICE_ID 0xb519 +#define BCM56519_A0_REV_ID 1 + +#define BCM56620_DEVICE_ID 0xb620 +#define BCM56620_A0_REV_ID 1 +#define BCM56620_A1_REV_ID 2 +#define BCM56620_B0_REV_ID 0x11 +#define BCM56620_B1_REV_ID 0x12 +#define BCM56620_B2_REV_ID 0x13 +#define BCM56624_DEVICE_ID 0xb624 +#define BCM56624_A0_REV_ID 1 +#define BCM56624_A1_REV_ID 2 +#define BCM56624_B0_REV_ID 0x11 +#define BCM56624_B1_REV_ID 0x12 +#define BCM56624_B2_REV_ID 0x13 +#define BCM56626_DEVICE_ID 0xb626 +#define BCM56626_A0_REV_ID 1 +#define BCM56626_A1_REV_ID 2 +#define BCM56626_B0_REV_ID 0x11 +#define BCM56626_B1_REV_ID 0x12 +#define BCM56626_B2_REV_ID 0x13 +#define BCM56628_DEVICE_ID 0xb628 +#define BCM56628_A0_REV_ID 1 +#define BCM56628_A1_REV_ID 2 +#define BCM56628_B0_REV_ID 0x11 +#define BCM56628_B1_REV_ID 0x12 +#define BCM56628_B2_REV_ID 0x13 +#define BCM56629_DEVICE_ID 0xb629 +#define BCM56629_A0_REV_ID 1 +#define BCM56629_A1_REV_ID 2 +#define BCM56629_B0_REV_ID 0x11 +#define BCM56629_B1_REV_ID 0x12 +#define BCM56629_B2_REV_ID 0x13 + +#define BCM56680_DEVICE_ID 0xb680 +#define BCM56680_A0_REV_ID 1 +#define BCM56680_A1_REV_ID 2 +#define BCM56680_B0_REV_ID 0x11 +#define BCM56680_B1_REV_ID 0x12 +#define BCM56680_B2_REV_ID 0x13 +#define BCM56684_DEVICE_ID 0xb684 +#define BCM56684_A0_REV_ID 1 +#define BCM56684_A1_REV_ID 2 +#define BCM56684_B0_REV_ID 0x11 +#define BCM56684_B1_REV_ID 0x12 +#define BCM56684_B2_REV_ID 0x13 +#define BCM56686_DEVICE_ID 0xb686 +#define BCM56686_B0_REV_ID 0x11 +#define BCM56686_B1_REV_ID 0x12 +#define BCM56686_B2_REV_ID 0x13 + +#define BCM56820_DEVICE_ID 0xb820 +#define BCM56820_A0_REV_ID 1 +#define BCM56820_B0_REV_ID 0x11 +#define BCM56821_DEVICE_ID 0xb821 +#define BCM56821_A0_REV_ID 1 +#define BCM56821_B0_REV_ID 0x11 +#define BCM56822_DEVICE_ID 0xb822 +#define BCM56822_A0_REV_ID 1 +#define BCM56822_B0_REV_ID 0x11 +#define BCM56823_DEVICE_ID 0xb823 +#define BCM56823_A0_REV_ID 1 +#define BCM56823_B0_REV_ID 0x11 +#define BCM56825_DEVICE_ID 0xb825 +#define BCM56825_B0_REV_ID 0x11 + +#define BCM56720_DEVICE_ID 0xb720 +#define BCM56720_A0_REV_ID 1 +#define BCM56720_B0_REV_ID 0x11 +#define BCM56721_DEVICE_ID 0xb721 +#define BCM56721_A0_REV_ID 1 +#define BCM56721_B0_REV_ID 0x11 + +#define BCM56725_DEVICE_ID 0xb725 +#define BCM56725_A0_REV_ID 1 +#define BCM56725_B0_REV_ID 0x11 + +#define BCM56630_DEVICE_ID 0xb630 +#define BCM56630_A0_REV_ID 1 +#define BCM56630_B0_REV_ID 0x11 +#define BCM56634_DEVICE_ID 0xb634 +#define BCM56634_A0_REV_ID 1 +#define BCM56634_B0_REV_ID 0x11 +#define BCM56636_DEVICE_ID 0xb636 +#define BCM56636_A0_REV_ID 1 +#define BCM56636_B0_REV_ID 0x11 +#define BCM56638_DEVICE_ID 0xb638 +#define BCM56638_A0_REV_ID 1 +#define BCM56638_B0_REV_ID 0x11 +#define BCM56639_DEVICE_ID 0xb639 +#define BCM56639_A0_REV_ID 1 +#define BCM56639_B0_REV_ID 0x11 + +#define BCM56685_DEVICE_ID 0xb685 +#define BCM56685_A0_REV_ID 1 +#define BCM56685_B0_REV_ID 0x11 +#define BCM56689_DEVICE_ID 0xb689 +#define BCM56689_A0_REV_ID 1 +#define BCM56689_B0_REV_ID 0x11 + +#define BCM56520_DEVICE_ID 0xb520 +#define BCM56520_A0_REV_ID 1 +#define BCM56520_B0_REV_ID 0x11 +#define BCM56521_DEVICE_ID 0xb521 +#define BCM56521_A0_REV_ID 1 +#define BCM56521_B0_REV_ID 0x11 +#define BCM56522_DEVICE_ID 0xb522 +#define BCM56522_A0_REV_ID 1 +#define BCM56522_B0_REV_ID 0x11 +#define BCM56524_DEVICE_ID 0xb524 +#define BCM56524_A0_REV_ID 1 +#define BCM56524_B0_REV_ID 0x11 +#define BCM56526_DEVICE_ID 0xb526 +#define BCM56526_A0_REV_ID 1 +#define BCM56526_B0_REV_ID 0x11 + +#define BCM56534_DEVICE_ID 0xb534 +#define BCM56534_B0_REV_ID 0x11 +#define BCM56538_DEVICE_ID 0xb538 +#define BCM56538_B0_REV_ID 0x11 + +#define BCM56331_DEVICE_ID 0xb331 +#define BCM56331_A0_REV_ID 1 +#define BCM56331_B0_REV_ID 0x11 +#define BCM56331_B1_REV_ID 0x12 +#define BCM56333_DEVICE_ID 0xb333 +#define BCM56333_A0_REV_ID 1 +#define BCM56333_B0_REV_ID 0x11 +#define BCM56333_B1_REV_ID 0x12 +#define BCM56334_DEVICE_ID 0xb334 +#define BCM56334_A0_REV_ID 1 +#define BCM56334_B0_REV_ID 0x11 +#define BCM56334_B1_REV_ID 0x12 +#define BCM56338_DEVICE_ID 0xb338 +#define BCM56338_A0_REV_ID 1 +#define BCM56338_B0_REV_ID 0x11 +#define BCM56338_B1_REV_ID 0x12 + +#define BCM56320_DEVICE_ID 0xb320 +#define BCM56320_A0_REV_ID 1 +#define BCM56320_B0_REV_ID 0x11 +#define BCM56320_B1_REV_ID 0x12 +#define BCM56321_DEVICE_ID 0xb321 +#define BCM56321_A0_REV_ID 1 +#define BCM56321_B0_REV_ID 0x11 +#define BCM56321_B1_REV_ID 0x12 + + +#define BCM56548H_DEVICE_ID 0xB54A +#define BCM56548H_A0_REV_ID 1 +#define BCM56548_DEVICE_ID 0xb548 +#define BCM56548_A0_REV_ID 1 +#define BCM56547_DEVICE_ID 0xb547 +#define BCM56547_A0_REV_ID 1 + +#define BCM56346_DEVICE_ID 0xb346 +#define BCM56346_A0_REV_ID 1 +#define BCM56345_DEVICE_ID 0xb345 +#define BCM56345_A0_REV_ID 1 +#define BCM56344_DEVICE_ID 0xb344 +#define BCM56344_A0_REV_ID 1 +#define BCM56342_DEVICE_ID 0xb342 +#define BCM56342_A0_REV_ID 1 +#define BCM56340_DEVICE_ID 0xb340 +#define BCM56340_A0_REV_ID 1 + +#define BCM56049_DEVICE_ID 0xb049 +#define BCM56049_A0_REV_ID 1 +#define BCM56048_DEVICE_ID 0xb048 +#define BCM56048_A0_REV_ID 1 +#define BCM56047_DEVICE_ID 0xb047 +#define BCM56047_A0_REV_ID 1 + +#define BCM56042_DEVICE_ID 0xb042 +#define BCM56042_A0_REV_ID 1 +#define BCM56041_DEVICE_ID 0xb041 +#define BCM56041_A0_REV_ID 1 +#define BCM56040_DEVICE_ID 0xb040 +#define BCM56040_A0_REV_ID 1 + +#define BCM56132_DEVICE_ID 0xb132 +#define BCM56132_A0_REV_ID 1 +#define BCM56132_B0_REV_ID 0x11 +#define BCM56132_B1_REV_ID 0x12 +#define BCM56134_DEVICE_ID 0xb134 +#define BCM56134_A0_REV_ID 1 +#define BCM56134_B0_REV_ID 0x11 +#define BCM56134_B1_REV_ID 0x12 + +#define BCM56230_DEVICE_ID 0xb230 +#define BCM56230_B1_REV_ID 0x12 +#define BCM56231_DEVICE_ID 0xb231 +#define BCM56231_B1_REV_ID 0x12 + +#define BCM56140_DEVICE_ID 0xb140 +#define BCM56140_A0_REV_ID 1 +#define BCM56142_DEVICE_ID 0xb142 +#define BCM56142_A0_REV_ID 1 +#define BCM56143_DEVICE_ID 0xb143 +#define BCM56143_A0_REV_ID 1 +#define BCM56144_DEVICE_ID 0xb144 +#define BCM56144_A0_REV_ID 1 +#define BCM56146_DEVICE_ID 0xb146 +#define BCM56146_A0_REV_ID 1 +#define BCM56147_DEVICE_ID 0xb147 +#define BCM56147_A0_REV_ID 1 +#define BCM56149_DEVICE_ID 0xb149 +#define BCM56149_A0_REV_ID 1 + +#define BCM56840_DEVICE_ID 0xb840 +#define BCM56840_A0_REV_ID 1 +#define BCM56840_A1_REV_ID 2 +#define BCM56840_A2_REV_ID 3 +#define BCM56840_A3_REV_ID 4 +#define BCM56840_A4_REV_ID 5 +#define BCM56840_B0_REV_ID 0x11 +#define BCM56840_B1_REV_ID 0x12 +#define BCM56841_DEVICE_ID 0xb841 +#define BCM56841_A0_REV_ID 1 +#define BCM56841_A1_REV_ID 2 +#define BCM56841_A2_REV_ID 3 +#define BCM56841_A3_REV_ID 4 +#define BCM56841_A4_REV_ID 5 +#define BCM56841_B0_REV_ID 0x11 +#define BCM56841_B1_REV_ID 0x12 +#define BCM56843_DEVICE_ID 0xb843 +#define BCM56843_A0_REV_ID 1 +#define BCM56843_A1_REV_ID 2 +#define BCM56843_A2_REV_ID 3 +#define BCM56843_A3_REV_ID 4 +#define BCM56843_A4_REV_ID 5 +#define BCM56843_B0_REV_ID 0x11 +#define BCM56843_B1_REV_ID 0x12 +#define BCM56845_DEVICE_ID 0xb845 +#define BCM56845_A0_REV_ID 1 +#define BCM56845_A1_REV_ID 2 +#define BCM56845_A2_REV_ID 3 +#define BCM56845_A3_REV_ID 4 +#define BCM56845_A4_REV_ID 5 +#define BCM56845_B0_REV_ID 0x11 +#define BCM56845_B1_REV_ID 0x12 + +#define BCM56743_DEVICE_ID 0xb743 +#define BCM56743_A0_REV_ID 1 +#define BCM56743_A1_REV_ID 2 +#define BCM56743_A2_REV_ID 3 +#define BCM56743_A3_REV_ID 4 +#define BCM56743_A4_REV_ID 5 +#define BCM56743_B0_REV_ID 0x11 +#define BCM56743_B1_REV_ID 0x12 +#define BCM56745_DEVICE_ID 0xb745 +#define BCM56745_A0_REV_ID 1 +#define BCM56745_A1_REV_ID 2 +#define BCM56745_A2_REV_ID 3 +#define BCM56745_A3_REV_ID 4 +#define BCM56745_A4_REV_ID 5 +#define BCM56745_B0_REV_ID 0x11 +#define BCM56745_B1_REV_ID 0x12 + +#define BCM56260_DEVICE_ID 0xb260 +#define BCM56260_A0_REV_ID 1 +#define BCM56260_B0_REV_ID 0x11 +#define BCM56261_DEVICE_ID 0xb261 +#define BCM56261_A0_REV_ID 1 +#define BCM56261_B0_REV_ID 0x11 +#define BCM56262_DEVICE_ID 0xb262 +#define BCM56262_A0_REV_ID 1 +#define BCM56262_B0_REV_ID 0x11 +#define BCM56263_DEVICE_ID 0xb263 +#define BCM56263_A0_REV_ID 1 +#define BCM56263_B0_REV_ID 0x11 + +#define BCM56265_DEVICE_ID 0xb265 +#define BCM56265_A0_REV_ID 1 +#define BCM56265_B0_REV_ID 0x11 +#define BCM56266_DEVICE_ID 0xb266 +#define BCM56266_A0_REV_ID 1 +#define BCM56266_B0_REV_ID 0x11 +#define BCM56267_DEVICE_ID 0xb267 +#define BCM56267_A0_REV_ID 1 +#define BCM56267_B0_REV_ID 0x11 +#define BCM56268_DEVICE_ID 0xb268 +#define BCM56268_A0_REV_ID 1 +#define BCM56268_B0_REV_ID 0x11 + +#define BCM56233_DEVICE_ID 0xb233 +#define BCM56233_B0_REV_ID 0x11 + +#define BCM56460_DEVICE_ID 0xb460 +#define BCM56460_A0_REV_ID 1 +#define BCM56460_B0_REV_ID 0x11 +#define BCM56461_DEVICE_ID 0xb461 +#define BCM56461_A0_REV_ID 1 +#define BCM56461_B0_REV_ID 0x11 +#define BCM56462_DEVICE_ID 0xb462 +#define BCM56462_A0_REV_ID 1 +#define BCM56462_B0_REV_ID 0x11 +#define BCM56463_DEVICE_ID 0xb463 +#define BCM56463_A0_REV_ID 1 +#define BCM56463_B0_REV_ID 0x11 + +#define BCM56465_DEVICE_ID 0xb465 +#define BCM56465_A0_REV_ID 1 +#define BCM56465_B0_REV_ID 0x11 +#define BCM56466_DEVICE_ID 0xb466 +#define BCM56466_A0_REV_ID 1 +#define BCM56466_B0_REV_ID 0x11 +#define BCM56467_DEVICE_ID 0xb467 +#define BCM56467_A0_REV_ID 1 +#define BCM56467_B0_REV_ID 0x11 +#define BCM56468_DEVICE_ID 0xb468 +#define BCM56468_A0_REV_ID 1 +#define BCM56468_B0_REV_ID 0x11 + +#define BCM56270_DEVICE_ID 0xb270 +#define BCM56270_A0_REV_ID 1 +#define BCM56271_DEVICE_ID 0xb271 +#define BCM56271_A0_REV_ID 1 +#define BCM56272_DEVICE_ID 0xb272 +#define BCM56272_A0_REV_ID 1 + +#define BCM53460_DEVICE_ID 0x8460 +#define BCM53460_A0_REV_ID 1 +#define BCM53461_DEVICE_ID 0x8461 +#define BCM53461_A0_REV_ID 1 + +#define BCM56842_DEVICE_ID 0xb842 +#define BCM56842_A0_REV_ID 1 +#define BCM56842_A1_REV_ID 2 +#define BCM56844_DEVICE_ID 0xb844 +#define BCM56844_A0_REV_ID 1 +#define BCM56844_A1_REV_ID 2 +#define BCM56846_DEVICE_ID 0xb846 +#define BCM56846_A0_REV_ID 1 +#define BCM56846_A1_REV_ID 2 +#define BCM56549_DEVICE_ID 0xb549 +#define BCM56549_A0_REV_ID 1 +#define BCM56549_A1_REV_ID 2 +#define BCM56053_DEVICE_ID 0xb053 +#define BCM56053_A0_REV_ID 1 +#define BCM56053_A1_REV_ID 2 +#define BCM56831_DEVICE_ID 0xb831 +#define BCM56831_A0_REV_ID 1 +#define BCM56831_A1_REV_ID 2 +#define BCM56835_DEVICE_ID 0xb835 +#define BCM56835_A0_REV_ID 1 +#define BCM56835_A1_REV_ID 2 +#define BCM56838_DEVICE_ID 0xb838 +#define BCM56838_A0_REV_ID 1 +#define BCM56838_A1_REV_ID 2 +#define BCM56847_DEVICE_ID 0xb847 +#define BCM56847_A0_REV_ID 1 +#define BCM56847_A1_REV_ID 2 +#define BCM56847_A2_REV_ID 3 +#define BCM56847_A3_REV_ID 4 +#define BCM56847_A4_REV_ID 5 +#define BCM56847_B0_REV_ID 0x11 +#define BCM56847_B1_REV_ID 0x12 +#define BCM56849_DEVICE_ID 0xb849 +#define BCM56849_A0_REV_ID 1 +#define BCM56849_A1_REV_ID 2 + +#define BCM56742_DEVICE_ID 0xb742 +#define BCM56742_A0_REV_ID 1 +#define BCM56742_A1_REV_ID 2 +#define BCM56742_A2_REV_ID 3 +#define BCM56744_DEVICE_ID 0xb744 +#define BCM56744_A0_REV_ID 1 +#define BCM56744_A1_REV_ID 2 +#define BCM56746_DEVICE_ID 0xb746 +#define BCM56746_A0_REV_ID 1 +#define BCM56746_A1_REV_ID 2 + +#define BCM88732_DEVICE_ID 0x0732 +#define BCM88732_A0_REV_ID 1 +#define BCM88732_A1_REV_ID 2 +#define BCM88732_A2_REV_ID 4 +#define BCM88732_B0_REV_ID 0x11 +#define BCM88732_B1_REV_ID 0x12 +#define BCM88732_B2_REV_ID 0x13 + +#define BCM56640_DEVICE_ID 0xb640 +#define BCM56640_A0_REV_ID 1 +#define BCM56640_A1_REV_ID 2 +#define BCM56640_B0_REV_ID 0x11 +#define BCM56643_DEVICE_ID 0xb643 +#define BCM56643_A0_REV_ID 1 +#define BCM56643_A1_REV_ID 2 +#define BCM56643_B0_REV_ID 0x11 +#define BCM56644_DEVICE_ID 0xb644 +#define BCM56644_A0_REV_ID 1 +#define BCM56644_A1_REV_ID 2 +#define BCM56644_B0_REV_ID 0x11 +#define BCM56648_DEVICE_ID 0xb648 +#define BCM56648_A0_REV_ID 1 +#define BCM56648_A1_REV_ID 2 +#define BCM56648_B0_REV_ID 0x11 +#define BCM56649_DEVICE_ID 0xb649 +#define BCM56649_A0_REV_ID 1 +#define BCM56649_A1_REV_ID 2 +#define BCM56649_B0_REV_ID 0x11 + +#define BCM56540_DEVICE_ID 0xb540 +#define BCM56540_A0_REV_ID 1 +#define BCM56540_A1_REV_ID 2 +#define BCM56540_B0_REV_ID 0x11 +#define BCM56541_DEVICE_ID 0xb541 +#define BCM56541_A0_REV_ID 1 +#define BCM56541_A1_REV_ID 2 +#define BCM56541_B0_REV_ID 0x11 +#define BCM56542_DEVICE_ID 0xb542 +#define BCM56542_A0_REV_ID 1 +#define BCM56542_A1_REV_ID 2 +#define BCM56542_B0_REV_ID 0x11 +#define BCM56543_DEVICE_ID 0xb543 +#define BCM56543_A0_REV_ID 1 +#define BCM56543_A1_REV_ID 2 +#define BCM56543_B0_REV_ID 0x11 +#define BCM56544_DEVICE_ID 0xb544 +#define BCM56544_A0_REV_ID 1 +#define BCM56544_A1_REV_ID 2 +#define BCM56544_B0_REV_ID 0x11 + +#define BCM56545_DEVICE_ID 0xb545 +#define BCM56545_A0_REV_ID 1 +#define BCM56545_A1_REV_ID 2 +#define BCM56545_B0_REV_ID 0x11 +#define BCM56546_DEVICE_ID 0xb546 +#define BCM56546_A0_REV_ID 1 +#define BCM56546_A1_REV_ID 2 +#define BCM56546_B0_REV_ID 0x11 + +#define BCM56044_DEVICE_ID 0xb044 +#define BCM56044_B0_REV_ID 0x11 +#define BCM56045_DEVICE_ID 0xb045 +#define BCM56045_A0_REV_ID 1 +#define BCM56045_A1_REV_ID 2 +#define BCM56045_B0_REV_ID 0x11 +#define BCM56046_DEVICE_ID 0xb046 +#define BCM56046_A0_REV_ID 1 +#define BCM56046_A1_REV_ID 2 +#define BCM56046_B0_REV_ID 0x11 + + +#define BCM56440_DEVICE_ID 0xb440 +#define BCM56440_A0_REV_ID 1 +#define BCM56440_B0_REV_ID 0x11 +#define BCM56441_DEVICE_ID 0xb441 +#define BCM56441_A0_REV_ID 1 +#define BCM56441_B0_REV_ID 0x11 +#define BCM56442_DEVICE_ID 0xb442 +#define BCM56442_A0_REV_ID 1 +#define BCM56442_B0_REV_ID 0x11 +#define BCM56443_DEVICE_ID 0xb443 +#define BCM56443_A0_REV_ID 1 +#define BCM56443_B0_REV_ID 0x11 +#define BCM56445_DEVICE_ID 0xb445 +#define BCM56445_A0_REV_ID 1 +#define BCM56445_B0_REV_ID 0x11 +#define BCM56446_DEVICE_ID 0xb446 +#define BCM56446_A0_REV_ID 1 +#define BCM56446_B0_REV_ID 0x11 +#define BCM56447_DEVICE_ID 0xb447 +#define BCM56447_A0_REV_ID 1 +#define BCM56447_B0_REV_ID 0x11 +#define BCM56448_DEVICE_ID 0xb448 +#define BCM56448_A0_REV_ID 1 +#define BCM56448_B0_REV_ID 0x11 +#define BCM56449_DEVICE_ID 0xb449 +#define BCM56449_A0_REV_ID 1 +#define BCM56449_B0_REV_ID 0x11 +#define BCM56240_DEVICE_ID 0xb240 +#define BCM56240_A0_REV_ID 1 +#define BCM56240_B0_REV_ID 0x11 +#define BCM56241_DEVICE_ID 0xb241 +#define BCM56241_A0_REV_ID 1 +#define BCM56241_B0_REV_ID 0x11 +#define BCM56242_DEVICE_ID 0xb242 +#define BCM56242_A0_REV_ID 1 +#define BCM56242_B0_REV_ID 0x11 +#define BCM56243_DEVICE_ID 0xb243 +#define BCM56243_A0_REV_ID 1 +#define BCM56243_B0_REV_ID 0x11 +#define BCM56245_DEVICE_ID 0xb245 +#define BCM56245_A0_REV_ID 1 +#define BCM56245_B0_REV_ID 0x11 +#define BCM56246_DEVICE_ID 0xb246 +#define BCM56246_A0_REV_ID 1 +#define BCM56246_B0_REV_ID 0x11 +#define BCM55440_DEVICE_ID 0xa440 +#define BCM55440_A0_REV_ID 1 +#define BCM55440_B0_REV_ID 0x11 +#define BCM55441_DEVICE_ID 0xa441 +#define BCM55441_A0_REV_ID 1 +#define BCM55441_B0_REV_ID 0x11 + +#define BCM55450_DEVICE_ID 0xa450 +#define BCM55450_A0_REV_ID 1 +#define BCM55450_B0_REV_ID 0x11 +#define BCM55450_B1_REV_ID 0x12 + +#define BCM55455_DEVICE_ID 0xa455 +#define BCM55455_A0_REV_ID 1 +#define BCM55455_B0_REV_ID 0x11 +#define BCM55455_B1_REV_ID 0x12 + +#define BCM56248_DEVICE_ID 0xb248 +#define BCM56248_A0_REV_ID 1 +#define BCM56248_B0_REV_ID 0x11 +#define BCM56248_B1_REV_ID 0x12 + +#define BCM56450_DEVICE_ID 0xb450 +#define BCM56450_A0_REV_ID 1 +#define BCM56450_B0_REV_ID 0x11 +#define BCM56450_B1_REV_ID 0x12 + +#define BCM56452_DEVICE_ID 0xb452 +#define BCM56452_A0_REV_ID 1 +#define BCM56452_B0_REV_ID 0x11 +#define BCM56452_B1_REV_ID 0x12 + +#define BCM56454_DEVICE_ID 0xb454 +#define BCM56454_A0_REV_ID 1 +#define BCM56454_B0_REV_ID 0x11 +#define BCM56454_B1_REV_ID 0x12 + +#define BCM56455_DEVICE_ID 0xb455 +#define BCM56455_A0_REV_ID 1 +#define BCM56455_B0_REV_ID 0x11 +#define BCM56455_B1_REV_ID 0x12 + +#define BCM56456_DEVICE_ID 0xb456 +#define BCM56456_A0_REV_ID 1 +#define BCM56456_B0_REV_ID 0x11 +#define BCM56456_B1_REV_ID 0x12 + +#define BCM56457_DEVICE_ID 0xb457 +#define BCM56457_A0_REV_ID 1 +#define BCM56457_B0_REV_ID 0x11 +#define BCM56457_B1_REV_ID 0x12 + +#define BCM56458_DEVICE_ID 0xb458 +#define BCM56458_A0_REV_ID 1 +#define BCM56458_B0_REV_ID 0x11 +#define BCM56458_B1_REV_ID 0x12 + +#define BCM56850_DEVICE_ID 0xb850 +#define BCM56850_A0_REV_ID 1 +#define BCM56850_A1_REV_ID 2 +#define BCM56850_A2_REV_ID 3 +#define BCM56851_DEVICE_ID 0xb851 +#define BCM56851_A0_REV_ID 1 +#define BCM56851_A1_REV_ID 2 +#define BCM56851_A2_REV_ID 3 +#define BCM56852_DEVICE_ID 0xb852 +#define BCM56852_A0_REV_ID 1 +#define BCM56852_A1_REV_ID 2 +#define BCM56852_A2_REV_ID 3 +#define BCM56853_DEVICE_ID 0xb853 +#define BCM56853_A0_REV_ID 1 +#define BCM56853_A1_REV_ID 2 +#define BCM56853_A2_REV_ID 3 +#define BCM56854_DEVICE_ID 0xb854 +#define BCM56854_A0_REV_ID 1 +#define BCM56854_A1_REV_ID 2 +#define BCM56854_A2_REV_ID 3 +#define BCM56855_DEVICE_ID 0xb855 +#define BCM56855_A0_REV_ID 1 +#define BCM56855_A1_REV_ID 2 +#define BCM56855_A2_REV_ID 3 +#define BCM56834_DEVICE_ID 0xb834 +#define BCM56834_A0_REV_ID 1 +#define BCM56834_A1_REV_ID 2 +#define BCM56834_A2_REV_ID 3 + +#define BCM56860_DEVICE_ID 0xb860 +#define BCM56860_A0_REV_ID 1 +#define BCM56860_A1_REV_ID 2 +#define BCM56861_DEVICE_ID 0xb861 +#define BCM56861_A0_REV_ID 1 +#define BCM56861_A1_REV_ID 2 +#define BCM56862_DEVICE_ID 0xb862 +#define BCM56862_A0_REV_ID 1 +#define BCM56862_A1_REV_ID 2 +#define BCM56864_DEVICE_ID 0xb864 +#define BCM56864_A0_REV_ID 1 +#define BCM56864_A1_REV_ID 2 +#define BCM56865_DEVICE_ID 0xb865 +#define BCM56865_A0_REV_ID 1 +#define BCM56865_A1_REV_ID 2 +#define BCM56866_DEVICE_ID 0xb866 +#define BCM56866_A0_REV_ID 1 +#define BCM56866_A1_REV_ID 2 +#define BCM56867_DEVICE_ID 0xb867 +#define BCM56867_A0_REV_ID 1 +#define BCM56867_A1_REV_ID 2 +#define BCM56868_DEVICE_ID 0xb868 +#define BCM56868_A0_REV_ID 1 +#define BCM56868_A1_REV_ID 2 +#define BCM56832_DEVICE_ID 0xb832 +#define BCM56832_A0_REV_ID 1 +#define BCM56832_A1_REV_ID 2 +#define BCM56833_DEVICE_ID 0xb833 +#define BCM56833_A0_REV_ID 1 +#define BCM56833_A1_REV_ID 2 +#define BCM56836_DEVICE_ID 0xb836 +#define BCM56836_A0_REV_ID 1 +#define BCM56836_A1_REV_ID 2 + + +#define BCM56750_DEVICE_ID 0xb750 +#define BCM56750_A0_REV_ID 1 +#define BCM56750_A1_REV_ID 2 +#define BCM56750_A2_REV_ID 3 + +#define BCM56830_DEVICE_ID 0xb830 +#define BCM56830_A0_REV_ID 1 +#define BCM56830_A1_REV_ID 2 +#define BCM56830_A2_REV_ID 3 + +#define BCM56150_DEVICE_ID 0xb150 +#define BCM56150_A0_REV_ID 1 +#define BCM56151_DEVICE_ID 0xb151 +#define BCM56151_A0_REV_ID 1 +#define BCM56152_DEVICE_ID 0xb152 +#define BCM56152_A0_REV_ID 1 + +#define BCM53342_DEVICE_ID 0x8342 +#define BCM53342_A0_REV_ID 1 +#define BCM53343_DEVICE_ID 0x8343 +#define BCM53343_A0_REV_ID 1 +#define BCM53344_DEVICE_ID 0x8344 +#define BCM53344_A0_REV_ID 1 +#define BCM53346_DEVICE_ID 0x8346 +#define BCM53346_A0_REV_ID 1 +#define BCM53347_DEVICE_ID 0x8347 +#define BCM53347_A0_REV_ID 1 + +#define BCM53333_DEVICE_ID 0x8333 +#define BCM53333_A0_REV_ID 1 +#define BCM53334_DEVICE_ID 0x8334 +#define BCM53334_A0_REV_ID 1 + +#define BCM53393_DEVICE_ID 0x8393 +#define BCM53393_A0_REV_ID 1 +#define BCM53394_DEVICE_ID 0x8394 +#define BCM53394_A0_REV_ID 1 + +#define BCM53400_DEVICE_ID 0x8400 +#define BCM53400_A0_REV_ID 1 +#define BCM56060_DEVICE_ID 0xb060 +#define BCM56060_A0_REV_ID 1 +#define BCM56062_DEVICE_ID 0xb062 +#define BCM56062_A0_REV_ID 1 +#define BCM56063_DEVICE_ID 0xb063 +#define BCM56063_A0_REV_ID 1 +#define BCM56064_DEVICE_ID 0xb064 +#define BCM56064_A0_REV_ID 1 +#define BCM56065_DEVICE_ID 0xb065 +#define BCM56065_A0_REV_ID 1 +#define BCM56066_DEVICE_ID 0xb066 +#define BCM56066_A0_REV_ID 1 +#define BCM53401_DEVICE_ID 0x8401 +#define BCM53411_DEVICE_ID 0x8411 +#define BCM53401_A0_REV_ID 1 +#define BCM53402_DEVICE_ID 0x8402 +#define BCM53412_DEVICE_ID 0x8412 +#define BCM53402_A0_REV_ID 1 +#define BCM53403_DEVICE_ID 0x8403 +#define BCM53413_DEVICE_ID 0x8413 +#define BCM53403_A0_REV_ID 1 +#define BCM53404_DEVICE_ID 0x8404 +#define BCM53414_DEVICE_ID 0x8414 +#define BCM53404_A0_REV_ID 1 +#define BCM53405_DEVICE_ID 0x8405 +#define BCM53415_DEVICE_ID 0x8415 +#define BCM53405_A0_REV_ID 1 +#define BCM53406_DEVICE_ID 0x8406 +#define BCM53416_DEVICE_ID 0x8416 +#define BCM53406_A0_REV_ID 1 +#define BCM53408_DEVICE_ID 0x8408 +#define BCM53418_DEVICE_ID 0x8418 +#define BCM53408_A0_REV_ID 1 +#define BCM53365_DEVICE_ID 0x8365 +#define BCM53365_A0_REV_ID 1 +#define BCM53369_DEVICE_ID 0x8369 +#define BCM53369_A0_REV_ID 1 + +#define BCM53454_DEVICE_ID 0x8454 +#define BCM53455_DEVICE_ID 0x8455 +#define BCM53454_A0_REV_ID 1 +#define BCM53456_DEVICE_ID 0x8456 +#define BCM53457_DEVICE_ID 0x8457 +#define BCM53456_A0_REV_ID 1 + +#define BCM53422_DEVICE_ID 0x8422 +#define BCM53422_A0_REV_ID 1 +#define BCM53424_DEVICE_ID 0x8424 +#define BCM53424_A0_REV_ID 1 +#define BCM53426_DEVICE_ID 0x8426 +#define BCM53426_A0_REV_ID 1 + +#define BCM56960_DEVICE_ID 0xb960 +#define BCM56960_A0_REV_ID 1 +#define BCM56960_B0_REV_ID 0x11 +#define BCM56960_B1_REV_ID 0x12 +#define BCM56961_DEVICE_ID 0xb961 +#define BCM56961_A0_REV_ID 1 +#define BCM56961_B0_REV_ID 0x11 +#define BCM56961_B1_REV_ID 0x12 +#define BCM56962_DEVICE_ID 0xb962 +#define BCM56962_A0_REV_ID 1 +#define BCM56962_B0_REV_ID 0x11 +#define BCM56962_B1_REV_ID 0x12 +#define BCM56963_DEVICE_ID 0xb963 +#define BCM56963_A0_REV_ID 1 +#define BCM56963_B0_REV_ID 0x11 +#define BCM56963_B1_REV_ID 0x12 +#define BCM56930_DEVICE_ID 0xb930 +#define BCM56930_A0_REV_ID 1 +#define BCM56930_B0_REV_ID 0x11 +#define BCM56930_B1_REV_ID 0x12 +#define BCM56930_C0_REV_ID 0x21 +#define BCM56931_DEVICE_ID 0xb931 +#define BCM56931_A0_REV_ID 1 +#define BCM56931_B0_REV_ID 0x11 +#define BCM56931_C0_REV_ID 0x21 +#define BCM56935_DEVICE_ID 0xb935 +#define BCM56935_A0_REV_ID 1 +#define BCM56935_B0_REV_ID 0x11 +#define BCM56935_C0_REV_ID 0x21 +#define BCM56936_DEVICE_ID 0xb936 +#define BCM56936_A0_REV_ID 1 +#define BCM56936_B0_REV_ID 0x11 +#define BCM56936_C0_REV_ID 0x21 +#define BCM56939_DEVICE_ID 0xb939 +#define BCM56939_A0_REV_ID 1 +#define BCM56939_B0_REV_ID 0x11 +#define BCM56939_C0_REV_ID 0x21 + +#define BCM56168_DEVICE_ID 0xb168 +#define BCM56168_A0_REV_ID 1 +#define BCM56168_B0_REV_ID 0x11 +#define BCM56168_B1_REV_ID 0x12 +#define BCM56169_DEVICE_ID 0xb169 +#define BCM56169_A0_REV_ID 1 +#define BCM56169_B0_REV_ID 0x11 +#define BCM56169_B1_REV_ID 0x12 + +#define BCM56980_DEVICE_ID_MASK 0xFFF0 +#define BCM56980_DEVICE_ID 0xb980 +#define BCM56980_A0_REV_ID 1 +#define BCM56980_B0_REV_ID 0x11 +#define BCM56981_DEVICE_ID 0xb981 +#define BCM56981_A0_REV_ID 1 +#define BCM56981_B0_REV_ID 0x11 +#define BCM56982_DEVICE_ID 0xb982 +#define BCM56982_A0_REV_ID 1 +#define BCM56982_B0_REV_ID 0x11 +#define BCM56983_DEVICE_ID 0xb983 +#define BCM56983_A0_REV_ID 1 +#define BCM56983_B0_REV_ID 0x11 +#define BCM56984_DEVICE_ID 0xb984 +#define BCM56984_A0_REV_ID 1 +#define BCM56984_B0_REV_ID 0x11 + +#define BCM56968_DEVICE_ID 0xb968 +#define BCM56968_A0_REV_ID 1 +#define BCM56968_B0_REV_ID 0x11 +#define BCM56968_B1_REV_ID 0x12 + +#define BCM56160_DEVICE_ID 0xb160 +#define BCM56160_A0_REV_ID 1 +#define BCM56160_B0_REV_ID 0x11 +#define BCM56162_DEVICE_ID 0xb162 +#define BCM56162_A0_REV_ID 1 +#define BCM56162_B0_REV_ID 0x11 + +#define BCM56163_DEVICE_ID 0xb163 +#define BCM56163_A0_REV_ID 1 +#define BCM56163_B0_REV_ID 0x11 +#define BCM56164_DEVICE_ID 0xb164 +#define BCM56164_A0_REV_ID 1 +#define BCM56164_B0_REV_ID 0x11 +#define BCM56166_DEVICE_ID 0xb166 +#define BCM56166_A0_REV_ID 1 +#define BCM56166_B0_REV_ID 0x11 + +#define BCM56273_DEVICE_ID 0xb273 +#define BCM56273_A0_REV_ID 1 +#define BCM56273_A1_REV_ID 2 + +#define BCM56274_DEVICE_ID 0xb274 +#define BCM56274_A0_REV_ID 1 +#define BCM56274_A1_REV_ID 2 + +#define BCM56275_DEVICE_ID 0xb275 +#define BCM56275_A0_REV_ID 1 +#define BCM56275_A1_REV_ID 2 + +#define BCM56276_DEVICE_ID 0xb276 +#define BCM56276_A0_REV_ID 1 +#define BCM56276_A1_REV_ID 2 + +#define BCM56277_DEVICE_ID 0xb277 +#define BCM56277_A0_REV_ID 1 +#define BCM56277_A1_REV_ID 2 + +#define BCM56278_DEVICE_ID 0xb278 +#define BCM56278_A0_REV_ID 1 +#define BCM56278_A1_REV_ID 2 + +#define BCM56279_DEVICE_ID 0xb279 +#define BCM56279_A1_REV_ID 2 + +#define BCM56575_DEVICE_ID 0xb575 +#define BCM56575_A1_REV_ID 2 + +#define BCM56175_DEVICE_ID 0xb175 +#define BCM56175_A1_REV_ID 2 + +#define BCM56176_DEVICE_ID 0xb176 +#define BCM56176_A1_REV_ID 2 + +#define BCM53440_DEVICE_ID 0x8440 +#define BCM53440_A0_REV_ID 1 +#define BCM53440_B0_REV_ID 0x11 +#define BCM53442_DEVICE_ID 0x8442 +#define BCM53442_A0_REV_ID 1 +#define BCM53442_B0_REV_ID 0x11 +#define BCM53443_DEVICE_ID 0x8443 +#define BCM53443_A0_REV_ID 1 +#define BCM53443_B0_REV_ID 0x11 + +#define BCM53434_DEVICE_ID 0x8434 +#define BCM53434_A0_REV_ID 1 +#define BCM53434_B0_REV_ID 0x11 + +#define BCM56560_DEVICE_ID 0xb560 +#define BCM56560_A0_REV_ID 1 +#define BCM56560_B0_REV_ID 0x11 + +#define BCM56561_DEVICE_ID 0xb561 +#define BCM56561_A0_REV_ID 1 +#define BCM56561_B0_REV_ID 0x11 + +#define BCM56562_DEVICE_ID 0xb562 +#define BCM56562_A0_REV_ID 1 +#define BCM56562_B0_REV_ID 0x11 + +#define BCM56670_DEVICE_ID 0xb670 +#define BCM56670_A0_REV_ID 1 +#define BCM56670_B0_REV_ID 0x11 +#define BCM56670_C0_REV_ID 0x21 + + +#define BCM56671_DEVICE_ID 0xb671 +#define BCM56671_A0_REV_ID 1 +#define BCM56671_B0_REV_ID 0x11 +#define BCM56671_C0_REV_ID 0x21 + +#define BCM56672_DEVICE_ID 0xb672 +#define BCM56672_A0_REV_ID 1 +#define BCM56672_B0_REV_ID 0x11 +#define BCM56672_C0_REV_ID 0x21 + +#define BCM56675_DEVICE_ID 0xb675 +#define BCM56675_A0_REV_ID 1 +#define BCM56675_B0_REV_ID 0x11 +#define BCM56675_C0_REV_ID 0x21 + + +#define BCM56565_DEVICE_ID 0xb565 +#define BCM56565_A0_REV_ID 1 +#define BCM56565_B0_REV_ID 0x11 + +#define BCM56566_DEVICE_ID 0xb566 +#define BCM56566_A0_REV_ID 1 +#define BCM56566_B0_REV_ID 0x11 + +#define BCM56567_DEVICE_ID 0xb567 +#define BCM56567_A0_REV_ID 1 +#define BCM56567_B0_REV_ID 0x11 + +#define BCM56568_DEVICE_ID 0xb568 +#define BCM56568_A0_REV_ID 1 +#define BCM56568_B0_REV_ID 0x11 + +#define BCM56760_DEVICE_ID 0xb760 +#define BCM56760_A0_REV_ID 1 +#define BCM56760_A1_REV_ID 2 +#define BCM56760_B0_REV_ID 0x11 + + +#define BCM56761_DEVICE_ID 0xb761 +#define BCM56761_A0_REV_ID 1 +#define BCM56761_A1_REV_ID 2 +#define BCM56761_B0_REV_ID 0x11 +#define BCM56761_B1_REV_ID 0x12 + +#define BCM56762_DEVICE_ID 0xb762 +#define BCM56762_A0_REV_ID 1 +#define BCM56762_B0_REV_ID 0x11 + +#define BCM56764_DEVICE_ID 0xb764 +#define BCM56764_A0_REV_ID 1 +#define BCM56764_B0_REV_ID 0x11 + +#define BCM56765_DEVICE_ID 0xb765 +#define BCM56765_A0_REV_ID 1 +#define BCM56765_B0_REV_ID 0x11 + +#define BCM56766_DEVICE_ID 0xb766 +#define BCM56766_A0_REV_ID 1 +#define BCM56766_B0_REV_ID 0x11 + +#define BCM56768_DEVICE_ID 0xb768 +#define BCM56768_A0_REV_ID 1 +#define BCM56768_B0_REV_ID 0x11 + +#define BCM56068_DEVICE_ID 0xb068 +#define BCM56068_A0_REV_ID 1 +#define BCM56068_B0_REV_ID 0x11 + +#define BCM56068_DEVICE_ID 0xb068 +#define BCM56068_A0_REV_ID 1 +#define BCM56068_B0_REV_ID 0x11 +#define BCM56068_B1_REV_ID 0x12 + +#define BCM56069_DEVICE_ID 0xb069 +#define BCM56069_A0_REV_ID 1 +#define BCM56069_B0_REV_ID 0x11 + +#define BCM56170_DEVICE_ID 0xb170 +#define BCM56170_A0_REV_ID 1 +#define BCM56170_B0_REV_ID 0x11 +#define BCM56172_DEVICE_ID 0xb172 +#define BCM56172_A0_REV_ID 1 +#define BCM56172_B0_REV_ID 0x11 +#define BCM56174_DEVICE_ID 0xb174 +#define BCM56174_A0_REV_ID 1 +#define BCM56174_B0_REV_ID 0x11 + +#define BCM53570_DEVICE_ID 0x8570 +#define BCM53570_A0_REV_ID 1 +#define BCM53570_B0_REV_ID 0x11 +#define BCM53575_DEVICE_ID 0x8575 +#define BCM53575_A0_REV_ID 1 +#define BCM53575_B0_REV_ID 0x11 + +#define BCM56070_DEVICE_ID 0xb070 +#define BCM56070_A0_REV_ID 1 +#define BCM56071_DEVICE_ID 0xb071 +#define BCM56071_A0_REV_ID 1 +#define BCM56072_DEVICE_ID 0xb072 +#define BCM56072_A0_REV_ID 1 + + +#define BCM56965_DEVICE_ID 0xb965 +#define BCM56965_A0_REV_ID 1 +#define BCM56965_A1_REV_ID 2 +#define BCM56969_DEVICE_ID 0xb969 +#define BCM56969_A0_REV_ID 1 +#define BCM56966_DEVICE_ID 0xb966 +#define BCM56966_A0_REV_ID 1 +#define BCM56967_DEVICE_ID 0xb967 +#define BCM56967_A0_REV_ID 1 + +#define BCM56970_DEVICE_ID 0xb970 +#define BCM56970_A0_REV_ID 1 +#define BCM56970_B0_REV_ID 0x11 +#define BCM56971_DEVICE_ID 0xb971 +#define BCM56971_A0_REV_ID 1 +#define BCM56971_B0_REV_ID 0x11 +#define BCM56972_DEVICE_ID 0xb972 +#define BCM56972_A0_REV_ID 1 +#define BCM56972_B0_REV_ID 0x11 +#define BCM56974_DEVICE_ID 0xb974 +#define BCM56974_A0_REV_ID 1 +#define BCM56974_B0_REV_ID 0x11 +#define BCM56975_DEVICE_ID 0xb975 +#define BCM56975_A0_REV_ID 1 +#define BCM56975_B0_REV_ID 0x11 + +#define BCM56870_DEVICE_ID 0xb870 +#define BCM56870_A0_REV_ID 1 +#define BCM56873_DEVICE_ID 0xb873 +#define BCM56873_A0_REV_ID 1 + +#define BCM56370_DEVICE_ID 0xb370 +#define BCM56370_A0_REV_ID 1 +#define BCM56370_A1_REV_ID 0x02 +#define BCM56370_A2_REV_ID 0x03 + +#define BCM56371_DEVICE_ID 0xb371 +#define BCM56371_A0_REV_ID 1 +#define BCM56371_A1_REV_ID 0x02 +#define BCM56371_A2_REV_ID 0x03 + +#define BCM56372_DEVICE_ID 0xb372 +#define BCM56372_A0_REV_ID 1 +#define BCM56372_A1_REV_ID 0x02 +#define BCM56372_A2_REV_ID 0x03 + +#define BCM56374_DEVICE_ID 0xb374 +#define BCM56374_A0_REV_ID 1 +#define BCM56374_A1_REV_ID 0x02 +#define BCM56374_A2_REV_ID 0x03 + +#define BCM56375_DEVICE_ID 0xb375 +#define BCM56375_A0_REV_ID 1 +#define BCM56375_A1_REV_ID 0x02 +#define BCM56375_A2_REV_ID 0x03 + +#define BCM56376_DEVICE_ID 0xb376 +#define BCM56376_A0_REV_ID 1 +#define BCM56376_A1_REV_ID 0x02 +#define BCM56376_A2_REV_ID 0x03 + +#define BCM56377_DEVICE_ID 0xb377 +#define BCM56377_A0_REV_ID 1 +#define BCM56377_A1_REV_ID 0x02 +#define BCM56377_A2_REV_ID 0x03 + +#define BCM56577_DEVICE_ID 0xb577 +#define BCM56577_A0_REV_ID 1 +#define BCM56577_A1_REV_ID 0x02 +#define BCM56577_A2_REV_ID 0x03 + +#define BCM56578_DEVICE_ID 0xb578 +#define BCM56578_A0_REV_ID 1 +#define BCM56578_A1_REV_ID 0x02 +#define BCM56578_A2_REV_ID 0x03 + +#define BCM56579_DEVICE_ID 0xb579 +#define BCM56579_A0_REV_ID 1 +#define BCM56579_A1_REV_ID 0x02 +#define BCM56579_A2_REV_ID 0x03 + +#define BCM56770_DEVICE_ID 0xb770 +#define BCM56770_A0_REV_ID 1 + +#define BCM56771_DEVICE_ID 0xb771 +#define BCM56771_A0_REV_ID 1 + +#define BCM56470_DEVICE_ID 0xb470 +#define BCM56470_A0_REV_ID 1 +#define BCM56471_DEVICE_ID 0xb471 +#define BCM56471_A0_REV_ID 1 +#define BCM56472_DEVICE_ID 0xb472 +#define BCM56472_A0_REV_ID 1 +#define BCM56475_DEVICE_ID 0xb475 +#define BCM56475_A0_REV_ID 1 + + +#define BCM53540_DEVICE_ID 0x8540 +#define BCM53540_A0_REV_ID 1 +#define BCM53547_DEVICE_ID 0x8547 +#define BCM53547_A0_REV_ID 1 +#define BCM53548_DEVICE_ID 0x8548 +#define BCM53548_A0_REV_ID 1 +#define BCM53549_DEVICE_ID 0x8549 +#define BCM53549_A0_REV_ID 1 + +#define BCM5665_DEVICE_ID 0x5665 +#define BCM5665_A0_REV_ID 1 +#define BCM5665_B0_REV_ID 0x11 + + +#define BCM5655_DEVICE_ID 0x5655 +#define BCM5655_A0_REV_ID 1 +#define BCM5655_B0_REV_ID 0x11 + + +#define BCM5650_DEVICE_ID 0x5650 +#define BCM5650_A0_REV_ID 1 +#define BCM5650_B0_REV_ID 0x11 +#define BCM5650_C0_REV_ID 0x21 + +#define BROADCOM_PHYID_HIGH 0x0040 + +#define GEDI_DEVICE_ID 0xa100 +#define GEDI_REV_ID 0x0001 +#define ARAD_DEVICE_ID 0x8650 +#define ARAD_A0_REV_ID 0x0000 +#define ARAD_B0_REV_ID 0x0011 +#define ARAD_B1_REV_ID 0x0012 +#define BCM88650_DEVICE_ID ARAD_DEVICE_ID +#define BCM88650_A0_REV_ID ARAD_A0_REV_ID +#define BCM88650_B0_REV_ID ARAD_B0_REV_ID +#define BCM88650_B1_REV_ID ARAD_B1_REV_ID +#define BCM88770_DEVICE_ID 0x8770 +#define BCM88770_A1_REV_ID 0x0002 +#define BCM88773_DEVICE_ID 0x8773 +#define BCM88773_A1_REV_ID 0x0002 +#define BCM88774_DEVICE_ID 0x8774 +#define BCM88774_A1_REV_ID 0x0002 +#define BCM88775_DEVICE_ID 0x8775 +#define BCM88775_A1_REV_ID 0x0002 +#define BCM88776_DEVICE_ID 0x8776 +#define BCM88776_A1_REV_ID 0x0002 +#define BCM88777_DEVICE_ID 0x8777 +#define BCM88777_A1_REV_ID 0x0002 +#define BCM88950_DEVICE_ID 0x8950 +#define BCM88950_A0_REV_ID 0x0001 +#define BCM88950_A1_REV_ID 0x0002 +#define BCM88953_DEVICE_ID 0x8953 +#define BCM88953_A1_REV_ID 0x0002 +#define BCM88954_DEVICE_ID 0x8954 +#define BCM88954_A1_REV_ID 0x0002 +#define BCM88955_DEVICE_ID 0x8955 +#define BCM88955_A1_REV_ID 0x0002 +#define BCM88956_DEVICE_ID 0x8956 +#define BCM88956_A1_REV_ID 0x0002 +#define DNXC_A0_REV_ID 0x0001 +#define DNXC_A1_REV_ID 0x0002 +#define DNXC_B0_REV_ID 0x0011 +#define DNXC_B1_REV_ID 0x0012 +#define DNXC_DEVID_FAMILY_MASK 0xfff0 +#define BCM88790_DEVICE_ID 0x8790 +#define BCM88790_A0_REV_ID DNXC_A0_REV_ID +#define BCM88790_B0_REV_ID DNXC_B0_REV_ID +#define BCM88791_DEVICE_ID 0x8791 +#define BCM88792_DEVICE_ID 0x8792 +#define BCM88793_DEVICE_ID 0x8793 +#define BCM88794_DEVICE_ID 0x8794 +#define BCM88795_DEVICE_ID 0x8795 +#define BCM88796_DEVICE_ID 0x8796 +#define BCM88797_DEVICE_ID 0x8797 +#define BCM88798_DEVICE_ID 0x8798 +#define BCM88799_DEVICE_ID 0x8799 +#define BCM8879A_DEVICE_ID 0x879A +#define BCM8879B_DEVICE_ID 0x879B +#define BCM8879C_DEVICE_ID 0x879C +#define BCM8879D_DEVICE_ID 0x879D +#define BCM8879E_DEVICE_ID 0x879E +#define BCM8879F_DEVICE_ID 0x879F +#define ARADPLUS_DEVICE_ID 0x8660 +#define ARADPLUS_A0_REV_ID 0x0001 +#define BCM88660_DEVICE_ID ARADPLUS_DEVICE_ID +#define BCM88660_A0_REV_ID ARADPLUS_A0_REV_ID +#define JERICHO_DEVICE_ID 0x8675 +#define JERICHO_A0_REV_ID 0x0001 +#define JERICHO_B0_REV_ID 0x0011 +#define JERICHO_A1_REV_ID 0x0002 +#define BCM88670_DEVICE_ID 0x8670 +#define BCM88670_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88670_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88671_DEVICE_ID 0x8671 +#define BCM88671_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88671_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88671M_DEVICE_ID 0x867A +#define BCM88671M_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88671M_A1_REV_ID JERICHO_A1_REV_ID + +#define BCM88670_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88671_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88671M_B0_REV_ID JERICHO_B0_REV_ID + +#define BCM88672_DEVICE_ID 0x8672 +#define BCM88672_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88672_A1_REV_ID JERICHO_A1_REV_ID + +#define BCM88672_B0_REV_ID JERICHO_B0_REV_ID + +#define BCM88673_DEVICE_ID 0x8673 +#define BCM88673_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88673_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88674_DEVICE_ID 0x8674 +#define BCM88674_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88674_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88675_DEVICE_ID JERICHO_DEVICE_ID +#define BCM88675_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88675_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88675M_DEVICE_ID 0x867B +#define BCM88675M_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88675M_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88676_DEVICE_ID 0x8676 +#define BCM88676_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88676_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88676M_DEVICE_ID 0x867C +#define BCM88676M_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88676M_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88677_DEVICE_ID 0x8677 +#define BCM88677_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88677_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88678_DEVICE_ID 0x8678 +#define BCM88678_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88678_A1_REV_ID JERICHO_A1_REV_ID +#define BCM88679_DEVICE_ID 0x8679 +#define BCM88679_A0_REV_ID JERICHO_A0_REV_ID +#define BCM88679_A1_REV_ID JERICHO_A1_REV_ID + +#define BCM88673_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88674_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88675_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88675M_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88676_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88676M_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88677_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88678_B0_REV_ID JERICHO_B0_REV_ID +#define BCM88679_B0_REV_ID JERICHO_B0_REV_ID +#define QMX_DEVICE_ID 0x8375 +#define QMX_A0_REV_ID 0x0001 +#define QMX_B0_REV_ID 0x0011 +#define QMX_A1_REV_ID 0x0002 +#define BCM88370_DEVICE_ID 0x8370 +#define BCM88370_A0_REV_ID QMX_A0_REV_ID +#define BCM88370_A1_REV_ID QMX_A1_REV_ID +#define BCM88371_DEVICE_ID 0x8371 +#define BCM88371_A0_REV_ID QMX_A0_REV_ID +#define BCM88371_A1_REV_ID QMX_A1_REV_ID +#define BCM88371M_DEVICE_ID 0x837A +#define BCM88371M_A0_REV_ID QMX_A0_REV_ID +#define BCM88371M_A1_REV_ID QMX_A1_REV_ID +#define BCM88375_DEVICE_ID QMX_DEVICE_ID +#define BCM88375_A0_REV_ID QMX_A0_REV_ID +#define BCM88375_A1_REV_ID QMX_A1_REV_ID +#define BCM88376_DEVICE_ID 0x8376 +#define BCM88376_A0_REV_ID QMX_A0_REV_ID +#define BCM88376_A1_REV_ID QMX_A1_REV_ID +#define BCM88376M_DEVICE_ID 0x837B +#define BCM88376M_A0_REV_ID QMX_A0_REV_ID +#define BCM88376M_A1_REV_ID QMX_A1_REV_ID +#define BCM88377_DEVICE_ID 0x8377 +#define BCM88377_A0_REV_ID QMX_A0_REV_ID +#define BCM88377_A1_REV_ID QMX_A1_REV_ID +#define BCM88378_DEVICE_ID 0x8378 +#define BCM88378_A0_REV_ID QMX_A0_REV_ID +#define BCM88378_A1_REV_ID QMX_A1_REV_ID +#define BCM88379_DEVICE_ID 0x8379 +#define BCM88379_A0_REV_ID QMX_A0_REV_ID +#define BCM88379_A1_REV_ID QMX_A1_REV_ID + +#define BCM88370_B0_REV_ID QMX_B0_REV_ID +#define BCM88371_B0_REV_ID QMX_B0_REV_ID +#define BCM88371M_B0_REV_ID QMX_B0_REV_ID +#define BCM88375_B0_REV_ID QMX_B0_REV_ID +#define BCM88376_B0_REV_ID QMX_B0_REV_ID +#define BCM88376M_B0_REV_ID QMX_B0_REV_ID +#define BCM88377_B0_REV_ID QMX_B0_REV_ID +#define BCM88378_B0_REV_ID QMX_B0_REV_ID +#define BCM88379_B0_REV_ID QMX_B0_REV_ID + + +#define JERICHO_PLUS_DEVICE_ID 0x8680 +#define JERICHO_PLUS_A0_REV_ID 0x0001 +#define BCM88680_DEVICE_ID JERICHO_PLUS_DEVICE_ID +#define BCM88680_A0_REV_ID JERICHO_PLUS_A0_REV_ID +#define BCM88680_A1_REV_ID 0x0002 + + +#define BCM88681_DEVICE_ID 0x8681 +#define BCM88681_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88682_DEVICE_ID 0x8682 +#define BCM88682_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88683_DEVICE_ID 0x8683 +#define BCM88683_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88684_DEVICE_ID 0x8684 +#define BCM88684_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88685_DEVICE_ID 0x8685 +#define BCM88685_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88687_DEVICE_ID 0x8687 +#define BCM88687_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define BCM88380_DEVICE_ID 0x8380 +#define BCM88380_A0_REV_ID JERICHO_PLUS_A0_REV_ID +#define BCM88381_DEVICE_ID 0x8381 +#define BCM88381_A0_REV_ID JERICHO_PLUS_A0_REV_ID + +#define JERICHO2_DEVICE_ID 0x8690 +#define JERICHO2_A0_REV_ID DNXC_A0_REV_ID +#define JERICHO2_B0_REV_ID DNXC_B0_REV_ID +#define JERICHO2_B1_REV_ID DNXC_B1_REV_ID +#define BCM88690_DEVICE_ID JERICHO2_DEVICE_ID +#define BCM88690_A0_REV_ID JERICHO2_A0_REV_ID +#define BCM88690_B0_REV_ID JERICHO2_B0_REV_ID +#define BCM88690_B1_REV_ID JERICHO2_B1_REV_ID +#define BCM88691_DEVICE_ID 0x8691 +#define BCM88692_DEVICE_ID 0x8692 +#define BCM88693_DEVICE_ID 0x8693 +#define BCM88694_DEVICE_ID 0x8694 +#define BCM88695_DEVICE_ID 0x8695 +#define BCM88696_DEVICE_ID 0x8696 +#define BCM88697_DEVICE_ID 0x8697 +#define BCM88698_DEVICE_ID 0x8698 +#define BCM88699_DEVICE_ID 0x8699 +#define BCM8869A_DEVICE_ID 0x869A +#define BCM8869B_DEVICE_ID 0x869B +#define BCM8869C_DEVICE_ID 0x869C +#define BCM8869D_DEVICE_ID 0x869D +#define BCM8869E_DEVICE_ID 0x869E +#define BCM8869F_DEVICE_ID 0x869F + +#define J2C_DEVICE_ID 0x8800 +#define J2C_2ND_DEVICE_ID 0x8820 +#define J2C_DEVID_FAMILY_MASK 0xffd0 +#define J2C_A0_REV_ID DNXC_A0_REV_ID +#define J2C_A1_REV_ID DNXC_A1_REV_ID +#define BCM88800_DEVICE_ID J2C_DEVICE_ID +#define BCM88820_DEVICE_ID J2C_2ND_DEVICE_ID +#define BCM88800_A0_REV_ID J2C_A0_REV_ID +#define BCM88800_A1_REV_ID J2C_A1_REV_ID +#define BCM88801_DEVICE_ID 0x8801 +#define BCM88802_DEVICE_ID 0x8802 +#define BCM88803_DEVICE_ID 0x8803 +#define BCM88804_DEVICE_ID 0x8804 +#define BCM88805_DEVICE_ID 0x8805 +#define BCM88806_DEVICE_ID 0x8806 +#define BCM88807_DEVICE_ID 0x8807 +#define BCM88808_DEVICE_ID 0x8808 +#define BCM88809_DEVICE_ID 0x8809 +#define BCM8880A_DEVICE_ID 0x880A +#define BCM8880B_DEVICE_ID 0x880B +#define BCM8880C_DEVICE_ID 0x880C +#define BCM8880D_DEVICE_ID 0x880D +#define BCM8880E_DEVICE_ID 0x880E +#define BCM8880F_DEVICE_ID 0x880F +#define BCM88821_DEVICE_ID 0x8821 +#define BCM88822_DEVICE_ID 0x8822 +#define BCM88823_DEVICE_ID 0x8823 +#define BCM88824_DEVICE_ID 0x8824 +#define BCM88825_DEVICE_ID 0x8825 +#define BCM88826_DEVICE_ID 0x8826 +#define BCM88827_DEVICE_ID 0x8827 +#define BCM88828_DEVICE_ID 0x8828 +#define BCM88829_DEVICE_ID 0x8829 +#define BCM8882A_DEVICE_ID 0x882A +#define BCM8882B_DEVICE_ID 0x882B +#define BCM8882C_DEVICE_ID 0x882C +#define BCM8882D_DEVICE_ID 0x882D +#define BCM8882E_DEVICE_ID 0x882E +#define BCM8882F_DEVICE_ID 0x882F + +#define J2P_DEVICE_ID 0x8850 +#define J2P_A0_REV_ID DNXC_A0_REV_ID +#define BCM88850_DEVICE_ID J2P_DEVICE_ID +#define BCM88850_A0_REV_ID J2P_A0_REV_ID +#define BCM88851_DEVICE_ID 0x8851 +#define BCM88852_DEVICE_ID 0x8852 +#define BCM88853_DEVICE_ID 0x8853 +#define BCM88854_DEVICE_ID 0x8854 +#define BCM88855_DEVICE_ID 0x8855 +#define BCM88856_DEVICE_ID 0x8856 +#define BCM88857_DEVICE_ID 0x8857 +#define BCM88858_DEVICE_ID 0x8858 +#define BCM88859_DEVICE_ID 0x8859 +#define BCM8885A_DEVICE_ID 0x885A +#define BCM8885B_DEVICE_ID 0x885B +#define BCM8885C_DEVICE_ID 0x885C +#define BCM8885D_DEVICE_ID 0x885D +#define BCM8885E_DEVICE_ID 0x885E +#define BCM8885F_DEVICE_ID 0x885F + + +#define Q2A_DEVICE_ID 0x8480 +#define Q2A_A0_REV_ID DNXC_A0_REV_ID +#define Q2A_B0_REV_ID DNXC_B0_REV_ID +#define Q2A_B1_REV_ID DNXC_B1_REV_ID +#define BCM88480_DEVICE_ID Q2A_DEVICE_ID +#define BCM88480_A0_REV_ID Q2A_A0_REV_ID +#define BCM88480_B0_REV_ID Q2A_B0_REV_ID +#define BCM88480_B1_REV_ID Q2A_B1_REV_ID +#define BCM88481_DEVICE_ID 0x8481 +#define BCM88482_DEVICE_ID 0x8482 +#define BCM88483_DEVICE_ID 0x8483 +#define BCM88484_DEVICE_ID 0x8484 +#define BCM88485_DEVICE_ID 0x8485 +#define BCM88486_DEVICE_ID 0x8486 +#define BCM88487_DEVICE_ID 0x8487 +#define BCM88488_DEVICE_ID 0x8488 +#define BCM88489_DEVICE_ID 0x8489 +#define BCM8848A_DEVICE_ID 0x848A +#define BCM8848B_DEVICE_ID 0x848B +#define BCM8848C_DEVICE_ID 0x848C +#define BCM8848D_DEVICE_ID 0x848D +#define BCM8848E_DEVICE_ID 0x848E +#define BCM8848F_DEVICE_ID 0x848F + +#define Q2U_DEVICE_ID 0x8280 +#define BCM88280_DEVICE_ID Q2U_DEVICE_ID +#define BCM88281_DEVICE_ID 0x8281 +#define BCM88282_DEVICE_ID 0x8282 +#define BCM88283_DEVICE_ID 0x8283 +#define BCM88284_DEVICE_ID 0x8284 +#define BCM88285_DEVICE_ID 0x8285 +#define BCM88286_DEVICE_ID 0x8286 +#define BCM88287_DEVICE_ID 0x8287 +#define BCM88288_DEVICE_ID 0x8288 +#define BCM88289_DEVICE_ID 0x8289 +#define BCM8828A_DEVICE_ID 0x828A +#define BCM8828B_DEVICE_ID 0x828B +#define BCM8828C_DEVICE_ID 0x828C +#define BCM8828D_DEVICE_ID 0x828D +#define BCM8828E_DEVICE_ID 0x828E +#define BCM8828F_DEVICE_ID 0x828F + +#define QAX_DEVICE_ID 0x8470 +#define QAX_A0_REV_ID 0x0001 +#define QAX_B0_REV_ID 0x0011 +#define BCM88470_DEVICE_ID QAX_DEVICE_ID +#define BCM88470_B0_REV_ID QAX_B0_REV_ID +#define BCM88470P_DEVICE_ID 0x847C +#define BCM88471_DEVICE_ID 0x8471 +#define BCM88473_DEVICE_ID 0x8473 +#define BCM88474_DEVICE_ID 0x8474 +#define BCM88474H_DEVICE_ID 0x847B +#define BCM88476_DEVICE_ID 0x8476 +#define BCM88477_DEVICE_ID 0x8477 + + + + +#define BCM88470_A0_REV_ID QAX_A0_REV_ID + +#define QUX_DEVICE_ID 0x8270 +#define QUX_A0_REV_ID 0x0001 +#define QUX_A1_REV_ID 0x0002 +#define QUX_B0_REV_ID 0x0011 +#define BCM88270_DEVICE_ID QUX_DEVICE_ID +#define BCM88270_A0_REV_ID QUX_A0_REV_ID +#define BCM88270_A1_REV_ID QUX_A1_REV_ID +#define BCM88271_DEVICE_ID 0x8271 +#define BCM88272_DEVICE_ID 0x8272 +#define BCM88273_DEVICE_ID 0x8273 +#define BCM88274_DEVICE_ID 0x8274 +#define BCM88276_DEVICE_ID 0x8276 +#define BCM88278_DEVICE_ID 0x8278 +#define BCM88279_DEVICE_ID 0x8279 + +#define FLAIR_DEVICE_ID 0xF000 +#define FLAIR_A0_REV_ID 0x0001 +#define BCM8206_DEVICE_ID FLAIR_DEVICE_ID +#define BCM8206_A0_REV_ID FLAIR_A0_REV_ID + +#define BCM88360_DEVICE_ID 0x8360 +#define BCM88360_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88361_DEVICE_ID 0x8361 +#define BCM88361_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88363_DEVICE_ID 0x8363 +#define BCM88363_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88460_DEVICE_ID 0x8460 +#define BCM88460_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88461_DEVICE_ID 0x8461 +#define BCM88461_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88560_DEVICE_ID 0x8560 +#define BCM88560_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88561_DEVICE_ID 0x8561 +#define BCM88561_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88562_DEVICE_ID 0x8562 +#define BCM88562_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88661_DEVICE_ID 0x8661 +#define BCM88661_A0_REV_ID ARADPLUS_A0_REV_ID +#define BCM88664_DEVICE_ID 0x8664 +#define BCM88664_A0_REV_ID ARADPLUS_A0_REV_ID + + +#define BCM88350_DEVICE_ID 0x8350 +#define BCM88350_B1_REV_ID ARAD_B1_REV_ID +#define BCM88351_DEVICE_ID 0x8351 +#define BCM88351_B1_REV_ID ARAD_B1_REV_ID +#define BCM88450_DEVICE_ID 0x8450 +#define BCM88450_B1_REV_ID ARAD_B1_REV_ID +#define BCM88451_DEVICE_ID 0x8451 +#define BCM88451_B1_REV_ID ARAD_B1_REV_ID +#define BCM88550_DEVICE_ID 0x8550 +#define BCM88550_B1_REV_ID ARAD_B0_REV_ID +#define BCM88551_DEVICE_ID 0x8551 +#define BCM88551_B1_REV_ID ARAD_B1_REV_ID +#define BCM88552_DEVICE_ID 0x8552 +#define BCM88552_B1_REV_ID ARAD_B1_REV_ID +#define BCM88651_DEVICE_ID 0x8651 +#define BCM88651_B1_REV_ID ARAD_B1_REV_ID +#define BCM88654_DEVICE_ID 0x8654 +#define BCM88654_B1_REV_ID ARAD_B1_REV_ID + +#define BCM88772_DEVICE_ID 0x8772 +#define BCM88952_DEVICE_ID 0x8952 +#define BCM88772_A1_REV_ID 0x0002 +#define BCM88952_A0_REV_ID 0x0001 +#define BCM88952_A1_REV_ID 0x0002 + +#define PCP_PCI_VENDOR_ID 0x1172 +#define PCP_PCI_DEVICE_ID 0x4 + +#define ACP_PCI_VENDOR_ID 0x10ee +#define ACP_PCI_DEVICE_ID 0x7011 +#define ACP_PCI_REV_ID 0x0001 + +#define PLX9056_DEVICE_ID 0x9056 + +#ifdef BCM_LTSW_SUPPORT +#define BCM56880_DEVICE_ID 0xb880 +#define BCM56880_A0_REV_ID 0x0001 +#define BCM56880_B0_REV_ID 0x0011 +#define BCM56881_DEVICE_ID 0xb881 +#define BCM56881_A0_REV_ID 0x0001 +#define BCM56881_B0_REV_ID 0x0011 +#define BCM56883_DEVICE_ID 0xb883 +#define BCM56883_A0_REV_ID 0x0001 +#define BCM56883_B0_REV_ID 0x0011 +#define BCM56889_DEVICE_ID 0xb889 +#define BCM56889_A0_REV_ID 0x0001 +#define BCM56889_B0_REV_ID 0x0011 + +#define BCM56780_DEVICE_ID 0xb780 +#define BCM56780_A0_REV_ID 0x0001 +#define BCM56782_DEVICE_ID 0xb782 +#define BCM56782_A0_REV_ID 0x0001 +#define BCM56784_DEVICE_ID 0xb784 +#define BCM56784_A0_REV_ID 0x0001 +#define BCM56786_DEVICE_ID 0xb786 +#define BCM56786_A0_REV_ID 0x0001 +#define BCM56788_DEVICE_ID 0xb788 +#define BCM56788_A0_REV_ID 0x0001 +#define BCM56789_DEVICE_ID 0xb789 +#define BCM56789_A0_REV_ID 0x0001 + +#define BCM56990_DEVICE_ID 0xb990 +#define BCM56990_A0_REV_ID 0x0001 +#define BCM56990_B0_REV_ID 0x0011 +#define BCM56992_DEVICE_ID 0xb992 +#define BCM56992_B0_REV_ID 0x0011 + +#define BCM56996_DEVICE_ID 0xb996 +#define BCM56996_A0_REV_ID 0x0001 +#define BCM56997_DEVICE_ID 0xb997 +#define BCM56997_A0_REV_ID 0x0001 +#endif +#endif + diff --git a/platform/broadcom/saibcm-modules/make/Make.config b/platform/broadcom/saibcm-modules/make/Make.config new file mode 100644 index 000000000000..b086aa3aa79b --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.config @@ -0,0 +1,371 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Make.config,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# + +ifneq ($(strip $(override-target)),) +override TARGET=$(override-target) +endif + +export TARGET + +# +# Set up the target name, and the target base variables. +# +# target = The full name of the target such as vxworks-bmw +# targetbase = 1st part of target (e.g. vxworks) +# targetplat = 2nd part of target (e.g. x86) if any; otherwise same as 1st +# +target = ${TARGET} +targetsplt = $(subst -, , ${target}) # change hyphens to spaces +targetbase = $(word 1,${targetsplt}) +targetplat = $(subst ${targetbase}-,,${TARGET}) + +# +# Common configuration for all platforms +# (Additional platform-dependent configurations are in Makefile.xxx) +# + +# +# THIS FILE SHOULD NOT BE MODIFIED LOCALLY, to override, add a file +# $SDK/make/Make.local that sets your local settings, and/or provide +# a path to your settings using the MAKE_LOCAL variable. If +# either of these files exists, their values will override those in this makefile. +# +ifdef MAKE_LOCAL +-include ${MAKE_LOCAL} +endif + +-include ${SDK}/make/Make.local + +ifdef ALL_CHIPS + ESW_CHIPS = 1 +endif # ALL_CHIPS + +# +# By default, turn off the "changing directory" message. +# +MAKEFLAGS += --no-print-directory + +# +# Use gmake by default +# + +include ${SDK}/make/Make.tools +include ${SDK}/make/Makefile.${target} + +# use QUIET=1 to control printing of compilation lines +ifdef QUIET +Q:=@ +else +Q:= +endif + +# +# Suffix to add to the "target" files to allow local builds with different +# flags. Set "target_suffix" to XXX to cause the build to put built objects +# in ${target}${target_suffix}. This allows things like building a debug +# version with different flags. This may also be set in another Makefile. +# + +#target_suffix := + +# +# Optional suffix to add to the build directory and output binary files +# to allow multiple builds to co-exist for various reasons. +# +#chip_suffix := -$(shell echo $(CHIP) | tr A-Z a-z) + +# +# Combined suffixes +# +all_suffix = ${chip_suffix}${target_suffix} + +# +# Default location to place binaries and make depend files for building +# purposes. +# +ifeq "$(HOSTTYPE)" "Windows2000PC" +BLDROOTWITHDRIVE = ${SDK}/build/${target}${all_suffix}${bldroot_suffix} +BLDROOT = ${SDK_NO_DRIVE_NAME}/build/${target}${all_suffix}${bldroot_suffix} +else # ifeq "$(HOSTTYPE)" "Windows2000PC" + +ifndef SDKBUILD +SDKBUILD :=build +endif + +BLDROOT = ${SDK}/${SDKBUILD}/$(if ${BLDCONFIG},${BLDCONFIG}/)${target}${all_suffix}${bldroot_suffix} + +endif # ifeq "$(HOSTTYPE)" "Windows2000PC" + +# This is needed because we cannot include Make.vxworks before Make.config +ifndef DEST_DIR_SUFFIX +export DEST_DIR_SUFFIX :=$(subst $(realpath $(SDK))/systems,,$(realpath $(CURDIR)/$(dir ($(firstword $(MAKEFILE_LIST)))))) +ifeq ($(MAKELEVEL),0) +endif +endif + +ifeq ($(DEST_DIR),) +export DEST_DIR :=${SDK}/${SDKBUILD}$(if ${BLDCONFIG},/${BLDCONFIG})$(DEST_DIR_SUFFIX) +endif + +ifdef LOCALDIR +BLDDIR = ${BLDROOT}/${LOCALDIR} +ifeq "$(HOSTTYPE)" "Windows2000PC" +BLDDIRWITHDRIVE = ${BLDROOTWITHDRIVE}/${LOCALDIR} +endif +else # ifdef LOCALDIR +BLDDIR = ${BLDROOT} +ifeq "$(HOSTTYPE)" "Windows2000PC" +BLDDIRWITHDRIVE = ${BLDROOTWITHDRIVE} +endif +endif # ifdef LOCALDIR + +LIBDIR = ${BLDROOT} + +# +# Export directory, where build objects used by the outside world are +# placed (exported header files, libs, bins) +# +EXPDIR = ${SDK}/export/${target}${all_suffix} + +# +# Standard include paths +# +INCDIR = ${SDK}/include + +# +# Compilation Flags +# +# Flags may be added to (see below) +# + +INCFLAGS = -I${INCDIR} -I${SDK}/systems + +CFLAGS += ${INCFLAGS} +CXXFLAGS += ${INCFLAGS} +CPPFLAGS += ${INCFLAGS} + +CFLAGS += -DSAI_FIXUP -UKCOM_FILTER_MAX -DKCOM_FILTER_MAX=1024 + +# +# Debug #ifdef control +# +# Compiling out #ifdef DEBUG code saves about 1.3% on executable size. +# It is recommended to leave debug enabled when developing applications. +# +ifndef DEBUG_IFDEFS +DEBUG_IFDEFS=TRUE +endif + +ifeq ($(DEBUG_IFDEFS),TRUE) +CFLAGS += -DBROADCOM_DEBUG +CXXFLAGS += -DBROADCOM_DEBUG +CPPFLAGS += -DBROADCOM_DEBUG +endif + +# +# Debug symbol information control +# +ifndef DEBUG_SYMBOLS +DEBUG_SYMBOLS=TRUE +endif + +ifeq ($(DEBUG_SYMBOLS),TRUE) +CFLAGS += -g +CXXFLAGS += -g +CPPFLAGS += -g +endif + +# +# If DEBUG_CFLAGS is set, add its contents to CFLAGS. +# May be useful for setting on the command line or adding to Make.local. +# Example: gmake DEBUG_CFLAGS=-save-temps system.c +# + +ifneq ($(DEBUG_CFLAGS),) +CFLAGS += $(DEBUG_CFLAGS) +CXXFLAGS += $(DEBUG_CFLAGS) +CPPFLAGS += $(DEBUG_CFLAGS) +endif + +# +# Optimization level +# +# Set DEBUG_OPTIMIZE to TRUE (default) to use a normal optimization +# determined by OPTFLAGS_DEFAULT in the platform Makefile. +# Set DEBUG_OPTIMIZE to FALSE to use no optimization, +# strongly recommended when using any debugger. +# Set DEBUG_OPTIMIZE to any other option string to request specific +# optimization flags (for example -O2). +# +ifndef DEBUG_OPTIMIZE +DEBUG_OPTIMIZE=TRUE +endif + +ifeq ($(DEBUG_OPTIMIZE),TRUE) +OPTFLAGS += $(OPTFLAGS_DEFAULT) +else +ifneq ($(DEBUG_OPTIMIZE),FALSE) +OPTFLAGS += $(DEBUG_OPTIMIZE) +endif +endif + +# +# Debug assertion control. +# +# Compiling out assert() saves about 1.1% on executable size, +# however doing so is VERY MUCH discouraged. +# +ifndef DEBUG_ASSERTS +DEBUG_ASSERTS=TRUE +endif + +ifeq ($(DEBUG_ASSERTS),FALSE) +CFLAGS += -DNDEBUG +CXXFLAGS += -DNDEBUG +CPPFLAGS += -DNDEBUG +endif + +# +# GCC pedantic mode. +# +ifeq ($(DEBUG_PEDANTIC),TRUE) +CFGFLAGS += -D__PEDANTIC__ +CFLAGS += --pedantic +CXXFLAGS += --pedantic +endif + +# +# In each directory, build a list of local sources, objects, and headers +# +LSRCS = $(wildcard *.c *.cpp *.s *.cc *.C) +LOBJS = $(addsuffix .o, $(basename ${LSRCS})) +BOBJS = $(addprefix ${BLDDIR}/,${LOBJS}) +LHDRS = $(wildcard *.h *.H) +LDOTIS = $(wildcard *.i) + + +# +# Rule to create object file (build) directory +# + +.PHONY: all install clean distclean + +.PRECIOUS: ${BLDDIR}/.tree + +%/.tree: + @$(ECHO) 'Creating build directory $(dir $@)' + @$(MKDIR) $(dir $@) + @$(ECHO) "Build Directory for ${LOCALDIR} Created" > $@ + +# Rule allowing build through CPP only, creates .E file from .c file. + +%.E: %.c + $Q${CC} -E ${CFLAGS} $< | sed -e '/^ *$$/d' -e p -e d > $@ + +# Rule allowing build through source only, creates .s file from .c file. + +%.s: %.c + $Q${CC} -S ${CFLAGS} $< + +# +# Default Build rules for .c --> .o, leaving the binary in BLDDIR/X.o, +# even if file not built from directory of source. +# +ifeq ($(FAST),1) +${BLDDIR}/%.o: %.c +else +ifdef GENERATE_C_FILES +${BLDDIR}/%.o: %.c +else +${BLDDIR}/%.o: %.c +endif +endif +ifdef QUIET + @${ECHO} Compiling ${LOCALDIR}/$< +endif +ifdef LOCAL_D_FILE + $Q$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< --write-user-dependencies + -@/bin/cp $*.d $(BLDDIR)/$*.d + -@/bin/rm -f $*.d +else + $Q$(CC) -MD -MF $(BLDDIR)/$*.d $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< +endif + @/bin/cp $(BLDDIR)/$*.d $(BLDDIR)/$*.tmp;\ + /bin/sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' \ + < $(BLDDIR)/$*.d >> $(BLDDIR)/$*.tmp; \ + /bin/sed \ + -e 's| \([0-9a-zA-Z]\)| '$(SDK)/$(LOCALDIR)'\/\1|g' \ + -e 's|^\([0-9a-zA-Z]\)|'$(SDK)/$(LOCALDIR)'/\1|g' \ + -e 's| \(\.\.\/\)| '$(SDK)/$(LOCALDIR)'\/\1|g' \ + -e 's|'$(SDK)'|'$$\{SDK\}'|g' \ + -e 's/\w*\/\.\.\/*//g' \ + -e 's/\w*\/\.\.\/*//g' \ + -e 's/\w*\/\.\.\/*//g' \ + < $(BLDDIR)/$*.tmp > $(BLDDIR)/$*.P; \ + /bin/rm -f $(BLDDIR)/$*.d $(BLDDIR)/$*.tmp + +${BLDDIR}/%.o: %.s +ifdef QUIET + @${ECHO} Assembling ${LOCALDIR}/$< +endif + $Q${CC} ${CFLAGS} ${EXTRA_CFLAGS} -c $< -o $@ + +${BLDDIR}/%.o: %.cpp +ifdef QUIET + @${ECHO} Compiling ${LOCALDIR}/$< +endif + $Q${CXX} -c ${CXXFLAGS} -c $< -o $@ + +${BLDDIR}/%.o: %.cc ${BLDDIR}/.tree +ifdef QUIET + @${ECHO} Compiling ${LOCALDIR}/$< +endif + $Q${CXX} -c ${CXXFLAGS} -c $< -o $@ + +# +# Cause "make foo.o" in any subdirectory to put the object in the build +# directory instead of the local directory. +# +%.o: ${BLDDIR}/%.o + @ + +# +# List of directories where built objects live. +# (we are not making the export directories for now) +# +#DIRS = ${BLDDIR} ${EXPDIR}/lib ${EXPDIR}/bin ${EXPDIR}/include +DIRS = ${BLDDIR} + +ifeq (C_COMPILER,$(MAKECMDGOALS)) +C_COMPILER: + @echo $(CC) +endif diff --git a/platform/broadcom/saibcm-modules/make/Make.depend b/platform/broadcom/saibcm-modules/make/Make.depend new file mode 100644 index 000000000000..802f5f4483c2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.depend @@ -0,0 +1,119 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Make.depend,v 1.14 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Default rule to build dependencies. This builds a x.d file for each +# x.c file that describes the dependencies. We then conditionally include +# the generated .d files. +# + +# +# If making 'clean', do not include any .d files. If they are included, +# gmake intrinsically tries to remake them all. +# +ifeq (,$(findstring clean,$(MAKECMDGOALS))) + +ZFS :=$(wildcard *.zf) +ZFC := $(ZFS:.zf=.c) + +ifdef GENERATE_C_FILES +ifndef GEN_INCS +$(error "GEN_INCS was not defined") +endif + +ZF_GEN = ${SDK}/tools/zFrameCodeGen.pl + +# 1=.zf +define ZFS_RULE +$(1:.zf=Console.c) : $(1:.zf=.c) + @echo updated $$@ from $$? + +$(1:.zf=.c) : $(1) $(ZF_GEN) + @$(PERL) $(ZF_GEN) -s -z . -p . -g $1 -t c + @echo generated ${LOCALDIR}/$$@ from $(1) + @mv $$(*F).cx $$@ + @if [ -e $$(*F)Console.cx ] ; then \ + mv $$(*F)Console.cx $$(*F)Console.c; \ + echo Created $$(*F)Console.c ;\ + fi + @if [ -e $$(*F)Console.hx ] ; then \ + echo Created $(GEN_INCS)/$$(*F)Console.hx ;\ + mv $$(*F)Console.hx $(GEN_INCS)/ ; \ + fi + @mv $$(*F).hx $(GEN_INCS)/ +endef + +$(foreach zf,$(ZFS),$(eval $(call ZFS_RULE,$(zf)))) + +${BLDDIR}/%.P : ${BLDDIR}/.tree %.c + +.PHONY: GENFILES +GENFILES: $(ZFC) + +$(BOBJS) : $(ZFC) + +else +# +# Attempt to build the depend files. If it fails, the depend file is +# removed so that it is not included in later builds. +# +${BLDDIR}/%.P : %.c ${BLDDIR}/.tree + @$(ECHO) Dependencies for ${LOCALDIR}/$< + +${BLDDIR}/%.P : %.cc ${BLDDIR}/.tree + @$(ECHO) Dependencies for ${LOCALDIR}/$< + +endif + +# +# If there are C or C++ files in this directory, include the +# depend files for them. +# + +ifeq ($(findstring _COMPILER,$(MAKECMDGOALS))$(findstring variable,$(MAKECMDGOALS)),) +ifneq ($(strip ${LSRCS}),) +ifneq (,$(findstring .o,$(MAKECMDGOALS))) +-include $(addprefix ${BLDDIR}/,$(MAKECMDGOALS:.o=.P)) $(addprefix ${BLDDIR}/,$(MAKECMDGOALS:.o=.sig)) +else +-include $(addprefix ${BLDDIR}/,$(addsuffix .P,$(basename $(LSRCS)))) $(addprefix ${BLDDIR}/,$(addsuffix .sig,$(basename $(LSRCS)))) +endif +endif +endif + +endif # !CLEANING + +clean_d:: +ifdef QUIET + @$(ECHO) Cleaning dependencies for ${LOCALDIR} +endif +ifdef GENERATE_C_FILES + $Q$(RM) $(ZFC:%=$(SDK)/$(LOCALDIR)/%) $(ZFC:%.c=$(SDK)/$(LOCALDIR)/%Console.c) +endif + +clean:: clean_d diff --git a/platform/broadcom/saibcm-modules/make/Make.kernlib b/platform/broadcom/saibcm-modules/make/Make.kernlib new file mode 100644 index 000000000000..94801acd4a69 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.kernlib @@ -0,0 +1,80 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Make.kernlib,v 1.7 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Make rules/targets for handling libraries + +.SECONDARY:: ${BOBJS} + +targetlibsoname = ${lib}.so.${SHAREDLIBVER} +targetlibrealname = ${targetlibsoname} +targetlibso = ${LIBDIR}/${targetlibrealname} + +ifeq ($(TOOLS),Borland) + +LIBSUFFIX=lib + +${LIBDIR}/%.lib: ${BORLAND_BOBJS} + $(RM) $@ + $(FOREACH) -subdir "$(LIBDIR)" \ + "tlib $@ $(foreach obj, $(BORLAND_LOBJS), +-$(obj))" + +else # !Borland + +LIBSUFFIX=a + +${LIBDIR}/%.a: ${BOBJS} +ifdef QUIET + @$(ECHO) Building library $(notdir $@) +endif + $Q$(RM) $@ + $Q$(AR) ${ARFLAGS} $@ $(sort ${BOBJS}) +ifeq ($(LINUX_MAKE_SHARED_LIB),1) +ifeq ($(targetbase),unix) + $(CC) -shared -Wl,-soname,${targetlibsoname} -o ${targetlibso} ${BOBJS} -lc +endif +endif # LINUX_MAKE_SHARED_LIB # +endif # !Borland + +targetlib = ${LIBDIR}/${lib}.${LIBSUFFIX} + +all:: ${BLDDIR}/.tree ${targetlib} + +install:: all + +clean:: +ifdef QUIET + @$(ECHO) Cleaning objects for ${LOCALDIR} and ${lib} +endif + $Q$(RM) ${BOBJS} + $Q$(RM) ${targetlib} + $Q$(RM) ${targetlibso} + +distclean:: clean + diff --git a/platform/broadcom/saibcm-modules/make/Make.lib b/platform/broadcom/saibcm-modules/make/Make.lib new file mode 100644 index 000000000000..ac81cc134f6d --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.lib @@ -0,0 +1,91 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Make.lib,v 1.14 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Make rules/targets for handling libraries + +.SECONDARY:: ${BOBJS} + +BOBJS_FAST = ${BOBJS} +BOBJS_MAKE_CMD = + +ifeq ($(FAST),1) + ifneq ($(strip $(BOBJS)),) + BOBJS_FAST = + BOBJS_ARGS = -j9 + BOBJS_MAKE_CMD = pwd && make LSRUN=$(SDK)/tools/lsrun.pl $(BOBJS_ARGS) ${BOBJS} + endif +endif + +ifeq ($(TOOLS),Borland) + +LIBSUFFIX=lib + +${LIBDIR}/%.lib: ${BORLAND_BOBJS} + $(RM) $@ + $(FOREACH) -subdir "$(LIBDIR)" \ + "tlib $@ $(foreach obj, $(BORLAND_LOBJS), +-$(obj))" + +else # !Borland + +ifeq ($(LINUX_MAKE_SHARED_LIB),1) +LIBSUFFIX=so.${SHAREDLIBVER} +else +LIBSUFFIX=a +endif + +targetlib = ${LIBDIR}/${lib}.${LIBSUFFIX} + +all:: ${BLDDIR}/.tree ${targetlib} + +${LIBDIR}/%.${LIBSUFFIX}: ${BOBJS_FAST} + $(BOBJS_MAKE_CMD) +ifdef QUIET + @$(ECHO) Building library $(notdir $@) +endif + $Q$(RM) $@ +ifeq ($(LINUX_MAKE_SHARED_LIB),1) + $(CC) -shared -Wl,-soname,${lib}.${LIBSUFFIX}${EXTRA_LIB_LDFLAGS} -o ${targetlib} ${BOBJS} -lc +else + $(AR) ${ARFLAGS} $@ $(sort ${BOBJS}) +endif + +endif # !Borland + + +install:: all + +clean:: +ifdef QUIET + @$(ECHO) Cleaning objects for ${LOCALDIR} and ${lib} +endif + $Q$(RM) ${BOBJS} + $Q$(RM) ${targetlib} + +distclean:: clean diff --git a/platform/broadcom/saibcm-modules/make/Make.linux b/platform/broadcom/saibcm-modules/make/Make.linux new file mode 100644 index 000000000000..ad18872a34eb --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.linux @@ -0,0 +1,108 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# +# $Id: Make.linux,v 1.18 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Common make targets for Linux user and kernel builds included by top +# level Linux makefiles +# +# Variables referenced: +# +# LINUX_MAKE_FLAGS +# Additional flags passed to Make +# +# LINUX_MAKE_USER +# Defined: user build +# Undefined: kernel build +# +# LINUX_MAKE_DIR +# Common makefile location, if it is not ../common +# +# + +export DEST_DIR_SUFFIX :=$(subst $(realpath $(SDK))/systems,,$(realpath $(CURDIR)/$(dir ($(firstword $(MAKEFILE_LIST)))))) + +ifeq (,$(kernel_version)) +kernel_version=2_4 +endif + +ifndef LINUX_MAKE_SHARED_LIB +LINUX_MAKE_SHARED_LIB=0 +endif + +ifeq (,$(SHAREDLIBVER)) +SHAREDLIBVER=1 +endif + +ifndef LINUX_MAKE_DIR +ifdef LINUX_MAKE_USER +LINUX_MAKE_DIR := $(SDK)/systems/linux/user/common +else +LINUX_MAKE_DIR := $(SDK)/systems/linux/kernel/common +endif +endif + +ifdef LINUX_MAKE_USER + CMD = $(LINUX_MAKE_FLAGS) -C $(LINUX_MAKE_DIR) \ + platform=$(platform) bldroot_suffix=/$(platform) kernel_version=$(kernel_version) \ + LINUX_MAKE_SHARED_LIB=$(LINUX_MAKE_SHARED_LIB) SHAREDLIBVER=$(SHAREDLIBVER) +else + export LINUX_MAKE_KERNEL := 1 + CMD = $(LINUX_MAKE_FLAGS) -C $(LINUX_MAKE_DIR) \ + platform=$(platform) kernel_version=$(kernel_version) +endif + +ifneq (,$(MIPS_TOOLS_DIR)) + CMD += MIPS_TOOLS_DIR=$(MIPS_TOOLS_DIR) +endif + +ifneq (,$(MIPS_CROSS_COMPILE)) + CMD += MIPS_CROSS_COMPILE=$(MIPS_CROSS_COMPILE) +endif + +ifneq (,$(LINUX_INCLUDE)) + CMD += LINUX_INCLUDE=$(LINUX_INCLUDE) +endif + +# gmake does not understand $(CMD) to be a submake +# options are to +$(CMD) or $(MAKE) $(CMD) +# trying the latter +build: + $(MAKE) $(CMD) + +DELIVER clean C_COMPILER CXX_COMPILER variable mod bcm user issu libopennsa: + $(MAKE) $(CMD) $@ + +clean_d: clean + +distclean: + $(MAKE) $(CMD) $@ + +.PHONY: build clean distclean clean_d DELIVER variable mod bcm user issu + diff --git a/platform/broadcom/saibcm-modules/make/Make.subdirs b/platform/broadcom/saibcm-modules/make/Make.subdirs new file mode 100644 index 000000000000..374d817d212d --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.subdirs @@ -0,0 +1,55 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Make.subdirs,v 1.8 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Make rules/targets for handling subdirectories + +.PHONY: ${subdirs} + +all:: ${subdirs} +ifdef QUIET + @$(ECHO) Subdirectory build for ${subdirs} +endif + +${subdirs}:: + $Q$(MAKE) -C $@ kernel_version=$(kernel_version) LINUX_MAKE_SHARED_LIB=${LINUX_MAKE_SHARED_LIB} SHAREDLIBVER=${SHAREDLIBVER} + +ifeq "$(HOSTTYPE)" "Windows2000PC" +clean clean_d install distclean:: +ifdef QUIET + @$(ECHO) Subdirectory $@ for ${subdirs} +endif + $Q$(FOREACH) "$(subdirs)" "${MAKE} -C ## $@" +else +clean clean_d install distclean:: +ifdef QUIET + @$(ECHO) Subdirectory $@ for ${subdirs} +endif + @(for name in $(subdirs); do $(MAKE) -C $$name $@; done) +endif diff --git a/platform/broadcom/saibcm-modules/make/Make.tools b/platform/broadcom/saibcm-modules/make/Make.tools new file mode 100644 index 000000000000..0d55eb2e653a --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Make.tools @@ -0,0 +1,49 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Make.tools,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +SYSNAME := $(shell uname -s) +HCC ?=/usr/bin/gcc +SED = /bin/sed +COMPRESS = /usr/bin/compress +PERL = /usr/bin/perl +LN = /bin/ln +HOSTTYPE= i386-linux + +# +# Platform Independent +# +MKTOOL = $(PERL) ${SDK}/tools/mktool.pl +RM = $(MKTOOL) -rm +MKDIR = $(MKTOOL) -md +FOREACH = $(MKTOOL) -foreach +CP = $(MKTOOL) -cp +MAKEDEP = $(MKTOOL) -dep +ECHO = $(MKTOOL) -echo +MKBEEP = ${MKTOOL} -beep diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-bmw-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-bmw-2_6 new file mode 100644 index 000000000000..6fa170fb75e6 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-bmw-2_6 @@ -0,0 +1,122 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-bmw-2_6,v 1.20 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Look for custom tools +ifneq (,$(PPC_TOOLS_DIR)) +ifneq (,$(PPC_CROSS_COMPILE)) +override PATH := $(PPC_TOOLS_DIR):$(PATH) +override CROSS_COMPILE := $(PPC_CROSS_COMPILE) +endif +endif + +# Default tools +ifeq (,$(WRS_LINUX_VERSION)) +WRS_LINUX_VERSION=2.0 +endif + +# Default Linux Kernel directory +ifeq (,$(KERNDIR)) + +ifeq (1.4,$(WRS_LINUX_VERSION)) + +KERNDIR := /projects/ntsw-tools/linux/wrslinux_1.4/bcm98245cpci/build/linux-2.6.14-cgl + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE = powerpc-wrs-linux-gnu-603e-glibc_std- +endif + +WRLINUX_BASE=/tools/windriver/linux_ed/1.4/Linux +export WIND_LIC_PROXY = $(WRLINUX_BASE)/setup/x86-linux2/bin +override PATH := $(WRLINUX_BASE)/gnu/3.4.4-wrlinux-1.4/x86-linux2/bin:$(PATH) + +WRS_SYSROOT_PATH := $(WRLINUX_GNU_PATH)/../lib/gcc/powerpc-wrs-linux-gnu/3.4.4/include +else + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE = powerpc-wrs-linux-gnu-ppc_603e-glibc_std- +endif + +KERNDIR:= /projects/ntsw-tools/linux/wrslinux_2.0/bmw/glibc_std/build/linux-2.6.21-standard + +WRLINUX_BASE=/tools/windriver/linux_ed/2.0_GA/Linux + +TOOLCHAIN_EXEC_PREFIX=$(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2 +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_EXEC_PREFIX) +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin + +WRLINUX_GNU_PATH = $(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2/bin + +override PATH := $(TOOLCHAIN_EXEC_PREFIX):$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/powerpc-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) + +export TOOLCHAIN_EXEC_PREFIX TOOLCHAIN_BIN_DIR WIND_LIC_PROXY + +WRS_SYSROOT_PATH := $(WRLINUX_GNU_PATH)/../lib/gcc/powerpc-wrs-linux-gnu/4.1.2/include + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") +endif +endif +endif + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"BMW_MPC8245/PPC603e\" + +ARCH = ppc +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +ifeq (1.4,$(WRS_LINUX_VERSION)) +# From linux/arch/ppc/Makefile + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -fsigned-char -msoft-float -pipe -ffixed-r2 -Wno-uninitialized -mmultiple -mstring +endif + +else +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -m32 -nostdinc -isystem $(WRS_SYSROOT_PATH) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -I$(KERNDIR)/arch/ppc -I$(KERNDIR)/arch/ppc/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -msoft-float -pipe -ffixed-r2 -mmultiple -mno-altivec -mstring -fomit-frame-pointer -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign +endif + +endif +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-gto b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto new file mode 100644 index 000000000000..4a20a99dac69 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto @@ -0,0 +1,127 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-gto-4_4,v 1.42 Broadcom SDK $ +# $Copyright: (c) 2015 Broadcom Corp. +# All Rights Reserved.$ + +# User must select one platform from below. +ifeq (,$(BUILD_PLATFORM)) +BUILD_PLATFORM=POWERPC_LINUX +endif + +# TOOLCHAIN_BASE_DIR Toolchain base directory for GTO devices +# TARGET_ARCHITECTURE Compiler for target architecture +# KERNDIR Kernel directory for iPROC-CMICd devices +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/gto +TARGET_ARCHITECTURE := powerpc-broadcom-linux-gnuspe +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/current + + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := $(TARGET_ARCHITECTURE)- +endif + + +# GTO toolchain +TOOLCHAIN_BIN_DIR := $(TOOLCHAIN_BASE_DIR)/toolchain/host/usr/bin +override PATH := $(TOOLCHAIN_BIN_DIR)/../$(TARGET_ARCHITECTURE)/bin:$(TOOLCHAIN_BIN_DIR):$(PATH) +export TOOLCHAIN_BIN_DIR + + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"GTO_MPC8548\" +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=32 + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +ARCH = powerpc +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + + +# From linux/arch/ppc/Makefile +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +KFLAG_INCLD = $(TOOLCHAIN_BIN_DIR)/../lib/gcc/$(TARGET_ARCHITECTURE)/4.6.4/include + +ifdef BROADCOM_SVK +ifeq ($PLX_PCI2LBUS, 1) +CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE +endif +endif + +ifdef DPP_CHIPS +CFLAGS += -DDUNE_BCM -D__DUNE_LINUX_BCM_CPU_PCP_DMA__ +CFGFLAGS += -DSOC_CM_FUNCTION +endif + +ifdef DFE_CHIPS +CFLAGS += -DDUNE_BCM +CFGFLAGS += -DSOC_CM_FUNCTION +endif + +ifdef SAND_CHIPS +CFLAGS += -D__DUNE_GTO_BCM_CPU__ -D__DUNE_LINUX_BCM_CPU_PCIE__ +endif + +ifdef SHADOW_PLX +CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE -DSHADOW_SVK +endif + +ifdef LTSW_CHIPS +# Default open source target build +OPENSRC_BUILD ?= uclibc_201402_ppc + +# Hardware interface (see $SDKLT/bcma/sys/probe directory) +SYSTEM_INTERFACE ?= ngbde + +# Turn on direct register access if running on real hardware. +ifeq (ngbde,$(SYSTEM_INTERFACE)) +LTSW_ADD_CPPFLAGS += -DBCMDRD_CONFIG_MEMMAP_DIRECT=1 +endif + +export SYSTEM_INTERFACE +endif + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -m32 -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/uapi/linux/version.h -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/powerpc -I$(KERNDIR)/arch/powerpc/include -I$(KERNDIR)/include/asm-powerpc -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -msoft-float -pipe -ffixed-r2 -mmultiple -mno-altivec -funit-at-a-time -Wa,-me500 -fomit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign +endif + +ifneq (,$(findstring TCL,$(FEATURE_LIST))) +#LINK_STATIC = 0 +#export LINK_STATIC +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-4_4 +endif + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-gto-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto-2_6 new file mode 100644 index 000000000000..56085c7a3cdd --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto-2_6 @@ -0,0 +1,270 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-gto-2_6,v 1.42 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# User must select one platform from below.By default WR_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +#BUILD_PLATFORM=ELDK +BUILD_PLATFORM=WR_LINUX +endif + +# Specify the ELDK version you want to use for building SDK. +ifeq (,$(ELDK_VERSION)) +ifeq (ELDK,$(BUILD_PLATFORM)) +ELDK_VERSION=4.0 +endif +endif + +# Specify the KERNEL VERSION you want to use for building SDK. +ifeq (,$(KERN_VER)) +ifeq (ELDK,$(BUILD_PLATFORM)) +KERN_VER=2.6.21.7 +endif +endif + + +# Specify the Windriver Linux version here.For example '2.0' as shown below. +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (,$(WRS_LINUX_VERSION)) +WRS_LINUX_VERSION=2.0 +endif +endif + + +#glibc_small and glibc_std have their own cross-compilation tools and and path for these tools are different as implemented below. To enable glibc_small build, line given below should be uncommented. + +#WRL_GLIBC_SMALL=TRUE + +ifeq (2.0,$(WRS_LINUX_VERSION)) +ifeq ($(WRL_GLIBC_SMALL),TRUE) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := powerpc-wrs-linux-gnu-ppc_e500v2-glibc_small- +endif + +KERNDIR ?=/projects/ntsw-tools/linux/wrslinux_2.0/gto/glibc_small/build/linux-2.6.21-standard + +else + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := powerpc-wrs-linux-gnu-ppc_e500v2-glibc_std- +endif + +KERNDIR ?= /projects/ntsw-tools/linux/wrslinux_2.0/gto/glibc_std/build/linux-2.6.21-standard + +endif + +export WRL_GLIBC_SMALL + +# After this point glibc_std and glibc_small share these flags + +WRLINUX_BASE ?=/tools/windriver/linux_ed/2.0_GA/Linux +TOOLCHAIN_EXEC_PREFIX=$(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2 +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_EXEC_PREFIX) +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin +WRLINUX_GNU_PATH = $(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2/bin +override PATH := $(TOOLCHAIN_EXEC_PREFIX):$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/powerpc-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) +export TOOLCHAIN_EXEC_PREFIX TOOLCHAIN_BIN_DIR WIND_LIC_PROXY +endif + + +ifeq (3.0,$(WRS_LINUX_VERSION)) +ifeq ($(WRL_GLIBC_SMALL),TRUE) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := powerpc-wrs-linux-gnu-ppc_e500v2-glibc_small- +endif + +KERNDIR ?=/projects/ntsw-tools/linux/wrslinux_3.0/gto/bcm98548xmc_30_glibc_small/build/linux-broadcom_bcm98548xmc-standard-build +KERNDIR_STD ?=/projects/ntsw-tools/linux/wrslinux_3.0/gto/bcm98548xmc_30_glibc_small/build/linux + +else + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := powerpc-wrs-linux-gnu-ppc_e500v2-glibc_std- +endif + +KERNDIR ?=/projects/ntsw-tools/linux/wrslinux_3.0/gto/bcm98548xmc_30_glibc_std_debug/build/linux-broadcom_bcm98548xmc-standard-build +KERNDIR_STD ?=/projects/ntsw-tools/linux/wrslinux_3.0/gto/bcm98548xmc_30_glibc_std_debug/build/linux + +endif + +export WRL_GLIBC_SMALL + +# After this point glibc_std and glibc_small share these flags + +WRLINUX_BASE ?=/tools/windriver/linux_ed/3.0/Linux +TOOLCHAIN_EXEC_PREFIX=$(WRLINUX_BASE)/wrlinux-3.0/layers/wrll-toolchain-4.3-85/powerpc/toolchain/x86-linux2 +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_EXEC_PREFIX) +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin +WRLINUX_GNU_PATH = $(WRLINUX_BASE)/wrlinux-3.0/layers/wrll-toolchain-4.3-85/powerpc/toolchain/x86-linux2/bin +override PATH := $(TOOLCHAIN_EXEC_PREFIX):$(KERNDIR_STD)/../../host-cross/bin:$(KERNDIR_STD)/../../host-cross/powerpc-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) +export TOOLCHAIN_EXEC_PREFIX TOOLCHAIN_BIN_DIR WIND_LIC_PROXY + +LINUX_INCLUDE_STD := $(KERNDIR_STD)/include + +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (2.6.21.7, $(KERN_VER)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := ppc_85xx- +endif + +ifeq (4.0, $(ELDK_VERSION)) +override PATH := /tools/eldk/4.0/usr/bin:$(PATH) +else +override PATH := /tools/eldk/4.1/usr/bin:$(PATH) +endif +KERNDIR ?= /projects/ntsw-tools/linux/eldk/gto_eldk/linux-2.6.21.7 +endif +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (2.6.24.4, $(KERN_VER)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := ppc_85xx- +endif + +ifeq (4.0, $(ELDK_VERSION)) +override PATH := /tools/eldk/4.0/usr/bin:$(PATH) +else +override PATH := /tools/eldk/4.1/usr/bin:$(PATH) +endif +KERNDIR ?= /projects/ntsw-tools/linux/eldk/gto_eldk/linux-2.6.24.4 +endif +endif + + +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (2.6.25, $(KERN_VER)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := ppc_85xx- +endif + +ifeq (4.0, $(ELDK_VERSION)) +override PATH := /tools/eldk/4.0/usr/bin:$(PATH) +else +override PATH := /tools/eldk/4.1/usr/bin:$(PATH) +endif +KERNDIR ?= /projects/ntsw-tools/linux/eldk/gto_eldk/linux-2.6.25 +endif +endif + + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"GTO_MPC8548\" +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=32 + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +ARCH = powerpc +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + + +# From linux/arch/ppc/Makefile +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + + +ifeq (,$(KFLAG_INCLD)) +ifeq (4.0,$(ELDK_VERSION)) +ifeq (ELDK,$(BUILD_PLATFORM)) +KFLAG_INCLD = /tools/eldk/4.0/usr/lib/gcc/powerpc-linux/4.0.0/include +endif +endif + +ifeq (4.1,$(ELDK_VERSION)) +ifeq (ELDK,$(BUILD_PLATFORM)) +KFLAG_INCLD = /tools/eldk/4.1/usr/lib/gcc/powerpc-linux/4.0.0/include +endif +endif + +ifeq (2.0,$(WRS_LINUX_VERSION)) +KFLAG_INCLD = $(WRLINUX_GNU_PATH)/../lib/gcc/powerpc-wrs-linux-gnu/4.1.2/include +endif + +ifeq (3.0,$(WRS_LINUX_VERSION)) +KFLAG_INCLD = $(WRLINUX_GNU_PATH)/../lib/gcc/powerpc-wrs-linux-gnu/4.3.2/include +endif +endif + +ifdef BROADCOM_SVK +ifeq ($PLX_PCI2LBUS, 1) +CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE +endif +endif + +ifdef DPP_CHIPS +CFLAGS += -DDUNE_BCM -D__DUNE_LINUX_BCM_CPU_PCP_DMA__ +CFGFLAGS += -DSOC_CM_FUNCTION +endif + +ifdef DFE_CHIPS +CFLAGS += -DDUNE_BCM +CFGFLAGS += -DSOC_CM_FUNCTION +endif + +ifdef SAND_CHIPS +CFLAGS += -D__DUNE_GTO_BCM_CPU__ -D__DUNE_LINUX_BCM_CPU_PCIE__ +endif + +ifdef SHADOW_PLX +CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE -DSHADOW_SVK +endif + +ifeq (,$(KFLAGS)) +#autoconf.h was moved in later kernels +LINUX_AUTOCONF = $(LINUX_INCLUDE)/generated/autoconf.h +ifeq (,$(shell ls $(LINUX_AUTOCONF) 2>/dev/null)) +LINUX_AUTOCONF = $(LINUX_INCLUDE)/linux/autoconf.h +endif + +KFLAGS := -D__KERNEL__ -m32 -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/version.h -include $(LINUX_AUTOCONF) -I$(KERNDIR)/arch/powerpc -I$(KERNDIR)/arch/powerpc -I$(KERNDIR)/arch/powerpc/include -I$(KERNDIR)/include/asm-powerpc -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -msoft-float -pipe -ffixed-r2 -mmultiple -mno-altivec -funit-at-a-time -Wa,-me500 -fomit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign +endif + +#Wind river Linux 3.0 needs addtional flags +ifeq (3.0,$(WRS_LINUX_VERSION)) + +# Use MSI interrupts if kernel is compiled with MSI support. +#CFLAGS += -DBDE_LINUX_USE_MSI_INTERRUPT +KFLAGS += -I$(LINUX_INCLUDE_STD) -I$(KERNDIR_STD)/arch/powerpc -I$(KERNDIR_STD)/arch/powerpc/include -I$(KERNDIR_STD)/include.asm-powerpc -mno-spe +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-gts b/platform/broadcom/saibcm-modules/make/Makefile.linux-gts new file mode 100644 index 000000000000..726dfdf505bd --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-gts @@ -0,0 +1,164 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-xlr-4_19,v 0.1 Broadcom SDK $ +# $Copyright: (c) 2015 Broadcom Corp. +# All Rights Reserved.$ + +# +# XLR system make file. +# +# Most of this was taken from target x86-smp_generic_64-2_6. +# + + +############################################################################# +# this segment is custom and not sourced from any existing makefile # +# (base thanks to http:confluence.broadcom.com/display/NTSWSW/X86+System) # +############################################################################# + +# set up a basic feature list. tcl, etc. # +#ifeq (,$(FEATURE_LIST)) +#FEATURE_LIST = TCL BFD PTP CINT L3 I2C MEM_SCAN EDITLINE BCM_SAL_PROFILE CUSTOMER TEST CHASSIS MSTP RCPU +#endif + +# some basic path variables for tools and kernel source, etc # +export XLR_TOOLS_BASE = /projects/ntsw-tools/linux/xlr-419 +TOOLCHAIN_DIR = $(XLR_TOOLS_BASE)/buildroot/host/usr +# Target machine for EDK-Host defconfig +TARGET_MACHINE ?= x86_64 +KERNDIR = $(XLR_TOOLS_BASE)/kernel/linux + +# set up cross compile prefix, tools dir variables. # +export CROSS_COMPILE := x86_64-broadcom-linux-gnu- +export TOOLS_DIR := $(TOOLCHAIN_DIR)/bin + +# architecture. # +ARCH = x86_64 +TARGET_ARCHITECTURE = x86_64-broadcom-linux-gnu + +# Noisy kernel build +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +# set up paths. # +export LIBRARY_PATH := $(TOOLCHAIN_DIR)/lib:$(TOOLCHAIN_DIR)/lib64:$(LIBRARY_PATH) +export PATH := $(TOOLCHAIN_DIR)/bin:$(KERNDIR):$(PATH) + +# set up SYSINC path # +export SYSINC := $(XLR_TOOLS_BASE)/buildroot/host/usr/lib/gcc/$(TARGET_ARCHITECTURE)/5.4.0/include + + +# CFLAGS/CFGFLAGS # +CFLAGS += -DUSE_LINUX_BDE_MMAP=1 +#CFLAGS += -DBDE_LINUX_USE_MSI_INTERRUPT +CFLAGS += -Wno-error=unused-value +CFLAGS += -Wno-error=unused-but-set-variable +CFLAGS += -Wno-error=maybe-uninitialized +CFLAGS += -Wno-error=cpp +CFLAGS += -Wno-error=aggressive-loop-optimizations +CFLAGS += -Wno-error=array-bounds +CFLAGS += -Wno-error=strict-overflow +CFLAGS += -L$(TOOLCHAIN_DIR)/lib +CFLAGS += -L$(TOOLCHAIN_DIR)/lib64 +#CFLAGS += -Wl,--rpath=/lib64 # may need to set rpath and dynamic-linker path here (and possibly in KLFAGS below) in the future, # +#CFLAGS += -Wl,--dynamic-linker=/lib64/ld-linux-x86-64.so.2 # if we want to build the target executable to be used with shared libs # + +#XLDK-568 fix inline references +CFGFLAGS += -fgnu89-inline + + +# set up KFLAGS appropriately. # +ifeq (,$(KFLAGS)) +KFLAGS := -L$(TOOLCHAIN_DIR)/lib -L$(TOOLCHAIN_DIR)/lib64 -I$(KERNDIR) -lc -nostdinc -isystem $(SYSINC) -Iinclude -I$(KERNDIR)/arch/x86/include -I$(KERNDIR)/arch/x86/include/generated -I$(KERNDIR)/arch/x86/include/generated/uapi -I$(KERNDIR)/arch/x86/include/uapi -I$(KERNDIR)/include -I$(KERNDIR)/include/generated -I$(KERNDIR)/include/generated/uapi -I$(KERNDIR)/include/uapi -include $(KERNDIR)/include/generated/autoconf.h -D__KERNEL__ -DNDEBUG -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Wno-format-security -fno-delete-null-pointer-checks -O2 -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -fstack-protector -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -Wframe-larger-than=1024 -fno-omit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign -fno-dwarf2-cfi-asm -fconserve-stack +endif + + +###################################################################### +# this segment comes from make/Makefile.linux-x86-smp_generic_64-2_6 # +###################################################################### +CFGFLAGS += -DLONGS_ARE_64BITS +CFGFLAGS += -DPTRS_ARE_64BITS +CFGFLAGS += -DSAL_SPL_LOCK_ON_IRQ + + +############################################################## +# This segment comes from make/Makefile.linux-x86-common-2_6 # +############################################################## +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"X86\" +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=32 + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ +-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +ifdef LTSW_CHIPS +# Ensure we do not use an out-of-date libelf.so +ELFUTILS_MIN = 158 +ELFUTILS_DIR ?= /projects/ntsw-tools/lib + +# Default open source target build +OPENSRC_BUILD ?= fed21-x86_64 + +# Hardware interface (see $SDKLT/bcma/sys/probe directory) +SYSTEM_INTERFACE ?= ngbde + +# Support BCMSIM in the same build +ifeq (1,$(BCM_SIM_PATH_SUPPORT)) +EXTRA_SYSTEM_INTERFACES = plisim +endif + +# Turn on direct register access if running on real hardware. +ifeq (ngbde,$(SYSTEM_INTERFACE)) +# Except if using multiple probe interfaces +ifeq (,$(EXTRA_SYSTEM_INTERFACES)) +LTSW_ADD_CPPFLAGS += -DBCMDRD_CONFIG_MEMMAP_DIRECT=1 +endif +endif + +export SYSTEM_INTERFACE +export EXTRA_SYSTEM_INTERFACES +endif + +ifneq ($(targetplat),user) +# By default we exclude -Werror from x86 kernel builds +BCM_CFLAGS = -Wall +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif + + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc new file mode 100644 index 000000000000..fa4911185aa8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc @@ -0,0 +1,115 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-iproc Exp $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ +# Makefile for iproc-CMICd + +# User must select one platform from below.By default ARM_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +BUILD_PLATFORM=ARM_LINUX +endif + +# TOOLCHAIN_BASE_DIR Toolchain base directory for iPROC-CMICd devices +# TARGET_ARCHITECTURE Compiler for target architecture +# KERNDIR Kernel directory for iPROC-CMICd devices +ifeq (BE,$(ENDIAN_MODE)) +#While BE mode is supported, it's use is very limited. We had a specific customer +#request for BE support but don't currently mainstream it. So a 5.1.0 version +#has not been built. Continue using 5.0.3 for any BE support +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk50-be/XLDK32 +TARGET_ARCHITECTURE:=armeb-broadcom-linux-uclibcgnueabi +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux +else +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk51/XLDK32 +TARGET_ARCHITECTURE:= arm-broadcom-linux-uclibcgnueabi +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux +endif + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE:= $(TARGET_ARCHITECTURE)- +endif + +# arm9tools +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/bin +override PATH:=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/$(TARGET_ARCHITECTURE)/bin:$(TOOLCHAIN_BIN_DIR):$(PATH) +LD_LIBRARY_PATH=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/lib +export TOOLCHAIN_BIN_DIR LD_LIBRARY_PATH + +CROSS_GCC_VER ?= $(shell $(TOOLCHAIN_BIN_DIR)/$(CROSS_COMPILE)gcc -dumpversion) + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +ifeq (BE,$(ENDIAN_MODE)) +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +else +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +endif + +CFLAGS += -fno-aggressive-loop-optimizations +CFLAGS += -Wno-error=maybe-uninitialized +CFLAGS += -Wno-error=array-bounds +CFLAGS += -fgnu89-inline +ifeq "$(shell expr `echo $(CROSS_GCC_VER) | cut -f1 -d.` \>= 7)" "1" + CFLAGS += -Wno-error=bool-operation +endif + +CFGFLAGS += -D$(ENDIAN) -DIPROC_CMICD +CFGFLAGS += -DBCM_PLATFORM_STRING=\"IPROC_CMICD\" + +ARCH = arm +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +KFLAG_INCLD ?= $(LD_LIBRARY_PATH)/gcc/$(TARGET_ARCHITECTURE)/$(CROSS_GCC_VER)/include + +ifeq (,$(KFLAGS)) +KFLAGS := -D__LINUX_ARM_ARCH__=7 -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/arm/include -I$(KERNDIR)/arch/arm/include/generated -I$(KERNDIR)/arch/arm/mach-iproc/include -Wall -Wstrict-prototypes -Wno-trigraphs -Os -fno-strict-aliasing -fno-common -marm -mabi=aapcs-linux -fno-pic -pipe -msoft-float -ffreestanding -march=armv7-a -mfpu=vfp -mfloat-abi=softfp -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +KFLAGS += -I$(LINUX_INCLUDE)/uapi -I$(LINUX_INCLUDE)/generated/uapi -I$(KERNDIR)/arch/arm/include/uapi -I$(KERNDIR)/arch/arm/include/generated/uapi +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-3_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-3_14 b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-3_14 new file mode 100644 index 000000000000..8d9f66aa50a0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-3_14 @@ -0,0 +1,114 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-iproc-3_6,v 1.1 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ +# Makefile for iproc-CMICd + +# User must select one platform from below.By default ARM_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +BUILD_PLATFORM=ARM_LINUX +endif + +# TOOLCHAIN_BASE_DIR Toolchain base directory for iPROC-CMICd devices +# TARGET_ARCHITECTURE Compiler for target architecture +# KERNDIR Kernel directory for iPROC-CMICd devices +ifeq (BE,$(ENDIAN_MODE)) +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk37-be/buildroot-2013.11-gcc48-opt-broadcom +TARGET_ARCHITECTURE:=armeb-buildroot-linux-gnueabi +KERNDIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk37-be/XLDK/kernel/linux +else +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk37/XLDK +TARGET_ARCHITECTURE:= arm-broadcom-linux-uclibcgnueabi +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux +endif + + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE:= $(TARGET_ARCHITECTURE)- +endif + +# arm9tools +ifeq (BE,$(ENDIAN_MODE)) +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_BASE_DIR)/host/usr/bin +override PATH:=$(TOOLCHAIN_BASE_DIR)/host/usr/$(TARGET_ARCHITECTURE)/bin:$(TOOLCHAIN_BIN_DIR):$(PATH) +LD_LIBRARY_PATH=$(TOOLCHAIN_BASE_DIR)/host/usr/lib +else +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_BASE_DIR)/buildroot/usr/bin +override PATH:=$(TOOLCHAIN_BASE_DIR)/buildroot/usr/$(TARGET_ARCHITECTURE)/bin:$(TOOLCHAIN_BIN_DIR):$(PATH) +LD_LIBRARY_PATH=$(TOOLCHAIN_BASE_DIR)/buildroot/usr/lib +endif + +export TOOLCHAIN_BIN_DIR LD_LIBRARY_PATH + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +ifeq (BE,$(ENDIAN_MODE)) +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +else +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +endif + +CFGFLAGS += -D$(ENDIAN) -DIPROC_CMICD +CFGFLAGS += -DBCM_PLATFORM_STRING=\"IPROC_CMICD\" + +ARCH = arm +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +ifeq (BE,$(ENDIAN_MODE)) +KFLAG_INCLD ?= $(TOOLCHAIN_BASE_DIR)/host/usr/lib/gcc/$(TARGET_ARCHITECTURE)/4.8.2/include +else +KFLAG_INCLD ?= $(TOOLCHAIN_BASE_DIR)/buildroot/usr/lib/gcc/$(TARGET_ARCHITECTURE)/4.7.2/include +endif + +ifeq (,$(KFLAGS)) +KFLAGS := -D__LINUX_ARM_ARCH__=7 -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/arm/include -I$(KERNDIR)/arch/arm/include/generated -I$(KERNDIR)/arch/arm/mach-northstar/include -I$(KERNDIR)/arch/arm/plat-iproc/include -Wall -Wstrict-prototypes -Wno-trigraphs -Os -fno-strict-aliasing -fno-common -marm -mabi=aapcs-linux -fno-pic -pipe -msoft-float -ffreestanding -march=armv7-a -mfpu=vfp -mfloat-abi=softfp -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +KFLAGS += -I$(LINUX_INCLUDE)/uapi -I$(LINUX_INCLUDE)/generated/uapi -I$(KERNDIR)/arch/arm/include/uapi -I$(KERNDIR)/arch/arm/include/generated/uapi +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-3_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-4_4 b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-4_4 new file mode 100644 index 000000000000..bcef1ff69dd4 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-4_4 @@ -0,0 +1,103 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-iproc Exp $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ +# Makefile for iproc-CMICd + +# User must select one platform from below.By default ARM_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +BUILD_PLATFORM=ARM_LINUX +endif + +# TOOLCHAIN_BASE_DIR Toolchain base directory for iPROC-CMICd devices +# TARGET_ARCHITECTURE Compiler for target architecture +# KERNDIR Kernel directory for iPROC-CMICd devices +ifeq (BE,$(ENDIAN_MODE)) +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk40-be/XLDK +TARGET_ARCHITECTURE:=armeb-broadcom-linux-uclibcgnueabi +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux +else +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk40/XLDK +TARGET_ARCHITECTURE:= arm-broadcom-linux-uclibcgnueabi +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux +endif + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE:= $(TARGET_ARCHITECTURE)- +endif + +# arm9tools +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/bin +override PATH:=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/$(TARGET_ARCHITECTURE)/bin:$(TOOLCHAIN_BIN_DIR):$(PATH) +LD_LIBRARY_PATH=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/lib + +export TOOLCHAIN_BIN_DIR LD_LIBRARY_PATH + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +ifeq (BE,$(ENDIAN_MODE)) +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +else +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +endif + +CFGFLAGS += -D$(ENDIAN) -DIPROC_CMICD +CFGFLAGS += -DBCM_PLATFORM_STRING=\"IPROC_CMICD\" + +ARCH = arm +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +KFLAG_INCLD ?= $(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/lib/gcc/$(TARGET_ARCHITECTURE)/4.9.3/include + +ifeq (,$(KFLAGS)) +KFLAGS := -D__LINUX_ARM_ARCH__=7 -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/arm/include -I$(KERNDIR)/arch/arm/include/generated -I$(KERNDIR)/arch/arm/mach-iproc/include -Wall -Wstrict-prototypes -Wno-trigraphs -Os -fno-strict-aliasing -fno-common -marm -mabi=aapcs-linux -fno-pic -pipe -msoft-float -ffreestanding -march=armv7-a -mfpu=vfp -mfloat-abi=softfp -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +KFLAGS += -I$(LINUX_INCLUDE)/uapi -I$(LINUX_INCLUDE)/generated/uapi -I$(KERNDIR)/arch/arm/include/uapi -I$(KERNDIR)/arch/arm/include/generated/uapi +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-3_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc_64 b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc_64 new file mode 100644 index 000000000000..247da7386370 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc_64 @@ -0,0 +1,117 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-iproc Exp $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ +# Makefile for iproc-CMICd + +# User must select one platform from below.By default ARM_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +BUILD_PLATFORM=ARM_LINUX +endif + +# TOOLCHAIN_BASE_DIR Toolchain base directory for iPROC-CMICd devices +# TARGET_ARCHITECTURE Compiler for target architecture +# KERNDIR Kernel directory for iPROC-CMICd devices +ifeq (BE,$(ENDIAN_MODE)) +#We've never actually built a 64 BE executable. Just here for any future +#customer requirements. +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk51-be/XLDK64 +TARGET_ARCHITECTURE ?= aarch64_be-broadcom-linux-uclibc +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux +else +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk51/XLDK64 +TARGET_ARCHITECTURE ?= aarch64-broadcom-linux-uclibc +KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux +endif + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE:= $(TARGET_ARCHITECTURE)- +endif + +# A72 tools +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/bin +override PATH:=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/$(TARGET_ARCHITECTURE)/bin:$(TOOLCHAIN_BIN_DIR):$(PATH) +LD_LIBRARY_PATH=$(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/lib +export TOOLCHAIN_BIN_DIR LD_LIBRARY_PATH + +CROSS_GCC_VER ?= $(shell $(TOOLCHAIN_BIN_DIR)/$(CROSS_COMPILE)gcc -dumpversion) + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +ifeq (BE,$(ENDIAN_MODE)) +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +else +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +endif + +CFLAGS += -DPTRS_ARE_64BITS -DLONGS_ARE_64BITS +CFLAGS += -DPHYS_ADDRS_ARE_64BITS +CFLAGS += -fno-aggressive-loop-optimizations -fno-strict-overflow +CFLAGS += -Wno-error=maybe-uninitialized +CFLAGS += -Wno-error=array-bounds +CFLAGS += -fgnu89-inline +ifeq "$(shell expr `echo $(CROSS_GCC_VER) | cut -f1 -d.` \>= 7)" "1" + CFLAGS += -Wno-error=bool-operation +endif + + +CFGFLAGS += -D$(ENDIAN) -DIPROC_CMICD +CFGFLAGS += -DBCM_PLATFORM_STRING=\"IPROC_CMICD\" +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=16 + +ARCH = arm64 +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +KFLAG_INCLD ?= $(LD_LIBRARY_PATH)/gcc/$(TARGET_ARCHITECTURE)/$(CROSS_GCC_VER)/include + +ifeq (,$(KFLAGS)) +KFLAGS := -D__LINUX_ARM_ARCH__=8 -D__KERNEL__ -DPTRS_ARE_64BITS -DLONGS_ARE_64BITS -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/arm64/include -I$(KERNDIR)/arch/arm64/include/generated -I$(KERNDIR)/arch/arm64/include/generated/uapi -I$(KERNDIR)/arch/arm64/include/generated/asm -I$(KERNDIR)/include/uapi -I$(KERNDIR)/include/generated/uapi -I$(KERNDIR)/arch/arm64/include/uapi -Wall -Wstrict-prototypes -Wno-trigraphs -Os -fno-strict-aliasing -fno-common -fno-pic -pipe -ffreestanding -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mcmodel=large +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-3_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-jag-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-jag-2_6 new file mode 100644 index 000000000000..1e89cdab2434 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-jag-2_6 @@ -0,0 +1,166 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-jag-2_6,v 1.20 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ + + +# User must select one platform from below.By default WR_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +#BUILD_PLATFORM=ELDK +BUILD_PLATFORM=WR_LINUX +endif + + +# Specify the KERNEL VERSION you want to use for building SDK. +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (,$(KERN_VER)) +KERN_VER=2.6.21.7 +endif +endif + +# Specify the Windriver Linux version here.For example '2.0' as shown below. +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (,$(WRS_LINUX_VERSION)) +WRS_LINUX_VERSION=2.0 +endif +endif + +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (1.4,$(WRS_LINUX_VERSION)) + +KERNDIR := /projects/ntsw-tools/linux/wrslinux_1.4/broadcom_bcm95836cpci_be/build/linux-2.6.14-small + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu- +endif + +export WIND_LIC_PROXY = /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/setup/x86-linux2/bin + +override PATH := /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/gnu/3.4.4-wrlinux-1.4/x86-linux2/bin:$(PATH) +endif + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +#CROSS_COMPILE = mips-wrs-linux-gnu- + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu-mips_softfp-glibc_std- +endif + +KERNDIR:= /projects/ntsw-tools/linux/wrslinux_2.0/jag/glibc_std/build/linux-2.6.21-standard + +endif + +WRLINUX_BASE=/tools/windriver/linux_ed/2.0_GA/Linux + +TOOLCHAIN_BIN_DIR=$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin + +WRLINUX_GNU_PATH=$(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2/bin + +override PATH:=$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) + +WRS_SYSROOT_PATH := $(WRLINUX_GNU_PATH)/../lib/gcc/mips-wrs-linux-gnu/4.1.2/include + +export TOOLCHAIN_BIN_DIR WIND_LIC_PROXY +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (2.6.21.7, $(KERN_VER)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips_4KC- +endif + +override PATH := /tools/eldk/4.1/usr/bin:$(PATH) +KERNDIR ?= /projects/ntsw-tools/linux/eldk/jag-ntswics-eldk/linux-2.6.21.7 +endif +endif + + + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=1 -DSYS_BE_OTHER=0 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"JAG_BCM4704\" + +ARCH = mips +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +ifeq (ELDK,$(BUILD_PLATFORM)) +KFLAG_INCLD = /tools/eldk/4.1/usr/lib/gcc/mips-linux/4.0.0/include/ +endif + +ifeq (1.4,$(WRS_LINUX_VERSION)) +# From linux/arch/mips/Makefile + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -Wall -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -g -G 0 -mno-abicalls -fno-pic -pipe -march=mips32 -Wa,-mips32 -Wa,--trap -funit-at-a-time -mlong-calls -Wundef -finline-limit=100000 -mabi=32 +endif + +#-Wdeclaration-after-statement -Wstrict-prototypes +else + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -nostdinc -isystem $(WRS_SYSROOT_PATH) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -I$(KERNDIR)/arch/mips -I$(KERNDIR)/arch/mips -I$(KERNDIR)/arch/mips/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -ffreestanding -march=mips32 -Wa,-mips32 -Wa,--trap -Iinclude/asm-mips/mach-bcm947xx -Iinclude/asm-mips/mach-generic -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +endif + +endif +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -I$(KERNDIR)/arch/mips -I$(KERNDIR)/arch/mips -I$(KERNDIR)/arch/mips/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -ffreestanding -march=mips32 -Wa,-mips32 -Wa,--trap -Iinclude/asm-mips/mach-bcm947xx -Iinclude/asm-mips/mach-generic -fomit-frame-pointer -g -Wdeclaration-after-statement -mlong-calls +endif + +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif + +ifneq (,$(findstring TCL,$(FEATURE_LIST))) +LINK_STATIC=0 +export LINK_STATIC +endif + + + + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel new file mode 100644 index 000000000000..ccb0c30d2acc --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel @@ -0,0 +1,123 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-kernel,v 1.27 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Configuration Flags + +# Filter out features that cannot or should not be supported in kernel mode +_FEATURE_EXCLUDE_LIST += EDITLINE TCL OOB_RCPU CINT APIMODE DUNE_UI C_UNIT +FEATURE_EXCLUDE_LIST = $(sort $(_FEATURE_EXCLUDE_LIST)) +# Tools + +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +LD = $(CROSS_COMPILE)ld +AR = $(CROSS_COMPILE)ar +ARFLAGS = -rc +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy + +# Handle differences between gcc 2.x and gcc 3.x +gcc-tune-flag = $(shell if ${CC} -dumpspecs | grep mcpu >/dev/null; then echo cpu; else echo tune; fi) + +# Configuration Variables + +# OSType Defines: This defines the type of RTOS or microkernel which you +# are compiling the SAL (and its associated driver) for. New platforms +# can be created by porting the routines (system.c) to your platform and +# adding the define in this Makefile. + +OSTYPE = LINUX + +# +# ORIGIN is used to Optionally select different CFLAGS. It is used to import +# source from other vendors. If SOURCE=Broadcom, then the BCM_ flags are added +# to those passed to the compiler. If SOURCE != Broadcom, BCM_ flags are NOT +# added. +# +# Default specifies Broadcom +# +ifndef ORIGIN + ORIGIN = Broadcom +endif + +# +# STD_{C|CPP|CXX}FLAGS - Standard flags used by ALL compilations +# BCM_{C|CPP|CXX}FLAGS - Flags used for Broadcom source files +# OPT_{C|CPP|CXX}FLAGS - Defined in local make files BEFORE inclusion of +# this Makefile, to define local "Extra" flags. +# + +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) + +CFGFLAGS += -DNO_FILEIO -DNO_CTRL_C -DNO_MEMTUNE + +CFGFLAGS += -D$(OSTYPE) + +# No user sal for the linux kernel +# NO_SAL_APPL=1 + +STD_CFLAGS = $(KFLAGS) $(CFGFLAGS) + + +STD_CPPFLAGS = ${STD_CFLAGS} +STD_CXXFLAGS = ${STD_CFLAGS} + +BCM_CFLAGS = -Wall -Werror +BCM_CPPFLAGS = ${BCM_CFLAGS} +BCM_CXXFLAGS = ${BCM_CFLAGS} + +ifeq (${ORIGIN}, Broadcom) + CFLAGS += ${STD_CFLAGS} ${BCM_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${BCM_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${BCM_CXXFLAGS} ${OPT_CXXFLAGS} +else + CFLAGS += ${STD_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${OPT_CXXFLAGS} +endif + +# +# Ignore pedantic flag for kernel modules +# +ifdef DEBUG_PEDANTIC +DEBUG_PEDANTIC = FALSE +endif + +# +# DEPEND is used as a command to generate the list of dependencies. +# The format of the output must be +# "file.o : file.c a/b/c.h d/e/f.h ...", +# if it is on multiple lines, each line must end in a backslash. +# The output MUST be on standard out. +# +DEPEND = ${CC} -M $(CFLAGS) $< diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-2_6 new file mode 100644 index 000000000000..08461e4c4b7c --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-2_6 @@ -0,0 +1,159 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-kernel-2_6,v 1.40 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Configuration Flags + +# Filter out features that cannot or should not be supported in kernel mode + +_FEATURE_EXCLUDE_LIST += EDITLINE TCL OOB_RCPU CINT APIMODE DUNE_UI C_UNIT +FEATURE_EXCLUDE_LIST = $(sort $(_FEATURE_EXCLUDE_LIST)) + +# Tools + +# Conditionally Replaces DEFAULT var +ifeq ($(origin CC),default) +CC = $(LSRUN) $(CROSS_COMPILE)gcc +endif + +ifeq ($(origin CXX),default) +CXX = $(CROSS_COMPILE)g++ +endif + +ifeq ($(origin LD),default) +LD = $(CROSS_COMPILE)ld +endif + +ifeq ($(origin AR),default) +AR = $(CROSS_COMPILE)ar +endif + +ifeq ($(origin AS),default) +AS = $(CROSS_COMPILE)as +endif + +ifeq ($(origin ARFLAGS),default) + ARFLAGS = -rc +endif + +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy +NM = $(CROSS_COMPILE)nm + +# Handle differences between gcc 2.x and gcc 3.x +gcc-tune-flag = $(shell if ${CC} -dumpspecs | grep mcpu >/dev/null; then echo cpu; else echo tune; fi) + +# Configuration Variables + +# OSType Defines: This defines the type of RTOS or microkernel which you +# are compiling the SAL (and its associated driver) for. New platforms +# can be created by porting the routines (system.c) to your platform and +# adding the define in this Makefile. + +OSTYPE = LINUX + +# +# ORIGIN is used to Optionally select different CFLAGS. It is used to import +# source from other vendors. If SOURCE=Broadcom, then the BCM_ flags are added +# to those passed to the compiler. If SOURCE != Broadcom, BCM_ flags are NOT +# added. +# +# Default specifies Broadcom +# +ifndef ORIGIN + ORIGIN = Broadcom +endif + +# +# STD_{C|CPP|CXX}FLAGS - Standard flags used by ALL compilations +# BCM_{C|CPP|CXX}FLAGS - Flags used for Broadcom source files +# OPT_{C|CPP|CXX}FLAGS - Defined in local make files BEFORE inclusion of +# this Makefile, to define local "Extra" flags. +# + +ifdef IPROC_BUILD +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(KERNDIR)/arch/$(ARCH) +else +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(LINUX_INCLUDE)/asm/gcc \ + -I$(LINUX_INCLUDE)/asm/mach-generic \ + -I$(KERNDIR)/arch/$(ARCH) +endif + +CFGFLAGS += -DNO_FILEIO -DNO_CTRL_C -DNO_MEMTUNE + +CFGFLAGS += -D$(OSTYPE) + +# No user sal for the linux kernel +# NO_SAL_APPL=1 + +STD_CFLAGS = $(KFLAGS) $(CFGFLAGS) + + +STD_CPPFLAGS = ${STD_CFLAGS} +STD_CXXFLAGS = ${STD_CFLAGS} + +ifndef BCM_CFLAGS +BCM_CFLAGS = -Wall -Werror +endif + +BCM_CPPFLAGS = ${BCM_CFLAGS} +BCM_CXXFLAGS = ${BCM_CFLAGS} + +ifeq (${ORIGIN}, Broadcom) + CFLAGS += ${STD_CFLAGS} ${BCM_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${BCM_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${BCM_CXXFLAGS} ${OPT_CXXFLAGS} +else + CFLAGS += ${STD_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${OPT_CXXFLAGS} +endif + +# +# Ignore pedantic flag for kernel modules +# +ifdef DEBUG_PEDANTIC +DEBUG_PEDANTIC = FALSE +endif + +# +# DEPEND is used as a command to generate the list of dependencies. +# The format of the output must be +# "file.o : file.c a/b/c.h d/e/f.h ...", +# if it is on multiple lines, each line must end in a backslash. +# The output MUST be on standard out. +# +DEPEND = ${CC} -M $(CFLAGS) $< diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-3_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-3_6 new file mode 100644 index 000000000000..528522ec4bd3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-3_6 @@ -0,0 +1,159 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-kernel-3_6,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Configuration Flags + +# Filter out features that cannot or should not be supported in kernel mode + +_FEATURE_EXCLUDE_LIST += EDITLINE TCL OOB_RCPU CINT APIMODE DUNE_UI +FEATURE_EXCLUDE_LIST = $(sort $(_FEATURE_EXCLUDE_LIST)) + +# Tools + +# Conditionally Replaces DEFAULT var +ifeq ($(origin CC),default) +CC = $(LSRUN) $(CROSS_COMPILE)gcc +endif + +ifeq ($(origin CXX),default) +CXX = $(CROSS_COMPILE)g++ +endif + +ifeq ($(origin LD),default) +LD = $(CROSS_COMPILE)ld +endif + +ifeq ($(origin AR),default) +AR = $(CROSS_COMPILE)ar +endif + +ifeq ($(origin AS),default) +AS = $(CROSS_COMPILE)as +endif + +ifeq ($(origin ARFLAGS),default) + ARFLAGS = -rc +endif + +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy +NM = $(CROSS_COMPILE)nm + +# Handle differences between gcc 2.x and gcc 3.x +gcc-tune-flag = $(shell if ${CC} -dumpspecs | grep mcpu >/dev/null; then echo cpu; else echo tune; fi) + +# Configuration Variables + +# OSType Defines: This defines the type of RTOS or microkernel which you +# are compiling the SAL (and its associated driver) for. New platforms +# can be created by porting the routines (system.c) to your platform and +# adding the define in this Makefile. + +OSTYPE = LINUX + +# +# ORIGIN is used to Optionally select different CFLAGS. It is used to import +# source from other vendors. If SOURCE=Broadcom, then the BCM_ flags are added +# to those passed to the compiler. If SOURCE != Broadcom, BCM_ flags are NOT +# added. +# +# Default specifies Broadcom +# +ifndef ORIGIN + ORIGIN = Broadcom +endif + +# +# STD_{C|CPP|CXX}FLAGS - Standard flags used by ALL compilations +# BCM_{C|CPP|CXX}FLAGS - Flags used for Broadcom source files +# OPT_{C|CPP|CXX}FLAGS - Defined in local make files BEFORE inclusion of +# this Makefile, to define local "Extra" flags. +# + +ifdef IPROC_BUILD +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(KERNDIR)/arch/$(ARCH) +else +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(LINUX_INCLUDE)/asm/gcc \ + -I$(LINUX_INCLUDE)/asm/mach-generic \ + -I$(KERNDIR)/arch/$(ARCH) +endif + +CFGFLAGS += -DNO_FILEIO -DNO_CTRL_C -DNO_MEMTUNE + +CFGFLAGS += -D$(OSTYPE) + +# No user sal for the linux kernel +# NO_SAL_APPL=1 + +STD_CFLAGS = $(KFLAGS) $(CFGFLAGS) + + +STD_CPPFLAGS = ${STD_CFLAGS} +STD_CXXFLAGS = ${STD_CFLAGS} + +ifndef BCM_CFLAGS +BCM_CFLAGS = -Wall -Werror +endif + +BCM_CPPFLAGS = ${BCM_CFLAGS} +BCM_CXXFLAGS = ${BCM_CFLAGS} + +ifeq (${ORIGIN}, Broadcom) + CFLAGS += ${STD_CFLAGS} ${BCM_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${BCM_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${BCM_CXXFLAGS} ${OPT_CXXFLAGS} +else + CFLAGS += ${STD_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${OPT_CXXFLAGS} +endif + +# +# Ignore pedantic flag for kernel modules +# +ifdef DEBUG_PEDANTIC +DEBUG_PEDANTIC = FALSE +endif + +# +# DEPEND is used as a command to generate the list of dependencies. +# The format of the output must be +# "file.o : file.c a/b/c.h d/e/f.h ...", +# if it is on multiple lines, each line must end in a backslash. +# The output MUST be on standard out. +# +DEPEND = ${CC} -M $(CFLAGS) $< diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-4_4 b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-4_4 new file mode 100644 index 000000000000..c02fc0edd89b --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-4_4 @@ -0,0 +1,168 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-kernel-2_6,v 1.40 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Configuration Flags + +# Filter out features that cannot or should not be supported in kernel mode + +_FEATURE_EXCLUDE_LIST += EDITLINE TCL OOB_RCPU CINT APIMODE DUNE_UI C_UNIT +FEATURE_EXCLUDE_LIST = $(sort $(_FEATURE_EXCLUDE_LIST)) + +# Tools + +# Conditionally Replaces DEFAULT var +ifeq ($(origin CC),default) +CC = $(LSRUN) $(CROSS_COMPILE)gcc +endif + +ifeq ($(origin CXX),default) +CXX = $(CROSS_COMPILE)g++ +endif + +ifeq ($(origin LD),default) +LD = $(CROSS_COMPILE)ld +endif + +ifeq ($(origin AR),default) +AR = $(CROSS_COMPILE)ar +endif + +ifeq ($(origin AS),default) +AS = $(CROSS_COMPILE)as +endif + +ifeq ($(origin ARFLAGS),default) + ARFLAGS = -rc +endif + +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy +NM = $(CROSS_COMPILE)nm + +# Handle differences between gcc 2.x and gcc 3.x +gcc-tune-flag = $(shell if ${CC} -dumpspecs | grep mcpu >/dev/null; then echo cpu; else echo tune; fi) + +# Configuration Variables + +# OSType Defines: This defines the type of RTOS or microkernel which you +# are compiling the SAL (and its associated driver) for. New platforms +# can be created by porting the routines (system.c) to your platform and +# adding the define in this Makefile. +OSTYPE = LINUX + +# +# ORIGIN is used to Optionally select different CFLAGS. It is used to import +# source from other vendors. If SOURCE=Broadcom, then the BCM_ flags are added +# to those passed to the compiler. If SOURCE != Broadcom, BCM_ flags are NOT +# added. +# +# Default specifies Broadcom +# +ifndef ORIGIN + ORIGIN = Broadcom +endif + +# +# STD_{C|CPP|CXX}FLAGS - Standard flags used by ALL compilations +# BCM_{C|CPP|CXX}FLAGS - Flags used for Broadcom source files +# OPT_{C|CPP|CXX}FLAGS - Defined in local make files BEFORE inclusion of +# this Makefile, to define local "Extra" flags. +# +ifdef IPROC_BUILD +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(LINUX_INCLUDE)/uapi \ + -I$(LINUX_INCLUDE)/generated/uapi \ + -I$(KERNDIR)/arch/$(ARCH) \ + -I$(KERNDIR)/arch/$(ARCH)/include/uapi \ + -I$(KERNDIR)/arch/$(ARCH)/include/generated \ + -I$(KERNDIR)/arch/$(ARCH)/include/generated/uapi +else +CFGFLAGS += -I$(SDK)/systems/linux/kernel/modules/include \ + -I$(SDK)/systems/bde/linux/include \ + -I$(LINUX_INCLUDE) \ + -I$(LINUX_INCLUDE)/asm/gcc \ + -I$(LINUX_INCLUDE)/asm/mach-generic \ + -I$(LINUX_INCLUDE)/uapi \ + -I$(LINUX_INCLUDE)/generated/uapi \ + -I$(KERNDIR)/arch/$(ARCH) \ + -I$(KERNDIR)/arch/$(ARCH)/include/uapi \ + -I$(KERNDIR)/arch/$(ARCH)/include/generated \ + -I$(KERNDIR)/arch/$(ARCH)/include/generated/uapi +endif + +CFGFLAGS += -DNO_FILEIO -DNO_CTRL_C -DNO_MEMTUNE + +CFGFLAGS += -D$(OSTYPE) + +# No user sal for the linux kernel +# NO_SAL_APPL=1 + +STD_CFLAGS = $(KFLAGS) $(CFGFLAGS) + + +STD_CPPFLAGS = ${STD_CFLAGS} +STD_CXXFLAGS = ${STD_CFLAGS} + +ifndef BCM_CFLAGS +BCM_CFLAGS = -Wall -Werror +endif + +BCM_CPPFLAGS = ${BCM_CFLAGS} +BCM_CXXFLAGS = ${BCM_CFLAGS} + +ifeq (${ORIGIN}, Broadcom) + CFLAGS += ${STD_CFLAGS} ${BCM_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${BCM_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${BCM_CXXFLAGS} ${OPT_CXXFLAGS} +else + CFLAGS += ${STD_CFLAGS} ${OPT_CFLAGS} + CPPFLAGS += ${STD_CPPFLAGS} ${OPT_CPPFLAGS} + CXXFLAGS += ${STD_CXXFLAGS} ${OPT_CXXFLAGS} +endif + +# +# Ignore pedantic flag for kernel modules +# +ifdef DEBUG_PEDANTIC +DEBUG_PEDANTIC = FALSE +endif + +# +# DEPEND is used as a command to generate the list of dependencies. +# The format of the output must be +# "file.o : file.c a/b/c.h d/e/f.h ...", +# if it is on multiple lines, each line must end in a backslash. +# The output MUST be on standard out. +# +DEPEND = ${CC} -M $(CFLAGS) $< + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule b/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule new file mode 100644 index 000000000000..46caf00f20b5 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule @@ -0,0 +1,99 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-kmodule-3_6,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2006 Broadcom Corp. +# All Rights Reserved.$ + +# Due to the extensive use of driver libraries, the SDK usually builds +# kernel modules from a precompiled object. To avoid various warnings +# and conflicts, the pre-compiled object must be named differently +# from the target module, and the object file itself should be +# appended with "_shipped". + +# If a module exports any symbols, then the exporting source file must +# be compiled within the kernel source tree for correct generation of +# module symbol versions. The symbol source file should be passed to +# this Makefile via the MODULE_SYM variable. + +MODULE := $(MOD_NAME).o +KMODULE := $(MOD_NAME).ko +PRE_COMPILED_OBJ := obj_$(MOD_NAME).o + +obj-m := $(MODULE) +$(MOD_NAME)-y := $(MODULE_SYM) $(PRE_COMPILED_OBJ) + + +ifeq (,$(CROSS_COMPILE)) + +export CROSS_COMPILE + +endif + +SAVE_CFLAGS := ${CFLAGS} + +include $(SDK)/make/Make.config + +PWD := $(shell pwd) + +ifneq ($(ARCH),) +# ELDK does not seem to `automatically' define ARCH where other gccs may +A := ARCH=$(ARCH) +export ARCH +endif + +# Provide an option in case kernel was built in separate directory +KERNBLDDIR ?= $(KERNDIR) + +# Standard SDK include path for building source files that export +# kernel symbols. + +override EXTRA_CFLAGS = -I${SDK}/include -I${SDK}/systems/linux/kernel/modules/include -I${SDK}/systems/bde/linux/include +# +# If, for any reason, the definition of LD was erased, then +# set it, again. +# +ifeq ($(LD),) +LD = $(CROSS_COMPILE)ld +endif + +# The precopiled object needs a dummy command file to avoid warnings +# from the Kbuild scripts (modpost stage). +# Kernels before 2.6.17 do not support external module symbols files, +# so we create a dummy to prevent build failures. + +$(KMODULE): + rm -f *.o *.ko .*.cmd + rm -fr .tmp_versions + ln -s $(LIBDIR)/$(MODULE) $(PRE_COMPILED_OBJ)_shipped + if [ ! -f $(KERNBLDDIR)/NO_SUPRESS ]; then echo "# suppress warning" > .$(PRE_COMPILED_OBJ).cmd; fi + $(MAKE) -C $(KERNBLDDIR) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules + if [ ! -f Module.symvers ]; then echo "old kernel (pre-2.6.17)" > Module.symvers; fi + cp -f $(KMODULE) $(LIBDIR) + rm -f $(PRE_COMPILED_OBJ)_shipped + +EXTRA_CFLAGS = $(CFLAGS) +CFLAGS := ${SAVE_CFLAGS} diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx-2_6 new file mode 100644 index 000000000000..785619f31fd4 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx-2_6 @@ -0,0 +1,56 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-nsx-2_6,v 1.9 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Look for custom tools +ifneq (,$(MIPS_TOOLS_DIR)) +override PATH := $(MIPS_TOOLS_DIR):$(PATH) +endif +ifneq (,$(MIPS_CROSS_COMPILE)) +override CROSS_COMPILE := $(MIPS_CROSS_COMPILE) +endif + +# Default tools +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips2_fp_be- +override PATH := $(PATH):/projects/ntsw-tools/linux/mvista/mvista-4.0/pro/devkit/mips/mips2_fp_be/bin +endif + +# Default Linux Kernel directory +ifeq (,$(KERNDIR)) +KERNDIR := /projects/ntsw-tools/linux/mvista/mvista-4.0-nsx/linux-2.6.10_dev +endif +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"NSX_BCM1125\" + +# From linux/arch/mips/Makefile + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -O2 -fomit-frame-pointer -fno-strict-aliasing -G 0 -mno-abicalls -fno-pic -mips64 -mtune=sb1 -Wa,--trap -pipe -mlong-calls +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx64 b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx64 new file mode 100644 index 000000000000..c4f71995be52 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx64 @@ -0,0 +1,54 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-nsx64,v 1.9 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Look for custom tools +ifneq (,$(MIPS_TOOLS_DIR)) +override PATH := $(MIPS_TOOLS_DIR):$(PATH) +endif +ifneq (,$(MIPS_CROSS_COMPILE)) +override CROSS_COMPILE := $(MIPS_CROSS_COMPILE) +endif + +# Default tools +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips64_fp_be- +override PATH := $(PATH):/projects/ntsw-tools/linux/mvista/mips64_be_tools-3.1/bin +endif + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE = /projects/ntsw-tools/linux/headers/mvl-3.1-nsx64/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) -Wa,-xgot -mips64 -mabi=64 -fno-strict-aliasing -DPTRS_ARE_64BITS -DLONGS_ARE_64BITS +CFGFLAGS += -DBCM_PLATFORM_STRING=\"NSX_BCM1125\" + +# From linux/arch/mips/Makefile + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -O2 -fomit-frame-pointer -fno-strict-aliasing -G 0 -mno-abicalls -fno-pic -mips64 -mabi=64 -mtune=sb1 -Wa,--trap -pipe -mlong-calls +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel +endif + +MODULE_LDFLAGS += -m elf64btsmip diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx_wrl-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx_wrl-2_6 new file mode 100644 index 000000000000..7b549038fd24 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-nsx_wrl-2_6 @@ -0,0 +1,127 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-nsx_wrl-2_6,v 1.15 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ + +ifeq (,$(WRS_LINUX_VERSION)) +WRS_LINUX_VERSION=2.0 +endif + +# Look for custom tools +ifneq (,$(MIPS_TOOLS_DIR)) +ifneq (,$(MIPS_CROSS_COMPILE)) +override PATH := $(MIPS_TOOLS_DIR):$(PATH) +override CROSS_COMPILE := $(MIPS_CROSS_COMPILE) +endif +endif + +# Default Linux Kernel directory +ifeq (,$(KERNDIR)) + +ifeq (1.4,$(WRS_LINUX_VERSION)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu- +endif + +KERNDIR := /projects/ntsw-tools/linux/wrslinux_1.4/broadcom_bcm91125cpci_32_be_glibc_std/build/linux-2.6.14-cgl + +export WIND_LIC_PROXY = /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/setup/x86-linux2/bin +override PATH := /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/gnu/3.4.4-wrlinux-1.4/x86-linux2/bin:$(PATH) +else + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu-mips-glibc_std- +endif + +KERNDIR:= /projects/ntsw-tools/linux/wrslinux_2.0/nsx/glibc_std/build/linux-2.6.21-standard + +WRLINUX_BASE=/tools/windriver/linux_ed/2.0_GA/Linux + +TOOLCHAIN_BIN_DIR=$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin + +WRLINUX_GNU_PATH=$(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2/bin +override PATH:=$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) + +WRS_SYSROOT_PATH := $(WRLINUX_GNU_PATH)/../lib/gcc/mips-wrs-linux-gnu/4.1.2/include + +export TOOLCHAIN_BIN_DIR WIND_LIC_PROXY + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +endif +endif +endif + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"NSX_BCM1125\" + +ARCH = mips +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +ifeq (1.4,$(WRS_LINUX_VERSION)) +# From Linux Kbuild output + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -Iinclude -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -g -G 0 -mno-abicalls -fno-pic -pipe -finline-limit=100000 -mabi=32 -march=sb1 -Wa,-32 -Wa,-march=sb1 -Wa,-mips64 -Wa,--trap -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL -mlong-calls +#-Wdeclaration-after-statement +endif + +else + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -nostdinc -isystem $(WRS_SYSROOT_PATH) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -ffreestanding -march=sb1 -Wa,--trap -Iinclude/asm-mips/mach-sibyte -Iinclude/asm-mips/mach-generic -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +endif + +endif +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif + + +ifneq (,$(findstring TCL,$(FEATURE_LIST))) +LINK_STATIC=0 +export LINK_STATIC +endif + + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor b/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor new file mode 100644 index 000000000000..80c51e782bea --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor @@ -0,0 +1,53 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-raptor,v 1.6 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# Look for custom tools +ifneq (,$(MIPS_TOOLS_DIR)) +override PATH := $(MIPS_TOOLS_DIR):$(PATH) +endif +ifneq (,$(MIPS_CROSS_COMPILE)) +override CROSS_COMPILE := $(MIPS_CROSS_COMPILE) +endif + +# Default tools +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips_fp_be- +override PATH := $(PATH):/projects/ntsw-tools/linux/mvista/mvista-3.1/pro/devkit/mips/fp_be/bin +endif + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE = /projects/ntsw-tools/linux/headers/mvl-3.1-raptor/include +endif + +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=1 -DSYS_BE_OTHER=0 -DBCM_ICS +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"Raptor_BCM56218\" + + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel +endif + +# From linux/arch/mips/Makefile + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -m$(gcc-tune-flag)=r4600 -mips2 -Wa,--trap -mlong-calls +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor-2_6 new file mode 100644 index 000000000000..0bebdf9564c6 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-raptor-2_6 @@ -0,0 +1,172 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# $Id: Makefile.linux-raptor-2_6,v 1.21 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ + + +# User must select one platform from below.By default WR_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +#BUILD_PLATFORM=ELDK +BUILD_PLATFORM=WR_LINUX +endif + + +# Specify the KERNEL VERSION you want to use for building SDK. +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (,$(KERN_VER)) +KERN_VER=2.6.21.7 +endif +endif + +# Specify the Windriver Linux version here.For example '2.0' as shown below. +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (,$(WRS_LINUX_VERSION)) +WRS_LINUX_VERSION=2.0 +endif +endif + + +# Default Linux Kernel directory +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (1.4,$(WRS_LINUX_VERSION)) + +KERNDIR ?= /projects/ntsw-tools/linux/wrslinux_1.4/broadcom_bcm95621x_be/build/linux-2.6.14-small + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu- +endif + +export WIND_LIC_PROXY = /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/setup/x86-linux2/bin + +override PATH := /projects/ntsw-tools/wrs/wrs_linux/GPP_LE_1.4_PPR/gnu/3.4.4-wrlinux-1.4/x86-linux2/bin:$(PATH) +endif + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips-wrs-linux-gnu-mips_softfp-glibc_std- +endif + +KERNDIR ?= /projects/ntsw-tools/linux/wrslinux_2.0/ntswics/glibc_std/build/linux-2.6.21-standard +override PATH:=$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) + +endif + +WRLINUX_BASE=/tools/windriver/linux_ed/2.0_GA/Linux + +TOOLCHAIN_BIN_DIR=$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin +WIND_LIC_PROXY=$(WRLINUX_BASE)/setup/x86-linux2/bin + +WRLINUX_GNU_PATH=$(WRLINUX_BASE)/gnu/4.1-wrlinux-2.0/x86-linux2/bin + +override PATH:=$(KERNDIR)/../../host-cross/bin:$(KERNDIR)/../../host-cross/mips-wrs-linux-gnu/bin:$(WRLINUX_GNU_PATH):$(PATH) + +WRS_SYSROOT_PATH := $(WRLINUX_GNU_PATH)/../lib/gcc/mips-wrs-linux-gnu/4.1.2/include + +export TOOLCHAIN_BIN_DIR WIND_LIC_PROXY + +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) +ifeq (2.6.21.7, $(KERN_VER)) +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE := mips_4KC- +endif +override PATH := /tools/eldk/4.1/usr/bin:$(PATH) +KERNDIR ?= /projects/ntsw-tools/linux/eldk/raptor_eldk/linux-2.6.21.7 +endif +endif + + + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=1 -DSYS_BE_OTHER=0 -DBCM_ICS +ENDIAN = BE_HOST=1 +CFGFLAGS += -D$(ENDIAN) -DRAPTOR +CFGFLAGS += -DBCM_PLATFORM_STRING=\"Raptor_BCM56218\" + + +ARCH = mips +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + + +ifeq (ELDK,$(BUILD_PLATFORM)) +KFLAG_INCLD = /tools/eldk/4.1/usr/lib/gcc/mips-linux/4.0.0/include +endif + + +# From linux/arch/mips/Makefile +ifeq (WR_LINUX,$(BUILD_PLATFORM)) +ifeq (1.4,$(WRS_LINUX_VERSION)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -Wall -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -g -G 0 -mno-abicalls -fno-pic -pipe -march=mips32 -Wa,-mips32 -Wa,--trap -funit-at-a-time -mlong-calls -Wundef -finline-limit=100000 -mabi=32 +endif + +endif + +ifeq (2.0,$(WRS_LINUX_VERSION)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -nostdinc -isystem $(WRS_SYSROOT_PATH) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -I$(KERNDIR)/arch/mips/mach-bcm56218 -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -ffreestanding -march=mips32 -Wa,-mips32 -Wa,--trap -Iinclude/asm-mips/mach-bcm56218 -Iinclude/asm-mips/mach-generic -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls +endif + +endif +endif + +ifeq (ELDK,$(BUILD_PLATFORM)) + +ifeq (,$(KFLAGS)) +KFLAGS := -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/linux/autoconf.h -I$(KERNDIR)/arch/mips/mach-bcm56218 -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -mabi=32 -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -ffreestanding -march=mips32 -Wa,-mips32 -Wa,--trap -Iinclude/asm-mips/mach-bcm56218 -Iinclude/asm-mips/mach-generic -fomit-frame-pointer -g -Wdeclaration-after-statement -mlong-calls +endif + + +endif + + + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif + +ifneq (,$(findstring TCL,$(FEATURE_LIST))) +LINK_STATIC=0 +export LINK_STATIC +endif + + + + + diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-slk b/platform/broadcom/saibcm-modules/make/Makefile.linux-slk new file mode 100644 index 000000000000..656835019a05 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-slk @@ -0,0 +1,161 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-slk-3_14,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2013 Broadcom Corp. +# All Rights Reserved.$ +# Makefile for SLK(BCM957812) + +# User must select one platform from below.By default ARM_LINUX is selected. . +ifeq (,$(BUILD_PLATFORM)) +BUILD_PLATFORM=ARM_LINUX +endif + +# Toolchain base directory for NS2 XMC card +ifeq (BE,$(ENDIAN_MODE)) +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/toolchains/slk/linaro-be +TARGET_ARCHITECTURE:=aarch64_be-linux-gnu +# Target machine for EDK-Host defconfig +TARGET_MACHINE ?= slk_be +KERNDIR ?= /projects/ntsw-tools/linux/iproc_ldks/slk-be/poky/brcm-released-source/git +else +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/toolchains/slk/linaro-le +# Compiler for target architecture +TARGET_ARCHITECTURE:= aarch64-linux-gnu +# Target machine for EDK-Host defconfig +TARGET_MACHINE ?= slk_le +# Kernel directory +KERNDIR ?= /projects/ntsw-tools/linux/iproc_ldks/slk/poky/brcm-released-source/git +endif + +ifeq (,$(CROSS_COMPILE)) +CROSS_COMPILE:= $(TARGET_ARCHITECTURE)- +endif + +# armtools +TOOLCHAIN_BIN_DIR=$(TOOLCHAIN_BASE_DIR)/bin +override PATH:=$(TOOLCHAIN_BIN_DIR):$(PATH) +LD_LIBRARY_PATH=$(TOOLCHAIN_BASE_DIR)/lib + +export TOOLCHAIN_BIN_DIR LD_LIBRARY_PATH + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +ifeq (BE,$(ENDIAN_MODE)) +CFGFLAGS += -DSYS_BE_PIO=1 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=1 +ENDIAN = BE_HOST=1 +else +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +endif + +CFGFLAGS += -D$(ENDIAN) -DBCM958525 +CFGFLAGS += -DBCM_PLATFORM_STRING=\"SLK_BCM957812\" +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=32 +ifeq (1,$(SLK_32BIT)) +CFGFLAGS += -DSAL_BDE_32BIT_USER_64BIT_KERNEL +else +CFGFLAGS += -DPTRS_ARE_64BITS -DLONGS_ARE_64BITS +endif +CFGFLAGS += -DPHYS_ADDRS_ARE_64BITS + +CFLAGS += -Wno-unused-value -Wno-unused-but-set-variable -Wno-sizeof-pointer-memaccess -fno-aggressive-loop-optimizations + +ifdef DPP_CHIPS +CFLAGS += -DDUNE_BCM -D__DUNE_LINUX_BCM_CPU_PCP_DMA__ +CFGFLAGS += -DSOC_CM_FUNCTION +endif + +ifdef DFE_CHIPS +CFLAGS += -DDUNE_BCM +CFGFLAGS += -DSOC_CM_FUNCTION +endif + +ifdef SAND_CHIPS +CFLAGS += -D__DUNE_SLK_BCM_CPU__ -D__DUNE_LINUX_BCM_CPU_PCIE__ +endif + +# Enable cached DMA memory by default +ifeq (,$(SAL_BDE_USE_CACHED_DMA_MEM)) +SAL_BDE_USE_CACHED_DMA_MEM = 1 +endif +ifeq ($(SAL_BDE_USE_CACHED_DMA_MEM),1) +CFGFLAGS += -DSAL_BDE_CACHE_DMA_MEM +endif + +ifeq (1,$(SLK_32BIT)) +ARCH = arm +else +ARCH = arm64 +endif + +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +KFLAG_INCLD = $(TOOLCHAIN_BASE_DIR)/lib/gcc/$(TARGET_ARCHITECTURE)/4.9.2/include + +ifeq (,$(KFLAGS)) +KFLAGS := -D__LINUX_ARM_ARCH__=8 -D__KERNEL__ -DPTRS_ARE_64BITS -DLONGS_ARE_64BITS -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/arm64/include -I$(KERNDIR)/arch/arm64/include/generated -I$(KERNDIR)/arch/arm64/include/generated/asm -I$(KERNDIR)/include/uapi -I$(KERNDIR)/include/generated/uapi -I$(KERNDIR)/arch/arm64/include/uapi -Wall -Wstrict-prototypes -Wno-trigraphs -Os -fno-strict-aliasing -fno-common -fno-pic -pipe -ffreestanding -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign +endif + +ifdef LTSW_CHIPS +# Default open source target build +ifeq (BE,$(ENDIAN_MODE)) +OPENSRC_BUILD ?= linaro_arm64_be +else +OPENSRC_BUILD ?= linaro_arm64_le +endif + +# Hardware interface (see $SDKLT/bcma/sys/probe directory) +SYSTEM_INTERFACE ?= ngbde + +# Turn on direct register access if running on real hardware. +ifeq (ngbde,$(SYSTEM_INTERFACE)) +LTSW_ADD_CPPFLAGS += -DBCMDRD_CONFIG_MEMMAP_DIRECT=1 +endif + +export SYSTEM_INTERFACE +endif + +ifneq ($(targetplat),user) +include ${SDK}/make/Makefile.linux-kernel-3_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 new file mode 100644 index 000000000000..dbd51ee1f627 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 @@ -0,0 +1,55 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-x86-common-2_6,v 1.13 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"X86\" +ifeq (,$(findstring -DSAL_BDE_DMA_MEM_DEFAULT,$(CFGFLAGS))) +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=16 +endif + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ +-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +ifneq ($(targetplat),user) +# By default we exclude -Werror from x86 kernel builds +BCM_CFLAGS = -Wall +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 new file mode 100644 index 000000000000..4b02aa53cda8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 @@ -0,0 +1,62 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-x86-generic-common-2_6,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2008 Broadcom Corp. +# All Rights Reserved.$ + +# Default kernel source directory +ifeq (,$(KERNDIR)) +KERNDIR := /lib/modules/$(shell uname -r)/build +export KERNDIR +endif + +# Default architecture +ifeq (,$(ARCH)) +ARCH = $(shell uname -p) +ifneq (x86_64,$(ARCH)) +ARCH = i386 +endif +endif + +# Noisy kernel build +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE KERNDIR + +# Default Linux include directory +ifeq (,$(LINUX_INCLUDE)) +LINUX_INCLUDE := $(KERNDIR)/include +endif + +# autoconf.h was moved in later kernels +AUTOCONF = $(KERNDIR)/include/generated/autoconf.h +ifeq (,$(shell ls $(AUTOCONF) 2>/dev/null)) +AUTOCONF = $(KERNDIR)/include/linux/autoconf.h +endif + +# gcc system include path +SYSINC = $(shell $(CC) -print-search-dirs | grep install | cut -c 10-)include diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 new file mode 100644 index 000000000000..9df0bee5a774 --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 @@ -0,0 +1,72 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-x86-smp_generic_64-2_6,v 1.5 Broadcom SDK $ +# $Copyright: (c) 2008 Broadcom Corp. +# All Rights Reserved.$ + +CFGFLAGS += -DLONGS_ARE_64BITS +CFGFLAGS += -DPTRS_ARE_64BITS +CFGFLAGS += -DPHYS_ADDRS_ARE_64BITS +CFGFLAGS += -DSAL_SPL_LOCK_ON_IRQ + +include ${SDK}/make/Makefile.linux-x86-generic-common-2_6 + +ifeq (,$(KFLAGS)) +KFLAGS := -nostdinc -isystem $(SYSINC) -I$(KERNDIR)/include -I$(KERNDIR)/arch/x86/include -include $(AUTOCONF) -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -fno-pie -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fno-stack-protector -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign +endif + +ifeq ($(LINUX_MAKE_SHARED_LIB), 1) + KFLAGS += -fPIC -mcmodel=small +else + KFLAGS += -fno-pie -mcmodel=kernel +endif + +LINUX_UAPI = $(LINUX_INCLUDE)/uapi +ifneq (,$(shell ls $(LINUX_UAPI) 2>/dev/null)) +KFLAGS += -I$(LINUX_INCLUDE)/uapi -I$(LINUX_INCLUDE)/generated/uapi -I$(KERNDIR)/arch/x86/include/generated -I$(KERNDIR)/arch/x86/include/uapi -I$(KERNDIR)/arch/x86/include/generated/uapi +endif + +ifdef LTSW_CHIPS +# Ensure we do not use an out-of-date libelf.so +ELFUTILS_MIN = 158 +ELFUTILS_DIR ?= /projects/ntsw-tools/lib + +# Default open source target build +OPENSRC_BUILD ?= x86_64 + +# Hardware interface (see $SDKLT/bcma/sys/probe directory) +SYSTEM_INTERFACE ?= ngbde + +# Turn on direct register access if running on real hardware. +ifeq (ngbde,$(SYSTEM_INTERFACE)) +LTSW_ADD_CPPFLAGS += -DBCMDRD_CONFIG_MEMMAP_DIRECT=1 +endif + +export SYSTEM_INTERFACE +endif + +include ${SDK}/make/Makefile.linux-x86-common-2_6 diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-xlr b/platform/broadcom/saibcm-modules/make/Makefile.linux-xlr new file mode 100644 index 000000000000..726dfdf505bd --- /dev/null +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-xlr @@ -0,0 +1,164 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# $Id: Makefile.linux-xlr-4_19,v 0.1 Broadcom SDK $ +# $Copyright: (c) 2015 Broadcom Corp. +# All Rights Reserved.$ + +# +# XLR system make file. +# +# Most of this was taken from target x86-smp_generic_64-2_6. +# + + +############################################################################# +# this segment is custom and not sourced from any existing makefile # +# (base thanks to http:confluence.broadcom.com/display/NTSWSW/X86+System) # +############################################################################# + +# set up a basic feature list. tcl, etc. # +#ifeq (,$(FEATURE_LIST)) +#FEATURE_LIST = TCL BFD PTP CINT L3 I2C MEM_SCAN EDITLINE BCM_SAL_PROFILE CUSTOMER TEST CHASSIS MSTP RCPU +#endif + +# some basic path variables for tools and kernel source, etc # +export XLR_TOOLS_BASE = /projects/ntsw-tools/linux/xlr-419 +TOOLCHAIN_DIR = $(XLR_TOOLS_BASE)/buildroot/host/usr +# Target machine for EDK-Host defconfig +TARGET_MACHINE ?= x86_64 +KERNDIR = $(XLR_TOOLS_BASE)/kernel/linux + +# set up cross compile prefix, tools dir variables. # +export CROSS_COMPILE := x86_64-broadcom-linux-gnu- +export TOOLS_DIR := $(TOOLCHAIN_DIR)/bin + +# architecture. # +ARCH = x86_64 +TARGET_ARCHITECTURE = x86_64-broadcom-linux-gnu + +# Noisy kernel build +KBUILD_VERBOSE = 1 + +export ARCH KBUILD_VERBOSE + +# set up paths. # +export LIBRARY_PATH := $(TOOLCHAIN_DIR)/lib:$(TOOLCHAIN_DIR)/lib64:$(LIBRARY_PATH) +export PATH := $(TOOLCHAIN_DIR)/bin:$(KERNDIR):$(PATH) + +# set up SYSINC path # +export SYSINC := $(XLR_TOOLS_BASE)/buildroot/host/usr/lib/gcc/$(TARGET_ARCHITECTURE)/5.4.0/include + + +# CFLAGS/CFGFLAGS # +CFLAGS += -DUSE_LINUX_BDE_MMAP=1 +#CFLAGS += -DBDE_LINUX_USE_MSI_INTERRUPT +CFLAGS += -Wno-error=unused-value +CFLAGS += -Wno-error=unused-but-set-variable +CFLAGS += -Wno-error=maybe-uninitialized +CFLAGS += -Wno-error=cpp +CFLAGS += -Wno-error=aggressive-loop-optimizations +CFLAGS += -Wno-error=array-bounds +CFLAGS += -Wno-error=strict-overflow +CFLAGS += -L$(TOOLCHAIN_DIR)/lib +CFLAGS += -L$(TOOLCHAIN_DIR)/lib64 +#CFLAGS += -Wl,--rpath=/lib64 # may need to set rpath and dynamic-linker path here (and possibly in KLFAGS below) in the future, # +#CFLAGS += -Wl,--dynamic-linker=/lib64/ld-linux-x86-64.so.2 # if we want to build the target executable to be used with shared libs # + +#XLDK-568 fix inline references +CFGFLAGS += -fgnu89-inline + + +# set up KFLAGS appropriately. # +ifeq (,$(KFLAGS)) +KFLAGS := -L$(TOOLCHAIN_DIR)/lib -L$(TOOLCHAIN_DIR)/lib64 -I$(KERNDIR) -lc -nostdinc -isystem $(SYSINC) -Iinclude -I$(KERNDIR)/arch/x86/include -I$(KERNDIR)/arch/x86/include/generated -I$(KERNDIR)/arch/x86/include/generated/uapi -I$(KERNDIR)/arch/x86/include/uapi -I$(KERNDIR)/include -I$(KERNDIR)/include/generated -I$(KERNDIR)/include/generated/uapi -I$(KERNDIR)/include/uapi -include $(KERNDIR)/include/generated/autoconf.h -D__KERNEL__ -DNDEBUG -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Wno-format-security -fno-delete-null-pointer-checks -O2 -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -fstack-protector -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -Wframe-larger-than=1024 -fno-omit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign -fno-dwarf2-cfi-asm -fconserve-stack +endif + + +###################################################################### +# this segment comes from make/Makefile.linux-x86-smp_generic_64-2_6 # +###################################################################### +CFGFLAGS += -DLONGS_ARE_64BITS +CFGFLAGS += -DPTRS_ARE_64BITS +CFGFLAGS += -DSAL_SPL_LOCK_ON_IRQ + + +############################################################## +# This segment comes from make/Makefile.linux-x86-common-2_6 # +############################################################## +CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 +ENDIAN = LE_HOST=1 +CFGFLAGS += -D$(ENDIAN) +CFGFLAGS += -DBCM_PLATFORM_STRING=\"X86\" +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=32 + +# Extra variables. +EXTRA_CFLAGS = -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +comma = , +basetarget = $(basename $(notdir $@)) +modname = $(basetarget) + +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ +-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +ifdef LTSW_CHIPS +# Ensure we do not use an out-of-date libelf.so +ELFUTILS_MIN = 158 +ELFUTILS_DIR ?= /projects/ntsw-tools/lib + +# Default open source target build +OPENSRC_BUILD ?= fed21-x86_64 + +# Hardware interface (see $SDKLT/bcma/sys/probe directory) +SYSTEM_INTERFACE ?= ngbde + +# Support BCMSIM in the same build +ifeq (1,$(BCM_SIM_PATH_SUPPORT)) +EXTRA_SYSTEM_INTERFACES = plisim +endif + +# Turn on direct register access if running on real hardware. +ifeq (ngbde,$(SYSTEM_INTERFACE)) +# Except if using multiple probe interfaces +ifeq (,$(EXTRA_SYSTEM_INTERFACES)) +LTSW_ADD_CPPFLAGS += -DBCMDRD_CONFIG_MEMMAP_DIRECT=1 +endif +endif + +export SYSTEM_INTERFACE +export EXTRA_SYSTEM_INTERFACES +endif + +ifneq ($(targetplat),user) +# By default we exclude -Werror from x86 kernel builds +BCM_CFLAGS = -Wall +include ${SDK}/make/Makefile.linux-kernel-2_6 +endif + + diff --git a/platform/broadcom/saibcm-modules/sdklt/LICENSES/gpl-2.0.txt b/platform/broadcom/saibcm-modules/sdklt/LICENSES/gpl-2.0.txt new file mode 100644 index 000000000000..d159169d1050 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/LICENSES/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + + 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/platform/broadcom/saibcm-modules/sdklt/Makefile b/platform/broadcom/saibcm-modules/sdklt/Makefile new file mode 100644 index 000000000000..d6f358c55283 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/Makefile @@ -0,0 +1,83 @@ +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# 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. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +help: + @echo '' + @echo 'Build Linux GPL kernel modules for SDKLT.' + @echo '' + @echo 'Available make targets:' + @echo 'kmod - Build kernel modules' + @echo 'clean - Remove object files' + @echo '' + @echo 'Supported make variables:' + @echo 'KDIR - Linux kernel source directory (mandatory)' + @echo 'CROSS_COPILE - Cross-compiler prefix (optional)' + @echo '' + @echo 'Examples:' + @echo 'make -s KDIR=$$KERNEL/linux kmod' + @echo 'make -s clean' + @echo '' + +ifndef KDIR +nokdir: + @echo 'Error: The $$KDIR environment variable is not set.' + @echo '$$KDIR must point to a configured Linux kernel source tree.' + exit 1 +endif + +export KDIR +export CROSS_COMPILE + +override SDK := $(CURDIR) + +ifeq ($(BUILD_PSAMPLE),1) +PSAMPLE=psample +PSAMPLE_SYMVERS=$(SDK)/linux/psample/Module.symvers +endif + +kmod: bde knet knetcb $(PSAMPLE) + +bde: + $(MAKE) -C $(SDK)/linux/bde SDK=$(SDK) \ + $(TARGET) + ln -sf $(SDK)/linux/bde/*.ko + +knet: bde + $(MAKE) -C $(SDK)/linux/knet SDK=$(SDK) \ + KBUILD_EXTRA_SYMBOLS=$(SDK)/linux/bde/Module.symvers \ + $(TARGET) + ln -sf $(SDK)/linux/knet/*.ko + +knetcb: knet $(PSAMPLE) + $(MAKE) -C $(SDK)/linux/knetcb SDK=$(SDK) \ + KBUILD_EXTRA_SYMBOLS=$(SDK)/linux/knet/Module.symvers \ + KBUILD_EXTRA_SYMBOLS+=$(PSAMPLE_SYMVERS) \ + $(TARGET) + ln -sf $(SDK)/linux/knetcb/*.ko + +ifeq ($(BUILD_PSAMPLE),1) +$(PSAMPLE): + $(MAKE) -C $(SDK)/linux/psample SDK=$(SDK) \ + $(TARGET) + ln -sf $(SDK)/linux/psample/*.ko +endif + +clean: + $(MAKE) kmod TARGET=clean + rm -f *.ko + +.PHONY: help kmod bde knet knetcb $(PSAMPLE) clean diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56780_a0/bcm56780_a0_pdma_attach.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56780_a0/bcm56780_a0_pdma_attach.c new file mode 100644 index 000000000000..e06dcb68bfc8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56780_a0/bcm56780_a0_pdma_attach.c @@ -0,0 +1,38 @@ +/*! \file bcm56780_a0_pdma_attach.c + * + * Initialize PDMA driver resources. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +int +bcm56780_a0_cnet_pdma_attach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_attach(dev); +} + +int +bcm56780_a0_cnet_pdma_detach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_detach(dev); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56880_a0/bcm56880_a0_pdma_attach.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56880_a0/bcm56880_a0_pdma_attach.c new file mode 100644 index 000000000000..9a2152e99ac0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56880_a0/bcm56880_a0_pdma_attach.c @@ -0,0 +1,38 @@ +/*! \file bcm56880_a0_pdma_attach.c + * + * Initialize PDMA driver resources. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +int +bcm56880_a0_cnet_pdma_attach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_attach(dev); +} + +int +bcm56880_a0_cnet_pdma_detach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_detach(dev); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_a0/bcm56990_a0_pdma_attach.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_a0/bcm56990_a0_pdma_attach.c new file mode 100644 index 000000000000..7827ef25de3d --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_a0/bcm56990_a0_pdma_attach.c @@ -0,0 +1,38 @@ +/*! \file bcm56990_a0_pdma_attach.c + * + * Initialize PDMA driver resources. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +int +bcm56990_a0_cnet_pdma_attach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_attach(dev); +} + +int +bcm56990_a0_cnet_pdma_detach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_detach(dev); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_b0/bcm56990_b0_pdma_attach.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_b0/bcm56990_b0_pdma_attach.c new file mode 100644 index 000000000000..e34ae1f0b45c --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_b0/bcm56990_b0_pdma_attach.c @@ -0,0 +1,38 @@ +/*! \file bcm56990_b0_pdma_attach.c + * + * Initialize PDMA driver resources. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +int +bcm56990_b0_cnet_pdma_attach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_attach(dev); +} + +int +bcm56990_b0_cnet_pdma_detach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_detach(dev); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56996_a0/bcm56996_a0_pdma_attach.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56996_a0/bcm56996_a0_pdma_attach.c new file mode 100644 index 000000000000..aab5822f68b7 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56996_a0/bcm56996_a0_pdma_attach.c @@ -0,0 +1,38 @@ +/*! \file bcm56996_a0_pdma_attach.c + * + * Initialize PDMA driver resources. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +int +bcm56996_a0_cnet_pdma_attach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_attach(dev); +} + +int +bcm56996_a0_cnet_pdma_detach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_detach(dev); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_hw.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_hw.c new file mode 100644 index 000000000000..83ce4d11b97f --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_hw.c @@ -0,0 +1,530 @@ +/*! \file bcmcnet_cmicd_pdma_hw.c + * + * Utility routines for handling BCMCNET hardware (CMICd). + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include + +/*! + * Read 32-bit register + */ +static inline void +cmicd_pdma_reg_read32(struct pdma_hw *hw, uint32_t addr, uint32_t *data) +{ + if (hw->dev->dev_read32) { + hw->dev->dev_read32(hw->dev, addr, data); + } else { + DEV_READ32(&hw->dev->ctrl, addr, data); + } +} + +/*! + * Write 32-bit register + */ +static inline void +cmicd_pdma_reg_write32(struct pdma_hw *hw, uint32_t addr, uint32_t data) +{ + if (hw->dev->dev_write32) { + hw->dev->dev_write32(hw->dev, addr, data); + } else { + DEV_WRITE32(&hw->dev->ctrl, addr, data); + } +} + +/*! + * Enable interrupt for a channel + */ +static inline void +cmicd_pdma_intr_enable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask) +{ + uint32_t reg = CMICD_IRQ_STAT(cmc); + + hw->dev->intr_unmask(hw->dev, cmc, chan, reg, mask); +} + +/*! + * Disable interrupt for a channel + */ +static inline void +cmicd_pdma_intr_disable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask) +{ + uint32_t reg = CMICD_IRQ_STAT(cmc); + + hw->dev->intr_mask(hw->dev, cmc, chan, reg, mask); +} + +/*! + * Initialize HW + */ +static int +cmicd_pdma_hw_init(struct pdma_hw *hw) +{ + dev_mode_t mode = DEV_MODE_MAX; + uint32_t val; + + /* Temporarily upgrade work mode to get HW information in VNET mode. */ + if (hw->dev->mode == DEV_MODE_VNET) { + mode = DEV_MODE_VNET; + hw->dev->mode = DEV_MODE_UNET; + } + + /* Release credits to EP. Only do this once when HW is initialized. */ + hw->hdls.reg_rd32(hw, CMICD_EPINTF_RELEASE_CREDITS, &val); + if (!val) { + hw->hdls.reg_wr32(hw, CMICD_EPINTF_RELEASE_CREDITS, 1); + } + + hw->info.name = CMICD_DEV_NAME; + hw->hdls.reg_rd32(hw, CMICD_CMICM_REV_ID, &val); + hw->info.ver_no = val; + hw->hdls.reg_rd32(hw, CMICD_DEV_REV_ID, &val); + hw->info.dev_id = val & 0xffff; + hw->info.rev_id = val >> 16; + hw->info.num_cmcs = CMICD_PDMA_CMC_MAX; + hw->info.cmc_chans = CMICD_PDMA_CMC_CHAN; + hw->info.num_chans = CMICD_PDMA_CMC_MAX * CMICD_PDMA_CMC_CHAN; + hw->info.rx_dcb_size = CMICD_PDMA_DCB_SIZE; + hw->info.tx_dcb_size = CMICD_PDMA_DCB_SIZE; + hw->info.rx_ph_size = 0; + hw->info.tx_ph_size = 0; + + /* Restore work mode to VNET. */ + if (mode == DEV_MODE_VNET) { + hw->dev->mode = DEV_MODE_VNET; + } + + return SHR_E_NONE; +} + +/*! + * Configure HW + */ +static int +cmicd_pdma_hw_config(struct pdma_hw *hw) +{ + struct dev_ctrl *ctrl = &hw->dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + uint32_t val, que_ctrl; + int grp, que; + uint32_t qi; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi]; + grp = rxq->group_id; + que = rxq->chan_id % CMICD_PDMA_CMC_CHAN; + que_ctrl = ctrl->grp[grp].que_ctrl[que]; + + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CMPLT(que)); + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que)); + val = 0; + if (que_ctrl & PDMA_PKT_BYTE_SWAP) { + val |= CMICD_PDMA_PKT_BIG_ENDIAN; + } + if (que_ctrl & PDMA_OTH_BYTE_SWAP) { + val |= CMICD_PDMA_DESC_BIG_ENDIAN; + } + if (!(hw->dev->flags & PDMA_CHAIN_MODE)) { + val |= CMICD_PDMA_CONTINUOUS; + } + val |= CMICD_PDMA_CNTLD_INTR; + val &= ~CMICD_PDMA_DIR; + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val); + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi]; + grp = txq->group_id; + que = txq->chan_id % CMICD_PDMA_CMC_CHAN; + que_ctrl = ctrl->grp[grp].que_ctrl[que]; + + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CMPLT(que)); + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que)); + val = 0; + if (que_ctrl & PDMA_PKT_BYTE_SWAP) { + val |= CMICD_PDMA_PKT_BIG_ENDIAN; + } + if (que_ctrl & PDMA_OTH_BYTE_SWAP) { + val |= CMICD_PDMA_DESC_BIG_ENDIAN; + } + if (!(hw->dev->flags & PDMA_CHAIN_MODE)) { + val |= CMICD_PDMA_CONTINUOUS; + } + val |= CMICD_PDMA_CNTLD_INTR | CMICD_PDMA_DIR; + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val); + } + + return SHR_E_NONE; +} + +/*! + * Reset HW + */ +static int +cmicd_pdma_hw_reset(struct pdma_hw *hw) +{ + int gi, qi; + + for (gi = 0; gi < hw->dev->num_groups; gi++) { + if (!hw->dev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < CMICD_PDMA_CMC_CHAN; qi++) { + if (1 << qi & hw->dev->ctrl.grp[gi].bm_rxq || + 1 << qi & hw->dev->ctrl.grp[gi].bm_txq) { + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(gi, qi), 0); + } + } + } + + return SHR_E_NONE; +} + +/*! + * Start a channel + */ +static int +cmicd_pdma_chan_start(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val); + val |= CMICD_PDMA_ENABLE; + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Stop a channel + */ +static int +cmicd_pdma_chan_stop(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + int retry = CMICD_HW_RETRY_TIMES; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val); + val |= CMICD_PDMA_ENABLE | CMICD_PDMA_ABORT; + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val); + + MEMORY_BARRIER; + + do { + val = ~CMICD_PDMA_ACTIVE(que); + hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT(grp), &val); + } while ((val & CMICD_PDMA_ACTIVE(que)) && (--retry > 0)); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val); + val &= ~(CMICD_PDMA_ENABLE | CMICD_PDMA_ABORT); + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val); + + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Setup a channel + */ +static int +cmicd_pdma_chan_setup(struct pdma_hw *hw, int chan, uint64_t addr) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICD_PDMA_DESC(grp, que), addr); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Set halt point for a channel + */ +static int +cmicd_pdma_chan_goto(struct pdma_hw *hw, int chan, uint64_t addr) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICD_PDMA_DESC_HALT(grp, que), addr); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Clear a channel + */ +static int +cmicd_pdma_chan_clear(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Get interrupt number for a channel + */ +static int +cmicd_pdma_chan_intr_num_get(struct pdma_hw *hw, int chan) +{ + int grp, que, start_num, mask_shift; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + mask_shift = 0; + if (grp > 0) { + mask_shift = CMICD_IRQ_MASK_SHIFT + grp * 32; + } + start_num = CMICD_IRQ_START_NUM + mask_shift; + + return start_num + (que * CMICD_IRQ_NUM_OFFSET); +} + +/*! + * Enable interrupt for a channel + */ +static int +cmicd_pdma_chan_intr_enable(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + cmicd_pdma_intr_enable(hw, grp, que, CMICD_IRQ_DESC_CNTLD(que)); + + return SHR_E_NONE; +} + +/*! + * Disable interrupt for a channel + */ +static int +cmicd_pdma_chan_intr_disable(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + cmicd_pdma_intr_disable(hw, grp, que, CMICD_IRQ_DESC_CNTLD(que)); + + return SHR_E_NONE; +} + +/*! + * Query interrupt status for a channel + * + * In group mode (interrupt processing per CMC), need to query each channel's + * interrupt status. + * + */ +static int +cmicd_pdma_chan_intr_query(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICD_IRQ_STAT(grp), &val); + + return val & CMICD_IRQ_DESC_CNTLD(que); +} + +/*! + * Check interrupt validity for a channel + * + * In group mode (interrupt processing per CMC), need to check each channel's + * interrupt validity based on its interrupt mask. + * + */ +static int +cmicd_pdma_chan_intr_check(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + if (!(hw->dev->ctrl.grp[grp].irq_mask & CMICD_IRQ_DESC_CNTLD(que))) { + return 0; + } + + return cmicd_pdma_chan_intr_query(hw, chan); +} + +/*! + * Coalesce interrupt for a channel + */ +static int +cmicd_pdma_chan_intr_coalesce(struct pdma_hw *hw, int chan, int count, int timer) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + val = CMICD_PDMA_INTR_COAL_ENA | + CMICD_PDMA_INTR_THRESH(count) | + CMICD_PDMA_INTR_TIMER(timer); + hw->hdls.reg_wr32(hw, CMICD_PDMA_INTR_COAL(grp, que), val); + + return SHR_E_NONE; +} + +/*! + * Dump registers for a channel + */ +static int +cmicd_pdma_chan_reg_dump(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val); + CNET_PR("CMIC_CMC%d_CH%d_DMA_CTRL: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_DESC(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_DESC%d: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_CURR_DESC(grp, que), &val); + CNET_PR("CMIC_CMC%d_CH%d_DMA_CURR_DESC: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_DESC_HALT(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_RX0(grp, que), &val); + CNET_PR("CMIC_CMC%d_CH%d_COS_CTRL_RX_0: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_RX1(grp, que), &val); + CNET_PR("CMIC_CMC%d_CH%d_COS_CTRL_RX_1: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_MASK0(grp), &val); + CNET_PR("CMIC_CMC%d_PROGRAMMABLE_COS_MASK0: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_MASK1(grp), &val); + CNET_PR("CMIC_CMC%d_PROGRAMMABLE_COS_MASK1: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_INTR_COAL(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_INTR_COAL: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_RBUF_THRE(grp, que), &val); + CNET_PR("CMIC_CMC%d_CH%d_RXBUF_THRESHOLD_CONFIG: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT(grp), &val); + CNET_PR("CMIC_CMC%d_DMA_STAT: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT_HI(grp), &val); + CNET_PR("CMIC_CMC%d_DMA_STAT_HI: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT_CLR(grp), &val); + CNET_PR("CMIC_CMC%d_DMA_STAT_CLR: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COUNT_RX(grp, que), &val); + CNET_PR("CMIC_CMC%d_PKT_COUNT_CH%d_RXPKT: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COUNT_TX(grp, que), &val); + CNET_PR("CMIC_CMC%d_PKT_COUNT_CH%d_TXPKT: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_IRQ_STAT(grp), &val); + CNET_PR("CMIC_CMC%d_IRQ_STAT0: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_IRQ_PCI_MASK(grp), &val); + CNET_PR("CMIC_CMC%d_PCIE_IRQ_MASK0: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_DEV_REV_ID, &val); + CNET_PR("CMIC_DEV_REV_ID: 0x%08x\n", val); + + hw->hdls.reg_rd32(hw, CMICD_CMICM_REV_ID, &val); + CNET_PR("CMIC_CMICM_REV_ID: 0x%08x\n", val); + + return SHR_E_NONE; +} + +/*! + * Initialize function pointers + */ +int +bcmcnet_cmicd_pdma_hw_hdls_init(struct pdma_hw *hw) +{ + if (!hw) { + return SHR_E_PARAM; + } + + hw->hdls.reg_rd32 = cmicd_pdma_reg_read32; + hw->hdls.reg_wr32 = cmicd_pdma_reg_write32; + hw->hdls.hw_init = cmicd_pdma_hw_init; + hw->hdls.hw_config = cmicd_pdma_hw_config; + hw->hdls.hw_reset = cmicd_pdma_hw_reset; + hw->hdls.chan_start = cmicd_pdma_chan_start; + hw->hdls.chan_stop = cmicd_pdma_chan_stop; + hw->hdls.chan_setup = cmicd_pdma_chan_setup; + hw->hdls.chan_goto = cmicd_pdma_chan_goto; + hw->hdls.chan_clear = cmicd_pdma_chan_clear; + hw->hdls.chan_intr_num_get = cmicd_pdma_chan_intr_num_get; + hw->hdls.chan_intr_enable = cmicd_pdma_chan_intr_enable; + hw->hdls.chan_intr_disable = cmicd_pdma_chan_intr_disable; + hw->hdls.chan_intr_query = cmicd_pdma_chan_intr_query; + hw->hdls.chan_intr_check = cmicd_pdma_chan_intr_check; + hw->hdls.chan_intr_coalesce = cmicd_pdma_chan_intr_coalesce; + hw->hdls.chan_reg_dump = cmicd_pdma_chan_reg_dump; + + return SHR_E_NONE; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_rxtx.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_rxtx.c new file mode 100644 index 000000000000..c4a10e160db9 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_rxtx.c @@ -0,0 +1,1062 @@ +/*! \file bcmcnet_cmicd_pdma_rxtx.c + * + * Utility routines for BCMCNET hardware (CMICd) specific Rx/Tx. + * + * Here are the CMIC specific Rx/Tx routines including DCBs resource allocation + * and clean up, DCBs configuration, Rx buffers allocation, Tx buffers release, + * Rx/Tx packets processing, etc. + * They are shared among all the modes (UNET, KNET, VNET, HNET) and in both of + * user space and kernel space. + * + * The driver uses a ring of DCBs per DMA channel based on Continuous DMA mode. + * The beginning is written to register pointing to the physical address of the + * start of the ring. The ring size is maintained by the driver. A HALT DCB + * physical address is written to DMA register timely to indicate how many DCBs + * can be handled by HW. + * + * When a packet is received, an interrupt is triggered. The handler will go + * through the Rx DCB ring to process the current completed DCB and every + * subsequent DCBs until no one is left. The received packet is processed and + * passed up to the high level SW. After that, a new buffer is allocated and + * the DCB is updated for receiving a new packet. A new HALT DCB is selected + * and its physical address is written to DMA register. + * + * When a packet is transmitted, the driver starts where it left off last time + * in the Tx DCB ring, updates the DCB and writes its physical address to DMA + * register so as to start DMA. Once the transmitting is finished, the handler + * is informed to clean up the buffer based on the work mode. In KNET or HNET + * mode, an interrupt will be triggered. Polling mode is used in CNET or VNET + * mode, the buffers will be cleaned up when the number of dirty DCBs reaches + * a pre-defined threshold. + * + * In VNET and HNET modes, DCB updating between virtual ring and real ring and + * a IOCTL based notification mechanism are involved. The hypervisor in kernel + * emulates the DMA HW behaviors to update DCBs in virtual network and inform + * the handler something happened. Likewise, the hypervisor updates itself real + * DCB ring from the virtual ring to start DMA for transmitting a packet once a + * notification is received from the virtual network. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include +#include + +/*! + * Configure Rx descriptor + */ +static inline void +cmicd_rx_desc_config(struct cmicd_rx_desc *rd, uint32_t addr, uint32_t len) +{ + rd->addr = addr; + rd->md.status = 0; + rd->ctrl = CMICD_DESC_CTRL_CNTLD_INTR | CMICD_DESC_CTRL_CHAIN | + CMICD_DESC_CTRL_LEN(len); +} + +/*! + * Configure Tx descriptor + */ +static inline void +cmicd_tx_desc_config(struct cmicd_tx_desc *td, uint32_t addr, uint32_t len, uint32_t flags) +{ + td->addr = addr; + td->md.status = 0; + td->ctrl = CMICD_DESC_CTRL_CNTLD_INTR | CMICD_DESC_CTRL_CHAIN | + CMICD_DESC_CTRL_FLAGS(flags) | CMICD_DESC_CTRL_LEN(len); +} + +/*! + * Configure Rx reload descriptor + */ +static inline void +cmicd_rx_rldesc_config(struct cmicd_rx_desc *rd, uint32_t addr) +{ + rd->addr = addr; + rd->md.status = 0; + rd->ctrl = CMICD_DESC_CTRL_CNTLD_INTR | CMICD_DESC_CTRL_CHAIN | + CMICD_DESC_CTRL_RELOAD; +} + +/*! + * Configure Tx reload descriptor + */ +static inline void +cmicd_tx_rldesc_config(struct cmicd_tx_desc *td, uint32_t addr) +{ + td->addr = addr; + td->md.status = 0; + td->ctrl = CMICD_DESC_CTRL_CNTLD_INTR | CMICD_DESC_CTRL_CHAIN | + CMICD_DESC_CTRL_RELOAD; +} + +/*! + * Chain Rx descriptor + */ +static inline void +cmicd_rx_desc_chain(struct cmicd_rx_desc *rd, int chain) +{ + if (chain) { + rd->ctrl |= CMICD_DESC_CTRL_CHAIN; + } else { + rd->ctrl &= ~CMICD_DESC_CTRL_CHAIN; + } +} + +/*! + * Chain Tx descriptor + */ +static inline void +cmicd_tx_desc_chain(struct cmicd_tx_desc *td, int chain) +{ + if (chain) { + td->ctrl |= CMICD_DESC_CTRL_CHAIN; + } else { + td->ctrl &= ~CMICD_DESC_CTRL_CHAIN; + } +} + +/*! + * Get unused descriptors in a Rx ring + */ +static inline int +cmicd_pdma_rx_ring_unused(struct pdma_rx_queue *rxq) +{ + /* Leave one descriptor unused so as not to halt */ + return rxq->curr > rxq->halt ? + rxq->curr - rxq->halt - 1 : + rxq->nb_desc + rxq->curr - rxq->halt - 1; +} + +/*! + * Get unused descriptors in a Tx ring + */ +static inline int +cmicd_pdma_tx_ring_unused(struct pdma_tx_queue *txq) +{ + /* Leave one descriptor unused so as not to halt */ + return txq->dirt > txq->curr ? + txq->dirt - txq->curr - 1 : + txq->nb_desc + txq->dirt - txq->curr - 1; +} + +/*! + * Initialize Rx descriptors + */ +static int +cmicd_pdma_rx_desc_init(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + dma_addr_t addr; + uint32_t di; + int rv; + + for (di = 0; di < rxq->nb_desc; di++) { + if (!rxq->pbuf[di].dma) { + /* Allocate pktbuf for ring entry */ + rxq->pbuf[di].adj = CMICD_RX_META_RESV; + rv = bm->rx_buf_alloc(dev, rxq, &rxq->pbuf[di]); + if (SHR_FAILURE(rv)) { + goto cleanup; + } + } + /* Config receive descriptor ring */ + bm->rx_buf_dma(dev, rxq, &rxq->pbuf[di], &addr); + cmicd_rx_desc_config(&ring[di], addr, rxq->buf_size); + if (hw->dev->flags & PDMA_CHAIN_MODE && di == rxq->nb_desc - 1) { + cmicd_rx_desc_chain(&ring[di], 0); + } + } + /* Config the last descriptor in the ring as reload descriptor */ + cmicd_rx_rldesc_config(&ring[di], rxq->ring_addr); + + rxq->curr = 0; + rxq->halt = rxq->state & PDMA_RX_BATCH_REFILL ? 0 : rxq->nb_desc; + + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * di; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + hw->hdls.chan_setup(hw, rxq->chan_id, rxq->ring_addr); + + return SHR_E_NONE; + +cleanup: + for (di = 0; di < rxq->nb_desc; di++) { + if (rxq->pbuf[di].dma) { + bm->rx_buf_free(dev, rxq, &rxq->pbuf[di]); + } + cmicd_rx_desc_config(&ring[di], 0, 0); + } + + CNET_PR("RX: Failed to allocate mem\n"); + + return SHR_E_MEMORY; +} + +/*! + * Cleanup Rx descriptors + */ +static int +cmicd_pdma_rx_desc_clean(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + uint32_t di; + + /* Go through all the descriptors and free pktbuf */ + for (di = 0; di < rxq->nb_desc; di++) { + if (rxq->pbuf[di].dma) { + bm->rx_buf_free(dev, rxq, &rxq->pbuf[di]); + } + cmicd_rx_desc_config(&ring[di], 0, 0); + } + + rxq->curr = 0; + rxq->halt = 0; + + return SHR_E_NONE; +} + +/*! + * Initialize Tx descriptors + */ +static int +cmicd_pdma_tx_desc_init(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + uint32_t di; + + for (di = 0; di < txq->nb_desc; di++) { + if (txq->pbuf[di].dma) { + bm->tx_buf_free(dev, txq, &txq->pbuf[di]); + } + /* Config transmit descriptor ring */ + cmicd_tx_desc_config(&ring[di], 0, 0, 0); + if (hw->dev->flags & PDMA_CHAIN_MODE) { + cmicd_tx_desc_chain(&ring[di], 0); + } + } + /* Config the last descriptor in the ring as reload descriptor */ + cmicd_tx_rldesc_config(&ring[di], txq->ring_addr); + + txq->curr = 0; + txq->dirt = 0; + txq->halt = 0; + + txq->halt_addr = txq->ring_addr; + hw->hdls.chan_goto(hw, txq->chan_id, txq->halt_addr); + hw->hdls.chan_setup(hw, txq->chan_id, txq->ring_addr); + + return SHR_E_NONE; +} + +/*! + * Cleanup Tx descriptors + */ +static int +cmicd_pdma_tx_desc_clean(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + uint32_t di; + + /* Go through all the descriptors and free pktbuf */ + for (di = 0; di < txq->nb_desc; di++) { + if (txq->pbuf[di].dma) { + bm->tx_buf_free(dev, txq, &txq->pbuf[di]); + } + cmicd_tx_desc_config(&ring[di], 0, 0, 0); + } + + txq->curr = 0; + txq->dirt = 0; + txq->halt = 0; + + return SHR_E_NONE; +} + +/*! + * Process Rx vring + */ +static int +cmicd_pdma_rx_vring_process(struct pdma_hw *hw, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + struct pdma_rx_queue *vrxq = NULL; + struct cmicd_rx_desc *vring = NULL; + struct pkt_hdr *pkh = &pbuf->pkb->pkh; + + vrxq = (struct pdma_rx_queue *)dev->ctrl.vnet_rxq[rxq->queue_id]; + vring = (struct cmicd_rx_desc *)vrxq->ring; + if (!vring) { + rxq->stats.dropped++; + return SHR_E_UNAVAIL; + } + + if (vring[vrxq->curr].md.status & CMICD_DESC_STAT_RTX_DONE) { + dev->xnet_wake(dev); + return SHR_E_BUSY; + } + + /* Copy descriptor and packet to vring */ + sal_memcpy(dev->sys_p2v(dev, (uint64_t)vring[vrxq->curr].addr), + &pbuf->pkb->data + pkh->meta_len, pkh->data_len); + sal_memcpy(&vring[vrxq->curr].md, &ring[rxq->curr].md, + sizeof(((struct rx_metadata *)0)->data)); + vring[vrxq->curr].md.status = ring[rxq->curr].md.status; + + MEMORY_BARRIER; + + /* Notify VNET to process if needed */ + if (!vring[(vrxq->curr + vrxq->nb_desc - 1) % vrxq->nb_desc].md.status) { + dev->xnet_wake(dev); + } + vrxq->curr = (vrxq->curr + 1) % vrxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * Refill Rx ring + */ +static int +cmicd_pdma_rx_ring_refill(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + struct pdma_rx_buf *pbuf = NULL; + int unused = cmicd_pdma_rx_ring_unused(rxq); + dma_addr_t addr; + uint32_t halt; + int rv; + + for (halt = rxq->halt; halt < rxq->halt + unused; halt++) { + pbuf = &rxq->pbuf[halt % rxq->nb_desc]; + /* Allocate a new pktbuf */ + if (!bm->rx_buf_avail(dev, rxq, pbuf)) { + rv = bm->rx_buf_alloc(dev, rxq, pbuf); + if (SHR_FAILURE(rv)) { + rxq->halt = halt % rxq->nb_desc; + rxq->stats.nomems++; + goto fail; + } + } + /* Setup the new descriptor */ + bm->rx_buf_dma(dev, rxq, pbuf, &addr); + cmicd_rx_desc_config(&ring[halt % rxq->nb_desc], addr, rxq->buf_size); + if (dev->flags & PDMA_CHAIN_MODE && halt % rxq->nb_desc == rxq->nb_desc - 1) { + cmicd_rx_desc_chain(&ring[halt % rxq->nb_desc], 0); + } + } + + sal_spinlock_lock(rxq->lock); + rxq->halt = halt % rxq->nb_desc; + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; + +fail: + CNET_PR("RX: Failed to allocate mem\n"); + + return SHR_E_MEMORY; +} + +/*! + * \brief Clean Rx ring + * + * \param [in] hw HW structure point. + * \param [in] rxq Rx queue structure point. + * \param [in] budget Polling budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicd_pdma_rx_ring_clean(struct pdma_hw *hw, struct pdma_rx_queue *rxq, int budget) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + struct pdma_rx_buf *pbuf = NULL; + struct pkt_hdr *pkh = NULL; + dma_addr_t addr; + uint32_t stat, curr; + int len, done = 0; + int rv; + + curr = rxq->curr; + while (CMICD_DESC_STAT_DONE(ring[curr].md.status)) { + if (dev->mode == DEV_MODE_VNET && rxq->state & PDMA_RX_QUEUE_XOFF) { + break; + } + if (!(rxq->state & PDMA_RX_BATCH_REFILL) && + !(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * curr; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + rxq->halt = curr; + } + if (done == budget) { + break; + } + + /* Get the current pktbuf to process */ + pbuf = &rxq->pbuf[curr]; + stat = ring[curr].md.status; + len = CMICD_DESC_STAT_LEN(stat); + pkh = bm->rx_buf_get(dev, rxq, pbuf, len); + if (!pkh) { + rxq->stats.nomems++; + goto fail; + } + + /* Setup packet header */ + pkh->data_len = len; + pkh->meta_len = pbuf->adj; + pkh->queue_id = rxq->queue_id; + pkh->attrs = CMICD_DESC_STAT_FLAGS(stat); + sal_memcpy(&pbuf->pkb->data, &ring[curr].md, sizeof(struct rx_metadata)); + + /* Send up the packet */ + rv = dev->pkt_recv(dev, rxq->queue_id, (void *)pbuf->skb); + if (SHR_FAILURE(rv)) { + if (dev->mode == DEV_MODE_HNET && pkh->attrs & PDMA_RX_TO_VNET) { + rv = cmicd_pdma_rx_vring_process(hw, rxq, pbuf); + if (SHR_FAILURE(rv) && rv == SHR_E_BUSY) { + rxq->state |= PDMA_RX_QUEUE_BUSY; + return done; + } + } else { + rxq->stats.dropped++; + } + bm->rx_buf_put(dev, rxq, pbuf, len); + } + + /* Count the packets/bytes */ + rxq->stats.packets++; + rxq->stats.bytes += len; + + /* Count the errors if any */ + if (stat & CMICD_DESC_STAT_ERR_MASK) { + rxq->stats.errors++; + if (stat & CMICD_DESC_STAT_HEAD_ERR) { + rxq->stats.head_errors++; + } + if (stat & CMICD_DESC_STAT_DATA_ERR) { + rxq->stats.data_errors++; + } + if (stat & CMICD_DESC_STAT_CELL_ERR) { + rxq->stats.cell_errors++; + } + } + + /* Setup the new descriptor */ + if (!(rxq->state & PDMA_RX_BATCH_REFILL)) { + if (!bm->rx_buf_avail(dev, rxq, pbuf)) { + rv = bm->rx_buf_alloc(dev, rxq, pbuf); + if (SHR_FAILURE(rv)) { + rxq->stats.nomems++; + goto fail; + } + } + bm->rx_buf_dma(dev, rxq, pbuf, &addr); + cmicd_rx_desc_config(&ring[curr], addr, rxq->buf_size); + if (dev->flags & PDMA_CHAIN_MODE && curr == rxq->nb_desc - 1) { + cmicd_rx_desc_chain(&ring[curr], 0); + } + } else { + cmicd_rx_desc_config(&ring[curr], 0, 0); + } + + /* Notify HNET to process if needed */ + if (dev->mode == DEV_MODE_VNET) { + MEMORY_BARRIER; + if (ring[(curr + rxq->nb_desc - 1) % rxq->nb_desc].md.status) { + dev->xnet_wake(dev); + } + } + + /* Update the indicators */ + if (!(rxq->state & PDMA_RX_BATCH_REFILL) && rxq->halt != curr) { + sal_spinlock_lock(rxq->lock); + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * curr; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + rxq->halt = curr; + } + curr = (curr + 1) % rxq->nb_desc; + sal_spinlock_unlock(rxq->lock); + } else { + curr = (curr + 1) % rxq->nb_desc; + } + rxq->curr = curr; + done++; + + /* Restart DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (curr == 0 && !(rxq->state & PDMA_RX_QUEUE_XOFF)) { + hw->hdls.chan_stop(hw, rxq->chan_id); + hw->hdls.chan_start(hw, rxq->chan_id); + } + } + } + + /* One more poll for chain done in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (curr == rxq->nb_desc - 1 && done) { + done = budget; + } + } + + /* In batching mode, replenish all the unused descriptors */ + if (rxq->state & PDMA_RX_BATCH_REFILL && + cmicd_pdma_rx_ring_unused(rxq) >= (int)rxq->free_thresh) { + cmicd_pdma_rx_ring_refill(hw, rxq); + } + + /* Notify the other side to process */ + if (dev->mode == DEV_MODE_VNET || dev->mode == DEV_MODE_HNET) { + if (done) { + dev->xnet_wake(dev); + } + } + + return done; + +fail: + CNET_PR("RX: Failed to allocate mem\n"); + + return done; +} + +/*! + * Process Tx vring + */ +static int +cmicd_pdma_tx_vring_process(struct pdma_hw *hw, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + struct pdma_tx_queue *vtxq = NULL; + struct cmicd_tx_desc *vring = NULL; + + vtxq = (struct pdma_tx_queue *)dev->ctrl.vnet_txq[txq->queue_id]; + vring = (struct cmicd_tx_desc *)vtxq->ring; + if (!vring) { + return SHR_E_UNAVAIL; + } + + /* Update vring descriptor */ + vring[vtxq->dirt].md.status = ring[txq->dirt].md.status; + pbuf->dma = 0; + + MEMORY_BARRIER; + + /* Notify VNET to process if needed */ + if (!vring[(vtxq->dirt + vtxq->nb_desc - 1) % vtxq->nb_desc].md.status) { + dev->xnet_wake(dev); + } + vtxq->dirt = (vtxq->dirt + 1) % vtxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * \brief Clean Tx ring + * + * \param [in] hw HW structure point. + * \param [in] txq Tx queue structure point. + * \param [in] budget Polling budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicd_pdma_tx_ring_clean(struct pdma_hw *hw, struct pdma_tx_queue *txq, int budget) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + uint32_t dirt, curr; + int done = 0; + + dirt = txq->dirt; + while (txq->pbuf[dirt].dma) { + if (!CMICD_DESC_STAT_DONE(ring[dirt].md.status)) { + break; + } + if (done == budget) { + break; + } + + if (dev->mode == DEV_MODE_HNET && !txq->pbuf[dirt].skb) { + cmicd_pdma_tx_vring_process(hw, txq, &txq->pbuf[dirt]); + } else { + /* Free the done pktbuf */ + bm->tx_buf_free(dev, txq, &txq->pbuf[dirt]); + } + + cmicd_tx_desc_config(&ring[dirt], 0, 0, 0); + + /* Update the indicators */ + dirt = (dirt + 1) % txq->nb_desc; + txq->dirt = dirt; + done++; + + /* Restart DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + sal_spinlock_lock(txq->lock); + curr = txq->curr; + if (dirt == txq->halt && dirt != curr) { + hw->hdls.chan_stop(hw, txq->chan_id); + cmicd_tx_desc_chain(&ring[(curr + txq->nb_desc - 1) % txq->nb_desc], 0); + hw->hdls.chan_setup(hw, txq->chan_id, + txq->ring_addr + sizeof(struct cmicd_tx_desc) * txq->halt); + hw->hdls.chan_start(hw, txq->chan_id); + txq->halt = curr; + } + sal_spinlock_unlock(txq->lock); + } + } + + /* One more poll for chain done in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + sal_spinlock_lock(txq->lock); + if (dirt != txq->halt) { + done = budget; + } + sal_spinlock_unlock(txq->lock); + } + + /* Resume Tx if any */ + sal_spinlock_lock(txq->lock); + if (cmicd_pdma_tx_ring_unused(txq) && txq->state & PDMA_TX_QUEUE_XOFF) { + txq->state &= ~PDMA_TX_QUEUE_XOFF; + sal_spinlock_unlock(txq->lock); + if (dev->tx_resume) { + dev->tx_resume(dev, txq->queue_id); + } else if (!(txq->state & PDMA_TX_QUEUE_POLL)) { + sal_sem_give(txq->sem); + } + return done; + } + sal_spinlock_unlock(txq->lock); + + return done; +} + +/*! + * Dump Rx ring + */ +static int +cmicd_pdma_rx_ring_dump(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + struct cmicd_rx_desc *rd; + uint32_t di; + + CNET_PR("\nRX: queue=%d, chan=%d, curr=%d, halt=%d, halt@%p\n", + rxq->queue_id, rxq->chan_id, rxq->curr, rxq->halt, (void *)&ring[rxq->halt]); + CNET_PR("----------------------------------------------------------------\n"); + for (di = 0; di < rxq->nb_desc + 1; di++) { + rd = &ring[di]; + CNET_PR("DESC[%03d]: (%p)->%08x %08x ... %08x\n", + di, (void *)(unsigned long)(rxq->ring_addr + di * CMICD_PDMA_DCB_SIZE), + rd->addr, rd->ctrl, rd->md.status); + } + + return SHR_E_NONE; +} + +/*! + * Dump Tx ring + */ +static int +cmicd_pdma_tx_ring_dump(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + struct cmicd_tx_desc *td; + uint32_t di; + + CNET_PR("\nTX: queue=%d, chan=%d, curr=%d, dirt=%d, halt@%p\n", + txq->queue_id, txq->chan_id, txq->curr, txq->dirt, (void *)&ring[txq->curr]); + CNET_PR("----------------------------------------------------------------\n"); + for (di = 0; di < txq->nb_desc + 1; di++) { + td = &ring[di]; + CNET_PR("DESC[%03d]: (%p)->%08x %08x ... %08x\n", + di, (void *)(unsigned long)(txq->ring_addr + di * CMICD_PDMA_DCB_SIZE), + td->addr, td->ctrl, td->md.status); + } + + return SHR_E_NONE; +} + +/*! + * Fetch Tx vring + */ +static int +cmicd_pdma_tx_vring_fetch(struct pdma_hw *hw, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + struct pdma_tx_queue *vtxq = NULL; + struct cmicd_tx_desc *vring = NULL; + + vtxq = (struct pdma_tx_queue *)dev->ctrl.vnet_txq[txq->queue_id]; + vring = (struct cmicd_tx_desc *)vtxq->ring; + if (!vring || !CMICD_DESC_CTRL_LEN(vring[vtxq->curr].ctrl)) { + return SHR_E_UNAVAIL; + } + + /* Fetch vring descriptor */ + sal_memcpy(&ring[txq->curr], &vring[vtxq->curr], sizeof(struct cmicd_tx_desc)); + vring[vtxq->curr].ctrl &= ~CMICD_DESC_CTRL_LEN(-1); + + MEMORY_BARRIER; + + pbuf->dma = vring[vtxq->curr].addr; + pbuf->len = CMICD_DESC_CTRL_LEN(ring[txq->curr].ctrl); + vtxq->curr = (vtxq->curr + 1) % vtxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * Check Tx ring + */ +static inline int +cmicd_pdma_tx_ring_check(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + if (cmicd_pdma_tx_ring_unused(txq)) { + return SHR_E_NONE; + } + + sal_spinlock_lock(txq->lock); + if (!cmicd_pdma_tx_ring_unused(txq)) { + txq->state |= PDMA_TX_QUEUE_XOFF; + txq->stats.xoffs++; + sal_spinlock_unlock(txq->lock); + if (hw->dev->tx_suspend) { + hw->dev->tx_suspend(hw->dev, txq->queue_id); + } + return SHR_E_BUSY; + } + sal_spinlock_unlock(txq->lock); + + return SHR_E_NONE; +} + +/*! + * \brief Start packet transmission + * + * \param [in] hw HW structure point. + * \param [in] txq Tx queue structure point. + * \param [in] buf Tx packet buffer. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicd_pdma_pkt_xmit(struct pdma_hw *hw, struct pdma_tx_queue *txq, void *buf) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + struct pdma_tx_buf *pbuf = NULL; + struct pkt_hdr *pkh = NULL; + dma_addr_t addr; + uint32_t curr, flags = 0; + int retry = 5000000; + int rv; + + if (!(txq->state & PDMA_TX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + if (dev->tx_suspend) { + sal_spinlock_lock(txq->mutex); + } else { + sal_sem_take(txq->sem, SAL_SEM_FOREVER); + } + + /* Check Tx resource */ + if (dev->tx_suspend) { + /* Suspend Tx if no resource */ + rv = cmicd_pdma_tx_ring_check(hw, txq); + if (SHR_FAILURE(rv)) { + sal_spinlock_unlock(txq->mutex); + return rv; + } + } else { + /* Abort Tx if a fatal error happened */ + if (txq->state & PDMA_TX_QUEUE_XOFF) { + sal_sem_give(txq->sem); + return SHR_E_RESOURCE; + } + } + + /* Setup the new descriptor */ + curr = txq->curr; + pbuf = &txq->pbuf[curr]; + if (dev->mode == DEV_MODE_HNET && !buf) { + rv = cmicd_pdma_tx_vring_fetch(hw, txq, pbuf); + if (SHR_FAILURE(rv)) { + sal_spinlock_unlock(txq->mutex); + return SHR_E_EMPTY; + } + } else { + pbuf->adj = 0; + pkh = bm->tx_buf_get(dev, txq, pbuf, buf); + if (!pkh) { + txq->stats.dropped++; + if (dev->tx_suspend) { + sal_spinlock_unlock(txq->mutex); + } else { + sal_sem_give(txq->sem); + } + return SHR_E_NONE; + } + bm->tx_buf_dma(dev, txq, pbuf, &addr); + flags |= pkh->attrs & PDMA_TX_HIGIG_PKT ? CMICD_DESC_TX_HIGIG_PKT : 0; + flags |= pkh->attrs & PDMA_TX_PAUSE_PKT ? CMICD_DESC_TX_PAUSE_PKT : 0; + flags |= pkh->attrs & PDMA_TX_PURGE_PKT ? CMICD_DESC_TX_PURGE_PKT : 0; + cmicd_tx_desc_config(&ring[curr], addr, pbuf->len, flags); + if (pkh->meta_len) { + sal_memcpy(&ring[curr].md, &pbuf->pkb->data, sizeof(ring->md.data)); + } + } + + /* Notify HNET to process if needed */ + if (dev->mode == DEV_MODE_VNET) { + MEMORY_BARRIER; + if (!CMICD_DESC_CTRL_LEN(ring[(curr + txq->nb_desc - 1) % txq->nb_desc].ctrl)) { + dev->xnet_wake(dev); + } + } + + /* Update the indicators */ + curr = (curr + 1) % txq->nb_desc; + txq->curr = curr; + + /* Start DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (txq->state & PDMA_TX_QUEUE_POLL) { + do { + rv = cmicd_pdma_tx_ring_clean(hw, txq, txq->nb_desc - 1); + if (rv != (int)txq->nb_desc - 1) { + break; + } + sal_usleep(1); + } while (retry--); + if (retry <= 0) { + CNET_PR("Last Tx could not be done in given time\n"); + } + } + sal_spinlock_lock(txq->lock); + if (txq->dirt == txq->halt && txq->dirt != curr) { + hw->hdls.chan_stop(hw, txq->chan_id); + cmicd_tx_desc_chain(&ring[(curr + txq->nb_desc - 1) % txq->nb_desc], 0); + hw->hdls.chan_setup(hw, txq->chan_id, + txq->ring_addr + sizeof(struct cmicd_tx_desc) * txq->halt); + hw->hdls.chan_start(hw, txq->chan_id); + txq->halt = curr; + } + sal_spinlock_unlock(txq->lock); + } + + /* Kick off DMA */ + txq->halt_addr = txq->ring_addr + sizeof(struct cmicd_tx_desc) * curr; + hw->hdls.chan_goto(hw, txq->chan_id, txq->halt_addr); + + /* Count the packets/bytes */ + txq->stats.packets++; + txq->stats.bytes += pbuf->len; + + /* Clean up ring if in polling mode */ + if (txq->state & PDMA_TX_QUEUE_POLL && + cmicd_pdma_tx_ring_unused(txq) <= (int)txq->free_thresh) { + cmicd_pdma_tx_ring_clean(hw, txq, txq->nb_desc - txq->free_thresh); + } + + /* Suspend Tx if no resource */ + rv = cmicd_pdma_tx_ring_check(hw, txq); + if (SHR_FAILURE(rv)) { + if (dev->mode == DEV_MODE_VNET) { + dev->xnet_wake(dev); + } + + if (txq->state & PDMA_TX_QUEUE_POLL) { + /* In polling mode, must wait till the ring is available */ + do { + cmicd_pdma_tx_ring_clean(hw, txq, txq->free_thresh); + if (!(txq->state & PDMA_TX_QUEUE_XOFF)) { + break; + } + sal_usleep(1); + } while (retry--); + if (retry <= 0) { + CNET_PR("Fatal error: Tx ring is full, packets have not been transmitted for 5 seconds\n"); + if (!dev->tx_suspend) { + sal_sem_give(txq->sem); + return SHR_E_RESOURCE; + } + } + } else { + /* In interrupt mode, the handle thread will wake up Tx */ + if (!dev->tx_suspend) { + return SHR_E_NONE; + } + } + } + + if (dev->tx_suspend) { + sal_spinlock_unlock(txq->mutex); + } else { + sal_sem_give(txq->sem); + } + + return SHR_E_NONE; +} + +/*! + * Suspend Rx queue + */ +static int +cmicd_pdma_rx_suspend(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + sal_spinlock_lock(rxq->lock); + rxq->state |= PDMA_RX_QUEUE_XOFF; + if (hw->dev->flags & PDMA_CHAIN_MODE) { + hw->hdls.chan_stop(hw, rxq->chan_id); + } + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; +} + +/*! + * Resume Rx queue + */ +static int +cmicd_pdma_rx_resume(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + sal_spinlock_lock(rxq->lock); + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + sal_spinlock_unlock(rxq->lock); + return SHR_E_NONE; + } + if (rxq->state & PDMA_RX_BATCH_REFILL) { + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } else if (rxq->halt == rxq->curr || (rxq->halt == rxq->nb_desc && rxq->curr == 0)) { + rxq->halt = (rxq->curr + 1) % rxq->nb_desc; + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } + if (hw->dev->flags & PDMA_CHAIN_MODE) { + rxq->curr = 0; + hw->hdls.chan_start(hw, rxq->chan_id); + } + rxq->state &= ~PDMA_RX_QUEUE_XOFF; + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; +} + +/*! + * Initialize function pointers + */ +int +bcmcnet_cmicd_pdma_desc_ops_init(struct pdma_hw *hw) +{ + if (!hw) { + return SHR_E_PARAM; + } + + hw->dops.rx_desc_init = cmicd_pdma_rx_desc_init; + hw->dops.rx_desc_clean = cmicd_pdma_rx_desc_clean; + hw->dops.rx_ring_clean = cmicd_pdma_rx_ring_clean; + hw->dops.rx_ring_dump = cmicd_pdma_rx_ring_dump; + hw->dops.rx_suspend = cmicd_pdma_rx_suspend; + hw->dops.rx_resume = cmicd_pdma_rx_resume; + hw->dops.tx_desc_init = cmicd_pdma_tx_desc_init; + hw->dops.tx_desc_clean = cmicd_pdma_tx_desc_clean; + hw->dops.tx_ring_clean = cmicd_pdma_tx_ring_clean; + hw->dops.tx_ring_dump = cmicd_pdma_tx_ring_dump; + hw->dops.pkt_xmit = cmicd_pdma_pkt_xmit; + + return SHR_E_NONE; +} + +/*! + * Attach device driver + */ +int +bcmcnet_cmicd_pdma_driver_attach(struct pdma_dev *dev) +{ + struct pdma_hw *hw = NULL; + + /* Allocate memory for HW data */ + hw = sal_alloc(sizeof(*hw), "bcmcnetPdmaHw"); + if (!hw) { + return SHR_E_MEMORY; + } + sal_memset(hw, 0, sizeof(*hw)); + hw->unit = dev->unit; + hw->dev = dev; + dev->ctrl.hw = hw; + + bcmcnet_cmicd_pdma_hw_hdls_init(hw); + bcmcnet_cmicd_pdma_desc_ops_init(hw); + + return SHR_E_NONE; +} + +/*! + * Detach device driver + */ +int +bcmcnet_cmicd_pdma_driver_detach(struct pdma_dev *dev) +{ + if (dev->ctrl.hw) { + sal_free(dev->ctrl.hw); + } + dev->ctrl.hw = NULL; + + return SHR_E_NONE; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_hw.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_hw.c new file mode 100644 index 000000000000..6dc77c4b7c04 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_hw.c @@ -0,0 +1,604 @@ +/*! \file bcmcnet_cmicx_pdma_hw.c + * + * Utility routines for handling BCMCNET hardware (CMICx). + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include + +/*! + * Read 32-bit register + */ +static inline void +cmicx_pdma_reg_read32(struct pdma_hw *hw, uint32_t addr, uint32_t *data) +{ + if (hw->dev->dev_read32) { + hw->dev->dev_read32(hw->dev, addr, data); + } else { + DEV_READ32(&hw->dev->ctrl, addr, data); + } +} + +/*! + * Write 32-bit register + */ +static inline void +cmicx_pdma_reg_write32(struct pdma_hw *hw, uint32_t addr, uint32_t data) +{ + if (hw->dev->dev_write32) { + hw->dev->dev_write32(hw->dev, addr, data); + } else { + DEV_WRITE32(&hw->dev->ctrl, addr, data); + } +} + +/*! + * Enable interrupt for a channel + */ +static inline void +cmicx_pdma_intr_enable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask) +{ + uint32_t reg, irq_mask; + + hw->dev->ctrl.grp[cmc].irq_mask |= mask; + irq_mask = hw->dev->ctrl.grp[cmc].irq_mask; + if (cmc == 0) { + reg = CMICX_PDMA_IRQ_RAW_STAT0; + } else { + if (chan < 4) { + reg = CMICX_PDMA_IRQ_RAW_STAT1; + hw->dev->ctrl.grp[cmc].irq_mask <<= CMICX_IRQ_MASK_SHIFT; + } else { + reg = CMICX_PDMA_IRQ_RAW_STAT2; + hw->dev->ctrl.grp[cmc].irq_mask >>= 32 - CMICX_IRQ_MASK_SHIFT; + } + } + + hw->dev->intr_unmask(hw->dev, cmc, chan, reg & 0xfff, 0); + hw->dev->ctrl.grp[cmc].irq_mask = irq_mask; +} + +/*! + * Disable interrupt for a channel + */ +static inline void +cmicx_pdma_intr_disable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask) +{ + uint32_t reg, irq_mask; + + hw->dev->ctrl.grp[cmc].irq_mask &= ~mask; + irq_mask = hw->dev->ctrl.grp[cmc].irq_mask; + if (cmc == 0) { + reg = CMICX_PDMA_IRQ_RAW_STAT0; + } else { + if (chan < 4) { + reg = CMICX_PDMA_IRQ_RAW_STAT1; + hw->dev->ctrl.grp[cmc].irq_mask <<= CMICX_IRQ_MASK_SHIFT; + } else { + reg = CMICX_PDMA_IRQ_RAW_STAT2; + hw->dev->ctrl.grp[cmc].irq_mask >>= 32 - CMICX_IRQ_MASK_SHIFT; + } + } + + hw->dev->intr_mask(hw->dev, cmc, chan, reg & 0xfff, 0); + hw->dev->ctrl.grp[cmc].irq_mask = irq_mask; +} + +/*! + * Release Packet DMA credits to EP. + */ +static int +cmicx_pdma_credits_release(struct pdma_hw *hw) +{ + int credits; + uint32_t val; + + /* + * Since only 6 bits of iproc_cmic_to_ep_credits[5:0] are being used, + * so we have to set the max credits value twice in order to release + * 64 credits to EP. + * Only do this once when HW is initialized. + */ + hw->hdls.reg_rd32(hw, CMICX_EPINTF_RELEASE_CREDITS, &val); + if (!val) { + credits = 63; + hw->hdls.reg_wr32(hw, CMICX_EPINTF_MAX_CREDITS, (0x1 << 8) | credits); + hw->hdls.reg_wr32(hw, CMICX_EPINTF_RELEASE_CREDITS, 1); + + hw->hdls.reg_wr32(hw, CMICX_EPINTF_RELEASE_CREDITS, 0); + credits = 1; + hw->hdls.reg_wr32(hw, CMICX_EPINTF_MAX_CREDITS, (0x1 << 8) | credits); + hw->hdls.reg_wr32(hw, CMICX_EPINTF_RELEASE_CREDITS, 1); + } + + return SHR_E_NONE; +} + +/*! + * Initialize HW + */ +static int +cmicx_pdma_hw_init(struct pdma_hw *hw) +{ + dev_mode_t mode = DEV_MODE_MAX; + uint32_t val; + + /* Temporarily upgrade work mode to get HW information in VNET mode. */ + if (hw->dev->mode == DEV_MODE_VNET) { + mode = DEV_MODE_VNET; + hw->dev->mode = DEV_MODE_UNET; + } + + /* Release Packet DMA credits to EP. */ + cmicx_pdma_credits_release(hw); + + hw->info.name = CMICX_DEV_NAME; + hw->info.dev_id = hw->dev->dev_id; + hw->info.num_cmcs = CMICX_PDMA_CMC_MAX; + hw->info.cmc_chans = CMICX_PDMA_CMC_CHAN; + hw->info.num_chans = CMICX_PDMA_CMC_MAX * CMICX_PDMA_CMC_CHAN; + hw->info.rx_dcb_size = CMICX_PDMA_DCB_SIZE; + hw->info.tx_dcb_size = CMICX_PDMA_DCB_SIZE; + hw->hdls.reg_rd32(hw, CMICX_EP_TO_CPU_HEADER_SIZE, &val); + hw->info.rx_ph_size = (val & 0xf) * 8; + hw->info.tx_ph_size = CMICX_TX_PKT_HDR_SIZE; + + /* Restore work mode to VNET. */ + if (mode == DEV_MODE_VNET) { + hw->dev->mode = DEV_MODE_VNET; + } + + return SHR_E_NONE; +} + +/*! + * Configure HW + */ +static int +cmicx_pdma_hw_config(struct pdma_hw *hw) +{ + struct dev_ctrl *ctrl = &hw->dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + uint32_t val, que_ctrl; + int grp, que; + uint32_t qi; + int ip_if_hdr_endian = 0; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi]; + grp = rxq->group_id; + que = rxq->chan_id % CMICX_PDMA_CMC_CHAN; + que_ctrl = ctrl->grp[grp].que_ctrl[que]; + + hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_MASK(que)); + val = 0; + if (que_ctrl & PDMA_PKT_BYTE_SWAP) { + val |= CMICX_PDMA_PKT_BIG_ENDIAN; + } + if (que_ctrl & PDMA_OTH_BYTE_SWAP) { + val |= CMICX_PDMA_DESC_BIG_ENDIAN; + } + if (que_ctrl & PDMA_HDR_BYTE_SWAP) { + val |= CMICX_PDMA_HDR_BIG_ENDIAN; + } + if (!(hw->dev->flags & PDMA_CHAIN_MODE)) { + val |= CMICX_PDMA_CONTINUOUS; + } + if (hw->dev->flags & PDMA_DESC_PREFETCH) { + val |= CMICX_PDMA_CONTINUOUS_DESC; + } + val |= CMICX_PDMA_INTR_ON_DESC; + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val); + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi]; + grp = txq->group_id; + que = txq->chan_id % CMICX_PDMA_CMC_CHAN; + que_ctrl = ctrl->grp[grp].que_ctrl[que]; + + hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_MASK(que)); + val = 0; + if (que_ctrl & PDMA_PKT_BYTE_SWAP) { + val |= CMICX_PDMA_PKT_BIG_ENDIAN; + val |= CMICX_PDMA_HDR_BIG_ENDIAN; + ip_if_hdr_endian = 1; + } + if (que_ctrl & PDMA_OTH_BYTE_SWAP) { + val |= CMICX_PDMA_DESC_BIG_ENDIAN; + } + if (que_ctrl & PDMA_HDR_BYTE_SWAP) { + ip_if_hdr_endian = 1; + } + if (!(hw->dev->flags & PDMA_CHAIN_MODE)) { + val |= CMICX_PDMA_CONTINUOUS; + } + if (hw->dev->flags & PDMA_DESC_PREFETCH) { + val |= CMICX_PDMA_CONTINUOUS_DESC; + } + val |= CMICX_PDMA_INTR_ON_DESC | CMICX_PDMA_DIR; + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val); + } + + if (ip_if_hdr_endian == 1) { + hw->hdls.reg_rd32(hw, CMICX_TOP_CONFIG, &val); + val |= 0x80; + hw->hdls.reg_wr32(hw, CMICX_TOP_CONFIG, val); + } + + return SHR_E_NONE; +} + +/*! + * Reset HW + */ +static int +cmicx_pdma_hw_reset(struct pdma_hw *hw) +{ + int gi, qi; + + for (gi = 0; gi < hw->dev->num_groups; gi++) { + if (!hw->dev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < CMICX_PDMA_CMC_CHAN; qi++) { + if (1 << qi & hw->dev->ctrl.grp[gi].bm_rxq || + 1 << qi & hw->dev->ctrl.grp[gi].bm_txq) { + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(gi, qi), 0); + } + } + } + + return SHR_E_NONE; +} + +/*! + * Start a channel + */ +static int +cmicx_pdma_chan_start(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val); + val |= CMICX_PDMA_ENABLE; + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Stop a channel + */ +static int +cmicx_pdma_chan_stop(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + int retry = CMICX_HW_RETRY_TIMES; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val); + val |= CMICX_PDMA_ENABLE | CMICX_PDMA_ABORT; + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val); + + MEMORY_BARRIER; + + do { + val = ~CMICX_PDMA_IS_ACTIVE; + hw->hdls.reg_rd32(hw, CMICX_PDMA_STAT(grp, que), &val); + } while ((val & CMICX_PDMA_IS_ACTIVE) && (--retry > 0)); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val); + val &= ~(CMICX_PDMA_ENABLE | CMICX_PDMA_ABORT); + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val); + + hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_MASK(que)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Setup a channel + */ +static int +cmicx_pdma_chan_setup(struct pdma_hw *hw, int chan, uint64_t addr) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_LO(grp, que), addr); + hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_HI(grp, que), DMA_TO_BUS_HI(addr >> 32)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Set halt point for a channel + */ +static int +cmicx_pdma_chan_goto(struct pdma_hw *hw, int chan, uint64_t addr) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_HALT_LO(grp, que), addr); + hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_HALT_HI(grp, que), DMA_TO_BUS_HI(addr >> 32)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Clear a channel + */ +static int +cmicx_pdma_chan_clear(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_CTRLD_INTR(que)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Get interrupt number for a channel + */ +static int +cmicx_pdma_chan_intr_num_get(struct pdma_hw *hw, int chan) +{ + int grp, que, start_num, mask_shift; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + mask_shift = 0; + if (grp > 0) { + mask_shift = CMICX_IRQ_MASK_SHIFT + grp * 32; + } + start_num = CMICX_IRQ_START_NUM + mask_shift; + + return start_num + (que * CMICX_IRQ_NUM_OFFSET); +} + +/*! + * Enable interrupt for a channel + */ +static int +cmicx_pdma_chan_intr_enable(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + cmicx_pdma_intr_enable(hw, grp, que, CMICX_PDMA_IRQ_CTRLD_INTR(que)); + + return SHR_E_NONE; +} + +/*! + * Disable interrupt for a channel + */ +static int +cmicx_pdma_chan_intr_disable(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + cmicx_pdma_intr_disable(hw, grp, que, CMICX_PDMA_IRQ_CTRLD_INTR(que)); + + return SHR_E_NONE; +} + +/*! + * Query interrupt status for a channel + * + * In group mode (interrupt processing per CMC), need to query each channel's + * interrupt status. + * + */ +static int +cmicx_pdma_chan_intr_query(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICX_PDMA_IRQ_STAT(grp), &val); + + return val & CMICX_PDMA_IRQ_CTRLD_INTR(que); +} + +/*! + * Check interrupt validity for a channel + * + * In group mode (interrupt processing per CMC), need to check each channel's + * interrupt validity based on its interrupt mask. + * + */ +static int +cmicx_pdma_chan_intr_check(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + if (!(hw->dev->ctrl.grp[grp].irq_mask & CMICX_PDMA_IRQ_CTRLD_INTR(que))) { + return 0; + } + + return cmicx_pdma_chan_intr_query(hw, chan); +} + +/*! + * Coalesce interrupt for a channel + */ +static int +cmicx_pdma_chan_intr_coalesce(struct pdma_hw *hw, int chan, int count, int timer) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + val = CMICX_PDMA_INTR_COAL_ENA | + CMICX_PDMA_INTR_THRESH(count) | + CMICX_PDMA_INTR_TIMER(timer); + hw->hdls.reg_wr32(hw, CMICX_PDMA_INTR_COAL(grp, que), val); + + return SHR_E_NONE; +} + +/*! + * Dump registers for a channel + */ +static int +cmicx_pdma_chan_reg_dump(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_CTRL: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_LO(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_LO: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_HI(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HI: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CURR_DESC_LO(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_CURR_DESC_LO: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CURR_DESC_HI(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_CURR_DESC_HI: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_HALT_LO(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR_LO: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_HALT_HI(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR_HI: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_COS_CTRL_RX0(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_COS_CTRL_RX_0: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_COS_CTRL_RX1(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_COS_CTRL_RX_1: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_INTR_COAL(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_INTR_COAL: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_RBUF_THRE(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_RXBUF_THRESHOLD_CONFIG: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_STAT(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_STAT: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_COUNT_RX(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_PKT_COUNT_RXPKT: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_COUNT_TX(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_PKT_COUNT_TXPKT: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_COUNT_RX_DROP(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_PKT_COUNT_RXPKT_DROP: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_IRQ_STAT(grp), &val); + CNET_PR("CMIC_CMC%d_IRQ_STAT: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), &val); + CNET_PR("CMIC_CMC%d_IRQ_STAT_CLR: 0x%08x\n", grp, val); + + val = hw->dev->ctrl.grp[grp].irq_mask; + CNET_PR("CMIC_CMC%d_IRQ_ENAB: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICX_EP_TO_CPU_HEADER_SIZE, &val); + CNET_PR("CMIC_EP_TO_CPU_HEADER_SIZE: 0x%08x\n", val); + + return SHR_E_NONE; +} + +/*! + * Initialize function pointers + */ +int +bcmcnet_cmicx_pdma_hw_hdls_init(struct pdma_hw *hw) +{ + if (!hw) { + return SHR_E_PARAM; + } + + hw->hdls.reg_rd32 = cmicx_pdma_reg_read32; + hw->hdls.reg_wr32 = cmicx_pdma_reg_write32; + hw->hdls.hw_init = cmicx_pdma_hw_init; + hw->hdls.hw_config = cmicx_pdma_hw_config; + hw->hdls.hw_reset = cmicx_pdma_hw_reset; + hw->hdls.chan_start = cmicx_pdma_chan_start; + hw->hdls.chan_stop = cmicx_pdma_chan_stop; + hw->hdls.chan_setup = cmicx_pdma_chan_setup; + hw->hdls.chan_goto = cmicx_pdma_chan_goto; + hw->hdls.chan_clear = cmicx_pdma_chan_clear; + hw->hdls.chan_intr_num_get = cmicx_pdma_chan_intr_num_get; + hw->hdls.chan_intr_enable = cmicx_pdma_chan_intr_enable; + hw->hdls.chan_intr_disable = cmicx_pdma_chan_intr_disable; + hw->hdls.chan_intr_query = cmicx_pdma_chan_intr_query; + hw->hdls.chan_intr_check = cmicx_pdma_chan_intr_check; + hw->hdls.chan_intr_coalesce = cmicx_pdma_chan_intr_coalesce; + hw->hdls.chan_reg_dump = cmicx_pdma_chan_reg_dump; + + return SHR_E_NONE; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_rxtx.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_rxtx.c new file mode 100644 index 000000000000..651728465d56 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_rxtx.c @@ -0,0 +1,1094 @@ +/*! \file bcmcnet_cmicx_pdma_rxtx.c + * + * Utility routines for BCMCNET hardware (CMICx) specific Rx/Tx. + * + * Here are the CMIC specific Rx/Tx routines including DCBs resource allocation + * and clean up, DCBs configuration, Rx buffers allocation, Tx buffers release, + * Rx/Tx packets processing, etc. + * They are shared among all the modes (UNET, KNET, VNET, HNET) and in both of + * user space and kernel space. + * + * The driver uses a ring of DCBs per DMA channel based on Continuous DMA mode. + * The beginning is written to register pointing to the physical address of the + * start of the ring. The ring size is maintained by the driver. A HALT DCB + * physical address is written to DMA register timely to indicate how many DCBs + * can be handled by HW. + * + * When a packet is received, an interrupt is triggered. The handler will go + * through the Rx DCB ring to process the current completed DCB and every + * subsequent DCBs until no one is left. The received packet is processed and + * passed up to the high level SW. After that, a new buffer is allocated and + * the DCB is updated for receiving a new packet. A new HALT DCB is selected + * and its physical address is written to DMA register. + * + * When a packet is transmitted, the driver starts where it left off last time + * in the Tx DCB ring, updates the DCB and writes its physical address to DMA + * register so as to start DMA. Once the transmitting is finished, the handler + * is informed to clean up the buffer based on the work mode. In KNET or HNET + * mode, an interrupt will be triggered. Polling mode is used in CNET or VNET + * mode, the buffers will be cleaned up when the number of dirty DCBs reaches + * a pre-defined threshold. + * + * In VNET and HNET modes, DCB updating between virtual ring and real ring and + * a IOCTL based notification mechanism are involved. The hypervisor in kernel + * emulates the DMA HW behaviors to update DCBs in virtual network and inform + * the handler something happened. Likewise, the hypervisor updates itself real + * DCB ring from the virtual ring to start DMA for transmitting a packet once a + * notification is received from the virtual network. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include +#include + +/*! + * Configure Rx descriptor + */ +static inline void +cmicx_rx_desc_config(struct cmicx_rx_desc *rd, uint64_t addr, uint32_t len) +{ + uint32_t ctrl; + + rd->addr_lo = addr; + rd->addr_hi = DMA_TO_BUS_HI(addr >> 32); + rd->status = 0; + ctrl = rd->ctrl; + ctrl &= CMICX_DESC_CTRL_REMAIN(0xf); + ctrl |= CMICX_DESC_CTRL_CNTLD_INTR | CMICX_DESC_CTRL_CHAIN | + CMICX_DESC_CTRL_LEN(len); + rd->ctrl = ctrl; +} + +/*! + * Configure Tx descriptor + */ +static inline void +cmicx_tx_desc_config(struct cmicx_tx_desc *td, uint64_t addr, uint32_t len, uint32_t flags) +{ + uint32_t ctrl; + + td->addr_lo = addr; + td->addr_hi = DMA_TO_BUS_HI(addr >> 32); + td->status = 0; + ctrl = td->ctrl; + ctrl &= CMICX_DESC_CTRL_REMAIN(0xf); + ctrl |= CMICX_DESC_CTRL_CNTLD_INTR | CMICX_DESC_CTRL_CHAIN | + CMICX_DESC_CTRL_FLAGS(flags) | CMICX_DESC_CTRL_LEN(len); + td->ctrl = ctrl; +} + +/*! + * Configure Rx reload descriptor + */ +static inline void +cmicx_rx_rldesc_config(struct cmicx_rx_desc *rd, uint64_t addr) +{ + rd->addr_lo = addr; + rd->addr_hi = DMA_TO_BUS_HI(addr >> 32); + rd->status = 0; + rd->ctrl = CMICX_DESC_CTRL_CNTLD_INTR | CMICX_DESC_CTRL_CHAIN | + CMICX_DESC_CTRL_RELOAD; +} + +/*! + * Configure Tx reload descriptor + */ +static inline void +cmicx_tx_rldesc_config(struct cmicx_tx_desc *td, uint64_t addr) +{ + td->addr_lo = addr; + td->addr_hi = DMA_TO_BUS_HI(addr >> 32); + td->status = 0; + td->ctrl = CMICX_DESC_CTRL_CNTLD_INTR | CMICX_DESC_CTRL_CHAIN | + CMICX_DESC_CTRL_RELOAD; +} + +/*! + * Chain Rx descriptor + */ +static inline void +cmicx_rx_desc_chain(struct cmicx_rx_desc *rd, int chain) +{ + if (chain) { + rd->ctrl |= CMICX_DESC_CTRL_CHAIN; + } else { + rd->ctrl &= ~CMICX_DESC_CTRL_CHAIN; + } +} + +/*! + * Chain Tx descriptor + */ +static inline void +cmicx_tx_desc_chain(struct cmicx_tx_desc *td, int chain) +{ + if (chain) { + td->ctrl |= CMICX_DESC_CTRL_CHAIN; + } else { + td->ctrl &= ~CMICX_DESC_CTRL_CHAIN; + } +} + +/*! + * Set Rx descriptor remain + */ +static inline void +cmicx_rx_desc_remain(struct cmicx_rx_desc *rd, uint32_t rm) +{ + rd->ctrl &= ~CMICX_DESC_CTRL_REMAIN(0xf); + rd->ctrl |= CMICX_DESC_CTRL_REMAIN(rm); +} + +/*! + * Set Tx descriptor remain + */ +static inline void +cmicx_tx_desc_remain(struct cmicx_tx_desc *td, uint32_t rm) +{ + td->ctrl &= ~CMICX_DESC_CTRL_REMAIN(0xf); + td->ctrl |= CMICX_DESC_CTRL_REMAIN(rm); +} + +/*! + * Get unused descriptors in a Rx ring + */ +static inline int +cmicx_pdma_rx_ring_unused(struct pdma_rx_queue *rxq) +{ + /* Leave one descriptor unused so as not to halt */ + return rxq->curr > rxq->halt ? + rxq->curr - rxq->halt - 1 : + rxq->nb_desc + rxq->curr - rxq->halt - 1; +} + +/*! + * Get unused descriptors in a Tx ring + */ +static inline int +cmicx_pdma_tx_ring_unused(struct pdma_tx_queue *txq) +{ + /* Leave one descriptor unused so as not to halt */ + return txq->dirt > txq->curr ? + txq->dirt - txq->curr - 1 : + txq->nb_desc + txq->dirt - txq->curr - 1; +} + +/*! + * Initialize Rx descriptors + */ +static int +cmicx_pdma_rx_desc_init(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + dma_addr_t addr; + uint32_t di, rm; + int rv; + + for (di = 0; di < rxq->nb_desc; di++) { + if (!rxq->pbuf[di].dma) { + /* Allocate pktbuf for ring entry */ + rv = bm->rx_buf_alloc(dev, rxq, &rxq->pbuf[di]); + if (SHR_FAILURE(rv)) { + goto cleanup; + } + } + /* Config receive descriptor ring */ + bm->rx_buf_dma(dev, rxq, &rxq->pbuf[di], &addr); + cmicx_rx_desc_config(&ring[di], addr, rxq->buf_size); + rm = (rxq->nb_desc - di) >= CMICX_DESC_REMAIN_MAX ? + CMICX_DESC_REMAIN_MAX : rxq->nb_desc - di; + cmicx_rx_desc_remain(&ring[di], rm); + if (hw->dev->flags & PDMA_CHAIN_MODE && di == rxq->nb_desc - 1) { + cmicx_rx_desc_chain(&ring[di], 0); + } + } + /* Config the last descriptor in the ring as reload descriptor */ + cmicx_rx_rldesc_config(&ring[di], rxq->ring_addr); + + rxq->curr = 0; + rxq->halt = rxq->state & PDMA_RX_BATCH_REFILL ? 0 : rxq->nb_desc; + + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * di; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + hw->hdls.chan_setup(hw, rxq->chan_id, rxq->ring_addr); + + return SHR_E_NONE; + +cleanup: + for (di = 0; di < rxq->nb_desc; di++) { + if (rxq->pbuf[di].dma) { + bm->rx_buf_free(dev, rxq, &rxq->pbuf[di]); + } + cmicx_rx_desc_config(&ring[di], 0, 0); + } + + CNET_PR("RX: Failed to allocate mem\n"); + + return SHR_E_MEMORY; +} + +/*! + * Cleanup Rx descriptors + */ +static int +cmicx_pdma_rx_desc_clean(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + uint32_t di; + + /* Go through all the descriptors and free pktbuf */ + for (di = 0; di < rxq->nb_desc; di++) { + if (rxq->pbuf[di].dma) { + bm->rx_buf_free(dev, rxq, &rxq->pbuf[di]); + } + cmicx_rx_desc_config(&ring[di], 0, 0); + } + + rxq->curr = 0; + rxq->halt = 0; + + return SHR_E_NONE; +} + +/*! + * Initialize Tx descriptors + */ +static int +cmicx_pdma_tx_desc_init(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + uint32_t di, rm; + + for (di = 0; di < txq->nb_desc; di++) { + if (txq->pbuf[di].dma) { + bm->tx_buf_free(dev, txq, &txq->pbuf[di]); + } + /* Config transmit descriptor ring */ + cmicx_tx_desc_config(&ring[di], 0, 0, 0); + rm = (txq->nb_desc - di) >= CMICX_DESC_REMAIN_MAX ? + CMICX_DESC_REMAIN_MAX : txq->nb_desc - di; + cmicx_tx_desc_remain(&ring[di], rm); + if (hw->dev->flags & PDMA_CHAIN_MODE) { + cmicx_tx_desc_chain(&ring[di], 0); + } + } + /* Config the last descriptor in the ring as reload descriptor */ + cmicx_tx_rldesc_config(&ring[di], txq->ring_addr); + + txq->curr = 0; + txq->dirt = 0; + txq->halt = 0; + + txq->halt_addr = txq->ring_addr; + hw->hdls.chan_goto(hw, txq->chan_id, txq->halt_addr); + hw->hdls.chan_setup(hw, txq->chan_id, txq->ring_addr); + + return SHR_E_NONE; +} + +/*! + * Cleanup Tx descriptors + */ +static int +cmicx_pdma_tx_desc_clean(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + uint32_t di; + + /* Go through all the descriptors and free pktbuf */ + for (di = 0; di < txq->nb_desc; di++) { + if (txq->pbuf[di].dma) { + bm->tx_buf_free(dev, txq, &txq->pbuf[di]); + } + cmicx_tx_desc_config(&ring[di], 0, 0, 0); + } + + txq->curr = 0; + txq->dirt = 0; + txq->halt = 0; + + return SHR_E_NONE; +} + +/*! + * Process Rx vring + */ +static int +cmicx_pdma_rx_vring_process(struct pdma_hw *hw, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + struct pdma_rx_queue *vrxq = NULL; + struct cmicx_rx_desc *vring = NULL; + struct pkt_hdr *pkh = &pbuf->pkb->pkh; + uint64_t buf_addr; + + vrxq = (struct pdma_rx_queue *)dev->ctrl.vnet_rxq[rxq->queue_id]; + vring = (struct cmicx_rx_desc *)vrxq->ring; + if (!vring) { + rxq->stats.dropped++; + return SHR_E_UNAVAIL; + } + + if (vring[vrxq->curr].status & CMICX_DESC_STAT_RTX_DONE) { + dev->xnet_wake(dev); + return SHR_E_BUSY; + } + + /* Copy descriptor and packet to vring */ + buf_addr = BUS_TO_DMA_HI(vring[vrxq->curr].addr_hi); + buf_addr = buf_addr << 32 | vring[vrxq->curr].addr_lo; + sal_memcpy(dev->sys_p2v(dev, buf_addr), &pbuf->pkb->data, + pkh->meta_len + pkh->data_len); + vring[vrxq->curr].status = ring[rxq->curr].status; + + MEMORY_BARRIER; + + /* Notify VNET to process if needed */ + if (!vring[(vrxq->curr + vrxq->nb_desc - 1) % vrxq->nb_desc].status) { + dev->xnet_wake(dev); + } + vrxq->curr = (vrxq->curr + 1) % vrxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * Refill Rx ring + */ +static int +cmicx_pdma_rx_ring_refill(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + struct pdma_rx_buf *pbuf = NULL; + int unused = cmicx_pdma_rx_ring_unused(rxq); + dma_addr_t addr; + uint32_t halt; + int rv; + + for (halt = rxq->halt; halt < rxq->halt + unused; halt++) { + pbuf = &rxq->pbuf[halt % rxq->nb_desc]; + /* Allocate a new pktbuf */ + if (!bm->rx_buf_avail(dev, rxq, pbuf)) { + rv = bm->rx_buf_alloc(dev, rxq, pbuf); + if (SHR_FAILURE(rv)) { + rxq->halt = halt % rxq->nb_desc; + rxq->stats.nomems++; + goto fail; + } + } + /* Setup the new descriptor */ + bm->rx_buf_dma(dev, rxq, pbuf, &addr); + cmicx_rx_desc_config(&ring[halt % rxq->nb_desc], addr, rxq->buf_size); + if (dev->flags & PDMA_CHAIN_MODE && halt % rxq->nb_desc == rxq->nb_desc - 1) { + cmicx_rx_desc_chain(&ring[halt % rxq->nb_desc], 0); + } + } + + sal_spinlock_lock(rxq->lock); + rxq->halt = halt % rxq->nb_desc; + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; + +fail: + CNET_PR("RX: Failed to allocate mem\n"); + + return SHR_E_MEMORY; +} + +/*! + * \brief Clean Rx ring + * + * \param [in] hw HW structure point. + * \param [in] rxq Rx queue structure point. + * \param [in] budget Polling budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicx_pdma_rx_ring_clean(struct pdma_hw *hw, struct pdma_rx_queue *rxq, int budget) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + struct pdma_rx_buf *pbuf = NULL; + struct pkt_hdr *pkh = NULL; + dma_addr_t addr; + uint32_t stat, curr; + int len, done = 0; + int rv; + + curr = rxq->curr; + while (CMICX_DESC_STAT_DONE(ring[curr].status)) { + if (dev->mode == DEV_MODE_VNET && rxq->state & PDMA_RX_QUEUE_XOFF) { + break; + } + if (!(rxq->state & PDMA_RX_BATCH_REFILL) && + !(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * curr; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + rxq->halt = curr; + } + if (done == budget) { + break; + } + + /* Get the current pktbuf to process */ + pbuf = &rxq->pbuf[curr]; + stat = ring[curr].status; + len = CMICX_DESC_STAT_LEN(stat); + pkh = bm->rx_buf_get(dev, rxq, pbuf, len); + if (!pkh) { + rxq->stats.nomems++; + goto fail; + } + + /* Setup packet header */ + pkh->data_len = len - hw->info.rx_ph_size; + pkh->meta_len = hw->info.rx_ph_size; + pkh->queue_id = rxq->queue_id; + pkh->attrs = CMICX_DESC_STAT_FLAGS(stat); + + /* Send up the packet */ + rv = dev->pkt_recv(dev, rxq->queue_id, (void *)pbuf->skb); + if (SHR_FAILURE(rv)) { + if (dev->mode == DEV_MODE_HNET && pkh->attrs & PDMA_RX_TO_VNET) { + rv = cmicx_pdma_rx_vring_process(hw, rxq, pbuf); + if (SHR_FAILURE(rv) && rv == SHR_E_BUSY) { + rxq->state |= PDMA_RX_QUEUE_BUSY; + return done; + } + } else { + rxq->stats.dropped++; + } + bm->rx_buf_put(dev, rxq, pbuf, len); + } + + /* Count the packets/bytes */ + rxq->stats.packets++; + rxq->stats.bytes += len; + + /* Count the errors if any */ + if (stat & CMICX_DESC_STAT_ERR_MASK) { + rxq->stats.errors++; + if (stat & CMICX_DESC_STAT_DATA_ERR) { + rxq->stats.data_errors++; + } + if (stat & CMICX_DESC_STAT_CELL_ERR) { + rxq->stats.cell_errors++; + } + } + + /* Setup the new descriptor */ + if (!(rxq->state & PDMA_RX_BATCH_REFILL)) { + if (!bm->rx_buf_avail(dev, rxq, pbuf)) { + rv = bm->rx_buf_alloc(dev, rxq, pbuf); + if (SHR_FAILURE(rv)) { + rxq->stats.nomems++; + goto fail; + } + } + bm->rx_buf_dma(dev, rxq, pbuf, &addr); + cmicx_rx_desc_config(&ring[curr], addr, rxq->buf_size); + if (dev->flags & PDMA_CHAIN_MODE && curr == rxq->nb_desc - 1) { + cmicx_rx_desc_chain(&ring[curr], 0); + } + } else { + cmicx_rx_desc_config(&ring[curr], 0, 0); + } + + /* Notify HNET to process if needed */ + if (dev->mode == DEV_MODE_VNET) { + MEMORY_BARRIER; + if (ring[(curr + rxq->nb_desc - 1) % rxq->nb_desc].status) { + dev->xnet_wake(dev); + } + } + + /* Update the indicators */ + if (!(rxq->state & PDMA_RX_BATCH_REFILL) && rxq->halt != curr) { + sal_spinlock_lock(rxq->lock); + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * curr; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + rxq->halt = curr; + } + curr = (curr + 1) % rxq->nb_desc; + sal_spinlock_unlock(rxq->lock); + } else { + curr = (curr + 1) % rxq->nb_desc; + } + rxq->curr = curr; + done++; + + /* Restart DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (curr == 0 && !(rxq->state & PDMA_RX_QUEUE_XOFF)) { + hw->hdls.chan_stop(hw, rxq->chan_id); + hw->hdls.chan_start(hw, rxq->chan_id); + } + } + } + + /* One more poll for chain done in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (curr == rxq->nb_desc - 1 && done) { + done = budget; + } + } + + /* In batching mode, replenish all the unused descriptors */ + if (rxq->state & PDMA_RX_BATCH_REFILL && + cmicx_pdma_rx_ring_unused(rxq) >= (int)rxq->free_thresh) { + cmicx_pdma_rx_ring_refill(hw, rxq); + } + + /* Notify the other side to process */ + if (dev->mode == DEV_MODE_VNET || dev->mode == DEV_MODE_HNET) { + if (done) { + dev->xnet_wake(dev); + } + } + + return done; + +fail: + CNET_PR("RX: Failed to allocate mem\n"); + + return done; +} + +/*! + * Process Tx vring + */ +static int +cmicx_pdma_tx_vring_process(struct pdma_hw *hw, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + struct pdma_tx_queue *vtxq = NULL; + struct cmicx_tx_desc *vring = NULL; + + vtxq = (struct pdma_tx_queue *)dev->ctrl.vnet_txq[txq->queue_id]; + vring = (struct cmicx_tx_desc *)vtxq->ring; + if (!vring) { + return SHR_E_UNAVAIL; + } + + /* Update vring descriptor */ + vring[vtxq->dirt].status = ring[txq->dirt].status; + pbuf->dma = 0; + + MEMORY_BARRIER; + + /* Notify VNET to process if needed */ + if (!vring[(vtxq->dirt + vtxq->nb_desc - 1) % vtxq->nb_desc].status) { + dev->xnet_wake(dev); + } + vtxq->dirt = (vtxq->dirt + 1) % vtxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * \brief Clean Tx ring + * + * \param [in] hw HW structure point. + * \param [in] txq Tx queue structure point. + * \param [in] budget Polling budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicx_pdma_tx_ring_clean(struct pdma_hw *hw, struct pdma_tx_queue *txq, int budget) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + uint32_t dirt, curr; + int done = 0; + + dirt = txq->dirt; + while (txq->pbuf[dirt].dma) { + if (!CMICX_DESC_STAT_DONE(ring[dirt].status)) { + break; + } + if (done == budget) { + break; + } + + if (dev->mode == DEV_MODE_HNET && !txq->pbuf[dirt].skb) { + cmicx_pdma_tx_vring_process(hw, txq, &txq->pbuf[dirt]); + } else { + /* Free the done pktbuf */ + bm->tx_buf_free(dev, txq, &txq->pbuf[dirt]); + } + + cmicx_tx_desc_config(&ring[dirt], 0, 0, 0); + + /* Update the indicators */ + dirt = (dirt + 1) % txq->nb_desc; + txq->dirt = dirt; + done++; + + /* Restart DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + sal_spinlock_lock(txq->lock); + curr = txq->curr; + if (dirt == txq->halt && dirt != curr) { + hw->hdls.chan_stop(hw, txq->chan_id); + cmicx_tx_desc_chain(&ring[(curr + txq->nb_desc - 1) % txq->nb_desc], 0); + hw->hdls.chan_setup(hw, txq->chan_id, + txq->ring_addr + sizeof(struct cmicx_tx_desc) * txq->halt); + hw->hdls.chan_start(hw, txq->chan_id); + txq->halt = curr; + } + sal_spinlock_unlock(txq->lock); + } + } + + /* One more poll for chain done in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + sal_spinlock_lock(txq->lock); + if (dirt != txq->halt) { + done = budget; + } + sal_spinlock_unlock(txq->lock); + } + + /* Resume Tx if any */ + sal_spinlock_lock(txq->lock); + if (cmicx_pdma_tx_ring_unused(txq) && txq->state & PDMA_TX_QUEUE_XOFF) { + txq->state &= ~PDMA_TX_QUEUE_XOFF; + sal_spinlock_unlock(txq->lock); + if (dev->tx_resume) { + dev->tx_resume(dev, txq->queue_id); + } else if (!(txq->state & PDMA_TX_QUEUE_POLL)) { + sal_sem_give(txq->sem); + } + return done; + } + sal_spinlock_unlock(txq->lock); + + return done; +} + +/*! + * Dump Rx ring + */ +static int +cmicx_pdma_rx_ring_dump(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + struct cmicx_rx_desc *rd; + uint32_t di; + + CNET_PR("\nRX: queue=%d, chan=%d, curr=%d, halt=%d, halt@%p\n", + rxq->queue_id, rxq->chan_id, rxq->curr, rxq->halt, (void *)&ring[rxq->halt]); + CNET_PR("----------------------------------------------------------------\n"); + for (di = 0; di < rxq->nb_desc + 1; di++) { + rd = &ring[di]; + CNET_PR("DESC[%03d]: (%p)->%08x %08x %08x %08x\n", + di, (void *)(unsigned long)(rxq->ring_addr + di * CMICX_PDMA_DCB_SIZE), + rd->addr_lo, rd->addr_hi, rd->ctrl, rd->status); + } + + return SHR_E_NONE; +} + +/*! + * Dump Tx ring + */ +static int +cmicx_pdma_tx_ring_dump(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + struct cmicx_tx_desc *td; + uint32_t di; + + CNET_PR("\nTX: queue=%d, chan=%d, curr=%d, dirt=%d, halt@%p\n", + txq->queue_id, txq->chan_id, txq->curr, txq->dirt, (void *)&ring[txq->curr]); + CNET_PR("----------------------------------------------------------------\n"); + for (di = 0; di < txq->nb_desc + 1; di++) { + td = &ring[di]; + CNET_PR("DESC[%03d]: (%p)->%08x %08x %08x %08x\n", + di, (void *)(unsigned long)(txq->ring_addr + di * CMICX_PDMA_DCB_SIZE), + td->addr_lo, td->addr_hi, td->ctrl, td->status); + } + + return SHR_E_NONE; +} + +/*! + * Fetch Tx vring + */ +static int +cmicx_pdma_tx_vring_fetch(struct pdma_hw *hw, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + struct pdma_tx_queue *vtxq = NULL; + struct cmicx_tx_desc *vring = NULL; + + vtxq = (struct pdma_tx_queue *)dev->ctrl.vnet_txq[txq->queue_id]; + vring = (struct cmicx_tx_desc *)vtxq->ring; + if (!vring || !CMICX_DESC_CTRL_LEN(vring[vtxq->curr].ctrl)) { + return SHR_E_UNAVAIL; + } + + /* Fetch vring descriptor */ + sal_memcpy(&ring[txq->curr], &vring[vtxq->curr], sizeof(struct cmicx_tx_desc)); + vring[vtxq->curr].ctrl &= ~CMICX_DESC_CTRL_LEN(-1); + + MEMORY_BARRIER; + + pbuf->dma = vring[vtxq->curr].addr_lo; + pbuf->len = CMICX_DESC_CTRL_LEN(ring[txq->curr].ctrl); + vtxq->curr = (vtxq->curr + 1) % vtxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * Check Tx ring + */ +static inline int +cmicx_pdma_tx_ring_check(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + if (cmicx_pdma_tx_ring_unused(txq)) { + return SHR_E_NONE; + } + + sal_spinlock_lock(txq->lock); + if (!cmicx_pdma_tx_ring_unused(txq)) { + txq->state |= PDMA_TX_QUEUE_XOFF; + txq->stats.xoffs++; + sal_spinlock_unlock(txq->lock); + if (hw->dev->tx_suspend) { + hw->dev->tx_suspend(hw->dev, txq->queue_id); + } + return SHR_E_BUSY; + } + sal_spinlock_unlock(txq->lock); + + return SHR_E_NONE; +} + +/*! + * \brief Start packet transmission + * + * \param [in] hw HW structure point. + * \param [in] txq Tx queue structure point. + * \param [in] buf Tx packet buffer. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicx_pdma_pkt_xmit(struct pdma_hw *hw, struct pdma_tx_queue *txq, void *buf) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + struct pdma_tx_buf *pbuf = NULL; + struct pkt_hdr *pkh = NULL; + dma_addr_t addr; + uint32_t curr, flags = 0; + int retry = 5000000; + int rv; + + if (!(txq->state & PDMA_TX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + if (dev->tx_suspend) { + sal_spinlock_lock(txq->mutex); + } else { + sal_sem_take(txq->sem, SAL_SEM_FOREVER); + } + + /* Check Tx resource */ + if (dev->tx_suspend) { + /* Suspend Tx if no resource */ + rv = cmicx_pdma_tx_ring_check(hw, txq); + if (SHR_FAILURE(rv)) { + sal_spinlock_unlock(txq->mutex); + return rv; + } + } else { + /* Abort Tx if a fatal error happened */ + if (txq->state & PDMA_TX_QUEUE_XOFF) { + sal_sem_give(txq->sem); + return SHR_E_RESOURCE; + } + } + + /* Setup the new descriptor */ + curr = txq->curr; + pbuf = &txq->pbuf[curr]; + if (dev->mode == DEV_MODE_HNET && !buf) { + rv = cmicx_pdma_tx_vring_fetch(hw, txq, pbuf); + if (SHR_FAILURE(rv)) { + sal_spinlock_unlock(txq->mutex); + return SHR_E_EMPTY; + } + } else { + pbuf->adj = 1; + pkh = bm->tx_buf_get(dev, txq, pbuf, buf); + if (!pkh) { + txq->stats.dropped++; + if (dev->tx_suspend) { + sal_spinlock_unlock(txq->mutex); + } else { + sal_sem_give(txq->sem); + } + return SHR_E_NONE; + } + bm->tx_buf_dma(dev, txq, pbuf, &addr); + flags |= pkh->attrs & PDMA_TX_HIGIG_PKT ? CMICX_DESC_TX_HIGIG_PKT : 0; + flags |= pkh->attrs & PDMA_TX_PURGE_PKT ? CMICX_DESC_TX_PURGE_PKT : 0; + cmicx_tx_desc_config(&ring[curr], addr, pbuf->len, flags); + } + + /* Notify HNET to process if needed */ + if (dev->mode == DEV_MODE_VNET) { + MEMORY_BARRIER; + if (!CMICX_DESC_CTRL_LEN(ring[(curr + txq->nb_desc - 1) % txq->nb_desc].ctrl)) { + dev->xnet_wake(dev); + } + } + + /* Update the indicators */ + curr = (curr + 1) % txq->nb_desc; + txq->curr = curr; + + /* Start DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (txq->state & PDMA_TX_QUEUE_POLL) { + do { + rv = cmicx_pdma_tx_ring_clean(hw, txq, txq->nb_desc - 1); + if (rv != (int)txq->nb_desc - 1) { + break; + } + sal_usleep(1); + } while (retry--); + if (retry <= 0) { + CNET_PR("Last Tx could not be done in given time\n"); + } + } + sal_spinlock_lock(txq->lock); + if (txq->dirt == txq->halt && txq->dirt != curr) { + hw->hdls.chan_stop(hw, txq->chan_id); + cmicx_tx_desc_chain(&ring[(curr + txq->nb_desc - 1) % txq->nb_desc], 0); + hw->hdls.chan_setup(hw, txq->chan_id, + txq->ring_addr + sizeof(struct cmicx_tx_desc) * txq->halt); + hw->hdls.chan_start(hw, txq->chan_id); + txq->halt = curr; + } + sal_spinlock_unlock(txq->lock); + } + + /* Kick off DMA */ + txq->halt_addr = txq->ring_addr + sizeof(struct cmicx_tx_desc) * curr; + hw->hdls.chan_goto(hw, txq->chan_id, txq->halt_addr); + + /* Count the packets/bytes */ + txq->stats.packets++; + txq->stats.bytes += pbuf->len; + + /* Clean up ring if in polling mode */ + if (txq->state & PDMA_TX_QUEUE_POLL && + cmicx_pdma_tx_ring_unused(txq) <= (int)txq->free_thresh) { + cmicx_pdma_tx_ring_clean(hw, txq, txq->nb_desc - txq->free_thresh); + } + + /* Suspend Tx if no resource */ + rv = cmicx_pdma_tx_ring_check(hw, txq); + if (SHR_FAILURE(rv)) { + if (dev->mode == DEV_MODE_VNET) { + dev->xnet_wake(dev); + } + + if (txq->state & PDMA_TX_QUEUE_POLL) { + /* In polling mode, must wait till the ring is available */ + do { + cmicx_pdma_tx_ring_clean(hw, txq, txq->free_thresh); + if (!(txq->state & PDMA_TX_QUEUE_XOFF)) { + break; + } + sal_usleep(1); + } while (retry--); + if (retry <= 0) { + CNET_PR("Fatal error: Tx ring is full, packets have not been transmitted for 5 seconds\n"); + if (!dev->tx_suspend) { + sal_sem_give(txq->sem); + return SHR_E_RESOURCE; + } + } + } else { + /* In interrupt mode, the handle thread will wake up Tx */ + if (!dev->tx_suspend) { + return SHR_E_NONE; + } + } + } + + if (dev->tx_suspend) { + sal_spinlock_unlock(txq->mutex); + } else { + sal_sem_give(txq->sem); + } + + return SHR_E_NONE; +} + +/*! + * Suspend Rx queue + */ +static int +cmicx_pdma_rx_suspend(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + sal_spinlock_lock(rxq->lock); + rxq->state |= PDMA_RX_QUEUE_XOFF; + if (hw->dev->flags & PDMA_CHAIN_MODE) { + hw->hdls.chan_stop(hw, rxq->chan_id); + } + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; +} + +/*! + * Resume Rx queue + */ +static int +cmicx_pdma_rx_resume(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + sal_spinlock_lock(rxq->lock); + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + sal_spinlock_unlock(rxq->lock); + return SHR_E_NONE; + } + if (rxq->state & PDMA_RX_BATCH_REFILL) { + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } else if (rxq->halt == rxq->curr || (rxq->halt == rxq->nb_desc && rxq->curr == 0)) { + rxq->halt = (rxq->curr + 1) % rxq->nb_desc; + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } + if (hw->dev->flags & PDMA_CHAIN_MODE) { + rxq->curr = 0; + hw->hdls.chan_start(hw, rxq->chan_id); + } + rxq->state &= ~PDMA_RX_QUEUE_XOFF; + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; +} + +/*! + * Initialize function pointers + */ +int +bcmcnet_cmicx_pdma_desc_ops_init(struct pdma_hw *hw) +{ + if (!hw) { + return SHR_E_PARAM; + } + + hw->dops.rx_desc_init = cmicx_pdma_rx_desc_init; + hw->dops.rx_desc_clean = cmicx_pdma_rx_desc_clean; + hw->dops.rx_ring_clean = cmicx_pdma_rx_ring_clean; + hw->dops.rx_ring_dump = cmicx_pdma_rx_ring_dump; + hw->dops.rx_suspend = cmicx_pdma_rx_suspend; + hw->dops.rx_resume = cmicx_pdma_rx_resume; + hw->dops.tx_desc_init = cmicx_pdma_tx_desc_init; + hw->dops.tx_desc_clean = cmicx_pdma_tx_desc_clean; + hw->dops.tx_ring_clean = cmicx_pdma_tx_ring_clean; + hw->dops.tx_ring_dump = cmicx_pdma_tx_ring_dump; + hw->dops.pkt_xmit = cmicx_pdma_pkt_xmit; + + return SHR_E_NONE; +} + +/*! + * Attach device driver + */ +int +bcmcnet_cmicx_pdma_driver_attach(struct pdma_dev *dev) +{ + struct pdma_hw *hw = NULL; + + /* Allocate memory for HW data */ + hw = sal_alloc(sizeof(*hw), "bcmcnetPdmaHw"); + if (!hw) { + return SHR_E_MEMORY; + } + sal_memset(hw, 0, sizeof(*hw)); + hw->unit = dev->unit; + hw->dev = dev; + dev->ctrl.hw = hw; + + bcmcnet_cmicx_pdma_hw_hdls_init(hw); + bcmcnet_cmicx_pdma_desc_ops_init(hw); + + return SHR_E_NONE; +} + +/*! + * Detach device driver + */ +int +bcmcnet_cmicx_pdma_driver_detach(struct pdma_dev *dev) +{ + if (dev->ctrl.hw) { + sal_free(dev->ctrl.hw); + } + dev->ctrl.hw = NULL; + + return SHR_E_NONE; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicd.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicd.h new file mode 100644 index 000000000000..ef9717923e70 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicd.h @@ -0,0 +1,369 @@ +/*! \file bcmcnet_cmicd.h + * + * CMICd registers and descriptors definitions. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_CMICD_H +#define BCMCNET_CMICD_H + +/*! + * \name CMICD PDMA HW definitions + */ +/*! \{ */ +/*! CMICD CMC number */ +#define CMICD_PDMA_CMC_MAX 3 +/*! CMICD CMC PDMA channels */ +#define CMICD_PDMA_CMC_CHAN 4 +/*! CMICD PDMA DCB size */ +#define CMICD_PDMA_DCB_SIZE 64 +/*! \} */ + +/*! + * \name CMICD PDMA register definitions + */ +/*! \{ */ +#define CMICD_PDMA_CTRLr 0x0140 +#define CMICD_PDMA_STATr 0x0150 +#define CMICD_PDMA_STAT_HIr 0x0130 +#define CMICD_PDMA_STAT_CLRr 0x01a4 +#define CMICD_PDMA_DESCr 0x0158 +#define CMICD_PDMA_CURR_DESCr 0x01a8 +#define CMICD_PDMA_DESC_HALTr 0x0120 +#define CMICD_PDMA_COS_RX0r 0x0168 +#define CMICD_PDMA_COS_RX1r 0x016c +#define CMICD_PDMA_COS_MASK0r 0x019c +#define CMICD_PDMA_COS_MASK1r 0x01a0 +#define CMICD_PDMA_INTR_COALr 0x0188 +#define CMICD_PDMA_RBUF_THREr 0x0110 +#define CMICD_PDMA_COUNT_RXr 0x0480 +#define CMICD_PDMA_COUNT_TXr 0x0484 +#define CMICD_PDMA_COUNT_ALL_RXr 0x04a0 +#define CMICD_PDMA_COUNT_ALL_TXr 0x04a4 +#define CMICD_IRQ_STATr 0x0400 +#define CMICD_IRQ_PCI_MASKr 0x0414 +#define CMICD_IRQ_UC0_MASKr 0x0428 +/*! \} */ + +/*! + * \name CMICD PDMA register address + */ +/*! \{ */ +/*! Base address */ +#define CMICD_GRP_BASE(g) (0x00031000 + 0x1000 * g) +/*! Control register address */ +#define CMICD_PDMA_CTRL(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_CTRLr + q * 4) +/*! Status register address */ +#define CMICD_PDMA_STAT(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_STATr) +/*! Status higher register address */ +#define CMICD_PDMA_STAT_HI(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_STAT_HIr) +/*! Status clear register address */ +#define CMICD_PDMA_STAT_CLR(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_STAT_CLRr) +/*! Descriptor register address */ +#define CMICD_PDMA_DESC(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_DESCr + q * 4) +/*! Current descriptor register address */ +#define CMICD_PDMA_CURR_DESC(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_CURR_DESCr + q * 4) +/*! Descriptor halt register address */ +#define CMICD_PDMA_DESC_HALT(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_DESC_HALTr + q * 4) +/*! COS Rx0 register address */ +#define CMICD_PDMA_COS_RX0(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_RX0r + q * 8) +/*! COS Rx1 register address */ +#define CMICD_PDMA_COS_RX1(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_RX1r + q * 8) +/*! COS Mask0 register address */ +#define CMICD_PDMA_COS_MASK0(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_MASK0r) +/*! COS Mask1 register address */ +#define CMICD_PDMA_COS_MASK1(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_MASK1r) +/*! Interrupt coalesce register address */ +#define CMICD_PDMA_INTR_COAL(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_INTR_COALr + q * 4) +/*! Rx buffer threshhold register address */ +#define CMICD_PDMA_RBUF_THRE(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_RBUF_THREr + q * 4) +/*! Rx counter register address */ +#define CMICD_PDMA_COUNT_RX(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_RXr + q * 8) +/*! Tx counter register address */ +#define CMICD_PDMA_COUNT_TX(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_TXr + q * 8) +/*! Rx global counter register address */ +#define CMICD_PDMA_COUNT_ALL_RX(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_ALL_RXr) +/*! Tx gloable counter register address */ +#define CMICD_PDMA_COUNT_ALL_TX(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_ALL_TXr) +/*! Interrupt status register address */ +#define CMICD_IRQ_STAT(g) (CMICD_GRP_BASE(g) + CMICD_IRQ_STATr) +/*! Interrupt PCI mask register address */ +#define CMICD_IRQ_PCI_MASK(g) (CMICD_GRP_BASE(g) + CMICD_IRQ_PCI_MASKr) +/*! Interrupt UC0 mask register address */ +#define CMICD_IRQ_UC0_MASK(g) (CMICD_GRP_BASE(g) + CMICD_IRQ_UC0_MASKr) +/*! Credits release release register address */ +#define CMICD_EPINTF_RELEASE_CREDITS 0x0001a000 +/*! Device revision register address */ +#define CMICD_DEV_REV_ID 0x00010224 +/*! CMIC revison register address */ +#define CMICD_CMICM_REV_ID 0x00010228 +/*! \} */ + +/*! + * \name Control register definitions + */ +/*! \{ */ +/*! Continuous DMA mode */ +#define CMICD_PDMA_CONTINUOUS 0x00000200 +/*! Controlled interrupt */ +#define CMICD_PDMA_CNTLD_INTR 0x00000100 +/*! Update status on reload */ +#define CMICD_PDMA_RLD_STAT_DIS 0x00000080 +/*! Dropped on chain end */ +#define CMICD_PDMA_DROP_ON_END 0x00000040 +/*! Descriptor big endianess */ +#define CMICD_PDMA_DESC_BIG_ENDIAN 0x00000020 +/*! Packet DMA big endianess */ +#define CMICD_PDMA_PKT_BIG_ENDIAN 0x00000010 +/*! Interrupt after descriptor */ +#define CMICD_PDMA_INTR_ON_DESC 0x00000008 +/*! Abort DMA */ +#define CMICD_PDMA_ABORT 0x00000004 +/*! Enable DMA */ +#define CMICD_PDMA_ENABLE 0x00000002 +/*! DMA direction */ +#define CMICD_PDMA_DIR 0x00000001 +/*! \} */ + +/*! + * \name Status register definitions + */ +/*! \{ */ +/*! Chain done */ +#define CMICD_PDMA_CHAIN_DONE(q) (0x00000001 << (q)) +/*! Descriptor done */ +#define CMICD_PDMA_DESC_DONE(q) (0x00000010 << (q)) +/*! Active */ +#define CMICD_PDMA_ACTIVE(q) (0x00000100 << (q)) +/*! \} */ + +/*! + * \name Status clear register definitions + */ +/*! \{ */ +/*! Clear completed interrupt */ +#define CMICD_PDMA_DESC_CMPLT(q) (0x00000001 << (q)) +/*! Clear controlled interrupt */ +#define CMICD_PDMA_DESC_CNTLD(q) (0x00000100 << (q)) +/*! \} */ + +/*! + * \name Interrupt_coalesce register definitions + */ +/*! \{ */ +/*! Interrupt coalesce enable */ +#define CMICD_PDMA_INTR_COAL_ENA (1 << 31) +/*! Interrupt coalesce threshhold */ +#define CMICD_PDMA_INTR_THRESH(cnt) (((cnt) & 0x7fff) << 16) +/*! Interrupt coalesce timeout */ +#define CMICD_PDMA_INTR_TIMER(tmr) ((tmr) & 0xffff) +/*! \} */ + +/*! + * \name Interrupt status&mask register definitions + */ +/*! \{ */ +/*! Interrupt mask */ +#define CMICD_PDMA_IRQ_MASK 0x78000000 +/*! Descriptor done */ +#define CMICD_IRQ_DESC_DONE(q) (0x00004000 >> (2 * (q))) +/*! Chain done */ +#define CMICD_IRQ_CHAIN_DONE(q) (0x00008000 >> (2 * (q))) +/*! Controlled interrupt */ +#define CMICD_IRQ_DESC_CNTLD(q) (0x08000000 << (q)) +/*! Interrupt start number */ +#define CMICD_IRQ_START_NUM 27 +/*! Interrupt number offset */ +#define CMICD_IRQ_NUM_OFFSET 1 +/*! Interrupt mask shift */ +#define CMICD_IRQ_MASK_SHIFT 0 +/*! Interrupt mask zeroing */ +#define CMICD_IRQ_ACT_CHAN(mask) (((mask) & CMICD_PDMA_IRQ_MASK) >> CMICD_IRQ_START_NUM) +/*! \} */ + +/*! 32-bit register read */ +#define DEV_READ32(_c, _a, _p) \ + do { \ + if ((_c)->dev->mode != DEV_MODE_VNET) { \ + *(_p) = ((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4]; \ + } \ + } while (0) + +/*! 32-bit register write */ +#define DEV_WRITE32(_c, _a, _v) \ + do { \ + if ((_c)->dev->mode != DEV_MODE_VNET) { \ + ((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4] = (_v); \ + } \ + } while (0) + +/*! + * \brief Rx metadata in descriptor. + */ +struct rx_metadata { + /*! Metadata */ + volatile uint32_t data[13]; + + /*! Status */ + volatile uint32_t status; +} __attribute__((packed)); + +/*! + * \brief Rx descriptor. + */ +struct cmicd_rx_desc { + /*! Packet address */ + volatile uint32_t addr; + + /*! Packet control */ + volatile uint32_t ctrl; + + /*! Metadata fields */ + struct rx_metadata md; +} __attribute__((packed)); + +/*! Reserve Rx meta data size in packet buffer */ +#define CMICD_RX_META_RESV 64 + +/*! + * \brief Tx metadata in descriptor. + */ +struct tx_metadata { + /*! Metadata */ + volatile uint32_t data[4]; + + /*! Reserved */ + volatile uint32_t rsvd[9]; + + /*! Status */ + volatile uint32_t status; +} __attribute__((packed)); + +/*! + * \brief Tx descriptor. + */ +struct cmicd_tx_desc { + /*! Packet address */ + volatile uint32_t addr; + + /*! Packet control */ + volatile uint32_t ctrl; + + /*! Metadata fields */ + struct tx_metadata md; +} __attribute__((packed)); + +/*! Reserve Tx meta data size in packet buffer */ +#define CMICD_TX_META_RESV 16 + +/*! + * Flags related to descriptors. + */ +/*! Controlled interrupt */ +#define CMICD_DESC_CTRL_CNTLD_INTR (1 << 24) +/*! Completed interrupt */ +#define CMICD_DESC_CTRL_CMPLT_INTR (1 << 23) +/*! Reload DCB */ +#define CMICD_DESC_CTRL_RELOAD (1 << 18) +/*! Scatter DCB */ +#define CMICD_DESC_CTRL_SCATTER (1 << 17) +/*! Chained DCB */ +#define CMICD_DESC_CTRL_CHAIN (1 << 16) +/*! Control flags */ +#define CMICD_DESC_CTRL_FLAGS(f) (((f) & 0xffff) << 16) +/*! Purge packet */ +#define CMICD_DESC_TX_PURGE_PKT (1 << 6) +/*! Pause packet */ +#define CMICD_DESC_TX_PAUSE_PKT (1 << 5) +/*! Higig packet */ +#define CMICD_DESC_TX_HIGIG_PKT (1 << 3) +/*! Packet length */ +#define CMICD_DESC_CTRL_LEN(len) ((len) & 0xffff) +/*! Done */ +#define CMICD_DESC_STAT_RTX_DONE (1 << 31) +/*! Head error */ +#define CMICD_DESC_STAT_HEAD_ERR (1 << 20) +/*! Data error */ +#define CMICD_DESC_STAT_DATA_ERR (1 << 19) +/*! Cell error */ +#define CMICD_DESC_STAT_CELL_ERR (1 << 18) +/*! Error mask */ +#define CMICD_DESC_STAT_ERR_MASK (CMICD_DESC_STAT_HEAD_ERR | \ + CMICD_DESC_STAT_DATA_ERR | \ + CMICD_DESC_STAT_CELL_ERR) +/*! Packet start */ +#define CMICD_DESC_STAT_PKT_START (1 << 17) +/*! Packet end */ +#define CMICD_DESC_STAT_PKT_END (1 << 16) +/*! Get done state */ +#define CMICD_DESC_STAT_DONE(stat) ((stat) & CMICD_DESC_STAT_RTX_DONE) +/*! Get flags */ +#define CMICD_DESC_STAT_FLAGS(stat) (((stat) >> 16) & ~0x8003) +/*! Get packet length */ +#define CMICD_DESC_STAT_LEN(stat) ((stat) & 0xffff) + +/*! HW access retry times */ +#define CMICD_HW_RETRY_TIMES 100000 + +/*! + * \brief Initialize HW handles. + * + * \param [in] hw HW structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicd_pdma_hw_hdls_init(struct pdma_hw *hw); + +/*! + * \brief Initialize descriptor operations. + * + * \param [in] hw HW structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicd_pdma_desc_ops_init(struct pdma_hw *hw); + +/*! + * \brief Attach device driver. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicd_pdma_driver_attach(struct pdma_dev *dev); + +/*! + * \brief Detach device driver. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicd_pdma_driver_detach(struct pdma_dev *dev); + +#endif /* BCMCNET_CMICD_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicx.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicx.h new file mode 100644 index 000000000000..a8657c8b46a9 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicx.h @@ -0,0 +1,379 @@ +/*! \file bcmcnet_cmicx.h + * + * CMICx registers and descriptors definitions. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_CMICX_H +#define BCMCNET_CMICX_H + +/*! + * \name CMICX PDMA HW definitions + */ +/*! \{ */ +/*! CMICX CMC number */ +#define CMICX_PDMA_CMC_MAX 2 +/*! CMICX CMC PDMA channels */ +#define CMICX_PDMA_CMC_CHAN 8 +/*! CMICX PDMA DCB size */ +#define CMICX_PDMA_DCB_SIZE 16 +/*! \} */ + +/*! + * \name CMICX PCIe device address definitions + */ +/*! \{ */ +/*! CMICX PCIE offset */ +#define CMICX_PCIE_SO_OFFSET 0x10000000 +/*! Higher DMA address to bus address */ +#define DMA_TO_BUS_HI(dma) ((dma) | CMICX_PCIE_SO_OFFSET) +/*! Higher bus address to DMA address */ +#define BUS_TO_DMA_HI(bus) ((bus) & ~CMICX_PCIE_SO_OFFSET) +/*! \} */ + +/*! + * \name CMICX PDMA register definitions + */ +/*! \{ */ +#define CMICX_PDMA_CTRLr 0x2100 +#define CMICX_PDMA_STATr 0x2114 +#define CMICX_PDMA_DESC_LOr 0x2104 +#define CMICX_PDMA_DESC_HIr 0x2108 +#define CMICX_PDMA_CURR_DESC_LOr 0x2124 +#define CMICX_PDMA_CURR_DESC_HIr 0x2128 +#define CMICX_PDMA_DESC_HALT_LOr 0x210c +#define CMICX_PDMA_DESC_HALT_HIr 0x2110 +#define CMICX_PDMA_COS_CTRL_RX0r 0x2118 +#define CMICX_PDMA_COS_CTRL_RX1r 0x211c +#define CMICX_PDMA_INTR_COALr 0x2120 +#define CMICX_PDMA_RBUF_THREr 0x212c +#define CMICX_PDMA_DEBUG_CTRLr 0x2130 +#define CMICX_PDMA_DEBUG_SM_STATr 0x2134 +#define CMICX_PDMA_DEBUG_STATr 0x2138 +#define CMICX_PDMA_COUNT_RXr 0x213c +#define CMICX_PDMA_COUNT_TXr 0x2140 +#define CMICX_PDMA_COUNT_RX_DROPr 0x2144 +#define CMICX_PDMA_DESC_CNT_REQr 0x2148 +#define CMICX_PDMA_DESC_CNT_RXr 0x214c +#define CMICX_PDMA_DESC_CNT_STATr 0x2150 +#define CMICX_PDMA_IRQ_STATr 0x106c +#define CMICX_PDMA_IRQ_STAT_CLRr 0x1074 +/*! \} */ + +/*! + * \name CMICX PDMA register address + */ +/*! \{ */ +/*! Base address */ +#define CMICX_GRP_BASE(g) (0x00000000 + 0x3000 * g) +/*! Control register address */ +#define CMICX_PDMA_CTRL(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_CTRLr + q * 0x80) +/*! Status register address */ +#define CMICX_PDMA_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_STATr + q * 0x80) +/*! Descriptor Address Lower register address */ +#define CMICX_PDMA_DESC_LO(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_LOr + q * 0x80) +/*! Descriptor Address Higher register address */ +#define CMICX_PDMA_DESC_HI(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_HIr + q * 0x80) +/*! Current Descriptor Address Lower register address */ +#define CMICX_PDMA_CURR_DESC_LO(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_CURR_DESC_LOr + q * 0x80) +/*! Current Descriptor Address Higher register address */ +#define CMICX_PDMA_CURR_DESC_HI(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_CURR_DESC_HIr + q * 0x80) +/*! Descriptor Halt Address Lower register address */ +#define CMICX_PDMA_DESC_HALT_LO(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_HALT_LOr + q * 0x80) +/*! Descriptor Halt Address Higher register address */ +#define CMICX_PDMA_DESC_HALT_HI(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_HALT_HIr + q * 0x80) +/*! COS Control Rx0 register address */ +#define CMICX_PDMA_COS_CTRL_RX0(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COS_CTRL_RX0r + q * 0x80) +/*! COS Control Rx1 register address */ +#define CMICX_PDMA_COS_CTRL_RX1(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COS_CTRL_RX1r + q * 0x80) +/*! Interrupt Coalesce register address */ +#define CMICX_PDMA_INTR_COAL(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_INTR_COALr + q * 0x80) +/*! Rx Buffer Threshhold register address */ +#define CMICX_PDMA_RBUF_THRE(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_RBUF_THREr + q * 0x80) +/*! Debug Control register address */ +#define CMICX_PDMA_DEBUG_CTRL(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DEBUG_CTRLr + q * 0x80) +/*! Debug Status register address */ +#define CMICX_PDMA_DEBUG_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DEBUG_STATr + q * 0x80) +/*! Debug State Machine Status register address */ +#define CMICX_PDMA_DEBUG_SM_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DEBUG_SM_STATr + q * 0x80) +/*! Rx Packet Count register address */ +#define CMICX_PDMA_COUNT_RX(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COUNT_RXr + q * 0x80) +/*! Tx Packet Count register address */ +#define CMICX_PDMA_COUNT_TX(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COUNT_TXr + q * 0x80) +/*! Dropped Rx Packet Count register address */ +#define CMICX_PDMA_COUNT_RX_DROP(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COUNT_RX_DROPr + q * 0x80) +/*! Requested Descriptor Count register address */ +#define CMICX_PDMA_DESC_CNT_REQ(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_CNT_REQr + q * 0x80) +/*! Received Descriptor Count register address */ +#define CMICX_PDMA_DESC_CNT_RX(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_CNT_RXr + q * 0x80) +/*! Updated Descriptor Count register address */ +#define CMICX_PDMA_DESC_CNT_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_CNT_STATr + q * 0x80) +/*! Interrupt Status register address */ +#define CMICX_PDMA_IRQ_STAT(g) (CMICX_GRP_BASE(g) + CMICX_PDMA_IRQ_STATr) +/*! Interrupt Status Clear register address */ +#define CMICX_PDMA_IRQ_STAT_CLR(g) (CMICX_GRP_BASE(g) + CMICX_PDMA_IRQ_STAT_CLRr) +/*! Interrupt Enable register address0 */ +#define CMICX_PDMA_IRQ_ENAB0 0x18013100 +/*! Interrupt Enable register address1 */ +#define CMICX_PDMA_IRQ_ENAB1 0x18013104 +/*! Interrupt Enable register address2 */ +#define CMICX_PDMA_IRQ_ENAB2 0x18013108 +/*! Interrupt raw status register address0 */ +#define CMICX_PDMA_IRQ_RAW_STAT0 0x18013150 +/*! Interrupt raw status register address1 */ +#define CMICX_PDMA_IRQ_RAW_STAT1 0x18013154 +/*! Interrupt raw status register address2 */ +#define CMICX_PDMA_IRQ_RAW_STAT2 0x18013158 +/*! EP_TO_CPU Header Size register address */ +#define CMICX_EP_TO_CPU_HEADER_SIZE 0x00000004 +/*! Top config register address */ +#define CMICX_TOP_CONFIG 0x00000008 +/*! Credits release register address */ +#define CMICX_EPINTF_RELEASE_CREDITS 0x0000006c +/*! Max credits register address */ +#define CMICX_EPINTF_MAX_CREDITS 0x00000070 +/*! \} */ + +/*! + * \name Control register definitions + */ +/*! \{ */ +/*! Disable abort on error */ +#define CMICX_PDMA_NO_ABORT_ON_ERR 0x00002000 +/*! EP_TO_CPU header big endianess */ +#define CMICX_PDMA_HDR_BIG_ENDIAN 0x00001000 +/*! Continuous descriptor mode */ +#define CMICX_PDMA_CONTINUOUS_DESC 0x00000200 +/*! Continuous DMA mode */ +#define CMICX_PDMA_CONTINUOUS 0x00000100 +/*! Interrupt after descriptor */ +#define CMICX_PDMA_INTR_ON_DESC 0x00000080 +/*! Update status on reload */ +#define CMICX_PDMA_RLD_STAT_DIS 0x00000040 +/*! Dropped on chain end */ +#define CMICX_PDMA_DROP_ON_END 0x00000020 +/*! Descriptor big endianess */ +#define CMICX_PDMA_DESC_BIG_ENDIAN 0x00000010 +/*! Packet DMA big endianess */ +#define CMICX_PDMA_PKT_BIG_ENDIAN 0x00000008 +/*! Abort DMA */ +#define CMICX_PDMA_ABORT 0x00000004 +/*! Enable DMA */ +#define CMICX_PDMA_ENABLE 0x00000002 +/*! DMA direction */ +#define CMICX_PDMA_DIR 0x00000001 +/*! EP_TO_CPU header alignment bytes */ +#define CMICX_PDMA_HDR_ALMNT(bytes) (((bytes) & 0x3) << 10) +/*! \} */ + +/*! + * \name Status register definitions + */ +/*! \{ */ +/*! Channel in halt */ +#define CMICX_PDMA_IN_HALT 0x00000040 +/*! Channel active */ +#define CMICX_PDMA_IS_ACTIVE 0x00000002 +/*! Chain done */ +#define CMICX_PDMA_CHAIN_DONE 0x00000001 +/*! \} */ + +/*! + * \name Interrupt_coalesce register definitions + */ +/*! \{ */ +/*! Interrupt coalesce enable */ +#define CMICX_PDMA_INTR_COAL_ENA (1 << 31) +/*! Interrupt coalesce threshhold */ +#define CMICX_PDMA_INTR_THRESH(cnt) (((cnt) & 0x7fff) << 16) +/*! Interrupt coalesce timeout */ +#define CMICX_PDMA_INTR_TIMER(tmr) ((tmr) & 0xffff) +/*! \} */ + +/*! + * \name Interrupt status&clear register definitions + */ +/*! \{ */ +/*! Descriptor done */ +#define CMICX_PDMA_IRQ_DESC_DONE(q) (0x00000001 << ((q) * 4)) +/*! Chain done */ +#define CMICX_PDMA_IRQ_CHAIN_DONE(q) (0x00000002 << ((q) * 4)) +/*! Coalescing interrupt */ +#define CMICX_PDMA_IRQ_COALESCE_INTR(q) (0x00000004 << ((q) * 4)) +/*! Controlled interrupt */ +#define CMICX_PDMA_IRQ_CTRLD_INTR(q) (0x00000008 << ((q) * 4)) +/*! Interrupt mask */ +#define CMICX_PDMA_IRQ_MASK(q) (0xf << ((q) * 4)) +/*! Interrupt start number */ +#define CMICX_IRQ_START_NUM (128 + 3) +/*! Interrupt number offset */ +#define CMICX_IRQ_NUM_OFFSET 4 +/*! Interrupt mask shift */ +#define CMICX_IRQ_MASK_SHIFT 16 +/*! \} */ + +/*! 32-bit register read */ +#define DEV_READ32(_c, _a, _p) \ + do { \ + if ((_c)->dev->mode != DEV_MODE_VNET) { \ + *(_p) = ((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4]; \ + } \ + } while (0) + +/*! 32-bit register write */ +#define DEV_WRITE32(_c, _a, _v) \ + do { \ + if ((_c)->dev->mode != DEV_MODE_VNET) { \ + ((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4] = (_v); \ + } \ + } while (0) + +/*! + * \brief Rx descriptor. + */ +struct cmicx_rx_desc { + /*! Packet address lower */ + volatile uint32_t addr_lo; + + /*! Packet address higher */ + volatile uint32_t addr_hi; + + /*! Packet control */ + volatile uint32_t ctrl; + + /*! Packet status */ + volatile uint32_t status; +} __attribute__((packed)); + +/*! + * \brief Tx descriptor. + */ +struct cmicx_tx_desc { + /*! Packet address lower */ + volatile uint32_t addr_lo; + + /*! Packet address higher */ + volatile uint32_t addr_hi; + + /*! Packet control */ + volatile uint32_t ctrl; + + /*! Packet status */ + volatile uint32_t status; +} __attribute__((packed)); + +/*! + * Flags related to descriptors. + */ +/*! Disable descriptor status write */ +#define CMICX_DESC_CTRL_STAT_WR_DIS (1 << 29) +/*! Descriptors remaining */ +#define CMICX_DESC_CTRL_REMAIN(cnt) (((cnt) & 0xf) << 25) +/*! Max remaining descriptors */ +#define CMICX_DESC_REMAIN_MAX 8 +/*! Controlled interrupt */ +#define CMICX_DESC_CTRL_CNTLD_INTR (1 << 24) +/*! Completed interrupt */ +#define CMICX_DESC_CTRL_CMPLT_INTR (1 << 23) +/*! Reload DCB */ +#define CMICX_DESC_CTRL_RELOAD (1 << 18) +/*! Scatter DCB */ +#define CMICX_DESC_CTRL_SCATTER (1 << 17) +/*! Chained DCB */ +#define CMICX_DESC_CTRL_CHAIN (1 << 16) +/*! Control flags */ +#define CMICX_DESC_CTRL_FLAGS(f) (((f) & 0xffff) << 16) +/*! Purge packet */ +#define CMICX_DESC_TX_PURGE_PKT (1 << 6) +/*! Higig packet */ +#define CMICX_DESC_TX_HIGIG_PKT (1 << 3) +/*! Packet length */ +#define CMICX_DESC_CTRL_LEN(len) ((len) & 0xffff) +/*! Done */ +#define CMICX_DESC_STAT_RTX_DONE (1 << 31) +/*! Ecc error */ +#define CMICX_DESC_STAT_DATA_ERR (1 << 19) +/*! Cell error */ +#define CMICX_DESC_STAT_CELL_ERR (1 << 18) +/*! Error mask */ +#define CMICX_DESC_STAT_ERR_MASK (CMICX_DESC_STAT_DATA_ERR | \ + CMICX_DESC_STAT_CELL_ERR) +/*! Packet start */ +#define CMICX_DESC_STAT_PKT_START (1 << 17) +/*! Packet end */ +#define CMICX_DESC_STAT_PKT_END (1 << 16) +/*! Get done state */ +#define CMICX_DESC_STAT_DONE(stat) ((stat) & CMICX_DESC_STAT_RTX_DONE) +/*! Get flags */ +#define CMICX_DESC_STAT_FLAGS(stat) (((stat) >> 16) & ~0x8003) +/*! Get packet length */ +#define CMICX_DESC_STAT_LEN(stat) ((stat) & 0xffff) + +/*! Tx packet header size */ +#define CMICX_TX_PKT_HDR_SIZE 16 + +/*! HW access retry times */ +#define CMICX_HW_RETRY_TIMES 100000 + +/*! + * \brief Initialize HW handles. + * + * \param [in] hw HW structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicx_pdma_hw_hdls_init(struct pdma_hw *hw); + +/*! + * \brief Initialize descriptor operations. + * + * \param [in] hw HW structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicx_pdma_desc_ops_init(struct pdma_hw *hw); + +/*! + * \brief Attach device driver. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicx_pdma_driver_attach(struct pdma_dev *dev); + +/*! + * \brief Detach device driver. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicx_pdma_driver_detach(struct pdma_dev *dev); + +#endif /* BCMCNET_CMICX_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_core.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_core.h new file mode 100644 index 000000000000..13db809dda36 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_core.h @@ -0,0 +1,1323 @@ +/*! \file bcmcnet_core.h + * + * Generic data structure definitions and APIs for BCMCNET driver. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_CORE_H +#define BCMCNET_CORE_H + +#include +#include + +/*! + * \brief Packet header structure. + */ +struct pkt_hdr { + /*! Meta data or outer header */ + uint8_t meta_data[16]; + + /*! Reserved */ + uint16_t rsvd0; + + /*! Packet signature */ + uint16_t pkt_sig; + + /*! Reserved */ + uint32_t rsvd1; + + /*! Data length */ + uint16_t data_len; + + /*! Reserved */ + uint16_t rsvd2; + + /*! Meta length */ + uint8_t meta_len; + + /*! Queue index */ + uint8_t queue_id; + + /*! Attributes */ + uint16_t attrs; + /*! Tx higig packet */ +#define PDMA_TX_HIGIG_PKT (1 << 0) + /*! Tx pause packet */ +#define PDMA_TX_PAUSE_PKT (1 << 1) + /*! Tx purge packet */ +#define PDMA_TX_PURGE_PKT (1 << 2) + /*! Tx queue number */ +#define PDMA_TX_BIND_QUE (1 << 3) + /*! Tx cookded header */ +#define PDMA_TX_HDR_COOKED (1 << 4) + /*! Tx to HNET */ +#define PDMA_TX_TO_HNET (1 << 5) + /*! Rx to VNET */ +#define PDMA_RX_TO_VNET (1 << 10) + /*! Rx strip vlan tag */ +#define PDMA_RX_STRIP_TAG (1 << 11) + /*! Rx set protocol type */ +#define PDMA_RX_SET_PROTO (1 << 12) + /*! Rx IP checksum */ +#define PDMA_RX_IP_CSUM (1 << 13) + /*! Rx TCPUDP checksum */ +#define PDMA_RX_TU_CSUM (1 << 14) +}; + +/*! Packet header size */ +#define PKT_HDR_SIZE sizeof(struct pkt_hdr) + +/*! + * \brief Packet buffer structure. + */ +struct pkt_buf { + /*! Packet header */ + struct pkt_hdr pkh; + + /*! Packet data */ + uint8_t data; +}; + +/*! + * \brief Interrupt handle. + */ +struct intr_handle { + /*! Device number */ + int unit; + + /*! Group number */ + int group; + + /*! Channel number */ + int chan; + + /*! Queue number */ + int queue; + + /*! Direction */ + int dir; + + /*! Polling budget */ + int budget; + + /*! Device point */ + void *dev; + + /*! Private point */ + void *priv; + + /*! Interrupt number */ + int intr_num; + + /*! Interrupt flags */ + uint32_t intr_flags; +}; + +/*! + * \brief Queue group structure. + */ +struct queue_group { + /*! Pointer to the device control structure */ + struct dev_ctrl *ctrl; + + /*! Interrupt handles */ + struct intr_handle intr_hdl[NUM_Q_PER_GRP]; + + /*! Rx queue pointers */ + void *rx_queue[NUM_Q_PER_GRP]; + + /*! Tx queue pointers */ + void *tx_queue[NUM_Q_PER_GRP]; + + /*! Virtual Rx queue pointers */ + void *vnet_rxq[NUM_Q_PER_GRP]; + + /*! Virtual Tx queue pointers */ + void *vnet_txq[NUM_Q_PER_GRP]; + + /*! Bitmap for Rx queues at work */ + uint32_t bm_rxq; + + /*! Bitmap for Tx queues at work */ + uint32_t bm_txq; + + /*! Number of Rx queues at work */ + uint32_t nb_rxq; + + /*! Number of Tx queues at work */ + uint32_t nb_txq; + + /*! Number of descriptors */ + uint32_t nb_desc[NUM_Q_PER_GRP]; + + /*! Rx buffer size */ + uint32_t rx_size[NUM_Q_PER_GRP]; + + /*! Queue mode */ + uint32_t que_ctrl[NUM_Q_PER_GRP]; + /*! Packet_byte_swap */ +#define PDMA_PKT_BYTE_SWAP (1 << 0) + /*! Non packet_byte_swap */ +#define PDMA_OTH_BYTE_SWAP (1 << 1) + /*! Header_byte_swap */ +#define PDMA_HDR_BYTE_SWAP (1 << 2) + + /*! Group ID */ + int id; + + /*! Queues need to poll */ + uint32_t poll_queues; + + /*! Active IRQs for DMA control */ + uint32_t irq_mask; + + /*! Indicating the group is attached */ + int attached; +}; + +/*! + * \brief Device control structure. + */ +struct dev_ctrl { + /*! Pointer to the device structure */ + struct pdma_dev *dev; + + /*! Pointer to hardware-specific data */ + void *hw; + + /*! HW base address */ + volatile void *hw_addr; + + /*! Queue groups */ + struct queue_group grp[NUM_GRP_MAX]; + + /*! Pointers to Rx queues */ + void *rx_queue[NUM_QUE_MAX]; + + /*! Pointers to Tx queues */ + void *tx_queue[NUM_QUE_MAX]; + + /*! Pointers to virtual Rx queues */ + void *vnet_rxq[NUM_QUE_MAX]; + + /*! Pointers to virtual Tx queues */ + void *vnet_txq[NUM_QUE_MAX]; + + /*! Pointer to buffer manager */ + void *buf_mngr; + + /*! VNET sync data */ + vnet_sync_t vsync; + + /*! Bitmap of groups at work */ + uint32_t bm_grp; + + /*! Bitmap of Rx queues at work */ + uint32_t bm_rxq; + + /*! Bitmap of Tx queues at work */ + uint32_t bm_txq; + + /*! Number of groups at work */ + uint32_t nb_grp; + + /*! Number of Rx queues at work */ + uint32_t nb_rxq; + + /*! Number of Tx queues at work */ + uint32_t nb_txq; + + /*! Number of descriptors for a queue */ + uint32_t nb_desc; + + /*! Budget for once queue processing */ + uint32_t budget; + + /*! Common Rx buffer size for all queues */ + uint32_t rx_buf_size; + + /*! Rx descriptor size */ + uint32_t rx_desc_size; + + /*! Tx descriptor size */ + uint32_t tx_desc_size; +}; + +/*! + * Configure device. + * + * \param [in] dev Pointer to device structure. + * \param [in] bm_rxq Rx queue bitmap. + * \param [in] bm_txq Tx queue bitmap. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_config_f)(struct pdma_dev *dev, uint32_t bm_rxq, uint32_t bm_txq); + +/*! + * Start device. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_start_f)(struct pdma_dev *dev); + +/*! + * Stop device. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_stop_f)(struct pdma_dev *dev); + +/*! + * Close device. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_close_f)(struct pdma_dev *dev); + +/*! + * Suspend device. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_suspend_f)(struct pdma_dev *dev); + +/*! + * Resume device. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_resume_f)(struct pdma_dev *dev); + +/*! + * Get device information. + * + * \param [in] dev Pointer to device structure. + */ +typedef void (*pdma_dev_info_get_f)(struct pdma_dev *dev); + +/*! + * Get device statistics. + * + * \param [in] dev Pointer to device structure. + */ +typedef void (*pdma_dev_stats_get_f)(struct pdma_dev *dev); + +/*! + * Reset device statistics. + * + * \param [in] dev Pointer to device structure. + */ +typedef void (*pdma_dev_stats_reset_f)(struct pdma_dev *dev); + +/*! + * Convert logic queue to physical queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Logic queue number. + * \param [in] dir Transmit direction. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_lq2pq_f)(struct pdma_dev *dev, int queue, int dir, int *chan); + +/*! + * Convert physical queue to logic queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] chan Channel number. + * \param [in] queue Logic queue number. + * \param [in] dir Transmit direction. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_pq2lq_f)(struct pdma_dev *dev, int chan, int *queue, int *dir); + +/*! + * Start queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_queue_start_f)(struct pdma_dev *dev, int queue); + +/*! + * Stop queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_queue_stop_f)(struct pdma_dev *dev, int queue); + +/*! + * Set up queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_queue_setup_f)(struct pdma_dev *dev, int queue); + +/*! + * Release queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_queue_release_f)(struct pdma_dev *dev, int queue); + +/*! + * Restore queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_queue_restore_f)(struct pdma_dev *dev, int queue); + +/*! + * Enable queue interrupt. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_intr_enable_f)(struct pdma_dev *dev, int queue); + +/*! + * Disable queue interrupt. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_intr_disable_f)(struct pdma_dev *dev, int queue); + +/*! + * Acknowledge queue interrupt. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_intr_ack_f)(struct pdma_dev *dev, int queue); + +/*! + * Query queue interrupt. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_intr_query_f)(struct pdma_dev *dev, int queue); + +/*! + * Check queue interrupt. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_intr_check_f)(struct pdma_dev *dev, int queue); + +/*! + * Suspend Rx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_rx_queue_suspend_f)(struct pdma_dev *dev, int queue); + +/*! + * Resume Rx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_rx_queue_resume_f)(struct pdma_dev *dev, int queue); + +/*! + * Wake up Tx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_tx_queue_wakeup_f)(struct pdma_dev *dev, int queue); + +/*! + * Poll Rx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * \param [in] budget Max number of descriptor to poll. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_rx_queue_poll_f)(struct pdma_dev *dev, int queue, int budget); + +/*! + * Poll Tx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * \param [in] budget Max number of descriptor to poll. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_tx_queue_poll_f)(struct pdma_dev *dev, int queue, int budget); + +/*! + * Poll queue group. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * \param [in] budget Max number of descriptor to poll. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_group_poll_f)(struct pdma_dev *dev, int group, int budget); + +/*! + * \brief Exported functions structure. + */ +struct dev_ops { + /*! Configure device */ + pdma_dev_config_f dev_config; + + /*! Start device */ + pdma_dev_start_f dev_start; + + /*! Stop device */ + pdma_dev_stop_f dev_stop; + + /*! Close device */ + pdma_dev_close_f dev_close; + + /*! Suspend device */ + pdma_dev_suspend_f dev_suspend; + + /*! Resume device */ + pdma_dev_resume_f dev_resume; + + /*! Get device information */ + pdma_dev_info_get_f dev_info_get; + + /*! Get device statistics */ + pdma_dev_stats_get_f dev_stats_get; + + /*! Reset device statistics */ + pdma_dev_stats_reset_f dev_stats_reset; + + /*! Logic queue to physical queue */ + pdma_dev_lq2pq_f dev_lq_to_pq; + + /*! Physical queue to logic queue */ + pdma_dev_pq2lq_f dev_pq_to_lq; + + /*! Start Rx for a queue */ + pdma_queue_start_f rx_queue_start; + + /*! Stop Rx for a queue */ + pdma_queue_stop_f rx_queue_stop; + + /*! Start Tx for a queue */ + pdma_queue_start_f tx_queue_start; + + /*! Stop Tx for a queue */ + pdma_queue_stop_f tx_queue_stop; + + /*! Set up Rx queue */ + pdma_queue_setup_f rx_queue_setup; + + /*! Release Rx queue */ + pdma_queue_release_f rx_queue_release; + + /*! Restore stopped Rx queue */ + pdma_queue_restore_f rx_queue_restore; + + /*! Set up virtual Rx queue */ + pdma_queue_setup_f rx_vqueue_setup; + + /*! Release virtual Rx queue */ + pdma_queue_release_f rx_vqueue_release; + + /*! Set up Tx queue */ + pdma_queue_setup_f tx_queue_setup; + + /*! Release Tx queue */ + pdma_queue_release_f tx_queue_release; + + /*! Restore stopped Tx queue */ + pdma_queue_restore_f tx_queue_restore; + + /*! Set up virtual Tx queue */ + pdma_queue_setup_f tx_vqueue_setup; + + /*! Release virtual Tx queue */ + pdma_queue_release_f tx_vqueue_release; + + /*! Enable Rx queue interrupt */ + pdma_intr_enable_f rx_queue_intr_enable; + + /*! Disable Rx queue interrupt */ + pdma_intr_disable_f rx_queue_intr_disable; + + /*! Acknowledge interrupt for Rx queue */ + pdma_intr_ack_f rx_queue_intr_ack; + + /*! Query interrupt status for Rx queue */ + pdma_intr_query_f rx_queue_intr_query; + + /*! Check interrupt validity for Rx queue */ + pdma_intr_check_f rx_queue_intr_check; + + /*! Enable Tx queue interrupt */ + pdma_intr_enable_f tx_queue_intr_enable; + + /*! Disable Tx queue interrupt */ + pdma_intr_disable_f tx_queue_intr_disable; + + /*! Acknowledge interrupt for Tx queue */ + pdma_intr_ack_f tx_queue_intr_ack; + + /*! Query interrupt status for Tx queue */ + pdma_intr_query_f tx_queue_intr_query; + + /*! Check interrupt validity for Tx queue */ + pdma_intr_check_f tx_queue_intr_check; + + /*! Suspend a Rx queue */ + pdma_rx_queue_suspend_f rx_queue_suspend; + + /*! Resume a Rx queue */ + pdma_rx_queue_resume_f rx_queue_resume; + + /*! Wake up a Tx queue to transmit */ + pdma_tx_queue_wakeup_f tx_queue_wakeup; + + /*! Poll for a Rx queue */ + pdma_rx_queue_poll_f rx_queue_poll; + + /*! Poll for a Tx queue */ + pdma_tx_queue_poll_f tx_queue_poll; + + /*! Poll for a group */ + pdma_group_poll_f group_poll; +}; + +/*! + * Read 32-bit device register. + * + * \param [in] dev Pointer to device structure. + * \param [in] addr Register address. + * \param [in] data Pointer to read data. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*reg32_read_f)(struct pdma_dev *dev, uint32_t addr, uint32_t *data); + +/*! + * Write 32-bit device register. + * + * \param [in] dev Pointer to device structure. + * \param [in] addr Register address. + * \param [in] data Data to write. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*reg32_write_f)(struct pdma_dev *dev, uint32_t addr, uint32_t data); + +/*! + * Receive packet. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Rx queue number. + * \param [in] buf Pointer to packet buffer. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*pdma_rx_f)(struct pdma_dev *dev, int queue, void *buf); + +/*! + * Transmit packet. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Tx queue number. + * \param [in] buf Pointer to packet buffer. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*pdma_tx_f)(struct pdma_dev *dev, int queue, void *buf); + +/*! + * Suspend Tx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Tx queue number. + */ +typedef void (*sys_tx_suspend_f)(struct pdma_dev *dev, int queue); + +/*! + * Resume Tx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Tx queue number. + */ +typedef void (*sys_tx_resume_f)(struct pdma_dev *dev, int queue); + +/*! + * Enable interrupts. + * + * \param [in] dev Pointer to device structure. + * \param [in] group Channel group number. + * \param [in] chan Channel number. + * \param [in] reg Interrupt enable register. + * \param [in] mask Interrupt mask. + */ +typedef void (*sys_intr_unmask_f)(struct pdma_dev *dev, int group, int chan, + uint32_t reg, uint32_t mask); + +/*! + * Disable interrupts. + * + * \param [in] dev Pointer to device structure. + * \param [in] group Channel group number. + * \param [in] chan Channel number. + * \param [in] reg Interrupt enable register. + * \param [in] mask Interrupt mask. + */ +typedef void (*sys_intr_mask_f)(struct pdma_dev *dev, int group, int chan, + uint32_t reg, uint32_t mask); + +/*! + * Wait for notification from the other side. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*xnet_wait_f)(struct pdma_dev *dev); + +/*! + * Wake up the other side. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*xnet_wake_f)(struct pdma_dev *dev); + +/*! + * Convert physical address to virtual address. + * + * \param [in] dev Pointer to device structure. + * \param [in] paddr Physical address. + * + * \retval Virtual address. + */ +typedef void *(*sys_p2v_f)(struct pdma_dev *dev, uint64_t paddr); + +/*! + * Convert virtual address to physical address. + * + * \param [in] dev Pointer to device structure. + * \param [in] vaddr Virtual address. + * + * \retval Physical address. + */ +typedef uint64_t (*sys_v2p_f)(struct pdma_dev *dev, void *vaddr); + +/*! + * \brief Device structure. + */ +struct pdma_dev { + /*! Device name */ + char name[DEV_NAME_LEN_MAX]; + + /*! Device ID */ + uint32_t dev_id; + + /*! Device type */ + uint32_t dev_type; + + /*! Device Number */ + int unit; + + /*! Device control structure */ + struct dev_ctrl ctrl; + + /*! Pointer to the exported funtions structure */ + struct dev_ops *ops; + + /*! Device information */ + struct bcmcnet_dev_info info; + + /*! Device statistics data */ + struct bcmcnet_dev_stats stats; + + /*! Private data */ + void *priv; + + /*! Read 32-bit device register */ + reg32_read_f dev_read32; + + /*! Write 32-bit device register */ + reg32_write_f dev_write32; + + /*! Packet reception */ + pdma_rx_f pkt_recv; + + /*! Packet transmission */ + pdma_tx_f pkt_xmit; + + /*! Tx suspend */ + sys_tx_suspend_f tx_suspend; + + /*! Tx resume */ + sys_tx_resume_f tx_resume; + + /*! Enable a set of interrupts */ + sys_intr_unmask_f intr_unmask; + + /*! Disable a set of interrupts */ + sys_intr_mask_f intr_mask; + + /*! Virtual network wait for */ + xnet_wait_f xnet_wait; + + /*! Virtual network wake up */ + xnet_wake_f xnet_wake; + + /*! Physical address to virtual address */ + sys_p2v_f sys_p2v; + + /*! Virtual address to physical address */ + sys_v2p_f sys_v2p; + + /*! Maximum number of groups */ + int num_groups; + + /*! Maximum number of group queues */ + int grp_queues; + + /*! Maximum number of queues */ + int num_queues; + + /*! Rx packet header size */ + uint32_t rx_ph_size; + + /*! Tx packet header size */ + uint32_t tx_ph_size; + + /*! Flags */ + uint32_t flags; + /*! Interrupt processing per group */ +#define PDMA_GROUP_INTR (1 << 0) + /*! Tx polling mode */ +#define PDMA_TX_POLLING (1 << 1) + /*! Rx batch refilling */ +#define PDMA_RX_BATCHING (1 << 2) + /*! DMA chain mode */ +#define PDMA_CHAIN_MODE (1 << 3) + /*! Descriptor prefetch mode */ +#define PDMA_DESC_PREFETCH (1 << 4) + /*! VNET is docked */ +#define PDMA_VNET_DOCKED (1 << 5) + + /*! Device mode */ + dev_mode_t mode; + + /*! Device is started */ + int started; + + /*! Device is initialized and HMI driver is attached */ + int attached; +}; + +/*! + * \brief Initialize device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_init(struct pdma_dev *dev); + +/*! + * \brief Clean up device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_cleanup(struct pdma_dev *dev); + +/*! + * \brief Start device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_start(struct pdma_dev *dev); + +/*! + * \brief Stop device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_stop(struct pdma_dev *dev); + +/*! + * \brief Suspend device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_suspend(struct pdma_dev *dev); + +/*! + * \brief Resume device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_resume(struct pdma_dev *dev); + +/*! + * \brief Suspend device Rx. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_rx_suspend(struct pdma_dev *dev); + +/*! + * \brief Resume device Rx. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_rx_resume(struct pdma_dev *dev); + +/*! + * \brief Dock device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_dock(struct pdma_dev *dev); + +/*! + * \brief Undock device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_undock(struct pdma_dev *dev); + +/*! + * \brief Get device information. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_info_get(struct pdma_dev *dev); + +/*! + * \brief Get device statistics. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_stats_get(struct pdma_dev *dev); + +/*! + * \brief Reset device statistics. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_stats_reset(struct pdma_dev *dev); + +/*! + * \brief Change queue number to channel number. + * + * \param [in] dev Device structure point. + * \param [in] queue Queue number. + * \param [in] dir Transmit direction. + * \param [out] chan Channel number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_queue_to_chan(struct pdma_dev *dev, int queue, int dir, int *chan); + +/*! + * \brief Change channel number to queue number. + * + * \param [in] dev Device structure point. + * \param [in] chan Channel number. + * \param [out] queue Queue number. + * \param [out] dir Transmit direction. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_chan_to_queue(struct pdma_dev *dev, int chan, int *queue, int *dir); + +/*! + * \brief Enable Rx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_rx_queue_intr_enable(struct pdma_dev *dev, int queue); + +/*! + * \brief Disable Rx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_rx_queue_intr_disable(struct pdma_dev *dev, int queue); + +/*! + * \brief Acknowledge Rx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_rx_queue_intr_ack(struct pdma_dev *dev, int queue); + +/*! + * \brief Check Rx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_rx_queue_intr_check(struct pdma_dev *dev, int queue); + +/*! + * \brief Enable Tx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_tx_queue_intr_enable(struct pdma_dev *dev, int queue); + +/*! + * \brief Disable Tx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_tx_queue_intr_disable(struct pdma_dev *dev, int queue); + +/*! + * \brief Acknowledge Tx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_tx_queue_intr_ack(struct pdma_dev *dev, int queue); + +/*! + * \brief Check Tx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_tx_queue_intr_check(struct pdma_dev *dev, int queue); + +/*! + * \brief Enable queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] hdl Queue interrupt handle. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_queue_intr_enable(struct pdma_dev *dev, struct intr_handle *hdl); + +/*! + * \brief Disable queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] hdl Queue interrupt handle. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_queue_intr_disable(struct pdma_dev *dev, struct intr_handle *hdl); + +/*! + * \brief Acknowledge queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] hdl Queue interrupt handle. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_queue_intr_ack(struct pdma_dev *dev, struct intr_handle *hdl); + +/*! + * \brief Check queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] hdl Queue interrupt handle. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_queue_intr_check(struct pdma_dev *dev, struct intr_handle *hdl); + +/*! + * \brief Enable group interrupt. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_group_intr_enable(struct pdma_dev *dev, int group); + +/*! + * \brief Disable group interrupt. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_group_intr_disable(struct pdma_dev *dev, int group); + +/*! + * \brief Acknowledge group interrupt. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_group_intr_ack(struct pdma_dev *dev, int group); + +/*! + * \brief Check group interrupt. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_group_intr_check(struct pdma_dev *dev, int group); + +/*! + * \brief Poll Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_rx_queue_poll(struct pdma_dev *dev, int queue, int budget); + +/*! + * \brief Poll Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_tx_queue_poll(struct pdma_dev *dev, int queue, int budget); + +/*! + * \brief Poll queue. + * + * \param [in] dev Device structure point. + * \param [in] hdl Queue interrupt handle. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_queue_poll(struct pdma_dev *dev, struct intr_handle *hdl, int budget); + +/*! + * \brief Poll group. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_group_poll(struct pdma_dev *dev, int group, int budget); + +#endif /* BCMCNET_CORE_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_dev.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_dev.h new file mode 100644 index 000000000000..bc3367b34fae --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_dev.h @@ -0,0 +1,544 @@ +/*! \file bcmcnet_dev.h + * + * Generic data structure and macro definitions for BCMCNET device. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_DEV_H +#define BCMCNET_DEV_H + +#include + +/*! + * \brief HW information. + */ +struct hw_info { + /*! HW name */ + char *name; + + /*! HW version */ + int ver_no; + + /*! Device ID */ + uint32_t dev_id; + + /*! Revision ID */ + uint32_t rev_id; + + /*! Number of CMCs */ + uint32_t num_cmcs; + + /*! Number of CMC channels */ + uint32_t cmc_chans; + + /*! Number of channels */ + uint32_t num_chans; + + /*! Rx DCB size */ + uint32_t rx_dcb_size; + + /*! Tx DCB size */ + uint32_t tx_dcb_size; + + /*! Rx packet header size */ + uint32_t rx_ph_size; + + /*! Tx packet header size */ + uint32_t tx_ph_size; + + /*! HW structure point */ + struct pdma_hw *hw; +}; + +/*! + * \brief Read 32-bit register. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] addr Register address. + * \param [in] data Pointer to read data. + */ +typedef void (*reg_rd32_f)(struct pdma_hw *hw, uint32_t addr, uint32_t *data); + +/*! + * \brief Write 32-bit register. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] addr Register address. + * \param [in] data Data to write. + */ +typedef void (*reg_wr32_f)(struct pdma_hw *hw, uint32_t addr, uint32_t data); + +/*! + * \brief Pre-initialize hardware. + * + * \param [in] hw Pointer to hardware structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*pre_init_f)(struct pdma_hw *hw); + +/*! + * \brief Initialize hardware. + * + * \param [in] hw Pointer to hardware structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*hw_init_f)(struct pdma_hw *hw); + +/*! + * \brief Configure hardware. + * + * \param [in] hw Pointer to hardware structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*hw_config_f)(struct pdma_hw *hw); + +/*! + * \brief Reset hardware. + * + * \param [in] hw Pointer to hardware structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*hw_reset_f)(struct pdma_hw *hw); + +/*! + * \brief Start channel. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_start_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Stop channel. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_stop_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Set up channel. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * \param [in] addr Start DMA address of descriptors. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_setup_f)(struct pdma_hw *hw, int chan, uint64_t addr); + +/*! + * \brief Go to ohter descriptor. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * \param [in] addr Destination DMA address of descriptors. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_goto_f)(struct pdma_hw *hw, int chan, uint64_t addr); + +/*! + * \brief Clear channel. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_clear_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Get interrupt number. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval Returned interrupt number, errors if negative value. + */ +typedef int (*chan_intr_num_get_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Enable interrupt. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_intr_enable_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Disable interrupt. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_intr_disable_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Query interrupt. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_intr_query_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Check interrupt. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_intr_check_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Coalesce interrupt. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * \param [in] count Count value to trigger interrupt. + * \param [in] timer Timer value to triggre interrupt. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_intr_coalesce_f)(struct pdma_hw *hw, int chan, int count, int timer); + +/*! + * \brief Dump registers. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_reg_dump_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief HW handlers. + */ +struct hw_handlers { + /*! 32 bits register read */ + reg_rd32_f reg_rd32; + + /*! 32 bits register write */ + reg_wr32_f reg_wr32; + + /*! HW pre-initialize */ + pre_init_f pre_init; + + /*! HW initialize */ + hw_init_f hw_init; + + /*! HW configure */ + hw_config_f hw_config; + + /*! HW reset */ + hw_reset_f hw_reset; + + /*! Channel start */ + chan_start_f chan_start; + + /*! Channel stop */ + chan_stop_f chan_stop; + + /*! Channel setup */ + chan_setup_f chan_setup; + + /*! Channel goto */ + chan_goto_f chan_goto; + + /*! Channel clear */ + chan_clear_f chan_clear; + + /*! Channel interrupt number get */ + chan_intr_num_get_f chan_intr_num_get; + + /*! Channel interrupt enable */ + chan_intr_enable_f chan_intr_enable; + + /*! Channel interrupt disable */ + chan_intr_disable_f chan_intr_disable; + + /*! Channel interrupt query */ + chan_intr_query_f chan_intr_query; + + /*! Channel interrupt check */ + chan_intr_check_f chan_intr_check; + + /*! Channel interrupt coalesce */ + chan_intr_coalesce_f chan_intr_coalesce; + + /*! Channel registers dump */ + chan_reg_dump_f chan_reg_dump; +}; + +/*! + * \brief Initialize Rx descriptor. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_MEMORY Allocation failed. + */ +typedef int (*rx_desc_init_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq); + +/*! + * \brief Clean up Rx descriptor. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*rx_desc_clean_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq); + +/*! + * \brief Clean up Rx ring. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] budget Budget for each operation. + * + * \retval Number of descriptors finished. + */ +typedef int (*rx_ring_clean_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq, int budget); + +/*! + * \brief Dump Rx ring. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*rx_ring_dump_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq); + +/*! + * \brief Suspend Rx queue. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*rx_suspend_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq); + +/*! + * \brief Resume Rx queue. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*rx_resume_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq); + +/*! + * \brief Initialize Tx descriptor. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] txq Pointer to Tx queue struture. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_MEMORY Allocation failed. + */ +typedef int (*tx_desc_init_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq); + +/*! + * \brief Clean up Tx descriptor. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] txq Pointer to Tx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*tx_desc_clean_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq); + +/*! + * \brief Clean up Tx ring. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] txq Pointer to Tx queue struture. + * \param [in] budget Budget for each operation. + * + * \retval Number of descriptors finished. + */ +typedef int (*tx_ring_clean_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq, int budget); + +/*! + * \brief Dump Tx ring. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] txq Pointer to Tx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*tx_ring_dump_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq); + +/*! + * \brief Transmit packet. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] txq Pointer to Tx queue struture. + * \param [in] buf Pointer to packet buffer struture. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pkt_xmit_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq, void *buf); + +/*! + * \brief Descriptor operations. + */ +struct desc_operations { + /*! Rx descriptor initialize */ + rx_desc_init_f rx_desc_init; + + /*! Rx descriptor cleanup */ + rx_desc_clean_f rx_desc_clean; + + /*! Rx ring cleanup */ + rx_ring_clean_f rx_ring_clean; + + /*! Rx ring dump */ + rx_ring_dump_f rx_ring_dump; + + /*! Rx suspend */ + rx_suspend_f rx_suspend; + + /*! Rx resume */ + rx_resume_f rx_resume; + + /*! Tx descriptor initialize */ + tx_desc_init_f tx_desc_init; + + /*! Tx descriptor cleanup */ + tx_desc_clean_f tx_desc_clean; + + /*! Tx ring cleanup */ + tx_ring_clean_f tx_ring_clean; + + /*! Tx ring dump */ + tx_ring_dump_f tx_ring_dump; + + /*! Tx transmit */ + pkt_xmit_f pkt_xmit; +}; + +/*! + * \brief HW structure. + */ +struct pdma_hw { + /*! Device number */ + int unit; + + /*! Device structure point */ + struct pdma_dev *dev; + + /*! HW information */ + struct hw_info info; + + /*! HW handlers */ + struct hw_handlers hdls; + + /*! HW operations */ + struct desc_operations dops; +}; + +/*! + * \brief Open device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_open(struct pdma_dev *dev); + +/*! + * \brief Coalesce Rx interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * \param [in] count Interrupt threshhold. + * \param [in] timer Timer value. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_int_coalesce(struct pdma_dev *dev, int queue, int count, int timer); + +/*! + * \brief Coalesce Tx interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * \param [in] count Interrupt threshhold. + * \param [in] timer Timer value. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_int_coalesce(struct pdma_dev *dev, int queue, int count, int timer); + +/*! + * \brief Dump Rx queue registers. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_reg_dump(struct pdma_dev *dev, int queue); + +/*! + * \brief Dump Tx queue registers. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_reg_dump(struct pdma_dev *dev, int queue); + +#endif /* BCMCNET_DEV_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_internal.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_internal.h new file mode 100644 index 000000000000..e4b2051a34bc --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_internal.h @@ -0,0 +1,305 @@ +/*! \file bcmcnet_internal.h + * + * BCMCNET internal data structure and macro definitions. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_INTERNAL_H +#define BCMCNET_INTERNAL_H + +#include + +/*! CMICD name */ +#define CMICD_DEV_NAME "cmicd" + +/*! CMICX name */ +#define CMICX_DEV_NAME "cmicx" + +/*! + * \brief Allocate descriptor ring buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] dma DMA address of ring buffer. + * + * \retval Pointer to DMA buffer or NULL if an error occurred. + */ +typedef void *(*ring_buf_alloc_f)(struct pdma_dev *dev, uint32_t, dma_addr_t *dma); + +/*! + * \brief Free descriptor ring buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] size Size of DMA buffer. + * \param [in] mem Pointer to DMA buffer. + * \param [in] dma DMA address of ring buffer. + */ +typedef void (*ring_buf_free_f)(struct pdma_dev *dev, uint32_t size, void *mem, + dma_addr_t dma); + +/*! + * \brief Allocate Rx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_MEMORY Allocation failed. + */ +typedef int (*rx_buf_alloc_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf); + +/*! + * \brief Get Rx packet buffer DMA address. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * \param [in] dma DMA address of packet buffer. + */ +typedef void (*rx_buf_dma_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, dma_addr_t *dma); + +/*! + * \brief Check Rx packet buffer validity. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * + * \retval Ture Buffer is available or FALSE. + */ +typedef int (*rx_buf_avail_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf); + +/*! + * \brief Get Rx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * \param [in] len Packet length. + * + * \retval Pointer to packet header structure or NULL if failed. + */ +typedef struct pkt_hdr *(*rx_buf_get_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, int len); + +/*! + * \brief Put Rx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * \param [in] len Packet length. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_MEMORY Allocation failed. + */ +typedef int (*rx_buf_put_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, int len); + +/*! + * \brief Free Rx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + */ +typedef void (*rx_buf_free_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf); + +/*! + * \brief Get Rx packet buffer mode. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval Buffer mode. + */ +typedef enum buf_mode (*rx_buf_mode_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq); + +/*! + * \brief Get Tx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] txq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * \param [in] buf Packet buffer. + * + * \retval Pointer to packet header structure or NULL if failed. + */ +typedef struct pkt_hdr *(*tx_buf_get_f)(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf, void *buf); + +/*! + * \brief Get Tx packet buffer DMA address. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] txq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * \param [in] dma DMA address of packet buffer. + */ +typedef void (*tx_buf_dma_f)(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf, dma_addr_t *dma); + +/*! + * \brief Free Tx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] txq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + */ +typedef void (*tx_buf_free_f)(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf); + +/*! + * \brief Buffer manager. + */ +struct pdma_buf_mngr { + /*! Allocate descriptor ring buffer */ + ring_buf_alloc_f ring_buf_alloc; + + /*! Free descriptor ring buffer */ + ring_buf_free_f ring_buf_free; + + /*! Allocate Rx packet buffer */ + rx_buf_alloc_f rx_buf_alloc; + + /*! Get Rx packet buffer DMA address */ + rx_buf_dma_f rx_buf_dma; + + /*! Check Rx packet buffer validity */ + rx_buf_avail_f rx_buf_avail; + + /*! Get Rx packet buffer */ + rx_buf_get_f rx_buf_get; + + /*! Put Rx packet buffer */ + rx_buf_put_f rx_buf_put; + + /*! Free Rx packet buffer */ + rx_buf_free_f rx_buf_free; + + /*! Get Rx packet buffer mode */ + rx_buf_mode_f rx_buf_mode; + + /*! Get Tx packet buffer */ + tx_buf_get_f tx_buf_get; + + /*! Get Tx packet buffer DMA address */ + tx_buf_dma_f tx_buf_dma; + + /*! Free Tx packet buffer */ + tx_buf_free_f tx_buf_free; +}; + +/*! + * \brief Wait for the kernel networking subsystem. + * + * \param [in] unit Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_FAIL Operation failed. + */ +typedef int (*bcmcnet_vnet_wait_f)(int unit); + +/*! + * \brief Wake up the kernel networking subsystem. + * + * \param [in] unit Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_FAIL Operation failed. + */ +typedef int (*bcmcnet_hnet_wake_f)(int unit); + +/*! + * \brief Dock to the kernel networking subsystem. + * + * \param [in] unit Device number. + * \param [in] vsync Sync data. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_FAIL Operation failed. + */ +typedef int (*bcmcnet_vnet_dock_f)(int unit, vnet_sync_t *vsync); + +/*! + * \brief Undock from the kernel networking subsystem. + * + * \param [in] unit Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_FAIL Operation failed. + */ +typedef int (*bcmcnet_vnet_undock_f)(int unit); + +/*! + * \brief VNET operations. + */ +typedef struct bcmcnet_vnet_ops_s { + /*! + * VNET wait for HNET. + * VNET calls this to wait for any notification from HNET. + */ + bcmcnet_vnet_wait_f vnet_wait; + + /*! + * VNET wake up HNET. + * VNET calls this to notify HNET that Tx/Rx is ready. + */ + bcmcnet_hnet_wake_f hnet_wake; + + /*! + * VNET dock to HNET. + * This is called to notify HNET that VNET is ready to work and synchronize + * vrings information to HNET. + */ + bcmcnet_vnet_dock_f vnet_dock; + + /*! + * VNET undock from HNET. + * This is called to notify HNET that VNET is ready to leave. + */ + bcmcnet_vnet_undock_f vnet_undock; +} bcmcnet_vnet_ops_t; + +/*! + * \brief Initialize buffer manager. + * + * \param [in] dev Device structure pointer. + */ +extern void +bcmcnet_buf_mngr_init(struct pdma_dev *dev); + +/*! + * \brief Register VNET operations. + * + * \param [in] unit Device number. + * \param [in] vnet_ops VNET operations. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_PARAM Invalid parameters. + */ +extern int +bcmcnet_vnet_ops_register(int unit, bcmcnet_vnet_ops_t *vnet_ops); + +#endif /* BCMCNET_INTERNAL_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_rxtx.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_rxtx.h new file mode 100644 index 000000000000..eb5834d895b0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_rxtx.h @@ -0,0 +1,512 @@ +/*! \file bcmcnet_rxtx.h + * + * Generic data structure and macro definitions for BCMCNET Rx/Tx. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_RXTX_H +#define BCMCNET_RXTX_H + +/*! Default descriptor number in each ring */ +#define NUM_RING_DESC 64 + +/*! Maximum number of packets to be handled in one poll call */ +#define NUM_RXTX_BUDGET 64 + +/*! + * \brief Rx buffer mode definitions. + */ +enum buf_mode { + /*! Private DMA buffer in user space */ + PDMA_BUF_MODE_PRIV, + + /*! SKB in kernel */ + PDMA_BUF_MODE_SKB, + + /*! Paged buffer in kernel */ + PDMA_BUF_MODE_PAGE, + + /*! Kernel buffer mapped to user space */ + PDMA_BUF_MODE_MAPPED, + + /*! MAX mode */ + PDMA_BUF_MODE_MAX +}; + +/*! + * \brief Rx queue statistics. + */ +struct rx_stats { + /*! Number of received packets */ + uint64_t packets; + + /*! Number of received bytes */ + uint64_t bytes; + + /*! Number of dropped packets */ + uint64_t dropped; + + /*! Number of errors */ + uint64_t errors; + + /*! Number of head errors */ + uint64_t head_errors; + + /*! Number of data errors */ + uint64_t data_errors; + + /*! Number of cell errors */ + uint64_t cell_errors; + + /*! Number of failed allocation */ + uint64_t nomems; +}; + +/*! + * Rx queue structure + */ +struct pdma_rx_queue { + /*! Group index to which this queue belongs */ + uint32_t group_id; + + /*! Global channel index */ + uint32_t chan_id; + + /*! Queue index */ + uint32_t queue_id; + + /*! Pointer to the device control structure */ + struct dev_ctrl *ctrl; + + /*! Rx packet buffer pointers */ + struct pdma_rx_buf *pbuf; + + /*! Rx ring address */ + void *ring; + + /*! Rx ring DMA address */ + dma_addr_t ring_addr; + + /*! Rx ring DMA halt address */ + dma_addr_t halt_addr; + + /*! Rx buffer size */ + uint32_t buf_size; + + /*! Total number of descriptors */ + uint32_t nb_desc; + + /*! Next free ring entry */ + uint32_t curr; + + /*! Halt ring entry */ + uint32_t halt; + + /*! Max free descriptors to hold */ + uint32_t free_thresh; + + /*! Rx interrupt coalesce value */ + uint32_t ic_val; + + /*! Rx interrupt coalescing */ + int intr_coalescing; + + /*! Queue statistics */ + struct rx_stats stats; + + /*! Rx queue spin lock */ + sal_spinlock_t lock; + + /*! Queue state */ + int state; + /*! Queue is used */ +#define PDMA_RX_QUEUE_USED (1 << 0) + /*! Queue is setup */ +#define PDMA_RX_QUEUE_SETUP (1 << 1) + /*! Queue is active */ +#define PDMA_RX_QUEUE_ACTIVE (1 << 2) + /*! Queue is busy */ +#define PDMA_RX_QUEUE_BUSY (1 << 3) + /*! Queue is suspended */ +#define PDMA_RX_QUEUE_XOFF (1 << 4) + /*! Queue is batch refilled */ +#define PDMA_RX_BATCH_REFILL (1 << 5) + + /*! DMA buffer mode */ + enum buf_mode mode; +}; + +/*! + * \brief Tx queue statistics. + */ +struct tx_stats { + /*! Number of sent packets */ + uint64_t packets; + + /*! Number of sent bytes */ + uint64_t bytes; + + /*! Number of dropped packets */ + uint64_t dropped; + + /*! Number of errors */ + uint64_t errors; + + /*! Number of suspends */ + uint64_t xoffs; +}; + +/*! + * \brief Tx queue structure. + */ +struct pdma_tx_queue { + /*! Group index to which this queue belongs */ + uint32_t group_id; + + /*! Global channel index */ + uint32_t chan_id; + + /*! Queue index */ + uint32_t queue_id; + + /*! pointer to the device control structure */ + struct dev_ctrl *ctrl; + + /*! Tx packet buffer pointers */ + struct pdma_tx_buf *pbuf; + + /*! Tx ring address */ + void *ring; + + /*! Tx ring DMA address */ + dma_addr_t ring_addr; + + /*! Tx ring DMA halt address */ + dma_addr_t halt_addr; + + /*! Total number of descriptors */ + uint32_t nb_desc; + + /*! Next free ring entry */ + uint32_t curr; + + /*! First entry to be transmitted */ + uint32_t dirt; + + /*! Halt ring entry */ + uint32_t halt; + + /*! Max free descriptors to hold in non-intr mode */ + uint32_t free_thresh; + + /*! Tx interrupt coalesce value */ + uint32_t ic_val; + + /*! Tx interrupt coalescing */ + int intr_coalescing; + + /*! Queue statistics */ + struct tx_stats stats; + + /*! Tx queue spin lock */ + sal_spinlock_t lock; + + /*! Tx mutex spin lock */ + sal_spinlock_t mutex; + + /*! Tx mutex and flow control semaphore */ + sal_sem_t sem; + + /*! Queue state */ + int state; + /*! Queue is used */ +#define PDMA_TX_QUEUE_USED (1 << 0) + /*! Queue is setup */ +#define PDMA_TX_QUEUE_SETUP (1 << 1) + /*! Queue is active */ +#define PDMA_TX_QUEUE_ACTIVE (1 << 2) + /*! Queue is setup */ +#define PDMA_TX_QUEUE_BUSY (1 << 3) + /*! Queue is suspended */ +#define PDMA_TX_QUEUE_XOFF (1 << 4) + /*! Queue is poll mode */ +#define PDMA_TX_QUEUE_POLL (1 << 5) + + /*! DMA buffer mode */ + enum buf_mode mode; +}; + +/*! + * \brief Setup Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_setup(struct pdma_dev *dev, int queue); + +/*! + * \brief Release Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_release(struct pdma_dev *dev, int queue); + +/*! + * \brief Restore Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_restore(struct pdma_dev *dev, int queue); + +/*! + * \brief Setup virtual Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_vqueue_setup(struct pdma_dev *dev, int queue); + +/*! + * \brief Release virtual Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_vqueue_release(struct pdma_dev *dev, int queue); + +/*! + * \brief Setup Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_setup(struct pdma_dev *dev, int queue); + +/*! + * \brief Release Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_release(struct pdma_dev *dev, int queue); + +/*! + * \brief Restore Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_restore(struct pdma_dev *dev, int queue); + +/*! + * \brief Setup virtual Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_vqueue_setup(struct pdma_dev *dev, int queue); + +/*! + * \brief Release virtual Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_vqueue_release(struct pdma_dev *dev, int queue); + +/*! + * \brief Suspend Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_suspend(struct pdma_dev *dev, int queue); + +/*! + * \brief Resume Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_resume(struct pdma_dev *dev, int queue); + +/*! + * \brief Suspend Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_suspend(struct pdma_dev *dev, int queue); + +/*! + * \brief Resume Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_resume(struct pdma_dev *dev, int queue); + +/*! + * \brief Wakeup Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_wakeup(struct pdma_dev *dev, int queue); + +/*! + * \brief Start Tx queue transmission. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * \param [in] buf Tx packet buffer. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_xmit(struct pdma_dev *dev, int queue, void *buf); + +/*! + * \brief Poll Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_poll(struct pdma_dev *dev, int queue, int budget); + +/*! + * \brief Poll Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_poll(struct pdma_dev *dev, int queue, int budget); + +/*! + * \brief Poll queue group. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_group_poll(struct pdma_dev *dev, int group, int budget); + +/*! + * \brief Dump Rx ring. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_ring_dump(struct pdma_dev *dev, int queue); + +/*! + * \brief Dump Tx ring. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_ring_dump(struct pdma_dev *dev, int queue); + +#endif /* BCMCNET_RXTX_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_types.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_types.h new file mode 100644 index 000000000000..42bd9240828b --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_types.h @@ -0,0 +1,263 @@ +/*! \file bcmcnet_types.h + * + * BCMCNET public data structure and macro definitions. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_TYPES_H +#define BCMCNET_TYPES_H + +#include + +/*! Maximum length of device name */ +#define DEV_NAME_LEN_MAX 16 + +/*! Maximum number of groups supported each device */ +#define NUM_GRP_MAX 4 + +/*! Maximum number of queues supported each group */ +#define NUM_Q_PER_GRP 8 + +/*! Maximum number of queues supported each device */ +#define NUM_QUE_MAX (NUM_GRP_MAX * NUM_Q_PER_GRP) + +/*! Maximum length of jumbo frame */ +#define JUMBO_FRAME_LEN_MAX 0xffff + +/*! Maximum Rx buffer size */ +#define RX_BUF_SIZE_MAX JUMBO_FRAME_LEN_MAX + +/*! Minimum Rx buffer size */ +#define RX_BUF_SIZE_MIN 68 + +/*! Default Rx buffer size */ +#define RX_BUF_SIZE_DFLT 9216 + +/*! + * \brief Transmission direction. + */ +enum pdma_dir { + PDMA_Q_RX = 0, + PDMA_Q_TX +}; + +/*! + * \brief Device information. + */ +typedef struct bcmcnet_dev_info { + /*! Device name */ + char dev_name[DEV_NAME_LEN_MAX]; + + /*! Device ID */ + uint32_t dev_id; + + /*! Device type */ + uint32_t dev_type; + + /*! Maximum number of groups */ + uint32_t max_groups; + + /*! Maximum number of queues */ + uint32_t max_queues; + + /*! Bitmap of groups at work */ + uint32_t bm_groups; + + /*! Bitmap of Rx queues at work */ + uint32_t bm_rx_queues; + + /*! Bitmap of Tx queues at work */ + uint32_t bm_tx_queues; + + /*! Number of groups at work */ + uint32_t nb_groups; + + /*! Number of Rx queues at work */ + uint32_t nb_rx_queues; + + /*! Number of Tx queues at work */ + uint32_t nb_tx_queues; + + /*! Rx descriptor size */ + uint32_t rx_desc_size; + + /*! Tx descriptor size */ + uint32_t tx_desc_size; + + /*! Rx packet header size */ + uint32_t rx_ph_size; + + /*! Tx packet header size */ + uint32_t tx_ph_size; + + /*! Rx buffer size */ + uint32_t rx_buf_dflt; + + /*! Number of descriptors for a queue */ + uint32_t nb_desc_dflt; + + /*! Rx buffer size per queue */ + uint32_t rx_buf_size[NUM_QUE_MAX]; + + /*! Number of Rx descriptors per queue */ + uint32_t nb_rx_desc[NUM_QUE_MAX]; + + /*! Number of Tx descriptors per queue */ + uint32_t nb_tx_desc[NUM_QUE_MAX]; +} bcmcnet_dev_info_t; + +/*! + * \brief Device statistics. + */ +typedef struct bcmcnet_dev_stats { + /*! Number of successfully received packets */ + uint64_t rx_packets; + + /*! Number of successfully received bytes */ + uint64_t rx_bytes; + + /*! Number of dropped packets */ + uint64_t rx_dropped; + + /*! Number of erroneous received packets */ + uint64_t rx_errors; + + /*! Number of error head packets */ + uint64_t rx_head_errors; + + /*! Number of error data packets */ + uint64_t rx_data_errors; + + /*! Number of error cell packets */ + uint64_t rx_cell_errors; + + /*! Number of RX pktbuf allocation failures */ + uint64_t rx_nomems; + + /*! Number of successfully transmitted packets */ + uint64_t tx_packets; + + /*! Number of successfully transmitted bytes */ + uint64_t tx_bytes; + + /*! Number of dropped packets */ + uint64_t tx_dropped; + + /*! Number of failed transmitted packets */ + uint64_t tx_errors; + + /*! Number of suspended transmission */ + uint64_t tx_xoffs; + + /*! Number of interrupts */ + uint64_t intrs; + + /*! Number of successfully received packets per queue */ + uint64_t rxq_packets[NUM_QUE_MAX]; + + /*! Number of successfully received bytes per queue */ + uint64_t rxq_bytes[NUM_QUE_MAX]; + + /*! Number of dropped packets per queue */ + uint64_t rxq_dropped[NUM_QUE_MAX]; + + /*! Number of erroneous received packets per queue */ + uint64_t rxq_errors[NUM_QUE_MAX]; + + /*! Number of error head packets per queue */ + uint64_t rxq_head_errors[NUM_QUE_MAX]; + + /*! Number of error data packets per queue */ + uint64_t rxq_data_errors[NUM_QUE_MAX]; + + /*! Number of error cell packets per queue */ + uint64_t rxq_cell_errors[NUM_QUE_MAX]; + + /*! Number of RX pktbuf allocation failures per queue */ + uint64_t rxq_nomems[NUM_QUE_MAX]; + + /*! Number of successfully transmitted bytes per queue */ + uint64_t txq_packets[NUM_QUE_MAX]; + + /*! Number of successfully transmitted bytes per queue */ + uint64_t txq_bytes[NUM_QUE_MAX]; + + /*! Number of dropped packets per queue */ + uint64_t txq_dropped[NUM_QUE_MAX]; + + /*! Number of failed transmitted packets per queue */ + uint64_t txq_errors[NUM_QUE_MAX]; + + /*! Number of suspended transmission per queue */ + uint64_t txq_xoffs[NUM_QUE_MAX]; +} bcmcnet_dev_stats_t; + +/*! + * \brief Device modes. + */ +typedef enum dev_mode_e { + /*! + * User network mode. + * The standalone CNET works in user space. + */ + DEV_MODE_UNET = 0, + + /*! + * Kernel network mode. + * Combined with KNET module, CNET works in kernel space. + */ + DEV_MODE_KNET, + + /*! + * Virtual network mode. + * CNET works in user space as a virtual network. + * The hypervisor must be deployed in KNET module. + */ + DEV_MODE_VNET, + + /*! + * Hyper network mode. + * Combined with KNET module, CNET works in kernel space as a hypervisor. + * The virtual network is not neccessary in this mode. + */ + DEV_MODE_HNET, + + /*! Maximum number of mode */ + DEV_MODE_MAX +} dev_mode_t; + +/*! + * \brief VNET sync data. + */ +typedef struct vnet_sync_s { + /*! Rx ring address */ + uint64_t rx_ring_addr[NUM_QUE_MAX]; + + /*! Rx ring size */ + uint32_t rx_ring_size[NUM_QUE_MAX]; + + /*! Tx ring address */ + uint64_t tx_ring_addr[NUM_QUE_MAX]; + + /*! Tx ring size */ + uint32_t tx_ring_size[NUM_QUE_MAX]; +} vnet_sync_t; + +#endif /* BCMCNET_TYPES_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_core.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_core.c new file mode 100644 index 000000000000..ef4aca7da49e --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_core.c @@ -0,0 +1,701 @@ +/*! \file bcmcnet_core.c + * + * Utility routines for BCMCNET driver. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include + +/*! + * Initialize a device + */ +int +bcmcnet_pdma_dev_init(struct pdma_dev *dev) +{ + int rv; + + /* Open the device */ + rv = bcmcnet_pdma_open(dev); + if (SHR_FAILURE(rv)) { + return rv; + } + + dev->attached = 1; + + return SHR_E_NONE; +} + +/*! + * Clean up a device + */ +int +bcmcnet_pdma_dev_cleanup(struct pdma_dev *dev) +{ + if (!dev->attached) { + return SHR_E_NONE; + } + + dev->ops->dev_close(dev); + dev->ops = NULL; + + dev->attached = 0; + + return SHR_E_NONE; +} + +/*! + * Start a device + */ +int +bcmcnet_pdma_dev_start(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + int rv; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + if (dev->started) { + return SHR_E_NONE; + } + + rv = dev->ops->dev_config(dev, ctrl->bm_rxq, ctrl->bm_txq); + if (SHR_FAILURE(rv)) { + return rv; + } + + /* Start all the Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rv = dev->ops->rx_queue_setup(dev, qi); + if (SHR_FAILURE(rv)) { + return rv; + } + dev->ops->rx_queue_intr_enable(dev, qi); + dev->ops->rx_queue_start(dev, qi); + } + + /* Start all the Tx queues */ + for (qi = 0; qi < ctrl->nb_txq; qi++) { + dev->ops->tx_queue_setup(dev, qi); + dev->ops->tx_queue_intr_enable(dev, qi); + dev->ops->tx_queue_start(dev, qi); + dev->ops->tx_queue_wakeup(dev, qi); + } + + bcmcnet_pdma_dev_info_get(dev); + + dev->started = 1; + + return SHR_E_NONE; +} + +/*! + * Stop a device + */ +int +bcmcnet_pdma_dev_stop(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + if (!dev->started) { + return SHR_E_NONE; + } + + /* Stop all the Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + dev->ops->rx_queue_intr_disable(dev, qi); + dev->ops->rx_queue_stop(dev, qi); + dev->ops->rx_queue_release(dev, qi); + } + + /* Stop all the Tx queues */ + for (qi = 0; qi < ctrl->nb_txq; qi++) { + dev->ops->tx_queue_intr_disable(dev, qi); + dev->ops->tx_queue_stop(dev, qi); + dev->ops->tx_queue_wakeup(dev, qi); + dev->ops->tx_queue_release(dev, qi); + } + + dev->started = 0; + + return SHR_E_NONE; +} + +/*! + * Suspend a device + */ +int +bcmcnet_pdma_dev_suspend(struct pdma_dev *dev) +{ + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + return dev->ops->dev_suspend(dev); +} + +/*! + * Resume a device + */ +int +bcmcnet_pdma_dev_resume(struct pdma_dev *dev) +{ + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + return dev->ops->dev_resume(dev); +} + +/*! + * Suspend Rx + */ +int +bcmcnet_pdma_dev_rx_suspend(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + /* Suspend all the Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + dev->ops->rx_queue_suspend(dev, qi); + } + + return SHR_E_NONE; +} + +/*! + * Resume Rx + */ +int +bcmcnet_pdma_dev_rx_resume(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + /* Resume all the Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + dev->ops->rx_queue_resume(dev, qi); + } + + return SHR_E_NONE; +} + +/*! + * Dock to HNET + */ +int +bcmcnet_pdma_dev_dock(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + int rv; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + /* Set up all the virtual Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rv = dev->ops->rx_vqueue_setup(dev, qi); + if (SHR_FAILURE(rv)) { + return rv; + } + } + + /* Set up all the virtual Tx queues */ + for (qi = 0; qi < ctrl->nb_txq; qi++) { + rv = dev->ops->tx_vqueue_setup(dev, qi); + if (SHR_FAILURE(rv)) { + return rv; + } + } + + return SHR_E_NONE; +} + +/*! + * Undock from HNET + */ +int +bcmcnet_pdma_dev_undock(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + /* Release all the virtual Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + dev->ops->rx_vqueue_release(dev, qi); + } + + /* Release all the virtual Tx queues */ + for (qi = 0; qi < ctrl->nb_txq; qi++) { + dev->ops->tx_vqueue_release(dev, qi); + } + + return SHR_E_NONE; +} + +/*! + * Get device information + */ +int +bcmcnet_pdma_dev_info_get(struct pdma_dev *dev) +{ + if (!dev->ops || !dev->ops->dev_info_get) { + return SHR_E_INTERNAL; + } + + dev->ops->dev_info_get(dev); + + return SHR_E_NONE; +} + +/*! + * Get device statistics + */ +int +bcmcnet_pdma_dev_stats_get(struct pdma_dev *dev) +{ + if (!dev->ops || !dev->ops->dev_stats_get) { + return SHR_E_INTERNAL; + } + + dev->ops->dev_stats_get(dev); + + return SHR_E_NONE; +} + +/*! + * Reset device statistics + */ +int +bcmcnet_pdma_dev_stats_reset(struct pdma_dev *dev) +{ + if (!dev->ops || !dev->ops->dev_stats_reset) { + return SHR_E_INTERNAL; + } + + dev->ops->dev_stats_reset(dev); + + return SHR_E_NONE; +} + +/*! + * Convert a queue index to channel index + */ +int +bcmcnet_pdma_dev_queue_to_chan(struct pdma_dev *dev, int queue, int dir, int *chan) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + + if (dir == PDMA_Q_RX) { + if ((uint32_t)queue >= ctrl->nb_rxq || chan == NULL) { + return SHR_E_PARAM; + } + } else { + if ((uint32_t)queue >= ctrl->nb_txq || chan == NULL) { + return SHR_E_PARAM; + } + } + + if (!dev->ops || !dev->ops->dev_lq_to_pq) { + return SHR_E_INTERNAL; + } + + return dev->ops->dev_lq_to_pq(dev, queue, dir, chan); +} + +/*! + * Convert a channel index to queue index + */ +int +bcmcnet_pdma_dev_chan_to_queue(struct pdma_dev *dev, int chan, int *queue, int *dir) +{ + if (chan < 0 || chan >= dev->num_queues || queue == NULL || dir == NULL) { + return SHR_E_PARAM; + } + + if (!dev->ops || !dev->ops->dev_pq_to_lq) { + return SHR_E_INTERNAL; + } + + return dev->ops->dev_pq_to_lq(dev, chan, queue, dir); +} + +/*! + * Enable interrupt for a Rx queue + */ +int +bcmcnet_rx_queue_intr_enable(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->rx_queue_intr_enable) { + return SHR_E_INTERNAL; + } + + return dev->ops->rx_queue_intr_enable(dev, queue); +} + +/*! + * Disable interrupt for a Rx queue + */ +int +bcmcnet_rx_queue_intr_disable(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->rx_queue_intr_disable) { + return SHR_E_INTERNAL; + } + + return dev->ops->rx_queue_intr_disable(dev, queue); +} + +/*! + * Acknowledge interrupt for a Rx queue + */ +int +bcmcnet_rx_queue_intr_ack(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->rx_queue_intr_ack) { + return SHR_E_INTERNAL; + } + + return dev->ops->rx_queue_intr_ack(dev, queue); +} + +/*! + * Check interrupt for a Rx queue + */ +int +bcmcnet_rx_queue_intr_check(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->rx_queue_intr_check) { + return SHR_E_INTERNAL; + } + + return dev->ops->rx_queue_intr_check(dev, queue); +} + +/*! + * Enable interrupt for a Tx queue + */ +int +bcmcnet_tx_queue_intr_enable(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->tx_queue_intr_enable) { + return SHR_E_INTERNAL; + } + + return dev->ops->tx_queue_intr_enable(dev, queue); +} + +/*! + * Disable interrupt for a Tx queue + */ +int +bcmcnet_tx_queue_intr_disable(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->tx_queue_intr_disable) { + return SHR_E_INTERNAL; + } + + return dev->ops->tx_queue_intr_disable(dev, queue); +} + +/*! + * Acknowledge interrupt for a Tx queue + */ +int +bcmcnet_tx_queue_intr_ack(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->tx_queue_intr_ack) { + return SHR_E_INTERNAL; + } + + return dev->ops->tx_queue_intr_ack(dev, queue); +} + +/*! + * Check interrupt for a Tx queue + */ +int +bcmcnet_tx_queue_intr_check(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->tx_queue_intr_check) { + return SHR_E_INTERNAL; + } + + return dev->ops->tx_queue_intr_check(dev, queue); +} + +/*! + * Enable interrupt for a queue + */ +int +bcmcnet_queue_intr_enable(struct pdma_dev *dev, struct intr_handle *hdl) +{ + if (hdl->dir == PDMA_Q_RX) { + return bcmcnet_rx_queue_intr_enable(dev, hdl->queue); + } else { + return bcmcnet_tx_queue_intr_enable(dev, hdl->queue); + } +} + +/*! + * Disable interrupt for a queue + */ +int +bcmcnet_queue_intr_disable(struct pdma_dev *dev, struct intr_handle *hdl) +{ + if (hdl->dir == PDMA_Q_RX) { + return bcmcnet_rx_queue_intr_disable(dev, hdl->queue); + } else { + return bcmcnet_tx_queue_intr_disable(dev, hdl->queue); + } +} + +/*! + * Acknowledge interrupt for a queue + */ +int +bcmcnet_queue_intr_ack(struct pdma_dev *dev, struct intr_handle *hdl) +{ + if (hdl->dir == PDMA_Q_RX) { + return bcmcnet_rx_queue_intr_ack(dev, hdl->queue); + } else { + return bcmcnet_tx_queue_intr_ack(dev, hdl->queue); + } +} + +/*! + * Check interrupt for a queue + */ +int +bcmcnet_queue_intr_check(struct pdma_dev *dev, struct intr_handle *hdl) +{ + if (hdl->dir == PDMA_Q_RX) { + return bcmcnet_rx_queue_intr_check(dev, hdl->queue); + } else { + return bcmcnet_tx_queue_intr_check(dev, hdl->queue); + } +} + +/*! + * Enable interrupt for a queue group + */ +int +bcmcnet_group_intr_enable(struct pdma_dev *dev, int group) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct queue_group *grp = &ctrl->grp[group]; + int queue, dir; + int i; + + if (!dev->ops) { + return SHR_E_INTERNAL; + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->rx_queue_intr_enable(dev, queue); + } + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_txq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->tx_queue_intr_enable(dev, queue); + } + } + + return SHR_E_NONE; +} + +/*! + * Disable interrupt for a queue group + */ +int +bcmcnet_group_intr_disable(struct pdma_dev *dev, int group) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct queue_group *grp = &ctrl->grp[group]; + int queue, dir; + int i; + + if (!dev->ops) { + return SHR_E_INTERNAL; + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->rx_queue_intr_disable(dev, queue); + } + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_txq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->tx_queue_intr_disable(dev, queue); + } + } + + return SHR_E_NONE; +} + +/*! + * Acknowledge interrupt for a queue group + */ +int +bcmcnet_group_intr_ack(struct pdma_dev *dev, int group) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct queue_group *grp = &ctrl->grp[group]; + int queue, dir; + int i; + + if (!dev->ops) { + return SHR_E_INTERNAL; + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->rx_queue_intr_ack(dev, queue); + } + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_txq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->tx_queue_intr_ack(dev, queue); + } + } + + return SHR_E_NONE; +} + +/*! + * Check interrupt for a queue group + */ +int +bcmcnet_group_intr_check(struct pdma_dev *dev, int group) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct queue_group *grp = &ctrl->grp[group]; + int queue, dir; + int i; + + if (!dev->ops) { + return SHR_E_INTERNAL; + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + if (dev->ops->rx_queue_intr_check(dev, queue)) { + return TRUE; + } + } + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_txq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + if (dev->ops->tx_queue_intr_check(dev, queue)) { + return TRUE; + } + } + } + + return FALSE; +} + +/*! + * Poll a Rx queue + */ +int +bcmcnet_rx_queue_poll(struct pdma_dev *dev, int queue, int budget) +{ + if (!dev->ops || !dev->ops->rx_queue_poll) { + return SHR_E_INTERNAL; + } + + return dev->ops->rx_queue_poll(dev, queue, budget); +} + +/*! + * Poll a Tx queue + */ +int +bcmcnet_tx_queue_poll(struct pdma_dev *dev, int queue, int budget) +{ + if (!dev->ops || !dev->ops->tx_queue_poll) { + return SHR_E_INTERNAL; + } + + return dev->ops->tx_queue_poll(dev, queue, budget); +} + +/*! + * Poll a queue + */ +int +bcmcnet_queue_poll(struct pdma_dev *dev, struct intr_handle *hdl, int budget) +{ + if (hdl->dir == PDMA_Q_RX) { + return bcmcnet_rx_queue_poll(dev, hdl->queue, budget); + } else { + return bcmcnet_tx_queue_poll(dev, hdl->queue, budget); + } +} + +/*! + * Poll a queue group + */ +int +bcmcnet_group_poll(struct pdma_dev *dev, int group, int budget) +{ + if (!dev->ops || !dev->ops->group_poll) { + return SHR_E_INTERNAL; + } + + return dev->ops->group_poll(dev, group, budget); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_dev.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_dev.c new file mode 100644 index 000000000000..1f39515a7a62 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_dev.c @@ -0,0 +1,1059 @@ +/*! \file bcmcnet_dev.c + * + * Utility routines for BCMCNET device. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include + +/*! + * Free resource for a Rx queue + */ +static void +bcn_rx_queues_free(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + int gi, qi; + + for (gi = 0; gi < dev->num_groups; gi++) { + for (qi = 0; qi < dev->grp_queues; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->grp[gi].rx_queue[qi]; + if (!rxq) { + continue; + } + sal_free(rxq); + ctrl->grp[gi].rx_queue[qi] = NULL; + if (dev->mode == DEV_MODE_HNET && ctrl->grp[gi].vnet_rxq[qi]) { + sal_free(ctrl->grp[gi].vnet_rxq[qi]); + ctrl->grp[gi].vnet_rxq[qi] = NULL; + } + } + } +} + +/*! + * Allocate resource for a Rx queue + */ +static int +bcn_rx_queues_alloc(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL, *vrxq = NULL; + int gi, qi; + + for (gi = 0; gi < dev->num_groups; gi++) { + for (qi = 0; qi < dev->grp_queues; qi++) { + rxq = sal_alloc(sizeof(*rxq), "bcmcnetRxQueue"); + if (!rxq) { + goto error; + } + sal_memset(rxq, 0, sizeof(*rxq)); + rxq->group_id = gi; + rxq->chan_id = qi + gi * dev->grp_queues; + rxq->ctrl = ctrl; + ctrl->grp[gi].rx_queue[qi] = rxq; + if (dev->mode == DEV_MODE_HNET) { + vrxq = sal_alloc(sizeof(*vrxq), "bcmcnetVnetRxQueue"); + if (!vrxq) { + goto error; + } + sal_memset(vrxq, 0, sizeof(*vrxq)); + vrxq->group_id = gi; + vrxq->chan_id = qi + gi * dev->grp_queues; + vrxq->ctrl = ctrl; + ctrl->grp[gi].vnet_rxq[qi] = vrxq; + } + } + } + + return SHR_E_NONE; + +error: + bcn_rx_queues_free(dev); + + return SHR_E_MEMORY; +} + +/*! + * Free resource for a Tx queue + */ +static void +bcn_tx_queues_free(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL; + int gi, qi; + + for (gi = 0; gi < dev->num_groups; gi++) { + for (qi = 0; qi < dev->grp_queues; qi++) { + txq = (struct pdma_tx_queue *)ctrl->grp[gi].tx_queue[qi]; + if (!txq) { + continue; + } + sal_free(txq); + ctrl->grp[gi].tx_queue[qi] = NULL; + if (dev->mode == DEV_MODE_HNET && ctrl->grp[gi].vnet_txq[qi]) { + sal_free(ctrl->grp[gi].vnet_txq[qi]); + ctrl->grp[gi].vnet_txq[qi] = NULL; + } + } + } +} + +/*! + * Allocate resource for a Tx queue + */ +static int +bcn_tx_queues_alloc(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL, *vtxq = NULL; + int gi, qi; + + for (gi = 0; gi < dev->num_groups; gi++) { + for (qi = 0; qi < dev->grp_queues; qi++) { + txq = sal_alloc(sizeof(*txq), "bcmcnetTxQueue"); + if (!txq) { + goto error; + } + sal_memset(txq, 0, sizeof(*txq)); + txq->group_id = gi; + txq->chan_id = qi + gi * dev->grp_queues; + txq->ctrl = ctrl; + ctrl->grp[gi].tx_queue[qi] = txq; + if (dev->mode == DEV_MODE_HNET) { + vtxq = sal_alloc(sizeof(*vtxq), "bcmcnetVnetTxQueue"); + if (!vtxq) { + goto error; + } + sal_memset(vtxq, 0, sizeof(*vtxq)); + vtxq->group_id = gi; + vtxq->chan_id = qi + gi * dev->grp_queues; + vtxq->ctrl = ctrl; + ctrl->grp[gi].vnet_txq[qi] = vtxq; + } + } + } + + return SHR_E_NONE; + +error: + bcn_tx_queues_free(dev); + + return SHR_E_MEMORY; +} + +/*! + * \brief Parse Rx groups + * + * \param [in] dev Device structure point. + * \param [in] qbm Rx queue bitmap. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +bcn_rx_queue_group_parse(struct pdma_dev *dev, uint32_t qbm) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr; + struct pdma_rx_queue *rxq = NULL; + struct intr_handle *hdl = NULL; + uint32_t mask; + int gi, qi, qn; + + ctrl->nb_rxq = 0; + sal_memset(ctrl->rx_queue, 0, sizeof(ctrl->rx_queue)); + + /* Figure out available groups and Rx queues */ + for (gi = 0; gi < dev->num_groups; gi++) { + if (!ctrl->grp[gi].attached) { + continue; + } + qn = 0; + mask = 0; + for (qi = 0; qi < dev->grp_queues; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->grp[gi].rx_queue[qi]; + hdl = &ctrl->grp[gi].intr_hdl[qi]; + if (1 << (qi + gi * dev->grp_queues) & qbm) { + /* Set the number of descriptors */ + rxq->nb_desc = ctrl->grp[gi].nb_desc[qi]; + if (!rxq->nb_desc) { + rxq->nb_desc = ctrl->nb_desc; + ctrl->grp[gi].nb_desc[qi] = rxq->nb_desc; + } + /* Set Rx buffer size */ + rxq->buf_size = ctrl->grp[gi].rx_size[qi]; + if (rxq->buf_size < RX_BUF_SIZE_MIN) { + rxq->buf_size = RX_BUF_SIZE_MIN; + ctrl->grp[gi].rx_size[qi] = rxq->buf_size; + } else if (rxq->buf_size > RX_BUF_SIZE_MAX) { + rxq->buf_size = ctrl->rx_buf_size; + ctrl->grp[gi].rx_size[qi] = rxq->buf_size; + } + rxq->buf_size += dev->rx_ph_size; + /* Set mode and state for the queue */ + rxq->mode = bm->rx_buf_mode(dev, rxq); + rxq->state = PDMA_RX_QUEUE_USED; + if (dev->flags & PDMA_RX_BATCHING) { + rxq->free_thresh = rxq->nb_desc / 4; + rxq->state |= PDMA_RX_BATCH_REFILL; + } + /* Update queue index */ + rxq->queue_id = ctrl->nb_rxq; + ctrl->rx_queue[rxq->queue_id] = rxq; + ctrl->nb_rxq++; + qn++; + mask |= 1 << qi; + /* Set up handler for the queue */ + hdl->queue = rxq->queue_id; + hdl->dir = PDMA_Q_RX; + hdl->budget = ctrl->budget < rxq->nb_desc ? + ctrl->budget : rxq->nb_desc; + if (dev->mode == DEV_MODE_HNET) { + ctrl->vnet_rxq[rxq->queue_id] = ctrl->grp[gi].vnet_rxq[qi]; + } + } else { + rxq->state = 0; + } + } + + /* Set group metadata */ + if (qn) { + ctrl->grp[gi].bm_rxq = mask; + ctrl->grp[gi].nb_rxq = qn; + } else { + ctrl->grp[gi].bm_rxq = 0; + ctrl->grp[gi].nb_rxq = 0; + } + } + + return SHR_E_NONE; +} + +/*! + * \brief Parse Tx groups + * + * \param [in] dev Device structure point. + * \param [in] qbm Tx queue bitmap. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +bcn_tx_queue_group_parse(struct pdma_dev *dev, uint32_t qbm) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL; + struct intr_handle *hdl = NULL; + uint32_t mask; + int gi, qi, qn; + + ctrl->nb_txq = 0; + sal_memset(ctrl->tx_queue, 0, sizeof(ctrl->tx_queue)); + + /* Figure out available groups and Tx queues */ + for (gi = 0; gi < dev->num_groups; gi++) { + if (!ctrl->grp[gi].attached) { + continue; + } + qn = 0; + mask = 0; + for (qi = 0; qi < dev->grp_queues; qi++) { + txq = (struct pdma_tx_queue *)ctrl->grp[gi].tx_queue[qi]; + hdl = &ctrl->grp[gi].intr_hdl[qi]; + if (1 << (qi + gi * dev->grp_queues) & qbm) { + /* Set the number of descriptors */ + txq->nb_desc = ctrl->grp[gi].nb_desc[qi]; + if (!txq->nb_desc) { + txq->nb_desc = ctrl->nb_desc; + ctrl->grp[gi].nb_desc[qi] = txq->nb_desc; + } + /* Set mode and state for the queue */ + txq->state = PDMA_TX_QUEUE_USED; + if (dev->flags & PDMA_TX_POLLING) { + txq->free_thresh = txq->nb_desc / 4; + txq->state |= PDMA_TX_QUEUE_POLL; + } + /* Update queue index */ + txq->queue_id = ctrl->nb_txq; + ctrl->tx_queue[txq->queue_id] = txq; + ctrl->nb_txq++; + qn++; + mask |= 1 << qi; + /* Set up handler for the queue */ + hdl->queue = txq->queue_id; + hdl->dir = PDMA_Q_TX; + hdl->budget = ctrl->budget < txq->nb_desc ? + ctrl->budget : txq->nb_desc; + if (dev->mode == DEV_MODE_HNET) { + ctrl->vnet_txq[txq->queue_id] = ctrl->grp[gi].vnet_txq[qi]; + } + } else { + txq->state = 0; + } + } + + /* Set group metadata */ + if (qn) { + ctrl->grp[gi].bm_txq = mask; + ctrl->grp[gi].nb_txq = qn; + } else { + ctrl->grp[gi].bm_txq = 0; + ctrl->grp[gi].nb_txq = 0; + } + } + + return SHR_E_NONE; +} + +/*! + * \brief Configure device + * + * \param [in] dev Device structure point. + * \param [in] bm_rxq Rx queue bitmap. + * \param [in] bm_txq Tx queue bitmap. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +bcmcnet_pdma_config(struct pdma_dev *dev, uint32_t bm_rxq, uint32_t bm_txq) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + int gi; + + if (!bm_rxq || !bm_txq || (bm_rxq & bm_txq)) { + return SHR_E_PARAM; + } + + bcn_rx_queue_group_parse(dev, bm_rxq); + bcn_tx_queue_group_parse(dev, bm_txq); + + for (gi = 0; gi < dev->num_groups; gi++) { + if (!ctrl->grp[gi].attached) { + continue; + } + /* Update group metadata */ + if (!ctrl->grp[gi].bm_rxq && !ctrl->grp[gi].bm_txq) { + ctrl->grp[gi].attached = 0; + ctrl->bm_grp &= ~(1 << gi); + ctrl->nb_grp--; + continue; + } + ctrl->grp[gi].ctrl = ctrl; + ctrl->grp[gi].id = gi; + ctrl->grp[gi].irq_mask = 0; + } + + return hw->hdls.hw_config(hw); +} + +/*! + * Close device + */ +static int +bcmcnet_pdma_close(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)dev->ctrl.hw; + int gi; + + hw->hdls.hw_reset(hw); + + for (gi = 0; gi < dev->num_groups; gi++) { + if (!ctrl->grp[gi].attached) { + continue; + } + /* Reset group metadata */ + ctrl->bm_grp &= ~(1 << gi); + ctrl->nb_grp--; + ctrl->grp[gi].irq_mask = 0; + ctrl->grp[gi].poll_queues = 0; + ctrl->grp[gi].attached = 0; + } + + bcn_rx_queues_free(dev); + bcn_tx_queues_free(dev); + + return SHR_E_NONE; +} + +/*! + * Suspend device + */ +static int +bcmcnet_pdma_suspend(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + bcmcnet_pdma_rx_queue_suspend(dev, qi); + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + bcmcnet_pdma_tx_queue_suspend(dev, qi); + } + + return SHR_E_NONE; +} + +/*! + * Resume device + */ +static int +bcmcnet_pdma_resume(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + bcmcnet_pdma_rx_queue_resume(dev, qi); + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + bcmcnet_pdma_tx_queue_resume(dev, qi); + } + + return SHR_E_NONE; +} + +/*! + * Get device information + */ +static void +bcmcnet_pdma_info_get(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + uint32_t qi; + + sal_strncpy(dev->info.dev_name, dev->name, sizeof(dev->info.dev_name) - 1); + dev->info.dev_name[sizeof(dev->info.dev_name) - 1] = 0; + dev->info.dev_id = dev->dev_id; + dev->info.dev_type = dev->dev_type; + dev->info.max_groups = hw->info.num_cmcs; + dev->info.max_queues = hw->info.num_chans; + dev->info.bm_groups = ctrl->bm_grp; + dev->info.bm_rx_queues = ctrl->bm_rxq; + dev->info.bm_tx_queues = ctrl->bm_txq; + dev->info.nb_groups = ctrl->nb_grp; + dev->info.nb_rx_queues = ctrl->nb_rxq; + dev->info.nb_tx_queues = ctrl->nb_txq; + dev->info.rx_desc_size = hw->info.rx_dcb_size; + dev->info.tx_desc_size = hw->info.tx_dcb_size; + dev->info.rx_ph_size = hw->info.rx_ph_size; + dev->info.tx_ph_size = hw->info.tx_ph_size; + dev->info.rx_buf_dflt = ctrl->rx_buf_size; + dev->info.nb_desc_dflt = ctrl->nb_desc; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi]; + if (!rxq) { + continue; + } + dev->info.rx_buf_size[qi] = rxq->buf_size; + dev->info.nb_rx_desc[qi] = rxq->nb_desc; + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi]; + if (!txq) { + continue; + } + dev->info.nb_tx_desc[qi] = txq->nb_desc; + } +} + +/*! + * Get device statistics + */ +static void +bcmcnet_pdma_stats_get(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + uint32_t packets = 0, bytes = 0, dropped = 0, errors = 0, nomems = 0, xoffs = 0; + uint32_t head_errors = 0, data_errors = 0, cell_errors = 0; + uint32_t qi; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi]; + if (!rxq) { + continue; + } + packets += rxq->stats.packets; + bytes += rxq->stats.bytes; + dropped += rxq->stats.dropped; + errors += rxq->stats.errors; + head_errors += rxq->stats.head_errors; + data_errors += rxq->stats.data_errors; + cell_errors += rxq->stats.cell_errors; + nomems += rxq->stats.nomems; + dev->stats.rxq_packets[qi] = rxq->stats.packets; + dev->stats.rxq_bytes[qi] = rxq->stats.bytes; + dev->stats.rxq_dropped[qi] = rxq->stats.dropped; + dev->stats.rxq_errors[qi] = rxq->stats.errors; + dev->stats.rxq_head_errors[qi] = rxq->stats.head_errors; + dev->stats.rxq_data_errors[qi] = rxq->stats.data_errors; + dev->stats.rxq_cell_errors[qi] = rxq->stats.cell_errors; + dev->stats.rxq_nomems[qi] = rxq->stats.nomems; + } + + dev->stats.rx_packets = packets; + dev->stats.rx_bytes = bytes; + dev->stats.rx_dropped = dropped; + dev->stats.rx_errors = errors; + dev->stats.rx_head_errors = head_errors; + dev->stats.rx_data_errors = data_errors; + dev->stats.rx_cell_errors = cell_errors; + dev->stats.rx_nomems = nomems; + + packets = bytes = dropped = errors = 0; + for (qi = 0; qi < ctrl->nb_txq; qi++) { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi]; + if (!txq) { + continue; + } + packets += txq->stats.packets; + bytes += txq->stats.bytes; + dropped += txq->stats.dropped; + errors += txq->stats.errors; + xoffs += txq->stats.xoffs; + dev->stats.txq_packets[qi] = txq->stats.packets; + dev->stats.txq_bytes[qi] = txq->stats.bytes; + dev->stats.txq_dropped[qi] = txq->stats.dropped; + dev->stats.txq_errors[qi] = txq->stats.errors; + dev->stats.txq_xoffs[qi] = txq->stats.xoffs; + } + + dev->stats.tx_packets = packets; + dev->stats.tx_bytes = bytes; + dev->stats.tx_dropped = dropped; + dev->stats.tx_errors = errors; + dev->stats.tx_xoffs = xoffs; +} + +/*! + * Reset device statistics + */ +static void +bcmcnet_pdma_stats_reset(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + uint32_t qi; + + sal_memset(&dev->stats, 0, sizeof(struct bcmcnet_dev_stats)); + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi]; + if (!rxq) { + continue; + } + rxq->stats.packets = 0; + rxq->stats.bytes = 0; + rxq->stats.dropped = 0; + rxq->stats.errors = 0; + rxq->stats.head_errors = 0; + rxq->stats.data_errors = 0; + rxq->stats.cell_errors = 0; + rxq->stats.nomems = 0; + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi]; + if (!txq) { + continue; + } + txq->stats.packets = 0; + txq->stats.bytes = 0; + txq->stats.dropped = 0; + txq->stats.errors = 0; + txq->stats.xoffs = 0; + } +} + +/*! + * Convert logic queue to physical queue + */ +static int +bcmcnet_pdma_lq_to_pq(struct pdma_dev *dev, int queue, int dir, int *chan) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + + if (dir == PDMA_Q_RX) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (rxq->state & PDMA_RX_QUEUE_USED) { + *chan = rxq->chan_id; + return SHR_E_NONE; + } + } else { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->state & PDMA_TX_QUEUE_USED) { + *chan = txq->chan_id; + return SHR_E_NONE; + } + } + + return SHR_E_UNAVAIL; +} + +/*! + * Convert physical queue to logic queue + */ +static int +bcmcnet_pdma_pq_to_lq(struct pdma_dev *dev, int chan, int *queue, int *dir) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + + rxq = ctrl->grp[chan / dev->grp_queues].rx_queue[chan % dev->grp_queues]; + if (rxq->state & PDMA_RX_QUEUE_USED) { + *queue = rxq->queue_id; + *dir = PDMA_Q_RX; + return SHR_E_NONE; + } + + txq = ctrl->grp[chan / dev->grp_queues].tx_queue[chan % dev->grp_queues]; + if (txq->state & PDMA_TX_QUEUE_USED) { + *queue = txq->queue_id; + *dir = PDMA_Q_TX; + return SHR_E_NONE; + } + + return SHR_E_UNAVAIL; +} + +/*! + * Start Rx queue + */ +static int +bcmcnet_pdma_rx_queue_start(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + rxq->state |= PDMA_RX_QUEUE_ACTIVE; + + return hw->hdls.chan_start(hw, rxq->chan_id); +} + +/*! + * Stop Rx queue + */ +static int +bcmcnet_pdma_rx_queue_stop(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + rxq->state &= ~PDMA_RX_QUEUE_ACTIVE; + + return hw->hdls.chan_stop(hw, rxq->chan_id); +} + +/*! + * Start Tx queue + */ +static int +bcmcnet_pdma_tx_queue_start(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + txq->state |= PDMA_TX_QUEUE_ACTIVE; + + return dev->flags & PDMA_CHAIN_MODE ? SHR_E_NONE : + hw->hdls.chan_start(hw, txq->chan_id); +} + +/*! + * Stop Tx queue + */ +static int +bcmcnet_pdma_tx_queue_stop(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + txq->state &= ~PDMA_TX_QUEUE_ACTIVE; + + return hw->hdls.chan_stop(hw, txq->chan_id); +} + +/*! + * Enable Rx queue interrupt + */ +static int +bcmcnet_pdma_rx_queue_intr_enable(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_intr_enable(hw, rxq->chan_id); +} + +/*! + * Disable Rx queue interrupt + */ +static int +bcmcnet_pdma_rx_queue_intr_disable(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_intr_disable(hw, rxq->chan_id); +} + +/*! + * Acknowledge Rx queue interrupt + */ +static int +bcmcnet_pdma_rx_queue_intr_ack(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_clear(hw, rxq->chan_id); +} + +/*! + * Query Rx queue interrupt + */ +static int +bcmcnet_pdma_rx_queue_intr_query(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_intr_query(hw, rxq->chan_id); +} + +/*! + * Check Rx queue interrupt + */ +static int +bcmcnet_pdma_rx_queue_intr_check(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_intr_check(hw, rxq->chan_id); +} + +/*! + * Enable Tx queue interrupt + */ +static int +bcmcnet_pdma_tx_queue_intr_enable(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + if (txq->state & PDMA_TX_QUEUE_POLL) { + return SHR_E_NONE; + } else { + return hw->hdls.chan_intr_enable(hw, txq->chan_id); + } +} + +/*! + * Disable Tx queue interrupt + */ +static int +bcmcnet_pdma_tx_queue_intr_disable(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + return hw->hdls.chan_intr_disable(hw, txq->chan_id); +} + +/*! + * Acknowledge Tx queue interrupt + */ +static int +bcmcnet_pdma_tx_queue_intr_ack(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + return hw->hdls.chan_clear(hw, txq->chan_id); +} + +/*! + * Query Tx queue interrupt + */ +static int +bcmcnet_pdma_tx_queue_intr_query(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + return hw->hdls.chan_intr_query(hw, txq->chan_id); +} + +/*! + * Check Tx queue interrupt + */ +static int +bcmcnet_pdma_tx_queue_intr_check(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + return hw->hdls.chan_intr_check(hw, txq->chan_id); +} + +/*! + * \brief Device operation functions. + */ +static const struct dev_ops pdma_dev_ops = { + .dev_config = bcmcnet_pdma_config, + .dev_close = bcmcnet_pdma_close, + .dev_suspend = bcmcnet_pdma_suspend, + .dev_resume = bcmcnet_pdma_resume, + .dev_info_get = bcmcnet_pdma_info_get, + .dev_stats_get = bcmcnet_pdma_stats_get, + .dev_stats_reset = bcmcnet_pdma_stats_reset, + .dev_lq_to_pq = bcmcnet_pdma_lq_to_pq, + .dev_pq_to_lq = bcmcnet_pdma_pq_to_lq, + .rx_queue_start = bcmcnet_pdma_rx_queue_start, + .rx_queue_stop = bcmcnet_pdma_rx_queue_stop, + .tx_queue_start = bcmcnet_pdma_tx_queue_start, + .tx_queue_stop = bcmcnet_pdma_tx_queue_stop, + .rx_queue_setup = bcmcnet_pdma_rx_queue_setup, + .rx_queue_release = bcmcnet_pdma_rx_queue_release, + .rx_queue_restore = bcmcnet_pdma_rx_queue_restore, + .rx_vqueue_setup = bcmcnet_pdma_rx_vqueue_setup, + .rx_vqueue_release = bcmcnet_pdma_rx_vqueue_release, + .tx_queue_setup = bcmcnet_pdma_tx_queue_setup, + .tx_queue_release = bcmcnet_pdma_tx_queue_release, + .tx_queue_restore = bcmcnet_pdma_tx_queue_restore, + .tx_vqueue_setup = bcmcnet_pdma_tx_vqueue_setup, + .tx_vqueue_release = bcmcnet_pdma_tx_vqueue_release, + .rx_queue_intr_enable = bcmcnet_pdma_rx_queue_intr_enable, + .rx_queue_intr_disable = bcmcnet_pdma_rx_queue_intr_disable, + .rx_queue_intr_ack = bcmcnet_pdma_rx_queue_intr_ack, + .rx_queue_intr_query = bcmcnet_pdma_rx_queue_intr_query, + .rx_queue_intr_check = bcmcnet_pdma_rx_queue_intr_check, + .tx_queue_intr_enable = bcmcnet_pdma_tx_queue_intr_enable, + .tx_queue_intr_disable = bcmcnet_pdma_tx_queue_intr_disable, + .tx_queue_intr_ack = bcmcnet_pdma_tx_queue_intr_ack, + .tx_queue_intr_query = bcmcnet_pdma_tx_queue_intr_query, + .tx_queue_intr_check = bcmcnet_pdma_tx_queue_intr_check, + .rx_queue_suspend = bcmcnet_pdma_rx_queue_suspend, + .rx_queue_resume = bcmcnet_pdma_rx_queue_resume, + .tx_queue_wakeup = bcmcnet_pdma_tx_queue_wakeup, + .rx_queue_poll = bcmcnet_pdma_rx_queue_poll, + .tx_queue_poll = bcmcnet_pdma_tx_queue_poll, + .group_poll = bcmcnet_pdma_group_poll, +}; + +/*! + * Open a device + */ +int +bcmcnet_pdma_open(struct pdma_dev *dev) +{ + struct pdma_hw *hw = (struct pdma_hw *)dev->ctrl.hw; + struct intr_handle *hdl = NULL; + int chan, gi, qi; + + if (!hw) { + return SHR_E_INIT; + } + + /* Initialize the hardware */ + hw->hdls.hw_reset(hw); + hw->hdls.hw_init(hw); + + if ((uint32_t)dev->num_groups > hw->info.num_cmcs) { + return SHR_E_PARAM; + } + dev->grp_queues = hw->info.cmc_chans; + dev->num_queues = hw->info.num_chans; + dev->rx_ph_size = hw->info.rx_ph_size; + dev->tx_ph_size = hw->info.tx_ph_size; + dev->ctrl.nb_desc = NUM_RING_DESC; + dev->ctrl.budget = NUM_RXTX_BUDGET; + dev->ctrl.rx_desc_size = hw->info.rx_dcb_size; + dev->ctrl.tx_desc_size = hw->info.tx_dcb_size; + + /* Initialize interrupt handler */ + for (chan = 0; chan < dev->num_queues; chan++) { + gi = chan / dev->grp_queues; + qi = chan % dev->grp_queues; + hdl = &dev->ctrl.grp[gi].intr_hdl[qi]; + hdl->unit = dev->unit; + hdl->group = gi; + hdl->chan = chan; + hdl->dev = dev; + hdl->intr_num = hw->hdls.chan_intr_num_get(hw, chan); + if (hdl->intr_num < 0) { + return SHR_E_INTERNAL; + } + } + + /* Initialize buffer manager */ + bcmcnet_buf_mngr_init(dev); + + /* Allocate all the queues */ + bcn_rx_queues_alloc(dev); + bcn_tx_queues_alloc(dev); + + dev->pkt_xmit = bcmcnet_pdma_tx_queue_xmit; + + dev->ops = (struct dev_ops *)&pdma_dev_ops; + + return SHR_E_NONE; +} + +/*! + * Coalesce Rx interrupt + */ +int +bcmcnet_pdma_rx_queue_int_coalesce(struct pdma_dev *dev, int queue, int count, int timer) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + if ((uint32_t)queue >= ctrl->nb_rxq) { + return SHR_E_PARAM; + } + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + rxq->intr_coalescing = 1; + rxq->ic_val = (count & 0x7fff) << 16 | (timer & 0xffff); + + return hw->hdls.chan_intr_coalesce(hw, rxq->chan_id, count, timer); +} + +/*! + * Coalesce Tx interrupt + */ +int +bcmcnet_pdma_tx_queue_int_coalesce(struct pdma_dev *dev, int queue, int count, int timer) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + if ((uint32_t)queue >= ctrl->nb_txq) { + return SHR_E_PARAM; + } + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + txq->intr_coalescing = 1; + txq->ic_val = (count & 0x7fff) << 16 | (timer & 0xffff); + + return hw->hdls.chan_intr_coalesce(hw, txq->chan_id, count, timer); +} + +/*! + * Dump Rx queue registers + */ +int +bcmcnet_pdma_rx_queue_reg_dump(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + if ((uint32_t)queue >= ctrl->nb_rxq) { + return SHR_E_PARAM; + } + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_reg_dump(hw, rxq->chan_id); +} + +/*! + * Dump Tx queue registers + */ +int +bcmcnet_pdma_tx_queue_reg_dump(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + if ((uint32_t)queue >= ctrl->nb_txq) { + return SHR_E_PARAM; + } + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + return hw->hdls.chan_reg_dump(hw, txq->chan_id); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_rxtx.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_rxtx.c new file mode 100644 index 000000000000..cfabe9d95d56 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_rxtx.c @@ -0,0 +1,708 @@ +/*! \file bcmcnet_rxtx.c + * + * Utility routines for BCMCNET Rx/Tx. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include + +/*! + * Free a Rx ring + */ +static void +bcn_rx_ring_free(struct pdma_rx_queue *rxq) +{ + struct dev_ctrl *ctrl = rxq->ctrl; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr; + + if (rxq->lock) { + sal_spinlock_destroy(rxq->lock); + rxq->lock = NULL; + } + + if (rxq->ring) { + bm->ring_buf_free(ctrl->dev, ctrl->rx_desc_size * (rxq->nb_desc + 1), + rxq->ring, rxq->ring_addr); + rxq->ring = NULL; + } + + if (rxq->pbuf) { + sal_free(rxq->pbuf); + rxq->pbuf = NULL; + } +} + +/*! + * Allocate a Rx ring + */ +static int +bcn_rx_ring_alloc(struct pdma_rx_queue *rxq) +{ + struct dev_ctrl *ctrl = rxq->ctrl; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr; + + /* Setup pktbuf ring */ + rxq->pbuf = sal_alloc(sizeof(*rxq->pbuf) * rxq->nb_desc, "bcmcnetRxBufRing"); + if (!rxq->pbuf) { + goto cleanup; + } + sal_memset(rxq->pbuf, 0, sizeof(*rxq->pbuf) * rxq->nb_desc); + + /* Allocate memory for descriptors */ + rxq->ring = bm->ring_buf_alloc(ctrl->dev, ctrl->rx_desc_size * (rxq->nb_desc + 1), + &rxq->ring_addr); + if (!rxq->ring) { + goto cleanup; + } + sal_memset(rxq->ring, 0, ctrl->rx_desc_size * (rxq->nb_desc + 1)); + + rxq->lock = sal_spinlock_create("bcmcnetRxQueueLock"); + if (!rxq->lock) { + goto cleanup; + } + + return SHR_E_NONE; + +cleanup: + bcn_rx_ring_free(rxq); + + return SHR_E_MEMORY; +} + +/*! + * Free a Tx ring + */ +static void +bcn_tx_ring_free(struct pdma_tx_queue *txq) +{ + struct dev_ctrl *ctrl = txq->ctrl; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr; + + if (txq->sem) { + sal_sem_destroy(txq->sem); + txq->sem = NULL; + } + + if (txq->mutex) { + sal_spinlock_destroy(txq->mutex); + txq->mutex = NULL; + } + + if (txq->lock) { + sal_spinlock_destroy(txq->lock); + txq->lock = NULL; + } + + if (txq->ring) { + bm->ring_buf_free(ctrl->dev, ctrl->tx_desc_size * (txq->nb_desc + 1), + txq->ring, txq->ring_addr); + txq->ring = NULL; + } + + if (txq->pbuf) { + sal_free(txq->pbuf); + txq->pbuf = NULL; + } +} + +/*! + * Allocate a Tx ring + */ +static int +bcn_tx_ring_alloc(struct pdma_tx_queue *txq) +{ + struct dev_ctrl *ctrl = txq->ctrl; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr; + + /* Setup pktbuf ring */ + txq->pbuf = sal_alloc(sizeof(*txq->pbuf) * txq->nb_desc, "bcmcnetTxBufRing"); + if (!txq->pbuf) { + goto cleanup; + } + sal_memset(txq->pbuf, 0, sizeof(*txq->pbuf) * txq->nb_desc); + + /* Allocate memory for descriptors */ + txq->ring = bm->ring_buf_alloc(ctrl->dev, ctrl->tx_desc_size * (txq->nb_desc + 1), + &txq->ring_addr); + if (!txq->ring) { + goto cleanup; + } + sal_memset(txq->ring, 0, ctrl->tx_desc_size * (txq->nb_desc + 1)); + + txq->lock = sal_spinlock_create("bcmcnetTxQueueLock"); + if (!txq->lock) { + goto cleanup; + } + + txq->mutex = sal_spinlock_create("bcmcnetTxMutexLock"); + if (!txq->mutex) { + goto cleanup; + } + + txq->sem = sal_sem_create("bcmcnetTxMutexSem", SAL_SEM_BINARY, 0); + if (!txq->sem) { + goto cleanup; + } + + return SHR_E_NONE; + +cleanup: + bcn_tx_ring_free(txq); + + return SHR_E_MEMORY; +} + +/*! + * Rx polling + */ +static int +bcn_rx_poll(struct pdma_rx_queue *rxq, int budget) +{ + struct dev_ctrl *ctrl = rxq->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + + return hw->dops.rx_ring_clean(hw, rxq, budget); +} + +/*! + * Tx polling + */ +static int +bcn_tx_poll(struct pdma_tx_queue *txq, int budget) +{ + struct dev_ctrl *ctrl = txq->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + + return hw->dops.tx_ring_clean(hw, txq, budget); +} + +/*! + * Setup a Rx queue + */ +int +bcmcnet_pdma_rx_queue_setup(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + int rv; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (rxq->state & PDMA_RX_QUEUE_SETUP) { + return SHR_E_NONE; + } + + rv = bcn_rx_ring_alloc(rxq); + if (SHR_FAILURE(rv)) { + return rv; + } + + rv = hw->dops.rx_desc_init(hw, rxq); + if (SHR_FAILURE(rv)) { + return rv; + } + + if (dev->mode == DEV_MODE_VNET) { + ctrl->vsync.rx_ring_addr[queue] = rxq->ring_addr; + ctrl->vsync.rx_ring_size[queue] = rxq->nb_desc; + } + + rxq->state |= PDMA_RX_QUEUE_SETUP; + + return SHR_E_NONE; +} + +/*! + * Release a Rx queue + */ +int +bcmcnet_pdma_rx_queue_release(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (rxq->state & PDMA_RX_QUEUE_SETUP) { + hw->dops.rx_desc_clean(hw, rxq); + bcn_rx_ring_free(rxq); + rxq->state &= ~PDMA_RX_QUEUE_SETUP; + } + + return SHR_E_NONE; +} + +/*! + * Restore a Rx queue + */ +int +bcmcnet_pdma_rx_queue_restore(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (rxq->state & PDMA_RX_QUEUE_SETUP) { + hw->dops.rx_desc_init(hw, rxq); + } + + return SHR_E_NONE; +} + +/*! + * Set up a virtual Rx queue + */ +int +bcmcnet_pdma_rx_vqueue_setup(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *vrxq = NULL; + + vrxq = (struct pdma_rx_queue *)ctrl->vnet_rxq[queue]; + if (vrxq->state & PDMA_RX_QUEUE_SETUP) { + return SHR_E_NONE; + } + + if (dev->ctrl.vsync.rx_ring_addr[queue]) { + vrxq->curr = 0; + vrxq->nb_desc = dev->ctrl.vsync.rx_ring_size[queue]; + vrxq->ring_addr = dev->ctrl.vsync.rx_ring_addr[queue]; + vrxq->ring = dev->sys_p2v(dev, vrxq->ring_addr); + vrxq->state |= PDMA_RX_QUEUE_SETUP; + } else { + return SHR_E_UNAVAIL; + } + + return SHR_E_NONE; +} + +/*! + * Release a virtual Rx queue + */ +int +bcmcnet_pdma_rx_vqueue_release(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *vrxq = NULL; + + vrxq = (struct pdma_rx_queue *)ctrl->vnet_rxq[queue]; + if (vrxq->state & PDMA_RX_QUEUE_SETUP) { + vrxq->state &= ~PDMA_RX_QUEUE_SETUP; + vrxq->ring = NULL; + } + + return SHR_E_NONE; +} + +/*! + * Setup a Tx queue + */ +int +bcmcnet_pdma_tx_queue_setup(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + int rv; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->state & PDMA_TX_QUEUE_SETUP) { + return SHR_E_NONE; + } + + rv = bcn_tx_ring_alloc(txq); + if (SHR_FAILURE(rv)) { + return rv; + } + + rv = hw->dops.tx_desc_init(hw, txq); + if (SHR_FAILURE(rv)) { + return rv; + } + + if (dev->mode == DEV_MODE_VNET) { + ctrl->vsync.tx_ring_addr[queue] = txq->ring_addr; + ctrl->vsync.tx_ring_size[queue] = txq->nb_desc; + } + + txq->state |= PDMA_TX_QUEUE_SETUP; + + return SHR_E_NONE; +} + +/*! + * Release a Tx queue + */ +int +bcmcnet_pdma_tx_queue_release(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->state & PDMA_TX_QUEUE_SETUP) { + hw->dops.tx_desc_clean(hw, txq); + bcn_tx_ring_free(txq); + txq->state &= ~PDMA_TX_QUEUE_SETUP; + } + + return SHR_E_NONE; +} + +/*! + * Restore a Tx queue + */ +int +bcmcnet_pdma_tx_queue_restore(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->state & PDMA_TX_QUEUE_SETUP) { + hw->dops.tx_desc_init(hw, txq); + } + + return SHR_E_NONE; +} + +/*! + * Set up a virtual Tx queue + */ +int +bcmcnet_pdma_tx_vqueue_setup(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *vtxq = NULL; + + vtxq = (struct pdma_tx_queue *)ctrl->vnet_txq[queue]; + if (vtxq->state & PDMA_TX_QUEUE_SETUP) { + return SHR_E_NONE; + } + + if (dev->ctrl.vsync.tx_ring_addr[queue]) { + vtxq->curr = 0; + vtxq->dirt = 0; + vtxq->nb_desc = dev->ctrl.vsync.tx_ring_size[queue]; + vtxq->ring_addr = dev->ctrl.vsync.tx_ring_addr[queue]; + vtxq->ring = dev->sys_p2v(dev, vtxq->ring_addr); + vtxq->state |= PDMA_TX_QUEUE_SETUP; + } else { + return SHR_E_UNAVAIL; + } + + return SHR_E_NONE; +} + +/*! + * Release a virtual Tx queue + */ +int +bcmcnet_pdma_tx_vqueue_release(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *vtxq = NULL; + + vtxq = (struct pdma_tx_queue *)ctrl->vnet_txq[queue]; + if (vtxq->state & PDMA_TX_QUEUE_SETUP) { + vtxq->state &= ~PDMA_TX_QUEUE_SETUP; + vtxq->ring = NULL; + } + + return SHR_E_NONE; +} + +/*! + * Suspend a Rx queue + */ +int +bcmcnet_pdma_rx_queue_suspend(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (!rxq || !(rxq->state & PDMA_RX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + return hw->dops.rx_suspend(hw, rxq); +} + +/*! + * Resume a Rx queue + */ +int +bcmcnet_pdma_rx_queue_resume(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (!rxq || !(rxq->state & PDMA_RX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + return hw->dops.rx_resume(hw, rxq); +} + +/*! + * Suspend a Tx queue + */ +int +bcmcnet_pdma_tx_queue_suspend(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (!txq || !(txq->state & PDMA_TX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + if (txq->sem) { + sal_sem_take(txq->sem, SAL_SEM_FOREVER); + } + if (dev->tx_suspend) { + dev->tx_suspend(dev, txq->queue_id); + } + + return SHR_E_NONE; +} + +/*! + * Resume a Tx queue + */ +int +bcmcnet_pdma_tx_queue_resume(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (!txq || !(txq->state & PDMA_TX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + if (txq->sem) { + sal_sem_give(txq->sem); + } + if (dev->tx_resume) { + dev->tx_resume(dev, txq->queue_id); + } + + return SHR_E_NONE; +} + +/*! + * Wake up a Tx queue + */ +int +bcmcnet_pdma_tx_queue_wakeup(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->sem) { + sal_sem_give(txq->sem); + } + + return SHR_E_NONE; +} + +/*! + * Transmit a outputing packet + */ +int +bcmcnet_pdma_tx_queue_xmit(struct pdma_dev *dev, int queue, void *buf) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (!txq || !(txq->state & PDMA_TX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + return hw->dops.pkt_xmit(hw, txq, buf); +} + +/*! + * Poll a Rx queues + */ +int +bcmcnet_pdma_rx_queue_poll(struct pdma_dev *dev, int queue, int budget) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = ctrl->rx_queue[queue]; + + return bcn_rx_poll(rxq, budget); +} + +/*! + * Poll a Tx queues + */ +int +bcmcnet_pdma_tx_queue_poll(struct pdma_dev *dev, int queue, int budget) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = ctrl->tx_queue[queue]; + + return bcn_tx_poll(txq, budget); +} + +/*! + * Poll for Rx/Tx queues in a group + */ +int +bcmcnet_pdma_group_poll(struct pdma_dev *dev, int group, int budget) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + struct queue_group *grp = &ctrl->grp[group]; + int done = 0, done_que, budget_que; + int i; + + /* Acknowledge the interrupts */ + for (i = 0; i < dev->grp_queues; i++) { + rxq = grp->rx_queue[i]; + if (rxq->state & PDMA_RX_QUEUE_ACTIVE) { + if (hw->hdls.chan_intr_query(hw, rxq->chan_id)) { + hw->hdls.chan_clear(hw, rxq->chan_id); + grp->poll_queues |= 1 << i; + } else if (rxq->state & PDMA_RX_QUEUE_BUSY) { + rxq->state &= ~PDMA_RX_QUEUE_BUSY; + grp->poll_queues |= 1 << i; + } + continue; + } + txq = grp->tx_queue[i]; + if (txq->state & PDMA_TX_QUEUE_ACTIVE) { + if (hw->hdls.chan_intr_query(hw, txq->chan_id)) { + hw->hdls.chan_clear(hw, txq->chan_id); + grp->poll_queues |= 1 << i; + } + } + } + + /* Calculate per queue budget */ + if (!grp->poll_queues) { + grp->poll_queues = grp->bm_rxq | grp->bm_txq; + budget_que = budget / grp->nb_rxq; + } else { + budget_que = 0; + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq & grp->poll_queues) { + budget_que++; + } + } + if (budget_que) { + budget_que = budget / budget_que; + } + } + + /* Poll Rx queues */ + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq & grp->poll_queues) { + rxq = grp->rx_queue[i]; + done_que = bcn_rx_poll(rxq, budget_que); + if (done_que < budget_que) { + grp->poll_queues &= ~(1 << i); + } + done += done_que; + } + } + + /* Poll Tx queues */ + for (i = 0; i < dev->grp_queues; i++) { + txq = grp->tx_queue[i]; + if (1 << i & grp->bm_txq & grp->poll_queues && !txq->free_thresh) { + if (bcn_tx_poll(txq, budget) < budget) { + grp->poll_queues &= ~(1 << i); + } + } + } + + return grp->poll_queues ? budget : done; +} + +/*! + * Dump a Rx ring + */ +int +bcmcnet_pdma_rx_ring_dump(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + if ((uint32_t)queue >= ctrl->nb_rxq) { + return SHR_E_PARAM; + } + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (rxq->state & PDMA_RX_QUEUE_ACTIVE) { + hw->dops.rx_ring_dump(hw, rxq); + } + if (dev->mode == DEV_MODE_HNET) { + rxq = (struct pdma_rx_queue *)ctrl->vnet_rxq[queue]; + hw->dops.rx_ring_dump(hw, rxq); + } + + return SHR_E_NONE; +} + +/*! + * Dump a Tx ring + */ +int +bcmcnet_pdma_tx_ring_dump(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + if ((uint32_t)queue >= ctrl->nb_txq) { + return SHR_E_PARAM; + } + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->state & PDMA_TX_QUEUE_ACTIVE) { + hw->dops.tx_ring_dump(hw, txq); + } + if (dev->mode == DEV_MODE_HNET) { + txq = (struct pdma_tx_queue *)ctrl->vnet_txq[queue]; + hw->dops.tx_ring_dump(hw, txq); + } + + return SHR_E_NONE; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd/bcmdrd_devlist.h b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd/bcmdrd_devlist.h new file mode 100644 index 000000000000..675b9426ea01 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd/bcmdrd_devlist.h @@ -0,0 +1,337 @@ +/* + * DO NOT EDIT THIS FILE! + * This file is auto-generated. + * Edits to this file will be lost when it is regenerated. + * Tool: INTERNAL/drd/instpkgs.pl + * + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +/* + * This file contains the complete list of supported devices. + * No other device lists should be used anywhere in the SDK. + */ + +#ifndef BCMDRD_DEVIDS_H +#define BCMDRD_DEVIDS_H + +#include + +/* + * All Supported Devices and Revisions + */ + +#define BROADCOM_VENDOR_ID 0x14e4 +#define BROADCOM_PHYID_MSB 0x0143 + +/* BCM56780 */ +#define BCM56780_VENDOR_ID 0x14e4 +#define BCM56780_DEVICE_ID 0xb780 +#define BCM56780_REV_A0 0x01 + +/* BCM56782 */ +#define BCM56782_VENDOR_ID 0x14e4 +#define BCM56782_DEVICE_ID 0xb782 +#define BCM56782_REV_A0 0x01 + +/* BCM56784 */ +#define BCM56784_VENDOR_ID 0x14e4 +#define BCM56784_DEVICE_ID 0xb784 +#define BCM56784_REV_A0 0x01 + +/* BCM56786 */ +#define BCM56786_VENDOR_ID 0x14e4 +#define BCM56786_DEVICE_ID 0xb786 +#define BCM56786_REV_A0 0x01 + +/* BCM56788 */ +#define BCM56788_VENDOR_ID 0x14e4 +#define BCM56788_DEVICE_ID 0xb788 +#define BCM56788_REV_A0 0x01 + +/* BCM56789 */ +#define BCM56789_VENDOR_ID 0x14e4 +#define BCM56789_DEVICE_ID 0xb789 +#define BCM56789_REV_A0 0x01 + +/* BCM56880 */ +#define BCM56880_VENDOR_ID 0x14e4 +#define BCM56880_DEVICE_ID 0xb880 +#define BCM56880_REV_A0 0x01 +#define BCM56880_REV_B0 0x11 + +/* BCM56881 */ +#define BCM56881_VENDOR_ID 0x14e4 +#define BCM56881_DEVICE_ID 0xb881 +#define BCM56881_REV_A0 0x01 +#define BCM56881_REV_B0 0x11 + +/* BCM56883 */ +#define BCM56883_VENDOR_ID 0x14e4 +#define BCM56883_DEVICE_ID 0xb883 +#define BCM56883_REV_A0 0x01 +#define BCM56883_REV_B0 0x11 + +/* BCM56889 */ +#define BCM56889_VENDOR_ID 0x14e4 +#define BCM56889_DEVICE_ID 0xb889 +#define BCM56889_REV_A0 0x01 +#define BCM56889_REV_B0 0x11 + +/* BCM56990 */ +#define BCM56990_VENDOR_ID 0x14e4 +#define BCM56990_DEVICE_ID 0xb990 +#define BCM56990_REV_A0 0x01 +#define BCM56990_REV_B0 0x11 + +/* BCM56992 */ +#define BCM56992_VENDOR_ID 0x14e4 +#define BCM56992_DEVICE_ID 0xb992 +#define BCM56992_REV_B0 0x11 + +/* BCM56996 */ +#define BCM56996_VENDOR_ID 0x14e4 +#define BCM56996_DEVICE_ID 0xb996 +#define BCM56996_REV_A0 0x01 + +/* BCM56997 */ +#define BCM56997_VENDOR_ID 0x14e4 +#define BCM56997_DEVICE_ID 0xb997 +#define BCM56997_REV_A0 0x01 + +/* + * End of Supported Devices and Revisions + */ + +#endif /* BCMDRD_DEVIDS_H */ + +#ifdef BCMDRD_DEVLIST_ENTRY +/* + * BCMDRD_DEVLIST_ENTRY macros. + * + * Before including this file, define BCMDRD_DEVLIST_ENTRY + * as a macro to operate on the following parameters: + * + * #define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) + * + * _nm: Chip Name + * _vn: Chip Vendor ID + * _dv: Chip Device ID + * _rv: Chip Revision + * _md: Chip Model + * _pi: Probe Information + * _bd: SW Base Driver + * _bc: SW Base Configuration + * _fn: SW Full Name + * _cn: Code Name + * _pf: Product Family + * _pd: Product Description + * _r0: Reserved + * _r1: Reserved + * + * Note that this macro will be undefined at the end of this file. + */ + +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +BCMDRD_DEVLIST_ENTRY(BCM56780, BCM56780_VENDOR_ID, BCM56780_DEVICE_ID, BCM56780_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56780_a0, bcm56780_a0, \ + "Trident4-X9", "BCM56780", \ + "8 Tb/s 160x50G-PAM4 Programmable Switch", 0, 0) +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56782_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56782, BCM56782_VENDOR_ID, BCM56782_DEVICE_ID, BCM56782_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56782_a0, bcm56782_a0, \ + "Trident4-X9", "BCM56780", \ + "8 Tb/s 160x50G-PAM4 Programmable Switch w/MACsec", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56784_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56784, BCM56784_VENDOR_ID, BCM56784_DEVICE_ID, BCM56784_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56784_a0, bcm56784_a0, \ + "Trident4-X9", "BCM56780", \ + "5.6 Tb/s 96x50G-PAM4/32x35G-NRZ Programmable Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56786_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56786, BCM56786_VENDOR_ID, BCM56786_DEVICE_ID, BCM56786_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56786_a0, bcm56786_a0, \ + "Trident4-X9", "BCM56780", \ + "5.6 Tb/s 96x50G-PAM4/32x35G-NRZ Programmable Switch w/MACsec", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56788_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56788, BCM56788_VENDOR_ID, BCM56788_DEVICE_ID, BCM56788_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56788_a0, bcm56788_a0, \ + "Trident4-X9", "BCM56780", \ + "8 Tb/s 160x50G-PAM4 Programmable Switch w/MACsec w/MTop", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56789_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56789, BCM56789_VENDOR_ID, BCM56789_DEVICE_ID, BCM56789_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56789_a0, bcm56789_a0, \ + "Trident4-X9", "BCM56780", \ + "8 Tb/s 160x50G-PAM4 Programmable Switch w/MTop", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +BCMDRD_DEVLIST_ENTRY(BCM56880, BCM56880_VENDOR_ID, BCM56880_DEVICE_ID, BCM56880_REV_A0, \ + 0, 0, \ + bcm56880_a0, bcm56880_a0, bcm56880_a0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56880_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56880, BCM56880_VENDOR_ID, BCM56880_DEVICE_ID, BCM56880_REV_B0, \ + 0, 0, \ + bcm56880_a0, bcm56880_a0, bcm56880_b0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56881_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56881, BCM56881_VENDOR_ID, BCM56881_DEVICE_ID, BCM56881_REV_A0, \ + 0, 0, \ + bcm56880_a0, bcm56881_a0, bcm56881_a0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56881_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56881, BCM56881_VENDOR_ID, BCM56881_DEVICE_ID, BCM56881_REV_B0, \ + 0, 0, \ + bcm56880_a0, bcm56881_a0, bcm56881_b0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56883_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56883, BCM56883_VENDOR_ID, BCM56883_DEVICE_ID, BCM56883_REV_A0, \ + 0, 0, \ + bcm56880_a0, bcm56883_a0, bcm56883_a0, \ + "Trident4", "BCM56880", \ + "8.0 Tb/s Switch Fabric 80x100G/40x200G/20x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56883_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56883, BCM56883_VENDOR_ID, BCM56883_DEVICE_ID, BCM56883_REV_B0, \ + 0, 0, \ + bcm56880_a0, bcm56883_a0, bcm56883_b0, \ + "Trident4", "BCM56880", \ + "8.0 Tb/s Switch Fabric 80x100G/40x200G/20x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56889_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56889, BCM56889_VENDOR_ID, BCM56889_DEVICE_ID, BCM56889_REV_A0, \ + 0, 0, \ + bcm56880_a0, bcm56889_a0, bcm56889_a0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56889_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56889, BCM56889_VENDOR_ID, BCM56889_DEVICE_ID, BCM56889_REV_B0, \ + 0, 0, \ + bcm56880_a0, bcm56889_a0, bcm56889_b0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56990_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +BCMDRD_DEVLIST_ENTRY(BCM56990, BCM56990_VENDOR_ID, BCM56990_DEVICE_ID, BCM56990_REV_A0, \ + 0, 0, \ + bcm56990_a0, bcm56990_a0, bcm56990_a0, \ + "Tomahawk4", "BCM56990", \ + "25.6 Tbps Multilayer Switch", 0, 0) +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56990_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +BCMDRD_DEVLIST_ENTRY(BCM56990, BCM56990_VENDOR_ID, BCM56990_DEVICE_ID, BCM56990_REV_B0, \ + 0, 0, \ + bcm56990_b0, bcm56990_b0, bcm56990_b0, \ + "Tomahawk4", "BCM56990", \ + "25.6 Tbps Multilayer Switch", 0, 0) +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56992_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56992, BCM56992_VENDOR_ID, BCM56992_DEVICE_ID, BCM56992_REV_B0, \ + 0, 0, \ + bcm56990_b0, bcm56992_b0, bcm56992_b0, \ + "Tomahawk4", "BCM56990", \ + "25.6 Tbps Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56996_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +BCMDRD_DEVLIST_ENTRY(BCM56996, BCM56996_VENDOR_ID, BCM56996_DEVICE_ID, BCM56996_REV_A0, \ + 0, 0, \ + bcm56996_a0, bcm56996_a0, bcm56996_a0, \ + "Tomahawk4G", "BCM56996", \ + "25.6 Tbps Multilayer Switch", 0, 0) +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56997_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56997, BCM56997_VENDOR_ID, BCM56997_DEVICE_ID, BCM56997_REV_A0, \ + 0, 0, \ + bcm56996_a0, bcm56997_a0, bcm56997_a0, \ + "Tomahawk4G", "BCM56996", \ + "12.8 Tbps Multilayer Switch", 0, 0) +#endif +#endif + +/* End BCMDRD_DEVLIST_ENTRY Macros */ + +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +#undef BCMDRD_DEVLIST_INCLUDE_ALL +#endif +#ifdef BCMDRD_DEVLIST_OVERRIDE +#undef BCMDRD_DEVLIST_OVERRIDE +#endif +#undef BCMDRD_DEVLIST_ENTRY +#endif /* BCMDRD_DEVLIST_ENTRY */ diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config.h b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config.h new file mode 100644 index 000000000000..68e5a0891098 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config.h @@ -0,0 +1,166 @@ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + * + * DO NOT EDIT THIS FILE! + * This file will be auto-generated in the near future. + * + * This config file defines all compilation-time specifications for + * the BCMDRD. + * + * Reasonable defaults are provided for all configuration options + * where appropriate. + * + * You need not edit this file directly to change your configuration, + * nor is modifying this file advised -- so doing will require + * manually merging whenever the BCMDRD is upgraded. + * + * You should provide your own configuration options or overrides + * through a combination of: + * + * 1. The compiler command line, such as -D{OPTION}={VALUE} + * + * 2. Create your own custom configuration file: + * a) Create a file called 'bcmdrd_custom_config.h' + * b) Define all custom settings, using this file as + * the reference + * c) Add -DBCMDRD_INCLUDE_CUSTOM_CONFIG to your + * compilation + * d) Make sure the compilation include path includes + * 'bcmdrd_custom_config.h' + * + */ + +#ifndef BCMDRD_CONFIG_H +#define BCMDRD_CONFIG_H + + +/* + * Include system config file if specified: + */ +#ifdef BCMDRD_INCLUDE_CUSTOM_CONFIG +#include +#endif + + +/* + * OPTIONAL configuration and feature values. + * Defaults are provided for all non-specified values. + */ + +/* Maximum number of chips supported */ +#ifndef BCMDRD_CONFIG_MAX_UNITS +#define BCMDRD_CONFIG_MAX_UNITS 8 +#endif + +/* Maximum number of ports per chip supported */ +#ifndef BCMDRD_CONFIG_MAX_PORTS +#define BCMDRD_CONFIG_MAX_PORTS 576 +#endif + +/* Maximum number of SCHAN polls */ +#ifndef BCMDRD_CONFIG_SCHAN_MAX_POLLS +#define BCMDRD_CONFIG_SCHAN_MAX_POLLS 100000 +#endif + +/* Maximum number of MIIM polls */ +#ifndef BCMDRD_CONFIG_MIIM_MAX_POLLS +#define BCMDRD_CONFIG_MIIM_MAX_POLLS 100000 +#endif + +/* Direct access to memory-mapped registers */ +#ifndef BCMDRD_CONFIG_MEMMAP_DIRECT +#define BCMDRD_CONFIG_MEMMAP_DIRECT 0 +#endif + +/* + * Include chip symbol tables for the debug shell. + * + * No symbolic debugging (register/memory names) will be available + * without this defined. + * + * You should enable at least these symbols if you can afford the + * space. + * + * This define is required to get any symbols at all. + * + * If you only wish to include symbols for a subset of chips in the + * system (probably for code space reasons), you can define the + * following for each chip whose symbols you wish to EXCLUDE: + * + * BCMDRD_CONFIG_EXCLUDE_CHIP_SYMBOLS_ + * + */ +#ifndef BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS +#define BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS 1 +#endif + +/* + * Include register and memory field information for the debug shell. + * + * This provides encoding, decoding, and displaying individual field + * values for each register and memory. + * + * Requires more code space than just the chip symbols alone. + * + * The per-chip exclusion define + * (BCMDRD_CONFIG_EXCLUDE_FIELD_INFO_) also applies. + */ +#ifndef BCMDRD_CONFIG_INCLUDE_FIELD_INFO +#define BCMDRD_CONFIG_INCLUDE_FIELD_INFO 1 +#endif + +/* + * Include alternative symbol names for registers and memories. + * + * Mainly for internal Broadcom use, so you can safely leave this + * option off. + */ +#ifndef BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES +#define BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES 1 +#endif + +#endif /* BCMDRD_CONFIG_H */ + +#ifdef CONFIG_OPTION +#ifdef BCMDRD_INCLUDE_CUSTOM_CONFIG +CONFIG_OPTION(BCMDRD_INCLUDE_CUSTOM_CONFIG) +#endif +#ifdef BCMDRD_CONFIG_MAX_UNITS +CONFIG_OPTION(BCMDRD_CONFIG_MAX_UNITS) +#endif +#ifdef BCMDRD_CONFIG_MAX_PORTS +CONFIG_OPTION(BCMDRD_CONFIG_MAX_PORTS) +#endif +#ifdef BCMDRD_CONFIG_SCHAN_MAX_POLLS +CONFIG_OPTION(BCMDRD_CONFIG_SCHAN_MAX_POLLS) +#endif +#ifdef BCMDRD_CONFIG_MIIM_MAX_POLLS +CONFIG_OPTION(BCMDRD_CONFIG_MIIM_MAX_POLLS) +#endif +#ifdef BCMDRD_CONFIG_MEMMAP_DIRECT +CONFIG_OPTION(BCMDRD_CONFIG_MEMMAP_DIRECT) +#endif +#ifdef BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS) +#endif +#ifdef BCMDRD_CONFIG_INCLUDE_FIELD_INFO +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_FIELD_INFO) +#endif +#ifdef BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES) +#endif +#endif /* CONFIG_OPTION */ +#include "bcmdrd_config_chips.h" diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config_chips.h b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config_chips.h new file mode 100644 index 000000000000..5b45879c90e9 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config_chips.h @@ -0,0 +1,545 @@ +/* + * DO NOT EDIT THIS FILE! + * This file is auto-generated. + * Edits to this file will be lost when it is regenerated. + * Tool: INTERNAL/drd/instpkgs.pl + * + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +/* + * Chip inclusion and exclusion support within the BCMDRD can be + * specified as a combination of the following defines: + * + * (1) #define BCMDRD_CONFIG_INCLUDE_ [1|0] + * -- Include or exclude all revisions of the given device + * Example: #define BCMDRD_CONFIG_INCLUDE_BCM56780 1 + * + * (2) #define BCMDRD_CONFIG_INCLUDE__X [1|0] + * -- Include or exclude all versions of the given revision + * Example: #define BCMDRD_CONFIG_INCLUDE_BCM56780_Ax 0 + * #define BCMDRD_CONFIG_INCLUde_BCM56780_Bx 1 + * + * (3) #define BCMDRD_CONFIG_INCLUDE_ [1|0] + * -- Include or exclude an exact device + * Example: #define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 + * #define BCMDRD_CONFIG_INCLUDE_BCM56780_A1 0 + * + * + * The value of BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT is used for any + * chips which are left unspecified. Set this value to 1 or 0 to + * include or exclude all chips by default. + * + */ + +#ifndef BCMDRD_CONFIG_CHIPS_H +#define BCMDRD_CONFIG_CHIPS_H + +/* This determines whether a chip is included or excluded by default */ +#ifndef BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#define BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT 1 +#endif + +/* + * Default configuration and dependencies for all chips + */ + +/* + * BCM56780 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780 +#define BCMDRD_CONFIG_INCLUDE_BCM56780 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56780_Ax BCMDRD_CONFIG_INCLUDE_BCM56780 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_BCM56780_Ax +#endif + + +/* + * BCM56782 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56782 +#define BCMDRD_CONFIG_INCLUDE_BCM56782 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56782_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56782_Ax BCMDRD_CONFIG_INCLUDE_BCM56782 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56782_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56782_A0 BCMDRD_CONFIG_INCLUDE_BCM56782_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56782_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56784 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56784 +#define BCMDRD_CONFIG_INCLUDE_BCM56784 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56784_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56784_Ax BCMDRD_CONFIG_INCLUDE_BCM56784 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56784_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56784_A0 BCMDRD_CONFIG_INCLUDE_BCM56784_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56784_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56786 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56786 +#define BCMDRD_CONFIG_INCLUDE_BCM56786 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56786_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56786_Ax BCMDRD_CONFIG_INCLUDE_BCM56786 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56786_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56786_A0 BCMDRD_CONFIG_INCLUDE_BCM56786_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56786_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56788 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56788 +#define BCMDRD_CONFIG_INCLUDE_BCM56788 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56788_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56788_Ax BCMDRD_CONFIG_INCLUDE_BCM56788 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56788_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56788_A0 BCMDRD_CONFIG_INCLUDE_BCM56788_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56788_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56789 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56789 +#define BCMDRD_CONFIG_INCLUDE_BCM56789 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56789_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56789_Ax BCMDRD_CONFIG_INCLUDE_BCM56789 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56789_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56789_A0 BCMDRD_CONFIG_INCLUDE_BCM56789_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56789_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56880 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880 +#define BCMDRD_CONFIG_INCLUDE_BCM56880 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56880_Ax BCMDRD_CONFIG_INCLUDE_BCM56880 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_BCM56880_Ax +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56880_Bx BCMDRD_CONFIG_INCLUDE_BCM56880 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_B0 BCMDRD_CONFIG_INCLUDE_BCM56880_Bx +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56880_B0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56881 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881 +#define BCMDRD_CONFIG_INCLUDE_BCM56881 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56881_Ax BCMDRD_CONFIG_INCLUDE_BCM56881 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56881_A0 BCMDRD_CONFIG_INCLUDE_BCM56881_Ax +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56881_Bx BCMDRD_CONFIG_INCLUDE_BCM56881 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56881_B0 BCMDRD_CONFIG_INCLUDE_BCM56881_Bx +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56881_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56881_B0 == 1 +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56883 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883 +#define BCMDRD_CONFIG_INCLUDE_BCM56883 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56883_Ax BCMDRD_CONFIG_INCLUDE_BCM56883 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56883_A0 BCMDRD_CONFIG_INCLUDE_BCM56883_Ax +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56883_Bx BCMDRD_CONFIG_INCLUDE_BCM56883 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56883_B0 BCMDRD_CONFIG_INCLUDE_BCM56883_Bx +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56883_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56883_B0 == 1 +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56889 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889 +#define BCMDRD_CONFIG_INCLUDE_BCM56889 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56889_Ax BCMDRD_CONFIG_INCLUDE_BCM56889 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56889_A0 BCMDRD_CONFIG_INCLUDE_BCM56889_Ax +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56889_Bx BCMDRD_CONFIG_INCLUDE_BCM56889 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56889_B0 BCMDRD_CONFIG_INCLUDE_BCM56889_Bx +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56889_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56889_B0 == 1 +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56990 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990 +#define BCMDRD_CONFIG_INCLUDE_BCM56990 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56990_Ax BCMDRD_CONFIG_INCLUDE_BCM56990 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56990_A0 BCMDRD_CONFIG_INCLUDE_BCM56990_Ax +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56990_Bx BCMDRD_CONFIG_INCLUDE_BCM56990 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0 BCMDRD_CONFIG_INCLUDE_BCM56990_Bx +#endif + + +/* + * BCM56992 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56992 +#define BCMDRD_CONFIG_INCLUDE_BCM56992 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56992_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56992_Bx BCMDRD_CONFIG_INCLUDE_BCM56992 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56992_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56992_B0 BCMDRD_CONFIG_INCLUDE_BCM56992_Bx +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56992_B0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56990_B0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56990_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56996 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996 +#define BCMDRD_CONFIG_INCLUDE_BCM56996 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56996_Ax BCMDRD_CONFIG_INCLUDE_BCM56996 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0 BCMDRD_CONFIG_INCLUDE_BCM56996_Ax +#endif + + +/* + * BCM56997 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56997 +#define BCMDRD_CONFIG_INCLUDE_BCM56997 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56997_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56997_Ax BCMDRD_CONFIG_INCLUDE_BCM56997 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56997_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56997_A0 BCMDRD_CONFIG_INCLUDE_BCM56997_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56997_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56996_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56996_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0_IMPLIED 1 +#endif +#endif + + +#endif /* BCMDRD_CONFIG_CHIPS_H */ + +/* + * CONFIG_OPTION Macros. Can be used to determine the build configuration. + */ + +#ifdef CONFIG_OPTION +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780_A0) +#ifdef BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED) +#endif +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56782) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56782_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56782_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56784) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56784_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56784_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56786) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56786_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56786_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56788) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56788_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56788_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56789) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56789_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56789_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_B0) +#ifdef BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED) +#endif +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_B0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_B0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_B0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_B0) +#ifdef BCMDRD_CONFIG_INCLUDE_BCM56990_A0_IMPLIED +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_A0_IMPLIED) +#endif +#ifdef BCMDRD_CONFIG_INCLUDE_BCM56990_B0_IMPLIED +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_B0_IMPLIED) +#endif +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56992) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56992_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56992_B0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996_A0) +#ifdef BCMDRD_CONFIG_INCLUDE_BCM56996_A0_IMPLIED +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996_A0_IMPLIED) +#endif +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56997) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56997_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56997_A0) +#undef CONFIG_OPTION +#endif /* #ifdef CONFIG_OPTION */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/Kbuild b/platform/broadcom/saibcm-modules/sdklt/linux/bde/Kbuild new file mode 100644 index 000000000000..76581c02eed2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/Kbuild @@ -0,0 +1,39 @@ +# -*- Kbuild -*- +# +# Linux kernel BDE module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# 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. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +obj-m := linux_ngbde.o + +ccflags-y := $(LKM_CFLAGS) \ + -I$(SDK)/linux/include \ + -I$(SDK)/linux/bde \ + -I$(SDK)/bcmdrd/include + +linux_ngbde-y := ngbde_main.o \ + ngbde_kapi.o \ + ngbde_ioctl.o \ + ngbde_procfs.o \ + ngbde_pio.o \ + ngbde_iio.o \ + ngbde_dma.o \ + ngbde_intr.o \ + ngbde_pgmem.o \ + ngbde_pci_probe.o \ + ngbde_iproc_probe.o \ + ngbde_swdev.o diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/Makefile b/platform/broadcom/saibcm-modules/sdklt/linux/bde/Makefile new file mode 100644 index 000000000000..590f4132306f --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/Makefile @@ -0,0 +1,33 @@ +# -*- Makefile -*- +# +# Linux kernel BDE module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# 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. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +include Kbuild + +ifeq ($(KERNELRELEASE),) + +MOD_NAME = linux_ngbde + +include $(SDK)/make/lkm.mk + +endif + +.PHONY: distclean + +distclean: diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde.h b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde.h new file mode 100644 index 000000000000..56e925f7098d --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde.h @@ -0,0 +1,836 @@ +/*! \file ngbde.h + * + * Shared definitions and APIs for NGBDE kernel module. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGBDE_H +#define NGBDE_H + +#include +#include + +/*! Module name. */ +#define MOD_NAME "linux_ngbde" + +/*! Major number for associated charcter device file. */ +#define MOD_MAJOR 120 + +/*! Read memory-mapped device register without byte-swap. */ +#define NGBDE_IOREAD32(_a) __raw_readl(_a) + +/*! Write memory-mapped device register without byte-swap. */ +#define NGBDE_IOWRITE32(_v, _a) __raw_writel(_v, _a) + +/*! Maximum number of I/O windows supported per device. */ +#define NGBDE_NUM_IOWIN_MAX 3 + +/*! Maximum number of DMA memory pools supported per device. */ +#define NGBDE_NUM_DMAPOOL_MAX 2 + +/*! Maximum number of IRQ status registers per interrupt source. */ +#define NGBDE_NUM_IRQ_REGS_MAX 16 + +/*! Maximum number of IRQ lines (MSI vectors) per device. */ +#define NGBDE_NUM_IRQS_MAX 1 + +/*! + * Maximum number of interrupt controller registers which may be + * written from both a user mode driver and a kernel mode driver. + * + * This feature is used when the kernel mode driver owns a subset of + * bits within a register, which is also used by the user mode driver. + * + * Both drivers must access such registers through a lock-protected + * access function. + */ +#define NGBDE_NUM_INTR_SHR_REGS_MAX 1 + +/*! I/O memory window definition. */ +struct ngbde_memwin_s { + + /*! Physical address of I/O window. */ + phys_addr_t addr; + + /*! Size of I/O window (in bytes). */ + phys_addr_t size; +}; + +/*! + * \brief Shared register value. + * + * This structure contains the current value of a register where user + * mode and kernel mode owns different bits within the same + * register. In this case access must be carefully controlled to avoid + * that one context overwrites the bits owned by the other context. + * + * The structure also contains the offset of the shared register in + * order to identify the register (in case there is more than one + * shared register). + */ +typedef struct ngbde_shr_reg_s { + + /*! Offset of the shared register. */ + uint32_t reg_offs; + + /*! Current value of the shared register. */ + uint32_t cur_val; + +} ngbde_shr_reg_t; + +/*! + * \brief Shared interrupt mask register control. + * + * This defines which bits of an interrupt mask register are owned by + * user mode context, and which are owned by kernel context. + * + * The structure contains the corresponding interrupt status register + * in order to allow identification of the interrupt mask register + * irrespective of the host CPU being used. + * + * For example, if the host CPU is connected via PCI, then we use one + * mask register, but if the host CPU is an embedded ARM CPU, then we + * use a different mask register (for the same interrupt status + * register). By using the status register to identify the shared mask + * register, the kernel mode driver does not need to know which host + * CPU it is running off. + */ +typedef struct ngbde_irq_reg_s { + + /*! Interrupt status register corresponding to the mask register. */ + uint32_t status_reg; + + /*! Shared interrupt mask register. */ + uint32_t mask_reg; + + /*! Mask identifying the register bits owned by the kernel mode driver. */ + uint32_t kmask; + +} ngbde_irq_reg_t; + +/*! + * \name Interrupt ACK register access flags. + * \anchor NGBDE_INTR_ACK_F_xxx + */ + +/*! \{ */ + +/*! ACK registers resides in PCI bridge I/O window. */ +#define NGBDE_INTR_ACK_F_PAXB (1 << 0) + +/*! \} */ + +/*! + * \brief Interrupt ACK register control. + * + * The structure contains the corresponding register offset + * and value in order to acknowledge interrupt in kernel driver. + * + * For example, if the host CPU is connected via PCI, then we use one + * ACK register, but if the host CPU is an embedded ARM CPU, then we + * use a different ACK register. + */ +typedef struct ngbde_intr_ack_reg_s { + + /*! Ack register offset. */ + uint32_t ack_reg; + + /*! Ack value. */ + uint32_t ack_val; + + /*! Flags to indicate ack_reg resides in PCI bridge window. */ + uint32_t flags; + +} ngbde_intr_ack_reg_t; + +/*! + * \brief BDE interrupt handler. + * + * The BDE will use a function of this type to register an interrupt + * handler with the Linux kernel. + * + * \param [in] data Interrupt handler context. + * + * \retval 0 Interrupt not recognized. + * \retval 1 Interrupt recognized and handled. + */ +typedef int (*ngbde_isr_f)(void *data); + +/*! + * \brief Kernel interrupt control. + * + * This structure controls the sharing of interrupt processing between + * a user mode thread and a kernel mode interrupt handler. + */ +typedef struct ngbde_intr_ctrl_s { + + /*! Handle for device I/O (for writing interrupt registers). */ + uint8_t *iomem; + + /*! Kernel device number (similar to user mode unit number). */ + int kdev; + + /*! Indicates that our interrupt handler is connected to the kernel. */ + int irq_active; + + /*! Interrupt number (IRQ# or MSI vector). */ + int irq_vect; + + /*! Number of interrupt status/mask register pairs. */ + int num_regs; + + /*! Interrupt status/mask register pairs for this device. */ + ngbde_irq_reg_t regs[NGBDE_NUM_IRQ_REGS_MAX]; + + /*! Interrupt ACK register/value for this device. */ + ngbde_intr_ack_reg_t intr_ack; + + /*! Wait queue for user mode interrupt thread. */ + wait_queue_head_t user_thread_wq; + + /*! Flag to wake up user mode interrupt thread. */ + atomic_t run_user_thread; + + /*! Primary interrupt handler. */ + ngbde_isr_f isr_func; + + /*! Context for primary interrupt handler. */ + void *isr_data; + +} ngbde_intr_ctrl_t; + +/*! Convenience macro for 1 kilobyte. */ +#define ONE_KB 1024 + +/*! Convenience macro for 1 megabyte. */ +#define ONE_MB (1024*1024) + +/*! + * \name DMA allocation types. + * \anchor NGBDE_DMA_T_xxx + */ + +/*! \{ */ + +/*! + * Do not allocate any DMA memory. + */ +#define NGBDE_DMA_T_NONE 0 + +/*! + * Try different allocation methods until DMA memory is successfully + * allocated. + */ +#define NGBDE_DMA_T_AUTO 1 + +/*! Use kernel DMA API (dma_alloc_coherent). */ +#define NGBDE_DMA_T_KAPI 2 + +/*! Use page allocator and map to physical address manually. */ +#define NGBDE_DMA_T_PGMEM 3 + +/*! \} */ + +/*! DMA memory allocation control structure. */ +typedef struct ngbde_dmactrl_s { + + /*! Requested size of DMA memory block (in bytes). */ + size_t size; + + /*! Kernel flags for memory allocation. */ + gfp_t flags; + + /*! Preferred DMA memory type (NGBDE_DMA_T_xxx). */ + int pref_type; + + /*! Kernel device for DMA memory management. */ + struct device *dev; + +} ngbde_dmactrl_t; + +/*! DMA memory descriptor. */ +typedef struct ngbde_dmamem_s { + + /*! Logical address of DMA memory block. */ + void *vaddr; + + /*! Physical address of DMA memory block. */ + dma_addr_t paddr; + + /*! Bus address of DMA memory block. */ + dma_addr_t baddr; + + /*! Actual size of DMA memory block (in bytes). */ + size_t size; + + /*! Actual DMA memory type (NGBDE_DMA_T_xxx). */ + int type; + + /*! Kernel device for DMA memory management. */ + struct device *dev; + +} ngbde_dmamem_t; + +/*! DMA memory pool. */ +typedef struct ngbde_dmapool_s { + + /*! DMA control parameters. */ + struct ngbde_dmactrl_s dmactrl; + + /*! DMA memory resources. */ + struct ngbde_dmamem_s dmamem; + +} ngbde_dmapool_t; + +/*! Switch device descriptor. */ +struct ngbde_dev_s { + + /*! Vendor ID (typically PCI vendor ID). */ + uint16_t vendor_id; + + /*! Device ID (typically PCI device ID). */ + uint16_t device_id; + + /*! Device revision (typically PCI revision). */ + uint16_t revision; + + /*! Additional device identification when primary ID is not unique. */ + uint16_t model; + + /*! Bus number (typically PCI bus number). */ + int bus_no; + + /*! Slot number (typically PCI slot number). */ + int slot_no; + + /*! Interrupt line associated with this device. */ + int irq_line; + + /*! Use MSI interrupts with this device. */ + int use_msi; + + /*! Non-zero if device was removed. */ + int inactive; + + /*! Physical I/O window for kernel driver device access. */ + struct ngbde_memwin_s pio_win; + + /*! Memory mapped I/O window for kernel driver device access. */ + uint8_t *pio_mem; + + /*! Physical I/O window for interrupt controller access. */ + struct ngbde_memwin_s iio_win; + + /*! Memory mapped I/O window for interrupt controller access. */ + uint8_t *iio_mem; + + /*! Physical I/O window for device PCI bridge access. */ + struct ngbde_memwin_s paxb_win; + + /*! Memory mapped I/O window for device PCI bridge access. */ + uint8_t *paxb_mem; + + /*! Current value of shared register (typically an IRQ mask register). */ + struct ngbde_shr_reg_s intr_shr_reg[NGBDE_NUM_INTR_SHR_REGS_MAX]; + + /*! Lock for shared register synchronization. */ + spinlock_t lock; + + /*! Interrupt control information. */ + struct ngbde_intr_ctrl_s intr_ctrl[NGBDE_NUM_IRQS_MAX]; + + /*! Linux PCI handle. */ + struct pci_dev *pci_dev; + + /*! Kernel device for DMA memory management. */ + struct device *dma_dev; + + /*! Physical device I/O. */ + struct ngbde_memwin_s iowin[NGBDE_NUM_IOWIN_MAX]; + + /*! DMA memory pools. */ + struct ngbde_dmapool_s dmapool[NGBDE_NUM_DMAPOOL_MAX]; +}; + +/*! + * \brief Linux IOCTL handler. + * + * This function handles communication between user mode and kernel + * mode. + * + * \param [in] file Device file handle. + * \param [in] cmd IOCTL command. + * \param [in] arg IOCTL command argument. + * + * \retval 0 No errors + */ +extern long +ngbde_ioctl(struct file *file, unsigned int cmd, unsigned long arg); + +/*! + * \brief Initialize procfs for BDE driver. + * + * Create procfs read interface for dumping probe information. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_procfs_init(void); + +/*! + * \brief Clean up procfs for BDE driver. + * + * Clean up resources allocated by \ref ngbde_procfs_init. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_procfs_cleanup(void); + +/*! + * \brief Allocate DMA memory pools for all probed devices. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_dma_init(void); + +/*! + * \brief Free DMA memory pools for all probed devices. + * + * \return Nothing. + */ +extern void +ngbde_dma_cleanup(void); + +/*! + * \brief Connect to hardware interrupt handler. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_connect(int kdev, unsigned int irq_num); + +/*! + * \brief Disconnect from hardware interrupt handler. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_disconnect(int kdev, unsigned int irq_num); + +/*! + * \brief Disconnect from all hardware interrupt handlers. + */ +void +ngbde_intr_cleanup(void); + +/*! + * \brief Wait for hardware interrupt. + * + * A user mode thread will call this function and sleep until a + * hardware interrupt occurs. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_wait(int kdev, unsigned int irq_num); + +/*! + * \brief Wake up sleeping interrupt thread. + * + * Wake up interrupt thread even if no interrupt has occurred. + * + * Intended for graceful shut-down procedure. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_stop(int kdev, unsigned int irq_num); + +/*! + * \brief Clear list of interrupt status/mask registers. + * + * This function is typically called before new interrupt register + * information is added. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_regs_clr(int kdev, unsigned int irq_num); + +/*! + * \brief Add interrupt status/mask register to monitor. + * + * This function adds a new interrupt status/mask register set to the + * list of registers monitored by the user-mode interrupt handler. + * + * The register list is used to determine whether a user-mode + * interrupt has occurred. + * + * See also \ref ngbde_intr_regs_clr. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * \param [in] ireg Interrupt status/mask register information. + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_reg_add(int kdev, unsigned int irq_num, + struct ngbde_irq_reg_s *ireg); + +/*! + * \brief Add interrupt ack register to monitor. + * + * This function adds a interrupt register and mask value + * to acknowledge corresponding irq_num. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * \param [in] ackreg Interrupt ack register information. + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_ack_reg_add(int kdev, unsigned int irq_num, + struct ngbde_intr_ack_reg_s *ackreg); + +/*! + * \brief Write shared interrupt mask register. + * + * This function is used by an interrupt handler when a shared + * interrupt mask register needs to be updated. + * + * Since the register is shared between multiple interrupt handlers, + * access must be protected by a lock. + * + * The register information provided via \ref ngbde_intr_reg_add is + * used to detemine which bits of the mask register belong to the user + * mode driver. + * + * Note that the mask register to access is referenced by the + * corresponding status register. This is because the mask register + * may be different depending on the host CPU interface being used + * (e.g. PCI vs. AXI). On the other hand, the status register is the + * same irrespective of the host CPU interface. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * \param [in] kapi Must be set to 1 if called from kernel API. + * \param [in] status_reg Corresponding interrupt status register offset. + * \param [in] mask_val New value to write to mask register. + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_mask_write(int kdev, unsigned int irq_num, int kapi, + uint32_t status_reg, uint32_t mask_val); + +/*! + * \brief Probe for PCI-attached Broadcom switch devices. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_pci_probe(void); + +/*! + * \brief Clean up resources for PCI-attached Broadcom switch devices. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_pci_cleanup(void); + +/*! + * \brief Add new switch device to BDE database. + * + * Add device information for probed or fixed switch device. + * + * \param [in] nd Switch device information. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_swdev_add(struct ngbde_dev_s *nd); + +/*! + * \brief Get device information for a BDE switch device. + * + * \param [in] kdev Switch device number. + * + * \return Pointer to switch device structure or NULL on error. + */ +struct ngbde_dev_s * +ngbde_swdev_get(int kdev); + +/*! + * \brief Get list of all probed switch devices. + * + * Return a pointer to the array of registered switch devices. + * + * \param [out] nd Pointer to array of switch devices. + * \param [in] num_nd number of valid entries in switch device array. + * + * \retval 0 No errors + */ +extern int +ngbde_swdev_get_all(struct ngbde_dev_s **nd, unsigned int *num_nd); + +/*! + * \brief Allocate memory using page allocator + * + * For any sizes less than MEM_CHUNK_SIZE, we ask the page allocator + * for the entire memory block, otherwise we try to assemble a + * contiguous cmblock ourselves. + * + * Upon successful allocation, the memory block will be added to the + * global list of allocated memory blocks. + * + * \param [in] size Number of bytes to allocate. + * \param [in] flags Kernel flags (GFP_xxx) for memory allocation. + * + * \return Pointer to allocated memory or NULL if failure. + */ +void * +ngbde_pgmem_alloc(size_t size, gfp_t flags); + +/*! + * \brief Free memory block allocated by ngbde_pgmem_alloc. + * + * \param [in] ptr Pointer returned by ngbde_pgmem_alloc. + * + * \return 0 if succesfully freed, otherwise -1. + */ +extern int +ngbde_pgmem_free(void *ptr); + +/*! + * \brief Free all memory blocks allocated by ngbde_pgmem_alloc. + * + * This function will walk the global list of allocated memory blocks + * and free all associated resources. + * + * Intended for a full clean up before the module is unloaded. + * + * \return Nothing. + */ +extern void +ngbde_pgmem_free_all(void); + +/*! + * \brief Map I/O memory in kernel driver. + * + * This function is used to provide device I/O access to a kernel mode + * driver. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] addr Physical address to map. + * \param [in] size Size of I/O window to map. + * + * \return Pointer to mapped I/O memory, or NULL on error. + */ +extern void * +ngbde_pio_map(void *devh, phys_addr_t addr, phys_addr_t size); + +/*! + * \brief Unmap I/O memory in kernel driver. + * + * Unmap I/O memory previously mapped via \ref ngbde_pio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * + * \return Nothing. + */ +extern void +ngbde_pio_unmap(void *devh); + +/*! + * \brief Unmap all I/O windows. + */ +extern void +ngbde_pio_cleanup(void); + +/*! + * \brief Write a memory-mapped register from kernel driver. + * + * Write a 32-bit register using I/O memory previously mapped via \ref + * ngbde_pio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] offs Register address offset. + * \param [in] val Value to write to register. + * + * \return Nothing. + */ +extern void +ngbde_pio_write32(void *devh, uint32_t offs, uint32_t val); + +/*! + * \brief Read a memory-mapped register from kernel driver. + * + * Read a 32-bit register using I/O memory previously mapped via \ref + * ngbde_pio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] offs Register address offset. + * + * \return Value read from register. + */ +extern uint32_t +ngbde_pio_read32(void *devh, uint32_t offs); + +/*! + * \brief Map interrupt controller I/O memory. + * + * On some devices the interrupt controller is a device separate from + * the main switch device. This function is used to provide interrupt + * controller I/O access to a kernel mode driver. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] addr Physical address to map. + * \param [in] size Size of I/O window to map. + * + * \return Pointer to mapped I/O memory, or NULL on error. + */ +extern void * +ngbde_iio_map(void *devh, phys_addr_t addr, phys_addr_t size); + +/*! + * \brief Unmap interrupt controller I/O memory. + * + * Unmap I/O memory previously mapped via \ref ngbde_iio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * + * \return Nothing. + */ +extern void +ngbde_iio_unmap(void *devh); + +/*! + * \brief Unmap all interrupt controller I/O windows. + */ +extern void +ngbde_iio_cleanup(void); + +/*! + * \brief Write a memory-mapped interrupt controller register. + * + * Write a 32-bit register using I/O memory previously mapped via \ref + * ngbde_iio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] offs Register address offset. + * \param [in] val Value to write to register. + * + * \return Nothing. + */ +extern void +ngbde_iio_write32(void *devh, uint32_t offs, uint32_t val); + +/*! + * \brief Read a memory-mapped interrupt controller register. + * + * Read a 32-bit register using I/O memory previously mapped via \ref + * ngbde_iio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] offs Register address offset. + * + * \return Value read from register. + */ +extern uint32_t +ngbde_iio_read32(void *devh, uint32_t offs); + +/*! + * \brief Map PCI bridge I/O memory. + * + * On some devices the interrupt controller is a device separate from + * the main switch device. This function is used to provide interrupt + * controller I/O access to a kernel mode driver. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] addr Physical address to map. + * \param [in] size Size of I/O window to map. + * + * \return Pointer to mapped I/O memory, or NULL on error. + */ +extern void * +ngbde_paxb_map(void *devh, phys_addr_t addr, phys_addr_t size); + +/*! + * \brief Unmap PCI bridge I/O memory. + * + * Unmap I/O memory previously mapped via \ref ngbde_paxb_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * + * \return Nothing. + */ +extern void +ngbde_paxb_unmap(void *devh); + +/*! + * \brief Unmap all PCI bridge I/O windows. + */ +extern void +ngbde_paxb_cleanup(void); + +/*! + * \brief Probe for Broadcom switch devices on IPROC internal bus. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_iproc_probe(void); + +/*! + * \brief Clean up resources for Broadcom switch devices on IPROC internal bus. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_iproc_cleanup(void); + +#endif /* NGBDE_H */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_dma.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_dma.c new file mode 100644 index 000000000000..9cc2b191f48c --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_dma.c @@ -0,0 +1,340 @@ +/*! \file ngbde_dma.c + * + * This module handles allocation of DMA memory pools. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +/*! \cond */ +static int dma_debug = 0; +module_param(dma_debug, int, 0); +MODULE_PARM_DESC(dma_debug, +"DMA debug output enable (default 0)."); +/*! \endcond */ + +/*! Default size of of DMA memory pools (in MB). */ +#define DMAPOOL_SIZE_DEFAULT 16 + +/*! Default number of DMA memory pools per device. */ +#define NUM_DMAPOOL_DEFAULT 1 + +/*! \cond */ +static int dma_size = DMAPOOL_SIZE_DEFAULT; +module_param(dma_size, int, 0); +MODULE_PARM_DESC(dma_size, +"Size of of DMA memory pools in MB (default 16 MB)."); +/*! \endcond */ + +/*! \cond */ +static char *dma_alloc; +module_param(dma_alloc, charp, 0); +MODULE_PARM_DESC(dma_alloc, +"DMA allocation method auto|kapi|pgmem (default auto)"); +/*! \endcond */ + +/*! \cond */ +static int dma_pools = NUM_DMAPOOL_DEFAULT; +module_param(dma_pools, int, 0); +MODULE_PARM_DESC(dma_pools, +"Number of DMA memory pools to pre-allocate per device (default 1)."); +/*! \endcond */ + +/*! + * \brief Allocate DMA memory via kernel API. + * + * \param [in] dmactrl DMA allocation control. + * \param [out] dmamem DMA allocation result. + * + * \return Nothing. + */ +static void +ngbde_dmamem_kapi_alloc(ngbde_dmactrl_t *dmactrl, ngbde_dmamem_t *dmamem) +{ + void *vaddr; + dma_addr_t baddr; + + vaddr = dma_alloc_coherent(dmactrl->dev, dmactrl->size, &baddr, + dmactrl->flags); + if (vaddr) { + /* Store allocation information in dmamem structure */ + dmamem->vaddr = vaddr; + dmamem->paddr = virt_to_phys(vaddr); + dmamem->dev = dmactrl->dev; + dmamem->size = dmactrl->size; + dmamem->type = NGBDE_DMA_T_KAPI; + dmamem->baddr = baddr; + + /* Write small signature for debug purposes */ + strcpy((char *)vaddr, "DMA_KAPI"); + + if (dma_debug) { + printk("DMA: Allocated %d KB of KAPI memory at 0x%08lx\n", + (int)(dmamem->size / ONE_KB), + (unsigned long)dmamem->paddr); + } + } else { + if (dma_debug) { + printk("DMA: Failed to allocate KAPI memory\n"); + } + } +} + +/*! + * \brief Allocate DMA memory via page allocator. + * + * \param [in] dmactrl DMA allocation control. + * \param [out] dmamem DMA allocation result. + * + * \return Nothing. + */ +static void +ngbde_dmamem_pgmem_alloc(ngbde_dmactrl_t *dmactrl, ngbde_dmamem_t *dmamem) +{ + void *vaddr; + + vaddr = ngbde_pgmem_alloc(dmactrl->size, dmactrl->flags); + if (vaddr) { + /* Store allocation information in dmamem structure */ + dmamem->vaddr = vaddr; + dmamem->paddr = virt_to_phys(vaddr); + dmamem->dev = dmactrl->dev; + dmamem->size = dmactrl->size; + dmamem->type = NGBDE_DMA_T_PGMEM; + dmamem->baddr = dma_map_single(dmamem->dev, dmamem->vaddr, + dmamem->size, DMA_BIDIRECTIONAL); + if (dma_mapping_error(dmactrl->dev, dmamem->baddr)) { + dmamem->baddr = 0; + if (dma_debug) { + printk("DMA: Failed to map PGMEM memory\n"); + } + } + + /* Write small signature for debug purposes */ + strcpy((char *)vaddr, "DMA_PGMEM"); + + if (dma_debug) { + printk("DMA: Allocated %d KB of PGMEM memory at 0x%08lx\n", + (int)(dmamem->size / ONE_KB), + (unsigned long)dmamem->paddr); + } + } else { + if (dma_debug) { + printk("DMA: Failed to allocate PGMEM memory\n"); + } + } +} + +/*! + * \brief Allocate DMA memory. + * + * Depending on the DMA allocation control parameters, we select one + * of several DMA memory allocation methods. + * + * \param [in] dmactrl DMA allocation control. + * \param [out] dmamem DMA allocation result. + * + * \return Nothing. + */ +static int +ngbde_dmamem_alloc(ngbde_dmactrl_t *dmactrl, ngbde_dmamem_t *dmamem) +{ + int kapi = 0; + + if (dmamem->vaddr) { + /* Already allocated */ + return 0; + } + +#ifdef CONFIG_CMA + /* Always allow KAPI when CMA is available */ + kapi = 1; +#else + if (dmactrl->size <= (1 << (MAX_ORDER - 1 + PAGE_SHIFT))) { + kapi = 1; + } +#endif + + /* Allocation via kernel DMA API (if allowed) */ + if (kapi) { + switch (dmactrl->pref_type) { + case NGBDE_DMA_T_AUTO: + case NGBDE_DMA_T_KAPI: + ngbde_dmamem_kapi_alloc(dmactrl, dmamem); + break; + default: + break; + } + } + + /* Allocation via private page allocator */ + if (dmamem->vaddr == NULL) { + switch (dmactrl->pref_type) { + case NGBDE_DMA_T_AUTO: + case NGBDE_DMA_T_PGMEM: + ngbde_dmamem_pgmem_alloc(dmactrl, dmamem); + break; + default: + break; + } + } + + if (dmamem->vaddr == NULL) { + printk(KERN_WARNING "%s: Failed to allocate DMA memory\n", + MOD_NAME); + return -1; + } + + return 0; +} + +/*! + * \brief Free DMA memory. + * + * Free DMA memory allocated via \ref ngbde_dmamem_alloc. + * + * \param [in] dmamem DMA allocation result from \ref ngbde_dmamem_alloc. + * + * \return Nothing. + */ +static int +ngbde_dmamem_free(ngbde_dmamem_t *dmamem) +{ + switch (dmamem->type) { + case NGBDE_DMA_T_KAPI: + if (dma_debug) { + printk("DMA: Freeing %d KB of KAPI memory\n", + (int)(dmamem->size / ONE_KB)); + } + dma_free_coherent(dmamem->dev, dmamem->size, + dmamem->vaddr, dmamem->paddr); + memset(dmamem, 0, sizeof(*dmamem)); + break; + case NGBDE_DMA_T_PGMEM: + if (dma_debug) { + printk("DMA: Freeing %d KB of PGMEM memory\n", + (int)(dmamem->size / ONE_KB)); + } + if (dmamem->baddr) { + if (dma_debug) { + printk("DMA: Unmapping PGMEM memory at 0x%08lx\n", + (unsigned long)dmamem->baddr); + } + dma_unmap_single(dmamem->dev, dmamem->baddr, + dmamem->size, DMA_BIDIRECTIONAL); + } + ngbde_pgmem_free(dmamem->vaddr); + memset(dmamem, 0, sizeof(*dmamem)); + break; + case NGBDE_DMA_T_NONE: + /* Nothing to free */ + break; + default: + printk(KERN_WARNING "%s: Unable to free unknown DMA memory type\n", + MOD_NAME); + break; + } + return 0; +} + +/*! + * \brief Free all DMA memory pools for all devices. + * + * \return Nothing. + */ +void +ngbde_dma_cleanup(void) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + unsigned int pool; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) { + if (swdev[idx].inactive) { + ngbde_dmamem_free(&swdev[idx].dmapool[pool].dmamem); + } + } + } +} + +/*! + * \brief Allocate DMA memory pools for all devices. + * + * \return Nothing. + */ +int +ngbde_dma_init(void) +{ + int rv; + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + int dma_type = NGBDE_DMA_T_AUTO; + struct ngbde_dmapool_s *dmapool; + unsigned int pool; + + /* Default DMA memory size per device */ + if (dma_size < 0) { + dma_size = DMAPOOL_SIZE_DEFAULT; + } + + /* Check for forced DMA allocation method */ + if (dma_alloc) { + if (strcmp(dma_alloc, "kapi") == 0) { + dma_type = NGBDE_DMA_T_KAPI; + } else if (strcmp(dma_alloc, "pgmem") == 0) { + dma_type = NGBDE_DMA_T_PGMEM; + } else { + printk(KERN_WARNING "%s: Unknown DMA type: %s\n", + MOD_NAME, dma_alloc); + } + } + + /* Number of DMA memory pools per device */ + if ((unsigned int)dma_pools >= NGBDE_NUM_DMAPOOL_MAX) { + dma_pools = NUM_DMAPOOL_DEFAULT; + } + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + + /* Set DMA allocation parameters */ + for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) { + dmapool = &swdev[idx].dmapool[pool]; + dmapool->dmactrl.dev = swdev[idx].dma_dev; + dmapool->dmactrl.size = dma_size * ONE_MB; + dmapool->dmactrl.pref_type = dma_type; + dmapool->dmactrl.flags = GFP_KERNEL | GFP_DMA32; + } + + /* Allocate DMA pools */ + for (pool = 0; pool < dma_pools; pool++) { + dmapool = &swdev[idx].dmapool[pool]; + rv = ngbde_dmamem_alloc(&dmapool->dmactrl, &dmapool->dmamem); + if (rv < 0) { + printk(KERN_WARNING "%s: Unable to allocate DMA pool %d %d\n", + MOD_NAME, idx, pool); + } + } + } + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iio.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iio.c new file mode 100644 index 000000000000..e97f1fcea730 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iio.c @@ -0,0 +1,143 @@ +/*! \file ngbde_iio.c + * + * API for managing and accessing memory-mapped I/O for interrupt + * controller registers. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +void * +ngbde_iio_map(void *devh, phys_addr_t addr, phys_addr_t size) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->iio_mem) { + if (addr == sd->iio_win.addr && size == sd->iio_win.size) { + /* Already mapped */ + return sd->iio_mem; + } + ngbde_iio_unmap(devh); + } + + sd->iio_mem = ioremap_nocache(addr, size); + + if (sd->iio_mem) { + /* Save mapped resources */ + sd->iio_win.addr = addr; + sd->iio_win.size = size; + } + + return sd->iio_mem; +} + +void +ngbde_iio_unmap(void *devh) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->iio_mem) { + iounmap(sd->iio_mem); + sd->iio_mem = NULL; + } +} + +void +ngbde_iio_cleanup(void) +{ + struct ngbde_dev_s *swdev, *sd; + unsigned int num_swdev, idx; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + sd = ngbde_swdev_get(idx); + ngbde_iio_unmap(sd); + } +} + +void +ngbde_iio_write32(void *devh, uint32_t offs, uint32_t val) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->iio_mem) { + NGBDE_IOWRITE32(val, sd->iio_mem + offs); + } +} + +uint32_t +ngbde_iio_read32(void *devh, uint32_t offs) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->iio_mem) { + return NGBDE_IOREAD32(sd->iio_mem + offs); + } + return 0; +} + +void * +ngbde_paxb_map(void *devh, phys_addr_t addr, phys_addr_t size) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->paxb_mem) { + if (addr == sd->paxb_win.addr && size == sd->paxb_win.size) { + /* Already mapped */ + return sd->paxb_mem; + } + iounmap(sd->paxb_mem); + } + + sd->paxb_mem = ioremap_nocache(addr, size); + + if (sd->paxb_mem) { + /* Save mapped resources */ + sd->paxb_win.addr = addr; + sd->paxb_win.size = size; + } + + return sd->paxb_mem; +} + +void +ngbde_paxb_unmap(void *devh) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->paxb_mem) { + iounmap(sd->paxb_mem); + sd->paxb_mem = NULL; + } +} + +void +ngbde_paxb_cleanup(void) +{ + struct ngbde_dev_s *swdev, *sd; + unsigned int num_swdev, idx; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + sd = ngbde_swdev_get(idx); + ngbde_paxb_unmap(sd); + } +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_intr.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_intr.c new file mode 100644 index 000000000000..acec7da100f7 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_intr.c @@ -0,0 +1,550 @@ +/*! \file ngbde_intr.c + * + * API for controlling a thread-based user-mode interrupt handler. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +/*! \cond */ +static int intr_debug = 0; +module_param(intr_debug, int, 0); +MODULE_PARM_DESC(intr_debug, +"Interrupt debug output enable (default 0)."); +/*! \endcond */ + +static int +ngbde_intr_shared_write32(struct ngbde_dev_s *sd, struct ngbde_intr_ctrl_s *ic, + uint32_t reg_offs, uint32_t reg_val, uint32_t shr_mask) +{ + unsigned long flags; + struct ngbde_shr_reg_s *sr; + int idx; + + sr = NULL; + for (idx = 0; idx < NGBDE_NUM_INTR_SHR_REGS_MAX; idx++) { + if (sd->intr_shr_reg[idx].reg_offs == 0) { + /* If not found, then we add a new entry */ + sd->intr_shr_reg[idx].reg_offs = reg_offs; + } + if (sd->intr_shr_reg[idx].reg_offs == reg_offs) { + sr = &sd->intr_shr_reg[idx]; + break; + } + } + + if (sr == NULL) { + return -1; + } + + spin_lock_irqsave(&sd->lock, flags); + + sr->cur_val &= ~shr_mask; + sr->cur_val |= (reg_val & shr_mask); + + NGBDE_IOWRITE32(sr->cur_val, ic->iomem + reg_offs); + + spin_unlock_irqrestore(&sd->lock, flags); + + return 0; +} + +/*! + * \brief Interrupt handler for user mode thread. + * + * This function will determine whether a user-mode interrupt has + * occurred by reading the configured interrupt status and mask + * registers. + * + * If an interrupt has occurred, any waiting user-mode thread is woken + * up. + * + * \param [in] ic Interrupt control information. + * + * \retval 1 One or more user mode interrupts occurred. + * \retval 0 No user mode interrupts occurred. + */ +static int +ngbde_user_isr(ngbde_intr_ctrl_t *ic) +{ + int idx; + int active_interrupts = 0; + uint32_t stat = 0, mask = 0; + uint32_t kmask; + + /* Check if any enabled interrupts are active */ + for (idx = 0; idx < ic->num_regs; idx++) { + ngbde_irq_reg_t *ir = &ic->regs[idx]; + + /* Get mask of all kernel interrupt sources for this register address */ + kmask = ir->kmask; + + stat = NGBDE_IOREAD32(&ic->iomem[ir->status_reg]); + mask = NGBDE_IOREAD32(&ic->iomem[ir->mask_reg]); + + if (stat & mask & ~kmask) { + active_interrupts = 1; + break; + } + } + + /* No active interrupts to service */ + if (!active_interrupts) { + return 0; + } + + /* Disable (mask off) all interrupts */ + for (idx = 0; idx < ic->num_regs; idx++) { + ngbde_irq_reg_t *ir = &ic->regs[idx]; + + /* Get mask of all kernel interrupt sources for this register address */ + kmask = ir->kmask; + + if (kmask == 0xffffffff) { + /* Kernel driver owns all interrupts in this register */ + continue; + } else if (kmask) { + /* Synchronized write */ + struct ngbde_dev_s *sd = ngbde_swdev_get(ic->kdev); + if (ngbde_intr_shared_write32(sd, ic, ir->mask_reg, 0, ~kmask) < 0) { + printk(KERN_WARNING + "%s: Failed to write shared register for device %d\n", + MOD_NAME, ic->kdev); + /* Fall back to normal write to ensure interrupts are masked */ + NGBDE_IOWRITE32(0, &ic->iomem[ir->mask_reg]); + } + } else { + NGBDE_IOWRITE32(0, &ic->iomem[ir->mask_reg]); + } + } + + atomic_set(&ic->run_user_thread, 1); + wake_up_interruptible(&ic->user_thread_wq); + + return 1; +} + +/*! + * \brief Interrupt handler for kernel driver. + * + * Typically used by the KNET driver. + * + * \param [in] ic Interrupt control information. + * + * \retval 1 One or more kernel mode interrupts occurred. + * \retval 0 No kernel mode interrupts occurred. + */ +static int +ngbde_kernel_isr(ngbde_intr_ctrl_t *ic) +{ + if (ic->isr_func) { + return ic->isr_func(ic->isr_data); + } + return 0; +} + +/*! + * \brief Acknowledge interrupt + * + * \param [in] data Interrupt control information + * + * \retval 0 + */ +static int +ngbde_intr_ack(ngbde_intr_ctrl_t *ic) +{ + struct ngbde_dev_s *sd = ngbde_swdev_get(ic->kdev); + struct ngbde_intr_ack_reg_s *ar = &ic->intr_ack; + + if (sd->use_msi) { + if (ar->flags & NGBDE_INTR_ACK_F_PAXB) { + NGBDE_IOWRITE32(ar->ack_val, &sd->paxb_mem[ar->ack_reg]); + } else { + NGBDE_IOWRITE32(ar->ack_val, &sd->pio_mem[ar->ack_reg]); + } + } + + return 0; +} + +/*! + * \brief Linux ISR + * + * Will call the user-mode interrupts handler and optionally also a + * kernel mode interrupt handler (typically KNET). + * + * \param [in] irq_num Interrupt vector from kernel. + * \param [in] data Interrupt control information + * + * \retval IRQ_NONE Interrupt not recognized. + * \retval IRQ_HANDLED Interrupt recognized and handled (masked off). + */ +static irqreturn_t +ngbde_isr(int irq_num, void *data) +{ + struct ngbde_intr_ctrl_s *ic = (struct ngbde_intr_ctrl_s *)data; + irqreturn_t rv = IRQ_NONE; + + ngbde_intr_ack(ic); + + if (ngbde_user_isr(ic)) { + rv = IRQ_HANDLED; + } + if (ngbde_kernel_isr(ic)) { + rv = IRQ_HANDLED; + } + return rv; +} + +int +ngbde_intr_connect(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + unsigned long irq_flags; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (ic->irq_active) { + return 0; + } + + if (sd->irq_line >= 0) { + if (sd->pio_mem == NULL) { + printk(KERN_WARNING "%s: No memory-mapped I/O for device %d\n", + MOD_NAME, kdev); + return -1; + } + ic->kdev = kdev; + ic->iomem = sd->pio_mem; + if (sd->iio_mem) { + if (intr_debug) { + printk("INTR: Using dedicated interrupt controller\n"); + } + ic->iomem = sd->iio_mem; + } + init_waitqueue_head(&ic->user_thread_wq); + atomic_set(&ic->run_user_thread, 0); + irq_flags = IRQF_SHARED; + ic->irq_vect = sd->irq_line; + + /* + * The pci_enable_msi function must be called after enabling + * BAR0_PAXB_OARR_FUNC0_MSI_PAGE, otherwise, MSI interrupts + * cannot be triggered! + */ + if (sd->use_msi) { + if (pci_enable_msi(sd->pci_dev) == 0) { + irq_flags = 0; + ic->irq_vect = sd->pci_dev->irq; + if (intr_debug) { + printk("INTR: Enabled MSI interrupts\n"); + } + } else { + printk(KERN_WARNING "%s: Failed to enable MSI for device %d\n", + MOD_NAME, kdev); + sd->use_msi = 0; + } + } + if (intr_debug) { + printk("INTR: Request IRQ %d\n", ic->irq_vect); + } + if (request_irq(ic->irq_vect, ngbde_isr, irq_flags, MOD_NAME, ic) < 0) { + printk(KERN_WARNING "%s: Could not get IRQ %d for device %d\n", + MOD_NAME, ic->irq_vect, kdev); + return -1; + } + ic->irq_active = 1; + } + + return 0; +} + +int +ngbde_intr_disconnect(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (!ic->irq_active) { + return 0; + } + + if (ic->isr_func) { + printk(KERN_WARNING "%s: Disconnecting IRQ %d blocked by kernel ISR\n", + MOD_NAME, irq_num); + return 0; + } + + if (ic->irq_vect >= 0) { + free_irq(ic->irq_vect, ic); + if (sd->use_msi) { + pci_disable_msi(sd->pci_dev); + } + ic->irq_active = 0; + } + + return 0; +} + +void +ngbde_intr_cleanup(void) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx, irq_num; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + for (irq_num = 0; irq_num < NGBDE_NUM_IRQS_MAX; irq_num++) { + ngbde_intr_disconnect(idx, irq_num); + } + } +} + +int +ngbde_intr_wait(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (!ic->irq_active) { + return 0; + } + + wait_event_interruptible(ic->user_thread_wq, + atomic_read(&ic->run_user_thread) != 0); + atomic_set(&ic->run_user_thread, 0); + + return 0; +} + +int +ngbde_intr_stop(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (!ic->irq_active) { + return 0; + } + + /* Wake up user thread */ + atomic_set(&ic->run_user_thread, 1); + wake_up_interruptible(&ic->user_thread_wq); + + return 0; +} + +int +ngbde_intr_regs_clr(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (ic->irq_active) { + /* Do not clear configuration with interrupt connected */ + return 0; + } + + ic->num_regs = 0; + memset(ic->regs, 0, sizeof(ic->regs)); + + return 0; +} + +int +ngbde_intr_reg_add(int kdev, unsigned int irq_num, + struct ngbde_irq_reg_s *ireg) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + struct ngbde_irq_reg_s *ir; + unsigned int idx; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (ic->irq_active) { + /* + * If the interrupt is connected, then we only update the + * kernel mask for existing entries. + */ + for (idx = 0; idx < ic->num_regs; idx++) { + ir = &ic->regs[idx]; + if (ir->status_reg == ireg->status_reg && + ir->mask_reg == ireg->mask_reg) { + ir->kmask = ireg->kmask; + if (intr_debug) { + printk("INTR: Updating interrupt register " + "0x%08x/0x%08x (0x%08x)\n", + ir->status_reg, ir->mask_reg, ir->kmask); + } + return 0; + } + } + return -1; + } + + if (ic->num_regs >= NGBDE_NUM_IRQ_REGS_MAX) { + return -1; + } + + ir = &ic->regs[ic->num_regs++]; + + memcpy(ir, ireg, sizeof (*ir)); + + if (intr_debug) { + printk("INTR: Adding interrupt register 0x%08x/0x%08x (0x%08x)\n", + ir->status_reg, ir->mask_reg, ir->kmask); + } + + return ic->num_regs; +} + +int +ngbde_intr_ack_reg_add(int kdev, unsigned int irq_num, + struct ngbde_intr_ack_reg_s *ackreg) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + struct ngbde_intr_ack_reg_s *ar; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (ic->irq_active) { + /* Ignore request if interrupt is connected */ + return 0; + } + + ar = &ic->intr_ack; + + memcpy(ar, ackreg, sizeof (*ar)); + + if (intr_debug) { + printk("INTR: Adding interrupt ACK register 0x%08x/0x%08x (0x%08x)\n", + ar->ack_reg, ar->ack_val, ar->flags); + } + + return 0; +} + +int +ngbde_intr_mask_write(int kdev, unsigned int irq_num, int kapi, + uint32_t status_reg, uint32_t mask_val) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + struct ngbde_irq_reg_s *ir; + unsigned int idx; + uint32_t bmask; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + ir = ic->regs; + for (idx = 0; idx < ic->num_regs; idx++) { + if (ir->status_reg == status_reg) { + bmask = kapi ? ir->kmask : ~ir->kmask; + ngbde_intr_shared_write32(sd, ic, ir->mask_reg, mask_val, bmask); + return 0; + } + ir++; + } + + return -1; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_ioctl.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_ioctl.c new file mode 100644 index 000000000000..ccd0b7ee01d0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_ioctl.c @@ -0,0 +1,237 @@ +/*! \file ngbde_ioctl.c + * + * NGBDE IOCTL interface. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +#include + +long +ngbde_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct ngbde_ioc_cmd_s ioc; + struct ngbde_dev_s *swdev; + struct ngbde_irq_reg_s ireg; + struct ngbde_intr_ack_reg_s ackreg; + phys_addr_t addr, size; + unsigned int num_swdev; + unsigned int rsrc_type, rsrc_idx; + unsigned int irq_num, intr_cmd; + uint32_t mreg, mval; + + if (copy_from_user(&ioc, (void *)arg, sizeof(ioc))) { + return -EFAULT; + } + + ioc.rc = NGBDE_IOC_SUCCESS; + + switch (cmd) { + case NGBDE_IOC_MOD_INFO: + ioc.op.mod_info.version = NGBDE_IOC_VERSION; + break; + case NGBDE_IOC_PROBE_INFO: + ngbde_swdev_get_all(NULL, &num_swdev); + ioc.op.probe_info.num_swdev = num_swdev; + break; + case NGBDE_IOC_DEV_INFO: + swdev = ngbde_swdev_get(ioc.devid); + if (!swdev) { + ioc.rc = NGBDE_IOC_FAIL; + break; + } + ioc.op.dev_info.vendor_id = swdev->vendor_id; + ioc.op.dev_info.device_id = swdev->device_id; + ioc.op.dev_info.revision = swdev->revision; + ioc.op.dev_info.model = swdev->model; + if (swdev->use_msi) { + ioc.op.dev_info.flags |= NGBDE_DEV_F_MSI; + } + break; + case NGBDE_IOC_PHYS_ADDR: + swdev = ngbde_swdev_get(ioc.devid); + if (!swdev) { + ioc.rc = NGBDE_IOC_FAIL; + break; + } + rsrc_type = ioc.op.rsrc_id.type; + rsrc_idx = ioc.op.rsrc_id.inst; + switch (rsrc_type) { + case NGBDE_IO_RSRC_DEV_IO: + if (rsrc_idx >= NGBDE_NUM_IOWIN_MAX) { + printk(KERN_WARNING + "ngbde: invalid resource index (%d)\n", + rsrc_idx); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + ioc.op.phys_addr.addr = swdev->iowin[rsrc_idx].addr; + ioc.op.phys_addr.size = swdev->iowin[rsrc_idx].size; + break; + case NGBDE_IO_RSRC_DMA_MEM: + if (rsrc_idx >= NGBDE_NUM_DMAPOOL_MAX) { + printk(KERN_WARNING + "ngbde: invalid resource index (%d)\n", + rsrc_idx); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + ioc.op.phys_addr.addr = swdev->dmapool[rsrc_idx].dmamem.paddr; + ioc.op.phys_addr.size = swdev->dmapool[rsrc_idx].dmactrl.size; + break; + case NGBDE_IO_RSRC_DMA_BUS: + if (rsrc_idx >= NGBDE_NUM_DMAPOOL_MAX) { + printk(KERN_WARNING + "ngbde: invalid resource index (%d)\n", + rsrc_idx); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + ioc.op.phys_addr.addr = swdev->dmapool[rsrc_idx].dmamem.baddr; + ioc.op.phys_addr.size = swdev->dmapool[rsrc_idx].dmactrl.size; + break; + default: + printk(KERN_WARNING + "ngbde: unknown resource type (%d)\n", + rsrc_type); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + break; + case NGBDE_IOC_INTR_CTRL: + irq_num = ioc.op.intr_ctrl.irq_num; + intr_cmd = ioc.op.intr_ctrl.cmd; + switch (intr_cmd) { + case NGBDE_ICTL_INTR_CONN: + if (ngbde_intr_connect(ioc.devid, irq_num) < 0) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_ICTL_INTR_DISC: + if (ngbde_intr_disconnect(ioc.devid, irq_num) < 0) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_ICTL_INTR_WAIT: + if (ngbde_intr_wait(ioc.devid, irq_num) < 0) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_ICTL_INTR_STOP: + if (ngbde_intr_stop(ioc.devid, irq_num) < 0) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_ICTL_REGS_CLR: + if (ngbde_intr_regs_clr(ioc.devid, irq_num) < 0) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + default: + printk(KERN_WARNING + "%s: unknown interrupt control command (%d)\n", + MOD_NAME, intr_cmd); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + break; + case NGBDE_IOC_IRQ_REG_ADD: + irq_num = ioc.op.irq_reg_add.irq_num; + ireg.status_reg = ioc.op.irq_reg_add.status_reg; + ireg.mask_reg = ioc.op.irq_reg_add.mask_reg; + ireg.kmask = ioc.op.irq_reg_add.kmask; + if (ngbde_intr_reg_add(ioc.devid, irq_num, &ireg) < 0) { + printk(KERN_WARNING + "%s: Unable to add interrupt register\n", + MOD_NAME); + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_IOC_INTR_ACK_REG_ADD: + irq_num = ioc.op.intr_ack_reg_add.irq_num; + ackreg.ack_reg = ioc.op.intr_ack_reg_add.ack_reg; + ackreg.ack_val = ioc.op.intr_ack_reg_add.ack_val; + ackreg.flags = ioc.op.intr_ack_reg_add.flags; + if (ngbde_intr_ack_reg_add(ioc.devid, irq_num, &ackreg) < 0) { + printk(KERN_WARNING + "%s: Unable to add interrupt ack register\n", + MOD_NAME); + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_IOC_IRQ_MASK_WR: + irq_num = ioc.op.irq_mask_wr.irq_num; + mreg = ioc.op.irq_mask_wr.offs; + mval = ioc.op.irq_mask_wr.val; + if (ngbde_intr_mask_write(ioc.devid, irq_num, 0, mreg, mval) < 0) { + printk(KERN_WARNING + "%s: Unable to write shared register\n", + MOD_NAME); + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_IOC_PIO_WIN_MAP: + swdev = ngbde_swdev_get(ioc.devid); + if (!swdev) { + ioc.rc = NGBDE_IOC_FAIL; + break; + } + addr = ioc.op.pio_win.addr; + size = ioc.op.pio_win.size; + if (ngbde_pio_map(swdev, addr, size) == NULL) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_IOC_IIO_WIN_MAP: + swdev = ngbde_swdev_get(ioc.devid); + if (!swdev) { + ioc.rc = NGBDE_IOC_FAIL; + break; + } + addr = ioc.op.pio_win.addr; + size = ioc.op.pio_win.size; + if (ngbde_iio_map(swdev, addr, size) == NULL) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_IOC_PAXB_WIN_MAP: + swdev = ngbde_swdev_get(ioc.devid); + if (!swdev) { + ioc.rc = NGBDE_IOC_FAIL; + break; + } + addr = ioc.op.pio_win.addr; + size = ioc.op.pio_win.size; + if (ngbde_paxb_map(swdev, addr, size) == NULL) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + default: + printk(KERN_ERR "ngbde: invalid ioctl (%08x)\n", cmd); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + + if (copy_to_user((void *)arg, &ioc, sizeof(ioc))) { + return -EFAULT; + } + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iproc_probe.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iproc_probe.c new file mode 100644 index 000000000000..63b02a4075a3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iproc_probe.c @@ -0,0 +1,164 @@ +/*! \file ngbde_iproc_probe.c + * + * BDE probe for IPROC internal bus devices. + * + * Validate CMICD existence on the platform. If Linux device tree matched, + * probe function of platform driver is called and the switch device read from + * CMICD register is added to the device list. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +/*! \cond */ +static int iproc_debug = 0; +module_param(iproc_debug, int, 0); +MODULE_PARM_DESC(iproc_debug, +"IPROC debug output enable (default 0)."); +/*! \endcond */ + +/*! + * \brief Probe devices on the IPROC internal bus. + * + * \param [in] pldev Platform device. + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +static int +iproc_cmicd_probe(struct platform_device *pldev) +{ + int rv; + uint32_t size; + void *base_address; + uint32_t dev_rev_id; + struct ngbde_dev_s ngbde_dev, *nd = &ngbde_dev; + struct resource *memres, *irqres; + + memres = platform_get_resource(pldev, IORESOURCE_MEM, 0); + if (memres == NULL) { + printk("Unable to retrieve iProc CMIC memory resource."); + return -1; + } + size = memres->end - memres->start + 1; + + if (iproc_debug) { + printk("CMIC info : Memory start=%p, end=%p\n", + (void *)memres->start, (void *)memres->end); + } + + base_address = ioremap_nocache(memres->start, size); + if (!base_address) { + printk(KERN_WARNING "Error mapping iProc CMIC registers"); + return -1; + } + + memset(nd, 0, sizeof(*nd)); + nd->pci_dev = NULL; /* No PCI bus */ + nd->dma_dev = &pldev->dev; + + /* Read switch device ID from CMIC */ + dev_rev_id = *((uint32_t*)(base_address + 0x10224)); + nd->vendor_id = 0x14e4; + nd->device_id = dev_rev_id & 0xffff; + nd->revision = (dev_rev_id >> 16) & 0xff; + + irqres = platform_get_resource(pldev, IORESOURCE_IRQ, 0); + if (irqres == NULL) { + printk(KERN_WARNING "Unable to retrieve iProc CMIC IRQ resource."); + return -1; + } + nd->irq_line = irqres->start; + if (iproc_debug) { + printk("CMIC info : IRQ line=%p\n", (void *)irqres->start); + } + + nd->iowin[0].addr = memres->start; + nd->iowin[0].size = size; + + if (base_address) { + iounmap(base_address); + } + rv = ngbde_swdev_add(nd); + + return rv; +} + +/*! + * \brief Remove the platform device. + * + * \param [in] pldev Platform device. + * + * \retval 0 No errors + */ +static int +iproc_cmicd_remove(struct platform_device *pldev) +{ + return 0; +} + +/*! Matching compatible property with device tree. */ +static const struct of_device_id iproc_cmicd_of_match[] = { + { .compatible = "brcm,iproc-cmicd" }, + {}, +}; +MODULE_DEVICE_TABLE(of, iproc_cmicd_of_match); + +static char iproc_cmicd_string[] = "bcmiproc-cmicd"; + +/*! Platform driver definition. */ +static struct platform_driver iproc_cmicd_driver = +{ + .probe = iproc_cmicd_probe, + .remove = iproc_cmicd_remove, + .driver = + { + .name = iproc_cmicd_string, + .owner = THIS_MODULE, + .of_match_table = iproc_cmicd_of_match, + }, +}; + +/*! + * \brief Probe for Broadcom switch devices on IPROC internal bus. + * + * \return 0 if no errors, otherwise -1. + */ +int +ngbde_iproc_probe(void) +{ + platform_driver_register(&iproc_cmicd_driver); + + return 0; +} + +/*! + * \brief Clean up resources for Broadcom switch devices on IPROC internal bus. + * + * \return 0 if no errors, otherwise -1. + */ +int +ngbde_iproc_cleanup(void) +{ + platform_driver_unregister(&iproc_cmicd_driver); + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_kapi.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_kapi.c new file mode 100644 index 000000000000..340e7b057d44 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_kapi.c @@ -0,0 +1,216 @@ +/*! \file ngbde_kapi.c + * + * Public BDE kernel API for use with other kernel modules. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +#include + +struct pci_dev * +ngbde_kapi_pci_dev_get(int kdev) +{ + struct ngbde_dev_s *sd; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return NULL; + } + + return sd->pci_dev; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_pci_dev_get); +/*! \endcond */ + +struct device * +ngbde_kapi_dma_dev_get(int kdev) +{ + struct ngbde_dev_s *sd; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return NULL; + } + + return sd->dma_dev; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_dma_dev_get); +/*! \endcond */ + +void * +ngbde_kapi_dma_bus_to_virt(int kdev, dma_addr_t baddr) +{ + struct ngbde_dev_s *sd; + struct ngbde_dmamem_s *dmamem; + size_t dma_offset; + int idx; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return NULL; + } + + for (idx = 0; idx < NGBDE_NUM_DMAPOOL_MAX; idx++) { + dmamem = &sd->dmapool[idx].dmamem; + dma_offset = baddr - dmamem->baddr; + if (dma_offset < dmamem->size) { + return (uint8_t *)dmamem->vaddr + dma_offset; + } + } + return NULL; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_dma_bus_to_virt); +/*! \endcond */ + +dma_addr_t +ngbde_kapi_dma_virt_to_bus(int kdev, void *vaddr) +{ + struct ngbde_dev_s *sd; + struct ngbde_dmamem_s *dmamem; + size_t dma_offset; + int idx; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return 0UL; + } + + for (idx = 0; idx < NGBDE_NUM_DMAPOOL_MAX; idx++) { + dmamem = &sd->dmapool[idx].dmamem; + dma_offset = (uintptr_t)vaddr - (uintptr_t)dmamem->vaddr; + if (dma_offset < dmamem->size) { + return dmamem->baddr + dma_offset; + } + } + return 0UL; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_dma_virt_to_bus); +/*! \endcond */ + +void +ngbde_kapi_pio_write32(int kdev, uint32_t offs, uint32_t val) +{ + struct ngbde_dev_s *sd; + + sd = ngbde_swdev_get(kdev); + if (sd) { + return ngbde_pio_write32(sd, offs, val); + } +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_pio_write32); +/*! \endcond */ + +uint32_t +ngbde_kapi_pio_read32(int kdev, uint32_t offs) +{ + struct ngbde_dev_s *sd; + + sd = ngbde_swdev_get(kdev); + if (sd) { + return ngbde_pio_read32(sd, offs); + } + + return (uint32_t)-1; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_pio_read32); +/*! \endcond */ + +void * +ngbde_kapi_pio_membase(int kdev) +{ + struct ngbde_dev_s *sd; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return NULL; + } + + return sd->pio_mem; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_pio_membase); +/*! \endcond */ + +int +ngbde_kapi_intr_connect(int kdev, unsigned int irq_num, + int (*isr_func)(void *), void *isr_data) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + ic->isr_func = isr_func; + ic->isr_data = isr_data; + + return 0; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_intr_connect); +/*! \endcond */ + +int +ngbde_kapi_intr_disconnect(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + ic->isr_func = NULL; + ic->isr_data = NULL; + + return 0; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_intr_disconnect); +/*! \endcond */ + +int +ngbde_kapi_intr_mask_write(int kdev, unsigned int irq_num, + uint32_t status_reg, uint32_t mask_val) +{ + return ngbde_intr_mask_write(kdev, irq_num, 1, status_reg, mask_val); +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_intr_mask_write); +/*! \endcond */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_main.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_main.c new file mode 100644 index 000000000000..5ce48ebc5134 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_main.c @@ -0,0 +1,297 @@ +/*! \file ngbde_main.c + * + * NGBDE module entry. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +/*! \cond */ +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("NG BDE Module"); +MODULE_LICENSE("GPL"); +/*! \endcond */ + +/*! \cond */ +static int mmap_debug = 0; +module_param(mmap_debug, int, 0); +MODULE_PARM_DESC(mmap_debug, +"MMAP debug output enable (default 0)."); +/*! \endcond */ + +/*! + * \brief Remap user space DMA memory to non-cached area. + * + * Since we cannot flush and invalidate DMA memory from user space, + * the DMA memory pools need to be cache-coherent, even if this means + * that we need to remap the DMA memory as non-cached. + * + * If undefined, we set this value according to kernel configuration. + */ +#ifndef REMAP_DMA_NONCACHED +# ifdef CONFIG_DMA_NONCOHERENT +# define REMAP_DMA_NONCACHED 1 +# else +# define REMAP_DMA_NONCACHED 0 +# endif +#endif + +static int +ngbde_open(struct inode *inode, struct file *filp) +{ + return 0; +} + +static int +ngbde_release(struct inode *inode, struct file *filp) +{ + return 0; +} + +/*! + * \brief Check if memory range is within existing DMA memory pools. + * + * \param [in] paddr Physical start address of memory range. + * \param [in] size Size of memory range. + * + * \retval true Range is valid. + * \retval false Range is not valid. + */ +static bool +ngbde_dma_range_valid(unsigned long paddr, unsigned long size) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + struct ngbde_dmamem_s *dmamem; + unsigned int pool; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) { + dmamem = &swdev[idx].dmapool[pool].dmamem; + if (paddr >= dmamem->paddr && + (paddr + size) <= (dmamem->paddr + dmamem->size)) { + return true; + } + } + } + return false; +} + +/*! + * \brief Check if memory range is within device I/O ranges. + * + * \param [in] paddr Physical start address of I/O memory range. + * \param [in] size Size of memory range. + * + * \retval true Range is valid. + * \retval false Range is not valid. + */ +static bool +ngbde_pio_range_valid(unsigned long paddr, unsigned long size) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + struct ngbde_memwin_s *iowin; + unsigned long iowin_size; + unsigned int wdx; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + for (wdx = 0; wdx < NGBDE_NUM_IOWIN_MAX; wdx++) { + iowin = &swdev[idx].iowin[wdx]; + iowin_size = iowin->size; + if (iowin_size < PAGE_SIZE) { + iowin_size = PAGE_SIZE; + } + if (mmap_debug) { + printk("MMAP: Check 0x%08lx/0x%08lx against " + "0x%08lx/0x%08lx(0x%08lx)\n", + paddr, size, + (unsigned long)iowin->addr, + (unsigned long)iowin->size, iowin_size); + } + if (paddr >= iowin->addr && + (paddr + size) <= (iowin->addr + iowin_size)) { + return true; + } + } + } + return false; +} + +/*! + * \brief Match incomplete address with device base addresses. + * + * Use for physical addresses larger than 44 bits. + * + * \param [in] paddr Physical address from user space. + * + * \return Matched device base addess or 0 if no match. + */ +static unsigned long +ngbde_pio_base_match(unsigned long paddr) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + struct ngbde_memwin_s *iowin; + unsigned int wdx; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + for (wdx = 0; wdx < NGBDE_NUM_IOWIN_MAX; wdx++) { + iowin = &swdev[idx].iowin[wdx]; + if (((paddr ^ iowin->addr) & 0xfffffffffffULL) == 0) { + if (mmap_debug) { + printk("MMAP: Matched 0x%08lx to 0x%08lx\n", + (unsigned long)paddr, + (unsigned long)iowin->addr); + } + return iowin->addr; + } + } + } + return 0; +} + +/* + * Some kernels are configured to prevent mapping of kernel RAM memory + * into user space via the /dev/mem device. + * + * The function below provides a backdoor to mapping the DMA pool to + * user space via the BDE device file. + */ +static int +ngbde_mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long paddr = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size = vma->vm_end - vma->vm_start; + int map_noncached = REMAP_DMA_NONCACHED; + int range_valid = 0; + + if (mmap_debug) { + printk("MMAP: Mapping %lu Kbytes at 0x%08lx (0x%lx)\n", + size / 1024, paddr, vma->vm_pgoff); + } + + if (ngbde_dma_range_valid(paddr, size)) { + range_valid = 1; + } else { + map_noncached = 1; + if (ngbde_pio_range_valid(paddr, size)) { + range_valid = 1; + } else { + paddr = ngbde_pio_base_match(paddr); + if (ngbde_pio_range_valid(paddr, size)) { + range_valid = 1; + } + } + } + + if (!range_valid) { + printk("BDE: Invalid mmap range 0x%08lx/0x%lx\n", paddr, size); + return -EINVAL; + } + + if (map_noncached) { + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + } + + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + size, vma->vm_page_prot)) { + printk("BDE: Failed to mmap phys range 0x%lx-0x%lx to 0x%lx-0x%lx\n", + paddr, paddr + size, vma->vm_start, vma->vm_end); + return -EAGAIN; + } + + return 0; +} + +static struct file_operations fops = { + .open = ngbde_open, + .release = ngbde_release, + .unlocked_ioctl = ngbde_ioctl, + .compat_ioctl = ngbde_ioctl, + .mmap = ngbde_mmap, +}; + +/*! + * \brief Standard module cleanup. + * + * \return Nothing. + */ +void __exit +cleanup_module(void) +{ + ngbde_intr_cleanup(); + ngbde_iio_cleanup(); + ngbde_paxb_cleanup(); + ngbde_pio_cleanup(); + ngbde_dma_cleanup(); + ngbde_procfs_cleanup(); + unregister_chrdev(MOD_MAJOR, MOD_NAME); + ngbde_pci_cleanup(); + ngbde_iproc_cleanup(); + printk(KERN_INFO "Broadcom NGBDE unloaded successfully\n"); +} + +/*! + * \brief Standard module initialization. + * + * \return Nothing. + */ +int __init +init_module(void) +{ + int rv; + + rv = register_chrdev(MOD_MAJOR, MOD_NAME, &fops); + if (rv < 0) { + printk(KERN_WARNING "%s: can't get major %d\n", + MOD_NAME, MOD_MAJOR); + return rv; + } + + rv = ngbde_iproc_probe(); + if (rv < 0) { + printk(KERN_WARNING "%s: Error probing for AXI bus devices.\n", + MOD_NAME); + return rv; + } + + rv = ngbde_pci_probe(); + if (rv < 0) { + printk(KERN_WARNING "%s: Error probing for PCI bus devices.\n", + MOD_NAME); + return rv; + } + + rv = ngbde_procfs_init(); + if (rv < 0) { + printk(KERN_WARNING "%s: Unable to initialize proc files\n", + MOD_NAME); + return rv; + } + + printk(KERN_INFO "Broadcom NGBDE loaded successfully\n"); + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pci_probe.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pci_probe.c new file mode 100644 index 000000000000..37da39cd38a7 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pci_probe.c @@ -0,0 +1,211 @@ +/*! \file ngbde_pci_probe.c + * + * NG BDE probe for PCI devices. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +/*! \cond */ +static int use_msi = 1; +module_param(use_msi, int, 0); +MODULE_PARM_DESC(use_msi, +"Use MSI interrupts if supported by the kernel (default 1)."); +/*! \endcond */ + +/*! \cond */ +static int pci_debug = 0; +module_param(pci_debug, int, 0); +MODULE_PARM_DESC(pci_debug, +"PCI debug output enable (default 0)."); +/*! \endcond */ + +/*! + * Use BCMDRD_DEVLIST_ENTRY macro to generate a device list based on + * supported/installed devices. + */ +#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \ + { _vn, _dv, PCI_ANY_ID, PCI_ANY_ID }, + +/*! Include all chip variants in the list of supported devices. */ +#define BCMDRD_DEVLIST_INCLUDE_ALL + +static struct pci_device_id pci_id_table[] = { +#include + { BROADCOM_VENDOR_ID, 0xb524, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, 0xb684, PCI_ANY_ID, PCI_ANY_ID }, + { 0, 0, 0, 0 } +}; + +static int +pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *ent) +{ + int rv; + int bdx; + int cmic_bar = 0; + uint8_t rev; + struct ngbde_dev_s ngbde_dev, *nd = &ngbde_dev; + int bus_no = pci_dev->bus ? pci_dev->bus->number : 0; + int slot_no = PCI_SLOT(pci_dev->devfn); + + if (PCI_FUNC(pci_dev->devfn) > 0) { + return 0; + } + + if (pci_debug) { + printk("PCI: pci_probe: bus %d slot %d: %04x:%04x\n", + bus_no, slot_no, + pci_dev->vendor, pci_dev->device); + } + + memset(nd, 0, sizeof(*nd)); + nd->pci_dev = pci_dev; + nd->dma_dev = &pci_dev->dev; + nd->vendor_id = pci_dev->vendor; + nd->device_id = pci_dev->device; + nd->bus_no = bus_no; + nd->slot_no = slot_no; + + /* PCI revision must extracted "manually */ + pci_read_config_byte(pci_dev, PCI_REVISION_ID, &rev); + nd->revision = rev; + + if (pci_enable_device(pci_dev)) { + printk(KERN_WARNING "%s: Cannot enable PCI device: " + "vendor_id = %x, device_id = %x\n", + MOD_NAME, pci_dev->vendor, pci_dev->device); + } + pci_set_master(pci_dev); + + /* IRQ number is only valid if PCI device is enabled */ + nd->irq_line = pci_dev->irq; + + /* Check for iProc */ + if (pci_resource_len(pci_dev, 2)) { + nd->iowin[1].addr = pci_resource_start(pci_dev, 0); + nd->iowin[1].size = pci_resource_len(pci_dev, 0); + cmic_bar = 2; + } + nd->iowin[0].addr = pci_resource_start(pci_dev, cmic_bar); + nd->iowin[0].size = pci_resource_len(pci_dev, cmic_bar); + + /* Verify basic I/O access by reading first word of each BAR window */ + for (bdx = 0; bdx < 2; bdx++) { + if (nd->iowin[bdx].size == 0) { + continue; + } + if (ngbde_pio_map(nd, nd->iowin[bdx].addr, nd->iowin[bdx].size)) { + if (pci_debug) { + printk("PCI: BAR %d adddress 0 = 0x%x\n", + bdx, (unsigned int)ngbde_pio_read32(nd, 0)); + } + ngbde_pio_unmap(nd); + } else { + printk(KERN_WARNING "%s: Cannot map PCI BAR %d: " + "start = %08lx, len = %lx\n", + MOD_NAME, bdx, + (unsigned long)nd->iowin[bdx].addr, + (unsigned long)nd->iowin[bdx].size); + } + } + + spin_lock_init(&nd->lock); + + /* Determine MSI configuration by enabling MSI on the device */ + nd->use_msi = use_msi; + if (nd->use_msi) { + if (pci_enable_msi(nd->pci_dev) == 0) { + pci_disable_msi(nd->pci_dev); + } else { + nd->use_msi = 0; + } + } + + rv = ngbde_swdev_add(nd); + + if (rv == 0) { + /* Update DMA pools for all devices */ + rv = ngbde_dma_init(); + if (rv < 0) { + printk(KERN_WARNING "%s: Error initializing DMA memory\n", + MOD_NAME); + /* Mark device as inactive */ + nd->inactive = 1; + } + } + + return rv; +} + +static void +pci_remove(struct pci_dev* pci_dev) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + int bus_no = pci_dev->bus ? pci_dev->bus->number : 0; + int slot_no = PCI_SLOT(pci_dev->devfn); + + if (pci_debug) { + printk("PCI: pci_remove: bus %d slot %d: %04x:%04x\n", + bus_no, slot_no, + pci_dev->vendor, pci_dev->device); + } + + ngbde_swdev_get_all(&swdev, &num_swdev); + for (idx = 0; idx < num_swdev; idx++) { + if (swdev[idx].bus_no == bus_no && + swdev[idx].slot_no == slot_no) { + if (swdev[idx].inactive) { + printk(KERN_WARNING "%s: Device already removed\n", + MOD_NAME); + } + /* Active device in this slot already? */ + swdev[idx].inactive = 1; + } + } + + /* Update DMA pools for all devices */ + ngbde_dma_cleanup(); +} + +static struct pci_driver pci_driver = { + .name = MOD_NAME, + .probe = pci_probe, + .remove = pci_remove, + .id_table = pci_id_table, + /* The rest are dynamic */ +}; + +int +ngbde_pci_probe(void) +{ + if (pci_register_driver(&pci_driver) < 0) { + return -ENODEV; + } + + return 0; +} + +int +ngbde_pci_cleanup(void) +{ + pci_unregister_driver(&pci_driver); + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pgmem.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pgmem.c new file mode 100644 index 000000000000..e473f0c545cb --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pgmem.c @@ -0,0 +1,472 @@ +/*! \file ngbde_pgmem.c + * + * \brief PGMEM allocator. + * + * This module is used to allocate large physically contiguous memory + * blocks using the Linux kernel page allocator. + * + * The Linux page allocator can allocate contiguous memory up until a + * certain size, which depends on the kernel version and the CPU + * architecture. + * + * If a larger contiguous memory block is requested, then we need to + * allocate multiple blocks from the Linux page allocator and then + * check if which ones are contiguous. + * + * The smaller memory blocks from which the larger block is assembled + * are referred to as "chunks". + * + * The PGMEM allocator will continue to allocate chunks from the Linux + * page allocator, until a contiguous memory block of the requested + * size has been assembled, or until a predefined maximum number of + * chunks have been allocated. Obviously the process is also stopped + * if the Linux page allocator returns an error. + * + * A physically contiguous memory block assembled from smaller memory + * chunks are referred to as "cmblocks". + * + * The chance of success depends on the requested memory block size as + * well as the fragmentation level of the system memory, i.e. the + * sooner after system boot these memory block are requested, the more + * likely these requests are to succeed. + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + + +/******************************************************************************* + * Local definitions + ******************************************************************************/ + +/*! Maximum size the kernel can allocate in a single allocation. */ +#define MEM_CHUNK_SIZE_MAX (1 << (MAX_ORDER - 1 + PAGE_SHIFT)) + +/*! Default block size we wil request from the kernel. */ +#define MEM_CHUNK_SIZE_DEFAULT (512 * ONE_KB) + +/*! \cond */ +static int pgmem_chunk_size = 0; +module_param(pgmem_chunk_size, int, 0); +MODULE_PARM_DESC(pgmem_chunk_size, +"Memory chunk size in KB used by page allocator (default auto)."); +/*! \endcond */ + +/*! \cond */ +static int pgmem_debug = 0; +module_param(pgmem_debug, int, 0); +MODULE_PARM_DESC(pgmem_debug, +"Enable page memory allocator debug output (default 0)."); +/*! \endcond */ + +/*! Helper macro for debug trace output. */ +#define PGMEM_TRACE(_s) \ + do { \ + if (pgmem_debug) { \ + printk(_s); \ + } \ + } while (0) + +/*! + * Chunk memory block descriptor. + */ +typedef struct cmblock_desc_s { + + /*! Linked-list handle. */ + struct list_head list; + + /*! Requested cmblock size. */ + unsigned long req_size; + + /*! Memory chunk size. */ + unsigned long chunk_size; + + /*! Memory chunk size in alternate format (2^x). */ + unsigned long chunk_order; + + /*! Current cmblock size. */ + unsigned long cmblk_size; + + /*! Logical address of cmblock. */ + unsigned long cmblk_begin; + + /*! Logical end address of cmblock. */ + unsigned long cmblk_end; + + /*! Array of logical chunk addresses. */ + unsigned long *chunk_ptr; + + /*! Maximum number of chunks to allocate. */ + int chunk_cnt_max; + + /*! Current number of chunks allocated. */ + int chunk_cnt; + +} cmblock_desc_t; + +static LIST_HEAD(cmblocks_list); + + +/*! + * \name Chunk tag mask. + * \anchor CT_xxx + * + * The lower two bits of the chunk address is used to tag the chunk + * with its current state. + */ +#define CT_MASK 0x3 + +/*! Chunk is untagged. */ +#define CT_UNTAGGED 0 + +/*! Chunk was discarded. */ +#define CT_DISCARDED 1 + +/*! Chunk is part of largest cmblock. */ +#define CT_LARGEST 2 + +/*! Chunk is part of current cmblock. */ +#define CT_CURRENT 3 + +/*! Set block as untagged. */ +#define CTAG_SET(_a, _t) \ + do { \ + (_a) &= ~CT_MASK; \ + (_a) |= _t; \ + } while (0) + +/*! Set block as untagged. */ +#define CTAG_GET(_a) \ + ((_a) & CT_MASK) + + +/******************************************************************************* + * Private Functions + ******************************************************************************/ + +/*! + * \brief Find largest contiguous memory block. + * + * Find largest contiguous memory block from a pool of memory chunks. + * + * Assembly stops if a cmblock of the requested cmblock size has been + * obtained. + * + * The lower two address bits of the memory chunks are encoded as a + * tag according to \ref CT_xxx. + * + * \param [in] cmbd cmblock descriptor. + * + * \return Always 0. + */ +static int +find_largest_cmblock(cmblock_desc_t *cmbd) +{ + int i, j, chunks, found; + unsigned long b, e, a; + unsigned long *cptr; + + /* Convenience variable */ + chunks = cmbd->chunk_cnt; + cptr = cmbd->chunk_ptr; + + /* Clear all chunk tags */ + for (i = 0; i < chunks; i++) { + CTAG_SET(cptr[i], CT_UNTAGGED); + } + for (i = 0; i < chunks && cmbd->cmblk_size < cmbd->req_size; i++) { + /* First chunk must be an untagged chunk */ + if (CTAG_GET(cptr[i]) == CT_UNTAGGED) { + /* Initial cmblock size is the chunk size */ + b = cptr[i]; + e = b + cmbd->chunk_size; + CTAG_SET(cptr[i], CT_CURRENT); + /* Loop looking for adjacent chunks */ + do { + found = 0; + for (j = i + 1; j < chunks && (e - b) < cmbd->req_size; j++) { + a = cptr[j]; + /* Check untagged chunks only */ + if (CTAG_GET(a) == CT_UNTAGGED) { + if (a == (b - cmbd->chunk_size)) { + /* Found adjacent chunk below current cmblock */ + CTAG_SET(cptr[j], CT_CURRENT); + b = a; + found = 1; + } else if (a == e) { + /* Found adjacent chunk above current cmblock */ + CTAG_SET(cptr[j], CT_CURRENT); + e += cmbd->chunk_size; + found = 1; + } + } + } + } while (found); + /* Now check the size of the assembled memory block */ + if ((e - b) > cmbd->cmblk_size) { + /* The current block is largest so far */ + cmbd->cmblk_begin = b; + cmbd->cmblk_end = e; + cmbd->cmblk_size = e - b; + /* Re-tag current and previous largest cmblock */ + for (j = 0; j < chunks; j++) { + if (CTAG_GET(cptr[j]) == CT_CURRENT) { + /* Tag current cmblock as the largest */ + CTAG_SET(cptr[j], CT_LARGEST); + } else if (CTAG_GET(cptr[j]) == CT_LARGEST) { + /* Discard previous largest cmblock */ + CTAG_SET(cptr[j], CT_DISCARDED); + } + } + } else { + /* Discard all chunks in current cmblock */ + for (j = 0; j < chunks; j++) { + if (CTAG_GET(cptr[j]) == CT_CURRENT) { + CTAG_SET(cptr[j], CT_DISCARDED); + } + } + } + } + } + return 0; +} + +/*! + * \brief Allocate memory chunks and add them to the pool. + * + * Memory chunks are allocated using the kernel page allocator. + * + * \param [in] cmbd - cmblock descriptor. + * \param [in] chunks - Number of memory chunks to allocate. + * + * \return 0 if no errors, otherwise -1. + */ +static int +alloc_mem_chunks(cmblock_desc_t *cmbd, int chunks) +{ + int i, start; + unsigned long addr; + + if (cmbd->chunk_cnt + chunks > cmbd->chunk_cnt_max) { + printk("PGMEM: No more memory chunks\n"); + return -1; + } + start = cmbd->chunk_cnt; + cmbd->chunk_cnt += chunks; + for (i = start; i < cmbd->chunk_cnt; i++) { + /* Get chunk from kernel allocator */ + addr = __get_free_pages(GFP_KERNEL | GFP_DMA32, cmbd->chunk_order); + PGMEM_TRACE("."); + if (addr) { + cmbd->chunk_ptr[i] = addr; + } else { + printk("PGMEM: Page memory allocation failed\n"); + return -1; + } + } + return 0; +} + +/*! + * \brief Allocate large physically contiguous memory block. + * + * If we cannot allocate a sufficiently large block of contiguous + * memory from the kernel, then we simply keep allocating smaller + * chunks until we can assemble a contiguous block of the desired + * size. + * + * When maximum amount of system memory has been allocated without the + * successful assembly of a contiguous memory block, the allocation + * function will return the largest contiguous block found so far. It + * is then up to the calling function to decide whether this amount is + * sufficient to proceed. + * + * \param [in] size Requested memory block size. + * \param [in] chunk_size Assemble cmblock from chunks of this size. + * + * \return Pointer to cmblock descriptor, or NULL if error. + */ +static cmblock_desc_t * +cmblock_alloc(size_t size, size_t chunk_size) +{ + cmblock_desc_t *cmbd; + int i, chunk_ptr_size; + unsigned long page_addr; + struct sysinfo si; + + /* Sanity check */ + if (size == 0 || chunk_size == 0) { + return NULL; + } + + /* Allocate an initialize memory cmblock descriptor */ + if ((cmbd = kmalloc(sizeof(cmblock_desc_t), GFP_KERNEL)) == NULL) { + return NULL; + } + memset(cmbd, 0, sizeof(*cmbd)); + cmbd->req_size = size; + cmbd->chunk_size = PAGE_ALIGN(chunk_size); + while ((PAGE_SIZE << cmbd->chunk_order) < cmbd->chunk_size) { + cmbd->chunk_order++; + } + + /* Determine the maximum possible number of memory chunks */ + si_meminfo(&si); + cmbd->chunk_cnt_max = (si.totalram << PAGE_SHIFT) / cmbd->chunk_size; + chunk_ptr_size = cmbd->chunk_cnt_max * sizeof(unsigned long); + + /* Allocate an initialize memory chunk pool */ + cmbd->chunk_ptr = kmalloc(chunk_ptr_size, GFP_KERNEL); + if (cmbd->chunk_ptr == NULL) { + kfree(cmbd); + return NULL; + } + memset(cmbd->chunk_ptr, 0, chunk_ptr_size); + + /* Allocate minimum number of memory chunks */ + (void)alloc_mem_chunks(cmbd, cmbd->req_size / cmbd->chunk_size); + + /* Allocate more chunks until we have a complete cmblock */ + do { + find_largest_cmblock(cmbd); + PGMEM_TRACE("o"); + if (cmbd->cmblk_size >= cmbd->req_size) { + break; + } + } while (alloc_mem_chunks(cmbd, 8) == 0); + + /* Reserve all pages in the cmblock and free unused chunks */ + for (i = 0; i < cmbd->chunk_cnt; i++) { + if (CTAG_GET(cmbd->chunk_ptr[i]) == CT_LARGEST) { + CTAG_SET(cmbd->chunk_ptr[i], CT_UNTAGGED); + for (page_addr = cmbd->chunk_ptr[i]; + page_addr < cmbd->chunk_ptr[i] + cmbd->chunk_size; + page_addr += PAGE_SIZE) { + SetPageReserved(virt_to_page((void *)page_addr)); + } + } else if (cmbd->chunk_ptr[i]) { + CTAG_SET(cmbd->chunk_ptr[i], CT_UNTAGGED); + free_pages(cmbd->chunk_ptr[i], cmbd->chunk_order); + PGMEM_TRACE("x"); + cmbd->chunk_ptr[i] = 0; + } + } + PGMEM_TRACE("O\n"); + return cmbd; +} + +/*! + * \brief Free cmblock and associated resources. + * + * Free all memory chunks and other associated resources associated + * with a contiguous memory block. + * + * See alse \ref cmblock_alloc. + * + * \param [in] cmbd Command block descriptor to free. + * + * \return Nothing. + */ +static void +cmblock_free(cmblock_desc_t *cmbd) +{ + int i; + unsigned long page_addr; + + if (cmbd->chunk_ptr) { + for (i = 0; i < cmbd->chunk_cnt; i++) { + if (cmbd->chunk_ptr[i]) { + for (page_addr = cmbd->chunk_ptr[i]; + page_addr < cmbd->chunk_ptr[i] + cmbd->chunk_size; + page_addr += PAGE_SIZE) { + ClearPageReserved(virt_to_page((void *)page_addr)); + } + free_pages(cmbd->chunk_ptr[i], cmbd->chunk_order); + PGMEM_TRACE("X"); + } + } + kfree(cmbd->chunk_ptr); + kfree(cmbd); + } +} + + +/******************************************************************************* + * Public Functions + ******************************************************************************/ + +void * +ngbde_pgmem_alloc(size_t size, gfp_t flags) +{ + cmblock_desc_t *cmbd; + size_t chunk_size; + + chunk_size = size; + + if (pgmem_chunk_size > 0) { + chunk_size = pgmem_chunk_size * ONE_KB; + } + + if (chunk_size > MEM_CHUNK_SIZE_MAX) { + chunk_size = MEM_CHUNK_SIZE_DEFAULT; + } + + if (pgmem_debug) { + printk("PGMEM: Allocate %d MB in %d KB chunks\n", + (int)(size / ONE_MB), (int)(chunk_size / ONE_KB)); + } + + if ((cmbd = cmblock_alloc(size, chunk_size)) == NULL) { + return NULL; + } + if (cmbd->cmblk_size < size) { + /* If we didn't get the full size then forget it */ + cmblock_free(cmbd); + return NULL; + } + list_add(&cmbd->list, &cmblocks_list); + return (void *)cmbd->cmblk_begin; +} + +int +ngbde_pgmem_free(void *ptr) +{ + struct list_head *pos; + + list_for_each(pos, &cmblocks_list) { + cmblock_desc_t *cmbd = list_entry(pos, cmblock_desc_t, list); + if (ptr == (void *)cmbd->cmblk_begin) { + list_del(&cmbd->list); + cmblock_free(cmbd); + return 0; + } + } + return -1; +} + +void +ngbde_pgmem_free_all(void) +{ + struct list_head *pos, *tmp; + + list_for_each_safe(pos, tmp, &cmblocks_list) { + cmblock_desc_t *cmbd = list_entry(pos, cmblock_desc_t, list); + list_del(&cmbd->list); + cmblock_free(cmbd); + } +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pio.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pio.c new file mode 100644 index 000000000000..cab094a2feca --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pio.c @@ -0,0 +1,97 @@ +/*! \file ngbde_pio.c + * + * API for managing and accessing memory-mapped I/O for switch + * registers. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +void * +ngbde_pio_map(void *devh, phys_addr_t addr, phys_addr_t size) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->pio_mem) { + if (addr == sd->pio_win.addr && size == sd->pio_win.size) { + /* Already mapped */ + return sd->pio_mem; + } + ngbde_pio_unmap(devh); + } + + sd->pio_mem = ioremap_nocache(addr, size); + + if (sd->pio_mem) { + /* Save mapped resources */ + sd->pio_win.addr = addr; + sd->pio_win.size = size; + } else { + printk(KERN_WARNING "%s: Unable to map address 0x%08lu\n", + MOD_NAME, (unsigned long)addr); + } + + return sd->pio_mem; +} + +void +ngbde_pio_unmap(void *devh) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->pio_mem) { + iounmap(sd->pio_mem); + sd->pio_mem = NULL; + } +} + +void +ngbde_pio_cleanup(void) +{ + struct ngbde_dev_s *swdev, *sd; + unsigned int num_swdev, idx; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + sd = ngbde_swdev_get(idx); + ngbde_pio_unmap(sd); + } +} + +void +ngbde_pio_write32(void *devh, uint32_t offs, uint32_t val) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->pio_mem) { + NGBDE_IOWRITE32(val, sd->pio_mem + offs); + } +} + +uint32_t +ngbde_pio_read32(void *devh, uint32_t offs) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->pio_mem) { + return NGBDE_IOREAD32(sd->pio_mem + offs); + } + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_procfs.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_procfs.c new file mode 100644 index 000000000000..f99339a5b0dc --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_procfs.c @@ -0,0 +1,120 @@ +/*! \file ngbde_procfs.c + * + * + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +static int +proc_show(struct seq_file *m, void *v) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + struct ngbde_dmamem_s *dmamem; + unsigned int pool; + unsigned int dma_pools; + char *dma_str; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + seq_printf(m, "Broadcom Device Enumerator (%s)\n", MOD_NAME); + + seq_printf(m, "Found %d switch device(s):\n", num_swdev); + for (idx = 0; idx < num_swdev; idx++) { + if (swdev->inactive) { + seq_printf(m, "%d:removed\n", idx); + continue; + } + seq_printf(m, "%d:%04x:%04x:%02x,%s(%d)\n", idx, + swdev->vendor_id, swdev->device_id, swdev->revision, + swdev->use_msi ? "MSI" : "IRQ", swdev->irq_line); + } + + seq_printf(m, "DMA pools:\n"); + for (idx = 0; idx < num_swdev; idx++) { + seq_printf(m, "%d", idx); + dma_pools = 0; + for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) { + dmamem = &swdev[idx].dmapool[pool].dmamem; + dma_str = "unknown"; + if (dmamem->type == NGBDE_DMA_T_NONE) { + /* Skip empty DMA pools */ + continue; + } else if (dmamem->type == NGBDE_DMA_T_KAPI) { + dma_str = "kapi"; + } else if (dmamem->type == NGBDE_DMA_T_PGMEM) { + dma_str = "pgmem"; + } + seq_printf(m, ":%dMB@0x%08lx(%s)", + (int)(dmamem->size / ONE_MB), + (unsigned long)dmamem->baddr, dma_str); + dma_pools++; + } + if (dma_pools == 0) { + seq_printf(m, ":none"); + } + seq_printf(m, "\n"); + } + + return 0; +} + +static int +proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_show, NULL); +} + +static int +proc_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_fops = { + owner: THIS_MODULE, + open: proc_open, + read: seq_read, + llseek: seq_lseek, + release: proc_release, +}; + +int +ngbde_procfs_init(void) +{ + struct proc_dir_entry *entry; + + PROC_CREATE(entry, MOD_NAME, 0666, NULL, &proc_fops); + + if (entry == NULL) { + printk(KERN_ERR "ngbde: proc_create failed\n"); + return -1; + } + + return 0; +} + +int +ngbde_procfs_cleanup(void) +{ + remove_proc_entry(MOD_NAME, NULL); + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_swdev.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_swdev.c new file mode 100644 index 000000000000..60d328ad2526 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_swdev.c @@ -0,0 +1,79 @@ +/*! \file ngbde_swdev.c + * + * + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +/* Switch devices */ +static struct ngbde_dev_s swdevs[NGBDE_NUM_SWDEV_MAX]; + +/* Number of probed switch devices */ +static unsigned int num_swdev; + +int +ngbde_swdev_add(struct ngbde_dev_s *nd) +{ + unsigned int idx; + + /* Look for existing slot */ + for (idx = 0; idx < num_swdev; idx++) { + if (swdevs[idx].bus_no == nd->bus_no && + swdevs[idx].slot_no == nd->slot_no) { + if (swdevs[idx].inactive) { + memcpy(&swdevs[idx], nd, sizeof(swdevs[0])); + return 0; + } + /* Active device in this slot already? */ + printk(KERN_WARNING "%s: Device exists\n", + MOD_NAME); + return -EBUSY; + } + } + + /* Add new device */ + if (num_swdev >= NGBDE_NUM_SWDEV_MAX) { + return -ENOMEM; + } + memcpy(&swdevs[num_swdev], nd, sizeof(swdevs[0])); + ++num_swdev; + return 0; +} + +struct ngbde_dev_s * +ngbde_swdev_get(int kdev) +{ + if ((unsigned int)kdev < num_swdev) { + return &swdevs[kdev]; + } + return NULL; +} + +int +ngbde_swdev_get_all(struct ngbde_dev_s **nd, unsigned int *num_nd) +{ + if (nd) { + *nd = swdevs; + } + if (num_nd) { + *num_nd = num_swdev; + } + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/lkm.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/lkm.h new file mode 100644 index 000000000000..c0ba0a319767 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/lkm.h @@ -0,0 +1,126 @@ +/*! \file lkm.h + * + * + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef LKM_H +#define LKM_H + +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +#error Kernel too old +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) +#include +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#include +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_DEVFS_FS +#include +#endif + +/* Compatibility Macros */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#define PROC_CREATE(_entry, _name, _acc, _path, _fops) \ + do { \ + _entry = proc_create(_name, _acc, _path, _fops); \ + } while (0) + +#define PROC_CREATE_DATA(_entry, _name, _acc, _path, _fops, _data) \ + do { \ + _entry = proc_create_data(_name, _acc, _path, _fops, _data); \ + } while (0) + +#define PROC_PDE_DATA(_node) PDE_DATA(_node) +#else +#define PROC_CREATE(_entry, _name, _acc, _path, _fops) \ + do { \ + _entry = create_proc_entry(_name, _acc, _path); \ + if (_entry) { \ + _entry->proc_fops = _fops; \ + } \ + } while (0) + +#define PROC_CREATE_DATA(_entry, _name, _acc, _path, _fops, _data) \ + do { \ + _entry = create_proc_entry(_name, _acc, _path); \ + if (_entry) { \ + _entry->proc_fops = _fops; \ + _entry->data=_data; \ + } \ + } while (0) + +#define PROC_PDE_DATA(_node) PROC_I(_node)->pde->data +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) +#define timer_arg(var, context, timer_fieldname) \ + (typeof(var))(context) +#define timer_context_t unsigned long +#else +#define timer_context_t struct timer_list * +#define timer_arg(var, context, timer_fieldname) \ + from_timer(var, context, timer_fieldname) +#endif + +#ifndef setup_timer +#define setup_timer(timer, fn, data) \ + timer_setup(timer, fn, 0) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) +static inline void page_ref_inc(struct page *page) +{ + atomic_inc(&page->_count); +} + +static inline void page_ref_dec(struct page *page) +{ + atomic_dec(&page->_count); +} +#endif + +#endif /* LKM_H */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_ioctl.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_ioctl.h new file mode 100644 index 000000000000..b90486ce06f2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_ioctl.h @@ -0,0 +1,345 @@ +/*! \file ngbde_ioctl.h + * + * NGBDE device I/O control definitions. + * + * This file is intended for use in both kernel mode and user mode. + * + * IMPORTANT! + * All shared structures must be properly 64-bit aligned. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGBDE_IOCTL_H +#define NGBDE_IOCTL_H + +#include +#include + +/*! Must be updated if backward compatibility is broken. */ +#define NGBDE_IOC_VERSION 2 + +/*! LUBDE IOCTL command magic. */ +#define NGBDE_IOC_MAGIC 'L' + +/*! + * \name IOCTL commands for the NGBDE kernel module. + * \anchor NGBDE_IOC_xxx + * + * Note that we use __u64 for the IOCTL parameter size because + * sizeof(void *) is different between 32-bit and 64-bit code, and we + * need a 32-bit user mode application to generate the same IOCTL + * command codes as a 64-bit kernel when using the _IOW macro. + */ + +/*! \{ */ + +/*! Get kernel module information. */ +#define NGBDE_IOC_MOD_INFO _IOW(NGBDE_IOC_MAGIC, 0, __u64) + +/*! Get information about registered devices. */ +#define NGBDE_IOC_PROBE_INFO _IOW(NGBDE_IOC_MAGIC, 1, __u64) + +/*! Get detailed switch device information. */ +#define NGBDE_IOC_DEV_INFO _IOW(NGBDE_IOC_MAGIC, 2, __u64) + +/*! Get a physical memory address associated with a switch device. */ +#define NGBDE_IOC_PHYS_ADDR _IOW(NGBDE_IOC_MAGIC, 3, __u64) + +/*! Interrupt control command (see \ref NGBDE_ICTL_xxx). */ +#define NGBDE_IOC_INTR_CTRL _IOW(NGBDE_IOC_MAGIC, 4, __u64) + +/*! Add interrupt status/mask register for kernel to control. */ +#define NGBDE_IOC_IRQ_REG_ADD _IOW(NGBDE_IOC_MAGIC, 5, __u64) + +/*! Write to a shared interrupt mask register. */ +#define NGBDE_IOC_IRQ_MASK_WR _IOW(NGBDE_IOC_MAGIC, 6, __u64) + +/*! Map device registers in kernel space. */ +#define NGBDE_IOC_PIO_WIN_MAP _IOW(NGBDE_IOC_MAGIC, 7, __u64) + +/*! Map interrupt controller registers in kernel space. */ +#define NGBDE_IOC_IIO_WIN_MAP _IOW(NGBDE_IOC_MAGIC, 8, __u64) + +/*! Map PCI bridge registers in kernel space. */ +#define NGBDE_IOC_PAXB_WIN_MAP _IOW(NGBDE_IOC_MAGIC, 9, __u64) + +/*! Add interrupt ACK register for kernel to control. */ +#define NGBDE_IOC_INTR_ACK_REG_ADD _IOW(NGBDE_IOC_MAGIC, 10, __u64) + +/*! \} */ + +/*! IOCTL command return code for success. */ +#define NGBDE_IOC_SUCCESS 0 + +/*! IOCTL command return code for failure. */ +#define NGBDE_IOC_FAIL ((__u32)-1) + +/*! + * \name Device flags. + * \anchor NGBDE_DEV_F_xxx + */ + +/*! \{ */ + +/*! Message-signaled interrupts, PCI interrupts are operating in MSI mode. */ +#define NGBDE_DEV_F_MSI (1 << 0) + +/*! \} */ + +/*! + * \name Interrupt control commands. + * \anchor NGBDE_ICTL_xxx + */ + +/*! \{ */ + +/*! Connect interrupt handler. */ +#define NGBDE_ICTL_INTR_CONN 0 + +/*! Disconnect interrupt handler. */ +#define NGBDE_ICTL_INTR_DISC 1 + +/*! Wait for interrupt. */ +#define NGBDE_ICTL_INTR_WAIT 2 + +/*! Force waiting thread to return. */ +#define NGBDE_ICTL_INTR_STOP 3 + +/*! Clear list of interrupt status/mask registers. */ +#define NGBDE_ICTL_REGS_CLR 4 + +/*! \} */ + +/*! Kernel module information. */ +struct ngbde_ioc_mod_info_s { + + /*! IOCTL version used by kernel module. */ + __u16 version; +}; + +/*! Probing results. */ +struct ngbde_ioc_probe_info_s { + + /*! Number of switch devices. */ + __u16 num_swdev; +}; + +/*! Device information. */ +struct ngbde_ioc_dev_info_s { + + /*! Device type. */ + __u16 type; + + /*! Device flags (\ref NGBDE_DEV_F_xxx). */ + __u16 flags; + + /*! Vendor ID (typically the PCI vendor ID). */ + __u16 vendor_id; + + /*! Device ID (typically the PCI vendor ID). */ + __u16 device_id; + + /*! Device revision (typically the PCI device revision). */ + __u16 revision; + + /*! Device model (device-identification beyond PCI generic ID). */ + __u16 model; +}; + +/*! + * \name I/O resource types. + * \anchor NGBDE_IO_RSRC_xxx + */ + +/*! \{ */ + +/*! Memory-mapped I/O. */ +#define NGBDE_IO_RSRC_DEV_IO 0 + +/*! DMA memory pool. */ +#define NGBDE_IO_RSRC_DMA_MEM 1 + +/*! DMA memory pool as mapped by IOMMU. */ +#define NGBDE_IO_RSRC_DMA_BUS 2 + +/*! \} */ + +/*! + * \brief Resource ID (IOCTL input). + * + * This structure is used to query a physical address resource in the + * kernel module. The caller must provide a resource type (device I/O, + * DMA memory, etc.) and a resource instance number (e.g. a PCI BAR + * address will have multiple instances). + * + * Also see \ref ngbde_ioc_phys_addr_s. + */ +struct ngbde_ioc_rsrc_id_s { + + /*! Resource type (\ref NGBDE_IO_RSRC_xxx). */ + __u32 type; + + /*! Resource instance number. */ + __u32 inst; +}; + +/*! + * \brief Physical device address. + * + * This structure is returned in response to the \ref + * NGBDE_IOC_PHYS_ADDR command. The caller must identify the requested + * physical address using the \ref ngbde_ioc_rsrc_id_s structure. + */ +struct ngbde_ioc_phys_addr_s { + + /*! Physical address. */ + __u64 addr; + + /*! Resource size (in bytes). */ + __u32 size; +}; + +/*! Interrupt control operation */ +struct ngbde_ioc_intr_ctrl_s { + + /*! Interrupt instance for this device. */ + __u32 irq_num; + + /*! Interrupt control command. */ + __u32 cmd; +}; + +/*! Add interrupt register information. */ +struct ngbde_ioc_irq_reg_add_s { + + /*! Interrupt instance for this device. */ + __u32 irq_num; + + /*! Interrupt status register address offset. */ + __u32 status_reg; + + /*! Interrupt mask register address offset. */ + __u32 mask_reg; + + /*! Interrupt mask for interrupts handled by the kernel. */ + __u32 kmask; + + /*! Reserved for future use. */ + __u32 flags; +}; + +/*! + * \name Interrupt ACK register access flags. + * \anchor NGBDE_DEV_INTR_ACK_F_xxx + */ + +/*! \{ */ + +/*! ACK registers resides in PCI bridge I/O window. */ +#define NGBDE_DEV_INTR_ACK_F_PAXB (1 << 0) + +/*! \} */ + +/*! Add interrupt ACK register information. */ +struct ngbde_ioc_intr_ack_reg_add_s { + + /*! Interrupt instance for this device. */ + __u32 irq_num; + + /*! Interrupt ACK register address offset. */ + __u32 ack_reg; + + /*! Interrupt ACK value. */ + __u32 ack_val; + + /*! Flags to indicate ack_reg resides in PCI bridge window. */ + __u32 flags; +}; + +/*! Memory-mapped I/O window */ +struct ngbde_ioc_pio_win_s { + + /*! Physical address */ + __u64 addr; + + /*! Resource size */ + __u32 size; +}; + +/*! Interrupt mask register write */ +struct ngbde_ioc_irq_mask_wr_s { + + /*! Interrupt instance for this device. */ + __u32 irq_num; + + /*! Register offset. */ + __u32 offs; + + /*! Value to write. */ + __u32 val; +}; + +/*! IOCTL operation data. */ +union ngbde_ioc_op_s { + + /*! Get kernel module information. */ + struct ngbde_ioc_mod_info_s mod_info; + + /*! Get information about registered devices. */ + struct ngbde_ioc_probe_info_s probe_info; + + /*! Get detailed switch device information. */ + struct ngbde_ioc_dev_info_s dev_info; + + /*! Resource ID (input). */ + struct ngbde_ioc_rsrc_id_s rsrc_id; + + /*! Get a physical memory address associated with a switch device. */ + struct ngbde_ioc_phys_addr_s phys_addr; + + /*! Interrupt control command (see \ref NGBDE_ICTL_xxx). */ + struct ngbde_ioc_intr_ctrl_s intr_ctrl; + + /*! Add interrupt status/mask register for kernel to control. */ + struct ngbde_ioc_irq_reg_add_s irq_reg_add; + + /*! Add interrupt ACK register for kernel to control. */ + struct ngbde_ioc_intr_ack_reg_add_s intr_ack_reg_add; + + /*! Write to a shared interrupt mask register. */ + struct ngbde_ioc_irq_mask_wr_s irq_mask_wr; + + /*! Map device registers in kernel space. */ + struct ngbde_ioc_pio_win_s pio_win; +}; + +/*! IOCTL command message. */ +typedef struct ngbde_ioc_cmd_s { + + /*! Device handle. */ + __u32 devid; + + /*! Return code (0 means success). */ + __u32 rc; + + /*! IOCTL operation. */ + union ngbde_ioc_op_s op; +} ngbde_ioc_cmd_t; + +#endif /* NGBDE_IOCTL_H */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_kapi.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_kapi.h new file mode 100644 index 000000000000..142aa63b572c --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_kapi.h @@ -0,0 +1,169 @@ +/*! \file ngbde_kapi.h + * + * NGBDE kernel API. + * + * This file is intended for use by other kernel modules relying on the BDE. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGBDE_KAPI_H +#define NGBDE_KAPI_H + +#include + +/*! Maximum number of switch devices supported. */ +#ifndef NGBDE_NUM_SWDEV_MAX +#define NGBDE_NUM_SWDEV_MAX 16 +#endif + +/*! + * \brief Get Linux PCI device handle for a switch device. + * + * \param [in] kdev Device number. + * + * \return Linux PCI device handle or NULL if unavailable. + */ +extern struct pci_dev * +ngbde_kapi_pci_dev_get(int kdev); + +/*! + * \brief Get Linux kernel device handle for a switch device. + * + * \param [in] kdev Device number. + * + * \return Linux kernel device handle or NULL if unavailable. + */ +extern struct device * +ngbde_kapi_dma_dev_get(int kdev); + +/*! + * \brief Convert DMA bus address to virtual address. + * + * This API will convert a physical DMA bus address to a kernel + * virtual address for a memory location that belongs to one of the + * DMA memory pools allocated by the BDE module. + * + * \param [in] kdev Device number. + * \param [in] baddr Physical DMA bus address for this device. + * + * \return Virtual kernel address or NULL on error. + */ +void * +ngbde_kapi_dma_bus_to_virt(int kdev, dma_addr_t baddr); + +/*! + * \brief Convert virtual address to DMA bus address. + * + * This API will convert a kernel virtual address to a physical DMA + * bus address for a memory location that belongs to one of the DMA + * memory pools allocated by the BDE module. + * + * \param [in] kdev Device number. + * \param [in] vaddr Virtual kernel address. + * + * \return Physical DMA bus address for this device or 0 on error. + */ +dma_addr_t +ngbde_kapi_dma_virt_to_bus(int kdev, void *vaddr); + +/*! + * \brief Write a memory-mapped register from kernel driver. + * + * \param [in] kdev Device number. + * \param [in] offs Register address offset. + * \param [in] val Value to write to register. + * + * \return Nothing. + */ +extern void +ngbde_kapi_pio_write32(int kdev, uint32_t offs, uint32_t val); + +/*! + * \brief Read a memory-mapped register from kernel driver. + * + * \param [in] kdev Device number. + * \param [in] offs Register address offset. + * + * \return Value read from register. + */ +extern uint32_t +ngbde_kapi_pio_read32(int kdev, uint32_t offs); + +/*! + * \brief Get base address fo memory-mapped I/O memory. + * + * The lgical base address returned can be used with ioread32, etc. + * + * \param [in] kdev Device number. + * + * \return Logical base address or NULL if unavailable. + */ +extern void * +ngbde_kapi_pio_membase(int kdev); + +/*! + * \brief Install kernel mode interrupt handler. + * + * \param [in] kdev Device number. + * \param [in] irq_num MSI interrupt number. + * \param [in] isr_func Interrupt handler function. + * \param [in] isr_data Interrupt handler context. + * + * \retval 0 No errors + */ +extern int +ngbde_kapi_intr_connect(int kdev, unsigned int irq_num, + int (*isr_func)(void *), void *isr_data); + +/*! + * \brief Uninstall kernel mode interrupt handler. + * + * \param [in] kdev Device number. + * \param [in] irq_num MSI interrupt number. + * + * \retval 0 No errors + */ +extern int +ngbde_kapi_intr_disconnect(int kdev, unsigned int irq_num); + +/*! + * \brief Write shared interrupt mask register. + * + * This function is used by an interrupt handler when a shared + * interrupt mask register needs to be updated. + * + * Note that the mask register to access is referenced by the + * corrsponding status register. This is because the mask register may + * be different depending on the host CPU interface being used + * (e.g. PCI vs. AXI). On the other hand, the status register is the + * same irrespective of the host CPU interface. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * \param [in] status_reg Corresponding interrupt status register offset. + * \param [in] mask_val New value to write to mask register. + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_kapi_intr_mask_write(int kdev, unsigned int irq_num, + uint32_t status_reg, uint32_t mask_val); + +#endif /* NGBDE_KAPI_H */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_dev.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_dev.h new file mode 100644 index 000000000000..74d3d5b350b0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_dev.h @@ -0,0 +1,408 @@ +/*! \file ngknet_dev.h + * + * NGKNET device definitions. + * + * This file is intended for use in both kernel mode and user mode. + * + * IMPORTANT! + * All shared structures must be properly 64-bit aligned. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_DEV_H +#define NGKNET_DEV_H + +#include + +/*! Device name length */ +#define NGKNET_DEV_NAME_MAX 16 + +/*! Maximum number of virtual network devices */ +#ifndef NGKNET_NETIF_MAX +#define NUM_VDEV_MAX 128 +#else +#define NUM_VDEV_MAX NGKNET_NETIF_MAX +#endif + +/*! Maximum number of filters */ +#ifndef NGKNET_FILTER_MAX +#define NUM_FILTER_MAX 128 +#else +#define NUM_FILTER_MAX NGKNET_FILTER_MAX +#endif + +/*! + * \brief System network interface + * + * Network interface types: + * + * NGKNET_NETIF_T_VLAN + * Transmits to this interface will go to ingress PIPE of switch + * CPU port using specified VLAN ID. Packet will be switched. + * + * NGKNET_NETIF_T_PORT + * Transmits to this interface will go to unmodified to specified + * physical switch port. All switching logic is bypassed. Meta data + * should be provided when this interface is created. + * + * NGKNET_NETIF_T_META + * Transmits to this interface will be done using raw meta data + * as DMA descriptors. + * + * Network interface flags: + * + * NGKNET_NETIF_F_RCPU_ENCAP + * Use RCPU encapsulation for packets that enter and exit this + * interface. + * + * NGKNET_NETIF_F_ADD_TAG + * Add VLAN tag to packets sent directly to physical port. + * + * NGKNET_NETIF_F_BIND_CHAN + * Bind this interface to a Rx channel. + */ +/*! Max network interface name length */ +#define NGKNET_NETIF_NAME_MAX 16 +/*! Max network interface meta bytes */ +#define NGKNET_NETIF_META_MAX 16 +/*! Max netif user data in bytes */ +#define NGKNET_NETIF_USER_DATA 64 + +/*! Send packets to switch */ +#define NGKNET_NETIF_T_VLAN 0 +/*! Send packets to port */ +#define NGKNET_NETIF_T_PORT 1 +/*! Send packets with matadata attached */ +#define NGKNET_NETIF_T_META 2 + +/*! Send packets with RCPU encapsulation */ +#define NGKNET_NETIF_F_RCPU_ENCAP (1U << 0) +/*! Send packets with vlan tag */ +#define NGKNET_NETIF_F_ADD_TAG (1U << 1) +/*! Bind network interface to Rx channel */ +#define NGKNET_NETIF_F_BIND_CHAN (1U << 2) + +/*! + * \brief Network interface description. + */ +typedef struct ngknet_netif_s { + /*! This network interface ID */ + uint16_t id; + + /*! Next network interface ID */ + uint16_t next; + + /*! Network interface type */ + uint16_t type; + + /*! Network interface flags */ + uint16_t flags; + + /*! Network interface VLAN ID */ + uint16_t vlan; + + /*! Network interface MAC address */ + uint8_t macaddr[6]; + + /*! Network interface MTU */ + uint32_t mtu; + + /*! Network interface bound to channel */ + uint32_t chan; + + /*! Network interface name */ + char name[NGKNET_NETIF_NAME_MAX]; + + /*! Metadata offset from Ethernet header */ + uint16_t meta_off; + + /*! Metadata length */ + uint16_t meta_len; + + /*! Metadata used to send packets to physical port */ + uint8_t meta_data[NGKNET_NETIF_META_MAX]; + + /*! User data gotten back through callbacks */ + uint8_t user_data[NGKNET_NETIF_USER_DATA]; +} ngknet_netif_t; + +/*! + * \brief Packet filters + * + * Filters work like software TCAMs where a mask is applied to the + * source data, and the result is then compared to the filter data. + * + * Filters are checked in priority order with the lowest priority + * values being checked first (i.e. 0 is the highest priority). + * + * Filter types: + * + * NGKNET_FILTER_T_RX_PKT + * Filter data and mask are applied to the Rx DMA control block + * as well as to the Rx packet contents. + * + * Destination types: + * + * NGKNET_FILTER_DEST_T_NULL + * Packet is dropped. + * + * NGKNET_FILTER_DEST_T_NETIF + * Packet is sent to network interface with ID . + * + * NGKNET_FILTER_DEST_T_VNET + * Packet is sent to VNET in user space. + * + * Filter flags: + * + * NGKNET_FILTER_F_ANY_DATA + * When this flags is set the filter will match any packet on + * the associated unit. + * + * NGKNET_FILTER_F_STRIP_TAG + * Strip VLAN tag before packet is sent to destination. + */ +/*! Roundup to word */ +#define NGKNET_BYTES2WORDS(bytes) ((bytes + 3) / 4) + +/*! Max filter description length */ +#define NGKNET_FILTER_DESC_MAX 32 +/*! Max filter bytes size */ +#define NGKNET_FILTER_BYTES_MAX 256 +/*! Max filter words size */ +#define NGKNET_FILTER_WORDS_MAX NGKNET_BYTES2WORDS(NGKNET_FILTER_BYTES_MAX) +/*! Max filter user data in bytes */ +#define NGKNET_FILTER_USER_DATA 64 + +/*! Filter to Rx */ +#define NGKNET_FILTER_T_RX_PKT 1 + +/*! Drop packet */ +#define NGKNET_FILTER_DEST_T_NULL 0 +/*! Send packet to netif */ +#define NGKNET_FILTER_DEST_T_NETIF 1 +/*! Send packet to VNET */ +#define NGKNET_FILTER_DEST_T_VNET 2 +/*! Send packet to kernel callback function (BCMPKT_DEST_T_CALLBACK) */ +#define NGKNET_FILTER_DEST_T_CB 3 + +/*! Match any data */ +#define NGKNET_FILTER_F_ANY_DATA (1U << 0) +/*! Strip vlan tag */ +#define NGKNET_FILTER_F_STRIP_TAG (1U << 1) +/*! Match Rx channel */ +#define NGKNET_FILTER_F_MATCH_CHAN (1U << 2) +/*! Filter created with raw metadata */ +#define NGKNET_FILTER_F_RAW_PMD (1U << 15) + +/*! + * \brief Filter description. + */ +typedef struct ngknet_filter_s { + /*! This filter ID */ + uint16_t id; + + /*! Next filter ID */ + uint16_t next; + + /*! Filter type. Refer to \ref NGKNET_FILTER_T_XXX. */ + uint16_t type; + + /*! Filter flags. Refer to \ref NGKNET_FILTER_F_XXX. */ + uint16_t flags; + + /*! Filter priority */ + uint32_t priority; + + /*! Filter belong to */ + uint32_t chan; + + /*! Filter description */ + char desc[NGKNET_FILTER_DESC_MAX]; + + /*! Destination type. Refer to \ref NGKNET_FILTER_DEST_T_XXX. */ + uint16_t dest_type; + + /*! Destination network interface ID */ + uint16_t dest_id; + + /*! Destination network interface protocol type */ + uint16_t dest_proto; + + /*! Mirror type */ + uint16_t mirror_type; + + /*! Mirror network interface ID */ + uint16_t mirror_id; + + /*! Mirror network interface protocol type */ + uint16_t mirror_proto; + + /*! Out band data offset */ + uint16_t oob_data_offset; + + /*! Out band data size */ + uint16_t oob_data_size; + + /*! Packet data offset */ + uint16_t pkt_data_offset; + + /*! Packet data size */ + uint16_t pkt_data_size; + + /*! Filtering data */ + union { + uint8_t b[NGKNET_FILTER_BYTES_MAX]; + uint32_t w[NGKNET_FILTER_WORDS_MAX]; + } data; + + /*! Filtering mask */ + union { + uint8_t b[NGKNET_FILTER_BYTES_MAX]; + uint32_t w[NGKNET_FILTER_WORDS_MAX]; + } mask; + + /*! User data gotten back through callbacks */ + uint8_t user_data[NGKNET_FILTER_USER_DATA]; +} ngknet_filter_t; + +/*! + * \brief Device configure structure. + */ +typedef struct ngknet_dev_cfg_s { + /*! Device name */ + char name[NGKNET_DEV_NAME_MAX]; + + /*! Device type string */ + char type_str[NGKNET_DEV_NAME_MAX]; + + /*! Device ID */ + uint32_t dev_id; + + /*! Device mode */ + dev_mode_t mode; + + /*! Number of groups */ + uint32_t nb_grp; + + /*! Bitmap of groups */ + uint32_t bm_grp; + + /*! Rx packet header size */ + uint32_t rx_ph_size; + + /*! Tx packet header size */ + uint32_t tx_ph_size; + + /*! Base network interface */ + ngknet_netif_t base_netif; +} ngknet_dev_cfg_t; + +/*! + * \brief Channel configure structure. + */ +typedef struct ngknet_chan_cfg_s { + /*! Channel number */ + int chan; + + /*! Number of descriptors */ + uint32_t nb_desc; + + /*! Rx buffer size */ + uint32_t rx_buf_size; + + /*! Channel control */ + uint32_t chan_ctrl; + /*! Packet_byte_swap */ +#define NGKNET_PKT_BYTE_SWAP (1 << 0) + /*! Non packet_byte_swap */ +#define NGKNET_OTH_BYTE_SWAP (1 << 1) + /*! Header_byte_swap */ +#define NGKNET_HDR_BYTE_SWAP (1 << 2) + + /*! Rx or Tx */ + int dir; + /*! Rx channel */ +#define NGKNET_RX_CHAN 0 + /*! Tx channel */ +#define NGKNET_TX_CHAN 1 +} ngknet_chan_cfg_t; + +/*! + * \brief RCPU header structure. + */ +struct ngknet_rcpu_hdr { + /*! Destination MAC address */ + uint8_t dst_mac[6]; + + /*! Source MAC address */ + uint8_t src_mac[6]; + + /*! VLAN TPID */ + uint16_t vlan_tpid; + + /*! VLAN TCI */ + uint16_t vlan_tci; + + /*! Ethernet type */ + uint16_t eth_type; + + /*! Packet signature */ + uint16_t pkt_sig; + + /*! Operation code */ + uint8_t op_code; + + /*! Flags */ + uint8_t flags; + + /*! Transaction number */ + uint16_t trans_id; + + /*! Packet data length */ + uint16_t data_len; + + /*! Reserved must be 0 */ + uint16_t rsvd0; + + /*! packet meta data length */ + uint8_t meta_len; + + /*! Transmission queue number */ + uint8_t queue_id; + + /*! Reserved must be 0 */ + uint16_t rsvd1; +}; + +/*! RCPU Rx operation */ +#define RCPU_OPCODE_RX 0x10 +/*! RCPU Tx operation */ +#define RCPU_OPCODE_TX 0x20 + +/*! RCPU purge flag */ +#define RCPU_FLAG_PURGE (1 << 0) +/*! RCPU pause flag */ +#define RCPU_FLAG_PAUSE (1 << 1) +/*! RCPU modhdr flag */ +#define RCPU_FLAG_MODHDR (1 << 2) +/*! RCPU bind queue flag */ +#define RCPU_FLAG_BIND_QUE (1 << 3) + +#endif /* NGKNET_DEV_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_ioctl.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_ioctl.h new file mode 100644 index 000000000000..6da52c778191 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_ioctl.h @@ -0,0 +1,112 @@ +/*! \file ngknet_ioctl.h + * + * NGKNET I/O control definitions. + * + * This file is intended for use in both kernel mode and user mode. + * + * IMPORTANT! + * All shared structures must be properly 64-bit aligned. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_IOCTL_H +#define NGKNET_IOCTL_H + +/*! Module information */ +#define NGKNET_MODULE_NAME "linux_ngknet" +#define NGKNET_MODULE_MAJOR 121 + +/*! Must be updated if backward compatibility is broken */ +#define NGKNET_IOC_VERSION 2 + +/*! Max number of input arguments */ +#define NGKNET_IOC_IARG_MAX 2 + +#define NGKNET_IOC_MAGIC 'K' + +#define NGKNET_VERSION_GET _IOR(NGKNET_IOC_MAGIC, 0xa0, unsigned int) +#define NGKNET_RX_RATE_LIMIT _IOWR(NGKNET_IOC_MAGIC, 0xa1, unsigned int) +#define NGKNET_DEV_INIT _IOWR(NGKNET_IOC_MAGIC, 0xb0, unsigned int) +#define NGKNET_DEV_DEINIT _IOWR(NGKNET_IOC_MAGIC, 0xb1, unsigned int) +#define NGKNET_DEV_SUSPEND _IOWR(NGKNET_IOC_MAGIC, 0xb2, unsigned int) +#define NGKNET_DEV_RESUME _IOWR(NGKNET_IOC_MAGIC, 0xb3, unsigned int) +#define NGKNET_DEV_VNET_WAIT _IOWR(NGKNET_IOC_MAGIC, 0xb4, unsigned int) +#define NGKNET_DEV_HNET_WAKE _IOWR(NGKNET_IOC_MAGIC, 0xb5, unsigned int) +#define NGKNET_DEV_VNET_DOCK _IOWR(NGKNET_IOC_MAGIC, 0xb6, unsigned int) +#define NGKNET_DEV_VNET_UNDOCK _IOWR(NGKNET_IOC_MAGIC, 0xb7, unsigned int) +#define NGKNET_QUEUE_CONFIG _IOWR(NGKNET_IOC_MAGIC, 0xc0, unsigned int) +#define NGKNET_QUEUE_QUERY _IOR(NGKNET_IOC_MAGIC, 0xc1, unsigned int) +#define NGKNET_RCPU_CONFIG _IOWR(NGKNET_IOC_MAGIC, 0xc2, unsigned int) +#define NGKNET_RCPU_GET _IOR(NGKNET_IOC_MAGIC, 0xc3, unsigned int) +#define NGKNET_NETIF_CREATE _IOWR(NGKNET_IOC_MAGIC, 0xd0, unsigned int) +#define NGKNET_NETIF_DESTROY _IOWR(NGKNET_IOC_MAGIC, 0xd1, unsigned int) +#define NGKNET_NETIF_GET _IOR(NGKNET_IOC_MAGIC, 0xd2, unsigned int) +#define NGKNET_NETIF_NEXT _IOR(NGKNET_IOC_MAGIC, 0xd3, unsigned int) +#define NGKNET_NETIF_LINK_SET _IOW(NGKNET_IOC_MAGIC, 0xd4, unsigned int) +#define NGKNET_FILT_CREATE _IOWR(NGKNET_IOC_MAGIC, 0xe0, unsigned int) +#define NGKNET_FILT_DESTROY _IOWR(NGKNET_IOC_MAGIC, 0xe1, unsigned int) +#define NGKNET_FILT_GET _IOR(NGKNET_IOC_MAGIC, 0xe2, unsigned int) +#define NGKNET_FILT_NEXT _IOR(NGKNET_IOC_MAGIC, 0xe3, unsigned int) +#define NGKNET_INFO_GET _IOR(NGKNET_IOC_MAGIC, 0xf0, unsigned int) +#define NGKNET_STATS_GET _IOR(NGKNET_IOC_MAGIC, 0xf1, unsigned int) +#define NGKNET_STATS_RESET _IOWR(NGKNET_IOC_MAGIC, 0xf2, unsigned int) +#define NGKNET_PTP_DEV_CTRL _IOWR(NGKNET_IOC_MAGIC, 0x90, unsigned int) + +/*! Kernel module information. */ +struct ngknet_ioc_mod_info { + /*! IOCTL version used by kernel module */ + uint32_t version; +}; + +/*! Data transmission */ +struct ngknet_ioc_data_xmit { + /*! Data buffer address */ + uint64_t buf; + + /*! Data buffer length */ + uint32_t len; +}; + +/*! IOCTL operations */ +union ngknet_ioc_op { + /*! Get module info */ + struct ngknet_ioc_mod_info info; + /*! Transmit data */ + struct ngknet_ioc_data_xmit data; +}; + +/*! + * \brief NGKNET IOCTL command message. + */ +struct ngknet_ioctl { + /*! Device number */ + uint32_t unit; + + /*! Return code (0 means success) */ + uint32_t rc; + + /*! Input arguments */ + int iarg[NGKNET_IOC_IARG_MAX]; + + /*! IOCTL operation */ + union ngknet_ioc_op op; +}; + +#endif /* NGKNET_IOCTL_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/net/psample.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/net/psample.h new file mode 100644 index 000000000000..64188c95daeb --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/net/psample.h @@ -0,0 +1,24 @@ +#ifndef __NET_PSAMPLE_H +#define __NET_PSAMPLE_H + +#include +#include +#include +#include + +struct psample_group { + struct list_head list; + struct net *net; + u32 group_num; + u32 refcount; + u32 seq; +}; + +extern struct psample_group *psample_group_get(struct net *net, u32 group_num); +extern void psample_group_put(struct psample_group *group); + +extern void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, + u32 trunc_size, int in_ifindex, int out_ifindex, + u32 sample_rate); + +#endif /* __NET_PSAMPLE_H */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/uapi/linux/psample.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/uapi/linux/psample.h new file mode 100644 index 000000000000..ed48996ec0e8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/uapi/linux/psample.h @@ -0,0 +1,35 @@ +#ifndef __UAPI_PSAMPLE_H +#define __UAPI_PSAMPLE_H + +enum { + /* sampled packet metadata */ + PSAMPLE_ATTR_IIFINDEX, + PSAMPLE_ATTR_OIFINDEX, + PSAMPLE_ATTR_ORIGSIZE, + PSAMPLE_ATTR_SAMPLE_GROUP, + PSAMPLE_ATTR_GROUP_SEQ, + PSAMPLE_ATTR_SAMPLE_RATE, + PSAMPLE_ATTR_DATA, + + /* commands attributes */ + PSAMPLE_ATTR_GROUP_REFCOUNT, + + __PSAMPLE_ATTR_MAX +}; + +enum psample_command { + PSAMPLE_CMD_SAMPLE, + PSAMPLE_CMD_GET_GROUP, + PSAMPLE_CMD_NEW_GROUP, + PSAMPLE_CMD_DEL_GROUP, +}; + +/* Can be overridden at runtime by module option */ +#define PSAMPLE_ATTR_MAX (__PSAMPLE_ATTR_MAX - 1) + +#define PSAMPLE_NL_MCGRP_CONFIG_NAME "config" +#define PSAMPLE_NL_MCGRP_SAMPLE_NAME "packets" +#define PSAMPLE_GENL_NAME "psample" +#define PSAMPLE_GENL_VERSION 1 + +#endif diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/Kbuild b/platform/broadcom/saibcm-modules/sdklt/linux/knet/Kbuild new file mode 100644 index 000000000000..fe5d5c5bfefc --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/Kbuild @@ -0,0 +1,44 @@ +# -*- Kbuild -*- +# +# Linux KNET module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# 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. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +obj-m := linux_ngknet.o + +ccflags-y := $(KNET_CPPFLAGS) $(LKM_CFLAGS) \ + -I$(SDK)/shr/include \ + -I$(SDK)/bcmdrd/include \ + -I$(SDK)/linux/include \ + -I$(SDK)/linux/knet/include \ + -I$(SDK)/linux/knet + +linux_ngknet-y := $(CHIP_OBJS) \ + bcmcnet_cmicd_pdma_hw.o \ + bcmcnet_cmicd_pdma_rxtx.o \ + bcmcnet_cmicx_pdma_hw.o \ + bcmcnet_cmicx_pdma_rxtx.o \ + bcmcnet_core.o \ + bcmcnet_dev.o \ + bcmcnet_rxtx.o \ + ngknet_buff.o \ + ngknet_callback.o \ + ngknet_extra.o \ + ngknet_linux.o \ + ngknet_main.o \ + ngknet_procfs.o \ + ngknet_ptp.o diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/Makefile b/platform/broadcom/saibcm-modules/sdklt/linux/knet/Makefile new file mode 100644 index 000000000000..785b81fadb17 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/Makefile @@ -0,0 +1,105 @@ +# -*- Makefile -*- +# +# Linux KNET module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# 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. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +CNETDIR = $(SDK)/bcmcnet +KNETDIR = $(SDK)/linux/knet +SRCIDIR = $(CNETDIR)/include/bcmcnet +DSTIDIR = $(KNETDIR)/include/bcmcnet + +# Change comma-separated list to space-separated list +comma = , +empty = +space = $(empty) $(empty) +spc_sep = $(subst $(comma),$(space),$1) + +# Convert chip name to uppercase +chip_uc = $(subst a,A,$(subst b,B,$(subst c,C,$(subst m,M,$1)))) + +# Convert chip name to lowercase +chip_lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst M,m,$1)))) + +# +# If SDK_CHIPS is defined, then exclude any chip directory which is +# not part of this list. +# +KNET_CHIPS := $(subst $(CNETDIR)/chip/,,$(wildcard $(CNETDIR)/chip/bcm*)) +ifdef SDK_CHIPS +# Create space-separated lowercase version of chip list +SDK_CHIPS_SPC := $(call spc_sep,$(SDK_CHIPS)) +SDK_CHIPS_LC := $(call chip_lc,$(SDK_CHIPS_SPC)) +# Configure build flags according to chip list +KNET_CHIPS := $(filter $(SDK_CHIPS_LC),$(KNET_CHIPS)) +KNET_CPPFLAGS := CHIP_DEFAULT=0 $(addsuffix =1,$(call chip_uc,$(KNET_CHIPS))) +KNET_CPPFLAGS := $(addprefix -DBCMDRD_CONFIG_INCLUDE_,$(KNET_CPPFLAGS)) +export KNET_CPPFLAGS +endif + +.PHONY: mklinks rmlinks + +knet: mklinks + $(MAKE) all + +# +# Suppress symlink error messages. +# +# Note that we do not use "ln -f" as this may cause failures if +# multiple builds are done in parallel on the same source tree. +# +R = 2>/dev/null + +mklinks: + mkdir -p $(DSTIDIR) + -ln -s $(KNETDIR)/ngknet_dep.h $(DSTIDIR)/bcmcnet_dep.h $(R) + -ln -s $(KNETDIR)/ngknet_buff.h $(DSTIDIR)/bcmcnet_buff.h $(R) + -ln -s $(SRCIDIR)/bcmcnet_types.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_internal.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_core.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_dev.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_rxtx.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_cmicd.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_cmicx.h $(DSTIDIR) $(R) + -ln -s $(CNETDIR)/chip/*/*attach.c $(KNETDIR) $(R) + -ln -s $(CNETDIR)/hmi/cmicd/*.c $(KNETDIR) $(R) + -ln -s $(CNETDIR)/hmi/cmicx/*.c $(KNETDIR) $(R) + -ln -s $(CNETDIR)/main/bcmcnet_core.c $(KNETDIR) $(R) + -ln -s $(CNETDIR)/main/bcmcnet_dev.c $(KNETDIR) $(R) + -ln -s $(CNETDIR)/main/bcmcnet_rxtx.c $(KNETDIR) $(R) + +rmlinks: + -rm -f bcm* + -rm -rf include + +CHIP_SRCS := $(addsuffix _pdma_attach.c,$(KNET_CHIPS)) +CHIP_OBJS ?= $(patsubst %.c, %.o, $(CHIP_SRCS)) +export CHIP_OBJS + +include Kbuild + +ifeq ($(KERNELRELEASE),) + +MOD_NAME = linux_ngknet + +include $(SDK)/make/lkm.mk + +endif + +.PHONY: distclean + +distclean: rmlinks diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.c new file mode 100644 index 000000000000..750fff69caf3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.c @@ -0,0 +1,326 @@ +/*! \file ngknet_buff.c + * + * Utility routines for NGKNET packet buffer management in Linux kernel mode. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include "ngknet_main.h" +#include "ngknet_buff.h" + +/*! + * Allocate coherent memory + */ +static void * +bcmcnet_ring_buf_alloc(struct pdma_dev *dev, uint32_t size, dma_addr_t *dma) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + + return dma_alloc_coherent(kdev->dev, size, dma, GFP_KERNEL); +} + +/*! + * Free coherent memory + */ +static void +bcmcnet_ring_buf_free(struct pdma_dev *dev, uint32_t size, void *addr, dma_addr_t dma) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + + dma_free_coherent(kdev->dev, size, addr, dma); +} + +/*! + * Allocate Rx buffer + */ +static int +bcmcnet_rx_buf_alloc(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + dma_addr_t dma; + struct page *page; + struct sk_buff *skb; + + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + page = kal_dev_alloc_page(); + if (unlikely(!page)) { + return SHR_E_MEMORY; + } + dma = dma_map_page(kdev->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(kdev->dev, dma))) { + __free_page(page); + return SHR_E_MEMORY; + } + pbuf->dma = dma; + pbuf->page = page; + pbuf->page_offset = 0; + } else { + skb = netdev_alloc_skb(kdev->net_dev, PDMA_RXB_RESV + pbuf->adj + rxq->buf_size); + if (unlikely(!skb)) { + return SHR_E_MEMORY; + } + skb_reserve(skb, PDMA_RXB_ALIGN - (((unsigned long)skb->data) & (PDMA_RXB_ALIGN - 1))); + pbuf->skb = skb; + pbuf->pkb = (struct pkt_buf *)skb->data; + dma = dma_map_single(kdev->dev, &pbuf->pkb->data + pbuf->adj, rxq->buf_size, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(kdev->dev, dma))) { + dev_kfree_skb_any(skb); + return SHR_E_MEMORY; + } + pbuf->dma = dma; + } + + return SHR_E_NONE; +} + +/*! + * Get Rx buffer DMA address + */ +static void +bcmcnet_rx_buf_dma(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, dma_addr_t *addr) +{ + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + *addr = pbuf->dma + pbuf->page_offset + PDMA_RXB_RESV + pbuf->adj; + } else { + *addr = pbuf->dma; + } +} + +/*! + * Check Rx buffer + */ +static int +bcmcnet_rx_buf_avail(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf) +{ + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + pbuf->skb = NULL; + } + + return pbuf->dma != 0; +} + +/*! + * Get Rx buffer + */ +static struct pkt_hdr * +bcmcnet_rx_buf_get(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, int len) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + struct sk_buff *skb; + + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + if (pbuf->skb) { + return &pbuf->pkb->pkh; + } + skb = kal_build_skb(page_address(pbuf->page) + pbuf->page_offset, + PDMA_SKB_RESV + pbuf->adj + rxq->buf_size); + if (unlikely(!skb)) { + return NULL; + } + skb_reserve(skb, PDMA_RXB_ALIGN); + dma_sync_single_range_for_cpu(kdev->dev, pbuf->dma, pbuf->page_offset, + PDMA_PAGE_BUF_MAX, DMA_FROM_DEVICE); + pbuf->skb = skb; + pbuf->pkb = (struct pkt_buf *)skb->data; + + /* Try to reuse this page */ + if (unlikely(page_count(pbuf->page) != 1)) { + dma_unmap_page(kdev->dev, pbuf->dma, PAGE_SIZE, DMA_FROM_DEVICE); + pbuf->dma = 0; + } else { + pbuf->page_offset ^= PDMA_PAGE_BUF_MAX; + page_ref_inc(pbuf->page); + dma_sync_single_range_for_device(kdev->dev, pbuf->dma, pbuf->page_offset, + PDMA_PAGE_BUF_MAX, DMA_FROM_DEVICE); + } + } else { + if (!pbuf->dma) { + return &pbuf->pkb->pkh; + } + skb = pbuf->skb; + dma_unmap_single(kdev->dev, pbuf->dma, rxq->buf_size, DMA_FROM_DEVICE); + pbuf->dma = 0; + } + + skb_put(skb, PKT_HDR_SIZE + pbuf->adj + len); + + return &pbuf->pkb->pkh; +} + +/*! + * Put Rx buffer + */ +static int +bcmcnet_rx_buf_put(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, int len) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + dma_addr_t dma; + struct sk_buff *skb; + + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + dev_kfree_skb_any(pbuf->skb); + } else { + skb = pbuf->skb; + dma = dma_map_single(kdev->dev, &pbuf->pkb->data + pbuf->adj, + rxq->buf_size, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(kdev->dev, dma))) { + dev_kfree_skb_any(skb); + pbuf->dma = 0; + return SHR_E_MEMORY; + } + pbuf->dma = dma; + skb_trim(skb, skb->len - (PKT_HDR_SIZE + pbuf->adj + len)); + } + + return SHR_E_NONE; +} + +/*! + * Free Rx buffer + */ +static void +bcmcnet_rx_buf_free(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + dma_unmap_single(kdev->dev, pbuf->dma, PAGE_SIZE, DMA_FROM_DEVICE); + __free_page(pbuf->page); + } else { + dma_unmap_single(kdev->dev, pbuf->dma, rxq->buf_size, DMA_FROM_DEVICE); + dev_kfree_skb_any(pbuf->skb); + } + + pbuf->dma = 0; + pbuf->page = NULL; + pbuf->page_offset = 0; + pbuf->skb = NULL; + pbuf->pkb = NULL; + pbuf->adj = 0; +} + +/*! + * Get Rx buffer mode + */ +static enum buf_mode +bcmcnet_rx_buf_mode(struct pdma_dev *dev, struct pdma_rx_queue *rxq) +{ + uint32_t len; + + len = dev->rx_ph_size ? rxq->buf_size : rxq->buf_size + PDMA_RXB_META; + if (PDMA_RXB_SIZE(len) <= PDMA_PAGE_BUF_MAX && PAGE_SIZE < 8192 && + kal_support_paged_skb()) { + return PDMA_BUF_MODE_PAGE; + } + + return PDMA_BUF_MODE_SKB; +} + +/*! + * Get Tx buffer + */ +static struct pkt_hdr * +bcmcnet_tx_buf_get(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf, void *buf) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + struct sk_buff *skb = (struct sk_buff *)buf; + struct pkt_buf *pkb = (struct pkt_buf *)skb->data; + dma_addr_t dma; + + pbuf->len = pkb->pkh.data_len + (pbuf->adj ? pkb->pkh.meta_len : 0); + dma = dma_map_single(kdev->dev, &pkb->data + (pbuf->adj ? 0 : pkb->pkh.meta_len), + pbuf->len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(kdev->dev, dma))) { + dev_kfree_skb_any(skb); + return NULL; + } + pbuf->dma = dma; + pbuf->skb = skb; + pbuf->pkb = pkb; + + return &pkb->pkh; +} + +/*! + * Get Tx buffer DMA address + */ +static void +bcmcnet_tx_buf_dma(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf, dma_addr_t *addr) +{ + *addr = pbuf->dma; +} + +/*! + * Free Tx buffer + */ +static void +bcmcnet_tx_buf_free(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + + dma_unmap_single(kdev->dev, pbuf->dma, pbuf->len, DMA_TO_DEVICE); + if (skb_shinfo(pbuf->skb)->tx_flags & SKBTX_IN_PROGRESS) { + skb_queue_tail(&kdev->ptp_tx_queue, pbuf->skb); + schedule_work(&kdev->ptp_tx_work); + } else { + dev_kfree_skb_any(pbuf->skb); + } + + pbuf->dma = 0; + pbuf->len = 0; + pbuf->skb = NULL; + pbuf->pkb = NULL; + pbuf->adj = 0; +} + +static const struct pdma_buf_mngr buf_mngr = { + .ring_buf_alloc = bcmcnet_ring_buf_alloc, + .ring_buf_free = bcmcnet_ring_buf_free, + .rx_buf_alloc = bcmcnet_rx_buf_alloc, + .rx_buf_dma = bcmcnet_rx_buf_dma, + .rx_buf_avail = bcmcnet_rx_buf_avail, + .rx_buf_get = bcmcnet_rx_buf_get, + .rx_buf_put = bcmcnet_rx_buf_put, + .rx_buf_free = bcmcnet_rx_buf_free, + .rx_buf_mode = bcmcnet_rx_buf_mode, + .tx_buf_get = bcmcnet_tx_buf_get, + .tx_buf_dma = bcmcnet_tx_buf_dma, + .tx_buf_free = bcmcnet_tx_buf_free, +}; + +/*! + * Open a device + */ +void +bcmcnet_buf_mngr_init(struct pdma_dev *dev) +{ + dev->ctrl.buf_mngr = (struct pdma_buf_mngr *)&buf_mngr; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.h new file mode 100644 index 000000000000..54768e826917 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.h @@ -0,0 +1,83 @@ +/*! \file ngknet_buff.h + * + * Generic data structure definitions for NGKNET packet buffer management. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_BUFF_H +#define NGKNET_BUFF_H + +/*! Rx buffer align size */ +#define PDMA_RXB_ALIGN 32 +/*! Rx buffer reserved size */ +#define PDMA_RXB_RESV (PDMA_RXB_ALIGN + PKT_HDR_SIZE) +/*! Rx SKB reserved size */ +#define PDMA_SKB_RESV (PDMA_RXB_RESV + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) +/*! Rx buffer size */ +#define PDMA_RXB_SIZE(len) (SKB_DATA_ALIGN(len + NET_SKB_PAD) + PDMA_SKB_RESV) +/*! Rx reserved meta size */ +#define PDMA_RXB_META 64 +/*! Max page buffer size */ +#define PDMA_PAGE_BUF_MAX 2048 + +/*! + * \brief Rx buffer. + */ +struct pdma_rx_buf { + /*! DMA address */ + dma_addr_t dma; + + /*! Buffer page */ + struct page *page; + + /*! Buffer page offset */ + unsigned int page_offset; + + /*! Rx SKB */ + struct sk_buff *skb; + + /*! Packet buffer point */ + struct pkt_buf *pkb; + + /*! Packet buffer adjustment */ + uint32_t adj; +}; + +/*! + * \brief Tx buffer. + */ +struct pdma_tx_buf { + /*! DMA address */ + dma_addr_t dma; + + /*! Tx buffer length */ + uint32_t len; + + /*! Tx SKB */ + struct sk_buff *skb; + + /*! Packet buffer point */ + struct pkt_buf *pkb; + + /*! Packet buffer adjustment */ + uint32_t adj; +}; + +#endif /* NGKNET_BUFF_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.c new file mode 100644 index 000000000000..21512a51fbd2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.c @@ -0,0 +1,315 @@ +/*! \file ngknet_callback.c + * + * Utility routines for NGKNET callbacks. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include "ngknet_callback.h" + +static struct ngknet_callback_ctrl callback_ctrl; + +int +ngknet_callback_control_get(struct ngknet_callback_ctrl **cbc) +{ + *cbc = &callback_ctrl; + + return 0; +} + +/*! + * Call-back interfaces for other Linux kernel drivers. + * + * The Rx call-back allows an external module to modify packet contents + * before it is handed off to the Linux network stack. + * + * The Tx call-back allows an external module to modify packet contents + * before it is injected into the switch. + */ + +int +ngknet_rx_cb_register(ngknet_rx_cb_f rx_cb) +{ + if (callback_ctrl.rx_cb != NULL) { + return -1; + } + callback_ctrl.rx_cb = rx_cb; + + return 0; +} + +int +ngknet_rx_cb_unregister(ngknet_rx_cb_f rx_cb) +{ + if (rx_cb == NULL || callback_ctrl.rx_cb != rx_cb) { + return -1; + } + callback_ctrl.rx_cb = NULL; + + return 0; +} + +int +ngknet_tx_cb_register(ngknet_tx_cb_f tx_cb) +{ + if (callback_ctrl.tx_cb != NULL) { + return -1; + } + callback_ctrl.tx_cb = tx_cb; + + return 0; +} + +int +ngknet_tx_cb_unregister(ngknet_tx_cb_f tx_cb) +{ + if (tx_cb == NULL || callback_ctrl.tx_cb != tx_cb) { + return -1; + } + callback_ctrl.tx_cb = NULL; + + return 0; +} + +int +ngknet_ptp_rx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb) +{ + if (callback_ctrl.ptp_rx_config_set_cb != NULL) { + return -1; + } + callback_ctrl.ptp_rx_config_set_cb = ptp_rx_config_set_cb; + + return 0; +} + +int +ngknet_ptp_rx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb) +{ + if (ptp_rx_config_set_cb == NULL || + callback_ctrl.ptp_rx_config_set_cb != ptp_rx_config_set_cb) { + return -1; + } + callback_ctrl.ptp_rx_config_set_cb = NULL; + + return 0; +} + +int +ngknet_ptp_tx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb) +{ + if (callback_ctrl.ptp_tx_config_set_cb != NULL) { + return -1; + } + callback_ctrl.ptp_tx_config_set_cb = ptp_tx_config_set_cb; + + return 0; +} + +int +ngknet_ptp_tx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb) +{ + if (ptp_tx_config_set_cb == NULL || + callback_ctrl.ptp_tx_config_set_cb != ptp_tx_config_set_cb) { + return -1; + } + callback_ctrl.ptp_tx_config_set_cb = NULL; + + return 0; +} + +int +ngknet_ptp_rx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb) +{ + if (callback_ctrl.ptp_rx_hwts_get_cb != NULL) { + return -1; + } + callback_ctrl.ptp_rx_hwts_get_cb = ptp_rx_hwts_get_cb; + + return 0; +} + +int +ngknet_ptp_rx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb) +{ + if (ptp_rx_hwts_get_cb == NULL || + callback_ctrl.ptp_rx_hwts_get_cb != ptp_rx_hwts_get_cb) { + return -1; + } + callback_ctrl.ptp_rx_hwts_get_cb = NULL; + + return 0; +} + +int +ngknet_ptp_tx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb) +{ + if (callback_ctrl.ptp_tx_hwts_get_cb != NULL) { + return -1; + } + callback_ctrl.ptp_tx_hwts_get_cb = ptp_tx_hwts_get_cb; + + return 0; +} + +int +ngknet_ptp_tx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb) +{ + if (ptp_tx_hwts_get_cb == NULL || + callback_ctrl.ptp_tx_hwts_get_cb != ptp_tx_hwts_get_cb) { + return -1; + } + callback_ctrl.ptp_tx_hwts_get_cb = NULL; + + return 0; +} + +int +ngknet_ptp_tx_meta_set_cb_register(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb) +{ + if (callback_ctrl.ptp_tx_meta_set_cb != NULL) { + return -1; + } + callback_ctrl.ptp_tx_meta_set_cb = ptp_tx_meta_set_cb; + + return 0; +} + +int +ngknet_ptp_tx_meta_set_cb_unregister(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb) +{ + if (ptp_tx_meta_set_cb == NULL || + callback_ctrl.ptp_tx_meta_set_cb != ptp_tx_meta_set_cb) { + return -1; + } + callback_ctrl.ptp_tx_meta_set_cb = NULL; + + return 0; +} + +int +ngknet_ptp_phc_index_get_cb_register(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb) +{ + if (callback_ctrl.ptp_phc_index_get_cb != NULL) { + return -1; + } + callback_ctrl.ptp_phc_index_get_cb = ptp_phc_index_get_cb; + + return 0; +} + +int +ngknet_ptp_phc_index_get_cb_unregister(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb) +{ + if (ptp_phc_index_get_cb == NULL || + callback_ctrl.ptp_phc_index_get_cb != ptp_phc_index_get_cb) { + return -1; + } + callback_ctrl.ptp_phc_index_get_cb = NULL; + + return 0; +} + +int +ngknet_ptp_dev_ctrl_cb_register(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb) +{ + if (callback_ctrl.ptp_dev_ctrl_cb != NULL) { + return -1; + } + callback_ctrl.ptp_dev_ctrl_cb = ptp_dev_ctrl_cb; + + return 0; +} + +int +ngknet_ptp_dev_ctrl_cb_unregister(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb) +{ + if (ptp_dev_ctrl_cb == NULL || + callback_ctrl.ptp_dev_ctrl_cb != ptp_dev_ctrl_cb) { + return -1; + } + callback_ctrl.ptp_dev_ctrl_cb = NULL; + + return 0; +} + +int +ngknet_netif_create_cb_register(ngknet_netif_cb_f netif_cb) +{ + if (callback_ctrl.netif_create_cb != NULL) { + return -1; + } + callback_ctrl.netif_create_cb = netif_cb; + + return 0; +} + +int +ngknet_netif_create_cb_unregister(ngknet_netif_cb_f netif_cb) +{ + if (netif_cb == NULL || callback_ctrl.netif_create_cb != netif_cb) { + return -1; + } + callback_ctrl.netif_create_cb = NULL; + + return 0; +} + +int +ngknet_netif_destroy_cb_register(ngknet_netif_cb_f netif_cb) +{ + if (callback_ctrl.netif_destroy_cb != NULL) { + return -1; + } + callback_ctrl.netif_destroy_cb = netif_cb; + + return 0; +} + +int +ngknet_netif_destroy_cb_unregister(ngknet_netif_cb_f netif_cb) +{ + if (netif_cb == NULL || callback_ctrl.netif_destroy_cb != netif_cb) { + return -1; + } + callback_ctrl.netif_destroy_cb = NULL; + + return 0; +} + +EXPORT_SYMBOL(ngknet_rx_cb_register); +EXPORT_SYMBOL(ngknet_rx_cb_unregister); +EXPORT_SYMBOL(ngknet_tx_cb_register); +EXPORT_SYMBOL(ngknet_tx_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_rx_config_set_cb_register); +EXPORT_SYMBOL(ngknet_ptp_rx_config_set_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_tx_config_set_cb_register); +EXPORT_SYMBOL(ngknet_ptp_tx_config_set_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_rx_hwts_get_cb_register); +EXPORT_SYMBOL(ngknet_ptp_rx_hwts_get_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_tx_hwts_get_cb_register); +EXPORT_SYMBOL(ngknet_ptp_tx_hwts_get_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_tx_meta_set_cb_register); +EXPORT_SYMBOL(ngknet_ptp_tx_meta_set_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_phc_index_get_cb_register); +EXPORT_SYMBOL(ngknet_ptp_phc_index_get_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_dev_ctrl_cb_register); +EXPORT_SYMBOL(ngknet_ptp_dev_ctrl_cb_unregister); +EXPORT_SYMBOL(ngknet_netif_create_cb_register); +EXPORT_SYMBOL(ngknet_netif_create_cb_unregister); +EXPORT_SYMBOL(ngknet_netif_destroy_cb_register); +EXPORT_SYMBOL(ngknet_netif_destroy_cb_unregister); diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.h new file mode 100644 index 000000000000..54583adffa36 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.h @@ -0,0 +1,364 @@ +/*! \file ngknet_callback.h + * + * Data structure definitions for NGKNET callbacks. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_CALLBACK_H +#define NGKNET_CALLBACK_H + +#include +#include "ngknet_main.h" + +/*! + * \brief NGKNET callback description. + */ +struct ngknet_callback_desc { + /*! Device number */ + int dev_no; + + /*! Device ID */ + uint32_t dev_id; + + /*! Device type string */ + const char *type_str; + + /*! Network interface private data */ + struct ngknet_private *priv; + + /*! Matched filter */ + struct ngknet_filter_s *filt; + + /*! Packet meta data */ + uint8_t *pmd; + + /*! Packet meta data length */ + int pmd_len; + + /*! Packet data length */ + int pkt_len; + + /*! Matched callback filter */ + struct ngknet_filter_s *filt_cb; +}; + +#define NGKNET_SKB_CB(_skb) ((struct ngknet_callback_desc *)_skb->cb) + +/*! Handle Rx packet */ +typedef struct sk_buff * +(*ngknet_rx_cb_f)(struct sk_buff *skb); + +/*! Handle Tx packet */ +typedef struct sk_buff * +(*ngknet_tx_cb_f)(struct sk_buff *skb); + +/*! PTP Rx/Tx config set */ +typedef int +(*ngknet_ptp_config_set_cb_f)(struct ngknet_private *priv, int *value); + +/*! PTP Rx/Tx HW timestamp get */ +typedef int +(*ngknet_ptp_hwts_get_cb_f)(struct sk_buff *skb, uint64_t *ts); + +/*! PTP Tx meta set */ +typedef int +(*ngknet_ptp_meta_set_cb_f)(struct sk_buff *skb); + +/*! PTP PHC index get */ +typedef int +(*ngknet_ptp_phc_index_get_cb_f)(struct ngknet_private *priv, int *index); + +/*! PTP device control */ +typedef int +(*ngknet_ptp_dev_ctrl_cb_f)(struct ngknet_dev *dev, int cmd, char *data, int len); + +/*! Netif callback */ +typedef int +(*ngknet_netif_cb_f)(struct net_device *dev); + +/*! + * \brief NGKNET callback control. + */ +struct ngknet_callback_ctrl { + /*! Handle Rx packet */ + ngknet_rx_cb_f rx_cb; + + /*! Handle Tx packet */ + ngknet_tx_cb_f tx_cb; + + /*! PTP Rx config set */ + ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb; + + /*! PTP Tx config set */ + ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb; + + /*! PTP Rx HW timestamp get */ + ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb; + + /*! PTP Tx HW timestamp get */ + ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb; + + /*! PTP Tx meta set */ + ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb; + + /*! PTP PHC index get */ + ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb; + + /*! PTP device control */ + ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb; + + /*! Handle Netif create */ + ngknet_netif_cb_f netif_create_cb; + + /*! Handle Netif destroy */ + ngknet_netif_cb_f netif_destroy_cb; +}; + +/*! + * \brief Get callback control. + * + * \param [in] cbc Pointer to callback control. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_callback_control_get(struct ngknet_callback_ctrl **cbc); + +/*! + * \brief Register Rx callback. + * + * \param [in] rx_cb Rx callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_rx_cb_register(ngknet_rx_cb_f rx_cb); + +/*! + * \brief Unregister Rx callback. + * + * \param [in] rx_cb Rx callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_rx_cb_unregister(ngknet_rx_cb_f rx_cb); + +/*! + * \brief Register Tx callback. + * + * \param [in] tx_cb Tx callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_tx_cb_register(ngknet_tx_cb_f tx_cb); + +/*! + * \brief Unregister Tx callback. + * + * \param [in] tx_cb Tx callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_tx_cb_unregister(ngknet_tx_cb_f tx_cb); + +/*! + * \brief Register PTP Rx config set callback. + * + * \param [in] ptp_rx_config_set_cb Rx config set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb); + +/*! + * \brief Unregister PTP Rx config set callback. + * + * \param [in] ptp_rx_config_set_cb Rx config set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb); + +/*! + * \brief Register PTP Tx config set callback. + * + * \param [in] ptp_tx_config_set_cb Tx config set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb); + +/*! + * \brief Unregister PTP Tx config set callback. + * + * \param [in] ptp_tx_config_set_cb Tx config set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb); + +/*! + * \brief Register PTP Rx HW timestamp get callback. + * + * \param [in] ptp_rx_hwts_get_cb Rx HW timestamp get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb); + +/*! + * \brief Unregister PTP Rx HW timestamp get callback. + * + * \param [in] ptp_rx_hwts_get_cb Rx HW timestamp get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb); + +/*! + * \brief Register PTP Tx HW timestamp get callback. + * + * \param [in] ptp_tx_hwts_get_cb Tx HW timestamp get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb); + +/*! + * \brief Unregister PTP Tx HW timestamp get callback. + * + * \param [in] ptp_tx_hwts_get_cb Tx HW timestamp get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb); + +/*! + * \brief Register PTP Tx meta set callback. + * + * \param [in] ptp_tx_meta_set_cb Tx meta set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_meta_set_cb_register(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb); + +/*! + * \brief Unregister PTP Tx meta set callback. + * + * \param [in] ptp_tx_meta_set_cb Tx meta set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_meta_set_cb_unregister(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb); + +/*! + * \brief Register PTP PHC index get callback. + * + * \param [in] ptp_phc_index_get_cb PHC index get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_phc_index_get_cb_register(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb); + +/*! + * \brief Unregister PTP PHC index get callback. + * + * \param [in] ptp_phc_index_get_cb PHC index get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_phc_index_get_cb_unregister(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb); + +/*! + * \brief Register PTP device control callback. + * + * \param [in] ptp_dev_ctrl_cb Device control callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_dev_ctrl_cb_register(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb); + +/*! + * \brief Unregister PTP device control callback. + * + * \param [in] ptp_dev_ctrl_cb Device control callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_dev_ctrl_cb_unregister(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb); + +/*! + * \brief Register Netif Create callback. + * + * \param [netif_cb] netif_cb create callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_netif_create_cb_register(ngknet_netif_cb_f netif_cb); + +/*! + * \brief Unregister Netif Create callback. + * + * \param [netif_cb] netif_cb destroy callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_netif_create_cb_unregister(ngknet_netif_cb_f netif_cb); + +/*! + * \brief Register Netif Destroy callback. + * + * \param [netif_cb] netif_cb destroy callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_netif_destroy_cb_register(ngknet_netif_cb_f netif_cb); + +/*! + * \brief Unregister Netif Destroy callback. + * + * \param [netif_cb] netif_cb destroy callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_netif_destroy_cb_unregister(ngknet_netif_cb_f netif_cb); + +#endif /* NGKNET_CALLBACK_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_dep.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_dep.h new file mode 100644 index 000000000000..919dd6450340 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_dep.h @@ -0,0 +1,61 @@ +/*! \file ngknet_dep.h + * + * Macro definitions for NGKNET dependence. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_DEP_H +#define NGKNET_DEP_H + +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/*! Memorry barrier */ +#define MEMORY_BARRIER smp_mb() + +/*! CNET print uitility */ +#define CNET_PR(fmt, args...) printk(fmt, ##args) + +struct pdma_dev; + +/*! Externs for the required functions. */ +#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \ +extern int _bd##_cnet_pdma_attach(struct pdma_dev *dev); \ +extern int _bd##_cnet_pdma_detach(struct pdma_dev *dev); +#include + +/*! Create enumeration values from list of supported devices. */ +#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \ + NGKNET_DEV_T_##_bd, +/*! Enumeration for all base device types. */ +typedef enum { + NGKNET_DEV_T_NONE = 0, +#include + NGKNET_DEV_T_COUNT +} ngknet_dev_type_t; + +#endif /* NGKNET_DEP_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.c new file mode 100644 index 000000000000..00fdb3da8849 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.c @@ -0,0 +1,505 @@ +/*! \file ngknet_extra.c + * + * Utility routines for NGKNET enhancement. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "ngknet_main.h" +#include "ngknet_extra.h" +#include "ngknet_callback.h" + +static struct ngknet_rl_ctrl rl_ctrl; + +int +ngknet_filter_create(struct ngknet_dev *dev, ngknet_filter_t *filter) +{ + struct filt_ctrl *fc = NULL; + struct list_head *list = NULL; + ngknet_filter_t *filt = NULL; + unsigned long flags; + int num, id, done = 0; + + switch (filter->type) { + case NGKNET_FILTER_T_RX_PKT: + break; + default: + return SHR_E_UNAVAIL; + } + + switch (filter->dest_type) { + case NGKNET_FILTER_DEST_T_NULL: + case NGKNET_FILTER_DEST_T_NETIF: + case NGKNET_FILTER_DEST_T_VNET: + case NGKNET_FILTER_DEST_T_CB: /* SDKLT-26907: support NGKNET_FILTER_DEST_T_CB */ + break; + default: + return SHR_E_UNAVAIL; + } + + spin_lock_irqsave(&dev->lock, flags); + + num = (long)dev->fc[0]; + for (id = 1; id < num + 1; id++) { + if (!dev->fc[id]) { + break; + } + } + if (id > NUM_FILTER_MAX) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_RESOURCE; + } + + fc = kzalloc(sizeof(*fc), GFP_KERNEL); + if (!fc) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_MEMORY; + } + + dev->fc[id] = fc; + num += id == (num + 1) ? 1 : 0; + dev->fc[0] = (void *)(long)num; + + memcpy(&fc->filt, filter, sizeof(fc->filt)); + fc->filt.id = id; + + list_for_each(list, &dev->filt_list) { + filt = &((struct filt_ctrl *)list)->filt; + if (filt->flags & NGKNET_FILTER_F_MATCH_CHAN) { + if (!(fc->filt.flags & NGKNET_FILTER_F_MATCH_CHAN) || + fc->filt.chan > filt->chan) { + continue; + } + if (fc->filt.chan < filt->chan || + fc->filt.priority < filt->priority) { + list_add_tail(&fc->list, list); + done = 1; + break; + } + } else { + if (fc->filt.flags & NGKNET_FILTER_F_MATCH_CHAN || + fc->filt.priority < filt->priority) { + list_add_tail(&fc->list, list); + done = 1; + break; + } + } + } + if (!done) { + list_add_tail(&fc->list, &dev->filt_list); + } + + filter->id = fc->filt.id; + + spin_unlock_irqrestore(&dev->lock, flags); + + return SHR_E_NONE; +} + +int +ngknet_filter_destroy(struct ngknet_dev *dev, int id) +{ + struct filt_ctrl *fc = NULL; + unsigned long flags; + int num; + + if (id <= 0 || id > NUM_FILTER_MAX) { + return SHR_E_PARAM; + } + + spin_lock_irqsave(&dev->lock, flags); + + fc = (struct filt_ctrl *)dev->fc[id]; + if (!fc) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NOT_FOUND; + } + + list_del(&fc->list); + kfree(fc); + + dev->fc[id] = NULL; + num = (long)dev->fc[0]; + while (num-- == id--) { + if (dev->fc[id]) { + dev->fc[0] = (void *)(long)num; + break; + } + } + + spin_unlock_irqrestore(&dev->lock, flags); + + return SHR_E_NONE; +} + +int +ngknet_filter_destroy_all(struct ngknet_dev *dev) +{ + int id; + int rv; + + for (id = 1; id <= NUM_FILTER_MAX; id++) { + rv = ngknet_filter_destroy(dev, id); + if (SHR_FAILURE(rv)) { + return rv; + } + } + + return SHR_E_NONE; +} + +int +ngknet_filter_get(struct ngknet_dev *dev, int id, ngknet_filter_t *filter) +{ + struct filt_ctrl *fc = NULL; + unsigned long flags; + int num; + + if (id <= 0 || id > NUM_FILTER_MAX) { + return SHR_E_PARAM; + } + + spin_lock_irqsave(&dev->lock, flags); + + fc = (struct filt_ctrl *)dev->fc[id]; + if (!fc) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NOT_FOUND; + } + + memcpy(filter, &fc->filt, sizeof(*filter)); + + num = (long)dev->fc[0]; + for (id++; id < num + 1; id++) { + if (dev->fc[id]) { + break; + } + } + filter->next = id == (num + 1) ? 0 : id; + + spin_unlock_irqrestore(&dev->lock, flags); + + return SHR_E_NONE; +} + +int +ngknet_filter_get_next(struct ngknet_dev *dev, ngknet_filter_t *filter) +{ + int id; + int rv; + + if (!filter->next) { + for (id = 1; id <= NUM_FILTER_MAX; id++) { + rv = ngknet_filter_get(dev, id, filter); + if (SHR_SUCCESS(rv)) { + return rv; + } + } + if (id > NUM_FILTER_MAX) { + return SHR_E_NOT_FOUND; + } + } + + return ngknet_filter_get(dev, filter->next, filter); +} + +int +ngknet_rx_pkt_filter(struct ngknet_dev *dev, struct sk_buff *skb, struct net_device **ndev, + struct net_device **mndev, struct sk_buff **mskb) +{ + struct pkt_buf *pkb = (struct pkt_buf *)skb->data; + struct net_device *dest_ndev = NULL, *mirror_ndev = NULL; + struct sk_buff *mirror_skb = NULL; + struct ngknet_private *priv = NULL; + struct filt_ctrl *fc = NULL; + struct list_head *list = NULL; + ngknet_filter_t scratch, *filt = NULL, *filt_cb = NULL; + uint8_t *oob = &pkb->data, *data = NULL; + uint16_t tpid; + unsigned long flags; + int wsize; + int chan_id; + int idx, match = 0, match_cb = 0; + + bcmcnet_pdma_dev_queue_to_chan(&dev->pdma_dev, pkb->pkh.queue_id, + PDMA_Q_RX, &chan_id); + + spin_lock_irqsave(&dev->lock, flags); + + dest_ndev = dev->bdev[chan_id]; + if (dest_ndev) { + skb->dev = dest_ndev; + priv = netdev_priv(dest_ndev); + priv->users++; + *ndev = dest_ndev; + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NONE; + } + + if (list_empty(&dev->filt_list)) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NONE; + } + + list_for_each(list, &dev->filt_list) { + fc = (struct filt_ctrl *)list; + filt = &fc->filt; + if (filt->flags & NGKNET_FILTER_F_ANY_DATA) { + match = 1; + break; + } + if (filt->flags & NGKNET_FILTER_F_MATCH_CHAN && filt->chan != chan_id) { + continue; + } + memcpy(&scratch.data.b[0], + &oob[filt->oob_data_offset], filt->oob_data_size); + memcpy(&scratch.data.b[filt->oob_data_size], + &pkb->data + pkb->pkh.meta_len + filt->pkt_data_offset, + filt->pkt_data_size); + wsize = NGKNET_BYTES2WORDS(filt->oob_data_size + filt->pkt_data_size); + for (idx = 0; idx < wsize; idx++) { + scratch.data.w[idx] &= filt->mask.w[idx]; + if (scratch.data.w[idx] != filt->data.w[idx]) { + break; + } + } + if (idx == wsize) { + if (NGKNET_FILTER_DEST_T_CB == filt->dest_type) { + match_cb = 1; + filt_cb = filt; + continue; + } + match = 1; + break; + } + } + + if (match) { + fc->hits++; + switch (filt->dest_type) { + case NGKNET_FILTER_DEST_T_NETIF: + if (filt->dest_id == 0) { + dest_ndev = dev->net_dev; + } else { + dest_ndev = dev->vdev[filt->dest_id]; + } + if (dest_ndev) { + skb->dev = dest_ndev; + if (filt->dest_proto) { + pkb->pkh.attrs |= PDMA_RX_SET_PROTO; + skb->protocol = filt->dest_proto; + } + priv = netdev_priv(dest_ndev); + priv->users++; + } + break; + case NGKNET_FILTER_DEST_T_VNET: + pkb->pkh.attrs |= PDMA_RX_TO_VNET; + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NO_HANDLER; + case NGKNET_FILTER_DEST_T_NULL: + default: + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_UNAVAIL; + } + } + + spin_unlock_irqrestore(&dev->lock, flags); + + if (!dest_ndev) { + return SHR_E_NONE; + } else { + *ndev = dest_ndev; + } + + if (filt->flags & NGKNET_FILTER_F_STRIP_TAG) { + pkb->pkh.attrs |= PDMA_RX_STRIP_TAG; + data = skb->data + PKT_HDR_SIZE + pkb->pkh.meta_len; + tpid = data[12] << 8 | data[13]; + if (tpid == ETH_P_8021Q || tpid == ETH_P_8021AD) { + pkb->pkh.data_len -= VLAN_HLEN; + memmove(skb->data + VLAN_HLEN, skb->data, + PKT_HDR_SIZE + pkb->pkh.meta_len + 2 * ETH_ALEN); + skb_pull(skb, VLAN_HLEN); + } + } + + if (dev->cbc->rx_cb) { + NGKNET_SKB_CB(skb)->filt = filt; + + /* Add callback filter if matched */ + if (match_cb) { + NGKNET_SKB_CB(skb)->filt_cb = filt_cb; + } + } + + if (filt->mirror_type == NGKNET_FILTER_DEST_T_NETIF) { + spin_lock_irqsave(&dev->lock, flags); + if (filt->mirror_id == 0) { + mirror_ndev = dev->net_dev; + } else { + mirror_ndev = dev->vdev[filt->mirror_id]; + } + if (mirror_ndev) { + mirror_skb = pskb_copy(skb, GFP_ATOMIC); + if (mirror_skb) { + mirror_skb->dev = mirror_ndev; + if (filt->mirror_proto) { + pkb->pkh.attrs |= PDMA_RX_SET_PROTO; + mirror_skb->protocol = filt->mirror_proto; + } + if (dev->cbc->rx_cb) { + NGKNET_SKB_CB(mirror_skb)->filt = filt; + } + priv = netdev_priv(mirror_ndev); + priv->users++; + *mndev = mirror_ndev; + *mskb = mirror_skb; + } + } + spin_unlock_irqrestore(&dev->lock, flags); + } + + return SHR_E_NONE; +} + +static void +ngknet_rl_process(timer_context_t data) +{ + struct ngknet_rl_ctrl *rc = timer_arg(rc, data, timer); + struct ngknet_dev *dev; + unsigned long flags; + int idx; + + spin_lock_irqsave(&rc->lock, flags); + rc->rx_pkts = 0; + for (idx = 0; idx < NUM_PDMA_DEV_MAX; idx++) { + dev = &rc->devs[idx]; + if (rc->dev_active[idx] && rc->dev_paused[idx]) { + bcmcnet_pdma_dev_rx_resume(&dev->pdma_dev); + rl_ctrl.dev_paused[dev->dev_no] = 0; + } + } + spin_unlock_irqrestore(&rc->lock, flags); + + rc->timer.expires = jiffies + HZ / rc->rx_ticks; + add_timer(&rc->timer); +} + +void +ngknet_rx_rate_limit_init(struct ngknet_dev *devs) +{ + sal_memset(&rl_ctrl, 0, sizeof(rl_ctrl)); + rl_ctrl.rx_ticks = 10; + setup_timer(&rl_ctrl.timer, ngknet_rl_process, (timer_context_t)&rl_ctrl); + spin_lock_init(&rl_ctrl.lock); + rl_ctrl.devs = devs; +} + +void +ngknet_rx_rate_limit_cleanup(void) +{ + del_timer_sync(&rl_ctrl.timer); +} + +int +ngknet_rx_rate_limit_started(void) +{ + return rl_ctrl.started; +} + +void +ngknet_rx_rate_limit_start(struct ngknet_dev *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&rl_ctrl.lock, flags); + rl_ctrl.dev_active[dev->dev_no] = 1; + spin_unlock_irqrestore(&rl_ctrl.lock, flags); + + if (!rl_ctrl.started) { + rl_ctrl.started = 1; + rl_ctrl.timer.expires = jiffies + HZ / rl_ctrl.rx_ticks; + add_timer(&rl_ctrl.timer); + } +} + +void +ngknet_rx_rate_limit_stop(struct ngknet_dev *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&rl_ctrl.lock, flags); + rl_ctrl.dev_active[dev->dev_no] = 0; + spin_unlock_irqrestore(&rl_ctrl.lock, flags); +} + +void +ngknet_rx_rate_limit(struct ngknet_dev *dev, int limit) +{ + unsigned long flags; + + spin_lock_irqsave(&rl_ctrl.lock, flags); + if ((++rl_ctrl.rx_pkts + rl_ctrl.rx_overruns > limit / rl_ctrl.rx_ticks) && + !rl_ctrl.dev_paused[dev->dev_no] && rl_ctrl.dev_active[dev->dev_no]) { + rl_ctrl.dev_paused[dev->dev_no] = 1; + rl_ctrl.rx_overruns = 0; + bcmcnet_pdma_dev_rx_suspend(&dev->pdma_dev); + } + if (rl_ctrl.dev_paused[dev->dev_no]) { + rl_ctrl.rx_overruns++; + } + spin_unlock_irqrestore(&rl_ctrl.lock, flags); +} + +void +ngknet_tx_queue_schedule(struct ngknet_dev *dev, struct sk_buff *skb, int *queue) +{ + struct pkt_buf *pkb = (struct pkt_buf *)skb->data; + + if (pkb->pkh.attrs & PDMA_TX_BIND_QUE) { + *queue = pkb->pkh.queue_id; + } +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.h new file mode 100644 index 000000000000..27dea9e368e7 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.h @@ -0,0 +1,218 @@ +/*! \file ngknet_extra.h + * + * Generic data structure definitions for NGKNET enhancement. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_EXTRA_H +#define NGKNET_EXTRA_H + +/*! + * \brief Filter control. + */ +struct filt_ctrl { + /*! List head */ + struct list_head list; + + /*! Device number */ + int dev_no; + + /*! Number of hits */ + uint64_t hits; + + /*! Filter description */ + ngknet_filter_t filt; +}; + +/*! + * \brief Create filter. + * + * \param [in] dev Device structure point. + * \param [in] filter Filter structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_filter_create(struct ngknet_dev *dev, ngknet_filter_t *filter); + +/*! + * \brief Destroy filter. + * + * \param [in] dev Device structure point. + * \param [in] id Filter ID. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_filter_destroy(struct ngknet_dev *dev, int id); + +/*! + * \brief Destroy all the filters. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_filter_destroy_all(struct ngknet_dev *dev); + +/*! + * \brief Get filter. + * + * \param [in] dev Device structure point. + * \param [in] id Filter ID. + * \param [out] filter Filter structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_filter_get(struct ngknet_dev *dev, int id, ngknet_filter_t *filter); + +/*! + * \brief Get the next filter. + * + * \param [in] dev Device structure point. + * \param [out] filter Filter structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_filter_get_next(struct ngknet_dev *dev, ngknet_filter_t *filter); + +/*! + * \brief Filter packet. + * + * \param [in] dev Device structure point. + * \param [in] skb Rx packet SKB. + * \param [out] mndev Mirror network interface. + * \param [out] mskb Mirror Rx packet SKB. + * + * \retval Matched network interface. + * \retval NULL No matched network interface. + */ +extern int +ngknet_rx_pkt_filter(struct ngknet_dev *dev, struct sk_buff *skb, struct net_device **ndev, + struct net_device **mndev, struct sk_buff **mskb); + +/*! + * \brief Rx rate limit control. + * + * This contains all the control information for Rx rate limit such as + * the number of Rx packets, status related to Rx rate limit, etc. + * + * The rate limit is kernel-oriented, i.e. all the Rx packets from any + * device/channel will be accounted for. Once the received packets reach + * the limit value in an 1-Sec interval, the driver API XXXX_rx_suspend() + * will be called to suspend Rx. The 1-Sec basis timer will call the driver + * API XXXX_rx_resume() to resume Rx and reset rate-related status/counters + * at the begin of the next 1-Sec interval. + * + * The NGKNET module parameter 'rx_rate_limit' is used to decide the maximum + * Rx rate. Disable Rx rate limit if set 0. It can be set when inserting + * NGKNET module or modified using its SYSFS attributions. + */ +struct ngknet_rl_ctrl { + /*! Rx packets */ + int rx_pkts; + + /*! Rx overruns */ + int rx_overruns; + + /*! Rx ticks */ + int rx_ticks; + + /*! Active devices under rate control */ + int dev_active[NUM_PDMA_DEV_MAX]; + + /*! Paused devices due to no Rx credit */ + int dev_paused[NUM_PDMA_DEV_MAX]; + + /*! Rate limit timer */ + struct timer_list timer; + + /*! Rate limit lock */ + spinlock_t lock; + + /*! Devices */ + struct ngknet_dev *devs; + + /*! Rate limit status indicator */ + int started; +}; + +/*! + * \brief Initialize Rx rate limit. + * + * \param [in] devs Devices array. + */ +extern void +ngknet_rx_rate_limit_init(struct ngknet_dev *devs); + +/*! + * \brief Cleanup Rx rate limit. + */ +extern void +ngknet_rx_rate_limit_cleanup(void); + +/*! + * \brief Get Rx rate limit state. + */ +extern int +ngknet_rx_rate_limit_started(void); + +/*! + * \brief Start Rx rate limit. + * + * \param [in] dev Device structure point. + */ +extern void +ngknet_rx_rate_limit_start(struct ngknet_dev *dev); + +/*! + * \brief Stop Rx rate limit. + * + * \param [in] dev Device structure point. + */ +extern void +ngknet_rx_rate_limit_stop(struct ngknet_dev *dev); + +/*! + * \brief Limit Rx rate. + * + * \param [in] dev Device structure point. + */ +extern void +ngknet_rx_rate_limit(struct ngknet_dev *dev, int limit); + +/*! + * \brief Schedule Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + */ +extern void +ngknet_tx_queue_schedule(struct ngknet_dev *dev, struct sk_buff *skb, int *queue); + +#endif /* NGKNET_EXTRA_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.c new file mode 100644 index 000000000000..0162ae5b96c1 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.c @@ -0,0 +1,173 @@ +/*! \file ngknet_linux.c + * + * Utility routines for Linux kernel APIs abstraction. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ngknet_linux.h" + +/*! + * Time + */ + +unsigned long +sal_time_usecs(void) +{ + struct timeval tv; + + kal_time_val_get(&tv); + + return tv.tv_sec * 1000000 + tv.tv_usec; +} + +void +sal_usleep(unsigned long usec) +{ + unsigned long then, now, hz; + + hz = usec * HZ / 1000000; + if (hz) { + schedule_timeout(hz); + } + usec = usec * HZ % 1000000 / HZ; + if (usec) { + then = sal_time_usecs(); + do { + schedule(); + now = sal_time_usecs(); + } while (now > then && (now - then) < usec); + } +} + +/*! + * Synchronization + */ + +typedef struct { + struct semaphore sem; + char *desc; + int binary; +} sem_ctrl_t; + +sal_sem_t +sal_sem_create(char *desc, int binary, int count) +{ + sem_ctrl_t *sc = kmalloc(sizeof(*sc), GFP_KERNEL); + + if (sc != NULL) { + sema_init(&sc->sem, count); + sc->desc = desc; + sc->binary = binary; + } + + return (sal_sem_t)sc; +} + +void +sal_sem_destroy(sal_sem_t sem) +{ + sem_ctrl_t *sc = (sem_ctrl_t *)sem; + + kfree(sc); +} + +int +sal_sem_take(sal_sem_t sem, int usec) +{ + sem_ctrl_t *sc = (sem_ctrl_t *)sem; + int rv; + + if (usec == SAL_SEM_FOREVER) { + do { + rv = down_interruptible(&sc->sem); + } while (rv == -EINTR); + return rv ? -1 : 0; + } + + return -1; +} + +int +sal_sem_give(sal_sem_t sem) +{ + sem_ctrl_t *sc = (sem_ctrl_t *)sem; + + up(&sc->sem); + + return 0; +} + +typedef struct spinlock_ctrl_s { + spinlock_t spinlock; + unsigned long flags; + char *desc; +} *spinlock_ctrl_t; + +sal_spinlock_t +sal_spinlock_create(char *desc) +{ + spinlock_ctrl_t sl = kmalloc(sizeof(*sl), GFP_KERNEL); + + if (sl != NULL) { + spin_lock_init(&sl->spinlock); + sl->flags = 0; + sl->desc = desc; + } + + return (sal_spinlock_t)sl; +} + +void +sal_spinlock_destroy(sal_spinlock_t lock) +{ + spinlock_ctrl_t sl = (spinlock_ctrl_t)lock; + + kfree(sl); +} + +int +sal_spinlock_lock(sal_spinlock_t lock) +{ + spinlock_ctrl_t sl = (spinlock_ctrl_t)lock; + + spin_lock_irqsave(&sl->spinlock, sl->flags); + + return 0; +} + +int +sal_spinlock_unlock(sal_spinlock_t lock) +{ + spinlock_ctrl_t sl = (spinlock_ctrl_t)lock; + + spin_unlock_irqrestore(&sl->spinlock, sl->flags); + + return 0; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.h new file mode 100644 index 000000000000..686aac8f5571 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.h @@ -0,0 +1,240 @@ +/*! \file ngknet_linux.h + * + * Data structure and macro definitions for Linux kernel APIs abstraction. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_LINUX_H +#define NGKNET_LINUX_H + +#include +#include +#include +#include + +/*! + * Kernel abstraction + */ + +#define MODULE_PARAM(n, t, p) module_param(n, t, p) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) +#define kal_vlan_hwaccel_put_tag(skb, proto, tci) \ + __vlan_hwaccel_put_tag(skb, tci) +#define NETIF_F_HW_VLAN_CTAG_RX NETIF_F_HW_VLAN_RX +#define NETIF_F_HW_VLAN_CTAG_TX NETIF_F_HW_VLAN_TX +#else +#define kal_vlan_hwaccel_put_tag(skb, proto, tci) \ + __vlan_hwaccel_put_tag(skb, htons(proto), tci) +#endif /* KERNEL_VERSION(3,10,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) +static inline int +kal_support_paged_skb(void) +{ + return false; +} +#else +static inline int +kal_support_paged_skb(void) +{ + return true; +} +#endif /* KERNEL_VERSION(3,6,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) +static inline struct page * +kal_dev_alloc_page(void) +{ + return NULL; +} +#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) +static inline struct page * +kal_dev_alloc_page(void) +{ + return alloc_pages(GFP_ATOMIC | __GFP_ZERO | __GFP_COLD | + __GFP_COMP | __GFP_MEMALLOC, 0); +} +#else +static inline struct page * +kal_dev_alloc_page(void) +{ + return dev_alloc_page(); +} +#endif /* KERNEL_VERSION(3,6,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) +static inline struct sk_buff * +kal_build_skb(void *data, unsigned int frag_size) +{ + return NULL; +} +#else +static inline struct sk_buff * +kal_build_skb(void *data, unsigned int frag_size) +{ + return build_skb(data, frag_size); +} +#endif /* KERNEL_VERSION(3,6,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static inline void +kal_netif_trans_update(struct net_device *dev) +{ + dev->trans_start = jiffies; +} +#else +static inline void +kal_netif_trans_update(struct net_device *dev) +{ + netif_trans_update(dev); +} +#endif /* KERNEL_VERSION(4,7,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) +static inline void +kal_time_val_get(struct timeval *tv) +{ + do_gettimeofday(tv); +} +#else +static inline void +kal_time_val_get(struct timeval *tv) +{ + struct timespec64 ts; + ktime_get_real_ts64(&ts); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; +} +#endif /* KERNEL_VERSION(3,17,0) */ + +static inline unsigned long +kal_copy_from_user(void *to, const void __user *from, + unsigned int dl, unsigned int sl) +{ + unsigned int len = dl; + + if (unlikely(len != sl)) { + printk(KERN_WARNING "Unmatched linux_ngknet.ko, please use the latest.\n"); + len = min(dl, sl); + } + + return copy_from_user(to, from, len); +} + +static inline unsigned long +kal_copy_to_user(void __user *to, const void *from, + unsigned int dl, unsigned int sl) +{ + unsigned int len = dl; + + if (unlikely(len != sl)) { + printk(KERN_WARNING "Unmatched linux_ngknet.ko, please use the latest.\n"); + len = min(dl, sl); + } + + return copy_to_user(to, from, len); +} + +/*! + * System abstraction + */ + +static inline void * +sal_alloc(unsigned int sz, char *s) +{ + return kmalloc(sz, GFP_KERNEL); +} + +static inline void +sal_free(void *addr) +{ + kfree(addr); +} + +static inline void * +sal_memset(void *dest, int c, size_t cnt) +{ + return memset(dest, c, cnt); +} + +static inline void * +sal_memcpy(void *dest, const void *src, size_t cnt) +{ + return memcpy(dest, src, cnt); +} + +static inline char * +sal_strncpy(char *dest, const char *src, size_t cnt) +{ + return strncpy(dest, src, cnt); +} + +/*! + * Time + */ + +extern unsigned long +sal_time_usecs(void); + +extern void +sal_usleep(unsigned long usec); + +/*! + * Synchronization + */ + +typedef struct sal_sem_s { + char semaphore_opaque_type; +} *sal_sem_t; + +typedef struct sal_spinlock_s { + char spinlock_opaque_type; +} *sal_spinlock_t; + +#define SAL_SEM_FOREVER -1 +#define SAL_SEM_BINARY 1 +#define SAL_SEM_COUNTING 0 + +extern sal_sem_t +sal_sem_create(char *desc, int binary, int count); + +extern void +sal_sem_destroy(sal_sem_t sem); + +extern int +sal_sem_take(sal_sem_t sem, int usec); + +extern int +sal_sem_give(sal_sem_t sem); + +extern sal_spinlock_t +sal_spinlock_create(char *desc); + +extern void +sal_spinlock_destroy(sal_spinlock_t lock); + +extern int +sal_spinlock_lock(sal_spinlock_t lock); + +extern int +sal_spinlock_unlock(sal_spinlock_t lock); + +#endif /* NGKNET_LINUX_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.c new file mode 100644 index 000000000000..b8af31d85ff2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.c @@ -0,0 +1,2689 @@ +/*! \file ngknet_main.c + * + * NGKNET module entry. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +/* + * This module implements a Linux network driver for Broadcom + * XGS switch devices. The driver simultaneously serves a + * number of virtual Linux network devices. + * + * Packets received from the switch device are sent to a virtual + * Linux network device based on a set of packet filters. + * + * Packets from the virtual Linux network devices are multiplexed + * with fifo mode if only one Tx queue enabled. + * + * A command-based IOCTL interface is used for managing the devices, + * packet filters and virtual Linux network interfaces. + * + * A virtual network interface can be configured to work in RCPU + * mode, which means that packets from the switch device will + * be encapsulated with a RCPU header and a block of meta data + * that basically contains the core DCB information. Likewise, + * packets received from the Linux network stack are assumed to + * be RCPU encapsulated when going out on an interface in RCPU + * mode. If a virtual network interface does not work in RCPU + * mode and transmits to this interface will unmodified go to + * specified physical switch port, DCB information should be + * provided when the interface is created. + * + * The module implements basic Rx DMA rate control. The rate is + * specified in packets per second, and different Rx DMA channels + * can be configured to use different maximum packet rates. + * The packet rate can be configure as a module parameter, and + * it can also be changed dynamically through the proc file + * system (syntax is described in function header comment). + * + * For a list of supported module parameters, please see below. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "ngknet_main.h" +#include "ngknet_extra.h" +#include "ngknet_procfs.h" +#include "ngknet_callback.h" +#include "ngknet_ptp.h" + +/*! \cond */ +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Network Device Driver Module"); +MODULE_LICENSE("GPL"); +/*! \endcond */ + +/*! \cond */ +static int debug = 0; +MODULE_PARAM(debug, int, 0); +MODULE_PARM_DESC(debug, +"Debug level (default 0)"); +/*! \endcond */ + +/*! \cond */ +static char *base_dev_name = "bcm"; +MODULE_PARAM(base_dev_name, charp, 0); +MODULE_PARM_DESC(base_dev_name, +"Base device name (default bcm0, bcm1, etc.)"); +/*! \endcond */ + +/*! \cond */ +static char *mac_addr = NULL; +MODULE_PARAM(mac_addr, charp, 0); +MODULE_PARM_DESC(mac_addr, +"Ethernet MAC address (default 02:10:18:xx:xx:xx)"); +/*! \endcond */ + +/*! \cond */ +static int default_mtu = 1500; +MODULE_PARAM(default_mtu, int, 0); +MODULE_PARM_DESC(default_mtu, +"Default MTU for NGKNET network interfaces (default 1500)"); +/*! \endcond */ + +/*! \cond */ +static int rx_buffer_size = RX_BUF_SIZE_DFLT; +MODULE_PARAM(rx_buffer_size, int, 0); +MODULE_PARM_DESC(rx_buffer_size, +"Default size of RX packet buffers (default 9216)"); +/*! \endcond */ + +/*! \cond */ +static int rx_rate_limit = -1; +MODULE_PARAM(rx_rate_limit, int, 0); +MODULE_PARM_DESC(rx_rate_limit, +"Rx rate limit (pps, default -1 no limit)"); +/*! \endcond */ + +/*! \cond */ +static int tx_polling = 0; +MODULE_PARAM(tx_polling, int, 0); +MODULE_PARM_DESC(tx_polling, +"Tx polling mode (default 0 in interrupt mode)"); +/*! \endcond */ + +/*! \cond */ +static int rx_batching = 0; +MODULE_PARAM(rx_batching, int, 0); +MODULE_PARM_DESC(rx_batching, +"Rx batching mode (default 0 in single fill mode)"); +/*! \endcond */ + +typedef int (*drv_ops_attach)(struct pdma_dev *dev); + +struct bcmcnet_drv_ops { + const char *drv_desc; + drv_ops_attach drv_attach; + drv_ops_attach drv_detach; +}; + +#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \ + static struct bcmcnet_drv_ops _bd##_cnet_drv_ops = { \ + #_bd, \ + _bd##_cnet_pdma_attach, \ + _bd##_cnet_pdma_detach, \ + }; +#include + +#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \ + &_bd##_cnet_drv_ops, +static struct bcmcnet_drv_ops *drv_ops[] = { + NULL, +#include + NULL +}; +static int drv_num = sizeof(drv_ops) / sizeof(drv_ops[0]); + +struct ngknet_dev ngknet_devices[NUM_PDMA_DEV_MAX]; + +/* Default random MAC address has Broadcom OUI with local admin bit set */ +static uint8_t ngknet_dev_mac[6] = {0x02, 0x10, 0x18, 0x00, 0x00, 0x00}; + +/* Interrupt handles */ +struct ngknet_intr_handle { + struct napi_struct napi; + struct intr_handle *hdl; + int napi_resched; + int napi_pending; +}; + +static struct ngknet_intr_handle priv_hdl[NUM_PDMA_DEV_MAX][NUM_QUE_MAX]; + +/*! + * Dump packet content for debug + */ +static void +ngknet_pkt_dump(uint8_t *data, int len) +{ + char str[128]; + int i; + + len = len > 256 ? 256 : len; + + for (i = 0; i < len; i++) { + if ((i & 0x1f) == 0) { + sprintf(str, "%04x: ", i); + } + sprintf(&str[strlen(str)], "%02x", data[i]); + if ((i & 0x1f) == 0x1f) { + sprintf(&str[strlen(str)], "\n"); + printk(str); + continue; + } + if ((i & 0x3) == 0x3) { + sprintf(&str[strlen(str)], " "); + } + } + if ((i & 0x1f) != 0) { + sprintf(&str[strlen(str)], "\n"); + printk(str); + } + printk("\n"); +} + +/*! + * Rx packets rate test for debug + */ +static void +ngknet_pkt_stats(struct pdma_dev *pdev, int dir) +{ + static struct timeval tv0[2], tv1[2]; + static uint32_t pkts[2] = {0}, prts[2] = {0}; + static uint64_t intrs = 0; + + if (pkts[dir] == 0) { + kal_time_val_get(&tv0[dir]); + intrs = pdev->stats.intrs; + } + if (++pkts[dir] >= 100000) { + uint32_t iv_time; + uint32_t pps; + kal_time_val_get(&tv1[dir]); + iv_time = (tv1[dir].tv_sec - tv0[dir].tv_sec) * 1000000 + + (tv1[dir].tv_usec - tv0[dir].tv_usec); + pps = 100000 * 1000 / (iv_time / 1000); + prts[dir]++; + if (pps <= 100000 || prts[dir] * 100000 >= pps) { + printk(KERN_CRIT "%s -- limit: %d pps, 100K pkts time: %d usec, rate: %d pps, intrs: %llu\n", + dir == PDMA_Q_RX ? "Rx" : "Tx", + dir == PDMA_Q_RX ? rx_rate_limit : -1, + iv_time, pps, pdev->stats.intrs - intrs); + prts[dir] = 0; + } + pkts[dir] = 0; + } +} + +/*! + * Read 32-bit register callback + */ +static int +ngknet_dev_read32(struct pdma_dev *dev, uint32_t addr, uint32_t *data) +{ + *data = ngbde_kapi_pio_read32(dev->unit, addr); + + return 0; +} + +/*! + * Write 32-bit register callback + */ +static int +ngknet_dev_write32(struct pdma_dev *dev, uint32_t addr, uint32_t data) +{ + ngbde_kapi_pio_write32(dev->unit, addr, data); + + return 0; +} + +/*! + * Set Rx HW timestamping. + */ +static int +ngknet_ptp_rx_hwts_set(struct net_device *ndev, struct sk_buff *skb) +{ + struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); + uint64_t ts = 0; + int rv; + + rv = ngknet_ptp_rx_hwts_get(ndev, skb, &ts); + if (SHR_FAILURE(rv) || !ts) { + return SHR_E_FAIL; + } + + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); + shhwtstamps->hwtstamp = ns_to_ktime(ts); + + return SHR_E_NONE; +} + +/*! + * \brief Process Rx packet. + * + * Add RCPU encapsulation or strip matadata if needed + * + * \param [in] ndev Network device structure point. + * \param [in] oskb Rx packet SKB. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_rx_frame_process(struct net_device *ndev, struct sk_buff **oskb) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct sk_buff *skb = *oskb; + struct ngknet_rcpu_hdr *rch = (struct ngknet_rcpu_hdr *)skb->data; + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + uint8_t meta_len = pkh->meta_len; + + /* Do Rx timestamping */ + if (priv->hwts_rx_filter) { + ngknet_ptp_rx_hwts_set(ndev, skb); + } + + /* Remove FCS from packet length */ + skb_trim(skb, skb->len - ETH_FCS_LEN); + pkh->data_len -= ETH_FCS_LEN; + + if (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) { + /* Set up RCPU header */ + memcpy(skb->data, skb->data + PKT_HDR_SIZE + meta_len, 2 * ETH_ALEN); + if (*(uint32_t *)&dev->rcpu_ctrl.dst_mac[0] != 0 || + *(uint16_t *)&dev->rcpu_ctrl.dst_mac[4] != 0) { + memcpy(rch->dst_mac, dev->rcpu_ctrl.dst_mac, ETH_ALEN); + } + if (*(uint32_t *)&dev->rcpu_ctrl.src_mac[0] != 0 || + *(uint16_t *)&dev->rcpu_ctrl.src_mac[4] != 0) { + memcpy(rch->src_mac, dev->rcpu_ctrl.src_mac, ETH_ALEN); + } + rch->vlan_tpid = htons(dev->rcpu_ctrl.vlan_tpid); + rch->vlan_tci = htons(dev->rcpu_ctrl.vlan_tci); + rch->eth_type = htons(dev->rcpu_ctrl.eth_type); + rch->pkt_sig = htons(dev->rcpu_ctrl.pkt_sig); + rch->op_code = RCPU_OPCODE_RX; + rch->flags = RCPU_FLAG_MODHDR; + rch->trans_id = htons(dev->rcpu_ctrl.trans_id); + rch->data_len = htons(pkh->data_len); + } else { + /* Remove packet header and meta data */ + skb_pull(skb, PKT_HDR_SIZE + meta_len); + } + + /* Optional callback handle */ + if (dev->cbc->rx_cb) { + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + cbd->dev_no = dev->dev_no; + cbd->dev_id = dev->pdma_dev.dev_id; + cbd->type_str = drv_ops[dev->pdma_dev.dev_type]->drv_desc; + cbd->priv = priv; + if (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) { + cbd->pmd = skb->data + PKT_HDR_SIZE; + cbd->pkt_len = ntohs(rch->data_len); + } else { + cbd->pmd = skb->data - meta_len; + cbd->pkt_len = pkh->data_len; + } + cbd->pmd_len = meta_len; + skb = dev->cbc->rx_cb(skb); + if (!skb) { + *oskb = NULL; + return SHR_E_UNAVAIL; + } + if (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) { + rch = (struct ngknet_rcpu_hdr *)skb->data; + rch->data_len = htons(skb->len - PKT_HDR_SIZE - meta_len); + } + } + + /* Update SKB pointer */ + *oskb = skb; + + return SHR_E_NONE; +} + +/*! + * \brief Network interface Rx function. + * + * After processing the packet, send it up to network stack. + * + * \param [in] ndev Network device structure point. + * \param [in] skb Rx packet SKB. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_netif_recv(struct net_device *ndev, struct sk_buff *skb) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct pdma_dev *pdev = &dev->pdma_dev; + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + struct napi_struct *napi = NULL; + uint16_t proto; + int chan, gi, qi; + int rv; + + /* Handle one incoming packet */ + rv = ngknet_rx_frame_process(ndev, &skb); + if (SHR_FAILURE(rv)) { + if (!skb) { + return SHR_E_NONE; + } + } + + DBG_VERB(("Rx packet sent up to ndev%d (%d bytes).\n", priv->id, skb->len)); + if (debug & DBG_LVL_PDMP) { + ngknet_pkt_dump(skb->data, skb->len); + } + + if (ndev->features & NETIF_F_RXCSUM) { + if ((pkh->attrs & (PDMA_RX_TU_CSUM | PDMA_RX_IP_CSUM)) == + (PDMA_RX_TU_CSUM | PDMA_RX_IP_CSUM)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + skb_checksum_none_assert(skb); + } + } + + if (!(priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) && + ndev->features & NETIF_F_HW_VLAN_CTAG_RX && + pkh->attrs & PDMA_RX_STRIP_TAG) { + kal_vlan_hwaccel_put_tag(skb, ETH_P_8021Q, priv->vlan); + } + + proto = eth_type_trans(skb, ndev); + if (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) { + skb->protocol = htons(dev->rcpu_ctrl.eth_type); + } else if (!(pkh->attrs & PDMA_RX_SET_PROTO) || !skb->protocol) { + skb->protocol = proto; + } + + skb_record_rx_queue(skb, pkh->queue_id); + + bcmcnet_pdma_dev_queue_to_chan(pdev, pkh->queue_id, PDMA_Q_RX, &chan); + gi = chan / pdev->grp_queues; + if (pdev->flags & PDMA_GROUP_INTR) { + napi = (struct napi_struct *)pdev->ctrl.grp[gi].intr_hdl[0].priv; + } else { + qi = pkh->queue_id; + napi = (struct napi_struct *)pdev->ctrl.grp[gi].intr_hdl[qi].priv; + } + napi_gro_receive(napi, skb); + + /* Update accounting */ + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; + + /* Rate limit */ + if (rx_rate_limit >= 0) { + if (!ngknet_rx_rate_limit_started()) { + ngknet_rx_rate_limit_start(dev); + } + ngknet_rx_rate_limit(dev, rx_rate_limit); + } + + return SHR_E_NONE; +} + +/*! + * \brief Driver Rx callback. + * + * After processing the packet, send it up to network stack. + * + * \param [in] pdev Packet DMA device structure point. + * \param [in] buf Raw Rx buffer. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_frame_recv(struct pdma_dev *pdev, int queue, void *buf) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + struct sk_buff *skb = (struct sk_buff *)buf, *mskb = NULL; + struct net_device *ndev = NULL, *mndev = NULL; + struct ngknet_private *priv = NULL; + unsigned long flags; + int rv; + + DBG_VERB(("Rx packet (%d bytes).\n", skb->len)); + if (debug & DBG_LVL_PDMP) { + ngknet_pkt_dump(skb->data, skb->len); + } + + /* Go through the filters */ + rv = ngknet_rx_pkt_filter(dev, skb, &ndev, &mndev, &mskb); + if (SHR_FAILURE(rv) || !ndev) { + return SHR_E_FAIL; + } + + /* Populate header, checksum status, VLAN, and protocol */ + priv = netdev_priv(ndev); + if (netif_carrier_ok(ndev)) { + ngknet_netif_recv(ndev, skb); + } else { + priv->stats.rx_dropped++; + rv = SHR_E_UNAVAIL; + } + + spin_lock_irqsave(&dev->lock, flags); + priv->users--; + if (!priv->users && priv->wait) { + wake_up(&dev->wq); + } + spin_unlock_irqrestore(&dev->lock, flags); + + /* Handle mirrored packet */ + if (mndev && mskb) { + priv = netdev_priv(mndev); + if (netif_carrier_ok(mndev)) { + ngknet_netif_recv(mndev, mskb); + } else { + priv->stats.rx_dropped++; + dev_kfree_skb_any(mskb); + } + spin_lock_irqsave(&dev->lock, flags); + priv->users--; + if (!priv->users && priv->wait) { + wake_up(&dev->wq); + } + spin_unlock_irqrestore(&dev->lock, flags); + } + + /* Measure speed */ + if (debug & DBG_LVL_RATE) { + ngknet_pkt_stats(pdev, PDMA_Q_RX); + } + + return rv; +} + +/*! + * Set Tx HW timestamping. + */ +static int +ngknet_ptp_tx_hwts_set(struct net_device *ndev, struct sk_buff *skb) +{ + struct skb_shared_hwtstamps shhwtstamps; + uint64_t ts = 0; + int rv; + + rv = ngknet_ptp_tx_hwts_get(ndev, skb, &ts); + if (SHR_FAILURE(rv) || !ts) { + return SHR_E_FAIL; + } + + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); + shhwtstamps.hwtstamp = ns_to_ktime(ts); + skb_tstamp_tx(skb, &shhwtstamps); + + return SHR_E_NONE; +} + +/*! + * PTP Tx worker. + */ +static void +ngknet_ptp_tx_work(struct work_struct *work) +{ + struct ngknet_dev *dev = container_of(work, struct ngknet_dev, ptp_tx_work); + struct sk_buff *skb; + int rv; + + while (skb_queue_len(&dev->ptp_tx_queue)) { + skb = skb_dequeue(&dev->ptp_tx_queue); + rv = ngknet_ptp_tx_hwts_set(dev->net_dev, skb); + if (SHR_FAILURE(rv)) { + printk("Timestamp value has not been set for current skb.\n"); + } + dev_kfree_skb_any(skb); + } +} + +/*! + * Config Tx metadata for HW timestamping. + */ +static int +ngknet_ptp_tx_config(struct net_device *ndev, struct sk_buff *skb) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + int rv; + + if (priv->type == NGKNET_NETIF_T_PORT) { + rv = ngknet_ptp_tx_meta_set(ndev, skb); + if (SHR_FAILURE(rv)) { + return rv; + } + } else if (priv->hwts_tx_type != HWTSTAMP_TX_ONESTEP_SYNC) { + return SHR_E_UNAVAIL; + } + + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + + if (priv->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC) { + skb_queue_tail(&dev->ptp_tx_queue, skb_get(skb)); + schedule_work(&dev->ptp_tx_work); + } + + return SHR_E_NONE; +} + +/*! + * \brief Process Tx packet. + * + * Strip RCPU encapsulation, setup CNET packet buffer, add vlan tag + * or pad the packet. + * + * \param [in] ndev Network device structure point. + * \param [in] oskb Tx packet SKB. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_tx_frame_process(struct net_device *ndev, struct sk_buff **oskb) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct sk_buff *skb = *oskb; + struct ngknet_rcpu_hdr *rch = (struct ngknet_rcpu_hdr *)skb->data; + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + struct sk_buff *nskb = NULL; + char *data = NULL; + uint32_t copy_len, meta_len, data_len, pkt_len, tag_len; + uint16_t tpid; + + /* Set up packet header */ + if (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) { + /* RCPU encapsulation packet */ + data_len = pkh->attrs & PDMA_TX_HDR_COOKED ? + pkh->data_len - ETH_FCS_LEN : ntohs(rch->data_len); + pkt_len = PKT_HDR_SIZE + rch->meta_len + data_len; + if (skb->len != pkt_len || skb->len < (PKT_HDR_SIZE + 14)) { + DBG_WARN(("Tx drop: Invalid RCPU encapsulation\n")); + return SHR_E_FAIL; + } + if (dev->rcpu_ctrl.pkt_sig && dev->rcpu_ctrl.pkt_sig != ntohs(rch->pkt_sig)) { + DBG_WARN(("Tx drop: Invalid RCPU signature\n")); + return SHR_E_FAIL; + } + if (pkh->attrs & PDMA_TX_HDR_COOKED) { + /* Resumed packet */ + return SHR_E_NONE; + } + pkh->data_len = data_len + ETH_FCS_LEN; + pkh->meta_len = rch->meta_len; + pkh->attrs = 0; + if (rch->flags & RCPU_FLAG_MODHDR) { + pkh->attrs |= PDMA_TX_HIGIG_PKT; + } + if (rch->flags & RCPU_FLAG_PAUSE) { + pkh->attrs |= PDMA_TX_PAUSE_PKT; + } + if (rch->flags & RCPU_FLAG_PURGE) { + pkh->attrs |= PDMA_TX_PURGE_PKT; + } + if (rch->flags & RCPU_FLAG_BIND_QUE) { + pkh->attrs |= PDMA_TX_BIND_QUE; + } + } else { + /* Non-RCPU encapsulation packet */ + data_len = pkh->data_len - ETH_FCS_LEN; + pkt_len = PKT_HDR_SIZE + pkh->meta_len + data_len; + if (skb->len == pkt_len && pkh->attrs & PDMA_TX_HDR_COOKED && + pkh->pkt_sig == dev->rcpu_ctrl.pkt_sig) { + /* Resumed packet */ + return SHR_E_NONE; + } + meta_len = 0; + if (priv->type == NGKNET_NETIF_T_PORT) { + meta_len = priv->meta_len; + if (!meta_len) { + printk("Tx abort: no metadata\n"); + return SHR_E_UNAVAIL; + } + } + if (skb_header_cloned(skb) || + skb_headroom(skb) < (PKT_HDR_SIZE + meta_len + VLAN_HLEN) || + skb_tailroom(skb) < ETH_FCS_LEN) { + nskb = skb_copy_expand(skb, PKT_HDR_SIZE + meta_len + VLAN_HLEN, + ETH_FCS_LEN, GFP_ATOMIC); + if (!nskb) { + return SHR_E_MEMORY; + } + skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags; + skb = nskb; + } + skb_push(skb, PKT_HDR_SIZE + meta_len); + memset(skb->data, 0, PKT_HDR_SIZE + meta_len); + pkh = (struct pkt_hdr *)skb->data; + pkh->data_len = skb->len - PKT_HDR_SIZE - meta_len + ETH_FCS_LEN; + pkh->meta_len = meta_len; + pkh->attrs = 0; + if (priv->type == NGKNET_NETIF_T_PORT) { + /* Send to physical port using netif metadata */ + if (priv->meta_off) { + memmove(skb->data + PKT_HDR_SIZE, skb->data + PKT_HDR_SIZE + meta_len, priv->meta_off); + } + memcpy(skb->data + PKT_HDR_SIZE + priv->meta_off, priv->meta_data, priv->meta_len); + pkh->attrs |= PDMA_TX_HIGIG_PKT; + } + pkh->pkt_sig = dev->rcpu_ctrl.pkt_sig; + } + + /* Packet header done here */ + pkh->attrs |= PDMA_TX_HDR_COOKED; + + data = skb->data + PKT_HDR_SIZE + pkh->meta_len; + tpid = data[12] << 8 | data[13]; + tag_len = (tpid == ETH_P_8021Q || tpid == ETH_P_8021AD) ? VLAN_HLEN : 0; + + /* Need to add VLAN tag if packet is untagged */ + if (!tag_len && (!(pkh->attrs & PDMA_TX_HIGIG_PKT) || priv->flags & NGKNET_NETIF_F_ADD_TAG)) { + copy_len = PKT_HDR_SIZE + pkh->meta_len + 2 * ETH_ALEN; + if (skb_header_cloned(skb) || skb_headroom(skb) < VLAN_HLEN) { + nskb = skb_copy_expand(skb, VLAN_HLEN, 0, GFP_ATOMIC); + if (!nskb) { + return SHR_E_MEMORY; + } + skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags; + skb = nskb; + } + skb_push(skb, VLAN_HLEN); + memmove(skb->data, skb->data + VLAN_HLEN, copy_len); + pkh = (struct pkt_hdr *)skb->data; + data = skb->data + PKT_HDR_SIZE + pkh->meta_len; + data[12] = 0x81; + data[13] = 0x00; + data[14] = priv->vlan >> 8 & 0xf; + data[15] = priv->vlan & 0xff; + pkh->data_len += VLAN_HLEN; + tag_len = VLAN_HLEN; + } + + /* Optional callback handle */ + if (dev->cbc->tx_cb) { + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + cbd->dev_no = dev->dev_no; + cbd->dev_id = dev->pdma_dev.dev_id; + cbd->type_str = drv_ops[dev->pdma_dev.dev_type]->drv_desc; + cbd->priv = priv; + cbd->pmd = skb->data + PKT_HDR_SIZE; + cbd->pmd_len = pkh->meta_len; + cbd->pkt_len = skb->len - PKT_HDR_SIZE - pkh->meta_len; + skb = dev->cbc->tx_cb(skb); + if (!skb) { + if (!nskb) { + *oskb = NULL; + } + return SHR_E_UNAVAIL; + } + pkh = (struct pkt_hdr *)skb->data; + pkh->data_len = skb->len - PKT_HDR_SIZE - pkh->meta_len + ETH_FCS_LEN; + } + + /* Pad packet if needed */ + if (pkh->data_len < (64 + tag_len)) { + pkh->data_len = 64 + tag_len; + if (skb_padto(skb, PKT_HDR_SIZE + pkh->meta_len + pkh->data_len - ETH_FCS_LEN)) { + if (!nskb) { + *oskb = NULL; + } + return SHR_E_MEMORY; + } + } + + /* Update SKB pointer */ + *oskb = skb; + + return SHR_E_NONE; +} + +/*! + * Suspend Tx queue callback + */ +static void +ngknet_tx_suspend(struct pdma_dev *pdev, int queue) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + unsigned long flags; + int vdi; + + netif_stop_subqueue(dev->net_dev, queue); + + spin_lock_irqsave(&dev->lock, flags); + for (vdi = 1; vdi <= NUM_VDEV_MAX; vdi++) { + if (!dev->vdev[vdi]) { + continue; + } + netif_stop_subqueue(dev->vdev[vdi], queue); + } + spin_unlock_irqrestore(&dev->lock, flags); +} + +/*! + * Resume Tx queue callback + */ +static void +ngknet_tx_resume(struct pdma_dev *pdev, int queue) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + unsigned long flags; + int vdi; + + if (__netif_subqueue_stopped(dev->net_dev, queue)) { + netif_wake_subqueue(dev->net_dev, queue); + } + + spin_lock_irqsave(&dev->lock, flags); + for (vdi = 1; vdi <= NUM_VDEV_MAX; vdi++) { + if (!dev->vdev[vdi]) { + continue; + } + if (__netif_subqueue_stopped(dev->vdev[vdi], queue)) { + netif_wake_subqueue(dev->vdev[vdi], queue); + } + } + spin_unlock_irqrestore(&dev->lock, flags); + + if (pdev->mode == DEV_MODE_HNET) { + atomic_set(&dev->hnet_active, 1); + wake_up_interruptible(&dev->hnet_wq); + } +} + +/*! + * Enable interrupt callback + */ +static void +ngknet_intr_enable(struct pdma_dev *pdev, int cmc, int chan, + uint32_t reg, uint32_t mask) +{ + pdev->ctrl.grp[cmc].irq_mask |= mask; + ngbde_kapi_intr_mask_write(pdev->unit, 0, reg, pdev->ctrl.grp[cmc].irq_mask); +} + +/*! + * Disable interrupt callback + */ +static void +ngknet_intr_disable(struct pdma_dev *pdev, int cmc, int chan, + uint32_t reg, uint32_t mask) +{ + pdev->ctrl.grp[cmc].irq_mask &= ~mask; + ngbde_kapi_intr_mask_write(pdev->unit, 0, reg, pdev->ctrl.grp[cmc].irq_mask); +} + +/*! + * NAPI polling function + */ +static int +ngknet_poll(struct napi_struct *napi, int budget) +{ + struct ngknet_intr_handle *kih = (struct ngknet_intr_handle *)napi; + struct intr_handle *hdl = kih->hdl; + struct pdma_dev *pdev = (struct pdma_dev *)hdl->dev; + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + unsigned long flags; + int work_done; + + DBG_NAPI(("Scheduled NAPI on queue %d.\n", hdl->queue)); + + kih->napi_resched = 0; + kih->napi_pending = 0; + + if (pdev->flags & PDMA_GROUP_INTR) { + work_done = bcmcnet_group_poll(pdev, hdl->group, budget); + } else { + work_done = bcmcnet_queue_poll(pdev, hdl, budget); + } + + if (work_done < budget) { + napi_complete(napi); + if (kih->napi_pending && napi_schedule_prep(napi)) { + __napi_schedule(napi); + return work_done; + } + spin_lock_irqsave(&dev->lock, flags); + if (!kih->napi_resched) { + if (pdev->flags & PDMA_GROUP_INTR) { + bcmcnet_group_intr_enable(pdev, hdl->group); + } else { + bcmcnet_queue_intr_enable(pdev, hdl); + } + } + spin_unlock_irqrestore(&dev->lock, flags); + } + + return work_done; +} + +/*! + * NGKNET ISR + */ +static int +ngknet_isr(void *isr_data) +{ + struct ngknet_dev *dev = isr_data; + struct pdma_dev *pdev = &dev->pdma_dev; + struct intr_handle *hdl = NULL; + struct napi_struct *napi = NULL; + unsigned long flags; + int gi, qi; + int iv = 0; + + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < pdev->grp_queues; qi++) { + hdl = &pdev->ctrl.grp[gi].intr_hdl[qi]; + if (pdev->flags & PDMA_GROUP_INTR) { + if (!bcmcnet_group_intr_check(pdev, gi)) { + break; + } + } else { + if (!bcmcnet_queue_intr_check(pdev, hdl)) { + continue; + } + } + spin_lock_irqsave(&dev->lock, flags); + if (pdev->flags & PDMA_GROUP_INTR) { + bcmcnet_group_intr_disable(pdev, gi); + } else { + bcmcnet_queue_intr_disable(pdev, hdl); + } + spin_unlock_irqrestore(&dev->lock, flags); + napi = (struct napi_struct *)hdl->priv; + if (likely(napi_schedule_prep(napi))) { + __napi_schedule(napi); + } + iv++; + if (pdev->flags & PDMA_GROUP_INTR) { + break; + } + } + } + + if (iv) { + DBG_IRQ(("Got interrupt on device %d.\n", dev->dev_no)); + pdev->stats.intrs++; + return IRQ_HANDLED; + } else { + return IRQ_NONE; + } +} + +/*! + * Hypervisor network work handler + */ +static void +ngknet_dev_hnet_work(struct pdma_dev *pdev) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + struct intr_handle *hdl = NULL; + struct napi_struct *napi = NULL; + struct ngknet_intr_handle *kih = NULL; + unsigned long flags; + int gi, qi; + + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < pdev->grp_queues; qi++) { + hdl = &pdev->ctrl.grp[gi].intr_hdl[qi]; + napi = (struct napi_struct *)hdl->priv; + kih = (struct ngknet_intr_handle *)napi; + kih->napi_pending = 1; + if (napi_schedule_prep(napi)) { + spin_lock_irqsave(&dev->lock, flags); + kih->napi_resched = 1; + spin_unlock_irqrestore(&dev->lock, flags); + local_bh_disable(); + __napi_schedule(napi); + local_bh_enable(); + } + if (pdev->flags & PDMA_GROUP_INTR) { + break; + } + } + } +} + +/*! + * Hypervisor network wait handler + */ +static int +ngknet_dev_hnet_wait(struct pdma_dev *pdev) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + int qi; + int rv; + + while (!kthread_should_stop()) { + wait_event_interruptible(dev->hnet_wq, + atomic_read(&dev->hnet_active) != 0); + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + schedule_timeout(HZ); + continue; + } + atomic_set(&dev->hnet_active, 0); + for (qi = 0; qi < pdev->ctrl.nb_txq; qi++) { + do { + rv = pdev->pkt_xmit(pdev, qi, 0); + } while (rv == SHR_E_NONE); + } + schedule_work(&dev->hnet_work); + } + + return 0; +} + +/*! + * Hypervisor network wake handler + */ +static int +ngknet_dev_vnet_wake(struct pdma_dev *pdev) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + + atomic_set(&dev->vnet_active, 1); + wake_up_interruptible(&dev->vnet_wq); + + return SHR_E_NONE; +} + +/*! + * Hypervisor network process + */ +static int +ngknet_dev_hnet_process(void *data) +{ + return ngknet_dev_hnet_wait((struct pdma_dev *)data); +} + +/*! + * Hypervisor network schedule + */ +static void +ngknet_dev_hnet_schedule(struct work_struct *work) +{ + struct ngknet_dev *dev = container_of(work, struct ngknet_dev, hnet_work); + + ngknet_dev_hnet_work(&dev->pdma_dev); +} + +/*! + * Convert physical address to virtual address + */ +static void * +ngknet_sys_p2v(struct pdma_dev *pdev, uint64_t paddr) +{ + return ngbde_kapi_dma_bus_to_virt(pdev->unit, (dma_addr_t)paddr); +} + +/*! + * Convert virtual address to physical address + */ +static uint64_t +ngknet_sys_v2p(struct pdma_dev *pdev, void *vaddr) +{ + return (uint64_t)ngbde_kapi_dma_virt_to_bus(pdev->unit, vaddr); +} + +/*! + * Open network device + */ +static int +ngknet_enet_open(struct net_device *ndev) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct pdma_dev *pdev = &dev->pdma_dev; + struct napi_struct *napi = NULL; + unsigned long bm_queue; + int gi, qi; + int rv; + + if (!pdev->ctrl.bm_rxq || !pdev->ctrl.bm_txq) { + printk("Not config Rx or Tx queue yet!\n"); + return -EPERM; + } + + if (priv->id <= 0) { + /* Register interrupt handler */ + ngbde_kapi_intr_connect(dev->dev_no, 0, ngknet_isr, dev); + + /* Start PDMA device */ + rv = bcmcnet_pdma_dev_start(pdev); + if (SHR_FAILURE(rv)) { + ngbde_kapi_intr_disconnect(dev->dev_no, 0); + return -EPERM; + } + + /* Start rate limit */ + if (rx_rate_limit >= 0) { + ngknet_rx_rate_limit_start(dev); + } + + /* Notify the stack of the actual queue counts. */ + rv = netif_set_real_num_rx_queues(dev->net_dev, pdev->ctrl.nb_rxq); + if (rv < 0) { + ngbde_kapi_intr_disconnect(dev->dev_no, 0); + return rv; + } + rv = netif_set_real_num_tx_queues(dev->net_dev, pdev->ctrl.nb_txq); + if (rv < 0) { + ngbde_kapi_intr_disconnect(dev->dev_no, 0); + return rv; + } + + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + bm_queue = pdev->ctrl.grp[gi].bm_rxq | pdev->ctrl.grp[gi].bm_txq; + for (qi = 0; qi < pdev->grp_queues; qi++) { + napi = (struct napi_struct *)pdev->ctrl.grp[gi].intr_hdl[qi].priv; + if (pdev->flags & PDMA_GROUP_INTR) { + napi_enable(napi); + break; + } + if (1 << qi & bm_queue) { + napi_enable(napi); + } + } + } + } else { + /* Notify the stack of the actual queue counts. */ + rv = netif_set_real_num_rx_queues(ndev, pdev->ctrl.nb_rxq); + if (rv < 0) { + return rv; + } + rv = netif_set_real_num_tx_queues(ndev, pdev->ctrl.nb_txq); + if (rv < 0) { + return rv; + } + } + + /* Prevent tx timeout */ + kal_netif_trans_update(ndev); + + netif_tx_wake_all_queues(ndev); + + return 0; +} + +/*! + * Stop network device + */ +static int +ngknet_enet_stop(struct net_device *ndev) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct pdma_dev *pdev = &dev->pdma_dev; + struct napi_struct *napi = NULL; + unsigned long bm_queue; + int gi, qi; + + netif_tx_stop_all_queues(ndev); + + if (priv->id <= 0) { + /* Stop rate limit */ + if (rx_rate_limit >= 0) { + ngknet_rx_rate_limit_stop(dev); + } + + /* Suspend PDMA device */ + bcmcnet_pdma_dev_suspend(pdev); + + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + bm_queue = pdev->ctrl.grp[gi].bm_rxq | pdev->ctrl.grp[gi].bm_txq; + for (qi = 0; qi < pdev->grp_queues; qi++) { + napi = (struct napi_struct *)pdev->ctrl.grp[gi].intr_hdl[qi].priv; + if (pdev->flags & PDMA_GROUP_INTR) { + napi_disable(napi); + break; + } + if (1 << qi & bm_queue) { + napi_disable(napi); + } + } + } + + /* Stop PDMA device */ + bcmcnet_pdma_dev_stop(pdev); + + /* Unregister interrupt handler */ + ngbde_kapi_intr_disconnect(dev->dev_no, 0); + } + + return 0; +} + +/*! + * Start transmission + */ +static int +ngknet_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct pdma_dev *pdev = &dev->pdma_dev; + struct sk_buff *bskb = skb; + uint32_t len = skb->len; + int queue; + int rv; + + DBG_VERB(("Tx packet from ndev%d (%d bytes).\n", priv->id, skb->len)); + if (debug & DBG_LVL_PDMP) { + ngknet_pkt_dump(skb->data, skb->len); + } + + /* Do not transmit on base device */ + if (priv->id <= 0) { + priv->stats.tx_dropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + /* Measure speed */ + if (debug & DBG_LVL_RATE) { + ngknet_pkt_stats(pdev, PDMA_Q_TX); + } + + queue = skb->queue_mapping; + + /* Handle one outgoing packet */ + rv = ngknet_tx_frame_process(ndev, &skb); + if (SHR_FAILURE(rv)) { + priv->stats.tx_dropped++; + if (skb) { + dev_kfree_skb_any(skb); + } + return NETDEV_TX_OK; + } + + /* Schedule Tx queue */ + ngknet_tx_queue_schedule(dev, skb, &queue); + skb->queue_mapping = queue; + + DBG_VERB(("Tx packet (%d bytes).\n", skb->len)); + if (debug & DBG_LVL_PDMP) { + ngknet_pkt_dump(skb->data, skb->len); + } + + /* Do Tx timestamping */ + if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { + ngknet_ptp_tx_config(ndev, skb); + } + + skb_tx_timestamp(skb); + + rv = pdev->pkt_xmit(pdev, queue, skb); + + if (rv == SHR_E_UNAVAIL) { + DBG_WARN(("Tx drop: DMA device not ready\n")); + priv->stats.tx_dropped++; + if (skb != bskb) { + dev_kfree_skb_any(skb); + } + dev_kfree_skb_any(bskb); + return NETDEV_TX_OK; + } + + if (rv == SHR_E_BUSY) { + DBG_WARN(("Tx suspend: No DMA resources\n")); + priv->stats.tx_fifo_errors++; + if (skb != bskb) { + dev_kfree_skb_any(skb); + } + return NETDEV_TX_BUSY; + } else { + if (skb != bskb) { + dev_kfree_skb_any(bskb); + } + } + + /* Update accounting */ + priv->stats.tx_packets++; + priv->stats.tx_bytes += len; + + return NETDEV_TX_OK; +} + +/*! + * Get network device stats + */ +static struct net_device_stats * +ngknet_get_stats(struct net_device *ndev) +{ + struct ngknet_private *priv = netdev_priv(ndev); + + return &priv->stats; +} + +/*! + * Set network device MC list + */ +static void +ngknet_set_multicast_list(struct net_device *ndev) +{ + return; +} + +/*! + * Set network device MAC address + */ +static int +ngknet_set_mac_address(struct net_device *ndev, void *addr) +{ + if (!is_valid_ether_addr(((struct sockaddr *)addr)->sa_data)) { + return -EINVAL; + } + + netdev_info(ndev, "Setting new MAC address\n"); + memcpy(ndev->dev_addr, ((struct sockaddr *)addr)->sa_data, ndev->addr_len); + + return 0; +} + +/*! + * Change network device MTU + */ +static int +ngknet_change_mtu(struct net_device *ndev, int new_mtu) +{ + int frame_size = new_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN; + + if (frame_size < 68 || frame_size > rx_buffer_size) { + return -EINVAL; + } + + netdev_info(ndev, "Changing MTU from %d to %d\n", ndev->mtu, new_mtu); + ndev->mtu = new_mtu; + + return 0; +} + +/*! + * Do I/O control + */ +static int +ngknet_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct hwtstamp_config config; + int rv; + + if (cmd == SIOCSHWTSTAMP) { + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) { + return -EFAULT; + } + + if (priv->type != NGKNET_NETIF_T_PORT) { + return -ENOSYS; + } + + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + priv->hwts_tx_type = HWTSTAMP_TX_OFF; + rv = ngknet_ptp_tx_config_set(ndev, priv->hwts_tx_type); + if (SHR_FAILURE(rv)) { + return -ENOSYS; + } + break; + case HWTSTAMP_TX_ON: + priv->hwts_tx_type = HWTSTAMP_TX_ON; + rv = ngknet_ptp_tx_config_set(ndev, priv->hwts_tx_type); + if (SHR_FAILURE(rv)) { + return -ENOSYS; + } + break; + case HWTSTAMP_TX_ONESTEP_SYNC: + priv->hwts_tx_type = HWTSTAMP_TX_ONESTEP_SYNC; + rv = ngknet_ptp_tx_config_set(ndev, priv->hwts_tx_type); + if (SHR_FAILURE(rv)) { + return -ENOSYS; + } + break; + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + rv = ngknet_ptp_rx_config_set(ndev, &config.rx_filter); + if (SHR_FAILURE(rv)) { + return -ENOSYS; + } + priv->hwts_rx_filter = HWTSTAMP_FILTER_NONE; + break; + default: + rv = ngknet_ptp_rx_config_set(ndev, &config.rx_filter); + if (SHR_FAILURE(rv)) { + return -ENOSYS; + } + priv->hwts_rx_filter = config.rx_filter; + break; + } + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) + if (cmd == SIOCGHWTSTAMP) { + config.flags = 0; + config.tx_type = priv->hwts_tx_type; + config.rx_filter = priv->hwts_rx_filter; + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; + } +#endif + + return -EINVAL; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +/*! + * Poll network device + */ +static void +ngknet_poll_controller(struct net_device *ndev) +{ + struct ngknet_private *priv = netdev_priv(ndev); + + disable_irq(ndev->irq); + ngknet_isr(priv->bkn_dev); + enable_irq(ndev->irq); +} +#endif + +static const struct net_device_ops ngknet_netdev_ops = { + .ndo_open = ngknet_enet_open, + .ndo_stop = ngknet_enet_stop, + .ndo_start_xmit = ngknet_start_xmit, + .ndo_get_stats = ngknet_get_stats, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = ngknet_set_multicast_list, + .ndo_set_mac_address = ngknet_set_mac_address, + .ndo_change_mtu = ngknet_change_mtu, + .ndo_set_features = NULL, + .ndo_do_ioctl = ngknet_do_ioctl, + .ndo_tx_timeout = NULL, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ngknet_poll_controller, +#endif +}; + +static void +ngknet_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) +{ + strlcpy(drvinfo->driver, "linux_ngknet", sizeof(drvinfo->driver)); + snprintf(drvinfo->version, sizeof(drvinfo->version), "%d", NGKNET_IOC_VERSION); + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info)); +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)) +static int +ngknet_get_ts_info(struct net_device *ndev, struct ethtool_ts_info *info) +{ + int rv; + + info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON | 1 << HWTSTAMP_TX_ONESTEP_SYNC; + info->rx_filters = 1 << HWTSTAMP_FILTER_NONE | 1 << HWTSTAMP_FILTER_ALL; + rv = ngknet_ptp_phc_index_get(ndev, &info->phc_index); + if (SHR_FAILURE(rv)) { + info->phc_index = -1; + } + + return 0; +} +#endif + +static const struct ethtool_ops ngknet_ethtool_ops = { + .get_drvinfo = ngknet_get_drvinfo, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)) + .get_ts_info = ngknet_get_ts_info, +#endif +}; + +/*! + * \brief Initialize network device. + * + * \param [in] name Network device name. + * \param [in] mac Network device MAC address. + * \param [out] nd New registered network device. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_ndev_init(ngknet_netif_t *netif, struct net_device **nd) +{ + struct net_device *ndev = NULL; + uint8_t *ma; + int rv; + + if (!netif) { + DBG_WARN(("Network interface is NULL.\n")); + return SHR_E_PARAM; + } + if (!nd) { + DBG_WARN(("Network device is NULL.\n")); + return SHR_E_PARAM; + } + + ndev = alloc_etherdev_mq(sizeof(struct ngknet_private), NUM_QUE_MAX); + if (!ndev) { + DBG_WARN(("Error allocating network device.\n")); + return SHR_E_MEMORY; + } + if (!ndev->dev_addr) { + DBG_WARN(("ndev->dev_addr is NULL\n")); + free_netdev(ndev); + return SHR_E_INTERNAL; + } + + /* Device information -- not available right now */ + ndev->irq = 0; + ndev->base_addr = 0; + + /* Fill in the dev structure */ + ndev->watchdog_timeo = 5 * HZ; + + /* Default MTU should not exceed MTU of switch front-panel ports */ + ndev->mtu = netif->mtu; + if (!ndev->mtu) { + ndev->mtu = default_mtu ? default_mtu : rx_buffer_size; + } + + ndev->netdev_ops = &ngknet_netdev_ops; + ndev->ethtool_ops = &ngknet_ethtool_ops; + + /* Network device name */ + if (netif->name && *netif->name) { + strncpy(ndev->name, netif->name, IFNAMSIZ - 1); + } + + /* Set the device MAC address */ + ma = netif->macaddr; + if ((ma[0] | ma[1] | ma[2] | ma[3] | ma[4] | ma[5]) == 0) { + ngknet_dev_mac[5]++; + ma = ngknet_dev_mac; + } + memcpy(ndev->dev_addr, ma, ETH_ALEN); + + /* Initialize the device features */ + ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX; + ndev->features |= NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_CTAG_RX; + + /* Register the kernel network device */ + rv = register_netdev(ndev); + if (rv < 0) { + DBG_WARN(("Error registering network device %s.\n", ndev->name)); + free_netdev(ndev); + return SHR_E_FAIL; + } + + *nd = ndev; + + DBG_VERB(("Created network device %s.\n", ndev->name)); + + return SHR_E_NONE; +} + +/*! + * \brief Initialize Packet DMA device. + * + * \param [in] dev NGKNET device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_pdev_init(struct ngknet_dev *dev) +{ + struct pdma_dev *pdev = &dev->pdma_dev; + int rv; + + /* Initialize PDMA control structure */ + pdev->unit = dev->dev_no; + pdev->priv = dev; + pdev->ctrl.dev = pdev; + pdev->ctrl.hw_addr = dev->base_addr; + pdev->ctrl.rx_buf_size = rx_buffer_size; + + /* Hook callbacks */ + pdev->dev_read32 = ngknet_dev_read32; + pdev->dev_write32 = ngknet_dev_write32; + pdev->pkt_recv = ngknet_frame_recv; + pdev->tx_suspend = ngknet_tx_suspend; + pdev->tx_resume = ngknet_tx_resume; + pdev->intr_unmask = ngknet_intr_enable; + pdev->intr_mask = ngknet_intr_disable; + pdev->xnet_wait = ngknet_dev_hnet_wait; + pdev->xnet_wake = ngknet_dev_vnet_wake; + pdev->sys_p2v = ngknet_sys_p2v; + pdev->sys_v2p = ngknet_sys_v2p; + + pdev->flags |= PDMA_GROUP_INTR; + if (tx_polling) { + pdev->flags |= PDMA_TX_POLLING; + } + if (rx_batching || pdev->mode == DEV_MODE_HNET) { + pdev->flags |= PDMA_RX_BATCHING; + } + + /* Attach PDMA driver */ + rv = drv_ops[pdev->dev_type]->drv_attach(pdev); + if (SHR_FAILURE(rv)) { + DBG_WARN(("Attach DMA driver failed.\n")); + return rv; + } + + /* Initialize PDMA device */ + rv = bcmcnet_pdma_dev_init(pdev); + if (SHR_FAILURE(rv)) { + DBG_WARN(("Init DMA device.failed.\n")); + return rv; + } + + DBG_VERB(("Attached DMA device %s.\n", pdev->name)); + + return SHR_E_NONE; +} + +/*! + * \brief Get device information from BDE. + * + * \param [in] dn Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_dev_info_get(int dn) +{ + struct ngknet_dev *dev = &ngknet_devices[dn]; + + dev->base_addr = ngbde_kapi_pio_membase(dn); + dev->dev = ngbde_kapi_dma_dev_get(dn); + + if (!dev->base_addr || !dev->dev) { + return SHR_E_ACCESS; + } + + dev->dev_no = dn; + + return SHR_E_NONE; +} + +/*! + * \brief Probe device. + * + * Get the information from BDE, initialize Packet DMA device, + * initialize base network device and allocate other resources. + * + * \param [in] dn Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_dev_probe(int dn, ngknet_netif_t *netif) +{ + struct ngknet_dev *dev = &ngknet_devices[dn]; + struct pdma_dev *pdev = &dev->pdma_dev; + struct net_device *ndev = NULL; + struct ngknet_private *priv = NULL; + struct intr_handle *hdl = NULL; + struct cpumask mask; + int gi, qi; + int rv; + + DBG_VERB(("%s: dev %d\n",__FUNCTION__, dn)); + + /* Get device information */ + rv = ngknet_dev_info_get(dn); + if (SHR_FAILURE(rv)) { + return rv; + } + + /* Initialize PDMA device */ + rv = ngknet_pdev_init(dev); + if (SHR_FAILURE(rv)) { + return rv; + } + + /* Get base network device name */ + if (netif->name[0] == '\0') { + /* Reserve 6 vacancies for base&vitual device number, i.e. nameAB_XYZ */ + if (strlen(base_dev_name) < IFNAMSIZ - 6) { + snprintf(netif->name, IFNAMSIZ, "%s%d", base_dev_name, dn); + } else { + DBG_WARN(("Too long network device name: %s.\n", base_dev_name)); + return SHR_E_PARAM; + } + } + + rv = ngknet_ndev_init(netif, &ndev); + if (SHR_FAILURE(rv)) { + bcmcnet_pdma_dev_cleanup(pdev); + return rv; + } + dev->net_dev = ndev; + + /* Initialize private information for base network device */ + priv = netdev_priv(ndev); + priv->net_dev = ndev; + priv->bkn_dev = dev; + priv->id = 0; + priv->type = netif->type; + if (priv->type == NGKNET_NETIF_T_PORT) { + priv->meta_off = netif->meta_off; + priv->meta_len = netif->meta_len; + memcpy(priv->meta_data, netif->meta_data, priv->meta_len); + } + priv->flags = netif->flags; + priv->vlan = netif->vlan; + priv->chan = netif->chan; + memcpy(priv->user_data, netif->user_data, sizeof(priv->user_data)); + + netif->id = priv->id; + memcpy(netif->macaddr, ndev->dev_addr, ETH_ALEN); + netif->mtu = ndev->mtu; + memcpy(netif->name, ndev->name, sizeof(netif->name) - 1); + + if (priv->flags & NGKNET_NETIF_F_BIND_CHAN) { + dev->bdev[priv->chan] = ndev; + } + + /* Register for napi */ + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < pdev->grp_queues; qi++) { + hdl = &pdev->ctrl.grp[gi].intr_hdl[qi]; + priv_hdl[hdl->unit][hdl->chan].hdl = hdl; + hdl->priv = &priv_hdl[hdl->unit][hdl->chan]; + netif_napi_add(ndev, (struct napi_struct *)hdl->priv, + ngknet_poll, pdev->ctrl.budget); + if (pdev->flags & PDMA_GROUP_INTR) { + break; + } + } + } + + /* Get callback control */ + ngknet_callback_control_get(&dev->cbc); + + INIT_LIST_HEAD(&dev->filt_list); + spin_lock_init(&dev->lock); + init_waitqueue_head(&dev->wq); + if (pdev->mode == DEV_MODE_HNET) { + init_waitqueue_head(&dev->vnet_wq); + atomic_set(&dev->vnet_active, 0); + init_waitqueue_head(&dev->hnet_wq); + atomic_set(&dev->hnet_active, 0); + dev->hnet_task = kthread_run(ngknet_dev_hnet_process, pdev, pdev->name); + if (IS_ERR(dev->hnet_task)) { + dev->hnet_task = NULL; + return SHR_E_INTERNAL; + } + cpumask_clear(&mask); + cpumask_set_cpu(1, &mask); + set_cpus_allowed_ptr(dev->hnet_task, &mask); + INIT_WORK(&dev->hnet_work, ngknet_dev_hnet_schedule); + } + + skb_queue_head_init(&dev->ptp_tx_queue); + INIT_WORK(&dev->ptp_tx_work, ngknet_ptp_tx_work); + + dev->flags |= NGKNET_DEV_ACTIVE; + + DBG_NDEV(("Broadcom NGKNET Attached\n")); + DBG_NDEV(("MAC: %pM\n", ndev->dev_addr)); + DBG_NDEV(("Running with NAPI enabled\n")); + + return SHR_E_NONE; +} + +/*! + * \brief Remove device. + * + * Suspend device firstly, destroy all virtual network devices + * and filters, clean up Packet DMA device. + * + * \param [in] dn Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_dev_remove(int dn) +{ + struct ngknet_dev *dev = &ngknet_devices[dn]; + struct pdma_dev *pdev = &dev->pdma_dev; + struct net_device *ndev = NULL; + struct intr_handle *hdl = NULL; + int di, gi, qi; + int rv; + + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + return SHR_E_NONE; + } + + DBG_VERB(("%s: dev %d\n",__FUNCTION__, dn)); + + dev->flags &= ~NGKNET_DEV_ACTIVE; + + skb_queue_purge(&dev->ptp_tx_queue); + + if (pdev->mode == DEV_MODE_HNET && dev->hnet_task) { + atomic_set(&dev->hnet_active, 1); + wake_up_interruptible(&dev->hnet_wq); + kthread_stop(dev->hnet_task); + dev->hnet_task = NULL; + } + + /* Destroy all the filters */ + ngknet_filter_destroy_all(dev); + + /* Destroy all the virtual devices */ + for (di = 1; di <= NUM_VDEV_MAX; di++) { + ndev = dev->vdev[di]; + if (ndev) { + netif_carrier_off(ndev); + unregister_netdev(ndev); + free_netdev(ndev); + dev->vdev[di] = NULL; + } + } + dev->vdev[0] = NULL; + + DBG_VERB(("Removing base network device %s.\n", dev->net_dev->name)); + + /* Destroy the base network device */ + ndev = dev->net_dev; + unregister_netdev(ndev); + free_netdev(ndev); + + for (qi = 0; qi < NUM_QUE_MAX; qi++) { + dev->bdev[qi] = NULL; + } + + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < pdev->grp_queues; qi++) { + hdl = &pdev->ctrl.grp[gi].intr_hdl[qi]; + netif_napi_del((struct napi_struct *)hdl->priv); + priv_hdl[hdl->unit][hdl->chan].hdl = NULL; + if (pdev->flags & PDMA_GROUP_INTR) { + break; + } + } + } + + /* Clean up PDMA device */ + bcmcnet_pdma_dev_cleanup(pdev); + + /* Detach PDMA driver */ + rv = drv_ops[pdev->dev_type]->drv_detach(pdev); + if (SHR_FAILURE(rv)) { + DBG_WARN(("Detach DMA driver failed.\n")); + } + + return rv; +} + +/*! + * Network interface functions + */ + +int +ngknet_netif_create(struct ngknet_dev *dev, ngknet_netif_t *netif) +{ + struct net_device *ndev = NULL; + struct ngknet_private *priv = NULL; + unsigned long flags; + int num, id; + int rv; + + switch (netif->type) { + case NGKNET_NETIF_T_VLAN: + case NGKNET_NETIF_T_PORT: + case NGKNET_NETIF_T_META: + break; + default: + return SHR_E_UNAVAIL; + } + + /* Get vitual network device name */ + if (netif->name[0] == '\0') { + /* Reserve 6 vacancies for base&vitual device number, i.e. nameAB_XYZ */ + if (strlen(base_dev_name) < IFNAMSIZ - 6) { + snprintf(netif->name, IFNAMSIZ, "%s%d%s", base_dev_name, dev->dev_no, "_"); + strncat(netif->name, "%d", 3); + } else { + DBG_WARN(("Too long network device name: %s.\n", base_dev_name)); + return SHR_E_PARAM; + } + } + + rv = ngknet_ndev_init(netif, &ndev); + if (SHR_FAILURE(rv)) { + return rv; + } + + spin_lock_irqsave(&dev->lock, flags); + + num = (long)dev->vdev[0]; + for (id = 1; id < num + 1; id++) { + if (!dev->vdev[id]) { + break; + } + } + if (id > NUM_VDEV_MAX) { + spin_unlock_irqrestore(&dev->lock, flags); + unregister_netdev(ndev); + free_netdev(ndev); + return SHR_E_RESOURCE; + } + + dev->vdev[id] = ndev; + num += id == (num + 1) ? 1 : 0; + dev->vdev[0] = (struct net_device *)(long)num; + + spin_unlock_irqrestore(&dev->lock, flags); + + priv = netdev_priv(ndev); + priv->net_dev = ndev; + priv->bkn_dev = dev; + priv->id = id; + priv->type = netif->type; + if (priv->type == NGKNET_NETIF_T_PORT) { + priv->meta_off = netif->meta_off; + priv->meta_len = netif->meta_len; + memcpy(priv->meta_data, netif->meta_data, priv->meta_len); + } + priv->flags = netif->flags; + priv->vlan = netif->vlan; + priv->chan = netif->chan; + memcpy(priv->user_data, netif->user_data, sizeof(priv->user_data)); + + netif->id = priv->id; + memcpy(netif->macaddr, ndev->dev_addr, ETH_ALEN); + netif->mtu = ndev->mtu; + memcpy(netif->name, ndev->name, sizeof(netif->name) - 1); + + if (priv->flags & NGKNET_NETIF_F_BIND_CHAN) { + dev->bdev[priv->chan] = ndev; + } + + /* Optional netif create callback handle */ + if (dev->cbc->netif_create_cb) { + rv = dev->cbc->netif_create_cb(ndev); + if (rv) { + DBG_WARN(("Netif create callback failed with rv %d for '%s'\n", rv, ndev->name)); + } + } + + DBG_VERB(("Created virtual network device %s (%d).\n", ndev->name, priv->id)); + + return SHR_E_NONE; +} + +int +ngknet_netif_destroy(struct ngknet_dev *dev, int id) +{ + struct net_device *ndev = NULL; + struct ngknet_private *priv = NULL; + unsigned long flags; + int num; + DECLARE_WAITQUEUE(wait, current); + + if (id <= 0 || id > NUM_VDEV_MAX) { + return SHR_E_PARAM; + } + + spin_lock_irqsave(&dev->lock, flags); + + ndev = dev->vdev[id]; + if (!ndev) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NOT_FOUND; + } + priv = netdev_priv(ndev); + + add_wait_queue(&dev->wq, &wait); + + while (priv->users) { + priv->wait = 1; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&dev->lock, flags); + schedule(); + spin_lock_irqsave(&dev->lock, flags); + priv->wait = 0; + set_current_state(TASK_RUNNING); + } + + if (priv->flags & NGKNET_NETIF_F_BIND_CHAN) { + dev->bdev[priv->chan] = NULL; + } + + dev->vdev[id] = NULL; + num = (long)dev->vdev[0]; + while (num-- == id--) { + if (dev->vdev[id]) { + dev->vdev[0] = (struct net_device *)(long)num; + break; + } + } + + spin_unlock_irqrestore(&dev->lock, flags); + + remove_wait_queue(&dev->wq, &wait); + + /* Optional netif destroy callback handle */ + if (dev->cbc->netif_destroy_cb) { + int rv = dev->cbc->netif_destroy_cb(ndev); + if (rv) { + DBG_WARN(("Netif destroy callback failed with rv %d for '%s'\n", rv, ndev->name)); + } + } + DBG_VERB(("Removing virtual network device %s (%d).\n", ndev->name, priv->id)); + + netif_carrier_off(ndev); + unregister_netdev(ndev); + free_netdev(ndev); + + return SHR_E_NONE; +} + +int +ngknet_netif_get(struct ngknet_dev *dev, int id, ngknet_netif_t *netif) +{ + struct net_device *ndev = NULL; + struct ngknet_private *priv = NULL; + unsigned long flags; + int num; + + if (id < 0 || id > NUM_VDEV_MAX) { + return SHR_E_PARAM; + } + + spin_lock_irqsave(&dev->lock, flags); + + ndev = id == 0 ? dev->net_dev : dev->vdev[id]; + if (!ndev) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NOT_FOUND; + } + + priv = netdev_priv(ndev); + netif->id = priv->id; + netif->type = priv->type; + netif->flags = priv->flags; + netif->vlan = priv->vlan; + memcpy(netif->macaddr, priv->net_dev->dev_addr, ETH_ALEN); + netif->mtu = priv->net_dev->mtu; + netif->chan = priv->chan; + memcpy(netif->name, priv->net_dev->name, sizeof(netif->name) - 1); + netif->meta_off = priv->meta_off; + netif->meta_len = priv->meta_len; + memcpy(netif->meta_data, priv->meta_data, netif->meta_len); + memcpy(netif->user_data, priv->user_data, sizeof(netif->user_data)); + + num = (long)dev->vdev[0]; + for (id++; id < num + 1; id++) { + if (dev->vdev[id]) { + break; + } + } + netif->next = id == (num + 1) ? 0 : id; + + spin_unlock_irqrestore(&dev->lock, flags); + + DBG_VERB(("Got virtual network device %s (%d).\n", ndev->name, priv->id)); + + return SHR_E_NONE; +} + +int +ngknet_netif_get_next(struct ngknet_dev *dev, ngknet_netif_t *netif) +{ + return ngknet_netif_get(dev, netif->next, netif); +} + +/*! + * System control interfaces + */ + +int +ngknet_debug_level_get(void) +{ + return debug; +} + +void +ngknet_debug_level_set(int debug_level) +{ + debug = debug_level; +} + +int +ngknet_rx_rate_limit_get(void) +{ + return rx_rate_limit; +} + +void +ngknet_rx_rate_limit_set(int rate_limit) +{ + rx_rate_limit = rate_limit; +} + +/*! + * Generic module functions + */ + +static int +ngknet_open(struct inode *inode, struct file *filp) +{ + return 0; +} + +static int +ngknet_release(struct inode *inode, struct file *filp) +{ + return 0; +} + +static long +ngknet_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct ngknet_ioctl ioc; + struct ngknet_dev *dev = NULL; + struct net_device *ndev = NULL; + struct pdma_dev *pdev = NULL; + union { + ngknet_dev_cfg_t dev_cfg; + ngknet_chan_cfg_t chan_cfg; + ngknet_netif_t netif; + ngknet_filter_t filter; + } iod; + ngknet_dev_cfg_t *dev_cfg = &iod.dev_cfg; + ngknet_chan_cfg_t *chan_cfg = &iod.chan_cfg; + ngknet_netif_t *netif = &iod.netif; + ngknet_filter_t *filter = &iod.filter; + char *data = NULL; + int dt, gi, qi; + + if (_IOC_TYPE(cmd) != NGKNET_IOC_MAGIC) { + DBG_WARN(("Unsupported command (cmd=%d)\n", cmd)); + return -EINVAL; + } + + if (copy_from_user(&ioc, (void *)arg, sizeof(ioc))) { + return -EFAULT; + } + + ioc.rc = SHR_E_NONE; + + dev = &ngknet_devices[ioc.unit]; + pdev = &dev->pdma_dev; + + if (cmd != NGKNET_VERSION_GET && + cmd != NGKNET_RX_RATE_LIMIT && + cmd != NGKNET_DEV_INIT && + !(dev->flags & NGKNET_DEV_ACTIVE)) { + ioc.rc = SHR_E_UNAVAIL; + if (copy_to_user((void *)arg, &ioc, sizeof(ioc))) { + return -EFAULT; + } + return 0; + } + + switch (cmd) { + case NGKNET_VERSION_GET: + DBG_CMD(("NGKNET_VERSION_GET\n")); + ioc.op.info.version = NGKNET_IOC_VERSION; + break; + case NGKNET_RX_RATE_LIMIT: + DBG_CMD(("NGKNET_RX_RATE_LIMIT\n")); + if (ioc.iarg[0]) { + ngknet_rx_rate_limit_set(ioc.iarg[1]); + } else { + ioc.iarg[1] = ngknet_rx_rate_limit_get(); + } + break; + case NGKNET_DEV_INIT: + DBG_CMD(("NGKNET_DEV_INIT\n")); + if (dev->flags & NGKNET_DEV_ACTIVE) { + DBG_CMD(("NGKNET_DEV_INIT, retrieve device configurations.\n")); + strlcpy(dev_cfg->name, pdev->name, sizeof(dev_cfg->name)); + dev_cfg->dev_id = pdev->dev_id; + dev_cfg->nb_grp = pdev->ctrl.nb_grp; + dev_cfg->bm_grp = pdev->ctrl.bm_grp; + ioc.rc = ngknet_netif_get(dev, 0, &dev_cfg->base_netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, dev_cfg, + ioc.op.data.len, sizeof(*dev_cfg))) { + return -EFAULT; + } + break; + } + if (kal_copy_from_user(dev_cfg, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*dev_cfg), ioc.op.data.len)) { + return -EFAULT; + } + if (!dev_cfg->name[0] || !dev_cfg->bm_grp || + dev_cfg->bm_grp >= (1 << NUM_GRP_MAX)) { + DBG_WARN(("Invalid parameter: name=%s, bm_grp=0x%x\n", + dev_cfg->name, dev_cfg->bm_grp)); + ioc.rc = SHR_E_PARAM; + break; + } + memset(pdev, 0, sizeof(*pdev)); + strlcpy(pdev->name, dev_cfg->name, sizeof(pdev->name)); + pdev->dev_id = dev_cfg->dev_id; + for (dt = 0; dt < drv_num; dt++) { + if (!drv_ops[dt]) { + continue; + } + if (!strcasecmp(dev_cfg->type_str, drv_ops[dt]->drv_desc)) { + pdev->dev_type = dt; + break; + } + } + if (pdev->dev_type <= NGKNET_DEV_T_NONE || + pdev->dev_type >= NGKNET_DEV_T_COUNT) { + ioc.rc = SHR_E_PARAM; + break; + } + pdev->ctrl.bm_grp = dev_cfg->bm_grp; + for (gi = 0; gi < NUM_GRP_MAX; gi++) { + if (1 << gi & dev_cfg->bm_grp) { + pdev->ctrl.nb_grp++; + pdev->ctrl.grp[gi].attached = 1; + pdev->num_groups = gi + 1; + } + } + pdev->rx_ph_size = dev_cfg->rx_ph_size; + pdev->tx_ph_size = dev_cfg->tx_ph_size; + pdev->mode = dev_cfg->mode; + if (pdev->mode != DEV_MODE_KNET && pdev->mode != DEV_MODE_HNET) { + pdev->mode = DEV_MODE_KNET; + } + ioc.rc = ngknet_dev_probe(ioc.unit, &dev_cfg->base_netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, dev_cfg, + ioc.op.data.len, sizeof(*dev_cfg))) { + return -EFAULT; + } + break; + case NGKNET_DEV_DEINIT: + DBG_CMD(("NGKNET_DEV_DEINIT\n")); + if (dev->flags & NGKNET_DEV_ACTIVE) { + ioc.rc = ngknet_dev_remove(ioc.unit); + } + break; + case NGKNET_QUEUE_CONFIG: + DBG_CMD(("NGKNET_QUEUE_CONFIG\n")); + if (kal_copy_from_user(chan_cfg, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*chan_cfg), ioc.op.data.len)) { + return -EFAULT; + } + gi = chan_cfg->chan / pdev->grp_queues; + if (!(1 << gi & pdev->ctrl.bm_grp)) { + DBG_WARN(("Invalid parameter: chan=%d (bm_grp=0x%x)\n", + chan_cfg->chan, pdev->ctrl.bm_grp)); + ioc.rc = SHR_E_PARAM; + break; + } + if (chan_cfg->dir == PDMA_Q_RX) { + if (1 << chan_cfg->chan & pdev->ctrl.bm_txq) { + pdev->ctrl.bm_txq &= ~(1 << chan_cfg->chan); + pdev->ctrl.nb_txq--; + } + if (!(1 << chan_cfg->chan & pdev->ctrl.bm_rxq)) { + pdev->ctrl.bm_rxq |= 1 << chan_cfg->chan; + pdev->ctrl.nb_rxq++; + } + } else { + if (1 << chan_cfg->chan & pdev->ctrl.bm_rxq) { + pdev->ctrl.bm_rxq &= ~(1 << chan_cfg->chan); + pdev->ctrl.nb_rxq--; + } + if (!(1 << chan_cfg->chan & pdev->ctrl.bm_txq)) { + pdev->ctrl.bm_txq |= 1 << chan_cfg->chan; + pdev->ctrl.nb_txq++; + } + } + qi = chan_cfg->chan % pdev->grp_queues; + pdev->ctrl.grp[gi].nb_desc[qi] = chan_cfg->nb_desc; + pdev->ctrl.grp[gi].rx_size[qi] = chan_cfg->rx_buf_size; + pdev->ctrl.grp[gi].que_ctrl[qi] &= ~(PDMA_PKT_BYTE_SWAP | + PDMA_OTH_BYTE_SWAP | + PDMA_HDR_BYTE_SWAP); + if (chan_cfg->chan_ctrl & NGKNET_PKT_BYTE_SWAP) { + pdev->ctrl.grp[gi].que_ctrl[qi] |= PDMA_PKT_BYTE_SWAP; + } + if (chan_cfg->chan_ctrl & NGKNET_OTH_BYTE_SWAP) { + pdev->ctrl.grp[gi].que_ctrl[qi] |= PDMA_OTH_BYTE_SWAP; + } + if (chan_cfg->chan_ctrl & NGKNET_HDR_BYTE_SWAP) { + pdev->ctrl.grp[gi].que_ctrl[qi] |= PDMA_HDR_BYTE_SWAP; + } + break; + case NGKNET_QUEUE_QUERY: + DBG_CMD(("NGKNET_QUEUE_QUERY\n")); + if (kal_copy_from_user(chan_cfg, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*chan_cfg), ioc.op.data.len)) { + return -EFAULT; + } + if (1 << chan_cfg->chan & pdev->ctrl.bm_rxq) { + chan_cfg->dir = PDMA_Q_RX; + } else if (1 << chan_cfg->chan & pdev->ctrl.bm_txq) { + chan_cfg->dir = PDMA_Q_TX; + } else { + ioc.rc = SHR_E_UNAVAIL; + break; + } + gi = chan_cfg->chan / pdev->grp_queues; + qi = chan_cfg->chan % pdev->grp_queues; + chan_cfg->nb_desc = pdev->ctrl.grp[gi].nb_desc[qi]; + chan_cfg->chan_ctrl = pdev->ctrl.grp[gi].que_ctrl[qi]; + if (chan_cfg->dir == PDMA_Q_RX) { + chan_cfg->rx_buf_size = pdev->ctrl.grp[gi].rx_size[qi]; + } else { + chan_cfg->rx_buf_size = 0; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, chan_cfg, + ioc.op.data.len, sizeof(*chan_cfg))) { + return -EFAULT; + } + break; + case NGKNET_DEV_SUSPEND: + DBG_CMD(("NGKNET_DEV_SUSPEND\n")); + if (rx_rate_limit >= 0) { + ngknet_rx_rate_limit_stop(dev); + } + ioc.rc = bcmcnet_pdma_dev_suspend(pdev); + break; + case NGKNET_DEV_RESUME: + DBG_CMD(("NGKNET_DEV_RESUME\n")); + ioc.rc = bcmcnet_pdma_dev_resume(pdev); + if (rx_rate_limit >= 0) { + ngknet_rx_rate_limit_start(dev); + } + break; + case NGKNET_DEV_VNET_WAIT: + DBG_CMD(("NGKNET_DEV_VNET_WAIT\n")); + if (pdev->mode != DEV_MODE_HNET) { + ioc.rc = SHR_E_UNAVAIL; + break; + } + wait_event_interruptible(dev->vnet_wq, + atomic_read(&dev->vnet_active) != 0); + atomic_set(&dev->vnet_active, 0); + break; + case NGKNET_DEV_HNET_WAKE: + DBG_CMD(("NGKNET_DEV_HNET_WAKE\n")); + if (pdev->mode != DEV_MODE_HNET) { + ioc.rc = SHR_E_UNAVAIL; + break; + } + atomic_set(&dev->hnet_active, 1); + wake_up_interruptible(&dev->hnet_wq); + break; + case NGKNET_DEV_VNET_DOCK: + DBG_CMD(("NGKNET_DEV_VNET_DOCK\n")); + if (pdev->mode != DEV_MODE_HNET) { + ioc.rc = SHR_E_UNAVAIL; + break; + } + if (kal_copy_from_user(&pdev->ctrl.vsync, (void *)(unsigned long)ioc.op.data.buf, + sizeof(pdev->ctrl.vsync), ioc.op.data.len)) { + return -EFAULT; + } + ioc.rc = bcmcnet_pdma_dev_dock(pdev); + break; + case NGKNET_DEV_VNET_UNDOCK: + DBG_CMD(("NGKNET_DEV_VNET_UNDOCK\n")); + if (pdev->mode != DEV_MODE_HNET) { + ioc.rc = SHR_E_UNAVAIL; + break; + } + ngknet_dev_vnet_wake(pdev); + ioc.rc = bcmcnet_pdma_dev_undock(pdev); + break; + case NGKNET_RCPU_CONFIG: + DBG_CMD(("NGKNET_RCPU_CONFIG\n")); + if (kal_copy_from_user(&dev->rcpu_ctrl, (void *)(unsigned long)ioc.op.data.buf, + sizeof(dev->rcpu_ctrl), ioc.op.data.len)) { + return -EFAULT; + } + break; + case NGKNET_RCPU_GET: + DBG_CMD(("NGKNET_RCPU_GET\n")); + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, &dev->rcpu_ctrl, + ioc.op.data.len, sizeof(dev->rcpu_ctrl))) { + return -EFAULT; + } + break; + case NGKNET_INFO_GET: + DBG_CMD(("NGKNET_INFO_GET\n")); + bcmcnet_pdma_dev_info_get(pdev); + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, &pdev->info, + ioc.op.data.len, sizeof(pdev->info))) { + return -EFAULT; + } + break; + case NGKNET_STATS_GET: + DBG_CMD(("NGKNET_STATS_GET\n")); + bcmcnet_pdma_dev_stats_get(pdev); + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, &pdev->stats, + ioc.op.data.len, sizeof(pdev->stats))) { + return -EFAULT; + } + break; + case NGKNET_STATS_RESET: + DBG_CMD(("NGKNET_STATS_RESET\n")); + bcmcnet_pdma_dev_stats_reset(pdev); + break; + case NGKNET_NETIF_CREATE: + DBG_CMD(("NGKNET_NETIF_CREATE\n")); + if (kal_copy_from_user(netif, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*netif), ioc.op.data.len)) { + return -EFAULT; + } + ioc.rc = ngknet_netif_create(dev, netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, netif, + ioc.op.data.len, sizeof(*netif))) { + return -EFAULT; + } + break; + case NGKNET_NETIF_DESTROY: + DBG_CMD(("NGKNET_NETIF_DESTROY\n")); + ioc.rc = ngknet_netif_destroy(dev, ioc.iarg[0]); + break; + case NGKNET_NETIF_GET: + DBG_CMD(("NGKNET_NETIF_GET\n")); + ioc.rc = ngknet_netif_get(dev, ioc.iarg[0], netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, netif, + ioc.op.data.len, sizeof(*netif))) { + return -EFAULT; + } + break; + case NGKNET_NETIF_NEXT: + DBG_CMD(("NGKNET_NETIF_NEXT\n")); + if (kal_copy_from_user(netif, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*netif), ioc.op.data.len)) { + return -EFAULT; + } + ioc.rc = ngknet_netif_get_next(dev, netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, netif, + ioc.op.data.len, sizeof(*netif))) { + return -EFAULT; + } + break; + case NGKNET_NETIF_LINK_SET: + DBG_CMD(("NGKNET_NETIF_LINK_SET\n")); + ioc.rc = ngknet_netif_get(dev, ioc.iarg[0], netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + ndev = dev->vdev[netif->id]; + if (ioc.iarg[1]) { + if (!netif_carrier_ok(ndev)) { + netif_carrier_on(ndev); + netif_tx_wake_all_queues(ndev); + DBG_LINK(("%s: link up\n", netif->name)); + } + } else { + if (netif_carrier_ok(ndev)) { + netif_carrier_off(ndev); + netif_tx_stop_all_queues(ndev); + DBG_LINK(("%s: link down\n", netif->name)); + } + } + break; + case NGKNET_FILT_CREATE: + DBG_CMD(("NGKNET_FILT_CREATE\n")); + if (kal_copy_from_user(filter, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*filter), ioc.op.data.len)) { + return -EFAULT; + } + ioc.rc = ngknet_filter_create(dev, filter); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, filter, + ioc.op.data.len, sizeof(*filter))) { + return -EFAULT; + } + break; + case NGKNET_FILT_DESTROY: + DBG_CMD(("NGKNET_FILT_DESTROY\n")); + ioc.rc = ngknet_filter_destroy(dev, ioc.iarg[0]); + break; + case NGKNET_FILT_GET: + DBG_CMD(("NGKNET_FILT_GET\n")); + ioc.rc = ngknet_filter_get(dev, ioc.iarg[0], filter); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, filter, + ioc.op.data.len, sizeof(*filter))) { + return -EFAULT; + } + break; + case NGKNET_FILT_NEXT: + DBG_CMD(("NGKNET_FILT_NEXT\n")); + if (kal_copy_from_user(filter, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*filter), ioc.op.data.len)) { + return -EFAULT; + } + ioc.rc = ngknet_filter_get_next(dev, filter); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, filter, + ioc.op.data.len, sizeof(*filter))) { + return -EFAULT; + } + break; + case NGKNET_PTP_DEV_CTRL: + DBG_CMD(("NGKNET_PTP_DEV_CTRL\n")); + if (ioc.op.data.len) { + data = kmalloc(ioc.op.data.len, GFP_ATOMIC); + if (data == NULL) { + printk("Fatal error: no memory for PTP device ioctl\n"); + return -EFAULT; + } + if (copy_from_user(data, (void *)(unsigned long)ioc.op.data.buf, + ioc.op.data.len)) { + kfree(data); + return -EFAULT; + } + } + ioc.rc = ngknet_ptp_dev_ctrl(dev, ioc.iarg[0], data, ioc.op.data.len); + if (SHR_FAILURE((int)ioc.rc)) { + if (data) { + kfree(data); + } + break; + } + if (ioc.op.data.len) { + if (copy_to_user((void *)(unsigned long)ioc.op.data.buf, data, + ioc.op.data.len)) { + kfree(data); + return -EFAULT; + } + kfree(data); + } + break; + default: + ioc.rc = SHR_E_UNAVAIL; + printk("Invalid IOCTL"); + break; + } + + if (copy_to_user((void *)arg, &ioc, sizeof(ioc))) { + return -EFAULT; + } + + return 0; +} + +static int +ngknet_mmap(struct file *filp, struct vm_area_struct *vma) +{ + return 0; +} + +static struct file_operations ngknet_fops = { + .open = ngknet_open, + .release = ngknet_release, + .unlocked_ioctl = ngknet_ioctl, + .compat_ioctl = ngknet_ioctl, + .mmap = ngknet_mmap, +}; + +static int __init +ngknet_init_module(void) +{ + int idx; + int rv; + + rv = register_chrdev(NGKNET_MODULE_MAJOR, NGKNET_MODULE_NAME, &ngknet_fops); + if (rv < 0) { + printk(KERN_WARNING "%s: can't get major %d\n", + NGKNET_MODULE_NAME, NGKNET_MODULE_MAJOR); + return rv; + } + + /* Randomize lower 3 bytes of the MAC address (TESTING ONLY) */ + get_random_bytes(&ngknet_dev_mac[3], 3); + + /* Check for user-supplied MAC address (recommended) */ + if (mac_addr != NULL && strlen(mac_addr) == 17) { + for (idx = 0; idx < 6; idx++) { + ngknet_dev_mac[idx] = simple_strtoul(&mac_addr[idx * 3], NULL, 16); + } + /* Do not allow multicast address */ + ngknet_dev_mac[0] &= ~0x01; + } + + /* Initialize procfs */ + ngknet_procfs_init(); + + /* Initialize Rx rate limit */ + ngknet_rx_rate_limit_init(ngknet_devices); + + return 0; +} + +static void __exit +ngknet_exit_module(void) +{ + int idx; + + /* Cleanup Rx rate limit */ + ngknet_rx_rate_limit_cleanup(); + + /* Cleanup procfs */ + ngknet_procfs_cleanup(); + + /* Remove all the devices */ + for (idx = 0; idx < NUM_PDMA_DEV_MAX; idx++) { + ngknet_dev_remove(idx); + } + + unregister_chrdev(NGKNET_MODULE_MAJOR, NGKNET_MODULE_NAME); +} + +module_init(ngknet_init_module); +module_exit(ngknet_exit_module); + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.h new file mode 100644 index 000000000000..fb38f1b9abc3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.h @@ -0,0 +1,278 @@ +/*! \file ngknet_main.h + * + * Data structure and macro definitions for NGKNET kernel module. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_MAIN_H +#define NGKNET_MAIN_H + +#include +#include +#include +#include + +/*! Maximum number of PDMA devices supported */ +#ifdef NGBDE_NUM_SWDEV_MAX +#define NUM_PDMA_DEV_MAX NGBDE_NUM_SWDEV_MAX +#else +#define NUM_PDMA_DEV_MAX 16 +#endif + +/*! + * Debug levels + */ +#define DBG_LVL_VERB 0x0001 +#define DBG_LVL_PKT 0x0002 +#define DBG_LVL_CMD 0x0004 +#define DBG_LVL_IRQ 0x0008 +#define DBG_LVL_NAPI 0x0010 +#define DBG_LVL_NDEV 0x0020 +#define DBG_LVL_FILT 0x0040 +#define DBG_LVL_RCPU 0x0080 +#define DBG_LVL_WARN 0x0100 +#define DBG_LVL_PDMP 0x0200 +#define DBG_LVL_RATE 0x0400 +#define DBG_LVL_LINK 0x0800 + +#define DBG_VERB(_s) do { if (debug & DBG_LVL_VERB) printk _s; } while (0) +#define DBG_PKT(_s) do { if (debug & DBG_LVL_PKT) printk _s; } while (0) +#define DBG_CMD(_s) do { if (debug & DBG_LVL_CMD) printk _s; } while (0) +#define DBG_IRQ(_s) do { if (debug & DBG_LVL_IRQ) printk _s; } while (0) +#define DBG_NAPI(_s) do { if (debug & DBG_LVL_NAPI) printk _s; } while (0) +#define DBG_NDEV(_s) do { if (debug & DBG_LVL_NDEV) printk _s; } while (0) +#define DBG_FILT(_s) do { if (debug & DBG_LVL_FILT) printk _s; } while (0) +#define DBG_RCPU(_s) do { if (debug & DBG_LVL_RCPU) printk _s; } while (0) +#define DBG_WARN(_s) do { if (debug & DBG_LVL_WARN) printk _s; } while (0) +#define DBG_PDMP(_s) do { if (debug & DBG_LVL_PDMP) printk _s; } while (0) +#define DBG_RATE(_s) do { if (debug & DBG_LVL_RATE) printk _s; } while (0) +#define DBG_LINK(_s) do { if (debug & DBG_LVL_LINK) printk _s; } while (0) + +/*! + * Device description + */ +struct ngknet_dev { + /*! Base address for PCI register access */ + volatile void *base_addr; + + /*! Required for DMA memory control */ + struct device *dev; + + /*! Required for PCI memory control */ + struct pci_dev *pci_dev; + + /*! Base network device */ + struct net_device *net_dev; + + /*! PDMA device */ + struct pdma_dev pdma_dev; + + /*! Device number (from BDE) */ + int dev_no; + + /*! Vitual network devices, 0 is reserved */ + struct net_device *vdev[NUM_VDEV_MAX + 1]; + + /*! Vitual network devices bound to queue */ + struct net_device *bdev[NUM_QUE_MAX]; + + /*! Filter list */ + struct list_head filt_list; + + /*! Filter control, 0 is reserved */ + void *fc[NUM_FILTER_MAX + 1]; + + /*! Callback control */ + struct ngknet_callback_ctrl *cbc; + + /*! RCPU control */ + struct ngknet_rcpu_hdr rcpu_ctrl; + + /*! NGKNET lock */ + spinlock_t lock; + + /*! NGKNET wait queue */ + wait_queue_head_t wq; + + /*! VNET wait queue */ + wait_queue_head_t vnet_wq; + + /*! VNET is active */ + atomic_t vnet_active; + + /*! HNET wait queue */ + wait_queue_head_t hnet_wq; + + /*! HNET is active */ + atomic_t hnet_active; + + /*! HNET deamon */ + struct task_struct *hnet_task; + + /*! HNET work */ + struct work_struct hnet_work; + + /*! PTP Tx queue */ + struct sk_buff_head ptp_tx_queue; + + /*! PTP Tx work */ + struct work_struct ptp_tx_work; + + /*! Flags */ + int flags; + /*! NGKNET device is active */ +#define NGKNET_DEV_ACTIVE (1 << 0) +}; + +/*! + * Network interface specific private data + */ +struct ngknet_private { + /*! Network device */ + struct net_device *net_dev; + + /*! Network stats */ + struct net_device_stats stats; + + /*! NGKNET device */ + struct ngknet_dev *bkn_dev; + + /*! Network interface ID */ + int id; + + /*! Network interface type */ + int type; + + /*! Network interface flags */ + uint32_t flags; + + /*! Network interface vlan */ + uint32_t vlan; + + /*! Network interface bound to */ + uint32_t chan; + + /*! Metadata offset from Ethernet header */ + uint32_t meta_off; + + /*! Metadata length */ + uint32_t meta_len; + + /*! Metadata used to send packets to physical port */ + uint8_t meta_data[NGKNET_NETIF_META_MAX]; + + /*! User data gotten back through callbacks */ + uint8_t user_data[NGKNET_NETIF_USER_DATA]; + + /*! Users of this network interface */ + int users; + + /*! Wait for this network interface free */ + int wait; + + /*! HW timestamp Rx filter */ + int hwts_rx_filter; + + /*! HW timestamp Tx type */ + int hwts_tx_type; +}; + +/*! + * \brief Create network interface. + * + * \param [in] dev NGKNET device structure point. + * \param [in] netif Network interface structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_netif_create(struct ngknet_dev *dev, ngknet_netif_t *netif); + +/*! + * \brief Destroy network interface. + * + * \param [in] dev NGKNET device structure point. + * \param [in] id Network interface ID. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_netif_destroy(struct ngknet_dev *dev, int id); + +/*! + * \brief Get network interface. + * + * \param [in] dev NGKNET device structure point. + * \param [in] id Network interface ID. + * \param [out] netif Network interface structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_netif_get(struct ngknet_dev *dev, int id, ngknet_netif_t *netif); + +/*! + * \brief Get the next network interface. + * + * \param [in] dev NGKNET device structure point. + * \param [out] netif Network interface structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_netif_get_next(struct ngknet_dev *dev, ngknet_netif_t *netif); + +/*! + * \brief Get debug level. + * + * \retval Current debug level. + */ +extern int +ngknet_debug_level_get(void); + +/*! + * \brief Set debug level. + * + * \param [in] debug_level Debug level to be set. + */ +extern void +ngknet_debug_level_set(int debug_level); + +/*! + * \brief Get Rx rate limit. + * + * \retval Current Rx rate limit. + */ +extern int +ngknet_rx_rate_limit_get(void); + +/*! + * \brief Set Rx rate limit. + * + * \param [in] rate_limit Rx rate limit to be set. + */ +extern void +ngknet_rx_rate_limit_set(int rate_limit); + +#endif /* NGKNET_MAIN_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.c new file mode 100644 index 000000000000..85edaa26abb9 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.c @@ -0,0 +1,655 @@ +/*! \file ngknet_procfs.c + * + * + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include "ngknet_main.h" +#include "ngknet_extra.h" + +extern struct ngknet_dev ngknet_devices[]; + +static struct proc_dir_entry *proc_root = NULL; + +static void +proc_data_show(struct seq_file *m, const unsigned char *buf, size_t len) +{ + uint32_t i; + + if (!buf || !len) { + seq_printf(m, "\n"); + return; + } + + for (i = 0; i < len; i++) { + seq_printf(m, "%02x ", buf[i]); + if ((i + 1) % 32 == 0 || (i + 1) == len) { + seq_printf(m, "\n"); + if ((i + 1) < len) { + seq_printf(m, " "); + } + } + } +} + +static int +proc_debug_level_show(struct seq_file *m, void *v) +{ + seq_printf(m, "Debug level: 0x%x\n", ngknet_debug_level_get()); + + return 0; +} + +static int +proc_debug_level_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_debug_level_show, NULL); +} + +static ssize_t +proc_debug_level_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + char level_str[11] = {0}; + int debug_level; + + if (copy_from_user(level_str, buf, sizeof(level_str) - 1)) { + return -EFAULT; + } + debug_level = simple_strtol(level_str, NULL, 16); + + ngknet_debug_level_set(debug_level); + printk("Debug level set to: 0x%x\n", debug_level); + + return count; +} + +static int +proc_debug_level_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_debug_level_fops = { + owner: THIS_MODULE, + open: proc_debug_level_open, + read: seq_read, + write: proc_debug_level_write, + llseek: seq_lseek, + release: proc_debug_level_release, +}; + +static int +proc_device_info_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + struct bcmcnet_dev_info *info; + int di, qi, ai = 0; + int rv; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + ai++; + + rv = bcmcnet_pdma_dev_info_get(&dev->pdma_dev); + if (SHR_FAILURE(rv)) { + printk("ngknet: get device%d info failed\n", di); + break; + } + + info = &dev->pdma_dev.info; + seq_printf(m, "dev_no: %d\n", di); + seq_printf(m, "dev_name: %s\n", info->dev_name); + seq_printf(m, "dev_id: 0x%x\n", info->dev_id); + seq_printf(m, "dev_type: %d\n", info->dev_type); + seq_printf(m, "max_groups: %d\n", info->max_groups); + seq_printf(m, "max_queues: %d\n", info->max_queues); + seq_printf(m, "bm_groups: 0x%x\n", info->bm_groups); + seq_printf(m, "bm_rx_queues: 0x%x\n", info->bm_rx_queues); + seq_printf(m, "bm_tx_queues: 0x%x\n", info->bm_tx_queues); + seq_printf(m, "nb_groups: %d\n", info->nb_groups); + seq_printf(m, "nb_rx_queues: %d\n", info->nb_rx_queues); + seq_printf(m, "nb_tx_queues: %d\n", info->nb_tx_queues); + seq_printf(m, "rx_desc_size: %d\n", info->rx_desc_size); + seq_printf(m, "tx_desc_size: %d\n", info->tx_desc_size); + seq_printf(m, "rx_ph_size: %d\n", info->rx_ph_size); + seq_printf(m, "tx_ph_size: %d\n", info->tx_ph_size); + for (qi = 0; qi < info->nb_rx_queues; qi++) { + seq_printf(m, "rx_buf_sz[%d]: %d\n", qi, info->rx_buf_size[qi]); + } + for (qi = 0; qi < info->nb_rx_queues; qi++) { + seq_printf(m, "nb_rx_desc[%d]: %d\n", qi, info->nb_rx_desc[qi]); + } + for (qi = 0; qi < info->nb_tx_queues; qi++) { + seq_printf(m, "nb_tx_desc[%d]: %d\n", qi, info->nb_tx_desc[qi]); + } + } + + if (!ai) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "------------------------\n"); + seq_printf(m, "Total %d devices\n", ai); + } + + return 0; +} + +static int +proc_device_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_device_info_show, NULL); +} + +static int +proc_device_info_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_device_info_fops = { + owner: THIS_MODULE, + open: proc_device_info_open, + read: seq_read, + llseek: seq_lseek, + release: proc_device_info_release, +}; + +static int +proc_filter_info_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + ngknet_filter_t filt = {0}; + int di, dn = 0, fn = 0; + int rv; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + dn++; + + do { + rv = ngknet_filter_get_next(dev, &filt); + if (SHR_FAILURE(rv)) { + printk("ngknet: get device%d filter failed\n", di); + break; + } + fn++; + + seq_printf(m, "\n"); + seq_printf(m, "dev_no: %d\n", di); + seq_printf(m, "id: %d\n", filt.id); + seq_printf(m, "next: %d\n", filt.next); + seq_printf(m, "type: %d\n", filt.type); + seq_printf(m, "flags: 0x%x\n", filt.flags); + seq_printf(m, "prio: %d\n", filt.priority); + seq_printf(m, "chan: %d\n", filt.chan); + seq_printf(m, "desc: %s\n", filt.desc); + seq_printf(m, "dest_type: %d\n", filt.dest_type); + seq_printf(m, "dest_id: %d\n", filt.dest_id); + seq_printf(m, "dest_proto: 0x%x\n", filt.dest_proto); + seq_printf(m, "mirror_type: %d\n", filt.mirror_type); + seq_printf(m, "mirror_id: %d\n", filt.mirror_id); + seq_printf(m, "mirror_proto: 0x%x\n", filt.mirror_proto); + seq_printf(m, "oob_offset: %d\n", filt.oob_data_offset); + seq_printf(m, "oob_size: %d\n", filt.oob_data_size); + seq_printf(m, "pkt_offset: %d\n", filt.pkt_data_offset); + seq_printf(m, "pkt_size: %d\n", filt.pkt_data_size); + seq_printf(m, "filt_data: "); + proc_data_show(m, filt.data.b, filt.oob_data_size + filt.pkt_data_size); + seq_printf(m, "filt_mask: "); + proc_data_show(m, filt.mask.b, filt.oob_data_size + filt.pkt_data_size); + seq_printf(m, "user_data: "); + proc_data_show(m, filt.user_data, NGKNET_FILTER_USER_DATA); + seq_printf(m, "hits: %llu\n", ((struct filt_ctrl *)dev->fc[filt.id])->hits); + } while (filt.next); + } + + if (!dn) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "--------------------------------\n"); + seq_printf(m, "Total %d devices, %d filters\n", dn, fn); + } + + return 0; +} + +static int +proc_filter_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_filter_info_show, NULL); +} + +static int +proc_filter_info_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_filter_info_fops = { + owner: THIS_MODULE, + open: proc_filter_info_open, + read: seq_read, + llseek: seq_lseek, + release: proc_filter_info_release, +}; + +static int +proc_netif_info_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + struct net_device *ndev; + struct ngknet_private *priv; + ngknet_netif_t netif = {0}; + int di, ma, dn = 0, nn = 0; + int rv; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + dn++; + + do { + rv = ngknet_netif_get_next(dev, &netif); + if (SHR_FAILURE(rv)) { + printk("ngknet: get device%d netif failed\n", di); + break; + } + nn++; + ndev = netif.id == 0 ? dev->net_dev : dev->vdev[netif.id]; + priv = netdev_priv(ndev); + + seq_printf(m, "\n"); + seq_printf(m, "dev_no: %d\n", di); + seq_printf(m, "id: %d\n", netif.id); + seq_printf(m, "next: %d\n", netif.next); + seq_printf(m, "type: %d\n", netif.type); + seq_printf(m, "flags: 0x%x\n", netif.flags); + seq_printf(m, "vlan: %d\n", netif.vlan); + seq_printf(m, "mac: "); + for (ma = 0; ma < 6; ma++) { + if (ma == 5) { + seq_printf(m, "%02x\n", netif.macaddr[ma]); + } else { + seq_printf(m, "%02x:", netif.macaddr[ma]); + } + } + seq_printf(m, "mtu: %d\n", netif.mtu); + seq_printf(m, "chan: %d\n", netif.chan); + seq_printf(m, "name: %s\n", netif.name); + seq_printf(m, "meta_off: %d\n", netif.meta_off); + seq_printf(m, "meta_len: %d\n", netif.meta_len); + seq_printf(m, "meta_data: "); + proc_data_show(m, netif.meta_data, netif.meta_len); + seq_printf(m, "user_data: "); + proc_data_show(m, netif.user_data, NGKNET_NETIF_USER_DATA); + seq_printf(m, "rx_packets: %lu\n", priv->stats.rx_packets); + seq_printf(m, "rx_bytes: %lu\n", priv->stats.rx_bytes); + seq_printf(m, "rx_dropped: %lu\n", priv->stats.rx_dropped); + seq_printf(m, "rx_errors: %lu\n", priv->stats.rx_errors); + seq_printf(m, "tx_packets: %lu\n", priv->stats.tx_packets); + seq_printf(m, "tx_bytes: %lu\n", priv->stats.tx_bytes); + seq_printf(m, "tx_dropped: %lu\n", priv->stats.tx_dropped); + seq_printf(m, "tx_errors: %lu\n", priv->stats.tx_errors); + } while (netif.next); + } + + if (!dn) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "--------------------------------\n"); + seq_printf(m, "Total %d devices, %d netifs\n", dn, nn); + } + + return 0; +} + +static int +proc_netif_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_netif_info_show, NULL); +} + +static int +proc_netif_info_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_netif_info_fops = { + owner: THIS_MODULE, + open: proc_netif_info_open, + read: seq_read, + llseek: seq_lseek, + release: proc_netif_info_release, +}; + +static int +proc_pkt_stats_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + struct bcmcnet_dev_stats *stats; + int di, qi, ai = 0; + int rv; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + ai++; + + rv = bcmcnet_pdma_dev_stats_get(&dev->pdma_dev); + if (SHR_FAILURE(rv)) { + printk("ngknet: get device%d stats failed\n", di); + break; + } + + stats = &dev->pdma_dev.stats; + seq_printf(m, "rx_packets: %llu\n", (unsigned long long)stats->rx_packets); + seq_printf(m, "rx_bytes: %llu\n", (unsigned long long)stats->rx_bytes); + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_rxq; qi++) { + seq_printf(m, "rx_packets[%d]: %llu\n", qi, (unsigned long long)stats->rxq_packets[qi]); + seq_printf(m, "rx_bytes[%d]: %llu\n", qi, (unsigned long long)stats->rxq_bytes[qi]); + } + seq_printf(m, "rx_dropped: %llu\n", (unsigned long long)stats->rx_dropped); + seq_printf(m, "rx_errors: %llu\n", (unsigned long long)stats->rx_errors); + seq_printf(m, "rx_nomems: %llu\n", (unsigned long long)stats->rx_nomems); + seq_printf(m, "tx_packets: %llu\n", (unsigned long long)stats->tx_packets); + seq_printf(m, "tx_bytes: %llu\n", (unsigned long long)stats->tx_bytes); + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_txq; qi++) { + seq_printf(m, "tx_packets[%d]: %llu\n", qi, (unsigned long long)stats->txq_packets[qi]); + seq_printf(m, "tx_bytes[%d]: %llu\n", qi, (unsigned long long)stats->txq_bytes[qi]); + } + seq_printf(m, "tx_dropped: %llu\n", (unsigned long long)stats->tx_dropped); + seq_printf(m, "tx_errors: %llu\n", (unsigned long long)stats->tx_errors); + seq_printf(m, "tx_xoffs: %llu\n", (unsigned long long)stats->tx_xoffs); + seq_printf(m, "interrupts: %llu\n", (unsigned long long)stats->intrs); + } + + if (!ai) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "------------------------\n"); + seq_printf(m, "Total %d devices\n", ai); + } + + return 0; +} + +static int +proc_pkt_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_pkt_stats_show, NULL); +} + +static int +proc_pkt_stats_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_pkt_stats_fops = { + owner: THIS_MODULE, + open: proc_pkt_stats_open, + read: seq_read, + llseek: seq_lseek, + release: proc_pkt_stats_release, +}; + +static int +proc_rate_limit_show(struct seq_file *m, void *v) +{ + seq_printf(m, "Rx rate limit: %d pps\n", ngknet_rx_rate_limit_get()); + + return 0; +} + +static int +proc_rate_limit_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_rate_limit_show, NULL); +} + +static ssize_t +proc_rate_limit_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + char limit_str[9] = {0}; + int rate_limit; + + if (copy_from_user(limit_str, buf, sizeof(limit_str) - 1)) { + return -EFAULT; + } + rate_limit = simple_strtol(limit_str, NULL, 10); + + ngknet_rx_rate_limit_set(rate_limit); + printk("Rx rate limit set to: %d pps\n", rate_limit); + + return count; +} + +static int +proc_rate_limit_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_rate_limit_fops = { + owner: THIS_MODULE, + open: proc_rate_limit_open, + read: seq_read, + write: proc_rate_limit_write, + llseek: seq_lseek, + release: proc_rate_limit_release, +}; + +static int +proc_reg_status_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + int di, qi, ai = 0; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + ai++; + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_rxq; qi++) { + bcmcnet_pdma_rx_queue_reg_dump(&dev->pdma_dev, qi); + } + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_txq; qi++) { + bcmcnet_pdma_tx_queue_reg_dump(&dev->pdma_dev, qi); + } + } + + if (!ai) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "------------------------\n"); + seq_printf(m, "Total %d devices\n", ai); + } + + return 0; +} + +static int +proc_reg_status_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_reg_status_show, NULL); +} + +static int +proc_reg_status_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_reg_status_fops = { + owner: THIS_MODULE, + open: proc_reg_status_open, + read: seq_read, + llseek: seq_lseek, + release: proc_reg_status_release, +}; + +static int +proc_ring_status_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + int di, qi, ai = 0; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + ai++; + seq_printf(m, "%s-%d, ", "Unit", di); + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_rxq; qi++) { + bcmcnet_pdma_rx_ring_dump(&dev->pdma_dev, qi); + } + seq_printf(m, "%s%d, ", "Rx queues: ", qi); + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_txq; qi++) { + bcmcnet_pdma_tx_ring_dump(&dev->pdma_dev, qi); + } + seq_printf(m, "%s%d. ", "Tx queues: ", qi); + seq_printf(m, "\n"); + } + + if (!ai) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "------------------------\n"); + seq_printf(m, "Total %d devices\n", ai); + } + + return 0; +} + +static int +proc_ring_status_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_ring_status_show, NULL); +} + +static int +proc_ring_status_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_ring_status_fops = { + owner: THIS_MODULE, + open: proc_ring_status_open, + read: seq_read, + llseek: seq_lseek, + release: proc_ring_status_release, +}; + +int +ngknet_procfs_init(void) +{ + struct proc_dir_entry *entry = NULL; + + proc_root = proc_mkdir(NGKNET_MODULE_NAME, NULL); + if (proc_root == NULL) { + printk(KERN_ERR "ngknet: proc_mkdir failed\n"); + return -1; + } + + PROC_CREATE(entry, "debug_level", 0666, proc_root, &proc_debug_level_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "device_info", 0444, proc_root, &proc_device_info_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "filter_info", 0444, proc_root, &proc_filter_info_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "netif_info", 0444, proc_root, &proc_netif_info_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "pkt_stats", 0444, proc_root, &proc_pkt_stats_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "rate_limit", 0666, proc_root, &proc_rate_limit_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "reg_status", 0444, proc_root, &proc_reg_status_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "ring_status", 0444, proc_root, &proc_ring_status_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + return 0; +} + +int +ngknet_procfs_cleanup(void) +{ + remove_proc_entry("debug_level", proc_root); + remove_proc_entry("device_info", proc_root); + remove_proc_entry("filter_info", proc_root); + remove_proc_entry("netif_info", proc_root); + remove_proc_entry("pkt_stats", proc_root); + remove_proc_entry("rate_limit", proc_root); + remove_proc_entry("reg_status", proc_root); + remove_proc_entry("ring_status", proc_root); + + remove_proc_entry(NGKNET_MODULE_NAME, NULL); + + return 0; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.h new file mode 100644 index 000000000000..3c1938121ebb --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.h @@ -0,0 +1,47 @@ +/*! \file ngknet_procfs.h + * + * Procfs-related definitions and APIs for NGKNET module. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_PROCFS_H +#define NGKNET_PROCFS_H + +/*! + * \brief Initialize procfs for KNET driver. + * + * Create procfs read/write interfaces. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngknet_procfs_init(void); + +/*! + * \brief Clean up procfs for KNET driver. + * + * Clean up resources allocated by \ref ngknet_procfs_init. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngknet_procfs_cleanup(void); + +#endif /* NGKNET_PROCFS_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.c new file mode 100644 index 000000000000..13579208eab0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.c @@ -0,0 +1,194 @@ +/*! \file ngknet_ptp.c + * + * Utility routines for PTP. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include "ngknet_callback.h" +#include "ngknet_ptp.h" + +int +ngknet_ptp_rx_config_set(struct net_device *ndev, int *filter) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + + if (!dev->cbc->ptp_rx_config_set_cb) { + return SHR_E_UNAVAIL; + } + + /* + * The expected Rx filter value is passed to the callback. The callback + * should pass back the actual filter value by the paramter . + * The callback can use priv->user_data to get other private parameters + * such as phys_port, dev_type, etc, which should be introduced when the + * netif is created. + */ + return dev->cbc->ptp_rx_config_set_cb(priv, filter); +} + +int +ngknet_ptp_tx_config_set(struct net_device *ndev, int type) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + + if (!dev->cbc->ptp_tx_config_set_cb) { + return SHR_E_UNAVAIL; + } + + /* + * The Tx type value is passed to the callback by the parameter . + * The callback should do the configuration according to the type. + * The callback can use priv->user_data to get other private parameters + * such as phys_port, dev_type, etc, which should be introduced when the + * netif is created. + */ + return dev->cbc->ptp_tx_config_set_cb(priv, &type); +} + +int +ngknet_ptp_rx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + + if (!dev->cbc->ptp_rx_hwts_get_cb) { + return SHR_E_UNAVAIL; + } + + cbd->dev_no = dev->dev_no; + cbd->dev_id = dev->pdma_dev.dev_id; + cbd->priv = priv; + cbd->pmd = skb->data + PKT_HDR_SIZE; + cbd->pmd_len = pkh->meta_len; + cbd->pkt_len = pkh->data_len; + + /* + * The callback should get timestamp value for a Rx packet and return + * by the parameter . + * Some parameters have been consolidated to SKB as above. They can be + * achieved by NGKNET_SKB_CB(skb). Specially more private paramters are + * in NGKNET_SKB_CB(skb)->priv->user_data[]. + */ + return dev->cbc->ptp_rx_hwts_get_cb(skb, ts); +} + +int +ngknet_ptp_tx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + + if (!dev->cbc->ptp_tx_hwts_get_cb) { + return SHR_E_UNAVAIL; + } + + cbd->dev_no = dev->dev_no; + cbd->dev_id = dev->pdma_dev.dev_id; + cbd->priv = priv; + cbd->pmd = skb->data + PKT_HDR_SIZE; + cbd->pmd_len = pkh->meta_len; + cbd->pkt_len = pkh->data_len; + + /* + * The callback should get timestamp value for a Tx packet and return + * by the parameter . + * For HWTSTAMP_TX_ONESTEP_SYNC type, the time value can be achieved and + * returned immediately. Otherwise, for HWTSTAMP_TX_ON type, the callback + * should wait till the time value can be available, i.e. the packet has + * been tranmitted out from port. + * Some parameters have been consolidated to SKB as above. They can be + * achieved by NGKNET_SKB_CB(skb). Specially more private paramters are + * in NGKNET_SKB_CB(skb)->priv->user_data[] such as phys_port, dev_type, + * and so on. + */ + return dev->cbc->ptp_tx_hwts_get_cb(skb, ts); +} + +int +ngknet_ptp_tx_meta_set(struct net_device *ndev, struct sk_buff *skb) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + + if (!dev->cbc->ptp_tx_meta_set_cb) { + return SHR_E_UNAVAIL; + } + + cbd->dev_no = dev->dev_no; + cbd->dev_id = dev->pdma_dev.dev_id; + cbd->priv = priv; + cbd->pmd = skb->data + PKT_HDR_SIZE; + cbd->pmd_len = pkh->meta_len; + cbd->pkt_len = pkh->data_len; + + /* + * The callback should configure the metadata pmd> + * for HW timestamping according to the corresponding switch device. + * Some parameters have been consolidated to SKB as above. They can be + * achieved by NGKNET_SKB_CB(skb). Specially more private paramters are + * in NGKNET_SKB_CB(skb)->priv->user_data[] such as phys_port, dev_type, + * and so on. + */ + return dev->cbc->ptp_tx_meta_set_cb(skb); +} + +int +ngknet_ptp_phc_index_get(struct net_device *ndev, int *index) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + + if (!dev->cbc->ptp_phc_index_get_cb) { + return SHR_E_UNAVAIL; + } + + /* + * The callback should return the HPC index by the parameter . + * priv->user_data[] can be used to get other private parameters such as + * phys_port, dev_type, etc, which should be introduced when the netif is + * created. + */ + return dev->cbc->ptp_phc_index_get_cb(priv, index); +} + +int +ngknet_ptp_dev_ctrl(struct ngknet_dev *dev, int cmd, char *data, int len) +{ + if (!dev->cbc->ptp_dev_ctrl_cb) { + return SHR_E_UNAVAIL; + } + + /* + * The callback is IOCTL dispatcher for PTP driver/module. + * The parameter is the command defined by the user. The parameter + * and are used for interactions between the user application + * and the driver for PTP device start/stop, enable/disable, set/get, and + * so on. + */ + return dev->cbc->ptp_dev_ctrl_cb(dev, cmd, data, len); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.h new file mode 100644 index 000000000000..86dcb6c4904a --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.h @@ -0,0 +1,111 @@ +/*! \file ngknet_ptp.h + * + * Definitions and APIs declaration for PTP. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_PTP_H +#define NGKNET_PTP_H + +#include +#include "ngknet_main.h" + +/*! + * \brief PTP Rx config set. + * + * \param [in] ndev Network device structure point. + * \param [in] filter Rx filter. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_config_set(struct net_device *ndev, int *filter); + +/*! + * \brief PTP Tx config set. + * + * \param [in] ndev Network device structure point. + * \param [in] type Tx type. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_config_set(struct net_device *ndev, int type); + +/*! + * \brief PTP Rx HW timestamping get. + * + * \param [in] ndev Network device structure point. + * \param [in] skb Rx packet SKB. + * \param [out] ts Timestamp value. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts); + +/*! + * \brief PTP Tx HW timestamping get. + * + * \param [in] ndev Network device structure point. + * \param [in] skb Tx packet SKB. + * \param [out] ts Timestamp value. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts); + +/*! + * \brief PTP Tx meta set. + * + * \param [in] ndev Network device structure point. + * \param [in] skb Tx packet SKB. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_meta_set(struct net_device *ndev, struct sk_buff *skb); + +/*! + * \brief PTP PHC index get. + * + * \param [in] ndev Network device structure point. + * \param [out] index PHC index. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_phc_index_get(struct net_device *ndev, int *index); + +/*! + * \brief PTP device control. + * + * \param [in] dev NGKNET device structure point. + * \param [in] cmd Command. + * \param [in] data Data buffer. + * \param [in] len Data length. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_dev_ctrl(struct ngknet_dev *dev, int cmd, char *data, int len); + +#endif /* NGKNET_PTP_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Kbuild b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Kbuild new file mode 100644 index 000000000000..2ce66edb3c63 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Kbuild @@ -0,0 +1,36 @@ +# -*- Kbuild -*- +# +# Linux KNET Callback module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# 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. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# +ifeq ($(BUILD_PSAMPLE),1) +PSAMPLE_CFLAGS=-DPSAMPLE_SUPPORT +PSAMPLE_CB_OBJS=psample-cb.o +endif + +obj-m := linux_ngknetcb.o + +ccflags-y := $(LKM_CFLAGS) \ + -I$(SDK)/shr/include \ + -I$(SDK)/bcmdrd/include \ + -I$(SDK)/linux/include \ + -I$(SDK)/linux/knet/include \ + -I$(SDK)/linux/knet \ + $(PSAMPLE_CFLAGS) + +linux_ngknetcb-y := ngknetcb_main.o \ + $(PSAMPLE_CB_OBJS) diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Makefile b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Makefile new file mode 100644 index 000000000000..e2acfed49d6c --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Makefile @@ -0,0 +1,33 @@ +# -*- Makefile -*- +# +# Linux KNET Callback module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# 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. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +include Kbuild + +ifeq ($(KERNELRELEASE),) + +MOD_NAME = linux_ngknetcb + +include $(SDK)/make/lkm.mk + +endif + +.PHONY: distclean + +distclean: diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/ngknetcb_main.c b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/ngknetcb_main.c new file mode 100644 index 000000000000..aa248dafce52 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/ngknetcb_main.c @@ -0,0 +1,444 @@ +/*! \file ngknetcb_main.c + * + * NGKNET Callback module entry. + */ +/* + * $Copyright: (c) 2019 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved.$ + */ + +#include +#include +#include "psample-cb.h" + +/*! \cond */ +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("NGKNET Callback Module"); +MODULE_LICENSE("GPL"); +/*! \endcond */ + +/*! \cond */ +int debug = 0; +MODULE_PARAM(debug, int, 0); +MODULE_PARM_DESC(debug, +"Debug level (default 0)"); +/*! \endcond */ + +/*! Module information */ +#define NGKNETCB_MODULE_NAME "linux_ngknetcb" +#define NGKNETCB_MODULE_MAJOR 122 + +/* set KNET_CB_DEBUG for debug info */ +#define KNET_CB_DEBUG + +/* These below need to match incoming enum values */ +#define FILTER_TAG_STRIP 0 +#define FILTER_TAG_KEEP 1 +#define FILTER_TAG_ORIGINAL 2 + +/* Maintain tag strip statistics */ +struct strip_stats_s { + unsigned long stripped; /* Number of packets that have been stripped */ + unsigned long checked; + unsigned long skipped; +}; + +static struct strip_stats_s strip_stats; +static unsigned int rx_count = 0; + +/* Local function prototypes */ +static void strip_vlan_tag(struct sk_buff *skb); + +/* Remove VLAN tag for select TPIDs */ +static void +strip_vlan_tag(struct sk_buff *skb) +{ + uint16_t vlan_proto; + uint8_t *pkt = skb->data; + + vlan_proto = (uint16_t) ((pkt[12] << 8) | pkt[13]); + if ((vlan_proto == 0x8100) || (vlan_proto == 0x88a8) || (vlan_proto == 0x9100)) { + /* Move first 12 bytes of packet back by 4 */ + memmove(&skb->data[4], skb->data, 12); + skb_pull(skb, 4); /* Remove 4 bytes from start of buffer */ + } +} + +/* + * The function get_tag_status() returns the tag status. + * 0 = Untagged + * 1 = Single inner-tag + * 2 = Single outer-tag + * 3 = Double tagged. + * -1 = Unsupported type + */ +static int +get_tag_status(uint32_t dev_type, void *meta) +{ + uint32_t *valptr; + uint32_t fd_index; + uint32_t outer_l2_hdr; + int tag_status = -1; + + if ((dev_type == 0xb880) || (dev_type == 0xb780)) + { + /* Field BCM_PKTIO_RXPMD_MATCH_ID_LO has tag status in RX PMD */ + fd_index = 2; + valptr = (uint32_t *)meta; + outer_l2_hdr = (valptr[fd_index] >> ((dev_type == 0xb780) ? 2 : 1) & 0xFF); + + if (outer_l2_hdr & 0x1) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(" L2 Header Present\n"); + } +#endif + tag_status = 0; + if (outer_l2_hdr & 0x4) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(" SNAP/LLC\n"); + } +#endif + tag_status = 0; + } + if (outer_l2_hdr & 0x10) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(" Outer Tagged\n"); + } +#endif + tag_status = 2; + if (outer_l2_hdr & 0x20) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(" Double Tagged\n"); + } +#endif + tag_status = 3; + } + } + else if (outer_l2_hdr & 0x20) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(" Inner Tagged\n"); + } +#endif + tag_status = 1; + } + } + } + else if ((dev_type == 0xb990)|| (dev_type == 0xb996)) + { + fd_index = 9; + valptr = (uint32_t *)meta; + /* On TH4, outer_l2_header means INCOMING_TAG_STATUS. + * TH4 only supports single tagging, so if TAG_STATUS + * says there's a tag, then we don't want to strip. + * Otherwise, we do. + */ + outer_l2_hdr = (valptr[fd_index] >> 13) & 3; + + if (outer_l2_hdr) + { + tag_status = 2; +#ifdef KNET_CB_DEBUG + if (debug & 0x1) + { + printk(" Incoming frame tagged\n"); + } +#endif + } + else + { + tag_status = 0; +#ifdef KNET_CB_DEBUG + if (debug & 0x1) + { + printk(" Incoming frame untagged\n"); + } +#endif + } + } +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk("%s; Device Type: %d; tag status: %d\n", __func__, dev_type, tag_status); + } +#endif + return tag_status; +} + +#ifdef KNET_CB_DEBUG +static void +dump_buffer(uint8_t * data, int size) +{ + const char *const to_hex = "0123456789ABCDEF"; + int i; + char buffer[128]; + char *buffer_ptr; + int addr = 0; + + buffer_ptr = buffer; + for (i = 0; i < size; i++) { + *buffer_ptr++ = ' '; + *buffer_ptr++ = to_hex[(data[i] >> 4) & 0xF]; + *buffer_ptr++ = to_hex[data[i] & 0xF]; + if (((i % 16) == 15) || (i == size - 1)) { + *buffer_ptr = '\0'; + buffer_ptr = buffer; + printk(KERN_INFO "%04X %s\n", addr, buffer); + addr = i + 1; + } + } +} + +static void +show_pmd(uint8_t *pmd, int len) +{ + if (debug & 0x1) { + printk("PMD (%d bytes):\n", len); + dump_buffer(pmd, len); + } +} + +static void +show_mac(uint8_t *pkt) +{ + if (debug & 0x1) { + printk("DMAC=%02X:%02X:%02X:%02X:%02X:%02X\n", + pkt[0], pkt[1], pkt[2], pkt[3], pkt[4], pkt[5]); + } +} +#endif + +static struct sk_buff * +strip_tag_rx_cb(struct sk_buff *skb) +{ + const struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + const struct ngknet_private *priv = cbd->priv; + int rcpu_mode = 0; + int tag_status; + + rcpu_mode = (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP)? 1 : 0; +#ifdef KNET_CB_DEBUG + if (debug & 0x1) + { + printk(KERN_INFO + "\n%4u --------------------------------------------------------------------------------\n", + rx_count); + printk(KERN_INFO + "RX KNET callback: dev_no=%1d; dev_id=0x%04X; type_str=%4s; RCPU: %3s \n", + cbd->dev_no, cbd->dev_id, cbd->type_str, rcpu_mode ? "yes" : "no"); + printk(KERN_INFO " pkt_len=%4d; pmd_len=%2d; SKB len: %4d\n", + cbd->pkt_len, cbd->pmd_len, skb->len); + if (cbd->filt) { + printk(KERN_INFO "Filter user data: 0x%08x\n", + *(uint32_t *) cbd->filt->user_data); + } + printk(KERN_INFO "Before SKB (%d bytes):\n", skb->len); + dump_buffer(skb->data, skb->len); + printk("rx_cb for dev %d: id 0x%x, %s\n", cbd->dev_no, cbd->dev_id, cbd->type_str); + printk("netif user data: 0x%08x\n", *(uint32_t *)cbd->priv->user_data); + show_pmd(cbd->pmd, cbd->pmd_len); + if (rcpu_mode) { + const int RCPU_header_len = PKT_HDR_SIZE + cbd->pmd_len; + const int payload_len = skb->len - RCPU_header_len; + unsigned char *payload_start = skb->data + payload_len; + + printk(KERN_INFO "Packet Payload (%d bytes):\n", payload_len); + dump_buffer(payload_start, payload_len); + } else { + printk(KERN_INFO "Packet (%d bytes):\n", cbd->pkt_len); + dump_buffer(skb->data, cbd->pkt_len); + } + } +#endif + + if ((!rcpu_mode) && (cbd->filt)) { + if (FILTER_TAG_ORIGINAL == cbd->filt->user_data[0]) { + tag_status = get_tag_status(cbd->dev_id, (void *)cbd->pmd); + if (tag_status < 0) { + strip_stats.skipped++; + goto _strip_tag_rx_cb_exit; + } + strip_stats.checked++; + if (tag_status < 2) { + strip_stats.stripped++; + strip_vlan_tag(skb); + } + } + } +_strip_tag_rx_cb_exit: +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(KERN_INFO "After SKB (%d bytes):\n", skb->len); + dump_buffer(skb->data, skb->len); + printk(KERN_INFO + "\n%4u --------------------------------------------------------------------------------\n", + rx_count++); + } +#endif + return skb; +} + +static struct sk_buff * +strip_tag_tx_cb(struct sk_buff *skb) +{ +#ifdef KNET_CB_DEBUG + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + + if (debug & 0x1) { + printk("tx_cb for dev %d: %s\n", cbd->dev_no, cbd->type_str); + } + show_pmd(cbd->pmd, cbd->pmd_len); + show_mac(cbd->pmd + cbd->pmd_len); +#endif + return skb; +} + +static struct sk_buff * +ngknet_rx_cb(struct sk_buff *skb) +{ + skb = strip_tag_rx_cb(skb); +#ifdef PSAMPLE_SUPPORT + skb = psample_rx_cb(skb); +#endif + return skb; +} + +static struct sk_buff * +ngknet_tx_cb(struct sk_buff *skb) +{ + skb = strip_tag_tx_cb(skb); + return skb; +} + +static int +ngknet_netif_create_cb(struct net_device *dev) +{ + int retv = 0; +#ifdef PSAMPLE_SUPPORT + retv = psample_netif_create_cb(dev); +#endif + return retv; +} + +static int +ngknet_netif_destroy_cb(struct net_device *dev) +{ + int retv = 0; +#ifdef PSAMPLE_SUPPORT + retv = psample_netif_destroy_cb(dev); +#endif + return retv; +} + +/*! + * Generic module functions + */ +static int +ngknetcb_show(struct seq_file *m, void *v) +{ + seq_printf(m, "Broadcom Linux NGKNET Callback: Untagged VLAN Stripper\n"); + seq_printf(m, " %lu stripped packets\n", strip_stats.stripped); + seq_printf(m, " %lu packets checked\n", strip_stats.checked); + seq_printf(m, " %lu packets skipped\n", strip_stats.skipped); + return 0; +} + +static int +ngknetcb_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, ngknetcb_show, NULL); +} + +static int +ngknetcb_release(struct inode *inode, struct file *filp) +{ + return 0; +} + +static ssize_t +ngknetcb_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + memset(&strip_stats, 0, sizeof(strip_stats)); + printk("Cleared NGKNET callback stats\n"); + return count; +} + +static long +ngknetcb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + return 0; +} + +static int +ngknetcb_mmap(struct file *filp, struct vm_area_struct *vma) +{ + return 0; +} + +static struct file_operations ngknetcb_fops = { + .owner = THIS_MODULE, + .open = ngknetcb_open, + .read = seq_read, + .write = ngknetcb_write, + .llseek = seq_lseek, + .release = ngknetcb_release, + .unlocked_ioctl = ngknetcb_ioctl, + .compat_ioctl = ngknetcb_ioctl, + .mmap = ngknetcb_mmap, +}; + +static int __init +ngknetcb_init_module(void) +{ + int rv; + struct proc_dir_entry *entry = NULL; + + rv = register_chrdev(NGKNETCB_MODULE_MAJOR, NGKNETCB_MODULE_NAME, &ngknetcb_fops); + if (rv < 0) { + printk(KERN_WARNING "%s: can't get major %d\n", + NGKNETCB_MODULE_NAME, NGKNETCB_MODULE_MAJOR); + return rv; + } + + PROC_CREATE(entry, NGKNETCB_MODULE_NAME, 0666, NULL, &ngknetcb_fops); + if (entry == NULL) { + printk(KERN_ERR "%s: proc_mkdir failed\n", + NGKNETCB_MODULE_NAME); + } + + ngknet_rx_cb_register(ngknet_rx_cb); + ngknet_tx_cb_register(ngknet_tx_cb); + +#ifdef PSAMPLE_SUPPORT + psample_init(); +#endif + + ngknet_netif_create_cb_register(ngknet_netif_create_cb); + ngknet_netif_destroy_cb_register(ngknet_netif_destroy_cb); + return 0; +} + +static void __exit +ngknetcb_exit_module(void) +{ + ngknet_netif_create_cb_unregister(ngknet_netif_create_cb); + ngknet_netif_destroy_cb_unregister(ngknet_netif_destroy_cb); + +#ifdef PSAMPLE_SUPPORT + psample_cleanup(); +#endif + + ngknet_rx_cb_unregister(ngknet_rx_cb); + ngknet_tx_cb_unregister(ngknet_tx_cb); + + remove_proc_entry(NGKNETCB_MODULE_NAME, NULL); + + unregister_chrdev(NGKNETCB_MODULE_MAJOR, NGKNETCB_MODULE_NAME); +} + +module_init(ngknetcb_init_module); +module_exit(ngknetcb_exit_module); diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.c b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.c new file mode 100644 index 000000000000..be34430218d3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.c @@ -0,0 +1,995 @@ +/* + * Copyright 2017-2019 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: psample_cb.c $ + * $Copyright: (c) 2019 Broadcom Corp. + * All Rights Reserved.$ + */ + +/* + * Driver for call-back functions for Linux KNET driver. + * + * This code is used to integrate packet sampling KNET callback to + * the psample infra for sending sampled pkts to userspace sflow + * applications such as Host Sflow (https://github.com/sflow/host-sflow) + * using genetlink interfaces. + * + * The module can be built from the standard Linux user mode target + * directories using the following command (assuming bash), e.g. + * + * cd $SDK/systems/linux/user/ + * make BUILD_KNET_CB=1 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "psample-cb.h" + +#define PSAMPLE_CB_DBG +#ifdef PSAMPLE_CB_DBG +extern int debug; +#define PSAMPLE_CB_DBG_LVL_VERB (0x1) +#define PSAMPLE_CB_DBG_LVL_PMD (0x2) +#define PSAMPLE_CB_DBG_PRINT(...) if (debug & PSAMPLE_CB_DBG_LVL_VERB) { printk(__VA_ARGS__); } +#define PSAMPLE_CB_PMD_PRINT(...) if (debug & PSAMPLE_CB_DBG_LVL_PMD) { printk(__VA_ARGS__); } +#else +#define PSAMPLE_CB_DBG_PRINT(...) +#define PSAMPLE_CB_PMD_PRINT(...) +#endif + +#define FCS_SZ 4 +#define PSAMPLE_NLA_PADDING 4 +#define PSAMPLE_PKT_HANDLED (1) + +#define PSAMPLE_RATE_DFLT 1 +#define PSAMPLE_SIZE_DFLT 128 +static int psample_size = PSAMPLE_SIZE_DFLT; +MODULE_PARAM(psample_size, int, 0); +MODULE_PARM_DESC(psample_size, +"psample pkt size (default 128 bytes)"); + +#define PSAMPLE_QLEN_DFLT 1024 +static int psample_qlen = PSAMPLE_QLEN_DFLT; +MODULE_PARAM(psample_qlen, int, 0); +MODULE_PARM_DESC(psample_qlen, +"psample queue length (default 1024 buffers)"); + +/* driver proc entry root */ +static struct proc_dir_entry *psample_proc_root = NULL; +static struct proc_dir_entry *knet_cb_proc_root = NULL; + +/* psample general info */ +typedef struct { + struct list_head netif_list; + int netif_count; + struct net *netns; + spinlock_t lock; + int dcb_type; +} psample_info_t; +static psample_info_t g_psample_info = {0}; + +/* Maintain sampled pkt statistics */ +typedef struct psample_stats_s { + unsigned long pkts_f_psample_cb; + unsigned long pkts_f_psample_mod; + unsigned long pkts_f_handled; + unsigned long pkts_f_pass_through; + unsigned long pkts_f_dst_mc; + unsigned long pkts_c_qlen_cur; + unsigned long pkts_c_qlen_hi; + unsigned long pkts_d_qlen_max; + unsigned long pkts_d_no_mem; + unsigned long pkts_d_no_group; + unsigned long pkts_d_sampling_disabled; + unsigned long pkts_d_not_ready; + unsigned long pkts_d_metadata; + unsigned long pkts_d_skb; + unsigned long pkts_d_skb_cbd; + unsigned long pkts_d_meta_srcport; + unsigned long pkts_d_meta_dstport; + unsigned long pkts_d_invalid_size; +} psample_stats_t; +static psample_stats_t g_psample_stats = {0}; + +typedef struct psample_meta_s { + int trunc_size; + int src_ifindex; + int dst_ifindex; + int sample_rate; +} psample_meta_t; + +typedef struct psample_pkt_s { + struct list_head list; + struct psample_group *group; + psample_meta_t meta; + struct sk_buff *skb; +} psample_pkt_t; + +typedef struct psample_work_s { + struct list_head pkt_list; + struct work_struct wq; + spinlock_t lock; +} psample_work_t; +static psample_work_t g_psample_work = {0}; + +static psample_netif_t* +psample_netif_lookup_by_ifindex(int ifindex) +{ + struct list_head *list; + psample_netif_t *psample_netif = NULL; + unsigned long flags; + + /* look for port from list of available net_devices */ + spin_lock_irqsave(&g_psample_info.lock, flags); + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (psample_netif->dev->ifindex == ifindex) { + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return psample_netif; + } + } + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return (NULL); +} + +static psample_netif_t* +psample_netif_lookup_by_port(int port) +{ + struct list_head *list; + psample_netif_t *psample_netif = NULL; + unsigned long flags; + + /* look for port from list of available net_devices */ + spin_lock_irqsave(&g_psample_info.lock, flags); + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (psample_netif->port == port) { + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return psample_netif; + } + } + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return (NULL); +} + +static int +psample_meta_sample_reason(uint8_t *pkt, void *pkt_meta) +{ + uint32_t *metadata = (uint32_t*)pkt_meta; + uint32_t reason = 0; + uint32_t reason_hi = 0; + uint32_t sample_rx_reason_mask = 0; + + if (metadata) { + /* Sample Pkt reason code (bcmRxReasonSampleSource) */ + switch(g_psample_info.dcb_type) { + case 36: /* TD3 */ + case 38: /* TH3 */ + reason_hi = *(metadata + 4); + reason = *(metadata + 5); + sample_rx_reason_mask = (1 << 3); + break; + case 32: /* TH1/TH2 */ + case 26: /* TD2 */ + case 23: /* HX4 */ + reason_hi = *(metadata + 2); + reason = *(metadata + 3); + sample_rx_reason_mask = (1 << 5); + break; + default: + break; + } + } + PSAMPLE_CB_DBG_PRINT("%s: DCB%d sample_rx_reason_mask: 0x%08x, reason: 0x%08x, reason_hi: 0x%08x\n", + __func__, g_psample_info.dcb_type, sample_rx_reason_mask, reason, reason_hi); + + /* Check if only sample reason code is set. + * If only sample reason code, then consume pkt. + * If other reason codes exist, then pkt should be + * passed through to Linux network stack. + */ + if ((reason & ~sample_rx_reason_mask) || reason_hi) { + return 0; /* multiple reasons set, pass through */ + } + + /* only sample rx reason set, consume pkt */ + return (PSAMPLE_PKT_HANDLED); +} + +static int +psample_meta_get(struct sk_buff *skb, psample_meta_t *sflow_meta) +{ + int src_ifindex = 0; + int sample_rate = 1; + int sample_size = PSAMPLE_SIZE_DFLT; + psample_netif_t *psample_netif = NULL; + const struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + const struct ngknet_private *netif = cbd->priv; + memset(sflow_meta, 0, sizeof(psample_meta_t)); + + /* find src port */ + if ((psample_netif = psample_netif_lookup_by_ifindex(netif->net_dev->ifindex))) { + src_ifindex = psample_netif->dev->ifindex; + sample_rate = psample_netif->sample_rate; + sample_size = psample_netif->sample_size; + } else { + g_psample_stats.pkts_d_meta_srcport++; + PSAMPLE_CB_DBG_PRINT("%s: could not find psample netif for src dev %s (ifidx %d)\n", + __func__, netif->net_dev->name, netif->net_dev->ifindex); + } + + sflow_meta->src_ifindex = src_ifindex; + sflow_meta->trunc_size = sample_size; + sflow_meta->sample_rate = sample_rate; + return (0); +} + +static void +psample_task(struct work_struct *work) +{ + psample_work_t *psample_work = container_of(work, psample_work_t, wq); + unsigned long flags; + struct list_head *list_ptr, *list_next; + psample_pkt_t *pkt; + + spin_lock_irqsave(&psample_work->lock, flags); + list_for_each_safe(list_ptr, list_next, &psample_work->pkt_list) { + /* dequeue pkt from list */ + pkt = list_entry(list_ptr, psample_pkt_t, list); + list_del(list_ptr); + g_psample_stats.pkts_c_qlen_cur--; + spin_unlock_irqrestore(&psample_work->lock, flags); + + /* send to psample */ + if (pkt) { + PSAMPLE_CB_DBG_PRINT("%s: group 0x%x, trunc_size %d, src_ifdx 0x%x, dst_ifdx 0x%x, sample_rate %d\n", + __func__, pkt->group->group_num, + pkt->meta.trunc_size, pkt->meta.src_ifindex, + pkt->meta.dst_ifindex, pkt->meta.sample_rate); + + psample_sample_packet(pkt->group, + pkt->skb, + pkt->meta.trunc_size, + pkt->meta.src_ifindex, + pkt->meta.dst_ifindex, + pkt->meta.sample_rate); + g_psample_stats.pkts_f_psample_mod++; + + dev_kfree_skb_any(pkt->skb); + kfree(pkt); + } + spin_lock_irqsave(&psample_work->lock, flags); + } + spin_unlock_irqrestore(&psample_work->lock, flags); +} + +struct sk_buff* +psample_rx_cb(struct sk_buff *skb) +{ + struct psample_group *group; + psample_meta_t meta; + int rv = 0, size; + const struct ngknet_callback_desc *cbd = NULL; + const struct ngknet_private *netif = NULL; + const struct ngknet_filter_s *filt = NULL; + const struct ngknet_filter_s *filt_src = NULL; + + if (!skb) { + printk("%s: skb is NULL\n", __func__); + g_psample_stats.pkts_d_skb++; + return (NULL); + } + cbd = NGKNET_SKB_CB(skb); + netif = cbd->priv; + filt_src = cbd->filt; + filt = cbd->filt_cb; + + if (!cbd || !netif || !filt_src) { + printk("%s: cbd(0x%p) or priv(0x%p) or filter src(0x%p) is NULL\n", + __func__, cbd, netif, filt_src); + g_psample_stats.pkts_d_skb_cbd++; + return (skb); + } + + /* Enable PMD output in dmesg: "echo "debug=0x2" > /proc/bcm/knet-cb/psample/debug" + * Use bshell cmd "pmddecode rxpmd ..." to decode pkt metadata + */ + if (debug & PSAMPLE_CB_DBG_LVL_PMD) { + char str[128]; + int i, len = cbd->pmd_len > 128? 128 : cbd->pmd_len; + PSAMPLE_CB_PMD_PRINT("PMD (%d bytes): %s\n", + cbd->pmd_len, skb->dev->name); + for (i=0; ipmd+i))); + if ((i & 0x1c) == 0x1c) { + sprintf(&str[strlen(str)], "\n"); + printk(str); + continue; + } + } + if ((i & 0x1f) != 0) { + sprintf(&str[strlen(str)], "\n"); + PSAMPLE_CB_PMD_PRINT(str); + } + } + + /* check if this packet is sampled packet (from sample filter) */ + if (!filt || + (NGKNET_FILTER_DEST_T_CB != filt->dest_type) || + (strncmp(filt->desc, PSAMPLE_CB_NAME, NGKNET_FILTER_DESC_MAX) != 0)) { + return (skb); + } + + PSAMPLE_CB_DBG_PRINT("%s: src dev %s, pkt size %d, filt->dest_id %d\n", + __func__, skb->dev->name, cbd->pkt_len, filt->dest_id); + g_psample_stats.pkts_f_psample_cb++; + + /* get psample group info. psample genetlink group ID passed in filt->dest_id */ + group = psample_group_get(g_psample_info.netns, filt->dest_id); + if (!group) { + printk("%s: Could not find psample genetlink group %d\n", __func__, filt->dest_id); + g_psample_stats.pkts_d_no_group++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* get psample metadata */ + rv = psample_meta_get(skb, &meta); + if (rv < 0) { + printk("%s: Could not parse pkt metadata\n", __func__); + g_psample_stats.pkts_d_metadata++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* Adjust original pkt size to remove 4B FCS */ + size = cbd->pkt_len; + if (size < FCS_SZ) { + g_psample_stats.pkts_d_invalid_size++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } else { + size -= FCS_SZ; + } + + /* Account for padding in libnl used by psample */ + if (meta.trunc_size >= size) { + meta.trunc_size = size - PSAMPLE_NLA_PADDING; + } + + PSAMPLE_CB_DBG_PRINT("%s: group 0x%x, trunc_size %d, src_ifdx 0x%x, dst_ifdx 0x%x, sample_rate %d\n", + __func__, group->group_num, meta.trunc_size, meta.src_ifindex, meta.dst_ifindex, meta.sample_rate); + + /* drop if configured sample rate is 0 */ + if (meta.sample_rate > 0) { + unsigned long flags; + psample_pkt_t *psample_pkt; + struct sk_buff *skb_psample; + + if (g_psample_stats.pkts_c_qlen_cur >= psample_qlen) { + printk("%s: tail drop due to max qlen %d reached\n", __func__, psample_qlen); + g_psample_stats.pkts_d_qlen_max++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + if ((psample_pkt = kmalloc(sizeof(psample_pkt_t), GFP_ATOMIC)) == NULL) { + printk("%s: failed to alloc psample mem for pkt\n", __func__); + g_psample_stats.pkts_d_no_mem++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + memcpy(&psample_pkt->meta, &meta, sizeof(psample_meta_t)); + psample_pkt->group = group; + + if ((skb_psample = dev_alloc_skb(meta.trunc_size)) == NULL) { + printk("%s: failed to alloc psample mem for pkt skb\n", __func__); + g_psample_stats.pkts_d_no_mem++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* setup skb to point to pkt */ + memcpy(skb_psample->data, skb->data, meta.trunc_size); + skb_put(skb_psample, meta.trunc_size); + skb_psample->len = meta.trunc_size; + psample_pkt->skb = skb_psample; + + spin_lock_irqsave(&g_psample_work.lock, flags); + list_add_tail(&psample_pkt->list, &g_psample_work.pkt_list); + + g_psample_stats.pkts_c_qlen_cur++; + if (g_psample_stats.pkts_c_qlen_cur > g_psample_stats.pkts_c_qlen_hi) { + g_psample_stats.pkts_c_qlen_hi = g_psample_stats.pkts_c_qlen_cur; + } + + schedule_work(&g_psample_work.wq); + spin_unlock_irqrestore(&g_psample_work.lock, flags); + } else { + g_psample_stats.pkts_d_sampling_disabled++; + } + +PSAMPLE_FILTER_CB_PKT_HANDLED: + /* if sample reason only, consume pkt. else pass through */ + rv = psample_meta_sample_reason(skb->data, cbd->pmd); + if (rv) { + g_psample_stats.pkts_f_handled++; + return NULL; + } + g_psample_stats.pkts_f_pass_through++; + return skb; +} + +int +psample_netif_create_cb(struct net_device *dev) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif, *lpsample_netif; + unsigned long flags; + struct ngknet_private *netif = NULL; + + if (!dev) { + printk("%s: net_device is NULL\n", __func__); + return (-1); + } + netif = netdev_priv(dev); + + if ((psample_netif = kmalloc(sizeof(psample_netif_t), GFP_ATOMIC)) == NULL) { + printk("%s: failed to alloc psample mem for netif '%s'\n", + __func__, dev->name); + return (-1); + } + + spin_lock_irqsave(&g_psample_info.lock, flags); + + psample_netif->dev = dev; + psample_netif->id = netif->id; + /* FIXME: port is not saved in ngknet_private, need to get from metadata?? */ + //psample_netif->port = netif->port; + psample_netif->vlan = netif->vlan; + psample_netif->sample_rate = PSAMPLE_RATE_DFLT; + psample_netif->sample_size = PSAMPLE_SIZE_DFLT; + + /* insert netif sorted by ID similar to bkn_knet_netif_create() */ + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + lpsample_netif = (psample_netif_t*)list; + if (netif->id < lpsample_netif->id) { + found = 1; + g_psample_info.netif_count++; + break; + } + } + + if (found) { + /* Replace previously removed interface */ + list_add_tail(&psample_netif->list, &lpsample_netif->list); + } else { + /* No holes - add to end of list */ + list_add_tail(&psample_netif->list, &g_psample_info.netif_list); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + PSAMPLE_CB_DBG_PRINT("%s: added psample netif '%s'\n", __func__, dev->name); + return (0); +} + +int +psample_netif_destroy_cb(struct net_device *dev) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + struct ngknet_private *netif = NULL; + + if (!dev) { + printk("%s: net_device is NULL\n", __func__); + return (-1); + } + netif = netdev_priv(dev); + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (netif->id == psample_netif->id) { + found = 1; + list_del(&psample_netif->list); + PSAMPLE_CB_DBG_PRINT("%s: removing psample netif '%s'\n", __func__, dev->name); + kfree(psample_netif); + g_psample_info.netif_count--; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + printk("%s: netif ID %d not found!\n", __func__, netif->id); + return (-1); + } + return (0); +} + +/* + * psample rate Proc Read Entry + */ +static int +psample_proc_rate_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %d\n", psample_netif->dev->name, psample_netif->sample_rate); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + return 0; +} + +static int +psample_proc_rate_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_rate_show, NULL); +} + +/* + * psample rate Proc Write Entry + * + * Syntax: + * = + * + * Where is a virtual network interface name. + * + * Examples: + * eth4=1000 + */ +static ssize_t +psample_proc_rate_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + char sample_str[40], *ptr, *newline; + unsigned long flags; + + + if (count > sizeof(sample_str)) { + count = sizeof(sample_str) - 1; + sample_str[count] = '\0'; + } + if (copy_from_user(sample_str, buf, count)) { + return -EFAULT; + } + sample_str[count] = 0; + newline = strchr(sample_str, '\n'); + if (newline) { + /* Chop off the trailing newline */ + *newline = '\0'; + } + + if ((ptr = strchr(sample_str, '=')) == NULL && + (ptr = strchr(sample_str, ':')) == NULL) { + printk("Error: Pkt sample rate syntax not recognized: '%s'\n", sample_str); + return count; + } + *ptr++ = 0; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (strcmp(psample_netif->dev->name, sample_str) == 0) { + psample_netif->sample_rate = simple_strtol(ptr, NULL, 10); + // TODO MLI@BRCM - check valid sample rate + found = 1; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + printk("Warning: Failed setting psample rate on unknown network interface: '%s'\n", sample_str); + } + return count; +} + +struct file_operations psample_proc_rate_file_ops = { + owner: THIS_MODULE, + open: psample_proc_rate_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_rate_write, + release: single_release, +}; + +/* + * psample size Proc Read Entry + */ +static int +psample_proc_size_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %d\n", psample_netif->dev->name, psample_netif->sample_size); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return 0; +} + +static int +psample_proc_size_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_size_show, NULL); +} + +/* + * psample size Proc Write Entry + * + * Syntax: + * = + * + * Where is a virtual network interface name. + * + * Examples: + * eth4=128 + */ +static ssize_t +psample_proc_size_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + char sample_str[40], *ptr, *newline; + unsigned long flags; + + if (count > sizeof(sample_str)) { + count = sizeof(sample_str) - 1; + sample_str[count] = '\0'; + } + if (copy_from_user(sample_str, buf, count)) { + return -EFAULT; + } + sample_str[count] = 0; + newline = strchr(sample_str, '\n'); + if (newline) { + /* Chop off the trailing newline */ + *newline = '\0'; + } + + if ((ptr = strchr(sample_str, '=')) == NULL && + (ptr = strchr(sample_str, ':')) == NULL) { + printk("Error: Pkt sample size syntax not recognized: '%s'\n", sample_str); + return count; + } + *ptr++ = 0; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (strcmp(psample_netif->dev->name, sample_str) == 0) { + psample_netif->sample_size = simple_strtol(ptr, NULL, 10); + // TODO MLI@BRCM - check valid sample size + found = 1; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + printk("Warning: Failed setting psample size on unknown network interface: '%s'\n", sample_str); + } + return count; +} + +struct file_operations psample_proc_size_file_ops = { + owner: THIS_MODULE, + open: psample_proc_size_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_size_write, + release: single_release, +}; + +/* + * psample map Proc Read Entry + */ +static int +psample_proc_map_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + seq_printf(m, " Interface logical port ifindex\n"); + seq_printf(m, "------------- ------------ -------\n"); + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %-14d %d\n", + psample_netif->dev->name, + psample_netif->port, + psample_netif->dev->ifindex); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return 0; +} + +static int +psample_proc_map_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_map_show, NULL); +} + +struct file_operations psample_proc_map_file_ops = { + owner: THIS_MODULE, + open: psample_proc_map_open, + read: seq_read, + llseek: seq_lseek, + write: NULL, + release: single_release, +}; + +/* + * psample debug Proc Read Entry + */ +static int +psample_proc_debug_show(struct seq_file *m, void *v) +{ + seq_printf(m, "BCM KNET %s Callback Config\n", PSAMPLE_CB_NAME); + seq_printf(m, " debug: 0x%x\n", debug); + seq_printf(m, " dcb_type: %d\n", g_psample_info.dcb_type); + seq_printf(m, " netif_count: %d\n", g_psample_info.netif_count); + seq_printf(m, " queue length: %d\n", psample_qlen); + + return 0; +} + +static int +psample_proc_debug_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_debug_show, NULL); +} + +/* + * psample debug Proc Write Entry + * + * Syntax: + * debug= + * + * Where corresponds to the debug module parameter. + * + * Examples: + * debug=0x1 + */ +static ssize_t +psample_proc_debug_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + char debug_str[40]; + char *ptr; + + if (count > sizeof(debug_str)) { + count = sizeof(debug_str) - 1; + debug_str[count] = '\0'; + } + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + if ((ptr = strstr(debug_str, "debug=")) != NULL) { + ptr += 6; + debug = simple_strtol(ptr, NULL, 0); + } else { + printk("Warning: unknown configuration setting\n"); + } + + return count; +} + +struct file_operations psample_proc_debug_file_ops = { + owner: THIS_MODULE, + open: psample_proc_debug_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_debug_write, + release: single_release, +}; + +static int +psample_proc_stats_show(struct seq_file *m, void *v) +{ + seq_printf(m, "BCM KNET %s Callback Stats\n", PSAMPLE_CB_NAME); + seq_printf(m, " DCB type %d\n", g_psample_info.dcb_type); + seq_printf(m, " pkts filter psample cb %10lu\n", g_psample_stats.pkts_f_psample_cb); + seq_printf(m, " pkts sent to psample module %10lu\n", g_psample_stats.pkts_f_psample_mod); + seq_printf(m, " pkts handled by psample %10lu\n", g_psample_stats.pkts_f_handled); + seq_printf(m, " pkts pass through %10lu\n", g_psample_stats.pkts_f_pass_through); + seq_printf(m, " pkts with mc destination %10lu\n", g_psample_stats.pkts_f_dst_mc); + seq_printf(m, " pkts current queue length %10lu\n", g_psample_stats.pkts_c_qlen_cur); + seq_printf(m, " pkts high queue length %10lu\n", g_psample_stats.pkts_c_qlen_hi); + seq_printf(m, " pkts drop max queue length %10lu\n", g_psample_stats.pkts_d_qlen_max); + seq_printf(m, " pkts drop no memory %10lu\n", g_psample_stats.pkts_d_no_mem); + seq_printf(m, " pkts drop no psample group %10lu\n", g_psample_stats.pkts_d_no_group); + seq_printf(m, " pkts drop sampling disabled %10lu\n", g_psample_stats.pkts_d_sampling_disabled); + seq_printf(m, " pkts drop psample not ready %10lu\n", g_psample_stats.pkts_d_not_ready); + seq_printf(m, " pkts drop metadata parse error %10lu\n", g_psample_stats.pkts_d_metadata); + seq_printf(m, " pkts drop skb error %10lu\n", g_psample_stats.pkts_d_skb); + seq_printf(m, " pkts drop skb cbd error %10lu\n", g_psample_stats.pkts_d_skb_cbd); + seq_printf(m, " pkts with invalid src port %10lu\n", g_psample_stats.pkts_d_meta_srcport); + seq_printf(m, " pkts with invalid dst port %10lu\n", g_psample_stats.pkts_d_meta_dstport); + seq_printf(m, " pkts with invalid orig pkt sz %10lu\n", g_psample_stats.pkts_d_invalid_size); + return 0; +} + +static int +psample_proc_stats_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_stats_show, NULL); +} + +/* + * psample stats Proc Write Entry + * + * Syntax: + * write any value to clear stats + */ +static ssize_t +psample_proc_stats_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int qlen_cur = 0; + unsigned long flags; + + spin_lock_irqsave(&g_psample_work.lock, flags); + qlen_cur = g_psample_stats.pkts_c_qlen_cur; + memset(&g_psample_stats, 0, sizeof(psample_stats_t)); + g_psample_stats.pkts_c_qlen_cur = qlen_cur; + spin_unlock_irqrestore(&g_psample_work.lock, flags); + + return count; +} +struct file_operations psample_proc_stats_file_ops = { + owner: THIS_MODULE, + open: psample_proc_stats_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_stats_write, + release: single_release, +}; + +int psample_cleanup(void) +{ + cancel_work_sync(&g_psample_work.wq); + remove_proc_entry("stats", psample_proc_root); + remove_proc_entry("rate", psample_proc_root); + remove_proc_entry("size", psample_proc_root); + remove_proc_entry("debug", psample_proc_root); + remove_proc_entry("map" , psample_proc_root); + remove_proc_entry("psample", knet_cb_proc_root); + remove_proc_entry("bcm/knet-cb", NULL); + remove_proc_entry("bcm", NULL); + return 0; +} + +int psample_init(void) +{ + #define PROCFS_MAX_PATH 1024 + char psample_procfs_path[PROCFS_MAX_PATH]; + struct proc_dir_entry *entry; + + /* initialize proc files (for ngknet) */ + proc_mkdir("bcm", NULL); + + /* create procfs for psample */ + snprintf(psample_procfs_path, PROCFS_MAX_PATH, "bcm/knet-cb"); + knet_cb_proc_root = proc_mkdir(psample_procfs_path, NULL); + snprintf(psample_procfs_path, PROCFS_MAX_PATH, "%s/%s", psample_procfs_path, PSAMPLE_CB_NAME); + psample_proc_root = proc_mkdir(psample_procfs_path, NULL); + + /* create procfs for psample stats */ + PROC_CREATE(entry, "stats", 0666, psample_proc_root, &psample_proc_stats_file_ops); + if (entry == NULL) { + printk("%s: Unable to create procfs entry '/procfs/%s/stats'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for setting sample rates */ + PROC_CREATE(entry, "rate", 0666, psample_proc_root, &psample_proc_rate_file_ops); + if (entry == NULL) { + printk("%s: Unable to create procfs entry '/procfs/%s/rate'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for setting sample size */ + PROC_CREATE(entry, "size", 0666, psample_proc_root, &psample_proc_size_file_ops); + if (entry == NULL) { + printk("%s: Unable to create procfs entry '/procfs/%s/size'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for getting netdev mapping */ + PROC_CREATE(entry, "map", 0666, psample_proc_root, &psample_proc_map_file_ops); + if (entry == NULL) { + printk("%s: Unable to create procfs entry '/procfs/%s/map'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for debug log */ + PROC_CREATE(entry, "debug", 0666, psample_proc_root, &psample_proc_debug_file_ops); + if (entry == NULL) { + printk("%s: Unable to create procfs entry '/procfs/%s/debug'\n", __func__, psample_procfs_path); + return -1; + } + + /* clear data structs */ + memset(&g_psample_stats, 0, sizeof(psample_stats_t)); + memset(&g_psample_info, 0, sizeof(psample_info_t)); + memset(&g_psample_work, 0, sizeof(psample_work_t)); + + /* FIXME: How to get DCB type from NGKNET? */ + //g_psample_info.dcb_type + + /* setup psample_info struct */ + INIT_LIST_HEAD(&g_psample_info.netif_list); + spin_lock_init(&g_psample_info.lock); + + /* setup psample work queue */ + spin_lock_init(&g_psample_work.lock); + INIT_LIST_HEAD(&g_psample_work.pkt_list); + INIT_WORK(&g_psample_work.wq, psample_task); + + /* get net namespace */ + g_psample_info.netns = get_net_ns_by_pid(current->pid); + if (!g_psample_info.netns) { + printk("%s: Could not get network namespace for pid %d\n", __func__, current->pid); + return (-1); + } + PSAMPLE_CB_DBG_PRINT("%s: current->pid %d, netns 0x%p, sample_size %d\n", __func__, + current->pid, g_psample_info.netns, psample_size); + + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.h b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.h new file mode 100644 index 000000000000..2e3342ead5c3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: psample_cb.h $ + * $Copyright: (c) 2019 Broadcom Corp. + * All Rights Reserved.$ + */ +#ifndef __PSAMPLE_CB_H__ +#define __PSAMPLE_CB_H__ + +#include +#include + +//#define PSAMPLE_SUPPORT 1 // TODO: MLI@BRCM - Add this as part of conditional in Makefile +#define PSAMPLE_CB_NAME "psample" + +extern int +psample_init(void); + +extern int +psample_cleanup(void); + +extern struct sk_buff* +psample_rx_cb(struct sk_buff *skb); + +/* psample data per interface */ +typedef struct { + struct list_head list; + struct net_device *dev; + uint16_t id; + uint8_t port; + uint16_t vlan; + uint16_t qnum; + uint32_t sample_rate; + uint32_t sample_size; +} psample_netif_t; + +extern int +psample_netif_create_cb(struct net_device *dev); + +extern int +psample_netif_destroy_cb(struct net_device *dev); + +#endif /* __PSAMPLE_CB_H__ */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/psample/Kbuild b/platform/broadcom/saibcm-modules/sdklt/linux/psample/Kbuild new file mode 100644 index 000000000000..0049e399076b --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/psample/Kbuild @@ -0,0 +1,18 @@ +# -*- Kbuild -*- +# +# Linux psample module. +# +# $Copyright: (c) 2020 Broadcom. +# Broadcom Proprietary and Confidential. All rights reserved.$ +# + +obj-m := linux_psample.o + +ccflags-y := $(LKM_CFLAGS) \ + -I$(SDK)/shr/include \ + -I$(SDK)/bcmdrd/include \ + -I$(SDK)/linux/include \ + -I$(SDK)/linux/knet/include \ + -I$(SDK)/linux/knet + +linux_psample-y := psample.o diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/psample/Makefile b/platform/broadcom/saibcm-modules/sdklt/linux/psample/Makefile new file mode 100644 index 000000000000..b37b8ebb1c29 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/psample/Makefile @@ -0,0 +1,21 @@ +# -*- Makefile -*- +# +# Linux psample module. +# +# $Copyright: (c) 2020 Broadcom. +# Broadcom Proprietary and Confidential. All rights reserved.$ +# + +include Kbuild + +ifeq ($(KERNELRELEASE),) + +MOD_NAME = linux_psample + +include $(SDK)/make/lkm.mk + +endif + +.PHONY: distclean + +distclean: diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/psample/psample.c b/platform/broadcom/saibcm-modules/sdklt/linux/psample/psample.c new file mode 100644 index 000000000000..f0c9beab5784 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/psample/psample.c @@ -0,0 +1,302 @@ +/* + * net/psample/psample.c - Netlink channel for packet sampling + * Copyright (c) 2017 Yotam Gigi + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PSAMPLE_MAX_PACKET_SIZE 0xffff + +static LIST_HEAD(psample_groups_list); +static DEFINE_SPINLOCK(psample_groups_lock); + +/* multicast groups */ +enum psample_nl_multicast_groups { + PSAMPLE_NL_MCGRP_CONFIG, + PSAMPLE_NL_MCGRP_SAMPLE, +}; + +static const struct genl_multicast_group psample_nl_mcgrps[] = { + [PSAMPLE_NL_MCGRP_CONFIG] = { .name = PSAMPLE_NL_MCGRP_CONFIG_NAME }, + [PSAMPLE_NL_MCGRP_SAMPLE] = { .name = PSAMPLE_NL_MCGRP_SAMPLE_NAME }, +}; + +static struct genl_family psample_nl_family; + +static int psample_group_nl_fill(struct sk_buff *msg, + struct psample_group *group, + enum psample_command cmd, u32 portid, u32 seq, + int flags) +{ + void *hdr; + int ret; + + hdr = genlmsg_put(msg, portid, seq, &psample_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_SAMPLE_GROUP, group->group_num); + if (ret < 0) + goto error; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_GROUP_REFCOUNT, group->refcount); + if (ret < 0) + goto error; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_GROUP_SEQ, group->seq); + if (ret < 0) + goto error; + + genlmsg_end(msg, hdr); + return 0; + +error: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static int psample_nl_cmd_get_group_dumpit(struct sk_buff *msg, + struct netlink_callback *cb) +{ + struct psample_group *group; + int start = cb->args[0]; + int idx = 0; + int err; + + spin_lock(&psample_groups_lock); + list_for_each_entry(group, &psample_groups_list, list) { + if (!net_eq(group->net, sock_net(msg->sk))) + continue; + if (idx < start) { + idx++; + continue; + } + err = psample_group_nl_fill(msg, group, PSAMPLE_CMD_NEW_GROUP, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI); + if (err) + break; + idx++; + } + + spin_unlock(&psample_groups_lock); + cb->args[0] = idx; + return msg->len; +} + +static const struct genl_ops psample_nl_ops[] = { + { + .cmd = PSAMPLE_CMD_GET_GROUP, + .dumpit = psample_nl_cmd_get_group_dumpit, + /* can be retrieved by unprivileged users */ + } +}; + +static struct genl_family psample_nl_family = { + .name = PSAMPLE_GENL_NAME, + .version = PSAMPLE_GENL_VERSION, + .maxattr = PSAMPLE_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .mcgrps = psample_nl_mcgrps, + .ops = psample_nl_ops, + .n_ops = ARRAY_SIZE(psample_nl_ops), + .n_mcgrps = ARRAY_SIZE(psample_nl_mcgrps), +}; + +static void psample_group_notify(struct psample_group *group, + enum psample_command cmd) +{ + struct sk_buff *msg; + int err; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); + if (!msg) + return; + + err = psample_group_nl_fill(msg, group, cmd, 0, 0, NLM_F_MULTI); + if (!err) + genlmsg_multicast_netns(&psample_nl_family, group->net, msg, 0, + PSAMPLE_NL_MCGRP_CONFIG, GFP_ATOMIC); + else + nlmsg_free(msg); +} + +static struct psample_group *psample_group_create(struct net *net, + u32 group_num) +{ + struct psample_group *group; + + group = kzalloc(sizeof(*group), GFP_ATOMIC); + if (!group) + return NULL; + + group->net = net; + group->group_num = group_num; + list_add_tail(&group->list, &psample_groups_list); + + psample_group_notify(group, PSAMPLE_CMD_NEW_GROUP); + return group; +} + +static void psample_group_destroy(struct psample_group *group) +{ + psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP); + list_del(&group->list); + kfree(group); +} + +static struct psample_group * +psample_group_lookup(struct net *net, u32 group_num) +{ + struct psample_group *group; + + list_for_each_entry(group, &psample_groups_list, list) + if ((group->group_num == group_num) && (group->net == net)) + return group; + return NULL; +} + +struct psample_group *psample_group_get(struct net *net, u32 group_num) +{ + struct psample_group *group; + + spin_lock(&psample_groups_lock); + + group = psample_group_lookup(net, group_num); + if (!group) { + group = psample_group_create(net, group_num); + if (!group) + goto out; + } + group->refcount++; + +out: + spin_unlock(&psample_groups_lock); + return group; +} +EXPORT_SYMBOL_GPL(psample_group_get); + +void psample_group_put(struct psample_group *group) +{ + spin_lock(&psample_groups_lock); + + if (--group->refcount == 0) + psample_group_destroy(group); + + spin_unlock(&psample_groups_lock); +} +EXPORT_SYMBOL_GPL(psample_group_put); + +void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, + u32 trunc_size, int in_ifindex, int out_ifindex, + u32 sample_rate) +{ + struct sk_buff *nl_skb; + int data_len; + int meta_len; + void *data; + int ret; + + meta_len = (in_ifindex ? nla_total_size(sizeof(u16)) : 0) + + (out_ifindex ? nla_total_size(sizeof(u16)) : 0) + + nla_total_size(sizeof(u32)) + /* sample_rate */ + nla_total_size(sizeof(u32)) + /* orig_size */ + nla_total_size(sizeof(u32)) + /* group_num */ + nla_total_size(sizeof(u32)); /* seq */ + + data_len = min(skb->len, trunc_size); + if (meta_len + nla_total_size(data_len) > PSAMPLE_MAX_PACKET_SIZE) + data_len = PSAMPLE_MAX_PACKET_SIZE - meta_len - NLA_HDRLEN + - NLA_ALIGNTO; + + nl_skb = genlmsg_new(meta_len + nla_total_size(data_len), GFP_ATOMIC); + if (unlikely(!nl_skb)) + return; + + data = genlmsg_put(nl_skb, 0, 0, &psample_nl_family, 0, + PSAMPLE_CMD_SAMPLE); + if (unlikely(!data)) + goto error; + + if (in_ifindex) { + ret = nla_put_u16(nl_skb, PSAMPLE_ATTR_IIFINDEX, in_ifindex); + if (unlikely(ret < 0)) + goto error; + } + + if (out_ifindex) { + ret = nla_put_u16(nl_skb, PSAMPLE_ATTR_OIFINDEX, out_ifindex); + if (unlikely(ret < 0)) + goto error; + } + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_SAMPLE_RATE, sample_rate); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_ORIGSIZE, skb->len); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_SAMPLE_GROUP, group->group_num); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_GROUP_SEQ, group->seq++); + if (unlikely(ret < 0)) + goto error; + + if (data_len) { + int nla_len = nla_total_size(data_len); + struct nlattr *nla; + + nla = (struct nlattr *)skb_put(nl_skb, nla_len); + nla->nla_type = PSAMPLE_ATTR_DATA; + nla->nla_len = nla_attr_size(data_len); + + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + goto error; + } + + genlmsg_end(nl_skb, data); + genlmsg_multicast_netns(&psample_nl_family, group->net, nl_skb, 0, + PSAMPLE_NL_MCGRP_SAMPLE, GFP_ATOMIC); + + return; +error: + pr_err_ratelimited("Could not create psample log message\n"); + nlmsg_free(nl_skb); +} +EXPORT_SYMBOL_GPL(psample_sample_packet); + +static int __init psample_module_init(void) +{ + return genl_register_family(&psample_nl_family); +} + +static void __exit psample_module_exit(void) +{ + genl_unregister_family(&psample_nl_family); +} + +module_init(psample_module_init); +module_exit(psample_module_exit); + +MODULE_AUTHOR("Yotam Gigi "); +MODULE_DESCRIPTION("netlink channel for packet sampling"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/broadcom/saibcm-modules/sdklt/make/lkm.mk b/platform/broadcom/saibcm-modules/sdklt/make/lkm.mk new file mode 100644 index 000000000000..c3d2a4d40b50 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/make/lkm.mk @@ -0,0 +1,76 @@ +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# 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. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# +# Shared makefile include for building Linux kernel modules. +# + +# KDIR must point to the Linux kernel sources +ifndef KDIR +nokdir:; @echo 'The $$KDIR variable is not set'; exit 1 +endif + +# Required for older kernels +export EXTRA_CFLAGS = $(ccflags-y) + +PWD := $(shell pwd) + +ifneq ($(LKM_BLDDIR),) +# +# If a build directory has been specified, then we symlink all sources +# to this directory and redirect the module build path. +# +# Note that the KBUILD_OUTPUT variable cannot be used to redirect the +# output as we want it. +# +MDIR = $(LKM_BLDDIR) +MSRCS = $(patsubst %.o,%.c,$($(MOD_NAME)-y)) +MSRCS += Makefile Kbuild +BSRCS = $(addprefix $(PWD)/,$(MSRCS)) +else +# +# Build in current directory by default. +# +MDIR = $(PWD) +endif + +all: + $(Q)echo Building kernel module $(MOD_NAME) +ifneq ($(LKM_BLDDIR),) +ifneq ($(LKM_BLDDIR),$(PWD)) + $(Q)mkdir -p $(MDIR) + (cd $(MDIR); \ + rm -rf *.c Makefile Kbuild; \ + for f in $(BSRCS); do \ + ln -s $$f; \ + done) +endif +endif + $(MAKE) -C $(KDIR) M=$(MDIR) + +clean:: + $(Q)echo Cleaning kernel module $(MOD_NAME) + $(MAKE) -C $(KDIR) M=$(MDIR) clean +ifneq ($(LKM_BLDDIR),) +ifneq ($(LKM_BLDDIR),$(PWD)) +# Remove all files except for Makefile (needed by 'make clean') + rm -f $(LKM_BLDDIR)/*[cdors] +endif +endif + +.PHONY: all clean + +# Standard documentation targets +-include $(SDK)/make/doc.mk diff --git a/platform/broadcom/saibcm-modules/sdklt/shr/include/shr/shr_error.h b/platform/broadcom/saibcm-modules/sdklt/shr/include/shr/shr_error.h new file mode 100644 index 000000000000..1924d600de53 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/shr/include/shr/shr_error.h @@ -0,0 +1,195 @@ +/*! \file shr_error.h + * + * Shared error codes. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef SHR_ERROR_H +#define SHR_ERROR_H + +/*! + * \brief Standard SDK error codes. + * + * IMPORTANT: These error codes must match the corresponding text + * messages in shr_error.c. + */ +typedef enum { + + /*! + * The operation completed successfully. + */ + SHR_E_NONE = 0, + + /*! + * This usually indicates that software encountered an internal + * data inconsistency or an unanticipated hardware state. + */ + SHR_E_INTERNAL = -1, + + /*! + * An operation failed due to insufficient dynamically allocated + * memory. + */ + SHR_E_MEMORY = -2, + + /*! + * The first argument of many API routines is a unit number. This + * error occurs if that number refers to a non-existent unit. + */ + SHR_E_UNIT = -3, + + /*! + * A parameter to an API routine was invalid. A null pointer value + * may have been passed to the routine, or an integer parameter + * may be outside of its allowed range. + */ + SHR_E_PARAM = -4, + + /*! + * The operation encountered a pooled resource (e.g. a table or a + * list) with no valid elements. + */ + SHR_E_EMPTY = -5, + + /*! + * The operation encountered a pooled resource (e.g. a table or a + * list) with no room for new elements. + */ + SHR_E_FULL = -6, + + /*! + * The specified entry in a pooled resource (e.g. a table or a + * list) could not be found. + */ + SHR_E_NOT_FOUND = -7, + + /*! + * The specified entry of a pooled resource (e.g. a table or a + * list) already exists. + */ + SHR_E_EXISTS = -8, + + /*! + * The operation did not complete within the maximum allowed time frame. + */ + SHR_E_TIMEOUT = -9, + + /*! + * An operation was attempted before the previous operation had + * completed. + */ + SHR_E_BUSY = -10, + + /*! + * An operation could not be completed. This may be due to a + * hardware or configuration problem. + */ + SHR_E_FAIL = -11, + + /*! + * The operation could not be completed because a required feature + * was disabled. + */ + SHR_E_DISABLED = -12, + + /*! + * The specified identifier was not valid. Note that this error + * code will normally take precedence over \ref SHR_E_PARAM. + */ + SHR_E_BADID = -13, + + /*! + * The operation could not be completed due to lack of hardware + * resources. + */ + SHR_E_RESOURCE = -14, + + /*! + * The operation could not be completed due to incomplete or + * incorrect configuration. + */ + SHR_E_CONFIG = -15, + + /*! + * The hardware does not support the requested operation. + */ + SHR_E_UNAVAIL = -16, + + /*! + * An operation was attempted before initialization was complete. + */ + SHR_E_INIT = -17, + + /*! + * The specified port value was not valid. Note that this error + * code will normally take precedence over \ref SHR_E_PARAM. + */ + SHR_E_PORT = -18, + + /*! + * A low-level register or memory access failed. + */ + SHR_E_IO = -19, + + /*! + * Access method not permitted. Typically returned if attempting + * to write to a read-only object. + */ + SHR_E_ACCESS = -20, + + /*! + * No handler exists to perform the hardware access associated + * with a an operation on a software object. + */ + SHR_E_NO_HANDLER = -21, + + /*! + * The operation was only partially completed, and this could + * potentially leave the system in an unexpected state. + */ + SHR_E_PARTIAL = -22, + + /*! + * The operation failed because of a hash collision. + */ + SHR_E_COLL = -23, + + SHR_E_LIMIT = -24 /* Must come last */ + +} shr_error_t; + +/*! Check for successful return value. */ +#define SHR_SUCCESS(_expr) ((_expr) >= 0) + +/*! Check for error return value. */ +#define SHR_FAILURE(_expr) ((_expr) < 0) + +/*! + * \brief Get standard error message + * + * Returns a text message corresponding to the error code passed in. + * + * \param [in] rv Error code + * + * \return Pointer to error message + */ +extern const char * +shr_errmsg(int rv); + +#endif /* SHR_ERROR_H */ diff --git a/platform/broadcom/saibcm-modules/systemd/opennsl-modules.service b/platform/broadcom/saibcm-modules/systemd/opennsl-modules.service new file mode 100644 index 000000000000..a83f4200dba9 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systemd/opennsl-modules.service @@ -0,0 +1,18 @@ +[Unit] +Description=Opennsl kernel modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/opennsl-modules start +# Don't remove opennsl driver when stopping service. Because +# removing knet drivers takes ~30 seconds to delete netdevs. +# This delay cuts too deep into warm reboot time budget. +# We could skip this step because we don't expect stopping +# opennsl service in any context other than rebooting. +# ExecStop=-/etc/init.d/opennsl-modules stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h new file mode 100644 index 000000000000..c4d31579bfdf --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h @@ -0,0 +1,313 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/*********************************************************************** + * + * $Id: linux-bde.h,v 1.24 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * Linux Broadcom Device Enumerators + * + * + * There are two Linux BDEs: + * + * 1. Linux Kernel BDE + * + * This is a kernel module implementing a BDE + * for the driver running as part of the kernel. + * + * It manages the devices through the linux PCI interfaces, + * and manages a chunk of contiguous, boot-time allocated + * DMA memory. This is all that is needed if the BCM driver + * is run as part of the kernel (in another module). + * + * 2. Linux User BDE + * + * This is a kernel module and userland library which implement + * a complete BDE for applications running in userland. + * + * The kernel module relies upon the real kernel bde, + * and allows a user space application (through the user library) + * to talk directly to the devices. It also virtualized the device + * interrupts, so the entire driver can be run as a userspace + * application. + * + * While this causes a significant degradation in performance, + * because the system runs as a user application, the development + * and debugging process is about a gillion times easier. + * After the core logic is debugged, it can be retargeted using + * only the kernel bde and run in the kernel. + * + * + **********************************************************************/ + +#ifndef __LINUX_BDE_H__ +#define __LINUX_BDE_H__ + +#include +#include + + +/* + * Device Major Numbers + * + * The kernel and user bdes need unique major numbers + * on systems that do not use devfs. + * + * They are defined here, along with the module names, + * to document them if you need to mknod them (or open) them, + * and to keep them unique. + * + */ + +#include + +#ifdef __KERNEL__ +#include +/* Key stone and Raptor has 2.6.21 but don't have definition */ +#if defined(KEYSTONE) || defined(RAPTOR) +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)) + #ifdef PHYS_ADDRS_ARE_64BITS + typedef u64 phys_addr_t; + #else + typedef u32 phys_addr_t; + #endif + #endif +#endif +#endif + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) +#define LINUX_BDE_DMA_DEVICE_SUPPORT +#endif + +#define LINUX_KERNEL_BDE_NAME "linux-kernel-bde" +#define LINUX_KERNEL_BDE_MAJOR 127 + +#define LINUX_USER_BDE_NAME "linux-user-bde" +#define LINUX_USER_BDE_MAJOR 126 + + +/* Max devices */ +/* 16 switch chips + 2 out-of-band Ethernet + 2 CPUs */ +#ifndef LINUX_BDE_MAX_SWITCH_DEVICES +#define LINUX_BDE_MAX_SWITCH_DEVICES 16 +#endif +#define LINUX_BDE_MAX_ETHER_DEVICES 2 +#define LINUX_BDE_MAX_CPU_DEVICES 2 +#define LINUX_BDE_MAX_DEVICES (LINUX_BDE_MAX_SWITCH_DEVICES + \ + LINUX_BDE_MAX_ETHER_DEVICES + \ + LINUX_BDE_MAX_CPU_DEVICES) +#define LINUX_BDE_NOF_DEVICE_BITMAP_WORDS ((LINUX_BDE_MAX_DEVICES+31)/32) +#define LINUX_BDE_MAX_IPROC_UC_CORES 12 /* Maximum number of R5 cores per device */ +typedef uint32 linux_bde_device_bitmap_t[LINUX_BDE_NOF_DEVICE_BITMAP_WORDS]; + +/* + * PCI devices will be initialized by the Linux Kernel, + * regardless of architecture. + * + * You need only provide bus endian settings. + */ + +typedef struct linux_bde_bus_s { + int be_pio; + int be_packet; + int be_other; +} linux_bde_bus_t; + + + +/* Device state used for PCI hot swap case. */ +/* + * BDE_DEV_STATE_NORMAL : A device is probed normally. Or when the device + * resource has been updated after "CHANGED", the state will move back to + * "NORMAL". + */ +#define BDE_DEV_STATE_NORMAL (0) +/* + * BDE_DEV_STATE_REMOVED : A previous probed device was removed. + * We will avoid any device access while the device is in this state. + * The state will be moved to "CHANGED" if the device is re-inserted + * and re-probed. + */ +#define BDE_DEV_STATE_REMOVED (1) +/* + * BDE_DEV_STATE_CHANGED : The device is re-probed after having been removed. + * The resouces assigned to the device might have been changed after + * re-probing, so we need to re-initialize our resource database accordingly. + * The state will change to "NORMAL" when the resource have been updated. + */ +#define BDE_DEV_STATE_CHANGED (2) + +/* + * BDE_DEV_INST_ID_INVALID : The invalid instance identifier. + */ +#define BDE_DEV_INST_ID_INVALID ((uint32)-1) + +extern int linux_bde_create(linux_bde_bus_t* bus, ibde_t** bde); +extern int linux_bde_destroy(ibde_t* bde); +#ifdef BCM_INSTANCE_SUPPORT +extern int linux_bde_instance_attach(unsigned int dev_mask,unsigned int dma_size); +extern int linux_bde_instance_config(linux_bde_device_bitmap_t dev_mask,unsigned int dma_size); +#endif + +#ifdef __KERNEL__ + +#ifdef INCLUDE_EDK +#define BDE_EDK_SUPPORT +#endif + +/* + * Backdoors provided by the kernel bde + * + */ + +/* + * The user bde needs to get cpu physical address for + * the userland code to mmap. + * And the second address is bus address, it is either + * identical to cpu physical address or another address + * (IOVA) translated by IOMMU. + */ +extern int lkbde_get_dma_info(phys_addr_t *cpu_pbase, phys_addr_t *dma_pbase, ssize_t *size); +extern uint32 lkbde_get_dev_phys(int d); +extern uint32 lkbde_get_dev_phys_hi(int d); +#ifdef BDE_EDK_SUPPORT +extern int lkbde_edk_get_dma_info(int dev_id, phys_addr_t* cpu_pbase, + phys_addr_t* dma_pbase, ssize_t* size); +#endif + +/* + * Virtual device address needed by kernel space + * interrupt handler. + */ +extern void *lkbde_get_dev_virt(int d); + +/* + * The user bde needs to get some physical addresses for + * the userland code to mmap. The following functions + * supports multiple resources for a single device. + */ +extern int lkbde_get_dev_resource(int d, int rsrc, uint32_t *phys_lo, + uint32_t *phys_hi, uint32_t *size); + +/* + * Backdoor to retrieve OS device structure to be used for + * DMA operations. + */ +extern void *lkbde_get_dma_dev(int d); + +/* + * Backdoor to retrieve original hardware/OS device. + */ +extern void *lkbde_get_hw_dev(int d); + +/* + * Backdoor to retrieve number of switch devices probed. + */ +extern int lkbde_get_num_devices(int type); + +/* + * Retrive the device state from Kernel BDE. + * Used for KNET and User BDE for pci hot swap case. + */ +extern int lkbde_dev_state_get(int d, uint32 *state); +extern int lkbde_dev_state_set(int d, uint32 state); + +/* + * Retrive the mapping between emulated HW device and instance id + */ +extern int lkbde_dev_instid_get(int d, uint32 *instid); +extern int lkbde_dev_instid_set(int d, uint32 instid); + + +/* + * Return none-zero if the SDK instance with the given instance ID + * manages the given device. + */ +extern int lkbde_is_dev_managed_by_instance(uint32 dev, uint32 inst_id); + +/* + * Return a pointer to the bitmap of the SDK instance managed devices. + */ +extern linux_bde_device_bitmap_t* lkbde_get_inst_devs(uint32 inst_id); + + +/* + * Functions that allow an interrupt handler in user mode to + * coexist with interrupt handler in kernel module. + */ +extern int lkbde_irq_mask_set(int d, uint32 addr, uint32 mask, uint32 fmask); +extern int lkbde_irq_mask_get(int d, uint32 *mask, uint32 *fmask); + +#ifdef BCM_SAND_SUPPORT +extern int lkbde_cpu_write(int d, uint32 addr, uint32 *buf); +extern int lkbde_cpu_read(int d, uint32 addr, uint32 *buf); +extern int lkbde_cpu_pci_register(int d); +#endif + +/* + * This flag must be OR'ed onto the device number when calling + * interrupt_connect/disconnect and irq_mask_set functions from + * a secondary device driver. + */ +#define LKBDE_ISR2_DEV 0x8000 +/* + * This flag should be OR'ed onto the device number when calling + * irq_mask_set functions from a secondary device driver if the + * mask register is iProc register. + */ +#define LKBDE_IPROC_REG 0x4000 + +#ifdef BCM_SAND_SUPPORT +#include +#if defined(__DUNE_LINUX_BCM_CPU_PCIE__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#ifndef _SIMPLE_MEMORY_ALLOCATION_ +#define _SIMPLE_MEMORY_ALLOCATION_ 1 +#endif +#endif +#endif + +#if defined(IPROC_CMICD) && defined(CONFIG_CMA) +#ifndef _SIMPLE_MEMORY_ALLOCATION_ +#define _SIMPLE_MEMORY_ALLOCATION_ 1 +#endif +#endif + +/* Allocation via dma_alloc_coherent is turned off by default */ +#ifndef _SIMPLE_MEMORY_ALLOCATION_ +#define _SIMPLE_MEMORY_ALLOCATION_ 9 /* compile in the allocation method, but do not use it by default */ +#endif + +/* By default we use our private mmap for DMA pool */ +#ifndef USE_LINUX_BDE_MMAP +#define USE_LINUX_BDE_MMAP 1 +#endif + +#endif /* __KERNEL__ */ + +#endif /* __LINUX_BDE_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h new file mode 100644 index 000000000000..23eb3fa33e9e --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h @@ -0,0 +1,86 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/*********************************************************************** + * + * $Id: linux_dma.h,v 1.24 Broadcom SDK $ + * $Copyright: (c) 2016 Broadcom Corp. + * All Rights Reserved.$ + * + **********************************************************************/ + +#ifndef __LINUX_DMA_H__ +#define __LINUX_DMA_H__ + +#include + +#ifdef __KERNEL__ + +#ifdef SAL_BDE_XLP +#define KMALLOC(size, flags) __kmalloc(size, flags) +#else +#define KMALLOC(size, flags) kmalloc(size, flags) +#endif + +#if defined(CONFIG_IDT_79EB334) || defined(CONFIG_BCM4702) +/* ioremap is broken in kernel */ +#define IOREMAP(addr, size) ((void *)KSEG1ADDR(addr)) +#else +#define IOREMAP(addr, size) ioremap_nocache(addr, size) +#endif + +#if defined (__mips__) +#if defined(CONFIG_NONCOHERENT_IO) || defined(CONFIG_DMA_NONCOHERENT) +/* Use flush/invalidate for cached memory */ +#define NONCOHERENT_DMA_MEMORY +/* Remap virtual DMA addresses to non-cached segment */ +#define REMAP_DMA_NONCACHED +#endif /* CONFIG_NONCOHERENT_IO || CONFIG_DMA_NONCOHERENT */ +#endif /* __mips__ */ + +#if defined(BCM958525) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,5)) +#define REMAP_DMA_NONCACHED +#endif + +#ifndef DMA_BIT_MASK +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) +#endif + +extern void _dma_init(int dev_index); +extern int _dma_cleanup(void); +extern void _dma_pprint(struct seq_file *m); +extern uint32_t *_salloc(int d, int size, const char *name); +extern void _sfree(int d, void *ptr); +extern int _sinval(int d, void *ptr, int length); +extern int _sflush(int d, void *ptr, int length); +extern sal_paddr_t _l2p(int d, void *vaddr); +extern void *_p2l(int d, sal_paddr_t paddr); +extern int _dma_pool_allocated(void); +extern int _dma_mmap(struct file *filp, struct vm_area_struct *vma); + +#endif /* __KERNEL__ */ + +#endif /* __LINUX_DMA_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/mpool.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/mpool.h new file mode 100644 index 000000000000..15d496ff623d --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/mpool.h @@ -0,0 +1,47 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: mpool.h,v 1.2 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef __MPOOL_H__ +#define __MPOOL_H__ + +struct mpool_mem_s; +typedef struct mpool_mem_s* mpool_handle_t; + +extern int mpool_init(void); +extern mpool_handle_t mpool_create(void* base_address, int size); +extern void* mpool_alloc(mpool_handle_t pool, int size); +extern void mpool_free(mpool_handle_t pool, void* ptr); +extern int mpool_destroy(mpool_handle_t pool); + +extern int mpool_usage(mpool_handle_t pool); + +#endif /* __MPOOL_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile new file mode 100644 index 000000000000..2aa3bec11d73 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile @@ -0,0 +1,105 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.18 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Makefile for Linux kernel BDE +# +LOCALDIR = systems/bde/linux/kernel + +# Make sure we build for the kernel if this is a user-mode build +ifneq ($(platform), ) +override-target=linux-$(platform) +endif + +include $(SDK)/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +BDE = linux-kernel-bde.o + +# need to add vpath sources +VPATH = ../shared + +# Add the srcs to be found by vpath +LSRCS += mpool.c + +# Add shared BDE sources +VPATH += ../../shared +LSRCS += shbde_pci.c shbde_iproc.c shbde_mdio.c +CFLAGS += -I../../shared/include + +LHDRS += mpool.h +LOBJS = $(addsuffix .o, $(basename $(LSRCS))) +BOBJS = $(addprefix $(BLDDIR)/,$(LOBJS)) + +ifneq ($(kernel_version),2_4) +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := linux-kernel-bde +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: kernel_libs module $(KMODULE) +else +MODULE = $(LIBDIR)/linux-kernel-bde.o + +build: kernel_libs module +endif + +module: kernel_libs $(MODULE) + +$(MODULE): $(BLDDIR)/.tree $(BOBJS) + mkdir -p $(@D) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +kernel_libs: + $(MAKE) -C $(SDK)/systems/linux/kernel/modules/shared + +include $(SDK)/make/Make.depend + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +clean:: + $(MAKE) -C $(SDK)/systems/linux/kernel/modules/shared $@ + $(RM) $(BOBJS) $(MODULE) + $(RM) $(BLDDIR)/$(KERNEL_MODULE_DIR) + +distclean:: + +ifneq ($(kernel_version),2_4) +.PHONY: build kernel_libs +endif diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c new file mode 100644 index 000000000000..9029b3b51477 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c @@ -0,0 +1,4625 @@ +/* + * Copyright 2017 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ + +/* + * Linux Kernel BDE + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "linux_shbde.h" + +#define MEMCPY memcpy + +#ifdef CONFIG_X86_64 +#if (defined(__GNUC__) && (__GNUC__ == 8)) +/* + * Prevent gcc 8.1.10 using a compiler inline memcpy even if using -fno-builtin or + * -fno-builtin-memcpy . + * __inline_memcpy and __memcpy are kernel functions that may be used instead, + * for either an inline or non-inline implementations of the function + */ +#undef MEMCPY +#define MEMCPY __memcpy +#endif /* (defined(__GNUC__) && (__GNUC__ == 8)) */ +#endif /* CONFIG_X86_64 */ + + +#if defined(CMIC_SOFT_BYTE_SWAP) +#define CMIC_SWAP32(_x) ((((_x) & 0xff000000) >> 24) \ + | (((_x) & 0x00ff0000) >> 8) \ + | (((_x) & 0x0000ff00) << 8) \ + | (((_x) & 0x000000ff) << 24)) +#endif /* defined(CMIC_SOFT_BYTE_SWAP) */ + +#define PCI_USE_INT_NONE (-1) +#define PCI_USE_INT_INTX (0) +#define PCI_USE_INT_MSI (1) +#define PCI_USE_INT_MSIX (2) +#ifdef CONFIG_PCI_MSI +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,110)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) +#define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) +#endif +#define msi_control_reg(base) (base + PCI_MSI_FLAGS) +#endif +#endif +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Kernel BDE"); +MODULE_LICENSE("GPL"); + +/* + * PCIe max payload size in bytes. + * The default value if not specified to the kernel module by maxpayload is historically 256. + * The default value may be changed using the BDE_PCIE_MAXPAYLOAD_DEFAULT macro. + */ +#ifndef BDE_PCIE_MAXPAYLOAD_DEFAULT +#define BDE_PCIE_MAXPAYLOAD_DEFAULT 256 +#endif +int maxpayload = BDE_PCIE_MAXPAYLOAD_DEFAULT; +LKM_MOD_PARAM(maxpayload, "i", int, 0); +MODULE_PARM_DESC(maxpayload, +"Limit maximum payload size and request size on PCIe devices"); + +/* Use MSI or MSIX interrupts */ +int usemsi = -1; +LKM_MOD_PARAM(usemsi, "i", int, 0); +MODULE_PARM_DESC(usemsi, +"Use MSI/ MSIX interrupts if supported by kernel"); + +/* Ignore all recognized devices (for debug purposes) */ +int nodevices; +LKM_MOD_PARAM(nodevices, "i", int, 0); +MODULE_PARM_DESC(nodevices, +"Ignore all recognized devices (default no)"); + +int msixcnt = 1; + +/* + * This usually is defined at /usr/include/linux/pci_ids.h + * But this ID is newer. + */ +#ifndef PCI_DEVICE_ID_PLX_9656 +#define PCI_DEVICE_ID_PLX_9656 0x9656 +#endif + +#ifndef PCI_DEVICE_ID_PLX_9056 +#define PCI_DEVICE_ID_PLX_9056 0x9056 +#endif + +/* For 2.4.x kernel support */ +#ifndef IRQF_SHARED +#define IRQF_SHARED SA_SHIRQ +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +typedef unsigned long resource_size_t; +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) */ + +#ifdef BCM_ICS +#define BCM_ICS_CMIC_BASE 0x08000000 +#else + +/* Force interrupt line */ +static int forceirq = -1; +static uint32_t forceirqubm = 0xffffffff; +LKM_MOD_PARAM(forceirq, "i", int, 0); +LKM_MOD_PARAM(forceirqubm, "i", uint, 0); +MODULE_PARM_DESC(forceirq, +"Override IRQ line assigned by boot loader"); +MODULE_PARM_DESC(forceirqubm, +"Bitmap for overriding the IRQ line assigned by boot loader for given units"); + +/* Create SPI slave device (cannot be probed) */ +static uint32_t spi_devid = 0; +LKM_MOD_PARAM(spi_devid, "i", uint, 0); +MODULE_PARM_DESC(spi_devid, +"Create SPI slave device using this device ID"); + +/* Select SPI device revision (cannot be probed) */ +static uint32_t spi_revid = 1; +LKM_MOD_PARAM(spi_revid, "i", uint, 0); +MODULE_PARM_DESC(spi_revid, +"Select device revision for SPI slave device"); + +#endif /* BCM_ICS */ + +/* Debug output */ +static int debug; +LKM_MOD_PARAM(debug, "i", int, 0); +MODULE_PARM_DESC(debug, +"Set debug level (default 0"); +/* Use high memory for DMA */ + +/* module param for probing EB devices. */ +static char *eb_bus; +LKM_MOD_PARAM(eb_bus, "s", charp, 0); +MODULE_PARM_DESC(eb_bus, +"List of EB devices on platform. Input format (BA=%x IRQ=%d RD16=%d WR16=%d"); + +#ifdef KEYSTONE +/* Force SPI Frequency */ +static int spifreq = 0; +LKM_MOD_PARAM(spifreq, "i", int, 0); +MODULE_PARM_DESC(spifreq, +"Force SPI Frequency for Keystone CPU (0 for default frequency)"); +#endif + + +/* Compatibility */ +#ifdef LKM_2_4 +#define _ISR_RET void +#define _ISR_PARAMS(_i,_d,_r) int _i, void *_d, struct pt_regs *_r +#define IRQ_NONE +#define IRQ_HANDLED +#define SYNC_IRQ(_i) synchronize_irq() +#else /* LKM_2_6 */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) +#define _ISR_RET irqreturn_t +#else +#define _ISR_RET int +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) +#define _ISR_PARAMS(_i,_d,_r) int _i, void *_d +#else +#define _ISR_PARAMS(_i,_d,_r) int _i, void *_d, struct pt_regs *_r +typedef irqreturn_t (*irq_handler_t)(int _i, void *_d, struct pt_regs *_r); +#endif +#define SYNC_IRQ(_i) synchronize_irq(_i) +char * ___strtok; +char * strtok(char * s,const char * ct) +{ + char *sbegin, *send; + sbegin = s ? s : ___strtok; + if (!sbegin) { + return NULL; + } + sbegin += strspn(sbegin,ct); + if (*sbegin == '\0') { + ___strtok = NULL; + return( NULL ); + } + send = strpbrk( sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + ___strtok = send; + return (sbegin); +} +LKM_EXPORT_SYM(___strtok); +LKM_EXPORT_SYM(strtok); +#endif /* LKM_2_x */ + +/* PCIe capabilities */ +#ifndef PCI_CAP_ID_EXP +#define PCI_CAP_ID_EXP 0x10 +#endif +#ifndef PCI_EXP_DEVCAP +#define PCI_EXP_DEVCAP 4 +#endif +#ifndef PCI_EXP_DEVCTL +#define PCI_EXP_DEVCTL 8 +#endif +#ifndef PCI_EXT_CAP_START +#define PCI_EXT_CAP_START 0x100 +#endif +#ifndef PCI_EXT_CAP_ID +#define PCI_EXT_CAP_ID(_hdr) (_hdr & 0x0000ffff) +#endif +#ifndef PCI_EXT_CAP_VER +#define PCI_EXT_CAP_VER(_hdr) ((_hdr >> 16) & 0xf) +#endif +#ifndef PCI_EXT_CAP_NEXT +#define PCI_EXT_CAP_NEXT(_hdr) ((_hdr >> 20) & 0xffc) +#endif +#ifndef PCI_EXT_CAP_ID_VNDR +#define PCI_EXT_CAP_ID_VNDR 0x0b +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +#define PCI_FIND_DEV(_d, _v, _fr) pci_find_device(_d, _v, _fr) +#else +#define PCI_FIND_DEV(_d, _v, _fr) pci_get_device(_d, _v, _fr) +#endif + +#if defined(CONFIG_RESOURCES_64BIT) || defined(CONFIG_PHYS_ADDR_T_64BIT) +#define PHYS_ADDR_IS_64BIT +#endif + +/* Structure of private SPI device */ +struct spi_dev { + uint8 cid; /* Chip ID */ + uint32 part; /* Part number of the chip */ + uint8 rev; /* Revision of the chip */ + void *robo; /* ptr to robo info required to access SPI */ + unsigned short phyid_high; /* PHYID HIGH in MII regs of detected chip */ + unsigned short phyid_low; /* PHYID LOW in MII regs of detected chip */ +}; + +struct bde_spi_device_id { + unsigned short phyid_high; /* PHYID HIGH in MII regs of detected chip */ + unsigned short phyid_low; /* PHYID LOW in MII regs of detected chip */ + uint32 model_info; + uint32 rev_info; + uint32 spifreq; +}; + +/* Maximum number of I/O windows supported per device. */ +#define BDE_NUM_IOWIN_MAX 3 + +/* I/O memory window definition. */ +struct memwin_s { + + /* Physical address of I/O window. */ + resource_size_t addr; + + /* Size of I/O window (in bytes). */ + resource_size_t size; +}; + +/* Control Data */ +typedef struct bde_ctrl_s { + struct list_head list; + + /* Specify the type of device, pci, spi, switch, ether ... */ + uint32 dev_type; + + int domain_no; + int bus_no; + int be_pio; + int use_msi; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + struct msix_entry *entries; +#endif + int msix_cnt; + union { + /* Linux PCI device pointer */ + struct pci_dev* _pci_dev; + + /* SPI device pointer */ + struct spi_dev* _spi_dev; + } dev; +#define pci_device dev._pci_dev +#define spi_device dev._spi_dev + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT + struct device *dma_dev; +#endif + + struct memwin_s iowin[BDE_NUM_IOWIN_MAX]; + + /* Secondary mapped base address */ + sal_vaddr_t alt_base_addr; + + /* BDE device description */ + ibde_dev_t bde_dev; + + /* Interrupt Handling */ + int iLine; /* Interrupt line */ + void (*isr)(void *); + void *isr_data; + + /* + * Controls to allow two drivers to share a single set of + * hardware registers. Typically a kernel driver will handle + * a subset of hardware interrupts and a user mode driver + * will handle the remaining interrupts. + */ + void (*isr2)(void *); + void *isr2_data; + uint32_t fmask; /* Interrupts controlled by secondary handler */ + uint32_t imask; /* Enabled interrupts for primary handler */ + uint32_t imask2; /* Enabled interrupts for secondary handler */ + spinlock_t lock; /* Lock for IRQ mask synchronization */ + + /* Hardware abstraction for shared BDE functions */ + shbde_hal_t shbde; + + /* Device state : BDE_DEV_STATE_REMOVED/CHANGED */ + uint32 dev_state; + + /* inst_id */ + uint32 inst_id; /* The instance ID of the instance controlling the device */ +} bde_ctrl_t; + +static bde_ctrl_t _devices[LINUX_BDE_MAX_DEVICES]; + +/* information stored per SDK instance, curently the devices it manages */ +typedef struct { + linux_bde_device_bitmap_t devices; /* The devices controlled by this instance */ +} lkbde_inst_info_t; + +/* Information for each SDK instance (array index), the device that it manages */ +static lkbde_inst_info_t _instance_info[LINUX_BDE_MAX_DEVICES] = {{ .devices = {0}}}; + +static int _ndevices = 0; +static int _switch_ndevices = 0; +static int _ether_ndevices = 0; +static int _cpu_ndevices = 0; + +#define VALID_DEVICE(_n) ((_n >= 0) && (_n < _ndevices)) + +#if defined(IPROC_CMICD) && defined(CONFIG_OF) +#define ICFG_CHIP_ID_REG 0x10236000 +#define IHOST_CMICX_MAX_INTRS 129 +static uint32 iproc_cmicx_irqs[IHOST_CMICX_MAX_INTRS]; +#endif + +/* CPU MMIO area used with CPU cards provided on demo boards */ +#if defined(BCM_SAND_SUPPORT) && (defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__)) +static void *cpu_address = NULL; +#endif + + +/* Broadcom BCM4704 */ +#define BCM4704_VENDOR_ID 0x14E4 +#define BCM4704_DEVICE_ID 0x4704 + +/* SiByte PCI Host */ +#define SIBYTE_PCI_VENDOR_ID 0x166D +#define SIBYTE_PCI_DEVICE_ID 0x0001 + +/* Intel 21150 PCI-PCI Bridge */ +#define DC21150_VENDOR_ID 0x1011 +#define DC21150_DEVICE_ID 0x0022 + +/* HiNT HB4 PCI-PCI Bridge (21150 clone) */ +#define HINT_HB4_VENDOR_ID 0x3388 +#define HINT_HB4_DEVICE_ID 0x0022 + +/* Pericom PI7C8150 PCI-PCI Bridge (21150 clone) */ +#define PI7C8150_VENDOR_ID 0x12D8 +#define PI7C8150_DEVICE_ID 0x8150 + +/* Pericom PI7C9X130 PCI-PCIE Bridge */ +#define PCI_VNDID_PERICOM 0x12D8 +#define PCI_DEVID_PI7C9X130 0xE130 +#define DEV_CTRL_REG 0xb8 + +#define MAX_PAYLOAD_256B (1 << 5) +#define MAX_PAYLOAD_512B (2 << 5) +#define MAX_READ_REQ_256B (1 << 12) + + +/* Freescale 8548 PCI-E host Bridge */ +#define FSL_VENDOR_ID 0x1957 +#define FSL8548PCIE_DEVICE_ID 0x0013 +#define FSL2020EPCIE_DEVICE_ID 0x0070 +#define FSL8548PCIE_DEV_CTRL_REG 0x54 + +/* 4716 PCI-E host Bridge */ +#define BCM4716_VENDOR_ID 0x14e4 +#define BCM4716PCIE_DEVICE_ID 0x4716 +#define BCM4716PCIE_DEV_CAP_REG 0xd4 +#define BCM4716PCIE_DEV_CTRL_REG 0xd8 +#define BCM53000_VENDOR_ID 0x14e4 +#define BCM53000PCIE_DEVICE_ID 0x5300 + +#define BCM53000PCIE_DEV(port) ((port == 0) ? pcie0 : pcie1) +#define BCM53000PCIE_BASE(port) ((port == 0) ? 0xb8005000 : 0xb800e000) +#define BCM53000PCIE_FUNC0_COFIG_SPACE 0x400 +#define BCM53000PCIE_SROM_SPACE 0x800 +#define BCM53000PCIE_DEV_CAP_REG 0xd4 +#define BCM53000PCIE_DEV_CTRL_REG 0xd8 +#define BCM53000PCIE_MAX_PAYLOAD_MASK 0x7 +#define BCM53000PCIE_CAP_MAX_PAYLOAD_256B (1 << 0) +#define BCM53000PCIE_DEFAULT_STATUS 0x00100146 + +/* 16bit wide register. offset 14, 14*2 = 0x1c */ +#define BCM53000PCIE_SPROM_OFFSET 0x1c +/* bit 15:13 spromData.MaxPayloadSize. 1: 256 bytes */ +#define BCM53000PCIE_SPROM_MAX_PAYLOAD_MASK 0xe000 +#define BCM53000PCIE_SPROM_MAX_PAYLOAD_256B (1 << 13) + + +/* Intel 21150, HiNT HB4 and other 21150-compatible */ +#define PCI_CFG_DEC21150_SEC_CLK 0x68 + +#define BCM4704_ENUM_BASE 0x18000000 +#define BCM4704_MEMC_BASE (BCM4704_ENUM_BASE+0x8000) +#define BCM4704_MEMC_PRIORINV 0x18 + +/* PLX PCI-E Switch */ +#define PLX_PEX8608_DEV_ID 0x8608 +#define PLX_PEX8617_DEV_ID 0x8617 +#define PLX_PEX86XX_DEV_CTRL_REG 0x70 + +/* Broadcom BCM58525 */ +#define BCM58525_PCI_VENDOR_ID 0x14E4 +#define BCM58525_PCI_DEVICE_ID 0x8025 +#define BCM58522_PCI_DEVICE_ID 0x8022 + +/* Broadcom BCM58712 */ +#define BCM58712_PCI_VENDOR_ID 0x14E4 +#define BCM58712_PCI_DEVICE_ID 0x168E + +/* Default gicd address if not available in DTB */ +#define IHOST_GICD_REG_ADDR 0x10781100 +#define IHOST_GICD_REG_REMAP_LEN 0x100 + +#define IHOST_GICD_REG_ADDR_VALID(d, addr) \ + (_devices[d].bde_dev.base_address1 && \ + (addr & 0xFFFFFF00) == _devices[d].iowin[1].addr) + +#define IHOST_GICD_REG_ADDR_REMAP(d, addr) \ + (void *)(_devices[d].bde_dev.base_address1 + \ + (addr - ((sal_vaddr_t)_devices[d].iowin[1].addr))) + +static uint32_t _read(int d, uint32_t addr); + +#ifdef BCM_ICS +#else +/* Used to determine overall memory limits across all devices */ +static uint32_t _pci_mem_start = 0xFFFFFFFF; +static uint32_t _pci_mem_end = 0; + +/* Used to control MSI interrupts */ +static int use_msi = 0; +#endif + +#ifdef BCM_PLX9656_LOCAL_BUS + +#define CPLD_OFFSET 0x00800000 +#define CPLD_REVISION_REG 0x0000 +#define CPLD_REVISION_MASK 0xffff +#define CPLD_RESET_REG 0x0004 +#define CPLD_RESET_NONE 0x0000 + +#define PL0_OFFSET 0x00800000 +#define PL0_SIZE 0x00040000 +#define PL0_REVISION_REG 0x0000 + +/* Assume there's only one PLX PCI-to-Local bus bridge if any */ +static bde_ctrl_t plx_ctrl; +static int num_plx = 0; + +#endif /* BCM_PLX9656_LOCAL_BUS */ + +static spinlock_t bus_lock; + +static int +_parse_eb_args(char *str, char * format, ...) + __attribute__ ((format (scanf, 2, 3))); + +static int +_parse_eb_args(char *str, char * format, ...) +{ + va_list args; + + va_start(args, format); + vsscanf(str, format, args); + va_end(args); + + return 0; +} + +static void +_bde_add_device(void) +{ + int add_switch_device = 0; + if (_devices[_ndevices].dev_type & BDE_SWITCH_DEV_TYPE) { + _switch_ndevices++; + add_switch_device = 1; + } else if (_devices[_ndevices].dev_type & BDE_ETHER_DEV_TYPE) { + _ether_ndevices++; + } else if (_devices[_ndevices].dev_type & BDE_CPU_DEV_TYPE) { + _cpu_ndevices++; + } else { + return; + } + _ndevices++; + + /* + * In order to be backward compatible with the user mode BDE + * (specifically the interrupt IOCTLs) and the CM, switch devices + * *must* come first. If this is not the case (due to the probing + * order), we let the non-switch device(s) drop down to the end of + * the device array. + */ + if (add_switch_device) { + bde_ctrl_t tmp_dev; + int i, s = 0; + + while (s < _switch_ndevices) { + if (_devices[s].dev_type & BDE_SWITCH_DEV_TYPE) { + s++; + continue; + } + tmp_dev = _devices[s]; + for (i = s; i < _ndevices - 1; i++) { + _devices[i] = _devices[i+1]; + } + _devices[i] = tmp_dev; + } + + _dma_init(_switch_ndevices-1); + } + + /* Initialize device locks */ + spin_lock_init(&_devices[_ndevices-1].lock); +} + +static int +_eb_device_create(resource_size_t paddr, int irq, int rd_hw, int wr_hw) +{ + bde_ctrl_t *ctrl; + uint32 dev_rev_id = 0x0, dev_id; + + dev_id = _ndevices; + + ctrl = _devices + _ndevices; + + ctrl->dev_type |= BDE_EB_DEV_TYPE | BDE_SWITCH_DEV_TYPE; + ctrl->pci_device = NULL; /* No PCI bus */ + + if(rd_hw) { + ctrl->dev_type |= BDE_DEV_BUS_RD_16BIT; + } + + if (wr_hw) { + ctrl->dev_type |= BDE_DEV_BUS_WR_16BIT; + } + + /* Map in the device */ + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(paddr, 0x10000); + ctrl->iowin[0].addr = paddr; + ctrl->iowin[0].size = 0x10000; + + dev_rev_id = _read(dev_id, 0x178); /* CMIC_DEV_REV_ID */ + + ctrl->bde_dev.device = dev_rev_id & 0xFFFF; + ctrl->bde_dev.rev = (dev_rev_id >> 16) & 0xFF; + + ctrl->iLine = irq; + ctrl->isr = NULL; + ctrl->isr_data = NULL; + + gprintk("Created EB device at BA=%x IRQ=%d RD16=%d WR16=%d device=0x%x\n", + (unsigned int)paddr, irq, rd_hw, wr_hw, ctrl->bde_dev.device); + + _bde_add_device(); + + return 0; +} + +#ifdef BCM_SAND_SUPPORT + +#include + +static int +sand_device_create(void) +{ + bde_ctrl_t* ctrl; + + ctrl = _devices; /* FIX_ME: on petra, take first device */ + +#ifndef __DUNE_LINUX_BCM_CPU_PCIE__ + ctrl->dev_type |= BDE_PCI_DEV_TYPE | BDE_SWITCH_DEV_TYPE; + ctrl->pci_device = NULL; /* No PCI bus */ + + /* Map in the device */ /* FIX_ME: not realy map anything */ + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(0x40000000, 0x100000); + ctrl->iowin[0].addr = 0x40000000; + ctrl->iowin[0].size = 0x100000; + + ctrl->iLine = 0; + ctrl->isr = NULL; + ctrl->isr_data = NULL; + + ctrl->bde_dev.device = BCM88950_DEVICE_ID; + ctrl->bde_dev.rev = BCM88950_A0_REV_ID; +#endif + + /* Map CPU regs */ +#ifdef __DUNE_WRX_BCM_CPU__ + cpu_address = IOREMAP(0x18000000, 0x4000000); +#elif defined(__DUNE_GTO_BCM_CPU__) + cpu_address = IOREMAP(0xe0000000, 0x100000); +#endif + + if ((ctrl->bde_dev.device == PCP_PCI_DEVICE_ID)) { + ctrl->bde_dev.device = GEDI_DEVICE_ID; + ctrl->bde_dev.rev = GEDI_REV_ID; + } + + if ((ctrl->bde_dev.device == ACP_PCI_DEVICE_ID)) { + ctrl->dev_type |= BDE_PCI_DEV_TYPE | BDE_SWITCH_DEV_TYPE; + } + +#ifndef __DUNE_LINUX_BCM_CPU_PCIE__ + _bde_add_device(); +#endif + + return 0; +} +#endif /* BCM_SAND_SUPPORT */ + +#ifdef IPROC_CMICD +static void +iproc_cmicd_get_irqres(ibde_dev_t bde_dev, struct resource *res_irq) +{ + shbde_iproc_config_t iproc_config, *icfg = &iproc_config; + + /* iProc configuration parameters */ + memset(icfg, 0, sizeof(*icfg)); + shbde_iproc_config_init(icfg, bde_dev.device, bde_dev.rev); + + if ((icfg->iproc_ver == 0) && (debug >= 1)) { + gprintk("Unable to determine iProc version\n"); + } + + if (icfg->iproc_ver == 7) { + res_irq->start = 221; + } else if (icfg->iproc_ver == 10) { + res_irq->start = 184; + } + +} + +#include +#include + +extern int iproc_platform_driver_register(struct platform_driver *drv); +extern void iproc_platform_driver_unregister(struct platform_driver *drv); +extern int iproc_platform_device_register(struct platform_device *drv); +extern void iproc_platform_device_unregister(struct platform_device *drv); + +extern struct resource * +iproc_platform_get_resource(struct platform_device *dev, unsigned int type, + unsigned int num); + +#define IPROC_CHIPCOMMONA_BASE 0x18000000 +#define IPROC_CMICD_BASE 0x48000000 +#define IPROC_CMICD_SIZE 0x40000 +#define IPROC_CMICD_INT 194 + +#define IPROC_CMICD_COMPATIBLE "brcm,iproc-cmicd" +#define IPROC_CMICX_COMPATIBLE "brcm,iproc-cmicx" + +static int +iproc_cmicd_probe(struct platform_device *pldev) +{ + bde_ctrl_t *ctrl; + uint32 size, dev_rev_id; + struct resource *memres, *irqres; +#ifdef CONFIG_OF + if (debug >= 1) { + gprintk("iproc_cmicd_probe %s\n", pldev->dev.of_node ? "with device node":""); + } +#endif + memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 0); + if (memres == NULL) { + gprintk("Unable to retrieve iProc CMIC resources"); + return -1; + } + size = memres->end - memres->start + 1; + + ctrl = _devices + _ndevices; + + ctrl->dev_type = BDE_AXI_DEV_TYPE | BDE_SWITCH_DEV_TYPE | BDE_256K_REG_SPACE; + ctrl->pci_device = NULL; /* No PCI bus */ + + /* Map CMIC block in the AXI memory space into CPU address space */ + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(memres->start, size); + if (!ctrl->bde_dev.base_address) { + gprintk("Error mapping iProc CMIC registers"); + return -1; + } + ctrl->iowin[0].addr = memres->start; + ctrl->iowin[0].size = size; + +#ifdef CONFIG_OF + if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) { + uint32 *icfg_chip_id; + icfg_chip_id = (uint32 *)IOREMAP(ICFG_CHIP_ID_REG, 2 * sizeof(uint32)); + if (icfg_chip_id == NULL) { + gprintk("Error mapping ICFG_CHIP_ID_REG\n"); + return -1; + } + ctrl->bde_dev.device = readl(icfg_chip_id) & 0xffff; + ctrl->bde_dev.rev = readl(icfg_chip_id+1) & 0xff; + iounmap(icfg_chip_id); + /* Map GICD block in the AXI memory space into CPU address space */ + memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 1); + if (memres) { + ctrl->bde_dev.base_address1 = (sal_vaddr_t)IOREMAP(memres->start, memres->end - memres->start + 1); + ctrl->iowin[1].addr = memres->start; + ctrl->iowin[1].size = memres->end - memres->start + 1; + } else { + /* Use default address if not available in DTB */ + ctrl->bde_dev.base_address1 = (sal_vaddr_t)IOREMAP(IHOST_GICD_REG_ADDR, IHOST_GICD_REG_REMAP_LEN); + ctrl->iowin[1].addr = IHOST_GICD_REG_ADDR; + ctrl->iowin[1].size = IHOST_GICD_REG_REMAP_LEN; + } + if (ctrl->bde_dev.base_address1) { + if (debug >= 1) { + gprintk("base_address1:0x%lx phys_address1:0x%lx\n", + (unsigned long)ctrl->bde_dev.base_address1, (unsigned long)ctrl->iowin[1].addr); + } + } else { + gprintk("Error mapping ihost GICD registers\n"); + } + } else +#endif + { + /* Read switch device ID from CMIC */ + dev_rev_id = *((uint32 *)(ctrl->bde_dev.base_address + 0x10224)); +#if defined(BCM_CMICM_SUPPORT) && defined(BE_HOST) + ctrl->bde_dev.device = ( (((dev_rev_id >> 16) & 0xff) << 8) | + ((dev_rev_id >> 24) & 0xff)); + ctrl->bde_dev.rev = (dev_rev_id >> 8) & 0xff ; +#else + ctrl->bde_dev.device = dev_rev_id & 0xffff; + ctrl->bde_dev.rev = (dev_rev_id >> 16) & 0xff; +#endif + ctrl->bde_dev.base_address1 = 0; + } + +#ifdef CONFIG_OF + if (!pldev->dev.of_node) +#endif + { + /* Assign locally if not available from device node */ + iproc_cmicd_get_irqres(ctrl->bde_dev, &pldev->resource[0]); + } + +#ifdef CONFIG_OF + if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) { + int i; + memset(iproc_cmicx_irqs, 0, IHOST_CMICX_MAX_INTRS*sizeof(uint32_t)); + for (i = 0; i < IHOST_CMICX_MAX_INTRS; i++) { + irqres = iproc_platform_get_resource(pldev, IORESOURCE_IRQ, i); + if (irqres) { + iproc_cmicx_irqs[i] = irqres->start; + } + if (debug >= 1) { + gprintk("iproc_cmicx_irqs[%d] = %d\n", i, iproc_cmicx_irqs[i]); + } + } + ctrl->iLine = iproc_cmicx_irqs[0]; + } else +#endif + { + irqres = iproc_platform_get_resource(pldev, IORESOURCE_IRQ, 0); + ctrl->iLine = irqres->start; + } + + ctrl->isr = NULL; + ctrl ->isr_data = NULL; + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT + ctrl->dma_dev = &pldev->dev; +#endif + + /* Let's boogie */ + _bde_add_device(); + return 0; +} + +static int +iproc_cmicd_remove(struct platform_device *pldev) +{ + int i; + uint32 mask = BDE_SWITCH_DEV_TYPE | BDE_AXI_DEV_TYPE; + bde_ctrl_t *ctrl; + + for (i = 0; i < _ndevices; i++) { + ctrl = _devices + i; + if ((ctrl->dev_type & mask) == mask) { + if (ctrl->bde_dev.base_address1) { + iounmap((void *)ctrl->bde_dev.base_address1); + ctrl->bde_dev.base_address1 = 0; + } + + if (ctrl->bde_dev.base_address) { + iounmap((void *)ctrl->bde_dev.base_address); + ctrl->bde_dev.base_address = 0; + } + } + } + + return 0; +} +#ifdef CONFIG_OF +static const struct of_device_id iproc_cmicd_of_match[] = { + { .compatible = IPROC_CMICD_COMPATIBLE }, + { .compatible = IPROC_CMICX_COMPATIBLE }, + {}, +}; +MODULE_DEVICE_TABLE(of, iproc_cmicd_of_match); +#endif +static char iproc_cmicd_string[] = "bcmiproc-cmicd"; + +static struct platform_driver iproc_cmicd_driver = +{ + .probe = iproc_cmicd_probe, + .remove = iproc_cmicd_remove, + .driver = + { + .name = iproc_cmicd_string, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = iproc_cmicd_of_match, +#endif + }, +}; + +typedef enum { + IPROC_CMICD_RES_INTR = 0, + IPROC_CMICD_RES_MEM +} IPROC_CMICD_RES_E; + +static struct resource iproc_cmicd_resources[] = { + [IPROC_CMICD_RES_INTR] = { + .flags = IORESOURCE_IRQ, + .start = IPROC_CMICD_INT, + }, + [IPROC_CMICD_RES_MEM] = { + .flags = IORESOURCE_MEM, + .start = IPROC_CMICD_BASE, + .end = IPROC_CMICD_BASE+IPROC_CMICD_SIZE-1, + }, +}; + +static void +iproc_cmicd_release(struct device *dev) +{ +} + +static u64 iproc_cmicd_dmamask = DMA_BIT_MASK(32); + +static struct platform_device iproc_cmicd_pdev = { + .name = iproc_cmicd_string, + .id = 0, + .dev = { + .release = iproc_cmicd_release, + .init_name = iproc_cmicd_string, + .dma_mask = &iproc_cmicd_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = iproc_cmicd_resources, + .num_resources = ARRAY_SIZE(iproc_cmicd_resources), +}; + +static int +iproc_has_cmicd(void) +{ + void *iproc_cca_base; + uint32 cca_cid; + + /* Read ChipcommonA chip id register to identify current SOC */ + iproc_cca_base = IOREMAP(IPROC_CHIPCOMMONA_BASE, 0x3000); + if (iproc_cca_base == NULL) { + gprintk("iproc_has_cmicd: ioremap of ChipcommonA registers failed"); + return 0; + } + cca_cid = readl((uint32 *)iproc_cca_base); + cca_cid &= 0xffff; + iounmap(iproc_cca_base); + + /* Only allowed accessing CMICD module if the SOC has it */ + switch (cca_cid) { + default: + break; + } + + /* Device has CMIC */ + return 1; +} + +#define IPROC_CHIPCOMMONA_EROM_PTR_OFFSET (0x180000fc) +#define EROM_MAX_SIZE (0x1000) +#define EROM_PARTNUM_CMICD (0x14) + +#define EROM_DESC_COMPIDENT (0x1) +#define EROM_DESC_MASTER (0x3) +#define EROM_DESC_ADDR (0x5) +#define EROM_DESC_END (0xF) +#define EROM_DESC_EMPTY (0) + +#define EROM_IS_DESC_COMPIDENT(x) ((x & 0x7) == EROM_DESC_COMPIDENT) +#define EROM_IS_DESC_MASTER(x) ((x & 0x7) == EROM_DESC_MASTER) +#define EROM_IS_DESC_ADDR(x) ((x & 0x7) == EROM_DESC_ADDR) +#define EROM_IS_DESC_END(x) ((x & 0xF) == EROM_DESC_END) + +#define EROM_GET_PARTNUM(x) ((x >> 8) & (0xFFF)) /* Bit 8~19 */ +#define EROM_GET_ADDRESS(x) ((x >> 12) & (0xFFFFF)) /* Bit 12~31 */ +#define EROM_GET_SIZETYPE(x) ((x >> 4) & (0x3)) /* Bit 4~5 */ +#define EROM_GET_AG32(x) ((x >> 3) & (0x1)) /* Bit 3 */ +#define EROM_GET_SIZE(x) ((x >> 12) & (0xFFFFF)) /* Bit 12~31 */ +#define EROM_GET_SG32(x) ((x >> 3) & (0x1)) /* Bit 3 */ + +#define EROM_ADDR_SIZETYPE_4K (0) +#define EROM_ADDR_SIZETYPE_8K (1) +#define EROM_ADDR_SIZETYPE_16K (2) +#define EROM_ADDR_SIZETYPE_MORE (3) + +#define EROM_ADDR_FLAG_AG32 (1) /* Address space greater than 32 bit */ +#define EROM_ADDR_FLAG_SIZE (2) /* Addition size descriptor */ +#define EROM_ADDR_FLAG_SG32 (4) /* Size descriptor greater than 32 bit */ + +static void +iproc_cmicd_get_memregion(struct resource *res_mem) +{ + void *erom_ptr_oft; + uint32_t erom_phy_addr; + uint32_t *erom_base; + uint32_t i = 0; + uint32_t word = 0; + uint8_t more_addr_word = 0; /* bit 0: AG32; bit 1: SIZE; bit 2: SG32 */ + uint8_t found_cmicd_dev = 0; + uint8_t size_type = 0; + bool is_compident_a = 1; /* 1: CompidentA; o/w: CompidentB */ + + erom_ptr_oft = IOREMAP(IPROC_CHIPCOMMONA_EROM_PTR_OFFSET, 0x100); + + erom_phy_addr = readl((uint32 *)(erom_ptr_oft)); + iounmap(erom_ptr_oft); + + erom_base = IOREMAP(erom_phy_addr, EROM_MAX_SIZE); + + while (1) { + word = readl((uint32 *)(erom_base + i)); + + if (EROM_IS_DESC_ADDR(word) || more_addr_word) { + if (more_addr_word == 0) { /* Normal Addr Desc */ + if (EROM_GET_AG32(word) == 1) { + more_addr_word |= EROM_ADDR_FLAG_AG32; + } + + size_type = EROM_GET_SIZETYPE(word); + if (size_type == EROM_ADDR_SIZETYPE_MORE) { + more_addr_word |= EROM_ADDR_FLAG_SIZE; + } + + if (found_cmicd_dev == 1) { + res_mem->start = EROM_GET_ADDRESS(word) << 12; + if (size_type < EROM_ADDR_SIZETYPE_MORE) { + res_mem->end = res_mem->start + 4096 * (1 << size_type) - 1; + } + } + } + else if (more_addr_word & EROM_ADDR_FLAG_AG32) { /* UpperAddr Desc */ + more_addr_word &= ~EROM_ADDR_FLAG_AG32; + + if (found_cmicd_dev == 1) { + /* res_mem->start |= word << 32; */ + gprintk("Expect cmicd address to be 32-bit\n"); + } + } + else if (more_addr_word & EROM_ADDR_FLAG_SIZE) { /* Size Desc */ + if (EROM_GET_SG32(word) == 1) { + more_addr_word |= EROM_ADDR_FLAG_SG32; + } + + more_addr_word &= ~EROM_ADDR_FLAG_SIZE; + + if (found_cmicd_dev == 1) { + res_mem->end = res_mem->start + (EROM_GET_SIZE(word) << 12) - 1; + } + } + else if (more_addr_word & EROM_ADDR_FLAG_SG32) { /* UpperSize Desc */ + more_addr_word &= ~EROM_ADDR_FLAG_SG32; + + if (found_cmicd_dev == 1) { + /* res_mem->end += (word) << 32; */ + gprintk("Expect cmicd size to be 32-bit\n"); + } + } + + if (found_cmicd_dev == 1 && more_addr_word == 0) { + break; /* We have gotten all necessary information, exit the loop */ + } + } + else if (EROM_IS_DESC_COMPIDENT(word)) { + if (is_compident_a == 1) { + if (EROM_GET_PARTNUM(word) == EROM_PARTNUM_CMICD) { + found_cmicd_dev = 1; + } + } + + is_compident_a = 1 - is_compident_a; + } + else if (EROM_IS_DESC_END(word)) { + break; + } + + i++; + } + iounmap(erom_base); + + if (debug >= 1) { + gprintk("CMICD info by %s: cmicd_mem.start=%lx, cmicd_mem.end=%lx\n", + found_cmicd_dev ? "EROM" : "Default", + (unsigned long)iproc_cmicd_resources[IPROC_CMICD_RES_MEM].start, + (unsigned long)iproc_cmicd_resources[IPROC_CMICD_RES_MEM].end); + } +} +#endif /* IPROC_CMICD */ + +#ifdef BCM_ICS +static int +_ics_bde_create(void) +{ + bde_ctrl_t *ctrl; + uint32 dev_rev_id = 0x0; + resource_size_t paddr; + + if (_ndevices == 0) { + ctrl = _devices + _ndevices; + + ctrl->dev_type |= BDE_ICS_DEV_TYPE | BDE_SWITCH_DEV_TYPE; + ctrl->pci_device = NULL; /* No PCI bus */ + + /* Map in the device */ + paddr = BCM_ICS_CMIC_BASE; + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(paddr, 0x10000); + ctrl->iowin[0].addr = paddr; + ctrl->iowin[0].size = 0x10000; + + dev_rev_id = *((unsigned int *)(KSEG1ADDR(paddr + 0x178))); + + ctrl->bde_dev.device = dev_rev_id & 0xFFFF; + ctrl->bde_dev.rev = (dev_rev_id >> 16) & 0xFF; + + ctrl->iLine = 5; /* From raptor linux BSP */ + + ctrl->isr = NULL; + ctrl->isr_data = NULL; + printk("Created ICS device ..%x\n", ctrl->bde_dev.base_address); + _bde_add_device(); + } + + return 0; +} + +#else /* !BCM_ICS */ + +extern struct pci_bus *pci_find_bus(int domain, int busnr); + +/* + * PCI device table. + * Populated from the include/soc/devids.h file. + */ + +static const struct pci_device_id _id_table[] = { + { BROADCOM_VENDOR_ID, BCM5675_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM5676_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56218X_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56218_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56219_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56218R_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56219R_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56214_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56215_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56214R_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56215R_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56216_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56217_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56212_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56213_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56230_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56231_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53718_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53714_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53716_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56018_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56014_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56224_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56225_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56226_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56227_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56228_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56229_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56024_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56025_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53724_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53726_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56100_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56101_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56102_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56105_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56106_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56107_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56110_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56111_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56112_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56115_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56116_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56117_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56300_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56301_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56302_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56303_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56304_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56404_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56305_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56306_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56307_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56308_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56309_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56310_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56311_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56312_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56313_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56314_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56315_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56316_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56317_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56318_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56319_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#ifndef EXCLUDE_BCM56324 + { BROADCOM_VENDOR_ID, BCM56322_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56324_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif /* EXCLUDE_BCM56324 */ + { BROADCOM_VENDOR_ID, BCM53312_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53313_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53314_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53324_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53333_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53334_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53342_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53343_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53344_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53346_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53347_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53393_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53394_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53300_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53301_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53302_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56500_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56501_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56502_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56503_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56504_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56505_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56506_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56507_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56508_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56509_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56510_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56511_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56512_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56513_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56514_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56516_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56517_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56518_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56519_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56580_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56620_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56624_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56626_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56628_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56629_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56680_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56684_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56700_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56701_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56720_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56721_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56725_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56800_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56801_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56802_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56803_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56820_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56821_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56822_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56823_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56825_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56630_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56634_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56636_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56638_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56639_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56538_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56520_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56521_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56522_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56524_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56526_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56534_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56685_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56689_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56331_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56333_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56334_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56338_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56320_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56321_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56132_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56134_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88732_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56140_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56142_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56143_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56144_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56146_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56147_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56149_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56150_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56151_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56152_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56930_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56931_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56936_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56939_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56840_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56841_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56842_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56843_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56844_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56845_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56846_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56847_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56549_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56053_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56838_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56831_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56835_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56849_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56742_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56743_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56744_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56745_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56746_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56640_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56548_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56547_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56346_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56345_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56344_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56342_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56340_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56049_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56048_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56047_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56042_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56041_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56040_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56643_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56644_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56648_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56649_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56540_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56541_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56542_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56543_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56544_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56545_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56546_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56044_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56045_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56046_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM55440_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56440_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56441_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56442_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56443_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56445_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56446_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56447_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56448_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56449_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56240_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56241_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56242_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56243_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56245_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56246_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM55450_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM55455_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56260_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56270_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56271_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56272_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53460_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53461_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56261_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56262_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56263_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56265_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56266_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56267_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56268_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56233_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56460_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56461_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56462_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56463_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56465_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56466_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56467_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56468_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56246_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56248_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56450_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56452_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56454_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56455_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56456_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56457_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56458_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56850_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56851_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56852_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56853_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56854_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56855_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56834_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56750_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56830_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM55440_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM55441_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56060_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56062_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56063_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56064_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56065_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56066_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53401_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53411_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53402_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53412_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53403_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53413_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53404_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53414_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53405_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53415_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53406_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53416_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53408_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53418_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53454_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53455_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53456_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53457_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53422_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53424_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53426_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53365_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53369_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56960_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56961_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56962_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56963_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56930_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56968_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56970_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56971_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56972_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56974_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56975_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56168_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56169_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56560_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56561_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56562_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56565_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56566_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56567_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56670_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56671_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56672_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56675_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56568_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56670_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56760_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56761_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56762_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56764_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56765_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56766_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56768_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56069_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56068_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56160_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56162_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56163_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56164_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56166_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53440_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53443_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53442_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53434_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56965_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56969_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56966_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56967_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56170_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56172_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56174_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53570_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53575_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56070_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56071_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56072_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9656, PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9056, PCI_ANY_ID, PCI_ANY_ID }, + { BCM53000_VENDOR_ID, BCM53000PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#ifdef BCM_PETRA_SUPPORT + { BROADCOM_VENDOR_ID, BCM88650_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88350_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88351_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88450_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88451_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88550_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88551_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88552_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88651_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88654_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { PCP_PCI_VENDOR_ID, PCP_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { ACP_PCI_VENDOR_ID, ACP_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88660_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88670_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88671_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88671M_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88672_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88673_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88674_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88675_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88675M_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88676_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88676M_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88677_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88678_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88679_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88370_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88371_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88371M_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88375_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88470_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88470P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88471_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88473_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88474_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88474H_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88476_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88477_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + + + { BROADCOM_VENDOR_ID, BCM88270_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88271_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88272_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88273_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88274_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88276_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88278_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88279_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + + { BROADCOM_VENDOR_ID, BCM8206_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + + { BROADCOM_VENDOR_ID, BCM88376_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88376M_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88377_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88378_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88379_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88680_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88681_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88682_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88683_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88684_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88685_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88687_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88380_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88381_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88360_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88361_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88363_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88460_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88461_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88560_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88561_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88562_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88661_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88664_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif +#ifdef BCM_DNX_SUPPORT + { BROADCOM_VENDOR_ID, BCM88690_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88690_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88691_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88692_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88693_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88694_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88695_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88696_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88697_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88698_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88699_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88800_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88801_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88802_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88803_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88804_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88805_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88806_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88807_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88808_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88809_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88820_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88821_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88822_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88823_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88824_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88825_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88826_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88827_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88828_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88829_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88480_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88481_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88482_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88483_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88484_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88485_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88486_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88487_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88488_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88489_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8848A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8848B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8848C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8848D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8848E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8848F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88280_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88281_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88282_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88283_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88284_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88285_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88286_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88287_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88288_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88289_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88850_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88851_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88852_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88853_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88854_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88855_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88856_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88857_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88858_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88859_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif /* BCM_DNX_SUPPORT */ +#ifdef BCM_DFE_SUPPORT + { BROADCOM_VENDOR_ID, BCM88770_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88773_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88774_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88775_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88776_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88777_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#ifndef DNX_IGNORE_FE3200 + { BROADCOM_VENDOR_ID, BCM88950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif + { BROADCOM_VENDOR_ID, BCM88953_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88954_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88955_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88956_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88772_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88952_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif +#ifdef BCM_DNXF_SUPPORT + { BROADCOM_VENDOR_ID, BCM88790_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88791_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88792_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88793_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88794_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88795_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88796_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88797_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88798_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88799_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8879A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8879B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8879C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8879D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8879F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif + { BROADCOM_VENDOR_ID, BCM56860_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56861_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56862_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56864_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56865_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56866_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56867_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56868_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56833_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56832_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56836_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56870_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56273_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56274_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56275_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56276_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56277_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56278_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56279_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56575_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56175_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56176_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56370_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56371_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56372_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56374_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56375_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56376_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56377_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56577_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56578_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56579_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56873_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56770_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56771_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56980_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56981_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56982_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56983_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56984_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53540_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53547_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53548_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM53549_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56470_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56471_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56472_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56475_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { 0, 0, 0, 0 } +};; + +MODULE_DEVICE_TABLE(pci, _id_table); + +#define pci_bus_b(n) list_entry(n, struct pci_bus, node) +#define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list) +#define MAX_RC_NUM 4 + +static struct pci_bus * +pci_do_bus_find(struct pci_bus* bus, int rc, int vendor, int device) +{ + struct list_head *tmp; + struct pci_dev *dev; + struct pci_bus *sub_bus; + int func = 0; + + if (unlikely(list_empty(&bus->children))) { + return NULL; + } + list_for_each(tmp, &bus->children) { + sub_bus = pci_bus_b(tmp); + dev = sub_bus->self; + func = dev->devfn & 0x7; + if (dev->vendor == vendor && dev->device == device && rc == func) { + if (debug >= 1) { + gprintk("pci_do_bus_find: dev->vendor = 0x%x, dev->device = 0x%x on rc(%d)\n", + dev->vendor, dev->device, rc); + } + return sub_bus; + } + } + return NULL; +} + +static struct pci_dev * +_pci_do_bus_dev_find(struct pci_bus* bus, unsigned int vendor, unsigned int device) +{ + struct list_head *tmp; + struct pci_dev *dev; + + if (unlikely(list_empty(&bus->devices))) { + return NULL; + } + list_for_each(tmp, &bus->devices) { + dev = pci_dev_b(tmp); + if (dev->vendor == vendor && (device == PCI_ANY_ID || dev->device == device)) { + if (debug >= 1) { + gprintk("_pci_do_rc_dev_find: vendor = %x, device = %x\n", vendor, device); + } + return dev; + } + } + return NULL; +} + +static struct pci_dev * +pci_do_rc_dev_find(int rc) +{ + struct pci_bus *root_bus = pci_find_bus(0,0); + struct pci_bus *bus_rc = NULL; + struct pci_dev *dev_on_rc = NULL; + unsigned int pci_dev_id = 0; + + if(NULL == root_bus) { + if (debug >= 1) gprintk("Not find root bus\n"); + return NULL; + } + bus_rc = pci_do_bus_find(root_bus, rc, 0x184e, 0x1004); + if (NULL == bus_rc) { + if (debug >= 1) { + gprintk("Not find vendor(0x184e) device(0x1004) bus\n"); + } + return NULL; + } + for(pci_dev_id = 0; pci_dev_id < sizeof(_id_table)/sizeof(struct pci_device_id); pci_dev_id++) { + dev_on_rc = _pci_do_bus_dev_find(bus_rc, _id_table[pci_dev_id].vendor, _id_table[pci_dev_id].device); + if (NULL != dev_on_rc) { + return dev_on_rc; + } + } + if (debug >= 1) { + gprintk("Not find device at rc(%d)\n", rc); + } + return NULL; +} + +/* + * Function: p2p_bridge + * + * Purpose: + * Finalize initialization secondary PCI-PCI bridge. + * Parameters: + * membase - start of memory address space for secondary PCI bus + * Returns: + * 0 + * Notes: + * The membase depends on the processor architecture, and is + * derived from the memory space addresses set up by the kernel. + */ +static int +p2p_bridge(void) +{ + struct pci_dev *dev, *dev_on_rc; + uint16 cmd; + uint16 mem_base; + uint16 mem_limit; + uint8 bridge_ctrl; + uint8 rc_index; + + if ((dev = PCI_FIND_DEV(DC21150_VENDOR_ID, DC21150_DEVICE_ID, NULL)) != NULL || + (dev = PCI_FIND_DEV(HINT_HB4_VENDOR_ID, HINT_HB4_DEVICE_ID, NULL)) != NULL || + (dev = PCI_FIND_DEV(PI7C8150_VENDOR_ID, PI7C8150_DEVICE_ID, NULL)) != NULL) { + + if (debug >= 1) gprintk("fixing up PCI-to-PCI bridge\n"); + /* Adjust command register */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + /* Disable device */ + pci_write_config_word(dev, PCI_COMMAND, 0); + /* Initialize non-prefetchable memory window if needed */ + pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base); + if (mem_base == 0) { + mem_base = (uint16)((_pci_mem_start & 0xFFF00000) >> 16); + mem_limit = (uint16)((_pci_mem_end & 0xFFF00000) >> 16); + pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base); + pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit); + } + /* Enable PCI clocks on remote end */ + pci_write_config_word(dev, PCI_CFG_DEC21150_SEC_CLK, 0); + /* Re-enable config space */ + pci_write_config_word(dev, PCI_COMMAND, cmd); + + /* Avoid DMA data corruption */ + if (dev->vendor == HINT_HB4_VENDOR_ID) { + /* Fix for HiNT bridge and BCM4704 DMA problem */ + if ((dev = PCI_FIND_DEV(BCM4704_VENDOR_ID, BCM4704_DEVICE_ID, NULL)) != NULL) { + /* Reset PrefetchEn (PE) */ + pci_write_config_dword(dev, 0x8c, 1); + if (debug >= 1) { + gprintk("reset PrefetchEn on BCM4704 when HiNT bridge is present\n"); + } + } + } + } + /* Enable fast back-to-back read/write */ + if ((dev = PCI_FIND_DEV(PI7C8150_VENDOR_ID, PI7C8150_DEVICE_ID, NULL)) != NULL) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_FAST_BACK; + pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bridge_ctrl); + bridge_ctrl |= PCI_BRIDGE_CTL_FAST_BACK; + pci_write_config_word(dev, PCI_COMMAND, 0); + pci_write_config_byte(dev, PCI_BRIDGE_CONTROL, bridge_ctrl); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + /* Netlogic XLP CPU */ + for(rc_index = 0; rc_index < MAX_RC_NUM; rc_index++) { + dev_on_rc = pci_do_rc_dev_find(rc_index); + if (dev_on_rc != NULL ) { + dev = PCI_FIND_DEV(0x184e, 0x1004, NULL); + if (dev != NULL ) { + pci_write_config_dword(dev,0x78,MAX_PAYLOAD_256B | + MAX_READ_REQ_256B); + } + } + } + if ((dev = PCI_FIND_DEV(0x14e4, 0xb634, NULL)) != NULL) { + pci_write_config_dword(dev,0x78,MAX_PAYLOAD_256B | + MAX_READ_REQ_256B); + } + + if ((dev = PCI_FIND_DEV(PCI_VNDID_PERICOM, PCI_DEVID_PI7C9X130, NULL)) != NULL) { + /* + * Configure the PCIE cap: Max payload size: 256, Max Read + * Request size: 256, disabling relax ordering. + * Writes to the PCIE capability device control register + */ + pci_write_config_dword(dev, DEV_CTRL_REG, + MAX_PAYLOAD_256B | MAX_READ_REQ_256B); + } + + if ((dev = PCI_FIND_DEV(FSL_VENDOR_ID, FSL8548PCIE_DEVICE_ID, NULL)) != NULL || + (dev = PCI_FIND_DEV(FSL_VENDOR_ID, FSL2020EPCIE_DEVICE_ID, NULL)) != NULL) { + /* + * Configure the PCIE cap: Max payload size: 256, Max Read + * Request size: 256, disabling relax ordering. + * Writes to the PCIE capability device control register + */ + pci_write_config_dword(dev, FSL8548PCIE_DEV_CTRL_REG, + MAX_PAYLOAD_256B | MAX_READ_REQ_256B); + } + if ((dev = PCI_FIND_DEV(BCM4716_VENDOR_ID, BCM4716PCIE_DEVICE_ID, NULL)) != NULL || + (dev = PCI_FIND_DEV(BCM53000_VENDOR_ID, BCM53000PCIE_DEVICE_ID, NULL)) != NULL) { + uint32 tmp, maxpayld, device_bmp=0, mask; + unsigned long addr; + uint16 tmp16, tmp161; + int i, bus0 = -1, bus1 = -1, port; + struct pci_dev *pcie0, *pcie1; + + pcie0 = dev; + bus0 = dev->bus->number; + if ((pcie1 = PCI_FIND_DEV(BCM53000_VENDOR_ID, BCM53000PCIE_DEVICE_ID, pcie0)) != NULL) { + bus1 = pcie1->bus->number; + } + + for(i = 0; i < _ndevices; i++) { + bde_ctrl_t *ctrl = _devices + i; + + mask = BDE_SWITCH_DEV_TYPE | BDE_PCI_DEV_TYPE; + if ((ctrl->dev_type & mask) == mask) { + if (ctrl->pci_device->bus->number == bus0) { + device_bmp |= 1 << 0; + } + if (ctrl->pci_device->bus->number == bus1) { + device_bmp |= 1 << 1; + } + } + } + + /* configure the PCIE cap: Max payload size: 256, Max Read + * Request size: 256, disabling relax ordering. + * Writes to the PCIE capability device control register + */ + + i = 0; + while(device_bmp) { + if (device_bmp & (1 << i)){ + port = i ; + pci_read_config_dword(BCM53000PCIE_DEV(port), + BCM53000PCIE_DEV_CAP_REG, &tmp); + maxpayld = (tmp & BCM53000PCIE_MAX_PAYLOAD_MASK); + if (debug >= 1) { + gprintk("port %d\n",port); + gprintk("DevCap (@%x): 0x%x%c\n", BCM53000PCIE_DEV_CAP_REG, tmp, + (maxpayld != BCM53000PCIE_CAP_MAX_PAYLOAD_256B) ? ' ':'\n'); + } + if (maxpayld != BCM53000PCIE_CAP_MAX_PAYLOAD_256B) { + addr = BCM53000PCIE_BASE(port); + addr |= (BCM53000PCIE_SROM_SPACE | BCM53000PCIE_SPROM_OFFSET); + tmp16 = *((uint16 *)addr); + if (debug >= 1){ + gprintk("addr %lx spromData.MaxPayloadSize: 0x%x\n", addr, tmp16); + } + mask = BCM53000PCIE_SPROM_MAX_PAYLOAD_MASK; + if ((tmp16 & mask) != BCM53000PCIE_SPROM_MAX_PAYLOAD_256B) { + tmp161 = (tmp16 & ~mask) | BCM53000PCIE_SPROM_MAX_PAYLOAD_256B; + *((uint16 *)addr) = tmp161; + if (debug >= 1) { + tmp16 = 0; + tmp16 = *((uint16 *)addr); + gprintk("Enable spromData.MaxPayloadSize to 1 (256 bytes): " + "0x%x (%s w/ 0x%x)\n", tmp161, + ((tmp16 & mask) == BCM53000PCIE_SPROM_MAX_PAYLOAD_256B) ? + "Success":"Fail", + tmp16); + } + } + pci_read_config_dword(BCM53000PCIE_DEV(port), + BCM53000PCIE_DEV_CAP_REG, &tmp); + if (debug >= 1){ + gprintk("DevCap (@%x): now is 0x%x\n\n", + BCM53000PCIE_DEV_CAP_REG, tmp); + } + } + + addr = BCM53000PCIE_BASE(port); + addr |= (BCM53000PCIE_FUNC0_COFIG_SPACE | BCM53000PCIE_DEV_CTRL_REG); + tmp16 = *((uint16 *)addr); + if (debug >= 1) { + gprintk("DevControl (@%x): 0x%x\n", BCM53000PCIE_DEV_CTRL_REG, tmp16); + } + if (!(tmp16 & MAX_PAYLOAD_256B) || !(tmp16 & MAX_READ_REQ_256B)) { + tmp161 = tmp16 | MAX_PAYLOAD_256B | MAX_READ_REQ_256B; + *((uint16 *)addr) = tmp161; + if (debug >= 1) { + tmp16 = 0; + tmp16 = *((uint16 *)addr); + gprintk("addr %lx Enable DevControl MaxPayloadSize to 1 (256 bytes): " + "0x%x (%s w/ 0x%x)\n", addr, tmp161, + (tmp16 & MAX_PAYLOAD_256B) ? "Success":"Fail", + tmp16); + gprintk("Enable DevControl MaxReadRequestSize to 1 (256 bytes): " + "0x%x (%s w/ 0x%x)\n\n", tmp161, + (tmp16 & MAX_READ_REQ_256B) ? "Success":"Fail", + tmp16); + } + } + device_bmp &= ~(1 << i); + } + i++; + } + } + + /* + * Configure max payload to 512 on all ports in the PLX8608/PLX8617. + * The device supports 128, 512, and 1024 max payload sizes. + */ + dev = NULL; + while ((dev = PCI_FIND_DEV(PCI_VENDOR_ID_PLX, PCI_ANY_ID, dev)) != NULL) { + if ((dev->device == PLX_PEX8608_DEV_ID) || + (dev->device == PLX_PEX8617_DEV_ID)) { + uint16 ctrl_reg; + pci_read_config_word(dev, PLX_PEX86XX_DEV_CTRL_REG, &ctrl_reg); + ctrl_reg = (ctrl_reg & ~(7<<5)) | MAX_PAYLOAD_512B; + pci_write_config_word(dev, PLX_PEX86XX_DEV_CTRL_REG, ctrl_reg); + } + } + return 0; +} + +#ifdef BCM_PLX9656_LOCAL_BUS + +#define PLX_LAS0_BA 0x00000004 /* LAS0 Local Base Address Remap */ +#define PLX_LAS1_BA 0x000000f4 /* LAS1 Local Base Address Remap */ +#define PLX_LAS_EN 0x00000001 /* Space Enable bit */ + +#define PLX_MMAP_PCIBAR0 0 /* Memory-Mapped Config (PCIBAR0) */ +#define PLX_LAS0_PCIBAR2 2 /* Local Address Space 0 (PCIBAR2) */ +#define PLX_LAS1_PCIBAR3 3 /* Local Address Space 1 (PCIBAR3) */ + +STATIC int +_plx_las_bar_get(struct pci_dev *dev) +{ + void *local_config_addr; + int bar = -1; + + local_config_addr = IOREMAP(pci_resource_start(dev, PLX_MMAP_PCIBAR0), + pci_resource_len(dev, PLX_MMAP_PCIBAR0)); + if (local_config_addr) { + uint32 las_remap_reg; + /* + * Make sure LAS0BA or LAS1BA is enabled before returning + * BAR that will be used to access the Local Bus + */ + las_remap_reg = ioread32(local_config_addr + PLX_LAS0_BA); + if (las_remap_reg & PLX_LAS_EN) { + bar = PLX_LAS0_PCIBAR2; + } else { + las_remap_reg = ioread32(local_config_addr + PLX_LAS1_BA); + if (las_remap_reg & PLX_LAS_EN) { + bar = PLX_LAS1_PCIBAR3; + } + } + } + iounmap(local_config_addr); + return bar; +} +#endif /* BCM_PLX9656_LOCAL_BUS */ + +static void +_shbde_log_func(int level, const char *str, int param) +{ + level = (level >= SHBDE_DBG) ? 1 : 0; + if (debug >= level) { + gprintk("%s (%d)\n", str, param); + } +} +/* + * Function: _device_rescan_validate + * + * Purpose: + * Check if the device is ever probed or not. + * Parameters: + * dev - Linux PCI device structure + * Returns: + * >= 0 : dev is ever probed + * reutrn value is the index point to the _devices[] + * -1 : dev is not probed before. + */ +static int +_device_rescan_validate(struct pci_dev *dev) +{ + bde_ctrl_t *ctrl; + int i; + + if (PCI_FUNC(dev->devfn) > 0) { + return -1; + } + ctrl = NULL; + for (i = 0; i < _ndevices; i ++) { + ctrl = _devices + i; + /* check the device id */ + if (dev->device == ctrl->bde_dev.device) { + /* check the bus number */ + if ((dev->bus)) { + if ((dev->bus->number == ctrl->bus_no) && + (pci_domain_nr(dev->bus) == ctrl->domain_no)) { + return i; + } + } + } + } + return -1; +} + +#ifdef CONFIG_PCI_MSI + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) +/** + * _pci_msix_table_size - return the number of device's MSI-X table entries + * @dev: pointer to the pci_dev data structure of MSI-X device function + */ +static int +_pci_msix_table_size(struct pci_dev *dev) +{ + int nr_entries = 0; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,110)) + u16 control; + int pos; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos) { + pci_read_config_word(dev, msi_control_reg(pos), &control); + nr_entries = msix_table_size(control); + } +#else +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)) +{ + /* Pass large entry value to enable MSIX to get # of entires */ + struct msix_entry *entries; + entries = kmalloc(sizeof(struct msix_entry) * + PCI_MSIX_FLAGS_QSIZE, GFP_KERNEL); + if (entries != NULL) { + nr_entries = pci_enable_msix(dev, + entries, PCI_MSIX_FLAGS_QSIZE); + if (nr_entries < 0) { + nr_entries = 0; + } + pci_disable_msix(dev); + kfree(entries); + } +} +#else + nr_entries = pci_msix_vec_count(dev); +#endif +#endif + + return nr_entries; +} +#endif + +static int +_msi_connect(bde_ctrl_t *ctrl) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + int ret; + if (ctrl->use_msi == PCI_USE_INT_MSIX) { + int i; + + ret = _pci_msix_table_size(ctrl->pci_device); + if (ret == 0) { + /* MSI-X failed */ + gprintk("MSI-X not supported.\n"); + goto er_intx; + } + ctrl->entries = kcalloc(ret, sizeof(struct msix_entry), GFP_KERNEL); + + if (!ctrl->entries) { + goto er_intx; + } + /* Only one vector is mapped by default */ + /* May be more in future, can be controlled using module param */ + ctrl->msix_cnt = msixcnt; + if (unlikely(debug > 1)) + gprintk("MSIX Table size = %d\n", ctrl->msix_cnt); + for (i = 0; i < ctrl->msix_cnt; i++) + ctrl->entries[i].entry = i; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) + ret = pci_enable_msix_range(ctrl->pci_device, + ctrl->entries, ctrl->msix_cnt, ctrl->msix_cnt); +#else + ret = pci_enable_msix(ctrl->pci_device, + ctrl->entries, ctrl->msix_cnt); + if (ret > 0) { + /* Not enough vectors available , Retry MSI-X */ + gprintk("Retrying with MSI-X interrupts = %d\n", ret); + ctrl->msix_cnt = ret; + msixcnt = ret; + ret = pci_enable_msix(ctrl->pci_device, + ctrl->entries, ctrl->msix_cnt); + if (ret != 0) + goto er_intx_free; + } +#endif + if (ret < 0) { + /* Error */ + goto er_intx_free; + } else { + gprintk("Enabled MSI-X interrupts = %d\n", ctrl->msix_cnt); + return 0; + } + } +#endif + + if (ctrl->use_msi == PCI_USE_INT_MSI) { + if (pci_enable_msi(ctrl->pci_device) == 0) { + ctrl->iLine = ctrl->pci_device->irq; + } else { + /* MSI failed */ + gprintk("Failed to initialize MSI interrupts.\n"); + goto er_intx; + } + } else { + /* failed */ + gprintk("Not MSI/MSIX interrupt.\n"); + goto er_intx; + } + return 0; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) +er_intx_free: + gprintk("Failed to enable MSI-X interrupts = %d\n", ret); + kfree(ctrl->entries); +#endif +er_intx: + return -1; + +} + +static int +_msi_disconnect(bde_ctrl_t *ctrl) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + if (ctrl->use_msi == PCI_USE_INT_MSIX) { + if (ctrl->msix_cnt) { + pci_disable_msix(ctrl->pci_device); + kfree(ctrl->entries); + ctrl->entries = NULL; + ctrl->msix_cnt = 0; + } + } +#endif + if (ctrl->use_msi == PCI_USE_INT_MSI) { + pci_disable_msi(ctrl->pci_device); + } else { + gprintk("MSI not used\n"); + } + return 0; +} + +#endif + + +static void +config_pci_intr_type(struct pci_dev *dev, bde_ctrl_t *ctrl, int iproc) +{ +#ifdef CONFIG_PCI_MSI + int ret; + shbde_iproc_config_t icfg; + + /* Each device follows global policy by default */ + ctrl->use_msi = use_msi; + + if (unlikely(debug > 1)) + gprintk("%s: msi = %d\n", __func__, ctrl->use_msi); + + /* Check IPROC version for MSIX support */ + if (iproc && ctrl->bde_dev.base_address1 && + (ctrl->use_msi == PCI_USE_INT_MSIX)) { + if (shbde_pci_iproc_version_get(&ctrl->shbde, dev, &icfg.iproc_ver, + &icfg.cmic_ver, &icfg.cmic_rev)) { + if (icfg.iproc_ver < 0xe) { + gprintk("%s: MSI-X not supported, using MSI.\n", __func__); + ctrl->use_msi = PCI_USE_INT_MSI; + } + } + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + if (ctrl->use_msi == PCI_USE_INT_MSIX) { + /* check for support MSIX vector */ + ret = _pci_msix_table_size(ctrl->pci_device); + if (ret == 0) { + gprintk("%s: Zero MSIX table size\n", __func__); + ctrl->use_msi = PCI_USE_INT_MSI; + } + } +#endif + + if (ctrl->use_msi == PCI_USE_INT_MSI) { + /* check for support MSI vector */ + ret = pci_enable_msi(ctrl->pci_device); + if (ret < 0) { + ctrl->use_msi = PCI_USE_INT_INTX; + gprintk("%s: Failed to enable MSI, using INTx.\n", __func__); + } else { + pci_disable_msi(ctrl->pci_device); + } + } +#else + ctrl->use_msi = PCI_USE_INT_INTX; +#endif +} + +/* + * Function: _pci_probe + * + * Purpose: + * Device initialization callback used by the Linux PCI + * subsystem. Called as a result of pci_register_driver(). + * Parameters: + * dev - Linux PCI device structure + * Returns: + * 0 + */ +static int +_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) +{ + bde_ctrl_t *ctrl; + resource_size_t paddr; + uint16 cmd = 0; + uint32 bar_len; + int i, cmic_bar; + int baroff = 0; + int iproc = 0; + int plx_dev = 0; + int eth_dev = 0; + int cpu_dev = 0; + int update_devid = 0; + int paxb_core = 0; + int add_dev = 0, rescan = 0, rescan_idx = -1; + shbde_hal_t shared_bde, *shbde = &shared_bde; + + if (debug >= 4) {gprintk("probing: vendor_id=0x%x, device_id=0x%x\n", dev->vendor, dev->device);} + if (nodevices == 1) { + return 0; + } + + /* Initialize Linux hardware abstraction for shared BDE functions */ + linux_shbde_hal_init(shbde, _shbde_log_func); + + /* + * If an AXI-based switch device has been found already, then it means + * that the AXI bus has been probed, and that we should ignore devices + * found on PCI bus zero. + */ + +#if defined(IPROC_CMICD) + if ((dev->bus) && (dev->bus->number == 0)) { + int i; + uint32 mask = BDE_SWITCH_DEV_TYPE | BDE_AXI_DEV_TYPE; + + for (i = 0; i < _ndevices; i++) { + ctrl = _devices + i; + + if ((ctrl->dev_type & mask) == mask) { + return 0; + } + } + } +#endif /* IPROC_CMICD */ + + /* + * Note that a few supported devices have a non-Broadcom PCI vendor ID, + * but since none of their associated PCI device IDs collide with the + * Broadcom device IDs, the probe code below only checks the device ID. + */ + + switch (dev->device) { + case PCI_DEVICE_ID_PLX_9056: +#ifdef DNX_TEST_BOARD + break; /* a PCIe bridge to a non PCIe device should be treated as the device */ +#endif /* DNX_TEST_BOARD */ + case PCI_DEVICE_ID_PLX_9656: + plx_dev = 1; + break; + case BCM53000PCIE_DEVICE_ID: + cpu_dev = 1; + break; + /* + * The device ID for 56500, 56100 and 56300 family of devices may + * be incorrect just after a PCI HW reset. It needs to be read + * again after stabilization. + */ + case BCM56102_DEVICE_ID: + case BCM56504_DEVICE_ID: + case BCM56304_DEVICE_ID: + case BCM56314_DEVICE_ID: + case BCM56112_DEVICE_ID: + update_devid = 1; + break; + default: + break; + } + + /* Check if the device is ever probed. */ + rescan_idx = _device_rescan_validate(dev); + if (rescan_idx != -1) { + rescan = 1; + } + + ctrl = NULL; + if (plx_dev) { +#if defined(BCM_PLX9656_LOCAL_BUS) + /* PLX chip itself won't be part of _devices[]. */ + baroff = _plx_las_bar_get(dev); + if (baroff == -1) { + gprintk("No Local Address Space enabled in PLX\n"); + return 0; + } + ctrl = &plx_ctrl; + num_plx++; +#endif + } else if (eth_dev) { + if (_ether_ndevices >= LINUX_BDE_MAX_ETHER_DEVICES) { + return 0;; + } + ctrl = _devices + _ndevices; + ctrl->dev_type |= BDE_ETHER_DEV_TYPE; + ctrl->iLine = dev->irq; + add_dev = 1; + if (debug >= 1) + gprintk("Found PCI device %04x:%04x as Ethernet device\n", + dev->vendor, dev->device); + } else if (cpu_dev) { + if (_cpu_ndevices >= LINUX_BDE_MAX_CPU_DEVICES) { + return 0;; + } + ctrl = _devices + _ndevices; + ctrl->dev_type |= BDE_CPU_DEV_TYPE; + add_dev = 1; + if (debug >= 1) + gprintk("Found PCI device %04x:%04x as CPU device\n", + dev->vendor, dev->device); + } else { + if (PCI_FUNC(dev->devfn) > 0) { + return 0; + } + if (_switch_ndevices >= LINUX_BDE_MAX_SWITCH_DEVICES) { + return 0; + } + + if (rescan) { + if (debug >= 1) { + gprintk("PCI device %04x:%04x is re-probed \n", + dev->vendor, dev->device); + } + ctrl = _devices + rescan_idx; + ctrl->dev_state = BDE_DEV_STATE_CHANGED; + } else { + ctrl = _devices + _ndevices; + ctrl->dev_type |= BDE_SWITCH_DEV_TYPE; + ctrl->domain_no = pci_domain_nr(dev->bus); + ctrl->bus_no = dev->bus->number; + ctrl->dev_state = BDE_DEV_STATE_NORMAL; + add_dev = 1; + } + + /* Save shared BDE HAL in device structure */ + MEMCPY(&ctrl->shbde, shbde, sizeof(ctrl->shbde)); + + if (update_devid) { + /* Re-read the device ID */ + pci_read_config_word(dev, + PCI_DEVICE_ID, + &ctrl->bde_dev.device); + dev->device = ctrl->bde_dev.device; + } + + if (debug >= 4) {gprintk("Enabling PCI device : vendor_id=0x%x, device_id=0x%x\n", dev->vendor, dev->device);} + if (pci_enable_device(dev)) { + gprintk("Cannot enable PCI device : vendor_id = %x, device_id = %x\n", + dev->vendor, dev->device); + } + + /* FIXME: "workarounds" previously called "total h_acks" */ + /* + * These are workarounds to get around some existing + * kernel problems :( + */ + + /* + * While probing we determine the overall limits for the PCI + * memory windows across all devices. These limits are used + * later on by the PCI-PCI bridge code. + */ + if (pci_resource_start(dev, baroff) < _pci_mem_start) { + _pci_mem_start = pci_resource_start(dev, baroff); + } + if (pci_resource_end(dev, baroff) > _pci_mem_end) { + _pci_mem_end = pci_resource_end(dev, baroff); + } + +#ifdef CONFIG_SANDPOINT + /* + * Something wrong with the PCI subsystem in the mousse kernel. + * The device is programmed correctly, but the irq in the pci + * structure is hosed. This checks for the hosed-ness and fixes it. + */ + if (dev->irq > 100) { + dev->irq = 2; + gprintk("irq problem: setting irq = %d\n", dev->irq); + } +#endif + +#ifdef CONFIG_BMW + /* + * PCI subsystem does not always program the system correctly. + */ + if (dev->irq < 16 && dev->irq != 2) { + dev->irq = 2; + gprintk("irq problem: setting irq = %d\n", dev->irq); + } +#endif + +#ifdef CONFIG_IDT_79EB334 + /* + * IDT kernel is not currently mapping interrupts correctly + * Hardwired to core mips interrupt, irq 3 for kernel 2.4.18 + */ + if (dev->irq != 3) { + dev->irq = 3; + gprintk("irq problem: setting irq = %d\n", dev->irq); + } +#endif + +#ifdef CONFIG_BCM94702_CPCI + /* + * Hardwired to core mips interrupt irq 6 on MBZ + */ + if (dev->irq != 6) { + dev->irq = 6; + gprintk("irq problem: setting irq = %d\n", dev->irq); + } +#endif + + if ((PCI_FIND_DEV(BCM4704_VENDOR_ID, BCM4704_DEVICE_ID, NULL)) != NULL) { + /* + * Decrease the PCI bus priority for the CPU for better overall + * system performance. This change significantly reduces the + * number of PCI retries from other devices on the PCI bus. + */ + void * _mc_vbase = IOREMAP(BCM4704_MEMC_BASE, 0x1000); + int priorinv = 0x80; + static int done = 0; + if (!done) { + done = 1; + writel(priorinv, _mc_vbase + BCM4704_MEMC_PRIORINV); + if (debug >= 1) + gprintk("set BCM4704 PriorInvTim register to 0x%x\n", priorinv); + iounmap(_mc_vbase); + } + } + + if ((PCI_FIND_DEV(SIBYTE_PCI_VENDOR_ID, SIBYTE_PCI_DEVICE_ID, NULL)) != NULL) { + /* + * The BCM91125CPCI CPU boards with a PCI-PCI bridge use the same + * interrupt line for all switch ships behind the bridge. + */ + if (PCI_FIND_DEV(DC21150_VENDOR_ID, DC21150_DEVICE_ID, NULL) || + PCI_FIND_DEV(HINT_HB4_VENDOR_ID, HINT_HB4_DEVICE_ID, NULL) || + PCI_FIND_DEV(PI7C8150_VENDOR_ID, PI7C8150_DEVICE_ID, NULL)) { + /* + * By default we try to guess the correct IRQ based on the design. + * For now we only look at the bridge vendor, but it may be necessary + * to look at the switch chip configuration as well. + */ + if (forceirq == -1) { + if ((PCI_FIND_DEV(HINT_HB4_VENDOR_ID, HINT_HB4_DEVICE_ID, NULL)) || + ((dev->device == BCM5674_DEVICE_ID) && + (PCI_FIND_DEV(PI7C8150_VENDOR_ID, PI7C8150_DEVICE_ID, NULL)))) { + forceirq = 58; + } else { + forceirq = 56; + } + } + } + } + + if (((PCI_FIND_DEV(BCM58525_PCI_VENDOR_ID, BCM58525_PCI_DEVICE_ID, NULL)) != NULL) || + ((PCI_FIND_DEV(BCM58525_PCI_VENDOR_ID, BCM58522_PCI_DEVICE_ID, NULL)) != NULL) || + ((PCI_FIND_DEV(BCM58712_PCI_VENDOR_ID, BCM58712_PCI_DEVICE_ID, NULL)) != NULL) ) { + /* BCM58525/BCM58712 CPU boards support 128 Max payload size */ + if (maxpayload && maxpayload != 128) { + maxpayload = 128; + if (debug >= 1) gprintk("force max payload size to 128\n"); + } + } + + if (forceirq > 0 && dev->irq != (uint32) forceirq) { + if (forceirqubm & (1U << (_ndevices - 1))) { + dev->irq = forceirq; + if (debug >= 1) gprintk("force irq to %d\n", forceirq); + } + } else if (debug >= 1) gprintk("found irq %d\n", dev->irq); + + ctrl->iLine = dev->irq; + if (unlikely(debug > 1)) + gprintk("%s:irq = %d\n",__func__, ctrl->iLine); + + if (shbde_pci_is_pcie(shbde, dev)) { + /* Set PCIe max payload */ + shbde_pci_max_payload_set(shbde, dev, maxpayload); + } else { + /* Set PCI retry to infinite on non-PCIe switch device */ + pci_write_config_word(dev, 0x40, 0x0080); + if (debug >= 1) gprintk("set DMA retry to infinite on switch device\n"); + } + } + +#if defined(BCM_DFE_SUPPORT) + switch (dev->device) { + case BCM88770_DEVICE_ID: + case BCM88773_DEVICE_ID: + case BCM88774_DEVICE_ID: + case BCM88775_DEVICE_ID: + case BCM88776_DEVICE_ID: + case BCM88777_DEVICE_ID: + case BCM88950_DEVICE_ID: + case BCM88953_DEVICE_ID: + case BCM88954_DEVICE_ID: + case BCM88955_DEVICE_ID: + case BCM88956_DEVICE_ID: + case BCM88772_DEVICE_ID: + case BCM88952_DEVICE_ID: + + /* + * For DMA transactions - set Max_Payload_Size and + * Max_Read_Request_Size to 128 bytes. + */ + pci_write_config_byte(dev, 0xb5, 0x0c); + pci_write_config_byte(dev, 0xb4, 0x0); + break; + default: + break; + } +#endif /* BCM_DFE_SUPPORT */ + + /* Prevent compiler warning */ + if (ctrl == NULL) { + return 0; + } + + ctrl->be_pio = 0; + ctrl->dev_type |= BDE_PCI_DEV_TYPE; + ctrl->pci_device = dev; + pci_set_drvdata(dev, ctrl); + + /* + * Sample setting of unique ID, used the PCIe address of the device: + * domain, bus, slot, function in hex digits: DDDDBBSS (SS includes the slot/device and function. + * Tested with old kernels from 2.6 . + * Do not use the PCI_DEVID macro which old kernel versions don't have. */ + ctrl->bde_dev.dev_unique_id = dev->bus ? + (((uint32)pci_domain_nr(dev->bus)) << 16) ^ (((uint32)dev->bus->number) << 8) ^ dev->devfn : + dev->devfn; + + /* Check for iProc device */ + if (shbde_pci_is_iproc(shbde, dev, &cmic_bar)) { + iproc = 1; + if (cmic_bar >= 0) { + baroff = cmic_bar; + } + } +#ifdef DNX_TEST_BOARD + else if (dev->device == PLX9056_DEVICE_ID && baroff == 0) { + baroff = 2; + ctrl->dev_type |= BDE_NO_IPROC/* | BDE_BYTE_SWAP*/; + } +#endif /* DNX_TEST_BOARD */ + + /* Get the device revision */ + pci_read_config_byte(dev, PCI_REVISION_ID, &ctrl->bde_dev.rev); + + /* Map in the device */ + ctrl->bde_dev.device = dev->device; + paddr = pci_resource_start(dev, baroff); + + switch (dev->device) { +#if defined(BCM_PETRA_SUPPORT) && defined(__DUNE_LINUX_BCM_CPU_PCIE__) + case GEDI_DEVICE_ID: + case PCP_PCI_DEVICE_ID: + bar_len = 0x1000000; + break; +#endif + default: + bar_len = pci_resource_len(dev, baroff); + break; + } + + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(paddr, bar_len); + ctrl->iowin[0].addr = paddr; + ctrl->iowin[0].size = bar_len; + + if (debug >= 3) { + gprintk("BAR %d: kernel addr:0x%lx phys addr:0x%lx length:%lx\n", + baroff, (unsigned long)ctrl->bde_dev.base_address, (unsigned long)paddr, (unsigned long)bar_len); + } + + /* Map secondary address spaces */ + for (i = 1; i < BDE_NUM_IOWIN_MAX; i++) { + ctrl->iowin[i].addr = 0; + ctrl->iowin[i].size = 0; + } + ctrl->bde_dev.base_address1 = 0; + + if (iproc +#ifdef DNX_TEST_BOARD + || (dev->device == PLX9056_DEVICE_ID && baroff == 2) +#endif /* DNX_TEST_BOARD */ + ) { + paddr = pci_resource_start(dev, 0); + bar_len = pci_resource_len(dev, 0); + ctrl->bde_dev.base_address1 = (sal_vaddr_t)IOREMAP(paddr, bar_len); + ctrl->iowin[1].addr = paddr; + ctrl->iowin[1].size = bar_len; + if (debug >= 3) { + gprintk("BAR 0: kernel addr:0x%lx phys addr:0x%lx length:%lx\n", + (unsigned long)ctrl->bde_dev.base_address1, (unsigned long)paddr, (unsigned long)bar_len); + } + } + + /* configure interrupt type */ + config_pci_intr_type(dev, ctrl, iproc); + + /* Configure iProc PCI-AXI bridge */ + if (iproc && ctrl->bde_dev.base_address1) { + void *iproc_regs; + shbde_iproc_config_t *icfg = &shbde->icfg; + + /* Mapped iProc regs in PCI BAR 0 */ + iproc_regs = (void *)ctrl->bde_dev.base_address1; + + /* iProc configuration parameters */ + (void)shbde_pci_iproc_version_get(shbde, dev, &icfg->iproc_ver, + &icfg->cmic_ver, &icfg->cmic_rev); + shbde_iproc_config_init(icfg, ctrl->bde_dev.device, ctrl->bde_dev.rev); + + if (debug >= 2) { + gprintk("iproc version = %x dma_hi_bits = %x\n", icfg->iproc_ver, icfg->dma_hi_bits); + } + icfg->use_msi = ctrl->use_msi; + + /* Call shared function */ + paxb_core = shbde_iproc_paxb_init(shbde, iproc_regs, icfg); + + /* Save PCI core information for CMIC */ + if (paxb_core == 1) { + ctrl->dev_type |= BDE_DEV_BUS_ALT; + } + + /* Save MSI enable state information */ + if (ctrl->use_msi) { + ctrl->dev_type |= BDE_DEV_BUS_MSI; + } + + /* iProc PCIe preemphasis */ + shbde_iproc_pcie_preemphasis_set(shbde, iproc_regs, icfg, dev); + } + + /* Save shared BDE HAL in device structure */ + MEMCPY(&ctrl->shbde, shbde, sizeof(ctrl->shbde)); + + + ctrl->isr = NULL; + ctrl->isr_data = NULL; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_MEMORY) || !(cmd & PCI_COMMAND_MASTER)) { + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_word(dev, PCI_COMMAND, cmd); + if (debug >= 1) gprintk("enable PCI resources 0x%x (PCI_COMMAND)\n", cmd); + } + + /* Check if we need 256 KB memory window (default is 64 KB) */ + bar_len = pci_resource_len(dev, baroff); + if (bar_len == 0x40000) { + ctrl->dev_type |= BDE_256K_REG_SPACE; + if (debug >= 1) gprintk("PCI resource len 256K\n"); + } else if (bar_len == 0x800000) { + ctrl->dev_type |= BDE_256K_REG_SPACE | BDE_8MB_REG_SPACE; + if (debug >= 1) gprintk("PCI resource len 8MB\n"); + } + + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT + ctrl->dma_dev = &dev->dev; +#endif + + if (debug >= 2) { + gprintk("_pci_probe: configured dev:0x%x rev:0x%x with base_addresses: 0x%lx 0x%lx\n", + (unsigned)ctrl->bde_dev.device, (unsigned)ctrl->bde_dev.rev, + (unsigned long)ctrl->bde_dev.base_address, (unsigned long)ctrl->bde_dev.base_address1); + } + + if (add_dev) { + _bde_add_device(); + } + /* Let's boogie */ + return 0; +} + +/* + * Function: _pci_remove + * + * Purpose: + * Detach driver from device. Called from pci_unregister_driver(). + * Parameters: + * dev - Linux PCI device structure + * Returns: + * 0 + */ +static void +_pci_remove(struct pci_dev* dev) +{ + bde_ctrl_t *ctrl; + + if (nodevices == 1) { + return; + } + +#if defined(BCM_DFE_SUPPORT) + if (dev->device == PCI_DEVICE_ID_PLX_9056) { + return; + } +#endif + + ctrl = (bde_ctrl_t *) pci_get_drvdata(dev); + + if (ctrl == NULL) { + /* Unused device */ + return; + } + ctrl->dev_state = BDE_DEV_STATE_REMOVED; + if (debug >= 1) { + gprintk("PCI device %04x:%04x is removed. \n", + dev->vendor, dev->device); + } + if (ctrl->bde_dev.base_address1) { + iounmap((void *)ctrl->bde_dev.base_address1); + } + if (ctrl->bde_dev.base_address) { + iounmap((void *)ctrl->bde_dev.base_address); + } + + /* Free our interrupt handler, if we have one */ + if (ctrl->isr || ctrl->isr2) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + if (ctrl->use_msi >= PCI_USE_INT_MSIX) { + int i; + for (i = 0; i < ctrl->msix_cnt; i++) + free_irq(ctrl->entries[i].vector, ctrl); + } + else +#endif + { + free_irq(ctrl->iLine, ctrl); + } + } +#ifdef CONFIG_PCI_MSI + _msi_disconnect(ctrl); +#endif + ctrl->isr = NULL; + ctrl->isr_data = NULL; + ctrl->isr2 = NULL; + ctrl->isr2_data = NULL; +} + +static struct pci_driver _device_driver = { + .name = LINUX_KERNEL_BDE_NAME, + .probe = _pci_probe, + .remove = _pci_remove, + .id_table = _id_table, + /* The rest are dynamic */ +}; + +static void +_spi_device_setup(void) { + bde_ctrl_t *ctrl; + ctrl = _devices + _ndevices; + ctrl->dev_type |= BDE_SWITCH_DEV_TYPE; + ctrl->iLine = 0xa3; + ctrl->be_pio = 0; + ctrl->dev_type |= BDE_SPI_DEV_TYPE; + ctrl->bde_dev.device = spi_devid; + ctrl->bde_dev.rev = spi_revid; + if (debug >= 1) { + gprintk("SPI Slave Mode: force ctrl->bde_dev.device=0x%x\n",ctrl->bde_dev.device); + gprintk("SPI Slave Mode: force ctrl->bde_dev.rev=0x%x\n",ctrl->bde_dev.rev); + gprintk("SPI Slave Mode: force ctrl->dev_type=0x%x\n",ctrl->dev_type); + } + _bde_add_device(); +} +#endif /* BCM_ICS */ + + + + +#if defined(BCM_METROCORE_LOCAL_BUS) +static bde_ctrl_t* +map_local_bus(uint64_t addr, uint32_t size) +{ + bde_ctrl_t *ctrl; + + ctrl = _devices + _ndevices; + + /* + * For now: use EB type as `local bus' + * (memory mapped, no DMA, no interrupts) + * metrocore local bus supports interrupts, but we don't use them. + */ + ctrl->dev_type |= BDE_EB_DEV_TYPE | BDE_SWITCH_DEV_TYPE + | (size > 64 * 1024 ? BDE_128K_REG_SPACE : 0); + ctrl->pci_device = NULL; /* No PCI bus */ + + /* Map in the device */ + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(addr, size); + ctrl->iowin[0].addr = addr; + ctrl->iowin[0].size = size; + + _bde_add_device(); + return(ctrl); +} + +#define BME_REVISION_OFFSET (0x0) + +#endif + +#ifdef BCM_PLX9656_LOCAL_BUS + +#if 1 +#define DEV_REG_BASE_OFFSET PL0_OFFSET /* Polaris register base */ +#define DEV_REG_DEVID 0 /* Device ID is first register */ +#endif + +/* + * The difference at map_local_bus2: + * + * The PLX9656 PCI-to-LOCAL bridge chip already has been iomapped the + * whole address space. So the devices off local bus don't need to be + * mapped again. They only need to claim their own sub-space. + */ +static bde_ctrl_t * +map_local_bus2(bde_ctrl_t *plx_ctrl, uint32_t dev_base, uint32_t size) +{ + uint32_t dev_rev_id; + uint8_t *addr; + bde_ctrl_t *ctrl; + + ctrl = _devices + _ndevices; + + /* + * For now: use EB type as `local bus' + * (memory mapped, no DMA, no interrupts) + * metrocore local bus supports interrupts, but we don't use them. + */ + ctrl->dev_type |= BDE_EB_DEV_TYPE | BDE_SWITCH_DEV_TYPE; + ctrl->dev_type |= BDE_320K_REG_SPACE; /* Polaris 18 bits address + FPGA */ + ctrl->pci_device = NULL; /* No PCI bus */ + + /* Map in the device */ + ctrl->bde_dev.base_address = plx_ctrl->bde_dev.base_address + dev_base; + ctrl->iowin[0].addr = plx_ctrl->iowin[0].addr + (resource_size_t)dev_base; + ctrl->iowin[0].size = size; + +#if 1 + addr = (uint8_t *)ctrl->bde_dev.base_address + PL0_REVISION_REG; +#endif + dev_rev_id = readl(addr); + ctrl->bde_dev.device = dev_rev_id >> 16; + ctrl->bde_dev.rev = (dev_rev_id & 0xFF); + + + _bde_add_device(); + + switch (ctrl->bde_dev.device) { + default: + return 0; + } + return(ctrl); +} + +static int +probe_plx_local_bus(void) +{ + bde_ctrl_t *ctrl; + uint32_t val; + uint8_t *addr; + char addr_hi_str[16]; + + if (num_plx > 1) { + printk(KERN_ERR "There's more than one PLX 9656/9056 chip\n"); + return -1; + } + addr_hi_str[0] = 0; +#ifdef PHYS_ADDR_IS_64BIT + sprintf(addr_hi_str, "%08x", (uint32_t)(plx_ctrl.iowin[0].addr >> 32)); +#endif + printk(KERN_ERR "Found PLX %04x:%04x vir: 0x%08x phy: 0x%s%08x\n", + plx_ctrl.bde_dev.device, plx_ctrl.bde_dev.rev, + plx_ctrl.bde_dev.base_address, addr_hi_str, + (uint32_t)(plx_ctrl.iowin[0].addr)); + + addr = (uint8_t *)plx_ctrl.bde_dev.base_address + CPLD_OFFSET + CPLD_REVISION_REG; + val = readl(addr); + printk(KERN_ERR "plx: CPLD revision %d\n", val & CPLD_REVISION_MASK); +#if 000 + addr = (uint8_t *)plx_ctrl.bde_dev.base_address + CPLD_OFFSET + CPLD_RESET_REG; + writel(CPLD_RESET_NONE, addr); +#endif +#if 1 + ctrl = map_local_bus2(&plx_ctrl, PL0_OFFSET, PL0_SIZE); +#endif + if (ctrl == 0) + return -1; + + /* Uses PLX IRQ for Polaris LC */ + ctrl->iLine = 48; + ctrl->isr = NULL; + ctrl->isr_data = NULL; + + return 0; +} + +#endif /* BCM_PLX9656_LOCAL_BUS */ + + + + +/* + * Generic module functions + */ + +/* + * Function: _init + * + * Purpose: + * Module initialization. + * Attaches to kernel BDE. + * Parameters: + * None + * Returns: + * 0 on success, < 0 on error. + */ +static int +_init(void) +{ + unsigned i; +#ifdef IPROC_CMICD + /* + * Adjust the PCI driver name to prevent our device file from + * getting removed when the module is unloaded. + */ + _device_driver.name = LINUX_KERNEL_BDE_NAME ".iproc"; +#ifdef CONFIG_OF + if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) { + iproc_platform_driver_register(&iproc_cmicd_driver); + } else +#endif + if (iproc_has_cmicd()) { + iproc_cmicd_get_memregion(&iproc_cmicd_resources[IPROC_CMICD_RES_MEM]); + iproc_platform_driver_register(&iproc_cmicd_driver); +#ifdef CONFIG_OF + if (!of_find_compatible_node(NULL, NULL, IPROC_CMICD_COMPATIBLE)) +#endif + { + /* Register platform device if no device node in dtb */ + iproc_platform_device_register(&iproc_cmicd_pdev); + } + } +#endif /* IPROC_CMICD */ + +#ifdef BCM_ICS + _ics_bde_create(); +#else /* PCI */ + + /* Configure MSI interrupt support */ + use_msi = usemsi; + +#ifdef CONFIG_PCI_MSI + if (use_msi == PCI_USE_INT_NONE) { + /* Compilation flag determines default value */ +#ifdef BDE_LINUX_USE_MSIX_INTERRUPT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + use_msi = PCI_USE_INT_MSIX; +#else + use_msi = PCI_USE_INT_MSI; +#endif +#elif defined(BDE_LINUX_USE_MSI_INTERRUPT) + use_msi = PCI_USE_INT_MSI; +#else + use_msi = PCI_USE_INT_INTX; +#endif + } +#else + if (use_msi > PCI_USE_INT_INTX) { + /* Warn if invalid configuration */ + gprintk("MSI interrupts not supported by kernel\n"); + } + use_msi = PCI_USE_INT_INTX; +#endif /* CONFIG_PCI_MSI */ + + if (unlikely(debug >= 1)) + gprintk("%s(%d):use_msi = %d\n", __func__, __LINE__, use_msi); + if (spi_devid) { + _spi_device_setup(); + } else { + if (pci_register_driver(&_device_driver) < 0) { + return -ENODEV; + } + } + + /* Note: PCI-PCI bridge uses results from pci_register_driver */ + p2p_bridge(); + +#ifdef BCM_METROCORE_LOCAL_BUS + if (probe_metrocore_local_bus()) { + return -1; + } +#endif +#ifdef BCM_PLX9656_LOCAL_BUS + if (num_plx > 0) { + probe_plx_local_bus(); + } +#endif +#endif /* BCM_ICS */ + + +#ifdef BCM_SAND_SUPPORT + sand_device_create(); +#endif + + /* + * Probe for EB Bus devices. + */ + if (eb_bus) { + char *tok; + uint irq = -1, eb_rd16bit=0, eb_wr16bit =0; + unsigned int eb_ba = 0x0; + + gprintk("EB bus info: %s\n", eb_bus); + tok = strtok(eb_bus,","); + while (tok) { + _parse_eb_args(tok, "BA=%x IRQ=%d RD16=%d WR16=%d", + &eb_ba, &irq, &eb_rd16bit, &eb_wr16bit); + _eb_device_create(eb_ba, irq, eb_rd16bit, eb_wr16bit); + tok = strtok(NULL,","); + } + } + + for (i = 0; i < LINUX_BDE_MAX_DEVICES; ++i) { + _devices[i].inst_id = BDE_DEV_INST_ID_INVALID; + } + + return 0; +} + +/* + * Function: _cleanup + * + * Purpose: + * Module cleanup function. + * Parameters: + * None + * Returns: + * Always 0 + */ +static int +_cleanup(void) +{ + int i; + + _dma_cleanup(); + +#ifdef IPROC_CMICD +#ifdef CONFIG_OF + if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) { + iproc_platform_driver_unregister(&iproc_cmicd_driver); + } else +#endif + if (iproc_has_cmicd()) { +#ifdef CONFIG_OF + if (!of_find_compatible_node(NULL, NULL, IPROC_CMICD_COMPATIBLE)) +#endif + { + iproc_platform_device_unregister(&iproc_cmicd_pdev); + } + iproc_platform_driver_unregister(&iproc_cmicd_driver); + } +#endif + + for (i = 0; i < _ndevices; i++) { + bde_ctrl_t *ctrl = _devices + i; + + /* free allocated kernel space memory */ + if (ctrl->dev_type & BDE_SPI_DEV_TYPE) { + if (ctrl->spi_device) { + kfree(ctrl->spi_device); + } + } + } +#if defined(BCM_SAND_SUPPORT) && (defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__)) + if (cpu_address) { /* unmap CPU card MMIO */ + iounmap(cpu_address); + cpu_address = NULL; + } +#endif + +#ifdef BCM_ICS +#else + pci_unregister_driver(&_device_driver); +#endif /* BCM_ICS */ + return 0; +} + +/* + * Function: _pprint + * + * Purpose: + * Print proc filesystem information. + * Parameters: + * None + * Returns: + * Always 0 + */ +static int +_pprint(struct seq_file *m) +{ + int i = 0; + + pprintf(m, "Broadcom Device Enumerator (%s)\n", LINUX_KERNEL_BDE_NAME); + + pprintf(m, "Module parameters:\n"); + pprintf(m, "\tmaxpayload=%d\n", maxpayload); + pprintf(m, "\tusemsi=%d\n", usemsi); + + _dma_pprint(m); + + if (_ndevices == 0) { + pprintf(m, "No devices found\n"); + } else { + pprintf(m, "Devices:\n"); + } + for (i = 0; i < _ndevices; i++) { + bde_ctrl_t *ctrl = _devices + i; + + if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) { + pprintf(m, "\t%d (swi) : ", i); + } else if (ctrl->dev_type & BDE_ETHER_DEV_TYPE) { + pprintf(m, "\t%d (eth) : ", i); + } else if (ctrl->dev_type & BDE_CPU_DEV_TYPE) { + pprintf(m, "\t%d (cpu) : ", i); + } else { + pprintf(m, "\t%d (?) : ", i); + } + + if (ctrl->dev_state == BDE_DEV_STATE_REMOVED) { + pprintf(m, "PCI device 0x%x:0x%x:%d REMOVED\n", + ctrl->pci_device->vendor, + ctrl->pci_device->device, + ctrl->bde_dev.rev); + continue; + } + if (ctrl->dev_type & BDE_PCI_DEV_TYPE) { + pprintf(m, "PCI device %02x:%02x.%x 0x%x:0x%x:%d:0x%.8lx:0x%.8lx:%d%s\n", + (unsigned int)ctrl->pci_device->bus->number, + PCI_SLOT(ctrl->pci_device->devfn), + PCI_FUNC(ctrl->pci_device->devfn), + ctrl->pci_device->vendor, + ctrl->pci_device->device, + ctrl->bde_dev.rev, + (unsigned long)pci_resource_start(ctrl->pci_device, 0), + (unsigned long)pci_resource_start(ctrl->pci_device, 2), + ctrl->pci_device->irq, + ctrl->use_msi ? " (MSI)" : ""); + } else if (ctrl->dev_type & BDE_SPI_DEV_TYPE) { + pprintf(m, "SPI Device %d:%x:%x:0x%x:0x%x:%d\n", + ctrl->spi_device->cid, + ctrl->spi_device->part, + ctrl->spi_device->rev, + ctrl->spi_device->phyid_high, + ctrl->spi_device->phyid_low, + ctrl->bde_dev.rev); + } else if (ctrl->dev_type & BDE_ICS_DEV_TYPE) { + pprintf(m, "ICS Device 0x%x:0x%x\n", + ctrl->bde_dev.device, + ctrl->bde_dev.rev); + } else if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + pprintf(m, "AXI Device 0x%x:0x%x:0x%.8lx:%d\n", + ctrl->bde_dev.device, + ctrl->bde_dev.rev, + (unsigned long)ctrl->iowin[0].addr, + ctrl->iLine); + } else if (ctrl->dev_type & BDE_EB_DEV_TYPE) { + pprintf(m, "EB Bus Device 0x%x:0x%x\n", + ctrl->bde_dev.device, + ctrl->bde_dev.rev); + } + if (debug >= 1) { + pprintf(m, "\t\timask:imask2:fmask 0x%x:0x%x:0x%x\n", + ctrl->imask, + ctrl->imask2, + ctrl->fmask); + } + if (debug >= 1) { + if (ctrl->inst_id == BDE_DEV_INST_ID_INVALID) { + pprintf(m, "\t\tinst_id INVALID\n"); + } else { + pprintf(m, "\t\tinst_id %u%s\n", + ctrl->inst_id, + ctrl->inst_id < LINUX_BDE_MAX_DEVICES ? "":"(Illegal)"); + } + } + } + return 0; +} +/* + * Some kernels are configured to prevent mapping of kernel RAM memory + * into user space via the /dev/mem device. + * + * The function below provides a backdoor to map IO and DMA memory to + * user space via the BDE device file. + */ +static int +_bde_mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long paddr = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size = vma->vm_end - vma->vm_start; + int i, j, pio_range_valid = 0; + + for(i = 0; i < _ndevices; i++) { + bde_ctrl_t *ctrl = _devices + i; + if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) { + for (j = 0; j < BDE_NUM_IOWIN_MAX; j++) { + if (paddr >= (unsigned long)ctrl->iowin[j].addr && + (paddr + size) <= (unsigned long)(ctrl->iowin[j].addr + ctrl->iowin[j].size)) { + pio_range_valid = 1; + break; + } + if ((ctrl->dev_type & BDE_AXI_DEV_TYPE) && (paddr == ctrl->iowin[j].addr)) { + pio_range_valid = 1; + break; + } + } + } + } + + if (pio_range_valid) { + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + if (remap_pfn_range(vma, + vma->vm_start, + vma->vm_pgoff, + size, + vma->vm_page_prot)) { + gprintk("Failed to mmap phys range 0x%lx-0x%lx to 0x%lx-0x%lx\n", + paddr, paddr + size, vma->vm_start,vma->vm_end); + return -EAGAIN; + } + return 0; + } + + return _dma_mmap(filp, vma); +} + +/* Workaround for broken Busybox/PPC insmod */ +static char _modname[] = LINUX_KERNEL_BDE_NAME; + +static gmodule_t _gmodule = { + name: LINUX_KERNEL_BDE_NAME, + major: LINUX_KERNEL_BDE_MAJOR, + init: _init, + cleanup: _cleanup, + pprint: _pprint, + mmap: _bde_mmap, +}; + +gmodule_t * +gmodule_get(void) +{ + _gmodule.name = _modname; + return &_gmodule; +} + + +/* + * BDE Interface + */ + +static const char * +_name(void) +{ + return LINUX_KERNEL_BDE_NAME; +} + +static int +_num_devices(int type) +{ + switch (type) { + case BDE_ALL_DEVICES: + return _ndevices; + case BDE_SWITCH_DEVICES: + return _switch_ndevices; + case BDE_ETHER_DEVICES: + return _ether_ndevices; + case BDE_CPU_DEVICES: + return _cpu_ndevices; + } + + return 0; +} + +static const ibde_dev_t * +_get_dev(int d) +{ + if (!VALID_DEVICE(d)) { + gprintk("_get_dev: Invalid device index %d\n", d); + return NULL; + } + + return &_devices[d].bde_dev; +} + +static uint32 +_get_dev_type(int d) +{ + if (!VALID_DEVICE(d)) { + gprintk("_get_dev: Invalid device index %d\n", d); + return 0; + } + + return _devices[d].dev_type; +} + +static uint32 +_pci_conf_read(int d, uint32 addr) +{ +#ifdef BCM_ICS + return 0xFFFFFFFF; +#else + uint32 rc = 0; + + if (!VALID_DEVICE(d)) { + gprintk("_pci_conf_read: Invalid device index %d\n", d); + return 0xFFFFFFFF; + } + + if (!(_devices[d].dev_type & BDE_PCI_DEV_TYPE)) { + gprintk("_pci_conf_read: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return 0xFFFFFFFF; + } + + pci_read_config_dword(_devices[d].pci_device, addr, &rc); + return rc; +#endif /* BCM_ICS */ +} + +static int +_pci_conf_write(int d, uint32 addr, uint32 data) +{ +#ifdef BCM_ICS + return -1; +#else + if (!VALID_DEVICE(d)) { + gprintk("_pci_conf_write: Invalid device index %d\n", d); + return -1; + } + + if (!(_devices[d].dev_type & BDE_PCI_DEV_TYPE)) { + gprintk("_pci_conf_write: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return -1; + } + + pci_write_config_dword(_devices[d].pci_device, addr, data); + return 0; +#endif /* BCM_ICS */ +} + +/* Initialized when the bde is created */ +static linux_bde_bus_t _bus; + +static void +_pci_bus_features(int unit, int *be_pio, int *be_packet, int *be_other) +{ + if ((_devices[unit].bde_dev.device & 0xFF00) != 0x5600 && + (_devices[unit].bde_dev.device & 0xF000) != 0xc000 && + (_devices[unit].bde_dev.device & 0xF000) != 0xb000 && + (_devices[unit].bde_dev.device & 0xF000) != 0x8000 && + (_devices[unit].bde_dev.device & 0xFFF0) != 0x0230 && + (_devices[unit].bde_dev.device & 0xFFF0) != 0xa440) { + if (be_pio) *be_pio = 0; + if (be_packet) *be_packet = 0; + if (be_other) *be_other = 0; + } else { + if (be_pio) *be_pio = _bus.be_pio; + if (be_packet) *be_packet = _bus.be_packet; + if (be_other) *be_other = _bus.be_other; + } +#if defined(BCM_METROCORE_LOCAL_BUS) + if (_devices[unit].dev_type & BDE_EB_DEV_TYPE && be_pio) { + *be_pio = 1; + } +#endif + +} + +static uint32_t +_read(int d, uint32_t addr) +{ + unsigned long flags; + volatile uint16 msb, lsb; + uint32 sl_addr, data; + + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + return -1; + } + + if (_devices[d].dev_type & BDE_DEV_BUS_RD_16BIT) { + /* + * Adjust the address presented to Eb slave. Move A15:A0 to A16:A1. + */ + sl_addr = (addr & 0xffff0000) | ((addr & 0xffff) << 1); + /* Disable interrupts */ + spin_lock_irqsave(&bus_lock, flags); + + lsb = *((uint16 *)(_devices[d].bde_dev.base_address + sl_addr)); + msb = *((uint16 *)(_devices[d].bde_dev.base_address + sl_addr)); + spin_unlock_irqrestore(&bus_lock, flags); + + return (msb << 16) | lsb; + } else { + data = ((VOL uint32_t *)_devices[d].bde_dev.base_address)[addr / 4]; +#if defined(CMIC_SOFT_BYTE_SWAP) + data = CMIC_SWAP32(data); +#endif + return data; + } +} + +static int +_write(int d, uint32_t addr, uint32_t data) +{ + unsigned long flags; + uint32 sl_addr; + + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + return -1; + } + + if (_devices[d].dev_type & BDE_DEV_BUS_WR_16BIT) { + /* + * Adjust the address presented to Eb slave. Move A15:A0 to A16:A1. + */ + sl_addr = (addr & 0xffff0000) | ((addr & 0xffff) << 1); + + /* Disable interrupts */ + spin_lock_irqsave(&bus_lock, flags); + + *((VOL uint16 *)(_devices[d].bde_dev.base_address + sl_addr)) = + data & 0xffff; + *((VOL uint16 *)(_devices[d].bde_dev.base_address + sl_addr)) = + (data >> 16) & 0xffff; + spin_unlock_irqrestore(&bus_lock, flags); + } else { +#if defined(CMIC_SOFT_BYTE_SWAP) + data = CMIC_SWAP32(data); +#endif + ((VOL uint32_t *)_devices[d].bde_dev.base_address)[addr / 4] = data; +#ifdef KEYSTONE + /* Enforce PCIe transaction ordering. Commit the write transaction */ + __asm__ __volatile__("sync"); +#endif + } + return 0; + +} + +static _ISR_RET +_isr(_ISR_PARAMS(irq, dev_id, iregs)) +{ + bde_ctrl_t *ctrl = (bde_ctrl_t *) dev_id; + + if (ctrl && ctrl->isr) { + ctrl->isr(ctrl->isr_data); + } + if (ctrl && ctrl->isr2) { + ctrl->isr2(ctrl->isr2_data); + } + return IRQ_HANDLED; +} + +static int +_interrupt_connect(int d, + void (*isr)(void *), + void *isr_data) +{ + bde_ctrl_t *ctrl; + unsigned long irq_flags; + int isr2_dev; + int isr_active; + int ret = 0; + + isr2_dev = d & LKBDE_ISR2_DEV; + d &= ~LKBDE_ISR2_DEV; + + if (!VALID_DEVICE(d)) { + gprintk("_interrupt_connect: Invalid device index %d\n", d); + return -1; + } + if (debug >= 1) { + gprintk("_interrupt_connect d %d\n", d); + } + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("_interrupt_connect: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return -1; + } + + ctrl = _devices + d; + + isr_active = (ctrl->isr || ctrl->isr2) ? 1 : 0; + + if (unlikely(debug > 1)) + gprintk("%s:isr_active = %d\n", __func__, isr_active); + + if (isr2_dev) { + if (debug >= 1) { + gprintk("connect secondary isr\n"); + } + ctrl->isr2_data = isr_data; + ctrl->isr2 = isr; + if (isr_active) { + /* Main handler (_isr) already installed */ + return 0; + } + } else { + if (debug >= 1) { + gprintk("connect primary isr\n"); + } + ctrl->isr = isr; + ctrl->isr_data = isr_data; + if (isr_active) { + /* Main handler (_isr) already installed */ + return 0; + } + } + + if (ctrl->iLine != -1) { + irq_flags = IRQF_SHARED; +#ifdef CONFIG_PCI_MSI + if (ctrl->use_msi >= PCI_USE_INT_MSI) { + ret = _msi_connect(ctrl); + if(ret != 0) + goto msi_exit; + } +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + if (ctrl->use_msi == PCI_USE_INT_MSIX) { + int i; + for (i = 0; i < ctrl->msix_cnt; i++) { + if (unlikely(debug >= 1)) { + gprintk("%s(%d):device# = %d, irq = %d\n", + __func__, __LINE__, d, ctrl->entries[i].vector); + } + ret = request_irq(ctrl->entries[i].vector, (irq_handler_t)_isr, 0, + LINUX_KERNEL_BDE_NAME, ctrl); + if (ret < 0) + break; + } + if (ret < 0) { + while (i >= 0) + free_irq(ctrl->entries[i--].vector, ctrl); + + goto err_disable_msi; + } + } + else +#endif + { +#if defined(IPROC_CMICD) && defined(CONFIG_OF) + if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) { + int i, j; + for (i = 0; i < IHOST_CMICX_MAX_INTRS; i++) { + if (!iproc_cmicx_irqs[i]) { + continue; + } + if (unlikely(debug >= 1)) + gprintk("%s(%d):device# = %d, request_irq(%d)\n", + __func__, __LINE__, d, iproc_cmicx_irqs[i]); + ret = request_irq(iproc_cmicx_irqs[i], (irq_handler_t)_isr, + irq_flags, LINUX_KERNEL_BDE_NAME, ctrl); + if (ret < 0) { + gprintk("request_irq(%d) failed(%d)\n", iproc_cmicx_irqs[i], ret); + break; + } + } + if (ret < 0) { + for (j = 0; j < i; j++) { + if (!iproc_cmicx_irqs[j]) { + continue; + } + free_irq(iproc_cmicx_irqs[j], ctrl); + } + goto err_disable_msi; + } + } else +#endif + { + ret = request_irq(ctrl->iLine, _isr, irq_flags, + LINUX_KERNEL_BDE_NAME, ctrl); + if (ret < 0) + goto err_disable_msi; + + if (unlikely(debug >= 1)) + gprintk("%s(%d):device# = %d, irq_flags = %lu, irq = %d\n", + __func__, __LINE__, d, + irq_flags, ctrl->pci_device ? ctrl->pci_device->irq : ctrl->iLine); + } + } + } + return 0; + +err_disable_msi: +#ifdef CONFIG_PCI_MSI + _msi_disconnect(ctrl); + +msi_exit: +#endif + gprintk("could not request IRQ\n"); + ctrl->isr = NULL; + ctrl->isr_data = NULL; + ctrl->isr2 = NULL; + ctrl->isr2_data = NULL; + + return -1; +} + +static int +_interrupt_disconnect(int d) +{ + bde_ctrl_t *ctrl; + int isr2_dev; + int isr_active; + + isr2_dev = d & LKBDE_ISR2_DEV; + d &= ~LKBDE_ISR2_DEV; + + if (!VALID_DEVICE(d)) { + return -1; + } + + if (debug >= 1) { + gprintk("_interrupt_disconnect d %d\n", d); + } + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("_interrupt_disconnect: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return -1; + } + + ctrl = _devices + d; + + isr_active = (ctrl->isr || ctrl->isr2) ? 1 : 0; + + if (unlikely(debug > 1)) + gprintk("%s: isr_active = %d\n", __func__, isr_active); + + if (isr2_dev) { + if (debug >= 1) { + gprintk("disconnect secondary isr\n"); + } + ctrl->isr2 = NULL; + ctrl->isr2_data = NULL; + ctrl->fmask = 0; + if (ctrl->isr) { + /* Primary handler still active */ + SYNC_IRQ(ctrl->iLine); + return 0; + } + } else { + if (debug >= 1) { + gprintk("disconnect primary isr\n"); + } + ctrl->isr = NULL; + ctrl->isr_data = NULL; + if (ctrl->isr2) { + /* Secondary handler still active */ + SYNC_IRQ(ctrl->iLine); + return 0; + } + } + + if (isr_active) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,84)) + if (ctrl->use_msi >= PCI_USE_INT_MSIX) { + int i; + for (i = 0; i < ctrl->msix_cnt; i++) { + if (unlikely(debug > 1)) { + gprintk("%s(%d):device# = %d, irq = %d\n", + __func__, __LINE__, d, ctrl->entries[i].vector); + } + free_irq(ctrl->entries[i].vector, ctrl); + } + } + else +#endif +#if defined(IPROC_CMICD) && defined(CONFIG_OF) + if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) { + int i; + for (i = 0; i < IHOST_CMICX_MAX_INTRS; i++) { + if (!iproc_cmicx_irqs[i]) { + continue; + } + if (unlikely(debug > 1)) { + gprintk("%s(%d):device# = %d, free_irq(%d)\n", + __func__, __LINE__, d, iproc_cmicx_irqs[i]); + } + free_irq(iproc_cmicx_irqs[i], ctrl); + } + } else +#endif + { + free_irq(ctrl->iLine, ctrl); + } +#ifdef CONFIG_PCI_MSI + if (ctrl->use_msi >= PCI_USE_INT_MSI) { + _msi_disconnect(ctrl); + } +#endif + } + + return 0; +} + +static uint32_t +_iproc_ihost_read(int d, uint32_t addr) +{ + uint32_t *mapaddr; + uint32_t reg_val; + mapaddr = IOREMAP(addr, sizeof(uint32_t)); + if (mapaddr == NULL) { + return -1; + } + reg_val = readl(mapaddr); + iounmap(mapaddr); + return reg_val; +} + +static int +_iproc_ihost_write(int d, uint32_t addr, uint32_t data) +{ + uint32_t *mapaddr; + mapaddr = IOREMAP(addr, sizeof(uint32_t)); + if (mapaddr == NULL) { + return -1; + } + writel(data, mapaddr); + iounmap(mapaddr); + return 0; +} + +static uint32_t +_iproc_read(int d, uint32_t addr) +{ + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + return -1; + } + + if (_devices[d].dev_type & BDE_AXI_DEV_TYPE) { + if (IHOST_GICD_REG_ADDR_VALID(d, addr)) { + return readl(IHOST_GICD_REG_ADDR_REMAP(d, addr)); + } + return _iproc_ihost_read(d, addr); + } + + return shbde_iproc_pci_read(&_devices[d].shbde, + (void *)_devices[d].bde_dev.base_address1, + addr); +} + +static int +_iproc_write(int d, uint32_t addr, uint32_t data) +{ + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + return -1; + } + + if (_devices[d].dev_type & BDE_AXI_DEV_TYPE) { + if (IHOST_GICD_REG_ADDR_VALID(d, addr)) { + writel(data, IHOST_GICD_REG_ADDR_REMAP(d, addr)); + return 0; + } + return _iproc_ihost_write(d, addr, data); + } + + shbde_iproc_pci_write(&_devices[d].shbde, + (void *)_devices[d].bde_dev.base_address1, + addr, data); + + return 0; +} + +static int +_get_cmic_ver(int d , uint32_t *ver) +{ + + unsigned int cap_base; + uint32_t rval = 0; + + if (!VALID_DEVICE(d)) { + gprintk("%s: Invalid device index %d\n", __func__, d); + return -1; + } + + if (!(_devices[d].dev_type & BDE_PCI_DEV_TYPE)) { + gprintk("%s: Not PCI device %d, type %x\n", __func__, + d, _devices[d].dev_type); + return -1; + } + + /* Look for PCIe vendor-specific extended capability (VSEC) */ + cap_base = PCI_EXT_CAP_START; + while (cap_base) { + pci_read_config_dword(_devices[d].pci_device, cap_base, &rval); + if (rval == 0xffffffff) { + /* Assume PCI HW read error */ + gprintk("%s: PCI HW read error\n", __func__); + return -1; + } + + if (PCI_EXT_CAP_ID(rval) == PCI_EXT_CAP_ID_VNDR) { + break; + } + cap_base = PCI_EXT_CAP_NEXT(rval); + } + if (cap_base) { + /* + * VSEC layout: + * + * 0x00: PCI Express Extended Capability Header + * 0x04: Vendor-Specific Header + * 0x08: Vendor-Specific Register 1 + * 0x0c: Vendor-Specific Register 2 + * ... + * 0x24: Vendor-Specific Register 8 + */ + pci_read_config_dword(_devices[d].pci_device, cap_base + 8, &rval); + if (unlikely(debug > 1)) + gprintk("%s:Found VSEC = %u\n", __func__, rval); + + /* Determine if CMICX */ + rval = ((rval >> 12) & 0xf); + *ver = rval; + + return 0; + } else { + gprintk("%s:VSEC not found\n", __func__); + } + + return -1; +} + +#ifdef BCM_SAND_SUPPORT +int +lkbde_cpu_write(int d, uint32 addr, uint32 *buf) +{ +#if defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__) + *((uint32_t*)((uint8_t*)cpu_address + addr)) = *buf; +#endif + + return 0; +} + +int +lkbde_cpu_read(int d, uint32 addr, uint32 *buf) +{ +#if defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__) + *buf = *((uint32_t*)((uint8_t*)cpu_address + addr)); +#else + *buf = (uint32_t)(-1); +#endif + + return 0; +} + +int +lkbde_cpu_pci_register(int d) +{ + bde_ctrl_t* ctrl; + uint16 cmd = 0; + + if (!VALID_DEVICE(d)) { + return -1; + } + + ctrl = &_devices[d]; + + /* enable device */ + if (pci_enable_device(ctrl->pci_device)) { + gprintk("Cannot enable pci device : vendor_id = %x, device_id = %x\n", + ctrl->pci_device->vendor, ctrl->pci_device->device); + } + + /* Add PCI_COMMAND_MEMORY and PCI_COMMAND_MASTER */ + pci_read_config_word(ctrl->pci_device, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_MEMORY) || !(cmd & PCI_COMMAND_MASTER)) { + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_word(ctrl->pci_device, PCI_COMMAND, cmd); + } + + switch (ctrl->bde_dev.device) { + case GEDI_DEVICE_ID: + /* Fix bar 0 address */ /* FIXME: write full phy address */ + pci_write_config_byte(ctrl->pci_device, 0x13, 0x60); + + /* Fix Max payload size */ + pci_write_config_byte(ctrl->pci_device, 0x88, 0x2f); + pci_write_config_byte(ctrl->pci_device, 0x89, 0x10); + break; + case BCM88770_DEVICE_ID: + case BCM88773_DEVICE_ID: + case BCM88774_DEVICE_ID: + case BCM88775_DEVICE_ID: + case BCM88776_DEVICE_ID: + case BCM88777_DEVICE_ID: + case BCM88950_DEVICE_ID: + case BCM88953_DEVICE_ID: + case BCM88954_DEVICE_ID: + case BCM88955_DEVICE_ID: + case BCM88956_DEVICE_ID: + case BCM88772_DEVICE_ID: + case BCM88952_DEVICE_ID: + case ACP_PCI_DEVICE_ID: + case BCM88650_DEVICE_ID: + + case BCM88670_DEVICE_ID: + case BCM88671_DEVICE_ID: + case BCM88671M_DEVICE_ID: + case BCM88672_DEVICE_ID: + case BCM88673_DEVICE_ID: + case BCM88674_DEVICE_ID: + case BCM88675_DEVICE_ID: + case BCM88675M_DEVICE_ID: + case BCM88676_DEVICE_ID: + case BCM88676M_DEVICE_ID: + case BCM88677_DEVICE_ID: + case BCM88678_DEVICE_ID: + case BCM88679_DEVICE_ID: + + case BCM88370_DEVICE_ID: + case BCM88371_DEVICE_ID: + case BCM88371M_DEVICE_ID: + case BCM88375_DEVICE_ID: + case BCM88376_DEVICE_ID: + case BCM88376M_DEVICE_ID: + case BCM88377_DEVICE_ID: + case BCM88378_DEVICE_ID: + case BCM88379_DEVICE_ID: + case BCM88681_DEVICE_ID: + case BCM88682_DEVICE_ID: + case BCM88683_DEVICE_ID: + case BCM88684_DEVICE_ID: + case BCM88685_DEVICE_ID: + case BCM88687_DEVICE_ID: + case BCM88380_DEVICE_ID: + case BCM88381_DEVICE_ID: + case BCM88680_DEVICE_ID: + case BCM88470_DEVICE_ID: + case BCM88470P_DEVICE_ID: + case BCM88471_DEVICE_ID: + case BCM88473_DEVICE_ID: + case BCM88474_DEVICE_ID: + case BCM88474H_DEVICE_ID: + case BCM88476_DEVICE_ID: + case BCM88477_DEVICE_ID: + case BCM88270_DEVICE_ID: + case BCM88271_DEVICE_ID: + case BCM88272_DEVICE_ID: + case BCM88273_DEVICE_ID: + case BCM88274_DEVICE_ID: + case BCM88276_DEVICE_ID: + case BCM88278_DEVICE_ID: + case BCM8206_DEVICE_ID: + case BCM88350_DEVICE_ID: + case BCM88351_DEVICE_ID: + case BCM88450_DEVICE_ID: + case BCM88451_DEVICE_ID: + case BCM88550_DEVICE_ID: + case BCM88551_DEVICE_ID: + case BCM88552_DEVICE_ID: + case BCM88651_DEVICE_ID: + case BCM88654_DEVICE_ID: + case BCM88660_DEVICE_ID: + case BCM88360_DEVICE_ID: + case BCM88361_DEVICE_ID: + case BCM88363_DEVICE_ID: + case BCM88460_DEVICE_ID: + case BCM88461_DEVICE_ID: + case BCM88560_DEVICE_ID: + case BCM88561_DEVICE_ID: + case BCM88562_DEVICE_ID: + case BCM88661_DEVICE_ID: + case BCM88664_DEVICE_ID: + /* Fix bar 0 address */ /* FIXME: write full phy address */ + pci_write_config_byte(ctrl->pci_device, 0x12, 0x10); + pci_write_config_byte(ctrl->pci_device, 0x13, 0x60); + + /* + * For DMA transactions - set Max_Payload_Size and + * Max_Read_Request_Size to 128 bytes. + */ + pci_write_config_byte(ctrl->pci_device, 0xb5, 0x0c); + pci_write_config_byte(ctrl->pci_device, 0xb4, 0x0); + break; + default: + break; + } + + /* configure iproc >=14 devices by device family */ +#if defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) + switch (ctrl->bde_dev.device & DNXC_DEVID_FAMILY_MASK) { +#ifdef BCM_DNX_SUPPORT + case JERICHO2_DEVICE_ID: + case J2C_DEVICE_ID: + case J2C_2ND_DEVICE_ID: + case Q2A_DEVICE_ID: + case Q2U_DEVICE_ID: + case J2P_DEVICE_ID: +#endif +#ifdef BCM_DNXF_SUPPORT + case BCM88790_DEVICE_ID: +#endif + /* + * For DMA transactions - set Max_Payload_Size and + * Max_Read_Request_Size to 128 bytes. + */ + pci_write_config_byte(ctrl->pci_device, 0xb5, 0x0c); + pci_write_config_byte(ctrl->pci_device, 0xb4, 0x0); + break; + } +#endif /* defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) */ + + /* Redo ioremap */ + if (ctrl->bde_dev.base_address) { + iounmap((void *)ctrl->bde_dev.base_address); + } + ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(ctrl->iowin[0].addr, 0x1000000); + + if (debug >= 1) { + gprintk("%s, %s(): info:\n", __FILE__, __FUNCTION__); + gprintk("_ndevices=%d, _switch_ndevices=%d\n", + _ndevices, _switch_ndevices); + gprintk("ctrl->dev_type=0x%x, ctrl->phys_address=0x%lx\n", + ctrl->dev_type, (unsigned long)ctrl->iowin[0].addr); + gprintk("ctrl->bde_dev.device=0x%x, ctrl->bde_dev.rev=0x%x, " + "ctrl->bde_dev.base_address=0x%lx\n", + ctrl->bde_dev.device, ctrl->bde_dev.rev, + (unsigned long)ctrl->bde_dev.base_address); + } + + return 0; +} + +/* + * Export Low level access function - currently for PCP DMA Kernel module. + */ +int +lkbde_mem_write(int d, uint32 addr, uint32 *buf) +{ + bde_ctrl_t* ctrl; + void *full_addr; + + if (!VALID_DEVICE(d)) return -1; + ctrl = &_devices[d]; + + full_addr = (void *)ctrl->bde_dev.base_address + addr; + *((uint32_t*)full_addr) = *buf; + return 0; +} +LKM_EXPORT_SYM(lkbde_mem_write); + +int +lkbde_mem_read(int d, uint32 addr, uint32 *buf) +{ + bde_ctrl_t* ctrl; + void *full_addr; + + if (!VALID_DEVICE(d)) return -1; + ctrl = &_devices[d]; + + full_addr = (void *)ctrl->bde_dev.base_address + addr; + *buf = *((uint32_t*)full_addr); + return 0; +} +LKM_EXPORT_SYM(lkbde_mem_read); +#endif /* BCM_SAND_SUPPORT */ + +static ibde_t _ibde = { + name: _name, + num_devices: _num_devices, + get_dev: _get_dev, + get_dev_type: _get_dev_type, + pci_conf_read: _pci_conf_read, + pci_conf_write: _pci_conf_write, + pci_bus_features: _pci_bus_features, + read: _read, + write: _write, + salloc: _salloc, + sfree: _sfree, + sinval: _sinval, + sflush: _sflush, + interrupt_connect: _interrupt_connect, + interrupt_disconnect: _interrupt_disconnect, + l2p: _l2p, + p2l: _p2l, + + NULL, + NULL, + iproc_read: _iproc_read, + iproc_write: _iproc_write, + get_cmic_ver: _get_cmic_ver, +}; + +/* + * Function: linux_bde_create + * + * Purpose: + * Creator function for this BDE interface. + * Parameters: + * bus - pointer to the bus features structure you want this + * bde to export. Depends on the system. + * ibde - pointer to a location to recieve the bde interface pointer. + * Returns: + * 0 on success + * -1 on failure. + * Notes: + * This is the main BDE create function for this interface. + * Used by the external system initialization code. + */ +int +linux_bde_create(linux_bde_bus_t *bus, ibde_t **ibde) +{ + + memset(&_bus, 0, sizeof(_bus)); + + if (bus) { + _bus = *bus; + } +#ifdef NONCOHERENT_DMA_MEMORY +#ifdef REMAP_DMA_NONCACHED + /* + * If we have a non-cached DMA memory pool + * there is no need to flush and invalidate. + */ + if (_dma_pool_allocated()) { + _ibde.sinval = NULL; + _ibde.sflush = NULL; + } +#endif +#else + _ibde.sinval = NULL; + _ibde.sflush = NULL; +#endif + *ibde = &_ibde; + return 0; +} + +/* + * Function: linux_bde_destroy + * + * Purpose: + * destroy this bde + * Parameters: + * BDE interface pointer + * Returns: + * 0 on success, < 0 on error. + */ +int +linux_bde_destroy(ibde_t *ibde) +{ + /* nothing */ + return 0; +} + +/* + * Backdoors provided by the kernel bde + */ + +uint32_t +lkbde_get_dev_phys(int d) +{ + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("lkbde_get_dev_phys: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return 0; + } + return _devices[d].iowin[0].addr; +} + +uint32_t +lkbde_get_dev_phys_hi(int d) +{ + if (!VALID_DEVICE(d)) { + return -1; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("lkbde_get_dev_phys: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return 0; + } +#ifdef PHYS_ADDR_IS_64BIT + return (uint32_t)(_devices[d].iowin[0].addr >> 32); +#else + return 0; +#endif +} + +void * +lkbde_get_dev_virt(int d) +{ + if (!VALID_DEVICE(d)) { + return NULL; + } + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("lkbde_get_dev_virt: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return 0; + } + + if (_devices[d].alt_base_addr) { + return (void *)_devices[d].alt_base_addr; + } + + return (void *)_devices[d].bde_dev.base_address; +} + +int +lkbde_get_dev_resource(int d, int rsrc, uint32_t *phys_lo, + uint32_t *phys_hi, uint32_t *size) +{ + if (!VALID_DEVICE(d)) { + return -1; + } + + *size = 0; + *phys_lo = 0; + *phys_hi = 0; + + if (!(BDE_DEV_MEM_MAPPED(_devices[d].dev_type))) { + gprintk("lkbde_get_dev_phys: Not PCI device %d, type %x\n", + d, _devices[d].dev_type); + return 0; + } + + switch (rsrc) { + case 0: + *phys_lo = (uint32_t)(_devices[d].iowin[0].addr); +#ifdef PHYS_ADDR_IS_64BIT + *phys_hi = (uint32_t)(_devices[d].iowin[0].addr >> 32); +#endif + *size = _devices[d].iowin[0].size; + break; + case 1: + *phys_lo = (uint32_t)(_devices[d].iowin[1].addr); +#ifdef PHYS_ADDR_IS_64BIT + *phys_hi = (uint32_t)(_devices[d].iowin[1].addr >> 32); +#endif + *size = _devices[d].iowin[1].size; + break; + default: + break; + } + + return 0; +} + +void * +lkbde_get_dma_dev(int d) +{ + if (!VALID_DEVICE(d)) { + return NULL; + } + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT + return (void *)_devices[d].dma_dev; +#else + return (void *)_devices[d].pci_device; +#endif +} + +void * +lkbde_get_hw_dev(int d) +{ + if (!VALID_DEVICE(d)) { + return NULL; + } + + return (void *)_devices[d].pci_device; +} + +int +lkbde_dev_state_set(int d, uint32 state) +{ + bde_ctrl_t *ctrl; + + if (!VALID_DEVICE(d)) { + return -1; + } + ctrl = _devices + d; + ctrl->dev_state = state; + return 0; +} + +int +lkbde_dev_state_get(int d, uint32 *state) +{ + bde_ctrl_t *ctrl; + if (!VALID_DEVICE(d)) { + gprintk("_get_dev: Invalid device index %d\n", d); + return -1; + } + ctrl = _devices + d; + + *state = ctrl->dev_state; + return 0; +} + +int +lkbde_dev_instid_set(int d, uint32 instid) +{ + bde_ctrl_t *ctrl; + + if (!VALID_DEVICE(d)) { + return -1; + } + ctrl = _devices + d; + ctrl->inst_id = instid; + + return 0; +} + +int +lkbde_dev_instid_get(int d, uint32 *instid) +{ + bde_ctrl_t *ctrl; + + if (!VALID_DEVICE(d)) { + return -1; + } + ctrl = _devices + d; + *instid = ctrl->inst_id; + + return 0; +} +/* + * When a secondary interrupt handler is installed this function + * is used for synchronizing hardware access to the IRQ mask + * register. The secondary driver will supply a non-zero fmask + * (filter mask) to indicate which interrupt bits it controls. + * The fmask is ignored for the primary driver. + */ +int +lkbde_irq_mask_set(int d, uint32_t addr, uint32_t mask, uint32_t fmask) +{ + bde_ctrl_t *ctrl; + int isr2_dev, iproc_reg; + unsigned long flags; + + isr2_dev = d & LKBDE_ISR2_DEV; + iproc_reg = d & LKBDE_IPROC_REG; + d &= ~(LKBDE_ISR2_DEV | LKBDE_IPROC_REG); + + if (!VALID_DEVICE(d)) { + return -1; + } + + ctrl = _devices + d; + + /* Lock is required to synchronize access from user space */ + spin_lock_irqsave(&ctrl->lock, flags); + + if (isr2_dev) { + /* This is the secondary interrupt handler */ + ctrl->fmask = fmask; + ctrl->imask2 = mask & ctrl->fmask; + } else { + /* This is the primary interrupt handler */ + ctrl->imask = mask & ~ctrl->fmask; + } + + if (iproc_reg) { + _iproc_write(d, addr, ctrl->imask | ctrl->imask2); + } else { + _write(d, addr, ctrl->imask | ctrl->imask2); + } + + spin_unlock_irqrestore(&ctrl->lock, flags); + + return 0; +} + +/* + * When a secondary interrupt handler is installed, this function + * is used to avoid activating the user mode interrupt handler + * thread if all pending interrupts are handled in kernel space. + * + * The mask returned is the mask of all interrupts, it can be used + * to do a logical AND with fmask, the result will tell you if + * the user mode interrupt handler needs to be invoked. + * + * Note that if no secondary handler is installed, the value of + * "mask & fmask" will be zero, and hence there will be no need to read the + * current interrupt status from hardware (from kernel space). + */ +int +lkbde_irq_mask_get(int d, uint32_t *mask, uint32_t *fmask) +{ + bde_ctrl_t *ctrl; + + d &= ~(LKBDE_ISR2_DEV | LKBDE_IPROC_REG); + + if (!VALID_DEVICE(d)) { + return -1; + } + + if (mask == NULL || fmask == NULL) { + return -1; + } + + ctrl = _devices + d; + + *fmask = ctrl->fmask; + *mask = ctrl->imask | ctrl->imask2; + + return 0; +} + +int +lkbde_get_num_devices(int type) +{ + return _num_devices(type); +} + +/* + * Return none-zero if the SDK instance with the given instance ID + * manages the given device. + */ +int lkbde_is_dev_managed_by_instance(uint32 dev, uint32 inst_id) +{ + if (inst_id >= LINUX_BDE_MAX_DEVICES || dev >= _ndevices) { + return 0; + } + return _instance_info[inst_id].devices[dev / 32] & (1 << (dev % 32)) ? 1 : 0; +} + +/* + * Return a pointer to the bitmap of the SDK instance managed devices. + */ +linux_bde_device_bitmap_t* lkbde_get_inst_devs(uint32 inst_id) +{ + if (inst_id >= LINUX_BDE_MAX_DEVICES) { + return NULL; + } + return &_instance_info[inst_id].devices; +} + +/* + * Export functions + */ +LKM_EXPORT_SYM(linux_bde_create); +LKM_EXPORT_SYM(linux_bde_destroy); +LKM_EXPORT_SYM(lkbde_get_dev_phys); +LKM_EXPORT_SYM(lkbde_get_dev_virt); +LKM_EXPORT_SYM(lkbde_get_dev_resource); +LKM_EXPORT_SYM(lkbde_get_hw_dev); +LKM_EXPORT_SYM(lkbde_get_dma_dev); +LKM_EXPORT_SYM(lkbde_irq_mask_set); +LKM_EXPORT_SYM(lkbde_irq_mask_get); +LKM_EXPORT_SYM(lkbde_get_dev_phys_hi); +LKM_EXPORT_SYM(lkbde_dev_state_set); +LKM_EXPORT_SYM(lkbde_dev_state_get); +LKM_EXPORT_SYM(lkbde_dev_instid_set); +LKM_EXPORT_SYM(lkbde_dev_instid_get); +#ifdef BCM_SAND_SUPPORT +LKM_EXPORT_SYM(lkbde_cpu_write); +LKM_EXPORT_SYM(lkbde_cpu_read); +LKM_EXPORT_SYM(lkbde_cpu_pci_register); +#endif +LKM_EXPORT_SYM(lkbde_is_dev_managed_by_instance); +LKM_EXPORT_SYM(lkbde_get_inst_devs); diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c new file mode 100644 index 000000000000..52711964a533 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c @@ -0,0 +1,1213 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: linux_dma.c,v 1.414 Broadcom SDK $ + * $Copyright: (c) 2016 Broadcom Corp. + * All Rights Reserved.$ + * + * Linux Kernel BDE DMA memory allocation + * + * + * DMA memory allocation modes + * =========================== + * + * 1. Using private pool in kernel memory + * -------------------------------------- + * In this mode the BDE module will try to assemble a physically contiguous + * of memory using the kernel page allocator. This memory block is then + * administered by the mpool allocation functions. Note that once a system + * has been running for a while, the memory fragmentation may prevent the + * allocator from assembling a contiguous memory block, however, if the + * module is loaded shortly after system startup, it is very unlikely to + * fail. + * + * This allocation method is used by default. + * + * 2. Using private pool in high memory + * ------------------------------------ + * In this mode the BDE module will assume that unused physical memory is + * present at the high_memory address, i.e. memory not managed by the Linux + * memory manager. This memory block is mapped into kernel space and + * administered by the mpool allocation functions. High memory must be + * reserved using either the mem=xxx kernel parameter (recommended), or by + * hardcoding the memory limit in the kernel image. + * + * The module parameter himem=1 enables this allocation mode. + * + * 3. Using kernel allocators (kmalloc, __get_free_pages) + * ------------------------------------------------------ + * In this mode all DMA memory is allocated from the kernel on the fly, i.e. + * no private DMA memory pool will be created. If large memory blocks are + * only allocated at system startup (or not at all), this allocation method + * is the most flexible and memory-efficient, however, it is not recommended + * for non-coherent memory platforms due to an overall system performance + * degradation arising from the use of cache flush/invalidate instructions. + * + * The module parameter dmasize=0M enables this allocation mode, however if + * DMA memory is requested from a user mode application, a private memory + * pool will be created and used irrespectively. + */ + +#include +#include +#include +#include +#include + +#if defined(IPROC_CMICD) && defined(CONFIG_OF) +#include +#endif + +#ifdef BCM_PLX9656_LOCAL_BUS +#include +#endif + +/* allocation types/methods for the DMA memory pool */ +#define ALLOC_TYPE_CHUNK 0 /* use small allocations and join them */ +#define ALLOC_TYPE_API 1 /* use one allocation */ + +#if _SIMPLE_MEMORY_ALLOCATION_ +#include +#if defined(CONFIG_CMA) && defined(CONFIG_CMA_SIZE_MBYTES) +#define DMA_MAX_ALLOC_SIZE (CONFIG_CMA_SIZE_MBYTES * 1024 * 1024) +#else +#define DMA_MAX_ALLOC_SIZE (1 << (MAX_ORDER - 1 + PAGE_SHIFT)) /* Maximum size the kernel can allocate in one allocation */ +#endif +#endif /* _SIMPLE_MEMORY_ALLOCATION_ */ + +#if _SIMPLE_MEMORY_ALLOCATION_ == 1 +/* Use Linux DMA API to allocate contiguous memory */ +#define ALLOC_METHOD_DEFAULT ALLOC_TYPE_API +#if defined(__arm__) +#define USE_DMA_MMAP_COHERENT +#define _PGPROT_NONCACHED(x) x = pgprot_noncached((x)) +#elif defined(__aarch64__ ) +#define USE_DMA_MMAP_COHERENT +#define _PGPROT_NONCACHED(x) x = pgprot_writecombine((x)) +#endif +#else +#define ALLOC_METHOD_DEFAULT ALLOC_TYPE_CHUNK +#endif + +#ifndef _PGPROT_NONCACHED +#ifdef REMAP_DMA_NONCACHED +#define _PGPROT_NONCACHED(x) x = pgprot_noncached((x)) +#else +#define _PGPROT_NONCACHED(x) +#endif +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +#include +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) +#define VIRT_TO_PAGE(p) virt_to_page((void*)(p)) +#else +#define VIRT_TO_PAGE(p) virt_to_page((p)) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)) +#define BDE_DMA_MAPPING_ERROR(d, p) dma_mapping_error((d),(p)) +#else +#define BDE_DMA_MAPPING_ERROR(d, p) dma_mapping_error((p)) +#endif + +#ifndef KMALLOC_MAX_SIZE +#define KMALLOC_MAX_SIZE (1UL << (MAX_ORDER - 1 + PAGE_SHIFT)) +#endif + +/* Compatibility */ +#ifdef LKM_2_4 +#define MEM_MAP_RESERVE mem_map_reserve +#define MEM_MAP_UNRESERVE mem_map_unreserve +#else /* LKM_2_6 */ +#define MEM_MAP_RESERVE SetPageReserved +#define MEM_MAP_UNRESERVE ClearPageReserved +#endif /* LKM_2_x */ + +#ifndef GFP_DMA32 +#define GFP_DMA32 0 +#endif + +/* Flags for memory allocations */ +#ifdef SAL_BDE_XLP +static int mem_flags = GFP_ATOMIC | GFP_KERNEL | GFP_DMA; +#else +#if defined(CONFIG_ZONE_DMA32) +static int mem_flags = GFP_ATOMIC | GFP_DMA32; +#else +static int mem_flags = GFP_ATOMIC | GFP_DMA; +#endif +#endif + +/* Debug output */ +static int dma_debug = 0; +module_param(dma_debug, int, 0); +MODULE_PARM_DESC(dma_debug, +"DMA debug output enable (default 0)."); + +/* DMA memory pool size */ +static char *dmasize; +LKM_MOD_PARAM(dmasize, "s", charp, 0); +MODULE_PARM_DESC(dmasize, +"Specify DMA memory size (default 4MB)"); + +/* Select DMA memory pool allocation method */ +static int dmaalloc = ALLOC_METHOD_DEFAULT; +LKM_MOD_PARAM(dmaalloc, "i", int, 0); +MODULE_PARM_DESC(dmaalloc, "Select DMA memory allocation method"); + +/* Use high memory for DMA */ +static char *himem; +LKM_MOD_PARAM(himem, "s", charp, 0); +MODULE_PARM_DESC(himem, +"Use high memory for DMA (default no)"); + +/* Physical high memory address to use for DMA */ +static char *himemaddr = 0; +LKM_MOD_PARAM(himemaddr, "s", charp, 0); +MODULE_PARM_DESC(himemaddr, +"Physical address to use for high memory DMA"); + +/* DMA memory allocation */ + +#define ONE_KB 1024 +#define ONE_MB (1024*1024) +#define ONE_GB (1024*1024*1024) + +/* Default DMA memory size */ +#ifdef SAL_BDE_DMA_MEM_DEFAULT +#define DMA_MEM_DEFAULT (SAL_BDE_DMA_MEM_DEFAULT * ONE_MB) +#else +#define DMA_MEM_DEFAULT (8 * ONE_MB) +#endif + +#ifdef BDE_EDK_SUPPORT +typedef struct { + phys_addr_t cpu_pbase; /* CPU physical base address of the DMA pool */ + phys_addr_t dma_pbase; /* Bus base address of the DMA pool */ + void __iomem *dma_vbase; + uint32 size; /* Total size of the pool */ +}_edk_dma_pool_t; +static _edk_dma_pool_t _edk_dma_pool[LINUX_BDE_MAX_DEVICES]; +static int _edk_use_dma_mapping = 0; +#endif + +/* We try to assemble a contiguous segment from chunks of this size */ +#define DMA_BLOCK_SIZE (512 * ONE_KB) + +typedef struct _dma_segment { + struct list_head list; + unsigned long req_size; /* Requested DMA segment size */ + unsigned long blk_size; /* DMA block size */ + unsigned long blk_order; /* DMA block size in alternate format */ + unsigned long seg_size; /* Current DMA segment size */ + unsigned long seg_begin; /* Logical address of segment */ + unsigned long seg_end; /* Logical end address of segment */ + unsigned long *blk_ptr; /* Array of logical DMA block addresses */ + int blk_cnt_max; /* Maximum number of block to allocate */ + int blk_cnt; /* Current number of blocks allocated */ +} dma_segment_t; + +static unsigned int _dma_mem_size = DMA_MEM_DEFAULT; +static mpool_handle_t _dma_pool = NULL; +static void __iomem *_dma_vbase = NULL; +/* cpu physical address for mmap */ +static phys_addr_t _cpu_pbase = 0; +/* + * DMA bus address, it is either identical to cpu physical address + * or another address(IOVA) translated by IOMMU. + */ +static phys_addr_t _dma_pbase = 0; +static int _use_himem = 0; +static unsigned long _himemaddr = 0; +static int _use_dma_mapping = 0; +static LIST_HEAD(_dma_seg); + +#define DMA_DEV_INDEX 0 /* Device index to allocate memory pool */ +#define DMA_DEV(n) lkbde_get_dma_dev(n) +#define BDE_NUM_DEVICES(t) lkbde_get_num_devices(t) + +/* + * Function: _find_largest_segment + * + * Purpose: + * Find largest contiguous segment from a pool of DMA blocks. + * Parameters: + * dseg - DMA segment descriptor + * Returns: + * 0 on success, < 0 on error. + * Notes: + * Assembly stops if a segment of the requested segment size + * has been obtained. + * + * Lower address bits of the DMA blocks are used as follows: + * 0: Untagged + * 1: Discarded block + * 2: Part of largest contiguous segment + * 3: Part of current contiguous segment + */ +static int +_find_largest_segment(dma_segment_t *dseg) +{ + int i, j, blks, found; + unsigned long b, e, a; + + blks = dseg->blk_cnt; + /* Clear all block tags */ + for (i = 0; i < blks; i++) { + dseg->blk_ptr[i] &= ~3; + } + for (i = 0; i < blks && dseg->seg_size < dseg->req_size; i++) { + /* First block must be an untagged block */ + if ((dseg->blk_ptr[i] & 3) == 0) { + /* Initial segment size is the block size */ + b = dseg->blk_ptr[i]; + e = b + dseg->blk_size; + dseg->blk_ptr[i] |= 3; + /* Loop looking for adjacent blocks */ + do { + found = 0; + for (j = i + 1; j < blks && (e - b) < dseg->req_size; j++) { + a = dseg->blk_ptr[j]; + /* Check untagged blocks only */ + if ((a & 3) == 0) { + if (a == (b - dseg->blk_size)) { + /* Found adjacent block below current segment */ + dseg->blk_ptr[j] |= 3; + b = a; + found = 1; + } else if (a == e) { + /* Found adjacent block above current segment */ + dseg->blk_ptr[j] |= 3; + e += dseg->blk_size; + found = 1; + } + } + } + } while (found); + if ((e - b) > dseg->seg_size) { + /* The current block is largest so far */ + dseg->seg_begin = b; + dseg->seg_end = e; + dseg->seg_size = e - b; + /* Re-tag current and previous largest segment */ + for (j = 0; j < blks; j++) { + if ((dseg->blk_ptr[j] & 3) == 3) { + /* Tag current segment as the largest */ + dseg->blk_ptr[j] &= ~1; + } else if ((dseg->blk_ptr[j] & 3) == 2) { + /* Discard previous largest segment */ + dseg->blk_ptr[j] ^= 3; + } + } + } else { + /* Discard all blocks in current segment */ + for (j = 0; j < blks; j++) { + if ((dseg->blk_ptr[j] & 3) == 3) { + dseg->blk_ptr[j] &= ~2; + } + } + } + } + } + return 0; +} + +/* + * Function: _alloc_dma_blocks + * + * Purpose: + * Allocate DMA blocks and add them to the pool. + * Parameters: + * dseg - DMA segment descriptor + * blks - number of DMA blocks to allocate + * Returns: + * 0 on success, < 0 on error. + * Notes: + * DMA blocks are allocated using the page allocator. + */ +static int +_alloc_dma_blocks(dma_segment_t *dseg, int blks) +{ + int i, start; + unsigned long addr; + + if (dseg->blk_cnt + blks > dseg->blk_cnt_max) { + gprintk("No more DMA blocks\n"); + return -1; + } + start = dseg->blk_cnt; + for (i = 0; i < blks; i++) { + /* + * Note that we cannot use pci_alloc_consistent when we + * want to be able to map DMA memory to user space. + * + * The GFP_DMA flag is omitted as this imposes the ISA + * addressing limitations on x86 platforms. As long as + * we have less than 1GB of memory, we can do PCI DMA + * to all physical RAM locations. + */ + addr = __get_free_pages(mem_flags, dseg->blk_order); + if (addr) { + dseg->blk_ptr[start + i] = addr; + ++dseg->blk_cnt; + } else { + gprintk("DMA allocation failed: allocated %d of %d " + "requested blocks\n", i, blks); + return -1; + } + } + return 0; +} + +/* + * Function: _dma_segment_alloc + * + * Purpose: + * Allocate large physically contiguous DMA segment. + * Parameters: + * size - requested DMA segment size + * blk_size - assemble segment from blocks of this size + * Returns: + * DMA segment descriptor. + * Notes: + * Since we cannot allocate large blocks of contiguous + * memory from the kernel, we simply keep allocating + * smaller chunks until we can assemble a contiguous + * block of the desired size. + * + * When system allowed maximum bytes of memory has been allocated + * without a successful assembly of a contiguous DMA + * segment, the allocation function will return the + * largest contiguous segment found so far. It is up + * to the calling function to decide whether this + * amount is sufficient to proceed. + */ +static dma_segment_t * +_dma_segment_alloc(size_t size, size_t blk_size) +{ + dma_segment_t *dseg; + int i, blk_ptr_size; + unsigned long page_addr; + struct sysinfo si; + + /* Sanity check */ + if (size == 0 || blk_size == 0) { + return NULL; + } + /* Allocate an initialize DMA segment descriptor */ + if ((dseg = kmalloc(sizeof(dma_segment_t), GFP_KERNEL)) == NULL) { + return NULL; + } + memset(dseg, 0, sizeof(dma_segment_t)); + dseg->req_size = size; + dseg->blk_size = PAGE_ALIGN(blk_size); + while ((PAGE_SIZE << dseg->blk_order) < dseg->blk_size) { + dseg->blk_order++; + } + + si_meminfo(&si); + dseg->blk_cnt_max = (si.totalram << PAGE_SHIFT) / dseg->blk_size; + blk_ptr_size = dseg->blk_cnt_max * sizeof(unsigned long); + if (blk_ptr_size > KMALLOC_MAX_SIZE) { + blk_ptr_size = KMALLOC_MAX_SIZE; + dseg->blk_cnt_max = KMALLOC_MAX_SIZE / sizeof(unsigned long); + } + /* Allocate an initialize DMA block pool */ + dseg->blk_ptr = KMALLOC(blk_ptr_size, GFP_KERNEL); + if (dseg->blk_ptr == NULL) { + kfree(dseg); + return NULL; + } + memset(dseg->blk_ptr, 0, blk_ptr_size); + /* Allocate minimum number of blocks */ + if (_alloc_dma_blocks(dseg, dseg->req_size / dseg->blk_size) != 0) { + gprintk("Failed to allocate minimum number of DMA blocks\n"); + /* + * _alloc_dma_blocks() returns -1 if it fails to allocate the requested + * number of blocks, but it may still have allocated something. Fall + * through and return dseg filled in with as much memory as we could + * allocate. + */ + } + /* Allocate more blocks until we have a complete segment */ + do { + _find_largest_segment(dseg); + if (dseg->seg_size >= dseg->req_size) { + break; + } + } while (_alloc_dma_blocks(dseg, 8) == 0); + /* Reserve all pages in the DMA segment and free unused blocks */ + for (i = 0; i < dseg->blk_cnt; i++) { + if ((dseg->blk_ptr[i] & 3) == 2) { + dseg->blk_ptr[i] &= ~3; + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) { + MEM_MAP_RESERVE(VIRT_TO_PAGE(page_addr)); + } + } else if (dseg->blk_ptr[i]) { + dseg->blk_ptr[i] &= ~3; + free_pages(dseg->blk_ptr[i], dseg->blk_order); + dseg->blk_ptr[i] = 0; + } + } + return dseg; +} + +/* + * Function: _dma_segment_free + * + * Purpose: + * Release resources used by DMA segment. + * Parameters: + * dseg - DMA segment descriptor + * Returns: + * Nothing. + */ +static void +_dma_segment_free(dma_segment_t *dseg) +{ + int i; + unsigned long page_addr; + + if (dseg->blk_ptr) { + for (i = 0; i < dseg->blk_cnt; i++) { + if (dseg->blk_ptr[i]) { + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) { + MEM_MAP_UNRESERVE(VIRT_TO_PAGE(page_addr)); + } + free_pages(dseg->blk_ptr[i], dseg->blk_order); + } + } + kfree(dseg->blk_ptr); + kfree(dseg); + } +} + +/* + * Function: _pgalloc + * + * Purpose: + * Allocate DMA memory using page allocator + * Parameters: + * size - number of bytes to allocate + * Returns: + * Pointer to allocated DMA memory or NULL if failure. + * Notes: + * For any sizes less than DMA_BLOCK_SIZE, we ask the page + * allocator for the entire memory block, otherwise we try + * to assemble a contiguous segment ourselves. + */ +static void * +_pgalloc(size_t size) +{ + dma_segment_t *dseg; + size_t blk_size; + + blk_size = (size < DMA_BLOCK_SIZE) ? size : DMA_BLOCK_SIZE; + if ((dseg = _dma_segment_alloc(size, blk_size)) == NULL) { + return NULL; + } + if (dseg->seg_size < size) { + /* If we didn't get the full size then forget it */ + gprintk("_pgalloc() failed to get requested size %zu: " + "only got %lu contiguous across %d blocks\n", + size, dseg->seg_size, dseg->blk_cnt); + _dma_segment_free(dseg); + return NULL; + } + list_add(&dseg->list, &_dma_seg); + return (void *)dseg->seg_begin; +} + +/* + * Function: _pgfree + * + * Purpose: + * Free memory allocated by _pgalloc + * Parameters: + * ptr - pointer returned by _pgalloc + * Returns: + * 0 if succesfully freed, otherwise -1. + */ +static int +_pgfree(void *ptr) +{ + struct list_head *pos; + list_for_each(pos, &_dma_seg) { + dma_segment_t *dseg = list_entry(pos, dma_segment_t, list); + if (ptr == (void *)dseg->seg_begin) { + list_del(&dseg->list); + _dma_segment_free(dseg); + return 0; + } + } + return -1; +} + +#ifdef BDE_EDK_SUPPORT +/* + * Function: _edk_mpool_free + * + * Purpose: + * Free all memory allocated by _adk_mpool_alloc + * Parameters: + * None + * Returns: + * Nothing. + */ +static void +_edk_mpool_free(void) +{ + int i, ndevices; + + ndevices = BDE_NUM_DEVICES(BDE_SWITCH_DEVICES); + for (i = 0; i < ndevices && DMA_DEV(i); i ++) { + if (_edk_dma_pool[i].dma_vbase) { + if (_edk_use_dma_mapping) { + dma_unmap_single(DMA_DEV(i), (dma_addr_t)_edk_dma_pool[i].dma_pbase, + _edk_dma_pool[i].size, DMA_BIDIRECTIONAL); + } + _pgfree(_edk_dma_pool[i].dma_vbase); + _edk_dma_pool[i].dma_vbase = NULL; + } + } + _edk_use_dma_mapping = 0; +} + +/* + * Function: edk_mpool_alloc + * + * Purpose: + * Allocate DMA memory pool for EDK + * Parameters: + * size - size of DMA memory pool + * Returns: + * Nothing. + */ +static void +_edk_mpool_alloc(int dev_id, size_t size) +{ + static void __iomem *dma_vbase = NULL; + static phys_addr_t cpu_pbase = 0; + static phys_addr_t dma_pbase = 0; + + struct device *dev = DMA_DEV(DMA_DEV_INDEX); + unsigned long pbase = 0; + + dma_vbase = _pgalloc(size); + if (!dma_vbase) { + gprintk("Failed to allocate memory pool of size 0x%lx for EDK\n", + (unsigned long)size); + return; + } + cpu_pbase = virt_to_bus(dma_vbase); + + /* Use dma_map_single to obtain DMA bus address or IOVA if IOMMU is present. */ + if (dev) { + pbase = dma_map_single(dev, dma_vbase, size, DMA_BIDIRECTIONAL); + if (BDE_DMA_MAPPING_ERROR(dev, pbase)) { + gprintk("Failed to map memory at %p for EDK\n", dma_vbase); + _pgfree(dma_vbase); + dma_vbase = NULL; + return; + } + _edk_use_dma_mapping = 1; + } else { + pbase = cpu_pbase; + } + + dma_pbase = pbase; + +#ifdef REMAP_DMA_NONCACHED + _dma_vbase = IOREMAP(dma_pbase, size); +#endif + _edk_dma_pool[dev_id].cpu_pbase = cpu_pbase; + _edk_dma_pool[dev_id].dma_pbase = dma_pbase; + _edk_dma_pool[dev_id].dma_vbase = dma_vbase; + _edk_dma_pool[dev_id].size = size; +} + +int +lkbde_edk_get_dma_info(int dev_id, phys_addr_t* cpu_pbase, phys_addr_t* dma_pbase, ssize_t* size) +{ + if (_edk_dma_pool[dev_id].dma_vbase == NULL) { + _edk_mpool_alloc(dev_id, *size * ONE_MB); + } + + if (cpu_pbase) { + *cpu_pbase = _edk_dma_pool[dev_id].cpu_pbase; + } + + if (dma_pbase) { + *dma_pbase = _edk_dma_pool[dev_id].dma_pbase; + } + + *size = (_edk_dma_pool[dev_id].dma_vbase) ? _edk_dma_pool[dev_id].size : 0; + return 0; +} + +/* + * The below function validates the memory to the EDK allocated DMA pool, + * required to user space via the BDE device file. + */ +static int +_edk_vm_is_valid(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size = vma->vm_end - vma->vm_start; + int i, ndevices; + + ndevices = BDE_NUM_DEVICES(BDE_SWITCH_DEVICES); + for (i = 0; i < ndevices; i++) { + if (phys_addr < (unsigned long )_edk_dma_pool[i].cpu_pbase || + (phys_addr + size) > ((unsigned long )_edk_dma_pool[i].cpu_pbase + + _edk_dma_pool[i].size)) { + continue; + } + return 1; + } + + return 0; +} +#endif + +/* + * Function: _mpool_free + * + * Purpose: + * Free all memory allocated by _mpool_alloc + * Parameters: + * None + * Returns: + * Nothing. + */ +static void +_mpool_free(void) +{ + switch (dmaalloc) { +#if _SIMPLE_MEMORY_ALLOCATION_ + case ALLOC_TYPE_API: + if (_dma_vbase) { + if (dma_debug >= 1) gprintk("freeing v=%p p=0x%lx size=0x%lx\n", _dma_vbase,(unsigned long) _dma_pbase, (unsigned long)_dma_mem_size); + dma_free_coherent(DMA_DEV(DMA_DEV_INDEX), _dma_mem_size, _dma_vbase, _dma_pbase); + } + break; +#endif /* _SIMPLE_MEMORY_ALLOCATION_ */ + + case ALLOC_TYPE_CHUNK: { + struct list_head *pos, *tmp; + int i, ndevices; + if (_use_dma_mapping) { + ndevices = BDE_NUM_DEVICES(BDE_SWITCH_DEVICES); + for (i = 0; i < ndevices && DMA_DEV(i); i ++) { + dma_unmap_single(DMA_DEV(i), (dma_addr_t)_dma_pbase, _dma_mem_size, DMA_BIDIRECTIONAL); + } + _use_dma_mapping = 0; + } + list_for_each_safe(pos, tmp, &_dma_seg) { + dma_segment_t *dseg = list_entry(pos, dma_segment_t, list); + list_del(&dseg->list); + _dma_segment_free(dseg); + } + break; + } + + default: + gprintk("DMA memory allocation method dmaalloc=%d is not supported\n", dmaalloc); + } +} + +/* + * Function: _mpool_alloc + * + * Purpose: + * Allocate DMA memory pool + * Parameters: + * size - size of DMA memory pool + * Returns: + * Nothing. + * Notes: + * If set up to use high memory, we simply map the memory into + * kernel space. + * It is assumed there is only one pool. + */ +static void +_mpool_alloc(size_t size) +{ + unsigned long pbase = 0; + struct device *dev = DMA_DEV(DMA_DEV_INDEX); + int dma64_support = 0; + +#if defined(IPROC_CMICD) && defined(CONFIG_OF) + if (of_find_compatible_node(NULL, NULL, "brcm,iproc-cmicx")) { + dma64_support = 1; + } +#endif + +#if defined(__arm__) && !defined(CONFIG_HIGHMEM) + if (_use_himem) { + gprintk("DMA in high memory requires CONFIG_HIGHMEM on ARM CPUs.\n"); + return; + } +#endif + + if (_use_himem) { + /* Use high memory for DMA */ + if (_himemaddr) { + pbase = _himemaddr; + } else { + pbase = virt_to_bus(high_memory); + } + if (((pbase + (size - 1)) >> 16) > DMA_BIT_MASK(16)) { + gprintk("DMA in high memory at 0x%lx size 0x%lx is beyond the 4GB limit and not supported.\n", pbase, (unsigned long)size); + return; + } + _cpu_pbase = pbase; + if (dev) { + /* Use dma_map_single to obtain DMA bus address or I/O virtual address, if + IOMMU is present. */ + pbase = dma_map_single(dev, bus_to_virt(_cpu_pbase), size, DMA_BIDIRECTIONAL); + if (BDE_DMA_MAPPING_ERROR(dev, pbase)) { + gprintk("Error !! Failed to map memory at phys base 0x%lx\n", + (unsigned long)_cpu_pbase); + _cpu_pbase = 0; + return; + } + _use_dma_mapping = 1; + } else { + pbase = _cpu_pbase; + } + _dma_pbase = pbase; + _dma_vbase = IOREMAP(_dma_pbase, size); + } else { + /* Get DMA memory from kernel */ + if (dma_debug >= 1) { + gprintk("Allocating DMA memory using method dmaalloc=%d\n", dmaalloc); + } + switch (dmaalloc) { +#if _SIMPLE_MEMORY_ALLOCATION_ + case ALLOC_TYPE_API: { + size_t alloc_size = size; /* size of memory allocated in current iteration */ + if (alloc_size > DMA_MAX_ALLOC_SIZE) { + alloc_size = DMA_MAX_ALLOC_SIZE; + } + /* get a memory allocation from the kernel */ + { + dma_addr_t dma_handle; + _dma_vbase = dma_alloc_coherent(dev, alloc_size, &dma_handle, GFP_KERNEL); + if (!_dma_vbase || !dma_handle) { + gprintk("Failed to allocate coherent memory pool of size 0x%lx\n", (unsigned long)alloc_size); + return; + } + _cpu_pbase = pbase = dma_handle; + } + + if (alloc_size != size) { + gprintk("allocated 0x%lx bytes instead of 0x%lx bytes.\n", + (unsigned long)alloc_size, (unsigned long)size); + } + size = _dma_mem_size = alloc_size; + break; + } +#endif /* _SIMPLE_MEMORY_ALLOCATION_ */ + + case ALLOC_TYPE_CHUNK: + _dma_vbase = _pgalloc(size); + if (!_dma_vbase) { + gprintk("Failed to allocate memory pool of size 0x%lx\n", (unsigned long)size); + return; + } + _cpu_pbase = virt_to_bus(_dma_vbase); + /* Use dma_map_single to obtain DMA bus address or IOVA if IOMMU is present. */ + if (dev) { + pbase = dma_map_single(dev, _dma_vbase, size, DMA_BIDIRECTIONAL); + if (BDE_DMA_MAPPING_ERROR(dev, pbase)) { + gprintk("Failed to map memory at %p\n", _dma_vbase); + _mpool_free(); + _dma_vbase = NULL; + return; + } + _use_dma_mapping = 1; + } else { + pbase = _cpu_pbase; + } + break; + default: + _dma_vbase = NULL; + gprintk("DMA memory allocation method dmaalloc=%d is not supported\n", dmaalloc); + return; + } + + _dma_pbase = pbase; + + if (!dma64_support && ((pbase + (size - 1)) >> 16) > DMA_BIT_MASK(16)) { + gprintk("DMA memory allocated at 0x%lx size 0x%lx is beyond the 4GB limit and not supported.\n", pbase, (unsigned long)size); + _mpool_free(); + _dma_vbase = NULL; + _dma_pbase = 0; + return; + } + +#ifdef REMAP_DMA_NONCACHED + _dma_vbase = IOREMAP(_dma_pbase, size); +#endif + if (dma_debug >= 1) { + gprintk("_use_dma_mapping:%d _dma_vbase:%p _dma_pbase:%lx _cpu_pbase:%lx allocated:%lx dmaalloc:%d, dma64_support:%d\n", + _use_dma_mapping, _dma_vbase, (unsigned long)_dma_pbase, + (unsigned long)_cpu_pbase, (unsigned long)size, dmaalloc, dma64_support); + } + } +} + +/* + * Function: _dma_cleanup + * + * Purpose: + * DMA cleanup function. + * Parameters: + * None + * Returns: + * Always 0 + */ +int +_dma_cleanup(void) +{ +#ifdef BDE_EDK_SUPPORT + _edk_mpool_free(); +#endif + if (_dma_vbase) { + mpool_destroy(_dma_pool); + if (_use_himem) { + int i, ndevices; + iounmap(_dma_vbase); + if (_use_dma_mapping) { + ndevices = BDE_NUM_DEVICES(BDE_SWITCH_DEVICES); + for (i = 0; i < ndevices && DMA_DEV(i); i ++) { + dma_unmap_single(DMA_DEV(i), (dma_addr_t)_dma_pbase, _dma_mem_size, + DMA_BIDIRECTIONAL); + } + _use_dma_mapping = 0; + } + } else { +#ifdef REMAP_DMA_NONCACHED + iounmap(_dma_vbase); +#endif + _mpool_free(); + } + _dma_vbase = NULL; + _dma_pbase = 0; + _cpu_pbase = 0; + } + return 0; +} + +void _dma_init(int dev_index) +{ + unsigned long pbase; + + if (dev_index > DMA_DEV_INDEX) { + if (_use_dma_mapping && DMA_DEV(dev_index) && _dma_vbase) { + pbase = dma_map_single(DMA_DEV(dev_index), _dma_vbase, _dma_mem_size, DMA_BIDIRECTIONAL); + if (BDE_DMA_MAPPING_ERROR(DMA_DEV(dev_index), pbase)) { + gprintk("Failed to map memory for device %d at %p\n", dev_index, _dma_vbase); + return; + } + if (pbase != (unsigned long)_dma_pbase) { + /* Bus address/IOVA must be identical for all devices. */ + gprintk("Device %d has different pbase: %lx (should be %lx)\n", + dev_index, pbase, (unsigned long)_dma_pbase); + } + } + return; + } + + /* DMA Setup */ + if (dmasize) { + if ((dmasize[strlen(dmasize)-1] & ~0x20) == 'M') { + _dma_mem_size = simple_strtoul(dmasize, NULL, 0); + _dma_mem_size *= ONE_MB; + } else { + gprintk("DMA memory size must be specified as e.g. dmasize=8M\n"); + } + if (_dma_mem_size & (_dma_mem_size-1)) { + gprintk("dmasize must be a power of 2 (1M, 2M, 4M, 8M etc.)\n"); + _dma_mem_size = 0; + } + } + + if (himem) { + if ((himem[0] & ~0x20) == 'Y' || himem[0] == '1') { + _use_himem = 1; + } else if ((himem[0] & ~0x20) == 'N' || himem[0] == '0') { + _use_himem = 0; + } + } + + if (himemaddr && strlen(himemaddr) > 0) { + char suffix = (himemaddr[strlen(himemaddr)-1] & ~0x20); + _himemaddr = simple_strtoul(himemaddr, NULL, 0); + if (suffix == 'M') { + _himemaddr *= ONE_MB; + } else if (suffix == 'G') { + _himemaddr *= ONE_GB; + } else { + gprintk("DMA high memory address must be specified as e.g. himemaddr=8[MG]\n"); + } + } + + if (_dma_mem_size) { + _mpool_alloc(_dma_mem_size); + if (_dma_vbase == NULL) { + gprintk("no DMA memory available\n"); + } else { + mpool_init(); + _dma_pool = mpool_create(_dma_vbase, _dma_mem_size); + } + } +} + +/* + * Some kernels are configured to prevent mapping of kernel RAM memory + * into user space via the /dev/mem device. + * + * The function below provides a backdoor to mapping the DMA pool to + * user space via the BDE device file. + */ +int _dma_mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size = vma->vm_end - vma->vm_start; + + if (phys_addr < (unsigned long )_cpu_pbase || + (phys_addr + size) > ((unsigned long )_cpu_pbase + _dma_mem_size)) { +#ifdef BDE_EDK_SUPPORT + if(!_edk_vm_is_valid(filp, vma)) { + gprintk("range 0x%lx-0x%lx outside DMA pool\n", phys_addr, phys_addr + size); + return -EINVAL; + } +#else + gprintk("range 0x%lx-0x%lx outside DMA pool 0x%lx-0x%lx\n", + phys_addr, phys_addr + size, (unsigned long )_cpu_pbase, + (unsigned long )_cpu_pbase + _dma_mem_size); + return -EINVAL; +#endif + } + +#ifdef USE_DMA_MMAP_COHERENT + if (dmaalloc == ALLOC_TYPE_API) { + vma->vm_pgoff = 0; + return dma_mmap_coherent(DMA_DEV(DMA_DEV_INDEX), vma, (void *)_dma_vbase, phys_addr, size); + } +#endif + + _PGPROT_NONCACHED(vma->vm_page_prot); + + if (remap_pfn_range(vma, + vma->vm_start, + vma->vm_pgoff, + size, + vma->vm_page_prot)) { + gprintk("Failed to mmap phys range 0x%lx-0x%lx to 0x%lx-0x%lx\n", + phys_addr, phys_addr + size, vma->vm_start,vma->vm_end); + return -EAGAIN; + } + return 0; +} + +/* + * Function: _dma_pool_allocated + * + * Purpose: + * Check if DMA pool has been allocated. + * Parameters: + * None + * Returns: + * 0 : not allocated + * 1 : allocated + */ +int +_dma_pool_allocated(void) +{ + return (_dma_vbase) ? 1 : 0; +} + +sal_paddr_t +_l2p(int d, void *vaddr) +{ + if (_dma_mem_size) { + /* dma memory is a contiguous block */ + if (vaddr) { + return _dma_pbase + (PTR_TO_UINTPTR(vaddr) - PTR_TO_UINTPTR(_dma_vbase)); + } + return 0; + } + return ((sal_paddr_t)virt_to_bus(vaddr)); +} + +void * +_p2l(int d, sal_paddr_t paddr) +{ + sal_vaddr_t vaddr = (sal_vaddr_t)_dma_vbase; + + if (_dma_mem_size) { + /* DMA memory is a contiguous block */ + if (paddr == 0) { + return NULL; + } + return (void *)(vaddr + (sal_vaddr_t)(paddr - _dma_pbase)); + } + return bus_to_virt(paddr); +} + +/* + * Some of the driver malloc's are too large for + * kmalloc(), so 'sal_alloc' and 'sal_free' in the + * linux kernel sal cannot be implemented with kmalloc(). + * + * Instead, they expect someone to provide an allocator + * that can handle the gimongous size of some of the + * allocations, and we provide it here, by allocating + * this memory out of the boot-time dma pool. + * + * These are the functions in question: + */ + +void* kmalloc_giant(int sz) +{ + return mpool_alloc(_dma_pool, sz); +} + +void kfree_giant(void* ptr) +{ + return mpool_free(_dma_pool, ptr); +} + +uint32_t * +_salloc(int d, int size, const char *name) +{ + void *ptr; + + if (_dma_mem_size) { + return mpool_alloc(_dma_pool, size); + } + if ((ptr = kmalloc(size, mem_flags)) == NULL) { + ptr = _pgalloc(size); + } + return ptr; +} + +void +_sfree(int d, void *ptr) +{ + if (_dma_mem_size) { + return mpool_free(_dma_pool, ptr); + } + if (_pgfree(ptr) < 0) { + kfree(ptr); + } +} + +int +_sinval(int d, void *ptr, int length) +{ +#if defined(dma_cache_wback_inv) + dma_cache_wback_inv((unsigned long)ptr, length); +#else +#if defined(IPROC_CMICD) || defined(BCM958525) + /* FIXME: need proper function to replace dma_cache_sync */ + dma_sync_single_for_cpu(NULL, (unsigned long)ptr, length, DMA_BIDIRECTIONAL); +#else + dma_cache_sync(NULL, ptr, length, DMA_BIDIRECTIONAL); +#endif +#endif + return 0; +} + +int +_sflush(int d, void *ptr, int length) +{ +#if defined(dma_cache_wback_inv) + dma_cache_wback_inv((unsigned long)ptr, length); +#else +#if defined(IPROC_CMICD) || defined(BCM958525) + /* FIXME: need proper function to replace dma_cache_sync */ + dma_sync_single_for_cpu(NULL, (unsigned long)ptr, length, DMA_BIDIRECTIONAL); +#else + dma_cache_sync(NULL, ptr, length, DMA_BIDIRECTIONAL); +#endif +#endif + + return 0; +} + +int +lkbde_get_dma_info(phys_addr_t* cpu_pbase, phys_addr_t* dma_pbase, ssize_t* size) +{ + if (_dma_vbase == NULL) { + if (_dma_mem_size == 0) { + _dma_mem_size = DMA_MEM_DEFAULT; + } + _mpool_alloc(_dma_mem_size); + } + *cpu_pbase = _cpu_pbase; + *dma_pbase = _dma_pbase; + *size = (_dma_vbase) ? _dma_mem_size : 0; + return 0; +} + +void +_dma_pprint(struct seq_file *m) +{ + pprintf(m, "\tdmasize=%s\n", dmasize); + pprintf(m, "\thimem=%s\n", himem); + pprintf(m, "\thimemaddr=%s\n", himemaddr); + pprintf(m, "DMA Memory (%s): %d bytes, %d used, %d free%s\n", + (_use_himem) ? "high" : "kernel", + (_dma_vbase) ? _dma_mem_size : 0, + (_dma_vbase) ? mpool_usage(_dma_pool) : 0, + (_dma_vbase) ? _dma_mem_size - mpool_usage(_dma_pool) : 0, + USE_LINUX_BDE_MMAP ? ", local mmap" : ""); +} + +/* + * Export functions + */ + +#ifdef BDE_EDK_SUPPORT +LKM_EXPORT_SYM(lkbde_edk_get_dma_info); +#endif +LKM_EXPORT_SYM(kmalloc_giant); +LKM_EXPORT_SYM(kfree_giant); +LKM_EXPORT_SYM(lkbde_get_dma_info); diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.c new file mode 100644 index 000000000000..dd003e1f9297 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.c @@ -0,0 +1,131 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#include +#include +#include +#include "linux_shbde.h" + +/* Hardware abstractions for shared BDE functions */ + +static unsigned short +linux_pcic16_read(void *pci_dev, unsigned int addr) +{ + u16 data = 0; + + pci_read_config_word((struct pci_dev *)pci_dev, addr, &data); + + return data; +} + +static void +linux_pcic16_write(void *pci_dev, unsigned int addr, unsigned short data) +{ + pci_write_config_word((struct pci_dev *)pci_dev, addr, (u16)data); +} + +static unsigned int +linux_pcic32_read(void *pci_dev, unsigned int addr) +{ + u32 data = 0; + + pci_read_config_dword((struct pci_dev *)pci_dev, addr, &data); + + return data; +} + +static void +linux_pcic32_write(void *pci_dev, unsigned int addr, unsigned int data) +{ + pci_write_config_dword((struct pci_dev *)pci_dev, addr, (u32)data); +} + +static unsigned int +linux_io32_read(void *addr) +{ + return *((volatile u32 *)addr); +} + +static void +linux_io32_write(void *addr, unsigned int data) +{ + *((volatile u32 *)addr) = data; +} + +static void +linux_usleep(int usec) +{ + udelay(usec); +} + + +/* To get the PCI parent device under linux, from only the device pointer */ +static void * +linux_pci_parent_device_get(void *pci_dev) +{ + return (void *)(((struct pci_dev *)pci_dev)->bus->self); +} + + +/* + * Function: + * linux_shbde_hal_init + * Purpose: + * Initialize hardware abstraction module for Linux kernel. + * Parameters: + * shbde - pointer to uninitialized hardware abstraction module + * log_func - optional log output function + * Returns: + * Always 0 + */ +int +linux_shbde_hal_init(shbde_hal_t *shbde, shbde_log_func_t log_func) +{ + memset(shbde, 0, sizeof(*shbde)); + + shbde->log_func = log_func; + + shbde->pcic16_read = linux_pcic16_read; + shbde->pcic16_write = linux_pcic16_write; + shbde->pcic32_read = linux_pcic32_read; + shbde->pcic32_write = linux_pcic32_write; + + shbde->io32_read = linux_io32_read; + shbde->io32_write = linux_io32_write; + + shbde->usleep = linux_usleep; + + shbde->pci_parent_device_get = linux_pci_parent_device_get; + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.h b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.h new file mode 100644 index 000000000000..ef4b49dc2124 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.h @@ -0,0 +1,44 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#ifndef __LINUX_SHBDE_H__ +#define __LINUX_SHBDE_H__ + +#include +#include +#include + +extern int +linux_shbde_hal_init(shbde_hal_t *shbde, shbde_log_func_t log_func); + +#endif /* __LINUX_SHBDE_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c b/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c new file mode 100644 index 000000000000..4c2db5e4de6c --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c @@ -0,0 +1,385 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: mpool.c,v 1.18 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#include + +#ifdef __KERNEL__ + +/* + * Abstractions used when compiling for Linux kernel mode. + */ + +#include + +/* + * We cannot use the linux kernel SAL for MALLOC/FREE because + * the current implementation of sal_alloc() allocates memory + * out of an mpool created by this module... + */ +#define MALLOC(x) kmalloc(x, GFP_ATOMIC) +#define FREE(x) kfree(x) + +static spinlock_t _mpool_lock; +#define MPOOL_LOCK_INIT() spin_lock_init(&_mpool_lock) +#define MPOOL_LOCK() unsigned long flags; spin_lock_irqsave(&_mpool_lock, flags) +#define MPOOL_UNLOCK() spin_unlock_irqrestore(&_mpool_lock, flags) + +#else /* !__KERNEL__*/ + +/* + * Abstractions used when compiling for Linux user mode. + */ + +#include +#include + +#define MALLOC(x) malloc(x) +#define FREE(x) free(x) + +static sal_sem_t _mpool_lock; +#define MPOOL_LOCK_INIT() _mpool_lock = sal_sem_create("mpool_lock", 1, 1) +#define MPOOL_LOCK() sal_sem_take(_mpool_lock, sal_sem_FOREVER) +#define MPOOL_UNLOCK() sal_sem_give(_mpool_lock) + +#endif /* __KERNEL__ */ + +/* Allow external override for system cache line size */ +#ifndef BCM_CACHE_LINE_BYTES +#ifdef L1_CACHE_BYTES +#define BCM_CACHE_LINE_BYTES L1_CACHE_BYTES +#else +#define BCM_CACHE_LINE_BYTES 128 /* Should be fine on most platforms */ +#endif +#endif + +#define MPOOL_BUF_SIZE 1024 +#define MPOOL_BUF_ALLOC_COUNT_MAX 128 + +typedef struct mpool_mem_s { + unsigned char *address; + int size; + struct mpool_mem_s *prev; + struct mpool_mem_s *next; +} mpool_mem_t; + +static int _mpool_count; +static int _buf_alloc_count; +static mpool_mem_t *mpool_buf[MPOOL_BUF_ALLOC_COUNT_MAX]; +static mpool_mem_t *free_list; + +static mpool_mem_t * +_mpool_buf_create(void) +{ + int i; + mpool_mem_t *ptr; + + if (_buf_alloc_count == MPOOL_BUF_ALLOC_COUNT_MAX) { + return NULL; + } + + mpool_buf[_buf_alloc_count] = MALLOC((sizeof(mpool_mem_t) * MPOOL_BUF_SIZE)); + if (!mpool_buf[_buf_alloc_count]) { + return NULL; + } + + ptr = mpool_buf[_buf_alloc_count]; + for (i = 0; i < MPOOL_BUF_SIZE - 1; i++) { + ptr[i].next = &ptr[i+1]; + } + + ptr[MPOOL_BUF_SIZE - 1].next = NULL; + + if (free_list) { + free_list->next = &ptr[0]; + } else { + free_list = &ptr[0]; + } + + _buf_alloc_count++; + return ptr; +} + +/* + * Function: mpool_init + * + * Purpose: + * Initialize mpool lock. + * Parameters: + * None + * Returns: + * Always 0 + */ +int +mpool_init(void) +{ + int i; + + MPOOL_LOCK_INIT(); + _buf_alloc_count = 0; + _mpool_count = 0; + for (i = 0; i < MPOOL_BUF_ALLOC_COUNT_MAX; i++) { + mpool_buf[i] = NULL; + } + free_list = NULL; + return 0; +} + +#ifdef TRACK_DMA_USAGE +static int _dma_mem_used = 0; +#endif + +/* + * Function: mpool_alloc + * + * Purpose: + * Allocate memory block from mpool. + * Parameters: + * pool - mpool handle (from mpool_create) + * size - size of memory block to allocate + * Returns: + * Pointer to allocated memory block or NULL if allocation fails. + */ +void * +mpool_alloc(mpool_handle_t pool, int size) +{ + mpool_mem_t *ptr = pool, *newptr = NULL; + int mod; + + MPOOL_LOCK(); + + if (size < BCM_CACHE_LINE_BYTES) { + size = BCM_CACHE_LINE_BYTES; + } + + mod = size & (BCM_CACHE_LINE_BYTES - 1); + if (mod != 0) { + size += (BCM_CACHE_LINE_BYTES - mod); + } + while (ptr && ptr->next) { + if (ptr->next->address - (ptr->address + ptr->size) >= size) { + break; + } + ptr = ptr->next; + } + + if (!(ptr && ptr->next)) { + MPOOL_UNLOCK(); + return NULL; + } + + if (!free_list && !_mpool_buf_create()) { + MPOOL_UNLOCK(); + return NULL; + } + + newptr = free_list; + free_list = free_list->next; + + newptr->address = ptr->address + ptr->size; + newptr->size = size; + newptr->next = ptr->next; + newptr->prev = ptr; + ptr->next->prev = newptr; + ptr->next = newptr; +#ifdef TRACK_DMA_USAGE + _dma_mem_used += size; +#endif + + MPOOL_UNLOCK(); + return newptr->address; +} + + +/* + * Function: mpool_free + * + * Purpose: + * Free memory block allocated from mpool.. + * Parameters: + * pool - mpool handle (from mpool_create) + * addr - address of memory block to free + * Returns: + * Nothing + */ +void +mpool_free(mpool_handle_t pool, void *addr) +{ + unsigned char *address = (unsigned char *)addr; + mpool_mem_t *head = pool, *ptr = NULL; + + MPOOL_LOCK(); + + if (!(head && head->prev)) { + MPOOL_UNLOCK(); + return; + } + + ptr = head->prev->prev; + + while (ptr && (ptr != head)) { + if (ptr->address == address) { +#ifdef TRACK_DMA_USAGE + _dma_mem_used -= ptr->size; +#endif + ptr->prev->next = ptr->next; + ptr->next->prev = ptr->prev; + ptr->next = free_list; + free_list = ptr; + break; + } + ptr = ptr->prev; + } + + MPOOL_UNLOCK(); +} + +/* + * Function: mpool_create + * + * Purpose: + * Create and initialize mpool control structures. + * Parameters: + * base_ptr - pointer to mpool memory block + * size - total size of mpool memory block + * Returns: + * mpool handle + * Notes + * The mpool handle returned must be used for subsequent + * memory allocations from the mpool. + */ +mpool_handle_t +mpool_create(void *base_ptr, int size) +{ + mpool_mem_t *head, *tail; + int mod = (int)(((unsigned long)base_ptr) & (BCM_CACHE_LINE_BYTES - 1)); + + MPOOL_LOCK(); + + if (!free_list || !(free_list->next)) { + if (!_mpool_buf_create()) { + MPOOL_UNLOCK(); + return NULL; + } + } + + if (mod) { + base_ptr = (char*)base_ptr + (BCM_CACHE_LINE_BYTES - mod); + size -= (BCM_CACHE_LINE_BYTES - mod); + } + size &= ~(BCM_CACHE_LINE_BYTES - 1); + + head = free_list; + free_list = free_list->next; + tail = free_list; + free_list = free_list->next; + + head->size = tail->size = 0; + head->address = base_ptr; + tail->address = head->address + size; + head->prev = tail; + head->next = tail; + tail->prev = head; + tail->next = NULL; + _mpool_count++; + + MPOOL_UNLOCK(); + return head; +} + +/* + * Function: mpool_destroy + * + * Purpose: + * Free mpool control structures. + * Parameters: + * pool - mpool handle (from mpool_create) + * Returns: + * Always 0 + */ +int +mpool_destroy(mpool_handle_t pool) +{ + int i; + mpool_mem_t *head = pool; + + MPOOL_LOCK(); + + if (!(head && head->prev)) { + MPOOL_UNLOCK(); + return 0; + } + + head->prev->next = free_list; + free_list = head; + _mpool_count--; + + if (_mpool_count == 0) { + for (i = 0; i < MPOOL_BUF_ALLOC_COUNT_MAX; i++) { + if (mpool_buf[i]) { + FREE(mpool_buf[i]); + mpool_buf[i] = NULL; + } + } + free_list = NULL; + } + + MPOOL_UNLOCK(); + + return 0; +} + +/* + * Function: mpool_usage + * + * Purpose: + * Report total sum of allocated mpool memory. + * Parameters: + * pool - mpool handle (from mpool_create) + * Returns: + * Number of bytes currently allocated using mpool_alloc. + */ +int +mpool_usage(mpool_handle_t pool) +{ + int usage = 0; + mpool_mem_t *ptr; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = ptr->next) { + usage += ptr->size; + } + + MPOOL_UNLOCK(); + + return usage; +} diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/Makefile b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/Makefile new file mode 100644 index 000000000000..2cc96df02d0a --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/Makefile @@ -0,0 +1,81 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.1 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/bde/linux/user/kernel + +# Make sure we build for the kernel if this is a user-mode build +ifneq ($(platform), ) +override-target=linux-$(platform) +endif + +include $(SDK)/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +ifneq ($(kernel_version),2_4) +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := linux-user-bde +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: kernel_libs $(MODULE) $(KMODULE) +else +MODULE = $(LIBDIR)/linux-user-bde.o + +build: kernel_libs $(MODULE) +endif + +KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../../kernel/kernel_module/Module.symvers + +$(MODULE): $(BLDDIR)/.tree $(BOBJS) $(LIBS) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + cat ${KBUILD_EXTRA_SYMBOLS} > $(BLDDIR)/$(KERNEL_MODULE_DIR)/Module.symvers + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +kernel_libs: + $(MAKE) -C $(SDK)/systems/linux/kernel/modules/shared + +include $(SDK)/make/Make.depend + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +clean:: + $(MAKE) -C $(SDK)/systems/linux/kernel/modules/shared $@ + $(RM) $(BOBJS) $(MODULE) + +.PHONY: build kernel_libs diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c new file mode 100644 index 000000000000..4e6186e2d80d --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c @@ -0,0 +1,1887 @@ +/* + * Copyright 2017 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ + +/* + * Linux User BDE Helper Module + */ +#include +#include +#include + +#include +#include +#include +#include +#include "linux-user-bde.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) +#include +#endif + +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("User BDE Helper Module"); +MODULE_LICENSE("GPL"); + +/* CMIC/CMICe defines */ +#define CMIC_IRQ_STAT 0x00000144 +#define CMIC_IRQ_MASK 0x00000148 +#define CMIC_IRQ_MASK_1 0x0000006C +#define CMIC_IRQ_MASK_2 0x00000070 + +/* CMICm defines */ +#define CMIC_CMCx_IRQ_STAT0_OFFSET(x) (0x31400 + (0x1000 * x)) +#define CMIC_CMCx_IRQ_STAT1_OFFSET(x) (0x31404 + (0x1000 * x)) +#define CMIC_CMCx_IRQ_STAT2_OFFSET(x) (0x31408 + (0x1000 * x)) +#define CMIC_CMCx_IRQ_STAT3_OFFSET(x) (0x3140c + (0x1000 * x)) +#define CMIC_CMCx_IRQ_STAT4_OFFSET(x) (0x31410 + (0x1000 * x)) + +#define CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(x) (0x31414 + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(x) (0x31418 + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(x) (0x3141c + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(x) (0x31420 + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(x) (0x31424 + (0x1000 * x)) + +/* CMICd defines */ +#define CMIC_CMCx_IRQ_STAT5_OFFSET(x) (0x314b0 + (0x1000 * x)) +#define CMIC_CMCx_IRQ_STAT6_OFFSET(x) (0x314b4 + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(x) (0x314b8 + (0x1000 * x)) +#define CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(x) (0x314bc + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(x) (0x314c0 + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(x) (0x314c4 + (0x1000 * x)) + +#define CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(x) (0x31428 + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(x) (0x3142c + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(x) (0x31430 + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(x) (0x31434 + (0x1000 * x)) +#define CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(x) (0x31438 + (0x1000 * x)) + +/* CMICX defines */ +#define INTC_INTR_REG_NUM (8) +#define PAXB_INTRCLR_DELAY_REG_NUM (16) +/* +TODO:HX5 +The INTR base address values are changed for HX5, +hence making new #defines so runtime decisions can +be made. +*/ +#define PAXB_0_PAXB_IC_INTRCLR_0 (0x180123a0) +#define PAXB_0_PAXB_IC_INTRCLR_1 (0x180123a4) +#define PAXB_0_PAXB_IC_INTRCLR_MODE_0 (0x180123a8) +#define PAXB_0_PAXB_IC_INTRCLR_MODE_1 (0x180123ac) +#define PAXB_0_PAXB_INTR_STATUS (0x18012f38) +#define PAXB_0_PAXB_IC_INTR_PACING_CTRL (0x18012398) +#define PAXB_0_PAXB_INTRCLR_DELAY_UNIT (0x1801239c) +#define PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0 (0x180123b0) +#define PAXB_0_PCIE_ERROR_STATUS (0x18012024) + +#define HX5_PAXB_0_PAXB_IC_INTRCLR_0 (0x102303a0) +#define HX5_PAXB_0_PAXB_IC_INTRCLR_1 (0x102303a4) + +#define HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_0 (0x102303a8) +#define HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_1 (0x102303ac) +#define HX5_PAXB_0_PAXB_INTR_STATUS (0x10230f38) +#define HX5_PAXB_0_PAXB_IC_INTR_PACING_CTRL (0x10230398) +#define HX5_PAXB_0_PAXB_INTRCLR_DELAY_UNIT (0x1023039c) +#define HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0 (0x102303b0) +#define HX5_PAXB_0_PCIE_ERROR_STATUS (0x10230024) + +#define PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE (PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0) +#define HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE (HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0) + +#define INTC_INTR_ENABLE_REG0 (0x180130f0) +#define INTC_INTR_STATUS_REG0 (0x18013190) +#define INTC_INTR_RAW_STATUS_REG0 (0x18013140) + +#define INTC_INTR_ENABLE_BASE (INTC_INTR_ENABLE_REG0) +#define INTC_INTR_STATUS_BASE (INTC_INTR_STATUS_REG0) +#define INTC_INTR_RAW_STATUS_BASE (INTC_INTR_RAW_STATUS_REG0) + +#define HX5_INTC_INTR_ENABLE_REG0 (0x102310f0) +#define HX5_INTC_INTR_STATUS_REG0 (0x10231190) +#define HX5_INTC_INTR_RAW_STATUS_REG0 (0x10231140) + +#define HX5_INTC_INTR_ENABLE_BASE (HX5_INTC_INTR_ENABLE_REG0) +#define HX5_INTC_INTR_STATUS_BASE (HX5_INTC_INTR_STATUS_REG0) +#define HX5_INTC_INTR_RAW_STATUS_BASE (HX5_INTC_INTR_RAW_STATUS_REG0) + +#define IOREMAP(addr, size) ioremap_nocache(addr, size) + +#define HX5_IHOST_GICD_ISENABLERN_0 (0x10781100) +#define HX5_IHOST_GICD_ISENABLERN_1 (0x10781104) +#define HX5_IHOST_GICD_ICENABLERN_1 (0x10781184) +#define HX5_IHOST_GICD_ICENABLERN_8 (0x107811a0) +#define HX5_IHOST_GICD_ISPENDRN_8 (0x10781220) +/* Offset between ISENABLERN_1 and ICENABLERN_1 in 4-bytes */ +#define HX5_IHOST_IRQ_MASK_OFFSET 0x20 +/* Offset between ISENABLERN_1 and ISPENDRN_1 in 4-bytes */ +#define HX5_IHOST_IRQ_PEND_OFFSET 0x40 +#define HX5_IHOST_INTR_MAP_NUM (HX5_IHOST_GICD_ISPENDRN_8 - HX5_IHOST_GICD_ISENABLERN_0) +#define HX5_IHOST_INTR_STATUS_MAP_NUM (INTC_INTR_REG_NUM * (sizeof(uint32))) +#define IRQ_BIT(intr) (intr % (sizeof(uint32)*8)) +#define IRQ_MASK_INDEX(intr) (intr / (sizeof(uint32)*8)) +#define HX5_SW_PROG_INTR_PRIORITY 73 +#define INTR_SW_PROG_INTR_BITPOS (1 << IRQ_BIT(HX5_SW_PROG_INTR_PRIORITY)) +#define INTC_SW_PROG_INTR_REG_IND IRQ_MASK_INDEX(HX5_SW_PROG_INTR_PRIORITY) +#define HX5_CHIP_INTR_LOW_PRIORITY 119 +#define INTR_LOW_PRIORITY_BITPOS (1 << IRQ_BIT(HX5_CHIP_INTR_LOW_PRIORITY)) +#define INTC_LOW_PRIORITY_INTR_REG_IND IRQ_MASK_INDEX(HX5_CHIP_INTR_LOW_PRIORITY) +#define INTC_PDMA_INTR_REG_IND 4 + +#define IPROC_READ(d, reg, v) \ + (v = user_bde->iproc_read(d, reg)) +#define IPROC_WRITE(d, reg, v) \ + (user_bde->iproc_write(d, reg, v)) + +#define IHOST_READ_INTR(d, reg, v) \ + (v = readl((reg))) +#define IHOST_WRITE_INTR(d, reg, v) \ + (writel((v), (reg))) + +/* Allow override of default CMICm CMC */ +#ifndef BDE_CMICM_PCIE_CMC +#define BDE_CMICM_PCIE_CMC 0 +#endif + +/* Allow override of default CMICm CMC */ +#ifndef BDE_CMICD_PCIE_CMC +#define BDE_CMICD_PCIE_CMC 0 +#endif + +/* Defines used to distinguish CMICe from CMICm */ +#define CMICE_DEV_REV_ID (0x178 / sizeof(uint32)) + +static uint32 *ihost_intr_status_base = NULL; +static uint32 *ihost_intr_enable_base = NULL; + +/* Module parameter for Interruptible timeout */ +static int intr_timeout = 0; +LKM_MOD_PARAM(intr_timeout, "i", int, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(intr_timeout, +"Interruptible wait timeout in milliseconds for Interrupt to be triggered."); + +static ulong intr_count = 0; +LKM_MOD_PARAM(intr_count, "intr_count", ulong, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(intr_count, +"Interrupt count provides information about the number of times the ISR is called."); + +static ulong intr_timeout_count = 0; +LKM_MOD_PARAM(intr_timeout_count, "intr_timeout_count", ulong, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(intr_timeout_count, +"Interrupt timeout count provides information about the number of times the interrupt wait is timeed out."); + +/* Debug output */ +static int debug; +LKM_MOD_PARAM(debug, "i", int, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(debug, +"Set debug level (default 0)."); + +static ibde_t *user_bde = NULL; + +typedef void (*isr_f)(void *); + +typedef struct _intr_regs_s { + uint32 intc_intr_status_base; + uint32 intc_intr_enable_base; + uint32 intc_intr_raw_status_base; + uint32 intc_intr_clear_0; + uint32 intc_intr_clear_1; + uint32 intc_intr_clear_mode_0; + uint32 intc_intr_clear_mode_1; + uint32 intc_intr_status; + uint32 intc_intr_pacing_ctrl; + uint32 intc_intr_clear_delay_unit; + uint32 intc_intr_clear_delay_base; + uint32 intc_intr_pcie_err_status; +} _intr_regs_t; + +typedef struct bde_ctrl_s { + uint32 dev_type; + int irq; + int enabled; + int devid; + isr_f isr; + uint32 *ba; + uint32 inst; /* the resource/instance index in _bde_inst_resource[] */ + int edk_irq_enabled; + _intr_regs_t intr_regs; +} bde_ctrl_t; + +#define VALID_DEVICE(_n) (_n < LINUX_BDE_MAX_DEVICES) + +static bde_ctrl_t _devices[LINUX_BDE_MAX_DEVICES]; + +static wait_queue_head_t _ether_interrupt_wq; +static atomic_t _ether_interrupt_has_taken_place = ATOMIC_INIT(0); + +/* + * Multiple instance resource data structure. + * To keep the DMA resource per instance. + * And track the DMA pool usage. + */ +static int _bde_multi_inst = 0; + +#define MAX_UC_CORES LINUX_BDE_MAX_IPROC_UC_CORES + +/* Structure to hold info about interrupts handled by EDK */ +typedef struct { + uint32_t timer_intrc_offset; /* Timer interrupts INTC offset */ + uint32_t timer_intrc_mask; /* Timer interrupts mask */ + uint32_t sw_intr_intrc_offset; /* SW Programmable Interrupt's offset */ + uint32_t sw_intr_intrc_mask; /* SW interrupt's mask */ + uint32_t sw_intr_src_bitmap; /* SW interrupt's bitmask to navigate ICFG registers */ + uint32_t sw_intr_icfg_reg[MAX_UC_CORES]; /* ICFG registers for each core */ +} bde_edk_intr_t; + +typedef struct { + int is_active; /* Is the instance active */ + unsigned int dma_offset; /* offset of the instance's DMA memory in the DMA buffer pool */ + unsigned int dma_size; /* size of the instance's DMA memory (in the DMA buffer pool) */ + wait_queue_head_t intr_wq; + wait_queue_head_t edk_intr_wq; + atomic_t intr; + atomic_t edk_intr; + bde_edk_intr_t edk_irqs; +} bde_inst_resource_t; + +/* This array contains information for SDK instance, the index in the array is the instance ID */ +static bde_inst_resource_t _bde_inst_resource[LINUX_BDE_MAX_DEVICES]; +/* + * Lock used to protect changes to _bde_inst_resource + */ +static spinlock_t bde_resource_lock; + + +typedef struct { + phys_addr_t cpu_pbase; /* CPU physical base address of the DMA pool */ + phys_addr_t dma_pbase; /* Bus base address of the DMA pool */ + uint32 total_size; /* Total size of the pool in MB */ + uint32 offset; /* Current offset of the pool in MB */ +}_dma_pool_t; + +static _dma_pool_t _dma_pool; + +#define ONE_MB (1024 * 1024) + +#ifdef KEYSTONE +/* + * Enforce PCIE transaction ordering. Commit the write transaction. + */ + +#define SSOC_WRITEL(val, addr) \ + do { \ + writel((val), (addr)); \ + __asm__ __volatile__("sync"); \ + } while(0) + +#else + +#define SSOC_WRITEL(val, addr) \ + writel((val), (addr)) + +#endif +/* + * Function: _interrupt + * + * Purpose: + * Interrupt Handler. + * Mask all interrupts on device and wake up interrupt + * thread. It is assumed that the interrupt thread unmasks + * interrupts again when interrupt handling is complete. + * Parameters: + * ctrl - BDE control structure for this device. + * Returns: + * Nothing + */ +static void +_cmic_interrupt(bde_ctrl_t *ctrl) +{ + int d; + uint32_t mask = 0, stat, imask = 0, fmask = 0; + bde_inst_resource_t *res; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + res = &_bde_inst_resource[ctrl->inst]; + + /* Check for secondary interrupt handler */ + if (lkbde_irq_mask_get(d, &mask, &fmask) < 0) { + fmask = 0; + } + + if (fmask != 0) { + imask = mask & ~fmask; + /* Check for pending user mode interrupts */ + stat = user_bde->read(d, CMIC_IRQ_STAT); + if ((stat & imask) == 0) { + /* All handled in kernel mode */ + lkbde_irq_mask_set(d, CMIC_IRQ_MASK, imask, 0); + return; + } + } + + lkbde_irq_mask_set(d, CMIC_IRQ_MASK, 0, 0); + + atomic_set(&res->intr, 1); + +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +void +dump_interrupt_regs(bde_ctrl_t *ctrl , int dev) +{ + int ind; + uint32_t val; + + if (debug >= 2) { + gprintk("Interrupt timeout count = %lu\n", intr_timeout_count); + gprintk("Interrupt count = %lu\n", intr_count); + for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { + IPROC_READ(dev, ctrl->intr_regs.intc_intr_status_base + 4 * ind, val); + gprintk("INTC_INTR_STATUS_REG_%d = 0x%x\n", ind, val); + IPROC_READ(dev, ctrl->intr_regs.intc_intr_raw_status_base + 4 * ind, val); + gprintk("INTC_INTR_RAW_STATUS_REG_%d = 0x%x\n", ind, val); + IPROC_READ(dev, ctrl->intr_regs.intc_intr_enable_base + 4 * ind, val); + gprintk("INTC_INTR_ENABLE_REG_%d = 0x%x\n", ind, val); + } + /* Dump PAXB Register */ + IPROC_READ(dev, ctrl->intr_regs.intc_intr_status, val); + gprintk("PAXB_0_PAXB_INTR_STATUS = 0x%x\n", val); + IPROC_READ(dev, ctrl->intr_regs.intc_intr_pacing_ctrl, val); + gprintk("PAXB_0_PAXB_IC_INTR_PACING_CTRL = 0x%x\n", val); + IPROC_READ(dev, ctrl->intr_regs.intc_intr_clear_delay_unit, val); + gprintk("PAXB_0_PAXB_INTRCLR_DELAY_UNIT = 0x%x\n", val); + IPROC_READ(dev, ctrl->intr_regs.intc_intr_pcie_err_status, val); + gprintk("PAXB_0_PCIE_ERROR_STATUS = 0x%x\n", val); + + for (ind = 0; ind < PAXB_INTRCLR_DELAY_REG_NUM; ind++) { + IPROC_READ(dev, ctrl->intr_regs.intc_intr_clear_delay_base + 4 * ind, val); + gprintk("PAXB_0_PAXB_IC_INTRCLR_DELAY_REG_%d = 0x%x\n", ind, val); + } + } + /* Clear interrupt enable registers */ + for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { + IPROC_WRITE(dev, ctrl->intr_regs.intc_intr_enable_base + 4 * ind, 0); + } +} + +#ifdef BDE_EDK_SUPPORT +static int +_cmicx_edk_interrupt_check(bde_ctrl_t *ctrl, int d) +{ + bde_inst_resource_t *res; + uint32 stat, mask = 0, bitmap = 0; + int idx; + + res = &_bde_inst_resource[ctrl->inst]; + bitmap = res->edk_irqs.sw_intr_src_bitmap; + + /* Explicitly reading raw_status so as to not clear the status on read */ + IPROC_READ(d, ctrl->intr_regs.intc_intr_raw_status_base + + (res->edk_irqs.sw_intr_intrc_offset * 4), stat); + /* Check whether Software Programmable Interrupt is set */ + if (stat & res->edk_irqs.sw_intr_intrc_mask) { + for (idx = 0; (bitmap && (idx < MAX_UC_CORES)); idx++) { + if (bitmap & 1) { + IPROC_READ(d, res->edk_irqs.sw_intr_icfg_reg[idx], stat); + mask |= (stat & 1) << idx; + } + bitmap = (bitmap >> 1); + } + if (mask) + return 1; + } + + /* EDK uses timer interrupt as watchdog to indicate the the firmware has crashed */ + IPROC_READ(d, ctrl->intr_regs.intc_intr_raw_status_base + + (res->edk_irqs.timer_intrc_offset * 4), stat); + if (stat & res->edk_irqs.timer_intrc_mask) { + return 1; + } + return 0; +} +#endif + +static int +_cmicx_interrupt_prepare(bde_ctrl_t *ctrl) +{ + int d, ind, ret = 0; + uint32 stat, iena, mask, fmask; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + + if (ctrl->dev_type & BDE_PCI_DEV_TYPE) { + IPROC_READ(d, ctrl->intr_regs.intc_intr_clear_mode_0, stat); + /* Clear MSI interrupts immediately to prevent spurious interrupts */ + if (stat == 0) { + IPROC_WRITE(d, ctrl->intr_regs.intc_intr_clear_0, 0xFFFFFFFF); + IPROC_WRITE(d, ctrl->intr_regs.intc_intr_clear_1, 0xFFFFFFFF); + } + } + + lkbde_irq_mask_get(d, &mask, &fmask); + + if (fmask) { + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + IHOST_READ_INTR(d, ihost_intr_status_base + INTC_PDMA_INTR_REG_IND, stat); + IHOST_READ_INTR(d, ihost_intr_enable_base + INTC_PDMA_INTR_REG_IND, iena); + } else { + IPROC_READ(d, ctrl->intr_regs.intc_intr_status_base + 4 * INTC_PDMA_INTR_REG_IND, stat); + IPROC_READ(d, ctrl->intr_regs.intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, iena); + } + if (stat & iena) { + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_PDMA_INTR_REG_IND + + HX5_IHOST_IRQ_MASK_OFFSET, ~0); + } else { + IPROC_WRITE(d, ctrl->intr_regs.intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, 0); + } + + for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { + if (ind == INTC_PDMA_INTR_REG_IND) { + continue; + } + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + if (ind < INTC_SW_PROG_INTR_REG_IND) { + continue; + } + if (ind == INTC_SW_PROG_INTR_REG_IND) { + IHOST_READ_INTR(d, ihost_intr_enable_base + ind + HX5_IHOST_IRQ_PEND_OFFSET, stat); + stat &= INTR_SW_PROG_INTR_BITPOS; + } else { + IHOST_READ_INTR(d, ihost_intr_status_base + ind, stat); + if (ind == INTC_LOW_PRIORITY_INTR_REG_IND) { + stat &= INTR_LOW_PRIORITY_BITPOS; + } + } + } else { + IPROC_READ(d, ctrl->intr_regs.intc_intr_status_base + 4 * ind, stat); + IPROC_READ(d, ctrl->intr_regs.intc_intr_enable_base + 4 * ind, iena); + } + if (stat & iena) { + break; + } + } + /* No pending interrupts */ + if (ind >= INTC_INTR_REG_NUM) { + return -1; + } + } + } + + /* Disable all interrupts.. Re-enable unserviced interrupts later + * So as to avoid getting new interrupts until the user level driver + * enumerates the interrupts to be serviced + */ +#ifdef BDE_EDK_SUPPORT + if (ctrl->edk_irq_enabled) + ret = _cmicx_edk_interrupt_check(ctrl, d); +#endif + + for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { + if (fmask && ind == INTC_PDMA_INTR_REG_IND) { + continue; + } + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + if (ind < INTC_SW_PROG_INTR_REG_IND) { + continue; + } + if (ind == INTC_SW_PROG_INTR_REG_IND) { + IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_SW_PROG_INTR_REG_IND + + HX5_IHOST_IRQ_MASK_OFFSET, INTR_SW_PROG_INTR_BITPOS); + } else if (ind == INTC_LOW_PRIORITY_INTR_REG_IND) { + IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_LOW_PRIORITY_INTR_REG_IND + + HX5_IHOST_IRQ_MASK_OFFSET, INTR_LOW_PRIORITY_BITPOS); + } else { + IHOST_WRITE_INTR(d, ihost_intr_enable_base + ind + + HX5_IHOST_IRQ_MASK_OFFSET, ~0); + } + } else { + IPROC_WRITE(d, ctrl->intr_regs.intc_intr_enable_base + (4 * ind), 0); + } + } + + return ret; +} + +static void +_cmicx_interrupt(bde_ctrl_t *ctrl) +{ + bde_inst_resource_t *res; + int ret; + + intr_count++; + + res = &_bde_inst_resource[ctrl->inst]; + ret = _cmicx_interrupt_prepare(ctrl); + if (ret < 0) { + return; + } else if (ret > 0) { + /* Notify */ + atomic_set(&res->edk_intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->edk_intr_wq); +#else + wake_up_interruptible(&res->edk_intr_wq); +#endif + } else { + /* Notify */ + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif + } +} + +static void +_cmicm_interrupt(bde_ctrl_t *ctrl) +{ + int d; + int cmc = BDE_CMICM_PCIE_CMC; + uint32 stat, mask = 0, fmask = 0, imask = 0; + bde_inst_resource_t *res; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + res = &_bde_inst_resource[ctrl->inst]; + + lkbde_irq_mask_get(d, &mask, &fmask); + + while (fmask) { + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); + imask = mask & ~fmask; + if (stat & imask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + return; + } + + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(1), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(2), 0); + } + else { + lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(1), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(2), 0); + } + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +/* some device has cmc0 only */ +static void +_cmicd_cmc0_interrupt(bde_ctrl_t *ctrl) +{ + int d; + int cmc = 0; + uint32 stat, mask = 0, fmask = 0, imask = 0; + bde_inst_resource_t *res; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + res = &_bde_inst_resource[ctrl->inst]; + lkbde_irq_mask_get(d, &mask, &fmask); + + while (fmask) { + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); + imask = mask & ~fmask; + if (stat & imask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT5_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT6_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + return; + } + + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc), 0); + } else { + lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), 0); + } + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + +static void +_cmicd_interrupt(bde_ctrl_t *ctrl) +{ + int d; + int cmc = BDE_CMICD_PCIE_CMC; + uint32 stat, mask = 0, fmask = 0, imask = 0; + bde_inst_resource_t *res; + + d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); + res = &_bde_inst_resource[ctrl->inst]; + lkbde_irq_mask_get(d, &mask, &fmask); + + while (fmask) { + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); + imask = mask & ~fmask; + if (stat & imask) { + break; + } + /** Check if there are interrupts other than PacketIO interrupts on CMC1 */ + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(1)); + imask = mask & ~fmask; + if (stat & imask) { + break; + } + /** Check if there are interrupts other than PacketIO interrupts on CMC2 */ + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(2)); + imask = mask & ~fmask; + if (stat & imask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT5_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT6_OFFSET(cmc)); + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc)); + } else { + mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc)); + } + if (stat & mask) { + break; + } + return; + } + + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(1), 0); + user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(2), 0); + } else { + lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(1), 0); + user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(2), 0); + } + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif +} + + +/* The actual interrupt handler of ethernet devices */ +static void +_ether_interrupt(bde_ctrl_t *ctrl) +{ + SSOC_WRITEL(0, ctrl->ba + 0x024/4); + + atomic_set(&_ether_interrupt_has_taken_place, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&_ether_interrupt_wq); +#else + wake_up_interruptible(&_ether_interrupt_wq); +#endif +} + + +static struct _intr_mode_s { + isr_f isr; + const char *name; +} _intr_mode[] = { + { (isr_f)_cmic_interrupt, "CMIC/CMICe" }, + { (isr_f)_cmicm_interrupt, "CMICm" }, + { (isr_f)_cmicd_interrupt, "CMICd" }, + { (isr_f)_cmicd_cmc0_interrupt, "CMICd CMC0" }, + { (isr_f)_cmicx_interrupt, "CMICx" }, + { NULL, NULL } +}; + +static const char * +_intr_mode_str(void *isr) +{ + int imx; + + imx = 0; + while (_intr_mode[imx].isr != NULL) { + if (isr == _intr_mode[imx].isr) { + return _intr_mode[imx].name; + } + imx++; + } + return NULL; +} + +static void +_intr_regs_init(bde_ctrl_t *ctrl, int hx5_intr) +{ + if (hx5_intr) { + ctrl->intr_regs.intc_intr_status_base = HX5_INTC_INTR_STATUS_BASE; + ctrl->intr_regs.intc_intr_enable_base = HX5_INTC_INTR_ENABLE_BASE; + ctrl->intr_regs.intc_intr_raw_status_base = HX5_INTC_INTR_RAW_STATUS_BASE; + ctrl->intr_regs.intc_intr_clear_0 = HX5_PAXB_0_PAXB_IC_INTRCLR_0; + ctrl->intr_regs.intc_intr_clear_1 = HX5_PAXB_0_PAXB_IC_INTRCLR_1; + ctrl->intr_regs.intc_intr_clear_mode_0 = HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_0; + ctrl->intr_regs.intc_intr_clear_mode_1 = HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_1; + ctrl->intr_regs.intc_intr_status = HX5_PAXB_0_PAXB_INTR_STATUS; + ctrl->intr_regs.intc_intr_pacing_ctrl = HX5_PAXB_0_PAXB_IC_INTR_PACING_CTRL; + ctrl->intr_regs.intc_intr_clear_delay_unit = HX5_PAXB_0_PAXB_INTRCLR_DELAY_UNIT; + ctrl->intr_regs.intc_intr_clear_delay_base = HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE; + ctrl->intr_regs.intc_intr_pcie_err_status = HX5_PAXB_0_PCIE_ERROR_STATUS; + + } else { + ctrl->intr_regs.intc_intr_status_base = INTC_INTR_STATUS_BASE; + ctrl->intr_regs.intc_intr_raw_status_base = INTC_INTR_RAW_STATUS_BASE; + ctrl->intr_regs.intc_intr_enable_base = INTC_INTR_ENABLE_BASE; + ctrl->intr_regs.intc_intr_clear_0 = PAXB_0_PAXB_IC_INTRCLR_0; + ctrl->intr_regs.intc_intr_clear_1 = PAXB_0_PAXB_IC_INTRCLR_1; + ctrl->intr_regs.intc_intr_clear_mode_0 = PAXB_0_PAXB_IC_INTRCLR_MODE_0; + ctrl->intr_regs.intc_intr_clear_mode_1 = PAXB_0_PAXB_IC_INTRCLR_MODE_1; + ctrl->intr_regs.intc_intr_status = PAXB_0_PAXB_INTR_STATUS; + ctrl->intr_regs.intc_intr_pacing_ctrl = PAXB_0_PAXB_IC_INTR_PACING_CTRL; + ctrl->intr_regs.intc_intr_clear_delay_unit = PAXB_0_PAXB_INTRCLR_DELAY_UNIT; + ctrl->intr_regs.intc_intr_clear_delay_base = PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE; + ctrl->intr_regs.intc_intr_pcie_err_status = PAXB_0_PCIE_ERROR_STATUS; + + } +} + +static void +_devices_init(int d) +{ + bde_ctrl_t *ctrl; + uint32 ver; + uint16 device_id_mask = 0xFFF0; + uint16 device_id; + uint32 state = 0; + + (void)lkbde_dev_state_get(d, &state); + if (state == BDE_DEV_STATE_REMOVED) { + return; + } + + ctrl = &_devices[d]; + /* Initialize our control info */ + ctrl->dev_type = user_bde->get_dev_type(d); + ctrl->devid = user_bde->get_dev(d)->device; + ctrl->inst = 0; + + if (BDE_DEV_MEM_MAPPED(ctrl->dev_type)) { + ctrl->enabled = 0; + ctrl->ba = lkbde_get_dev_virt(d); + } + if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) { + switch (user_bde->get_dev(d)->device) { + case BCM53540_DEVICE_ID: + case BCM53547_DEVICE_ID: + case BCM53548_DEVICE_ID: + case BCM53549_DEVICE_ID: + ctrl->isr = (isr_f)_cmicd_cmc0_interrupt; + break; + case BCM88670_DEVICE_ID: + case BCM88671_DEVICE_ID: + case BCM88671M_DEVICE_ID: + case BCM88672_DEVICE_ID: + case BCM88673_DEVICE_ID: + case BCM88674_DEVICE_ID: + case BCM88675_DEVICE_ID: + case BCM88675M_DEVICE_ID: + case BCM88676_DEVICE_ID: + case BCM88676M_DEVICE_ID: + case BCM88677_DEVICE_ID: + case BCM88678_DEVICE_ID: + case BCM88679_DEVICE_ID: + case BCM88370_DEVICE_ID: + case BCM88371_DEVICE_ID: + case BCM88371M_DEVICE_ID: + case BCM88375_DEVICE_ID: + case BCM88376_DEVICE_ID: + case BCM88376M_DEVICE_ID: + case BCM88377_DEVICE_ID: + case BCM88378_DEVICE_ID: + case BCM88379_DEVICE_ID: + case BCM88681_DEVICE_ID: + case BCM88682_DEVICE_ID: + case BCM88683_DEVICE_ID: + case BCM88684_DEVICE_ID: + case BCM88685_DEVICE_ID: + case BCM88687_DEVICE_ID: + case BCM88380_DEVICE_ID: + case BCM88381_DEVICE_ID: + case BCM88680_DEVICE_ID: + case BCM88770_DEVICE_ID: + case BCM88773_DEVICE_ID: + case BCM88774_DEVICE_ID: + case BCM88775_DEVICE_ID: + case BCM88776_DEVICE_ID: + case BCM88777_DEVICE_ID: + case BCM88470_DEVICE_ID: + case BCM88470P_DEVICE_ID: + case BCM88471_DEVICE_ID: + case BCM88473_DEVICE_ID: + case BCM88474_DEVICE_ID: + case BCM88474H_DEVICE_ID: + case BCM88476_DEVICE_ID: + case BCM88477_DEVICE_ID: + case BCM88270_DEVICE_ID: + case BCM88272_DEVICE_ID: + case BCM88273_DEVICE_ID: + case BCM88274_DEVICE_ID: + case BCM88278_DEVICE_ID: + case BCM88279_DEVICE_ID: + case BCM8206_DEVICE_ID: + case BCM88950_DEVICE_ID: + case BCM88953_DEVICE_ID: + case BCM88954_DEVICE_ID: + case BCM88955_DEVICE_ID: + case BCM88956_DEVICE_ID: + case BCM88772_DEVICE_ID: + case BCM88952_DEVICE_ID: + ctrl->isr = (isr_f)_cmicd_interrupt; + break; + case BCM56370_DEVICE_ID: + case BCM56371_DEVICE_ID: + case BCM56372_DEVICE_ID: + case BCM56374_DEVICE_ID: + case BCM56375_DEVICE_ID: + case BCM56376_DEVICE_ID: + case BCM56377_DEVICE_ID: + case BCM56577_DEVICE_ID: + case BCM56578_DEVICE_ID: + case BCM56579_DEVICE_ID: + case BCM56273_DEVICE_ID: + case BCM56274_DEVICE_ID: + case BCM56275_DEVICE_ID: + case BCM56276_DEVICE_ID: + case BCM56277_DEVICE_ID: + case BCM56278_DEVICE_ID: + case BCM56279_DEVICE_ID: + case BCM56575_DEVICE_ID: + case BCM56175_DEVICE_ID: + case BCM56176_DEVICE_ID: + ctrl->isr = (isr_f)_cmicx_interrupt; + if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { + if (!ihost_intr_enable_base) { + ihost_intr_enable_base = (uint32_t *)IOREMAP(HX5_IHOST_GICD_ISENABLERN_1, + HX5_IHOST_INTR_MAP_NUM); + } + if (!ihost_intr_status_base) { + ihost_intr_status_base = (uint32_t *)IOREMAP(HX5_INTC_INTR_RAW_STATUS_REG0, + HX5_IHOST_INTR_STATUS_MAP_NUM); + } + } + _intr_regs_init(ctrl, 1); + break; + default: + /* Get CMIC version */ + if (user_bde->get_cmic_ver(d, &ver) != 0) { + ver = -1; + } + device_id = ctrl->devid & device_id_mask; + /* TH/TH+/TH2 should use cmicd interrupt handler */ + if (BCM56960_DEVICE_ID == device_id || + BCM56930_DEVICE_ID == device_id || + BCM56970_DEVICE_ID == device_id) { + ctrl->isr = (isr_f)_cmicd_interrupt; + } + /* check if version is CMICX */ + else if (ver == 0x04) { + ctrl->isr = (isr_f)_cmicx_interrupt; + _intr_regs_init(ctrl, 0); + } else { + ctrl->isr = (isr_f)_cmic_interrupt; + if ((ctrl->dev_type & BDE_256K_REG_SPACE) && +#ifdef BCM_PETRA_SUPPORT /* FIXME remove code when hardware design is fixed */ + ctrl->devid != 0x1234 && +#endif + readl(ctrl->ba + CMICE_DEV_REV_ID) == 0) { + ctrl->isr = (isr_f)_cmicm_interrupt; + } + } + break; + } + + /* configure interrupts for DNX devices using iproc >=14 */ +#if defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) + switch (user_bde->get_dev(d)->device & DNXC_DEVID_FAMILY_MASK) { +#ifdef BCM_DNX_SUPPORT + case JERICHO2_DEVICE_ID: + case J2C_DEVICE_ID: + case J2C_2ND_DEVICE_ID: + case Q2A_DEVICE_ID: + case Q2U_DEVICE_ID: + case J2P_DEVICE_ID: +#endif +#ifdef BCM_DNXF_SUPPORT + case BCM88790_DEVICE_ID: +#endif + ctrl->isr = (isr_f)_cmicx_interrupt; + _intr_regs_init(ctrl, 0); + break; + } +#endif /* defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) */ + + if (_intr_mode_str(ctrl->isr) == NULL) { + gprintk("Warning: Unknown interrupt mode\n"); + } + } +} +/* + * Function: _init + * + * Purpose: + * Module initialization. + * Attaches to kernel BDE. + * Parameters: + * None + * Returns: + * Always 0 + */ +static int +_init(void) +{ + int i, nof_devices; + phys_addr_t cpu_pbase, dma_pbase; + ssize_t dmasize; + bde_inst_resource_t *res; + uint32 *bitmap_ptr; + + /* Connect to the kernel bde */ + if ((linux_bde_create(NULL, &user_bde) < 0) || user_bde == NULL) { + return -ENODEV; + } + spin_lock_init(&bde_resource_lock); + + init_waitqueue_head(&_ether_interrupt_wq); + + lkbde_get_dma_info(&cpu_pbase, &dma_pbase, &dmasize); + + memset(&_dma_pool, 0, sizeof(_dma_pool)); + _dma_pool.cpu_pbase = cpu_pbase; + _dma_pool.dma_pbase = dma_pbase; + _dma_pool.total_size = dmasize / ONE_MB; + + memset(_devices, 0, sizeof(_devices)); + + /* Use _bde_inst_resource[0] as the default resource */ + memset(_bde_inst_resource, 0, sizeof(_bde_inst_resource)); + res = &_bde_inst_resource[0]; + res->dma_offset = 0; + res->dma_size = _dma_pool.total_size; + init_waitqueue_head(&res->intr_wq); + init_waitqueue_head(&res->edk_intr_wq); + atomic_set(&res->intr, 0); + atomic_set(&res->edk_intr, 0); + + ihost_intr_enable_base = NULL; + ihost_intr_status_base = NULL; + + nof_devices = user_bde->num_devices(BDE_ALL_DEVICES); + /* for no BDE instances, mark the single SDK as controlling all devices */ + bitmap_ptr = *lkbde_get_inst_devs(0); + for (i = nof_devices; i >=32; i -= 32) { + *(bitmap_ptr++) = 0xffffffff; + } + *bitmap_ptr = (((uint32)1) << i) - 1; + res->is_active = 1; + + for (i = 0; i < nof_devices; i++) { /* init all devices */ + _devices_init(i); + } + + if (intr_timeout > 0) { + gprintk("Interruptible wait timeout = %d msecs\n", intr_timeout); + } + + return 0; +} + +/* + * Function: _cleanup + * + * Purpose: + * Module cleanup function. + * Parameters: + * None + * Returns: + * Always 0 + */ +static int +_cleanup(void) +{ + int i; + + if (user_bde) { + for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { + if (_devices[i].enabled && + BDE_DEV_MEM_MAPPED(_devices[i].dev_type)) { + user_bde->interrupt_disconnect(i); + } + lkbde_dev_instid_set(i, BDE_DEV_INST_ID_INVALID); + } + linux_bde_destroy(user_bde); + user_bde = NULL; + } + + if (ihost_intr_enable_base) { + iounmap(ihost_intr_enable_base); + ihost_intr_enable_base = NULL; + } + if (ihost_intr_status_base) { + iounmap(ihost_intr_status_base); + ihost_intr_status_base = NULL; + } + + return 0; +} + +/* + * Function: _pprint + * + * Purpose: + * Print proc filesystem information. + * Parameters: + * None + * Returns: + * Always 0 + */ +static int +_pprint(struct seq_file *m) +{ + int idx; + const char *name; + bde_inst_resource_t *res; + uint32 state, instid; + + pprintf(m, "Broadcom Device Enumerator (%s)\n", LINUX_USER_BDE_NAME); + for (idx = 0; idx < user_bde->num_devices(BDE_ALL_DEVICES); idx++) { + name = _intr_mode_str(_devices[idx].isr); + if (name == NULL) { + name = "unknown"; + } + pprintf(m, "\t%d: Interrupt mode %s ",idx, name); + (void)lkbde_dev_state_get(idx, &state); + if (state == BDE_DEV_STATE_REMOVED) { + pprintf(m, " Device REMOVED ! \n"); + } else { + (void)lkbde_dev_instid_get(idx, &instid); + if (instid != BDE_DEV_INST_ID_INVALID) { + pprintf(m, "Inst id 0x%x\n",instid); + } else { + pprintf(m, "\n"); + } + } + } + pprintf(m, "Instance resource \n"); + + for (idx = 0; idx < user_bde->num_devices(BDE_ALL_DEVICES); idx++) { + res = &_bde_inst_resource[idx]; + if (res->is_active) { + linux_bde_device_bitmap_t* bitmap_p = lkbde_get_inst_devs(idx); + pprintf(m, "\t%d: DMA offset %d size %d MB Dev mask 0x", + idx, + res->dma_offset, + res->dma_size); + for (state = 0; state * 32 < user_bde->num_devices(BDE_ALL_DEVICES); ++state) { + pprintf(m,"%.8x ", (*bitmap_p)[state]); + } + pprintf(m,"\n"); + } + } + + return 0; +} + +#ifdef BCM_INSTANCE_SUPPORT +/* + * Allocate the DMA resource from DMA pool + * Parameter : + * dma_size (IN): allocate dma_size in MB + * dma_offset (OUT): dma offset in MB + */ +static int +_dma_resource_alloc(unsigned int dma_size, unsigned int *dma_offset) +{ + uint32 left; + + left = _dma_pool.total_size - _dma_pool.offset; + if (dma_size > left) { + gprintk("ERROR: Run out the dma resource!\n"); + return -1; + } + *dma_offset = _dma_pool.offset; + _dma_pool.offset += dma_size; + return 0; +} +#endif + +static int +_dma_resource_get(unsigned inst_id, phys_addr_t *cpu_pbase, phys_addr_t *dma_pbase, ssize_t* size) +{ + unsigned int dma_size = 0, dma_offset = 0; + bde_inst_resource_t *res; + + if (inst_id >= user_bde->num_devices(BDE_ALL_DEVICES)) { + gprintk("ERROR: requested DMA resources for an instance number out of range: %u\n", inst_id); + return -1; + } + res = &_bde_inst_resource[inst_id]; + dma_size = res->dma_size; + dma_offset = res->dma_offset; + + *cpu_pbase = _dma_pool.cpu_pbase + dma_offset * ONE_MB; + *dma_pbase = _dma_pool.dma_pbase + dma_offset * ONE_MB; + *size = dma_size * ONE_MB; + + return 0; +} + +#ifdef BCM_INSTANCE_SUPPORT +/* + * Checks if we have the instance in _bde_inst_resource. If not, return LUBDE_SUCCESS==0 (considered a new instance). + * If it exists with the same dmasize, return 1 (It is considered already in use) + * Otherwise if the device with the same index of the resource, has resource/instance index 0, return LUBDE_SUCCESS==0. (bug) + * Otherwise return LUBDE_FAIL==-1 (It is considered to exist with a different dmasize). + */ +static int +_instance_validate(unsigned int inst_id, unsigned int dmasize, linux_bde_device_bitmap_t inst_devices) +{ + unsigned i; + uint32 bits; + bde_inst_resource_t *res = _bde_inst_resource + inst_id; + linux_bde_device_bitmap_t* bitmap_p; + + if (inst_id >= user_bde->num_devices(BDE_ALL_DEVICES)) { + gprintk("ERROR: instance number out of range: %u\n", inst_id); + return LUBDE_FAIL; + } + + if (res->is_active == 0) { + /* FIXME SDK-225233 check that the devices are not used by another active instance */ + return LUBDE_SUCCESS; + } + + bitmap_p = lkbde_get_inst_devs(inst_id); + for (i = 0; i < LINUX_BDE_NOF_DEVICE_BITMAP_WORDS; ++i) { + bits = inst_devices[i] ^ (*bitmap_p)[i]; + if (bits != 0) { + for (i *= 32; (bits & 1) == 0; bits >>= 1, ++i); + gprintk("ERROR: existing instance number %u does not control the same devices, see device %u\n", inst_id, i); + return LUBDE_FAIL; + } + } + + if (res->dma_size == dmasize) { + return 1; /* For an existing same instance with the same DMA size, do nothing */ + } + /* with a different DMS size */ + gprintk("ERROR: dma_size mismatch\n"); + return LUBDE_FAIL; +} +#endif + +static int +_device_reprobe(void) +{ + int i; + + for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { + if (_devices[i].devid == 0) { + _devices_init(i); + } + } + return 0; +} + +#ifdef BCM_INSTANCE_SUPPORT +/* + * Attach an SDK instance: + * _device_reprobe(); + * Check If an instance with the same bitmap exists, if yes with the same dmasize, return, if yes a different dmasize return an error, if no: + * Allocate DMA for the instance. + * This loop finds the first free resource in _bde_inst_resource[] and configure it for the instance. + * Store the resource/instance index in _bde_inst_resource for every device in the instance. + */ +static int +_instance_attach(unsigned int inst_id, unsigned int dma_size, linux_bde_device_bitmap_t inst_devices) +{ + unsigned int dma_offset; + int i, exist; + bde_inst_resource_t *res; + uint32 previous_inst_id; + + /* Reprobe the system for hot-plugged device */ + _device_reprobe(); + + if (debug >= 2) { + gprintk("INFO: Request to attach to instance_id %u with dma size %d!\n", inst_id, dma_size); + } + + spin_lock(&bde_resource_lock); + + /* If not in multi instance mode, move to the mode and fix the first instance that represented all devices */ + if (_bde_multi_inst == 0) { + _bde_multi_inst = 1; + _bde_inst_resource->is_active = 0; + /*_bde_inst_resource->dev will not be used when _bde_inst_resource->is_active == 0 */ + } + + /* Validate the resource with inst_devices */ + exist = _instance_validate(inst_id, dma_size, inst_devices); + + if (exist == LUBDE_FAIL) { + spin_unlock(&bde_resource_lock); + return LUBDE_FAIL; + } + if (exist > 0) { + if (debug >= 2) { + gprintk("INFO: Already attached to instance_id %u with dma size %d!\n", inst_id, dma_size); + } + spin_unlock(&bde_resource_lock); + return LUBDE_SUCCESS; + } + if (_dma_resource_alloc(dma_size, &dma_offset) < 0) { + spin_unlock(&bde_resource_lock); + return LUBDE_FAIL; + } + + /* configure the instance ID resources */ + res = _bde_inst_resource + inst_id; + res->is_active = 1; + res->dma_offset = dma_offset; + res->dma_size = dma_size; +#ifdef SAI_FIXUP /* SDK-240875 */ + /* skip instance 0, WQ for instance 0 has been initialized in user_bde init, see _init() */ + if (inst_id != 0) { + init_waitqueue_head(&res->intr_wq); + init_waitqueue_head(&res->edk_intr_wq); + atomic_set(&res->intr, 0); + atomic_set(&res->edk_intr, 0); + } +#endif + memcpy(*lkbde_get_inst_devs(inst_id), inst_devices, sizeof(linux_bde_device_bitmap_t)); /* SDK-225233 */ + + /* store the resource/instance index in _bde_inst_resource for every device in the instance */ + for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { + if (inst_devices[i / 32] & (1 << (i % 32))) { + _devices[i].inst = inst_id; + /* Pass the inst_id to the kernel BDE */ + if (lkbde_dev_instid_get(i, &previous_inst_id) == 0) { /* If the linux-kernel-bde inst_id is not set for the device, set it to the instance ID */ + if (previous_inst_id == BDE_DEV_INST_ID_INVALID) { + lkbde_dev_instid_set(i, inst_id); + } + } /* TODO handle the case where the device is marked belonging to a different instance */ + } + } + spin_unlock(&bde_resource_lock); + if (debug >= 2) { + gprintk("INFO: Attached to instance_id %lu with dma size %d! SUCCESS\n", (unsigned long)inst_devices, dma_size); + } + + return LUBDE_SUCCESS; +} +#endif /* BCM_INSTANCE_SUPPORT */ + +#ifdef BDE_EDK_SUPPORT +static int +_edk_instance_attach(unsigned int inst_id, unsigned int dma_size) +{ + ssize_t size = (ssize_t)dma_size; + if (size) { + lkbde_edk_get_dma_info(inst_id, NULL, NULL, &size); + if (!size) { + gprintk("Error: EDK Attached to instance_id %lu failed\n", (unsigned long)inst_id); + return LUBDE_FAIL; + } + } + return LUBDE_SUCCESS; +} +#endif + +/* + * Function: _ioctl + * + * Purpose: + * Handle IOCTL commands from user mode. + * Parameters: + * cmd - IOCTL cmd + * arg - IOCTL parameters + * Returns: + * 0 on success, <0 on error + */ +static int +_ioctl(unsigned int cmd, unsigned long arg) +{ + lubde_ioctl_t io; + phys_addr_t cpu_pbase, dma_pbase; + ssize_t size; + const ibde_dev_t *bde_dev; + int inst_id, idx; + bde_inst_resource_t *res; + uint32_t *mapaddr; + + if (copy_from_user(&io, (void *)arg, sizeof(io))) { + return -EFAULT; + } + + io.rc = LUBDE_SUCCESS; + + switch(cmd) { + case LUBDE_VERSION: + io.d0 = KBDE_VERSION; + break; + case LUBDE_GET_NUM_DEVICES: + io.d0 = user_bde->num_devices(io.dev); + break; + case LUBDE_GET_DEVICE: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + bde_dev = user_bde->get_dev(io.dev); + if (bde_dev) { + io.d0 = bde_dev->device; + io.d1 = bde_dev->rev; + io.dx.dw[0] = bde_dev->dev_unique_id; + if (BDE_DEV_MEM_MAPPED(_devices[io.dev].dev_type)) { + /* Get physical address to map */ + io.d2 = lkbde_get_dev_phys(io.dev); + io.d3 = lkbde_get_dev_phys_hi(io.dev); + } + } else { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_GET_DEVICE_TYPE: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + io.d0 = _devices[io.dev].dev_type; + break; + case LUBDE_GET_BUS_FEATURES: + user_bde->pci_bus_features(io.dev, (int *) &io.d0, (int *) &io.d1, + (int *) &io.d2); + break; + case LUBDE_PCI_CONFIG_PUT32: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) { + user_bde->pci_conf_write(io.dev, io.d0, io.d1); + } else { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_PCI_CONFIG_GET32: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) { + io.d0 = user_bde->pci_conf_read(io.dev, io.d0); + } else { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_GET_DMA_INFO: + inst_id = io.dev; + if (_bde_multi_inst){ + if (_dma_resource_get(inst_id, &cpu_pbase, &dma_pbase, &size)) { + io.rc = LUBDE_FAIL; + } + } else { + lkbde_get_dma_info(&cpu_pbase, &dma_pbase, &size); + } +#ifdef BDE_EDK_SUPPORT + case LUBDE_GET_EDK_DMA_INFO: + if (cmd == LUBDE_GET_EDK_DMA_INFO) { + inst_id = io.dev; + lkbde_edk_get_dma_info(inst_id, &cpu_pbase, &dma_pbase, &size); + } +#endif + io.d0 = dma_pbase; + io.d1 = size; + /* Optionally enable DMA mmap via /dev/linux-kernel-bde */ + io.d2 = USE_LINUX_BDE_MMAP; + /* Get physical address for mmap */ + io.dx.dw[0] = cpu_pbase; +#ifdef PHYS_ADDRS_ARE_64BITS + io.dx.dw[1] = cpu_pbase >> 32; + io.d3 = dma_pbase >> 32; +#else + io.dx.dw[1] = 0; + io.d3 = 0; +#endif + break; + case LUBDE_ENABLE_INTERRUPTS: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) { + if (_devices[io.dev].isr && !_devices[io.dev].enabled) { + user_bde->interrupt_connect(io.dev, + _devices[io.dev].isr, + _devices+io.dev); + _devices[io.dev].enabled = 1; + } + } else { + /* Process ethernet device interrupt */ + /* FIXME: for multiple chips */ + if (!_devices[io.dev].enabled) { + user_bde->interrupt_connect(io.dev, + (void(*)(void *))_ether_interrupt, + _devices+io.dev); + _devices[io.dev].enabled = 1; + } + } + break; + case LUBDE_DISABLE_INTERRUPTS: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].enabled) { + user_bde->interrupt_disconnect(io.dev); + _devices[io.dev].enabled = 0; + } + break; + case LUBDE_SET_EDK_INTERRUPTS: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + res = &_bde_inst_resource[_devices[io.dev].inst]; + res->edk_irqs.timer_intrc_offset = io.d0; + res->edk_irqs.timer_intrc_mask = io.d1; + res->edk_irqs.sw_intr_intrc_offset = io.d2; + res->edk_irqs.sw_intr_intrc_mask = io.d3; + res->edk_irqs.sw_intr_src_bitmap = io.dx.dw[0]; + for (idx = 0; idx < MAX_UC_CORES; idx++) { + res->edk_irqs.sw_intr_icfg_reg[idx] = io.dx.dw[idx + 1]; + } + break; + case LUBDE_ENABLE_EDK_INTERRUPTS: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + _devices[io.dev].edk_irq_enabled = 1; + break; + case LUBDE_DISABLE_EDK_INTERRUPTS: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + _devices[io.dev].edk_irq_enabled = 0; + break; + case LUBDE_WAIT_FOR_INTERRUPT: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) { + res = &_bde_inst_resource[_devices[io.dev].inst]; +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wait_event_timeout(res->intr_wq, + atomic_read(&res->intr) != 0, 100); + +#else + /* CMICX Devices */ + if ((_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) && + (_devices[io.dev].isr == (isr_f)_cmicx_interrupt) && + (intr_timeout > 0)) { + unsigned long t_jiffies; + int err=0; + t_jiffies = msecs_to_jiffies(intr_timeout); + err = wait_event_interruptible_timeout(res->intr_wq, + atomic_read(&res->intr) != 0, + t_jiffies); + /* Timeout happend and condition not set */ + if (err == 0) { + bde_ctrl_t *ctrl; + ctrl = &_devices[io.dev]; + intr_timeout_count++; + if (debug >= 1) { + gprintk("Timeout happend and condition not set\n"); + } + dump_interrupt_regs(ctrl, io.dev); + } else if (err == -ERESTARTSYS) { + if (debug >= 1) { + gprintk("Interrupted by Signal\n"); + } + } + } else { + wait_event_interruptible(res->intr_wq, + atomic_read(&res->intr) != 0); + } +#endif + /* + * Even if we get multiple interrupts, we + * only run the interrupt handler once. + */ + atomic_set(&res->intr, 0); + } else { +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wait_event_timeout(_ether_interrupt_wq, + atomic_read(&_ether_interrupt_has_taken_place) != 0, 100); +#else + wait_event_interruptible(_ether_interrupt_wq, + atomic_read(&_ether_interrupt_has_taken_place) != 0); + +#endif + /* + * Even if we get multiple interrupts, we + * only run the interrupt handler once. + */ + atomic_set(&_ether_interrupt_has_taken_place, 0); + } + break; + case LUBDE_WAIT_FOR_EDK_INTERRUPT: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + res = &_bde_inst_resource[_devices[io.dev].inst]; +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wait_event_timeout(res->edk_intr_wq, + atomic_read(&res->edk_intr) != 0, 100); + +#else + /* CMICX Devices */ + if ((_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) && + (_devices[io.dev].isr == (isr_f)_cmicx_interrupt) && + (intr_timeout > 0)) { + unsigned long t_jiffies; + int err = 0; + t_jiffies = msecs_to_jiffies(intr_timeout); + err = wait_event_interruptible_timeout(res->edk_intr_wq, + atomic_read(&res->edk_intr) != 0, t_jiffies); + /* Timeout happend and condition not set */ + if (err == 0) { + bde_ctrl_t *ctrl; + ctrl = &_devices[io.dev]; + intr_timeout_count++; + if (debug >= 1) { + gprintk("EDK Interrrupt: Timeout happened\n"); + } + dump_interrupt_regs(ctrl, io.dev); + } else if (err == -ERESTARTSYS) { + if (debug >= 1) { + gprintk("EDK Interrrupt: Interrupted by Signal\n"); + } + } + } else { + wait_event_interruptible(res->edk_intr_wq, atomic_read(&res->edk_intr) != 0); + } +#endif + /* Even if we get multiple interrupts, we + * only run the interrupt handler once. */ + atomic_set(&res->edk_intr, 0); + break; + case LUBDE_USLEEP: + case LUBDE_UDELAY: + case LUBDE_SEM_OP: + return -EINVAL; + case LUBDE_WRITE_IRQ_MASK: + io.rc = lkbde_irq_mask_set(io.dev, io.d0, io.d1, 0); + break; + case LUBDE_SPI_READ_REG: + if (user_bde->spi_read(io.dev, io.d0, io.dx.buf, io.d1) == -1) { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_SPI_WRITE_REG: + if (user_bde->spi_write(io.dev, io.d0, io.dx.buf, io.d1) == -1) { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_READ_REG_16BIT_BUS: + io.d1 = user_bde->read(io.dev, io.d0); + break; + case LUBDE_WRITE_REG_16BIT_BUS: + io.rc = user_bde->write(io.dev, io.d0, io.d1); + break; +#ifdef BCM_SAND_SUPPORT + case LUBDE_CPU_WRITE_REG: + { + if (lkbde_cpu_write(io.dev, io.d0, (uint32*)io.dx.buf) == -1) { + io.rc = LUBDE_FAIL; + } + break; + } + case LUBDE_CPU_READ_REG: + { + if (lkbde_cpu_read(io.dev, io.d0, (uint32*)io.dx.buf) == -1) { + io.rc = LUBDE_FAIL; + } + break; + } + case LUBDE_CPU_PCI_REGISTER: + { + if (lkbde_cpu_pci_register(io.dev) == -1) { + io.rc = LUBDE_FAIL; + } + break; + } +#endif + case LUBDE_DEV_RESOURCE: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + bde_dev = user_bde->get_dev(io.dev); + if (bde_dev) { + if (BDE_DEV_MEM_MAPPED(_devices[io.dev].dev_type)) { + /* Get physical address to map */ + io.rc = lkbde_get_dev_resource(io.dev, io.d0, + &io.d2, &io.d3, &io.d1); + } + } else { + io.rc = LUBDE_FAIL; + } + break; + case LUBDE_IPROC_READ_REG: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + if (_devices[io.dev].dev_type & BDE_AXI_DEV_TYPE) { + mapaddr = IOREMAP(io.d0, sizeof(uint32_t)); + if (mapaddr == NULL) { + io.rc = LUBDE_FAIL; + return -1; + } + io.d1 = readl(mapaddr); + iounmap(mapaddr); + } else { + io.d1 = user_bde->iproc_read(io.dev, io.d0); + if (io.d1 == -1) { + io.rc = LUBDE_FAIL; + } + } + break; + case LUBDE_IPROC_WRITE_REG: + if (user_bde->iproc_write(io.dev, io.d0, io.d1) == -1) { + io.rc = LUBDE_FAIL; + } + break; +#ifdef BDE_EDK_SUPPORT + case LUBDE_ATTACH_EDK_INSTANCE: + io.rc = _edk_instance_attach(io.d0, io.d1); + break; +#endif +#ifdef BCM_INSTANCE_SUPPORT + case LUBDE_ATTACH_INSTANCE: + io.rc = _instance_attach(io.d0, io.d1, io.dx.dw); + break; +#endif + case LUBDE_GET_DEVICE_STATE: + io.rc = lkbde_dev_state_get(io.dev, &io.d0); + break; + case LUBDE_REPROBE: + io.rc = _device_reprobe(); + break; + default: + gprintk("Error: Invalid ioctl (%08x)\n", cmd); + io.rc = LUBDE_FAIL; + break; + } + + if (copy_to_user((void *)arg, &io, sizeof(io))) { + return -EFAULT; + } + + return 0; +} + +/* Workaround for broken Busybox/PPC insmod */ +static char _modname[] = LINUX_USER_BDE_NAME; + +static gmodule_t _gmodule = +{ + name: LINUX_USER_BDE_NAME, + major: LINUX_USER_BDE_MAJOR, + init: _init, + cleanup: _cleanup, + pprint: _pprint, + ioctl: _ioctl, +}; + +gmodule_t* +gmodule_get(void) +{ + _gmodule.name = _modname; + return &_gmodule; +} diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.h b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.h new file mode 100644 index 000000000000..4bd4b746c521 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.h @@ -0,0 +1,132 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: linux-user-bde.h,v 1.23 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef __LINUX_USER_BDE_H__ +#define __LINUX_USER_BDE_H__ + +#include +#include +#include +#ifndef __KERNEL__ +#include +#endif + +#if defined(SAL_BDE_32BIT_USER_64BIT_KERNEL) || defined(PTRS_ARE_64BITS) +typedef uint64_t bde_kernel_addr_t; +#else +typedef uint32_t bde_kernel_addr_t; +#endif + +/* Ioctl control structure */ +typedef struct { + unsigned int dev; /* Device ID */ + unsigned int rc; /* Operation Return Code */ + unsigned int d0; /* Operation specific data */ + unsigned int d1; + unsigned int d2; + unsigned int d3; + bde_kernel_addr_t p0; + union { + uint32_t dw[16]; + unsigned char buf[64]; + } dx; +} lubde_ioctl_t; + + +/* LUBDE ioctls */ +#define LUBDE_MAGIC 'L' + +#define LUBDE_VERSION _IO(LUBDE_MAGIC, 0) +#define LUBDE_GET_NUM_DEVICES _IO(LUBDE_MAGIC, 1) +#define LUBDE_GET_DEVICE _IO(LUBDE_MAGIC, 2) +#define LUBDE_PCI_CONFIG_PUT32 _IO(LUBDE_MAGIC, 3) +#define LUBDE_PCI_CONFIG_GET32 _IO(LUBDE_MAGIC, 4) +#define LUBDE_GET_DMA_INFO _IO(LUBDE_MAGIC, 5) +#define LUBDE_ENABLE_INTERRUPTS _IO(LUBDE_MAGIC, 6) +#define LUBDE_DISABLE_INTERRUPTS _IO(LUBDE_MAGIC, 7) +#define LUBDE_USLEEP _IO(LUBDE_MAGIC, 8) +#define LUBDE_WAIT_FOR_INTERRUPT _IO(LUBDE_MAGIC, 9) +#define LUBDE_SEM_OP _IO(LUBDE_MAGIC, 10) +#define LUBDE_UDELAY _IO(LUBDE_MAGIC, 11) +#define LUBDE_GET_DEVICE_TYPE _IO(LUBDE_MAGIC, 12) +#define LUBDE_SPI_READ_REG _IO(LUBDE_MAGIC, 13) +#define LUBDE_SPI_WRITE_REG _IO(LUBDE_MAGIC, 14) +#define LUBDE_READ_REG_16BIT_BUS _IO(LUBDE_MAGIC, 19) +#define LUBDE_WRITE_REG_16BIT_BUS _IO(LUBDE_MAGIC, 20) +#define LUBDE_GET_BUS_FEATURES _IO(LUBDE_MAGIC, 21) +#define LUBDE_WRITE_IRQ_MASK _IO(LUBDE_MAGIC, 22) +#define LUBDE_CPU_WRITE_REG _IO(LUBDE_MAGIC, 23) +#define LUBDE_CPU_READ_REG _IO(LUBDE_MAGIC, 24) +#define LUBDE_CPU_PCI_REGISTER _IO(LUBDE_MAGIC, 25) +#define LUBDE_DEV_RESOURCE _IO(LUBDE_MAGIC, 26) +#define LUBDE_IPROC_READ_REG _IO(LUBDE_MAGIC, 27) +#define LUBDE_IPROC_WRITE_REG _IO(LUBDE_MAGIC, 28) +#define LUBDE_ATTACH_INSTANCE _IO(LUBDE_MAGIC, 29) +#define LUBDE_GET_DEVICE_STATE _IO(LUBDE_MAGIC, 30) +#define LUBDE_REPROBE _IO(LUBDE_MAGIC, 31) +#define LUBDE_SET_EDK_INTERRUPTS _IO(LUBDE_MAGIC, 32) +#define LUBDE_ENABLE_EDK_INTERRUPTS _IO(LUBDE_MAGIC, 33) +#define LUBDE_DISABLE_EDK_INTERRUPTS _IO(LUBDE_MAGIC, 34) +#define LUBDE_WAIT_FOR_EDK_INTERRUPT _IO(LUBDE_MAGIC, 35) +#define LUBDE_ATTACH_EDK_INSTANCE _IO(LUBDE_MAGIC, 36) +#define LUBDE_GET_EDK_DMA_INFO _IO(LUBDE_MAGIC, 37) + + +#define LUBDE_SEM_OP_CREATE 1 +#define LUBDE_SEM_OP_DESTROY 2 +#define LUBDE_SEM_OP_TAKE 3 +#define LUBDE_SEM_OP_GIVE 4 + +#define LUBDE_SUCCESS 0 +#define LUBDE_FAIL ((unsigned int)-1) + + +/* + * Version history + * 1: add LUBDE_GET_DEVICE_STATE to support PCI hot plug + * 2: add LUBDE_REPROBE to support reprobe available devices + */ +#define KBDE_VERSION 2 + + +/* This is the signal that will be used + * when an interrupt occurs + */ + +#ifndef __KERNEL__ +#include +#endif + +#define LUBDE_INTERRUPT_SIGNAL SIGUSR1 +#define LUBDE_ETHER_INTERRUPT_SIGNAL SIGUSR2 + +#endif /* __LUBDE_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde.h new file mode 100644 index 000000000000..2d0651191fbb --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde.h @@ -0,0 +1,87 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#ifndef __SHBDE_H__ +#define __SHBDE_H__ + +typedef void (*shbde_log_func_t)(int level, const char *str, int param); + +#define SHBDE_ERR 0 +#define SHBDE_WARN 1 +#define SHBDE_DBG 2 + +/* iProc configuration (primarily used for PCI-AXI bridge) */ +typedef struct shbde_iproc_config_s { + unsigned int dev_id; + unsigned int dev_rev; + unsigned int use_msi; + unsigned int iproc_ver; + unsigned int cmic_ver; + unsigned int cmic_rev; + unsigned int dma_hi_bits; + unsigned int mdio_base_addr; + unsigned int pcie_phy_addr; + unsigned int adjust_pcie_preemphasis; +} shbde_iproc_config_t; + +/* Hardware abstraction functions */ +typedef struct shbde_hal_s { + + /* Optional log output interface */ + shbde_log_func_t log_func; + + /* PCI configuration access */ + unsigned char (*pcic8_read)(void *pci_dev, unsigned int reg); + void (*pcic8_write)(void *pci_dev, unsigned int reg, unsigned char data); + unsigned short (*pcic16_read)(void *pci_dev, unsigned int reg); + void (*pcic16_write)(void *pci_dev, unsigned int reg, unsigned short data); + unsigned int (*pcic32_read)(void *pci_dev, unsigned int reg); + void (*pcic32_write)(void *pci_dev, unsigned int reg, unsigned int data); + + /* iProc register access */ + unsigned int (*io32_read)(void *addr); + void (*io32_write)(void *addr, unsigned int); + + /* usleep function (optional) */ + void (*usleep)(int usec); + + /* PCI parent device access */ + void *(*pci_parent_device_get)(void *pci_dev); + + /* iProc configuration */ + shbde_iproc_config_t icfg; + +} shbde_hal_t; + + +#endif /* __SHBDE_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_iproc.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_iproc.h new file mode 100644 index 000000000000..4b71b8f16ee3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_iproc.h @@ -0,0 +1,59 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#ifndef __SHBDE_IPROC_H__ +#define __SHBDE_IPROC_H__ + +#include + +extern int +shbde_iproc_config_init(shbde_iproc_config_t *icfg, + unsigned int dev_id, unsigned int dev_rev); + +extern int +shbde_iproc_paxb_init(shbde_hal_t *shbde, void *iproc_regs, + shbde_iproc_config_t *icfg); + +extern unsigned int +shbde_iproc_pci_read(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr); + +extern void +shbde_iproc_pci_write(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr, unsigned int data); + +extern int +shbde_iproc_pcie_preemphasis_set(shbde_hal_t *shbde, void *iproc_regs, + shbde_iproc_config_t *icfg, void *pci_dev); + +#endif /* __SHBDE_IPROC_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_mdio.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_mdio.h new file mode 100644 index 000000000000..a51dd2ac6f5f --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_mdio.h @@ -0,0 +1,70 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: $ + * $Copyright: (c) 2015 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#ifndef __SHBDE_MDIO_H__ +#define __SHBDE_MDIO_H__ + +#include + +typedef struct shbde_mdio_ctrl_s { + + /* Primary HAL*/ + shbde_hal_t *shbde; + + /* Context for iProc MDIO register access */ + void *regs; + + /* Base address for MDIO registers */ + unsigned int base_addr; + + /* iProc MDIO register access */ + unsigned int (*io32_read)(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr); + void (*io32_write)(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr, unsigned int data); + +} shbde_mdio_ctrl_t; + + +extern int +shbde_iproc_mdio_init(shbde_mdio_ctrl_t *smc); + +extern int +shbde_iproc_mdio_read(shbde_mdio_ctrl_t *smc, unsigned int phy_addr, + unsigned int reg, unsigned int *val); + +extern int +shbde_iproc_mdio_write(shbde_mdio_ctrl_t *smc, unsigned int phy_addr, + unsigned int reg, unsigned int val); + +#endif /* __SHBDE_MDIO_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_pci.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_pci.h new file mode 100644 index 000000000000..a0b88494823f --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_pci.h @@ -0,0 +1,57 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#ifndef __SHBDE_PCI_H__ +#define __SHBDE_PCI_H__ + +#include + +extern unsigned int +shbde_pci_pcie_cap(shbde_hal_t *shbde, void *pci_dev); + +extern int +shbde_pci_is_pcie(shbde_hal_t *shbde, void *pci_dev); + +extern int +shbde_pci_is_iproc(shbde_hal_t *shbde, void *pci_dev, int *cmic_bar); + +extern int +shbde_pci_max_payload_set(shbde_hal_t *shbde, void *pci_dev, int maxpayload); + +extern int +shbde_pci_iproc_version_get(shbde_hal_t *shbde, void *pci_dev, + unsigned int *iproc_ver, + unsigned int *cmic_ver, + unsigned int *cmic_rev); + +#endif /* __SHBDE_PCI_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c new file mode 100644 index 000000000000..ca8024c78a32 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c @@ -0,0 +1,521 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#include +#include +#include + +/* PAXB register offsets within PCI BAR0 window */ +#define BAR0_PAXB_ENDIANESS 0x2030 +#define BAR0_PAXB_PCIE_EP_AXI_CONFIG 0x2104 +#define BAR0_PAXB_CONFIG_IND_ADDR 0x2120 +#define BAR0_PAXB_CONFIG_IND_DATA 0x2124 + +#define PAXB_0_CMICD_TO_PCIE_INTR_EN 0x2380 + +#define BAR0_PAXB_IMAP0_0 (0x2c00) +#define BAR0_PAXB_IMAP0_1 (0x2c04) +#define BAR0_PAXB_IMAP0_2 (0x2c08) +#define BAR0_PAXB_IMAP0_7 (0x2c1c) + +#define BAR0_PAXB_OARR_FUNC0_MSI_PAGE 0x2d34 +#define BAR0_PAXB_OARR_2 0x2d60 +#define BAR0_PAXB_OARR_2_UPPER 0x2d64 +#define BAR0_DMU_PCU_PCIE_SLAVE_RESET_MODE 0x7024 + +#define PAXB_0_FUNC0_IMAP1_3 0x2d88 + +/* Force byte pointer for offset adjustments */ +#define ROFFS(_ptr, _offset) ((unsigned char*)(_ptr) + (_offset)) + +#define PAXB_CONFIG_IND_ADDRr_PROTOCOL_LAYERf_SHFT 11 +#define PAXB_CONFIG_IND_ADDRr_PROTOCOL_LAYERf_MASK 0x3 +#define PAXB_CONFIG_IND_ADDRr_ADDRESSf_SHFT 0 +#define PAXB_CONFIG_IND_ADDRr_ADDRESSf_MASK 0x7ff +#define PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT 20 + +/* Register value set/get by field */ +#define REG_FIELD_SET(_r, _f, _r_val, _f_val) \ + _r_val = ((_r_val) & ~(_r##_##_f##_MASK << _r##_##_f##_SHFT)) | \ + (((_f_val) & _r##_##_f##_MASK) << _r##_##_f##_SHFT) +#define REG_FIELD_GET(_r, _f, _r_val) \ + (((_r_val) >> _r##_##_f##_SHFT) & _r##_##_f##_MASK) + +/* PCIe capabilities definition */ +#ifndef PCI_EXP_LNKSTA +#define PCI_EXP_LNKSTA 0x12 +#endif +/* Current Link Speed 5.0GT/s */ +#ifndef PCI_EXP_LNKSTA_CLS_5_0GB +#define PCI_EXP_LNKSTA_CLS_5_0GB 2 +#endif +#ifndef PCI_EXP_LNKSTA2 +#define PCI_EXP_LNKSTA2 0x32 +#endif +/* Current Deemphasis Level -3.5 dB */ +#ifndef PCI_EXP_LNKSTA2_CDL_3_5DB +#define PCI_EXP_LNKSTA2_CDL_3_5DB 0x1 +#endif + +static unsigned int +iproc32_read(shbde_hal_t *shbde, void *addr) +{ + if (!shbde || !shbde->io32_read) { + return 0; + } + return shbde->io32_read(addr); +} + +static void +iproc32_write(shbde_hal_t *shbde, void *addr, unsigned int data) +{ + if (!shbde || !shbde->io32_write) { + return; + } + shbde->io32_write(addr, data); +} + +static void +wait_usec(shbde_hal_t *shbde, int usec) +{ + if (shbde && shbde->usleep) { + shbde->usleep(usec); + } else { + int idx; + volatile int count; + for (idx = 0; idx < usec; idx++) { + for (count = 0; count < 100; count++); + } + } +} + +/* + * Function: + * shbde_iproc_config_init + * Purpose: + * Initialize iProc configuration parameters + * Parameters: + * icfg - pointer to empty iProc configuration structure + * Returns: + * -1 if error, otherwise 0 + */ +int +shbde_iproc_config_init(shbde_iproc_config_t *icfg, + unsigned int dev_id, unsigned int dev_rev) +{ + if (!icfg) { + return -1; + } + + /* Save device ID and revision */ + icfg->dev_id = dev_id; + icfg->dev_rev = dev_rev; + + /* Check device families first */ + switch (icfg->dev_id & 0xfff0) { + case 0x8400: /* Greyhound Lite */ + case 0x8410: /* Greyhound */ + case 0x8420: /* Bloodhound */ + case 0x8450: /* Elkhound */ + case 0xb060: /* Ranger2(Greyhound) */ + case 0x8360: /* Greyhound 53365 & 53369 */ + case 0xb260: /* saber2 */ + case 0xb460: /* saber2+ */ + case 0xb170: /* Hurricane3-MG */ + case 0x8570: /* Greyhound2 */ + case 0xb070: /* Greyhound2(emulation) */ + case 0x8580: /* Greyhound2(emulation) */ + case 0xb230: /* Dagger2 */ + icfg->iproc_ver = 7; + icfg->dma_hi_bits = 0x2; + break; + case 0xb560: /* Apache */ + case 0xb670: /* MO */ + case 0xb760: /* Maverick */ + icfg->iproc_ver = 0xB; + break; + case 0xb160: /* Hurricane3 */ + case 0x8440: /* Buckhound2 */ + case 0x8430: /* Foxhound2 */ + case 0x8540: /* Wolfhound2 */ + icfg->iproc_ver = 10; + icfg->dma_hi_bits = 0x2; + break; + default: + break; + } + + /* Check for exceptions */ + switch (icfg->dev_id) { + case 0xb069: + case 0xb068: + icfg->iproc_ver = 0xB; /*Ranger2+ Apache Family */ + icfg->dma_hi_bits = 0; + break; + case 0xb168: /* Ranger3+ */ + case 0xb169: + icfg->iproc_ver = 0; + icfg->dma_hi_bits = 0; + break; + default: + break; + } + /* Check for PCIe PHY address that needs PCIe preemphasis and + * assign the MDIO base address + */ + switch (icfg->dev_id & 0xfff0) { + case 0xb150: /* Hurricane2 */ + case 0x8340: /* Wolfhound */ + case 0x8330: /* Foxhound */ + case 0x8390: /* Dearhound */ + icfg->mdio_base_addr = 0x18032000; + icfg->pcie_phy_addr = 0x2; + break; + case 0xb340: /* Helilx4 */ + case 0xb540: /* FireScout */ + case 0xb040: /* Spiral, Ranger */ + icfg->mdio_base_addr = 0x18032000; + icfg->pcie_phy_addr = 0x5; + icfg->adjust_pcie_preemphasis = 1; + break; + case 0xa450: /* Katana2 */ + case 0xb240: + case 0xb450: + icfg->mdio_base_addr = 0x18032000; + icfg->pcie_phy_addr = 0x5; + icfg->adjust_pcie_preemphasis = 1; + break; + default: + break; + } + + /* Check for exceptions */ + switch (icfg->dev_id) { + default: + break; + } + + return 0; +} + +/* + * Function: + * shbde_iproc_paxb_init + * Purpose: + * Initialize iProc PCI-AXI bridge for CMIC access + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * iproc_regs - memory mapped iProc registers in PCI BAR + * icfg - iProc configuration parameters + * Returns: + * -1 if error, otherwise 0 + */ +int +shbde_iproc_paxb_init(shbde_hal_t *shbde, void *iproc_regs, + shbde_iproc_config_t *icfg) +{ + void *reg; + unsigned int data; + int pci_num; + + if (!iproc_regs || !icfg) { + return -1; + } + + /* + * The following code attempts to auto-detect the correct + * iProc PCI endianess configuration by reading a well-known + * register (the endianess configuration register itself). + * Note that the PCI endianess may be different for different + * big endian host processors. + */ + reg = ROFFS(iproc_regs, BAR0_PAXB_ENDIANESS); + /* Select big endian */ + iproc32_write(shbde, reg, 0x01010101); + /* Check if endianess register itself is correct endian */ + if (iproc32_read(shbde, reg) != 1) { + /* If not, then assume little endian */ + iproc32_write(shbde, reg, 0x0); + } + + /* Select which PCI core to use */ + pci_num = 0; + reg = ROFFS(iproc_regs, BAR0_PAXB_IMAP0_2); + data = iproc32_read(shbde, reg); + if (data & 0x1000) { + /* PAXB_1 is mapped to sub-window 2 */ + pci_num = 1; + } + + /* Default DMA mapping if uninitialized */ + if (icfg->dma_hi_bits == 0) { + icfg->dma_hi_bits = 0x1; + if (pci_num == 1) { + icfg->dma_hi_bits = 0x2; + } + } + + /* Enable iProc DMA to external host memory */ + reg = ROFFS(iproc_regs, BAR0_PAXB_PCIE_EP_AXI_CONFIG); + iproc32_write(shbde, reg, 0x0); + if(icfg->cmic_ver < 4) { /* Non-CMICX */ + reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_2); + iproc32_write(shbde, reg, 0x1); + reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_2_UPPER); + iproc32_write(shbde, reg, icfg->dma_hi_bits); + /* Configure MSI interrupt page */ + if (icfg->use_msi) { + reg = ROFFS(iproc_regs, BAR0_PAXB_OARR_FUNC0_MSI_PAGE); + data = iproc32_read(shbde, reg); + iproc32_write(shbde, reg, data | 0x1); + } + } + + /* Configure MSIX interrupt page, need for iproc ver 0x10 and 0x12 */ + if ((icfg->use_msi == 2) && + ((icfg->iproc_ver == 0x10) + || (icfg->iproc_ver == 0x12) + || (icfg->iproc_ver == 0x11))){ + unsigned int mask = (0x1 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT) - 1; + reg = ROFFS(iproc_regs, PAXB_0_FUNC0_IMAP1_3); + data = iproc32_read(shbde, reg); + data &= mask; + if (icfg->iproc_ver == 0x11) { + data |= 0x400 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT; + } else { + data |= 0x410 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT; + } + + iproc32_write(shbde, reg, data); + } + + /* Disable INTx interrupt if MSI/MSIX is selected */ + reg = ROFFS(iproc_regs, PAXB_0_CMICD_TO_PCIE_INTR_EN); + data = iproc32_read(shbde, reg); + if (icfg->use_msi) { + data &= ~0x1; + } else { + data |= 0x1; + } + iproc32_write(shbde, reg, data); + + return pci_num; +} + +/* + * Function: + * shbde_iproc_pci_read + * Purpose: + * Read iProc register through PCI BAR 0 + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * iproc_regs - memory mapped iProc registers in PCI BAR + * addr - iProc register address in AXI memory space + * Returns: + * Register value + */ +unsigned int +shbde_iproc_pci_read(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr) +{ + unsigned int subwin_base; + void *reg; + shbde_iproc_config_t *icfg = &shbde->icfg; + + if (!iproc_regs) { + return -1; + } + + /* Sub-window size is 0x1000 (4K) */ + subwin_base = (addr & ~0xfff); + + if((icfg->cmic_ver >= 4) && + ((subwin_base == 0x10230000) || (subwin_base == 0x18012000))) { + /* Route the PAXB register through IMAP0_2 */ + reg = ROFFS(iproc_regs, 0x2000 + (addr & 0xfff)); + } else if((icfg->cmic_ver >= 4) && + ((subwin_base == 0x10231000) || (subwin_base == 0x18013000))) { + /* Route the INTC block access through IMAP0_6 */ + reg = ROFFS(iproc_regs, 0x6000 + (addr & 0xfff)); + } else { + /* Update base address for sub-window 7 */ + subwin_base |= 1; /* Valid bit */ + reg = ROFFS(iproc_regs, BAR0_PAXB_IMAP0_7); + iproc32_write(shbde, reg, subwin_base); + /* Read it to make sure the write actually goes through */ + subwin_base = iproc32_read(shbde, reg); + + /* Read register through sub-window 7 */ + reg = ROFFS(iproc_regs, 0x7000 + (addr & 0xfff)); + } + + return iproc32_read(shbde, reg); +} + +/* + * Function: + * shbde_iproc_pci_write + * Purpose: + * Write iProc register through PCI BAR 0 + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * iproc_regs - memory mapped iProc registers in PCI BAR + * addr - iProc register address in AXI memory space + * data - data to write to iProc register + * Returns: + * Register value + */ +void +shbde_iproc_pci_write(shbde_hal_t *shbde, void *iproc_regs, + unsigned int addr, unsigned int data) +{ + unsigned int subwin_base; + void *reg; + shbde_iproc_config_t *icfg = &shbde->icfg; + + if (!iproc_regs) { + return; + } + + /* Sub-window size is 0x1000 (4K) */ + subwin_base = (addr & ~0xfff); + + if((icfg->cmic_ver >= 4) && + ((subwin_base == 0x10230000) || (subwin_base == 0x18012000))) { + /* Route the PAXB register through IMAP0_2 */ + reg = ROFFS(iproc_regs, 0x2000 + (addr & 0xfff)); + } else if((icfg->cmic_ver >= 4) && + ((subwin_base == 0x10231000) || (subwin_base == 0x18013000))) { + /* Route the INTC block access through IMAP0_6 */ + reg = ROFFS(iproc_regs, 0x6000 + (addr & 0xfff)); + } else { + /* Update base address for sub-window 7 */ + subwin_base |= 1; /* Valid bit */ + reg = ROFFS(iproc_regs, BAR0_PAXB_IMAP0_7); + iproc32_write(shbde, reg, subwin_base); + /* Read it to make sure the write actually goes through */ + subwin_base = iproc32_read(shbde, reg); + + /* Read register through sub-window 7 */ + reg = ROFFS(iproc_regs, 0x7000 + (addr & 0xfff)); + } + + iproc32_write(shbde, reg, data); +} + +int +shbde_iproc_pcie_preemphasis_set(shbde_hal_t *shbde, void *iproc_regs, + shbde_iproc_config_t *icfg, void *pci_dev) +{ + shbde_mdio_ctrl_t mdio_ctrl, *smc = &mdio_ctrl; + unsigned int phy_addr, data; + void *reg; + unsigned int pcie_cap_base; + unsigned short link_stat, link_stat2; + + if (!icfg) { + return -1; + } + + /* PHY address for PCIe link */ + phy_addr = icfg->pcie_phy_addr; + if (phy_addr == 0 || icfg->mdio_base_addr == 0) { + return 0; + } + + /* Initialize MDIO control */ + smc->shbde = shbde; + smc->regs = iproc_regs; + smc->base_addr = icfg->mdio_base_addr; + smc->io32_read = shbde_iproc_pci_read; + smc->io32_write = shbde_iproc_pci_write; + shbde_iproc_mdio_init(smc); + + /* PCIe SerDes Gen1/Gen2 CDR Track Bandwidth Adjustment + * for Better Jitter Tolerance + */ + shbde_iproc_mdio_write(smc, phy_addr, 0x1f, 0x8630); + shbde_iproc_mdio_write(smc, phy_addr, 0x13, 0x190); + shbde_iproc_mdio_write(smc, phy_addr, 0x19, 0x191); + + if (!icfg->adjust_pcie_preemphasis) { + return 0; + } + + /* Check to see if the PCIe SerDes deemphasis needs to be changed + * based on the advertisement from the root complex + */ + /* Find PCIe capability base */ + if (!shbde || !shbde->pcic16_read || !pci_dev) { + return -1; + } + pcie_cap_base = shbde_pci_pcie_cap(shbde, pci_dev); + if (pcie_cap_base) { + link_stat = shbde->pcic16_read(pci_dev, + pcie_cap_base + PCI_EXP_LNKSTA); + link_stat2 = shbde->pcic16_read(pci_dev, + pcie_cap_base + PCI_EXP_LNKSTA2); + if (((link_stat & 0xf) == PCI_EXP_LNKSTA_CLS_5_0GB) && + (link_stat2 & PCI_EXP_LNKSTA2_CDL_3_5DB)) { + /* Device is operating at Gen2 speeds and RC requested -3.5dB */ + /* Change the transmitter setting */ + shbde_iproc_mdio_write(smc, phy_addr, 0x1f, 0x8610); + shbde_iproc_mdio_read(smc, phy_addr, 0x17, &data); + data &= ~0xf00; + data |= 0x700; + shbde_iproc_mdio_write(smc, phy_addr, 0x17, data); + + /* Force the PCIe link to retrain */ + data = 0; + REG_FIELD_SET(PAXB_CONFIG_IND_ADDRr, PROTOCOL_LAYERf, data, 0x2); + REG_FIELD_SET(PAXB_CONFIG_IND_ADDRr, ADDRESSf, data, 0x4); + reg = ROFFS(iproc_regs, BAR0_PAXB_CONFIG_IND_ADDR); + iproc32_write(shbde, reg, data); + + reg = ROFFS(iproc_regs, BAR0_PAXB_CONFIG_IND_DATA); + data = iproc32_read(shbde, reg); + data &= ~0x4000; + iproc32_write(shbde, reg, data); + data |= 0x4000; + iproc32_write(shbde, reg, data); + data &= ~0x4000; + iproc32_write(shbde, reg, data); + + /* Wait a short while for the retraining to complete */ + wait_usec(shbde, 1000); + } + } + + return 0; +} + diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_mdio.c b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_mdio.c new file mode 100644 index 000000000000..1e38eb024adc --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_mdio.c @@ -0,0 +1,197 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: $ + * $Copyright: (c) 2015 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#include + +/* iProc MDIO register offset */ +#define MII_MGMT_CTRL 0x0 +#define MII_MGMT_CMD_DATA 0x4 + +/* iProc MII register with fields definition */ +#define MII_MGMT_CTRLr_MDCDIVf_SHFT 0 +#define MII_MGMT_CTRLr_MDCDIVf_MASK 0x7f +#define MII_MGMT_CTRLr_BSYf_SHFT 8 +#define MII_MGMT_CTRLr_BSYf_MASK 0x1 + +#define MII_MGMT_CMD_DATAr_DATAf_SHFT 0 +#define MII_MGMT_CMD_DATAr_DATAf_MASK 0xffff +#define MII_MGMT_CMD_DATAr_TAf_SHFT 16 +#define MII_MGMT_CMD_DATAr_TAf_MASK 0x3 +#define MII_MGMT_CMD_DATAr_RAf_SHFT 18 +#define MII_MGMT_CMD_DATAr_RAf_MASK 0x1f +#define MII_MGMT_CMD_DATAr_PAf_SHFT 23 +#define MII_MGMT_CMD_DATAr_PAf_MASK 0x1f +#define MII_MGMT_CMD_DATAr_OPf_SHFT 28 +#define MII_MGMT_CMD_DATAr_OPf_MASK 0x3 +#define MII_MGMT_CMD_DATAr_SBf_SHFT 30 +#define MII_MGMT_CMD_DATAr_SBf_MASK 0x3 + +/* Register field value set/get */ +#define REG_FIELD_SET(_r, _f, _r_val, _f_val) \ + _r_val = ((_r_val) & ~(_r##_##_f##_MASK << _r##_##_f##_SHFT)) | \ + (((_f_val) & _r##_##_f##_MASK) << _r##_##_f##_SHFT) +#define REG_FIELD_GET(_r, _f, _r_val) \ + (((_r_val) >> _r##_##_f##_SHFT) & _r##_##_f##_MASK) + +#define LOG_OUT(_shbde, _lvl, _str, _prm) \ + if ((_shbde)->log_func) { \ + (_shbde)->log_func(_lvl, _str, _prm); \ + } +#define LOG_ERR(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_ERR, _str, _prm) +#define LOG_WARN(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_WARN, _str, _prm) +#define LOG_DBG(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_DBG, _str, _prm) + +static unsigned int +mdio32_read(shbde_mdio_ctrl_t *smc, unsigned int offset) +{ + if (!smc || !smc->io32_read) { + return 0; + } + return smc->io32_read(smc->shbde, smc->regs, smc->base_addr + offset); +} + +static void +mdio32_write(shbde_mdio_ctrl_t *smc, unsigned int offset, unsigned int data) +{ + if (!smc || !smc->io32_read) { + return; + } + smc->io32_write(smc->shbde, smc->regs, smc->base_addr + offset, data); +} + +static void +wait_usec(shbde_mdio_ctrl_t *smc, int usec) +{ + shbde_hal_t *shbde = smc->shbde; + + if (shbde && shbde->usleep) { + shbde->usleep(usec); + } else { + int idx; + volatile int count; + for (idx = 0; idx < usec; idx++) { + for (count = 0; count < 100; count++); + } + } +} + +static int +iproc_mdio_wait_for_busy(shbde_mdio_ctrl_t *smc) +{ + int mii_busy; + unsigned int reg_val; + int count = 1000; + + /* Wait until MII is not busy */ + do { + reg_val = mdio32_read(smc, MII_MGMT_CTRL); + mii_busy = REG_FIELD_GET(MII_MGMT_CTRLr, BSYf, reg_val); + if (!mii_busy) { + break; + } + wait_usec(smc, 10); + count --; + } while (count > 0); + + return mii_busy; +} + +int +shbde_iproc_mdio_init(shbde_mdio_ctrl_t *smc) +{ + shbde_hal_t *shbde = smc->shbde; + unsigned int reg_val = 0; + + /* Enable the iProc internal MDIO interface */ + REG_FIELD_SET(MII_MGMT_CTRLr, MDCDIVf, reg_val, 0x7f); + mdio32_write(smc, MII_MGMT_CTRL, reg_val); + + if (shbde && !shbde->usleep) { + LOG_DBG(shbde, "shbde_mdio: no registration of usleep vector", 0); + } + + wait_usec(smc, 100); + + return 0; +} + +int +shbde_iproc_mdio_read(shbde_mdio_ctrl_t *smc, unsigned int phy_addr, + unsigned int reg, unsigned int *val) +{ + unsigned int reg_val = 0; + + REG_FIELD_SET(MII_MGMT_CMD_DATAr, SBf, reg_val, 0x1); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, TAf, reg_val, 0x2); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, OPf, reg_val, 0x2); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, PAf, reg_val, phy_addr); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, RAf, reg_val, reg); + mdio32_write(smc, MII_MGMT_CMD_DATA, reg_val); + + if (iproc_mdio_wait_for_busy(smc)) { + *val = 0; + LOG_DBG(smc->shbde, "shbde_iproc_mdio_read busy", reg); + return -1; + } + + reg_val = mdio32_read(smc, MII_MGMT_CMD_DATA); + *val = REG_FIELD_GET(MII_MGMT_CMD_DATAr, DATAf, reg_val); + + return 0; +} + +int +shbde_iproc_mdio_write(shbde_mdio_ctrl_t *smc, unsigned int phy_addr, + unsigned int reg, unsigned int val) +{ + unsigned int reg_val = 0; + + REG_FIELD_SET(MII_MGMT_CMD_DATAr, SBf, reg_val, 0x1); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, TAf, reg_val, 0x2); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, OPf, reg_val, 0x1); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, PAf, reg_val, phy_addr); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, RAf, reg_val, reg); + REG_FIELD_SET(MII_MGMT_CMD_DATAr, DATAf, reg_val, val); + mdio32_write(smc, MII_MGMT_CMD_DATA, reg_val); + + if (iproc_mdio_wait_for_busy(smc)) { + LOG_DBG(smc->shbde, "shbde_iproc_mdio_write busy", reg); + return -1; + } + + /* Wait for some time for the write to take effect */ + wait_usec(smc, 100); + + return 0; +} + diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_pci.c b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_pci.c new file mode 100644 index 000000000000..8e64b475a41f --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_pci.c @@ -0,0 +1,403 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: $ + * $Copyright: (c) 2014 Broadcom Corp. + * All Rights Reserved.$ + * + */ + +#include + +/* PCIe capabilities */ +#ifndef PCI_CAPABILITY_LIST +#define PCI_CAPABILITY_LIST 0x34 +#endif +#ifndef PCI_CAP_ID_EXP +#define PCI_CAP_ID_EXP 0x10 +#endif +#ifndef PCI_EXP_DEVCAP +#define PCI_EXP_DEVCAP 4 +#endif +#ifndef PCI_EXP_DEVCTL +#define PCI_EXP_DEVCTL 8 +#endif +#ifndef PCI_EXT_CAP_START +#define PCI_EXT_CAP_START 0x100 +#endif +#ifndef PCI_EXT_CAP_ID +#define PCI_EXT_CAP_ID(_hdr) (_hdr & 0x0000ffff) +#endif +#ifndef PCI_EXT_CAP_VER +#define PCI_EXT_CAP_VER(_hdr) ((_hdr >> 16) & 0xf) +#endif +#ifndef PCI_EXT_CAP_NEXT +#define PCI_EXT_CAP_NEXT(_hdr) ((_hdr >> 20) & 0xffc) +#endif +#ifndef PCI_EXT_CAP_ID_VNDR +#define PCI_EXT_CAP_ID_VNDR 0x0b +#endif + +#define LOG_OUT(_shbde, _lvl, _str, _prm) \ + if ((_shbde)->log_func) { \ + (_shbde)->log_func(_lvl, _str, _prm); \ + } +#define LOG_ERR(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_ERR, _str, _prm) +#define LOG_WARN(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_WARN, _str, _prm) +#define LOG_DBG(_shbde, _str, _prm) LOG_OUT(_shbde, SHBDE_DBG, _str, _prm) + +#ifndef NULL +#define NULL (void *)0 +#endif + +/* + * Warpper functions with null-pointer checks. + */ +static unsigned int +pcic16_read(shbde_hal_t *shbde, void *pci_dev, + unsigned int addr) +{ + if (!shbde || !shbde->pcic16_read) { + return 0; + } + return shbde->pcic16_read(pci_dev, addr); +} + +static void +pcic16_write(shbde_hal_t *shbde, void *pci_dev, + unsigned int addr, unsigned int data) +{ + if (!shbde || !shbde->pcic16_write) { + return; + } + shbde->pcic16_write(pci_dev, addr, data); +} + +static unsigned int +pcic32_read(shbde_hal_t *shbde, void *pci_dev, + unsigned int addr) +{ + if (!shbde || !shbde->pcic32_read) { + return 0; + } + return shbde->pcic32_read(pci_dev, addr); +} + +static void * +pci_parent_device_get(shbde_hal_t *shbde, void *pci_dev) +{ + if (!shbde || !shbde->pci_parent_device_get) { + return NULL; + } + return shbde->pci_parent_device_get(pci_dev); +} + +/* + * Function: + * shbde_pci_pcie_cap + * Purpose: + * Return offset of PCIe capabilities in PCI configuration space + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * dev - PCI device handle (passed back to PCI HAL functions) + * Returns: + * PCI_CAP_ID_EXP offset in PCI configuration space if PCIe, otherwise 0 + */ +unsigned int +shbde_pci_pcie_cap(shbde_hal_t *shbde, void *pci_dev) +{ + unsigned int cap_base, rval; + + cap_base = pcic16_read(shbde, pci_dev, PCI_CAPABILITY_LIST); + while (cap_base) { + rval = pcic16_read(shbde, pci_dev, cap_base); + if ((rval & 0xff) == PCI_CAP_ID_EXP) { + break; + } + cap_base = (rval >> 8) & 0xff; + } + + return cap_base; +} + +/* + * Function: + * shbde_pci_is_pcie + * Purpose: + * Check if PCI device is PCIe device + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * dev - PCI device handle (passed back to PCI HAL functions) + * Returns: + * 1 if PCIe, otherwise 0 + */ +int +shbde_pci_is_pcie(shbde_hal_t *shbde, void *pci_dev) +{ + return shbde_pci_pcie_cap(shbde, pci_dev) ? 1 : 0; +} + +/* + * Function: + * shbde_pci_is_iproc + * Purpose: + * Check if PCI device is iProc-based + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * dev - PCI device handle (passed back to PCI HAL functions) + * cmic_bar - (OUT) PCI BAR which contains switch CMIC registers + * Returns: + * 1 if iProc-based, otherwise 0 + */ +int +shbde_pci_is_iproc(shbde_hal_t *shbde, void *pci_dev, int *cmic_bar) +{ + unsigned int cap_base, rval; + + if (!shbde_pci_is_pcie(shbde, pci_dev)) { + return 0; + } + + /* Look for PCIe vendor-specific extended capability (VSEC) */ + cap_base = PCI_EXT_CAP_START; + while (cap_base) { + rval = pcic32_read(shbde, pci_dev, cap_base); + if (rval == 0xffffffff) { + /* Assume PCI HW read error */ + return 0; + } + + if (PCI_EXT_CAP_ID(rval) == PCI_EXT_CAP_ID_VNDR) { + break; + } + cap_base = PCI_EXT_CAP_NEXT(rval); + } + if (cap_base) { + /* + * VSEC layout: + * + * 0x00: PCI Express Extended Capability Header + * 0x04: Vendor-Specific Header + * 0x08: Vendor-Specific Register 1 + * 0x0c: Vendor-Specific Register 2 + * ... + * 0x24: Vendor-Specific Register 8 + */ + /* 32'b // 31:12=0 Reserved; 11:08=CMIC BAR; 07:00=iProc Configuration ID */ + rval = pcic32_read(shbde, pci_dev, cap_base + 8); + LOG_DBG(shbde, "Found VSEC", rval); + + /* Determine PCI BAR of CMIC */ + *cmic_bar = 0; + if ((rval & 0x100) == 0x100) { + *cmic_bar = 2; + } + /* Assume iProc device */ + return 1; + } + + return 0; +} + +/* + * Function: + * shbde_pci_iproc_version_get + * Purpose: + * Get iproc, cmic versions and revisions + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * dev - PCI device handle (passed back to PCI HAL functions) + * iproc_ver - (OUT) iProc version + * cmic_ver - (OUT) CMIC version + * cmic_rev - (OUT) CMIC revision + * Returns: + * 1 for no error, otherwise 0 + */ +int +shbde_pci_iproc_version_get(shbde_hal_t *shbde, void *pci_dev, + unsigned int *iproc_ver, + unsigned int *cmic_ver, + unsigned int *cmic_rev) +{ + unsigned int cap_base, rval; + + if (!shbde_pci_is_pcie(shbde, pci_dev)) { + return 0; + } + + /* Look for PCIe vendor-specific extended capability (VSEC) */ + cap_base = PCI_EXT_CAP_START; + while (cap_base) { + rval = pcic32_read(shbde, pci_dev, cap_base); + if (rval == 0xffffffff) { + /* Assume PCI HW read error */ + return 0; + } + + if (PCI_EXT_CAP_ID(rval) == PCI_EXT_CAP_ID_VNDR) { + break; + } + cap_base = PCI_EXT_CAP_NEXT(rval); + } + if (cap_base) { + /* + * VSEC layout: + * + * 0x00: PCI Express Extended Capability Header + * 0x04: Vendor-Specific Header + * 0x08: Vendor-Specific Register 1 + * 0x0c: Vendor-Specific Register 2 + * ... + * 0x24: Vendor-Specific Register 8 + */ + + /* Read PCIe Vendor Specific Register 1 */ + /* VENODR REG FORMAT + * [7:0] iProc Rev = 8'h0E (for P14) + * [11:8] CMIC BAR = 4'h1 (BAR64-1) + * [15:12] CMIC Version = 4'h4 + * [19:16] CMIC Rev = 4'h1 + * [22:20] SBUS Version = 4'h4 + */ + + rval = pcic32_read(shbde, pci_dev, cap_base + 8); + LOG_DBG(shbde, "Found VSEC", rval); + + /* Determine PCI BAR of CMIC */ + *iproc_ver = rval & 0xff; + *cmic_ver = (rval >> 12) & 0xf; + *cmic_rev = (rval >> 16) & 0xf; + return 1; + } + + return 0; +} + +/* + * Function: + * shbde_pci_max_payload_set + * Purpose: + * Set PCIe maximum payload + * Parameters: + * shbde - pointer to initialized hardware abstraction module + * dev - PCI device handle (passed back to PCI HAL functions) + * maxpayload - maximum payload (in byte) + * Returns: + * -1 if error, otherwise 0 + * Notes: + * If not PCIe device, set the PCI retry count to infinte instead. + */ +int +shbde_pci_max_payload_set(shbde_hal_t *shbde, void *pci_dev, int maxpayload) +{ + unsigned int cap_base, parent_cap_base; + unsigned int devcap, devctl, parent_devctl; + int max_val, max_cap, parent_max_val; + void *parent_pci_dev; + + cap_base = shbde_pci_pcie_cap(shbde, pci_dev); + + if (cap_base == 0) { + /* Not PCIe */ + return 0; + } + + /* Get current device control settings */ + devctl = pcic16_read(shbde, pci_dev, cap_base + PCI_EXP_DEVCTL); + + /* Get current max payload setting */ + max_val = (devctl >> 5) & 0x7; + + if (maxpayload) { + /* Get encoding from byte value */ + max_val = 0; + while ((1 << (max_val + 7)) < maxpayload) { + max_val++; + } + LOG_DBG(shbde, "Set max payload size", maxpayload); + LOG_DBG(shbde, "Set max payload val", max_val); + + /* Get max supported payload size */ + devcap = pcic16_read(shbde, pci_dev, cap_base + PCI_EXP_DEVCAP); + max_cap = (devcap & 0x7); + + /* Do not exceed device capabilities */ + if (max_val > max_cap) { + max_val = max_cap; + LOG_DBG(shbde, + "Payload size exceeds device capability", + maxpayload); + } + + /* Get currently set max payload size for the parent device + * in the PCI tree (if it exists). + */ + parent_pci_dev = pci_parent_device_get(shbde, pci_dev); + if (parent_pci_dev != NULL) { + parent_cap_base = shbde_pci_pcie_cap(shbde, parent_pci_dev); + parent_devctl = pcic16_read(shbde, + parent_pci_dev, + parent_cap_base + PCI_EXP_DEVCTL); + parent_max_val = (parent_devctl >> 5) & 0x7; + + /* Do not exceed current parent max payload setting (our device + * should have an MPS setting <= current parent MPS setting in + * the tree of PCIe devices). + */ + if (max_val > parent_max_val) { + max_val = parent_max_val; + LOG_DBG(shbde, + "Payload size exceeds current parent device setting", + maxpayload); + } + } + + /* Update max payload size */ + devctl &= ~(0x7 << 5); + devctl |= (max_val) << 5; + + /* Update max request size */ + devctl &= ~(0x7 << 12); + devctl |= (max_val << 12); + } + + /* Always disable relaxed ordering */ + devctl &= ~(1 << 4); + + /* Update device control settings */ + pcic16_write(shbde, pci_dev, cap_base + PCI_EXP_DEVCTL, devctl); + + /* Warn if non-default setting is used */ + if (max_val > 0) { + LOG_WARN(shbde, + "Selected payload size may not be supported by all " + "PCIe bridges by default.", + (1 << (max_val + 7))); + } + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/Makefile new file mode 100644 index 000000000000..b599580ae861 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/Makefile @@ -0,0 +1,42 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.10 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +# Makefile for SOC SAL support +# +LOCALDIR = systems/linux/kernel/modules + +include ${SDK}/make/Make.config + +subdirs= + +include ${SDK}/make/Make.subdirs + +include ${SDK}/make/Make.depend diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/Makefile new file mode 100644 index 000000000000..9879be69b0b6 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/Makefile @@ -0,0 +1,75 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/linux/kernel/modules/bcm-knet + +include ${SDK}/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +ifeq ($(kernel_version),2_4) +MODULE = $(LIBDIR)/linux-bcm-knet.o +else +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := linux-bcm-knet +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: $(MODULE) $(KMODULE) +endif + +KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../../../../bde/linux/kernel/kernel_module/Module.symvers + +# BCM Network Device + +$(MODULE): $(BLDDIR)/.tree $(BOBJS) $(LIBS) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + cat ${KBUILD_EXTRA_SYMBOLS} > $(BLDDIR)/$(KERNEL_MODULE_DIR)/Module.symvers + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +include ${SDK}/make/Make.depend + +clean:: + $(RM) $(BLDDIR)/version.c $(BLDDIR)/version.o + $(RM) $(BOBJS) $(MODULE) + +ifneq ($(kernel_version),2_4) +.PHONY: build +endif diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c new file mode 100644 index 000000000000..a3f92b17584b --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c @@ -0,0 +1,9213 @@ +/* + * Copyright 2017 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ + +/* + * This module implements a Linux network driver for Broadcom + * XGS switch devices. The driver simultaneously serves a + * number of vitual Linux network devices and a Tx/Rx API + * implemented in user space. + * + * Packets received from the switch device are sent to either + * a virtual Linux network device or the user mode Rx API + * based on a set of packet filters.susp + * + * Packets from the virtual Linux network devices and the user + * mode Tx API are multiplexed with priority given to the Tx API. + * + * A message-based IOCTL interface is used for managing packet + * filters and virtual Linux network interfaces. + * + * A virtual network interface can be configured to work in RCPU + * mode, which means that packets from the switch device will + * be encasulated with a RCPU header and a block of meta data + * that basically contains the core DCB information. Likewise, + * packets received from the Linux network stack are assumed to + * be RCPU encapsulated when going out on an interface in RCPU + * mode. + * + * The module implements basic Rx DMA rate control. The rate is + * specified in packets per second, and different Rx DMA channels + * can be configured to use different maximum packet rates. + * The packet rate can be configure as a module parameter, and + * it can also be changed dynamically through the proc file + * system (syntax is described in function header comment). + * + * To support multiple instance, each instance has its event queue. + * + * To support pci hot-plug in this module, the resource update + * should be handled when the PCI device is re-plugged. + * NOTE: the KNET detach should be invoked before removing the + * device. + * + * For a list of supported module parameters, please see below. + */ + +#include /* Must be included first */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Network Device Driver for Broadcom BCM TxRx API"); +MODULE_LICENSE("GPL"); + +static int debug; +LKM_MOD_PARAM(debug, "i", int, 0); +MODULE_PARM_DESC(debug, +"Debug level (default 0)"); + +static char *mac_addr = NULL; +LKM_MOD_PARAM(mac_addr, "s", charp, 0); +MODULE_PARM_DESC(mac_addr, +"Ethernet MAC address (default 02:10:18:xx:xx:xx)"); + +static int rx_buffer_size = 9216; +LKM_MOD_PARAM(rx_buffer_size, "i", int, 0); +MODULE_PARM_DESC(rx_buffer_size, +"Size of RX packet buffers (default 9216)"); + +static int default_mtu = 1500; +LKM_MOD_PARAM(default_mtu, "i", int, 0); +MODULE_PARM_DESC(default_mtu, +"Default MTU for KNET network interfaces (default 1500)"); + +static int rx_sync_retry = 1000; +LKM_MOD_PARAM(rx_sync_retry, "i", int, 0); +MODULE_PARM_DESC(rx_sync_retry, +"Retries if chain is incomplete on interrupt (default 10)"); + +static char *base_dev_name = NULL; +LKM_MOD_PARAM(base_dev_name, "s", charp, 0); +MODULE_PARM_DESC(base_dev_name, +"Base device name (default bcm0, bcm1, etc.)"); + +static int rcpu_mode = 0; +LKM_MOD_PARAM(rcpu_mode, "i", int, 0); +MODULE_PARM_DESC(rcpu_mode, +"Enable RCPU encapsulation (default 0)"); + +static char *rcpu_dmac = NULL; +LKM_MOD_PARAM(rcpu_dmac, "s", charp, 0); +MODULE_PARM_DESC(rcpu_dmac, +"RCPU destination MAC address (by default use L2 destination MAC address)"); + +static char *rcpu_smac = NULL; +LKM_MOD_PARAM(rcpu_smac, "s", charp, 0); +MODULE_PARM_DESC(rcpu_smac, +"RCPU source MAC address (by default use L2 source MAC address)"); + +static int rcpu_ethertype = 0xde08; +LKM_MOD_PARAM(rcpu_ethertype, "i", int, 0); +MODULE_PARM_DESC(rcpu_ethertype, +"RCPU EtherType (default DE08h)"); + +static int rcpu_signature = 0; +LKM_MOD_PARAM(rcpu_signature, "i", int, 0); +MODULE_PARM_DESC(rcpu_signature, +"RCPU Signature (default is PCI device ID)"); + +static int rcpu_vlan = 1; +LKM_MOD_PARAM(rcpu_vlan, "i", int, 0); +MODULE_PARM_DESC(rcpu_vlan, +"RCPU VLAN ID (default 1)"); + +static int use_rx_skb = 0; +LKM_MOD_PARAM(use_rx_skb, "i", int, 0); +MODULE_PARM_DESC(use_rx_skb, +"Use socket buffers for receive operation (default 0)"); + +static int num_rx_prio = 1; +LKM_MOD_PARAM(num_rx_prio, "i", int, 0); +MODULE_PARM_DESC(num_rx_prio, +"Number of filter priorities per Rx DMA channel"); + +static int rx_rate[8] = { 100000, 100000, 100000, 100000, 100000, 100000, 100000, 0 }; +LKM_MOD_PARAM_ARRAY(rx_rate, "1-4i", int, NULL, 0); +MODULE_PARM_DESC(rx_rate, +"Rx rate in packets per second (default 100000)"); + +static int rx_burst[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +LKM_MOD_PARAM_ARRAY(rx_burst, "1-4i", int, NULL, 0); +MODULE_PARM_DESC(rx_burst, +"Rx rate burst maximum in packets (default rx_rate/10)"); + +static int check_rcpu_signature = 0; +LKM_MOD_PARAM(check_rcpu_signature, "i", int, 0); +MODULE_PARM_DESC(check_rcpu_signature, +"Check RCPU Signature for Tx packets from RCPU interfaces"); + +static int basedev_suspend = 0; +LKM_MOD_PARAM(basedev_suspend, "i", int, 0); +MODULE_PARM_DESC(basedev_suspend, +"Pause traffic till base device is up (enabled by default in NAPI mode)"); + +/* + * Force to add one layer of VLAN tag to untagged packets on Dune devices + */ +#if defined(SAI_FIXUP) && defined(BCM_DNX_SUPPORT) /* SONIC-16195 CS9129167 - Change the default to NOT add tag */ +static int force_tagged = 0; +#else +static int force_tagged = 1; +#endif +LKM_MOD_PARAM(force_tagged, "i", int, 0); +MODULE_PARM_DESC(force_tagged, +"Always tagged with VLAN tag with spceified VID or VSI(default 1)"); + +static int ft_tpid=0x8100; +LKM_MOD_PARAM(ft_tpid, "i", int, 0); +MODULE_PARM_DESC(ft_tpid, +"Tag Protocol Identifier (TPID) indicates the frame type (default 0x8100)"); + +static int ft_pri=0; +LKM_MOD_PARAM(ft_pri, "i", int, 0); +MODULE_PARM_DESC(ft_cfi, +"Priority (PRI) indicates the frame priority (default 0)"); + +static int ft_cfi=0; +LKM_MOD_PARAM(ft_cfi, "i", int, 0); +MODULE_PARM_DESC(ft_cfi, +"Canonical Format Indicator (CFI) indicates whether a MAC address is encapsulated in canonical format over different transmission media (default 0)"); + +static int ft_vid=0; +LKM_MOD_PARAM(ft_vid, "i", int, 0); +MODULE_PARM_DESC(ft_vid, +"VLAN ID (VID) indicates the VLAN to which a frame belongs (default 0)"); + + +/* Debug levels */ +#define DBG_LVL_VERB 0x1 +#define DBG_LVL_DCB 0x2 +#define DBG_LVL_PKT 0x4 +#define DBG_LVL_SKB 0x8 +#define DBG_LVL_CMD 0x10 +#define DBG_LVL_EVT 0x20 +#define DBG_LVL_IRQ 0x40 +#define DBG_LVL_NAPI 0x80 +#define DBG_LVL_PDMP 0x100 +#define DBG_LVL_FLTR 0x200 +#define DBG_LVL_KCOM 0x400 +#define DBG_LVL_RCPU 0x800 +#define DBG_LVL_WARN 0x1000 +#define DBG_LVL_NDEV 0x2000 +#define DBG_LVL_INST 0x4000 +/* Level to output Dune internal headers Parsing */ +#define DBG_LVL_DUNE 0x8000 +#define DBG_LVL_DCB_TX 0x10000 +#define DBG_LVL_DCB_RX 0x20000 +#define DBG_LVL_PDMP_TX 0x40000 +#define DBG_LVL_PDMP_RX 0x80000 +#define DBG_LVL_PTP 0x100000 + +#define DBG_VERB(_s) do { if (debug & DBG_LVL_VERB) gprintk _s; } while (0) +#define DBG_PKT(_s) do { if (debug & DBG_LVL_PKT) gprintk _s; } while (0) +#define DBG_SKB(_s) do { if (debug & DBG_LVL_SKB) gprintk _s; } while (0) +#define DBG_CMD(_s) do { if (debug & DBG_LVL_CMD) gprintk _s; } while (0) +#define DBG_EVT(_s) do { if (debug & DBG_LVL_EVT) gprintk _s; } while (0) +#define DBG_IRQ(_s) do { if (debug & DBG_LVL_IRQ) gprintk _s; } while (0) +#define DBG_NAPI(_s) do { if (debug & DBG_LVL_NAPI) gprintk _s; } while (0) +#define DBG_PDMP(_s) do { if (debug & DBG_LVL_PDMP) gprintk _s; } while (0) +#define DBG_FLTR(_s) do { if (debug & DBG_LVL_FLTR) gprintk _s; } while (0) +#define DBG_KCOM(_s) do { if (debug & DBG_LVL_KCOM) gprintk _s; } while (0) +#define DBG_RCPU(_s) do { if (debug & DBG_LVL_RCPU) gprintk _s; } while (0) +#define DBG_WARN(_s) do { if (debug & DBG_LVL_WARN) gprintk _s; } while (0) +#define DBG_NDEV(_s) do { if (debug & DBG_LVL_NDEV) gprintk _s; } while (0) +#define DBG_INST(_s) do { if (debug & DBG_LVL_INST) gprintk _s; } while (0) +#define DBG_DUNE(_s) do { if (debug & DBG_LVL_DUNE) gprintk _s; } while (0) +#define DBG_DCB_TX(_s) do { if (debug & (DBG_LVL_DCB|DBG_LVL_DCB_TX)) \ + gprintk _s; } while (0) +#define DBG_DCB_RX(_s) do { if (debug & (DBG_LVL_DCB|DBG_LVL_DCB_RX)) \ + gprintk _s; } while (0) +#define DBG_DCB(_s) do { if (debug & (DBG_LVL_DCB|DBG_LVL_DCB_TX| \ + DBG_LVL_DCB_RX)) \ + gprintk _s; } while (0) +#define DBG_PTP(_s) do { if (debug & DBG_LVL_PTP) gprintk _s; } while (0) + + +/* This flag is used to indicate if debugging packet function is open or closed */ +static int dbg_pkt_enable = 0; + +/* Module Information */ +#define MODULE_MAJOR 122 +#define MODULE_NAME "linux-bcm-knet" + +#ifndef NAPI_SUPPORT +#define NAPI_SUPPORT 1 +#endif + +#if NAPI_SUPPORT + +static int use_napi = 0; +LKM_MOD_PARAM(use_napi, "i", int, 0); +MODULE_PARM_DESC(use_napi, +"Use NAPI interface (default 0)"); + +static int napi_weight = 64; +LKM_MOD_PARAM(napi_weight, "i", int, 0); +MODULE_PARM_DESC(napi_weight, +"Weight of NAPI interfaces (default 64)"); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +#define bkn_napi_enable(_dev, _napi) netif_poll_enable(_dev) +#define bkn_napi_disable(_dev, _napi) netif_poll_disable(_dev) +#define bkn_napi_schedule(_dev, _napi) netif_rx_schedule(_dev) +#define bkn_napi_schedule_prep(_dev, _napi) netif_rx_schedule_prep(_dev) +#define __bkn_napi_schedule(_dev, _napi) __netif_rx_schedule(_dev) +#define bkn_napi_complete(_dev, _napi) netif_rx_complete(_dev) +#else +#define bkn_napi_enable(_dev, _napi) napi_enable(_napi) +#define bkn_napi_disable(_dev, _napi) napi_disable(_napi) +#define bkn_napi_schedule(_dev, _napi) napi_schedule(_napi) +#define bkn_napi_schedule_prep(_dev, _napi) napi_schedule_prep(_napi) +#define __bkn_napi_schedule(_dev, _napi) __napi_schedule(_napi) +#define bkn_napi_complete(_dev, _napi) napi_complete(_napi) +#endif + +#else + +static int use_napi = 0; +static int napi_weight = 0; + +#define bkn_napi_enable(_dev, _napi) +#define bkn_napi_disable(_dev, _napi) +#define bkn_napi_schedule(_dev, _napi) +#define bkn_napi_schedule_prep(_dev, _napi) (0) +#define __bkn_napi_schedule(_dev, _napi) +#define bkn_napi_complete(_dev, _napi) + +#endif + +/* Compatibility */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)) +#define NETDEV_UPDATE_TRANS_START_TIME(dev) dev->trans_start = jiffies +#else +#define NETDEV_UPDATE_TRANS_START_TIME(dev) netif_trans_update(dev) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) +#define skb_copy_to_linear_data(_skb, _pkt, _len) \ + eth_copy_and_sum(_skb, _pkt, _len, 0) +struct napi_struct { int not_used; }; +#define netif_napi_add(_dev, _napi, _poll, _weight) do { \ + (_dev)->poll = _poll; \ + (_dev)->weight = _weight; \ +} while(0) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) +#define SKB_PADTO(_skb,_len) (((_skb = skb_padto(_skb,_len)) == NULL) ? -1 : 0) +#else +#define SKB_PADTO(_skb,_len) skb_padto(_skb,_len) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)) +#define skb_header_cloned(_skb) \ + skb_cloned(_skb) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) +static inline void *netdev_priv(struct net_device *dev) +{ + return dev->priv; +} +#endif /* KERNEL_VERSION(2,4,27) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) +/* Special check for MontaVista 2.4.20 MIPS */ +#if !(defined(MAX_USER_RT_PRIO) && defined(CONFIG_MIPS)) +static inline void free_netdev(struct net_device *dev) +{ + kfree(dev); +} +#endif +static inline void netif_poll_disable(struct net_device *dev) +{ + while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state)) { + /* No hurry. */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } +} +static inline void netif_poll_enable(struct net_device *dev) +{ + clear_bit(__LINK_STATE_RX_SCHED, &dev->state); +} +#endif /* KERNEL_VERSION(2,4,23) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) +static struct sk_buff *skb_pad(struct sk_buff *skb, int pad) +{ + struct sk_buff *nskb; + + /* If the skbuff is non linear tailroom is always zero.. */ + if(skb_tailroom(skb) >= pad) + { + memset(skb->data+skb->len, 0, pad); + return skb; + } + + nskb = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb) + pad, GFP_ATOMIC); + kfree_skb(skb); + if(nskb) + memset(nskb->data+nskb->len, 0, pad); + return nskb; +} +static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len) +{ + unsigned int size = skb->len; + if(likely(size >= len)) + return skb; + return skb_pad(skb, len-size); +} +#endif /* KERNEL_VERSION(2,4,21) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) +#define bkn_vlan_hwaccel_put_tag(_skb, _proto, _tci) \ + __vlan_hwaccel_put_tag(_skb, _tci) +#else +#define bkn_vlan_hwaccel_put_tag(_skb, _proto, _tci) \ + __vlan_hwaccel_put_tag(_skb, htons(_proto), _tci) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) +#define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */ +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +#define bkn_dma_mapping_error(d, a) \ + dma_mapping_error(a) +#define bkn_pci_dma_mapping_error(d, a) \ + pci_dma_mapping_error(a) +#else +#define bkn_dma_mapping_error(d, a) \ + dma_mapping_error(d, a) +#define bkn_pci_dma_mapping_error(d, a) \ + pci_dma_mapping_error(d, a) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) +enum hwtstamp_tx_types { + HWTSTAMP_TX_OFF, + HWTSTAMP_TX_ON, + HWTSTAMP_TX_ONESTEP_SYNC +}; +enum { + SKBTX_HW_TSTAMP = 1 << 0, + SKBTX_SW_TSTAMP = 1 << 1, + SKBTX_IN_PROGRESS = 1 << 2, +}; +struct skb_shared_hwtstamps { + ktime_t hwtstamp; + ktime_t syststamp; +}; +struct bkn_skb_shared_info { + uint8_t tx_flags; + struct skb_shared_hwtstamps hwtstamps; +}; +#define bkn_skb_shinfo(_skb) ((struct bkn_skb_shared_info *)(unsigned char *)_skb->end) +#define bkn_skb_tx_flags(_skb) bkn_skb_shinfo(_skb)->tx_flags +static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb) +{ + return &bkn_skb_shinfo(skb)->hwtstamps; +} +void skb_tstamp_tx(struct sk_buff *orig_skb, struct skb_shared_hwtstamps *hwtstamps) +{ +} +static inline void bkn_skb_tx_timestamp(struct sk_buff *skb) +{ +} +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) +static inline ktime_t ns_to_ktime(u64 ns) +{ + static const ktime_t ktime; + return ktime; +} +#endif +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) +#include +#define HWTSTAMP_TX_ONESTEP_SYNC 2 +enum { + SKBTX_HW_TSTAMP = 1 << 0, + SKBTX_SW_TSTAMP = 1 << 1, + SKBTX_IN_PROGRESS = 1 << 2, +}; +#define bkn_skb_tx_flags(_skb) skb_shinfo(_skb)->tx_flags.flags +static inline void bkn_skb_tx_timestamp(struct sk_buff *skb) +{ +} +#else +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) +#define HWTSTAMP_TX_ONESTEP_SYNC 2 +#endif + +#define bkn_skb_tx_flags(_skb) skb_shinfo(_skb)->tx_flags +static inline void bkn_skb_tx_timestamp(struct sk_buff *skb) +{ + return skb_tx_timestamp(skb); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) +#define bkn_dev_net_set(dev, net) +#else +#define bkn_dev_net_set(dev, net) dev_net_set(dev, net) +#endif + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT +#define BKN_DMA_DEV device +#define BKN_DMA_FROMDEV DMA_FROM_DEVICE +#define BKN_DMA_TODEV DMA_TO_DEVICE +#define BKN_DMA_MAP_SINGLE(d,p,s,r) dma_map_single(d,p,s,r) +#define BKN_DMA_UNMAP_SINGLE(d,a,s,r) dma_unmap_single(d,a,s,r) +#define BKN_DMA_ALLOC_COHERENT(d,s,h) dma_alloc_coherent(d,s,h,GFP_ATOMIC|GFP_DMA32) +#define BKN_DMA_FREE_COHERENT(d,s,a,h) dma_free_coherent(d,s,a,h) +#define BKN_DMA_MAPPING_ERROR(d,a) bkn_dma_mapping_error(d,a) +#else +#define BKN_DMA_DEV pci_dev +#define BKN_DMA_FROMDEV PCI_DMA_FROMDEVICE +#define BKN_DMA_TODEV PCI_DMA_TODEVICE +#define BKN_DMA_MAP_SINGLE(d,p,s,r) pci_map_single(d,p,s,r) +#define BKN_DMA_UNMAP_SINGLE(d,a,s,r) pci_unmap_single(d,a,s,r) +#define BKN_DMA_ALLOC_COHERENT(d,s,h) pci_alloc_consistent(d,s,h) +#define BKN_DMA_FREE_COHERENT(d,s,a,h) pci_free_consistent(d,s,a,h) +#define BKN_DMA_MAPPING_ERROR(d,a) bkn_pci_dma_mapping_error(d,a) +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) +#define BKN_NETDEV_TX_BUSY NETDEV_TX_BUSY +#else +#define BKN_NETDEV_TX_BUSY 1 +#endif + +/* + * Get a 16-bit value from packet offset + * _data Pointer to packet + * _offset Offset + */ +#define PKT_U16_GET(_data, _offset) \ + (uint16_t)(_data[_offset] << 8 | _data[_offset + 1]) + + +/* RCPU operations */ +#define RCPU_OPCODE_RX 0x10 +#define RCPU_OPCODE_TX 0x20 + +/* RCPU flags */ +#define RCPU_F_MODHDR 0x4 + +/* RCPU encapsulation */ +#define RCPU_HDR_SIZE 32 +#define RCPU_TX_META_SIZE 32 +#define RCPU_TX_ENCAP_SIZE (RCPU_HDR_SIZE + RCPU_TX_META_SIZE) +#define RCPU_RX_META_SIZE 64 +#define RCPU_RX_ENCAP_SIZE (RCPU_HDR_SIZE + RCPU_RX_META_SIZE) + +#define PKT_TX_HDR_SIZE 16 + +static volatile int module_initialized; + +static ibde_t *kernel_bde = NULL; + +/* Descriptor info */ +typedef struct bkn_desc_info_s { + uint32_t *dcb_mem; + uint64_t dcb_dma; + struct sk_buff *skb; + uint64_t skb_dma; + uint32_t dma_size; +} bkn_desc_info_t; + +/* DCB chain info */ +typedef struct bkn_dcb_chain_s { + struct list_head list; + int dcb_cnt; + int dcb_cur; + uint32_t *dcb_mem; + uint64_t dcb_dma; +} bkn_dcb_chain_t; + +#define MAX_TX_DCBS 64 +#define MAX_RX_DCBS 64 + +#define NUM_DMA_CHAN 8 +#define NUM_RX_CHAN 7 +#define NUM_CMICX_RX_CHAN 7 +#define NUM_CMICM_RX_CHAN 3 + +#define FCS_SZ 4 +#define TAG_SZ 4 + +/* Device control info */ +typedef struct bkn_switch_info_s { + struct list_head list; + struct list_head ndev_list; /* Associated virtual Ethernet interfaces */ + struct net_device **ndevs; /* Indexed array of ndev_list */ + int ndev_max; /* Size of indexed array */ + struct list_head rxpf_list; /* Associated Rx packet filters */ + volatile void *base_addr; /* Base address for PCI register access */ + struct BKN_DMA_DEV *dma_dev; /* Required for DMA memory control */ + struct pci_dev *pdev; /* Required for DMA memory control */ + struct net_device *dev; /* Base network device */ + struct napi_struct napi; /* New NAPI */ + struct timer_list timer; /* Retry/resource timer */ + int timer_queued; /* Flag indicating queued timer function */ + uint32_t timer_runs; /* Timer function runs (debug only) */ + struct timer_list rxtick; /* Rx rate control timer */ + uint32_t rxticks_per_sec; /* Rx rate control update frequency */ + uint32_t rxtick_jiffies; /* Time between updates (in jiffies) */ + uint32_t rxticks; /* Rx rate control debug counter */ + uint32_t interrupts; /* Total number of interrupts */ + spinlock_t lock; /* Main lock for device */ + int dev_no; /* Device number (from BDE) */ + int cpu_no; /* Cpu number. 1 for iHost(AXI),0 for others */ + int dcb_type; /* DCB type */ + int dcb_wsize; /* DCB size (in 32-bit words) */ + int pkt_hdr_size; /* Packet header size */ + uint32_t ftmh_lb_key_ext_size; /* FTMH LB-Key Extension existence/size */ + uint32_t ftmh_stacking_ext_size; /* FTMH Stacking extension existence/size */ + uint32_t pph_base_size; /* Size of PPH base */ + uint32_t pph_lif_ext_size[8]; /* Size of PPH Lif extension header */ + uint32_t udh_length_type[4]; /* Size of UDH header per type */ + uint32_t udh_size; /* Size of UDH header on legacy devices */ + uint32_t oamp_punt; /* OAMP port if nonzero */ + uint8_t no_skip_udh_check; /* Indicates UDH won't be skipped */ + uint8_t system_headers_mode; /* Indicates system header mode */ + uint8_t udh_enable; /* Indicates UDH existence */ + int rx_chans; /* Number of Rx channels */ + uint32_t dma_hi; /* DMA higher address */ + uint32_t cmic_type; /* CMIC type (CMICe or CMICm) */ + uint32_t irq_mask; /* Active IRQs for DMA control */ + uint32_t napi_poll_mode; /* NAPI is in polling mode */ + uint32_t napi_not_done; /* NAPI poll did not process all packets */ + uint32_t napi_poll_again; /* Used if DCB chain is restarted */ + uint32_t tx_yield; /* Tx schedule for Continuous DMA and Non-NAPI mode */ + void *dcb_mem; /* Logical pointer to DCB memory */ + uint64_t dcb_dma; /* Physical bus address for DCB memory */ + int dcb_mem_size; /* Total size of allocated DCB memory */ + uint32_t dma_events; /* DMA events pending for BCM API */ + uint32_t rcpu_sig; /* RCPU signature */ + uint64_t halt_addr[NUM_DMA_CHAN]; /* DMA halt address */ + uint32_t cdma_channels; /* Active channels for Continuous DMA mode */ + uint32_t poll_channels; /* Channels for polling */ + uint32_t inst_id; /* Instance id of this device */ + int evt_idx; /* Event queue index for this device*/ + int basedev_suspended; /* Base device suspended */ + struct sk_buff_head tx_ptp_queue; /* Tx PTP skb queue */ + struct work_struct tx_ptp_work; /* Tx PTP work */ + struct { + bkn_desc_info_t desc[MAX_TX_DCBS+1]; + int free; /* Number of free Tx DCBs */ + int cur; /* Index of current Tx DCB */ + int dirty; /* Index of next Tx DCB to complete */ + int api_active; /* BCM Tx API is in progress */ + int suspends; /* Calls to netif_stop_queue (debug only) */ + struct list_head api_dcb_list; /* Tx DCB chains from BCM Tx API */ + bkn_dcb_chain_t *api_dcb_chain; /* Current Tx DCB chain */ + bkn_dcb_chain_t *api_dcb_chain_end; /* Tx DCB chain end */ + uint32_t pkts; /* Tx packet counter */ + uint32_t pkts_d_no_skb; /* Tx drop - skb allocation failed */ + uint32_t pkts_d_rcpu_encap; /* Tx drop - bad RCPU encapsulation */ + uint32_t pkts_d_rcpu_sig; /* Tx drop - bad RCPU signature */ + uint32_t pkts_d_rcpu_meta; /* Tx drop - bad RCPU meta data */ + uint32_t pkts_d_pad_fail; /* Tx drop - pad to minimum size failed */ + uint32_t pkts_d_dma_resrc; /* Tx drop - no DMA resources */ + uint32_t pkts_d_callback; /* Tx drop - consumed by call-back */ + uint32_t pkts_d_no_link; /* Tx drop - software link down */ + uint32_t pkts_d_over_limit; /* Tx drop - length is out of range */ + } tx; + struct { + bkn_desc_info_t desc[MAX_RX_DCBS+1]; + int free; /* Number of free Rx DCBs */ + int cur; /* Index of current Rx DCB */ + int dirty; /* Index of next Rx DCB to complete */ + int running; /* Rx DMA is active */ + int api_active; /* BCM Rx API is active */ + int chain_complete; /* All DCBs in chain processed */ + int sync_err; /* Chain done with incomplete DCBs (debug) */ + int sync_retry; /* Total retry times for sync error (debug) */ + int sync_maxloop; /* Max loop times once in recovering sync (debug) */ + int use_rx_skb; /* Use SKBs for DMA */ + uint32_t rate_max; /* Rx rate in packets/sec */ + uint32_t burst_max; /* Rx burst size in number of packets */ + uint32_t tokens; /* Tokens for Rx rate control */ + uint32_t rate; /* Current packet rate */ + unsigned long tok_jif; /* Jiffies at last token update */ + unsigned long rate_jif; /* Jiffies at last rate update */ + struct list_head api_dcb_list; /* Rx DCB chains from BCM Rx API */ + bkn_dcb_chain_t *api_dcb_chain; /* Current Rx DCB chain */ + bkn_dcb_chain_t *api_dcb_chain_end; /* Rx DCB chain end */ + uint32_t pkts; /* Rx packet counter */ + uint32_t pkts_ref; /* Rx packet count for rate calculation */ + uint32_t pkts_f_api; /* Rx packets filtered to API */ + uint32_t pkts_f_netif; /* Rx packets filtered to net interface */ + uint32_t pkts_m_api; /* Rx packets mirrored to API */ + uint32_t pkts_m_netif; /* Rx packets mirrored to net interface */ + uint32_t pkts_d_no_skb; /* Rx drop - skb allocation failed */ + uint32_t pkts_d_no_match; /* Rx drop - no matching filters */ + uint32_t pkts_d_unkn_netif; /* Rx drop - unknown net interface ID */ + uint32_t pkts_d_unkn_dest; /* Rx drop - unknown destination type */ + uint32_t pkts_d_callback; /* Rx drop - consumed by call-back */ + uint32_t pkts_d_no_link; /* Rx drop - software link down */ + uint32_t pkts_d_no_api_buf; /* Rx drop - no API buffers */ + } rx[NUM_RX_CHAN]; +} bkn_switch_info_t; + +#define INVALID_INSTANCE_ID BDE_DEV_INST_ID_INVALID + +/* 0x1 - Jericho 2 mode */ +#define BKN_DNX_JR2_MODE 1 +/* PTCH_2 */ +#define BKN_DNX_PTCH_2_SIZE 2 +/* ITMH */ +#define BKN_DNX_ITMH_SIZE 5 +/* Modlue Header */ +#define BKN_DNX_MODULE_HEADER_SIZE 20 +/* FTMH */ +#define BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_MSB 17 +#define BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_NOF_BITS 16 +#define BKN_DNX_FTMH_PP_DSP_MSB 33 +#define BKN_DNX_FTMH_PP_DSP_NOF_BITS 8 +#define BKN_DNX_FTMH_ACTION_TYPE_MSB 43 +#define BKN_DNX_FTMH_ACTION_TYPE_NOF_BITS 2 +#define BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_MSB 73 +#define BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_NOF_BITS 1 +#define BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_MSB 74 +#define BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_NOF_BITS 1 +#define BKN_DNX_FTMH_TM_DST_EXT_PRESENT_MSB 75 +#define BKN_DNX_FTMH_TM_DST_EXT_PRESENT_NOF_BITS 1 +#define BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_MSB 76 +#define BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_NOF_BITS 1 +#define BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_MSB 77 +#define BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_NOF_BITS 1 +#define BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_MSB 78 +#define BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_NOF_BITS 1 +/* Fix Length for FTMH and Extension headers */ +#define BKN_DNX_FTMH_BASE_SIZE 10 +#define BKN_DNX_FTMH_BIER_BFR_EXT_SIZE 2 +#define BKN_DNX_FTMH_TM_DST_EXT_SIZE 3 +#define BKN_DNX_FTMH_FLOW_ID_EXT_SIZE 3 +#define BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE 6 +/* TSH */ +#define BKN_DNX_TSH_SIZE 4 +/* PPH */ +#define BKN_DNX_INTERNAL_BASE_TYPE_9 9 +#define BKN_DNX_INTERNAL_BASE_TYPE_10 10 +#define BKN_DNX_INTERNAL_BASE_TYPE_12 12 +#define BKN_DNX_INTERNAL_9_FORWARD_DOMAIN_MSB 5 +#define BKN_DNX_INTERNAL_9_FORWARD_DOMAIN_NOF_BITS 16 +#define BKN_DNX_INTERNAL_9_LEARN_EXT_PRESENT_MSB 53 +#define BKN_DNX_INTERNAL_9_LEARN_EXT_PRESENT_NOF_BITS 1 +#define BKN_DNX_INTERNAL_9_FHEI_SIZE_MSB 54 +#define BKN_DNX_INTERNAL_9_FHEI_SIZE_NOF_BITS 2 +#define BKN_DNX_INTERNAL_9_LIF_EXT_TYPE_MSB 56 +#define BKN_DNX_INTERNAL_9_LIF_EXT_TYPE_NOF_BITS 3 +#define BKN_DNX_INTERNAL_10_FORWARD_DOMAIN_MSB 9 +#define BKN_DNX_INTERNAL_10_FORWARD_DOMAIN_NOF_BITS 16 +#define BKN_DNX_INTERNAL_10_LEARN_EXT_PRESENT_MSB 61 +#define BKN_DNX_INTERNAL_10_LEARN_EXT_PRESENT_NOF_BITS 1 +#define BKN_DNX_INTERNAL_10_FHEI_SIZE_MSB 62 +#define BKN_DNX_INTERNAL_10_FHEI_SIZE_NOF_BITS 2 +#define BKN_DNX_INTERNAL_10_LIF_EXT_TYPE_MSB 64 +#define BKN_DNX_INTERNAL_10_LIF_EXT_TYPE_NOF_BITS 3 +#define BKN_DNX_INTERNAL_12_FORWARD_DOMAIN_MSB 21 +#define BKN_DNX_INTERNAL_12_FORWARD_DOMAIN_NOF_BITS 18 +#define BKN_DNX_INTERNAL_12_LEARN_EXT_PRESENT_MSB 77 +#define BKN_DNX_INTERNAL_12_LEARN_EXT_PRESENT_NOF_BITS 1 +#define BKN_DNX_INTERNAL_12_FHEI_SIZE_MSB 78 +#define BKN_DNX_INTERNAL_12_FHEI_SIZE_NOF_BITS 2 +#define BKN_DNX_INTERNAL_12_LIF_EXT_TYPE_MSB 80 +#define BKN_DNX_INTERNAL_12_LIF_EXT_TYPE_NOF_BITS 3 +/* PPH.FHEI_TYPE */ +#define BKN_DNX_INTERNAL_FHEI_TYPE_SZ0 1 +#define BKN_DNX_INTERNAL_FHEI_TYPE_SZ1 2 +#define BKN_DNX_INTERNAL_FHEI_TYPE_SZ2 3 +/* FHEI */ +#define BKN_DNX_INTERNAL_FHEI_SZ0_SIZE 3 +#define BKN_DNX_INTERNAL_FHEI_SZ1_SIZE 5 +#define BKN_DNX_INTERNAL_FHEI_SZ2_SIZE 8 +#define BKN_DNX_INTERNAL_FHEI_TRAP_5B_QUALIFIER_MSB 0 +#define BKN_DNX_INTERNAL_FHEI_TRAP_5B_QUALIFIER_NOF_BITS 27 +#define BKN_DNX_INTERNAL_FHEI_TRAP_5B_CODE_MSB 27 +#define BKN_DNX_INTERNAL_FHEI_TRAP_5B_CODE_NOF_BITS 9 +#define BKN_DNX_INTERNAL_FHEI_TRAP_5B_TYPE_MSB 36 +#define BKN_DNX_INTERNAL_FHEI_TRAP_5B_TYPE_NOF_BITS 4 +/* PPH Extension */ +#define BKN_DNX_INTERNAL_LEARN_EXT_SIZE 19 +/* UDH */ +#define BKN_DNX_UDH_DATA_TYPE_0_MSB 0 +#define BKN_DNX_UDH_DATA_TYPE_0_NOF_BITS 2 +#define BKN_DNX_UDH_DATA_TYPE_1_MSB 2 +#define BKN_DNX_UDH_DATA_TYPE_1_NOF_BITS 2 +#define BKN_DNX_UDH_DATA_TYPE_2_MSB 4 +#define BKN_DNX_UDH_DATA_TYPE_2_NOF_BITS 2 +#define BKN_DNX_UDH_DATA_TYPE_3_MSB 6 +#define BKN_DNX_UDH_DATA_TYPE_3_NOF_BITS 2 +#define BKN_DNX_UDH_BASE_SIZE 1 + +#define BKN_DPP_HDR_MAX_SIZE 40 +/* PTCH_2 */ +#define BKN_DPP_PTCH_2_SIZE 2 +/* ITMH */ +#define BKN_DPP_ITMH_SIZE 4 +/* FTMH */ +#define BKN_DPP_FTMH_LB_EXT_EN 0x1 +#define BKN_DPP_FTMH_STACKING_EXT_EN 0x2 +#define BKN_DPP_FTMH_SIZE_BYTE 9 +#define BKN_DPP_FTMH_LB_EXT_SIZE_BYTE 1 +#define BKN_DPP_FTMH_STACKING_SIZE_BYTE 2 +#define BKN_DPP_FTMH_DEST_EXT_SIZE_BYTE 2 +#define BKN_DPP_FTMH_LB_EXT_SIZE_BYTE 1 +#define BKN_DPP_FTMH_PKT_SIZE_MSB 0 +#define BKN_DPP_FTMH_PKT_SIZE_NOF_BITS 14 +#define BKN_DPP_FTMH_TC_MSB 14 +#define BKN_DPP_FTMH_TC_NOF_BITS 3 +#define BKN_DPP_FTMH_SRC_SYS_PORT_MSB 17 +#define BKN_DPP_FTMH_SRC_SYS_PORT_NOF_BITS 16 +#define BKN_DPP_FTMH_EXT_DSP_EXIST_MSB 68 +#define BKN_DPP_FTMH_EXT_DSP_EXIST_NOF_BITS 1 +#define BKN_DPP_FTMH_EXT_MSB 45 +#define BKN_DPP_FTMH_EXT_NOF_BITS 2 +#define BKN_DPP_FTMH_FIRST_EXT_MSB 72 +#define BKN_DPP_FTMH_ACTION_TYPE_MSB 43 +#define BKN_DPP_FTMH_ACTION_TYPE_NOF_BITS 2 +#define BKN_DPP_FTMH_PPH_TYPE_MSB 45 +#define BKN_DPP_FTMH_PPH_TYPE_NOF_BITS 2 + +/* OTSH */ +#define BKN_DPP_OTSH_SIZE_BYTE 6 +#define BKN_DPP_OTSH_TYPE_MSB 0 +#define BKN_DPP_OTSH_TYPE_NOF_BITS 2 +#define BKN_DPP_OTSH_OAM_SUB_TYPE_MSB 2 +#define BKN_DPP_OTSH_OAM_SUB_TYPE_NOF_BITS 3 + +#define BKN_DPP_OTSH_TYPE_OAM 0 +#define BKN_DPP_OTSH_OAM_SUB_TYPE_DM_1588 2 +#define BKN_DPP_OTSH_OAM_SUB_TYPE_DM_NTP 3 + +#define BKN_DPP_OAM_DM_TOD_SIZE_BYTE 4 + +/* PPH */ +#define BKN_DPP_INTERNAL_SIZE_BYTE 7 +#define BKN_DPP_INTERNAL_EEI_EXTENSION_PRESENT_MSB 0 +#define BKN_DPP_INTERNAL_EEI_EXTENSION_PRESENT_NOF_BITS 1 +#define BKN_DPP_INTERNAL_LEARN_EXENSION_PRESENT_MSB 1 +#define BKN_DPP_INTERNAL_LEARN_EXENSION_PRESENT_NOF_BITS 1 +#define BKN_DPP_INTERNAL_FHEI_SIZE_MSB 2 +#define BKN_DPP_INTERNAL_FHEI_SIZE_NOF_BITS 2 +#define BKN_DPP_INTERNAL_FORWARD_CODE_MSB 4 +#define BKN_DPP_INTERNAL_FORWARD_CODE_NOF_BITS 4 +#define BKN_DPP_INTERNAL_FORWARD_CODE_CPU_TRAP 7 +#define BKN_DPP_INTERNAL_FORWARDING_HEADER_OFFSET_MSB 8 +#define BKN_DPP_INTERNAL_FORWARDING_HEADER_OFFSET_NOF_BITS 7 +#define BKN_DPP_INTERNAL_VSI_MSB 22 +#define BKN_DPP_INTERNAL_VSI_NOF_BITS 16 + +/* FHEI TRAP/SNOOP 3B */ +#define BKN_DPP_INTERNAL_FHEI_3B_SIZE_BYTE 3 +#define BKN_DPP_INTERNAL_FHEI_5B_SIZE_BYTE 5 +#define BKN_DPP_INTERNAL_FHEI_8B_SIZE_BYTE 8 +#define BKN_DPP_INTERNAL_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_MSB 0 +#define BKN_DPP_INTERNAL_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_NOF_BITS 16 +#define BKN_DPP_INTERNAL_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_MSB 16 +#define BKN_DPP_INTERNAL_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_NOF_BITS 8 +/* PPH extension */ +#define BKN_DPP_INTERNAL_EXPLICIT_EDITING_INFOMATION_EXTENSION_SIZE_BYTE 3 +#define BKN_DPP_INTERNAL_LEARN_EXTENSION_SIZE_BYTE 5 + +#define BKN_SAND_SCRATCH_DATA_SIZE 4 + +/* ftmh action type. */ +typedef enum bkn_dpp_ftmh_action_type_e { + BKN_DPP_FTMH_ACTION_TYPE_FORWARD = 0, /* TM action is forward */ + BKN_DPP_FTMH_ACTION_TYPE_SNOOP = 1, /* TM action is snoop */ + BKN_DPP_FTMH_ACTION_TYPE_INBOUND_MIRROR = 2, /* TM action is inbound mirror. */ + BKN_DPP_FTMH_ACTION_TYPE_OUTBOUND_MIRROR = 3 /* TM action is outbound mirror. */ +}bkn_dpp_ftmh_action_type_t; + +/* ftmh dest extension. */ +typedef struct bkn_dpp_ftmh_dest_extension_s { + uint8_t valid; /* Set if the extension is present */ + uint32_t dst_sys_port; /* Destination System Port */ +} bkn_dpp_ftmh_dest_extension_t; + +/* dnx packet */ +typedef struct bkn_dune_system_header_info_s { + uint32_t system_header_size; + struct { + uint32_t action_type; /* Indicates if the copy is one of the Forward Snoop or Mirror packet copies */ + uint32_t source_sys_port_aggregate; /* Source System port*/ + } ftmh; + struct { + uint32_t forward_domain; + uint32_t trap_qualifier; + uint32_t trap_id; + } internal; +} bkn_dune_system_header_info_t; + +#define PREV_IDX(_cur, _max) (((_cur) == 0) ? (_max) - 1 : (_cur) - 1) + +#if defined(CMIC_SOFT_BYTE_SWAP) + +#define CMIC_SWAP32(_x) ((((_x) & 0xff000000) >> 24) \ + | (((_x) & 0x00ff0000) >> 8) \ + | (((_x) & 0x0000ff00) << 8) \ + | (((_x) & 0x000000ff) << 24)) + +#define DEV_READ32(_d, _a, _p) \ + do { \ + uint32_t _data; \ + _data = (((volatile uint32_t *)(_d)->base_addr)[(_a)/4]); \ + *(_p) = CMIC_SWAP32(_data); \ + } while(0) + +#define DEV_WRITE32(_d, _a, _v) \ + do { \ + uint32_t _data = CMIC_SWAP32(_v); \ + ((volatile uint32_t *)(_d)->base_addr)[(_a)/4] = (_data); \ + } while(0) + +#else + +#define DEV_READ32(_d, _a, _p) \ + do { \ + *(_p) = (((volatile uint32_t *)(_d)->base_addr)[(_a)/4]); \ + } while(0) + +#define DEV_WRITE32(_d, _a, _v) \ + do { \ + ((volatile uint32_t *)(_d)->base_addr)[(_a)/4] = (_v); \ + } while(0) + +#endif /* defined(CMIC_SOFT_BYTE_SWAP) */ + +#define MEMORY_BARRIER smp_mb() + +/* Default random MAC address has Broadcom OUI with local admin bit set */ +static u8 bkn_dev_mac[6] = { 0x02, 0x10, 0x18, 0x00, 0x00, 0x00 }; + +static u8 bkn_rcpu_dmac[6]; +static u8 bkn_rcpu_smac[6]; + +/* Driver Proc Entry root */ +static struct proc_dir_entry *bkn_proc_root = NULL; + +typedef struct bkn_priv_s { + struct list_head list; + struct net_device_stats stats; + struct net_device *dev; + bkn_switch_info_t *sinfo; + int id; + int type; + int port; + int qnum; + uint32_t vlan; + uint32_t flags; + uint32_t cb_user_data; + uint8_t system_headers[27]; + uint32_t system_headers_size; + int tx_hwts; /* HW timestamp for Tx */ + int rx_hwts; /* HW timestamp for Rx */ + int phys_port; + struct ethtool_link_settings link_settings; +} bkn_priv_t; + +typedef struct bkn_filter_s { + struct list_head list; + int dev_no; + unsigned long hits; + kcom_filter_t kf; +} bkn_filter_t; + + +/* + * Multiple instance support in KNET + */ +static int _bkn_multi_inst = 0; +typedef struct { + wait_queue_head_t evt_wq; + int evt_wq_put; + int evt_wq_get; + uint32_t inst_id; +} bkn_evt_resource_t; + +static bkn_evt_resource_t _bkn_evt[LINUX_BDE_MAX_DEVICES]; + +static int bkn_knet_dev_init(int d); +static int bkn_knet_dev_reinit(int d); + +/* IOCTL debug counters */ +static int ioctl_cmd; +static int ioctl_evt; + +/* Switch devices */ +LIST_HEAD(_sinfo_list); + +/* Reallocation chunk size for netif array */ +#define NDEVS_CHUNK 64 + +/* User call-backs */ +static knet_skb_cb_f knet_rx_cb = NULL; +static knet_skb_cb_f knet_tx_cb = NULL; +static knet_filter_cb_f knet_filter_cb = NULL; +static knet_hw_tstamp_enable_cb_f knet_hw_tstamp_enable_cb = NULL; +static knet_hw_tstamp_enable_cb_f knet_hw_tstamp_disable_cb = NULL; +static knet_hw_tstamp_tx_time_get_cb_f knet_hw_tstamp_tx_time_get_cb = NULL; +static knet_hw_tstamp_tx_meta_get_cb_f knet_hw_tstamp_tx_meta_get_cb = NULL; +static knet_hw_tstamp_ptp_clock_index_cb_f knet_hw_tstamp_ptp_clock_index_cb = NULL; +static knet_hw_tstamp_rx_time_upscale_cb_f knet_hw_tstamp_rx_time_upscale_cb = NULL; +static knet_hw_tstamp_ioctl_cmd_cb_f knet_hw_tstamp_ioctl_cmd_cb = NULL; +static knet_netif_cb_f knet_netif_create_cb = NULL; +static knet_netif_cb_f knet_netif_destroy_cb = NULL; + +/* + * Thread management + */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) +static void +bkn_sleep(int clicks) +{ + wait_queue_head_t wq; + + init_waitqueue_head(&wq); + sleep_on_timeout(&wq, clicks); +} +#else +static void +bkn_sleep(int clicks) +{ + wait_queue_head_t wq; + + init_waitqueue_head(&wq); + wait_event_timeout(wq, 0, clicks); +} +#endif + +/* + * On XGS devices bit 15 fo the Transferred Bytes field in + * the DCBs is used to indicate that kernel processing is + * complete. Using this bit reduces the theoretically maximum + * supported packet size from 64K to 32K, but this is still + * adequate for 16K jumbo packets. + */ +#define SOC_DCB_KNET_DONE 0x8000 +#define SOC_DCB_KNET_COUNT_MASK 0x7fff +#define SOC_DCB_META_OFFSET 2 + +/* Default channel configuration */ +#define XGS_DMA_TX_CHAN 0 +#define XGS_DMA_RX_CHAN 1 + +/* CMIC registers */ +#define CMIC_DMA_CTRLr 0x00000100 +#define CMIC_DMA_STATr 0x00000104 +#define CMIC_DMA_DESC0r 0x00000110 +#define CMIC_IRQ_STATr 0x00000144 +#define CMIC_IRQ_MASKr 0x00000148 +#define CMIC_DEV_REV_IDr 0x00000178 + +/* CMIC interrupts reserved for kernel handler */ +#define CMIC_TXRX_IRQ_MASK 0x7f80 + +/* CMICm registers */ +#define CMICM_CMC_BASE 0x00031000 +#define CMICM_DMA_CTRLr (CMICM_CMC_BASE + 0x00000140) +#define CMICM_DMA_STATr (CMICM_CMC_BASE + 0x00000150) +#define CMICM_DMA_STAT_CLRr (CMICM_CMC_BASE + 0x000001a4) +#define CMICM_DMA_DESC0r (CMICM_CMC_BASE + 0x00000158) +#define CMICM_DMA_HALT_ADDRr (CMICM_CMC_BASE + 0x00000120) +#define CMICM_IRQ_STATr (CMICM_CMC_BASE + 0x00000400) +#define CMICM_IRQ_PCI_MASKr (CMICM_CMC_BASE + 0x00000414) +#define CMICM_IRQ_UC0_MASKr (CMICM_CMC_BASE + 0x00000428) +#define CMICM_DEV_REV_IDr 0x00010224 + +/* CMICm interrupts reserved for kernel handler */ +#define CMICM_TXRX_IRQ_MASK 0xff00 + +/* CMICd increased interrupts reserved for kernel handler */ +#define CMICD_CTRLD_IRQ_MASK 0x78000000 + +/* CMICx registers */ +#define CMICX_CMC_BASE 0x00000000 +#define CMICX_DMA_CTRLr (CMICX_CMC_BASE + 0x00002100) +#define CMICX_DMA_STATr (CMICX_CMC_BASE + 0x00002114) +#define CMICX_DMA_DESC_HIr (CMICX_CMC_BASE + 0x00002108) +#define CMICX_DMA_DESC_LOr (CMICX_CMC_BASE + 0x00002104) +#define CMICX_DMA_HALT_HIr (CMICX_CMC_BASE + 0x00002110) +#define CMICX_DMA_HALT_LOr (CMICX_CMC_BASE + 0x0000210c) +#define CMICX_IRQ_STATr (CMICX_CMC_BASE + 0x0000106c) +#define CMICX_IRQ_STAT_CLRr (CMICX_CMC_BASE + 0x00001074) +#define CMICX_IRQ_ENABr 0x18013100 +#define IHOST_GIC_GIC400_GICD_ISENABLERN_5r 0x10781114 +#define IHOST_GIC_GIC400_GICD_ICENABLERN_5r 0x10781194 + +/* CMICx interrupts reserved for kernel handler */ +#define CMICX_TXRX_IRQ_MASK 0xffffffff + +#define DEV_IS_CMICX(_sinfo) ((_sinfo)->cmic_type == 'x') +#define DEV_IS_CMICM(_sinfo) ((_sinfo)->cmic_type == 'm') +#define DEV_IS_CMIC(_sinfo) ((_sinfo)->cmic_type != 0) +#define CDMA_CH(_d, _ch) ((_d)->cdma_channels & (1 << (_ch))) + +/* + * DMA_STAT: control bits + * + * xxx_SET and xxx_CLR can be WRITTEN to CMIC_DMA_STAT + * xxx_TST can be masked against values read from CMIC_DMA_STAT. + * Argument required: 0 <= ch <= 3 + */ +#define DS_DMA_ACTIVE(ch) (0x00040000 << (ch)) +#define DS_DMA_EN_SET(ch) (0x80|(ch)) +#define DS_DMA_EN_CLR(ch) (0x00|(ch)) +#define DS_DMA_EN_TST(ch) (0x00000001 << (ch)) + +#define DS_CHAIN_DONE_SET(ch) (0x80|(4+(ch))) +#define DS_CHAIN_DONE_CLR(ch) (0x00|(4+(ch))) +#define DS_CHAIN_DONE_TST(ch) (0x00000010 << (ch)) + +#define DS_DESC_DONE_SET(ch) (0x80|(8+(ch))) +#define DS_DESC_DONE_CLR(ch) (0x00|(8+(ch))) +#define DS_DESC_DONE_TST(ch) (0x00000100 << (ch)) + +#define DC_ABORT_DMA(ch) (0x04 << (8 * (ch))) + +#define DS_CMC_DESCRD_CMPLT_CLR(ch) (0x00000001 << (ch)) +#define DS_CMC_CTRLD_INT_CLR(ch) (0x00000100 << (ch)) +#define DS_CMC_DMA_ACTIVE(ch) (0x00000100 << (ch)) + +#define CMICX_DS_CMC_DESC_DONE(ch) (0x00000001 << ((ch) * 4)) +#define CMICX_DS_CMC_CHAIN_DONE(ch) (0x00000002 << ((ch) * 4)) +#define CMICX_DS_CMC_CTRLD_INT(ch) (0x00000008 << ((ch) * 4)) +#define CMICX_DS_CMC_DMA_CHAIN_DONE (0x00000001) +#define CMICX_DS_CMC_DMA_ACTIVE (0x00000002) + +#define DMA_TO_BUS_HI(dma) ((dma) | sinfo->dma_hi) +#define BUS_TO_DMA_HI(bus) ((bus) & ~sinfo->dma_hi) + +/* + * DMA_CTRL: control bits + */ +#define DC_CMC_DIRECTION (0x00000001) +#define DC_CMC_ENABLE (0x00000002) +#define DC_CMC_ABORT (0x00000004) +#define DC_CMC_CTRLD_INT (0x00000100) +#define DC_CMC_CONTINUOUS (0x00000200) + +#define CMICX_DC_CMC_DIRECTION (0x00000001) +#define CMICX_DC_CMC_ENABLE (0x00000002) +#define CMICX_DC_CMC_ABORT (0x00000004) +#define CMICX_DC_CMC_CTRLD_INT (0x00000080) +#define CMICX_DC_CMC_CONTINUOUS (0x00000100) + +/* + * Per-channel operations. + * These are the basis for the TX/RX functions + */ + +static inline void +xgs_dma_chain_clear(bkn_switch_info_t *sinfo, int chan) +{ + DBG_IRQ(("Clear chain on device %d chan %d\n", + sinfo->dev_no, chan)); + DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DMA_EN_CLR(chan)); + DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_CHAIN_DONE_CLR(chan)); + + MEMORY_BARRIER; +} + +static inline void +xgs_dma_desc_clear(bkn_switch_info_t *sinfo, int chan) +{ + uint32_t val; + + DBG_IRQ(("Clear desc on device %d chan %d\n", + sinfo->dev_no, chan)); + DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DESC_DONE_CLR(chan)); + + MEMORY_BARRIER; + + /* Flush write buffer */ + DEV_READ32(sinfo, CMIC_DMA_STATr, &val); + + MEMORY_BARRIER; +} + +static int +xgs_dma_chan_clear(bkn_switch_info_t *sinfo, int chan) +{ + xgs_dma_chain_clear(sinfo, chan); + xgs_dma_desc_clear(sinfo, chan); + + return 0; +} + +static int +xgs_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir) +{ + uint32_t cdc; + + DEV_READ32(sinfo, CMIC_DMA_CTRLr, &cdc); + + cdc &= ~(0x9 << (8 * chan)); + if (dir) { + cdc |= 0x1 << (8 * chan); + } else { + cdc |= 0x8 << (8 * chan); + } + + DEV_WRITE32(sinfo, CMIC_DMA_CTRLr, cdc); + + return 0; +} + +static int +xgs_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb) +{ + /* Write the DCB address to the DESC address for this channel */ + DEV_WRITE32(sinfo, CMIC_DMA_DESC0r + 4 * chan, dcb); + + MEMORY_BARRIER; + + /* Kick it off */ + DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DMA_EN_SET(chan)); + + MEMORY_BARRIER; + + return 0; +} + +static int +xgs_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls) +{ + uint32_t ctrl, dma_stat; + int p; + + /* Clear enable */ + DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DMA_EN_CLR(chan)); + + MEMORY_BARRIER; + + /* Abort the channel */ + DEV_READ32(sinfo, CMIC_DMA_CTRLr, &ctrl); + DEV_WRITE32(sinfo, CMIC_DMA_CTRLr, ctrl | DC_ABORT_DMA(chan)); + + MEMORY_BARRIER; + + /* Poll for abort completion */ + for (p = 0; p < polls; p++) { + DEV_READ32(sinfo, CMIC_DMA_STATr, &dma_stat); + if (!(dma_stat & DS_DMA_ACTIVE(chan))) { + /* Restore previous control value */ + DEV_WRITE32(sinfo, CMIC_DMA_CTRLr, ctrl); + + MEMORY_BARRIER; + + /* Clear up channel */ + xgs_dma_chan_clear(sinfo, chan); + + return polls; + } + } + DBG_WARN(("DMA channel %d abort failed\n", chan)); + + return -1; +} + +static inline void +xgs_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask) +{ + if (sinfo->napi_poll_mode) { + mask = 0; + } + lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV, CMIC_IRQ_MASKr, + mask, CMIC_TXRX_IRQ_MASK); +} + +static inline void +xgs_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (chan == XGS_DMA_TX_CHAN) { + mask = 0x100; + } else { + mask = 0x180 << (2 * chan); + } + + sinfo->irq_mask |= mask; + + if (update_hw) { + xgs_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +xgs_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (chan == XGS_DMA_TX_CHAN) { + mask = 0x100; + } else { + mask = 0x180 << (2 * chan); + } + + sinfo->irq_mask &= ~mask; + + if (update_hw) { + xgs_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +xgsm_dma_chain_clear(bkn_switch_info_t *sinfo, int chan) +{ + uint32_t cdc; + + /* Disabing DMA clears chain done */ + DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &cdc); + cdc &= ~(DC_CMC_ENABLE | DC_CMC_ABORT); + DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, cdc); + + MEMORY_BARRIER; +} + +static inline void +xgsm_dma_desc_clear(bkn_switch_info_t *sinfo, int chan) +{ + uint32_t val; + + val = DS_CMC_DESCRD_CMPLT_CLR(chan); + if (CDMA_CH(sinfo, chan)) { + val |= DS_CMC_CTRLD_INT_CLR(chan); + } + DEV_WRITE32(sinfo, CMICM_DMA_STAT_CLRr, val); + + MEMORY_BARRIER; + + /* Flush write buffer */ + DEV_READ32(sinfo, CMICM_DMA_STAT_CLRr, &val); + + MEMORY_BARRIER; +} + +static int +xgsm_dma_chan_clear(bkn_switch_info_t *sinfo, int chan) +{ + xgsm_dma_chain_clear(sinfo, chan); + xgsm_dma_desc_clear(sinfo, chan); + + return 0; +} + +static inline void +xgsm_cdma_halt_set(bkn_switch_info_t *sinfo, int chan) +{ + DEV_WRITE32(sinfo, CMICM_DMA_HALT_ADDRr + 4 * chan, + sinfo->halt_addr[chan]); + + MEMORY_BARRIER; +} + +static int +xgsm_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir) +{ + uint32_t cdc; + + DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &cdc); + cdc &= ~DC_CMC_DIRECTION; + if (dir) { + cdc |= DC_CMC_DIRECTION; + } + if (CDMA_CH(sinfo, chan)) { + cdc |= DC_CMC_CONTINUOUS | DC_CMC_CTRLD_INT; + xgsm_cdma_halt_set(sinfo, chan); + } + DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, cdc); + + return 0; +} + +static int +xgsm_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb) +{ + uint32_t cdc; + + /* Write the DCB address to the DESC address for this channel */ + DEV_WRITE32(sinfo, CMICM_DMA_DESC0r + 4 * chan, dcb); + + MEMORY_BARRIER; + + /* Kick it off */ + DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &cdc); + cdc |= DC_CMC_ENABLE; + DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, cdc); + + MEMORY_BARRIER; + + return 0; +} + +static int +xgsm_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls) +{ + uint32_t ctrl, dma_stat; + int p; + + /* Skip abort sequence if channel is not active */ + DEV_READ32(sinfo, CMICM_DMA_STATr, &dma_stat); + if (!(dma_stat & DS_CMC_DMA_ACTIVE(chan))) { + return 0; + } + + /* Abort the channel */ + DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &ctrl); + ctrl |= (DC_CMC_ENABLE | DC_CMC_ABORT); + DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, ctrl); + + MEMORY_BARRIER; + + /* Poll for abort completion */ + for (p = 0; p < polls; p++) { + DEV_READ32(sinfo, CMICM_DMA_STATr, &dma_stat); + if (!(dma_stat & DS_CMC_DMA_ACTIVE(chan))) { + /* Clear up channel */ + xgsm_dma_chan_clear(sinfo, chan); + return polls; + } + } + DBG_WARN(("DMA channel %d abort failed\n", chan)); + + return -1; +} + +static inline void +xgsm_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask) +{ + uint32_t irq_mask_reg = CMICM_IRQ_PCI_MASKr; + uint32_t ctrld_mask = 0; + + if (sinfo->napi_poll_mode) { + mask = 0; + } + if (sinfo->cpu_no == 1) { + irq_mask_reg = CMICM_IRQ_UC0_MASKr; + } + + /* Get the Controlled Interrupts mask for Continuous DMA mode */ + ctrld_mask |= (sinfo->cdma_channels << 27) & CMICD_CTRLD_IRQ_MASK; + + lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV, irq_mask_reg, + mask, CMICM_TXRX_IRQ_MASK | ctrld_mask); +} + +static inline void +xgsm_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (CDMA_CH(sinfo, chan)) { + mask = 0x08000000 << chan; + } else { + if (chan == XGS_DMA_TX_CHAN) { + mask = 0x8000; + } else { + mask = 0xc000 >> (2 * chan); + } + } + + sinfo->irq_mask |= mask; + + if (update_hw) { + xgsm_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +xgsm_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (CDMA_CH(sinfo, chan)) { + mask = 0x08000000 << chan; + } else { + if (chan == XGS_DMA_TX_CHAN) { + mask = 0x8000; + } else { + mask = 0xc000 >> (2 * chan); + } + } + + sinfo->irq_mask &= ~mask; + + if (update_hw) { + xgsm_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +xgsx_dma_chain_clear(bkn_switch_info_t *sinfo, int chan) +{ + uint32_t ctrl, stat; + + /* Disabing DMA clears chain done */ + DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl); + ctrl &= ~(CMICX_DC_CMC_ENABLE | CMICX_DC_CMC_ABORT); + DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl); + + stat = CMICX_DS_CMC_CHAIN_DONE(chan); + DEV_WRITE32(sinfo, CMICX_IRQ_STAT_CLRr, stat); + + MEMORY_BARRIER; + + /* Flush write buffer */ + DEV_READ32(sinfo, CMICX_IRQ_STAT_CLRr, &stat); + + MEMORY_BARRIER; +} + +static inline void +xgsx_dma_desc_clear(bkn_switch_info_t *sinfo, int chan) +{ + uint32_t stat; + + if (CDMA_CH(sinfo, chan)) { + stat = CMICX_DS_CMC_CTRLD_INT(chan); + } else { + stat = CMICX_DS_CMC_DESC_DONE(chan); + } + DEV_WRITE32(sinfo, CMICX_IRQ_STAT_CLRr, stat); + + MEMORY_BARRIER; + + /* Flush write buffer */ + DEV_READ32(sinfo, CMICX_IRQ_STAT_CLRr, &stat); + + MEMORY_BARRIER; +} + +static int +xgsx_dma_chan_clear(bkn_switch_info_t *sinfo, int chan) +{ + xgsx_dma_chain_clear(sinfo, chan); + xgsx_dma_desc_clear(sinfo, chan); + + return 0; +} + +static inline void +xgsx_cdma_halt_set(bkn_switch_info_t *sinfo, int chan) +{ + DEV_WRITE32(sinfo, CMICX_DMA_HALT_LOr + 0x80 * chan, + sinfo->halt_addr[chan]); + DEV_WRITE32(sinfo, CMICX_DMA_HALT_HIr + 0x80 * chan, + DMA_TO_BUS_HI(sinfo->halt_addr[chan] >> 32)); + + MEMORY_BARRIER; +} + +static int +xgsx_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir) +{ + uint32_t ctrl; + + DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl); + ctrl &= ~CMICX_DC_CMC_DIRECTION; + if (dir) { + ctrl |= CMICX_DC_CMC_DIRECTION; + } + if (CDMA_CH(sinfo, chan)) { + ctrl |= CMICX_DC_CMC_CONTINUOUS | CMICX_DC_CMC_CTRLD_INT; + xgsx_cdma_halt_set(sinfo, chan); + } + DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl); + + MEMORY_BARRIER; + + return 0; +} + +static int +xgsx_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb) +{ + uint32_t ctrl; + + /* Write the DCB address to the DESC address for this channel */ + DEV_WRITE32(sinfo, CMICX_DMA_DESC_LOr + 0x80 * chan, dcb); + DEV_WRITE32(sinfo, CMICX_DMA_DESC_HIr + 0x80 * chan, DMA_TO_BUS_HI(dcb >> 32)); + + MEMORY_BARRIER; + + /* Kick it off */ + DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl); + ctrl |= CMICX_DC_CMC_ENABLE; + DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl); + + MEMORY_BARRIER; + + return 0; +} + +static int +xgsx_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls) +{ + uint32_t ctrl, stat; + int p; + + /* Skip abort sequence if channel is not active */ + DEV_READ32(sinfo, CMICX_DMA_STATr + 0x80 * chan, &stat); + if (!(stat & CMICX_DS_CMC_DMA_ACTIVE)) { + return 0; + } + + /* Abort the channel */ + DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl); + ctrl |= CMICX_DC_CMC_ENABLE | CMICX_DC_CMC_ABORT; + DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl); + + MEMORY_BARRIER; + + /* Poll for abort completion */ + for (p = 0; p < polls; p++) { + DEV_READ32(sinfo, CMICX_DMA_STATr + 0x80 * chan, &stat); + if (!(stat & CMICX_DS_CMC_DMA_ACTIVE)) { + /* Clear up channel */ + xgsx_dma_chan_clear(sinfo, chan); + return polls; + } + } + + DBG_WARN(("DMA channel %d abort failed\n", chan)); + + return -1; +} + +static inline void +xgsx_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask) +{ + uint32_t irq_mask_reg = CMICX_IRQ_ENABr; + uint32_t irq_mask, irq_fmask, disable_mask; + + if (sinfo->napi_poll_mode) { + mask = 0; + } + + if (sinfo->cpu_no == 1) { + lkbde_irq_mask_get(sinfo->dev_no, &irq_mask, &irq_fmask); + disable_mask = ~mask & (irq_mask & irq_fmask); + if (disable_mask) { + lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV | LKBDE_IPROC_REG, + IHOST_GIC_GIC400_GICD_ICENABLERN_5r, disable_mask, CMICX_TXRX_IRQ_MASK); + } + irq_mask_reg = IHOST_GIC_GIC400_GICD_ISENABLERN_5r; + } + + lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV | LKBDE_IPROC_REG, + irq_mask_reg, mask, CMICX_TXRX_IRQ_MASK); +} + +static inline void +xgsx_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (CDMA_CH(sinfo, chan)) { + mask = CMICX_DS_CMC_CTRLD_INT(chan); + } else { + if (chan == XGS_DMA_TX_CHAN) { + mask = CMICX_DS_CMC_CHAIN_DONE(chan); + } else { + mask = CMICX_DS_CMC_DESC_DONE(chan) | + CMICX_DS_CMC_CHAIN_DONE(chan); + } + } + + sinfo->irq_mask |= mask; + + if (update_hw) { + xgsx_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +xgsx_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + uint32_t mask; + + if (CDMA_CH(sinfo, chan)) { + mask = CMICX_DS_CMC_CTRLD_INT(chan); + } else { + if (chan == XGS_DMA_TX_CHAN) { + mask = CMICX_DS_CMC_CHAIN_DONE(chan); + } else { + mask = CMICX_DS_CMC_DESC_DONE(chan) | + CMICX_DS_CMC_CHAIN_DONE(chan); + } + } + + sinfo->irq_mask &= ~mask; + + if (update_hw) { + xgsx_irq_mask_set(sinfo, sinfo->irq_mask); + } +} + +static inline void +dev_dma_chain_clear(bkn_switch_info_t *sinfo, int chan) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_dma_chain_clear(sinfo, chan); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_dma_chain_clear(sinfo, chan); + } else { + xgs_dma_chain_clear(sinfo, chan); + } +} + +static inline void +dev_dma_desc_clear(bkn_switch_info_t *sinfo, int chan) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_dma_desc_clear(sinfo, chan); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_dma_desc_clear(sinfo, chan); + } else { + xgs_dma_desc_clear(sinfo, chan); + } +} + +static int +dev_dma_chan_clear(bkn_switch_info_t *sinfo, int chan) +{ + if (DEV_IS_CMICX(sinfo)) { + return xgsx_dma_chan_clear(sinfo, chan); + } else if (DEV_IS_CMICM(sinfo)) { + return xgsm_dma_chan_clear(sinfo, chan); + } else { + return xgs_dma_chan_clear(sinfo, chan); + } +} + +static void +dev_cdma_halt_set(bkn_switch_info_t *sinfo, int chan) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_cdma_halt_set(sinfo, chan); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_cdma_halt_set(sinfo, chan); + } +} + +static int +dev_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir) +{ + if (DEV_IS_CMICX(sinfo)) { + return xgsx_dma_chan_init(sinfo, chan, dir); + } else if (DEV_IS_CMICM(sinfo)) { + return xgsm_dma_chan_init(sinfo, chan, dir); + } else { + return xgs_dma_chan_init(sinfo, chan, dir); + } +} + +static int +dev_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb) +{ + if (DEV_IS_CMICX(sinfo)) { + return xgsx_dma_chan_start(sinfo, chan, dcb); + } else if (DEV_IS_CMICM(sinfo)) { + return xgsm_dma_chan_start(sinfo, chan, dcb); + } else { + return xgs_dma_chan_start(sinfo, chan, dcb); + } +} + +static int +dev_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls) +{ + if (DEV_IS_CMICX(sinfo)) { + return xgsx_dma_chan_abort(sinfo, chan, polls); + } else if (DEV_IS_CMICM(sinfo)) { + return xgsm_dma_chan_abort(sinfo, chan, polls); + } else { + return xgs_dma_chan_abort(sinfo, chan, polls); + } +} + +static inline void +dev_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_irq_mask_set(sinfo, mask); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_irq_mask_set(sinfo, mask); + } else { + xgs_irq_mask_set(sinfo, mask); + } +} + +static inline void +dev_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_irq_mask_enable(sinfo, chan, update_hw); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_irq_mask_enable(sinfo, chan, update_hw); + } else { + xgs_irq_mask_enable(sinfo, chan, update_hw); + } +} + +static void +dev_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw) +{ + if (DEV_IS_CMICX(sinfo)) { + xgsx_irq_mask_disable(sinfo, chan, update_hw); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_irq_mask_disable(sinfo, chan, update_hw); + } else { + xgs_irq_mask_disable(sinfo, chan, update_hw); + } +} + +static int +bkn_alloc_dcbs(bkn_switch_info_t *sinfo) +{ + int dcb_size; + int tx_ring_size, rx_ring_size; + dma_addr_t dcb_dma = 0; + + dcb_size = sinfo->dcb_wsize * sizeof(uint32_t); + tx_ring_size = dcb_size * (MAX_TX_DCBS + 1); + rx_ring_size = dcb_size * (MAX_RX_DCBS + 1); + sinfo->dcb_mem_size = tx_ring_size + rx_ring_size * sinfo->rx_chans; + + sinfo->dcb_mem = BKN_DMA_ALLOC_COHERENT(sinfo->dma_dev, + sinfo->dcb_mem_size, + &dcb_dma); + if (sinfo->dcb_mem == NULL) { + gprintk("DCB memory allocation (%d bytes) failed.\n", + sinfo->dcb_mem_size); + return -ENOMEM; + } + sinfo->dcb_dma = (uint64_t)dcb_dma; + + return 0; +} + +static void +bkn_free_dcbs(bkn_switch_info_t *sinfo) +{ + if (sinfo->dcb_mem != NULL) { + BKN_DMA_FREE_COHERENT(sinfo->dma_dev, sinfo->dcb_mem_size, + sinfo->dcb_mem, (dma_addr_t)sinfo->dcb_dma); + sinfo->dcb_mem = NULL; + } +} + +static void +bkn_clean_tx_dcbs(bkn_switch_info_t *sinfo) +{ + bkn_desc_info_t *desc; + + DBG_DCB_TX(("Cleaning Tx DCBs (%d %d).\n", + sinfo->tx.cur, sinfo->tx.dirty)); + while (sinfo->tx.free < MAX_TX_DCBS) { + desc = &sinfo->tx.desc[sinfo->tx.dirty]; + if (desc->skb != NULL) { + DBG_SKB(("Cleaning Tx SKB from DCB %d.\n", + sinfo->tx.dirty)); + BKN_DMA_UNMAP_SINGLE(sinfo->dma_dev, + desc->skb_dma, desc->dma_size, + BKN_DMA_TODEV); + desc->skb_dma = 0; + dev_kfree_skb_any(desc->skb); + desc->skb = NULL; + } + if (++sinfo->tx.dirty >= MAX_TX_DCBS) { + sinfo->tx.dirty = 0; + } + sinfo->tx.free++; + } + sinfo->tx.api_active = 0; + DBG_DCB_TX(("Cleaned Tx DCBs (%d %d).\n", + sinfo->tx.cur, sinfo->tx.dirty)); +} + +static void +bkn_clean_rx_dcbs(bkn_switch_info_t *sinfo, int chan) +{ + bkn_desc_info_t *desc; + + DBG_DCB_RX(("Cleaning Rx%d DCBs (%d %d).\n", + chan, sinfo->rx[chan].cur, sinfo->rx[chan].dirty)); + while (sinfo->rx[chan].free) { + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty]; + if (desc->skb != NULL) { + DBG_SKB(("Cleaning Rx%d SKB from DCB %d.\n", + chan, sinfo->rx[chan].dirty)); + BKN_DMA_UNMAP_SINGLE(sinfo->dma_dev, + desc->skb_dma, desc->dma_size, + BKN_DMA_FROMDEV); + desc->skb_dma = 0; + dev_kfree_skb_any(desc->skb); + desc->skb = NULL; + } + if (++sinfo->rx[chan].dirty >= MAX_RX_DCBS) { + sinfo->rx[chan].dirty = 0; + } + sinfo->rx[chan].free--; + } + sinfo->rx[chan].running = 0; + sinfo->rx[chan].api_active = 0; + DBG_DCB_RX(("Cleaned Rx%d DCBs (%d %d).\n", + chan, sinfo->rx[chan].cur, sinfo->rx[chan].dirty)); +} + +static void +bkn_clean_dcbs(bkn_switch_info_t *sinfo) +{ + int chan; + + bkn_clean_tx_dcbs(sinfo); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + bkn_clean_rx_dcbs(sinfo, chan); + } +} + +static void +bkn_init_dcbs(bkn_switch_info_t *sinfo) +{ + int dcb_size; + uint32_t *dcb_mem; + uint64_t dcb_dma; + bkn_desc_info_t *desc; + int idx; + int chan; + + memset(sinfo->dcb_mem, 0, sinfo->dcb_mem_size); + + dcb_size = sinfo->dcb_wsize * sizeof(uint32_t); + dcb_mem = sinfo->dcb_mem; + dcb_dma = sinfo->dcb_dma; + + for (idx = 0; idx < (MAX_TX_DCBS + 1); idx++) { + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + if (sinfo->cmic_type == 'x') { + dcb_mem[2] |= 1 << 24 | 1 << 16; + } else { + dcb_mem[1] |= 1 << 24 | 1 << 16; + } + if (idx == MAX_TX_DCBS) { + if (sinfo->cmic_type == 'x') { + dcb_mem[0] = sinfo->tx.desc[0].dcb_dma; + dcb_mem[1] = DMA_TO_BUS_HI(sinfo->tx.desc[0].dcb_dma >> 32); + dcb_mem[2] |= 1 << 18; + } else { + dcb_mem[0] = sinfo->tx.desc[0].dcb_dma; + dcb_mem[1] |= 1 << 18; + } + } + } + desc = &sinfo->tx.desc[idx]; + desc->dcb_mem = dcb_mem; + desc->dcb_dma = dcb_dma; + dcb_mem += sinfo->dcb_wsize; + dcb_dma += dcb_size; + } + sinfo->halt_addr[XGS_DMA_TX_CHAN] = sinfo->tx.desc[0].dcb_dma; + sinfo->tx.free = MAX_TX_DCBS; + sinfo->tx.cur = 0; + sinfo->tx.dirty = 0; + + DBG_DCB_TX(("Tx DCBs @ 0x%08x.\n", + (uint32_t)sinfo->tx.desc[0].dcb_dma)); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + for (idx = 0; idx < (MAX_RX_DCBS + 1); idx++) { + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + if (sinfo->cmic_type == 'x') { + dcb_mem[2] |= 1 << 24 | 1 << 16; + } else { + dcb_mem[1] |= 1 << 24 | 1 << 16; + } + if (idx == MAX_RX_DCBS) { + if (sinfo->cmic_type == 'x') { + dcb_mem[0] = sinfo->rx[chan].desc[0].dcb_dma; + dcb_mem[1] = DMA_TO_BUS_HI(sinfo->rx[chan].desc[0].dcb_dma >> 32); + dcb_mem[2] |= 1 << 18; + } else { + dcb_mem[0] = sinfo->rx[chan].desc[0].dcb_dma; + dcb_mem[1] |= 1 << 18; + } + } + } + desc = &sinfo->rx[chan].desc[idx]; + desc->dcb_mem = dcb_mem; + desc->dcb_dma = dcb_dma; + dcb_mem += sinfo->dcb_wsize; + dcb_dma += dcb_size; + } + sinfo->halt_addr[XGS_DMA_RX_CHAN + chan] = sinfo->rx[chan].desc[MAX_RX_DCBS].dcb_dma; + sinfo->rx[chan].free = 0; + sinfo->rx[chan].cur = 0; + sinfo->rx[chan].dirty = 0; + + DBG_DCB_RX(("Rx%d DCBs @ 0x%08x.\n", + chan, (uint32_t)sinfo->rx[chan].desc[0].dcb_dma)); + } +} + +static void +bkn_dump_dcb(char *prefix, uint32_t *dcb, int wsize, int txrx) +{ + if (XGS_DMA_TX_CHAN == txrx) { + if (wsize > 4) { + DBG_DCB_TX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x ... 0x%08x\n", + prefix, dcb[0], dcb[1], dcb[2], dcb[3], dcb[4], dcb[5], + dcb[wsize - 1])); + } else { + DBG_DCB_TX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x\n", + prefix, dcb[0], dcb[1], dcb[2], dcb[3])); + } + } else { + if (wsize > 4) { + DBG_DCB_RX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x ... 0x%08x\n", + prefix, dcb[0], dcb[1], dcb[2], dcb[3], dcb[4], dcb[5], + dcb[wsize - 1])); + } else { + DBG_DCB_RX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x\n", + prefix, dcb[0], dcb[1], dcb[2], dcb[3])); + } + } +} + +static void +bkn_dump_pkt(uint8_t *data, int size, int txrx) +{ + int idx; + char str[128]; + + if (!(debug & DBG_LVL_PDMP) && + !(txrx == XGS_DMA_TX_CHAN && debug & DBG_LVL_PDMP_TX) && + !(txrx == XGS_DMA_RX_CHAN && debug & DBG_LVL_PDMP_RX)) { + return; + } + + for (idx = 0; idx < size; idx++) { + if ((idx & 0xf) == 0) { + sprintf(str, "%04x: ", idx); + } + if ((idx & 0xf) == 8) { + sprintf(&str[strlen(str)], "- "); + } + sprintf(&str[strlen(str)], "%02x ", data[idx]); + if ((idx & 0xf) == 0xf) { + sprintf(&str[strlen(str)], "\n"); + gprintk(str); + } + } + if ((idx & 0xf) != 0) { + sprintf(&str[strlen(str)], "\n"); + gprintk(str); + } +} + +static bkn_switch_info_t * +bkn_sinfo_from_unit(int unit) +{ + struct list_head *list; + bkn_switch_info_t *sinfo; + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + if (sinfo->dev_no == unit || unit == -1) { + return sinfo; + } + } + return NULL; +} + +static void +bkn_cdma_goto(bkn_switch_info_t *sinfo, int chan, uint64_t dcb) +{ + if (sinfo->basedev_suspended) { + return; + } + + /* Set the new halt location */ + sinfo->halt_addr[chan] = dcb; + dev_cdma_halt_set(sinfo, chan); +} + +static void +bkn_api_rx_restart(bkn_switch_info_t *sinfo, int chan) +{ + bkn_dcb_chain_t *dcb_chain; + int start_dma; + + if (sinfo->basedev_suspended) { + return; + } + + /* If resume from basedev suspended, there could be a suspended chain */ + if (sinfo->rx[chan].api_dcb_chain) { + return; + } + + /* Assume that driver lock is held */ + if (!list_empty(&sinfo->rx[chan].api_dcb_list)) { + dcb_chain = list_entry(sinfo->rx[chan].api_dcb_list.next, + bkn_dcb_chain_t, list); + start_dma = 0; + if (sinfo->rx[chan].use_rx_skb == 0) { + sinfo->rx[chan].chain_complete = 0; + start_dma = 1; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && + sinfo->rx[chan].api_active) { + /* HW is running already, so we just move to the next chain */ + start_dma = 0; + } + } + sinfo->rx[chan].api_dcb_chain = dcb_chain; + sinfo->rx[chan].api_active = 1; + if (start_dma) { + DBG_DCB_RX(("Start API Rx DMA, first DCB @ 0x%08x (%d DCBs).\n", + (uint32_t)dcb_chain->dcb_dma, dcb_chain->dcb_cnt)); + dev_dma_chan_clear(sinfo, XGS_DMA_RX_CHAN + chan); + dev_irq_mask_enable(sinfo, XGS_DMA_RX_CHAN + chan, 1); + dev_dma_chan_start(sinfo, XGS_DMA_RX_CHAN + chan, dcb_chain->dcb_dma); + } + + list_del(&dcb_chain->list); + } +} + +static void +bkn_api_rx_chain_done(bkn_switch_info_t *sinfo, int chan) +{ + DBG_DCB_RX(("API Rx DMA chain done\n")); + + if (!CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + sinfo->rx[chan].api_active = 0; + } + if (sinfo->rx[chan].api_dcb_chain) { + kfree(sinfo->rx[chan].api_dcb_chain); + sinfo->rx[chan].api_dcb_chain = NULL; + } + bkn_api_rx_restart(sinfo, chan); +} + +static int +bkn_api_rx_copy_from_skb(bkn_switch_info_t *sinfo, + int chan, bkn_desc_info_t *desc, int rx_hwts) +{ + bkn_dcb_chain_t *dcb_chain; + uint32_t *dcb; + uint32_t dcb_stat; + uint8_t *pkt; + uint8_t *skb_pkt; + uint64_t pkt_dma; + int pktlen; + int i; + bkn_evt_resource_t *evt; + + dcb_stat = desc->dcb_mem[sinfo->dcb_wsize-1]; + pktlen = dcb_stat & SOC_DCB_KNET_COUNT_MASK; + + dcb_chain = sinfo->rx[chan].api_dcb_chain; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && dcb_chain == NULL) { + /* Last chain done, try to get a new one */ + bkn_api_rx_chain_done(sinfo, chan); + dcb_chain = sinfo->rx[chan].api_dcb_chain; + } + if (dcb_chain == NULL) { + DBG_WARN(("No Rx API buffers\n")); + sinfo->rx[chan].pkts_d_no_api_buf++; + return -1; + } + dcb = &dcb_chain->dcb_mem[dcb_chain->dcb_cur * sinfo->dcb_wsize]; + if ((sinfo->cmic_type == 'x' && (dcb[2] & 0xffff) < pktlen) || + (sinfo->cmic_type != 'x' && (dcb[1] & 0xffff) < pktlen)) { + DBG_WARN(("Rx API buffer too small\n")); + return -1; + } + if (sinfo->cmic_type == 'x') { + pkt_dma = BUS_TO_DMA_HI(dcb[1]); + pkt_dma = pkt_dma << 32 | dcb[0]; + } else { + pkt_dma = dcb[0]; + } + pkt = (uint8_t *)kernel_bde->p2l(sinfo->dev_no, (sal_paddr_t)pkt_dma); + if (pkt == NULL) { + DBG_WARN(("Invalid Rx API buffer\n")); + return -1; + } + + skb_pkt = desc->skb->data; + + /* Strip custom header from KNETSync packets. */ + if ((rx_hwts) && + ((skb_pkt[0] == 'B') && (skb_pkt[1] == 'C') && + (skb_pkt[2] == 'M') && (skb_pkt[3] == 'C'))) { + + skb_pkt = skb_pkt + skb_pkt[4]; + } + + /* Copy packet data */ + memcpy(pkt, skb_pkt, pktlen); + + /* Copy packet metadata and mark as done */ + if (sinfo->cmic_type != 'x') { + for (i = SOC_DCB_META_OFFSET; i < sinfo->dcb_wsize; i++) { + dcb[i] = desc->dcb_mem[i]; + } + } + dcb[sinfo->dcb_wsize-1] = dcb_stat | SOC_DCB_KNET_DONE; + MEMORY_BARRIER; + + dcb_chain->dcb_cur++; + + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + dcb = &dcb_chain->dcb_mem[dcb_chain->dcb_cur * sinfo->dcb_wsize]; + if ((sinfo->cmic_type == 'x' && dcb[2] & (1 << 18)) || + (sinfo->cmic_type != 'x' && dcb[1] & (1 << 18))) { + /* Get the next chain if reload done */ + dcb[sinfo->dcb_wsize-1] |= 1 << 31 | SOC_DCB_KNET_DONE; + MEMORY_BARRIER; + bkn_api_rx_chain_done(sinfo, chan); + dcb_chain = sinfo->rx[chan].api_dcb_chain; + if (dcb_chain == NULL) { + sinfo->rx[chan].api_dcb_chain_end = NULL; + } + } + } else { + if ((sinfo->cmic_type == 'x' && (dcb[2] & (1 << 16)) == 0) || + (sinfo->cmic_type != 'x' && (dcb[1] & (1 << 16)) == 0)) { + bkn_api_rx_chain_done(sinfo, chan); + } + } + + sinfo->dma_events |= KCOM_DMA_INFO_F_RX_DONE; + + evt = &_bkn_evt[sinfo->evt_idx]; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + + return 0; +} + +static void +bkn_rx_refill(bkn_switch_info_t *sinfo, int chan) +{ + struct sk_buff *skb; + bkn_desc_info_t *desc; + uint32_t *dcb; + uint32_t resv_size = sinfo->cmic_type == 'x' ? RCPU_HDR_SIZE : RCPU_RX_ENCAP_SIZE; + uint32_t meta_size = sinfo->cmic_type == 'x' ? RCPU_RX_META_SIZE : 0; + int prev; + + if (sinfo->rx[chan].use_rx_skb == 0) { + /* Rx buffers are provided by BCM Rx API */ + return; + } + + if (!CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && + sinfo->rx[chan].tokens < MAX_RX_DCBS) { + /* Pause DMA for now */ + return; + } + + while (sinfo->rx[chan].free < MAX_RX_DCBS) { + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].cur]; + if (desc->skb == NULL) { + skb = dev_alloc_skb(rx_buffer_size + SKB_DATA_ALIGN(resv_size)); + if (skb == NULL) { + break; + } + skb_reserve(skb, SKB_DATA_ALIGN(resv_size)); + desc->skb = skb; + } else { + DBG_DCB_RX(("Refill Rx%d SKB in DCB %d recycled.\n", + chan, sinfo->rx[chan].cur)); + } + skb = desc->skb; + desc->dma_size = rx_buffer_size + meta_size; +#ifdef KNET_NO_AXI_DMA_INVAL + /* + * FIXME: Need to retain this code until iProc customers have been + * migrated to updated u-boot. Old u-boot versions are unable to load + * the kernel into non-ACP memory. + */ + /* + * Cache invalidate may corrupt DMA memory on some iProc-based devices + * if the kernel is mapped to ACP memory. + */ + if (sinfo->pdev == NULL) { + desc->dma_size = 0; + } +#endif + desc->skb_dma = BKN_DMA_MAP_SINGLE(sinfo->dma_dev, + skb->data, desc->dma_size, + BKN_DMA_FROMDEV); + if (BKN_DMA_MAPPING_ERROR(sinfo->dma_dev, desc->skb_dma)) { + dev_kfree_skb_any(skb); + desc->skb = NULL; + break; + } + DBG_DCB_RX(("Refill Rx%d DCB %d (0x%08x).\n", + chan, sinfo->rx[chan].cur, (uint32_t)desc->skb_dma)); + dcb = desc->dcb_mem; + dcb[0] = desc->skb_dma; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + if (sinfo->cmic_type == 'x') { + dcb[2] |= 1 << 24 | 1 << 16; + } else { + dcb[1] |= 1 << 24 | 1 << 16; + } + } else { + prev = PREV_IDX(sinfo->rx[chan].cur, MAX_RX_DCBS); + if (prev < (MAX_RX_DCBS - 1)) { + if (sinfo->cmic_type == 'x') { + sinfo->rx[chan].desc[prev].dcb_mem[2] |= 1 << 16; + } else { + sinfo->rx[chan].desc[prev].dcb_mem[1] |= 1 << 16; + } + } + } + if (sinfo->cmic_type == 'x') { + dcb[1] = DMA_TO_BUS_HI(desc->skb_dma >> 32); + dcb[2] |= rx_buffer_size + meta_size; + } else { + dcb[1] |= rx_buffer_size; + } + + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && + sinfo->rx[chan].tokens > MAX_RX_DCBS) { + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma); + } + + if (++sinfo->rx[chan].cur >= MAX_RX_DCBS) { + sinfo->rx[chan].cur = 0; + } + sinfo->rx[chan].free++; + sinfo->rx[chan].tokens--; + } +} + +static int +bkn_rx_restart(bkn_switch_info_t *sinfo, int chan) +{ + bkn_desc_info_t *desc; + + if (sinfo->basedev_suspended) { + return 0; + } + + if (sinfo->rx[chan].running) { + return 0; + } + + if (sinfo->rx[chan].free < MAX_RX_DCBS) { + return 1; + } + + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty]; + sinfo->rx[chan].chain_complete = 0; + DBG_DCB_RX(("Restart Rx%d DMA, DCB @ 0x%08x (%d).\n", + chan, (uint32_t)desc->dcb_dma, sinfo->rx[chan].dirty)); + dev_dma_chan_clear(sinfo, XGS_DMA_RX_CHAN + chan); + dev_irq_mask_enable(sinfo, XGS_DMA_RX_CHAN + chan, 1); + dev_dma_chan_start(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma); + sinfo->rx[chan].running = 1; + + /* Request one extra poll if chain was restarted during poll */ + if (sinfo->napi_poll_mode) { + sinfo->napi_poll_again = 1; + } + + return 0; +} + +static int +bkn_tx_dma_start(bkn_switch_info_t *sinfo) +{ + bkn_desc_info_t *desc; + + desc = &sinfo->tx.desc[sinfo->tx.cur]; + if (sinfo->tx.free == MAX_TX_DCBS) { + if (!sinfo->tx.api_active) { + DBG_DCB_TX(("Start Tx DMA, DCB @ 0x%08x (%d).\n", + (uint32_t)desc->dcb_dma, sinfo->tx.cur)); + dev_dma_chan_clear(sinfo, XGS_DMA_TX_CHAN); + dev_irq_mask_enable(sinfo, XGS_DMA_TX_CHAN, 1); + dev_dma_chan_start(sinfo, XGS_DMA_TX_CHAN, desc->dcb_dma); + } + } + + return 0; +} + +static int +bkn_dma_init(bkn_switch_info_t *sinfo) +{ + int chan; + + dev_dma_chan_init(sinfo, XGS_DMA_TX_CHAN, 1); + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + bkn_tx_dma_start(sinfo); + } + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + dev_dma_chan_init(sinfo, XGS_DMA_RX_CHAN + chan, 0); + bkn_rx_refill(sinfo, chan); + bkn_rx_restart(sinfo, chan); + } + + return 0; +} + +static int +bkn_dma_abort_tx(bkn_switch_info_t *sinfo) +{ + bkn_dcb_chain_t *dcb_chain; + + DBG_VERB(("Aborting Tx DMA.\n")); + + dev_irq_mask_disable(sinfo, XGS_DMA_TX_CHAN, 1); + + dev_dma_chan_abort(sinfo, XGS_DMA_TX_CHAN, 10000); + + if (sinfo->tx.api_dcb_chain) { + DBG_DCB_TX(("Freeing active Tx DCB chain.\n")); + kfree(sinfo->tx.api_dcb_chain); + sinfo->tx.api_dcb_chain = NULL; + } + while (!list_empty(&sinfo->tx.api_dcb_list)) { + dcb_chain = list_entry(sinfo->tx.api_dcb_list.next, + bkn_dcb_chain_t, list); + list_del(&dcb_chain->list); + DBG_DCB_TX(("Freeing Tx DCB chain.\n")); + kfree(dcb_chain); + } + sinfo->tx.api_dcb_chain_end = NULL; + + return 0; +} + +static int +bkn_dma_abort_rx(bkn_switch_info_t *sinfo, int chan) +{ + bkn_dcb_chain_t *dcb_chain; + + DBG_VERB(("Aborting Rx%d DMA.\n", chan)); + + dev_irq_mask_disable(sinfo, XGS_DMA_RX_CHAN + chan, 1); + + dev_dma_chan_abort(sinfo, XGS_DMA_RX_CHAN + chan, 10000); + + if (sinfo->rx[chan].api_dcb_chain) { + DBG_DCB_RX(("Freeing active Rx%d DCB chain.\n", chan)); + kfree(sinfo->rx[chan].api_dcb_chain); + sinfo->rx[chan].api_dcb_chain = NULL; + } + while (!list_empty(&sinfo->rx[chan].api_dcb_list)) { + dcb_chain = list_entry(sinfo->rx[chan].api_dcb_list.next, + bkn_dcb_chain_t, list); + list_del(&dcb_chain->list); + DBG_DCB_RX(("Freeing Rx%d DCB chain.\n", chan)); + kfree(dcb_chain); + } + sinfo->rx[chan].api_dcb_chain_end = NULL; + + return 0; +} + +static int +bkn_dma_abort(bkn_switch_info_t *sinfo) +{ + int chan; + + bkn_dma_abort_tx(sinfo); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + bkn_dma_abort_rx(sinfo, chan); + } + + return 0; +} + +static int +device_is_dpp(bkn_switch_info_t *sinfo) +{ + int is_dpp = 0; + + is_dpp = (sinfo->dcb_type == 28) ? 1 : 0; + return is_dpp; +} + +static int +device_is_dnx(bkn_switch_info_t *sinfo) +{ + int is_dnx = 0; + + is_dnx = (sinfo->dcb_type == 39) ? 1 : 0; + return is_dnx; +} + +/* is DPP or is DNX*/ +static int +device_is_sand(bkn_switch_info_t *sinfo) +{ + int is_sand = 0; + + if (device_is_dpp(sinfo) || device_is_dnx(sinfo)) { + is_sand = 1; + } + return is_sand; +} + +static bkn_filter_t * +bkn_match_rx_pkt(bkn_switch_info_t *sinfo, uint8_t *pkt, int pktlen, + void *meta, int chan, bkn_filter_t *cbf) +{ + struct list_head *list; + bkn_filter_t *filter; + kcom_filter_t scratch, *kf; + uint8_t *oob = (uint8_t *)meta; + int size, wsize; + int idx, match; + + list_for_each(list, &sinfo->rxpf_list) { + filter = (bkn_filter_t *)list; + kf = &filter->kf; + memcpy(&scratch.data.b[0], + &oob[kf->oob_data_offset], kf->oob_data_size); + memcpy(&scratch.data.b[kf->oob_data_size], + &pkt[kf->pkt_data_offset], kf->pkt_data_size); + size = kf->oob_data_size + kf->pkt_data_size; + wsize = BYTES2WORDS(size); + DBG_VERB(("Filter: size = %d (%d), data = 0x%08x, mask = 0x%08x\n", + size, wsize, kf->data.w[0], kf->mask.w[0])); + + if (device_is_sand(sinfo)) { + DBG_DUNE(("Filter: size = %d (wsize %d)\n", size, wsize)); + for (idx = 0; idx < wsize; idx++) + { + DBG_DUNE(("OOB[%d]: 0x%08x [0x%08x]\n", idx, kf->data.w[idx], kf->mask.w[idx])); + } + DBG_DUNE(("Meta Data [+ Selected Raw packet data]\n")); + for (idx = 0; idx < wsize; idx++) + { + DBG_DUNE(("Scratch[%d]: 0x%08x\n", idx, scratch.data.w[idx])); + } + } + + match = 1; + if (match) { + if (device_is_dnx(sinfo)) + { + /* + * Mutliple RX channels are enabled on JR2 and above devices + * Bind between priority 0 and RX channel 0 is not checked, then all enabled RX channels can receive packets. + */ + if (kf->priority && (kf->priority < (num_rx_prio * sinfo->rx_chans))) { + if (kf->priority < (num_rx_prio * chan) || + kf->priority >= (num_rx_prio * (chan + 1))) { + match = 0; + } + } + } + else { + if (kf->priority < (num_rx_prio * sinfo->rx_chans)) { + if (kf->priority < (num_rx_prio * chan) || + kf->priority >= (num_rx_prio * (chan + 1))) { + match = 0; + } + } + } + } + if (match) { + for (idx = 0; idx < wsize; idx++) { + scratch.data.w[idx] &= kf->mask.w[idx]; + if (scratch.data.w[idx] != kf->data.w[idx]) { + match = 0; + break; + } + } + } + if (match) { + if (kf->dest_type == KCOM_DEST_T_CB) { + /* Check for custom filters */ + if (knet_filter_cb != NULL && cbf != NULL) { + memset(cbf, 0, sizeof(*cbf)); + memcpy(&cbf->kf, kf, sizeof(cbf->kf)); + if (knet_filter_cb(pkt, pktlen, sinfo->dev_no, + meta, chan, &cbf->kf)) { + filter->hits++; + return cbf; + } + } else { + DBG_FLTR(("Match, but not filter callback\n")); + } + } else { + filter->hits++; + return filter; + } + } + } + + return NULL; +} + +static bkn_priv_t * +bkn_netif_lookup(bkn_switch_info_t *sinfo, int id) +{ + struct list_head *list; + bkn_priv_t *priv; + int found; + + /* Fast path */ + if (id < sinfo->ndev_max) { + if (sinfo->ndevs[id] != NULL) { + DBG_NDEV(("Look up netif ID %d successful\n", id)); + return netdev_priv(sinfo->ndevs[id]); + } + } + + /* Slow path - should normally not get here */ + found = 0; + priv = NULL; + list_for_each(list, &sinfo->ndev_list) { + priv = (bkn_priv_t *)list; + if (priv->id == id) { + found = 1; + break; + } + } + if (found && priv != NULL) { + return priv; + } + return NULL; +} + +static int +bkn_hw_tstamp_rx_set(bkn_switch_info_t *sinfo, int phys_port, struct sk_buff *skb, uint32 *meta) +{ + struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); + uint64_t ts = 0; + + + if (knet_hw_tstamp_rx_time_upscale_cb) { + if (knet_hw_tstamp_rx_time_upscale_cb(sinfo->dev_no, phys_port, skb, meta, &ts) < 0) { + return -1; + } + } + + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); + shhwtstamps->hwtstamp = ns_to_ktime(ts); + + return 0; +} + +static int +bkn_add_rcpu_encap(bkn_switch_info_t *sinfo, struct sk_buff *skb, void *meta, int len) +{ + int pktlen = skb->len; + uint32_t *dmeta, *smeta, wsize, psize; + int idx; + + /* Add and clear RCPU encapsulation */ + if (device_is_sand(sinfo)) { + psize = RCPU_RX_ENCAP_SIZE; + skb_push(skb, psize); + memset(skb->data, 0, RCPU_RX_ENCAP_SIZE); + } else if (sinfo->cmic_type == 'x') { + psize = RCPU_HDR_SIZE + sinfo->pkt_hdr_size; + skb_push(skb, psize); + memset(skb->data, 0, RCPU_HDR_SIZE); + } else { + psize = RCPU_RX_ENCAP_SIZE; + skb_push(skb, psize); + memset(skb->data, 0, RCPU_RX_ENCAP_SIZE); + } + + /* RCPU Header */ + memcpy(skb->data, &skb->data[psize], 12); + if (rcpu_dmac != NULL) { + memcpy(skb->data, bkn_rcpu_dmac, 6); + } + if (rcpu_smac != NULL) { + memcpy(&skb->data[6], bkn_rcpu_smac, 6); + } + skb->data[12] = 0x81; + skb->data[14] = rcpu_vlan >> 8; + skb->data[15] = rcpu_vlan & 0xff; + skb->data[16] = rcpu_ethertype >> 8; + skb->data[17] = rcpu_ethertype & 0xff; + skb->data[18] = sinfo->rcpu_sig >> 8; + skb->data[19] = sinfo->rcpu_sig & 0xff; + skb->data[20] = RCPU_OPCODE_RX; + skb->data[21] = RCPU_F_MODHDR; + skb->data[24] = pktlen >> 8; + skb->data[25] = pktlen & 0xff; + + /* Meta data */ + dmeta = (uint32_t *)&skb->data[RCPU_HDR_SIZE]; + + if (device_is_sand(sinfo)) { + /* Copy at most 64 bytes system headers */ + len = len > RCPU_RX_META_SIZE ? RCPU_RX_META_SIZE : len; + memcpy(&skb->data[RCPU_HDR_SIZE], (uint8_t *)meta, len); + } else { + smeta = sinfo->cmic_type == 'x' ? (uint32_t *)meta : (uint32_t *)meta + 2; + wsize = sinfo->cmic_type == 'x' ? sinfo->pkt_hdr_size / 4 : sinfo->dcb_wsize - 3; + for (idx = 0; idx < wsize; idx++) { + dmeta[idx] = htonl(smeta[idx]); + } + } + + + return 0; +} + +static void +bkn_eth_type_update(struct sk_buff *skb, int ethertype) +{ +#if defined(PM_ETH_TYPE) && defined(PM_FC_TYPE) + /* Optionally override standard protocol */ + skb->protocol = PM_ETH_TYPE; + if (ethertype == ETH_P_FCOE) { + skb->protocol = PM_FC_TYPE; + } +#endif +} + +#define BKN_DNX_BIT(x) (1<<(x)) +#define BKN_DNX_RBIT(x) (~(1<<(x))) +#ifdef __LITTLE_ENDIAN +#define BKN_DNX_BYTE_SWAP(x) (x) +#else +#define BKN_DNX_BYTE_SWAP(x) ((((x) << 24)) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) >> 24))) +#endif + +static int +packet_is_untagged(uint16_t tpid) +{ + int is_untagged = 0; + + /* 0x8100 is used in 802.1Q */ + /* 0x8848 is used in 802.11ad, the dtag tpid can be set to anything besides 0x8848, 0x9100 is a typical value, but couldn't cover all scenarios. */ + is_untagged = ((tpid != 0x8100) && (tpid != 0x8848) && (tpid != 0x9100)); + return is_untagged; +} + +static void +bkn_bitstream_set_field(uint32_t *input_buffer, uint32_t start_bit, uint32_t nof_bits, uint32_t field) +{ + uint32_t place; + uint32_t field_bit_i; + uint32_t bit_indicator; + + if( nof_bits > 32) + { + return; + } + + for( place=start_bit, field_bit_i = 0; field_bit_i< nof_bits; ++place, ++field_bit_i) + { + bit_indicator = field & BKN_DNX_BIT(nof_bits-field_bit_i-1); + if(bit_indicator) + { + input_buffer[place>>5] |= (0x80000000 >> (place & 0x0000001F)); + } + else + { + input_buffer[place>>5] &= ~(0x80000000 >> (place & 0x0000001F)); + } + } + return; +} + +static void +bkn_bitstream_get_field(uint8_t *input_buffer, uint32_t start_bit, uint32_t nof_bits, uint32_t *output_value) +{ + uint32_t idx; + uint32_t buf_sizes=0; + uint32_t tmp_output_value[2]={0}; + uint32_t first_byte_ndx; + uint32_t last_byte_ndx; + uint32_t place; + uint32_t field_bit_i; + uint8_t *tmp_output_value_u8_ptr = (uint8_t*)&tmp_output_value; + uint32_t bit_indicator; + + if (nof_bits > 32) + { + return; + } + + first_byte_ndx = start_bit / 8; + last_byte_ndx = ((start_bit + nof_bits - 1) / 8); + *output_value=0; + + /* get 32 bit value, MSB */ + for (idx = first_byte_ndx; idx <= last_byte_ndx; ++idx) + { + tmp_output_value_u8_ptr[last_byte_ndx - idx] = input_buffer[idx]; + buf_sizes += 8; + } + tmp_output_value[0] = BKN_DNX_BYTE_SWAP(tmp_output_value[0]); + if (last_byte_ndx > 4) + { + tmp_output_value[1] = BKN_DNX_BYTE_SWAP(tmp_output_value[1]); + } + + place = buf_sizes - (start_bit % 8 + nof_bits); + for (field_bit_i = 0; field_bit_i< nof_bits; ++place, ++field_bit_i) + { + uint32_t result; + result = tmp_output_value[place>>5] & BKN_DNX_BIT(place & 0x0000001F); + if (result) + { + bit_indicator = 1; + } else { + bit_indicator = 0; + } + *output_value |= bit_indicator << field_bit_i; + } + return; +} + +static void +bkn_dpp_packet_parse_ftmh( + bkn_switch_info_t *sinfo, + uint8_t *buf, + uint32_t buf_len, + bkn_dune_system_header_info_t *packet_info, + uint8_t *is_tsh_en, + uint8_t *is_inter_hdr_en) +{ + uint32_t pkt_offset = packet_info->system_header_size; + uint32_t dsp_ext_exist = 0; + uint32_t fld_val; + + /* FTMH: Source-system-port-aggregate */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_FTMH_SRC_SYS_PORT_MSB, + BKN_DPP_FTMH_SRC_SYS_PORT_NOF_BITS, + &packet_info->ftmh.source_sys_port_aggregate); + /* FTMH: TM-action-type */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_FTMH_ACTION_TYPE_MSB, + BKN_DPP_FTMH_ACTION_TYPE_NOF_BITS, + &packet_info->ftmh.action_type); + /* FTMH: Internal-type */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_FTMH_PPH_TYPE_MSB, + BKN_DPP_FTMH_PPH_TYPE_NOF_BITS, + &fld_val); + + /* FTMH: DSP Extension */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_FTMH_EXT_DSP_EXIST_MSB, + BKN_DPP_FTMH_EXT_DSP_EXIST_NOF_BITS, + &dsp_ext_exist); + + if (fld_val & 0x1) + { + *is_inter_hdr_en = TRUE; + } + if (fld_val & 0x2) + { + *is_tsh_en = TRUE; + } + + pkt_offset += BKN_DPP_FTMH_SIZE_BYTE; + DBG_DUNE(("FTMH(9-%u): Action-type %d Source-system-port 0x%x\n", pkt_offset, + packet_info->ftmh.action_type, + packet_info->ftmh.source_sys_port_aggregate)); + + /* FTMH LB-Key Extension */ + if (sinfo->ftmh_lb_key_ext_size) + { + pkt_offset += sinfo->ftmh_lb_key_ext_size; + DBG_DUNE(("FTMH LB-Key Extension(1-%u) is present\n", pkt_offset)); + } + + if (dsp_ext_exist) + { + pkt_offset += BKN_DPP_FTMH_DEST_EXT_SIZE_BYTE; + DBG_DUNE(("FTMH DSP Extension(2-%u) is present\n", pkt_offset)); + } + + /* FTMH Stacking Extension */ + if (sinfo->ftmh_stacking_ext_size) + { + pkt_offset += sinfo->ftmh_stacking_ext_size; + DBG_DUNE(("FTMH Stacking Extension(2-%u) is present\n", pkt_offset)); + } + + packet_info->system_header_size = pkt_offset; + return; +} + +static void +bkn_dpp_packet_parse_otsh( + bkn_switch_info_t *sinfo, + uint8_t *buf, + uint32_t buf_len, + bkn_dune_system_header_info_t *packet_info, + uint8_t *is_oam_dm_tod_en, + uint8_t *is_skip_udh) +{ + uint32_t pkt_offset = packet_info->system_header_size; + uint32_t type = 0; + uint32_t oam_sub_type = 0; + + /* OTSH: TYPE */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_OTSH_TYPE_MSB, + BKN_DPP_OTSH_TYPE_NOF_BITS, + &type); + if (type == BKN_DPP_OTSH_TYPE_OAM) { + /* OTSH: OAM_SUB_TYPE */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_OTSH_OAM_SUB_TYPE_MSB, + BKN_DPP_OTSH_OAM_SUB_TYPE_NOF_BITS, + &oam_sub_type); + if ((oam_sub_type == BKN_DPP_OTSH_OAM_SUB_TYPE_DM_1588) || (oam_sub_type == BKN_DPP_OTSH_OAM_SUB_TYPE_DM_NTP)) { + *is_oam_dm_tod_en = TRUE; + /* Down MEP DM trapped packets will not have UDH present (even if configured), except for QAX when custom_feature_oam_dm_tod_msb_add_enable=0 */ + if (!sinfo->no_skip_udh_check) { + *is_skip_udh = TRUE; + } + } + } + packet_info->system_header_size += BKN_DPP_OTSH_SIZE_BYTE; + + DBG_DUNE(("OTSH(%d): Type 0x%x OAM-Sub-Type 0x%x\n", BKN_DPP_OTSH_SIZE_BYTE, type, oam_sub_type)); + return; +} + +static void +bkn_dpp_packet_parse_internal( + bkn_switch_info_t *sinfo, + uint8_t *buf, + uint32_t buf_len, + bkn_dune_system_header_info_t *packet_info, + uint8_t is_oamp_punted, + uint8_t *is_trapped) +{ + uint32_t pkt_offset = packet_info->system_header_size; + uint32_t fld_val = 0; + uint32_t eei_extension_present = 0; + uint32_t learn_extension_present = 0; + uint32_t fhei_size = 0; + + /* Internal: EEI EXT */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_INTERNAL_EEI_EXTENSION_PRESENT_MSB, + BKN_DPP_INTERNAL_EEI_EXTENSION_PRESENT_NOF_BITS, + &eei_extension_present); + /* Internal: LERAN EXT */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_INTERNAL_LEARN_EXENSION_PRESENT_MSB, + BKN_DPP_INTERNAL_LEARN_EXENSION_PRESENT_NOF_BITS, + &learn_extension_present); + /* Internal: FHEI EXT */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_INTERNAL_FHEI_SIZE_MSB, + BKN_DPP_INTERNAL_FHEI_SIZE_NOF_BITS, + &fhei_size); + /* Internal: FORWARD_CODE */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_INTERNAL_FORWARD_CODE_MSB, + BKN_DPP_INTERNAL_FORWARD_CODE_NOF_BITS, + &fld_val); + *is_trapped = (uint8_t)(fld_val == BKN_DPP_INTERNAL_FORWARD_CODE_CPU_TRAP); + /* Internal: VSI */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_INTERNAL_VSI_MSB, + BKN_DPP_INTERNAL_VSI_NOF_BITS, + &fld_val); + packet_info->internal.forward_domain = fld_val; + + if (is_oamp_punted && *is_trapped) { + if(fhei_size == 3) { + /* Force to FHEI size 1 when packets are punted by OAMP */ + fhei_size = 1; + } + } + + /* Move forward to end of Internal header */ + pkt_offset += BKN_DPP_INTERNAL_SIZE_BYTE; + + DBG_DUNE(("PPH(7-%u): EEI-Extension %d Learn-Extension %d VSI %d FHEI-size %d\n", + pkt_offset, eei_extension_present,learn_extension_present, packet_info->internal.forward_domain, fhei_size)); + + /* Advance header according to FHEI Trap extension */ + switch(fhei_size) { + case 1: + /* 3B FHEI Extension: do nothing, header poniter is in the right location */ + break; + case 2: + /* 5B FHEI Extension: adavance header pointer in 2B */ + pkt_offset += 2; + break; + case 3: + /* 8B FHEI Extension: adavance header pointer in 5B */ + pkt_offset += 5; + break; + default: + break; + } + + /* Internal extension */ + if (*is_trapped && fhei_size) + { + /* CPU trap code qualifier */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_INTERNAL_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_MSB, + BKN_DPP_INTERNAL_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_NOF_BITS, + &packet_info->internal.trap_qualifier); + /* CPU trap code */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DPP_INTERNAL_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_MSB, + BKN_DPP_INTERNAL_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_NOF_BITS, + &packet_info->internal.trap_id); + + DBG_DUNE(("FHEI: trap_qualifier 0x%x trap_id 0x%x\n", + packet_info->internal.trap_qualifier, + packet_info->internal.trap_id)); + } + + /* Move forward to end of FHEI Trap extension */ + if (fhei_size) { + pkt_offset += 3; + } + + /* EEI extension */ + if (eei_extension_present) { + pkt_offset += BKN_DPP_INTERNAL_EXPLICIT_EDITING_INFOMATION_EXTENSION_SIZE_BYTE; + } + /* Learn extension */ + if (learn_extension_present) { + pkt_offset += BKN_DPP_INTERNAL_LEARN_EXTENSION_SIZE_BYTE; + } + + packet_info->system_header_size = pkt_offset; + return; +} + +static int +bkn_dpp_packet_header_parse( + bkn_switch_info_t *sinfo, + uint8_t *buff, + uint32_t buff_len, + bkn_dune_system_header_info_t *packet_info) +{ + uint8_t is_inter_hdr_en = FALSE; + uint8_t is_tsh_en = FALSE; + uint8_t is_oamp_punted = FALSE; + uint8_t is_trapped = FALSE; + uint8_t is_oam_dm_tod_en = FALSE; + uint8_t is_skip_udh = FALSE; + + if ((sinfo == NULL) || (buff == NULL) || (packet_info == NULL)) { + return -1; + } + + /* FTMH */ + bkn_dpp_packet_parse_ftmh(sinfo, buff, buff_len, packet_info, &is_tsh_en, &is_inter_hdr_en); + /* Check if packet is punted from OAMP */ + if (sinfo->oamp_punt && (packet_info->ftmh.source_sys_port_aggregate == sinfo->oamp_punt)) { + is_oamp_punted = TRUE; + } + /* OTSH */ + if (is_tsh_en == TRUE) + { + bkn_dpp_packet_parse_otsh(sinfo, buff, buff_len, packet_info, &is_oam_dm_tod_en, &is_skip_udh); + } + /* Internal header is forced to be present if packet was punted to CPU by OAMP */ + if (sinfo->oamp_punt && (packet_info->ftmh.source_sys_port_aggregate == sinfo->oamp_punt)) + { + is_inter_hdr_en = TRUE; + } + /* Internal */ + if (is_inter_hdr_en) + { + bkn_dpp_packet_parse_internal(sinfo, buff, buff_len, packet_info, is_oamp_punted, &is_trapped); + } + /* Skip UDH for the outer layer when packet is punted by OAM for JR2 in JR1 mode */ + if (device_is_dnx(sinfo) && is_oamp_punted) { + is_skip_udh = TRUE; + } + /* UDH */ + if (sinfo->udh_size && !is_skip_udh) { + packet_info->system_header_size += sinfo->udh_size; + } + /* OAM DM TOD header */ + if(is_oam_dm_tod_en) { + packet_info->system_header_size += BKN_DPP_OAM_DM_TOD_SIZE_BYTE; + } + + /* Additional layer of system headers */ + if (is_oamp_punted && is_trapped) + { + is_inter_hdr_en = FALSE; + is_tsh_en = FALSE; + is_oamp_punted = FALSE; + is_trapped = FALSE; + is_oam_dm_tod_en = FALSE; + is_skip_udh = FALSE; + + /* FTMH */ + bkn_dpp_packet_parse_ftmh(sinfo, buff, buff_len, packet_info, &is_tsh_en, &is_inter_hdr_en); + /* OTSH */ + if (is_tsh_en == TRUE) + { + bkn_dpp_packet_parse_otsh(sinfo, buff, buff_len, packet_info, &is_oam_dm_tod_en, &is_skip_udh); + } + /* Internal */ + if (is_inter_hdr_en) + { + bkn_dpp_packet_parse_internal(sinfo, buff, buff_len, packet_info, is_oamp_punted, &is_trapped); + } + /* OAMP Punted packets do not have UDH in the inner header for both JR1 and JR2 in JR1 mode */ + /* OAM DM TOD header */ + if(is_oam_dm_tod_en) { + packet_info->system_header_size += BKN_DPP_OAM_DM_TOD_SIZE_BYTE; + } + } + + DBG_DUNE(("Total length of headers is %u\n", packet_info->system_header_size)); + + return 0; +} + + +static int +bkn_dnx_packet_parse_ftmh( + bkn_switch_info_t *sinfo, + uint8_t *buf, + uint32_t buf_len, + bkn_dune_system_header_info_t *packet_info, + uint8_t *is_tsh_en, + uint8_t *is_inter_hdr_en) +{ + uint32_t fld_val; + uint32_t pkt_offset = packet_info->system_header_size; + uint8_t tm_dst_ext_present = 0; + uint8_t app_specific_ext_size = 0; + uint8_t flow_id_ext_size = 0; + uint8_t bier_bfr_ext_size = 0; + + if ((sinfo == NULL) || (buf == NULL) || (packet_info == NULL)) { + return -1; + } + + /* FTMH: Source-System-Port-Aggregate */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_MSB, + BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_NOF_BITS, + &fld_val); + packet_info->ftmh.source_sys_port_aggregate = fld_val; + /* FTMH: Action-Type */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_FTMH_ACTION_TYPE_MSB, + BKN_DNX_FTMH_ACTION_TYPE_NOF_BITS, + &fld_val); + packet_info->ftmh.action_type = fld_val; + /* FTMH: PPH-Type TSH */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_MSB, + BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_NOF_BITS, + &fld_val); + *is_tsh_en = fld_val; + /* FTMH: PPH-Type PPH base */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_MSB, + BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_NOF_BITS, + &fld_val); + *is_inter_hdr_en = fld_val; + /* FTMH: TM-Destination-Extension-Present */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_FTMH_TM_DST_EXT_PRESENT_MSB, + BKN_DNX_FTMH_TM_DST_EXT_PRESENT_NOF_BITS, + &fld_val); + tm_dst_ext_present = fld_val; + /* FTMH: Application-Specific-Extension-Size */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_MSB, + BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_NOF_BITS, + &fld_val); + app_specific_ext_size = fld_val; + /* FTMH: Flow-ID-Extension-Size */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_MSB, + BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_NOF_BITS, + &fld_val); + flow_id_ext_size = fld_val; + /* FTMH: BIER-BFR-Extension-Size */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_MSB, + BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_NOF_BITS, + &fld_val); + bier_bfr_ext_size = fld_val; + + pkt_offset += BKN_DNX_FTMH_BASE_SIZE; + + DBG_DUNE(("FTMH(10-%u): source-system-port 0x%x action_type %u is_tsh_en %u is_inter_hdr_en %u\n", + pkt_offset, packet_info->ftmh.source_sys_port_aggregate, + packet_info->ftmh.action_type, *is_tsh_en, *is_inter_hdr_en)); + + /* FTMH LB-Key Extension */ + if (sinfo->ftmh_lb_key_ext_size > 0) + { + pkt_offset += sinfo->ftmh_lb_key_ext_size; + DBG_DUNE(("FTMH LB-Key Extension(%u-%u) is present\n", sinfo->ftmh_lb_key_ext_size, pkt_offset)); + } + /* FTMH Stacking Extension */ + if (sinfo->ftmh_stacking_ext_size > 0) + { + pkt_offset += sinfo->ftmh_stacking_ext_size; + DBG_DUNE(("FTMH Stacking Extension(%u-%u) is present\n", sinfo->ftmh_stacking_ext_size, pkt_offset)); + } + /* FTMH BIER BFR Extension */ + if (bier_bfr_ext_size > 0) + { + pkt_offset += BKN_DNX_FTMH_BIER_BFR_EXT_SIZE; + DBG_DUNE(("FTMH BIER BFR Extension(2-%u) is present\n", pkt_offset)); + } + /* FTMH TM Destination Extension */ + if (tm_dst_ext_present > 0) + { + pkt_offset += BKN_DNX_FTMH_TM_DST_EXT_SIZE; + DBG_DUNE(("FTMH TM Destination Extension(3-%u) is present\n", pkt_offset)); + } + /* FTMH Application Specific Extension */ + if (app_specific_ext_size > 0) + { + pkt_offset += BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE; + DBG_DUNE(("FTMH Application Specific Extension(6-%u) is present\n", pkt_offset)); + } + /* FTMH Flow-ID Extension */ + if (flow_id_ext_size > 0) + { + pkt_offset += BKN_DNX_FTMH_FLOW_ID_EXT_SIZE; + DBG_DUNE(("FTMH Flow-ID Extension(3-%u) is present\n", pkt_offset)); + } + + packet_info->system_header_size = pkt_offset; + + return 0; +} + + +static int +bkn_dnx_packet_parse_internal( + bkn_switch_info_t *sinfo, + uint8_t *buf, + uint32_t buf_len, + bkn_dune_system_header_info_t *packet_info, + uint8_t is_oamp_punted, + uint8_t *is_trapped) +{ + uint32_t fld_val; + uint32_t pkt_offset = packet_info->system_header_size; + uint8_t learn_ext_present; + uint8_t fhei_size; + uint8_t lif_ext_type; + uint8_t udh_en = sinfo->udh_enable; + + if ((sinfo == NULL) || (buf == NULL) || (packet_info == NULL)) { + return -1; + } + + /* Internal: Forward-Domain */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_INTERNAL_12_FORWARD_DOMAIN_MSB, + BKN_DNX_INTERNAL_12_FORWARD_DOMAIN_NOF_BITS, + &fld_val); + packet_info->internal.forward_domain = fld_val; + /* Internal: Learn-Extension-Present */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_INTERNAL_12_LEARN_EXT_PRESENT_MSB, + BKN_DNX_INTERNAL_12_LEARN_EXT_PRESENT_NOF_BITS, + &fld_val); + learn_ext_present = fld_val; + /* Internal: FHEI-Size */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_INTERNAL_12_FHEI_SIZE_MSB, + BKN_DNX_INTERNAL_12_FHEI_SIZE_NOF_BITS, + &fld_val); + fhei_size = fld_val; + /* Internal: LIF-Extension-Type */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_INTERNAL_12_LIF_EXT_TYPE_MSB, + BKN_DNX_INTERNAL_12_LIF_EXT_TYPE_NOF_BITS, + &fld_val); + lif_ext_type = fld_val; + + pkt_offset += BKN_DNX_INTERNAL_BASE_TYPE_12; + DBG_DUNE(("Internal(12-%u): FWD_DOMAIN %d, LEARN_EXT %d, FHEI_SIZE %d, LIF_EXT %d \n", + pkt_offset, packet_info->internal.forward_domain, + learn_ext_present, fhei_size, lif_ext_type)); + + if (fhei_size) + { + switch (fhei_size) + { + case BKN_DNX_INTERNAL_FHEI_TYPE_SZ0: + pkt_offset += BKN_DNX_INTERNAL_FHEI_SZ0_SIZE; + DBG_DUNE(("FHEI(3-%u) is present\n", pkt_offset)); + break; + case BKN_DNX_INTERNAL_FHEI_TYPE_SZ1: + /* FHEI: Type */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_INTERNAL_FHEI_TRAP_5B_TYPE_MSB, + BKN_DNX_INTERNAL_FHEI_TRAP_5B_TYPE_NOF_BITS, + &fld_val); + /* FHEI-Size == 5B, FHEI-Type == Trap/Sniff */ + if (fld_val == 0x5) + { + *is_trapped = TRUE; + /* FHEI: Qualifier */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_INTERNAL_FHEI_TRAP_5B_QUALIFIER_MSB, + BKN_DNX_INTERNAL_FHEI_TRAP_5B_QUALIFIER_NOF_BITS, + &fld_val); + packet_info->internal.trap_qualifier = fld_val; + /* FHEI: Code */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_INTERNAL_FHEI_TRAP_5B_CODE_MSB, + BKN_DNX_INTERNAL_FHEI_TRAP_5B_CODE_NOF_BITS, + &fld_val); + packet_info->internal.trap_id= fld_val; + } + pkt_offset += BKN_DNX_INTERNAL_FHEI_SZ1_SIZE; + DBG_DUNE(("FHEI(5-%u): code 0x%x qualifier 0x%x\n", pkt_offset, packet_info->internal.trap_id, packet_info->internal.trap_qualifier)); + break; + case BKN_DNX_INTERNAL_FHEI_TYPE_SZ2: + pkt_offset += BKN_DNX_INTERNAL_FHEI_SZ1_SIZE; + DBG_DUNE(("FHEI(8-%u) is present\n", pkt_offset)); + break; + } + } + + /* PPH LIF Extension */ + if (lif_ext_type) + { + pkt_offset += sinfo->pph_lif_ext_size[lif_ext_type]; + DBG_DUNE(("PPH LIF Extension(%d-%u) is present\n", sinfo->pph_lif_ext_size[lif_ext_type], pkt_offset)); + } + + /* PPH Learn Extension */ + if (learn_ext_present) + { + pkt_offset += BKN_DNX_INTERNAL_LEARN_EXT_SIZE; + DBG_DUNE(("PPH Learn Extension(19-%u) is present\n", pkt_offset)); + } + + /** Skip UDH If packet is punted to CPU by OAMP */ + if (is_oamp_punted) { + udh_en = FALSE; + } + + /* UDH Header */ + if (udh_en) + { + uint8_t data_type_0; + uint8_t data_type_1; + uint8_t data_type_2; + uint8_t data_type_3; + + /* UDH: UDH-Data-Type[0] */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_UDH_DATA_TYPE_0_MSB, + BKN_DNX_UDH_DATA_TYPE_0_NOF_BITS, + &fld_val); + data_type_0 = fld_val; + /* UDH: UDH-Data-Type[1] */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_UDH_DATA_TYPE_1_MSB, + BKN_DNX_UDH_DATA_TYPE_1_NOF_BITS, + &fld_val); + data_type_1 = fld_val; + /* UDH: UDH-Data-Type[2] */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_UDH_DATA_TYPE_2_MSB, + BKN_DNX_UDH_DATA_TYPE_2_NOF_BITS, + &fld_val); + data_type_2 = fld_val; + /* UDH: UDH-Data-Type[3] */ + bkn_bitstream_get_field( + &buf[pkt_offset], + BKN_DNX_UDH_DATA_TYPE_3_MSB, + BKN_DNX_UDH_DATA_TYPE_3_NOF_BITS, + &fld_val); + data_type_3 = fld_val; + pkt_offset += BKN_DNX_UDH_BASE_SIZE; + pkt_offset += sinfo->udh_length_type[data_type_0]; + pkt_offset += sinfo->udh_length_type[data_type_1]; + pkt_offset += sinfo->udh_length_type[data_type_2]; + pkt_offset += sinfo->udh_length_type[data_type_3]; + DBG_DUNE(("UDH base(1-%u) is present\n", pkt_offset)); + } + + packet_info->system_header_size = pkt_offset; + + return 0; +} + +static int +bkn_dnx_packet_header_parse( + bkn_switch_info_t *sinfo, + uint8_t *buff, + uint32_t buff_len, + bkn_dune_system_header_info_t *packet_info) +{ + uint8_t is_inter_hdr_en = FALSE; + uint8_t is_tsh_en = FALSE; + uint8_t is_oamp_punted = FALSE; + uint8_t is_trapped = FALSE; + + if ((sinfo == NULL) || (buff == NULL) || (packet_info == NULL)) { + return -1; + } + + /* FTMH */ + bkn_dnx_packet_parse_ftmh(sinfo, buff, buff_len, packet_info, &is_tsh_en, &is_inter_hdr_en); + + /* Time-Stamp */ + if (is_tsh_en == TRUE) + { + packet_info->system_header_size += BKN_DNX_TSH_SIZE; + DBG_DUNE(("Time-Stamp Header(4-%u) is present\n", packet_info->system_header_size)); + } + + /* Check if packet was punted to CPU by OAMP */ + if ((packet_info->ftmh.source_sys_port_aggregate == 232) + || (packet_info->ftmh.source_sys_port_aggregate == 233)) + { + is_oamp_punted = TRUE; + } + + /* Internal */ + if (is_inter_hdr_en) + { + bkn_dnx_packet_parse_internal(sinfo, buff, buff_len, packet_info, is_oamp_punted, &is_trapped); + } + + if (is_oamp_punted) + { + is_inter_hdr_en = FALSE; + is_tsh_en = FALSE; + is_oamp_punted = FALSE; + is_trapped = FALSE; + + /* FTMH */ + bkn_dnx_packet_parse_ftmh(sinfo, buff, buff_len, packet_info, &is_tsh_en, &is_inter_hdr_en); + /* Time-Stamp */ + if (is_tsh_en == TRUE) + { + packet_info->system_header_size += BKN_DNX_TSH_SIZE; + DBG_DUNE(("Time-Stamp Header(4-%u) is present\n", packet_info->system_header_size)); + } + /* Internal */ + if (is_inter_hdr_en) + { + bkn_dnx_packet_parse_internal(sinfo, buff, buff_len, packet_info, is_oamp_punted, &is_trapped); + } + } + + DBG_DUNE(("Total length of headers is %u\n", packet_info->system_header_size)); + + return 0; +} + +static int +bkn_packet_header_parse(bkn_switch_info_t *sinfo, uint8_t *buf, uint32_t buf_len, bkn_dune_system_header_info_t *packet_info) +{ + if (device_is_dpp(sinfo)) + { + bkn_dpp_packet_header_parse(sinfo, buf, buf_len, packet_info); + } + else if (device_is_dnx(sinfo)) + { + if (sinfo->system_headers_mode == BKN_DNX_JR2_MODE) + { + /* Jericho 2 mode */ + bkn_dnx_packet_header_parse(sinfo, buf, buf_len, packet_info); + } + else + { + /* Jericho/QMX/QAX mode */ + bkn_dpp_packet_header_parse(sinfo, buf, buf_len, packet_info); + } + } + return 0; +} + +static int +bkn_do_api_rx(bkn_switch_info_t *sinfo, int chan, int budget) +{ + bkn_priv_t *priv; + bkn_dcb_chain_t *dcb_chain; + struct sk_buff *skb; + bkn_filter_t cbf; + bkn_filter_t *filter; + uint32_t err_woff; + uint32_t *dcb, *meta; + uint8_t *pkt; + uint64_t pkt_dma; + int drop_api; + int ethertype; + int pktlen; + int idx; + int dcbs_done = 0; + bkn_dune_system_header_info_t packet_info; + uint32_t sand_scratch_data[BKN_SAND_SCRATCH_DATA_SIZE] = {0}; + + dcb_chain = sinfo->rx[chan].api_dcb_chain; + if (dcb_chain == NULL) { + /* No active chains */ + return 0; + } + + while (dcb_chain->dcb_cur < dcb_chain->dcb_cnt) { + dcb = &dcb_chain->dcb_mem[dcb_chain->dcb_cur * sinfo->dcb_wsize]; + DBG_VERB(("DCB %2d: 0x%08x\n", + dcb_chain->dcb_cur, dcb[sinfo->dcb_wsize-1])); + if ((dcb[sinfo->dcb_wsize-1] & (1 << 31)) == 0) { + break; + } + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + /* Handle for Continuous DMA mode */ + if (dcbs_done >= budget) { + break; + } + if ((sinfo->cmic_type == 'x' && dcb[2] & (1 << 18)) || + (sinfo->cmic_type != 'x' && dcb[1] & (1 << 18))) { + dcb[sinfo->dcb_wsize-1] |= SOC_DCB_KNET_DONE; + bkn_api_rx_chain_done(sinfo, chan); + dcb_chain = sinfo->rx[chan].api_dcb_chain; + if (dcb_chain == NULL) { + break; + } + continue; + } + } + if ((sinfo->cmic_type == 'x' && (dcb[2] & (1 << 16)) == 0) || + (sinfo->cmic_type != 'x' && (dcb[1] & (1 << 16)) == 0)) { + sinfo->rx[chan].chain_complete = 1; + } + sinfo->rx[chan].pkts++; + if (sinfo->cmic_type == 'x') { + pkt_dma = BUS_TO_DMA_HI(dcb[1]); + pkt_dma = pkt_dma << 32 | dcb[0]; + } else { + pkt_dma = dcb[0]; + } + pkt = (uint8_t *)kernel_bde->p2l(sinfo->dev_no, (sal_paddr_t)pkt_dma); + + if (device_is_sand(sinfo)) { + err_woff = BKN_SAND_SCRATCH_DATA_SIZE - 1; + sand_scratch_data[err_woff] = dcb[sinfo->dcb_wsize-1]; + meta = (uint32_t *)pkt; + } else { + if (sinfo->cmic_type == 'x') { + meta = (uint32_t *)pkt; + err_woff = sinfo->pkt_hdr_size / sizeof(uint32_t) - 1; + meta[err_woff] = dcb[sinfo->dcb_wsize-1]; + } else { + meta = dcb; + err_woff = sinfo->dcb_wsize - 1; + } + } + + pktlen = dcb[sinfo->dcb_wsize-1] & SOC_DCB_KNET_COUNT_MASK; + bkn_dump_pkt(pkt, pktlen, XGS_DMA_RX_CHAN); + + if (device_is_sand(sinfo)) { + memset(&packet_info, 0, sizeof(bkn_dune_system_header_info_t)); + /* decode system headers and fill sratch data */ + bkn_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info); + bkn_bitstream_set_field(sand_scratch_data, 0, 16, packet_info.internal.trap_id); + bkn_bitstream_set_field(sand_scratch_data, 16, 16, packet_info.internal.trap_qualifier); + bkn_bitstream_set_field(sand_scratch_data, 32, 16, packet_info.ftmh.source_sys_port_aggregate); + bkn_bitstream_set_field(sand_scratch_data, 48, 16, packet_info.internal.forward_domain); + bkn_bitstream_set_field(sand_scratch_data, 64, 2, packet_info.ftmh.action_type); + + if (force_tagged) { + uint8_t *eth_hdr = pkt + packet_info.system_header_size; + uint16_t tpid = 0; + + tpid = PKT_U16_GET(eth_hdr, 12); + if (packet_is_untagged(tpid)) { + int raw_packet_len = pktlen - packet_info.system_header_size; + uint32_t vid = 0; + + if ((pktlen + 4) < rx_buffer_size) { + for (idx = (raw_packet_len - 1); idx >= 12; idx--) { + eth_hdr[idx+4] = eth_hdr[idx]; + } + if (ft_vid) { + vid = ft_vid; + } + else if (packet_info.internal.forward_domain) { + vid = packet_info.internal.forward_domain & 0xfff; + } + else { + vid = 1; + } + DBG_DUNE(("add vlan tag (%d) to untagged packets\n", vid)); + + eth_hdr[12] = (ft_tpid >> 8) & 0xff; + eth_hdr[13] = ft_tpid & 0xff; + eth_hdr[14] = (((ft_pri & 0x7) << 5) | ((ft_cfi & 0x1) << 4) | ((vid >> 8) & 0xf)) & 0xff; + eth_hdr[15] = vid & 0xff; + /* reset packet length in DCB */ + pktlen += 4; + bkn_dump_pkt(pkt, pktlen, XGS_DMA_RX_CHAN); + dcb[sinfo->dcb_wsize-1] &= ~SOC_DCB_KNET_COUNT_MASK; + dcb[sinfo->dcb_wsize-1] |= pktlen & SOC_DCB_KNET_COUNT_MASK; + } + } + } + } + + if (device_is_sand(sinfo)) { + filter = bkn_match_rx_pkt(sinfo, pkt + packet_info.system_header_size, + pktlen - packet_info.system_header_size, sand_scratch_data, chan, &cbf); + } else { + filter = bkn_match_rx_pkt(sinfo, pkt + sinfo->pkt_hdr_size, + pktlen - sinfo->pkt_hdr_size, meta, chan, &cbf); + } + if ((dcb[sinfo->dcb_wsize-1] & 0xf0000) != 0x30000) { + /* Fragment or error */ + if (filter && filter->kf.mask.w[err_woff] == 0) { + /* Drop unless DCB status is part of filter */ + filter = NULL; + } + } + drop_api = 1; + if (filter) { + DBG_FLTR(("Match filter ID %d\n", filter->kf.id)); + switch (filter->kf.dest_type) { + case KCOM_DEST_T_API: + DBG_FLTR(("Send to Rx API\n")); + sinfo->rx[chan].pkts_f_api++; + drop_api = 0; + break; + case KCOM_DEST_T_NETIF: + priv = bkn_netif_lookup(sinfo, filter->kf.dest_id); + if (priv) { + /* Check that software link is up */ + if (!netif_carrier_ok(priv->dev)) { + sinfo->rx[chan].pkts_d_no_link++; + break; + } + + if (device_is_sand(sinfo)) { + pkt += packet_info.system_header_size; + pktlen -= packet_info.system_header_size; + } else if (sinfo->cmic_type == 'x') { + pkt += sinfo->pkt_hdr_size; + pktlen -= sinfo->pkt_hdr_size; + } + + /* Add 2 bytes for IP header alignment (see below) */ + skb = dev_alloc_skb(pktlen + RCPU_RX_ENCAP_SIZE + 2); + if (skb == NULL) { + sinfo->rx[chan].pkts_d_no_skb++; + break; + } + skb_reserve(skb, RCPU_RX_ENCAP_SIZE); + + DBG_FLTR(("Send to netif %d (%s)\n", + priv->id, priv->dev->name)); + sinfo->rx[chan].pkts_f_netif++; + skb->dev = priv->dev; + skb_reserve(skb, 2); /* 16 byte align the IP fields. */ + + /* Save for RCPU before stripping tag */ + ethertype = PKT_U16_GET(pkt, 16); + if ((priv->flags & KCOM_NETIF_F_KEEP_RX_TAG) == 0) { + uint16_t vlan_proto = PKT_U16_GET(pkt, 12); + + if (filter->kf.flags & KCOM_FILTER_F_STRIP_TAG) { + /* Strip the VLAN tag */ + if (vlan_proto == ETH_P_8021Q || + vlan_proto == ETH_P_8021AD) { + DBG_FLTR(("Strip VLAN tag\n")); + for (idx = 11; idx >= 0; idx--) { + pkt[idx+4] = pkt[idx]; + } + pktlen -= 4; + pkt += 4; + } + } else { + /* + * Mark packet as VLAN-tagged, otherwise newer + * kernels will strip the tag. + */ + uint16_t tci = PKT_U16_GET(pkt, 14); + + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_vlan_hwaccel_put_tag(skb, ETH_P_8021Q, tci); + } else { + if (vlan_proto == ETH_P_8021AD) { + bkn_vlan_hwaccel_put_tag + (skb, ETH_P_8021AD, tci); + } else { + bkn_vlan_hwaccel_put_tag + (skb, ETH_P_8021Q, tci); + } + } + } + } + + skb_copy_to_linear_data(skb, pkt, pktlen); + if (device_is_sand(sinfo)) { + /* CRC has been stripped */ + skb_put(skb, pktlen); + } else { + skb_put(skb, pktlen - 4); /* Strip CRC */ + } + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; + + /* Optional SKB updates */ + KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF; + if (knet_rx_cb != NULL) { + KNET_SKB_CB(skb)->netif_user_data = priv->cb_user_data; + KNET_SKB_CB(skb)->filter_user_data = filter->kf.cb_user_data; + if (device_is_sand(sinfo)) { + skb = knet_rx_cb(skb, sinfo->dev_no, sand_scratch_data); + } + else { + skb = knet_rx_cb(skb, sinfo->dev_no, meta); + } + if (skb == NULL) { + /* Consumed by call-back */ + sinfo->rx[chan].pkts_d_callback++; + break; + } + } + + /* Do Rx timestamping */ + if (priv->rx_hwts) { + bkn_hw_tstamp_rx_set(sinfo, priv->phys_port, skb, meta); + } + + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_add_rcpu_encap(sinfo, skb, meta, packet_info.system_header_size); + DBG_PDMP(("After add RCPU ENCAP\n")); + bkn_dump_pkt(skb->data, pktlen + RCPU_RX_ENCAP_SIZE, XGS_DMA_RX_CHAN); + } + skb->protocol = eth_type_trans(skb, skb->dev); + if (filter->kf.dest_proto) { + skb->protocol = filter->kf.dest_proto; + } + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_eth_type_update(skb, ethertype); + } + DBG_DUNE(("skb protocol 0x%04x\n",skb->protocol)); + + /* Unlock while calling up network stack */ + spin_unlock(&sinfo->lock); + if (use_napi) { + netif_receive_skb(skb); + } else { + netif_rx(skb); + } + spin_lock(&sinfo->lock); + + if (filter->kf.mirror_type == KCOM_DEST_T_API || + dbg_pkt_enable) { + DBG_FLTR(("Mirror to Rx API\n")); + sinfo->rx[chan].pkts_m_api++; + drop_api = 0; + } + } else { + DBG_FLTR(("Unknown netif %d\n", + filter->kf.dest_id)); + sinfo->rx[chan].pkts_d_unkn_netif++; + } + break; + default: + /* Drop packet */ + DBG_FLTR(("Unknown dest type %d\n", + filter->kf.dest_type)); + sinfo->rx[chan].pkts_d_unkn_dest++; + break; + } + } else { + DBG_PKT(("Rx packet dropped.\n")); + sinfo->rx[chan].pkts_d_no_match++; + } + if (drop_api) { + /* If count is zero, the DCB will just be recycled */ + dcb[sinfo->dcb_wsize-1] &= ~SOC_DCB_KNET_COUNT_MASK; + } + dcb[sinfo->dcb_wsize-1] |= SOC_DCB_KNET_DONE; + dcb_chain->dcb_cur++; + dcbs_done++; + } + + return dcbs_done; +} + +static int +bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) +{ + bkn_priv_t *priv; + bkn_desc_info_t *desc; + struct sk_buff *skb; + bkn_filter_t cbf; + bkn_filter_t *filter; + uint32_t err_woff; + uint32_t *dcb, *meta; + int ethertype; + int pktlen; + int idx; + int dcbs_done = 0; + bkn_dune_system_header_info_t packet_info = {0}; + uint32_t sand_scratch_data[BKN_SAND_SCRATCH_DATA_SIZE] = {0}; + uint8_t sand_system_headers[RCPU_RX_META_SIZE] = {0}; + uint8_t *pkt = NULL; + + if (!sinfo->rx[chan].running) { + /* Rx not ready */ + return 0; + } + + while (dcbs_done < budget) { + char str[32]; + + if (!sinfo->rx[chan].running) { + /* DCBs might be cleaned up when bkn_knet_hw_reset is triggered. */ + return 0; + } + sprintf(str, "Rx DCB (%d)", sinfo->rx[chan].dirty); + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty]; + dcb = desc->dcb_mem; + bkn_dump_dcb(str, dcb, sinfo->dcb_wsize, XGS_DMA_RX_CHAN); + if ((dcb[sinfo->dcb_wsize-1] & (1 << 31)) == 0) { + break; + } + if ((sinfo->cmic_type == 'x' && (dcb[2] & (1 << 16)) == 0) || + (sinfo->cmic_type != 'x' && (dcb[1] & (1 << 16)) == 0)) { + sinfo->rx[chan].chain_complete = 1; + /* Request one extra poll to check for chain done interrupt */ + if (sinfo->napi_poll_mode) { + sinfo->napi_poll_again = 1; + } + } + sinfo->rx[chan].pkts++; + skb = desc->skb; + + DBG_DCB_RX(("Rx%d SKB DMA done (%d).\n", chan, sinfo->rx[chan].dirty)); + BKN_DMA_UNMAP_SINGLE(sinfo->dma_dev, + desc->skb_dma, desc->dma_size, + BKN_DMA_FROMDEV); + desc->skb_dma = 0; + + if (device_is_sand(sinfo)) { + err_woff = BKN_SAND_SCRATCH_DATA_SIZE - 1; + sand_scratch_data[err_woff] = dcb[sinfo->dcb_wsize-1]; + meta = (uint32_t *)skb->data; + pkt = skb->data; + } else { + if (sinfo->cmic_type == 'x') { + meta = (uint32_t *)skb->data; + err_woff = sinfo->pkt_hdr_size / sizeof(uint32_t) - 1; + meta[err_woff] = dcb[sinfo->dcb_wsize-1]; + } else { + meta = dcb; + err_woff = sinfo->dcb_wsize - 1; + } + } + + pktlen = dcb[sinfo->dcb_wsize-1] & 0xffff; + priv = netdev_priv(sinfo->dev); + bkn_dump_pkt(skb->data, pktlen, XGS_DMA_RX_CHAN); + + if (device_is_sand(sinfo)) { + memset(&packet_info, 0, sizeof(bkn_dune_system_header_info_t)); + /* decode system headers and fill sratch data */ + bkn_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info); + bkn_bitstream_set_field(sand_scratch_data, 0, 16, packet_info.internal.trap_id); + bkn_bitstream_set_field(sand_scratch_data, 16, 16, packet_info.internal.trap_qualifier); + bkn_bitstream_set_field(sand_scratch_data, 32, 16, packet_info.ftmh.source_sys_port_aggregate); + bkn_bitstream_set_field(sand_scratch_data, 48, 16, packet_info.internal.forward_domain); + bkn_bitstream_set_field(sand_scratch_data, 64, 2, packet_info.ftmh.action_type); + memcpy(sand_system_headers, pkt, + ((packet_info.system_header_size > RCPU_RX_META_SIZE) ? RCPU_RX_META_SIZE : packet_info.system_header_size)); + meta = (uint32_t *)sand_system_headers; + if (force_tagged) { + uint8_t *eth_hdr = pkt + packet_info.system_header_size; + uint16_t tpid = 0; + + tpid = PKT_U16_GET(eth_hdr, 12); + if (packet_is_untagged(tpid)) { + int raw_packet_len = pktlen - packet_info.system_header_size; + uint32_t vid = 0; + + if ((pktlen + 4) < rx_buffer_size) { + for (idx = (raw_packet_len - 1); idx >= 12; idx--) { + eth_hdr[idx+4] = eth_hdr[idx]; + } + if (ft_vid) { + vid = ft_vid; + } + else if (packet_info.internal.forward_domain) { + vid = packet_info.internal.forward_domain & 0xfff; + } + else { + vid = 1; + } + DBG_DUNE(("add vlan tag (%d) to untagged packets\n", vid)); + eth_hdr[12] = (ft_tpid >> 8) & 0xff; + eth_hdr[13] = ft_tpid & 0xff; + eth_hdr[14] = (((ft_pri & 0x7) << 5) | ((ft_cfi & 0x1) << 4) | ((vid >> 8) & 0xf)) & 0xff; + eth_hdr[15] = vid & 0xff; + /* reset packet length in DCB */ + pktlen += 4; + bkn_dump_pkt(pkt, pktlen, XGS_DMA_RX_CHAN); + dcb[sinfo->dcb_wsize-1] &= ~SOC_DCB_KNET_COUNT_MASK; + dcb[sinfo->dcb_wsize-1] |= pktlen & SOC_DCB_KNET_COUNT_MASK; + } + } + } + } + if (device_is_sand(sinfo)) { + filter = bkn_match_rx_pkt(sinfo, skb->data + packet_info.system_header_size, + pktlen - packet_info.system_header_size, sand_scratch_data, chan, &cbf); + } else { + filter = bkn_match_rx_pkt(sinfo, skb->data + sinfo->pkt_hdr_size, + pktlen - sinfo->pkt_hdr_size, meta, chan, &cbf); + } + if ((dcb[sinfo->dcb_wsize-1] & 0xf0000) != 0x30000) { + /* Fragment or error */ + priv->stats.rx_errors++; + if (filter && filter->kf.mask.w[err_woff] == 0) { + /* Drop unless DCB status is part of filter */ + filter = NULL; + } + } + DBG_PKT(("Rx packet (%d bytes).\n", pktlen)); + if (filter) { + DBG_FLTR(("Match filter ID %d\n", filter->kf.id)); + switch (filter->kf.dest_type) { + case KCOM_DEST_T_API: + DBG_FLTR(("Send to Rx API\n")); + sinfo->rx[chan].pkts_f_api++; + bkn_api_rx_copy_from_skb(sinfo, chan, desc, 0); + break; + case KCOM_DEST_T_NETIF: + priv = bkn_netif_lookup(sinfo, filter->kf.dest_id); + if (priv) { + /* Check that software link is up */ + if (!netif_carrier_ok(priv->dev)) { + sinfo->rx[chan].pkts_d_no_link++; + break; + } + DBG_FLTR(("Send to netif %d (%s)\n", + priv->id, priv->dev->name)); + sinfo->rx[chan].pkts_f_netif++; + + if ((filter->kf.mirror_type == KCOM_DEST_T_API) || dbg_pkt_enable) { + sinfo->rx[chan].pkts_m_api++; + bkn_api_rx_copy_from_skb(sinfo, chan, desc, priv->rx_hwts); + } + + if (device_is_sand(sinfo)) { + /* CRC has been stripped on Dune*/ + skb_put(skb, pktlen); + } else { + skb_put(skb, pktlen - 4); /* Strip CRC */ + } + + if (device_is_sand(sinfo)) { + skb_pull(skb, packet_info.system_header_size); + } else if (sinfo->cmic_type == 'x') { + skb_pull(skb, sinfo->pkt_hdr_size); + } + + /* Optional SKB updates */ + KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF; + /* Do Rx timestamping */ + if (priv->rx_hwts) { + bkn_hw_tstamp_rx_set(sinfo, priv->phys_port, skb, meta); + } + + /* Save for RCPU before stripping tag */ + ethertype = PKT_U16_GET(skb->data, 16); + if ((priv->flags & KCOM_NETIF_F_KEEP_RX_TAG) == 0) { + uint16_t vlan_proto; + + vlan_proto = PKT_U16_GET(skb->data, 12); + if (filter->kf.flags & KCOM_FILTER_F_STRIP_TAG) { + /* Strip VLAN tag */ + if (vlan_proto == ETH_P_8021Q || + vlan_proto == ETH_P_8021AD) { + DBG_FLTR(("Strip VLAN tag\n")); + ((u32*)skb->data)[3] = ((u32*)skb->data)[2]; + ((u32*)skb->data)[2] = ((u32*)skb->data)[1]; + ((u32*)skb->data)[1] = ((u32*)skb->data)[0]; + skb_pull(skb, 4); + if (device_is_sand(sinfo)) { + for (idx = packet_info.system_header_size; idx >= 4; idx--) { + pkt[idx] = pkt[idx - 4]; + } + } else if (sinfo->cmic_type == 'x') { + for (idx = sinfo->pkt_hdr_size / sizeof(uint32_t); idx; idx--) { + meta[idx] = meta[idx - 1]; + } + meta++; + } + } + } else { + /* + * Mark packet as VLAN-tagged, otherwise newer + * kernels will strip the tag. + */ + uint16_t tci = PKT_U16_GET(skb->data, 14); + + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_vlan_hwaccel_put_tag(skb, ETH_P_8021Q, tci); + } else { + if (vlan_proto == ETH_P_8021AD) { + bkn_vlan_hwaccel_put_tag + (skb, ETH_P_8021AD, tci); + } else { + bkn_vlan_hwaccel_put_tag + (skb, ETH_P_8021Q, tci); + } + } + } + } + + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; + skb->dev = priv->dev; + + if (knet_rx_cb != NULL) { + KNET_SKB_CB(skb)->netif_user_data = priv->cb_user_data; + KNET_SKB_CB(skb)->filter_user_data = filter->kf.cb_user_data; + if (device_is_sand(sinfo)) { + skb = knet_rx_cb(skb, sinfo->dev_no, sand_scratch_data); + } + else { + skb = knet_rx_cb(skb, sinfo->dev_no, meta); + } + if (skb == NULL) { + /* Consumed by call-back */ + sinfo->rx[chan].pkts_d_callback++; + priv->stats.rx_dropped++; + desc->skb = NULL; + break; + } + } + + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_add_rcpu_encap(sinfo, skb, meta, packet_info.system_header_size); + DBG_PDMP(("After add RCPU ENCAP\n")); + bkn_dump_pkt(skb->data, pktlen + RCPU_RX_ENCAP_SIZE, XGS_DMA_RX_CHAN); + } + skb->protocol = eth_type_trans(skb, skb->dev); + if (filter->kf.dest_proto) { + skb->protocol = filter->kf.dest_proto; + } + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + bkn_eth_type_update(skb, ethertype); + } + DBG_DUNE(("skb protocol 0x%04x\n",skb->protocol)); + + if (filter->kf.mirror_type == KCOM_DEST_T_NETIF) { + bkn_priv_t *mpriv; + struct sk_buff *mskb; + mpriv = bkn_netif_lookup(sinfo, filter->kf.mirror_id); + if (mpriv && netif_carrier_ok(mpriv->dev)) { + mskb = skb_clone(skb, GFP_ATOMIC); + if (mskb == NULL) { + sinfo->rx[chan].pkts_d_no_skb++; + } else { + sinfo->rx[chan].pkts_m_netif++; + mpriv->stats.rx_packets++; + mpriv->stats.rx_bytes += mskb->len; + skb->dev = mpriv->dev; + if (filter->kf.mirror_proto) { + skb->protocol = filter->kf.mirror_proto; + } + /* Unlock while calling up network stack */ + spin_unlock(&sinfo->lock); + if (use_napi) { + netif_receive_skb(mskb); + } else { + netif_rx(mskb); + } + spin_lock(&sinfo->lock); + } + } + } + + /* Ensure that we reallocate SKB for this DCB */ + desc->skb = NULL; + + /* Unlock while calling up network stack */ + spin_unlock(&sinfo->lock); + if (use_napi) { + netif_receive_skb(skb); + } else { + netif_rx(skb); + } + spin_lock(&sinfo->lock); + + } else { + DBG_FLTR(("Unknown netif %d\n", + filter->kf.dest_id)); + sinfo->rx[chan].pkts_d_unkn_netif++; + } + break; + default: + /* Drop packet */ + DBG_FLTR(("Unknown dest type %d\n", + filter->kf.dest_type)); + sinfo->rx[chan].pkts_d_unkn_dest++; + break; + } + } else { + DBG_PKT(("Rx packet dropped.\n")); + sinfo->rx[chan].pkts_d_no_match++; + priv->stats.rx_dropped++; + } + dcb[sinfo->dcb_wsize-1] &= ~(1 << 31); + if (++sinfo->rx[chan].dirty >= MAX_RX_DCBS) { + sinfo->rx[chan].dirty = 0; + } + sinfo->rx[chan].free--; + dcbs_done++; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + /* Right now refill for Continuous DMA mode */ + bkn_rx_refill(sinfo, chan); + } + } + + return dcbs_done; +} + +static int +bkn_do_rx(bkn_switch_info_t *sinfo, int chan, int budget) +{ + if (sinfo->rx[chan].use_rx_skb == 0) { + /* Rx buffers are provided by BCM Rx API */ + return bkn_do_api_rx(sinfo, chan, budget); + } else { + /* Rx buffers are provided by Linux kernel */ + return bkn_do_skb_rx(sinfo, chan, budget); + } +} + +static void +bkn_rx_desc_done(bkn_switch_info_t *sinfo, int chan) +{ + bkn_evt_resource_t *evt; + evt = &_bkn_evt[sinfo->evt_idx]; + DBG_IRQ(("Rx%d desc done\n", chan)); + + if (sinfo->rx[chan].use_rx_skb == 0) { + sinfo->dma_events |= KCOM_DMA_INFO_F_RX_DONE; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + } +} + +static void +bkn_rx_chain_done(bkn_switch_info_t *sinfo, int chan) +{ + DBG_IRQ(("Rx%d chain done\n", chan)); + + if (sinfo->rx[chan].chain_complete == 0) { + /* + * In certain environments the DCB memory is updated after + * the corresponding interrupt has been received. + * The following code will ensure that this situation is + * handled properly. + */ + int maxloop = 0; + while (sinfo->rx[chan].chain_complete == 0) { + sinfo->rx[chan].sync_retry++; + if (maxloop == 0) { + sinfo->rx[chan].sync_err++; + } + if (maxloop > sinfo->rx[chan].sync_maxloop) { + sinfo->rx[chan].sync_maxloop = maxloop; + } + if (bkn_do_rx(sinfo, chan, MAX_RX_DCBS) > 0) { + bkn_rx_desc_done(sinfo, chan); + } + if (++maxloop > rx_sync_retry) { + gprintk("Fatal error: Incomplete chain\n"); + sinfo->rx[chan].chain_complete = 1; + break; + } + } + } + + sinfo->rx[chan].running = 0; + + if (sinfo->rx[chan].use_rx_skb == 0) { + bkn_api_rx_chain_done(sinfo, chan); + } else { + bkn_rx_refill(sinfo, chan); + + if (bkn_rx_restart(sinfo, chan) != 0) { + /* Presumably out of resources */ + sinfo->timer.expires = jiffies + 1; + if (!sinfo->timer_queued) { + sinfo->timer_queued = 1; + add_timer(&sinfo->timer); + } + } + } +} + +static void +bkn_suspend_tx(bkn_switch_info_t *sinfo) +{ + struct list_head *list; + bkn_priv_t *priv = netdev_priv(sinfo->dev); + + /* Stop main device */ + netif_stop_queue(priv->dev); + sinfo->tx.suspends++; + /* Stop associated virtual devices */ + list_for_each(list, &sinfo->ndev_list) { + priv = (bkn_priv_t *)list; + netif_stop_queue(priv->dev); + } +} + +static void +bkn_resume_tx(bkn_switch_info_t *sinfo) +{ + struct list_head *list; + bkn_priv_t *priv = netdev_priv(sinfo->dev); + + /* Check main device */ + if (netif_queue_stopped(priv->dev) && sinfo->tx.free > 1) { + netif_wake_queue(priv->dev); + } + /* Check associated virtual devices */ + list_for_each(list, &sinfo->ndev_list) { + priv = (bkn_priv_t *)list; + if (netif_queue_stopped(priv->dev) && sinfo->tx.free > 1) { + netif_wake_queue(priv->dev); + } + } +} + +static void +bkn_skb_tstamp_copy(struct sk_buff *new_skb, struct sk_buff *skb) +{ + bkn_skb_tx_flags(new_skb) = bkn_skb_tx_flags(skb); + new_skb->sk = skb->sk; + + return; +} + +static int +bkn_hw_tstamp_tx_set(bkn_switch_info_t *sinfo, struct sk_buff *skb) +{ + int hwts; + int port; + uint64_t ts = 0; + uint32_t hdrlen = sinfo->cmic_type == 'x' ? PKT_TX_HDR_SIZE : 0; + struct skb_shared_hwtstamps shhwtstamps; + + if (!knet_hw_tstamp_tx_time_get_cb) { + return -1; + } + + port = KNET_SKB_CB(skb)->port; + hwts = KNET_SKB_CB(skb)->hwts; + ts = KNET_SKB_CB(skb)->ts; + + + if (hwts == HWTSTAMP_TX_ONESTEP_SYNC) { + if (ts == 0) { + return 1; + } + } else if (hwts == HWTSTAMP_TX_ON) { + if (knet_hw_tstamp_tx_time_get_cb(sinfo->dev_no, port, skb->data + hdrlen, &ts) < 0) { + return -1; + } + } + + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); + shhwtstamps.hwtstamp = ns_to_ktime(ts); + skb_tstamp_tx(skb, &shhwtstamps); + + return 0; +} + +static void +bkn_hw_tstamp_tx_work(struct work_struct *work) +{ + bkn_switch_info_t *sinfo = container_of(work, bkn_switch_info_t, tx_ptp_work); + struct sk_buff *skb; + int ret; + + while (skb_queue_len(&sinfo->tx_ptp_queue)) { + skb = skb_dequeue(&sinfo->tx_ptp_queue); + ret = bkn_hw_tstamp_tx_set(sinfo, skb); + if (ret < 0) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + ktime_t now; + now = ktime_get(); + DBG_PTP(("2Step TX Timestamp has not been taken for the current skb (%lld us)\n", + ktime_us_delta(now, skb->tstamp))); + } else { + ktime_t now; + now = ktime_get(); + /* Timeout 20 should be same as configured by PTP4L */ + if (ktime_us_delta(now, skb->tstamp) >= 20000) { + DBG_PTP(("2Step TX Timestamp fetch took long time %lld us\n", + ktime_us_delta(now, skb->tstamp))); + } +#else + DBG_PTP(("2Step TX Timestamp has not been taken for the current skb\n")); +#endif + } + dev_kfree_skb_any(skb); + } +} + +static int +bkn_do_tx(bkn_switch_info_t *sinfo) +{ + bkn_desc_info_t *desc; + int dcbs_done = 0; + + if (!CDMA_CH(sinfo, XGS_DMA_TX_CHAN) && sinfo->tx.api_active) { + return dcbs_done; + } + + while (dcbs_done < MAX_TX_DCBS) { + char str[32]; + if (sinfo->tx.free == MAX_TX_DCBS) { + break; + } + sprintf(str, "Tx DCB (%d)", sinfo->tx.dirty); + desc = &sinfo->tx.desc[sinfo->tx.dirty]; + bkn_dump_dcb(str, desc->dcb_mem, sinfo->dcb_wsize, XGS_DMA_TX_CHAN); + if ((desc->dcb_mem[sinfo->dcb_wsize-1] & (1 << 31)) == 0) { + break; + } + if (desc->skb) { + DBG_DCB_TX(("Tx SKB DMA done (%d).\n", sinfo->tx.dirty)); + BKN_DMA_UNMAP_SINGLE(sinfo->dma_dev, + desc->skb_dma, desc->dma_size, + BKN_DMA_TODEV); + + if ((KNET_SKB_CB(desc->skb)->hwts == HWTSTAMP_TX_ONESTEP_SYNC) && + (bkn_skb_tx_flags(desc->skb) & SKBTX_IN_PROGRESS)) { + + if (bkn_hw_tstamp_tx_set(sinfo, desc->skb) < 0) { + gprintk("Timestamp has not been taken for the current skb.\n"); + } + bkn_skb_tx_flags(desc->skb) &= ~SKBTX_IN_PROGRESS; + } + + if (bkn_skb_tx_flags(desc->skb) & SKBTX_IN_PROGRESS) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + desc->skb->tstamp = ktime_get(); +#endif + skb_queue_tail(&sinfo->tx_ptp_queue, desc->skb); + schedule_work(&sinfo->tx_ptp_work); + } else { + dev_kfree_skb_any(desc->skb); + } + desc->skb = NULL; + desc->skb_dma = 0; + } + desc->dcb_mem[sinfo->dcb_wsize-1] &= ~(1 << 31); + if (++sinfo->tx.dirty >= MAX_TX_DCBS) { + sinfo->tx.dirty = 0; + } + if (++sinfo->tx.free > MAX_TX_DCBS) { + gprintk("Too many free Tx DCBs(%d).\n", sinfo->tx.free); + } + dcbs_done++; + } + + return dcbs_done; +} + +static void +bkn_tx_cdma_chain_switch(bkn_switch_info_t *sinfo) +{ + bkn_dcb_chain_t *dcb_chain = sinfo->tx.api_dcb_chain; + uint32_t *dcb_mem; + uint64_t dcb_dma; + int woffset; + + /* Switch between SKB Tx and API Tx for Continuous DMA mode */ + if (!sinfo->tx.api_active) { + /* + * Set the current SKB DCB as reload DCB and the last DCB of + * the pending API chain as the new halt location. + */ + sinfo->tx.api_active = 1; + dcb_mem = sinfo->tx.desc[sinfo->tx.cur].dcb_mem; + memset(dcb_mem, 0, sinfo->dcb_wsize * sizeof(uint32_t)); + dcb_mem[0] = dcb_chain->dcb_dma; + if (sinfo->cmic_type == 'x') { + dcb_mem[1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32); + dcb_mem[2] |= 1 << 24 | 1 << 18 | 1 << 16; + } else { + dcb_mem[1] |= 1 << 24 | 1 << 18 | 1 << 16; + } + if (++sinfo->tx.cur >= MAX_TX_DCBS) { + sinfo->tx.cur = 0; + } + sinfo->tx.free--; + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t); + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, dcb_dma); + } else { + /* Only need to set the current SKB DCB as the new halt location */ + sinfo->tx.api_active = 0; + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_mem = &dcb_chain->dcb_mem[woffset]; + dcb_mem[0] = sinfo->tx.desc[sinfo->tx.dirty].dcb_dma; + if (sinfo->cmic_type == 'x') { + dcb_mem[1] = DMA_TO_BUS_HI(sinfo->tx.desc[sinfo->tx.dirty].dcb_dma >> 32); + } + dcb_dma = sinfo->tx.desc[sinfo->tx.cur].dcb_dma; + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, dcb_dma); + } +} + +static void +bkn_skb_tx(bkn_switch_info_t *sinfo) +{ + if (sinfo->tx.api_active) { + /* Switch from API Tx to SKB Tx */ + bkn_tx_cdma_chain_switch(sinfo); + } +} + +static void +bkn_api_tx(bkn_switch_info_t *sinfo) +{ + bkn_dcb_chain_t *dcb_chain; + uint64_t pkt_dma; + unsigned char *pktdata; + int pktlen; + int i; + + /* Assume that driver lock is held */ + if (list_empty(&sinfo->tx.api_dcb_list)) { + sinfo->tx.api_active = 0; + } else { + sinfo->tx.pkts++; + dcb_chain = list_entry(sinfo->tx.api_dcb_list.next, + bkn_dcb_chain_t, list); + DBG_DCB_TX(("Start API Tx DMA, first DCB @ 0x%08x (%d DCBs).\n", + (uint32_t)dcb_chain->dcb_dma, dcb_chain->dcb_cnt)); + for (i = 0; i < dcb_chain->dcb_cnt && debug & DBG_LVL_PDMP; i++) { + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN) && i == dcb_chain->dcb_cnt - 1) { + break; + } + if (sinfo->cmic_type == 'x') { + pkt_dma = BUS_TO_DMA_HI(dcb_chain->dcb_mem[sinfo->dcb_wsize * i + 1]); + pkt_dma = pkt_dma << 32 | dcb_chain->dcb_mem[sinfo->dcb_wsize * i]; + } else { + pkt_dma = dcb_chain->dcb_mem[sinfo->dcb_wsize * i]; + } + pktdata = kernel_bde->p2l(sinfo->dev_no, pkt_dma); + if (sinfo->cmic_type == 'x') { + pktlen = dcb_chain->dcb_mem[sinfo->dcb_wsize * i + 2] & 0xffff; + } else { + pktlen = dcb_chain->dcb_mem[sinfo->dcb_wsize * i + 1] & 0xffff; + } + bkn_dump_pkt(pktdata, pktlen, XGS_DMA_TX_CHAN); + } + + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + sinfo->tx.api_dcb_chain = dcb_chain; + if (!sinfo->tx.api_active) { + /* Switch from SKB Tx to API Tx */ + bkn_tx_cdma_chain_switch(sinfo); + } + list_del(&dcb_chain->list); + } else { + sinfo->tx.api_active = 1; + dev_dma_chan_clear(sinfo, XGS_DMA_TX_CHAN); + dev_irq_mask_enable(sinfo, XGS_DMA_TX_CHAN, 1); + dev_dma_chan_start(sinfo, XGS_DMA_TX_CHAN, dcb_chain->dcb_dma); + list_del(&dcb_chain->list); + kfree(dcb_chain); + } + } +} + +static void +bkn_tx_cdma_chain_done(bkn_switch_info_t *sinfo, int done) +{ + int woffset; + int dcbs_done = 0; + bkn_evt_resource_t *evt; + + DBG_IRQ(("Tx CDMA chain done \n")); + + evt = &_bkn_evt[sinfo->evt_idx]; + + if (sinfo->tx.api_active) { + /* Drain API Tx chains */ + while (sinfo->tx.api_dcb_chain != sinfo->tx.api_dcb_chain_end) { + woffset = sinfo->tx.api_dcb_chain->dcb_cnt * sinfo->dcb_wsize - 1; + if (!(sinfo->tx.api_dcb_chain->dcb_mem[woffset] & (1 << 31))) { + return; + } + sinfo->tx.api_dcb_chain->dcb_mem[woffset - sinfo->dcb_wsize] |= SOC_DCB_KNET_DONE; + sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + kfree(sinfo->tx.api_dcb_chain); + sinfo->tx.api_dcb_chain = NULL; + bkn_api_tx(sinfo); + if ((++dcbs_done + done) >= MAX_TX_DCBS) { + if (sinfo->napi_poll_mode) { + /* Request one extra poll to reschedule Tx */ + sinfo->napi_poll_again = 1; + } else { + /* Request to yield for Continuous DMA mode */ + sinfo->tx_yield = 1; + } + return; + } + } + woffset = (sinfo->tx.api_dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize - 1; + if (!(sinfo->tx.api_dcb_chain->dcb_mem[woffset] & (1 << 31))) { + return; + } + sinfo->tx.api_dcb_chain->dcb_mem[woffset] |= SOC_DCB_KNET_DONE; + /* Try and park at SKB Tx if API Tx done */ + bkn_skb_tx(sinfo); + sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + kfree(sinfo->tx.api_dcb_chain); + sinfo->tx.api_dcb_chain = NULL; + sinfo->tx.api_dcb_chain_end = NULL; + if (!sinfo->napi_poll_mode) { + /* Not need to yield for Continuous DMA mode */ + sinfo->tx_yield = 0; + } + } else { + if (sinfo->tx.free == MAX_TX_DCBS) { + /* Try API Tx if SKB Tx done */ + bkn_api_tx(sinfo); + if (sinfo->tx.api_active) { + return; + } + } + } + + /* Resume if netif Tx resources available and API Tx not active */ + bkn_resume_tx(sinfo); +} + +static void +bkn_tx_chain_done(bkn_switch_info_t *sinfo, int done) +{ + bkn_desc_info_t *desc; + int idx, pending; + bkn_evt_resource_t *evt; + + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + return bkn_tx_cdma_chain_done(sinfo, done); + } + + DBG_IRQ(("Tx chain done (%d/%d)\n", sinfo->tx.cur, sinfo->tx.dirty)); + + dev_irq_mask_disable(sinfo, XGS_DMA_TX_CHAN, 0); + + evt = &_bkn_evt[sinfo->evt_idx]; + + if (sinfo->tx.api_active) { + sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + /* Check if BCM API has more to send */ + bkn_api_tx(sinfo); + if (sinfo->tx.api_active) { + return; + } + } + + if (sinfo->tx.free == MAX_TX_DCBS) { + /* If netif Tx is idle then allow BCM API to send */ + bkn_api_tx(sinfo); + if (sinfo->tx.api_active) { + return; + } + } else { + /* If two or more DCBs are pending, chain them */ + pending = MAX_TX_DCBS - sinfo->tx.free; + idx = sinfo->tx.dirty; + while (--pending && idx < (MAX_TX_DCBS - 1)) { + if (sinfo->cmic_type == 'x') { + sinfo->tx.desc[idx++].dcb_mem[2] |= 1 << 16; + } else { + sinfo->tx.desc[idx++].dcb_mem[1] |= 1 << 16; + } + DBG_DCB_TX(("Chain Tx DCB %d (%d)\n", idx, pending)); + } + /* Restart DMA from where we stopped */ + desc = &sinfo->tx.desc[sinfo->tx.dirty]; + DBG_DCB_TX(("Restart Tx DMA, DCB @ 0x%08x (%d).\n", + (uint32_t)desc->dcb_dma, sinfo->tx.dirty)); + dev_dma_chan_clear(sinfo, XGS_DMA_TX_CHAN); + dev_irq_mask_enable(sinfo, XGS_DMA_TX_CHAN, 0); + dev_dma_chan_start(sinfo, XGS_DMA_TX_CHAN, desc->dcb_dma); + } + + /* Resume if netif Tx resources available and API Tx not active */ + bkn_resume_tx(sinfo); +} + +static void +bkn_schedule_napi_poll(bkn_switch_info_t *sinfo) +{ + /* Schedule NAPI poll */ + DBG_NAPI(("Schedule NAPI poll on %s.\n", sinfo->dev->name)); + /* Disable interrupts until poll job is complete */ + sinfo->napi_poll_mode = 1; + /* Unlock while calling up network stack */ + spin_unlock(&sinfo->lock); + if (bkn_napi_schedule_prep(sinfo->dev, &sinfo->napi)) { + __bkn_napi_schedule(sinfo->dev, &sinfo->napi); + DBG_NAPI(("Schedule prep OK on %s.\n", sinfo->dev->name)); + } else { + /* Most likely the base device is has not been opened */ + gprintk("Warning: Unable to schedule NAPI - base device not up?\n"); + } + spin_lock(&sinfo->lock); +} + +static void +bkn_napi_poll_complete(bkn_switch_info_t *sinfo) +{ + /* Unlock while calling up network stack */ + spin_unlock(&sinfo->lock); + bkn_napi_complete(sinfo->dev, &sinfo->napi); + spin_lock(&sinfo->lock); + /* Re-enable interrupts */ + sinfo->napi_poll_mode = 0; + dev_irq_mask_set(sinfo, sinfo->irq_mask); +} + +static int +xgs_do_dma(bkn_switch_info_t *sinfo, int budget) +{ + int rx_dcbs_done = 0, tx_dcbs_done = 0; + int chan_done, budget_chans = 0; + uint32_t dma_stat; + int chan; + + DEV_READ32(sinfo, CMIC_DMA_STATr, &dma_stat); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (dma_stat & DS_DESC_DONE_TST(XGS_DMA_RX_CHAN + chan)) { + xgs_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan); + sinfo->poll_channels |= 1 << chan; + } + } + if (!sinfo->poll_channels) { + sinfo->poll_channels = (uint32_t)(1 << sinfo->rx_chans) - 1; + budget_chans = budget / sinfo->rx_chans; + } else { + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (1 << chan & sinfo->poll_channels) { + budget_chans++; + } + } + budget_chans = budget / budget_chans; + } + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (1 << chan & sinfo->poll_channels) { + chan_done = bkn_do_rx(sinfo, chan, budget_chans); + rx_dcbs_done += chan_done; + if (chan_done < budget_chans) { + sinfo->poll_channels &= ~(1 << chan); + } + bkn_rx_desc_done(sinfo, chan); + } + + if (dma_stat & DS_CHAIN_DONE_TST(XGS_DMA_RX_CHAN + chan)) { + xgs_dma_chain_clear(sinfo, XGS_DMA_RX_CHAN + chan); + bkn_rx_chain_done(sinfo, chan); + } + } + + if (dma_stat & DS_CHAIN_DONE_TST(XGS_DMA_TX_CHAN)) { + xgs_dma_chain_clear(sinfo, XGS_DMA_TX_CHAN); + tx_dcbs_done = bkn_do_tx(sinfo); + bkn_tx_chain_done(sinfo, tx_dcbs_done); + } + + return sinfo->poll_channels ? budget : rx_dcbs_done; +} + +static int +xgsm_do_dma(bkn_switch_info_t *sinfo, int budget) +{ + int rx_dcbs_done = 0, tx_dcbs_done = 0; + int chan_done, budget_chans = 0; + uint32_t dma_stat, irq_stat = 0; + int chan; + + /* Get Controlled interrupt states for Continuous DMA mode */ + if (sinfo->cdma_channels) { + DEV_READ32(sinfo, CMICM_IRQ_STATr, &irq_stat); + } + + DEV_READ32(sinfo, CMICM_DMA_STATr, &dma_stat); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (dma_stat & (0x10 << (XGS_DMA_RX_CHAN + chan)) || + irq_stat & (0x08000000 << (XGS_DMA_RX_CHAN + chan))) { + xgsm_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan); + sinfo->poll_channels |= 1 << chan; + } + } + if (!sinfo->poll_channels) { + sinfo->poll_channels = (uint32_t)(1 << sinfo->rx_chans) - 1; + budget_chans = budget / sinfo->rx_chans; + } else { + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (1 << chan & sinfo->poll_channels) { + budget_chans++; + } + } + budget_chans = budget / budget_chans; + } + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (1 << chan & sinfo->poll_channels) { + chan_done = bkn_do_rx(sinfo, chan, budget_chans); + rx_dcbs_done += chan_done; + if (chan_done < budget_chans) { + sinfo->poll_channels &= ~(1 << chan); + } + bkn_rx_desc_done(sinfo, chan); + } + + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + continue; + } + + if (dma_stat & (0x1 << (XGS_DMA_RX_CHAN + chan))) { + xgsm_dma_chain_clear(sinfo, XGS_DMA_RX_CHAN + chan); + bkn_rx_chain_done(sinfo, chan); + } + } + + if (dma_stat & (0x1 << XGS_DMA_TX_CHAN) || + irq_stat & (0x08000000 << XGS_DMA_TX_CHAN)) { + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + xgsm_dma_desc_clear(sinfo, XGS_DMA_TX_CHAN); + } else { + xgsm_dma_chain_clear(sinfo, XGS_DMA_TX_CHAN); + } + tx_dcbs_done = bkn_do_tx(sinfo); + bkn_tx_chain_done(sinfo, tx_dcbs_done); + } + + return sinfo->poll_channels ? budget : rx_dcbs_done; +} + +static int +xgsx_do_dma(bkn_switch_info_t *sinfo, int budget) +{ + int rx_dcbs_done = 0, tx_dcbs_done = 0; + int chan_done, budget_chans = 0; + uint32_t irq_stat, tx_dma_stat, rx_dma_stat[NUM_CMICX_RX_CHAN]; + int chan; + + DEV_READ32(sinfo, CMICX_IRQ_STATr, &irq_stat); + DEV_READ32(sinfo, CMICX_DMA_STATr + 0x80 * XGS_DMA_TX_CHAN, &tx_dma_stat); + for (chan = 0; chan < sinfo->rx_chans; chan++) { + DEV_READ32(sinfo, + CMICX_DMA_STATr + 0x80 * (XGS_DMA_RX_CHAN + chan), + &rx_dma_stat[chan]); + } + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if ((irq_stat & CMICX_DS_CMC_CTRLD_INT(XGS_DMA_RX_CHAN + chan)) || + (irq_stat & CMICX_DS_CMC_DESC_DONE(XGS_DMA_RX_CHAN + chan))) { + xgsx_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan); + sinfo->poll_channels |= 1 << chan; + } + } + if (!sinfo->poll_channels) { + sinfo->poll_channels = (uint32_t)(1 << sinfo->rx_chans) - 1; + budget_chans = budget / sinfo->rx_chans; + } else { + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (1 << chan & sinfo->poll_channels) { + budget_chans++; + } + } + budget_chans = budget / budget_chans; + } + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (1 << chan & sinfo->poll_channels) { + chan_done = bkn_do_rx(sinfo, chan, budget_chans); + rx_dcbs_done += chan_done; + if (chan_done < budget_chans) { + sinfo->poll_channels &= ~(1 << chan); + } + bkn_rx_desc_done(sinfo, chan); + } + + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + continue; + } + + if (rx_dma_stat[chan] & CMICX_DS_CMC_DMA_CHAIN_DONE) { + xgsx_dma_chain_clear(sinfo, XGS_DMA_RX_CHAN + chan); + bkn_rx_chain_done(sinfo, chan); + } + } + + if ((irq_stat & CMICX_DS_CMC_CTRLD_INT(XGS_DMA_TX_CHAN)) || + (tx_dma_stat & CMICX_DS_CMC_DMA_CHAIN_DONE)) { + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + xgsx_dma_desc_clear(sinfo, XGS_DMA_TX_CHAN); + } else { + xgsx_dma_chain_clear(sinfo, XGS_DMA_TX_CHAN); + } + tx_dcbs_done = bkn_do_tx(sinfo); + bkn_tx_chain_done(sinfo, tx_dcbs_done); + } + + return sinfo->poll_channels ? budget : rx_dcbs_done; +} + +static int +dev_do_dma(bkn_switch_info_t *sinfo, int budget) +{ + if (DEV_IS_CMICX(sinfo)) { + return xgsx_do_dma(sinfo, budget); + } else if (DEV_IS_CMICM(sinfo)) { + return xgsm_do_dma(sinfo, budget); + } else { + return xgs_do_dma(sinfo, budget); + } +} + +static void +xgs_isr(bkn_switch_info_t *sinfo) +{ + uint32_t irq_stat; + int rx_dcbs_done; + + DEV_READ32(sinfo, CMIC_IRQ_STATr, &irq_stat); + if ((irq_stat & sinfo->irq_mask) == 0) { + /* Not ours */ + return; + } + sinfo->interrupts++; + + DBG_IRQ(("Got interrupt on device %d (0x%08x)\n", + sinfo->dev_no, irq_stat)); + + if (use_napi) { + bkn_schedule_napi_poll(sinfo); + } else { + xgs_irq_mask_set(sinfo, 0); + do { + rx_dcbs_done = xgs_do_dma(sinfo, MAX_RX_DCBS); + } while (rx_dcbs_done); + } + + xgs_irq_mask_set(sinfo, sinfo->irq_mask); +} + +static void +xgsm_isr(bkn_switch_info_t *sinfo) +{ + uint32_t irq_stat; + int rx_dcbs_done; + + DEV_READ32(sinfo, CMICM_IRQ_STATr, &irq_stat); + if ((irq_stat & sinfo->irq_mask) == 0) { + /* Not ours */ + return; + } + sinfo->interrupts++; + + DBG_IRQ(("Got interrupt on device %d (0x%08x)\n", + sinfo->dev_no, irq_stat)); + + if (use_napi) { + bkn_schedule_napi_poll(sinfo); + } else { + xgsm_irq_mask_set(sinfo, 0); + do { + rx_dcbs_done = xgsm_do_dma(sinfo, MAX_RX_DCBS); + if (sinfo->cdma_channels) { + if (rx_dcbs_done >= MAX_RX_DCBS || sinfo->tx_yield) { + /* Continuous DMA mode requires to yield timely */ + break; + } + } + } while (rx_dcbs_done); + } + + xgsm_irq_mask_set(sinfo, sinfo->irq_mask); +} + +static void +xgsx_isr(bkn_switch_info_t *sinfo) +{ + uint32_t irq_stat; + int rx_dcbs_done; + + DEV_READ32(sinfo, CMICX_IRQ_STATr, &irq_stat); + if ((irq_stat & sinfo->irq_mask) == 0) { + /* Not ours */ + return; + } + + /* Bypass chain_done from Abort */ + if (device_is_dnx(sinfo)) { + uint32_t ctrl = 0; + int chan = 0; + for (chan = 0; chan < NUM_DMA_CHAN; chan++) { + if (irq_stat & CMICX_DS_CMC_CHAIN_DONE(chan)) { + DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl); + if (ctrl & CMICX_DC_CMC_ABORT) { + DBG_IRQ(("chain %d: chain done for Abort\n", chan)); + return; + } + } + } + } + + sinfo->interrupts++; + + DBG_IRQ(("Got interrupt on device %d (0x%08x)\n", + sinfo->dev_no, irq_stat)); + + if (use_napi) { + bkn_schedule_napi_poll(sinfo); + } else { + xgsx_irq_mask_set(sinfo, 0); + do { + rx_dcbs_done = xgsx_do_dma(sinfo, MAX_RX_DCBS); + if (sinfo->cdma_channels) { + if (rx_dcbs_done >= MAX_RX_DCBS || sinfo->tx_yield) { + /* Continuous DMA mode requires to yield timely */ + break; + } + } + } while (rx_dcbs_done); + } + + xgsx_irq_mask_set(sinfo, sinfo->irq_mask); +} + +static void +bkn_isr(void *isr_data) +{ + bkn_switch_info_t *sinfo = isr_data; + + /* Safe exit on SMP systems */ + if (!module_initialized) { + return; + } + + /* Ensure that we do not touch registers during device reset */ + if (sinfo->irq_mask == 0) { + /* Not ours */ + return; + } + + spin_lock(&sinfo->lock); + + if (sinfo->napi_poll_mode) { + /* Not ours */ + spin_unlock(&sinfo->lock); + return; + } + + if (DEV_IS_CMICX(sinfo)) { + xgsx_isr(sinfo); + } else if (DEV_IS_CMICM(sinfo)) { + xgsm_isr(sinfo); + } else { + xgs_isr(sinfo); + } + + spin_unlock(&sinfo->lock); +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void +bkn_poll_controller(struct net_device *dev) +{ + bkn_priv_t *priv = netdev_priv(dev); + + disable_irq(dev->irq); + bkn_isr(priv->sinfo); + enable_irq(dev->irq); +} +#endif + +static void +bkn_resume_rx(bkn_switch_info_t *sinfo) +{ + bkn_desc_info_t *desc; + bkn_dcb_chain_t *dcb_chain; + uint64_t cur_halt, last_dcb, dcb_dma; + int woffset, chan, cdma_running; + + /* Resume Rx DMA on all channels */ + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (sinfo->rx[chan].use_rx_skb) { + cdma_running = 0; + bkn_api_rx_restart(sinfo, chan); + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + cur_halt = sinfo->halt_addr[XGS_DMA_RX_CHAN + chan]; + last_dcb = sinfo->rx[chan].desc[MAX_RX_DCBS].dcb_dma; + if (cur_halt != last_dcb) { + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty + 1]; + bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma); + cdma_running = 1; + } + } + if (!cdma_running) { + bkn_rx_restart(sinfo, chan); + } + } else { + cdma_running = 0; + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + if (sinfo->rx[chan].api_active) { + dcb_chain = sinfo->rx[chan].api_dcb_chain_end; + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t); + bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, dcb_dma); + cdma_running = 1; + } + } + if (!cdma_running) { + bkn_api_rx_restart(sinfo, chan); + } + } + } +} + +static int +bkn_open(struct net_device *dev) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + unsigned long flags; + + /* Check if base device */ + if (priv->id <= 0) { + /* NAPI used only on base device */ + if (use_napi) { + bkn_napi_enable(dev, &sinfo->napi); + } + + /* Start DMA when base device is started */ + if (sinfo->basedev_suspended) { + spin_lock_irqsave(&sinfo->lock, flags); + dev_do_dma(sinfo, MAX_RX_DCBS); + sinfo->basedev_suspended = 0; + bkn_api_tx(sinfo); + if (!sinfo->tx.api_active) { + bkn_resume_tx(sinfo); + } + bkn_resume_rx(sinfo); + spin_unlock_irqrestore(&sinfo->lock, flags); + } + } + + if (!sinfo->basedev_suspended) { + netif_start_queue(dev); + } + + return 0; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) +static int +bkn_set_mac_address(struct net_device *dev, void *addr) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,12)) + if (!is_valid_ether_addr((const u8*)(((struct sockaddr *)addr)->sa_data))) { +#else + if (!is_valid_ether_addr(((struct sockaddr *)addr)->sa_data)) { +#endif + return -EINVAL; + } + memcpy(dev->dev_addr, ((struct sockaddr *)addr)->sa_data, dev->addr_len); + return 0; +} +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) +static int +bkn_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + struct hwtstamp_config config; + + if (cmd == SIOCSHWTSTAMP) { + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) { + return -EFAULT; + } + + if (!knet_hw_tstamp_enable_cb || !knet_hw_tstamp_disable_cb || + priv->type != KCOM_NETIF_T_PORT) { + return -ENOSYS; + } + + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + knet_hw_tstamp_disable_cb(sinfo->dev_no, priv->phys_port, config.tx_type); + priv->tx_hwts = (config.tx_type); + break; + case HWTSTAMP_TX_ON: + knet_hw_tstamp_enable_cb(sinfo->dev_no, priv->phys_port, config.tx_type); + priv->tx_hwts = (config.tx_type); + break; + case HWTSTAMP_TX_ONESTEP_SYNC: + knet_hw_tstamp_enable_cb(sinfo->dev_no, priv->phys_port, config.tx_type); + priv->tx_hwts = (config.tx_type); + break; + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + if (priv->rx_hwts) { + knet_hw_tstamp_disable_cb(sinfo->dev_no, priv->phys_port, config.tx_type); + priv->rx_hwts = 0; + } + break; + default: + if (!priv->rx_hwts) { + knet_hw_tstamp_enable_cb(sinfo->dev_no, priv->phys_port, config.tx_type); + priv->rx_hwts = 1; + } + config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + } + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) + if (cmd == SIOCGHWTSTAMP) { + config.flags = 0; + config.tx_type = priv->tx_hwts; + config.rx_filter = priv->rx_hwts ? HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE; + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; + } +#endif + + return -EINVAL; +} +#endif + +static int +bkn_change_mtu(struct net_device *dev, int new_mtu) +{ + int max_size = new_mtu + ETH_HLEN + VLAN_HLEN + 4; + + if (new_mtu < 68 || max_size > rx_buffer_size) { + return -EINVAL; + } + dev->mtu = new_mtu; + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +static int +bkn_poll(struct net_device *dev, int *budget) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + int cur_budget = *budget; + int poll_again = 0; + int rx_dcbs_done; + unsigned long flags; + + spin_lock_irqsave(&sinfo->lock, flags); + + DBG_NAPI(("NAPI poll on %s.\n", dev->name)); + + sinfo->napi_poll_again = 0; + + if (cur_budget > dev->quota) { + cur_budget = dev->quota; + } + + rx_dcbs_done = dev_do_dma(sinfo, cur_budget); + + *budget -= rx_dcbs_done; + cur_budget -= rx_dcbs_done; + dev->quota -= rx_dcbs_done; + + if (sinfo->napi_poll_again || cur_budget <= 0) { + poll_again = 1; + sinfo->napi_not_done++; + } else { + bkn_napi_poll_complete(sinfo); + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return poll_again; +} +#else +static int +bkn_poll(struct napi_struct *napi, int budget) +{ + bkn_switch_info_t *sinfo = container_of(napi, bkn_switch_info_t, napi); + int rx_dcbs_done; + unsigned long flags; + + spin_lock_irqsave(&sinfo->lock, flags); + + DBG_NAPI(("NAPI poll on %s.\n", sinfo->dev->name)); + + sinfo->napi_poll_again = 0; + + rx_dcbs_done = dev_do_dma(sinfo, budget); + + if (sinfo->napi_poll_again || rx_dcbs_done >= budget) { + /* Force poll again */ + rx_dcbs_done = budget; + sinfo->napi_not_done++; + } else { + bkn_napi_poll_complete(sinfo); + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return rx_dcbs_done; +} +#endif + +static int +bkn_stop(struct net_device *dev) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + unsigned long flags; + + netif_stop_queue(dev); + + /* Check if base device */ + if (priv->id <= 0) { + /* NAPI used only on base device */ + if (use_napi) { + bkn_napi_disable(dev, &sinfo->napi); + } + /* Suspend all devices if base device is stopped */ + if (basedev_suspend) { + spin_lock_irqsave(&sinfo->lock, flags); + bkn_suspend_tx(sinfo); + sinfo->basedev_suspended = 1; + spin_unlock_irqrestore(&sinfo->lock, flags); + } + } + + return 0; +} + +/* + * Network Device Statistics. + * Cleared at init time. + */ +static struct net_device_stats * +bkn_get_stats(struct net_device *dev) +{ + bkn_priv_t *priv = netdev_priv(dev); + + return &priv->stats; +} + +/* Fake multicast ability */ +static void +bkn_set_multicast_list(struct net_device *dev) +{ +} + +static int +bkn_hw_tstamp_tx_config(bkn_switch_info_t *sinfo, + int hwts, int hdrlen, + struct sk_buff *skb, u32 *meta) +{ + uint32_t *md = NULL; + + if (!knet_hw_tstamp_tx_meta_get_cb) { + return -1; + } + + KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF; + knet_hw_tstamp_tx_meta_get_cb(sinfo->dev_no, hwts, hdrlen, skb, + &(KNET_SKB_CB(skb)->ts), (meta ? &md : NULL)); + + if (!meta) { + return 0; + } + + if (!md) { + return -1; + } + + switch (sinfo->dcb_type) { + case 26: + case 32: + case 33: + case 35: + meta[2] |= md[0]; + meta[3] |= md[1]; + meta[4] |= md[2]; + meta[5] |= md[3]; + break; + case 36: + case 38: + meta[0] |= htonl(md[0]); + meta[1] |= htonl(md[1]); + meta[2] |= htonl(md[2]); + meta[3] |= htonl(md[3]); + break; + default: + return -1; + } + + return 0; +} + +static int +bkn_tx(struct sk_buff *skb, struct net_device *dev) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + struct sk_buff *new_skb = NULL; + unsigned char *pktdata; + int pktlen, hdrlen, taglen, rcpulen, metalen; + int sop, idx; + uint16_t tpid; + uint32_t *metadata; + unsigned long flags; + uint32_t cpu_channel = 0; + int headroom, tailroom; + + DBG_VERB(("Netif Tx: Len=%d priv->id=%d\n", skb->len, priv->id)); + + if (priv->id <= 0) { + /* Do not transmit on base device */ + priv->stats.tx_dropped++; + dev_kfree_skb_any(skb); + return 0; + } + + if (device_is_dnx(sinfo) && (skb->len == 0)) { + priv->stats.tx_dropped++; + dev_kfree_skb_any(skb); + return 0; + } + + if (!netif_carrier_ok(dev)) { + DBG_WARN(("Tx drop: Netif link is down.\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_no_link++; + dev_kfree_skb_any(skb); + return 0; + } + + spin_lock_irqsave(&sinfo->lock, flags); + + if (sinfo->tx.free > 1) { + bkn_desc_info_t *desc = &sinfo->tx.desc[sinfo->tx.cur]; + uint32_t *dcb, *meta; + + pktdata = skb->data; + pktlen = skb->len; + + if (device_is_sand(sinfo)) { + hdrlen = priv->system_headers_size; + } + else { + hdrlen = (sinfo->cmic_type == 'x' ) ? PKT_TX_HDR_SIZE : 0; + } + rcpulen = 0; + sop = 0; + + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + rcpulen = RCPU_HDR_SIZE; + if (skb->len < (rcpulen + 14)) { + DBG_WARN(("Tx drop: Invalid RCPU encapsulation\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_rcpu_encap++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + if (check_rcpu_signature && + PKT_U16_GET(skb->data, 18) != sinfo->rcpu_sig) { + DBG_WARN(("Tx drop: Invalid RCPU signature\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_rcpu_sig++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + + if (device_is_sand(sinfo)) { + /* Dune devices don't use meta data */ + sop = 0; + /* Get CPU channel from rcpu_hdr_t.reserved */ + cpu_channel = (skb->data[28] << 24) | (skb->data[29] << 16) | (skb->data[30] << 8) | (skb->data[31]); + /* System headers are supposed to be set by users in RCPU mode. */ + hdrlen = 0; + } else if (skb->data[21] & RCPU_F_MODHDR) { + sop = skb->data[RCPU_HDR_SIZE]; + switch (sop) { + case 0xff: + case 0x81: + case 0xfb: + case 0xfc: + break; + default: + DBG_WARN(("Tx drop: Invalid RCPU meta data\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_rcpu_meta++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + if (sinfo->cmic_type != 'x') { + rcpulen += RCPU_TX_META_SIZE; + } + } + /* Skip over RCPU encapsulation */ + pktdata = &skb->data[rcpulen]; + pktlen -= rcpulen; + + /* CPU packets require tag */ + if (sop == 0) { + if (device_is_sand(sinfo)) { + /* + * There should be Module Header + PTCH_2 + [ITMH] on JR2, + * PTCH_2 +[ITMH] on JR1 + */ + } else { + hdrlen = 0; + tpid = PKT_U16_GET(pktdata, 12); + if (tpid != 0x8100) { + if (skb_header_cloned(skb)) { + /* Current SKB cannot be modified */ + DBG_SKB(("Realloc Tx SKB\n")); + /* + * New SKB needs extra TAG_SZ for VLAN tag + * and extra FCS_SZ for Ethernet FCS. + */ + headroom = TAG_SZ; + tailroom = FCS_SZ; + new_skb = skb_copy_expand(skb, + headroom + skb_headroom(skb), + tailroom + skb_tailroom(skb), + GFP_ATOMIC); + if (new_skb == NULL) { + DBG_WARN(("Tx drop: No SKB memory\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_no_skb++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + /* Remove rcpulen from buffer. */ + skb_pull(new_skb, rcpulen); + /* Extended by TAG_SZ at the start of buffer. */ + skb_push(new_skb, TAG_SZ); + /* Restore the data before the tag. */ + memcpy(new_skb->data, pktdata, 12); + bkn_skb_tstamp_copy(new_skb, skb); + dev_kfree_skb_any(skb); + skb = new_skb; + pktdata = skb->data; + rcpulen = 0; + } else { + /* Add tag to RCPU header space */ + DBG_SKB(("Expand into unused RCPU header\n")); + rcpulen -= TAG_SZ; + pktdata = &skb->data[rcpulen]; + for (idx = 0; idx < 12; idx++) { + pktdata[idx] = pktdata[idx + TAG_SZ]; + } + } + pktdata[12] = 0x81; + pktdata[13] = 0x00; + pktdata[14] = (priv->vlan >> 8) & 0xf; + pktdata[15] = priv->vlan & 0xff; + pktlen += TAG_SZ; + } + } + } + } else { + if (((sinfo->cmic_type == 'x') && (priv->port >= 0)) + || device_is_sand(sinfo)) { + if (skb_header_cloned(skb) || skb_headroom(skb) < hdrlen + 4) { + /* Current SKB cannot be modified */ + DBG_SKB(("Realloc Tx SKB\n")); + if (device_is_sand(sinfo)) { + headroom = hdrlen; + } else { + headroom = hdrlen + 4; + } + tailroom = FCS_SZ; + new_skb = skb_copy_expand(skb, + headroom + skb_headroom(skb), + tailroom + skb_tailroom(skb), + GFP_ATOMIC); + if (new_skb == NULL) { + DBG_WARN(("Tx drop: No SKB memory\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_no_skb++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + skb_push(new_skb, hdrlen); + bkn_skb_tstamp_copy(new_skb, skb); + dev_kfree_skb_any(skb); + skb = new_skb; + } else { + DBG_SKB(("Expand Tx SKB\n")); + skb_push(skb, hdrlen); + } + memset(skb->data, 0, hdrlen); + pktdata = skb->data; + pktlen += hdrlen; + } else { + hdrlen = 0; + } + + if (priv->port < 0 || (priv->flags & KCOM_NETIF_F_ADD_TAG)) { + DBG_DUNE(("ADD VLAN TAG\n")); + /* Need to add VLAN tag if packet is untagged */ + tpid = PKT_U16_GET(skb->data, hdrlen + 12); + if (tpid != 0x8100) { + if (skb_header_cloned(skb) || skb_headroom(skb) < 4) { + /* Current SKB cannot be modified */ + DBG_SKB(("Realloc Tx SKB\n")); + headroom = TAG_SZ; + tailroom = FCS_SZ; + new_skb = skb_copy_expand(skb, + headroom + skb_headroom(skb), + tailroom + skb_tailroom(skb), + GFP_ATOMIC); + if (new_skb == NULL) { + DBG_WARN(("Tx drop: No SKB memory\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_no_skb++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + skb_push(new_skb, TAG_SZ); + memcpy(new_skb->data, pktdata, hdrlen + 12); + bkn_skb_tstamp_copy(new_skb, skb); + dev_kfree_skb_any(skb); + skb = new_skb; + } else { + /* Add tag to existing buffer */ + DBG_SKB(("Expand Tx SKB\n")); + skb_push(skb, TAG_SZ); + for (idx = 0; idx < hdrlen + 12; idx++) { + skb->data[idx] = skb->data[idx + TAG_SZ]; + } + } + pktdata = skb->data; + pktdata[hdrlen + 12] = 0x81; + pktdata[hdrlen + 13] = 0x00; + pktdata[hdrlen + 14] = (priv->vlan >> 8) & 0xf; + pktdata[hdrlen + 15] = priv->vlan & 0xff; + pktlen += TAG_SZ; + } + } + } + + /* Pad packet if needed */ + taglen = 0; + tpid = PKT_U16_GET(pktdata, hdrlen + 12); + if (tpid == 0x8100) { + taglen = 4; + } + if (pktlen < (60 + taglen + hdrlen)) { + pktlen = (60 + taglen + hdrlen); + if (SKB_PADTO(skb, pktlen) != 0) { + DBG_WARN(("Tx drop: skb_padto failed\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_pad_fail++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + /* skb_padto may update the skb->data pointer */ + pktdata = &skb->data[rcpulen]; + } + + if ((pktlen + FCS_SZ) > SOC_DCB_KNET_COUNT_MASK) { + DBG_WARN(("Tx drop: size of pkt (%d) is out of range(%d)\n", + (pktlen + FCS_SZ), SOC_DCB_KNET_COUNT_MASK)); + sinfo->tx.pkts_d_over_limit++; + priv->stats.tx_dropped++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + + dcb = desc->dcb_mem; + meta = (sinfo->cmic_type == 'x') ? (uint32_t *)pktdata : dcb; + memset(dcb, 0, sinfo->dcb_wsize * sizeof(uint32_t)); + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { + if (device_is_sand(sinfo)) { + if (sinfo->cmic_type == 'x') { + dcb[2] |= 1 << 19; + /* Given Module Header exists and set first byte to be CPU channel */ + pktdata[0] = cpu_channel; + } else { + dcb[1] |= 1 << 19; + /* Set CPU channel */ + dcb[2] = (cpu_channel & 0xff) << 24; + } + + } else if (sop != 0) { + /* If module header SOP is non-zero, use RCPU meta data */ + if (sinfo->cmic_type == 'x') { + dcb[2] |= 1 << 19; + } else { + metalen = (sinfo->dcb_wsize - 3) * sizeof(uint32_t); + if (metalen > RCPU_TX_META_SIZE) { + metalen = RCPU_TX_META_SIZE; + } + metadata = (uint32_t *)&skb->data[RCPU_HDR_SIZE]; + for (idx = 0; idx < BYTES2WORDS(metalen); idx++) { + dcb[idx + 2] = ntohl(metadata[idx]); + } + dcb[1] |= 1 << 19; + } + } + } else if (priv->port >= 0) { + /* Send to physical port */ + if (sinfo->cmic_type == 'x') { + dcb[2] |= 1 << 19; + } else { + dcb[1] |= 1 << 19; + } + switch (sinfo->dcb_type) { + case 23: + case 26: + case 30: + case 31: + case 34: + case 37: + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[3] |= (priv->qnum & 0xc00) << 20; + dcb[4] = 0x00040000; + dcb[4] |= (priv->qnum & 0x3ff) << 8; + break; + case 24: + dcb[2] = 0xff000000; + dcb[3] = 0x00000100; + dcb[4] = priv->port; + dcb[4] |= (priv->qnum & 0xfff) << 14; + break; + case 28: + /* + * If KCOM_NETIF_T_PORT, add PTCH+ITMH header + * If KCOM_NETIF_T_VLAN, add PTCH+header + */ + pktdata = skb->data; + memcpy(&pktdata[0], priv->system_headers, priv->system_headers_size); + /* Set CPU channel */ + dcb[2] = ((priv->qnum & 0xff) << 24); + break; + case 29: + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[4] = 0x00100000; + dcb[4] |= (priv->qnum & 0xfff) << 8; + break; + case 32: + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[4] = 0x00004000; + dcb[4] |= (priv->qnum & 0x3f) << 8; + break; + case 33: + dcb[2] = 0x81000000; + dcb[3] = (priv->port) << 2; + dcb[4] = 0x00100000; + dcb[4] |= (priv->qnum & 0xfff) << 8; + break; + case 35: + dcb[2] = 0x81000000; + dcb[3] = (priv->port) << 4; + dcb[4] = 0x00400000; + dcb[4] |= (priv->qnum & 0x3fff) << 8; + break; + case 36: + if (sinfo->cmic_type == 'x') { + meta[0] = htonl(0x81000000); + meta[1] = htonl(priv->port); + meta[2] = htonl(0x00008000 | (priv->qnum & 0x3f) << 9); + } else { + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[4] = 0x00008000; + dcb[4] |= (priv->qnum & 0x3f) << 9; + } + break; + case 38: + if (sinfo->cmic_type == 'x') { + meta[0] = htonl(0x81000000); + meta[1] = htonl(priv->port); + meta[2] = htonl(0x00004000 | (priv->qnum & 0x3f) << 8); + } else { + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[4] = 0x00004000; + dcb[4] |= (priv->qnum & 0x3f) << 8; + } + break; + case 39: + if (device_is_dnx(sinfo)) { + /* + * if KCOM_NETIF_T_PORT, add MH+PTCH+ITMH header + * if KCOM_NETIF_T_VLAN, add MH+PTCH+header + */ + pktdata = skb->data; + memcpy(&pktdata[0], priv->system_headers, priv->system_headers_size); + } + break; + case 40: + if (sinfo->cmic_type == 'x') { + meta[0] = htonl(0x81000000); + meta[1] = htonl(priv->port | (priv->qnum & 0xc00) << 20); + meta[2] = htonl(0x00040000 | (priv->qnum & 0x3ff) << 8); + } else { + dcb[2] = 0x81000000; + dcb[3] = priv->port; + dcb[3] |= (priv->qnum & 0xc00) << 20; + dcb[4] = 0x00040000; + dcb[4] |= (priv->qnum & 0x3ff) << 8; + } + break; + default: + dcb[2] = 0xff000000; + dcb[3] = 0x00000100; + dcb[4] = priv->port; + break; + } + } + + /* Optional SKB updates */ + if (knet_tx_cb != NULL) { + KNET_SKB_CB(skb)->netif_user_data = priv->cb_user_data; + KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF; + skb = knet_tx_cb(skb, sinfo->dev_no, meta); + if (skb == NULL) { + /* Consumed by call-back */ + DBG_WARN(("Tx drop: Consumed by call-back\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_callback++; + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + /* Restore (possibly) altered packet variables + * bit0 -bit15 of dcb[1] is used to save requested byte count + */ + if ((skb->len + FCS_SZ) <= SOC_DCB_KNET_COUNT_MASK) { + pktlen = skb->len; + if (pktlen < (60 + taglen + hdrlen)) { + pktlen = (60 + taglen + hdrlen); + if (SKB_PADTO(skb, pktlen) != 0) { + DBG_WARN(("Tx drop: skb_padto failed\n")); + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_pad_fail++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + DBG_SKB(("Packet padded to %d bytes after tx callback\n", pktlen)); + } + pktdata = skb->data; + if (sinfo->cmic_type == 'x') { + meta = (uint32_t *)pktdata; + } + } else { + DBG_WARN(("Tx drop: size of pkt (%d) is out of range(%d)\n", + (pktlen + FCS_SZ), SOC_DCB_KNET_COUNT_MASK)); + sinfo->tx.pkts_d_over_limit++; + priv->stats.tx_dropped++; + sinfo->tx.pkts_d_callback++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + } + + /* Do Tx timestamping */ + if (bkn_skb_tx_flags(skb) & SKBTX_HW_TSTAMP) { + KNET_SKB_CB(skb)->hwts = priv->tx_hwts; + if ((priv->port >= 0) && (priv->tx_hwts & HWTSTAMP_TX_ON)) { + /* TwoStep Processing of ptp-packets */ + KNET_SKB_CB(skb)->port = priv->phys_port; + bkn_hw_tstamp_tx_config(sinfo, priv->tx_hwts, PKT_TX_HDR_SIZE, skb, meta); + + bkn_skb_tx_flags(skb) |= SKBTX_IN_PROGRESS; + bkn_skb_tx_timestamp(skb); + + } else if (priv->tx_hwts & HWTSTAMP_TX_ONESTEP_SYNC) { + + /* OneStep Processing of ptp-packets */ + KNET_SKB_CB(skb)->port = priv->phys_port; + KNET_SKB_CB(skb)->ts = 0; + bkn_hw_tstamp_tx_config(sinfo, priv->tx_hwts, PKT_TX_HDR_SIZE, skb, + ((priv->port >= 0) ? meta : NULL)); + + if (KNET_SKB_CB(skb)->ts != 0) { + bkn_skb_tx_flags(skb) |= SKBTX_IN_PROGRESS; + bkn_skb_tx_timestamp(skb); + } + + } + } + + /* Prepare for DMA */ + desc->skb = skb; + /* + * Add FCS bytes + * FCS bytes are always appended to packet by MAC on Dune devices + */ + if (!device_is_sand(sinfo)) { + pktlen = pktlen + FCS_SZ; + } + desc->dma_size = pktlen; + desc->skb_dma = BKN_DMA_MAP_SINGLE(sinfo->dma_dev, + pktdata, desc->dma_size, + BKN_DMA_TODEV); + if (BKN_DMA_MAPPING_ERROR(sinfo->dma_dev, desc->skb_dma)) { + priv->stats.tx_dropped++; + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&sinfo->lock, flags); + return 0; + } + dcb[0] = desc->skb_dma; + if (sinfo->cmic_type == 'x') { + dcb[1] = DMA_TO_BUS_HI(desc->skb_dma >> 32); + dcb[2] &= ~SOC_DCB_KNET_COUNT_MASK; + dcb[2] |= pktlen; + } else { + dcb[1] &= ~SOC_DCB_KNET_COUNT_MASK; + dcb[1] |= pktlen; + } + + bkn_dump_dcb("Tx RCPU", dcb, sinfo->dcb_wsize, XGS_DMA_TX_CHAN); + DBG_DCB_TX(("Add Tx DCB @ 0x%08x (%d) [%d free] (%d bytes).\n", + (uint32_t)desc->dcb_dma, sinfo->tx.cur, + sinfo->tx.free, pktlen)); + bkn_dump_pkt(pktdata, pktlen, XGS_DMA_TX_CHAN); + + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + if (sinfo->cmic_type == 'x') { + dcb[2] |= 1 << 24 | 1 << 16; + } else { + dcb[1] |= 1 << 24 | 1 << 16; + } + } else { + bkn_tx_dma_start(sinfo); + } + if (++sinfo->tx.cur >= MAX_TX_DCBS) { + sinfo->tx.cur = 0; + } + sinfo->tx.free--; + + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN) && !sinfo->tx.api_active) { + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, + sinfo->tx.desc[sinfo->tx.cur].dcb_dma); + } + + priv->stats.tx_packets++; + priv->stats.tx_bytes += pktlen; + sinfo->tx.pkts++; + } else { + DBG_VERB(("Tx busy: No DMA resources\n")); + sinfo->tx.pkts_d_dma_resrc++; + bkn_suspend_tx(sinfo); + spin_unlock_irqrestore(&sinfo->lock, flags); + return BKN_NETDEV_TX_BUSY; + } + + NETDEV_UPDATE_TRANS_START_TIME(dev); + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return 0; +} + +static void +bkn_timer_func(bkn_switch_info_t *sinfo) +{ + unsigned long flags; + int chan; + int restart_timer; + + spin_lock_irqsave(&sinfo->lock, flags); + + sinfo->timer_runs++; + + restart_timer = 0; + for (chan = 0; chan < sinfo->rx_chans; chan++) { + /* Restart channel if not running */ + if (sinfo->rx[chan].running == 0) { + bkn_rx_refill(sinfo, chan); + if (bkn_rx_restart(sinfo, chan) != 0) { + restart_timer = 1; + } + } + } + + if (restart_timer) { + /* Presumably still out of memory */ + sinfo->timer.expires = jiffies + 1; + add_timer(&sinfo->timer); + } else { + sinfo->timer_queued = 0; + } + + spin_unlock_irqrestore(&sinfo->lock, flags); +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) +static void +bkn_timer(unsigned long context) +{ + bkn_switch_info_t *sinfo = (bkn_switch_info_t *)context; + return bkn_timer_func(sinfo); +} +#else +static void +bkn_timer(struct timer_list *t) +{ + bkn_switch_info_t *sinfo = from_timer(sinfo, t, timer); + return bkn_timer_func(sinfo); +} +#endif + +static void +bkn_rx_add_tokens(bkn_switch_info_t *sinfo, int chan) +{ + unsigned long cur_jif, ticks; + uint32_t tokens_per_tick; + bkn_desc_info_t *desc; + + tokens_per_tick = sinfo->rx[chan].rate_max / HZ; + cur_jif = jiffies; + ticks = cur_jif - sinfo->rx[chan].tok_jif; + sinfo->rx[chan].tokens += ticks * tokens_per_tick; + sinfo->rx[chan].tok_jif = cur_jif; + if (sinfo->rx[chan].tokens > sinfo->rx[chan].burst_max) { + sinfo->rx[chan].tokens = sinfo->rx[chan].burst_max; + } + + /* Restart channel if Rx is suppressed */ + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + bkn_rx_refill(sinfo, chan); + desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty]; + if (desc->dcb_dma == sinfo->halt_addr[XGS_DMA_RX_CHAN + chan]) { + desc = &sinfo->rx[chan].desc[MAX_RX_DCBS]; + bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma); + } + } else { + if (sinfo->rx[chan].running == 0) { + bkn_rx_refill(sinfo, chan); + bkn_rx_restart(sinfo, chan); + } + } +} + +static void +bkn_rxtick_func(bkn_switch_info_t *sinfo) +{ + unsigned long flags; + unsigned long cur_jif, ticks; + uint32_t pkt_diff; + int chan; + + spin_lock_irqsave(&sinfo->lock, flags); + + sinfo->rxtick.expires = jiffies + sinfo->rxtick_jiffies; + + /* For debug purposes we maintain a rough actual packet rate */ + if (++sinfo->rxticks >= sinfo->rxticks_per_sec) { + for (chan = 0; chan < sinfo->rx_chans; chan++) { + pkt_diff = sinfo->rx[chan].pkts - sinfo->rx[chan].pkts_ref; + cur_jif = jiffies; + ticks = cur_jif - sinfo->rx[chan].rate_jif; + sinfo->rx[chan].rate = (pkt_diff * HZ) / ticks; + sinfo->rx[chan].rate_jif = cur_jif; + sinfo->rx[chan].pkts_ref = sinfo->rx[chan].pkts; + } + sinfo->rxticks = 0; + } + + /* Update tokens for Rx rate control */ + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (sinfo->rx[chan].tokens < sinfo->rx[chan].burst_max) { + bkn_rx_add_tokens(sinfo, chan); + } + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + add_timer(&sinfo->rxtick); +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) +static void +bkn_rxtick(unsigned long context) +{ + bkn_switch_info_t *sinfo = (bkn_switch_info_t *)context; + return bkn_rxtick_func(sinfo); +} +#else +static void +bkn_rxtick(struct timer_list *t) +{ + bkn_switch_info_t *sinfo = from_timer(sinfo, t, rxtick); + return bkn_rxtick_func(sinfo); +} +#endif + +static void +bkn_rx_rate_config(bkn_switch_info_t *sinfo) +{ + unsigned long flags; + int chan; + uint32_t rxticks_per_sec, rps; + uint32_t jiffies_per_rxtick; + uint32_t tokens_per_rxtick; + + spin_lock_irqsave(&sinfo->lock, flags); + + /* Calculate the minimum update frequency across all channels */ + rxticks_per_sec = 1; + for (chan = 0; chan < NUM_RX_CHAN; chan++) { + if (sinfo->rx[chan].burst_max == 0) { + sinfo->rx[chan].burst_max = sinfo->rx[chan].rate_max / 10; + } + rps = sinfo->rx[chan].rate_max / sinfo->rx[chan].burst_max; + if (rxticks_per_sec < rps) { + rxticks_per_sec = rps; + } + } + + /* Convert update frequency to system ticks */ + jiffies_per_rxtick = HZ / rxticks_per_sec; + if (jiffies_per_rxtick == 0) { + jiffies_per_rxtick = 1; + } + rxticks_per_sec = HZ / jiffies_per_rxtick; + + for (chan = 0; chan < NUM_RX_CHAN; chan++) { + /* Ensure that burst size satifies overall rate */ + tokens_per_rxtick = sinfo->rx[chan].rate_max / rxticks_per_sec; + if (sinfo->rx[chan].burst_max < tokens_per_rxtick) { + sinfo->rx[chan].burst_max = tokens_per_rxtick; + } + /* Ensure that rate has a sane value */ + if (sinfo->rx[chan].rate_max != 0) { + if (sinfo->rx[chan].rate_max < rxticks_per_sec) { + sinfo->rx[chan].rate_max = rxticks_per_sec; + } + } + sinfo->rx[chan].tokens = sinfo->rx[chan].burst_max; + } + + /* Update timer controls */ + sinfo->rxticks_per_sec = rxticks_per_sec; + sinfo->rxtick_jiffies = jiffies_per_rxtick; + + spin_unlock_irqrestore(&sinfo->lock, flags); +} + +static void +bkn_destroy_sinfo(bkn_switch_info_t *sinfo) +{ + list_del(&sinfo->list); + bkn_free_dcbs(sinfo); + kfree(sinfo); +} + +static bkn_switch_info_t * +bkn_create_sinfo(int dev_no) +{ + bkn_switch_info_t *sinfo; + int chan; + + if ((sinfo = kmalloc(sizeof(*sinfo), GFP_KERNEL)) == NULL) { + return NULL; + } + memset(sinfo, 0, sizeof(*sinfo)); + INIT_LIST_HEAD(&sinfo->ndev_list); + INIT_LIST_HEAD(&sinfo->rxpf_list); + sinfo->base_addr = lkbde_get_dev_virt(dev_no); + sinfo->dma_dev = lkbde_get_dma_dev(dev_no); + sinfo->pdev = lkbde_get_hw_dev(dev_no); + sinfo->dev_no = dev_no; + sinfo->inst_id = INVALID_INSTANCE_ID; + sinfo->evt_idx = -1; + + spin_lock_init(&sinfo->lock); + skb_queue_head_init(&sinfo->tx_ptp_queue); + INIT_WORK(&sinfo->tx_ptp_work, bkn_hw_tstamp_tx_work); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) + init_timer(&sinfo->timer); + sinfo->timer.data = (unsigned long)sinfo; + sinfo->timer.function = bkn_timer; +#else + timer_setup(&sinfo->timer, bkn_timer, 0); +#endif + sinfo->timer.expires = jiffies + 1; + + INIT_LIST_HEAD(&sinfo->tx.api_dcb_list); + + for (chan = 0; chan < NUM_RX_CHAN; chan++) { + INIT_LIST_HEAD(&sinfo->rx[chan].api_dcb_list); + sinfo->rx[chan].use_rx_skb = use_rx_skb; + } + + /* + * Check for dual DMA mode where Rx DMA channel 0 uses DMA buffers + * provided by the BCM API, and the remaining Rx DMA channel(s) + * use socket buffers (SKB) provided by the Linux kernel. + */ + if (use_rx_skb == 2) { + sinfo->rx[0].use_rx_skb = 0; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) + init_timer(&sinfo->rxtick); + sinfo->rxtick.data = (unsigned long)sinfo; + sinfo->rxtick.function = bkn_rxtick; +#else + timer_setup(&sinfo->rxtick, bkn_rxtick, 0); +#endif + sinfo->rxtick.expires = jiffies + 1; + + for (chan = 0; chan < NUM_RX_CHAN; chan++) { + sinfo->rx[chan].rate_max = rx_rate[chan]; + sinfo->rx[chan].burst_max = rx_burst[chan]; + } + bkn_rx_rate_config(sinfo); + + add_timer(&sinfo->rxtick); + + list_add_tail(&sinfo->list, &_sinfo_list); + + return sinfo; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) +static const struct net_device_ops bkn_netdev_ops = { + .ndo_open = bkn_open, + .ndo_stop = bkn_stop, + .ndo_start_xmit = bkn_tx, + .ndo_get_stats = bkn_get_stats, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = bkn_set_multicast_list, + .ndo_set_mac_address = bkn_set_mac_address, + .ndo_do_ioctl = bkn_ioctl, + .ndo_tx_timeout = NULL, + .ndo_change_mtu = bkn_change_mtu, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = bkn_poll_controller, +#endif +}; +#endif + +static void +bkn_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) +{ + strlcpy(drvinfo->driver, "bcm-knet", sizeof(drvinfo->driver)); + snprintf(drvinfo->version, sizeof(drvinfo->version), "%d", KCOM_VERSION); + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info)); +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)) +static int +bkn_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + + switch (sinfo->dcb_type) { + case 26: + case 32: + case 33: + case 35: + case 36: + case 38: + case 40: + info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON; + info->rx_filters = 1 << HWTSTAMP_FILTER_NONE | 1 << HWTSTAMP_FILTER_ALL; + if (knet_hw_tstamp_ptp_clock_index_cb) { + info->phc_index = knet_hw_tstamp_ptp_clock_index_cb(sinfo->dev_no); + } else { + info->phc_index = -1; + } + break; + default: + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + info->phc_index = -1; + break; + } + + return 0; +} +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0)) +static int bkn_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + bkn_priv_t *priv = netdev_priv(netdev); + + /* only speed info now, can enhance later */ + if (priv) { + cmd->base.speed = priv->link_settings.speed; + cmd->base.duplex = priv->link_settings.duplex; + } + return 0; +} + +static int bkn_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) +{ + bkn_priv_t *priv = netdev_priv(netdev); + + /* only speed info now, can enhance later */ + if (priv) { + priv->link_settings.speed = cmd->base.speed; + priv->link_settings.duplex = cmd->base.speed? DUPLEX_FULL : 0; + } + return 0; +} +#endif + +static const struct ethtool_ops bkn_ethtool_ops = { + .get_drvinfo = bkn_get_drvinfo, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)) + .get_ts_info = bkn_get_ts_info, +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0)) + .get_link_ksettings = bkn_get_link_ksettings, + .set_link_ksettings = bkn_set_link_ksettings, +#endif +}; + +static struct net_device * +bkn_init_ndev(u8 *mac, char *name) +{ + struct net_device *dev; + + /* Create Ethernet device */ + dev = alloc_etherdev(sizeof(bkn_priv_t)); + + if (dev == NULL) { + DBG_WARN(("Error allocating Ethernet device.\n")); + return NULL; + } +#ifdef SET_MODULE_OWNER + SET_MODULE_OWNER(dev); +#endif + + /* Set the device MAC address */ + memcpy(dev->dev_addr, mac, 6); + + /* Device information -- not available right now */ + dev->irq = 0; + dev->base_addr = 0; + + /* Default MTU should not exceed MTU of switch front-panel ports */ + dev->mtu = default_mtu; + if (dev->mtu == 0) { + dev->mtu = rx_buffer_size; + } + + /* Device vectors */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) + dev->netdev_ops = &bkn_netdev_ops; +#else + dev->open = bkn_open; + dev->hard_start_xmit = bkn_tx; + dev->stop = bkn_stop; + dev->set_multicast_list = bkn_set_multicast_list; + dev->do_ioctl = NULL; + dev->get_stats = bkn_get_stats; + dev->change_mtu = bkn_change_mtu; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = bkn_poll_controller; +#endif +#endif + dev->ethtool_ops = &bkn_ethtool_ops; + if (name && *name) { + strncpy(dev->name, name, IFNAMSIZ-1); + } + +#if defined(CONFIG_NET_NS) + bkn_dev_net_set(dev, current->nsproxy->net_ns); +#endif + + /* Register the kernel Ethernet device */ + if (register_netdev(dev)) { + DBG_WARN(("Error registering Ethernet device.\n")); + free_netdev(dev); + return NULL; + } + DBG_VERB(("Created Ethernet device %s.\n", dev->name)); + + return dev; +} + +/* + * Device Link Control Proc Read Entry + */ +static int +bkn_proc_link_show(struct seq_file *m, void *v) +{ + struct list_head *slist, *dlist; + struct net_device *dev; + bkn_priv_t *priv; + bkn_switch_info_t *sinfo; + unsigned long flags; + + seq_printf(m, "Software link status:\n"); + list_for_each(slist, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)slist; + spin_lock_irqsave(&sinfo->lock, flags); + list_for_each(dlist, &sinfo->ndev_list) { + priv = (bkn_priv_t *)dlist; + dev = priv->dev; + if (dev) { + seq_printf(m, " %-14s %s\n", dev->name, + netif_carrier_ok(dev) ? "up" : "down"); + } + } + spin_unlock_irqrestore(&sinfo->lock, flags); + } + return 0; +} + +static int +bkn_proc_link_open(struct inode * inode, struct file * file) +{ + return single_open(file, bkn_proc_link_show, NULL); +} + +/* + * Device Link Control Proc Write Entry + * + * Syntax: + * =up|down + * + * Where is a virtual network interface name. + * + * Examples: + * eth4=up + * eth4=down + */ +static ssize_t +bkn_proc_link_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + struct list_head *slist, *dlist; + struct net_device *dev; + bkn_priv_t *priv; + bkn_switch_info_t *sinfo; + unsigned long flags; + char link_str[40]; + char *ptr; + char *newline; + + if (count > sizeof(link_str)) { + count = sizeof(link_str) - 1; + link_str[count] = '\0'; + } + if (copy_from_user(link_str, buf, count)) { + return -EFAULT; + } + link_str[count] = 0; + newline = strchr(link_str, '\n'); + if (newline) { + /* Chop off the trailing newline */ + *newline = '\0'; + } + + if ((ptr = strchr(link_str, '=')) == NULL && + (ptr = strchr(link_str, ':')) == NULL) { + gprintk("Error: link syntax not recognized: '%s'\n", link_str); + return count; + } + *ptr++ = 0; + + dev = NULL; + list_for_each(slist, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)slist; + spin_lock_irqsave(&sinfo->lock, flags); + list_for_each(dlist, &sinfo->ndev_list) { + priv = (bkn_priv_t *)dlist; + if (priv->dev) { + if (strcmp(priv->dev->name, link_str) == 0) { + dev = priv->dev; + break; + } + } + } + if (dev) { + if (strcmp(ptr, "up") == 0) { + netif_carrier_on(dev); + } else if (strcmp(ptr, "down") == 0) { + netif_carrier_off(dev); + } else { + gprintk("Warning: unknown link state setting: '%s'\n", ptr); + } + spin_unlock_irqrestore(&sinfo->lock, flags); + return count; + } + spin_unlock_irqrestore(&sinfo->lock, flags); + } + + gprintk("Warning: unknown network interface: '%s'\n", link_str); + + return count; +} + +struct file_operations bkn_proc_link_file_ops = { + owner: THIS_MODULE, + open: bkn_proc_link_open, + read: seq_read, + llseek: seq_lseek, + write: bkn_proc_link_write, + release: single_release, +}; + +/* + * Device Rate Control Proc Read Entry + */ +static int +bkn_proc_rate_show(struct seq_file *m, void *v) +{ + int unit = 0; + struct list_head *list; + bkn_switch_info_t *sinfo; + int chan; + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + + seq_printf(m, "Rate control (unit %d):\n", unit); + for (chan = 0; chan < sinfo->rx_chans; chan++) { + seq_printf(m, " Rx%d max rate %8u\n", + chan, sinfo->rx[chan].rate_max); + seq_printf(m, " Rx%d max burst %8u\n", + chan, sinfo->rx[chan].burst_max); + seq_printf(m, " Rx%d rate %8u\n", + chan, sinfo->rx[chan].rate); + seq_printf(m, " Rx%d tokens %8u\n", + chan, sinfo->rx[chan].tokens); + } + + unit++; + } + return 0; +} + +static int +bkn_proc_rate_open(struct inode * inode, struct file * file) +{ + return single_open(file, bkn_proc_rate_show, NULL); +} + +/* + * Device Rate Control Proc Write Entry + * + * Syntax: + * [:]rx_rate=[,[, is packets/sec for the first Rx DMA channel, + * is packets/sec for the second Rx DMA channel, etc. + * + * Examples: + * rx_rate=5000 + * 0:rx_rate=10000,10000 + * 1:rx_rate=10000,5000 + */ +static ssize_t +bkn_proc_rate_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + bkn_switch_info_t *sinfo; + char rate_str[80]; + char *ptr; + int unit, chan; + + if (count > sizeof(rate_str)) { + count = sizeof(rate_str) - 1; + rate_str[count] = '\0'; + } + if (copy_from_user(rate_str, buf, count)) { + return -EFAULT; + } + + unit = simple_strtol(rate_str, NULL, 10); + sinfo = bkn_sinfo_from_unit(unit); + if (sinfo == NULL) { + gprintk("Warning: unknown unit: %d\n", unit); + return count; + } + + if ((ptr = strstr(rate_str, "rx_rate=")) != NULL) { + ptr += 7; + chan = 0; + do { + ptr++; + sinfo->rx[chan].rate_max = simple_strtol(ptr, NULL, 10); + } while ((ptr = strchr(ptr, ',')) != NULL && ++chan < sinfo->rx_chans); + bkn_rx_rate_config(sinfo); + } else if ((ptr = strstr(rate_str, "rx_burst=")) != NULL) { + ptr += 8; + chan = 0; + do { + ptr++; + sinfo->rx[chan].burst_max = simple_strtol(ptr, NULL, 10); + } while ((ptr = strchr(ptr, ',')) != NULL && ++chan < sinfo->rx_chans); + bkn_rx_rate_config(sinfo); + } else { + gprintk("Warning: unknown configuration setting\n"); + } + + return count; +} + +struct file_operations bkn_proc_rate_file_ops = { + owner: THIS_MODULE, + open: bkn_proc_rate_open, + read: seq_read, + llseek: seq_lseek, + write: bkn_proc_rate_write, + release: single_release, +}; + +/* + * Driver DMA Proc Entry + * + * This output can be rather large (> PAGE_SIZE) so we use the + * seq_file interface to do the output. Special header records + * are indicated by a negative DCB index. + */ +typedef struct { + int dev_no; /* Current unit */ + int rx_dma; /* 0: Tx DMA, 1: Rx DMA*/ + int ch_no; /* DMA channel no. (Rx only) */ + int idx; /* DCB index */ +} bkn_seq_dma_iter_t; + +/* From current record, move forward 'pos' records */ +static int +bkn_seq_dma_next_pos(bkn_seq_dma_iter_t *iter, loff_t pos) +{ + bkn_switch_info_t *sinfo; + + sinfo = bkn_sinfo_from_unit(iter->dev_no); + while (pos) { + if (iter->rx_dma) { + if (++iter->idx >= MAX_RX_DCBS + 1) { + iter->idx = -1; + if (++iter->ch_no >= sinfo->rx_chans) { + iter->rx_dma = 0; + iter->ch_no = 0; + iter->dev_no++; + if ((sinfo = bkn_sinfo_from_unit(iter->dev_no)) == NULL) { + return -1; + } + } + } + } else { + if (++iter->idx >= MAX_TX_DCBS + 1) { + iter->idx = -1; + iter->rx_dma = 1; + } + } + pos--; + } + return 0; +} + +/* Initialize private data and move to requested start record */ +static void * +bkn_seq_dma_start(struct seq_file *s, loff_t *pos) +{ + bkn_seq_dma_iter_t *iter; + + iter = kmalloc(sizeof(bkn_seq_dma_iter_t), GFP_KERNEL); + if (!iter) { + return NULL; + } + memset(iter, 0, sizeof(*iter)); + iter->idx = -2; + if (bkn_seq_dma_next_pos(iter, *pos) < 0) { + kfree(iter); + return NULL; + } + return iter; +} + +/* Move to next record */ +static void * +bkn_seq_dma_next(struct seq_file *s, void *v, loff_t *pos) +{ + bkn_seq_dma_iter_t *iter = (bkn_seq_dma_iter_t *)v; + void *rv = iter; + + if (bkn_seq_dma_next_pos(iter, 1) < 0) { + return NULL; + } + (*pos)++; + return rv; +} + +/* Release private data */ +static void +bkn_seq_dma_stop(struct seq_file *s, void *v) +{ + if (v) { + kfree(v); + } +} + +/* Print current record */ +static int +bkn_seq_dma_show(struct seq_file *s, void *v) +{ + bkn_seq_dma_iter_t *iter = (bkn_seq_dma_iter_t *)v; + bkn_switch_info_t *sinfo; + uint32_t *dcb = NULL; + bkn_dcb_chain_t *dcb_chain = NULL; + struct list_head *curr, *next; + unsigned long flags; + int chan, cnt; + + sinfo = bkn_sinfo_from_unit(iter->dev_no); + if (sinfo == NULL) { + /* Should not happen */ + return 0; + } + + if (iter->rx_dma == 0) { + if (iter->idx == -2) { + seq_printf(s, "Pending events: 0x%x\n", sinfo->dma_events); + } else if (iter->idx == -1) { + spin_lock_irqsave(&sinfo->lock, flags); + curr = &sinfo->tx.api_dcb_list; + dcb_chain = sinfo->tx.api_dcb_chain; + while (dcb_chain) { + seq_printf(s, " [0x%08lx]--->\n", (unsigned long)dcb_chain->dcb_dma); + for (cnt = 0; cnt < dcb_chain->dcb_cnt; cnt++) { + dcb = &dcb_chain->dcb_mem[sinfo->dcb_wsize * cnt]; + if (sinfo->cmic_type == 'x') { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x 0x%08x 0x%08x\n", cnt, + dcb[0], dcb[1], dcb[2], dcb[sinfo->dcb_wsize-1]); + } else { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x ... 0x%08x\n", cnt, + dcb[0], dcb[1], dcb[sinfo->dcb_wsize-1]); + } + } + next = curr->next; + if (next != &sinfo->tx.api_dcb_list) { + dcb_chain = list_entry(next, bkn_dcb_chain_t, list); + curr = next; + } else { + dcb_chain = NULL; + } + } + dcb = NULL; + spin_unlock_irqrestore(&sinfo->lock, flags); + seq_printf(s, + "Tx DCB info (unit %d):\n" + " api: %d\n" + " dirty: %d\n" + " cur: %d\n" + " free: %d\n" + " pause: %s\n", + iter->dev_no, + sinfo->tx.api_active, + sinfo->tx.dirty, + sinfo->tx.cur, + sinfo->tx.free, + netif_queue_stopped(sinfo->dev) ? "yes" : "no"); + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + bkn_desc_info_t *desc = &sinfo->tx.desc[0]; + uint64_t halt = sinfo->halt_addr[XGS_DMA_TX_CHAN]; + seq_printf(s, + " halt: %d\n", + (int)((uint32_t)(halt - desc->dcb_dma) / (sinfo->dcb_wsize * sizeof(uint32_t)))); + } + } else { + dcb = sinfo->tx.desc[iter->idx].dcb_mem; + if (iter->idx == 0) { + seq_printf(s, " [0x%08lx]--->\n", (unsigned long)sinfo->tx.desc[0].dcb_dma); + } + } + } else { + if (iter->idx == -1) { + chan = iter->ch_no; + seq_printf(s, + "Rx%d DCB info (unit %d):\n" + " api: %d\n" + " dirty: %d\n" + " cur: %d\n" + " free: %d\n" + " run: %d\n", + chan, iter->dev_no, + sinfo->rx[chan].api_active, + sinfo->rx[chan].dirty, + sinfo->rx[chan].cur, + sinfo->rx[chan].free, + sinfo->rx[chan].running); + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && sinfo->rx[chan].use_rx_skb) { + bkn_desc_info_t *desc = &sinfo->rx[chan].desc[0]; + uint64_t halt = sinfo->halt_addr[XGS_DMA_RX_CHAN + chan]; + seq_printf(s, + " halt: %d\n", + (int)((uint32_t)(halt - desc->dcb_dma) / (sinfo->dcb_wsize * sizeof(uint32_t)))); + } + } else if (sinfo->rx[iter->ch_no].use_rx_skb) { + dcb = sinfo->rx[iter->ch_no].desc[iter->idx].dcb_mem; + if (iter->idx == 0) { + seq_printf(s, " [0x%08lx]--->\n", (unsigned long)sinfo->rx[iter->ch_no].desc[0].dcb_dma); + } + } else if (!sinfo->rx[iter->ch_no].use_rx_skb && iter->idx == 0) { + spin_lock_irqsave(&sinfo->lock, flags); + curr = &sinfo->rx[iter->ch_no].api_dcb_list; + dcb_chain = sinfo->rx[iter->ch_no].api_dcb_chain; + while (dcb_chain) { + seq_printf(s, " [0x%08lx]--->\n", (unsigned long)dcb_chain->dcb_dma); + for (cnt = 0; cnt < dcb_chain->dcb_cnt; cnt++) { + dcb = &dcb_chain->dcb_mem[sinfo->dcb_wsize * cnt]; + if (sinfo->cmic_type == 'x') { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x 0x%08x 0x%08x\n", cnt, + dcb[0], dcb[1], dcb[2], dcb[sinfo->dcb_wsize-1]); + } else { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x ... 0x%08x\n", cnt, + dcb[0], dcb[1], dcb[sinfo->dcb_wsize-1]); + } + } + next = curr->next; + if (next != &sinfo->rx[iter->ch_no].api_dcb_list) { + dcb_chain = list_entry(next, bkn_dcb_chain_t, list); + curr = next; + } else { + dcb_chain = NULL; + } + } + dcb = NULL; + spin_unlock_irqrestore(&sinfo->lock, flags); + } + } + if (dcb) { + if (sinfo->cmic_type == 'x') { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x 0x%08x 0x%08x\n", iter->idx, + dcb[0], dcb[1], dcb[2], dcb[sinfo->dcb_wsize-1]); + } else { + seq_printf(s, " DCB %2d: 0x%08x 0x%08x ... 0x%08x\n", iter->idx, + dcb[0], dcb[1], dcb[sinfo->dcb_wsize-1]); + } + } + return 0; +} + +static struct seq_operations bkn_seq_dma_ops = { + .start = bkn_seq_dma_start, + .next = bkn_seq_dma_next, + .stop = bkn_seq_dma_stop, + .show = bkn_seq_dma_show +}; + +static int +bkn_seq_dma_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &bkn_seq_dma_ops); +}; + +static struct file_operations bkn_seq_dma_file_ops = { + .owner = THIS_MODULE, + .open = bkn_seq_dma_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + +/* + * Device Debug Control Proc Write Entry + * + * Syntax: + * [:]debug= + * + * Where corresponds to the debug module parameter. + * + * Examples: + * debug=0xffff + * 0:debug-0x2000 + */ +static ssize_t +bkn_proc_debug_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + bkn_switch_info_t *sinfo; + char debug_str[40]; + char *ptr; + int unit; + + if (count > sizeof(debug_str)) { + count = sizeof(debug_str) - 1; + debug_str[count] = '\0'; + } + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + unit = simple_strtol(debug_str, NULL, 10); + sinfo = bkn_sinfo_from_unit(unit); + if (sinfo == NULL) { + gprintk("Warning: unknown unit: %d\n", unit); + return count; + } + + if ((ptr = strstr(debug_str, "debug=")) != NULL) { + ptr += 6; + debug = simple_strtol(ptr, NULL, 0); + } else { + gprintk("Warning: unknown configuration setting\n"); + } + + return count; +} + +/* + * Driver Debug Proc Entry + */ +static int +bkn_proc_debug_show(struct seq_file *m, void *v) +{ + int unit = 0; + struct list_head *list; + bkn_switch_info_t *sinfo; + + seq_printf(m, "Configuration:\n"); + seq_printf(m, " debug: 0x%x\n", debug); + seq_printf(m, " mac_addr: %02x:%02x:%02x:%02x:%02x:%02x\n", + bkn_dev_mac[0], bkn_dev_mac[1], bkn_dev_mac[2], + bkn_dev_mac[3], bkn_dev_mac[4], bkn_dev_mac[5]); + seq_printf(m, " rx_buffer_size: %d (0x%x)\n", + rx_buffer_size, rx_buffer_size); + seq_printf(m, " rcpu_mode: %d\n", rcpu_mode); + seq_printf(m, " rcpu_dmac: %02x:%02x:%02x:%02x:%02x:%02x\n", + bkn_rcpu_dmac[0], bkn_rcpu_dmac[1], bkn_rcpu_dmac[2], + bkn_rcpu_dmac[3], bkn_rcpu_dmac[4], bkn_rcpu_dmac[5]); + seq_printf(m, " rcpu_smac: %02x:%02x:%02x:%02x:%02x:%02x\n", + bkn_rcpu_smac[0], bkn_rcpu_smac[1], bkn_rcpu_smac[2], + bkn_rcpu_smac[3], bkn_rcpu_smac[4], bkn_rcpu_smac[5]); + seq_printf(m, " rcpu_ethertype: 0x%x\n", rcpu_ethertype); + seq_printf(m, " rcpu_signature: 0x%x\n", rcpu_signature); + seq_printf(m, " rcpu_vlan: %d\n", rcpu_vlan); + seq_printf(m, " use_rx_skb: %d\n", use_rx_skb); + seq_printf(m, " num_rx_prio: %d\n", num_rx_prio); + seq_printf(m, " check_rcpu_sig: %d\n", check_rcpu_signature); + seq_printf(m, " default_mtu: %d\n", default_mtu); + seq_printf(m, " rx_sync_retry: %d\n", rx_sync_retry); + seq_printf(m, " use_napi: %d\n", use_napi); + seq_printf(m, " napi_weight: %d\n", napi_weight); + seq_printf(m, " basedev_susp: %d\n", basedev_suspend); + seq_printf(m, " force_tagged: %d\n", force_tagged); + seq_printf(m, " ft_tpid: %d\n", ft_tpid); + seq_printf(m, " ft_pri: %d\n", ft_pri); + seq_printf(m, " ft_pri: %d\n", ft_cfi); + seq_printf(m, " ft_tpid: %d\n", ft_vid); + seq_printf(m, "Active IOCTLs:\n"); + seq_printf(m, " Command: %d\n", ioctl_cmd); + seq_printf(m, " Event: %d\n", ioctl_evt); + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + + seq_printf(m, "Device %d:\n", unit); + seq_printf(m, " base_addr: 0x%p\n", sinfo->base_addr); + seq_printf(m, " dev_no: %d\n", sinfo->dev_no); + seq_printf(m, " cmic_type: %c\n", sinfo->cmic_type); + seq_printf(m, " dcb_type: %d\n", sinfo->dcb_type); + seq_printf(m, " dcb_wsize: %d\n", sinfo->dcb_wsize); + seq_printf(m, " pkt_hdr_size: %d\n", sinfo->pkt_hdr_size); + seq_printf(m, " rx_chans: %d\n", sinfo->rx_chans); + seq_printf(m, " cdma_chans: 0x%x\n", sinfo->cdma_channels); + seq_printf(m, " irq_mask: 0x%x\n", sinfo->irq_mask); + seq_printf(m, " dma_events: 0x%x\n", sinfo->dma_events); + seq_printf(m, " dcb_dma: 0x%p\n", (void *)(sal_paddr_t)sinfo->dcb_dma); + seq_printf(m, " dcb_mem_size: 0x%x\n", sinfo->dcb_mem_size); + seq_printf(m, " rcpu_sig: 0x%x\n", sinfo->rcpu_sig); + seq_printf(m, " napi_poll_mode: %d\n", sinfo->napi_poll_mode); + seq_printf(m, " inst_id: 0x%x\n", sinfo->inst_id); + seq_printf(m, " evt_queue: %d\n", sinfo->evt_idx); + + unit++; + } + + return 0; +} + +static int bkn_proc_debug_open(struct inode * inode, struct file * file) +{ + return single_open(file, bkn_proc_debug_show, NULL); +} + +struct file_operations bkn_proc_debug_file_ops = { + owner: THIS_MODULE, + open: bkn_proc_debug_open, + read: seq_read, + llseek: seq_lseek, + write: bkn_proc_debug_write, + release: single_release, +}; + +/* + * Device Statistics Proc Entry + */ +static int +bkn_proc_stats_show(struct seq_file *m, void *v) +{ + int unit = 0; + struct list_head *list, *flist; + bkn_switch_info_t *sinfo; + bkn_filter_t *filter; + int chan; + + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + + seq_printf(m, "Device stats (unit %d):\n", unit); + seq_printf(m, " Interrupts %10u\n", sinfo->interrupts); + seq_printf(m, " Tx packets %10u\n", sinfo->tx.pkts); + for (chan = 0; chan < sinfo->rx_chans; chan++) { + seq_printf(m, " Rx%d packets %10u\n", chan, sinfo->rx[chan].pkts); + } + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (sinfo->interrupts == 0) { + /* Avoid divide-by-zero */ + seq_printf(m, " Rx%d pkts/intr -\n", chan); + } else { + seq_printf(m, " Rx%d pkts/intr %8u\n", + chan, sinfo->rx[chan].pkts / sinfo->interrupts); + } + } + seq_printf(m, " Timer runs %10u\n", sinfo->timer_runs); + seq_printf(m, " NAPI reruns %10u\n", sinfo->napi_not_done); + + list_for_each(flist, &sinfo->rxpf_list) { + filter = (bkn_filter_t *)flist; + + seq_printf(m, " Filter %d stats:\n", filter->kf.id); + seq_printf(m, " Hits %10lu\n", filter->hits); + } + + unit++; + } + return 0; +} + +static int bkn_proc_stats_open(struct inode * inode, struct file * file) +{ + return single_open(file, bkn_proc_stats_show, NULL); +} + +/* + * Device Statistics Proc Write Entry + * + * Syntax: + * [:]clear[=all] + * + * Where corresponds to the debug module parameter. + * + * Examples: + * clear + * 0:clear=all + */ +static ssize_t +bkn_proc_stats_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + bkn_switch_info_t *sinfo; + struct list_head *flist; + bkn_filter_t *filter; + char debug_str[40]; + char *ptr; + int unit; + int clear_mask; + int chan; + + if (count > sizeof(debug_str)) { + count = sizeof(debug_str) - 1; + debug_str[count] = '\0'; + } + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + unit = simple_strtol(debug_str, NULL, 10); + sinfo = bkn_sinfo_from_unit(unit); + if (sinfo == NULL) { + gprintk("Warning: unknown unit: %d\n", unit); + return count; + } + + clear_mask = 0; + if ((ptr = strstr(debug_str, "clear=")) != NULL) { + ptr += 6; + if (strncmp(ptr, "all", 3) == 0) { + clear_mask = ~0; + } + } else if ((ptr = strstr(debug_str, "clear")) != NULL) { + clear_mask = ~0; + } else { + gprintk("Warning: unknown configuration setting\n"); + } + + if (clear_mask) { + sinfo->tx.pkts = 0; + for (chan = 0; chan < sinfo->rx_chans; chan++) { + sinfo->rx[chan].pkts = 0; + } + sinfo->interrupts = 0; + sinfo->timer_runs = 0; + sinfo->napi_not_done = 0; + list_for_each(flist, &sinfo->rxpf_list) { + filter = (bkn_filter_t *)flist; + filter->hits = 0; + } + } + + return count; +} + +struct file_operations bkn_proc_stats_file_ops = { + owner: THIS_MODULE, + open: bkn_proc_stats_open, + read: seq_read, + llseek: seq_lseek, + write: bkn_proc_stats_write, + release: single_release, +}; + +/* + * Device Debug Statistics Proc Entry + */ +static int +bkn_proc_dstats_show(struct seq_file *m, void *v) +{ + int unit = 0; + struct list_head *list; + bkn_switch_info_t *sinfo; + int chan; + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + + seq_printf(m, "Device debug stats (unit %d):\n", unit); + seq_printf(m, " Tx drop no skb %10u\n", + sinfo->tx.pkts_d_no_skb); + seq_printf(m, " Tx drop rcpu encap %10u\n", + sinfo->tx.pkts_d_rcpu_encap); + seq_printf(m, " Tx drop rcpu sig %10u\n", + sinfo->tx.pkts_d_rcpu_sig); + seq_printf(m, " Tx drop rcpu meta %10u\n", + sinfo->tx.pkts_d_rcpu_meta); + seq_printf(m, " Tx drop pad failed %10u\n", + sinfo->tx.pkts_d_pad_fail); + seq_printf(m, " Tx drop no resource %10u\n", + sinfo->tx.pkts_d_dma_resrc); + seq_printf(m, " Tx drop callback %10u\n", + sinfo->tx.pkts_d_callback); + seq_printf(m, " Tx drop no link %10u\n", + sinfo->tx.pkts_d_no_link); + seq_printf(m, " Tx drop oversized %10u\n", + sinfo->tx.pkts_d_over_limit); + seq_printf(m, " Tx suspends %10u\n", + sinfo->tx.suspends); + for (chan = 0; chan < sinfo->rx_chans; chan++) { + seq_printf(m, " Rx%d filter to api %10u\n", + chan, sinfo->rx[chan].pkts_f_api); + seq_printf(m, " Rx%d filter to netif %10u\n", + chan, sinfo->rx[chan].pkts_f_netif); + seq_printf(m, " Rx%d mirror to api %10u\n", + chan, sinfo->rx[chan].pkts_m_api); + seq_printf(m, " Rx%d mirror to netif %10u\n", + chan, sinfo->rx[chan].pkts_m_netif); + seq_printf(m, " Rx%d drop no skb %10u\n", + chan, sinfo->rx[chan].pkts_d_no_skb); + seq_printf(m, " Rx%d drop no match %10u\n", + chan, sinfo->rx[chan].pkts_d_no_match); + seq_printf(m, " Rx%d drop unkn netif %10u\n", + chan, sinfo->rx[chan].pkts_d_unkn_netif); + seq_printf(m, " Rx%d drop unkn dest %10u\n", + chan, sinfo->rx[chan].pkts_d_unkn_dest); + seq_printf(m, " Rx%d drop callback %10u\n", + chan, sinfo->rx[chan].pkts_d_callback); + seq_printf(m, " Rx%d drop no link %10u\n", + chan, sinfo->rx[chan].pkts_d_no_link); + seq_printf(m, " Rx%d sync error %10u\n", + chan, sinfo->rx[chan].sync_err); + seq_printf(m, " Rx%d sync retry %10u\n", + chan, sinfo->rx[chan].sync_retry); + seq_printf(m, " Rx%d sync maxloop %10u\n", + chan, sinfo->rx[chan].sync_maxloop); + seq_printf(m, " Rx%d drop no buffer %10u\n", + chan, sinfo->rx[chan].pkts_d_no_api_buf); + } + unit++; + } + return 0; +} + +static int bkn_proc_dstats_open(struct inode * inode, struct file * file) +{ + return single_open(file, bkn_proc_dstats_show, NULL); +} + +/* + * Device Debug Statistics Proc Write Entry + * + * Syntax: + * [:]clear[=all|tx|rx[]] + * + * Where corresponds to the debug module parameter. + * + * Examples: + * clear + * 0:clear=rx1 + */ +static ssize_t +bkn_proc_dstats_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + bkn_switch_info_t *sinfo; + char debug_str[40]; + char *ptr; + int unit; + int clear_mask; + int chan; + + if (count > sizeof(debug_str)) { + count = sizeof(debug_str) - 1; + debug_str[count] = '\0'; + } + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + unit = simple_strtol(debug_str, NULL, 10); + sinfo = bkn_sinfo_from_unit(unit); + if (sinfo == NULL) { + gprintk("Warning: unknown unit: %d\n", unit); + return count; + } + + clear_mask = 0; + if ((ptr = strstr(debug_str, "clear=")) != NULL) { + ptr += 6; + if (strncmp(ptr, "all", 3) == 0) { + clear_mask = ~0; + } else if (strncmp(ptr, "dev", 3) == 0) { + clear_mask = 0x20; + } else if (strncmp(ptr, "tx", 2) == 0) { + clear_mask = 0x10; + } else if (strncmp(ptr, "rx0", 3) == 0) { + clear_mask = (1 << 0); + } else if (strncmp(ptr, "rx1", 3) == 0) { + clear_mask = (1 << 1); + } else if (strncmp(ptr, "rx", 2) == 0) { + clear_mask = 0xf; + } + } else if ((ptr = strstr(debug_str, "clear")) != NULL) { + clear_mask = ~0; + } else { + gprintk("Warning: unknown configuration setting\n"); + } + + /* Tx counters */ + if (clear_mask & 0x10) { + sinfo->tx.pkts_d_no_skb = 0; + sinfo->tx.pkts_d_rcpu_encap = 0; + sinfo->tx.pkts_d_rcpu_sig = 0; + sinfo->tx.pkts_d_rcpu_meta = 0; + sinfo->tx.pkts_d_pad_fail = 0; + sinfo->tx.pkts_d_over_limit = 0; + sinfo->tx.pkts_d_dma_resrc = 0; + sinfo->tx.suspends = 0; + } + /* Rx counters */ + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (clear_mask & (1 << chan)) { + sinfo->rx[chan].pkts_f_api = 0; + sinfo->rx[chan].pkts_f_netif = 0; + sinfo->rx[chan].pkts_m_api = 0; + sinfo->rx[chan].pkts_m_netif = 0; + sinfo->rx[chan].pkts_d_no_skb = 0; + sinfo->rx[chan].pkts_d_no_match = 0; + sinfo->rx[chan].pkts_d_unkn_netif = 0; + sinfo->rx[chan].pkts_d_unkn_dest = 0; + sinfo->rx[chan].pkts_d_no_api_buf = 0; + sinfo->rx[chan].sync_err = 0; + sinfo->rx[chan].sync_retry = 0; + sinfo->rx[chan].sync_maxloop = 0; + } + } + + return count; +} + +struct file_operations bkn_proc_dstats_file_ops = { + owner: THIS_MODULE, + open: bkn_proc_dstats_open, + read: seq_read, + llseek: seq_lseek, + write: bkn_proc_dstats_write, + release: single_release, +}; + +static int +bkn_proc_init(void) +{ + struct proc_dir_entry *entry; + + PROC_CREATE(entry, "link", 0666, bkn_proc_root, &bkn_proc_link_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "rate", 0666, bkn_proc_root, &bkn_proc_rate_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "dma", 0, bkn_proc_root, &bkn_seq_dma_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "debug", 0666, bkn_proc_root, &bkn_proc_debug_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "stats", 0666, bkn_proc_root, &bkn_proc_stats_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "dstats", 0666, bkn_proc_root, &bkn_proc_dstats_file_ops); + if (entry == NULL) { + return -1; + } + + return 0; +} + +static int +bkn_proc_cleanup(void) +{ + remove_proc_entry("link", bkn_proc_root); + remove_proc_entry("rate", bkn_proc_root); + remove_proc_entry("dma", bkn_proc_root); + remove_proc_entry("debug", bkn_proc_root); + remove_proc_entry("stats", bkn_proc_root); + remove_proc_entry("dstats", bkn_proc_root); + return 0; +} + +/* + * Generic module functions + */ + +static int +_pprint(struct seq_file *m) +{ + pprintf(m, "Broadcom BCM KNET Linux Network Driver\n"); + + return 0; +} + +static int +bkn_knet_dma_info(kcom_msg_dma_info_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_dcb_chain_t *dcb_chain, *dcb_chain_end; + unsigned long flags; + int chan; + uint64_t dcb_dma; + int woffset; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + dcb_chain = kmalloc(sizeof(*dcb_chain), GFP_KERNEL); + if (dcb_chain == NULL) { + gprintk("Fatal error: No memory for dcb_chain\n"); + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + memset(dcb_chain, 0, sizeof(*dcb_chain)); + dcb_chain->dcb_cnt = kmsg->dma_info.cnt; + dcb_chain->dcb_dma = kmsg->dma_info.data.dcb_start; + dcb_chain->dcb_mem = kernel_bde->p2l(sinfo->dev_no, + (sal_paddr_t)dcb_chain->dcb_dma); + + if (kmsg->dma_info.type == KCOM_DMA_INFO_T_TX_DCB) { + spin_lock_irqsave(&sinfo->lock, flags); + + /* Hold back packets from kernel */ + bkn_suspend_tx(sinfo); + + list_add_tail(&dcb_chain->list, &sinfo->tx.api_dcb_list); + + /* Handle for Continuous DMA mode */ + if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize + 1; + if (sinfo->cmic_type == 'x') { + woffset += 1; + } + if ((dcb_chain->dcb_mem[woffset] & ((1 << 18) | (1 << 16))) != 0x50000) { + gprintk("Not suitable API DCB chain for Continuous DMA mode\n"); + list_del(&dcb_chain->list); + kfree(dcb_chain); + kmsg->hdr.status = KCOM_E_PARAM; + spin_unlock_irqrestore(&sinfo->lock, flags); + return sizeof(kcom_msg_hdr_t); + } + dcb_chain_end = sinfo->tx.api_dcb_chain_end; + if (dcb_chain_end != NULL) { + /* Stitch this chain */ + woffset = (dcb_chain_end->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_chain_end->dcb_mem[woffset] = dcb_chain->dcb_dma; + if (sinfo->cmic_type == 'x') { + dcb_chain_end->dcb_mem[woffset + 1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32); + } + MEMORY_BARRIER; + } + sinfo->tx.api_dcb_chain_end = dcb_chain; + if (sinfo->tx.api_active) { + /* Set new halt location */ + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t); + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, dcb_dma); + } + } + + if (sinfo->tx.free == MAX_TX_DCBS && + !sinfo->tx.api_active && + !sinfo->basedev_suspended) { + bkn_api_tx(sinfo); + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + } else if (kmsg->dma_info.type == KCOM_DMA_INFO_T_RX_DCB) { + spin_lock_irqsave(&sinfo->lock, flags); + + chan = kmsg->dma_info.chan - 1; + if ((chan < 0) || (chan > sinfo->rx_chans)) { + gprintk("Invalid RX DMA channel specified: %d\n", + kmsg->dma_info.chan); + kmsg->hdr.status = KCOM_E_PARAM; + spin_unlock_irqrestore(&sinfo->lock, flags); + return sizeof(kcom_msg_hdr_t); + } + + list_add_tail(&dcb_chain->list, &sinfo->rx[chan].api_dcb_list); + + /* Handle for Continuous DMA mode */ + if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) { + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize + 1; + if (sinfo->cmic_type == 'x') { + woffset += 1; + } + if ((dcb_chain->dcb_mem[woffset] & ((1 << 18) | (1 << 16))) != 0x50000) { + gprintk("Not suitable API DCB chain for Continuous DMA mode\n"); + list_del(&dcb_chain->list); + kfree(dcb_chain); + kmsg->hdr.status = KCOM_E_PARAM; + spin_unlock_irqrestore(&sinfo->lock, flags); + return sizeof(kcom_msg_hdr_t); + } + dcb_chain_end = sinfo->rx[chan].api_dcb_chain_end; + if (dcb_chain_end != NULL) { + /* Stitch this chain */ + woffset = (dcb_chain_end->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_chain_end->dcb_mem[woffset] = dcb_chain->dcb_dma; + if (sinfo->cmic_type == 'x') { + dcb_chain_end->dcb_mem[woffset + 1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32); + } + MEMORY_BARRIER; + } + sinfo->rx[chan].api_dcb_chain_end = dcb_chain; + if (!sinfo->rx[chan].use_rx_skb) { + /* Set new halt location */ + woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize; + dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t); + /* DMA run to the new halt location */ + bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, dcb_dma); + } + } + + if (sinfo->rx[chan].api_active == 0) { + bkn_api_rx_restart(sinfo, chan); + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + } else { + DBG_DCB(("Unknown DCB_INFO type (%d).\n", kmsg->dma_info.type)); + kfree(dcb_chain); + kmsg->hdr.status = KCOM_E_PARAM; + } + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_create_inst(uint32 inst_id) +{ + bkn_switch_info_t *sinfo; + bkn_evt_resource_t *evt; + unsigned long flags; + int i, evt_idx = -1; + + /* multiple instance mode */ + for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) { + evt = &_bkn_evt[i]; + if (evt->inst_id == inst_id) { + evt_idx = i; + DBG_INST(("%s evt_idx %d inst_id 0x%x\n",__FUNCTION__, i, inst_id)); + break; + } + if ((_bkn_multi_inst == 0) || (evt->inst_id == INVALID_INSTANCE_ID)) { + _bkn_multi_inst ++; + evt_idx = i; + init_waitqueue_head(&evt->evt_wq); + evt->inst_id = inst_id; + DBG_INST(("%s evt_idx %d inst_id 0x%x\n",__FUNCTION__, i, inst_id)); + break; + } + } + + if (evt_idx == -1) { + DBG_WARN(("Run out the event queue resource !\n")); + return -1; + } + for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) { + if (lkbde_is_dev_managed_by_instance(i, inst_id)) { + sinfo = bkn_sinfo_from_unit(i); + spin_lock_irqsave(&sinfo->lock, flags); + sinfo->evt_idx = evt_idx; + spin_unlock_irqrestore(&sinfo->lock, flags); + DBG_INST(("%s d(%d) evt_idx %d \n",__FUNCTION__, i, evt_idx)); + } + } + return 0; +} + +/* + * Device reprobe driven by application to check if new device is probed or + * existed device is changed after inserting KNET module. + */ +static int +bkn_knet_dev_reprobe(void) +{ + bkn_switch_info_t *sinfo; + int i; + + for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) { + sinfo = bkn_sinfo_from_unit(i); + if (sinfo == NULL) { + /* New device found after re-probe. */ + if (bkn_knet_dev_init(i) < 0) { + return -1; + } + } else { + /* Existed device reinit after re-probe. */ + if (bkn_knet_dev_reinit(i) < 0) { + return -1; + } + } + } + return 0; +} + +/* Assign the inst_id and evt_idx */ +static int +bkn_knet_dev_inst_set(kcom_msg_reprobe_t *kmsg) +{ + bkn_switch_info_t *sinfo; + int d = kmsg->hdr.unit; + uint32 inst = INVALID_INSTANCE_ID; + unsigned long flags; + struct list_head *list; + + sinfo = bkn_sinfo_from_unit(d); +#ifdef BCM_INSTANCE_SUPPORT + lkbde_dev_instid_get(d, &inst); +#else + inst = INVALID_INSTANCE_ID; +#endif + DBG_INST(("%s sinfo->inst_id %d d %d inst %d\n",__FUNCTION__,sinfo->inst_id, d, inst)); + + spin_lock_irqsave(&sinfo->lock, flags); + if (sinfo->inst_id != inst) { + /* Instance database changed, reinit the inst_id */ + sinfo->inst_id = INVALID_INSTANCE_ID; + sinfo->evt_idx = -1; + } + spin_unlock_irqrestore(&sinfo->lock, flags); + + if (inst != INVALID_INSTANCE_ID) { + if (sinfo->inst_id == INVALID_INSTANCE_ID) { + if (bkn_create_inst(inst) != 0) { + return -1; + } + } + spin_lock_irqsave(&sinfo->lock, flags); + sinfo->inst_id = inst; + spin_unlock_irqrestore(&sinfo->lock, flags); + } else { + /* legacy mode */ + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + spin_lock_irqsave(&sinfo->lock, flags); + sinfo->evt_idx = 0; + sinfo->inst_id = INVALID_INSTANCE_ID; + spin_unlock_irqrestore(&sinfo->lock, flags); + } + } + return 0; +} + +static int +bkn_knet_version(kcom_msg_version_t *kmsg, int len) +{ + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + kmsg->version = KCOM_VERSION; + kmsg->netif_max = KCOM_NETIF_MAX; + kmsg->filter_max = KCOM_FILTER_MAX; + + return sizeof(kcom_msg_version_t); +} + +static int +bkn_knet_hw_reset(kcom_msg_hw_reset_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + unsigned long flags; + int chan; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + if (kmsg->channels == 0) { + /* Clean all if no channels specified */ + bkn_dma_abort(sinfo); + bkn_clean_dcbs(sinfo); + skb_queue_purge(&sinfo->tx_ptp_queue); + } else { + if (kmsg->channels & (1 << XGS_DMA_TX_CHAN)) { + bkn_dma_abort_tx(sinfo); + bkn_clean_tx_dcbs(sinfo); + skb_queue_purge(&sinfo->tx_ptp_queue); + } + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (kmsg->channels & (1 << (XGS_DMA_RX_CHAN + chan))) { + bkn_dma_abort_rx(sinfo, chan); + bkn_clean_rx_dcbs(sinfo, chan); + } + } + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_knet_hw_init(kcom_msg_hw_init_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + uint32_t dev_type; + unsigned long flags; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + DBG_DCB(("DCB size %d, type %d\n", kmsg->dcb_size, kmsg->dcb_type)); + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + sinfo->cmic_type = kmsg->cmic_type; + sinfo->dcb_type = kmsg->dcb_type; + sinfo->dcb_wsize = BYTES2WORDS(kmsg->dcb_size); + sinfo->pkt_hdr_size = kmsg->pkt_hdr_size; + sinfo->dma_hi = kmsg->dma_hi; + sinfo->rx_chans = sinfo->cmic_type == 'x' ? NUM_CMICX_RX_CHAN : NUM_CMICM_RX_CHAN; + if (sinfo->rx_chans > NUM_RX_CHAN) { + sinfo->rx_chans = NUM_RX_CHAN; + } + + DBG_DUNE(("CMIC:%c DCB:%d WSIZE:%d DMA HI: 0x%08x HDR size: %d\n", + sinfo->cmic_type, sinfo->dcb_type, sinfo->dcb_wsize, + sinfo->dma_hi, sinfo->pkt_hdr_size)); + + /* Config Continuous DMA mode */ + sinfo->cdma_channels = kmsg->cdma_channels & ~(~0 << (sinfo->rx_chans + 1)); + + /* Ensure 32-bit PCI DMA is mapped properly on 64-bit platforms */ + dev_type = kernel_bde->get_dev_type(sinfo->dev_no); + if (dev_type & BDE_PCI_DEV_TYPE && sinfo->cmic_type != 'x') { + if (pci_set_dma_mask(sinfo->pdev, 0xffffffff)) { + spin_unlock_irqrestore(&sinfo->lock, flags); + gprintk("No suitable DMA available for SKBs\n"); + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + } + + /* First time called we need to allocate DCBs */ + if (sinfo->dcb_mem == NULL) { + if (bkn_alloc_dcbs(sinfo) < 0) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + } + + if (device_is_sand(sinfo)) { + int idx = 0; + /* Information to parser Dune system headers */ + sinfo->ftmh_lb_key_ext_size = kmsg->ftmh_lb_key_ext_size; + sinfo->ftmh_stacking_ext_size = kmsg->ftmh_stacking_ext_size; + sinfo->pph_base_size = kmsg->pph_base_size; + for (idx = 0; idx < 8; idx++) + { + sinfo->pph_lif_ext_size[idx] = kmsg->pph_lif_ext_size[idx]; + } + for (idx = 0; idx < 4; idx++) + { + sinfo->udh_length_type[idx] = kmsg->udh_length_type[idx]; + } + sinfo->udh_size = kmsg->udh_size; + sinfo->oamp_punt = kmsg->oamp_punted; + sinfo->no_skip_udh_check = kmsg->no_skip_udh_check; + sinfo->system_headers_mode = kmsg->system_headers_mode; + sinfo->udh_enable = kmsg->udh_enable; + } + + /* Ensure that we restart properly */ + bkn_dma_abort(sinfo); + bkn_clean_dcbs(sinfo); + + if (basedev_suspend) { + if (!netif_running(sinfo->dev)) { + sinfo->basedev_suspended = 1; + } + } + + /* Ensure all interrupts are disabled, e.g. if warmbooting */ + dev_irq_mask_set(sinfo, 0); + + /* Register interrupt handler */ + kernel_bde->interrupt_connect(sinfo->dev_no | LKBDE_ISR2_DEV, + bkn_isr, sinfo); + + /* Init DCBs */ + bkn_init_dcbs(sinfo); + + bkn_dma_init(sinfo); + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_knet_detach(kcom_msg_detach_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + unsigned long flags; + bkn_evt_resource_t *evt; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + if (sinfo->evt_idx != -1) { + /* Create dummy event to unblock pending IOCTL */ + sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE; + evt = &_bkn_evt[sinfo->evt_idx]; + evt->evt_wq_put++; + wake_up_interruptible(&evt->evt_wq); + } + spin_unlock_irqrestore(&sinfo->lock, flags); + + /* Ensure that we return a valid unit number */ + kmsg->hdr.unit = sinfo->dev_no; + + return sizeof(kcom_msg_detach_t); +} + +static int +bkn_knet_reprobe(kcom_msg_reprobe_t *kmsg, int len) +{ + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + /* Support pci hot plug and multiple instance */ + if ((bkn_knet_dev_reprobe() < 0) || + (bkn_knet_dev_inst_set(kmsg) < 0)) { + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_reprobe_t); + } + + return sizeof(kcom_msg_reprobe_t); +} + +static int +bkn_knet_netif_create(kcom_msg_netif_create_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + struct net_device *dev; + struct list_head *list; + bkn_priv_t *priv, *lpriv; + unsigned long flags; + int found, id; + uint8_t *ma; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + switch (kmsg->netif.type) { + case KCOM_NETIF_T_VLAN: + case KCOM_NETIF_T_PORT: + case KCOM_NETIF_T_META: + break; + default: + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + ma = kmsg->netif.macaddr; + if ((ma[0] | ma[1] | ma[2] | ma[3] | ma[4] | ma[5]) == 0) { + bkn_dev_mac[5]++; + ma = bkn_dev_mac; + } + if ((dev = bkn_init_ndev(ma, kmsg->netif.name)) == NULL) { + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + priv = netdev_priv(dev); + priv->dev = dev; + priv->sinfo = sinfo; + priv->type = kmsg->netif.type; + priv->vlan = kmsg->netif.vlan; + /* System headers are prepared at BCM API for Dune headers */ + if (device_is_sand(sinfo)) { + int idx = 0; + for (idx = 0; idx < KCOM_NETIF_SYSTEM_HEADERS_SIZE_MAX; idx++) + { + priv->system_headers[idx] = kmsg->netif.system_headers[idx]; + } + priv->system_headers_size = kmsg->netif.system_headers_size; + } + if (priv->type == KCOM_NETIF_T_PORT) { + priv->port = kmsg->netif.port; + priv->phys_port = kmsg->netif.phys_port; + priv->qnum = kmsg->netif.qnum; + memset(&(priv->link_settings), 0, sizeof(struct ethtool_link_settings));; + } else { + if (device_is_sand(sinfo) && (priv->type == KCOM_NETIF_T_VLAN)) { + /* PTCH.SSPA */ + priv->port = kmsg->netif.port; + priv->qnum = kmsg->netif.qnum; + } else { + priv->port = -1; + } + } + priv->flags = kmsg->netif.flags; + priv->cb_user_data = kmsg->netif.cb_user_data; + + /* Force RCPU encapsulation if rcpu_mode */ + if (rcpu_mode) { + priv->flags |= KCOM_NETIF_F_RCPU_ENCAP; + DBG_RCPU(("RCPU auto-enabled\n")); + } + + /* Prevent (incorrect) compiler warning */ + lpriv = NULL; + + spin_lock_irqsave(&sinfo->lock, flags); + + /* + * We insert network interfaces sorted by ID. + * In case an interface is destroyed, we reuse the ID + * the next time an interface is created. + */ + found = 0; + id = 1; + list_for_each(list, &sinfo->ndev_list) { + lpriv = (bkn_priv_t *)list; + if (id < lpriv->id) { + found = 1; + break; + } + id = lpriv->id + 1; + } + priv->id = id; + if (found) { + /* Replace previously removed interface */ + list_add_tail(&priv->list, &lpriv->list); + } else { + /* No holes - add to end of list */ + list_add_tail(&priv->list, &sinfo->ndev_list); + } + + if (id < sinfo->ndev_max) { + DBG_NDEV(("Add netif ID %d to table\n", id)); + sinfo->ndevs[id] = dev; + } else { + int ndev_max = sinfo->ndev_max + NDEVS_CHUNK; + int size = ndev_max * sizeof(struct net_device *); + void *ndevs = kmalloc(size, GFP_ATOMIC); + if (ndevs != NULL) { + DBG_NDEV(("Reallocate netif table for ID %d\n", id)); + memset(ndevs, 0, size); + if (sinfo->ndevs != NULL) { + size = sinfo->ndev_max * sizeof(struct net_device *); + memcpy(ndevs, sinfo->ndevs, size); + kfree(sinfo->ndevs); + } + sinfo->ndevs = ndevs; + sinfo->ndev_max = ndev_max; + sinfo->ndevs[id] = dev; + } + } + + + DBG_VERB(("Assigned ID %d to Ethernet device %s\n", + priv->id, dev->name)); + + kmsg->netif.id = priv->id; + memcpy(kmsg->netif.macaddr, dev->dev_addr, 6); + memcpy(kmsg->netif.name, dev->name, KCOM_NETIF_NAME_MAX - 1); + if (knet_netif_create_cb != NULL) { + int retv = knet_netif_create_cb(kmsg->hdr.unit, &(kmsg->netif), dev); + if (retv) { + gprintk("Warning: knet_netif_create_cb() returned %d for netif '%s'\n", retv, dev->name); + } + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + if (device_is_sand(sinfo)) { + int idx = 0; + for (idx = 0; idx < priv->system_headers_size; idx++) { + DBG_DUNE(("System Header[%d]: 0x%02x\n", idx, priv->system_headers[idx])); + } + } + + return sizeof(*kmsg); +} + +static int +bkn_knet_netif_destroy(kcom_msg_netif_destroy_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + struct net_device *dev; + bkn_priv_t *priv; + struct list_head *list; + unsigned long flags; + int found; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + found = 0; + list_for_each(list, &sinfo->ndev_list) { + priv = (bkn_priv_t *)list; + if (kmsg->hdr.id == priv->id) { + found = 1; + break; + } + } + + if (!found) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_NOT_FOUND; + return sizeof(kcom_msg_hdr_t); + } + + if (knet_netif_destroy_cb != NULL) { + kcom_netif_t netif; + memset(&netif, 0, sizeof(kcom_netif_t)); + netif.id = priv->id; + knet_netif_destroy_cb(kmsg->hdr.unit, &netif, priv->dev); + } + + list_del(&priv->list); + + if (priv->id < sinfo->ndev_max) { + sinfo->ndevs[priv->id] = NULL; + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + dev = priv->dev; + DBG_VERB(("Removing virtual Ethernet device %s (%d).\n", + dev->name, priv->id)); + unregister_netdev(dev); + free_netdev(dev); + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_knet_netif_list(kcom_msg_netif_list_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_priv_t *priv; + struct list_head *list; + unsigned long flags; + int idx; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + idx = 0; + list_for_each(list, &sinfo->ndev_list) { + if (idx >= KCOM_NETIF_MAX) { + DBG_WARN(("Too many network interfaces to list (max %d).\n", + KCOM_NETIF_MAX)); + break; + } + priv = (bkn_priv_t *)list; + kmsg->id[idx] = priv->id; + idx++; + } + kmsg->ifcnt = idx; + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(*kmsg) - sizeof(kmsg->id) + (idx * sizeof(kmsg->id[0])); +} + +static int +bkn_knet_netif_get(kcom_msg_netif_get_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_priv_t *priv; + unsigned long flags; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + priv = bkn_netif_lookup(sinfo, kmsg->hdr.id); + + if (priv == NULL) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_NOT_FOUND; + return sizeof(kcom_msg_hdr_t); + } + + memcpy(kmsg->netif.macaddr, priv->dev->dev_addr, 6); + memcpy(kmsg->netif.name, priv->dev->name, KCOM_NETIF_NAME_MAX - 1); + kmsg->netif.vlan = priv->vlan; + kmsg->netif.type = priv->type; + kmsg->netif.id = priv->id; + kmsg->netif.flags = priv->flags; + kmsg->netif.cb_user_data = priv->cb_user_data; + + if (priv->port < 0) { + kmsg->netif.port = 0; + } else { + kmsg->netif.port = priv->port; + } + kmsg->netif.qnum = priv->qnum; + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(*kmsg); +} + +static int +bkn_knet_filter_create(kcom_msg_filter_create_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + struct list_head *list; + bkn_filter_t *filter, *lfilter; + unsigned long flags; + int found, id; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + switch (kmsg->filter.type) { + case KCOM_FILTER_T_RX_PKT: + break; + default: + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + /* + * Find available ID + */ + found = 1; + id = 0; + while (found && ++id < KCOM_FILTER_MAX) { + found = 0; + list_for_each(list, &sinfo->rxpf_list) { + lfilter = (bkn_filter_t *)list; + if (id == lfilter->kf.id) { + found = 1; + break; + } + } + } + if (found) { + /* Too many filters */ + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + filter = kmalloc(sizeof(*filter), GFP_ATOMIC); + if (filter == NULL) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + memset(filter, 0, sizeof(*filter)); + memcpy(&filter->kf, &kmsg->filter, sizeof(filter->kf)); + filter->kf.id = id; + + /* Add according to priority */ + found = 0; + list_for_each(list, &sinfo->rxpf_list) { + lfilter = (bkn_filter_t *)list; + if (filter->kf.priority < lfilter->kf.priority) { + list_add_tail(&filter->list, &lfilter->list); + found = 1; + break; + } + } + if (!found) { + list_add_tail(&filter->list, &sinfo->rxpf_list); + } + + kmsg->filter.id = filter->kf.id; + + spin_unlock_irqrestore(&sinfo->lock, flags); + + DBG_VERB(("Created filter ID %d (%s).\n", + filter->kf.id, filter->kf.desc)); + if (device_is_sand(sinfo)) { + int idx, wsize; + wsize = BYTES2WORDS(filter->kf.oob_data_size + filter->kf.pkt_data_size); + DBG_DUNE(("Filter: oob_data_size = %d pkt_data_size=%d wsize %d\n", filter->kf.oob_data_size, filter->kf.pkt_data_size, wsize)); + for (idx = 0; idx < wsize; idx++) + { + DBG_DUNE(("OOB[%d]: 0x%08x [0x%08x]\n", idx, filter->kf.data.w[idx], filter->kf.mask.w[idx])); + } + DBG_DUNE(("DNX system headers parameters:LB_KEY_EXT %d, STK_EXT %d, PPH_BASE %d, LIF_EXT %d %d %d, UDH_ENA %d, %d %d %d %d\n", + sinfo->ftmh_lb_key_ext_size, sinfo->ftmh_stacking_ext_size, sinfo->pph_base_size, + sinfo->pph_lif_ext_size[1],sinfo->pph_lif_ext_size[2], sinfo->pph_lif_ext_size[3], + sinfo->udh_enable, sinfo->udh_length_type[0], sinfo->udh_length_type[1], sinfo->udh_length_type[2], sinfo->udh_length_type[3])); + } + return len; +} + +static int +bkn_knet_filter_destroy(kcom_msg_filter_destroy_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_filter_t *filter; + struct list_head *list; + unsigned long flags; + int found; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + found = 0; + list_for_each(list, &sinfo->rxpf_list) { + filter = (bkn_filter_t *)list; + if (kmsg->hdr.id == filter->kf.id) { + found = 1; + break; + } + } + + if (!found) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_NOT_FOUND; + return sizeof(kcom_msg_hdr_t); + } + + list_del(&filter->list); + + spin_unlock_irqrestore(&sinfo->lock, flags); + + DBG_VERB(("Removing filter ID %d.\n", filter->kf.id)); + kfree(filter); + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_knet_filter_list(kcom_msg_filter_list_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_filter_t *filter; + struct list_head *list; + unsigned long flags; + int idx; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + idx = 0; + list_for_each(list, &sinfo->rxpf_list) { + if (idx >= KCOM_FILTER_MAX) { + DBG_WARN(("Too many filters to list (max %d).\n", + KCOM_FILTER_MAX)); + break; + } + filter = (bkn_filter_t *)list; + kmsg->id[idx] = filter->kf.id; + idx++; + } + kmsg->fcnt = idx; + + spin_unlock_irqrestore(&sinfo->lock, flags); + return sizeof(*kmsg) - sizeof(kmsg->id) + (idx * sizeof(kmsg->id[0])); +} + +static int +bkn_knet_filter_get(kcom_msg_filter_get_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_filter_t *filter; + struct list_head *list; + unsigned long flags; + int found; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + found = 0; + list_for_each(list, &sinfo->rxpf_list) { + filter = (bkn_filter_t *)list; + if (kmsg->hdr.id == filter->kf.id) { + found = 1; + break; + } + } + + if (!found) { + spin_unlock_irqrestore(&sinfo->lock, flags); + kmsg->hdr.status = KCOM_E_NOT_FOUND; + return sizeof(kcom_msg_hdr_t); + } + + memcpy(&kmsg->filter, &filter->kf, sizeof(kmsg->filter)); + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(*kmsg); +} + +static int +bkn_knet_dbg_pkt_set(kcom_msg_dbg_pkt_set_t *kmsg, int len) +{ + dbg_pkt_enable = kmsg->enable; + return sizeof(kcom_msg_dbg_pkt_set_t); +} + +static int +bkn_knet_dbg_pkt_get(kcom_msg_dbg_pkt_get_t *kmsg, int len) +{ + kmsg->value = dbg_pkt_enable; + return sizeof(kcom_msg_dbg_pkt_get_t); +} + +static int +bkn_knet_wb_cleanup(kcom_msg_wb_cleanup_t *kmsg, int len) +{ + bkn_switch_info_t *sinfo; + bkn_dcb_chain_t *dcb_chain; + unsigned long flags; + int chan; + + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + kmsg->hdr.status = KCOM_E_PARAM; + return sizeof(kcom_msg_hdr_t); + } + + spin_lock_irqsave(&sinfo->lock, flags); + + for (chan = 0; chan < sinfo->rx_chans; chan++) { + if (sinfo->rx[chan].api_dcb_chain) { + DBG_DCB_RX(("Freeing active Rx%d DCB chain.\n", chan)); + kfree(sinfo->rx[chan].api_dcb_chain); + sinfo->rx[chan].api_dcb_chain = NULL; + } + while (!list_empty(&sinfo->rx[chan].api_dcb_list)) { + dcb_chain = list_entry(sinfo->rx[chan].api_dcb_list.next, + bkn_dcb_chain_t, list); + list_del(&dcb_chain->list); + DBG_DCB_RX(("Freeing Rx%d DCB chain.\n", chan)); + kfree(dcb_chain); + } + sinfo->rx[chan].api_dcb_chain_end = NULL; + sinfo->rx[chan].api_active = 0; + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + return sizeof(kcom_msg_hdr_t); +} + +static int +bkn_handle_cmd_req(kcom_msg_t *kmsg, int len) +{ + /* Silently drop events and unrecognized message types */ + if (kmsg->hdr.type != KCOM_MSG_TYPE_CMD) { + if (kmsg->hdr.opcode == KCOM_M_STRING) { + DBG_VERB(("Debug string: '%s'\n", kmsg->string.val)); + return 0; + } + DBG_WARN(("Unsupported message (type=%d, opcode=%d)\n", + kmsg->hdr.type, kmsg->hdr.opcode)); + return 0; + } + + switch (kmsg->hdr.opcode) { + case KCOM_M_DMA_INFO: + DBG_CMD(("KCOM_M_DMA_INFO\n")); + /* Packet buffer */ + len = bkn_knet_dma_info(&kmsg->dma_info, len); + break; + case KCOM_M_VERSION: + DBG_CMD(("KCOM_M_VERSION\n")); + /* Return procotol version */ + len = bkn_knet_version(&kmsg->version, len); + break; + case KCOM_M_HW_RESET: + DBG_CMD(("KCOM_M_HW_RESET\n")); + /* Shut down DMA and release buffers */ + len = bkn_knet_hw_reset(&kmsg->hw_reset, len); + break; + case KCOM_M_HW_INIT: + DBG_CMD(("KCOM_M_HW_INIT\n")); + /* Initialize DMA */ + len = bkn_knet_hw_init(&kmsg->hw_init, len); + break; + case KCOM_M_DETACH: + DBG_CMD(("KCOM_M_DETACH\n")); + /* Detach kernel module */ + len = bkn_knet_detach(&kmsg->detach, len); + break; + case KCOM_M_REPROBE: + DBG_CMD(("KCOM_M_REPROBE\n")); + /* Reprobe device */ + len = bkn_knet_reprobe(&kmsg->reprobe, len); + break; + case KCOM_M_NETIF_CREATE: + DBG_CMD(("KCOM_M_NETIF_CREATE\n")); + /* Create network interface */ + len = bkn_knet_netif_create(&kmsg->netif_create, len); + break; + case KCOM_M_NETIF_DESTROY: + DBG_CMD(("KCOM_M_NETIF_DESTROY\n")); + /* Destroy network interface */ + len = bkn_knet_netif_destroy(&kmsg->netif_destroy, len); + break; + case KCOM_M_NETIF_LIST: + DBG_CMD(("KCOM_M_NETIF_LIST\n")); + /* Return list of IDs of installed network interfaces */ + len = bkn_knet_netif_list(&kmsg->netif_list, len); + break; + case KCOM_M_NETIF_GET: + DBG_CMD(("KCOM_M_NETIF_GET\n")); + /* Return network interface info */ + len = bkn_knet_netif_get(&kmsg->netif_get, len); + break; + case KCOM_M_FILTER_CREATE: + DBG_CMD(("KCOM_M_FILTER_CREATE\n")); + /* Create packet filter */ + len = bkn_knet_filter_create(&kmsg->filter_create, len); + break; + case KCOM_M_FILTER_DESTROY: + DBG_CMD(("KCOM_M_FILTER_DESTROY\n")); + /* Destroy packet filter */ + len = bkn_knet_filter_destroy(&kmsg->filter_destroy, len); + break; + case KCOM_M_FILTER_LIST: + DBG_CMD(("KCOM_M_FILTER_LIST\n")); + /* Return list of IDs of installed packet filters */ + len = bkn_knet_filter_list(&kmsg->filter_list, len); + break; + case KCOM_M_FILTER_GET: + DBG_CMD(("KCOM_M_FILTER_GET\n")); + /* Return packet filter info */ + len = bkn_knet_filter_get(&kmsg->filter_get, len); + break; + case KCOM_M_DBGPKT_SET: + DBG_CMD(("KCOM_M_DBGPKT_SET\n")); + /* Set debugging packet function */ + len = bkn_knet_dbg_pkt_set(&kmsg->dbg_pkt_set, len); + break; + case KCOM_M_DBGPKT_GET: + DBG_CMD(("KCOM_M_DBGPKT_GET\n")); + /* Get debugging packet function info */ + len = bkn_knet_dbg_pkt_get(&kmsg->dbg_pkt_get, len); + break; + case KCOM_M_WB_CLEANUP: + DBG_CMD(("KCOM_M_WB_CLEANUP\n")); + /* Clean up for warmbooting */ + len = bkn_knet_wb_cleanup(&kmsg->wb_cleanup, len); + break; + case KCOM_M_CLOCK_CMD: + /* PHC clock control*/ + if (knet_hw_tstamp_ioctl_cmd_cb) { + bkn_switch_info_t *sinfo; + sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit); + if (sinfo == NULL) { + /* The device is not probed or initialized yet.*/ + return 0; + } + DBG_CMD(("KCOM_M_CLOCK_CMD\n")); + len = knet_hw_tstamp_ioctl_cmd_cb(&kmsg->clock_cmd, len, sinfo->dcb_type); + } else { + DBG_WARN(("Unsupported command (type=%d, opcode=%d)\n", + kmsg->hdr.type, kmsg->hdr.opcode)); + kmsg->hdr.opcode = 0; + len = sizeof(kcom_msg_hdr_t); + } + break; + default: + DBG_WARN(("Unsupported command (type=%d, opcode=%d)\n", + kmsg->hdr.type, kmsg->hdr.opcode)); + kmsg->hdr.opcode = 0; + len = sizeof(kcom_msg_hdr_t); + break; + } + return len; +} + +static int +bkn_get_next_dma_event(kcom_msg_dma_info_t *kmsg) +{ + static int last_dev_no = 0; + bkn_switch_info_t *sinfo; + unsigned long flags; + int dev_no, dev_evt; + bkn_evt_resource_t *evt; + + dev_evt = kmsg->hdr.unit; + sinfo = bkn_sinfo_from_unit(dev_evt); + if (sinfo == NULL) { + /* The device is not probed or initialized yet.*/ + return 0; + } + if (sinfo->evt_idx == -1) { + /* Event queue is not ready yet */ + return 0; + } + + DBG_INST(("%s dev %d evt_idx %d\n",__FUNCTION__, dev_evt, sinfo->evt_idx)); + dev_no = last_dev_no; + while (1) { + dev_no++; + sinfo = bkn_sinfo_from_unit(dev_no); + if (sinfo == NULL) { + dev_no = 0; + sinfo = bkn_sinfo_from_unit(dev_no); + } + + if (sinfo && (sinfo->inst_id != INVALID_INSTANCE_ID) && + (!lkbde_is_dev_managed_by_instance(dev_evt, sinfo->inst_id))) { + DBG_INST((" %s skip dev(%d)\n",__FUNCTION__,dev_no)); + continue; + } + + if (sinfo->evt_idx == -1) { + /* Event queue is not ready yet */ + continue; + } + if (sinfo && sinfo->dma_events) { + DBG_EVT(("Next DMA events (0x%08x)\n", sinfo->dma_events)); + kmsg->hdr.unit = sinfo->dev_no; + + spin_lock_irqsave(&sinfo->lock, flags); + kmsg->dma_info.flags = sinfo->dma_events; + sinfo->dma_events = 0; + spin_unlock_irqrestore(&sinfo->lock, flags); + + last_dev_no = dev_no; + break; + } + + if ((dev_no == last_dev_no) || + (_bkn_multi_inst && (dev_no == dev_evt))) { + evt = &_bkn_evt[sinfo->evt_idx]; + DBG_INST(("dev_no %d dev_evt %d wait queue index %d\n", + dev_no, dev_evt, sinfo->evt_idx)); + wait_event_interruptible(evt->evt_wq, + evt->evt_wq_get != evt->evt_wq_put); + DBG_VERB(("Event thread wakeup\n")); + + /* Thread interrupted */ + if (signal_pending(current)) { + return 0; + } + + evt->evt_wq_get = evt->evt_wq_put; + } + } + return sizeof(*kmsg); +} + +static int +_cleanup(void) +{ + struct list_head *list; + struct net_device *dev; + bkn_filter_t *filter; + bkn_priv_t *priv; + bkn_switch_info_t *sinfo; + unsigned long flags; + + /* Inidicate that we are shutting down */ + module_initialized = 0; + + bkn_proc_cleanup(); + remove_proc_entry("bcm/knet", NULL); + remove_proc_entry("bcm", NULL); + + list_for_each(list, &_sinfo_list) { + sinfo = (bkn_switch_info_t *)list; + + del_timer_sync(&sinfo->timer); + del_timer_sync(&sinfo->rxtick); + + spin_lock_irqsave(&sinfo->lock, flags); + if (DEV_IS_CMIC(sinfo)) { + bkn_dma_abort(sinfo); + dev_irq_mask_set(sinfo, 0); + } + spin_unlock_irqrestore(&sinfo->lock, flags); + + DBG_IRQ(("Unregister ISR.\n")); + kernel_bde->interrupt_disconnect(sinfo->dev_no | LKBDE_ISR2_DEV); + + if (use_napi) { + while (sinfo->napi_poll_mode) { + bkn_sleep(1); + } + } + + spin_lock_irqsave(&sinfo->lock, flags); + bkn_clean_dcbs(sinfo); + skb_queue_purge(&sinfo->tx_ptp_queue); + spin_unlock_irqrestore(&sinfo->lock, flags); + } + + /* Destroy all switch devices */ + while (!list_empty(&_sinfo_list)) { + sinfo = list_entry(_sinfo_list.next, bkn_switch_info_t, list); + + /* Destroy all associated Rx packet filters */ + while (!list_empty(&sinfo->rxpf_list)) { + filter = list_entry(sinfo->rxpf_list.next, bkn_filter_t, list); + list_del(&filter->list); + DBG_VERB(("Removing filter ID %d.\n", filter->kf.id)); + kfree(filter); + } + + /* Destroy all associated virtual net devices */ + while (!list_empty(&sinfo->ndev_list)) { + priv = list_entry(sinfo->ndev_list.next, bkn_priv_t, list); + list_del(&priv->list); + dev = priv->dev; + DBG_VERB(("Removing virtual Ethernet device %s.\n", dev->name)); + unregister_netdev(dev); + free_netdev(dev); + } + if (sinfo->ndevs != NULL) { + kfree(sinfo->ndevs); + } + + /* Destroy base net device */ + if (sinfo->dev) { + DBG_VERB(("Removing Ethernet device %s.\n", sinfo->dev->name)); + unregister_netdev(sinfo->dev); + free_netdev(sinfo->dev); + } + + DBG_VERB(("Removing switch device.\n")); + bkn_destroy_sinfo(sinfo); + } + + return 0; +} + +static int +bkn_knet_dev_reinit(int d) +{ + bkn_switch_info_t *sinfo; + uint32 dev_state; + unsigned long flags; + + if (lkbde_dev_state_get(d, &dev_state) < 0) { + return -1; + } + DBG_VERB(("%s dev %d dev_state %d\n",__FUNCTION__, d, dev_state)); + if (dev_state == BDE_DEV_STATE_CHANGED) { + sinfo = bkn_sinfo_from_unit(d); + spin_lock_irqsave(&sinfo->lock, flags); + sinfo->base_addr = lkbde_get_dev_virt(d); + sinfo->dma_dev = lkbde_get_dma_dev(d); + sinfo->pdev = lkbde_get_hw_dev(d); + spin_unlock_irqrestore(&sinfo->lock, flags); + + dev_state = 0; + lkbde_dev_state_set(d, dev_state); + } + return 0; +} + +static int +bkn_knet_dev_init(int d) +{ + uint32_t dev_type; + struct net_device *dev; + bkn_switch_info_t *sinfo; + bkn_priv_t *priv; + char *bdev_name; + const ibde_dev_t *bde_dev; + + DBG_VERB(("%s dev %d\n",__FUNCTION__, d)); + /* Base network device name */ + bdev_name = "bcm%d"; + if (base_dev_name) { + if (strlen(base_dev_name) < IFNAMSIZ) { + bdev_name = base_dev_name; + } else { + DBG_WARN(("Base device name too long\n")); + } + } + + dev_type = kernel_bde->get_dev_type(d); + DBG_VERB(("Found device type 0x%x\n", dev_type)); + if ((dev_type & BDE_SWITCH_DEV_TYPE) == 0) { + DBG_WARN(("Not switch device - skipping\n")); + return 0; + } + switch (dev_type & BDE_DEV_BUS_TYPE_MASK) { + case BDE_PCI_DEV_TYPE: + case BDE_ICS_DEV_TYPE: + case BDE_AXI_DEV_TYPE: + break; + default: + DBG_WARN(("Not PCI/ICS/AXI device - skipping\n")); + return 0; + } + + if ((sinfo = bkn_create_sinfo(d)) == NULL) { + _cleanup(); + return -ENOMEM; + } + + /* Initialize the cpu_no.*/ + if (dev_type & BDE_AXI_DEV_TYPE) { + /* AXI device type implies the activated iProc iHost */ + sinfo->cpu_no = 1; + } + /* Initialize default RCPU signature */ + if ((bde_dev = kernel_bde->get_dev(d)) != NULL) { + sinfo->rcpu_sig = bde_dev->device & ~0xf; + } + /* Check for override */ + if (rcpu_signature) { + sinfo->rcpu_sig = rcpu_signature; + } + + /* Create base virtual net device */ + bkn_dev_mac[5]++; + if ((dev = bkn_init_ndev(bkn_dev_mac, bdev_name)) == NULL) { + _cleanup(); + return -ENOMEM; + } else { + sinfo->dev = dev; + priv = netdev_priv(dev); + priv->dev = dev; + priv->sinfo = sinfo; + priv->vlan = 1; + priv->port = -1; + priv->id = -1; + } + + if (use_napi) { + netif_napi_add(dev, &sinfo->napi, bkn_poll, napi_weight); + } + return 0; +} + +static int +_init(void) +{ + int idx; + int num_dev; + int rv; + bkn_evt_resource_t *evt; + + /* Connect to the kernel bde */ + if ((linux_bde_create(NULL, &kernel_bde) < 0) || kernel_bde == NULL) { + return -ENODEV; + } + + /* Randomize Lower 3 bytes of the MAC address (TESTING ONLY) */ + get_random_bytes(&bkn_dev_mac[3], 3); + + /* Check for user-supplied MAC address (recommended) */ + if (mac_addr != NULL && strlen(mac_addr) == 17) { + for (idx = 0; idx < 6; idx++) { + bkn_dev_mac[idx] = simple_strtoul(&mac_addr[idx*3], NULL, 16); + } + /* Do not allow multicast address */ + bkn_dev_mac[0] &= ~0x01; + } + + /* Optional RCPU MAC addresses */ + if (rcpu_dmac != NULL && strlen(rcpu_dmac) == 17) { + for (idx = 0; idx < 6; idx++) { + bkn_rcpu_dmac[idx] = simple_strtoul(&rcpu_dmac[idx*3], NULL, 16); + } + } + if (rcpu_smac != NULL && strlen(rcpu_smac) == 17) { + for (idx = 0; idx < 6; idx++) { + bkn_rcpu_smac[idx] = simple_strtoul(&rcpu_smac[idx*3], NULL, 16); + } + } + + /* NAPI implies that base device must be up before we can pass traffic */ + if (use_napi) { + basedev_suspend = 1; + } + + num_dev = kernel_bde->num_devices(BDE_ALL_DEVICES); + for (idx = 0; idx < num_dev; idx++) { + rv = bkn_knet_dev_init(idx); + if (rv) { + return rv; + } + } + + /* Initialize proc files */ + proc_mkdir("bcm", NULL); + bkn_proc_root = proc_mkdir("bcm/knet", NULL); + + bkn_proc_init(); + + /* Initialize event queue */ + for (idx = 0; idx < LINUX_BDE_MAX_DEVICES; idx++) { + memset(&_bkn_evt[idx], 0, sizeof(bkn_evt_resource_t)); + _bkn_evt[idx].inst_id = INVALID_INSTANCE_ID; + } + evt = &_bkn_evt[0]; + init_waitqueue_head(&evt->evt_wq); + + module_initialized = 1; + + return 0; +} + +static int +_ioctl(unsigned int cmd, unsigned long arg) +{ + bkn_ioctl_t io; + kcom_msg_t kmsg; + + if (!module_initialized) { + return -EFAULT; + } + + if (copy_from_user(&io, (void*)arg, sizeof(io))) { + return -EFAULT; + } + + if (io.len > sizeof(kmsg)) { + return -EINVAL; + } + + io.rc = 0; + + switch(cmd) { + case 0: + if (io.len > 0) { + if (copy_from_user(&kmsg, (void *)(unsigned long)io.buf, io.len)) { + return -EFAULT; + } + ioctl_cmd++; + io.len = bkn_handle_cmd_req(&kmsg, io.len); + ioctl_cmd--; + } else { + memset(&kmsg, 0, sizeof(kcom_msg_t)); + /* + * Retrive the kmsg.hdr.unit from user space. The dma event queue + * selection is based the instance derived from unit. + */ + if (copy_from_user(&kmsg, (void *)(unsigned long)io.buf, sizeof(kmsg))) { + return -EFAULT; + } + kmsg.hdr.type = KCOM_MSG_TYPE_EVT; + kmsg.hdr.opcode = KCOM_M_DMA_INFO; + ioctl_evt++; + io.len = bkn_get_next_dma_event((kcom_msg_dma_info_t *)&kmsg); + ioctl_evt--; + } + if (io.len > 0) { + if (copy_to_user((void *)(unsigned long)io.buf, &kmsg, io.len)) { + return -EFAULT; + } + } + break; + default: + gprintk("Invalid IOCTL"); + io.rc = -1; + break; + } + + if (copy_to_user((void*)arg, &io, sizeof(io))) { + return -EFAULT; + } + + return 0; +} + +static gmodule_t _gmodule = { + name: MODULE_NAME, + major: MODULE_MAJOR, + init: _init, + cleanup: _cleanup, + pprint: _pprint, + ioctl: _ioctl, + open: NULL, + close: NULL, +}; + +gmodule_t * +gmodule_get(void) +{ + EXPORT_NO_SYMBOLS; + return &_gmodule; +} + +/* + * Get DCB type and other HW info + */ +int +bkn_hw_info_get(int unit, knet_hw_info_t *hw_info) +{ + bkn_switch_info_t *sinfo; + sinfo = bkn_sinfo_from_unit(unit); + if (sinfo == NULL) { + gprintk("Warning: unknown unit: %d\n", unit); + return (-1); + } + + hw_info->cmic_type = sinfo->cmic_type; + hw_info->dcb_type = sinfo->dcb_type; + hw_info->dcb_size = WORDS2BYTES(sinfo->dcb_wsize); + hw_info->pkt_hdr_size = sinfo->pkt_hdr_size; + hw_info->cdma_channels = sinfo->cdma_channels; + + return (0); +} + +int +bkn_netif_create_cb_register(knet_netif_cb_f netif_cb) +{ + if (knet_netif_create_cb != NULL) { + return -1; + } + knet_netif_create_cb = netif_cb; + return 0; +} + +int +bkn_netif_create_cb_unregister(knet_netif_cb_f netif_cb) +{ + if (netif_cb != NULL && knet_netif_create_cb != netif_cb) { + return -1; + } + knet_netif_create_cb = NULL; + return 0; +} + +int +bkn_netif_destroy_cb_register(knet_netif_cb_f netif_cb) +{ + if (knet_netif_destroy_cb != NULL) { + return -1; + } + knet_netif_destroy_cb = netif_cb; + return 0; +} + +int +bkn_netif_destroy_cb_unregister(knet_netif_cb_f netif_cb) +{ + if (netif_cb != NULL && knet_netif_destroy_cb != netif_cb) { + return -1; + } + knet_netif_destroy_cb = NULL; + return 0; +} + +/* + * Call-back interfaces for other Linux kernel drivers. + * + * The Rx call-back allows an external module to modify SKB contents + * before it is handed off to the Linux network stack. + * + * The Tx call-back allows an external module to modify SKB contents + * before it is injected inot the switch. + * + * The HW timestamp callbacks invoke an external module to enable, disable + * HW timestamp on a specific port which is indicated while the netif is + * created through KNET API. KNET can also get device-specific SOBMH and + * timestamp for a Tx PTP packet through these callbacks. + */ + +int +bkn_rx_skb_cb_register(knet_skb_cb_f rx_cb) +{ + if (knet_rx_cb != NULL) { + return -1; + } + knet_rx_cb = rx_cb; + return 0; +} + +int +bkn_rx_skb_cb_unregister(knet_skb_cb_f rx_cb) +{ + if (rx_cb != NULL && knet_rx_cb != rx_cb) { + return -1; + } + knet_rx_cb = NULL; + return 0; +} + +int +bkn_tx_skb_cb_register(knet_skb_cb_f tx_cb) +{ + if (knet_tx_cb != NULL) { + return -1; + } + knet_tx_cb = tx_cb; + return 0; +} + +int +bkn_tx_skb_cb_unregister(knet_skb_cb_f tx_cb) +{ + if (tx_cb != NULL && knet_tx_cb != tx_cb) { + return -1; + } + knet_tx_cb = NULL; + return 0; +} + +int +bkn_filter_cb_register(knet_filter_cb_f filter_cb) +{ + if (knet_filter_cb != NULL) { + return -1; + } + knet_filter_cb = filter_cb; + return 0; +} + +int +bkn_filter_cb_unregister(knet_filter_cb_f filter_cb) +{ + if (filter_cb != NULL && knet_filter_cb != filter_cb) { + return -1; + } + knet_filter_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_enable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb) +{ + if (knet_hw_tstamp_enable_cb != NULL) { + return -1; + } + knet_hw_tstamp_enable_cb = hw_tstamp_enable_cb; + return 0; +} + +int +bkn_hw_tstamp_enable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb) +{ + if (hw_tstamp_enable_cb == NULL || + knet_hw_tstamp_enable_cb != hw_tstamp_enable_cb) { + return -1; + } + knet_hw_tstamp_enable_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_disable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb) +{ + if (knet_hw_tstamp_disable_cb != NULL) { + return -1; + } + knet_hw_tstamp_disable_cb = hw_tstamp_disable_cb; + return 0; +} + +int +bkn_hw_tstamp_disable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb) +{ + if (hw_tstamp_disable_cb == NULL || + knet_hw_tstamp_disable_cb != hw_tstamp_disable_cb) { + return -1; + } + knet_hw_tstamp_disable_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_tx_time_get_cb_register(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb) +{ + if (knet_hw_tstamp_tx_time_get_cb != NULL) { + return -1; + } + knet_hw_tstamp_tx_time_get_cb = hw_tstamp_tx_time_get_cb; + return 0; +} + +int +bkn_hw_tstamp_tx_time_get_cb_unregister(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb) +{ + if (hw_tstamp_tx_time_get_cb == NULL || + knet_hw_tstamp_tx_time_get_cb != hw_tstamp_tx_time_get_cb) { + return -1; + } + knet_hw_tstamp_tx_time_get_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_tx_meta_get_cb_register(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb) +{ + if (knet_hw_tstamp_tx_meta_get_cb != NULL) { + return -1; + } + knet_hw_tstamp_tx_meta_get_cb = hw_tstamp_tx_meta_get_cb; + return 0; +} + +int +bkn_hw_tstamp_tx_meta_get_cb_unregister(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb) +{ + if (hw_tstamp_tx_meta_get_cb == NULL || + knet_hw_tstamp_tx_meta_get_cb != hw_tstamp_tx_meta_get_cb) { + return -1; + } + knet_hw_tstamp_tx_meta_get_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_ptp_clock_index_cb_register(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb) +{ + if (knet_hw_tstamp_ptp_clock_index_cb != NULL) { + return -1; + } + knet_hw_tstamp_ptp_clock_index_cb = hw_tstamp_ptp_clock_index_cb; + return 0; +} + +int +bkn_hw_tstamp_ptp_clock_index_cb_unregister(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb) +{ + if (hw_tstamp_ptp_clock_index_cb == NULL || + knet_hw_tstamp_ptp_clock_index_cb != hw_tstamp_ptp_clock_index_cb) { + return -1; + } + knet_hw_tstamp_ptp_clock_index_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_rx_time_upscale_cb_register(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb) +{ + if (knet_hw_tstamp_rx_time_upscale_cb != NULL) { + return -1; + } + knet_hw_tstamp_rx_time_upscale_cb = hw_tstamp_rx_time_upscale_cb; + return 0; +} + +int +bkn_hw_tstamp_rx_time_upscale_cb_unregister(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb) +{ + if (hw_tstamp_rx_time_upscale_cb == NULL || + knet_hw_tstamp_rx_time_upscale_cb != hw_tstamp_rx_time_upscale_cb) { + return -1; + } + knet_hw_tstamp_rx_time_upscale_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_ioctl_cmd_cb_register(knet_hw_tstamp_ioctl_cmd_cb_f hw_tstamp_ioctl_cmd_cb) +{ + if (knet_hw_tstamp_ioctl_cmd_cb != NULL) { + return -1; + } + knet_hw_tstamp_ioctl_cmd_cb = hw_tstamp_ioctl_cmd_cb; + return 0; +} + +int +bkn_hw_tstamp_ioctl_cmd_cb_unregister(knet_hw_tstamp_ioctl_cmd_cb_f hw_tstamp_ioctl_cmd_cb) +{ + if (knet_hw_tstamp_ioctl_cmd_cb == NULL || + knet_hw_tstamp_ioctl_cmd_cb != hw_tstamp_ioctl_cmd_cb) { + return -1; + } + knet_hw_tstamp_ioctl_cmd_cb = NULL; + return 0; +} + +LKM_EXPORT_SYM(bkn_rx_skb_cb_register); +LKM_EXPORT_SYM(bkn_rx_skb_cb_unregister); +LKM_EXPORT_SYM(bkn_tx_skb_cb_register); +LKM_EXPORT_SYM(bkn_tx_skb_cb_unregister); +LKM_EXPORT_SYM(bkn_filter_cb_register); +LKM_EXPORT_SYM(bkn_filter_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_enable_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_enable_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_disable_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_disable_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_tx_time_get_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_tx_time_get_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_tx_meta_get_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_tx_meta_get_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_ptp_clock_index_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_ptp_clock_index_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_rx_time_upscale_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_rx_time_upscale_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_info_get); +LKM_EXPORT_SYM(bkn_netif_create_cb_register); +LKM_EXPORT_SYM(bkn_netif_create_cb_unregister); +LKM_EXPORT_SYM(bkn_netif_destroy_cb_register); +LKM_EXPORT_SYM(bkn_netif_destroy_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_ioctl_cmd_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_ioctl_cmd_cb_unregister); diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/Makefile new file mode 100644 index 000000000000..9aa3be686851 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/Makefile @@ -0,0 +1,65 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 2012/07/17 07:39:51 mlarsen Exp $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/linux/kernel/modules/bcm-ptp-clock + +include ${SDK}/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +ifeq ($(kernel_version),2_4) +MODULE = $(LIBDIR)/linux-bcm-ptp-clock.o +else +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := linux-bcm-ptp-clock +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: $(MODULE) $(KMODULE) +endif + +#KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../../../../bde/linux/kernel/kernel_module/Module.symvers +KBUILD_EXTRA_SYMBOLS += ${BLDDIR}/../bcm-knet/kernel_module/Module.symvers + +# BCM PTP Clock Device + +$(MODULE): $(BLDDIR)/.tree $(BOBJS) $(LIBS) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + cat ${KBUILD_EXTRA_SYMBOLS} > $(BLDDIR)/$(KERNEL_MODULE_DIR)/Module.symvers + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +include ${SDK}/make/Make.depend + +clean:: + $(RM) $(BLDDIR)/version.c $(BLDDIR)/version.o + $(RM) $(BOBJS) $(MODULE) + +ifneq ($(kernel_version),2_4) +.PHONY: build +endif diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/bcm-ptp-clock.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/bcm-ptp-clock.c new file mode 100644 index 000000000000..edc4a38c741c --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/bcm-ptp-clock.c @@ -0,0 +1,2001 @@ +/* + * Copyright 2017 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ + +/* + * This module implements a Linux PTP Clock driver for Broadcom + * XGS switch devices. + * + * For a list of supported module parameters, please see below. + * debug: Debug level (default 0) + * network_transport : Transport Type (default 0 - Raw) + * base_dev_name: Base device name (default ptp0, ptp1, etc.) + * + * - All the data structures and functions work on the physical port. + * For array indexing purposes, we use (phy_port - 1). + */ + +#include /* Must be included first */ +/* Module Information */ +#define MODULE_MAJOR 125 +#define MODULE_NAME "linux-bcm-ptp-clock" + +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("PTP Clock Driver for Broadcom XGS Switch"); +MODULE_LICENSE("GPL"); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,17,0) +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Configuration Parameters */ +static int debug; +LKM_MOD_PARAM(debug, "i", int, 0); +MODULE_PARM_DESC(debug, + "Debug level (default 0)"); + +static int pci_cos; + +static int network_transport; +LKM_MOD_PARAM(network_transport, "i", int, 0); +MODULE_PARM_DESC(network_transport, + "Transport Type (default - Detect from packet)"); + +static char *base_dev_name = "ptp0"; +LKM_MOD_PARAM(base_dev_name, "s", charp, 0); +MODULE_PARM_DESC(base_dev_name, + "Base device name (default ptp0, ptp1, etc.)"); + +static int fw_core; +LKM_MOD_PARAM(fw_core, "i", int, 0); +MODULE_PARM_DESC(fw_core, + "Firmware core (default 0)"); + +/* Debug levels */ +#define DBG_LVL_VERB 0x1 +#define DBG_LVL_WARN 0x2 +#define DBG_LVL_TXTS 0x4 +#define DBG_LVL_CMDS 0x8 + +#define DBG_VERB(_s) do { if (debug & DBG_LVL_VERB) gprintk _s; } while (0) +#define DBG_WARN(_s) do { if (debug & DBG_LVL_WARN) gprintk _s; } while (0) +#define DBG_TXTS(_s) do { if (debug & DBG_LVL_TXTS) gprintk _s; } while (0) +#define DBG_CMDS(_s) do { if (debug & DBG_LVL_CMDS) gprintk _s; } while (0) +#define DBG_ERR(_s) do { if (1) gprintk _s; } while (0) + + +#ifdef LINUX_BDE_DMA_DEVICE_SUPPORT +#define DMA_DEV device +#define DMA_ALLOC_COHERENT(d,s,h) dma_alloc_coherent(d,s,h,GFP_ATOMIC|GFP_DMA32) +#define DMA_FREE_COHERENT(d,s,a,h) dma_free_coherent(d,s,a,h) +#else +#define DMA_DEV pci_dev +#define DMA_ALLOC_COHERENT(d,s,h) pci_alloc_consistent(d,s,h) +#define DMA_FREE_COHERENT(d,s,a,h) pci_free_consistent(d,s,a,h) +#endif + +/* Type length in bytes */ +#define BKSYNC_PACKLEN_U8 1 +#define BKSYNC_PACKLEN_U16 2 +#define BKSYNC_PACKLEN_U24 3 +#define BKSYNC_PACKLEN_U32 4 + +#define BKSYNC_UNPACK_U8(_buf, _var) \ + _var = *_buf++ + +#define BKSYNC_UNPACK_U16(_buf, _var) \ + do { \ + (_var) = (((_buf)[0] << 8) | \ + (_buf)[1]); \ + (_buf) += BKSYNC_PACKLEN_U16; \ + } while (0) + +#define BKSYNC_UNPACK_U24(_buf, _var) \ + do { \ + (_var) = (((_buf)[0] << 16) | \ + ((_buf)[1] << 8) | \ + (_buf)[2]); \ + (_buf) += BKSYNC_PACKLEN_U24; \ + } while (0) + +#define BKSYNC_UNPACK_U32(_buf, _var) \ + do { \ + (_var) = (((_buf)[0] << 24) | \ + ((_buf)[1] << 16) | \ + ((_buf)[2] << 8) | \ + (_buf)[3]); \ + (_buf) += BKSYNC_PACKLEN_U32; \ + } while (0) + + +#define CMICX_DEV_TYPE ((ptp_priv->dcb_type == 38) || \ + (ptp_priv->dcb_type == 36)) + +/* CMIC MCS-0 SCHAN Messaging registers */ +/* Core0:CMC1 Core1:CMC2 */ +#define CMIC_CMC_BASE \ + (CMICX_DEV_TYPE ? (fw_core ? 0x10400 : 0x10300) : \ + (fw_core ? 0x33000 : 0x32000)) + +#define CMIC_CMC_SCHAN_MESSAGE_10r(BASE) (BASE + 0x00000034) +#define CMIC_CMC_SCHAN_MESSAGE_11r(BASE) (BASE + 0x00000038) +#define CMIC_CMC_SCHAN_MESSAGE_12r(BASE) (BASE + 0x0000003c) +#define CMIC_CMC_SCHAN_MESSAGE_13r(BASE) (BASE + 0x00000040) +#define CMIC_CMC_SCHAN_MESSAGE_14r(BASE) (BASE + 0x00000044) +#define CMIC_CMC_SCHAN_MESSAGE_15r(BASE) (BASE + 0x00000048) +#define CMIC_CMC_SCHAN_MESSAGE_16r(BASE) (BASE + 0x0000004c) +#define CMIC_CMC_SCHAN_MESSAGE_17r(BASE) (BASE + 0x00000050) +#define CMIC_CMC_SCHAN_MESSAGE_18r(BASE) (BASE + 0x00000054) +#define CMIC_CMC_SCHAN_MESSAGE_19r(BASE) (BASE + 0x00000058) +#define CMIC_CMC_SCHAN_MESSAGE_20r(BASE) (BASE + 0x0000005c) +#define CMIC_CMC_SCHAN_MESSAGE_21r(BASE) (BASE + 0x00000060) + +u32 hostcmd_regs[5] = { 0 }; + +#define BCMKSYNC_NUM_PORTS 128 /* NUM_PORTS where 2-step is supported. */ +#define BCMKSYNC_MAX_NUM_PORTS 256 /* Max ever NUM_PORTS in the system */ +#define BCMKSYNC_MAX_MTP_IDX 8 /* Max number of mtps in the system */ + +/* Service request commands to Firmware. */ +enum { + BKSYNC_DONE = (0x0), + BKSYNC_INIT = (0x1), + BKSYNC_DEINIT = (0x2), + BKSYNC_GETTIME = (0x3), + BKSYNC_SETTIME = (0x4), + BKSYNC_FREQCOR = (0x5), + BKSYNC_PBM_UPDATE = (0x6), + BKSYNC_ADJTIME = (0x7), + BKSYNC_GET_TSTIME = (0x8), + BKSYNC_MTP_TS_UPDATE_ENABLE = (0x9), + BKSYNC_MTP_TS_UPDATE_DISABLE = (0xa), + BKSYNC_ACK_TSTIME = (0xb), +}; + + +/* 1588 message types. */ +enum +{ + IEEE1588_MSGTYPE_SYNC = (0x0), + IEEE1588_MSGTYPE_DELREQ = (0x1), + IEEE1588_MSGTYPE_PDELREQ = (0x2), + IEEE1588_MSGTYPE_PDELRESP = (0x3), + /* reserved (0x4) */ + /* reserved (0x5) */ + /* reserved (0x6) */ + /* reserved (0x7) */ + IEEE1588_MSGTYPE_GENERALMASK = (0x8), /* all non-event messages have this bit set */ + IEEE1588_MSGTYPE_FLWUP = (0x8), + IEEE1588_MSGTYPE_DELRESP = (0x9), + IEEE1588_MSGTYPE_PDELRES_FLWUP = (0xA), + IEEE1588_MSGTYPE_ANNOUNCE = (0xB), + IEEE1588_MSGTYPE_SGNLNG = (0xC), + IEEE1588_MSGTYPE_MNGMNT = (0xD) + /* reserved (0xE) */ + /* reserved (0xF) */ +}; + +/* Usage macros */ +#define ONE_BILLION (1000000000) + +#define SKB_U16_GET(_skb, _pkt_offset) \ + ((_skb->data[_pkt_offset] << 8) | _skb->data[_pkt_offset + 1]) + +#define BKSYNC_PTP_EVENT_MSG(_ptp_msg_type) \ + ((_ptp_msg_type == IEEE1588_MSGTYPE_DELREQ) || \ + (_ptp_msg_type == IEEE1588_MSGTYPE_SYNC)) + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) +#define HWTSTAMP_TX_ONESTEP_SYNC 2 +#else +#include +#endif + + +/* + * Hardware specific information. + * 4 words of information used from this data set. + * 0 - 3: 2-step untagged. + * 4 - 7: 2-step tagged. + * 8 - 11: 1-step untagged. + * 12 - 15: 1-step tagged. + * 16 - 19: 1-step untagged with ITS-set. + * 20 - 23: 1-step tagged with ITS-set. + */ +uint32_t sobmhrawpkts_dcb26[24] = {0x00000000, 0x00020E00, 0x00000000, 0x00000000, 0x00000000, 0x00021200, 0x00000000, 0x00000000, + 0x00000000, 0x00100E00, 0x00000000, 0x00000000, 0x00000000, 0x00101200, 0x00000000, 0x00000000, + 0x00000000, 0x00140E00, 0x00000000, 0x00000000, 0x00000000, 0x00141200, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv4_dcb26[24] = {0x00000000, 0x00022A00, 0x00000000, 0x00000000, 0x00000000, 0x00022E00, 0x00000000, 0x00000000, + 0x00000000, 0x00102A00, 0x00000000, 0x00000000, 0x00000000, 0x00102E00, 0x00000000, 0x00000000, + 0x00000000, 0x00142A00, 0x00000000, 0x00000000, 0x00000000, 0x00142E00, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv6_dcb26[24] = {0x00000000, 0x00023E00, 0x00000000, 0x00000000, 0x00000000, 0x00024200, 0x00000000, 0x00000000, + 0x00000000, 0x00103E00, 0x00000000, 0x00000000, 0x00000000, 0x00104200, 0x00000000, 0x00000000, + 0x00000000, 0x00143E00, 0x00000000, 0x00000000, 0x00000000, 0x00144200, 0x00000000, 0x00000000}; + +uint32_t sobmhrawpkts_dcb32[24] = {0x00000000, 0x00010E00, 0x00000000, 0x00000000, 0x00000000, 0x00011200, 0x00000000, 0x00000000, + 0x00000000, 0x00080E00, 0x00000000, 0x00000000, 0x00000000, 0x00081200, 0x00000000, 0x00000000, + 0x00000000, 0x00080E00, 0x00000000, 0x00000000, 0x00000000, 0x00081200, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv4_dcb32[24] = {0x00000000, 0x00012A00, 0x00000000, 0x00000000, 0x00000000, 0x00012E00, 0x00000000, 0x00000000, + 0x00000000, 0x000C2A00, 0x00000000, 0x00000000, 0x00000000, 0x000C2E00, 0x00000000, 0x00000000, + 0x00000000, 0x000C2A00, 0x00000000, 0x00000000, 0x00000000, 0x000C2E00, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv6_dcb32[24] = {0x00000000, 0x00013E00, 0x00000000, 0x00000000, 0x00000000, 0x00014200, 0x00000000, 0x00000000, + 0x00000000, 0x000C3E00, 0x00000000, 0x00000000, 0x00000000, 0x000C4200, 0x00000000, 0x00000000, + 0x00000000, 0x000C3E00, 0x00000000, 0x00000000, 0x00000000, 0x000C4200, 0x00000000, 0x00000000}; + +uint32_t sobmhrawpkts_dcb35[24] = {0x00000000, 0x0020E000, 0x00000000, 0x00000000, 0x00000000, 0x00212000, 0x00000000, 0x00000000, + 0x00000000, 0x0100E000, 0x00000000, 0x00000000, 0x00000000, 0x01012000, 0x00000000, 0x00000000, + 0x00000000, 0x0140E000, 0x00000000, 0x00000000, 0x00000000, 0x01412000, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv4_dcb35[24] = {0x00000000, 0x0022A000, 0x00000000, 0x00000000, 0x00000000, 0x0022E000, 0x00000000, 0x00000000, + 0x00000000, 0x0102A000, 0x00000000, 0x00000000, 0x00000000, 0x0102E000, 0x00000000, 0x00000000, + 0x00000000, 0x0142A000, 0x00000000, 0x00000000, 0x00000000, 0x0142E000, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv6_dcb35[24] = {0x00000000, 0x0023E000, 0x00000000, 0x00000000, 0x00000000, 0x00242000, 0x00000000, 0x00000000, + 0x00000000, 0x0103E000, 0x00000000, 0x00000000, 0x00000000, 0x01042000, 0x00000000, 0x00000000, + 0x00000000, 0x0143E000, 0x00000000, 0x00000000, 0x00000000, 0x01442000, 0x00000000, 0x00000000}; + + +uint32_t sobmhrawpkts_dcb36[24] = {0x00000000, 0x00010E00, 0x00000000, 0x00000000, 0x00000000, 0x00011200, 0x00000000, 0x00000000, + 0x00000000, 0x00080E00, 0x00000000, 0x00000000, 0x00000000, 0x00081200, 0x00000000, 0x00000000, + 0x00000000, 0x00080E00, 0x00000000, 0x00000000, 0x00000000, 0x00081200, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv4_dcb36[24] = {0x00000000, 0x00012A00, 0x00000000, 0x00000000, 0x00000000, 0x00012E00, 0x00000000, 0x00000000, + 0x00000000, 0x000C2A00, 0x00000000, 0x00000000, 0x00000000, 0x000C2E00, 0x00000000, 0x00000000, + 0x00000000, 0x000C2A00, 0x00000000, 0x00000000, 0x00000000, 0x000C2E00, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv6_dcb36[24] = {0x00000000, 0x00013E00, 0x00000000, 0x00000000, 0x00000000, 0x00014200, 0x00000000, 0x00000000, + 0x00000000, 0x000C3E00, 0x00000000, 0x00000000, 0x00000000, 0x000C4200, 0x00000000, 0x00000000, + 0x00000000, 0x000C3E00, 0x00000000, 0x00000000, 0x00000000, 0x000C4200, 0x00000000, 0x00000000}; +/* th3: onestep only */ +uint32_t sobmhrawpkts_dcb38[24] = {0x00000000, 0x00080E00, 0x00000000, 0x00000000, 0x00000000, 0x00081200, 0x00000000, 0x00000000, + 0x00000000, 0x00080E00, 0x00000000, 0x00000000, 0x00000000, 0x00081200, 0x00000000, 0x00000000, + 0x00000000, 0x00080E00, 0x00000000, 0x00000000, 0x00000000, 0x00081200, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv4_dcb38[24] = {0x00000000, 0x00082A00, 0x00000000, 0x00000000, 0x00000000, 0x00082E00, 0x00000000, 0x00000000, + 0x00000000, 0x000C2A00, 0x00000000, 0x00000000, 0x00000000, 0x000C2E00, 0x00000000, 0x00000000, + 0x00000000, 0x000C2A00, 0x00000000, 0x00000000, 0x00000000, 0x000C2E00, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv6_dcb38[24] = {0x00000000, 0x00083E00, 0x00000000, 0x00000000, 0x00000000, 0x00084200, 0x00000000, 0x00000000, + 0x00000000, 0x000C3E00, 0x00000000, 0x00000000, 0x00000000, 0x000C4200, 0x00000000, 0x00000000, + 0x00000000, 0x000C3E00, 0x00000000, 0x00000000, 0x00000000, 0x000C4200, 0x00000000, 0x00000000}; + +/* Driver Proc Entry root */ +static struct proc_dir_entry *bksync_proc_root = NULL; + +/* Shared data structures with R5 */ +typedef struct _bksync_tx_ts_data_s +{ + u32 ts_valid; /* Timestamp valid indication */ + u32 port_id; /* Port number */ + u32 ts_seq_id; /* Sequency Id */ + u32 ts_cnt; + u64 timestamp; /* Timestamp */ +} bksync_tx_ts_data_t; + +typedef struct _bksync_uc_linux_ipc_s +{ + u32 ksyncinit; + u32 dev_id; + s64 freqcorr; + u64 portmap[BCMKSYNC_NUM_PORTS/64]; /* Two-step enabled ports */ + u64 ptptime; + u64 reftime; + s64 phase_offset; + bksync_tx_ts_data_t port_ts_data[BCMKSYNC_NUM_PORTS]; +} bksync_uc_linux_ipc_t; + +typedef struct bksync_port_stats_s { + u32 pkt_rxctr; /* All ingress packets */ + u32 pkt_txctr; /* All egress packets */ + u32 pkt_txonestep; /* 1-step Tx packet counter */ + u32 tsts_match; /* 2-Step tstamp req match */ + u32 tsts_timeout; /* 2-Step tstamp req timeouts */ + u32 tsts_discard; /* 2-Step tstamp req discards */ + u32 osts_event_pkts; /* 1-step event packet counter */ + u32 osts_tstamp_reqs; /* 1-step events with tstamp request */ + u32 fifo_rxctr; /* 2-Step tstamp req match */ + u64 tsts_best_fetch_time; /* 1-step events with tstamp request */ + u64 tsts_worst_fetch_time; /* 1-step events with tstamp request */ + u32 tsts_avg_fetch_time; /* 1-step events with tstamp request */ +} bksync_port_stats_t; + +/* Clock Private Data */ +struct bksync_ptp_priv { + struct device dev; + int dcb_type; + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_caps; + struct mutex ptp_lock; + struct mutex ptp_pair_lock; + volatile void *base_addr; /* address for PCI register access */ + volatile bksync_uc_linux_ipc_t *shared_addr; /* address for shared memory access */ + uint64_t dma_mem; + int dma_mem_size; + struct DMA_DEV *dma_dev; /* Required for DMA memory control */ + int num_pports; + int timekeep_status; + u32 mirror_encap_bmp; + struct delayed_work time_keep; + bksync_port_stats_t *port_stats; +}; + +static struct bksync_ptp_priv *ptp_priv; +volatile bksync_uc_linux_ipc_t *linuxPTPMemory = (bksync_uc_linux_ipc_t*)(0); +static volatile int module_initialized; +static int num_retries = 10; /* Retry count */ + +static void bksync_ptp_time_keep_init(void); +static void bksync_ptp_time_keep_deinit(void); + +#if defined(CMIC_SOFT_BYTE_SWAP) + +#define CMIC_SWAP32(_x) ((((_x) & 0xff000000) >> 24) \ + | (((_x) & 0x00ff0000) >> 8) \ + | (((_x) & 0x0000ff00) << 8) \ + | (((_x) & 0x000000ff) << 24)) + +#define DEV_READ32(_d, _a, _p) \ + do { \ + uint32_t _data; \ + _data = (((volatile uint32_t *)(_d)->base_addr)[(_a)/4]); \ + *(_p) = CMIC_SWAP32(_data); \ + } while(0) + +#define DEV_WRITE32(_d, _a, _v) \ + do { \ + uint32_t _data = CMIC_SWAP32(_v); \ + ((volatile uint32_t *)(_d)->base_addr)[(_a)/4] = (_data); \ + } while(0) + +#else + +#define DEV_READ32(_d, _a, _p) \ + do { \ + *(_p) = (((volatile uint32_t *)(_d)->base_addr)[(_a)/4]); \ + } while(0) + +#define DEV_WRITE32(_d, _a, _v) \ + do { \ + ((volatile uint32_t *)(_d)->base_addr)[(_a)/4] = (_v); \ + } while(0) +#endif /* defined(CMIC_SOFT_BYTE_SWAP) */ + +static void +ptp_usleep(int usec) +{ + usleep_range(usec,usec+1); +} + +static void +ptp_sleep(int jiffies) +{ + wait_queue_head_t wq; + init_waitqueue_head(&wq); + + wait_event_timeout(wq, 0, jiffies); + +} + + +static void bksync_hostcmd_data_op(int setget, u64 *d1, u64 *d2) +{ + u32 w0, w1; + u64 data; + + if (!d1) { + return; + } + + if (setget) { + data = *d1; + w0 = (data & 0xFFFFFFFF); + w1 = (data >> 32); + DEV_WRITE32(ptp_priv, hostcmd_regs[1], w0); + DEV_WRITE32(ptp_priv, hostcmd_regs[2], w1); + } else { + DEV_READ32(ptp_priv, hostcmd_regs[1], &w0); + DEV_READ32(ptp_priv, hostcmd_regs[2], &w1); + data = (((u64)w1 << 32) | (w0)); + *d1 = data; + + if (d2) { + DEV_READ32(ptp_priv, hostcmd_regs[3], &w0); + DEV_READ32(ptp_priv, hostcmd_regs[4], &w1); + data = (((u64)w1 << 32) | (w0)); + *d2 = data; + } + } +} + + +static int bksync_cmd_go(u32 cmd, void *data0, void *data1) +{ + int ret = -1; + int retry_cnt = (1000); /* 1ms default timeout for hostcmd response */ + u32 cmd_status; + char cmd_str[20]; + int port; + uint32_t seq_id; + ktime_t start, now; + + if (ptp_priv == NULL || ptp_priv->shared_addr == NULL) { + return ret; + } + + mutex_lock(&ptp_priv->ptp_lock); + + if (cmd == BKSYNC_GET_TSTIME || cmd == BKSYNC_ACK_TSTIME) { + port = *((uint64_t *)data0) & 0xFFF; + seq_id = *((uint64_t*)data0) >> 16; + } + start = ktime_get(); + + ptp_priv->shared_addr->ksyncinit = cmd; + + /* init data */ + DEV_WRITE32(ptp_priv, hostcmd_regs[1], 0x0); + DEV_WRITE32(ptp_priv, hostcmd_regs[2], 0x0); + DEV_WRITE32(ptp_priv, hostcmd_regs[3], 0x0); + DEV_WRITE32(ptp_priv, hostcmd_regs[4], 0x0); + + switch (cmd) { + case BKSYNC_INIT: + sprintf(cmd_str, "KSYNC_INIT"); + ptp_priv->shared_addr->phase_offset = 0; + bksync_hostcmd_data_op(1, (u64 *)&(ptp_priv->shared_addr->phase_offset), 0); + break; + case BKSYNC_FREQCOR: + sprintf(cmd_str, "KSYNC_FREQCORR"); + ptp_priv->shared_addr->freqcorr = *((s32 *)data0); + bksync_hostcmd_data_op(1, (u64 *)&(ptp_priv->shared_addr->freqcorr), 0); + break; + case BKSYNC_ADJTIME: + sprintf(cmd_str, "KSYNC_ADJTIME"); + ptp_priv->shared_addr->phase_offset = *((s64 *)data0); + bksync_hostcmd_data_op(1, (u64 *)&(ptp_priv->shared_addr->phase_offset), 0); + break; + case BKSYNC_GETTIME: + retry_cnt = (retry_cnt * 2); + sprintf(cmd_str, "KSYNC_GETTIME"); + break; + case BKSYNC_GET_TSTIME: + retry_cnt = (retry_cnt * 2); + sprintf(cmd_str, "KSYNC_GET_TSTIME"); + bksync_hostcmd_data_op(1, data0, data1); + break; + case BKSYNC_ACK_TSTIME: + retry_cnt = (retry_cnt * 2); + sprintf(cmd_str, "KSYNC_ACK_TSTIME"); + bksync_hostcmd_data_op(1, data0, data1); + break; + case BKSYNC_SETTIME: + sprintf(cmd_str, "KSYNC_SETTIME"); + ptp_priv->shared_addr->ptptime = *((s64 *)data0); + ptp_priv->shared_addr->phase_offset = 0; + bksync_hostcmd_data_op(1, (u64 *)&(ptp_priv->shared_addr->ptptime), (u64 *)&(ptp_priv->shared_addr->phase_offset)); + break; + case BKSYNC_MTP_TS_UPDATE_ENABLE: + retry_cnt = (retry_cnt * 6); + sprintf(cmd_str, "KSYNC_MTP_TS_UPDATE_ENABLE"); + bksync_hostcmd_data_op(1, (u64 *)data0, 0); + break; + case BKSYNC_MTP_TS_UPDATE_DISABLE: + retry_cnt = (retry_cnt * 6); + sprintf(cmd_str, "KSYNC_MTP_TS_UPDATE_DISABLE"); + bksync_hostcmd_data_op(1, (u64 *)data0, 0); + break; + case BKSYNC_DEINIT: + retry_cnt = (retry_cnt * 4); + sprintf(cmd_str, "KSYNC_DEINIT"); + break; + default: + sprintf(cmd_str, "KSYNC_XXX"); + break; + } + DEV_WRITE32(ptp_priv, hostcmd_regs[0], ptp_priv->shared_addr->ksyncinit); + + do { + DEV_READ32(ptp_priv, hostcmd_regs[0], &cmd_status); + ptp_priv->shared_addr->ksyncinit = cmd_status; + + if (cmd_status == BKSYNC_DONE) { + ret = 0; + switch (cmd) { + case BKSYNC_GET_TSTIME: + case BKSYNC_GETTIME: + bksync_hostcmd_data_op(0, (u64 *)data0, (u64 *)data1); + break; + default: + break; + } + break; + } + ptp_usleep(100); + retry_cnt--; + } while (retry_cnt); + + now = ktime_get(); + mutex_unlock(&ptp_priv->ptp_lock); + + if (retry_cnt == 0) { + DBG_ERR(("Timeout on response from R5 to cmd %s time taken %lld us\n", cmd_str, ktime_us_delta(now, start))); + if (cmd == BKSYNC_GET_TSTIME) { + DBG_TXTS(("Timeout Port %d SeqId %d\n", port, seq_id)); + } + } + if (debug & DBG_LVL_CMDS) { + if (ktime_us_delta(now, start) > 5000) + DBG_CMDS(("R5 Command %s exceeded time expected (%lld us)\n", cmd_str, ktime_us_delta(now, start))); + } + + + return ret; +} + + +/** + * bksync_ptp_adjfreq + * + * @ptp: pointer to ptp_clock_info structure + * @ppb: frequency correction value + * + * Description: this function will set the frequency correction + */ +static int bksync_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + int ret = -1; + u32 cmd_status = BKSYNC_FREQCOR; + + ret = bksync_cmd_go(cmd_status, &ppb, NULL); + DBG_VERB(("applying freq correction: %x\n", ppb)); + + return ret; +} + +/** + * bksync_ptp_adjtime + * + * @ptp: pointer to ptp_clock_info structure + * @delta: desired change in nanoseconds + * + * Description: this function will shift/adjust the hardware clock time. + */ +static int bksync_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + u32 cmd_status = BKSYNC_ADJTIME; + int ret = -1; + + ret = bksync_cmd_go(cmd_status, (void *)&delta, NULL); + DBG_VERB(("ptp adjtime: 0x%llx \n", delta)); + + return ret; +} + +/** + * bksync_ptp_gettime + * + * @ptp: pointer to ptp_clock_info structure + * @ts: pointer to hold time/result + * + * Description: this function will read the current time from the + * hardware clock and store it in @ts. + */ +static int bksync_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) +{ + int ret = -1; + u32 cmd_status = BKSYNC_GETTIME; + s64 reftime = 0; + s64 refctr = 0; + + ret = bksync_cmd_go(cmd_status, (void *)&reftime, (void *)&refctr); + if (ret == 0) { + DBG_VERB(("ptp gettime: 0x%llx refctr:0x%llx\n", reftime, refctr)); + mutex_lock(&ptp_priv->ptp_pair_lock); + ptp_priv->shared_addr->ptptime = reftime; + ptp_priv->shared_addr->reftime = refctr; + mutex_unlock(&ptp_priv->ptp_pair_lock); + + *ts = ns_to_timespec64(reftime); + } + return ret; +} + + +/** + * bksync_ptp_settime + * + * @ptp: pointer to ptp_clock_info structure + * @ts: time value to set + * + * Description: this function will set the current time on the + * hardware clock. + */ +static int bksync_ptp_settime(struct ptp_clock_info *ptp, + const struct timespec64 *ts) +{ + s64 reftime, phaseadj; + int ret = -1; + u32 cmd_status = BKSYNC_SETTIME; + + phaseadj = 0; + reftime = timespec64_to_ns(ts); + + ret = bksync_cmd_go(cmd_status, (void *)&reftime, (void *)&phaseadj); + DBG_VERB(("ptp settime: 0x%llx \n", reftime)); + + return ret; +} + +static int bksync_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + return 0; +} + + +static int bksync_ptp_mirror_encap_update(struct ptp_clock_info *ptp, + int mtp_idx, int start) +{ + int ret = -1; + u64 mirror_encap_idx; + u32 cmd_status; + + if (mtp_idx > BCMKSYNC_MAX_MTP_IDX) { + return ret; + } + + mirror_encap_idx = mtp_idx; + if (start) { + cmd_status = BKSYNC_MTP_TS_UPDATE_ENABLE; + ptp_priv->mirror_encap_bmp |= (1 << mtp_idx); + } else { + if (!(ptp_priv->mirror_encap_bmp & mtp_idx)) { + /* Not running */ + return ret; + } + cmd_status = BKSYNC_MTP_TS_UPDATE_DISABLE; + ptp_priv->mirror_encap_bmp &= ~mtp_idx; + } + + ret = bksync_cmd_go(cmd_status, &mirror_encap_idx, NULL); + DBG_VERB(("ptp mmirror_encap_update: %d, mpt_index: %d, ret:%d \n", start, mtp_idx, ret)); + + return ret; + +} + +/* structure describing a PTP hardware clock */ +static struct ptp_clock_info bksync_ptp_caps = { + .owner = THIS_MODULE, + .name = "bksync_ptp_clock", + .max_adj = 200000, + .n_alarm = 0, + .n_ext_ts = 0, + .n_per_out = 0, /* will be overwritten in bksync_ptp_register */ + .n_pins = 0, + .pps = 0, + .adjfreq = bksync_ptp_adjfreq, + .adjtime = bksync_ptp_adjtime, + .gettime64 = bksync_ptp_gettime, + .settime64 = bksync_ptp_settime, + .enable = bksync_ptp_enable, +}; + +/** + * bksync_ptp_hw_tstamp_enable + * + * @dev_no: device number + * @port: port number + * + * Description: this is a callback function to enable the timestamping on + * a given port + */ +int bksync_ptp_hw_tstamp_enable(int dev_no, int port, int tx_type) +{ + uint64_t portmap = 0; + int map = 0; + int ret = 0; + + if (!module_initialized) { + ret = -1; + goto exit; + } + + if (tx_type == HWTSTAMP_TX_ONESTEP_SYNC) { + bksync_ptp_time_keep_init(); + goto exit; + } + + DBG_VERB(("Enable timestamp on a given port:%d\n", port)); + if (port <= 0) { + DBG_ERR(("Error enabling timestamp on port:%d\n", port)); + ret = -1; + goto exit; + } + + port -= 1; + map = port/64; port = port%64; + + /* Update the shared structure member */ + if (ptp_priv->shared_addr) { + portmap = ptp_priv->shared_addr->portmap[map]; + portmap |= (uint64_t)0x1 << port; + ptp_priv->shared_addr->portmap[map] = portmap; + /* Command to R5 for the update */ + ptp_priv->shared_addr->ksyncinit=BKSYNC_PBM_UPDATE; + } + +exit: + return ret; +} + +/** + * bksync_ptp_hw_tstamp_disable + * + * @dev_no: device number + * @port: port number + * + * Description: this is a callback function to disable the timestamping on + * a given port + */ +int bksync_ptp_hw_tstamp_disable(int dev_no, int port, int tx_type) +{ + uint64_t portmap = 0; + int map = 0; + int ret = 0; + + if (!module_initialized) { + ret = -1; + goto exit; + } + + if (tx_type == HWTSTAMP_TX_ONESTEP_SYNC) { + goto exit; + } + + DBG_VERB(("Disable timestamp on a given port:%d\n", port)); + if (port <= 0) { + DBG_ERR(("Error disabling timestamp on port:%d\n", port)); + ret = -1; + goto exit; + } + + port -= 1; + map = port/64; port = port%64; + + /* Update the shared structure member */ + if (ptp_priv->shared_addr) { + portmap = ptp_priv->shared_addr->portmap[map]; + portmap &= ~((uint64_t)0x1 << port); + ptp_priv->shared_addr->portmap[map]= portmap; + + /* Command to R5 for the update */ + ptp_priv->shared_addr->ksyncinit = BKSYNC_PBM_UPDATE; + } +exit: + return ret; +} + +int bksync_ptp_transport_get(uint8_t *pkt) +{ + int transport = 0; + uint16_t ethertype; + uint16_t tpid; + int tpid_offset, ethype_offset; + + /* Need to check VLAN tag if packet is tagged */ + tpid_offset = 12; + tpid = pkt[tpid_offset] << 8 | pkt[tpid_offset + 1]; + if (tpid == 0x8100) { + ethype_offset = tpid_offset + 4; + } else { + ethype_offset = tpid_offset; + } + + ethertype = pkt[ethype_offset] << 8 | pkt[ethype_offset+1]; + + switch (ethertype) { + case 0x88f7: /* ETHERTYPE_PTPV2 */ + transport = 2; + break; + + case 0x0800: /* ETHERTYPE_IPV4 */ + transport = 4; + break; + + case 0x86DD: /* ETHERTYPE_IPV6 */ + transport = 6; + break; + + default: + transport = 0; + } + + return transport; +} + +static int +bksync_txpkt_tsts_tsamp_get(int port, uint32_t pkt_seq_id, uint32_t *ts_valid, uint32_t *seq_id, uint64_t *timestamp) +{ + int ret = 0; + uint64_t tmp; + u32 fifo_rxctr = 0; + + tmp = (port & 0xFFFF) | (pkt_seq_id << 16); + + ret = bksync_cmd_go(BKSYNC_GET_TSTIME, &tmp, timestamp); + + if (ret >= 0) { + fifo_rxctr = (tmp >> 32) & 0xFFFF; + *seq_id = ((tmp >> 16) & 0xFFFF); + *ts_valid = (tmp & 0x1); + if (*ts_valid) { + tmp = (port & 0xFFFF) | (pkt_seq_id << 16); + bksync_cmd_go(BKSYNC_ACK_TSTIME, &tmp, 0); + if (fifo_rxctr != 0) { + if (fifo_rxctr != ptp_priv->port_stats[port].fifo_rxctr + 1) { + DBG_ERR(("FW Reset or Lost Timestamp RxSeq:(Prev %d : Current %d)\n", ptp_priv->port_stats[port].fifo_rxctr, fifo_rxctr)); + } + ptp_priv->port_stats[port].fifo_rxctr = fifo_rxctr; + } + } + } + + + return ret; +} + + +/** + * bksync_ptp_hw_tstamp_tx_time_get + * + * @dev_no: device number + * @port: port number + * @pkt: packet address + * @ts: timestamp to be retrieved + * + * Description: this is a callback function to retrieve the timestamp on + * a given port + */ +int bksync_ptp_hw_tstamp_tx_time_get(int dev_no, int port, uint8_t *pkt, uint64_t *ts) +{ + /* Get Timestamp from R5 or CLMAC */ + uint32_t ts_valid = 0; + uint32_t seq_id = 0; + uint32_t pktseq_id = 0; + uint64_t timestamp = 0; + uint16_t tpid = 0; + ktime_t start; + u64 delta; + int retry_cnt = num_retries; + int seq_id_offset, tpid_offset; + int transport = network_transport; + start = ktime_get(); + + if (!ptp_priv || !pkt || !ts || port < 1 || port > 255 || ptp_priv->shared_addr == NULL) { + return -1; + } + + *ts = 0; + + tpid_offset = 12; + + /* Parse for nw transport */ + if (transport == 0) { + transport = bksync_ptp_transport_get(pkt); + } + + switch(transport) + { + case 2: + seq_id_offset = 0x2c; + break; + case 4: + seq_id_offset = 0x48; + break; + case 6: + seq_id_offset = 0x5c; + break; + default: + seq_id_offset = 0x2c; + break; + } + + /* Need to check VLAN tag if packet is tagged */ + tpid = pkt[tpid_offset] << 8 | pkt[tpid_offset + 1]; + if (tpid == 0x8100) { + seq_id_offset += 4; + } + + + pktseq_id = pkt[seq_id_offset] << 8 | pkt[seq_id_offset + 1]; + + port -= 1; + + /* Fetch the TX timestamp from shadow memory */ + do { + bksync_txpkt_tsts_tsamp_get(port, pktseq_id, &ts_valid, &seq_id, ×tamp); + if (ts_valid) { + + /* Clear the shadow memory to get next entry */ + ptp_priv->shared_addr->port_ts_data[port].timestamp = 0; + ptp_priv->shared_addr->port_ts_data[port].port_id = 0; + ptp_priv->shared_addr->port_ts_data[port].ts_seq_id = 0; + ptp_priv->shared_addr->port_ts_data[port].ts_valid = 0; + + if (seq_id == pktseq_id) { + *ts = timestamp; + ptp_priv->port_stats[port].tsts_match += 1; + + delta = ktime_us_delta(ktime_get(), start); + DBG_VERB(("Port: %d Skb_SeqID %d FW_SeqId %d and TS:%llx FetchTime %lld\n", + port, pktseq_id, seq_id, timestamp, delta)); + + if (delta < ptp_priv->port_stats[port].tsts_best_fetch_time || ptp_priv->port_stats[port].tsts_best_fetch_time == 0) { + ptp_priv->port_stats[port].tsts_best_fetch_time = delta; + } + if (delta > ptp_priv->port_stats[port].tsts_worst_fetch_time || ptp_priv->port_stats[port].tsts_worst_fetch_time == 0) { + ptp_priv->port_stats[port].tsts_worst_fetch_time = delta; + } + /* Calculate Moving Average*/ + ptp_priv->port_stats[port].tsts_avg_fetch_time = ((u32)delta + ((ptp_priv->port_stats[port].tsts_match - 1) * ptp_priv->port_stats[port].tsts_avg_fetch_time)) / ptp_priv->port_stats[port].tsts_match; + break; + } else { + DBG_TXTS(("Discard timestamp on port %d Skb_SeqID %d FW_SeqId %d RetryCnt %d TimeLapsed (%lld us)\n", + port, pktseq_id, seq_id, (num_retries - retry_cnt), ktime_us_delta(ktime_get(),start))); + + ptp_priv->port_stats[port].tsts_discard += 1; + continue; + } + } + ptp_sleep(1); + retry_cnt--; + } while(retry_cnt); + + + ptp_priv->port_stats[port].pkt_txctr += 1; + + if (retry_cnt == 0) { + ptp_priv->port_stats[port].tsts_timeout += 1; + DBG_ERR(("FW Response timeout: Tx TS on phy port:%d Skb_SeqID: %d TimeLapsed (%lld us)\n", + port, pktseq_id, ktime_us_delta(ktime_get(), start))); + } + + + return 0; +} + + +enum { + bxconCustomEncapVersionInvalid = 0, + bxconCustomEncapVersionOne = 1, + + bxconCustomEncapVersionCurrent = bxconCustomEncapVersionOne, + bxconCustomEncapVersionReserved = 255 /* last */ +} bxconCustomEncapVersion; + +enum { + bxconCustomEncapOpcodeInvalid = 0, + bxconCustomEncapOpcodePtpRx = 1, + bxconCustomEncapOpcodeReserved = 255 /* last */ +} bxconCustomEncapOpcode; + +enum { + bxconCustomEncapPtpRxTlvInvalid = 0, + bxconCustomEncapPtpRxTlvPtpRxTime = 1, + bxconCustomEncapPtpRxTlvReserved = 255 /* last */ +} bxconCustomEncapPtpRxTlvType; + +void +bksync_dump_pkt(uint8_t *data, int size) +{ + int idx; + char str[128]; + + for (idx = 0; idx < size; idx++) { + if ((idx & 0xf) == 0) { + sprintf(str, "%04x: ", idx); + } + sprintf(&str[strlen(str)], "%02x ", data[idx]); + if ((idx & 0xf) == 0xf) { + sprintf(&str[strlen(str)], "\n"); + gprintk(str); + } + } + if ((idx & 0xf) != 0) { + sprintf(&str[strlen(str)], "\n"); + gprintk(str); + } +} + + +static inline int +bksync_pkt_custom_encap_ptprx_get(uint8_t *pkt, uint64_t *ing_ptptime) +{ + uint8_t *custom_hdr; + uint8_t id[4]; + uint8_t ver, opc; + uint8_t nh_type, nh_rsvd; + uint16_t len, tot_len; + uint16_t nh_len; + uint32_t seq_id = 0; + uint32_t ptp_rx_time[2]; + uint64_t u64_ptp_rx_time = 0; + + custom_hdr = pkt; + + BKSYNC_UNPACK_U8(custom_hdr, id[0]); + BKSYNC_UNPACK_U8(custom_hdr, id[1]); + BKSYNC_UNPACK_U8(custom_hdr, id[2]); + BKSYNC_UNPACK_U8(custom_hdr, id[3]); + if (!((id[0] == 'B') && (id[1] == 'C') && (id[2] == 'M') && (id[3] == 'C'))) { + /* invalid signature */ + return -1; + } + + BKSYNC_UNPACK_U8(custom_hdr, ver); + switch (ver) { + case bxconCustomEncapVersionCurrent: + break; + default: + gprintk("invalid ver\n"); + return -1; + } + + BKSYNC_UNPACK_U8(custom_hdr, opc); + switch (opc) { + case bxconCustomEncapOpcodePtpRx: + break; + default: + gprintk("invalid opcode\n"); + return -1; + } + + + BKSYNC_UNPACK_U16(custom_hdr, len); + BKSYNC_UNPACK_U32(custom_hdr, seq_id); + tot_len = len; + + /* remaining length of custom encap */ + len = len - (custom_hdr - pkt); + + + /* process tlv */ + while (len > 0) { + BKSYNC_UNPACK_U8(custom_hdr, nh_type); + BKSYNC_UNPACK_U8(custom_hdr, nh_rsvd); + BKSYNC_UNPACK_U16(custom_hdr, nh_len); + len = len - (nh_len); + if (nh_rsvd != 0x0) { + continue; /* invalid tlv */ + } + + switch (nh_type) { + case bxconCustomEncapPtpRxTlvPtpRxTime: + BKSYNC_UNPACK_U32(custom_hdr, ptp_rx_time[0]); + BKSYNC_UNPACK_U32(custom_hdr, ptp_rx_time[1]); + u64_ptp_rx_time = ((uint64_t)ptp_rx_time[1] << 32) | (uint64_t)ptp_rx_time[0]; + *ing_ptptime = u64_ptp_rx_time; + break; + default: + custom_hdr += nh_len; + break; + } + } + +#if 0 +if (!(seq_id % 100)) { + gprintk("****** seq_id = %d ptp time = 0x%llx\n", seq_id, u64_ptp_rx_time); + bksync_dump_pkt(pkt, tot_len); +} +#endif + + DBG_VERB(("Custom encap header: ver=%d opcode=%d seq_id=0x%x\n", ver, opc, seq_id)); + + return (tot_len); +} + + + +/** + * bksync_ptp_hw_tstamp_rx_time_upscale + * + * @dev_no: device number + * @ts: timestamp to be retrieved + * + * Description: this is a callback function to retrieve 64b equivalent of + * rx timestamp + */ +int bksync_ptp_hw_tstamp_rx_time_upscale(int dev_no, int port, struct sk_buff *skb, uint32_t *meta, uint64_t *ts) +{ + int ret = 0; + int custom_encap_len = 0; + + switch (KNET_SKB_CB(skb)->dcb_type) { + case 26: + case 32: + case 35: + if (pci_cos != (meta[4] & 0x3F)) { + return -1; + } + break; + case 38: + if (pci_cos != ((meta[12] >> 22) & 0x2F)) { + return -1; + } + break; + case 36: + if (pci_cos != ((meta[6] >> 22) & 0x2F)) { + return -1; + } + break; + default: + return -1; + } + + /* parse custom encap header in pkt for ptp rxtime */ + custom_encap_len = bksync_pkt_custom_encap_ptprx_get((skb->data), ts); + + /* Remove the custom encap header from pkt */ + if (custom_encap_len > 0) { + skb_pull(skb, custom_encap_len); + + DBG_VERB(("###### ptp message type: %d\n", skb->data[42])); + } + + if (port > 0){ + port -= 1; + ptp_priv->port_stats[port].pkt_rxctr += 1; + } + + return ret; +} + + +void bksync_hton64(u8 *buf, const uint64_t *data) +{ +#ifdef __LITTLE_ENDIAN + /* LITTLE ENDIAN */ + buf[0] = (*(((uint8_t*)(data)) + 7u)); + buf[1] = (*(((uint8_t*)(data)) + 6u)); + buf[2] = (*(((uint8_t*)(data)) + 5u)); + buf[3] = (*(((uint8_t*)(data)) + 4u)); + buf[4] = (*(((uint8_t*)(data)) + 3u)); + buf[5] = (*(((uint8_t*)(data)) + 2u)); + buf[6] = (*(((uint8_t*)(data)) + 1u)); + buf[7] = (*(((uint8_t*)(data)) + 0u)); +#else + memcpy(buf, data, 8); +#endif +} + + + +int bksync_ptp_hw_tstamp_tx_meta_get(int dev_no, + int hwts, int hdrlen, + struct sk_buff *skb, + uint64_t *tstamp, + u32 **md) +{ + uint16_t tpid = 0; + int md_offset = 0; + int pkt_offset = 0; + int ptp_hdr_offset = 0; + int transport = network_transport; + s64 ptptime = 0; + s64 ptpcounter = 0; + int64_t corrField; + int32_t negCurTS32; + int64_t negCurTS64; + + if(!ptp_priv || ptp_priv->shared_addr == NULL) { + return 0; + } + + mutex_lock(&ptp_priv->ptp_pair_lock); + ptptime = ptp_priv->shared_addr->ptptime; + ptpcounter = ptp_priv->shared_addr->reftime; + mutex_unlock(&ptp_priv->ptp_pair_lock); + + negCurTS32 = - (int32_t) ptpcounter; + negCurTS64 = - (int64_t)(ptpcounter); + + if (CMICX_DEV_TYPE) { + pkt_offset = ptp_hdr_offset = hdrlen; + } + + /* Need to check VLAN tag if packet is tagged */ + tpid = SKB_U16_GET(skb, (pkt_offset + 12)); + if (tpid == 0x8100) { + md_offset = 4; + ptp_hdr_offset += 4; + } + + /* One Step Meta Data */ + if (hwts == HWTSTAMP_TX_ONESTEP_SYNC) { + md_offset += 8; + if (KNET_SKB_CB(skb)->dcb_type == 26) { + corrField = (((int64_t)negCurTS32) << 16); + if (negCurTS32 >= 0) { + md_offset += 8; + } + } else { + corrField = (((int64_t)negCurTS64) << 16); + } + } + + + /* Parse for nw transport */ + if (transport == 0) { + transport = bksync_ptp_transport_get(skb->data + pkt_offset); + } + + switch(transport) + { + case 2: /* IEEE 802.3 */ + ptp_hdr_offset += 14; + if (KNET_SKB_CB(skb)->dcb_type == 32) { + if (md) *md = &sobmhrawpkts_dcb32[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 26) { + if (md) *md = &sobmhrawpkts_dcb26[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 35) { + if (md) *md = &sobmhrawpkts_dcb35[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 36) { + if (md) *md = &sobmhrawpkts_dcb36[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 38) { + if (md) *md = &sobmhrawpkts_dcb38[md_offset]; + } + break; + case 4: /* UDP IPv4 */ + ptp_hdr_offset += 42; + if (KNET_SKB_CB(skb)->dcb_type == 32) { + if (md) *md = &sobmhudpipv4_dcb32[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 26) { + if (md) *md = &sobmhudpipv4_dcb26[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 35) { + if (md) *md = &sobmhudpipv4_dcb35[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 36) { + if (md) *md = &sobmhudpipv4_dcb36[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 38) { + if (md) *md = &sobmhudpipv4_dcb38[md_offset]; + } + break; + case 6: /* UDP IPv6 */ + ptp_hdr_offset += 62; + if (KNET_SKB_CB(skb)->dcb_type == 32) { + if (md) *md = &sobmhudpipv6_dcb32[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 26) { + if (md) *md = &sobmhudpipv6_dcb26[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 35) { + if (md) *md = &sobmhudpipv6_dcb35[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 36) { + if (md) *md = &sobmhudpipv6_dcb36[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 38) { + if (md) *md = &sobmhudpipv6_dcb38[md_offset]; + } + break; + default: + ptp_hdr_offset += 42; + if (KNET_SKB_CB(skb)->dcb_type == 32) { + if (md) *md = &sobmhudpipv4_dcb32[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 26) { + if (md) *md = &sobmhudpipv4_dcb26[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 35) { + if (md) *md = &sobmhudpipv4_dcb35[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 36) { + if (md) *md = &sobmhudpipv4_dcb36[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 38) { + if (md) *md = &sobmhudpipv4_dcb38[md_offset]; + } + break; + } + + + if ((hwts == HWTSTAMP_TX_ONESTEP_SYNC) && + BKSYNC_PTP_EVENT_MSG(skb->data[ptp_hdr_offset])) { + /* One Step Timestamp Field updation */ + int corr_offset = ptp_hdr_offset + 8; + int origin_ts_offset = ptp_hdr_offset + 34; + u32 tmp; + struct timespec64 ts; + int udp_csum_regen; + u32 udp_csum20; + u16 udp_csum; + int port; + + udp_csum = SKB_U16_GET(skb, (ptp_hdr_offset - 2)); + + switch (transport) { + case 2: + udp_csum_regen = 0; + break; + case 6: + udp_csum_regen = 1; + break; + default: + udp_csum_regen = (udp_csum != 0x0); + break; + } + + /* Fill the correction field */ + bksync_hton64(&(skb->data[corr_offset]), (const u64 *)&corrField); + + /* Fill the Origin Timestamp Field */ + ts = ns_to_timespec64(ptptime); + + tmp = (ts.tv_sec >> 32); + skb->data[origin_ts_offset + 0] = ((tmp >> 8) & 0xFF); + skb->data[origin_ts_offset + 1] = ((tmp ) & 0xFF); + + tmp = (ts.tv_sec & 0xFFFFFFFFLL); + skb->data[origin_ts_offset + 2] = ((tmp >> 24) & 0xFF); + skb->data[origin_ts_offset + 3] = ((tmp >> 16) & 0xFF); + skb->data[origin_ts_offset + 4] = ((tmp >> 8) & 0xFF); + skb->data[origin_ts_offset + 5] = ((tmp ) & 0xFF); + + tmp = (ts.tv_nsec & 0xFFFFFFFFLL); + skb->data[origin_ts_offset + 6] = ((tmp >> 24) & 0xFF); + skb->data[origin_ts_offset + 7] = ((tmp >> 16) & 0xFF); + skb->data[origin_ts_offset + 8] = ((tmp >> 8) & 0xFF); + skb->data[origin_ts_offset + 9] = ((tmp ) & 0xFF); + + if (udp_csum_regen) { + udp_csum20 = (~udp_csum) & 0xFFFF; + + udp_csum20 += SKB_U16_GET(skb, (corr_offset + 0)); + udp_csum20 += SKB_U16_GET(skb, (corr_offset + 2)); + udp_csum20 += SKB_U16_GET(skb, (corr_offset + 4)); + udp_csum20 += SKB_U16_GET(skb, (corr_offset + 6)); + + udp_csum20 += SKB_U16_GET(skb, (origin_ts_offset + 0)); + udp_csum20 += SKB_U16_GET(skb, (origin_ts_offset + 2)); + udp_csum20 += SKB_U16_GET(skb, (origin_ts_offset + 4)); + udp_csum20 += SKB_U16_GET(skb, (origin_ts_offset + 6)); + udp_csum20 += SKB_U16_GET(skb, (origin_ts_offset + 8)); + + /* Fold 20bit checksum into 16bit udp checksum */ + udp_csum20 = ((udp_csum20 & 0xFFFF) + (udp_csum20 >> 16)); + udp_csum = ((udp_csum20 & 0xFFFF) + (udp_csum20 >> 16)); + + /* invert again to get final checksum. */ + udp_csum = ~udp_csum; + if (udp_csum == 0) { + udp_csum = 0xFFFF; + } + + skb->data[ptp_hdr_offset - 2] = ((udp_csum >> 8) & 0xFF); + skb->data[ptp_hdr_offset - 1] = ((udp_csum ) & 0xFF); + } + + if (skb->data[ptp_hdr_offset] == IEEE1588_MSGTYPE_DELREQ) { + *tstamp = ptptime; + + DBG_VERB(("ptp delay req packet tstamp : 0x%llx corrField: 0x%llx\n", ptptime, corrField)); + } + + port = KNET_SKB_CB(skb)->port; + port -= 1; + ptp_priv->port_stats[port].pkt_txonestep += 1; + } + + return 0; +} + + +int bksync_ptp_hw_tstamp_ptp_clock_index_get(int dev_no) +{ + int phc_index = -1; + if (ptp_priv && ptp_priv->ptp_clock) + phc_index = ptp_clock_index(ptp_priv->ptp_clock); + return phc_index; +} + + +/** +* bcm_ptp_time_keep - call timecounter_read every second to avoid timer overrun +* because a 32bit counter, will timeout in 4s +*/ +static void bksync_ptp_time_keep(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct bksync_ptp_priv *priv = + container_of(dwork, struct bksync_ptp_priv, time_keep); + struct timespec64 ts; + + /* Call bcm_ptp_gettime function to keep the ref_time_64 and ref_counter_48 in sync */ + bksync_ptp_gettime(&(priv->ptp_caps), &ts); + schedule_delayed_work(&priv->time_keep, HZ); +} + +static void bksync_ptp_time_keep_init(void) +{ + if (!ptp_priv->timekeep_status) { + INIT_DELAYED_WORK(&(ptp_priv->time_keep), bksync_ptp_time_keep); + schedule_delayed_work(&ptp_priv->time_keep, HZ); + + ptp_priv->timekeep_status = 1; + } + + return; +} + +static void bksync_ptp_time_keep_deinit(void) +{ + if (ptp_priv->timekeep_status) { + /* Cancel delayed work */ + cancel_delayed_work_sync(&(ptp_priv->time_keep)); + + ptp_priv->timekeep_status = 0; + } + + return; +} + + + +static int bksync_ptp_init(struct ptp_clock_info *ptp) +{ + return bksync_cmd_go(BKSYNC_INIT, NULL, NULL); +} + +static int bksync_ptp_deinit(struct ptp_clock_info *ptp) +{ + bksync_ptp_time_keep_deinit(); + + return bksync_cmd_go(BKSYNC_DEINIT, NULL, NULL); +} + +/* + * Device Debug Statistics Proc Entry + */ +/** +* This function is called at the beginning of a sequence. +* ie, when: +* - the /proc/bcm/ksync/stats file is read (first time) +* - after the function stop (end of sequence) +* +*/ +static void *bksync_proc_seq_start(struct seq_file *s, loff_t *pos) +{ + /* beginning a new sequence ? */ + if ( (int)*pos == 0 && ptp_priv->shared_addr != NULL) + { + seq_printf(s, "TwoStep Port Bitmap : %08llx%08llx\n", + (uint64_t)(ptp_priv->shared_addr->portmap[1]), + (uint64_t)(ptp_priv->shared_addr->portmap[0])); + seq_printf(s,"%4s| %9s| %9s| %9s| %9s| %9s| %9s| %9s| %9s| %9s| %9s| %9s\n", + "Port", "RxCounter", "TxCounter", "TxOneStep", "TSTimeout", "TSRead", "TSMatch", "TSDiscard", + "TimeHi" , "TimeLo", "TimeAvg", "FIFORx"); + } + + if ((int)*pos < (ptp_priv->num_pports)) + return (void *)(unsigned long)(*pos + 1); + /* End of the sequence, return NULL */ + return NULL; +} + +/** +* This function is called after the beginning of a sequence. +* It's called untill the return is NULL (this ends the sequence). +* +*/ +static void *bksync_proc_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + (*pos)++; + return bksync_proc_seq_start(s, pos); +} +/** +* This function is called at the end of a sequence +* +*/ +static void bksync_proc_seq_stop(struct seq_file *s, void *v) +{ + /* nothing to do, we use a static value in bksync_proc_seq_start() */ +} + +/** +* This function is called for each "step" of a sequence +* +*/ +static int bksync_proc_seq_show(struct seq_file *s, void *v) +{ + unsigned long port = (unsigned long)v; + port = port - 1; + if (ptp_priv->port_stats[port].pkt_rxctr || ptp_priv->port_stats[port].pkt_txctr || + ptp_priv->port_stats[port].pkt_txonestep|| + ptp_priv->port_stats[port].tsts_discard || ptp_priv->port_stats[port].tsts_timeout || + ptp_priv->shared_addr->port_ts_data[port].ts_cnt || ptp_priv->port_stats[port].tsts_match) { + seq_printf(s, "%4lu | %9d| %9d| %9d| %9d| %9d| %9d| %9d| %9lld| %9lld | %9d|%9d | %s\n", (port + 1), + ptp_priv->port_stats[port].pkt_rxctr, + ptp_priv->port_stats[port].pkt_txctr, + ptp_priv->port_stats[port].pkt_txonestep, + ptp_priv->port_stats[port].tsts_timeout, + ptp_priv->shared_addr->port_ts_data[port].ts_cnt, + ptp_priv->port_stats[port].tsts_match, + ptp_priv->port_stats[port].tsts_discard, + ptp_priv->port_stats[port].tsts_worst_fetch_time, + ptp_priv->port_stats[port].tsts_best_fetch_time, + ptp_priv->port_stats[port].tsts_avg_fetch_time, + ptp_priv->port_stats[port].fifo_rxctr, + ptp_priv->port_stats[port].pkt_txctr != ptp_priv->port_stats[port].tsts_match ? "***":""); + } + return 0; +} + +/** +* seq_operations for bsync_proc_*** entries +* +*/ +static struct seq_operations bksync_proc_seq_ops = { + .start = bksync_proc_seq_start, + .next = bksync_proc_seq_next, + .stop = bksync_proc_seq_stop, + .show = bksync_proc_seq_show +}; +static int bksync_proc_txts_open(struct inode * inode, struct file * file) +{ + return seq_open(file, &bksync_proc_seq_ops); +} + +static ssize_t +bksync_proc_txts_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + char debug_str[40]; + char *ptr; + int port; + + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + if ((ptr = strstr(debug_str, "clear")) != NULL) { + for (port = 0; port < ptp_priv->num_pports; port++) { + ptp_priv->port_stats[port].pkt_rxctr = 0; + ptp_priv->port_stats[port].pkt_txctr = 0; + ptp_priv->port_stats[port].pkt_txonestep = 0; + ptp_priv->port_stats[port].tsts_timeout = 0; + ptp_priv->port_stats[port].tsts_match = 0; + ptp_priv->port_stats[port].tsts_discard = 0; + if (ptp_priv->shared_addr) + ptp_priv->shared_addr->port_ts_data[port].ts_cnt = 0; + } + } else { + gprintk("Warning: unknown input\n"); + } + + return count; +} + +struct file_operations bksync_proc_txts_file_ops = { + owner: THIS_MODULE, + open: bksync_proc_txts_open, + read: seq_read, + llseek: seq_lseek, + write: bksync_proc_txts_write, + release: seq_release, +}; + +/* + * Driver Debug Proc Entry + */ +static int +bksync_proc_debug_show(struct seq_file *m, void *v) +{ + seq_printf(m, "Configuration:\n"); + seq_printf(m, " debug: 0x%x\n", debug); + return 0; +} + +static ssize_t +bksync_proc_debug_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + char debug_str[40]; + char *ptr; + + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + if ((ptr = strstr(debug_str, "debug=")) != NULL) { + ptr += 6; + debug = simple_strtol(ptr, NULL, 0); + } else { + gprintk("Warning: unknown configuration\n"); + } + + return count; +} + +static int bksync_proc_debug_open(struct inode * inode, struct file * file) +{ + return single_open(file, bksync_proc_debug_show, NULL); +} + + +struct file_operations bksync_proc_debug_file_ops = { + owner: THIS_MODULE, + open: bksync_proc_debug_open, + read: seq_read, + llseek: seq_lseek, + write: bksync_proc_debug_write, + release: single_release, +}; + + +static int +bksync_proc_init(void) +{ + struct proc_dir_entry *entry; + + PROC_CREATE(entry, "stats", 0666, bksync_proc_root, &bksync_proc_txts_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "debug", 0666, bksync_proc_root, &bksync_proc_debug_file_ops); + if (entry == NULL) { + return -1; + } + return 0; +} + +static int +bksync_proc_cleanup(void) +{ + remove_proc_entry("stats", bksync_proc_root); + remove_proc_entry("debug", bksync_proc_root); + return 0; +} + +static void bksync_ptp_dma_init(int dcb_type) +{ + int endianess; + int num_pports = 256; + + + ptp_priv->num_pports = num_pports; + ptp_priv->dcb_type = dcb_type; + ptp_priv->dma_mem_size = 16384;/*sizeof(bksync_uc_linux_ipc_t);*/ + + if (ptp_priv->shared_addr == NULL) { + ptp_priv->shared_addr = kzalloc(16384, GFP_KERNEL); + ptp_priv->port_stats = kzalloc((sizeof(bksync_port_stats_t) * num_pports), GFP_KERNEL); + } + + if (ptp_priv->shared_addr != NULL) { + /* Reset memory. */ + memset((void *)ptp_priv->shared_addr, 0, ptp_priv->dma_mem_size); + +#ifdef __LITTLE_ENDIAN + endianess = 0; +#else + endianess = 1; +#endif + DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_14r(CMIC_CMC_BASE), ((pci_cos << 16) | endianess)); + + DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_15r(CMIC_CMC_BASE), 1); + DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_16r(CMIC_CMC_BASE), 1); + + } + + if (debug & DBG_LVL_VERB) { + printk(KERN_EMERG"%s %p:%p\n",__FUNCTION__, + ptp_priv->base_addr,(void *)ptp_priv->shared_addr); + } + + ptp_priv->mirror_encap_bmp = 0x0; + + hostcmd_regs[0] = CMIC_CMC_SCHAN_MESSAGE_21r(CMIC_CMC_BASE); + hostcmd_regs[1] = CMIC_CMC_SCHAN_MESSAGE_20r(CMIC_CMC_BASE); + hostcmd_regs[2] = CMIC_CMC_SCHAN_MESSAGE_19r(CMIC_CMC_BASE); + hostcmd_regs[3] = CMIC_CMC_SCHAN_MESSAGE_18r(CMIC_CMC_BASE); + hostcmd_regs[4] = CMIC_CMC_SCHAN_MESSAGE_17r(CMIC_CMC_BASE); + + return; +} + + +/** + * bksync_ioctl_cmd_handler + * @kmsg: kcom message - ptp clock ioctl command. + * Description: This function will handle ioctl commands + * from user mode. + */ +static int +bksync_ioctl_cmd_handler(kcom_msg_clock_cmd_t *kmsg, int len, int dcb_type) +{ + u32 fw_status; + kmsg->hdr.type = KCOM_MSG_TYPE_RSP; + + if (!module_initialized && kmsg->clock_info.cmd != KSYNC_M_HW_INIT) { + kmsg->hdr.status = KCOM_E_NOT_FOUND; + return sizeof(kcom_msg_hdr_t); + } + + switch(kmsg->clock_info.cmd) { + case KSYNC_M_HW_INIT: + pci_cos = kmsg->clock_info.data[0]; + if (kmsg->clock_info.data[1] == 0 || kmsg->clock_info.data[1] == 1) { + fw_core = kmsg->clock_info.data[1]; + DEV_READ32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_21r(CMIC_CMC_BASE), &fw_status); + + /* Return success if the app is already initialized. */ + if (module_initialized) { + kmsg->hdr.status = KCOM_E_NONE; + return sizeof(kcom_msg_hdr_t); + } + + /* Return error if the app is not ready yet. */ + if (fw_status != 0xBADC0DE1) { + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + + bksync_ptp_dma_init(dcb_type); + if (bksync_ptp_init(&(ptp_priv->ptp_caps)) >= 0) { + module_initialized = 1; + } + } + break; + case KSYNC_M_HW_DEINIT: + bksync_ptp_deinit(&(ptp_priv->ptp_caps)); + module_initialized = 0; + break; + case KSYNC_M_HW_TS_DISABLE: + bksync_ptp_hw_tstamp_disable(0, kmsg->clock_info.data[0], 0); + break; + case KSYNC_M_MTP_TS_UPDATE_ENABLE: + bksync_ptp_mirror_encap_update(0, kmsg->clock_info.data[0], TRUE); + break; + case KSYNC_M_MTP_TS_UPDATE_DISABLE: + bksync_ptp_mirror_encap_update(0, kmsg->clock_info.data[0], FALSE); + break; + case KSYNC_M_VERSION: + break; + default: + kmsg->hdr.status = KCOM_E_NOT_FOUND; + return sizeof(kcom_msg_hdr_t); + } + + return sizeof(*kmsg); +} + + + +/** + * bksync_ptp_register + * @priv: driver private structure + * Description: this function will register the ptp clock driver + * to kernel. It also does some house keeping work. + */ +static int bksync_ptp_register(void) +{ + int err = -ENODEV; + + /* Support on core-0 or core-1 */ + if (fw_core < 0 || fw_core > 1) { + goto exit; + } + + /* default transport is raw, ieee 802.3 */ + switch (network_transport) { + case 2: /* IEEE 802.3 */ + case 4: /* UDP IPv4 */ + case 6: /* UDP IPv6 */ + break; + default: + network_transport = 0; + } + + ptp_priv = kzalloc(sizeof(*ptp_priv), GFP_KERNEL); + if (!ptp_priv) { + err = -ENOMEM; + goto exit; + } + + /* Reset memory */ + memset(ptp_priv, 0, sizeof(*ptp_priv)); + + err = -ENODEV; + + ptp_priv->ptp_caps = bksync_ptp_caps; + + mutex_init(&(ptp_priv->ptp_lock)); + mutex_init(&(ptp_priv->ptp_pair_lock)); + + /* Register ptp clock driver with bksync_ptp_caps */ + ptp_priv->ptp_clock = ptp_clock_register(&ptp_priv->ptp_caps, NULL); + + /* Initialize the Base address for CMIC and shared Memory access */ + ptp_priv->base_addr = lkbde_get_dev_virt(0); + ptp_priv->dma_dev = lkbde_get_dma_dev(0); + + if (IS_ERR(ptp_priv->ptp_clock)) { + ptp_priv->ptp_clock = NULL; + } else if (ptp_priv->ptp_clock) { + err = 0; + + /* Register BCM-KNET HW Timestamp Callback Functions */ + bkn_hw_tstamp_enable_cb_register(bksync_ptp_hw_tstamp_enable); + bkn_hw_tstamp_disable_cb_register(bksync_ptp_hw_tstamp_disable); + bkn_hw_tstamp_tx_time_get_cb_register(bksync_ptp_hw_tstamp_tx_time_get); + bkn_hw_tstamp_tx_meta_get_cb_register(bksync_ptp_hw_tstamp_tx_meta_get); + bkn_hw_tstamp_rx_time_upscale_cb_register(bksync_ptp_hw_tstamp_rx_time_upscale); + bkn_hw_tstamp_ptp_clock_index_cb_register(bksync_ptp_hw_tstamp_ptp_clock_index_get); + bkn_hw_tstamp_ioctl_cmd_cb_register(bksync_ioctl_cmd_handler); + + } + + /* Initialize proc files */ + bksync_proc_root = proc_mkdir("bcm/ksync", NULL); + bksync_proc_init(); + ptp_priv->shared_addr = NULL; + ptp_priv->port_stats = NULL; +exit: + return err; +} + +static int bksync_ptp_remove(void) +{ + if (!ptp_priv) + return 0; + + bksync_ptp_time_keep_deinit(); + + bksync_proc_cleanup(); + remove_proc_entry("bcm/ksync", NULL); + + /* UnRegister BCM-KNET HW Timestamp Callback Functions */ + bkn_hw_tstamp_enable_cb_unregister(bksync_ptp_hw_tstamp_enable); + bkn_hw_tstamp_disable_cb_unregister(bksync_ptp_hw_tstamp_disable); + bkn_hw_tstamp_tx_time_get_cb_unregister(bksync_ptp_hw_tstamp_tx_time_get); + bkn_hw_tstamp_tx_meta_get_cb_unregister(bksync_ptp_hw_tstamp_tx_meta_get); + bkn_hw_tstamp_rx_time_upscale_cb_unregister(bksync_ptp_hw_tstamp_rx_time_upscale); + bkn_hw_tstamp_ptp_clock_index_cb_unregister(bksync_ptp_hw_tstamp_ptp_clock_index_get); + bkn_hw_tstamp_ioctl_cmd_cb_unregister(bksync_ioctl_cmd_handler); + + if (module_initialized) { + DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_15r(CMIC_CMC_BASE), 0); + DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_16r(CMIC_CMC_BASE), 0); + } + /* Deinitialize the PTP */ + bksync_ptp_deinit(&(ptp_priv->ptp_caps)); + module_initialized = 0; + + if (ptp_priv->port_stats != NULL) { + kfree((void *)ptp_priv->port_stats); + ptp_priv->port_stats = NULL; + } + if (ptp_priv->shared_addr != NULL) { + kfree((void *)ptp_priv->shared_addr); + ptp_priv->shared_addr = NULL; + DBG_ERR(("Free R5 memory\n")); + } + + /* Unregister the bcm ptp clock driver */ + ptp_clock_unregister(ptp_priv->ptp_clock); + + /* Free Memory */ + kfree(ptp_priv); + + return 0; +} +#endif + + +/* + * Generic module functions + */ + +/* + * Function: _pprint + * + * Purpose: + * Print proc filesystem information. + * Parameters: + * None + * Returns: + * Always 0 + */ + static int +_pprint(struct seq_file *m) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,17,0) + /* put some goodies here */ + pprintf(m, "Broadcom BCM PTP Hardware Clock Module\n"); +#else + pprintf(m, "Broadcom BCM PTP Hardware Clock Module not supported\n"); +#endif + return 0; +} + +/* + * Function: _init + * + * Purpose: + * Module initialization. + * Attached SOC all devices and optionally initializes these. + * Parameters: + * None + * Returns: + * 0 on success, otherwise -1 + */ + static int +_init(void) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,17,0) + bksync_ptp_register(); + return 0; +#else + return -1; +#endif +} + +/* + * Function: _cleanup + * + * Purpose: + * Module cleanup function + * Parameters: + * None + * Returns: + * Always 0 + */ + static int +_cleanup(void) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,17,0) + mutex_destroy(&(ptp_priv->ptp_lock)); + mutex_destroy(&(ptp_priv->ptp_pair_lock)); + bksync_ptp_remove(); + return 0; +#else + return -1; +#endif +} + +static gmodule_t _gmodule = { +name: MODULE_NAME, + major: MODULE_MAJOR, + init: _init, + cleanup: _cleanup, + pprint: _pprint, + ioctl: NULL, + open: NULL, + close: NULL, +}; + + gmodule_t* +gmodule_get(void) +{ + EXPORT_NO_SYMBOLS; + return &_gmodule; +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h new file mode 100644 index 000000000000..8d710869824f --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h @@ -0,0 +1,179 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: bcm-knet.h,v 1.4 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ +#ifndef __LINUX_BCM_KNET_H__ +#define __LINUX_BCM_KNET_H__ + +#ifndef __KERNEL__ +#include +#endif + +typedef struct { + int rc; + int len; + int bufsz; + int reserved; + uint64_t buf; +} bkn_ioctl_t; + +#ifdef __KERNEL__ + +/* + * Call-back interfaces for other Linux kernel drivers. + */ +#include +#include +#include + +typedef struct { + uint32 netif_user_data; + uint32 filter_user_data; + uint16 dcb_type; + int port; + uint64_t ts; + uint32 hwts; +} knet_skb_cb_t; + +#define KNET_SKB_CB(_skb) ((knet_skb_cb_t *)_skb->cb) + +typedef struct sk_buff * +(*knet_skb_cb_f)(struct sk_buff *skb, int dev_no, void *meta); + +typedef int +(*knet_filter_cb_f)(uint8_t *pkt, int size, int dev_no, void *meta, + int chan, kcom_filter_t *filter); + +typedef int +(*knet_hw_tstamp_enable_cb_f)(int dev_no, int phys_port, int tx_type); + +typedef int +(*knet_hw_tstamp_tx_time_get_cb_f)(int dev_no, int phys_port, uint8_t *pkt, uint64_t *ts); + +typedef int +(*knet_hw_tstamp_tx_meta_get_cb_f)(int dev_no, int hwts, int hdrlen, struct sk_buff *skb, uint64_t *ts, uint32_t **md); + +typedef int +(*knet_hw_tstamp_ptp_clock_index_cb_f)(int dev_no); + +typedef int +(*knet_hw_tstamp_rx_time_upscale_cb_f)(int dev_no, int phys_port, struct sk_buff *skb, uint32_t *meta, uint64_t *ts); + +typedef int +(*knet_hw_tstamp_ioctl_cmd_cb_f)(kcom_msg_clock_cmd_t *kmsg, int len, int dcb_type); + +extern int +bkn_rx_skb_cb_register(knet_skb_cb_f rx_cb); + +extern int +bkn_rx_skb_cb_unregister(knet_skb_cb_f rx_cb); + +extern int +bkn_tx_skb_cb_register(knet_skb_cb_f tx_cb); + +extern int +bkn_tx_skb_cb_unregister(knet_skb_cb_f tx_cb); + +extern int +bkn_filter_cb_register(knet_filter_cb_f filter_cb); + +extern int +bkn_filter_cb_unregister(knet_filter_cb_f filter_cb); + +extern int +bkn_hw_tstamp_enable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb); + +extern int +bkn_hw_tstamp_enable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb); + +extern int +bkn_hw_tstamp_disable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb); + +extern int +bkn_hw_tstamp_disable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb); + +extern int +bkn_hw_tstamp_tx_time_get_cb_register(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb); + +extern int +bkn_hw_tstamp_tx_time_get_cb_unregister(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb); + +extern int +bkn_hw_tstamp_tx_meta_get_cb_register(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb); + +extern int +bkn_hw_tstamp_tx_meta_get_cb_unregister(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb); + +extern int +bkn_hw_tstamp_ptp_clock_index_cb_register(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb); + +extern int +bkn_hw_tstamp_ptp_clock_index_cb_unregister(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb); + +extern int +bkn_hw_tstamp_rx_time_upscale_cb_register(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb); + +extern int +bkn_hw_tstamp_rx_time_upscale_cb_unregister(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb); + +extern int +bkn_hw_tstamp_ioctl_cmd_cb_register(knet_hw_tstamp_ioctl_cmd_cb_f hw_tstamp_ioctl_cmd_cb); + +extern int +bkn_hw_tstamp_ioctl_cmd_cb_unregister(knet_hw_tstamp_ioctl_cmd_cb_f hw_tstamp_ioctl_cmd_cb); +typedef struct { + uint8 cmic_type; + uint8 dcb_type; + uint8 dcb_size; + uint8 pkt_hdr_size; + uint32 cdma_channels; +} knet_hw_info_t; + +extern int +bkn_hw_info_get(int unit, knet_hw_info_t *hw_info); + +typedef int +(*knet_netif_cb_f)(int unit, kcom_netif_t *netif, struct net_device *dev); + +extern int +bkn_netif_create_cb_register(knet_netif_cb_f netif_cb); + +extern int +bkn_netif_create_cb_unregister(knet_netif_cb_f netif_cb); + +extern int +bkn_netif_destroy_cb_register(knet_netif_cb_f netif_cb); + +extern int +bkn_netif_destroy_cb_unregister(knet_netif_cb_f netif_cb); + +#endif + +#endif /* __LINUX_BCM_KNET_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/gmodule.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/gmodule.h new file mode 100644 index 000000000000..a9db097f3062 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/gmodule.h @@ -0,0 +1,75 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: gmodule.h,v 1.9 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef __COMMON_LINUX_KRN_GMODULE_H__ +#define __COMMON_LINUX_KRN_GMODULE_H__ + +#include +#include + +typedef struct gmodule_s { + + const char* name; + int major; + int minor; + + int (*init)(void); + int (*cleanup)(void); + int (*pprint)(struct seq_file *m); + int (*open)(void); + int (*ioctl)(unsigned int cmd, unsigned long arg); + int (*close)(void); + int (*mmap) (struct file *filp, struct vm_area_struct *vma); + +} gmodule_t; + + +/* The framework will ask for your module definition */ +extern gmodule_t* gmodule_get(void); + + +/* Proc Filesystem information */ +extern int pprintf(struct seq_file *m, const char* fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int gmodule_vpprintf(char** page, const char* fmt, va_list args) + __attribute__ ((format (printf, 2, 0))); +extern int gmodule_pprintf(char** page, const char* fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +extern int gprintk(const char* fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +extern int gdbg(const char* fmt, ...) + __attribute__ ((format (printf, 1, 2))); +#define GDBG gdbg + +#endif /* __COMMON_LINUX_KRN_GMODULE_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/lkm.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/lkm.h new file mode 100644 index 000000000000..9ea8fc5896d8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/lkm.h @@ -0,0 +1,199 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: lkm.h,v 1.22 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#ifndef __COMMON_LINUX_KRN_LKM_H__ +#define __COMMON_LINUX_KRN_LKM_H__ + +#ifndef __KERNEL__ +# define __KERNEL__ +#endif +#ifndef MODULE +# define MODULE +#endif + +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +/* The version kconfig.h became available in. */ +#include +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#if defined(INCLUDE_KNET) && LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) +#ifdef CONFIG_NF_CONNTRACK_MODULE +#include +#endif +#endif +#include +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) +#include +#endif +#include + +/* Helper defines for multi-version kernel support */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#define LKM_2_4 +#else +#define LKM_2_6 +#endif + +#include /* printk() */ +#include /* everything... */ +#include /* error codes */ +#include /* size_t */ +#include +#include /* O_ACCMODE */ +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0) +#include +#endif +#include + +#include +#include +#include + +#ifdef CONFIG_DEVFS_FS +#include +#endif + +#define PROC_INTERFACE_KERN_VER_3_10 (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) + +/* Compatibility Macros */ + +#ifdef LKM_2_4 + +#include +#include +#define LKM_MOD_PARAM(n,ot,nt,d) MODULE_PARM(n,ot) +#define LKM_MOD_PARAM_ARRAY(n,ot,nt,c,d) MODULE_PARM(n,ot) +#define LKM_EXPORT_SYM(s) +#define _free_netdev kfree + +#else /* LKM_2_6 */ + +#define LKM_MOD_PARAM(n,ot,nt,d) module_param(n,nt,d) +#define LKM_MOD_PARAM_ARRAY(n,ot,nt,c,d) module_param_array(n,nt,c,d) +#define LKM_EXPORT_SYM(s) EXPORT_SYMBOL(s) +#define _free_netdev free_netdev + +#endif /* LKM_2_x */ + +#ifndef list_for_each_safe +#define list_for_each_safe(l,t,i) t = 0; list_for_each((l),(i)) +#endif + +#ifndef reparent_to_init +#define reparent_to_init() +#endif + +#ifndef MODULE_LICENSE +#define MODULE_LICENSE(str) +#endif + +#ifndef EXPORT_NO_SYMBOLS +#define EXPORT_NO_SYMBOLS +#endif + +#ifndef DEFINE_SPINLOCK +#define DEFINE_SPINLOCK(_lock) spinlock_t _lock = SPIN_LOCK_UNLOCKED +#endif + +#ifndef __SPIN_LOCK_UNLOCKED +#define __SPIN_LOCK_UNLOCKED(_lock) SPIN_LOCK_UNLOCKED +#endif + +#ifndef lock_kernel +#ifdef preempt_disable +#define lock_kernel() preempt_disable() +#else +#define lock_kernel() +#endif +#endif + +#ifndef unlock_kernel +#ifdef preempt_enable +#define unlock_kernel() preempt_enable() +#else +#define unlock_kernel() +#endif +#endif + +#ifndef init_MUTEX_LOCKED +#define init_MUTEX_LOCKED(_sem) sema_init(_sem, 0) +#endif + +#ifdef CONFIG_BCM98245 +#define CONFIG_BMW +#endif + +#if PROC_INTERFACE_KERN_VER_3_10 +#define PROC_CREATE(_entry, _name, _acc, _path, _fops) \ + do { \ + _entry = proc_create(_name, _acc, _path, _fops); \ + } while (0) + +#define PROC_CREATE_DATA(_entry, _name, _acc, _path, _fops, _data) \ + do { \ + _entry = proc_create_data(_name, _acc, _path, _fops, _data); \ + } while (0) + +#define PROC_PDE_DATA(_node) PDE_DATA(_node) + +#else +#define PROC_CREATE(_entry, _name, _acc, _path, _fops) \ + do { \ + _entry = create_proc_entry(_name, _acc, _path); \ + if (_entry) { \ + _entry->proc_fops = _fops; \ + } \ + } while (0) + +#define PROC_CREATE_DATA(_entry, _name, _acc, _path, _fops, _data) \ + do { \ + _entry = create_proc_entry(_name, _acc, _path); \ + if (_entry) { \ + _entry->proc_fops = _fops; \ + _entry->data=_data; \ + } \ + } while (0) + +#define PROC_PDE_DATA(_node) PROC_I(_node)->pde->data +#endif + +#endif /* __COMMON_LINUX_KRN_LKM_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/net/psample.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/net/psample.h new file mode 100644 index 000000000000..57c000785e9c --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/net/psample.h @@ -0,0 +1,24 @@ +#ifndef __NET_PSAMPLE_H +#define __NET_PSAMPLE_H + +#include +#include +#include +#include + +struct psample_group { + struct list_head list; + struct net *net; + u32 group_num; + u32 refcount; + u32 seq; +}; + +extern struct psample_group *psample_group_get(struct net *net, u32 group_num); +extern void psample_group_put(struct psample_group *group); + +extern void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, + u32 trunc_size, int in_ifindex, int out_ifindex, + u32 sample_rate); + +#endif /* __NET_PSAMPLE_H */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/uapi/linux/psample.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/uapi/linux/psample.h new file mode 100644 index 000000000000..ed48996ec0e8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/uapi/linux/psample.h @@ -0,0 +1,35 @@ +#ifndef __UAPI_PSAMPLE_H +#define __UAPI_PSAMPLE_H + +enum { + /* sampled packet metadata */ + PSAMPLE_ATTR_IIFINDEX, + PSAMPLE_ATTR_OIFINDEX, + PSAMPLE_ATTR_ORIGSIZE, + PSAMPLE_ATTR_SAMPLE_GROUP, + PSAMPLE_ATTR_GROUP_SEQ, + PSAMPLE_ATTR_SAMPLE_RATE, + PSAMPLE_ATTR_DATA, + + /* commands attributes */ + PSAMPLE_ATTR_GROUP_REFCOUNT, + + __PSAMPLE_ATTR_MAX +}; + +enum psample_command { + PSAMPLE_CMD_SAMPLE, + PSAMPLE_CMD_GET_GROUP, + PSAMPLE_CMD_NEW_GROUP, + PSAMPLE_CMD_DEL_GROUP, +}; + +/* Can be overridden at runtime by module option */ +#define PSAMPLE_ATTR_MAX (__PSAMPLE_ATTR_MAX - 1) + +#define PSAMPLE_NL_MCGRP_CONFIG_NAME "config" +#define PSAMPLE_NL_MCGRP_SAMPLE_NAME "packets" +#define PSAMPLE_GENL_NAME "psample" +#define PSAMPLE_GENL_VERSION 1 + +#endif diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile new file mode 100644 index 000000000000..b8697731dd4e --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile @@ -0,0 +1,78 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/linux/kernel/modules/knet-cb + +include ${SDK}/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +ifeq ($(kernel_version),2_4) +MODULE = $(LIBDIR)/linux-knet-cb.o +else +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := linux-knet-cb +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: $(MODULE) $(KMODULE) +endif + +KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../bcm-knet/kernel_module/Module.symvers +ifeq ($(BUILD_PSAMPLE),1) +KBUILD_EXTRA_SYMBOLS += ${BLDDIR}/../psample/kernel_module/Module.symvers +endif + +# BCM Network Device + +$(MODULE): $(BLDDIR)/.tree $(BOBJS) $(LIBS) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + cat ${KBUILD_EXTRA_SYMBOLS} > $(BLDDIR)/$(KERNEL_MODULE_DIR)/Module.symvers + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +include ${SDK}/make/Make.depend + +clean:: + $(RM) $(BLDDIR)/version.c $(BLDDIR)/version.o + $(RM) $(BOBJS) $(MODULE) + +ifneq ($(kernel_version),2_4) +.PHONY: build +endif diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c new file mode 100644 index 000000000000..650a4ced1d7a --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c @@ -0,0 +1,442 @@ +/* + * Copyright 2017-2019 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: $ + * $Copyright: (c) 2017 Broadcom Corp. + * All Rights Reserved.$ + */ + +/* + * Driver for call-back functions for Linux KNET driver. + * + * This is sample code that demonstrates how to selectively strip VLAN tags + * from an incoming packet based on tag information in the DMA control block + * (DCB). The switch will automatically add a VLAN tag to packets that ingress + * without an outer VLAN tag. Outer tagged and double tagged packets are + * not modified. The call back defined here determines which packets have + * had tags added by those and strips only those tags from the packet. + * + * This is sample code, the customer is responsible for maintaining and + * modifying this code as necessary. + * + * The module can be built from the standard Linux user mode target + * directories using the following command (assuming bash), e.g. + * + * cd $SDK/systems/linux/user/ + * make BUILD_KNET_CB=1 + * + */ + +#include /* Must be included first */ +#include +#include +#include + +/* Enable sflow sampling using psample */ +#ifdef PSAMPLE_SUPPORT +#include "psample-cb.h" +#endif + +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Broadcom Linux KNET Call-Back Driver"); +MODULE_LICENSE("GPL"); + +int debug; +LKM_MOD_PARAM(debug, "i", int, 0); +MODULE_PARM_DESC(debug, +"Debug level (default 0)"); + +static int tpid=0x8100; +LKM_MOD_PARAM(tpid, "i", int, 0); +MODULE_PARM_DESC(debug, +"Tag Protocol Identifier (TPID) indicates the frame type (default 0x8100)"); + +static int pri=0; +LKM_MOD_PARAM(pri, "i", int, 0); +MODULE_PARM_DESC(pri, +"Priority (PRI) indicates the frame priority (default 0)"); + +static int cfi=0; +LKM_MOD_PARAM(cfi, "i", int, 0); +MODULE_PARM_DESC(cfi, +"Canonical Format Indicator (CFI) indicates whether a MAC address is encapsulated in canonical format over different transmission media (default 0)"); + +static int vid=0; +LKM_MOD_PARAM(vid, "i", int, 0); +MODULE_PARM_DESC(vid, +"VLAN ID (VID) indicates the VLAN to which a frame belongs (default 0)"); + +/* Module Information */ +#define MODULE_MAJOR 121 +#define MODULE_NAME "linux-knet-cb" + +/* set KNET_CB_DEBUG for debug info */ +#define KNET_CB_DEBUG + +/* These below need to match incoming enum values */ +#define FILTER_TAG_STRIP 0 +#define FILTER_TAG_KEEP 1 +#define FILTER_TAG_ORIGINAL 2 + +/* Maintain tag strip statistics */ +struct strip_stats_s { + unsigned long stripped; /* Number of packets that have been stripped */ + unsigned long checked; + unsigned long skipped; +}; + +static struct strip_stats_s strip_stats; + +/* Local function prototypes */ +static void strip_vlan_tag(struct sk_buff *skb); +static int get_tag_status(int dcb_type, void *meta); +static struct sk_buff *strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *meta); +static struct sk_buff *strip_tag_tx_cb(struct sk_buff *skb, int dev_no, void *meta); +static int strip_tag_filter_cb(uint8_t * pkt, int size, int dev_no, void *meta, + int chan, kcom_filter_t * kf); +static int _pprint(struct seq_file *m); +static int _cleanup(void); +static int _init(void); + +/* Remove VLAN tag for select TPIDs */ +static void +strip_vlan_tag(struct sk_buff *skb) +{ + uint16_t vlan_proto = (uint16_t) ((skb->data[12] << 8) | skb->data[13]); + if ((vlan_proto == 0x8100) || (vlan_proto == 0x88a8) || (vlan_proto == 0x9100)) { + /* Move first 12 bytes of packet back by 4 */ + ((u32 *) skb->data)[3] = ((u32 *) skb->data)[2]; + ((u32 *) skb->data)[2] = ((u32 *) skb->data)[1]; + ((u32 *) skb->data)[1] = ((u32 *) skb->data)[0]; + skb_pull(skb, 4); /* Remove 4 bytes from start of buffer */ + } +} + +/* Add VLAN tag to untagged packet */ +static void +add_vlan_tag(struct sk_buff *skb, u32 forward_domain) +{ + u32 vlan = 0; + uint16_t vlan_proto = (uint16_t) ((skb->data[12] << 8) | skb->data[13]); + + if ((vlan_proto != 0x8100) && (vlan_proto != 0x88a8) && (vlan_proto != 0x9100)) { + /* If vid is specified, use configued vid as VLAN ID, or, use forward_domain as vid */ + vlan = vid ? vid: forward_domain; + + skb_push(skb, 4); /* Add 4 bytes from start of buffer */ + /* Move first 12 bytes of packet forward by 4 */ + ((u32 *) skb->data)[0] = ((u32 *) skb->data)[1]; + ((u32 *) skb->data)[1] = ((u32 *) skb->data)[2]; + ((u32 *) skb->data)[2] = ((u32 *) skb->data)[3]; + + /* Set VLAN tag */ + skb->data[12] = (tpid >> 8) & 0xff; + skb->data[13] = tpid & 0xff; + skb->data[14] = (((pri & 0x7) << 5) | ((cfi & 0x1) << 4) | ((vlan >> 8) & 0xf)) & 0xff; + skb->data[15] = vlan & 0xff; + } +} + +/* + * Location of tagging status in select DCB types found below: + * + * DCB type 14: word 12, bits 10.11 + * DCB type 19, 20, 21, 22, 30: word 12, bits 10..11 + * DCB type 23, 29: word 13, bits 0..1 + * DCB type 31, 34, 37: word 13, bits 0..1 + * DCB type 26, 32, 33, 35: word 13, bits 0..1 + * + * The function get_tag_status() returns the tag status for known DCB types. + * 0 = Untagged + * 1 = Single inner-tag + * 2 = Single outer-tag + * 3 = Double tagged. + * 4 = Dedicated for Dune device, packets are received with original tag status. + * -1 = Unsupported DCB type + */ +static int +get_tag_status(int dcb_type, void *meta) +{ + uint32 *dcb = (uint32 *) meta; + int tag_status; + switch (dcb_type) { + case 14: + case 19: + case 20: + case 21: + case 22: + case 30: + tag_status = (dcb[12] > 10) & 0x3; + break; + case 23: + case 29: + case 31: + case 34: + case 37: + case 26: + case 32: + case 33: + case 35: + tag_status = dcb[13] & 0x3; + break; + case 36: + /* TD3 */ + tag_status = ((dcb[13] >> 9) & 0x3); + break; + break; + case 38: + { + /* untested */ + /* TH3 only parses outer tag. */ + const int tag_map[4] = { 0, 2, -1, -1 }; + tag_status = tag_map[(dcb[9] >> 13) & 0x3]; + } + break; + case 28: + case 39: + tag_status = 4; + break; + break; + default: + tag_status = -1; + break; + } +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + gprintk("%s; DCB Type: %d; tag status: %d\n", __func__, dcb_type, tag_status); + } +#endif + return tag_status; +} + +/* Rx packet callback function */ +static struct sk_buff * +strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *meta) +{ + unsigned netif_flags = KNET_SKB_CB(skb)->netif_user_data; + unsigned filter_flags = KNET_SKB_CB(skb)->filter_user_data; + unsigned dcb_type; + int tag_status; + unsigned int strip_tag = 0; + /* Currently not using filter flags: + * unsigned filter_flags = KNET_SKB_CB(skb)->filter_user_data; + */ + +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + gprintk("%s Enter; netif Flags: %08X filter_flags %08X \n", + __func__, netif_flags, filter_flags); + } +#endif + /* Get DCB type for this packet, passed by KNET driver */ + dcb_type = KNET_SKB_CB(skb)->dcb_type; + + /* KNET implements this already */ + if (filter_flags == FILTER_TAG_KEEP) + { + if (dcb_type ==28 || dcb_type == 39) + { + uint32 *meta_buffer = (uint32 *)meta; + uint32 forward_domain = meta_buffer[1] & 0xffff; + add_vlan_tag(skb, forward_domain); + } + strip_stats.skipped++; + return skb; + } + + /* SAI strip implies always strip. If the packet is untagged or + inner taged, SDK adds a .1q tag, so we need to strip tag + anyway */ + if (filter_flags == FILTER_TAG_STRIP) + { + strip_tag = 1; + } + + + + /* Get tag status from DCB */ + tag_status = get_tag_status(dcb_type, meta); +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + gprintk("%s; DCB Type: %d; tag status: %d\n", __func__, dcb_type, tag_status); + } +#endif + if (tag_status < 0) { + /* Unsupported DCB type */ + return skb; + } + + if (filter_flags == FILTER_TAG_ORIGINAL) + { + /* If untagged or single inner, strip the extra tag that knet + keep tag will add. */ + if (tag_status < 2) + { + strip_tag = 1; + } + } + + strip_stats.checked++; + + if (strip_tag) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + gprintk("%s; Stripping VLAN tag\n", __func__); + } +#endif + strip_stats.stripped++; + strip_vlan_tag(skb); + } +#ifdef KNET_CB_DEBUG + else { + if (debug & 0x1) { + gprintk("%s; Keeping VLAN tag\n", __func__); + } + } +#endif + + return skb; +} + +/* Tx callback not used */ +static struct sk_buff * +strip_tag_tx_cb(struct sk_buff *skb, int dev_no, void *meta) +{ + /* Pass through for now */ + return skb; +} + +/* Filter callback not used */ +static int +strip_tag_filter_cb(uint8_t * pkt, int size, int dev_no, void *meta, + int chan, kcom_filter_t *kf) +{ + /* Pass through for now */ + return 0; +} + +static int +knet_filter_cb(uint8_t * pkt, int size, int dev_no, void *meta, + int chan, kcom_filter_t *kf) +{ + /* check for filter callback handler */ + #ifdef PSAMPLE_SUPPORT + if (strncmp(kf->desc, PSAMPLE_CB_NAME, KCOM_FILTER_DESC_MAX) == 0) { + return psample_filter_cb (pkt, size, dev_no, meta, chan, kf); + } + #endif + return strip_tag_filter_cb (pkt, size, dev_no, meta, chan, kf); +} + +static int +knet_netif_create_cb(int unit, kcom_netif_t *netif, struct net_device *dev) +{ + int retv = 0; +#ifdef PSAMPLE_SUPPORT + retv = psample_netif_create_cb(unit, netif, dev); +#endif + return retv; +} + +static int +knet_netif_destroy_cb(int unit, kcom_netif_t *netif, struct net_device *dev) +{ + int retv = 0; +#ifdef PSAMPLE_SUPPORT + retv = psample_netif_destroy_cb(unit, netif, dev); +#endif + return retv; +} + +/* + * Get statistics. + * % cat /proc/linux-knet-cb + */ +static int +_pprint(struct seq_file *m) +{ + pprintf(m, "Broadcom Linux KNET Call-Back: Untagged VLAN Stripper\n"); + pprintf(m, " %lu stripped packets\n", strip_stats.stripped); + pprintf(m ," %lu packets checked\n", strip_stats.checked); + pprintf(m, " %lu packets skipped\n", strip_stats.skipped); + + return 0; +} + +static int +_cleanup(void) +{ + bkn_rx_skb_cb_unregister(strip_tag_rx_cb); + /* strip_tag_tx_cb is currently a noop, so + * no need to unregister. + */ + if (0) + { + bkn_tx_skb_cb_unregister(strip_tag_tx_cb); + } + + bkn_filter_cb_unregister(knet_filter_cb); + bkn_netif_create_cb_unregister(knet_netif_create_cb); + bkn_netif_destroy_cb_unregister(knet_netif_destroy_cb); + +#ifdef PSAMPLE_SUPPORT + psample_cleanup(); +#endif + + return 0; +} + +static int +_init(void) +{ + bkn_rx_skb_cb_register(strip_tag_rx_cb); + /* strip_tag_tx_cb is currently a noop, so + * no need to register. + */ + if (0) + { + bkn_tx_skb_cb_register(strip_tag_tx_cb); + } + + #ifdef PSAMPLE_SUPPORT + psample_init(); + #endif + + + bkn_filter_cb_register(knet_filter_cb); + bkn_netif_create_cb_register(knet_netif_create_cb); + bkn_netif_destroy_cb_register(knet_netif_destroy_cb); + + return 0; +} + +static gmodule_t _gmodule = { + name: MODULE_NAME, + major: MODULE_MAJOR, + init: _init, + cleanup: _cleanup, + pprint: _pprint, + ioctl: NULL, + open: NULL, + close: NULL, +}; + +gmodule_t* +gmodule_get(void) +{ + EXPORT_NO_SYMBOLS; + return &_gmodule; +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c new file mode 100644 index 000000000000..755955b20fdd --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c @@ -0,0 +1,1081 @@ +/* + * Copyright 2017-2019 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: psample_cb.c $ + * $Copyright: (c) 2019 Broadcom Corp. + * All Rights Reserved.$ + */ + +/* + * Driver for call-back functions for Linux KNET driver. + * + * This code is used to integrate packet sampling KNET callback to + * the psample infra for sending sampled pkts to userspace sflow + * applications such as Host Sflow (https://github.com/sflow/host-sflow) + * using genetlink interfaces. + * + * The module can be built from the standard Linux user mode target + * directories using the following command (assuming bash), e.g. + * + * cd $SDK/systems/linux/user/ + * make BUILD_KNET_CB=1 + * + */ + +#include /* Must be included first */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "psample-cb.h" + +#define PSAMPLE_CB_DBG +#ifdef PSAMPLE_CB_DBG +extern int debug; +#define PSAMPLE_CB_DBG_PRINT(...) \ + if (debug & 0x1) { \ + gprintk(__VA_ARGS__); \ + } +#else +#define PSAMPLE_CB_DBG_PRINT(...) +#endif + +/* HIGIG2 header fields */ +#define SOC_HIGIG_SOP (0xfb) +#define SOC_HIGIG_START(x) ((x[0] >> 24) & 0xff) +#define SOC_HIGIG_DSTPORT(x) ((x[1] >> 11) & 0x1f) +#define SOC_HIGIG_SRCPORT(x) ((x[1] >> 16) & 0x1f) +#define SOC_HIGIG2_SOP (0xfb) //0xfc - TODO: how can we differentiate between Higig and higig2? +#define SOC_HIGIG2_START(x) ((x[0] >> 24) & 0xff) +#define SOC_HIGIG2_IS_MC(x) ((x[0] >> 20) & 0x1) +#define SOC_HIGIG2_DSTPORT(x) ((x[0] >> 0) & 0xff) +#define SOC_HIGIG2_SRCPORT(x) ((x[1] >> 16) & 0xff) +#define SOC_DCB32_HG_OFFSET (6) + +/* sFlow v5 datagram dst ifindex field type + * dst ifindex encoding bits [31:30] + */ +#define DSTPORT_TYPE_DISCARD 1 +#define DSTPORT_TYPE_MC 2 + +#define DSTPORT_TYPE_OFFSET 30 +#define DSTPORT_TYPE_MASK 0x3 +#define DSTPORT_TYPE_CLR(_dst) (_dst &= ~(DSTPORT_TYPE_MASK << DSTPORT_TYPE_OFFSET)) +#define DSTPORT_TYPE_SET(_dst,_type) (_dst |= ((_type & DSTPORT_TYPE_MASK) << DSTPORT_TYPE_OFFSET)) +#define DSTPORT_TYPE_GET(_dst) ((_dst >> DSTPORT_TYPE_OFFSET) & DSTPORT_TYPE_MASK) +#define DSTPORT_GET(_dst) (_dst & ~(DSTPORT_TYPE_MASK << DSTPORT_TYPE_OFFSET)) + +#define FCS_SZ 4 +#define PSAMPLE_NLA_PADDING 4 + +#define PSAMPLE_RATE_DFLT 1 +#define PSAMPLE_SIZE_DFLT 128 +static int psample_size = PSAMPLE_SIZE_DFLT; +LKM_MOD_PARAM(psample_size, "i", int, 0); +MODULE_PARM_DESC(psample_size, +"psample pkt size (default 128 bytes)"); + +#define PSAMPLE_QLEN_DFLT 1024 +static int psample_qlen = PSAMPLE_QLEN_DFLT; +LKM_MOD_PARAM(psample_qlen, "i", int, 0); +MODULE_PARM_DESC(psample_qlen, +"psample queue length (default 1024 buffers)"); + +/* driver proc entry root */ +static struct proc_dir_entry *psample_proc_root = NULL; +static struct proc_dir_entry *knet_cb_proc_root = NULL; + +/* psample general info */ +typedef struct { + struct list_head netif_list; + int netif_count; + knet_hw_info_t hw; + struct net *netns; + spinlock_t lock; +} psample_info_t; +static psample_info_t g_psample_info = {0}; + +/* Maintain sampled pkt statistics */ +typedef struct psample_stats_s { + unsigned long pkts_f_psample_cb; + unsigned long pkts_f_psample_mod; + unsigned long pkts_f_handled; + unsigned long pkts_f_pass_through; + unsigned long pkts_f_dst_mc; + unsigned long pkts_c_qlen_cur; + unsigned long pkts_c_qlen_hi; + unsigned long pkts_d_qlen_max; + unsigned long pkts_d_no_mem; + unsigned long pkts_d_no_group; + unsigned long pkts_d_sampling_disabled; + unsigned long pkts_d_not_ready; + unsigned long pkts_d_metadata; + unsigned long pkts_d_meta_srcport; + unsigned long pkts_d_meta_dstport; + unsigned long pkts_d_invalid_size; +} psample_stats_t; +static psample_stats_t g_psample_stats = {0}; + +typedef struct psample_meta_s { + int trunc_size; + int src_ifindex; + int dst_ifindex; + int sample_rate; +} psample_meta_t; + +typedef struct psample_pkt_s { + struct list_head list; + struct psample_group *group; + psample_meta_t meta; + struct sk_buff *skb; +} psample_pkt_t; + +typedef struct psample_work_s { + struct list_head pkt_list; + struct work_struct wq; + spinlock_t lock; +} psample_work_t; +static psample_work_t g_psample_work = {0}; + +static psample_netif_t* +psample_netif_lookup_by_port(int unit, int port) +{ + struct list_head *list; + psample_netif_t *psample_netif = NULL; + unsigned long flags; + + /* look for port from list of available net_devices */ + spin_lock_irqsave(&g_psample_info.lock, flags); + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (psample_netif->port == port) { + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return psample_netif; + } + } + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return (NULL); +} + +static int +psample_info_get (int unit, psample_info_t *psample_info) +{ + int rv = 0; + if (!psample_info) { + gprintk("%s: psample_info is NULL\n", __func__); + return (-1); + } + + /* get hw info */ + rv = bkn_hw_info_get(unit, &psample_info->hw); + if (rv < 0) { + gprintk("%s: failed to get hw info\n", __func__); + return (-1); + } + + PSAMPLE_CB_DBG_PRINT("%s: DCB type %d\n", + __func__, psample_info->hw.dcb_type); + return (0); +} + +static int +psample_meta_srcport_get(uint8_t *pkt, void *pkt_meta) +{ + int srcport = 0; + uint32_t *metadata = (uint32_t*)pkt_meta; + + switch(g_psample_info.hw.dcb_type) { + case 36: /* TD3 */ + case 38: /* TH3 */ + break; + case 32: /* TH1/TH2 */ + case 26: /* TD2 */ + case 23: /* HX4 */ + metadata += SOC_DCB32_HG_OFFSET; + default: + break; + } + + if (SOC_HIGIG2_START(metadata) == SOC_HIGIG2_SOP) + { + srcport = SOC_HIGIG2_SRCPORT(metadata); + } + else if (SOC_HIGIG_START(metadata) == SOC_HIGIG_SOP) + { + srcport = SOC_HIGIG_SRCPORT(metadata); + } + else + { + PSAMPLE_CB_DBG_PRINT("%s: Could not detect metadata sop type: 0x%02x (w[0]: 0x%04x)\n", __func__, + SOC_HIGIG_START(metadata), metadata[0]); + return -1; + } + return srcport; +} + +static int +psample_meta_dstport_get(uint8_t *pkt, void *pkt_meta) +{ + int dstport = 0; + uint32_t *metadata = (uint32_t*)pkt_meta; + + switch(g_psample_info.hw.dcb_type) { + case 36: /* TD3 */ + case 38: /* TH3 */ + break; + case 32: /* TH1/TH2 */ + case 26: /* TD2 */ + case 23: /* HX4 */ + default: + metadata += SOC_DCB32_HG_OFFSET; + break; + } + + if (SOC_HIGIG2_START(metadata) == SOC_HIGIG2_SOP) + { + if (SOC_HIGIG2_IS_MC(metadata)) + { + DSTPORT_TYPE_CLR(dstport); + DSTPORT_TYPE_SET(dstport, DSTPORT_TYPE_MC); + } + else + { + dstport = SOC_HIGIG2_DSTPORT(metadata); + } + } + else if (SOC_HIGIG_START(metadata) == SOC_HIGIG_SOP) + { + dstport = SOC_HIGIG_DSTPORT(metadata); + } + else + { + PSAMPLE_CB_DBG_PRINT("%s: Could not detect metadata sop type: 0x%02x (w[0]: 0x%04x)\n", __func__, + SOC_HIGIG_START(metadata), metadata[0]); + return (-1); + } + return dstport; +} + +static int +psample_meta_sample_reason(uint8_t *pkt, void *pkt_meta) +{ + uint32_t *metadata = (uint32_t*)pkt_meta; + uint32_t reason = 0; + uint32_t reason_hi = 0; + uint32_t sample_rx_reason_mask = 0; + + /* Sample Pkt reason code (bcmRxReasonSampleSource) */ + switch(g_psample_info.hw.dcb_type) { + case 36: /* TD3 */ + case 38: /* TH3 */ + reason_hi = *(metadata + 4); + reason = *(metadata + 5); + sample_rx_reason_mask = (1 << 3); + break; + case 32: /* TH1/TH2 */ + case 26: /* TD2 */ + case 23: /* HX4 */ + default: + reason_hi = *(metadata + 2); + reason = *(metadata + 3); + sample_rx_reason_mask = (1 << 5); + break; + } + + PSAMPLE_CB_DBG_PRINT("%s: DCB%d sample_rx_reason_mask: 0x%08x, reason: 0x%08x, reason_hi: 0x%08x\n", + __func__, g_psample_info.hw.dcb_type, sample_rx_reason_mask, reason, reason_hi); + + /* Check if only sample reason code is set. + * If only sample reason code, then consume pkt. + * If other reason codes exist, then pkt should be + * passed through to Linux network stack. + */ + if ((reason & ~sample_rx_reason_mask) || reason_hi) { + return 0; /* multiple reasons set, pass through */ + } + + /* only sample rx reason set, consume pkt */ + return (1); +} + +static int +psample_meta_get(int unit, uint8_t *pkt, void *pkt_meta, psample_meta_t *sflow_meta) +{ + int srcport, dstport, dstport_type; + int src_ifindex = 0; + int dst_ifindex = 0; + int sample_rate = 1; + int sample_size = PSAMPLE_SIZE_DFLT; + psample_netif_t *psample_netif = NULL; + +#ifdef PSAMPLE_CB_DBG + if (debug & 0x1) { + int i=0; + uint8_t *meta = (uint8_t*)pkt_meta; + PSAMPLE_CB_DBG_PRINT("%s: psample pkt metadata\n", __func__); + for (i=0; i<64; i+=16) { + PSAMPLE_CB_DBG_PRINT("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + meta[i+0], meta[i+1], meta[i+2], meta[i+3], meta[i+4], meta[i+5], meta[i+6], meta[i+7], + meta[i+8], meta[i+9], meta[i+10], meta[i+11], meta[i+12], meta[i+13], meta[i+14], meta[i+15]); + } + } +#endif + + /* parse pkt metadata for src and dst ports */ + srcport = psample_meta_srcport_get(pkt, pkt_meta); + dstport = psample_meta_dstport_get(pkt, pkt_meta); + if ((srcport == -1) || (dstport == -1)) { + gprintk("%s: invalid srcport %d or dstport %d\n", __func__, srcport, dstport); + return (-1); + } + + /* find src port netif (no need to lookup CPU port) */ + if (srcport != 0) { + if ((psample_netif = psample_netif_lookup_by_port(unit, srcport))) { + src_ifindex = psample_netif->dev->ifindex; + sample_rate = psample_netif->sample_rate; + sample_size = psample_netif->sample_size; + } else { + g_psample_stats.pkts_d_meta_srcport++; + PSAMPLE_CB_DBG_PRINT("%s: could not find srcport(%d)\n", __func__, srcport); + } + } + + dstport_type = DSTPORT_TYPE_GET(dstport); + dstport = DSTPORT_GET(dstport); + + /* set sFlow dst type for MC pkts */ + if (dstport_type == DSTPORT_TYPE_MC) { + DSTPORT_TYPE_SET(dst_ifindex, DSTPORT_TYPE_MC); + g_psample_stats.pkts_f_dst_mc++; + + /* find dst port netif for UC pkts (no need to lookup CPU port) */ + } else if (dstport != 0) { + if ((psample_netif = psample_netif_lookup_by_port(unit, dstport))) { + dst_ifindex = psample_netif->dev->ifindex; + } else { + g_psample_stats.pkts_d_meta_dstport++; + PSAMPLE_CB_DBG_PRINT("%s: could not find dstport(%d)\n", __func__, dstport); + } + } + + PSAMPLE_CB_DBG_PRINT("%s: srcport %d, dstport %d, src_ifindex 0x%x, dst_ifindex 0x%x, trunc_size %d, sample_rate %d\n", + __func__, srcport, dstport, src_ifindex, dst_ifindex, sample_size, sample_rate); + + sflow_meta->src_ifindex = src_ifindex; + sflow_meta->dst_ifindex = dst_ifindex; + sflow_meta->trunc_size = sample_size; + sflow_meta->sample_rate = sample_rate; + + return (0); +} + +static void +psample_task(struct work_struct *work) +{ + psample_work_t *psample_work = container_of(work, psample_work_t, wq); + unsigned long flags; + struct list_head *list_ptr, *list_next; + psample_pkt_t *pkt; + + spin_lock_irqsave(&psample_work->lock, flags); + list_for_each_safe(list_ptr, list_next, &psample_work->pkt_list) { + /* dequeue pkt from list */ + pkt = list_entry(list_ptr, psample_pkt_t, list); + list_del(list_ptr); + g_psample_stats.pkts_c_qlen_cur--; + spin_unlock_irqrestore(&psample_work->lock, flags); + + /* send to psample */ + if (pkt) { + PSAMPLE_CB_DBG_PRINT("%s: group 0x%x, trunc_size %d, src_ifdx 0x%x, dst_ifdx 0x%x, sample_rate %d\n", + __func__, pkt->group->group_num, + pkt->meta.trunc_size, pkt->meta.src_ifindex, + pkt->meta.dst_ifindex, pkt->meta.sample_rate); + + psample_sample_packet(pkt->group, + pkt->skb, + pkt->meta.trunc_size, + pkt->meta.src_ifindex, + pkt->meta.dst_ifindex, + pkt->meta.sample_rate); + g_psample_stats.pkts_f_psample_mod++; + + dev_kfree_skb_any(pkt->skb); + kfree(pkt); + } + spin_lock_irqsave(&psample_work->lock, flags); + } + spin_unlock_irqrestore(&psample_work->lock, flags); +} + +int +psample_filter_cb(uint8_t * pkt, int size, int dev_no, void *pkt_meta, + int chan, kcom_filter_t *kf) +{ + struct psample_group *group; + psample_meta_t meta; + int rv = 0; + static int info_get = 0; + + if (!info_get) { + rv = psample_info_get (dev_no, &g_psample_info); + if (rv < 0) { + gprintk("%s: failed to get psample info\n", __func__); + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + info_get = 1; + } + + PSAMPLE_CB_DBG_PRINT("%s: pkt size %d, kf->dest_id %d, kf->cb_user_data %d\n", + __func__, size, kf->dest_id, kf->cb_user_data); + g_psample_stats.pkts_f_psample_cb++; + + /* get psample group info. psample genetlink group ID passed in kf->dest_id */ + group = psample_group_get(g_psample_info.netns, kf->dest_id); + if (!group) { + gprintk("%s: Could not find psample genetlink group %d\n", __func__, kf->cb_user_data); + g_psample_stats.pkts_d_no_group++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* get psample metadata */ + rv = psample_meta_get(dev_no, pkt, pkt_meta, &meta); + if (rv < 0) { + gprintk("%s: Could not parse pkt metadata\n", __func__); + g_psample_stats.pkts_d_metadata++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* Adjust original pkt size to remove 4B FCS */ + if (size < FCS_SZ) { + g_psample_stats.pkts_d_invalid_size++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } else { + size -= FCS_SZ; + } + + /* Account for padding in libnl used by psample */ + if (meta.trunc_size >= size) { + meta.trunc_size = size - PSAMPLE_NLA_PADDING; + } + + PSAMPLE_CB_DBG_PRINT("%s: group 0x%x, trunc_size %d, src_ifdx 0x%x, dst_ifdx 0x%x, sample_rate %d\n", + __func__, group->group_num, meta.trunc_size, meta.src_ifindex, meta.dst_ifindex, meta.sample_rate); + + /* drop if configured sample rate is 0 */ + if (meta.sample_rate > 0) { + unsigned long flags; + psample_pkt_t *psample_pkt; + struct sk_buff *skb; + + if (g_psample_stats.pkts_c_qlen_cur >= psample_qlen) { + gprintk("%s: tail drop due to max qlen %d reached\n", __func__, psample_qlen); + g_psample_stats.pkts_d_qlen_max++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + if ((psample_pkt = kmalloc(sizeof(psample_pkt_t), GFP_ATOMIC)) == NULL) { + gprintk("%s: failed to alloc psample mem for pkt\n", __func__); + g_psample_stats.pkts_d_no_mem++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + memcpy(&psample_pkt->meta, &meta, sizeof(psample_meta_t)); + psample_pkt->group = group; + + if ((skb = dev_alloc_skb(meta.trunc_size)) == NULL) { + gprintk("%s: failed to alloc psample mem for pkt skb\n", __func__); + g_psample_stats.pkts_d_no_mem++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* setup skb to point to pkt */ + memcpy(skb->data, pkt, meta.trunc_size); + skb_put(skb, meta.trunc_size); + skb->len = meta.trunc_size; + psample_pkt->skb = skb; + + spin_lock_irqsave(&g_psample_work.lock, flags); + list_add_tail(&psample_pkt->list, &g_psample_work.pkt_list); + + g_psample_stats.pkts_c_qlen_cur++; + if (g_psample_stats.pkts_c_qlen_cur > g_psample_stats.pkts_c_qlen_hi) { + g_psample_stats.pkts_c_qlen_hi = g_psample_stats.pkts_c_qlen_cur; + } + + schedule_work(&g_psample_work.wq); + spin_unlock_irqrestore(&g_psample_work.lock, flags); + } else { + g_psample_stats.pkts_d_sampling_disabled++; + } + +PSAMPLE_FILTER_CB_PKT_HANDLED: + /* if sample reason only, consume pkt. else pass through */ + rv = psample_meta_sample_reason(pkt, pkt_meta); + if (rv) { + g_psample_stats.pkts_f_handled++; + } else { + g_psample_stats.pkts_f_pass_through++; + } + return rv; +} + +int +psample_netif_create_cb(int unit, kcom_netif_t *netif, struct net_device *dev) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif, *lpsample_netif; + unsigned long flags; + + if ((psample_netif = kmalloc(sizeof(psample_netif_t), GFP_ATOMIC)) == NULL) { + gprintk("%s: failed to alloc psample mem for netif '%s'\n", + __func__, dev->name); + return (-1); + } + + spin_lock_irqsave(&g_psample_info.lock, flags); + + psample_netif->dev = dev; + psample_netif->id = netif->id; + psample_netif->port = netif->port; + psample_netif->vlan = netif->vlan; + psample_netif->qnum = netif->qnum; + psample_netif->sample_rate = PSAMPLE_RATE_DFLT; + psample_netif->sample_size = PSAMPLE_SIZE_DFLT; + + /* insert netif sorted by ID similar to bkn_knet_netif_create() */ + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + lpsample_netif = (psample_netif_t*)list; + if (netif->id < lpsample_netif->id) { + found = 1; + g_psample_info.netif_count++; + break; + } + } + + if (found) { + /* Replace previously removed interface */ + list_add_tail(&psample_netif->list, &lpsample_netif->list); + } else { + /* No holes - add to end of list */ + list_add_tail(&psample_netif->list, &g_psample_info.netif_list); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + PSAMPLE_CB_DBG_PRINT("%s: added psample netif '%s'\n", __func__, dev->name); + return (0); +} + +int +psample_netif_destroy_cb(int unit, kcom_netif_t *netif, struct net_device *dev) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + if (!netif || !dev) { + gprintk("%s: netif or net_device is NULL\n", __func__); + return (-1); + } + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (netif->id == psample_netif->id) { + found = 1; + list_del(&psample_netif->list); + PSAMPLE_CB_DBG_PRINT("%s: removing psample netif '%s'\n", __func__, dev->name); + kfree(psample_netif); + g_psample_info.netif_count--; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + gprintk("%s: netif ID %d not found!\n", __func__, netif->id); + return (-1); + } + return (0); +} + +/* + * psample rate Proc Read Entry + */ +static int +psample_proc_rate_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %d\n", psample_netif->dev->name, psample_netif->sample_rate); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + return 0; +} + +static int +psample_proc_rate_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_rate_show, NULL); +} + +/* + * psample rate Proc Write Entry + * + * Syntax: + * = + * + * Where is a virtual network interface name. + * + * Examples: + * eth4=1000 + */ +static ssize_t +psample_proc_rate_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + char sample_str[40], *ptr, *newline; + unsigned long flags; + + + if (count > sizeof(sample_str)) { + count = sizeof(sample_str) - 1; + sample_str[count] = '\0'; + } + if (copy_from_user(sample_str, buf, count)) { + return -EFAULT; + } + sample_str[count] = 0; + newline = strchr(sample_str, '\n'); + if (newline) { + /* Chop off the trailing newline */ + *newline = '\0'; + } + + if ((ptr = strchr(sample_str, '=')) == NULL && + (ptr = strchr(sample_str, ':')) == NULL) { + gprintk("Error: Pkt sample rate syntax not recognized: '%s'\n", sample_str); + return count; + } + *ptr++ = 0; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (strcmp(psample_netif->dev->name, sample_str) == 0) { + psample_netif->sample_rate = simple_strtol(ptr, NULL, 10); + // TODO MLI@BRCM - check valid sample rate + found = 1; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + gprintk("Warning: Failed setting psample rate on unknown network interface: '%s'\n", sample_str); + } + return count; +} + +struct file_operations psample_proc_rate_file_ops = { + owner: THIS_MODULE, + open: psample_proc_rate_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_rate_write, + release: single_release, +}; + +/* + * psample size Proc Read Entry + */ +static int +psample_proc_size_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %d\n", psample_netif->dev->name, psample_netif->sample_size); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return 0; +} + +static int +psample_proc_size_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_size_show, NULL); +} + +/* + * psample size Proc Write Entry + * + * Syntax: + * = + * + * Where is a virtual network interface name. + * + * Examples: + * eth4=128 + */ +static ssize_t +psample_proc_size_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + char sample_str[40], *ptr, *newline; + unsigned long flags; + + if (count > sizeof(sample_str)) { + count = sizeof(sample_str) - 1; + sample_str[count] = '\0'; + } + if (copy_from_user(sample_str, buf, count)) { + return -EFAULT; + } + sample_str[count] = 0; + newline = strchr(sample_str, '\n'); + if (newline) { + /* Chop off the trailing newline */ + *newline = '\0'; + } + + if ((ptr = strchr(sample_str, '=')) == NULL && + (ptr = strchr(sample_str, ':')) == NULL) { + gprintk("Error: Pkt sample size syntax not recognized: '%s'\n", sample_str); + return count; + } + *ptr++ = 0; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (strcmp(psample_netif->dev->name, sample_str) == 0) { + psample_netif->sample_size = simple_strtol(ptr, NULL, 10); + // TODO MLI@BRCM - check valid sample size + found = 1; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + gprintk("Warning: Failed setting psample size on unknown network interface: '%s'\n", sample_str); + } + return count; +} + +struct file_operations psample_proc_size_file_ops = { + owner: THIS_MODULE, + open: psample_proc_size_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_size_write, + release: single_release, +}; + +/* + * psample map Proc Read Entry + */ +static int +psample_proc_map_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + seq_printf(m, " Interface logical port ifindex\n"); + seq_printf(m, "------------- ------------ -------\n"); + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %-14d %d\n", + psample_netif->dev->name, + psample_netif->port, + psample_netif->dev->ifindex); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return 0; +} + +static int +psample_proc_map_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_map_show, NULL); +} + +struct file_operations psample_proc_map_file_ops = { + owner: THIS_MODULE, + open: psample_proc_map_open, + read: seq_read, + llseek: seq_lseek, + write: NULL, + release: single_release, +}; + +/* + * psample debug Proc Read Entry + */ +static int +psample_proc_debug_show(struct seq_file *m, void *v) +{ + seq_printf(m, "BCM KNET %s Callback Config\n", PSAMPLE_CB_NAME); + seq_printf(m, " debug: 0x%x\n", debug); + seq_printf(m, " cmic_type: %d\n", g_psample_info.hw.cmic_type); + seq_printf(m, " dcb_type: %d\n", g_psample_info.hw.dcb_type); + seq_printf(m, " dcb_size: %d\n", g_psample_info.hw.dcb_size); + seq_printf(m, " pkt_hdr_size: %d\n", g_psample_info.hw.pkt_hdr_size); + seq_printf(m, " cdma_channels: %d\n", g_psample_info.hw.cdma_channels); + seq_printf(m, " netif_count: %d\n", g_psample_info.netif_count); + seq_printf(m, " queue length: %d\n", psample_qlen); + + return 0; +} + +static int +psample_proc_debug_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_debug_show, NULL); +} + +/* + * psample debug Proc Write Entry + * + * Syntax: + * debug= + * + * Where corresponds to the debug module parameter. + * + * Examples: + * debug=0x1 + */ +static ssize_t +psample_proc_debug_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + char debug_str[40]; + char *ptr; + + if (count > sizeof(debug_str)) { + count = sizeof(debug_str) - 1; + debug_str[count] = '\0'; + } + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + if ((ptr = strstr(debug_str, "debug=")) != NULL) { + ptr += 6; + debug = simple_strtol(ptr, NULL, 0); + } else { + gprintk("Warning: unknown configuration setting\n"); + } + + return count; +} + +struct file_operations psample_proc_debug_file_ops = { + owner: THIS_MODULE, + open: psample_proc_debug_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_debug_write, + release: single_release, +}; + +static int +psample_proc_stats_show(struct seq_file *m, void *v) +{ + seq_printf(m, "BCM KNET %s Callback Stats\n", PSAMPLE_CB_NAME); + seq_printf(m, " DCB type %d\n", g_psample_info.hw.dcb_type); + seq_printf(m, " pkts filter psample cb %10lu\n", g_psample_stats.pkts_f_psample_cb); + seq_printf(m, " pkts sent to psample module %10lu\n", g_psample_stats.pkts_f_psample_mod); + seq_printf(m, " pkts handled by psample %10lu\n", g_psample_stats.pkts_f_handled); + seq_printf(m, " pkts pass through %10lu\n", g_psample_stats.pkts_f_pass_through); + seq_printf(m, " pkts with mc destination %10lu\n", g_psample_stats.pkts_f_dst_mc); + seq_printf(m, " pkts current queue length %10lu\n", g_psample_stats.pkts_c_qlen_cur); + seq_printf(m, " pkts high queue length %10lu\n", g_psample_stats.pkts_c_qlen_hi); + seq_printf(m, " pkts drop max queue length %10lu\n", g_psample_stats.pkts_d_qlen_max); + seq_printf(m, " pkts drop no memory %10lu\n", g_psample_stats.pkts_d_no_mem); + seq_printf(m, " pkts drop no psample group %10lu\n", g_psample_stats.pkts_d_no_group); + seq_printf(m, " pkts drop sampling disabled %10lu\n", g_psample_stats.pkts_d_sampling_disabled); + seq_printf(m, " pkts drop psample not ready %10lu\n", g_psample_stats.pkts_d_not_ready); + seq_printf(m, " pkts drop metadata parse error %10lu\n", g_psample_stats.pkts_d_metadata); + seq_printf(m, " pkts with invalid src port %10lu\n", g_psample_stats.pkts_d_meta_srcport); + seq_printf(m, " pkts with invalid dst port %10lu\n", g_psample_stats.pkts_d_meta_dstport); + seq_printf(m, " pkts with invalid orig pkt sz %10lu\n", g_psample_stats.pkts_d_invalid_size); + return 0; +} + +static int +psample_proc_stats_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_stats_show, NULL); +} + +/* + * psample stats Proc Write Entry + * + * Syntax: + * write any value to clear stats + */ +static ssize_t +psample_proc_stats_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int qlen_cur = 0; + unsigned long flags; + + spin_lock_irqsave(&g_psample_work.lock, flags); + qlen_cur = g_psample_stats.pkts_c_qlen_cur; + memset(&g_psample_stats, 0, sizeof(psample_stats_t)); + g_psample_stats.pkts_c_qlen_cur = qlen_cur; + spin_unlock_irqrestore(&g_psample_work.lock, flags); + + return count; +} +struct file_operations psample_proc_stats_file_ops = { + owner: THIS_MODULE, + open: psample_proc_stats_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_stats_write, + release: single_release, +}; + +int psample_cleanup(void) +{ + cancel_work_sync(&g_psample_work.wq); + remove_proc_entry("stats", psample_proc_root); + remove_proc_entry("rate", psample_proc_root); + remove_proc_entry("size", psample_proc_root); + remove_proc_entry("debug", psample_proc_root); + remove_proc_entry("map" , psample_proc_root); + remove_proc_entry("psample", knet_cb_proc_root); + remove_proc_entry("bcm/knet-cb", NULL); + return 0; +} + +int psample_init(void) +{ + #define PROCFS_MAX_PATH 1024 + #define PSAMPLE_PROCFS_PATH "bcm/knet-cb" + char psample_procfs_path[PROCFS_MAX_PATH]; + struct proc_dir_entry *entry; + + /* create procfs for psample */ + proc_mkdir(PSAMPLE_PROCFS_PATH, NULL); + snprintf(psample_procfs_path, sizeof(psample_procfs_path), "%s/%s", PSAMPLE_PROCFS_PATH, PSAMPLE_CB_NAME); + psample_proc_root = proc_mkdir(psample_procfs_path, NULL); + + /* create procfs for psample stats */ + PROC_CREATE(entry, "stats", 0666, psample_proc_root, &psample_proc_stats_file_ops); + if (entry == NULL) { + gprintk("%s: Unable to create procfs entry '/procfs/%s/stats'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for setting sample rates */ + PROC_CREATE(entry, "rate", 0666, psample_proc_root, &psample_proc_rate_file_ops); + if (entry == NULL) { + gprintk("%s: Unable to create procfs entry '/procfs/%s/rate'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for setting sample size */ + PROC_CREATE(entry, "size", 0666, psample_proc_root, &psample_proc_size_file_ops); + if (entry == NULL) { + gprintk("%s: Unable to create procfs entry '/procfs/%s/size'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for getting netdev mapping */ + PROC_CREATE(entry, "map", 0666, psample_proc_root, &psample_proc_map_file_ops); + if (entry == NULL) { + gprintk("%s: Unable to create procfs entry '/procfs/%s/map'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for debug log */ + PROC_CREATE(entry, "debug", 0666, psample_proc_root, &psample_proc_debug_file_ops); + if (entry == NULL) { + gprintk("%s: Unable to create procfs entry '/procfs/%s/debug'\n", __func__, psample_procfs_path); + return -1; + } + + /* clear data structs */ + memset(&g_psample_stats, 0, sizeof(psample_stats_t)); + memset(&g_psample_info, 0, sizeof(psample_info_t)); + memset(&g_psample_work, 0, sizeof(psample_work_t)); + + /* setup psample_info struct */ + INIT_LIST_HEAD(&g_psample_info.netif_list); + spin_lock_init(&g_psample_info.lock); + + /* setup psample work queue */ + spin_lock_init(&g_psample_work.lock); + INIT_LIST_HEAD(&g_psample_work.pkt_list); + INIT_WORK(&g_psample_work.wq, psample_task); + + /* get net namespace */ + g_psample_info.netns = get_net_ns_by_pid(current->pid); + if (!g_psample_info.netns) { + gprintk("%s: Could not get network namespace for pid %d\n", __func__, current->pid); + return (-1); + } + PSAMPLE_CB_DBG_PRINT("%s: current->pid %d, netns 0x%p, sample_size %d\n", __func__, + current->pid, g_psample_info.netns, psample_size); + + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.h new file mode 100644 index 000000000000..8f9398c51692 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.h @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: psample_cb.h $ + * $Copyright: (c) 2019 Broadcom Corp. + * All Rights Reserved.$ + */ +#ifndef __PSAMPLE_CB_H__ +#define __PSAMPLE_CB_H__ + +#include +#include +#include + +#define PSAMPLE_CB_NAME "psample" + +extern int +psample_init(void); + +extern int +psample_cleanup(void); + +extern int +psample_filter_cb(uint8_t * pkt, int size, int dev_no, void *pkt_meta, + int chan, kcom_filter_t *kf); + +/* psample data per interface */ +typedef struct { + struct list_head list; + struct net_device *dev; + uint16 id; + uint8 port; + uint16 vlan; + uint16 qnum; + uint32 sample_rate; + uint32 sample_size; +} psample_netif_t; + +extern int +psample_netif_create_cb(int unit, kcom_netif_t *netif, struct net_device *dev); + +extern int +psample_netif_destroy_cb(int unit, kcom_netif_t *netif, struct net_device *dev); + +#endif /* __PSAMPLE_CB_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/Makefile new file mode 100644 index 000000000000..631590104cd8 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/Makefile @@ -0,0 +1,64 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/linux/kernel/modules/psample + +include ${SDK}/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +ifeq ($(kernel_version),2_4) +MODULE = $(LIBDIR)/psample.o +else +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := psample +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: $(MODULE) $(KMODULE) +endif + +KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../bcm-knet/kernel_module/Module.symvers + +# BCM Network Device + +$(MODULE): $(BLDDIR)/.tree $(BOBJS) $(LIBS) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + cat ${KBUILD_EXTRA_SYMBOLS} > $(BLDDIR)/$(KERNEL_MODULE_DIR)/Module.symvers + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +include ${SDK}/make/Make.depend + +clean:: + $(RM) $(BLDDIR)/version.c $(BLDDIR)/version.o + $(RM) $(BOBJS) $(MODULE) + +ifneq ($(kernel_version),2_4) +.PHONY: build +endif diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c new file mode 100644 index 000000000000..99317cbf30cc --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c @@ -0,0 +1,302 @@ +/* + * net/psample/psample.c - Netlink channel for packet sampling + * Copyright (c) 2017 Yotam Gigi + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PSAMPLE_MAX_PACKET_SIZE 0xffff + +static LIST_HEAD(psample_groups_list); +static DEFINE_SPINLOCK(psample_groups_lock); + +/* multicast groups */ +enum psample_nl_multicast_groups { + PSAMPLE_NL_MCGRP_CONFIG, + PSAMPLE_NL_MCGRP_SAMPLE, +}; + +static const struct genl_multicast_group psample_nl_mcgrps[] = { + [PSAMPLE_NL_MCGRP_CONFIG] = { .name = PSAMPLE_NL_MCGRP_CONFIG_NAME }, + [PSAMPLE_NL_MCGRP_SAMPLE] = { .name = PSAMPLE_NL_MCGRP_SAMPLE_NAME }, +}; + +static struct genl_family psample_nl_family; + +static int psample_group_nl_fill(struct sk_buff *msg, + struct psample_group *group, + enum psample_command cmd, u32 portid, u32 seq, + int flags) +{ + void *hdr; + int ret; + + hdr = genlmsg_put(msg, portid, seq, &psample_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_SAMPLE_GROUP, group->group_num); + if (ret < 0) + goto error; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_GROUP_REFCOUNT, group->refcount); + if (ret < 0) + goto error; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_GROUP_SEQ, group->seq); + if (ret < 0) + goto error; + + genlmsg_end(msg, hdr); + return 0; + +error: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static int psample_nl_cmd_get_group_dumpit(struct sk_buff *msg, + struct netlink_callback *cb) +{ + struct psample_group *group; + int start = cb->args[0]; + int idx = 0; + int err; + + spin_lock(&psample_groups_lock); + list_for_each_entry(group, &psample_groups_list, list) { + if (!net_eq(group->net, sock_net(msg->sk))) + continue; + if (idx < start) { + idx++; + continue; + } + err = psample_group_nl_fill(msg, group, PSAMPLE_CMD_NEW_GROUP, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI); + if (err) + break; + idx++; + } + + spin_unlock(&psample_groups_lock); + cb->args[0] = idx; + return msg->len; +} + +static const struct genl_ops psample_nl_ops[] = { + { + .cmd = PSAMPLE_CMD_GET_GROUP, + .dumpit = psample_nl_cmd_get_group_dumpit, + /* can be retrieved by unprivileged users */ + } +}; + +static struct genl_family psample_nl_family = { + .name = PSAMPLE_GENL_NAME, + .version = PSAMPLE_GENL_VERSION, + .maxattr = PSAMPLE_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .mcgrps = psample_nl_mcgrps, + .ops = psample_nl_ops, + .n_ops = ARRAY_SIZE(psample_nl_ops), + .n_mcgrps = ARRAY_SIZE(psample_nl_mcgrps), +}; + +static void psample_group_notify(struct psample_group *group, + enum psample_command cmd) +{ + struct sk_buff *msg; + int err; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); + if (!msg) + return; + + err = psample_group_nl_fill(msg, group, cmd, 0, 0, NLM_F_MULTI); + if (!err) + genlmsg_multicast_netns(&psample_nl_family, group->net, msg, 0, + PSAMPLE_NL_MCGRP_CONFIG, GFP_ATOMIC); + else + nlmsg_free(msg); +} + +static struct psample_group *psample_group_create(struct net *net, + u32 group_num) +{ + struct psample_group *group; + + group = kzalloc(sizeof(*group), GFP_ATOMIC); + if (!group) + return NULL; + + group->net = net; + group->group_num = group_num; + list_add_tail(&group->list, &psample_groups_list); + + psample_group_notify(group, PSAMPLE_CMD_NEW_GROUP); + return group; +} + +static void psample_group_destroy(struct psample_group *group) +{ + psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP); + list_del(&group->list); + kfree(group); +} + +static struct psample_group * +psample_group_lookup(struct net *net, u32 group_num) +{ + struct psample_group *group; + + list_for_each_entry(group, &psample_groups_list, list) + if ((group->group_num == group_num) && (group->net == net)) + return group; + return NULL; +} + +struct psample_group *psample_group_get(struct net *net, u32 group_num) +{ + struct psample_group *group; + + spin_lock(&psample_groups_lock); + + group = psample_group_lookup(net, group_num); + if (!group) { + group = psample_group_create(net, group_num); + if (!group) + goto out; + } + group->refcount++; + +out: + spin_unlock(&psample_groups_lock); + return group; +} +EXPORT_SYMBOL_GPL(psample_group_get); + +void psample_group_put(struct psample_group *group) +{ + spin_lock(&psample_groups_lock); + + if (--group->refcount == 0) + psample_group_destroy(group); + + spin_unlock(&psample_groups_lock); +} +EXPORT_SYMBOL_GPL(psample_group_put); + +void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, + u32 trunc_size, int in_ifindex, int out_ifindex, + u32 sample_rate) +{ + struct sk_buff *nl_skb; + int data_len; + int meta_len; + void *data; + int ret; + + meta_len = (in_ifindex ? nla_total_size(sizeof(u16)) : 0) + + (out_ifindex ? nla_total_size(sizeof(u16)) : 0) + + nla_total_size(sizeof(u32)) + /* sample_rate */ + nla_total_size(sizeof(u32)) + /* orig_size */ + nla_total_size(sizeof(u32)) + /* group_num */ + nla_total_size(sizeof(u32)); /* seq */ + + data_len = min(skb->len, trunc_size); + if (meta_len + nla_total_size(data_len) > PSAMPLE_MAX_PACKET_SIZE) + data_len = PSAMPLE_MAX_PACKET_SIZE - meta_len - NLA_HDRLEN + - NLA_ALIGNTO; + + nl_skb = genlmsg_new(meta_len + nla_total_size(data_len), GFP_ATOMIC); + if (unlikely(!nl_skb)) + return; + + data = genlmsg_put(nl_skb, 0, 0, &psample_nl_family, 0, + PSAMPLE_CMD_SAMPLE); + if (unlikely(!data)) + goto error; + + if (in_ifindex) { + ret = nla_put_u16(nl_skb, PSAMPLE_ATTR_IIFINDEX, in_ifindex); + if (unlikely(ret < 0)) + goto error; + } + + if (out_ifindex) { + ret = nla_put_u16(nl_skb, PSAMPLE_ATTR_OIFINDEX, out_ifindex); + if (unlikely(ret < 0)) + goto error; + } + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_SAMPLE_RATE, sample_rate); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_ORIGSIZE, skb->len); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_SAMPLE_GROUP, group->group_num); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_GROUP_SEQ, group->seq++); + if (unlikely(ret < 0)) + goto error; + + if (data_len) { + int nla_len = nla_total_size(data_len); + struct nlattr *nla; + + nla = (struct nlattr *)skb_put(nl_skb, nla_len); + nla->nla_type = PSAMPLE_ATTR_DATA; + nla->nla_len = nla_attr_size(data_len); + + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + goto error; + } + + genlmsg_end(nl_skb, data); + genlmsg_multicast_netns(&psample_nl_family, group->net, nl_skb, 0, + PSAMPLE_NL_MCGRP_SAMPLE, GFP_ATOMIC); + + return; +error: + pr_err_ratelimited("Could not create psample log message\n"); + nlmsg_free(nl_skb); +} +EXPORT_SYMBOL_GPL(psample_sample_packet); + +static int __init psample_module_init(void) +{ + return genl_register_family(&psample_nl_family); +} + +static void __exit psample_module_exit(void) +{ + genl_unregister_family(&psample_nl_family); +} + +module_init(psample_module_init); +module_exit(psample_module_exit); + +MODULE_AUTHOR("Yotam Gigi "); +MODULE_DESCRIPTION("netlink channel for packet sampling"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/Makefile new file mode 100644 index 000000000000..966f639f6983 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/Makefile @@ -0,0 +1,40 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/linux/kernel/modules/shared + +include ${SDK}/make/Make.config + +lib = libkern + +include ${SDK}/make/Make.kernlib + +include ${SDK}/make/Make.depend diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/gmodule.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/gmodule.c new file mode 100644 index 000000000000..3ef000961837 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/gmodule.c @@ -0,0 +1,433 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: gmodule.c,v 1.20 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + * + * Generic Linux Module Framework + * + * Hooks up your driver to the kernel + */ + +#include +#include +#include +/* Module Vector Table */ +static gmodule_t* _gmodule = NULL; + + +/* Allow DEVFS Support on 2.4 Kernels */ +#if defined(LKM_2_4) && defined(CONFIG_DEVFS_FS) +#define GMODULE_CONFIG_DEVFS_FS +#endif + + +#ifdef GMODULE_CONFIG_DEVFS_FS +devfs_handle_t devfs_handle = NULL; +#endif + +/* FIXME: support dynamic debugging */ + +static int _dbg_enable = 0; + +static int +gvprintk(const char* fmt, va_list args) + __attribute__ ((format (printf, 1, 0))); + +static int +gvprintk(const char* fmt, va_list args) +{ + static char _buf[256]; + + strcpy(_buf, ""); + sprintf(_buf, "%s (%d): ", _gmodule->name, current->pid); + vsprintf(_buf+strlen(_buf), fmt, args); + printk("%s",_buf); + + return 0; +} + +int +gprintk(const char* fmt, ...) +{ + int rv; + + va_list args; + va_start(args, fmt); + rv = gvprintk(fmt, args); + va_end(args); + return rv; +} + +int +gdbg(const char* fmt, ...) +{ + int rv = 0; + + va_list args; + va_start(args, fmt); + if(_dbg_enable) { + rv = gvprintk(fmt, args); + } + va_end(args); + return rv; +} + + +/* + * Proc FS Utilities + */ +#if PROC_INTERFACE_KERN_VER_3_10 +int +pprintf(struct seq_file *m, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + seq_vprintf(m, fmt, args); + va_end(args); + return 0; +} + +static int _gmodule_proc_show(struct seq_file *m, void *v){ + _gmodule->pprint(m); + return 0; +} + +static int +_gmodule_proc_open(struct inode * inode, struct file * file) { + if(_gmodule->open) { + _gmodule->open(); + } + + return single_open(file, _gmodule_proc_show, NULL); +} + +static ssize_t +_gmodule_proc_write(struct file *file, const char *buffer, + size_t count, loff_t *loff) +{ + /* Workaround to toggle debugging */ + if(count > 2) { + if(buffer[0] == 'd') { + _dbg_enable = buffer[1] - '0'; + GDBG("Debugging Enabled"); + } + } + return count; +} + +static int _gmodule_proc_release(struct inode * inode, struct file * file) { + if(_gmodule->close) { + _gmodule->close(); + } + + return single_release(inode, file); +} + +struct file_operations _gmodule_proc_fops = { + owner: THIS_MODULE, + open: _gmodule_proc_open, + read: seq_read, + llseek: seq_lseek, + write: _gmodule_proc_write, + release: _gmodule_proc_release, +}; +#else +int +gmodule_vpprintf(char** page_ptr, const char* fmt, va_list args) +{ + *page_ptr += vsprintf(*page_ptr, fmt, args); + return 0; +} + +int +gmodule_pprintf(char** page_ptr, const char* fmt, ...) +{ + int rv; + + va_list args; + va_start(args, fmt); + rv = gmodule_vpprintf(page_ptr, fmt, args); + va_end(args); + return rv; +} + +static char* _proc_buf = NULL; + +int +pprintf(struct seq_file *m, const char* fmt, ...) +{ + int rv; + + va_list args; + va_start(args, fmt); + rv = gmodule_vpprintf(&_proc_buf, fmt, args); + va_end(args); + return rv; +} + +#define PSTART(b) _proc_buf = b +#define PPRINT proc_print +#define PEND(b) (_proc_buf-b) + +static int +_gmodule_pprint(char* buf) +{ + PSTART(buf); + _gmodule->pprint(NULL); + return PEND(buf); +} + +static int +_gmodule_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + *eof = 1; + return _gmodule_pprint(page); +} + +static int +_gmodule_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + /* Workaround to toggle debugging */ + if(count > 2) { + if(buffer[0] == 'd') { + _dbg_enable = buffer[1] - '0'; + GDBG("Debugging Enabled"); + } + } + return count; +} +#endif + +static int +_gmodule_create_proc(void) +{ + struct proc_dir_entry* ent; +#if PROC_INTERFACE_KERN_VER_3_10 + if((ent = proc_create(_gmodule->name, + S_IRUGO | S_IWUGO, + NULL, + &_gmodule_proc_fops)) != NULL) { + return 0; + } +#else + if((ent = create_proc_entry(_gmodule->name, S_IRUGO | S_IWUGO, NULL)) != NULL) { + ent->read_proc = _gmodule_read_proc; + ent->write_proc = _gmodule_write_proc; + return 0; + } +#endif + return -1; +} + +static void +_gmodule_remove_proc(void) +{ + remove_proc_entry(_gmodule->name, NULL); +} + +static int +_gmodule_open(struct inode *inode, struct file *filp) +{ + if(_gmodule->open) { + _gmodule->open(); + } + return 0; +} + +static int +_gmodule_release(struct inode *inode, struct file *filp) +{ + if(_gmodule->close) { + _gmodule->close(); + } + return 0; +} + +#ifdef HAVE_UNLOCKED_IOCTL +static long +_gmodule_unlocked_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + if(_gmodule->ioctl) { + return _gmodule->ioctl(cmd, arg); + } else { + return -1; + } +} +#else +static int +_gmodule_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + if(_gmodule->ioctl) { + return _gmodule->ioctl(cmd, arg); + } else { + return -1; + } +} +#endif + +#ifdef HAVE_COMPAT_IOCTL +static long +_gmodule_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + if(_gmodule->ioctl) { + return _gmodule->ioctl(cmd, arg); + } else { + return -1; + } +} +#endif + + +static int +_gmodule_mmap(struct file *filp, struct vm_area_struct *vma) +{ + if (_gmodule->mmap) { + return _gmodule->mmap(filp, vma); + } +#ifdef BCM_PLX9656_LOCAL_BUS + vma->vm_flags |= VM_RESERVED | VM_IO; + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED; + + if (io_remap_pfn_range( vma, + vma->vm_start, + vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) { + return (-EAGAIN); + } + return (0); +#else/* BCM_PLX9656_LOCAL_BUS */ + return -EPERM; +#endif/* BCM_PLX9656_LOCAL_BUS */ +} + +/* FILE OPERATIONS */ + +struct file_operations _gmodule_fops = { +#ifdef HAVE_UNLOCKED_IOCTL + unlocked_ioctl: _gmodule_unlocked_ioctl, +#else + ioctl: _gmodule_ioctl, +#endif + open: _gmodule_open, + release: _gmodule_release, + mmap: _gmodule_mmap, +#ifdef HAVE_COMPAT_IOCTL + compat_ioctl: _gmodule_compat_ioctl, +#endif +}; + + +void __exit +cleanup_module(void) +{ + if(!_gmodule) return; + + /* Specific Cleanup */ + if(_gmodule->cleanup) { + _gmodule->cleanup(); + } + + /* Remove any proc entries */ + if(_gmodule->pprint) { + _gmodule_remove_proc(); + } + + /* Finally, remove ourselves from the universe */ +#ifdef GMODULE_CONFIG_DEVFS_FS + if(devfs_handle) devfs_unregister(devfs_handle); +#else + unregister_chrdev(_gmodule->major, _gmodule->name); +#endif +} + +int __init +init_module(void) +{ + int rc; + + /* Get our definition */ + _gmodule = gmodule_get(); + if(!_gmodule) return -ENODEV; + + + /* Register ourselves */ +#ifdef GMODULE_CONFIG_DEVFS_FS + devfs_handle = devfs_register(NULL, + _gmodule->name, + DEVFS_FL_NONE, + _gmodule->major, + _gmodule->minor, + S_IFCHR | S_IRUGO | S_IWUGO, + &_gmodule_fops, + NULL); + if(!devfs_handle) { + printk(KERN_WARNING "%s: can't register device with devfs", + _gmodule->name); + } + rc = 0; +#else + rc = register_chrdev(_gmodule->major, + _gmodule->name, + &_gmodule_fops); + if (rc < 0) { + printk(KERN_WARNING "%s: can't get major %d", + _gmodule->name, _gmodule->major); + return rc; + } + + if(_gmodule->major == 0) { + _gmodule->major = rc; + } +#endif + + /* Specific module Initialization */ + if(_gmodule->init) { + int rc; + if((rc = _gmodule->init()) < 0) { +#ifdef GMODULE_CONFIG_DEVFS_FS + if(devfs_handle) devfs_unregister(devfs_handle); +#else + unregister_chrdev(_gmodule->major, _gmodule->name); +#endif + return rc; + } + } + + /* Add a /proc entry, if valid */ + if(_gmodule->pprint) { + _gmodule_create_proc(); + } + + return 0; /* succeed */ +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/ksal.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/ksal.c new file mode 100644 index 000000000000..7f90c59c3a39 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/ksal.c @@ -0,0 +1,260 @@ +/* + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa + */ +/* + * $Id: ksal.c,v 1.1 Broadcom SDK $ + * $Copyright: (c) 2005 Broadcom Corp. + * All Rights Reserved.$ + */ + +#include +#include + +#include "lkm.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else +#include +#endif +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) +#include +#endif +#include + +#ifdef MAX_USER_RT_PRIO +/* Assume 2.6 scheduler */ +#define SAL_YIELD(task) \ + yield() +#else +/* Assume 2.4 scheduler */ +#define SAL_YIELD(task) \ +do { \ + task->policy |= SCHED_YIELD; \ + schedule(); \ +} while (0) +#endif + +#define SECOND_USEC (1000000) +#define USECS_PER_JIFFY (SECOND_USEC / HZ) +#define USEC_TO_JIFFIES(usec) ((usec + (USECS_PER_JIFFY - 1)) / USECS_PER_JIFFY) + +#define sal_alloc(size, desc) kmalloc(size, GFP_KERNEL) +#define sal_free(ptr) kfree(ptr) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) +#define WQ_SLEEP(a, b) wait_event_interruptible_timeout(a, NULL, b) +#else +#define WQ_SLEEP(a, b) interruptible_sleep_on_timeout(&(a), b) +#endif +/* + * sem_ctrl_t + * + * The semaphore control type uses the binary property to implement + * timed semaphores with improved performance using wait queues. + */ + +typedef struct sem_ctrl_s { + struct semaphore sem; + int binary; + int cnt; + wait_queue_head_t wq; +} sem_ctrl_t; + +sal_sem_t +sal_sem_create(char *desc, int binary, int initial_count) +{ + sem_ctrl_t *s; + + if ((s = sal_alloc(sizeof(*s), desc)) != 0) { + sema_init(&s->sem, initial_count); + s->binary = binary; + if (s->binary) { + init_waitqueue_head(&s->wq); + } + } + + return (sal_sem_t) s; +} + +void +sal_sem_destroy(sal_sem_t b) +{ + sem_ctrl_t *s = (sem_ctrl_t *) b; + + if (s == NULL) { + return; + } + + /* + * the linux kernel does not have a sema_destroy(s) + */ + sal_free(s); +} + +int +sal_sem_take(sal_sem_t b, int usec) +{ + sem_ctrl_t *s = (sem_ctrl_t *) b; + int err; + + if (usec == sal_sem_FOREVER && !in_interrupt()) { + err = down_interruptible(&s->sem); + } else { + int time_wait = 1; + int cnt = s->cnt; + + for (;;) { + if (down_trylock(&s->sem) == 0) { + err = 0; + break; + } + + if (s->binary) { + + /* Wait for event or timeout */ + + if (time_wait > 1) { + err = 1; + break; + } + err = wait_event_interruptible_timeout(s->wq, cnt != s->cnt, + USEC_TO_JIFFIES(usec)); + if (err < 0) { + break; + } + time_wait++; + + } else { + + /* Retry algorithm with exponential backoff */ + + if (time_wait > usec) { + time_wait = usec; + } + + sal_usleep(time_wait); + + usec -= time_wait; + + if (usec == 0) { + err = ETIMEDOUT; + break; + } + + if ((time_wait *= 2) > 100000) { + time_wait = 100000; + } + } + } + } + return err ? -1 : 0; +} + +int +sal_sem_give(sal_sem_t b) +{ + sem_ctrl_t *s = (sem_ctrl_t *) b; + + up(&s->sem); + if (s->binary) { + s->cnt++; + wake_up_interruptible(&s->wq); + } + return 0; +} + +uint32 +sal_time_usecs(void) +{ + struct timeval ltv; + do_gettimeofday(<v); + return (ltv.tv_sec * SECOND_USEC + ltv.tv_usec); +} + +void +sal_usleep(uint32 usec) +{ + uint32 start_usec; + wait_queue_head_t queue; + + if (usec <= SECOND_USEC / HZ) { + start_usec = sal_time_usecs(); + do { + SAL_YIELD(current); + } while ((sal_time_usecs() - start_usec) < usec); + } else { + init_waitqueue_head(&queue); + WQ_SLEEP(queue, USEC_TO_JIFFIES(usec)); + } +} + +void +sal_udelay(uint32 usec) +{ + static volatile int _sal_udelay_counter; + static int loops = 0; + int ix, iy; + + if (loops == 0 || usec == 0) { /* Need calibration? */ + int max_loops; + int start = 0, stop = 0; + int mpt = USECS_PER_JIFFY; /* usec/tick */ + + for (loops = 1; loops < 0x1000 && stop == start; loops <<= 1) { + /* Wait for clock turn over */ + for (stop = start = jiffies; start == stop; start = jiffies) { + /* Empty */ + } + sal_udelay(mpt); /* Single recursion */ + stop = jiffies; + } + + max_loops = loops / 2; /* Loop above overshoots */ + + start = stop = 0; + + if (loops < 4) { + loops = 4; + } + + for (loops /= 4; loops < max_loops && stop == start; loops++) { + /* Wait for clock turn over */ + for (stop = start = jiffies; start == stop; start = jiffies) { + /* Empty */ + } + sal_udelay(mpt); /* Single recursion */ + stop = jiffies; + } + } + + for (iy = 0; iy < usec; iy++) { + for (ix = 0; ix < loops; ix++) { + _sal_udelay_counter++; /* Prevent optimizations */ + } + } +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/bmw-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/bmw-2_6/Makefile new file mode 100644 index 000000000000..899c7b405374 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/bmw-2_6/Makefile @@ -0,0 +1,63 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.4 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# PPC_TOOLS_DIR - path to build tools (if not in PATH already) +# PPC_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=bmw-$(kernel_version) + +# Windriver linux version +#WRS_LINUX_VERSION=1.4 +#WRS_LINUX_VERSION=2.0 + +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile new file mode 100644 index 000000000000..8f59a763e314 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile @@ -0,0 +1,302 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.4 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override-target=linux-$(platform) + +ifeq ($(LINUX_MAKE_SHARED_LIB),1) +libext = so.$(SHAREDLIBVER) +else +libext = a +endif + +ifeq (,$(platform)) +$(error Internal error: platform variable is not set) +endif + +include $(SDK)/make/Make.config +LOCALDIR=systems/linux/user/common +include $(SDK)/make/Make.depend +kernel-override=linux-$(platform) +ifdef BLDCONFIG +KERN_BLDROOT=${SDK}/${SDKBUILD}/${BLDCONFIG}/$(kernel-override)$(bldroot_suffix) +else +KERN_BLDROOT=${SDK}/${SDKBUILD}/$(kernel-override)$(bldroot_suffix) +endif + +ifeq (,$(kernel_version)) +kernel_version=2_4 +endif + +ifneq ($(kernel_version),2_4) +KOBJ=ko +else +KOBJ=o +endif + +ifneq (,$(TOOLS_DIR)) +override PATH := $(TOOLS_DIR):$(PATH) +endif + +ifeq ($(DEST_DIR),) +DEST_DIR=${BLDDIR} +endif + +KERNEL_BDE_LOCAL :=linux-kernel-bde.$(KOBJ) +KERNEL_BDE :=$(DEST_DIR)/$(KERNEL_BDE_LOCAL) + +USER_BDE_LOCAL :=linux-user-bde.$(KOBJ) +USER_BDE=$(DEST_DIR)/$(USER_BDE_LOCAL) + +KNET_CB_LOCAL := linux-knet-cb.$(KOBJ) +KNET_CB := $(DEST_DIR)/$(KNET_CB_LOCAL) + +BCM_KNET_LOCAL :=linux-bcm-knet.$(KOBJ) +BCM_KNET=$(DEST_DIR)/$(BCM_KNET_LOCAL) + +PSAMPLE_LOCAL := psample.$(KOBJ) +PSAMPLE := $(DEST_DIR)/$(PSAMPLE_LOCAL) + +BCM_LPTP_LOCAL :=linux-bcm-ptp-clock.$(KOBJ) +BCM_LPTP=$(DEST_DIR)/$(BCM_LPTP_LOCAL) + +ifeq (,$(findstring DELIVER,$(MAKECMDGOALS))) +.DEFAULT_GOAL := all +all_targets := kernel_modules $(KERNEL_BDE) $(USER_BDE) + +LOCAL_TARGETS := + +ifeq ($(NO_LOCAL_TARGETS),) +LOCAL_TARGETS +=$(patsubst %,$(realpath ..)/$(platform)/%,$(KERNEL_BDE_LOCAL) $(USER_BDE_LOCAL)) + +all_targets +=$(LOCAL_TARGETS) +endif + +# Build all by default +ifndef BUILD_KNET +BUILD_KNET = 1 +endif + +# Remove this when LinuxPTP support becomes optional. +ifndef BUILD_LPTP +BUILD_LPTP = 1 +BUILD_KNETSYNC = 1 +endif + +ifeq ($(BUILD_KNET),1) +# Kernel network support +all_targets += $(BCM_KNET) + +ifeq ($(NO_LOCAL_TARGETS),) +LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(BCM_KNET_LOCAL)) +all_targets +=$(LOCAL_TARGETS) +endif + +ifdef BUILD_KNET_CB +all_targets += $(KNET_CB) + +ifeq ($(NO_LOCAL_TARGETS),) +LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(KNET_CB_LOCAL)) +all_targets +=$(LOCAL_TARGETS) +endif +endif + +ifdef BUILD_PSAMPLE +all_targets += $(PSAMPLE) +ADD_TO_CFLAGS += -DPSAMPLE_SUPPORT + +# KnetSync support +ifdef BUILD_KNETSYNC + +KERNEL_TARGETS += $(BCM_PTP_CLOCK) +LOCAL_KERNEL_TARGETS += $(patsubst %,$(realpath ..)/$(platform)/%,$(BCM_PTP_CLOCK_LOCAL)) + +endif # BUILD_KNETSYNC + +ifeq ($(NO_LOCAL_TARGETS),) + LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(PSAMPLE_LOCAL)) + all_targets +=$(LOCAL_TARGETS) +endif +endif + +ifdef BUILD_LPTP + all_targets += $(BCM_LPTP) + +ifeq ($(NO_LOCAL_TARGETS),) + LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(BCM_LPTP_LOCAL)) + all_targets +=$(LOCAL_TARGETS) +endif +endif + +ADD_TO_CFLAGS += -I$(SDK)/systems/linux/kernel/modules/include +COND_KNET_LIBS = libuser.$(libext) +endif + +all: $(BLDDIR)/.tree $(all_targets) + +ifeq ($(NO_LOCAL_TARGETS),) +define LOCAL_TARGET_DEF +$(1) : $(DEST_DIR)/$(notdir $(1)) + cp $$? $$@ +endef +endif + +# User BDE libraries +ADD_TO_CFLAGS += -I$(SDK)/systems/bde/linux/include + +# Use raw IOCTL for KNET +ADD_TO_CFLAGS += -DPROXY_SUPPORT=0 + +CFLAGS += $(ADD_TO_CFLAGS) + +#SAI_FIXUP +CFLAGS:=$(filter-out -fPIC, $(CFLAGS)) + +# KnetSync Support +ifdef BUILD_KNETSYNC + knetsync_subdirs = bcm-ptp-clock +endif # BUILD_KNETSYNC + +kernel_modules: + $(MAKE) -C $(SDK)/systems/bde/linux/kernel kernel_version=$(kernel_version) + $(MAKE) -C $(SDK)/systems/bde/linux/user/kernel kernel_version=$(kernel_version) +ifeq ($(BUILD_KNET),1) + $(MAKE) -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ + subdirs="shared bcm-knet" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" +ifdef BUILD_PSAMPLE + $(MAKE) -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ + subdirs="psample" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" +endif +ifdef BUILD_KNET_CB + $(MAKE) -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ + subdirs="knet-cb" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" +endif +ifdef BUILD_LPTP + $(MAKE) -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ + subdirs="bcm-ptp-clock" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" +endif +endif + +$(KERNEL_BDE): $(KERN_BLDROOT)/linux-kernel-bde.$(KOBJ) + mkdir -p $(@D) + $(OBJCOPY) --strip-debug $< $@ + +$(USER_BDE): $(KERN_BLDROOT)/linux-user-bde.$(KOBJ) + $(OBJCOPY) --strip-debug $< $@ + +$(BCM_KNET): $(KERN_BLDROOT)/linux-bcm-knet.$(KOBJ) + $(OBJCOPY) --strip-debug $< $@ + +$(KNET_CB): $(KERN_BLDROOT)/linux-knet-cb.$(KOBJ) + $(OBJCOPY) --strip-debug $< $@ + +$(PSAMPLE): $(KERN_BLDROOT)/psample.$(KOBJ) + $(OBJCOPY) --strip-debug $< $@ + +$(BCM_LPTP): $(KERN_BLDROOT)/linux-bcm-ptp-clock.$(KOBJ) + $(OBJCOPY) --strip-debug $< $@ + +ifeq ($(NO_LOCAL_TARGETS),) +$(foreach targ,$(LOCAL_TARGETS),$(eval $(call LOCAL_TARGET_DEF,$(targ)))) +endif + +clean:: + $(MAKE) -C $(SDK)/systems/bde/linux/kernel $@ + $(MAKE) -C $(SDK)/systems/bde/linux/user/kernel $@ + $(MAKE) -C $(SDK)/systems/linux/kernel/modules \ + subdirs="shared bcm-knet knet-cb psample bcm-ptp-clock" \ + override-target=linux-$(platform) $@ + $(RM) $(KERNEL_BDE) $(USER_BDE) + $(RM) $(BCM_KNET) $(KNET_CB) $(PSAMPLE) $(BCM_LPTP) + $(RM) $(KERN_BLDROOT)/linux-kernel-bde.$(KOBJ) + $(RM) $(KERN_BLDROOT)/linux-user-bde.$(KOBJ) + $(RM) $(KERN_BLDROOT)/linux-bcm-knet.$(KOBJ) + $(RM) $(KERN_BLDROOT)/linux-knet-cb.$(KOBJ) + $(RM) $(KERN_BLDROOT)/psample.$(KOBJ) + $(RM) $(LOCAL_TARGETS) + +distclean:: clean + +.PHONY: variable + +# +# Echo variable values used for configuration +# usage: make VAR=CC variable +# +variable:: + @echo $($(VAR)) + +else +ifndef DELIVERY +$(error DELIVERY required) +endif + +DELIVERABLES := $(KERNEL_BDE) $(USER_BDE) +# 1= source +define DELIVERY_RULE +_DEL_TARG += $(DELIVERY)/$(notdir $(1)) +$(DELIVERY)/$(notdir $(1)) : $(1) + @mkdir -p $(DELIVERY) +ifeq ($(filter $(notdir $(BCM)) $(notdir $(BCM).dbg),$(notdir $1)),) + $(OBJCOPY) --strip-debug $$< $$@ +else + $(CP) -p $$< $$@ +endif +endef + +$(foreach f,$(DELIVERABLES),$(eval $(call DELIVERY_RULE,$(f)))) + +DELIVER: $(_DEL_TARG) +endif + +# Make.config defines remaining phony targets +.PHONY: build kernel_modules DELIVER + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/gto-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/gto-2_6/Makefile new file mode 100644 index 000000000000..c157f9ff35fc --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/gto-2_6/Makefile @@ -0,0 +1,84 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.9 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# PPC_TOOLS_DIR - path to build tools (if not in PATH already) +# PPC_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=gto-$(kernel_version) +LINUX_MAKE_USER=1 +export LINKER_RELAX=1 + +# Select the build environment +#BUILD_PLATFORM=ELDK +#BUILD_PLATFORM=WR_LINUX + +#Select the LINUX KERNEL VERSION +#KERN_VER = 2.6.21.7 +#KERN_VER = 2.6.24.4 +#KERN_VER = 2.6.25 + + +# Select the ELDK version +#ELDK_VERSION=4.1 +#ELDK_VERSION=4.0 + +#Select WRS Linux version +#WRS_LINUX_VERSION=2.0 +#WRS_LINUX_VERSION=3.0 + + +export KERN_VER +export ELDK_VERSION +export BUILD_PLATFORM +export WRS_LINUX_VERSION + +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/gto/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/gto/Makefile new file mode 100644 index 000000000000..fd98f6d2f963 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/gto/Makefile @@ -0,0 +1,60 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.9 Broadcom SDK $ +# $Copyright: (c) 2015 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# PPC_TOOLS_DIR - path to build tools (if not in PATH already) +# PPC_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=4_4 +platform=gto +LINUX_MAKE_USER=1 +export LINKER_RELAX=1 + +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/gts/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/gts/Makefile new file mode 100644 index 000000000000..5acaeab271cc --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/gts/Makefile @@ -0,0 +1,74 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 0.1 Broadcom SDK $ +# $Copyright: (c) 2015 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# TOOLS_DIR - path to build tools (if not in PATH already) +# CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=4_19 +platform=gts +LINUX_MAKE_USER=1 +export LINKER_RELAX = 1 +export ADD_TO_CFLAGS +export BR_NO_CCACHE + + +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc-3_14/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc-3_14/Makefile new file mode 100644 index 000000000000..b874340ddec2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc-3_14/Makefile @@ -0,0 +1,76 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.7 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=3_14 +platform=iproc-$(kernel_version) + +IPROC_BUILD=1 +export IPROC_BUILD +export BUILD_PLATFORM +export ARM_LINUX_VERSION + +LINUX_MAKE_USER=1 +export ADD_TO_CFLAGS + +include ${SDK}/make/Make.linux diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc-4_4/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc-4_4/Makefile new file mode 100644 index 000000000000..2b724be3202f --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc-4_4/Makefile @@ -0,0 +1,70 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.7 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=4_4 +platform=iproc-$(kernel_version) + +IPROC_BUILD=1 +export IPROC_BUILD +export BUILD_PLATFORM +export ARM_LINUX_VERSION + +LINUX_MAKE_USER=1 +export ADD_TO_CFLAGS +export BR_NO_CCACHE + +include ${SDK}/make/Make.linux diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile new file mode 100644 index 000000000000..f10c5c37a082 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile @@ -0,0 +1,70 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.7 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=4_14 +platform=iproc + +IPROC_BUILD=1 +export IPROC_BUILD +export BUILD_PLATFORM +export ARM_LINUX_VERSION + +LINUX_MAKE_USER=1 +export ADD_TO_CFLAGS +export BR_NO_CCACHE + +include ${SDK}/make/Make.linux diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc_64/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc_64/Makefile new file mode 100644 index 000000000000..983b3abbced7 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc_64/Makefile @@ -0,0 +1,70 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.7 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=4_14 +platform=iproc_64 + +IPROC_BUILD=1 +export IPROC_BUILD +export BUILD_PLATFORM +export ARM_LINUX_VERSION + +LINUX_MAKE_USER=1 +export ADD_TO_CFLAGS +export BR_NO_CCACHE + +include ${SDK}/make/Make.linux diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/jag-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/jag-2_6/Makefile new file mode 100644 index 000000000000..26a7f520f2d2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/jag-2_6/Makefile @@ -0,0 +1,79 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.4 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=jag-$(kernel_version) + +# Select the build environment +#BUILD_PLATFORM=ELDK +#BUILD_PLATFORM=WR_LINUX + +#Select the LINUX KERNEL VERSION +#KERN_VER = 2.6.21.7 + + +# Select the ELDK version +#ELDK_VERSION=4.1 + +# Windriver linux version +#WRS_LINUX_VERSION=1.4 +#WRS_LINUX_VERSION=2.0 + +export KERN_VER +export ELDK_VERSION +export BUILD_PLATFORM +export WRS_LINUX_VERSION + +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/nsx-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/nsx-2_6/Makefile new file mode 100644 index 000000000000..881ec34c2d36 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/nsx-2_6/Makefile @@ -0,0 +1,58 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.4 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=nsx-$(kernel_version) +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/nsx64/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/nsx64/Makefile new file mode 100644 index 000000000000..9e79d90fa992 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/nsx64/Makefile @@ -0,0 +1,57 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +platform=nsx64 +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/nsx_wrl-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/nsx_wrl-2_6/Makefile new file mode 100644 index 000000000000..4e86843cdc7c --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/nsx_wrl-2_6/Makefile @@ -0,0 +1,65 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=nsx_wrl-$(kernel_version) + +# Windriver linux version +#WRS_LINUX_VERSION=1.4 +#WRS_LINUX_VERSION=2.0 + +export WRS_LINUX_VERSION + +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/raptor-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/raptor-2_6/Makefile new file mode 100644 index 000000000000..10ab1a1cc259 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/raptor-2_6/Makefile @@ -0,0 +1,79 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.5 Broadcom SDK $ +# $Copyright: (c) 2007 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=raptor-$(kernel_version) + +# Select the build environment +#BUILD_PLATFORM=ELDK +#BUILD_PLATFORM=WR_LINUX + +#Select the LINUX KERNEL VERSION +#KERN_VER = 2.6.21.7 + + +# Select the ELDK version +#ELDK_VERSION=4.1 + +# Windriver linux version +#WRS_LINUX_VERSION=1.4 +#WRS_LINUX_VERSION=2.0 + +export KERN_VER +export ELDK_VERSION +export BUILD_PLATFORM +export WRS_LINUX_VERSION + +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/raptor/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/raptor/Makefile new file mode 100644 index 000000000000..df8800a1a786 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/raptor/Makefile @@ -0,0 +1,58 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.1 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# MIPS_TOOLS_DIR - path to build tools (if not in PATH already) +# MIPS_CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +platform=raptor +LINUX_MAKE_USER=1 +CFGFLAGS += -DBCM_ICS +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/slk/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/slk/Makefile new file mode 100644 index 000000000000..6ef360156572 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/slk/Makefile @@ -0,0 +1,71 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 0.1 Broadcom SDK $ +# $Copyright: (c) 2015 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# TOOLS_DIR - path to build tools (if not in PATH already) +# CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=3_14 +platform=slk +LINUX_MAKE_USER=1 +export LINKER_RELAX = 1 + +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/x86-smp_generic_64-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/x86-smp_generic_64-2_6/Makefile new file mode 100644 index 000000000000..78c2c0cb1702 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/x86-smp_generic_64-2_6/Makefile @@ -0,0 +1,56 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 1.2 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=2_6 +platform=x86-smp_generic_64-$(kernel_version) + +LINUX_MAKE_USER=1 +include ${SDK}/make/Make.linux diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/xlr/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/xlr/Makefile new file mode 100644 index 000000000000..e19eeff4aef2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/user/xlr/Makefile @@ -0,0 +1,74 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# -*- Makefile -*- +# $Id: Makefile,v 0.1 Broadcom SDK $ +# $Copyright: (c) 2015 Broadcom Corp. +# All Rights Reserved.$ + +# +# This make job requires the following environment variables to be set: +# +# SDK - path to StrataXGS SDK root directory +# +# Optionally the following environment variables can be set to +# override the default build server configuration: +# +# TOOLS_DIR - path to build tools (if not in PATH already) +# CROSS_COMPILE - cross compile tools prefix +# LINUX_INCLUDE - path to Linux kernel include directory +# + +SDK :=$(shell if [ -n "$$SDK" ] ; then\ + echo $$SDK;\ + else\ + cd $(dir $(lastword $(MAKEFILE_LIST))); while /usr/bin/test ! -e RELEASE ; do \ + dir=`cd ../;pwd`; \ + if [ "$$dir" = "/" ] ; then \ + echo Cannot find SDK in $(lastword $(MAKEFILE_LIST)) 1>&2; \ + exit 1; \ + fi ; \ + cd $$dir; \ + done ; \ + pwd; \ + fi) + +ifeq ($(SDK),) +$(error Please run this in a tree) +endif + +export SDK + +override kernel_version=4_19 +platform=xlr +LINUX_MAKE_USER=1 +export LINKER_RELAX = 1 +export ADD_TO_CFLAGS +export BR_NO_CCACHE + + +include ${SDK}/make/Make.linux + diff --git a/platform/broadcom/saibcm-modules/tools/mktool.pl b/platform/broadcom/saibcm-modules/tools/mktool.pl new file mode 100644 index 000000000000..518ab25535c3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/tools/mktool.pl @@ -0,0 +1,303 @@ +# +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa +# +# +# mktool.pl +# +# $Id: mktool.pl,v 1.5 Broadcom SDK $ +# +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved. $ + +use File::Path; +use File::Find; +use File::Copy; +use Cwd; + +($prog = $0) =~ s/.*\///; + +SWITCH: +{ + $op = shift; + + if ($op eq "-rm") { mktool_rm(@ARGV); last SWITCH; } + if ($op eq "-cp") { mktool_cp(@ARGV); last SWITCH; } + if ($op eq "-md") { mktool_md(@ARGV); last SWITCH; } + if ($op eq "-ln") { mktool_ln(@ARGV); last SWITCH; } + if ($op eq "-foreach") { mktool_foreach(@ARGV); last SWITCH; } + if ($op eq "-dep") { mktool_makedep(@ARGV); last SWITCH; } + if ($op eq "-echo") { mktool_echo(@ARGV); last SWITCH; } + if ($op eq "-beep") { mktool_beep(@ARGV); last SWITCH; } + die("$prog: unknown option '$op'\n"); +} + +exit 0; + + + + +# +# mktool_execute +# +# Executes a command, returns exist status. +# Performs token special translation before execution. +# + +sub mktool_execute +{ + my $token = shift; + my @cmds = @_; + +# printf("mktool_execute: token = '$token'\n"); + foreach $cmd (@cmds) + { + #printf("mktool_execute: cmd = '$cmd'\n"); + $cmd =~ s/\#\#/$token/g; + if($cmd =~ /^-p/) + { + $cmd =~ s/^-p//; + printf("$cmd\n"); + } + else + { + system($cmd); + my $excode = ($? >> 8); + exit $excode if $excode; + } + } +} + + +$find_regexp = ""; +@find_cmd; + +# +# mktool_foreach +# +sub mktool_foreach +{ + if($_[0] eq "-find") + { + shift; + $find_dir = shift; + $find_regexp = shift; + @find_cmds = @_; + + if(!($find_dir =~ /^\//)) + { + $find_dir = cwd() . "/" . $find_dir; + } + find(\&_mktool_foreach_find_wanted, $find_dir); + } + else + { + my $subdir = 0; + if($_[0] eq "-subdir") + { + $subdir = 1; + shift; + } + + my @thingies = split(' ', shift); + + foreach $thingy (@thingies) + { + chdir $thingy unless $subdir == 0; + mktool_execute($thingy, @_); + chdir ".." unless $subdir == 0; + } + } +} + + + +sub _mktool_foreach_find_wanted +{ + my $expr = "\$File::Find::name =~ /\^$find_regexp\$/"; + + if(eval($expr)) + { + mktool_execute($File::Find::name, @find_cmds); + exit $excode if $excode; + } +} + + +# +# rm +# +# Removes a list of objects +# +sub mktool_rm +{ + my($f); + + foreach $f (@_) { + eval { rmtree($f) }; + if ($@) { + die "$prog $op: failed to remove $f: $@\n"; + } + } +} + +# +# md +# +# Makes a list of directories +# +sub mktool_md +{ + my($dir); + + foreach $dir (@_) { + $dir =~ s!/+$!!; + eval { mkpath($dir) }; + if ($@) { + die "$prog $op: failed to make directory $dir: $@\n"; + } + } +} + + +sub mktool_cp +{ + my($from, $to) = @_; + + if (@_ != 2) { + die "$prog $op: must have two arguments\n"; + } + copy($from, $to) || + die "$prog $op: failed to copy $from to $to: $!\n"; +} + +sub mktool_ln +{ + my($old, $new) = @_; + + if (@_ != 2) { + die "$prog $op: must have two arguments\n"; + } + link ($old, $new) || + die "$prog $op: failed to link $new to $old: $!\n"; +} + + +# @echo "$@ \\" > ${BLDDIR}/$(notdir $@) +# @if ($(DEPEND)) >> $(BLDDIR)/$(notdir $@); then \ +# exit 0; \ +# else \ +# rm -f ${BLDDIR}/$(notdir $@); \ +# exit 1; \ +# fi + +# $(MAKEDEP) "$@" "$(BLDDIR)/$(notdir $@)" "$(DEPEND)" + +sub mktool_makedep +{ + my ($source, $target, $cmd, $curdir) = @_; + my @result = `$cmd`; + my $sdk = $ENV{'SDK'}; + my $count; + my $tmp; + local $resultant; + +## Comman $cmd +#Command $cmd +print <-1) & ($count < 20) ) + { + $line=~s/\/\w+\/\.\.//; + # if we hit a major recursion, revert the line, report + # this to the output and drop out of the loop, but do + # continue, this should not halt generation + if($count++>19) + { + print "mktool.pl: could not process $line \n\n"; + print ":: curdir $curdir\n"; + print ":: target $target\n"; + print ":: cmd $cmd\n"; + $line=$tmp; + } + } + + # set all the paths to use the $SDK variable + $line =~ s/$ENV{'SDK'}/\$\{SDK\}/g; + $resultant=$resultant . $line; + } + + # some compilers return extra newlines + $resultant=~s/\n//g; + + # now clean up the result + $resultant=~s/\\/\\\n/g; + + mktool_md($dirName) unless (-d $dirName); + open (TARGET, ">$target") || + die("$prog $op: cannot open '$target' for writing: $!\n"); + print TARGET "$resultant\n"; + close(TARGET); + } +} + +sub mktool_echo +{ + print "@_\n"; +} + +sub mktool_beep +{ + -t STDOUT && defined $ENV{MAKEBEEP} && print "\007"; +} diff --git a/platform/broadcom/sonic-platform-modules-accton/.gitignore b/platform/broadcom/sonic-platform-modules-accton/.gitignore new file mode 100644 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-accton/LICENSE b/platform/broadcom/sonic-platform-modules-accton/LICENSE new file mode 100644 index 000000000000..bc693f7a4c40 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Accton Technology Corporation + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-accton/README.md b/platform/broadcom/sonic-platform-modules-accton/README.md new file mode 100644 index 000000000000..0ff20bb2d21b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/README.md @@ -0,0 +1 @@ +platform drivers of Accton products for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/fanutil.py new file mode 100755 index 000000000000..d046834ecf33 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/fanutil.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +# Copyright (c) 2019 Edgecore Networks Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. +# +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 10/24/2019:Jostar craete for as4630_54pe +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 3 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + + FAN_NODE_NUM_OF_MAP = 4 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + FAN_NODE_PRESENT_IDX_OF_MAP= 3 + FAN_NODE_SPEED_IDX_OF_MAP = 4 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/3-0060/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/3-0060/fan_duty_cycle_percentage' + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_device_path_mapping = {} + + _fan_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan_fault_1', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan_direction_1', + (FAN_NUM_1_IDX, FAN_NODE_PRESENT_IDX_OF_MAP): 'fan_present_1', + (FAN_NUM_1_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan1_input', + + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan_fault_2', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan_direction_2', + (FAN_NUM_2_IDX, FAN_NODE_PRESENT_IDX_OF_MAP):'fan_present_2', + (FAN_NUM_2_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan2_input', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan_fault_3', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan_direction_3', + (FAN_NUM_3_IDX, FAN_NODE_PRESENT_IDX_OF_MAP):'fan_present_3', + (FAN_NUM_3_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan3_input', + } + + def _get_fan_device_node(self, fan_num, node_num): + return self._fan_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_device_node_mapping[(fan_num, node_num)]) + + def get_size_node_map(self): + return len(self._fan_device_node_mapping) + + def get_fan_device_path(self, fan_num, node_num): + return self._fan_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + def get_fan_present(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_PRESENT_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + + def set_fan_duty_cycle(self, val): + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + fan_file.write(str(val)) + fan_file.close() + return True + + def get_fan_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + if self.get_fan_fault(fan_num)==0 and self.get_fan_present(fan_num)>0: + return 1 + else: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return 0 + +def main(): + fan = FanUtil() + logging.debug('fan_duty_cycle=%d', fan.get_fan_duty_cycle()) + for i in range(1,4): + logging.debug('fan-%d speed=%d', i, fan.get_fan_speed(i)) + logging.debug('fan-%d present=%d', i, fan.get_fan_present(i)) + logging.debug('fan-%d fault=%d', i, fan.get_fan_fault(i)) + logging.debug('fan-%d status=%d', i, fan.get_fan_status(i)) + +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/thermalutil.py new file mode 100755 index 000000000000..bd5530fd9035 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/classes/thermalutil.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# Copyright (c) 2019 Edgecore Networks Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. +# +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 10/24/2019:Jostar craete for as4630_54pe +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_MAX = 4 + THERMAL_NUM_1_IDX = 1 + THERMAL_NUM_2_IDX = 2 + THERMAL_NUM_3_IDX = 3 + THERMAL_NUM_4_IDX = 4 + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/14-0048/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/24-004b/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/25-004a/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/class/hwmon/hwmon1/temp1_input"], + } + + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + return 0 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + +def main(): + thermal = ThermalUtil() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/Makefile new file mode 100755 index 000000000000..f845f2e17d86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/Makefile @@ -0,0 +1,19 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= x86-64-accton-as4630-54pe-cpld.o x86-64-accton-as4630-54pe-psu.o \ + x86-64-accton-as4630-54pe-leds.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +#$(error KERNEL_SRC is not defined) +KVERSION=3.16.0-8-amd64 +KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ +KERNELDIR:=$(KERNEL_DIR) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.mod.c *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/x86-64-accton-as4630-54pe-cpld.c b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/x86-64-accton-as4630-54pe-cpld.c new file mode 100755 index 000000000000..d1205516ef53 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/x86-64-accton-as4630-54pe-cpld.c @@ -0,0 +1,1106 @@ +/* + * Copyright (C) Jostar yang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as4630_54pe CPLD + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ +#define FAN_DUTY_CYCLE_REG_MASK 0x1F +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 114 // R.P.M value = read value x3.79*60/2 + +#define NUM_THERMAL_SENSORS (3) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x4a, 0x4b} + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as4630_54pe_cpld, +}; +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, +}; + +static const u8 fan_reg[] = { + 0x87, /* fan status, fan direction */ + 0x1A, /* fan PWM(for fan1 ,fan2) */ + 0x1B, /* fan PWM(for fan1 ,fan2) */ + 0x88, /* front fan1 speed(rpm) */ + 0x89, /* front fan2 speed(rpm) */ + 0x8A, /* front fan3 speed(rpm) */ + 0x20, /*fan fault*/ +}; + +struct as4630_54pe_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_fan_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + + + +static const struct i2c_device_id as4630_54pe_cpld_id[] = { + { "as4630_54pe_cpld", as4630_54pe_cpld}, + { } +}; +MODULE_DEVICE_TABLE(i2c, as4630_54pe_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define FAN_SPEED_RPM_ATTR_ID(index) FAN_SPEED_RPM_##index +#define FAN_DIRECTION_ID(index) FAN_DIRECTION_##index +#define FAN_PRESENT_ATTR_ID(index) FAN_PRESENT_##index +#define FAN_FAULT_ATTR_ID(index) FAN_FAULT_##index + +enum as4630_54pe_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + /* transceiver attributes */ + TRANSCEIVER_RXLOS_ATTR_ID(49), + TRANSCEIVER_RXLOS_ATTR_ID(50), + TRANSCEIVER_RXLOS_ATTR_ID(51), + TRANSCEIVER_RXLOS_ATTR_ID(52), + TRANSCEIVER_TXFAULT_ATTR_ID(49), + TRANSCEIVER_TXFAULT_ATTR_ID(50), + TRANSCEIVER_TXFAULT_ATTR_ID(51), + TRANSCEIVER_TXFAULT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(49), + TRANSCEIVER_TXDISABLE_ATTR_ID(50), + TRANSCEIVER_TXDISABLE_ATTR_ID(51), + TRANSCEIVER_TXDISABLE_ATTR_ID(52), + FAN_PRESENT_ATTR_ID(1), + FAN_PRESENT_ATTR_ID(2), + FAN_PRESENT_ATTR_ID(3), + FAN_SPEED_RPM_ATTR_ID(1), + FAN_SPEED_RPM_ATTR_ID(2), + FAN_SPEED_RPM_ATTR_ID(3), + FAN_DIRECTION_ID(1), + FAN_DIRECTION_ID(2), + FAN_DIRECTION_ID(3), + FAN_FAULT_ATTR_ID(1), + FAN_FAULT_ATTR_ID(2), + FAN_FAULT_ATTR_ID(3), + FAN_DUTY_CYCLE_PERCENTAGE, +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as4630_54pe_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as4630_54pe_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/*fan sysfs*/ +static struct as4630_54pe_cpld_data *as4630_54pe_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); +//static ssize_t show_power(struct device *dev, struct device_attribute *da, + // char *buf); + + + +/* transceiver attributes */ +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index); + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_present_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +#define DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index); + +#define DECLARE_QSFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_present_##index.dev_attr.attr + + +#define DECLARE_FAN_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_present_##index, S_IRUGO, fan_show_value, NULL, FAN_PRESENT_##index); \ + static SENSOR_DEVICE_ATTR(fan_fault_##index, S_IRUGO, fan_show_value, NULL, FAN_FAULT_##index); \ + static SENSOR_DEVICE_ATTR(fan_speed_rpm_##index, S_IRUGO, fan_show_value, NULL, FAN_SPEED_RPM_##index); \ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN_SPEED_RPM_##index);\ + static SENSOR_DEVICE_ATTR(fan_direction_##index, S_IRUGO, fan_show_value, NULL, FAN_DIRECTION_##index); + +#define DECLARE_FAN_ATTR(index) \ + &sensor_dev_attr_fan_present_##index.dev_attr.attr, \ + &sensor_dev_attr_fan_fault_##index.dev_attr.attr, \ + &sensor_dev_attr_fan_speed_rpm_##index.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan_direction_##index.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE); +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); + + + +/* transceiver attributes */ +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); +/* fan attributes */ +DECLARE_FAN_SENSOR_DEV_ATTR(1); +DECLARE_FAN_SENSOR_DEV_ATTR(2); +DECLARE_FAN_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); + +static struct attribute *as4630_54pe_cpld_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + DECLARE_SFP_TRANSCEIVER_ATTR(49), + DECLARE_SFP_TRANSCEIVER_ATTR(50), + DECLARE_SFP_TRANSCEIVER_ATTR(51), + DECLARE_SFP_TRANSCEIVER_ATTR(52), + DECLARE_QSFP_TRANSCEIVER_ATTR(53), + DECLARE_QSFP_TRANSCEIVER_ATTR(54), + DECLARE_FAN_ATTR(1), + DECLARE_FAN_ATTR(2), + DECLARE_FAN_ATTR(3), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + NULL +}; + +static const struct attribute_group as4630_54pe_cpld_group = { + .attrs = as4630_54pe_cpld_attributes, +}; + + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as4630_54pe_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) + { + case MODULE_RXLOS_49 ... MODULE_RXLOS_50: + reg=0x5; + mask = 0x1<< (attr->index==MODULE_RXLOS_49?4:0); + break; + case MODULE_TXFAULT_49 ... MODULE_TXFAULT_50: + reg=0x5; + mask=0x1 << (attr->index==MODULE_TXFAULT_49?5:1); + break; + case MODULE_PRESENT_49 ... MODULE_PRESENT_50: + reg=0x5; + mask=0x1 << (attr->index==MODULE_PRESENT_49?6:2); + break; + case MODULE_TXDISABLE_49 ... MODULE_TXDISABLE_50: + reg=0x5; + mask=0x1 << (attr->index==MODULE_TXFAULT_49?7:3); + break; + + case MODULE_RXLOS_51 ... MODULE_RXLOS_52: + reg=0x6; + mask = 0x1<< (attr->index==MODULE_RXLOS_51?4:0); + break; + case MODULE_TXFAULT_51 ... MODULE_TXFAULT_52: + reg=0x6; + mask=0x1 << (attr->index==MODULE_TXFAULT_51?5:1); + break; + case MODULE_PRESENT_51 ... MODULE_PRESENT_52: + reg=0x6; + mask=0x1 << (attr->index==MODULE_PRESENT_51?6:2); + break; + case MODULE_TXDISABLE_51 ... MODULE_TXDISABLE_52: + reg=0x6; + mask=0x1 << (attr->index==MODULE_TXFAULT_51?7:3); + break; + case MODULE_PRESENT_53 ... MODULE_PRESENT_54: + reg=0x21; + mask=0x1 << (attr->index==MODULE_PRESENT_53?0:4); + break; + default: + return 0; + } + + if( attr->index >= MODULE_PRESENT_49 && attr->index <= MODULE_PRESENT_54 ) + { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as4630_54pe_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as4630_54pe_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + reg = 0x9; + switch (attr->index) + { + case MODULE_TXDISABLE_49 ... MODULE_TXDISABLE_50: + reg=0x5; + mask=0x1 << (attr->index==MODULE_TXFAULT_49?7:3); + break; + case MODULE_TXDISABLE_51 ... MODULE_TXDISABLE_52: + reg=0x6; + mask=0x1 << (attr->index==MODULE_TXFAULT_51?7:3); + break; + + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as4630_54pe_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + /* Update tx_disable status */ + if (disable) { + status &= ~mask; + } + else { + status |= mask; + } + status = as4630_54pe_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as4630_54pe_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as4630_54pe_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as4630_54pe_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as4630_54pe_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val) * 625)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as4630_54pe_cpld_write_internal(client, fan_reg[1], duty_cycle_to_reg_val(value)); + as4630_54pe_cpld_write_internal(client, fan_reg[2], duty_cycle_to_reg_val(value)); + return count; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as4630_54pe_cpld_data *data, enum fan_id id) +{ + u8 ret = 1; + + if(id > FAN3_ID) + return 1; + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_fan_val[id+3])) + { + + ret = 0; + } + + return ret; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as4630_54pe_cpld_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as4630_54pe_cpld_data *data = as4630_54pe_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 duty_cycle; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as4630_54pe_cpld_data *data = as4630_54pe_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) + { + case FAN_PRESENT_1: + case FAN_PRESENT_2: + case FAN_PRESENT_3: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_fan_val[0], + attr->index - FAN_PRESENT_1)); + break; + case FAN_DUTY_CYCLE_PERCENTAGE: + duty_cycle = reg_val_to_duty_cycle(data->reg_fan_val[1]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + case FAN_SPEED_RPM_1: + case FAN_SPEED_RPM_2: + case FAN_SPEED_RPM_3: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_fan_val[attr->index-FAN_SPEED_RPM_1+3])); + break; + case FAN_FAULT_1: + case FAN_FAULT_2: + case FAN_FAULT_3: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN_FAULT_1)); + break; + case FAN_DIRECTION_1: + case FAN_DIRECTION_2: + case FAN_DIRECTION_3: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_fan_val[0], + attr->index - FAN_DIRECTION_1)); + break; + default: + break; + } + } + + return ret; +} + +static struct as4630_54pe_cpld_data *as4630_54pe_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as4630_54pe_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as4630_54pe_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_fan_val); i++) { + int status = as4630_54pe_cpld_read_internal(client, fan_reg[i]); + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg 0x%x, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_fan_val[i] = status & 0xff; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +/* +static ssize_t show_power(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as4630_54pe_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + reg=0xc; + mask=0x2; + mutex_lock(&data->update_lock); + status = as4630_54pe_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} +*/ +/* + * I2C init/probing/exit functions + */ +static int as4630_54pe_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as4630_54pe_cpld_data *data; + int ret = -ENODEV; +// int status; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as4630_54pe_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) + { + case as4630_54pe_cpld: + group = &as4630_54pe_cpld_group; + break; + default: + break; + } + + if (group) + { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as4630_54pe_cpld_add_client(client); + + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + ret = PTR_ERR(data->hwmon_dev); + goto exit_free; + } + + + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as4630_54pe_cpld_remove(struct i2c_client *client) +{ + struct as4630_54pe_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as4630_54pe_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) + { + case as4630_54pe_cpld: + group = &as4630_54pe_cpld_group; + break; + default: + break; + } + + if (group) { + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, group); + } + + + kfree(data); + + return 0; +} + +static int as4630_54pe_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as4630_54pe_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as4630_54pe_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as4630_54pe_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as4630_54pe_cpld_read); + +int as4630_54pe_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as4630_54pe_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as4630_54pe_cpld_write); + +static struct i2c_driver as4630_54pe_cpld_driver = { + .driver = { + .name = "as4630_54pe_cpld", + .owner = THIS_MODULE, + }, + .probe = as4630_54pe_cpld_probe, + .remove = as4630_54pe_cpld_remove, + .id_table = as4630_54pe_cpld_id, +}; + +static int __init as4630_54pe_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as4630_54pe_cpld_driver); +} + +static void __exit as4630_54pe_cpld_exit(void) +{ + i2c_del_driver(&as4630_54pe_cpld_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as4630_54pe_cpld_init); +module_exit(as4630_54pe_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/x86-64-accton-as4630-54pe-leds.c b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/x86-64-accton-as4630-54pe-leds.c new file mode 100755 index 000000000000..34c22fd82aa1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/x86-64-accton-as4630-54pe-leds.c @@ -0,0 +1,579 @@ +/* + * A LED driver for the accton_as4630_54pe_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as4630_54pe_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as4630_54pe_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#define DRVNAME "accton_as4630_54pe_led" + +struct accton_as4630_54pe_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[2]; /* only 1 register*/ +}; + +static struct accton_as4630_54pe_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x20|0x40|0x80) +#define LED_MODE_DIAG_GREEN_VALUE (0x20) +#define LED_MODE_DIAG_GREEN_BLINK_VALUE (0x60) +#define LED_MODE_DIAG_AMBER_VALUE (0x80) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x0) + +#define LED_TYPE_PRI_REG_MASK (0x8|0x4) +#define LED_MODE_PRI_GREEN_VALUE 0x4 +#define LED_MODE_PRI_AMBER_VALUE 0x8 +#define LED_MODE_PRI_OFF_VALUE 0x0 + +#define LED_TYPE_POE_REG_MASK (0x2|0x1) +#define LED_MODE_POE_GREEN_VALUE 0x1 +#define LED_MODE_POE_AMBER_VALUE 0x2 +#define LED_MODE_POE_OFF_VALUE 0x0 + +#define LED_TYPE_STK1_REG_MASK 0x20 +#define LED_MODE_STK1_GREEN_VALUE 0x0 +#define LED_MODE_STK1_OFF_VALUE 0x20 + +#define LED_TYPE_STK2_REG_MASK 0x10 +#define LED_MODE_STK2_GREEN_VALUE 0x0 +#define LED_MODE_STK2_OFF_VALUE 0x10 + +#define LED_TYPE_FAN_REG_MASK (0x20|0x10) +#define LED_MODE_FAN_AMBER_VALUE 0x20 +#define LED_MODE_FAN_GREEN_VALUE 0x10 +#define LED_MODE_FAN_OFF_VALUE (0x0) + +#define LED_TYPE_PSU2_REG_MASK (0x8|0x4) +#define LED_MODE_PSU2_AMBER_VALUE 0x8 +#define LED_MODE_PSU2_GREEN_VALUE 0x4 +#define LED_MODE_PSU2_OFF_VALUE (0x0) + +#define LED_TYPE_PSU1_REG_MASK (0x2|0x1) +#define LED_MODE_PSU1_AMBER_VALUE 0x2 +#define LED_MODE_PSU1_GREEN_VALUE 0x1 +#define LED_MODE_PSU1_OFF_VALUE (0x0) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_PRI, + LED_TYPE_POE, + LED_TYPE_STK1, + LED_TYPE_STK2, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as4630_54pe_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as4630_54pe_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as4630_54pe_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + + reg_val = accton_as4630_54pe_led_read_value(reg); + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + + accton_as4630_54pe_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as4630_54pe_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as4630_54pe_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as4630_54pe_led_diag_get(struct led_classdev *cdev) +{ + accton_as4630_54pe_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as4630_54pe_led_pri_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as4630_54pe_led_set(led_cdev, led_light_mode, LED_TYPE_PRI); +} + +static enum led_brightness accton_as4630_54pe_led_pri_get(struct led_classdev *cdev) +{ + accton_as4630_54pe_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PRI, ledctl->reg_val[0]); +} + +static void accton_as4630_54pe_led_poe_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as4630_54pe_led_set(led_cdev, led_light_mode, LED_TYPE_POE); +} + +static enum led_brightness accton_as4630_54pe_led_poe_get(struct led_classdev *cdev) +{ + accton_as4630_54pe_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_POE, ledctl->reg_val[1]); +} + + +static void accton_as4630_54pe_led_stk1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as4630_54pe_led_set(led_cdev, led_light_mode, LED_TYPE_STK1); +} + +static enum led_brightness accton_as4630_54pe_led_stk1_get(struct led_classdev *cdev) +{ + accton_as4630_54pe_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_STK1, ledctl->reg_val[1]); +} + +static void accton_as4630_54pe_led_stk2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as4630_54pe_led_set(led_cdev, led_light_mode, LED_TYPE_STK2); +} + +static enum led_brightness accton_as4630_54pe_led_stk2_get(struct led_classdev *cdev) +{ + accton_as4630_54pe_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_STK2, ledctl->reg_val[1]); +} + +static void accton_as4630_54pe_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as4630_54pe_led_set(led_cdev, led_light_mode, LED_TYPE_FAN); +} + +static enum led_brightness accton_as4630_54pe_led_fan_get(struct led_classdev *cdev) +{ + accton_as4630_54pe_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + +static void accton_as4630_54pe_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as4630_54pe_led_set(led_cdev, led_light_mode, LED_TYPE_PSU1); +} + +static enum led_brightness accton_as4630_54pe_led_psu1_get(struct led_classdev *cdev) +{ + accton_as4630_54pe_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[0]); +} + +static void accton_as4630_54pe_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as4630_54pe_led_set(led_cdev, led_light_mode, LED_TYPE_PSU2); +} + +static enum led_brightness accton_as4630_54pe_led_psu2_get(struct led_classdev *cdev) +{ + accton_as4630_54pe_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[0]); +} + +static struct led_classdev accton_as4630_54pe_leds[] = { + [LED_TYPE_DIAG] = { + .name = "diag", + .default_trigger = "unused", + .brightness_set = accton_as4630_54pe_led_diag_set, + .brightness_get = accton_as4630_54pe_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN, + }, + [LED_TYPE_PRI] = { + .name = "pri", + .default_trigger = "unused", + .brightness_set = accton_as4630_54pe_led_pri_set, + .brightness_get = accton_as4630_54pe_led_pri_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_POE] = { + .name = "poe", + .default_trigger = "unused", + .brightness_set = accton_as4630_54pe_led_poe_set, + .brightness_get = accton_as4630_54pe_led_poe_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_STK1] = { + .name = "stk1", + .default_trigger = "unused", + .brightness_set = accton_as4630_54pe_led_stk1_set, + .brightness_get = accton_as4630_54pe_led_stk1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN, + }, + [LED_TYPE_STK2] = { + .name = "stk2", + .default_trigger = "unused", + .brightness_set = accton_as4630_54pe_led_stk2_set, + .brightness_get = accton_as4630_54pe_led_stk2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN, + }, + [LED_TYPE_FAN] = { + .name = "fan", + .default_trigger = "unused", + .brightness_set = accton_as4630_54pe_led_fan_set, + .brightness_get = accton_as4630_54pe_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "psu1", + .default_trigger = "unused", + .brightness_set = accton_as4630_54pe_led_psu1_set, + .brightness_get = accton_as4630_54pe_led_psu1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "psu2", + .default_trigger = "unused", + .brightness_set = accton_as4630_54pe_led_psu2_set, + .brightness_get = accton_as4630_54pe_led_psu2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as4630_54pe_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as4630_54pe_leds); i++) { + led_classdev_suspend(&accton_as4630_54pe_leds[i]); + } + + return 0; +} + +static int accton_as4630_54pe_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as4630_54pe_leds); i++) { + led_classdev_resume(&accton_as4630_54pe_leds[i]); + } + + return 0; +} + +static int accton_as4630_54pe_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as4630_54pe_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as4630_54pe_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as4630_54pe_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as4630_54pe_leds[i]); + } + } + + return ret; +} + +static int accton_as4630_54pe_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as4630_54pe_leds); i++) { + led_classdev_unregister(&accton_as4630_54pe_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as4630_54pe_led_driver = { + .probe = accton_as4630_54pe_led_probe, + .remove = accton_as4630_54pe_led_remove, + .suspend = accton_as4630_54pe_led_suspend, + .resume = accton_as4630_54pe_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as4630_54pe_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as4630_54pe_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as4630_54pe_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as4630_54pe_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as4630_54pe_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as4630_54pe_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as4630_54pe_led_driver); + kfree(ledctl); +} + +module_init(accton_as4630_54pe_led_init); +module_exit(accton_as4630_54pe_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as4630_54pe_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/x86-64-accton-as4630-54pe-psu.c b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/x86-64-accton-as4630-54pe-psu.c new file mode 100755 index 000000000000..798a5656410e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/x86-64-accton-as4630-54pe-psu.c @@ -0,0 +1,320 @@ +/* + * An hwmon driver for accton as4630_54pe Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODEL_NAME 20 +#define MAX_SERIAL_NUMBER 18 + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as4630_54pe_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as4630_54pe_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as4630_54pe_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MAX_MODEL_NAME]; /* Model name, read from eeprom */ + char serial_number[MAX_SERIAL_NUMBER]; +}; + +static struct as4630_54pe_psu_data *as4630_54pe_psu_update_device(struct device *dev); + +enum as4630_54pe_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + + +static struct attribute *as4630_54pe_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_number.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as4630_54pe_psu_data *data = as4630_54pe_psu_update_device(dev); + u8 status = 0; + + //printk("data->status=0x%x, attr->index=%d,data->index=%d \n", data->status, attr->index, data->index); + if (attr->index == PSU_PRESENT) { + if(data->index==0) + status = !( (data->status >> 5) & 0x1); + else + status = !( (data->status >> 1) & 0x1); + } + else { /* PSU_POWER_GOOD */ + if(data->index==0) + status = ( (data->status >> 6) & 0x1); + else + status = ( (data->status >> 2) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as4630_54pe_psu_data *data = as4630_54pe_psu_update_device(dev); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case PSU_MODEL_NAME: + ptr = data->model_name; + break; + case PSU_SERIAL_NUMBER: + ptr = data->serial_number; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as4630_54pe_psu_group = { + .attrs = as4630_54pe_psu_attributes, +}; + +static int as4630_54pe_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as4630_54pe_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as4630_54pe_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as4630_54pe_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as4630_54pe_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as4630_54pe_psu_remove(struct i2c_client *client) +{ + struct as4630_54pe_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as4630_54pe_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as4630_54pe_psu1, + as4630_54pe_psu2 +}; + +static const struct i2c_device_id as4630_54pe_psu_id[] = { + { "as4630_54pe_psu1", as4630_54pe_psu1 }, + { "as4630_54pe_psu2", as4630_54pe_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as4630_54pe_psu_id); + +static struct i2c_driver as4630_54pe_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as4630_54pe_psu", + }, + .probe = as4630_54pe_psu_probe, + .remove = as4630_54pe_psu_remove, + .id_table = as4630_54pe_psu_id, + .address_list = normal_i2c, +}; + +static int as4630_54pe_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as4630_54pe_psu_data *as4630_54pe_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as4630_54pe_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as4630_54pe update\n"); + + /* Read psu status */ + status = as4630_54pe_cpld_read(0x60, 0x22); + //printk("status=0x%x in %s\n", status, __FUNCTION__); + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial_number, 0, sizeof(data->serial_number)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as4630_54pe_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + printk("unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + + } + /* Read from offset 0x2e ~ 0x3d (16 bytes) */ + status = as4630_54pe_psu_read_block(client, 0x35,data->serial_number, MAX_SERIAL_NUMBER); + if (status < 0) + { + data->serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x2e)\n", client->addr); + printk("unable to read model name from (0x%x) offset(0x2e)\n", client->addr); + } + data->serial_number[MAX_SERIAL_NUMBER-1]='\0'; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as4630_54pe_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as4630_54pe_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-platform-monitor-fan.service new file mode 100644 index 000000000000..9f562d2a05e1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS4630-54PE Platform Monitoring FAN service +Before=pmon.service +After=as4630-54pe-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as4630_54pe_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-platform-monitor-psu.service new file mode 100644 index 000000000000..28d6013aa19d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS4630-54PE Platform Monitoring PSU service +Before=pmon.service +After=as4630-54pe-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as4630_54pe_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-platform-monitor.service new file mode 100644 index 000000000000..8ed60fca95f3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS4630-54PE Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as4630_54pe_util.py install +ExecStart=/usr/local/bin/accton_as4630_54pe_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/setup.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/setup.py new file mode 100755 index 000000000000..34e6bb59de52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as4630_54pe', + version='1.0', + description='Module to initialize Accton AS4630-54PE platforms', + + packages=['as4630_54pe'], + package_dir={'as4630_54pe': 'as4630-54pe/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/README b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/README new file mode 100755 index 000000000000..f656d2b0a855 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/README @@ -0,0 +1,67 @@ +Copyright (C) 2019 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS4630-54pe has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are at module dir. +2. A operational script, accton_as4630_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + Run "accton_as4630_util.py install" to install drivers. + +To initialize the system, run "accton_as4630_util.py install". +To clean up the drivers & devices, run "accton_as4630_util.py clean". +To dump information of sensors, run "accton_as4630_util.py show". +To dump SFP EEPROM, run "accton_as4630_util.py sff". +To set fan speed, run "accton_as4630_util.py set fan". +To enable/disable SFP emission, run "accton_as4630_util.py set sfp". +To set system LEDs' color, run "accton_as4630_util.py set led" +For more information, run "accton_as4630_util.py --help". + +==================================================================== +Besides applying accton_as4630_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor.py new file mode 100755 index 000000000000..8913233366e2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -* +# Copyright (c) 2019 Edgecore Networks Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. +# +# HISTORY: +# mm/dd/yyyy (A.D.)# +# 10/24/2019:Jostar create for as4630_54pe thermal plan +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time + import commands + from as4630_54pe.fanutil import FanUtil + from as4630_54pe.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as4630_54pe_monitor' + +global log_file +global log_level + + + + + +# Temperature Policy +# If any fan fail , please set fan speed register to 16 +# The max value of fan speed register is 14 +# LM77(48)+LM75(4B)+LM75(4A) > 140, Set 10 +# LM77(48)+LM75(4B)+LM75(4A) > 150, Set 12 +# LM77(48)+LM75(4B)+LM75(4A) > 160, Set 14 +# LM77(48)+LM75(4B)+LM75(4A) < 140, Set 8 +# LM77(48)+LM75(4B)+LM75(4A) < 150, Set 10 +# LM77(48)+LM75(4B)+LM75(4A) < 160, Set 12 +# Reset DUT:LM77(48)>=70C +# +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + +fan_policy_state=0 +fan_fail=0 +alarm_state = 0 #0->default or clear, 1-->alarm detect +test_temp = 0 +test_temp_list = [0, 0, 0] +temp_test_data=0 +test_temp_revert=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + # static temp var + temp = 0 + new_pwm = 0 + pwm=0 + ori_pwm = 0 + default_pwm=0x4 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + + def get_state_from_fan_policy(self, temp, policy): + state=0 + for i in range(0, len(policy)): + if (temp > policy[i][2]): #temp_down + if temp <= policy[i][3]: #temp_up + state =i + + return state + + def manage_fans(self): + global fan_policy_state + global fan_fail + global test_temp + global test_temp_list + global alarm_state + global temp_test_data + global test_temp_revert + LEVEL_FAN_MIN=0 + LEVEL_FAN_NORMAL=1 + LEVEL_FAN_MID=2 + LEVEL_FAN_HIGH=3 + LEVEL_TEMP_CRITICAL=4 + fan_policy = { + LEVEL_FAN_MIN: [50, 8, 0, 140000], + LEVEL_FAN_NORMAL: [62, 10, 140000, 150000], + LEVEL_FAN_MID: [75, 12, 150000, 160000], + LEVEL_FAN_HIGH: [88, 14, 160000, 240000], + LEVEL_TEMP_CRITICAL: [100, 16, 240000, 300000], + } + temp = [0, 0 , 0] + temp_fail=0 + thermal = ThermalUtil() + fan = FanUtil() + ori_duty_cycle=fan.get_fan_duty_cycle() + new_duty_cycle=0 + + if test_temp==0: + for i in range(0,3): + temp[i]=thermal._get_thermal_val(i+1) + if temp[i]==0 or temp[i]==None: + temp_fail=1 + logging.warning("Get temp-%d fail", i); + return False + else: + if test_temp_revert==0: + temp_test_data=temp_test_data+2000 + else: + temp_test_data=temp_test_data-2000 + + for i in range(0,3): + temp[i]=test_temp_list[i]+temp_test_data + fan_fail=0 + + temp_val=0 + for i in range(0,3): + if temp[i]==None: + break + temp_val+=temp[i] + + #Check Fan status + for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): + if fan.get_fan_status(i)==0: + new_pwm=100 + logging.warning('Fan_%d fail, set pwm to 100',i) + if test_temp==0: + fan_fail=1 + fan.set_fan_duty_cycle(new_pwm) + break + else: + fan_fail=0 + + ori_state=fan_policy_state + fan_policy_state=self.get_state_from_fan_policy(temp_val, fan_policy) + + if fan_policy_state > LEVEL_TEMP_CRITICAL or fan_policy_state < LEVEL_FAN_MIN: + logging.error("Get error fan current_state\n"); + return 0 + + #Decision : Decide new fan pwm percent. + if fan_fail==0 and ori_duty_cycle!=fan_policy[fan_policy_state][0]: + new_duty_cycle = fan_policy[fan_policy_state][0]; + fan.set_fan_duty_cycle(new_duty_cycle) + + if temp[0] >= 70000: #LM75-48 + #critical case*/ + logging.critical('Alarm-Critical for temperature critical is detected, reset DUT') + cmd_str="i2cset -y -f 3 0x60 0x4 0xE4" + time.sleep(2); + status, output = commands.getstatusoutput(cmd_str) + + #logging.debug('ori_state=%d, current_state=%d, temp_val=%d\n\n',ori_state, fan_policy_state, temp_val) + + if ori_state < LEVEL_FAN_HIGH: + if fan_policy_state >= LEVEL_FAN_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + + if fan_policy_state < LEVEL_FAN_MID: + if alarm_state==1: + logging.info('Alarm for temperature high is cleared') + alarm_state=0 + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global test_temp + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdlt:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + if sys.argv[1]== '-t': + if len(sys.argv)!=5: + print "temp test, need input three temp" + return 0 + + i=0 + for x in range(2, 5): + test_temp_list[i]= int(sys.argv[x])*1000 + i=i+1 + test_temp = 1 + log_level = logging.DEBUG + print test_temp_list + + fan = FanUtil() + fan.set_fan_duty_cycle(50) + print "set default fan speed to 50%" + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) #10sec + +if __name__ == '__main__': + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor_fan.py new file mode 100755 index 000000000000..c775e86874b8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor_fan.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 5/15/2019: Jostar create for as4630-54pe +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as4630_54pe_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.fan_num = 3 + self.fan_path = "/sys/bus/i2c/devices/3-0060/" + self.present = { + 0: "fan_present_1", + 1: "fan_present_2", + 2: "fan_present_3", + } + + self.fault = { + 0: "fan_fault_1", + 1: "fan_fault_2", + 2: "fan_fault_3", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor_psu.py new file mode 100755 index 000000000000..02f4541127a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_monitor_psu.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 5/15/2019: Jostar create for as4630-54pe +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as4630_54pe_monitor_psu' + +global log_file +global log_level + + +psu_state=[2, 2] +psu_status_state=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "10-0050", + 1: "11-0051", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + PSU_STATUS_IDLE =2 + + global psu_state + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=1: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_status_state[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=0: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_IDLE + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "0": + if psu_status_state[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d failed is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_NO_POWER + else: + if psu_state[idx]==PSU_STATE_INSERT: + if psu_status_state[idx]!=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py new file mode 100755 index 000000000000..4039119288a0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py @@ -0,0 +1,573 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + +PROJECT_NAME = 'as4630_54pe' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':54} + + +led_prefix ='/sys/devices/platform/as4630_54pe_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as4630_54pe_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['54-0066'], + 'thermal': ['54-004c', '55-0048','55-0049', '55-004a', '55-004b'] , + 'psu': ['49-0050','50-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'], + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_ ', 'module_tx_disable_']} + +sfp_map = [18, 19, 20, 21, 22, 23] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-3/new_device', + +'echo as4630_54pe_cpld 0x60 > /sys/bus/i2c/devices/i2c-3/new_device', + +'echo lm77 0x48 > /sys/bus/i2c/devices/i2c-14/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-25/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-24/new_device', + + +# PSU-1 +'echo as4630_54pe_psu1 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ype1200am 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', + +# PSU-2 +'echo as4630_54pe_psu2 0x51> /sys/bus/i2c/devices/i2c-11/new_device', +'echo ype1200am 0x59 > /sys/bus/i2c/devices/i2c-11/new_device', + +#EERPOM +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +# Disable CPLD debug mode +cpld_set =[ +'i2cset -y -f 3 0x60 0x2a 0xff', +'i2cset -y -f 3 0x60 0x2b 0xff', +'i2cset -y -f 3 0x60 0x86 0x89' +] + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + print "TEST" + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + +#'modprobe cpr_4011_4mxx', + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe ym2651y', +'modprobe x86_64_accton_as4630_54pe_cpld', +'modprobe x86_64_accton_as4630_54pe_leds', +'modprobe x86_64_accton_as4630_54pe_psu', +'modprobe optoe'] + +def driver_install(): + global FORCE + + ret=log_os_system("lsmod|grep i2c_ismt",1) + my_log("rmmond i2cismt") + log_os_system("rmmod i2c_ismt", 1) + log_os_system("rmmod i2c_i801", 1) + log_os_system("modprobe i2c-i801", 1) + time.sleep(1) + log_os_system("modprobe i2c-ismt", 1) + + + + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + lst = rm.split(" ") + print "lst=%s"%lst + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + print("Check SFP") + for i in range(0,len(sfp_map)): + if(i < 4): + opt='optoe2' + else: + opt='optoe1' + status, output =log_os_system("echo " + str(opt) + " 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + status, output =log_os_system("echo port"+str(i+49) + " > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + print "not device_exist()" + return False + return True + +def do_install(): + if driver_inserted() == False: + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + + for i in range(len(cpld_set)): + status, output = log_os_system(cpld_set[i], 1) + if status: + if FORCE == 0: + return status + return + +def do_uninstall(): + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + print "node=%s"%node + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/fanutil.py new file mode 100755 index 000000000000..c16771e214e4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/fanutil.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 5 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + + FAN_NODE_NUM_OF_MAP = 6 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 3 + FAN_NODE_DUTY_IDX_OF_MAP = 4 + FANR_NODE_FAULT_IDX_OF_MAP = 5 + FANR_NODE_SPEED_IDX_OF_MAP = 6 + + BASE_VAL_PATH = '/sys/devices/platform/as5712_54x_fan/{0}' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan1_speed_rpm', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + (FAN_NUM_1_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan1_duty_cycle_percentage', + (FAN_NUM_1_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr1_fault', + (FAN_NUM_1_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr1_speed_rpm', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan2_speed_rpm', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + (FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + (FAN_NUM_2_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr2_fault', + (FAN_NUM_2_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr2_speed_rpm', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan3_speed_rpm', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + (FAN_NUM_3_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan3_duty_cycle_percentage', + (FAN_NUM_3_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr3_fault', + (FAN_NUM_3_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr3_speed_rpm', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan4_speed_rpm', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + (FAN_NUM_4_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan4_duty_cycle_percentage', + (FAN_NUM_4_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr4_fault', + (FAN_NUM_4_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr4_speed_rpm', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan5_speed_rpm', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + (FAN_NUM_5_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan5_duty_cycle_percentage', + (FAN_NUM_5_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr5_fault', + (FAN_NUM_5_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr5_speed_rpm', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + def get_fan_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) + + def set_fan_duty_cycle(self, fan_num, val): + return self._set_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP, val) + + def get_fanr_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + logging.debug('GET. FANR fault. fan_num, %d', fan_num) + return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/thermalutil.py new file mode 100755 index 000000000000..5b8f890e8819 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/classes/thermalutil.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['61', '48'], + THERMAL_NUM_2_IDX: ['62', '49'], + THERMAL_NUM_3_IDX: ['63', '4a'], + } + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/Makefile new file mode 100755 index 000000000000..39fe78bf8cae --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= i2c-mux-accton_as5712_54x_cpld.o \ + accton_as5712_54x_fan.o leds-accton_as5712_54x.o accton_as5712_54x_psu.o \ + cpr_4011_4mxx.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_fan.c new file mode 100644 index 000000000000..3f74e3f375a9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_fan.c @@ -0,0 +1,456 @@ +/* + * A hwmon driver for the Accton as5710 54x fan contrl + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as5712_54x_fan" + +#define FAN_MAX_NUMBER 5 +#define FAN_SPEED_CPLD_TO_RPM_STEP 150 +#define FAN_SPEED_PRECENT_TO_CPLD_STEP 5 +#define FAN_DUTY_CYCLE_MIN 0 /* 10% ??*/ +#define FAN_DUTY_CYCLE_MAX 100 /* 100% */ + +#define CPLD_REG_FAN_STATUS_OFFSET 0xC +#define CPLD_REG_FANR_STATUS_OFFSET 0x1F +#define CPLD_REG_FAN_DIRECTION_OFFSET 0x1E + +#define CPLD_FAN1_REG_SPEED_OFFSET 0x10 +#define CPLD_FAN2_REG_SPEED_OFFSET 0x11 +#define CPLD_FAN3_REG_SPEED_OFFSET 0x12 +#define CPLD_FAN4_REG_SPEED_OFFSET 0x13 +#define CPLD_FAN5_REG_SPEED_OFFSET 0x14 + +#define CPLD_FANR1_REG_SPEED_OFFSET 0x18 +#define CPLD_FANR2_REG_SPEED_OFFSET 0x19 +#define CPLD_FANR3_REG_SPEED_OFFSET 0x1A +#define CPLD_FANR4_REG_SPEED_OFFSET 0x1B +#define CPLD_FANR5_REG_SPEED_OFFSET 0x1C + +#define CPLD_REG_FAN_PWM_CYCLE_OFFSET 0xD + +#define CPLD_FAN1_INFO_BIT_MASK 0x1 +#define CPLD_FAN2_INFO_BIT_MASK 0x2 +#define CPLD_FAN3_INFO_BIT_MASK 0x4 +#define CPLD_FAN4_INFO_BIT_MASK 0x8 +#define CPLD_FAN5_INFO_BIT_MASK 0x10 + +#define PROJECT_NAME + +#define LOCAL_DEBUG 0 + +static struct accton_as5712_54x_fan *fan_data = NULL; + +struct accton_as5712_54x_fan { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[FAN_MAX_NUMBER]; /* inner first fan status */ + u32 speed[FAN_MAX_NUMBER]; /* inner first fan speed */ + u8 direction[FAN_MAX_NUMBER]; /* reconrd the direction of inner first and second fans */ + u32 duty_cycle[FAN_MAX_NUMBER]; /* control the speed of inner first and second fans */ + u8 r_status[FAN_MAX_NUMBER]; /* inner second fan status */ + u32 r_speed[FAN_MAX_NUMBER]; /* inner second fan speed */ +}; + +/*******************/ +#define MAKE_FAN_MASK_OR_REG(name,type) \ + CPLD_FAN##type##1_##name, \ + CPLD_FAN##type##2_##name, \ + CPLD_FAN##type##3_##name, \ + CPLD_FAN##type##4_##name, \ + CPLD_FAN##type##5_##name, + +/* fan related data + */ +static const u8 fan_info_mask[] = { + MAKE_FAN_MASK_OR_REG(INFO_BIT_MASK,) +}; + +static const u8 fan_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,) +}; + +static const u8 fanr_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,R) +}; + +/*******************/ +#define DEF_FAN_SET(id) \ + FAN##id##_FAULT, \ + FAN##id##_SPEED, \ + FAN##id##_DUTY_CYCLE, \ + FAN##id##_DIRECTION, \ + FANR##id##_FAULT, \ + FANR##id##_SPEED, + +enum sysfs_fan_attributes { + DEF_FAN_SET(1) + DEF_FAN_SET(2) + DEF_FAN_SET(3) + DEF_FAN_SET(4) + DEF_FAN_SET(5) +}; +/*******************/ +static void accton_as5712_54x_fan_update_device(struct device *dev); +static int accton_as5712_54x_fan_read_value(u8 reg); +static int accton_as5712_54x_fan_write_value(u8 reg, u8 value); + +static ssize_t fan_set_duty_cycle(struct device *dev, + struct device_attribute *da,const char *buf, size_t count); +static ssize_t fan_show_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t show_name(struct device *dev, struct device_attribute *da, + char *buf); +extern int as5712_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5712_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + + +/*******************/ +#define _MAKE_SENSOR_DEVICE_ATTR(prj, id, id2) \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, \ + fan_set_duty_cycle, FAN##id##_DUTY_CYCLE); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_direction, S_IRUGO, fan_show_value, NULL, FAN##id##_DIRECTION); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_fault, S_IRUGO, fan_show_value, NULL, FANR##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED);\ + static SENSOR_DEVICE_ATTR(prj##fan##id##_input, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id2##_input, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED);\ + static SENSOR_DEVICE_ATTR(prj##fan##id##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fan##id2##_fault, S_IRUGO, fan_show_value, NULL, FANR##id##_FAULT); + +#define MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) _MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) + +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 1, 11) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 2, 12) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 3, 13) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 4, 14) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 5, 15) + +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +/*******************/ + +#define _MAKE_FAN_ATTR(prj, id, id2) \ + &sensor_dev_attr_##prj##fan##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_duty_cycle_percentage.dev_attr.attr,\ + &sensor_dev_attr_##prj##fan##id##_direction.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_speed_rpm.dev_attr.attr,\ + &sensor_dev_attr_##prj##fan##id##_input.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id2##_input.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id2##_fault.dev_attr.attr, + + +#define MAKE_FAN_ATTR(prj, id, id2) _MAKE_FAN_ATTR(prj, id, id2) + +static struct attribute *accton_as5712_54x_fan_attributes[] = { + /* fan related attributes */ + MAKE_FAN_ATTR(PROJECT_NAME,1, 11) + MAKE_FAN_ATTR(PROJECT_NAME,2, 12) + MAKE_FAN_ATTR(PROJECT_NAME,3, 13) + MAKE_FAN_ATTR(PROJECT_NAME,4, 14) + MAKE_FAN_ATTR(PROJECT_NAME,5, 15) + &sensor_dev_attr_name.dev_attr.attr, + NULL +}; +/*******************/ + +/* fan related functions + */ +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + ssize_t ret = 0; + int data_index, type_index; + + accton_as5712_54x_fan_update_device(dev); + + if (fan_data->valid == 0) { + return ret; + } + + type_index = attr->index%FAN2_FAULT; + data_index = attr->index/FAN2_FAULT; + + switch (type_index) { + case FAN1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->status[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->speed[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DUTY_CYCLE: + ret = sprintf(buf, "%d\n", fan_data->duty_cycle[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DIRECTION: + ret = sprintf(buf, "%d\n", fan_data->direction[data_index]); /* presnet, need to modify*/ + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->r_status[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->r_speed[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + default: + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d] \n", __FUNCTION__, __LINE__); + break; + } + + return ret; +} + +static ssize_t show_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf(buf, "%s\n", DRVNAME); +} +/*******************/ +static ssize_t fan_set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < FAN_DUTY_CYCLE_MIN || value > FAN_DUTY_CYCLE_MAX) + return -EINVAL; + + accton_as5712_54x_fan_write_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET, value/FAN_SPEED_PRECENT_TO_CPLD_STEP); + + fan_data->valid = 0; + + return count; +} + +static const struct attribute_group accton_as5712_54x_fan_group = { + .attrs = accton_as5712_54x_fan_attributes, +}; + +static int accton_as5712_54x_fan_read_value(u8 reg) +{ + return as5712_54x_cpld_read(0x60, reg); +} + +static int accton_as5712_54x_fan_write_value(u8 reg, u8 value) +{ + return as5712_54x_cpld_write(0x60, reg, value); +} + +static void accton_as5712_54x_fan_update_device(struct device *dev) +{ + int speed, r_speed, fault, r_fault, ctrl_speed, direction; + int i; + + mutex_lock(&fan_data->update_lock); + + if (LOCAL_DEBUG) + printk ("Starting accton_as5712_54x_fan update \n"); + + if (!(time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || !fan_data->valid)) { + /* do nothing */ + goto _exit; + } + + fan_data->valid = 0; + + if (LOCAL_DEBUG) + printk ("Starting accton_as5712_54x_fan update 2 \n"); + + fault = accton_as5712_54x_fan_read_value(CPLD_REG_FAN_STATUS_OFFSET); + r_fault = accton_as5712_54x_fan_read_value(CPLD_REG_FANR_STATUS_OFFSET); + direction = accton_as5712_54x_fan_read_value(CPLD_REG_FAN_DIRECTION_OFFSET); + ctrl_speed = accton_as5712_54x_fan_read_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET); + + if ( (fault < 0) || (r_fault < 0) || (direction < 0) || (ctrl_speed < 0) ) + { + if (LOCAL_DEBUG) + printk ("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + if (LOCAL_DEBUG) + printk ("[fan:] fault:%d, r_fault=%d, direction=%d, ctrl_speed=%d \n",fault, r_fault, direction, ctrl_speed); + + for (i=0; istatus[i] = (fault & fan_info_mask[i]) >> i; + if (LOCAL_DEBUG) + printk ("[fan%d:] fail=%d \n",i, fan_data->status[i]); + + fan_data->r_status[i] = (r_fault & fan_info_mask[i]) >> i; + fan_data->direction[i] = (direction & fan_info_mask[i]) >> i; + fan_data->duty_cycle[i] = ctrl_speed * FAN_SPEED_PRECENT_TO_CPLD_STEP; + + /* fan speed + */ + speed = accton_as5712_54x_fan_read_value(fan_speed_reg[i]); + r_speed = accton_as5712_54x_fan_read_value(fanr_speed_reg[i]); + if ( (speed < 0) || (r_speed < 0) ) + { + if (LOCAL_DEBUG) + printk ("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + if (LOCAL_DEBUG) + printk ("[fan%d:] speed:%d, r_speed=%d \n", i, speed, r_speed); + + fan_data->speed[i] = speed * FAN_SPEED_CPLD_TO_RPM_STEP; + fan_data->r_speed[i] = r_speed * FAN_SPEED_CPLD_TO_RPM_STEP; + } + + /* finish to update */ + fan_data->last_updated = jiffies; + fan_data->valid = 1; + +_exit: + mutex_unlock(&fan_data->update_lock); +} + +static int accton_as5712_54x_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &accton_as5712_54x_fan_group); + if (status) { + goto exit; + + } + + fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(fan_data->hwmon_dev)) { + status = PTR_ERR(fan_data->hwmon_dev); + goto exit_remove; + } + + dev_info(&pdev->dev, "accton_as5712_54x_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &accton_as5712_54x_fan_group); +exit: + return status; +} + +static int accton_as5712_54x_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&fan_data->pdev->dev.kobj, &accton_as5712_54x_fan_group); + + return 0; +} + + + +static struct platform_driver accton_as5712_54x_fan_driver = { + .probe = accton_as5712_54x_fan_probe, + .remove = accton_as5712_54x_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5712_54x_fan_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5712_54x_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct accton_as5712_54x_fan), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as5712_54x_fan_driver); + goto exit; + } + + mutex_init(&fan_data->update_lock); + fan_data->valid = 0; + + fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fan_data->pdev)) { + ret = PTR_ERR(fan_data->pdev); + platform_driver_unregister(&accton_as5712_54x_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as5712_54x_fan_exit(void) +{ + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&accton_as5712_54x_fan_driver); + kfree(fan_data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5712_54x_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_as5712_54x_fan_init); +module_exit(accton_as5712_54x_fan_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_psu.c new file mode 100755 index 000000000000..9a0d1dae58ba --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_psu.c @@ -0,0 +1,371 @@ +/* + * An hwmon driver for accton as5712_54x Power Module + * + * Copyright (C) 2015 Accton Technology Corporation. + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as5712_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as5712_54x_cpld_read(unsigned short cpld_addr, u8 reg); +static int as5712_54x_psu_model_name_get(struct device *dev); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5712_54x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[14]; /* Model name, read from eeprom */ +}; + +static struct as5712_54x_psu_data *as5712_54x_psu_update_device(struct device *dev); + +enum as5712_54x_psu_sysfs_attributes { + PSU_INDEX, + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as5712_54x_psu_attributes[] = { + &sensor_dev_attr_psu_index.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_psu_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->index); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5712_54x_psu_data *data = as5712_54x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as5712_54x_psu_data *data = as5712_54x_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + if (as5712_54x_psu_model_name_get(dev) < 0) { + return -ENXIO; + } + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as5712_54x_psu_group = { + .attrs = as5712_54x_psu_attributes, +}; + +static int as5712_54x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5712_54x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5712_54x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5712_54x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5712_54x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5712_54x_psu_remove(struct i2c_client *client) +{ + struct as5712_54x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5712_54x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as5712_54x_psu1, + as5712_54x_psu2 +}; + +static const struct i2c_device_id as5712_54x_psu_id[] = { + { "as5712_54x_psu1", as5712_54x_psu1 }, + { "as5712_54x_psu2", as5712_54x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5712_54x_psu_id); + +static struct i2c_driver as5712_54x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5712_54x_psu", + }, + .probe = as5712_54x_psu_probe, + .remove = as5712_54x_psu_remove, + .id_table = as5712_54x_psu_id, + .address_list = normal_i2c, +}; + +static int as5712_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +enum psu_type { + PSU_YM_2401_JCR, /* AC110V - F2B */ + PSU_YM_2401_JDR, /* AC110V - B2F */ + PSU_CPR_4011_4M11, /* AC110V - F2B */ + PSU_CPR_4011_4M21, /* AC110V - B2F */ + PSU_CPR_6011_2M11, /* AC110V - F2B */ + PSU_CPR_6011_2M21, /* AC110V - B2F */ + PSU_UM400D_01G, /* DC48V - F2B */ + PSU_UM400D01_01G /* DC48V - B2F */ +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_YM_2401_JCR, 0x20, 11, "YM-2401JCR"}, +{PSU_YM_2401_JDR, 0x20, 11, "YM-2401JDR"}, +{PSU_CPR_4011_4M11, 0x26, 13, "CPR-4011-4M11"}, +{PSU_CPR_4011_4M21, 0x26, 13, "CPR-4011-4M21"}, +{PSU_CPR_6011_2M11, 0x26, 13, "CPR-6011-2M11"}, +{PSU_CPR_6011_2M21, 0x26, 13, "CPR-6011-2M21"}, +{PSU_UM400D_01G, 0x50, 9, "um400d01G"}, +{PSU_UM400D01_01G, 0x50, 12, "um400d01-01G"}, +}; + +static int as5712_54x_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as5712_54x_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR) { + /* Skip the meaningless data byte 8*/ + data->model_name[8] = data->model_name[9]; + data->model_name[9] = data->model_name[10]; + data->model_name[10] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} + +static struct as5712_54x_psu_data *as5712_54x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + + dev_dbg(&client->dev, "Starting as5712_54x update\n"); + data->valid = 0; + + + /* Read psu status */ + status = as5712_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as5712_54x_psu_init(void) +{ + return i2c_add_driver(&as5712_54x_psu_driver); +} + +static void __exit as5712_54x_psu_exit(void) +{ + i2c_del_driver(&as5712_54x_psu_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as5712_54x_psu driver"); +MODULE_LICENSE("GPL"); + +module_init(as5712_54x_psu_init); +module_exit(as5712_54x_psu_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_sfp.c new file mode 100755 index 000000000000..d236057c4e59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/accton_as5712_54x_sfp.c @@ -0,0 +1,825 @@ +/* + * An hwmon driver for accton as5712_54x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_OF_SFF_PORT 54 +#define SFP_PORT_MAX 48 +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x61 +#define I2C_ADDR_CPLD3 0x62 +#define CPLD3_OFFSET_QSFP_MOD_RST 0x15 +#define CPLD3_OFFSET_QSFP_LPMODE 0x16 + + +#define BIT_INDEX(i) (1ULL << (i)) + +#if 0 +static ssize_t show_status(struct device *dev, struct device_attribute *da,char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +static int as5712_54x_sfp_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as5712_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5712_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +#endif + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5712_54x_sfp_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + int port; /* Front port index */ + char eeprom[256]; /* eeprom data */ + u64 status[4]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => is_present + 1 => tx_fail + 2 => tx_disable + 3 => rx_loss */ +}; + +/* The table maps active port to cpld port. + * Array index 0 is for active port 1, + * index 1 for active port 2, and so on. + * The array content implies cpld port index. + */ +static const u8 cpld_to_front_port_table[] = +{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 52, 50, 53, 51, 54}; + +#define CPLD_PORT_TO_FRONT_PORT(port) (cpld_to_front_port_table[port]) + +static struct as5712_54x_sfp_data *as5712_54x_sfp_update_device(struct device *dev, int update_eeprom); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_lp_mode(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_lp_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +extern int as5712_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5712_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +enum as5712_54x_sfp_sysfs_attributes { + SFP_IS_PRESENT, + SFP_TX_FAULT, + SFP_TX_DISABLE, + SFP_RX_LOSS, + SFP_PORT_NUMBER, + SFP_EEPROM, + SFP_RX_LOS_ALL, + SFP_IS_PRESENT_ALL, + SFP_LP_MODE, + SFP_MOD_RST, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_status, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, show_status, NULL, SFP_TX_FAULT); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, show_status, set_tx_disable, SFP_TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_rx_loss, S_IRUGO, show_status,NULL, SFP_RX_LOSS); +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM); +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, show_status,NULL, SFP_RX_LOS_ALL); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_status,NULL, SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_lp_mode, S_IWUSR | S_IRUGO, get_lp_mode, set_lp_mode, SFP_LP_MODE); +static SENSOR_DEVICE_ATTR(sfp_mod_rst, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, SFP_MOD_RST); + +static struct attribute *as5712_54x_sfp_attributes[] = { + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_eeprom.dev_attr.attr, + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_lp_mode.dev_attr.attr, + &sensor_dev_attr_sfp_mod_rst.dev_attr.attr, + NULL +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5712_54x_sfp_data *data; + u8 val; + int values[7]; + + /* Error-check the CPLD read results. */ +#define VALIDATED_READ(_buf, _rv, _read_expr, _invert) \ + do { \ + _rv = (_read_expr); \ + if(_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if(_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ + } while(0) + + if(attr->index == SFP_RX_LOS_ALL) { + /* + * Report the RX_LOS status for all ports. + * This does not depend on the currently active SFP selector. + */ + + /* RX_LOS Ports 1-8 */ + VALIDATED_READ(buf, values[0], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x0F), 0); + /* RX_LOS Ports 9-16 */ + VALIDATED_READ(buf, values[1], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x10), 0); + /* RX_LOS Ports 17-24 */ + VALIDATED_READ(buf, values[2], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x11), 0); + /* RX_LOS Ports 25-32 */ + VALIDATED_READ(buf, values[3], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x0F), 0); + /* RX_LOS Ports 33-40 */ + VALIDATED_READ(buf, values[4], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x10), 0); + /* RX_LOS Ports 41-48 */ + VALIDATED_READ(buf, values[5], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x11), 0); + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + if(attr->index == SFP_IS_PRESENT_ALL) { + /* + * Report the SFP_PRESENCE status for all ports. + * This does not depend on the currently active SFP selector. + */ + + /* SFP_PRESENT Ports 1-8 */ + VALIDATED_READ(buf, values[0], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x6), 1); + /* SFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x7), 1); + /* SFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x8), 1); + /* SFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x6), 1); + /* SFP_PRESENT Ports 33-40 */ + VALIDATED_READ(buf, values[4], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x7), 1); + /* SFP_PRESENT Ports 41-48 */ + VALIDATED_READ(buf, values[5], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x8), 1); + /* QSFP_PRESENT Ports 49-54 */ + VALIDATED_READ(buf, values[6], as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14), 1); + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6] & 0x3F); + } + /* + * The remaining attributes are gathered on a per-selected-sfp basis. + */ + data = as5712_54x_sfp_update_device(dev, 0); + if (attr->index == SFP_IS_PRESENT) { + val = (data->status[attr->index] & BIT_INDEX(data->port)) ? 0 : 1; + } + else { + val = (data->status[attr->index] & BIT_INDEX(data->port)) ? 1 : 0; + } + + return sprintf(buf, "%d", val); +} + +static ssize_t get_lp_mode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + int port_bit; + int status = -EINVAL; + + /* Low power mode is not supported for SFP ports(1-48) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + mutex_lock(&data->update_lock); + + port_bit = data->port - SFP_PORT_MAX; + cpld_val = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_LPMODE); + cpld_val = cpld_val & 0x3F; + cpld_val = cpld_val & BIT_INDEX(port_bit); + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", cpld_val>>port_bit); + + mutex_unlock(&data->update_lock); + + return status; +} + +static ssize_t set_lp_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + long mode; + int error, port_bit; + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + port_bit = data->port - SFP_PORT_MAX; + error = kstrtol(buf, 10, &mode); + if (error) { + return error; + } + mutex_lock(&data->update_lock); + + cpld_val = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_LPMODE); + /* Update lp_mode status */ + if (mode) + { + cpld_val |= BIT_INDEX(port_bit); + } + else + { + cpld_val &=~BIT_INDEX(port_bit); + } + as5712_54x_i2c_cpld_write(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_LPMODE, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + int port_bit; + int status = -EINVAL; + + /* Low power mode is not supported for SFP ports(1-48) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + mutex_lock(&data->update_lock); + + port_bit = data->port - SFP_PORT_MAX; + cpld_val = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_MOD_RST); + cpld_val = cpld_val & 0x3F; + cpld_val = cpld_val & BIT_INDEX(port_bit); + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", cpld_val>>port_bit); + + mutex_unlock(&data->update_lock); + + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + long reset; + int error, port_bit; + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + port_bit = data->port - SFP_PORT_MAX; + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + mutex_lock(&data->update_lock); + + cpld_val = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_MOD_RST); + /* Update lp_mode status */ + if (reset) + { + cpld_val |= BIT_INDEX(port_bit); + } + else + { + cpld_val &=~BIT_INDEX(port_bit); + } + as5712_54x_i2c_cpld_write(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_MOD_RST, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + unsigned short cpld_addr = 0; + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long disable; + int error; + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port >= SFP_PORT_MAX) { + return -EINVAL; + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + if(data->port < 24) { + cpld_addr = I2C_ADDR_CPLD2; + cpld_reg = 0xC + data->port / 8; + cpld_bit = 1 << (data->port % 8); + } + else { + cpld_addr = I2C_ADDR_CPLD3; + cpld_reg = 0xC + (data->port - 24) / 8; + cpld_bit = 1 << (data->port % 8); + } + + cpld_val = as5712_54x_i2c_cpld_read(cpld_addr, cpld_reg); + + /* Update tx_disable status */ + if (disable) { + data->status[SFP_TX_DISABLE] |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->status[SFP_TX_DISABLE] &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + as5712_54x_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as5712_54x_sfp_data *data = as5712_54x_sfp_update_device(dev, 1); + + if (!data->valid) { + return 0; + } + + if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) != 0) { + return 0; + } + + memcpy(buf, data->eeprom, sizeof(data->eeprom)); + + return sizeof(data->eeprom); +} + +static const struct attribute_group as5712_54x_sfp_group = { + .attrs = as5712_54x_sfp_attributes, +}; + +static int as5712_54x_sfp_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5712_54x_sfp_data *data; + int status; + + extern int platform_accton_as5712_54x(void); + if(!platform_accton_as5712_54x()) { + return -ENODEV; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5712_54x_sfp_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + i2c_set_clientdata(client, data); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5712_54x_sfp_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sfp '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5712_54x_sfp_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5712_54x_sfp_remove(struct i2c_client *client) +{ + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5712_54x_sfp_group); + kfree(data); + + return 0; +} + +enum port_numbers { +as5712_54x_sfp1, as5712_54x_sfp2, as5712_54x_sfp3, as5712_54x_sfp4, +as5712_54x_sfp5, as5712_54x_sfp6, as5712_54x_sfp7, as5712_54x_sfp8, +as5712_54x_sfp9, as5712_54x_sfp10, as5712_54x_sfp11,as5712_54x_sfp12, +as5712_54x_sfp13, as5712_54x_sfp14, as5712_54x_sfp15,as5712_54x_sfp16, +as5712_54x_sfp17, as5712_54x_sfp18, as5712_54x_sfp19,as5712_54x_sfp20, +as5712_54x_sfp21, as5712_54x_sfp22, as5712_54x_sfp23,as5712_54x_sfp24, +as5712_54x_sfp25, as5712_54x_sfp26, as5712_54x_sfp27,as5712_54x_sfp28, +as5712_54x_sfp29, as5712_54x_sfp30, as5712_54x_sfp31,as5712_54x_sfp32, +as5712_54x_sfp33, as5712_54x_sfp34, as5712_54x_sfp35,as5712_54x_sfp36, +as5712_54x_sfp37, as5712_54x_sfp38, as5712_54x_sfp39,as5712_54x_sfp40, +as5712_54x_sfp41, as5712_54x_sfp42, as5712_54x_sfp43,as5712_54x_sfp44, +as5712_54x_sfp45, as5712_54x_sfp46, as5712_54x_sfp47,as5712_54x_sfp48, +as5712_54x_sfp49, as5712_54x_sfp52, as5712_54x_sfp50,as5712_54x_sfp53, +as5712_54x_sfp51, as5712_54x_sfp54 +}; + +static const struct i2c_device_id as5712_54x_sfp_id[] = { +{ "as5712_54x_sfp1", as5712_54x_sfp1 }, { "as5712_54x_sfp2", as5712_54x_sfp2 }, +{ "as5712_54x_sfp3", as5712_54x_sfp3 }, { "as5712_54x_sfp4", as5712_54x_sfp4 }, +{ "as5712_54x_sfp5", as5712_54x_sfp5 }, { "as5712_54x_sfp6", as5712_54x_sfp6 }, +{ "as5712_54x_sfp7", as5712_54x_sfp7 }, { "as5712_54x_sfp8", as5712_54x_sfp8 }, +{ "as5712_54x_sfp9", as5712_54x_sfp9 }, { "as5712_54x_sfp10", as5712_54x_sfp10 }, +{ "as5712_54x_sfp11", as5712_54x_sfp11 }, { "as5712_54x_sfp12", as5712_54x_sfp12 }, +{ "as5712_54x_sfp13", as5712_54x_sfp13 }, { "as5712_54x_sfp14", as5712_54x_sfp14 }, +{ "as5712_54x_sfp15", as5712_54x_sfp15 }, { "as5712_54x_sfp16", as5712_54x_sfp16 }, +{ "as5712_54x_sfp17", as5712_54x_sfp17 }, { "as5712_54x_sfp18", as5712_54x_sfp18 }, +{ "as5712_54x_sfp19", as5712_54x_sfp19 }, { "as5712_54x_sfp20", as5712_54x_sfp20 }, +{ "as5712_54x_sfp21", as5712_54x_sfp21 }, { "as5712_54x_sfp22", as5712_54x_sfp22 }, +{ "as5712_54x_sfp23", as5712_54x_sfp23 }, { "as5712_54x_sfp24", as5712_54x_sfp24 }, +{ "as5712_54x_sfp25", as5712_54x_sfp25 }, { "as5712_54x_sfp26", as5712_54x_sfp26 }, +{ "as5712_54x_sfp27", as5712_54x_sfp27 }, { "as5712_54x_sfp28", as5712_54x_sfp28 }, +{ "as5712_54x_sfp29", as5712_54x_sfp29 }, { "as5712_54x_sfp30", as5712_54x_sfp30 }, +{ "as5712_54x_sfp31", as5712_54x_sfp31 }, { "as5712_54x_sfp32", as5712_54x_sfp32 }, +{ "as5712_54x_sfp33", as5712_54x_sfp33 }, { "as5712_54x_sfp34", as5712_54x_sfp34 }, +{ "as5712_54x_sfp35", as5712_54x_sfp35 }, { "as5712_54x_sfp36", as5712_54x_sfp36 }, +{ "as5712_54x_sfp37", as5712_54x_sfp37 }, { "as5712_54x_sfp38", as5712_54x_sfp38 }, +{ "as5712_54x_sfp39", as5712_54x_sfp39 }, { "as5712_54x_sfp40", as5712_54x_sfp40 }, +{ "as5712_54x_sfp41", as5712_54x_sfp41 }, { "as5712_54x_sfp42", as5712_54x_sfp42 }, +{ "as5712_54x_sfp43", as5712_54x_sfp43 }, { "as5712_54x_sfp44", as5712_54x_sfp44 }, +{ "as5712_54x_sfp45", as5712_54x_sfp45 }, { "as5712_54x_sfp46", as5712_54x_sfp46 }, +{ "as5712_54x_sfp47", as5712_54x_sfp47 }, { "as5712_54x_sfp48", as5712_54x_sfp48 }, +{ "as5712_54x_sfp49", as5712_54x_sfp49 }, { "as5712_54x_sfp50", as5712_54x_sfp50 }, +{ "as5712_54x_sfp51", as5712_54x_sfp51 }, { "as5712_54x_sfp52", as5712_54x_sfp52 }, +{ "as5712_54x_sfp53", as5712_54x_sfp53 }, { "as5712_54x_sfp54", as5712_54x_sfp54 }, + +{} +}; +MODULE_DEVICE_TABLE(i2c, as5712_54x_sfp_id); + +static struct i2c_driver as5712_54x_sfp_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5712_54x_sfp", + }, + .probe = as5712_54x_sfp_probe, + .remove = as5712_54x_sfp_remove, + .id_table = as5712_54x_sfp_id, + .address_list = normal_i2c, +}; + +static int as5712_54x_sfp_read_byte(struct i2c_client *client, u8 command, u8 *data) +{ + int result = i2c_smbus_read_byte_data(client, command); + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 0; + +abort: + return result; +} + +#define ALWAYS_UPDATE_DEVICE 1 + +static struct as5712_54x_sfp_data *as5712_54x_sfp_update_device(struct device *dev, int update_eeprom) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (ALWAYS_UPDATE_DEVICE || time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + int i = 0, j = 0; + + data->valid = 0; + //dev_dbg(&client->dev, "Starting as5712_54x sfp status update\n"); + memset(data->status, 0, sizeof(data->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 12; j++) { + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2+i, 0x6+j); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + goto exit; + } + + data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* + * Bring QSFPs out of reset, + * This is a temporary fix until the QSFP+_MOD_RST register + * can be exposed through the driver. + */ + as5712_54x_i2c_cpld_write(I2C_ADDR_CPLD3, 0x15, 0x3F); + + /* Read present status of port 49-54(QSFP port) */ + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + } + else { + data->status[SFP_IS_PRESENT] |= (u64)status << 48; + } + + if (update_eeprom) { + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) == 0) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom); i++) { + status = as5712_54x_sfp_read_byte(client, i, data->eeprom + i); + + if (status < 0) { + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", + CPLD_PORT_TO_FRONT_PORT(data->port)); + goto exit; + } + } + } + } + + data->valid = 1; + data->last_updated = jiffies; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as5712_54x_sfp_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as5712_54x_sfp driver"); +MODULE_LICENSE("GPL"); + +#if 0 + int i = 0, j = 0; + + data->valid = 0; + //dev_dbg(&client->dev, "Starting as5712_54x sfp update\n"); + memset(data->status, 0, sizeof(data->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 12; j++) { + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2+i, 0x6+j); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + continue; + } + + data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* Read present status of port 49-54(QSFP port) */ + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + } + else { + data->status[SFP_IS_PRESENT] |= (u64)status << 48; + } +#endif + +/* Reserver to prevent from CPLD port mapping is changed + */ +#if 0 +BIT_INDEX(port_present_index[data->port]) +/* The bit index of is_present field read from CPLD + * Array index 0 is for as5712_54x_sfp1, + * index 1 is for as5712_54x_sfp2, and so on. + */ +static const int port_present_index[] = { + 4, 5, 6, 7, 9, 8, 11, 10, + 0, 1, 2, 3, 12, 13, 14, 15, +16, 17, 18, 19, 28, 29, 30, 31, +20, 21, 22, 23, 24, 25, 26, 27 +}; +#endif + +#if 0 +static struct as5712_54x_sfp_data *as5712_54x_sfp_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_sfp_data *data = i2c_get_clientdata(client); + int status = -1; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->status_last_updated + HZ + HZ / 2) + || !data->status_valid) { + int status = -1; + int i = 0, j = 0; + + data->status_valid = 0; + //dev_dbg(&client->dev, "Starting as5712_54x sfp status update\n"); + memset(data->status, 0, sizeof(data->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 12; j++) { + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD2+i, 0x6+j); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + goto exit; + } + + data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* + * Bring QSFPs out of reset, + * This is a temporary fix until the QSFP+_MOD_RST register + * can be exposed through the driver. + */ + as5712_54x_i2c_cpld_write(I2C_ADDR_CPLD3, 0x15, 0x3F); + + /* Read present status of port 49-54(QSFP port) */ + status = as5712_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + } + else { + data->status[SFP_IS_PRESENT] |= (u64)status << 48; + } + + data->status_valid = 1; + data->status_last_updated = jiffies; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static struct as5712_54x_sfp_data *as5712_54x_sfp_update_eeprom(struct device *dev) +{ + struct as5712_54x_sfp_data *data = NULL; + + data = as5712_54x_sfp_update_status(dev); + + if (data == NULL || data->status_valid == 0) { + data->eeprom_valid = 0; + return data; + } + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->eeprom_last_updated + HZ + HZ / 2) + || !data->eeprom_valid) { + int status = -1; + int i = 0; + + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) == 0) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom)/I2C_SMBUS_BLOCK_MAX; i++) { + status = as5712_54x_sfp_read_block(client, i*I2C_SMBUS_BLOCK_MAX, + data->eeprom+(i*I2C_SMBUS_BLOCK_MAX), + I2C_SMBUS_BLOCK_MAX); + if (status < 0) { + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", + CPLD_PORT_TO_FRONT_PORT(data->port)); + goto exit; + } + } + } + + data->eeprom_last_updated = jiffies; + data->eeprom_valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} +#endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/cpr_4011_4mxx.c new file mode 120000 index 000000000000..fd43cc1f1c77 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/cpr_4011_4mxx.c @@ -0,0 +1 @@ +../../common/modules/cpr_4011_4mxx.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/i2c-mux-accton_as5712_54x_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/i2c-mux-accton_as5712_54x_cpld.c new file mode 100755 index 000000000000..9dbac9ca337e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/i2c-mux-accton_as5712_54x_cpld.c @@ -0,0 +1,1421 @@ +/* + * An I2C multiplexer dirver for accton as5712 CPLD + * + * Copyright (C) 2015 Accton Technology Corporation. + * Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as5712_54x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define NUM_OF_CPLD1_CHANS 0x0 +#define NUM_OF_CPLD2_CHANS 0x18 +#define NUM_OF_CPLD3_CHANS 0x1E +#define CPLD_CHANNEL_SELECT_REG 0x2 +#define CPLD_DESELECT_CHANNEL 0xFF + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_mux_type { + as5712_54x_cpld2, + as5712_54x_cpld3, + as5712_54x_cpld1 +}; + +struct as5712_54x_cpld_data { + enum cpld_mux_type type; + struct i2c_client *client; + u8 last_chan; /* last register value */ + + struct device *hwmon_dev; + struct mutex update_lock; +}; + +struct chip_desc { + u8 nchans; + u8 deselectChan; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [as5712_54x_cpld1] = { + .nchans = NUM_OF_CPLD1_CHANS, + .deselectChan = CPLD_DESELECT_CHANNEL, + }, + [as5712_54x_cpld2] = { + .nchans = NUM_OF_CPLD2_CHANS, + .deselectChan = CPLD_DESELECT_CHANNEL, + }, + [as5712_54x_cpld3] = { + .nchans = NUM_OF_CPLD3_CHANS, + .deselectChan = CPLD_DESELECT_CHANNEL, + } +}; + +static const struct i2c_device_id as5712_54x_cpld_mux_id[] = { + { "as5712_54x_cpld1", as5712_54x_cpld1 }, + { "as5712_54x_cpld2", as5712_54x_cpld2 }, + { "as5712_54x_cpld3", as5712_54x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as5712_54x_cpld_mux_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_LPMODE_ATTR_ID(index) MODULE_LPMODE_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as5712_54x_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), + TRANSCEIVER_LPMODE_ATTR_ID(49), + TRANSCEIVER_LPMODE_ATTR_ID(50), + TRANSCEIVER_LPMODE_ATTR_ID(51), + TRANSCEIVER_LPMODE_ATTR_ID(52), + TRANSCEIVER_LPMODE_ATTR_ID(53), + TRANSCEIVER_LPMODE_ATTR_ID(54), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_lp_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as5712_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5712_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +#define DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_lp_mode_##index, S_IRUGO | S_IWUSR, show_status, set_lp_mode, MODULE_LPMODE_##index); \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, show_status, set_mode_reset, MODULE_RESET_##index) + +#define DECLARE_QSFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_lp_mode_##index.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##index.dev_attr.attr + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); + +static struct attribute *as5712_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5712_54x_cpld1_group = { + .attrs = as5712_54x_cpld1_attributes, +}; + +static struct attribute *as5712_54x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + NULL +}; + +static const struct attribute_group as5712_54x_cpld2_group = { + .attrs = as5712_54x_cpld2_attributes, +}; + +static struct attribute *as5712_54x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + DECLARE_QSFP_TRANSCEIVER_ATTR(49), + DECLARE_QSFP_TRANSCEIVER_ATTR(50), + DECLARE_QSFP_TRANSCEIVER_ATTR(51), + DECLARE_QSFP_TRANSCEIVER_ATTR(52), + DECLARE_QSFP_TRANSCEIVER_ATTR(53), + DECLARE_QSFP_TRANSCEIVER_ATTR(54), + NULL +}; + +static const struct attribute_group as5712_54x_cpld3_group = { + .attrs = as5712_54x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status, num_regs = 0; + u8 values[4] = {0}; + u8 regs[] = {0x6, 0x7, 0x8, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + + mutex_lock(&data->update_lock); + + num_regs = (data->type == as5712_54x_cpld2) ? 3 : 4; + + for (i = 0; i < num_regs; i++) { + status = as5712_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + if (data->type == as5712_54x_cpld2) { + status = sprintf(buf, "%.2x %.2x %.2x\n", + values[0], values[1], values[2]); + } + else { /* as5712_54x_cpld3 */ + values[3] &= 0x3F; + status = sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + } + + return status; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[3] = {0}; + u8 regs[] = {0xF, 0x10, 0x11}; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as5712_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_40: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_33); + break; + case MODULE_PRESENT_41 ... MODULE_PRESENT_48: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_41); + break; + case MODULE_PRESENT_49: + reg = 0x14; + mask = 0x1; + break; + case MODULE_PRESENT_50: + reg = 0x14; + mask = 0x4; + break; + case MODULE_PRESENT_51: + reg = 0x14; + mask = 0x10; + break; + case MODULE_PRESENT_52: + reg = 0x14; + mask = 0x2; + break; + case MODULE_PRESENT_53: + reg = 0x14; + mask = 0x8; + break; + case MODULE_PRESENT_54: + reg = 0x14; + mask = 0x20; + break; + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_8: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_1); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_16: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_9); + break; + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_24: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_TXFAULT_17); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_32: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_40: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_33); + break; + case MODULE_TXFAULT_41 ... MODULE_TXFAULT_48: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_TXFAULT_41); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_1); + break; + case MODULE_RXLOS_9 ... MODULE_RXLOS_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_9); + break; + case MODULE_RXLOS_17 ... MODULE_RXLOS_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_RXLOS_17); + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_RXLOS_33 ... MODULE_RXLOS_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_33); + break; + case MODULE_RXLOS_41 ... MODULE_RXLOS_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_RXLOS_41); + break; + case MODULE_LPMODE_49 ... MODULE_LPMODE_54: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + break; + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_49); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_54) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as5712_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5712_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5712_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_lp_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + + long on; + int status= -ENOENT; + u8 reg = 0x16, mask = 0; + + if(attr->index < MODULE_LPMODE_49 || attr->index > MODULE_LPMODE_54) + return status; + + status = kstrtol(buf, 10, &on); + if (status) { + return status; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5712_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + + /* Update lp_mode status */ + if (on) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5712_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; + +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + + long on; + int status= -ENOENT; + u8 reg = 0x15, mask = 0; + + if(attr->index < MODULE_RESET_49 || attr->index > MODULE_RESET_54) + return status; + + status = kstrtol(buf, 10, &on); + if (status) { + return status; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5712_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + mask = 0x1 << (attr->index - MODULE_RESET_49); + + /* Update tx_disable status */ + if (on) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5712_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; + +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + int status; + u32 addr, val; + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as5712_54x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int as5712_54x_cpld_mux_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + unsigned long orig_jiffies; + unsigned short flags; + union i2c_smbus_data data; + int try; + s32 res = -EIO; + + data.byte = val; + flags = client->flags; + flags &= I2C_M_TEN | I2C_CLIENT_PEC; + + if (adap->algo->smbus_xfer) { + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (res = 0, try = 0; try <= adap->retries; try++) { + res = adap->algo->smbus_xfer(adap, client->addr, flags, + I2C_SMBUS_WRITE, CPLD_CHANNEL_SELECT_REG, + I2C_SMBUS_BYTE_DATA, &data); + if (res != -EAGAIN) + break; + if (time_after(jiffies, + orig_jiffies + adap->timeout)) + break; + } + } + + return res; +} + +static int as5712_54x_cpld_mux_select_chan(struct i2c_mux_core *muxc, + u32 chan) +{ + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + u8 regval; + int ret = 0; + + regval = chan; + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + ret = as5712_54x_cpld_mux_reg_write(muxc->parent, client, regval); + data->last_chan = regval; + } + + return ret; +} + +static int as5712_54x_cpld_mux_deselect_mux(struct i2c_mux_core *muxc, + u32 chan) +{ + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + /* Deselect active channel */ + data->last_chan = chips[data->type].deselectChan; + + return as5712_54x_cpld_mux_reg_write(muxc->parent, client, data->last_chan); +} + +static void as5712_54x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as5712_54x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as5712_54x_cpld_mux_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + int num, force, class; + struct i2c_mux_core *muxc; + struct as5712_54x_cpld_data *data; + int ret = 0; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + muxc = i2c_mux_alloc(adap, &client->dev, + chips[id->driver_data].nchans, sizeof(*data), 0, + as5712_54x_cpld_mux_select_chan, as5712_54x_cpld_mux_deselect_mux); + if (!muxc) + return -ENOMEM; + + i2c_set_clientdata(client, muxc); + data = i2c_mux_priv(muxc); + data->client = client; + data->type = id->driver_data; + data->last_chan = chips[data->type].deselectChan; /* force the first selection */ + mutex_init(&data->update_lock); + + /* Now create an adapter for each channel */ + for (num = 0; num < chips[data->type].nchans; num++) { + force = 0; /* dynamic adap number */ + class = 0; /* no class by default */ + + ret = i2c_mux_add_adapter(muxc, force, num, class); + + if (ret) { + dev_err(&client->dev, + "failed to register multiplexed adapter" + " %d as bus %d\n", num, force); + goto add_mux_failed; + } + } + + /* Register sysfs hooks */ + switch (data->type) { + case as5712_54x_cpld1: + group = &as5712_54x_cpld1_group; + break; + case as5712_54x_cpld2: + group = &as5712_54x_cpld2_group; + break; + case as5712_54x_cpld3: + group = &as5712_54x_cpld3_group; + + /* Bring QSFPs out of reset */ + as5712_54x_cpld_write_internal(client, 0x15, 0x3F); + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto add_mux_failed; + } + } + + if (chips[data->type].nchans) { + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s\n", + num, client->name); + } + else { + dev_info(&client->dev, + "device %s registered\n", client->name); + } + + as5712_54x_cpld_add_client(client); + + return 0; + +add_mux_failed: + i2c_mux_del_adapters(muxc); + return ret; +} + +static int as5712_54x_cpld_mux_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_mux_priv(muxc); + const struct attribute_group *group = NULL; + + as5712_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as5712_54x_cpld1: + group = &as5712_54x_cpld1_group; + break; + case as5712_54x_cpld2: + group = &as5712_54x_cpld2_group; + break; + case as5712_54x_cpld3: + group = &as5712_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + i2c_mux_del_adapters(muxc); + + return 0; +} + +static int as5712_54x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as5712_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as5712_54x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5712_54x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5712_54x_cpld_read); + +int as5712_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5712_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5712_54x_cpld_write); + +static struct i2c_driver as5712_54x_cpld_mux_driver = { + .driver = { + .name = "as5712_54x_cpld", + .owner = THIS_MODULE, + }, + .probe = as5712_54x_cpld_mux_probe, + .remove = as5712_54x_cpld_mux_remove, + .id_table = as5712_54x_cpld_mux_id, +}; + +static int __init as5712_54x_cpld_mux_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as5712_54x_cpld_mux_driver); +} + +static void __exit as5712_54x_cpld_mux_exit(void) +{ + i2c_del_driver(&as5712_54x_cpld_mux_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton as5712-54x CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as5712_54x_cpld_mux_init); +module_exit(as5712_54x_cpld_mux_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/leds-accton_as5712_54x.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/leds-accton_as5712_54x.c new file mode 100755 index 000000000000..36988aecfc49 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/leds-accton_as5712_54x.c @@ -0,0 +1,593 @@ +/* + * A LED driver for the accton_as5712_54x_led + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include + +extern int as5712_54x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as5712_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as5712_54x_led" + +struct accton_as5712_54x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[4]; /* Register value, 0 = LOC/DIAG/FAN LED + 1 = PSU1/PSU2 LED + 2 = FAN1-4 LED + 3 = FAN5-6 LED */ +}; + +static struct accton_as5712_54x_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_TYPE_PSU1_REG_MASK 0x03 +#define LED_MODE_PSU1_GREEN_MASK 0x02 +#define LED_MODE_PSU1_AMBER_MASK 0x01 +#define LED_MODE_PSU1_OFF_MASK 0x03 +#define LED_MODE_PSU1_AUTO_MASK 0x00 + +#define LED_TYPE_PSU2_REG_MASK 0x0C +#define LED_MODE_PSU2_GREEN_MASK 0x08 +#define LED_MODE_PSU2_AMBER_MASK 0x04 +#define LED_MODE_PSU2_OFF_MASK 0x0C +#define LED_MODE_PSU2_AUTO_MASK 0x00 + +#define LED_TYPE_DIAG_REG_MASK 0x0C +#define LED_MODE_DIAG_GREEN_MASK 0x08 +#define LED_MODE_DIAG_AMBER_MASK 0x04 +#define LED_MODE_DIAG_OFF_MASK 0x0C + +#define LED_TYPE_FAN_REG_MASK 0x03 +#define LED_MODE_FAN_GREEN_MASK 0x02 +#define LED_MODE_FAN_AMBER_MASK 0x01 +#define LED_MODE_FAN_OFF_MASK 0x03 +#define LED_MODE_FAN_AUTO_MASK 0x00 + +#define LED_TYPE_FAN1_REG_MASK 0x03 +#define LED_TYPE_FAN2_REG_MASK 0x0C +#define LED_TYPE_FAN3_REG_MASK 0x30 +#define LED_TYPE_FAN4_REG_MASK 0xC0 +#define LED_TYPE_FAN5_REG_MASK 0x03 +#define LED_TYPE_FAN6_REG_MASK 0x0C + +#define LED_MODE_FANX_GREEN_MASK 0x01 +#define LED_MODE_FANX_RED_MASK 0x02 +#define LED_MODE_FANX_OFF_MASK 0x00 + +#define LED_TYPE_LOC_REG_MASK 0x30 +#define LED_MODE_LOC_ON_MASK 0x00 +#define LED_MODE_LOC_OFF_MASK 0x10 +#define LED_MODE_LOC_BLINK_MASK 0x20 + +static const u8 led_reg[] = { + 0xA, /* LOC/DIAG/FAN LED*/ + 0xB, /* PSU1/PSU2 LED */ + 0x16, /* FAN1-4 LED */ + 0x17, /* FAN4-6 LED */ +}; + +enum led_type { + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_DIAG, + LED_TYPE_FAN, + LED_TYPE_FAN1, + LED_TYPE_FAN2, + LED_TYPE_FAN3, + LED_TYPE_FAN4, + LED_TYPE_FAN5, + LED_TYPE_LOC +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_AUTO, +}; + +struct led_type_mode { + enum led_type type; + int type_mask; + enum led_light_mode mode; + int mode_mask; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU1_AUTO_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU2_AUTO_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AUTO, LED_MODE_FAN_AUTO_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_GREEN, LED_MODE_DIAG_GREEN_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_AMBER, LED_MODE_DIAG_AMBER_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_OFF, LED_MODE_DIAG_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER, LED_MODE_LOC_ON_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_OFF, LED_MODE_LOC_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER_BLINK, LED_MODE_LOC_BLINK_MASK} +}; + + +struct fanx_info_s { + u8 cname; /* device name */ + enum led_type type; + u8 reg_id; /* map to led_reg & reg_val */ +}; + +static struct fanx_info_s fanx_info[] = { + {'1', LED_TYPE_FAN1, 2}, + {'2', LED_TYPE_FAN2, 2}, + {'3', LED_TYPE_FAN3, 2}, + {'4', LED_TYPE_FAN4, 2}, + {'5', LED_TYPE_FAN5, 3} +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + } + + return reg_val; +} + +static int accton_as5712_54x_led_read_value(u8 reg) +{ + return as5712_54x_cpld_read(0x60, reg); +} + +static int accton_as5712_54x_led_write_value(u8 reg, u8 value) +{ + return as5712_54x_cpld_write(0x60, reg, value); +} + +static void accton_as5712_54x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as5712_54x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as5712_54x_led_read_value(led_reg[i]); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5712_54x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + + reg_val = accton_as5712_54x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as5712_54x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5712_54x_led_psu_1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness accton_as5712_54x_led_psu_1_get(struct led_classdev *cdev) +{ + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void accton_as5712_54x_led_psu_2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness accton_as5712_54x_led_psu_2_get(struct led_classdev *cdev) +{ + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static void accton_as5712_54x_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN); +} + +static enum led_brightness accton_as5712_54x_led_fan_get(struct led_classdev *cdev) +{ + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + + +static void accton_as5712_54x_led_fanx_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (led_cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1); + return; + } + } +} + + +static enum led_brightness accton_as5712_54x_led_fanx_get(struct led_classdev *cdev) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]); + } + } + + + return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[2]); +} + + +static void accton_as5712_54x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_as5712_54x_led_diag_get(struct led_classdev *cdev) +{ + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as5712_54x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5712_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness accton_as5712_54x_led_loc_get(struct led_classdev *cdev) +{ + accton_as5712_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static struct led_classdev accton_as5712_54x_leds[] = { + [LED_TYPE_PSU1] = { + .name = "accton_as5712_54x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_psu_1_set, + .brightness_get = accton_as5712_54x_led_psu_1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as5712_54x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_psu_2_set, + .brightness_get = accton_as5712_54x_led_psu_2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "accton_as5712_54x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fan_set, + .brightness_get = accton_as5712_54x_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN1] = { + .name = "accton_as5712_54x_led::fan1", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fanx_set, + .brightness_get = accton_as5712_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN2] = { + .name = "accton_as5712_54x_led::fan2", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fanx_set, + .brightness_get = accton_as5712_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN3] = { + .name = "accton_as5712_54x_led::fan3", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fanx_set, + .brightness_get = accton_as5712_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN4] = { + .name = "accton_as5712_54x_led::fan4", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fanx_set, + .brightness_get = accton_as5712_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN5] = { + .name = "accton_as5712_54x_led::fan5", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_fanx_set, + .brightness_get = accton_as5712_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_DIAG] = { + .name = "accton_as5712_54x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_diag_set, + .brightness_get = accton_as5712_54x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_LOC] = { + .name = "accton_as5712_54x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as5712_54x_led_loc_set, + .brightness_get = accton_as5712_54x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as5712_54x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as5712_54x_leds); i++) { + led_classdev_suspend(&accton_as5712_54x_leds[i]); + } + + return 0; +} + +static int accton_as5712_54x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as5712_54x_leds); i++) { + led_classdev_resume(&accton_as5712_54x_leds[i]); + } + + return 0; +} + +static int accton_as5712_54x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as5712_54x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as5712_54x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as5712_54x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as5712_54x_leds[i]); + } + } + + return ret; +} + +static int accton_as5712_54x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as5712_54x_leds); i++) { + led_classdev_unregister(&accton_as5712_54x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as5712_54x_led_driver = { + .probe = accton_as5712_54x_led_probe, + .remove = accton_as5712_54x_led_remove, + .suspend = accton_as5712_54x_led_suspend, + .resume = accton_as5712_54x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5712_54x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5712_54x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as5712_54x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as5712_54x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as5712_54x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as5712_54x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as5712_54x_led_driver); + kfree(ledctl); +} + +module_init(accton_as5712_54x_led_init); +module_exit(accton_as5712_54x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5712_54x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/service/as5712-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/service/as5712-platform-monitor.service new file mode 100755 index 000000000000..da5d283a6d61 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/service/as5712-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS5712-54X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as5712_util.py install +ExecStart=/usr/local/bin/accton_as5712_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/setup.py new file mode 100755 index 000000000000..f4cb5f960a4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as5712_54x', + version='1.0', + description='Module to initialize Accton AS5712-54X platforms', + + packages=['as5712_54x'], + package_dir={'as5712_54x': 'as5712-54x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/README new file mode 100755 index 000000000000..44e03cab5f52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_monitor.py new file mode 100755 index 000000000000..f032088dc525 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_monitor.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 05/08/2019: Roy Lee, changed for as5712-54x. +# ------------------------------------------------------------------ + +try: + import getopt + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from as5712_54x.fanutil import FanUtil + from as5712_54x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as5712_monitor' +DUTY_MAX = 100 + +global log_file +global log_level + +# Make a class we can use to capture stdout and sterr in the log +class accton_as5712_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + FAN_LEV1_UP_TEMP = 57700 # temperature + FAN_LEV1_DOWN_TEMP = 0 # unused + FAN_LEV1_SPEED_PERC = DUTY_MAX # percentage*/ + + FAN_LEV2_UP_TEMP = 53000 + FAN_LEV2_DOWN_TEMP = 52700 + FAN_LEV2_SPEED_PERC = 80 + + FAN_LEV3_UP_TEMP = 49500 + FAN_LEV3_DOWN_TEMP = 47700 + FAN_LEV3_SPEED_PERC = 65 + + FAN_LEV4_UP_TEMP = 0 # unused + FAN_LEV4_DOWN_TEMP = 42700 + FAN_LEV4_SPEED_PERC = 40 + + + thermal = ThermalUtil() + fan = FanUtil() + + temp1 = thermal.get_thermal_1_val() + if temp1 is None: + return False + + temp2 = thermal.get_thermal_2_val() + if temp2 is None: + return False + + new_temp = (temp1 + temp2) / 2 + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_stat = fan.get_fan_status(x) + if fan_stat is None: + return False + if fan_stat is False: + self._new_perc = FAN_LEV1_SPEED_PERC + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', self._new_perc, x) + break + logging.debug('INFO. fan_stat is True (fan_num:%d)', x) + + if fan_stat is not None and fan_stat is not False: + diff = new_temp - self._ori_temp + if diff == 0: + logging.debug('INFO. RETURN. THERMAL temp not changed. %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + return True + else: + if diff >= 0: + is_up = True + logging.debug('INFO. THERMAL temp UP %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + else: + is_up = False + logging.debug('INFO. THERMAL temp DOWN %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + + if is_up is True: + if new_temp >= FAN_LEV1_UP_TEMP: + self._new_perc = FAN_LEV1_SPEED_PERC + elif new_temp >= FAN_LEV2_UP_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + elif new_temp >= FAN_LEV3_UP_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + else: + self._new_perc = FAN_LEV4_SPEED_PERC + logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + else: + if new_temp <= FAN_LEV4_DOWN_TEMP: + self._new_perc = FAN_LEV4_SPEED_PERC + elif new_temp <= FAN_LEV3_DOWN_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + elif new_temp <= FAN_LEV2_DOWN_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + else: + self._new_perc = FAN_LEV1_SPEED_PERC + logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + + cur_perc = fan.get_fan_duty_cycle(fan.get_idx_fan_start()) + if cur_perc == self._new_perc: + logging.debug('INFO. RETURN. FAN speed not changed. %d / %d (new_perc / ori_perc)', self._new_perc, cur_perc) + return True + + set_stat = fan.set_fan_duty_cycle(fan.get_idx_fan_start(), self._new_perc) + if set_stat is True: + logging.debug('INFO: PASS. set_fan_duty_cycle (%d)', self._new_perc) + else: + logging.debug('INFO: FAIL. set_fan_duty_cycle (%d)', self._new_perc) + + logging.debug('INFO: GET. ori_perc is %d. ori_temp is %d', cur_perc, self._ori_temp) + self._ori_temp = new_temp + logging.debug('INFO: UPDATE. ori_perc to %d. ori_temp to %d', cur_perc, self._ori_temp) + + return True + +def handler(signum, frame): + fan = FanUtil() + logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(fan.get_idx_fan_start(), DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) + monitor = accton_as5712_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_util.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_util.py new file mode 100755 index 000000000000..ed9667da8c99 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_util.py @@ -0,0 +1,671 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import getopt +import sys +import logging +import re +import time + +PROJECT_NAME = 'as5712_54x' +version = '0.2.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':54} + + +led_prefix ='/sys/devices/platform/as5712_54x_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as5712_54x_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan1_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan2_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan3_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan5_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['61-0048','62-0049', '63-004a'] , + 'psu': ['57-0050','58-0053'], + 'sfp': ['-0050']} +i2c_nodes = { + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +QSFP_START = 48 + +sfp_map = [2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 52, 54, 51, 53, 55] + +port_cpld_path = [ "/sys/bus/i2c/devices/0-0061/" + ,'/sys/bus/i2c/devices/0-0062/'] + +mknod =[ +'echo as5712_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as5712_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as5712_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', + +# PSU-1 +'echo as5712_54x_psu1 0x38 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-57/new_device', +'echo as5712_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-57/new_device', + +# PSU-2 +'echo as5712_54x_psu2 0x3b > /sys/bus/i2c/devices/i2c-58/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-58/new_device', +'echo as5712_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-58/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-61/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-62/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-63/new_device', + +#EERPOM +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +mknod2 =[ +'echo as5712_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as5712_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as5712_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', + +# PSU-1 +'echo as5712_54x_psu1 0x38 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-57/new_device', +'echo as5712_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-57/new_device', + +# PSU-2 +'echo as5712_54x_psu2 0x3b > /sys/bus/i2c/devices/i2c-58/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-58/new_device', +'echo as5712_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-58/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-61/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-62/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-63/new_device', + +#EERPOM +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', +] + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-48 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe optoe', +'modprobe i2c-mux-accton_as5712_54x_cpld', +'modprobe cpr_4011_4mxx', +'modprobe ym2651y', +'modprobe accton_as5712_54x_fan', +'modprobe leds-accton_as5712_54x', +'modprobe accton_as5712_54x_psu'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + ret = log_os_system(kos[i], 1) + if ret[0]: + if FORCE == 0: + return ret[0] + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + #remove parameter if any + rm = kos[-(i+1)] + lst = rm.split(" ") + if len(lst) > 2: + del(lst[2:]) + rm = " ".join(lst) + + #Change to removing commands + rm = rm.replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + ret = log_os_system(rm, 1) + if ret[0]: + if FORCE == 0: + return ret[0] + return 0 + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x70 is exist @ i2c-0 + tmp = "i2cget -y -f 0 0x70" + ret = log_os_system(tmp, 0) + if not ret[0]: + order = 1 + else: + order = 0 + m = "[%s]Detected I2C_BUS_ORDER:%d" % (os.path.basename(__file__), order) + my_log(m) + return order + +def get_i2c_order(): + return i2c_order_check() + +def device_install(): + global FORCE + + order = get_i2c_order() + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + if i < QSFP_START: + status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + else: + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + order = get_i2c_order() + if order == 0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_inserted() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + + +def get_cpld_path(index): + order = get_i2c_order() + if order !=0 : + return port_cpld_path[index].replace("0-", "1-") + else: + return port_cpld_path[index] + +def cpld_path_of_port(port_index): + if port_index < 1 and port_index > DEVICE_NO['sfp']: + return None + if port_index < 25: + return get_cpld_path(0) + else: + return get_cpld_path(1) + +def get_path_sfp_tx_dis(port_index): + cpld_p = cpld_path_of_port(port_index) + if cpld_p is None: + return False, '' + else: + dev = cpld_p+"module_tx_disable_"+str(port_index) + return True, dev + +def get_path_sfp_presence(port_index): + cpld_p = cpld_path_of_port(port_index) + if cpld_p is None: + return False, '' + else: + dev = cpld_p+"module_present_"+str(port_index) + return True, dev + + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret[0] = log_os_system("echo "+args[1]+" >"+k, 1) + if ret[0]: + return ret[0] + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + #if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + #There no tx_disable for QSFP port + if int(args[1]) > QSFP_START or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + port_index = int(args[1]) + ret, dev = get_path_sfp_tx_dis(port_index) + if ret == False: + return False + else: + ret = log_os_system("echo "+args[2]+" >"+ dev, 1) + return ret[0] + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def print_1_device_traversal(i, j, k): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + return func+"="+log+" " + else: + return func+"="+"X"+" " + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + if i == 'sfp': + port_index = int(filter(str.isdigit, j)) + for k in (ALL_DEVICE[i][j]): + if k.find('tx_disable')!= -1: + ret, k = get_path_sfp_tx_dis(port_index) + if ret == False: + continue + log = print_1_device_traversal(i, j, k) + print log, + if k.find('present')!= -1: + ret, k = get_path_sfp_presence(port_index) + if ret == False: + continue + log = print_1_device_traversal(i, j, k) + print log, + + else: + for k in (ALL_DEVICE[i][j]): + log = print_1_device_traversal(i, j, k) + print log, + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1 = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2 = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1[0] or ret2[0]) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/fanutil.py new file mode 100755 index 000000000000..223408fb962c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/fanutil.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 5 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + + FAN_NODE_NUM_OF_MAP = 6 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 3 + FAN_NODE_DUTY_IDX_OF_MAP = 4 + FANR_NODE_FAULT_IDX_OF_MAP = 5 + FANR_NODE_SPEED_IDX_OF_MAP = 6 + + BASE_VAL_PATH = '/sys/devices/platform/as5812_54t_fan/{0}' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan1_speed_rpm', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + (FAN_NUM_1_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan1_duty_cycle_percentage', + (FAN_NUM_1_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr1_fault', + (FAN_NUM_1_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr1_speed_rpm', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan2_speed_rpm', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + (FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + (FAN_NUM_2_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr2_fault', + (FAN_NUM_2_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr2_speed_rpm', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan3_speed_rpm', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + (FAN_NUM_3_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan3_duty_cycle_percentage', + (FAN_NUM_3_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr3_fault', + (FAN_NUM_3_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr3_speed_rpm', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan4_speed_rpm', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + (FAN_NUM_4_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan4_duty_cycle_percentage', + (FAN_NUM_4_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr4_fault', + (FAN_NUM_4_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr4_speed_rpm', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan5_speed_rpm', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + (FAN_NUM_5_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan5_duty_cycle_percentage', + (FAN_NUM_5_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr5_fault', + (FAN_NUM_5_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr5_speed_rpm', + } + + logger = logging.getLogger(__name__) + def __init__(self, log_level=logging.DEBUG): + ch = logging.StreamHandler() + ch.setLevel(log_level) + self.logger.addHandler(ch) + + fan_path = self.BASE_VAL_PATH + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + self.logger.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'r') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + self.logger.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + def get_fan_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) + + def set_fan_duty_cycle(self, fan_num, val): + return self._set_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP, val) + + def get_fanr_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + self.logger.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + self.logger.debug('GET. FANR fault. fan_num, %d', fan_num) + return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/thermalutil.py new file mode 100755 index 000000000000..0095a7871029 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/thermalutil.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['15', '48'], + THERMAL_NUM_2_IDX: ['16', '49'], + THERMAL_NUM_3_IDX: ['17', '4a'], + } + + logger = logging.getLogger(__name__) + def __init__(self, log_level=logging.DEBUG): + ch = logging.StreamHandler() + ch.setLevel(log_level) + self.logger.addHandler(ch) + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/Makefile new file mode 100755 index 000000000000..db535d8d6771 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/Makefile @@ -0,0 +1,4 @@ +obj-m:= x86-64-accton-as5812-54t-cpld.o x86-64-accton-as5812-54t-fan.o \ + x86-64-accton-as5812-54t-leds.o \ + x86-64-accton-as5812-54t-psu.o ym2651y.o cpr_4011_4mxx.o + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/cpr_4011_4mxx.c new file mode 120000 index 000000000000..fd43cc1f1c77 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/cpr_4011_4mxx.c @@ -0,0 +1 @@ +../../common/modules/cpr_4011_4mxx.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-cpld.c new file mode 100755 index 000000000000..2d44d5355ca0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-cpld.c @@ -0,0 +1,544 @@ +/* + * A hwmon driver for the as5812_54t_cpld + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static ssize_t show_bit(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_1bit(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as5812_54t_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5812_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +struct as5812_54t_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; +}; + +/* Addresses scanned for as5812_54t_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + + + +#define _ATTR_CONCAT(name,idx) name##idx + +#define TRANSCEIVER_ATTR_ID(_attr) \ + _ATTR_CONCAT(MODULE_##_attr##_, 49), \ + _ATTR_CONCAT(MODULE_##_attr##_, 50), \ + _ATTR_CONCAT(MODULE_##_attr##_, 51), \ + _ATTR_CONCAT(MODULE_##_attr##_, 52), \ + _ATTR_CONCAT(MODULE_##_attr##_, 53), \ + _ATTR_CONCAT(MODULE_##_attr##_, 54) + + +enum as5812_54t_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + /* transceiver attributes */ + TRANSCEIVER_ATTR_ID(PRESENT), + TRANSCEIVER_ATTR_ID(LPMODE), + TRANSCEIVER_ATTR_ID(RESET), +}; + +/* sysfs attributes for hwmon + */ + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_bit, NULL, MODULE_PRESENT_##index);\ + static SENSOR_DEVICE_ATTR(module_lp_mode_##index, S_IRUGO|S_IWUSR, show_bit, set_1bit, MODULE_LPMODE_##index);\ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO|S_IWUSR, show_bit, set_1bit, MODULE_RESET_##index) + +#define DECLARE_TRANSCEIVER_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr, \ + &sensor_dev_attr_module_lp_mode_##index.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##index.dev_attr.attr + + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); + +static struct attribute *as5812_54t_cpld_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_ATTR(49), + DECLARE_TRANSCEIVER_ATTR(50), + DECLARE_TRANSCEIVER_ATTR(51), + DECLARE_TRANSCEIVER_ATTR(52), + DECLARE_TRANSCEIVER_ATTR(53), + DECLARE_TRANSCEIVER_ATTR(54), + NULL +}; + +static const struct attribute_group as5812_54t_cpld_group = { + .attrs = as5812_54t_cpld_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + u8 value = 0; + u8 reg = 0x22; + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + status = as5812_54t_cpld_read_internal(client, reg); + if (status < 0) { + goto exit; + } + + value = ~(u8)status; + value &= 0x3F; + + mutex_unlock(&data->update_lock); + + /* Return values 49 -> 54 in order */ + return sprintf(buf, "%.2x\n", value); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int get_reg_index(struct sensor_device_attribute *attr, u8 *reg, u8 *index, u8 *revert) { + if (attr->index >= MODULE_RESET_49){ + *reg = 0x23; + *index = attr->index - MODULE_RESET_49; + *revert = 1; + }else if (attr->index >= MODULE_LPMODE_49){ + *reg = 0x24; + *index = attr->index - MODULE_LPMODE_49; + *revert = 0; + } else { + *reg = 0x22; + *index = attr->index - MODULE_PRESENT_49; + *revert = 1; + } + return 0; +} + +static ssize_t set_1bit(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + u8 index, revert; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_cpld_data *data = i2c_get_clientdata(client); + int status, value; + u8 reg = 0, mask = 0; + + status = kstrtoint(buf, 10, &value); + if (status) + return status; + + get_reg_index(attr, ®, &index, &revert); + mask = 0x1 << index; + + mutex_lock(&data->update_lock); + status = as5812_54t_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + status &= ~(mask); + value = !value; + if (!revert) + value = !value; + status |= (value << index); /*low-active*/ + status = as5812_54t_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_bit(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 index, revert; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + get_reg_index(attr, ®, &index, &revert); + mask = 0x1 << index; + + mutex_lock(&data->update_lock); + status = as5812_54t_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + status = !(status & mask); + if (!revert) + status = !status; + + return sprintf(buf, "%d\n", status); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 reg = 0, mask = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + + switch (attr->index) { + case CPLD_VERSION: + reg = 0x1; + mask = 0xFF; + break; + default: + break; + } + + mutex_lock(&data->update_lock); + status = as5812_54t_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", (status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as5812_54t_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as5812_54t_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as5812_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static void as5812_54t_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as5812_54t_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int as5812_54t_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct as5812_54t_cpld_data *data = NULL; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5812_54t_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5812_54t_cpld_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5812_54t_cpld", + NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + as5812_54t_cpld_add_client(client); + + /* + * Bring QSFPs out of reset, + * This is a temporary fix until the QSFP+_MOD_RST register + * can be exposed through the driver. + */ + as5812_54t_cpld_write_internal(client, 0x23, 0x3F); + + dev_info(&client->dev, "%s: cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5812_54t_cpld_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5812_54t_cpld_remove(struct i2c_client *client) +{ + struct as5812_54t_cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5812_54t_cpld_group); + kfree(data); + as5812_54t_cpld_remove_client(client); + + return 0; +} + +int as5812_54t_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5812_54t_cpld_read); + +int as5812_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5812_54t_cpld_write); + +static const struct i2c_device_id as5812_54t_cpld_id[] = { + { "as5812_54t_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5812_54t_cpld_id); + +static struct i2c_driver as5812_54t_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5812_54t_cpld", + }, + .probe = as5812_54t_cpld_probe, + .remove = as5812_54t_cpld_remove, + .id_table = as5812_54t_cpld_id, + .address_list = normal_i2c, +}; + +static int __init as5812_54t_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as5812_54t_cpld_driver); +} + +static void __exit as5812_54t_cpld_exit(void) +{ + i2c_del_driver(&as5812_54t_cpld_driver); +} + +module_init(as5812_54t_cpld_init); +module_exit(as5812_54t_cpld_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as5812_54t_cpld driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-fan.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-fan.c new file mode 100644 index 000000000000..66370fb37ff4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-fan.c @@ -0,0 +1,458 @@ +/* + * A hwmon driver for the Accton as5812 54t fan + * + * Copyright (C) 2015 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as5812_54t_fan" + +#define FAN_MAX_NUMBER 5 +#define FAN_SPEED_CPLD_TO_RPM_STEP 150 +#define FAN_SPEED_PRECENT_TO_CPLD_STEP 5 +#define FAN_DUTY_CYCLE_MIN 0 +#define FAN_DUTY_CYCLE_MAX 100 /* 100% */ + +#define CPLD_REG_FAN_STATUS_OFFSET 0xC +#define CPLD_REG_FANR_STATUS_OFFSET 0x1F +#define CPLD_REG_FAN_DIRECTION_OFFSET 0x1E + +#define CPLD_FAN1_REG_SPEED_OFFSET 0x10 +#define CPLD_FAN2_REG_SPEED_OFFSET 0x11 +#define CPLD_FAN3_REG_SPEED_OFFSET 0x12 +#define CPLD_FAN4_REG_SPEED_OFFSET 0x13 +#define CPLD_FAN5_REG_SPEED_OFFSET 0x14 + +#define CPLD_FANR1_REG_SPEED_OFFSET 0x18 +#define CPLD_FANR2_REG_SPEED_OFFSET 0x19 +#define CPLD_FANR3_REG_SPEED_OFFSET 0x1A +#define CPLD_FANR4_REG_SPEED_OFFSET 0x1B +#define CPLD_FANR5_REG_SPEED_OFFSET 0x1C + +#define CPLD_REG_FAN_PWM_CYCLE_OFFSET 0xD + +#define CPLD_FAN1_INFO_BIT_MASK 0x1 +#define CPLD_FAN2_INFO_BIT_MASK 0x2 +#define CPLD_FAN3_INFO_BIT_MASK 0x4 +#define CPLD_FAN4_INFO_BIT_MASK 0x8 +#define CPLD_FAN5_INFO_BIT_MASK 0x10 + +#define PROJECT_NAME + +#define LOCAL_DEBUG 0 + +static struct accton_as5812_54t_fan *fan_data = NULL; + +struct accton_as5812_54t_fan { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[FAN_MAX_NUMBER]; /* inner first fan status */ + u32 speed[FAN_MAX_NUMBER]; /* inner first fan speed */ + u8 direction[FAN_MAX_NUMBER]; /* reconrd the direction of inner first and second fans */ + u32 duty_cycle[FAN_MAX_NUMBER]; /* control the speed of inner first and second fans */ + u8 r_status[FAN_MAX_NUMBER]; /* inner second fan status */ + u32 r_speed[FAN_MAX_NUMBER]; /* inner second fan speed */ +}; + +/*******************/ +#define MAKE_FAN_MASK_OR_REG(name,type) \ + CPLD_FAN##type##1_##name, \ + CPLD_FAN##type##2_##name, \ + CPLD_FAN##type##3_##name, \ + CPLD_FAN##type##4_##name, \ + CPLD_FAN##type##5_##name, + +/* fan related data + */ +static const u8 fan_info_mask[] = { + MAKE_FAN_MASK_OR_REG(INFO_BIT_MASK,) +}; + +static const u8 fan_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,) +}; + +static const u8 fanr_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,R) +}; + +/*******************/ +#define DEF_FAN_SET(id) \ + FAN##id##_FAULT, \ + FAN##id##_SPEED, \ + FAN##id##_DUTY_CYCLE, \ + FAN##id##_DIRECTION, \ + FANR##id##_FAULT, \ + FANR##id##_SPEED, + +enum sysfs_fan_attributes { + DEF_FAN_SET(1) + DEF_FAN_SET(2) + DEF_FAN_SET(3) + DEF_FAN_SET(4) + DEF_FAN_SET(5) +}; +/*******************/ +static void accton_as5812_54t_fan_update_device(struct device *dev); +static int accton_as5812_54t_fan_read_value(u8 reg); +static int accton_as5812_54t_fan_write_value(u8 reg, u8 value); + +static ssize_t fan_set_duty_cycle(struct device *dev, + struct device_attribute *da,const char *buf, size_t count); +static ssize_t fan_show_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t show_name(struct device *dev, + struct device_attribute *da, char *buf); + +extern int as5812_54t_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5812_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + + +/*******************/ +#define _MAKE_SENSOR_DEVICE_ATTR(prj, id, id2) \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, \ + fan_set_duty_cycle, FAN##id##_DUTY_CYCLE); \ + static SENSOR_DEVICE_ATTR(prj##pwm##id, S_IWUSR | S_IRUGO, fan_show_value, \ + fan_set_duty_cycle, FAN##id##_DUTY_CYCLE); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_direction, S_IRUGO, fan_show_value, NULL, FAN##id##_DIRECTION); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_fault, S_IRUGO, fan_show_value, NULL, FANR##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_input, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id2##_input, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fan##id2##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); + +#define MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) _MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) + +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,1,11) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,2,12) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,3,13) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,4,14) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,5,15) + +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +/*******************/ + +#define _MAKE_FAN_ATTR(prj, id, id2) \ + &sensor_dev_attr_##prj##fan##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_duty_cycle_percentage.dev_attr.attr,\ + &sensor_dev_attr_##prj##pwm##id.dev_attr.attr,\ + &sensor_dev_attr_##prj##fan##id##_direction.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_input.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id2##_input.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id2##_fault.dev_attr.attr, + + +#define MAKE_FAN_ATTR(prj, id, id2) _MAKE_FAN_ATTR(prj, id, id2) + +static struct attribute *accton_as5812_54t_fan_attributes[] = { + /* fan related attributes */ + MAKE_FAN_ATTR(PROJECT_NAME,1,11) + MAKE_FAN_ATTR(PROJECT_NAME,2,12) + MAKE_FAN_ATTR(PROJECT_NAME,3,13) + MAKE_FAN_ATTR(PROJECT_NAME,4,14) + MAKE_FAN_ATTR(PROJECT_NAME,5,15) + &sensor_dev_attr_name.dev_attr.attr, + NULL +}; +/*******************/ + +/* fan related functions + */ +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + ssize_t ret = 0; + int data_index, type_index; + + accton_as5812_54t_fan_update_device(dev); + + if (fan_data->valid == 0) { + return ret; + } + + type_index = attr->index%FAN2_FAULT; + data_index = attr->index/FAN2_FAULT; + + switch (type_index) { + case FAN1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->status[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->speed[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DUTY_CYCLE: + ret = sprintf(buf, "%d\n", fan_data->duty_cycle[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DIRECTION: + ret = sprintf(buf, "%d\n", fan_data->direction[data_index]); /* presnet, need to modify*/ + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->r_status[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->r_speed[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + default: + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d] \n", __FUNCTION__, __LINE__); + break; + } + + return ret; +} + +static ssize_t show_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf(buf, "%s\n", DRVNAME); +} +/*******************/ +static ssize_t fan_set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < FAN_DUTY_CYCLE_MIN || value > FAN_DUTY_CYCLE_MAX) + return -EINVAL; + + accton_as5812_54t_fan_write_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET, value/FAN_SPEED_PRECENT_TO_CPLD_STEP); + + fan_data->valid = 0; + + return count; +} + +static const struct attribute_group accton_as5812_54t_fan_group = { + .attrs = accton_as5812_54t_fan_attributes, +}; + +static int accton_as5812_54t_fan_read_value(u8 reg) +{ + return as5812_54t_cpld_read(0x60, reg); +} + +static int accton_as5812_54t_fan_write_value(u8 reg, u8 value) +{ + return as5812_54t_cpld_write(0x60, reg, value); +} + +static void accton_as5812_54t_fan_update_device(struct device *dev) +{ + int speed, r_speed, fault, r_fault, ctrl_speed, direction; + int i; + + mutex_lock(&fan_data->update_lock); + + if (LOCAL_DEBUG) + printk ("Starting accton_as5812_54t_fan update \n"); + + if (!(time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || !fan_data->valid)) { + /* do nothing */ + goto _exit; + } + + fan_data->valid = 0; + + if (LOCAL_DEBUG) + printk ("Starting accton_as5812_54t_fan update 2 \n"); + + fault = accton_as5812_54t_fan_read_value(CPLD_REG_FAN_STATUS_OFFSET); + r_fault = accton_as5812_54t_fan_read_value(CPLD_REG_FANR_STATUS_OFFSET); + direction = accton_as5812_54t_fan_read_value(CPLD_REG_FAN_DIRECTION_OFFSET); + ctrl_speed = accton_as5812_54t_fan_read_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET); + + if ( (fault < 0) || (r_fault < 0) || (direction < 0) || (ctrl_speed < 0) ) + { + if (LOCAL_DEBUG) + printk ("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + if (LOCAL_DEBUG) + printk ("[fan:] fault:%d, r_fault=%d, direction=%d, ctrl_speed=%d \n",fault, r_fault, direction, ctrl_speed); + + for (i=0; istatus[i] = (fault & fan_info_mask[i]) >> i; + if (LOCAL_DEBUG) + printk ("[fan%d:] fail=%d \n",i, fan_data->status[i]); + + fan_data->r_status[i] = (r_fault & fan_info_mask[i]) >> i; + fan_data->direction[i] = (direction & fan_info_mask[i]) >> i; + fan_data->duty_cycle[i] = ctrl_speed * FAN_SPEED_PRECENT_TO_CPLD_STEP; + + /* fan speed + */ + speed = accton_as5812_54t_fan_read_value(fan_speed_reg[i]); + r_speed = accton_as5812_54t_fan_read_value(fanr_speed_reg[i]); + if ( (speed < 0) || (r_speed < 0) ) + { + if (LOCAL_DEBUG) + printk ("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + if (LOCAL_DEBUG) + printk ("[fan%d:] speed:%d, r_speed=%d \n", i, speed, r_speed); + + fan_data->speed[i] = speed * FAN_SPEED_CPLD_TO_RPM_STEP; + fan_data->r_speed[i] = r_speed * FAN_SPEED_CPLD_TO_RPM_STEP; + } + + /* finish to update */ + fan_data->last_updated = jiffies; + fan_data->valid = 1; + +_exit: + mutex_unlock(&fan_data->update_lock); +} + +static int accton_as5812_54t_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &accton_as5812_54t_fan_group); + if (status) { + goto exit; + + } + + fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(fan_data->hwmon_dev)) { + status = PTR_ERR(fan_data->hwmon_dev); + goto exit_remove; + } + + dev_info(&pdev->dev, "accton_as5812_54t_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &accton_as5812_54t_fan_group); +exit: + return status; +} + +static int accton_as5812_54t_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&fan_data->pdev->dev.kobj, &accton_as5812_54t_fan_group); + + return 0; +} + + +static struct platform_driver accton_as5812_54t_fan_driver = { + .probe = accton_as5812_54t_fan_probe, + .remove = accton_as5812_54t_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5812_54t_fan_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5812_54t_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct accton_as5812_54t_fan), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as5812_54t_fan_driver); + goto exit; + } + + mutex_init(&fan_data->update_lock); + fan_data->valid = 0; + + fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fan_data->pdev)) { + ret = PTR_ERR(fan_data->pdev); + platform_driver_unregister(&accton_as5812_54t_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as5812_54t_fan_exit(void) +{ + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&accton_as5812_54t_fan_driver); + kfree(fan_data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5812_54t_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_as5812_54t_fan_init); +module_exit(accton_as5812_54t_fan_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-leds.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-leds.c new file mode 100644 index 000000000000..39e553d2f544 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-leds.c @@ -0,0 +1,591 @@ +/* + * A LED driver for the accton_as5812_54t_led + * + * Copyright (C) 2015 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include + +extern int as5812_54t_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5812_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#define DRVNAME "as5812_54t_led" + +struct accton_as5812_54t_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[4]; /* Register value, 0 = LOC/DIAG/FAN LED + 1 = PSU1/PSU2 LED + 2 = FAN1-4 LED + 3 = FAN5-6 LED */ +}; + +static struct accton_as5812_54t_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_TYPE_PSU1_REG_MASK 0x03 +#define LED_MODE_PSU1_GREEN_MASK 0x02 +#define LED_MODE_PSU1_AMBER_MASK 0x01 +#define LED_MODE_PSU1_OFF_MASK 0x03 +#define LED_MODE_PSU1_AUTO_MASK 0x00 + +#define LED_TYPE_PSU2_REG_MASK 0x0C +#define LED_MODE_PSU2_GREEN_MASK 0x08 +#define LED_MODE_PSU2_AMBER_MASK 0x04 +#define LED_MODE_PSU2_OFF_MASK 0x0C +#define LED_MODE_PSU2_AUTO_MASK 0x00 + +#define LED_TYPE_DIAG_REG_MASK 0x0C +#define LED_MODE_DIAG_GREEN_MASK 0x08 +#define LED_MODE_DIAG_AMBER_MASK 0x04 +#define LED_MODE_DIAG_OFF_MASK 0x0C + +#define LED_TYPE_FAN_REG_MASK 0x03 +#define LED_MODE_FAN_GREEN_MASK 0x02 +#define LED_MODE_FAN_AMBER_MASK 0x01 +#define LED_MODE_FAN_OFF_MASK 0x03 +#define LED_MODE_FAN_AUTO_MASK 0x00 + +#define LED_TYPE_FAN1_REG_MASK 0x03 +#define LED_TYPE_FAN2_REG_MASK 0x0C +#define LED_TYPE_FAN3_REG_MASK 0x30 +#define LED_TYPE_FAN4_REG_MASK 0xC0 +#define LED_TYPE_FAN5_REG_MASK 0x03 +#define LED_TYPE_FAN6_REG_MASK 0x0C + +#define LED_MODE_FANX_GREEN_MASK 0x01 +#define LED_MODE_FANX_RED_MASK 0x02 +#define LED_MODE_FANX_OFF_MASK 0x00 + +#define LED_TYPE_LOC_REG_MASK 0x30 +#define LED_MODE_LOC_ON_MASK 0x00 +#define LED_MODE_LOC_OFF_MASK 0x10 +#define LED_MODE_LOC_BLINK_MASK 0x20 + +static const u8 led_reg[] = { + 0xA, /* LOC/DIAG/FAN LED*/ + 0xB, /* PSU1/PSU2 LED */ + 0x16, /* FAN1-4 LED */ + 0x17, /* FAN4-6 LED */ +}; + +enum led_type { + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_DIAG, + LED_TYPE_FAN, + LED_TYPE_FAN1, + LED_TYPE_FAN2, + LED_TYPE_FAN3, + LED_TYPE_FAN4, + LED_TYPE_FAN5, + LED_TYPE_LOC +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER, + LED_MODE_AMBER_BLINK, + LED_MODE_RED, + LED_MODE_RED_BLINK, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + int type_mask; + enum led_light_mode mode; + int mode_mask; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU1_AUTO_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU2_AUTO_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AUTO, LED_MODE_FAN_AUTO_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_GREEN, LED_MODE_DIAG_GREEN_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_AMBER, LED_MODE_DIAG_AMBER_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_OFF, LED_MODE_DIAG_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER, LED_MODE_LOC_ON_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_OFF, LED_MODE_LOC_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER_BLINK, LED_MODE_LOC_BLINK_MASK} +}; + + +struct fanx_info_s { + u8 cname; /* device name */ + enum led_type type; + u8 reg_id; /* map to led_reg & reg_val */ +}; + +static struct fanx_info_s fanx_info[] = { + {'1', LED_TYPE_FAN1, 2}, + {'2', LED_TYPE_FAN2, 2}, + {'3', LED_TYPE_FAN3, 2}, + {'4', LED_TYPE_FAN4, 2}, + {'5', LED_TYPE_FAN5, 3} +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + } + + return reg_val; +} + +static int accton_as5812_54t_led_read_value(u8 reg) +{ + return as5812_54t_cpld_read(0x60, reg); +} + +static int accton_as5812_54t_led_write_value(u8 reg, u8 value) +{ + return as5812_54t_cpld_write(0x60, reg, value); +} + +static void accton_as5812_54t_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as5812_54t_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as5812_54t_led_read_value(led_reg[i]); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5812_54t_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + + reg_val = accton_as5812_54t_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as5812_54t_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5812_54t_led_psu_1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness accton_as5812_54t_led_psu_1_get(struct led_classdev *cdev) +{ + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void accton_as5812_54t_led_psu_2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness accton_as5812_54t_led_psu_2_get(struct led_classdev *cdev) +{ + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static void accton_as5812_54t_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN); +} + +static enum led_brightness accton_as5812_54t_led_fan_get(struct led_classdev *cdev) +{ + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + + +static void accton_as5812_54t_led_fanx_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (led_cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1); + return; + } + } +} + + +static enum led_brightness accton_as5812_54t_led_fanx_get(struct led_classdev *cdev) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]); + } + } + + + return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[2]); +} + + +static void accton_as5812_54t_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_as5812_54t_led_diag_get(struct led_classdev *cdev) +{ + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as5812_54t_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness accton_as5812_54t_led_loc_get(struct led_classdev *cdev) +{ + accton_as5812_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static struct led_classdev accton_as5812_54t_leds[] = { + [LED_TYPE_PSU1] = { + .name = "accton_as5812_54t_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_psu_1_set, + .brightness_get = accton_as5812_54t_led_psu_1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as5812_54t_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_psu_2_set, + .brightness_get = accton_as5812_54t_led_psu_2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "accton_as5812_54t_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fan_set, + .brightness_get = accton_as5812_54t_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN1] = { + .name = "accton_as5812_54t_led::fan1", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fanx_set, + .brightness_get = accton_as5812_54t_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN2] = { + .name = "accton_as5812_54t_led::fan2", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fanx_set, + .brightness_get = accton_as5812_54t_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN3] = { + .name = "accton_as5812_54t_led::fan3", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fanx_set, + .brightness_get = accton_as5812_54t_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN4] = { + .name = "accton_as5812_54t_led::fan4", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fanx_set, + .brightness_get = accton_as5812_54t_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN5] = { + .name = "accton_as5812_54t_led::fan5", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_fanx_set, + .brightness_get = accton_as5812_54t_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_DIAG] = { + .name = "accton_as5812_54t_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_diag_set, + .brightness_get = accton_as5812_54t_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_LOC] = { + .name = "accton_as5812_54t_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as5812_54t_led_loc_set, + .brightness_get = accton_as5812_54t_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as5812_54t_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54t_leds); i++) { + led_classdev_suspend(&accton_as5812_54t_leds[i]); + } + + return 0; +} + +static int accton_as5812_54t_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54t_leds); i++) { + led_classdev_resume(&accton_as5812_54t_leds[i]); + } + + return 0; +} + +static int accton_as5812_54t_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54t_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as5812_54t_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as5812_54t_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as5812_54t_leds[i]); + } + } + + return ret; +} + +static int accton_as5812_54t_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54t_leds); i++) { + led_classdev_unregister(&accton_as5812_54t_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as5812_54t_led_driver = { + .probe = accton_as5812_54t_led_probe, + .remove = accton_as5812_54t_led_remove, + .suspend = accton_as5812_54t_led_suspend, + .resume = accton_as5812_54t_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5812_54t_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5812_54t_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as5812_54t_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as5812_54t_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as5812_54t_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as5812_54t_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as5812_54t_led_driver); + kfree(ledctl); +} + +module_init(accton_as5812_54t_led_init); +module_exit(accton_as5812_54t_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5812_54t_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-psu.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-psu.c new file mode 100644 index 000000000000..c62998655bcd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-psu.c @@ -0,0 +1,357 @@ +/* + * An hwmon driver for accton as5812_54t Power Module + * + * Copyright (C) 2015 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as5812_54t_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as5812_54t_cpld_read(unsigned short cpld_addr, u8 reg); +static int as5812_54t_psu_model_name_get(struct device *dev); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5812_54t_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[14]; /* Model name, read from eeprom */ +}; + +static struct as5812_54t_psu_data *as5812_54t_psu_update_device(struct device *dev); + +enum as5812_54t_psu_sysfs_attributes { + PSU_INDEX, + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as5812_54t_psu_attributes[] = { + &sensor_dev_attr_psu_index.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_psu_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->index); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5812_54t_psu_data *data = as5812_54t_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as5812_54t_psu_data *data = as5812_54t_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + if (as5812_54t_psu_model_name_get(dev) < 0) { + return -ENXIO; + } + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as5812_54t_psu_group = { + .attrs = as5812_54t_psu_attributes, +}; + +static int as5812_54t_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5812_54t_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5812_54t_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5812_54t_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5812_54t_psu", + NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5812_54t_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5812_54t_psu_remove(struct i2c_client *client) +{ + struct as5812_54t_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5812_54t_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as5812_54t_psu1, + as5812_54t_psu2 +}; + +static const struct i2c_device_id as5812_54t_psu_id[] = { + { "as5812_54t_psu1", as5812_54t_psu1 }, + { "as5812_54t_psu2", as5812_54t_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5812_54t_psu_id); + +static struct i2c_driver as5812_54t_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5812_54t_psu", + }, + .probe = as5812_54t_psu_probe, + .remove = as5812_54t_psu_remove, + .id_table = as5812_54t_psu_id, + .address_list = normal_i2c, +}; + +static int as5812_54t_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +enum psu_type { + PSU_YM_2401_JCR, /* AC110V - F2B */ + PSU_YM_2401_JDR, /* AC110V - B2F */ + PSU_CPR_4011_4M11, /* AC110V - F2B */ + PSU_CPR_4011_4M21, /* AC110V - B2F */ + PSU_CPR_6011_2M11, /* AC110V - F2B */ + PSU_CPR_6011_2M21, /* AC110V - B2F */ + PSU_UM400D_01G, /* DC48V - F2B */ + PSU_UM400D01_01G /* DC48V - B2F */ +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_YM_2401_JCR, 0x20, 11, "YM-2401JCR"}, +{PSU_YM_2401_JDR, 0x20, 11, "YM-2401JDR"}, +{PSU_CPR_4011_4M11, 0x26, 13, "CPR-4011-4M11"}, +{PSU_CPR_4011_4M21, 0x26, 13, "CPR-4011-4M21"}, +{PSU_CPR_6011_2M11, 0x26, 13, "CPR-6011-2M11"}, +{PSU_CPR_6011_2M21, 0x26, 13, "CPR-6011-2M21"}, +{PSU_UM400D_01G, 0x50, 9, "um400d01G"}, +{PSU_UM400D01_01G, 0x50, 12, "um400d01-01G"}, +}; + +static int as5812_54t_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as5812_54t_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR) { + /* Skip the meaningless data byte 8*/ + data->model_name[8] = data->model_name[9]; + data->model_name[9] = data->model_name[10]; + data->model_name[10] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} + +static struct as5812_54t_psu_data *as5812_54t_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54t_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + + dev_dbg(&client->dev, "Starting as5812_54t update\n"); + data->valid = 0; + + /* Read psu status */ + status = as5812_54t_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as5812_54t_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as5812_54t_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/service/as5812-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/service/as5812-platform-init.service new file mode 100755 index 000000000000..91c9adb01ccb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/service/as5812-platform-init.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS5812-54X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +Type=simple +ExecStartPre=/usr/local/bin/accton_as5812_util.py install +ExecStart=/usr/local/bin/accton_as5812_monitor.py +#RemainAfterExit=yes + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/setup.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/setup.py new file mode 100755 index 000000000000..0af58ba919bc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as5812_54t', + version='1.0', + description='Module to initialize Accton AS5812-54X platforms', + + packages=['as5812_54t'], + package_dir={'as5812_54t': 'as5812-54t/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/README b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/README new file mode 100755 index 000000000000..2284eb091fcb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/README @@ -0,0 +1,60 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +To initialize the system, run "accton_as5812_54t_util.py install". +To clean up the drivers & devices, run "accton_as5812_54t_util.py clean". +To dump information of sensors, run "accton_as5812_54t_util.py show". +To dump SFP EEPROM, run "accton_as5812_54t_util.py sff". +To set fan speed, run "accton_as5812_54t_util.py set fan". +To enable/disable SFP emission, run "accton_as5812_54t_util.py set sfp". +To set system LEDs' color, run "accton_as5812_54t_util.py set led" +For more information, run "accton_as5812_54t_util.py --help". + +==================================================================== +Besides applying accton_as5812_54t_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +LED controls can be found under /sys/class/leds. The sysfs interface +color mappings are as follows: +Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + +There are 5 system LEDs, loc, diag, fan, ps1, and ps2. +They are lit automatically by CPLD, but the loc and diag. +The loc led has only 1 color, blue. +The diag one has 3 colors: red, amber, and green. + +Fan controls can be found in /sys/bus/i2c/devices/2-0066. +There are 12 fans inside 6 fan modules. +All fans share 1 duty setting, ranged from 0~100. + +Three temperature sensors are controlled by the lm75 kernel modules. +They should already be visible under /sys/bus/i2c/drivers/lm75/. + +Two power supplies are controlled by the CPLD. +Here provide their status under +/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. + +There are 32 QSFP+ modules are equipped. +Apply "accton_as5812_54t_util.py show" to get their status. +Apply "accton_as5812_54t_util.py set sfp" to turn on/off light transmission. +Apply "accton_as5812_54t_util.py sff" to dump EEPROM information. +Before operating on that QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_monitor.py new file mode 100755 index 000000000000..6f55e703d7d1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_monitor.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 05/08/2019: Roy Lee, changed for as5812-54t. +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example + import signal + from as5812_54t.fanutil import FanUtil + from as5812_54t.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as5812_monitor' +DUTY_MAX = 100 + +global log_file +global log_console + +# Make a class we can use to capture stdout and sterr in the log +class accton_as5812_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + + llog = logging.getLogger("["+FUNCTION_NAME+"]") + def __init__(self, log_console, log_file): + """Needs a logger and a logger level.""" + + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + sys_handler.setLevel(logging.WARNING) #only fatal for syslog + self.llog.addHandler(sys_handler) + self.llog.setLevel(logging.DEBUG) + + if log_file: + fh = logging.FileHandler(log_file) + fh.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s') + fh.setFormatter(formatter) + self.llog.addHandler(fh) + + # set up logging to console + if log_console: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) #For debugging + formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s') + console.setFormatter(formatter) + self.llog.addHandler(console) + + def manage_fans(self): + FAN_LEV1_UP_TEMP = 57700 # temperature + FAN_LEV1_DOWN_TEMP = 0 # unused + FAN_LEV1_SPEED_PERC = DUTY_MAX # percentage*/ + + FAN_LEV2_UP_TEMP = 53000 + FAN_LEV2_DOWN_TEMP = 52700 + FAN_LEV2_SPEED_PERC = 80 + + FAN_LEV3_UP_TEMP = 49500 + FAN_LEV3_DOWN_TEMP = 47700 + FAN_LEV3_SPEED_PERC = 65 + + FAN_LEV4_UP_TEMP = 0 # unused + FAN_LEV4_DOWN_TEMP = 42700 + FAN_LEV4_SPEED_PERC = 40 + + + thermal = ThermalUtil() + fan = FanUtil() + + temp1 = thermal.get_thermal_1_val() + if temp1 is None: + return False + + temp2 = thermal.get_thermal_2_val() + if temp2 is None: + return False + + new_temp = (temp1 + temp2) / 2 + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_stat = fan.get_fan_status(x) + if fan_stat is None or fan_stat is False: + self._new_perc = FAN_LEV1_SPEED_PERC + self.llog.error('SET new_perc to %d (FAN fault. fan_num:%d)', self._new_perc, x) + break + else: + self.llog.debug('fan_stat is True (fan_num:%d)', x) + + if fan_stat is not None and fan_stat is not False: + diff = new_temp - self._ori_temp + if diff == 0: + self.llog.debug('RETURN. THERMAL temp not changed. %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + return True + else: + if diff >= 0: + is_up = True + self.llog.debug('THERMAL temp UP %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + else: + is_up = False + self.llog.debug('THERMAL temp DOWN %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + + if is_up is True: + if new_temp >= FAN_LEV1_UP_TEMP: + self._new_perc = FAN_LEV1_SPEED_PERC + elif new_temp >= FAN_LEV2_UP_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + elif new_temp >= FAN_LEV3_UP_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + else: + self._new_perc = FAN_LEV4_SPEED_PERC + self.llog.debug('SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + else: + if new_temp <= FAN_LEV4_DOWN_TEMP: + self._new_perc = FAN_LEV4_SPEED_PERC + elif new_temp <= FAN_LEV3_DOWN_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + elif new_temp <= FAN_LEV2_DOWN_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + else: + self._new_perc = FAN_LEV1_SPEED_PERC + self.llog.debug('SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + + cur_perc = fan.get_fan_duty_cycle(fan.get_idx_fan_start()) + if cur_perc == self._new_perc: + self.llog.debug('RETURN. FAN speed not changed. %d / %d (new_perc / ori_perc)', self._new_perc, cur_perc) + return True + + set_stat = fan.set_fan_duty_cycle(fan.get_idx_fan_start(), self._new_perc) + if set_stat is True: + self.llog.debug('PASS. set_fan_duty_cycle (%d)', self._new_perc) + else: + self.llog.error('FAIL. set_fan_duty_cycle (%d)', self._new_perc) + + self.llog.debug('GET. ori_perc is %d. ori_temp is %d', cur_perc, self._ori_temp) + self._ori_temp = new_temp + self.llog.info('UPDATE. ori_perc to %d. ori_temp to %d', cur_perc, self._ori_temp) + + return True + +def sig_handler(signum, frame): + fan = FanUtil() + logging.critical('Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(fan.get_idx_fan_start(), DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_console = 0 + log_file = "" + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl') + except getopt.GetoptError: + print 'Usage: %s [-d] [-l]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l]' % sys.argv[0] + return 0 + elif opt in ('-d'): + log_console = 1 + elif opt in ('-l'): + log_file = '%s.log' % sys.argv[0] + + signal.signal(signal.SIGINT, sig_handler) + signal.signal(signal.SIGTERM, sig_handler) + monitor = accton_as5812_monitor(log_console, log_file) + + #time.sleep(100) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_util.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_util.py new file mode 100755 index 000000000000..3859c3279c45 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_util.py @@ -0,0 +1,563 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + + + + +PROJECT_NAME = 'as5812_54t' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':5,'thermal':3, 'psu':2, 'sfp':6} +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-6 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe optoe', +'modprobe x86-64-accton-as5812-54t-cpld' , +'modprobe cpr_4011_4mxx' , +'modprobe ym2651y' , +'modprobe x86-64-accton-as5812-54t-psu' , +'modprobe x86-64-accton-as5812-54t-fan' , +'modprobe x86-64-accton-as5812-54t-leds' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + lst = rm.split(" ") + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['2-0066'] , + 'thermal': ['15-0048','16-0049', '17-004a'] , + 'psu': ['11-0050','12-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable_all']} + +sfp_map = [4,6,3,5,7,2] + +sfp_1st_index = 48 + +mknod =[ +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo as5812_54t_cpld 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-15/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-16/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-17/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as5812_54t_psu1 0x38 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5812_54t_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5812_54t_psu2 0x3b > /sys/bus/i2c/devices/i2c-12/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as5812_54t_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device'] + +mknod2 =[ +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo as5812_54t_cpld 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-15/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-16/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-17/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as5812_54t_psu1 0x38 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5812_54t_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5812_54t_psu2 0x3b > /sys/bus/i2c/devices/i2c-12/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as5812_54t_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device'] + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x71 is exist @ i2c-0 + tmp = "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x71 > /sys/bus/i2c/devices/i2c-0/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x71 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0071", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(sfp_1st_index,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(sfp_1st_index,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0071", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/classes/fanutil.py new file mode 100755 index 000000000000..95a4558622e9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/classes/fanutil.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 5 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + + FAN_NODE_NUM_OF_MAP = 6 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 3 + FAN_NODE_DUTY_IDX_OF_MAP = 4 + FANR_NODE_FAULT_IDX_OF_MAP = 5 + FANR_NODE_SPEED_IDX_OF_MAP = 6 + + BASE_VAL_PATH = '/sys/devices/platform/as5812_54x_fan/{0}' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan1_speed_rpm', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + (FAN_NUM_1_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan1_duty_cycle_percentage', + (FAN_NUM_1_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr1_fault', + (FAN_NUM_1_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr1_speed_rpm', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan2_speed_rpm', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + (FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + (FAN_NUM_2_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr2_fault', + (FAN_NUM_2_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr2_speed_rpm', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan3_speed_rpm', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + (FAN_NUM_3_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan3_duty_cycle_percentage', + (FAN_NUM_3_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr3_fault', + (FAN_NUM_3_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr3_speed_rpm', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan4_speed_rpm', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + (FAN_NUM_4_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan4_duty_cycle_percentage', + (FAN_NUM_4_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr4_fault', + (FAN_NUM_4_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr4_speed_rpm', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan5_speed_rpm', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + (FAN_NUM_5_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan5_duty_cycle_percentage', + (FAN_NUM_5_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr5_fault', + (FAN_NUM_5_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr5_speed_rpm', + } + + logger = logging.getLogger(__name__) + def __init__(self, log_level=logging.DEBUG): + ch = logging.StreamHandler() + ch.setLevel(log_level) + self.logger.addHandler(ch) + + fan_path = self.BASE_VAL_PATH + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + self.logger.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'r') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + self.logger.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + def get_fan_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) + + def set_fan_duty_cycle(self, fan_num, val): + return self._set_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP, val) + + def get_fanr_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + self.logger.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + self.logger.debug('GET. FANR fault. fan_num, %d', fan_num) + return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/classes/thermalutil.py new file mode 100755 index 000000000000..7799bb3d53c4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/classes/thermalutil.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['61', '48'], + THERMAL_NUM_2_IDX: ['62', '49'], + THERMAL_NUM_3_IDX: ['63', '4a'], + } + + logger = logging.getLogger(__name__) + def __init__(self, log_level=logging.DEBUG): + ch = logging.StreamHandler() + ch.setLevel(log_level) + self.logger.addHandler(ch) + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/Makefile new file mode 100755 index 000000000000..ba91f25f2430 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= i2c-mux-accton_as5812_54x_cpld.o \ + accton_as5812_54x_fan.o leds-accton_as5812_54x.o accton_as5812_54x_psu.o \ + cpr_4011_4mxx.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/accton_as5812_54x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/accton_as5812_54x_fan.c new file mode 100644 index 000000000000..deeabde23b28 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/accton_as5812_54x_fan.c @@ -0,0 +1,457 @@ +/* + * A hwmon driver for the Accton as5710 54x fan contrl + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as5812_54x_fan" + +#define FAN_MAX_NUMBER 5 +#define FAN_SPEED_CPLD_TO_RPM_STEP 150 +#define FAN_SPEED_PRECENT_TO_CPLD_STEP 5 +#define FAN_DUTY_CYCLE_MIN 0 /* 10% ??*/ +#define FAN_DUTY_CYCLE_MAX 100 /* 100% */ + +#define CPLD_REG_FAN_STATUS_OFFSET 0xC +#define CPLD_REG_FANR_STATUS_OFFSET 0x1F +#define CPLD_REG_FAN_DIRECTION_OFFSET 0x1E + +#define CPLD_FAN1_REG_SPEED_OFFSET 0x10 +#define CPLD_FAN2_REG_SPEED_OFFSET 0x11 +#define CPLD_FAN3_REG_SPEED_OFFSET 0x12 +#define CPLD_FAN4_REG_SPEED_OFFSET 0x13 +#define CPLD_FAN5_REG_SPEED_OFFSET 0x14 + +#define CPLD_FANR1_REG_SPEED_OFFSET 0x18 +#define CPLD_FANR2_REG_SPEED_OFFSET 0x19 +#define CPLD_FANR3_REG_SPEED_OFFSET 0x1A +#define CPLD_FANR4_REG_SPEED_OFFSET 0x1B +#define CPLD_FANR5_REG_SPEED_OFFSET 0x1C + +#define CPLD_REG_FAN_PWM_CYCLE_OFFSET 0xD + +#define CPLD_FAN1_INFO_BIT_MASK 0x1 +#define CPLD_FAN2_INFO_BIT_MASK 0x2 +#define CPLD_FAN3_INFO_BIT_MASK 0x4 +#define CPLD_FAN4_INFO_BIT_MASK 0x8 +#define CPLD_FAN5_INFO_BIT_MASK 0x10 + +#define PROJECT_NAME + +#define LOCAL_DEBUG 0 + +static struct accton_as5812_54x_fan *fan_data = NULL; + +struct accton_as5812_54x_fan { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[FAN_MAX_NUMBER]; /* inner first fan status */ + u32 speed[FAN_MAX_NUMBER]; /* inner first fan speed */ + u8 direction[FAN_MAX_NUMBER]; /* reconrd the direction of inner first and second fans */ + u32 duty_cycle[FAN_MAX_NUMBER]; /* control the speed of inner first and second fans */ + u8 r_status[FAN_MAX_NUMBER]; /* inner second fan status */ + u32 r_speed[FAN_MAX_NUMBER]; /* inner second fan speed */ +}; + +/*******************/ +#define MAKE_FAN_MASK_OR_REG(name,type) \ + CPLD_FAN##type##1_##name, \ + CPLD_FAN##type##2_##name, \ + CPLD_FAN##type##3_##name, \ + CPLD_FAN##type##4_##name, \ + CPLD_FAN##type##5_##name, + +/* fan related data + */ +static const u8 fan_info_mask[] = { + MAKE_FAN_MASK_OR_REG(INFO_BIT_MASK,) +}; + +static const u8 fan_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,) +}; + +static const u8 fanr_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,R) +}; + +/*******************/ +#define DEF_FAN_SET(id) \ + FAN##id##_FAULT, \ + FAN##id##_SPEED, \ + FAN##id##_DUTY_CYCLE, \ + FAN##id##_DIRECTION, \ + FANR##id##_FAULT, \ + FANR##id##_SPEED, + +enum sysfs_fan_attributes { + DEF_FAN_SET(1) + DEF_FAN_SET(2) + DEF_FAN_SET(3) + DEF_FAN_SET(4) + DEF_FAN_SET(5) +}; +/*******************/ +static void accton_as5812_54x_fan_update_device(struct device *dev); +static int accton_as5812_54x_fan_read_value(u8 reg); +static int accton_as5812_54x_fan_write_value(u8 reg, u8 value); + +static ssize_t fan_set_duty_cycle(struct device *dev, + struct device_attribute *da,const char *buf, size_t count); +static ssize_t fan_show_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t show_name(struct device *dev, + struct device_attribute *da, char *buf); + +extern int as5812_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5812_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + + +/*******************/ +#define _MAKE_SENSOR_DEVICE_ATTR(prj, id, id2) \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, \ + fan_set_duty_cycle, FAN##id##_DUTY_CYCLE); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_direction, S_IRUGO, fan_show_value, NULL, FAN##id##_DIRECTION); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_fault, S_IRUGO, fan_show_value, NULL, FANR##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_input, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id2##_input, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fan##id2##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); + +#define MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) _MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) + +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,1,11) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,2,12) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,3,13) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,4,14) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,5,15) + +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +/*******************/ + +#define _MAKE_FAN_ATTR(prj, id, id2) \ + &sensor_dev_attr_##prj##fan##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_duty_cycle_percentage.dev_attr.attr,\ + &sensor_dev_attr_##prj##fan##id##_direction.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_input.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id2##_input.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id2##_fault.dev_attr.attr, + + +#define MAKE_FAN_ATTR(prj, id, id2) _MAKE_FAN_ATTR(prj, id, id2) + +static struct attribute *accton_as5812_54x_fan_attributes[] = { + /* fan related attributes */ + MAKE_FAN_ATTR(PROJECT_NAME,1,11) + MAKE_FAN_ATTR(PROJECT_NAME,2,12) + MAKE_FAN_ATTR(PROJECT_NAME,3,13) + MAKE_FAN_ATTR(PROJECT_NAME,4,14) + MAKE_FAN_ATTR(PROJECT_NAME,5,15) + &sensor_dev_attr_name.dev_attr.attr, + NULL +}; +/*******************/ + +/* fan related functions + */ +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + ssize_t ret = 0; + int data_index, type_index; + + accton_as5812_54x_fan_update_device(dev); + + if (fan_data->valid == 0) { + return ret; + } + + type_index = attr->index%FAN2_FAULT; + data_index = attr->index/FAN2_FAULT; + + switch (type_index) { + case FAN1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->status[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->speed[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DUTY_CYCLE: + ret = sprintf(buf, "%d\n", fan_data->duty_cycle[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DIRECTION: + ret = sprintf(buf, "%d\n", fan_data->direction[data_index]); /* presnet, need to modify*/ + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->r_status[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->r_speed[data_index]); + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + default: + if (LOCAL_DEBUG) + printk ("[Check !!][%s][%d] \n", __FUNCTION__, __LINE__); + break; + } + + return ret; +} + +static ssize_t show_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf(buf, "%s\n", DRVNAME); +} +/*******************/ +static ssize_t fan_set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < FAN_DUTY_CYCLE_MIN || value > FAN_DUTY_CYCLE_MAX) + return -EINVAL; + + accton_as5812_54x_fan_write_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET, value/FAN_SPEED_PRECENT_TO_CPLD_STEP); + + fan_data->valid = 0; + + return count; +} + +static const struct attribute_group accton_as5812_54x_fan_group = { + .attrs = accton_as5812_54x_fan_attributes, +}; + +static int accton_as5812_54x_fan_read_value(u8 reg) +{ + return as5812_54x_cpld_read(0x60, reg); +} + +static int accton_as5812_54x_fan_write_value(u8 reg, u8 value) +{ + return as5812_54x_cpld_write(0x60, reg, value); +} + +static void accton_as5812_54x_fan_update_device(struct device *dev) +{ + int speed, r_speed, fault, r_fault, ctrl_speed, direction; + int i; + + mutex_lock(&fan_data->update_lock); + + if (LOCAL_DEBUG) + printk ("Starting accton_as5812_54x_fan update \n"); + + if (!(time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || !fan_data->valid)) { + /* do nothing */ + goto _exit; + } + + fan_data->valid = 0; + + if (LOCAL_DEBUG) + printk ("Starting accton_as5812_54x_fan update 2 \n"); + + fault = accton_as5812_54x_fan_read_value(CPLD_REG_FAN_STATUS_OFFSET); + r_fault = accton_as5812_54x_fan_read_value(CPLD_REG_FANR_STATUS_OFFSET); + direction = accton_as5812_54x_fan_read_value(CPLD_REG_FAN_DIRECTION_OFFSET); + ctrl_speed = accton_as5812_54x_fan_read_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET); + + if ( (fault < 0) || (r_fault < 0) || (direction < 0) || (ctrl_speed < 0) ) + { + if (LOCAL_DEBUG) + printk ("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + if (LOCAL_DEBUG) + printk ("[fan:] fault:%d, r_fault=%d, direction=%d, ctrl_speed=%d \n",fault, r_fault, direction, ctrl_speed); + + for (i=0; istatus[i] = (fault & fan_info_mask[i]) >> i; + if (LOCAL_DEBUG) + printk ("[fan%d:] fail=%d \n",i, fan_data->status[i]); + + fan_data->r_status[i] = (r_fault & fan_info_mask[i]) >> i; + fan_data->direction[i] = (direction & fan_info_mask[i]) >> i; + fan_data->duty_cycle[i] = ctrl_speed * FAN_SPEED_PRECENT_TO_CPLD_STEP; + + /* fan speed + */ + speed = accton_as5812_54x_fan_read_value(fan_speed_reg[i]); + r_speed = accton_as5812_54x_fan_read_value(fanr_speed_reg[i]); + if ( (speed < 0) || (r_speed < 0) ) + { + if (LOCAL_DEBUG) + printk ("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + if (LOCAL_DEBUG) + printk ("[fan%d:] speed:%d, r_speed=%d \n", i, speed, r_speed); + + fan_data->speed[i] = speed * FAN_SPEED_CPLD_TO_RPM_STEP; + fan_data->r_speed[i] = r_speed * FAN_SPEED_CPLD_TO_RPM_STEP; + } + + /* finish to update */ + fan_data->last_updated = jiffies; + fan_data->valid = 1; + +_exit: + mutex_unlock(&fan_data->update_lock); +} + +static int accton_as5812_54x_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &accton_as5812_54x_fan_group); + if (status) { + goto exit; + + } + + fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(fan_data->hwmon_dev)) { + status = PTR_ERR(fan_data->hwmon_dev); + goto exit_remove; + } + + dev_info(&pdev->dev, "accton_as5812_54x_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &accton_as5812_54x_fan_group); +exit: + return status; +} + +static int accton_as5812_54x_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&fan_data->pdev->dev.kobj, &accton_as5812_54x_fan_group); + + return 0; +} + + + +static struct platform_driver accton_as5812_54x_fan_driver = { + .probe = accton_as5812_54x_fan_probe, + .remove = accton_as5812_54x_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5812_54x_fan_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5812_54x_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct accton_as5812_54x_fan), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as5812_54x_fan_driver); + goto exit; + } + + mutex_init(&fan_data->update_lock); + fan_data->valid = 0; + + fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fan_data->pdev)) { + ret = PTR_ERR(fan_data->pdev); + platform_driver_unregister(&accton_as5812_54x_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as5812_54x_fan_exit(void) +{ + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&accton_as5812_54x_fan_driver); + kfree(fan_data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5812_54x_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_as5812_54x_fan_init); +module_exit(accton_as5812_54x_fan_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/accton_as5812_54x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/accton_as5812_54x_psu.c new file mode 100755 index 000000000000..2c6b5f492a97 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/accton_as5812_54x_psu.c @@ -0,0 +1,371 @@ +/* + * An hwmon driver for accton as5812_54x Power Module + * + * Copyright (C) 2015 Accton Technology Corporation. + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as5812_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as5812_54x_cpld_read(unsigned short cpld_addr, u8 reg); +static int as5812_54x_psu_model_name_get(struct device *dev); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5812_54x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[14]; /* Model name, read from eeprom */ +}; + +static struct as5812_54x_psu_data *as5812_54x_psu_update_device(struct device *dev); + +enum as5812_54x_psu_sysfs_attributes { + PSU_INDEX, + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as5812_54x_psu_attributes[] = { + &sensor_dev_attr_psu_index.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_psu_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->index); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5812_54x_psu_data *data = as5812_54x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as5812_54x_psu_data *data = as5812_54x_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + if (as5812_54x_psu_model_name_get(dev) < 0) { + return -ENXIO; + } + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as5812_54x_psu_group = { + .attrs = as5812_54x_psu_attributes, +}; + +static int as5812_54x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5812_54x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5812_54x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5812_54x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5812_54x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5812_54x_psu_remove(struct i2c_client *client) +{ + struct as5812_54x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5812_54x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as5812_54x_psu1, + as5812_54x_psu2 +}; + +static const struct i2c_device_id as5812_54x_psu_id[] = { + { "as5812_54x_psu1", as5812_54x_psu1 }, + { "as5812_54x_psu2", as5812_54x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5812_54x_psu_id); + +static struct i2c_driver as5812_54x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5812_54x_psu", + }, + .probe = as5812_54x_psu_probe, + .remove = as5812_54x_psu_remove, + .id_table = as5812_54x_psu_id, + .address_list = normal_i2c, +}; + +static int as5812_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +enum psu_type { + PSU_YM_2401_JCR, /* AC110V - F2B */ + PSU_YM_2401_JDR, /* AC110V - B2F */ + PSU_CPR_4011_4M11, /* AC110V - F2B */ + PSU_CPR_4011_4M21, /* AC110V - B2F */ + PSU_CPR_6011_2M11, /* AC110V - F2B */ + PSU_CPR_6011_2M21, /* AC110V - B2F */ + PSU_UM400D_01G, /* DC48V - F2B */ + PSU_UM400D01_01G /* DC48V - B2F */ +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_YM_2401_JCR, 0x20, 11, "YM-2401JCR"}, +{PSU_YM_2401_JDR, 0x20, 11, "YM-2401JDR"}, +{PSU_CPR_4011_4M11, 0x26, 13, "CPR-4011-4M11"}, +{PSU_CPR_4011_4M21, 0x26, 13, "CPR-4011-4M21"}, +{PSU_CPR_6011_2M11, 0x26, 13, "CPR-6011-2M11"}, +{PSU_CPR_6011_2M21, 0x26, 13, "CPR-6011-2M21"}, +{PSU_UM400D_01G, 0x50, 9, "um400d01G"}, +{PSU_UM400D01_01G, 0x50, 12, "um400d01-01G"}, +}; + +static int as5812_54x_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as5812_54x_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR) { + /* Skip the meaningless data byte 8*/ + data->model_name[8] = data->model_name[9]; + data->model_name[9] = data->model_name[10]; + data->model_name[10] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} + +static struct as5812_54x_psu_data *as5812_54x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + + dev_dbg(&client->dev, "Starting as5812_54x update\n"); + data->valid = 0; + + + /* Read psu status */ + status = as5812_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as5812_54x_psu_init(void) +{ + return i2c_add_driver(&as5812_54x_psu_driver); +} + +static void __exit as5812_54x_psu_exit(void) +{ + i2c_del_driver(&as5812_54x_psu_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as5812_54x_psu driver"); +MODULE_LICENSE("GPL"); + +module_init(as5812_54x_psu_init); +module_exit(as5812_54x_psu_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/accton_as5812_54x_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/accton_as5812_54x_sfp.c new file mode 100755 index 000000000000..10841c1d22e4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/accton_as5812_54x_sfp.c @@ -0,0 +1,825 @@ +/* + * An hwmon driver for accton as5812_54x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_OF_SFF_PORT 54 +#define SFP_PORT_MAX 48 +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x61 +#define I2C_ADDR_CPLD3 0x62 +#define CPLD3_OFFSET_QSFP_MOD_RST 0x15 +#define CPLD3_OFFSET_QSFP_LPMODE 0x16 + + +#define BIT_INDEX(i) (1ULL << (i)) + +#if 0 +static ssize_t show_status(struct device *dev, struct device_attribute *da,char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +static int as5812_54x_sfp_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as5812_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5812_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +#endif + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5812_54x_sfp_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + int port; /* Front port index */ + char eeprom[256]; /* eeprom data */ + u64 status[4]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => is_present + 1 => tx_fail + 2 => tx_disable + 3 => rx_loss */ +}; + +/* The table maps active port to cpld port. + * Array index 0 is for active port 1, + * index 1 for active port 2, and so on. + * The array content implies cpld port index. + */ +static const u8 cpld_to_front_port_table[] = +{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 52, 50, 53, 51, 54}; + +#define CPLD_PORT_TO_FRONT_PORT(port) (cpld_to_front_port_table[port]) + +static struct as5812_54x_sfp_data *as5812_54x_sfp_update_device(struct device *dev, int update_eeprom); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_lp_mode(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_lp_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +extern int as5812_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5812_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +enum as5812_54x_sfp_sysfs_attributes { + SFP_IS_PRESENT, + SFP_TX_FAULT, + SFP_TX_DISABLE, + SFP_RX_LOSS, + SFP_PORT_NUMBER, + SFP_EEPROM, + SFP_RX_LOS_ALL, + SFP_IS_PRESENT_ALL, + SFP_LP_MODE, + SFP_MOD_RST, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_status, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, show_status, NULL, SFP_TX_FAULT); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, show_status, set_tx_disable, SFP_TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_rx_loss, S_IRUGO, show_status,NULL, SFP_RX_LOSS); +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM); +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, show_status,NULL, SFP_RX_LOS_ALL); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_status,NULL, SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_lp_mode, S_IWUSR | S_IRUGO, get_lp_mode, set_lp_mode, SFP_LP_MODE); +static SENSOR_DEVICE_ATTR(sfp_mod_rst, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, SFP_MOD_RST); + +static struct attribute *as5812_54x_sfp_attributes[] = { + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_eeprom.dev_attr.attr, + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_lp_mode.dev_attr.attr, + &sensor_dev_attr_sfp_mod_rst.dev_attr.attr, + NULL +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5812_54x_sfp_data *data; + u8 val; + int values[7]; + + /* Error-check the CPLD read results. */ +#define VALIDATED_READ(_buf, _rv, _read_expr, _invert) \ + do { \ + _rv = (_read_expr); \ + if(_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if(_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ + } while(0) + + if(attr->index == SFP_RX_LOS_ALL) { + /* + * Report the RX_LOS status for all ports. + * This does not depend on the currently active SFP selector. + */ + + /* RX_LOS Ports 1-8 */ + VALIDATED_READ(buf, values[0], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x0F), 0); + /* RX_LOS Ports 9-16 */ + VALIDATED_READ(buf, values[1], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x10), 0); + /* RX_LOS Ports 17-24 */ + VALIDATED_READ(buf, values[2], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x11), 0); + /* RX_LOS Ports 25-32 */ + VALIDATED_READ(buf, values[3], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x0F), 0); + /* RX_LOS Ports 33-40 */ + VALIDATED_READ(buf, values[4], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x10), 0); + /* RX_LOS Ports 41-48 */ + VALIDATED_READ(buf, values[5], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x11), 0); + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + if(attr->index == SFP_IS_PRESENT_ALL) { + /* + * Report the SFP_PRESENCE status for all ports. + * This does not depend on the currently active SFP selector. + */ + + /* SFP_PRESENT Ports 1-8 */ + VALIDATED_READ(buf, values[0], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x6), 1); + /* SFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x7), 1); + /* SFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD2, 0x8), 1); + /* SFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x6), 1); + /* SFP_PRESENT Ports 33-40 */ + VALIDATED_READ(buf, values[4], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x7), 1); + /* SFP_PRESENT Ports 41-48 */ + VALIDATED_READ(buf, values[5], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x8), 1); + /* QSFP_PRESENT Ports 49-54 */ + VALIDATED_READ(buf, values[6], as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14), 1); + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6] & 0x3F); + } + /* + * The remaining attributes are gathered on a per-selected-sfp basis. + */ + data = as5812_54x_sfp_update_device(dev, 0); + if (attr->index == SFP_IS_PRESENT) { + val = (data->status[attr->index] & BIT_INDEX(data->port)) ? 0 : 1; + } + else { + val = (data->status[attr->index] & BIT_INDEX(data->port)) ? 1 : 0; + } + + return sprintf(buf, "%d", val); +} + +static ssize_t get_lp_mode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + int port_bit; + int status = -EINVAL; + + /* Low power mode is not supported for SFP ports(1-48) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + mutex_lock(&data->update_lock); + + port_bit = data->port - SFP_PORT_MAX; + cpld_val = as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_LPMODE); + cpld_val = cpld_val & 0x3F; + cpld_val = cpld_val & BIT_INDEX(port_bit); + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", cpld_val>>port_bit); + + mutex_unlock(&data->update_lock); + + return status; +} + +static ssize_t set_lp_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + long mode; + int error, port_bit; + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + port_bit = data->port - SFP_PORT_MAX; + error = kstrtol(buf, 10, &mode); + if (error) { + return error; + } + mutex_lock(&data->update_lock); + + cpld_val = as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_LPMODE); + /* Update lp_mode status */ + if (mode) + { + cpld_val |= BIT_INDEX(port_bit); + } + else + { + cpld_val &=~BIT_INDEX(port_bit); + } + as5812_54x_i2c_cpld_write(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_LPMODE, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + int port_bit; + int status = -EINVAL; + + /* Low power mode is not supported for SFP ports(1-48) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + mutex_lock(&data->update_lock); + + port_bit = data->port - SFP_PORT_MAX; + cpld_val = as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_MOD_RST); + cpld_val = cpld_val & 0x3F; + cpld_val = cpld_val & BIT_INDEX(port_bit); + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", cpld_val>>port_bit); + + mutex_unlock(&data->update_lock); + + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + long reset; + int error, port_bit; + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + port_bit = data->port - SFP_PORT_MAX; + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + mutex_lock(&data->update_lock); + + cpld_val = as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_MOD_RST); + /* Update lp_mode status */ + if (reset) + { + cpld_val |= BIT_INDEX(port_bit); + } + else + { + cpld_val &=~BIT_INDEX(port_bit); + } + as5812_54x_i2c_cpld_write(I2C_ADDR_CPLD3, CPLD3_OFFSET_QSFP_MOD_RST, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); + unsigned short cpld_addr = 0; + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long disable; + int error; + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port >= SFP_PORT_MAX) { + return -EINVAL; + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + if(data->port < 24) { + cpld_addr = I2C_ADDR_CPLD2; + cpld_reg = 0xC + data->port / 8; + cpld_bit = 1 << (data->port % 8); + } + else { + cpld_addr = I2C_ADDR_CPLD3; + cpld_reg = 0xC + (data->port - 24) / 8; + cpld_bit = 1 << (data->port % 8); + } + + cpld_val = as5812_54x_i2c_cpld_read(cpld_addr, cpld_reg); + + /* Update tx_disable status */ + if (disable) { + data->status[SFP_TX_DISABLE] |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->status[SFP_TX_DISABLE] &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + as5812_54x_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as5812_54x_sfp_data *data = as5812_54x_sfp_update_device(dev, 1); + + if (!data->valid) { + return 0; + } + + if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) != 0) { + return 0; + } + + memcpy(buf, data->eeprom, sizeof(data->eeprom)); + + return sizeof(data->eeprom); +} + +static const struct attribute_group as5812_54x_sfp_group = { + .attrs = as5812_54x_sfp_attributes, +}; + +static int as5812_54x_sfp_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5812_54x_sfp_data *data; + int status; + + extern int platform_accton_as5812_54x(void); + if(!platform_accton_as5812_54x()) { + return -ENODEV; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5812_54x_sfp_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + i2c_set_clientdata(client, data); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5812_54x_sfp_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sfp '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5812_54x_sfp_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5812_54x_sfp_remove(struct i2c_client *client) +{ + struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5812_54x_sfp_group); + kfree(data); + + return 0; +} + +enum port_numbers { +as5812_54x_sfp1, as5812_54x_sfp2, as5812_54x_sfp3, as5812_54x_sfp4, +as5812_54x_sfp5, as5812_54x_sfp6, as5812_54x_sfp7, as5812_54x_sfp8, +as5812_54x_sfp9, as5812_54x_sfp10, as5812_54x_sfp11,as5812_54x_sfp12, +as5812_54x_sfp13, as5812_54x_sfp14, as5812_54x_sfp15,as5812_54x_sfp16, +as5812_54x_sfp17, as5812_54x_sfp18, as5812_54x_sfp19,as5812_54x_sfp20, +as5812_54x_sfp21, as5812_54x_sfp22, as5812_54x_sfp23,as5812_54x_sfp24, +as5812_54x_sfp25, as5812_54x_sfp26, as5812_54x_sfp27,as5812_54x_sfp28, +as5812_54x_sfp29, as5812_54x_sfp30, as5812_54x_sfp31,as5812_54x_sfp32, +as5812_54x_sfp33, as5812_54x_sfp34, as5812_54x_sfp35,as5812_54x_sfp36, +as5812_54x_sfp37, as5812_54x_sfp38, as5812_54x_sfp39,as5812_54x_sfp40, +as5812_54x_sfp41, as5812_54x_sfp42, as5812_54x_sfp43,as5812_54x_sfp44, +as5812_54x_sfp45, as5812_54x_sfp46, as5812_54x_sfp47,as5812_54x_sfp48, +as5812_54x_sfp49, as5812_54x_sfp52, as5812_54x_sfp50,as5812_54x_sfp53, +as5812_54x_sfp51, as5812_54x_sfp54 +}; + +static const struct i2c_device_id as5812_54x_sfp_id[] = { +{ "as5812_54x_sfp1", as5812_54x_sfp1 }, { "as5812_54x_sfp2", as5812_54x_sfp2 }, +{ "as5812_54x_sfp3", as5812_54x_sfp3 }, { "as5812_54x_sfp4", as5812_54x_sfp4 }, +{ "as5812_54x_sfp5", as5812_54x_sfp5 }, { "as5812_54x_sfp6", as5812_54x_sfp6 }, +{ "as5812_54x_sfp7", as5812_54x_sfp7 }, { "as5812_54x_sfp8", as5812_54x_sfp8 }, +{ "as5812_54x_sfp9", as5812_54x_sfp9 }, { "as5812_54x_sfp10", as5812_54x_sfp10 }, +{ "as5812_54x_sfp11", as5812_54x_sfp11 }, { "as5812_54x_sfp12", as5812_54x_sfp12 }, +{ "as5812_54x_sfp13", as5812_54x_sfp13 }, { "as5812_54x_sfp14", as5812_54x_sfp14 }, +{ "as5812_54x_sfp15", as5812_54x_sfp15 }, { "as5812_54x_sfp16", as5812_54x_sfp16 }, +{ "as5812_54x_sfp17", as5812_54x_sfp17 }, { "as5812_54x_sfp18", as5812_54x_sfp18 }, +{ "as5812_54x_sfp19", as5812_54x_sfp19 }, { "as5812_54x_sfp20", as5812_54x_sfp20 }, +{ "as5812_54x_sfp21", as5812_54x_sfp21 }, { "as5812_54x_sfp22", as5812_54x_sfp22 }, +{ "as5812_54x_sfp23", as5812_54x_sfp23 }, { "as5812_54x_sfp24", as5812_54x_sfp24 }, +{ "as5812_54x_sfp25", as5812_54x_sfp25 }, { "as5812_54x_sfp26", as5812_54x_sfp26 }, +{ "as5812_54x_sfp27", as5812_54x_sfp27 }, { "as5812_54x_sfp28", as5812_54x_sfp28 }, +{ "as5812_54x_sfp29", as5812_54x_sfp29 }, { "as5812_54x_sfp30", as5812_54x_sfp30 }, +{ "as5812_54x_sfp31", as5812_54x_sfp31 }, { "as5812_54x_sfp32", as5812_54x_sfp32 }, +{ "as5812_54x_sfp33", as5812_54x_sfp33 }, { "as5812_54x_sfp34", as5812_54x_sfp34 }, +{ "as5812_54x_sfp35", as5812_54x_sfp35 }, { "as5812_54x_sfp36", as5812_54x_sfp36 }, +{ "as5812_54x_sfp37", as5812_54x_sfp37 }, { "as5812_54x_sfp38", as5812_54x_sfp38 }, +{ "as5812_54x_sfp39", as5812_54x_sfp39 }, { "as5812_54x_sfp40", as5812_54x_sfp40 }, +{ "as5812_54x_sfp41", as5812_54x_sfp41 }, { "as5812_54x_sfp42", as5812_54x_sfp42 }, +{ "as5812_54x_sfp43", as5812_54x_sfp43 }, { "as5812_54x_sfp44", as5812_54x_sfp44 }, +{ "as5812_54x_sfp45", as5812_54x_sfp45 }, { "as5812_54x_sfp46", as5812_54x_sfp46 }, +{ "as5812_54x_sfp47", as5812_54x_sfp47 }, { "as5812_54x_sfp48", as5812_54x_sfp48 }, +{ "as5812_54x_sfp49", as5812_54x_sfp49 }, { "as5812_54x_sfp50", as5812_54x_sfp50 }, +{ "as5812_54x_sfp51", as5812_54x_sfp51 }, { "as5812_54x_sfp52", as5812_54x_sfp52 }, +{ "as5812_54x_sfp53", as5812_54x_sfp53 }, { "as5812_54x_sfp54", as5812_54x_sfp54 }, + +{} +}; +MODULE_DEVICE_TABLE(i2c, as5812_54x_sfp_id); + +static struct i2c_driver as5812_54x_sfp_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5812_54x_sfp", + }, + .probe = as5812_54x_sfp_probe, + .remove = as5812_54x_sfp_remove, + .id_table = as5812_54x_sfp_id, + .address_list = normal_i2c, +}; + +static int as5812_54x_sfp_read_byte(struct i2c_client *client, u8 command, u8 *data) +{ + int result = i2c_smbus_read_byte_data(client, command); + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 0; + +abort: + return result; +} + +#define ALWAYS_UPDATE_DEVICE 1 + +static struct as5812_54x_sfp_data *as5812_54x_sfp_update_device(struct device *dev, int update_eeprom) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (ALWAYS_UPDATE_DEVICE || time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + int i = 0, j = 0; + + data->valid = 0; + //dev_dbg(&client->dev, "Starting as5812_54x sfp status update\n"); + memset(data->status, 0, sizeof(data->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 12; j++) { + status = as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD2+i, 0x6+j); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + goto exit; + } + + data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* + * Bring QSFPs out of reset, + * This is a temporary fix until the QSFP+_MOD_RST register + * can be exposed through the driver. + */ + as5812_54x_i2c_cpld_write(I2C_ADDR_CPLD3, 0x15, 0x3F); + + /* Read present status of port 49-54(QSFP port) */ + status = as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + } + else { + data->status[SFP_IS_PRESENT] |= (u64)status << 48; + } + + if (update_eeprom) { + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) == 0) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom); i++) { + status = as5812_54x_sfp_read_byte(client, i, data->eeprom + i); + + if (status < 0) { + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", + CPLD_PORT_TO_FRONT_PORT(data->port)); + goto exit; + } + } + } + } + + data->valid = 1; + data->last_updated = jiffies; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as5812_54x_sfp_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as5812_54x_sfp driver"); +MODULE_LICENSE("GPL"); + +#if 0 + int i = 0, j = 0; + + data->valid = 0; + //dev_dbg(&client->dev, "Starting as5812_54x sfp update\n"); + memset(data->status, 0, sizeof(data->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 12; j++) { + status = as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD2+i, 0x6+j); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + continue; + } + + data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* Read present status of port 49-54(QSFP port) */ + status = as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + } + else { + data->status[SFP_IS_PRESENT] |= (u64)status << 48; + } +#endif + +/* Reserver to prevent from CPLD port mapping is changed + */ +#if 0 +BIT_INDEX(port_present_index[data->port]) +/* The bit index of is_present field read from CPLD + * Array index 0 is for as5812_54x_sfp1, + * index 1 is for as5812_54x_sfp2, and so on. + */ +static const int port_present_index[] = { + 4, 5, 6, 7, 9, 8, 11, 10, + 0, 1, 2, 3, 12, 13, 14, 15, +16, 17, 18, 19, 28, 29, 30, 31, +20, 21, 22, 23, 24, 25, 26, 27 +}; +#endif + +#if 0 +static struct as5812_54x_sfp_data *as5812_54x_sfp_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5812_54x_sfp_data *data = i2c_get_clientdata(client); + int status = -1; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->status_last_updated + HZ + HZ / 2) + || !data->status_valid) { + int status = -1; + int i = 0, j = 0; + + data->status_valid = 0; + //dev_dbg(&client->dev, "Starting as5812_54x sfp status update\n"); + memset(data->status, 0, sizeof(data->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 12; j++) { + status = as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD2+i, 0x6+j); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + goto exit; + } + + data->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* + * Bring QSFPs out of reset, + * This is a temporary fix until the QSFP+_MOD_RST register + * can be exposed through the driver. + */ + as5812_54x_i2c_cpld_write(I2C_ADDR_CPLD3, 0x15, 0x3F); + + /* Read present status of port 49-54(QSFP port) */ + status = as5812_54x_i2c_cpld_read(I2C_ADDR_CPLD3, 0x14); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD2+i, 0x6+j, status); + } + else { + data->status[SFP_IS_PRESENT] |= (u64)status << 48; + } + + data->status_valid = 1; + data->status_last_updated = jiffies; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static struct as5812_54x_sfp_data *as5812_54x_sfp_update_eeprom(struct device *dev) +{ + struct as5812_54x_sfp_data *data = NULL; + + data = as5812_54x_sfp_update_status(dev); + + if (data == NULL || data->status_valid == 0) { + data->eeprom_valid = 0; + return data; + } + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->eeprom_last_updated + HZ + HZ / 2) + || !data->eeprom_valid) { + int status = -1; + int i = 0; + + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if ((data->status[SFP_IS_PRESENT] & BIT_INDEX(data->port)) == 0) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom)/I2C_SMBUS_BLOCK_MAX; i++) { + status = as5812_54x_sfp_read_block(client, i*I2C_SMBUS_BLOCK_MAX, + data->eeprom+(i*I2C_SMBUS_BLOCK_MAX), + I2C_SMBUS_BLOCK_MAX); + if (status < 0) { + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", + CPLD_PORT_TO_FRONT_PORT(data->port)); + goto exit; + } + } + } + + data->eeprom_last_updated = jiffies; + data->eeprom_valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} +#endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/cpr_4011_4mxx.c new file mode 100755 index 000000000000..30bea914d589 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/cpr_4011_4mxx.c @@ -0,0 +1,400 @@ +/* + * An hwmon driver for the CPR-4011-4Mxx Redundant Power Module + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x3c, 0x3d, 0x3e, 0x3f, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct cpr_4011_4mxx_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev); + +enum cpr_4011_4mxx_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); + +static struct attribute *cpr_4011_4mxx_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cpr_4011_4mxx_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static const struct attribute_group cpr_4011_4mxx_group = { + .attrs = cpr_4011_4mxx_attributes, +}; + +static int cpr_4011_4mxx_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct cpr_4011_4mxx_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct cpr_4011_4mxx_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpr_4011_4mxx_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int cpr_4011_4mxx_remove(struct i2c_client *client) +{ + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id cpr_4011_4mxx_id[] = { + { "cpr_4011_4mxx", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpr_4011_4mxx_id); + +static struct i2c_driver cpr_4011_4mxx_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cpr_4011_4mxx", + }, + .probe = cpr_4011_4mxx_probe, + .remove = cpr_4011_4mxx_remove, + .id_table = cpr_4011_4mxx_id, + .address_list = normal_i2c, +}; + +static int cpr_4011_4mxx_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cpr_4011_4mxx_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + struct reg_data_byte regs_byte[] = { {0x20, &data->vout_mode}, + {0x81, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &(data->fan_speed[0])}, + {0x91, &(data->fan_speed[1])}}; + + dev_dbg(&client->dev, "Starting cpr_4011_4mxx update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cpr_4011_4mxx_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = cpr_4011_4mxx_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init cpr_4011_4mxx_init(void) +{ + return i2c_add_driver(&cpr_4011_4mxx_driver); +} + +static void __exit cpr_4011_4mxx_exit(void) +{ + i2c_del_driver(&cpr_4011_4mxx_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("CPR_4011_4MXX driver"); +MODULE_LICENSE("GPL"); + +module_init(cpr_4011_4mxx_init); +module_exit(cpr_4011_4mxx_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/i2c-mux-accton_as5812_54x_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/i2c-mux-accton_as5812_54x_cpld.c new file mode 100644 index 000000000000..1578d75bdd92 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/i2c-mux-accton_as5812_54x_cpld.c @@ -0,0 +1,1421 @@ +/* + * An I2C multiplexer dirver for accton as5812 CPLD + * + * Copyright (C) 2015 Accton Technology Corporation. + * Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as5812_54x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define NUM_OF_CPLD1_CHANS 0x0 +#define NUM_OF_CPLD2_CHANS 0x18 +#define NUM_OF_CPLD3_CHANS 0x1E +#define CPLD_CHANNEL_SELECT_REG 0x2 +#define CPLD_DESELECT_CHANNEL 0xFF + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_mux_type { + as5812_54x_cpld2, + as5812_54x_cpld3, + as5812_54x_cpld1 +}; + +struct as5812_54x_cpld_data { + enum cpld_mux_type type; + struct i2c_client *client; + u8 last_chan; /* last register value */ + + struct device *hwmon_dev; + struct mutex update_lock; +}; + +struct chip_desc { + u8 nchans; + u8 deselectChan; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [as5812_54x_cpld1] = { + .nchans = NUM_OF_CPLD1_CHANS, + .deselectChan = CPLD_DESELECT_CHANNEL, + }, + [as5812_54x_cpld2] = { + .nchans = NUM_OF_CPLD2_CHANS, + .deselectChan = CPLD_DESELECT_CHANNEL, + }, + [as5812_54x_cpld3] = { + .nchans = NUM_OF_CPLD3_CHANS, + .deselectChan = CPLD_DESELECT_CHANNEL, + } +}; + +static const struct i2c_device_id as5812_54x_cpld_mux_id[] = { + { "as5812_54x_cpld1", as5812_54x_cpld1 }, + { "as5812_54x_cpld2", as5812_54x_cpld2 }, + { "as5812_54x_cpld3", as5812_54x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as5812_54x_cpld_mux_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_LPMODE_ATTR_ID(index) MODULE_LPMODE_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as5812_54x_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), + TRANSCEIVER_LPMODE_ATTR_ID(49), + TRANSCEIVER_LPMODE_ATTR_ID(50), + TRANSCEIVER_LPMODE_ATTR_ID(51), + TRANSCEIVER_LPMODE_ATTR_ID(52), + TRANSCEIVER_LPMODE_ATTR_ID(53), + TRANSCEIVER_LPMODE_ATTR_ID(54), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_lp_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as5812_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5812_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +#define DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_lp_mode_##index, S_IRUGO | S_IWUSR, show_status, set_lp_mode, MODULE_LPMODE_##index); \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, show_status, set_mode_reset, MODULE_RESET_##index) + +#define DECLARE_QSFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_lp_mode_##index.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##index.dev_attr.attr + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); + +static struct attribute *as5812_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5812_54x_cpld1_group = { + .attrs = as5812_54x_cpld1_attributes, +}; + +static struct attribute *as5812_54x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + NULL +}; + +static const struct attribute_group as5812_54x_cpld2_group = { + .attrs = as5812_54x_cpld2_attributes, +}; + +static struct attribute *as5812_54x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + DECLARE_QSFP_TRANSCEIVER_ATTR(49), + DECLARE_QSFP_TRANSCEIVER_ATTR(50), + DECLARE_QSFP_TRANSCEIVER_ATTR(51), + DECLARE_QSFP_TRANSCEIVER_ATTR(52), + DECLARE_QSFP_TRANSCEIVER_ATTR(53), + DECLARE_QSFP_TRANSCEIVER_ATTR(54), + NULL +}; + +static const struct attribute_group as5812_54x_cpld3_group = { + .attrs = as5812_54x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status, num_regs = 0; + u8 values[4] = {0}; + u8 regs[] = {0x6, 0x7, 0x8, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5812_54x_cpld_data *data = i2c_mux_priv(muxc); + + mutex_lock(&data->update_lock); + + num_regs = (data->type == as5812_54x_cpld2) ? 3 : 4; + + for (i = 0; i < num_regs; i++) { + status = as5812_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + if (data->type == as5812_54x_cpld2) { + status = sprintf(buf, "%.2x %.2x %.2x\n", + values[0], values[1], values[2]); + } + else { /* as5812_54x_cpld3 */ + values[3] &= 0x3F; + status = sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + } + + return status; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[3] = {0}; + u8 regs[] = {0xF, 0x10, 0x11}; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5812_54x_cpld_data *data = i2c_mux_priv(muxc); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as5812_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5812_54x_cpld_data *data = i2c_mux_priv(muxc); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_40: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_33); + break; + case MODULE_PRESENT_41 ... MODULE_PRESENT_48: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_41); + break; + case MODULE_PRESENT_49: + reg = 0x14; + mask = 0x1; + break; + case MODULE_PRESENT_50: + reg = 0x14; + mask = 0x4; + break; + case MODULE_PRESENT_51: + reg = 0x14; + mask = 0x10; + break; + case MODULE_PRESENT_52: + reg = 0x14; + mask = 0x2; + break; + case MODULE_PRESENT_53: + reg = 0x14; + mask = 0x8; + break; + case MODULE_PRESENT_54: + reg = 0x14; + mask = 0x20; + break; + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_8: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_1); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_16: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_9); + break; + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_24: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_TXFAULT_17); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_32: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_40: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_33); + break; + case MODULE_TXFAULT_41 ... MODULE_TXFAULT_48: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_TXFAULT_41); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_1); + break; + case MODULE_RXLOS_9 ... MODULE_RXLOS_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_9); + break; + case MODULE_RXLOS_17 ... MODULE_RXLOS_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_RXLOS_17); + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_RXLOS_33 ... MODULE_RXLOS_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_33); + break; + case MODULE_RXLOS_41 ... MODULE_RXLOS_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_RXLOS_41); + break; + case MODULE_LPMODE_49 ... MODULE_LPMODE_54: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + break; + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_49); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_54) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as5812_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5812_54x_cpld_data *data = i2c_mux_priv(muxc); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5812_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5812_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_lp_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5812_54x_cpld_data *data = i2c_mux_priv(muxc); + + long on; + int status= -ENOENT; + u8 reg = 0x16, mask = 0; + + if(attr->index < MODULE_LPMODE_49 || attr->index > MODULE_LPMODE_54) + return status; + + status = kstrtol(buf, 10, &on); + if (status) { + return status; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5812_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + + /* Update lp_mode status */ + if (on) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5812_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; + +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5812_54x_cpld_data *data = i2c_mux_priv(muxc); + + long on; + int status= -ENOENT; + u8 reg = 0x15, mask = 0; + + if(attr->index < MODULE_RESET_49 || attr->index > MODULE_RESET_54) + return status; + + status = kstrtol(buf, 10, &on); + if (status) { + return status; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5812_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + mask = 0x1 << (attr->index - MODULE_RESET_49); + + /* Update tx_disable status */ + if (on) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5812_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; + +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5812_54x_cpld_data *data = i2c_mux_priv(muxc); + int status; + u32 addr, val; + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as5812_54x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int as5812_54x_cpld_mux_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + unsigned long orig_jiffies; + unsigned short flags; + union i2c_smbus_data data; + int try; + s32 res = -EIO; + + data.byte = val; + flags = client->flags; + flags &= I2C_M_TEN | I2C_CLIENT_PEC; + + if (adap->algo->smbus_xfer) { + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (res = 0, try = 0; try <= adap->retries; try++) { + res = adap->algo->smbus_xfer(adap, client->addr, flags, + I2C_SMBUS_WRITE, CPLD_CHANNEL_SELECT_REG, + I2C_SMBUS_BYTE_DATA, &data); + if (res != -EAGAIN) + break; + if (time_after(jiffies, + orig_jiffies + adap->timeout)) + break; + } + } + + return res; +} + +static int as5812_54x_cpld_mux_select_chan(struct i2c_mux_core *muxc, + u32 chan) +{ + struct as5812_54x_cpld_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + u8 regval; + int ret = 0; + + regval = chan; + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + ret = as5812_54x_cpld_mux_reg_write(muxc->parent, client, regval); + data->last_chan = regval; + } + + return ret; +} + +static int as5812_54x_cpld_mux_deselect_mux(struct i2c_mux_core *muxc, + u32 chan) +{ + struct as5812_54x_cpld_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + /* Deselect active channel */ + data->last_chan = chips[data->type].deselectChan; + + return as5812_54x_cpld_mux_reg_write(muxc->parent, client, data->last_chan); +} + +static void as5812_54x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as5812_54x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as5812_54x_cpld_mux_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + int num, force, class; + struct i2c_mux_core *muxc; + struct as5812_54x_cpld_data *data; + int ret = 0; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + muxc = i2c_mux_alloc(adap, &client->dev, + chips[id->driver_data].nchans, sizeof(*data), 0, + as5812_54x_cpld_mux_select_chan, as5812_54x_cpld_mux_deselect_mux); + if (!muxc) + return -ENOMEM; + + i2c_set_clientdata(client, muxc); + data = i2c_mux_priv(muxc); + data->client = client; + data->type = id->driver_data; + data->last_chan = chips[data->type].deselectChan; /* force the first selection */ + mutex_init(&data->update_lock); + + /* Now create an adapter for each channel */ + for (num = 0; num < chips[data->type].nchans; num++) { + force = 0; /* dynamic adap number */ + class = 0; /* no class by default */ + + ret = i2c_mux_add_adapter(muxc, force, num, class); + + if (ret) { + dev_err(&client->dev, + "failed to register multiplexed adapter" + " %d as bus %d\n", num, force); + goto add_mux_failed; + } + } + + /* Register sysfs hooks */ + switch (data->type) { + case as5812_54x_cpld1: + group = &as5812_54x_cpld1_group; + break; + case as5812_54x_cpld2: + group = &as5812_54x_cpld2_group; + break; + case as5812_54x_cpld3: + group = &as5812_54x_cpld3_group; + + /* Bring QSFPs out of reset */ + as5812_54x_cpld_write_internal(client, 0x15, 0x3F); + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto add_mux_failed; + } + } + + if (chips[data->type].nchans) { + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s\n", + num, client->name); + } + else { + dev_info(&client->dev, + "device %s registered\n", client->name); + } + + as5812_54x_cpld_add_client(client); + + return 0; + +add_mux_failed: + i2c_mux_del_adapters(muxc); + return ret; +} + +static int as5812_54x_cpld_mux_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as5812_54x_cpld_data *data = i2c_mux_priv(muxc); + const struct attribute_group *group = NULL; + + as5812_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as5812_54x_cpld1: + group = &as5812_54x_cpld1_group; + break; + case as5812_54x_cpld2: + group = &as5812_54x_cpld2_group; + break; + case as5812_54x_cpld3: + group = &as5812_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + i2c_mux_del_adapters(muxc); + + return 0; +} + +static int as5812_54x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as5812_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as5812_54x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5812_54x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5812_54x_cpld_read); + +int as5812_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5812_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5812_54x_cpld_write); + +static struct i2c_driver as5812_54x_cpld_mux_driver = { + .driver = { + .name = "as5812_54x_cpld", + .owner = THIS_MODULE, + }, + .probe = as5812_54x_cpld_mux_probe, + .remove = as5812_54x_cpld_mux_remove, + .id_table = as5812_54x_cpld_mux_id, +}; + +static int __init as5812_54x_cpld_mux_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as5812_54x_cpld_mux_driver); +} + +static void __exit as5812_54x_cpld_mux_exit(void) +{ + i2c_del_driver(&as5812_54x_cpld_mux_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton as5812-54x CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as5812_54x_cpld_mux_init); +module_exit(as5812_54x_cpld_mux_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/leds-accton_as5812_54x.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/leds-accton_as5812_54x.c new file mode 100755 index 000000000000..430a16db11e1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/leds-accton_as5812_54x.c @@ -0,0 +1,593 @@ +/* + * A LED driver for the accton_as5812_54x_led + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include + +extern int as5812_54x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as5812_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as5812_54x_led" + +struct accton_as5812_54x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[4]; /* Register value, 0 = LOC/DIAG/FAN LED + 1 = PSU1/PSU2 LED + 2 = FAN1-4 LED + 3 = FAN5-6 LED */ +}; + +static struct accton_as5812_54x_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_TYPE_PSU1_REG_MASK 0x03 +#define LED_MODE_PSU1_GREEN_MASK 0x02 +#define LED_MODE_PSU1_AMBER_MASK 0x01 +#define LED_MODE_PSU1_OFF_MASK 0x03 +#define LED_MODE_PSU1_AUTO_MASK 0x00 + +#define LED_TYPE_PSU2_REG_MASK 0x0C +#define LED_MODE_PSU2_GREEN_MASK 0x08 +#define LED_MODE_PSU2_AMBER_MASK 0x04 +#define LED_MODE_PSU2_OFF_MASK 0x0C +#define LED_MODE_PSU2_AUTO_MASK 0x00 + +#define LED_TYPE_DIAG_REG_MASK 0x0C +#define LED_MODE_DIAG_GREEN_MASK 0x08 +#define LED_MODE_DIAG_AMBER_MASK 0x04 +#define LED_MODE_DIAG_OFF_MASK 0x0C + +#define LED_TYPE_FAN_REG_MASK 0x03 +#define LED_MODE_FAN_GREEN_MASK 0x02 +#define LED_MODE_FAN_AMBER_MASK 0x01 +#define LED_MODE_FAN_OFF_MASK 0x03 +#define LED_MODE_FAN_AUTO_MASK 0x00 + +#define LED_TYPE_FAN1_REG_MASK 0x03 +#define LED_TYPE_FAN2_REG_MASK 0x0C +#define LED_TYPE_FAN3_REG_MASK 0x30 +#define LED_TYPE_FAN4_REG_MASK 0xC0 +#define LED_TYPE_FAN5_REG_MASK 0x03 +#define LED_TYPE_FAN6_REG_MASK 0x0C + +#define LED_MODE_FANX_GREEN_MASK 0x01 +#define LED_MODE_FANX_RED_MASK 0x02 +#define LED_MODE_FANX_OFF_MASK 0x00 + +#define LED_TYPE_LOC_REG_MASK 0x30 +#define LED_MODE_LOC_ON_MASK 0x00 +#define LED_MODE_LOC_OFF_MASK 0x10 +#define LED_MODE_LOC_BLINK_MASK 0x20 + +static const u8 led_reg[] = { + 0xA, /* LOC/DIAG/FAN LED*/ + 0xB, /* PSU1/PSU2 LED */ + 0x16, /* FAN1-4 LED */ + 0x17, /* FAN4-6 LED */ +}; + +enum led_type { + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_DIAG, + LED_TYPE_FAN, + LED_TYPE_FAN1, + LED_TYPE_FAN2, + LED_TYPE_FAN3, + LED_TYPE_FAN4, + LED_TYPE_FAN5, + LED_TYPE_LOC +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_AUTO, +}; + +struct led_type_mode { + enum led_type type; + int type_mask; + enum led_light_mode mode; + int mode_mask; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU1_AUTO_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU2_AUTO_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AUTO, LED_MODE_FAN_AUTO_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_GREEN, LED_MODE_DIAG_GREEN_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_AMBER, LED_MODE_DIAG_AMBER_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_OFF, LED_MODE_DIAG_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER, LED_MODE_LOC_ON_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_OFF, LED_MODE_LOC_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER_BLINK, LED_MODE_LOC_BLINK_MASK} +}; + + +struct fanx_info_s { + u8 cname; /* device name */ + enum led_type type; + u8 reg_id; /* map to led_reg & reg_val */ +}; + +static struct fanx_info_s fanx_info[] = { + {'1', LED_TYPE_FAN1, 2}, + {'2', LED_TYPE_FAN2, 2}, + {'3', LED_TYPE_FAN3, 2}, + {'4', LED_TYPE_FAN4, 2}, + {'5', LED_TYPE_FAN5, 3} +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + } + + return reg_val; +} + +static int accton_as5812_54x_led_read_value(u8 reg) +{ + return as5812_54x_cpld_read(0x60, reg); +} + +static int accton_as5812_54x_led_write_value(u8 reg, u8 value) +{ + return as5812_54x_cpld_write(0x60, reg, value); +} + +static void accton_as5812_54x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as5812_54x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as5812_54x_led_read_value(led_reg[i]); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5812_54x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + + reg_val = accton_as5812_54x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as5812_54x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5812_54x_led_psu_1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness accton_as5812_54x_led_psu_1_get(struct led_classdev *cdev) +{ + accton_as5812_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void accton_as5812_54x_led_psu_2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness accton_as5812_54x_led_psu_2_get(struct led_classdev *cdev) +{ + accton_as5812_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static void accton_as5812_54x_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN); +} + +static enum led_brightness accton_as5812_54x_led_fan_get(struct led_classdev *cdev) +{ + accton_as5812_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + + +static void accton_as5812_54x_led_fanx_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (led_cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as5812_54x_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1); + return; + } + } +} + + +static enum led_brightness accton_as5812_54x_led_fanx_get(struct led_classdev *cdev) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as5812_54x_led_update(); + return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]); + } + } + + + return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[2]); +} + + +static void accton_as5812_54x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_as5812_54x_led_diag_get(struct led_classdev *cdev) +{ + accton_as5812_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as5812_54x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5812_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness accton_as5812_54x_led_loc_get(struct led_classdev *cdev) +{ + accton_as5812_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static struct led_classdev accton_as5812_54x_leds[] = { + [LED_TYPE_PSU1] = { + .name = "accton_as5812_54x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as5812_54x_led_psu_1_set, + .brightness_get = accton_as5812_54x_led_psu_1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as5812_54x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as5812_54x_led_psu_2_set, + .brightness_get = accton_as5812_54x_led_psu_2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "accton_as5812_54x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as5812_54x_led_fan_set, + .brightness_get = accton_as5812_54x_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN1] = { + .name = "accton_as5812_54x_led::fan1", + .default_trigger = "unused", + .brightness_set = accton_as5812_54x_led_fanx_set, + .brightness_get = accton_as5812_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN2] = { + .name = "accton_as5812_54x_led::fan2", + .default_trigger = "unused", + .brightness_set = accton_as5812_54x_led_fanx_set, + .brightness_get = accton_as5812_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN3] = { + .name = "accton_as5812_54x_led::fan3", + .default_trigger = "unused", + .brightness_set = accton_as5812_54x_led_fanx_set, + .brightness_get = accton_as5812_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN4] = { + .name = "accton_as5812_54x_led::fan4", + .default_trigger = "unused", + .brightness_set = accton_as5812_54x_led_fanx_set, + .brightness_get = accton_as5812_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN5] = { + .name = "accton_as5812_54x_led::fan5", + .default_trigger = "unused", + .brightness_set = accton_as5812_54x_led_fanx_set, + .brightness_get = accton_as5812_54x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_DIAG] = { + .name = "accton_as5812_54x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as5812_54x_led_diag_set, + .brightness_get = accton_as5812_54x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_LOC] = { + .name = "accton_as5812_54x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as5812_54x_led_loc_set, + .brightness_get = accton_as5812_54x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as5812_54x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54x_leds); i++) { + led_classdev_suspend(&accton_as5812_54x_leds[i]); + } + + return 0; +} + +static int accton_as5812_54x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54x_leds); i++) { + led_classdev_resume(&accton_as5812_54x_leds[i]); + } + + return 0; +} + +static int accton_as5812_54x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as5812_54x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as5812_54x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as5812_54x_leds[i]); + } + } + + return ret; +} + +static int accton_as5812_54x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as5812_54x_leds); i++) { + led_classdev_unregister(&accton_as5812_54x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as5812_54x_led_driver = { + .probe = accton_as5812_54x_led_probe, + .remove = accton_as5812_54x_led_remove, + .suspend = accton_as5812_54x_led_suspend, + .resume = accton_as5812_54x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5812_54x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5812_54x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as5812_54x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as5812_54x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as5812_54x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as5812_54x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as5812_54x_led_driver); + kfree(ledctl); +} + +module_init(accton_as5812_54x_led_init); +module_exit(accton_as5812_54x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5812_54x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/ym2651y.c new file mode 100755 index 000000000000..519530387e29 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/modules/ym2651y.c @@ -0,0 +1,683 @@ +/* + * An hwmon driver for the 3Y Power YM-2651Y Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +enum chips { + YM2651, + YM2401, +}; + +/* Each client has this additional data + */ +struct ym2651y_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 chip; /* chip id */ + u8 capability; /* Register value */ + u16 status_word; /* Register value */ + u8 fan_fault; /* Register value */ + u8 over_temp; /* Register value */ + u16 v_out; /* Register value */ + u16 i_out; /* Register value */ + u16 p_out; /* Register value */ + u8 vout_mode; /* Register value */ + u16 temp; /* Register value */ + u16 fan_speed; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u8 fan_dir[5]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[16]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct ym2651y_data *ym2651y_update_device(struct device *dev); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum ym2651y_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); + +static struct attribute *ym2651y_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + NULL +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + if (!data->valid) { + return 0; + } + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u16 status = 0; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ + status = (data->status_word & 0x40) ? 0 : 1; + break; + case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ + status = (data->status_word & 0x4) >> 2; + break; + case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ + status = (data->status_word & 0x800) ? 0 : 1; + break; + } + + return sprintf(buf, "%d\n", status); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_V_OUT: + value = data->v_out; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + case PSU_FAN1_DUTY_CYCLE: + value = data->fan_duty_cycle[0]; + multiplier = 1; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_VOUT_MIN: + value = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + value = data->mfr_vout_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 shift; + + if (!data->valid) { + return 0; + } + + shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + + if (!data->valid) { + return 0; + } + + return sprintf(buf, "%d\n", data->over_temp >> 7); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_FAN_DIRECTION: /* psu_fan_dir */ + ptr = data->fan_dir + 1; /* Skip the first byte since it is the length of string. */ + break; + case PSU_MFR_ID: /* psu_mfr_id */ + ptr = data->mfr_id + 1; /* The first byte is the count byte of string. */; + break; + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model + 1; /* The first byte is the count byte of string. */ + break; + case PSU_MFR_REVISION: /* psu_mfr_revision */ + ptr = data->mfr_revsion + 1; /* The first byte is the count byte of string. */ + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static ssize_t show_vout_by_mode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + if (!data->valid) { + return 0; + } + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + if (data->chip == YM2401) { + return show_vout_by_mode(dev, da, buf); + } + + return show_linear(dev, da, buf); +} + +static const struct attribute_group ym2651y_group = { + .attrs = ym2651y_attributes, +}; + +static int ym2651y_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ym2651y_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->chip = dev_id->driver_data; + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int ym2651y_remove(struct i2c_client *client) +{ + struct ym2651y_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id ym2651y_id[] = { + { "ym2651", YM2651 }, + { "ym2401", YM2401 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ym2651y_id); + +static struct i2c_driver ym2651y_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ym2651", + }, + .probe = ym2651y_probe, + .remove = ym2651y_remove, + .id_table = ym2651y_id, + .address_list = normal_i2c, +}; + +static int ym2651y_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int ym2651y_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct ym2651y_data *ym2651y_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status, length; + u8 command, buf; + struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, + {0x20, &data->vout_mode}, + {0x7d, &data->over_temp}, + {0x81, &data->fan_fault}, + {0x98, &data->pmbus_revision}}; + struct reg_data_word regs_word[] = { {0x79, &data->status_word}, + {0x8b, &data->v_out}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x8d, &data->temp}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &data->fan_speed}, + {0xa0, &data->mfr_vin_min}, + {0xa1, &data->mfr_vin_max}, + {0xa2, &data->mfr_iin_max}, + {0xa3, &data->mfr_pin_max}, + {0xa4, &data->mfr_vout_min}, + {0xa5, &data->mfr_vout_max}, + {0xa6, &data->mfr_iout_max}, + {0xa7, &data->mfr_pout_max}}; + + dev_dbg(&client->dev, "Starting ym2651 update\n"); + data->valid = 0; + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = ym2651y_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + goto exit; + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = ym2651y_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + goto exit; + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read fan_direction */ + command = 0xC3; + status = ym2651y_read_block(client, command, data->fan_dir, + ARRAY_SIZE(data->fan_dir)-1); + data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + /* Read mfr_id */ + command = 0x99; + status = ym2651y_read_block(client, command, data->mfr_id, + ARRAY_SIZE(data->mfr_id)-1); + data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + /* Read mfr_model */ + command = 0x9a; + length = 1; + + /* Read first byte to determine the length of data */ + status = ym2651y_read_block(client, command, &buf, length); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + status = ym2651y_read_block(client, command, data->mfr_model, buf+1); + data->mfr_model[buf+1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + /* Read mfr_revsion */ + command = 0x9b; + status = ym2651y_read_block(client, command, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)-1); + data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init ym2651y_init(void) +{ + return i2c_add_driver(&ym2651y_driver); +} + +static void __exit ym2651y_exit(void) +{ + i2c_del_driver(&ym2651y_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); +MODULE_LICENSE("GPL"); + +module_init(ym2651y_init); +module_exit(ym2651y_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/service/as5812-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/service/as5812-platform-monitor.service new file mode 100755 index 000000000000..91c9adb01ccb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/service/as5812-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS5812-54X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +Type=simple +ExecStartPre=/usr/local/bin/accton_as5812_util.py install +ExecStart=/usr/local/bin/accton_as5812_monitor.py +#RemainAfterExit=yes + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/setup.py new file mode 100755 index 000000000000..aa8615fd8a88 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as5812_54x', + version='1.0', + description='Module to initialize Accton AS5812-54X platforms', + + packages=['as5812_54x'], + package_dir={'as5812_54x': 'as5812-54x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/utils/README new file mode 100755 index 000000000000..4ce43d9407d8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5812_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5812-fan-psu-cpld.patch + for as5812's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5812-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5812 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5812-54X.patch" from patch/installer. + - Change setting for AS5812-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5812-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5812-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5812-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5812-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5812_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5812-54X.patch. + It's done by patching onie_installer-accton-AS5812-54X.patch at build-image. + Run "accton_as5812_util.py install" to install drivers. + +To initialize the system, run "accton_as5812_util.py install". +To clean up the drivers & devices, run "accton_as5812_util.py clean". +To dump information of sensors, run "accton_as5812_util.py show". +To dump SFP EEPROM, run "accton_as5812_util.py sff". +To set fan speed, run "accton_as5812_util.py set fan". +To enable/disable SFP emission, run "accton_as5812_util.py set sfp". +To set system LEDs' color, run "accton_as5812_util.py set led" +For more information, run "accton_as5812_util.py --help". + +==================================================================== +Besides applying accton_as5812_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/utils/accton_as5812_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/utils/accton_as5812_monitor.py new file mode 100755 index 000000000000..5e3b368659cc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/utils/accton_as5812_monitor.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 05/08/2019: Roy Lee, changed for as5812-54x. +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example + import signal + from as5812_54x.fanutil import FanUtil + from as5812_54x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as5812_monitor' +DUTY_MAX = 100 + +global log_file +global log_console + +# Make a class we can use to capture stdout and sterr in the log +class accton_as5812_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + + llog = logging.getLogger("["+FUNCTION_NAME+"]") + def __init__(self, log_console, log_file): + """Needs a logger and a logger level.""" + + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + sys_handler.setLevel(logging.WARNING) #only fatal for syslog + self.llog.addHandler(sys_handler) + self.llog.setLevel(logging.DEBUG) + + if log_file: + fh = logging.FileHandler(log_file) + fh.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s') + fh.setFormatter(formatter) + self.llog.addHandler(fh) + + # set up logging to console + if log_console: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) #For debugging + formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s') + console.setFormatter(formatter) + self.llog.addHandler(console) + + def manage_fans(self): + FAN_LEV1_UP_TEMP = 57700 # temperature + FAN_LEV1_DOWN_TEMP = 0 # unused + FAN_LEV1_SPEED_PERC = DUTY_MAX # percentage*/ + + FAN_LEV2_UP_TEMP = 53000 + FAN_LEV2_DOWN_TEMP = 52700 + FAN_LEV2_SPEED_PERC = 80 + + FAN_LEV3_UP_TEMP = 49500 + FAN_LEV3_DOWN_TEMP = 47700 + FAN_LEV3_SPEED_PERC = 65 + + FAN_LEV4_UP_TEMP = 0 # unused + FAN_LEV4_DOWN_TEMP = 42700 + FAN_LEV4_SPEED_PERC = 40 + + + thermal = ThermalUtil() + fan = FanUtil() + + temp1 = thermal.get_thermal_1_val() + if temp1 is None: + return False + + temp2 = thermal.get_thermal_2_val() + if temp2 is None: + return False + + new_temp = (temp1 + temp2) / 2 + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_stat = fan.get_fan_status(x) + if fan_stat is None or fan_stat is False: + self._new_perc = FAN_LEV1_SPEED_PERC + self.llog.error('SET new_perc to %d (FAN fault. fan_num:%d)', self._new_perc, x) + break + else: + self.llog.debug('fan_stat is True (fan_num:%d)', x) + + if fan_stat is not None and fan_stat is not False: + diff = new_temp - self._ori_temp + if diff == 0: + self.llog.debug('RETURN. THERMAL temp not changed. %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + return True + else: + if diff >= 0: + is_up = True + self.llog.debug('THERMAL temp UP %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + else: + is_up = False + self.llog.debug('THERMAL temp DOWN %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + + if is_up is True: + if new_temp >= FAN_LEV1_UP_TEMP: + self._new_perc = FAN_LEV1_SPEED_PERC + elif new_temp >= FAN_LEV2_UP_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + elif new_temp >= FAN_LEV3_UP_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + else: + self._new_perc = FAN_LEV4_SPEED_PERC + self.llog.debug('SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + else: + if new_temp <= FAN_LEV4_DOWN_TEMP: + self._new_perc = FAN_LEV4_SPEED_PERC + elif new_temp <= FAN_LEV3_DOWN_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + elif new_temp <= FAN_LEV2_DOWN_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + else: + self._new_perc = FAN_LEV1_SPEED_PERC + self.llog.debug('SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + + cur_perc = fan.get_fan_duty_cycle(fan.get_idx_fan_start()) + if cur_perc == self._new_perc: + self.llog.debug('RETURN. FAN speed not changed. %d / %d (new_perc / ori_perc)', self._new_perc, cur_perc) + return True + + set_stat = fan.set_fan_duty_cycle(fan.get_idx_fan_start(), self._new_perc) + if set_stat is True: + self.llog.debug('PASS. set_fan_duty_cycle (%d)', self._new_perc) + else: + self.llog.error('FAIL. set_fan_duty_cycle (%d)', self._new_perc) + + self.llog.debug('GET. ori_perc is %d. ori_temp is %d', cur_perc, self._ori_temp) + self._ori_temp = new_temp + self.llog.info('UPDATE. ori_perc to %d. ori_temp to %d', cur_perc, self._ori_temp) + + return True + +def sig_handler(signum, frame): + fan = FanUtil() + logging.critical('Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(fan.get_idx_fan_start(), DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_console = 0 + log_file = "" + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl') + except getopt.GetoptError: + print 'Usage: %s [-d] [-l]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l]' % sys.argv[0] + return 0 + elif opt in ('-d'): + log_console = 1 + elif opt in ('-l'): + log_file = '%s.log' % sys.argv[0] + + signal.signal(signal.SIGINT, sig_handler) + signal.signal(signal.SIGTERM, sig_handler) + monitor = accton_as5812_monitor(log_console, log_file) + + #time.sleep(100) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54x/utils/accton_as5812_util.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/utils/accton_as5812_util.py new file mode 100755 index 000000000000..464c85745f90 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54x/utils/accton_as5812_util.py @@ -0,0 +1,673 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import getopt +import sys +import logging +import re +import time + +PROJECT_NAME = 'as5812_54x' +version = '0.2.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':54} + + +led_prefix ='/sys/devices/platform/as5812_54x_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as5812_54x_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan1_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan2_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan3_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan5_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['61-0048','62-0049', '63-004a'] , + 'psu': ['57-0050','58-0053'], + 'sfp': ['-0050']} +i2c_nodes = { + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +QSFP_START = 48 + +sfp_map = [2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 52, 54, 51, 53, 55] + +port_cpld_path = [ "/sys/bus/i2c/devices/0-0061/" + ,'/sys/bus/i2c/devices/0-0062/'] + +mknod =[ +'echo as5812_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as5812_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as5812_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', + +# PSU-1 +'echo as5812_54x_psu1 0x38 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-57/new_device', +'echo as5812_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-57/new_device', + +# PSU-2 +'echo as5812_54x_psu2 0x3b > /sys/bus/i2c/devices/i2c-58/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-58/new_device', +'echo as5812_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-58/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-61/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-62/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-63/new_device', + +#EERPOM +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +mknod2 =[ +'echo as5812_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as5812_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as5812_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', + +# PSU-1 +'echo as5812_54x_psu1 0x38 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-57/new_device', +'echo as5812_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-57/new_device', + +# PSU-2 +'echo as5812_54x_psu2 0x3b > /sys/bus/i2c/devices/i2c-58/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-58/new_device', +'echo as5812_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-58/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-61/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-62/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-63/new_device', + +#EERPOM +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', +] + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-48 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe optoe', +'modprobe i2c-mux-accton_as5812_54x_cpld', +'modprobe cpr_4011_4mxx', +'modprobe ym2651y', +'modprobe accton_as5812_54x_fan', +'modprobe leds-accton_as5812_54x', +'modprobe accton_as5812_54x_psu'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + #remove parameter if any + rm = kos[-(i+1)] + lst = rm.split(" ") + if len(lst) > 2: + del(lst[2:]) + rm = " ".join(lst) + + #Change to removing commands + rm = rm.replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x70 is exist @ i2c-0 + tmp = "i2cget -y -f 0 0x70" + ret = log_os_system(tmp, 0) + if not ret[0]: + order = 1 + else: + order = 0 + m = "[%s]Detected I2C_BUS_ORDER:%d" % (os.path.basename(__file__), order) + my_log(m) + return order + +def get_i2c_order(): + return i2c_order_check() + +def device_install(): + global FORCE + + order = get_i2c_order() + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + if i < QSFP_START: + status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + else: + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + order = get_i2c_order() + if order == 0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_inserted() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + + +def get_cpld_path(index): + order = get_i2c_order() + if order !=0 : + return port_cpld_path[index].replace("0-", "1-") + else: + return port_cpld_path[index] + +def cpld_path_of_port(port_index): + if port_index < 1 and port_index > DEVICE_NO['sfp']: + return None + if port_index < 25: + return get_cpld_path(0) + else: + return get_cpld_path(1) + +def get_path_sfp_tx_dis(port_index): + cpld_p = cpld_path_of_port(port_index) + if cpld_p is None: + return False, '' + else: + dev = cpld_p+"module_tx_disable_"+str(port_index) + return True, dev + +def get_path_sfp_presence(port_index): + cpld_p = cpld_path_of_port(port_index) + if cpld_p is None: + return False, '' + else: + dev = cpld_p+"module_present_"+str(port_index) + return True, dev + + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + #if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + #There no tx_disable for QSFP port + if int(args[1]) > QSFP_START or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + port_index = int(args[1]) + ret, dev = get_path_sfp_tx_dis(port_index) + if ret == False: + return False + else: + ret, log = log_os_system("echo "+args[2]+" >"+ dev, 1) + return ret + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def print_1_device_traversal(i, j, k): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + return func+"="+log+" " + else: + return func+"="+"X"+" " + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + if i == 'sfp': + port_index = int(filter(str.isdigit, j)) + for k in (ALL_DEVICE[i][j]): + if k.find('tx_disable')!= -1: + ret, k = get_path_sfp_tx_dis(port_index) + if ret == False: + continue + log = print_1_device_traversal(i, j, k) + print log, + if k.find('present')!= -1: + ret, k = get_path_sfp_presence(port_index) + if ret == False: + continue + log = print_1_device_traversal(i, j, k) + print log, + + else: + for k in (ALL_DEVICE[i][j]): + log = print_1_device_traversal(i, j, k) + print log, + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/fanutil.py new file mode 100644 index 000000000000..c741ebfd7246 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/fanutil.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 5/27/2019: Brandon_Chuang create +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 5 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/3-0063/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/3-0063/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + + def set_fan_duty_cycle(self, val): + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/thermalutil.py new file mode 100644 index 000000000000..1dc97cfe276d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/thermalutil.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 6/11/2019: Brandon_Chuang create +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_MAX = 4 + THERMAL_NUM_1_IDX = 1 # 1_ON_CPU_BROAD. LM75 + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 + THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75 + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + #_thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['18', '4b'], + THERMAL_NUM_2_IDX: ['19', '4c'], + THERMAL_NUM_3_IDX: ['20', '49'], + THERMAL_NUM_4_IDX: ['21', '4a'], + } + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon3/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/19-004c/hwmon/hwmon4/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/20-0049/hwmon/hwmon5/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/21-004a/hwmon/hwmon6/temp1_input"], + } + + #def __init__(self): + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + if(os.path.isfile(device_path)): + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + return int(content) + + else: + print "No such device_path=%s"%device_path + return 0 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_to_device_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + def get_thermal_1_val(self): + return self._get_thermal_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_val(self.THERMAL_NUM_2_IDX) + + def get_thermal_3_val(self): + return self._get_thermal_val(self.THERMAL_NUM_3_IDX) + + def get_thermal_temp(self): + return (self._get_thermal_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_val(self.THERMAL_NUM_3_IDX)) + +def main(): + thermal = ThermalUtil() + print "termal1=%d" %thermal._get_thermal_val(1) + print "termal2=%d" %thermal._get_thermal_val(2) + print "termal3=%d" %thermal._get_thermal_val(3) + print "termal4=%d" %thermal._get_thermal_val(4) +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/Makefile new file mode 100644 index 000000000000..887ac3189cec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as5835_54t_cpld.o accton_as5835_54t_psu.o \ + accton_as5835_54t_fan.o accton_as5835_54t_leds.o \ + ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_cpld.c new file mode 100755 index 000000000000..9765fd430432 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_cpld.c @@ -0,0 +1,607 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as5835_54t CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954t.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954t.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as5835_54t_cpld1, + as5835_54t_cpld2, + as5835_54t_cpld3 +}; + +struct as5835_54t_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as5835_54t_cpld_id[] = { + { "as5835_54t_cpld1", as5835_54t_cpld1 }, + { "as5835_54t_cpld2", as5835_54t_cpld2 }, + { "as5835_54t_cpld3", as5835_54t_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as5835_54t_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_LPMODE_ATTR_ID(index) MODULE_LPMODE_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as5835_54t_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_LPMODE_ATTR_ID(49), + TRANSCEIVER_LPMODE_ATTR_ID(50), + TRANSCEIVER_LPMODE_ATTR_ID(51), + TRANSCEIVER_LPMODE_ATTR_ID(52), + TRANSCEIVER_LPMODE_ATTR_ID(53), + TRANSCEIVER_LPMODE_ATTR_ID(54), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_control(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as5835_54t_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5835_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_lpmode_##index, S_IRUGO | S_IWUSR, show_status, set_control, MODULE_LPMODE_##index); \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR, show_status, set_control, MODULE_RESET_##index) +#define DECLARE_QSFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_lpmode_##index.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); + +static struct attribute *as5835_54t_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5835_54t_cpld1_group = { + .attrs = as5835_54t_cpld1_attributes, +}; + +static struct attribute *as5835_54t_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + NULL +}; + +static const struct attribute_group as5835_54t_cpld2_group = { + .attrs = as5835_54t_cpld2_attributes, +}; + +static struct attribute *as5835_54t_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_QSFP_TRANSCEIVER_ATTR(49), + DECLARE_QSFP_TRANSCEIVER_ATTR(50), + DECLARE_QSFP_TRANSCEIVER_ATTR(51), + DECLARE_QSFP_TRANSCEIVER_ATTR(52), + DECLARE_QSFP_TRANSCEIVER_ATTR(53), + DECLARE_QSFP_TRANSCEIVER_ATTR(54), + NULL +}; + +static const struct attribute_group as5835_54t_cpld3_group = { + .attrs = as5835_54t_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[5] = {0}; + u8 regs_cpld3[] = {0x14}; + u8 *regs[] = {NULL, NULL, regs_cpld3}; + u8 size[] = {0, 0, ARRAY_SIZE(regs_cpld3)}; + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < size[data->type]; i++) { + status = as5835_54t_cpld_read_internal(client, regs[data->type][i]); + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values in order */ + values[0] &= 0x3F; + return sprintf(buf, "%.2x\n", values[0]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, invert = 0; + + switch (attr->index) { + case MODULE_PRESENT_49 ... MODULE_PRESENT_54: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_PRESENT_49); + break; + case MODULE_LPMODE_49 ... MODULE_LPMODE_54: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + break; + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_49); + invert = 1; + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_49 && attr->index <= MODULE_PRESENT_54) { + invert = 1; + } + + mutex_lock(&data->update_lock); + status = as5835_54t_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", invert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_control(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_cpld_data *data = i2c_get_clientdata(client); + long value; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &value); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_LPMODE_49 ... MODULE_LPMODE_54: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + break; + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_49); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5835_54t_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable/lpmode/reset status */ + if (attr->index >= MODULE_RESET_49 && attr->index <= MODULE_RESET_54) { + value = !value; + } + if (value) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5835_54t_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as5835_54t_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as5835_54t_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as5835_54t_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as5835_54t_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as5835_54t_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as5835_54t_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as5835_54t_cpld1: + group = &as5835_54t_cpld1_group; + break; + case as5835_54t_cpld2: + group = &as5835_54t_cpld2_group; + break; + case as5835_54t_cpld3: + group = &as5835_54t_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as5835_54t_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as5835_54t_cpld_remove(struct i2c_client *client) +{ + struct as5835_54t_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as5835_54t_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as5835_54t_cpld1: + group = &as5835_54t_cpld1_group; + break; + case as5835_54t_cpld2: + group = &as5835_54t_cpld2_group; + break; + case as5835_54t_cpld3: + group = &as5835_54t_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as5835_54t_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as5835_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5835_54t_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5835_54t_cpld_read); + +int as5835_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5835_54t_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5835_54t_cpld_write); + +static struct i2c_driver as5835_54t_cpld_driver = { + .driver = { + .name = "as5835_54t_cpld", + .owner = THIS_MODULE, + }, + .probe = as5835_54t_cpld_probe, + .remove = as5835_54t_cpld_remove, + .id_table = as5835_54t_cpld_id, +}; + +static int __init as5835_54t_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as5835_54t_cpld_driver); +} + +static void __exit as5835_54t_cpld_exit(void) +{ + i2c_del_driver(&as5835_54t_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as5835_54t_cpld_init); +module_exit(as5835_54t_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_fan.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_fan.c new file mode 100644 index 000000000000..ea6fdb8296c9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_fan.c @@ -0,0 +1,484 @@ +/* + * A hwmon driver for the Accton as5835 54t fan + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as5835_54t_fan" +#define MAX_FAN_SPEED_RPM 21500 + +static struct as5835_54t_fan_data *as5835_54t_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +extern int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5835_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x02, /* fan 1-5 present status */ + 0x03, /* fan 1-5 direction(0:F2B 1:B2F) */ + 0x04, /* front fan 1-5 fault status */ + 0x05, /* rear fan 1-5 fault status */ + 0x06, /* fan PWM(for all fan) */ + 0x07, /* front fan 1 speed(rpm) */ + 0x08, /* front fan 2 speed(rpm) */ + 0x09, /* front fan 3 speed(rpm) */ + 0x0A, /* front fan 4 speed(rpm) */ + 0x0B, /* front fan 5 speed(rpm) */ + 0x0C, /* rear fan 1 speed(rpm) */ + 0x0D, /* rear fan 2 speed(rpm) */ + 0x0E, /* rear fan 3 speed(rpm) */ + 0x0F, /* rear fan 4 speed(rpm) */ + 0x10, /* rear fan 5 speed(rpm) */ +}; + +/* fan data */ +struct as5835_54t_fan_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_FRONT_FAULT_REG, + FAN_REAR_FAULT_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN_MAX_RPM, + CPLD_VERSION +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(fan_max_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN_MAX_RPM); +#define DECLARE_FAN_MAX_RPM_ATTR(index) &sensor_dev_attr_fan_max_speed_rpm.dev_attr.attr + + +/* 5 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1, 11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2, 12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3, 13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4, 14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5, 15); +/* 5 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1, 11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2, 12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3, 13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4, 14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5, 15); +/* 5 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +/* 5 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); + +static struct attribute *as5835_54t_fan_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1, 11), + DECLARE_FAN_FAULT_ATTR(2, 12), + DECLARE_FAN_FAULT_ATTR(3, 13), + DECLARE_FAN_FAULT_ATTR(4, 14), + DECLARE_FAN_FAULT_ATTR(5, 15), + DECLARE_FAN_SPEED_RPM_ATTR(1, 11), + DECLARE_FAN_SPEED_RPM_ATTR(2, 12), + DECLARE_FAN_SPEED_RPM_ATTR(3, 13), + DECLARE_FAN_SPEED_RPM_ATTR(4, 14), + DECLARE_FAN_SPEED_RPM_ATTR(5, 15), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_MAX_RPM_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0x1F +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150 + +static int as5835_54t_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as5835_54t_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + return (reg_val & FAN_DUTY_CYCLE_REG_MASK) * 5; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle > FAN_MAX_DUTY_CYCLE) { + duty_cycle = FAN_MAX_DUTY_CYCLE; + } + + return (duty_cycle / 5); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + return !!(reg_val & BIT(id)); /* 0: Front to Back, 1: Back to Front*/ +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + return !(reg_val & BIT(id)); +} + +static u8 is_fan_fault(struct as5835_54t_fan_data *data, enum fan_id id) +{ + if ((data->reg_val[FAN_FRONT_FAULT_REG] & BIT(id)) || + (data->reg_val[FAN_REAR_FAULT_REG] & BIT(id))) { + return 1; + } + + return 0; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) { + return error; + } + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) { + return -EINVAL; + } + + as5835_54t_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5835_54t_fan_data *data = as5835_54t_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + case FAN_MAX_RPM: + ret = sprintf(buf, "%d\n", MAX_FAN_SPEED_RPM); + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as5835_54t_fan_group = { + .attrs = as5835_54t_fan_attributes, +}; + +static struct as5835_54t_fan_data *as5835_54t_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as5835_54t_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as5835_54t_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +static int as5835_54t_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5835_54t_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5835_54t_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5835_54t_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5835_54t_fan", + NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5835_54t_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5835_54t_fan_remove(struct i2c_client *client) +{ + struct as5835_54t_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5835_54t_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static const struct i2c_device_id as5835_54t_fan_id[] = { + { "as5835_54t_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5835_54t_fan_id); + +static struct i2c_driver as5835_54t_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as5835_54t_fan_probe, + .remove = as5835_54t_fan_remove, + .id_table = as5835_54t_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as5835_54t_fan_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as5835_54t_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_leds.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_leds.c new file mode 100644 index 000000000000..e02930a2f6e0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_leds.c @@ -0,0 +1,380 @@ +/* + * A LED driver for the accton_as5822_54t_led + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as5835_54t_led" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +extern int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5835_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +struct accton_as5835_54t_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[2]; /* Register value, 0 = RELEASE/DIAG LED, + 1 = FAN/PSU LED, + 2 ~ 4 = SYSTEM LED */ +}; + +static struct accton_as5835_54t_led_data *ledctl = NULL; + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x0C) +#define LED_MODE_DIAG_GREEN_VALUE (0x08) +#define LED_MODE_DIAG_AMBER_VALUE (0x04) +#define LED_MODE_DIAG_OFF_VALUE (0x0C) +#define LED_MODE_DIAG_AMBER_VALUE1 (0x00) + +#define LED_TYPE_LOC_REG_MASK (0x30) +#define LED_MODE_LOC_AMBER_BLINK_VALUE (0x20) +#define LED_MODE_LOC_OFF_VALUE (0x10) +#define LED_MODE_LOC_AMBER_VALUE (0x00) + +static const u8 led_reg[] = { + 0xA, /* LOC/DIAG/FAN LED */ + 0xB, /* PSU LED */ +}; + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +/* FAN/PSU/DIAG/RELEASE led mode */ +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER, + LED_MODE_AMBER_BLINK, + LED_MODE_RED, + LED_MODE_RED_BLINK, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int type_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINK_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_VALUE}, +{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE}, +{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE}, +{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE}, +{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE1}, +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) { + continue; + } + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_value) { + return led_type_mode_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + int type_mask, mode_value; + + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + type_mask = led_type_mode_data[i].type_mask; + mode_value = led_type_mode_data[i].mode_value; + reg_val = (reg_val & ~type_mask) | mode_value; + } + + return reg_val; +} + +static int accton_as5835_54t_led_read_value(u8 reg) +{ + return as5835_54t_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int accton_as5835_54t_led_write_value(u8 reg, u8 value) +{ + return as5835_54t_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void accton_as5835_54t_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as5835_54t_led update\n"); + ledctl->valid = 0; + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as5835_54t_led_read_value(led_reg[i]); + + if (status < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + ledctl->reg_val[i] = status; + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5835_54t_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + reg_val = accton_as5835_54t_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as5835_54t_led_write_value(reg, reg_val); + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7312_54t_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7312_54t_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static void accton_as5835_54t_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5835_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_as5835_54t_led_diag_get(struct led_classdev *cdev) +{ + accton_as5835_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static enum led_brightness accton_as5835_54t_led_loc_get(struct led_classdev *cdev) +{ + accton_as5835_54t_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as5835_54t_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5835_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static struct led_classdev accton_as5835_54t_leds[] = { + [LED_TYPE_LOC] = { + .name = "as5835_54t_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as5835_54t_led_loc_set, + .brightness_get = accton_as5835_54t_led_loc_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_DIAG] = { + .name = "as5835_54t_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as5835_54t_led_diag_set, + .brightness_get = accton_as5835_54t_led_diag_get, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU1] = { + .name = "as5835_54t_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7312_54t_led_auto_set, + .brightness_get = accton_as7312_54t_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as5835_54t_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7312_54t_led_auto_set, + .brightness_get = accton_as7312_54t_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "as5835_54t_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7312_54t_led_auto_set, + .brightness_get = accton_as7312_54t_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as5835_54t_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as5835_54t_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as5835_54t_leds[i]); + + if (ret < 0) { + break; + } + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as5835_54t_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as5835_54t_leds[i]); + } + } + + return ret; +} + +static int accton_as5835_54t_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as5835_54t_leds); i++) { + led_classdev_unregister(&accton_as5835_54t_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as5835_54t_led_driver = { + .probe = accton_as5835_54t_led_probe, + .remove = accton_as5835_54t_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5835_54t_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5835_54t_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as5835_54t_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + goto exit_driver; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + goto exit_free; + } + + return 0; + +exit_free: + kfree(ledctl); +exit_driver: + platform_driver_unregister(&accton_as5835_54t_led_driver); +exit: + return ret; +} + +static void __exit accton_as5835_54t_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as5835_54t_led_driver); + kfree(ledctl); +} + +late_initcall(accton_as5835_54t_led_init); +module_exit(accton_as5835_54t_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5835_54t_led driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_psu.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_psu.c new file mode 100644 index 000000000000..78f0b4298a58 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_psu.c @@ -0,0 +1,343 @@ +/* + * An hwmon driver for accton as5835_54t Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define MODEL_NAME_LEN 8 +#define MODEL_NAME_REG_OFFSET 0x20 + +#define SERIAL_NUM_LEN 18 +#define SERIAL_NUM_REG_OFFSET 0x35 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +extern int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5835_54t_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MODEL_NAME_LEN+1]; /* Model name, read from eeprom */ + char serial[SERIAL_NUM_LEN+1]; /* Serial number, read from eeprom*/ +}; + +static struct as5835_54t_psu_data *as5835_54t_psu_update_device(struct device *dev); + +enum as5835_54t_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_numer, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + +static struct attribute *as5835_54t_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_numer.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5835_54t_psu_data *data = as5835_54t_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5835_54t_psu_data *data = as5835_54t_psu_update_device(dev); + char *str = NULL; + + if (!data->valid) { + return 0; + } + + if (attr->index == PSU_MODEL_NAME) { + str = data->model_name; + } + else { /* PSU_SERIAL_NUBMER */ + str = data->serial; + } + + return sprintf(buf, "%s\n", str); +} + +static const struct attribute_group as5835_54t_psu_group = { + .attrs = as5835_54t_psu_attributes, +}; + +static int as5835_54t_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5835_54t_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5835_54t_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5835_54t_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5835_54t_psu", + NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5835_54t_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5835_54t_psu_remove(struct i2c_client *client) +{ + struct as5835_54t_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5835_54t_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as5835_54t_psu1, + as5835_54t_psu2 +}; + +static const struct i2c_device_id as5835_54t_psu_id[] = { + { "as5835_54t_psu1", as5835_54t_psu1 }, + { "as5835_54t_psu2", as5835_54t_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5835_54t_psu_id); + +static struct i2c_driver as5835_54t_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5835_54t_psu", + }, + .probe = as5835_54t_psu_probe, + .remove = as5835_54t_psu_remove, + .id_table = as5835_54t_psu_id, + .address_list = normal_i2c, +}; + +static int as5835_54t_psu_read_byte(struct i2c_client *client, u8 command, u8 *data) +{ + int status = 0; + int retry_count = 5; + + while (retry_count) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(10); + retry_count--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + +abort: + return status; +} + +static int as5835_54t_psu_read_bytes(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int ret = 0; + + while (data_len) { + ssize_t status; + + status = as5835_54t_psu_read_byte(client, command, data); + if (status <= 0) { + ret = status; + break; + } + + data += 1; + command += 1; + data_len -= 1; + } + + return ret; +} + +static struct as5835_54t_psu_data *as5835_54t_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54t_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + + dev_dbg(&client->dev, "Starting as5835_54t update\n"); + data->valid = 0; + + /* Read psu status */ + status = as5835_54t_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial, 0, sizeof(data->serial)); + + if (IS_PRESENT(data->index, data->status)) { + /* Read model name */ + status = as5835_54t_psu_read_bytes(client, MODEL_NAME_REG_OFFSET, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + goto exit; + } + + /* Read serial number */ + status = as5835_54t_psu_read_bytes(client, SERIAL_NUM_REG_OFFSET, data->serial, + ARRAY_SIZE(data->serial)-1); + if (status < 0) { + data->serial[0] = '\0'; + dev_dbg(&client->dev, "unable to read serial number from (0x%x)\n", client->addr); + goto exit; + } + else { + data->serial[SERIAL_NUM_LEN] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as5835_54t_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as5835_54t_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-fan.service new file mode 100644 index 000000000000..19ad3e519471 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS5835-54T Platform Monitoring FAN service +Before=pmon.service +After=as5835-54t-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as5835_54t_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-psu.service new file mode 100644 index 000000000000..f30b13b6bc3b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS5835-54T Platform Monitoring PSU service +Before=pmon.service +After=as5835-54t-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as5835_54t_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor.service new file mode 100644 index 000000000000..9789201034c0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description=Accton AS5835-54T Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as5835_54t_util.py install +ExecStart=/usr/local/bin/accton_as5835_54t_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/setup.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/setup.py new file mode 100644 index 000000000000..ac880c41e4e0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as5835_54t', + version='1.0', + description='Module to initialize Accton AS5835-54T platforms', + + packages=['as5835_54t'], + package_dir={'as5835_54t': 'as5835-54t/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/README b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/README new file mode 100644 index 000000000000..dc9b838f9f1b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/README @@ -0,0 +1,74 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + module - Contains source code of as5835 kernel driver modules. + util - operational scripts. + +Sonic creates a docker container and run building process under it. +If user tries to built new drivers, please get into that docker and +dpkg-buildpackage for them. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5835-54T has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers can be built to individual ko during dpkg-buildpackage. +2. A operational script, accton_as5835_54t_util.py, for device initializatian. + Run "accton_as5835_54t_util.py install" to install drivers. + +To initialize the system, run "accton_as5835_54t_util.py install". +To clean up the drivers & devices, run "accton_as5835_54t_util.py clean". +To dump information of sensors, run "accton_as5835_54t_util.py show". +To dump SFP EEPROM, run "accton_as5835_54t_util.py sff". +To set fan speed, run "accton_as5835_54t_util.py set fan". +To enable/disable SFP emission, run "accton_as5835_54t_util.py set sfp". +To set system LEDs' color, run "accton_as5835_54t_util.py set led" +For more information, run "accton_as5835_54t_util.py --help". + +==================================================================== +Besides applying accton_as5835_54t_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => green blinking + 3 => amber + 4 => amber blinking + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 4 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor.py new file mode 100755 index 000000000000..ceea8e12f852 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 05/08/2019: Roy Lee, changed for as5812-54x. +# 05/29/2019: Brandon Chuang, changed for as5835-54x. +# 06/11/2019: Brandon Chuang, changed for as5835-54t. +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from as5835_54t.fanutil import FanUtil + from as5835_54t.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as5835_54t_monitor' +DUTY_MAX = 100 + +global log_file +global log_level + +# Make a class we can use to capture stdout and sterr in the log +class accton_as5835_54t_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + FAN_LEV1_UP_TEMP = 57700 # temperature + FAN_LEV1_DOWN_TEMP = 0 # unused + FAN_LEV1_SPEED_PERC = DUTY_MAX # percentage*/ + + FAN_LEV2_UP_TEMP = 53000 + FAN_LEV2_DOWN_TEMP = 52700 + FAN_LEV2_SPEED_PERC = 80 + + FAN_LEV3_UP_TEMP = 49500 + FAN_LEV3_DOWN_TEMP = 47700 + FAN_LEV3_SPEED_PERC = 65 + + FAN_LEV4_UP_TEMP = 0 # unused + FAN_LEV4_DOWN_TEMP = 42700 + FAN_LEV4_SPEED_PERC = 40 + + + thermal = ThermalUtil() + fan = FanUtil() + + temp2 = thermal.get_thermal_2_val() + if temp2 is None: + return False + + temp3 = thermal.get_thermal_3_val() + if temp3 is None: + return False + + new_temp = (temp2 + temp3) / 2 + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_stat = fan.get_fan_status(x) + if fan_stat is None: + return False + if fan_stat is False: + self._new_perc = FAN_LEV1_SPEED_PERC + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', self._new_perc, x) + break + logging.debug('INFO. fan_stat is True (fan_num:%d)', x) + + if fan_stat is not None and fan_stat is not False: + diff = new_temp - self._ori_temp + if diff == 0: + logging.debug('INFO. RETURN. THERMAL temp not changed. %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + return True + else: + if diff >= 0: + is_up = True + logging.debug('INFO. THERMAL temp UP %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + else: + is_up = False + logging.debug('INFO. THERMAL temp DOWN %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + + if is_up is True: + if new_temp >= FAN_LEV1_UP_TEMP: + self._new_perc = FAN_LEV1_SPEED_PERC + elif new_temp >= FAN_LEV2_UP_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + elif new_temp >= FAN_LEV3_UP_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + else: + self._new_perc = FAN_LEV4_SPEED_PERC + logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + else: + if new_temp <= FAN_LEV4_DOWN_TEMP: + self._new_perc = FAN_LEV4_SPEED_PERC + elif new_temp <= FAN_LEV3_DOWN_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + elif new_temp <= FAN_LEV2_DOWN_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + else: + self._new_perc = FAN_LEV1_SPEED_PERC + logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + + cur_perc = fan.get_fan_duty_cycle() + if cur_perc == self._new_perc: + logging.debug('INFO. RETURN. FAN speed not changed. %d / %d (new_perc / ori_perc)', self._new_perc, cur_perc) + return True + + set_stat = fan.set_fan_duty_cycle(self._new_perc) + if set_stat is True: + logging.debug('INFO: PASS. set_fan_duty_cycle (%d)', self._new_perc) + else: + logging.debug('INFO: FAIL. set_fan_duty_cycle (%d)', self._new_perc) + + logging.debug('INFO: GET. ori_perc is %d. ori_temp is %d', cur_perc, self._ori_temp) + self._ori_temp = new_temp + logging.debug('INFO: UPDATE. ori_perc to %d. ori_temp to %d', cur_perc, self._ori_temp) + + return True + +def handler(signum, frame): + fan = FanUtil() + logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) + monitor = accton_as5835_54t_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_fan.py new file mode 100755 index 000000000000..7978012b0da0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_fan.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 5/27/2019: Brandon_Chuang create +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example + +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as5835_54t_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + #/sys/bus/i2c/devices/3-0063 + #fan1_present, fan5_present + + def __init__(self, log_file, log_level): + + self.fan_num = 5 + self.fan_path = "/sys/bus/i2c/devices/3-0063/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + 4: "fan5_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + 4: "fan5_fault", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_psu.py new file mode 100755 index 000000000000..9be72fda9993 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_psu.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as5835_54t_monitor_psu' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +psu_state=[2, 2] +psu_power_status=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "11-0050", + 1: "12-0053", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + + global psu_state + global psu_power_status + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=PSU_STATE_INSERT: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_power_status[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=PSU_STATE_REMOVE: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_NO_POWER + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + #logging.info("content=%s, psu_power_status[%d]=%d", content, idx, psu_power_status[idx]); + if content == "0": + if psu_power_status[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d fault is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_NO_POWER + else: + if psu_power_status[idx] !=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_util.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_util.py new file mode 100755 index 000000000000..48e49cbaba13 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_util.py @@ -0,0 +1,579 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + + + + +PROJECT_NAME = 'as5835_54t' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':5,'thermal':4, 'psu':2, 'sfp':6} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 49-54 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[Debug]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_as5835_54t_cpld' , +'modprobe ym2651y' , +'modprobe accton_as5835_54t_fan' , +'modprobe optoe' , +'modprobe accton_as5835_54t_leds' , +'modprobe accton_as5835_54t_psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + lst = rm.split(" ") + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['3-0063'] , + 'thermal': ['18-004b','19-004c', '20-0049', '21-004a'] , + 'psu': ['11-0050','12-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_', 'module_tx_disable_']} + +sfp_map = [28,29,26,30,31,27] + +qsfp_start = 48 + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', + +'echo as5835_54t_fan 0x63 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-19/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-21/new_device', +'echo as5835_54t_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5835_54t_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as5835_54t_cpld1 0x60 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54t_cpld2 0x61 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54t_cpld3 0x62 > /sys/bus/i2c/devices/i2c-3/new_device'] + +mknod2 =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as5835_54t_fan 0x63 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-19/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-21/new_device', +'echo as5835_54t_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5835_54t_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as5835_54t_cpld1 0x60 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54t_cpld2 0x61 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54t_cpld3 0x62 > /sys/bus/i2c/devices/i2c-3/new_device'] + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x77 is exist @ i2c-1 + tmp = "echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x77 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x77 is not exist @i2c-1, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + time.sleep(0.01) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(49, 55): #Set qsfp port to normal state + log_os_system("echo 0 > /sys/bus/i2c/devices/3-0062/module_reset_" + str(i), 1) + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + path = "/sys/bus/i2c/devices/{0}-0050/port_name" + status, output =log_os_system("echo port{0} > ".format(i+49)+path.format(sfp_map[i]), 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0077", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~5 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/classes/fanutil.py new file mode 100644 index 000000000000..c741ebfd7246 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/classes/fanutil.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 5/27/2019: Brandon_Chuang create +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 5 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/3-0063/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/3-0063/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + + def set_fan_duty_cycle(self, val): + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/classes/thermalutil.py new file mode 100644 index 000000000000..ce903db35487 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/classes/thermalutil.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 5/27/2019: Brandon_Chuang create +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_MAX = 4 + THERMAL_NUM_1_IDX = 1 # 1_ON_CPU_BROAD. LM75 + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 + THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75 + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + #_thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['18', '4b'], + THERMAL_NUM_2_IDX: ['19', '4c'], + THERMAL_NUM_3_IDX: ['20', '49'], + THERMAL_NUM_4_IDX: ['21', '4a'], + } + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon3/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/19-004c/hwmon/hwmon4/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/20-0049/hwmon/hwmon5/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/21-004a/hwmon/hwmon6/temp1_input"], + } + + #def __init__(self): + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + if(os.path.isfile(device_path)): + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + return int(content) + + else: + print "No such device_path=%s"%device_path + return 0 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_to_device_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + def get_thermal_1_val(self): + return self._get_thermal_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_val(self.THERMAL_NUM_2_IDX) + + def get_thermal_3_val(self): + return self._get_thermal_val(self.THERMAL_NUM_3_IDX) + + def get_thermal_temp(self): + return (self._get_thermal_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_val(self.THERMAL_NUM_3_IDX)) + +def main(): + thermal = ThermalUtil() + print "termal1=%d" %thermal._get_thermal_val(1) + print "termal2=%d" %thermal._get_thermal_val(2) + print "termal3=%d" %thermal._get_thermal_val(3) + print "termal4=%d" %thermal._get_thermal_val(4) +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/Makefile new file mode 100644 index 000000000000..ec29de5fe791 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as5835_54x_cpld.o accton_as5835_54x_psu.o \ + accton_as5835_54x_fan.o accton_as5835_54x_leds.o \ + ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_cpld.c new file mode 100755 index 000000000000..97b7d879f03a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_cpld.c @@ -0,0 +1,1200 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as5835_54x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as5835_54x_cpld1, + as5835_54x_cpld2, + as5835_54x_cpld3 +}; + +struct as5835_54x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as5835_54x_cpld_id[] = { + { "as5835_54x_cpld1", as5835_54x_cpld1 }, + { "as5835_54x_cpld2", as5835_54x_cpld2 }, + { "as5835_54x_cpld3", as5835_54x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as5835_54x_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_LPMODE_ATTR_ID(index) MODULE_LPMODE_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as5835_54x_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), + TRANSCEIVER_LPMODE_ATTR_ID(49), + TRANSCEIVER_LPMODE_ATTR_ID(50), + TRANSCEIVER_LPMODE_ATTR_ID(51), + TRANSCEIVER_LPMODE_ATTR_ID(52), + TRANSCEIVER_LPMODE_ATTR_ID(53), + TRANSCEIVER_LPMODE_ATTR_ID(54), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_control(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as5835_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5835_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_control, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +#define DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_lpmode_##index, S_IRUGO | S_IWUSR, show_status, set_control, MODULE_LPMODE_##index); \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR, show_status, set_control, MODULE_RESET_##index) +#define DECLARE_QSFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_lpmode_##index.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); + +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); + +static struct attribute *as5835_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5835_54x_cpld1_group = { + .attrs = as5835_54x_cpld1_attributes, +}; + +static struct attribute *as5835_54x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + NULL +}; + +static const struct attribute_group as5835_54x_cpld2_group = { + .attrs = as5835_54x_cpld2_attributes, +}; + +static struct attribute *as5835_54x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + DECLARE_QSFP_TRANSCEIVER_ATTR(49), + DECLARE_QSFP_TRANSCEIVER_ATTR(50), + DECLARE_QSFP_TRANSCEIVER_ATTR(51), + DECLARE_QSFP_TRANSCEIVER_ATTR(52), + DECLARE_QSFP_TRANSCEIVER_ATTR(53), + DECLARE_QSFP_TRANSCEIVER_ATTR(54), + NULL +}; + +static const struct attribute_group as5835_54x_cpld3_group = { + .attrs = as5835_54x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[5] = {0}; + u8 regs_cpld2[] = {0x8, 0x9, 0xA, 0xB, 0xC}; + u8 regs_cpld3[] = {0x6, 0x7, 0x14}; + u8 *regs[] = {NULL, regs_cpld2, regs_cpld3}; + u8 size[] = {0, ARRAY_SIZE(regs_cpld2), ARRAY_SIZE(regs_cpld3)}; + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < size[data->type]; i++) { + status = as5835_54x_cpld_read_internal(client, regs[data->type][i]); + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values in order */ + if (data->type == as5835_54x_cpld2) { + values[4] &= 0x3F; + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3], values[4]); + } + else { /* as5835_54x_cpld3 */ + values[1] &= 0x3; + values[1] |= (values[2] & 0x3F) << 2; /* Shift port49-54 to bit2-7 */ + return sprintf(buf, "%.2x %.2x\n", values[0], values[1]); + } + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[5] = {0}; + u8 regs_cpld2[] = {0x17, 0x18, 0x19, 0x1A, 0x1B}; + u8 regs_cpld3[] = {0xF, 0x10}; + u8 *regs[] = {NULL, regs_cpld2, regs_cpld3}; + u8 size[] = {0, ARRAY_SIZE(regs_cpld2), ARRAY_SIZE(regs_cpld3)}; + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < size[data->type]; i++) { + status = as5835_54x_cpld_read_internal(client, regs[data->type][i]); + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values in order */ + if (data->type == as5835_54x_cpld2) { + values[4] &= 0x3F; + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3], values[4]); + } + else { /* as5835_54x_cpld3 */ + values[1] &= 0x3; + return sprintf(buf, "%.2x %.2x\n", values[0], values[1]); + } + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, invert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_38: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_PRESENT_33); + break; + case MODULE_PRESENT_39 ... MODULE_PRESENT_46: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_39); + break; + case MODULE_PRESENT_47 ... MODULE_PRESENT_48: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_47); + break; + case MODULE_PRESENT_49 ... MODULE_PRESENT_54: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_PRESENT_49); + break; + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_8: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXFAULT_1); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_16: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXFAULT_9); + break; + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_24: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXFAULT_17); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_32: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_38: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXFAULT_33); + break; + case MODULE_TXFAULT_39 ... MODULE_TXFAULT_46: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_39); + break; + case MODULE_TXFAULT_47 ... MODULE_TXFAULT_48: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_47); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_38: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_39 ... MODULE_TXDISABLE_46: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_39); + break; + case MODULE_TXDISABLE_47 ... MODULE_TXDISABLE_48: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_47); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_8: + reg = 0x17; + mask = 0x1 << (attr->index - MODULE_RXLOS_1); + break; + case MODULE_RXLOS_9 ... MODULE_RXLOS_16: + reg = 0x18; + mask = 0x1 << (attr->index - MODULE_RXLOS_9); + break; + case MODULE_RXLOS_17 ... MODULE_RXLOS_24: + reg = 0x19; + mask = 0x1 << (attr->index - MODULE_RXLOS_17); + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_32: + reg = 0x1A; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_RXLOS_33 ... MODULE_RXLOS_38: + reg = 0x1B; + mask = 0x1 << (attr->index - MODULE_RXLOS_33); + break; + case MODULE_RXLOS_39 ... MODULE_RXLOS_46: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_39); + break; + case MODULE_RXLOS_47 ... MODULE_RXLOS_48: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_47); + break; + case MODULE_LPMODE_49 ... MODULE_LPMODE_54: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + break; + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_49); + invert = 1; + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_54) { + invert = 1; + } + + mutex_lock(&data->update_lock); + status = as5835_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", invert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_control(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54x_cpld_data *data = i2c_get_clientdata(client); + long value; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &value); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_38: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_39 ... MODULE_TXDISABLE_46: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_39); + break; + case MODULE_TXDISABLE_47 ... MODULE_TXDISABLE_48: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_47); + break; + case MODULE_LPMODE_49 ... MODULE_LPMODE_54: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + break; + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_49); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5835_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable/lpmode/reset status */ + if (attr->index >= MODULE_RESET_49 && attr->index <= MODULE_RESET_54) { + value = !value; + } + if (value) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5835_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54x_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as5835_54x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as5835_54x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as5835_54x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as5835_54x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as5835_54x_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as5835_54x_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as5835_54x_cpld1: + group = &as5835_54x_cpld1_group; + break; + case as5835_54x_cpld2: + group = &as5835_54x_cpld2_group; + break; + case as5835_54x_cpld3: + group = &as5835_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as5835_54x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as5835_54x_cpld_remove(struct i2c_client *client) +{ + struct as5835_54x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as5835_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as5835_54x_cpld1: + group = &as5835_54x_cpld1_group; + break; + case as5835_54x_cpld2: + group = &as5835_54x_cpld2_group; + break; + case as5835_54x_cpld3: + group = &as5835_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as5835_54x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as5835_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as5835_54x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5835_54x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5835_54x_cpld_read); + +int as5835_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as5835_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5835_54x_cpld_write); + +static struct i2c_driver as5835_54x_cpld_driver = { + .driver = { + .name = "as5835_54x_cpld", + .owner = THIS_MODULE, + }, + .probe = as5835_54x_cpld_probe, + .remove = as5835_54x_cpld_remove, + .id_table = as5835_54x_cpld_id, +}; + +static int __init as5835_54x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as5835_54x_cpld_driver); +} + +static void __exit as5835_54x_cpld_exit(void) +{ + i2c_del_driver(&as5835_54x_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as5835_54x_cpld_init); +module_exit(as5835_54x_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_fan.c new file mode 100644 index 000000000000..45b8d0d9840f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_fan.c @@ -0,0 +1,484 @@ +/* + * A hwmon driver for the Accton as5835 54x fan + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as5835_54x_fan" +#define MAX_FAN_SPEED_RPM 21500 + +static struct as5835_54x_fan_data *as5835_54x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +extern int as5835_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5835_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x02, /* fan 1-5 present status */ + 0x03, /* fan 1-5 direction(0:F2B 1:B2F) */ + 0x04, /* front fan 1-5 fault status */ + 0x05, /* rear fan 1-5 fault status */ + 0x06, /* fan PWM(for all fan) */ + 0x07, /* front fan 1 speed(rpm) */ + 0x08, /* front fan 2 speed(rpm) */ + 0x09, /* front fan 3 speed(rpm) */ + 0x0A, /* front fan 4 speed(rpm) */ + 0x0B, /* front fan 5 speed(rpm) */ + 0x0C, /* rear fan 1 speed(rpm) */ + 0x0D, /* rear fan 2 speed(rpm) */ + 0x0E, /* rear fan 3 speed(rpm) */ + 0x0F, /* rear fan 4 speed(rpm) */ + 0x10, /* rear fan 5 speed(rpm) */ +}; + +/* fan data */ +struct as5835_54x_fan_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_FRONT_FAULT_REG, + FAN_REAR_FAULT_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN_MAX_RPM, + CPLD_VERSION +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(fan_max_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN_MAX_RPM); +#define DECLARE_FAN_MAX_RPM_ATTR(index) &sensor_dev_attr_fan_max_speed_rpm.dev_attr.attr + + +/* 5 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1, 11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2, 12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3, 13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4, 14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5, 15); +/* 5 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1, 11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2, 12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3, 13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4, 14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5, 15); +/* 5 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +/* 5 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); + +static struct attribute *as5835_54x_fan_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1, 11), + DECLARE_FAN_FAULT_ATTR(2, 12), + DECLARE_FAN_FAULT_ATTR(3, 13), + DECLARE_FAN_FAULT_ATTR(4, 14), + DECLARE_FAN_FAULT_ATTR(5, 15), + DECLARE_FAN_SPEED_RPM_ATTR(1, 11), + DECLARE_FAN_SPEED_RPM_ATTR(2, 12), + DECLARE_FAN_SPEED_RPM_ATTR(3, 13), + DECLARE_FAN_SPEED_RPM_ATTR(4, 14), + DECLARE_FAN_SPEED_RPM_ATTR(5, 15), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_MAX_RPM_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0x1F +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150 + +static int as5835_54x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as5835_54x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + return (reg_val & FAN_DUTY_CYCLE_REG_MASK) * 5; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle > FAN_MAX_DUTY_CYCLE) { + duty_cycle = FAN_MAX_DUTY_CYCLE; + } + + return (duty_cycle / 5); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + return !!(reg_val & BIT(id)); /* 0: Front to Back, 1: Back to Front*/ +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + return !(reg_val & BIT(id)); +} + +static u8 is_fan_fault(struct as5835_54x_fan_data *data, enum fan_id id) +{ + if ((data->reg_val[FAN_FRONT_FAULT_REG] & BIT(id)) || + (data->reg_val[FAN_REAR_FAULT_REG] & BIT(id))) { + return 1; + } + + return 0; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) { + return error; + } + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) { + return -EINVAL; + } + + as5835_54x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5835_54x_fan_data *data = as5835_54x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + case FAN_MAX_RPM: + ret = sprintf(buf, "%d\n", MAX_FAN_SPEED_RPM); + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as5835_54x_fan_group = { + .attrs = as5835_54x_fan_attributes, +}; + +static struct as5835_54x_fan_data *as5835_54x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as5835_54x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as5835_54x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +static int as5835_54x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5835_54x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5835_54x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5835_54x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5835_54x_fan", + NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5835_54x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5835_54x_fan_remove(struct i2c_client *client) +{ + struct as5835_54x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5835_54x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static const struct i2c_device_id as5835_54x_fan_id[] = { + { "as5835_54x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5835_54x_fan_id); + +static struct i2c_driver as5835_54x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as5835_54x_fan_probe, + .remove = as5835_54x_fan_remove, + .id_table = as5835_54x_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as5835_54x_fan_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as5835_54x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_leds.c new file mode 100644 index 000000000000..3b9dce6a4cdf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_leds.c @@ -0,0 +1,380 @@ +/* + * A LED driver for the accton_as5822_54x_led + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as5835_54x_led" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +extern int as5835_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5835_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +struct accton_as5835_54x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[2]; /* Register value, 0 = RELEASE/DIAG LED, + 1 = FAN/PSU LED, + 2 ~ 4 = SYSTEM LED */ +}; + +static struct accton_as5835_54x_led_data *ledctl = NULL; + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x0C) +#define LED_MODE_DIAG_GREEN_VALUE (0x08) +#define LED_MODE_DIAG_AMBER_VALUE (0x04) +#define LED_MODE_DIAG_OFF_VALUE (0x0C) +#define LED_MODE_DIAG_AMBER_VALUE1 (0x00) + +#define LED_TYPE_LOC_REG_MASK (0x30) +#define LED_MODE_LOC_AMBER_BLINK_VALUE (0x20) +#define LED_MODE_LOC_OFF_VALUE (0x10) +#define LED_MODE_LOC_AMBER_VALUE (0x00) + +static const u8 led_reg[] = { + 0xA, /* LOC/DIAG/FAN LED */ + 0xB, /* PSU LED */ +}; + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +/* FAN/PSU/DIAG/RELEASE led mode */ +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER, + LED_MODE_AMBER_BLINK, + LED_MODE_RED, + LED_MODE_RED_BLINK, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int type_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINK_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_VALUE}, +{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE}, +{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE}, +{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE}, +{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE1}, +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) { + continue; + } + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_value) { + return led_type_mode_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + int type_mask, mode_value; + + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + type_mask = led_type_mode_data[i].type_mask; + mode_value = led_type_mode_data[i].mode_value; + reg_val = (reg_val & ~type_mask) | mode_value; + } + + return reg_val; +} + +static int accton_as5835_54x_led_read_value(u8 reg) +{ + return as5835_54x_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int accton_as5835_54x_led_write_value(u8 reg, u8 value) +{ + return as5835_54x_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void accton_as5835_54x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as5835_54x_led update\n"); + ledctl->valid = 0; + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as5835_54x_led_read_value(led_reg[i]); + + if (status < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + ledctl->reg_val[i] = status; + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as5835_54x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + reg_val = accton_as5835_54x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as5835_54x_led_write_value(reg, reg_val); + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7312_54x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7312_54x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static void accton_as5835_54x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5835_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_as5835_54x_led_diag_get(struct led_classdev *cdev) +{ + accton_as5835_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static enum led_brightness accton_as5835_54x_led_loc_get(struct led_classdev *cdev) +{ + accton_as5835_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as5835_54x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as5835_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static struct led_classdev accton_as5835_54x_leds[] = { + [LED_TYPE_LOC] = { + .name = "as5835_54x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as5835_54x_led_loc_set, + .brightness_get = accton_as5835_54x_led_loc_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_DIAG] = { + .name = "as5835_54x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as5835_54x_led_diag_set, + .brightness_get = accton_as5835_54x_led_diag_get, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU1] = { + .name = "as5835_54x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as5835_54x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "as5835_54x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as5835_54x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as5835_54x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as5835_54x_leds[i]); + + if (ret < 0) { + break; + } + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as5835_54x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as5835_54x_leds[i]); + } + } + + return ret; +} + +static int accton_as5835_54x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as5835_54x_leds); i++) { + led_classdev_unregister(&accton_as5835_54x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as5835_54x_led_driver = { + .probe = accton_as5835_54x_led_probe, + .remove = accton_as5835_54x_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as5835_54x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as5835_54x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as5835_54x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + goto exit_driver; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + goto exit_free; + } + + return 0; + +exit_free: + kfree(ledctl); +exit_driver: + platform_driver_unregister(&accton_as5835_54x_led_driver); +exit: + return ret; +} + +static void __exit accton_as5835_54x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as5835_54x_led_driver); + kfree(ledctl); +} + +late_initcall(accton_as5835_54x_led_init); +module_exit(accton_as5835_54x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as5835_54x_led driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_psu.c new file mode 100644 index 000000000000..00b43829e32f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/accton_as5835_54x_psu.c @@ -0,0 +1,343 @@ +/* + * An hwmon driver for accton as5835_54x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define MODEL_NAME_LEN 8 +#define MODEL_NAME_REG_OFFSET 0x20 + +#define SERIAL_NUM_LEN 18 +#define SERIAL_NUM_REG_OFFSET 0x35 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +extern int as5835_54x_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as5835_54x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MODEL_NAME_LEN+1]; /* Model name, read from eeprom */ + char serial[SERIAL_NUM_LEN+1]; /* Serial number, read from eeprom*/ +}; + +static struct as5835_54x_psu_data *as5835_54x_psu_update_device(struct device *dev); + +enum as5835_54x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_numer, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + +static struct attribute *as5835_54x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_numer.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5835_54x_psu_data *data = as5835_54x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as5835_54x_psu_data *data = as5835_54x_psu_update_device(dev); + char *str = NULL; + + if (!data->valid) { + return 0; + } + + if (attr->index == PSU_MODEL_NAME) { + str = data->model_name; + } + else { /* PSU_SERIAL_NUBMER */ + str = data->serial; + } + + return sprintf(buf, "%s\n", str); +} + +static const struct attribute_group as5835_54x_psu_group = { + .attrs = as5835_54x_psu_attributes, +}; + +static int as5835_54x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as5835_54x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as5835_54x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5835_54x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5835_54x_psu", + NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as5835_54x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as5835_54x_psu_remove(struct i2c_client *client) +{ + struct as5835_54x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as5835_54x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as5835_54x_psu1, + as5835_54x_psu2 +}; + +static const struct i2c_device_id as5835_54x_psu_id[] = { + { "as5835_54x_psu1", as5835_54x_psu1 }, + { "as5835_54x_psu2", as5835_54x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as5835_54x_psu_id); + +static struct i2c_driver as5835_54x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as5835_54x_psu", + }, + .probe = as5835_54x_psu_probe, + .remove = as5835_54x_psu_remove, + .id_table = as5835_54x_psu_id, + .address_list = normal_i2c, +}; + +static int as5835_54x_psu_read_byte(struct i2c_client *client, u8 command, u8 *data) +{ + int status = 0; + int retry_count = 5; + + while (retry_count) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(10); + retry_count--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + +abort: + return status; +} + +static int as5835_54x_psu_read_bytes(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int ret = 0; + + while (data_len) { + ssize_t status; + + status = as5835_54x_psu_read_byte(client, command, data); + if (status <= 0) { + ret = status; + break; + } + + data += 1; + command += 1; + data_len -= 1; + } + + return ret; +} + +static struct as5835_54x_psu_data *as5835_54x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as5835_54x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + + dev_dbg(&client->dev, "Starting as5835_54x update\n"); + data->valid = 0; + + /* Read psu status */ + status = as5835_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial, 0, sizeof(data->serial)); + + if (IS_PRESENT(data->index, data->status)) { + /* Read model name */ + status = as5835_54x_psu_read_bytes(client, MODEL_NAME_REG_OFFSET, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + goto exit; + } + + /* Read serial number */ + status = as5835_54x_psu_read_bytes(client, SERIAL_NUM_REG_OFFSET, data->serial, + ARRAY_SIZE(data->serial)-1); + if (status < 0) { + data->serial[0] = '\0'; + dev_dbg(&client->dev, "unable to read serial number from (0x%x)\n", client->addr); + goto exit; + } + else { + data->serial[SERIAL_NUM_LEN] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as5835_54x_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as5835_54x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/service/as5835-54x-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/service/as5835-54x-platform-monitor-fan.service new file mode 100644 index 000000000000..3d7df4e48a6c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/service/as5835-54x-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS5835-54X Platform Monitoring FAN service +Before=pmon.service +After=as5835-54x-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as5835_54x_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/service/as5835-54x-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/service/as5835-54x-platform-monitor-psu.service new file mode 100644 index 000000000000..2a9279cc4aea --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/service/as5835-54x-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS5835-54X Platform Monitoring PSU service +Before=pmon.service +After=as5835-54x-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as5835_54x_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/service/as5835-54x-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/service/as5835-54x-platform-monitor.service new file mode 100644 index 000000000000..d522a0ca5377 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/service/as5835-54x-platform-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description=Accton AS5835-54X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as5835_54x_util.py install +ExecStart=/usr/local/bin/accton_as5835_54x_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/setup.py new file mode 100644 index 000000000000..af0320318ea6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as5835_54x', + version='1.0', + description='Module to initialize Accton AS5835-54X platforms', + + packages=['as5835_54x'], + package_dir={'as5835_54x': 'as5835-54x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/README new file mode 100644 index 000000000000..f75f8e008c79 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/README @@ -0,0 +1,74 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + module - Contains source code of as7326 kernel driver modules. + util - operational scripts. + +Sonic creates a docker container and run building process under it. +If user tries to built new drivers, please get into that docker and +dpkg-buildpackage for them. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5835-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers can be built to individual ko during dpkg-buildpackage. +2. A operational script, accton_as7326_util.py, for device initializatian. + Run "accton_as5835_54x_util.py install" to install drivers. + +To initialize the system, run "accton_as5835_54x_util.py install". +To clean up the drivers & devices, run "accton_as5835_54x_util.py clean". +To dump information of sensors, run "accton_as5835_54x_util.py show". +To dump SFP EEPROM, run "accton_as5835_54x_util.py sff". +To set fan speed, run "accton_as5835_54x_util.py set fan". +To enable/disable SFP emission, run "accton_as5835_54x_util.py set sfp". +To set system LEDs' color, run "accton_as5835_54x_util.py set led" +For more information, run "accton_as5835_54x_util.py --help". + +==================================================================== +Besides applying accton_as7326_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => green blinking + 3 => amber + 4 => amber blinking + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 4 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_monitor.py new file mode 100755 index 000000000000..9c5e955ce17d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_monitor.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 05/08/2019: Roy Lee, changed for as5812-54x. +# 05/29/2019: Brandon Chuang, changed for as5835-54x. +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from as5835_54x.fanutil import FanUtil + from as5835_54x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as5835_54x_monitor' +DUTY_MAX = 100 + +global log_file +global log_level + +# Make a class we can use to capture stdout and sterr in the log +class accton_as5835_54x_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + FAN_LEV1_UP_TEMP = 57700 # temperature + FAN_LEV1_DOWN_TEMP = 0 # unused + FAN_LEV1_SPEED_PERC = DUTY_MAX # percentage*/ + + FAN_LEV2_UP_TEMP = 53000 + FAN_LEV2_DOWN_TEMP = 52700 + FAN_LEV2_SPEED_PERC = 80 + + FAN_LEV3_UP_TEMP = 49500 + FAN_LEV3_DOWN_TEMP = 47700 + FAN_LEV3_SPEED_PERC = 65 + + FAN_LEV4_UP_TEMP = 0 # unused + FAN_LEV4_DOWN_TEMP = 42700 + FAN_LEV4_SPEED_PERC = 40 + + + thermal = ThermalUtil() + fan = FanUtil() + + temp2 = thermal.get_thermal_2_val() + if temp2 is None: + return False + + temp3 = thermal.get_thermal_3_val() + if temp3 is None: + return False + + new_temp = (temp2 + temp3) / 2 + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_stat = fan.get_fan_status(x) + if fan_stat is None: + return False + if fan_stat is False: + self._new_perc = FAN_LEV1_SPEED_PERC + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', self._new_perc, x) + break + logging.debug('INFO. fan_stat is True (fan_num:%d)', x) + + if fan_stat is not None and fan_stat is not False: + diff = new_temp - self._ori_temp + if diff == 0: + logging.debug('INFO. RETURN. THERMAL temp not changed. %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + return True + else: + if diff >= 0: + is_up = True + logging.debug('INFO. THERMAL temp UP %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + else: + is_up = False + logging.debug('INFO. THERMAL temp DOWN %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp) + + if is_up is True: + if new_temp >= FAN_LEV1_UP_TEMP: + self._new_perc = FAN_LEV1_SPEED_PERC + elif new_temp >= FAN_LEV2_UP_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + elif new_temp >= FAN_LEV3_UP_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + else: + self._new_perc = FAN_LEV4_SPEED_PERC + logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + else: + if new_temp <= FAN_LEV4_DOWN_TEMP: + self._new_perc = FAN_LEV4_SPEED_PERC + elif new_temp <= FAN_LEV3_DOWN_TEMP: + self._new_perc = FAN_LEV3_SPEED_PERC + elif new_temp <= FAN_LEV2_DOWN_TEMP: + self._new_perc = FAN_LEV2_SPEED_PERC + else: + self._new_perc = FAN_LEV1_SPEED_PERC + logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp) + + cur_perc = fan.get_fan_duty_cycle() + if cur_perc == self._new_perc: + logging.debug('INFO. RETURN. FAN speed not changed. %d / %d (new_perc / ori_perc)', self._new_perc, cur_perc) + return True + + set_stat = fan.set_fan_duty_cycle(self._new_perc) + if set_stat is True: + logging.debug('INFO: PASS. set_fan_duty_cycle (%d)', self._new_perc) + else: + logging.debug('INFO: FAIL. set_fan_duty_cycle (%d)', self._new_perc) + + logging.debug('INFO: GET. ori_perc is %d. ori_temp is %d', cur_perc, self._ori_temp) + self._ori_temp = new_temp + logging.debug('INFO: UPDATE. ori_perc to %d. ori_temp to %d', cur_perc, self._ori_temp) + + return True + +def handler(signum, frame): + fan = FanUtil() + logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) + monitor = accton_as5835_54x_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_monitor_fan.py new file mode 100755 index 000000000000..dec1e036142d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_monitor_fan.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 5/27/2019: Brandon_Chuang create +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example + +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as5835_54x_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + #/sys/bus/i2c/devices/3-0063 + #fan1_present, fan5_present + + def __init__(self, log_file, log_level): + + self.fan_num = 5 + self.fan_path = "/sys/bus/i2c/devices/3-0063/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + 4: "fan5_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + 4: "fan5_fault", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_monitor_psu.py new file mode 100755 index 000000000000..f994d635239a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_monitor_psu.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as5835_54x_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +psu_state=[2, 2] +psu_power_status=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "11-0050", + 1: "12-0053", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + + global psu_state + global psu_power_status + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=PSU_STATE_INSERT: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_power_status[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=PSU_STATE_REMOVE: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_NO_POWER + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + #logging.info("content=%s, psu_power_status[%d]=%d", content, idx, psu_power_status[idx]); + if content == "0": + if psu_power_status[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d fault is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_NO_POWER + else: + if psu_power_status[idx] !=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_util.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_util.py new file mode 100755 index 000000000000..738a1766fbef --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54x/utils/accton_as5835_54x_util.py @@ -0,0 +1,595 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + + + + +PROJECT_NAME = 'as5835_54x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':5,'thermal':4, 'psu':2, 'sfp':54} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-48 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[Debug]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_as5835_54x_cpld' , +'modprobe ym2651y' , +'modprobe accton_as5835_54x_fan' , +'modprobe optoe' , +'modprobe accton_as5835_54x_leds' , +'modprobe accton_as5835_54x_psu' ] + +def driver_install(): + global FORCE + log_os_system("depmod", 1) + for i in range(0,len(kos)): + ret = log_os_system(kos[i], 1) + if ret[0]: + if FORCE == 0: + return ret[0] + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + lst = rm.split(" ") + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + ret = log_os_system(rm, 1) + if ret[0]: + if FORCE == 0: + return ret[0] + return 0 + +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['3-0063'] , + 'thermal': ['18-004b','19-004c', '20-0049', '21-004a'] , + 'psu': ['11-0050','12-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_', 'module_tx_disable_']} + +sfp_map = [42,43,44,45,46,47,48,49,50,51, + 52,53,54,55,56,57,58,59,60,61, + 62,63,64,65,66,67,68,69,70,71, + 72,73,74,75,76,77,78,79,80,81, + 82,83,84,85,86,87,88,89,28,29, + 26,30,31,27] + +qsfp_start = 48 + +#For sideband signals of SFP/QSFP modules. +cpld_of_module = {'3-0061': list(range(0,38)), + '3-0062': list(range(38,54)) } + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-34/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-35/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-36/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-37/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-38/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-39/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', + +'echo as5835_54x_fan 0x63 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-19/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-21/new_device', +'echo as5835_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5835_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as5835_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-3/new_device'] + +mknod2 =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-34/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-35/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-36/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-37/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-38/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-39/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as5835_54x_fan 0x63 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-19/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-21/new_device', +'echo as5835_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as5835_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as5835_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as5835_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-3/new_device'] + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x77 is exist @ i2c-1 + tmp = "i2cget -y -f 0 0x77" + ret = log_os_system(tmp, 0) + if not ret[0]: + order = 1 + else: + order = 0 + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x77 is not exist @i2c-1, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + time.sleep(0.01) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(49, 55): #Set qsfp port to normal state + log_os_system("echo 0 > /sys/bus/i2c/devices/3-0062/module_reset_" + str(i), 1) + + for i in range(0,len(sfp_map)): + if i < qsfp_start: + status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + else: + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + order = i2c_order_check() + if order: + nodelist = mknod2 + else: + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + for lk in cpld_of_module: + if k in cpld_of_module[lk]: + node = key+str(k+1) + path = i2c_prefix + lk + "/"+ nodes[j] + str(k+1) + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if log : + hex_cmd = 'hexdump' + elif log2 : + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret = log_os_system("echo "+args[1]+" >"+k, 1) + if ret[0]: + return ret[0] + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~5 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret = log_os_system("cat "+ node, 1) + if ret[0] == 0: + print ("Previous fan duty: " + log.strip() +"%") + ret = log_os_system("echo "+args[1]+" >"+node, 1) + if ret[0] == 0: + print ("Current fan duty: " + args[1] +"%") + return ret[0] + elif args[0]=='sfp': + if int(args[1])> qsfp_start or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret[0]: + return ret[0] + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1 = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2 = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1[0] or ret2[0]) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/fanutil.py new file mode 100644 index 000000000000..73d020acccce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/fanutil.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 3/32/2018: Roy Lee modify for as7326_56x +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 5 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + #BASE_VAL_PATH = '/sys/bus/i2c/devices/11-0066/{0}' + #FAN_DUTY_PATH = '/sys/bus/i2c/devices/11-0066/fan_duty_cycle_percentage' + BASE_VAL_PATH = '/sys/devices/platform/as6712_32x_fan/{0}' + FAN_DUTY_PATH = '/sys/devices/platform/as6712_32x_fan/fan1_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/thermalutil.py new file mode 100644 index 000000000000..8fdb01ecc564 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/classes/thermalutil.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 3/23/2018: Roy Lee modify for as7326_56x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['38', '48'], + THERMAL_NUM_2_IDX: ['39', '49'], + THERMAL_NUM_3_IDX: ['40', '4a'], + } + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/Makefile new file mode 100644 index 000000000000..d052ddaf04e6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/Makefile @@ -0,0 +1,2 @@ +obj-m:= accton_as6712_32x_psu.o accton-as6712-32x-cpld.o \ + accton_as6712_32x_fan.o cpr_4011_4mxx.o leds-accton_as6712_32x.o diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton-as6712-32x-cpld.c b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton-as6712-32x-cpld.c new file mode 100755 index 000000000000..0c86cb94711c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton-as6712-32x-cpld.c @@ -0,0 +1,867 @@ +/* + * I2C multiplexer + * + * Copyright (C) 2014 Accton Technology Corporation. + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as6712_32x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define NUM_OF_CPLD1_CHANS 0x0 +#define NUM_OF_CPLD2_CHANS 0x10 +#define NUM_OF_CPLD3_CHANS 0x10 +#define CPLD_CHANNEL_SELECT_REG 0x2 +#define CPLD_DESELECT_CHANNEL 0xFF + +#define ACCTON_I2C_CPLD_MUX_MAX_NCHANS NUM_OF_CPLD3_CHANS + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_mux_type { + as6712_32x_cpld2, + as6712_32x_cpld3, + as6712_32x_cpld1 +}; + +struct as6712_32x_cpld_data { + enum cpld_mux_type type; + struct i2c_client *client; + u8 last_chan; /* last register value */ + struct device *hwmon_dev; + struct mutex update_lock; +}; + +struct chip_desc { + u8 nchans; + u8 deselectChan; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [as6712_32x_cpld1] = { + .nchans = NUM_OF_CPLD1_CHANS, + .deselectChan = NUM_OF_CPLD1_CHANS, + }, + [as6712_32x_cpld2] = { + .nchans = NUM_OF_CPLD2_CHANS, + .deselectChan = NUM_OF_CPLD2_CHANS, + }, + [as6712_32x_cpld3] = { + .nchans = NUM_OF_CPLD3_CHANS, + .deselectChan = NUM_OF_CPLD3_CHANS, + } +}; + +static const struct i2c_device_id as6712_32x_cpld_mux_id[] = { + { "as6712_32x_cpld1", as6712_32x_cpld1 }, + { "as6712_32x_cpld2", as6712_32x_cpld2 }, + { "as6712_32x_cpld3", as6712_32x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as6712_32x_cpld_mux_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_LPMODE_ATTR_ID(index) MODULE_LPMODE_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as6712_32x_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + /*Reset*/ + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32), + TRANSCEIVER_LPMODE_ATTR_ID(1), + TRANSCEIVER_LPMODE_ATTR_ID(2), + TRANSCEIVER_LPMODE_ATTR_ID(3), + TRANSCEIVER_LPMODE_ATTR_ID(4), + TRANSCEIVER_LPMODE_ATTR_ID(5), + TRANSCEIVER_LPMODE_ATTR_ID(6), + TRANSCEIVER_LPMODE_ATTR_ID(7), + TRANSCEIVER_LPMODE_ATTR_ID(8), + TRANSCEIVER_LPMODE_ATTR_ID(9), + TRANSCEIVER_LPMODE_ATTR_ID(10), + TRANSCEIVER_LPMODE_ATTR_ID(11), + TRANSCEIVER_LPMODE_ATTR_ID(12), + TRANSCEIVER_LPMODE_ATTR_ID(13), + TRANSCEIVER_LPMODE_ATTR_ID(14), + TRANSCEIVER_LPMODE_ATTR_ID(15), + TRANSCEIVER_LPMODE_ATTR_ID(16), + TRANSCEIVER_LPMODE_ATTR_ID(17), + TRANSCEIVER_LPMODE_ATTR_ID(18), + TRANSCEIVER_LPMODE_ATTR_ID(19), + TRANSCEIVER_LPMODE_ATTR_ID(20), + TRANSCEIVER_LPMODE_ATTR_ID(21), + TRANSCEIVER_LPMODE_ATTR_ID(22), + TRANSCEIVER_LPMODE_ATTR_ID(23), + TRANSCEIVER_LPMODE_ATTR_ID(24), + TRANSCEIVER_LPMODE_ATTR_ID(25), + TRANSCEIVER_LPMODE_ATTR_ID(26), + TRANSCEIVER_LPMODE_ATTR_ID(27), + TRANSCEIVER_LPMODE_ATTR_ID(28), + TRANSCEIVER_LPMODE_ATTR_ID(29), + TRANSCEIVER_LPMODE_ATTR_ID(30), + TRANSCEIVER_LPMODE_ATTR_ID(31), + TRANSCEIVER_LPMODE_ATTR_ID(32), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_status(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as6712_32x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as6712_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index); \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR|S_IRUGO, show_status, set_status, MODULE_RESET_##index); \ + static SENSOR_DEVICE_ATTR(module_lp_mode_##index, S_IRUGO | S_IWUSR, show_status, set_status, MODULE_LPMODE_##index) +#define DECLARE_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_present_##index.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##index.dev_attr.attr, \ + &sensor_dev_attr_module_lp_mode_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); + + +static struct attribute *as6712_32x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as6712_32x_cpld1_group = { + .attrs = as6712_32x_cpld1_attributes, +}; + +static struct attribute *as6712_32x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_ATTR(1), + DECLARE_TRANSCEIVER_ATTR(2), + DECLARE_TRANSCEIVER_ATTR(3), + DECLARE_TRANSCEIVER_ATTR(4), + DECLARE_TRANSCEIVER_ATTR(5), + DECLARE_TRANSCEIVER_ATTR(6), + DECLARE_TRANSCEIVER_ATTR(7), + DECLARE_TRANSCEIVER_ATTR(8), + DECLARE_TRANSCEIVER_ATTR(9), + DECLARE_TRANSCEIVER_ATTR(10), + DECLARE_TRANSCEIVER_ATTR(11), + DECLARE_TRANSCEIVER_ATTR(12), + DECLARE_TRANSCEIVER_ATTR(13), + DECLARE_TRANSCEIVER_ATTR(14), + DECLARE_TRANSCEIVER_ATTR(15), + DECLARE_TRANSCEIVER_ATTR(16), + NULL +}; + +static const struct attribute_group as6712_32x_cpld2_group = { + .attrs = as6712_32x_cpld2_attributes, +}; + +static struct attribute *as6712_32x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_ATTR(17), + DECLARE_TRANSCEIVER_ATTR(18), + DECLARE_TRANSCEIVER_ATTR(19), + DECLARE_TRANSCEIVER_ATTR(20), + DECLARE_TRANSCEIVER_ATTR(21), + DECLARE_TRANSCEIVER_ATTR(22), + DECLARE_TRANSCEIVER_ATTR(23), + DECLARE_TRANSCEIVER_ATTR(24), + DECLARE_TRANSCEIVER_ATTR(25), + DECLARE_TRANSCEIVER_ATTR(26), + DECLARE_TRANSCEIVER_ATTR(27), + DECLARE_TRANSCEIVER_ATTR(28), + DECLARE_TRANSCEIVER_ATTR(29), + DECLARE_TRANSCEIVER_ATTR(30), + DECLARE_TRANSCEIVER_ATTR(31), + DECLARE_TRANSCEIVER_ATTR(32), + NULL +}; + +static const struct attribute_group as6712_32x_cpld3_group = { + .attrs = as6712_32x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[2] = {0}; + u8 regs[] = {0xA, 0xB}; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as6712_32x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 32 in order */ + return sprintf(buf, "%.2x %.2x\n", values[0], values[1]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_status(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + + int status = 0, reverse = 0; + u8 reg = 0, mask = 0; + u32 val, para; + + if (sscanf(buf, "%d", ¶) != 1) { + return -EINVAL; + } + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_32: + reg = 0x4 + (((attr->index - MODULE_RESET_1)/8)%2); + mask = 0x1 << ((attr->index - MODULE_RESET_1)%8); + reverse = 1; + break; + case MODULE_LPMODE_1 ... MODULE_LPMODE_32: + reg = 0xC + (((attr->index - MODULE_LPMODE_1)/8)%2); + mask = 0x1 << ((attr->index - MODULE_LPMODE_1)%8); + break; + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as6712_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + val = status & ~mask; + if (!para && reverse) { /*0 means reset*/ + val |= mask; + } + + status = as6712_32x_cpld_write_internal(client, reg, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_RESET_1 ... MODULE_RESET_32: + reg = 0x4 + (((attr->index - MODULE_RESET_1)/8)%2); + mask = 0x1 << ((attr->index - MODULE_RESET_1)%8); + break; + case MODULE_LPMODE_1 ... MODULE_LPMODE_32: + reg = 0xC + (((attr->index - MODULE_LPMODE_1)/8)%2); + mask = 0x1 << ((attr->index - MODULE_LPMODE_1)%8); + break; + + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as6712_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as6712_32x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int as6712_32x_cpld_mux_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + unsigned long orig_jiffies; + unsigned short flags; + union i2c_smbus_data data; + int try; + s32 res = -EIO; + + data.byte = val; + flags = client->flags; + flags &= I2C_M_TEN | I2C_CLIENT_PEC; + + if (adap->algo->smbus_xfer) { + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (res = 0, try = 0; try <= adap->retries; try++) { + res = adap->algo->smbus_xfer(adap, client->addr, flags, + I2C_SMBUS_WRITE, CPLD_CHANNEL_SELECT_REG, + I2C_SMBUS_BYTE_DATA, &data); + if (res != -EAGAIN) + break; + if (time_after(jiffies, + orig_jiffies + adap->timeout)) + break; + } + } + + return res; +} + +static int as6712_32x_cpld_mux_select_chan(struct i2c_mux_core *muxc, + u32 chan) +{ + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + u8 regval; + int ret = 0; + regval = chan; + + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + ret = as6712_32x_cpld_mux_reg_write(muxc->parent, client, regval); + data->last_chan = regval; + } + + return ret; +} + +static int as6712_32x_cpld_mux_deselect_mux(struct i2c_mux_core *muxc, + u32 chan) +{ + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + /* Deselect active channel */ + data->last_chan = chips[data->type].deselectChan; + + return as6712_32x_cpld_mux_reg_write(muxc->parent, client, data->last_chan); +} + +static void as6712_32x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as6712_32x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as6712_32x_cpld_mux_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + int force, class; + struct i2c_mux_core *muxc; + struct as6712_32x_cpld_data *data; + int chan = 0; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + muxc = i2c_mux_alloc(adap, &client->dev, + chips[id->driver_data].nchans, + sizeof(*data), 0, + as6712_32x_cpld_mux_select_chan, + as6712_32x_cpld_mux_deselect_mux); + if (!muxc) + return -ENOMEM; + + i2c_set_clientdata(client, muxc); + data = i2c_mux_priv(muxc); + data->client = client; + mutex_init(&data->update_lock); + + if (data->type == as6712_32x_cpld2 || data->type == as6712_32x_cpld3) { + data->type = id->driver_data; + data->last_chan = chips[data->type].deselectChan; /* force the first selection */ + + /* Now create an adapter for each channel */ + for (chan = 0; chan < chips[data->type].nchans; chan++) { + force = 0; /* dynamic adap number */ + class = 0; /* no class by default */ + + ret = i2c_mux_add_adapter(muxc, force, chan, class); + + if (ret) { + ret = -ENODEV; + dev_err(&client->dev, "failed to register multiplexed adapter %d\n", chan); + goto exit_mux_register; + } + } + + dev_info(&client->dev, "registered %d multiplexed busses for I2C mux %s\n", + chan, client->name); + } + + /* Register sysfs hooks */ + switch (data->type) { + case as6712_32x_cpld1: + group = &as6712_32x_cpld1_group; + break; + case as6712_32x_cpld2: + group = &as6712_32x_cpld2_group; + break; + case as6712_32x_cpld3: + group = &as6712_32x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_mux_register; + } + } + + if (chips[data->type].nchans) { + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s\n", + chan, client->name); + } + else { + dev_info(&client->dev, + "device %s registered\n", client->name); + } + + as6712_32x_cpld_add_client(client); + + return 0; + +exit_mux_register: + i2c_mux_del_adapters(muxc); + kfree(data); + return ret; +} + +static int as6712_32x_cpld_mux_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct as6712_32x_cpld_data *data = i2c_mux_priv(muxc); + const struct attribute_group *group = NULL; + + as6712_32x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as6712_32x_cpld1: + group = &as6712_32x_cpld1_group; + break; + case as6712_32x_cpld2: + group = &as6712_32x_cpld2_group; + break; + case as6712_32x_cpld3: + group = &as6712_32x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + i2c_mux_del_adapters(muxc); + + return 0; +} + +static int as6712_32x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as6712_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as6712_32x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as6712_32x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as6712_32x_cpld_read); + +int as6712_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as6712_32x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as6712_32x_cpld_write); + +static struct i2c_driver as6712_32x_cpld_mux_driver = { + .driver = { + .name = "as6712_32x_cpld", + .owner = THIS_MODULE, + }, + .probe = as6712_32x_cpld_mux_probe, + .remove = as6712_32x_cpld_mux_remove, + .id_table = as6712_32x_cpld_mux_id, +}; + +static int __init as6712_32x_cpld_mux_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as6712_32x_cpld_mux_driver); +} + +static void __exit as6712_32x_cpld_mux_exit(void) +{ + i2c_del_driver(&as6712_32x_cpld_mux_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton as6712-32x CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as6712_32x_cpld_mux_init); +module_exit(as6712_32x_cpld_mux_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_fan.c new file mode 100644 index 000000000000..7033d8b75687 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_fan.c @@ -0,0 +1,463 @@ +/* + * A hwmon driver for the Accton as6712 32x fan contrl + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as6712_32x_fan" + +#define FAN_MAX_NUMBER 5 +#define FAN_SPEED_CPLD_TO_RPM_STEP 150 +#define FAN_SPEED_PRECENT_TO_CPLD_STEP 5 +#define FAN_DUTY_CYCLE_MIN 0 /* 10% ??*/ +#define FAN_DUTY_CYCLE_MAX 100 /* 100% */ + +#define CPLD_REG_FAN_STATUS_OFFSET 0xC +#define CPLD_REG_FANR_STATUS_OFFSET 0x17 +#define CPLD_REG_FAN_DIRECTION_OFFSET 0x1E + +#define CPLD_FAN1_REG_SPEED_OFFSET 0x10 +#define CPLD_FAN2_REG_SPEED_OFFSET 0x11 +#define CPLD_FAN3_REG_SPEED_OFFSET 0x12 +#define CPLD_FAN4_REG_SPEED_OFFSET 0x13 +#define CPLD_FAN5_REG_SPEED_OFFSET 0x14 + +#define CPLD_FANR1_REG_SPEED_OFFSET 0x18 +#define CPLD_FANR2_REG_SPEED_OFFSET 0x19 +#define CPLD_FANR3_REG_SPEED_OFFSET 0x1A +#define CPLD_FANR4_REG_SPEED_OFFSET 0x1B +#define CPLD_FANR5_REG_SPEED_OFFSET 0x1C + +#define CPLD_REG_FAN_PWM_CYCLE_OFFSET 0xD + +#define CPLD_FAN1_INFO_BIT_MASK 0x1 +#define CPLD_FAN2_INFO_BIT_MASK 0x2 +#define CPLD_FAN3_INFO_BIT_MASK 0x4 +#define CPLD_FAN4_INFO_BIT_MASK 0x8 +#define CPLD_FAN5_INFO_BIT_MASK 0x10 + +#define PROJECT_NAME + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(format, ...) printk(format, __VA_ARGS__) +#else + #define DEBUG_PRINT(format, ...) +#endif + +static struct accton_as6712_32x_fan *fan_data = NULL; + +struct accton_as6712_32x_fan { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[FAN_MAX_NUMBER]; /* inner first fan status */ + u32 speed[FAN_MAX_NUMBER]; /* inner first fan speed */ + u8 direction[FAN_MAX_NUMBER]; /* reconrd the direction of inner first and second fans */ + u32 duty_cycle[FAN_MAX_NUMBER]; /* control the speed of inner first and second fans */ + u8 r_status[FAN_MAX_NUMBER]; /* inner second fan status */ + u32 r_speed[FAN_MAX_NUMBER]; /* inner second fan speed */ +}; + +/*******************/ +#define MAKE_FAN_MASK_OR_REG(name,type) \ + CPLD_FAN##type##1_##name, \ + CPLD_FAN##type##2_##name, \ + CPLD_FAN##type##3_##name, \ + CPLD_FAN##type##4_##name, \ + CPLD_FAN##type##5_##name, + +/* fan related data + */ +static const u8 fan_info_mask[] = { + MAKE_FAN_MASK_OR_REG(INFO_BIT_MASK,) +}; + +static const u8 fan_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,) +}; + +static const u8 fanr_speed_reg[] = { + MAKE_FAN_MASK_OR_REG(REG_SPEED_OFFSET,R) +}; + +/*******************/ +#define DEF_FAN_SET(id) \ + FAN##id##_FAULT, \ + FAN##id##_SPEED, \ + FAN##id##_DUTY_CYCLE, \ + FAN##id##_DIRECTION, \ + FANR##id##_FAULT, \ + FANR##id##_SPEED, + +enum sysfs_fan_attributes { + DEF_FAN_SET(1) + DEF_FAN_SET(2) + DEF_FAN_SET(3) + DEF_FAN_SET(4) + DEF_FAN_SET(5) +}; +/*******************/ +static void accton_as6712_32x_fan_update_device(struct device *dev); +static int accton_as6712_32x_fan_read_value(u8 reg); +static int accton_as6712_32x_fan_write_value(u8 reg, u8 value); + +static ssize_t fan_set_duty_cycle(struct device *dev, + struct device_attribute *da,const char *buf, size_t count); +static ssize_t fan_show_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t show_name(struct device *dev, + struct device_attribute *da, char *buf); + +extern int as6712_32x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as6712_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + + +/*******************/ +#define _MAKE_SENSOR_DEVICE_ATTR(prj, id, id2) \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, \ + fan_set_duty_cycle, FAN##id##_DUTY_CYCLE); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_direction, S_IRUGO, fan_show_value, NULL, FAN##id##_DIRECTION); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_fault, S_IRUGO, fan_show_value, NULL, FANR##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fanr##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_input, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id2##_input, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); \ + static SENSOR_DEVICE_ATTR(prj##fan##id##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); \ + static SENSOR_DEVICE_ATTR(prj##fan##id2##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); + +#define MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) _MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) + +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME ,1 ,11) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME ,2 ,12) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME ,3 ,13) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME ,4 ,14) +MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME ,5 ,15) + +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); +/*******************/ + +#define _MAKE_FAN_ATTR(prj, id, id2) \ + &sensor_dev_attr_##prj##fan##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_duty_cycle_percentage.dev_attr.attr,\ + &sensor_dev_attr_##prj##fan##id##_direction.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fanr##id##_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_input.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id2##_input.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id##_fault.dev_attr.attr, \ + &sensor_dev_attr_##prj##fan##id2##_fault.dev_attr.attr, + + +#define MAKE_FAN_ATTR(prj, id, id2) _MAKE_FAN_ATTR(prj, id, id2) + +static struct attribute *accton_as6712_32x_fan_attributes[] = { + /* fan related attributes */ + MAKE_FAN_ATTR(PROJECT_NAME,1 ,11) + MAKE_FAN_ATTR(PROJECT_NAME,2 ,12) + MAKE_FAN_ATTR(PROJECT_NAME,3 ,13) + MAKE_FAN_ATTR(PROJECT_NAME,4 ,14) + MAKE_FAN_ATTR(PROJECT_NAME,5 ,15) + &sensor_dev_attr_name.dev_attr.attr, + NULL +}; +/*******************/ + +/* fan related functions + */ +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + ssize_t ret = 0; + int data_index, type_index; + + accton_as6712_32x_fan_update_device(dev); + + if (fan_data->valid == 0) { + return ret; + } + + type_index = attr->index%FAN2_FAULT; + data_index = attr->index/FAN2_FAULT; + + switch (type_index) { + case FAN1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->status[data_index]); + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->speed[data_index]); + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DUTY_CYCLE: + ret = sprintf(buf, "%d\n", fan_data->duty_cycle[data_index]); + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FAN1_DIRECTION: + ret = sprintf(buf, "%d\n", fan_data->direction[data_index]); /* presnet, need to modify*/ + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_FAULT: + ret = sprintf(buf, "%d\n", fan_data->r_status[data_index]); + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + case FANR1_SPEED: + ret = sprintf(buf, "%d\n", fan_data->r_speed[data_index]); + DEBUG_PRINT("[Check !!][%s][%d][type->index=%d][data->index=%d]\n", __FUNCTION__, __LINE__, type_index, data_index); + break; + default: + DEBUG_PRINT("[Check !!][%s][%d] \n", __FUNCTION__, __LINE__); + break; + } + + return ret; +} + +static ssize_t show_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf(buf, "%s\n", DRVNAME); +} +/*******************/ +static ssize_t fan_set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < FAN_DUTY_CYCLE_MIN || value > FAN_DUTY_CYCLE_MAX) + return -EINVAL; + + accton_as6712_32x_fan_write_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET, value/FAN_SPEED_PRECENT_TO_CPLD_STEP); + + fan_data->valid = 0; + + return count; +} + +static const struct attribute_group accton_as6712_32x_fan_group = { + .attrs = accton_as6712_32x_fan_attributes, +}; + +static int accton_as6712_32x_fan_read_value(u8 reg) +{ + return as6712_32x_cpld_read(0x60, reg); +} + +static int accton_as6712_32x_fan_write_value(u8 reg, u8 value) +{ + return as6712_32x_cpld_write(0x60, reg, value); +} + +static void accton_as6712_32x_fan_update_device(struct device *dev) +{ + int speed, r_speed, fault, r_fault, direction, ctrl_speed; + int i; + int retry_count; + + mutex_lock(&fan_data->update_lock); + + DEBUG_PRINT("Starting accton_as6712_32x_fan update \n"); + + if (!(time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || !fan_data->valid)) { + /* do nothing */ + goto _exit; + } + + fan_data->valid = 0; + + DEBUG_PRINT("Starting accton_as6712_32x_fan update 2 \n"); + + fault = accton_as6712_32x_fan_read_value(CPLD_REG_FAN_STATUS_OFFSET); + r_fault = accton_as6712_32x_fan_read_value(CPLD_REG_FANR_STATUS_OFFSET); + direction = accton_as6712_32x_fan_read_value(CPLD_REG_FAN_DIRECTION_OFFSET); + ctrl_speed = accton_as6712_32x_fan_read_value(CPLD_REG_FAN_PWM_CYCLE_OFFSET); + + if ( (fault < 0) || (r_fault < 0) || (ctrl_speed < 0) ) + { + DEBUG_PRINT("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + + DEBUG_PRINT("[fan:] fault:%d, r_fault=%d, ctrl_speed=%d \n",fault, r_fault, ctrl_speed); + + for (i = 0; i < FAN_MAX_NUMBER; i++) + { + /* Update fan data + */ + + /* fan fault + * 0: normal, 1:abnormal + * Each FAN-tray module has two fans. + */ + fan_data->status[i] = (fault & fan_info_mask[i]) >> i; + DEBUG_PRINT("[fan%d:] fail=%d \n",i, fan_data->status[i]); + + fan_data->r_status[i] = (r_fault & fan_info_mask[i]) >> i; + fan_data->direction[i] = (direction & fan_info_mask[i]) >> i; + fan_data->duty_cycle[i] = ctrl_speed * FAN_SPEED_PRECENT_TO_CPLD_STEP; + + /* fan speed + */ + speed = 0; + r_speed = 0; + retry_count = 3; + while (retry_count) { + retry_count--; + speed = accton_as6712_32x_fan_read_value(fan_speed_reg[i]); + r_speed = accton_as6712_32x_fan_read_value(fanr_speed_reg[i]); + if ( (speed < 0) || (r_speed < 0) ) + { + DEBUG_PRINT("[Error!!][%s][%d] \n", __FUNCTION__, __LINE__); + goto _exit; /* error */ + } + if ( (speed == 0) || (r_speed == 0) ) + { + msleep(50); + continue; + } + break; + } + + DEBUG_PRINT("[fan%d:] speed:%d, r_speed=%d \n", i, speed, r_speed); + + fan_data->speed[i] = speed * FAN_SPEED_CPLD_TO_RPM_STEP; + fan_data->r_speed[i] = r_speed * FAN_SPEED_CPLD_TO_RPM_STEP; + } + + /* finish to update */ + fan_data->last_updated = jiffies; + fan_data->valid = 1; + +_exit: + mutex_unlock(&fan_data->update_lock); +} + +static int accton_as6712_32x_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &accton_as6712_32x_fan_group); + if (status) { + goto exit; + + } + + fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(fan_data->hwmon_dev)) { + status = PTR_ERR(fan_data->hwmon_dev); + goto exit_remove; + } + + dev_info(&pdev->dev, "accton_as6712_32x_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &accton_as6712_32x_fan_group); +exit: + return status; +} + +static int accton_as6712_32x_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&fan_data->pdev->dev.kobj, &accton_as6712_32x_fan_group); + + return 0; +} + + + +static struct platform_driver accton_as6712_32x_fan_driver = { + .probe = accton_as6712_32x_fan_probe, + .remove = accton_as6712_32x_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as6712_32x_fan_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as6712_32x_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct accton_as6712_32x_fan), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as6712_32x_fan_driver); + goto exit; + } + + mutex_init(&fan_data->update_lock); + fan_data->valid = 0; + + fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fan_data->pdev)) { + ret = PTR_ERR(fan_data->pdev); + platform_driver_unregister(&accton_as6712_32x_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as6712_32x_fan_exit(void) +{ + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&accton_as6712_32x_fan_driver); + kfree(fan_data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as6712_32x_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_as6712_32x_fan_init); +module_exit(accton_as6712_32x_fan_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_psu.c new file mode 100644 index 000000000000..5b9eda261489 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/accton_as6712_32x_psu.c @@ -0,0 +1,364 @@ +/* + * An hwmon driver for accton as6712_32x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as6712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as6712_32x_cpld_read(unsigned short cpld_addr, u8 reg); +static int as6712_32x_psu_model_name_get(struct device *dev); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as6712_32x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[14]; /* Model name, read from eeprom */ +}; + +static struct as6712_32x_psu_data *as6712_32x_psu_update_device(struct device *dev); + +enum as6712_32x_psu_sysfs_attributes { + PSU_INDEX, + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as6712_32x_psu_attributes[] = { + &sensor_dev_attr_psu_index.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as6712_32x_psu_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->index); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as6712_32x_psu_data *data = as6712_32x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as6712_32x_psu_data *data = as6712_32x_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + if (as6712_32x_psu_model_name_get(dev) < 0) { + return -ENXIO; + } + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as6712_32x_psu_group = { + .attrs = as6712_32x_psu_attributes, +}; + +static int as6712_32x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as6712_32x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as6712_32x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as6712_32x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as6712_32x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as6712_32x_psu_remove(struct i2c_client *client) +{ + struct as6712_32x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as6712_32x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as6712_32x_psu1, + as6712_32x_psu2 +}; + +static const struct i2c_device_id as6712_32x_psu_id[] = { + { "as6712_32x_psu1", as6712_32x_psu1 }, + { "as6712_32x_psu2", as6712_32x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as6712_32x_psu_id); + +static struct i2c_driver as6712_32x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as6712_32x_psu", + }, + .probe = as6712_32x_psu_probe, + .remove = as6712_32x_psu_remove, + .id_table = as6712_32x_psu_id, + .address_list = normal_i2c, +}; + +static int as6712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +enum psu_type { + PSU_YM_2401_JCR, /* AC110V - F2B */ + PSU_YM_2401_JDR, /* AC110V - B2F */ + PSU_CPR_4011_4M11, /* AC110V - F2B */ + PSU_CPR_4011_4M21, /* AC110V - B2F */ + PSU_CPR_6011_2M11, /* AC110V - F2B */ + PSU_CPR_6011_2M21, /* AC110V - B2F */ + PSU_UM400D_01G, /* DC48V - F2B */ + PSU_UM400D01_01G /* DC48V - B2F */ +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_YM_2401_JCR, 0x20, 11, "YM-2401JCR"}, +{PSU_YM_2401_JDR, 0x20, 11, "YM-2401JDR"}, +{PSU_CPR_4011_4M11, 0x26, 13, "CPR-4011-4M11"}, +{PSU_CPR_4011_4M21, 0x26, 13, "CPR-4011-4M21"}, +{PSU_CPR_6011_2M11, 0x26, 13, "CPR-6011-2M11"}, +{PSU_CPR_6011_2M21, 0x26, 13, "CPR-6011-2M21"}, +{PSU_UM400D_01G, 0x50, 9, "um400d01G"}, +{PSU_UM400D01_01G, 0x50, 12, "um400d01-01G"}, +}; + +static int as6712_32x_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as6712_32x_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as6712_32x_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR) { + /* Skip the meaningless data byte 8*/ + data->model_name[8] = data->model_name[9]; + data->model_name[9] = data->model_name[10]; + data->model_name[10] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} +static struct as6712_32x_psu_data *as6712_32x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as6712_32x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + + dev_dbg(&client->dev, "Starting as6812_32x update\n"); + data->valid = 0; + + /* Read psu status */ + status = as6712_32x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as6712_32x_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as6712_32x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/cpr_4011_4mxx.c new file mode 100644 index 000000000000..15cef4ef50d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/cpr_4011_4mxx.c @@ -0,0 +1,439 @@ +/* + * An hwmon driver for the CPR-4011-4Mxx Redundant Power Module + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x3c, 0x3d, 0x3e, 0x3f, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct cpr_4011_4mxx_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev); + +enum cpr_4011_4mxx_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_P_IN_UV, + PSU_P_OUT_UV, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); + +/*Duplicate nodes for lm-sensors. 1 for input, 2 for output.*/ +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_linear, NULL, PSU_P_IN_UV); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); + + + + + +static struct attribute *cpr_4011_4mxx_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_fault.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cpr_4011_4mxx_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static const struct attribute_group cpr_4011_4mxx_group = { + .attrs = cpr_4011_4mxx_attributes, +}; + +static int cpr_4011_4mxx_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct cpr_4011_4mxx_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct cpr_4011_4mxx_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpr_4011_4mxx_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int cpr_4011_4mxx_remove(struct i2c_client *client) +{ + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id cpr_4011_4mxx_id[] = { + { "cpr_4011_4mxx", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpr_4011_4mxx_id); + +static struct i2c_driver cpr_4011_4mxx_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cpr_4011_4mxx", + }, + .probe = cpr_4011_4mxx_probe, + .remove = cpr_4011_4mxx_remove, + .id_table = cpr_4011_4mxx_id, + .address_list = normal_i2c, +}; + +static int cpr_4011_4mxx_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cpr_4011_4mxx_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + struct reg_data_byte regs_byte[] = { {0x20, &data->vout_mode}, + {0x81, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {0x96, &data->p_out}, /*p_out must be the first one.*/ + {0x97, &data->p_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &(data->fan_speed[0])}, + {0x91, &(data->fan_speed[1])}}; + + dev_dbg(&client->dev, "Starting cpr_4011_4mxx update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cpr_4011_4mxx_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = cpr_4011_4mxx_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + } + else { + *(regs_word[i].value) = status; + } + + /*Elimated false values. so p_out must be updated at first. */ + if (data->p_out == 0) { + *(regs_word[i].value) = 0; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init cpr_4011_4mxx_init(void) +{ + return i2c_add_driver(&cpr_4011_4mxx_driver); +} + +static void __exit cpr_4011_4mxx_exit(void) +{ + i2c_del_driver(&cpr_4011_4mxx_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("CPR_4011_4MXX driver"); +MODULE_LICENSE("GPL"); + +module_init(cpr_4011_4mxx_init); +module_exit(cpr_4011_4mxx_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/leds-accton_as6712_32x.c b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/leds-accton_as6712_32x.c new file mode 100644 index 000000000000..6e5c1d2118e4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/modules/leds-accton_as6712_32x.c @@ -0,0 +1,611 @@ +/* + * A LED driver for the accton_as6712_32x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include + +extern int as6712_32x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as6712_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as6712_32x_led" + +struct accton_as6712_32x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[4]; /* Register value, 0 = LOC/DIAG/FAN LED + 1 = PSU1/PSU2 LED + 2 = FAN1-4 LED + 3 = FAN5-6 LED */ +}; + +static struct accton_as6712_32x_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_TYPE_PSU1_REG_MASK 0x03 +#define LED_MODE_PSU1_GREEN_MASK 0x02 +#define LED_MODE_PSU1_AMBER_MASK 0x01 +#define LED_MODE_PSU1_OFF_MASK 0x03 +#define LED_MODE_PSU1_AUTO_MASK 0x00 + +#define LED_TYPE_PSU2_REG_MASK 0x0C +#define LED_MODE_PSU2_GREEN_MASK 0x08 +#define LED_MODE_PSU2_AMBER_MASK 0x04 +#define LED_MODE_PSU2_OFF_MASK 0x0C +#define LED_MODE_PSU2_AUTO_MASK 0x00 + +#define LED_TYPE_DIAG_REG_MASK 0x0C +#define LED_MODE_DIAG_GREEN_MASK 0x08 +#define LED_MODE_DIAG_AMBER_MASK 0x04 +#define LED_MODE_DIAG_OFF_MASK 0x0C +#define LED_MODE_DIAG_BLINK_MASK 0x48 + +#define LED_TYPE_FAN_REG_MASK 0x03 +#define LED_MODE_FAN_GREEN_MASK 0x02 +#define LED_MODE_FAN_AMBER_MASK 0x01 +#define LED_MODE_FAN_OFF_MASK 0x03 +#define LED_MODE_FAN_AUTO_MASK 0x00 + +#define LED_TYPE_FAN1_REG_MASK 0x03 +#define LED_TYPE_FAN2_REG_MASK 0xC0 +#define LED_TYPE_FAN3_REG_MASK 0x30 +#define LED_TYPE_FAN4_REG_MASK 0x0C +#define LED_TYPE_FAN5_REG_MASK 0x03 + +#define LED_MODE_FANX_GREEN_MASK 0x01 +#define LED_MODE_FANX_RED_MASK 0x02 +#define LED_MODE_FANX_OFF_MASK 0x00 + +#define LED_TYPE_LOC_REG_MASK 0x30 +#define LED_MODE_LOC_ON_MASK 0x00 +#define LED_MODE_LOC_OFF_MASK 0x10 +#define LED_MODE_LOC_BLINK_MASK 0x20 + +static const u8 led_reg[] = { + 0xA, /* LOC/DIAG/FAN LED*/ + 0xB, /* PSU1/PSU2 LED */ + 0xE, /* FAN2-5 LED */ + 0xF, /* FAN1 LED */ +}; + +enum led_type { + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_DIAG, + LED_TYPE_FAN, + LED_TYPE_FAN1, + LED_TYPE_FAN2, + LED_TYPE_FAN3, + LED_TYPE_FAN4, + LED_TYPE_FAN5, + LED_TYPE_LOC +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_AUTO, +}; + +struct led_type_mode { + enum led_type type; + int type_mask; + enum led_light_mode mode; + int mode_mask; +}; + +struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU1_AUTO_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AUTO, LED_MODE_PSU2_AUTO_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AUTO, LED_MODE_FAN_AUTO_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_GREEN, LED_MODE_DIAG_GREEN_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_AMBER, LED_MODE_DIAG_AMBER_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_OFF, LED_MODE_DIAG_OFF_MASK}, +{LED_TYPE_DIAG, LED_TYPE_DIAG_REG_MASK, LED_MODE_GREEN_BLINK, LED_MODE_DIAG_BLINK_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER, LED_MODE_LOC_ON_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_OFF, LED_MODE_LOC_OFF_MASK}, +{LED_TYPE_LOC, LED_TYPE_LOC_REG_MASK, LED_MODE_AMBER_BLINK, LED_MODE_LOC_BLINK_MASK} +}; + + +struct fanx_info_s { + u8 cname; /* device name */ + enum led_type type; + u8 reg_id; /* map to led_reg & reg_val */ +}; + +static struct fanx_info_s fanx_info[] = { + {'1', LED_TYPE_FAN1, 3}, + {'2', LED_TYPE_FAN2, 2}, + {'3', LED_TYPE_FAN3, 2}, + {'4', LED_TYPE_FAN4, 2}, + {'5', LED_TYPE_FAN5, 2}, +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if (type == LED_TYPE_DIAG) + { /* special case : bit 6 - meaning blinking */ + if (0x40 & reg_val) + return LED_MODE_GREEN_BLINK; + } + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + if (type == LED_TYPE_DIAG) + { + if (mode == LED_MODE_GREEN_BLINK) + { /* special case : bit 6 - meaning blinking */ + reg_val = 0x48 | (reg_val & ~0x4C); + break; + } + else + { /* for diag led, other case must cancel bit 6 first */ + reg_val = reg_val & ~0x40; + } + } + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + break; + } + + return reg_val; +} + +static int accton_as6712_32x_led_read_value(u8 reg) +{ + return as6712_32x_cpld_read(0x60, reg); +} + +static int accton_as6712_32x_led_write_value(u8 reg, u8 value) +{ + return as6712_32x_cpld_write(0x60, reg, value); +} + +static void accton_as6712_32x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as6712_32x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as6712_32x_led_read_value(led_reg[i]); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as6712_32x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + + reg_val = accton_as6712_32x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as6712_32x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as6712_32x_led_psu_1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness accton_as6712_32x_led_psu_1_get(struct led_classdev *cdev) +{ + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void accton_as6712_32x_led_psu_2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness accton_as6712_32x_led_psu_2_get(struct led_classdev *cdev) +{ + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static void accton_as6712_32x_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN); +} + +static enum led_brightness accton_as6712_32x_led_fan_get(struct led_classdev *cdev) +{ + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + + +static void accton_as6712_32x_led_fanx_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (led_cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1); + return; + } + } +} + + +static enum led_brightness accton_as6712_32x_led_fanx_get(struct led_classdev *cdev) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]); + } + } + + + return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[2]); +} + + +static void accton_as6712_32x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness accton_as6712_32x_led_diag_get(struct led_classdev *cdev) +{ + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as6712_32x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as6712_32x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness accton_as6712_32x_led_loc_get(struct led_classdev *cdev) +{ + accton_as6712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static struct led_classdev accton_as6712_32x_leds[] = { + [LED_TYPE_PSU1] = { + .name = "accton_as6712_32x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_psu_1_set, + .brightness_get = accton_as6712_32x_led_psu_1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as6712_32x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_psu_2_set, + .brightness_get = accton_as6712_32x_led_psu_2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "accton_as6712_32x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fan_set, + .brightness_get = accton_as6712_32x_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN1] = { + .name = "accton_as6712_32x_led::fan1", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fanx_set, + .brightness_get = accton_as6712_32x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN2] = { + .name = "accton_as6712_32x_led::fan2", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fanx_set, + .brightness_get = accton_as6712_32x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN3] = { + .name = "accton_as6712_32x_led::fan3", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fanx_set, + .brightness_get = accton_as6712_32x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN4] = { + .name = "accton_as6712_32x_led::fan4", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fanx_set, + .brightness_get = accton_as6712_32x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN5] = { + .name = "accton_as6712_32x_led::fan5", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_fanx_set, + .brightness_get = accton_as6712_32x_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_DIAG] = { + .name = "accton_as6712_32x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_diag_set, + .brightness_get = accton_as6712_32x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_LOC] = { + .name = "accton_as6712_32x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as6712_32x_led_loc_set, + .brightness_get = accton_as6712_32x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as6712_32x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as6712_32x_leds); i++) { + led_classdev_suspend(&accton_as6712_32x_leds[i]); + } + + return 0; +} + +static int accton_as6712_32x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as6712_32x_leds); i++) { + led_classdev_resume(&accton_as6712_32x_leds[i]); + } + + return 0; +} + +static int accton_as6712_32x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as6712_32x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as6712_32x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as6712_32x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as6712_32x_leds[i]); + } + } + + return ret; +} + +static int accton_as6712_32x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as6712_32x_leds); i++) { + led_classdev_unregister(&accton_as6712_32x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as6712_32x_led_driver = { + .probe = accton_as6712_32x_led_probe, + .remove = accton_as6712_32x_led_remove, + .suspend = accton_as6712_32x_led_suspend, + .resume = accton_as6712_32x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as6712_32x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as6712_32x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as6712_32x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as6712_32x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as6712_32x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as6712_32x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as6712_32x_led_driver); + kfree(ledctl); +} + +module_init(accton_as6712_32x_led_init); +module_exit(accton_as6712_32x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as6712_32x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/service/as6712-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/service/as6712-platform-init.service new file mode 100644 index 000000000000..ffdd6e1cee74 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/service/as6712-platform-init.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS6712-32X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as6712_util.py install +ExecStart=/usr/local/bin/accton_as6712_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/setup.py new file mode 100644 index 000000000000..114b0837be69 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as6712_32x', + version='1.0', + description='Module to initialize Accton AS6712-32X platforms', + + packages=['as6712_32x'], + package_dir={'as6712_32x': 'as6712-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/README new file mode 100644 index 000000000000..bfa90e6b68e1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/README @@ -0,0 +1,74 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + module - Contains source code of as6712 kernel driver modules. + util - operational scripts. + +Sonic creates a docker container and run building process under it. +If user tries to built new drivers, please get into that docker and +dpkg-buildpackage for them. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS6712-32X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers can be built to individual ko during dpkg-buildpackage. +2. A operational script, accton_as6712_util.py, for device initializatian. + Run "accton_as6712_util.py install" to install drivers. + +To initialize the system, run "accton_as6712_util.py install". +To clean up the drivers & devices, run "accton_as6712_util.py clean". +To dump information of sensors, run "accton_as6712_util.py show". +To dump SFP EEPROM, run "accton_as6712_util.py sff". +To set fan speed, run "accton_as6712_util.py set fan". +To enable/disable SFP emission, run "accton_as6712_util.py set sfp". +To set system LEDs' color, run "accton_as6712_util.py set led" +For more information, run "accton_as6712_util.py --help". + +==================================================================== +Besides applying accton_as6712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 32 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_monitor.py new file mode 100755 index 000000000000..07e40f6b7fb4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_monitor.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 4/10/2018: Roy Lee modify for as6712_32x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import time # this is only being used as part of the example + from as6712_32x.fanutil import FanUtil + from as6712_32x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as6712_monitor' + +global log_file +global log_level + +# (LM75_1+ LM75_2+ LM75_3) is LM75 at i2c addresses 0x48, 0x49, and 0x4A. +# TMP = (LM75_1+ LM75_2+ LM75_3)/3 +#1. If TMP < 35, All fans run with duty 30%. +#2. If TMP>=35 or the temperature of any one of fan is higher than 40, +# All fans run with duty 50% +#3. If TMP >= 40 or the temperature of any one of fan is higher than 45, +# All fans run with duty 65%. +#4. If TMP >= 45 or the temperature of any one of fan is higher than 50, +# All fans run with duty 100%. +#5. Any one of 5 fans is fault, set duty = 100%. +#6. Direction factor. If it is B2F direction, duty + 10%. + + # MISC: + # 1.Check single LM75 before applied average. + # 2.If no matched fan speed is found from the policy, + # use FAN_DUTY_CYCLE_MIN as default speed + # Get current temperature + # 4.Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature + + + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as6712_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + max_duty = 100 + fan_policy_f2b = { + 0: [30, 0, 105000], + 1: [50, 105000, 120000], + 2: [65, 120000, 135000], + 3: [max_duty, 135000, sys.maxsize], + } + fan_policy_b2f = { + 0: [40, 0, 105000], + 1: [60, 105000, 120000], + 2: [75, 120000, 135000], + 3: [max_duty, 135000, sys.maxsize], + } + fan_policy_single = { + 0: 40000, + 1: 45000, + 2: 50000, + } + + thermal = ThermalUtil() + fan = FanUtil() + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + return False + if fan_status is False: + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + fan.set_fan_duty_cycle(max_duty) + return True + #logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + fan_dir=fan.get_fan_dir(1) + if fan_dir == 0: + fan_policy = fan_policy_f2b + else: + fan_policy = fan_policy_b2f + + #Decide fan duty by if any of sensors > fan_policy_single. + new_duty_cycle = fan_policy[0][0] + for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): + single_thm = thermal._get_thermal_node_val(x) + for y in range(0, len(fan_policy_single)): + if single_thm > fan_policy_single[y]: + if fan_policy[y+1][0] > new_duty_cycle: + new_duty_cycle = fan_policy[y+1][0] + logging.debug('INFO. Single thermal sensor %d with temp %d > %d , new_duty_cycle=%d', + x, single_thm, fan_policy_single[y], new_duty_cycle) + single_result = new_duty_cycle + + + #Find if current duty matched any of define duty. + #If not, set it to highest one. + cur_duty_cycle = fan.get_fan_duty_cycle() + for x in range(0, len(fan_policy)): + if cur_duty_cycle == fan_policy[x][0]: + break + if x == len(fan_policy) : + fan.set_fan_duty_cycle(fan_policy[0][0]) + cur_duty_cycle = max_duty + + #Decide fan duty by if sum of sensors falls into any of fan_policy{} + get_temp = thermal.get_thermal_temp() + new_duty_cycle = cur_duty_cycle + for x in range(0, len(fan_policy)): + y = len(fan_policy) - x -1 #checked from highest + if get_temp > fan_policy[y][1] and get_temp <= fan_policy[y][2] : + new_duty_cycle= fan_policy[y][0] + logging.debug('INFO. Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + + sum_result = new_duty_cycle + if (sum_result>single_result): + new_duty_cycle = sum_result; + else: + new_duty_cycle = single_result + + logging.debug('INFO. Final duty_cycle=%d', new_duty_cycle) + if(new_duty_cycle != cur_duty_cycle): + fan.set_fan_duty_cycle(new_duty_cycle) + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + monitor = accton_as6712_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_util.py b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_util.py new file mode 100755 index 000000000000..10cdac787309 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as6712-32x/utils/accton_as6712_util.py @@ -0,0 +1,636 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Description: +# Due to adoption of optoe drivers, sideband signals of SFPs are moved +# into cpld drivers. Add a new dict, cpld_of_module, for mapping this +# attributes to corresponding cpld nodes. +# + + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + +PROJECT_NAME = 'as6712_32x' +version = '0.2.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':4, 'psu':2, 'sfp':32} + + +led_prefix ='/sys/devices/platform/as6712_32x_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as6712_32x_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan1_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan2_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan3_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan5_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['38-0048','39-0049', '40-004a', '41-004b'] , + 'psu': ['35-0038','36-003b'], + 'sfp': ['-0050']} +i2c_nodes = { + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_', 'sfp_tx_disable']} + +sfp_map = [ 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33 + ] + +#For sideband signals of SFP/QSFP modules. +bus_of_cpld = [0, 1] +cpld_of_module = {'-0062': list(range(0,16)), + '-0064': list(range(16,32)) } + + +mknod =[ +'echo as6712_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as6712_32x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as6712_32x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', + +# PSU-1 +'echo as6712_32x_psu1 0x38 > /sys/bus/i2c/devices/i2c-35/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-35/new_device', +#'echo as6712_32x_psu1 0x50 > /sys/bus/i2c/devices/i2c-35/new_device', +#'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-35/new_device', + +# PSU-2 +'echo as6712_32x_psu2 0x3b > /sys/bus/i2c/devices/i2c-36/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-36/new_device', +#'echo as6712_32x_psu2 0x53 > /sys/bus/i2c/devices/i2c-36/new_device', +#'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-36/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-38/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-39/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-40/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-41/new_device', +] + +mknod2 =[ +'echo as6712_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as6712_32x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as6712_32x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', + +# PSU-1 +'echo as6712_32x_psu1 0x38 > /sys/bus/i2c/devices/i2c-35/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-35/new_device', +#'echo as6712_32x_psu1 0x50 > /sys/bus/i2c/devices/i2c-35/new_device', +#'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-35/new_device', + +# PSU-2 +'echo as6712_32x_psu2 0x3b > /sys/bus/i2c/devices/i2c-36/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-36/new_device', +#'echo as6712_32x_psu2 0x53 > /sys/bus/i2c/devices/i2c-36/new_device', +#'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-36/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-38/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-39/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-40/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-41/new_device', +] + +FORCE = 0 + + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe optoe', +'modprobe accton_as6712_32x_cpld', +'modprobe cpr_4011_4mxx', +#'modprobe ym2651y', +'modprobe accton_as6712_32x_fan', +'modprobe leds-accton_as6712_32x', +'modprobe accton_as6712_32x_psu'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + #remove parameter if any + rm = kos[-(i+1)] + lst = rm.split(" ") + if len(lst) > 2: + del(lst[2:]) + rm = " ".join(lst) + + #Change to removing commands + rm = rm.replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +def cpld_bus_check(): + tmp = "i2cget -y -f 0 0x60" + status, output = log_os_system(tmp, 0) + if status: + return 1 + else: + return 0 + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x70 is exist @ i2c-0 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca932x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca932x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_inserted() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + order = cpld_bus_check() + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + for lk in cpld_of_module: + if k in cpld_of_module[lk]: + bus = bus_of_cpld[order] + node = key+str(k+1) + path = i2c_prefix + str(bus) + lk + "/"+ nodes[j] + str(k+1) + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/fanutil.py new file mode 100755 index 000000000000..92e79da72746 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/fanutil.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 2/27/2018: Roy Lee modify for as7312_54x +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + #BASE_VAL_PATH = '/sys/devices/platform/as5712_54x_fan/{0}' + BASE_VAL_PATH = '/sys/bus/i2c/devices/2-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/2-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + with open(device_path, 'r') as val_file: + content = val_file.readline().rstrip() + if not content: + logging.debug('GET. content is NULL, path:%s', device_path) + return None + except IOError as e: + logging.error('GET. unable to read file: %s', str(e)) + else: + return int(content) + + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + with open(device_path, 'w') as val_file: + val_file.write(content) + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + with open(self.FAN_DUTY_PATH) as val_file: + content = val_file.readline().rstrip() + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + return int(content) + + def set_fan_duty_cycle(self, val): + try: + with open(self.FAN_DUTY_PATH, 'r+') as val_file: + val_file.write(str(val)) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/thermalutil.py new file mode 100755 index 000000000000..4b3868ee6ec9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/classes/thermalutil.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 2/27/2018: Roy Lee modify for as7312_54x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['3', '48'], + THERMAL_NUM_2_IDX: ['3', '49'], + THERMAL_NUM_3_IDX: ['3', '4a'], + } + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + with open(filename, 'r') as val_file: + val_file = open(filename, 'r') + content = val_file.readline().rstrip() + if not content : + logging.debug('File is NULL. path:%s', device_path) + return None + else: + return int(content) + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + + return None + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/Makefile new file mode 100755 index 000000000000..488fdb321cac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_i2c_cpld.o \ + accton_as7312_54x_fan.o accton_as7312_54x_leds.o \ + accton_as7312_54x_psu.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_fan.c new file mode 100755 index 000000000000..8764ec8a3176 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_fan.c @@ -0,0 +1,815 @@ +/* + * A hwmon driver for the Accton as7312 54x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7312_54x_fan" + +#define NUM_THERMAL_SENSORS (3) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a} + +#define IN +#define OUT + +static struct as7312_54x_fan_data *as7312_54x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7312_54x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as7312_54x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7312_54x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7312_54x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7312_54x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0) + return -EINVAL; + + value = (value > FAN_MAX_DUTY_CYCLE)? FAN_MAX_DUTY_CYCLE : value; + + as7312_54x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7312_54x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + OUT int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as7312_54x_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7312_54x_fan_group = { + .attrs = as7312_54x_fan_attributes, +}; + +static struct as7312_54x_fan_data *as7312_54x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7312_54x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7312_54x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7312_54x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7312_54x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7312_54x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->enable = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7312_54x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7312_54x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7312_54x_fan_remove(struct i2c_client *client) +{ + struct as7312_54x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7312_54x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7312_54x_fan_id[] = { + { "as7312_54x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7312_54x_fan_id); + +static struct i2c_driver as7312_54x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7312_54x_fan_probe, + .remove = as7312_54x_fan_remove, + .id_table = as7312_54x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7312_54x_fan_init(void) +{ + return i2c_add_driver(&as7312_54x_fan_driver); +} + +static void __exit as7312_54x_fan_exit(void) +{ + i2c_del_driver(&as7312_54x_fan_driver); +} + +module_init(as7312_54x_fan_init); +module_exit(as7312_54x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7312_54x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_leds.c new file mode 100644 index 000000000000..f53716440107 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_leds.c @@ -0,0 +1,437 @@ +/* + * A LED driver for the accton_as7312_54x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as7312_54x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as7312_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "accton_as7312_54x_led" + +struct accton_as7312_54x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct accton_as7312_54x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7312_54x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as7312_54x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7312_54x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as7312_54x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7312_54x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as7312_54x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7312_54x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as7312_54x_led_diag_get(struct led_classdev *cdev) +{ + accton_as7312_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as7312_54x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7312_54x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as7312_54x_led_loc_get(struct led_classdev *cdev) +{ + accton_as7312_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as7312_54x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7312_54x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev accton_as7312_54x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as7312_54x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_diag_set, + .brightness_get = accton_as7312_54x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "accton_as7312_54x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_loc_set, + .brightness_get = accton_as7312_54x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "accton_as7312_54x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as7312_54x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as7312_54x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as7312_54x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + led_classdev_suspend(&accton_as7312_54x_leds[i]); + } + + return 0; +} + +static int accton_as7312_54x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + led_classdev_resume(&accton_as7312_54x_leds[i]); + } + + return 0; +} + +static int accton_as7312_54x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7312_54x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7312_54x_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7312_54x_leds[i]); + } + } + + return ret; +} + +static int accton_as7312_54x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + led_classdev_unregister(&accton_as7312_54x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7312_54x_led_driver = { + .probe = accton_as7312_54x_led_probe, + .remove = accton_as7312_54x_led_remove, + .suspend = accton_as7312_54x_led_suspend, + .resume = accton_as7312_54x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7312_54x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7312_54x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7312_54x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7312_54x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7312_54x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7312_54x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7312_54x_led_driver); + kfree(ledctl); +} + +module_init(accton_as7312_54x_led_init); +module_exit(accton_as7312_54x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7312_54x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_psu.c new file mode 100644 index 000000000000..4646224ef903 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_psu.c @@ -0,0 +1,277 @@ +/* + * An hwmon driver for accton as7312_54x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as7312_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7312_54x_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7312_54x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[9]; /* Model name, read from eeprom */ +}; + +static struct as7312_54x_psu_data *as7312_54x_psu_update_device(struct device *dev); + +enum as7312_54x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7312_54x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7312_54x_psu_data *data = as7312_54x_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7312_54x_psu_data *data = as7312_54x_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as7312_54x_psu_group = { + .attrs = as7312_54x_psu_attributes, +}; + +static int as7312_54x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7312_54x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7312_54x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7312_54x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7312_54x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7312_54x_psu_remove(struct i2c_client *client) +{ + struct as7312_54x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7312_54x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7312_54x_psu1, + as7312_54x_psu2 +}; + +static const struct i2c_device_id as7312_54x_psu_id[] = { + { "as7312_54x_psu1", as7312_54x_psu1 }, + { "as7312_54x_psu2", as7312_54x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7312_54x_psu_id); + +static struct i2c_driver as7312_54x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7312_54x_psu", + }, + .probe = as7312_54x_psu_probe, + .remove = as7312_54x_psu_remove, + .id_table = as7312_54x_psu_id, + .address_list = normal_i2c, +}; + +static int as7312_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7312_54x_psu_data *as7312_54x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as7312_54x update\n"); + + /* Read psu status */ + status = as7312_54x_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as7312_54x_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as7312_54x_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7312_54x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_sfp.c new file mode 100644 index 000000000000..921d9f892cac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_as7312_54x_sfp.c @@ -0,0 +1,1972 @@ +/* + * SFP driver for accton as7312_54x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "as7312_54x_sfp" /* Platform dependent */ + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) +#define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else +#define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_PORT 54 +#define SFP_PORT_MAX 48 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +#define MULTIPAGE_SUPPORT 1 + +#if (MULTIPAGE_SUPPORT == 1) +/* fundamental unit of addressing for SFF_8472/SFF_8436 */ +#define SFF_8436_PAGE_SIZE 128 +/* + * The current 8436 (QSFP) spec provides for only 4 supported + * pages (pages 0-3). + * This driver is prepared to support more, but needs a register in the + * EEPROM to indicate how many pages are supported before it is safe + * to implement more pages in the driver. + */ +#define SFF_8436_SPECED_PAGES 4 +#define SFF_8436_EEPROM_SIZE ((1 + SFF_8436_SPECED_PAGES) * SFF_8436_PAGE_SIZE) +#define SFF_8436_EEPROM_UNPAGED_SIZE (2 * SFF_8436_PAGE_SIZE) +/* + * The current 8472 (SFP) spec provides for only 3 supported + * pages (pages 0-2). + * This driver is prepared to support more, but needs a register in the + * EEPROM to indicate how many pages are supported before it is safe + * to implement more pages in the driver. + */ +#define SFF_8472_SPECED_PAGES 3 +#define SFF_8472_EEPROM_SIZE ((3 + SFF_8472_SPECED_PAGES) * SFF_8436_PAGE_SIZE) +#define SFF_8472_EEPROM_UNPAGED_SIZE (4 * SFF_8436_PAGE_SIZE) + +/* a few constants to find our way around the EEPROM */ +#define SFF_8436_PAGE_SELECT_REG 0x7F +#define SFF_8436_PAGEABLE_REG 0x02 +#define SFF_8436_NOT_PAGEABLE (1<<2) +#define SFF_8472_PAGEABLE_REG 0x40 +#define SFF_8472_PAGEABLE (1<<4) + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = SFF_8436_PAGE_SIZE; + +/* + * specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; + +typedef enum qsfp_opcode { + QSFP_READ_OP = 0, + QSFP_WRITE_OP = 1 +} qsfp_opcode_e; +#endif + +/* Platform dependent +++ */ +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x62 +#define I2C_ADDR_CPLD3 0x64 + +#define CPLD3_OFFSET_QSFP_MOD_RST 0x17 +/* Platform dependent --- */ +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL, + SFP_MOD_RST +}; + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static SENSOR_DEVICE_ATTR(sfp_mod_rst, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, SFP_MOD_RST); + +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + &sensor_dev_attr_sfp_mod_rst.dev_attr.attr, + NULL +}; + +/* SFP msa attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); +static struct attribute *sfp_msa_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { + as7312_54x_port1, as7312_54x_port2, as7312_54x_port3, as7312_54x_port4, + as7312_54x_port5, as7312_54x_port6, as7312_54x_port7, as7312_54x_port8, + as7312_54x_port9, as7312_54x_port10, as7312_54x_port11, as7312_54x_port12, + as7312_54x_port13, as7312_54x_port14, as7312_54x_port15, as7312_54x_port16, + as7312_54x_port17, as7312_54x_port18, as7312_54x_port19, as7312_54x_port20, + as7312_54x_port21, as7312_54x_port22, as7312_54x_port23, as7312_54x_port24, + as7312_54x_port25, as7312_54x_port26, as7312_54x_port27, as7312_54x_port28, + as7312_54x_port29, as7312_54x_port30, as7312_54x_port31, as7312_54x_port32, + as7312_54x_port33, as7312_54x_port34, as7312_54x_port35, as7312_54x_port36, + as7312_54x_port37, as7312_54x_port38, as7312_54x_port39, as7312_54x_port40, + as7312_54x_port41, as7312_54x_port42, as7312_54x_port43, as7312_54x_port44, + as7312_54x_port45, as7312_54x_port46, as7312_54x_port47, as7312_54x_port48, + as7312_54x_port49, as7312_54x_port52, as7312_54x_port50, as7312_54x_port53, + as7312_54x_port51, as7312_54x_port54 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { + I2C_DEV_ID(as7312_54x_port1), + I2C_DEV_ID(as7312_54x_port2), + I2C_DEV_ID(as7312_54x_port3), + I2C_DEV_ID(as7312_54x_port4), + I2C_DEV_ID(as7312_54x_port5), + I2C_DEV_ID(as7312_54x_port6), + I2C_DEV_ID(as7312_54x_port7), + I2C_DEV_ID(as7312_54x_port8), + I2C_DEV_ID(as7312_54x_port9), + I2C_DEV_ID(as7312_54x_port10), + I2C_DEV_ID(as7312_54x_port11), + I2C_DEV_ID(as7312_54x_port12), + I2C_DEV_ID(as7312_54x_port13), + I2C_DEV_ID(as7312_54x_port14), + I2C_DEV_ID(as7312_54x_port15), + I2C_DEV_ID(as7312_54x_port16), + I2C_DEV_ID(as7312_54x_port17), + I2C_DEV_ID(as7312_54x_port18), + I2C_DEV_ID(as7312_54x_port19), + I2C_DEV_ID(as7312_54x_port20), + I2C_DEV_ID(as7312_54x_port21), + I2C_DEV_ID(as7312_54x_port22), + I2C_DEV_ID(as7312_54x_port23), + I2C_DEV_ID(as7312_54x_port24), + I2C_DEV_ID(as7312_54x_port25), + I2C_DEV_ID(as7312_54x_port26), + I2C_DEV_ID(as7312_54x_port27), + I2C_DEV_ID(as7312_54x_port28), + I2C_DEV_ID(as7312_54x_port29), + I2C_DEV_ID(as7312_54x_port30), + I2C_DEV_ID(as7312_54x_port31), + I2C_DEV_ID(as7312_54x_port32), + I2C_DEV_ID(as7312_54x_port33), + I2C_DEV_ID(as7312_54x_port34), + I2C_DEV_ID(as7312_54x_port35), + I2C_DEV_ID(as7312_54x_port36), + I2C_DEV_ID(as7312_54x_port37), + I2C_DEV_ID(as7312_54x_port38), + I2C_DEV_ID(as7312_54x_port39), + I2C_DEV_ID(as7312_54x_port40), + I2C_DEV_ID(as7312_54x_port41), + I2C_DEV_ID(as7312_54x_port42), + I2C_DEV_ID(as7312_54x_port43), + I2C_DEV_ID(as7312_54x_port44), + I2C_DEV_ID(as7312_54x_port45), + I2C_DEV_ID(as7312_54x_port46), + I2C_DEV_ID(as7312_54x_port47), + I2C_DEV_ID(as7312_54x_port48), + I2C_DEV_ID(as7312_54x_port49), + I2C_DEV_ID(as7312_54x_port50), + I2C_DEV_ID(as7312_54x_port51), + I2C_DEV_ID(as7312_54x_port52), + I2C_DEV_ID(as7312_54x_port53), + I2C_DEV_ID(as7312_54x_port54), + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); +/* Platform dependent --- */ + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[6]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss + 3 => device id + 4 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 5 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +#if (MULTIPAGE_SUPPORT == 1) + struct i2c_client *ddm_client; /* dummy client instance for 0xA2 */ +#endif +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct qsfp_data *qsfp; + + struct i2c_client *client; +#if (MULTIPAGE_SUPPORT == 1) + int use_smbus; + u8 *writebuf; + unsigned write_max; +#endif +}; + +#if (MULTIPAGE_SUPPORT == 1) +static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, + char *buf, loff_t off, size_t len, qsfp_opcode_e opcode); +#endif +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +/* Platform dependent +++ */ +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + int i = 0, j = 0, status = -1; + u8 reg; + unsigned short cpld_addr; + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + data->present = 0; + + /* Read present status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + cpld_addr = I2C_ADDR_CPLD2 + i*2; + reg = 0x9+j; + status = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); + data->present |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* Read present status of port 49-52(QSFP port) */ + cpld_addr = I2C_ADDR_CPLD2; + reg = 0x18; + status = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + else { + data->present |= (u64)(status & 0xF) << SFP_PORT_MAX; + } + + /* Read present status of port 53-54(QSFP port) */ + cpld_addr = I2C_ADDR_CPLD3; + reg = 0x18; + status = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + else { + data->present |= (u64)(status & 0x3) << 52; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static struct sfp_port_data* sfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0, j = 0; + int status = -1; + + if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { + return data; + } + + DEBUG_PRINT("Starting as7312_54x sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->msa->valid = 0; + memset(data->msa->status, 0, sizeof(data->msa->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 9; j++) { + u8 reg; + unsigned short cpld_addr; + reg = 0xc+j; + cpld_addr = I2C_ADDR_CPLD2 + i*2; + + status = accton_i2c_cpld_read(cpld_addr, reg); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + data->msa->valid = 1; + data->msa->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + unsigned short cpld_addr = 0; + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long disable; + int error; + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_set_tx_disable(dev, da, buf, count); + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + if(data->port < 24) { + cpld_addr = I2C_ADDR_CPLD2; + cpld_reg = 0xF + data->port / 8; + cpld_bit = 1 << (data->port % 8); + } + else { /* port 24 ~ 48 */ + cpld_addr = I2C_ADDR_CPLD3; + cpld_reg = 0xF + (data->port - 24) / 8; + cpld_bit = 1 << (data->port % 8); + } + + /* Read current status */ + cpld_val = accton_i2c_cpld_read(cpld_addr, cpld_reg); + + /* Update tx_disable status */ + if (disable) { + data->msa->status[1] |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->msa->status[1] &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + accton_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); + mutex_unlock(&data->update_lock); + return count; +} + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = sfp_update_present(client); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + return (data->present & BIT_INDEX(data->port)) ? 0 : 1; /* Platform dependent */ +} + +/* Platform dependent +++ */ +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if (PRESENT_ALL == attr->index) { + int i; + u8 values[7] = {0}; + struct sfp_port_data *data = sfp_update_present(client); + + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = ~(u8)(data->present >> (i * 8)); + } + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6] & 0x3F); + } + else { + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + /* PRESENT */ + return sprintf(buf, "%d\n", present); + } +} +/* Platform dependent --- */ + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + DEBUG_PRINT("Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + int port_bit; + int status = -EINVAL; + u8 cpld_addr[] = {I2C_ADDR_CPLD2, I2C_ADDR_CPLD3}; + + /* Low power mode is not supported for SFP ports(1-48) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + mutex_lock(&data->update_lock); + + port_bit = data->port - SFP_PORT_MAX; + cpld_val = accton_i2c_cpld_read(cpld_addr[port_bit/4], CPLD3_OFFSET_QSFP_MOD_RST); + + pr_err("[ROY]%s#%d, %x from %x\n", __func__, __LINE__, cpld_val, cpld_addr[port_bit/4]); + + cpld_val = cpld_val & 0x0F; + cpld_val = cpld_val & BIT_INDEX(port_bit%4); + + pr_err("[ROY]%s#%d, %x of bit %d\n", __func__, __LINE__, cpld_val, port_bit); + + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", cpld_val>>(port_bit%4)); + + mutex_unlock(&data->update_lock); + + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + long reset; + int error, port_bit; + u8 cpld_addr[] = {I2C_ADDR_CPLD2, I2C_ADDR_CPLD3}; + + pr_err("[ROY]%s#%d, port:%d\n", __func__, __LINE__, data->port); + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + port_bit = data->port - SFP_PORT_MAX; + error = kstrtol(buf, 10, &reset); + + pr_err("[ROY]%s#%d, %s == %d\n", __func__, __LINE__, buf, error); + if (error) { + return error; + } + mutex_lock(&data->update_lock); + + cpld_val = accton_i2c_cpld_read(cpld_addr[port_bit/4], CPLD3_OFFSET_QSFP_MOD_RST); + pr_err("[ROY]%s#%d, %x\n", __func__, __LINE__, cpld_val); + /* Update lp_mode status */ + if (reset) + { + cpld_val |= BIT_INDEX(port_bit%4); + } + else + { + cpld_val &= ~BIT_INDEX(port_bit%4); + } + pr_err("[ROY]%s#%d, %x to %x\n", __func__, __LINE__, cpld_val, cpld_addr[port_bit/4]); + + accton_i2c_cpld_write(cpld_addr[port_bit/4], CPLD3_OFFSET_QSFP_MOD_RST, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + int present; + u8 val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENXIO; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + switch (attr->index) { + case TX_FAULT: + val = !!(data->qsfp->status[2] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + case TX_DISABLE: + val = data->qsfp->status[1] & 0xF; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + case RX_LOS: + val = !!(data->qsfp->status[0] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); + break; + default: + break; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (!status) { + /* port is not present */ + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + mutex_lock(&data->update_lock); + + if (attr->index == TX_DISABLE) { + if (disable) { + data->qsfp->status[1] |= 0xF; + } + else { + data->qsfp->status[1] &= ~0xF; + } + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +/* Platform dependent +++ */ +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_show_tx_rx_status(dev, da, buf); + } + + data = sfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + if(attr->index == RX_LOS_ALL) { + int i = 0; + u8 values[6] = {0}; + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = (u8)(data->msa->status[2] >> (i * 8)); + } + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + case RX_LOS: + index = 2; + break; + default: + return 0; + } + + val = (data->msa->status[index] & BIT_INDEX(data->port)) ? 1 : 0; + return sprintf(buf, "%d\n", val); +} +/* Platform dependent --- */ +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, command, *data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return 1; +#endif + + +} + +#if (MULTIPAGE_SUPPORT == 0) +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} +#endif + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + +#if (MULTIPAGE_SUPPORT == 1) + return sfp_port_read_write(data, buf, off, count, QSFP_WRITE_OP); +#else + return sfp_port_write(data, buf, off, count); +#endif +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return status; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + status = 1; + +abort: + return status; +#endif +} + +#if (MULTIPAGE_SUPPORT == 1) +/*-------------------------------------------------------------------------*/ +/* + * This routine computes the addressing information to be used for + * a given r/w request. + * + * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), + * the page, and the offset. + * + * Handles both SFP and QSFP. + * For SFP, offset 0-255 are on client[0], >255 is on client[1] + * Offset 256-383 are on the lower half of client[1] + * Pages are accessible on the upper half of client[1]. + * Offset >383 are in 128 byte pages mapped into the upper half + * + * For QSFP, all offsets are on client[0] + * offset 0-127 are on the lower half of client[0] (no paging) + * Pages are accessible on the upper half of client[1]. + * Offset >127 are in 128 byte pages mapped into the upper half + * + * Callers must not read/write beyond the end of a client or a page + * without recomputing the client/page. Hence offset (within page) + * plus length must be less than or equal to 128. (Note that this + * routine does not have access to the length of the call, hence + * cannot do the validity check.) + * + * Offset within Lower Page 00h and Upper Page 00h are not recomputed + */ +static uint8_t sff_8436_translate_offset(struct sfp_port_data *port_data, + loff_t *offset, struct i2c_client **client) +{ + unsigned page = 0; + + *client = port_data->client; + + /* if SFP style, offset > 255, shift to i2c addr 0x51 */ + if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { + if (*offset > 255) { + /* like QSFP, but shifted to client[1] */ + *client = port_data->msa->ddm_client; + *offset -= 256; + } + } + + /* + * if offset is in the range 0-128... + * page doesn't matter (using lower half), return 0. + * offset is already correct (don't add 128 to get to paged area) + */ + if (*offset < SFF_8436_PAGE_SIZE) + return page; + + /* note, page will always be positive since *offset >= 128 */ + page = (*offset >> 7)-1; + /* 0x80 places the offset in the top half, offset is last 7 bits */ + *offset = SFF_8436_PAGE_SIZE + (*offset & 0x7f); + + return page; /* note also returning client and offset */ +} + +static ssize_t sff_8436_eeprom_read(struct sfp_port_data *port_data, + struct i2c_client *client, + char *buf, unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + u8 msgbuf[2]; + unsigned long timeout, read_time; + int status, i; + + memset(msg, 0, sizeof(msg)); + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* + * When we have a better choice than SMBus calls, use a + * combined I2C message. Write address; then read up to + * io_limit data bytes. msgbuf is u8 and will cast to our + * needs. + */ + i = 0; + msgbuf[i++] = offset; + + msg[0].addr = client->addr; + msg[0].buf = msgbuf; + msg[0].len = i; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_read_i2c_block_data(client, offset, + count, buf); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; + if (count == 2) + buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_read_byte_data(client, offset); + if (status >= 0) { + buf[0] = status; + status = count; + } + break; + default: + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + status = count; + } + + dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) /* happy path */ + return count; + + if (status == -ENXIO) /* no module present */ + return status; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t sff_8436_eeprom_write(struct sfp_port_data *port_data, + struct i2c_client *client, + const char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page_start; + int i = 0; + + /* write max is at most a page + * (In this driver, write_max is actually one byte!) + */ + if (count > port_data->write_max) + count = port_data->write_max; + + /* shorten count if necessary to avoid crossing page boundary */ + next_page_start = roundup(offset + 1, SFF_8436_PAGE_SIZE); + if (offset + count > next_page_start) + count = next_page_start - offset; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* If we'll use I2C calls for I/O, set up the message */ + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = port_data->writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + break; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + break; + case I2C_SMBUS_WORD_DATA: + if (count == 2) { + status = i2c_smbus_write_word_data(client, + offset, (u16)((buf[0])|(buf[1] << 8))); + } else { + /* count = 1 */ + status = i2c_smbus_write_byte_data(client, + offset, buf[0]); + } + if (status == 0) + status = count; + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_write_byte_data(client, offset, + buf[0]); + if (status == 0) + status = count; + break; + default: + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + break; + } + + dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", + count, offset, (long int) status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + + +static ssize_t sff_8436_eeprom_update_client(struct sfp_port_data *port_data, + char *buf, loff_t off, + size_t count, qsfp_opcode_e opcode) +{ + struct i2c_client *client; + ssize_t retval = 0; + u8 page = 0; + loff_t phy_offset = off; + int ret = 0; + + page = sff_8436_translate_offset(port_data, &phy_offset, &client); + + dev_dbg(&client->dev, + "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", + off, page, phy_offset, (long int) count, opcode); + if (page > 0) { + ret = sff_8436_eeprom_write(port_data, client, &page, + SFF_8436_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_dbg(&client->dev, + "Write page register for page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + + while (count) { + ssize_t status; + + if (opcode == QSFP_READ_OP) { + status = sff_8436_eeprom_read(port_data, client, + buf, phy_offset, count); + } else { + status = sff_8436_eeprom_write(port_data, client, + buf, phy_offset, count); + } + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + phy_offset += status; + count -= status; + retval += status; + } + + + if (page > 0) { + /* return the page register to page 0 (why?) */ + page = 0; + ret = sff_8436_eeprom_write(port_data, client, &page, + SFF_8436_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_err(&client->dev, + "Restore page register to page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + return retval; +} + + +/* + * Figure out if this access is within the range of supported pages. + * Note this is called on every access because we don't know if the + * module has been replaced since the last call. + * If/when modules support more pages, this is the routine to update + * to validate and allow access to additional pages. + * + * Returns updated len for this access: + * - entire access is legal, original len is returned. + * - access begins legal but is too long, len is truncated to fit. + * - initial offset exceeds supported pages, return -EINVAL + */ +static ssize_t sff_8436_page_legal(struct sfp_port_data *port_data, + loff_t off, size_t len) +{ + struct i2c_client *client = port_data->client; + u8 regval; + int status; + size_t maxlen; + + if (off < 0) return -EINVAL; + if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { + /* SFP case */ + if ((off + len) <= 256) return len; + /* if no pages needed, we're good */ + //if ((off + len) <= SFF_8472_EEPROM_UNPAGED_SIZE) return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= SFF_8472_EEPROM_SIZE) return -EINVAL; + + /* Check if ddm is supported */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF8472_DIAG_MON_TYPE_ADDR, 1); + if (status < 0) return status; /* error out (no module?) */ + if (!(regval & SFF8472_DIAG_MON_TYPE_DDM_MASK)) { + if (off >= 256) return -EINVAL; + maxlen = 256 - off; + } + else { + /* in between, are pages supported? */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF_8472_PAGEABLE_REG, 1); + if (status < 0) return status; /* error out (no module?) */ + if (regval & SFF_8472_PAGEABLE) { + /* Pages supported, trim len to the end of pages */ + maxlen = SFF_8472_EEPROM_SIZE - off; + } else { + /* pages not supported, trim len to unpaged size */ + if (off >= SFF_8472_EEPROM_UNPAGED_SIZE) return -EINVAL; + maxlen = SFF_8472_EEPROM_UNPAGED_SIZE - off; + } + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, SFP, off %lld len %ld\n", + off, (long int) len); + } + else if (port_data->driver_type == DRIVER_TYPE_QSFP) { + /* QSFP case */ + /* if no pages needed, we're good */ + if ((off + len) <= SFF_8436_EEPROM_UNPAGED_SIZE) return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= SFF_8436_EEPROM_SIZE) return -EINVAL; + /* in between, are pages supported? */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF_8436_PAGEABLE_REG, 1); + if (status < 0) return status; /* error out (no module?) */ + if (regval & SFF_8436_NOT_PAGEABLE) { + /* pages not supported, trim len to unpaged size */ + if (off >= SFF_8436_EEPROM_UNPAGED_SIZE) return -EINVAL; + maxlen = SFF_8436_EEPROM_UNPAGED_SIZE - off; + } else { + /* Pages supported, trim len to the end of pages */ + maxlen = SFF_8436_EEPROM_SIZE - off; + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, QSFP, off %lld len %ld\n", + off, (long int) len); + } + else { + return -EINVAL; + } + return len; +} + + +static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, + char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) +{ + struct i2c_client *client = port_data->client; + int chunk; + int status = 0; + ssize_t retval; + size_t pending_len = 0, chunk_len = 0; + loff_t chunk_offset = 0, chunk_start_offset = 0; + + if (unlikely(!len)) + return len; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&port_data->update_lock); + + /* + * Confirm this access fits within the device suppored addr range + */ + len = sff_8436_page_legal(port_data, off, len); + if (len < 0) { + status = len; + goto err; + } + + /* + * For each (128 byte) chunk involved in this request, issue a + * separate call to sff_eeprom_update_client(), to + * ensure that each access recalculates the client/page + * and writes the page register as needed. + * Note that chunk to page mapping is confusing, is different for + * QSFP and SFP, and never needs to be done. Don't try! + */ + pending_len = len; /* amount remaining to transfer */ + retval = 0; /* amount transferred */ + for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { + + /* + * Compute the offset and number of bytes to be read/write + * + * 1. start at offset 0 (within the chunk), and read/write + * the entire chunk + * 2. start at offset 0 (within the chunk) and read/write less + * than entire chunk + * 3. start at an offset not equal to 0 and read/write the rest + * of the chunk + * 4. start at an offset not equal to 0 and read/write less than + * (end of chunk - offset) + */ + chunk_start_offset = chunk * SFF_8436_PAGE_SIZE; + + if (chunk_start_offset < off) { + chunk_offset = off; + if ((off + pending_len) < (chunk_start_offset + + SFF_8436_PAGE_SIZE)) + chunk_len = pending_len; + else + chunk_len = (chunk+1)*SFF_8436_PAGE_SIZE - off;/*SFF_8436_PAGE_SIZE - off;*/ + } else { + chunk_offset = chunk_start_offset; + if (pending_len > SFF_8436_PAGE_SIZE) + chunk_len = SFF_8436_PAGE_SIZE; + else + chunk_len = pending_len; + } + + dev_dbg(&client->dev, + "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", + off, (long int) len, chunk_start_offset, chunk_offset, + (long int) chunk_len, (long int) pending_len); + + /* + * note: chunk_offset is from the start of the EEPROM, + * not the start of the chunk + */ + status = sff_8436_eeprom_update_client(port_data, buf, + chunk_offset, chunk_len, opcode); + if (status != chunk_len) { + /* This is another 'no device present' path */ + dev_dbg(&client->dev, + "sff_8436_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", + chunk, chunk_offset, (long int) chunk_len, status); + goto err; + } + buf += status; + pending_len -= status; + retval += status; + } + mutex_unlock(&port_data->update_lock); + + return retval; + +err: + mutex_unlock(&port_data->update_lock); + + return status; +} + +#else +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} +#endif + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + +#if (MULTIPAGE_SUPPORT == 1) + return sfp_port_read_write(data, buf, off, count, QSFP_READ_OP); +#else + return sfp_port_read(data, buf, off, count); +#endif +} + +#if (MULTIPAGE_SUPPORT == 1) +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, size_t size) +#else +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +#endif +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; +#if (MULTIPAGE_SUPPORT == 1) + eeprom->size = size; +#else + eeprom->size = EEPROM_SIZE; +#endif + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + + +#if (MULTIPAGE_SUPPORT == 0) +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} +#endif + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + +#if (MULTIPAGE_SUPPORT == 0) + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } +#endif + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ +#if (MULTIPAGE_SUPPORT == 1) + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin, SFF_8436_EEPROM_SIZE); +#else + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); +#endif + if (status) { + goto exit_remove; + } + +#if (MULTIPAGE_SUPPORT == 1) + msa->ddm_client = i2c_new_dummy(client->adapter, client->addr + 1); + if (!msa->ddm_client) { + dev_err(&client->dev, "address 0x%02x unavailable\n", client->addr + 1); + status = -EADDRINUSE; + goto exit_eeprom; + } +#endif + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +exit_eeprom: + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &msa->eeprom.bin); +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + +#if (MULTIPAGE_SUPPORT == 0) + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } +#endif + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ +#if (MULTIPAGE_SUPPORT == 1) + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, SFF_8436_EEPROM_SIZE); +#else + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); +#endif + if (status) { + goto exit_remove; + } + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +/* Platform dependent +++ */ +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int ret = 0; + struct sfp_port_data *data = NULL; + + if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { + return -ENODEV; + } + + if (dev_id->driver_data < as7312_54x_port1 || dev_id->driver_data > as7312_54x_port54) { + return -ENXIO; + } + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + +#if (MULTIPAGE_SUPPORT == 1) + data->use_smbus = 0; + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + data->use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + data->use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + data->use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + ret = -EPFNOSUPPORT; + goto exit_kfree; + } + } + + if (!data->use_smbus || + (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_WORD_DATA) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + /* + * NOTE: AN-2079 + * Finisar recommends that the host implement 1 byte writes + * only since this module only supports 32 byte page boundaries. + * 2 byte writes are acceptable for PE and Vout changes per + * Application Note AN-2071. + */ + unsigned write_max = 1; + + if (write_max > io_limit) + write_max = io_limit; + if (data->use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + data->write_max = write_max; + + /* buffer (data + address at the beginning) */ + data->writebuf = kmalloc(write_max + 2, GFP_KERNEL); + if (!data->writebuf) { + ret = -ENOMEM; + goto exit_kfree; + } + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + + if (data->use_smbus == I2C_SMBUS_WORD_DATA || + data->use_smbus == I2C_SMBUS_BYTE_DATA) { + dev_notice(&client->dev, "Falling back to %s reads, " + "performance will suffer\n", data->use_smbus == + I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } +#endif + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if (dev_id->driver_data >= as7312_54x_port1 && dev_id->driver_data <= as7312_54x_port48) { + data->driver_type = DRIVER_TYPE_SFP_MSA; + ret = sfp_msa_probe(client, dev_id, &data->msa); + } + else { /* as7312_54x_portsfp49 ~ as7312_54x_portsfp54 */ + data->driver_type = DRIVER_TYPE_QSFP; + ret = qsfp_probe(client, dev_id, &data->qsfp); + } + + if (ret < 0) { + goto exit_kfree_buf; + } + + + return ret; + +exit_kfree_buf: +#if (MULTIPAGE_SUPPORT == 1) + if (data->writebuf) kfree(data->writebuf); +#endif + +exit_kfree: + kfree(data); + return ret; +} +/* Platform dependent --- */ + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); +#if (MULTIPAGE_SUPPORT == 1) + i2c_unregister_device(data->ddm_client); +#endif + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + int ret = 0; + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + +#if (MULTIPAGE_SUPPORT == 1) + if (data->writebuf) + kfree(data->writebuf); +#endif + kfree(data); + return ret; +} + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7312_54x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_i2c_cpld.c new file mode 100644 index 000000000000..67ecd8e036a9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/accton_i2c_cpld.c @@ -0,0 +1,1219 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as7312_54x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as7312_54x_cpld1, + as7312_54x_cpld2, + as7312_54x_cpld3 +}; + +struct as7312_54x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as7312_54x_cpld_id[] = { + { "as7312_54x_cpld1", as7312_54x_cpld1 }, + { "as7312_54x_cpld2", as7312_54x_cpld2 }, + { "as7312_54x_cpld3", as7312_54x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as7312_54x_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as7312_54x_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as7312_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7312_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR, show_status, set_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(54); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); + +static struct attribute *as7312_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7312_54x_cpld1_group = { + .attrs = as7312_54x_cpld1_attributes, +}; + +static struct attribute *as7312_54x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_RESET_ATTR(49), + DECLARE_TRANSCEIVER_RESET_ATTR(50), + DECLARE_TRANSCEIVER_RESET_ATTR(51), + DECLARE_TRANSCEIVER_RESET_ATTR(52), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + NULL +}; + +static const struct attribute_group as7312_54x_cpld2_group = { + .attrs = as7312_54x_cpld2_attributes, +}; + +static struct attribute *as7312_54x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_TRANSCEIVER_RESET_ATTR(53), + DECLARE_TRANSCEIVER_RESET_ATTR(54), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + NULL +}; + +static const struct attribute_group as7312_54x_cpld3_group = { + .attrs = as7312_54x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[4] = {0}; + u8 regs[] = {0x9, 0xA, 0xB, 0x18}; + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7312_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + if (data->type == as7312_54x_cpld2) { + values[3] &= 0xF; + } + else { /* as7312_54x_cpld3 */ + values[3] &= 0x3; + } + + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[3] = {0}; + u8 regs[] = {0x12, 0x13, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7312_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_40: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_33); + break; + case MODULE_PRESENT_41 ... MODULE_PRESENT_48: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_41); + break; + case MODULE_PRESENT_49: + reg = 0x18; + mask = 0x1; + break; + case MODULE_PRESENT_50: + reg = 0x18; + mask = 0x2; + break; + case MODULE_PRESENT_51: + reg = 0x18; + mask = 0x4; + break; + case MODULE_PRESENT_52: + reg = 0x18; + mask = 0x8; + break; + case MODULE_PRESENT_53: + reg = 0x18; + mask = 0x1; + break; + case MODULE_PRESENT_54: + reg = 0x18; + mask = 0x2; + break; + + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x17; + mask = 1 << ((attr->index - MODULE_PRESENT_49)%4); + break; + + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXFAULT_1); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXFAULT_9); + break; + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXFAULT_17); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXFAULT_33); + break; + case MODULE_TXFAULT_41 ... MODULE_TXFAULT_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXFAULT_41); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_8: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_RXLOS_1); + break; + case MODULE_RXLOS_9 ... MODULE_RXLOS_16: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_RXLOS_9); + break; + case MODULE_RXLOS_17 ... MODULE_RXLOS_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RXLOS_17); + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_32: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_RXLOS_33 ... MODULE_RXLOS_40: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_RXLOS_33); + break; + case MODULE_RXLOS_41 ... MODULE_RXLOS_48: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RXLOS_41); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_54) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x17; + mask = 1 << ((attr->index - MODULE_RESET_49)%4); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update reset status */ + if (reset) { + status |= mask; + } + else { + status &= ~mask; + } + status = as7312_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7312_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as7312_54x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7312_54x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as7312_54x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as7312_54x_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as7312_54x_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as7312_54x_cpld1: + group = &as7312_54x_cpld1_group; + break; + case as7312_54x_cpld2: + group = &as7312_54x_cpld2_group; + break; + case as7312_54x_cpld3: + group = &as7312_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as7312_54x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as7312_54x_cpld_remove(struct i2c_client *client) +{ + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as7312_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as7312_54x_cpld1: + group = &as7312_54x_cpld1_group; + break; + case as7312_54x_cpld2: + group = &as7312_54x_cpld2_group; + break; + case as7312_54x_cpld3: + group = &as7312_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as7312_54x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7312_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as7312_54x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7312_54x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7312_54x_cpld_read); + +int as7312_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7312_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7312_54x_cpld_write); + +static struct i2c_driver as7312_54x_cpld_driver = { + .driver = { + .name = "as7312_54x_cpld", + .owner = THIS_MODULE, + }, + .probe = as7312_54x_cpld_probe, + .remove = as7312_54x_cpld_remove, + .id_table = as7312_54x_cpld_id, +}; + +static int __init as7312_54x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7312_54x_cpld_driver); +} + +static void __exit as7312_54x_cpld_exit(void) +{ + i2c_del_driver(&as7312_54x_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as7312_54x_cpld_init); +module_exit(as7312_54x_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/service/as7312-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/service/as7312-platform-monitor.service new file mode 100755 index 000000000000..b79357665bed --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/service/as7312-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS7312-54X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7312_util.py install +ExecStart=/usr/local/bin/accton_as7312_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/setup.py new file mode 100755 index 000000000000..5e862ce15048 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7312_54x', + version='1.0', + description='Module to initialize Accton AS7312-54X platforms', + + packages=['as7312_54x'], + package_dir={'as7312_54x': 'as7312-54x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/sonic_platform_setup.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/sonic_platform_setup.py new file mode 100755 index 000000000000..672fe89cef6c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/sonic_platform_setup.py @@ -0,0 +1,34 @@ +from setuptools import setup + +DEVICE_NAME = 'accton' +HW_SKU = 'x86_64-accton_as7312_54x-r0' + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on Accton Platforms', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + maintainer='Jostar Yang', + maintainer_email='jostar_yang@edge-core.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 :: 3.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/README new file mode 100755 index 000000000000..66f31a030423 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as7312_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as7312-fan-psu-cpld.patch + for as7312's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS7312-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as7312 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS7312-54X.patch" from patch/installer. + - Change setting for AS7312-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS7312-54X.patch" + !!NOTICE, patching onie_installer-accton-AS7312-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS7312-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as7312-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as7312_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS7312-54X.patch. + It's done by patching onie_installer-accton-AS7312-54X.patch at build-image. + Run "accton_as7312_util.py install" to install drivers. + +To initialize the system, run "accton_as7312_util.py install". +To clean up the drivers & devices, run "accton_as7312_util.py clean". +To dump information of sensors, run "accton_as7312_util.py show". +To dump SFP EEPROM, run "accton_as7312_util.py sff". +To set fan speed, run "accton_as7312_util.py set fan". +To enable/disable SFP emission, run "accton_as7312_util.py set sfp". +To set system LEDs' color, run "accton_as7312_util.py set led" +For more information, run "accton_as7312_util.py --help". + +==================================================================== +Besides applying accton_as7312_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_monitor.py new file mode 100755 index 000000000000..2f87c3f58736 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_monitor.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 2/27/2018: Roy Lee modify for as7312_54x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from as7312_54x.fanutil import FanUtil + from as7312_54x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7312_monitor' +DUTY_MAX = 100 + +global log_file +global log_level + +# (LM75_1+ LM75_2+ LM75_3) is LM75 at i2c addresses 0x48, 0x49, and 0x4A. +# TMP = (LM75_1+ LM75_2+ LM75_3)/3 +#1. If TMP < 35, All fans run with duty 31.25%. +#2. If TMP>=35 or the temperature of any one of fan is higher than 40, +# All fans run with duty 50% +#3. If TMP >= 40 or the temperature of any one of fan is higher than 45, +# All fans run with duty 62.5%. +#4. If TMP >= 45 or the temperature of any one of fan is higher than 50, +# All fans run with duty 100%. +#5. Any one of 6 fans is fault, set duty = 100%. +#6. Direction factor. If it is B2F direction, duty + 12%. + + # MISC: + # 1.Check single LM75 before applied average. + # 2.If no matched fan speed is found from the policy, + # use FAN_DUTY_CYCLE_MIN as default speed + # Get current temperature + # 4.Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature + + + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7312_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + self.thermal = ThermalUtil() + self.fan = FanUtil() + + def manage_fans(self): + max_duty = DUTY_MAX + fan_policy_f2b = { + 0: [32, 0, 105000], + 1: [50, 105000, 120000], + 2: [63, 120000, 135000], + 3: [max_duty, 135000, sys.maxsize], + } + fan_policy_b2f = { + 0: [44, 0, 105000], + 1: [63, 105000, 120000], + 2: [75, 120000, 135000], + 3: [max_duty, 135000, sys.maxsize], + } + fan_policy_single = { + 0: 40000, + 1: 45000, + 2: 50000, + } + + thermal = self.thermal + fan = self.fan + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + return False + if fan_status is False: + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + fan.set_fan_duty_cycle(max_duty) + return True + #logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + fan_dir=fan.get_fan_dir(1) + if fan_dir == 1: + fan_policy = fan_policy_f2b + else: + fan_policy = fan_policy_b2f + + #Decide fan duty by if any of sensors > fan_policy_single. + new_duty_cycle = fan_policy[0][0] + for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): + single_thm = thermal._get_thermal_node_val(x) + for y in range(0, len(fan_policy_single)): + if single_thm > fan_policy_single[y]: + if fan_policy[y+1][0] > new_duty_cycle: + new_duty_cycle = fan_policy[y+1][0] + logging.debug('INFO. Single thermal sensor %d with temp %d > %d , new_duty_cycle=%d', + x, single_thm, fan_policy_single[y], new_duty_cycle) + single_result = new_duty_cycle + + + #Find if current duty matched any of define duty. + #If not, set it to highest one. + cur_duty_cycle = fan.get_fan_duty_cycle() + for x in range(0, len(fan_policy)): + if cur_duty_cycle == fan_policy[x][0]: + break + if x == len(fan_policy) : + fan.set_fan_duty_cycle(fan_policy[0][0]) + cur_duty_cycle = max_duty + + #Decide fan duty by if sum of sensors falls into any of fan_policy{} + get_temp = thermal.get_thermal_temp() + new_duty_cycle = cur_duty_cycle + for x in range(0, len(fan_policy)): + y = len(fan_policy) - x -1 #checked from highest + if get_temp > fan_policy[y][1] and get_temp < fan_policy[y][2] : + new_duty_cycle= fan_policy[y][0] + logging.debug('INFO. Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + + sum_result = new_duty_cycle + if (sum_result>single_result): + new_duty_cycle = sum_result; + else: + new_duty_cycle = single_result + + logging.debug('INFO. Final duty_cycle=%d', new_duty_cycle) + if(new_duty_cycle != cur_duty_cycle): + fan.set_fan_duty_cycle(new_duty_cycle) + return True + +def handler(signum, frame): + fan = FanUtil() + logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) + monitor = accton_as7312_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_util.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_util.py new file mode 100755 index 000000000000..e2f058b4e37a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_util.py @@ -0,0 +1,648 @@ +#!/usr/bin/env python +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time +import os + +PROJECT_NAME = 'as7312_54x' +version = '0.1.0' +verbose = False +DEBUG = False +ARGS = [] +ALL_DEVICE = {} +DEVICE_NO = { + 'led': 5, + 'fan': 6, + 'thermal': 4, + 'psu': 2, + 'sfp': 54, + } +FORCE = 0 + +# logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +# logging.basicConfig(level=logging.INFO) + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global ARGS + global FORCE + + if len(sys.argv) < 2: + show_help() + + (options, ARGS) = getopt.getopt(sys.argv[1:], 'hdf', + ['help','debug', 'force']) + if DEBUG == True: + print options + print ARGS + print len(sys.argv) + + for (opt, arg) in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in ARGS: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'api': + do_sonic_platform_install() + elif arg == 'api_clean': + do_sonic_platform_clean() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(ARGS) != 2: + show_eeprom_help() + elif int(ARGS[1]) == 0 or int(ARGS[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(ARGS[1]) + return + elif arg == 'set': + if len(ARGS) < 3: + show_set_help() + else: + set_device(ARGS[1:]) + return + else: + show_help() + return 0 + + +def show_help(): + print __doc__ % {'scriptName': sys.argv[0].split('/')[-1]} + sys.exit(0) + + +def show_set_help(): + cmd = sys.argv[0].split('/')[-1] + ' ' + ARGS[0] + print cmd + ' [led|sfp|fan]' + print ' use "' + cmd + ' led 0-4 " to set led color' + print ' use "' + cmd + ' fan 0-100" to set fan duty percetage' + print ' use "' + cmd + ' sfp 1-48 {0|1}" to set sfp# tx_disable' + sys.exit(0) + + +def show_eeprom_help(): + cmd = sys.argv[0].split('/')[-1] + ' ' + ARGS[0] + print ' use "' + cmd + ' 1-54 " to dump sfp# eeprom' + sys.exit(0) + + +def my_log(txt): + if DEBUG == True: + print '[DBG]' + txt + return + + +def log_os_system(cmd, show): + logging.info('Run :' + cmd) + (status, output) = commands.getstatusoutput(cmd) + my_log(cmd + 'with result:' + str(status)) + my_log(' output:' + output) + if status: + logging.info('Failed :' + cmd) + if show: + print 'Failed :' + cmd + return (status, output) + + +def driver_check(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + +kos = [ + 'modprobe i2c_dev', + 'modprobe i2c_mux_pca954x force_deselect_on_exit=1', + 'modprobe accton_i2c_cpld', + 'modprobe ym2651y', + 'modprobe accton_as7312_54x_fan', + 'modprobe optoe', + 'modprobe accton_as7312_54x_leds', + 'modprobe accton_as7312_54x_psu', + ] + + +def driver_install(): + global FORCE + log_os_system('depmod', 1) + for i in range(0, len(kos)): + ret = log_os_system(kos[i], 1) + if ret[0] and FORCE == 0: + return status + return 0 + + +def driver_uninstall(): + global FORCE + for i in range(0, len(kos)): + rm = kos[-(i + 1)].replace('modprobe', 'modprobe -rq') + rm = rm.replace('insmod', 'rmmod') + lst = rm.split(' ') + if len(lst) > 3: + del lst[3] + rm = ' '.join(lst) + ret = log_os_system(rm, 1) + if ret[0] and FORCE == 0: + return ret[0] + return 0 + + +led_prefix = '/sys/class/leds/accton_' + PROJECT_NAME + '_led::' +hwmon_types = {'led': ['diag', 'fan', 'loc', 'psu1', 'psu2']} +hwmon_nodes = {'led': ['brightness']} +hwmon_prefix = {'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = { + 'fan': ['2-0066'], + 'thermal': ['3-0048', '3-0049', '3-004a', '3-004b'], + 'psu': ['10-0050', '11-0053'], + 'sfp': ['-0050'], + } +i2c_nodes = { + 'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'], + 'thermal': ['hwmon/hwmon*/temp1_input'], + 'psu': ['psu_present ', 'psu_power_good'], + 'sfp': ['module_present', 'module_tx_disable'], + } + +sfp_map = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71] + +qsfp_start = 48 + +mknod_common = [ + 'echo as7312_54x_fan 0x66 > /sys/bus/i2c/devices/i2c-2/new_device ', + 'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo as7312_54x_psu1 0x53 > /sys/bus/i2c/devices/i2c-11/new_device', + 'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-11/new_device', + 'echo as7312_54x_psu2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', + 'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', + 'echo as7312_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-4/new_device', + 'echo as7312_54x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo as7312_54x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-6/new_device'] + +mknod = [ + 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device',] +mknod = mknod + mknod_common + +mknod2 = [ + 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device',] + +mknod2 = mknod2 + mknod_common + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x70 is exist @ i2c-1 + tmp = "i2cget -y -f 0 0x70" + ret = log_os_system(tmp, 0) + if not ret[0]: + order = 1 + else: + order = 0 + return order + + +def device_install(): + global FORCE + + order = i2c_order_check() + # if 0x70 is not exist @i2c-1, use reversed bus order + if order: + for i in range(0, len(mknod2)): + # for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + (status, output) = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0, len(mknod)): + # for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + (status, output) = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(0, len(sfp_map)): + if i < qsfp_start: + (status, output) = \ + log_os_system('echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-' + + str(sfp_map[i]) + '/new_device', 1) + else: + (status, output) = \ + log_os_system('echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-' + + str(sfp_map[i]) + '/new_device', 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + for i in range(0, len(sfp_map)): + target = '/sys/bus/i2c/devices/i2c-' + str(sfp_map[i]) \ + + '/delete_device' + (status, output) = log_os_system('echo 0x50 > ' + target, 1) + if status: + print output + if FORCE == 0: + return status + + order = i2c_order_check() + if order : + nodelist = mknod2 + else: + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i + 1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + (status, output) = log_os_system(' '.join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + + +def system_ready(): + if driver_check() is False: + return False + if not device_exist(): + return False + return True + +PLATFORM_ROOT_PATH = '/usr/share/sonic/device' +PLATFORM_API2_WHL_FILE_PY3 ='sonic_platform-1.0-py3-none-any.whl' +def do_sonic_platform_install(): + device_path = "{}{}{}{}".format(PLATFORM_ROOT_PATH, '/x86_64-accton_', PROJECT_NAME, '-r0') + SONIC_PLATFORM_BSP_WHL_PKG_PY3 = "/".join([device_path, PLATFORM_API2_WHL_FILE_PY3]) + + #Check API2.0 on py whl file + status, output = log_os_system("pip3 show sonic-platform > /dev/null 2>&1", 0) + if status: + if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_PY3): + status, output = log_os_system("pip3 install "+ SONIC_PLATFORM_BSP_WHL_PKG_PY3, 1) + if status: + print "Error: Failed to install {}".format(PLATFORM_API2_WHL_FILE_PY3) + return status + else: + print "Successfully installed {} package".format(PLATFORM_API2_WHL_FILE_PY3) + else: + print('{} is not found'.format(PLATFORM_API2_WHL_FILE_PY3)) + else: + print('{} has installed'.format(PLATFORM_API2_WHL_FILE_PY3)) + + return + +def do_sonic_platform_clean(): + status, output = log_os_system("pip3 show sonic-platform > /dev/null 2>&1", 0) + if status: + print('{} does not install, not need to uninstall'.format(PLATFORM_API2_WHL_FILE_PY3)) + + else: + status, output = log_os_system("pip3 uninstall sonic-platform -y", 0) + if status: + print('Error: Failed to uninstall {}'.format(PLATFORM_API2_WHL_FILE_PY3)) + return status + else: + print('{} is uninstalled'.format(PLATFORM_API2_WHL_FILE_PY3)) + + return + +def do_install(): + print 'Checking system....' + if driver_check() is False: + print 'No driver, installing....' + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper() + ' drivers detected....' + if not device_exist(): + print 'No device, installing....' + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper() + ' devices detected....' + do_sonic_platform_install() + + return + + +def do_uninstall(): + print 'Checking system....' + if not device_exist(): + print PROJECT_NAME.upper() + ' has no device installed....' + else: + print 'Removing device....' + status = device_uninstall() + if status and FORCE == 0: + return status + + if driver_check() is False: + print PROJECT_NAME.upper() + ' has no driver installed....' + else: + print 'Removing installed driver....' + status = driver_uninstall() + if status and FORCE == 0: + return status + + do_sonic_platform_clean() + + return None + + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key] = {} + for i in range(0, DEVICE_NO[key]): + ALL_DEVICE[key][key + str(i + 1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0, len(buses)): + for j in range(0, len(nodes)): + if 'fan' == key: + for k in range(0, DEVICE_NO[key]): + node = key + str(k + 1) + path = i2c_prefix + buses[i] + '/fan' + str(k + + 1) + '_' + nodes[j] + my_log(node + ': ' + path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0, DEVICE_NO[key]): + if k in range(24) or k in range(48, 52): + fmt = i2c_prefix + '5-0062/{0}_{1}' + else: + fmt = i2c_prefix + '6-0064/{0}_{1}' + node = key + str(k + 1) + path = fmt.format(nodes[j], k + 1) + my_log(node + ': ' + path) + ALL_DEVICE[key][node].append(path) + else: + node = key + str(i + 1) + path = i2c_prefix + buses[i] + '/' + nodes[j] + my_log(node + ': ' + path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0, len(itypes)): + for j in range(0, len(nodes)): + node = key + '_' + itypes[i] + path = hwmon_prefix[key] + itypes[i] + '/' + nodes[j] + my_log(node + ': ' + path) + ALL_DEVICE[key][key + str(i + 1)].append(path) + + # show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print i + ': ' + for j in sorted(ALL_DEVICE[i].keys()): + print ' ' + j + for k in ALL_DEVICE[i][j]: + print ' ' + ' ' + k + return + + +def show_eeprom(index): + if system_ready() is False: + print('Systems not ready.') + print('Please install first!') + return + + if len(ALL_DEVICE) == 0: + devices_info() + node = ALL_DEVICE['sfp']['sfp' + str(index)][0] + node = node.replace(node.split('/')[-1], 'sfp_eeprom') + + # check if got hexdump command in current environment + (ret, log) = log_os_system('which hexdump', 0) + (ret, log2) = log_os_system('which busybox hexdump', 0) + if log: + hex_cmd = 'hexdump' + elif log2: + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ':' + (ret, log) = log_os_system('cat ' + node + '| ' + hex_cmd + ' -C', + 1) + if ret == 0: + print log + else: + print( '**********device no found**********') + return + + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready() is False: + print('System is not ready.') + print('Please install first!') + return + + if not ALL_DEVICE: + devices_info() + + if args[0] == 'led': + if int(args[1]) > 4: + show_set_help() + return + + # print ALL_DEVICE['led'] + for i in range(0, len(ALL_DEVICE['led'])): + for k in ALL_DEVICE['led']['led' + str(i + 1)]: + ret = log_os_system('echo ' + args[1] + ' >' + k, 1) + if ret[0]: + return ret[0] + elif args[0] == 'fan': + if int(args[1]) > 100: + show_set_help() + return + + # print ALL_DEVICE['fan'] + # fan1~6 is all fine, all fan share same setting + + node = ALL_DEVICE['fan']['fan1'][0] + node = node.replace(node.split('/')[-1], + 'fan_duty_cycle_percentage') + (ret, log) = log_os_system('cat ' + node, 1) + if ret == 0: + print 'Previous fan duty: ' + log.strip() + '%' + ret = log_os_system('echo ' + args[1] + ' >' + node, 1) + if ret[0] == 0: + print 'Current fan duty: ' + args[1] + '%' + return ret + elif args[0] == 'sfp': + if int(args[1]) > qsfp_start or int(args[1]) == 0: + show_set_help() + return + if len(args) < 2: + show_set_help() + return + + if int(args[2]) > 1: + show_set_help() + return + + # print ALL_DEVICE[args[0]] + + for i in range(len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0] + str(args[1])]: + if j.find('tx_disable') != -1: + ret = log_os_system('echo ' + args[2] + ' >' + j, 1) + if ret[0]: + return ret[0] + + return + + +# get digits inside a string. +# Ex: get 31 from "sfp31" +def get_value(i): + digit = re.findall('\d+', i) + return int(digit[0]) + + +def device_traversal(): + if system_ready() is False: + print "System is not ready." + print 'Please install first!' + return + + if not ALL_DEVICE: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print '============================================' + print i.upper() + ': ' + print '============================================' + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print ' ' + j + ':', + for k in ALL_DEVICE[i][j]: + (ret, log) = log_os_system('cat ' + k, 0) + func = k.split('/')[-1].strip() + func = re.sub(j + '_', '', func, 1) + func = re.sub(i.lower() + '_', '', func, 1) + if ret == 0: + print func + '=' + log + ' ', + else: + print func + '=' + 'X' + ' ', + print + print '----------------------------------------------------------------' + print + return + + +def device_exist(): + ret1 = log_os_system('ls ' + i2c_prefix + '*0070', 0) + ret2 = log_os_system('ls ' + i2c_prefix + 'i2c-2', 0) + return not (ret1[0] or ret2[0]) + + +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/classes/fanutil.py new file mode 100755 index 000000000000..18802c803638 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/classes/fanutil.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 2/27/2018: Roy Lee modify for as7312_54x +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + #BASE_VAL_PATH = '/sys/devices/platform/as5712_54x_fan/{0}' + BASE_VAL_PATH = '/sys/bus/i2c/devices/2-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/2-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + + _fan_to_device_path_mapping = {} + logger = logging.getLogger(__name__) + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + self.logger.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + self.logger.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self, log_level=logging.INFO): + ch = logging.StreamHandler() + ch.setLevel(log_level) + self.logger.addHandler(ch) + + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + self.logger.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/classes/thermalutil.py new file mode 100755 index 000000000000..ddc3521fafac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/classes/thermalutil.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 2/27/2018: Roy Lee modify for as7312_54x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + Value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['3', '48'], + THERMAL_NUM_2_IDX: ['3', '49'], + THERMAL_NUM_3_IDX: ['3', '4a'], + } + + logger = logging.getLogger(__name__) + def __init__(self, log_level=logging.INFO): + ch = logging.StreamHandler() + ch.setLevel(log_level) + self.logger.addHandler(ch) + + thermal_path = self.BASE_VAL_PATH + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/Makefile new file mode 100755 index 000000000000..488fdb321cac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_i2c_cpld.o \ + accton_as7312_54x_fan.o accton_as7312_54x_leds.o \ + accton_as7312_54x_psu.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_fan.c new file mode 100755 index 000000000000..8764ec8a3176 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_fan.c @@ -0,0 +1,815 @@ +/* + * A hwmon driver for the Accton as7312 54x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7312_54x_fan" + +#define NUM_THERMAL_SENSORS (3) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a} + +#define IN +#define OUT + +static struct as7312_54x_fan_data *as7312_54x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7312_54x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as7312_54x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7312_54x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7312_54x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7312_54x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0) + return -EINVAL; + + value = (value > FAN_MAX_DUTY_CYCLE)? FAN_MAX_DUTY_CYCLE : value; + + as7312_54x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7312_54x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + OUT int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as7312_54x_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7312_54x_fan_data *data = as7312_54x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7312_54x_fan_group = { + .attrs = as7312_54x_fan_attributes, +}; + +static struct as7312_54x_fan_data *as7312_54x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7312_54x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7312_54x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7312_54x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7312_54x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7312_54x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->enable = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7312_54x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7312_54x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7312_54x_fan_remove(struct i2c_client *client) +{ + struct as7312_54x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7312_54x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7312_54x_fan_id[] = { + { "as7312_54x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7312_54x_fan_id); + +static struct i2c_driver as7312_54x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7312_54x_fan_probe, + .remove = as7312_54x_fan_remove, + .id_table = as7312_54x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7312_54x_fan_init(void) +{ + return i2c_add_driver(&as7312_54x_fan_driver); +} + +static void __exit as7312_54x_fan_exit(void) +{ + i2c_del_driver(&as7312_54x_fan_driver); +} + +module_init(as7312_54x_fan_init); +module_exit(as7312_54x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7312_54x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_leds.c new file mode 100644 index 000000000000..f53716440107 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_leds.c @@ -0,0 +1,437 @@ +/* + * A LED driver for the accton_as7312_54x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as7312_54x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as7312_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "accton_as7312_54x_led" + +struct accton_as7312_54x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct accton_as7312_54x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7312_54x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as7312_54x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7312_54x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as7312_54x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7312_54x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as7312_54x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7312_54x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as7312_54x_led_diag_get(struct led_classdev *cdev) +{ + accton_as7312_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as7312_54x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7312_54x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as7312_54x_led_loc_get(struct led_classdev *cdev) +{ + accton_as7312_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as7312_54x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7312_54x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev accton_as7312_54x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as7312_54x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_diag_set, + .brightness_get = accton_as7312_54x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "accton_as7312_54x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_loc_set, + .brightness_get = accton_as7312_54x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "accton_as7312_54x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as7312_54x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as7312_54x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7312_54x_led_auto_set, + .brightness_get = accton_as7312_54x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as7312_54x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + led_classdev_suspend(&accton_as7312_54x_leds[i]); + } + + return 0; +} + +static int accton_as7312_54x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + led_classdev_resume(&accton_as7312_54x_leds[i]); + } + + return 0; +} + +static int accton_as7312_54x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7312_54x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7312_54x_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7312_54x_leds[i]); + } + } + + return ret; +} + +static int accton_as7312_54x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7312_54x_leds); i++) { + led_classdev_unregister(&accton_as7312_54x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7312_54x_led_driver = { + .probe = accton_as7312_54x_led_probe, + .remove = accton_as7312_54x_led_remove, + .suspend = accton_as7312_54x_led_suspend, + .resume = accton_as7312_54x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7312_54x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7312_54x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7312_54x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7312_54x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7312_54x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7312_54x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7312_54x_led_driver); + kfree(ledctl); +} + +module_init(accton_as7312_54x_led_init); +module_exit(accton_as7312_54x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7312_54x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_psu.c new file mode 100644 index 000000000000..4646224ef903 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_psu.c @@ -0,0 +1,277 @@ +/* + * An hwmon driver for accton as7312_54x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as7312_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7312_54x_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7312_54x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[9]; /* Model name, read from eeprom */ +}; + +static struct as7312_54x_psu_data *as7312_54x_psu_update_device(struct device *dev); + +enum as7312_54x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7312_54x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7312_54x_psu_data *data = as7312_54x_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7312_54x_psu_data *data = as7312_54x_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as7312_54x_psu_group = { + .attrs = as7312_54x_psu_attributes, +}; + +static int as7312_54x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7312_54x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7312_54x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7312_54x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7312_54x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7312_54x_psu_remove(struct i2c_client *client) +{ + struct as7312_54x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7312_54x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7312_54x_psu1, + as7312_54x_psu2 +}; + +static const struct i2c_device_id as7312_54x_psu_id[] = { + { "as7312_54x_psu1", as7312_54x_psu1 }, + { "as7312_54x_psu2", as7312_54x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7312_54x_psu_id); + +static struct i2c_driver as7312_54x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7312_54x_psu", + }, + .probe = as7312_54x_psu_probe, + .remove = as7312_54x_psu_remove, + .id_table = as7312_54x_psu_id, + .address_list = normal_i2c, +}; + +static int as7312_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7312_54x_psu_data *as7312_54x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as7312_54x update\n"); + + /* Read psu status */ + status = as7312_54x_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as7312_54x_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as7312_54x_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7312_54x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_sfp.c new file mode 100644 index 000000000000..921d9f892cac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_as7312_54x_sfp.c @@ -0,0 +1,1972 @@ +/* + * SFP driver for accton as7312_54x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "as7312_54x_sfp" /* Platform dependent */ + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) +#define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else +#define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_PORT 54 +#define SFP_PORT_MAX 48 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +#define MULTIPAGE_SUPPORT 1 + +#if (MULTIPAGE_SUPPORT == 1) +/* fundamental unit of addressing for SFF_8472/SFF_8436 */ +#define SFF_8436_PAGE_SIZE 128 +/* + * The current 8436 (QSFP) spec provides for only 4 supported + * pages (pages 0-3). + * This driver is prepared to support more, but needs a register in the + * EEPROM to indicate how many pages are supported before it is safe + * to implement more pages in the driver. + */ +#define SFF_8436_SPECED_PAGES 4 +#define SFF_8436_EEPROM_SIZE ((1 + SFF_8436_SPECED_PAGES) * SFF_8436_PAGE_SIZE) +#define SFF_8436_EEPROM_UNPAGED_SIZE (2 * SFF_8436_PAGE_SIZE) +/* + * The current 8472 (SFP) spec provides for only 3 supported + * pages (pages 0-2). + * This driver is prepared to support more, but needs a register in the + * EEPROM to indicate how many pages are supported before it is safe + * to implement more pages in the driver. + */ +#define SFF_8472_SPECED_PAGES 3 +#define SFF_8472_EEPROM_SIZE ((3 + SFF_8472_SPECED_PAGES) * SFF_8436_PAGE_SIZE) +#define SFF_8472_EEPROM_UNPAGED_SIZE (4 * SFF_8436_PAGE_SIZE) + +/* a few constants to find our way around the EEPROM */ +#define SFF_8436_PAGE_SELECT_REG 0x7F +#define SFF_8436_PAGEABLE_REG 0x02 +#define SFF_8436_NOT_PAGEABLE (1<<2) +#define SFF_8472_PAGEABLE_REG 0x40 +#define SFF_8472_PAGEABLE (1<<4) + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = SFF_8436_PAGE_SIZE; + +/* + * specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; + +typedef enum qsfp_opcode { + QSFP_READ_OP = 0, + QSFP_WRITE_OP = 1 +} qsfp_opcode_e; +#endif + +/* Platform dependent +++ */ +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x62 +#define I2C_ADDR_CPLD3 0x64 + +#define CPLD3_OFFSET_QSFP_MOD_RST 0x17 +/* Platform dependent --- */ +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL, + SFP_MOD_RST +}; + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static SENSOR_DEVICE_ATTR(sfp_mod_rst, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, SFP_MOD_RST); + +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + &sensor_dev_attr_sfp_mod_rst.dev_attr.attr, + NULL +}; + +/* SFP msa attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); +static struct attribute *sfp_msa_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { + as7312_54x_port1, as7312_54x_port2, as7312_54x_port3, as7312_54x_port4, + as7312_54x_port5, as7312_54x_port6, as7312_54x_port7, as7312_54x_port8, + as7312_54x_port9, as7312_54x_port10, as7312_54x_port11, as7312_54x_port12, + as7312_54x_port13, as7312_54x_port14, as7312_54x_port15, as7312_54x_port16, + as7312_54x_port17, as7312_54x_port18, as7312_54x_port19, as7312_54x_port20, + as7312_54x_port21, as7312_54x_port22, as7312_54x_port23, as7312_54x_port24, + as7312_54x_port25, as7312_54x_port26, as7312_54x_port27, as7312_54x_port28, + as7312_54x_port29, as7312_54x_port30, as7312_54x_port31, as7312_54x_port32, + as7312_54x_port33, as7312_54x_port34, as7312_54x_port35, as7312_54x_port36, + as7312_54x_port37, as7312_54x_port38, as7312_54x_port39, as7312_54x_port40, + as7312_54x_port41, as7312_54x_port42, as7312_54x_port43, as7312_54x_port44, + as7312_54x_port45, as7312_54x_port46, as7312_54x_port47, as7312_54x_port48, + as7312_54x_port49, as7312_54x_port52, as7312_54x_port50, as7312_54x_port53, + as7312_54x_port51, as7312_54x_port54 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { + I2C_DEV_ID(as7312_54x_port1), + I2C_DEV_ID(as7312_54x_port2), + I2C_DEV_ID(as7312_54x_port3), + I2C_DEV_ID(as7312_54x_port4), + I2C_DEV_ID(as7312_54x_port5), + I2C_DEV_ID(as7312_54x_port6), + I2C_DEV_ID(as7312_54x_port7), + I2C_DEV_ID(as7312_54x_port8), + I2C_DEV_ID(as7312_54x_port9), + I2C_DEV_ID(as7312_54x_port10), + I2C_DEV_ID(as7312_54x_port11), + I2C_DEV_ID(as7312_54x_port12), + I2C_DEV_ID(as7312_54x_port13), + I2C_DEV_ID(as7312_54x_port14), + I2C_DEV_ID(as7312_54x_port15), + I2C_DEV_ID(as7312_54x_port16), + I2C_DEV_ID(as7312_54x_port17), + I2C_DEV_ID(as7312_54x_port18), + I2C_DEV_ID(as7312_54x_port19), + I2C_DEV_ID(as7312_54x_port20), + I2C_DEV_ID(as7312_54x_port21), + I2C_DEV_ID(as7312_54x_port22), + I2C_DEV_ID(as7312_54x_port23), + I2C_DEV_ID(as7312_54x_port24), + I2C_DEV_ID(as7312_54x_port25), + I2C_DEV_ID(as7312_54x_port26), + I2C_DEV_ID(as7312_54x_port27), + I2C_DEV_ID(as7312_54x_port28), + I2C_DEV_ID(as7312_54x_port29), + I2C_DEV_ID(as7312_54x_port30), + I2C_DEV_ID(as7312_54x_port31), + I2C_DEV_ID(as7312_54x_port32), + I2C_DEV_ID(as7312_54x_port33), + I2C_DEV_ID(as7312_54x_port34), + I2C_DEV_ID(as7312_54x_port35), + I2C_DEV_ID(as7312_54x_port36), + I2C_DEV_ID(as7312_54x_port37), + I2C_DEV_ID(as7312_54x_port38), + I2C_DEV_ID(as7312_54x_port39), + I2C_DEV_ID(as7312_54x_port40), + I2C_DEV_ID(as7312_54x_port41), + I2C_DEV_ID(as7312_54x_port42), + I2C_DEV_ID(as7312_54x_port43), + I2C_DEV_ID(as7312_54x_port44), + I2C_DEV_ID(as7312_54x_port45), + I2C_DEV_ID(as7312_54x_port46), + I2C_DEV_ID(as7312_54x_port47), + I2C_DEV_ID(as7312_54x_port48), + I2C_DEV_ID(as7312_54x_port49), + I2C_DEV_ID(as7312_54x_port50), + I2C_DEV_ID(as7312_54x_port51), + I2C_DEV_ID(as7312_54x_port52), + I2C_DEV_ID(as7312_54x_port53), + I2C_DEV_ID(as7312_54x_port54), + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); +/* Platform dependent --- */ + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[6]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss + 3 => device id + 4 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 5 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +#if (MULTIPAGE_SUPPORT == 1) + struct i2c_client *ddm_client; /* dummy client instance for 0xA2 */ +#endif +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct qsfp_data *qsfp; + + struct i2c_client *client; +#if (MULTIPAGE_SUPPORT == 1) + int use_smbus; + u8 *writebuf; + unsigned write_max; +#endif +}; + +#if (MULTIPAGE_SUPPORT == 1) +static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, + char *buf, loff_t off, size_t len, qsfp_opcode_e opcode); +#endif +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +/* Platform dependent +++ */ +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + int i = 0, j = 0, status = -1; + u8 reg; + unsigned short cpld_addr; + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + data->present = 0; + + /* Read present status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + cpld_addr = I2C_ADDR_CPLD2 + i*2; + reg = 0x9+j; + status = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); + data->present |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* Read present status of port 49-52(QSFP port) */ + cpld_addr = I2C_ADDR_CPLD2; + reg = 0x18; + status = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + else { + data->present |= (u64)(status & 0xF) << SFP_PORT_MAX; + } + + /* Read present status of port 53-54(QSFP port) */ + cpld_addr = I2C_ADDR_CPLD3; + reg = 0x18; + status = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + else { + data->present |= (u64)(status & 0x3) << 52; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static struct sfp_port_data* sfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0, j = 0; + int status = -1; + + if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { + return data; + } + + DEBUG_PRINT("Starting as7312_54x sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->msa->valid = 0; + memset(data->msa->status, 0, sizeof(data->msa->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 9; j++) { + u8 reg; + unsigned short cpld_addr; + reg = 0xc+j; + cpld_addr = I2C_ADDR_CPLD2 + i*2; + + status = accton_i2c_cpld_read(cpld_addr, reg); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + data->msa->valid = 1; + data->msa->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + unsigned short cpld_addr = 0; + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long disable; + int error; + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_set_tx_disable(dev, da, buf, count); + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + if(data->port < 24) { + cpld_addr = I2C_ADDR_CPLD2; + cpld_reg = 0xF + data->port / 8; + cpld_bit = 1 << (data->port % 8); + } + else { /* port 24 ~ 48 */ + cpld_addr = I2C_ADDR_CPLD3; + cpld_reg = 0xF + (data->port - 24) / 8; + cpld_bit = 1 << (data->port % 8); + } + + /* Read current status */ + cpld_val = accton_i2c_cpld_read(cpld_addr, cpld_reg); + + /* Update tx_disable status */ + if (disable) { + data->msa->status[1] |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->msa->status[1] &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + accton_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); + mutex_unlock(&data->update_lock); + return count; +} + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = sfp_update_present(client); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + return (data->present & BIT_INDEX(data->port)) ? 0 : 1; /* Platform dependent */ +} + +/* Platform dependent +++ */ +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if (PRESENT_ALL == attr->index) { + int i; + u8 values[7] = {0}; + struct sfp_port_data *data = sfp_update_present(client); + + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = ~(u8)(data->present >> (i * 8)); + } + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6] & 0x3F); + } + else { + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + /* PRESENT */ + return sprintf(buf, "%d\n", present); + } +} +/* Platform dependent --- */ + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + DEBUG_PRINT("Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + int port_bit; + int status = -EINVAL; + u8 cpld_addr[] = {I2C_ADDR_CPLD2, I2C_ADDR_CPLD3}; + + /* Low power mode is not supported for SFP ports(1-48) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + mutex_lock(&data->update_lock); + + port_bit = data->port - SFP_PORT_MAX; + cpld_val = accton_i2c_cpld_read(cpld_addr[port_bit/4], CPLD3_OFFSET_QSFP_MOD_RST); + + pr_err("[ROY]%s#%d, %x from %x\n", __func__, __LINE__, cpld_val, cpld_addr[port_bit/4]); + + cpld_val = cpld_val & 0x0F; + cpld_val = cpld_val & BIT_INDEX(port_bit%4); + + pr_err("[ROY]%s#%d, %x of bit %d\n", __func__, __LINE__, cpld_val, port_bit); + + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", cpld_val>>(port_bit%4)); + + mutex_unlock(&data->update_lock); + + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_val = 0; + long reset; + int error, port_bit; + u8 cpld_addr[] = {I2C_ADDR_CPLD2, I2C_ADDR_CPLD3}; + + pr_err("[ROY]%s#%d, port:%d\n", __func__, __LINE__, data->port); + + /* Tx disable is not supported for QSFP ports(49-54) */ + if (data->port < SFP_PORT_MAX) { + return -EINVAL; + } + port_bit = data->port - SFP_PORT_MAX; + error = kstrtol(buf, 10, &reset); + + pr_err("[ROY]%s#%d, %s == %d\n", __func__, __LINE__, buf, error); + if (error) { + return error; + } + mutex_lock(&data->update_lock); + + cpld_val = accton_i2c_cpld_read(cpld_addr[port_bit/4], CPLD3_OFFSET_QSFP_MOD_RST); + pr_err("[ROY]%s#%d, %x\n", __func__, __LINE__, cpld_val); + /* Update lp_mode status */ + if (reset) + { + cpld_val |= BIT_INDEX(port_bit%4); + } + else + { + cpld_val &= ~BIT_INDEX(port_bit%4); + } + pr_err("[ROY]%s#%d, %x to %x\n", __func__, __LINE__, cpld_val, cpld_addr[port_bit/4]); + + accton_i2c_cpld_write(cpld_addr[port_bit/4], CPLD3_OFFSET_QSFP_MOD_RST, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + int present; + u8 val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENXIO; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + switch (attr->index) { + case TX_FAULT: + val = !!(data->qsfp->status[2] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + case TX_DISABLE: + val = data->qsfp->status[1] & 0xF; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + case RX_LOS: + val = !!(data->qsfp->status[0] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); + break; + default: + break; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (!status) { + /* port is not present */ + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + mutex_lock(&data->update_lock); + + if (attr->index == TX_DISABLE) { + if (disable) { + data->qsfp->status[1] |= 0xF; + } + else { + data->qsfp->status[1] &= ~0xF; + } + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +/* Platform dependent +++ */ +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_show_tx_rx_status(dev, da, buf); + } + + data = sfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + if(attr->index == RX_LOS_ALL) { + int i = 0; + u8 values[6] = {0}; + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = (u8)(data->msa->status[2] >> (i * 8)); + } + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + case RX_LOS: + index = 2; + break; + default: + return 0; + } + + val = (data->msa->status[index] & BIT_INDEX(data->port)) ? 1 : 0; + return sprintf(buf, "%d\n", val); +} +/* Platform dependent --- */ +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, command, *data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return 1; +#endif + + +} + +#if (MULTIPAGE_SUPPORT == 0) +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} +#endif + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + +#if (MULTIPAGE_SUPPORT == 1) + return sfp_port_read_write(data, buf, off, count, QSFP_WRITE_OP); +#else + return sfp_port_write(data, buf, off, count); +#endif +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return status; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + status = 1; + +abort: + return status; +#endif +} + +#if (MULTIPAGE_SUPPORT == 1) +/*-------------------------------------------------------------------------*/ +/* + * This routine computes the addressing information to be used for + * a given r/w request. + * + * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), + * the page, and the offset. + * + * Handles both SFP and QSFP. + * For SFP, offset 0-255 are on client[0], >255 is on client[1] + * Offset 256-383 are on the lower half of client[1] + * Pages are accessible on the upper half of client[1]. + * Offset >383 are in 128 byte pages mapped into the upper half + * + * For QSFP, all offsets are on client[0] + * offset 0-127 are on the lower half of client[0] (no paging) + * Pages are accessible on the upper half of client[1]. + * Offset >127 are in 128 byte pages mapped into the upper half + * + * Callers must not read/write beyond the end of a client or a page + * without recomputing the client/page. Hence offset (within page) + * plus length must be less than or equal to 128. (Note that this + * routine does not have access to the length of the call, hence + * cannot do the validity check.) + * + * Offset within Lower Page 00h and Upper Page 00h are not recomputed + */ +static uint8_t sff_8436_translate_offset(struct sfp_port_data *port_data, + loff_t *offset, struct i2c_client **client) +{ + unsigned page = 0; + + *client = port_data->client; + + /* if SFP style, offset > 255, shift to i2c addr 0x51 */ + if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { + if (*offset > 255) { + /* like QSFP, but shifted to client[1] */ + *client = port_data->msa->ddm_client; + *offset -= 256; + } + } + + /* + * if offset is in the range 0-128... + * page doesn't matter (using lower half), return 0. + * offset is already correct (don't add 128 to get to paged area) + */ + if (*offset < SFF_8436_PAGE_SIZE) + return page; + + /* note, page will always be positive since *offset >= 128 */ + page = (*offset >> 7)-1; + /* 0x80 places the offset in the top half, offset is last 7 bits */ + *offset = SFF_8436_PAGE_SIZE + (*offset & 0x7f); + + return page; /* note also returning client and offset */ +} + +static ssize_t sff_8436_eeprom_read(struct sfp_port_data *port_data, + struct i2c_client *client, + char *buf, unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + u8 msgbuf[2]; + unsigned long timeout, read_time; + int status, i; + + memset(msg, 0, sizeof(msg)); + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* + * When we have a better choice than SMBus calls, use a + * combined I2C message. Write address; then read up to + * io_limit data bytes. msgbuf is u8 and will cast to our + * needs. + */ + i = 0; + msgbuf[i++] = offset; + + msg[0].addr = client->addr; + msg[0].buf = msgbuf; + msg[0].len = i; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_read_i2c_block_data(client, offset, + count, buf); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; + if (count == 2) + buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_read_byte_data(client, offset); + if (status >= 0) { + buf[0] = status; + status = count; + } + break; + default: + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + status = count; + } + + dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) /* happy path */ + return count; + + if (status == -ENXIO) /* no module present */ + return status; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t sff_8436_eeprom_write(struct sfp_port_data *port_data, + struct i2c_client *client, + const char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page_start; + int i = 0; + + /* write max is at most a page + * (In this driver, write_max is actually one byte!) + */ + if (count > port_data->write_max) + count = port_data->write_max; + + /* shorten count if necessary to avoid crossing page boundary */ + next_page_start = roundup(offset + 1, SFF_8436_PAGE_SIZE); + if (offset + count > next_page_start) + count = next_page_start - offset; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* If we'll use I2C calls for I/O, set up the message */ + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = port_data->writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + break; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + break; + case I2C_SMBUS_WORD_DATA: + if (count == 2) { + status = i2c_smbus_write_word_data(client, + offset, (u16)((buf[0])|(buf[1] << 8))); + } else { + /* count = 1 */ + status = i2c_smbus_write_byte_data(client, + offset, buf[0]); + } + if (status == 0) + status = count; + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_write_byte_data(client, offset, + buf[0]); + if (status == 0) + status = count; + break; + default: + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + break; + } + + dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", + count, offset, (long int) status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + + +static ssize_t sff_8436_eeprom_update_client(struct sfp_port_data *port_data, + char *buf, loff_t off, + size_t count, qsfp_opcode_e opcode) +{ + struct i2c_client *client; + ssize_t retval = 0; + u8 page = 0; + loff_t phy_offset = off; + int ret = 0; + + page = sff_8436_translate_offset(port_data, &phy_offset, &client); + + dev_dbg(&client->dev, + "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", + off, page, phy_offset, (long int) count, opcode); + if (page > 0) { + ret = sff_8436_eeprom_write(port_data, client, &page, + SFF_8436_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_dbg(&client->dev, + "Write page register for page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + + while (count) { + ssize_t status; + + if (opcode == QSFP_READ_OP) { + status = sff_8436_eeprom_read(port_data, client, + buf, phy_offset, count); + } else { + status = sff_8436_eeprom_write(port_data, client, + buf, phy_offset, count); + } + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + phy_offset += status; + count -= status; + retval += status; + } + + + if (page > 0) { + /* return the page register to page 0 (why?) */ + page = 0; + ret = sff_8436_eeprom_write(port_data, client, &page, + SFF_8436_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_err(&client->dev, + "Restore page register to page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + return retval; +} + + +/* + * Figure out if this access is within the range of supported pages. + * Note this is called on every access because we don't know if the + * module has been replaced since the last call. + * If/when modules support more pages, this is the routine to update + * to validate and allow access to additional pages. + * + * Returns updated len for this access: + * - entire access is legal, original len is returned. + * - access begins legal but is too long, len is truncated to fit. + * - initial offset exceeds supported pages, return -EINVAL + */ +static ssize_t sff_8436_page_legal(struct sfp_port_data *port_data, + loff_t off, size_t len) +{ + struct i2c_client *client = port_data->client; + u8 regval; + int status; + size_t maxlen; + + if (off < 0) return -EINVAL; + if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { + /* SFP case */ + if ((off + len) <= 256) return len; + /* if no pages needed, we're good */ + //if ((off + len) <= SFF_8472_EEPROM_UNPAGED_SIZE) return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= SFF_8472_EEPROM_SIZE) return -EINVAL; + + /* Check if ddm is supported */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF8472_DIAG_MON_TYPE_ADDR, 1); + if (status < 0) return status; /* error out (no module?) */ + if (!(regval & SFF8472_DIAG_MON_TYPE_DDM_MASK)) { + if (off >= 256) return -EINVAL; + maxlen = 256 - off; + } + else { + /* in between, are pages supported? */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF_8472_PAGEABLE_REG, 1); + if (status < 0) return status; /* error out (no module?) */ + if (regval & SFF_8472_PAGEABLE) { + /* Pages supported, trim len to the end of pages */ + maxlen = SFF_8472_EEPROM_SIZE - off; + } else { + /* pages not supported, trim len to unpaged size */ + if (off >= SFF_8472_EEPROM_UNPAGED_SIZE) return -EINVAL; + maxlen = SFF_8472_EEPROM_UNPAGED_SIZE - off; + } + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, SFP, off %lld len %ld\n", + off, (long int) len); + } + else if (port_data->driver_type == DRIVER_TYPE_QSFP) { + /* QSFP case */ + /* if no pages needed, we're good */ + if ((off + len) <= SFF_8436_EEPROM_UNPAGED_SIZE) return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= SFF_8436_EEPROM_SIZE) return -EINVAL; + /* in between, are pages supported? */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF_8436_PAGEABLE_REG, 1); + if (status < 0) return status; /* error out (no module?) */ + if (regval & SFF_8436_NOT_PAGEABLE) { + /* pages not supported, trim len to unpaged size */ + if (off >= SFF_8436_EEPROM_UNPAGED_SIZE) return -EINVAL; + maxlen = SFF_8436_EEPROM_UNPAGED_SIZE - off; + } else { + /* Pages supported, trim len to the end of pages */ + maxlen = SFF_8436_EEPROM_SIZE - off; + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, QSFP, off %lld len %ld\n", + off, (long int) len); + } + else { + return -EINVAL; + } + return len; +} + + +static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, + char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) +{ + struct i2c_client *client = port_data->client; + int chunk; + int status = 0; + ssize_t retval; + size_t pending_len = 0, chunk_len = 0; + loff_t chunk_offset = 0, chunk_start_offset = 0; + + if (unlikely(!len)) + return len; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&port_data->update_lock); + + /* + * Confirm this access fits within the device suppored addr range + */ + len = sff_8436_page_legal(port_data, off, len); + if (len < 0) { + status = len; + goto err; + } + + /* + * For each (128 byte) chunk involved in this request, issue a + * separate call to sff_eeprom_update_client(), to + * ensure that each access recalculates the client/page + * and writes the page register as needed. + * Note that chunk to page mapping is confusing, is different for + * QSFP and SFP, and never needs to be done. Don't try! + */ + pending_len = len; /* amount remaining to transfer */ + retval = 0; /* amount transferred */ + for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { + + /* + * Compute the offset and number of bytes to be read/write + * + * 1. start at offset 0 (within the chunk), and read/write + * the entire chunk + * 2. start at offset 0 (within the chunk) and read/write less + * than entire chunk + * 3. start at an offset not equal to 0 and read/write the rest + * of the chunk + * 4. start at an offset not equal to 0 and read/write less than + * (end of chunk - offset) + */ + chunk_start_offset = chunk * SFF_8436_PAGE_SIZE; + + if (chunk_start_offset < off) { + chunk_offset = off; + if ((off + pending_len) < (chunk_start_offset + + SFF_8436_PAGE_SIZE)) + chunk_len = pending_len; + else + chunk_len = (chunk+1)*SFF_8436_PAGE_SIZE - off;/*SFF_8436_PAGE_SIZE - off;*/ + } else { + chunk_offset = chunk_start_offset; + if (pending_len > SFF_8436_PAGE_SIZE) + chunk_len = SFF_8436_PAGE_SIZE; + else + chunk_len = pending_len; + } + + dev_dbg(&client->dev, + "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", + off, (long int) len, chunk_start_offset, chunk_offset, + (long int) chunk_len, (long int) pending_len); + + /* + * note: chunk_offset is from the start of the EEPROM, + * not the start of the chunk + */ + status = sff_8436_eeprom_update_client(port_data, buf, + chunk_offset, chunk_len, opcode); + if (status != chunk_len) { + /* This is another 'no device present' path */ + dev_dbg(&client->dev, + "sff_8436_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", + chunk, chunk_offset, (long int) chunk_len, status); + goto err; + } + buf += status; + pending_len -= status; + retval += status; + } + mutex_unlock(&port_data->update_lock); + + return retval; + +err: + mutex_unlock(&port_data->update_lock); + + return status; +} + +#else +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} +#endif + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + +#if (MULTIPAGE_SUPPORT == 1) + return sfp_port_read_write(data, buf, off, count, QSFP_READ_OP); +#else + return sfp_port_read(data, buf, off, count); +#endif +} + +#if (MULTIPAGE_SUPPORT == 1) +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, size_t size) +#else +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +#endif +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; +#if (MULTIPAGE_SUPPORT == 1) + eeprom->size = size; +#else + eeprom->size = EEPROM_SIZE; +#endif + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + + +#if (MULTIPAGE_SUPPORT == 0) +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} +#endif + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + +#if (MULTIPAGE_SUPPORT == 0) + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } +#endif + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ +#if (MULTIPAGE_SUPPORT == 1) + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin, SFF_8436_EEPROM_SIZE); +#else + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); +#endif + if (status) { + goto exit_remove; + } + +#if (MULTIPAGE_SUPPORT == 1) + msa->ddm_client = i2c_new_dummy(client->adapter, client->addr + 1); + if (!msa->ddm_client) { + dev_err(&client->dev, "address 0x%02x unavailable\n", client->addr + 1); + status = -EADDRINUSE; + goto exit_eeprom; + } +#endif + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +exit_eeprom: + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &msa->eeprom.bin); +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + +#if (MULTIPAGE_SUPPORT == 0) + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } +#endif + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ +#if (MULTIPAGE_SUPPORT == 1) + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, SFF_8436_EEPROM_SIZE); +#else + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); +#endif + if (status) { + goto exit_remove; + } + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +/* Platform dependent +++ */ +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int ret = 0; + struct sfp_port_data *data = NULL; + + if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { + return -ENODEV; + } + + if (dev_id->driver_data < as7312_54x_port1 || dev_id->driver_data > as7312_54x_port54) { + return -ENXIO; + } + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + +#if (MULTIPAGE_SUPPORT == 1) + data->use_smbus = 0; + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + data->use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + data->use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + data->use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + ret = -EPFNOSUPPORT; + goto exit_kfree; + } + } + + if (!data->use_smbus || + (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_WORD_DATA) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + /* + * NOTE: AN-2079 + * Finisar recommends that the host implement 1 byte writes + * only since this module only supports 32 byte page boundaries. + * 2 byte writes are acceptable for PE and Vout changes per + * Application Note AN-2071. + */ + unsigned write_max = 1; + + if (write_max > io_limit) + write_max = io_limit; + if (data->use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + data->write_max = write_max; + + /* buffer (data + address at the beginning) */ + data->writebuf = kmalloc(write_max + 2, GFP_KERNEL); + if (!data->writebuf) { + ret = -ENOMEM; + goto exit_kfree; + } + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + + if (data->use_smbus == I2C_SMBUS_WORD_DATA || + data->use_smbus == I2C_SMBUS_BYTE_DATA) { + dev_notice(&client->dev, "Falling back to %s reads, " + "performance will suffer\n", data->use_smbus == + I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } +#endif + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if (dev_id->driver_data >= as7312_54x_port1 && dev_id->driver_data <= as7312_54x_port48) { + data->driver_type = DRIVER_TYPE_SFP_MSA; + ret = sfp_msa_probe(client, dev_id, &data->msa); + } + else { /* as7312_54x_portsfp49 ~ as7312_54x_portsfp54 */ + data->driver_type = DRIVER_TYPE_QSFP; + ret = qsfp_probe(client, dev_id, &data->qsfp); + } + + if (ret < 0) { + goto exit_kfree_buf; + } + + + return ret; + +exit_kfree_buf: +#if (MULTIPAGE_SUPPORT == 1) + if (data->writebuf) kfree(data->writebuf); +#endif + +exit_kfree: + kfree(data); + return ret; +} +/* Platform dependent --- */ + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); +#if (MULTIPAGE_SUPPORT == 1) + i2c_unregister_device(data->ddm_client); +#endif + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + int ret = 0; + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + +#if (MULTIPAGE_SUPPORT == 1) + if (data->writebuf) + kfree(data->writebuf); +#endif + kfree(data); + return ret; +} + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7312_54x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_i2c_cpld.c new file mode 100644 index 000000000000..67ecd8e036a9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/accton_i2c_cpld.c @@ -0,0 +1,1219 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as7312_54x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as7312_54x_cpld1, + as7312_54x_cpld2, + as7312_54x_cpld3 +}; + +struct as7312_54x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as7312_54x_cpld_id[] = { + { "as7312_54x_cpld1", as7312_54x_cpld1 }, + { "as7312_54x_cpld2", as7312_54x_cpld2 }, + { "as7312_54x_cpld3", as7312_54x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as7312_54x_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as7312_54x_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as7312_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7312_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR, show_status, set_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(54); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); + +static struct attribute *as7312_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7312_54x_cpld1_group = { + .attrs = as7312_54x_cpld1_attributes, +}; + +static struct attribute *as7312_54x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_RESET_ATTR(49), + DECLARE_TRANSCEIVER_RESET_ATTR(50), + DECLARE_TRANSCEIVER_RESET_ATTR(51), + DECLARE_TRANSCEIVER_RESET_ATTR(52), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + NULL +}; + +static const struct attribute_group as7312_54x_cpld2_group = { + .attrs = as7312_54x_cpld2_attributes, +}; + +static struct attribute *as7312_54x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_TRANSCEIVER_RESET_ATTR(53), + DECLARE_TRANSCEIVER_RESET_ATTR(54), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + NULL +}; + +static const struct attribute_group as7312_54x_cpld3_group = { + .attrs = as7312_54x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[4] = {0}; + u8 regs[] = {0x9, 0xA, 0xB, 0x18}; + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7312_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + if (data->type == as7312_54x_cpld2) { + values[3] &= 0xF; + } + else { /* as7312_54x_cpld3 */ + values[3] &= 0x3; + } + + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[3] = {0}; + u8 regs[] = {0x12, 0x13, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7312_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_40: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_PRESENT_33); + break; + case MODULE_PRESENT_41 ... MODULE_PRESENT_48: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_PRESENT_41); + break; + case MODULE_PRESENT_49: + reg = 0x18; + mask = 0x1; + break; + case MODULE_PRESENT_50: + reg = 0x18; + mask = 0x2; + break; + case MODULE_PRESENT_51: + reg = 0x18; + mask = 0x4; + break; + case MODULE_PRESENT_52: + reg = 0x18; + mask = 0x8; + break; + case MODULE_PRESENT_53: + reg = 0x18; + mask = 0x1; + break; + case MODULE_PRESENT_54: + reg = 0x18; + mask = 0x2; + break; + + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x17; + mask = 1 << ((attr->index - MODULE_PRESENT_49)%4); + break; + + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXFAULT_1); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXFAULT_9); + break; + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXFAULT_17); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXFAULT_33); + break; + case MODULE_TXFAULT_41 ... MODULE_TXFAULT_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXFAULT_41); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_8: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_RXLOS_1); + break; + case MODULE_RXLOS_9 ... MODULE_RXLOS_16: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_RXLOS_9); + break; + case MODULE_RXLOS_17 ... MODULE_RXLOS_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RXLOS_17); + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_32: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_RXLOS_33 ... MODULE_RXLOS_40: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_RXLOS_33); + break; + case MODULE_RXLOS_41 ... MODULE_RXLOS_48: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RXLOS_41); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_54) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_RESET_49 ... MODULE_RESET_54: + reg = 0x17; + mask = 1 << ((attr->index - MODULE_RESET_49)%4); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update reset status */ + if (reset) { + status |= mask; + } + else { + status &= ~mask; + } + status = as7312_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7312_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7312_54x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as7312_54x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7312_54x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as7312_54x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as7312_54x_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as7312_54x_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as7312_54x_cpld1: + group = &as7312_54x_cpld1_group; + break; + case as7312_54x_cpld2: + group = &as7312_54x_cpld2_group; + break; + case as7312_54x_cpld3: + group = &as7312_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as7312_54x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as7312_54x_cpld_remove(struct i2c_client *client) +{ + struct as7312_54x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as7312_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as7312_54x_cpld1: + group = &as7312_54x_cpld1_group; + break; + case as7312_54x_cpld2: + group = &as7312_54x_cpld2_group; + break; + case as7312_54x_cpld3: + group = &as7312_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as7312_54x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7312_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as7312_54x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7312_54x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7312_54x_cpld_read); + +int as7312_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7312_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7312_54x_cpld_write); + +static struct i2c_driver as7312_54x_cpld_driver = { + .driver = { + .name = "as7312_54x_cpld", + .owner = THIS_MODULE, + }, + .probe = as7312_54x_cpld_probe, + .remove = as7312_54x_cpld_remove, + .id_table = as7312_54x_cpld_id, +}; + +static int __init as7312_54x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7312_54x_cpld_driver); +} + +static void __exit as7312_54x_cpld_exit(void) +{ + i2c_del_driver(&as7312_54x_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as7312_54x_cpld_init); +module_exit(as7312_54x_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/service/as7312-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/service/as7312-platform-monitor.service new file mode 100755 index 000000000000..b79357665bed --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/service/as7312-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS7312-54X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7312_util.py install +ExecStart=/usr/local/bin/accton_as7312_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/setup.py new file mode 100755 index 000000000000..d1351ab3e597 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7312_54xs', + version='1.0', + description='Module to initialize Accton AS7312-54XS platforms', + + packages=['as7312_54xs'], + package_dir={'as7312_54xs': 'as7312-54xs/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/utils/README new file mode 100755 index 000000000000..66f31a030423 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as7312_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as7312-fan-psu-cpld.patch + for as7312's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS7312-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as7312 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS7312-54X.patch" from patch/installer. + - Change setting for AS7312-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS7312-54X.patch" + !!NOTICE, patching onie_installer-accton-AS7312-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS7312-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as7312-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as7312_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS7312-54X.patch. + It's done by patching onie_installer-accton-AS7312-54X.patch at build-image. + Run "accton_as7312_util.py install" to install drivers. + +To initialize the system, run "accton_as7312_util.py install". +To clean up the drivers & devices, run "accton_as7312_util.py clean". +To dump information of sensors, run "accton_as7312_util.py show". +To dump SFP EEPROM, run "accton_as7312_util.py sff". +To set fan speed, run "accton_as7312_util.py set fan". +To enable/disable SFP emission, run "accton_as7312_util.py set sfp". +To set system LEDs' color, run "accton_as7312_util.py set led" +For more information, run "accton_as7312_util.py --help". + +==================================================================== +Besides applying accton_as7312_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/utils/accton_as7312_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/utils/accton_as7312_monitor.py new file mode 100755 index 000000000000..58ffe1923a85 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/utils/accton_as7312_monitor.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 2/27/2018: Roy Lee modify for as7312_54x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from as7312_54xs.fanutil import FanUtil + from as7312_54xs.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7312_monitor' +DUTY_MAX = 100 + +global log_file +global log_level + +# (LM75_1+ LM75_2+ LM75_3) is LM75 at i2c addresses 0x48, 0x49, and 0x4A. +# TMP = (LM75_1+ LM75_2+ LM75_3)/3 +#1. If TMP < 35, All fans run with duty 31.25%. +#2. If TMP>=35 or the temperature of any one of fan is higher than 40, +# All fans run with duty 50% +#3. If TMP >= 40 or the temperature of any one of fan is higher than 45, +# All fans run with duty 62.5%. +#4. If TMP >= 45 or the temperature of any one of fan is higher than 50, +# All fans run with duty 100%. +#5. Any one of 6 fans is fault, set duty = 100%. +#6. Direction factor. If it is B2F direction, duty + 12%. + + # MISC: + # 1.Check single LM75 before applied average. + # 2.If no matched fan speed is found from the policy, + # use FAN_DUTY_CYCLE_MIN as default speed + # Get current temperature + # 4.Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature + + + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7312_monitor(object): + # static temp var + llog = logging.getLogger("["+FUNCTION_NAME+"]") + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_console, log_file, log_level=logging.INFO): + """Needs a logger and a logger level.""" + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + sys_handler.setLevel(log_level) + self.llog.addHandler(sys_handler) + + if log_file: + fh = logging.FileHandler(log_file) + fh.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s') + fh.setFormatter(formatter) + self.llog.addHandler(fh) + + if log_console: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s') + console.setFormatter(formatter) + self.llog.addHandler(console) + + + def manage_fans(self): + max_duty = DUTY_MAX + fan_policy_f2b = { + 0: [32, 0, 105000], + 1: [50, 105000, 120000], + 2: [63, 120000, 135000], + 3: [max_duty, 135000, sys.maxsize], + } + fan_policy_b2f = { + 0: [44, 0, 105000], + 1: [63, 105000, 120000], + 2: [75, 120000, 135000], + 3: [max_duty, 135000, sys.maxsize], + } + fan_policy_single = { + 0: 40000, + 1: 45000, + 2: 50000, + } + + thermal = ThermalUtil() + fan = FanUtil() + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + self.llog.debug('SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + return False + if fan_status is False: + self.llog.warning('SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + fan.set_fan_duty_cycle(max_duty) + return True + + fan_dir=fan.get_fan_dir(1) + if fan_dir == 1: + fan_policy = fan_policy_f2b + else: + fan_policy = fan_policy_b2f + + #Decide fan duty by if any of sensors > fan_policy_single. + new_duty_cycle = fan_policy[0][0] + for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): + single_thm = thermal._get_thermal_node_val(x) + for y in range(0, len(fan_policy_single)): + if single_thm > fan_policy_single[y]: + if fan_policy[y+1][0] > new_duty_cycle: + new_duty_cycle = fan_policy[y+1][0] + self.llog.debug('Single thermal sensor %d with temp %d > %d , new_duty_cycle=%d', + x, single_thm, fan_policy_single[y], new_duty_cycle) + single_result = new_duty_cycle + + + #Find if current duty matched any of define duty. + #If not, set it to highest one. + cur_duty_cycle = fan.get_fan_duty_cycle() + for x in range(0, len(fan_policy)): + if cur_duty_cycle == fan_policy[x][0]: + break + if x == len(fan_policy) : + fan.set_fan_duty_cycle(fan_policy[0][0]) + cur_duty_cycle = max_duty + + #Decide fan duty by if sum of sensors falls into any of fan_policy{} + get_temp = thermal.get_thermal_temp() + new_duty_cycle = cur_duty_cycle + for x in range(0, len(fan_policy)): + y = len(fan_policy) - x -1 #checked from highest + if get_temp > fan_policy[y][1] and get_temp < fan_policy[y][2] : + new_duty_cycle= fan_policy[y][0] + self.llog.debug('Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + + sum_result = new_duty_cycle + if (sum_result>single_result): + new_duty_cycle = sum_result; + else: + new_duty_cycle = single_result + + self.llog.debug('Final duty_cycle=%d', new_duty_cycle) + if(new_duty_cycle != cur_duty_cycle): + fan.set_fan_duty_cycle(new_duty_cycle) + return True + +def sig_handler(signum, frame): + fan = FanUtil() + logging.critical('Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(DUTY_MAX) + sys.exit(0) + +def main(argv): + log_level = logging.INFO + log_console = 0 + log_file = "" + + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl') + except getopt.GetoptError: + print 'Usage: %s [-d]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l]' % sys.argv[0] + return 0 + elif opt in ('-d'): + log_console = 1 + elif opt in ('-l'): + log_file = '%s.log' % sys.argv[0] + + signal.signal(signal.SIGINT, sig_handler) + signal.signal(signal.SIGTERM, sig_handler) + monitor = accton_as7312_monitor(log_console, log_file) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/utils/accton_as7312_util.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/utils/accton_as7312_util.py new file mode 100755 index 000000000000..f6a21bdd3df9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54xs/utils/accton_as7312_util.py @@ -0,0 +1,588 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + + + + +PROJECT_NAME = 'as7312_54x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':6,'thermal':4, 'psu':2, 'sfp':54} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_cpld' , +'modprobe ym2651y' , +'modprobe accton_as7312_54x_fan' , +'modprobe optoe' , +'modprobe accton_as7312_54x_leds' , +'modprobe accton_as7312_54x_psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + lst = rm.split(" ") + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['2-0066'] , + 'thermal': ['3-0048','3-0049', '3-004a', '3-004b'] , + 'psu': ['10-0051','11-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present', 'sfp_tx_disable']} + +sfp_map = [18,19,20,21,22,23,24,25,26,27, + 28,29,30,31,32,33,34,35,36,37, + 38,39,40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55,56,57, + 58,59,60,61,62,63,64,65,66,67, + 68,69,70,71] + +qsfp_start = 48 + +mknod =[ +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', + +'echo as7312_54x_fan 0x66 > /sys/bus/i2c/devices/i2c-2/new_device ', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as7312_54x_psu1 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2651 0x59 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as7312_54x_psu2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo as7312_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-4/new_device', +'echo as7312_54x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo as7312_54x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-6/new_device'] + +mknod2 =[ +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as7312_54x_fan 0x66 > /sys/bus/i2c/devices/i2c-2/new_device ', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as7312_54x_psu1 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2651 0x59 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as7312_54x_psu2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo as7312_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-4/new_device', +'echo as7312_54x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo as7312_54x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-6/new_device'] + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x70 is exist @ i2c-1 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x70 is not exist @i2c-1, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(0,len(sfp_map)): + if i < qsfp_start: + status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + else: + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py new file mode 100644 index 000000000000..0e7b06bbd287 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/fanutil.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_TOTAL_NUM = 5 + FAN_NUM_1_IDX = 1 + + FAN_NODE_NUM = 2 + FAN_FAULT_IDX = 1 + #FAN_SPEED_IDX = 2 + FAN_DIR_IDX = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/50-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/50-0066/fan{0}_pwm' + + #logfile = '' + #loglevel = self.logger.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + dev_paths = {} + + node_postfix = ["fault", "direction"] + def _get_fan_to_device_node(self, fan_num, node_num): + return "fan{0}_{1}".format(fan_num, self.node_postfix[node_num-1]) + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_TOTAL_NUM: + self.logger.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_FAULT_IDX or node_num > self.FAN_NODE_NUM: + self.logger.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_TOTAL_NUM: + self.logger.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_FAULT_IDX or node_num > self.FAN_NODE_NUM: + self.logger.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + logger = logging.getLogger(__name__) + def __init__(self, log_level=logging.DEBUG): + ch = logging.StreamHandler() + ch.setLevel(log_level) + self.logger.addHandler(ch) + + fan_path = self.BASE_VAL_PATH + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_TOTAL_NUM+1): + for node_num in range(1, self.FAN_NODE_NUM+1): + node = self._get_fan_to_device_node(fan_num, node_num) + self.dev_paths[(fan_num, node_num)] = fan_path.format(node) + + def get_num_fans(self): + return self.FAN_TOTAL_NUM + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM + + def get_idx_node_start(self): + return self.FAN_FAULT_IDX + + def get_size_node_map(self): + return len(self.dev_paths) + + def get_size_path_map(self): + return len(self.dev_paths) + + def get_fan_to_device_path(self, fan_num, node_num): + return self.dev_paths[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_FAULT_IDX) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_SPEED_IDX) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_DIR_IDX) + + def get_fan_duty_cycle(self): + try: + val_file = open(self.FAN_DUTY_PATH.format(1)) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + return int(content) + + def set_fan_duty_cycle(self, val): + for fan_num in range(1, self.FAN_TOTAL_NUM+1): + try: + fan_file = open(self.FAN_DUTY_PATH.format(fan_num), 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + fan_file.write(str(val)) + fan_file.close() + return True + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_TOTAL_NUM: + self.logger.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + self.logger.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # self.logger.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py new file mode 100644 index 000000000000..47dba67f2c1f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/classes/thermalutil.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = [ + ['51', '49'], + ['52', '4a'], + ['53', '4c'], + ] + logger = logging.getLogger(__name__) + def __init__(self, log_level=logging.DEBUG): + ch = logging.StreamHandler() + ch.setLevel(log_level) + self.logger.addHandler(ch) + + thermal_path = self.BASE_VAL_PATH + for x in range(self.THERMAL_NUM_ON_MAIN_BROAD): + self._thermal_to_device_path_mapping[x+1] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + self.logger.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + self.logger.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + self.logger.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + self.logger.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + + def get_thermal_temp(self): + sum = 0 + o = [] + for x in range(self.THERMAL_NUM_ON_MAIN_BROAD): + sum += self._get_thermal_node_val(x+1) + avg = sum/self.THERMAL_NUM_ON_MAIN_BROAD + avg = (avg/1000)*1000 #round down for hysteresis. + return avg + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/Makefile new file mode 100644 index 000000000000..a1bf8335378c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/Makefile @@ -0,0 +1,2 @@ +obj-m:= accton_as7315_27xb_fan.o x86-64-accton-as7315-27xb-cpld.o x86-64-accton-as7315-27xb-psu.o \ + at24_as7315_27xb.o x86-64-accton-as7315-27xb-led.o ym2651y.o diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c new file mode 100644 index 000000000000..adf8fc69ea35 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/accton_as7315_27xb_fan.c @@ -0,0 +1,673 @@ +/* + * A hwmon driver for the Accton as5710 54x fan contrl + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRV_NAME "as5812_54x_fan" + +#define FAN_MAX_NUMBER 5 +#define FAN_SPEED_TACH_TO_RPM_STEP 175 +#define FAN_SPEED_PWM_STEPS 31 +#define FAN_DUTY_CYCLE_MIN 0 /* 10% ??*/ +#define FAN_DUTY_CYCLE_MAX 100 /* 100% */ + + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ +#define ATTR_ALLOC_SIZE 1 /*For last attribute which is NUll.*/ +#define NAME_SIZE 24 + +typedef ssize_t (*show_func)( struct device *dev, + struct device_attribute *attr, + char *buf); +typedef ssize_t (*store_func)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); + + +struct fan_sensor { + struct fan_sensor *next; + char name[NAME_SIZE+1]; /* sysfs sensor name */ + struct device_attribute attribute; + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. Negative if there was a read error */ + + u8 reg; /* register */ + u8 mask; /* bit mask */ + bool invert; /* inverted value*/ + +}; + +#define to_fan_sensor(_attr) \ + container_of(_attr, struct fan_sensor, attribute) + + +struct model_attrs { + struct attrs **cmn; + struct attrs **indiv; +}; + + +struct fan_data_t { + struct device *dev; + struct device *hwmon_dev; + + int num_attributes; + struct attribute_group group; + struct fan_sensor *sensors; + int attr_index; + struct model_attrs *attrs; + + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + + u8 fan_num; + + u8 status[FAN_MAX_NUMBER]; /* inner first fan status */ + u32 speed[FAN_MAX_NUMBER]; /* inner first fan speed */ + u8 direction[FAN_MAX_NUMBER]; /* reconrd the direction of inner first and second fans */ + u32 duty_cycle[FAN_MAX_NUMBER]; /* control the speed of inner first and second fans */ + u8 r_status[FAN_MAX_NUMBER]; /* inner second fan status */ + u32 r_speed[FAN_MAX_NUMBER]; /* inner second fan speed */ +}; + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_byte(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t set_1bit(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_pwm(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_rpm(struct device *dev, + struct device_attribute *devattr, char *buf); + +struct base_attrs { + const char *name; + umode_t mode; + show_func get; + store_func set; +}; + +struct attrs { + int reg; + int mask; + bool invert; + struct base_attrs *base; +}; + +enum common_attrs { + BRD_VERSION, + PLD_VERSION, + PLD_SVERSION, + NUM_COMMON_ATTR +}; + +struct base_attrs common_base_attrs[NUM_COMMON_ATTR] = +{ + [BRD_VERSION] = {"borad_ver", S_IRUGO, show_byte, NULL}, + [PLD_VERSION] = {"cpld_ver", S_IRUGO, show_byte, NULL}, + [PLD_SVERSION] = {"cpld_subver", S_IRUGO, show_byte, NULL}, +}; + +struct attrs common_attrs[] = { + [BRD_VERSION] = {0x00, -1, false, &common_base_attrs[BRD_VERSION]}, + [PLD_VERSION] = {0x01, -1, false, &common_base_attrs[PLD_VERSION]}, + [PLD_SVERSION] = {0x02, -1, false, &common_base_attrs[PLD_SVERSION]}, +}; + +struct attrs *as7315_cmn_list[] = { + &common_attrs[BRD_VERSION], + &common_attrs[PLD_VERSION], + &common_attrs[PLD_SVERSION], + NULL +}; + +enum fan_attrs { + _ENABLE, + _PRESENT, + _FAULT, + _SPEED_RPM, + _PWM, + _DIRECTION, + NUM_FAN_ATTRS +}; + +struct base_attrs tray_base_attrs[NUM_FAN_ATTRS] = +{ + {"enable", S_IRUGO|S_IWUSR, show_bit, set_1bit}, + {"present", S_IRUGO, show_bit, NULL}, + {"fault", S_IRUGO, show_bit, NULL}, + {"input", S_IRUGO, show_rpm, NULL}, + {"pwm", S_IRUGO|S_IWUSR, show_pwm, set_pwm}, + {"dir", S_IRUGO, show_bit, NULL}, +}; + +struct attrs as7315_module[NUM_FAN_ATTRS] = { + {0x10, -1, false, &tray_base_attrs[_ENABLE]}, + {0x22, 0, true, &tray_base_attrs[_PRESENT]}, + {0x22, 1, false, &tray_base_attrs[_FAULT]}, + {0x20, 0, false, &tray_base_attrs[_SPEED_RPM]}, + {0x21, 0, false, &tray_base_attrs[_PWM]}, + {-1, -1, false, &tray_base_attrs[_DIRECTION]}, +}; + +struct attrs *as7315_mod_list[] = { + &as7315_module[_ENABLE], + &as7315_module[_PRESENT], + &as7315_module[_FAULT], + &as7315_module[_SPEED_RPM], + &as7315_module[_PWM], + NULL +}; + +struct model_attrs models_attr = { + .cmn = as7315_cmn_list, + .indiv = as7315_mod_list, +}; + + +static const struct i2c_device_id as7315_fan_id[] = { + { "as7315_fan", 0}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, as7315_fan_id); + + +static int cpld_write_internal( + struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + break; + } + return status; +} + +static int cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + break; + } + return status; +} + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int value; + struct i2c_client *client = to_i2c_client(dev); + struct fan_data_t *data = i2c_get_clientdata(client); + struct fan_sensor *sensor = to_fan_sensor(devattr); + + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, sensor->reg); + if (unlikely(value < 0)) { + mutex_unlock(&data->update_lock); + return value; + } + value = value & sensor->mask; + if (sensor->invert) + value = !value; + mutex_unlock(&data->update_lock); + + return snprintf(buf, PAGE_SIZE, "%x\n", !!value); +} + +static ssize_t _read_1byte(struct device *dev, + struct device_attribute *devattr, u8 *data) +{ + int rv; + struct i2c_client *client = to_i2c_client(dev); + struct fan_data_t *fdata = i2c_get_clientdata(client); + struct fan_sensor *sensor = to_fan_sensor(devattr); + + mutex_lock(&fdata->update_lock); + rv = cpld_read_internal(client, sensor->reg); + if (unlikely(rv < 0)) { + mutex_unlock(&fdata->update_lock); + return rv; + } + mutex_unlock(&fdata->update_lock); + *data = rv; + return 0; +} + +static ssize_t show_byte(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + u8 data; + int rv; + + rv =_read_1byte(dev, devattr, &data); + if (unlikely(rv < 0)) { + return rv; + } + return snprintf(buf, PAGE_SIZE, "0x%x\n", data); +} + + +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + return ((u32)(reg_val+1) * 156 + 88) / 100; +} +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 155) - 1; +} + +static ssize_t show_pwm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + u8 data; + int rv; + + rv =_read_1byte(dev, devattr, &data); + if (unlikely(rv < 0)) { + return rv; + } + data = reg_val_to_duty_cycle(data); + data = (data > FAN_DUTY_CYCLE_MAX)? FAN_DUTY_CYCLE_MAX: data; + return snprintf(buf, PAGE_SIZE, "%d\n", data); +} + +static ssize_t show_rpm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + u8 data; + int rv; + + rv =_read_1byte(dev, devattr, &data); + if (unlikely(rv < 0)) { + return rv; + } + rv = data * FAN_SPEED_TACH_TO_RPM_STEP; + return snprintf(buf, PAGE_SIZE, "%d\n", rv); +} +static ssize_t set_1bit(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + long is_reset; + int value, status; + struct i2c_client *client = to_i2c_client(dev); + struct fan_data_t *data = i2c_get_clientdata(client); + struct fan_sensor *sensor = to_fan_sensor(devattr); + u8 cpld_bit, reg; + + status = kstrtol(buf, 10, &is_reset); + if (status) { + return status; + } + reg = sensor->reg; + cpld_bit = sensor->mask; + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + if (sensor->invert) + is_reset = !is_reset; + + if (is_reset) { + value |= cpld_bit; + } + else { + value &= ~cpld_bit; + } + + status = cpld_write_internal(client, reg, value); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + long value; + int status; + struct i2c_client *client = to_i2c_client(dev); + struct fan_data_t *data = i2c_get_clientdata(client); + struct fan_sensor *sensor = to_fan_sensor(devattr); + u8 reg; + + status = kstrtol(buf, 10, &value); + if (status) { + return status; + } + + value = (value > FAN_DUTY_CYCLE_MAX )? FAN_DUTY_CYCLE_MAX: value; + value = duty_cycle_to_reg_val(value); + reg = sensor->reg; + + mutex_lock(&data->update_lock); + status = cpld_write_internal(client, reg, value); + if (unlikely(status < 0)) { + mutex_unlock(&data->update_lock); + return status; + } + mutex_unlock(&data->update_lock); + return count; +} + + + +static int _add_attribute(struct fan_data_t *data, struct attribute *attr) +{ + int new_max_attrs = ++data->num_attributes + ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + + if (!new_attrs) + return -ENOMEM; + + data->group.attrs = new_attrs; + data->group.attrs[data->num_attributes-1] = attr; + data->group.attrs[data->num_attributes] = NULL; + + return 0; +} + +static void cpld_dev_attr_init(struct device_attribute *dev_attr, + const char *name, umode_t mode, + show_func show, store_func store) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static struct fan_sensor * _add_sensor(struct fan_data_t *data, + const char *name, + u8 reg, u8 mask, bool invert, + bool update, umode_t mode, + show_func get, store_func set) +{ + struct fan_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), name); + sensor->reg = reg; + sensor->mask = mask; + sensor->update = update; + sensor->invert = invert; + cpld_dev_attr_init(a, sensor->name, + mode, + get, set); + + if (_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int _add_attributes_cmn(struct fan_data_t *data, struct attrs **cmn) +{ + u8 reg, i ; + bool invert; + struct attrs *a; + struct base_attrs *b; + + if (NULL == cmn) + return -1; + + for (i = 0; cmn[i]; i++) + { + a = cmn[i]; + reg = a->reg; + invert = a->invert; + + + + b = a->base; + if (NULL == b) + break; + + + if (_add_sensor(data, b->name, + reg, 0xff, invert, + true, b->mode, + b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + return 0; +} + +static int _add_attributes_indiv(struct fan_data_t *data, struct attrs **pa) +{ + char name[NAME_SIZE+1]; + int i, j, mask; + u8 reg, invert, reg_start, jump; + struct attrs *a; + struct base_attrs *b; + + if (NULL == pa) + return -EFAULT; + + jump = 0x10; + for (i = 0; pa[i]; i++) { + a = pa[i]; + reg_start = a->reg; + + if (reg < 0) + break; + + b = a->base; + if (b == NULL) + break; + invert = a->invert; + for (j = 0; j < data->fan_num; j++) + { + + snprintf(name, NAME_SIZE, "fan%d_%s", j+1, b->name); + /*If mask < 0, mask is as index*/ + if (a->mask < 0) { + mask = 1 << (j%8); + reg = reg_start; + } else { /*If mask >= 0, means to get full byte and reg need to shift*/ + mask = 1 << (a->mask); + reg = reg_start + ((j%8)*jump); + } + if (_add_sensor(data, name, reg, mask, invert, + true, b->mode, b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + } + + + return 0; +} + +static int _add_attributes(struct i2c_client *client, + struct fan_data_t *data) +{ + struct model_attrs *m = data->attrs; + + if (m == NULL) + return -EINVAL; + + /* Common attributes.*/ + _add_attributes_cmn(data, m->cmn); + + /* Port-wise attributes.*/ + _add_attributes_indiv(data, m->indiv); + + return 0; +} + +static int fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct fan_data_t *data = NULL; + struct device *dev = &client->dev; + + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->attrs = &models_attr; + data->fan_num = FAN_MAX_NUMBER; + mutex_init(&data->update_lock); + data->dev = dev; + dev_info(dev, "chip found\n"); + + + status = _add_attributes(client, data); + if (status) { + return status; + } + + if (!data->num_attributes) { + dev_err(&client->dev, "No attributes found\n"); + return -ENODEV; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->group); + if (status) { + goto out_kfree; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, + client->name, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_rm_sys; + } + + i2c_set_clientdata(client, data); + dev_info(dev, "%s: cpld '%s'\n", + dev_name(data->dev), client->name); + + return 0; + +exit_rm_sys: + sysfs_remove_group(&client->dev.kobj, &data->group); +out_kfree: + kfree(data->group.attrs); + return status; +} + + +static int fan_remove(struct i2c_client *client) +{ + struct fan_data_t *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->group); + kfree(data->group.attrs); + return 0; +} + + +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver as7315_i2c_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRV_NAME, + }, + .probe = fan_probe, + .remove = fan_remove, + .id_table = as7315_fan_id, + .address_list = normal_i2c, +}; + +static int __init accton_as7315_27xb_fan_init(void) +{ + return i2c_add_driver(&as7315_i2c_fan_driver); +} + +static void __exit accton_as7315_27xb_fan_exit(void) +{ + i2c_del_driver(&as7315_i2c_fan_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7315_27xb_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_as7315_27xb_fan_init); +module_exit(accton_as7315_27xb_fan_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/at24_as7315_27xb.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/at24_as7315_27xb.c new file mode 100755 index 000000000000..8d8c7601a71d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/at24_as7315_27xb.c @@ -0,0 +1,695 @@ +/* + * at24_as7315_27xb.c - handle most I2C EEPROMs for ethernet switch, as7315_27xb. + * + * Copyright (C) 2005-2007 David Brownell + * Copyright (C) 2008 Wolfram Sang, Pengutronix + * Copyright (C) 2019 Roy Lee, EdgeCore network. + * Revised to support specially I2C transactions, pure READ and WRITE. + * + * 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 +/* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. + * Differences between different vendor product lines (like Atmel AT24C or + * MicroChip 24LC, etc) won't much matter for typical read/write access. + * There are also I2C RAM chips, likewise interchangeable. One example + * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). + * + * However, misconfiguration can lose data. "Set 16-bit memory address" + * to a part with 8-bit addressing will overwrite data. Writing with too + * big a page size also loses data. And it's not safe to assume that the + * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC + * uses 0x51, for just one example. + * + * Accordingly, explicit board-specific configuration data should be used + * in almost all cases. (One partial exception is an SMBus used to access + * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) + * + * So this driver uses "new style" I2C driver binding, expecting to be + * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or + * similar kernel-resident tables; or, configuration data coming from + * a bootloader. + * + * Other than binding model, current differences from "eeprom" driver are + * that this one handles write access and isn't restricted to 24c02 devices. + * It also handles larger devices (32 kbit and up) with two-byte addresses, + * which won't work on pure SMBus systems. + */ + +struct at24_data { + struct at24_platform_data chip; + int use_smbus; + int use_smbus_write; + + ssize_t (*read_func)(struct at24_data *, char *, unsigned int, size_t); + ssize_t (*write_func)(struct at24_data *, + const char *, unsigned int, size_t); + + /* + * Lock protects against activities from other Linux tasks, + * but not from changes by other I2C masters. + */ + struct mutex lock; + + u8 *writebuf; + unsigned write_max; + unsigned num_addresses; + + struct nvmem_config nvmem_config; + struct nvmem_device *nvmem; + + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. + */ + struct i2c_client *client[]; +}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 128; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + +#define AT24_SIZE_BYTELEN 5 +#define AT24_SIZE_FLAGS 8 + +#define AT24_BITMASK(x) (BIT(x) - 1) + +/* create non-zero magic value for given eeprom parameters */ +#define AT24_DEVICE_MAGIC(_len, _flags) \ + ((1 << AT24_SIZE_FLAGS | (_flags)) \ + << AT24_SIZE_BYTELEN | ilog2(_len)) + +/* + * Both reads and writes fail if the previous write didn't complete yet. This + * macro loops a few times waiting at least long enough for one entire page + * write to work while making sure that at least one iteration is run before + * checking the break condition. + * + * It takes two parameters: a variable in which the future timeout in jiffies + * will be stored and a temporary variable holding the time of the last + * iteration of processing the request. Both should be unsigned integers + * holding at least 32 bits. + */ +#define loop_until_timeout(tout, op_time) \ + for (tout = jiffies + msecs_to_jiffies(write_timeout), op_time = 0; \ + op_time ? time_before(op_time, tout) : true; \ + usleep_range(1000, 1500), op_time = jiffies) + +static const struct i2c_device_id at24_ids[] = { + { "24cxb04", AT24_DEVICE_MAGIC(4096 / 8, AT24_FLAG_ADDR16) }, + { "24cxb08", AT24_DEVICE_MAGIC(8192 / 8, AT24_FLAG_ADDR16) }, + { "24cxb16", AT24_DEVICE_MAGIC(16384 / 8, AT24_FLAG_ADDR16) }, + { "24cxb32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) }, + { "24cxb64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) }, + { "at24", 0 }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, at24_ids); + +static const struct acpi_device_id at24_acpi_ids[] = { + { "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) }, + { } +}; +MODULE_DEVICE_TABLE(acpi, at24_acpi_ids); + +/*-------------------------------------------------------------------------*/ + +/* + * This routine supports chips which consume multiple I2C addresses. It + * computes the addressing information to be used for a given r/w request. + * Assumes that sanity checks for offset happened at sysfs-layer. + * + * Slave address and byte offset derive from the offset. Always + * set the byte address; on a multi-master board, another master + * may have changed the chip's "current" address pointer. + * + * REVISIT some multi-address chips don't rollover page reads to + * the next slave address, so we may need to truncate the count. + * Those chips might need another quirk flag. + * + * If the real hardware used four adjacent 24c02 chips and that + * were misconfigured as one 24c08, that would be a similar effect: + * one "eeprom" file not four, but larger reads would fail when + * they crossed certain pages. + */ +static struct i2c_client *at24_translate_offset(struct at24_data *at24, + unsigned int *offset) +{ + unsigned i; + + /*Always AT24_FLAG_ADDR16*/ + i = *offset >> 16; + *offset &= 0xffff; + + return at24->client[i]; +} + +static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, read_time; + struct i2c_client *client; + int status; + client = at24_translate_offset(at24, &offset); + + if (count > io_limit) + count = io_limit; + + loop_until_timeout(timeout, read_time) { +/* + status = i2c_smbus_read_i2c_block_data_or_emulated(client, + offset, + count, buf); + + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); +*/ + int i=0; + + /*Write 2-byte offset*/ + unsigned char bb = offset&0xff; + status = i2c_smbus_write_i2c_block_data(client, offset>>8, 1, &bb); + if (status < 0) { + return status; + } + + while (i < count) { + status = i2c_smbus_read_byte(client); + if (status < 0) { + return status; + } + buf[i] = status; + i++; + } + + + if (i == count) + return count; + } + + return -ETIMEDOUT; +} + +/* + * Note that if the hardware write-protect pin is pulled high, the whole + * chip is normally write protected. But there are plenty of product + * variants here, including OTP fuses and partial chip protect. + * + * We only use page mode writes; the alternative is sloooow. These routines + * write at most one page. + */ + +static size_t at24_adjust_write_count(struct at24_data *at24, + unsigned int offset, size_t count) +{ + unsigned next_page; + + /* write_max is at most a page */ + if (count > at24->write_max) + count = at24->write_max; + + /* Never roll over backwards, to the start of this page */ + next_page = roundup(offset + 1, at24->chip.page_size); + if (offset + count > next_page) + count = next_page - offset; + + return count; +} + +static ssize_t at24_eeprom_write_smbus_block(struct at24_data *at24, + const char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, write_time; + struct i2c_client *client; + ssize_t status = 0; + + client = at24_translate_offset(at24, &offset); + count = at24_adjust_write_count(at24, offset, count); + + loop_until_timeout(timeout, write_time) { + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + + return -ETIMEDOUT; +} + +static ssize_t at24_eeprom_write_smbus_byte(struct at24_data *at24, + const char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, write_time; + struct i2c_client *client; + ssize_t status = 0; + + client = at24_translate_offset(at24, &offset); + + loop_until_timeout(timeout, write_time) { + status = i2c_smbus_write_byte_data(client, offset, buf[0]); + if (status == 0) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + + return -ETIMEDOUT; +} + +static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf, + unsigned int offset, size_t count) +{ + unsigned long timeout, write_time; + struct i2c_client *client; + struct i2c_msg msg; + ssize_t status = 0; + int i = 0; + + client = at24_translate_offset(at24, &offset); + count = at24_adjust_write_count(at24, offset, count); + + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = at24->writebuf; + if (at24->chip.flags & AT24_FLAG_ADDR16) + msg.buf[i++] = offset >> 8; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + loop_until_timeout(timeout, write_time) { + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + } + + return -ETIMEDOUT; +} + +static int at24_read(void *priv, unsigned int off, void *val, size_t count) +{ + struct at24_data *at24 = priv; + char *buf = val; + + + + if (unlikely(!count)) + return count; + + if (off + count > at24->chip.byte_len) + return -EINVAL; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + int status; + + status = at24->read_func(at24, buf, off, count); + if (status < 0) { + mutex_unlock(&at24->lock); + return status; + } + buf += status; + off += status; + count -= status; + } + + mutex_unlock(&at24->lock); + + return 0; +} + +static int at24_write(void *priv, unsigned int off, void *val, size_t count) +{ + struct at24_data *at24 = priv; + char *buf = val; + + if (unlikely(!count)) + return -EINVAL; + + if (off + count > at24->chip.byte_len) + return -EINVAL; + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + int status; + + status = at24->write_func(at24, buf, off, count); + if (status < 0) { + mutex_unlock(&at24->lock); + return status; + } + buf += status; + off += status; + count -= status; + } + + mutex_unlock(&at24->lock); + + return 0; +} + +#ifdef CONFIG_OF +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ + const __be32 *val; + struct device_node *node = client->dev.of_node; + + if (node) { + if (of_get_property(node, "read-only", NULL)) + chip->flags |= AT24_FLAG_READONLY; + val = of_get_property(node, "pagesize", NULL); + if (val) + chip->page_size = be32_to_cpup(val); + } +} +#else +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ } +#endif /* CONFIG_OF */ + +static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct at24_platform_data chip; + kernel_ulong_t magic = 0; + bool writable; + int use_smbus = 0; + int use_smbus_write = 0; + struct at24_data *at24; + int err; + unsigned i, num_addresses; + + if (client->dev.platform_data) { + chip = *(struct at24_platform_data *)client->dev.platform_data; + } else { + if (id) { + magic = id->driver_data; + } else { + const struct acpi_device_id *aid; + + aid = acpi_match_device(at24_acpi_ids, &client->dev); + if (aid) + magic = aid->driver_data; + } + if (!magic) + return -ENODEV; + + chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); + magic >>= AT24_SIZE_BYTELEN; + chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); + /* + * This is slow, but we can't know all eeproms, so we better + * play safe. Specifying custom eeprom-types via platform_data + * is recommended anyhow. + */ + chip.page_size = 1; + + /* update chipdata if OF is present */ + at24_get_ofdata(client, &chip); + + chip.setup = NULL; + chip.context = NULL; + } + + if (!is_power_of_2(chip.byte_len)) + dev_warn(&client->dev, + "byte_len looks suspicious (no power of 2)!\n"); + if (!chip.page_size) { + dev_err(&client->dev, "page_size must not be 0!\n"); + return -EINVAL; + } + if (!is_power_of_2(chip.page_size)) + dev_warn(&client->dev, + "page_size looks suspicious (no power of 2)!\n"); + + /* + * REVISIT: the size of the EUI-48 byte array is 6 in at24mac402, while + * the call to ilog2() in AT24_DEVICE_MAGIC() rounds it down to 4. + * + * Eventually we'll get rid of the magic values altoghether in favor of + * real structs, but for now just manually set the right size. + */ + if (chip.flags & AT24_FLAG_MAC && chip.byte_len == 4) + chip.byte_len = 6; + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + /*if (chip.flags & AT24_FLAG_ADDR16){ + return -EPFNOSUPPORT; + }*/ + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + return -EPFNOSUPPORT; + } + + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + use_smbus_write = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + use_smbus_write = I2C_SMBUS_BYTE_DATA; + chip.page_size = 1; + } + } + + if (chip.flags & AT24_FLAG_TAKE8ADDR) + num_addresses = 8; + else + num_addresses = DIV_ROUND_UP(chip.byte_len, + (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); + + at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + + num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); + if (!at24) + return -ENOMEM; + + mutex_init(&at24->lock); + at24->use_smbus = use_smbus; + at24->use_smbus_write = use_smbus_write; + at24->chip = chip; + at24->num_addresses = num_addresses; + + if ((chip.flags & AT24_FLAG_SERIAL) && (chip.flags & AT24_FLAG_MAC)) { + dev_err(&client->dev, + "invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC."); + return -EINVAL; + } + at24->read_func = at24_eeprom_read_smbus; + + if (at24->use_smbus) { + if (at24->use_smbus_write == I2C_SMBUS_I2C_BLOCK_DATA) + at24->write_func = at24_eeprom_write_smbus_block; + else + at24->write_func = at24_eeprom_write_smbus_byte; + } else { + at24->write_func = at24_eeprom_write_i2c; + } + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { + if (!use_smbus || use_smbus_write) { + + unsigned write_max = chip.page_size; + + if (write_max > io_limit) + write_max = io_limit; + if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + at24->write_max = write_max; + + /* buffer (data + address at the beginning) */ + at24->writebuf = devm_kzalloc(&client->dev, + write_max + 2, GFP_KERNEL); + if (!at24->writebuf) + return -ENOMEM; + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + } + + at24->client[0] = client; + + /* use dummy devices for multiple-address chips */ + for (i = 1; i < num_addresses; i++) { + at24->client[i] = i2c_new_dummy(client->adapter, + client->addr + i); + if (!at24->client[i]) { + dev_err(&client->dev, "address 0x%02x unavailable\n", + client->addr + i); + err = -EADDRINUSE; + goto err_clients; + } + } + + i2c_set_clientdata(client, at24); + at24->nvmem_config.name = dev_name(&client->dev); + at24->nvmem_config.dev = &client->dev; + at24->nvmem_config.read_only = !writable; + at24->nvmem_config.root_only = true; + at24->nvmem_config.owner = THIS_MODULE; + at24->nvmem_config.compat = true; + at24->nvmem_config.base_dev = &client->dev; + at24->nvmem_config.reg_read = at24_read; + at24->nvmem_config.reg_write = at24_write; + at24->nvmem_config.priv = at24; + at24->nvmem_config.stride = 1; + at24->nvmem_config.word_size = 1; + at24->nvmem_config.size = chip.byte_len; + + at24->nvmem = nvmem_register(&at24->nvmem_config); + + if (IS_ERR(at24->nvmem)) { + err = PTR_ERR(at24->nvmem); + goto err_clients; + } + + dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n", + chip.byte_len, client->name, + writable ? "writable" : "read-only", at24->write_max); + if (use_smbus == I2C_SMBUS_WORD_DATA || + use_smbus == I2C_SMBUS_BYTE_DATA) { + dev_notice(&client->dev, "Falling back to %s reads, " + "performance will suffer\n", use_smbus == + I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } + + /* export data to kernel code */ + if (chip.setup) + chip.setup(at24->nvmem, chip.context); + + return 0; + +err_clients: + for (i = 1; i < num_addresses; i++) + if (at24->client[i]) + i2c_unregister_device(at24->client[i]); + + return err; +} + +static int at24_remove(struct i2c_client *client) +{ + struct at24_data *at24; + int i; + + at24 = i2c_get_clientdata(client); + + nvmem_unregister(at24->nvmem); + + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct i2c_driver at24_as7315_27xb_driver = { + .driver = { + .name = "at24_as7315_27xb", + .acpi_match_table = ACPI_PTR(at24_acpi_ids), + }, + .probe = at24_probe, + .remove = at24_remove, + .id_table = at24_ids, +}; + +static int __init at24_as7315_27xb_init(void) +{ + if (!io_limit) { + pr_err("at24_as7315_27xb: io_limit must not be 0!\n"); + return -EINVAL; + } + + io_limit = rounddown_pow_of_two(io_limit); + return i2c_add_driver(&at24_as7315_27xb_driver); +} +module_init(at24_as7315_27xb_init); + +static void __exit at24_as7315_27xb_exit(void) +{ + i2c_del_driver(&at24_as7315_27xb_driver); +} +module_exit(at24_as7315_27xb_exit); + +MODULE_DESCRIPTION("Driver for I2C EEPROMs on accton switch, as7315_27xb"); +MODULE_AUTHOR("Roy Lee"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-cpld.c new file mode 100755 index 000000000000..dcd604f1f61b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-cpld.c @@ -0,0 +1,1008 @@ +/* + * A hwmon driver for the as7315_i2c_cpld + * + * Copyright (C) 2019 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRV_NAME "as7315_i2c_cpld" +#define NUM_SFP 24 +#define NUM_QSFP 3 +#define NUM_ALL_PORTS 27 + +#define SFP_1ST_PRST_REG 0x10 +#define QSFP_1ST_PRST_REG 0x18 + +#define SFP_1ST_RXLOS_REG 0x13 +#define MUX_CHANNEL_SELECT_REG 0x80 + + +enum models { + MDL_CPLD_SFP, + MDL_CPLD_QSFP, + PLAIN_CPLD, /*No attribute but add i2c addr to the list.*/ + NUM_MODEL +}; + + +#define MAX_PORT_NUM 64 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +/* + * Number of additional attribute pointers to allocate + * with each call to krealloc + */ +#define ATTR_ALLOC_SIZE 1 /*For last attribute which is NUll.*/ + +#define NAME_SIZE 24 + +typedef ssize_t (*show_func)( struct device *dev, + struct device_attribute *attr, + char *buf); +typedef ssize_t (*store_func)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); + +enum port_type { + PT_SFP, + PT_QSFP, +}; + +enum common_attrs { + CMN_VERSION, + CMN_ACCESS, + CMN_PRESENT_ALL, + CMN_RXLOS_ALL, + NUM_COMMON_ATTR +}; + +enum sfp_sb_attrs { + SFP_PRESENT, + SFP_RESET, + SFP_TX_DIS, + SFP_TX_FAULT, + SFP_RX_LOS, + QSFP_PRESENT, + QSFP_LP_MODE, + NUM_SFP_SB_ATTR +}; + +struct cpld_sensor { + struct cpld_sensor *next; + char name[NAME_SIZE+1]; /* sysfs sensor name */ + struct device_attribute attribute; + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. Negative if there was a read error */ + + u8 reg; /* register */ + u8 mask; /* bit mask */ + bool invert; /* inverted value*/ + +}; + +#define to_cpld_sensor(_attr) \ + container_of(_attr, struct cpld_sensor, attribute) + +struct cpld_data { + struct device *dev; + struct device *hwmon_dev; + + int num_attributes; + struct attribute_group group; + + enum models model; + struct cpld_sensor *sensors; + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + int attr_index; + u16 sfp_num; + u8 sfp_types; + struct model_attrs *attrs; + + /*For mux function*/ + struct i2c_mux_core *muxc; +}; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + + +struct base_attrs { + const char *name; + umode_t mode; + show_func get; + store_func set; +}; + +struct attrs { + int reg; + bool invert; + struct base_attrs *base; +}; + +struct model_attrs { + struct attrs **cmn; + struct attrs **portly; +}; + + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_rxlos_all(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_presnet_all(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t set_1bit(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_byte(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +int accton_i2c_cpld_read(u8 cpld_addr, u8 reg); +int accton_i2c_cpld_write(u8 cpld_addr, u8 reg, u8 value); + + +struct base_attrs common_base_attrs[NUM_COMMON_ATTR] = +{ + [CMN_VERSION] = {"version", S_IRUGO, show_bit, NULL}, + [CMN_ACCESS] = {"access", S_IWUSR, NULL, set_byte}, + [CMN_PRESENT_ALL] = {"module_present_all", S_IRUGO, show_presnet_all, NULL}, + [CMN_RXLOS_ALL] = {"rx_los_all", S_IRUGO, show_rxlos_all, NULL}, +}; + +struct attrs common_attrs[] = { + [CMN_VERSION] = {0x01, false, &common_base_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {-1, false, &common_base_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {-1, false, &common_base_attrs[CMN_PRESENT_ALL]}, + [CMN_RXLOS_ALL] = {-1, false, &common_base_attrs[CMN_RXLOS_ALL]}, +}; +struct attrs plain_common[] = { + [CMN_VERSION] = {0x01, false, &common_base_attrs[CMN_VERSION]}, +}; + +struct base_attrs portly_attrs[] = +{ + [SFP_PRESENT] = {"present", S_IRUGO, show_bit, NULL}, + [SFP_RESET] = {0}, + [SFP_TX_DIS] = {"tx_disable", S_IRUGO|S_IWUSR, show_bit, set_1bit}, + [SFP_TX_FAULT] = {"tx_fault", S_IRUGO|S_IWUSR, show_bit, set_1bit}, + [SFP_RX_LOS] = {"rx_los", S_IRUGO|S_IWUSR, show_bit, set_1bit}, + [QSFP_PRESENT] = {"present", S_IRUGO, show_bit, NULL}, + [QSFP_LP_MODE] = {"low_power_mode", S_IRUGO|S_IWUSR, show_bit, set_1bit}, +}; + +struct attrs as7315_port[NUM_SFP_SB_ATTR] = { + {SFP_1ST_PRST_REG, true, &portly_attrs[SFP_PRESENT]}, + {0}, + {0x12, false, &portly_attrs[SFP_TX_DIS]}, + {0x11, false, &portly_attrs[SFP_TX_FAULT]}, + {SFP_1ST_RXLOS_REG, false, &portly_attrs[SFP_RX_LOS]}, + {QSFP_1ST_PRST_REG, true, &portly_attrs[QSFP_PRESENT]}, + {0x19, false, &portly_attrs[QSFP_LP_MODE]}, +}; + +struct attrs *as7315_cmn_list[] = { + &common_attrs[CMN_VERSION], + &common_attrs[CMN_ACCESS], + &common_attrs[CMN_PRESENT_ALL], + &common_attrs[CMN_RXLOS_ALL], + NULL +}; + +struct attrs *plain_cmn_list[] = { + &plain_common[CMN_VERSION], + NULL +}; + +struct attrs *as7315_qsfp_list[] = { + &as7315_port[QSFP_PRESENT], + &as7315_port[QSFP_LP_MODE], + NULL +}; + +struct attrs *as7315_sfp_list[] = { + &as7315_port[SFP_PRESENT], + &as7315_port[SFP_TX_DIS], + &as7315_port[SFP_TX_FAULT], + &as7315_port[SFP_RX_LOS], + NULL +}; + +struct model_attrs models_attr[NUM_MODEL] = { + {.cmn = as7315_cmn_list, .portly=as7315_sfp_list}, + {.cmn = as7315_cmn_list, .portly=as7315_qsfp_list}, + {.cmn = plain_cmn_list, .portly=NULL}, +}; + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; +/* Addresses scanned for as7315_i2c_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +struct chip_desc { + u8 nchans; + u8 deselectChan; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [MDL_CPLD_SFP] = {0}, + [MDL_CPLD_QSFP] = { + .nchans = 4, /*Fan + 3*LM75*/ + .deselectChan = 0, + }, +}; + +static const struct i2c_device_id as7315_cpld_id[] = { + { "as7315_cpld1", MDL_CPLD_SFP}, + { "as7315_cpld2", MDL_CPLD_QSFP}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, as7315_cpld_id); + + + + +static int get_sfp_spec(int model, u16 *num, u8 *types) +{ + switch (model) { + case MDL_CPLD_SFP: + *num = NUM_SFP; + *types = PT_SFP; + break; + case MDL_CPLD_QSFP: + *num = NUM_QSFP; + *types = PT_QSFP; + break; + default: + *types = 0; + *num = 0; + break; + } + + return 0; +} + +/*num: how many bits can be applied for this read.*/ +static int get_present_reg(int model, u8 port, u8 *reg, u8 *num) +{ + + switch (model) { + case MDL_CPLD_SFP: + if (port < NUM_SFP) { + *reg = SFP_1ST_PRST_REG + (port/8)*4; + *num = (NUM_SFP > 8)? 8 : NUM_SFP; + return 0; + } + break; + case MDL_CPLD_QSFP: + if (port < NUM_QSFP) { + *reg = QSFP_1ST_PRST_REG + (port/8); + *num = (NUM_QSFP > 8)? 8 : NUM_QSFP; + return 0; + } + break; + default: + return -EINVAL; + } + return -EINVAL; +} + +static int get_rxlos_reg(int model, u8 port, u8 *reg, u8 *num) +{ + + switch (model) { + case MDL_CPLD_SFP: + if (port < NUM_SFP) { + *reg = SFP_1ST_RXLOS_REG + (port/8)*4; + *num = (NUM_SFP > 8)? 8 : NUM_SFP; + return 0; + } + break; + default: + return -EINVAL; + } + return -EINVAL; +} + +static int cpld_write_internal( + struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + break; + } + return status; +} + +static int cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + break; + } + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 i, value, reg, num; + u64 values; + + i = num = reg =0; + values = 0; + mutex_lock(&data->update_lock); + while (i < data->sfp_num) + { + /*No rxlos for QSFP*/ + if (data->model == MDL_CPLD_QSFP) { + values = 0; + break; + } + get_rxlos_reg(data->model, i, ®, &num); + if (!(num > 0)) + { + value = -EINVAL; + goto exit; + } + value = cpld_read_internal(client, reg); + if (unlikely(value < 0)) { + goto exit; + } + values |= (value &((1<<(num))-1)) << i; + i += num; + } + mutex_unlock(&data->update_lock); + values = cpu_to_le64(values); + return snprintf(buf, sizeof(values)+1, "%llx\n", values); +exit: + mutex_unlock(&data->update_lock); + return value; +} + + +static ssize_t show_presnet_all(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 i, value, reg, num; + u64 values; + + i = num = reg =0; + values = 0; + mutex_lock(&data->update_lock); + while (i < data->sfp_num) + { + get_present_reg(data->model, i, ®, &num); + if (!(num > 0)) + { + value = -EINVAL; + goto exit; + } + value = cpld_read_internal(client, reg); + if (unlikely(value < 0)) { + goto exit; + } + values |= (~value&((1<<(num))-1)) << i; + i += num; + } + mutex_unlock(&data->update_lock); + values = cpu_to_le64(values); + return snprintf(buf, sizeof(values)+1, "%llx\n", values); +exit: + mutex_unlock(&data->update_lock); + return value; +} + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int value; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, sensor->reg); + value = value & sensor->mask; + if (sensor->invert) + value = !value; + mutex_unlock(&data->update_lock); + + return snprintf(buf, PAGE_SIZE, "%x\n", !!value); +} + +static ssize_t set_1bit(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + long is_reset; + int value, status; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + u8 cpld_bit, reg; + + status = kstrtol(buf, 10, &is_reset); + if (status) { + return status; + } + reg = sensor->reg; + cpld_bit = sensor->mask; + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + if (sensor->invert) + is_reset = !is_reset; + + if (is_reset) { + value |= cpld_bit; + } + else { + value &= ~cpld_bit; + } + + status = cpld_write_internal(client, reg, value); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_byte(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return access(dev, da, buf, count); +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void accton_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = + kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", + client->addr); + return; + } + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void accton_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int cpld_add_attribute(struct cpld_data *data, struct attribute *attr) +{ + int new_max_attrs = ++data->num_attributes + ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + data->group.attrs[data->num_attributes-1] = attr; + data->group.attrs[data->num_attributes] = NULL; + + return 0; +} + +static void cpld_dev_attr_init(struct device_attribute *dev_attr, + const char *name, umode_t mode, + show_func show, store_func store) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static struct cpld_sensor * add_sensor(struct cpld_data *data, + const char *name, + u8 reg, u8 mask, bool invert, + bool update, umode_t mode, + show_func get, store_func set) +{ + struct cpld_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), name); + sensor->reg = reg; + sensor->mask = mask; + sensor->update = update; + sensor->invert = invert; + cpld_dev_attr_init(a, sensor->name, + mode, + get, set); + + if (cpld_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int add_attributes_cmn(struct cpld_data *data, struct attrs **cmn) +{ + u8 reg, i ; + bool invert; + struct attrs *a; + struct base_attrs *b; + + if (NULL == cmn) + return -1; + + for (i = 0; cmn[i]; i++) + { + a = cmn[i]; + + reg = a->reg; + invert = a->invert; + + b = a->base; + if (NULL == b) + break; + + if (add_sensor(data, b->name, + reg, 0xff, invert, + true, b->mode, + b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + return 0; +} + +static int add_attributes_portly(struct cpld_data *data, struct attrs **pa) +{ + char name[NAME_SIZE+1]; + int i, j; + u8 reg, mask, invert, reg_start, jump; + struct attrs *a; + struct base_attrs *b; + + if (NULL == pa) + return -EFAULT; + + jump = 0; + if (data->sfp_types == PT_SFP) { + jump = 4; /*SFP sideband registers in set of 4 bytes.*/ + } else if (data->sfp_types == PT_QSFP) { + jump = 1; + } + + for (i = 0; pa[i]; i++) { + a = pa[i]; + reg_start = a->reg; + invert = a->invert; + b = a->base; + if (b == NULL) + break; + + for (j = 0; j < data->sfp_num; j++) + { + snprintf(name, NAME_SIZE, "%s_%d", b->name, j+1); + reg = reg_start + ((j/8)*jump); + mask = 1 << ((j)%8); + if (add_sensor(data, name, reg, mask, invert, + true, b->mode, b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + } + + + return 0; +} + +static int add_attributes(struct i2c_client *client, + struct cpld_data *data) +{ + struct model_attrs *m = data->attrs; + + if (m == NULL) + return -EINVAL; + + /* Common attributes.*/ + add_attributes_cmn(data, m->cmn); + + /* Port-wise attributes.*/ + add_attributes_portly(data, m->portly); + + return 0; +} + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int _cpld_mux_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + unsigned long orig_jiffies; + unsigned short flags; + union i2c_smbus_data data; + int try; + s32 res = -EIO; + + data.byte = val; + flags = client->flags; + flags &= ~(I2C_M_TEN | I2C_CLIENT_PEC); + + if (adap->algo->smbus_xfer) { + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (res = 0, try = 0; try <= adap->retries; try++) { + res = adap->algo->smbus_xfer(adap, client->addr, flags, + I2C_SMBUS_WRITE, MUX_CHANNEL_SELECT_REG, + I2C_SMBUS_BYTE_DATA, &data); + if (res != -EAGAIN) + break; + if (time_after(jiffies, + orig_jiffies + adap->timeout)) + break; + } + } + + return res; +} + + +static int _mux_select_chan(struct i2c_mux_core *muxc, + u32 chan) +{ + u8 regval; + struct i2c_client *client = i2c_mux_priv(muxc); + int ret = 0; + + regval = (chan+1) << 5; + ret = _cpld_mux_reg_write(muxc->parent, client, regval); + if (unlikely(ret < 0)) { + return ret; + } + return ret; +} + + +static int _prealloc_attrs(struct cpld_data *data) +{ + void *new_attrs = krealloc(data->group.attrs, + ATTR_ALLOC_SIZE * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + + return 0; +} + +static int _add_sysfs_attributes(struct i2c_client *client, + struct cpld_data *data) +{ + int status; + + status = add_attributes(client, data); + if (status) { + return status; + } + + /*If there are no attributes, something is wrong. + * Bail out instead of trying to register nothing. + */ + if (!data->num_attributes) { + dev_err(&client->dev, "No attributes found\n"); + return -ENODEV; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->group); + if (status) { + return status; + } + + return 0; +} + + +static int _add_mux_channels(struct i2c_client *client, + const struct i2c_device_id *id, struct cpld_data *data) +{ + int num, force, class; + int status; + struct i2c_mux_core *muxc; + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + int model = id->driver_data; + + data->muxc = i2c_mux_alloc(adap, &client->dev, + chips[model].nchans, + sizeof(client), 0, + _mux_select_chan, NULL); + + if (!data->muxc) { + return ENOMEM; + } + muxc = data->muxc; + muxc->priv = client; + for (num = 0; num < chips[model].nchans; num++) { + force = 0; /* dynamic adap number */ + class = 0; /* no class by default */ + status = i2c_mux_add_adapter(muxc, force, num, class); + if (status) + return status ; + } + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s\n", + num, client->name); + + return 0; +} + +static int as7315_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + int status; + struct cpld_data *data = NULL; + struct device *dev = &client->dev; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + data->model = dev_id->driver_data; + data->attrs = &models_attr[data->model]; + get_sfp_spec(data->model, &data->sfp_num, &data->sfp_types); + mutex_init(&data->update_lock); + data->dev = dev; + dev_info(dev, "chip found\n"); + + + status = _prealloc_attrs(data); + if (status) + return -ENOMEM; + + status = _add_sysfs_attributes(client, data); + if (status) + goto out_kfree; + + status = _add_mux_channels(client, dev_id, data); + if (status) + goto exit_rm_sys; + + i2c_set_clientdata(client, data); + accton_i2c_cpld_add_client(client); + dev_info(dev, "%s: cpld '%s'\n", + dev_name(data->dev), client->name); + + return 0; + +exit_rm_sys: + sysfs_remove_group(&client->dev.kobj, &data->group); +out_kfree: + kfree(data->group.attrs); + return status; +} + + +static int as7315_i2c_cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + struct i2c_mux_core *muxc = data->muxc; + + sysfs_remove_group(&client->dev.kobj, &data->group); + kfree(data->group.attrs); + if(muxc) { + i2c_mux_del_adapters(muxc); + } + accton_i2c_cpld_remove_client(client); + return 0; +} + +int accton_i2c_cpld_read(u8 cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_read); + +int accton_i2c_cpld_write(u8 cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_write); + + +static struct i2c_driver as7315_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRV_NAME, + }, + .probe = as7315_i2c_cpld_probe, + .remove = as7315_i2c_cpld_remove, + .id_table = as7315_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init as7315_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7315_i2c_cpld_driver); +} + +static void __exit as7315_i2c_cpld_exit(void) +{ + i2c_del_driver(&as7315_i2c_cpld_driver); +} + +module_init(as7315_i2c_cpld_init); +module_exit(as7315_i2c_cpld_exit); + +MODULE_AUTHOR("Roy Lee "); +MODULE_DESCRIPTION("as7315_i2c_cpld driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-led.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-led.c new file mode 100755 index 000000000000..fefb44fad33f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-led.c @@ -0,0 +1,408 @@ +/* + * A LED driver for the accton_as7315_27xb_led + * + * Copyright (C) 2019 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7315_27xb_led" +#define CPLD_I2C_ADDR 0x64 + +enum led_type { + TYPE_DIAG, + TYPE_LOC, + TYPE_MAX +}; + +struct led_list_s { + enum led_type type; + char name[64]; + u8 reg_addr; + u8 slave_addr; +} led_list[TYPE_MAX] = { + {TYPE_DIAG, "as7315_27xb_diag", 0x41, CPLD_I2C_ADDR}, + {TYPE_LOC, "as7315_27xb_loc", 0x40, CPLD_I2C_ADDR} +}; + +struct accton_as7315_27xb_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 slave_addr[TYPE_MAX]; /* For LOC and DIAG.*/ + u8 reg_addr[TYPE_MAX]; /* For LOC and DIAG.*/ + u8 reg_val[TYPE_MAX]; /* Register value, 0 = LOC + 1 = DIAG */ +}; +static struct accton_as7315_27xb_led_data *ledctl = NULL; + +/* LED related data + */ +#define TYPE_DIAG_REG_MASK 0x30 +#define MODE_DIAG_GREEN_MASK 0x10 +#define MODE_DIAG_AMBER_MASK 0x20 +#define MODE_DIAG_GBLINK_MASK 0x00 +#define MODE_DIAG_OFF_MASK 0x30 + +#define TYPE_LOC_REG_MASK 0x40 +#define MODE_LOC_OFF_MASK 0x40 +#define MODE_LOC_BLINK_MASK 0x00 + + +typedef enum onlp_led_mode_e { + ONLP_LED_MODE_OFF, + ONLP_LED_MODE_ON, + ONLP_LED_MODE_BLINKING, + ONLP_LED_MODE_RED = 10, + ONLP_LED_MODE_RED_BLINKING = 11, + ONLP_LED_MODE_ORANGE = 12, + ONLP_LED_MODE_ORANGE_BLINKING = 13, + ONLP_LED_MODE_YELLOW = 14, + ONLP_LED_MODE_YELLOW_BLINKING = 15, + ONLP_LED_MODE_GREEN = 16, + ONLP_LED_MODE_GREEN_BLINKING = 17, + ONLP_LED_MODE_BLUE = 18, + ONLP_LED_MODE_BLUE_BLINKING = 19, + ONLP_LED_MODE_PURPLE = 20, + ONLP_LED_MODE_PURPLE_BLINKING = 21, + ONLP_LED_MODE_AUTO = 22, + ONLP_LED_MODE_AUTO_BLINKING = 23, +} onlp_led_mode_t; + + +struct led_type_mode { + enum led_type type; + int type_mask; + enum onlp_led_mode_e mode; + int mode_mask; +}; + +static struct led_type_mode led_type_mode_data[] = { + {TYPE_DIAG, TYPE_DIAG_REG_MASK, ONLP_LED_MODE_GREEN_BLINKING, MODE_DIAG_GBLINK_MASK}, + {TYPE_DIAG, TYPE_DIAG_REG_MASK, ONLP_LED_MODE_GREEN, MODE_DIAG_GREEN_MASK}, + {TYPE_DIAG, TYPE_DIAG_REG_MASK, ONLP_LED_MODE_ORANGE, MODE_DIAG_AMBER_MASK}, + {TYPE_DIAG, TYPE_DIAG_REG_MASK, ONLP_LED_MODE_OFF, MODE_DIAG_OFF_MASK}, + {TYPE_LOC, TYPE_LOC_REG_MASK, ONLP_LED_MODE_BLUE_BLINKING, MODE_LOC_BLINK_MASK}, + {TYPE_LOC, TYPE_LOC_REG_MASK, ONLP_LED_MODE_OFF, MODE_LOC_OFF_MASK}, +}; + +extern int accton_i2c_cpld_read (u8 cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(u8 cpld_addr, u8 reg, u8 value); + + +static int pdata_init(struct accton_as7315_27xb_led_data *data) { + int i; + + for (i=0; ireg_addr[i] = led_list[i].reg_addr; + data->slave_addr[i] = led_list[i].slave_addr; + } + + return 0; +} + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum onlp_led_mode_e mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + } + + return reg_val; +} + +static int accton_as7315_27xb_led_read_value(u8 slave, u8 reg) +{ + return accton_i2c_cpld_read(slave, reg); +} + +static int accton_as7315_27xb_led_write_value(u8 slave, u8 reg, u8 value) +{ + return accton_i2c_cpld_write(slave, reg, value); +} + +static void accton_as7315_27xb_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7315_27xb_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status; + u8 addr, offset; + addr = ledctl->slave_addr[i]; + offset = ledctl->reg_addr[i]; + status = accton_as7315_27xb_led_read_value(addr, offset); + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", ledctl->reg_addr[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7315_27xb_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 addr, offset; + + if (type >= ARRAY_SIZE(led_list)) { + dev_dbg(&ledctl->pdev->dev, "Illegal type:%d\n", type); + return; + } + mutex_lock(&ledctl->update_lock); + addr = ledctl->slave_addr[type], + offset = ledctl->reg_addr[type], + reg_val = accton_as7315_27xb_led_read_value(addr, offset); + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", offset, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7315_27xb_led_write_value(addr, offset, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static enum led_type get_led_type(struct led_classdev *cdev) +{ + int i; + + for (i=0; iname)) + return i; + } + return -EINVAL; +} + +static void led_mode_set(struct led_classdev *cdev, + enum led_brightness led_light_mode) +{ + enum led_type type; + + type = get_led_type(cdev); + if (type < 0) { + dev_dbg(&ledctl->pdev->dev, "Found no corresponding type:%d\n", type); + return ; + } + accton_as7315_27xb_led_set(cdev, led_light_mode, type); +} + +static enum led_brightness led_mode_get(struct led_classdev *cdev) +{ + enum led_type type; + + type = get_led_type(cdev); + if (type < 0) + return type; + + accton_as7315_27xb_led_update(); + return led_reg_val_to_light_mode(type, ledctl->reg_val[type]); +} + +static struct led_classdev accton_as7315_27xb_leds[TYPE_MAX] = { + [TYPE_DIAG] = { + .name = led_list[TYPE_DIAG].name, + .default_trigger = "unused", + .brightness_set = led_mode_set, + .brightness_get = led_mode_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = ONLP_LED_MODE_AUTO, + }, + [TYPE_LOC] = { + .name = led_list[TYPE_LOC].name, + .default_trigger = "unused", + .brightness_set = led_mode_set, + .brightness_get = led_mode_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = ONLP_LED_MODE_AUTO, + }, +}; + +static int accton_as7315_27xb_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7315_27xb_leds); i++) { + led_classdev_suspend(&accton_as7315_27xb_leds[i]); + } + + return 0; +} + +static int accton_as7315_27xb_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7315_27xb_leds); i++) { + led_classdev_resume(&accton_as7315_27xb_leds[i]); + } + + return 0; +} + +static int accton_as7315_27xb_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7315_27xb_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7315_27xb_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7315_27xb_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7315_27xb_leds[i]); + } + } + + return ret; +} + +static int accton_as7315_27xb_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7315_27xb_leds); i++) { + led_classdev_unregister(&accton_as7315_27xb_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7315_27xb_led_driver = { + .probe = accton_as7315_27xb_led_probe, + .remove = accton_as7315_27xb_led_remove, + .suspend = accton_as7315_27xb_led_suspend, + .resume = accton_as7315_27xb_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7315_27xb_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7315_27xb_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7315_27xb_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7315_27xb_led_driver); + goto exit; + } + + pdata_init(ledctl); + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7315_27xb_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7315_27xb_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7315_27xb_led_driver); + kfree(ledctl); +} + +module_init(accton_as7315_27xb_led_init); +module_exit(accton_as7315_27xb_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7315_27xb_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-psu.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-psu.c new file mode 100644 index 000000000000..1cf6313eab09 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/x86-64-accton-as7315-27xb-psu.c @@ -0,0 +1,454 @@ +/* + * An hwmon driver for accton as7315_27xb Power Module + * + * Copyright (C) 2019 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "as7315_27xb_psu" +#define PSU_STATUS_I2C_ADDR 0x64 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 +#define USE_BYTE_ACCESS 0 /*Somehow i2c block access is failed on this platform.*/ +#define UPDATE_PERIOD (HZ*2) +#define MAX_OUTPUT_LENGTH 32 +#define BASIC_EEPROM_SIZE 32 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id + 2))) +#define IS_PRESENT(id, value) (!(value & BIT(id))) + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7315_27xb_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char eeprom[BASIC_EEPROM_SIZE*2]; /* EEPROM*/ +}; + + +enum as7315_27xb_psu_sysfs_attributes { + PSU_INDEX, + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +enum psu_type { + PSU_YM_1401_A, /* AC110V - B2F */ + PSU_YM_2401_JCR, /* AC110V - F2B */ + PSU_YM_2401_JDR, /* AC110V - B2F */ + PSU_YM_2401_TCR, /* AC110V - B2F */ + PSU_CPR_4011_4M11, /* AC110V - F2B */ + PSU_CPR_4011_4M21, /* AC110V - B2F */ + PSU_CPR_6011_2M11, /* AC110V - F2B */ + PSU_CPR_6011_2M21, /* AC110V - B2F */ + PSU_UM400D_01G, /* DC48V - F2B */ + PSU_UM400D01_01G, /* DC48V - B2F */ + PSU_BEL_TOT120, /* DC48V - N/A */ + PSU_TYPE_MAX +}; + +struct model_info { + enum psu_type type; + u8 offset; + char* model_name; + u8 serial_offset; +}; + +struct model_info models[] = { + {PSU_YM_1401_A, 0x20, "YM-1401ACR",0x35}, + {PSU_YM_2401_JCR, 0x20, "YM-2401JCR",0x35}, + {PSU_YM_2401_JDR, 0x20, "YM-2401JDR",0x35}, + {PSU_YM_2401_TCR, 0x20, "YM-2401TCR",0x35}, + {PSU_CPR_4011_4M11, 0x26, "CPR-4011-4M11",0x47}, + {PSU_CPR_4011_4M21, 0x26, "CPR-4011-4M21",0x47}, + {PSU_CPR_6011_2M11, 0x26, "CPR-6011-2M11",0x46}, + {PSU_CPR_6011_2M21, 0x26, "CPR-6011-2M21",0x46}, + {PSU_UM400D_01G, 0x50, "um400d01G",0x50}, + {PSU_UM400D01_01G, 0x50, "um400d01-01G",0x50}, + {PSU_BEL_TOT120, 0x0A, "CRXT-T0T120",0x18}, +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_serial_number(struct device *dev, struct device_attribute *da,char *buf); +static int as7315_27xb_psu_block_read(struct i2c_client *client, u8 command, u8 *data,int data_len); +static int as7315_27xb_psu_model_name_get( + struct device *dev, char *buf); +static int as7315_27xb_psu_serial_number_get( + struct device *dev, enum psu_type type, char *out); +static struct as7315_27xb_psu_data *as7315_27xb_psu_update_device(struct device *dev); +extern int accton_i2c_cpld_read(u8 cpld_addr, u8 reg); + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_serial, S_IRUGO, show_serial_number, NULL, PSU_SERIAL_NUMBER); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7315_27xb_psu_attributes[] = { + &sensor_dev_attr_psu_index.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_serial.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_index(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7315_27xb_psu_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->index); +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7315_27xb_psu_data *data = as7315_27xb_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_serial_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i; + struct as7315_27xb_psu_data *data = as7315_27xb_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + i = as7315_27xb_psu_model_name_get(dev, buf); + if ( i < 0) { + return -ENXIO; + } + + if (as7315_27xb_psu_serial_number_get(dev, i, buf) < 0) { + return -ENXIO; + } + return sprintf(buf, "%s\n", buf); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7315_27xb_psu_data *data = as7315_27xb_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!IS_PRESENT(data->index, data->status)) { + return 0; + } + + if (as7315_27xb_psu_model_name_get(dev, buf) < 0) { + return -ENXIO; + } + + return sprintf(buf, "%s\n", buf); +} + +static const struct attribute_group as7315_27xb_psu_group = { + .attrs = as7315_27xb_psu_attributes, +}; + +static int as7315_27xb_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7315_27xb_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7315_27xb_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7315_27xb_psu_group); + if (status) { + goto exit_free; + } + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, + client->name, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7315_27xb_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7315_27xb_psu_remove(struct i2c_client *client) +{ + struct as7315_27xb_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7315_27xb_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7315_27xb_psu1, + as7315_27xb_psu2 +}; + +static const struct i2c_device_id as7315_27xb_psu_id[] = { + { "as7315_27xb_psu1", as7315_27xb_psu1 }, + { "as7315_27xb_psu2", as7315_27xb_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7315_27xb_psu_id); + +static struct i2c_driver as7315_27xb_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRV_NAME, + }, + .probe = as7315_27xb_psu_probe, + .remove = as7315_27xb_psu_remove, + .id_table = as7315_27xb_psu_id, + .address_list = normal_i2c, +}; + +static int as7315_27xb_psu_block_read(struct i2c_client *client, + u8 command, u8 *data, int max_len) +{ + int result; + + u8 i, offset; + + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + for (i = 0; i < max_len; i += 32) { + offset = i + command ; + result = i2c_smbus_read_i2c_block_data(client, offset, + 32, data + i); + + if (result != 32) { + result = -EIO; + goto abort; + } + } + + } else { + for (i = 0; i < max_len; i += 2) { + int word; + offset = i + command ; + word = i2c_smbus_read_word_data(client, offset); + if (word < 0) { + result = -EIO; + goto abort; + } + data[i] = word & 0xff; + data[i + 1] = word >> 8; + } + } + result = 0; +abort: + return result; +} + +static int as7315_27xb_psu_serial_number_get( + struct device *dev, enum psu_type type, char *out) +{ + char *serial; + struct as7315_27xb_psu_data *data = as7315_27xb_psu_update_device(dev); + + if (type >= PSU_TYPE_MAX) { + return -EINVAL; + } + + if (!data->valid) { + out[0] = '\0'; + return 0; + } + + serial = data->eeprom + models[type].serial_offset; + strncpy(out, serial, MAX_OUTPUT_LENGTH); + return 0; +} + +static int find_model_name_from_eeprom( char *eeprom) +{ + int i; + char *name; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + name = eeprom + models[i].offset; + if (strncmp(name, models[i].model_name, + strlen(models[i].model_name)) == 0) { + break; + } + } + + return (i == ARRAY_SIZE(models))? -EINVAL: i; +} +static int as7315_27xb_psu_model_name_get( + struct device *dev, char *buf) +{ + int i; + struct as7315_27xb_psu_data *data = as7315_27xb_psu_update_device(dev); + + if (!data->valid) { + return sprintf(buf, "0\n"); + } + + /* Determine if the model name is known, if not, read next index + */ + i = find_model_name_from_eeprom(data->eeprom); + if (i < 0) { + return -ENODATA; + } + + mutex_lock(&data->update_lock); + strncpy(buf, models[i].model_name, MAX_OUTPUT_LENGTH); + /*Work-around for some special models*/ + if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR || + i == PSU_YM_1401_A || i == PSU_YM_2401_TCR) { + /* Skip the meaningless data byte 8*/ + buf[8] = buf[9]; + buf[9] = buf[10]; + buf = '\0'; + } + + mutex_unlock(&data->update_lock); + return i; +} + +static struct as7315_27xb_psu_data *as7315_27xb_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7315_27xb_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + UPDATE_PERIOD) + || !data->valid) { + int status = -1; + + dev_dbg(&client->dev, "Starting as7315_27xb update\n"); + data->valid = 0; + + /* Read psu status */ + status = accton_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + if (status < 0) { + dev_dbg(&client->dev, + "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + + /*Read the eeprom of psu*/ + memset(data->eeprom, 0, sizeof(data->eeprom)); + status = as7315_27xb_psu_block_read(client, 0, + data->eeprom, sizeof(data->eeprom)); + + if (status < 0) { + dev_dbg(&client->dev, "unable to read eeprom from (0x%x)\n", + client->addr); + goto exit; + } + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +module_i2c_driver(as7315_27xb_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7315_27xb_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/service/as7315-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/service/as7315-platform-init.service new file mode 100755 index 000000000000..cdaf437166bd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/service/as7315-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Accton AS7315-27XB Platform initialization service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7315_util.py install +ExecStart=/usr/local/bin/accton_as7315_monitor.py +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/setup.py new file mode 100755 index 000000000000..09187900c7ee --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7315_27xb', + version='1.0', + description='Module to initialize Accton AS7315-27XB platforms', + + packages=['as7315_27xb'], + package_dir={'as7315_27xb': 'as7315-27xb/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README new file mode 100755 index 000000000000..0561fe7a2775 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/README @@ -0,0 +1,60 @@ +Copyright (C) 2019 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +To initialize the system, run "accton_as7315_util.py install". +To clean up the drivers & devices, run "accton_as7315_util.py clean". +To dump information of sensors, run "accton_as7315_util.py show". +To dump SFP EEPROM, run "accton_as7315_util.py sff". +To set fan speed, run "accton_as7315_util.py set fan". +To enable/disable SFP emission, run "accton_as7315_util.py set sfp". +To set system LEDs' color, run "accton_as7315_util.py set led" +For more information, run "accton_as7315_util.py --help". + +==================================================================== +Besides applying accton_as7315_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +LED controls can be found under /sys/class/leds. The sysfs interface +color mappings are as follows: +Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + +There are 5 system LEDs, loc, diag, fan, ps1, and ps2. +They are lit automatically by CPLD, but the loc and diag. +The loc led has only 1 color, blue. +The diag one has 3 colors: red, amber, and green. + +Fan controls can be found in /sys/bus/i2c/devices/2-0066. +There are 10 fans inside 5 fan modules. +All fans share 1 duty setting, ranged from 0~100. + +Three temperature sensors are controlled by the lm75 kernel modules. +They should already be visible under /sys/bus/i2c/drivers/lm75/. + +Two power supplies are controlled by the CPLD. +Here provide their status under +/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. + +There are QSFP/SFP modules are equipped. +Apply "accton_as7315_util.py show" to get their status. +Apply "accton_as7315_util.py set sfp" to turn on/off light transmission. +Apply "accton_as7315_util.py sff" to dump EEPROM information. +Before operating on that QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py new file mode 100755 index 000000000000..d5b868255f4a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_monitor.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 8/02/2019: Roy Lee modify for as7315_27x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from as7315_27xb.fanutil import FanUtil + from as7315_27xb.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7315_monitor' +DUTY_MAX = 100 +DUTY_DEF = 40 + +global log_file +global log_console + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7315_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + llog = logging.getLogger("["+FUNCTION_NAME+"]") + def __init__(self, log_console, log_file): + """Needs a logger and a logger level.""" + formatter = logging.Formatter('%(name)s %(message)s') + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setFormatter(formatter) + sys_handler.ident = 'common' + sys_handler.setLevel(logging.WARNING) #only fatal for syslog + self.llog.addHandler(sys_handler) + self.llog.setLevel(logging.DEBUG) + + if log_file: + fh = logging.FileHandler(log_file) + fh.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s') + fh.setFormatter(formatter) + self.llog.addHandler(fh) + + # set up logging to console + if log_console: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) #For debugging + formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s') + console.setFormatter(formatter) + self.llog.addHandler(console) + + def manage_fans(self): + max_duty = DUTY_MAX + fan_policy = { + 0: [52, 0, 43000], + 1: [63, 43000, 46000], + 2: [75, 46000, 52000], + 3: [88, 52000, 57000], + 4: [max_duty, 57000, sys.maxsize], + } + + thermal = ThermalUtil() + fan = FanUtil() + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + self.llog.debug('SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + return False + if fan_status is False: + self.llog.debug('SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + fan.set_fan_duty_cycle(max_duty) + return True + + #Find if current duty matched any of define duty. + #If not, set it to highest one. + cur_duty_cycle = fan.get_fan_duty_cycle() + new_duty_cycle = DUTY_DEF + for x in range(0, len(fan_policy)): + if cur_duty_cycle == fan_policy[x][0]: + break + if x == len(fan_policy) : + fan.set_fan_duty_cycle(fan_policy[0][0]) + cur_duty_cycle = max_duty + + #Decide fan duty by if sum of sensors falls into any of fan_policy{} + get_temp = thermal.get_thermal_temp() + for x in range(0, len(fan_policy)): + y = len(fan_policy) - x -1 #checked from highest + if get_temp > fan_policy[y][1] and get_temp < fan_policy[y][2] : + new_duty_cycle = fan_policy[y][0] + self.llog.debug('Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + + self.llog.debug('Final duty_cycle=%d', new_duty_cycle) + if(new_duty_cycle != cur_duty_cycle): + fan.set_fan_duty_cycle(new_duty_cycle) + return True + +def sig_handler(signum, frame): + fan = FanUtil() + logging.critical('Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_console = 0 + log_file = "" + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl') + except getopt.GetoptError: + print 'Usage: %s [-d] [-l]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l]' % sys.argv[0] + return 0 + elif opt in ('-d'): + log_console = 1 + elif opt in ('-l'): + log_file = '%s.log' % sys.argv[0] + + signal.signal(signal.SIGINT, sig_handler) + signal.signal(signal.SIGTERM, sig_handler) + monitor = accton_as7315_monitor(log_console, log_file) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py new file mode 100755 index 000000000000..e3810e42102e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7315-27xb/utils/accton_as7315_util.py @@ -0,0 +1,535 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + + + + +PROJECT_NAME = 'as7315_27xb' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':2, 'fan':5,'thermal':3, 'psu':2, 'sfp':27} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + +qsfp_start_index = 24 + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-1 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-27 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-27 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe optoe', +'modprobe ym2651y', +'modprobe accton_as7315_27xb_fan', +'modprobe at24_as7315_27xb', +'modprobe x86-64-accton-as7315_27xb-cpld', +'modprobe x86-64-accton-as7315_27xb-led', +'modprobe x86-64-accton-as7315_27xb-psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + #remove parameter if any + rm = kos[-(i+1)] + lst = rm.split(" ") + if len(lst) > 2: + del(lst[2:]) + rm = " ".join(lst) + + #Change to removing commands + rm = rm.replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_' +hwmon_types = {'led': ['diag','loc']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['50-0066'] , + 'thermal': ['51-0049','52-004a', '53-004c'] , + 'psu': ['13-0053','12-0050'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'input'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present', 'psu_power_good'] , + 'sfp': ['present']} + +sfp_map = [26,27,28,29,30,31,32,33, + 34,35,36,37,38,39,40,41, + 42,43,44,45,46,47,48,49, + 21, 22, 23] + +mknod =[ +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-19/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-20/new_device', + +'echo as7315_cpld1 0x63 > /sys/bus/i2c/devices/i2c-8/new_device', +'echo as7315_cpld2 0x64 > /sys/bus/i2c/devices/i2c-7/new_device', + +'echo 24cxb04 0x57 > /sys/bus/i2c/devices/i2c-4/new_device', +'echo as7315_27xb_psu2 0x50 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as7315_27xb_psu1 0x53 > /sys/bus/i2c/devices/i2c-13/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-13/new_device', +'echo as7315_fan 0x66 > /sys/bus/i2c/devices/i2c-50/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-51/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-52/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-53/new_device', +] + +def i2c_order_check(): + return 0 + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + path = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device" + if 1 >= qsfp_start_index: + status, output =log_os_system("echo optoe1 0x50 > " + path, 1) + else: + status, output =log_os_system("echo optoe2 0x50 > " + path, 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + if k > qsfp_start_index: + fmt = i2c_prefix+"7-0064/{0}_{1}" + else: + fmt = i2c_prefix+"8-0063/{0}_{1}" + path = fmt.format(nodes[j], (k%qsfp_start_index)+1) + + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + i = int(index)-1 + node = i2c_prefix+ str(sfp_map[i])+ i2c_bus['sfp'][0]+"/"+ 'eeprom' + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system(hex_cmd +" -C "+node, 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0076", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/fanutil.py new file mode 100755 index 000000000000..91ca21aa528e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/fanutil.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 3/23/2018: Roy Lee modify for as7326_56x +# 6/26/2018: Jostar implement by new thermal policy from HW RD +# ------------------------------------------------------------------ +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/11-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/11-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + #logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/thermalutil.py new file mode 100755 index 000000000000..9087ff1c38f4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/classes/thermalutil.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 3/23/2018: Roy Lee modify for as7326_56x +# 6/26/2018: Jostar implement by new thermal policy from HW RD +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + if show: + print "ACC: " + str(cmd) + " , result:"+ str(status) + + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_MAX = 6 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD. LM75 + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 + THERMAL_NUM_4_IDX = 4 # CPU board. LM75 + THERMAL_NUM_5_IDX = 5 # CPU core thermal + THERMAL_NUM_6_IDX = 6 # BCM thermal + + BCM_thermal_cmd = 'bcmcmd "show temp" > /tmp/bcm_thermal' + BCM_thermal_path = '/tmp/bcm_thermal' + #BCM_thermal_path = '/tmp/bcm_debug' + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + #_thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['15', '48'], + THERMAL_NUM_2_IDX: ['15', '49'], + THERMAL_NUM_3_IDX: ['15', '4a'], + THERMAL_NUM_4_IDX: ['15', '4b'], + } + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/drivers/lm75/15-0048/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/drivers/lm75/15-0049/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/drivers/lm75/15-004a/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/drivers/lm75/15-004b/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_5_IDX: ["/sys/class/hwmon/hwmon0/temp1_input"], + } + + #def __init__(self): + + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + if thermal_num < self.THERMAL_NUM_6_IDX: + device_path = self.get_thermal_to_device_path(thermal_num) + + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + return int(content) + + else: + log_os_system(self.BCM_thermal_cmd,0) + file_path = self.BCM_thermal_path + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return 0 + file_str = check_file.read() + search_str="average current temperature is" + str_len = len(search_str) + idx=file_str.find(search_str) + if idx==-1: + logging.debug('bcm sdk is not ready ,retrun 0') + return 0 + else: + temp_str=file_str[idx+str_len+1] + file_str[idx+str_len+2] + file_str[idx+str_len+3]+file_str[idx+str_len+4] +file_str[idx+str_len+5] + check_file.close() + return float(temp_str)*1000 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_to_device_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +def main(): + thermal = ThermalUtil() + logging.debug('thermal1=%d' ,thermal._get_thermal_val(1)) + logging.debug('thermal2=%d' ,thermal._get_thermal_val(2)) + logging.debug('thermal3=%d' ,thermal._get_thermal_val(3)) + logging.debug('thermal4=%d' ,thermal._get_thermal_val(4)) + logging.debug('thermal5=%d' ,thermal._get_thermal_val(5)) + logging.debug('thermal6=%d' ,thermal._get_thermal_val(6)) + +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/Makefile new file mode 100755 index 000000000000..85c066571c2f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_i2c_cpld.o \ + accton_as7326_56x_fan.o accton_as7326_56x_leds.o \ + accton_as7326_56x_psu.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_fan.c new file mode 100755 index 000000000000..606019f3ea44 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_fan.c @@ -0,0 +1,815 @@ +/* + * A hwmon driver for the Accton as7326 56x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7326_56x_fan" + +#define NUM_THERMAL_SENSORS (3) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a} + +#define IN +#define OUT + +static struct as7326_56x_fan_data *as7326_56x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7326_56x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as7326_56x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7326_56x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7326_56x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7326_56x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7326_56x_fan_data *data = as7326_56x_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7326_56x_fan_data *data = as7326_56x_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0) + return -EINVAL; + + value = (value > FAN_MAX_DUTY_CYCLE)? FAN_MAX_DUTY_CYCLE : value; + + as7326_56x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7326_56x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + OUT int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as7326_56x_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as7326_56x_fan_data *data = as7326_56x_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7326_56x_fan_data *data = as7326_56x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7326_56x_fan_group = { + .attrs = as7326_56x_fan_attributes, +}; + +static struct as7326_56x_fan_data *as7326_56x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7326_56x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7326_56x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7326_56x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7326_56x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7326_56x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->enable = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7326_56x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7326_56x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7326_56x_fan_remove(struct i2c_client *client) +{ + struct as7326_56x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7326_56x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7326_56x_fan_id[] = { + { "as7326_56x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7326_56x_fan_id); + +static struct i2c_driver as7326_56x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7326_56x_fan_probe, + .remove = as7326_56x_fan_remove, + .id_table = as7326_56x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7326_56x_fan_init(void) +{ + return i2c_add_driver(&as7326_56x_fan_driver); +} + +static void __exit as7326_56x_fan_exit(void) +{ + i2c_del_driver(&as7326_56x_fan_driver); +} + +module_init(as7326_56x_fan_init); +module_exit(as7326_56x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7326_56x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_leds.c new file mode 100644 index 000000000000..54df5b09eea8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_leds.c @@ -0,0 +1,437 @@ +/* + * A LED driver for the accton_as7326_56x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as7326_56x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as7326_56x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "accton_as7326_56x_led" + +struct accton_as7326_56x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct accton_as7326_56x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7326_56x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as7326_56x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7326_56x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as7326_56x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7326_56x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as7326_56x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7326_56x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as7326_56x_led_diag_get(struct led_classdev *cdev) +{ + accton_as7326_56x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as7326_56x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7326_56x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as7326_56x_led_loc_get(struct led_classdev *cdev) +{ + accton_as7326_56x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as7326_56x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7326_56x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev accton_as7326_56x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as7326_56x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as7326_56x_led_diag_set, + .brightness_get = accton_as7326_56x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "accton_as7326_56x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as7326_56x_led_loc_set, + .brightness_get = accton_as7326_56x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "accton_as7326_56x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7326_56x_led_auto_set, + .brightness_get = accton_as7326_56x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as7326_56x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7326_56x_led_auto_set, + .brightness_get = accton_as7326_56x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as7326_56x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7326_56x_led_auto_set, + .brightness_get = accton_as7326_56x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as7326_56x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7326_56x_leds); i++) { + led_classdev_suspend(&accton_as7326_56x_leds[i]); + } + + return 0; +} + +static int accton_as7326_56x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7326_56x_leds); i++) { + led_classdev_resume(&accton_as7326_56x_leds[i]); + } + + return 0; +} + +static int accton_as7326_56x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7326_56x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7326_56x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7326_56x_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7326_56x_leds[i]); + } + } + + return ret; +} + +static int accton_as7326_56x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7326_56x_leds); i++) { + led_classdev_unregister(&accton_as7326_56x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7326_56x_led_driver = { + .probe = accton_as7326_56x_led_probe, + .remove = accton_as7326_56x_led_remove, + .suspend = accton_as7326_56x_led_suspend, + .resume = accton_as7326_56x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7326_56x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7326_56x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7326_56x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7326_56x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7326_56x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7326_56x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7326_56x_led_driver); + kfree(ledctl); +} + +module_init(accton_as7326_56x_led_init); +module_exit(accton_as7326_56x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7326_56x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_psu.c new file mode 100644 index 000000000000..8c2ece6200fe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_as7326_56x_psu.c @@ -0,0 +1,277 @@ +/* + * An hwmon driver for accton as7326_56x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as7326_56x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7326_56x_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7326_56x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[9]; /* Model name, read from eeprom */ +}; + +static struct as7326_56x_psu_data *as7326_56x_psu_update_device(struct device *dev); + +enum as7326_56x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7326_56x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7326_56x_psu_data *data = as7326_56x_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7326_56x_psu_data *data = as7326_56x_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as7326_56x_psu_group = { + .attrs = as7326_56x_psu_attributes, +}; + +static int as7326_56x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7326_56x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7326_56x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7326_56x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7326_56x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7326_56x_psu_remove(struct i2c_client *client) +{ + struct as7326_56x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7326_56x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7326_56x_psu1, + as7326_56x_psu2 +}; + +static const struct i2c_device_id as7326_56x_psu_id[] = { + { "as7326_56x_psu1", as7326_56x_psu1 }, + { "as7326_56x_psu2", as7326_56x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7326_56x_psu_id); + +static struct i2c_driver as7326_56x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7326_56x_psu", + }, + .probe = as7326_56x_psu_probe, + .remove = as7326_56x_psu_remove, + .id_table = as7326_56x_psu_id, + .address_list = normal_i2c, +}; + +static int as7326_56x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7326_56x_psu_data *as7326_56x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as7326_56x update\n"); + + /* Read psu status */ + status = as7326_56x_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as7326_56x_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as7326_56x_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7326_56x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_i2c_cpld.c new file mode 100644 index 000000000000..70d9a66affdb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/accton_i2c_cpld.c @@ -0,0 +1,1176 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as7326_56x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as7326_56x_cpld1, + as7326_56x_cpld2, + as7326_56x_cpld3 +}; + +struct as7326_56x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as7326_56x_cpld_id[] = { + { "as7326_56x_cpld1", as7326_56x_cpld1 }, + { "as7326_56x_cpld2", as7326_56x_cpld2 }, + { "as7326_56x_cpld3", as7326_56x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as7326_56x_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as7326_56x_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_PRESENT_ATTR_ID(55), + TRANSCEIVER_PRESENT_ATTR_ID(56), + TRANSCEIVER_PRESENT_ATTR_ID(57), + TRANSCEIVER_PRESENT_ATTR_ID(58), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_TXDISABLE_ATTR_ID(57), + TRANSCEIVER_TXDISABLE_ATTR_ID(58), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(57), + TRANSCEIVER_RXLOS_ATTR_ID(58), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(57), + TRANSCEIVER_TXFAULT_ATTR_ID(58), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), + TRANSCEIVER_RESET_ATTR_ID(55), + TRANSCEIVER_RESET_ATTR_ID(56), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as7326_56x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7326_56x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR, show_status, set_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(55); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(56); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(57); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(58); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(57); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(58); + +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(54); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(55); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(56); + +static struct attribute *as7326_56x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7326_56x_cpld3_group = { + .attrs = as7326_56x_cpld3_attributes, +}; + +static struct attribute *as7326_56x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + NULL +}; + +static const struct attribute_group as7326_56x_cpld2_group = { + .attrs = as7326_56x_cpld2_attributes, +}; + +static struct attribute *as7326_56x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_TRANSCEIVER_PRESENT_ATTR(55), + DECLARE_TRANSCEIVER_PRESENT_ATTR(56), + DECLARE_TRANSCEIVER_PRESENT_ATTR(57), + DECLARE_TRANSCEIVER_PRESENT_ATTR(58), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + DECLARE_SFP_TRANSCEIVER_ATTR(57), + DECLARE_SFP_TRANSCEIVER_ATTR(58), + DECLARE_TRANSCEIVER_RESET_ATTR(49), + DECLARE_TRANSCEIVER_RESET_ATTR(50), + DECLARE_TRANSCEIVER_RESET_ATTR(51), + DECLARE_TRANSCEIVER_RESET_ATTR(52), + DECLARE_TRANSCEIVER_RESET_ATTR(53), + DECLARE_TRANSCEIVER_RESET_ATTR(54), + DECLARE_TRANSCEIVER_RESET_ATTR(55), + DECLARE_TRANSCEIVER_RESET_ATTR(56), + NULL +}; + +static const struct attribute_group as7326_56x_cpld1_group = { + .attrs = as7326_56x_cpld1_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u32 values; + u8 *value = (u8*)&values; + u8 regs_h1[] = {0x0f, 0x10, 0x11, 0x12}; + u8 regs_h2[] = {0x10, 0x11, 0x12, 0x13}; + u8 *regs_p; + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + + if (data->type == as7326_56x_cpld2) { + regs_p = regs_h1; + } else { + regs_p = regs_h2; + } + mutex_lock(&data->update_lock); + for (i = 0; i < sizeof(values); i++) { + status = as7326_56x_cpld_read_internal(client, regs_p[i]); + + if (status < 0) { + goto exit; + } + + value[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + values = cpu_to_le32(values); + /* For port 1 ~ 30 in order */ + if (data->type == as7326_56x_cpld2) { + values &= 0x3FFFFFFF; + } else { /* Port 31 ~ 56 */ + u8 tmp1 = (values >> 18) & 0x3; + u8 tmp2 = (values >> 24) ; + + values &= 0x3ffff; + values |= (tmp2 << 18); + values |= (tmp1 << 26); + } + + return sprintf(buf, "%x\n", values); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[3] = {0}; + u8 regs[] = {0x12, 0x13, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7326_56x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_30: + reg = 0x0f + (attr->index-MODULE_PRESENT_1)/8; + mask = 0x1 << ((attr->index - MODULE_PRESENT_1)%8); + break; + case MODULE_PRESENT_31 ... MODULE_PRESENT_48: + reg = 0x10 + (attr->index-MODULE_PRESENT_31)/8; + mask = 0x1 << ((attr->index - MODULE_PRESENT_31)%8); + break; + case MODULE_PRESENT_57 ... MODULE_PRESENT_58: + reg = 0x12; + mask = 0x1 << (( MODULE_PRESENT_58 - attr->index)+2); + break; + case MODULE_PRESENT_49 ... MODULE_PRESENT_56: /*QSFP*/ + reg = 0x13 ; + mask = 0x1 << ((attr->index - MODULE_PRESENT_49)%8); + break; + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_30: + reg = 0x03 + (attr->index - MODULE_TXFAULT_1)/8; + mask = 0x1 << ((attr->index - MODULE_TXFAULT_1)%8); + break; + case MODULE_TXFAULT_31 ... MODULE_TXFAULT_48: + reg = 0x1a + (attr->index-MODULE_TXFAULT_31)/8; + mask = 0x1 << ((attr->index - MODULE_TXFAULT_31)%8); + break; + case MODULE_TXFAULT_57 ... MODULE_TXFAULT_58: + reg = 0x1c; + mask = 0x1 << (( attr->index - MODULE_TXFAULT_57)+2); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_30: + reg = 0x07 + (attr->index - MODULE_TXDISABLE_1)/8; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_1)%8); + break; + case MODULE_TXDISABLE_31 ... MODULE_TXDISABLE_48: + reg = 0x14 + (attr->index-MODULE_TXDISABLE_31)/8; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_31)%8); + break; + case MODULE_TXDISABLE_57 ... MODULE_TXDISABLE_58: + reg = 0x16; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_57)+2); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_30: + reg = 0x0b + (attr->index - MODULE_RXLOS_1)/8; + mask = 0x1 << ((attr->index - MODULE_RXLOS_1)%8); + break; + case MODULE_RXLOS_31 ... MODULE_RXLOS_48: + reg = 0x17 + (attr->index-MODULE_RXLOS_31)/8; + mask = 0x1 << ((attr->index - MODULE_RXLOS_31)%8); + break; + case MODULE_RXLOS_57 ... MODULE_RXLOS_58: + reg = 0x19; + mask = 0x1 << (( attr->index - MODULE_RXLOS_57)+2); + break; + case MODULE_RESET_49 ... MODULE_RESET_56: + reg = 0x4; + mask = 0x1 << (attr->index - MODULE_RESET_49); + revert = 1; + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_56) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as7326_56x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_30: + reg = 0x07 + (attr->index - MODULE_TXDISABLE_1)/8; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_1)%8); + break; + case MODULE_TXDISABLE_31 ... MODULE_TXDISABLE_48: + reg = 0x14 + (attr->index - MODULE_TXDISABLE_31)/8; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_31)%8); + break; + case MODULE_TXDISABLE_57 ... MODULE_TXDISABLE_58: + reg = 0x16; + mask = 0x1 << ((attr->index - MODULE_TXDISABLE_57)+2); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7326_56x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7326_56x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + switch (attr->index) + { + case MODULE_RESET_49 ... MODULE_RESET_56: + reg = 0x4; + mask = 0x1 << (attr->index - MODULE_RESET_49); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7326_56x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update reset status */ + if (!reset) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7326_56x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7326_56x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as7326_56x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7326_56x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as7326_56x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as7326_56x_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as7326_56x_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as7326_56x_cpld1: + group = &as7326_56x_cpld1_group; + break; + case as7326_56x_cpld2: + group = &as7326_56x_cpld2_group; + break; + case as7326_56x_cpld3: + group = &as7326_56x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as7326_56x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as7326_56x_cpld_remove(struct i2c_client *client) +{ + struct as7326_56x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as7326_56x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as7326_56x_cpld1: + group = &as7326_56x_cpld1_group; + break; + case as7326_56x_cpld2: + group = &as7326_56x_cpld2_group; + break; + case as7326_56x_cpld3: + group = &as7326_56x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as7326_56x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7326_56x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as7326_56x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7326_56x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7326_56x_cpld_read); + +int as7326_56x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7326_56x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7326_56x_cpld_write); + +static struct i2c_driver as7326_56x_cpld_driver = { + .driver = { + .name = "as7326_56x_cpld", + .owner = THIS_MODULE, + }, + .probe = as7326_56x_cpld_probe, + .remove = as7326_56x_cpld_remove, + .id_table = as7326_56x_cpld_id, +}; + +static int __init as7326_56x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7326_56x_cpld_driver); +} + +static void __exit as7326_56x_cpld_exit(void) +{ + i2c_del_driver(&as7326_56x_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as7326_56x_cpld_init); +module_exit(as7326_56x_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-handle_mac.service b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-handle_mac.service new file mode 100644 index 000000000000..3d03ec4f1540 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-handle_mac.service @@ -0,0 +1,15 @@ +[Unit] +Description=Accton AS7326-56X Platform MAC handle service +Before=opennsl-modules.service +After=local-fs.target + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/idt_init.sh +RemainAfterExit=yes + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=opennsl-modules.service diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-fan.service new file mode 100644 index 000000000000..e714561bdf8c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS7326-56X Platform Monitoring FAN service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as7326_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-psu.service new file mode 100644 index 000000000000..77fa1fd5c14f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS7326-56X Platform Monitoring PSU service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as7326_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor.service new file mode 100644 index 000000000000..9da83704715a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/service/as7326-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS7326-56X Platform Monitoring service +Before=pmon.service +After=as7326-platform-handle_mac.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7326_util.py install +ExecStart=/usr/local/bin/accton_as7326_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/setup.py new file mode 100755 index 000000000000..77114c71285b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env pytho + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7326_56x', + version='1.0', + description='Module to initialize Accton AS7326-56X platforms', + + packages=['as7326_56x'], + package_dir={'as7326_56x': 'as7326-56x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/README new file mode 100755 index 000000000000..ef0d03cf5e45 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/README @@ -0,0 +1,74 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + module - Contains source code of as7326 kernel driver modules. + util - operational scripts. + +Sonic creates a docker container and run building process under it. +If user tries to built new drivers, please get into that docker and +dpkg-buildpackage for them. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS7326-56X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers can be built to individual ko during dpkg-buildpackage. +2. A operational script, accton_as7326_util.py, for device initializatian. + Run "accton_as7326_util.py install" to install drivers. + +To initialize the system, run "accton_as7326_util.py install". +To clean up the drivers & devices, run "accton_as7326_util.py clean". +To dump information of sensors, run "accton_as7326_util.py show". +To dump SFP EEPROM, run "accton_as7326_util.py sff". +To set fan speed, run "accton_as7326_util.py set fan". +To enable/disable SFP emission, run "accton_as7326_util.py set sfp". +To set system LEDs' color, run "accton_as7326_util.py set led" +For more information, run "accton_as7326_util.py --help". + +==================================================================== +Besides applying accton_as7326_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 6 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 8 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor.py new file mode 100755 index 000000000000..07ec446ab88e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor.py @@ -0,0 +1,320 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 3/23/2018: Roy Lee modify for as7326_56x +# 6/26/2018: Jostar implement by new thermal policy from HW RD +# ------------------------------------------------------------------ + +try: + import os + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example + from as7326_56x.fanutil import FanUtil + from as7326_56x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7326_monitor' + +global log_file +global log_level + + +#Default FAN speed: 37.5%(0x05) +#Ori is that detect: (U45_BCM56873 + Thermal sensor_LM75_CPU:0x4B) /2 +#New Detect: (sensor_LM75_49 + Thermal sensor_LM75_CPU_4B) /2 +#Thermal policy: Both F2B and B2F +#1. (sensor_LM75_49 + Thermal sensor_LM75_CPU) /2 =< 39C , Keep 37.5%(0x05) Fan speed +#2. (sensor_LM75_49 + Thermal sensor_LM75_CPU) /2 > 39C , Change Fan speed from 37.5%(0x05) to % 75%(0x0B) +#3. (sensor_LM75_49 + Thermal sensor_LM75_CPU) /2 > 45C , Change Fan speed from 75%(0x0B) to 100%(0x0F) +#4. (sensor_LM75_49 + Thermal sensor_LM75_CPU) /2 > 61C , Send alarm message +#5. (sensor_LM75_49 + Thermal sensor_LM75_CPU) /2 > 66C , Shutdown system +#6. One Fan fail , Change Fan speed to 100%(0x0F) + +#fan-dev 0-11 speed 0x05 Setup fan speed 37.50% +#fan-dev 0-11 speed 0xB Setup fan speed 75% +#fan-dev 0-11 speed 0xF Setup fan speed 100.00% + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_policy_state=1 +fan_fail=0 +alarm_state = 0 #0->default or clear, 1-->alarm detect +test_temp = 0 +test_temp_list = [0, 0, 0, 0, 0, 0] + +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + # static temp var + temp = 0 + new_pwm = 0 + pwm=0 + ori_pwm = 0 + default_pwm=0x4 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def get_state_from_fan_policy(self, temp, policy): + state=0 + logging.debug('temp=%d', temp) + for i in range(0, len(policy)): + #logging.debug('policy[%d][0]=%d, policy[%d][1]=%d', i,policy[i][0],i, policy[i][1]) + if temp > policy[i][0]: + if temp <= policy[i][1]: + state =policy[i][2] + logging.debug ('temp=%d >= policy[%d][0]=%d, temp=%d < policy[%d][1]=%d' , temp, i, policy[i][0], temp, i, policy[i][1]) + logging.debug ('fan_state=%d', state) + if state==0: + state=policy[0][2] #below fan_min, set to default pwm + logging.debug('set default state') + return state + + def manage_fans(self): + + thermal_pwm_list = {} #Ori sort is lm75_48, 49, 4a, 4b, cpu, bcm + # After get pwm, do sort to get max pwm. + LEVEL_FAN_DEF=1 + LEVEL_FAN_MID=2 + LEVEL_FAN_MAX=3 + LEVEL_TEMP_HIGH=4 + LEVEL_TEMP_CRITICAL=5 + + fan_policy_state_pwm_tlb = { + LEVEL_FAN_DEF: [38, 0x4], + LEVEL_FAN_MID: [75, 0xB], + LEVEL_FAN_MAX: [100, 0xE], + LEVEL_TEMP_HIGH: [100, 0xE], + LEVEL_TEMP_CRITICAL: [100, 0xE], + } + global fan_policy_state + global fan_fail + global test_temp + global test_temp_list + global alarm_state + fan_policy ={ + 0: [0, 39000, LEVEL_FAN_DEF], #F2B_policy, B2F_plicy, PWM, reg_val + 1: [39000, 45000, LEVEL_FAN_MID], + 2: [45000, 61000, LEVEL_FAN_MAX], + 3: [61000, 66000, LEVEL_TEMP_HIGH], + 4: [66000, 200000, LEVEL_TEMP_CRITICAL], + } + + thermal = ThermalUtil() + fan = FanUtil() + fan_dir=fan.get_fan_dir(1) + if fan_dir > 1: + fan_dri=1 #something wrong, set fan_dir to default val + if fan_dir < 0: + fan_dri=1 #something wrong, set fan_dir to default val + ori_pwm=fan.get_fan_duty_cycle() + new_pwm=0 + logging.debug('fan_dir=%d, ori_pwm=%d', fan_dir, ori_pwm) + logging.debug('test_temp=%d', test_temp) + if test_temp==0: + temp1 = thermal._get_thermal_val(1) + temp2 = thermal._get_thermal_val(2) + temp3 = thermal._get_thermal_val(3) + temp4 = thermal._get_thermal_val(4) + temp5 = thermal._get_thermal_val(5) + temp6=0 + else: + temp1 = test_temp_list[0] + temp2 = test_temp_list[1] + temp3 = test_temp_list[2] + temp4 = test_temp_list[3] + temp5 = test_temp_list[4] + temp6=0 + fan_fail=0 + + if temp2==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_49 detect fail, so set temp_get=50000, let fan to 75%') + elif temp2==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_4b detect fail, so set temp_get=50000, let fan to 75%') + else: + temp_get= (temp2 + temp4)/2 # Use (sensor_LM75_49 + Thermal sensor_LM75_CPU_4B) /2 + ori_state=fan_policy_state + fan_policy_state=self.get_state_from_fan_policy(temp_get, fan_policy) + logging.debug('lm75_48=%d, lm75_49=%d, lm75_4a=%d, lm_4b=%d, cpu=%d, bcm=%d', temp1,temp2,temp3,temp4,temp5,temp6) + logging.debug('ori_state=%d, fan_policy_state=%d', ori_state, fan_policy_state) + new_pwm = fan_policy_state_pwm_tlb[fan_policy_state][0] + if fan_fail==0: + logging.debug('new_pwm=%d', new_pwm) + + if fan_fail==0: + if new_pwm!=ori_pwm: + fan.set_fan_duty_cycle(new_pwm) + logging.info('Set fan speed from %d to %d', ori_pwm, new_pwm) + + for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): + if fan.get_fan_status(i)==0: + new_pwm=100 + logging.debug('fan_%d fail, set pwm to 100',i) + if test_temp==0: + fan_fail=1 + fan.set_fan_duty_cycle(new_pwm) + break + else: + fan_fail=0 + + new_state = fan_policy_state + + if ori_state==LEVEL_FAN_DEF: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected, reboot DUT') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MID: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MAX: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if alarm_state==1: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_HIGH: + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if new_state <= LEVEL_FAN_MID: + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if new_state <= LEVEL_FAN_MAX: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_CRITICAL: + if new_state <= LEVEL_FAN_MAX: + logging.warning('Alarm for temperature critical is cleared') + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global test_temp + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdlt:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + if sys.argv[1]== '-t': + if len(sys.argv)!=8: + print "temp test, need input six temp" + return 0 + + i=0 + for x in range(2, 8): + test_temp_list[i]= int(sys.argv[x])*1000 + i=i+1 + test_temp = 1 + log_level = logging.DEBUG + print test_temp_list + + fan = FanUtil() + fan.set_fan_duty_cycle(38) + print "set default fan speed to 37.5%" + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(5) + +if __name__ == '__main__': + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_fan.py new file mode 100755 index 000000000000..b52ada307698 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_fan.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7326_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + #/sys/bus/i2c/devices/11-0066 + #fan1_present, fan6_present + + def __init__(self, log_file, log_level): + + self.fan_num = 6 + self.fan_path = "/sys/bus/i2c/devices/11-0066/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + 4: "fan5_present", + 5: "fan6_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + 4: "fan5_fault", + 5: "fan6_fault", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_psu.py new file mode 100755 index 000000000000..cb897b942aeb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_monitor_psu.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7326_monitor_psu' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +psu_state=[2, 2] +psu_power_status=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "17-0051", + 1: "13-0053", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + + global psu_state + global psu_power_status + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=PSU_STATE_INSERT: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_power_status[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=PSU_STATE_REMOVE: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_NO_POWER + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + #logging.info("content=%s, psu_power_status[%d]=%d", content, idx, psu_power_status[idx]); + if content == "0": + if psu_power_status[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d fault is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_NO_POWER + else: + if psu_power_status[idx] !=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_power_status[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_util.py b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_util.py new file mode 100755 index 000000000000..c5d047e9d4e0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_as7326_util.py @@ -0,0 +1,606 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# +# Description: +# Due to adoption of optoe drivers, sideband signals of SFPs are moved +# into cpld drivers. Add a new dict, cpld_of_module, for mapping this +# attributes to corresponding cpld nodes. +# + + + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + + + + +PROJECT_NAME = 'as7326_56x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':6,'thermal':4, 'psu':2, 'sfp':58} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-56 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def dis_i2c_ir3570a(addr): + cmd = "i2cset -y 0 0x%x 0xE5 0x01" % addr + status, output = commands.getstatusoutput(cmd) + cmd = "i2cset -y 0 0x%x 0x12 0x02" % addr + status, output = commands.getstatusoutput(cmd) + return status + +def ir3570_check(): + cmd = "i2cdump -y 0 0x42 s 0x9a" + try: + status, output = commands.getstatusoutput(cmd) + lines = output.split('\n') + hn = re.findall(r'\w+', lines[-1]) + version = int(hn[1], 16) + if version == 0x24: #only for ir3570a + ret = dis_i2c_ir3570a(4) + else: + ret = 0 + except Exception as e: + print "Error on ir3570_check() e:" + str(e) + return -1 + return ret + + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-56 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_cpld' , +'modprobe ym2651y' , +'modprobe accton_as7326_56x_fan' , +'modprobe optoe' , +'modprobe accton_as7326_56x_leds' , +'modprobe accton_as7326_56x_psu' ] + +def driver_install(): + global FORCE + + status, output = log_os_system('modprobe i2c_dev', 1) + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + lst = rm.split(" ") + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['11-0066'] , + 'thermal': ['15-0048','15-0049', '15-004a', '15-004b'] , + 'psu': ['17-0051','13-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_', 'module_tx_disable_']} + +sfp_map = [ + 42,41,44,43,47,45,46,50, + 48,49,52,51,53,56,55,54, + 58,57,60,59,61,63,62,64, + 66,68,65,67,69,71,72,70, + 74,73,76,75,77,79,78,80, + 81,82,84,85,83,87,88,86, #port 41~48 + 25,26,27,28,29,30,31,32, #port 49~56 QSFP + 22,23] #port 57~58 SFP+ from CPU NIF. +qsfp_start = 48 +qsfp_end = 56 + +#For sideband signals of SFP/QSFP modules. +cpld_of_module = {'12-0062': list(range(0,30)), + '18-0060': list(range(30,58)) } + + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-24/new_device' , +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' , +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-33/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-34/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-35/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-36/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-37/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-38/new_device', +'echo 24c04 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as7326_56x_fan 0x66 > /sys/bus/i2c/devices/i2c-11/new_device ', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-15/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-15/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-15/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-15/new_device', +'echo as7326_56x_psu1 0x51 > /sys/bus/i2c/devices/i2c-17/new_device', +'echo ym2651 0x59 > /sys/bus/i2c/devices/i2c-17/new_device', +'echo as7326_56x_psu2 0x53 > /sys/bus/i2c/devices/i2c-13/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-13/new_device', +'echo as7326_56x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo as7326_56x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as7326_56x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-19/new_device'] + +mknod2 =[ +] + + + +def i2c_order_check(): + # This project has only 1 i2c bus. + return 0 + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x70 is not exist @i2c-1, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(0,len(sfp_map)): + if i < qsfp_start or i >= qsfp_end: + status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + else: + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + + ir3570_check() + + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + for lk in cpld_of_module: + if k in cpld_of_module[lk]: + cpld_str = lk + node = key+str(k+1) + path = i2c_prefix+ lk + "/"+ nodes[j] + str(k+1) + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_handle_idt.sh b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_handle_idt.sh new file mode 100755 index 000000000000..f5de5628bc70 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/accton_handle_idt.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +if [ -s /usr/local/bin/done_idt_init ];then + echo "There is a done_idt_init file" +else + + cat /etc/init.d/opennsl-modules|grep idt_init.sh + if [ $? -ne 0 ];then + echo "Add idt_init.sh to opennsl-modules for TD3 MAC" + sed -i '/modprobe linux-kernel-bde/i sleep 1' /etc/init.d/opennsl-modules + sed -i '/sleep/i /usr/local/bin/idt_init.sh' /etc/init.d/opennsl-modules + sed -i '/idt_init/i echo "IDT init" ' /etc/init.d/opennsl-modules + sed -i '/IDT init/i echo 1 > /usr/local/bin/done_idt_init' /etc/init.d/opennsl-modules + + fi + +fi + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/idt_init.sh b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/idt_init.sh new file mode 100755 index 000000000000..7c1f1fcf3a7b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7326-56x/utils/idt_init.sh @@ -0,0 +1,150 @@ +#!/bin/bash +test_log=/usr/local/bin/check_idt_status.txt +modprobe i2c-i801 +modprobe i2c-dev +i2cset -y 0 0x77 0x1 +i2cset -y 0 0x70 0x1 +i2cget -y 0 0x54 0 b > /dev/null +if [ $? -ne 0 ];then + printf "Device 8v89307(0x54) not found\n" + exit 1 +fi +echo "IDT 82V89307 " +echo "idt init 1" +# Title = --- IDT 82V89307 Registers --- +#Select to Page 0 +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x7F 0x05 +i2cset -y 0 0x54 0x7E 0x85 +i2cset -y 0 0x54 0x7B 0x00 +i2cset -y 0 0x54 0x7A 0x00 +i2cset -y 0 0x54 0x79 0x40 +i2cset -y 0 0x54 0x78 0x06 +i2cset -y 0 0x54 0x73 0x40 +i2cset -y 0 0x54 0x72 0x40 + +# OUT3:25MHz +i2cset -y 0 0x54 0x71 0x0A +i2cset -y 0 0x54 0x70 0x00 + +# OUT1:1pps +i2cset -y 0 0x54 0x6B 0x4E +i2cset -y 0 0x54 0x69 0x00 +i2cset -y 0 0x54 0x68 0x00 +i2cset -y 0 0x54 0x67 0x19 +i2cset -y 0 0x54 0x66 0xAB +i2cset -y 0 0x54 0x65 0x8C +i2cset -y 0 0x54 0x64 0x00 +i2cset -y 0 0x54 0x63 0x00 +i2cset -y 0 0x54 0x62 0x00 +i2cset -y 0 0x54 0x5F 0x00 +i2cset -y 0 0x54 0x5E 0x00 +i2cset -y 0 0x54 0x5D 0x00 +i2cset -y 0 0x54 0x5C 0x78 +i2cset -y 0 0x54 0x5B 0x02 +i2cset -y 0 0x54 0x5A 0xE5 +i2cset -y 0 0x54 0x59 0x88 +i2cset -y 0 0x54 0x58 0x4B +i2cset -y 0 0x54 0x57 0x6C +i2cset -y 0 0x54 0x56 0x6C + +# Lock to DPLL, output 625MHz +i2cset -y 0 0x54 0x55 0x80 +i2cset -y 0 0x54 0x53 0x00 +i2cset -y 0 0x54 0x52 0x81 +i2cset -y 0 0x54 0x50 0x00 +i2cset -y 0 0x54 0x4F 0x00 +i2cset -y 0 0x54 0x4E 0x00 +i2cset -y 0 0x54 0x4C 0xCB +i2cset -y 0 0x54 0x4A 0x00 +i2cset -y 0 0x54 0x45 0x66 +i2cset -y 0 0x54 0x44 0x66 +i2cset -y 0 0x54 0x42 0x80 +i2cset -y 0 0x54 0x41 0x03 +i2cset -y 0 0x54 0x40 0x01 +i2cset -y 0 0x54 0x3F 0x08 +i2cset -y 0 0x54 0x3E 0x04 +i2cset -y 0 0x54 0x3D 0x20 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x34 0x01 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x2F 0x23 +i2cset -y 0 0x54 0x2E 0x0B +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x28 0x76 +i2cset -y 0 0x54 0x27 0x54 +i2cset -y 0 0x54 0x25 0x00 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x1A 0x8C +i2cset -y 0 0x54 0x19 0x8C +i2cset -y 0 0x54 0x18 0x00 +i2cset -y 0 0x54 0x16 0x0D +i2cset -y 0 0x54 0x11 0x00 +i2cset -y 0 0x54 0x10 0x00 +i2cset -y 0 0x54 0x0E 0x3F +i2cset -y 0 0x54 0x0D 0xFF +i2cset -y 0 0x54 0x0C 0x02 +i2cset -y 0 0x54 0x0B 0xA1 +i2cset -y 0 0x54 0x0A 0x89 +i2cset -y 0 0x54 0x09 0xA2 +i2cset -y 0 0x54 0x08 0x32 +i2cset -y 0 0x54 0x06 0x00 +i2cset -y 0 0x54 0x05 0x00 +i2cset -y 0 0x54 0x04 0x00 +i2cset -y 0 0x54 0x03 0x00 +i2cset -y 0 0x54 0x02 0x05 +i2cset -y 0 0x54 0x01 0x33 +i2cset -y 0 0x54 0x00 0x91 + +echo "idt init 2" +# PreDivider_Parameters +#IN1 +i2cset -y 0 0x54 0x23 0x05 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN2 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN3 +i2cset -y 0 0x54 0x23 0x03 +i2cset -y 0 0x54 0x24 0x00 +i2cset -y 0 0x54 0x25 0x00 + +echo "idt init 3" +# Page1_Parameters +#Select to Page 1 +i2cset -y 0 0x54 0x2D 0x01 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3D 0x20 +#Return to Page 0 +i2cset -y 0 0x54 0x2D 0x00 + +echo "idt init 4" +#reset the in-path mux +i2cset -y 0 0x70 0x0 +i2cset -y 0 0x77 0x0 + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/Makefile new file mode 100644 index 000000000000..d9566355b849 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/Makefile @@ -0,0 +1,2 @@ +obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ + accton_as7712_32x_psu.o accton_i2c_cpld.o ym2651y.o diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_fan.c new file mode 100755 index 000000000000..73dd36c2883e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_fan.c @@ -0,0 +1,634 @@ +/* + * A hwmon driver for the Accton as7712 32x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7712_32x_fan" + +#define NUM_THERMAL_SENSORS (3) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a} + +#define IN +#define OUT + +static struct as7712_32x_fan_data *as7712_32x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); + + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7712_32x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as7712_32x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7712_32x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7712_32x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7712_32x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0) + return -EINVAL; + + value = (value > FAN_MAX_DUTY_CYCLE)? FAN_MAX_DUTY_CYCLE : value; + + as7712_32x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7712_32x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +/* Struct and define are copied from drivers/hwmon/hwmon.c. */ +struct hwmon_device { + const char *name; + struct device dev; + const struct hwmon_chip_info *chip; + + struct attribute_group group; + const struct attribute_group **groups; +}; +#define to_hwmon_device(d) container_of(d, struct hwmon_device, dev) + +/*Find the 1st valid dev of all childs, it supposes to have only 1 child.*/ +static int is_valid_dev(struct device *dev, void *data) +{ + struct hwmon_device *hwmon_dev; + + if(dev) { + hwmon_dev = to_hwmon_device(dev); + if(hwmon_dev) { + int ret; + long t; + ret = hwmon_dev->chip->ops->read(dev, hwmon_temp, hwmon_temp_input, + 0, &t); + return !ret; + } + } + return 0; +} + +static int hwmon_get_temp(struct device *dev, long *mini_cel) +{ + struct hwmon_device *hwmon_dev = to_hwmon_device(dev); + int ret = 0; + + if(hwmon_dev) { + long t; + ret = hwmon_dev->chip->ops->read(dev, hwmon_temp, hwmon_temp_input, + 0, &t); + if (ret < 0) + return ret; + + *mini_cel = t; + } + return ret; +} + +/* Find devices under i2c_bus which with driver = lm75. + * Use the device to find its descendent hwmon_dev and read the temperature. + */ +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as7712_32x_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + struct i2c_client *client; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + + client = to_i2c_client(dev); + if (client) + { + long miniCelsius = 0; + struct device *child_dev; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + child_dev = device_find_child(dev, NULL, is_valid_dev); + if(child_dev) { + int ret = hwmon_get_temp(child_dev, &miniCelsius); + if (ret < 0) + return ret; + + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7712_32x_fan_group = { + .attrs = as7712_32x_fan_attributes, +}; + +static struct as7712_32x_fan_data *as7712_32x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7712_32x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7712_32x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7712_32x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7712_32x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7712_32x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7712_32x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->enable = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7712_32x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7712_32x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7712_32x_fan_remove(struct i2c_client *client) +{ + struct as7712_32x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7712_32x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7712_32x_fan_id[] = { + { "as7712_32x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7712_32x_fan_id); + +static struct i2c_driver as7712_32x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7712_32x_fan_probe, + .remove = as7712_32x_fan_remove, + .id_table = as7712_32x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7712_32x_fan_init(void) +{ + return i2c_add_driver(&as7712_32x_fan_driver); +} + +static void __exit as7712_32x_fan_exit(void) +{ + i2c_del_driver(&as7712_32x_fan_driver); +} + +module_init(as7712_32x_fan_init); +module_exit(as7712_32x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7712_32x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_psu.c new file mode 100644 index 000000000000..233aef78e09f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_psu.c @@ -0,0 +1,288 @@ +/* + * An hwmon driver for accton as7712_32x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as7712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7712_32x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[9]; /* Model name, read from eeprom */ +}; + +static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *dev); + +enum as7712_32x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7712_32x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7712_32x_psu_data *data = as7712_32x_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7712_32x_psu_data *data = as7712_32x_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as7712_32x_psu_group = { + .attrs = as7712_32x_psu_attributes, +}; + +static int as7712_32x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7712_32x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7712_32x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7712_32x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7712_32x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7712_32x_psu_remove(struct i2c_client *client) +{ + struct as7712_32x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7712_32x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7712_32x_psu1, + as7712_32x_psu2 +}; + +static const struct i2c_device_id as7712_32x_psu_id[] = { + { "as7712_32x_psu1", as7712_32x_psu1 }, + { "as7712_32x_psu2", as7712_32x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7712_32x_psu_id); + +static struct i2c_driver as7712_32x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7712_32x_psu", + }, + .probe = as7712_32x_psu_probe, + .remove = as7712_32x_psu_remove, + .id_table = as7712_32x_psu_id, + .address_list = normal_i2c, +}; + +static int as7712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7712_32x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as7712_32x update\n"); + + /* Read psu status */ + status = accton_i2c_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as7712_32x_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7712_32x_psu_init(void) +{ + return i2c_add_driver(&as7712_32x_psu_driver); +} + +static void __exit as7712_32x_psu_exit(void) +{ + i2c_del_driver(&as7712_32x_psu_driver); +} + +module_init(as7712_32x_psu_init); +module_exit(as7712_32x_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7712_32x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_sfp.c new file mode 100644 index 000000000000..4668f5a7f050 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_as7712_32x_sfp.c @@ -0,0 +1,1171 @@ +/* + * SFP driver for accton as7712_32x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "as7712_32x_sfp" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_SFP_PORT 32 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) +#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { SFP_EEPROM_A0_I2C_ADDR, SFP_EEPROM_A2_I2C_ADDR, I2C_CLIENT_END }; + +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +sfp1, sfp2, sfp3, sfp4, sfp5, sfp6, sfp7, sfp8, +sfp9, sfp10, sfp11, sfp12, sfp13, sfp14, sfp15, sfp16, +sfp17, sfp18, sfp19, sfp20, sfp21, sfp22, sfp23, sfp24, +sfp25, sfp26, sfp27, sfp28, sfp29, sfp30, sfp31, sfp32 +}; + +static const struct i2c_device_id sfp_device_id[] = { +{ "sfp1", sfp1 }, { "sfp2", sfp2 }, { "sfp3", sfp3 }, { "sfp4", sfp4 }, +{ "sfp5", sfp5 }, { "sfp6", sfp6 }, { "sfp7", sfp7 }, { "sfp8", sfp8 }, +{ "sfp9", sfp9 }, { "sfp10", sfp10 }, { "sfp11", sfp11 }, { "sfp12", sfp12 }, +{ "sfp13", sfp13 }, { "sfp14", sfp14 }, { "sfp15", sfp15 }, { "sfp16", sfp16 }, +{ "sfp17", sfp17 }, { "sfp18", sfp18 }, { "sfp19", sfp19 }, { "sfp20", sfp20 }, +{ "sfp21", sfp21 }, { "sfp22", sfp22 }, { "sfp23", sfp23 }, { "sfp24", sfp24 }, +{ "sfp25", sfp25 }, { "sfp26", sfp26 }, { "sfp27", sfp27 }, { "sfp28", sfp28 }, +{ "sfp29", sfp29 }, { "sfp30", sfp30 }, { "sfp31", sfp31 }, { "sfp32", sfp32 }, +{} +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[2]; /* index 0 => device id + 1 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 2 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + u64 port_reset; /* reset status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + TX_DISABLE_ALL, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL, + PORT_RESET +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x30, 0x31, 0x32, 0x33}; + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port 1~32 */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = accton_i2c_cpld_read(0x60, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); + data->present |= (u64)status << (i*8); + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + return NULL; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return 0; +} + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = sfp_update_present(client); + return (data->present & BIT_INDEX(data->port)) ? 0 : 1; +} + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (PRESENT_ALL == attr->index) { + + } + + /* PRESENT */ + return sprintf(buf, "%d\n", sfp_is_port_present(client, data->port)); +} + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(data->client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, data->port)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + + +static struct sfp_port_data *sfp_update_port_reset(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x4, 0x5, 0x6, 0x7}; + + mutex_lock(&data->update_lock); + + /* Read reset status of port 1~32 */ + data->port_reset = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = accton_i2c_cpld_read(0x60, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("reset status = 0x%x", status); + data->port_reset |= (u64)status << (i*8); + } + + DEBUG_PRINT("reset status = 0x%llx", data->port_reset); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int is_reset = 0; + + if (!sfp_is_port_present(client, data->port)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_reset(client); + is_reset = (data->port_reset & BIT_INDEX(data->port))? 0 : 1; + + return sprintf(buf, "%d\n", is_reset); +} + +static ssize_t sfp_set_port_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long is_reset; + int error; + + error = kstrtol(buf, 10, &is_reset); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + cpld_reg = 0x4 + data->port / 8; + cpld_bit = 1 << (data->port % 8); + + cpld_val = accton_i2c_cpld_read(0x60, cpld_reg); + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update reset status. CPLD defined 0 is reset state, 1 is normal state. + * is_reset: 0 is not reset. 1 is reset. + */ + if (is_reset == 0) { + data->port_reset |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->port_reset &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + accton_i2c_cpld_write(0x60, cpld_reg, cpld_val); + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x cpld_bit = 0x%x", cpld_reg, cpld_val,cpld_bit); + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + dev_dbg(dev, "Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + mutex_unlock(&data->update_lock); + return data; + +exit: + mutex_unlock(&data->update_lock); + return NULL; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, data->port)) { + return -ENODEV; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + switch (attr->index) { + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = (data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)) ? 1 : 0; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = (data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)) ? 1 : 0; + break; + case TX_DISABLE_ALL: + val = ((data->qsfp->status[1] & 0xF) == 0xF) ? 1 : 0; + break; + + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = (data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)) ? 1 : 0; + break; + default: + break; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int result; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + result = kstrtol(buf, 10, &disable); + if (result) { + return result; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + mutex_lock(&data->update_lock); + + DEBUG_PRINT ("disable:%ld %d==%d %u\r\n", disable, attr->index, TX_DISABLE_ALL, data->qsfp->status[1]); + + if (attr->index == TX_DISABLE_ALL) + { + data->qsfp->status[1] = disable? 0xF:0; + } + else + { + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + result = sfp_eeprom_write(client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, data->port)) { + return -ENODEV; + } + + status = sfp_eeprom_read(data->client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (status < 0) { + return -EIO; + } + + return sprintf(buf, "%d\n", (ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK) ? 1 : 0); +} + +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + data = sfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + case RX_LOS: + index = 2; + break; + default: + break; + } + + val = (data->ddm->status[index] & BIT_INDEX(data->port)) ? 1 : 0; + return sprintf(buf, "%d\n", val); +} + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT_RESET); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable_all, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE_ALL); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_port_reset.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + NULL +}; + +/* SFP msa attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); +static struct attribute *sfp_msa_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, + NULL +}; + +/* SFP ddm attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); +static struct attribute *sfp_ddm_attributes[] = { + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + NULL +}; + +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return data_len; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_write_byte_data(client, command, *data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return 1; +#endif + + +} + + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return result; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_read_byte_data(client, command); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 1; + +abort: + return result; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + + /* Bring QSFPs out of reset + as6712_32x_i2c_cpld_write(0x62, 0x4, 0xFF); + as6712_32x_i2c_cpld_write(0x62, 0x5, 0xFF); + as6712_32x_i2c_cpld_write(0x64, 0x4, 0xFF); + as6712_32x_i2c_cpld_write(0x64, 0x5, 0xFF);*/ + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { + return -ENODEV; + } + + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); +} + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7712_32x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_i2c_cpld.c new file mode 120000 index 000000000000..39c0826d16fd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_i2c_cpld.c @@ -0,0 +1 @@ +../../common/modules/accton_i2c_cpld.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_pmbus_3y.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_pmbus_3y.c new file mode 120000 index 000000000000..7504a0556e18 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/accton_pmbus_3y.c @@ -0,0 +1 @@ +../../common/modules/accton_pmbus_3y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/leds-accton_as7712_32x.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/leds-accton_as7712_32x.c new file mode 100644 index 000000000000..a3238d4b1615 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/leds-accton_as7712_32x.c @@ -0,0 +1,689 @@ +/* + * A LED driver for the accton_as7712_32x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int accton_i2c_cpld_read (unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "accton_as7712_32x_led" +#define ENABLE_PORT_LED 1 + +struct accton_as7712_32x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct accton_as7712_32x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +#if (ENABLE_PORT_LED == 1) +#define LED_TYPE_PORT_LED(port) \ + LED_TYPE_PORT##port##_LED0, \ + LED_TYPE_PORT##port##_LED1, \ + LED_TYPE_PORT##port##_LED2, \ + LED_TYPE_PORT##port##_LED3 +#endif + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2, +#if (ENABLE_PORT_LED == 1) + LED_TYPE_PORT_LED(0), + LED_TYPE_PORT_LED(1), + LED_TYPE_PORT_LED(2), + LED_TYPE_PORT_LED(3), + LED_TYPE_PORT_LED(4), + LED_TYPE_PORT_LED(5), + LED_TYPE_PORT_LED(6), + LED_TYPE_PORT_LED(7), + LED_TYPE_PORT_LED(8), + LED_TYPE_PORT_LED(9), + LED_TYPE_PORT_LED(10), + LED_TYPE_PORT_LED(11), + LED_TYPE_PORT_LED(12), + LED_TYPE_PORT_LED(13), + LED_TYPE_PORT_LED(14), + LED_TYPE_PORT_LED(15), + LED_TYPE_PORT_LED(16), + LED_TYPE_PORT_LED(17), + LED_TYPE_PORT_LED(18), + LED_TYPE_PORT_LED(19), + LED_TYPE_PORT_LED(20), + LED_TYPE_PORT_LED(21), + LED_TYPE_PORT_LED(22), + LED_TYPE_PORT_LED(23), + LED_TYPE_PORT_LED(24), + LED_TYPE_PORT_LED(25), + LED_TYPE_PORT_LED(26), + LED_TYPE_PORT_LED(27), + LED_TYPE_PORT_LED(28), + LED_TYPE_PORT_LED(29), + LED_TYPE_PORT_LED(30), + LED_TYPE_PORT_LED(31), +#endif +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7712_32x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as7712_32x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7712_32x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as7712_32x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7712_32x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as7712_32x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7712_32x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as7712_32x_led_diag_get(struct led_classdev *cdev) +{ + accton_as7712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as7712_32x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7712_32x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as7712_32x_led_loc_get(struct led_classdev *cdev) +{ + accton_as7712_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as7712_32x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7712_32x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +#if (ENABLE_PORT_LED == 1) +#define PORT_LED_COLOR_MASK (0x7 << 2) +#define PORT_LED_COLOR1_REG_VAL (0x0 << 2) +#define PORT_LED_COLOR2_REG_VAL (0x1 << 2) +#define PORT_LED_COLOR3_REG_VAL (0x2 << 2) +#define PORT_LED_COLOR4_REG_VAL (0x3 << 2) +#define PORT_LED_COLOR5_REG_VAL (0x4 << 2) +#define PORT_LED_COLOR6_REG_VAL (0x5 << 2) +#define PORT_LED_COLOR7_REG_VAL (0x6 << 2) +#define PORT_LED_COLOR8_REG_VAL (0x7 << 2) + +static int accton_as7712_32x_port_led_read_value(unsigned short cpld_addr, u8 reg) +{ + return accton_i2c_cpld_read(cpld_addr, reg); +} + +static int accton_as7712_32x_port_led_write_value(unsigned short cpld_addr, u8 reg, u8 value) +{ + return accton_i2c_cpld_write(cpld_addr, reg, value); +} + +static int port_led_mode_to_cpld_val(int mode) +{ + u8 color = 0; + u8 blinking = 0; + u8 on = 1 << 0; + + switch (mode) { + case LED_MODE_WHITE_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_WHITE: color = 0x0 << 2; + break; + case LED_MODE_YELLOW_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_YELLOW: color = 0x1 << 2; + break; + case LED_MODE_ORANGE_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_ORANGE: color = 0x2 << 2; + break; + case LED_MODE_PURPLE_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_PURPLE: color = 0x3 << 2; + break; + case LED_MODE_CYAN_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_CYAN: color = 0x4 << 2; + break; + case LED_MODE_RED_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_RED: color = 0x5 << 2; + break; + case LED_MODE_GREEN_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_GREEN: color = 0x6 << 2; + break; + case LED_MODE_BLUE_BLINKING: blinking = 1 << 1; /* fall through */ + case LED_MODE_BLUE: color = 0x7 << 2; + break; + case LED_MODE_OFF: on = 0 << 0; + break; + default: + return -EINVAL; + } + + return (color | blinking | on); +} + +static int cpld_val_to_port_led_mode(uint8_t value) +{ + int on = (value & 0x1); + int blinking = (value & 0x2); + int color = (value & PORT_LED_COLOR_MASK) ; + + if (!on) { + return LED_MODE_OFF; + } + + switch (color) { + case PORT_LED_COLOR1_REG_VAL: + return blinking ? LED_MODE_WHITE_BLINKING : LED_MODE_WHITE; + case PORT_LED_COLOR2_REG_VAL: + return blinking ? LED_MODE_YELLOW_BLINKING : LED_MODE_YELLOW; + case PORT_LED_COLOR3_REG_VAL: + return blinking ? LED_MODE_ORANGE_BLINKING : LED_MODE_ORANGE; + case PORT_LED_COLOR4_REG_VAL: + return blinking ? LED_MODE_PURPLE_BLINKING : LED_MODE_PURPLE; + case PORT_LED_COLOR5_REG_VAL: + return blinking ? LED_MODE_CYAN_BLINKING : LED_MODE_CYAN; + case PORT_LED_COLOR6_REG_VAL: + return blinking ? LED_MODE_RED_BLINKING : LED_MODE_RED; + case PORT_LED_COLOR7_REG_VAL: + return blinking ? LED_MODE_GREEN_BLINKING : LED_MODE_GREEN; + case PORT_LED_COLOR8_REG_VAL: + return blinking ? LED_MODE_BLUE_BLINKING : LED_MODE_BLUE; + default: + return -EINVAL;; + } +} + + +static void accton_as7712_32x_port_led_set(struct led_classdev *cdev, + enum led_brightness led_light_mode) +{ + unsigned int port, lid; + unsigned short cpld_addr; + u8 reg, value; + sscanf(cdev->name, "accton_as7712_32x_led::port%u_led%u", &port, &lid); + + if (port > 32 || lid > 4) { + dev_dbg(&ledctl->pdev->dev, "Port(%u), Led_id(%u) not match\n", port, lid); + return; + } + + cpld_addr = (port < 16) ? 0x64 : 0x62; + reg = (0x50 + (port % 16) * 4 + lid); + value = port_led_mode_to_cpld_val(led_light_mode); + + if (value < 0) { + dev_dbg(&ledctl->pdev->dev, "Unknow port led mode(%d)\n", led_light_mode); + return; + } + + accton_as7712_32x_port_led_write_value(cpld_addr, reg, value); +} + +static enum led_brightness accton_as7712_32x_port_led_get(struct led_classdev *cdev) +{ + unsigned int port, lid; + unsigned short cpld_addr; + u8 reg, value; + sscanf(cdev->name, "accton_as7712_32x_led::port%u_led%u", &port, &lid); + + if (port > 32 || lid > 4) { + dev_dbg(&ledctl->pdev->dev, "Port(%u), Led_id(%u) not match\n", port, lid); + return -EINVAL; + } + + cpld_addr = (port < 16) ? 0x64 : 0x62; + reg = (0x50 + (port % 16) * 4 + lid); + value = accton_as7712_32x_port_led_read_value(cpld_addr, reg); + + if (value < 0) { + dev_dbg(&ledctl->pdev->dev, "Unable to read reg value from cpld(0x%x), reg(0x%x)\n", cpld_addr, reg); + return value; + } + + return cpld_val_to_port_led_mode(value); +} + +#define _PORT_LED_CLASSDEV(port, lid) \ + [LED_TYPE_PORT##port##_LED##lid] = { \ + .name = "accton_as7712_32x_led::port"#port"_led"#lid,\ + .default_trigger = "unused", \ + .brightness_set = accton_as7712_32x_port_led_set, \ + .brightness_get = accton_as7712_32x_port_led_get, \ + .max_brightness = LED_MODE_CYAN_BLINKING, \ + } + +#define PORT_LED_CLASSDEV(port) \ + _PORT_LED_CLASSDEV(port, 0),\ + _PORT_LED_CLASSDEV(port, 1),\ + _PORT_LED_CLASSDEV(port, 2),\ + _PORT_LED_CLASSDEV(port, 3) +#endif + +static struct led_classdev accton_as7712_32x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as7712_32x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as7712_32x_led_diag_set, + .brightness_get = accton_as7712_32x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "accton_as7712_32x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as7712_32x_led_loc_set, + .brightness_get = accton_as7712_32x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "accton_as7712_32x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7712_32x_led_auto_set, + .brightness_get = accton_as7712_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as7712_32x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7712_32x_led_auto_set, + .brightness_get = accton_as7712_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as7712_32x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7712_32x_led_auto_set, + .brightness_get = accton_as7712_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +#if (ENABLE_PORT_LED == 1) + PORT_LED_CLASSDEV(0), + PORT_LED_CLASSDEV(1), + PORT_LED_CLASSDEV(2), + PORT_LED_CLASSDEV(3), + PORT_LED_CLASSDEV(4), + PORT_LED_CLASSDEV(5), + PORT_LED_CLASSDEV(6), + PORT_LED_CLASSDEV(7), + PORT_LED_CLASSDEV(8), + PORT_LED_CLASSDEV(9), + PORT_LED_CLASSDEV(10), + PORT_LED_CLASSDEV(11), + PORT_LED_CLASSDEV(12), + PORT_LED_CLASSDEV(13), + PORT_LED_CLASSDEV(14), + PORT_LED_CLASSDEV(15), + PORT_LED_CLASSDEV(16), + PORT_LED_CLASSDEV(17), + PORT_LED_CLASSDEV(18), + PORT_LED_CLASSDEV(19), + PORT_LED_CLASSDEV(20), + PORT_LED_CLASSDEV(21), + PORT_LED_CLASSDEV(22), + PORT_LED_CLASSDEV(23), + PORT_LED_CLASSDEV(24), + PORT_LED_CLASSDEV(25), + PORT_LED_CLASSDEV(26), + PORT_LED_CLASSDEV(27), + PORT_LED_CLASSDEV(28), + PORT_LED_CLASSDEV(29), + PORT_LED_CLASSDEV(30), + PORT_LED_CLASSDEV(31), +#endif +}; + +static int accton_as7712_32x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) { + led_classdev_suspend(&accton_as7712_32x_leds[i]); + } + + return 0; +} + +static int accton_as7712_32x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) { + led_classdev_resume(&accton_as7712_32x_leds[i]); + } + + return 0; +} + +static int accton_as7712_32x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7712_32x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7712_32x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7712_32x_leds[i]); + } + } + + return ret; +} + +static int accton_as7712_32x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7712_32x_leds); i++) { + led_classdev_unregister(&accton_as7712_32x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7712_32x_led_driver = { + .probe = accton_as7712_32x_led_probe, + .remove = accton_as7712_32x_led_remove, + .suspend = accton_as7712_32x_led_suspend, + .resume = accton_as7712_32x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7712_32x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7712_32x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7712_32x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7712_32x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7712_32x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7712_32x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7712_32x_led_driver); + kfree(ledctl); +} + +module_init(accton_as7712_32x_led_init); +module_exit(accton_as7712_32x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7712_32x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/pmbus.h new file mode 120000 index 000000000000..b0e1a57107fd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/pmbus.h @@ -0,0 +1 @@ +../../common/modules/pmbus.h \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/service/as7712-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/service/as7712-platform-init.service new file mode 100755 index 000000000000..d5d25b6cde04 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/service/as7712-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Accton AS7712-32X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/accton_as7712_util.py install +ExecStop=/usr/local/bin/accton_as7712_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/setup.py new file mode 100755 index 000000000000..09c763c84f01 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7712_32x', + version='1.0', + description='Module to initialize Accton AS7712-32X platforms', + + packages=['as7712_32x'], + package_dir={'as7712_32x': 'as7712-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/README new file mode 100755 index 000000000000..0b9fc1633999 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/README @@ -0,0 +1,60 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +To initialize the system, run "accton_as7712_util.py install". +To clean up the drivers & devices, run "accton_as7712_util.py clean". +To dump information of sensors, run "accton_as7712_util.py show". +To dump SFP EEPROM, run "accton_as7712_util.py sff". +To set fan speed, run "accton_as7712_util.py set fan". +To enable/disable SFP emission, run "accton_as7712_util.py set sfp". +To set system LEDs' color, run "accton_as7712_util.py set led" +For more information, run "accton_as7712_util.py --help". + +==================================================================== +Besides applying accton_as7712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +LED controls can be found under /sys/class/leds. The sysfs interface +color mappings are as follows: +Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + +There are 5 system LEDs, loc, diag, fan, ps1, and ps2. +They are lit automatically by CPLD, but the loc and diag. +The loc led has only 1 color, blue. +The diag one has 3 colors: red, amber, and green. + +Fan controls can be found in /sys/bus/i2c/devices/2-0066. +There are 12 fans inside 6 fan modules. +All fans share 1 duty setting, ranged from 0~100. + +Three temperature sensors are controlled by the lm75 kernel modules. +They should already be visible under /sys/bus/i2c/drivers/lm75/. + +Two power supplies are controlled by the CPLD. +Here provide their status under +/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. + +There are 32 QSFP+ modules are equipped. +Apply "accton_as7712_util.py show" to get their status. +Apply "accton_as7712_util.py set sfp" to turn on/off light transmission. +Apply "accton_as7712_util.py sff" to dump EEPROM information. +Before operating on that QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/accton_as7712_util.py b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/accton_as7712_util.py new file mode 100755 index 000000000000..8ebc39e6c9c1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7712-32x/utils/accton_as7712_util.py @@ -0,0 +1,569 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + + + + +PROJECT_NAME = 'as7712_32x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':6,'thermal':4, 'psu':2, 'sfp':32} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_cpld' , +'modprobe ym2651y' , +'modprobe accton_as7712_32x_fan' , +'modprobe optoe' , +'modprobe leds-accton_as7712_32x' , +'modprobe accton_as7712_32x_psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['2-0066'] , + 'thermal': ['3-0048','3-0049', '3-004a', '3-004b'] , + 'psu': ['10-0050','11-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present', 'sfp_tx_disable_all']} + +sfp_map = [22,23,24,25,27,26,29,28, + 18,19,20,21,30,31,32,33, + 34,35,36,37,46,47,48,49, + 38,39,40,41,42,43,44,45] +mknod =[ +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device' , +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', + +'echo as7712_32x_fan 0x66 > /sys/bus/i2c/devices/i2c-2/new_device ', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as7712_32x_psu1 0x53 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as7712_32x_psu2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo cpld_as7712 0x60 > /sys/bus/i2c/devices/i2c-4/new_device', +'echo cpld_plain 0x62 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo cpld_plain 0x64 > /sys/bus/i2c/devices/i2c-6/new_device'] + +mknod2 =[ +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0X73 > /sys/bus/i2c/devices/i2c-0/new_device' , +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as7712_32x_fan 0x66 > /sys/bus/i2c/devices/i2c-2/new_device ', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-3/new_device', +'echo as7712_32x_psu1 0x53 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as7712_32x_psu2 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo cpld_as7712 0x60 > /sys/bus/i2c/devices/i2c-4/new_device', +'echo cpld_plain 0x62 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo cpld_plain 0x64 > /sys/bus/i2c/devices/i2c-6/new_device'] + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + tmp = "echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-0/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x76 > /sys/bus/i2c/devices/i2c-0/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0076", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/fanutil.py new file mode 100755 index 000000000000..9a69f6e1d537 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/fanutil.py @@ -0,0 +1,254 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + #BASE_VAL_PATH = '/sys/devices/platform/as5712_54x_fan/{0}' + BASE_VAL_PATH = '/sys/bus/i2c/devices/9-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/9-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/thermalutil.py new file mode 100755 index 000000000000..50d8c85d94ca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/classes/thermalutil.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['10', '48'], + THERMAL_NUM_2_IDX: ['10', '49'], + THERMAL_NUM_3_IDX: ['10', '4a'], + } + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/Makefile new file mode 100755 index 000000000000..6cdbdd81ac1e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/Makefile @@ -0,0 +1,21 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as7716_32x_cpld1.o accton_as7716_32x_fan.o \ + accton_as7716_32x_leds.o accton_as7716_32x_psu.o cpr_4011_4mxx.o ym2651y.o \ + accton_i2c_cpld.o + +else +ifeq (,$(KERNEL_SRC)) +#$(error KERNEL_SRC is not defined) +KVERSION := $(shell uname -r) +KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ +KERNELDIR:=$(KERNEL_DIR) +#export KERNELDIR:=${PWD}/../../../../../src/sonic-linux-kernel/linux-3.16.43/ +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_cpld1.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_cpld1.c new file mode 100755 index 000000000000..cbab013f5860 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_cpld1.c @@ -0,0 +1,781 @@ +/* + * A hwmon driver for the as7716_32x_cpld + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +static int as7716_32x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7716_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +struct as7716_32x_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; +}; + +/* Addresses scanned for as7716_32x_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as7716_32x_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32), +}; + +/* sysfs attributes for hwmon + */ + +/* transceiver attributes */ +/*present*/ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_present, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +/*reset*/ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); + +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(32); + + +static struct attribute *as7716_32x_cpld_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_ATTR(1), + DECLARE_TRANSCEIVER_ATTR(2), + DECLARE_TRANSCEIVER_ATTR(3), + DECLARE_TRANSCEIVER_ATTR(4), + DECLARE_TRANSCEIVER_ATTR(5), + DECLARE_TRANSCEIVER_ATTR(6), + DECLARE_TRANSCEIVER_ATTR(7), + DECLARE_TRANSCEIVER_ATTR(8), + DECLARE_TRANSCEIVER_ATTR(9), + DECLARE_TRANSCEIVER_ATTR(10), + DECLARE_TRANSCEIVER_ATTR(11), + DECLARE_TRANSCEIVER_ATTR(12), + DECLARE_TRANSCEIVER_ATTR(13), + DECLARE_TRANSCEIVER_ATTR(14), + DECLARE_TRANSCEIVER_ATTR(15), + DECLARE_TRANSCEIVER_ATTR(16), + DECLARE_TRANSCEIVER_ATTR(17), + DECLARE_TRANSCEIVER_ATTR(18), + DECLARE_TRANSCEIVER_ATTR(19), + DECLARE_TRANSCEIVER_ATTR(20), + DECLARE_TRANSCEIVER_ATTR(21), + DECLARE_TRANSCEIVER_ATTR(22), + DECLARE_TRANSCEIVER_ATTR(23), + DECLARE_TRANSCEIVER_ATTR(24), + DECLARE_TRANSCEIVER_ATTR(25), + DECLARE_TRANSCEIVER_ATTR(26), + DECLARE_TRANSCEIVER_ATTR(27), + DECLARE_TRANSCEIVER_ATTR(28), + DECLARE_TRANSCEIVER_ATTR(29), + DECLARE_TRANSCEIVER_ATTR(30), + DECLARE_TRANSCEIVER_ATTR(31), + DECLARE_TRANSCEIVER_ATTR(32), + DECLARE_TRANSCEIVER_RESET_ATTR(1), + DECLARE_TRANSCEIVER_RESET_ATTR(2), + DECLARE_TRANSCEIVER_RESET_ATTR(3), + DECLARE_TRANSCEIVER_RESET_ATTR(4), + DECLARE_TRANSCEIVER_RESET_ATTR(5), + DECLARE_TRANSCEIVER_RESET_ATTR(6), + DECLARE_TRANSCEIVER_RESET_ATTR(7), + DECLARE_TRANSCEIVER_RESET_ATTR(8), + DECLARE_TRANSCEIVER_RESET_ATTR(9), + DECLARE_TRANSCEIVER_RESET_ATTR(10), + DECLARE_TRANSCEIVER_RESET_ATTR(11), + DECLARE_TRANSCEIVER_RESET_ATTR(12), + DECLARE_TRANSCEIVER_RESET_ATTR(13), + DECLARE_TRANSCEIVER_RESET_ATTR(14), + DECLARE_TRANSCEIVER_RESET_ATTR(15), + DECLARE_TRANSCEIVER_RESET_ATTR(16), + DECLARE_TRANSCEIVER_RESET_ATTR(17), + DECLARE_TRANSCEIVER_RESET_ATTR(18), + DECLARE_TRANSCEIVER_RESET_ATTR(19), + DECLARE_TRANSCEIVER_RESET_ATTR(20), + DECLARE_TRANSCEIVER_RESET_ATTR(21), + DECLARE_TRANSCEIVER_RESET_ATTR(22), + DECLARE_TRANSCEIVER_RESET_ATTR(23), + DECLARE_TRANSCEIVER_RESET_ATTR(24), + DECLARE_TRANSCEIVER_RESET_ATTR(25), + DECLARE_TRANSCEIVER_RESET_ATTR(26), + DECLARE_TRANSCEIVER_RESET_ATTR(27), + DECLARE_TRANSCEIVER_RESET_ATTR(28), + DECLARE_TRANSCEIVER_RESET_ATTR(29), + DECLARE_TRANSCEIVER_RESET_ATTR(30), + DECLARE_TRANSCEIVER_RESET_ATTR(31), + DECLARE_TRANSCEIVER_RESET_ATTR(32), + NULL +}; + +static const struct attribute_group as7716_32x_cpld_group = { + .attrs = as7716_32x_cpld_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[4] = {0}; + u8 regs[] = {0x30, 0x31, 0x32, 0x33}; + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7716_32x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 32 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x30; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x31; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x32; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x33; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as7716_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 reg = 0, mask = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + + switch (attr->index) { + case CPLD_VERSION: + reg = 0x1; + mask = 0xFF; + break; + default: + break; + } + + mutex_lock(&data->update_lock); + status = as7716_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", (status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7716_32x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as7716_32x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7716_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static void as7716_32x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7716_32x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int as7716_32x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct as7716_32x_cpld_data *data = NULL; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7716_32x_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32x_cpld_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + as7716_32x_cpld_add_client(client); + + dev_info(&client->dev, "%s: cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32x_cpld_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32x_cpld_remove(struct i2c_client *client) +{ + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32x_cpld_group); + kfree(data); + as7716_32x_cpld_remove_client(client); + + return 0; +} + +int as7716_32x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7716_32x_cpld_read); + +int as7716_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7716_32x_cpld_write); + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x04; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x05; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x06; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x07; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as7716_32x_cpld_read_internal(client, reg); + + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\r\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status=0, val, error; + u8 reg = 0, mask = 0; + + + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x04; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x05; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x06; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x07; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + mutex_lock(&data->update_lock); + + status = as7716_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update lp_mode status */ + if (reset) + { + val = status&(~mask); + } + else + { + val =status | (mask); + } + + status = as7716_32x_cpld_write_internal(client, reg, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + +static const struct i2c_device_id as7716_32x_cpld_id[] = { + { "as7716_32x_cpld1", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32x_cpld_id); + +static struct i2c_driver as7716_32x_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32x_cpld1", + }, + .probe = as7716_32x_cpld_probe, + .remove = as7716_32x_cpld_remove, + .id_table = as7716_32x_cpld_id, + .address_list = normal_i2c, +}; + +static int __init as7716_32x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7716_32x_cpld_driver); +} + +static void __exit as7716_32x_cpld_exit(void) +{ + i2c_del_driver(&as7716_32x_cpld_driver); +} + +module_init(as7716_32x_cpld_init); +module_exit(as7716_32x_cpld_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32x_cpld driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_fan.c new file mode 100644 index 000000000000..3a0610fe370d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_fan.c @@ -0,0 +1,535 @@ +/* + * A hwmon driver for the Accton as7716 32x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7716_32x_fan" + +#define IN +#define OUT + +static struct as7716_32x_fan_data *as7716_32x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:B2F 1:F2B) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7716_32x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); + +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); + +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); + +static struct attribute *as7716_32x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7716_32x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7716_32x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7716_32x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7716_32x_fan_data *data = as7716_32x_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7716_32x_fan_data *data = as7716_32x_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as7716_32x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7716_32x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7716_32x_fan_data *data = as7716_32x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7716_32x_fan_group = { + .attrs = as7716_32x_fan_attributes, +}; + +static struct as7716_32x_fan_data *as7716_32x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7716_32x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7716_32x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7716_32x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7716_32x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32x_fan_remove(struct i2c_client *client) +{ + struct as7716_32x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7716_32x_fan_id[] = { + { "as7716_32x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32x_fan_id); + +static struct i2c_driver as7716_32x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7716_32x_fan_probe, + .remove = as7716_32x_fan_remove, + .id_table = as7716_32x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7716_32x_fan_init(void) +{ + return i2c_add_driver(&as7716_32x_fan_driver); +} + +static void __exit as7716_32x_fan_exit(void) +{ + i2c_del_driver(&as7716_32x_fan_driver); +} + +module_init(as7716_32x_fan_init); +module_exit(as7716_32x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_leds.c new file mode 100755 index 000000000000..cb08189e3360 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_leds.c @@ -0,0 +1,441 @@ +/* + * A LED driver for the as7716_32x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as7716_32x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as7716_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as7716_32x_led" + +struct as7716_32x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct as7716_32x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting as7716_32x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as7716_32x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as7716_32x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = as7716_32x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + as7716_32x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void as7716_32x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7716_32x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness as7716_32x_led_diag_get(struct led_classdev *cdev) +{ + as7716_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void as7716_32x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7716_32x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness as7716_32x_led_loc_get(struct led_classdev *cdev) +{ + as7716_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void as7716_32x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness as7716_32x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev as7716_32x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "as7716_32x_led::diag", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_diag_set, + .brightness_get = as7716_32x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "as7716_32x_led::loc", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_loc_set, + .brightness_get = as7716_32x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "as7716_32x_led::fan", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "as7716_32x_led::psu1", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as7716_32x_led::psu2", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int as7716_32x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_suspend(&as7716_32x_leds[i]); + } + + return 0; +} + +static int as7716_32x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_resume(&as7716_32x_leds[i]); + } + + return 0; +} + +static int as7716_32x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as7716_32x_leds[i]); + + if (ret < 0) + { + break; + } + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as7716_32x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&as7716_32x_leds[i]); + } + } + + return 0; +} + +static int as7716_32x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_unregister(&as7716_32x_leds[i]); + } + + return 0; +} + +static struct platform_driver as7716_32x_led_driver = { + .probe = as7716_32x_led_probe, + .remove = as7716_32x_led_remove, + .suspend = as7716_32x_led_suspend, + .resume = as7716_32x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as7716_32x_led_init(void) +{ + int ret; + + + ret = platform_driver_register(&as7716_32x_led_driver); + if (ret < 0) { + + goto exit; + } + + ledctl = kzalloc(sizeof(struct as7716_32x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&as7716_32x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&as7716_32x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return 0; +} + +static void __exit as7716_32x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as7716_32x_led_driver); + kfree(ledctl); +} + +module_init(as7716_32x_led_init); +module_exit(as7716_32x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_psu.c new file mode 100755 index 000000000000..78a58b820b2a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_psu.c @@ -0,0 +1,381 @@ +/* + * An hwmon driver for accton as7716_32x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODEL_NAME 16 + +#define DC12V_FAN_DIR_OFFSET 0x34 +#define DC12V_FAN_DIR_LEN 3 + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as7716_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7716_32x_cpld_read (unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MAX_MODEL_NAME+1]; /* Model name, read from eeprom */ + char fan_dir[DC12V_FAN_DIR_LEN+1]; /* DC12V fan direction */ +}; + +static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *dev); + +enum as7716_32x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_FAN_DIR /* For DC12V only */ +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_string, NULL, PSU_FAN_DIR); + +static struct attribute *as7716_32x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7716_32x_psu_data *data = as7716_32x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return -EIO; + } + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7716_32x_psu_data *data = as7716_32x_psu_update_device(dev); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + if (attr->index == PSU_MODEL_NAME) { + ptr = data->model_name; + } + else { /* PSU_FAN_DIR */ + ptr = data->fan_dir; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as7716_32x_psu_group = { + .attrs = as7716_32x_psu_attributes, +}; + +static int as7716_32x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7716_32x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32x_psu_remove(struct i2c_client *client) +{ + struct as7716_32x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7716_32x_psu1, + as7716_32x_psu2 +}; + +static const struct i2c_device_id as7716_32x_psu_id[] = { + { "as7716_32x_psu1", as7716_32x_psu1 }, + { "as7716_32x_psu2", as7716_32x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32x_psu_id); + +static struct i2c_driver as7716_32x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32x_psu", + }, + .probe = as7716_32x_psu_probe, + .remove = as7716_32x_psu_remove, + .id_table = as7716_32x_psu_id, + .address_list = normal_i2c, +}; + +static int as7716_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +enum psu_type { + PSU_TYPE_AC_110V, + PSU_TYPE_DC_48V, + PSU_TYPE_DC_12V +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_TYPE_AC_110V, 0x20, 8, "YM-2651Y"}, +{PSU_TYPE_DC_48V, 0x20, 8, "YM-2651V"}, +{PSU_TYPE_DC_12V, 0x00, 11, "PSU-12V-750"}, +}; + +static int as7716_32x_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as7716_32x_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} + +static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + data->valid = 0; + dev_dbg(&client->dev, "Starting as7716_32x update\n"); + + /* Read psu status */ + status = as7716_32x_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + goto exit; + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->fan_dir, 0, sizeof(data->fan_dir)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + if (as7716_32x_psu_model_name_get(dev) < 0) { + goto exit; + } + + if (strncmp(data->model_name, + models[PSU_TYPE_DC_12V].model_name, + models[PSU_TYPE_DC_12V].length) == 0) + { + /* Read fan direction */ + + status = as7716_32x_psu_read_block(client, DC12V_FAN_DIR_OFFSET, + data->fan_dir, DC12V_FAN_DIR_LEN); + + if (status < 0) { + data->fan_dir[0] = '\0'; + dev_dbg(&client->dev, "unable to read fan direction from (0x%x) offset(0x%x)\n", + client->addr, DC12V_FAN_DIR_OFFSET); + goto exit; + } + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7716_32x_psu_init(void) +{ + return i2c_add_driver(&as7716_32x_psu_driver); +} + +static void __exit as7716_32x_psu_exit(void) +{ + i2c_del_driver(&as7716_32x_psu_driver); +} + +module_init(as7716_32x_psu_init); +module_exit(as7716_32x_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_sfp.c new file mode 100755 index 000000000000..9c7a05632154 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_as7716_32x_sfp.c @@ -0,0 +1,365 @@ +/* + * An hwmon driver for accton as7716_32x sfp + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BIT_INDEX(i) (1UL << (i)) +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x62 +#define I2C_ADDR_CPLD3 0x64 +#define CPLD1_OFFSET_QSFP_PRESET1 0x30 +#define CPLD1_OFFSET_QSFP_PRESET2 0x31 +#define CPLD1_OFFSET_QSFP_PRESET3 0x32 +#define CPLD1_OFFSET_QSFP_PRESET4 0x33 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32x_sfp_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + int port; /* Front port index */ + char eeprom[256]; /* eeprom data */ + u32 is_present; /* present status */ +}; + +static struct as7716_32x_sfp_data *as7716_32x_sfp_update_device(struct device *dev); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da,char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +enum as7716_32x_sfp_sysfs_attributes { + SFP_PORT_NUMBER, + SFP_IS_PRESENT, + SFP_IS_PRESENT_ALL, + SFP_EEPROM +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM); + +static struct attribute *as7716_32x_sfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_eeprom.dev_attr.attr, + NULL +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->port+1); +} + +/* Error-check the CPLD read results. */ +#define VALIDATED_READ(_buf, _rv, _read_expr, _invert) \ +do { \ + _rv = (_read_expr); \ + if(_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if(_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ +} while(0) + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if(attr->index == SFP_IS_PRESENT_ALL) { + int values[4]; + /* + * Report the SFP_PRESENCE status for all ports. + */ + + /* QSFP_PRESENT Ports 1-8 */ + //VALIDATED_READ(buf, values[0], accton_i2c_cpld_read(0x62, 0x9), 1); + VALIDATED_READ(buf, values[0], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET1), 1); + /* QSFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET2), 1); + /* QSFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET3), 1); + /* QSFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET4), 1); + + /* Return values 1 -> 32 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + } + else { /* SFP_IS_PRESENT */ + struct as7716_32x_sfp_data *data = as7716_32x_sfp_update_device(dev); + + if (!data->valid) { + printk("return -EIO\n"); + return -EIO; + } + + return sprintf(buf, "%d\n", data->is_present); + } +} + +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7716_32x_sfp_data *data = as7716_32x_sfp_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!data->is_present) { + return 0; + } + + memcpy(buf, data->eeprom, sizeof(data->eeprom)); + + return sizeof(data->eeprom); +} + +static const struct attribute_group as7716_32x_sfp_group = { + .attrs = as7716_32x_sfp_attributes, +}; + +static int as7716_32x_sfp_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32x_sfp_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7716_32x_sfp_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + i2c_set_clientdata(client, data); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32x_sfp_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sfp '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32x_sfp_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32x_sfp_remove(struct i2c_client *client) +{ + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32x_sfp_group); + kfree(data); + + return 0; +} + +enum port_numbers { +as7716_32x_sfp1, as7716_32x_sfp2, as7716_32x_sfp3, as7716_32x_sfp4, +as7716_32x_sfp5, as7716_32x_sfp6, as7716_32x_sfp7, as7716_32x_sfp8, +as7716_32x_sfp9, as7716_32x_sfp10,as7716_32x_sfp11,as7716_32x_sfp12, +as7716_32x_sfp13,as7716_32x_sfp14,as7716_32x_sfp15,as7716_32x_sfp16, +as7716_32x_sfp17,as7716_32x_sfp18,as7716_32x_sfp19,as7716_32x_sfp20, +as7716_32x_sfp21,as7716_32x_sfp22,as7716_32x_sfp23,as7716_32x_sfp24, +as7716_32x_sfp25,as7716_32x_sfp26,as7716_32x_sfp27,as7716_32x_sfp28, +as7716_32x_sfp29,as7716_32x_sfp30,as7716_32x_sfp31,as7716_32x_sfp32 +}; + +static const struct i2c_device_id as7716_32x_sfp_id[] = { +{ "as7716_32x_sfp1", as7716_32x_sfp1 }, { "as7716_32x_sfp2", as7716_32x_sfp2 }, +{ "as7716_32x_sfp3", as7716_32x_sfp3 }, { "as7716_32x_sfp4", as7716_32x_sfp4 }, +{ "as7716_32x_sfp5", as7716_32x_sfp5 }, { "as7716_32x_sfp6", as7716_32x_sfp6 }, +{ "as7716_32x_sfp7", as7716_32x_sfp7 }, { "as7716_32x_sfp8", as7716_32x_sfp8 }, +{ "as7716_32x_sfp9", as7716_32x_sfp9 }, { "as7716_32x_sfp10", as7716_32x_sfp10 }, +{ "as7716_32x_sfp11", as7716_32x_sfp11 }, { "as7716_32x_sfp12", as7716_32x_sfp12 }, +{ "as7716_32x_sfp13", as7716_32x_sfp13 }, { "as7716_32x_sfp14", as7716_32x_sfp14 }, +{ "as7716_32x_sfp15", as7716_32x_sfp15 }, { "as7716_32x_sfp16", as7716_32x_sfp16 }, +{ "as7716_32x_sfp17", as7716_32x_sfp17 }, { "as7716_32x_sfp18", as7716_32x_sfp18 }, +{ "as7716_32x_sfp19", as7716_32x_sfp19 }, { "as7716_32x_sfp20", as7716_32x_sfp20 }, +{ "as7716_32x_sfp21", as7716_32x_sfp21 }, { "as7716_32x_sfp22", as7716_32x_sfp22 }, +{ "as7716_32x_sfp23", as7716_32x_sfp23 }, { "as7716_32x_sfp24", as7716_32x_sfp24 }, +{ "as7716_32x_sfp25", as7716_32x_sfp25 }, { "as7716_32x_sfp26", as7716_32x_sfp26 }, +{ "as7716_32x_sfp27", as7716_32x_sfp27 }, { "as7716_32x_sfp28", as7716_32x_sfp28 }, +{ "as7716_32x_sfp29", as7716_32x_sfp29 }, { "as7716_32x_sfp30", as7716_32x_sfp30 }, +{ "as7716_32x_sfp31", as7716_32x_sfp31 }, { "as7716_32x_sfp32", as7716_32x_sfp32 }, +{} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32x_sfp_id); + +static struct i2c_driver as7716_32x_sfp_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32x_sfp", + }, + .probe = as7716_32x_sfp_probe, + .remove = as7716_32x_sfp_remove, + .id_table = as7716_32x_sfp_id, + .address_list = normal_i2c, +}; + +static int as7716_32x_sfp_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +static struct as7716_32x_sfp_data *as7716_32x_sfp_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + int i = 0; + u8 cpld_reg = 0x30 + (data->port/8); + + data->valid = 0; + + /* Read present status of the specified port number */ + data->is_present = 0; + status = accton_i2c_cpld_read(I2C_ADDR_CPLD1, cpld_reg); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD1, cpld_reg, status); + goto exit; + } + + data->is_present = (status & (1 << (data->port % 8))) ? 0 : 1; + printk("data->is_present=%d, data->port=%d, status=0x%x\n",data->is_present, data->port, status); + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if (data->is_present) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom)/I2C_SMBUS_BLOCK_MAX; i++) { + status = as7716_32x_sfp_read_block(client, i*I2C_SMBUS_BLOCK_MAX, + data->eeprom+(i*I2C_SMBUS_BLOCK_MAX), + I2C_SMBUS_BLOCK_MAX); + if (status < 0) { + printk("unable to read eeprom from port(%d)\n", data->port); + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", data->port); + goto exit; + } + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7716_32x_sfp_init(void) +{ + //extern int platform_accton_as7716_32x(void); + //if (!platform_accton_as7716_32x()) { +// return -ENODEV; + //} + + return i2c_add_driver(&as7716_32x_sfp_driver); +} + +static void __exit as7716_32x_sfp_exit(void) +{ + i2c_del_driver(&as7716_32x_sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7716_32x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(as7716_32x_sfp_init); +module_exit(as7716_32x_sfp_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_i2c_cpld.c new file mode 100755 index 000000000000..46d1e2773287 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/accton_i2c_cpld.c @@ -0,0 +1,259 @@ +/* + * A hwmon driver for the accton_i2c_cpld + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPLD_VERSION_REG 0x1 + +enum as5712_54x_cpld_sysfs_attributes { + CPLD_READ_VERSION, + CPLD_BYTE_ACCESS, + CPLD_DUMP_ALL, +}; + +static ssize_t read_cpld_version(struct device *dev, struct device_attribute *da, + char *buf); +int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); + + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for accton_i2c_cpld + */ +static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, I2C_CLIENT_END }; + +static SENSOR_DEVICE_ATTR(cpld_get_version, S_IRUGO, read_cpld_version, NULL, CPLD_READ_VERSION); + +static struct attribute *as5712_54x_cpld_attributes[] = { + &sensor_dev_attr_cpld_get_version.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5712_54x_cpld_group = { + .attrs = as5712_54x_cpld_attributes, +}; + +static ssize_t read_cpld_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + unsigned short cpld_reg = CPLD_VERSION_REG; + u8 reg; + + if(attr->index == CPLD_READ_VERSION) { + reg = accton_i2c_cpld_read(client->addr, cpld_reg); + return sprintf(buf, "%02x\n",reg); + } + return -1 ; +} + + +static void accton_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void accton_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int accton_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5712_54x_cpld_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + accton_i2c_cpld_add_client(client); + + return 0; +exit: + return status; +} + +static int accton_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &as5712_54x_cpld_group); + + accton_i2c_cpld_remove_client(client); + return 0; +} + +static const struct i2c_device_id accton_i2c_cpld_id[] = { + { "accton_i2c_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); + +static struct i2c_driver accton_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_cpld", + }, + .probe = accton_i2c_cpld_probe, + .remove = accton_i2c_cpld_remove, + .id_table = accton_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_read); + +int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_write); + +static int __init accton_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&accton_i2c_cpld_driver); +} + +static void __exit accton_i2c_cpld_exit(void) +{ + i2c_del_driver(&accton_i2c_cpld_driver); +} +/* +static struct dmi_system_id as7712_dmi_table[] = { + { + .ident = "Accton AS7712", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"), + }, + } +}; + +int platform_accton_as7712_32x(void) +{ + return dmi_check_system(as7712_dmi_table); +} +EXPORT_SYMBOL(platform_accton_as7712_32x); +*/ +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_cpld_init); +module_exit(accton_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/cpr_4011_4mxx.c new file mode 100755 index 000000000000..30bea914d589 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/cpr_4011_4mxx.c @@ -0,0 +1,400 @@ +/* + * An hwmon driver for the CPR-4011-4Mxx Redundant Power Module + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x3c, 0x3d, 0x3e, 0x3f, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct cpr_4011_4mxx_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev); + +enum cpr_4011_4mxx_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); + +static struct attribute *cpr_4011_4mxx_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cpr_4011_4mxx_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static const struct attribute_group cpr_4011_4mxx_group = { + .attrs = cpr_4011_4mxx_attributes, +}; + +static int cpr_4011_4mxx_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct cpr_4011_4mxx_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct cpr_4011_4mxx_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpr_4011_4mxx_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int cpr_4011_4mxx_remove(struct i2c_client *client) +{ + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id cpr_4011_4mxx_id[] = { + { "cpr_4011_4mxx", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpr_4011_4mxx_id); + +static struct i2c_driver cpr_4011_4mxx_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cpr_4011_4mxx", + }, + .probe = cpr_4011_4mxx_probe, + .remove = cpr_4011_4mxx_remove, + .id_table = cpr_4011_4mxx_id, + .address_list = normal_i2c, +}; + +static int cpr_4011_4mxx_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cpr_4011_4mxx_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + struct reg_data_byte regs_byte[] = { {0x20, &data->vout_mode}, + {0x81, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &(data->fan_speed[0])}, + {0x91, &(data->fan_speed[1])}}; + + dev_dbg(&client->dev, "Starting cpr_4011_4mxx update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cpr_4011_4mxx_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = cpr_4011_4mxx_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init cpr_4011_4mxx_init(void) +{ + return i2c_add_driver(&cpr_4011_4mxx_driver); +} + +static void __exit cpr_4011_4mxx_exit(void) +{ + i2c_del_driver(&cpr_4011_4mxx_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("CPR_4011_4MXX driver"); +MODULE_LICENSE("GPL"); + +module_init(cpr_4011_4mxx_init); +module_exit(cpr_4011_4mxx_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/ym2651y.c new file mode 100755 index 000000000000..8e76c56b54fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/modules/ym2651y.c @@ -0,0 +1,603 @@ +/* + * An hwmon driver for the 3Y Power YM-2651Y Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct ym2651y_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 capability; /* Register value */ + u16 status_word; /* Register value */ + u8 fan_fault; /* Register value */ + u8 over_temp; /* Register value */ + u16 v_out; /* Register value */ + u16 i_out; /* Register value */ + u16 p_out; /* Register value */ + u16 temp; /* Register value */ + u16 fan_speed; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u8 fan_dir[4]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[10]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct ym2651y_data *ym2651y_update_device(struct device *dev); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum ym2651y_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/ + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + +static struct attribute *ym2651y_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u16 status = 0; + + switch (attr->index) { + case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ + status = (data->status_word & 0x40) ? 0 : 1; + break; + case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ + status = (data->status_word & 0x4) >> 2; + break; + case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ + status = (data->status_word & 0x800) ? 0 : 1; + break; + } + + return sprintf(buf, "%d\n", status); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_OUT: + value = data->v_out; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_OUT_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + case PSU_FAN1_DUTY_CYCLE: + value = data->fan_duty_cycle[0]; + multiplier = 1; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_VOUT_MIN: + value = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + value = data->mfr_vout_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + + return sprintf(buf, "%d\n", data->over_temp >> 7); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 *ptr = NULL; + + switch (attr->index) { + case PSU_FAN_DIRECTION: /* psu_fan_dir */ + ptr = data->fan_dir; + break; + case PSU_MFR_ID: /* psu_mfr_id */ + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: /* psu_mfr_revision */ + ptr = data->mfr_revsion; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group ym2651y_group = { + .attrs = ym2651y_attributes, +}; + +static int ym2651y_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ym2651y_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int ym2651y_remove(struct i2c_client *client) +{ + struct ym2651y_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id ym2651y_id[] = { + { "ym2651", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ym2651y_id); + +static struct i2c_driver ym2651y_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ym2651", + }, + .probe = ym2651y_probe, + .remove = ym2651y_remove, + .id_table = ym2651y_id, + .address_list = normal_i2c, +}; + +static int ym2651y_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int ym2651y_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct ym2651y_data *ym2651y_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + u8 command; + u8 fan_dir[5] = {0}; + struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, + {0x7d, &data->over_temp}, + {0x81, &data->fan_fault}, + {0x98, &data->pmbus_revision}}; + struct reg_data_word regs_word[] = { {0x79, &data->status_word}, + {0x8b, &data->v_out}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x8d, &data->temp}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &data->fan_speed}, + {0xa0, &data->mfr_vin_min}, + {0xa1, &data->mfr_vin_max}, + {0xa2, &data->mfr_iin_max}, + {0xa3, &data->mfr_pin_max}, + {0xa4, &data->mfr_vout_min}, + {0xa5, &data->mfr_vout_max}, + {0xa6, &data->mfr_iout_max}, + {0xa7, &data->mfr_pout_max}}; + + dev_dbg(&client->dev, "Starting ym2651 update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = ym2651y_read_byte(client, regs_byte[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = ym2651y_read_word(client, regs_word[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read fan_direction */ + command = 0xC3; + status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + } + + strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1); + data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; + + /* Read mfr_id */ + command = 0x99; + status = ym2651y_read_block(client, command, data->mfr_id, + ARRAY_SIZE(data->mfr_id)-1); + data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_model */ + command = 0x9a; + status = ym2651y_read_block(client, command, data->mfr_model, + ARRAY_SIZE(data->mfr_model)-1); + data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_revsion */ + command = 0x9b; + status = ym2651y_read_block(client, command, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)-1); + data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(ym2651y_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/service/as7716-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/service/as7716-platform-monitor.service new file mode 100755 index 000000000000..b1428d7844f8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/service/as7716-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS7716-32X Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7716_util.py install +ExecStart=/usr/local/bin/accton_as7716_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/setup.py new file mode 100755 index 000000000000..7a3d784d326e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7716_32x', + version='1.0', + description='Module to initialize Accton AS7716-32X platforms', + + packages=['as7716_32x'], + package_dir={'as7716_32x': 'as7716-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/README new file mode 100755 index 000000000000..44e03cab5f52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_monitor.py new file mode 100755 index 000000000000..c423cc441d92 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_monitor.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import time # this is only being used as part of the example + from as7716_32x.fanutil import FanUtil + from as7716_32x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7716_monitor' + +global log_file +global log_level + + # For AC power Front to Back : + # If any fan fail, please fan speed register to 15 + # The max value of Fan speed register is 9 + # [LM75(48) + LM75(49) + LM75(4A)] > 174 => set Fan speed value from 4 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] > 182 => set Fan speed value from 5 to 7 + # [LM75(48) + LM75(49) + LM75(4A)] > 190 => set Fan speed value from 7 to 9 + # + # [LM75(48) + LM75(49) + LM75(4A)] < 170 => set Fan speed value from 5 to 4 + # [LM75(48) + LM75(49) + LM75(4A)] < 178 => set Fan speed value from 7 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] < 186 => set Fan speed value from 9 to 7 + # + # + # For AC power Back to Front : + # If any fan fail, please fan speed register to 15 + # The max value of Fan speed register is 10 + # [LM75(48) + LM75(49) + LM75(4A)] > 140 => set Fan speed value from 4 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] > 150 => set Fan speed value from 5 to 7 + # [LM75(48) + LM75(49) + LM75(4A)] > 160 => set Fan speed value from 7 to 10 + # + # [LM75(48) + LM75(49) + LM75(4A)] < 135 => set Fan speed value from 5 to 4 + # [LM75(48) + LM75(49) + LM75(4A)] < 145 => set Fan speed value from 7 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] < 155 => set Fan speed value from 10 to 7 + # + + + # 2.If no matched fan speed is found from the policy, + # use FAN_DUTY_CYCLE_MIN as default speed + # Get current temperature + # 4.Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature + + + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7716_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + + fan_policy_f2b = { + 0: [32, 0, 174000], + 1: [38, 170000, 182000], + 2: [50, 178000, 190000], + 3: [63, 186000, 0], + } + fan_policy_b2f = { + 0: [32, 0, 140000], + 1: [38, 135000, 150000], + 2: [50, 145000, 160000], + 3: [69, 15500, 0], + } + + thermal = ThermalUtil() + fan = FanUtil() + get_temp = thermal.get_thermal_temp() + + cur_duty_cycle = fan.get_fan_duty_cycle() + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', 100, x) + return False + if fan_status is False: + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', 100, x) + fan.set_fan_duty_cycle(45) + return True + logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + if fan_status is not None and fan_status is not False: + fan_dir=fan.get_fan_dir(1) + for x in range(0, 4): + if cur_duty_cycle == fan_policy_f2b[x][0]: + break + + if fan_dir == 1: + if x == 4 : + fan.set_fan_duty_cycle(fan_policy_f2b[0][0]) + new_duty_cycle=cur_duty_cycle + # if temp > up_levle, else if temp < down_level + if get_temp > fan_policy_f2b[x][2] and x != 3 : + new_duty_cycle= fan_policy_f2b[x+1][0] + logging.debug('INFO. THERMAL temp UP, temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy_f2b[x][2], new_duty_cycle) + elif get_temp < fan_policy_f2b[x][1] : + new_duty_cycle= fan_policy_f2b[x-1][0] + logging.debug('INFO. THERMAL temp down, temp %d < %d , new_duty_cycle=%d', get_temp, fan_policy_f2b[x][1], new_duty_cycle) + if new_duty_cycle == cur_duty_cycle : + return True + else: + if x == 4 : + fan.set_fan_duty_cycle(fan_policy_b2f[0][0]) + new_duty_cycle=cur_duty_cycle + # if temp > up_levle, else if temp < down_level + if get_temp > fan_policy_b2f[x][1] and x != 3 : + new_duty_cycle= fan_policy_b2f[x+1][0] + logging.debug('INFO. THERMAL temp UP, temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy_b2f[x][2], new_duty_cycle) + elif get_temp < fan_policy_b2f[x][0] and x != 0 : + new_duty_cycle= fan_policy_b2f[x-1][0] + logging.debug('INFO. THERMAL temp down, temp %d < %d , new_duty_cycle=%d', get_temp, fan_policy_b2f[x][1], new_duty_cycle) + if new_duty_cycle == cur_duty_cycle : + return True + + fan.set_fan_duty_cycle(new_duty_cycle) + + return True + + + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + monitor = accton_as7716_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(1) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_util.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_util.py new file mode 100755 index 000000000000..142ce754a5c7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32x/utils/accton_as7716_util.py @@ -0,0 +1,629 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + +PROJECT_NAME = 'as7716_32x' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':54} + + +led_prefix ='/sys/devices/platform/as7716_32x_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as7716_32x_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['10-0048','10-0049', '10-004a'] , + 'psu': ['17-0050','18-0053'], + 'sfp': ['-0050']} +i2c_nodes = { + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +sfp_map = [29, 30, 31, 32, 34, 33, 36, 35, + 25, 26, 27, 28, 37, 38, 39, 40, + 41, 42, 43, 44, 53, 54, 55, 56, + 45, 46, 47, 48, 49, 50, 51, 52] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo as7716_32x_fan 0x66 > /sys/bus/i2c/devices/i2c-9/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-10/new_device', + +'echo as7716_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo accton_i2c_cpld 0x62 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo accton_i2c_cpld 0x64 > /sys/bus/i2c/devices/i2c-13/new_device', + +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-2/new_device', + +# PSU-1 +'echo as7716_32x_psu1 0x53 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-18/new_device', + +# PSU-2 +'echo as7716_32x_psu2 0x50> /sys/bus/i2c/devices/i2c-17/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-17/new_device', + + + +#EERPOM +'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +mknod2 =[ +'echo as7716_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo accton_i2c_cpld 0x61 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo accton_i2c_cpld 0x62 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', + +# PSU-1 +'echo as7716_32x_psu1 0x38 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-57/new_device', +'echo as7716_32x_psu1 0x50 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-57/new_device', + +# PSU-2 +'echo as7716_32x_psu2 0x3b > /sys/bus/i2c/devices/i2c-58/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-58/new_device', +'echo as7716_32x_psu2 0x53 > /sys/bus/i2c/devices/i2c-58/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-58/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-61/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-62/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-63/new_device', + +#EERPOM +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def dis_i2c_ir3570a(addr): + cmd = "i2cset -y 0 0x%x 0xE5 0x01" % addr + status, output = commands.getstatusoutput(cmd) + cmd = "i2cset -y 0 0x%x 0x12 0x02" % addr + status, output = commands.getstatusoutput(cmd) + return status + +def ir3570_check(): + cmd = "i2cdump -y 0 0x42 s 0x9a" + try: + status, output = commands.getstatusoutput(cmd) + lines = output.split('\n') + hn = re.findall(r'\w+', lines[-1]) + version = int(hn[1], 16) + if version == 0x24: #only for ir3570a + ret = dis_i2c_ir3570a(4) + else: + ret = 0 + except Exception as e: + print "Error on ir3570_check() e:" + str(e) + return -1 + return ret + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + +#'modprobe cpr_4011_4mxx', + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_cpld', +'modprobe cpr_4011_4mxx', +'modprobe ym2651y', +'modprobe accton_as7716_32x_cpld1', +'modprobe accton_as7716_32x_fan', +'modprobe accton_as7716_32x_leds', +'modprobe accton_as7716_32x_psu'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + #remove parameter if any + rm = kos[-(i+1)] + lst = rm.split(" ") + if len(lst) > 2: + del(lst[2:]) + rm = " ".join(lst) + + #Change to removing commands + rm = rm.replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca932x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + print "not device_exist()" + return False + return True + +def do_install(): + if driver_inserted() == False: + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + + ir3570_check() + + if not device_exist(): + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/fanutil.py new file mode 100755 index 000000000000..e001e94092c7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/fanutil.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + #BASE_VAL_PATH = '/sys/devices/platform/as5712_54x_fan/{0}' + BASE_VAL_PATH = '/sys/bus/i2c/devices/9-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/9-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + #print "fan_num=%d" %fan_num + #print "node_num=%d" %node_num + #print "device_path=%s" %device_path + #print "content=%s" %content + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + #self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path + self._fan_to_device_node_mapping[(fan_num, node_num)]) + #print "fan_num=%d" %fan_num + #print "node_num=%d" %node_num + #print "self._fan_to_device_path_mapping[(fan_num, node_num)]=%s" %self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + print "fan %d return none" %fan_num + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/thermalutil.py new file mode 100755 index 000000000000..d3feda8faad9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/classes/thermalutil.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 3 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD + + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['10', '48'], + THERMAL_NUM_2_IDX: ['10', '49'], + THERMAL_NUM_3_IDX: ['10', '4a'], + } + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1): + self._thermal_to_device_path_mapping[x] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + #print "self._thermal_to_device_path_mapping[x]=%s" %self._thermal_to_device_path_mapping[x] + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/Makefile new file mode 100755 index 000000000000..3dfb021a7aaf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/Makefile @@ -0,0 +1,17 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as7716_32xb_cpld1.o accton_as7716_32xb_fan.o \ + accton_as7716_32xb_leds.o accton_as7716_32xb_psu.o \ + accton_as7716_32xb_thermal.o accton_as7716_32xb_oom.o accton_as7716_32xb_pmbus.o\ + accton_as7716_32xb_sys.o accton_i2c_cpld.o +else +ifeq (,$(KERNEL_SRC)) +$(error KERNEL_SRC is not defined) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_cpld1.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_cpld1.c new file mode 100644 index 000000000000..c322972481ba --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_cpld1.c @@ -0,0 +1,1021 @@ +/* + * A hwmon driver for the as7716_32xbb_cpld + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ +#define STRING_TO_DEC_VALUE 10 + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +static int as7716_32xb_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7716_32xb_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +static ssize_t sfp_value_show(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t sfp_value_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size); + + +#define PORT_NUM_MAX 32 + +struct as7716_32xb_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; + unsigned int present[PORT_NUM_MAX]; + unsigned int reset[PORT_NUM_MAX]; +}; +enum port_id { + PORT1_ID, + PORT2_ID, + PORT3_ID, + PORT4_ID, + PORT5_ID, + PORT6_ID, + PORT7_ID, + PORT8_ID, + PORT9_ID, + PORT10_ID, + PORT11_ID, + PORT12_ID, + PORT13_ID, + PORT14_ID, + PORT15_ID, + PORT16_ID, + PORT17_ID, + PORT18_ID, + PORT19_ID, + PORT20_ID, + PORT21_ID, + PORT22_ID, + PORT23_ID, + PORT24_ID, + PORT25_ID, + PORT26_ID, + PORT27_ID, + PORT28_ID, + PORT29_ID, + PORT30_ID, + PORT31_ID, + PORT32_ID +}; + +/* Addresses scanned for as7716_32xbb_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index + +enum as7716_32xb_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32), +}; + +/* sysfs attributes for hwmon + */ + +/* transceiver attributes */ +/*present*/ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IWUSR|S_IRUGO, sfp_value_show, sfp_value_store, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +/*reset*/ +//#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ +// static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, MODULE_RESET_##index) +//#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, sfp_value_show, sfp_value_store, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + + + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); + +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(32); + + +static struct attribute *as7716_32xb_cpld_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + DECLARE_TRANSCEIVER_ATTR(1), + DECLARE_TRANSCEIVER_ATTR(2), + DECLARE_TRANSCEIVER_ATTR(3), + DECLARE_TRANSCEIVER_ATTR(4), + DECLARE_TRANSCEIVER_ATTR(5), + DECLARE_TRANSCEIVER_ATTR(6), + DECLARE_TRANSCEIVER_ATTR(7), + DECLARE_TRANSCEIVER_ATTR(8), + DECLARE_TRANSCEIVER_ATTR(9), + DECLARE_TRANSCEIVER_ATTR(10), + DECLARE_TRANSCEIVER_ATTR(11), + DECLARE_TRANSCEIVER_ATTR(12), + DECLARE_TRANSCEIVER_ATTR(13), + DECLARE_TRANSCEIVER_ATTR(14), + DECLARE_TRANSCEIVER_ATTR(15), + DECLARE_TRANSCEIVER_ATTR(16), + DECLARE_TRANSCEIVER_ATTR(17), + DECLARE_TRANSCEIVER_ATTR(18), + DECLARE_TRANSCEIVER_ATTR(19), + DECLARE_TRANSCEIVER_ATTR(20), + DECLARE_TRANSCEIVER_ATTR(21), + DECLARE_TRANSCEIVER_ATTR(22), + DECLARE_TRANSCEIVER_ATTR(23), + DECLARE_TRANSCEIVER_ATTR(24), + DECLARE_TRANSCEIVER_ATTR(25), + DECLARE_TRANSCEIVER_ATTR(26), + DECLARE_TRANSCEIVER_ATTR(27), + DECLARE_TRANSCEIVER_ATTR(28), + DECLARE_TRANSCEIVER_ATTR(29), + DECLARE_TRANSCEIVER_ATTR(30), + DECLARE_TRANSCEIVER_ATTR(31), + DECLARE_TRANSCEIVER_ATTR(32), + DECLARE_TRANSCEIVER_RESET_ATTR(1), + DECLARE_TRANSCEIVER_RESET_ATTR(2), + DECLARE_TRANSCEIVER_RESET_ATTR(3), + DECLARE_TRANSCEIVER_RESET_ATTR(4), + DECLARE_TRANSCEIVER_RESET_ATTR(5), + DECLARE_TRANSCEIVER_RESET_ATTR(6), + DECLARE_TRANSCEIVER_RESET_ATTR(7), + DECLARE_TRANSCEIVER_RESET_ATTR(8), + DECLARE_TRANSCEIVER_RESET_ATTR(9), + DECLARE_TRANSCEIVER_RESET_ATTR(10), + DECLARE_TRANSCEIVER_RESET_ATTR(11), + DECLARE_TRANSCEIVER_RESET_ATTR(12), + DECLARE_TRANSCEIVER_RESET_ATTR(13), + DECLARE_TRANSCEIVER_RESET_ATTR(14), + DECLARE_TRANSCEIVER_RESET_ATTR(15), + DECLARE_TRANSCEIVER_RESET_ATTR(16), + DECLARE_TRANSCEIVER_RESET_ATTR(17), + DECLARE_TRANSCEIVER_RESET_ATTR(18), + DECLARE_TRANSCEIVER_RESET_ATTR(19), + DECLARE_TRANSCEIVER_RESET_ATTR(20), + DECLARE_TRANSCEIVER_RESET_ATTR(21), + DECLARE_TRANSCEIVER_RESET_ATTR(22), + DECLARE_TRANSCEIVER_RESET_ATTR(23), + DECLARE_TRANSCEIVER_RESET_ATTR(24), + DECLARE_TRANSCEIVER_RESET_ATTR(25), + DECLARE_TRANSCEIVER_RESET_ATTR(26), + DECLARE_TRANSCEIVER_RESET_ATTR(27), + DECLARE_TRANSCEIVER_RESET_ATTR(28), + DECLARE_TRANSCEIVER_RESET_ATTR(29), + DECLARE_TRANSCEIVER_RESET_ATTR(30), + DECLARE_TRANSCEIVER_RESET_ATTR(31), + DECLARE_TRANSCEIVER_RESET_ATTR(32), + NULL +}; + +static const struct attribute_group as7716_32xb_cpld_group = { + .attrs = as7716_32xb_cpld_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[4] = {0}; + u8 regs[] = {0x30, 0x31, 0x32, 0x33}; + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7716_32xb_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 32 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int sfp_array_index_get(int attr_idx) +{ + switch(attr_idx) + { + case TRANSCEIVER_PRESENT_ATTR_ID(1): + case TRANSCEIVER_RESET_ATTR_ID(1): + return PORT1_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(2): + case TRANSCEIVER_RESET_ATTR_ID(2): + return PORT2_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(3): + case TRANSCEIVER_RESET_ATTR_ID(3): + return PORT3_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(4): + case TRANSCEIVER_RESET_ATTR_ID(4): + return PORT4_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(5): + case TRANSCEIVER_RESET_ATTR_ID(5): + return PORT5_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(6): + case TRANSCEIVER_RESET_ATTR_ID(6): + return PORT6_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(7): + case TRANSCEIVER_RESET_ATTR_ID(7): + return PORT7_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(8): + case TRANSCEIVER_RESET_ATTR_ID(8): + return PORT8_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(9): + case TRANSCEIVER_RESET_ATTR_ID(9): + return PORT9_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(10): + case TRANSCEIVER_RESET_ATTR_ID(10): + return PORT10_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(11): + case TRANSCEIVER_RESET_ATTR_ID(11): + return PORT11_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(12): + case TRANSCEIVER_RESET_ATTR_ID(12): + return PORT12_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(13): + case TRANSCEIVER_RESET_ATTR_ID(13): + return PORT13_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(14): + case TRANSCEIVER_RESET_ATTR_ID(14): + return PORT14_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(15): + case TRANSCEIVER_RESET_ATTR_ID(15): + return PORT15_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(16): + case TRANSCEIVER_RESET_ATTR_ID(16): + return PORT16_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(17): + case TRANSCEIVER_RESET_ATTR_ID(17): + return PORT17_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(18): + case TRANSCEIVER_RESET_ATTR_ID(18): + return PORT18_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(19): + case TRANSCEIVER_RESET_ATTR_ID(19): + return PORT19_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(20): + case TRANSCEIVER_RESET_ATTR_ID(20): + return PORT20_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(21): + case TRANSCEIVER_RESET_ATTR_ID(21): + return PORT21_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(22): + case TRANSCEIVER_RESET_ATTR_ID(22): + return PORT22_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(23): + case TRANSCEIVER_RESET_ATTR_ID(23): + return PORT23_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(24): + case TRANSCEIVER_RESET_ATTR_ID(24): + return PORT24_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(25): + case TRANSCEIVER_RESET_ATTR_ID(25): + return PORT25_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(26): + case TRANSCEIVER_RESET_ATTR_ID(26): + return PORT26_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(27): + case TRANSCEIVER_RESET_ATTR_ID(27): + return PORT27_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(28): + case TRANSCEIVER_RESET_ATTR_ID(28): + return PORT28_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(29): + case TRANSCEIVER_RESET_ATTR_ID(29): + return PORT29_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(30): + case TRANSCEIVER_RESET_ATTR_ID(30): + return PORT30_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(31): + case TRANSCEIVER_RESET_ATTR_ID(31): + return PORT31_ID; + case TRANSCEIVER_PRESENT_ATTR_ID(32): + case TRANSCEIVER_RESET_ATTR_ID(32): + return PORT32_ID; + default : + return -1; + } +} + + +static ssize_t sfp_value_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + int index; + long keyin = 0; + + //printk("sfp_value_store\n"); + //printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + index=sfp_array_index_get(attr->index); + if(index < 0 || index > PORT_NUM_MAX -1) + break; + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if(keyin < 0 || keyin > 1) + break; + data->present[index]=keyin; + break; + case MODULE_RESET_1 ... MODULE_RESET_8: + case MODULE_RESET_9 ... MODULE_RESET_16: + case MODULE_RESET_17 ... MODULE_RESET_24: + case MODULE_RESET_25 ... MODULE_RESET_32: + index=sfp_array_index_get(attr->index); + if(index < 0 || index > PORT_NUM_MAX -1) + break; + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if(keyin < 0 || keyin > 1) + break; + data->reset[index]=keyin; + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return size; +} +static ssize_t sfp_value_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + ssize_t ret = 0; + int index; + int status = -EINVAL; + + //printk("sfp_value_show, attr->index=%d\n", attr->index); + //printk("TRANSCEIVER_PRESENT_ATTR_ID(1)=%d, TRANSCEIVER_RESET_ATTR_ID(1)=%d\n", TRANSCEIVER_PRESENT_ATTR_ID(1), TRANSCEIVER_RESET_ATTR_ID(1)); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + index=sfp_array_index_get(attr->index); + if(index < 0 || index > PORT_NUM_MAX -1) + break; + status = sprintf(buf, "%u\n", data->present[index]); + break; + case MODULE_RESET_1 ... MODULE_RESET_8: + case MODULE_RESET_9 ... MODULE_RESET_16: + case MODULE_RESET_17 ... MODULE_RESET_24: + case MODULE_RESET_25 ... MODULE_RESET_32: + index=sfp_array_index_get(attr->index); + //printk("rst:attr->index=%d, index=%d\n",attr->index, index); + if(index < 0 || index > PORT_NUM_MAX -1) + break; + status = sprintf(buf, "%u\n", data->reset[index]); + break; + default : + break; + } + + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x30; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x31; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x32; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x33; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as7716_32xb_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 reg = 0, mask = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + + switch (attr->index) { + case CPLD_VERSION: + reg = 0x1; + mask = 0xFF; + break; + default: + break; + } + + mutex_lock(&data->update_lock); + status = as7716_32xb_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", (status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7716_32xb_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as7716_32xb_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7716_32xb_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static void as7716_32xb_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7716_32xb_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int as7716_32xb_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct as7716_32xb_cpld_data *data = NULL; + + data = kzalloc(sizeof(struct as7716_32xb_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_cpld_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + as7716_32xb_cpld_add_client(client); + + dev_info(&client->dev, "%s: cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_cpld_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_cpld_remove(struct i2c_client *client) +{ + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_cpld_group); + kfree(data); + as7716_32xb_cpld_remove_client(client); + + return 0; +} + +int as7716_32xb_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7716_32xb_cpld_read); + +int as7716_32xb_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7716_32xb_cpld_write); + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x04; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x05; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x06; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x07; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as7716_32xb_cpld_read_internal(client, reg); + + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\r\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status=0, val, error; + u8 reg = 0, mask = 0; + + + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + //printk("set_mode_reset:attr->index=%d\n",attr->index); + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x04; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x05; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x06; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x07; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + mutex_lock(&data->update_lock); + + status = as7716_32xb_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + //printk("set_mode_reset:reset=%d, reg=0x%x, mask=0x%x, ori_val=0x%x\n", reset, reg, mask, status); + /* Update lp_mode status */ + if (reset) + { + val = status&(~mask); + //printk("1:new val=0x%x\n", val); + } + else + { + val =status | (mask); + //printk("0:new val=0x%x\n", val); + } + + status = as7716_32xb_cpld_write_internal(client, reg, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + +static const struct i2c_device_id as7716_32xb_cpld_id[] = { + { "as7716_32xb_cpld1", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_cpld_id); + +static struct i2c_driver as7716_32xb_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_cpld1", + }, + .probe = as7716_32xb_cpld_probe, + .remove = as7716_32xb_cpld_remove, + .id_table = as7716_32xb_cpld_id, + .address_list = normal_i2c, +}; + +static int __init as7716_32xb_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7716_32xb_cpld_driver); +} + +static void __exit as7716_32xb_cpld_exit(void) +{ + i2c_del_driver(&as7716_32xb_cpld_driver); +} + +module_init(as7716_32xb_cpld_init); +module_exit(as7716_32xb_cpld_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32xb_cpld driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_fan.c new file mode 100644 index 000000000000..65f3251c00ec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_fan.c @@ -0,0 +1,710 @@ +/* + * A hwmon driver for the Accton as7716 32x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7716_32xb_fan" + +#define NUM_THERMAL_SENSORS (3) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define STRING_TO_DEC_VALUE 10 + +#define IN +#define OUT + +static struct as7716_32xb_fan_data *as7716_32xb_fan_update_device(struct device *dev); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_enable(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +static ssize_t fan_value_show(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t fan_value_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:B2F 1:F2B) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +#define FAN_NUM_MAX 6 +/* Each client has this additional data */ +struct as7716_32xb_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + u8 enable; + u8 duty_cycle; + unsigned int present[FAN_NUM_MAX]; + unsigned int front_speed_rpm[FAN_NUM_MAX]; + unsigned int rear_speed_rpm[FAN_NUM_MAX]; + unsigned int direction[FAN_NUM_MAX]; + unsigned int fault[FAN_NUM_MAX]; + unsigned int input[FAN_NUM_MAX]; +}; + +enum FAN_ID { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO|S_IWUSR, fan_value_show, fan_value_store, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO|S_IWUSR, fan_value_show, fan_value_store, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO|S_IWUSR, fan_value_show, fan_value_store, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_value_show, fan_value_store, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_value_show, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index##_enable, S_IWUSR | S_IRUGO, get_enable, set_enable, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr, \ + &sensor_dev_attr_pwm##index##_enable.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IWUSR|S_IRUGO, fan_value_show, fan_value_store, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IWUSR|S_IRUGO, fan_value_show, fan_value_store, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IWUSR|S_IRUGO, fan_value_show, fan_value_store, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IWUSR|S_IRUGO, fan_value_show, fan_value_store, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IWUSR|S_IRUGO, fan_value_show, fan_value_store, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); + +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); + +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); + +static struct attribute *as7716_32xb_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7716_32xb_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7716_32xb_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum FAN_ID id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum FAN_ID id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7716_32xb_fan_data *data, enum FAN_ID id) +{ + u8 ret = 0; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (!data->front_speed_rpm[id] && + !data->rear_speed_rpm[id] ) + { + ret = 1; + } + + return ret; +} + + +static ssize_t set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7716_32xb_fan_data *data = as7716_32xb_fan_update_device(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 1) + return -EINVAL; + + data->enable = value; + if (value == 0) + { + return set_duty_cycle(dev, da, buf, FAN_MAX_DUTY_CYCLE); + } + return count; +} + + + +static ssize_t get_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7716_32xb_fan_data *data = as7716_32xb_fan_update_device(dev); + + return sprintf(buf, "%u\n", data->enable); +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as7716_32xb_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7716_32xb_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static int fan_array_index_get(int attr_idx) +{ + switch(attr_idx) + { + case FAN1_PRESENT: + case FAN1_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN1_FAULT: + case FAN1_DIRECTION: + return FAN1_ID; + case FAN2_PRESENT: + case FAN2_FRONT_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN2_FAULT: + case FAN2_DIRECTION: + return FAN2_ID; + case FAN3_PRESENT: + case FAN3_FRONT_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN3_FAULT: + case FAN3_DIRECTION: + return FAN3_ID; + case FAN4_PRESENT: + case FAN4_FRONT_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN4_FAULT: + case FAN4_DIRECTION: + return FAN4_ID; + case FAN5_PRESENT: + case FAN5_FRONT_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN5_FAULT: + case FAN5_DIRECTION: + return FAN5_ID; + case FAN6_PRESENT: + case FAN6_FRONT_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + case FAN6_FAULT: + case FAN6_DIRECTION: + return FAN6_ID; + default : + return -1; + } +} + +static ssize_t fan_value_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_fan_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + int index; + long keyin = 0; + //printk("fan_value_store\n"); + //printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case FAN_DUTY_CYCLE_PERCENTAGE: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + if (keyin > 1 || keyin < 0) + break; + data->duty_cycle=keyin; + break; + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + data->front_speed_rpm[index]=keyin; + break; + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + data->rear_speed_rpm[index]=keyin; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + if(keyin < 0 || keyin > 1) + break; + data->present[index]=keyin; + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + if(keyin < 0 || keyin > 1) + break; + data->fault[index]=keyin; + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + break; + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + if(keyin < 0 || keyin > 1) + break; + data->direction[index]=keyin; + break; + default: + break; + } + mutex_unlock(&data->update_lock); + return size; +} +static ssize_t fan_value_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_fan_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + int index=0; + //printk("ffan_value_show\n"); + //printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case FAN_DUTY_CYCLE_PERCENTAGE: + status = sprintf(buf, "%u\n", data->duty_cycle); + break; + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + status = sprintf(buf, "%u\n", data->front_speed_rpm[index]); + break; + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + status = sprintf(buf, "%u\n", data->rear_speed_rpm[index]); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + status = sprintf(buf, "%d\n", data->present[index]); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + index=fan_array_index_get(attr->index); + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + status = sprintf(buf, "%d\n", is_fan_fault(data, index)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + index=fan_array_index_get(attr->index);; + if(index < 0 || index > (FAN_NUM_MAX-1)) + break; + status = sprintf(buf, "%d\n", data->direction[index]); + break; + default: + break; + } + mutex_unlock(&data->update_lock); + return status; +} + +static const struct attribute_group as7716_32xb_fan_group = { + .attrs = as7716_32xb_fan_attributes, +}; + +static struct as7716_32xb_fan_data *as7716_32xb_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7716_32xb_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7716_32xb_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7716_32xb_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_fan_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_fan_remove(struct i2c_client *client) +{ + struct as7716_32xb_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7716_32xb_fan_id[] = { + { "as7716_32xb_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_fan_id); + +static struct i2c_driver as7716_32xb_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7716_32xb_fan_probe, + .remove = as7716_32xb_fan_remove, + .id_table = as7716_32xb_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7716_32xb_fan_init(void) +{ + return i2c_add_driver(&as7716_32xb_fan_driver); +} + +static void __exit as7716_32xb_fan_exit(void) +{ + i2c_del_driver(&as7716_32xb_fan_driver); +} + +module_init(as7716_32xb_fan_init); +module_exit(as7716_32xb_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32xb_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_leds.c new file mode 100755 index 000000000000..4e2162843a9e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_leds.c @@ -0,0 +1,442 @@ +/* + * A LED driver for the as7716_32xb_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as7716_32x_led" + +struct as7716_32x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct as7716_32x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting as7716_32x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as7716_32x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as7716_32x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = as7716_32x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + as7716_32x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void as7716_32x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7716_32x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness as7716_32x_led_diag_get(struct led_classdev *cdev) +{ + as7716_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void as7716_32x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7716_32x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness as7716_32x_led_loc_get(struct led_classdev *cdev) +{ + as7716_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void as7716_32x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness as7716_32x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev as7716_32x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "as7716_32x_led::diag", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_diag_set, + .brightness_get = as7716_32x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "as7716_32x_led::loc", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_loc_set, + .brightness_get = as7716_32x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "as7716_32x_led::fan", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "as7716_32x_led::psu1", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as7716_32x_led::psu2", + .default_trigger = "unused", + .brightness_set = as7716_32x_led_auto_set, + .brightness_get = as7716_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int as7716_32x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_suspend(&as7716_32x_leds[i]); + } + + return 0; +} + +static int as7716_32x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_resume(&as7716_32x_leds[i]); + } + + return 0; +} + +static int as7716_32x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + printk("as7716_32x_led_probe 1\n"); + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as7716_32x_leds[i]); + + if (ret < 0) + { + printk("ret < 0, i=%d\n", i); + break; + } + } + printk("as7716_32x_led_probe 2\n"); + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as7716_32x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&as7716_32x_leds[i]); + } + } + + printk("as7716_32x_led_probe 3\n"); + return 0; +} + +static int as7716_32x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as7716_32x_leds); i++) { + led_classdev_unregister(&as7716_32x_leds[i]); + } + + return 0; +} + +static struct platform_driver as7716_32x_led_driver = { + .probe = as7716_32x_led_probe, + .remove = as7716_32x_led_remove, + .suspend = as7716_32x_led_suspend, + .resume = as7716_32x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as7716_32x_led_init(void) +{ + int ret; + + printk("leds:1\n"); + ret = platform_driver_register(&as7716_32x_led_driver); + if (ret < 0) { + printk("leds:fail platform_driver_register\n"); + goto exit; + } + printk("leds:2\n"); + ledctl = kzalloc(sizeof(struct as7716_32x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&as7716_32x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + printk("leds:3\n"); + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + printk("leds:fail platform_device_register_simple\n"); + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&as7716_32x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return 0; +} + +static void __exit as7716_32x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as7716_32x_led_driver); + kfree(ledctl); +} + +module_init(as7716_32x_led_init); +module_exit(as7716_32x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_oom.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_oom.c new file mode 100755 index 000000000000..5e88d9efad5d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_oom.c @@ -0,0 +1,267 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STRING_TO_DEC_VALUE 10 +#define EEPROM_DATA_SIZE 512 + + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +#define MAX_PORT_NAME_LEN 20 +/* Each client has this additional data + */ +struct as7716_32xb_oom_data { + struct device *hwmon_dev; + struct mutex lock; + u8 index; + unsigned char eeprom[EEPROM_DATA_SIZE]; + char port_name[MAX_PORT_NAME_LEN]; + +}; + + + +enum as7716_32xb_oom_sysfs_attributes { + TEMP1_INPUT, + TEMP1_MAX_HYST, + TEMP1_MAX +}; + +/* sysfs attributes for hwmon + */ + +static ssize_t oom_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t oom_info_show(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_port_name(struct device *dev, + struct device_attribute *dattr, char *buf); +static ssize_t set_port_name(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +static SENSOR_DEVICE_ATTR(eeprom, S_IWUSR|S_IRUGO, oom_info_show, oom_info_store, 0); +static SENSOR_DEVICE_ATTR(port_name, S_IRUGO | S_IWUSR, show_port_name, set_port_name, 1); + + +static struct attribute *as7716_32xb_oom_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + &sensor_dev_attr_port_name.dev_attr.attr, + NULL +}; + + +static ssize_t oom_info_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_oom_data *data = i2c_get_clientdata(client); + int i; + + mutex_lock(&data->lock); + memcpy(buf, data->eeprom, EEPROM_DATA_SIZE); + //for(i=0; i < EEPROM_DATA_SIZE ; i++) + //{ + // buf[i]=data->eeprom[i]; + // printk("buf[%d]=0x%x ",i, buf[i]); + //} + //status = EEPROM_DATA_SIZE+1; + + + memcpy(buf, data->eeprom, 256); + mutex_unlock(&data->lock); + + return 256; +} + +static ssize_t oom_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_oom_data *data = i2c_get_clientdata(client); + int i=0, j=0, k=0; + unsigned char str[3]; + unsigned int val; + + // printk("strlen(buf)=%d\n",strlen(buf)); + k=0; + mutex_lock(&data->lock); + memset(data->eeprom, 0xFF, EEPROM_DATA_SIZE); + memset(str, 0x0, 3); + if(strlen(buf) >= 256 ) + { + for(i=0; i < strlen(buf) ; i++) + { + // printk("i=%d ", i); + for(j=0;j<2; j++) + { + str[j]=buf[i+j]; + } + sscanf(str, "%x", &val); + //printk("str=%s val=0x%x ", str, val); + i=j+i-1; + if(k>=EEPROM_DATA_SIZE) + { + break; + } + data->eeprom[k]=(unsigned char)val; + //printk("data->eeprom[%d]=0x%x\n",k, data->eeprom[k]); + k++; + } + } + //printk("buf=\n"); + //for(i=0; i < strlen(buf) ; i++) + //{ + // printk("%c%c ", buf[i], buf[i+1]); + // if((i % 31)==0) + // printk("\n"); + //} + //printk("\n"); + + + mutex_unlock(&data->lock); + return size; + +} + +static ssize_t show_port_name(struct device *dev, + struct device_attribute *dattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_oom_data *data = i2c_get_clientdata(client); + ssize_t count; + + mutex_lock(&data->lock); + count = sprintf(buf, "%s\n", data->port_name); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_port_name(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_oom_data *data = i2c_get_clientdata(client); + char port_name[MAX_PORT_NAME_LEN]; + + /* no checking, this value is not used except by show_port_name */ + + if (sscanf(buf, "%19s", port_name) != 1) + return -EINVAL; + + mutex_lock(&data->lock); + strcpy(data->port_name, port_name); + mutex_unlock(&data->lock); + + return count; +} + + +static const struct attribute_group as7716_32xb_oom_group = { + .attrs = as7716_32xb_oom_attributes, +}; + +static int as7716_32xb_oom_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_oom_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_oom_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + i2c_set_clientdata(client, data); + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_oom_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: oom '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_oom_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_oom_remove(struct i2c_client *client) +{ + struct as7716_32xb_oom_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_oom_group); + kfree(data); + + return 0; +} + + +static const struct i2c_device_id as7716_32xb_oom_id[] = { + { "as7716_32xb_oom", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_oom_id); + +static struct i2c_driver as7716_32xb_oom_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_oom", + }, + .probe = as7716_32xb_oom_probe, + .remove = as7716_32xb_oom_remove, + .id_table = as7716_32xb_oom_id, + .address_list = normal_i2c, +}; + + + + + + +static int __init as7716_32xb_oom_init(void) +{ + return i2c_add_driver(&as7716_32xb_oom_driver); +} + +static void __exit as7716_32xb_oom_exit(void) +{ + i2c_del_driver(&as7716_32xb_oom_driver); +} + +module_init(as7716_32xb_oom_init); +module_exit(as7716_32xb_oom_exit); + +MODULE_AUTHOR("Jostar yang "); +MODULE_DESCRIPTION("as7716_32xb_oom driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_pmbus.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_pmbus.c new file mode 100755 index 000000000000..3f4dba90d1aa --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_pmbus.c @@ -0,0 +1,444 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STRING_TO_DEC_VALUE 10 + + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32xb_pmbus_data { + struct device *hwmon_dev; + struct mutex update_lock; + u8 index; + u8 capability; + u16 status_word; + u8 fan_fault; + u8 over_temp; + u16 v_out; + u16 i_out; + u16 p_out; + u16 temp; + u16 fan_speed; + u16 fan_duty_cycle; + u8 fan_dir[4]; + u8 pmbus_revision; + u8 mfr_id[10]; + u8 mfr_model[10]; + u8 mfr_revision[3]; + u16 mfr_vin_min; + u16 mfr_vin_max; + u16 mfr_iin_max; + u16 mfr_iout_max; + u16 mfr_pin_max; + u16 mfr_pout_max; + u16 mfr_vout_min; + u16 mfr_vout_max; + u16 power_on; + u16 temp_fault; + u16 power_good; +}; + + + +enum as7716_32xb_pmbus_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/ + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static ssize_t pmbus_info_show(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t pmbus_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static SENSOR_DEVICE_ATTR(psu_power_on, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input,S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm,S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IWUSR| S_IRUGO, pmbus_info_show,pmbus_info_store, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IWUSR|S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IWUSR| S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_MFR_POUT_MAX); + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, pmbus_info_show, pmbus_info_store, PSU_TEMP_FAULT); + + +static struct attribute *as7716_32xb_pmbus_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + + +static ssize_t pmbus_info_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_pmbus_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + //printk("pmbus_info_show\n"); + printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case PSU_POWER_ON: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->power_on); + break; + case PSU_TEMP_FAULT: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->temp_fault); + break; + case PSU_POWER_GOOD: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->power_good); + break; + case PSU_FAN1_FAULT: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->fan_fault); + break; + case PSU_FAN_DIRECTION: + status=snprintf(buf, PAGE_SIZE-1, "%s\r\n", data->fan_dir); + break; + case PSU_OVER_TEMP: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->over_temp); + break; + case PSU_V_OUT: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->v_out); + break; + case PSU_I_OUT: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->i_out); + break; + case PSU_P_OUT: + printk("read PSU_P_OUT\n"); + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->p_out); + break; + case PSU_P_OUT_UV: + printk("read PSU_P_OUT_UV\n"); + status=snprintf(buf, PAGE_SIZE-1, "%ld\r\n", data->p_out * 1000000); + break; + case PSU_TEMP1_INPUT: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->temp); + break; + case PSU_FAN1_SPEED: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->fan_speed); + break; + case PSU_FAN1_DUTY_CYCLE: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->fan_duty_cycle); + break; + case PSU_PMBUS_REVISION: + break; + case PSU_MFR_ID: + status=snprintf(buf, PAGE_SIZE-1, "%s\r\n", data->mfr_id); + break; + case PSU_MFR_MODEL: + status=snprintf(buf, PAGE_SIZE-1, "%s\r\n", data->mfr_model); + break; + case PSU_MFR_REVISION: + status=snprintf(buf, PAGE_SIZE-1, "%s\r\n", data->mfr_revision); + break; + case PSU_MFR_VIN_MIN: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_vin_min); + break; + case PSU_MFR_VIN_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_vin_max); + break; + case PSU_MFR_VOUT_MIN: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_vin_max); + break; + case PSU_MFR_VOUT_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_vout_max); + break; + case PSU_MFR_IIN_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_iin_max); + break; + case PSU_MFR_IOUT_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_iout_max); + break; + case PSU_MFR_PIN_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_pin_max); + break; + case PSU_MFR_POUT_MAX: + status=snprintf(buf, PAGE_SIZE-1, "%d\r\n", data->mfr_pout_max); + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t pmbus_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_pmbus_data *data = i2c_get_clientdata(client); + long keyin = 0; + int status = -EINVAL; + //printk("pmbus_info_store\n"); + //printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + switch (attr->index) + { + case PSU_POWER_ON: + data->power_on=keyin; + break; + case PSU_TEMP_FAULT: + data->temp_fault=keyin; + break; + case PSU_POWER_GOOD: + data->power_good=keyin; + break; + case PSU_FAN1_FAULT: + break; + case PSU_FAN_DIRECTION: + memcpy(data->fan_dir, buf, sizeof(data->fan_dir)); + break; + case PSU_OVER_TEMP: + data->over_temp=keyin; + break; + case PSU_V_OUT: + data->v_out=keyin; + break; + case PSU_I_OUT: + data->i_out=keyin; + break; + case PSU_P_OUT: + printk("data->p_out=%d\n", data->p_out); + data->p_out=keyin; + break; + case PSU_P_OUT_UV: + //multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + + break; + case PSU_TEMP1_INPUT: + data->temp=keyin; + break; + case PSU_FAN1_SPEED: + data->fan_speed=keyin; + break; + case PSU_FAN1_DUTY_CYCLE: + break; + case PSU_PMBUS_REVISION: + data->pmbus_revision=keyin; + break; + case PSU_MFR_ID: + memcpy(data->mfr_id, buf, sizeof(data->mfr_id)); + break; + case PSU_MFR_MODEL: + memcpy(data->mfr_model, buf, sizeof(data->mfr_model)); + break; + case PSU_MFR_REVISION: + memcpy(data->mfr_revision, buf, sizeof(data->mfr_revision)); + break; + case PSU_MFR_VIN_MIN: + data->mfr_vin_min=keyin; + break; + case PSU_MFR_VIN_MAX: + data->mfr_vin_max=keyin; + break; + case PSU_MFR_VOUT_MIN: + data->mfr_vout_min=keyin; + break; + case PSU_MFR_VOUT_MAX: + data->mfr_vout_max=keyin; + break; + case PSU_MFR_IIN_MAX: + data->mfr_iin_max=keyin; + break; + case PSU_MFR_IOUT_MAX: + data->mfr_iout_max=keyin; + break; + case PSU_MFR_PIN_MAX: + data->mfr_pin_max=keyin; + break; + case PSU_MFR_POUT_MAX: + data->mfr_pout_max=keyin; + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return count; +} + + +static const struct attribute_group as7716_32xb_pmbus_group = { + .attrs = as7716_32xb_pmbus_attributes, +}; + +static int as7716_32xb_pmbus_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_pmbus_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_pmbus_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + i2c_set_clientdata(client, data); + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_pmbus_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: pmbus '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_pmbus_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_pmbus_remove(struct i2c_client *client) +{ + struct as7716_32xb_pmbus_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_pmbus_group); + kfree(data); + + return 0; +} + + +static const struct i2c_device_id as7716_32xb_pmbus_id[] = { + { "as7716_32xb_pmbus", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_pmbus_id); + +static struct i2c_driver as7716_32xb_pmbus_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_pmbus", + }, + .probe = as7716_32xb_pmbus_probe, + .remove = as7716_32xb_pmbus_remove, + .id_table = as7716_32xb_pmbus_id, + .address_list = normal_i2c, +}; + + + + + + +static int __init as7716_32xb_pmbus_init(void) +{ + return i2c_add_driver(&as7716_32xb_pmbus_driver); +} + +static void __exit as7716_32xb_pmbus_exit(void) +{ + i2c_del_driver(&as7716_32xb_pmbus_driver); +} + +module_init(as7716_32xb_pmbus_init); +module_exit(as7716_32xb_pmbus_exit); + +MODULE_AUTHOR("Jostar yang "); +MODULE_DESCRIPTION("as7716_32xb_pmbus driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_psu.c new file mode 100755 index 000000000000..01756e8596eb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_psu.c @@ -0,0 +1,355 @@ +/* + * An hwmon driver for accton as7716_32xbb Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODEL_NAME 16 +#define DC12V_FAN_DIR_OFFSET 0x34 +#define DC12V_FAN_DIR_LEN 3 +#define STRING_TO_DEC_VALUE 10 + +//static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as7716_32xb_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7716_32xb_cpld_read (unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32xb_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + u8 present; + u8 power_good; + char model_name[MAX_MODEL_NAME+1]; /* Model name, read from eeprom */ + char fan_dir[DC12V_FAN_DIR_LEN+1]; /* DC12V fan direction */ +}; + +enum as7716_32xb_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_FAN_DIR /* For DC12V only */ +}; + +/* sysfs attributes for hwmon + */ +static ssize_t psu_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t psu_info_show(struct device *dev, struct device_attribute *da, + char *buf); +static SENSOR_DEVICE_ATTR(psu_present, S_IWUSR|S_IRUGO, psu_info_show, psu_info_store, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IWUSR|S_IRUGO, psu_info_show, psu_info_store, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IWUSR|S_IRUGO, psu_info_show, psu_info_store, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IWUSR|S_IRUGO, psu_info_show, psu_info_store, PSU_FAN_DIR); + + +static struct attribute *as7716_32xb_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + NULL +}; + +static ssize_t psu_info_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_psu_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + //printk("psu_info_show\n"); + // printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case PSU_PRESENT: + //printk("data->present=%d\n",data->present); + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", data->present); + break; + case PSU_MODEL_NAME: + //printk("data->model_name=%s\n",data->model_name); + status = snprintf(buf, PAGE_SIZE - 1, "%s\r\n", data->model_name); + break; + case PSU_POWER_GOOD: + // printk("data->present=%d\n",data->power_good); + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", data->power_good); + break; + case PSU_FAN_DIR: + //printk("data->fan_dir=%s\n",data->fan_dir); + status = snprintf(buf, PAGE_SIZE - 1, "%s\r\n", data->fan_dir); + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t psu_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_psu_data *data = i2c_get_clientdata(client); + long keyin = 0; + int status = -EINVAL; + //printk("psu_info_store\n"); + //printk("attr->index=%d\n", attr->index); + mutex_lock(&data->update_lock); + switch (attr->index) + { + case PSU_PRESENT: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + goto fail_exit; + if (keyin > 1 || keyin < 0) + goto fail_exit; + data->present=keyin; + break; + case PSU_MODEL_NAME: + memcpy(data->model_name, buf, MAX_MODEL_NAME); + break; + case PSU_POWER_GOOD: + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + if (status) + goto fail_exit; + if (keyin > 1 || keyin < 0) + goto fail_exit; + data->power_good=keyin; + break; + case PSU_FAN_DIR: + memcpy(data->fan_dir, buf, DC12V_FAN_DIR_LEN); + break; + default : + goto fail_exit; + } + mutex_unlock(&data->update_lock); + return count; + +fail_exit: + mutex_unlock(&data->update_lock); + return -EINVAL; +} + +static const struct attribute_group as7716_32xb_psu_group = { + .attrs = as7716_32xb_psu_attributes, +}; + +static int as7716_32xb_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_psu_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_psu_remove(struct i2c_client *client) +{ + struct as7716_32xb_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7716_32xb_psu1, + as7716_32xb_psu2 +}; + +static const struct i2c_device_id as7716_32xb_psu_id[] = { + { "as7716_32xb_psu1", as7716_32xb_psu1 }, + { "as7716_32xb_psu2", as7716_32xb_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_psu_id); + +static struct i2c_driver as7716_32xb_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_psu", + }, + .probe = as7716_32xb_psu_probe, + .remove = as7716_32xb_psu_remove, + .id_table = as7716_32xb_psu_id, + .address_list = normal_i2c, +}; + +static int as7716_32xb_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +enum psu_type { + PSU_TYPE_AC_110V, + PSU_TYPE_DC_48V, + PSU_TYPE_DC_12V +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; + +struct model_name_info models[] = { +{PSU_TYPE_AC_110V, 0x20, 8, "YM-2651Y"}, +{PSU_TYPE_DC_48V, 0x20, 8, "YM-2651V"}, +{PSU_TYPE_DC_12V, 0x00, 11, "PSU-12V-750"}, +}; + +static int as7716_32xb_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as7716_32xb_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} + +static int __init as7716_32xb_psu_init(void) +{ + return i2c_add_driver(&as7716_32xb_psu_driver); +} + +static void __exit as7716_32xb_psu_exit(void) +{ + i2c_del_driver(&as7716_32xb_psu_driver); +} + +module_init(as7716_32xb_psu_init); +module_exit(as7716_32xb_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7716_32xb_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sfp.c new file mode 100755 index 000000000000..9c7a05632154 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sfp.c @@ -0,0 +1,365 @@ +/* + * An hwmon driver for accton as7716_32x sfp + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BIT_INDEX(i) (1UL << (i)) +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x62 +#define I2C_ADDR_CPLD3 0x64 +#define CPLD1_OFFSET_QSFP_PRESET1 0x30 +#define CPLD1_OFFSET_QSFP_PRESET2 0x31 +#define CPLD1_OFFSET_QSFP_PRESET3 0x32 +#define CPLD1_OFFSET_QSFP_PRESET4 0x33 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32x_sfp_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + int port; /* Front port index */ + char eeprom[256]; /* eeprom data */ + u32 is_present; /* present status */ +}; + +static struct as7716_32x_sfp_data *as7716_32x_sfp_update_device(struct device *dev); +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da,char *buf); +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf); +extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +enum as7716_32x_sfp_sysfs_attributes { + SFP_PORT_NUMBER, + SFP_IS_PRESENT, + SFP_IS_PRESENT_ALL, + SFP_EEPROM +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM); + +static struct attribute *as7716_32x_sfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_eeprom.dev_attr.attr, + NULL +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", data->port+1); +} + +/* Error-check the CPLD read results. */ +#define VALIDATED_READ(_buf, _rv, _read_expr, _invert) \ +do { \ + _rv = (_read_expr); \ + if(_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if(_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ +} while(0) + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if(attr->index == SFP_IS_PRESENT_ALL) { + int values[4]; + /* + * Report the SFP_PRESENCE status for all ports. + */ + + /* QSFP_PRESENT Ports 1-8 */ + //VALIDATED_READ(buf, values[0], accton_i2c_cpld_read(0x62, 0x9), 1); + VALIDATED_READ(buf, values[0], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET1), 1); + /* QSFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET2), 1); + /* QSFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET3), 1); + /* QSFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], accton_i2c_cpld_read(I2C_ADDR_CPLD1, CPLD1_OFFSET_QSFP_PRESET4), 1); + + /* Return values 1 -> 32 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + } + else { /* SFP_IS_PRESENT */ + struct as7716_32x_sfp_data *data = as7716_32x_sfp_update_device(dev); + + if (!data->valid) { + printk("return -EIO\n"); + return -EIO; + } + + return sprintf(buf, "%d\n", data->is_present); + } +} + +static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7716_32x_sfp_data *data = as7716_32x_sfp_update_device(dev); + + if (!data->valid) { + return 0; + } + + if (!data->is_present) { + return 0; + } + + memcpy(buf, data->eeprom, sizeof(data->eeprom)); + + return sizeof(data->eeprom); +} + +static const struct attribute_group as7716_32x_sfp_group = { + .attrs = as7716_32x_sfp_attributes, +}; + +static int as7716_32x_sfp_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32x_sfp_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7716_32x_sfp_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + i2c_set_clientdata(client, data); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32x_sfp_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sfp '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32x_sfp_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32x_sfp_remove(struct i2c_client *client) +{ + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32x_sfp_group); + kfree(data); + + return 0; +} + +enum port_numbers { +as7716_32x_sfp1, as7716_32x_sfp2, as7716_32x_sfp3, as7716_32x_sfp4, +as7716_32x_sfp5, as7716_32x_sfp6, as7716_32x_sfp7, as7716_32x_sfp8, +as7716_32x_sfp9, as7716_32x_sfp10,as7716_32x_sfp11,as7716_32x_sfp12, +as7716_32x_sfp13,as7716_32x_sfp14,as7716_32x_sfp15,as7716_32x_sfp16, +as7716_32x_sfp17,as7716_32x_sfp18,as7716_32x_sfp19,as7716_32x_sfp20, +as7716_32x_sfp21,as7716_32x_sfp22,as7716_32x_sfp23,as7716_32x_sfp24, +as7716_32x_sfp25,as7716_32x_sfp26,as7716_32x_sfp27,as7716_32x_sfp28, +as7716_32x_sfp29,as7716_32x_sfp30,as7716_32x_sfp31,as7716_32x_sfp32 +}; + +static const struct i2c_device_id as7716_32x_sfp_id[] = { +{ "as7716_32x_sfp1", as7716_32x_sfp1 }, { "as7716_32x_sfp2", as7716_32x_sfp2 }, +{ "as7716_32x_sfp3", as7716_32x_sfp3 }, { "as7716_32x_sfp4", as7716_32x_sfp4 }, +{ "as7716_32x_sfp5", as7716_32x_sfp5 }, { "as7716_32x_sfp6", as7716_32x_sfp6 }, +{ "as7716_32x_sfp7", as7716_32x_sfp7 }, { "as7716_32x_sfp8", as7716_32x_sfp8 }, +{ "as7716_32x_sfp9", as7716_32x_sfp9 }, { "as7716_32x_sfp10", as7716_32x_sfp10 }, +{ "as7716_32x_sfp11", as7716_32x_sfp11 }, { "as7716_32x_sfp12", as7716_32x_sfp12 }, +{ "as7716_32x_sfp13", as7716_32x_sfp13 }, { "as7716_32x_sfp14", as7716_32x_sfp14 }, +{ "as7716_32x_sfp15", as7716_32x_sfp15 }, { "as7716_32x_sfp16", as7716_32x_sfp16 }, +{ "as7716_32x_sfp17", as7716_32x_sfp17 }, { "as7716_32x_sfp18", as7716_32x_sfp18 }, +{ "as7716_32x_sfp19", as7716_32x_sfp19 }, { "as7716_32x_sfp20", as7716_32x_sfp20 }, +{ "as7716_32x_sfp21", as7716_32x_sfp21 }, { "as7716_32x_sfp22", as7716_32x_sfp22 }, +{ "as7716_32x_sfp23", as7716_32x_sfp23 }, { "as7716_32x_sfp24", as7716_32x_sfp24 }, +{ "as7716_32x_sfp25", as7716_32x_sfp25 }, { "as7716_32x_sfp26", as7716_32x_sfp26 }, +{ "as7716_32x_sfp27", as7716_32x_sfp27 }, { "as7716_32x_sfp28", as7716_32x_sfp28 }, +{ "as7716_32x_sfp29", as7716_32x_sfp29 }, { "as7716_32x_sfp30", as7716_32x_sfp30 }, +{ "as7716_32x_sfp31", as7716_32x_sfp31 }, { "as7716_32x_sfp32", as7716_32x_sfp32 }, +{} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32x_sfp_id); + +static struct i2c_driver as7716_32x_sfp_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32x_sfp", + }, + .probe = as7716_32x_sfp_probe, + .remove = as7716_32x_sfp_remove, + .id_table = as7716_32x_sfp_id, + .address_list = normal_i2c, +}; + +static int as7716_32x_sfp_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +static struct as7716_32x_sfp_data *as7716_32x_sfp_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_sfp_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status = -1; + int i = 0; + u8 cpld_reg = 0x30 + (data->port/8); + + data->valid = 0; + + /* Read present status of the specified port number */ + data->is_present = 0; + status = accton_i2c_cpld_read(I2C_ADDR_CPLD1, cpld_reg); + + if (status < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", I2C_ADDR_CPLD1, cpld_reg, status); + goto exit; + } + + data->is_present = (status & (1 << (data->port % 8))) ? 0 : 1; + printk("data->is_present=%d, data->port=%d, status=0x%x\n",data->is_present, data->port, status); + /* Read eeprom data based on port number */ + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Check if the port is present */ + if (data->is_present) { + /* read eeprom */ + for (i = 0; i < sizeof(data->eeprom)/I2C_SMBUS_BLOCK_MAX; i++) { + status = as7716_32x_sfp_read_block(client, i*I2C_SMBUS_BLOCK_MAX, + data->eeprom+(i*I2C_SMBUS_BLOCK_MAX), + I2C_SMBUS_BLOCK_MAX); + if (status < 0) { + printk("unable to read eeprom from port(%d)\n", data->port); + dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n", data->port); + goto exit; + } + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7716_32x_sfp_init(void) +{ + //extern int platform_accton_as7716_32x(void); + //if (!platform_accton_as7716_32x()) { +// return -ENODEV; + //} + + return i2c_add_driver(&as7716_32x_sfp_driver); +} + +static void __exit as7716_32x_sfp_exit(void) +{ + i2c_del_driver(&as7716_32x_sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7716_32x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(as7716_32x_sfp_init); +module_exit(as7716_32x_sfp_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sys.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sys.c new file mode 100755 index 000000000000..f0a8125139cc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_sys.c @@ -0,0 +1,243 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STRING_TO_DEC_VALUE 10 +#define EEPROM_DATA_SIZE 256 + + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +#define MAX_PORT_NAME_LEN 20 +/* Each client has this additional data + */ +struct as7716_32xb_sys_data { + struct device *hwmon_dev; + struct mutex lock; + u8 index; + unsigned char eeprom[EEPROM_DATA_SIZE]; +}; + + +/* sysfs attributes for hwmon + */ + +static ssize_t sys_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t sys_info_show(struct device *dev, struct device_attribute *da, + char *buf); + +static SENSOR_DEVICE_ATTR(eeprom, S_IWUSR|S_IRUGO, sys_info_show, sys_info_store, 0); + + + +static struct attribute *as7716_32xb_sys_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + NULL +}; + + +static ssize_t sys_info_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_sys_data *data = i2c_get_clientdata(client); +// int status = -EINVAL; + int i; + + //printk("sys_info_show\n"); + // printk("attr->index=%d\n", attr->index); + mutex_lock(&data->lock); + //for(i=0; i<8; i++) + // printk("data->eeprom[%d]=0x%x ",i, data->eeprom[i]); + //printk("\n"); + memcpy(buf, data->eeprom, EEPROM_DATA_SIZE); + //for(i=0; i < EEPROM_DATA_SIZE ; i++) + //{ + // buf[i]=data->eeprom[i]; + // printk("buf[%d]=0x%x ",i, buf[i]); + //} + //status = EEPROM_DATA_SIZE+1; + + //printk("\n"); + //status = sprintf(buf, "%x", 0xA); + //data->eeprom[0]=0x0d; + //data->eeprom[1]=0x0; + //data->eeprom[2]=0x06; + // buf[3]=0xFF; + + // for(i=0; i< 16; i++) + // printk("buf[%d]=0x%x ",i, buf[i]); + //printk("\n"); + + memcpy(buf, data->eeprom, 256); + + + mutex_unlock(&data->lock); + + return 256; +} + +static ssize_t sys_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_sys_data *data = i2c_get_clientdata(client); + int i=0, j=0, k=0; + unsigned char str[3]; + unsigned int val; + + //printk("sys_info_store\n"); + //printk("attr->index=%d\n", attr->index); + //printk("buf[0]=0x%x, buf[1]=0x%x, buf[2]=0x%x, buf[3]=0x%x\n", buf[0], buf[1], buf[2], buf[3]); + + // printk("strlen(buf)=%d\n",strlen(buf)); + k=0; + mutex_lock(&data->lock); + memset(data->eeprom, 0xFF, EEPROM_DATA_SIZE); + memset(str, 0x0, 3); + if(strlen(buf) >= 256 ) + { + for(i=0; i < strlen(buf) ; i++) + { + // printk("i=%d ", i); + for(j=0;j<2; j++) + { + str[j]=buf[i+j]; + } + sscanf(str, "%x", &val); + // printk("str=%s val=0x%x ", str, val); + i=j+i-1; + if(k>=EEPROM_DATA_SIZE) + { + break; + } + data->eeprom[k]=(unsigned char)val; + // printk("data->eeprom[%d]=0x%x\n",k, data->eeprom[k]); + k++; + } + } + //printk("buf=\n"); + //for(i=0; i < strlen(buf) ; i++) + //{ + // printk("%c%c ", buf[i], buf[i+1]); + // if((i % 31)==0) + // printk("\n"); + //} + //printk("\n"); + + //printk("eeprom[0]=0x%x, eeprom[1]=0x%x, eeprom[2]=0x%x, eeprom[3]=0x%x\n", + // data->eeprom[0], data->eeprom[1], data->eeprom[2], data->eeprom[3]); + + mutex_unlock(&data->lock); + return size; + +} + +static const struct attribute_group as7716_32xb_sys_group = { + .attrs = as7716_32xb_sys_attributes, +}; + +static int as7716_32xb_sys_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_sys_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_sys_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + i2c_set_clientdata(client, data); + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_sys_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sys '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_sys_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_sys_remove(struct i2c_client *client) +{ + struct as7716_32xb_sys_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_sys_group); + kfree(data); + + return 0; +} + + +static const struct i2c_device_id as7716_32xb_sys_id[] = { + { "as7716_32xb_sys", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_sys_id); + +static struct i2c_driver as7716_32xb_sys_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_sys", + }, + .probe = as7716_32xb_sys_probe, + .remove = as7716_32xb_sys_remove, + .id_table = as7716_32xb_sys_id, + .address_list = normal_i2c, +}; + + + + + + +static int __init as7716_32xb_sys_init(void) +{ + return i2c_add_driver(&as7716_32xb_sys_driver); +} + +static void __exit as7716_32xb_sys_exit(void) +{ + i2c_del_driver(&as7716_32xb_sys_driver); +} + +module_init(as7716_32xb_sys_init); +module_exit(as7716_32xb_sys_exit); + +MODULE_AUTHOR("Jostar yang "); +MODULE_DESCRIPTION("as7716_32xb_sys driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_thermal.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_thermal.c new file mode 100755 index 000000000000..d42341bb181a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_as7716_32xb_thermal.c @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define STRING_TO_DEC_VALUE 10 +#define STRING_TO_HEX_VALUE 16 + +#define TEMP1_MAX_HYST_DEFAULT 75000 +#define TEMP1_MAX_DEFAULT 80000 +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7716_32xb_thermal_data { + struct device *hwmon_dev; + struct mutex update_lock; + u8 index; + unsigned int temp1_input; + unsigned int temp1_max_hyst; + unsigned int temp1_max; +}; + + + +enum as7716_32xb_thermal_sysfs_attributes { + TEMP1_INPUT, + TEMP1_MAX_HYST, + TEMP1_MAX +}; + +/* sysfs attributes for hwmon + */ + +static ssize_t temp_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t temp_info_show(struct device *dev, struct device_attribute *da, + char *buf); +static SENSOR_DEVICE_ATTR(temp1_input, S_IWUSR|S_IRUGO, temp_info_show, temp_info_store, TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO, temp_info_show, temp_info_store, TEMP1_MAX_HYST); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR|S_IRUGO, temp_info_show, temp_info_store, TEMP1_MAX); + + +static struct attribute *as7716_32xb_thermal_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + NULL +}; + + +static ssize_t temp_info_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_thermal_data *data = i2c_get_clientdata(client); + int status = -EINVAL; + + mutex_lock(&data->update_lock); + switch (attr->index) + { + case TEMP1_INPUT: + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", data->temp1_input); + break; + case TEMP1_MAX_HYST: + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", TEMP1_MAX_HYST_DEFAULT); + break; + case TEMP1_MAX: + status = snprintf(buf, PAGE_SIZE - 1, "%d\r\n", TEMP1_MAX_DEFAULT); + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t temp_info_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t size) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32xb_thermal_data *data = i2c_get_clientdata(client); + long keyin = 0; + int status = -EINVAL; + + mutex_lock(&data->update_lock); + status = kstrtol(buf, STRING_TO_DEC_VALUE, &keyin); + switch (attr->index) + { + case TEMP1_INPUT: + data->temp1_input=keyin; + break; + case TEMP1_MAX_HYST: + data->temp1_max_hyst=keyin; + break; + case TEMP1_MAX: + data->temp1_max=keyin; + break; + default : + break; + } + mutex_unlock(&data->update_lock); + return size; + +} + +static const struct attribute_group as7716_32xb_thermal_group = { + .attrs = as7716_32xb_thermal_attributes, +}; + +static int as7716_32xb_thermal_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7716_32xb_thermal_data *data; + int status; + + data = kzalloc(sizeof(struct as7716_32xb_thermal_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + i2c_set_clientdata(client, data); + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7716_32xb_thermal_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: thermal '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_thermal_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7716_32xb_thermal_remove(struct i2c_client *client) +{ + struct as7716_32xb_thermal_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7716_32xb_thermal_group); + kfree(data); + + return 0; +} + + +static const struct i2c_device_id as7716_32xb_thermal_id[] = { + { "as7716_32xb_thermal", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7716_32xb_thermal_id); + +static struct i2c_driver as7716_32xb_thermal_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7716_32xb_thermal", + }, + .probe = as7716_32xb_thermal_probe, + .remove = as7716_32xb_thermal_remove, + .id_table = as7716_32xb_thermal_id, + .address_list = normal_i2c, +}; + + + + + + +static int __init as7716_32xb_thermal_init(void) +{ + return i2c_add_driver(&as7716_32xb_thermal_driver); +} + +static void __exit as7716_32xb_thermal_exit(void) +{ + i2c_del_driver(&as7716_32xb_thermal_driver); +} + +module_init(as7716_32xb_thermal_init); +module_exit(as7716_32xb_thermal_exit); + +MODULE_AUTHOR("Jostar yang "); +MODULE_DESCRIPTION("as7716_32xb_thermal driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_i2c_cpld.c new file mode 100755 index 000000000000..46d1e2773287 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/modules/accton_i2c_cpld.c @@ -0,0 +1,259 @@ +/* + * A hwmon driver for the accton_i2c_cpld + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPLD_VERSION_REG 0x1 + +enum as5712_54x_cpld_sysfs_attributes { + CPLD_READ_VERSION, + CPLD_BYTE_ACCESS, + CPLD_DUMP_ALL, +}; + +static ssize_t read_cpld_version(struct device *dev, struct device_attribute *da, + char *buf); +int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); + + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for accton_i2c_cpld + */ +static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, I2C_CLIENT_END }; + +static SENSOR_DEVICE_ATTR(cpld_get_version, S_IRUGO, read_cpld_version, NULL, CPLD_READ_VERSION); + +static struct attribute *as5712_54x_cpld_attributes[] = { + &sensor_dev_attr_cpld_get_version.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5712_54x_cpld_group = { + .attrs = as5712_54x_cpld_attributes, +}; + +static ssize_t read_cpld_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + unsigned short cpld_reg = CPLD_VERSION_REG; + u8 reg; + + if(attr->index == CPLD_READ_VERSION) { + reg = accton_i2c_cpld_read(client->addr, cpld_reg); + return sprintf(buf, "%02x\n",reg); + } + return -1 ; +} + + +static void accton_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void accton_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int accton_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as5712_54x_cpld_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + accton_i2c_cpld_add_client(client); + + return 0; +exit: + return status; +} + +static int accton_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &as5712_54x_cpld_group); + + accton_i2c_cpld_remove_client(client); + return 0; +} + +static const struct i2c_device_id accton_i2c_cpld_id[] = { + { "accton_i2c_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); + +static struct i2c_driver accton_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_cpld", + }, + .probe = accton_i2c_cpld_probe, + .remove = accton_i2c_cpld_remove, + .id_table = accton_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_read); + +int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_write); + +static int __init accton_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&accton_i2c_cpld_driver); +} + +static void __exit accton_i2c_cpld_exit(void) +{ + i2c_del_driver(&accton_i2c_cpld_driver); +} +/* +static struct dmi_system_id as7712_dmi_table[] = { + { + .ident = "Accton AS7712", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"), + }, + } +}; + +int platform_accton_as7712_32x(void) +{ + return dmi_check_system(as7712_dmi_table); +} +EXPORT_SYMBOL(platform_accton_as7712_32x); +*/ +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_cpld_init); +module_exit(accton_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/service/as7716_32xb-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/service/as7716_32xb-platform-monitor.service new file mode 100755 index 000000000000..05a5d93c48b9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/service/as7716_32xb-platform-monitor.service @@ -0,0 +1,17 @@ +[Unit] +Description=Accton AS7716-32XB Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7716_32xb_util.py install +ExecStart=/usr/local/bin/accton_as7716_32xb_drv_handler.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/setup.py new file mode 100755 index 000000000000..3edfc29b3817 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7716_32xb', + version='1.0', + description='Module to initialize Accton AS7716-32XB platforms', + + packages=['as7716_32xb'], + package_dir={'as7716_32xb': 'as7716-32xb/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/README new file mode 100755 index 000000000000..c602d753301e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-4-amd64_3.16.36-1+deb8u2_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-4-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_drv_handler.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_drv_handler.py new file mode 100755 index 000000000000..ed5af4818de3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_drv_handler.py @@ -0,0 +1,437 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 1/18/2018: Jostar create for as7716_32xb +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import time # this is only being used as part of the example + import commands +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'as7716_32xb_drv_handler' +DEBUG = False + +global log_file +global log_level + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + if DEBUG == True: + my_log (cmd +" , result:" + str(status)) + else: + if show: + print "ACC: " + str(cmd) + " , result:"+ str(status) + #my_log ("cmd:" + cmd) + #my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7716xb_drv_handler(object): + + QSFP_PORT_START = 1 + QSFP_PORT_END = 32 + BASE_PATH = "/usr/local/bin/" + BASE_I2C_PATH="/sys/bus/i2c/devices/" + QSFP_PRESENT_PATH = "/sys/bus/i2c/devices/0-0060/module_present_" + QSFP_RESET_PATH = "/sys/bus/i2c/devices/0-0060/module_reset_" + QSFP_PRESENT_FILE = "/tmp/ipmi_qsfp_pres" + QSFP_EEPROM_FILE = "/tmp/ipmi_qsfp_ee_" + THERMAL_FILE = "/tmp/ipmi_thermal" + IPMI_CMD_QSFP = "ipmitool raw 0x34 0x10 " + IPMI_CMD_THERMAL = "ipmitool raw 0x34 0x12 " + IPMI_CMD_FAN = "ipmitool raw 0x34 0x14 " + IPMI_CMD_PSU ="ipmitool raw 0x34 0x16 " + IPMI_CMD_SYS_EEPROM_1 ="ipmitool raw 0x34 0x18 0x0 0x80" + IPMI_CMD_SYS_EEPROM_2 ="ipmitool raw 0x34 0x18 0x80 0x80" + FAN_ID_START = 1 + FAN_ID_END = 6 + FAN_FILE = "/tmp/ipmi_fan" + FAN_PATH = "/sys/bus/i2c/devices/0-0066/fan" + PSU_ID_START = 1 + PSU_ID_END = 2 + PSU1_PATH = "/sys/bus/i2c/devices/0-0053/" + PSU2_PATH = "/sys/bus/i2c/devices/0-0050/" + PSU1_PMBUS_PATH = "/sys/bus/i2c/devices/0-005b/" + PSU2_PMBUS_PATH = "/sys/bus/i2c/devices/0-0058/" + PSU_FILE = "/tmp/ipmi_psu_" + SYS_EEPROM_FILE_1 = "/tmp/ipmi_sys_eeprom_1" + SYS_EEPROM_FILE_2 = "/tmp/ipmi_sys_eeprom_2" + SYS_EEPROM_PATH = "/sys/bus/i2c/devices/0-0056/eeprom" + + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_ipmi_qsfp(self): + logging.debug ("drv hanlder-manage_ipmi_qsfp") + print "drv hanlder" + #Handle QSFP case + ipmi_cmd = self.IPMI_CMD_QSFP + " 0x10 > " +self.QSFP_PRESENT_FILE + log_os_system(ipmi_cmd, 0) + file_path = self.QSFP_PRESENT_FILE + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + pres_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + pres_line+=line.rstrip().replace(" ","") + check_file.close() + + + for i in range(self.QSFP_PORT_START, self.QSFP_PORT_END+1, 1): + if i>1: + k=(i-1)*2 +1 + else: + k=1; + if pres_line[k] == '1': + #Set QSFP present + #print "port-%d present" %i + set_drv_cmd = "echo 1 > " + self.QSFP_PRESENT_PATH + str(i) + log_os_system(set_drv_cmd, 0) + #Read QSFP EEPROM + ipmi_cmd = self.IPMI_CMD_QSFP +str(i)+ " 0x00 > " +self.QSFP_EEPROM_FILE + str(i) + "_1" + log_os_system(ipmi_cmd, 0) + ipmi_cmd = self.IPMI_CMD_QSFP +str(i)+ " 0x01 > " +self.QSFP_EEPROM_FILE + str(i) + "_2" + log_os_system(ipmi_cmd, 0) + file_path = self.QSFP_EEPROM_FILE + str(i) + "_1" + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + file_path = self.QSFP_EEPROM_FILE + str(i) + "_2" + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line+= line.rstrip().replace(" ","") + + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + #Set QSFP EEPROM + if(i < 10): + set_drv_cmd = "echo " + str_line+ " > " + self.BASE_I2C_PATH + "0-000"+str(i) +"/eeprom" + else: + set_drv_cmd = "echo " + str_line+ " > " + self.BASE_I2C_PATH + "0-00"+str(i) +"/eeprom" + #print(set_drv_cmd) + log_os_system(set_drv_cmd, 0) + else: + ipmi_cmd = "echo 0 > " + self.QSFP_PRESENT_PATH + str(i) + log_os_system(ipmi_cmd, 0) + if(i < 10): + set_drv_cmd = "echo 0 > " + self.BASE_I2C_PATH + "0-000"+str(i) +"/eeprom" + else: + set_drv_cmd = "echo 0 > " + self.BASE_I2C_PATH + "0-00"+str(i) +"/eeprom" + #print(set_drv_cmd) + log_os_system(set_drv_cmd, 0) + + time.sleep(0.01) + return True + + def manage_ipmi_thermal(self): + logging.debug ("drv hanlder-manage_ipmi_thermal") + #Handle thermal case + #ipmitool raw 0x34 0x12 + ipmi_cmd = self.IPMI_CMD_THERMAL + " > " +self.THERMAL_FILE + log_os_system(ipmi_cmd, 0) + file_path = self.THERMAL_FILE + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + val_str= "0x" + str(str_line[4])+str(str_line[5]) + val_int=int(val_str, 16)*1000 + check_file.close() + set_drv_cmd = "echo "+str(val_int) + " > " + self.BASE_I2C_PATH + "0-0048/temp1_input" + log_os_system(set_drv_cmd,0) + val_str= "0x" + str(str_line[10])+str(str_line[11]) + val_int=int(val_str, 16) * 1000 + set_drv_cmd = "echo "+str(val_int) + " > " + self.BASE_I2C_PATH + "0-0049/temp1_input" + log_os_system(set_drv_cmd,0) + val_str= "0x" + str(str_line[16])+str(str_line[17]) + val_int=int(val_str, 16) * 1000 + set_drv_cmd = "echo "+str(val_int) + " > " + self.BASE_I2C_PATH + "0-004a/temp1_input" + log_os_system(set_drv_cmd, 0) + + return True + + def manage_ipmi_fan(self): + logging.debug ("drv hanlder-manage_ipmi_fan") + #Handle fan case + #ipmitool raw 0x34 0x14 + ipmi_cmd = self.IPMI_CMD_FAN + " > " +self.FAN_FILE + log_os_system(ipmi_cmd, 0) + file_path = self.FAN_FILE + #print(file_path) + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + #print (str_line) + k=0 + for i in range(self.FAN_ID_START, self.FAN_ID_END+1, 1): + #print "k=%d"%k + if str_line[k+1]=='0': + set_drv_cmd = "echo 1 > " + self.FAN_PATH + str(i) + "_present" + else: + set_drv_cmd = "echo 0 > " + self.FAN_PATH + str(i) + "_present" + log_os_system(set_drv_cmd, 0) + + val_str= "0x" + str(str_line[k+6])+str(str_line[k+7]) + str(str_line[k+4])+str(str_line[k+5]) + val_int=int(val_str, 16) + set_drv_cmd = "echo " + str(val_int) + " > " + self.FAN_PATH + str(i) + "_front_speed_rpm" + log_os_system(set_drv_cmd, 0) + val_str= "0x" + str(str_line[k+54])+str(str_line[k+55]) + str(str_line[k+52])+str(str_line[k+53]) + val_int=int(val_str, 16) + set_drv_cmd = "echo " + str(val_int) + " > " + self.FAN_PATH + str(i) + "_rear_speed_rpm" + log_os_system(set_drv_cmd, 0) + k+=8; + return True + + + def manage_ipmi_psu(self): + logging.debug ("drv hanlder-manage_ipmi_psu") + #Handle psu case + #present: ipmitool raw 0x34 0x16 '0x1' . Param-1 is psu id(id_1:0x1, id_2:0x2) + + #cpld access psu + for i in range(self.PSU_ID_START, self.PSU_ID_END+1, 1): + #present case + ipmi_cmd = self.IPMI_CMD_PSU + str(i) + " > " +self.PSU_FILE + str(i) + log_os_system(ipmi_cmd, 0) + if i==1: + psu_sysfs_path = self.PSU1_PATH + else: + psu_sysfs_path = self.PSU2_PATH + file_path = self.PSU_FILE + str(i) + #print(file_path) + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + #print (line) + if str_line[1]=='0': + int_val=1 #psu insert + #print "psu_%d present"%i + set_drv_cmd = "echo " +str(int_val) + " > " + psu_sysfs_path + "psu_present" + log_os_system(set_drv_cmd, 0) + set_drv_cmd = "echo " + str(str_line[5]) + " > " + psu_sysfs_path + "psu_power_good" + log_os_system(set_drv_cmd, 0) + else: + int_val=0 + set_drv_cmd = "echo " +str(int_val) + " > " + psu_sysfs_path + "psu_present" + log_os_system(set_drv_cmd, 0) + set_drv_cmd = "echo " + str(int_val) + " > " + psu_sysfs_path + "psu_power_good" + log_os_system(set_drv_cmd, 0) + + #pmbus + if i==1: + psu_sysfs_path = self.PSU1_PMBUS_PATH + else: + psu_sysfs_path = self.PSU2_PMBUS_PATH + + if str_line[5]=='1': #power_on + val_str= "0x" + str(str_line[28])+str(str_line[29]) + str(str_line[26])+str(str_line[27]) + val_int=int(val_str, 16) * 1000 + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_temp1_input" + log_os_system(set_drv_cmd, 0) + #print "val_int=%d"%val_int + val_str= "0x" + str(str_line[32])+str(str_line[33]) + str(str_line[30])+str(str_line[31]) + val_int=int(val_str, 16) + #print "fan:val_int=%d"%val_int + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_fan1_speed_rpm" + log_os_system(set_drv_cmd, 0) + val_str= "0x" + str(str_line[36])+str(str_line[37]) + str(str_line[34])+str(str_line[35]) + val_int=int(val_str, 16) + #print "pout val_int=%d"%val_int + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_p_out" + log_os_system(set_drv_cmd, 0) + else: #power_off + val_int=0 + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_temp1_input" + log_os_system(set_drv_cmd, 0) + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_fan1_speed_rpm" + log_os_system(set_drv_cmd, 0) + set_drv_cmd = "echo " + str(val_int) + " > " + psu_sysfs_path + "psu_p_out" + log_os_system(set_drv_cmd, 0) + + time.sleep(2) + return True + + def manage_ipmi_sys(self): + logging.debug ("drv hanlder-manage_ipmi_sys") + #Handle sys case + #ipmitool -raw 0x34 0x18 0x00 0x80 + #ipmitool -raw 0x34 0x18 0x80 0x80 + + ipmi_cmd = self.IPMI_CMD_SYS_EEPROM_1 + " > " + self.SYS_EEPROM_FILE_1 + log_os_system(ipmi_cmd, 0) + ipmi_cmd = self.IPMI_CMD_SYS_EEPROM_2 + " > " + self.SYS_EEPROM_FILE_2 + log_os_system(ipmi_cmd, 0) + + #Read SYS EEPROM + file_path = self.SYS_EEPROM_FILE_1 + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + + file_path = self.SYS_EEPROM_FILE_2 + check_file = open(file_path) + try: + check_file = open(file_path) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + line = check_file.readline() + str_line+= line.rstrip().replace(" ","") + while line: + line = check_file.readline() + str_line+=line.rstrip().replace(" ","") + check_file.close() + #print(len(str_line)) + #print(str_line) + set_drv_cmd = "echo " + str_line+ " > " + self.SYS_EEPROM_PATH + #print(set_drv_cmd) + log_os_system(set_drv_cmd, 0) + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.WARNING + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + set_drv_cmd = "echo 100 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us" + log_os_system(set_drv_cmd, 0) + monitor = accton_as7716xb_drv_handler(log_file, log_level) + + set_sys_eeprom=0 + thermal_chk_time=0 + psu_chk_time=0 + # Loop forever, doing something useful hopefully: + while True: + logging.debug ("monitor.manage_ipmi") + if set_sys_eeprom==0: + monitor.manage_ipmi_sys() + set_sys_eeprom=1 + monitor.manage_ipmi_qsfp() + time.sleep(0.1) + monitor.manage_ipmi_thermal() + monitor.manage_ipmi_psu() + time.sleep(0.1) + monitor.manage_ipmi_fan() + time.sleep(0.05) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_monitor.py new file mode 100755 index 000000000000..86b4f1852066 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_monitor.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import time # this is only being used as part of the example + from as7716_32x.fanutil import FanUtil + from as7716_32x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7716_monitor' + +global log_file +global log_level + + # For AC power Front to Back : + # If any fan fail, please fan speed register to 15 + # The max value of Fan speed register is 9 + # [LM75(48) + LM75(49) + LM75(4A)] > 174 => set Fan speed value from 4 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] > 182 => set Fan speed value from 5 to 7 + # [LM75(48) + LM75(49) + LM75(4A)] > 190 => set Fan speed value from 7 to 9 + # + # [LM75(48) + LM75(49) + LM75(4A)] < 170 => set Fan speed value from 5 to 4 + # [LM75(48) + LM75(49) + LM75(4A)] < 178 => set Fan speed value from 7 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] < 186 => set Fan speed value from 9 to 7 + # + # + # For AC power Back to Front : + # If any fan fail, please fan speed register to 15 + # The max value of Fan speed register is 10 + # [LM75(48) + LM75(49) + LM75(4A)] > 140 => set Fan speed value from 4 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] > 150 => set Fan speed value from 5 to 7 + # [LM75(48) + LM75(49) + LM75(4A)] > 160 => set Fan speed value from 7 to 10 + # + # [LM75(48) + LM75(49) + LM75(4A)] < 135 => set Fan speed value from 5 to 4 + # [LM75(48) + LM75(49) + LM75(4A)] < 145 => set Fan speed value from 7 to 5 + # [LM75(48) + LM75(49) + LM75(4A)] < 155 => set Fan speed value from 10 to 7 + # + + + # 2.If no matched fan speed is found from the policy, + # use FAN_DUTY_CYCLE_MIN as default speed + # Get current temperature + # 4.Decision 3: Decide new fan speed depend on fan direction/current fan speed/temperature + + + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7716_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + + fan_policy_f2b = { + 0: [32, 0, 174000], + 1: [38, 170000, 182000], + 2: [50, 178000, 190000], + 3: [63, 186000, 0], + } + fan_policy_b2f = { + 0: [32, 0, 140000], + 1: [38, 135000, 150000], + 2: [50, 145000, 160000], + 3: [69, 15500, 0], + } + + thermal = ThermalUtil() + fan = FanUtil() + get_temp = thermal.get_thermal_temp() + # 1. Get each fan status, one not presented, set speed to full + # Get fan direction (Only get the first one since all fan direction are the same) + # Get current fan duty cycle + cur_duty_cycle = fan.get_fan_duty_cycle() + #print "cur_duty_cycle=%d" %cur_duty_cycle + #print "get_temp=%d" %get_temp + + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + #print "fan_status is None" + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', 100, x) + return False + if fan_status is False: + #self._new_perc = FAN_LEV1_SPEED_PERC + #print "fan_%d status=false, set 45 duty_cycle" %x + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', 100, x) + fan.set_fan_duty_cycle(45) + return True + logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + if fan_status is not None and fan_status is not False: + fan_dir=fan.get_fan_dir(1) + for x in range(0, 4): + if cur_duty_cycle == fan_policy_f2b[x][0]: + break + #print "x=%d" %x + #print "fan_dir=%d" %fan_dir + #print "fan_policy_f2b[x][0]=%d" %fan_policy_f2b[x][0] + #print "cur_duty_cycle=%d" %cur_duty_cycle + + if fan_dir == 1: + if x == 4 : + fan.set_fan_duty_cycle(fan_policy_f2b[0][0]) + new_duty_cycle=cur_duty_cycle + # if temp > up_levle, else if temp < down_level + if get_temp > fan_policy_f2b[x][2] and x != 3 : + new_duty_cycle= fan_policy_f2b[x+1][0] + #print "new_duty_cycle= fan_policy_f2b[x+1][0]=%d" %new_duty_cycle + #print "Becasue get_temp > fan_policy_f2b[x][2]=%d" %fan_policy_f2b[x][2] + logging.debug('INFO. THERMAL temp UP, temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy_f2b[x][2], new_duty_cycle) + #else get_temp < fan_policy_f2b[x][1] and x != 0 : + elif get_temp < fan_policy_f2b[x][1] : + new_duty_cycle= fan_policy_f2b[x-1][0] + #print "new_duty_cycle= fan_policy_f2b[x-1][0]=%d" %new_duty_cycle + #print "Becasue get_temp < fan_policy_f2b[x][1]=%d" %fan_policy_f2b[x][1] + logging.debug('INFO. THERMAL temp down, temp %d < %d , new_duty_cycle=%d', get_temp, fan_policy_f2b[x][1], new_duty_cycle) + if new_duty_cycle == cur_duty_cycle : + #print "new_duty_cycle == cur_duty_cycle case, so return True" + return True + else: + if x == 4 : + fan.set_fan_duty_cycle(fan_policy_b2f[0][0]) + new_duty_cycle=cur_duty_cycle + # if temp > up_levle, else if temp < down_level + if get_temp > fan_policy_b2f[x][1] and x != 3 : + new_duty_cycle= fan_policy_b2f[x+1][0] + logging.debug('INFO. THERMAL temp UP, temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy_b2f[x][2], new_duty_cycle) + elif get_temp < fan_policy_b2f[x][0] and x != 0 : + #elif get_temp < fan_policy_b2f[x][0] + new_duty_cycle= fan_policy_b2f[x-1][0] + logging.debug('INFO. THERMAL temp down, temp %d < %d , new_duty_cycle=%d', get_temp, fan_policy_b2f[x][1], new_duty_cycle) + if new_duty_cycle == cur_duty_cycle : + return True + + fan.set_fan_duty_cycle(new_duty_cycle) + #print "set new_duty_cycle=%d" %new_duty_cycle + #print "old_duty_cycle=%d" %cur_duty_cycle + + return True + + + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + monitor = accton_as7716_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(1) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_util.py b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_util.py new file mode 100755 index 000000000000..3a31d253f633 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7716-32xb/utils/accton_as7716_32xb_util.py @@ -0,0 +1,615 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re + +PROJECT_NAME = 'as7716_32xb' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':54} + + +led_prefix ='/sys/devices/platform/as7716_32xb_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as7716_32xb_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_drv_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['10-0048','10-0049', '10-004a'] , + 'psu': ['17-0050','18-0053'], + 'sfp': ['-0050']} +i2c_nodes = { + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +sfp_map = [1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32] + +mknod =[ +'echo as7716_32xb_cpld1 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo accton_i2c_cpld 0x62 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo accton_i2c_cpld 0x64 > /sys/bus/i2c/devices/i2c-0/new_device', + +] + +mknod_xb =[ +'echo as7716_32xb_cpld1 0x60 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo accton_i2c_cpld 0x62 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo accton_i2c_cpld 0x64 > /sys/bus/i2c/devices/i2c-0/new_device', +#Thermal +'echo as7716_32xb_thermal 0x48 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as7716_32xb_thermal 0x49 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as7716_32xb_thermal 0x4a > /sys/bus/i2c/devices/i2c-0/new_device', +#Fan +'echo as7716_32xb_fan 0x66 > /sys/bus/i2c/devices/i2c-0/new_device', +# PSU-1 +'echo as7716_32xb_psu1 0x53 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as7716_32xb_psu2 0x50> /sys/bus/i2c/devices/i2c-0/new_device', +# PSU-2 +'echo as7716_32xb_pmbus 0x5b > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as7716_32xb_pmbus 0x58 > /sys/bus/i2c/devices/i2c-0/new_device', +#EERPOM +'echo as7716_32xb_sys 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +] + + + +mknod2 =[ +'echo as7716_32xb_cpld1 0x60 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo accton_i2c_cpld 0x61 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo accton_i2c_cpld 0x62 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', + +# PSU-1 +'echo as7716_32xb_psu1 0x38 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo cpr_4011_4mxx 0x3c > /sys/bus/i2c/devices/i2c-57/new_device', +'echo as7716_32xb_psu1 0x50 > /sys/bus/i2c/devices/i2c-57/new_device', +'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-57/new_device', + +# PSU-2 +'echo as7716_32xb_psu2 0x3b > /sys/bus/i2c/devices/i2c-58/new_device', +'echo cpr_4011_4mxx 0x3f > /sys/bus/i2c/devices/i2c-58/new_device', +'echo as7716_32xb_psu2 0x53 > /sys/bus/i2c/devices/i2c-58/new_device', +'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-58/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-61/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-62/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-63/new_device', + +#EERPOM +#'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + +kos = [ +'depmod -ae', +'modprobe ipmi_msghandler', +'modprobe ipmi_si', +'modprobe ipmi_devintf', +'modprobe i2c_dev', +'modprobe accton_i2c_cpld', +'modprobe accton_as7716_32xb_cpld1', +'modprobe accton_as7716_32xb_fan', +'modprobe accton_as7716_32xb_leds', +'modprobe accton_as7716_32xb_psu', +'modprobe accton_as7716_32xb_oom', +'modprobe accton_as7716_32xb_thermal', +'modprobe accton_as7716_32xb_pmbus', +'modprobe accton_as7716_32xb_sys'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + else: + order = 0 + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-1/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + #order = i2c_order_check() + # if 0x76 is not exist @i2c-0, use reversed bus order + #if order: + # for i in range(0,len(mknod2)): + # #for pca932x need times to built new i2c buses + # if mknod2[i].find('pca954') != -1: + # time.sleep(2) + + # status, output = log_os_system(mknod2[i], 1) + # if status: + # print output + # if FORCE == 0: + # return status + #else: + print "Prepar to create instance.............." + for i in range(0,len(mknod_xb)): + print "Beginn to create instance.............." + status, output = log_os_system(mknod_xb[i], 1) + print "status=%s" %status + print "output=%s" %output + if status: + print output + if FORCE == 0: + return status + #time.sleep (50.0 / 1000.0) + print "Create sfp instance.............." + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo as7716_32xb_oom 0x"+str(sfp_map[i])+ " > /sys/bus/i2c/devices/i2c-0/new_device", 1) + if status: + print output + if FORCE == 0: + return status + #status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/0-000"+str(sfp_map[i])+"/port_name", 1) + #if status: + # print output + # if FORCE == 0: + # return status + return + +def device_uninstall(): + global FORCE + + for i in range(0,len(sfp_map)): + target = "echo 0x"+str(sfp_map[i])+ " > /sys/bus/i2c/devices/i2c-0/delete_device" + print(target) + status, output =log_os_system(target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod_xb + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + print "driver_inserted() == False" + return False + if not device_exist(): + print "not device_exist()" + return False + return True + +def do_install(): + print "Checking system...." + if driver_inserted() == False: + print "No driver, installing.1..." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing..2.." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking systemm...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + print "path= %s" %path + print "i=%d" %i + print "k=%d" %k + print "j= %d" %j + print "sfp_map[k]=%s" %sfp_map[k] + print " buses[i]=%s" %buses[i] + print "nodes[j]=%s" %nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0060", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-0", 0) + print(ret1) + print(ret2) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/fanutil.py new file mode 100755 index 000000000000..ca0f3f9da1e3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/fanutil.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 12/03/2018: Jostar modify for as7726_32 +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/54-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/54-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + #val = ((val + 1 ) * 625 +75 ) / 100 + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/thermalutil.py new file mode 100755 index 000000000000..35ccf7efdd1e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/classes/thermalutil.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 12/03/2018:Jostar modify for as7726_32x thermal plan +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_MAX = 5 + THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD. LM75 + THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75 + THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75 + THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75 + THERMAL_NUM_5_IDX = 5 # 5_ON_MAIN_BROAD. LM75 + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + #_thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = { + THERMAL_NUM_1_IDX: ['55', '48'], + THERMAL_NUM_2_IDX: ['55', '49'], + THERMAL_NUM_3_IDX: ['55', '4a'], + THERMAL_NUM_4_IDX: ['55', '4b'], + THERMAL_NUM_5_IDX: ['54', '4c'], + } + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/55-0048/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/55-0049/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/55-004a/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/55-004b/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_5_IDX: ["/sys/bus/i2c/devices/54-004c/hwmon/hwmon*/temp1_input"], + } + + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + return int(content) + + return 0 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_to_device_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + def get_thermal_1_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + def get_thermal_temp(self): + return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX)) + +def main(): + thermal = ThermalUtil() + logging.debug('thermal1=%d', thermal._get_thermal_val(1)) + logging.debug('thermal2=%d', thermal._get_thermal_val(2)) + logging.debug('thermal3=%d', thermal._get_thermal_val(3)) + logging.debug('thermal4=%d', thermal._get_thermal_val(4)) + logging.debug('thermal5=%d', thermal._get_thermal_val(5)) +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/Makefile new file mode 100755 index 000000000000..5b5e6912c56a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/Makefile @@ -0,0 +1,19 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as7726_32x_cpld.o accton_as7726_32x_fan.o \ + accton_as7726_32x_leds.o accton_as7726_32x_psu.o ym2651y.o + +else +ifeq (,$(KERNEL_SRC)) +#$(error KERNEL_SRC is not defined) +KVERSION=3.16.0-6-amd64 +KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ +KERNELDIR:=$(KERNEL_DIR) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_cpld.c new file mode 100755 index 000000000000..9ffc3353839c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_cpld.c @@ -0,0 +1,919 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as7726_32x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as7726_32x_cpld1, + as7726_32x_cpld2, + as7726_32x_cpld3 +}; + +struct as7726_32x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as7726_32x_cpld_id[] = { + { "as7726_32x_cpld1", as7726_32x_cpld1 }, + { "as7726_32x_cpld2", as7726_32x_cpld2 }, + { "as7726_32x_cpld3", as7726_32x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as7726_32x_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index +//#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index + +enum as7726_32x_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32) +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as7726_32x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as7726_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + + +#define DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO|S_IWUSR, show_status, set_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); + + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_RESET_SENSOR_DEVICE_ATTR(32); + +static struct attribute *as7726_32x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_TRANSCEIVER_RESET_ATTR(1), + DECLARE_TRANSCEIVER_RESET_ATTR(2), + DECLARE_TRANSCEIVER_RESET_ATTR(3), + DECLARE_TRANSCEIVER_RESET_ATTR(4), + DECLARE_TRANSCEIVER_RESET_ATTR(5), + DECLARE_TRANSCEIVER_RESET_ATTR(6), + DECLARE_TRANSCEIVER_RESET_ATTR(7), + DECLARE_TRANSCEIVER_RESET_ATTR(8), + DECLARE_TRANSCEIVER_RESET_ATTR(9), + DECLARE_TRANSCEIVER_RESET_ATTR(10), + DECLARE_TRANSCEIVER_RESET_ATTR(11), + DECLARE_TRANSCEIVER_RESET_ATTR(12), + DECLARE_TRANSCEIVER_RESET_ATTR(13), + DECLARE_TRANSCEIVER_RESET_ATTR(14), + DECLARE_TRANSCEIVER_RESET_ATTR(15), + DECLARE_TRANSCEIVER_RESET_ATTR(16), + DECLARE_TRANSCEIVER_RESET_ATTR(17), + DECLARE_TRANSCEIVER_RESET_ATTR(18), + DECLARE_TRANSCEIVER_RESET_ATTR(19), + DECLARE_TRANSCEIVER_RESET_ATTR(20), + DECLARE_TRANSCEIVER_RESET_ATTR(21), + DECLARE_TRANSCEIVER_RESET_ATTR(22), + DECLARE_TRANSCEIVER_RESET_ATTR(23), + DECLARE_TRANSCEIVER_RESET_ATTR(24), + DECLARE_TRANSCEIVER_RESET_ATTR(25), + DECLARE_TRANSCEIVER_RESET_ATTR(26), + DECLARE_TRANSCEIVER_RESET_ATTR(27), + DECLARE_TRANSCEIVER_RESET_ATTR(28), + DECLARE_TRANSCEIVER_RESET_ATTR(29), + DECLARE_TRANSCEIVER_RESET_ATTR(30), + DECLARE_TRANSCEIVER_RESET_ATTR(31), + DECLARE_TRANSCEIVER_RESET_ATTR(32), + NULL +}; + +static const struct attribute_group as7726_32x_cpld1_group = { + .attrs = as7726_32x_cpld1_attributes, +}; + +static struct attribute *as7726_32x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7726_32x_cpld2_group = { + .attrs = as7726_32x_cpld2_attributes, +}; + +static struct attribute *as7726_32x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7726_32x_cpld3_group = { + .attrs = as7726_32x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[5] = {0}; + u8 regs[] = {0x30, 0x31, 0x32, 0x33, 0x50}; + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7726_32x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + values[4] &= 0x3; + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3], values[4]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + u8 value=0; + u8 reg = 0x50; + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + status = as7726_32x_cpld_read_internal(client, reg); + + if (status < 0) + goto exit; + + value = (u8)status; + value &= 0x0C; + value = value >> 2; + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 34 in order */ + return sprintf(buf, "00 00 00 00 %.2x\n", value); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x30; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x31; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x32; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x33; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33: + reg = 0x50; + mask = 0x1; + break; + case MODULE_PRESENT_34: + reg = 0x50; + mask = 0x2; + break; + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x4; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x5; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + case MODULE_RXLOS_33: + reg = 0x50; + mask = 0x4; + break; + case MODULE_RXLOS_34: + reg = 0x50; + mask = 0x8; + break; + case MODULE_TXDISABLE_33: + reg = 0x49; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x49; + mask = 0x2; + break; + + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_34) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as7726_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_33: + reg = 0x49; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x49; + mask = 0x2; + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7726_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7726_32x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + switch (attr->index) + { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x4; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x5; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7726_32x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (!reset) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as7726_32x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as7726_32x_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as7726_32x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7726_32x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as7726_32x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as7726_32x_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as7726_32x_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as7726_32x_cpld1: + group = &as7726_32x_cpld1_group; + break; + case as7726_32x_cpld2: + group = &as7726_32x_cpld2_group; + break; + case as7726_32x_cpld3: + group = &as7726_32x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as7726_32x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as7726_32x_cpld_remove(struct i2c_client *client) +{ + struct as7726_32x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as7726_32x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as7726_32x_cpld1: + group = &as7726_32x_cpld1_group; + break; + case as7726_32x_cpld2: + group = &as7726_32x_cpld2_group; + break; + case as7726_32x_cpld3: + group = &as7726_32x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as7726_32x_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as7726_32x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as7726_32x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7726_32x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7726_32x_cpld_read); + +int as7726_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as7726_32x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7726_32x_cpld_write); + +static struct i2c_driver as7726_32x_cpld_driver = { + .driver = { + .name = "as7726_32x_cpld", + .owner = THIS_MODULE, + }, + .probe = as7726_32x_cpld_probe, + .remove = as7726_32x_cpld_remove, + .id_table = as7726_32x_cpld_id, +}; + +static int __init as7726_32x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7726_32x_cpld_driver); +} + +static void __exit as7726_32x_cpld_exit(void) +{ + i2c_del_driver(&as7726_32x_cpld_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as7726_32x_cpld_init); +module_exit(as7726_32x_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_fan.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_fan.c new file mode 100755 index 000000000000..beb58804ac94 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_fan.c @@ -0,0 +1,763 @@ +/* + * A hwmon driver for the Accton as7726 32x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7726_32x_fan" + +#define NUM_THERMAL_SENSORS (5) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a, 0x4b, 0x4c} + +#define IN +#define OUT + +static struct as7726_32x_fan_data *as7726_32x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7726_32x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) + +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); + +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as7726_32x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as7726_32x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7726_32x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as7726_32x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as7726_32x_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as7726_32x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + OUT int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as7726_32x_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as7726_32x_fan_data *data = as7726_32x_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7726_32x_fan_data *data = as7726_32x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7726_32x_fan_group = { + .attrs = as7726_32x_fan_attributes, +}; + +static struct as7726_32x_fan_data *as7726_32x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7726_32x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7726_32x_fan_read_value(client, fan_reg[i]); + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7726_32x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7726_32x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7726_32x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7726_32x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7726_32x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7726_32x_fan_remove(struct i2c_client *client) +{ + struct as7726_32x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7726_32x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7726_32x_fan_id[] = { + { "as7726_32x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7726_32x_fan_id); + +static struct i2c_driver as7726_32x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7726_32x_fan_probe, + .remove = as7726_32x_fan_remove, + .id_table = as7726_32x_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as7726_32x_fan_driver); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("as7726_32x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_leds.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_leds.c new file mode 100755 index 000000000000..c179fd855bd2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_leds.c @@ -0,0 +1,437 @@ +/* + * A LED driver for the accton_as7726_32x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as7726_32x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as7726_32x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "accton_as7726_32x_led" + +struct accton_as7726_32x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct accton_as7726_32x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x3) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x00) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_OFF_VALUE (0x03) + + +#define LED_TYPE_LOC_REG_MASK (0x80) +#define LED_MODE_LOC_ON_VALUE (0) +#define LED_MODE_LOC_OFF_VALUE (0x80) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7726_32x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as7726_32x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as7726_32x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as7726_32x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + accton_as7726_32x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as7726_32x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7726_32x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as7726_32x_led_diag_get(struct led_classdev *cdev) +{ + accton_as7726_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as7726_32x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as7726_32x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as7726_32x_led_loc_get(struct led_classdev *cdev) +{ + accton_as7726_32x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void accton_as7726_32x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness accton_as7726_32x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev accton_as7726_32x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as7726_32x_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as7726_32x_led_diag_set, + .brightness_get = accton_as7726_32x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_LOC] = { + .name = "accton_as7726_32x_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as7726_32x_led_loc_set, + .brightness_get = accton_as7726_32x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE, + }, + [LED_TYPE_FAN] = { + .name = "accton_as7726_32x_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as7726_32x_led_auto_set, + .brightness_get = accton_as7726_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as7726_32x_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as7726_32x_led_auto_set, + .brightness_get = accton_as7726_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as7726_32x_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as7726_32x_led_auto_set, + .brightness_get = accton_as7726_32x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_as7726_32x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) { + led_classdev_suspend(&accton_as7726_32x_leds[i]); + } + + return 0; +} + +static int accton_as7726_32x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) { + led_classdev_resume(&accton_as7726_32x_leds[i]); + } + + return 0; +} + +static int accton_as7726_32x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as7726_32x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as7726_32x_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as7726_32x_leds[i]); + } + } + + return ret; +} + +static int accton_as7726_32x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as7726_32x_leds); i++) { + led_classdev_unregister(&accton_as7726_32x_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as7726_32x_led_driver = { + .probe = accton_as7726_32x_led_probe, + .remove = accton_as7726_32x_led_remove, + .suspend = accton_as7726_32x_led_suspend, + .resume = accton_as7726_32x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as7726_32x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as7726_32x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as7726_32x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as7726_32x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as7726_32x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as7726_32x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as7726_32x_led_driver); + kfree(ledctl); +} + +module_init(accton_as7726_32x_led_init); +module_exit(accton_as7726_32x_led_exit); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("accton_as7726_32x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_psu.c new file mode 100755 index 000000000000..f4da01e86d9b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/accton_as7726_32x_psu.c @@ -0,0 +1,276 @@ +/* + * An hwmon driver for accton as7726_32x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as7726_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7726_32x_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7726_32x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[9]; /* Model name, read from eeprom */ +}; + +static struct as7726_32x_psu_data *as7726_32x_psu_update_device(struct device *dev); + +enum as7726_32x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7726_32x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7726_32x_psu_data *data = as7726_32x_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7726_32x_psu_data *data = as7726_32x_psu_update_device(dev); + + return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as7726_32x_psu_group = { + .attrs = as7726_32x_psu_attributes, +}; + +static int as7726_32x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7726_32x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7726_32x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7726_32x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7726_32x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7726_32x_psu_remove(struct i2c_client *client) +{ + struct as7726_32x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7726_32x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7726_32x_psu1, + as7726_32x_psu2 +}; + +static const struct i2c_device_id as7726_32x_psu_id[] = { + { "as7726_32x_psu1", as7726_32x_psu1 }, + { "as7726_32x_psu2", as7726_32x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7726_32x_psu_id); + +static struct i2c_driver as7726_32x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7726_32x_psu", + }, + .probe = as7726_32x_psu_probe, + .remove = as7726_32x_psu_remove, + .id_table = as7726_32x_psu_id, + .address_list = normal_i2c, +}; + +static int as7726_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7726_32x_psu_data *as7726_32x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7726_32x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as7726_32x update\n"); + + /* Read psu status */ + status = as7726_32x_cpld_read(0x60, 0x2); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as7726_32x_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as7726_32x_psu_driver); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("as7726_32x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/ym2651y.c new file mode 100755 index 000000000000..8e76c56b54fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/modules/ym2651y.c @@ -0,0 +1,603 @@ +/* + * An hwmon driver for the 3Y Power YM-2651Y Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct ym2651y_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 capability; /* Register value */ + u16 status_word; /* Register value */ + u8 fan_fault; /* Register value */ + u8 over_temp; /* Register value */ + u16 v_out; /* Register value */ + u16 i_out; /* Register value */ + u16 p_out; /* Register value */ + u16 temp; /* Register value */ + u16 fan_speed; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u8 fan_dir[4]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[10]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct ym2651y_data *ym2651y_update_device(struct device *dev); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum ym2651y_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/ + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + +static struct attribute *ym2651y_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u16 status = 0; + + switch (attr->index) { + case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ + status = (data->status_word & 0x40) ? 0 : 1; + break; + case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ + status = (data->status_word & 0x4) >> 2; + break; + case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ + status = (data->status_word & 0x800) ? 0 : 1; + break; + } + + return sprintf(buf, "%d\n", status); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_OUT: + value = data->v_out; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_OUT_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + case PSU_FAN1_DUTY_CYCLE: + value = data->fan_duty_cycle[0]; + multiplier = 1; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_VOUT_MIN: + value = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + value = data->mfr_vout_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + + return sprintf(buf, "%d\n", data->over_temp >> 7); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 *ptr = NULL; + + switch (attr->index) { + case PSU_FAN_DIRECTION: /* psu_fan_dir */ + ptr = data->fan_dir; + break; + case PSU_MFR_ID: /* psu_mfr_id */ + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: /* psu_mfr_revision */ + ptr = data->mfr_revsion; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group ym2651y_group = { + .attrs = ym2651y_attributes, +}; + +static int ym2651y_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ym2651y_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int ym2651y_remove(struct i2c_client *client) +{ + struct ym2651y_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id ym2651y_id[] = { + { "ym2651", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ym2651y_id); + +static struct i2c_driver ym2651y_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ym2651", + }, + .probe = ym2651y_probe, + .remove = ym2651y_remove, + .id_table = ym2651y_id, + .address_list = normal_i2c, +}; + +static int ym2651y_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int ym2651y_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct ym2651y_data *ym2651y_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + u8 command; + u8 fan_dir[5] = {0}; + struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, + {0x7d, &data->over_temp}, + {0x81, &data->fan_fault}, + {0x98, &data->pmbus_revision}}; + struct reg_data_word regs_word[] = { {0x79, &data->status_word}, + {0x8b, &data->v_out}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x8d, &data->temp}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &data->fan_speed}, + {0xa0, &data->mfr_vin_min}, + {0xa1, &data->mfr_vin_max}, + {0xa2, &data->mfr_iin_max}, + {0xa3, &data->mfr_pin_max}, + {0xa4, &data->mfr_vout_min}, + {0xa5, &data->mfr_vout_max}, + {0xa6, &data->mfr_iout_max}, + {0xa7, &data->mfr_pout_max}}; + + dev_dbg(&client->dev, "Starting ym2651 update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = ym2651y_read_byte(client, regs_byte[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = ym2651y_read_word(client, regs_word[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read fan_direction */ + command = 0xC3; + status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + } + + strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1); + data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; + + /* Read mfr_id */ + command = 0x99; + status = ym2651y_read_block(client, command, data->mfr_id, + ARRAY_SIZE(data->mfr_id)-1); + data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_model */ + command = 0x9a; + status = ym2651y_read_block(client, command, data->mfr_model, + ARRAY_SIZE(data->mfr_model)-1); + data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_revsion */ + command = 0x9b; + status = ym2651y_read_block(client, command, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)-1); + data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(ym2651y_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-handle_mac.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-handle_mac.service new file mode 100644 index 000000000000..5492775eee62 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-handle_mac.service @@ -0,0 +1,15 @@ +[Unit] +Description=Accton AS7726-32X Platform MAC handle service +Before=opennsl-modules.service +After=local-fs.target + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/idt_init.sh +RemainAfterExit=yes + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=opennsl-modules.service diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-fan.service new file mode 100644 index 000000000000..e18d592d6c19 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS7726-32X Platform Monitoring FAN service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as7726_32x_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-psu.service new file mode 100644 index 000000000000..99f7479494e0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS7726-32X Platform Monitoring PSU service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as7726_32x_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor.service new file mode 100644 index 000000000000..5b04ad410101 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/service/as7726-32x-platform-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description=Accton AS7726-32X Platform Monitoring service +Before=pmon.service +After=as7726-32x-platform-handle_mac.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7726_32x_util.py install +ExecStart=/usr/local/bin/accton_as7726_32x_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/setup.py new file mode 100755 index 000000000000..9841874dbd1e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7726_32x', + version='1.0', + description='Module to initialize Accton AS7726-32X platforms', + + packages=['as7726_32x'], + package_dir={'as7726_32x': 'as7726-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/README new file mode 100755 index 000000000000..44e03cab5f52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor.py new file mode 100755 index 000000000000..aada6ba5c507 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor.py @@ -0,0 +1,329 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.)# +# 4/20/2018: Jostar modify for as7726_32x +# 12/03/2018:Jostar modify for as7726_32x thermal plan +# ------------------------------------------------------------------ + +try: + import os + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example + from as7726_32x.fanutil import FanUtil + from as7726_32x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7726_32x_monitor' + +global log_file +global log_level + + +# Air Flow Front to Back : +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=38C : Keep 37.5%(0x04) Fan speed +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 38C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 46C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 58C : Send alarm message +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 66C : Shut down system +# One Fan fail : Change Fan speed to 100%(0x0E) + + +# Air Flow Back to Front : +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=34C : Keep 37.5%(0x04) Fan speed +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 34C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 44C : Change Fan speed from 62.5%(0x08) to 100%(0x0E) +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 59C : Send alarm message +# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 67C : Shut down system +# One Fan fail: Change Fan speed to 100%(0x0E) +# sensor_LM75_CPU == sensor_LM75_4B + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_policy_state=1 +fan_fail=0 +alarm_state = 0 #0->default or clear, 1-->alarm detect +test_temp = 0 +test_temp_list = [0, 0, 0, 0, 0, 0] +temp_test_data=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + # static temp var + temp = 0 + new_pwm = 0 + pwm=0 + ori_pwm = 0 + default_pwm=0x4 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + + def get_state_from_fan_policy(self, temp, policy): + state=0 + + logging.debug('temp=%d', temp) + for i in range(0, len(policy)): + if temp > policy[i][2]: + if temp <= policy[i][3]: + state =i + logging.debug ('temp=%d >= policy[%d][2]=%d, temp=%d < policy[%d][3]=%d' , temp, i, policy[i][2], temp, i, policy[i][3]) + logging.debug ('fan_state=%d', state) + break + + return state + + def manage_fans(self): + + global fan_policy_state + global fan_fail + global test_temp + global test_temp_list + global alarm_state + global temp_test_data + + LEVEL_FAN_DEF=0 + LEVEL_FAN_MID=1 + LEVEL_FAN_MAX=2 + LEVEL_TEMP_HIGH=3 + LEVEL_TEMP_CRITICAL=4 + + fan_policy_f2b = { + LEVEL_FAN_DEF: [38, 0x4, 0, 38000], + LEVEL_FAN_MID: [63, 0x6, 38000, 46000], + LEVEL_FAN_MAX: [100, 0xE, 46000, 58000], + LEVEL_TEMP_HIGH: [100, 0xE, 58000, 66000], + LEVEL_TEMP_CRITICAL: [100, 0xE, 58000, 200000], + } + fan_policy_b2f = { + LEVEL_FAN_DEF: [38, 0x4, 0, 34000], + LEVEL_FAN_MID: [63, 0x8, 34000, 44000], + LEVEL_FAN_MAX: [100, 0xE, 44000, 59000], + LEVEL_TEMP_HIGH: [100, 0xE, 59000, 67000], + LEVEL_TEMP_CRITICAL: [100, 0xE, 59000, 200000], + } + + fan_policy = fan_policy_f2b + + thermal = ThermalUtil() + fan = FanUtil() + fan_dir=fan.get_fan_dir(1) + if fan_dir == 1: + fan_dri=1 #something wrong, set fan_dir to default val + else: + fan_policy = fan_policy_b2f + + ori_pwm=fan.get_fan_duty_cycle() + new_pwm=0 + logging.debug('fan_dir=%d, ori_pwm=%d', fan_dir, ori_pwm) + logging.debug('test_temp=%d', test_temp) + if test_temp==0: + temp1 = thermal._get_thermal_val(1) + temp2 = thermal._get_thermal_val(2) + temp3 = thermal._get_thermal_val(3) + temp4 = thermal._get_thermal_val(4) + temp5 = thermal._get_thermal_val(5) + else: + temp1 = test_temp_list[0] + temp2 = test_temp_list[1] + temp3 = test_temp_list[2] + temp4 = test_temp_list[3] + temp5 = test_temp_list[4] + fan_fail=0 + + if temp3==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_49 detect fail, so set temp_get=50000, let fan to 75%') + elif temp4==0: + temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75% + logging.debug('lm75_4b detect fail, so set temp_get=50000, let fan to 75%') + else: + temp_get= (temp3 + temp4)/2 # Use (sensor_LM75_4a + sensor_LM75_4b) /2 + ori_state=fan_policy_state + + if test_temp!=0: + temp_test_data=temp_test_data+1000 + temp_get = temp_get + temp_test_data + logging.debug('Unit test:temp_get=%d', temp_get) + + fan_policy_state=self.get_state_from_fan_policy(temp_get, fan_policy) + + logging.debug('lm75_48=%d, lm75_49=%d, lm75_4a=%d, lm_4b=%d, lm_4c=%d', temp1,temp2,temp3,temp4,temp5) + logging.debug('ori_state=%d, fan_policy_state=%d', ori_state, fan_policy_state) + new_pwm = fan_policy[fan_policy_state][0] + if fan_fail==0: + logging.debug('new_fan_cycle=%d', new_pwm) + + if fan_fail==0: + if new_pwm!=ori_pwm: + fan.set_fan_duty_cycle(new_pwm) + logging.info('Set fan speed from %d to %d', ori_pwm, new_pwm) + + #Check Fan status + for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): + if fan.get_fan_status(i)==0: + new_pwm=100 + logging.debug('fan_%d fail, set pwm to 100',i) + if test_temp==0: + fan_fail=1 + fan.set_fan_duty_cycle(new_pwm) + break + else: + fan_fail=0 + + new_state = fan_policy_state + + if ori_state==LEVEL_FAN_DEF: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected, reboot DUT') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MID: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if ori_state==LEVEL_FAN_MAX: + if new_state==LEVEL_TEMP_HIGH: + if alarm_state==0: + logging.warning('Alarm for temperature high is detected') + alarm_state=1 + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if alarm_state==1: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_HIGH: + if new_state==LEVEL_TEMP_CRITICAL: + logging.critical('Alarm for temperature critical is detected') + time.sleep(2) + os.system('reboot') + if new_state <= LEVEL_FAN_MID: + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if new_state <= LEVEL_FAN_MAX: + if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm + logging.warning('Alarm for temperature high is cleared') + alarm_state=0 + if ori_state==LEVEL_TEMP_CRITICAL: + if new_state <= LEVEL_FAN_MAX: + logging.warning('Alarm for temperature critical is cleared') + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global test_temp + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdlt:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + if sys.argv[1]== '-t': + if len(sys.argv)!=7: + print "temp test, need input six temp" + return 0 + + i=0 + for x in range(2, 7): + test_temp_list[i]= int(sys.argv[x])*1000 + i=i+1 + test_temp = 1 + log_level = logging.DEBUG + print test_temp_list + + fan = FanUtil() + fan.set_fan_duty_cycle(38) + print "set default fan speed to 37.5%" + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(5) + +if __name__ == '__main__': + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_fan.py new file mode 100755 index 000000000000..a2139341150c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_fan.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7726_32x_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.fan_num = 6 + self.fan_path = "/sys/bus/i2c/devices/54-0066/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + 4: "fan5_present", + 5: "fan6_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + 4: "fan5_fault", + 5: "fan6_fault", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_psu.py new file mode 100755 index 000000000000..d139e3f3f1c8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_monitor_psu.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/2/2018: Jostar create for as7326-56x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as7726_32x_monitor_psu' + +global log_file +global log_level + + +psu_state=[2, 2] +psu_status_state=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "50-0053", + 1: "49-0050", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + PSU_STATUS_IDLE =2 + + global psu_state + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=1: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_status_state[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=0: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_IDLE + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "0": + if psu_status_state[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d failed is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_NO_POWER + else: + if psu_state[idx]==PSU_STATE_INSERT: + if psu_status_state[idx]!=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_util.py b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_util.py new file mode 100755 index 000000000000..a6aa855174be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_as7726_32x_util.py @@ -0,0 +1,599 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + +PROJECT_NAME = 'as7726_32x' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':54} + + +led_prefix ='/sys/devices/platform/as7716_32x_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as7716_32x_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan4_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['54-0066'], + 'thermal': ['54-004c', '55-0048','55-0049', '55-004a', '55-004b'] , + 'psu': ['49-0050','50-0053'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'], + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_ ', 'module_tx_disable_']} + +sfp_map = [21, 22, 23, 24, 26, 25, 28, 27, + 17, 18, 19, 20, 29, 30, 31, 32, + 33, 34, 35, 36, 45, 46, 47, 48, + 37, 38, 39, 40, 41, 42, 43, 44, + 15, 16] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', + +'echo as7726_32x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo as7726_32x_cpld2 0x62 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo as7726_32x_cpld3 0x64 > /sys/bus/i2c/devices/i2c-13/new_device', + +'echo as7726_32x_fan 0x66 > /sys/bus/i2c/devices/i2c-54/new_device', + + +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-54/new_device', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-55/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-55/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-55/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-55/new_device', + + +# PSU-1 +'echo as7726_32x_psu1 0x53 > /sys/bus/i2c/devices/i2c-50/new_device', +'echo ym2651 0x5b > /sys/bus/i2c/devices/i2c-50/new_device', + +# PSU-2 +'echo as7726_32x_psu2 0x50> /sys/bus/i2c/devices/i2c-49/new_device', +'echo ym2651 0x58 > /sys/bus/i2c/devices/i2c-49/new_device', + +#EERPOM +'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +] + + + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def dis_i2c_ir3570a(addr): + cmd = "i2cset -y 0 0x%x 0xE5 0x01" % addr + status, output = commands.getstatusoutput(cmd) + cmd = "i2cset -y 0 0x%x 0x12 0x02" % addr + status, output = commands.getstatusoutput(cmd) + return status + +def ir3570_check(): + cmd = "i2cdump -y 0 0x42 s 0x9a" + try: + status, output = commands.getstatusoutput(cmd) + lines = output.split('\n') + hn = re.findall(r'\w+', lines[-1]) + version = int(hn[1], 16) + if version == 0x24: #only for ir3570a + ret = dis_i2c_ir3570a(4) + else: + ret = 0 + except Exception as e: + print "Error on ir3570_check() e:" + str(e) + return -1 + return ret + + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + +def cpld_reset_mac(): + ret, lsmod = log_os_system("i2cset -y 0 0x77 0x1", 0) + ret, lsmod = log_os_system("i2cset -y 0 0x76 0x4", 0) + ret, lsmod = log_os_system("i2cset -y 0 0x60 0x8 0x77", 0) + time.sleep(1) + ret, lsmod = log_os_system("i2cset -y 0 0x60 0x8 0xf7", 0) + return True + + + +#'modprobe cpr_4011_4mxx', + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe ym2651y', +'modprobe accton_as7726_32x_cpld', +'modprobe accton_as7726_32x_fan', +'modprobe accton_as7726_32x_leds', +'modprobe accton_as7726_32x_psu', +'modprobe optoe'] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + + #status=cpld_reset_mac() + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + lst = rm.split(" ") + print "lst=%s"%lst + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + print "not device_exist()" + return False + return True + +def do_install(): + if driver_inserted() == False: + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + + ir3570_check() + + if not device_exist(): + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + print "node=%s"%node + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_handle_idt.sh b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_handle_idt.sh new file mode 100755 index 000000000000..6c9af53dce37 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/accton_handle_idt.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +if [ -s /usr/local/bin/done_idt_init ];then + echo "There is a done_idt_init file" +else + cat /etc/init.d/opennsl-modules|grep idt_init.sh + if [ $? -ne 0 ];then + echo "Add idt_init.sh to opennsl-modules for TD3 MAC" + sed -i '/modprobe linux-kernel-bde/i sleep 1' /etc/init.d/opennsl-modules + sed -i '/sleep/i /usr/local/bin/idt_init.sh' /etc/init.d/opennsl-modules + sed -i '/idt_init/i echo "IDT init" ' /etc/init.d/opennsl-modules + sed -i '/IDT init/i echo 1 > /usr/local/bin/done_idt_init' /etc/init.d/opennsl-modules + fi + +fi + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/idt_init.sh b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/idt_init.sh new file mode 100755 index 000000000000..257a0242702f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/idt_init.sh @@ -0,0 +1,152 @@ +#!/bin/bash +test_log=/usr/local/bin/check_idt_status.txt +modprobe i2c-i801 +modprobe i2c-dev +i2cset -y 0 0x77 0x1 +i2cset -y 0 0x76 0x1 +i2cget -y 0 0x54 0 b > /dev/null +if [ $? -ne 0 ];then + printf "Device 8v89307(0x54) not found\n" + exit 1 +fi +echo "IDT 82V89307 " +echo "idt init 1" +# Title = --- IDT 82V89307 Registers --- +#Select to Page 0 +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x7F 0x05 +i2cset -y 0 0x54 0x7E 0x85 +i2cset -y 0 0x54 0x7B 0x00 +i2cset -y 0 0x54 0x7A 0x00 +i2cset -y 0 0x54 0x79 0x40 +i2cset -y 0 0x54 0x78 0x06 +i2cset -y 0 0x54 0x73 0x40 +i2cset -y 0 0x54 0x72 0x40 + +# OUT3:25MHz +i2cset -y 0 0x54 0x71 0x0A +i2cset -y 0 0x54 0x70 0x00 + +# OUT1:1pps +i2cset -y 0 0x54 0x6B 0x4E +i2cset -y 0 0x54 0x69 0x00 +i2cset -y 0 0x54 0x68 0x00 +i2cset -y 0 0x54 0x67 0x19 +i2cset -y 0 0x54 0x66 0xAB +i2cset -y 0 0x54 0x65 0x8C +i2cset -y 0 0x54 0x64 0x00 +i2cset -y 0 0x54 0x63 0x00 +i2cset -y 0 0x54 0x62 0x00 +i2cset -y 0 0x54 0x5F 0x00 +i2cset -y 0 0x54 0x5E 0x00 +i2cset -y 0 0x54 0x5D 0x00 +i2cset -y 0 0x54 0x5C 0x78 +i2cset -y 0 0x54 0x5B 0x02 +i2cset -y 0 0x54 0x5A 0xE5 +i2cset -y 0 0x54 0x59 0x88 +i2cset -y 0 0x54 0x58 0x4B +i2cset -y 0 0x54 0x57 0x6C +i2cset -y 0 0x54 0x56 0x6C + +# Lock to DPLL, output 625MHz +i2cset -y 0 0x54 0x55 0x80 +i2cset -y 0 0x54 0x53 0x00 +i2cset -y 0 0x54 0x52 0x81 +i2cset -y 0 0x54 0x50 0x00 +i2cset -y 0 0x54 0x4F 0x00 +i2cset -y 0 0x54 0x4E 0x00 +i2cset -y 0 0x54 0x4C 0xCB +i2cset -y 0 0x54 0x4A 0x00 +i2cset -y 0 0x54 0x45 0x66 +i2cset -y 0 0x54 0x44 0x66 +i2cset -y 0 0x54 0x42 0x80 +i2cset -y 0 0x54 0x41 0x03 +i2cset -y 0 0x54 0x40 0x01 +i2cset -y 0 0x54 0x3F 0x08 +i2cset -y 0 0x54 0x3E 0x04 +i2cset -y 0 0x54 0x3D 0x20 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x34 0x01 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x2F 0x23 +i2cset -y 0 0x54 0x2E 0x0B +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x28 0x76 +i2cset -y 0 0x54 0x27 0x54 +i2cset -y 0 0x54 0x25 0x00 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x1A 0x8C +i2cset -y 0 0x54 0x19 0x8C +i2cset -y 0 0x54 0x18 0x00 +i2cset -y 0 0x54 0x16 0x0D +i2cset -y 0 0x54 0x11 0x00 +i2cset -y 0 0x54 0x10 0x00 +i2cset -y 0 0x54 0x0E 0x3F +i2cset -y 0 0x54 0x0D 0xFF +i2cset -y 0 0x54 0x0C 0x02 +i2cset -y 0 0x54 0x0B 0xA1 +i2cset -y 0 0x54 0x0A 0x89 +i2cset -y 0 0x54 0x09 0xA2 +i2cset -y 0 0x54 0x08 0x32 +i2cset -y 0 0x54 0x06 0x00 +i2cset -y 0 0x54 0x05 0x00 +i2cset -y 0 0x54 0x04 0x00 +i2cset -y 0 0x54 0x03 0x00 +i2cset -y 0 0x54 0x02 0x05 +i2cset -y 0 0x54 0x01 0x33 +i2cset -y 0 0x54 0x00 0x91 + +echo "idt init 2" +# PreDivider_Parameters +#IN1 +i2cset -y 0 0x54 0x23 0x05 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN2 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN3 +i2cset -y 0 0x54 0x23 0x03 +i2cset -y 0 0x54 0x24 0x00 +i2cset -y 0 0x54 0x25 0x00 + +echo "idt init 3" +# Page1_Parameters +#Select to Page 1 +i2cset -y 0 0x54 0x2D 0x01 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3D 0x20 +#Return to Page 0 +i2cset -y 0 0x54 0x2D 0x00 + +echo "idt init 4" +#reset the in-path mux +i2cset -y 0 0x76 0x0 +i2cset -y 0 0x77 0x0 + + + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/mac_reset.sh b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/mac_reset.sh new file mode 100755 index 000000000000..9f688058c305 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7726-32x/utils/mac_reset.sh @@ -0,0 +1,242 @@ +#!/bin/bash +test_log=/usr/local/bin/check_mac_status.txt +modprobe i2c-i801 +modprobe i2c-dev +i2cset -y 0 0x77 0x1 +i2cset -y 0 0x76 0x1 +i2cget -y 0 0x54 0 b > /dev/null +if [ $? -ne 0 ];then + printf "Device 8v89307(0x54) not found\n" + i2cdetect -y 0 + echo "Reset both MAC and PCI (write 0x6F)" + i2cset -y 0 0x60 0x8 0x6f + + echo "Sleep 1s" + sleep 1 + + echo "Pull back MAC reset, keep PCIE reset (write 0xEF)" + i2cset -y 0 0x60 0x7 0xef + + echo "Sleep 1s" + sleep 1 + + echo "Set to default normal state (write 0xFF)" + i2cset -y 0 0x60 0x8 0xff + + + echo "remove PCI device" + echo 1 > /sys/bus/pci/devices/0000:07:00.0/remove + ls /sys/bus/pci/devices/ + echo "rescan PCI device" + echo 1 > /sys/bus/pci/rescan + ls /sys/bus/pci/devices/ + echo "Sleep 1s" + sleep 1 + lspci -n|grep 07:00.0 + if [ $? -ne 0 ];then + echo "Broadcom Corporation Device is not detect">>$test_log + echo "rescan PCI again" >>$test_log + echo 1 > /sys/bus/pci/rescan + sleep 1 + lspci -n|grep 07:00.0 + if [ $? -ne 0 ];then + echo "Broadcom Corporation Device NG">>$test_log + echo "rescan PCI again-2" >>$test_log + echo 1 > /sys/bus/pci/rescan + sleep 1 + else + echo "done mac_pci_reset_rescan" + fi + fi + + exit 1 +fi +echo "idt init 1" +# Title = --- IDT 82V89307 Registers --- +#Select to Page 0 +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x7F 0x05 +i2cset -y 0 0x54 0x7E 0x85 +i2cset -y 0 0x54 0x7B 0x00 +i2cset -y 0 0x54 0x7A 0x00 +i2cset -y 0 0x54 0x79 0x40 +i2cset -y 0 0x54 0x78 0x06 +i2cset -y 0 0x54 0x73 0x40 +i2cset -y 0 0x54 0x72 0x40 + +# OUT3:25MHz +i2cset -y 0 0x54 0x71 0x0A +i2cset -y 0 0x54 0x70 0x00 + +# OUT1:1pps +i2cset -y 0 0x54 0x6B 0x4E +i2cset -y 0 0x54 0x69 0x00 +i2cset -y 0 0x54 0x68 0x00 +i2cset -y 0 0x54 0x67 0x19 +i2cset -y 0 0x54 0x66 0xAB +i2cset -y 0 0x54 0x65 0x8C +i2cset -y 0 0x54 0x64 0x00 +i2cset -y 0 0x54 0x63 0x00 +i2cset -y 0 0x54 0x62 0x00 +i2cset -y 0 0x54 0x5F 0x00 +i2cset -y 0 0x54 0x5E 0x00 +i2cset -y 0 0x54 0x5D 0x00 +i2cset -y 0 0x54 0x5C 0x78 +i2cset -y 0 0x54 0x5B 0x02 +i2cset -y 0 0x54 0x5A 0xE5 +i2cset -y 0 0x54 0x59 0x88 +i2cset -y 0 0x54 0x58 0x4B +i2cset -y 0 0x54 0x57 0x6C +i2cset -y 0 0x54 0x56 0x6C + +# Lock to DPLL, output 625MHz +i2cset -y 0 0x54 0x55 0x80 +i2cset -y 0 0x54 0x53 0x00 +i2cset -y 0 0x54 0x52 0x81 +i2cset -y 0 0x54 0x50 0x00 +i2cset -y 0 0x54 0x4F 0x00 +i2cset -y 0 0x54 0x4E 0x00 +i2cset -y 0 0x54 0x4C 0xCB +i2cset -y 0 0x54 0x4A 0x00 +i2cset -y 0 0x54 0x45 0x66 +i2cset -y 0 0x54 0x44 0x66 +i2cset -y 0 0x54 0x42 0x80 +i2cset -y 0 0x54 0x41 0x03 +i2cset -y 0 0x54 0x40 0x01 +i2cset -y 0 0x54 0x3F 0x08 +i2cset -y 0 0x54 0x3E 0x04 +i2cset -y 0 0x54 0x3D 0x20 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x34 0x01 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x2F 0x23 +i2cset -y 0 0x54 0x2E 0x0B +i2cset -y 0 0x54 0x2D 0x00 +i2cset -y 0 0x54 0x28 0x76 +i2cset -y 0 0x54 0x27 0x54 +i2cset -y 0 0x54 0x25 0x00 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x1A 0x8C +i2cset -y 0 0x54 0x19 0x8C +i2cset -y 0 0x54 0x18 0x00 +i2cset -y 0 0x54 0x16 0x0D +i2cset -y 0 0x54 0x11 0x00 +i2cset -y 0 0x54 0x10 0x00 +i2cset -y 0 0x54 0x0E 0x3F +i2cset -y 0 0x54 0x0D 0xFF +i2cset -y 0 0x54 0x0C 0x02 +i2cset -y 0 0x54 0x0B 0xA1 +i2cset -y 0 0x54 0x0A 0x89 +i2cset -y 0 0x54 0x09 0xA2 +i2cset -y 0 0x54 0x08 0x32 +i2cset -y 0 0x54 0x06 0x00 +i2cset -y 0 0x54 0x05 0x00 +i2cset -y 0 0x54 0x04 0x00 +i2cset -y 0 0x54 0x03 0x00 +i2cset -y 0 0x54 0x02 0x05 +i2cset -y 0 0x54 0x01 0x33 +i2cset -y 0 0x54 0x00 0x91 + +echo "idt init 2" +# PreDivider_Parameters +#IN1 +i2cset -y 0 0x54 0x23 0x05 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN2 +i2cset -y 0 0x54 0x23 0x06 +i2cset -y 0 0x54 0x24 0x03 +i2cset -y 0 0x54 0x25 0x00 +#IN3 +i2cset -y 0 0x54 0x23 0x03 +i2cset -y 0 0x54 0x24 0x00 +i2cset -y 0 0x54 0x25 0x00 + +echo "idt init 3" +# Page1_Parameters +#Select to Page 1 +i2cset -y 0 0x54 0x2D 0x01 +i2cset -y 0 0x54 0x30 0x03 +i2cset -y 0 0x54 0x31 0x08 +i2cset -y 0 0x54 0x32 0x08 +i2cset -y 0 0x54 0x33 0x08 +i2cset -y 0 0x54 0x35 0x7C +i2cset -y 0 0x54 0x36 0xCE +i2cset -y 0 0x54 0x37 0x04 +i2cset -y 0 0x54 0x38 0xE6 +i2cset -y 0 0x54 0x39 0x01 +i2cset -y 0 0x54 0x3A 0x98 +i2cset -y 0 0x54 0x3B 0x00 +i2cset -y 0 0x54 0x3C 0x13 +i2cset -y 0 0x54 0x3D 0x20 +#Return to Page 0 +i2cset -y 0 0x54 0x2D 0x00 + +echo "idt init 4" +#reset the in-path mux +i2cset -y 0 0x76 0x0 +i2cset -y 0 0x77 0x0 + +#flip MAC reset at CPLD +echo "Work around: We need to reset MAC after set 8v89307 clock output" +echo " or it is possible to get sdk init failure sometimes" +echo "MAC reset at CPLD" +i2cset -y 0 0x77 0x1 +i2cset -y 0 0x76 0x4 +#i2cset -y 0 0x60 0x8 0x7f +#sleep 1 +#i2cset -y 0 0x60 0x8 0xff + + echo "Reset both MAC and PCI (write 0x6F)" + i2cset -y 0 0x60 0x8 0x6f + + echo "Sleep 1s" + sleep 1 + + echo "Pull back MAC reset, keep PCIE reset (write 0xEF)" + i2cset -y 0 0x60 0x7 0xef + + echo "Sleep 1s" + sleep 1 + + echo "Set to default normal state (write 0xFF)" + i2cset -y 0 0x60 0x8 0xff + + + echo "remove PCI device" + echo 1 > /sys/bus/pci/devices/0000:07:00.0/remove + ls /sys/bus/pci/devices/ + echo "rescan PCI device" + echo 1 > /sys/bus/pci/rescan + ls /sys/bus/pci/devices/ + echo "Sleep 1s" + sleep 1 + lspci -n|grep 07:00.0 + if [ $? -ne 0 ];then + echo "Broadcom Corporation Device is not detect">>$test_log + echo "rescan PCI again" >>$test_log + echo 1 > /sys/bus/pci/rescan + sleep 1 + lspci -n|grep 07:00.0 + if [ $? -ne 0 ];then + echo "Broadcom Corporation Device NG">>$test_log + echo "rescan PCI again-2" >>$test_log + echo 1 > /sys/bus/pci/rescan + sleep 1 + else + echo "done mac_pci_reset_rescan" + fi + fi + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/fanutil.py new file mode 100644 index 000000000000..42ccb17eaa06 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/fanutil.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 4 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/17-0068/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/17-0068/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/thermalutil.py new file mode 100644 index 000000000000..65e872c6beb8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/thermalutil.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 6 + THERMAL_NUM_1_IDX = 1 + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = [ + ['18', '48'], + ['18', '49'], + ['18', '4a'], + ['18', '4b'], + ['17', '4d'], + ['17', '4e'], + ] + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_ON_MAIN_BROAD): + self._thermal_to_device_path_mapping[x+1] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + + def get_thermal_temp(self): + sum = 0 + o = [] + for x in range(self.THERMAL_NUM_ON_MAIN_BROAD): + sum += self._get_thermal_node_val(x+1) + avg = sum/self.THERMAL_NUM_ON_MAIN_BROAD + avg = (avg/1000)*1000 #round down for hysteresis. + return avg + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/Makefile new file mode 100644 index 000000000000..1b3477b0b771 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/Makefile @@ -0,0 +1,2 @@ +obj-m:=x86-64-accton-as7816-64x-fan.o x86-64-accton-as7816-64x-sfp.o x86-64-accton-as7816-64x-leds.o \ + x86-64-accton-as7816-64x-psu.o accton_i2c_cpld.o ym2651y.o diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_i2c_cpld.c new file mode 120000 index 000000000000..39c0826d16fd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_i2c_cpld.c @@ -0,0 +1 @@ +../../common/modules/accton_i2c_cpld.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-fan.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-fan.c new file mode 100644 index 000000000000..2cd85c43a9c2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-fan.c @@ -0,0 +1,472 @@ +/* + * A hwmon driver for the Accton as7816-64x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7816_64x_fan" + +static struct as7816_64x_fan_data *as7816_64x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x80, /* fan 1-4 present status */ + 0x81, /* fan 1-4 direction(0:F2B 1:B2F) */ + 0x87, /* fan PWM(for all fan) */ + 0x90, /* front fan 1 speed(rpm) */ + 0x91, /* front fan 2 speed(rpm) */ + 0x92, /* front fan 3 speed(rpm) */ + 0x93, /* front fan 4 speed(rpm) */ + 0x98, /* rear fan 1 speed(rpm) */ + 0x99, /* rear fan 2 speed(rpm) */ + 0x9A, /* rear fan 3 speed(rpm) */ + 0x9B, /* rear fan 4 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7816_64x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr + + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); + +static struct attribute *as7816_64x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 + +static int as7816_64x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7816_64x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + + if (!reg_val) { + return 0; + } + + if (reg_val == 0xF) { + return FAN_MAX_DUTY_CYCLE; + } + + return (reg_val * 6) + 10; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle < 16) { + return 0; + } + + if (duty_cycle >= 100) { + return 0xF; + } + + return (duty_cycle - 10) / 6; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + if (reg_val == 0 || reg_val == 255) { + return 0; + } else { + u64 f, dv; + dv = 2 * 2 * 40960 * (u64)(255 - reg_val); + f = 60000000000 / dv; + return (u32)f; + } +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + return !!(reg_val & mask); +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + return !(reg_val & mask); +} + +static u8 is_fan_fault(struct as7816_64x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as7816_64x_fan_write_value(client, 0x28, 0); /* Disable fan speed watch dog */ + as7816_64x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7816_64x_fan_data *data = as7816_64x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + { + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + } + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7816_64x_fan_group = { + .attrs = as7816_64x_fan_attributes, +}; + +static struct as7816_64x_fan_data *as7816_64x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7816_64x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7816_64x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7816_64x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7816_64x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7816_64x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7816_64x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7816_64x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7816_64x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7816_64x_fan_remove(struct i2c_client *client) +{ + struct as7816_64x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7816_64x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static const struct i2c_device_id as7816_64x_fan_id[] = { + { "as7816_64x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7816_64x_fan_id); + +static struct i2c_driver as7816_64x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7816_64x_fan_probe, + .remove = as7816_64x_fan_remove, + .id_table = as7816_64x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7816_64x_fan_init(void) +{ + return i2c_add_driver(&as7816_64x_fan_driver); +} + +static void __exit as7816_64x_fan_exit(void) +{ + i2c_del_driver(&as7816_64x_fan_driver); +} + +module_init(as7816_64x_fan_init); +module_exit(as7816_64x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7816_64x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-leds.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-leds.c new file mode 100644 index 000000000000..3102e968c93f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-leds.c @@ -0,0 +1,459 @@ +/* + * A LED driver for the as7816_64x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int accton_i2c_cpld_read (u8 cpld_addr, u8 reg); +extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "as7816_64x_led" + +struct as7816_64x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct as7816_64x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x03) +#define LED_MODE_DIAG_YELLOW_VALUE (0x00) +#define LED_MODE_DIAG_RED_VALUE (0x01) +#define LED_MODE_DIAG_GREEN_VALUE (0x02) +#define LED_MODE_DIAG_OFF_VALUE (0x03) + +#define LED_TYPE_LOC_REG_MASK (0x10) +#define LED_MODE_LOC_ORANGE_VALUE (0x00) +#define LED_MODE_LOC_OFF_VALUE (0x10) + +#define LED_TYPE_FAN_REG_MASK (0x0C) +#define LED_MODE_FAN_ORANGE_VALUE (0x04) +#define LED_MODE_FAN_GREEN_VALUE_1 (0x00) +#define LED_MODE_FAN_GREEN_VALUE_2 (0x08) +#define LED_MODE_FAN_OFF_VALUE (0x0C) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1 << LED_TYPE_LOC) | (1 << LED_TYPE_DIAG) | (1 << LED_TYPE_FAN), 0x30}, +}; + +enum led_light_mode { + LED_MODE_OFF, + LED_MODE_RED = 10, + LED_MODE_RED_BLINKING = 11, + LED_MODE_ORANGE = 12, + LED_MODE_ORANGE_BLINKING = 13, + LED_MODE_YELLOW = 14, + LED_MODE_YELLOW_BLINKING = 15, + LED_MODE_GREEN = 16, + LED_MODE_GREEN_BLINKING = 17, + LED_MODE_BLUE = 18, + LED_MODE_BLUE_BLINKING = 19, + LED_MODE_PURPLE = 20, + LED_MODE_PURPLE_BLINKING = 21, + LED_MODE_AUTO = 22, + LED_MODE_AUTO_BLINKING = 23, + LED_MODE_WHITE = 24, + LED_MODE_WHITE_BLINKING = 25, + LED_MODE_CYAN = 26, + LED_MODE_CYAN_BLINKING = 27, + LED_MODE_UNKNOWN = 99 +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int reg_bit_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, +{LED_TYPE_LOC, LED_MODE_ORANGE,LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_ORANGE_VALUE}, +{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE}, +{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE}, +{LED_TYPE_DIAG, LED_MODE_RED, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_RED_VALUE}, +{LED_TYPE_DIAG, LED_MODE_YELLOW,LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_YELLOW_VALUE}, +{LED_TYPE_FAN, LED_MODE_OFF, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_OFF_VALUE}, +{LED_TYPE_FAN, LED_MODE_GREEN, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_GREEN_VALUE_1}, +{LED_TYPE_FAN, LED_MODE_GREEN, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_GREEN_VALUE_2}, +{LED_TYPE_FAN, LED_MODE_ORANGE,LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_ORANGE_VALUE} +}; + +static int get_led_reg(enum led_type type, u8 *reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(led_reg_map); i++) { + if(led_reg_map[i].types & (1 << type)) { + *reg = led_reg_map[i].reg_addr; + return 0; + } + } + + return 1; +} + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].reg_bit_mask & reg_val) == + led_type_mode_data[i].mode_value) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_value | + (reg_val & (~led_type_mode_data[i].reg_bit_mask)); + break; + } + + return reg_val; +} + +static int as7816_64x_led_read_value(u8 reg) +{ + return accton_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int as7816_64x_led_write_value(u8 reg, u8 value) +{ + return accton_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void as7816_64x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting as7816_64x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as7816_64x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as7816_64x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !get_led_reg(type, ®)) { + dev_dbg(&ledctl->pdev->dev, "Not match register for %d.\n", type); + } + + reg_val = as7816_64x_led_read_value(reg); + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + as7816_64x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void as7816_64x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7816_64x_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness as7816_64x_led_diag_get(struct led_classdev *cdev) +{ + as7816_64x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void as7816_64x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7816_64x_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness as7816_64x_led_loc_get(struct led_classdev *cdev) +{ + as7816_64x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void as7816_64x_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7816_64x_led_set(led_cdev, led_light_mode, LED_TYPE_FAN); +} + +static enum led_brightness as7816_64x_led_fan_get(struct led_classdev *cdev) +{ + as7816_64x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + +static void as7816_64x_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness as7816_64x_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static struct led_classdev as7816_64x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "as7816_64x_led::diag", + .default_trigger = "unused", + .brightness_set = as7816_64x_led_diag_set, + .brightness_get = as7816_64x_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN, + }, + [LED_TYPE_LOC] = { + .name = "as7816_64x_led::loc", + .default_trigger = "unused", + .brightness_set = as7816_64x_led_loc_set, + .brightness_get = as7816_64x_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_ORANGE, + }, + [LED_TYPE_FAN] = { + .name = "as7816_64x_led::fan", + .default_trigger = "unused", + .brightness_set = as7816_64x_led_fan_set, + .brightness_get = as7816_64x_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN, + }, + [LED_TYPE_PSU1] = { + .name = "as7816_64x_led::psu1", + .default_trigger = "unused", + .brightness_set = as7816_64x_led_auto_set, + .brightness_get = as7816_64x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as7816_64x_led::psu2", + .default_trigger = "unused", + .brightness_set = as7816_64x_led_auto_set, + .brightness_get = as7816_64x_led_auto_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int as7816_64x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7816_64x_leds); i++) { + led_classdev_suspend(&as7816_64x_leds[i]); + } + + return 0; +} + +static int as7816_64x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(as7816_64x_leds); i++) { + led_classdev_resume(&as7816_64x_leds[i]); + } + + return 0; +} + +static int as7816_64x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(as7816_64x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as7816_64x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as7816_64x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&as7816_64x_leds[i]); + } + } + + return ret; +} + +static int as7816_64x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as7816_64x_leds); i++) { + led_classdev_unregister(&as7816_64x_leds[i]); + } + + return 0; +} + +static struct platform_driver as7816_64x_led_driver = { + .probe = as7816_64x_led_probe, + .remove = as7816_64x_led_remove, + .suspend = as7816_64x_led_suspend, + .resume = as7816_64x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as7816_64x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&as7816_64x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct as7816_64x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&as7816_64x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&as7816_64x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit as7816_64x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as7816_64x_led_driver); + kfree(ledctl); +} + +module_init(as7816_64x_led_init); +module_exit(as7816_64x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7816_64x_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-psu.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-psu.c new file mode 100644 index 000000000000..cdc535347dc0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-psu.c @@ -0,0 +1,239 @@ +/* + * An hwmon driver for accton as7816_64x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x03 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(2+id))) +#define IS_PRESENT(id, value) (!(value & BIT(id))) + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static struct as7816_64x_psu_data *as7816_64x_psu_update_device(struct device *dev); +extern int accton_i2c_cpld_read (u8 cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7816_64x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ +}; + +enum as7816_64x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as7816_64x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7816_64x_psu_data *data = as7816_64x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return -EIO; + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static const struct attribute_group as7816_64x_psu_group = { + .attrs = as7816_64x_psu_attributes, +}; + +static int as7816_64x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7816_64x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7816_64x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7816_64x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7816_64x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7816_64x_psu_remove(struct i2c_client *client) +{ + struct as7816_64x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7816_64x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7816_64x_psu1, + as7816_64x_psu2 +}; + +static const struct i2c_device_id as7816_64x_psu_id[] = { + { "as7816_64x_psu1", as7816_64x_psu1 }, + { "as7816_64x_psu2", as7816_64x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7816_64x_psu_id); + +static struct i2c_driver as7816_64x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7816_64x_psu", + }, + .probe = as7816_64x_psu_probe, + .remove = as7816_64x_psu_remove, + .id_table = as7816_64x_psu_id, + .address_list = normal_i2c, +}; + +static struct as7816_64x_psu_data *as7816_64x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7816_64x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + + data->valid = 0; + dev_dbg(&client->dev, "Starting as7816_64x update\n"); + + /* Read psu status */ + status = accton_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7816_64x_psu_init(void) +{ + return i2c_add_driver(&as7816_64x_psu_driver); +} + +static void __exit as7816_64x_psu_exit(void) +{ + i2c_del_driver(&as7816_64x_psu_driver); +} + +module_init(as7816_64x_psu_init); +module_exit(as7816_64x_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7816_64x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-sfp.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-sfp.c new file mode 100644 index 000000000000..76444ebbafcb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/x86-64-accton-as7816-64x-sfp.c @@ -0,0 +1,1576 @@ +/* + * SFP driver for accton as7816_64x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "as7816_64x_sfp" /* Platform dependent */ + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_SFP_PORT 24 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +#define MULTIPAGE_SUPPORT 1 + +#if (MULTIPAGE_SUPPORT == 1) +/* fundamental unit of addressing for SFF_8472/SFF_8436 */ +#define SFF_8436_PAGE_SIZE 128 +/* + * The current 8436 (QSFP) spec provides for only 4 supported + * pages (pages 0-3). + * This driver is prepared to support more, but needs a register in the + * EEPROM to indicate how many pages are supported before it is safe + * to implement more pages in the driver. + */ +#define SFF_8436_SPECED_PAGES 4 +#define SFF_8436_EEPROM_SIZE ((1 + SFF_8436_SPECED_PAGES) * SFF_8436_PAGE_SIZE) +#define SFF_8436_EEPROM_UNPAGED_SIZE (2 * SFF_8436_PAGE_SIZE) +/* + * The current 8472 (SFP) spec provides for only 3 supported + * pages (pages 0-2). + * This driver is prepared to support more, but needs a register in the + * EEPROM to indicate how many pages are supported before it is safe + * to implement more pages in the driver. + */ +#define SFF_8472_SPECED_PAGES 3 +#define SFF_8472_EEPROM_SIZE ((3 + SFF_8472_SPECED_PAGES) * SFF_8436_PAGE_SIZE) +#define SFF_8472_EEPROM_UNPAGED_SIZE (4 * SFF_8436_PAGE_SIZE) + +/* a few constants to find our way around the EEPROM */ +#define SFF_8436_PAGE_SELECT_REG 0x7F +#define SFF_8436_PAGEABLE_REG 0x02 +#define SFF_8436_NOT_PAGEABLE (1<<2) +#define SFF_8472_PAGEABLE_REG 0x40 +#define SFF_8472_PAGEABLE (1<<4) + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = SFF_8436_PAGE_SIZE; + +/* + * specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; + +typedef enum qsfp_opcode { + QSFP_READ_OP = 0, + QSFP_WRITE_OP = 1 +} qsfp_opcode_e; +#endif + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +extern int accton_i2c_cpld_read (u8 cpld_addr, u8 reg); + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL +}; + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +as7816_64x_port1, as7816_64x_port2, as7816_64x_port3, as7816_64x_port4, +as7816_64x_port5, as7816_64x_port6, as7816_64x_port7, as7816_64x_port8, +as7816_64x_port9, as7816_64x_port10, as7816_64x_port11, as7816_64x_port12, +as7816_64x_port13, as7816_64x_port14, as7816_64x_port15, as7816_64x_port16, +as7816_64x_port17, as7816_64x_port18, as7816_64x_port19, as7816_64x_port20, +as7816_64x_port21, as7816_64x_port22, as7816_64x_port23, as7816_64x_port24, +as7816_64x_port25, as7816_64x_port26, as7816_64x_port27, as7816_64x_port28, +as7816_64x_port29, as7816_64x_port30, as7816_64x_port31, as7816_64x_port32, +as7816_64x_port33, as7816_64x_port34, as7816_64x_port35, as7816_64x_port36, +as7816_64x_port37, as7816_64x_port38, as7816_64x_port39, as7816_64x_port40, +as7816_64x_port41, as7816_64x_port42, as7816_64x_port43, as7816_64x_port44, +as7816_64x_port45, as7816_64x_port46, as7816_64x_port47, as7816_64x_port48, +as7816_64x_port49, as7816_64x_port50, as7816_64x_port51, as7816_64x_port52, +as7816_64x_port53, as7816_64x_port54, as7816_64x_port55, as7816_64x_port56, +as7816_64x_port57, as7816_64x_port58, as7816_64x_port59, as7816_64x_port60, +as7816_64x_port61, as7816_64x_port62, as7816_64x_port63, as7816_64x_port64 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { +I2C_DEV_ID(as7816_64x_port1), +I2C_DEV_ID(as7816_64x_port2), +I2C_DEV_ID(as7816_64x_port3), +I2C_DEV_ID(as7816_64x_port4), +I2C_DEV_ID(as7816_64x_port5), +I2C_DEV_ID(as7816_64x_port6), +I2C_DEV_ID(as7816_64x_port7), +I2C_DEV_ID(as7816_64x_port8), +I2C_DEV_ID(as7816_64x_port9), +I2C_DEV_ID(as7816_64x_port10), +I2C_DEV_ID(as7816_64x_port11), +I2C_DEV_ID(as7816_64x_port12), +I2C_DEV_ID(as7816_64x_port13), +I2C_DEV_ID(as7816_64x_port14), +I2C_DEV_ID(as7816_64x_port15), +I2C_DEV_ID(as7816_64x_port16), +I2C_DEV_ID(as7816_64x_port17), +I2C_DEV_ID(as7816_64x_port18), +I2C_DEV_ID(as7816_64x_port19), +I2C_DEV_ID(as7816_64x_port20), +I2C_DEV_ID(as7816_64x_port21), +I2C_DEV_ID(as7816_64x_port22), +I2C_DEV_ID(as7816_64x_port23), +I2C_DEV_ID(as7816_64x_port24), +I2C_DEV_ID(as7816_64x_port25), +I2C_DEV_ID(as7816_64x_port26), +I2C_DEV_ID(as7816_64x_port27), +I2C_DEV_ID(as7816_64x_port28), +I2C_DEV_ID(as7816_64x_port29), +I2C_DEV_ID(as7816_64x_port30), +I2C_DEV_ID(as7816_64x_port31), +I2C_DEV_ID(as7816_64x_port32), +I2C_DEV_ID(as7816_64x_port33), +I2C_DEV_ID(as7816_64x_port34), +I2C_DEV_ID(as7816_64x_port35), +I2C_DEV_ID(as7816_64x_port36), +I2C_DEV_ID(as7816_64x_port37), +I2C_DEV_ID(as7816_64x_port38), +I2C_DEV_ID(as7816_64x_port39), +I2C_DEV_ID(as7816_64x_port40), +I2C_DEV_ID(as7816_64x_port41), +I2C_DEV_ID(as7816_64x_port42), +I2C_DEV_ID(as7816_64x_port43), +I2C_DEV_ID(as7816_64x_port44), +I2C_DEV_ID(as7816_64x_port45), +I2C_DEV_ID(as7816_64x_port46), +I2C_DEV_ID(as7816_64x_port47), +I2C_DEV_ID(as7816_64x_port48), +I2C_DEV_ID(as7816_64x_port49), +I2C_DEV_ID(as7816_64x_port50), +I2C_DEV_ID(as7816_64x_port51), +I2C_DEV_ID(as7816_64x_port52), +I2C_DEV_ID(as7816_64x_port53), +I2C_DEV_ID(as7816_64x_port54), +I2C_DEV_ID(as7816_64x_port55), +I2C_DEV_ID(as7816_64x_port56), +I2C_DEV_ID(as7816_64x_port57), +I2C_DEV_ID(as7816_64x_port58), +I2C_DEV_ID(as7816_64x_port59), +I2C_DEV_ID(as7816_64x_port60), +I2C_DEV_ID(as7816_64x_port61), +I2C_DEV_ID(as7816_64x_port62), +I2C_DEV_ID(as7816_64x_port63), +I2C_DEV_ID(as7816_64x_port64), +{ /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); +/* Platform dependent --- */ + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP, + DRIVER_TYPE_XFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct qsfp_data *qsfp; + + struct i2c_client *client; +#if (MULTIPAGE_SUPPORT == 1) + int use_smbus; + u8 *writebuf; + unsigned write_max; +#endif +}; + +#if (MULTIPAGE_SUPPORT == 1) +static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, + char *buf, loff_t off, size_t len, qsfp_opcode_e opcode); +#endif +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +/* Platform dependent +++ */ +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77}; + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port 1~64 */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = accton_i2c_cpld_read(0x60, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); + data->present |= (u64)status << (i*8); + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +/* Platform dependent --- */ + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = sfp_update_present(client); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + return (data->present & BIT_INDEX(data->port)) ? 0 : 1; /* Platform dependent */ +} + +/* Platform dependent +++ */ +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if (PRESENT_ALL == attr->index) { + int i; + u8 values[8] = {0}; + struct sfp_port_data *data = sfp_update_present(client); + + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = ~(u8)(data->present >> (i * 8)); + } + + /* Return values 1 -> 64 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3], + values[4], values[5], values[6], values[7]); + } + else { + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + /* PRESENT */ + return sprintf(buf, "%d\n", present); + } +} +/* Platform dependent --- */ + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + DEBUG_PRINT("Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + int present; + u8 val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENXIO; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + switch (attr->index) { + case TX_FAULT: + val = !!(data->qsfp->status[2] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + case TX_DISABLE: + val = data->qsfp->status[1] & 0xF; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + case RX_LOS: + val = !!(data->qsfp->status[0] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); + break; + default: + break; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (!status) { + /* port is not present */ + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + mutex_lock(&data->update_lock); + + if (attr->index == TX_DISABLE) { + if (disable) { + data->qsfp->status[1] |= 0xF; + } + else { + data->qsfp->status[1] &= ~0xF; + } + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, command, *data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return 1; +#endif + + +} + +#if (MULTIPAGE_SUPPORT == 0) +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} +#endif + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + +#if (MULTIPAGE_SUPPORT == 1) + return sfp_port_read_write(data, buf, off, count, QSFP_WRITE_OP); +#else + return sfp_port_write(data, buf, off, count); +#endif +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return status; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + status = 1; + +abort: + return status; +#endif +} + +#if (MULTIPAGE_SUPPORT == 1) +/*-------------------------------------------------------------------------*/ +/* + * This routine computes the addressing information to be used for + * a given r/w request. + * + * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), + * the page, and the offset. + * + * Handles both SFP and QSFP. + * For SFP, offset 0-255 are on client[0], >255 is on client[1] + * Offset 256-383 are on the lower half of client[1] + * Pages are accessible on the upper half of client[1]. + * Offset >383 are in 128 byte pages mapped into the upper half + * + * For QSFP, all offsets are on client[0] + * offset 0-127 are on the lower half of client[0] (no paging) + * Pages are accessible on the upper half of client[1]. + * Offset >127 are in 128 byte pages mapped into the upper half + * + * Callers must not read/write beyond the end of a client or a page + * without recomputing the client/page. Hence offset (within page) + * plus length must be less than or equal to 128. (Note that this + * routine does not have access to the length of the call, hence + * cannot do the validity check.) + * + * Offset within Lower Page 00h and Upper Page 00h are not recomputed + */ +static uint8_t sff_8436_translate_offset(struct sfp_port_data *port_data, + loff_t *offset, struct i2c_client **client) +{ + unsigned page = 0; + + *client = port_data->client; + + /* + * if offset is in the range 0-128... + * page doesn't matter (using lower half), return 0. + * offset is already correct (don't add 128 to get to paged area) + */ + if (*offset < SFF_8436_PAGE_SIZE) + return page; + + /* note, page will always be positive since *offset >= 128 */ + page = (*offset >> 7)-1; + /* 0x80 places the offset in the top half, offset is last 7 bits */ + *offset = SFF_8436_PAGE_SIZE + (*offset & 0x7f); + + return page; /* note also returning client and offset */ +} + +static ssize_t sff_8436_eeprom_read(struct sfp_port_data *port_data, + struct i2c_client *client, + char *buf, unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + u8 msgbuf[2]; + unsigned long timeout, read_time; + int status, i; + + memset(msg, 0, sizeof(msg)); + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* + * When we have a better choice than SMBus calls, use a + * combined I2C message. Write address; then read up to + * io_limit data bytes. msgbuf is u8 and will cast to our + * needs. + */ + i = 0; + msgbuf[i++] = offset; + + msg[0].addr = client->addr; + msg[0].buf = msgbuf; + msg[0].len = i; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_read_i2c_block_data(client, offset, + count, buf); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; + if (count == 2) + buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_read_byte_data(client, offset); + if (status >= 0) { + buf[0] = status; + status = count; + } + break; + default: + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + status = count; + } + + dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) /* happy path */ + return count; + + if (status == -ENXIO) /* no module present */ + return status; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t sff_8436_eeprom_write(struct sfp_port_data *port_data, + struct i2c_client *client, + const char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page_start; + int i = 0; + + /* write max is at most a page + * (In this driver, write_max is actually one byte!) + */ + if (count > port_data->write_max) + count = port_data->write_max; + + /* shorten count if necessary to avoid crossing page boundary */ + next_page_start = roundup(offset + 1, SFF_8436_PAGE_SIZE); + if (offset + count > next_page_start) + count = next_page_start - offset; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + /*smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + break; + case I2C_SMBUS_WORD_DATA: + /* Check for odd length transaction */ + count = (count == 1) ? 1 : 2; + break; + case I2C_SMBUS_BYTE_DATA: + count = 1; + break; + default: + /* If we'll use I2C calls for I/O, set up the message */ + msg.addr = client->addr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = port_data->writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + break; + } + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + + switch (port_data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_write_i2c_block_data(client, + offset, count, buf); + if (status == 0) + status = count; + break; + case I2C_SMBUS_WORD_DATA: + if (count == 2) { + status = i2c_smbus_write_word_data(client, + offset, (u16)((buf[0])|(buf[1] << 8))); + } else { + /* count = 1 */ + status = i2c_smbus_write_byte_data(client, + offset, buf[0]); + } + if (status == 0) + status = count; + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_write_byte_data(client, offset, + buf[0]); + if (status == 0) + status = count; + break; + default: + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + break; + } + + dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", + count, offset, (long int) status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + + +static ssize_t sff_8436_eeprom_update_client(struct sfp_port_data *port_data, + char *buf, loff_t off, + size_t count, qsfp_opcode_e opcode) +{ + struct i2c_client *client; + ssize_t retval = 0; + u8 page = 0; + loff_t phy_offset = off; + int ret = 0; + + page = sff_8436_translate_offset(port_data, &phy_offset, &client); + + dev_dbg(&client->dev, + "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", + off, page, phy_offset, (long int) count, opcode); + if (page > 0) { + ret = sff_8436_eeprom_write(port_data, client, &page, + SFF_8436_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_dbg(&client->dev, + "Write page register for page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + + while (count) { + ssize_t status; + + if (opcode == QSFP_READ_OP) { + status = sff_8436_eeprom_read(port_data, client, + buf, phy_offset, count); + } else { + status = sff_8436_eeprom_write(port_data, client, + buf, phy_offset, count); + } + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + phy_offset += status; + count -= status; + retval += status; + } + + + if (page > 0) { + /* return the page register to page 0 (why?) */ + page = 0; + ret = sff_8436_eeprom_write(port_data, client, &page, + SFF_8436_PAGE_SELECT_REG, 1); + if (ret < 0) { + dev_err(&client->dev, + "Restore page register to page %d failed ret:%d!\n", + page, ret); + return ret; + } + } + return retval; +} + + +/* + * Figure out if this access is within the range of supported pages. + * Note this is called on every access because we don't know if the + * module has been replaced since the last call. + * If/when modules support more pages, this is the routine to update + * to validate and allow access to additional pages. + * + * Returns updated len for this access: + * - entire access is legal, original len is returned. + * - access begins legal but is too long, len is truncated to fit. + * - initial offset exceeds supported pages, return -EINVAL + */ +static ssize_t sff_8436_page_legal(struct sfp_port_data *port_data, + loff_t off, size_t len) +{ + struct i2c_client *client = port_data->client; + u8 regval; + int status; + size_t maxlen; + + if (off < 0) return -EINVAL; + if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { + /* SFP case */ + /* if no pages needed, we're good */ + if ((off + len) <= SFF_8472_EEPROM_UNPAGED_SIZE) return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= SFF_8472_EEPROM_SIZE) return -EINVAL; + /* in between, are pages supported? */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF_8472_PAGEABLE_REG, 1); + if (status < 0) return status; /* error out (no module?) */ + if (regval & SFF_8472_PAGEABLE) { + /* Pages supported, trim len to the end of pages */ + maxlen = SFF_8472_EEPROM_SIZE - off; + } else { + /* pages not supported, trim len to unpaged size */ + maxlen = SFF_8472_EEPROM_UNPAGED_SIZE - off; + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, SFP, off %lld len %ld\n", + off, (long int) len); + } + else if (port_data->driver_type == DRIVER_TYPE_QSFP || + port_data->driver_type == DRIVER_TYPE_XFP) { + /* QSFP case */ + /* if no pages needed, we're good */ + if ((off + len) <= SFF_8436_EEPROM_UNPAGED_SIZE) return len; + /* if offset exceeds possible pages, we're not good */ + if (off >= SFF_8436_EEPROM_SIZE) return -EINVAL; + /* in between, are pages supported? */ + status = sff_8436_eeprom_read(port_data, client, ®val, + SFF_8436_PAGEABLE_REG, 1); + if (status < 0) return status; /* error out (no module?) */ + if (regval & SFF_8436_NOT_PAGEABLE) { + /* pages not supported, trim len to unpaged size */ + maxlen = SFF_8436_EEPROM_UNPAGED_SIZE - off; + } else { + /* Pages supported, trim len to the end of pages */ + maxlen = SFF_8436_EEPROM_SIZE - off; + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, + "page_legal, QSFP, off %lld len %ld\n", + off, (long int) len); + } + else { + return -EINVAL; + } + return len; +} + + +static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, + char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) +{ + struct i2c_client *client = port_data->client; + int chunk; + int status = 0; + ssize_t retval; + size_t pending_len = 0, chunk_len = 0; + loff_t chunk_offset = 0, chunk_start_offset = 0; + + if (unlikely(!len)) + return len; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&port_data->update_lock); + + /* + * Confirm this access fits within the device suppored addr range + */ + len = sff_8436_page_legal(port_data, off, len); + if (len < 0) { + status = len; + goto err; + } + + /* + * For each (128 byte) chunk involved in this request, issue a + * separate call to sff_eeprom_update_client(), to + * ensure that each access recalculates the client/page + * and writes the page register as needed. + * Note that chunk to page mapping is confusing, is different for + * QSFP and SFP, and never needs to be done. Don't try! + */ + pending_len = len; /* amount remaining to transfer */ + retval = 0; /* amount transferred */ + for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { + + /* + * Compute the offset and number of bytes to be read/write + * + * 1. start at offset 0 (within the chunk), and read/write + * the entire chunk + * 2. start at offset 0 (within the chunk) and read/write less + * than entire chunk + * 3. start at an offset not equal to 0 and read/write the rest + * of the chunk + * 4. start at an offset not equal to 0 and read/write less than + * (end of chunk - offset) + */ + chunk_start_offset = chunk * SFF_8436_PAGE_SIZE; + + if (chunk_start_offset < off) { + chunk_offset = off; + if ((off + pending_len) < (chunk_start_offset + + SFF_8436_PAGE_SIZE)) + chunk_len = pending_len; + else + chunk_len = (chunk+1)*SFF_8436_PAGE_SIZE - off;/*SFF_8436_PAGE_SIZE - off;*/ + } else { + chunk_offset = chunk_start_offset; + if (pending_len > SFF_8436_PAGE_SIZE) + chunk_len = SFF_8436_PAGE_SIZE; + else + chunk_len = pending_len; + } + + dev_dbg(&client->dev, + "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", + off, (long int) len, chunk_start_offset, chunk_offset, + (long int) chunk_len, (long int) pending_len); + + /* + * note: chunk_offset is from the start of the EEPROM, + * not the start of the chunk + */ + status = sff_8436_eeprom_update_client(port_data, buf, + chunk_offset, chunk_len, opcode); + if (status != chunk_len) { + /* This is another 'no device present' path */ + dev_dbg(&client->dev, + "sff_8436_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", + chunk, chunk_offset, (long int) chunk_len, status); + goto err; + } + buf += status; + pending_len -= status; + retval += status; + } + mutex_unlock(&port_data->update_lock); + + return retval; + +err: + mutex_unlock(&port_data->update_lock); + + return status; +} + +#else +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} +#endif + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + +#if (MULTIPAGE_SUPPORT == 1) + return sfp_port_read_write(data, buf, off, count, QSFP_READ_OP); +#else + return sfp_port_read(data, buf, off, count); +#endif +} + +#if (MULTIPAGE_SUPPORT == 1) +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, size_t size) +#else +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +#endif +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; +#if (MULTIPAGE_SUPPORT == 1) + eeprom->size = size; +#else + eeprom->size = EEPROM_SIZE; +#endif + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + + +#if (MULTIPAGE_SUPPORT == 0) +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} +#endif + + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + +#if (MULTIPAGE_SUPPORT == 0) + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } +#endif + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ +#if (MULTIPAGE_SUPPORT == 1) + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, SFF_8436_EEPROM_SIZE); +#else + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); +#endif + if (status) { + goto exit_remove; + } + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +/* Platform dependent +++ */ +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int ret = 0; + struct sfp_port_data *data = NULL; + + if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { + return -ENODEV; + } + + if (dev_id->driver_data < as7816_64x_port1 || dev_id->driver_data > as7816_64x_port64) { + return -ENXIO; + } + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + +#if (MULTIPAGE_SUPPORT == 1) + data->use_smbus = 0; + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + data->use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) { + data->use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + data->use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + ret = -EPFNOSUPPORT; + goto exit_kfree; + } + } + + if (!data->use_smbus || + (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_WORD_DATA) || + i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + /* + * NOTE: AN-2079 + * Finisar recommends that the host implement 1 byte writes + * only since this module only supports 32 byte page boundaries. + * 2 byte writes are acceptable for PE and Vout changes per + * Application Note AN-2071. + */ + unsigned write_max = 1; + + if (write_max > io_limit) + write_max = io_limit; + if (data->use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + data->write_max = write_max; + + /* buffer (data + address at the beginning) */ + data->writebuf = kmalloc(write_max + 2, GFP_KERNEL); + if (!data->writebuf) { + ret = -ENOMEM; + goto exit_kfree; + } + } else { + dev_warn(&client->dev, + "cannot write due to controller restrictions."); + } + + if (data->use_smbus == I2C_SMBUS_WORD_DATA || + data->use_smbus == I2C_SMBUS_BYTE_DATA) { + dev_notice(&client->dev, "Falling back to %s reads, " + "performance will suffer\n", data->use_smbus == + I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } +#endif + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + data->driver_type = DRIVER_TYPE_QSFP; + + ret = qsfp_probe(client, dev_id, &data->qsfp); + if (ret < 0) { + goto exit_kfree_buf; + } + + return ret; + +exit_kfree_buf: +#if (MULTIPAGE_SUPPORT == 1) + if (data->writebuf) kfree(data->writebuf); +#endif + +exit_kfree: + kfree(data); + return ret; +} +/* Platform dependent --- */ + +static int qsfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + int ret = 0; + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (data->driver_type == DRIVER_TYPE_QSFP) { + ret = qsfp_remove(client, data->qsfp); + } + + kfree(data); + return ret; +} + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7816_64x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/ym2651y.c new file mode 120000 index 000000000000..f4d67640ccc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/ym2651y.c @@ -0,0 +1 @@ +../../common/modules/ym2651y.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-platform-init.service new file mode 100755 index 000000000000..486ed74f8243 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Accton AS7816-64X Platform initialization service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as7816_util.py install +ExecStart=/usr/local/bin/accton_as7816_monitor.py +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/setup.py new file mode 100755 index 000000000000..6633b9438b86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as7816_64x', + version='1.0', + description='Module to initialize Accton AS7816-64X platforms', + + packages=['as7816_64x'], + package_dir={'as7816_64x': 'as7816-64x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/README b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/README new file mode 100755 index 000000000000..0b9fc1633999 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/README @@ -0,0 +1,60 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +To initialize the system, run "accton_as7712_util.py install". +To clean up the drivers & devices, run "accton_as7712_util.py clean". +To dump information of sensors, run "accton_as7712_util.py show". +To dump SFP EEPROM, run "accton_as7712_util.py sff". +To set fan speed, run "accton_as7712_util.py set fan". +To enable/disable SFP emission, run "accton_as7712_util.py set sfp". +To set system LEDs' color, run "accton_as7712_util.py set led" +For more information, run "accton_as7712_util.py --help". + +==================================================================== +Besides applying accton_as7712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +LED controls can be found under /sys/class/leds. The sysfs interface +color mappings are as follows: +Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + +There are 5 system LEDs, loc, diag, fan, ps1, and ps2. +They are lit automatically by CPLD, but the loc and diag. +The loc led has only 1 color, blue. +The diag one has 3 colors: red, amber, and green. + +Fan controls can be found in /sys/bus/i2c/devices/2-0066. +There are 12 fans inside 6 fan modules. +All fans share 1 duty setting, ranged from 0~100. + +Three temperature sensors are controlled by the lm75 kernel modules. +They should already be visible under /sys/bus/i2c/drivers/lm75/. + +Two power supplies are controlled by the CPLD. +Here provide their status under +/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. + +There are 32 QSFP+ modules are equipped. +Apply "accton_as7712_util.py show" to get their status. +Apply "accton_as7712_util.py set sfp" to turn on/off light transmission. +Apply "accton_as7712_util.py sff" to dump EEPROM information. +Before operating on that QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_monitor.py new file mode 100755 index 000000000000..217351ad2a3c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_monitor.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import time # this is only being used as part of the example + import signal + from as7816_64x.fanutil import FanUtil + from as7816_64x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7816_monitor' +DUTY_MAX = 100 +DUTY_DEF = 40 + +global log_file +global log_level + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7816_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + + self.thermal = ThermalUtil() + self.fan = FanUtil() + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + max_duty = DUTY_MAX + fan_policy = { + 0: [52, 0, 43000], + 1: [63, 43000, 46000], + 2: [75, 46000, 52000], + 3: [88, 52000, 57000], + 4: [max_duty, 57000, sys.maxsize], + } + + thermal = self.thermal + fan = self.fan + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + return False + if fan_status is False: + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + fan.set_fan_duty_cycle(max_duty) + return True + #logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + #Find if current duty matched any of define duty. + #If not, set it to highest one. + cur_duty_cycle = fan.get_fan_duty_cycle() + new_duty_cycle = DUTY_DEF + for x in range(0, len(fan_policy)): + if cur_duty_cycle == fan_policy[x][0]: + break + if x == len(fan_policy) : + fan.set_fan_duty_cycle(fan_policy[0][0]) + cur_duty_cycle = max_duty + + #Decide fan duty by if sum of sensors falls into any of fan_policy{} + get_temp = thermal.get_thermal_temp() + for x in range(0, len(fan_policy)): + y = len(fan_policy) - x -1 #checked from highest + if get_temp > fan_policy[y][1] and get_temp < fan_policy[y][2] : + new_duty_cycle = fan_policy[y][0] + logging.debug('INFO. Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + + logging.debug('INFO. Final duty_cycle=%d', new_duty_cycle) + if(new_duty_cycle != cur_duty_cycle): + fan.set_fan_duty_cycle(new_duty_cycle) + return True + +def handler(signum, frame): + fan = FanUtil() + logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) + monitor = accton_as7816_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_util.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_util.py new file mode 100755 index 000000000000..3aae150dad5c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_util.py @@ -0,0 +1,558 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + + + +PROJECT_NAME = 'as7816_64x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':4,'thermal':6, 'psu':2, 'sfp':64} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-64 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def dis_i2c_ir3570a(addr): + cmd = "i2cset -y 0 0x%x 0xE5 0x01" % addr + status, output = commands.getstatusoutput(cmd) + cmd = "i2cset -y 0 0x%x 0x12 0x02" % addr + status, output = commands.getstatusoutput(cmd) + return status + +def ir3570_check(): + cmd = "i2cdump -y 0 0x42 s 0x9a" + try: + status, output = commands.getstatusoutput(cmd) + lines = output.split('\n') + hn = re.findall(r'\w+', lines[-1]) + version = int(hn[1], 16) + if version == 0x24: #only for ir3570a + ret = dis_i2c_ir3570a(4) + else: + ret = 0 + except Exception as e: + print "Error on ir3570_check() e:" + str(e) + return -1 + return ret + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-64 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe optoe', +'modprobe accton_i2c_cpld' , +'modprobe ym2651y' , +'modprobe x86-64-accton-as7816-64x-fan' , +#'modprobe x86-64-accton-as7816-64x-sfp' , +'modprobe x86-64-accton-as7816-64x-leds' , +'modprobe x86-64-accton-as7816-64x-psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + #remove parameter if any + rm = kos[-(i+1)] + lst = rm.split(" ") + if len(lst) > 2: + del(lst[2:]) + rm = " ".join(lst) + + #Change to removing commands + rm = rm.replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['17-0068'] , + 'thermal': ['18-0048','18-0049', '18-004a' , '18-004b', '17-004d', '17-004e'] , + 'psu': ['10-0053','9-0050'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present', 'psu_power_good'] , + 'sfp': ['module_present']} + +sfp_map = [37,38,39,40,42,41,44,43,33,34,35,36,45,46,47,48,49,50,51,52, + 61,62,63,64,53,54,55,56,57,58,59,60,69,70,71,72,77,78,79,80,65, + 66,67,68,73,74,75,76,85,86,87,88,31,32,29,30,81,82,83,84,25,26, + 27,28] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo as7816_64x_psu1 0x53 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2851 0x5b > /sys/bus/i2c/devices/i2c-10/new_device', +'echo as7816_64x_psu2 0x50 > /sys/bus/i2c/devices/i2c-9/new_device', +'echo ym2851 0x58 > /sys/bus/i2c/devices/i2c-9/new_device', +'echo as7816_64x_fan 0x68 > /sys/bus/i2c/devices/i2c-17/new_device', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4d > /sys/bus/i2c/devices/i2c-17/new_device', +'echo lm75 0x4e > /sys/bus/i2c/devices/i2c-17/new_device', +'echo cpld_as7816 0x60 > /sys/bus/i2c/devices/i2c-19/new_device', +'echo cpld_plain 0x62 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo cpld_plain 0x64 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo cpld_plain 0x66 > /sys/bus/i2c/devices/i2c-22/new_device'] + +def i2c_order_check(): + return 0 + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + path = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device" + status, output =log_os_system("echo optoe1 0x50 > " + path, 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + + ir3570_check() + + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + fmt = i2c_prefix+"19-0060/{0}_{1}" + path = fmt.format(nodes[j], k+1) + + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + i = int(index)-1 + node = i2c_prefix+ str(sfp_map[i])+ i2c_bus['sfp'][0]+"/"+ 'eeprom' + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system(hex_cmd +" -C "+node, 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0076", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py new file mode 100755 index 000000000000..52889cd5895d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/fanutil.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python +# Copyright (c) 2019 Edgecore Networks Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. +# +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 8/27/2019:Jostar craete for as9716_32d +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 6 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + FAN_NUM_5_IDX = 5 + FAN_NUM_6_IDX = 6 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + FAN_NODE_DIR_IDX_OF_MAP = 2 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/17-0066/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/17-0066/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + + (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault', + (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction', + + (FAN_NUM_6_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan6_fault', + (FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction', + } + + def _get_fan_device_node(self, fan_num, node_num): + return self._fan_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_device_path_mapping) + + def get_fan_device_path(self, fan_num, node_num): + return self._fan_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + + def set_fan_duty_cycle(self, val): + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + fan_file.write(str(val)) + fan_file.close() + return True + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py new file mode 100755 index 000000000000..abbc5e819a8a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/classes/thermalutil.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# Copyright (c) 2019 Edgecore Networks Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. +# +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 8/27/2019:Jostar craete for as9716_32d +# ------------------------------------------------------------------ + +try: + import os + import time + import logging + import glob + import commands + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + THERMAL_NUM_MAX = 8 + THERMAL_NUM_1_IDX = 1 # 1~7 are mainboard thermal sensors + THERMAL_NUM_2_IDX = 2 + THERMAL_NUM_3_IDX = 3 + THERMAL_NUM_4_IDX = 4 + THERMAL_NUM_5_IDX = 5 + THERMAL_NUM_6_IDX = 6 + THERMAL_NUM_7_IDX = 7 # CPU core + THERMAL_NUM_8_IDX = 8 + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + #_thermal_to_device_path_mapping = {} + + thermal_sysfspath ={ + THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/18-0048/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/18-0049/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/18-004a/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/18-004c/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_5_IDX: ["/sys/bus/i2c/devices/18-004e/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_6_IDX: ["/sys/bus/i2c/devices/18-004f/hwmon/hwmon*/temp1_input"], + THERMAL_NUM_7_IDX: ["/sys/class/hwmon/hwmon0/temp1_input"], + THERMAL_NUM_8_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon*/temp1_input"], + } + + #def __init__(self): + + def _get_thermal_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + content = val_file.readline().rstrip() + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + return 0 + + def get_num_thermals(self): + return self.THERMAL_NUM_MAX + + def get_size_path_map(self): + return len(self.thermal_sysfspath) + + def get_thermal_path(self, thermal_num): + return self.thermal_sysfspath[thermal_num][0] + + +def main(): + thermal = ThermalUtil() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile new file mode 100755 index 000000000000..be04fc82cb59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/Makefile @@ -0,0 +1,19 @@ +ifneq ($(KERNELRELEASE),) +obj-m:= accton_as9716_32d_cpld.o accton_as9716_32d_fan.o \ + accton_as9716_32d_leds.o accton_as9716_32d_psu.o accton_i2c_psu.o + +else +ifeq (,$(KERNEL_SRC)) +#$(error KERNEL_SRC is not defined) +KVERSION=3.16.0-8-amd64 +KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ +KERNELDIR:=$(KERNEL_DIR) +else +KERNELDIR:=$(KERNEL_SRC) +endif +PWD:=$(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +clean: + rm -rf *.o *.mod.o *.mod.o *.ko .*cmd *.mod.c .tmp_versions Module.markers Module.symvers modules.order +endif diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c new file mode 100755 index 000000000000..d473bb452411 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_cpld.c @@ -0,0 +1,974 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as9716_32d CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as9716_32d_fpga, + as9716_32d_cpld1, + as9716_32d_cpld2, + as9716_32d_cpld_cpu +}; + +struct as9716_32d_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as9716_32d_cpld_id[] = { + { "as9716_32d_fpga", as9716_32d_fpga }, + { "as9716_32d_cpld1", as9716_32d_cpld1 }, + { "as9716_32d_cpld2", as9716_32d_cpld2 }, + { "as9716_32d_cpld_cpu", as9716_32d_cpld_cpu }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index +#define CPLD_INTR_ATTR_ID(index) CPLD_INTR_##index + +enum as9716_32d_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_RESET_ATTR_ID(1), + TRANSCEIVER_RESET_ATTR_ID(2), + TRANSCEIVER_RESET_ATTR_ID(3), + TRANSCEIVER_RESET_ATTR_ID(4), + TRANSCEIVER_RESET_ATTR_ID(5), + TRANSCEIVER_RESET_ATTR_ID(6), + TRANSCEIVER_RESET_ATTR_ID(7), + TRANSCEIVER_RESET_ATTR_ID(8), + TRANSCEIVER_RESET_ATTR_ID(9), + TRANSCEIVER_RESET_ATTR_ID(10), + TRANSCEIVER_RESET_ATTR_ID(11), + TRANSCEIVER_RESET_ATTR_ID(12), + TRANSCEIVER_RESET_ATTR_ID(13), + TRANSCEIVER_RESET_ATTR_ID(14), + TRANSCEIVER_RESET_ATTR_ID(15), + TRANSCEIVER_RESET_ATTR_ID(16), + TRANSCEIVER_RESET_ATTR_ID(17), + TRANSCEIVER_RESET_ATTR_ID(18), + TRANSCEIVER_RESET_ATTR_ID(19), + TRANSCEIVER_RESET_ATTR_ID(20), + TRANSCEIVER_RESET_ATTR_ID(21), + TRANSCEIVER_RESET_ATTR_ID(22), + TRANSCEIVER_RESET_ATTR_ID(23), + TRANSCEIVER_RESET_ATTR_ID(24), + TRANSCEIVER_RESET_ATTR_ID(25), + TRANSCEIVER_RESET_ATTR_ID(26), + TRANSCEIVER_RESET_ATTR_ID(27), + TRANSCEIVER_RESET_ATTR_ID(28), + TRANSCEIVER_RESET_ATTR_ID(29), + TRANSCEIVER_RESET_ATTR_ID(30), + TRANSCEIVER_RESET_ATTR_ID(31), + TRANSCEIVER_RESET_ATTR_ID(32), + CPLD_INTR_ATTR_ID(1), + CPLD_INTR_ATTR_ID(2), + CPLD_INTR_ATTR_ID(3), + CPLD_INTR_ATTR_ID(4), + +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_interrupt(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int as9716_32d_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +/*reset*/ +#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, MODULE_RESET_##index) +#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr + +/*cpld interrupt*/ +#define DECLARE_CPLD_DEVICE_INTR_ATTR(index) \ + static SENSOR_DEVICE_ATTR(cpld_intr_##index, S_IRUGO, show_interrupt, NULL, CPLD_INTR_##index) +#define DECLARE_CPLD_INTR_ATTR(index) &sensor_dev_attr_cpld_intr_##index.dev_attr.attr + + + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(1); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(2); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(3); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(4); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(5); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(6); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(7); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(8); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(9); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(10); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(11); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(12); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(13); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(14); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(15); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(16); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(17); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(18); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(19); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(20); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(21); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(22); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(23); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(24); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(25); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(26); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(27); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(28); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(29); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(30); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(31); +DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(32); +DECLARE_CPLD_DEVICE_INTR_ATTR(1); +DECLARE_CPLD_DEVICE_INTR_ATTR(2); +DECLARE_CPLD_DEVICE_INTR_ATTR(3); +DECLARE_CPLD_DEVICE_INTR_ATTR(4); + + + +static struct attribute *as9716_32d_fpga_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as9716_32d_fpga_group = { + .attrs = as9716_32d_fpga_attributes, +}; + +static struct attribute *as9716_32d_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_RESET_ATTR(1), + DECLARE_TRANSCEIVER_RESET_ATTR(2), + DECLARE_TRANSCEIVER_RESET_ATTR(3), + DECLARE_TRANSCEIVER_RESET_ATTR(4), + DECLARE_TRANSCEIVER_RESET_ATTR(5), + DECLARE_TRANSCEIVER_RESET_ATTR(6), + DECLARE_TRANSCEIVER_RESET_ATTR(7), + DECLARE_TRANSCEIVER_RESET_ATTR(8), + DECLARE_TRANSCEIVER_RESET_ATTR(9), + DECLARE_TRANSCEIVER_RESET_ATTR(10), + DECLARE_TRANSCEIVER_RESET_ATTR(11), + DECLARE_TRANSCEIVER_RESET_ATTR(12), + DECLARE_TRANSCEIVER_RESET_ATTR(13), + DECLARE_TRANSCEIVER_RESET_ATTR(14), + DECLARE_TRANSCEIVER_RESET_ATTR(15), + DECLARE_TRANSCEIVER_RESET_ATTR(16), + DECLARE_CPLD_INTR_ATTR(1), + DECLARE_CPLD_INTR_ATTR(2), + NULL +}; + +static const struct attribute_group as9716_32d_cpld1_group = { + .attrs = as9716_32d_cpld1_attributes, +}; + +static struct attribute *as9716_32d_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_TRANSCEIVER_RESET_ATTR(17), + DECLARE_TRANSCEIVER_RESET_ATTR(18), + DECLARE_TRANSCEIVER_RESET_ATTR(19), + DECLARE_TRANSCEIVER_RESET_ATTR(20), + DECLARE_TRANSCEIVER_RESET_ATTR(21), + DECLARE_TRANSCEIVER_RESET_ATTR(22), + DECLARE_TRANSCEIVER_RESET_ATTR(23), + DECLARE_TRANSCEIVER_RESET_ATTR(24), + DECLARE_TRANSCEIVER_RESET_ATTR(25), + DECLARE_TRANSCEIVER_RESET_ATTR(26), + DECLARE_TRANSCEIVER_RESET_ATTR(27), + DECLARE_TRANSCEIVER_RESET_ATTR(28), + DECLARE_TRANSCEIVER_RESET_ATTR(29), + DECLARE_TRANSCEIVER_RESET_ATTR(30), + DECLARE_TRANSCEIVER_RESET_ATTR(31), + DECLARE_TRANSCEIVER_RESET_ATTR(32), + DECLARE_CPLD_INTR_ATTR(3), + DECLARE_CPLD_INTR_ATTR(4), + NULL +}; + +static const struct attribute_group as9716_32d_cpld2_group = { + .attrs = as9716_32d_cpld2_attributes, +}; + + +static ssize_t show_interrupt(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0; + + switch (attr->index) + { + case CPLD_INTR_1: + reg = 0x10; + break; + case CPLD_INTR_3: + reg = 0x10; + break; + case CPLD_INTR_2: + reg = 0x11; + break; + case CPLD_INTR_4: + reg = 0x11; + break; + default: + return -ENODEV; + } + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "0x%x\n", status); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x13; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33: + reg = 0x20; + mask = 0x1; + break; + case MODULE_PRESENT_34: + reg = 0x20; + mask = 0x8; + break; + case MODULE_RXLOS_33: + reg = 0x20; + mask = 0x2; + break; + case MODULE_RXLOS_34: + reg = 0x20; + mask = 0x10; + break; + case MODULE_TXDISABLE_33: + reg = 0x21; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x21; + mask = 0x2; + break; + + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_34) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_33: + reg = 0x21; + mask = 0x1; + break; + case MODULE_TXDISABLE_34: + reg = 0x21; + mask = 0x2; + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as9716_32d_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as9716_32d_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as9716_32d_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_mode_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + + + mutex_lock(&data->update_lock); + status = as9716_32d_cpld_read_internal(client, reg); + + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\r\n", !(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_mode_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + long reset; + int status=0, val, error; + u8 reg = 0, mask = 0; + + + error = kstrtol(buf, 10, &reset); + if (error) { + return error; + } + + switch (attr->index) { + case MODULE_RESET_1 ... MODULE_RESET_8: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_1); + break; + case MODULE_RESET_9 ... MODULE_RESET_16: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_9); + break; + case MODULE_RESET_17 ... MODULE_RESET_24: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_RESET_17); + break; + case MODULE_RESET_25 ... MODULE_RESET_32: + reg = 0x15; + mask = 0x1 << (attr->index - MODULE_RESET_25); + break; + default: + return 0; + } + mutex_lock(&data->update_lock); + + status = as9716_32d_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update lp_mode status */ + if (reset) + { + val = status&(~mask); + } + else + { + val =status | (mask); + } + + status = as9716_32d_cpld_write_internal(client, reg, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + + + +/* + * I2C init/probing/exit functions + */ +static int as9716_32d_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as9716_32d_cpld_data *data; + int ret = -ENODEV; + int status; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as9716_32d_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + + /* Register sysfs hooks */ + switch (data->type) { + case as9716_32d_fpga: + group = &as9716_32d_fpga_group; + break; + case as9716_32d_cpld1: + group = &as9716_32d_cpld1_group; + /*Set interrupt mask to 0, and then can get intr from 0x8*/ + status=as9716_32d_cpld_write_internal(client, 0x9, 0x0); + if (status < 0) + { + dev_dbg(&client->dev, "cpld1 reg 0x9 err %d\n", status); + } + break; + case as9716_32d_cpld2: + group = &as9716_32d_cpld2_group; + /*Set interrupt mask to 0, and then can get intr from 0x8*/ + status=as9716_32d_cpld_write_internal(client, 0x9, 0x0); + if (status < 0) + { + dev_dbg(&client->dev, "cpld2 reg 0x65 err %d\n", status); + } + break; + case as9716_32d_cpld_cpu: + /* Disable CPLD reset to avoid DUT will be reset. + */ + status=as9716_32d_cpld_write_internal(client, 0x3, 0x0); + if (status < 0) + { + dev_dbg(&client->dev, "cpu_cpld reg 0x65 err %d\n", status); + } + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as9716_32d_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as9716_32d_cpld_remove(struct i2c_client *client) +{ + struct as9716_32d_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as9716_32d_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as9716_32d_fpga: + group = &as9716_32d_fpga_group; + break; + case as9716_32d_cpld1: + group = &as9716_32d_cpld1_group; + break; + case as9716_32d_cpld2: + group = &as9716_32d_cpld2_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as9716_32d_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as9716_32d_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as9716_32d_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as9716_32d_cpld_read); + +int as9716_32d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as9716_32d_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as9716_32d_cpld_write); + +static struct i2c_driver as9716_32d_cpld_driver = { + .driver = { + .name = "as9716_32d_cpld", + .owner = THIS_MODULE, + }, + .probe = as9716_32d_cpld_probe, + .remove = as9716_32d_cpld_remove, + .id_table = as9716_32d_cpld_id, +}; + +static int __init as9716_32d_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as9716_32d_cpld_driver); +} + +static void __exit as9716_32d_cpld_exit(void) +{ + i2c_del_driver(&as9716_32d_cpld_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as9716_32d_cpld_init); +module_exit(as9716_32d_cpld_exit); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c new file mode 100755 index 000000000000..4d2433e7981e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_fan.c @@ -0,0 +1,760 @@ +/* + * A hwmon driver for the Accton as9716 32d fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as9716_32d_fan" + +#define NUM_THERMAL_SENSORS (7) /* Get sum of this number of sensors.*/ +#define THERMAL_SENSORS_DRIVER "lm75" +#define THERMAL_SENSORS_ADDRS {0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4c , 0x4e} + +static struct as9716_32d_fan_data *as9716_32d_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, char *buf); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x11, /* fan PWM(for all fan) */ + 0x12, /* front fan 1 speed(rpm) */ + 0x13, /* front fan 2 speed(rpm) */ + 0x14, /* front fan 3 speed(rpm) */ + 0x15, /* front fan 4 speed(rpm) */ + 0x16, /* front fan 5 speed(rpm) */ + 0x17, /* front fan 6 speed(rpm) */ + 0x22, /* rear fan 1 speed(rpm) */ + 0x23, /* rear fan 2 speed(rpm) */ + 0x24, /* rear fan 3 speed(rpm) */ + 0x25, /* rear fan 4 speed(rpm) */ + 0x26, /* rear fan 5 speed(rpm) */ + 0x27, /* rear fan 6 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as9716_32d_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ + int system_temp; /*In unit of mini-Celsius*/ + int sensors_found; +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, + FAN6_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) + +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR() \ + static SENSOR_DEVICE_ATTR(sys_temp, S_IRUGO, get_sys_temp, NULL, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_SYSTEM_TEMP_ATTR() &sensor_dev_attr_sys_temp.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6,16); + +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5,15); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6,16); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); +/* System temperature for fancontrol */ +DECLARE_FAN_SYSTEM_TEMP_SENSOR_DEV_ATTR(); + +static struct attribute *as9716_32d_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_FAULT_ATTR(5,15), + DECLARE_FAN_FAULT_ATTR(6,16), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(5,15), + DECLARE_FAN_SPEED_RPM_ATTR(6,16), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_SYSTEM_TEMP_ATTR(), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int as9716_32d_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as9716_32d_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return ((u32)(reg_val+1) * 625 + 75)/ 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct as9716_32d_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + as9716_32d_fan_write_value(client, 0x33, 0); /* Disable fan speed watch dog */ + as9716_32d_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +/* Due to this struct is declared at lm75.c, it cannot be include + * under Sonic environment. I duplicate it from lm75.c. + */ +struct lm75_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct thermal_zone_device *tz; + struct mutex update_lock; + u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, + 0 = input + 1 = max + 2 = hyst */ +}; + +/*Copied from lm75.c*/ +static inline long lm75_reg_to_mc(s16 temp, u8 resolution) +{ + return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8); +} + +/*Get hwmon_dev from i2c_client, set hwmon_dev = NULL is failed.*/ +static struct device * get_hwmon_dev( + struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if(data) + { + if( data->valid == 1 && data->hwmon_dev) + { + return data->hwmon_dev; + } + + } + return NULL; +} + +/* To find hwmon index by opening hwmon under that i2c address. + */ +static int find_hwmon_index_by_FileOpen( + int bus_nr, + unsigned short addr, + int *index) +{ +#define MAX_HWMON_DEVICE (10) /* Find hwmon device in 0~10*/ + struct file *sfd; + char client_name[96]; + int i=0; + + do { + snprintf(client_name, sizeof(client_name), + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + + sfd = filp_open(client_name, O_RDONLY, 0); + i++; + } while( IS_ERR(sfd) && i < MAX_HWMON_DEVICE); + + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", client_name, __LINE__); + return -ENOENT; + } + filp_close(sfd, 0); + *index = i - 1; + return 0; + +#undef MAX_HWMON_DEVICE +} + +static int get_temp_file_path( + int bus_nr, unsigned short addr, + struct device *hwmon_dev + ,char *path, int max_len) +{ + + if(hwmon_dev && strlen(dev_name(hwmon_dev))) + { + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/%s/temp1_input", + bus_nr, addr, dev_name(hwmon_dev)); + } + else + { + int i=0; + if(find_hwmon_index_by_FileOpen( bus_nr, addr, &i)) + { + return -EIO; + } + snprintf(path, max_len, + "/sys/bus/i2c/devices/%d-%04x/hwmon/hwmon%d/temp1_input", + bus_nr, addr, i); + } + + return 0; +} + +/*File read the dev file at user space.*/ +static int read_devfile_temp1_input( + struct device *dev, + int bus_nr, + unsigned short addr, + struct device *hwmon_dev, + int *miniCelsius) +{ + struct file *sfd; + char buffer[96]; + char devfile[96]; + int rc, status; + int rdlen, value; + mm_segment_t old_fs; + + rc = 0; + get_temp_file_path(bus_nr, addr, hwmon_dev, devfile, sizeof(devfile)); + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + pr_err("Failed to open file(%s)#%d\r\n", devfile, __LINE__); + return -ENOENT; + } + dev_dbg(dev, "Found device:%s\n",devfile); + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + pr_err("file %s cann't readable ?\n",devfile); + return -ENOENT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + pr_err( "File(%s) empty!\n", devfile); + rc = -EIO; + goto exit; + } + status = sscanf(buffer, "%d", &value); + if (status != 1) { + rc = -EIO; + goto exit; + } + *miniCelsius = value; + dev_dbg(dev,"found sensors: %d @i2c %d-%04x\n", value, bus_nr, addr); + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + return rc; +} + +static u8 is_lm75_data_due(struct i2c_client *client) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + if (time_after(jiffies, data->last_updated + data->sample_time)) + { + return 1; + } + return 0; +} +static int get_lm75_temp(struct i2c_client *client, int *miniCelsius) +{ + struct lm75_data *data = NULL; + + data = i2c_get_clientdata(client); + *miniCelsius = lm75_reg_to_mc(data->temp[0], data->resolution); + + return 0; +} + +static bool lm75_addr_mached(unsigned short addr) +{ + int i; + unsigned short addrs[] = THERMAL_SENSORS_ADDRS; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) + { + if( addr == addrs[i]) + return 1; + } + return 0; +} + +static int _find_lm75_device(struct device *dev, void *data) +{ + struct device_driver *driver; + struct as9716_32d_fan_data *prv = data; + char *driver_name = THERMAL_SENSORS_DRIVER; + + driver = dev->driver; + if (driver && driver->name && + strcmp(driver->name, driver_name) == 0) + { + struct i2c_client *client; + client = to_i2c_client(dev); + if (client) + { + /*cannot use "struct i2c_adapter *adap = to_i2c_adapter(dev);"*/ + struct i2c_adapter *adap = client->adapter; + int miniCelsius = 0; + + if (! lm75_addr_mached(client->addr)) + { + return 0; + } + + if (!adap) { + return -ENXIO; + } + + /* If the data is not updated, read them from devfile + to drive them updateing data from chip.*/ + if (is_lm75_data_due(client)) + { + struct device *hwmon_dev; + + hwmon_dev = get_hwmon_dev(client); + if(0 == read_devfile_temp1_input(dev, adap->nr, + client->addr, hwmon_dev, &miniCelsius)) + { + prv->system_temp += miniCelsius; + prv->sensors_found++; + } + + } + else + { + get_lm75_temp(client, &miniCelsius); + prv->system_temp += miniCelsius; + prv->sensors_found++; + + } + } + } + return 0; +} + +/*Find all lm75 devices and return sum of temperatures.*/ +static ssize_t get_sys_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + ssize_t ret = 0; + struct as9716_32d_fan_data *data = as9716_32d_fan_update_device(dev); + + data->system_temp=0; + data->sensors_found=0; + i2c_for_each_dev(data, _find_lm75_device); + if (NUM_THERMAL_SENSORS != data->sensors_found) + { + dev_dbg(dev,"only %d of %d temps are found\n", + data->sensors_found, NUM_THERMAL_SENSORS); + data->system_temp = INT_MAX; + } + ret = sprintf(buf, "%d\n",data->system_temp); + return ret; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_fan_data *data = as9716_32d_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as9716_32d_fan_group = { + .attrs = as9716_32d_fan_attributes, +}; + +static struct as9716_32d_fan_data *as9716_32d_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as9716_32d_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as9716_32d_fan_read_value(client, fan_reg[i]); + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as9716_32d_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as9716_32d_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as9716_32d_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as9716_32d_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as9716_32d_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as9716_32d_fan_remove(struct i2c_client *client) +{ + struct as9716_32d_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as9716_32d_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as9716_32d_fan_id[] = { + { "as9716_32d_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_fan_id); + +static struct i2c_driver as9716_32d_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as9716_32d_fan_probe, + .remove = as9716_32d_fan_remove, + .id_table = as9716_32d_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as9716_32d_fan_driver); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("as9716_32d_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c new file mode 100755 index 000000000000..0fd28a4631b2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_leds.c @@ -0,0 +1,492 @@ +/* + * A LED driver for the accton_as9716_32d_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int as9716_32d_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as9716_32d_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#define DRVNAME "accton_as9716_32d_led" + +struct accton_as9716_32d_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[2]; /* only 1 register*/ +}; + +static struct accton_as9716_32d_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x61) + +#define LED_TYPE_DIAG_REG_MASK (0x1|0x2|0x4) +#define LED_MODE_DIAG_GREEN_VALUE (0x01) +#define LED_MODE_DIAG_AMBER_VALUE (0x02) /*It's yellow actually. Green+Red=Yellow*/ +#define LED_MODE_DIAG_GREEN_BLINK_VALUE (0x04) +#define LED_MODE_DIAG_OFF_VALUE (0x0) + + +#define LED_TYPE_LOC_REG_MASK (0x80|0x40) +#define LED_MODE_LOC_GREEN_BLIKN_VALUE 0x80 +#define LED_MODE_LOC_AMBER_VALUE 0x40 +#define LED_MODE_LOC_OFF_VALUE (0x0) + +#define LED_TYPE_FAN_REG_MASK (0x20|0x10) +#define LED_MODE_FAN_AMBER_VALUE 0x20 +#define LED_MODE_FAN_GREEN_VALUE 0x10 +#define LED_MODE_FAN_OFF_VALUE (0x0) + +#define LED_TYPE_PSU2_REG_MASK (0x8|0x4) +#define LED_MODE_PSU2_AMBER_VALUE 0x8 +#define LED_MODE_PSU2_GREEN_VALUE 0x4 +#define LED_MODE_PSU2_OFF_VALUE (0x0) + +#define LED_TYPE_PSU1_REG_MASK (0x2|0x1) +#define LED_MODE_PSU1_AMBER_VALUE 0x2 +#define LED_MODE_PSU1_GREEN_VALUE 0x1 +#define LED_MODE_PSU1_OFF_VALUE (0x0) + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as9716_32d_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_as9716_32d_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_as9716_32d_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + reg_val = accton_as9716_32d_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + + accton_as9716_32d_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_as9716_32d_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG); +} + +static enum led_brightness accton_as9716_32d_led_diag_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void accton_as9716_32d_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_as9716_32d_led_loc_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[1]); +} + +static void accton_as9716_32d_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_FAN); +} + +static enum led_brightness accton_as9716_32d_led_fan_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[1]); +} + +static void accton_as9716_32d_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_PSU1); +} + +static enum led_brightness accton_as9716_32d_led_psu1_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void accton_as9716_32d_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_as9716_32d_led_set(led_cdev, led_light_mode, LED_TYPE_PSU2); +} + +static enum led_brightness accton_as9716_32d_led_psu2_get(struct led_classdev *cdev) +{ + accton_as9716_32d_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static struct led_classdev accton_as9716_32d_leds[] = { + [LED_TYPE_DIAG] = { + .name = "accton_as9716_32d_led::diag", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_diag_set, + .brightness_get = accton_as9716_32d_led_diag_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN_BLINK, + }, + [LED_TYPE_LOC] = { + .name = "accton_as9716_32d_led::loc", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_loc_set, + .brightness_get = accton_as9716_32d_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN_BLINK, + }, + [LED_TYPE_FAN] = { + .name = "accton_as9716_32d_led::fan", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_fan_set, + .brightness_get = accton_as9716_32d_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU1] = { + .name = "accton_as9716_32d_led::psu1", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_psu1_set, + .brightness_get = accton_as9716_32d_led_psu1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU2] = { + .name = "accton_as9716_32d_led::psu2", + .default_trigger = "unused", + .brightness_set = accton_as9716_32d_led_psu2_set, + .brightness_get = accton_as9716_32d_led_psu2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, +}; + +static int accton_as9716_32d_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_suspend(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static int accton_as9716_32d_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_resume(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static int accton_as9716_32d_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_as9716_32d_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_as9716_32d_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_as9716_32d_leds[i]); + } + } + + return ret; +} + +static int accton_as9716_32d_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_as9716_32d_leds); i++) { + led_classdev_unregister(&accton_as9716_32d_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_as9716_32d_led_driver = { + .probe = accton_as9716_32d_led_probe, + .remove = accton_as9716_32d_led_remove, + .suspend = accton_as9716_32d_led_suspend, + .resume = accton_as9716_32d_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_as9716_32d_led_init(void) +{ + int ret; + + ret = platform_driver_register(&accton_as9716_32d_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_as9716_32d_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_as9716_32d_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&accton_as9716_32d_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit accton_as9716_32d_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_as9716_32d_led_driver); + kfree(ledctl); +} + +module_init(accton_as9716_32d_led_init); +module_exit(accton_as9716_32d_led_exit); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("accton_as9716_32d_led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c new file mode 100755 index 000000000000..06e8e23c3c53 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_as9716_32d_psu.c @@ -0,0 +1,311 @@ +/* + * An hwmon driver for accton as9716_32d Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODEL_NAME 16 +#define MAX_SERIAL_NUMBER 19 + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as9716_32d_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as9716_32d_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as9716_32d_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MAX_MODEL_NAME]; /* Model name, read from eeprom */ + char serial_number[MAX_SERIAL_NUMBER]; +}; + +static struct as9716_32d_psu_data *as9716_32d_psu_update_device(struct device *dev); + +enum as9716_32d_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + + +static struct attribute *as9716_32d_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_number.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_psu_data *data = as9716_32d_psu_update_device(dev); + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = !(data->status >> (1-data->index) & 0x1); + } + else { /* PSU_POWER_GOOD */ + status = (data->status >> (3-data->index) & 0x1); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as9716_32d_psu_data *data = as9716_32d_psu_update_device(dev); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + switch (attr->index) { + case PSU_MODEL_NAME: + ptr = data->model_name; + break; + case PSU_SERIAL_NUMBER: + ptr = data->serial_number; + break; + default: + return -EINVAL; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as9716_32d_psu_group = { + .attrs = as9716_32d_psu_attributes, +}; + +static int as9716_32d_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as9716_32d_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as9716_32d_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as9716_32d_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as9716_32d_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as9716_32d_psu_remove(struct i2c_client *client) +{ + struct as9716_32d_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as9716_32d_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as9716_32d_psu1, + as9716_32d_psu2 +}; + +static const struct i2c_device_id as9716_32d_psu_id[] = { + { "as9716_32d_psu1", as9716_32d_psu1 }, + { "as9716_32d_psu2", as9716_32d_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as9716_32d_psu_id); + +static struct i2c_driver as9716_32d_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as9716_32d_psu", + }, + .probe = as9716_32d_psu_probe, + .remove = as9716_32d_psu_remove, + .id_table = as9716_32d_psu_id, + .address_list = normal_i2c, +}; + +static int as9716_32d_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as9716_32d_psu_data *as9716_32d_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as9716_32d_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int power_good = 0; + + dev_dbg(&client->dev, "Starting as9716_32d update\n"); + + /* Read psu status */ + status = as9716_32d_cpld_read(0x60, 0x3); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + } + else { + data->status = status; + } + + /* Read model name */ + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial_number, 0, sizeof(data->serial_number)); + power_good = (data->status >> (3-data->index) & 0x1); + + if (power_good) { + status = as9716_32d_psu_read_block(client, 0x20, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + } + else { + data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + + } + /* Read from offset 0x2e ~ 0x3d (16 bytes) */ + status = as9716_32d_psu_read_block(client, 0x2e,data->serial_number, MAX_SERIAL_NUMBER); + if (status < 0) + { + data->serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x2e)\n", client->addr); + } + data->serial_number[MAX_SERIAL_NUMBER-1]='\0'; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(as9716_32d_psu_driver); + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("as9716_32d_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c new file mode 100755 index 000000000000..df7324de5604 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/modules/accton_i2c_psu.c @@ -0,0 +1,602 @@ +/* + * An hwmon driver for the Accton Redundant Power Module + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_DESCRIPTION_NAME "accton i2c psu driver" +/* PMBus Protocol. */ +#define PMBUS_LITERAL_DATA_MULTIPLIER 1000 +#define PMBUS_REGISTER_VOUT_MODE 0x20 +#define PMBUS_REGISTER_STATUS_BYTE 0x78 +#define PMBUS_REGISTER_STATUS_WORD 0x79 +#define PMBUS_REGISTER_STATUS_FAN 0x81 +#define PMBUS_REGISTER_READ_VIN 0x88 +#define PMBUS_REGISTER_READ_IIN 0x89 +#define PMBUS_REGISTER_READ_VOUT 0x8B +#define PMBUS_REGISTER_READ_IOUT 0x8C +#define PMBUS_REGISTER_READ_TEMPERATURE_1 0x8D +#define PMBUS_REGISTER_READ_TEMPERATURE_2 0x8E +#define PMBUS_REGISTER_READ_TEMPERATURE_3 0x8F +#define PMBUS_REGISTER_READ_FAN_SPEED_1 0x90 +#define PMBUS_REGISTER_READ_FAN_SPEED_2 0x91 + +#define PMBUS_REGISTER_READ_FAN_CONFIG_1 0x3A +#define PMBUS_REGISTER_FAN_COMMAND_1 0x3B + +#define PMBUS_REGISTER_READ_POUT 0x96 +#define PMBUS_REGISTER_READ_PIN 0x97 +#define PMBUS_REGISTER_MFR_ID 0x99 +#define PMBUS_REGISTER_MFR_MODEL 0x9A +#define PMBUS_REGISTER_MFR_REVISION 0x9B +#define PMBUS_REGISTER_MFR_SERIAL 0x9E + + +#define MAX_FAN_DUTY_CYCLE 100 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct accton_i2c_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[16]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u8 mfr_serial[26]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); + +static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev); + +enum accton_i2c_psu_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT_UV, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_SERIAL, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL); + + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +//static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + + +static struct attribute *accton_i2c_psu_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + //&sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + accton_i2c_psu_write_word(client, PMBUS_REGISTER_FAN_COMMAND_1 + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 0; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT_UV: + multiplier=1; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + if(!multiplier) + multiplier = PMBUS_LITERAL_DATA_MULTIPLIER; + if(attr->index==PSU_P_OUT_UV) + multiplier = 1000000; + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + int exponent, mantissa; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * PMBUS_LITERAL_DATA_MULTIPLIER) : + sprintf(buf, "%d\n", (mantissa * PMBUS_LITERAL_DATA_MULTIPLIER) / (1 << -exponent)); +} + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + + if (!data->valid) { + return 0; + } + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct accton_i2c_psu_data *data = accton_i2c_psu_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) { + return 0; + } + switch (attr->index) { + + case PSU_MFR_ID: + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: + ptr = data->mfr_revsion; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + + +static const struct attribute_group accton_i2c_psu_group = { + .attrs = accton_i2c_psu_attributes, +}; + +static int accton_i2c_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct accton_i2c_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct accton_i2c_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &accton_i2c_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int accton_i2c_psu_remove(struct i2c_client *client) +{ + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &accton_i2c_psu_group); + kfree(data); + + return 0; +} +/* Support psu moduel + */ +static const struct i2c_device_id accton_i2c_psu_id[] = { + { "acbel_fsh082", 0 }, + { "yesm1300am", 1 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_psu_id); + +static struct i2c_driver accton_i2c_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_psu", + }, + .probe = accton_i2c_psu_probe, + .remove = accton_i2c_psu_remove, + .id_table = accton_i2c_psu_id, + .address_list = normal_i2c, +}; + +static int accton_i2c_psu_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int accton_i2c_psu_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int accton_i2c_psu_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int accton_i2c_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + + +static int accton_i2c_psu_read_block_data(struct i2c_client *client, u8 command, u8 *data, int data_length) +{ + int status = -EIO; + int length; + u8 buffer[128] = {0}, *ptr = buffer; + + status = accton_i2c_psu_read_byte(client, command); + if (status < 0) + { + dev_dbg(&client->dev, "Unable to get data from offset 0x%02X\r\n", command); + status = -EIO; + goto EXIT_READ_BLOCK_DATA; + } + + status = (status & 0xFF) + 1; + if ( status > 128) + { + dev_dbg(&client->dev, "Unable to get big data from offset 0x%02X\r\n", command); + status = -EINVAL; + goto EXIT_READ_BLOCK_DATA; + } + + length = status; + status = accton_i2c_psu_read_block(client, command, buffer, length); + if (unlikely(status < 0)) + goto EXIT_READ_BLOCK_DATA; + if (unlikely(status != length)) { + status = -EIO; + goto EXIT_READ_BLOCK_DATA; + } + /* The first byte is the count byte of string. */ + ptr++; + status--; + + length=status>(data_length-1)?(data_length-1):status; + memcpy(data, ptr, length); + data[length-1] = 0; + +EXIT_READ_BLOCK_DATA: + + return status; +} + + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct accton_i2c_psu_data *accton_i2c_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct accton_i2c_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + //u8 command, buf; + struct reg_data_byte regs_byte[] = { {PMBUS_REGISTER_VOUT_MODE, &data->vout_mode}, + {PMBUS_REGISTER_STATUS_FAN, &data->fan_fault}}; + struct reg_data_word regs_word[] = { {PMBUS_REGISTER_READ_VIN, &data->v_in}, + {PMBUS_REGISTER_READ_VOUT, &data->v_out}, + {PMBUS_REGISTER_READ_IIN, &data->i_in}, + {PMBUS_REGISTER_READ_IOUT, &data->i_out}, + {PMBUS_REGISTER_READ_POUT, &data->p_out}, + {PMBUS_REGISTER_READ_PIN, &data->p_in}, + {PMBUS_REGISTER_READ_TEMPERATURE_1, &(data->temp_input[0])}, + {PMBUS_REGISTER_READ_TEMPERATURE_2, &(data->temp_input[1])}, + {PMBUS_REGISTER_FAN_COMMAND_1, &(data->fan_duty_cycle[0])}, + {PMBUS_REGISTER_READ_FAN_SPEED_1, &(data->fan_speed[0])}, + {PMBUS_REGISTER_READ_FAN_SPEED_2, &(data->fan_speed[1])}, + }; + + dev_dbg(&client->dev, "Starting accton_i2c_psu update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = accton_i2c_psu_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = accton_i2c_psu_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + + } + /* Read mfr_id */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_ID, data->mfr_id, + ARRAY_SIZE(data->mfr_id)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_ID, status); + goto exit; + } + /* Read mfr_model */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_MODEL, data->mfr_model, + ARRAY_SIZE(data->mfr_model)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_MODEL, status); + goto exit; + } + /* Read mfr_revsion */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_REVISION, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_REVISION, status); + goto exit; + } + /* Read mfr_serial */ + status = accton_i2c_psu_read_block_data(client, PMBUS_REGISTER_MFR_SERIAL, data->mfr_serial, + ARRAY_SIZE(data->mfr_serial)); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", PMBUS_REGISTER_MFR_SERIAL, status); + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init accton_i2c_psu_init(void) +{ + return i2c_add_driver(&accton_i2c_psu_driver); +} + +static void __exit accton_i2c_psu_exit(void) +{ + i2c_del_driver(&accton_i2c_psu_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION(DRIVER_DESCRIPTION_NAME); +MODULE_LICENSE("GPL"); + +module_init(accton_i2c_psu_init); +module_exit(accton_i2c_psu_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service new file mode 100644 index 000000000000..b77b40d67299 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-fan.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS9716-32D Platform Monitoring FAN service +Before=pmon.service +After=as9716-32d-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as9716_32d_monitor_fan.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service new file mode 100644 index 000000000000..69bcf37e27f5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor-psu.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS9716-32D Platform Monitoring PSU service +Before=pmon.service +After=as9716-32d-platform-monitor.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as9716_32d_monitor_psu.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service new file mode 100644 index 000000000000..1d77c39120a5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/service/as9716-32d-platform-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description=Accton AS9716-32D Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/accton_as9716_32d_util.py install +ExecStart=/usr/local/bin/accton_as9716_32d_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py new file mode 100755 index 000000000000..7c70492e5d6d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='as9716_32d', + version='1.0', + description='Module to initialize Accton AS9716-32D platforms', + + packages=['as9716_32d'], + package_dir={'as9716_32d': 'as9716-32d/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README new file mode 100755 index 000000000000..44e03cab5f52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/README @@ -0,0 +1,117 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + patch - files under patch/ is for kernel and ONIE installer + for the kernel: + config-accton-as5712_54x.patch + for kernel configuration. + driver-i2c-muxes-pca954x-always-deselect.patch + for i2c_mux deselects after transaction. + driver-patches-for-accton-as5712-fan-psu-cpld.patch + for as5712's fan/psu/cpld/led/sfp drivers. + for ONIE: + onie_installer-accton-AS5712-54X.patch + for console port setting and copy util script o rootfs. + module - Contains source code of as5712 kernel driver modules. + +The late Sonic building scripts, pushed @Dec 5 2016, will automatically +create a docker container and run building process under it. +User is not necessary to handle docker environment creation. + +1. Download sonic-buildimage environment. + - Run "git clone https://github.com/Azure/sonic-buildimage". + - cd to sonic-buildimage and run "git submodule update --init --recursive". +2. Build kernel + - cd ./src/sonic-linux-kernel + - Copy patches and series from patch/kernel of this release to + sonic-linux-kernel/patch. + - Build kernel by "make". + - The built kernel package, linux-image-3.16.0-5-amd64_3.16.51-3+deb8u1_amd64.deb + , is generated. +3. Build installer + - Change directory back to sonic-buildimage/. + - Get onie_installer-accton-AS5712-54X.patch" from patch/installer. + - Change setting for AS5712-54X by patching build_image.sh. + "patch -p1 < onie_installer-accton-AS5712-54X.patch" + !!NOTICE, patching onie_installer-accton-AS5712-54X.patch comments out the + "git status" checking at build_image.sh. + - The account and password of installed OS can be given at rules/config. + The default user and password are "admin" & "YourPaSsWoRd" respectively. + - Run "make configure PLATFORM=broadcom" + - Copy the built kernel debian package to target/debs/. + The file is linux-image-3.16.0-5-amd64_*_amd64.deb under directory + src/sonic-linux-kernel/. + - Run "make target/sonic-generic.bin" + - Get the installer, target/sonic-generic.bin, to target machine and install. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +The code for integacting with Accton AS5712-54X has 2 parts, +kernel drivers and operational script. +The kernel drivers of peripherals are under module/ directory. +1. These drivers are patched into kernel by + driver-patches-for-accton-as5712-fan-psu-cpld.patch + Or you can build the driver under module/ by setting environment variable, + KERNEL_SRC, to proper linux built directory and run make. + It may be sonic-linux-kernel/linux-3.*/debian/build/build_amd64_none_amd64/. +2. A operational script, accton_as5712_util.py, for device initializatian and + peripheral accessing should be installed at /usr/bin. + This script is generated by onie_installer-accton-AS5712-54X.patch. + It's done by patching onie_installer-accton-AS5712-54X.patch at build-image. + Run "accton_as5712_util.py install" to install drivers. + +To initialize the system, run "accton_as5712_util.py install". +To clean up the drivers & devices, run "accton_as5712_util.py clean". +To dump information of sensors, run "accton_as5712_util.py show". +To dump SFP EEPROM, run "accton_as5712_util.py sff". +To set fan speed, run "accton_as5712_util.py set fan". +To enable/disable SFP emission, run "accton_as5712_util.py set sfp". +To set system LEDs' color, run "accton_as5712_util.py set led" +For more information, run "accton_as5712_util.py --help". + +==================================================================== +Besides applying accton_as5712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +System LED: + There are 5 system LEDs at the lower-left corner of front panel. + They are loc, diag, fan, ps1, and ps2. + The sysfs interface color mappings are as follows: + Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + But not all colors are available for each LED. + +Fan Control: + There are 10 fans inside 5 fan modules. + All fans share 1 duty setting, ranged from 0~100. + +Thermal sensers: + 3 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There 2 power supplies slot at the left/right side of the back. + Once if a PSU is not plugged, the status of it is shown failed. + +There are 48 SFP+ and 6 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py new file mode 100755 index 000000000000..49a99aa777a3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor.py @@ -0,0 +1,531 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -* +# Copyright (c) 2019 Edgecore Networks Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. +# +# HISTORY: +# mm/dd/yyyy (A.D.)# +# 8/27/2019:Jostar create for as9716_32d thermal plan +# ------------------------------------------------------------------ + +try: + import commands + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example + from as9716_32d.fanutil import FanUtil + from as9716_32d.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9716_32d_monitor' + +global log_file +global log_level + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + + +# Read fanN_direction=1: The air flow of Fan6 is “AFI-Back to Front” +# 0: The air flow of Fan6 is “AFO-Front to back” +# +# Thermal policy: +# a.Defaut fan duty_cycle=100% +# b.One fan fail, set to fan duty_cycle=100% +# 1.For AFI: +# Default fan duty_cycle will be 100%(fan_policy_state=LEVEL_FAN_MAX). +# If all below case meet with, set to 75%(LEVEL_FAN_MID). +# MB board +# LM75-1(0X48)<=57 +# LM75-2(0X49)<=47.3 +# LM75-3(0X4A)<=45 +# LM75-4(0X4C)<=45.1 +# LM75-5(0X4E)<=40.75 +# LM75-6(0X4F)<=42.1 +# CPU board +# Core<=44 +# LM75-1(0X4B)<=35 + +# When fan_policy_state=LEVEL_FAN_MID, meet with below case, Fan duty_cycle will be 100%(LEVEL_FAN_DAX) +# (MB board) +# LM75-1(0X48)>=61.5 +# LM75-2(0X49)>=51.5 +# LM75-3(0X4A)>=49.4 +# LM75-4(0X4C)>=49.4 +# LM75-5(0X4E)>=45.1 +# LM75-6(0X4F)>=46.75 +# (CPU board) +# Core>=48 +# LM75-1(0X4B)>=38.5 + +# 2. For AFO: +# At default, FAN duty_cycle was 100%(LEVEL_FAN_MAX). If all below case meet with, set to 75%(LEVEL_FAN_MID). +# (MB board) +# LM75-1(0X48)<=59 +# LM75-2(0X49)<=53.5 +# LM75-3(0X4A)<=55.3 +# LM75-4(0X4C)<=50.3 +# LM75-5(0X4E)<=50 +# LM75-6(0X4F)<=52.5 +# (CPU board) +# Core<=59 +# LM75-1(0X4B)<=41.1 + +# When FAN duty_cycle was 75%(LEVEL_FAN_MID). If all below case meet with, set to 50%(LEVEL_FAN_DEF). +# (MB board) +# LM75-1(0X48)<=55.8 +# LM75-2(0X49)<=50.5 +# LM75-3(0X4A)<=51.1 +# LM75-4(0X4C)<=47.6 +# LM75-5(0X4E)<=45.75 +# LM75-6(0X4F)<=50.1 +# (CPU board) +# Core<=57 +# LM75-1(0X4B)<=36.6 + +# When fan_speed 50%(LEVEL_FAN_DEF). +# Meet with below case, Fan duty_cycle will be 75%(LEVEL_FAN_MID) +# (MB board) +# LM75-1(0X48)>=70 +# LM75-2(0X49)>=66 +# LM75-3(0X4A)>=68 +# LM75-4(0X4C)>=62 +# LM75-5(0X4E)>=62 +# LM75-6(0X4F)>=67 +# (CPU board) +# Core>=77 +# LM75-1(0X4B)>=50 + +# When FAN duty_cycle was 75%(LEVEL_FAN_MID). If all below case meet with, set to 100%(LEVEL_FAN_MAX). +# (MB board) +# LM75-1(0X48)>=67 +# LM75-2(0X49)>=62.5 +# LM75-3(0X4A)>=65 +# LM75-4(0X4C)>=59 +# LM75-5(0X4E)>=58.5 +# LM75-6(0X4F)>=63 + +# (CPU board) +# Core >=69 +# LM75-1(0X4B)>=49 + + +#Yellow Alarm +#MB board +#LM75-1(0X48)>=68 +#LM75-2(0X49)>=64 +#LM75-3(0X4A)>=65 +#LM75-4(0X4C)>=61 +#LM75-5(0X4E)>=60 +#LM75-6(0X4F)>=64 +#CPU Board +#Core>=70 +#LM75-1(0X4B)>=68 + +#Red Alarm +#MB board +#LM75-1(0X48)>=72 +#LM75-2(0X49)>=68 +#LM75-3(0X4A)>=69 +#LM75-4(0X4C)>=65 +#LM75-5(0X4E)>=64 +#LM75-6(0X4F)>=68 +#CPU Board +#Core>=74 +#LM75-1(0X4B)>=72 + +#Shut down +#MB board +#LM75-1(0X48)>=77 +#LM75-2(0X49)>=73 +#LM75-3(0X4A)>=74 +#LM75-4(0X4C)>=70 +#LM75-5(0X4E)>=69 +#LM75-6(0X4F)>=73 +#CPU Board +#Core>=79 +#LM75-1(0X4B)>=77 + + + +def power_off_dut(): + cmd_str="i2cset -y -f 19 0x60 0x60 0x10" + status, output = commands.getstatusoutput(cmd_str) + return status + +#If only one PSU insert(or one of PSU pwoer fail), and watt >800w. Must let DUT fan pwm >= 75% in AFO. +#Because the psu temp is high. +# Return 1: full load +# Return 0: Not full load +def check_psu_loading(): + psu_power_status=[1, 1] + + psu_power_good = { + 2: "/sys/bus/i2c/devices/10-0051/psu_power_good", + 1: "/sys/bus/i2c/devices/9-0050/psu_power_good", + } + psu_power_in = { + 2: "/sys/bus/i2c/devices/10-0059/psu_p_in", + 1: "/sys/bus/i2c/devices/9-0058/psu_p_in", + } + psu_power_out = { + 2: "/sys/bus/i2c/devices/10-0059/psu_p_out", + 1: "/sys/bus/i2c/devices/9-0058/psu_p_out", + } + + check_psu_watt=0 + for i in range(1,3): + node = psu_power_good[i] + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return None + + psu_power_status[i-1]=int(status) + if status==0: + check_psu_watt=1 + + if check_psu_watt: + for i in range(1,3): + if psu_power_status[i-1]==1: + #check watt + node = psu_power_in[i] + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return None + + psu_p_in= int(status) + if psu_p_in/1000 > 800: + return True + + node = psu_power_out[i] + try: + with open(node, 'r') as power_status: + status = int(power_status.read()) + except IOError: + return None + psu_p_out= int(status) + if psu_p_out/1000 > 800: + return True + else: + return False + + + return False + +fan_policy_state=0 +fan_policy_alarm=0 +send_yellow_alarm=0 +send_red_alarm=0 +fan_fail=0 +count_check=0 + +test_temp = 0 +test_temp_list = [0, 0, 0, 0, 0, 0, 0, 0] +temp_test_data=0 +test_temp_revert=0 + +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + # static temp var + temp = 0 + new_duty_cycle = 0 + duty_cycle=0 + ori_duty_cycle = 0 + + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + + def manage_fans(self): + + global fan_policy_state + global fan_policy_alarm + global send_yellow_alarm + global send_red_alarm + global fan_fail + global count_check + global test_temp + global test_temp_list + global temp_test_data + global test_temp_revert + + CHECK_TIMES=3 + + LEVEL_FAN_INIT=0 + LEVEL_FAN_MIN=1 + LEVEL_FAN_MID=2 + LEVEL_FAN_MAX=3 + LEVEL_FAN_DEF=LEVEL_FAN_MAX + LEVEL_FAN_YELLOW_ALARM=4 + LEVEL_FAN_RED_ALARM=5 + LEVEL_FAN_SHUTDOWN=6 + + fan_policy_f2b = { #AFO + LEVEL_FAN_MIN: [50, 0x7], + LEVEL_FAN_MID: [75, 0xb], + LEVEL_FAN_MAX: [100, 0xf] + } + fan_policy_b2f = { #AFI + LEVEL_FAN_MID: [75, 0xb], + LEVEL_FAN_MAX: [100, 0xf] + } + + afi_thermal_spec={ + "mid_to_max_temp":[61500, 51500, 49400, 49400, 45100, 46750, 48000, 38500], + "max_to_mid_temp":[57000, 47300, 45000, 45100, 40750, 42100, 44000, 35000] + } + afo_thermal_spec={ + "min_to_mid_temp": [70000, 66000, 68000, 62000, 62000, 67000, 77000, 50000], + "mid_to_max_temp": [67000, 62000, 65000, 59000, 58500, 63000, 69000, 49000], + "max_to_mid_temp": [59000, 53500, 55300, 50300, 50000, 52500, 59000, 41100], + "mid_to_min_temp": [55800, 50500, 51100, 47600, 45750, 50100, 57000, 36600], + "max_to_yellow_alarm": [68000, 64000, 65000, 61000, 60000, 64000, 70000, 68000], + "yellow_to_red_alarm": [72000, 68000, 69000, 65000, 64000, 68000, 74000, 72000], + "red_alarm_to_shutdown": [77000, 73000, 74000, 70000, 69000, 73000, 79000, 77000] + } + + thermal_val=[0,0,0,0,0,0,0,0] + max_to_mid=0 + mid_to_min=0 + + fan = FanUtil() + if fan_policy_state==LEVEL_FAN_INIT: + fan_policy_state=LEVEL_FAN_MAX #This is default state + logging.debug("fan_policy_state=LEVEL_FAN_MAX") + return + + count_check=count_check+1 + if count_check < CHECK_TIMES: + return + else: + count_check=0 + + thermal = ThermalUtil() + fan_dir=1 + fan_dir=fan.get_fan_dir(1) + + if fan_dir==1: # AFI + fan_thermal_spec = afi_thermal_spec + fan_policy=fan_policy_b2f + elif fan_dir==0: # AFO + fan_thermal_spec = afo_thermal_spec + fan_policy=fan_policy_f2b + else: + logging.debug( "NULL case") + + ori_duty_cycle=fan.get_fan_duty_cycle() + new_duty_cycle=0 + + if test_temp_revert==0: + temp_test_data=temp_test_data+2000 + else: + temp_test_data=temp_test_data-2000 + + if test_temp==0: + for i in range (thermal.THERMAL_NUM_1_IDX, thermal.THERMAL_NUM_MAX+1): + thermal_val[i-1]=thermal._get_thermal_val(i) + else: + for i in range (thermal.THERMAL_NUM_1_IDX, thermal.THERMAL_NUM_MAX+1): + thermal_val[i-1]=test_temp_list[i-1] + thermal_val[i-1]= thermal_val[i-1] + temp_test_data + + fan_fail=0 + + ori_state=fan_policy_state; + current_state=fan_policy_state; + + if fan_dir==1: #AFI + for i in range (0, thermal.THERMAL_NUM_MAX): + if ori_state==LEVEL_FAN_MID: + if thermal_val[i] >= fan_thermal_spec["mid_to_max_temp"][i]: + current_state=LEVEL_FAN_MAX + logging.debug("current_state=LEVEL_FAN_MAX") + break + else: + if (thermal_val[i] <= fan_thermal_spec["max_to_mid_temp"][i]): + max_to_mid=max_to_mid+1 + + if max_to_mid==thermal.THERMAL_NUM_MAX and fan_policy_state==LEVEL_FAN_MAX: + current_state=LEVEL_FAN_MID + logging.debug("current_state=LEVEL_FAN_MID") + else: #AFO + psu_full_load=check_psu_loading() + for i in range (0, thermal.THERMAL_NUM_MAX): + if ori_state==LEVEL_FAN_MID: + if thermal_val[i] >= fan_thermal_spec["mid_to_max_temp"][i]: + current_state=LEVEL_FAN_MAX + break + else: + if psu_full_load!=True and thermal_val[i] <= fan_thermal_spec["mid_to_min_temp"][i]: + mid_to_min=mid_to_min+1 + elif ori_state==LEVEL_FAN_MIN: + if psu_full_load==True: + current_state=LEVEL_FAN_MID + logging.debug("psu_full_load, set current_state=LEVEL_FAN_MID") + if thermal_val[i] >= fan_thermal_spec["min_to_mid_temp"][i]: + current_state=LEVEL_FAN_MID + + else: + if thermal_val[i] <= fan_thermal_spec["max_to_mid_temp"][i] : + max_to_mid=max_to_mid+1 + if fan_policy_alarm==0: + if thermal_val[i] >= fan_thermal_spec["max_to_yellow_alarm"][i]: + if send_yellow_alarm==0: + logging.warning('Alarm-Yellow for temperature high is detected') + fan_policy_alarm=LEVEL_FAN_YELLOW_ALARM + send_yellow_alarm=1 + elif fan_policy_alarm==LEVEL_FAN_YELLOW_ALARM: + if thermal_val[i] >= fan_thermal_spec["yellow_to_red_alarm"][i]: + if send_red_alarm==0: + logging.warning('Alarm-Red for temperature high is detected') + fan_policy_alarm=LEVEL_FAN_RED_ALARM + send_red_alarm=1 + elif fan_policy_alarm==LEVEL_FAN_RED_ALARM: + if thermal_val[i] >= fan_thermal_spec["red_alarm_to_shutdown"][i]: + logging.critical('Alarm-Critical for temperature high is detected, shutdown DUT') + fan_policy_alarm=LEVEL_FAN_SHUTDOWN + time.sleep(2) + power_off_dut() + + if max_to_mid==thermal.THERMAL_NUM_MAX and ori_state==LEVEL_FAN_MAX: + current_state=LEVEL_FAN_MID + if fan_policy_alarm!=0: + logging.warning('Alarm for temperature high is cleared') + fan_policy_alarm=0 + send_yellow_alarm=0 + send_red_alarm=0 + test_temp_revert=0 + logging.debug("current_state=LEVEL_FAN_MID") + + if mid_to_min==thermal.THERMAL_NUM_MAX and ori_state==LEVEL_FAN_MID: + if psu_full_load==0: + current_state=LEVEL_FAN_MIN + logging.debug("current_state=LEVEL_FAN_MIN") + + #Check Fan status + for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1): + if fan.get_fan_status(i)==0: + new_duty_cycle=100 + logging.debug('fan_%d fail, set duty_cycle to 100',i) + if test_temp==0: + fan_fail=1 + fan.set_fan_duty_cycle(new_duty_cycle) + break + else: + fan_fail=0 + + if current_state!=ori_state: + fan_policy_state=current_state + new_duty_cycle=fan_policy[current_state][0] + logging.debug("fan_policy_state=%d, new_duty_cycle=%d", fan_policy_state, new_duty_cycle) + if new_duty_cycle!=ori_duty_cycle and fan_fail==0: + fan.set_fan_duty_cycle(new_duty_cycle) + return True + if new_duty_cycle==0 and fan_fail==0: + fan.set_fan_duty_cycle(FAN_DUTY_CYCLE_MAX) + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + global test_temp + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdlt:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + if sys.argv[1]== '-t': + if len(sys.argv)!=10: + print "temp test, need input 8 temp" + return 0 + i=0 + for x in range(2, 10): + test_temp_list[i]= int(sys.argv[x])*1000 + i=i+1 + test_temp = 1 + log_level = logging.DEBUG + print test_temp_list + + fan = FanUtil() + fan.set_fan_duty_cycle(100) + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + + +if __name__ == '__main__': + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py new file mode 100755 index 000000000000..b22dd5d7984d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_fan.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 12/13/2018: Jostar create for as9716-32d +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9716_32d_monitor_fan' + +global log_file +global log_level + + +class switch(object): + def __init__(self, value): + self.value = value + self.fall = False + + def __iter__(self): + """Return the match method once, then stop""" + yield self.match + raise StopIteration + + def match(self, *args): + """Indicate whether or not to enter a case suite""" + if self.fall or not args: + return True + elif self.value in args: # changed for v1.5, see below + self.fall = True + return True + else: + return False + + +fan_state=[2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0 +fan_status_state=[2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0 +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.fan_num = 6 + self.fan_path = "/sys/bus/i2c/devices/17-0066/" + self.present = { + 0: "fan1_present", + 1: "fan2_present", + 2: "fan3_present", + 3: "fan4_present", + 4: "fan5_present", + 5: "fan6_present", + } + + self.fault = { + 0: "fan1_fault", + 1: "fan2_fault", + 2: "fan3_fault", + 3: "fan4_fault", + 4: "fan5_fault", + 5: "fan6_fault", + } + + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fan(self): + + FAN_STATE_REMOVE = 0 + FAN_STATE_INSERT = 1 + + FAN_STATUS_FAULT = 1 + FAN_STATUS_NORMAL = 0 + + global fan_state + global fan_status_state + + for idx in range (0, self.fan_num): + node = self.fan_path + self.present[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_state[idx]!=1: + fan_state[idx]=FAN_STATE_INSERT + logging.info("FAN-%d present is detected", idx+1); + else: + if fan_state[idx]!=0: + fan_state[idx]=FAN_STATE_REMOVE + logging.warning("Alarm for FAN-%d absent is detected", idx+1) + + for idx in range (0, self.fan_num): + node = self.fan_path + self.fault[idx] + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if fan_status_state[idx]!=FAN_STATUS_FAULT: + if fan_state[idx] == FAN_STATE_INSERT: + logging.warning("Alarm for FAN-%d failed is detected", idx+1); + fan_status_state[idx]=FAN_STATUS_FAULT + else: + fan_status_state[idx]=FAN_STATUS_NORMAL + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_fan() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py new file mode 100755 index 000000000000..a3c8a0be65b3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_monitor_psu.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Accton Technology Corporation +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 12/12/2018: Jostar create for as9716-32d +# ------------------------------------------------------------------ + +try: + import getopt + import sys + import logging + import logging.config + import logging.handlers + import time # this is only being used as part of the example +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/accton_as9716_32d_monitor_psu' + +global log_file +global log_level + + +psu_state=[2, 2] +psu_status_state=[2, 2] +# Make a class we can use to capture stdout and sterr in the log +class device_monitor(object): + + def __init__(self, log_file, log_level): + + self.psu_num = 2 + self.psu_path = "/sys/bus/i2c/devices/" + self.presence = "/psu_present" + self.oper_status = "/psu_power_good" + self.mapping = { + 0: "9-0050", + 1: "10-0051", + } + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = logging.handlers.SysLogHandler(address = '/dev/log') + #sys_handler.setLevel(logging.WARNING) + sys_handler.setLevel(logging.INFO) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_psu(self): + + PSU_STATE_REMOVE = 0 + PSU_STATE_INSERT = 1 + + PSU_STATUS_NO_POWER = 0 + PSU_STATUS_POWER_GOOD = 1 + PSU_STATUS_IDLE =2 + + global psu_state + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.presence + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "1": + if psu_state[idx]!=1: + psu_state[idx]=PSU_STATE_INSERT + logging.info("PSU-%d present is detected", idx+1); + #psu_status_state[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it. + else: + if psu_state[idx]!=0: + psu_state[idx]=PSU_STATE_REMOVE + logging.warning("Alarm for PSU-%d absent is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_IDLE + + for idx in range (0, self.psu_num): + node = self.psu_path + self.mapping[idx] + self.oper_status + try: + val_file = open(node) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + content = val_file.readline().rstrip() + val_file.close() + # content is a string, either "0" or "1" + if content == "0": + if psu_status_state[idx]!=PSU_STATUS_NO_POWER: + if psu_state[idx]==PSU_STATE_INSERT: + logging.warning("Alarm for PSU-%d failed is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_NO_POWER + else: + if psu_state[idx]==PSU_STATE_INSERT: + if psu_status_state[idx]!=PSU_STATUS_POWER_GOOD: + logging.info("PSU-%d power_good is detected", idx+1); + psu_status_state[idx]=PSU_STATUS_POWER_GOOD + + + return True + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + monitor = device_monitor(log_file, log_level) + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_psu() + time.sleep(3) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py new file mode 100755 index 000000000000..898fcaa0f0d3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as9716-32d/utils/accton_as9716_32d_util.py @@ -0,0 +1,622 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + +PROJECT_NAME = 'as9716_32d' +version = '0.0.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan1':1, 'fan2':1,'fan3':1,'fan4':1,'fan5':1,'thermal':3, 'psu':2, 'sfp':34} + + +led_prefix ='/sys/devices/platform/as9716_32d_led/leds/accton_'+PROJECT_NAME+'_led::' +fan_prefix ='/sys/devices/platform/as9716_32d_' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2'], + 'fan1': ['fan'], + 'fan2': ['fan'], + 'fan3': ['fan'], + 'fan4': ['fan'], + 'fan5': ['fan'], + } +hwmon_nodes = {'led': ['brightness'] , + 'fan1': ['fan_duty_cycle_percentage', 'fan1_fault', 'fan1_speed_rpm', 'fan1_direction', 'fanr1_fault', 'fanr1_speed_rpm'], + 'fan2': ['fan_duty_cycle_percentage','fan2_fault', 'fan2_speed_rpm', 'fan2_direction', 'fanr2_fault', 'fanr2_speed_rpm'], + 'fan3': ['fan_duty_cycle_percentage','fan3_fault', 'fan3_speed_rpm', 'fan3_direction', 'fanr3_fault', 'fanr3_speed_rpm'], + 'fan4': ['fan_duty_cycle_percentage','fan4_fault', 'fan4_speed_rpm', 'fan4_direction', 'fanr4_fault', 'fanr4_speed_rpm'], + 'fan5': ['fan_duty_cycle_percentage','fan5_fault', 'fan5_speed_rpm', 'fan5_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + 'fan6': ['fan_duty_cycle_percentage','fan6_fault', 'fan6_speed_rpm', 'fan6_direction', 'fanr5_fault', 'fanr5_speed_rpm'], + } +hwmon_prefix ={'led': led_prefix, + 'fan1': fan_prefix, + 'fan2': fan_prefix, + 'fan3': fan_prefix, + 'fan4': fan_prefix, + 'fan5': fan_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['54-0066'], + 'thermal': ['18-0048', '18-0049','18-004a', '18-004b', '18-004c', '18-004e', '18-004f'] , + 'psu': ['9-0058', '10-0059'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'], + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_ ', 'module_tx_disable_']} + +sfp_map = [25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58] + +#sfp_map = [25, 26] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-2/new_device', + +'echo as9716_32d_fpga 0x60 > /sys/bus/i2c/devices/i2c-19/new_device', +'echo as9716_32d_cpld1 0x61 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo as9716_32d_cpld2 0x62 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo as9716_32d_cpld_cpu 0x65 > /sys/bus/i2c/devices/i2c-0/new_device', + +'echo as9716_32d_fan 0x66 > /sys/bus/i2c/devices/i2c-17/new_device', + +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4e > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4f > /sys/bus/i2c/devices/i2c-18/new_device', + +# PSU-1 +'echo as9716_32d_psu1 0x50 > /sys/bus/i2c/devices/i2c-9/new_device', +'echo acbel_fsh082 0x58 > /sys/bus/i2c/devices/i2c-9/new_device', + +# PSU-2 +'echo as9716_32d_psu2 0x51 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo acbel_fsh082 0x59 > /sys/bus/i2c/devices/i2c-10/new_device', +] + +#EERPOM +eeprom_mknod =[ +'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +] + +FORCE = 0 +logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) > DEVICE_NO['sfp'] -1: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def dis_i2c_ir3570a(addr): + cmd = "i2cset -y 0 0x%x 0xE5 0x01" % addr + status, output = commands.getstatusoutput(cmd) + cmd = "i2cset -y 0 0x%x 0x12 0x02" % addr + status, output = commands.getstatusoutput(cmd) + return status + +def ir3570_check(): + cmd = "i2cdump -y 0 0x42 s 0x9a" + try: + status, output = commands.getstatusoutput(cmd) + lines = output.split('\n') + hn = re.findall(r'\w+', lines[-1]) + version = int(hn[1], 16) + if version == 0x24: #only for ir3570a + ret = dis_i2c_ir3570a(4) + else: + ret = 0 + except Exception as e: + print "Error on ir3570_check() e:" + str(e) + return -1 + return ret + + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe accton_i2c_psu', +'modprobe accton_as9716_32d_cpld', +'modprobe accton_as9716_32d_fan', +'modprobe accton_as9716_32d_leds', +'modprobe accton_as9716_32d_psu', +'modprobe optoe', +'modprobe lm75'] + +cpld_reset_stop='i2cset -y 0 0x65 0x3 0x0' + +def driver_install(): + + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + log_os_system(cpld_reset_stop, 1) + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + lst = rm.split(" ") + print "lst=%s"%lst + if len(lst) > 3: + del(lst[3]) + rm = " ".join(lst) + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +def eeprom_check(): + cmd = "i2cget -y -f 0 0x57" + status, output = commands.getstatusoutput(cmd) + return status + +def device_install(): + global FORCE + global use_57_eeprom + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + print "init i2c device instance" + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + ret=eeprom_check() + if ret==0: + log_os_system(eeprom_mknod[0], 1) #new board, 0x57 eeprom + else: + log_os_system(eeprom_mknod[1], 1) #old board, 0x56 eeprom + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/0-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + ret=eeprom_check() + if ret==0: + target = eeprom_mknod[0] #0x57 + else: + target = eeprom_mknod[1] #0x56 + + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + print "not device_exist()" + return False + return True + +def do_install(): + if driver_inserted() == False: + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + + ir3570_check() + + if not device_exist(): + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + #if len(ALL_DEVICE)==0: + # devices_info() + #node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + #node = node.replace(node.split("/")[-1], 'eeprom') + node= "/sys/bus/i2c/devices/"+str(sfp_map[int(index)])+"-0050" + "/eeprom" + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + print "node=%s"%node + #print node + ":" + #ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + ret, log = log_os_system(hex_cmd+" -C " + node, 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan1'] ['fan11'][0] + node = node.replace(node.split("/")[-1], 'fan1_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_i2c_cpld.c new file mode 100755 index 000000000000..03e528ef8d5b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_i2c_cpld.c @@ -0,0 +1,888 @@ +/* + * A hwmon driver for the accton_i2c_cpld + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define MAX_PORT_NUM 64 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x62 +#define I2C_ADDR_CPLD3 0x64 +#define CPLD_ADDRS {I2C_ADDR_CPLD1, I2C_ADDR_CPLD2, I2C_ADDR_CPLD3} + + +/* + * Number of additional attribute pointers to allocate + * with each call to krealloc + */ +#define ATTR_ALLOC_SIZE 1 /*For last attribute which is NUll.*/ + +#define NAME_SIZE 24 +#define MAX_RESP_LENGTH 48 + +typedef ssize_t (*show_func)( struct device *dev, + struct device_attribute *attr, + char *buf); +typedef ssize_t (*store_func)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); + +enum models { + AS7712_32X, + AS7716_32X, + AS7816_64X, + AS7312_54X, + PLAIN_CPLD, /*No attribute but add i2c addr to the list.*/ + NUM_MODEL +}; + +enum sfp_func { + HAS_SFP = 1<<0 , + HAS_QSFP = 1<<1 , +}; + +enum common_attrs { + CMN_VERSION, + CMN_ACCESS, + CMN_PRESENT_ALL, + NUM_COMMON_ATTR +}; + +enum sfp_attrs { + SFP_PRESENT, + SFP_RESET, + SFP_LP_MODE, + NUM_SFP_ATTR +}; + +struct cpld_sensor { + struct cpld_sensor *next; + char name[NAME_SIZE+1]; /* sysfs sensor name */ + struct device_attribute attribute; + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. Negative if there was a read error */ + + u8 reg; /* register */ + u8 mask; /* bit mask */ + bool invert; /* inverted value*/ + +}; + +#define to_cpld_sensor(_attr) \ + container_of(_attr, struct cpld_sensor, attribute) + +struct cpld_data { + struct device *dev; + struct device *hwmon_dev; + + int num_attributes; + struct attribute_group group; + + enum models model; + struct cpld_sensor *sensors; + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + int attr_index; + u16 sfp_num; + u8 sfp_types; + struct model_attrs *cmn_attr; +}; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + + +struct base_attrs { + const char *name; + umode_t mode; + show_func get; + store_func set; +}; + +struct attrs { + int reg; + bool invert; + struct base_attrs *base; +}; + +struct model_attrs { + struct attrs **cmn; + struct attrs **portly; +}; + + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_presnet_all(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t set_1bit(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_byte(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +int accton_i2c_cpld_read(u8 cpld_addr, u8 reg); +int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + + +struct base_attrs common_attrs[NUM_COMMON_ATTR] = +{ + [CMN_VERSION] = {"version", S_IRUGO, show_bit, NULL}, + [CMN_ACCESS] = {"access", S_IWUSR, NULL, set_byte}, + [CMN_PRESENT_ALL] = {"module_present_all", S_IRUGO, show_presnet_all, NULL}, +}; + +struct attrs as7712_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {0x30, false, &common_attrs[CMN_PRESENT_ALL]}, +}; +struct attrs as7816_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {0x70, false, &common_attrs[CMN_PRESENT_ALL]}, +}; +struct attrs as7312_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {-1, false, &common_attrs[CMN_PRESENT_ALL]}, +}; +struct attrs plain_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, +}; + +struct base_attrs portly_attrs[] = +{ + [SFP_PRESENT] = {"module_present", S_IRUGO, show_bit, NULL}, + [SFP_RESET] = {"module_reset", S_IRUGO|S_IWUSR, show_bit, set_1bit}, +}; + +struct attrs as7712_port[] = { + {0x30, true, &portly_attrs[SFP_PRESENT]}, + {0x04, true, &portly_attrs[SFP_RESET]}, +}; + +struct attrs as7816_port[] = { + {0x70, true, &portly_attrs[SFP_PRESENT]}, + {0x40, true, &portly_attrs[SFP_RESET]}, +}; + +struct attrs *as7712_cmn_list[] = { + &as7712_common[CMN_VERSION], + &as7712_common[CMN_ACCESS], + &as7712_common[CMN_PRESENT_ALL], + NULL +}; + +struct attrs *as7816_cmn_list[] = { + &as7816_common[CMN_VERSION], + &as7816_common[CMN_ACCESS], + &as7816_common[CMN_PRESENT_ALL], + NULL +}; + +struct attrs *as7312_cmn_list[] = { + &as7312_common[CMN_VERSION], + &as7312_common[CMN_ACCESS], + &as7312_common[CMN_PRESENT_ALL], + NULL +}; + +struct attrs *plain_cmn_list[] = { + &plain_common[CMN_VERSION], + NULL +}; + +struct attrs *as7712_port_list[] = { + &as7712_port[SFP_PRESENT], + &as7712_port[SFP_RESET], + NULL +}; +struct attrs *as7816_port_list[] = { + &as7816_port[SFP_PRESENT], + &as7816_port[SFP_RESET], + NULL +}; + +struct model_attrs models_attr[NUM_MODEL] = { + {.cmn = as7712_cmn_list, .portly=as7712_port_list}, + {.cmn = as7712_cmn_list, .portly=as7712_port_list}, /*7716's as 7712*/ + {.cmn = as7816_cmn_list, .portly=as7816_port_list}, + {.cmn = as7312_cmn_list, .portly=as7816_port_list}, + {.cmn = plain_cmn_list, .portly=NULL}, +}; + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; +/* Addresses scanned for accton_i2c_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static int get_sfp_spec(int model, u16 *num, u8 *types) +{ + switch (model) { + case AS7712_32X: + case AS7716_32X: + *num = 32; + *types = HAS_QSFP; + break; + case AS7816_64X: + *num = 64; + *types = HAS_QSFP; + break; + case AS7312_54X: + *num = 54; + *types = HAS_QSFP|HAS_SFP; + default: + *types = 0; + *num = 0; + break; + } + + return 0; +} + +static int get_present_reg_distinct(int model, u8 port, u8 *cpld_addr, u8 *reg, u8 *num) +{ + u8 cpld_address[] = CPLD_ADDRS; + + switch (model) { + case AS7312_54X: + if (port < 48) { + *cpld_addr = cpld_address[1 + port/24]; + *reg = 0x09 + (port%24)/8; + *num = 8; + } + else + { + *reg = 0x18; + *num = 4; + *cpld_addr = ( port < 52)? cpld_address[1]: cpld_address[2]; + } + break; + default: + return -EINVAL; + } +} + + +/*Assume the bits for ports are listed in-a-row.*/ +static int get_reg_bit(u8 reg_start, int port, + u8 *reg ,u8 *mask) +{ + *reg = reg_start + ((port)/8); + *mask = 1 << ((port)%8); + + return 0; +} + +static int cpld_write_internal( + struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + + +/*Turn a numberic array into string with " " between each element. + * e.g., {0x11, 0x33, 0xff, 0xf1} => "11 33 ff f1" + */ +static ssize_t array_stringify(char *buf, u8 *input, size_t size) { + + int i; + char t[MAX_RESP_LENGTH+1]; + + buf[0] = '\0'; + for (i = 0; i < size; i++) { + snprintf(t, MAX_RESP_LENGTH, "%x ", input[i]); + strncat(buf, t, MAX_RESP_LENGTH); + } + + if (strlen(buf) > 0) + buf[strlen(buf)-1] = '\0'; /*Remove tailing blank*/ + + return snprintf(buf, MAX_RESP_LENGTH, "%s\n", buf); +} + +static ssize_t show_presnet_all_distinct(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 i, value, reg; + u8 cpld_addr, num; + u8 _value[8]; + u64 *values = (u64 *)_value; + + values = 0; + mutex_lock(&data->update_lock); + while(i < data->sfp_num) + { + get_present_reg_distinct(data->model, i, &cpld_addr, ®, &num); + if(cpld_addr == client->addr) + value = cpld_read_internal(client, reg); + else + value = accton_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(value < 0)) { + goto exit; + } + + *values |= (value&((1<<(num))-1)) << i; + i += num; + } + mutex_unlock(&data->update_lock); + + *values = cpu_to_le64(*values); + return array_stringify(buf, _value, i); +exit: + mutex_unlock(&data->update_lock); + return value; +} + +static ssize_t show_presnet_all(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + u8 i, values[MAX_PORT_NUM/8]; + + /*In case, the registers out-of-order*/ + if (sensor->reg < 0) { + return show_presnet_all_distinct(dev, devattr, buf); + } + + mutex_lock(&data->update_lock); + for (i = 0; i < ((data->sfp_num + 7)/8); i++) { + values[i] = cpld_read_internal(client, sensor->reg + i); + if (unlikely(values[i] < 0)) { + goto exit; + } + } + mutex_unlock(&data->update_lock); + return array_stringify(buf, values, i); + +exit: + mutex_unlock(&data->update_lock); + return values[i]; +} + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int value; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, sensor->reg); + value = value & sensor->mask; + if (sensor->invert) + value = !value; + mutex_unlock(&data->update_lock); + + return snprintf(buf, PAGE_SIZE, "%x\n", value); +} + +static ssize_t set_1bit(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + long is_reset; + int value, status; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + u8 cpld_bit, reg; + + status = kstrtol(buf, 10, &is_reset); + if (status) { + return status; + } + reg = sensor->reg; + cpld_bit = sensor->mask; + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + if (sensor->invert) + is_reset = !is_reset; + + if (is_reset) { + value |= cpld_bit; + } + else { + value &= ~cpld_bit; + } + + status = cpld_write_internal(client, reg, value); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_byte(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return access(dev, da, buf, count); +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void accton_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = + kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", + client->addr); + return; + } + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void accton_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int cpld_add_attribute(struct cpld_data *data, struct attribute *attr) +{ + int new_max_attrs = ++data->num_attributes + ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + + + data->group.attrs[data->num_attributes-1] = attr; + data->group.attrs[data->num_attributes] = NULL; + + return 0; +} + +static void cpld_dev_attr_init(struct device_attribute *dev_attr, + const char *name, umode_t mode, + show_func show, store_func store) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static struct cpld_sensor * add_sensor(struct cpld_data *data, + const char *name, + u8 reg, u8 mask, bool invert, + bool update, umode_t mode, + show_func get, store_func set) +{ + struct cpld_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), name); + sensor->reg = reg; + sensor->mask = mask; + sensor->update = update; + sensor->invert = invert; + cpld_dev_attr_init(a, sensor->name, + mode, + get, set); + + if (cpld_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int add_attributes_cmn(struct cpld_data *data, struct attrs **cmn) +{ + u8 reg, i ; + bool invert; + struct attrs *a; + struct base_attrs *b; + + if (NULL == cmn) + return -1; + + for (i = 0; cmn[i]; i++) + { + a = cmn[i]; + + reg = a->reg; + invert = a->invert; + + b = a->base; + if (NULL == b) + break; + + if (add_sensor(data, b->name, + reg, 0xff, invert, + true, b->mode, + b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + return 0; +} + +static int add_attributes_portly(struct cpld_data *data, struct attrs **pa) +{ + char name[NAME_SIZE+1]; + int i, j; + u8 reg, mask, invert; + struct attrs *a; + struct base_attrs *b; + + if (NULL == pa) + return -1; + + + for (i = 0; pa[i]; i++) { + a = pa[i]; + b = a->base; + if (b == NULL) + break; + + invert = a->invert; + for (j = 0; j < data->sfp_num; j++) + { + snprintf(name, NAME_SIZE, "%s_%d", b->name, j+1); + get_reg_bit(a->reg, j, ®, &mask); + + if (add_sensor(data, name, reg, mask, invert, + true, b->mode, b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + } + return 0; +} + +static int add_attributes(struct i2c_client *client, + struct cpld_data *data) +{ + struct model_attrs *m = data->cmn_attr; + + if (m == NULL) + return -EINVAL; + + /* Common attributes.*/ + add_attributes_cmn(data, m->cmn); + + /* Port-wise attributes.*/ + add_attributes_portly(data, m->portly); + + return 0; +} + +static int accton_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + struct device *dev = &client->dev; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + return -EIO; + } + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->model = dev_id->driver_data; + data->cmn_attr = &models_attr[data->model]; + get_sfp_spec(data->model, &data->sfp_num, &data->sfp_types); + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->dev = dev; + dev_info(dev, "chip found\n"); + + status = add_attributes(client, data); + if (status) + goto out_kfree; + + /* + * If there are no attributes, something is wrong. + * Bail out instead of trying to register nothing. + */ + if (!data->num_attributes) { + dev_err(dev, "No attributes found\n"); + status = -ENODEV; + goto out_kfree; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->group); + if (status) { + goto out_kfree; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + accton_i2c_cpld_add_client(client); + dev_info(dev, "%s: cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->group); +out_kfree: + kfree(data->group.attrs); + return status; + +} + +static int accton_i2c_cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->group); + kfree(data->group.attrs); + accton_i2c_cpld_remove_client(client); + return 0; +} + +int accton_i2c_cpld_read(u8 cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_read); + +int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(accton_i2c_cpld_write); + + +static const struct i2c_device_id accton_i2c_cpld_id[] = { + { "cpld_as7712", AS7712_32X}, + { "cpld_as7716", AS7716_32X}, + { "cpld_as7816", AS7816_64X}, + { "cpld_as7312", AS7312_54X}, + { "cpld_plain", PLAIN_CPLD}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); + +static struct i2c_driver accton_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "accton_i2c_cpld", + }, + .probe = accton_i2c_cpld_probe, + .remove = accton_i2c_cpld_remove, + .id_table = accton_i2c_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init accton_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&accton_i2c_cpld_driver); +} + +static void __exit accton_i2c_cpld_exit(void) +{ + i2c_del_driver(&accton_i2c_cpld_driver); +} + +module_init(accton_i2c_cpld_init); +module_exit(accton_i2c_cpld_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_i2c_cpld driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_pmbus_3y.c b/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_pmbus_3y.c new file mode 100644 index 000000000000..76ac4368a8d4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/common/modules/accton_pmbus_3y.c @@ -0,0 +1,1978 @@ +/* + * Hardware monitoring driver for 3Y power devices. + * + * Copyright (C) 2018 Accton Technology Corporation. + * Roy Lee + * + * Based on pmbus.c, pmbus.h and pmbus_core.c. + * Copyright 2012 Guenter Roeck/Ericsson AB. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pmbus.h" + + +enum chips { + YM2651, + YM2401, + YM2851, + LIMITED_CHIPS, +}; + + +/* + * Number of additional attribute pointers to allocate + * with each call to krealloc + */ +#define PMBUS_ATTR_ALLOC_SIZE 32 + +/* + * Index into status register array, per status register group + */ +#define PB_STATUS_BASE 0 +#define PB_STATUS_VOUT_BASE (PB_STATUS_BASE + PMBUS_PAGES) +#define PB_STATUS_IOUT_BASE (PB_STATUS_VOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN_BASE (PB_STATUS_IOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN34_BASE (PB_STATUS_FAN_BASE + PMBUS_PAGES) +#define PB_STATUS_TEMP_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES) +#define PB_STATUS_INPUT_BASE (PB_STATUS_TEMP_BASE + PMBUS_PAGES) +#define PB_STATUS_VMON_BASE (PB_STATUS_INPUT_BASE + 1) + +#define PB_NUM_STATUS_REG (PB_STATUS_VMON_BASE + 1) + +#define PMBUS_NAME_SIZE 24 + +struct pmbus_sensor { + struct pmbus_sensor *next; + char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */ + struct device_attribute attribute; + u8 page; /* page number */ + u16 reg; /* register */ + enum pmbus_sensor_classes class; /* sensor class */ + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. + Negative if there was a read error */ +}; +#define to_pmbus_sensor(_attr) \ + container_of(_attr, struct pmbus_sensor, attribute) + +struct pmbus_boolean { + char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ + struct sensor_device_attribute attribute; + struct pmbus_sensor *s1; + struct pmbus_sensor *s2; +}; +#define to_pmbus_boolean(_attr) \ + container_of(_attr, struct pmbus_boolean, attribute) + +struct pmbus_label { + char name[PMBUS_NAME_SIZE]; /* sysfs label name */ + struct device_attribute attribute; + char label[PMBUS_NAME_SIZE]; /* label */ +}; +#define to_pmbus_label(_attr) \ + container_of(_attr, struct pmbus_label, attribute) + +struct pmbus_data { + struct device *dev; + struct device *hwmon_dev; + + u32 flags; /* from platform data */ + + int exponent[PMBUS_PAGES]; + /* linear mode: exponent for output voltages */ + + const struct pmbus_driver_info *info; + + int max_attributes; + int num_attributes; + struct attribute_group group; + const struct attribute_group *groups[2]; + + struct pmbus_sensor *sensors; + + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + /* + * A single status register covers multiple attributes, + * so we keep them all together. + */ + u8 status[PB_NUM_STATUS_REG]; + u8 status_register; + + u8 currpage; + bool linear_16; +}; + + +static int limited_models(const struct i2c_device_id *id); + +int _pmbus_set_page(struct i2c_client *client, u8 page) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int rv = 0; + int newpage; + + if (page != data->currpage) { + rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); + newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); + if (newpage != page) + rv = -EIO; + else + data->currpage = page; + } + return 0; +} + +/* + * _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->write_byte) { + status = info->write_byte(client, page, value); + if (status != -ENODATA) + return status; + } + /*Ignore page*/ + return i2c_smbus_write_byte(client, value);; +} + +/* + * _pmbus_write_word_data() is similar to pmbus_write_word_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg, + u16 word) +{ + if (reg >= PMBUS_VIRT_BASE) + return -ENXIO; + /*Ignore page*/ + return i2c_smbus_write_word_data(client, reg, word); +} + +/* + * _pmbus_read_word_data() is similar to pmbus_read_word_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg) +{ + /*Ignore page*/ + return i2c_smbus_read_word_data(client, reg);; +} + +/* + * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg) +{ + if (reg >= PMBUS_VIRT_BASE) + return -ENXIO; + + /*Ignore page*/ + return i2c_smbus_read_byte_data(client, reg); +} + +static void pmbus_clear_fault_page(struct i2c_client *client, int page) +{ + _pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); +} + + +static int pmbus_check_status_cml(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int status, status2; + + status = _pmbus_read_byte_data(client, -1, data->status_register); + if (status < 0 || (status & PB_STATUS_CML)) { + status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML); + if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND)) + return -EIO; + } + return 0; +} + +static bool pmbus_check_register(struct i2c_client *client, + int (*func)(struct i2c_client *client, + int page, int reg), + int page, int reg) +{ + int rv; + struct pmbus_data *data = i2c_get_clientdata(client); + + if((data->flags & PMBUS_SKIP_STATUS_CHECK)) + return 1; + + rv = func(client, page, reg); + if (rv >= 0) + rv = pmbus_check_status_cml(client); + pmbus_clear_fault_page(client, -1); + return rv >= 0; +} + +static struct _pmbus_status { + u32 func; + u16 base; + u16 reg; +} pmbus_status[] = { + { PMBUS_HAVE_STATUS_VOUT, PB_STATUS_VOUT_BASE, PMBUS_STATUS_VOUT }, + { PMBUS_HAVE_STATUS_IOUT, PB_STATUS_IOUT_BASE, PMBUS_STATUS_IOUT }, + { PMBUS_HAVE_STATUS_TEMP, PB_STATUS_TEMP_BASE, + PMBUS_STATUS_TEMPERATURE + }, + { PMBUS_HAVE_STATUS_FAN12, PB_STATUS_FAN_BASE, PMBUS_STATUS_FAN_12 }, + { PMBUS_HAVE_STATUS_FAN34, PB_STATUS_FAN34_BASE, PMBUS_STATUS_FAN_34 }, +}; + +void _pmbus_clear_faults(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int i; + + for (i = 0; i < data->info->pages; i++) + pmbus_clear_fault_page(client, i); +} +static struct pmbus_data *pmbus_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev->parent); + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + struct pmbus_sensor *sensor; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + int i, j; + + for (i = 0; i < info->pages; i++) { + data->status[PB_STATUS_BASE + i] + = _pmbus_read_byte_data(client, i, + data->status_register); + for (j = 0; j < ARRAY_SIZE(pmbus_status); j++) { + struct _pmbus_status *s = &pmbus_status[j]; + + if (!(info->func[i] & s->func)) + continue; + data->status[s->base + i] + = _pmbus_read_byte_data(client, i, + s->reg); + } + } + + if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) + data->status[PB_STATUS_INPUT_BASE] + = _pmbus_read_byte_data(client, 0, + PMBUS_STATUS_INPUT); + + if (info->func[0] & PMBUS_HAVE_STATUS_VMON) + data->status[PB_STATUS_VMON_BASE] + = _pmbus_read_byte_data(client, 0, + PMBUS_VIRT_STATUS_VMON); + + for (sensor = data->sensors; sensor; sensor = sensor->next) { + if (!data->valid || sensor->update) + sensor->data + = _pmbus_read_word_data(client, + sensor->page, + sensor->reg); + } + _pmbus_clear_faults(client); + data->last_updated = jiffies; + data->valid = 1; + } + mutex_unlock(&data->update_lock); + return data; +} + +/* + * Convert linear sensor values to milli- or micro-units + * depending on sensor type. + */ +static long pmbus_reg2data_linear(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + s16 exponent; + s32 mantissa; + long val; + + /* LINEAR16 */ + if ( data->linear_16 && + sensor->class == PSC_VOLTAGE_OUT) { + exponent = data->exponent[sensor->page]; + mantissa = (u16) sensor->data; + } else + { /* LINEAR11 */ + exponent = ((s16)sensor->data) >> 11; + mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5; + } + + val = mantissa; + + /* scale result to milli-units for all sensors except fans */ + if (sensor->class != PSC_FAN) + val = val * 1000L; + + /* scale result to micro-units for power sensors */ + if (sensor->class == PSC_POWER) + val = val * 1000L; + + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +/* + * Convert direct sensor values to milli- or micro-units + * depending on sensor type. + */ +static long pmbus_reg2data_direct(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + long val = (s16) sensor->data; + long m, b, R; + + m = data->info->m[sensor->class]; + b = data->info->b[sensor->class]; + R = data->info->R[sensor->class]; + + if (m == 0) + return 0; + + /* X = 1/m * (Y * 10^-R - b) */ + R = -R; + /* scale result to milli-units for everything but fans */ + if (sensor->class != PSC_FAN) { + R += 3; + b *= 1000; + } + + /* scale result to micro-units for power sensors */ + if (sensor->class == PSC_POWER) { + R += 3; + b *= 1000; + } + + while (R > 0) { + val *= 10; + R--; + } + while (R < 0) { + val = DIV_ROUND_CLOSEST(val, 10); + R++; + } + + return (val - b) / m; +} + +/* + * Convert VID sensor values to milli- or micro-units + * depending on sensor type. + * We currently only support VR11. + */ +static long pmbus_reg2data_vid(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + long val = sensor->data; + + if (val < 0x02 || val > 0xb2) + return 0; + return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100); +} + +static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) +{ + long val; + + switch (data->info->format[sensor->class]) { + case direct: + val = pmbus_reg2data_direct(data, sensor); + break; + case vid: + val = pmbus_reg2data_vid(data, sensor); + break; + case linear: + default: + val = pmbus_reg2data_linear(data, sensor); + break; + } + return val; +} + +#define MAX_MANTISSA (1023 * 1000) +#define MIN_MANTISSA (511 * 1000) + +static u16 pmbus_data2reg_linear(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + s16 exponent = 0, mantissa; + bool negative = false; + + /* simple case */ + if (val == 0) + return 0; + + if (data->linear_16 && + sensor->class == PSC_VOLTAGE_OUT) { + /* LINEAR16 does not support negative voltages */ + if (val < 0) + return 0; + + /* + * For a static exponents, we don't have a choice + * but to adjust the value to it. + */ + if (data->exponent[sensor->page] < 0) + val <<= -data->exponent[sensor->page]; + else + val >>= data->exponent[sensor->page]; + val = DIV_ROUND_CLOSEST(val, 1000); + return val & 0xffff; + } + + if (val < 0) { + negative = true; + val = -val; + } + + /* Power is in uW. Convert to mW before converting. */ + if (sensor->class == PSC_POWER) + val = DIV_ROUND_CLOSEST(val, 1000L); + + /* + * For simplicity, convert fan data to milli-units + * before calculating the exponent. + */ + if (sensor->class == PSC_FAN) + val = val * 1000; + + /* Reduce large mantissa until it fits into 10 bit */ + while (val >= MAX_MANTISSA && exponent < 15) { + exponent++; + val >>= 1; + } + /* Increase small mantissa to improve precision */ + while (val < MIN_MANTISSA && exponent > -15) { + exponent--; + val <<= 1; + } + + /* Convert mantissa from milli-units to units */ + mantissa = DIV_ROUND_CLOSEST(val, 1000); + + /* Ensure that resulting number is within range */ + if (mantissa > 0x3ff) + mantissa = 0x3ff; + + /* restore sign */ + if (negative) + mantissa = -mantissa; + + /* Convert to 5 bit exponent, 11 bit mantissa */ + return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800); +} + +static u16 pmbus_data2reg_direct(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + long m, b, R; + + m = data->info->m[sensor->class]; + b = data->info->b[sensor->class]; + R = data->info->R[sensor->class]; + + /* Power is in uW. Adjust R and b. */ + if (sensor->class == PSC_POWER) { + R -= 3; + b *= 1000; + } + + /* Calculate Y = (m * X + b) * 10^R */ + if (sensor->class != PSC_FAN) { + R -= 3; /* Adjust R and b for data in milli-units */ + b *= 1000; + } + val = val * m + b; + + while (R > 0) { + val *= 10; + R--; + } + while (R < 0) { + val = DIV_ROUND_CLOSEST(val, 10); + R++; + } + + return val; +} + +static u16 pmbus_data2reg_vid(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + val = clamp_val(val, 500, 1600); + + return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625); +} + +static u16 pmbus_data2reg(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + u16 regval; + + switch (data->info->format[sensor->class]) { + case direct: + regval = pmbus_data2reg_direct(data, sensor, val); + break; + case vid: + regval = pmbus_data2reg_vid(data, sensor, val); + break; + case linear: + default: + regval = pmbus_data2reg_linear(data, sensor, val); + break; + } + return regval; +} + +/* + * Return boolean calculated from converted data. + * defines a status register index and mask. + * The mask is in the lower 8 bits, the register index is in bits 8..23. + * + * The associated pmbus_boolean structure contains optional pointers to two + * sensor attributes. If specified, those attributes are compared against each + * other to determine if a limit has been exceeded. + * + * If the sensor attribute pointers are NULL, the function returns true if + * (status[reg] & mask) is true. + * + * If sensor attribute pointers are provided, a comparison against a specified + * limit has to be performed to determine the boolean result. + * In this case, the function returns true if v1 >= v2 (where v1 and v2 are + * sensor values referenced by sensor attribute pointers s1 and s2). + * + * To determine if an object exceeds upper limits, specify = . + * To determine if an object exceeds lower limits, specify = . + * + * If a negative value is stored in any of the referenced registers, this value + * reflects an error code which will be returned. + */ +static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b, + int index) +{ + struct pmbus_sensor *s1 = b->s1; + struct pmbus_sensor *s2 = b->s2; + u16 reg = (index >> 8) & 0xffff; + u8 mask = index & 0xff; + int ret, status; + u8 regval; + + status = data->status[reg]; + if (status < 0) + return status; + + regval = status & mask; + if (!s1 && !s2) { + ret = !!regval; + } else if (!s1 || !s2) { + WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2); + return 0; + } else { + long v1, v2; + + if (s1->data < 0) + return s1->data; + if (s2->data < 0) + return s2->data; + + v1 = pmbus_reg2data(data, s1); + v2 = pmbus_reg2data(data, s2); + ret = !!(regval && v1 >= v2); + } + return ret; +} + +static ssize_t pmbus_show_boolean(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct pmbus_boolean *boolean = to_pmbus_boolean(attr); + struct pmbus_data *data = pmbus_update_device(dev); + int val; + + val = pmbus_get_boolean(data, boolean, attr->index); + if (val < 0) { + return snprintf(buf, PAGE_SIZE, "%d\n", 1); + } + return snprintf(buf, PAGE_SIZE, "%d\n", val); +} + +static ssize_t pmbus_show_sensor(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct pmbus_data *data = pmbus_update_device(dev); + struct pmbus_sensor *sensor = to_pmbus_sensor(devattr); + + + if (sensor->data < 0) { + return snprintf(buf, PAGE_SIZE, "%d\n", 0); + } + + + return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor)); +} + +static ssize_t pmbus_set_sensor(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev->parent); + struct pmbus_data *data = i2c_get_clientdata(client); + struct pmbus_sensor *sensor = to_pmbus_sensor(devattr); + ssize_t rv = count; + long val = 0; + int ret; + u16 regval; + + if (kstrtol(buf, 10, &val) < 0) + return -EINVAL; + + mutex_lock(&data->update_lock); + regval = pmbus_data2reg(data, sensor, val); + ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval); + if (ret < 0) + rv = ret; + else + sensor->data = regval; + mutex_unlock(&data->update_lock); + return rv; +} + +static ssize_t pmbus_show_label(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct pmbus_label *label = to_pmbus_label(da); + + return snprintf(buf, PAGE_SIZE, "%s\n", label->label); +} + +static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr) +{ + if (data->num_attributes >= data->max_attributes - 1) { + int new_max_attrs = data->max_attributes + PMBUS_ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + data->max_attributes = new_max_attrs; + } + + + + data->group.attrs[data->num_attributes++] = attr; + data->group.attrs[data->num_attributes] = NULL; + return 0; +} + +static void pmbus_dev_attr_init(struct device_attribute *dev_attr, + const char *name, + umode_t mode, + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*store)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count)) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static void pmbus_attr_init(struct sensor_device_attribute *a, + const char *name, + umode_t mode, + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*store)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count), + int idx) +{ + pmbus_dev_attr_init(&a->dev_attr, name, mode, show, store); + a->index = idx; +} + +static int pmbus_add_boolean(struct pmbus_data *data, + const char *name, const char *type, int seq, + struct pmbus_sensor *s1, + struct pmbus_sensor *s2, + u16 reg, u8 mask) +{ + struct pmbus_boolean *boolean; + struct sensor_device_attribute *a; + + boolean = devm_kzalloc(data->dev, sizeof(*boolean), GFP_KERNEL); + if (!boolean) + return -ENOMEM; + + a = &boolean->attribute; + + snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s", + name, seq, type); + boolean->s1 = s1; + boolean->s2 = s2; + pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL, + (reg << 8) | mask); + + return pmbus_add_attribute(data, &a->dev_attr.attr); +} + +static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data, + const char *name, const char *type, + int seq, int page, int reg, + enum pmbus_sensor_classes class, + bool update, bool readonly) +{ + struct pmbus_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s", + name, seq, type); + sensor->page = page; + sensor->reg = reg; + sensor->class = class; + sensor->update = update; + pmbus_dev_attr_init(a, sensor->name, + readonly ? S_IRUGO : S_IRUGO | S_IWUSR, + pmbus_show_sensor, pmbus_set_sensor); + + if (pmbus_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int pmbus_add_label(struct pmbus_data *data, + const char *name, int seq, + const char *lstring, int index) +{ + struct pmbus_label *label; + struct device_attribute *a; + + label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL); + if (!label) + return -ENOMEM; + + a = &label->attribute; + + snprintf(label->name, sizeof(label->name), "%s%d_label", name, seq); + if (!index) + strncpy(label->label, lstring, sizeof(label->label) - 1); + else + snprintf(label->label, sizeof(label->label), "%s%d", lstring, + index); + + pmbus_dev_attr_init(a, label->name, S_IRUGO, pmbus_show_label, NULL); + return pmbus_add_attribute(data, &a->attr); +} + +/* + * Search for attributes. Allocate sensors, booleans, and labels as needed. + */ + +/* + * The pmbus_limit_attr structure describes a single limit attribute + * and its associated alarm attribute. + */ +struct pmbus_limit_attr { + u16 reg; /* Limit register */ + u16 sbit; /* Alarm attribute status bit */ + bool update; /* True if register needs updates */ + bool low; /* True if low limit; for limits with compare + functions only */ + const char *attr; /* Attribute name */ + const char *alarm; /* Alarm attribute name */ +}; + +/* + * The pmbus_sensor_attr structure describes one sensor attribute. This + * description includes a reference to the associated limit attributes. + */ +struct pmbus_sensor_attr { + u16 reg; /* sensor register */ + u8 gbit; /* generic status bit */ + u8 nlimit; /* # of limit registers */ + enum pmbus_sensor_classes class;/* sensor class */ + const char *label; /* sensor label */ + bool paged; /* true if paged sensor */ + bool update; /* true if update needed */ + bool compare; /* true if compare function needed */ + u32 func; /* sensor mask */ + u32 sfunc; /* sensor status mask */ + int sbase; /* status base register */ + const struct pmbus_limit_attr *limit;/* limit registers */ +}; + +/* + * Add a set of limit attributes and, if supported, the associated + * alarm attributes. + * returns 0 if no alarm register found, 1 if an alarm register was found, + * < 0 on errors. + */ +static int pmbus_add_limit_attrs(struct i2c_client *client, + struct pmbus_data *data, + const struct pmbus_driver_info *info, + const char *name, int index, int page, + struct pmbus_sensor *base, + const struct pmbus_sensor_attr *attr) +{ + const struct pmbus_limit_attr *l = attr->limit; + int nlimit = attr->nlimit; + int have_alarm = 0; + int i, ret; + struct pmbus_sensor *curr; + + for (i = 0; i < nlimit; i++) { + if (_pmbus_check_word_register(client, page, l->reg)) + { + curr = pmbus_add_sensor(data, name, l->attr, index, + page, l->reg, attr->class, + attr->update || l->update, + false); + if (!curr) + return -ENOMEM; + if (l->sbit && (info->func[page] & attr->sfunc)) { + ret = pmbus_add_boolean(data, name, + l->alarm, index, + attr->compare ? l->low ? curr : base + : NULL, + attr->compare ? l->low ? base : curr + : NULL, + attr->sbase + page, l->sbit); + if (ret) + return ret; + have_alarm = 1; + } + } + l++; + } + return have_alarm; +} + +bool _pmbus_check_byte_register(struct i2c_client *client, int page, int reg) +{ + return pmbus_check_register(client, _pmbus_read_byte_data, page, reg); +} + + +bool _pmbus_check_word_register(struct i2c_client *client, int page, int reg) +{ + return pmbus_check_register(client, _pmbus_read_word_data, page, reg); +} + +static int pmbus_add_sensor_attrs_one(struct i2c_client *client, + struct pmbus_data *data, + const struct pmbus_driver_info *info, + const char *name, + int index, int page, + const struct pmbus_sensor_attr *attr) +{ + struct pmbus_sensor *base; + int ret; + + if (attr->label) { + ret = pmbus_add_label(data, name, index, attr->label, + attr->paged ? page + 1 : 0); + if (ret) + return ret; + } + base = pmbus_add_sensor(data, name, "input", index, page, attr->reg, + attr->class, true, true); + + + if (!base) + return -ENOMEM; + + if (attr->sfunc) { + ret = pmbus_add_limit_attrs(client, data, info, name, + index, page, base, attr); + if (ret < 0) + return ret; + /* + * Add generic alarm attribute only if there are no individual + * alarm attributes, if there is a global alarm bit, and if + * the generic status register for this page is accessible. + */ + if (!ret && attr->gbit && + _pmbus_check_byte_register(client, page, + data->status_register)) { + ret = pmbus_add_boolean(data, name, "alarm", index, + NULL, NULL, + PB_STATUS_BASE + page, + attr->gbit); + if (ret) + return ret; + } + } + return 0; +} + +static int pmbus_add_sensor_attrs(struct i2c_client *client, + struct pmbus_data *data, + const char *name, + const struct pmbus_sensor_attr *attrs, + int nattrs) +{ + const struct pmbus_driver_info *info = data->info; + int index, i; + int ret; + + index = 1; + for (i = 0; i < nattrs; i++) { + int page, pages; + + pages = attrs->paged ? info->pages : 1; + for (page = 0; page < pages; page++) { + if (!(info->func[page] & attrs->func)) + continue; + ret = pmbus_add_sensor_attrs_one(client, data, info, + name, index, page, + attrs); + if (ret) + return ret; + index++; + } + attrs++; + } + return 0; +} + +static const struct pmbus_limit_attr vin_limit_attrs[] = { + { + .reg = PMBUS_VIN_UV_WARN_LIMIT, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_VOLTAGE_UV_WARNING, + }, { + .reg = PMBUS_VIN_UV_FAULT_LIMIT, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_VOLTAGE_UV_FAULT, + }, { + .reg = PMBUS_VIN_OV_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_VOLTAGE_OV_WARNING, + }, { + .reg = PMBUS_VIN_OV_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_VOLTAGE_OV_FAULT, + }, { + .reg = PMBUS_VIRT_READ_VIN_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_VIN_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_VIN_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_VIN_HISTORY, + .attr = "reset_history", + }, +}; + +static const struct pmbus_limit_attr vmon_limit_attrs[] = { + { + .reg = PMBUS_VIRT_VMON_UV_WARN_LIMIT, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_VOLTAGE_UV_WARNING, + }, { + .reg = PMBUS_VIRT_VMON_UV_FAULT_LIMIT, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_VOLTAGE_UV_FAULT, + }, { + .reg = PMBUS_VIRT_VMON_OV_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_VOLTAGE_OV_WARNING, + }, { + .reg = PMBUS_VIRT_VMON_OV_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_VOLTAGE_OV_FAULT, + } +}; + +static const struct pmbus_limit_attr vout_limit_attrs[] = { + { + .reg = PMBUS_VOUT_UV_WARN_LIMIT, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_VOLTAGE_UV_WARNING, + }, { + .reg = PMBUS_VOUT_UV_FAULT_LIMIT, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_VOLTAGE_UV_FAULT, + }, { + .reg = PMBUS_VOUT_OV_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_VOLTAGE_OV_WARNING, + }, { + .reg = PMBUS_VOUT_OV_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_VOLTAGE_OV_FAULT, + }, { + .reg = PMBUS_VIRT_READ_VOUT_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_VOUT_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_VOUT_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_VOUT_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_sensor_attr voltage_attributes[] = { + { + .reg = PMBUS_READ_VIN, + .class = PSC_VOLTAGE_IN, + .label = "vin", + .func = PMBUS_HAVE_VIN, + .sfunc = PMBUS_HAVE_STATUS_INPUT, + .sbase = PB_STATUS_INPUT_BASE, + .gbit = PB_STATUS_VIN_UV, + .limit = vin_limit_attrs, + .nlimit = ARRAY_SIZE(vin_limit_attrs), + }, { + .reg = PMBUS_VIRT_READ_VMON, + .class = PSC_VOLTAGE_IN, + .label = "vmon", + .func = PMBUS_HAVE_VMON, + .sfunc = PMBUS_HAVE_STATUS_VMON, + .sbase = PB_STATUS_VMON_BASE, + .limit = vmon_limit_attrs, + .nlimit = ARRAY_SIZE(vmon_limit_attrs), + }, { + .reg = PMBUS_READ_VCAP, + .class = PSC_VOLTAGE_IN, + .label = "vcap", + .func = PMBUS_HAVE_VCAP, + }, { + .reg = PMBUS_READ_VOUT, + .class = PSC_VOLTAGE_OUT, + .label = "vout", + .paged = true, + .func = PMBUS_HAVE_VOUT, + .sfunc = PMBUS_HAVE_STATUS_VOUT, + .sbase = PB_STATUS_VOUT_BASE, + .gbit = PB_STATUS_VOUT_OV, + .limit = vout_limit_attrs, + .nlimit = ARRAY_SIZE(vout_limit_attrs), + } +}; + +/* Current attributes */ + +static const struct pmbus_limit_attr iin_limit_attrs[] = { + { + .reg = PMBUS_IIN_OC_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_IIN_OC_WARNING, + }, { + .reg = PMBUS_IIN_OC_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_IIN_OC_FAULT, + }, { + .reg = PMBUS_VIRT_READ_IIN_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_IIN_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_IIN_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_IIN_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_limit_attr iout_limit_attrs[] = { + { + .reg = PMBUS_IOUT_OC_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_IOUT_OC_WARNING, + }, { + .reg = PMBUS_IOUT_UC_FAULT_LIMIT, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_IOUT_UC_FAULT, + }, { + .reg = PMBUS_IOUT_OC_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_IOUT_OC_FAULT, + }, { + .reg = PMBUS_VIRT_READ_IOUT_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_IOUT_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_IOUT_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_IOUT_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_sensor_attr current_attributes[] = { + { + .reg = PMBUS_READ_IIN, + .class = PSC_CURRENT_IN, + .label = "iin", + .func = PMBUS_HAVE_IIN, + .sfunc = PMBUS_HAVE_STATUS_INPUT, + .sbase = PB_STATUS_INPUT_BASE, + .limit = iin_limit_attrs, + .nlimit = ARRAY_SIZE(iin_limit_attrs), + }, { + .reg = PMBUS_READ_IOUT, + .class = PSC_CURRENT_OUT, + .label = "iout", + .paged = true, + .func = PMBUS_HAVE_IOUT, + .sfunc = PMBUS_HAVE_STATUS_IOUT, + .sbase = PB_STATUS_IOUT_BASE, + .gbit = PB_STATUS_IOUT_OC, + .limit = iout_limit_attrs, + .nlimit = ARRAY_SIZE(iout_limit_attrs), + } +}; + +/* Power attributes */ + +static const struct pmbus_limit_attr pin_limit_attrs[] = { + { + .reg = PMBUS_PIN_OP_WARN_LIMIT, + .attr = "max", + .alarm = "alarm", + .sbit = PB_PIN_OP_WARNING, + }, { + .reg = PMBUS_VIRT_READ_PIN_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_PIN_MAX, + .update = true, + .attr = "input_highest", + }, { + .reg = PMBUS_VIRT_RESET_PIN_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_limit_attr pout_limit_attrs[] = { + { + .reg = PMBUS_POUT_MAX, + .attr = "cap", + .alarm = "cap_alarm", + .sbit = PB_POWER_LIMITING, + }, { + .reg = PMBUS_POUT_OP_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_POUT_OP_WARNING, + }, { + .reg = PMBUS_POUT_OP_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_POUT_OP_FAULT, + }, { + .reg = PMBUS_VIRT_READ_POUT_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_POUT_MAX, + .update = true, + .attr = "input_highest", + }, { + .reg = PMBUS_VIRT_RESET_POUT_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_sensor_attr power_attributes[] = { + { + .reg = PMBUS_READ_PIN, + .class = PSC_POWER, + .label = "pin", + .func = PMBUS_HAVE_PIN, + .sfunc = PMBUS_HAVE_STATUS_INPUT, + .sbase = PB_STATUS_INPUT_BASE, + .limit = pin_limit_attrs, + .nlimit = ARRAY_SIZE(pin_limit_attrs), + }, { + .reg = PMBUS_READ_POUT, + .class = PSC_POWER, + .label = "pout", + .paged = true, + .func = PMBUS_HAVE_POUT, + .sfunc = PMBUS_HAVE_STATUS_IOUT, + .sbase = PB_STATUS_IOUT_BASE, + .limit = pout_limit_attrs, + .nlimit = ARRAY_SIZE(pout_limit_attrs), + } +}; + +/* Temperature atributes */ + +static const struct pmbus_limit_attr temp_limit_attrs[] = { + { + .reg = PMBUS_UT_WARN_LIMIT, + .low = true, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_TEMP_UT_WARNING, + }, { + .reg = PMBUS_UT_FAULT_LIMIT, + .low = true, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_TEMP_UT_FAULT, + }, { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + }, { + .reg = PMBUS_OT_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_TEMP_OT_FAULT, + }, { + .reg = PMBUS_VIRT_READ_TEMP_MIN, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_TEMP_AVG, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_TEMP_MAX, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_TEMP_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_limit_attr temp_limit_attrs2[] = { + { + .reg = PMBUS_UT_WARN_LIMIT, + .low = true, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_TEMP_UT_WARNING, + }, { + .reg = PMBUS_UT_FAULT_LIMIT, + .low = true, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_TEMP_UT_FAULT, + }, { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + }, { + .reg = PMBUS_OT_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_TEMP_OT_FAULT, + }, { + .reg = PMBUS_VIRT_READ_TEMP2_MIN, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_TEMP2_AVG, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_TEMP2_MAX, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_limit_attr temp_limit_attrs3[] = { + { + .reg = PMBUS_UT_WARN_LIMIT, + .low = true, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_TEMP_UT_WARNING, + }, { + .reg = PMBUS_UT_FAULT_LIMIT, + .low = true, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_TEMP_UT_FAULT, + }, { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + }, { + .reg = PMBUS_OT_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_TEMP_OT_FAULT, + } +}; + +static const struct pmbus_sensor_attr temp_attributes[] = { + { + .reg = PMBUS_READ_TEMPERATURE_1, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs, + .nlimit = ARRAY_SIZE(temp_limit_attrs), + }, { + .reg = PMBUS_READ_TEMPERATURE_2, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP2, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs2, + .nlimit = ARRAY_SIZE(temp_limit_attrs2), + }, { + .reg = PMBUS_READ_TEMPERATURE_3, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP3, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs3, + .nlimit = ARRAY_SIZE(temp_limit_attrs3), + } +}; + +static const int pmbus_fan_registers[] = { + PMBUS_READ_FAN_SPEED_1, + PMBUS_READ_FAN_SPEED_2, + PMBUS_READ_FAN_SPEED_3, + PMBUS_READ_FAN_SPEED_4 +}; + +static const int pmbus_fan_config_registers[] = { + PMBUS_FAN_CONFIG_12, + PMBUS_FAN_CONFIG_12, + PMBUS_FAN_CONFIG_34, + PMBUS_FAN_CONFIG_34 +}; + +static const int pmbus_fan_status_registers[] = { + PMBUS_STATUS_FAN_12, + PMBUS_STATUS_FAN_12, + PMBUS_STATUS_FAN_34, + PMBUS_STATUS_FAN_34 +}; + +static const u32 pmbus_fan_flags[] = { + PMBUS_HAVE_FAN12, + PMBUS_HAVE_FAN12, + PMBUS_HAVE_FAN34, + PMBUS_HAVE_FAN34 +}; + +static const u32 pmbus_fan_status_flags[] = { + PMBUS_HAVE_STATUS_FAN12, + PMBUS_HAVE_STATUS_FAN12, + PMBUS_HAVE_STATUS_FAN34, + PMBUS_HAVE_STATUS_FAN34 +}; + +/* Fans */ +static int pmbus_add_fan_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + const struct pmbus_driver_info *info = data->info; + int index = 1; + int page; + int ret; + + for (page = 0; page < info->pages; page++) { + int f; + + for (f = 0; f < ARRAY_SIZE(pmbus_fan_registers); f++) { + int regval; + + if (f >= info->fan_num) + break; + + if (!(info->func[page] & pmbus_fan_flags[f])) + break; + + if (!_pmbus_check_word_register(client, page, + pmbus_fan_registers[f])) + break; + + /* + * Skip fan if not installed. + * Each fan configuration register covers multiple fans, + * so we have to do some magic. + */ + regval = _pmbus_read_byte_data(client, page, + pmbus_fan_config_registers[f]); + if (regval < 0 || + (!(regval & (PB_FAN_1_INSTALLED >> ((f & 1) * 4))))) + continue; + + if (pmbus_add_sensor(data, "fan", "input", index, + page, pmbus_fan_registers[f], + PSC_FAN, true, true) == NULL) + return -ENOMEM; + + /* + * Each fan status register covers multiple fans, + * so we have to do some magic. + */ + if ((info->func[page] & pmbus_fan_status_flags[f]) && + _pmbus_check_byte_register(client, + page, pmbus_fan_status_registers[f])) { + int base; + + if (f > 1) /* fan 3, 4 */ + base = PB_STATUS_FAN34_BASE + page; + else + base = PB_STATUS_FAN_BASE + page; + ret = pmbus_add_boolean(data, "fan", + "alarm", index, NULL, NULL, base, + PB_FAN_FAN1_WARNING >> (f & 1)); + if (ret) + return ret; + ret = pmbus_add_boolean(data, "fan", + "fault", index, NULL, NULL, base, + PB_FAN_FAN1_FAULT >> (f & 1)); + if (ret) + return ret; + } + index++; + } + } + return 0; +} + +static int pmbus_find_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + int ret; + + /* Voltage sensors */ + ret = pmbus_add_sensor_attrs(client, data, "in", voltage_attributes, + ARRAY_SIZE(voltage_attributes)); + if (ret) + return ret; + + /* Current sensors */ + ret = pmbus_add_sensor_attrs(client, data, "curr", current_attributes, + ARRAY_SIZE(current_attributes)); + if (ret) + return ret; + + /* Power sensors */ + ret = pmbus_add_sensor_attrs(client, data, "power", power_attributes, + ARRAY_SIZE(power_attributes)); + if (ret) + return ret; + + /* Temperature sensors */ + ret = pmbus_add_sensor_attrs(client, data, "temp", temp_attributes, + ARRAY_SIZE(temp_attributes)); + if (ret) + return ret; + + /* Fans */ + ret = pmbus_add_fan_attributes(client, data); + return ret; +} + +/* + * Identify chip parameters. + * This function is called for all chips. + */ +static int pmbus_identify_common(struct i2c_client *client, + struct pmbus_data *data, int page) +{ + int vout_mode = -1; + + if (_pmbus_check_byte_register(client, page, PMBUS_VOUT_MODE)) + { + vout_mode = _pmbus_read_byte_data(client, page, + PMBUS_VOUT_MODE); + } + + if (vout_mode >= 0 && vout_mode != 0xff) { + /* + * Not all chips support the VOUT_MODE command, + * so a failure to read it is not an error. + */ + switch (vout_mode >> 5) { + case 0: /* linear mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != linear) + return -ENODEV; + + data->exponent[page] = ((s8)(vout_mode << 3)) >> 3; + break; + case 1: /* VID mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != vid) + return -ENODEV; + break; + case 2: /* direct mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != direct) + return -ENODEV; + break; + default: + return -ENODEV; + } + } + + pmbus_clear_fault_page(client, page); + return 0; +} + +static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, + struct pmbus_driver_info *info) +{ + struct device *dev = &client->dev; + int page, ret; + + /* + * Some PMBus chips don't support PMBUS_STATUS_BYTE, so try + * to use PMBUS_STATUS_WORD instead if that is the case. + * Bail out if both registers are not supported. + */ + if(0) { /*Skip this for the i2c access may fail if PSU is not powered.*/ + data->status_register = PMBUS_STATUS_BYTE; + ret = i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE); + if (ret < 0 || ret == 0xff) { + data->status_register = PMBUS_STATUS_WORD; + ret = i2c_smbus_read_word_data(client, PMBUS_STATUS_WORD); + if (ret < 0 || ret == 0xffff) { + dev_err(dev, "PMBus status register not found\n"); + return -ENODEV; + } + } + } + _pmbus_clear_faults(client); + + if (info->identify) { + ret = (*info->identify)(client, info); + if (ret < 0) { + dev_err(dev, "Chip identification failed\n"); + return ret; + } + } + + if (info->pages <= 0 || info->pages > PMBUS_PAGES) { + dev_err(dev, "Bad number of PMBus pages: %d\n", info->pages); + return -ENODEV; + } + + for (page = 0; page < info->pages; page++) { + ret = pmbus_identify_common(client, data, page); + if (ret < 0) { + dev_err(dev, "Failed to identify chip capabilities\n"); + return ret; + } + } + return 0; +} + +int _pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info) +{ + struct device *dev = &client->dev; + struct pmbus_data *data; + int ret; + + if (!info) + return -ENODEV; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE + | I2C_FUNC_SMBUS_BYTE_DATA + | I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->dev = dev; + + if (limited_models(id)) + { + data->flags |= PMBUS_SKIP_STATUS_CHECK; + info->pages = 1; + info->fan_num = 1; + data->linear_16 = 0; + } + else + { + info->pages = id->driver_data; + info->fan_num = 4; + data->linear_16 = 1; + + } + + data->info = info; + + ret = pmbus_init_common(client, data, info); + if (ret < 0) + return ret; + + ret = pmbus_find_attributes(client, data); + if (ret) + goto out_kfree; + + /* + * If there are no attributes, something is wrong. + * Bail out instead of trying to register nothing. + */ + if (!data->num_attributes) { + dev_err(dev, "No attributes found\n"); + ret = -ENODEV; + goto out_kfree; + } + + data->groups[0] = &data->group; + data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + if (IS_ERR(data->hwmon_dev)) { + ret = PTR_ERR(data->hwmon_dev); + dev_err(dev, "Failed to register hwmon device\n"); + goto out_kfree; + } + return 0; + +out_kfree: + kfree(data->group.attrs); + return ret; +} + +/* + * Find sensor groups and status registers on each page. + */ +static void pmbus_find_sensor_groups(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int page; + + /* For i2c might not available when this driver installing, + turn on all attributes but VMON and FAN34.*/ + info->func[0] |= 0x1feff; + return ; + + + /* Sensors detected on page 0 only */ + if (_pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) + info->func[0] |= PMBUS_HAVE_VIN; + if (_pmbus_check_word_register(client, 0, PMBUS_READ_VCAP)) + info->func[0] |= PMBUS_HAVE_VCAP; + if (_pmbus_check_word_register(client, 0, PMBUS_READ_IIN)) + info->func[0] |= PMBUS_HAVE_IIN; + if (_pmbus_check_word_register(client, 0, PMBUS_READ_PIN)) + info->func[0] |= PMBUS_HAVE_PIN; + if (info->func[0] + && _pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) + info->func[0] |= PMBUS_HAVE_STATUS_INPUT; + if (info->fan_num > 0) + { + if (_pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && + _pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { + info->func[0] |= PMBUS_HAVE_FAN12; + if (_pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN12; + } + } + if (info->fan_num > 2) + { + if (_pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) && + _pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) { + info->func[0] |= PMBUS_HAVE_FAN34; + if (_pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN34; + } + } + + if (_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) + info->func[0] |= PMBUS_HAVE_TEMP; + if (_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) + info->func[0] |= PMBUS_HAVE_TEMP2; + if (_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) + info->func[0] |= PMBUS_HAVE_TEMP3; + + if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_TEMP3) + && _pmbus_check_byte_register(client, 0, + PMBUS_STATUS_TEMPERATURE)) + info->func[0] |= PMBUS_HAVE_STATUS_TEMP; + + /* Sensors detected on all pages */ + for (page = 0; page < info->pages; page++) { + if (_pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) { + info->func[page] |= PMBUS_HAVE_VOUT; + if (_pmbus_check_byte_register(client, page, + PMBUS_STATUS_VOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_VOUT; + } + if (_pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) { + info->func[page] |= PMBUS_HAVE_IOUT; + if (_pmbus_check_byte_register(client, 0, + PMBUS_STATUS_IOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_IOUT; + } + if (_pmbus_check_word_register(client, page, PMBUS_READ_POUT)) + info->func[page] |= PMBUS_HAVE_POUT; + } +} + +/* + * Identify chip parameters. + */ +static int pmbus_identify(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int ret = 0; + + if (!info->pages) { + /* + * Check if the PAGE command is supported. If it is, + * keep setting the page number until it fails or until the + * maximum number of pages has been reached. Assume that + * this is the number of pages supported by the chip. + */ + if (_pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { + int page; + + for (page = 1; page < PMBUS_PAGES; page++) { + if (_pmbus_set_page(client, page) < 0) + break; + } + _pmbus_set_page(client, 0); + info->pages = page; + } else { + info->pages = 1; + } + } + + if (_pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { + int vout_mode; + + vout_mode = _pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); + if (vout_mode >= 0 && vout_mode != 0xff) { + switch (vout_mode >> 5) { + case 0: + break; + case 1: + info->format[PSC_VOLTAGE_OUT] = vid; + break; + case 2: + info->format[PSC_VOLTAGE_OUT] = direct; + break; + default: + ret = -ENODEV; + goto abort; + } + } + } + + + /* + * We should check if the COEFFICIENTS register is supported. + * If it is, and the chip is configured for direct mode, we can read + * the coefficients from the chip, one set per group of sensor + * registers. + * + * To do this, we will need access to a chip which actually supports the + * COEFFICIENTS command, since the command is too complex to implement + * without testing it. Until then, abort if a chip configured for direct + * mode was detected. + */ + if (info->format[PSC_VOLTAGE_OUT] == direct) { + ret = -ENODEV; + goto abort; + } + + /* Try to find sensor groups */ + pmbus_find_sensor_groups(client, info); +abort: + return ret; +} + +/* + * Use driver_data to set the number of pages supported by the chip. + */ +static const struct i2c_device_id pmbus_id[] = { + { "accton_ym2651", YM2651 }, + { "accton_ym2401", YM2401 }, + { "accton_ym2851", YM2851 }, + {} +}; + +static int limited_models(const struct i2c_device_id *id) +{ + int j; + + if (!id->name) + return 0; + + for (j = 0; j < ARRAY_SIZE(pmbus_id); j++) { + if (!pmbus_id[j].name) + continue; + + if (!strcmp(id->name, pmbus_id[j].name)) + { + if(id->driver_data < LIMITED_CHIPS) + { + return 1; + } + else + { + return 0; + } + } + + } + + return 0; +} + +static int pmbus_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pmbus_driver_info *info; + + info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), + GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->identify = pmbus_identify; + + return _pmbus_do_probe(client, id, info); +} + +int _pmbus_do_remove(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + kfree(data->group.attrs); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, pmbus_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver pmbus_driver = { + .driver = { + .name = "accton_pmbus_3y", + }, + .probe = pmbus_probe, + .remove = _pmbus_do_remove, + .id_table = pmbus_id, +}; + +module_i2c_driver(pmbus_driver); + +MODULE_AUTHOR("Roy Lee"); +MODULE_DESCRIPTION("Accton PMBus driver for 3Y Power YM-2651Y."); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/common/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/common/modules/cpr_4011_4mxx.c new file mode 100644 index 000000000000..f1790b4515ff --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/common/modules/cpr_4011_4mxx.c @@ -0,0 +1,428 @@ +/* + * An hwmon driver for the CPR-4011-4Mxx Redundant Power Module + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x3c, 0x3d, 0x3e, 0x3f, I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct cpr_4011_4mxx_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[2]; /* Register value */ + u8 fan_fault; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u16 fan_speed[2]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value); +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev); + +enum cpr_4011_4mxx_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); + + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(pwm1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); + + + +static struct attribute *cpr_4011_4mxx_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_fault.dev_attr.attr, + &sensor_dev_attr_pwm1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cpr_4011_4mxx_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct cpr_4011_4mxx_data *data = cpr_4011_4mxx_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static const struct attribute_group cpr_4011_4mxx_group = { + .attrs = cpr_4011_4mxx_attributes, +}; + +static int cpr_4011_4mxx_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct cpr_4011_4mxx_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct cpr_4011_4mxx_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpr_4011_4mxx_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int cpr_4011_4mxx_remove(struct i2c_client *client) +{ + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpr_4011_4mxx_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id cpr_4011_4mxx_id[] = { + { "cpr_4011_4mxx", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpr_4011_4mxx_id); + +static struct i2c_driver cpr_4011_4mxx_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cpr_4011_4mxx", + }, + .probe = cpr_4011_4mxx_probe, + .remove = cpr_4011_4mxx_remove, + .id_table = cpr_4011_4mxx_id, + .address_list = normal_i2c, +}; + +static int cpr_4011_4mxx_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cpr_4011_4mxx_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cpr_4011_4mxx_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct cpr_4011_4mxx_data *cpr_4011_4mxx_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpr_4011_4mxx_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + struct reg_data_byte regs_byte[] = { {0x20, &data->vout_mode}, + {0x81, &data->fan_fault} + }; + struct reg_data_word regs_word[] = { {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &(data->fan_speed[0])}, + {0x91, &(data->fan_speed[1])} + }; + + dev_dbg(&client->dev, "Starting cpr_4011_4mxx update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cpr_4011_4mxx_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = cpr_4011_4mxx_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } + else { + *(regs_word[i].value) = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init cpr_4011_4mxx_init(void) +{ + return i2c_add_driver(&cpr_4011_4mxx_driver); +} + +static void __exit cpr_4011_4mxx_exit(void) +{ + i2c_del_driver(&cpr_4011_4mxx_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("CPR_4011_4MXX driver"); +MODULE_LICENSE("GPL"); + +module_init(cpr_4011_4mxx_init); +module_exit(cpr_4011_4mxx_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/common/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-accton/common/modules/pmbus.h new file mode 100644 index 000000000000..cb6dbc34d87c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/common/modules/pmbus.h @@ -0,0 +1,389 @@ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PMBUS_H +#define PMBUS_H + +/* + * Registers + */ +#define PMBUS_PAGE 0x00 +#define PMBUS_OPERATION 0x01 +#define PMBUS_ON_OFF_CONFIG 0x02 +#define PMBUS_CLEAR_FAULTS 0x03 +#define PMBUS_PHASE 0x04 + +#define PMBUS_CAPABILITY 0x19 +#define PMBUS_QUERY 0x1A + +#define PMBUS_VOUT_MODE 0x20 +#define PMBUS_VOUT_COMMAND 0x21 +#define PMBUS_VOUT_TRIM 0x22 +#define PMBUS_VOUT_CAL_OFFSET 0x23 +#define PMBUS_VOUT_MAX 0x24 +#define PMBUS_VOUT_MARGIN_HIGH 0x25 +#define PMBUS_VOUT_MARGIN_LOW 0x26 +#define PMBUS_VOUT_TRANSITION_RATE 0x27 +#define PMBUS_VOUT_DROOP 0x28 +#define PMBUS_VOUT_SCALE_LOOP 0x29 +#define PMBUS_VOUT_SCALE_MONITOR 0x2A + +#define PMBUS_COEFFICIENTS 0x30 +#define PMBUS_POUT_MAX 0x31 + +#define PMBUS_FAN_CONFIG_12 0x3A +#define PMBUS_FAN_COMMAND_1 0x3B +#define PMBUS_FAN_COMMAND_2 0x3C +#define PMBUS_FAN_CONFIG_34 0x3D +#define PMBUS_FAN_COMMAND_3 0x3E +#define PMBUS_FAN_COMMAND_4 0x3F + +#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40 +#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41 +#define PMBUS_VOUT_OV_WARN_LIMIT 0x42 +#define PMBUS_VOUT_UV_WARN_LIMIT 0x43 +#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44 +#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45 +#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46 +#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47 +#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48 +#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49 +#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A +#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B +#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C + +#define PMBUS_OT_FAULT_LIMIT 0x4F +#define PMBUS_OT_FAULT_RESPONSE 0x50 +#define PMBUS_OT_WARN_LIMIT 0x51 +#define PMBUS_UT_WARN_LIMIT 0x52 +#define PMBUS_UT_FAULT_LIMIT 0x53 +#define PMBUS_UT_FAULT_RESPONSE 0x54 +#define PMBUS_VIN_OV_FAULT_LIMIT 0x55 +#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56 +#define PMBUS_VIN_OV_WARN_LIMIT 0x57 +#define PMBUS_VIN_UV_WARN_LIMIT 0x58 +#define PMBUS_VIN_UV_FAULT_LIMIT 0x59 + +#define PMBUS_IIN_OC_FAULT_LIMIT 0x5B +#define PMBUS_IIN_OC_WARN_LIMIT 0x5D + +#define PMBUS_POUT_OP_FAULT_LIMIT 0x68 +#define PMBUS_POUT_OP_WARN_LIMIT 0x6A +#define PMBUS_PIN_OP_WARN_LIMIT 0x6B + +#define PMBUS_STATUS_BYTE 0x78 +#define PMBUS_STATUS_WORD 0x79 +#define PMBUS_STATUS_VOUT 0x7A +#define PMBUS_STATUS_IOUT 0x7B +#define PMBUS_STATUS_INPUT 0x7C +#define PMBUS_STATUS_TEMPERATURE 0x7D +#define PMBUS_STATUS_CML 0x7E +#define PMBUS_STATUS_OTHER 0x7F +#define PMBUS_STATUS_MFR_SPECIFIC 0x80 +#define PMBUS_STATUS_FAN_12 0x81 +#define PMBUS_STATUS_FAN_34 0x82 + +#define PMBUS_READ_VIN 0x88 +#define PMBUS_READ_IIN 0x89 +#define PMBUS_READ_VCAP 0x8A +#define PMBUS_READ_VOUT 0x8B +#define PMBUS_READ_IOUT 0x8C +#define PMBUS_READ_TEMPERATURE_1 0x8D +#define PMBUS_READ_TEMPERATURE_2 0x8E +#define PMBUS_READ_TEMPERATURE_3 0x8F +#define PMBUS_READ_FAN_SPEED_1 0x90 +#define PMBUS_READ_FAN_SPEED_2 0x91 +#define PMBUS_READ_FAN_SPEED_3 0x92 +#define PMBUS_READ_FAN_SPEED_4 0x93 +#define PMBUS_READ_DUTY_CYCLE 0x94 +#define PMBUS_READ_FREQUENCY 0x95 +#define PMBUS_READ_POUT 0x96 +#define PMBUS_READ_PIN 0x97 + +#define PMBUS_REVISION 0x98 +#define PMBUS_MFR_ID 0x99 +#define PMBUS_MFR_MODEL 0x9A +#define PMBUS_MFR_REVISION 0x9B +#define PMBUS_MFR_LOCATION 0x9C +#define PMBUS_MFR_DATE 0x9D +#define PMBUS_MFR_SERIAL 0x9E + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ +#define PMBUS_VIRT_BASE 0x100 +#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0) +#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1) +#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2) +#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3) +#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4) +#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5) +#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6) +#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7) +#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8) +#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9) +#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10) +#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11) +#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12) +#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13) +#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14) +#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15) +#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16) +#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17) +#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18) +#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19) +#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20) +#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21) +#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22) +#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23) +#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24) +#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25) +#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26) +#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27) +#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28) +#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29) + +#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30) +#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31) +#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32) +#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33) +#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34) +#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT (1<<4) +#define PB_CAPABILITY_ERROR_CHECK (1<<7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1)) +#define PB_FAN_2_RPM (1 << 2) +#define PB_FAN_2_INSTALLED (1 << 3) +#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5)) +#define PB_FAN_1_RPM (1 << 6) +#define PB_FAN_1_INSTALLED (1 << 7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE (1<<0) +#define PB_STATUS_CML (1<<1) +#define PB_STATUS_TEMPERATURE (1<<2) +#define PB_STATUS_VIN_UV (1<<3) +#define PB_STATUS_IOUT_OC (1<<4) +#define PB_STATUS_VOUT_OV (1<<5) +#define PB_STATUS_OFF (1<<6) +#define PB_STATUS_BUSY (1<<7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN (1<<8) +#define PB_STATUS_OTHER (1<<9) +#define PB_STATUS_FANS (1<<10) +#define PB_STATUS_POWER_GOOD_N (1<<11) +#define PB_STATUS_WORD_MFR (1<<12) +#define PB_STATUS_INPUT (1<<13) +#define PB_STATUS_IOUT_POUT (1<<14) +#define PB_STATUS_VOUT (1<<15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING (1<<0) +#define PB_POUT_OP_FAULT (1<<1) +#define PB_POWER_LIMITING (1<<2) +#define PB_CURRENT_SHARE_FAULT (1<<3) +#define PB_IOUT_UC_FAULT (1<<4) +#define PB_IOUT_OC_WARNING (1<<5) +#define PB_IOUT_OC_LV_FAULT (1<<6) +#define PB_IOUT_OC_FAULT (1<<7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT (1<<4) +#define PB_VOLTAGE_UV_WARNING (1<<5) +#define PB_VOLTAGE_OV_WARNING (1<<6) +#define PB_VOLTAGE_OV_FAULT (1<<7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING (1<<0) +#define PB_IIN_OC_WARNING (1<<1) +#define PB_IIN_OC_FAULT (1<<2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT (1<<4) +#define PB_TEMP_UT_WARNING (1<<5) +#define PB_TEMP_OT_WARNING (1<<6) +#define PB_TEMP_OT_FAULT (1<<7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING (1<<0) +#define PB_FAN_AIRFLOW_FAULT (1<<1) +#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2) +#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3) +#define PB_FAN_FAN2_WARNING (1<<4) +#define PB_FAN_FAN1_WARNING (1<<5) +#define PB_FAN_FAN2_FAULT (1<<6) +#define PB_FAN_FAN1_FAULT (1<<7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0) +#define PB_CML_FAULT_OTHER_COMM (1<<1) +#define PB_CML_FAULT_PROCESSOR (1<<3) +#define PB_CML_FAULT_MEMORY (1<<4) +#define PB_CML_FAULT_PACKET_ERROR (1<<5) +#define PB_CML_FAULT_INVALID_DATA (1<<6) +#define PB_CML_FAULT_INVALID_COMMAND (1<<7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN (1 << 0) +#define PMBUS_HAVE_VCAP (1 << 1) +#define PMBUS_HAVE_VOUT (1 << 2) +#define PMBUS_HAVE_IIN (1 << 3) +#define PMBUS_HAVE_IOUT (1 << 4) +#define PMBUS_HAVE_PIN (1 << 5) +#define PMBUS_HAVE_POUT (1 << 6) +#define PMBUS_HAVE_FAN12 (1 << 7) +#define PMBUS_HAVE_FAN34 (1 << 8) +#define PMBUS_HAVE_TEMP (1 << 9) +#define PMBUS_HAVE_TEMP2 (1 << 10) +#define PMBUS_HAVE_TEMP3 (1 << 11) +#define PMBUS_HAVE_STATUS_VOUT (1 << 12) +#define PMBUS_HAVE_STATUS_IOUT (1 << 13) +#define PMBUS_HAVE_STATUS_INPUT (1 << 14) +#define PMBUS_HAVE_STATUS_TEMP (1 << 15) +#define PMBUS_HAVE_STATUS_FAN12 (1 << 16) +#define PMBUS_HAVE_STATUS_FAN34 (1 << 17) +#define PMBUS_HAVE_VMON (1 << 18) +#define PMBUS_HAVE_STATUS_VMON (1 << 19) + +enum pmbus_data_format { linear = 0, direct, vid }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); + + int fan_num; +}; + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +void _pmbus_clear_faults(struct i2c_client *client); +bool _pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool _pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int _pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); + +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-accton/common/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/common/modules/ym2651y.c new file mode 100755 index 000000000000..5834b1d4ef8b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/common/modules/ym2651y.c @@ -0,0 +1,676 @@ +/* + * An hwmon driver for the 3Y Power YM-2651Y Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END }; + +enum chips { + YM2651, + YM2401, + YM2851, + YPEB1200AM +}; + +/* Each client has this additional data + */ +struct ym2651y_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 chip; /* chip id */ + u8 capability; /* Register value */ + u16 status_word; /* Register value */ + u8 fan_fault; /* Register value */ + u8 over_temp; /* Register value */ + u16 v_out; /* Register value */ + u16 i_out; /* Register value */ + u16 p_out; /* Register value */ + u8 vout_mode; /* Register value */ + u16 temp; /* Register value */ + u16 fan_speed; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u8 fan_dir[4]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[10]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ +}; + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct ym2651y_data *ym2651y_update_device(struct device *dev); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum ym2651y_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/ + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_vout, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + +static struct attribute *ym2651y_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u16 status = 0; + + switch (attr->index) { + case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ + status = (data->status_word & 0x40) ? 0 : 1; + break; + case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ + status = (data->status_word & 0x4) >> 2; + break; + case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ + status = (data->status_word & 0x800) ? 0 : 1; + break; + } + + return sprintf(buf, "%d\n", status); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_OUT: + value = data->v_out; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_OUT_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + case PSU_FAN1_DUTY_CYCLE: + value = data->fan_duty_cycle[0]; + multiplier = 1; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_VOUT_MIN: + value = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + value = data->mfr_vout_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + + return sprintf(buf, "%d\n", data->over_temp >> 7); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 *ptr = NULL; + + switch (attr->index) { + case PSU_FAN_DIRECTION: /* psu_fan_dir */ + if (data->chip==YPEB1200AM) + { + memcpy(data->fan_dir, "F2B", 3); + data->fan_dir[3]='\0'; + } + ptr = data->fan_dir; + break; + case PSU_MFR_ID: /* psu_mfr_id */ + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: /* psu_mfr_revision */ + ptr = data->mfr_revsion; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static ssize_t show_vout_by_mode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + if (!data->valid) { + return 0; + } + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + switch (attr->index) { + case PSU_MFR_VOUT_MIN: + mantissa = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + mantissa = data->mfr_vout_max; + break; + case PSU_V_OUT: + mantissa = data->v_out; + break; + default: + return 0; + } + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_vout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + if (data->chip == YM2401) { + return show_vout_by_mode(dev, da, buf); + } + else { + return show_linear(dev, da, buf); + } +} + +static const struct attribute_group ym2651y_group = { + .attrs = ym2651y_attributes, +}; + +static int ym2651y_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ym2651y_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->chip = dev_id->driver_data; + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int ym2651y_remove(struct i2c_client *client) +{ + struct ym2651y_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id ym2651y_id[] = { + { "ym2651", YM2651 }, + { "ym2401", YM2401 }, + { "ym2851", YM2851 }, + { "ype1200am", YPEB1200AM }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ym2651y_id); + +static struct i2c_driver ym2651y_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ym2651", + }, + .probe = ym2651y_probe, + .remove = ym2651y_remove, + .id_table = ym2651y_id, + .address_list = normal_i2c, +}; + +static int ym2651y_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int ym2651y_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct ym2651y_data *ym2651y_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + u8 command; + u8 fan_dir[5] = {0}; + struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, + {0x20, &data->vout_mode}, + {0x7d, &data->over_temp}, + {0x81, &data->fan_fault}, + {0x98, &data->pmbus_revision} + }; + struct reg_data_word regs_word[] = { {0x79, &data->status_word}, + {0x8b, &data->v_out}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x8d, &data->temp}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &data->fan_speed}, + {0xa0, &data->mfr_vin_min}, + {0xa1, &data->mfr_vin_max}, + {0xa2, &data->mfr_iin_max}, + {0xa3, &data->mfr_pin_max}, + {0xa4, &data->mfr_vout_min}, + {0xa5, &data->mfr_vout_max}, + {0xa6, &data->mfr_iout_max}, + {0xa7, &data->mfr_pout_max} + }; + + dev_dbg(&client->dev, "Starting ym2651 update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = ym2651y_read_byte(client, regs_byte[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = ym2651y_read_word(client, regs_word[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read fan_direction */ + command = 0xC3; + status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + } + + strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1); + data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; + + /* Read mfr_id */ + command = 0x99; + status = ym2651y_read_block(client, command, data->mfr_id, + ARRAY_SIZE(data->mfr_id)-1); + data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_model */ + command = 0x9a; + status = ym2651y_read_block(client, command, data->mfr_model, + ARRAY_SIZE(data->mfr_model)-1); + data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_revsion */ + command = 0x9b; + status = ym2651y_read_block(client, command, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)-1); + data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(ym2651y_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/changelog b/platform/broadcom/sonic-platform-modules-accton/debian/changelog new file mode 100755 index 000000000000..2b08b12c206a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/changelog @@ -0,0 +1,18 @@ +sonic-accton-platform-modules (1.1) unstable; urgency=low + + * Add support for AS7816-64X. + + -- Accton Network Tue, 19 Dec 2017 09:35:58 +0800 + +sonic-accton-platform-modules (1.1) unstable; urgency=low + + * Add support for Accton AS5712-54X + + -- Accton Network Wed, 11 Oct 2017 14:21:45 +0800 + +sonic-accton-platform-modules (1.0) unstable; urgency=low + + * Add support for Accton AS7712-32X + * Initial release + + -- Accton Network Thu, 01 Jun 2017 14:06:38 +0800 diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/compat b/platform/broadcom/sonic-platform-modules-accton/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control new file mode 100755 index 000000000000..2b3c1af3d80f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/control @@ -0,0 +1,78 @@ +Source: sonic-accton-platform-modules +Section: main +Priority: extra +Maintainer: Accton network , Accton Network , Accton Network , Accton Network +Build-Depends: debhelper (>= 9), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-accton-as7712-32x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as5712-54x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7816-64x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7716-32x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7716-32xb +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7312-54x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7326-56x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as6712-32x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7726-32x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as4630-54pe +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-minipack +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as5812-54x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as5812-54t +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as5835-54x +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as9716-32d +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as5835-54t +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7312-54xs +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-accton-as7315-27xb +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/rules b/platform/broadcom/sonic-platform-modules-accton/debian/rules new file mode 100755 index 000000000000..e894b10f8234 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules @@ -0,0 +1,94 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 +PYTHON3 ?= python3 + +PACKAGE_PRE_NAME := sonic-platform-accton +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS := as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x +MODULE_DIRS += as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x +MODULE_DIRS += as5835-54x as9716-32d as5835-54t as7312-54xs as7315-27xb as5812-54t +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + cd $(MOD_SRC_DIR)/$${mod}; \ + if [ -f sonic_platform_setup.py ]; then \ + $(PYTHON3) sonic_platform_setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}; \ + echo "Finished makig whl package for $$mod"; \ + fi; \ + cd $(MOD_SRC_DIR); \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as7312-54x.install b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as7312-54x.install new file mode 100644 index 000000000000..c0e14a1f6b1b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as7312-54x.install @@ -0,0 +1,2 @@ +as7312-54x/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-accton_as7312_54x-r0 + diff --git a/platform/broadcom/sonic-platform-modules-accton/minipack/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/minipack/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-accton/minipack/classes/pimutil.py b/platform/broadcom/sonic-platform-modules-accton/minipack/classes/pimutil.py new file mode 100755 index 000000000000..778ff76afd19 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/minipack/classes/pimutil.py @@ -0,0 +1,578 @@ +# Copyright (c) 2019 Edgecore Networks Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 5/29/2019: Jostar create for minipack +# ----------------------------------------------------------- +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + import fbfpgaio + import re + import time + from select import select + #from ctypes import fbfpgaio + +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +# pimutil.py +# +# Platform-specific PIM interface for SONiC +# + +iob = { + "revision": 0x0, + "scratchpad": 0x4, + "interrupt_status": 0x2C, + "pim_status": 0x40, + "pim_present_intr_mask": 0x44, +} + +dom_base = [ + 0xFFFFFFFF, # Padding + 0x40000, + 0x48000, + 0x50000, + 0x58000, + 0x60000, + 0x68000, + 0x70000, + 0x78000, +] + + +dom = { + "revision": 0x0, + "system_led": 0xC, + "intr_status": 0x2C, + "qsfp_present": 0x48, + "qsfp_present_intr": 0x50, + "qsfp_present_intr_mask": 0x58, + "qsfp_intr": 0x60, + "qsfp_intr_mask": 0x68, + "qsfp_reset": 0x70, + "qsfp_lp_mode": 0x78, + "device_power_bad_status": 0x90, + "port_led_color_profile": { + 0: 0x300, + 1: 0x300, + 2: 0x304, + 3: 0x304, + 4: 0x308, + 5: 0x308, + 6: 0x30C, + 7: 0x30C, + }, + "port_led_control": { + 1: 0x310, + 2: 0x314, + 3: 0x318, + 4: 0x31C, + 5: 0x320, + 6: 0x324, + 7: 0x328, + 8: 0x32C, + 9: 0x330, + 10: 0x334, + 11: 0x338, + 12: 0x33C, + 13: 0x340, + 14: 0x344, + 15: 0x348, + 16: 0x34C, + }, + "dom_control_config": 0x410, + "dom_global_status": 0x414, + "dom_data": 0x4000, + + + "mdio": { + "config": 0x0200, + "command": 0x0204, + "write": 0x0208, + "read": 0x020C, + "status": 0x0210, + "intr_mask": 0x0214, + "source_sel": 0x0218, + }, # mdio +} + +mdio_read_cmd = 0x1 +mdio_write_cmd = 0x0 +mdio_device_type = 0x1F + + +#fbfpgaio=cdll.LoadLibrary('./fbfpgaio.so') + +def init_resources(): + fbfpgaio.hw_init() + return + +def release_resources(): + fbfpgaio.hw_release() + return + +def fpga_io(offset, data=None): + if data is None: + return fbfpgaio.hw_io(offset) + else: + fbfpgaio.hw_io(offset, data) + return + +def pim_io(pim, offset, data=None): + global dom_base + target_offset = dom_base[pim]+offset + if data is None: + retval = fpga_io(target_offset) + #print ("0x%04X" % retval) # idebug + return retval + else: + retval = fpga_io(target_offset, data) + return retval + + +def show_pim_present(): + pim_status = fpga_io(iob["pim_status"]) + + header = "PIM # " + status_str = " " + for shift in range(0,8): + status = pim_status & (0x10000 << shift) #[23:16] from pim_0 to pim_7 + header += " %d " % (shift+1) + if status: + status_str += (" | ") + else: + status_str += (" X ") + print(header) + print(status_str) + +def show_qsfp_present_status(pim_num): + status = fpga_io(dom_base[pim_num]+dom["qsfp_present"]) + interrupt = fpga_io(dom_base[pim_num]+dom["qsfp_present_intr"]) + mask = fpga_io(dom_base[pim_num]+dom["qsfp_present_intr_mask"]) + + print + print(" (0x48) (0x50) (0x58)") + print(" 0x%08X 0x%08X 0x%08X" %(status, interrupt, mask)) + print(" Status Interrupt Mask") + for row in range(8): + output_str = str() + status_left = bool(status & (0x1 << row*2)) + status_right = bool(status & (0x2 << row*2)) + interrupt_left = bool(interrupt & (0x1 << row*2)) + interrupt_right = bool(interrupt & (0x2 << row*2)) + mask_left = bool(mask & (0x1 << row*2)) + mask_right = bool(mask & (0x2 << row*2)) + print("%2d: %d %d %d %d %d %d" % \ + (row*2+1, status_left, status_right, \ + interrupt_left, interrupt_right, \ + mask_left, mask_right)) + print + + + +#pim_index start from 0 to 7 +#port_index start from 0 to 127. Each 16-port is to one pim card. +class PimUtil(object): + + PORT_START = 0 + PORT_END = 127 + + def __init__(self): + self.value=1 + + def __del__(self): + self.value=0 + + def init_pim_fpga(self): + init_resources() + + def release_pim_fpga(self): + release_resources() + + def get_pim_by_port(self, port_num): + if port_num < self.PORT_START or port_num > self.PORT_END: + return False + pim_num=port_num/16 + return True, pim_num+1 + + def get_onepimport_by_port(self, port_num): + if port_num < self.PORT_START or port_num > self.PORT_END: + return False + if port_num < 16: + return True, port_num + else: + return True, port_num%16 + + def get_pim_presence(self, pim_num): + if pim_num <0 or pim_num > 7: + return 0 + pim_status = fpga_io(iob["pim_status"]) + status = pim_status & (0x10000 << pim_num) + if status: + return 1 #present + else: + return 0 #not present + + #return code=0:100G. return code=1:400G + def get_pim_board_id(self, pim_num): + if pim_num <0 or pim_num > 7: + return False + board_id = fpga_io(dom_base[pim_num+1]+dom["revision"]) + board_id = board_id & 0x1 + if board_id==0x0: + return 0 + else: + return 1 + + + def get_pim_status(self, pim_num): + if pim_num <0 or pim_num > 7: + return 0xFF + power_status =0 + #device_power_bad_status + status=fpga_io(dom_base[pim_num+1]+dom["device_power_bad_status"]) + + for x in range(0, 5): + if status & ( (0xf) << (4*x) ) : + power_status = power_status | (0x1 << x) + + if ( status & 0x1000000): + power_status=power_status | (0x1 << 5) + if ( status & 0x2000000): + power_status=power_status | (0x1 << 6) + if ( status & 0x8000000): + power_status=power_status | (0x1 << 7) + if ( status & 0x10000000): + power_status=power_status | (0x1 << 8) + if ( status & 0x40000000): + power_status=power_status | (0x1 << 9) + if ( status & 0x80000000): + power_status=power_status | (0x1 << 10) + + return power_status + #path=0:MDIO path is set on TH3. path=1:MDIO path is set on FPGA. + def set_pim_mdio_source_sel(self, pim_num, path): + if pim_num <0 or pim_num > 7: + return False + status= pim_io(pim_num+1, dom["mdio"]["source_sel"]) + + if path==1: + status = status | 0x2 + else: + status = status & 0xfffffffd + + pim_io(pim_num+1, dom["mdio"]["source_sel"], status) + return True + #retrun code=0, path is TH3. retrun code=1, path is FPGA + def get_pim_mdio_source_sel(sefl, pim_num): + if pim_num <0 or pim_num > 7: + return False + path= pim_io(pim_num+1, dom["mdio"]["source_sel"]) + path = path & 0x2 + if path: + return 1 + else: + return 0 + + #This api will set mdio path to MAC side.(At default, mdio path is set to FPGA side). + def pim_init(self, pim_num): + if pim_num <0 or pim_num > 7: + return False + status=self.set_pim_mdio_source_sel(pim_num, 0) + #put init phy cmd here + + + #return code="pim_dict[pim_num]='1' ":insert evt. return code="pim_dict[pim_num]='0' ":remove evt + def get_pim_change_event(self, timeout=0): + start_time = time.time() + pim_dict = {} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print "get_transceiver_change_event:Invalid timeout value", timeout + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print 'get_transceiver_change_event:' \ + 'time wrap / invalid timeout value', timeout + + return False, {} # Time wrap or possibly incorrect timeout + + pim_mask_status = fpga_io(iob["pim_present_intr_mask"], 0xffff00000) + + while timeout >= 0: + new_pim_status=0 + pim_status = fpga_io(iob["pim_status"]) + present_status= pim_status & 0xff0000 + change_status=pim_status & 0xff + interrupt_status = fpga_io(iob["interrupt_status"]) + + for pim_num in range(0,8): + if change_status & (0x1 << pim_num) : + status = present_status & (0x10000 << pim_num) + new_pim_status = new_pim_status | (0x1 << pim_num) #prepare to W1C to clear + if status: + pim_dict[pim_num]='1' + else: + pim_dict[pim_num]='0' + + if change_status: + new_pim_status = pim_status | new_pim_status #Write one to clear interrupt bit + fpga_io(iob["pim_status"], new_pim_status) + return True, pim_dict + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + print "get_evt_change_event: Should not reach here." + return False, {} + + + def get_pim_max_number(self): + return 8 + + #pim_num start from 0 to 7 + #color:0=amber, 1=blue + #contrl:off(0),on(1), flash(2) + def set_pim_led(self, pim_num, color, control): + if pim_num <0 or pim_num > 7: + return False + + led_val=fpga_io(dom_base[pim_num+1]+dom["system_led"]) + + if color==1: + led_val = led_val | (0x8000 | 0x4000) #blue + elif color==0: + led_val = (led_val & ( ~ 0x8000)) | 0x4000 #amber + else: + print "Set RGB control to Green1" + led_val = led_val & (~ 0x4000) + led_val = led_val & (~ 0xfff) + led_val = led_val | 0x0f0 #B.G.R Birghtness, set to Green + + if control==0: + led_val = led_val & ( ~ 0x3000) #Off + elif control==1: + led_val = led_val & ( ~ 0x3000) #Off + led_val = led_val | 0x1000 #On + else: + led_val = led_val | 0x3000 #Flash + + fpga_io(dom_base[pim_num+1]+dom["system_led"], led_val) + + def get_qsfp_presence(self, port_num): + #xlate port to get pim_num + status, pim_num=self.get_pim_by_port(port_num) + + if status==0: + return False + else: + present = fpga_io(dom_base[pim_num]+dom["qsfp_present"]) + status, shift = self.get_onepimport_by_port(port_num) + if status==0: + return False + else: + if bool(present & (0x1 << shift)): + return 1 #present + else: + return 0 #not present + + #return code: low_power(1) or high_power(0) + def get_low_power_mode(self, port_num): + status, pim_num=self.get_pim_by_port(port_num) + + if status==0: + return False + else: + lp_mode = fpga_io(dom_base[pim_num]+dom["qsfp_lp_mode"]) + + status, shift=self.get_onepimport_by_port(port_num) + if status==0: + return False + else: + if (lp_mode & (0x1 << shift)): + return 1 #low + else: + return 0 #high + + #lpmode=1 to hold QSFP in low power mode. lpmode=0 to release QSFP from low power mode. + def set_low_power_mode(self, port_num, mode): + status, pim_num=self.get_pim_by_port(port_num) + if status==0: + return False + val = fpga_io(dom_base[pim_num]+dom["qsfp_lp_mode"]) + status, shift=self.get_onepimport_by_port(port_num) + if status==0: + return False + else: + if mode==0: + new_val = val & (~(0x1 << shift)) + else: + new_val=val|(0x1 << shift) + status=fpga_io(dom_base[pim_num]+dom["qsfp_lp_mode"], new_val) + return status + + #port_dict[idx]=1 means get interrupt(change evt), port_dict[idx]=0 means no get interrupt + def get_qsfp_interrupt(self): + port_dict={} + #show_qsfp_present_status(1) + for pim_num in range(0, 8): + fpga_io(dom_base[pim_num+1]+dom["qsfp_present_intr_mask"], 0xffff0000) + fpga_io(dom_base[pim_num+1]+dom["qsfp_intr_mask"], 0xffff0000) + for pim_num in range(0, 8): + clear_bit=0 + qsfp_present_intr_status = fpga_io(dom_base[pim_num+1]+dom["qsfp_present_intr"]) + interrupt_status = qsfp_present_intr_status & 0xffff + #time.sleep(2) + if interrupt_status: + for idx in range (0,16): + port_idx=idx + (pim_num*16) + if interrupt_status & (0x1< +#include +#include +#include +#include + +//#define IDEBUG(...) printf(__VA_ARGS__) +#define IDEBUG(...) + +#define FPGA_RESOURCE_NODE "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0/resource0" +#define FPGA_RESOURCE_LENGTH 0x80000 + + +static int hw_handle = -1; +static void *io_base = NULL; + +static PyObject *fbfpgaio_hw_init(PyObject *self) +{ + const char fpga_resource_node[] = FPGA_RESOURCE_NODE; + + /* Open hardware resource node */ + hw_handle = open(fpga_resource_node, O_RDWR|O_SYNC); + if (hw_handle == -1) { + IDEBUG("[ERROR] %s: open hw resource node\n", __func__); + return Py_False; + } + + IDEBUG("[PASS] %s: open hw resource node\n", __func__); + + /* Mapping hardware resource */ + io_base = mmap(NULL, FPGA_RESOURCE_LENGTH, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, hw_handle, 0); + if (io_base == MAP_FAILED) { + IDEBUG("[ERROR] %s: mapping resource node\n", __func__); + perror("map_failed"); + fprintf(stderr,"%d %s\\n",errno,strerror(errno)); + return Py_False; + } + + IDEBUG("[PASS] %s: mapping resource node\n", __func__); + + return Py_True; +} + +static PyObject *fbfpgaio_hw_release(PyObject *self) +{ + int retval = 0; + + if ((io_base != NULL) && (io_base != MAP_FAILED)) { + retval = munmap(io_base, FPGA_RESOURCE_LENGTH); + if (retval == 0) { + IDEBUG("[PASS] %s: Unmapping hardware resources\n", __func__); + close(hw_handle); + return Py_True; + } + } + + IDEBUG("[ERROR] %s: unmapping resource node\n", __func__); + return Py_False; +} + +static PyObject *fbfpgaio_hw_io(PyObject *self, PyObject *args) +{ + void *offset = NULL; + /* We are not able to diffrentiate the input data between an unsigned value or a + 'None' object. We assume that the input data (if any) will be an unsigned integer. + The default value of 'data' is larger than the max. number of unsigned integer. + This value signify that the caller of this function does not input a data argument. */ + unsigned long input_data = 0x1FFFFFFFF; + + if (!PyArg_ParseTuple(args, "I|k", &offset, &input_data)) { + return NULL; + } + + if (input_data == 0x1FFFFFFFF) { + // Read operation + IDEBUG("Read operation\n"); + unsigned int *address = (unsigned int *) ((unsigned long) io_base + (unsigned long) offset); + return Py_BuildValue("k", *address); + } else { + // Write operation + IDEBUG("Write operation\n"); + unsigned int *address = (unsigned int *) ((unsigned long) io_base + (unsigned long) offset); + unsigned int data = (unsigned int) (input_data & 0xFFFFFFFF); + *address = data; + + Py_INCREF(Py_None); + return Py_None; + } +} + +static PyMethodDef FbfpgaMethods[] = { + { "hw_init", (PyCFunction) fbfpgaio_hw_init, METH_NOARGS, "Initialize resources for accessing FPGA" }, + { "hw_release", (PyCFunction) fbfpgaio_hw_release, METH_NOARGS, "Release resources for accessing FPGA" }, + { "hw_io", fbfpgaio_hw_io, METH_VARARGS, "Access FPGA" }, + { NULL, NULL, 0, NULL }, +}; + +PyMODINIT_FUNC +initfbfpgaio(void) +{ + char docstr[] = "\ +1. hw_init():\n\ + return value: True/False\n\ +2. hw_release():\n\ + return value: True/False\n\ +3. hw_io(offset,[data])\n\ + return value:\n\ + In reading operation: data which is read from FPGA\n\ + In writing operation: None\n"; + + (void) Py_InitModule3("fbfpgaio", FbfpgaMethods, docstr); +} diff --git a/platform/broadcom/sonic-platform-modules-accton/minipack/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/minipack/modules/Makefile new file mode 100644 index 000000000000..607c2ce7607f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/minipack/modules/Makefile @@ -0,0 +1 @@ +obj-m:= minipack_psensor.o diff --git a/platform/broadcom/sonic-platform-modules-accton/minipack/modules/minipack_psensor.c b/platform/broadcom/sonic-platform-modules-accton/minipack/modules/minipack_psensor.c new file mode 100755 index 000000000000..3155b2b27c4f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/minipack/modules/minipack_psensor.c @@ -0,0 +1,1097 @@ +/* + * A hwmon driver for the minipack. + * + * Copyright (C) 2018 Accton Technology Corporation. + * Roy Lee + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * This driver retrieves sensors' data through uart interface by opening + * an user-space tty device node. + * Designed pariticular for ethernet switch with BMC. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DEBUG_BUF_LEN 256 +#define DEBUG_INTR(args...) \ + debug_print(__func__, __LINE__, 1, args) + +static unsigned int verbose = 0; +module_param(verbose, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(verbose, "Print more information for debugging. Default is disabled."); + +static unsigned int poll_interval = 9; +module_param(poll_interval, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(poll_interval, "Time interval for data polling, in unit of second."); + + +#define DRVNAME "minipack_psensor" /*Platform Sensor*/ + +#define MAX_THERMAL_COUNT 8 +#define MAX_FAN_COUNT (8) +#define MAX_PSU_COUNT (4) +#define CHASSIS_PSU_CHAR_COUNT (2) /*2 for input and output.*/ +#define CHASSIS_LED_COUNT (2) +#define CHASSIS_PSU_VOUT_COUNT (1) /*V output only.*/ +#define CHASSIS_PSU_VOUT_INDEX (1) /*V output start index.*/ + + +#define ATTR_ALLOC_EXTRA 1 /*For last attribute which is NUll.*/ +#define ATTR_NAME_SIZE 24 +#define ATTR_NAME_OUTFIT_SIZE 12 +#define ATTR_MAX_LIST 8 + +#define TTY_DEVICE "/dev/ttyACM0" +#define TTY_PROMPT "@bmc-oob" +#define TTY_USER "root" +#define TTY_PASSWORD "0penBmc" +#define TTY_BAUDRATE (57600) +#define TTY_LOGIN_RETRY 10 +#define TTY_LOGIN_RETRY_INTV (200) +#define TTY_RETRY_INTERVAL (100) /*mini-seconds*/ +#define TTY_RESPONSE_INTERVAL (1000) /*mini-seconds*/ +#define TTY_PMBUS_INTERVAL (1800) /*mini-seconds*/ +#define MAXIMUM_TTY_BUFFER_LENGTH 1024 +#define MAXIMUM_TTY_STRING_LENGTH (MAXIMUM_TTY_BUFFER_LENGTH - 1) +#define TTY_CMD_RETRY 3 +#define TTY_RX_RETRY 3 +#define TTY_CMD_MAX_LEN (64) +#define TTY_READ_MAX_LEN (256) + +#define TTY_RESP_SEPARATOR '|' /*For the ease to debug*/ +#define MAX_ATTR_PATTERN (8) +#define MIN_FAN_RPM (0) +#define MAX_PSU_VOUT (12000*1005/1000) /*12 + 0.5%*/ +#define MIN_PSU_VOUT (12000*995/1000) /*12 - 0.5%*/ + +#define ATTR_TYPE_INDEX_GAP (100) + +enum sensor_type_e { + SENSOR_TYPE_THERMAL, + SENSOR_TYPE_FAN_RPM, + SENSOR_TYPE_FAN_RPM_DN, + SENSOR_TYPE_PSU1, + SENSOR_TYPE_PSU2, + SENSOR_TYPE_PSU3, + SENSOR_TYPE_PSU4, + SENSOR_TYPE_MAX, +}; + +enum sysfs_attributes_index { + INDEX_THRM_IN_START = SENSOR_TYPE_THERMAL *ATTR_TYPE_INDEX_GAP, + INDEX_FAN_RPM_START = SENSOR_TYPE_FAN_RPM *ATTR_TYPE_INDEX_GAP, + INDEX_FAN_RPM_START_DN = SENSOR_TYPE_FAN_RPM_DN*ATTR_TYPE_INDEX_GAP, + INDEX_PSU1_START = SENSOR_TYPE_PSU1 *ATTR_TYPE_INDEX_GAP, + INDEX_PSU2_START = SENSOR_TYPE_PSU2 *ATTR_TYPE_INDEX_GAP, + INDEX_PSU3_START = SENSOR_TYPE_PSU3 *ATTR_TYPE_INDEX_GAP, + INDEX_PSU4_START = SENSOR_TYPE_PSU4 *ATTR_TYPE_INDEX_GAP, + INDEX_NAME = SENSOR_TYPE_MAX *ATTR_TYPE_INDEX_GAP, +}; + +/* Pmbus reg defines are copied from drivers/hwmon/pmbus/pmbus.h*/ +#define PMBUS_READ_VIN 0x88 +#define PMBUS_READ_IIN 0x89 +#define PMBUS_READ_VOUT 0x8B +#define PMBUS_READ_IOUT 0x8C +#define PMBUS_READ_POUT 0x96 +#define PMBUS_READ_PIN 0x97 + +#define PMBUS_REG_START PMBUS_READ_VIN +#define PMBUS_REG_END PMBUS_READ_PIN + +enum psu_data_e { + PSU_DATA_VIN = 0, + PSU_DATA_VOUT, + PSU_DATA_IIN, + PSU_DATA_IOUT, + PSU_DATA_PIN, + PSU_DATA_POUT, + PSU_DATA_MAX, +}; + +struct pmbus_reg_t { + u8 addr; + bool power; /*power attribute is in unit of uW instead of mW.*/ +} pmbus_regs[] = { + [PSU_DATA_VIN ] = {PMBUS_READ_VIN, false}, + [PSU_DATA_VOUT] = {PMBUS_READ_VOUT, false}, + [PSU_DATA_IIN ] = {PMBUS_READ_IIN, false}, + [PSU_DATA_IOUT] = {PMBUS_READ_IOUT, false}, + [PSU_DATA_PIN ] = {PMBUS_READ_PIN, true}, + [PSU_DATA_POUT] = {PMBUS_READ_POUT, true}, +}; + +struct sensor_data { + int lm75_input[MAX_THERMAL_COUNT]; + int fan_rpm[MAX_FAN_COUNT]; + int fan_rpm_dn[MAX_FAN_COUNT]; + int psu_data [MAX_PSU_COUNT][PSU_DATA_MAX]; + int led_bright[CHASSIS_LED_COUNT]; +}; + +struct psensor { + struct psensor *next; + char name[ATTR_NAME_SIZE+1]; /* sysfs sensor name */ + struct sensor_device_attribute sensor_dev_attr; +}; + +struct minipack_data { + struct platform_device *pdev; + struct device *dev; + struct device *hwmon_dev; + struct mutex update_lock; + struct tty_struct *tty; + struct ktermios old_ktermios; + bool logged_in; + bool valid[SENSOR_TYPE_MAX]; + unsigned long last_updated[SENSOR_TYPE_MAX]; /* In jiffies */ + struct sensor_data sdata; + int num_attributes; + struct attribute_group group; +}; + +typedef ssize_t (*show_func)( struct device *dev, + struct device_attribute *attr, char *buf); +typedef ssize_t (*store_func)(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count); +static ssize_t show_name(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t _attr_show(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_psu_vout_min(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_psu_vout_max(struct device *dev, struct device_attribute *da, + char *buf); +static int add_attr2group(struct minipack_data *data, struct attribute *attr); + + +struct attr_pattern { + int count; /*How many attr of this pattern*/ + int index_addon; /* For attribute naming, e.g. + * X of "fanX_input",start from a number but 0. + */ + char prefix[ATTR_NAME_OUTFIT_SIZE+1]; /*e.g. "temp"4_input*/ + char postfix[ATTR_NAME_OUTFIT_SIZE+1]; /*e.g. temp4"_input"*/ + umode_t mode; + show_func show; + store_func store; +}; + +struct sensor_set { + int total; /*How many attr of this type*/ + int start_index; + char *query; + u32 mdelay; /*TTY delay to read after sent.*/ + struct attr_pattern *ptn[MAX_ATTR_PATTERN]; +}; + + + +#define DECLARE_PSU_SENSOR_DEVICE_ATTR(index) \ +static struct attr_pattern psu##index##_vin = {CHASSIS_PSU_CHAR_COUNT, \ +CHASSIS_PSU_CHAR_COUNT*index, "in","_input", S_IRUGO, _attr_show, NULL}; \ +static struct attr_pattern psu##index##_curr = {CHASSIS_PSU_CHAR_COUNT, \ +CHASSIS_PSU_CHAR_COUNT*index, "curr","_input", S_IRUGO, _attr_show, NULL}; \ +static struct attr_pattern psu##index##_pwr = {CHASSIS_PSU_CHAR_COUNT, \ +CHASSIS_PSU_CHAR_COUNT*index, "power","_input", S_IRUGO, _attr_show, NULL}; \ +static struct attr_pattern psu##index##_vmax = {CHASSIS_PSU_VOUT_COUNT, \ +CHASSIS_PSU_CHAR_COUNT*index + 1, "in","_max", S_IRUGO, show_psu_vout_max, NULL};\ +static struct attr_pattern psu##index##_vmin = {CHASSIS_PSU_VOUT_COUNT, \ +CHASSIS_PSU_CHAR_COUNT*index + 1, "in","_min", S_IRUGO, show_psu_vout_min, NULL} + +#define DECLARE_PSU_ATTR(index) \ + &psu##index##_vin, &psu##index##_curr, &psu##index##_pwr, \ + &psu##index##_vmax, &psu##index##_vmin + + +DECLARE_PSU_SENSOR_DEVICE_ATTR(0); +DECLARE_PSU_SENSOR_DEVICE_ATTR(1); +DECLARE_PSU_SENSOR_DEVICE_ATTR(2); +DECLARE_PSU_SENSOR_DEVICE_ATTR(3); + + + +static char tty_cmd[SENSOR_TYPE_MAX][TTY_CMD_MAX_LEN] = { + "ls -v /sys/class/hwmon/hwmon*/temp1_input|head -n "\ + __stringify(MAX_THERMAL_COUNT)"| xargs cat\r", + "ls -v /sys/bus/i2c/devices/72-0033/fan*_input | xargs cat\r", + "ls -v /sys/bus/i2c/devices/64-0033/fan*_input | xargs cat\r", + "i2cdump -y -f -r "\ + __stringify(PMBUS_REG_START)"-" __stringify(PMBUS_REG_END)\ + " 49 0x59 w\r", + "i2cdump -y -f -r "\ + __stringify(PMBUS_REG_START)"-" __stringify(PMBUS_REG_END)\ + " 48 0x58 w\r", + "i2cdump -y -f -r "\ + __stringify(PMBUS_REG_START)"-" __stringify(PMBUS_REG_END)\ + " 57 0x59 w\r", + "i2cdump -y -f -r "\ + __stringify(PMBUS_REG_START)"-" __stringify(PMBUS_REG_END)\ + " 56 0x58 w\r", +}; + +static struct attr_pattern temp_in = +{ MAX_THERMAL_COUNT, 0, "temp","_input", + S_IRUGO, _attr_show, NULL +}; +static struct attr_pattern fan_in_up = +{ MAX_FAN_COUNT, 0, "fan","_input", + S_IRUGO, _attr_show, NULL +}; +static struct attr_pattern fan_min_up = +{ MAX_FAN_COUNT, 0, "fan","_min", + S_IRUGO, show_fan_min, NULL +}; +static struct attr_pattern fan_in_dw = +{ MAX_FAN_COUNT, MAX_FAN_COUNT, "fan","_input", + S_IRUGO, _attr_show, NULL +}; +static struct attr_pattern fan_min_dw = +{ MAX_FAN_COUNT, MAX_FAN_COUNT, "fan","_min", + S_IRUGO, show_fan_min, NULL +}; + +struct sensor_set model_ssets[SENSOR_TYPE_MAX] = +{ + { MAX_THERMAL_COUNT, INDEX_THRM_IN_START, tty_cmd[SENSOR_TYPE_THERMAL], + TTY_RESPONSE_INTERVAL, {&temp_in, NULL}, + }, + { MAX_FAN_COUNT, INDEX_FAN_RPM_START, tty_cmd[SENSOR_TYPE_FAN_RPM], + TTY_RESPONSE_INTERVAL, {&fan_in_up, &fan_min_up, NULL}, + }, + { MAX_FAN_COUNT, INDEX_FAN_RPM_START_DN, tty_cmd[SENSOR_TYPE_FAN_RPM_DN], + TTY_RESPONSE_INTERVAL, {&fan_in_dw, &fan_min_dw, NULL}, + }, + { PSU_DATA_MAX, INDEX_PSU1_START, tty_cmd[SENSOR_TYPE_PSU1], + TTY_PMBUS_INTERVAL, {DECLARE_PSU_ATTR(0), NULL}, + }, + { PSU_DATA_MAX, INDEX_PSU2_START, tty_cmd[SENSOR_TYPE_PSU2], + TTY_PMBUS_INTERVAL, {DECLARE_PSU_ATTR(1), NULL}, + }, + { PSU_DATA_MAX, INDEX_PSU3_START, tty_cmd[SENSOR_TYPE_PSU3], + TTY_PMBUS_INTERVAL, {DECLARE_PSU_ATTR(2), NULL}, + }, + { PSU_DATA_MAX, INDEX_PSU4_START, tty_cmd[SENSOR_TYPE_PSU4], + TTY_PMBUS_INTERVAL, {DECLARE_PSU_ATTR(3), NULL}, + }, +}; +static struct minipack_data *mp_data = NULL; + +/*-----------------------------------------------------------------------*/ + +static void debug_print(const char *func, int line, int level, + const char *fmt, ...) +{ + va_list args; + char buf[DEBUG_BUF_LEN]; + if (verbose >= level) { + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + pr_info("[DBG]%s#%d: %s\n", func, line, buf); + } +} + + + +static int _tty_wait(u32 mdelay) { + if (mdelay) { + msleep(mdelay); + } + return 0; +} + +static int _tty_open(struct file **fd) +{ + struct ktermios kt; + struct tty_struct *tty; + speed_t baudrate = 57600; + struct file *tty_fd = *fd; + + /*TTY must be not opened.*/ + if (tty_fd != NULL) { + return -EINVAL; + } + + tty_fd = filp_open(TTY_DEVICE, O_RDWR|O_NOCTTY|O_NDELAY, 0644); + if (IS_ERR(tty_fd)) { + DEBUG_INTR("Failed to open file(%s)\r\n", TTY_DEVICE); + return -ENOENT; + } else { + spin_lock(&tty_fd->f_lock); + tty = ((struct tty_file_private *)tty_fd ->private_data)->tty; + mp_data->old_ktermios = (tty->termios); + + kt = tty->termios; + tty_termios_encode_baud_rate(&kt, baudrate, baudrate); + kt.c_cflag = B57600 | CS8 | CLOCAL | CREAD; + kt.c_iflag = IGNPAR; + kt.c_oflag = 0; + kt.c_lflag = 0; + kt.c_cc[VMIN] = (unsigned char) + ((MAXIMUM_TTY_STRING_LENGTH > 0xFF) ? + 0xFF : MAXIMUM_TTY_STRING_LENGTH); + kt.c_cc[VTIME] = 0; + tty_set_termios(tty, &kt); + + mp_data->tty = tty ; + *fd = tty_fd; + return 0; + } + return -ENXIO; +} + +static int _tty_close(struct file **tty_fd) +{ + struct file *fd = *tty_fd; + + if(*tty_fd == NULL) { + return -EINVAL; + } + spin_unlock(&fd->f_lock); + filp_close(*tty_fd, 0); + *tty_fd = NULL; + + return 0; +} + +static int _tty_tx(struct file *tty_fd, const char *str) +{ + int rc; + + /*Sanity check*/ + if (tty_fd == NULL) + return -EINVAL; + if(!(tty_fd->f_op) || !(tty_fd->f_op->read) ||!(tty_fd->f_op->write)) { + return -EINVAL; + } + + rc = tty_fd->f_op->write(tty_fd, str, strlen(str)+1,0); + if (rc < 0) { + pr_info( "failed to write(%d)\n", rc); + return -EBUSY; + } + DEBUG_INTR("[TX]%s-%d, %d BYTES, write:\n\"%s\"\n", __func__, __LINE__,rc, str); + return rc; +} + +static int _tty_rx(struct file *tty_fd, char *buf, int max_len) +{ + int rc; + u32 timeout = 0; + + /*Sanity check*/ + if (tty_fd == NULL) + return -EINVAL; + if(!(tty_fd->f_op) || !(tty_fd->f_op->read) ||!(tty_fd->f_op->write)) { + return -EINVAL; + } + + /*Clear for remained data cause ambiguous string*/ + memset(buf, 0, max_len); + do { + rc = tty_fd->f_op->read(tty_fd, buf, max_len, 0); + if (rc == 0) { /*Buffer Empty, waits. */ + timeout++; + _tty_wait(TTY_RETRY_INTERVAL); + continue; + } else { + break; + } + } while (rc < 0 && timeout < TTY_RX_RETRY); + + if (timeout == TTY_RX_RETRY) { + rc = -EAGAIN; + } + DEBUG_INTR("[RX]%s-%d, %d BYTES, read:\n\"%s\"\n", __func__, __LINE__,rc, buf); + return rc; +} + +/*Clear Rx buffer by reading it out.*/ +static int _tty_clear_rxbuf(struct file *tty_fd, char* buf, size_t max_size) { + int rc, i; + mm_segment_t old_fs; + int retry = TTY_CMD_RETRY; + + if (tty_fd == NULL) { + return -EINVAL; + } + old_fs = get_fs(); + set_fs(KERNEL_DS); + i = 0; + do { + rc = tty_fd->f_op->read(tty_fd, buf, max_size, 0); + memset(buf, 0, max_size); + i++; + } while (rc > 0 && i < retry); + + set_fs(old_fs); + return rc; +} + +static int _tty_writeNread(struct file *tty_fd, + char *wr_p, char *rd_p, int rx_max_len, u32 mdelay) +{ + int rc; + mm_segment_t old_fs; + + /*Presumed file is opened!*/ + if (tty_fd == NULL) + return -EINVAL; + + if(!(tty_fd->f_op) || !(tty_fd->f_op->read) ||!(tty_fd->f_op->write)) { + pr_info("file %s cann't readable or writable?\n", TTY_DEVICE); + return -EINVAL; + } + + memset(rd_p, 0, rx_max_len); + old_fs = get_fs(); + set_fs(KERNEL_DS); + rc = _tty_tx(tty_fd, wr_p); + if (rc < 0) { + DEBUG_INTR( "failed to write(%d)\n", rc); + goto exit; + } + _tty_wait(mdelay); + rc = _tty_rx(tty_fd, rd_p, rx_max_len); + if (rc < 0) { + DEBUG_INTR("failed to read(%d)\n", rc); + goto exit; + } + +exit: + set_fs(old_fs); + return rc; +} + +static bool _is_logged_in(struct file *tty_fd, char* buf, size_t max_size) +{ + int i, ret; + + if (mp_data->logged_in) { + return true; + } + + _tty_clear_rxbuf(tty_fd, buf, max_size); + for (i = 0; i < TTY_LOGIN_RETRY; i++) { + ret = _tty_writeNread(tty_fd, "\r\r", buf, max_size, TTY_RETRY_INTERVAL); + if (ret < 0) { + DEBUG_INTR("%s-%d, failed ret:%d\n", __func__, __LINE__, ret); + continue; + } + + DEBUG_INTR("%s-%d, tty_buf:%s\n", __func__, __LINE__, buf); + /*Check if logined by comparing BMC's cmd prompt.*/ + if (strstr(buf, TTY_PROMPT) != NULL) { + mp_data->logged_in = true; + return true; + } else { + return false; + } + } + return false; + +} + +static int _tty_login(struct file *tty_fd, char* buf, size_t max_size) +{ + int i; + int ret = -EINVAL; + + if(!tty_fd) + return -EINVAL; + + for (i = 1; i <= TTY_LOGIN_RETRY; i++) { + if (_is_logged_in(tty_fd, buf, max_size)) + return 0; + + DEBUG_INTR("%s-%d, tty_buf:%s\n", __func__, __LINE__, buf); + if ((strstr(buf, "bmc") != NULL) && + (strstr(buf, "login:") != NULL)) + { + ret = _tty_writeNread(tty_fd, TTY_USER"\r", + buf, max_size, TTY_LOGIN_RETRY_INTV); + if (ret < 0) { + DEBUG_INTR("%s-%d, failed ret:%d\n", __func__, __LINE__, ret); + continue; + } + DEBUG_INTR("%s-%d, tty_buf:%s\n", __func__, __LINE__, buf); + if (strstr(buf, "Password:") != NULL) { + DEBUG_INTR("%s-%d, tty_buf:%s\n", __func__, __LINE__, buf); + ret = _tty_writeNread(tty_fd, TTY_PASSWORD"\r", buf, max_size, 0); + if (ret < 0) { + DEBUG_INTR("%s-%d, failed ret:%d\n", __func__, __LINE__, ret); + continue; + } + if (strstr(buf, TTY_PROMPT) != NULL) { + DEBUG_INTR("%s-%d, tty_buf:%s\n", __func__, __LINE__, buf); + return 0; + } + } + } + _tty_wait(TTY_RETRY_INTERVAL); + } + + dev_err(mp_data->dev, "Failed on %s ret:%d\n", __func__, ret); + return -EAGAIN; +} + +static int +bmc_transaction(char *cmd, char* resp, int max, u32 mdelay) +{ + u32 i; + struct file *tty_fd = NULL; + char *buf; + int buf_size = MAXIMUM_TTY_BUFFER_LENGTH; + int ret = 0; + + if(!cmd || !resp) + return -EINVAL; + + if (_tty_open(&tty_fd) != 0) { + DEBUG_INTR("ERROR: Cannot open TTY device\n"); + return -EAGAIN; + } + buf = (char *)kmalloc(buf_size, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto exit; + } + if (_tty_login(tty_fd, buf, buf_size) != 0) { + dev_err(mp_data->dev, "Failed to login TTY device\n"); + _tty_close(&tty_fd); + ret = -ENOENT; + goto exit; + } + + i = 0; + do { + ret = _tty_writeNread(tty_fd, cmd, buf, buf_size, + mdelay+((i)*500)); + if (ret < 0) { + goto exit; + } + i++; + } while(strstr(buf, cmd) == NULL && i <= TTY_CMD_RETRY); + if (i > TTY_CMD_RETRY) { + ret = -ENOENT; + goto exit; + } + strncpy(resp, buf, max); +exit: + kfree(buf); + _tty_close(&tty_fd); + return ret; +} + +static void dev_attr_init(struct device_attribute *dev_attr, + const char *name, umode_t mode, + show_func show, store_func store) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +/*Allowcat sensor_device_attributes and adds them to a group.*/ +static int attributs_init(struct minipack_data *data) +{ + struct sensor_set *model = model_ssets; + char name[64] = {0}; + int start, pi, si, ai, num, ret, acc; + struct psensor *sensor; + struct sensor_device_attribute *sensor_dattr; + struct device_attribute *dev_attr; + + /*name*/ + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return -ENOENT; + sensor_dattr = &sensor->sensor_dev_attr; + dev_attr = &sensor_dattr->dev_attr; + snprintf(sensor->name, sizeof(sensor->name), "name"); + dev_attr_init(dev_attr, sensor->name, S_IRUGO, show_name, NULL); + sensor_dattr->index = INDEX_NAME; + ret = add_attr2group(data, &dev_attr->attr); + if (ret) + return ret; + + /*types*/ + for (si = 0; si < SENSOR_TYPE_MAX; si++) { + struct sensor_set *ss = model+si; + num = ss->total; + start = ss->start_index; + acc = start; + for (pi = 0; ss->ptn[pi]; pi++) + { + char *prefix, *postfix; + struct attr_pattern *ptn = ss->ptn[pi]; + prefix = ptn->prefix; + postfix = ptn->postfix; + for (ai = 0; ai < ptn->count ; ai++) { + u32 ptn_index = ai + ptn->index_addon + 1 ; + snprintf(name, sizeof(name), "%s%d%s",prefix, ptn_index, postfix); + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return -ENOENT; + + sensor_dattr = &sensor->sensor_dev_attr; + dev_attr = &sensor_dattr->dev_attr; + snprintf(sensor->name, sizeof(sensor->name), name); + dev_attr_init(dev_attr, sensor->name, ptn->mode, + ptn->show, ptn->store); + sensor_dattr->index = acc + ai; + + DEBUG_INTR("%s-%d, name:%s index:%d\n", __func__, __LINE__, + name, sensor_dattr->index); + ret = add_attr2group(data, &dev_attr->attr); + if (ret) + return ret; + } + acc += ptn->count; + } + } + + return 0 ; +} + +static void mp_data_init(struct minipack_data *data) +{ + +} + +static int extract_numbers(char *buf, int *out, int out_cnt) +{ + char *ptr; + int cnt, x; + + ptr = buf; + /*replace non-digits into '|', for sscanf(%s)'s ease to handle it.*/ + for (x = 0; x < strlen(ptr); x++) { + if( (ptr[x]<'0' || ptr[x] >'9') && ptr[x] != '-') + ptr[x] = TTY_RESP_SEPARATOR; + } + + cnt = 0; + while (strchr(ptr, TTY_RESP_SEPARATOR)) + { + if (sscanf(ptr,"%d%s",out,ptr)) { + cnt++; + out++; + if (cnt == out_cnt) { + return 0; + } + } else { + ptr++; + } + } + + return -EINVAL; +} + +static int extract_2byteHex(char *buf, int *out, int out_cnt) +{ + char tmp[TTY_READ_MAX_LEN]; + char *ptr; + int cnt, x; + long y; + + + if (strstr(buf, "XXXX") != NULL) { + return -ENODEV; + } + + ptr = buf; + /*replace non-hex into '|', for sscanf(%s)'s ease to handle it.*/ + for (x = 0; x < strlen(ptr); x++) { + if((ptr[x]>='0' && ptr[x] <= '9') || (ptr[x] >= 'a' && ptr[x] <= 'f')) + ; + else + ptr[x] = TTY_RESP_SEPARATOR; + } + + cnt = 0; + while (strchr(ptr, TTY_RESP_SEPARATOR)) + { + ptr++; + if (strlen(ptr) && *ptr == TTY_RESP_SEPARATOR) { + continue; + } + if (sscanf(ptr,"%4s",tmp)) { + if(!strchr(tmp, TTY_RESP_SEPARATOR)) { + if (kstrtol(tmp, 16, &y) < 0) + return -EINVAL; + *out = (int)y; + cnt++; + out++; + if (cnt == out_cnt) { + return 0; + } + ptr += 4; + } + } else { + break; + } + } + + return -EINVAL; +} + +int pmbus_linear11(int in, bool power) { + int exponent; + int mantissa, val; + int data = in; + + exponent = ((short)data) >> 11; + mantissa = ((short)((data & 0x7ff) << 5)) >> 5; + + val = mantissa*1000; + if (power) + val *= 1000; + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +static int get_pmbus_regs_partial(int *in, int in_cnt, int *out, int *out_cnt) +{ + int i, j, k; + k = 0; + for (j = 0; j < ARRAY_SIZE(pmbus_regs); j++) { + for (i = 0; i < in_cnt; i++) { + if (i == (pmbus_regs[j].addr - PMBUS_REG_START)) { + *out = pmbus_linear11(in[i], pmbus_regs[j].power); + out++; + k++; + break; + } + } + } + if (k == 0) + return -EINVAL; + + *out_cnt = k; + return 0; +} + + +static int comm2BMC(enum sensor_type_e type, int *out, int out_cnt) +{ + char cmd[TTY_CMD_MAX_LEN], resp[TTY_READ_MAX_LEN]; + char *ptr; + int ret; + + if (out == NULL) + return -EINVAL; + if (out_cnt == 0) + return 0; + + snprintf(cmd, sizeof(cmd), model_ssets[type].query); + DEBUG_INTR("%s-%d, cmd:%s\n", __func__, __LINE__, cmd); + ret = bmc_transaction(cmd, resp, sizeof(resp)-1, model_ssets[type].mdelay); + if (ret < 0) { + return ret; + } + /*Strip off string of command just sent, if any.*/ + if (strstr(resp, cmd) != NULL) { + ptr = resp + strlen(cmd); + } else { + ptr = resp; + } + + switch (type) { + case SENSOR_TYPE_THERMAL: + case SENSOR_TYPE_FAN_RPM: + case SENSOR_TYPE_FAN_RPM_DN: + ret = extract_numbers(ptr, out, out_cnt); + break; + case SENSOR_TYPE_PSU1: + case SENSOR_TYPE_PSU2: + case SENSOR_TYPE_PSU3: + case SENSOR_TYPE_PSU4: + { + int reg[(PMBUS_REG_END - PMBUS_REG_START) +1]; + int total = (PMBUS_REG_END - PMBUS_REG_START) +1; + ret = extract_2byteHex(ptr, reg, total); + if(ret == 0) + get_pmbus_regs_partial(reg, total, out, &out_cnt); + break; + } + default: + return -EINVAL; + } + + return ret; +} + +static int get_type_data ( + struct sensor_data *data, enum sensor_type_e type, int index, + int **out, int *count) +{ + struct sensor_set *model = model_ssets; + + switch (type) { + case SENSOR_TYPE_THERMAL: + *out = &data->lm75_input[index]; + break; + case SENSOR_TYPE_FAN_RPM: + *out = &data->fan_rpm[index]; + break; + case SENSOR_TYPE_FAN_RPM_DN: + *out = &data->fan_rpm_dn[index]; + break; + case SENSOR_TYPE_PSU1: + case SENSOR_TYPE_PSU2: + case SENSOR_TYPE_PSU3: + case SENSOR_TYPE_PSU4: + *out = &data->psu_data[type-SENSOR_TYPE_PSU1][index]; + break; + default: + return -EINVAL; + } + *count = model[type].total; + return 0; +} + +static struct sensor_data* +update_data(struct device *dev, enum sensor_type_e type) { + struct minipack_data *data = mp_data; + bool *valid = &data->valid[type]; + unsigned long *last_updated = &data->last_updated[type]; + struct sensor_data* ret = NULL; + int *data_ptr = NULL; + int data_cnt, rc; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, (*last_updated) + (poll_interval*HZ)) + || !(*valid)) + { + rc = get_type_data(&data->sdata, type, 0, &data_ptr, &data_cnt); + if (rc < 0) + goto exit_err; + + DEBUG_INTR("%s-%d, type:%d cnt:%d\n", __func__, __LINE__, type, data_cnt); + rc = comm2BMC(type, data_ptr, data_cnt); + if (rc < 0) { + /*Clear data if failed.*/ + if (data_ptr != NULL) + memset(data_ptr, 0, sizeof(*data_ptr)*data_cnt); + /*Make it valid if no such device, to avoid frequenctly access.*/ + if (rc == -ENODEV) { + *valid = 1; + } else { + *valid = 0; + } + } else { + *valid = 1; + } + *last_updated = jiffies; + } + ret = &data->sdata; +exit_err: + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf(buf, "%s\n", DRVNAME); +} + +static ssize_t _attr_show(struct device *dev, struct device_attribute *da, + char *buf) +{ + int index, count, rc; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sensor_data* data; + int *out = NULL; + enum sensor_type_e type; + + type = attr->index / ATTR_TYPE_INDEX_GAP; + + DEBUG_INTR("%s-%d, type:%d index:%d\n", __func__, __LINE__, type, attr->index); + data = update_data(dev, type); + if (data == NULL) + return -EINVAL; + + index = attr->index % ATTR_TYPE_INDEX_GAP; + rc = get_type_data(data, type, index, &out, &count); + if (rc < 0 || out == NULL) + return -EINVAL; + + if( index > count) + return -EINVAL; + + return sprintf(buf, "%d\n", *out); +} + +static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf(buf, "%d\n", MIN_FAN_RPM); +} + +static ssize_t show_psu_vout_max(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf(buf, "%d\n", MAX_PSU_VOUT); +} + +static ssize_t show_psu_vout_min(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf(buf, "%d\n", MIN_PSU_VOUT); +} + +static int add_attr2group(struct minipack_data *data, struct attribute *attr) +{ + int new_max_attrs = ++data->num_attributes + ATTR_ALLOC_EXTRA; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + DEBUG_INTR("%s-%d, num_attr:%d\n", __func__, __LINE__, new_max_attrs); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + + + data->group.attrs[data->num_attributes-1] = attr; + data->group.attrs[data->num_attributes] = NULL; + + return 0; +} + +static int minipack_probe(struct platform_device *pdev) +{ + int status = -1; + + mp_data->dev = &pdev->dev; + status = attributs_init(mp_data); + DEBUG_INTR("%s-%d, status:%d\n", __func__, __LINE__, status); + if (status) { + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &mp_data->group); + DEBUG_INTR("%s-%d, status:%d\n", __func__, __LINE__, status); + + if (status) { + goto exit_kfree; + } + + mp_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(mp_data->hwmon_dev)) { + status = PTR_ERR(mp_data->hwmon_dev); + goto exit_remove; + } + dev_info(&pdev->dev, "minipack sensors found\n"); + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &mp_data->group); +exit_kfree: + kfree(mp_data->group.attrs); +exit: + return status; +} + +static int minipack_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(mp_data->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &mp_data->group); + kfree(mp_data->group.attrs); + return 0; +} + +static struct platform_driver minipack_driver = { + .probe = minipack_probe, + .remove = minipack_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + + +static int __init minipack_init(void) +{ + int ret; + + ret = platform_driver_register(&minipack_driver); + if (ret < 0) { + goto exit; + } + mp_data = kzalloc(sizeof(struct minipack_data), GFP_KERNEL); + if (!mp_data) { + ret = -ENOMEM; + platform_driver_unregister(&minipack_driver); + goto exit; + } + mutex_init(&mp_data->update_lock); + mp_data_init(mp_data); + + mp_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(mp_data->pdev)) { + ret = PTR_ERR(mp_data->pdev); + platform_driver_unregister(&minipack_driver); + kfree(mp_data); + goto exit; + } +exit: + return ret; +} + +static void __exit minipack_exit(void) +{ + if (!mp_data) { + return; + } + platform_device_unregister(mp_data->pdev); + platform_driver_unregister(&minipack_driver); + kfree(mp_data); +} + +module_init(minipack_init); +module_exit(minipack_exit); + +MODULE_AUTHOR("Roy Lee "); +MODULE_DESCRIPTION("Minipack platform sensors driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-accton/minipack/service/minipack-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/minipack/service/minipack-platform-init.service new file mode 100644 index 000000000000..4a0f803b2711 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/minipack/service/minipack-platform-init.service @@ -0,0 +1,14 @@ +[Unit] +Description=Accton MiniPack Platform Monitoring service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/accton_minipack_util.py install +ExecStop=/usr/local/bin/accton_minipack_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/minipack/service/minipack-setup-qsfp-oom.service b/platform/broadcom/sonic-platform-modules-accton/minipack/service/minipack-setup-qsfp-oom.service new file mode 100644 index 000000000000..df1c961bf181 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/minipack/service/minipack-setup-qsfp-oom.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton MiniPack Platform setup qsfp oom service +Before=pmon.service +After=minipack-platform-init.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/setup_qsfp_eeprom.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/minipack/setup.py b/platform/broadcom/sonic-platform-modules-accton/minipack/setup.py new file mode 100755 index 000000000000..b5d08c090bab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/minipack/setup.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup, Extension +os.listdir + +module1 = Extension("fbfpgaio", sources = ["minipack/lib/fbfpgaiomodule.c"]) + +setup( + name='minipack', + version='1.0', + description='Module to initialize Accton MiniPack platforms', + + packages=['minipack'], + package_dir={'minipack': 'minipack/classes'}, + ext_modules=[module1], + +) + diff --git a/platform/broadcom/sonic-platform-modules-accton/minipack/utils/README b/platform/broadcom/sonic-platform-modules-accton/minipack/utils/README new file mode 100644 index 000000000000..bb52538deb3b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/minipack/utils/README @@ -0,0 +1,48 @@ +Copyright (C) 2019 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Contents of this package: + module - Contains source code of kernel driver modules. + util - operational scripts. + +Sonic creates a docker container and run building process under it. +If user tries to built new drivers, please get into that docker and +dpkg-buildpackage for them. + +All Linux kernel code is licensed under the GPLv1. All other code is +licensed under the GPLv3. Please see the LICENSE file for copies of +both licenses. + +==================================================================== +The most of peripherals are accessed through BMC. +Only system eeprom and QSFP are directly accessed by CPU. + +System LED: + There are 2 system LEDs at the upper-left corner of front panel. + +Fan Control: + There are 16 fans inside 8 fan modules. + +Thermal sensers: + 8 temperature sensors are controlled by the lm75 kernel modules. + +PSUs: + There r42 power supplies slot at the back. + Once if a PSU is not plugged, the data of it is shown all 0's. + +There are 128 QSFP modules are equipped. +Before operating on PSU and QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/broadcom/sonic-platform-modules-accton/minipack/utils/accton_minipack_util.py b/platform/broadcom/sonic-platform-modules-accton/minipack/utils/accton_minipack_util.py new file mode 100755 index 000000000000..25979963bb30 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/minipack/utils/accton_minipack_util.py @@ -0,0 +1,485 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Description: +# Due to adoption of optoe drivers, sideband signals of SFPs are moved +# into cpld drivers. Add a new dict, cpld_of_module, for mapping this +# attributes to corresponding cpld nodes. +# + + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with led|sfp +""" + +import commands +import getopt +import sys +import logging +import re +import time + +PROJECT_NAME = 'minipack' +version = '0.2.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'psu':2, 'sfp':32} + + +led_prefix ='' +hwmon_types = {'led': ['diag','loc'], + } +hwmon_nodes = {'led': ['brightness'] , + } +hwmon_prefix ={'led': led_prefix, + } + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = { + 'psu': ['35-0038','36-003b'], + 'sfp': ['-0050']} +i2c_nodes = { + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['module_present_', 'sfp_tx_disable']} + +NO_QSFP = 128 + +#For sideband signals of SFP/QSFP modules. +cpld_of_module = {'-0062': list(range(0,16)), + '-0064': list(range(16,32)) } + + +mknod =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo 24c64 0x57 > /sys/bus/i2c/devices/i2c-1/new_device', +] + +FORCE = 0 + + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log ("cmd:" + cmd) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_inserted(): + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) + logging.info('mods:'+lsmod) + if ret : + return False + else : + return True + + + +kos = [ +'depmod -ae', +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe optoe', +'modprobe minipack_psensor'] + +def driver_install(): + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + for i in range(0,len(kos)): + #remove parameter if any + rm = kos[-(i+1)] + lst = rm.split(" ") + if len(lst) > 2: + del(lst[2:]) + rm = " ".join(lst) + + #Change to removing commands + rm = rm.replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +def sfp_map(index): + port = index + 1 + base = ((port-1)/8*8) + 10 + index = (port - 1) % 8 + index = 7 - index + if (index%2): + index = index -1 + else: + index = index +1 + bus = base + index + return bus + +def device_install(): + for i in range(0,len(mknod)): + #for pca932x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(2) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + rm_cmd="rm -rf /usr/local/bin/minipack_qsfp > /dev/null 2>&1" + log_os_system(rm_cmd, 1) + mk_cmd= "mkdir /usr/local/bin/minipack_qsfp" + log_os_system(mk_cmd, 1) + + return + +def device_uninstall(): + nodelist = mknod + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_inserted() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_inserted() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_inserted()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + bus = 1 + node = key+str(k+1) + path = i2c_prefix + str(bus) + lk + "/"+ nodes[j] + str(k+1) + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-accton/minipack/utils/setup_qsfp_eeprom.py b/platform/broadcom/sonic-platform-modules-accton/minipack/utils/setup_qsfp_eeprom.py new file mode 100755 index 000000000000..257bc1cd90e6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/minipack/utils/setup_qsfp_eeprom.py @@ -0,0 +1,317 @@ +#!/usr/bin/env python +# +# Copyright (c) 2019 Edgecore Networks Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 7/22/2019: Jostar create for minipack +# ------------------------------------------------------------------ + +try: + import os + import getopt + import sys + import subprocess + import click + import imp + import commands + import logging + import logging.config + import logging.handlers + import types + import time # this is only being used as part of the example + import traceback + from tabulate import tabulate + from minipack.pimutil import PimUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +#2:idle state. 1:insert state, 0:remove state. +pim_state=[2,2,2,2,2,2,2,2] + +# port_use_i2c_bus[idx], idx means port_idx. Idx start from 0 to 127 +# port_use_i2c_bus[0] means port0 use i2c-device number +# port_use_i2c_bus[1] means port1 use i2c-device number +#At default , port_use_i2c_bus are 0. When PIM insert, it will no be 0 +port_use_i2c_bus= [0] * 128 + +#pim_port_use_bus[idx] are for 8 channel use. At default, pim_port_use_bus[idx]=0 +#pim_port_use_bus[idx] will save pim_idx(0 to 7). +#setup service will check when pim insert at first time. +#It will find +# 1. Does this pim card insert or not in the past. So it will check pim_port_use_bus[idx] +# 2. If make sure that pim_port_use_bus[idx]==0. Assgin oom start i2c dev numer to pim_port_use_bus[idx]. +#Never set pim_port_use_bus[idx] to 0 +#So if pim next insert, it need to check whether pim_port_use_bus[idx] is 0 or not. +#if pim_port_use_bus[idx]!=0, means this pim card has setup oom sysfs +pim_port_use_bus=[0] * 8 + +oom_i2c_bus_table=1 + +pim_dev=PimUtil() + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/usr/local/bin/setup_qsfp_eeprom' +DEBUG = False +PIM_MIN=0 +PIM_MAX=8 + +def my_log(txt): + if DEBUG == True: + print "[ACCTON DBG]: "+txt + return + +def log_os_system(cmd): + logging.info('Run :'+cmd) + status = 1 + output = "" + status, output = commands.getstatusoutput(cmd) + if status: + logging.info('Failed :'+cmd) + return status, output + +def qsfp_map_bus(idx): + port = idx + 1 + base = ((port-1)/8*8) + 10 + idx = (port - 1) % 8 + idx = 7 - idx + if (idx%2): + idx = idx -1 + else: + idx = idx +1 + bus = base + idx + return bus + +def pca9548_sysfs(i2c_bus, create): + if create==1: + cmdl = "echo pca9548 0x%x > /sys/bus/i2c/devices/i2c-%d/new_device" + else: + cmdl = "echo 0x%x > /sys/bus/i2c/devices/i2c-%d/delete_device" + + cmdm = cmdl % (0x72, i2c_bus) + status1, output =log_os_system(cmdm) + cmdm = cmdl % (0x71, i2c_bus) + status2, output =log_os_system(cmdm) + return (status1 | status2) + + +def qsfp_eeprom_sys(pim_idx, i2c_bus_order, create): + # initialize multiplexer for 8 PIMs + global port_use_i2c_bus + start_port=pim_idx*16 + end_port = (pim_idx+1)*16 + start_bus=(i2c_bus_order-1)*16 + end_bus = i2c_bus_order*16 + k=start_port + for i in range(start_bus, end_bus): + bus = qsfp_map_bus(i) + if create==1: + status, output =log_os_system( + "echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(bus)+"/new_device") + if status: + print output + return 1 + status, output =log_os_system( + "echo port"+str(k+1)+" > /sys/bus/i2c/devices/"+str(bus)+"-0050/port_name") + + status, output =log_os_system( + "ln -s -f /sys/bus/i2c/devices/"+str(bus)+"-0050/eeprom" + " /usr/local/bin/minipack_qsfp/port" + str(k) + "_eeprom") + if status: + print output + return 1 + else: + status, output =log_os_system( + "echo 0x50 > /sys/bus/i2c/devices/i2c-"+str(bus)+"/delete_device") + if status: + print output + + k=k+1 + + return 0 + +def check_pca_active( i2c_addr, bus): + cmd = "i2cget -y -f %d 0x%x 0x0" + cmd = cmd %(bus, i2c_addr) + status, output = commands.getstatusoutput(cmd) + return status + +def set_pim_port_use_bus(pim_idx): + + global pim_port_use_bus + global oom_i2c_bus_table + + if pim_port_use_bus[pim_idx]!=0: + return 0 + + pim_port_use_bus[pim_idx]=oom_i2c_bus_table + oom_i2c_bus_table=oom_i2c_bus_table+1 + + return pim_port_use_bus[pim_idx] + + +def del_pim_port_use_bus(pim_idx): + global oom_i2c_bus_table + + oom_i2c_bus_table=oom_i2c_bus_table-1 + pim_port_use_bus[pim_idx]=0 + + +def device_remove(): + cmd1 = "echo 0x%x > /sys/bus/i2c/devices/i2c-%d/delete_device" + + for bus in range(2, 10): + #ret=check_pca_active(0x72, bus) + #if ret==0: + + cmdm= cmd1 % (0x72, bus) + status, output = commands.getstatusoutput(cmdm) + print "Remove %d-0072 i2c device"%bus + cmdm= cmd1 % (0x71, bus) + status, output = commands.getstatusoutput(cmdm) + print "Remove %d-0071 i2c device"%bus + + cmd="rm -f /usr/local/bin/minipack_qsfp/port*" + status, output=log_os_system(cmd) + return status + +class device_monitor(object): + + PIM_STATE_REMOVE = 0 + PIM_STATE_INSERT = 1 + PIM_STATE_IDLE=2 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log') + sys_handler.setLevel(logging.WARNING) + logging.getLogger('').addHandler(sys_handler) + + #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_pim(self): + global pim_dev + global pim_state + + for pim_idx in range(PIM_MIN, PIM_MAX): + presence=pim_dev.get_pim_presence(pim_idx) + if presence==1: + if pim_state[pim_idx]!=self.PIM_STATE_INSERT: + #find which i2c_device can use. It start from 2 + i2c_bus_order=set_pim_port_use_bus(pim_idx) + if i2c_bus_order==0: + logging.info("pim_state[%d] PIM_STATE_INSERT", pim_idx); + pim_state[pim_idx]=self.PIM_STATE_INSERT + continue + + logging.info ("pim_idx=%d oom use i2c_bus_order=%d", pim_idx, i2c_bus_order) + ready=0 + retry_limit=100 + retry_count=0 + while retry_count < retry_limit: + ret=check_pca_active(0x72, pim_idx+2) + if ret==0: + ready=1 + break + retry_count=retry_count+1 + time.sleep(0.2) + + if ready==1: + status=pca9548_sysfs(pim_idx+2, 1) + if status: + status=pca9548_sysfs(pim_idx+2, 0) #del pca i2c device, give up set oom at this time. + del_pim_port_use_bus(pim_idx) + continue + status=qsfp_eeprom_sys(pim_idx,i2c_bus_order, 1) + if status: + status=pca9548_sysfs(pim_idx+2, 0) #del pca i2c device, give up set oom at this time. + del_pim_port_use_bus(pim_idx) + continue + #ret_2=check_pca_active(0x72, pim_idx+2) + #ret_1=check_pca_active(0x71, pim_idx+2) + + pim_state[pim_idx]=self.PIM_STATE_INSERT + logging.info("pim_state[%d] PIM_STATE_INSERT", pim_idx); + else: + print "retry check 100 times for check pca addr" + del_pim_port_use_bus(pim_idx) + else: + if pim_state[pim_idx]==self.PIM_STATE_INSERT: + #pca9548_sysfs(pim_idx+2, 0) + pim_state[pim_idx]=self.PIM_STATE_REMOVE + logging.info("pim_state[%d] PIM_STATE_REMOVE", pim_idx); + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + remove_dev=0 + cpu_pca_i2c_ready=0 + + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdlr',['lfile=']) + except getopt.GetoptError: + print 'A:Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'B:Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + elif opt in ('-r', '--remove'): + remove_dev=1 + + if remove_dev==1: + device_remove() + return 0 + monitor = device_monitor(log_file, log_level) + global pim_dev + pim_dev.init_pim_fpga() + + while cpu_pca_i2c_ready==0: + status=check_pca_active(0x70, 1) + time.sleep(0.5) + if status==0: + cpu_pca_i2c_ready=1 + print "Make sure CPU pca i2c device is ready" + break + + while True: + monitor.manage_pim() + time.sleep(2) + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/.gitignore b/platform/broadcom/sonic-platform-modules-alphanetworks/.gitignore new file mode 100644 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/README.md b/platform/broadcom/sonic-platform-modules-alphanetworks/README.md new file mode 100644 index 000000000000..a0c753830103 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/README.md @@ -0,0 +1 @@ +platform drivers of Alphanetworks products for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog new file mode 100644 index 000000000000..2742b7c6a416 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/changelog @@ -0,0 +1,6 @@ +sonic-alphanetworks-platform-modules (1.0) unstable; urgency=low + + * Add support for SNH60A0-320FV2 and SNH60B0_640F. + + -- Alphanetworks Tue, 19 Dec 2017 09:35:58 +0800 + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/compat b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control new file mode 100644 index 000000000000..6535dbb88bb8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control @@ -0,0 +1,17 @@ +Source: sonic-alphanetworks-platform-modules +Section: main +Priority: extra +Maintainer: Alphanetworks , Alphanetworks +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-alphanetworks-snh60a0-320fv2 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-alphanetworks-snh60b0-640f +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules new file mode 100755 index 000000000000..0d1a588db6bd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/rules @@ -0,0 +1,86 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-alphanetworks +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= snh60a0-320fv2 snh60b0-640f +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/classes/__init__.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/Makefile b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/Makefile new file mode 100644 index 000000000000..f9477910d382 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/Makefile @@ -0,0 +1,8 @@ +# obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ +# goreme_system_cpld.o ym2651y.o optoe.o + +obj-m:=alphanetworks_snh60a0-320fv2_sfp.o snh60a0_system_cpld.o snh60a0_power_cpld.o snh60a0_onie_eeprom.o + + +# obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ +# accton_as7712_32x_psu.o accton_i2c_cpld.o ym2651y.o optoe.o diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c new file mode 100644 index 000000000000..af47c6521a0f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/alphanetworks_snh60a0-320fv2_sfp.c @@ -0,0 +1,1669 @@ +/* + * SFP driver for alphanetworks snh60a0-320fv2 sfp + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Philip Wang + * + * 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 3 of the License, or + * 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. + * see + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "snh60a0_320fv2_sfp" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s[%s,%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_SFP_PORT 32 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_CPLD_I2C_ADDR 0x5F +#define SFP_EEPROM_A0_I2C_ADDR 0x50 +#define SFP_EEPROM_A2_I2C_ADDR 0x68 + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +/* extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); */ +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { SFP_EEPROM_A0_I2C_ADDR, SFP_EEPROM_A2_I2C_ADDR, SFP_CPLD_I2C_ADDR, I2C_CLIENT_END }; + +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +sfp1, sfp2, sfp3, sfp4, sfp5, sfp6, sfp7, sfp8, +sfp9, sfp10, sfp11, sfp12, sfp13, sfp14, sfp15, sfp16, +sfp17, sfp18, sfp19, sfp20, sfp21, sfp22, sfp23, sfp24, +sfp25, sfp26, sfp27, sfp28, sfp29, sfp30, sfp31, sfp32 +}; + +static const struct i2c_device_id sfp_device_id[] = { +{ "sfpcpld1", sfp1 }, { "sfpcpld2", sfp2 }, { "sfpcpld3", sfp3 }, { "sfpcpld4", sfp4 }, +{ "sfpcpld5", sfp5 }, { "sfpcpld6", sfp6 }, { "sfpcpld7", sfp7 }, { "sfpcpld8", sfp8 }, +{ "sfpcpld9", sfp9 }, { "sfpcpld10", sfp10 }, { "sfpcpld11", sfp11 }, { "sfpcpld12", sfp12 }, +{ "sfpcpld13", sfp13 }, { "sfpcpld14", sfp14 }, { "sfpcpld15", sfp15 }, { "sfpcpld16", sfp16 }, +{ "sfpcpld17", sfp17 }, { "sfpcpld18", sfp18 }, { "sfpcpld19", sfp19 }, { "sfpcpld20", sfp20 }, +{ "sfpcpld21", sfp21 }, { "sfpcpld22", sfp22 }, { "sfpcpld23", sfp23 }, { "sfpcpld24", sfp24 }, +{ "sfpcpld25", sfp25 }, { "sfpcpld26", sfp26 }, { "sfpcpld27", sfp27 }, { "sfpcpld28", sfp28 }, +{ "sfpcpld29", sfp29 }, { "sfpcpld30", sfp30 }, { "sfpcpld31", sfp31 }, { "sfpcpld32", sfp32 }, +{} +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[2]; /* index 0 => device id + 1 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 2 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + u64 port_reset; /* reset status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +enum sfp_sysfs_port_num_attributes { + PORT1_NUMBER, + PORT2_NUMBER, + PORT3_NUMBER, + PORT4_NUMBER, + PORT5_NUMBER, + PORT6_NUMBER, + PORT7_NUMBER, + PORT8_NUMBER, + PORT_NUMBER_MAX +}; + +enum sfp_sysfs_present_attributes { + PORT1_PRESENT, + PORT2_PRESENT, + PORT3_PRESENT, + PORT4_PRESENT, + PORT5_PRESENT, + PORT6_PRESENT, + PORT7_PRESENT, + PORT8_PRESENT, + PORT1_PRESENT_ALL, + PORT2_PRESENT_ALL, + PORT3_PRESENT_ALL, + PORT4_PRESENT_ALL, + PORT5_PRESENT_ALL, + PORT6_PRESENT_ALL, + PORT7_PRESENT_ALL, + PORT8_PRESENT_ALL, + PORT_PRESENT_MAX +}; + +enum sfp_sysfs_type_attributes { + PORT1_TYPE, + PORT2_TYPE, + PORT3_TYPE, + PORT4_TYPE, + PORT5_TYPE, + PORT6_TYPE, + PORT7_TYPE, + PORT8_TYPE, + PORT_TYPE_MAX +}; + +enum sfp_sysfs_reset_attributes { + PORT1_RESET, + PORT2_RESET, + PORT3_RESET, + PORT4_RESET, + PORT5_RESET, + PORT6_RESET, + PORT7_RESET, + PORT8_RESET, + PORT_RESET_MAX +}; + +enum sfp_sysfs_rx_los_attributes { + PORT1_RX_LOS, + PORT2_RX_LOS, + PORT3_RX_LOS, + PORT4_RX_LOS, + PORT5_RX_LOS, + PORT6_RX_LOS, + PORT7_RX_LOS, + PORT8_RX_LOS, + PORT1_RX_LOS1, + PORT2_RX_LOS1, + PORT3_RX_LOS1, + PORT4_RX_LOS1, + PORT5_RX_LOS1, + PORT6_RX_LOS1, + PORT7_RX_LOS1, + PORT8_RX_LOS1, + PORT1_RX_LOS2, + PORT2_RX_LOS2, + PORT3_RX_LOS2, + PORT4_RX_LOS2, + PORT5_RX_LOS2, + PORT6_RX_LOS2, + PORT7_RX_LOS2, + PORT8_RX_LOS2, + PORT1_RX_LOS3, + PORT2_RX_LOS3, + PORT3_RX_LOS3, + PORT4_RX_LOS3, + PORT5_RX_LOS3, + PORT6_RX_LOS3, + PORT7_RX_LOS3, + PORT8_RX_LOS3, + PORT1_RX_LOS4, + PORT2_RX_LOS4, + PORT3_RX_LOS4, + PORT4_RX_LOS4, + PORT5_RX_LOS4, + PORT6_RX_LOS4, + PORT7_RX_LOS4, + PORT8_RX_LOS4, + PORT1_RX_LOS_ALL, + PORT2_RX_LOS_ALL, + PORT3_RX_LOS_ALL, + PORT4_RX_LOS_ALL, + PORT5_RX_LOS_ALL, + PORT6_RX_LOS_ALL, + PORT7_RX_LOS_ALL, + PORT8_RX_LOS_ALL, + PORT_RX_LOS_MAX +}; + +enum sfp_sysfs_tx_disable_attributes { + PORT1_TX_DISABLE = PORT_RX_LOS_MAX, + PORT2_TX_DISABLE, + PORT3_TX_DISABLE, + PORT4_TX_DISABLE, + PORT5_TX_DISABLE, + PORT6_TX_DISABLE, + PORT7_TX_DISABLE, + PORT8_TX_DISABLE, + PORT1_TX_DISABLE1, + PORT2_TX_DISABLE1, + PORT3_TX_DISABLE1, + PORT4_TX_DISABLE1, + PORT5_TX_DISABLE1, + PORT6_TX_DISABLE1, + PORT7_TX_DISABLE1, + PORT8_TX_DISABLE1, + PORT1_TX_DISABLE2, + PORT2_TX_DISABLE2, + PORT3_TX_DISABLE2, + PORT4_TX_DISABLE2, + PORT5_TX_DISABLE2, + PORT6_TX_DISABLE2, + PORT7_TX_DISABLE2, + PORT8_TX_DISABLE2, + PORT1_TX_DISABLE3, + PORT2_TX_DISABLE3, + PORT3_TX_DISABLE3, + PORT4_TX_DISABLE3, + PORT5_TX_DISABLE3, + PORT6_TX_DISABLE3, + PORT7_TX_DISABLE3, + PORT8_TX_DISABLE3, + PORT1_TX_DISABLE4, + PORT2_TX_DISABLE4, + PORT3_TX_DISABLE4, + PORT4_TX_DISABLE4, + PORT5_TX_DISABLE4, + PORT6_TX_DISABLE4, + PORT7_TX_DISABLE4, + PORT8_TX_DISABLE4, + PORT1_TX_DISABLE_ALL, + PORT2_TX_DISABLE_ALL, + PORT3_TX_DISABLE_ALL, + PORT4_TX_DISABLE_ALL, + PORT5_TX_DISABLE_ALL, + PORT6_TX_DISABLE_ALL, + PORT7_TX_DISABLE_ALL, + PORT8_TX_DISABLE_ALL, + PORT_TX_DISABLE_MAX +}; + +enum sfp_sysfs_tx_fault_attributes { + PORT1_TX_FAULT = PORT_TX_DISABLE_MAX, + PORT2_TX_FAULT, + PORT3_TX_FAULT, + PORT4_TX_FAULT, + PORT5_TX_FAULT, + PORT6_TX_FAULT, + PORT7_TX_FAULT, + PORT8_TX_FAULT, + PORT1_TX_FAULT1, + PORT2_TX_FAULT1, + PORT3_TX_FAULT1, + PORT4_TX_FAULT1, + PORT5_TX_FAULT1, + PORT6_TX_FAULT1, + PORT7_TX_FAULT1, + PORT8_TX_FAULT1, + PORT1_TX_FAULT2, + PORT2_TX_FAULT2, + PORT3_TX_FAULT2, + PORT4_TX_FAULT2, + PORT5_TX_FAULT2, + PORT6_TX_FAULT2, + PORT7_TX_FAULT2, + PORT8_TX_FAULT2, + PORT1_TX_FAULT3, + PORT2_TX_FAULT3, + PORT3_TX_FAULT3, + PORT4_TX_FAULT3, + PORT5_TX_FAULT3, + PORT6_TX_FAULT3, + PORT7_TX_FAULT3, + PORT8_TX_FAULT3, + PORT1_TX_FAULT4, + PORT2_TX_FAULT4, + PORT3_TX_FAULT4, + PORT4_TX_FAULT4, + PORT5_TX_FAULT4, + PORT6_TX_FAULT4, + PORT7_TX_FAULT4, + PORT8_TX_FAULT4, + PORT_TX_FAULT_MAX +}; + +enum sfp_sysfs_eeprom_attributes { + PORT1_EEPROM, + PORT2_EEPROM, + PORT3_EEPROM, + PORT4_EEPROM, + PORT5_EEPROM, + PORT6_EEPROM, + PORT7_EEPROM, + PORT8_EEPROM, + PORT_EEPROM_MAX +}; + +enum sfp_sysfs_ddm_implemented_attributes { + PORT1_DDM_IMPLEMENTED, + PORT2_DDM_IMPLEMENTED, + PORT3_DDM_IMPLEMENTED, + PORT4_DDM_IMPLEMENTED, + PORT5_DDM_IMPLEMENTED, + PORT6_DDM_IMPLEMENTED, + PORT7_DDM_IMPLEMENTED, + PORT8_DDM_IMPLEMENTED, + PORT_DDM_IMPLEMENTED_MAX +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + DEBUG_PRINT("show_port_number port number:%d", data->port + attr->index); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port + attr->index)); +} + +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x05}; + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port 1~32 */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x5f) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); + data->present |= (u64)status << (i*8); + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + return NULL; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return 0; +} + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = sfp_update_present(client); + return (data->present & BIT_INDEX(port)) ? 1 : 0; +} + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if ((attr->index >= PORT1_PRESENT_ALL) && (attr->index <= PORT8_PRESENT_ALL)) { + + } + + /* PRESENT */ + return sprintf(buf, "%d\n", sfp_is_port_present(client, attr->index)); +} + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(data->client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + + if (!sfp_is_port_present(client, attr->index)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + + +static struct sfp_port_data *sfp_update_port_reset(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x7}; + + mutex_lock(&data->update_lock); + + /* Read reset status of port 1~32 */ + data->port_reset = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("reset status = 0x%x", status); + data->port_reset |= (u64)status << (i*8); + } + + DEBUG_PRINT("reset status = 0x%llx", data->port_reset); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int is_reset = 0; + + if (!sfp_is_port_present(client, attr->index)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_reset(client); + is_reset = (data->port_reset & BIT_INDEX(attr->index))? 0 : 1; + + return sprintf(buf, "%d\n", is_reset); +} + +static ssize_t sfp_set_port_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_reg = 0, cpld_val = 0; /*, cpld_bit = 0; //remove unused variable */ + long is_reset; + int error; + + error = kstrtol(buf, 10, &is_reset); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + cpld_reg = 0x07; + + cpld_val = i2c_smbus_read_byte_data(client, cpld_reg); + + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update reset status. CPLD defined 0 is reset state, 1 is normal state. + * is_reset: 0 is not reset. 1 is reset. + */ + if (is_reset == 0) { + data->port_reset |= BIT_INDEX(attr->index); + } + else { + data->port_reset &= ~BIT_INDEX(attr->index); + } + + alpha_i2c_cpld_write(0x5f, cpld_reg, cpld_val); + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + dev_dbg(dev, "Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + mutex_unlock(&data->update_lock); + return data; + +exit: + mutex_unlock(&data->update_lock); + return NULL; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, attr->index)) { + return -ENODEV; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + if ((attr->index >= PORT1_TX_FAULT1) && (attr->index <= PORT8_TX_FAULT4)){ + val = (data->qsfp->status[2] & BIT_INDEX(attr->index - PORT1_TX_FAULT1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE1) && (attr->index <= PORT8_TX_DISABLE4)){ + val = (data->qsfp->status[1] & BIT_INDEX(attr->index - PORT1_TX_DISABLE1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index <= PORT8_TX_DISABLE_ALL)){ + val = ((data->qsfp->status[1] & 0xF) == 0xF) ? 1 : 0; + } + if ((attr->index >= PORT1_RX_LOS1) && (attr->index <= PORT8_RX_LOS4)){ + val = (data->qsfp->status[0] & BIT_INDEX(attr->index - PORT1_RX_LOS1)) ? 1 : 0; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int result; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + result = kstrtol(buf, 10, &disable); + if (result) { + return result; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + mutex_lock(&data->update_lock); + + if((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index <= PORT8_TX_DISABLE_ALL)){ + DEBUG_PRINT ("disable:%ld %d==TX_DISABLE_ALL %u\r\n", disable, attr->index, data->qsfp->status[1]); + data->qsfp->status[1] = disable? 0xF:0; + } + else{ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - PORT1_TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - PORT1_TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + result = sfp_eeprom_write(client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (!sfp_is_port_present(client, attr->index)) { + return -ENODEV; + } + + status = sfp_eeprom_read(data->client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (status < 0) { + return -EIO; + } + + return sprintf(buf, "%d\n", (ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK) ? 1 : 0); +} + +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + data = sfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + if ((attr->index >= PORT1_TX_FAULT) && (attr->index <= PORT8_TX_FAULT)){ + index = 0; + } + else if ((attr->index >= PORT1_TX_DISABLE) && (attr->index <= PORT8_TX_DISABLE)){ + index = 1; + } + if ((attr->index >= PORT1_RX_LOS) && (attr->index <= PORT8_RX_LOS)){ + index = 2; + } + + val = (data->ddm->status[index] & BIT_INDEX(attr->index)) ? 1 : 0; + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + char devfile[96]; + struct file *sfd; + int i2c_index = 0; + int status, result, offset = 0xb; + int rdlen, rc; + mm_segment_t old_fs; + char buffer[256]; + + if (!sfp_is_port_present(client, attr->index)) { + return 0; + } + + if(strcmp(client->name, "sfpcpld1") == 0) + i2c_index = 14; + else if(strcmp(client->name, "sfpcpld9") == 0) + i2c_index = 15; + else if(strcmp(client->name, "sfpcpld17") == 0) + i2c_index = 16; + else if(strcmp(client->name, "sfpcpld25") == 0) + i2c_index = 17; + + snprintf(devfile, sizeof(devfile), "/sys/bus/i2c/devices/%d-0050/sfp_eeprom", i2c_index); + + /* Set module select register */ + result = i2c_smbus_write_byte_data(client, offset, BIT_INDEX(attr->index)); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data faill(%d)", result); + } + + /* Read SFP EEPROM */ + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + dev_info(&client->dev, "Failed to open file(%s)#%d", devfile, __LINE__); + return 0; + } + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + dev_info(&client->dev, "file %s cann't readable ?\n", devfile); + return 0; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + dev_info(&client->dev, "File(%s) empty!\n", devfile); + rc = 0; + goto exit; + } + + rc = sizeof(buffer); + memcpy(buf, buffer, rc); + + /* Reset module select register */ + result = i2c_smbus_write_byte_data(client, offset, 0); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data faill(%d)", result); + } + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + + return rc; +} + +#if 0 +static ssize_t qsfp_set_eeprom(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + DEBUG_PRINT("data->port:%d attr index:%d", data->port, attr->index); + return 1; +} +#endif + +/* SFP/QSFP common attributes for sysfs */ +#define DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT1##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT2##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT3##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT4##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT5##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT6##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT7##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT8##_NUMBER); +#define DECLARE_PORT_NUMBER_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_number.dev_attr.attr, +DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_is_present, S_IRUGO, show_present, NULL, PORT##PORT1##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_is_present, S_IRUGO, show_present, NULL, PORT##PORT2##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_is_present, S_IRUGO, show_present, NULL, PORT##PORT3##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_is_present, S_IRUGO, show_present, NULL, PORT##PORT4##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_is_present, S_IRUGO, show_present, NULL, PORT##PORT5##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_is_present, S_IRUGO, show_present, NULL, PORT##PORT6##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_is_present, S_IRUGO, show_present, NULL, PORT##PORT7##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_is_present, S_IRUGO, show_present, NULL, PORT##PORT8##_PRESENT); +#define DECLARE_PORT_IS_PRESENT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_is_present.dev_attr.attr, +DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT1##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT2##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT3##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT4##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT5##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT6##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT7##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT8##_TYPE); +#define DECLARE_PORT_TYPE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_type.dev_attr.attr, +DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT1##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT2##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT3##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT4##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT5##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT6##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT7##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT8##_RESET); +#define DECLARE_PORT_RESET_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_reset.dev_attr.attr, +DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +/* QSFP attributes for sysfs */ +#define DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT1##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT2##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT3##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT4##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT5##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS##INDEX); +#define DECLARE_PORT_RX_LOSn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_rx_los##INDEX.dev_attr.attr, +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT1##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT2##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT3##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT4##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT5##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT6##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT7##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT8##_TX_DISABLE##INDEX); + +#define DECLARE_PORT_TX_DISABLEn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_disable##INDEX.dev_attr.attr, +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT1##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT2##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT3##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT4##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT5##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT##INDEX); +#define DECLARE_PORT_TX_FAULTn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_fault##INDEX.dev_attr.attr, +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT1##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT2##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT3##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT4##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT5##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT6##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT7##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT8##_EEPROM); +#define DECLARE_PORT_EEPROMTn_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_eeprom.dev_attr.attr, +DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +static struct attribute *qsfp_attributes[] = { + DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_EEPROMTn_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + NULL +}; + + +/* SFP msa attributes for sysfs */ +static struct attribute *sfp_msa_attributes[] = { + DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + NULL +}; + +/* SFP ddm attributes for sysfs */ +#define DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT1##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT2##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT3##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT4##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT5##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS); +#define DECLARE_RX_LOS_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_rx_los.dev_attr.attr, +DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT1##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT2##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT3##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT4##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT5##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT6##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT7##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT8##_TX_DISABLE); +#define DECLARE_TX_DISABLE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_disable.dev_attr.attr, +DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +#define DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT1##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT2##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT3##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT4##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT5##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT); +#define DECLARE_TX_FAULT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_fault.dev_attr.attr, +DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + +static struct attribute *sfp_ddm_attributes[] = { + DECLARE_RX_LOS_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_DISABLE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_FAULT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + NULL +}; + +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return data_len; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_write_byte_data(client, command, *data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return 1; +#endif + + +} + + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", (int)off, (int)count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + /* result = data_len; */ + +abort: + return result; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_read_byte_data(client, command); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 1; + +abort: + return result; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", (int)off, (int)count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + dev_info(&client->dev, "sfp msa '%s' (sfp_sysfs_eeprom_init fail...)\n", client->name); + /* goto exit_remove; */ + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +/* exit_remove: */ + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + if (client->addr == SFP_CPLD_I2C_ADDR){ + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + } + + if (client->addr == SFP_EEPROM_A0_I2C_ADDR){ + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + } + + /* Bring QSFPs out of reset */ + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if ((client->addr != SFP_EEPROM_A0_I2C_ADDR) && (client->addr != SFP_CPLD_I2C_ADDR)){ + DEBUG_PRINT("client->addr:0x%0x\n", client->addr); + return -ENODEV; + } + + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); +} + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if (client->addr == SFP_CPLD_I2C_ADDR) + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if (client->addr == SFP_CPLD_I2C_ADDR) + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if (client->addr == SFP_CPLD_I2C_ADDR) + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Philip Wang "); +MODULE_DESCRIPTION("alphanetworks snh60a0-320fv2 driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_onie_eeprom.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_onie_eeprom.c new file mode 100644 index 000000000000..d8e246ec2a86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_onie_eeprom.c @@ -0,0 +1,268 @@ +/* + * A driver for alphanetworks_snh60a0_320fv2 onie eeprom + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 3 of the License, or + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EEPROM_SIZE 256 + +#define SYS_LED_REG 0x8 +#define FAN12_LED_REG 0x9 +#define FAN34_LED_REG 0xA +#define FAN56_LED_REG 0xB +#define SYS_RESET1_REG 0x2 + +#define SYS_LOCATOR_LED_BITS 0x01 +#define SYS_PWR_LED_BITS 0x0E +#define SYS_STATUS_LED_BITS 0x70 +#define FAN135_LED_BITS 0x07 +#define FAN246_LED_BITS 0x38 + + +extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t onie_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t onie_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for alphanetworks_snh60a0_320fv2_onie_eeprom */ +static const unsigned short normal_i2c[] = { 0x56, I2C_CLIENT_END }; + + +enum sysfs_onie_attributes { + ONIE_RW, +}; + +static SENSOR_DEVICE_ATTR(eeprom, (0660), onie_read, onie_write, ONIE_RW); + +static struct attribute *alphanetworks_snh60a0_320fv2_onie_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + NULL +}; + +static const struct attribute_group alphanetworks_snh60a0_320fv2_onie_group = { + .attrs = alphanetworks_snh60a0_320fv2_onie_attributes, +}; + + +static ssize_t onie_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + __u8 read_write; + unsigned short offset = 0; + union i2c_smbus_data temp; + char rbuf[EEPROM_SIZE]; + + for( offset=0 ; offset < EEPROM_SIZE ; ++offset ) + { + read_write = I2C_SMBUS_WRITE; + offset = offset & 0x3fff; + temp.byte = (u8)offset; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 2, &temp); + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 2, &temp); + + read_write = I2C_SMBUS_READ; + temp.byte = 0xaa; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 1, &temp); + if (!res) + { + res = temp.byte; + rbuf[offset] = (char)temp.byte; + } + + read_write = I2C_SMBUS_READ; + temp.byte = 0xbb; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 1, &temp); + if (!res) + { + res = temp.byte; + } + } + + memcpy(buf, rbuf, EEPROM_SIZE); + return EEPROM_SIZE; +} + +static ssize_t onie_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int error, write, command, read; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + if (write < 0 || write > 255) + return -EINVAL; + + /* Not support yet */ + + return count; +} + + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int onie_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_onie_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int onie_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_onie_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id onie_eeprom_id[] = { + { "snh60a0_onie_eeprom", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, onie_eeprom_id); + +static struct i2c_driver onie_eeprom_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60a0_onie_eeprom", + }, + .probe = onie_eeprom_probe, + .remove = onie_eeprom_remove, + .id_table = onie_eeprom_id, + .address_list = normal_i2c, +}; + + +static int __init onie_eeprom_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&onie_eeprom_driver); +} + +static void __exit onie_eeprom_exit(void) + +{ + i2c_del_driver(&onie_eeprom_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("onie eeprom driver"); +MODULE_LICENSE("GPL"); + +module_init(onie_eeprom_init); +module_exit(onie_eeprom_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_power_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_power_cpld.c new file mode 100644 index 000000000000..c9a9104d266f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_power_cpld.c @@ -0,0 +1,507 @@ +/* + * A hwmon driver for the alphanetworks_snh60a0_320fv2_power_cpld + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 3 of the License, or + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRIVER_NAME "snh60a0_power_cpld" +#define PSU1_STATUS_REG 0x3 +#define PSU2_STATUS_REG 0x4 +#define FAN_PWM_REG 0x23 + +#define PSU_PRESENT_BIT 0x4 +#define PSU_POWER_BIT 0x2 +#define FAN_PRESENT_BIT 0x2 + + +static ssize_t psu_show_status(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t fan_pwm_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +static ssize_t fan_show_status(struct device *dev, struct device_attribute *attr, char *buf); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for alphanetworks_snh60a0_320fv2_power_cpld */ +static const unsigned short normal_i2c[] = { 0x5E, I2C_CLIENT_END }; + +struct alphanetworks_snh60a0_320fv2_pwr_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; + char model_name[9]; /* Model name, read from eeprom */ +}; + + +enum sysfs_psu_attributes { + PSU1_PRESENT, + PSU2_PRESENT, + PSU1_POWER_GOOD, + PSU2_POWER_GOOD, + FAN_PWM, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT, + FAN1_PRESENT=0x10, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN1_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN6_FRONT_SPEED_RPM, + FAN6_REAR_SPEED_RPM, +}; + +static SENSOR_DEVICE_ATTR(psu1_present, S_IRUGO, psu_show_status, NULL, PSU1_PRESENT); +static SENSOR_DEVICE_ATTR(psu2_present, S_IRUGO, psu_show_status, NULL, PSU2_PRESENT); +static SENSOR_DEVICE_ATTR(psu1_power_good, S_IRUGO, psu_show_status, NULL, PSU1_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu2_power_good, S_IRUGO, psu_show_status, NULL, PSU2_POWER_GOOD); +static SENSOR_DEVICE_ATTR(fan_pwm, (0660), fan_pwm_show, set_fan_pwm, FAN_PWM); +static SENSOR_DEVICE_ATTR(fan1_present, S_IRUGO, fan_show_status, NULL, FAN1_PRESENT); +static SENSOR_DEVICE_ATTR(fan2_present, S_IRUGO, fan_show_status, NULL, FAN2_PRESENT); +static SENSOR_DEVICE_ATTR(fan3_present, S_IRUGO, fan_show_status, NULL, FAN3_PRESENT); +static SENSOR_DEVICE_ATTR(fan4_present, S_IRUGO, fan_show_status, NULL, FAN4_PRESENT); +static SENSOR_DEVICE_ATTR(fan5_present, S_IRUGO, fan_show_status, NULL, FAN5_PRESENT); +static SENSOR_DEVICE_ATTR(fan6_present, S_IRUGO, fan_show_status, NULL, FAN6_PRESENT); +static SENSOR_DEVICE_ATTR(fan1_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN1_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN2_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN3_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN4_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan5_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN5_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan6_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN6_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan1_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN1_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN2_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN3_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN4_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan5_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN5_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan6_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN6_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, fan_show_status, NULL, FAN1_FAULT); static SENSOR_DEVICE_ATTR(fan11_fault, S_IRUGO, fan_show_status, NULL, FAN1_FAULT); +static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, fan_show_status, NULL, FAN2_FAULT); static SENSOR_DEVICE_ATTR(fan12_fault, S_IRUGO, fan_show_status, NULL, FAN2_FAULT); +static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, fan_show_status, NULL, FAN3_FAULT); static SENSOR_DEVICE_ATTR(fan13_fault, S_IRUGO, fan_show_status, NULL, FAN3_FAULT); +static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, fan_show_status, NULL, FAN4_FAULT); static SENSOR_DEVICE_ATTR(fan14_fault, S_IRUGO, fan_show_status, NULL, FAN4_FAULT); +static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, fan_show_status, NULL, FAN5_FAULT); static SENSOR_DEVICE_ATTR(fan15_fault, S_IRUGO, fan_show_status, NULL, FAN5_FAULT); +static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, fan_show_status, NULL, FAN6_FAULT); static SENSOR_DEVICE_ATTR(fan16_fault, S_IRUGO, fan_show_status, NULL, FAN6_FAULT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, fan_show_status, NULL, FAN1_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, fan_show_status, NULL, FAN1_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, fan_show_status, NULL, FAN2_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, fan_show_status, NULL, FAN2_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, fan_show_status, NULL, FAN3_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan13_input, S_IRUGO, fan_show_status, NULL, FAN3_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, fan_show_status, NULL, FAN4_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan14_input, S_IRUGO, fan_show_status, NULL, FAN4_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, fan_show_status, NULL, FAN5_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan15_input, S_IRUGO, fan_show_status, NULL, FAN5_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, fan_show_status, NULL, FAN6_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan16_input, S_IRUGO, fan_show_status, NULL, FAN6_REAR_SPEED_RPM); + + +static struct attribute *alphanetworks_snh60a0_320fv2_psu_attributes[] = { + &sensor_dev_attr_psu1_present.dev_attr.attr, + &sensor_dev_attr_psu2_present.dev_attr.attr, + &sensor_dev_attr_psu1_power_good.dev_attr.attr, + &sensor_dev_attr_psu2_power_good.dev_attr.attr, + &sensor_dev_attr_fan_pwm.dev_attr.attr, + &sensor_dev_attr_fan1_present.dev_attr.attr, + &sensor_dev_attr_fan2_present.dev_attr.attr, + &sensor_dev_attr_fan3_present.dev_attr.attr, + &sensor_dev_attr_fan4_present.dev_attr.attr, + &sensor_dev_attr_fan5_present.dev_attr.attr, + &sensor_dev_attr_fan6_present.dev_attr.attr, + &sensor_dev_attr_fan1_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan6_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan1_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan6_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan1_fault.dev_attr.attr, &sensor_dev_attr_fan11_fault.dev_attr.attr, + &sensor_dev_attr_fan2_fault.dev_attr.attr, &sensor_dev_attr_fan12_fault.dev_attr.attr, + &sensor_dev_attr_fan3_fault.dev_attr.attr, &sensor_dev_attr_fan13_fault.dev_attr.attr, + &sensor_dev_attr_fan4_fault.dev_attr.attr, &sensor_dev_attr_fan14_fault.dev_attr.attr, + &sensor_dev_attr_fan5_fault.dev_attr.attr, &sensor_dev_attr_fan15_fault.dev_attr.attr, + &sensor_dev_attr_fan6_fault.dev_attr.attr, &sensor_dev_attr_fan16_fault.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan11_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan12_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan13_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, &sensor_dev_attr_fan14_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, &sensor_dev_attr_fan15_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, &sensor_dev_attr_fan16_input.dev_attr.attr, + NULL +}; + +static const struct attribute_group alphanetworks_snh60a0_320fv2_psu_group = { + .attrs = alphanetworks_snh60a0_320fv2_psu_attributes, +}; + + +static ssize_t psu_show_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case PSU1_PRESENT: + case PSU1_POWER_GOOD: + command = PSU1_STATUS_REG; + break; + case PSU2_PRESENT: + case PSU2_POWER_GOOD: + command = PSU2_STATUS_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + res = (val & PSU_PRESENT_BIT ? 1 : 0 ); + break; + case PSU1_POWER_GOOD: + case PSU2_POWER_GOOD: + res = (val & PSU_POWER_BIT ? 1 : 0 ); + break; + } + + return sprintf(buf, "%d\n", res); +} + +static ssize_t fan_pwm_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, FAN_PWM_REG); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 0xFF) + return -EINVAL; + + i2c_smbus_write_byte_data(client, FAN_PWM_REG, value); + + return count; +} + +static ssize_t fan_show_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + // struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + ssize_t ret = 0; + int val, val2; + + switch (sda->index) { + /* case FAN_DUTY_CYCLE_PERCENTAGE: */ + /* { */ + /* u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); */ + /* ret = sprintf(buf, "%u\n", duty_cycle); */ + /* break; */ + /* } */ + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN6_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + case FAN6_REAR_SPEED_RPM: + val = i2c_smbus_read_byte_data(client, sda->index); + ret = sprintf(buf, "%d\n", val * 150); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + val = i2c_smbus_read_byte_data(client, sda->index); + ret = sprintf(buf, "%d\n", (val & FAN_PRESENT_BIT) ? 1 : 0); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + val = i2c_smbus_read_byte_data(client, (sda->index - FAN1_FAULT)*2 + FAN1_FRONT_SPEED_RPM); + val2 = i2c_smbus_read_byte_data(client, (sda->index - FAN1_FAULT)*2 + FAN1_REAR_SPEED_RPM); + ret = sprintf(buf, "%d\n", (val|val2) ? 0 : 1); + break; + default: + break; + } + + return ret; +} + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int alpha_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct alphanetworks_snh60a0_320fv2_pwr_cpld_data* data; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct alphanetworks_snh60a0_320fv2_pwr_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_psu_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit; + } + + dev_info(&client->dev, "%s: pwr_cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_cpld_remove(struct i2c_client *client) +{ + struct alphanetworks_snh60a0_320fv2_pwr_cpld_data *data = i2c_get_clientdata(client); + sysfs_remove_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_psu_group); + alpha_i2c_cpld_remove_client(client); + kfree(data); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { DRIVER_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRIVER_NAME, + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_read); + +int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_write); + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + +static struct dmi_system_id alphanetworks_snh60a0_320fv2_dmi_table[] = { + { + .ident = "Alpha Zion", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alpha"), + DMI_MATCH(DMI_PRODUCT_NAME, "Zion"), + }, + } +}; + +int platform_alphanetworks_snh60a0_320fv2(void) +{ + return dmi_check_system(alphanetworks_snh60a0_320fv2_dmi_table); +} +EXPORT_SYMBOL(platform_alphanetworks_snh60a0_320fv2); + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_power_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_system_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_system_cpld.c new file mode 100644 index 000000000000..13c302b35696 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/modules/snh60a0_system_cpld.c @@ -0,0 +1,380 @@ +/* + * A hwmon driver for the alphanetworks_snh60a0_320fv2_system_cpld + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 3 of the License, or + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SYS_LED_REG 0x8 +#define FAN12_LED_REG 0x9 +#define FAN34_LED_REG 0xA +#define FAN56_LED_REG 0xB +#define SYS_RESET1_REG 0x2 +#define SWI_CTRL_REG 0x4 + +#define SYS_LOCATOR_LED_BITS 0x01 +#define SYS_PWR_LED_BITS 0x0E +#define SYS_STATUS_LED_BITS 0x70 +#define FAN135_LED_BITS 0x07 +#define FAN246_LED_BITS 0x38 +#define REST_BUTTON_BITS 0x0 + + +extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t sys_led_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t sys_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for alphanetworks_snh60a0_320fv2_system_cpld */ +static const unsigned short normal_i2c[] = { 0x5F, I2C_CLIENT_END }; + + +enum sysfs_sys_attributes { + SYS_LOCATOR, + SYS_PWR, + SYS_STATUS, + FAN1_LED, + FAN2_LED, + FAN3_LED, + FAN4_LED, + FAN5_LED, + FAN6_LED, + SYS_REST1, + SWI_CTRL, +}; + +static SENSOR_DEVICE_ATTR(sys_locator, (0660), sys_led_read, sys_led_write, SYS_LOCATOR); +static SENSOR_DEVICE_ATTR(sys_pwr, (0660), sys_led_read, sys_led_write, SYS_PWR); +static SENSOR_DEVICE_ATTR(sys_status, (0600), sys_led_read, sys_led_write, SYS_STATUS); +static SENSOR_DEVICE_ATTR(fan1_led, (0660), sys_led_read, sys_led_write, FAN1_LED); +static SENSOR_DEVICE_ATTR(fan2_led, (0660), sys_led_read, sys_led_write, FAN2_LED); +static SENSOR_DEVICE_ATTR(fan3_led, (0660), sys_led_read, sys_led_write, FAN3_LED); +static SENSOR_DEVICE_ATTR(fan4_led, (0660), sys_led_read, sys_led_write, FAN4_LED); +static SENSOR_DEVICE_ATTR(fan5_led, (0660), sys_led_read, sys_led_write, FAN5_LED); +static SENSOR_DEVICE_ATTR(fan6_led, (0660), sys_led_read, sys_led_write, FAN6_LED); +static SENSOR_DEVICE_ATTR(sys_reset1, (0660), sys_led_read, sys_led_write, SYS_REST1); +static SENSOR_DEVICE_ATTR(swi_ctrl, (0660), sys_led_read, NULL, SWI_CTRL); + +static struct attribute *alphanetworks_snh60a0_320fv2_sys_attributes[] = { + &sensor_dev_attr_sys_locator.dev_attr.attr, + &sensor_dev_attr_sys_pwr.dev_attr.attr, + &sensor_dev_attr_sys_status.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &sensor_dev_attr_fan3_led.dev_attr.attr, + &sensor_dev_attr_fan4_led.dev_attr.attr, + &sensor_dev_attr_fan5_led.dev_attr.attr, + &sensor_dev_attr_fan6_led.dev_attr.attr, + &sensor_dev_attr_sys_reset1.dev_attr.attr, + &sensor_dev_attr_swi_ctrl.dev_attr.attr, + NULL +}; + +static const struct attribute_group alphanetworks_snh60a0_320fv2_sys_group = { + .attrs = alphanetworks_snh60a0_320fv2_sys_attributes, +}; + + +static ssize_t sys_led_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case SYS_LOCATOR: + case SYS_PWR: + case SYS_STATUS: + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + case FAN5_LED: + case FAN6_LED: + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + command = SYS_RESET1_REG; + break; + case SWI_CTRL: + command = SWI_CTRL_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case SYS_LOCATOR: + res = (val & SYS_LOCATOR_LED_BITS) >> 0; + break; + case SYS_PWR: + res = (val & SYS_PWR_LED_BITS) >> 1; + break; + case SYS_STATUS: + res = (val & SYS_STATUS_LED_BITS) >> 4; + break; + case FAN1_LED: + case FAN3_LED: + case FAN5_LED: + res = (val & FAN135_LED_BITS) >> 0; + break; + case FAN2_LED: + case FAN4_LED: + case FAN6_LED: + res = (val & FAN246_LED_BITS) >> 3; + break; + case SYS_REST1: + res = val; + break; + case SWI_CTRL: + res = (val & REST_BUTTON_BITS) >> 0; + break; + } + + return sprintf(buf, "%d\n", res); +} + +static ssize_t sys_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + int error, write, command, read; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + + switch(sda->index) { + case SYS_LOCATOR: + if(write < 0 || write > 2) + return -EINVAL; + case SYS_PWR: + case SYS_STATUS: + if (write < 0 || write > 7) + return -EINVAL; + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + case FAN5_LED: + case FAN6_LED: + if (write < 0 || write > 7) + return -EINVAL; + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + if (write < 0 || write > 15) + return -EINVAL; + command = SYS_RESET1_REG; + break; + } + + read = i2c_smbus_read_byte_data(client, command); + if (read < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, read); + } + + switch(sda->index) { + case SYS_LOCATOR: + read &= ~SYS_LOCATOR_LED_BITS; + read |= write << 0; + break; + case SYS_PWR: + read &= ~SYS_PWR_LED_BITS; + read |= write << 1; + break; + case SYS_STATUS: + read &= ~SYS_STATUS_LED_BITS; + read |= write << 4; + break; + case FAN1_LED: + case FAN3_LED: + case FAN5_LED: + read &= ~FAN135_LED_BITS; + read |= write << 0; + break; + case FAN2_LED: + case FAN4_LED: + case FAN6_LED: + read &= ~FAN246_LED_BITS; + read |= write << 3; + break; + case SYS_REST1: + read = write; + break; + } + + i2c_smbus_write_byte_data(client, command, read); + + return count; +} + + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int alpha_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_sys_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &alphanetworks_snh60a0_320fv2_sys_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { "snh60a0_system_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60a0_system_cpld", + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_system_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/service/snh60a0-platform-init.service b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/service/snh60a0-platform-init.service new file mode 100644 index 000000000000..564a8dcdb7a4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/service/snh60a0-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Alphanetworks SNH60A0-320F Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/alphanetworks_snh60a0_util.py install +ExecStop=/usr/local/bin/alphanetworks_snh60a0_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/setup.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/setup.py new file mode 100644 index 000000000000..94435eef3c0e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='snh60a0_320fv2', + version='1.0', + description='Module to initialize Alphanetworks SNH60A0-320FV2 platforms', + + packages=['snh60a0_320fv2'], + package_dir={'snh60a0_320fv2': 'snh60a0-320fv2/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py new file mode 100755 index 000000000000..870267e31c26 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60a0-320fv2/utils/alphanetworks_snh60a0_util.py @@ -0,0 +1,399 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Alphanetworks Technology Corporation. +# Robin Chen +# 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 3 of the License, or +# 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. +# see +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'snh60a0-320fv2' +device_path = "x86_64-alphanetworks_snh60a0_320fv2-r0" +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +FORCE = 0 + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print PROJECT_NAME.upper()+": "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +" with result: " + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod | grep alphanetworks", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe optoe' , +'modprobe snh60a0_power_cpld' , +'modprobe snh60a0_system_cpld' , +'modprobe snh60a0_onie_eeprom' , +'modprobe alphanetworks_snh60a0_320fv2_sfp' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + if kos[i].find('pca954') != -1: + status, output = log_os_system(kos[i]+ " force_deselect_on_exit=1", 1) + else: + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +i2c_prefix = '/sys/bus/i2c/devices/' + +sfp_map = [14,15,16,17] +mknod =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-8/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo snh60a0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60a0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60a0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-9/new_device', +'echo lm75 0x4D > /sys/bus/i2c/devices/i2c-4/new_device', +'echo lm75 0x4C > /sys/bus/i2c/devices/i2c-5/new_device', +'echo lm75 0x4F > /sys/bus/i2c/devices/i2c-0/new_device' ] + +mknod2 =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-8/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo snh60a0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60a0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60a0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-9/new_device', +'echo lm75 0x4D > /sys/bus/i2c/devices/i2c-4/new_device', +'echo lm75 0x4C > /sys/bus/i2c/devices/i2c-5/new_device', +'echo lm75 0x4F > /sys/bus/i2c/devices/i2c-1/new_device' ] + + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + + status, output = log_os_system("i2cdetect -l | grep I801 | grep i2c-0", 0) + if not output: + order = 1 + else: + order = 0 + + if not device_exist(): + #order = 1 + tmp = "sed -i 's/0-/1-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + status, output = log_os_system(tmp, 0) + tmp = "sed -i 's/0-/1-/g' /usr/share/sonic/device/"+device_path+"/plugins/led_control.py" + status, output = log_os_system(tmp, 0) + else: + #order = 0 + tmp = "sed -i 's/1-/0-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + status, output = log_os_system(tmp, 0) + tmp = "sed -i 's/1-/0-/g' /usr/share/sonic/device/"+device_path+"/plugins/led_control.py" + status, output = log_os_system(tmp, 0) + + + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + if mknod2[i].find('lm75') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + if mknod[i].find('lm75') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + status, output =log_os_system("echo 0 > /sys/bus/i2c/devices/9-005f/sys_reset1", 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0, 32): + index = i / 8 + port = i % 8 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x5f > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + status, output = log_os_system("i2cdetect -l | grep I801 | grep i2c-0", 0) + + if not output: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0, 32): + index = i / 8 + port = i % 8 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x5f > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + tmp = "find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '429d' | sed '428a if \[ $? -ne 1 \]' | sed '425d' | sed '424a return' > /tmp/tmp_fancontrol" + status, output = log_os_system(tmp, 1) + tmp = "fancontrol_tmp=`find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol` ; cp /tmp/tmp_fancontrol $fancontrol_tmp" + status, output = log_os_system(tmp, 1) + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/classes/__init__.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/Makefile b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/Makefile new file mode 100644 index 000000000000..ec14f1229d66 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/Makefile @@ -0,0 +1,8 @@ +# obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ +# goreme_system_cpld.o ym2651y.o optoe.o + +obj-m:=alphanetworks_snh60b0-640f_sfp.o snh60b0-640f_system_cpld.o snh60b0-640f_power_cpld.o snh60b0-640f_onie_eeprom.o + + +# obj-m:=accton_as7712_32x_fan.o accton_as7712_32x_sfp.o leds-accton_as7712_32x.o \ +# accton_as7712_32x_psu.o accton_i2c_cpld.o ym2651y.o optoe.o diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c new file mode 100644 index 000000000000..8985790cce6c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/alphanetworks_snh60b0-640f_sfp.c @@ -0,0 +1,2076 @@ +/* + * SFP driver for alphanetworks snh60b0-640f sfp + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Philip Wang + * + * 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 3 of the License, or + * 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. + * see + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "snh60b0_640f_sfp" + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s[%s,%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define NUM_OF_SFP_PORT 64 +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_CPLD_I2C_ADDR 0x5F +#define SFP_EEPROM_A0_I2C_ADDR 0x50 +#define SFP_EEPROM_A2_I2C_ADDR 0x68 +#define SFP_PCA9506_I2C_ADDR 0x20 + + +#define SFPPLUS_1_PORT_NUMBER 64 +#define SFPPLUS_2_PORT_NUMBER 65 + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +/* extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); */ +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { SFP_EEPROM_A0_I2C_ADDR, SFP_EEPROM_A2_I2C_ADDR, SFP_CPLD_I2C_ADDR, SFP_PCA9506_I2C_ADDR, I2C_CLIENT_END }; + +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +sfp1, sfp2, sfp3, sfp4, sfp5, sfp6, sfp7, sfp8, +sfp9, sfp10, sfp11, sfp12, sfp13, sfp14, sfp15, sfp16, +sfp17, sfp18, sfp19, sfp20, sfp21, sfp22, sfp23, sfp24, +sfp25, sfp26, sfp27, sfp28, sfp29, sfp30, sfp31, sfp32, +sfp33, sfp34, sfp35, sfp36, sfp37, sfp38, sfp39, sfp40, +sfp41, sfp42, sfp43, sfp44, sfp45, sfp46, sfp47, sfp48, +sfp49, sfp50, sfp51, sfp52, sfp53, sfp54, sfp55, sfp56, +sfp57, sfp58, sfp59, sfp60, sfp61, sfp62, sfp63, sfp64, +sfp65, sfp66 +}; + +static const struct i2c_device_id sfp_device_id[] = { +{ "sfpcpld1", sfp1 }, { "sfpcpld2", sfp2 }, { "sfpcpld3", sfp3 }, { "sfpcpld4", sfp4 }, +{ "sfpcpld5", sfp5 }, { "sfpcpld6", sfp6 }, { "sfpcpld7", sfp7 }, { "sfpcpld8", sfp8 }, +{ "sfpcpld9", sfp9 }, { "sfpcpld10", sfp10 }, { "sfpcpld11", sfp11 }, { "sfpcpld12", sfp12 }, +{ "sfpcpld13", sfp13 }, { "sfpcpld14", sfp14 }, { "sfpcpld15", sfp15 }, { "sfpcpld16", sfp16 }, +{ "sfpcpld17", sfp17 }, { "sfpcpld18", sfp18 }, { "sfpcpld19", sfp19 }, { "sfpcpld20", sfp20 }, +{ "sfpcpld21", sfp21 }, { "sfpcpld22", sfp22 }, { "sfpcpld23", sfp23 }, { "sfpcpld24", sfp24 }, +{ "sfpcpld25", sfp25 }, { "sfpcpld26", sfp26 }, { "sfpcpld27", sfp27 }, { "sfpcpld28", sfp28 }, +{ "sfpcpld29", sfp29 }, { "sfpcpld30", sfp30 }, { "sfpcpld31", sfp31 }, { "sfpcpld32", sfp32 }, +{ "sfpcpld33", sfp33 }, { "sfpcpld34", sfp34 }, { "sfpcpld35", sfp35 }, { "sfpcpld36", sfp36 }, +{ "sfpcpld37", sfp37 }, { "sfpcpld38", sfp38 }, { "sfpcpld39", sfp39 }, { "sfpcpld40", sfp40 }, +{ "sfpcpld41", sfp41 }, { "sfpcpld42", sfp42 }, { "sfpcpld43", sfp43 }, { "sfpcpld44", sfp44 }, +{ "sfpcpld45", sfp45 }, { "sfpcpld46", sfp46 }, { "sfpcpld47", sfp47 }, { "sfpcpld48", sfp48 }, +{ "sfpcpld49", sfp49 }, { "sfpcpld50", sfp50 }, { "sfpcpld51", sfp51 }, { "sfpcpld52", sfp52 }, +{ "sfpcpld53", sfp53 }, { "sfpcpld54", sfp54 }, { "sfpcpld55", sfp55 }, { "sfpcpld56", sfp56 }, +{ "sfpcpld57", sfp57 }, { "sfpcpld58", sfp58 }, { "sfpcpld59", sfp59 }, { "sfpcpld60", sfp60 }, +{ "sfpcpld61", sfp61 }, { "sfpcpld62", sfp62 }, { "sfpcpld63", sfp63 }, { "sfpcpld64", sfp64 }, +{ "sfpcpld65", sfp65 }, { "sfpcpld66", sfp66 }, {} +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[2]; /* index 0 => device id + 1 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 2 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + u64 port_reset; /* reset status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +enum sfp_sysfs_port_num_attributes { + PORT1_NUMBER, + PORT2_NUMBER, + PORT3_NUMBER, + PORT4_NUMBER, + PORT5_NUMBER, + PORT6_NUMBER, + PORT7_NUMBER, + PORT8_NUMBER, + PORT9_NUMBER, + PORT10_NUMBER, + PORT11_NUMBER, + PORT12_NUMBER, + PORT13_NUMBER, + PORT14_NUMBER, + PORT15_NUMBER, + PORT16_NUMBER, + PORT_NUMBER_MAX +}; + +enum sfp_sysfs_present_attributes { + PORT1_PRESENT, + PORT2_PRESENT, + PORT3_PRESENT, + PORT4_PRESENT, + PORT5_PRESENT, + PORT6_PRESENT, + PORT7_PRESENT, + PORT8_PRESENT, + PORT9_PRESENT, + PORT10_PRESENT, + PORT11_PRESENT, + PORT12_PRESENT, + PORT13_PRESENT, + PORT14_PRESENT, + PORT15_PRESENT, + PORT16_PRESENT, + PORT1_PRESENT_ALL, + PORT2_PRESENT_ALL, + PORT3_PRESENT_ALL, + PORT4_PRESENT_ALL, + PORT5_PRESENT_ALL, + PORT6_PRESENT_ALL, + PORT7_PRESENT_ALL, + PORT8_PRESENT_ALL, + PORT9_PRESENT_ALL, + PORT10_PRESENT_ALL, + PORT11_PRESENT_ALL, + PORT12_PRESENT_ALL, + PORT13_PRESENT_ALL, + PORT14_PRESENT_ALL, + PORT15_PRESENT_ALL, + PORT16_PRESENT_ALL, + PORT_PRESENT_MAX +}; + +enum sfp_sysfs_type_attributes { + PORT1_TYPE, + PORT2_TYPE, + PORT3_TYPE, + PORT4_TYPE, + PORT5_TYPE, + PORT6_TYPE, + PORT7_TYPE, + PORT8_TYPE, + PORT9_TYPE, + PORT10_TYPE, + PORT11_TYPE, + PORT12_TYPE, + PORT13_TYPE, + PORT14_TYPE, + PORT15_TYPE, + PORT16_TYPE, + PORT_TYPE_MAX +}; + +enum sfp_sysfs_reset_attributes { + PORT1_RESET, + PORT2_RESET, + PORT3_RESET, + PORT4_RESET, + PORT5_RESET, + PORT6_RESET, + PORT7_RESET, + PORT8_RESET, + PORT9_RESET, + PORT10_RESET, + PORT11_RESET, + PORT12_RESET, + PORT13_RESET, + PORT14_RESET, + PORT15_RESET, + PORT16_RESET, + PORT_RESET_MAX +}; + +enum sfp_sysfs_rx_los_attributes { + PORT1_RX_LOS, + PORT2_RX_LOS, + PORT3_RX_LOS, + PORT4_RX_LOS, + PORT5_RX_LOS, + PORT6_RX_LOS, + PORT7_RX_LOS, + PORT8_RX_LOS, + PORT9_RX_LOS, + PORT10_RX_LOS, + PORT11_RX_LOS, + PORT12_RX_LOS, + PORT13_RX_LOS, + PORT14_RX_LOS, + PORT15_RX_LOS, + PORT16_RX_LOS, + PORT_RX_LOS_MAX +}; + +enum sfp_sysfs_rx_los1_attributes { + PORT1_RX_LOS1 = PORT_RX_LOS_MAX, + PORT2_RX_LOS1, + PORT3_RX_LOS1, + PORT4_RX_LOS1, + PORT5_RX_LOS1, + PORT6_RX_LOS1, + PORT7_RX_LOS1, + PORT8_RX_LOS1, + PORT9_RX_LOS1, + PORT10_RX_LOS1, + PORT11_RX_LOS1, + PORT12_RX_LOS1, + PORT13_RX_LOS1, + PORT14_RX_LOS1, + PORT15_RX_LOS1, + PORT16_RX_LOS1, + PORT_RX_LOS1_MAX +}; + +enum sfp_sysfs_rx_los2_attributes { + PORT1_RX_LOS2 = PORT_RX_LOS1_MAX, + PORT2_RX_LOS2, + PORT3_RX_LOS2, + PORT4_RX_LOS2, + PORT5_RX_LOS2, + PORT6_RX_LOS2, + PORT7_RX_LOS2, + PORT8_RX_LOS2, + PORT9_RX_LOS2, + PORT10_RX_LOS2, + PORT11_RX_LOS2, + PORT12_RX_LOS2, + PORT13_RX_LOS2, + PORT14_RX_LOS2, + PORT15_RX_LOS2, + PORT16_RX_LOS2, + PORT_RX_LOS2_MAX +}; + +enum sfp_sysfs_rx_los3_attributes { + PORT1_RX_LOS3 = PORT_RX_LOS2_MAX, + PORT2_RX_LOS3, + PORT3_RX_LOS3, + PORT4_RX_LOS3, + PORT5_RX_LOS3, + PORT6_RX_LOS3, + PORT7_RX_LOS3, + PORT8_RX_LOS3, + PORT9_RX_LOS3, + PORT10_RX_LOS3, + PORT11_RX_LOS3, + PORT12_RX_LOS3, + PORT13_RX_LOS3, + PORT14_RX_LOS3, + PORT15_RX_LOS3, + PORT16_RX_LOS3, + PORT_RX_LOS3_MAX +}; + +enum sfp_sysfs_rx_los4_attributes { + PORT1_RX_LOS4 = PORT_RX_LOS3_MAX, + PORT2_RX_LOS4, + PORT3_RX_LOS4, + PORT4_RX_LOS4, + PORT5_RX_LOS4, + PORT6_RX_LOS4, + PORT7_RX_LOS4, + PORT8_RX_LOS4, + PORT9_RX_LOS4, + PORT10_RX_LOS4, + PORT11_RX_LOS4, + PORT12_RX_LOS4, + PORT13_RX_LOS4, + PORT14_RX_LOS4, + PORT15_RX_LOS4, + PORT16_RX_LOS4, + PORT_RX_LOS4_MAX +}; + +enum sfp_sysfs_rx_los_all_attributes { + PORT1_RX_LOS_ALL = PORT_RX_LOS4_MAX, + PORT2_RX_LOS_ALL, + PORT3_RX_LOS_ALL, + PORT4_RX_LOS_ALL, + PORT5_RX_LOS_ALL, + PORT6_RX_LOS_ALL, + PORT7_RX_LOS_ALL, + PORT8_RX_LOS_ALL, + PORT9_RX_LOS_ALL, + PORT10_RX_LOS_ALL, + PORT11_RX_LOS_ALL, + PORT12_RX_LOS_ALL, + PORT13_RX_LOS_ALL, + PORT14_RX_LOS_ALL, + PORT15_RX_LOS_ALL, + PORT16_RX_LOS_ALL, + PORT_RX_LOS_ALL_MAX +}; + +enum sfp_sysfs_tx_disable_attributes { + PORT1_TX_DISABLE = PORT_RX_LOS_ALL_MAX, + PORT2_TX_DISABLE, + PORT3_TX_DISABLE, + PORT4_TX_DISABLE, + PORT5_TX_DISABLE, + PORT6_TX_DISABLE, + PORT7_TX_DISABLE, + PORT8_TX_DISABLE, + PORT9_TX_DISABLE, + PORT10_TX_DISABLE, + PORT11_TX_DISABLE, + PORT12_TX_DISABLE, + PORT13_TX_DISABLE, + PORT14_TX_DISABLE, + PORT15_TX_DISABLE, + PORT16_TX_DISABLE, + PORT_TX_DISABLE_MAX +}; + +enum sfp_sysfs_tx_disable1_attributes { + PORT1_TX_DISABLE1 = PORT_TX_DISABLE_MAX, + PORT2_TX_DISABLE1, + PORT3_TX_DISABLE1, + PORT4_TX_DISABLE1, + PORT5_TX_DISABLE1, + PORT6_TX_DISABLE1, + PORT7_TX_DISABLE1, + PORT8_TX_DISABLE1, + PORT9_TX_DISABLE1, + PORT10_TX_DISABLE1, + PORT11_TX_DISABLE1, + PORT12_TX_DISABLE1, + PORT13_TX_DISABLE1, + PORT14_TX_DISABLE1, + PORT15_TX_DISABLE1, + PORT16_TX_DISABLE1, + PORT_TX_DISABLE1_MAX +}; + +enum sfp_sysfs_tx_disable2_attributes { + PORT1_TX_DISABLE2 = PORT_TX_DISABLE1_MAX, + PORT2_TX_DISABLE2, + PORT3_TX_DISABLE2, + PORT4_TX_DISABLE2, + PORT5_TX_DISABLE2, + PORT6_TX_DISABLE2, + PORT7_TX_DISABLE2, + PORT8_TX_DISABLE2, + PORT9_TX_DISABLE2, + PORT10_TX_DISABLE2, + PORT11_TX_DISABLE2, + PORT12_TX_DISABLE2, + PORT13_TX_DISABLE2, + PORT14_TX_DISABLE2, + PORT15_TX_DISABLE2, + PORT16_TX_DISABLE2, + PORT_TX_DISABLE2_MAX +}; + +enum sfp_sysfs_tx_disable3_attributes { + PORT1_TX_DISABLE3 = PORT_TX_DISABLE2_MAX, + PORT2_TX_DISABLE3, + PORT3_TX_DISABLE3, + PORT4_TX_DISABLE3, + PORT5_TX_DISABLE3, + PORT6_TX_DISABLE3, + PORT7_TX_DISABLE3, + PORT8_TX_DISABLE3, + PORT9_TX_DISABLE3, + PORT10_TX_DISABLE3, + PORT11_TX_DISABLE3, + PORT12_TX_DISABLE3, + PORT13_TX_DISABLE3, + PORT14_TX_DISABLE3, + PORT15_TX_DISABLE3, + PORT16_TX_DISABLE3, + PORT_TX_DISABLE3_MAX +}; + +enum sfp_sysfs_tx_disable4_attributes { + PORT1_TX_DISABLE4 = PORT_TX_DISABLE3_MAX, + PORT2_TX_DISABLE4, + PORT3_TX_DISABLE4, + PORT4_TX_DISABLE4, + PORT5_TX_DISABLE4, + PORT6_TX_DISABLE4, + PORT7_TX_DISABLE4, + PORT8_TX_DISABLE4, + PORT9_TX_DISABLE4, + PORT10_TX_DISABLE4, + PORT11_TX_DISABLE4, + PORT12_TX_DISABLE4, + PORT13_TX_DISABLE4, + PORT14_TX_DISABLE4, + PORT15_TX_DISABLE4, + PORT16_TX_DISABLE4, + PORT_TX_DISABLE4_MAX +}; + +enum sfp_sysfs_tx_disable_all_attributes { + PORT1_TX_DISABLE_ALL = PORT_TX_DISABLE4_MAX, + PORT2_TX_DISABLE_ALL, + PORT3_TX_DISABLE_ALL, + PORT4_TX_DISABLE_ALL, + PORT5_TX_DISABLE_ALL, + PORT6_TX_DISABLE_ALL, + PORT7_TX_DISABLE_ALL, + PORT8_TX_DISABLE_ALL, + PORT9_TX_DISABLE_ALL, + PORT10_TX_DISABLE_ALL, + PORT11_TX_DISABLE_ALL, + PORT12_TX_DISABLE_ALL, + PORT13_TX_DISABLE_ALL, + PORT14_TX_DISABLE_ALL, + PORT15_TX_DISABLE_ALL, + PORT16_TX_DISABLE_ALL, + PORT_TX_DISABLE_ALL_MAX +}; + +enum sfp_sysfs_tx_fault_attributes { + PORT1_TX_FAULT = PORT_TX_DISABLE_ALL_MAX, + PORT2_TX_FAULT, + PORT3_TX_FAULT, + PORT4_TX_FAULT, + PORT5_TX_FAULT, + PORT6_TX_FAULT, + PORT7_TX_FAULT, + PORT8_TX_FAULT, + PORT9_TX_FAULT, + PORT10_TX_FAULT, + PORT11_TX_FAULT, + PORT12_TX_FAULT, + PORT13_TX_FAULT, + PORT14_TX_FAULT, + PORT15_TX_FAULT, + PORT16_TX_FAULT, + PORT_TX_FAULT_MAX +}; + +enum sfp_sysfs_tx_fault1_attributes { + PORT1_TX_FAULT1 = PORT_TX_FAULT_MAX, + PORT2_TX_FAULT1, + PORT3_TX_FAULT1, + PORT4_TX_FAULT1, + PORT5_TX_FAULT1, + PORT6_TX_FAULT1, + PORT7_TX_FAULT1, + PORT8_TX_FAULT1, + PORT9_TX_FAULT1, + PORT10_TX_FAULT1, + PORT11_TX_FAULT1, + PORT12_TX_FAULT1, + PORT13_TX_FAULT1, + PORT14_TX_FAULT1, + PORT15_TX_FAULT1, + PORT16_TX_FAULT1, + PORT_TX_FAULT1_MAX +}; + +enum sfp_sysfs_tx_fault2_attributes { + PORT1_TX_FAULT2 = PORT_TX_FAULT1_MAX, + PORT2_TX_FAULT2, + PORT3_TX_FAULT2, + PORT4_TX_FAULT2, + PORT5_TX_FAULT2, + PORT6_TX_FAULT2, + PORT7_TX_FAULT2, + PORT8_TX_FAULT2, + PORT9_TX_FAULT2, + PORT10_TX_FAULT2, + PORT11_TX_FAULT2, + PORT12_TX_FAULT2, + PORT13_TX_FAULT2, + PORT14_TX_FAULT2, + PORT15_TX_FAULT2, + PORT16_TX_FAULT2, + PORT_TX_FAULT2_MAX +}; + +enum sfp_sysfs_tx_fault3_attributes { + PORT1_TX_FAULT3 = PORT_TX_FAULT2_MAX, + PORT2_TX_FAULT3, + PORT3_TX_FAULT3, + PORT4_TX_FAULT3, + PORT5_TX_FAULT3, + PORT6_TX_FAULT3, + PORT7_TX_FAULT3, + PORT8_TX_FAULT3, + PORT9_TX_FAULT3, + PORT10_TX_FAULT3, + PORT11_TX_FAULT3, + PORT12_TX_FAULT3, + PORT13_TX_FAULT3, + PORT14_TX_FAULT3, + PORT15_TX_FAULT3, + PORT16_TX_FAULT3, + PORT_TX_FAULT3_MAX +}; + +enum sfp_sysfs_tx_fault4_attributes { + PORT1_TX_FAULT4 = PORT_TX_FAULT3_MAX, + PORT2_TX_FAULT4, + PORT3_TX_FAULT4, + PORT4_TX_FAULT4, + PORT5_TX_FAULT4, + PORT6_TX_FAULT4, + PORT7_TX_FAULT4, + PORT8_TX_FAULT4, + PORT9_TX_FAULT4, + PORT10_TX_FAULT4, + PORT11_TX_FAULT4, + PORT12_TX_FAULT4, + PORT13_TX_FAULT4, + PORT14_TX_FAULT4, + PORT15_TX_FAULT4, + PORT16_TX_FAULT4, + PORT_TX_FAULT4_MAX +}; + +enum sfp_sysfs_eeprom_attributes { + PORT1_EEPROM, + PORT2_EEPROM, + PORT3_EEPROM, + PORT4_EEPROM, + PORT5_EEPROM, + PORT6_EEPROM, + PORT7_EEPROM, + PORT8_EEPROM, + PORT9_EEPROM, + PORT10_EEPROM, + PORT11_EEPROM, + PORT12_EEPROM, + PORT13_EEPROM, + PORT14_EEPROM, + PORT15_EEPROM, + PORT16_EEPROM, + PORT_EEPROM_MAX +}; + +enum sfp_sysfs_ddm_implemented_attributes { + PORT1_DDM_IMPLEMENTED, + PORT2_DDM_IMPLEMENTED, + PORT3_DDM_IMPLEMENTED, + PORT4_DDM_IMPLEMENTED, + PORT5_DDM_IMPLEMENTED, + PORT6_DDM_IMPLEMENTED, + PORT7_DDM_IMPLEMENTED, + PORT8_DDM_IMPLEMENTED, + PORT9_DDM_IMPLEMENTED, + PORT10_DDM_IMPLEMENTED, + PORT11_DDM_IMPLEMENTED, + PORT12_DDM_IMPLEMENTED, + PORT13_DDM_IMPLEMENTED, + PORT14_DDM_IMPLEMENTED, + PORT15_DDM_IMPLEMENTED, + PORT16_DDM_IMPLEMENTED, + PORT_DDM_IMPLEMENTED_MAX +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + DEBUG_PRINT("show_port_number port number:%d", data->port + attr->index); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port + attr->index)); +} + +static struct sfp_port_data *sfp_pca9506_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x03}; + + DEBUG_PRINT("Starting pca9506 sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + /* status = alpha_i2c_cpld_read(0x5f, regs[i]); */ + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("pca9506(0x20) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + data->present = status; + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x05, 0x06}; + + if(data->port >= SFPPLUS_1_PORT_NUMBER){ + return sfp_pca9506_update_present(client); + } + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + + /* Read present status of port 1~32 */ + data->present = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + /* status = alpha_i2c_cpld_read(0x5f, regs[i]); */ + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x5f) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + data->present |= (u64)status << (i*8); + DEBUG_PRINT("Present status = 0x%llx", data->present); + } + + DEBUG_PRINT("Present status = 0x%llx", data->present); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + return NULL; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return 0; +} + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = sfp_update_present(client); + + if(data->port >= SFPPLUS_1_PORT_NUMBER) + return (data->present & BIT_INDEX(port)) ? 0 : 1; + else + return (data->present & BIT_INDEX(port)) ? 1 : 0; +} + +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if ((attr->index >= PORT1_PRESENT_ALL) && (attr->index <= PORT8_PRESENT_ALL)) { + + } + + /* PRESENT */ + return sprintf(buf, "%d\n", sfp_is_port_present(client, attr->index)); +} + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(data->client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(data->client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (status < 0) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (!sfp_is_port_present(client, attr->index)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + + +static struct sfp_port_data *sfp_update_port_reset(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0; + int status = -1; + u8 regs[] = {0x07, 0x08}; + + mutex_lock(&data->update_lock); + + /* Read reset status of port 1~32 */ + data->port_reset = 0; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = i2c_smbus_read_byte_data(client, regs[i]); + + if (status < 0) { + DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); + goto exit; + } + + DEBUG_PRINT("reset status = 0x%x", status); + data->port_reset |= (u64)status << (i*8); + } + + DEBUG_PRINT("reset status = 0x%llx", data->port_reset); +exit: + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int is_reset = 0; + + if (!sfp_is_port_present(client, attr->index)) { + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_reset(client); + is_reset = (data->port_reset & BIT_INDEX(attr->index))? 0 : 1; + + return sprintf(buf, "%d\n", is_reset); +} + +static ssize_t sfp_set_port_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 cpld_reg = 0, cpld_val = 0; /*, cpld_bit = 0; //remove unused variable */ + long is_reset; + int error; + + error = kstrtol(buf, 10, &is_reset); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + cpld_reg = 0x07; + + cpld_val = i2c_smbus_read_byte_data(client, cpld_reg); + + DEBUG_PRINT("current cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + /* Update reset status. CPLD defined 0 is reset state, 1 is normal state. + * is_reset: 0 is not reset. 1 is reset. + */ + if (is_reset == 0) { + data->port_reset |= BIT_INDEX(attr->index); + } + else { + data->port_reset &= ~BIT_INDEX(attr->index); + } + + alpha_i2c_cpld_write(0x5f, cpld_reg, cpld_val); + DEBUG_PRINT("write cpld reg = 0x%x value = 0x%x", cpld_reg, cpld_val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + dev_dbg(dev, "Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + } + msleep(200); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(data->client, reg[i], &buf, sizeof(buf)); + if (status < 0) { + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + mutex_unlock(&data->update_lock); + return data; + +exit: + mutex_unlock(&data->update_lock); + return NULL; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data = i2c_get_clientdata(client); + + if (!sfp_is_port_present(client, attr->index)) { + return -ENODEV; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + if ((attr->index >= PORT1_TX_FAULT1) && (attr->index < PORT_TX_FAULT4_MAX)){ + val = (data->qsfp->status[2] & BIT_INDEX(attr->index - PORT1_TX_FAULT1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE1) && (attr->index < PORT_TX_DISABLE4_MAX)){ + val = (data->qsfp->status[1] & BIT_INDEX(attr->index - PORT1_TX_DISABLE1)) ? 1 : 0; + } + else if ((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index < PORT_TX_DISABLE_ALL_MAX)){ + val = ((data->qsfp->status[1] & 0xF) == 0xF) ? 1 : 0; + } + if ((attr->index >= PORT1_RX_LOS1) && (attr->index < PORT_RX_LOS4_MAX)){ + val = (data->qsfp->status[0] & BIT_INDEX(attr->index - PORT1_RX_LOS1)) ? 1 : 0; + } + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int result; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + result = kstrtol(buf, 10, &disable); + if (result) { + return result; + } + + data = qsfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + + mutex_lock(&data->update_lock); + + if((attr->index >= PORT1_TX_DISABLE_ALL) && (attr->index < PORT_TX_DISABLE_ALL_MAX)){ + DEBUG_PRINT ("disable:%ld %d==TX_DISABLE_ALL %u\r\n", disable, attr->index, data->qsfp->status[1]); + data->qsfp->status[1] = disable? 0xF:0; + } + else{ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - PORT1_TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - PORT1_TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + result = sfp_eeprom_write(client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + if (!sfp_is_port_present(client, attr->index)) { + return -ENODEV; + } + + status = sfp_eeprom_read(data->client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (status < 0) { + return -EIO; + } + + return sprintf(buf, "%d\n", (ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK) ? 1 : 0); +} + +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct sfp_port_data *data; + + data = sfp_update_tx_rx_status(dev); + if (!data) { + return -EIO; + } + if ((attr->index >= PORT1_TX_FAULT) && (attr->index < PORT_TX_FAULT_MAX)){ + index = 0; + } + else if ((attr->index >= PORT1_TX_DISABLE) && (attr->index < PORT_TX_DISABLE_MAX)){ + index = 1; + } + if ((attr->index >= PORT1_RX_LOS) && (attr->index < PORT_RX_LOS_MAX)){ + index = 2; + } + + if(data->port == SFPPLUS_1_PORT_NUMBER) + val = (data->ddm->status[index] & BIT_INDEX(0)) ? 1 : 0; + else if(data->port == SFPPLUS_1_PORT_NUMBER) + val = (data->ddm->status[index] & BIT_INDEX(1)) ? 1 : 0; + else + val = (data->ddm->status[index] & BIT_INDEX(attr->index)) ? 1 : 0; + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_show_eeprom(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + char devfile[96]; + struct file *sfd; + int i2c_index = 0; + int result; + int offset[] = {0x0b, 0x0c}; + int rdlen, rc; + mm_segment_t old_fs; + char buffer[256]; + + if (!sfp_is_port_present(client, attr->index)) { + return 0; + } + + if(strcmp(client->name, "sfpcpld1") == 0) + i2c_index = 13; + else if(strcmp(client->name, "sfpcpld17") == 0) + i2c_index = 14; + else if(strcmp(client->name, "sfpcpld33") == 0) + i2c_index = 15; + else if(strcmp(client->name, "sfpcpld49") == 0) + i2c_index = 16; + else if(strcmp(client->name, "sfpcpld65") == 0){ + if(attr->index == 0) + i2c_index = 21; + else if(attr->index == 1) + i2c_index = 22; + } + + snprintf(devfile, sizeof(devfile), "/sys/bus/i2c/devices/%d-0050/sfp_eeprom", i2c_index); + + /* Set module select register */ + switch(i2c_index){ + case 13: + case 14: + case 15: + case 16: + if((attr->index/8) == 0){ + /* Port number is 1-8 */ + result = i2c_smbus_write_byte_data(client, offset[0], BIT_INDEX(attr->index)); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + else if((attr->index/8) == 1){ + /* Port number is 9-16 */ + result = i2c_smbus_write_byte_data(client, offset[1], BIT_INDEX((attr->index)%8)); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + break; + default: + break; + } + + /* Read SFP EEPROM */ + sfd = filp_open(devfile, O_RDONLY, 0); + if (IS_ERR(sfd)) { + dev_info(&client->dev, "Failed to open file(%s)#%d", devfile, __LINE__); + return 0; + } + + if(!(sfd->f_op) || !(sfd->f_op->read) ) { + dev_info(&client->dev, "file %s cann't readable ?\n", devfile); + return 0; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + rdlen = sfd->f_op->read(sfd, buffer, sizeof(buffer), &sfd->f_pos); + if (rdlen == 0) { + dev_info(&client->dev, "File(%s) empty!\n", devfile); + rc = 0; + goto exit; + } + + rc = sizeof(buffer); + memcpy(buf, buffer, rc); + + /* Reset module select register */ + switch(i2c_index){ + case 13: + case 14: + case 15: + case 16: + if((attr->index/8) == 0){ + /* Port number is 1-8 */ + result = i2c_smbus_write_byte_data(client, offset[0], 0); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + else if((attr->index/8) == 1){ + /* Port number is 9-16 */ + result = i2c_smbus_write_byte_data(client, offset[1], 0); + if (result < 0) { + dev_info(&client->dev, "i2c_smbus_write_byte_data fail(%d)", result); + } + } + break; + default: + break; + } + +exit: + set_fs(old_fs); + filp_close(sfd, 0); + + return rc; +} + +#if 0 +static ssize_t qsfp_set_eeprom(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + DEBUG_PRINT("data->port:%d attr index:%d", data->port, attr->index); + return 1; +} +#endif + +/* SFP/QSFP common attributes for sysfs */ +#define DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT1##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT2##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT3##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT4##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT5##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT6##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT7##_NUMBER); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_number, S_IRUGO, show_port_number, NULL, PORT##PORT8##_NUMBER); +#define DECLARE_PORT_NUMBER_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_number.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_number.dev_attr.attr, +DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_NUMBER_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_is_present, S_IRUGO, show_present, NULL, PORT##PORT1##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_is_present, S_IRUGO, show_present, NULL, PORT##PORT2##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_is_present, S_IRUGO, show_present, NULL, PORT##PORT3##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_is_present, S_IRUGO, show_present, NULL, PORT##PORT4##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_is_present, S_IRUGO, show_present, NULL, PORT##PORT5##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_is_present, S_IRUGO, show_present, NULL, PORT##PORT6##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_is_present, S_IRUGO, show_present, NULL, PORT##PORT7##_PRESENT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_is_present, S_IRUGO, show_present, NULL, PORT##PORT8##_PRESENT); +#define DECLARE_PORT_IS_PRESENT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_is_present.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_is_present.dev_attr.attr, +DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_IS_PRESENT_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT1##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT2##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT3##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT4##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT5##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT6##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT7##_TYPE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_type, S_IRUGO, show_port_type, NULL, PORT##PORT8##_TYPE); +#define DECLARE_PORT_TYPE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_type.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_type.dev_attr.attr, +DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TYPE_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT1##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT2##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT3##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT4##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT5##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT6##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT7##_RESET); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_port_reset, S_IWUSR | S_IRUGO, show_port_reset, sfp_set_port_reset, PORT##PORT8##_RESET); +#define DECLARE_PORT_RESET_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_port_reset.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_port_reset.dev_attr.attr, +DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RESET_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +/* QSFP attributes for sysfs */ +#define DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT1##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT2##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT3##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT4##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT5##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS##INDEX); +#define DECLARE_PORT_RX_LOSn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_rx_los##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_rx_los##INDEX.dev_attr.attr, +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_RX_LOSn_SENSOR_DEVICE_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT1##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT2##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT3##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT4##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT5##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT6##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT7##_TX_DISABLE##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable##INDEX, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, PORT##PORT8##_TX_DISABLE##INDEX); + +#define DECLARE_PORT_TX_DISABLEn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_disable##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_disable##INDEX.dev_attr.attr, +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_DISABLEn_SENSOR_DEVICE_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT1##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT2##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT3##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT4##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT5##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT##INDEX); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault##INDEX, S_IRUGO, qsfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT##INDEX); +#define DECLARE_PORT_TX_FAULTn_ATTR(INDEX, PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_fault##INDEX.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_fault##INDEX.dev_attr.attr, +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_TX_FAULTn_SENSOR_DEVICE_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT1##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT2##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT3##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT4##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT5##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT6##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT7##_EEPROM); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_eeprom, S_IRUGO, qsfp_show_eeprom, NULL, PORT##PORT8##_EEPROM); +#define DECLARE_PORT_EEPROMTn_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + &sensor_dev_attr_sfp##PORT1##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_eeprom.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_eeprom.dev_attr.attr, +DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_PORT_EEPROMn_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +static struct attribute *qsfp_attributes[] = { + DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_NUMBER_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_IS_PRESENT_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RESET_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RX_LOSn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RX_LOSn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RX_LOSn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RX_LOSn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RX_LOSn_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_DISABLEn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_DISABLEn_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(1, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(1, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(2, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(2, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(3, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(3, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TX_FAULTn_ATTR(4, 1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TX_FAULTn_ATTR(4, 9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_EEPROMTn_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_EEPROMTn_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + NULL +}; + + +/* SFP msa attributes for sysfs */ +static struct attribute *sfp_msa_attributes[] = { + DECLARE_PORT_NUMBER_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_NUMBER_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_TYPE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_TYPE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_IS_PRESENT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_IS_PRESENT_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_PORT_RESET_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_PORT_RESET_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + NULL +}; + +/* SFP ddm attributes for sysfs */ +#define DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT1##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT2##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT3##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT4##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT5##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_RX_LOS); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_RX_LOS); +#define DECLARE_RX_LOS_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_rx_los.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_rx_los.dev_attr.attr, +DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_RX_LOS_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT1##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT2##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT3##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT4##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT5##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT6##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT7##_TX_DISABLE); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, PORT##PORT8##_TX_DISABLE); +#define DECLARE_TX_DISABLE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_disable.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_disable.dev_attr.attr, +DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_TX_DISABLE_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + +#define DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) \ + static SENSOR_DEVICE_ATTR(sfp##PORT1##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT1##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT2##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT2##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT3##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT3##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT4##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT4##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT5##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT5##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT6##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT6##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT7##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT7##_TX_FAULT); \ + static SENSOR_DEVICE_ATTR(sfp##PORT8##_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, PORT##PORT8##_TX_FAULT); +#define DECLARE_TX_FAULT_ATTR(PORT1, PORT2, PORT3, PORT4, PORT5, PORT6, PORT7, PORT8) &sensor_dev_attr_sfp##PORT1##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT2##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT3##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT4##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT5##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT6##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT7##_tx_fault.dev_attr.attr, \ + &sensor_dev_attr_sfp##PORT8##_tx_fault.dev_attr.attr, +DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) +DECLARE_TX_FAULT_SENSOR_DEVICE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) +static struct attribute *sfp_ddm_attributes[] = { + DECLARE_RX_LOS_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_RX_LOS_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_TX_DISABLE_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_DISABLE_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + DECLARE_TX_FAULT_ATTR(1, 2, 3, 4, 5, 6, 7, 8) + DECLARE_TX_FAULT_ATTR(9, 10, 11, 12, 13, 14, 15, 16) + NULL +}; + +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return data_len; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_write_byte_data(client, command, *data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return 1; +#endif + + +} + + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", (int)off, (int)count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + /* result = data_len; */ + +abort: + return result; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_read_byte_data(client, command); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); + goto abort; + } + + *data = (u8)result; + result = 1; + +abort: + return result; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", (int)off, (int)count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + dev_info(&client->dev, "sfp msa '%s' (sfp_sysfs_eeprom_init fail...)\n", client->name); + /* goto exit_remove; */ + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +/* exit_remove: */ + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)){ + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + } + + if (client->addr == SFP_EEPROM_A0_I2C_ADDR){ + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + } + + /* Bring QSFPs out of reset */ + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + DEBUG_PRINT("data->port:%d client->addr:0x%0x\n", data->port, client->addr); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)){ + if(data->port >= SFPPLUS_1_PORT_NUMBER){ + if(client->addr != SFP_PCA9506_I2C_ADDR){ + DEBUG_PRINT("client->addr:0x%0x\n", client->addr); + return -ENODEV; + } + } + else if(client->addr != SFP_CPLD_I2C_ADDR){ + DEBUG_PRINT("client->addr:0x%0x\n", client->addr); + return -ENODEV; + } + } + + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); +} + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)) + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)) + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + if ((client->addr == SFP_CPLD_I2C_ADDR) || (client->addr == SFP_PCA9506_I2C_ADDR)) + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Philip Wang "); +MODULE_DESCRIPTION("alphanetworks snh60b0-640f driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_onie_eeprom.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_onie_eeprom.c new file mode 100644 index 000000000000..f259abdca8fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_onie_eeprom.c @@ -0,0 +1,268 @@ +/* + * A driver for snh60b0-640f onie eeprom + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 3 of the License, or + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EEPROM_SIZE 256 + +#define SYS_LED_REG 0x8 +#define FAN12_LED_REG 0x9 +#define FAN34_LED_REG 0xA +#define FAN56_LED_REG 0xB +#define SYS_RESET1_REG 0x2 + +#define SYS_LOCATOR_LED_BITS 0x01 +#define SYS_PWR_LED_BITS 0x0E +#define SYS_STATUS_LED_BITS 0x70 +#define FAN135_LED_BITS 0x07 +#define FAN246_LED_BITS 0x38 + + +extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t onie_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t onie_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for snh60b0-640f_onie_eeprom */ +static const unsigned short normal_i2c[] = { 0x56, I2C_CLIENT_END }; + + +enum sysfs_onie_attributes { + ONIE_RW, +}; + +static SENSOR_DEVICE_ATTR(eeprom, (0660), onie_read, onie_write, ONIE_RW); + +static struct attribute *snh60b0_onie_attributes[] = { + &sensor_dev_attr_eeprom.dev_attr.attr, + NULL +}; + +static const struct attribute_group snh60b0_onie_group = { + .attrs = snh60b0_onie_attributes, +}; + + +static ssize_t onie_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + __u8 read_write; + unsigned short offset = 0; + union i2c_smbus_data temp; + char rbuf[EEPROM_SIZE]; + + for( offset=0 ; offset < EEPROM_SIZE ; ++offset ) + { + read_write = I2C_SMBUS_WRITE; + offset = offset & 0x3fff; + temp.byte = (u8)offset; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 2, &temp); + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 2, &temp); + + read_write = I2C_SMBUS_READ; + temp.byte = 0xaa; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 1, &temp); + if (!res) + { + res = temp.byte; + rbuf[offset] = (char)temp.byte; + } + + read_write = I2C_SMBUS_READ; + temp.byte = 0xbb; + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags=0, + read_write, 0, 1, &temp); + if (!res) + { + res = temp.byte; + } + } + + memcpy(buf, rbuf, EEPROM_SIZE); + return EEPROM_SIZE; +} + +static ssize_t onie_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int error, write, command, read; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + if (write < 0 || write > 255) + return -EINVAL; + + /* Not support yet */ + + return count; +} + + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int onie_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &snh60b0_onie_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int onie_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &snh60b0_onie_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id onie_eeprom_id[] = { + { "snh60b0_onie_eeprom", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, onie_eeprom_id); + +static struct i2c_driver onie_eeprom_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60b0_onie_eeprom", + }, + .probe = onie_eeprom_probe, + .remove = onie_eeprom_remove, + .id_table = onie_eeprom_id, + .address_list = normal_i2c, +}; + + +static int __init onie_eeprom_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&onie_eeprom_driver); +} + +static void __exit onie_eeprom_exit(void) + +{ + i2c_del_driver(&onie_eeprom_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("onie eeprom driver"); +MODULE_LICENSE("GPL"); + +module_init(onie_eeprom_init); +module_exit(onie_eeprom_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_power_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_power_cpld.c new file mode 100644 index 000000000000..00b8779ad50c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_power_cpld.c @@ -0,0 +1,501 @@ +/* + * A hwmon driver for the snh60b0-640f_power_cpld + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 3 of the License, or + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRIVER_NAME "snh60b0_power_cpld" +#define PSU1_STATUS_REG 0x3 +#define PSU2_STATUS_REG 0x4 +#define FAN_PWM_REG 0x23 + +#define PSU_PRESENT_BIT 0x4 +#define PSU_POWER_BIT 0x2 +#define FAN_PRESENT_BIT 0x2 + + +static ssize_t psu_show_status(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t fan_pwm_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +static ssize_t fan_show_status(struct device *dev, struct device_attribute *attr, char *buf); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for snh60b0-640f_power_cpld */ +static const unsigned short normal_i2c[] = { 0x5E, I2C_CLIENT_END }; + +struct snh60b0_pwr_cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; + char model_name[9]; /* Model name, read from eeprom */ +}; + + +enum sysfs_psu_attributes { + PSU1_PRESENT, + PSU2_PRESENT, + PSU1_POWER_GOOD, + PSU2_POWER_GOOD, + FAN_PWM, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + /* FAN5_FAULT, */ + /* FAN6_FAULT, */ + FAN1_PRESENT=0x12, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + /* FAN5_PRESENT, */ + /* FAN6_PRESENT, */ + FAN1_FRONT_SPEED_RPM=0x1A, + FAN1_REAR_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + /* FAN5_FRONT_SPEED_RPM, */ + /* FAN5_REAR_SPEED_RPM, */ + /* FAN6_FRONT_SPEED_RPM, */ + /* FAN6_REAR_SPEED_RPM, */ +}; + +static SENSOR_DEVICE_ATTR(psu1_present, S_IRUGO, psu_show_status, NULL, PSU1_PRESENT); +static SENSOR_DEVICE_ATTR(psu2_present, S_IRUGO, psu_show_status, NULL, PSU2_PRESENT); +static SENSOR_DEVICE_ATTR(psu1_power_good, S_IRUGO, psu_show_status, NULL, PSU1_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu2_power_good, S_IRUGO, psu_show_status, NULL, PSU2_POWER_GOOD); +static SENSOR_DEVICE_ATTR(fan_pwm, (0660), fan_pwm_show, set_fan_pwm, FAN_PWM); +static SENSOR_DEVICE_ATTR(fan1_present, S_IRUGO, fan_show_status, NULL, FAN1_PRESENT); +static SENSOR_DEVICE_ATTR(fan2_present, S_IRUGO, fan_show_status, NULL, FAN2_PRESENT); +static SENSOR_DEVICE_ATTR(fan3_present, S_IRUGO, fan_show_status, NULL, FAN3_PRESENT); +static SENSOR_DEVICE_ATTR(fan4_present, S_IRUGO, fan_show_status, NULL, FAN4_PRESENT); +/* static SENSOR_DEVICE_ATTR(fan5_present, S_IRUGO, fan_show_status, NULL, FAN5_PRESENT); */ +/* static SENSOR_DEVICE_ATTR(fan6_present, S_IRUGO, fan_show_status, NULL, FAN6_PRESENT); */ +static SENSOR_DEVICE_ATTR(fan1_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN1_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN2_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN3_FRONT_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN4_FRONT_SPEED_RPM); +/* static SENSOR_DEVICE_ATTR(fan5_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN5_FRONT_SPEED_RPM); */ +/* static SENSOR_DEVICE_ATTR(fan6_front_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN6_FRONT_SPEED_RPM); */ +static SENSOR_DEVICE_ATTR(fan1_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN1_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN2_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN3_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN4_REAR_SPEED_RPM); +/* static SENSOR_DEVICE_ATTR(fan5_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN5_REAR_SPEED_RPM); */ +/* static SENSOR_DEVICE_ATTR(fan6_rear_speed_rpm, S_IRUGO, fan_show_status, NULL, FAN6_REAR_SPEED_RPM); */ +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, fan_show_status, NULL, FAN1_FAULT); static SENSOR_DEVICE_ATTR(fan11_fault, S_IRUGO, fan_show_status, NULL, FAN1_FAULT); +static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, fan_show_status, NULL, FAN2_FAULT); static SENSOR_DEVICE_ATTR(fan12_fault, S_IRUGO, fan_show_status, NULL, FAN2_FAULT); +static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, fan_show_status, NULL, FAN3_FAULT); static SENSOR_DEVICE_ATTR(fan13_fault, S_IRUGO, fan_show_status, NULL, FAN3_FAULT); +static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, fan_show_status, NULL, FAN4_FAULT); static SENSOR_DEVICE_ATTR(fan14_fault, S_IRUGO, fan_show_status, NULL, FAN4_FAULT); +/* static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, fan_show_status, NULL, FAN5_FAULT); static SENSOR_DEVICE_ATTR(fan15_fault, S_IRUGO, fan_show_status, NULL, FAN5_FAULT); */ +/* static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, fan_show_status, NULL, FAN6_FAULT); static SENSOR_DEVICE_ATTR(fan16_fault, S_IRUGO, fan_show_status, NULL, FAN6_FAULT); */ +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, fan_show_status, NULL, FAN1_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, fan_show_status, NULL, FAN1_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, fan_show_status, NULL, FAN2_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, fan_show_status, NULL, FAN2_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, fan_show_status, NULL, FAN3_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan13_input, S_IRUGO, fan_show_status, NULL, FAN3_REAR_SPEED_RPM); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, fan_show_status, NULL, FAN4_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan14_input, S_IRUGO, fan_show_status, NULL, FAN4_REAR_SPEED_RPM); +/* static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, fan_show_status, NULL, FAN5_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan15_input, S_IRUGO, fan_show_status, NULL, FAN5_REAR_SPEED_RPM); */ +/* static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, fan_show_status, NULL, FAN6_FRONT_SPEED_RPM); static SENSOR_DEVICE_ATTR(fan16_input, S_IRUGO, fan_show_status, NULL, FAN6_REAR_SPEED_RPM); */ + + +static struct attribute *snh60b0_psu_attributes[] = { + &sensor_dev_attr_psu1_present.dev_attr.attr, + &sensor_dev_attr_psu2_present.dev_attr.attr, + &sensor_dev_attr_psu1_power_good.dev_attr.attr, + &sensor_dev_attr_psu2_power_good.dev_attr.attr, + &sensor_dev_attr_fan_pwm.dev_attr.attr, + &sensor_dev_attr_fan1_present.dev_attr.attr, + &sensor_dev_attr_fan2_present.dev_attr.attr, + &sensor_dev_attr_fan3_present.dev_attr.attr, + &sensor_dev_attr_fan4_present.dev_attr.attr, + /* &sensor_dev_attr_fan5_present.dev_attr.attr, */ + /* &sensor_dev_attr_fan6_present.dev_attr.attr, */ + &sensor_dev_attr_fan1_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_front_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_front_speed_rpm.dev_attr.attr, + /* &sensor_dev_attr_fan5_front_speed_rpm.dev_attr.attr, */ + /* &sensor_dev_attr_fan6_front_speed_rpm.dev_attr.attr, */ + &sensor_dev_attr_fan1_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_rear_speed_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_rear_speed_rpm.dev_attr.attr, + /* &sensor_dev_attr_fan5_rear_speed_rpm.dev_attr.attr, */ + /* &sensor_dev_attr_fan6_rear_speed_rpm.dev_attr.attr, */ + &sensor_dev_attr_fan1_fault.dev_attr.attr, &sensor_dev_attr_fan11_fault.dev_attr.attr, + &sensor_dev_attr_fan2_fault.dev_attr.attr, &sensor_dev_attr_fan12_fault.dev_attr.attr, + &sensor_dev_attr_fan3_fault.dev_attr.attr, &sensor_dev_attr_fan13_fault.dev_attr.attr, + &sensor_dev_attr_fan4_fault.dev_attr.attr, &sensor_dev_attr_fan14_fault.dev_attr.attr, + /* &sensor_dev_attr_fan5_fault.dev_attr.attr, &sensor_dev_attr_fan15_fault.dev_attr.attr, */ + /* &sensor_dev_attr_fan6_fault.dev_attr.attr, &sensor_dev_attr_fan16_fault.dev_attr.attr, */ + &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan11_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan12_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan13_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, &sensor_dev_attr_fan14_input.dev_attr.attr, + /* &sensor_dev_attr_fan5_input.dev_attr.attr, &sensor_dev_attr_fan15_input.dev_attr.attr, */ + /* &sensor_dev_attr_fan6_input.dev_attr.attr, &sensor_dev_attr_fan16_input.dev_attr.attr, */ + NULL +}; + +static const struct attribute_group snh60b0_psu_group = { + .attrs = snh60b0_psu_attributes, +}; + + +static ssize_t psu_show_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case PSU1_PRESENT: + case PSU1_POWER_GOOD: + command = PSU1_STATUS_REG; + break; + case PSU2_PRESENT: + case PSU2_POWER_GOOD: + command = PSU2_STATUS_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + res = (val & PSU_PRESENT_BIT ? 1 : 0 ); + break; + case PSU1_POWER_GOOD: + case PSU2_POWER_GOOD: + res = (val & PSU_POWER_BIT ? 1 : 0 ); + break; + } + + return sprintf(buf, "%d\n", res); +} + +static ssize_t fan_pwm_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, FAN_PWM_REG); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > 0xFF) + return -EINVAL; + + i2c_smbus_write_byte_data(client, FAN_PWM_REG, value); + + return count; +} + +static ssize_t fan_show_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + // struct as7712_32x_fan_data *data = as7712_32x_fan_update_device(dev); + ssize_t ret = 0; + int val, val2; + + switch (sda->index) { + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + /* case FAN5_FRONT_SPEED_RPM: */ + /* case FAN6_FRONT_SPEED_RPM: */ + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + /* case FAN5_REAR_SPEED_RPM: */ + /* case FAN6_REAR_SPEED_RPM: */ + val = i2c_smbus_read_byte_data(client, sda->index); + ret = sprintf(buf, "%d\n", val * 150); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + /* case FAN5_PRESENT: */ + /* case FAN6_PRESENT: */ + val = i2c_smbus_read_byte_data(client, sda->index); + ret = sprintf(buf, "%d\n", (val & FAN_PRESENT_BIT) ? 1 : 0); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + /* case FAN5_FAULT: */ + /* case FAN6_FAULT: */ + val = i2c_smbus_read_byte_data(client, (sda->index - FAN1_FAULT)*2 + FAN1_FRONT_SPEED_RPM); + val2 = i2c_smbus_read_byte_data(client, (sda->index - FAN1_FAULT)*2 + FAN1_REAR_SPEED_RPM); + ret = sprintf(buf, "%d\n", (val|val2) ? 0 : 1); + break; + default: + break; + } + + return ret; +} + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int alpha_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct snh60b0_pwr_cpld_data* data; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct snh60b0_pwr_cpld_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &snh60b0_psu_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit; + } + + dev_info(&client->dev, "%s: pwr_cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_cpld_remove(struct i2c_client *client) +{ + struct snh60b0_pwr_cpld_data *data = i2c_get_clientdata(client); + sysfs_remove_group(&client->dev.kobj, &snh60b0_psu_group); + alpha_i2c_cpld_remove_client(client); + kfree(data); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { DRIVER_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRIVER_NAME, + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + +int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_read); + +int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(alpha_i2c_cpld_write); + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + +static struct dmi_system_id snh60b0_dmi_table[] = { + { + .ident = "Alpha snh60b0-640f", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alpha"), + DMI_MATCH(DMI_PRODUCT_NAME, "snh60b0-640f"), + }, + } +}; + +int platform_alpha_snh60b0(void) +{ + return dmi_check_system(snh60b0_dmi_table); +} +EXPORT_SYMBOL(platform_alpha_snh60b0); + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_power_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_system_cpld.c b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_system_cpld.c new file mode 100644 index 000000000000..ddba09370ca2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/modules/snh60b0-640f_system_cpld.c @@ -0,0 +1,365 @@ +/* + * A hwmon driver for the snh60b0-640f_system_cpld + * + * Copyright (C) 2018 Alphanetworks Technology Corporation. + * Robin Chen + * 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 3 of the License, or + * 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. + * see + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SYS_LED_REG 0x8 +#define FAN12_LED_REG 0x9 +#define FAN34_LED_REG 0xA +#define SYS_RESET1_REG 0x2 +#define SWI_CTRL_REG 0x4 + +#define SYS_LOCATOR_LED_BITS 0x01 +#define SYS_PWR_LED_BITS 0x0E +#define SYS_STATUS_LED_BITS 0x70 +#define FAN135_LED_BITS 0x07 +#define FAN246_LED_BITS 0x38 +#define REST_BUTTON_BITS 0x0 + + +extern int alpha_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int alpha_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t sys_led_read(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t sys_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for snh60b0-640f_system_cpld */ +static const unsigned short normal_i2c[] = { 0x5F, I2C_CLIENT_END }; + + +enum sysfs_sys_attributes { + SYS_LOCATOR, + SYS_PWR, + SYS_STATUS, + FAN1_LED, + FAN2_LED, + FAN3_LED, + FAN4_LED, + SYS_REST1, + SWI_CTRL, +}; + +static SENSOR_DEVICE_ATTR(sys_locator, (0660), sys_led_read, sys_led_write, SYS_LOCATOR); +static SENSOR_DEVICE_ATTR(sys_pwr, (0660), sys_led_read, sys_led_write, SYS_PWR); +static SENSOR_DEVICE_ATTR(sys_status, (0600), sys_led_read, sys_led_write, SYS_STATUS); +static SENSOR_DEVICE_ATTR(fan1_led, (0660), sys_led_read, sys_led_write, FAN1_LED); +static SENSOR_DEVICE_ATTR(fan2_led, (0660), sys_led_read, sys_led_write, FAN2_LED); +static SENSOR_DEVICE_ATTR(fan3_led, (0660), sys_led_read, sys_led_write, FAN3_LED); +static SENSOR_DEVICE_ATTR(fan4_led, (0660), sys_led_read, sys_led_write, FAN4_LED); +static SENSOR_DEVICE_ATTR(sys_reset1, (0660), sys_led_read, sys_led_write, SYS_REST1); +static SENSOR_DEVICE_ATTR(swi_ctrl, (0660), sys_led_read, NULL, SWI_CTRL); + +static struct attribute *snh60b0_sys_attributes[] = { + &sensor_dev_attr_sys_locator.dev_attr.attr, + &sensor_dev_attr_sys_pwr.dev_attr.attr, + &sensor_dev_attr_sys_status.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &sensor_dev_attr_fan3_led.dev_attr.attr, + &sensor_dev_attr_fan4_led.dev_attr.attr, + &sensor_dev_attr_sys_reset1.dev_attr.attr, + &sensor_dev_attr_swi_ctrl.dev_attr.attr, + NULL +}; + +static const struct attribute_group snh60b0_sys_group = { + .attrs = snh60b0_sys_attributes, +}; + + +static ssize_t sys_led_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0, res = 0; + u8 command; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + + switch(sda->index) { + case SYS_LOCATOR: + case SYS_PWR: + case SYS_STATUS: + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + command = SYS_RESET1_REG; + break; + case SWI_CTRL: + command = SWI_CTRL_REG; + break; + } + + val = i2c_smbus_read_byte_data(client, command); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + switch(sda->index) { + case SYS_LOCATOR: + res = (val & SYS_LOCATOR_LED_BITS) >> 0; + break; + case SYS_PWR: + res = (val & SYS_PWR_LED_BITS) >> 1; + break; + case SYS_STATUS: + res = (val & SYS_STATUS_LED_BITS) >> 4; + break; + case FAN1_LED: + case FAN3_LED: + res = (val & FAN135_LED_BITS) >> 0; + break; + case FAN2_LED: + case FAN4_LED: + res = (val & FAN246_LED_BITS) >> 3; + break; + case SYS_REST1: + res = val; + break; + case SWI_CTRL: + res = (val & REST_BUTTON_BITS) >> 0; + break; + } + + return sprintf(buf, "%d\n", res); +} + +static ssize_t sys_led_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + int error, write, command, read; + + error = kstrtoint(buf, 10, &write); + if (error) + return error; + + + switch(sda->index) { + case SYS_LOCATOR: + if(write < 0 || write > 2) + return -EINVAL; + case SYS_PWR: + case SYS_STATUS: + if (write < 0 || write > 7) + return -EINVAL; + command = SYS_LED_REG; + break; + case FAN1_LED: + case FAN2_LED: + case FAN3_LED: + case FAN4_LED: + if (write < 0 || write > 7) + return -EINVAL; + command = FAN12_LED_REG + (sda->index - FAN1_LED)/2; + break; + case SYS_REST1: + if (write < 0 || write > 15) + return -EINVAL; + command = SYS_RESET1_REG; + break; + } + + read = i2c_smbus_read_byte_data(client, command); + if (read < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, read); + } + + switch(sda->index) { + case SYS_LOCATOR: + read &= ~SYS_LOCATOR_LED_BITS; + read |= write << 0; + break; + case SYS_PWR: + read &= ~SYS_PWR_LED_BITS; + read |= write << 1; + break; + case SYS_STATUS: + read &= ~SYS_STATUS_LED_BITS; + read |= write << 4; + break; + case FAN1_LED: + case FAN3_LED: + read &= ~FAN135_LED_BITS; + read |= write << 0; + break; + case FAN2_LED: + case FAN4_LED: + read &= ~FAN246_LED_BITS; + read |= write << 3; + break; + case SYS_REST1: + read = write; + break; + } + + i2c_smbus_write_byte_data(client, command, read); + + return count; +} + + + +static void alpha_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void alpha_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int alpha_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_group(&client->dev.kobj, &snh60b0_sys_group); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + alpha_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int alpha_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &snh60b0_sys_group); + alpha_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id alpha_i2c_cpld_id[] = { + { "snh60b0_system_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, alpha_i2c_cpld_id); + +static struct i2c_driver alpha_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "snh60b0_system_cpld", + }, + .probe = alpha_i2c_cpld_probe, + .remove = alpha_i2c_cpld_remove, + .id_table = alpha_i2c_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init alpha_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&alpha_i2c_cpld_driver); +} + +static void __exit alpha_i2c_cpld_exit(void) +{ + i2c_del_driver(&alpha_i2c_cpld_driver); +} + + +MODULE_AUTHOR("Alpha-SID6"); +MODULE_DESCRIPTION("alpha_system_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(alpha_i2c_cpld_init); +module_exit(alpha_i2c_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/service/snh60b0-platform-init.service b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/service/snh60b0-platform-init.service new file mode 100644 index 000000000000..fa2e849c7c34 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/service/snh60b0-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Alphanetworks SNH60B0-640F Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/alphanetworks_snh60b0_util.py -f install +ExecStop=/usr/local/bin/alphanetworks_snh60b0_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/setup.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/setup.py new file mode 100644 index 000000000000..785a36660182 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='snh60b0_640f', + version='1.0', + description='Module to initialize Alphanetworks SNH60B0-640F platforms', + + packages=['snh60b0_640f'], + package_dir={'snh60b0_640f': 'snh60b0-640f/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py new file mode 100755 index 000000000000..4b64a2e12a1f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/snh60b0-640f/utils/alphanetworks_snh60b0_util.py @@ -0,0 +1,427 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Alphanetworks Technology Corporation. +# Robin Chen +# 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 3 of the License, or +# 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. +# see +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'snh60b0-640f' +device_path = "x86_64-alphanetworks_snh60b0_640f-r0" +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +FORCE = 0 + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print PROJECT_NAME.upper()+": "+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +" with result: " + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep alphanetworks", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x', +'modprobe optoe' , +'modprobe snh60b0-640f_power_cpld' , +'modprobe snh60b0-640f_system_cpld' , +'modprobe snh60b0-640f_onie_eeprom' , +'modprobe alphanetworks_snh60b0_640f_sfp' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + if kos[i].find('pca954') != -1: + status, output = log_os_system(kos[i]+ " force_deselect_on_exit=1", 1) + else: + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +i2c_prefix = '/sys/bus/i2c/devices/' + +sfp_map = [13,14,15,16,23] +mknod =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo snh60b0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60b0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-0/new_device', +'echo snh60b0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-8/new_device', +'echo lm75 0x4D > /sys/bus/i2c/devices/i2c-3/new_device', +'echo lm75 0x4C > /sys/bus/i2c/devices/i2c-4/new_device', +'echo lm75 0x4F > /sys/bus/i2c/devices/i2c-0/new_device' ] + +mknod2 =[ +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-8/new_device', +'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-11/new_device', +'echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-12/new_device', +'echo snh60b0_onie_eeprom 0x56 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60b0_power_cpld 0x5e > /sys/bus/i2c/devices/i2c-1/new_device', +'echo snh60b0_system_cpld 0x5f > /sys/bus/i2c/devices/i2c-9/new_device', +'echo lm75 0x4D > /sys/bus/i2c/devices/i2c-4/new_device', +'echo lm75 0x4C > /sys/bus/i2c/devices/i2c-5/new_device', +'echo lm75 0x4F > /sys/bus/i2c/devices/i2c-1/new_device' ] + + +def i2c_order_check(): + # i2c bus 0 and 1 might be installed in different order. + # Here check if 0x76 is exist @ i2c-0 + tmp = "echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device" + status, output = log_os_system(tmp, 0) + if not device_exist(): + order = 1 + tmp = "sed -i 's/0-/1-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + status, output = log_os_system(tmp, 0) + else: + order = 0 + tmp = "sed -i 's/1-/0-/g' /usr/share/sonic/device/"+device_path+"/fancontrol" + status, output = log_os_system(tmp, 0) + tmp = "echo 0x70 > /sys/bus/i2c/devices/i2c-0/delete_device" + status, output = log_os_system(tmp, 0) + return order + +def device_install(): + global FORCE + + order = i2c_order_check() + + # if 0x76 is not exist @i2c-0, use reversed bus order + if order: + for i in range(0,len(mknod2)): + #for pca954x need times to built new i2c buses + if mknod2[i].find('pca954') != -1: + time.sleep(1) + + if mknod2[i].find('lm75') != -1: + time.sleep(1) + + status, output = log_os_system(mknod2[i], 1) + if status: + print output + if FORCE == 0: + return status + else: + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + if mknod[i].find('lm75') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + status, output =log_os_system("echo 0 > /sys/bus/i2c/devices/8-005f/sys_reset1", 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0, 66): + index = i / 16 + port = i % 16 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + if i == 64: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x20 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + if i < 64: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x5f > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + if i == 64: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-21/new_device", 1) + if status: + print output + if FORCE == 0: + return status + if i == 65: + status, output =log_os_system("echo sfpcpld"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-22/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0070", 0) + if status==0: + I2C_ORDER=1 + else: + I2C_ORDER=0 + + for i in range(0, 66): + index = i / 16 + port = i % 16 + reg_sfp = 0 + if port == 0: + reg_sfp = 1 + + if reg_sfp == 1: + if i == 64: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x20 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + if i < 64: + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x5f > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[index])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + if i == 64: + status, output =log_os_system("echo 0x50 > /sys/bus/i2c/devices/i2c-21/delete_device", 1) + if status: + print output + if FORCE == 0: + return status + if i == 65: + status, output =log_os_system("echo 0x50 > /sys/bus/i2c/devices/i2c-22/delete_device", 1) + if status: + print output + if FORCE == 0: + return status + if I2C_ORDER==0: + nodelist = mknod + else: + nodelist = mknod2 + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + tmp = "find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol | xargs cat | sed '429d' | sed '428a if \[ $? -ne 1 \]' | sed '425d' | sed '424a return' > /tmp/tmp_fancontrol" + status, output = log_os_system(tmp, 1) + tmp = "fancontrol_tmp=`find /var/lib/docker/overlay -iname fancontrol | grep usr/sbin/fancontrol` ; cp /tmp/tmp_fancontrol $fancontrol_tmp" + status, output = log_os_system(tmp, 1) + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0070", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-arista b/platform/broadcom/sonic-platform-modules-arista new file mode 160000 index 000000000000..86f7b81834a1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-arista @@ -0,0 +1 @@ +Subproject commit 86f7b81834a1093d1df644b09232ddacb40784ef diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/Makefile b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/Makefile new file mode 100644 index 000000000000..3f93a0bfe52a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/Makefile @@ -0,0 +1,14 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + +MAIN_TARGET = $(BRCM_XLR_GTS_PLATFORM_MODULE) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Build the package + export PYBUILD_INSTALL_ARGS_python2=--install-scripts=/dev/null + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + + mv $(addprefix ../, $* $(EXTRA_TARGETS)) $(DEST)/ + +$(addprefix $(DEST)/, $(EXTRA_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/confs/sonic-platform-brcm-xlr-gts.service b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/confs/sonic-platform-brcm-xlr-gts.service new file mode 100644 index 000000000000..55ceca0e0193 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/confs/sonic-platform-brcm-xlr-gts.service @@ -0,0 +1,11 @@ +[Unit] +Description=Broadcom XLR/GTS platform setup +Before=systemd-logind docker.service + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/brcm-xlr-gts-platform-setup + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/changelog b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/changelog new file mode 100755 index 000000000000..3168c7c4d691 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/changelog @@ -0,0 +1,5 @@ +sonic-platform-brcm-xlr-gts (1.0) unstable; + + * Initial release + + -- Olivier Singla Thursday, 14 Feb 2019 11:11:11 -0800 diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/compat b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/compat new file mode 100755 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/control b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/control new file mode 100755 index 000000000000..a046edb6930d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/control @@ -0,0 +1,27 @@ +Source: sonic-platform-brcm-xlr-gts +Section: main +Priority: extra +Maintainer: Olivier Singla +Build-Depends: + dh-python, + debhelper (>= 9.0.0), + python-all, + python(>=2.7-3~), + python-setuptools, + python3(>=3.2), + python3-setuptools, + bzip2 +Standards-Version: 1.0.0 +X-Python-Version: >= 2.7 +X-Python3-Version: >= 3.2 +XS-Python-Version: >= 2.7 +XS-Python3-Version: >= 3.2 + +Package: sonic-platform-brcm-xlr-gts +Architecture: amd64 +Depends: + ${python:Depends}, + ${misc:Depends}, + python(>=2.7), + i2c-tools +Description: Miscellaneous XLR scripts and tools diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/copyright b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/copyright new file mode 100644 index 000000000000..ebdb940a0c98 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/copyright @@ -0,0 +1,1016 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + + 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + + + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/rules b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/rules new file mode 100755 index 000000000000..9c680102251a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/debian/rules @@ -0,0 +1,31 @@ +#!/usr/bin/make -f + +include /usr/share/dpkg/pkg-info.mk + +BIN_FILES := brcm-xlr-gts-platform-setup brcm-xlr-gts-create-eeprom-file.py +RULE_FILES := +SERVICE_FILES := sonic-platform-brcm-xlr-gts.service +USR_SBIN_FILES := brcm-xlr-gts-platform-setup brcm-xlr-gts-create-eeprom-file.py + +BASE_DIR := $(shell pwd) +MODULE_SRC := $(BASE_DIR)/src +TEST_DIR := $(BASE_DIR)/tests +BIN_SRC := $(addprefix $(BASE_DIR)/utils/,$(BIN_FILES)) +SERVICE_SRC := $(addprefix $(BASE_DIR)/confs/,$(SERVICE_FILES)) +USRLOCALSBIN_SRC := $(addprefix $(BASE_DIR)/utils/,$(USR_SBIN_FILES)) + +%: + dh $@ --with python2,python3,systemd --buildsystem=pybuild + +override_dh_auto_install: + dh_installdirs -p$(DEB_SOURCE) lib/systemd/system + cp $(SERVICE_SRC) debian/$(DEB_SOURCE)/lib/systemd/system + dh_installdirs -p$(DEB_SOURCE) usr/bin + cp $(BIN_SRC) debian/$(DEB_SOURCE)/usr/bin + dh_systemd_enable sonic-platform-brcm-xlr-gts.service + +override_dh_clean: + dh_clean + +print-%: + @echo $($*) diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/setup.py b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/setup.py new file mode 100755 index 000000000000..6ade72b8163d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/setup.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +from setuptools import setup +import os + +setup( + name='platform-xlr-gts', + version='%s' % os.environ.get('BRCM_XLR_GTS_PLATFORM_MODULE_VERSION', '1.0'), + description='Module to initialize Broadcom XLR/GTS platforms', + packages=[], +) + diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/src/Makefile b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/src/Makefile new file mode 100644 index 000000000000..fc16fbbfdbff --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/src/Makefile @@ -0,0 +1,13 @@ +ccflags-y := -Werror + +#ifeq ($(ARISTA_SCD_DRIVER_CONFIG),m) +#obj-$(ARISTA_SCD_DRIVER_CONFIG) += scd.o +#else +#KBUILD_EXTRA_SYMBOLS += $(EXTRA_SYMBOLS) +#endif + +#obj-m += scd-hwmon.o +#obj-m += crow-fan-driver.o +#obj-m += raven-fan-driver.o +#obj-m += rook-led-driver.o +#obj-m += rook-fan-cpld.o diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/src/modules.order b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/src/modules.order new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/tests/all-platforms.sh b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/tests/all-platforms.sh new file mode 100755 index 000000000000..ce5c7b145cb9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/tests/all-platforms.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# +# This script provides a simple helper to test if the initscripts for all +# platforms work. +# It runs in simulation mode and don't actually initialize anything but still +# checks most of the codepaths +# + +echo "Nothing to do!" diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/utils/brcm-xlr-gts-create-eeprom-file.py b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/utils/brcm-xlr-gts-create-eeprom-file.py new file mode 100755 index 000000000000..d8e7ec0ee138 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/utils/brcm-xlr-gts-create-eeprom-file.py @@ -0,0 +1,105 @@ +#!/usr/bin/python + +# Since the XLR/GTS cards do not have an EEPROM, we create a file which +# will be use like an EEPROM. + +import sys +import struct +from ctypes import * +import os + +TLV_CODE_PRODUCT_NAME = 0x21 +TLV_CODE_SERIAL_NUMBER = 0x23 +TLV_CODE_MAC_BASE = 0x24 +TLV_CODE_PLATFORM_NAME = 0x28 +TLV_CODE_ONIE_VERSION = 0x29 +TLV_CODE_MANUF_NAME = 0x2B +TLV_CODE_CRC_32 = 0xFE + +def getmac(interface): + try: + mac = open('/sys/class/net/'+interface+'/address').readline() + except: + mac = "00:00:00:00:00:00" + return mac[0:17] + +class TLVINFO_HEADER(Structure): + _fields_ = [("signature", c_char*8), + ("version", c_ubyte), + ("totallen", c_ushort)] + def dump(self): + return struct.pack('8s', self.signature) + \ + struct.pack('B', self.version) + \ + struct.pack('>H', self.totallen) + +class TLVINFO_DATA: + data = []; + def add_tlv_str(self, type, value): + self.data.append(struct.pack('B', type) + struct.pack('B', len(value)) + value.encode()) + def add_tlv_mac(self, type, value): + self.data.append(struct.pack('B', type) + struct.pack('B', len(value))) + for v in value: + self.data.append(struct.pack('B', int(v, 16))) + def dump(self): + r = ''; + for m in self.data: + r += bytes(m) + return r + struct.pack('B', TLV_CODE_CRC_32) + struct.pack('B', 4) + +def crc32(crc, p, len): + crc = 0xffffffff & ~crc + for i in range(len): + crc = crc ^ p[i] + for j in range(8): + crc = (crc >> 1) ^ (0xedb88320 & -(crc & 1)) + return 0xffffffff & ~crc + +def crc(header, data): + r = ''; + for m in header: + r += bytes(m) + for m in data: + r += bytes(m) + c = crc32(0, bytearray(r), len(r)) + s = struct.pack('>I', c) + return s + +def main(): + + tlvinfo_header = TLVINFO_HEADER('TlvInfo', 1, 0) + + tlvinfo_data = TLVINFO_DATA() + tlvinfo_data.add_tlv_str(TLV_CODE_SERIAL_NUMBER, 'S/N') + + onie_machine = os.popen("cat /host/machine.conf | grep 'onie_machine=' | sed 's/onie_machine=//'").read().strip() + if onie_machine == 'bcm_xlr': + tlvinfo_data.add_tlv_str(TLV_CODE_PRODUCT_NAME, 'BCM9COMX2XMC') + else: + tlvinfo_data.add_tlv_str(TLV_CODE_PRODUCT_NAME, 'Unknown') + + tlvinfo_data.add_tlv_str(TLV_CODE_MANUF_NAME, 'Broadcom') + + eth0_mac_str = getmac('eth0') + eth0_mac = eth0_mac_str.split(':') + tlvinfo_data.add_tlv_mac(TLV_CODE_MAC_BASE, eth0_mac) + + brcm_dev = os.popen("lspci | grep -m1 'Ethernet controller: Broadcom ' | grep 'Device' | sed 's/(.*//' | awk '{print $NF}'").read().strip() + if brcm_dev == 'b960': + tlvinfo_data.add_tlv_str(TLV_CODE_PLATFORM_NAME, 'BCM956960K') + + onie_version = os.popen("cat /host/machine.conf | grep 'onie_version' | sed 's/onie_version=//'").read().strip() + tlvinfo_data.add_tlv_str(TLV_CODE_ONIE_VERSION, onie_version) + + tlvinfo_header.totallen = len(tlvinfo_data.dump())+4; + + try: + f = open('/usr/share/sonic/device/x86_64-bcm_xlr-r0/sys_eeprom.bin', 'w+') + f.write(tlvinfo_header.dump()) + f.write(tlvinfo_data.dump()) + f.write(crc(tlvinfo_header.dump(), tlvinfo_data.dump())) + f.close() + except: + print('Unable to write file /usr/share/sonic/device/x86_64-bcm_xlr-r0/sys_eeprom.bin') + +if __name__== "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/utils/brcm-xlr-gts-platform-setup b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/utils/brcm-xlr-gts-platform-setup new file mode 100755 index 000000000000..1b5d20a5c948 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-brcm-xlr-gts/utils/brcm-xlr-gts-platform-setup @@ -0,0 +1,23 @@ +#!/bin/sh + +. /host/machine.conf + +# We boot SONiC from an XMC card : identify the switch at run-time and update the SKU +if [ "${onie_machine}" = "bcm_xlr" ]; then + grep "HandleLidSwitch=ignore" /etc/systemd/logind.conf > /dev/null + if [ ! $? = 0 ]; then + echo "HandleLidSwitch=ignore" >> /etc/systemd/logind.conf + echo "IdleAction=ignore" >> /etc/systemd/logind.conf + systemctl is-active --quiet systemd-logind + if [ $? = 0 ]; then + systemctl restart systemd-logind + fi + fi + /usr/bin/brcm-xlr-gts-create-eeprom-file.py + brcm_sw=$(lspci | grep -m1 "Ethernet controller: Broadcom " | grep "Device" | sed 's/(.*//' | awk '{print $NF}') + case "$brcm_sw" in + b960) + echo "BCM956960K t1" > /usr/share/sonic/device/${onie_platform}/default_sku + ;; + esac +fi diff --git a/platform/broadcom/sonic-platform-modules-cel/.gitignore b/platform/broadcom/sonic-platform-modules-cel/.gitignore new file mode 100644 index 000000000000..2490baa9d1e2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/.gitignore @@ -0,0 +1,59 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-cel/LICENSE b/platform/broadcom/sonic-platform-modules-cel/LICENSE new file mode 100644 index 000000000000..2386a3920c07 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2017 Celestica, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-cel/README.md b/platform/broadcom/sonic-platform-modules-cel/README.md new file mode 100644 index 000000000000..9881d6ecb1d0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/README.md @@ -0,0 +1 @@ +platform drivers of Celestica network switchs for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/changelog b/platform/broadcom/sonic-platform-modules-cel/debian/changelog new file mode 100644 index 000000000000..843b028e4301 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/changelog @@ -0,0 +1,57 @@ +sonic-cel-platform-modules (0.9) unstable; urgency=low + + * Add haliburton platform module. + + -- Wirut Getbamrung Fri, 17 Aug 2018 10:10:10 +0700 + +sonic-cel-platform-modules (0.8) unstable; urgency=low + + * Add dx010 platform fan led control. + * The platform gpio init moved to kernel space. + + -- Pradchaya Phucharoen Mon, 1 Jul 2018 11:09:13 +0700 + +sonic-cel-platform-modules (0.7) unstable; urgency=low + + * Add dx010 plaform gpio sysfs exported when module load. + + -- Pradchaya Phucharoen Wed, 21 Jun 2018 13:29:05 +0700 + +sonic-cel-platform-modules (0.6) unstable; urgency=low + + * Remove unused port-mode switch script. This should be done by hwsku config script. + * Add script to turn off QSFP low power mode when boot up. + + -- Pradchaya Phucharoen Wed, 26 July 2017 10:43:00 +0700 + +sonic-cel-platform-modules (0.5) unstable; urgency=low + + * Add port-mode switch script to support 100G 50G 10G_50G qsfp modes. + * Fix garbage data when using sfputil to read QSFP-transceiver's eeprom. + * Fix incorrect endian in eeprom read word data. + + -- Pradchaya Phucharoen Tue, 18 July 2017 11:30:00 +0700 + +sonic-cel-platform-modules (0.4) unstable; urgency=low + + * Add support for DX010's fancontrol, automatic run-up and FIX bug lpmod + + -- Pariwat Leamsumran Thu, 14 June 2017 16:25:00 +0700 + +sonic-cel-platform-modules (0.3) unstable; urgency=low + + * Add support for DX010's DPS800 + + -- Abhisit Sangjan Thu, 29 May 2017 19:23:00 +0700 + +sonic-cel-platform-modules (0.2) unstable; urgency=low + + * Add support for DX010's LM75B, Watchdog and EMC2305 + + -- Abhisit Sangjan Thu, 25 May 2017 15:26:00 +0700 + +sonic-cel-platform-modules (0.1) unstable; urgency=low + + * Initial release + + -- Abhisit Sangjan Mon, 2 May 2017 14:47:00 +0700 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/compat b/platform/broadcom/sonic-platform-modules-cel/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/control b/platform/broadcom/sonic-platform-modules-cel/debian/control new file mode 100644 index 000000000000..a41f92ab54e9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/control @@ -0,0 +1,27 @@ +Source: sonic-cel-platform-modules +Section: main +Priority: extra +Maintainer: Wirut Getbamrung +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-dx010 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + + +Package: platform-modules-haliburton +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-seastone2 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as led, sfp + +Package: platform-modules-silverstone +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as led, sfp. diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init new file mode 100644 index 000000000000..e27d4df46782 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.init @@ -0,0 +1,160 @@ +#!/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 DX010 board. +### END INIT INFO + +function export_gpio { +label=$3 +gpio_dir=$2 +gpio_num=$1 +gpio_base=`( cat /sys/class/gpio/gpiochip*/base | head -1 ) 2>/dev/null` +gpio_label=`( cat /sys/class/gpio/gpiochip*/label | head -1 ) 2>/dev/null` +if [[ "X$gpio_base" == "X" ]] || +( [[ "X$label" != "X" ]] && [[ "$label" != "$gpio_label" ]] ); then + echo "Platform driver error: No gpiochip found!" + exit 1; +fi +ionum=$((gpio_base+gpio_num)) +echo $ionum > /sys/class/gpio/export +if [ $? -ne 0 ]; then + echo "Platform driver error: Cannot export gpio$ionum!" + exit 1; +fi +if [[ "X$gpio_dir" != "X" ]]; then + echo $gpio_dir > /sys/class/gpio/gpio${ionum}/direction + if [ $? -ne 0 ]; then + echo "Platform driver error: Cannot set direction of gpio$ionum!" + exit 1; + fi +fi +} + +case "$1" in +start) + echo -n "Setting up board... " + + modprobe i2c-dev + modprobe i2c-mux-pca954x force-deselect-on-exit=1 + modprobe dx010_wdt + modprobe leds-dx010 + modprobe lm75 + modprobe slx_gpio_ich + + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find iSMT" && exit 1 + + i2cset -y ${devnum} 0x70 0x10 0x00 0x01 i + sleep 1 + + # Attach PCA9548 0x71 Channel Extender for Main Board + echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + sleep 1 + + # Attach PCA9548 0x73 Channel Extender for CPU Board + echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + sleep 1 + + # Attach PCA9548 0x77 Channel Extender for Fan's EEPROMs + echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + sleep 1 + + # Attach syseeprom + echo 24lc64t 0x50 > /sys/bus/i2c/devices/i2c-12/new_device + + # Attach temperature sensors + echo lm75b 0x48 > /sys/bus/i2c/devices/i2c-5/new_device + echo lm75b 0x49 > /sys/bus/i2c/devices/i2c-6/new_device + echo lm75b 0x4a > /sys/bus/i2c/devices/i2c-7/new_device + echo lm75b 0x48 > /sys/bus/i2c/devices/i2c-14/new_device + echo lm75b 0x4e > /sys/bus/i2c/devices/i2c-15/new_device + + # Attach fans + echo emc2305 0x2e > /sys/bus/i2c/devices/i2c-13/new_device + echo emc2305 0x4d > /sys/bus/i2c/devices/i2c-13/new_device + + # Attach PSUs + echo dps460 0x5a > /sys/bus/i2c/devices/i2c-10/new_device + echo dps460 0x5b > /sys/bus/i2c/devices/i2c-11/new_device + + # Attach PCA9506 GPIO expander for 40 pins + echo pca9505 0x20 > /sys/bus/i2c/devices/i2c-17/new_device + + modprobe dx010_cpld + sleep 2 + + # Export platform gpio sysfs + export_gpio 10 "in" # Fan 1 present + export_gpio 11 "in" # Fan 2 present + export_gpio 12 "in" # Fan 3 present + export_gpio 13 "in" # Fan 4 present + export_gpio 14 "in" # Fan 5 present + + export_gpio 15 "in" # Fan 1 direction + export_gpio 16 "in" # Fan 2 direction + export_gpio 17 "in" # Fan 3 direction + export_gpio 18 "in" # Fan 4 direction + export_gpio 19 "in" # Fan 5 direction + + export_gpio 22 "in" # PSU L PWOK + export_gpio 25 "in" # PSU R PWOK + export_gpio 27 "in" # PSU L ABS + export_gpio 28 "in" # PSU R ABS + + export_gpio 29 "out" # Fan 1 LED: Red + export_gpio 30 "out" # Fan 1 LED: Yellow + export_gpio 31 "out" # Fan 2 LED: Red + export_gpio 32 "out" # Fan 2 LED: Yellow + export_gpio 33 "out" # Fan 3 LED: Red + export_gpio 34 "out" # Fan 3 LED: Yellow + export_gpio 35 "out" # Fan 4 LED: Red + export_gpio 36 "out" # Fan 4 LED: Yellow + export_gpio 37 "out" # Fan 5 LED: Red + export_gpio 38 "out" # Fan 5 LED: Yellow + + # Turn off/down lpmod by defult (0 - Normal, 1 - Low Pow) + echo 0x00000000 > /sys/devices/platform/dx010_cpld/qsfp_lpmode + + # Attach 32 instances of EEPROM driver QSFP ports + for ((n=26;n<=58;n++)); + do + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-$n/new_device + sleep 0.1 + done + + /bin/sh /usr/local/bin/platform_api_mgnt.sh init + + echo "done." + ;; + +stop) + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-dx010.init {start|stop}" + exit 1 + ;; +esac + +exit 0 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 new file mode 100644 index 000000000000..a36e2cd1377c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install @@ -0,0 +1,8 @@ +dx010/scripts/dx010_check_qsfp.sh usr/local/bin +dx010/cfg/dx010-modules.conf etc/modules-load.d +dx010/systemd/platform-modules-dx010.service lib/systemd/system +dx010/scripts/fancontrol.sh etc/init.d +dx010/scripts/fancontrol.service lib/systemd/system +services/fancontrol/fancontrol usr/local/bin +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 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst new file mode 100644 index 000000000000..b198584282db --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst @@ -0,0 +1,10 @@ +depmod -a +systemctl enable platform-modules-dx010.service +systemctl enable fancontrol.service + +systemctl start platform-modules-dx010.service +systemctl start fancontrol.service + +/usr/local/bin/platform_api_mgnt.sh install +/etc/init.d/fancontrol.sh install + diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init new file mode 100644 index 000000000000..80964d5338af --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init @@ -0,0 +1,92 @@ +#!/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 Haliburton board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + modprobe smc + modprobe hlx_gpio_ich + modprobe dps200 + modprobe cp210x + + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find iSMT" && exit 1 + + i2cset -y ${devnum} 0x73 0x10 0x00 0x01 i + + # Attach PCA9548 0x73 Channel Extender for CPU Board + echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + sleep 1 + + # Attach PCA9541 Ox71 Master Selector + chmod 755 /sys/bus/i2c/devices/i2c-${devnum}/new_device + echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-8/new_device + sleep 1 + + # Attach PCA9548 0x72 Channel Extender for Main Board + echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-8/new_device + sleep 1 + + # Attach syseeprom + echo 24lc64t 0x50 > /sys/bus/i2c/devices/i2c-2/new_device + + echo max6699 0x1a > /sys/bus/i2c/devices/i2c-3/new_device + echo max6699 0x1a > /sys/bus/i2c/devices/i2c-11/new_device + + # Attach PSUs + echo dps200 0x5a > /sys/bus/i2c/devices/i2c-12/new_device + echo dps200 0x5b > /sys/bus/i2c/devices/i2c-13/new_device + + # Attach fans + echo emc2305 0x4d > /sys/bus/i2c/devices/i2c-23/new_device + + # Attach 4 SFP+ Uplink + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-14/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-15/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-16/new_device + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-17/new_device + + # Enable SFP module presence interrupt + echo "both" > /sys/devices/platform/e1031.smc/SFP/modabs_trig + echo 0 > /sys/devices/platform/e1031.smc/SFP/modabs_mask + + /bin/sh /usr/local/bin/platform_api_mgnt.sh init + + echo "done." + ;; + +stop) + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-haliburton.init {start|stop}" + exit 1 + ;; +esac + +exit 0 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 new file mode 100644 index 000000000000..167de45532db --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install @@ -0,0 +1,10 @@ +haliburton/cfg/haliburton-modules.conf etc/modules-load.d +haliburton/systemd/platform-modules-haliburton.service lib/systemd/system +haliburton/script/fancontrol.sh etc/init.d +haliburton/script/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 +haliburton/script/popmsg.sh usr/local/bin +haliburton/script/udev_prefix.sh usr/local/bin +haliburton/script/50-ttyUSB-C0.rules etc/udev/rules.d diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.postinst new file mode 100644 index 000000000000..74a4a4b17928 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.postinst @@ -0,0 +1,10 @@ +depmod -a +systemctl enable platform-modules-haliburton.service +systemctl enable fancontrol.service + +systemctl start platform-modules-haliburton.service +systemctl start fancontrol.service + +/usr/local/bin/platform_api_mgnt.sh install +sudo chmod +x /usr/local/bin/udev_prefix.sh +sudo chmod +x /usr/local/bin/popmsg.sh diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.init new file mode 100644 index 000000000000..977cdac06000 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.init @@ -0,0 +1,52 @@ +#!/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 seastone2 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + # Add driver to support HW + modprobe i2c-dev + modprobe ipmi_devintf + modprobe ipmi_si + modprobe baseboard_cpld + modprobe switchboard_fpga + modprobe mc24lc64t + + # Add driver to support TLV - EEPROM + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-${devnum}/new_device + break + fi + done + sleep 1 + echo "done." + ;; + +stop) + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-seastone2.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.install new file mode 100644 index 000000000000..41a381eeb0ce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.install @@ -0,0 +1,4 @@ +seastone2/cfg/seastone2-modules.conf etc/modules-load.d +seastone2/systemd/platform-modules-seastone2.service lib/systemd/system +seastone2/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_seastone_2-r0 +services/platform_api/platform_api_mgnt.sh usr/local/bin \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.postinst new file mode 100644 index 000000000000..f232a2cac59d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-seastone2.postinst @@ -0,0 +1,5 @@ +depmod -a +systemctl enable platform-modules-seastone2.service +systemctl start platform-modules-seastone2.service + +/usr/local/bin/platform_api_mgnt.sh install diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.init new file mode 100644 index 000000000000..eb003599ec61 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.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 SilverStone board. +### END INIT INFO + + +case "$1" in +start) + echo -n "Setting up board... " + + modprobe i2c-dev + modprobe baseboard-lpc + modprobe switchboard + modprobe mc24lc64t + modprobe ipmi_devintf + + # Instantiate TLV EEPROM device on I801 bus + devname=`cat /sys/bus/i2c/devices/i2c-0/name` + if [[ $devname == 'SMBus I801 adapter at '* ]]; then + echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-0/new_device + fi + decode-syseeprom --init 2> /dev/null & + + /bin/sh /usr/local/bin/platform_api_mgnt.sh init + + echo "done." + ;; + +stop) + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-silverstone.init {start|stop}" + exit 1 + ;; +esac + +exit 0 \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.install new file mode 100644 index 000000000000..67b433ced85f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.install @@ -0,0 +1,6 @@ +silverstone/scripts/sensors usr/bin +silverstone/scripts/platform_sensors.py usr/local/bin +silverstone/cfg/silverstone-modules.conf etc/modules-load.d +silverstone/systemd/platform-modules-silverstone.service lib/systemd/system +silverstone/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_silverstone-r0 +services/platform_api/platform_api_mgnt.sh usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.postinst new file mode 100644 index 000000000000..feb9cf45c219 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-silverstone.postinst @@ -0,0 +1,5 @@ +depmod -a +systemctl enable platform-modules-silverstone.service +systemctl start platform-modules-silverstone.service + +/usr/local/bin/platform_api_mgnt.sh install diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/rules b/platform/broadcom/sonic-platform-modules-cel/debian/rules new file mode 100755 index 000000000000..a7293e0b6700 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/rules @@ -0,0 +1,40 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= dx010 haliburton silverstone seastone2 + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd $(MOD_SRC_DIR); \ + if [ $$mod = "seastone2" ]; then \ + cd services/platform_api; \ + python2 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + fi \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/cfg/dx010-modules.conf b/platform/broadcom/sonic-platform-modules-cel/dx010/cfg/dx010-modules.conf new file mode 100644 index 000000000000..5bccc6578850 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/cfg/dx010-modules.conf @@ -0,0 +1,14 @@ +# /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 + diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/Makefile new file mode 100644 index 000000000000..29cf0f71d62b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/Makefile @@ -0,0 +1 @@ +obj-m := dx010_cpld.o mc24lc64t.o emc2305.o dx010_wdt.o leds-dx010.o slx_gpio_ich.o \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c new file mode 100644 index 000000000000..d8142777c6e1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_cpld.c @@ -0,0 +1,795 @@ +/* + * dx010_cpld.c - driver for SeaStone's CPLD + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "dx010_cpld" + +#define CPLD1_VERSION_ADDR 0x100 +#define CPLD2_VERSION_ADDR 0x200 +#define CPLD3_VERSION_ADDR 0x280 +#define CPLD4_VERSION_ADDR 0x300 +#define CPLD5_VERSION_ADDR 0x380 + + +#define RESET0108 0x250 +#define RESET0910 0x251 +#define RESET1118 0x2d0 +#define RESET1921 0x2d1 +#define RESET2229 0x3d0 +#define RESET3032 0x3d1 + +#define LPMOD0108 0x252 +#define LPMOD0910 0x253 +#define LPMOD1118 0x2d2 +#define LPMOD1921 0x2d3 +#define LPMOD2229 0x3d2 +#define LPMOD3032 0x3d3 + +#define ABS0108 0x254 +#define ABS0910 0x255 +#define ABS1118 0x2d4 +#define ABS1921 0x2d5 +#define ABS2229 0x3d4 +#define ABS3032 0x3d5 + +#define INT0108 0x256 +#define INT0910 0x257 +#define INT1118 0x2d6 +#define INT1921 0x2d7 +#define INT2229 0x3d6 +#define INT3032 0x3d7 + +#define ABS_INT0108 0x260 +#define ABS_INT0910 0x261 +#define ABS_INT1118 0x2E0 +#define ABS_INT1921 0x2E1 +#define ABS_INT2229 0x3E0 +#define ABS_INT3032 0x3E1 + +#define ABS_INT_MSK0108 0x262 +#define ABS_INT_MSK0910 0x263 +#define ABS_INT_MSK1118 0x2E2 +#define ABS_INT_MSK1921 0x2E3 +#define ABS_INT_MSK2229 0x3E2 +#define ABS_INT_MSK3032 0x3E3 + +#define CPLD4_INT0 0x313 +#define CPLD4_INT0_MSK 0x315 + +#define LENGTH_PORT_CPLD 34 +#define PORT_BANK1_START 1 +#define PORT_BANK1_END 10 +#define PORT_BANK2_START 11 +#define PORT_BANK2_END 21 +#define PORT_BANK3_START 22 +#define PORT_BANK3_END 32 +#define PORT_SFPP1 33 +#define PORT_SFPP2 34 + +#define PORT_ID_BANK1 0x210 +#define PORT_ID_BANK2 0x290 +#define PORT_ID_BANK3 0x390 + +#define OPCODE_ID_BANK1 0x211 +#define OPCODE_ID_BANK2 0x291 +#define OPCODE_ID_BANK3 0x391 + +#define DEVADDR_ID_BANK1 0x212 +#define DEVADDR_ID_BANK2 0x292 +#define DEVADDR_ID_BANK3 0x392 + +#define CMDBYT_ID_BANK1 0x213 +#define CMDBYT_ID_BANK2 0x293 +#define CMDBYT_ID_BANK3 0x393 + +#define WRITE_ID_BANK1 0x220 +#define WRITE_ID_BANK2 0x2A0 +#define WRITE_ID_BANK3 0x3A0 + +#define READ_ID_BANK1 0x230 +#define READ_ID_BANK2 0x2B0 +#define READ_ID_BANK3 0x3B0 + +#define SSRR_ID_BANK1 0x216 +#define SSRR_ID_BANK2 0x296 +#define SSRR_ID_BANK3 0x396 + +#define HST_CNTL2_QUICK 0x00 +#define HST_CNTL2_BYTE 0x01 +#define HST_CNTL2_BYTE_DATA 0x02 +#define HST_CNTL2_WORD_DATA 0x03 +#define HST_CNTL2_BLOCK 0x05 + +struct dx010_i2c_data { + int portid; +}; + +struct dx010_cpld_data { + struct i2c_adapter *i2c_adapter[LENGTH_PORT_CPLD]; + struct mutex cpld_lock; + uint16_t read_addr; +}; + +struct dx010_cpld_data *cpld_data; + +static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + + 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; + 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 ssize_t get_reset(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long reset = 0; + + mutex_lock(&cpld_data->cpld_lock); + + reset = + (inb(RESET3032) & 0x07) << (24+5) | + inb(RESET2229) << (24-3) | + (inb(RESET1921) & 0x07) << (16 + 2) | + inb(RESET1118) << (16-6) | + (inb(RESET0910) & 0x03 ) << 8 | + inb(RESET0108); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%8.8lx\n", reset & 0xffffffff); +} + +static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + + 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 ssize_t set_reset(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long reset; + int err; + + mutex_lock(&cpld_data->cpld_lock); + + err = kstrtoul(buf, 16, &reset); + if (err) + { + mutex_unlock(&cpld_data->cpld_lock); + return err; + } + + outb( (reset >> 0) & 0xFF, RESET0108); + outb( (reset >> 8) & 0x03, RESET0910); + outb( (reset >> 10) & 0xFF, RESET1118); + outb( (reset >> 18) & 0x07, RESET1921); + outb( (reset >> 21) & 0xFF, RESET2229); + outb( (reset >> 29) & 0x07, RESET3032); + + mutex_unlock(&cpld_data->cpld_lock); + + return count; +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long lpmod = 0; + + mutex_lock(&cpld_data->cpld_lock); + + lpmod = + (inb(LPMOD3032) & 0x07) << (24+5) | + inb(LPMOD2229) << (24-3) | + (inb(LPMOD1921) & 0x07) << (16 + 2) | + inb(LPMOD1118) << (16-6) | + (inb(LPMOD0910) & 0x03 ) << 8 | + inb(LPMOD0108); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%8.8lx\n", lpmod & 0xffffffff); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long lpmod; + int err; + + mutex_lock(&cpld_data->cpld_lock); + + err = kstrtoul(buf, 16, &lpmod); + if (err) + { + mutex_unlock(&cpld_data->cpld_lock); + return err; + } + + outb( (lpmod >> 0) & 0xFF, LPMOD0108); + outb( (lpmod >> 8) & 0x03, LPMOD0910); + outb( (lpmod >> 10) & 0xFF, LPMOD1118); + outb( (lpmod >> 18) & 0x07, LPMOD1921); + outb( (lpmod >> 21) & 0xFF, LPMOD2229); + outb( (lpmod >> 29) & 0x07, LPMOD3032); + + mutex_unlock(&cpld_data->cpld_lock); + + return count; +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long present; + + mutex_lock(&cpld_data->cpld_lock); + + present = + (inb(ABS3032) & 0x07) << (24+5) | + inb(ABS2229) << (24-3) | + (inb(ABS1921) & 0x07) << (16 + 2) | + inb(ABS1118) << (16-6) | + (inb(ABS0910) & 0x03) << 8 | + inb(ABS0108); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%8.8lx\n", present & 0xffffffff); +} + +static ssize_t get_modirq(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long irq; + + mutex_lock(&cpld_data->cpld_lock); + + irq = + (inb(INT3032) & 0x07) << (24+5) | + inb(INT2229) << (24-3) | + (inb(INT1921) & 0x07) << (16 + 2) | + inb(INT1118) << (16-6) | + (inb(INT0910) & 0x03) << 8 | + inb(INT0108); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%8.8lx\n", irq & 0xffffffff); +} + +static ssize_t get_modprs_irq(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long prs_int = 0; + + mutex_lock(&cpld_data->cpld_lock); + + /* Clear interrupt source */ + inb(CPLD4_INT0); + + prs_int = + (inb(ABS_INT3032) & 0x07) << (24+5) | + inb(ABS_INT2229) << (24-3) | + (inb(ABS_INT1921) & 0x07) << (16 + 2) | + inb(ABS_INT1118) << (16-6) | + (inb(ABS_INT0910) & 0x03 ) << 8 | + inb(ABS_INT0108); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%8.8lx\n", prs_int & 0xffffffff); +} + +static ssize_t get_modprs_msk(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long prs_int_msk = 0; + + mutex_lock(&cpld_data->cpld_lock); + + prs_int_msk = + (inb(ABS_INT_MSK3032) & 0x07) << (24+5) | + inb(ABS_INT_MSK2229) << (24-3) | + (inb(ABS_INT_MSK1921) & 0x07) << (16 + 2) | + inb(ABS_INT_MSK1118) << (16-6) | + (inb(ABS_INT_MSK0910) & 0x03 ) << 8 | + inb(ABS_INT_MSK0108); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%8.8lx\n", prs_int_msk & 0xffffffff); +} + +static ssize_t set_modprs_msk(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long prs_int_msk; + int err; + + mutex_lock(&cpld_data->cpld_lock); + + err = kstrtoul(buf, 16, &prs_int_msk); + if (err) + { + mutex_unlock(&cpld_data->cpld_lock); + return err; + } + + outb( (prs_int_msk >> 0) & 0xFF, ABS_INT_MSK0108); + outb( (prs_int_msk >> 8) & 0x03, ABS_INT_MSK0910); + outb( (prs_int_msk >> 10) & 0xFF, ABS_INT_MSK1118); + outb( (prs_int_msk >> 18) & 0x07, ABS_INT_MSK1921); + outb( (prs_int_msk >> 21) & 0xFF, ABS_INT_MSK2229); + outb( (prs_int_msk >> 29) & 0x07, ABS_INT_MSK3032); + + mutex_unlock(&cpld_data->cpld_lock); + + return count; +} + +static ssize_t get_cpld4_int0(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char int0 = 0; + + mutex_lock(&cpld_data->cpld_lock); + + int0 = inb(CPLD4_INT0); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%2.2x\n", int0 & 0xff); +} + +static ssize_t get_cpld4_int0_msk(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char int0_msk = 0; + + mutex_lock(&cpld_data->cpld_lock); + + int0_msk = inb(CPLD4_INT0_MSK); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%2.2x\n", int0_msk & 0xff); +} + +static ssize_t set_cpld4_int0_msk(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned long int0_msk; + int err; + + mutex_lock(&cpld_data->cpld_lock); + + err = kstrtoul(buf, 16, &int0_msk); + if (err) + { + mutex_unlock(&cpld_data->cpld_lock); + return err; + } + + outb(int0_msk & 0x3f, CPLD4_INT0_MSK); + + mutex_unlock(&cpld_data->cpld_lock); + + return count; +} + +static DEVICE_ATTR_RW(getreg); +static DEVICE_ATTR_WO(setreg); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); +static DEVICE_ATTR(qsfp_modirq, S_IRUGO, get_modirq, NULL); +static DEVICE_ATTR(qsfp_modprs_irq, S_IRUGO, get_modprs_irq, NULL); +static DEVICE_ATTR(qsfp_modprs_msk, S_IRUGO | S_IWUSR, get_modprs_msk, set_modprs_msk); +static DEVICE_ATTR(cpld4_int0, S_IRUGO, get_cpld4_int0, NULL); +static DEVICE_ATTR(cpld4_int0_msk, S_IRUGO | S_IWUSR, get_cpld4_int0_msk, set_cpld4_int0_msk); + +static struct attribute *dx010_lpc_attrs[] = { + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_qsfp_modirq.attr, + &dev_attr_qsfp_modprs_irq.attr, + &dev_attr_qsfp_modprs_msk.attr, + &dev_attr_cpld4_int0.attr, + &dev_attr_cpld4_int0_msk.attr, + NULL, +}; + +static struct attribute_group dx010_lpc_attr_grp = { + .attrs = dx010_lpc_attrs, +}; + +static struct resource cel_dx010_lpc_resources[] = { + { + .flags = IORESOURCE_IO, + }, +}; + +static void cel_dx010_lpc_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device cel_dx010_lpc_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(cel_dx010_lpc_resources), + .resource = cel_dx010_lpc_resources, + .dev = { + .release = cel_dx010_lpc_dev_release, + } +}; + + +/** + * Read eeprom of QSFP device. + * @param a i2c adapter. + * @param addr address to read. + * @param new_data QSFP port number struct. + * @param cmd i2c command. + * @return 0 if not error, else the error code. + */ +static int i2c_read_eeprom(struct i2c_adapter *a, u16 addr, + struct dx010_i2c_data *new_data, u8 cmd, union i2c_smbus_data *data){ + + u32 reg; + int ioBase=0; + char byte; + short temp; + short portid, opcode, devaddr, cmdbyte0, ssrr, writedata, readdata; + __u16 word_data; + int error = -EIO; + + mutex_lock(&cpld_data->cpld_lock); + + if (((new_data->portid >= PORT_BANK1_START) + && (new_data->portid <= PORT_BANK1_END)) + || (new_data->portid == PORT_SFPP1) + || (new_data->portid == PORT_SFPP2)) + { + portid = PORT_ID_BANK1; + opcode = OPCODE_ID_BANK1; + devaddr = DEVADDR_ID_BANK1; + cmdbyte0 = CMDBYT_ID_BANK1; + ssrr = SSRR_ID_BANK1; + writedata = WRITE_ID_BANK1; + readdata = READ_ID_BANK1; + }else if ((new_data->portid >= PORT_BANK2_START) && (new_data->portid <= PORT_BANK2_END)){ + portid = PORT_ID_BANK2; + opcode = OPCODE_ID_BANK2; + devaddr = DEVADDR_ID_BANK2; + cmdbyte0 = CMDBYT_ID_BANK2; + ssrr = SSRR_ID_BANK2; + writedata = WRITE_ID_BANK2; + readdata = READ_ID_BANK2; + }else if ((new_data->portid >= PORT_BANK3_START) && (new_data->portid <= PORT_BANK3_END)){ + portid = PORT_ID_BANK3; + opcode = OPCODE_ID_BANK3; + devaddr = DEVADDR_ID_BANK3; + cmdbyte0 = CMDBYT_ID_BANK3; + ssrr = SSRR_ID_BANK3; + writedata = WRITE_ID_BANK3; + readdata = READ_ID_BANK3; + }else{ + /* Invalid parameter! */ + error = -EINVAL; + goto exit; + } + + while ((inb(ioBase + ssrr) & 0x40)); + if ((inb(ioBase + ssrr) & 0x80) == 0x80) { + error = -EIO; + /* Read error reset the port */ + outb(0x00, ioBase + ssrr); + udelay(3000); + outb(0x01, ioBase + ssrr); + goto exit; + } + + byte = 0x40 +new_data->portid; + reg = cmd; + outb(byte, ioBase + portid); + outb(reg,ioBase + cmdbyte0); + byte = 33; + outb(byte, ioBase + opcode); + addr = addr << 1; + addr |= 0x01; + outb(addr, ioBase + devaddr); + while ((inb(ioBase + ssrr) & 0x40)) + { + udelay(100); + } + + if ((inb(ioBase + ssrr) & 0x80) == 0x80) { + /* Read error reset the port */ + error = -EIO; + outb(0x00, ioBase + ssrr); + udelay(3000); + outb(0x01, ioBase + ssrr); + goto exit; + } + + temp = ioBase + readdata; + word_data = inb(temp); + word_data |= (inb(++temp) << 8); + + mutex_unlock(&cpld_data->cpld_lock); + data->word = word_data; + return 0; + +exit: + mutex_unlock(&cpld_data->cpld_lock); + return error; +} + +static int dx010_i2c_access(struct i2c_adapter *a, u16 addr, + unsigned short flags, char rw, u8 cmd, + int size, union i2c_smbus_data *data) +{ + + int error = 0; + + struct dx010_i2c_data *new_data; + + /* Write the command register */ + new_data = i2c_get_adapdata(a); + + /* Map the size to what the chip understands */ + switch (size) { + case I2C_SMBUS_QUICK: + size = HST_CNTL2_QUICK; + break; + case I2C_SMBUS_BYTE: + size = HST_CNTL2_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + size = HST_CNTL2_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + size = HST_CNTL2_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + size = HST_CNTL2_BLOCK; + break; + default: + dev_warn(&a->dev, "Unsupported transaction %d\n", size); + error = -EOPNOTSUPP; + goto Done; + } + + switch (size) { + case HST_CNTL2_BYTE: /* Result put in SMBHSTDAT0 */ + break; + case HST_CNTL2_BYTE_DATA: + break; + case HST_CNTL2_WORD_DATA: + if( 0 == i2c_read_eeprom(a,addr,new_data,cmd,data)){ + error = 0; + }else{ + error = -EIO; + } + break; + } + +Done: + return error; +} + +static u32 dx010_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; +} + +static const struct i2c_algorithm dx010_i2c_algorithm = { + .smbus_xfer = dx010_i2c_access, + .functionality = dx010_i2c_func, +}; + +static struct i2c_adapter * cel_dx010_i2c_init(struct platform_device *pdev, int portid) +{ + int error; + + struct i2c_adapter *new_adapter; + struct dx010_i2c_data *new_data; + + new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL); + if (!new_adapter) + return NULL; + + new_adapter->dev.parent = &pdev->dev; + new_adapter->owner = THIS_MODULE; + new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + new_adapter->algo = &dx010_i2c_algorithm; + + snprintf(new_adapter->name, sizeof(new_adapter->name), + "SMBus dx010 i2c Adapter portid@%04x", portid); + + new_data = kzalloc(sizeof(*new_data), GFP_KERNEL); + if (!new_data) + return NULL; + + new_data->portid = portid; + + i2c_set_adapdata(new_adapter,new_data); + + error = i2c_add_adapter(new_adapter); + if(error) + return NULL; + + return new_adapter; +}; + +static int cel_dx010_lpc_drv_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret = 0; + int portid_count; + + cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct dx010_cpld_data), + GFP_KERNEL); + if (!cpld_data) + return -ENOMEM; + + mutex_init(&cpld_data->cpld_lock); + cpld_data->read_addr = CPLD1_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, &dx010_lpc_attr_grp); + if (ret) { + printk(KERN_ERR "Cannot create sysfs\n"); + } + + for(portid_count=1 ; portid_count<=LENGTH_PORT_CPLD ; portid_count++) + cpld_data->i2c_adapter[portid_count-1] = + cel_dx010_i2c_init(pdev, portid_count); + + /* Enable INT0 interrupt register */ + outb(inb(CPLD4_INT0_MSK) & 0xf8, CPLD4_INT0_MSK); + + /* Enable modprs interrupt register */ + outb(0, ABS_INT_MSK0108); + outb(0, ABS_INT_MSK0910); + outb(0, ABS_INT_MSK1118); + outb(0, ABS_INT_MSK1921); + outb(0, ABS_INT_MSK2229); + outb(0, ABS_INT_MSK3032); + + return 0; +} + +static int cel_dx010_lpc_drv_remove(struct platform_device *pdev) +{ + int portid_count; + + sysfs_remove_group(&pdev->dev.kobj, &dx010_lpc_attr_grp); + + for (portid_count=1 ; portid_count<=LENGTH_PORT_CPLD ; portid_count++) + i2c_del_adapter(cpld_data->i2c_adapter[portid_count-1]); + + return 0; +} + +static struct platform_driver cel_dx010_lpc_drv = { + .probe = cel_dx010_lpc_drv_probe, + .remove = __exit_p(cel_dx010_lpc_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int cel_dx010_lpc_init(void) +{ + platform_device_register(&cel_dx010_lpc_dev); + platform_driver_register(&cel_dx010_lpc_drv); + + return 0; +} + +void cel_dx010_lpc_exit(void) +{ + platform_driver_unregister(&cel_dx010_lpc_drv); + platform_device_unregister(&cel_dx010_lpc_dev); +} + +module_init(cel_dx010_lpc_init); +module_exit(cel_dx010_lpc_exit); + +MODULE_AUTHOR("Pradchaya P "); +MODULE_VERSION("1.0.1"); +MODULE_DESCRIPTION("Celestica SeaStone DX010 LPC Driver"); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_wdt.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_wdt.c new file mode 100644 index 000000000000..a386c065051a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/dx010_wdt.c @@ -0,0 +1,215 @@ +/* + * Watchdog driver for the Seastone DX010 + * + * 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 +#include +#include +#include + + +#define DRIVER_NAME "dx010_wdt" + +#define RESET_CTRL 0x102 +#define WDT_MASK 0x04 +#define WDI_GPIO_DIR 0x504 +#define WDI_GPIO 0x508 + +static bool nowayout = WATCHDOG_NOWAYOUT; + +struct dx010_wdt_drvdata { + struct watchdog_device wdt; + struct mutex lock; +}; + +static struct resource dx010_wdt_resources[] = { + { + .flags = IORESOURCE_IO, + }, +}; + +static void dx010_wdt_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device dx010_wdt_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(dx010_wdt_resources), + .resource = dx010_wdt_resources, + .dev = { + .release = dx010_wdt_dev_release, + } +}; + +static int dx010_wdt_start(struct watchdog_device *wdt_dev) +{ + struct dx010_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); + unsigned char reset_ctrl = 0x00; + unsigned long gpio ,dir; + + mutex_lock(&drvdata->lock); + + gpio = inl(WDI_GPIO); + gpio |= 1 << 15; + outl(gpio, WDI_GPIO); + + outl((inl(WDI_GPIO_DIR) & (~(1 << 15))), WDI_GPIO_DIR); + + reset_ctrl = inb(RESET_CTRL); + + gpio = inl(WDI_GPIO); + gpio &= ~(1 << 15); + outl_p( gpio, WDI_GPIO ); + + mdelay(10); + + gpio = inl(WDI_GPIO); + gpio |= (1 << 15); + outl_p( gpio, WDI_GPIO ); + + reset_ctrl |= WDT_MASK; + outb(reset_ctrl, RESET_CTRL); + + mutex_unlock(&drvdata->lock); + + return 0; +} + +static int dx010_wdt_stop(struct watchdog_device *wdt_dev) +{ + struct dx010_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); + unsigned long reset_ctrl; + + mutex_lock(&drvdata->lock); + + reset_ctrl = inb(RESET_CTRL); + reset_ctrl &= ~WDT_MASK; + outb(reset_ctrl, RESET_CTRL); + + mutex_unlock(&drvdata->lock); + + return 0; +} + +static int dx010_wdt_ping(struct watchdog_device *wdt_dev) +{ + struct dx010_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); + unsigned long gpio; + + mutex_lock(&drvdata->lock); + + gpio = inl(WDI_GPIO); + gpio &= ~(1 << 15); + outl_p( gpio, WDI_GPIO ); + + mdelay(10); + + gpio = inl(WDI_GPIO); + gpio |= (1 << 15); + outl_p( gpio, WDI_GPIO ); + + mutex_unlock(&drvdata->lock); + + return 0; +} + +static const struct watchdog_info dx010_wdt_info = { + .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .identity = "DX010 Watchdog", +}; + +static const struct watchdog_ops dx010_wdt_ops = { + .owner = THIS_MODULE, + .start = dx010_wdt_start, + .stop = dx010_wdt_stop, + .ping = dx010_wdt_ping, +}; + +static int dx010_wdt_probe(struct platform_device *pdev) +{ + struct dx010_wdt_drvdata *drvdata; + int ret; + + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), + GFP_KERNEL); + if (!drvdata) { + ret = -ENOMEM; + goto err; + } + + mutex_init(&drvdata->lock); + + drvdata->wdt.info = &dx010_wdt_info; + drvdata->wdt.ops = &dx010_wdt_ops; + + watchdog_set_nowayout(&drvdata->wdt, nowayout); + watchdog_set_drvdata(&drvdata->wdt, drvdata); + + ret = watchdog_register_device(&drvdata->wdt); + if (ret != 0) { + dev_err(&pdev->dev, "watchdog_register_device() failed: %d\n", + ret); + goto err; + } + + platform_set_drvdata(pdev, drvdata); + +err: + return ret; +} + +static int dx010_wdt_remove(struct platform_device *pdev) +{ + struct dx010_wdt_drvdata *drvdata = platform_get_drvdata(pdev); + + watchdog_unregister_device(&drvdata->wdt); + + return 0; +} + +static struct platform_driver dx010_wdt_drv = { + .probe = dx010_wdt_probe, + .remove = dx010_wdt_remove, + .driver = { + .name = DRIVER_NAME, + }, +}; + +int dx010_wdt_init(void) +{ + platform_device_register(&dx010_wdt_dev); + platform_driver_register(&dx010_wdt_drv); + + return 0; +} + +void dx010_wdt_exit(void) +{ + platform_driver_unregister(&dx010_wdt_drv); + platform_device_unregister(&dx010_wdt_dev); +} + +module_init(dx010_wdt_init); +module_exit(dx010_wdt_exit); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_AUTHOR("Pariwat Leamsumran "); +MODULE_DESCRIPTION("Seastone DX010 Watchdog"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:dx010-watchdog"); diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/emc2305.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/emc2305.c new file mode 100644 index 000000000000..b406a29fd9be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/emc2305.c @@ -0,0 +1,886 @@ +/* + * emc2305.c - hwmon driver for SMSC EMC2305 fan controller + * (C) Copyright 2013 + * Reinhard Pfau, Guntermann & Drunck GmbH + * + * Based on emc2103 driver by SMSC. + * + * Datasheet available at: + * http://www.smsc.com/Downloads/SMSC/Downloads_Public/Data_Sheets/2305.pdf + * + * Also supports the EMC2303 fan controller which has the same functionality + * and register layout as EMC2305, but supports only up to 3 fans instead of 5. + * + * Also supports EMC2302 (up to 2 fans) and EMC2301 (1 fan) fan controller. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * TODO / IDEAS: + * - expose more of the configuration and features + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Addresses scanned. + * Listed in the same order as they appear in the EMC2305, EMC2303 data sheets. + * + * Note: these are the I2C adresses which are possible for EMC2305 and EMC2303 + * chips. + * The EMC2302 supports only 0x2e (EMC2302-1) and 0x2f (EMC2302-2). + * The EMC2301 supports only 0x2f. + */ +static const unsigned short i2c_adresses[] = { + 0x2E, + 0x2F, + 0x2C, + 0x2D, + 0x4C, + 0x4D, + I2C_CLIENT_END +}; + +/* + * global registers + */ +enum { + REG_CONFIGURATION = 0x20, + REG_FAN_STATUS = 0x24, + REG_FAN_STALL_STATUS = 0x25, + REG_FAN_SPIN_STATUS = 0x26, + REG_DRIVE_FAIL_STATUS = 0x27, + REG_FAN_INTERRUPT_ENABLE = 0x29, + REG_PWM_POLARITY_CONFIG = 0x2a, + REG_PWM_OUTPUT_CONFIG = 0x2b, + REG_PWM_BASE_FREQ_1 = 0x2c, + REG_PWM_BASE_FREQ_2 = 0x2d, + REG_SOFTWARE_LOCK = 0xef, + REG_PRODUCT_FEATURES = 0xfc, + REG_PRODUCT_ID = 0xfd, + REG_MANUFACTURER_ID = 0xfe, + REG_REVISION = 0xff +}; + +/* + * fan specific registers + */ +enum { + REG_FAN_SETTING = 0x30, + REG_PWM_DIVIDE = 0x31, + REG_FAN_CONFIGURATION_1 = 0x32, + REG_FAN_CONFIGURATION_2 = 0x33, + REG_GAIN = 0x35, + REG_FAN_SPIN_UP_CONFIG = 0x36, + REG_FAN_MAX_STEP = 0x37, + REG_FAN_MINIMUM_DRIVE = 0x38, + REG_FAN_VALID_TACH_COUNT = 0x39, + REG_FAN_DRIVE_FAIL_BAND_LOW = 0x3a, + REG_FAN_DRIVE_FAIL_BAND_HIGH = 0x3b, + REG_TACH_TARGET_LOW = 0x3c, + REG_TACH_TARGET_HIGH = 0x3d, + REG_TACH_READ_HIGH = 0x3e, + REG_TACH_READ_LOW = 0x3f, +}; + +#define SEL_FAN(fan, reg) (reg + fan * 0x10) + +/* + * Factor by equations [2] and [3] from data sheet; valid for fans where the + * number of edges equals (poles * 2 + 1). + */ +#define FAN_RPM_FACTOR 3932160 + + +struct emc2305_fan_data { + bool enabled; + bool valid; + unsigned long last_updated; + bool rpm_control; + u8 multiplier; + u8 poles; + u16 target; + u16 tach; + u16 rpm_factor; + u8 pwm; +}; + +struct emc2305_data { + struct device *hwmon_dev; + struct mutex update_lock; + int fans; + struct emc2305_fan_data fan[5]; +}; + +static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output) +{ + int status = i2c_smbus_read_byte_data(client, i2c_reg); + if (status < 0) { + dev_warn(&client->dev, "reg 0x%02x, err %d\n", + i2c_reg, status); + } else { + *output = status; + } + return status; +} + +static void read_fan_from_i2c(struct i2c_client *client, u16 *output, + u8 hi_addr, u8 lo_addr) +{ + u8 high_byte, lo_byte; + + if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0) + return; + + if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0) + return; + + *output = ((u16)high_byte << 5) | (lo_byte >> 3); +} + +static void write_fan_target_to_i2c(struct i2c_client *client, int fan, + u16 new_target) +{ + const u8 lo_reg = SEL_FAN(fan, REG_TACH_TARGET_LOW); + const u8 hi_reg = SEL_FAN(fan, REG_TACH_TARGET_HIGH); + u8 high_byte = (new_target & 0x1fe0) >> 5; + u8 low_byte = (new_target & 0x001f) << 3; + i2c_smbus_write_byte_data(client, lo_reg, low_byte); + i2c_smbus_write_byte_data(client, hi_reg, high_byte); +} + +static void read_fan_config_from_i2c(struct i2c_client *client, int fan) + +{ + struct emc2305_data *data = i2c_get_clientdata(client); + u8 conf1; + + if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_CONFIGURATION_1), + &conf1) < 0) + return; + + data->fan[fan].rpm_control = (conf1 & 0x80) != 0; + data->fan[fan].multiplier = 1 << ((conf1 & 0x60) >> 5); + data->fan[fan].poles = ((conf1 & 0x18) >> 3) + 1; +} + +static void read_fan_setting(struct i2c_client *client, int fan) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + u8 setting; + + if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_SETTING), + &setting) < 0) + return; + + data->fan[fan].pwm = setting; +} + +static void read_fan_data(struct i2c_client *client, int fan_idx) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + + read_fan_from_i2c(client, &data->fan[fan_idx].target, + SEL_FAN(fan_idx, REG_TACH_TARGET_HIGH), + SEL_FAN(fan_idx, REG_TACH_TARGET_LOW)); + read_fan_from_i2c(client, &data->fan[fan_idx].tach, + SEL_FAN(fan_idx, REG_TACH_READ_HIGH), + SEL_FAN(fan_idx, REG_TACH_READ_LOW)); +} + +static struct emc2305_fan_data * +emc2305_update_fan(struct i2c_client *client, int fan_idx) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan_data = &data->fan[fan_idx]; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) + || !fan_data->valid) { + read_fan_config_from_i2c(client, fan_idx); + read_fan_data(client, fan_idx); + read_fan_setting(client, fan_idx); + fan_data->valid = true; + fan_data->last_updated = jiffies; + } + + mutex_unlock(&data->update_lock); + return fan_data; +} + +static struct emc2305_fan_data * +emc2305_update_device_fan(struct device *dev, struct device_attribute *da) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + + return emc2305_update_fan(client, fan_idx); +} + +/* + * set/ config functions + */ + +/* + * Note: we also update the fan target here, because its value is + * determined in part by the fan clock divider. This follows the principle + * of least surprise; the user doesn't expect the fan target to change just + * because the divider changed. + */ +static int +emc2305_set_fan_div(struct i2c_client *client, int fan_idx, long new_div) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); + int new_range_bits, old_div = 8 / fan->multiplier; + int status = 0; + + if (new_div == old_div) /* No change */ + return 0; + + switch (new_div) { + case 1: + new_range_bits = 3; + break; + case 2: + new_range_bits = 2; + break; + case 4: + new_range_bits = 1; + break; + case 8: + new_range_bits = 0; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + status = i2c_smbus_read_byte_data(client, reg_conf1); + if (status < 0) { + dev_dbg(&client->dev, "reg 0x%02x, err %d\n", + reg_conf1, status); + status = -EIO; + goto exit_unlock; + } + status &= 0x9F; + status |= (new_range_bits << 5); + status = i2c_smbus_write_byte_data(client, reg_conf1, status); + if (status < 0) { + status = -EIO; + goto exit_invalidate; + } + + fan->multiplier = 8 / new_div; + + /* update fan target if high byte is not disabled */ + if ((fan->target & 0x1fe0) != 0x1fe0) { + u16 new_target = (fan->target * old_div) / new_div; + fan->target = min_t(u16, new_target, 0x1fff); + write_fan_target_to_i2c(client, fan_idx, fan->target); + } + +exit_invalidate: + /* invalidate fan data to force re-read from hardware */ + fan->valid = false; +exit_unlock: + mutex_unlock(&data->update_lock); + return status; +} + +static int +emc2305_set_fan_target(struct i2c_client *client, int fan_idx, long rpm_target) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + + /* + * Datasheet states 16000 as maximum RPM target + * (table 2.2 and section 4.3) + */ + if ((rpm_target < 0) || (rpm_target > 16000)) + return -EINVAL; + + mutex_lock(&data->update_lock); + + if (rpm_target == 0) + fan->target = 0x1fff; + else + fan->target = clamp_val( + (FAN_RPM_FACTOR * fan->multiplier) / rpm_target, + 0, 0x1fff); + + write_fan_target_to_i2c(client, fan_idx, fan->target); + + mutex_unlock(&data->update_lock); + return 0; +} + +static int +emc2305_set_pwm_enable(struct i2c_client *client, int fan_idx, long enable) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_fan_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); + int status = 0; + u8 conf_reg; + + mutex_lock(&data->update_lock); + switch (enable) { + case 0: + fan->rpm_control = false; + break; + case 3: + fan->rpm_control = true; + break; + default: + status = -EINVAL; + goto exit_unlock; + } + + status = read_u8_from_i2c(client, reg_fan_conf1, &conf_reg); + if (status < 0) { + status = -EIO; + goto exit_unlock; + } + + if (fan->rpm_control) + conf_reg |= 0x80; + else + conf_reg &= ~0x80; + + status = i2c_smbus_write_byte_data(client, reg_fan_conf1, conf_reg); + if (status < 0) + status = -EIO; + +exit_unlock: + mutex_unlock(&data->update_lock); + return status; +} + +static int +emc2305_set_pwm(struct i2c_client *client, int fan_idx, long pwm) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_fan_setting = SEL_FAN(fan_idx, REG_FAN_SETTING); + int status = 0; + + /* + * Datasheet states 255 as maximum PWM + * (section 5.7) + */ + if ((pwm < 0) || (pwm > 255)) + return -EINVAL; + + fan->pwm = pwm; + + mutex_lock(&data->update_lock); + + status = i2c_smbus_write_byte_data(client, reg_fan_setting, fan->pwm); + + mutex_unlock(&data->update_lock); + return status; +} +/* + * sysfs callback functions + * + * Note: + * Naming of the funcs is modelled after the naming scheme described in + * Documentation/hwmon/sysfs-interface: + * + * For a sysfs file _ the functions are named like this: + * the show function: show__ + * the store function: set__ + * For read only (RO) attributes of course only the show func is required. + * + * This convention allows us to define the sysfs attributes by using macros. + */ + +static ssize_t +show_fan_input(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int rpm = 0; + if (fan->tach != 0) + rpm = (FAN_RPM_FACTOR * fan->multiplier) / fan->tach; + return sprintf(buf, "%d\n", rpm); +} + +static ssize_t +show_fan_fault(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + bool fault = ((fan->tach & 0x1fe0) == 0x1fe0); + return sprintf(buf, "%d\n", fault ? 1 : 0); +} + +static ssize_t +show_fan_div(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int fan_div = 8 / fan->multiplier; + return sprintf(buf, "%d\n", fan_div); +} + +static ssize_t +show_fan_alarm(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + bool fault = ((fan->tach & 0x1fe0) == 0x1fe0); + return sprintf(buf, "%d\n", fault ? 1 : 0); +} + +static ssize_t +set_fan_div(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long new_div; + int status; + + status = kstrtol(buf, 10, &new_div); + if (status < 0) + return -EINVAL; + + status = emc2305_set_fan_div(client, fan_idx, new_div); + if (status < 0) + return status; + + return count; +} + +static ssize_t +show_fan_target(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int rpm = 0; + + /* high byte of 0xff indicates disabled so return 0 */ + if ((fan->target != 0) && ((fan->target & 0x1fe0) != 0x1fe0)) + rpm = (FAN_RPM_FACTOR * fan->multiplier) + / fan->target; + + return sprintf(buf, "%d\n", rpm); +} + +static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long rpm_target; + int status; + + status = kstrtol(buf, 10, &rpm_target); + if (status < 0) + return -EINVAL; + + status = emc2305_set_fan_target(client, fan_idx, rpm_target); + if (status < 0) + return status; + + return count; +} + +static ssize_t +show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + return sprintf(buf, "%d\n", fan->rpm_control ? 3 : 0); +} + +static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long new_value; + int status; + + status = kstrtol(buf, 10, &new_value); + if (status < 0) + return -EINVAL; + status = emc2305_set_pwm_enable(client, fan_idx, new_value); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + return sprintf(buf, "%d\n", fan->pwm); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + unsigned long val; + int ret; + int status; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + if (val > 255) + return -EINVAL; + + status = emc2305_set_pwm(client, fan_idx, val); + return count; +} + +/* define a read only attribute */ +#define EMC2305_ATTR_RO(_type, _item, _num) \ + SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO, \ + show_## _type ## _ ## _item, NULL, _num - 1) + +/* define a read/write attribute */ +#define EMC2305_ATTR_RW(_type, _item, _num) \ + SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO | S_IWUSR, \ + show_## _type ##_ ## _item, \ + set_## _type ## _ ## _item, _num - 1) + +/* + * TODO: Ugly hack, but temporary as this whole logic needs + * to be rewritten as per standard HWMON sysfs registration + */ + +/* define a read/write attribute */ +#define EMC2305_ATTR_RW2(_type, _num) \ + SENSOR_ATTR(_type ## _num, S_IRUGO | S_IWUSR, \ + show_## _type, set_## _type, _num - 1) + +/* defines the attributes for a single fan */ +#define EMC2305_DEFINE_FAN_ATTRS(_num) \ + static const \ + struct sensor_device_attribute emc2305_attr_fan ## _num[] = { \ + EMC2305_ATTR_RO(fan, input, _num), \ + EMC2305_ATTR_RO(fan, fault, _num), \ + EMC2305_ATTR_RW(fan, div, _num), \ + EMC2305_ATTR_RO(fan, alarm, _num), \ + EMC2305_ATTR_RW(fan, target, _num), \ + EMC2305_ATTR_RW(pwm, enable, _num), \ + EMC2305_ATTR_RW2(pwm, _num) \ + } + +#define EMC2305_NUM_FAN_ATTRS ARRAY_SIZE(emc2305_attr_fan1) + +/* common attributes for EMC2303 and EMC2305 */ +static const struct sensor_device_attribute emc2305_attr_common[] = { +}; + +/* fan attributes for the single fans */ +EMC2305_DEFINE_FAN_ATTRS(1); +EMC2305_DEFINE_FAN_ATTRS(2); +EMC2305_DEFINE_FAN_ATTRS(3); +EMC2305_DEFINE_FAN_ATTRS(4); +EMC2305_DEFINE_FAN_ATTRS(5); +EMC2305_DEFINE_FAN_ATTRS(6); + +/* fan attributes */ +static const struct sensor_device_attribute *emc2305_fan_attrs[] = { + emc2305_attr_fan1, + emc2305_attr_fan2, + emc2305_attr_fan3, + emc2305_attr_fan4, + emc2305_attr_fan5, +}; + +/* + * driver interface + */ + +static int emc2305_remove(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + int fan_idx, i; + + hwmon_device_unregister(data->hwmon_dev); + + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) + device_remove_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) + device_remove_file(&client->dev, + &emc2305_attr_common[i].dev_attr); + + kfree(data); + return 0; +} + + +#ifdef CONFIG_OF +/* + * device tree support + */ + +struct of_fan_attribute { + const char *name; + int (*set)(struct i2c_client*, int, long); +}; + +struct of_fan_attribute of_fan_attributes[] = { + {"fan-div", emc2305_set_fan_div}, + {"fan-target", emc2305_set_fan_target}, + {"pwm-enable", emc2305_set_pwm_enable}, + {NULL, NULL} +}; + +static int emc2305_config_of(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct device_node *node; + unsigned int fan_idx; + + if (!client->dev.of_node) + return -EINVAL; + if (!of_get_next_child(client->dev.of_node, NULL)) + return 0; + + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + data->fan[fan_idx].enabled = false; + + for_each_child_of_node(client->dev.of_node, node) { + const __be32 *property; + int len; + struct of_fan_attribute *attr; + + property = of_get_property(node, "reg", &len); + if (!property || len != sizeof(int)) { + dev_err(&client->dev, "invalid reg on %s\n", + node->full_name); + continue; + } + + fan_idx = be32_to_cpup(property); + if (fan_idx >= data->fans) { + dev_err(&client->dev, + "invalid fan index %d on %s\n", + fan_idx, node->full_name); + continue; + } + + data->fan[fan_idx].enabled = true; + + for (attr = of_fan_attributes; attr->name; ++attr) { + int status = 0; + long value; + property = of_get_property(node, attr->name, &len); + if (!property) + continue; + if (len != sizeof(int)) { + dev_err(&client->dev, "invalid %s on %s\n", + attr->name, node->full_name); + continue; + } + value = be32_to_cpup(property); + status = attr->set(client, fan_idx, value); + if (status == -EINVAL) { + dev_err(&client->dev, + "invalid value for %s on %s\n", + attr->name, node->full_name); + } + } + } + + return 0; +} + +#endif + +static void emc2305_get_config(struct i2c_client *client) +{ + int i; + struct emc2305_data *data = i2c_get_clientdata(client); + + for (i = 0; i < data->fans; ++i) { + data->fan[i].enabled = true; + emc2305_update_fan(client, i); + } + +#ifdef CONFIG_OF + emc2305_config_of(client); +#endif + +} + +static int +emc2305_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct emc2305_data *data; + int status; + int i; + int fan_idx; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct emc2305_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID); + switch (status) { + case 0x34: /* EMC2305 */ + data->fans = 5; + break; + case 0x35: /* EMC2303 */ + data->fans = 3; + break; + case 0x36: /* EMC2302 */ + data->fans = 2; + break; + case 0x37: /* EMC2301 */ + data->fans = 1; + break; + default: + if (status >= 0) + status = -EINVAL; + goto exit_free; + } + + emc2305_get_config(client); + + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) { + status = device_create_file(&client->dev, + &emc2305_attr_common[i].dev_attr); + if (status) + goto exit_remove; + } + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) { + if (!data->fan[fan_idx].enabled) + continue; + status = device_create_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + if (status) + goto exit_remove_fans; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove_fans; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove_fans: + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) + device_remove_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + +exit_remove: + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) + device_remove_file(&client->dev, + &emc2305_attr_common[i].dev_attr); +exit_free: + kfree(data); + return status; +} + +static const struct i2c_device_id emc2305_id[] = { + { "emc2305", 0 }, + { "emc2303", 0 }, + { "emc2302", 0 }, + { "emc2301", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2305_id); + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int +emc2305_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int manufacturer, product; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + manufacturer = + i2c_smbus_read_byte_data(new_client, REG_MANUFACTURER_ID); + if (manufacturer != 0x5D) + return -ENODEV; + + product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID); + + switch (product) { + case 0x34: + strlcpy(info->type, "emc2305", I2C_NAME_SIZE); + break; + case 0x35: + strlcpy(info->type, "emc2303", I2C_NAME_SIZE); + break; + case 0x36: + strlcpy(info->type, "emc2302", I2C_NAME_SIZE); + break; + case 0x37: + strlcpy(info->type, "emc2301", I2C_NAME_SIZE); + break; + default: + return -ENODEV; + } + + return 0; +} + +static struct i2c_driver emc2305_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", + }, + .probe = emc2305_probe, + .remove = emc2305_remove, + .id_table = emc2305_id, +/* + .detect = emc2305_detect, + .address_list = i2c_adresses, +*/ +}; + +module_i2c_driver(emc2305_driver); + +MODULE_AUTHOR("Reinhard Pfau "); +MODULE_DESCRIPTION("SMSC EMC2305 hwmon driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/leds-dx010.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/leds-dx010.c new file mode 100644 index 000000000000..fac8322f06b0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/leds-dx010.c @@ -0,0 +1,289 @@ +/* + * leds-dx010-status.c - Driver for Seastone DX010 front panel LEDs + * + * 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. + * + * 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 Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define DRIVER_NAME "leds_dx010" +#define FRONT_LED_STAT 0x303 + +static int dx010_led_blink_stat(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + unsigned char led; + + if (!(*delay_on == 0 && *delay_off == 0) && + !(*delay_on == 250 && *delay_off == 250) && + !(*delay_on == 500 && *delay_off == 500)) + return -EINVAL; + + led = inb(FRONT_LED_STAT); + led &= 0xfc; + + if ((*delay_on == 250) && (*delay_off == 250)) + led |= 0x02; + else if ((*delay_on == 500) && (*delay_off == 500)) + led |= 0x01; + + outb(led, FRONT_LED_STAT); + + return 0; +} + +static ssize_t dx010_led_blink_show_stat(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *leddev = dev_get_drvdata(dev); + unsigned char led; + const char *msg; + + led = inb(FRONT_LED_STAT); + led &= 0x03; + + switch (led) + { + case 0: + msg = "No blinking, turn on"; + break; + case 1: + msg = "1 Hz is blinking"; + break; + case 2: + msg = "4 Hz is blinking"; + break; + case 3: + msg = "No blinking, turn off"; + break; + default: + msg = "Unknown error"; + break; + } + + return sprintf(buf, "%s\n", msg); +} + +static ssize_t dx010_led_blink_store_stat(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + struct led_classdev *leddev = dev_get_drvdata(dev); + unsigned long blink_state; + unsigned char led; + + ret = kstrtoul(buf, 10, &blink_state); + if (ret) + return ret; + + led = inb(FRONT_LED_STAT); + led &= 0xfc; + + switch (blink_state) + { + case 0: + led |= 0x03; + break; + case 1: + break; + case 250: + led |= 0x02; + break; + case 500: + led |= 0x01; + break; + default: + return -EINVAL; + break; + } + + outb(led, FRONT_LED_STAT); + + return size; +} +static DEVICE_ATTR(blink, 0644, dx010_led_blink_show_stat, dx010_led_blink_store_stat); + +static void dx010_led_brightness_set_stat(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + unsigned char led; + + led = inb(FRONT_LED_STAT); + led &= 0xfc; + + if (!brightness) + led |= 0x03; + + outb( led, FRONT_LED_STAT); +} + +enum led_brightness dx010_led_brightness_get_p2(struct led_classdev *led_cdev) +{ + unsigned char led; + + led = inb(FRONT_LED_STAT); + + return (led & 0x08) ? LED_OFF : LED_FULL; +} + +static void dx010_led_brightness_set_p2(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + unsigned char led; + + led = inb(FRONT_LED_STAT); + led &= 0xf7; + + if (!brightness) + led |= 0x08; + + outb( led, FRONT_LED_STAT); +} + +enum led_brightness dx010_led_brightness_get_p1(struct led_classdev *led_cdev) +{ + unsigned char led; + + led = inb(FRONT_LED_STAT); + + return (led & 0x04) ? LED_OFF : LED_FULL; +} + +static void dx010_led_brightness_set_p1(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + unsigned char led; + + led = inb(FRONT_LED_STAT); + led &= 0xfb; + + if (!brightness) + led |= 0x04; + + outb( led, FRONT_LED_STAT); +} + +static struct led_classdev dx010_leds[] = { + { + .name = "dx010:green:p-1", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_get = dx010_led_brightness_get_p1, + .brightness_set = dx010_led_brightness_set_p1, + }, + { + .name = "dx010:green:p-2", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_get = dx010_led_brightness_get_p2, + .brightness_set = dx010_led_brightness_set_p2, + }, + { + .name = "dx010:green:stat", + .brightness = LED_OFF, + .max_brightness = 1, + .brightness_set = dx010_led_brightness_set_stat, + .blink_set = dx010_led_blink_stat, + .flags = LED_CORE_SUSPENDRESUME, + }, +}; + +static struct resource dx010_led_resources[] = { + { + .flags = IORESOURCE_IO, + }, +}; + +static void dx010_led_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device dx010_lpc_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(dx010_led_resources), + .resource = dx010_led_resources, + .dev = { + .release = dx010_led_dev_release, + } +}; + +static int dx010_led_drv_probe(struct platform_device *pdev) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(dx010_leds); i++) { + ret = led_classdev_register(&pdev->dev, &dx010_leds[i]); + if (ret < 0) + goto exit; + } + + ret = device_create_file(&pdev->dev, &dev_attr_blink); + if (ret) + { + for (i = 0; i < ARRAY_SIZE(dx010_leds); i++) + led_classdev_unregister(&dx010_leds[i]); + } +exit: + return ret; +} + +static int dx010_led_drv_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dx010_leds); i++) + led_classdev_unregister(&dx010_leds[i]); + + device_remove_file(&pdev->dev, &dev_attr_blink); + + return 0; +} + +static struct platform_driver dx010_led_drv = { + .probe = dx010_led_drv_probe, + .remove = __exit_p(dx010_led_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int dx010_led_init(void) +{ + platform_device_register(&dx010_lpc_dev); + platform_driver_register(&dx010_led_drv); + + return 0; +} + +void dx010_led_exit(void) +{ + platform_driver_unregister(&dx010_led_drv); + platform_device_unregister(&dx010_lpc_dev); +} + +module_init(dx010_led_init); +module_exit(dx010_led_exit); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_DESCRIPTION("Celestica SeaStone DX010 LEDs Front Panel Status Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/mc24lc64t.c new file mode 100644 index 000000000000..a391056d09a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/mc24lc64t.c @@ -0,0 +1,142 @@ +/* + * 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 + +struct mc24lc64t_data { + struct i2c_client *fake_client; + 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 struct bin_attribute mc24lc64t_bit_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = 65536, + .read = mc24lc64t_read, +}; + +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; + + drvdata->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); + if (!drvdata->fake_client) + return -ENOMEM; + + i2c_set_clientdata(client, drvdata); + mutex_init(&drvdata->update_lock); + + err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + if (err) + i2c_unregister_device(drvdata->fake_client); + + return err; +} + +static int mc24lc64t_remove(struct i2c_client *client) +{ + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + + i2c_unregister_device(drvdata->fake_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/dx010/modules/slx_gpio_ich.c b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/slx_gpio_ich.c new file mode 100644 index 000000000000..0d6ca743b1fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/modules/slx_gpio_ich.c @@ -0,0 +1,1003 @@ +/* Copyright (c) 2018 Dell Inc. + * slx_gpio_ich.c - ICH driver for Rangeley switches + * + * 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. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "slx-ich" + +#define C2000_PCU_DEVICE_ID 0x1f38 + +// GPIO registers +// GPIO Core Control/Access Registers in I/O Space +#define GPIO_SC_USE_SEL 0x0 +#define GPIO_SC_IO_SEL 0x4 +#define GPIO_SC_GP_LVL 0x8 +#define GPIO_SC_TPE 0xC +#define GPIO_SC_TNE 0x10 +#define GPIO_SC_TS 0x14 + +// GPIO SUS Control/Access Registers in I/O Space +#define GPIO_SUS_USE_SEL 0x80 +#define GPIO_SUS_IO_SEL 0x84 +#define GPIO_SUS_GP_LVL 0x88 +#define GPIO_SUS_TPE 0x8C +#define GPIO_SUS_TNE 0x90 +#define GPIO_SUS_TS 0x94 +#define GPIO_SUS_WAKE_EN 0x98 + +static const unsigned char c2000_gpio_regs[] = { + GPIO_SC_USE_SEL, + GPIO_SC_IO_SEL, + GPIO_SC_GP_LVL, + GPIO_SC_TPE, + GPIO_SC_TNE, + GPIO_SC_TS, + GPIO_SUS_USE_SEL, + GPIO_SUS_IO_SEL, + GPIO_SUS_GP_LVL, + GPIO_SUS_TPE, + GPIO_SUS_TNE, + GPIO_SUS_TS, + GPIO_SUS_WAKE_EN +}; + +#define GPIO_REG_LEN 0x4 + +#define GPIOS0_EN (1 << 0) +#define GPIOS1_EN (1 << 1) +#define GPIOS2_EN (1 << 2) +#define GPIOS3_EN (1 << 3) +#define GPIOS4_EN (1 << 4) +#define GPIOS5_EN (1 << 5) +#define GPIOS6_EN (1 << 6) +#define GPIOS7_EN (1 << 7) + +#define GPIOSUS0_EN (1 << 0) +#define GPIOSUS1_EN (1 << 1) +#define GPIOSUS2_EN (1 << 2) +#define GPIOSUS3_EN (1 << 3) +// GPIOSUS4_EN : unused +// GPIOSUS5_EN : unused +#define GPIOSUS6_EN (1 << 6) +#define GPIOSUS7_EN (1 << 7) + + +// GPE0a_EN - General Purpose Event 0 Enables +#define GPIO_GPE0a_EN_SUS0 (1 << 16) +#define GPIO_GPE0a_EN_SUS1 (1 << 17) +#define GPIO_GPE0a_EN_SUS2 (1 << 18) +#define GPIO_GPE0a_EN_SUS3 (1 << 19) +// GPIO_GPE0a_EN_SUS4 : unused +// GPIO_GPE0a_EN_SUS5 : unused +#define GPIO_GPE0a_EN_SUS6 (1 << 22) +#define GPIO_GPE0a_EN_SUS7 (1 << 23) + +#define GPIO_GPE0a_EN_CORE0 (1 << 24) +#define GPIO_GPE0a_EN_CORE1 (1 << 25) +#define GPIO_GPE0a_EN_CORE2 (1 << 26) +#define GPIO_GPE0a_EN_CORE3 (1 << 27) +#define GPIO_GPE0a_EN_CORE4 (1 << 28) +#define GPIO_GPE0a_EN_CORE5 (1 << 29) +#define GPIO_GPE0a_EN_CORE6 (1 << 30) +#define GPIO_GPE0a_EN_CORE7 (1 << 31) + +// GPE0a_STS - General Purpose Event 0 Status +// We're interested in only SUS6 for now +#define GPIO_GPE0a_STS_SUS6 (1 << 22) +#define GPIO_GPE0a_STS_SUS7 (1 << 23) + +// GPIO_ROUT - GPIO_ROUT Register +#define GPIO_ROUT_OFFSET_SUS0 0 +#define GPIO_ROUT_OFFSET_SUS1 2 +#define GPIO_ROUT_OFFSET_SUS2 4 +#define GPIO_ROUT_OFFSET_SUS3 6 +// GPIO_ROUT_OFFSET_SUS4 : unused +// GPIO_ROUT_OFFSET_SUS5 : unused +#define GPIO_ROUT_OFFSET_SUS6 12 +#define GPIO_ROUT_OFFSET_SUS7 14 + +#define GPIO_ROUT_OFFSET_CORE0 16 +#define GPIO_ROUT_OFFSET_CORE1 18 +#define GPIO_ROUT_OFFSET_CORE2 20 +#define GPIO_ROUT_OFFSET_CORE3 22 +#define GPIO_ROUT_OFFSET_CORE4 24 +#define GPIO_ROUT_OFFSET_CORE5 26 +#define GPIO_ROUT_OFFSET_CORE6 28 +#define GPIO_ROUT_OFFSET_CORE7 30 + +enum GPIO_ROUT { + GPIO_NO_EFFECT = 0, + GPIO_SMI, + GPIO_SCI, + GPIO_RESERVED +}; + +/* + * GPIO resources + * defined as in drivers/gpio/gpio-ich.c + */ +#define ICH_RES_GPIO 0 +#define ICH_RES_GPE0 1 +static struct resource gpio_ich_res[] = { + /* GPIO */ + { + .flags = IORESOURCE_IO, + }, + /* ACPI - GPE0 */ + { + .flags = IORESOURCE_IO, + }, +}; + +// ACPI registers +#define ACPI_GPE0a_STS 0x20 +#define ACPI_GPE0a_EN 0x28 + +// PMC registers +#define PMC_GPIO_ROUT 0x58 +#define PMC_REG_LEN 0x4 + +// lpc_ich_priv is derived from drivers/mfd/lpc_ich.c +struct lpc_ich_priv { + int chipset; + + int abase; /* ACPI base */ + int actrl_pbase; /* ACPI control or PMC base */ + int gbase; /* GPIO base */ + int gctrl; /* GPIO control */ + + int abase_save; /* Cached ACPI base value */ + int actrl_pbase_save; /* Cached ACPI control or PMC base value */ + int gctrl_save; /* Cached GPIO control value */ +}; + +#define ICH_RES_MEM_GCS_PMC 0 + +#define IO_REG_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start) +#define IO_REG_READ(reg, base_res) inl((reg) + (base_res)->start) + +struct resource pmc_res = {.flags = IORESOURCE_MEM,}; + +static struct kobject *slx_kobj; +static unsigned short force_id; +module_param(force_id, ushort, 0); + +struct slx_ich_data { + struct resource *gpio_base, *acpi_base, *pmc_base; + int gpio_alloc,pmc_alloc; + unsigned int int_gpio_sus6_count; +}; + +// GPIO sysfs attributes + +static ssize_t get_sc_use_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_USE_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_use_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_USE_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_io_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_IO_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_io_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_IO_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_lvl(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_GP_LVL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_lvl(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_GP_LVL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_tpe(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TPE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_tpe(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TPE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_tne(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TNE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_tne(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TNE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_ts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TS,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_ts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TS,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_use_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_USE_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_use_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_USE_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_io_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_IO_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_io_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_IO_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_lvl(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_GP_LVL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_lvl(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_GP_LVL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_tpe(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TPE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_tpe(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TPE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_tne(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TNE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_tne(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TNE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_ts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TS,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_ts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TS,ich_data->gpio_base); + + return count; +} + +static DEVICE_ATTR(sc_use_sel, S_IRUGO | S_IWUSR, get_sc_use_sel, set_sc_use_sel); +static DEVICE_ATTR(sc_io_sel, S_IRUGO | S_IWUSR, get_sc_io_sel, set_sc_io_sel); +static DEVICE_ATTR(sc_gp_lvl, S_IRUGO | S_IWUSR, get_sc_gp_lvl, set_sc_gp_lvl); +static DEVICE_ATTR(sc_gp_tpe, S_IRUGO | S_IWUSR, get_sc_gp_tpe, set_sc_gp_tpe); +static DEVICE_ATTR(sc_gp_tne, S_IRUGO | S_IWUSR, get_sc_gp_tne, set_sc_gp_tne); +static DEVICE_ATTR(sc_gp_ts, S_IRUGO | S_IWUSR, get_sc_gp_ts, set_sc_gp_ts); +static DEVICE_ATTR(sus_use_sel, S_IRUGO | S_IWUSR, get_sus_use_sel,set_sus_use_sel); +static DEVICE_ATTR(sus_io_sel, S_IRUGO | S_IWUSR, get_sus_io_sel, set_sus_io_sel); +static DEVICE_ATTR(sus_gp_lvl, S_IRUGO | S_IWUSR, get_sus_gp_lvl, set_sus_gp_lvl); +static DEVICE_ATTR(sus_gp_tpe, S_IRUGO | S_IWUSR, get_sus_gp_tpe, set_sus_gp_tpe); +static DEVICE_ATTR(sus_gp_tne, S_IRUGO | S_IWUSR, get_sus_gp_tne, set_sus_gp_tne); +static DEVICE_ATTR(sus_gp_ts, S_IRUGO | S_IWUSR, get_sus_gp_ts, set_sus_gp_ts); + +static struct attribute *gpio_attrs[] = { + &dev_attr_sc_use_sel.attr, + &dev_attr_sc_io_sel.attr, + &dev_attr_sc_gp_lvl.attr, + &dev_attr_sc_gp_tpe.attr, + &dev_attr_sc_gp_tne.attr, + &dev_attr_sc_gp_ts.attr, + &dev_attr_sus_use_sel.attr, + &dev_attr_sus_io_sel.attr, + &dev_attr_sus_gp_lvl.attr, + &dev_attr_sus_gp_tpe.attr, + &dev_attr_sus_gp_tne.attr, + &dev_attr_sus_gp_ts.attr, + NULL, +}; + +static struct attribute_group gpio_attrs_group= { + .attrs = gpio_attrs, +}; + +// ACPI sysfs attributes + +static ssize_t get_gpe0a_sts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(ACPI_GPE0a_STS,ich_data->acpi_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_gpe0a_sts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,ACPI_GPE0a_STS,ich_data->acpi_base); + + return count; +} + +static ssize_t get_gpe0a_en(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(ACPI_GPE0a_EN,ich_data->acpi_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_gpe0a_en(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,ACPI_GPE0a_EN,ich_data->acpi_base); + + return count; +} + +static DEVICE_ATTR(gpe0a_sts, S_IRUGO | S_IWUSR, get_gpe0a_sts, set_gpe0a_sts); +static DEVICE_ATTR(gpe0a_en, S_IRUGO | S_IWUSR, get_gpe0a_en, set_gpe0a_en); + +static struct attribute *acpi_attrs[] = { + &dev_attr_gpe0a_sts.attr, + &dev_attr_gpe0a_en.attr, + NULL, +}; + +static struct attribute_group acpi_attrs_group= { + .attrs = acpi_attrs, +}; + +static ssize_t get_gpio_rout(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = readl(ich_data->pmc_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +// PMC sysfs attributes + +static ssize_t set_gpio_rout(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + writel(devdata,ich_data->pmc_base); + + return count; +} + +static DEVICE_ATTR(gpio_rout, S_IRUGO | S_IWUSR, get_gpio_rout, set_gpio_rout); + +static struct attribute *pmc_attrs[] = { + &dev_attr_gpio_rout.attr, + NULL, +}; + +static struct attribute_group pmc_attrs_group= { + .attrs = pmc_attrs, +}; + +// SCI interrupt sysfs attributes + +static ssize_t get_sci_int_gpio_sus6(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = ich_data->int_gpio_sus6_count; + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sci_int_gpio_sus6(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + ich_data->int_gpio_sus6_count = devdata; + + return count; +} + +static DEVICE_ATTR(sci_int_gpio_sus6, S_IRUGO | S_IWUSR, get_sci_int_gpio_sus6, set_sci_int_gpio_sus6); + +static struct attribute *sci_attrs[] = { + &dev_attr_sci_int_gpio_sus6.attr, + NULL, +}; + +static struct attribute_group sci_attrs_group= { + .attrs = sci_attrs, +}; + +static u32 slx_ich_sci_handler(void *context) +{ + unsigned int data; + struct device *dev = (struct device *)context; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + if(!dev) return ACPI_INTERRUPT_NOT_HANDLED; + + ich_data = dev_get_platdata(dev); + if(!ich_data) return ACPI_INTERRUPT_NOT_HANDLED; + + data=IO_REG_READ(ACPI_GPE0a_STS,ich_data->acpi_base); + if(data & GPIO_GPE0a_STS_SUS6) { + // Clear the SUS6 status + IO_REG_WRITE(data,ACPI_GPE0a_STS,ich_data->acpi_base); + ich_data->int_gpio_sus6_count++; + // and notify the user space clients + sysfs_notify(&dev->kobj, NULL, "sci_int_gpio_sus6"); + return ACPI_INTERRUPT_HANDLED; + } + + return ACPI_INTERRUPT_NOT_HANDLED; +} + +/* + * Setup GPIO SUS6 to generate an SCI interrupt for optics detection + * This can be alternatively be setup using sysfs + */ +int setup_gpio_sus6_sci_interrupt(struct device *dev) +{ + int ret=0; + unsigned int data; + struct resource *acpi_base, *pmc_base, *gpio_base; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + + gpio_base = ich_data->gpio_base; + acpi_base = ich_data->acpi_base; + pmc_base = ich_data->pmc_base; + + // Enable GPIOSUS6_EN + data = IO_REG_READ(GPIO_SUS_USE_SEL,gpio_base); + data |= GPIOSUS6_EN; + IO_REG_WRITE(data,GPIO_SUS_USE_SEL,gpio_base); + + // GPIOSUS6_EN is input + data = IO_REG_READ(GPIO_SUS_IO_SEL,gpio_base); + data |= GPIOSUS6_EN; + IO_REG_WRITE(data,GPIO_SUS_IO_SEL,gpio_base); + + // Clear the positive edge for GPIOSUS6_EN + data = IO_REG_READ(GPIO_SUS_TPE,gpio_base); + data &= ~(GPIOSUS6_EN); + IO_REG_WRITE(data,GPIO_SUS_TPE,gpio_base); + + // Trigger on negative edge for GPIOSUS6_EN + data = IO_REG_READ(GPIO_SUS_TNE,gpio_base); + data |= GPIOSUS6_EN; + IO_REG_WRITE(data,GPIO_SUS_TNE,gpio_base); + + // Enable GPE for SUS6 to generate an SCI + data=IO_REG_READ(ACPI_GPE0a_EN,acpi_base); + data|=GPIO_GPE0a_EN_SUS6; + IO_REG_WRITE(data,ACPI_GPE0a_EN,acpi_base); + + data=readl(pmc_base); + data=(data & ~(0x3 << GPIO_ROUT_OFFSET_SUS6)) | (GPIO_SCI << GPIO_ROUT_OFFSET_SUS6); + writel(data,pmc_base); + + ret = acpi_install_sci_handler(slx_ich_sci_handler,(void*)dev); + if(ret) { + pr_info("slx_ich acpi_install_sci_handler failed %d\n",ret); + return ret; + } + + return ret; +} + +static int slx_ich_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + struct pci_dev *lpc_ich_dev; + struct lpc_ich_priv *priv; + struct resource *res; + unsigned int base_addr_cfg, base_addr; + int ret,i; + + // Get the PCU device + lpc_ich_dev=pci_get_device(PCI_VENDOR_ID_INTEL,C2000_PCU_DEVICE_ID,NULL); + priv=(struct lpc_ich_priv*) pci_get_drvdata(lpc_ich_dev); + if(!priv) { + pr_info("slx_ich: Unable to retrieve private data\n"); + return -ENODEV; + } + + // Retrieve the GPIO Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->gbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + pr_info("slx_ich I/O space for GPIO uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &gpio_ich_res[ICH_RES_GPIO]; + res->start = base_addr; + res->end = res->start + 0x9c - 1; + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("slx_ich gpio resource conflict ret %d\n",ret); + } + + ich_data->gpio_base=res; + // Request regions for GPIO registers + for(i=0; istart+c2000_gpio_regs[i],GPIO_REG_LEN, "slx_ich_gpio")) { + pr_info("slx_ich: request_region failed for GPIO : %x\n",(unsigned int) res->start+c2000_gpio_regs[i]); + ret = -EBUSY; + goto probe_err; + } + ich_data->gpio_alloc |= (1<kobj, &gpio_attrs_group); + if (ret) { + pr_info("slx_ich cannot create sysfs for GPIO %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + // Retrieve the ACPI Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->abase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + pr_info("slx_ich I/O space for ACPI uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &gpio_ich_res[ICH_RES_GPE0]; + res->start = base_addr; + res->end = base_addr + 0x40; + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("slx_ich acpi resource conflict ret %d\n",ret); + } + + // ACPI region is requested by pnp 00:01/ACPI GPE0_BLK + ich_data->acpi_base=res; + + /* Register sysfs hooks for ACPI */ + ret = sysfs_create_group(&dev->kobj, &acpi_attrs_group); + if (ret) { + pr_info("slx_ich cannot create sysfs for ACPI %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + // Retrieve the PMC Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->actrl_pbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0xfffffe00; + pr_info("slx_ich base_addr_cfg %x base_addr %x\n",(int)base_addr_cfg,(int)base_addr); + if (!base_addr) { + pr_info("slx_ich PMC space for GPIO uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &pmc_res; + res->start = base_addr + PMC_GPIO_ROUT; + res->end = base_addr + PMC_GPIO_ROUT + PMC_REG_LEN - 1; + pr_info("slx_ich pmc res_start:end %x:%x\n",(int)res->start,(int)res->end); + + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("slx_ich acpi resource conflict ret %d\n",ret); + } + + if (!request_mem_region(res->start,resource_size(res),"slx_ich_pmc")) { + pr_info("slx_ich pmc request_region failed\n"); + ret = -EBUSY; + goto probe_err; + } else { + ich_data->pmc_alloc=1; + } + + ich_data->pmc_base = ioremap(res->start, resource_size(res)); + if(!ich_data->pmc_base) { + pr_info("slx_ich pmc ioremap failed\n"); + ret = -ENOMEM; + goto probe_err; + } + + /* Register sysfs hooks for pmc */ + ret = sysfs_create_group(&dev->kobj, &pmc_attrs_group); + if (ret) { + pr_info("slx_ich cannot create sysfs for PMC %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + /* Register sysfs hooks for SCI interrupts*/ + ret = sysfs_create_group(&dev->kobj, &sci_attrs_group); + if (ret) { + pr_info("slx_ich cannot create sysfs for SCI %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + ret = setup_gpio_sus6_sci_interrupt(dev); + if (ret) { + pr_info("slx_ich unable to setup SCI interrupt %d\n",ret); + goto probe_err; + } + + return 0; + +probe_err: + pr_info("slx_ich slx_ich_probe failed with : %d\n",ret); + return ret; +} + +static int slx_ich_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct slx_ich_data *ich_data = dev_get_platdata(dev); + int i,ret; + + // Release GPIO regions + for(i=0; igpio_alloc & (1<gpio_base->start+c2000_gpio_regs[i], GPIO_REG_LEN); + } + } + + // Unmap and release PMC regions + if(ich_data->pmc_base) iounmap(ich_data->pmc_base); + if(ich_data->pmc_alloc) release_region(pmc_res.start, PMC_REG_LEN); + + ret = acpi_remove_sci_handler(slx_ich_sci_handler); + if(ret) { + pr_info("slx_ich acpi_remove_sci_handler failed %d\n",ret); + return ret; + } + + pr_info("slx_ich : slx_ich_remove done.\n"); + + return 0; +} + +static struct platform_driver slx_ich_driver= { + .driver = { + .name = DRV_NAME, + }, + .probe = slx_ich_probe, + .remove = slx_ich_remove, +}; + +static struct platform_device *pdev; + +static int __init slx_ich_init(void) +{ + int err; + struct slx_ich_data ich_data; + + memset(&ich_data, 0, sizeof(struct slx_ich_data)); + + err = platform_driver_register(&slx_ich_driver); + if (err) + goto exit; + + pdev = platform_device_alloc(DRV_NAME, 0); + if (!pdev) { + err = -ENOMEM; + pr_err("slx_ich: Device allocation failed\n"); + goto exit_unregister; + } + + err = platform_device_add_data(pdev, &ich_data, + sizeof(struct slx_ich_data)); + if (err) { + pr_err("slx_ich: Platform data allocation failed\n"); + goto exit_device_put; + } + + /* platform_device_add calls probe() */ + err = platform_device_add(pdev); + if (err) { + pr_err("slx_ich: Device addition failed (%d)\n", err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit_unregister: + platform_driver_unregister(&slx_ich_driver); +exit: + pr_err("slx_ich: slx_ich_init failed (%d)\n", err); + return err; +} + +static void __exit slx_ich_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&slx_ich_driver); + + /*Remove sysfs slx_kobj*/ + kobject_put(slx_kobj); +} + +MODULE_AUTHOR("Padmanabhan Narayanan"); +MODULE_DESCRIPTION("ICH driver for Rangeley switches"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + +module_init(slx_ich_init); +module_exit(slx_ich_exit); diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/dx010_check_qsfp.sh b/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/dx010_check_qsfp.sh new file mode 100644 index 000000000000..938b07952e0d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/dx010_check_qsfp.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +#Usage: +# TBD + +echo "Do we need to check qsfp?" + diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/fancontrol.service b/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/fancontrol.service new file mode 100644 index 000000000000..25b9f34df2d0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/fancontrol.service @@ -0,0 +1,12 @@ +[Unit] +Description=fan speed regulator +After=platform-modules-dx010.service +Before=pmon.service + +[Service] +ExecStart=-/etc/init.d/fancontrol.sh start +ExecStop=-/etc/init.d/fancontrol.sh stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/fancontrol.sh b/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/fancontrol.sh new file mode 100644 index 000000000000..21274ed6e27d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/fancontrol.sh @@ -0,0 +1,48 @@ +#! /bin/sh + +### BEGIN INIT INFO +# Provides: fancontrol +# Required-Start: $remote_fs +# Required-Stop: $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: +# Short-Description: fancontrol +# Description: fancontrol configuration selector +### END INIT INFO + +. /lib/lsb/init-functions + +[ -f /etc/default/rcS ] && . /etc/default/rcS +MAIN_CONF=/usr/share/sonic/device/x86_64-cel_seastone-r0/fancontrol +GPIO_DIR=/sys/class/gpio + +init() { + DIRGPIO_START=15 + BASE_GPIO=$(find $GPIO_DIR | grep gpiochip | grep -o '[[:digit:]]*') + FANDIR_GPIO_NUMBER=$((DIRGPIO_START + BASE_GPIO)) + FANDIR_VALUE=$(cat ${GPIO_DIR}/gpio${FANDIR_GPIO_NUMBER}/value) + DIRGPIO_START=$((DIRGPIO_START + 1)) + FANDIR=$([ $FANDIR_VALUE = 1 ] && echo "B2F" || echo "F2B") + CONF=${MAIN_CONF}-${FANDIR} + echo $FANDIR > /usr/share/sonic/device/x86_64-cel_seastone-r0/fan_airflow +} + +install() { + find /var/lib/docker/overlay*/ -path */sbin/fancontrol -exec cp /usr/local/bin/fancontrol {} \; +} + +case "$1" in +start) + init + cp $CONF $MAIN_CONF + ;; +install) + install + ;; +*) + log_success_msg "Usage: /etc/init.d/fancontrol {start} | {install}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/setup.py b/platform/broadcom/sonic-platform-modules-cel/dx010/setup.py new file mode 100644 index 000000000000..8183788184a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/setup.py @@ -0,0 +1,34 @@ +from setuptools import setup + +DEVICE_NAME = 'celestica' +HW_SKU = 'x86_64-cel_seastone-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/dx010/systemd/platform-modules-dx010.service b/platform/broadcom/sonic-platform-modules-cel/dx010/systemd/platform-modules-dx010.service new file mode 100644 index 000000000000..32827dcf0dec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/systemd/platform-modules-dx010.service @@ -0,0 +1,14 @@ + +[Unit] +Description=Celestica Seastone dx010 platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-dx010 start +ExecStop=-/etc/init.d/platform-modules-dx010 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/cfg/haliburton-modules.conf b/platform/broadcom/sonic-platform-modules-cel/haliburton/cfg/haliburton-modules.conf new file mode 100644 index 000000000000..66f002a5fc94 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/cfg/haliburton-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/haliburton/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/Makefile new file mode 100644 index 000000000000..415d1b5e62f0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/Makefile @@ -0,0 +1 @@ +obj-m := mc24lc64t.o emc2305.o smc.o hlx_gpio_ich.o dps200.o diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/dps200.c b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/dps200.c new file mode 100644 index 000000000000..6279ca70decf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/dps200.c @@ -0,0 +1,128 @@ +/* + * Hardware monitoring driver for Delta DPS200 + * + * (C) Copyright 2019, Celestica Inc. + * Author: Pradchaya Phucharoen + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pmbus.h" + + +static int dps200_read_word_data(struct i2c_client *client, int page, int reg) +{ + + if (reg >= PMBUS_VIRT_BASE || + reg == PMBUS_VOUT_OV_FAULT_LIMIT || + reg == PMBUS_VOUT_OV_WARN_LIMIT || + reg == PMBUS_VOUT_UV_WARN_LIMIT || + reg == PMBUS_VOUT_UV_FAULT_LIMIT || + reg == PMBUS_IOUT_OC_LV_FAULT_LIMIT || + reg == PMBUS_IOUT_UC_FAULT_LIMIT || + reg == PMBUS_UT_WARN_LIMIT || + reg == PMBUS_UT_FAULT_LIMIT || + reg == PMBUS_VIN_OV_FAULT_LIMIT || + reg == PMBUS_VIN_OV_WARN_LIMIT || + reg == PMBUS_IIN_OC_FAULT_LIMIT || + reg == PMBUS_POUT_MAX) + return -ENXIO; + + /* + * WARNING: The following feild have coinstant driver value. + * If the register are + * PMBUS_IOUT_OC_WARN_LIMIT or PMBUS_IOUT_OC_FAULT_LIMIT convert + * the constant value from linear to direct fomat. + */ + if (reg == PMBUS_IOUT_OC_WARN_LIMIT) + return 0xb4; + else if (reg == PMBUS_IOUT_OC_FAULT_LIMIT) + return 0xc8; + else + return pmbus_read_word_data(client, page, reg); +} + +/* + * Form DPS-200 datasheet the supported sensors format defined as: + * VOUT: direct mode with one decimal place. + * + * Other sensors: + * IOUT: direct mode with one decimal place. + * IOUT Limits: linear mode, which difference from IOUT. + * VIN, IIN, POWER, TEMP, & FAN: linear mode. + */ +static struct pmbus_driver_info dps200_info = { + .pages = 1, + .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT + | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT + | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT + | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 + | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP + | PMBUS_HAVE_STATUS_INPUT, + .format = { + [PSC_VOLTAGE_OUT] = direct, + [PSC_CURRENT_OUT] = direct, + }, + .m = { + [PSC_VOLTAGE_OUT] = 10, + [PSC_CURRENT_OUT] = 10, + }, + .b = { + [PSC_VOLTAGE_OUT] = 0, + [PSC_CURRENT_OUT] = 0, + }, + .R = { + [PSC_VOLTAGE_OUT] = 0, + [PSC_CURRENT_OUT] = 0, + }, + .read_word_data = &dps200_read_word_data, +}; + +static int pmbus_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + return pmbus_do_probe(client, id, &dps200_info); +} +/* user driver datat to pass the grpup */ +static const struct i2c_device_id dps200_id[] = { + {"dps200", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, dps200_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver dps200_driver = { + .driver = { + .name = "dps200", + }, + .probe = pmbus_probe, + .remove = pmbus_do_remove, + .id_table = dps200_id, +}; + +module_i2c_driver(dps200_driver); + +MODULE_AUTHOR("Pradchaya Phucharoen"); +MODULE_DESCRIPTION("PMBus driver for Delta DPS200"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/emc2305.c b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/emc2305.c new file mode 100644 index 000000000000..f08033e080ce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/emc2305.c @@ -0,0 +1,877 @@ +/* + * emc2305.c - hwmon driver for SMSC EMC2305 fan controller + * (C) Copyright 2013 + * Reinhard Pfau, Guntermann & Drunck GmbH + * + * Based on emc2103 driver by SMSC. + * + * Datasheet available at: + * http://www.smsc.com/Downloads/SMSC/Downloads_Public/Data_Sheets/2305.pdf + * + * Also supports the EMC2303 fan controller which has the same functionality + * and register layout as EMC2305, but supports only up to 3 fans instead of 5. + * + * Also supports EMC2302 (up to 2 fans) and EMC2301 (1 fan) fan controller. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * TODO / IDEAS: + * - expose more of the configuration and features + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Addresses scanned. + * Listed in the same order as they appear in the EMC2305, EMC2303 data sheets. + * + * Note: these are the I2C adresses which are possible for EMC2305 and EMC2303 + * chips. + * The EMC2302 supports only 0x2e (EMC2302-1) and 0x2f (EMC2302-2). + * The EMC2301 supports only 0x2f. + */ +static const unsigned short i2c_adresses[] = { + 0x2E, + 0x2F, + 0x2C, + 0x2D, + 0x4C, + 0x4D, + I2C_CLIENT_END +}; + +/* + * global registers + */ +enum { + REG_CONFIGURATION = 0x20, + REG_FAN_STATUS = 0x24, + REG_FAN_STALL_STATUS = 0x25, + REG_FAN_SPIN_STATUS = 0x26, + REG_DRIVE_FAIL_STATUS = 0x27, + REG_FAN_INTERRUPT_ENABLE = 0x29, + REG_PWM_POLARITY_CONFIG = 0x2a, + REG_PWM_OUTPUT_CONFIG = 0x2b, + REG_PWM_BASE_FREQ_1 = 0x2c, + REG_PWM_BASE_FREQ_2 = 0x2d, + REG_SOFTWARE_LOCK = 0xef, + REG_PRODUCT_FEATURES = 0xfc, + REG_PRODUCT_ID = 0xfd, + REG_MANUFACTURER_ID = 0xfe, + REG_REVISION = 0xff +}; + +/* + * fan specific registers + */ +enum { + REG_FAN_SETTING = 0x30, + REG_PWM_DIVIDE = 0x31, + REG_FAN_CONFIGURATION_1 = 0x32, + REG_FAN_CONFIGURATION_2 = 0x33, + REG_GAIN = 0x35, + REG_FAN_SPIN_UP_CONFIG = 0x36, + REG_FAN_MAX_STEP = 0x37, + REG_FAN_MINIMUM_DRIVE = 0x38, + REG_FAN_VALID_TACH_COUNT = 0x39, + REG_FAN_DRIVE_FAIL_BAND_LOW = 0x3a, + REG_FAN_DRIVE_FAIL_BAND_HIGH = 0x3b, + REG_TACH_TARGET_LOW = 0x3c, + REG_TACH_TARGET_HIGH = 0x3d, + REG_TACH_READ_HIGH = 0x3e, + REG_TACH_READ_LOW = 0x3f, +}; + +#define SEL_FAN(fan, reg) (reg + fan * 0x10) + +/* + * Factor by equations [2] and [3] from data sheet; valid for fans where the + * number of edges equals (poles * 2 + 1). + */ +#define FAN_RPM_FACTOR 3932160 + + +struct emc2305_fan_data { + bool enabled; + bool valid; + unsigned long last_updated; + bool rpm_control; + u8 multiplier; + u8 poles; + u16 target; + u16 tach; + u16 rpm_factor; + u8 pwm; +}; + +struct emc2305_data { + struct device *hwmon_dev; + struct mutex update_lock; + int fans; + struct emc2305_fan_data fan[5]; +}; + +static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output) +{ + int status = i2c_smbus_read_byte_data(client, i2c_reg); + if (status < 0) { + dev_warn(&client->dev, "reg 0x%02x, err %d\n", + i2c_reg, status); + } else { + *output = status; + } + return status; +} + +static void read_fan_from_i2c(struct i2c_client *client, u16 *output, + u8 hi_addr, u8 lo_addr) +{ + u8 high_byte, lo_byte; + + if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0) + return; + + if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0) + return; + + *output = ((u16)high_byte << 5) | (lo_byte >> 3); +} + +static void write_fan_target_to_i2c(struct i2c_client *client, int fan, + u16 new_target) +{ + const u8 lo_reg = SEL_FAN(fan, REG_TACH_TARGET_LOW); + const u8 hi_reg = SEL_FAN(fan, REG_TACH_TARGET_HIGH); + u8 high_byte = (new_target & 0x1fe0) >> 5; + u8 low_byte = (new_target & 0x001f) << 3; + i2c_smbus_write_byte_data(client, lo_reg, low_byte); + i2c_smbus_write_byte_data(client, hi_reg, high_byte); +} + +static void read_fan_config_from_i2c(struct i2c_client *client, int fan) + +{ + struct emc2305_data *data = i2c_get_clientdata(client); + u8 conf1; + + if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_CONFIGURATION_1), + &conf1) < 0) + return; + + data->fan[fan].rpm_control = (conf1 & 0x80) != 0; + data->fan[fan].multiplier = 1 << ((conf1 & 0x60) >> 5); + data->fan[fan].poles = ((conf1 & 0x18) >> 3) + 1; +} + +static void read_fan_setting(struct i2c_client *client, int fan) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + u8 setting; + + if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_SETTING), + &setting) < 0) + return; + + data->fan[fan].pwm = setting; +} + +static void read_fan_data(struct i2c_client *client, int fan_idx) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + + read_fan_from_i2c(client, &data->fan[fan_idx].target, + SEL_FAN(fan_idx, REG_TACH_TARGET_HIGH), + SEL_FAN(fan_idx, REG_TACH_TARGET_LOW)); + read_fan_from_i2c(client, &data->fan[fan_idx].tach, + SEL_FAN(fan_idx, REG_TACH_READ_HIGH), + SEL_FAN(fan_idx, REG_TACH_READ_LOW)); +} + +static struct emc2305_fan_data * +emc2305_update_fan(struct i2c_client *client, int fan_idx) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan_data = &data->fan[fan_idx]; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) + || !fan_data->valid) { + read_fan_config_from_i2c(client, fan_idx); + read_fan_data(client, fan_idx); + read_fan_setting(client, fan_idx); + fan_data->valid = true; + fan_data->last_updated = jiffies; + } + + mutex_unlock(&data->update_lock); + return fan_data; +} + +static struct emc2305_fan_data * +emc2305_update_device_fan(struct device *dev, struct device_attribute *da) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + + return emc2305_update_fan(client, fan_idx); +} + +/* + * set/ config functions + */ + +/* + * Note: we also update the fan target here, because its value is + * determined in part by the fan clock divider. This follows the principle + * of least surprise; the user doesn't expect the fan target to change just + * because the divider changed. + */ +static int +emc2305_set_fan_div(struct i2c_client *client, int fan_idx, long new_div) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); + int new_range_bits, old_div = 8 / fan->multiplier; + int status = 0; + + if (new_div == old_div) /* No change */ + return 0; + + switch (new_div) { + case 1: + new_range_bits = 3; + break; + case 2: + new_range_bits = 2; + break; + case 4: + new_range_bits = 1; + break; + case 8: + new_range_bits = 0; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + status = i2c_smbus_read_byte_data(client, reg_conf1); + if (status < 0) { + dev_dbg(&client->dev, "reg 0x%02x, err %d\n", + reg_conf1, status); + status = -EIO; + goto exit_unlock; + } + status &= 0x9F; + status |= (new_range_bits << 5); + status = i2c_smbus_write_byte_data(client, reg_conf1, status); + if (status < 0) { + status = -EIO; + goto exit_invalidate; + } + + fan->multiplier = 8 / new_div; + + /* update fan target if high byte is not disabled */ + if ((fan->target & 0x1fe0) != 0x1fe0) { + u16 new_target = (fan->target * old_div) / new_div; + fan->target = min_t(u16, new_target, 0x1fff); + write_fan_target_to_i2c(client, fan_idx, fan->target); + } + +exit_invalidate: + /* invalidate fan data to force re-read from hardware */ + fan->valid = false; +exit_unlock: + mutex_unlock(&data->update_lock); + return status; +} + +static int +emc2305_set_fan_target(struct i2c_client *client, int fan_idx, long rpm_target) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + + /* + * Datasheet states 16000 as maximum RPM target + * (table 2.2 and section 4.3) + */ + if ((rpm_target < 0) || (rpm_target > 16000)) + return -EINVAL; + + mutex_lock(&data->update_lock); + + if (rpm_target == 0) + fan->target = 0x1fff; + else + fan->target = clamp_val( + (FAN_RPM_FACTOR * fan->multiplier) / rpm_target, + 0, 0x1fff); + + write_fan_target_to_i2c(client, fan_idx, fan->target); + + mutex_unlock(&data->update_lock); + return 0; +} + +static int +emc2305_set_pwm_enable(struct i2c_client *client, int fan_idx, long enable) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_fan_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); + int status = 0; + u8 conf_reg; + + mutex_lock(&data->update_lock); + switch (enable) { + case 0: + fan->rpm_control = false; + break; + case 3: + fan->rpm_control = true; + break; + default: + status = -EINVAL; + goto exit_unlock; + } + + status = read_u8_from_i2c(client, reg_fan_conf1, &conf_reg); + if (status < 0) { + status = -EIO; + goto exit_unlock; + } + + if (fan->rpm_control) + conf_reg |= 0x80; + else + conf_reg &= ~0x80; + + status = i2c_smbus_write_byte_data(client, reg_fan_conf1, conf_reg); + if (status < 0) + status = -EIO; + +exit_unlock: + mutex_unlock(&data->update_lock); + return status; +} + +static int +emc2305_set_pwm(struct i2c_client *client, int fan_idx, long pwm) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_fan_setting = SEL_FAN(fan_idx, REG_FAN_SETTING); + int status = 0; + + /* + * Datasheet states 255 as maximum PWM + * (section 5.7) + */ + if ((pwm < 0) || (pwm > 255)) + return -EINVAL; + + fan->pwm = pwm; + + mutex_lock(&data->update_lock); + + status = i2c_smbus_write_byte_data(client, reg_fan_setting, fan->pwm); + + mutex_unlock(&data->update_lock); + return status; +} +/* + * sysfs callback functions + * + * Note: + * Naming of the funcs is modelled after the naming scheme described in + * Documentation/hwmon/sysfs-interface: + * + * For a sysfs file _ the functions are named like this: + * the show function: show__ + * the store function: set__ + * For read only (RO) attributes of course only the show func is required. + * + * This convention allows us to define the sysfs attributes by using macros. + */ + +static ssize_t +show_fan_input(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int rpm = 0; + if (fan->tach != 0) + rpm = (FAN_RPM_FACTOR * fan->multiplier) / fan->tach; + return sprintf(buf, "%d\n", rpm); +} + +static ssize_t +show_fan_fault(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + bool fault = ((fan->tach & 0x1fe0) == 0x1fe0); + return sprintf(buf, "%d\n", fault ? 1 : 0); +} + +static ssize_t +show_fan_div(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int fan_div = 8 / fan->multiplier; + return sprintf(buf, "%d\n", fan_div); +} + +static ssize_t +set_fan_div(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long new_div; + int status; + + status = kstrtol(buf, 10, &new_div); + if (status < 0) + return -EINVAL; + + status = emc2305_set_fan_div(client, fan_idx, new_div); + if (status < 0) + return status; + + return count; +} + +static ssize_t +show_fan_target(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int rpm = 0; + + /* high byte of 0xff indicates disabled so return 0 */ + if ((fan->target != 0) && ((fan->target & 0x1fe0) != 0x1fe0)) + rpm = (FAN_RPM_FACTOR * fan->multiplier) + / fan->target; + + return sprintf(buf, "%d\n", rpm); +} + +static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long rpm_target; + int status; + + status = kstrtol(buf, 10, &rpm_target); + if (status < 0) + return -EINVAL; + + status = emc2305_set_fan_target(client, fan_idx, rpm_target); + if (status < 0) + return status; + + return count; +} + +static ssize_t +show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + return sprintf(buf, "%d\n", fan->rpm_control ? 3 : 0); +} + +static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long new_value; + int status; + + status = kstrtol(buf, 10, &new_value); + if (status < 0) + return -EINVAL; + status = emc2305_set_pwm_enable(client, fan_idx, new_value); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + return sprintf(buf, "%d\n", fan->pwm); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + unsigned long val; + int ret; + int status; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + if (val > 255) + return -EINVAL; + + status = emc2305_set_pwm(client, fan_idx, val); + return count; +} + +/* define a read only attribute */ +#define EMC2305_ATTR_RO(_type, _item, _num) \ + SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO, \ + show_## _type ## _ ## _item, NULL, _num - 1) + +/* define a read/write attribute */ +#define EMC2305_ATTR_RW(_type, _item, _num) \ + SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO | S_IWUSR, \ + show_## _type ##_ ## _item, \ + set_## _type ## _ ## _item, _num - 1) + +/* + * TODO: Ugly hack, but temporary as this whole logic needs + * to be rewritten as per standard HWMON sysfs registration + */ + +/* define a read/write attribute */ +#define EMC2305_ATTR_RW2(_type, _num) \ + SENSOR_ATTR(_type ## _num, S_IRUGO | S_IWUSR, \ + show_## _type, set_## _type, _num - 1) + +/* defines the attributes for a single fan */ +#define EMC2305_DEFINE_FAN_ATTRS(_num) \ + static const \ + struct sensor_device_attribute emc2305_attr_fan ## _num[] = { \ + EMC2305_ATTR_RO(fan, input, _num), \ + EMC2305_ATTR_RO(fan, fault, _num), \ + EMC2305_ATTR_RW(fan, div, _num), \ + EMC2305_ATTR_RW(fan, target, _num), \ + EMC2305_ATTR_RW(pwm, enable, _num), \ + EMC2305_ATTR_RW2(pwm, _num) \ + } + +#define EMC2305_NUM_FAN_ATTRS ARRAY_SIZE(emc2305_attr_fan1) + +/* common attributes for EMC2303 and EMC2305 */ +static const struct sensor_device_attribute emc2305_attr_common[] = { +}; + +/* fan attributes for the single fans */ +EMC2305_DEFINE_FAN_ATTRS(1); +EMC2305_DEFINE_FAN_ATTRS(2); +EMC2305_DEFINE_FAN_ATTRS(3); +EMC2305_DEFINE_FAN_ATTRS(4); +EMC2305_DEFINE_FAN_ATTRS(5); +EMC2305_DEFINE_FAN_ATTRS(6); + +/* fan attributes */ +static const struct sensor_device_attribute *emc2305_fan_attrs[] = { + emc2305_attr_fan1, + emc2305_attr_fan2, + emc2305_attr_fan3, + emc2305_attr_fan4, + emc2305_attr_fan5, +}; + +/* + * driver interface + */ + +static int emc2305_remove(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + int fan_idx, i; + + hwmon_device_unregister(data->hwmon_dev); + + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) + device_remove_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) + device_remove_file(&client->dev, + &emc2305_attr_common[i].dev_attr); + + kfree(data); + return 0; +} + + +#ifdef CONFIG_OF +/* + * device tree support + */ + +struct of_fan_attribute { + const char *name; + int (*set)(struct i2c_client*, int, long); +}; + +struct of_fan_attribute of_fan_attributes[] = { + {"fan-div", emc2305_set_fan_div}, + {"fan-target", emc2305_set_fan_target}, + {"pwm-enable", emc2305_set_pwm_enable}, + {NULL, NULL} +}; + +static int emc2305_config_of(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct device_node *node; + unsigned int fan_idx; + + if (!client->dev.of_node) + return -EINVAL; + if (!of_get_next_child(client->dev.of_node, NULL)) + return 0; + + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + data->fan[fan_idx].enabled = false; + + for_each_child_of_node(client->dev.of_node, node) { + const __be32 *property; + int len; + struct of_fan_attribute *attr; + + property = of_get_property(node, "reg", &len); + if (!property || len != sizeof(int)) { + dev_err(&client->dev, "invalid reg on %s\n", + node->full_name); + continue; + } + + fan_idx = be32_to_cpup(property); + if (fan_idx >= data->fans) { + dev_err(&client->dev, + "invalid fan index %d on %s\n", + fan_idx, node->full_name); + continue; + } + + data->fan[fan_idx].enabled = true; + + for (attr = of_fan_attributes; attr->name; ++attr) { + int status = 0; + long value; + property = of_get_property(node, attr->name, &len); + if (!property) + continue; + if (len != sizeof(int)) { + dev_err(&client->dev, "invalid %s on %s\n", + attr->name, node->full_name); + continue; + } + value = be32_to_cpup(property); + status = attr->set(client, fan_idx, value); + if (status == -EINVAL) { + dev_err(&client->dev, + "invalid value for %s on %s\n", + attr->name, node->full_name); + } + } + } + + return 0; +} + +#endif + +static void emc2305_get_config(struct i2c_client *client) +{ + int i; + struct emc2305_data *data = i2c_get_clientdata(client); + + for (i = 0; i < data->fans; ++i) { + data->fan[i].enabled = true; + emc2305_update_fan(client, i); + } + +#ifdef CONFIG_OF + emc2305_config_of(client); +#endif + +} + +static int +emc2305_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct emc2305_data *data; + int status; + int i; + int fan_idx; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct emc2305_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID); + switch (status) { + case 0x34: /* EMC2305 */ + data->fans = 5; + break; + case 0x35: /* EMC2303 */ + data->fans = 3; + break; + case 0x36: /* EMC2302 */ + data->fans = 2; + break; + case 0x37: /* EMC2301 */ + data->fans = 1; + break; + default: + if (status >= 0) + status = -EINVAL; + goto exit_free; + } + + emc2305_get_config(client); + + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) { + status = device_create_file(&client->dev, + &emc2305_attr_common[i].dev_attr); + if (status) + goto exit_remove; + } + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) { + if (!data->fan[fan_idx].enabled) + continue; + status = device_create_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + if (status) + goto exit_remove_fans; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove_fans; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove_fans: + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) + device_remove_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + +exit_remove: + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) + device_remove_file(&client->dev, + &emc2305_attr_common[i].dev_attr); +exit_free: + kfree(data); + return status; +} + +static const struct i2c_device_id emc2305_id[] = { + { "emc2305", 0 }, + { "emc2303", 0 }, + { "emc2302", 0 }, + { "emc2301", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2305_id); + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int +emc2305_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int manufacturer, product; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + manufacturer = + i2c_smbus_read_byte_data(new_client, REG_MANUFACTURER_ID); + if (manufacturer != 0x5D) + return -ENODEV; + + product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID); + + switch (product) { + case 0x34: + strlcpy(info->type, "emc2305", I2C_NAME_SIZE); + break; + case 0x35: + strlcpy(info->type, "emc2303", I2C_NAME_SIZE); + break; + case 0x36: + strlcpy(info->type, "emc2302", I2C_NAME_SIZE); + break; + case 0x37: + strlcpy(info->type, "emc2301", I2C_NAME_SIZE); + break; + default: + return -ENODEV; + } + + return 0; +} + +static struct i2c_driver emc2305_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", + }, + .probe = emc2305_probe, + .remove = emc2305_remove, + .id_table = emc2305_id, +/* + .detect = emc2305_detect, + .address_list = i2c_adresses, +*/ +}; + +module_i2c_driver(emc2305_driver); + +MODULE_AUTHOR("Reinhard Pfau "); +MODULE_DESCRIPTION("SMSC EMC2305 hwmon driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/hlx_gpio_ich.c b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/hlx_gpio_ich.c new file mode 100644 index 000000000000..3667da0db847 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/hlx_gpio_ich.c @@ -0,0 +1,1047 @@ +/* Copyright (c) 2018 Dell Inc. + * gpio_ich.c - ICH driver for Rangeley switches + * + * 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. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "hlx-ich" + +#define C2000_PCU_DEVICE_ID 0x1f38 + +// GPIO registers +// GPIO Core Control/Access Registers in I/O Space +#define GPIO_SC_USE_SEL 0x0 +#define GPIO_SC_IO_SEL 0x4 +#define GPIO_SC_GP_LVL 0x8 +#define GPIO_SC_TPE 0xC +#define GPIO_SC_TNE 0x10 +#define GPIO_SC_TS 0x14 + +// GPIO SUS Control/Access Registers in I/O Space +#define GPIO_SUS_USE_SEL 0x80 +#define GPIO_SUS_IO_SEL 0x84 +#define GPIO_SUS_GP_LVL 0x88 +#define GPIO_SUS_TPE 0x8C +#define GPIO_SUS_TNE 0x90 +#define GPIO_SUS_TS 0x94 +#define GPIO_SUS_WAKE_EN 0x98 + +static const unsigned char c2000_gpio_regs[] = { + GPIO_SC_USE_SEL, + GPIO_SC_IO_SEL, + GPIO_SC_GP_LVL, + GPIO_SC_TPE, + GPIO_SC_TNE, + GPIO_SC_TS, + GPIO_SUS_USE_SEL, + GPIO_SUS_IO_SEL, + GPIO_SUS_GP_LVL, + GPIO_SUS_TPE, + GPIO_SUS_TNE, + GPIO_SUS_TS, + GPIO_SUS_WAKE_EN +}; + +#define GPIO_REG_LEN 0x4 + +#define GPIOS0_EN (1 << 0) +#define GPIOS1_EN (1 << 1) +#define GPIOS2_EN (1 << 2) +#define GPIOS3_EN (1 << 3) +#define GPIOS4_EN (1 << 4) +#define GPIOS5_EN (1 << 5) +#define GPIOS6_EN (1 << 6) +#define GPIOS7_EN (1 << 7) + +#define GPIOSUS0_EN (1 << 0) +#define GPIOSUS1_EN (1 << 1) +#define GPIOSUS2_EN (1 << 2) +#define GPIOSUS3_EN (1 << 3) +// GPIOSUS4_EN : unused +// GPIOSUS5_EN : unused +#define GPIOSUS6_EN (1 << 6) +#define GPIOSUS7_EN (1 << 7) + + +// GPE0a_EN - General Purpose Event 0 Enables +#define GPIO_GPE0a_EN_SUS0 (1 << 16) +#define GPIO_GPE0a_EN_SUS1 (1 << 17) +#define GPIO_GPE0a_EN_SUS2 (1 << 18) +#define GPIO_GPE0a_EN_SUS3 (1 << 19) +// GPIO_GPE0a_EN_SUS4 : unused +// GPIO_GPE0a_EN_SUS5 : unused +#define GPIO_GPE0a_EN_SUS6 (1 << 22) +#define GPIO_GPE0a_EN_SUS7 (1 << 23) + +#define GPIO_GPE0a_EN_CORE0 (1 << 24) +#define GPIO_GPE0a_EN_CORE1 (1 << 25) +#define GPIO_GPE0a_EN_CORE2 (1 << 26) +#define GPIO_GPE0a_EN_CORE3 (1 << 27) +#define GPIO_GPE0a_EN_CORE4 (1 << 28) +#define GPIO_GPE0a_EN_CORE5 (1 << 29) +#define GPIO_GPE0a_EN_CORE6 (1 << 30) +#define GPIO_GPE0a_EN_CORE7 (1 << 31) + +// GPE0a_STS - General Purpose Event 0 Status +// We're interested in only SUS6 for now +#define GPIO_GPE0a_STS_SUS6 (1 << 22) +#define GPIO_GPE0a_STS_SUS7 (1 << 23) + +// GPIO_ROUT - GPIO_ROUT Register +#define GPIO_ROUT_OFFSET_SUS0 0 +#define GPIO_ROUT_OFFSET_SUS1 2 +#define GPIO_ROUT_OFFSET_SUS2 4 +#define GPIO_ROUT_OFFSET_SUS3 6 +// GPIO_ROUT_OFFSET_SUS4 : unused +// GPIO_ROUT_OFFSET_SUS5 : unused +#define GPIO_ROUT_OFFSET_SUS6 12 +#define GPIO_ROUT_OFFSET_SUS7 14 + +#define GPIO_ROUT_OFFSET_CORE0 16 +#define GPIO_ROUT_OFFSET_CORE1 18 +#define GPIO_ROUT_OFFSET_CORE2 20 +#define GPIO_ROUT_OFFSET_CORE3 22 +#define GPIO_ROUT_OFFSET_CORE4 24 +#define GPIO_ROUT_OFFSET_CORE5 26 +#define GPIO_ROUT_OFFSET_CORE6 28 +#define GPIO_ROUT_OFFSET_CORE7 30 + +enum GPIO_ROUT { + GPIO_NO_EFFECT = 0, + GPIO_SMI, + GPIO_SCI, + GPIO_RESERVED +}; + +/* + * GPIO resources + * defined as in drivers/gpio/gpio-ich.c + */ +#define ICH_RES_GPIO 0 +#define ICH_RES_GPE0 1 +static struct resource gpio_ich_res[] = { + /* GPIO */ + { + .flags = IORESOURCE_IO, + }, + /* ACPI - GPE0 */ + { + .flags = IORESOURCE_IO, + }, +}; + +// ACPI registers +#define ACPI_GPE0a_STS 0x20 +#define ACPI_GPE0a_EN 0x28 + +// PMC registers +#define PMC_GPIO_ROUT 0x58 +#define PMC_REG_LEN 0x4 + +// lpc_ich_priv is derived from drivers/mfd/lpc_ich.c +struct lpc_ich_priv { + int chipset; + + int abase; /* ACPI base */ + int actrl_pbase; /* ACPI control or PMC base */ + int gbase; /* GPIO base */ + int gctrl; /* GPIO control */ + + int abase_save; /* Cached ACPI base value */ + int actrl_pbase_save; /* Cached ACPI control or PMC base value */ + int gctrl_save; /* Cached GPIO control value */ +}; + +#define ICH_RES_MEM_GCS_PMC 0 + +#define IO_REG_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start) +#define IO_REG_READ(reg, base_res) inl((reg) + (base_res)->start) + +struct resource pmc_res = {.flags = IORESOURCE_MEM,}; + +static struct kobject *hlx_kobj; +static unsigned short force_id; +module_param(force_id, ushort, 0); + +#define SMF_REG_ADDR 0x200 +#define SIO_REG_DEVID 0x1 +#define SIO_Z9100_ID 0x1 +#define SIO_S6100_ID 0x2 +#define SIO_S4200_ID 0x3 +#define SIO_S5148_ID 0x4 +#define SIO_E1031_ID 0x5a + +enum kinds { + z9100smf, s6100smf, e1031 +}; + +struct hlx_ich_data { + enum kinds kind; + struct resource *gpio_base, *acpi_base, *pmc_base; + int gpio_alloc,pmc_alloc; + unsigned int int_gpio_sus7_count; +}; + +// GPIO sysfs attributes + +static ssize_t get_sc_use_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_USE_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_use_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_USE_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_io_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_IO_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_io_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_IO_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_lvl(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_GP_LVL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_lvl(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_GP_LVL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_tpe(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TPE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_tpe(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TPE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_tne(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TNE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_tne(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TNE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_ts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TS,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_ts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TS,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_use_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_USE_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_use_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_USE_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_io_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_IO_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_io_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_IO_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_lvl(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_GP_LVL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_lvl(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_GP_LVL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_tpe(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TPE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_tpe(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TPE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_tne(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TNE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_tne(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TNE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_ts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TS,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_ts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TS,ich_data->gpio_base); + + return count; +} + +static DEVICE_ATTR(sc_use_sel, S_IRUGO | S_IWUSR, get_sc_use_sel, set_sc_use_sel); +static DEVICE_ATTR(sc_io_sel, S_IRUGO | S_IWUSR, get_sc_io_sel, set_sc_io_sel); +static DEVICE_ATTR(sc_gp_lvl, S_IRUGO | S_IWUSR, get_sc_gp_lvl, set_sc_gp_lvl); +static DEVICE_ATTR(sc_gp_tpe, S_IRUGO | S_IWUSR, get_sc_gp_tpe, set_sc_gp_tpe); +static DEVICE_ATTR(sc_gp_tne, S_IRUGO | S_IWUSR, get_sc_gp_tne, set_sc_gp_tne); +static DEVICE_ATTR(sc_gp_ts, S_IRUGO | S_IWUSR, get_sc_gp_ts, set_sc_gp_ts); +static DEVICE_ATTR(sus_use_sel, S_IRUGO | S_IWUSR, get_sus_use_sel,set_sus_use_sel); +static DEVICE_ATTR(sus_io_sel, S_IRUGO | S_IWUSR, get_sus_io_sel, set_sus_io_sel); +static DEVICE_ATTR(sus_gp_lvl, S_IRUGO | S_IWUSR, get_sus_gp_lvl, set_sus_gp_lvl); +static DEVICE_ATTR(sus_gp_tpe, S_IRUGO | S_IWUSR, get_sus_gp_tpe, set_sus_gp_tpe); +static DEVICE_ATTR(sus_gp_tne, S_IRUGO | S_IWUSR, get_sus_gp_tne, set_sus_gp_tne); +static DEVICE_ATTR(sus_gp_ts, S_IRUGO | S_IWUSR, get_sus_gp_ts, set_sus_gp_ts); + +static struct attribute *gpio_attrs[] = { + &dev_attr_sc_use_sel.attr, + &dev_attr_sc_io_sel.attr, + &dev_attr_sc_gp_lvl.attr, + &dev_attr_sc_gp_tpe.attr, + &dev_attr_sc_gp_tne.attr, + &dev_attr_sc_gp_ts.attr, + &dev_attr_sus_use_sel.attr, + &dev_attr_sus_io_sel.attr, + &dev_attr_sus_gp_lvl.attr, + &dev_attr_sus_gp_tpe.attr, + &dev_attr_sus_gp_tne.attr, + &dev_attr_sus_gp_ts.attr, + NULL, +}; + +static struct attribute_group gpio_attrs_group= { + .attrs = gpio_attrs, +}; + +// ACPI sysfs attributes + +static ssize_t get_gpe0a_sts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(ACPI_GPE0a_STS,ich_data->acpi_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_gpe0a_sts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,ACPI_GPE0a_STS,ich_data->acpi_base); + + return count; +} + +static ssize_t get_gpe0a_en(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(ACPI_GPE0a_EN,ich_data->acpi_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_gpe0a_en(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,ACPI_GPE0a_EN,ich_data->acpi_base); + + return count; +} + +static DEVICE_ATTR(gpe0a_sts, S_IRUGO | S_IWUSR, get_gpe0a_sts, set_gpe0a_sts); +static DEVICE_ATTR(gpe0a_en, S_IRUGO | S_IWUSR, get_gpe0a_en, set_gpe0a_en); + +static struct attribute *acpi_attrs[] = { + &dev_attr_gpe0a_sts.attr, + &dev_attr_gpe0a_en.attr, + NULL, +}; + +static struct attribute_group acpi_attrs_group= { + .attrs = acpi_attrs, +}; + +static ssize_t get_gpio_rout(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = readl(ich_data->pmc_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +// PMC sysfs attributes + +static ssize_t set_gpio_rout(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + writel(devdata,ich_data->pmc_base); + + return count; +} + +static DEVICE_ATTR(gpio_rout, S_IRUGO | S_IWUSR, get_gpio_rout, set_gpio_rout); + +static struct attribute *pmc_attrs[] = { + &dev_attr_gpio_rout.attr, + NULL, +}; + +static struct attribute_group pmc_attrs_group= { + .attrs = pmc_attrs, +}; + +// SCI interrupt sysfs attributes + +static ssize_t get_sci_int_gpio_sus7(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = ich_data->int_gpio_sus7_count; + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sci_int_gpio_sus7(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + ich_data->int_gpio_sus7_count = devdata; + + return count; +} + +static DEVICE_ATTR(sci_int_gpio_sus7, S_IRUGO | S_IWUSR, get_sci_int_gpio_sus7, set_sci_int_gpio_sus7); + +static struct attribute *sci_attrs[] = { + &dev_attr_sci_int_gpio_sus7.attr, + NULL, +}; + +static struct attribute_group sci_attrs_group= { + .attrs = sci_attrs, +}; + +static u32 hlx_ich_sci_handler(void *context) +{ + unsigned int data; + struct device *dev = (struct device *)context; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + if(!dev) return ACPI_INTERRUPT_NOT_HANDLED; + + ich_data = dev_get_platdata(dev); + if(!ich_data) return ACPI_INTERRUPT_NOT_HANDLED; + + data=IO_REG_READ(ACPI_GPE0a_STS,ich_data->acpi_base); + if(data & GPIO_GPE0a_STS_SUS7) { + // Clear the SUS7 status + IO_REG_WRITE(data,ACPI_GPE0a_STS,ich_data->acpi_base); + ich_data->int_gpio_sus7_count++; + // and notify the user space clients + sysfs_notify(&dev->kobj, NULL, "sci_int_gpio_sus7"); + return ACPI_INTERRUPT_HANDLED; + } + + return ACPI_INTERRUPT_NOT_HANDLED; +} + +/* + * Setup GPIO SUS7 to generate an SCI interrupt for optics detection + * This can be alternatively be setup using sysfs + */ +int setup_gpio_sus7_sci_interrupt(struct device *dev) +{ + int ret=0; + unsigned int data; + struct resource *acpi_base, *pmc_base, *gpio_base; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + + gpio_base = ich_data->gpio_base; + acpi_base = ich_data->acpi_base; + pmc_base = ich_data->pmc_base; + + // Enable GPIOSUS7_EN + data = IO_REG_READ(GPIO_SUS_USE_SEL,gpio_base); + data |= GPIOSUS7_EN; + IO_REG_WRITE(data,GPIO_SUS_USE_SEL,gpio_base); + + // GPIOSUS7_EN is input + data = IO_REG_READ(GPIO_SUS_IO_SEL,gpio_base); + data |= GPIOSUS7_EN; + IO_REG_WRITE(data,GPIO_SUS_IO_SEL,gpio_base); + + // Trigger on positive edge for GPIOSUS7_EN + data = IO_REG_READ(GPIO_SUS_TPE,gpio_base); + data |= GPIOSUS7_EN; + IO_REG_WRITE(data,GPIO_SUS_TPE,gpio_base); + + // Enable GPE for SUS7 to generate an SCI + data=IO_REG_READ(ACPI_GPE0a_EN,acpi_base); + data|=GPIO_GPE0a_EN_SUS7; + IO_REG_WRITE(data,ACPI_GPE0a_EN,acpi_base); + + data=readl(pmc_base); + data=(data & ~(0x3 << GPIO_ROUT_OFFSET_SUS7)) | (GPIO_SCI << GPIO_ROUT_OFFSET_SUS7); + writel(data,pmc_base); + + ret = acpi_install_sci_handler(hlx_ich_sci_handler,(void*)dev); + if(ret) { + pr_info("hlx_ich acpi_install_sci_handler failed %d\n",ret); + return ret; + } + + return ret; +} + +static int hlx_ich_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + struct pci_dev *lpc_ich_dev; + struct lpc_ich_priv *priv; + struct resource *res; + unsigned int base_addr_cfg, base_addr; + int ret,i; + + // Get the PCU device + lpc_ich_dev=pci_get_device(PCI_VENDOR_ID_INTEL,C2000_PCU_DEVICE_ID,NULL); + priv=(struct lpc_ich_priv*) pci_get_drvdata(lpc_ich_dev); + if(!priv) { + pr_info("hlx_ich: Unable to retrieve private data\n"); + return -ENODEV; + } + + // Retrieve the GPIO Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->gbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + pr_info("hlx_ich I/O space for GPIO uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &gpio_ich_res[ICH_RES_GPIO]; + res->start = base_addr; + res->end = res->start + 0x9c - 1; + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("hlx_ich gpio resource conflict ret %d\n",ret); + } + + ich_data->gpio_base=res; + // Request regions for GPIO registers + for(i=0; istart+c2000_gpio_regs[i],GPIO_REG_LEN, "hlx_ich_gpio")) { + pr_info("hlx_ich: request_region failed for GPIO : %x\n",(unsigned int) res->start+c2000_gpio_regs[i]); + ret = -EBUSY; + goto probe_err; + } + ich_data->gpio_alloc |= (1<kobj, &gpio_attrs_group); + if (ret) { + pr_info("hlx_ich cannot create sysfs for GPIO %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + // Retrieve the ACPI Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->abase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + pr_info("hlx_ich I/O space for ACPI uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &gpio_ich_res[ICH_RES_GPE0]; + res->start = base_addr; + res->end = base_addr + 0x40; + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("hlx_ich acpi resource conflict ret %d\n",ret); + } + + // ACPI region is requested by pnp 00:01/ACPI GPE0_BLK + ich_data->acpi_base=res; + + /* Register sysfs hooks for ACPI */ + ret = sysfs_create_group(&dev->kobj, &acpi_attrs_group); + if (ret) { + pr_info("hlx_ich cannot create sysfs for ACPI %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + // Retrieve the PMC Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->actrl_pbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0xfffffe00; + pr_info("hlx_ich base_addr_cfg %x base_addr %x\n",(int)base_addr_cfg,(int)base_addr); + if (!base_addr) { + pr_info("hlx_ich PMC space for GPIO uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &pmc_res; + res->start = base_addr + PMC_GPIO_ROUT; + res->end = base_addr + PMC_GPIO_ROUT + PMC_REG_LEN - 1; + pr_info("hlx_ich pmc res_start:end %x:%x\n",(int)res->start,(int)res->end); + + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("hlx_ich acpi resource conflict ret %d\n",ret); + } + + if (!request_mem_region(res->start,resource_size(res),"hlx_ich_pmc")) { + pr_info("hlx_ich pmc request_region failed\n"); + ret = -EBUSY; + goto probe_err; + } else { + ich_data->pmc_alloc=1; + } + + ich_data->pmc_base = ioremap(res->start, resource_size(res)); + if(!ich_data->pmc_base) { + pr_info("hlx_ich pmc ioremap failed\n"); + ret = -ENOMEM; + goto probe_err; + } + + /* Register sysfs hooks for pmc */ + ret = sysfs_create_group(&dev->kobj, &pmc_attrs_group); + if (ret) { + pr_info("hlx_ich cannot create sysfs for PMC %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + /* Register sysfs hooks for SCI interrupts*/ + ret = sysfs_create_group(&dev->kobj, &sci_attrs_group); + if (ret) { + pr_info("hlx_ich cannot create sysfs for SCI %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + if((ich_data->kind == z9100smf) || (ich_data->kind == s6100smf) || (ich_data->kind == e1031)) { + ret = setup_gpio_sus7_sci_interrupt(dev); + if (ret) { + pr_info("hlx_ich unable to setup SCI interrupt %d\n",ret); + goto probe_err; + } + } + + return 0; + +probe_err: + pr_info("hlx_ich hlx_ich_probe failed with : %d\n",ret); + return ret; +} + +static int hlx_ich_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct hlx_ich_data *ich_data = dev_get_platdata(dev); + int i,ret; + + // Release GPIO regions + for(i=0; igpio_alloc & (1<gpio_base->start+c2000_gpio_regs[i], GPIO_REG_LEN); + } + } + + // Unmap and release PMC regions + if(ich_data->pmc_base) iounmap(ich_data->pmc_base); + if(ich_data->pmc_alloc) release_region(pmc_res.start, PMC_REG_LEN); + + ret = acpi_remove_sci_handler(hlx_ich_sci_handler); + if(ret) { + pr_info("hlx_ich acpi_remove_sci_handler failed %d\n",ret); + return ret; + } + + pr_info("hlx_ich : hlx_ich_remove done.\n"); + + return 0; +} + +static struct platform_driver hlx_ich_driver= { + .driver = { + .name = DRV_NAME, + }, + .probe = hlx_ich_probe, + .remove = hlx_ich_remove, +}; + +int __init +init_ich_data(int smf_address, struct hlx_ich_data *ich_data) +{ + int val; + + memset(ich_data, 0, sizeof(struct hlx_ich_data)); + + if (force_id) + val = force_id; + else + val = inb(smf_address + SIO_REG_DEVID); + + switch (val) { + case SIO_Z9100_ID: + ich_data->kind = z9100smf; + break; + case SIO_S6100_ID: + ich_data->kind = s6100smf; + break; + case SIO_E1031_ID: + ich_data->kind = e1031; + break; + default: + if (val != 0xffff) + pr_debug("unsupported chip ID: 0x%04x\n", val); + return -ENODEV; + } + + pr_info("hlx_ich: found SMF for ID %#x\n", ich_data->kind); + + return (0); +} + +static struct platform_device *pdev; + +static int __init hlx_ich_init(void) +{ + int err; + struct hlx_ich_data ich_data; + + if (init_ich_data(SMF_REG_ADDR, &ich_data)) + return -ENODEV; + + err = platform_driver_register(&hlx_ich_driver); + if (err) + goto exit; + + pdev = platform_device_alloc(DRV_NAME, 0); + if (!pdev) { + err = -ENOMEM; + pr_err("hlx_ich: Device allocation failed\n"); + goto exit_unregister; + } + + err = platform_device_add_data(pdev, &ich_data, + sizeof(struct hlx_ich_data)); + if (err) { + pr_err("hlx_ich: Platform data allocation failed\n"); + goto exit_device_put; + } + + /* platform_device_add calls probe() */ + err = platform_device_add(pdev); + if (err) { + pr_err("hlx_ich: Device addition failed (%d)\n", err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit_unregister: + platform_driver_unregister(&hlx_ich_driver); +exit: + pr_err("hlx_ich: hlx_ich_init failed (%d)\n", err); + return err; +} + +static void __exit hlx_ich_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&hlx_ich_driver); + + /*Remove sysfs hlx_kobj*/ + kobject_put(hlx_kobj); +} + +MODULE_AUTHOR("Padmanabhan Narayanan"); +MODULE_DESCRIPTION("ICH driver for Rangeley switches"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + +module_init(hlx_ich_init); +module_exit(hlx_ich_exit); diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/mc24lc64t.c new file mode 100644 index 000000000000..a391056d09a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/mc24lc64t.c @@ -0,0 +1,142 @@ +/* + * 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 + +struct mc24lc64t_data { + struct i2c_client *fake_client; + 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 struct bin_attribute mc24lc64t_bit_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = 65536, + .read = mc24lc64t_read, +}; + +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; + + drvdata->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); + if (!drvdata->fake_client) + return -ENOMEM; + + i2c_set_clientdata(client, drvdata); + mutex_init(&drvdata->update_lock); + + err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + if (err) + i2c_unregister_device(drvdata->fake_client); + + return err; +} + +static int mc24lc64t_remove(struct i2c_client *client) +{ + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + + i2c_unregister_device(drvdata->fake_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/haliburton/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/pmbus.h new file mode 100644 index 000000000000..521baf6da49a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/pmbus.h @@ -0,0 +1,425 @@ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PMBUS_H +#define PMBUS_H + +#include +#include + +/* + * Registers + */ +enum pmbus_regs { + PMBUS_PAGE = 0x00, + PMBUS_OPERATION = 0x01, + PMBUS_ON_OFF_CONFIG = 0x02, + PMBUS_CLEAR_FAULTS = 0x03, + PMBUS_PHASE = 0x04, + + PMBUS_CAPABILITY = 0x19, + PMBUS_QUERY = 0x1A, + + PMBUS_VOUT_MODE = 0x20, + PMBUS_VOUT_COMMAND = 0x21, + PMBUS_VOUT_TRIM = 0x22, + PMBUS_VOUT_CAL_OFFSET = 0x23, + PMBUS_VOUT_MAX = 0x24, + PMBUS_VOUT_MARGIN_HIGH = 0x25, + PMBUS_VOUT_MARGIN_LOW = 0x26, + PMBUS_VOUT_TRANSITION_RATE = 0x27, + PMBUS_VOUT_DROOP = 0x28, + PMBUS_VOUT_SCALE_LOOP = 0x29, + PMBUS_VOUT_SCALE_MONITOR = 0x2A, + + PMBUS_COEFFICIENTS = 0x30, + PMBUS_POUT_MAX = 0x31, + + PMBUS_FAN_CONFIG_12 = 0x3A, + PMBUS_FAN_COMMAND_1 = 0x3B, + PMBUS_FAN_COMMAND_2 = 0x3C, + PMBUS_FAN_CONFIG_34 = 0x3D, + PMBUS_FAN_COMMAND_3 = 0x3E, + PMBUS_FAN_COMMAND_4 = 0x3F, + + PMBUS_VOUT_OV_FAULT_LIMIT = 0x40, + PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41, + PMBUS_VOUT_OV_WARN_LIMIT = 0x42, + PMBUS_VOUT_UV_WARN_LIMIT = 0x43, + PMBUS_VOUT_UV_FAULT_LIMIT = 0x44, + PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45, + PMBUS_IOUT_OC_FAULT_LIMIT = 0x46, + PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47, + PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48, + PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49, + PMBUS_IOUT_OC_WARN_LIMIT = 0x4A, + PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B, + PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C, + + PMBUS_OT_FAULT_LIMIT = 0x4F, + PMBUS_OT_FAULT_RESPONSE = 0x50, + PMBUS_OT_WARN_LIMIT = 0x51, + PMBUS_UT_WARN_LIMIT = 0x52, + PMBUS_UT_FAULT_LIMIT = 0x53, + PMBUS_UT_FAULT_RESPONSE = 0x54, + PMBUS_VIN_OV_FAULT_LIMIT = 0x55, + PMBUS_VIN_OV_FAULT_RESPONSE = 0x56, + PMBUS_VIN_OV_WARN_LIMIT = 0x57, + PMBUS_VIN_UV_WARN_LIMIT = 0x58, + PMBUS_VIN_UV_FAULT_LIMIT = 0x59, + + PMBUS_IIN_OC_FAULT_LIMIT = 0x5B, + PMBUS_IIN_OC_WARN_LIMIT = 0x5D, + + PMBUS_POUT_OP_FAULT_LIMIT = 0x68, + PMBUS_POUT_OP_WARN_LIMIT = 0x6A, + PMBUS_PIN_OP_WARN_LIMIT = 0x6B, + + PMBUS_STATUS_BYTE = 0x78, + PMBUS_STATUS_WORD = 0x79, + PMBUS_STATUS_VOUT = 0x7A, + PMBUS_STATUS_IOUT = 0x7B, + PMBUS_STATUS_INPUT = 0x7C, + PMBUS_STATUS_TEMPERATURE = 0x7D, + PMBUS_STATUS_CML = 0x7E, + PMBUS_STATUS_OTHER = 0x7F, + PMBUS_STATUS_MFR_SPECIFIC = 0x80, + PMBUS_STATUS_FAN_12 = 0x81, + PMBUS_STATUS_FAN_34 = 0x82, + + PMBUS_READ_VIN = 0x88, + PMBUS_READ_IIN = 0x89, + PMBUS_READ_VCAP = 0x8A, + PMBUS_READ_VOUT = 0x8B, + PMBUS_READ_IOUT = 0x8C, + PMBUS_READ_TEMPERATURE_1 = 0x8D, + PMBUS_READ_TEMPERATURE_2 = 0x8E, + PMBUS_READ_TEMPERATURE_3 = 0x8F, + PMBUS_READ_FAN_SPEED_1 = 0x90, + PMBUS_READ_FAN_SPEED_2 = 0x91, + PMBUS_READ_FAN_SPEED_3 = 0x92, + PMBUS_READ_FAN_SPEED_4 = 0x93, + PMBUS_READ_DUTY_CYCLE = 0x94, + PMBUS_READ_FREQUENCY = 0x95, + PMBUS_READ_POUT = 0x96, + PMBUS_READ_PIN = 0x97, + + PMBUS_REVISION = 0x98, + PMBUS_MFR_ID = 0x99, + PMBUS_MFR_MODEL = 0x9A, + PMBUS_MFR_REVISION = 0x9B, + PMBUS_MFR_LOCATION = 0x9C, + PMBUS_MFR_DATE = 0x9D, + PMBUS_MFR_SERIAL = 0x9E, + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ + PMBUS_VIRT_BASE = 0x100, + PMBUS_VIRT_READ_TEMP_AVG, + PMBUS_VIRT_READ_TEMP_MIN, + PMBUS_VIRT_READ_TEMP_MAX, + PMBUS_VIRT_RESET_TEMP_HISTORY, + PMBUS_VIRT_READ_VIN_AVG, + PMBUS_VIRT_READ_VIN_MIN, + PMBUS_VIRT_READ_VIN_MAX, + PMBUS_VIRT_RESET_VIN_HISTORY, + PMBUS_VIRT_READ_IIN_AVG, + PMBUS_VIRT_READ_IIN_MIN, + PMBUS_VIRT_READ_IIN_MAX, + PMBUS_VIRT_RESET_IIN_HISTORY, + PMBUS_VIRT_READ_PIN_AVG, + PMBUS_VIRT_READ_PIN_MIN, + PMBUS_VIRT_READ_PIN_MAX, + PMBUS_VIRT_RESET_PIN_HISTORY, + PMBUS_VIRT_READ_POUT_AVG, + PMBUS_VIRT_READ_POUT_MIN, + PMBUS_VIRT_READ_POUT_MAX, + PMBUS_VIRT_RESET_POUT_HISTORY, + PMBUS_VIRT_READ_VOUT_AVG, + PMBUS_VIRT_READ_VOUT_MIN, + PMBUS_VIRT_READ_VOUT_MAX, + PMBUS_VIRT_RESET_VOUT_HISTORY, + PMBUS_VIRT_READ_IOUT_AVG, + PMBUS_VIRT_READ_IOUT_MIN, + PMBUS_VIRT_READ_IOUT_MAX, + PMBUS_VIRT_RESET_IOUT_HISTORY, + PMBUS_VIRT_READ_TEMP2_AVG, + PMBUS_VIRT_READ_TEMP2_MIN, + PMBUS_VIRT_READ_TEMP2_MAX, + PMBUS_VIRT_RESET_TEMP2_HISTORY, + + PMBUS_VIRT_READ_VMON, + PMBUS_VIRT_VMON_UV_WARN_LIMIT, + PMBUS_VIRT_VMON_OV_WARN_LIMIT, + PMBUS_VIRT_VMON_UV_FAULT_LIMIT, + PMBUS_VIRT_VMON_OV_FAULT_LIMIT, + PMBUS_VIRT_STATUS_VMON, +}; + +/* + * OPERATION + */ +#define PB_OPERATION_CONTROL_ON BIT(7) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT BIT(4) +#define PB_CAPABILITY_ERROR_CHECK BIT(7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1)) +#define PB_FAN_2_RPM BIT(2) +#define PB_FAN_2_INSTALLED BIT(3) +#define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5)) +#define PB_FAN_1_RPM BIT(6) +#define PB_FAN_1_INSTALLED BIT(7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE BIT(0) +#define PB_STATUS_CML BIT(1) +#define PB_STATUS_TEMPERATURE BIT(2) +#define PB_STATUS_VIN_UV BIT(3) +#define PB_STATUS_IOUT_OC BIT(4) +#define PB_STATUS_VOUT_OV BIT(5) +#define PB_STATUS_OFF BIT(6) +#define PB_STATUS_BUSY BIT(7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN BIT(8) +#define PB_STATUS_OTHER BIT(9) +#define PB_STATUS_FANS BIT(10) +#define PB_STATUS_POWER_GOOD_N BIT(11) +#define PB_STATUS_WORD_MFR BIT(12) +#define PB_STATUS_INPUT BIT(13) +#define PB_STATUS_IOUT_POUT BIT(14) +#define PB_STATUS_VOUT BIT(15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING BIT(0) +#define PB_POUT_OP_FAULT BIT(1) +#define PB_POWER_LIMITING BIT(2) +#define PB_CURRENT_SHARE_FAULT BIT(3) +#define PB_IOUT_UC_FAULT BIT(4) +#define PB_IOUT_OC_WARNING BIT(5) +#define PB_IOUT_OC_LV_FAULT BIT(6) +#define PB_IOUT_OC_FAULT BIT(7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT BIT(4) +#define PB_VOLTAGE_UV_WARNING BIT(5) +#define PB_VOLTAGE_OV_WARNING BIT(6) +#define PB_VOLTAGE_OV_FAULT BIT(7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING BIT(0) +#define PB_IIN_OC_WARNING BIT(1) +#define PB_IIN_OC_FAULT BIT(2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT BIT(4) +#define PB_TEMP_UT_WARNING BIT(5) +#define PB_TEMP_OT_WARNING BIT(6) +#define PB_TEMP_OT_FAULT BIT(7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING BIT(0) +#define PB_FAN_AIRFLOW_FAULT BIT(1) +#define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2) +#define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3) +#define PB_FAN_FAN2_WARNING BIT(4) +#define PB_FAN_FAN1_WARNING BIT(5) +#define PB_FAN_FAN2_FAULT BIT(6) +#define PB_FAN_FAN1_FAULT BIT(7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0) +#define PB_CML_FAULT_OTHER_COMM BIT(1) +#define PB_CML_FAULT_PROCESSOR BIT(3) +#define PB_CML_FAULT_MEMORY BIT(4) +#define PB_CML_FAULT_PACKET_ERROR BIT(5) +#define PB_CML_FAULT_INVALID_DATA BIT(6) +#define PB_CML_FAULT_INVALID_COMMAND BIT(7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN BIT(0) +#define PMBUS_HAVE_VCAP BIT(1) +#define PMBUS_HAVE_VOUT BIT(2) +#define PMBUS_HAVE_IIN BIT(3) +#define PMBUS_HAVE_IOUT BIT(4) +#define PMBUS_HAVE_PIN BIT(5) +#define PMBUS_HAVE_POUT BIT(6) +#define PMBUS_HAVE_FAN12 BIT(7) +#define PMBUS_HAVE_FAN34 BIT(8) +#define PMBUS_HAVE_TEMP BIT(9) +#define PMBUS_HAVE_TEMP2 BIT(10) +#define PMBUS_HAVE_TEMP3 BIT(11) +#define PMBUS_HAVE_STATUS_VOUT BIT(12) +#define PMBUS_HAVE_STATUS_IOUT BIT(13) +#define PMBUS_HAVE_STATUS_INPUT BIT(14) +#define PMBUS_HAVE_STATUS_TEMP BIT(15) +#define PMBUS_HAVE_STATUS_FAN12 BIT(16) +#define PMBUS_HAVE_STATUS_FAN34 BIT(17) +#define PMBUS_HAVE_VMON BIT(18) +#define PMBUS_HAVE_STATUS_VMON BIT(19) + +enum pmbus_data_format { linear = 0, direct, vid }; +enum vrm_version { vr11 = 0, vr12 }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + enum vrm_version vrm_version; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); + + /* Regulator functionality, if supported by this chip driver. */ + int num_regulators; + const struct regulator_desc *reg_desc; +}; + +/* Regulator ops */ + +extern const struct regulator_ops pmbus_regulator_ops; + +/* Macro for filling in array of struct regulator_desc */ +#define PMBUS_REGULATOR(_name, _id) \ + [_id] = { \ + .name = (_name # _id), \ + .id = (_id), \ + .of_match = of_match_ptr(_name # _id), \ + .regulators_node = of_match_ptr("regulators"), \ + .ops = &pmbus_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, + u8 value); +int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg, + u8 mask, u8 value); +void pmbus_clear_faults(struct i2c_client *client); +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); + +#endif /* PMBUS_H */ \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c new file mode 100644 index 000000000000..7ec9753066b3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c @@ -0,0 +1,1068 @@ +/* + * smc.c - The CPLD driver for E1031 System Management. + * The driver implement sysfs to access CPLD register on the E1031 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 + + +#define DRIVER_NAME "e1031.smc" + +/** + * CPLD register address for read and write. + */ +#define VERSION 0x0200 +#define SCRATCH 0x0201 +#define BROAD_ID 0x0202 + +/* SEPERATE RESET + * [7:5] RESERVED + * [4] RESET PCIE + * [3] RESET USBHUB + * [2] RESET B50282 + * [1] RESET PCA9548 + * [0] RESET BCM54616 + * 1: not reset, 0: reset + */ +#define SPR_RESET 0x0222 + +/* PSU STATUS + * [7] PSUR_ACOK + * [6] PSUR_PWOK + * [5] PSUR_ALRT + * [4] PSUR_PRS + * [3] PSUL_ACOK + * [2] PSUL_PWOK + * [1] PSUL_ALRT + * [0] PSUL_PRS + */ +#define PSU_STAT 0x0204 +#define PSUR_ACOK 7 +#define PSUR_PWOK 6 +#define PSUR_ALRT 5 +#define PSUR_PRS 4 +#define PSUL_ACOK 3 +#define PSUL_PWOK 2 +#define PSUL_ALRT 1 +#define PSUL_PRS 0 + +/* FAN LED CTRL + * [7:3] RESERVED + * [2:0] LED CTRL + */ +#define FAN_LED_1 0x0205 +#define FAN_LED_2 0x0206 +#define FAN_LED_3 0x0207 + +enum FAN_LED { + fan_led_grn = 0, + fan_led_grn_bnk, + fan_led_amb, + fan_led_amb_bnk, + fan_led_off +} fan_led; + +#define LED_OPMOD 0x0208 +#define LED_TEST 0x0209 + +/* SYSTEM LED + * [7:4] RESERVED + * [3:2] STATUS LED + * [1:0] MASTER LED + */ +#define LED_FPS 0x020a + +enum STAT_LED { + stat_led_off = 0, + stat_led_grn, + stat_led_grn_bnk +} stat_led; + +enum MASTER_LED { + master_led_off = 0, + master_led_grn, + master_led_amb +} master_led; + +/* FAN DIRECTION STAT + * [7:4] RESERVED + * [3] USB HUB STAT + * [2:0] FAN_DIR + */ +#define DEV_STAT 0x020c +#define FAN_3 2 +#define FAN_2 1 +#define FAN_1 0 + +/* FAN STATUS + * [7:5] FAN STATUS + * [4] FAN INTERRUPT + * [3:0] PSU ALERT + */ +#define FAN_STAT 0x0234 +#define FAN3_PRS 7 +#define FAN2_PRS 6 +#define FAN1_PRS 5 + +/* SFP PORT INT TRIGGER MODE + * [7:6] RESERVED + * [5:4] RXLOS + * [3:2] MODABS + * [1:0] TXFAULT + * 00: falling edge, + * 01: rising edge, + * 10: Both edges, + * 11: low level detect + */ +#define TRIG_MODE 0x0240 +#define TXFAULT_TRIG 0 +#define MODABS_TRIG 2 +#define RXLOS_TRIG 4 + + +/* SFP PORT STATUS + * [7:4] RESERVED + * [3:0] TX_FAULT / MODABS / RXLOS + */ +#define SFP_TXFAULT 0x0242 +#define SFP_MODABS 0x0243 +#define SFP_RXLOS 0x0244 + +/* SFP PORT INTERRUPT + * [7:4] RESERVED + * [3:0] TX_FAULT / MODABS / RXLOS + * 1: int, 0: no int + */ +#define TXFAULT_INT 0x0246 +#define MODABS_INT 0x0247 +#define RXLOS_INT 0x0248 + +/* INTERRUPT MASK REGISTER + * [7:4] RESERVED + * [3:0] TX_FAULT / MODABS / RXLOS + * 1: mask, 0: not mask + */ +#define TXFAULT_MSK 0x024A +#define MODABS_MSK 0x024B +#define RXLOS_MSK 0x024C + +/* SFP PORT CTRL + * [7:4] RATE SEL (RS0/RS1) + * [3:0] TX_DIS + */ +#define SFP_TXCTRL 0x0255 + +struct cpld_data { + struct mutex cpld_lock; + uint16_t read_addr; + struct device *fpp_node; + struct device *sfp_devices[4]; +}; + +struct sfp_device_data { + int portid; +}; + +struct class *celplatform; +struct cpld_data *cpld_data; + +struct index_device_attribute { + struct device_attribute dev_attr; + int index; +}; + +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); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%2.2x\n", data); +} + +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); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + + +static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = 0; + mutex_lock(&cpld_data->cpld_lock); + len = sprintf(buf, "0x%2.2x\n", inb(VERSION)); + mutex_unlock(&cpld_data->cpld_lock); + return len; +} + +static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + 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; + 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 ssize_t setreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + 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; +} + +/** + * @brief Show status led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return led state - off/on/blink + */ +static ssize_t status_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(LED_FPS); + mutex_unlock(&cpld_data->cpld_lock); + data = data & 0xc; + return sprintf(buf, "%s\n", + data == stat_led_grn ? "on" : data == stat_led_grn_bnk ? "blink" : "off"); +} + +/** + * @brief Set the status led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value - off/on/blink + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t status_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 = stat_led_off; + } else if (sysfs_streq(buf, "on")) { + led_status = stat_led_grn; + } else if (sysfs_streq(buf, "blink")) { + led_status = stat_led_grn_bnk; + } else { + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(LED_FPS); + data = data & ~(0xc); + data = data | ( led_status << 2 ); + outb(data, LED_FPS); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +/** + * @brief Show master led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer for get value + * @return led state - off/green/amber + */ +static ssize_t master_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(LED_FPS); + mutex_unlock(&cpld_data->cpld_lock); + data = data & 0x3; + return sprintf(buf, "%s\n", + data == master_led_grn ? "on" : data == master_led_amb ? "amber" : "off"); +} + +/** + * @brief Set the master led + * @param dev kernel device + * @param devattr kernel device attribute + * @param buf buffer of set value - off/green/amber + * @param count number of bytes in buffer + * @return number of bytes written, or error code < 0. + */ +static ssize_t master_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 = master_led_off; + } else if (sysfs_streq(buf, "green")) { + led_status = master_led_grn; + } else if (sysfs_streq(buf, "amber")) { + led_status = master_led_amb; + } else { + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + data = inb(LED_FPS); + data = data & ~(0x3); + data = data | led_status; + outb(data, LED_FPS); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +static ssize_t psuL_prs_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(PSU_STAT); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%d\n", ~(data >> PSUL_PRS) & 1U); +} + +static ssize_t psuR_prs_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(PSU_STAT); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%d\n", ~(data >> PSUR_PRS) & 1U); +} +static DEVICE_ATTR_RO(psuR_prs); + +static ssize_t psuL_status_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(PSU_STAT); + mutex_unlock(&cpld_data->cpld_lock); + data = ( data >> PSUL_PWOK ) & 0x3; + return sprintf(buf, "%d\n", data == 0x3 ); +} + +static ssize_t psuR_status_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(PSU_STAT); + mutex_unlock(&cpld_data->cpld_lock); + data = ( data >> PSUR_PWOK ) & 0x3; + return sprintf(buf, "%d\n", data == 0x3 ); +} + + +static ssize_t fan_dir_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(DEV_STAT); + mutex_unlock(&cpld_data->cpld_lock); + data = ( data >> index ) & 1U; + return sprintf(buf, "%s\n", data ? "B2F" : "F2B" ); +} + +static ssize_t fan_prs_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + unsigned char data = 0; + mutex_lock(&cpld_data->cpld_lock); + data = inb(FAN_STAT); + mutex_unlock(&cpld_data->cpld_lock); + data = ( data >> index ) & 1U; + return sprintf(buf, "%d\n", data); +} + +static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SFP_TXFAULT); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SFP_MODABS); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SFP_RXLOS); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sfp_txdis_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SFP_TXCTRL); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sfp_txdis_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + long value; + ssize_t status; + unsigned char data; + + mutex_lock(&cpld_data->cpld_lock); + status = kstrtol(buf, 0, &value); + if (status == 0) { + data = inb(SFP_TXCTRL); + data = data & ~(0x0F); + data = data | (value & 0x0F); + outb(data, SFP_TXCTRL); + status = size; + } + mutex_unlock(&cpld_data->cpld_lock); + return status; +} + +static ssize_t sfp_rs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(SFP_TXCTRL) >> 4; + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sfp_rs_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + long value; + ssize_t status; + unsigned char data; + + mutex_lock(&cpld_data->cpld_lock); + status = kstrtol(buf, 0, &value); + value = (value & 0x0F) << 4; + if (status == 0) { + data = inb(SFP_TXCTRL); + data = data & ~(0xF0); + data = data | value; + outb(data, SFP_TXCTRL); + status = size; + } + mutex_unlock(&cpld_data->cpld_lock); + return status; +} + +/** + * @brief Show the avaliable interrupt trigger mode. + * "none" means the interrupt is masked. + * + * @return Current trigger mode. + */ +static ssize_t txfault_trig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char mode; + char *mode_str[5] = {"falling", "rising", "both", "low"}; + + mutex_lock(&cpld_data->cpld_lock); + mode = inb(TRIG_MODE) >> TXFAULT_TRIG; + mode = mode & 0x3; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%s\n", mode_str[mode]); +} + +/** + * @brief Set the trigger mode of each interrupt type. + * Only one trigger mode allow in a type. + * + * @param buf The trigger mode of follwings + * "falling", "rising", "both" + */ +static ssize_t txfault_trig_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + ssize_t status; + unsigned char data, trig_mode; + + if (sysfs_streq(buf, "falling")) { + trig_mode = 0; + } else if (sysfs_streq(buf, "rising")) { + trig_mode = 1; + } else if (sysfs_streq(buf, "both")) { + trig_mode = 2; + } else if (sysfs_streq(buf, "low")) { + trig_mode = 3; + } else { + status = -EINVAL; + return status; + } + + mutex_lock(&cpld_data->cpld_lock); + data = inb(TRIG_MODE); + data = data & ~(0x03 << TXFAULT_TRIG); + data = data | trig_mode << TXFAULT_TRIG; + outb(data, TRIG_MODE); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + return status; +} + +/** + * @brief Show the avaliable interrupt trigger mode. + * "none" means the interrupt is masked. + * + * @return Current trigger mode. + */ +static ssize_t modabs_trig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char mode; + char *mode_str[5] = {"falling", "rising", "both", "low"}; + + mutex_lock(&cpld_data->cpld_lock); + mode = inb(TRIG_MODE) >> MODABS_TRIG; + mode = mode & 0x3; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%s\n", mode_str[mode]); +} + +/** + * @brief Set the trigger mode of each interrupt type. + * Only one trigger mode allow in a type. + * + * @param buf The trigger mode of follwings + * "falling", "rising", "both", "low" + */ +static ssize_t modabs_trig_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + ssize_t status; + unsigned char data, trig_mode; + + if (sysfs_streq(buf, "falling")) { + trig_mode = 0; + } else if (sysfs_streq(buf, "rising")) { + trig_mode = 1; + } else if (sysfs_streq(buf, "both")) { + trig_mode = 2; + } else if (sysfs_streq(buf, "low")) { + trig_mode = 3; + } else { + status = -EINVAL; + return status; + } + + mutex_lock(&cpld_data->cpld_lock); + data = inb(TRIG_MODE); + data = data & ~(0x03 << MODABS_TRIG); + data = data | trig_mode << MODABS_TRIG; + outb(data, TRIG_MODE); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + return status; +} + +/** + * @brief Show the avaliable interrupt trigger mode. + * "none" means the interrupt is masked. + * + * @return Current trigger mode. + */ +static ssize_t rxlos_trig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char mode; + char *mode_str[5] = {"falling", "rising", "both", "low"}; + + mutex_lock(&cpld_data->cpld_lock); + mode = inb(TRIG_MODE) >> RXLOS_TRIG; + mode = mode & 0x3; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%s\n", mode_str[mode]); +} + +/** + * @brief Set the trigger mode of each interrupt type. + * Only one trigger mode allow in a type. + * + * @param buf The trigger mode of follwings + * "falling", "rising", "both", "low" + */ +static ssize_t rxlos_trig_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + ssize_t status; + unsigned char data, trig_mode; + + if (sysfs_streq(buf, "falling")) { + trig_mode = 0; + } else if (sysfs_streq(buf, "rising")) { + trig_mode = 1; + } else if (sysfs_streq(buf, "both")) { + trig_mode = 2; + } else if (sysfs_streq(buf, "low")) { + trig_mode = 3; + } else { + status = -EINVAL; + return status; + } + + mutex_lock(&cpld_data->cpld_lock); + data = inb(TRIG_MODE); + data = data & ~(0x03 << RXLOS_TRIG); + data = data | trig_mode << RXLOS_TRIG; + outb(data, TRIG_MODE); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + return status; +} + +static ssize_t txfault_int_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(TXFAULT_INT); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t modabs_int_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(MODABS_INT); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t rxlos_int_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(RXLOS_INT); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t txfault_mask_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(TXFAULT_MSK); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t txfault_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + long value; + ssize_t status; + + status = kstrtol(buf, 0, &value); + value = value & 0x0F; + if (status == 0) { + mutex_lock(&cpld_data->cpld_lock); + outb(value, TXFAULT_MSK); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + } + return status; +} + +static ssize_t modabs_mask_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(MODABS_MSK); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t modabs_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + long value; + ssize_t status; + + status = kstrtol(buf, 0, &value); + value = value & 0x0F; + if (status == 0) { + mutex_lock(&cpld_data->cpld_lock); + outb(value, MODABS_MSK); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + } + return status; +} + +static ssize_t rxlos_mask_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned char data; + mutex_lock(&cpld_data->cpld_lock); + data = inb(RXLOS_MSK); + data = data & 0x0F; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t rxlos_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + long value; + ssize_t status; + + status = kstrtol(buf, 0, &value); + value = value & 0x0F; + if (status == 0) { + mutex_lock(&cpld_data->cpld_lock); + outb(value, RXLOS_MSK); + mutex_unlock(&cpld_data->cpld_lock); + status = size; + } + return status; +} + +static ssize_t fan_led_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + unsigned char data = 0; + char *led_str[5] = {"green", "green-blink", "amber", "amber-blink", "off"}; + + // Use index to determind the status bit + mutex_lock(&cpld_data->cpld_lock); + data = inb(FAN_LED_1 + index); + data = data & 0x7; + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%s\n", led_str[data]); +} + +static ssize_t fan_led_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + unsigned char led_status = 0; + + if (sysfs_streq(buf, "off")) { + led_status = fan_led_off; + } else if (sysfs_streq(buf, "green")) { + led_status = fan_led_grn; + } else if (sysfs_streq(buf, "amber")) { + led_status = fan_led_amb; + } else if (sysfs_streq(buf, "green-blink")) { + led_status = fan_led_grn_bnk; + } else if (sysfs_streq(buf, "amber-blink")) { + led_status = fan_led_amb_bnk; + } else { + count = -EINVAL; + return count; + } + mutex_lock(&cpld_data->cpld_lock); + outb(led_status, FAN_LED_1 + index); + mutex_unlock(&cpld_data->cpld_lock); + return count; +} + +static DEVICE_ATTR_RO(version); +static DEVICE_ATTR_RW(scratch); +static DEVICE_ATTR_RW(getreg); +static DEVICE_ATTR_WO(setreg); +static DEVICE_ATTR_RW(status_led); +static DEVICE_ATTR_RW(master_led); +static DEVICE_ATTR_RO(psuL_prs); +static DEVICE_ATTR_RO(psuL_status); +static DEVICE_ATTR_RO(psuR_status); +static DEVICE_ATTR_RO(sfp_txfault); +static DEVICE_ATTR_RO(sfp_modabs); +static DEVICE_ATTR_RO(sfp_rxlos); +static DEVICE_ATTR_RW(sfp_txdis); +static DEVICE_ATTR_RW(sfp_rs); +static DEVICE_ATTR_RW(txfault_trig); +static DEVICE_ATTR_RW(modabs_trig); +static DEVICE_ATTR_RW(rxlos_trig); +static DEVICE_ATTR_RO(txfault_int); +static DEVICE_ATTR_RO(modabs_int); +static DEVICE_ATTR_RO(rxlos_int); +static DEVICE_ATTR_RW(txfault_mask); +static DEVICE_ATTR_RW(modabs_mask); +static DEVICE_ATTR_RW(rxlos_mask); +static SENSOR_DEVICE_ATTR(fan1_dir, S_IRUGO, fan_dir_show, NULL, FAN_1); +static SENSOR_DEVICE_ATTR(fan2_dir, S_IRUGO, fan_dir_show, NULL, FAN_2); +static SENSOR_DEVICE_ATTR(fan3_dir, S_IRUGO, fan_dir_show, NULL, FAN_3); +static SENSOR_DEVICE_ATTR(fan1_led, S_IWUSR | S_IRUGO, fan_led_show, fan_led_store, FAN_1); +static SENSOR_DEVICE_ATTR(fan2_led, S_IWUSR | S_IRUGO, fan_led_show, fan_led_store, FAN_2); +static SENSOR_DEVICE_ATTR(fan3_led, S_IWUSR | S_IRUGO, fan_led_show, fan_led_store, FAN_3); +static SENSOR_DEVICE_ATTR(fan1_prs, S_IRUGO, fan_prs_show, NULL, FAN1_PRS); +static SENSOR_DEVICE_ATTR(fan2_prs, S_IRUGO, fan_prs_show, NULL, FAN2_PRS); +static SENSOR_DEVICE_ATTR(fan3_prs, S_IRUGO, fan_prs_show, NULL, FAN3_PRS); + +static struct attribute *cpld_attrs[] = { + &dev_attr_version.attr, + &dev_attr_scratch.attr, + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, + // LEDs + &dev_attr_status_led.attr, + &dev_attr_master_led.attr, + // PSUs + &dev_attr_psuL_prs.attr, + &dev_attr_psuR_prs.attr, + &dev_attr_psuL_status.attr, + &dev_attr_psuR_status.attr, + // FANs + &sensor_dev_attr_fan1_dir.dev_attr.attr, + &sensor_dev_attr_fan2_dir.dev_attr.attr, + &sensor_dev_attr_fan3_dir.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &sensor_dev_attr_fan3_led.dev_attr.attr, + &sensor_dev_attr_fan1_prs.dev_attr.attr, + &sensor_dev_attr_fan2_prs.dev_attr.attr, + &sensor_dev_attr_fan3_prs.dev_attr.attr, + NULL, +}; + +static struct attribute_group cpld_group = { + .attrs = cpld_attrs, +}; + +static struct attribute *sfp_attrs[] = { + // SFP + &dev_attr_sfp_txfault.attr, + &dev_attr_sfp_modabs.attr, + &dev_attr_sfp_rxlos.attr, + &dev_attr_sfp_txdis.attr, + &dev_attr_sfp_rs.attr, + &dev_attr_txfault_trig.attr, + &dev_attr_modabs_trig.attr, + &dev_attr_rxlos_trig.attr, + &dev_attr_txfault_int.attr, + &dev_attr_modabs_int.attr, + &dev_attr_rxlos_int.attr, + &dev_attr_txfault_mask.attr, + &dev_attr_modabs_mask.attr, + &dev_attr_rxlos_mask.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(sfp); + +static struct resource cpld_resources[] = { + { + .start = 0x0200, + .end = 0x0255, + .flags = IORESOURCE_IO, + }, +}; + +static void cpld_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device cpld_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(cpld_resources), + .resource = cpld_resources, + .dev = { + .release = cpld_dev_release, + } +}; + +static int cpld_drv_probe(struct platform_device *pdev) +{ + struct resource *res; + int err; + + cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_data), + GFP_KERNEL); + if (!cpld_data) + return -ENOMEM; + + mutex_init(&cpld_data->cpld_lock); + + cpld_data->read_addr = VERSION; + + 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_group); + if (err) { + printk(KERN_ERR "Cannot create sysfs for SMC.\n"); + return err; + } + + celplatform = class_create(THIS_MODULE, "celplatform"); + if (IS_ERR(celplatform)) { + printk(KERN_ERR "Failed to register device class\n"); + sysfs_remove_group(&pdev->dev.kobj, &cpld_group); + return PTR_ERR(celplatform); + } + + cpld_data->fpp_node = device_create_with_groups(celplatform, NULL, MKDEV(0, 0), NULL, sfp_groups, "optical_ports"); + + if (IS_ERR(cpld_data->fpp_node)) { + class_destroy(celplatform); + sysfs_remove_group(&pdev->dev.kobj, &cpld_group); + return PTR_ERR(cpld_data->fpp_node); + } + + err = sysfs_create_link(&pdev->dev.kobj, &cpld_data->fpp_node->kobj, "SFP"); + if (err != 0) { + put_device(cpld_data->fpp_node); + device_unregister(cpld_data->fpp_node); + class_destroy(celplatform); + sysfs_remove_group(&pdev->dev.kobj, &cpld_group); + return err; + } + + // Clear all reset signals + outb(0xFF, SPR_RESET); + return 0; +} + +static int cpld_drv_remove(struct platform_device *pdev) +{ + device_unregister(cpld_data->fpp_node); + put_device(cpld_data->fpp_node); + sysfs_remove_group(&pdev->dev.kobj, &cpld_group); + class_destroy(celplatform); + return 0; +} + +static struct platform_driver cpld_drv = { + .probe = cpld_drv_probe, + .remove = __exit_p(cpld_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int cpld_init(void) +{ + // Register platform device and platform driver + platform_device_register(&cpld_dev); + platform_driver_register(&cpld_drv); + return 0; +} + +void cpld_exit(void) +{ + // Unregister platform device and platform driver + platform_driver_unregister(&cpld_drv); + platform_device_unregister(&cpld_dev); +} + +module_init(cpld_init); +module_exit(cpld_exit); + + +MODULE_AUTHOR("Celestica Inc."); +MODULE_DESCRIPTION("Celestica E1031 SMC driver"); +MODULE_VERSION("1.0.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/script/50-ttyUSB-C0.rules b/platform/broadcom/sonic-platform-modules-cel/haliburton/script/50-ttyUSB-C0.rules new file mode 100644 index 000000000000..a4200daa71dd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/script/50-ttyUSB-C0.rules @@ -0,0 +1,254 @@ + + +LABEL="parent info" +ACTION=="add",KERNEL=="1-1",SUBSYSTEM=="usb",RUN+="/bin/bash -c '/usr/local/bin/udev_prefix.sh clear'" +ACTION=="add",KERNEL=="ttyUSB*",SUBSYSTEM=="tty",KERNELS=="1-1.1",ATTRS{idProduct}=="2517",ATTRS{idVendor}=="0424",RUN+="/bin/bash -c '/usr/local/bin/udev_prefix.sh C0-'",GOTO="C0 Add" +ACTION=="remove",KERNELS=="1-1.1",ENV{PRODUCT}=="*424/2517/*",RUN+="/bin/bash -c '/usr/local/bin/udev_prefix.sh clear'",GOTO="C0 Remove" + + +LABEL="C0 Add" +ACTION=="add",KERNELS=="1-1.1.1:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-1",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.1:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-2",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.1:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-3",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.1:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-4",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.2:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-5",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.2:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-6",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.2:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-7",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.2:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-8",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.3:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-9",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.3:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-10",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.3:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-11",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.3:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-12",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.4:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-13",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.4:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-14",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.4:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-15",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.4:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-16",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.5:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-17",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.5:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-18",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.5:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-19",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.5:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-20",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.6:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-21",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.6:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-22",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.6:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-23",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.6:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-24",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.1:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-25",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.1:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-26",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.1:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-27",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.1:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-28",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.2:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-29",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.2:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-30",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.2:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-31",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.2:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-32",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.3:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-33",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.3:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-34",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.3:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-35",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.3:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-36",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.4:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-37",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.4:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-38",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.4:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-39",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.4:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-40",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.5:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-41",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.5:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-42",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.5:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-43",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.5:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-44",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.6:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-45",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.6:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-46",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.6:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-47",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.6:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-48",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.1:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-49",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.1:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-50",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.1:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-51",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.1:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-52",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.2:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-53",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.2:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-54",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.2:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-55",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.2:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-56",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.3:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-57",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.3:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-58",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.3:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-59",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.3:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-60",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.4:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-61",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.4:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-62",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.4:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-63",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.4:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-64",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.5:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-65",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.5:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-66",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.5:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-67",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.5:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-68",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.6:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-69",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.6:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-70",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.6:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-71",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.6:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-72",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.7.1:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-73",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.1:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-74",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.1:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-75",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.1:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-76",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.7.2:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-77",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.2:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-78",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.2:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-79",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.2:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-80",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.7.3:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-81",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.3:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-82",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.3:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-83",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.3:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-84",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.7.4:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-85",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.4:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-86",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.4:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-87",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.4:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-88",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.7.5:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-89",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.5:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-90",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.5:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-91",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.5:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-92",MODE="0666" + +ACTION=="add",KERNELS=="1-1.1.7.7.7.6:1.0",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="00",ATTRS{interface}=="CP2108 Interface 0",SYMLINK+="C0-93",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.6:1.1",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="01",ATTRS{interface}=="CP2108 Interface 1",SYMLINK+="C0-94",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.6:1.2",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="02",ATTRS{interface}=="CP2108 Interface 2",SYMLINK+="C0-95",MODE="0666" +ACTION=="add",KERNELS=="1-1.1.7.7.7.6:1.3",DRIVERS=="cp210x",ATTRS{bInterfaceNumber}=="03",ATTRS{interface}=="CP2108 Interface 3",SYMLINK+="C0-96",MODE="0666" + + + +LABEL="C0 Remove" +ACTION=="remove",KERNELS=="1-1.1.1:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 1'" +ACTION=="remove",KERNELS=="1-1.1.1:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 2'" +ACTION=="remove",KERNELS=="1-1.1.1:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 3'" +ACTION=="remove",KERNELS=="1-1.1.1:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 4'" + +ACTION=="remove",KERNELS=="1-1.1.2:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 5'" +ACTION=="remove",KERNELS=="1-1.1.2:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 6'" +ACTION=="remove",KERNELS=="1-1.1.2:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 7'" +ACTION=="remove",KERNELS=="1-1.1.2:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 8'" + +ACTION=="remove",KERNELS=="1-1.1.3:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 9'" +ACTION=="remove",KERNELS=="1-1.1.3:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 10'" +ACTION=="remove",KERNELS=="1-1.1.3:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 11'" +ACTION=="remove",KERNELS=="1-1.1.3:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 12'" + +ACTION=="remove",KERNELS=="1-1.1.4:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 13" +ACTION=="remove",KERNELS=="1-1.1.4:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 14" +ACTION=="remove",KERNELS=="1-1.1.4:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 15" +ACTION=="remove",KERNELS=="1-1.1.4:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 16" + +ACTION=="remove",KERNELS=="1-1.1.5:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 17" +ACTION=="remove",KERNELS=="1-1.1.5:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 18" +ACTION=="remove",KERNELS=="1-1.1.5:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 19" +ACTION=="remove",KERNELS=="1-1.1.5:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 20" + +ACTION=="remove",KERNELS=="1-1.1.6:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 21" +ACTION=="remove",KERNELS=="1-1.1.6:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 22" +ACTION=="remove",KERNELS=="1-1.1.6:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 23" +ACTION=="remove",KERNELS=="1-1.1.6:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 24" + +ACTION=="remove",KERNELS=="1-1.1.7.1:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 25" +ACTION=="remove",KERNELS=="1-1.1.7.1:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 26" +ACTION=="remove",KERNELS=="1-1.1.7.1:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 27" +ACTION=="remove",KERNELS=="1-1.1.7.1:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 28" + +ACTION=="remove",KERNELS=="1-1.1.7.2:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 29" +ACTION=="remove",KERNELS=="1-1.1.7.2:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 30" +ACTION=="remove",KERNELS=="1-1.1.7.2:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 31" +ACTION=="remove",KERNELS=="1-1.1.7.2:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 32" + +ACTION=="remove",KERNELS=="1-1.1.7.3:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 33" +ACTION=="remove",KERNELS=="1-1.1.7.3:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 34" +ACTION=="remove",KERNELS=="1-1.1.7.3:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 35" +ACTION=="remove",KERNELS=="1-1.1.7.3:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 36" + +ACTION=="remove",KERNELS=="1-1.1.7.4:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 37" +ACTION=="remove",KERNELS=="1-1.1.7.4:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 38" +ACTION=="remove",KERNELS=="1-1.1.7.4:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 39" +ACTION=="remove",KERNELS=="1-1.1.7.4:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 40" + +ACTION=="remove",KERNELS=="1-1.1.7.5:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 41" +ACTION=="remove",KERNELS=="1-1.1.7.5:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 42" +ACTION=="remove",KERNELS=="1-1.1.7.5:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 43" +ACTION=="remove",KERNELS=="1-1.1.7.5:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 44" + +ACTION=="remove",KERNELS=="1-1.1.7.6:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 45" +ACTION=="remove",KERNELS=="1-1.1.7.6:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 46" +ACTION=="remove",KERNELS=="1-1.1.7.6:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 47" +ACTION=="remove",KERNELS=="1-1.1.7.6:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 48" + + +ACTION=="remove",KERNELS=="1-1.1.7.7.1:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 49" +ACTION=="remove",KERNELS=="1-1.1.7.7.1:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 50" +ACTION=="remove",KERNELS=="1-1.1.7.7.1:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 51" +ACTION=="remove",KERNELS=="1-1.1.7.7.1:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 52" + +ACTION=="remove",KERNELS=="1-1.1.7.7.2:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 53" +ACTION=="remove",KERNELS=="1-1.1.7.7.2:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 54" +ACTION=="remove",KERNELS=="1-1.1.7.7.2:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 55" +ACTION=="remove",KERNELS=="1-1.1.7.7.2:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 56" + +ACTION=="remove",KERNELS=="1-1.1.7.7.3:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 57" +ACTION=="remove",KERNELS=="1-1.1.7.7.3:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 58" +ACTION=="remove",KERNELS=="1-1.1.7.7.3:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 59" +ACTION=="remove",KERNELS=="1-1.1.7.7.3:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 60" + +ACTION=="remove",KERNELS=="1-1.1.7.7.4:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 61" +ACTION=="remove",KERNELS=="1-1.1.7.7.4:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 62" +ACTION=="remove",KERNELS=="1-1.1.7.7.4:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 63" +ACTION=="remove",KERNELS=="1-1.1.7.7.4:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 64" + +ACTION=="remove",KERNELS=="1-1.1.7.7.5:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 65" +ACTION=="remove",KERNELS=="1-1.1.7.7.5:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 66" +ACTION=="remove",KERNELS=="1-1.1.7.7.5:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 67" +ACTION=="remove",KERNELS=="1-1.1.7.7.5:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 68" + +ACTION=="remove",KERNELS=="1-1.1.7.7.6:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 69" +ACTION=="remove",KERNELS=="1-1.1.7.7.6:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 70" +ACTION=="remove",KERNELS=="1-1.1.7.7.6:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 71" +ACTION=="remove",KERNELS=="1-1.1.7.7.6:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 72" + + +ACTION=="remove",KERNELS=="1-1.1.7.7.7.1:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 73" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.1:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 74" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.1:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 75" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.1:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 76" + +ACTION=="remove",KERNELS=="1-1.1.7.7.7.2:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 77" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.2:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 78" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.2:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 79" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.2:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 80" + +ACTION=="remove",KERNELS=="1-1.1.7.7.7.3:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 81" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.3:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 82" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.3:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 83" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.3:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 84" + +ACTION=="remove",KERNELS=="1-1.1.7.7.7.4:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 85" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.4:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 86" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.4:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 87" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.4:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 88" + +ACTION=="remove",KERNELS=="1-1.1.7.7.7.5:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 89" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.5:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 90" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.5:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 91" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.5:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 92" + +ACTION=="remove",KERNELS=="1-1.1.7.7.7.6:1.0",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 93" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.6:1.1",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 94" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.6:1.2",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 95" +ACTION=="remove",KERNELS=="1-1.1.7.7.7.6:1.3",ENV{PRODUCT}=="10c4/ea71/*",RUN+="/bin/bash -c '/usr/local/bin/popmsg.sh 96" + + diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/script/fancontrol.service b/platform/broadcom/sonic-platform-modules-cel/haliburton/script/fancontrol.service new file mode 100755 index 000000000000..bda541670028 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/script/fancontrol.service @@ -0,0 +1,12 @@ +[Unit] +Description=fan speed regulator +After=platform-modules-haliburton.service +Before=pmon.service + +[Service] +ExecStart=-/etc/init.d/fancontrol.sh start +ExecStop=-/etc/init.d/fancontrol.sh stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/script/fancontrol.sh b/platform/broadcom/sonic-platform-modules-cel/haliburton/script/fancontrol.sh new file mode 100755 index 000000000000..f2c0f3cd0f4e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/script/fancontrol.sh @@ -0,0 +1,78 @@ +#! /bin/sh + +### BEGIN INIT INFO +# Provides: fancontrol +# Required-Start: $remote_fs +# Required-Stop: $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: +# Short-Description: fancontrol +# Description: fan speed regulator +### END INIT INFO + +. /lib/lsb/init-functions + +[ -f /etc/default/rcS ] && . /etc/default/rcS +PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin +DAEMON=/usr/local/bin/fancontrol +DESC="fan speed regulator" +NAME="fancontrol" +PIDFILE=/var/run/fancontrol.pid +PLATFORMPATH=/sys/devices/platform/e1031.smc +MAIN_CONF=/usr/share/sonic/device/x86_64-cel_e1031-r0/fancontrol +DEVPATH=/sys/devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-23/23-004d + +test -x $DAEMON || exit 0 + +for i in 1 2 3 +do + j=$i + [ $i -eq 3 ] && j=4 + FANFAULT=$(cat ${DEVPATH}/fan${j}_fault) + [ $FANFAULT = 1 ] && continue + FANDIR=$(cat ${PLATFORMPATH}/fan${i}_dir) +done +CONF=${MAIN_CONF}-${FANDIR} + +case "$1" in + start) + if [ -f $CONF ] ; then + if $DAEMON --check $CONF 1>/dev/null 2>/dev/null ; then + log_daemon_msg "Starting $DESC" "$NAME\n" + start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON $CONF + log_end_msg $? + else + log_failure_msg "Not starting fancontrol, broken configuration file; please re-run pwmconfig." + fi + else + if [ "$VERBOSE" != no ]; then + log_warning_msg "Not starting fancontrol; run pwmconfig first." + fi + fi + ;; + stop) + log_daemon_msg "Stopping $DESC" "$NAME" + start-stop-daemon --stop --quiet --pidfile $PIDFILE --oknodo --startas $DAEMON $CONF + rm -f $PIDFILE + log_end_msg $? + ;; + restart) + $0 stop + sleep 3 + $0 start + ;; + force-reload) + if start-stop-daemon --stop --test --quiet --pidfile $PIDFILE --startas $DAEMON $CONF ; then + $0 restart + fi + ;; + status) + status_of_proc $DAEMON $NAME $CONF && exit 0 || exit $? + ;; + *) + log_success_msg "Usage: /etc/init.d/fancontrol {start|stop|restart|force-reload|status}" + exit 1 + ;; +esac + +exit 0 \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/script/popmsg.sh b/platform/broadcom/sonic-platform-modules-cel/haliburton/script/popmsg.sh new file mode 100644 index 000000000000..0789c3a3ee42 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/script/popmsg.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +dev="/dev/" +index=0 + +cnt=$(who | wc -l) +for((i=0;i ${list[$i]} +done + diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/script/udev_prefix.sh b/platform/broadcom/sonic-platform-modules-cel/haliburton/script/udev_prefix.sh new file mode 100644 index 000000000000..c5842fab0a7e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/script/udev_prefix.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +PREV_REBOOT_CAUSE="/host/reboot-cause/" +DEVICE="/usr/share/sonic/device" +PLATFORM=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) +PLATFORM_PATH=$DEVICE/$PLATFORM +FILENAME="udevprefix.conf" + +if [ "$1" = "clear" ] +then + if [ -e $PLATFORM_PATH/$FILENAME ]; then + rm $PLATFORM_PATH/$FILENAME + fi +else + if [ -e $PLATFORM_PATH/$FILENAME ]; then + : > $PLATFORM_PATH/$FILENAME + echo -n "$1" > $PLATFORM_PATH/$FILENAME + else + touch $PLATFORM_PATH/$FILENMAE + echo -n "$1" > $PLATFORM_PATH/$FILENAME + fi +fi + diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/setup.py b/platform/broadcom/sonic-platform-modules-cel/haliburton/setup.py new file mode 100644 index 000000000000..17056855106e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/setup.py @@ -0,0 +1,34 @@ +from setuptools import setup + +DEVICE_NAME = 'celestica' +HW_SKU = 'x86_64-cel_e1031-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/haliburton/systemd/platform-modules-haliburton.service b/platform/broadcom/sonic-platform-modules-cel/haliburton/systemd/platform-modules-haliburton.service new file mode 100644 index 000000000000..bf1295038856 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/systemd/platform-modules-haliburton.service @@ -0,0 +1,14 @@ + +[Unit] +Description=Celestica haliburton platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-haliburton start +ExecStop=-/etc/init.d/platform-modules-haliburton stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/cfg/seastone2-modules.conf b/platform/broadcom/sonic-platform-modules-cel/seastone2/cfg/seastone2-modules.conf new file mode 100644 index 000000000000..795e6af74305 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/cfg/seastone2-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 +ipmi_devintf +ipmi_si diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/Makefile new file mode 100644 index 000000000000..3b59a78682a0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/Makefile @@ -0,0 +1,2 @@ +KBUILD_CFLAGS+=-DSEASTONE2 +obj-m := mc24lc64t.o baseboard_cpld.o switchboard_fpga.o \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/baseboard_cpld.c b/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/baseboard_cpld.c new file mode 100644 index 000000000000..07ab42c21686 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/baseboard_cpld.c @@ -0,0 +1,378 @@ +/* + * baseboard_cpld.c - driver for Seastone2 Base Board CPLD + * This driver implement sysfs for CPLD register access using LPC bus. + * Copyright (C) 2019 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 "baseboard" +/** + * 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) +{ + int len = -EIO; + // 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 = -EIO; + // 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); + +/** + * Show system led status - on/off/1hz/4hz + * @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 ? "4hz" : data ==0x01 ? "1hz": "on"); +} + +/** + * Set the status of system led - on/off/1hz/4hz + * @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, "4hz")){ + led_status = 0x02; + }else if(sysfs_streq(buf, "1hz")){ + 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 attribute_group baseboard_cpld_attrs_grp = { + .attrs = baseboard_cpld_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; + + 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 Seastone2 Baseboard CPLD Driver"); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/mc24lc64t.c new file mode 100644 index 000000000000..fc15bb74b68d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/mc24lc64t.c @@ -0,0 +1,174 @@ +/* + * 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 &0xff)); + 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"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/switchboard_fpga.c b/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/switchboard_fpga.c new file mode 100644 index 000000000000..5918d27f3911 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/modules/switchboard_fpga.c @@ -0,0 +1,2365 @@ +/* + * switchboard_fpga.c - driver for seastone2 Switch board FPGA/CPLD. + * + * Author: Pradchaya Phucharoen + * + * Copyright (C) 2019 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 + * \--switchboard + * |--FPGA + * |--CPLD1 + * |--CPLD2 + * \--SFF + * |--QSFP[1..32] + * \--SFP1 + * + */ + +#ifndef TEST_MODE +#define MOD_VERSION "2.2.0" +#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 + +static int majorNumber; + +#define CLASS_NAME "seastone2_fpga" +#define DRIVER_NAME "switchboard" +#define FPGA_PCI_NAME "Seastone2_fpga_pci" +#define DEVICE_NAME "fwupgrade" + + +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 fpgafw_init(void); +static void fpgafw_exit(void); + +/* +======================================== +FPGA PCIe BAR 0 Registers +======================================== +Misc Control 0x00000000 – 0x000000FF. +I2C_CH1 0x00000100 - 0x00000110 +I2C_CH2 0x00000200 - 0x00000210. +I2C_CH3 0x00000300 - 0x00000310. +I2C_CH4 0x00000400 - 0x00000410. +I2C_CH5 0x00000500 - 0x00000510. +I2C_CH6 0x00000600 - 0x00000610. +I2C_CH7 0x00000700 - 0x00000710. +I2C_CH8 0x00000800 - 0x00000810. +I2C_CH9 0x00000900 - 0x00000910. +I2C_CH10 0x00000A00 - 0x00000A10. +SPI Master 0x00001200 - 0x00001300. +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 FPGA_BROAD_REV_MSK 0x0038 +#define FPGA_BROAD_ID_MSK 0x0007 +#define FPGA_PLL_STATUS 0x0014 +#define BMC_I2C_SCRATCH 0x0020 +#define FPGA_SLAVE_CPLD_REST 0x0030 +#define FPGA_PERIPH_RESET_CTRL 0x0034 +#define FPGA_INT_STATUS 0x0040 +#define FPGA_INT_SRC_STATUS 0x0044 +#define FPGA_INT_FLAG 0x0048 +#define FPGA_INT_MASK 0x004c +#define FPGA_MISC_CTRL 0x0050 +#define FPGA_MISC_STATUS 0x0054 +#define FPGA_AVS_VID_STATUS 0x0068 +#define FPGA_FEATURE_CARD_GPIO 0x0070 +#define FPGA_PORT_XCVR_READY 0x000c + +/* I2C_MASTER BASE ADDR */ +#define I2C_MASTER_FREQ_1 0x0100 +#define I2C_MASTER_CTRL_1 0x0104 +#define I2C_MASTER_STATUS_1 0x0108 +#define I2C_MASTER_DATA_1 0x010c +#define I2C_MASTER_PORT_ID_1 0x0110 +#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_TOTAL I2C_MASTER_CH_10 + +/* 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] LPMOD 6 +[5] RSVD +[4] RST 4 +[3:1] RSVD +[0] TXDIS 0 +*/ +#define CTRL_LPMOD 6 +#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_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_RXLOS 1 +#define MASK_MODABS 0 + +enum { + I2C_SR_BIT_RXAK = 0, + I2C_SR_BIT_MIF, + I2C_SR_BIT_SRW, + I2C_SR_BIT_BCSTM, + I2C_SR_BIT_MAL, + I2C_SR_BIT_MBB, + I2C_SR_BIT_MAAS, + I2C_SR_BIT_MCF +}; + +enum { + I2C_CR_BIT_BCST = 0, + I2C_CR_BIT_RSTA = 2, + I2C_CR_BIT_TXAK, + I2C_CR_BIT_MTX, + I2C_CR_BIT_MSTA, + I2C_CR_BIT_MIEN, + I2C_CR_BIT_MEN, +}; + +/** + * + * 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_QSFP_PORT 32 +#define VIRTUAL_I2C_SFP_PORT 1 + +#define SFF_PORT_TOTAL VIRTUAL_I2C_QSFP_PORT + VIRTUAL_I2C_SFP_PORT + +#define VIRTUAL_I2C_BUS_OFFSET 2 +#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 +static struct platform_device *seastone2_dev; + +#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 + +#define GET_REG_BIT(REG,BIT) ((ioread8(REG) >> BIT) & 0x01) +#define SET_REG_BIT_H(REG,BIT) iowrite8(ioread8(REG) | (0x01 << BIT),REG) +#define SET_REG_BIT_L(REG,BIT) iowrite8(ioread8(REG) & ~(0x01 << BIT),REG) + +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]; + +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[] = { + /* BUS2 QSFP Exported as virtual bus */ + {I2C_MASTER_CH_2, 0x72, 0, QSFP, "QSFP1"}, {I2C_MASTER_CH_2, 0x72, 1, QSFP, "QSFP2"}, + {I2C_MASTER_CH_2, 0x72, 2, QSFP, "QSFP3"}, {I2C_MASTER_CH_2, 0x72, 3, QSFP, "QSFP4"}, + {I2C_MASTER_CH_2, 0x72, 4, QSFP, "QSFP5"}, {I2C_MASTER_CH_2, 0x72, 5, QSFP, "QSFP6"}, + {I2C_MASTER_CH_2, 0x72, 6, QSFP, "QSFP7"}, {I2C_MASTER_CH_2, 0x72, 7, QSFP, "QSFP8"}, + {I2C_MASTER_CH_2, 0x73, 0, QSFP, "QSFP9"}, {I2C_MASTER_CH_2, 0x73, 1, QSFP, "QSFP10"}, + {I2C_MASTER_CH_2, 0x73, 2, QSFP, "QSFP11"}, {I2C_MASTER_CH_2, 0x73, 3, QSFP, "QSFP12"}, + {I2C_MASTER_CH_2, 0x73, 4, QSFP, "QSFP13"}, {I2C_MASTER_CH_2, 0x73, 5, QSFP, "QSFP14"}, + {I2C_MASTER_CH_2, 0x73, 6, QSFP, "QSFP15"}, {I2C_MASTER_CH_2, 0x73, 7, QSFP, "QSFP16"}, + {I2C_MASTER_CH_2, 0x74, 0, QSFP, "QSFP17"}, {I2C_MASTER_CH_2, 0x74, 1, QSFP, "QSFP18"}, + {I2C_MASTER_CH_2, 0x74, 2, QSFP, "QSFP19"}, {I2C_MASTER_CH_2, 0x74, 3, QSFP, "QSFP20"}, + {I2C_MASTER_CH_2, 0x74, 4, QSFP, "QSFP21"}, {I2C_MASTER_CH_2, 0x74, 5, QSFP, "QSFP22"}, + {I2C_MASTER_CH_2, 0x74, 6, QSFP, "QSFP23"}, {I2C_MASTER_CH_2, 0x74, 7, QSFP, "QSFP24"}, + {I2C_MASTER_CH_2, 0x75, 0, QSFP, "QSFP25"}, {I2C_MASTER_CH_2, 0x75, 1, QSFP, "QSFP26"}, + {I2C_MASTER_CH_2, 0x75, 2, QSFP, "QSFP27"}, {I2C_MASTER_CH_2, 0x75, 3, QSFP, "QSFP28"}, + {I2C_MASTER_CH_2, 0x75, 4, QSFP, "QSFP29"}, {I2C_MASTER_CH_2, 0x75, 5, QSFP, "QSFP30"}, + {I2C_MASTER_CH_2, 0x75, 6, QSFP, "QSFP31"}, {I2C_MASTER_CH_2, 0x75, 7, QSFP, "QSFP32"}, + /* BUS1 SFP+ Exported as virtual bus */ + {I2C_MASTER_CH_1, 0x72, 0, SFP, "SFP1"}, + /* BUS3 Switchboard CPLD */ + {I2C_MASTER_CH_3, 0xFF, 0, NONE, "I2C_3"}, +}; + +#define VIRTUAL_I2C_PORT_LENGTH ARRAY_SIZE(fpga_i2c_bus_dev) +#define VIRTUAL_I2C_CPLD_INDEX SFF_PORT_TOTAL + +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 seastone2_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 seastone2_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 *attr, 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 *attr, + const char *buf, size_t count) +{ + ssize_t status; + uint32_t addr; + + status = kstrtou32(buf, 0, &addr); + if (status == 0) { + fpga_data->fpga_read_addr = fpga_dev.data_base_addr + addr; + status = count; + } + return status; +} + +/** + * 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 *attr, char *buf) +{ + uint32_t data; + data = ioread32(fpga_dev.data_base_addr + FPGA_SCRATCH); + data &= 0xffffffff; + return sprintf(buf, "0x%8.8x\n", data); +} + +/** + * 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 *attr, + const char *buf, size_t count) +{ + ssize_t status; + uint32_t data; + + status = kstrtou32(buf, 0, &data); + if (status == 0) { + iowrite32(data, fpga_dev.data_base_addr + FPGA_SCRATCH); + status = count; + } + return status; +} + +/** + * 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 *attr, + const char *buf, size_t count) +{ + //register is 4 bytes + uint32_t addr; + uint32_t value; + uint32_t mode = 8; + char *tok; + char clone[count]; + char *pclone = clone; + ssize_t status; + + strcpy(clone, buf); + + mutex_lock(&fpga_data->fpga_lock); + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + status = kstrtou32(tok, 0, &addr); + if (status != 0) { + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + status = kstrtou32(tok, 0, &value); + if (status != 0) { + mutex_unlock(&fpga_data->fpga_lock); + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + mode = 32; + } else { + status = kstrtou32(tok, 0, &mode); + if (status != 0) { + 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; +} + +/** + * Show FPGA port XCVR ready status + */ +static ssize_t ready_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + unsigned int REGISTER = FPGA_PORT_XCVR_READY; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> 0) & 1U); +} + +/* 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 DEVICE_ATTR_RO(ready); + +static struct attribute *fpga_attrs[] = { + &dev_attr_getreg.attr, + &dev_attr_scratch.attr, + &dev_attr_setreg.attr, + &dev_attr_ready.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; + int err; + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, + I2C_SMBUS_READ, fpga_data->cpld1_read_addr, + 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_getreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + uint8_t addr; + + status = kstrtou8(buf, 0, &addr); + if (status == 0) { + fpga_data->cpld1_read_addr = addr; + status = count; + } + return status; +} + +static ssize_t cpld1_scratch_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + // CPLD register is one byte + uint8_t data; + int err; + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_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 count) +{ + // CPLD register is one byte + uint8_t data; + ssize_t status; + int err; + + status = kstrtou8(buf, 0, &data); + if (status != 0) { + return status; + } + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_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 count; +} + +static ssize_t cpld1_setreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + + uint8_t addr, value; + char *tok; + char clone[count]; + char *pclone = clone; + ssize_t status; + int err; + + strcpy(clone, buf); + + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + return -EINVAL; + } + status = kstrtou8(tok, 0, &addr); + if (status != 0) { + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + return -EINVAL; + } + status = kstrtou8(tok, 0, &value); + if (status != 0) { + return -EINVAL; + } + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_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 count; +} + +struct device_attribute dev_attr_cpld1_getreg = __ATTR(getreg, 0600, cpld1_getreg_show, cpld1_getreg_store); +struct device_attribute dev_attr_cpld1_scratch = __ATTR(scratch, 0600, cpld1_scratch_show, cpld1_scratch_store); +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; + int err; + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, fpga_data->cpld2_read_addr, + 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_getreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + // CPLD register is one byte + uint8_t addr; + ssize_t status; + + status = kstrtou8(buf, 0, &addr); + if (status == 0) { + fpga_data->cpld2_read_addr = addr; + status = count; + } + return status; +} + +static ssize_t cpld2_scratch_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + // CPLD register is one byte + uint8_t data; + int err; + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_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 count) +{ + // CPLD register is one byte + uint8_t data; + int err; + ssize_t status; + + status = kstrtou8(buf, 0, &data); + if (status != 0) { + return -EINVAL; + } + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_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 count; +} + +static ssize_t cpld2_setreg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + uint8_t addr, value; + char *tok; + char clone[count]; + char *pclone = clone; + ssize_t status; + int err; + + strcpy(clone, buf); + + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + return -EINVAL; + } + status = kstrtou8(tok, 0, &addr); + if (status != 0) { + return -EINVAL; + } + tok = strsep((char**)&pclone, " "); + if (tok == NULL) { + return -EINVAL; + } + status = kstrtou8(tok, 0, &value); + if (status != 0) { + return -EINVAL; + } + + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_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 count; +} + +struct device_attribute dev_attr_cpld2_getreg = __ATTR(getreg, 0600, cpld2_getreg_show, cpld2_getreg_store); +struct device_attribute dev_attr_cpld2_scratch = __ATTR(scratch, 0600, cpld2_scratch_show, cpld2_scratch_store); +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) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_IRQ) & 1U); +} +DEVICE_ATTR_RO(qsfp_modirq); + +static ssize_t qsfp_modprs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_PRESENT) & 1U); +} +DEVICE_ATTR_RO(qsfp_modprs); + +static ssize_t sfp_txfault_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_TXFAULT) & 1U); +} +DEVICE_ATTR_RO(sfp_txfault); + +static ssize_t sfp_rxlos_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_RXLOS) & 1U); +} +DEVICE_ATTR_RO(sfp_rxlos); + +static ssize_t sfp_modabs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_MODABS) & 1U); +} +DEVICE_ATTR_RO(sfp_modabs); + +static ssize_t qsfp_lpmode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> CTRL_LPMOD) & 1U); +} +static ssize_t qsfp_lpmode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + uint32_t value; + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtou32(buf, 0, &value); + if (status == 0) { + // check if value is 0 clear + data = ioread32(fpga_dev.data_base_addr + REGISTER); + if (!value) + data = data & ~( (u32)0x1 << CTRL_LPMOD); + else + data = data | ((u32)0x1 << CTRL_LPMOD); + iowrite32(data, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(qsfp_lpmode); + +static ssize_t qsfp_reset_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> CTRL_RST) & 1U); +} + +static ssize_t qsfp_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + uint32_t value; + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtou32(buf, 0, &value); + if (status == 0) { + // check if value is 0 clear + data = ioread32(fpga_dev.data_base_addr + REGISTER); + if (!value) + data = data & ~( (u32)0x1 << CTRL_RST); + else + data = data | ((u32)0x1 << CTRL_RST); + iowrite32(data, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(qsfp_reset); + +static ssize_t qsfp_isr_flags_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_STATUS_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_INT_N) | BIT(INTR_PRESENT); + + mutex_lock(&fpga_data->fpga_lock); + data = (u8) ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + + /* + * Unify the return pattern to 2-bit + * [1] : module interrupt + * [0] : presence + */ + data = data & valid_bits; + data = data >> 4; + + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t qsfp_isr_flags_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + u32 value; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_STATUS_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_INT_N) | BIT(INTR_PRESENT); + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtou32(buf, 0, &value); + if (status == 0) { + value = value << 4; + value = value & valid_bits; + iowrite32(value, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(qsfp_isr_flags); + +static ssize_t qsfp_isr_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_MASK_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_INT_N) | BIT(INTR_PRESENT); + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + + /* + * Unify the return pattern to 2-bit + * [1] : module interrupt + * [0] : presence + */ + data = data & valid_bits; + data = data >> 4; + + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t qsfp_isr_mask_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + u32 value; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_MASK_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_INT_N) | BIT(INTR_PRESENT); + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtou32(buf, 0, &value); + if (status == 0) { + value = value << 4; + value = value & valid_bits; + iowrite32(value, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(qsfp_isr_mask); + +static ssize_t sfp_txdisable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> CTRL_TXDIS) & 1U); +} +static ssize_t sfp_txdisable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + long value; + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtol(buf, 0, &value); + if (status == 0) { + // check if value is 0 clear + data = ioread32(fpga_dev.data_base_addr + REGISTER); + if (!value) + data = data & ~( (u32)0x1 << CTRL_TXDIS); + else + data = data | ((u32)0x1 << CTRL_TXDIS); + iowrite32(data, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(sfp_txdisable); + +static ssize_t sfp_isr_flags_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 data; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_STATUS_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_RXLOS) | BIT(INTR_MODABS); + + mutex_lock(&fpga_data->fpga_lock); + data = (u8) ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + + data = data & valid_bits; + + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t sfp_isr_flags_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + u32 value; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_STATUS_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_INT_N) | BIT(INTR_PRESENT); + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtou32(buf, 0, &value); + if (status == 0) { + value = value & valid_bits; + iowrite32(value, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(sfp_isr_flags); + +static ssize_t sfp_isr_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 data; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_MASK_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_RXLOS) | BIT(INTR_MODABS); + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + + data = data & valid_bits; + + return sprintf(buf, "0x%2.2x\n", data); +} + +static ssize_t sfp_isr_mask_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t status; + u32 value; + u8 valid_bits; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_INT_MASK_BASE + (portid - 1) * 0x10; + valid_bits = BIT(INTR_RXLOS) | BIT(INTR_MODABS); + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtou32(buf, 0, &value); + if (status == 0) { + value = value & valid_bits; + iowrite32(value, fpga_dev.data_base_addr + REGISTER); + status = count; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(sfp_isr_mask); + +static struct attribute *sff_attrs[] = { + &dev_attr_qsfp_modirq.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_isr_flags.attr, + &dev_attr_qsfp_isr_mask.attr, + &dev_attr_sfp_txfault.attr, + &dev_attr_sfp_rxlos.attr, + &dev_attr_sfp_modabs.attr, + &dev_attr_sfp_txdisable.attr, + &dev_attr_sfp_isr_flags.attr, + &dev_attr_sfp_isr_mask.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[VIRTUAL_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[VIRTUAL_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 count) +{ + 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[VIRTUAL_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[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_WRITE, 0x09, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_mode_1); + return count; +} +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 "off", "green", "amber", "both" + __u8 led_color1, led_color2; + int err; + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD1_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x0A, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color1); + if (err < 0) + return err; + err = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, I2C_SMBUS_READ, 0x0A, + I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&led_color2); + if (err < 0) + return err; + return sprintf(buf, "%s %s\n", + led_color1 == 0x03 ? "off" : led_color1 == 0x02 ? "green" : led_color1 == 0x01 ? "amber" : "both", + led_color2 == 0x03 ? "off" : led_color2 == 0x02 ? "green" : led_color2 == 0x01 ? "amber" : "both"); +} + +static ssize_t port_led_color_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int status; + __u8 led_color; + if (sysfs_streq(buf, "off")) { + led_color = 0x03; + } else if (sysfs_streq(buf, "green")) { + led_color = 0x02; + } else if (sysfs_streq(buf, "amber")) { + led_color = 0x01; + } else if (sysfs_streq(buf, "both")) { + led_color = 0x00; + } else { + status = -EINVAL; + return status; + } + status = fpga_i2c_access(fpga_data->i2c_adapter[VIRTUAL_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[VIRTUAL_I2C_CPLD_INDEX], + CPLD2_SLAVE_ADDR, 0x00, + I2C_SMBUS_WRITE, 0x0A, I2C_SMBUS_BYTE_DATA, + (union i2c_smbus_data*)&led_color); + return count; +} +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 * seastone2_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_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_FDR0; + unsigned int REG_CR0; + unsigned int REG_SR0; + unsigned int REG_DR0; + unsigned int REG_ID0; + + 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_FDR0 = I2C_MASTER_FREQ_1 + (master_bus - 1) * 0x0100; + REG_CR0 = I2C_MASTER_CTRL_1 + (master_bus - 1) * 0x0100; + REG_SR0 = I2C_MASTER_STATUS_1 + (master_bus - 1) * 0x0100; + REG_DR0 = I2C_MASTER_DATA_1 + (master_bus - 1) * 0x0100; + REG_ID0 = I2C_MASTER_PORT_ID_1 + (master_bus - 1) * 0x0100; + + check(pci_bar + REG_SR0); + check(pci_bar + REG_CR0); + + timeout = jiffies + msecs_to_jiffies(timeout); + while (1) { + Status = ioread8(pci_bar + REG_SR0); + if (jiffies > timeout) { + info("Status %2.2X", Status); + info("Error Timeout"); + error = -ETIMEDOUT; + break; + } + + + if (Status & (1 << I2C_SR_BIT_MIF)) { + break; + } + + if (writing == 0 && (Status & (1 << I2C_SR_BIT_MCF))) { + break; + } + } + Status = ioread8(pci_bar + REG_SR0); + iowrite8(0, pci_bar + REG_SR0); + + if (error < 0) { + info("Status %2.2X", Status); + return error; + } + + if (!(Status & (1 << I2C_SR_BIT_MCF))) { + info("Error Unfinish"); + return -EIO; + } + + if (Status & (1 << I2C_SR_BIT_MAL)) { + info("Error MAL"); + return -EAGAIN; + } + + if (Status & (1 << I2C_SR_BIT_RXAK)) { + info( "SL No Acknowlege"); + if (writing) { + info("Error No Acknowlege"); + iowrite8(1 << I2C_CR_BIT_MEN, pci_bar + REG_CR0); + return -ENXIO; + } + } else { + info( "SL Acknowlege"); + } + + return 0; +} + +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; + + unsigned int REG_FDR0; + unsigned int REG_CR0; + unsigned int REG_SR0; + unsigned int REG_DR0; + unsigned int REG_ID0; + + REG_FDR0 = 0; + REG_CR0 = 0; + REG_SR0 = 0; + REG_DR0 = 0; + REG_ID0 = 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)%-15s|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 + /* 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 = -ENXIO; + goto Done; + } + + REG_FDR0 = I2C_MASTER_FREQ_1 + (master_bus - 1) * 0x0100; + REG_CR0 = I2C_MASTER_CTRL_1 + (master_bus - 1) * 0x0100; + REG_SR0 = I2C_MASTER_STATUS_1 + (master_bus - 1) * 0x0100; + REG_DR0 = I2C_MASTER_DATA_1 + (master_bus - 1) * 0x0100; + REG_ID0 = I2C_MASTER_PORT_ID_1 + (master_bus - 1) * 0x0100; + + iowrite8(portid, pci_bar + REG_ID0); + + ////[S][ADDR/R] + // Clear status register + iowrite8(0, pci_bar + REG_SR0); + iowrite8(1 << I2C_CR_BIT_MIEN | + 1 << I2C_CR_BIT_MTX | + 1 << I2C_CR_BIT_MSTA , pci_bar + REG_CR0); + SET_REG_BIT_H(pci_bar + REG_CR0, I2C_CR_BIT_MEN); + + 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_DR0); + } else { + // sent device address with Write mode + iowrite8(addr << 1 | 0x00, pci_bar + REG_DR0); + } + + + + info( "MS Start"); + + //// Wait {A} + error = i2c_wait_ack(adapter, 12, 1); + if (error < 0) { + info( "get error %d", 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_DR0); + info( "MS Send CMD 0x%2.2X", cmd); + + // Wait {A} + error = i2c_wait_ack(adapter, 12, 1); + if (error < 0) { + info( "get error %d", 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 modes 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_DR0); + info( "MS Send CNT 0x%2.2X", cnt); + + // Wait {A} + error = i2c_wait_ack(adapter, 12, 1); + if (error < 0) { + info( "get error %d", 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 + )) { + 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++) { + + iowrite8(data->block[bid], pci_bar + REG_DR0); + info( " Data > %2.2X", data->block[bid]); + // Wait {A} + error = i2c_wait_ack(adapter, 12, 1); + if (error < 0) { + 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"); + + SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MEN); + iowrite8(1 << I2C_CR_BIT_MIEN | + 1 << I2C_CR_BIT_MTX | + 1 << I2C_CR_BIT_MSTA | + 1 << I2C_CR_BIT_RSTA , pci_bar + REG_CR0); + SET_REG_BIT_H(pci_bar + REG_CR0, I2C_CR_BIT_MEN); + + // sent Address with Read mode + iowrite8( addr << 1 | 0x1 , pci_bar + REG_DR0); + + // Wait {A} + error = i2c_wait_ack(adapter, 12, 1); + if (error < 0) { + 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; + } + + bid = 0; + info( "MS Receive"); + + //set to Receive mode + iowrite8(1 << I2C_CR_BIT_MEN | + 1 << I2C_CR_BIT_MIEN | + 1 << I2C_CR_BIT_MSTA , pci_bar + REG_CR0); + + for (bid = -1; bid < cnt; bid++) { + + // Wait for byte transfer + error = i2c_wait_ack(adapter, 12, 0); + if (error < 0) { + goto Done; + } + + if (bid == cnt - 2) { + info( "SET NAK"); + SET_REG_BIT_H(pci_bar + REG_CR0, I2C_CR_BIT_TXAK); + } + + if (bid < 0) { + ioread8(pci_bar + REG_DR0); + info( "READ Dummy Byte" ); + } else { + + if (bid == cnt - 1) { + info ( "SET STOP in read loop"); + SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MSTA); + } + if (size == I2C_SMBUS_I2C_BLOCK_DATA) { + // block[0] is read length + data->block[bid + 1] = ioread8(pci_bar + REG_DR0); + } else { + data->block[bid] = ioread8(pci_bar + REG_DR0); + } + info( "DATA IN [%d] %2.2X", bid, data->block[bid]); + + if (size == I2C_SMBUS_BLOCK_DATA && bid == 0) { + cnt = data->block[0] + 1; + } + } + } + } + + // [P] + SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MSTA); + info( "MS STOP"); + +Done: + iowrite8(1 << I2C_CR_BIT_MEN, pci_bar + REG_CR0); + check(pci_bar + REG_CR0); + check(pci_bar + REG_SR0); +#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 = 0; + struct i2c_dev_data *dev_data; + unsigned char master_bus; + unsigned char switch_addr; + unsigned char channel; + uint16_t prev_port = 0; + unsigned char prev_switch; + unsigned char prev_ch; + int retry; + + 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; + + // 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 + 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 deselect 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 deselect 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 + error = smbus_access(adapter, addr, flags, rw, cmd, size, data); + 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); + } + +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 error; +} + + + +/** + * 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 seastone2_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 * seastone2_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; + void __iomem *i2c_freq_base_reg; + + 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 = &seastone2_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_freq_base_reg = fpga_dev.data_base_addr + I2C_MASTER_FREQ_1; + iowrite8(0x07, i2c_freq_base_reg + (new_data->pca9548.master_bus - 1) * 0x100); // 0x07 400kHz + 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; +}; + +/** + * Board info for QSFP/SFP+ eeprom. + * Note: Using sff8436 as I2C eeprom driver. + */ +static struct i2c_board_info sff8436_eeprom_info[] = { + { I2C_BOARD_INFO("optoe1", 0x50) }, + { I2C_BOARD_INFO("optoe2", 0x50) }, +}; + +static int seastone2_drv_probe(struct platform_device *pdev) +{ + 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 seastone2_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]); + } + + 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 = 0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++) { + fpga_data->i2c_adapter[portid_count] = seastone2_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] = seastone2_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[VIRTUAL_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[VIRTUAL_I2C_CPLD_INDEX], CPLD2_SLAVE_ADDR, 0x00, + I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, (union i2c_smbus_data*)&cpld2_version); + + printk(KERN_INFO "CPLD1 VERSON: %2.2x\n", cpld1_version); + printk(KERN_INFO "CPLD2 VERSON: %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++) { + + 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 seastone2_drv_remove(struct platform_device *pdev) +{ + int portid_count; + struct sff_device_data *rem_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]); + i2c_del_adapter(fpga_data->i2c_adapter[portid_count]); + } + } + + 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 seastone2_drv = { + .probe = seastone2_drv_probe, + .remove = __exit_p(seastone2_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 = pci_iomap(pdev, FPGA_PCI_BAR_NUM, 0); + 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); + if ((err = fpgafw_init()) < 0) { + goto pci_unmap; + } + seastone2_dev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); + platform_driver_register(&seastone2_drv); + return 0; + +pci_unmap: + pci_iounmap(pdev, fpga_dev.data_base_addr); +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(&seastone2_drv); + platform_device_unregister(seastone2_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"); // Made it! device was initialized + return 0; +} + +static void fpgafw_exit(void) { + device_destroy(fpgafwclass, MKDEV(majorNumber, 0)); // remove the device + class_destroy(fpgafwclass); // remove the device class + unregister_chrdev(majorNumber, DEVICE_NAME); // unregister the major number + printk(KERN_INFO "Goodbye!\n"); +} + +int seastone2_init(void) +{ + int rc; + rc = pci_register_driver(&pci_dev_ops); + if (rc) + return rc; + return 0; +} + +void seastone2_exit(void) +{ + pci_unregister_driver(&pci_dev_ops); +} + +module_init(seastone2_init); +module_exit(seastone2_exit); + +MODULE_AUTHOR("Pradchaya P. "); +MODULE_DESCRIPTION("Celestica Seastone2 switchboard driver"); +MODULE_VERSION(MOD_VERSION); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/seastone2/systemd/platform-modules-seastone2.service b/platform/broadcom/sonic-platform-modules-cel/seastone2/systemd/platform-modules-seastone2.service new file mode 100644 index 000000000000..02553bf24538 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/seastone2/systemd/platform-modules-seastone2.service @@ -0,0 +1,14 @@ + +[Unit] +Description=Celestica seastone2 platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-seastone2 start +ExecStop=-/etc/init.d/platform-modules-seastone2 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/services/fancontrol/fancontrol b/platform/broadcom/sonic-platform-modules-cel/services/fancontrol/fancontrol new file mode 100755 index 000000000000..da32acedd2f9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/fancontrol/fancontrol @@ -0,0 +1,614 @@ +#!/bin/bash +# +# Simple script implementing a temperature dependent fan speed control +# Supported Linux kernel versions: 2.6.5 and later +# +# Version 0.70 +# +# Usage: fancontrol [CONFIGFILE] +# +# Dependencies: +# bash, egrep, sed, cut, sleep, readlink, lm_sensors :) +# +# Please send any questions, comments or success stories to +# marius.reiner@hdev.de +# Thanks! +# +# For configuration instructions and warnings please see fancontrol.txt, which +# can be found in the doc/ directory or at the website mentioned above. +# +# +# Copyright 2003 Marius Reiner +# Copyright (C) 2007-2009 Jean Delvare +# +# 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. +# +# 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 Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# +# + +PIDFILE="/var/run/fancontrol.pid" +THERMAL_OVERLOAD_CONTROL_FILE="/usr/local/bin/thermal_overload_control.sh" + +#DEBUG=1 +MAX=255 + +function LoadConfig +{ + local fcvcount fcv + + echo "Loading configuration from $1 ..." + if [ ! -r "$1" ] + then + echo "Error: Can't read configuration file" >&2 + exit 1 + fi + + # grep configuration from file + INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'` + DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'` + DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'` + FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'` + MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'` + MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'` + MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'` + MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'` + # optional settings: + FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'` + MINPWM=`egrep '^MINPWM=.*$' $1 | sed -e 's/MINPWM=//g'` + MAXPWM=`egrep '^MAXPWM=.*$' $1 | sed -e 's/MAXPWM=//g'` + THYST=`egrep '^THYST=.*$' $1 | sed -e 's/THYST=//g'` + MAXTEMPCRIT=`egrep '^MAXTEMPCRIT=.*$' $1 | sed -e 's/MAXTEMPCRIT=//g'` + MAXTEMPTYPE=`egrep '^MAXTEMPTYPE=.*$' $1 | sed -e 's/MAXTEMPTYPE=//g'` + echo + # Check whether all mandatory settings are set + if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]] + then + echo "Some mandatory settings missing, please check your config file!" >&2 + exit 1 + fi + if [ "$INTERVAL" -le 0 ] + then + echo "Error in configuration file:" >&2 + echo "INTERVAL must be at least 1" >&2 + exit 1 + fi + + # write settings to arrays for easier use and print them + echo + echo "Common settings:" + echo " INTERVAL=$INTERVAL" + + let fcvcount=0 + for fcv in $FCTEMPS + do + if ! echo $fcv | egrep -q '=' + then + echo "Error in configuration file:" >&2 + echo "FCTEMPS value is improperly formatted" >&2 + exit 1 + fi + + AFCPWM[$fcvcount]=`echo $fcv |cut -d'=' -f1` + AFCTEMP[$fcvcount]=`echo $fcv |cut -d'=' -f2` + AFCFAN[$fcvcount]=`echo $FCFANS |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2` + AFCFANFAULT[$fcvcount]=`echo "${AFCFAN[$fcvcount]}" |sed -e 's/input/fault/g'` + AFCMINTEMP[$fcvcount]=`echo $MINTEMP |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2` + AFCMAXTEMP[$fcvcount]=`echo $MAXTEMP |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2` + AFCMINSTART[$fcvcount]=`echo $MINSTART |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2` + AFCMINSTOP[$fcvcount]=`echo $MINSTOP |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2` + AFCMINPWM[$fcvcount]=`echo $MINPWM |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2` + [ -z "${AFCMINPWM[$fcvcount]}" ] && AFCMINPWM[$fcvcount]=0 + AFCMAXPWM[$fcvcount]=`echo $MAXPWM |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2` + [ -z "${AFCMAXPWM[$fcvcount]}" ] && AFCMAXPWM[$fcvcount]=255 + AFCTHYST[$fcvcount]=`echo $THYST |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2` + [ -z "${AFCTHYST[$fcvcount]}" ] && AFCTHYST[$fcvcount]=0 + + # verify the validity of the settings + if [ "${AFCMINTEMP[$fcvcount]}" -ge "${AFCMAXTEMP[$fcvcount]}" ] + then + echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2 + echo "MINTEMP must be less than MAXTEMP" >&2 + exit 1 + fi + if [ "${AFCMAXPWM[$fcvcount]}" -gt 255 ] + then + echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2 + echo "MAXPWM must be at most 255" >&2 + exit 1 + fi + if [ "${AFCMINSTOP[$fcvcount]}" -ge "${AFCMAXPWM[$fcvcount]}" ] + then + echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2 + echo "MINSTOP must be less than MAXPWM" >&2 + exit 1 + fi + if [ "${AFCMINSTOP[$fcvcount]}" -lt "${AFCMINPWM[$fcvcount]}" ] + then + echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2 + echo "MINSTOP must be greater than or equal to MINPWM" >&2 + exit 1 + fi + if [ "${AFCMINPWM[$fcvcount]}" -lt 0 ] + then + echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2 + echo "MINPWM must be at least 0" >&2 + exit 1 + fi + + echo + echo "Settings for ${AFCPWM[$fcvcount]}:" + echo " Depends on ${AFCTEMP[$fcvcount]}" + echo " Controls ${AFCFAN[$fcvcount]}" + echo " MINTEMP=${AFCMINTEMP[$fcvcount]}" + echo " MAXTEMP=${AFCMAXTEMP[$fcvcount]}" + echo " MINSTART=${AFCMINSTART[$fcvcount]}" + echo " MINSTOP=${AFCMINSTOP[$fcvcount]}" + echo " MINPWM=${AFCMINPWM[$fcvcount]}" + echo " MAXPWM=${AFCMAXPWM[$fcvcount]}" + echo " THYST=${AFCTHYST[$fcvcount]}" + let fcvcount=fcvcount+1 + done + echo + + + let tscount=0 + for ts in $MAXTEMPCRIT + do + CSTEMP[$tscount]=`echo $ts | cut -d '=' -f1` + CSMAXTEMPCRIT[$tscount]=`echo $ts | cut -d '=' -f2` + CSMAXTEMPTYPE=($(echo $MAXTEMPTYPE |sed -e 's/ /\n/g'| cut -d'=' -f2)) + + echo + echo "Settings for ${CSMAXTEMPTYPE[$tscount]} temperature sensor:" + echo " Depends on ${CSTEMP[$tscount]}" + echo " MAXTEMPCRIT=${CSMAXTEMPCRIT[$tscount]}" + let tscount=tscount+1 + done + echo + +} + + +function DevicePath() +{ + if [ -h "$1/device" ] + then + readlink -f "$1/device" | sed -e 's/^\/sys\///' + fi +} + +function DeviceName() +{ + if [ -r "$1/name" ] + then + cat "$1/name" | sed -e 's/[[:space:]=]/_/g' + elif [ -r "$1/device/name" ] + then + cat "$1/device/name" | sed -e 's/[[:space:]=]/_/g' + fi +} + +function ValidateDevices() +{ + local OLD_DEVPATH="$1" OLD_DEVNAME="$2" outdated=0 + local entry device name path + + for entry in $OLD_DEVPATH + do + device=`echo "$entry" | sed -e 's/=[^=]*$//'` + path=`echo "$entry" | sed -e 's/^[^=]*=//'` + + if [ "`DevicePath "$device"`" != "$path" ] + then + echo "Device path of $device has changed" >&2 + outdated=1 + fi + done + + for entry in $OLD_DEVNAME + do + device=`echo "$entry" | sed -e 's/=[^=]*$//'` + name=`echo "$entry" | sed -e 's/^[^=]*=//'` + + if [ "`DeviceName "$device"`" != "$name" ] + then + echo "Device name of $device has changed" >&2 + outdated=1 + fi + done + + return $outdated +} + +# Check that all referenced sysfs files exist +function CheckFiles +{ + local outdated=0 fcvcount pwmo tsen fan + + let fcvcount=0 + while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs + do + pwmo=${AFCPWM[$fcvcount]} + if [ ! -w $pwmo ] + then + echo "Error: file $pwmo doesn't exist" >&2 + outdated=1 + fi + let fcvcount=$fcvcount+1 + done + + let fcvcount=0 + while (( $fcvcount < ${#AFCTEMP[@]} )) # go through all temp inputs + do + tsen=${AFCTEMP[$fcvcount]} + if [ ! -r $tsen ] + then + echo "Error: file $tsen doesn't exist" >&2 + outdated=1 + fi + let fcvcount=$fcvcount+1 + done + + let fcvcount=0 + while (( $fcvcount < ${#AFCFAN[@]} )) # go through all fan inputs + do + # A given PWM output can control several fans + for fan in $(echo ${AFCFAN[$fcvcount]} | sed -e 's/+/ /') + do + if [ ! -r $fan ] + then + echo "Error: file $fan doesn't exist" >&2 + outdated=1 + fi + done + let fcvcount=$fcvcount+1 + done + + if [ $outdated -eq 1 ] + then + echo >&2 + echo "At least one referenced file is missing. Either some required kernel" >&2 + echo "modules haven't been loaded, or your configuration file is outdated." >&2 + echo "In the latter case, you should run pwmconfig again." >&2 + fi + + return $outdated +} + +if [ "$1" == "--check" ] +then + if [ -f "$2" ] + then + LoadConfig $2 + else + LoadConfig /etc/fancontrol + fi + exit 0 +fi + +if [ -f "$1" ] +then + LoadConfig $1 +else + LoadConfig /etc/fancontrol +fi + +# Detect path to sensors +if echo "${AFCPWM[0]}" | egrep -q '^/' +then + DIR=/ +elif echo "${AFCPWM[0]}" | egrep -q '^hwmon[0-9]' +then + DIR=/sys/class/hwmon +elif echo "${AFCPWM[0]}" | egrep -q '^[1-9]*[0-9]-[0-9abcdef]{4}' +then + DIR=/sys/bus/i2c/devices +else + echo "$0: Invalid path to sensors" >&2 + exit 1 +fi + +if [ ! -d $DIR ] +then + echo $0: 'No sensors found! (did you load the necessary modules?)' >&2 + exit 1 +fi +cd $DIR + +# Check for configuration change +# if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] +# then +# echo "Configuration is too old, please run pwmconfig again" >&2 +# exit 1 +# fi + +if [ "$DIR" = "/" -a -n "$DEVPATH" ] +then + echo "Unneeded DEVPATH with absolute device paths" >&2 + exit 1 +fi +if ! ValidateDevices "$DEVPATH" "$DEVNAME" +then + echo "Configuration appears to be outdated, please run pwmconfig again" >&2 + exit 1 +fi +CheckFiles || exit 1 + +if [ -f "$PIDFILE" ] +then + echo "File $PIDFILE exists, is fancontrol already running?" >&2 + exit 1 +fi +echo $$ > "$PIDFILE" + +# $1 = pwm file name +function pwmdisable() +{ + local ENABLE=${1}_enable + + # No enable file? Just set to max + if [ ! -f $ENABLE ] + then + echo $MAX > $1 + return 0 + fi + + # Try pwmN_enable=0 + echo 0 > $ENABLE 2> /dev/null + if [ `cat $ENABLE` -eq 0 ] + then + # Success + echo $MAX > $1 + return 0 + fi + + # It didn't work, try pwmN_enable=1 pwmN=255 + echo 1 > $ENABLE 2> /dev/null + echo $MAX > $1 + if [ `cat $ENABLE` -eq 1 -a `cat $1` -ge 190 ] + then + # Success + return 0 + fi + + # Nothing worked + echo "$ENABLE stuck to" `cat $ENABLE` >&2 + return 1 +} + +# $1 = pwm file name +function pwmenable() +{ + local ENABLE=${1}_enable + + if [ -f $ENABLE ] + then + echo 1 > $ENABLE 2> /dev/null + if [ $? -ne 0 ] + then + return 1 + fi + fi + echo $MAX > $1 +} + +function restorefans() +{ + local status=$1 fcvcount pwmo + + echo 'Aborting, restoring fans...' + let fcvcount=0 + while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs + do + pwmo=${AFCPWM[$fcvcount]} + pwmdisable $pwmo + let fcvcount=$fcvcount+1 + done + echo 'Verify fans have returned to full speed' + rm -f "$PIDFILE" + exit $status +} + +trap 'restorefans 0' SIGQUIT SIGTERM +trap 'restorefans 1' SIGHUP SIGINT + +function upperBound +{ + # $1: temperature + # $2: Tmin + # $3: Tmax + # $4: MinPWM + # $5: MaxPWM + # $6 Thyst + # upper_bound = (temperature-Tmin+2) * (MaxPWM-MinPWM)/(Tmax-Tmin)+MinPWM + let a="($1-$2+$6)*($5-$4)/($3-$2)+$4" + up_b=$a +} +function lowerBound +{ + # $1: temperature + # $2: Tmin + # $3: Tmax + # $4: MinPWM + # $5: MaxPWM + # $6 Thyst + # lower_bound = (temperature-Tmin) *(MaxPWM-MinPWM)/(Tmax-Tmin)+MinPWM + let a="($1-$2)*($5-$4)/($3-$2)+$4" + lw_b=$a +} + +# main function +function UpdateFanSpeeds +{ + local fcvcount + local pwmo tsens fan mint maxt minsa minso minpwm maxpwm tHyst + local tval pwmpval fanval min_fanval one_fan one_fanval + local -i pwmval + + let fcvcount=0 + while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs + do + #hopefully shorter vars will improve readability: + pwmo=${AFCPWM[$fcvcount]} + tsens=${AFCTEMP[$fcvcount]} + fan=${AFCFAN[$fcvcount]} + let mint="${AFCMINTEMP[$fcvcount]}*1000" + let maxt="${AFCMAXTEMP[$fcvcount]}*1000" + minsa=${AFCMINSTART[$fcvcount]} + minso=${AFCMINSTOP[$fcvcount]} + minpwm=${AFCMINPWM[$fcvcount]} + maxpwm=${AFCMAXPWM[$fcvcount]} + let tHyst="${AFCTHYST[$fcvcount]}*1000" + + read tval < ${tsens} + if [ $? -ne 0 ] + then + echo "Error reading temperature from $DIR/$tsens" + restorefans 1 + fi + + read pwmpval < ${pwmo} + if [ $? -ne 0 ] + then + echo "Error reading PWM value from $DIR/$pwmo" + restorefans 1 + fi + + # If fanspeed-sensor output shall be used, do it + if [[ -n ${fan} ]] + then + min_fanval=100000 + fanval= + # A given PWM output can control several fans + for one_fan in $(echo $fan | sed -e 's/+/ /') + do + read one_fanval < ${one_fan} + if [ $? -ne 0 ] + then + echo "Error reading Fan value from $DIR/$one_fan" >&2 + restorefans 1 + fi + + # Remember the minimum, it only matters if it is 0 + if [ $one_fanval -lt $min_fanval ] + then + min_fanval=$one_fanval + fi + + if [ -z "$fanval" ] + then + fanval=$one_fanval + else + fanval="$fanval/$one_fanval" + fi + done + else + fanval=1 # set it to a non zero value, so the rest of the script still works + fi + + # debug info + if [ "$DEBUG" != "" ] + then + echo "pwmo=$pwmo" + echo "tsens=$tsens" + echo "fan=$fan" + echo "mint=$mint" + echo "maxt=$maxt" + echo "minsa=$minsa" + echo "minso=$minso" + echo "minpwm=$minpwm" + echo "maxpwm=$maxpwm" + echo "tval=$tval" + echo "pwmpval=$pwmpval" + echo "fanval=$fanval" + echo "min_fanval=$min_fanval" + echo "tHyst=$tHyst" + fi + pwmval=$pwmpval + if (( $tval+$tHyst <= $mint )) + then pwmval=$minpwm # below min temp, use defined min pwm + elif (( $tval >= $maxt )) + then pwmval=$maxpwm # over max temp, use defined max pwm + elif (( $tval+$tHyst >= $maxt )) && (( $pwmpval == $maxpwm )) + then pwmval=$maxpwm + else + # calculate the new value from temperature and settings + # pwmval="(${tval}-${mint})*(${maxpwm}-${minso})/(${maxt}-${mint})+${minso} + lowerBound ${tval} ${mint} ${maxt} ${minpwm} ${maxpwm} ${tHyst} + lb=$lw_b + upperBound ${tval} ${mint} ${maxt} ${minpwm} ${maxpwm} ${tHyst} + ub=$up_b + + if [ "$DEBUG" != "" ] + then + echo "old pwm=$pwmval lw_b=$lw_b up_b=$up_b" + fi + + if [[ "$pwmval" -gt "$ub" ]] + then + pwmval=$ub + else + if [[ "$pwmval" -lt "$lb" ]] + then + pwmval=$lb + fi + fi + + if [ $pwmpval -eq 0 -o $min_fanval -eq 0 ] + then # if fan was stopped start it using a safe value + echo $minsa > $pwmo + # Sleep while still handling signals + sleep 1 & + wait + fi + fi + echo $pwmval > $pwmo # write new value to pwm output + if [ $? -ne 0 ] + then + echo "Error writing PWM value to $DIR/$pwmo" >&2 + restorefans 1 + fi + if [ "$DEBUG" != "" ] + then + echo "new pwmval=$pwmval" + fi + let fcvcount=$fcvcount+1 + done +} + +echo 'Enabling PWM on fans...' +let fcvcount=0 +while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs +do + pwmo=${AFCPWM[$fcvcount]} + pwmenable $pwmo + if [ $? -ne 0 ] + then + echo "Error enabling PWM on $DIR/$pwmo" >&2 + restorefans 1 + fi + let fcvcount=$fcvcount+1 +done + +echo 'Starting automatic fan control...' + +# main loop calling the main function at specified intervals +while true +do + UpdateFanSpeeds + # Sleep while still handling signals + sleep $INTERVAL & + wait +done diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/platform_api_mgnt.sh b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/platform_api_mgnt.sh new file mode 100755 index 000000000000..e1d330357894 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/platform_api_mgnt.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +PREV_REBOOT_CAUSE="/host/reboot-cause/" +DEVICE="/usr/share/sonic/device" +PLATFORM=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) +FILES=$DEVICE/$PLATFORM/api_files + +install() { + # Install sonic-platform package + if [ -e $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl ]; then + pip install $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl + fi +} + +init() { + # mount needed files for sonic-platform package + mkdir -p $FILES + + mkdir -p $FILES/reboot-cause + mount -B $PREV_REBOOT_CAUSE $FILES/reboot-cause +} + +deinit() { + # deinit sonic-platform package + umount -f $PREV_REBOOT_CAUSE $FILES/reboot-cause >/dev/null 2>/dev/null +} + +uninstall() { + # Uninstall sonic-platform package + pip uninstall -y sonic-platform >/dev/null 2>/dev/null +} + +case "$1" in +install | uninstall | init | deinit) + $1 + ;; +*) + echo "Usage: $0 {install|uninstall|init|deinit}" + exit 1 + ;; +esac diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/setup.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/setup.py new file mode 100755 index 000000000000..b0c8d1d8c9b8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/setup.py @@ -0,0 +1,30 @@ +from setuptools import setup + +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', + ], + 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/services/platform_api/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/__init__.py new file mode 100644 index 000000000000..7b86fa12b515 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +import chassis +import platform diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/chassis.py new file mode 100644 index 000000000000..aa7671484889 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/chassis.py @@ -0,0 +1,317 @@ +#!/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 +# +############################################################################# + +try: + import sys + from sonic_platform_base.chassis_base import ChassisBase + from common import Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + CHASSIS_CONFIG = 'chassis.json' + THERMAL_CONFIG = 'thermal.json' + SFP_CONFIG = 'sfp.json' + PSU_CONFIG = 'psu.json' + FAN_CONFIG = 'fan.json' + COMPONENT_CONFIG = 'component.json' + + def __init__(self): + ChassisBase.__init__(self) + self._api_common = Common() + config_path = self._api_common.get_config_path(self.CHASSIS_CONFIG) + self._config = self._api_common.load_json_file(config_path) + + self.sfp_module_initialized = False + self.__initialize_eeprom() + + if not self._api_common.is_host(): + self.__initialize_fan() + self.__initialize_psu() + self.__initialize_thermals() + else: + self.__initialize_components() + + def __initialize_fan(self): + from sonic_platform.fan import Fan + from sonic_platform.fan_drawer import FanDrawer + + fan_config_path = self._api_common.get_config_path(self.FAN_CONFIG) + self._fan_config = self._api_common.load_json_file(fan_config_path) + + if self._fan_config: + fan_index = 0 + for drawer_index in range(0, self._fan_config['drawer_num']): + drawer_fan_list = [] + for index in range(0, self._fan_config['fan_num_per_drawer']): + fan = Fan(fan_index, conf=self._fan_config) + fan_index += 1 + self._fan_list.append(fan) + drawer_fan_list.append(fan) + fan_drawer = FanDrawer(drawer_index, drawer_fan_list) + self._fan_drawer_list.append(fan_drawer) + + def __initialize_sfp(self): + from sonic_platform.sfp import Sfp + + sfp_config_path = self._api_common.get_config_path(self.SFP_CONFIG) + sfp_config = self._api_common.load_json_file(sfp_config_path) + + sfp_index = 0 + for index in range(0, sfp_config['port_num']): + sfp = Sfp(sfp_index, conf=sfp_config) + self._sfp_list.append(sfp) + sfp_index += 1 + self.sfp_module_initialized = True + + def __initialize_psu(self): + from sonic_platform.psu import Psu + + psu_config_path = self._api_common.get_config_path(self.PSU_CONFIG) + psu_config = self._api_common.load_json_file(psu_config_path) + + if psu_config: + psu_index = 0 + for index in range(0, psu_config['psu_num']): + psu = Psu(psu_index, conf=psu_config, + fan_conf=self._fan_config) + psu_index += 1 + self._psu_list.append(psu) + + def __initialize_thermals(self): + from sonic_platform.thermal import Thermal + + thermal_config_path = self._api_common.get_config_path( + self.THERMAL_CONFIG) + thermal_config = self._api_common.load_json_file(thermal_config_path) + + thermal_index = 0 + for index in range(0, thermal_config['thermal_num']): + thermal = Thermal(thermal_index, conf=thermal_config) + thermal_index += 1 + self._thermal_list.append(thermal) + + def __initialize_eeprom(self): + from sonic_platform.eeprom import Tlv + self._eeprom = Tlv(self._config) + + def __initialize_components(self): + from component import Component + + component_config_path = self._api_common.get_config_path( + self.COMPONENT_CONFIG) + component_config = self._api_common.load_json_file( + component_config_path) + + for index in range(0, component_config['component_num']): + component = Component(index, conf=component_config) + self._component_list.append(component) + + 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_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. + + Avaliable reboot cause: + REBOOT_CAUSE_POWER_LOSS = "Power Loss" + REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "Thermal Overload: CPU" + REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "Thermal Overload: ASIC" + REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "Thermal Overload: Other" + REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED = "Insufficient Fan Speed" + REBOOT_CAUSE_WATCHDOG = "Watchdog" + REBOOT_CAUSE_HARDWARE_OTHER = "Hardware - Other" + REBOOT_CAUSE_NON_HARDWARE = "Non-Hardware" + + """ + reboot_cause = self._api_common.get_output( + 0, self._config['get_reboot_cause'], self.REBOOT_CAUSE_HARDWARE_OTHER) + description = self._api_common.get_output( + 0, self._config['get_reboot_description'], 'Unknown') + + return (reboot_cause, description) + + # ############################################################## + # ######################## SFP methods ######################### + # ############################################################## + + def get_num_sfps(self): + """ + Retrieves the number of sfps available on this chassis + Returns: + An integer, the number of sfps available on this chassis + """ + if not self.sfp_module_initialized: + self.__initialize_sfp() + + return len(self._sfp_list) + + def get_all_sfps(self): + """ + Retrieves all sfps available on this chassis + Returns: + A list of objects derived from SfpBase representing all sfps + available on this chassis + """ + if not self.sfp_module_initialized: + self.__initialize_sfp() + + return self._sfp_list + + 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, 1 for Ethernet0, 2 for Ethernet4 and so on. + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + if not self.sfp_module_initialized: + self.__initialize_sfp() + + try: + # The index will start from 1 + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + return sfp + + ############################################################## + ###################### Event methods ######################### + ############################################################## + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + Specifically for SFP event, besides SFP plug in and plug out, + there are some other error event could be raised from SFP, when + these error happened, SFP eeprom will not be avalaible, XCVRD shall + stop to read eeprom before SFP recovered from error status. + status='2' I2C bus stuck, + status='3' Bad eeprom, + status='4' Unsupported cable, + status='5' High Temperature, + status='6' Bad cable. + """ + + if not self.sfp_module_initialized: + self.__initialize_sfp() + + return self._api_common.get_event(timeout, self._config['get_change_event'], self._sfp_list) + + # ############################################################## + # ###################### Other methods ######################## + # ############################################################## + + 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: + wdt = self._api_common.get_output( + 0, self._config['get_watchdog'], None) + self._watchdog = wdt() + + return self._watchdog + + # ############################################################## + # ###################### Device methods ######################## + # ############################################################## + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self._api_common.hwsku + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._eeprom.get_pn() + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return self._eeprom.get_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 True diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/common.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/common.py new file mode 100644 index 000000000000..697308b8c3cf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/common.py @@ -0,0 +1,283 @@ +import os +import imp +import yaml +import subprocess + +from sonic_py_common import device_info + + +class Common: + + DEVICE_PATH = '/usr/share/sonic/device/' + PMON_PLATFORM_PATH = '/usr/share/sonic/platform/' + CONFIG_DIR = 'sonic_platform_config' + + OUTPUT_SOURCE_IPMI = 'ipmitool' + OUTPUT_SOURCE_GIVEN_LIST = 'value_list' + OUTPUT_SOURCE_GIVEN_VALUE = 'value' + OUTPUT_SOURCE_GIVEN_CLASS = 'class' + OUTPUT_SOURCE_SYSFS = 'sysfs_value' + OUTPUT_SOURCE_FUNC = 'function' + OUTPUT_SOURCE_GIVEN_TXT_FILE = 'txt_file' + OUTPUT_SOURCE_GIVEN_VER_HEX_FILE = 'hex_version_file' + OUTPUT_SOURCE_GIVEN_VER_HEX_ADDR = 'hex_version_getreg' + + SET_METHOD_IPMI = 'ipmitool' + NULL_VAL = 'N/A' + HOST_CHK_CMD = "docker > /dev/null 2>&1" + REF_KEY = '$ref:' + + def __init__(self, conf=None): + self._main_conf = conf + (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() + + def _run_command(self, command): + status = False + output = "" + try: + p = subprocess.Popen( + command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + raw_data, err = p.communicate() + if err == '': + status, output = True, raw_data.strip() + except Exception: + pass + return status, output + + def _clean_input(self, input, config): + cleaned_input = input + + ai = config.get('avaliable_input') + if ai and input not in ai: + return None + + input_translator = config.get('input_translator') + if type(input_translator) is dict: + cleaned_input = input_translator.get(input) + + elif type(input_translator) is str: + cleaned_input = eval(input_translator.format(input)) + + return cleaned_input + + def _clean_output(self, index, output, config): + output_translator = config.get('output_translator') + + if type(output_translator) is dict: + output = output_translator.get(output) + elif type(output_translator) is str: + output = eval(output_translator.format(output)) + elif type(output_translator) is list: + output = eval(output_translator[index].format(output)) + + return output + + def _ipmi_get(self, index, config): + argument = config.get('argument') + cmd = config['command'].format( + config['argument'][index]) if argument else config['command'] + status, output = self._run_command(cmd) + return output if status else None + + def _sysfs_read(self, index, config): + sysfs_path = config.get('sysfs_path') + argument = config.get('argument', '') + + if self.REF_KEY in argument: + argument = self._main_conf[argument.split(":")[1]] + + if type(argument) is list: + sysfs_path = sysfs_path.format(argument[index]) + + content = "" + try: + content = open(sysfs_path) + content = content.readline().rstrip() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + return content + + def _sysfs_write(self, index, config, input): + sysfs_path = config.get('sysfs_path') + argument = config.get('argument', '') + + if self.REF_KEY in argument: + argument = self._main_conf[argument.split(":")[1]] + + if type(argument) is list: + sysfs_path = sysfs_path.format(argument[index]) + + write_offset = int(config.get('write_offset', 0)) + output = "" + try: + open_file = open(sysfs_path, "r+") + open_file.seek(write_offset) + open_file.write(input) + open_file.close() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False, output + return True, output + + def _ipmi_set(self, index, config, input): + arg = config['argument'][index].format(input) + return self._run_command(config['command'].format(arg)) + + def _hex_ver_decode(self, hver, num_of_bits, num_of_points): + ver_list = [] + c_bit = 0 + bin_val = bin(int(hver, 16))[2:].zfill(num_of_bits) + bit_split = num_of_bits / (num_of_points + 1) + for x in range(0, num_of_points+1): + split_bin = bin_val[c_bit:c_bit+bit_split] + ver_list.append(str(int(split_bin, 2))) + c_bit += bit_split + return '.'.join(ver_list) + + def _get_class(self, config): + """ + Retreives value of expected attribute + Returns: + A value of the attribute of object + """ + path = config['host_path'] if self.is_host() else config['pmon_path'] + module = imp.load_source(config['class'], path) + class_ = getattr(module, config['class']) + return class_ + + def get_reg(self, path, reg_addr): + cmd = "echo {1} > {0}; cat {0}".format(path, reg_addr) + status, output = self._run_command(cmd) + return output if status else None + + def read_txt_file(self, path): + with open(path, 'r') as f: + output = f.readline() + return output.strip('\n') + + def write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except Exception: + return False + return True + + def is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def load_json_file(self, path): + """ + Retrieves the json object from json file path + + Returns: + A json object + """ + with open(path, 'r') as f: + json_data = yaml.safe_load(f) + + return json_data + + def get_config_path(self, config_name): + """ + Retrieves the path to platform api config directory + + Args: + config_name: A string containing the name of config file. + + Returns: + A string containing the path to json file + """ + return os.path.join(self.DEVICE_PATH, self.platform, self.CONFIG_DIR, config_name) if self.is_host() else os.path.join(self.PMON_PLATFORM_PATH, self.CONFIG_DIR, config_name) + + def get_output(self, index, config, default): + """ + Retrieves the output for each function base on config + + Args: + index: An integer containing the index of device. + config: A dict object containing the configuration of specified function. + default: A string containing the default output of specified function. + + Returns: + A string containing the output of specified function in config + """ + output_source = config.get('output_source') + + if output_source == self.OUTPUT_SOURCE_IPMI: + output = self._ipmi_get(index, config) + + elif output_source == self.OUTPUT_SOURCE_GIVEN_VALUE: + output = config["value"] + + elif output_source == self.OUTPUT_SOURCE_GIVEN_CLASS: + output = self._get_class(config) + + elif output_source == self.OUTPUT_SOURCE_GIVEN_LIST: + output = config["value_list"][index] + + elif output_source == self.OUTPUT_SOURCE_SYSFS: + output = self._sysfs_read(index, config) + + elif output_source == self.OUTPUT_SOURCE_FUNC: + func_conf = self._main_conf[config['function'][index]] + output = self.get_output(index, func_conf, default) + + elif output_source == self.OUTPUT_SOURCE_GIVEN_TXT_FILE: + path = config.get('path') + output = self.read_txt_file(path) + + elif output_source == self.OUTPUT_SOURCE_GIVEN_VER_HEX_FILE: + path = config.get('path') + hex_ver = self.read_txt_file(path) + output = self._hex_ver_decode( + hex_ver, config['num_of_bits'], config['num_of_points']) + + elif output_source == self.OUTPUT_SOURCE_GIVEN_VER_HEX_ADDR: + path = config.get('path') + addr = config.get('reg_addr') + hex_ver = self.get_reg(path, addr) + output = self._hex_ver_decode( + hex_ver, config['num_of_bits'], config['num_of_points']) + + else: + output = default + + return self._clean_output(index, output, config) or default + + def set_output(self, index, input, config): + """ + Sets the output of specified function on config + + Args: + config: A dict object containing the configuration of specified function. + index: An integer containing the index of device. + input: A string containing the input of specified function. + + Returns: + bool: True if set function is successfully, False if not + """ + cleaned_input = self._clean_input(input, config) + if not cleaned_input: + return False + + set_method = config.get('set_method') + if set_method == self.SET_METHOD_IPMI: + output = self._ipmi_set(index, config, cleaned_input)[0] + elif set_method == self.OUTPUT_SOURCE_SYSFS: + output = self._sysfs_write(index, config, cleaned_input)[0] + else: + output = False + + return output + + def get_event(self, timeout, config, sfp_list): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + """ + event_class = self._get_class(config) + return event_class(sfp_list).get_event(timeout) diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/component.py new file mode 100644 index 000000000000..958b34623222 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/component.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +try: + from sonic_platform_base.component_base import ComponentBase + from common import Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Component(ComponentBase): + """Platform-specific Component class""" + + def __init__(self, component_index, conf): + ComponentBase.__init__(self) + + self._index = component_index + self._config = conf + self._api_common = Common(self._config) + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + default = 'N/A' + config = self._config["get_name"] + return self._api_common.get_output(self._index, config, default) + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + default = 'N/A' + config = self._config["get_description"] + return self._api_common.get_output(self._index, config, default) + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Note: the firmware version will be read from HW + Returns: + A string containing the firmware version of the component + """ + default = 'N/A' + config = self._config["get_firmware_version"] + return self._api_common.get_output(self._index, config, default) diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/eeprom.py new file mode 100644 index 000000000000..7756c0f2f839 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/eeprom.py @@ -0,0 +1,113 @@ +############################################################################# +# Celestica +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import os + import sys + import re + + if sys.version_info.major == 3: + from io import StringIO + else: + from cStringIO import StringIO + + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + + +class Tlv(eeprom_tlvinfo.TlvInfoDecoder): + + EEPROM_DECODE_HEADLINES = 6 + DEFAULT_EEPROM_PATH = "/sys/class/i2c-adapter/i2c-12/12-0050/eeprom" + + def __init__(self, conf=None): + eeprom_path = conf.get('eeprom', self.DEFAULT_EEPROM_PATH) + super(Tlv, self).__init__(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 Exception: + pass + return _eeprom_info_dict + + def _load_eeprom(self): + original_stdout = sys.stdout + sys.stdout = StringIO() + try: + self.read_eeprom_db() + except Exception: + 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 Exception: + 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 Exception: + pass + + e = self.read_eeprom() + if e is None: + return 0 + + try: + self.update_cache(e) + except Exception: + 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/services/platform_api/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/fan.py new file mode 100644 index 000000000000..b0ebebccd3d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/fan.py @@ -0,0 +1,193 @@ +#!/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 +# +############################################################################# + +try: + from sonic_platform_base.fan_base import FanBase + from common import Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, index, is_psu_fan=False, psu_index=0, conf=None): + FanBase.__init__(self) + + self._fan_index = index + self._config = conf + self._api_common = Common() + + self._is_psu_fan = is_psu_fan + if self._is_psu_fan: + self._initialize_psu_fan(psu_index) + + self._name = self.get_name() + + def _initialize_psu_fan(self, psu_index): + self._psu_index = psu_index + self._psu_fan_config = self._config['psu_fan'][self._psu_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 + """ + return self._api_common.get_output(self._fan_index, self._config['get_direction'], self.FAN_DIRECTION_NOT_APPLICABLE) + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + + Note: + speed = pwm_in/255*100 + """ + config = self._config['get_speed'] if not self._is_psu_fan else self._psu_fan_config['get_speed'] + max_rpm = config['max_rear'] if 'R' in self._name else config['max_front'] + raw_speed = self._api_common.get_output( + self._fan_index, config, 0) + + return int(float(raw_speed) / max_rpm * 100.0) + + 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: + 0 : when PWM mode is not in use + pwm : when pwm mode is not use + """ + return self._api_common.get_output(self._fan_index, self._config['get_target_speed'], Common.NULL_VAL) + + 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 self._api_common.get_output(self._fan_index, self._config['get_speed_tolerance'], Common.NULL_VAL) + + def set_speed(self, speed): + """ + Sets the fan speed + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + A boolean, True if speed is set successfully, False if not + + Note: + Depends on pwm or target mode is selected: + 1) pwm = speed_pc * 255 <-- Currently use this mode. + 2) target_pwm = speed_pc * 100 / 255 + 2.1) set pwm{}_enable to 3 + + ipmitool raw 0x3a 0x0e 0x00 > enable auto fcs + ipmitool raw 0x3a 0x0e 0x01 > disable auto fcs + """ + if speed not in range(1, 101) or self._is_psu_fan: + return False + + return self._api_common.set_output(self._fan_index, speed, self._config['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: Required Manual Control LED mode ('ipmitool raw 0x3a 0x0f 0x2 0x0') + """ + config = self._config['set_status_led'] + avaliable_input = config.get('avaliable_input') + if (avaliable_input and color not in avaliable_input) or self._is_psu_fan: + return False + + return self._api_common.set_output(self._fan_index, color, config) + + 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" + """ + + default = self.STATUS_LED_COLOR_OFF + + if self._is_psu_fan: + return default + + return self._api_common.get_output(self._fan_index, self._config['get_status_led'], default) + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + config = self._config['get_name'] if not self._is_psu_fan else self._psu_fan_config['get_name'] + return self._api_common.get_output(self._fan_index, config, Common.NULL_VAL) + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if FAN is present, False if not + """ + return self._api_common.get_output(self._fan_index, self._config['get_presence'], False) + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + default = Common.NULL_VAL + if self._is_psu_fan: + return default + return self._api_common.get_output(self._fan_index, self._config['get_model'], default) + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + default = Common.NULL_VAL + if self._is_psu_fan: + return default + return self._api_common.get_output(self._fan_index, self._config['get_serial'], default) + + 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() > 10 diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..5ef283a105d4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/fan_drawer.py @@ -0,0 +1,82 @@ +#!/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 +# +############################################################################# + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanDrawer(FanDrawerBase): + + def __init__(self, index, fan_list): + FanDrawerBase.__init__(self) + + self._fan_list = fan_list + self._index = index + 1 + + def set_status_led(self, color): + """ + Sets the state of the fan drawer status LED + Args: + color: A string representing the color with which to set the + fan drawer status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + return self._fan_list[0].set_status_led(color) + + def get_status_led(self, color): + """ + Gets the state of the fan drawer LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + return self._fan_list[0].get_status_led() + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return 'Fan {}'.format(self._index) + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if FAN is present, False if not + """ + return self._fan_list[0].get_presence() + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._fan_list[0].get_model() + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return self._fan_list[0].get_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._fan_list[0].get_status() diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/platform.py new file mode 100644 index 000000000000..a632de87e742 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/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/services/platform_api/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/psu.py new file mode 100644 index 000000000000..68dfe201d33f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/psu.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the psu status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.psu_base import PsuBase + from common import Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Psu(PsuBase): + """Platform-specific Fan class""" + + def __init__(self, index, conf=None, fan_conf=None): + PsuBase.__init__(self) + + self._psu_index = index + self._config = conf + self._api_common = Common(self._config) + self._fan_conf = fan_conf + self._initialize_psu_fan() + + def _initialize_psu_fan(self): + from sonic_platform.fan import Fan + + num_fan = self._fan_conf['psu_fan'][self._psu_index]["num_of_fan"] + for fan_index in range(0, num_fan): + fan = Fan(fan_index, is_psu_fan=True, + psu_index=self._psu_index, conf=self._fan_conf) + self._fan_list.append(fan) + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + return self._api_common.get_output(self._psu_index, self._config['get_voltage'], 0.0) + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + return self._api_common.get_output(self._psu_index, self._config['get_current'], 0.0) + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, e.g. 302.6 + """ + return self._api_common.get_output(self._psu_index, self._config['get_current'], 0.0) + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + return self._api_common.get_output(self._psu_index, self._config['get_powergood_status'], False) + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Note: + Seastone2 CPLD able to set only AMBER color. + This function should be disable auto mode before execute + command: ipmitool raw 0x3a 0x0f 0x02 0x00 + Args: + color: A string representing the color with which to set the + PSU status LED + + Returns: + bool: True if status LED state is set successfully, False if not + """ + return self._api_common.set_output(self._psu_index, color, self._config['set_status_led']) + + def get_status_led(self): + """ + Gets the state of the PSU status LED + Note: + Seastone2 PSU LED got only 2 mode, AMBER and Hardware control mode. + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + return self._api_common.get_output(self._psu_index, self._config['get_status_led'], Common.NULL_VAL) + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + return self._api_common.get_output(self._psu_index, self._config['get_temperature'], 0.0) + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return self._api_common.get_output(self._psu_index, self._config['get_temperature_high_threshold'], 0.0) + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + + Returns: + ucr as float number and return 0 if the BMC output is na. + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return self._api_common.get_output(self._psu_index, self._config['get_voltage_high_threshold'], 0.0) + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + + Returns: + lcr as float number and return 0 if the BMC output is na. + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return self._api_common.get_output(self._psu_index, self._config['get_voltage_low_threshold'], 0.0) + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + return self._api_common.get_output(self._psu_index, self._config['get_name'], Common.NULL_VAL) + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + return self._api_common.get_output(self._psu_index, self._config['get_name'], False) + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return self._api_common.get_output(self._psu_index, self._config['get_model'], Common.NULL_VAL) + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return self._api_common.get_output(self._psu_index, self._config['get_serial'], Common.NULL_VAL) + + 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_powergood_status() diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py new file mode 100644 index 000000000000..07eac37d8d82 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py @@ -0,0 +1,2037 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the sfp status which are available in the platform +# +############################################################################# + +import time +from ctypes import create_string_buffer + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.inf8628 import inf8628InterfaceId + from sonic_platform_base.sonic_sfp.qsfp_dd import qsfp_dd_InterfaceId + from sonic_platform_base.sonic_sfp.qsfp_dd import qsfp_dd_Dom + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from common import Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_EXT_SPECIFICATION_COMPLIANCE_OFFSET = 64 +XCVR_EXT_SPECIFICATION_COMPLIANCE_WIDTH = 1 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 + +XCVR_INTERFACE_DATA_START = 0 +XCVR_INTERFACE_DATA_SIZE = 92 + +QSFP_DOM_BULK_DATA_START = 22 +QSFP_DOM_BULK_DATA_SIZE = 36 +SFP_DOM_BULK_DATA_START = 96 +SFP_DOM_BULK_DATA_SIZE = 10 +QSFP_DD_DOM_BULK_DATA_START = 14 +QSFP_DD_DOM_BULK_DATA_SIZE = 4 + +# definitions of the offset for values in OSFP info eeprom +OSFP_TYPE_OFFSET = 0 +OSFP_VENDOR_NAME_OFFSET = 129 +OSFP_VENDOR_PN_OFFSET = 148 +OSFP_HW_REV_OFFSET = 164 +OSFP_VENDOR_SN_OFFSET = 166 + +# definitions of the offset for values in QSFP_DD info eeprom +QSFP_DD_TYPE_OFFSET = 0 +QSFP_DD_VENDOR_NAME_OFFSET = 1 +QSFP_DD_VENDOR_PN_OFFSET = 20 +QSFP_DD_VENDOR_SN_OFFSET = 38 +QSFP_DD_VENDOR_OUI_OFFSET = 17 + +# definitions of the offset and width for values in XCVR_QSFP_DD info eeprom +XCVR_EXT_TYPE_OFFSET_QSFP_DD = 72 +XCVR_EXT_TYPE_WIDTH_QSFP_DD = 2 +XCVR_CONNECTOR_OFFSET_QSFP_DD = 75 +XCVR_CONNECTOR_WIDTH_QSFP_DD = 1 +XCVR_CABLE_LENGTH_OFFSET_QSFP_DD = 74 +XCVR_CABLE_LENGTH_WIDTH_QSFP_DD = 1 +XCVR_HW_REV_OFFSET_QSFP_DD = 36 +XCVR_HW_REV_WIDTH_QSFP_DD = 2 +XCVR_VENDOR_DATE_OFFSET_QSFP_DD = 54 +XCVR_VENDOR_DATE_WIDTH_QSFP_DD = 8 +XCVR_DOM_CAPABILITY_OFFSET_QSFP_DD = 2 +XCVR_DOM_CAPABILITY_WIDTH_QSFP_DD = 1 +XCVR_MEDIA_TYPE_OFFSET_QSFP_DD = 85 +XCVR_MEDIA_TYPE_WIDTH_QSFP_DD = 1 +XCVR_FIRST_APPLICATION_LIST_OFFSET_QSFP_DD = 86 +XCVR_FIRST_APPLICATION_LIST_WIDTH_QSFP_DD = 32 +XCVR_SECOND_APPLICATION_LIST_OFFSET_QSFP_DD = 351 +XCVR_SECOND_APPLICATION_LIST_WIDTH_QSFP_DD = 28 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_MODULE_MONITOR_OFFSET = 0 +QSFP_MODULE_MONITOR_WIDTH = 9 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_POWEROVERRIDE_BIT = 0 +QSFP_POWERSET_BIT = 1 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 +QSFP_MODULE_UPPER_PAGE3_START = 384 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNL_THRESHOLD_OFFSET = 176 +QSFP_CHANNL_THRESHOLD_WIDTH = 24 + +SFP_MODULE_ADDRA2_OFFSET = 256 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_CHANNL_STATUS_OFFSET = 110 +SFP_CHANNL_STATUS_WIDTH = 1 + +QSFP_DD_TEMPE_OFFSET = 14 +QSFP_DD_TEMPE_WIDTH = 2 +QSFP_DD_VOLT_OFFSET = 16 +QSFP_DD_VOLT_WIDTH = 2 +QSFP_DD_TX_BIAS_OFFSET = 42 +QSFP_DD_TX_BIAS_WIDTH = 16 +QSFP_DD_RX_POWER_OFFSET = 58 +QSFP_DD_RX_POWER_WIDTH = 16 +QSFP_DD_TX_POWER_OFFSET = 26 +QSFP_DD_TX_POWER_WIDTH = 16 +QSFP_DD_CHANNL_MON_OFFSET = 154 +QSFP_DD_CHANNL_MON_WIDTH = 48 +QSFP_DD_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_DD_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_DD_CHANNL_RX_LOS_STATUS_OFFSET = 19 +QSFP_DD_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_DD_CHANNL_TX_FAULT_STATUS_OFFSET = 7 +QSFP_DD_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_DD_MODULE_THRESHOLD_OFFSET = 0 +QSFP_DD_MODULE_THRESHOLD_WIDTH = 72 +QSFP_DD_CHANNL_STATUS_OFFSET = 26 +QSFP_DD_CHANNL_STATUS_WIDTH = 1 + + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +info_dict_keys = ['type', 'hardwarerev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', + 'vendor_date', 'vendor_oui', 'application_advertisement'] + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +dom_info_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'lp_mode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'rx5power', 'rx6power', 'rx7power', 'rx8power', + 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx5bias', 'tx6bias', 'tx7bias', 'tx8bias', + 'tx1power', 'tx2power', 'tx3power', 'tx4power', 'tx5power', 'tx6power', 'tx7power', 'tx8power'] + +threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', + 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + +SFP_TYPE_CODE_LIST = [ + '03' # SFP/SFP+/SFP28 +] +QSFP_TYPE_CODE_LIST = [ + '0d', # QSFP+ or later + '11' # QSFP28 or later +] +QSFP_DD_TYPE_CODE_LIST = [ + '18' # QSFP-DD Double Density 8X Pluggable Transceiver +] + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" +OSFP_TYPE = "OSFP" +QSFP_DD_TYPE = "QSFP_DD" + + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + + def __init__(self, sfp_index=0, conf=None): + SfpBase.__init__(self) + + self._sfp_index = sfp_index + self._config = conf + self._api_common = Common(self._config) + + self._read_porttab_mappings() + self._dom_capability_detect() + + def _read_porttab_mappings(self): + self._sfputil_helper = SfpUtilHelper() + self._sfputil_helper.read_porttab_mappings( + self._get_path_to_port_config_file()) + + def _get_path_to_port_config_file(self): + host_platform_root_path = '/usr/share/sonic/device' + docker_hwsku_path = '/usr/share/sonic/hwsku' + + host_platform_path = "/".join([host_platform_root_path, + self._api_common.platform]) + hwsku_path = "/".join([host_platform_path, self._api_common.hwsku] + ) if self._api_common.is_host() else docker_hwsku_path + + return "/".join([hwsku_path, "port_config.ini"]) + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return Common.NULL_VAL + elif "Unknown" in value_str: + return Common.NULL_VAL + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return Common.NULL_VAL + + def _read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self._get_eeprom_path() + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except Exception: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def _detect_sfp_type(self): + sfp_type = QSFP_TYPE + eeprom_raw = [] + eeprom_raw = self._read_eeprom_specific_bytes( + XCVR_TYPE_OFFSET, XCVR_TYPE_WIDTH) + if eeprom_raw: + if eeprom_raw[0] in SFP_TYPE_CODE_LIST: + self.sfp_type = SFP_TYPE + elif eeprom_raw[0] in QSFP_TYPE_CODE_LIST: + self.sfp_type = QSFP_TYPE + elif eeprom_raw[0] in QSFP_DD_TYPE_CODE_LIST: + self.sfp_type = QSFP_DD_TYPE + else: + self.sfp_type = sfp_type + else: + self.sfp_type = sfp_type + + def _get_eeprom_path(self): + eeprom_path = self._config['eeprom_path'] + port_to_i2c_mapping = self._config['port_i2c_mapping'] + port_eeprom_path = eeprom_path.format( + port_to_i2c_mapping[self._sfp_index]) + + return port_eeprom_path + + def _dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + return + + self._detect_sfp_type() + + if self.sfp_type == QSFP_TYPE: + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # 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( + (offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self._read_eeprom_specific_bytes( + QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH) + qsfp_version_compliance = int( + qsfp_version_compliance_raw[0], 16) + dom_capability = sfpi_obj.parse_dom_capability( + qsfp_dom_capability_raw, 0) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = dom_capability['data']['Temp_support']['value'] == 'On' + self.dom_volt_supported = dom_capability['data']['Voltage_support']['value'] == 'On' + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = dom_capability['data']['Tx_power_support']['value'] == 'On' + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = True + + self.dom_supported = True + self.calibration = 1 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + qsfp_option_value_raw = self._read_eeprom_specific_bytes( + QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH) + if qsfp_option_value_raw is not None: + optional_capability = sfpd_obj.parse_option_params( + qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = optional_capability[ + 'data']['TxDisable']['value'] == 'On' + dom_status_indicator = sfpd_obj.parse_dom_status_indicator( + qsfp_version_compliance_raw, 1) + self.qsfp_page3_available = dom_status_indicator['data']['FlatMem']['value'] == 'Off' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.qsfp_page3_available = False + + elif self.sfp_type == QSFP_DD_TYPE: + sfpi_obj = qsfp_dd_InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + + offset = 0 + # two types of QSFP-DD cable types supported: Copper and Optical. + qsfp_dom_capability_raw = self._read_eeprom_specific_bytes( + (offset + XCVR_DOM_CAPABILITY_OFFSET_QSFP_DD), XCVR_DOM_CAPABILITY_WIDTH_QSFP_DD) + if qsfp_dom_capability_raw is not None: + self.dom_temp_supported = True + self.dom_volt_supported = True + dom_capability = sfpi_obj.parse_dom_capability( + qsfp_dom_capability_raw, 0) + if dom_capability['data']['Flat_MEM']['value'] == 'Off': + self.dom_supported = True + self.second_application_list = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + self.dom_tx_bias_power_supported = True + self.dom_thresholds_supported = True + # currently set to False becasue Page 11h is not supported by FW + self.dom_rx_tx_power_bias_supported = False + else: + self.dom_supported = False + self.second_application_list = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.dom_tx_bias_power_supported = False + self.dom_thresholds_supported = False + self.dom_rx_tx_power_bias_supported = False + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.dom_tx_bias_power_supported = False + self.dom_thresholds_supported = False + self.dom_rx_tx_power_bias_supported = False + + elif self.sfp_type == SFP_TYPE: + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self._read_eeprom_specific_bytes( + XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = ( + int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def get_name(self): + """ + Retrieves the human-readable name of a sfp by 1-based index + + Returns: + :param index: An integer, 1-based index of the sfp of which to query status + :return: String, + A string representing the name of the sfp. + """ + return self._sfputil_helper.logical[self._sfp_index] or "Unknown" + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return self._api_common.get_output(self._sfp_index, self._config['get_presence'], False) + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("model", Common.NULL_VAL) + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("serial", Common.NULL_VAL) + + 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() + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ================================================================================ + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + application_advertisement |1*255VCHAR |supported applications advertisement + ================================================================================ + """ + + transceiver_info_dict = {} + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys( + info_dict_keys, Common.NULL_VAL) + + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + if self.sfp_type == OSFP_TYPE: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP + + sfpi_obj = inf8628InterfaceId() + if sfpi_obj is None: + return None + + sfp_type_raw = self._read_eeprom_specific_bytes( + (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes( + (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes( + (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes( + (offset + OSFP_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes( + (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_vendor_sn_raw, 0) + else: + return None + + transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + + elif self.sfp_type == QSFP_TYPE: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + elif self.sfp_type == QSFP_DD_TYPE: + offset = 128 + + sfpi_obj = qsfp_dd_InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + sfp_type_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes( + (offset + XCVR_HW_REV_OFFSET_QSFP_DD), XCVR_HW_REV_WIDTH_QSFP_DD) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_vendor_sn_raw, 0) + else: + return None + + sfp_vendor_oui_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_vendor_oui_raw, 0) + else: + return None + + sfp_vendor_date_raw = self._read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_DATE_OFFSET_QSFP_DD), XCVR_VENDOR_DATE_WIDTH_QSFP_DD) + if sfp_vendor_date_raw is not None: + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_vendor_date_raw, 0) + else: + return None + + sfp_connector_raw = self._read_eeprom_specific_bytes( + (offset + XCVR_CONNECTOR_OFFSET_QSFP_DD), XCVR_CONNECTOR_WIDTH_QSFP_DD) + if sfp_connector_raw is not None: + sfp_connector_data = sfpi_obj.parse_connector( + sfp_connector_raw, 0) + else: + return None + + sfp_ext_identifier_raw = self._read_eeprom_specific_bytes( + (offset + XCVR_EXT_TYPE_OFFSET_QSFP_DD), XCVR_EXT_TYPE_WIDTH_QSFP_DD) + if sfp_ext_identifier_raw is not None: + sfp_ext_identifier_data = sfpi_obj.parse_ext_iden( + sfp_ext_identifier_raw, 0) + else: + return None + + sfp_cable_len_raw = self._read_eeprom_specific_bytes( + (offset + XCVR_CABLE_LENGTH_OFFSET_QSFP_DD), XCVR_CABLE_LENGTH_WIDTH_QSFP_DD) + if sfp_cable_len_raw is not None: + sfp_cable_len_data = sfpi_obj.parse_cable_len( + sfp_cable_len_raw, 0) + else: + return None + + sfp_media_type_raw = self._read_eeprom_specific_bytes( + XCVR_MEDIA_TYPE_OFFSET_QSFP_DD, XCVR_MEDIA_TYPE_WIDTH_QSFP_DD) + if sfp_media_type_raw is not None: + sfp_media_type_dict = sfpi_obj.parse_media_type( + sfp_media_type_raw, 0) + if sfp_media_type_dict is None: + return None + + host_media_list = "" + sfp_application_type_first_list = self._read_eeprom_specific_bytes( + (XCVR_FIRST_APPLICATION_LIST_OFFSET_QSFP_DD), XCVR_FIRST_APPLICATION_LIST_WIDTH_QSFP_DD) + if self.second_application_list: + possible_application_count = 15 + sfp_application_type_second_list = self._read_eeprom_specific_bytes( + (XCVR_SECOND_APPLICATION_LIST_OFFSET_QSFP_DD), XCVR_SECOND_APPLICATION_LIST_WIDTH_QSFP_DD) + if sfp_application_type_first_list is not None and sfp_application_type_second_list is not None: + sfp_application_type_list = sfp_application_type_first_list + \ + sfp_application_type_second_list + else: + return None + else: + possible_application_count = 8 + if sfp_application_type_first_list is not None: + sfp_application_type_list = sfp_application_type_first_list + else: + return None + + for i in range(0, possible_application_count): + if sfp_application_type_list[i * 4] == 'ff': + break + host_electrical, media_interface = sfpi_obj.parse_application( + sfp_media_type_dict, sfp_application_type_list[i * 4], sfp_application_type_list[i * 4 + 1]) + host_media_list = host_media_list + host_electrical + \ + ' - ' + media_interface + '\n\t\t\t\t ' + else: + return None + + transceiver_info_dict['type'] = str( + sfp_type_data['data']['type']['value']) + transceiver_info_dict['manufacturer'] = str( + sfp_vendor_name_data['data']['Vendor Name']['value']) + transceiver_info_dict['model'] = str( + sfp_vendor_pn_data['data']['Vendor PN']['value']) + transceiver_info_dict['hardware_rev'] = str( + sfp_vendor_rev_data['data']['Vendor Rev']['value']) + transceiver_info_dict['serial'] = str( + sfp_vendor_sn_data['data']['Vendor SN']['value']) + transceiver_info_dict['vendor_oui'] = str( + sfp_vendor_oui_data['data']['Vendor OUI']['value']) + transceiver_info_dict['vendor_date'] = str( + sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value']) + transceiver_info_dict['connector'] = str( + sfp_connector_data['data']['Connector']['value']) + transceiver_info_dict['encoding'] = "Not supported for CMIS cables" + transceiver_info_dict['ext_identifier'] = str( + sfp_ext_identifier_data['data']['Extended Identifier']['value']) + transceiver_info_dict['ext_rateselect_compliance'] = "Not supported for CMIS cables" + transceiver_info_dict['specification_compliance'] = "Not supported for CMIS cables" + transceiver_info_dict['cable_type'] = "Length Cable Assembly(m)" + transceiver_info_dict['cable_length'] = str( + sfp_cable_len_data['data']['Length Cable Assembly(m)']['value']) + transceiver_info_dict['nominal_bit_rate'] = "Not supported for CMIS cables" + transceiver_info_dict['application_advertisement'] = host_media_list + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + if self.sfp_type != QSFP_DD_TYPE: + sfp_interface_bulk_raw = self._read_eeprom_specific_bytes( + offset + XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE) + if sfp_interface_bulk_raw is None: + return None + + start = XCVR_INTFACE_BULK_OFFSET - XCVR_INTERFACE_DATA_START + end = start + interface_info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_NAME_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_NAME_WIDTH + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_PN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_PN_WIDTH + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_HW_REV_OFFSET - XCVR_INTERFACE_DATA_START + end = start + vendor_rev_width + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_SN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_SN_WIDTH + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_OUI_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_OUI_WIDTH + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_DATE_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_DATE_WIDTH + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_interface_bulk_raw[start: end], 0) + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + sfp_ext_specification_compliance_raw = self._read_eeprom_specific_bytes( + offset + XCVR_EXT_SPECIFICATION_COMPLIANCE_OFFSET, XCVR_EXT_SPECIFICATION_COMPLIANCE_WIDTH) + if sfp_ext_specification_compliance_raw is not None: + sfp_ext_specification_compliance_data = sfpi_obj.parse_ext_specification_compliance( + sfp_ext_specification_compliance_raw[0: 1], 0) + if sfp_ext_specification_compliance_data['data']['Extended Specification compliance']['value'] != "Unspecified": + compliance_code_dict['Extended Specification compliance'] = sfp_ext_specification_compliance_data[ + 'data']['Extended Specification compliance']['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict = dict.fromkeys( + dom_info_dict_keys, Common.NULL_VAL) + + if self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + + dom_data_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DOM_BULK_DATA_START), QSFP_DOM_BULK_DATA_SIZE) + if dom_data_raw is None: + return transceiver_dom_info_dict + + if self.dom_temp_supported: + start = QSFP_TEMPE_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + temp = dom_temperature_data['data']['Temperature']['value'] + if temp is not None: + transceiver_dom_info_dict['temperature'] = temp + + if self.dom_volt_supported: + start = QSFP_VOLT_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + volt = dom_voltage_data['data']['Vcc']['value'] + if volt is not None: + transceiver_dom_info_dict['voltage'] = volt + + start = QSFP_CHANNL_MON_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power( + dom_data_raw[start: end], 0) + + if self.dom_tx_power_supported: + 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'] + + if self.dom_rx_power_supported: + 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'] + + elif self.sfp_type == QSFP_DD_TYPE: + + offset = 0 + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + + dom_data_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_DOM_BULK_DATA_START), QSFP_DD_DOM_BULK_DATA_SIZE) + if dom_data_raw is None: + return transceiver_dom_info_dict + + if self.dom_temp_supported: + start = QSFP_DD_TEMPE_OFFSET - QSFP_DD_DOM_BULK_DATA_START + end = start + QSFP_DD_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + temp = dom_temperature_data['data']['Temperature']['value'] + if temp is not None: + transceiver_dom_info_dict['temperature'] = temp + + if self.dom_volt_supported: + start = QSFP_DD_VOLT_OFFSET - QSFP_DD_DOM_BULK_DATA_START + end = start + QSFP_DD_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + volt = dom_voltage_data['data']['Vcc']['value'] + if volt is not None: + transceiver_dom_info_dict['voltage'] = volt + + if self.dom_rx_tx_power_bias_supported: + # page 11h + dom_data_raw = self._read_eeprom_specific_bytes( + (QSFP_DD_CHANNL_MON_OFFSET), QSFP_DD_CHANNL_MON_WIDTH) + if dom_data_raw is None: + return transceiver_dom_info_dict + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_data_raw, 0) + + if self.dom_tx_power_supported: + transceiver_dom_info_dict['tx1power'] = str( + dom_channel_monitor_data['data']['TX1Power']['value']) + transceiver_dom_info_dict['tx2power'] = str( + dom_channel_monitor_data['data']['TX2Power']['value']) + transceiver_dom_info_dict['tx3power'] = str( + dom_channel_monitor_data['data']['TX3Power']['value']) + transceiver_dom_info_dict['tx4power'] = str( + dom_channel_monitor_data['data']['TX4Power']['value']) + transceiver_dom_info_dict['tx5power'] = str( + dom_channel_monitor_data['data']['TX5Power']['value']) + transceiver_dom_info_dict['tx6power'] = str( + dom_channel_monitor_data['data']['TX6Power']['value']) + transceiver_dom_info_dict['tx7power'] = str( + dom_channel_monitor_data['data']['TX7Power']['value']) + transceiver_dom_info_dict['tx8power'] = str( + dom_channel_monitor_data['data']['TX8Power']['value']) + + if self.dom_rx_power_supported: + transceiver_dom_info_dict['rx1power'] = str( + dom_channel_monitor_data['data']['RX1Power']['value']) + transceiver_dom_info_dict['rx2power'] = str( + dom_channel_monitor_data['data']['RX2Power']['value']) + transceiver_dom_info_dict['rx3power'] = str( + dom_channel_monitor_data['data']['RX3Power']['value']) + transceiver_dom_info_dict['rx4power'] = str( + dom_channel_monitor_data['data']['RX4Power']['value']) + transceiver_dom_info_dict['rx5power'] = str( + dom_channel_monitor_data['data']['RX5Power']['value']) + transceiver_dom_info_dict['rx6power'] = str( + dom_channel_monitor_data['data']['RX6Power']['value']) + transceiver_dom_info_dict['rx7power'] = str( + dom_channel_monitor_data['data']['RX7Power']['value']) + transceiver_dom_info_dict['rx8power'] = str( + dom_channel_monitor_data['data']['RX8Power']['value']) + + if self.dom_tx_bias_power_supported: + transceiver_dom_info_dict['tx1bias'] = str( + dom_channel_monitor_data['data']['TX1Bias']['value']) + transceiver_dom_info_dict['tx2bias'] = str( + dom_channel_monitor_data['data']['TX2Bias']['value']) + transceiver_dom_info_dict['tx3bias'] = str( + dom_channel_monitor_data['data']['TX3Bias']['value']) + transceiver_dom_info_dict['tx4bias'] = str( + dom_channel_monitor_data['data']['TX4Bias']['value']) + transceiver_dom_info_dict['tx5bias'] = str( + dom_channel_monitor_data['data']['TX5Bias']['value']) + transceiver_dom_info_dict['tx6bias'] = str( + dom_channel_monitor_data['data']['TX6Bias']['value']) + transceiver_dom_info_dict['tx7bias'] = str( + dom_channel_monitor_data['data']['TX7Bias']['value']) + transceiver_dom_info_dict['tx8bias'] = str( + dom_channel_monitor_data['data']['TX8Bias']['value']) + + return transceiver_dom_info_dict + + else: + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + dom_data_raw = self._read_eeprom_specific_bytes( + (offset + SFP_DOM_BULK_DATA_START), SFP_DOM_BULK_DATA_SIZE) + + start = SFP_TEMPE_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + + start = SFP_VOLT_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + + start = SFP_CHANNL_MON_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_CHANNL_MON_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_data_raw[start: end], 0) + + 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['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['tx_disable'] = self.get_tx_disable() + transceiver_dom_info_dict['tx_disabled_channel'] = self.get_tx_disable_channel( + ) + + for key in transceiver_dom_info_dict: + val = transceiver_dom_info_dict[key] + transceiver_dom_info_dict[key] = self._convert_string_to_num( + val) if type(val) is str else val + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + transceiver_dom_threshold_info_dict = dict.fromkeys( + threshold_dict_keys, Common.NULL_VAL) + + if self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + if not self.dom_supported or not self.qsfp_page3_available: + return transceiver_dom_threshold_info_dict + + # Dom Threshold data starts from offset 384 + # Revert offset back to 0 once data is retrieved + offset = QSFP_MODULE_UPPER_PAGE3_START + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values( + dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self._read_eeprom_specific_bytes((offset + QSFP_CHANNL_THRESHOLD_OFFSET), + QSFP_CHANNL_THRESHOLD_WIDTH) + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values( + dom_channel_threshold_raw, 0) + + # 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'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + + elif self.sfp_type == QSFP_DD_TYPE: + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + if not self.dom_thresholds_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + # page 02 + offset = 384 + dom_module_threshold_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_MODULE_THRESHOLD_OFFSET), QSFP_DD_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values( + dom_module_threshold_raw, 0) + + # 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_module_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['TxBiasLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TxPowerLowWarning']['value'] + + else: + offset = SFP_MODULE_ADDRA2_OFFSET + + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = sff8472Dom(None, self.calibration) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_specific_bytes((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 + + # 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'] + + for key in transceiver_dom_threshold_info_dict: + transceiver_dom_threshold_info_dict[key] = self._convert_string_to_num( + transceiver_dom_threshold_info_dict[key]) + + return transceiver_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + return self._api_common.get_output(self._sfp_index, self._config['get_reset_status'], False) + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + if not self.dom_supported: + return None + + rx_los_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + + elif self.sfp_type == QSFP_DD_TYPE: + # page 11h + if self.dom_rx_tx_power_bias_supported: + offset = 128 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_DD_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 8) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + rx_los_list.append(rx_los_data & 0x10 != 0) + rx_los_list.append(rx_los_data & 0x20 != 0) + rx_los_list.append(rx_los_data & 0x40 != 0) + rx_los_list.append(rx_los_data & 0x80 != 0) + + else: + offset = 256 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x02 != 0) + else: + return None + return rx_los_list + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + if not self.dom_supported: + return None + + tx_fault_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + + elif self.sfp_type == QSFP_DD_TYPE: + # page 11h + if self.dom_rx_tx_power_bias_supported: + offset = 128 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_DD_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 8) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + tx_fault_list.append(tx_fault_data & 0x10 != 0) + tx_fault_list.append(tx_fault_data & 0x20 != 0) + tx_fault_list.append(tx_fault_data & 0x40 != 0) + tx_fault_list.append(tx_fault_data & 0x80 != 0) + + else: + offset = 256 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + else: + return None + return tx_fault_list + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + Returns: + A list of boolean values, representing the TX disable status + of each available channel, value is True if SFP channel + is TX disabled, False if not. + E.g., for a tranceiver with four channels: [False, False, True, False] + """ + if not self.dom_supported: + return None + + tx_disable_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_DISABLE_STATUS_OFFSET), QSFP_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0x01 != 0) + tx_disable_list.append(tx_disable_data & 0x02 != 0) + tx_disable_list.append(tx_disable_data & 0x04 != 0) + tx_disable_list.append(tx_disable_data & 0x08 != 0) + + elif self.sfp_type == QSFP_DD_TYPE: + if self.dom_rx_tx_power_bias_supported: + offset = 128 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_CHANNL_DISABLE_STATUS_OFFSET), QSFP_DD_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0x01 != 0) + tx_disable_list.append(tx_disable_data & 0x02 != 0) + tx_disable_list.append(tx_disable_data & 0x04 != 0) + tx_disable_list.append(tx_disable_data & 0x08 != 0) + tx_disable_list.append(tx_disable_data & 0x10 != 0) + tx_disable_list.append(tx_disable_data & 0x20 != 0) + tx_disable_list.append(tx_disable_data & 0x40 != 0) + tx_disable_list.append(tx_disable_data & 0x80 != 0) + + else: + offset = 256 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0xC0 != 0) + else: + return None + return tx_disable_list + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + return self._api_common.get_output(self._sfp_index, self._config['get_lpmode'], False) + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + if self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_CONTROL_OFFSET), QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes( + dom_control_raw, 0) + return ('On' == dom_control_data['data']['PowerOverride']) + else: + return NotImplementedError + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + if not self.dom_supported: + return None + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_temp_supported: + dom_temperature_raw = self._read_eeprom_specific_bytes( + (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) + temp = self._convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + return temp + else: + return None + else: + return None + + elif self.sfp_type == QSFP_DD_TYPE: + offset = 0 + + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return None + + if self.dom_temp_supported: + dom_temperature_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_TEMPE_OFFSET), QSFP_DD_TEMPE_WIDTH) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature( + dom_temperature_raw, 0) + temp = self._convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + return temp + return None + + else: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + sfpd_obj._calibration_type = 1 + + dom_temperature_raw = self._read_eeprom_specific_bytes( + (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) + temp = self._convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + return temp + else: + return None + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + Returns: + An integer number of supply voltage in mV + """ + if not self.dom_supported: + return None + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_volt_supported: + dom_voltage_raw = self._read_eeprom_specific_bytes( + (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) + voltage = self._convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + return voltage + else: + return None + return None + + if self.sfp_type == QSFP_DD_TYPE: + offset = 128 + + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return None + + if self.dom_volt_supported: + dom_voltage_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_VOLT_OFFSET), QSFP_DD_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage( + dom_voltage_raw, 0) + voltage = self._convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + return voltage + return None + + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + sfpd_obj._calibration_type = self.calibration + + dom_voltage_raw = self._read_eeprom_specific_bytes( + (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) + voltage = self._convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + return voltage + else: + return None + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + tx_bias_list = [] + if self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (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) + tx_bias_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['TX4Bias']['value'])) + + elif self.sfp_type == QSFP_DD_TYPE: + # page 11h + if self.dom_rx_tx_power_bias_supported: + offset = 128 + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return None + + if dom_tx_bias_power_supported: + dom_tx_bias_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_TX_BIAS_OFFSET), QSFP_DD_TX_BIAS_WIDTH) + if dom_tx_bias_raw is not None: + dom_tx_bias_data = sfpd_obj.parse_dom_tx_bias( + dom_tx_bias_raw, 0) + tx_bias_list.append(self._convert_string_to_num( + dom_tx_bias_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num( + dom_tx_bias_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num( + dom_tx_bias_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num( + dom_tx_bias_data['data']['TX4Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num( + dom_tx_bias_data['data']['TX5Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num( + dom_tx_bias_data['data']['TX6Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num( + dom_tx_bias_data['data']['TX7Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num( + dom_tx_bias_data['data']['TX8Bias']['value'])) + + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + sfpd_obj._calibration_type = self.calibration + + if self.dom_supported: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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) + tx_bias_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['TXBias']['value'])) + else: + return None + else: + return None + + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + rx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (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) + rx_power_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['RX4Power']['value'])) + else: + return None + else: + return None + + elif self.sfp_type == QSFP_DD_TYPE: + # page 11 + if self.dom_rx_tx_power_bias_supported: + offset = 128 + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_rx_power_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_RX_POWER_OFFSET), QSFP_DD_RX_POWER_WIDTH) + if dom_rx_power_raw is not None: + dom_rx_power_data = sfpd_obj.parse_dom_rx_power( + dom_rx_power_raw, 0) + rx_power_list.append(self._convert_string_to_num( + dom_rx_power_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num( + dom_rx_power_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num( + dom_rx_power_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num( + dom_rx_power_data['data']['RX4Power']['value'])) + rx_power_list.append(self._convert_string_to_num( + dom_rx_power_data['data']['RX5Power']['value'])) + rx_power_list.append(self._convert_string_to_num( + dom_rx_power_data['data']['RX6Power']['value'])) + rx_power_list.append(self._convert_string_to_num( + dom_rx_power_data['data']['RX7Power']['value'])) + rx_power_list.append(self._convert_string_to_num( + dom_rx_power_data['data']['RX8Power']['value'])) + + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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) + rx_power_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['RXPower']['value'])) + else: + return None + else: + return None + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + tx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_tx_power_supported: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (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) + tx_power_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['TX4Power']['value'])) + else: + return None + else: + return None + + elif self.sfp_type == QSFP_DD_TYPE: + # page 11 + if self.dom_rx_tx_power_bias_supported: + offset = 128 + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return None + + if self.dom_tx_power_supported: + dom_tx_power_raw = self._read_eeprom_specific_bytes( + (offset + QSFP_DD_TX_POWER_OFFSET), QSFP_DD_TX_POWER_WIDTH) + if dom_tx_power_raw is not None: + dom_tx_power_data = sfpd_obj.parse_dom_tx_power( + dom_tx_power_raw, 0) + tx_power_list.append(self._convert_string_to_num( + dom_tx_power_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num( + dom_tx_power_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num( + dom_tx_power_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num( + dom_tx_power_data['data']['TX4Power']['value'])) + tx_power_list.append(self._convert_string_to_num( + dom_tx_power_data['data']['TX5Power']['value'])) + tx_power_list.append(self._convert_string_to_num( + dom_tx_power_data['data']['TX6Power']['value'])) + tx_power_list.append(self._convert_string_to_num( + dom_tx_power_data['data']['TX7Power']['value'])) + tx_power_list.append(self._convert_string_to_num( + dom_tx_power_data['data']['TX8Power']['value'])) + + else: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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) + tx_power_list.append(self._convert_string_to_num( + dom_channel_monitor_data['data']['TXPower']['value'])) + else: + return None + else: + return None + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + config = self._config['reset'] + # Convert our register value back to a hex string and write back + output1 = self._api_common.set_output(self._sfp_index, "0x0", config) + + # 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 + output2 = self._api_common.set_output(self._sfp_index, "0x1", config) + + return True if (output1 and output2) else False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + if self.sfp_type == QSFP_TYPE: + sysfsfile_eeprom = None + try: + tx_disable_ctl = 0xf if tx_disable else 0x0 + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self._get_eeprom_path() + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + if self.sfp_type == QSFP_TYPE: + sysfsfile_eeprom = None + try: + channel_state = self.get_tx_disable_channel() + tx_enable_mask = [0xe, 0xd, 0xb, 0x7] + tx_disable_mask = [0x1, 0x3, 0x7, 0xf] + tx_disable_ctl = channel_state | tx_disable_mask[ + channel] if disable else channel_state & tx_enable_mask[channel] + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self._get_eeprom_path() + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + return self._api_common.set_output(self._sfp_index, str(lpmode), self._config['set_lpmode']) + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + if self.sfp_type == QSFP_TYPE: + sysfsfile_eeprom = None + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self._get_eeprom_path() + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + + return False diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/thermal.py new file mode 100644 index 000000000000..714e073db37d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/thermal.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the thermal status which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.thermal_base import ThermalBase + from common import Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + def __init__(self, index, _thermal_index=0, conf=None): + ThermalBase.__init__(self) + + self._thermal_index = index + self._config = conf + self._api_common = Common(self._config) + + def get_name(self): + """ + Retrieves the human-readable name of a thermal sensor by 1-based index + + Returns: + :param index: An integer, 1-based index of the thermal sensor of which to query status + :return: String, + A string representing the name of the thermal sensor. + """ + return self._api_common.get_output(self._thermal_index, self._config['get_name'], Common.NULL_VAL) + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + by using command ipmitool raw 0x04 0x2D [address] + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + output = self._api_common.get_output( + self._thermal_index, self._config['get_temperature'], Common.NULL_VAL) + return float(output) if output != Common.NULL_VAL else output + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + output = self._api_common.get_output( + self._thermal_index, self._config['get_high_threshold'], Common.NULL_VAL) + return float(output) if output != Common.NULL_VAL else output + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + lnc as float number and return 0 if the BMC output is na. + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + output = self._api_common.get_output( + self._thermal_index, self._config['get_low_threshold'], Common.NULL_VAL) + return float(output) if output != Common.NULL_VAL else output + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + For AMI BMC device : + use ipmitool command + ipmitool sensor thresh [sensor name] unc [0>= temp_value <=62] + if the current value of unc is 'na' ipmitool can't be set the value + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + output = self._api_common.get_output( + self._thermal_index, self._config['set_high_threshold'], Common.NULL_VAL) + return float(output) if output != Common.NULL_VAL else output + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + For AMI BMC device : + use ipmitool command + ipmitool sensor thresh [sensor name] lnc [temp_value] + if the current value of lnc is 'na' ipmitool can't be set the value + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + output = self._api_common.get_output( + self._thermal_index, self._config['set_low_threshold'], Common.NULL_VAL) + return float(output) if output != Common.NULL_VAL else output + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + ucr as float number and return 0 if the BMC output is na. + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + output = self._api_common.get_output( + self._thermal_index, self._config['get_high_critical_threshold'], Common.NULL_VAL) + return float(output) if output != Common.NULL_VAL else output + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature of thermal + + Returns: + lnr as float number and return 0 if the BMC output is na. + A float number, the low critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + output = self._api_common.get_output( + self._thermal_index, self._config['get_low_critical_threshold'], Common.NULL_VAL) + return float(output) if output != Common.NULL_VAL else output + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + return Common.NULL_VAL + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + return Common.NULL_VAL + + 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 True diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/cfg/silverstone-modules.conf b/platform/broadcom/sonic-platform-modules-cel/silverstone/cfg/silverstone-modules.conf new file mode 100644 index 000000000000..cb8dcf640ba3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/cfg/silverstone-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-pca954x +ipmi_devintf +ipmi_si \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/Makefile new file mode 100644 index 000000000000..f6ad4d9ba4d1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/Makefile @@ -0,0 +1 @@ +obj-m := baseboard-lpc.o mc24lc64t.o switchboard.o \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/baseboard-lpc.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/baseboard-lpc.c new file mode 100644 index 000000000000..b6291f7d3ce4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/baseboard-lpc.c @@ -0,0 +1,433 @@ +/* + * baseboard-lpc.c - The CPLD driver for the Base Board of Silverstone + * The driver implement sysfs to access CPLD register on the baseboard of Silverstone 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 "baseboard-lpc" +/** + * CPLD register address for read and write. + */ +#define VERSION_ADDR 0xA100 +#define SCRATCH_ADDR 0xA101 +#define BLT_MONTH_ADDR 0xA102 +#define BLT_DATE_ADDR 0xA103 +#define REBOOT_CAUSE 0xA106 +#define SYS_LED_ADDR 0xA162 +#define CPLD_REGISTER_SIZE 0x93 + +/* System reboot cause recorded in CPLD */ +static const struct { + const char *reason; + u8 reset_code; +} reboot_causes[] = { + {"POR", 0x11}, + {"soft-warm-rst", 0x22}, + {"soft-cold-rst", 0x33}, + {"warm-rst", 0x44}, + {"cold-rst", 0x55}, + {"wdt-rst", 0x66}, + {"power-cycle", 0x77} +}; + +struct cpld_b_data { + struct mutex cpld_lock; + uint16_t read_addr; +}; + +struct cpld_b_data *cpld_data; + +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); +} + +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) +{ + u8 version; + mutex_lock(&cpld_data->cpld_lock); + version = inb(VERSION_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%d.%d\n", version >> 4, version & 0x0F); +} +static DEVICE_ATTR_RO(version); + +/* CPLD version attributes */ +static ssize_t build_date_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u8 month, day_of_month; + mutex_lock(&cpld_data->cpld_lock); + day_of_month = inb(BLT_DATE_ADDR); + month = inb(BLT_MONTH_ADDR); + mutex_unlock(&cpld_data->cpld_lock); + return sprintf(buf, "%x/%x\n", day_of_month, month); +} +static DEVICE_ATTR_RO(build_date); + + +static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + 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; + + 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) +{ + 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. + */ +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/1hz/4hz + * @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 ? "4hz" : data ==0x01 ? "1hz": "on"); +} + +/** + * Set the status of system led - on/off/1hz/4hz + */ +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, "4hz")){ + led_status = 0x02; + }else if(sysfs_streq(buf, "1hz")){ + 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 + * @return Current led color. + */ +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 + */ +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 ssize_t reboot_cause_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t status; + u8 reg; + int i; + + mutex_lock(&cpld_data->cpld_lock); + reg = inb(REBOOT_CAUSE); + mutex_unlock(&cpld_data->cpld_lock); + + status = 0; + dev_dbg(dev,"reboot: 0x%x\n", (u8)reg); + for(i = 0; i < ARRAY_SIZE(reboot_causes); i++){ + if((u8)reg == reboot_causes[i].reset_code){ + status = sprintf(buf, "%s\n", + reboot_causes[i].reason); + break; + } + } + return status; +} +DEVICE_ATTR_RO(reboot_cause); + +static struct attribute *cpld_b_attrs[] = { + &dev_attr_version.attr, + &dev_attr_build_date.attr, + &dev_attr_scratch.attr, + &dev_attr_getreg.attr, + &dev_attr_setreg.attr, + &dev_attr_sys_led.attr, + &dev_attr_sys_led_color.attr, + &dev_attr_reboot_cause.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 = 0xA192, + .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("Celestica Inc."); +MODULE_DESCRIPTION("Celestica Silverstone CPLD baseboard driver"); +MODULE_VERSION("0.2.0"); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/mc24lc64t.c new file mode 100644 index 000000000000..fc15bb74b68d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/mc24lc64t.c @@ -0,0 +1,174 @@ +/* + * 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 &0xff)); + 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"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switchboard.c b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switchboard.c new file mode 100644 index 000000000000..2ee6c858a8b6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/modules/switchboard.c @@ -0,0 +1,2106 @@ +/* + * switchboard.c - driver for Silverstone 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 + * \--silverstone + * |--FPGA + * |--CPLD1 + * |--CPLD2 + * \--SFF + * |--QSFP[1..32] + * \--SFP[1..2] + * + */ + +#ifndef TEST_MODE +#define MOD_VERSION "1.2.0" +#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 "silverstone_fpga" +#define DRIVER_NAME "switchboard" +#define FPGA_PCI_NAME "Silverstone_fpga_pci" +#define DEVICE_NAME "fwupgrade" + + +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 fpgafw_init(void); +static void fpgafw_exit(void); + + +/* +======================================== +FPGA PCIe BAR 0 Registers +======================================== +Misc Control 0x00000000 – 0x000000FF. +I2C_CH1 0x00000100 - 0x00000110 +I2C_CH2 0x00000200 - 0x00000210. +I2C_CH3 0x00000300 - 0x00000310. +I2C_CH4 0x00000400 - 0x00000410. +I2C_CH5 0x00000500 - 0x00000510. +I2C_CH6 0x00000600 - 0x00000610. +I2C_CH7 0x00000700 - 0x00000710. +I2C_CH8 0x00000800 - 0x00000810. +I2C_CH9 0x00000900 - 0x00000910. +I2C_CH10 0x00000A00 - 0x00000A10. +I2C_CH11 0x00000B00 - 0x00000B10. +I2C_CH12 0x00000C00 - 0x00000C10. +I2C_CH13 0x00000D00 - 0x00000D10. +SPI Master 0x00001200 - 0x00001300. +DPLL SPI Master 0x00001320 - 0x0000132F. +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 FPGA_BROAD_REV_MSK 0x0038 +#define FPGA_BROAD_ID_MSK 0x0007 +#define FPGA_PLL_STATUS 0x0014 +#define BMC_I2C_SCRATCH 0x0020 +#define FPGA_SLAVE_CPLD_REST 0x0030 +#define FPGA_PERIPH_RESET_CTRL 0x0034 +#define FPGA_INT_STATUS 0x0040 +#define FPGA_INT_SRC_STATUS 0x0044 +#define FPGA_INT_FLAG 0x0048 +#define FPGA_INT_MASK 0x004c +#define FPGA_MISC_CTRL 0x0050 +#define FPGA_MISC_STATUS 0x0054 +#define FPGA_AVS_VID_STATUS 0x0068 +#define FPGA_PORT_XCVR_READY 0x000c + +/* I2C_MASTER BASE ADDR */ +#define I2C_MASTER_FREQ_1 0x0100 +#define I2C_MASTER_CTRL_1 0x0104 +#define I2C_MASTER_STATUS_1 0x0108 +#define I2C_MASTER_DATA_1 0x010c +#define I2C_MASTER_PORT_ID_1 0x0110 +#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_TOTAL I2C_MASTER_CH_5 + +/* 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] LPMOD 6 +[5] RSVD +[4] RST 4 +[3:1] RSVD +[0] TXDIS 0 +*/ +#define CTRL_LPMOD 6 +#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 + +enum { + I2C_SR_BIT_RXAK = 0, + I2C_SR_BIT_MIF, + I2C_SR_BIT_SRW, + I2C_SR_BIT_BCSTM, + I2C_SR_BIT_MAL, + I2C_SR_BIT_MBB, + I2C_SR_BIT_MAAS, + I2C_SR_BIT_MCF +}; + +enum { + I2C_CR_BIT_BCST = 0, + I2C_CR_BIT_RSTA = 2, + I2C_CR_BIT_TXAK, + I2C_CR_BIT_MTX, + I2C_CR_BIT_MSTA, + I2C_CR_BIT_MIEN, + I2C_CR_BIT_MEN, +}; + +/** + * + * 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_QSFP_PORT 32 +#define VIRTUAL_I2C_SFP_PORT 2 + +#define SFF_PORT_TOTAL VIRTUAL_I2C_QSFP_PORT + VIRTUAL_I2C_SFP_PORT + +#define VIRTUAL_I2C_BUS_OFFSET 10 +#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 + +#define GET_REG_BIT(REG,BIT) ((ioread8(REG) >> BIT) & 0x01) +#define SET_REG_BIT_H(REG,BIT) iowrite8(ioread8(REG) | (0x01 << BIT),REG) +#define SET_REG_BIT_L(REG,BIT) iowrite8(ioread8(REG) & ~(0x01 << BIT),REG) + +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]; + +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[] = { + /* BUS3 QSFP Exported as virtual bus */ + {I2C_MASTER_CH_3, 0x71, 2, QSFP, "QSFP1"}, {I2C_MASTER_CH_3, 0x71, 3, QSFP, "QSFP2"}, + {I2C_MASTER_CH_3, 0x71, 0, QSFP, "QSFP3"}, {I2C_MASTER_CH_3, 0x71, 1, QSFP, "QSFP4"}, + {I2C_MASTER_CH_3, 0x71, 6, QSFP, "QSFP5"}, {I2C_MASTER_CH_3, 0x71, 5, QSFP, "QSFP6"}, + {I2C_MASTER_CH_3, 0x73, 7, QSFP, "QSFP7"}, {I2C_MASTER_CH_3, 0x71, 4, QSFP, "QSFP8"}, + + {I2C_MASTER_CH_3, 0x73, 4, QSFP, "QSFP9"}, {I2C_MASTER_CH_3, 0x73, 3, QSFP, "QSFP10"}, + {I2C_MASTER_CH_3, 0x73, 6, QSFP, "QSFP11"}, {I2C_MASTER_CH_3, 0x73, 2, QSFP, "QSFP12"}, + {I2C_MASTER_CH_3, 0x73, 1, QSFP, "QSFP13"}, {I2C_MASTER_CH_3, 0x73, 5, QSFP, "QSFP14"}, + {I2C_MASTER_CH_3, 0x71, 7, QSFP, "QSFP15"}, {I2C_MASTER_CH_3, 0x73, 0, QSFP, "QSFP16"}, + + {I2C_MASTER_CH_3, 0x72, 1, QSFP, "QSFP17"}, {I2C_MASTER_CH_3, 0x72, 7, QSFP, "QSFP18"}, + {I2C_MASTER_CH_3, 0x72, 4, QSFP, "QSFP19"}, {I2C_MASTER_CH_3, 0x72, 0, QSFP, "QSFP20"}, + {I2C_MASTER_CH_3, 0x72, 5, QSFP, "QSFP21"}, {I2C_MASTER_CH_3, 0x72, 2, QSFP, "QSFP22"}, + {I2C_MASTER_CH_3, 0x70, 5, QSFP, "QSFP23"}, {I2C_MASTER_CH_3, 0x72, 6, QSFP, "QSFP24"}, + + {I2C_MASTER_CH_3, 0x72, 3, QSFP, "QSFP25"}, {I2C_MASTER_CH_3, 0x70, 6, QSFP, "QSFP26"}, + {I2C_MASTER_CH_3, 0x70, 0, QSFP, "QSFP27"}, {I2C_MASTER_CH_3, 0x70, 7, QSFP, "QSFP28"}, + {I2C_MASTER_CH_3, 0x70, 2, QSFP, "QSFP29"}, {I2C_MASTER_CH_3, 0x70, 4, QSFP, "QSFP30"}, + {I2C_MASTER_CH_3, 0x70, 3, QSFP, "QSFP31"}, {I2C_MASTER_CH_3, 0x70, 1, QSFP, "QSFP32"}, + /* BUS1 SFP+ Exported as virtual bus */ + {I2C_MASTER_CH_1, 0xFF, 0, SFP, "SFP1"}, + /* BUS2 SFP+ Exported as virtual bus */ + {I2C_MASTER_CH_2, 0xFF, 0, SFP, "SFP2"}, + /* BUS4 CPLD Access via I2C */ + {I2C_MASTER_CH_4, 0xFF, 0, NONE, "CPLD_S"}, + /* BUS5 CPLD_B */ + {I2C_MASTER_CH_5, 0xFF, 0, NONE, "CPLD_B"}, +}; + +#define VIRTUAL_I2C_PORT_LENGTH ARRAY_SIZE(fpga_i2c_bus_dev) +#define SW_I2C_CPLD_INDEX SFF_PORT_TOTAL + +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 silverstone_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 silverstone_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; + + +static ssize_t version_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + u32 version; + + mutex_lock(&fpga_data->fpga_lock); + version = ioread32(fpga_dev.data_base_addr + FPGA_VERSION); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d.%d\n", version >> 16, version & 0xFFFF); +} + +/** + * 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; +} + +/** + * Show FPGA port XCVR ready status + * @param buf 1 if the functin is ready, 0 if not. + * @return number of bytes read, or an error code + */ +static ssize_t ready_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + unsigned int REGISTER = FPGA_PORT_XCVR_READY; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> 0) & 1U); +} + +/* 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 DEVICE_ATTR_RO(ready); +static DEVICE_ATTR_RO(version); + +static struct attribute *fpga_attrs[] = { + &dev_attr_getreg.attr, + &dev_attr_scratch.attr, + &dev_attr_setreg.attr, + &dev_attr_ready.attr, + &dev_attr_version.attr, + NULL, +}; + +static struct attribute_group fpga_attr_grp = { + .attrs = fpga_attrs, +}; + +static ssize_t cpld1_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 version; + int err; + err = 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 *)&version); + if (err < 0) + return err; + return sprintf(buf, "%d.%d\n", version >> 4, version & 0x0F); +} +struct device_attribute dev_attr_cpld1_version = __ATTR(version, 0444, cpld1_version_show , NULL); + +/* 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_version.attr, + &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_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 version; + int err; + err = 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 *)&version); + if (err < 0) + return err; + return sprintf(buf, "%d.%d\n", version >> 4, version & 0x0F); +} +struct device_attribute dev_attr_cpld2_version = __ATTR(version, 0444, cpld2_version_show , NULL); + +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_version.attr, + &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) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_IRQ) & 1U); +} +DEVICE_ATTR_RO(qsfp_modirq); + +static ssize_t qsfp_modprs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_PRESENT) & 1U); +} +DEVICE_ATTR_RO(qsfp_modprs); + +static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_TXFAULT) & 1U); +} +DEVICE_ATTR_RO(sfp_txfault); + +static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_RXLOS) & 1U); +} +DEVICE_ATTR_RO(sfp_rxlos); + +static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_STATUS_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> STAT_MODABS) & 1U); +} +DEVICE_ATTR_RO(sfp_modabs); + +static ssize_t qsfp_lpmode_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> CTRL_LPMOD) & 1U); +} +static ssize_t qsfp_lpmode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + ssize_t status; + long value; + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtol(buf, 0, &value); + if (status == 0) { + // if value is 0, disable the lpmode + data = ioread32(fpga_dev.data_base_addr + REGISTER); + if (!value) + data = data & ~( (u32)0x1 << CTRL_LPMOD); + else + data = data | ((u32)0x1 << CTRL_LPMOD); + iowrite32(data, fpga_dev.data_base_addr + REGISTER); + status = size; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(qsfp_lpmode); + +static ssize_t qsfp_reset_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> 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; + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtol(buf, 0, &value); + if (status == 0) { + // if value is 0, reset signal is low + data = ioread32(fpga_dev.data_base_addr + REGISTER); + if (!value) + data = data & ~( (u32)0x1 << CTRL_RST); + else + data = data | ((u32)0x1 << CTRL_RST); + iowrite32(data, fpga_dev.data_base_addr + REGISTER); + status = size; + } + mutex_unlock(&fpga_data->fpga_lock); + return status; +} +DEVICE_ATTR_RW(qsfp_reset); + +static ssize_t sfp_txdisable_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + data = ioread32(fpga_dev.data_base_addr + REGISTER); + mutex_unlock(&fpga_data->fpga_lock); + return sprintf(buf, "%d\n", (data >> 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; + u32 data; + struct sff_device_data *dev_data = dev_get_drvdata(dev); + unsigned int portid = dev_data->portid; + unsigned int REGISTER = SFF_PORT_CTRL_BASE + (portid - 1) * 0x10; + + mutex_lock(&fpga_data->fpga_lock); + status = kstrtol(buf, 0, &value); + if (status == 0) { + // check if value is 0 clear + data = ioread32(fpga_dev.data_base_addr + REGISTER); + if (!value) + data = data & ~( (u32)0x1 << CTRL_TXDIS); + else + data = data | ((u32)0x1 << CTRL_TXDIS); + iowrite32(data, fpga_dev.data_base_addr + REGISTER); + 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_lpmode.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 R/G/B/C/M/Y/W/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 ? "red" : led_color1 == 0x04 ? + "yellow" : led_color1 == 0x03 ? "blue" : led_color1 == 0x02 ? "cyan" : led_color1 == 0x01 ? "magenta" : "white", + led_color1 == 0x07 ? "off" : led_color1 == 0x06 ? "green" : led_color1 == 0x05 ? "red" : led_color1 == 0x04 ? + "yellow" : led_color1 == 0x03 ? "blue" : led_color1 == 0x02 ? "cyan" : led_color1 == 0x01 ? "magenta" : "white"); +} + +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, "red")) { + led_color = 0x05; + } else if (sysfs_streq(buf, "yellow")) { + led_color = 0x04; + } else if (sysfs_streq(buf, "blue")) { + led_color = 0x03; + } else if (sysfs_streq(buf, "cyan")) { + led_color = 0x02; + } else if (sysfs_streq(buf, "magenta")) { + led_color = 0x01; + } else if (sysfs_streq(buf, "white")) { + led_color = 0x00; + } 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 * silverstone_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_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_FDR0; + unsigned int REG_CR0; + unsigned int REG_SR0; + unsigned int REG_DR0; + unsigned int REG_ID0; + + 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_FDR0 = I2C_MASTER_FREQ_1 + (master_bus - 1) * 0x0100; + REG_CR0 = I2C_MASTER_CTRL_1 + (master_bus - 1) * 0x0100; + REG_SR0 = I2C_MASTER_STATUS_1 + (master_bus - 1) * 0x0100; + REG_DR0 = I2C_MASTER_DATA_1 + (master_bus - 1) * 0x0100; + REG_ID0 = I2C_MASTER_PORT_ID_1 + (master_bus - 1) * 0x0100; + + check(pci_bar + REG_SR0); + check(pci_bar + REG_CR0); + + timeout = jiffies + msecs_to_jiffies(timeout); + while (1) { + Status = ioread8(pci_bar + REG_SR0); + if (jiffies > timeout) { + info("Status %2.2X", Status); + info("Error Timeout"); + error = -ETIMEDOUT; + break; + } + + + if (Status & (1 << I2C_SR_BIT_MIF)) { + break; + } + + if (writing == 0 && (Status & (1 << I2C_SR_BIT_MCF))) { + break; + } + } + Status = ioread8(pci_bar + REG_SR0); + iowrite8(0, pci_bar + REG_SR0); + + if (error < 0) { + info("Status %2.2X", Status); + return error; + } + + if (!(Status & (1 << I2C_SR_BIT_MCF))) { + info("Error Unfinish"); + return -EIO; + } + + if (Status & (1 << I2C_SR_BIT_MAL)) { + info("Error MAL"); + return -EAGAIN; + } + + if (Status & (1 << I2C_SR_BIT_RXAK)) { + info( "SL No Acknowlege"); + if (writing) { + info("Error No Acknowlege"); + iowrite8(1 << I2C_CR_BIT_MEN, pci_bar + REG_CR0); + return -ENXIO; + } + } else { + info( "SL Acknowlege"); + } + + return 0; +} + +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; + unsigned int REG_FDR0; + unsigned int REG_CR0; + unsigned int REG_SR0; + unsigned int REG_DR0; + unsigned int REG_ID0; + + /* Write the command register */ + dev_data = i2c_get_adapdata(adapter); + portid = dev_data->portid; + pci_bar = fpga_dev.data_base_addr; + master_bus = dev_data->pca9548.master_bus; + REG_FDR0 = I2C_MASTER_FREQ_1 + (master_bus - 1) * 0x0100; + REG_CR0 = I2C_MASTER_CTRL_1 + (master_bus - 1) * 0x0100; + REG_SR0 = I2C_MASTER_STATUS_1 + (master_bus - 1) * 0x0100; + REG_DR0 = I2C_MASTER_DATA_1 + (master_bus - 1) * 0x0100; + REG_ID0 = I2C_MASTER_PORT_ID_1 + (master_bus - 1) * 0x0100; + + if (master_bus < I2C_MASTER_CH_1 || master_bus > I2C_MASTER_CH_TOTAL) { + error = -EINVAL; + goto Done; + } + +#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" : "ERROR" + , cmd); +#endif + /* 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: + break; + default: + printk(KERN_INFO "Unsupported transaction %d\n", size); + error = -EOPNOTSUPP; + goto Done; + } + + iowrite8(portid, pci_bar + REG_ID0); + + ////[S][ADDR/R] + //Clear status register + iowrite8(0, pci_bar + REG_SR0); + iowrite8(1 << I2C_CR_BIT_MIEN | 1 << I2C_CR_BIT_MTX | 1 << I2C_CR_BIT_MSTA , pci_bar + REG_CR0); + SET_REG_BIT_H(pci_bar + REG_CR0, I2C_CR_BIT_MEN); + + 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_DR0); + } else { + // sent device address with Write mode + iowrite8(addr << 1 | 0x00, pci_bar + REG_DR0); + } + + + + info( "MS Start"); + + //// Wait {A} + error = i2c_wait_ack(adapter, 12, 1); + if (error < 0) { + info( "get error %d", error); + goto Done; + } + + //// [CMD]{A} + if (size == I2C_SMBUS_BYTE_DATA || + size == I2C_SMBUS_WORD_DATA || + size == I2C_SMBUS_BLOCK_DATA || + (size == I2C_SMBUS_BYTE && rw == I2C_SMBUS_WRITE)) { + + //sent command code to data register + iowrite8(cmd, pci_bar + REG_DR0); + info( "MS Send CMD 0x%2.2X", cmd); + + // Wait {A} + error = i2c_wait_ack(adapter, 12, 1); + if (error < 0) { + info( "get error %d", 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: + // in block data mode keep number of byte in block[0] + cnt = data->block[0]; + break; + default: + cnt = 0; break; + } + + // [CNT] used only bloack data write + if (size == I2C_SMBUS_BLOCK_DATA && rw == I2C_SMBUS_WRITE) { + + iowrite8(cnt, pci_bar + REG_DR0); + info( "MS Send CNT 0x%2.2X", cnt); + + // Wait {A} + error = i2c_wait_ack(adapter, 12, 1); + if (error < 0) { + info( "get error %d", 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 + )) { + int bid = 0; + info( "MS prepare to sent [%d bytes]", cnt); + if (size == I2C_SMBUS_BLOCK_DATA ) { + bid = 1; // block[0] is cnt; + cnt += 1; // offset from block[0] + } + for (; bid < cnt; bid++) { + + iowrite8(data->block[bid], pci_bar + REG_DR0); + info( " Data > %2.2X", data->block[bid]); + // Wait {A} + error = i2c_wait_ack(adapter, 12, 1); + if (error < 0) { + goto Done; + } + } + } + + //REPEATE START + if ( rw == I2C_SMBUS_READ && ( + size == I2C_SMBUS_BYTE_DATA || + size == I2C_SMBUS_WORD_DATA || + size == I2C_SMBUS_BLOCK_DATA + )) { + info( "MS Repeated Start"); + + SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MEN); + iowrite8(1 << I2C_CR_BIT_MIEN | + 1 << I2C_CR_BIT_MTX | + 1 << I2C_CR_BIT_MSTA | + 1 << I2C_CR_BIT_RSTA , pci_bar + REG_CR0); + SET_REG_BIT_H(pci_bar + REG_CR0, I2C_CR_BIT_MEN); + + // sent Address with Read mode + iowrite8( addr << 1 | 0x1 , pci_bar + REG_DR0); + + // Wait {A} + error = i2c_wait_ack(adapter, 12, 1); + if (error < 0) { + 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 + )) { + + 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; + default: + cnt = 0; break; + } + + info( "MS Receive"); + + //set to Receive mode + iowrite8(1 << I2C_CR_BIT_MEN | + 1 << I2C_CR_BIT_MIEN | + 1 << I2C_CR_BIT_MSTA , pci_bar + REG_CR0); + + for (bid = -1; bid < cnt; bid++) { + + // Wait {A} + error = i2c_wait_ack(adapter, 12, 0); + if (error < 0) { + goto Done; + } + + if (bid == cnt - 2) { + info( "SET NAK"); + SET_REG_BIT_H(pci_bar + REG_CR0, I2C_CR_BIT_TXAK); + } + + if (bid < 0) { + ioread8(pci_bar + REG_DR0); + info( "READ Dummy Byte" ); + } else { + + if (bid == cnt - 1) { + info ( "SET STOP in read loop"); + SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MSTA); + } + data->block[bid] = ioread8(pci_bar + REG_DR0); + + info( "DATA IN [%d] %2.2X", bid, data->block[bid]); + + if (size == I2C_SMBUS_BLOCK_DATA && bid == 0) { + cnt = data->block[0] + 1; + } + } + } + } + + //[P] + SET_REG_BIT_L(pci_bar + REG_CR0, I2C_CR_BIT_MSTA); + i2c_wait_ack(adapter, 12, 0); + info( "MS STOP"); + +Done: + iowrite8(1 << I2C_CR_BIT_MEN, pci_bar + REG_CR0); + check(pci_bar + REG_CR0); + check(pci_bar + REG_SR0); +#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 = 0; + struct i2c_dev_data *dev_data; + unsigned char master_bus; + unsigned char switch_addr; + unsigned char channel; + uint16_t prev_port = 0; + unsigned char prev_switch; + unsigned char prev_ch; + int retry; + + 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; + + // 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 + 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", channel, switch_addr, 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", channel, switch_addr, 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 + error = smbus_access(adapter, addr, flags, rw, cmd, size, data); + 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); + } + +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 error; +} + + + +/** + * 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; +} + +static const struct i2c_algorithm silverstone_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 * silverstone_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; + void __iomem *i2c_freq_base_reg; + + 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 = &silverstone_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_freq_base_reg = fpga_dev.data_base_addr + I2C_MASTER_FREQ_1; + iowrite8(0x07, i2c_freq_base_reg + (new_data->pca9548.master_bus - 1) * 0x100); // 0x07 400kHz + 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; +}; + +static void silverstone_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device silverstone_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = 0, + .resource = NULL, + .dev = { + .release = silverstone_dev_release, + } +}; + +/** + * Board info for QSFP/SFP+ eeprom. + * Note: Using OOM optoe as I2C 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 silverstone_drv_probe(struct platform_device *pdev) +{ + 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 silverstone_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]); + } + + 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 = 0 ; portid_count < VIRTUAL_I2C_PORT_LENGTH ; portid_count++) { + fpga_data->i2c_adapter[portid_count] = silverstone_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] = silverstone_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"); + } + } + +#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++) { + + 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 silverstone_drv_remove(struct platform_device *pdev) +{ + int portid_count; + struct sff_device_data *rem_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]); + i2c_del_adapter(fpga_data->i2c_adapter[portid_count]); + } + } + + 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; +} + +#ifdef TEST_MODE +#define FPGA_PCI_BAR_NUM 2 +#else +#define FPGA_PCI_BAR_NUM 0 +#endif + +static struct platform_driver silverstone_drv = { + .probe = silverstone_drv_probe, + .remove = __exit_p(silverstone_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +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 = pci_iomap(pdev, FPGA_PCI_BAR_NUM, 0); + 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(&silverstone_dev); + platform_driver_register(&silverstone_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(&silverstone_drv); + platform_device_unregister(&silverstone_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 silverstone_init(void) +{ + int rc; + rc = pci_register_driver(&pci_dev_ops); + if (rc) + return rc; + return 0; +} + +void silverstone_exit(void) +{ + pci_unregister_driver(&pci_dev_ops); +} + +module_init(silverstone_init); +module_exit(silverstone_exit); + +MODULE_AUTHOR("Celestica Inc."); +MODULE_DESCRIPTION("Celestica Silverstone platform driver"); +MODULE_VERSION(MOD_VERSION); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/platform_sensors.py new file mode 100755 index 000000000000..186ee6c5450e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/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/silverstone/scripts/sensors b/platform/broadcom/sonic-platform-modules-cel/silverstone/scripts/sensors new file mode 100755 index 000000000000..405d92c2b3cc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/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/silverstone/setup.py b/platform/broadcom/sonic-platform-modules-cel/silverstone/setup.py new file mode 100644 index 000000000000..20a2b6d1063a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/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/silverstone/systemd/platform-modules-silverstone.service b/platform/broadcom/sonic-platform-modules-cel/silverstone/systemd/platform-modules-silverstone.service new file mode 100644 index 000000000000..907764153a27 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone/systemd/platform-modules-silverstone.service @@ -0,0 +1,13 @@ +[Unit] +Description=Celestica Silverstone platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-silverstone start +ExecStop=-/etc/init.d/platform-modules-silverstone stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/.gitignore b/platform/broadcom/sonic-platform-modules-dell/.gitignore new file mode 100644 index 000000000000..f62ae4876450 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/.gitignore @@ -0,0 +1,53 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars + +# Cloned source repositories +tools/flashrom/ diff --git a/platform/broadcom/sonic-platform-modules-dell/LICENSE b/platform/broadcom/sonic-platform-modules-dell/LICENSE new file mode 100644 index 000000000000..243a846ea80b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Dell, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-dell/README.md b/platform/broadcom/sonic-platform-modules-dell/README.md new file mode 100644 index 000000000000..a9f5358192ad --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/README.md @@ -0,0 +1 @@ +platform drivers for Dell Z9100 for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-dell/common/dell_i2c_utils.sh b/platform/broadcom/sonic-platform-modules-dell/common/dell_i2c_utils.sh new file mode 100755 index 000000000000..7ebf1e544497 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/dell_i2c_utils.sh @@ -0,0 +1,127 @@ +# Perform an i2c device configuration : instantiate / delete. +# Input is of the form: +# "echo [driver] > " +# where operation = "new_device" or "delete_device" + +i2c_config() { + local count=0 + local MAX_BUS_RETRY=20 + local MAX_I2C_OP_RETRY=10 + + i2c_bus_op=`echo "$@" | cut -d'>' -f 2` + i2c_bus=$(dirname $i2c_bus_op) + + # check if bus exists + while [[ "$count" -lt "$MAX_BUS_RETRY" ]]; do + [[ -e $i2c_bus ]] && break || sleep .1 + count=$((count+1)) + done + + if [[ "$count" -eq "$MAX_BUS_RETRY" ]]; then + echo "dell_i2c_utils : ERROR: $@ : i2c bus not created" + return + fi + + # perform the add/delete + count=0 + while [[ "$count" -lt "$MAX_I2C_OP_RETRY" ]]; do + eval "$@" > /dev/null 2>&1 + [[ $? == 0 ]] && break || sleep .2 + count=$((count+1)) + done + + if [[ "$count" -eq "$MAX_I2C_OP_RETRY" ]]; then + echo "dell_i2c_utils : ERROR: $@ : i2c operation failed" + return + fi +} + +# Check if a i2c bus exists. Poll for upto 2 seconds since mux creation may take time.. +# Input: bus to check for existence + +i2c_poll_bus_exists() { + local count=0 + local MAX_BUS_RETRY=20 + local i2c_bus + + i2c_bus=$1 + + # check if bus exists + while [[ "$count" -lt "$MAX_BUS_RETRY" ]]; do + [[ -e $i2c_bus ]] && break || sleep .1 + count=$((count+1)) + done + + if [[ "$count" -eq "$MAX_BUS_RETRY" ]]; then + echo "dell_i2c_utils : ERROR: $@ : i2c bus not created" + return 1 + else + return 0 + fi +} + +# Perform an i2c mux device create +# Input is of the form: +# i2c_mux_create mux_driver i2c_addr i2c_bus_num i2c_child_bus_num_start +# where i2c_bus_num is the bus number in which the mux is to be created and +# i2c_child_bus_num_start is the first of the 8 bus channels that this mux should create +i2c_mux_create() { + local MAX_MUX_CHANNEL_RETRY=3 + local MAX_MUX_CHANNELS=8 + local count=0 + local i + local mux_driver=$1 + local i2c_addr=$2 + local i2c_bus_num=$3 + local i2c_child_bus_num_start=$4 + + # Construct the i2c bus, the first and last bus channels that will be created under the MUX + i2c_bus=/sys/bus/i2c/devices/i2c-$i2c_bus_num + i2c_mux_channel_first=$i2c_bus/i2c-$i2c_child_bus_num_start + i2c_mux_channel_last=$i2c_bus/i2c-$(expr $i2c_child_bus_num_start + $MAX_MUX_CHANNELS - 1) + + if i2c_poll_bus_exists $i2c_bus; then + while [[ "$count" -lt "$MAX_MUX_CHANNEL_RETRY" ]]; do + eval "echo $mux_driver $i2c_addr > /sys/bus/i2c/devices/i2c-$i2c_bus_num/new_device" > /dev/null 2>&1 + ret=$? + + # Give more time for the mux channels to get created based on retries + i=0 + while [[ "$i" -lt "$count" ]]; do + sleep 1 + i=$((i+1)) + done + + # Check if the (first and last) mux channels got created + if [[ $ret -eq "0" && -e $i2c_mux_channel_first && -e $i2c_mux_channel_last ]]; then + break; + else + # If the channel did not get created, remove the mux, reset the mux tree and retry + echo "dell_i2c_utils : ERROR: i2c mux channel not created for $mux_driver,$i2c_addr,$i2c_bus_num" + i2c_mux_delete $i2c_addr $i2c_bus_num + reset_muxes + fi + + count=$((count+1)) + done + fi + + if [[ "$count" -eq "$MAX_MUX_CHANNEL_RETRY" ]]; then + echo "dell_i2c_utils : ERROR: $1,$2 : i2c mux channel not created" + return + fi + + return +} + +# Perform an i2c mux device delete +# Input is of the form: +# i2c_mux_delete i2c_addr i2c_bus_num +i2c_mux_delete() { + local i2c_addr + local i2c_bus_num + + i2c_addr=$1 + i2c_bus_num=$2 + i2c_config "echo $i2c_addr > /sys/bus/i2c/devices/i2c-$i2c_bus_num/delete_device" +} diff --git a/platform/broadcom/sonic-platform-modules-dell/common/dell_ich.c b/platform/broadcom/sonic-platform-modules-dell/common/dell_ich.c new file mode 100644 index 000000000000..eb164e46fac5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/dell_ich.c @@ -0,0 +1,1043 @@ +/* Copyright (c) 2018 Dell Inc. + * dell_ich.c - ICH driver for Dell Avoton/Rangeley switches + * + * 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. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "dell_ich" + +#define AVOTON_PCU_DEVICE_ID 0x1f38 + +// GPIO registers +// GPIO Core Control/Access Registers in I/O Space +#define GPIO_SC_USE_SEL 0x0 +#define GPIO_SC_IO_SEL 0x4 +#define GPIO_SC_GP_LVL 0x8 +#define GPIO_SC_TPE 0xC +#define GPIO_SC_TNE 0x10 +#define GPIO_SC_TS 0x14 + +// GPIO SUS Control/Access Registers in I/O Space +#define GPIO_SUS_USE_SEL 0x80 +#define GPIO_SUS_IO_SEL 0x84 +#define GPIO_SUS_GP_LVL 0x88 +#define GPIO_SUS_TPE 0x8C +#define GPIO_SUS_TNE 0x90 +#define GPIO_SUS_TS 0x94 +#define GPIO_SUS_WAKE_EN 0x98 + +static const unsigned char avoton_gpio_regs[] = { + GPIO_SC_USE_SEL, + GPIO_SC_IO_SEL, + GPIO_SC_GP_LVL, + GPIO_SC_TPE, + GPIO_SC_TNE, + GPIO_SC_TS, + GPIO_SUS_USE_SEL, + GPIO_SUS_IO_SEL, + GPIO_SUS_GP_LVL, + GPIO_SUS_TPE, + GPIO_SUS_TNE, + GPIO_SUS_TS, + GPIO_SUS_WAKE_EN +}; + +#define GPIO_REG_LEN 0x4 + +#define GPIOS0_EN (1 << 0) +#define GPIOS1_EN (1 << 1) +#define GPIOS2_EN (1 << 2) +#define GPIOS3_EN (1 << 3) +#define GPIOS4_EN (1 << 4) +#define GPIOS5_EN (1 << 5) +#define GPIOS6_EN (1 << 6) +#define GPIOS7_EN (1 << 7) + +#define GPIOSUS0_EN (1 << 0) +#define GPIOSUS1_EN (1 << 1) +#define GPIOSUS2_EN (1 << 2) +#define GPIOSUS3_EN (1 << 3) +// GPIOSUS4_EN : unused +// GPIOSUS5_EN : unused +#define GPIOSUS6_EN (1 << 6) +#define GPIOSUS7_EN (1 << 7) + + +// GPE0a_EN - General Purpose Event 0 Enables +#define GPIO_GPE0a_EN_SUS0 (1 << 16) +#define GPIO_GPE0a_EN_SUS1 (1 << 17) +#define GPIO_GPE0a_EN_SUS2 (1 << 18) +#define GPIO_GPE0a_EN_SUS3 (1 << 19) +// GPIO_GPE0a_EN_SUS4 : unused +// GPIO_GPE0a_EN_SUS5 : unused +#define GPIO_GPE0a_EN_SUS6 (1 << 22) +#define GPIO_GPE0a_EN_SUS7 (1 << 23) + +#define GPIO_GPE0a_EN_CORE0 (1 << 24) +#define GPIO_GPE0a_EN_CORE1 (1 << 25) +#define GPIO_GPE0a_EN_CORE2 (1 << 26) +#define GPIO_GPE0a_EN_CORE3 (1 << 27) +#define GPIO_GPE0a_EN_CORE4 (1 << 28) +#define GPIO_GPE0a_EN_CORE5 (1 << 29) +#define GPIO_GPE0a_EN_CORE6 (1 << 30) +#define GPIO_GPE0a_EN_CORE7 (1 << 31) + +// GPE0a_STS - General Purpose Event 0 Status +// We're interested in only SUS6 for now +#define GPIO_GPE0a_STS_SUS6 (1 << 22) + +// GPIO_ROUT - GPIO_ROUT Register +#define GPIO_ROUT_OFFSET_SUS0 0 +#define GPIO_ROUT_OFFSET_SUS1 2 +#define GPIO_ROUT_OFFSET_SUS2 4 +#define GPIO_ROUT_OFFSET_SUS3 6 +// GPIO_ROUT_OFFSET_SUS4 : unused +// GPIO_ROUT_OFFSET_SUS5 : unused +#define GPIO_ROUT_OFFSET_SUS6 12 +#define GPIO_ROUT_OFFSET_SUS7 14 + +#define GPIO_ROUT_OFFSET_CORE0 16 +#define GPIO_ROUT_OFFSET_CORE1 18 +#define GPIO_ROUT_OFFSET_CORE2 20 +#define GPIO_ROUT_OFFSET_CORE3 22 +#define GPIO_ROUT_OFFSET_CORE4 24 +#define GPIO_ROUT_OFFSET_CORE5 26 +#define GPIO_ROUT_OFFSET_CORE6 28 +#define GPIO_ROUT_OFFSET_CORE7 30 + +enum GPIO_ROUT { + GPIO_NO_EFFECT = 0, + GPIO_SMI, + GPIO_SCI, + GPIO_RESERVED +}; + +/* + * GPIO resources + * defined as in drivers/gpio/gpio-ich.c + */ +#define ICH_RES_GPIO 0 +#define ICH_RES_GPE0 1 +static struct resource gpio_ich_res[] = { + /* GPIO */ + { + .flags = IORESOURCE_IO, + }, + /* ACPI - GPE0 */ + { + .flags = IORESOURCE_IO, + }, +}; + +// ACPI registers +#define ACPI_GPE0a_STS 0x20 +#define ACPI_GPE0a_EN 0x28 + +// PMC registers +#define PMC_GPIO_ROUT 0x58 +#define PMC_REG_LEN 0x4 + +// lpc_ich_priv is derived from drivers/mfd/lpc_ich.c +struct lpc_ich_priv { + int chipset; + + int abase; /* ACPI base */ + int actrl_pbase; /* ACPI control or PMC base */ + int gbase; /* GPIO base */ + int gctrl; /* GPIO control */ + + int abase_save; /* Cached ACPI base value */ + int actrl_pbase_save; /* Cached ACPI control or PMC base value */ + int gctrl_save; /* Cached GPIO control value */ +}; + +#define ICH_RES_MEM_GCS_PMC 0 + +#define IO_REG_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start) +#define IO_REG_READ(reg, base_res) inl((reg) + (base_res)->start) + +struct resource pmc_res = {.flags = IORESOURCE_MEM,}; + +static struct kobject *dell_kobj; +static unsigned short force_id; +module_param(force_id, ushort, 0); + +#define SMF_REG_ADDR 0x200 +#define SIO_REG_DEVID 0x1 +#define SIO_Z9100_ID 0x1 +#define SIO_S6100_ID 0x2 +#define SIO_S4200_ID 0x3 +#define SIO_S5148_ID 0x4 + +enum kinds { + z9100smf, s6100smf +}; + +struct dell_ich_data { + enum kinds kind; + struct resource *gpio_base, *acpi_base, *pmc_base; + int gpio_alloc,pmc_alloc; + unsigned int int_gpio_sus6_count; +}; + +// GPIO sysfs attributes + +static ssize_t get_sc_use_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_USE_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_use_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_USE_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_io_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_IO_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_io_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_IO_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_lvl(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_GP_LVL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_lvl(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_GP_LVL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_tpe(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TPE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_tpe(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TPE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_tne(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TNE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_tne(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TNE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sc_gp_ts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SC_TS,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sc_gp_ts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SC_TS,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_use_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_USE_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_use_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_USE_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_io_sel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_IO_SEL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_io_sel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_IO_SEL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_lvl(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_GP_LVL,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_lvl(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_GP_LVL,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_tpe(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TPE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_tpe(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TPE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_tne(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TNE,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_tne(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TNE,ich_data->gpio_base); + + return count; +} + +static ssize_t get_sus_gp_ts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(GPIO_SUS_TS,ich_data->gpio_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sus_gp_ts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,GPIO_SUS_TS,ich_data->gpio_base); + + return count; +} + +static DEVICE_ATTR(sc_use_sel, S_IRUGO | S_IWUSR, get_sc_use_sel, set_sc_use_sel); +static DEVICE_ATTR(sc_io_sel, S_IRUGO | S_IWUSR, get_sc_io_sel, set_sc_io_sel); +static DEVICE_ATTR(sc_gp_lvl, S_IRUGO | S_IWUSR, get_sc_gp_lvl, set_sc_gp_lvl); +static DEVICE_ATTR(sc_gp_tpe, S_IRUGO | S_IWUSR, get_sc_gp_tpe, set_sc_gp_tpe); +static DEVICE_ATTR(sc_gp_tne, S_IRUGO | S_IWUSR, get_sc_gp_tne, set_sc_gp_tne); +static DEVICE_ATTR(sc_gp_ts, S_IRUGO | S_IWUSR, get_sc_gp_ts, set_sc_gp_ts); +static DEVICE_ATTR(sus_use_sel, S_IRUGO | S_IWUSR, get_sus_use_sel,set_sus_use_sel); +static DEVICE_ATTR(sus_io_sel, S_IRUGO | S_IWUSR, get_sus_io_sel, set_sus_io_sel); +static DEVICE_ATTR(sus_gp_lvl, S_IRUGO | S_IWUSR, get_sus_gp_lvl, set_sus_gp_lvl); +static DEVICE_ATTR(sus_gp_tpe, S_IRUGO | S_IWUSR, get_sus_gp_tpe, set_sus_gp_tpe); +static DEVICE_ATTR(sus_gp_tne, S_IRUGO | S_IWUSR, get_sus_gp_tne, set_sus_gp_tne); +static DEVICE_ATTR(sus_gp_ts, S_IRUGO | S_IWUSR, get_sus_gp_ts, set_sus_gp_ts); + +static struct attribute *gpio_attrs[] = { + &dev_attr_sc_use_sel.attr, + &dev_attr_sc_io_sel.attr, + &dev_attr_sc_gp_lvl.attr, + &dev_attr_sc_gp_tpe.attr, + &dev_attr_sc_gp_tne.attr, + &dev_attr_sc_gp_ts.attr, + &dev_attr_sus_use_sel.attr, + &dev_attr_sus_io_sel.attr, + &dev_attr_sus_gp_lvl.attr, + &dev_attr_sus_gp_tpe.attr, + &dev_attr_sus_gp_tne.attr, + &dev_attr_sus_gp_ts.attr, + NULL, +}; + +static struct attribute_group gpio_attrs_group= { + .attrs = gpio_attrs, +}; + +// ACPI sysfs attributes + +static ssize_t get_gpe0a_sts(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(ACPI_GPE0a_STS,ich_data->acpi_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_gpe0a_sts(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,ACPI_GPE0a_STS,ich_data->acpi_base); + + return count; +} + +static ssize_t get_gpe0a_en(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = IO_REG_READ(ACPI_GPE0a_EN,ich_data->acpi_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_gpe0a_en(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + IO_REG_WRITE(devdata,ACPI_GPE0a_EN,ich_data->acpi_base); + + return count; +} + +static DEVICE_ATTR(gpe0a_sts, S_IRUGO | S_IWUSR, get_gpe0a_sts, set_gpe0a_sts); +static DEVICE_ATTR(gpe0a_en, S_IRUGO | S_IWUSR, get_gpe0a_en, set_gpe0a_en); + +static struct attribute *acpi_attrs[] = { + &dev_attr_gpe0a_sts.attr, + &dev_attr_gpe0a_en.attr, + NULL, +}; + +static struct attribute_group acpi_attrs_group= { + .attrs = acpi_attrs, +}; + +static ssize_t get_gpio_rout(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = readl(ich_data->pmc_base); + return sprintf(buf,"0x%08x\n",devdata); +} + +// PMC sysfs attributes + +static ssize_t set_gpio_rout(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + writel(devdata,ich_data->pmc_base); + + return count; +} + +static DEVICE_ATTR(gpio_rout, S_IRUGO | S_IWUSR, get_gpio_rout, set_gpio_rout); + +static struct attribute *pmc_attrs[] = { + &dev_attr_gpio_rout.attr, + NULL, +}; + +static struct attribute_group pmc_attrs_group= { + .attrs = pmc_attrs, +}; + +// SCI interrupt sysfs attributes + +static ssize_t get_sci_int_gpio_sus6(struct device *dev, struct device_attribute *devattr, char *buf) +{ + u32 devdata=0; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!ich_data) return sprintf(buf, "read error"); + + devdata = ich_data->int_gpio_sus6_count; + return sprintf(buf,"0x%08x\n",devdata); +} + +static ssize_t set_sci_int_gpio_sus6(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + ich_data->int_gpio_sus6_count = devdata; + + return count; +} + +static DEVICE_ATTR(sci_int_gpio_sus6, S_IRUGO | S_IWUSR, get_sci_int_gpio_sus6, set_sci_int_gpio_sus6); + +static struct attribute *sci_attrs[] = { + &dev_attr_sci_int_gpio_sus6.attr, + NULL, +}; + +static struct attribute_group sci_attrs_group= { + .attrs = sci_attrs, +}; + +static u32 dell_ich_sci_handler(void *context) +{ + unsigned int data; + struct device *dev = (struct device *)context; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + if(!dev) return ACPI_INTERRUPT_NOT_HANDLED; + + ich_data = dev_get_platdata(dev); + if(!ich_data) return ACPI_INTERRUPT_NOT_HANDLED; + + data=IO_REG_READ(ACPI_GPE0a_STS,ich_data->acpi_base); + if(data & GPIO_GPE0a_STS_SUS6) { + // Clear the SUS6 status + IO_REG_WRITE(data,ACPI_GPE0a_STS,ich_data->acpi_base); + ich_data->int_gpio_sus6_count++; + // and notify the user space clients + sysfs_notify(&dev->kobj, NULL, "sci_int_gpio_sus6"); + return ACPI_INTERRUPT_HANDLED; + } + + return ACPI_INTERRUPT_NOT_HANDLED; +} + +/* + * Setup GPIO SUS6 to generate an SCI interrupt for optics detection + * This can be alternatively be setup using sysfs + */ +int setup_gpio_sus6_sci_interrupt(struct device *dev) +{ + int ret=0; + unsigned int data; + struct resource *acpi_base, *pmc_base, *gpio_base; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + + gpio_base = ich_data->gpio_base; + acpi_base = ich_data->acpi_base; + pmc_base = ich_data->pmc_base; + + // Enable GPIOSUS6_EN + data = IO_REG_READ(GPIO_SUS_USE_SEL,gpio_base); + data |= GPIOSUS6_EN; + IO_REG_WRITE(data,GPIO_SUS_USE_SEL,gpio_base); + + // GPIOSUS6_EN is input + data = IO_REG_READ(GPIO_SUS_IO_SEL,gpio_base); + data |= GPIOSUS6_EN; + IO_REG_WRITE(data,GPIO_SUS_IO_SEL,gpio_base); + + // Trigger on positive edge for GPIOSUS6_EN + data = IO_REG_READ(GPIO_SUS_TPE,gpio_base); + data |= GPIOSUS6_EN; + IO_REG_WRITE(data,GPIO_SUS_TPE,gpio_base); + + // Enable GPE for SUS6 to generate an SCI + data=IO_REG_READ(ACPI_GPE0a_EN,acpi_base); + data|=GPIO_GPE0a_EN_SUS6; + IO_REG_WRITE(data,ACPI_GPE0a_EN,acpi_base); + + data=readl(pmc_base); + data=(data & ~(0x3 << GPIO_ROUT_OFFSET_SUS6)) | (GPIO_SCI << GPIO_ROUT_OFFSET_SUS6); + writel(data,pmc_base); + + ret = acpi_install_sci_handler(dell_ich_sci_handler,(void*)dev); + if(ret) { + pr_info("dell_ich acpi_install_sci_handler failed %d\n",ret); + return ret; + } + + return ret; +} + +static int dell_ich_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + struct pci_dev *lpc_ich_dev; + struct lpc_ich_priv *priv; + struct resource *res; + unsigned int base_addr_cfg, base_addr; + int ret,i; + + // Get the PCU device + lpc_ich_dev=pci_get_device(PCI_VENDOR_ID_INTEL,AVOTON_PCU_DEVICE_ID,NULL); + priv=(struct lpc_ich_priv*) pci_get_drvdata(lpc_ich_dev); + if(!priv) { + pr_info("dell_ich: Unable to retrieve private data\n"); + return -ENODEV; + } + + // Retrieve the GPIO Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->gbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + pr_info("dell_ich I/O space for GPIO uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &gpio_ich_res[ICH_RES_GPIO]; + res->start = base_addr; + res->end = res->start + 0x9c - 1; + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("dell_ich gpio resource conflict ret %d\n",ret); + } + + ich_data->gpio_base=res; + // Request regions for GPIO registers + for(i=0; istart+avoton_gpio_regs[i],GPIO_REG_LEN, "dell_ich_gpio")) { + pr_info("dell_ich: request_region failed for GPIO : %x\n",(unsigned int) res->start+avoton_gpio_regs[i]); + ret = -EBUSY; + goto probe_err; + } + ich_data->gpio_alloc |= (1<kobj, &gpio_attrs_group); + if (ret) { + pr_info("dell_ich cannot create sysfs for GPIO %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + // Retrieve the ACPI Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->abase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + pr_info("dell_ich I/O space for ACPI uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &gpio_ich_res[ICH_RES_GPE0]; + res->start = base_addr; + res->end = base_addr + 0x40; + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("dell_ich acpi resource conflict ret %d\n",ret); + } + + // ACPI region is requested by pnp 00:01/ACPI GPE0_BLK + ich_data->acpi_base=res; + + /* Register sysfs hooks for ACPI */ + ret = sysfs_create_group(&dev->kobj, &acpi_attrs_group); + if (ret) { + pr_info("dell_ich cannot create sysfs for ACPI %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + // Retrieve the PMC Base (that was initialized by lpc-ich) + pci_read_config_dword(lpc_ich_dev, priv->actrl_pbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0xfffffe00; + pr_info("dell_ich base_addr_cfg %x base_addr %x\n",(int)base_addr_cfg,(int)base_addr); + if (!base_addr) { + pr_info("dell_ich PMC space for GPIO uninitialized\n"); + ret = -ENODEV; + goto probe_err; + } + + res = &pmc_res; + res->start = base_addr + PMC_GPIO_ROUT; + res->end = base_addr + PMC_GPIO_ROUT + PMC_REG_LEN - 1; + pr_info("dell_ich pmc res_start:end %x:%x\n",(int)res->start,(int)res->end); + + ret = acpi_check_resource_conflict(res); + if (ret) { + pr_info("dell_ich acpi resource conflict ret %d\n",ret); + } + + if (!request_mem_region(res->start,resource_size(res),"dell_ich_pmc")) { + pr_info("dell_ich pmc request_region failed\n"); + ret = -EBUSY; + goto probe_err; + } else { + ich_data->pmc_alloc=1; + } + + ich_data->pmc_base = ioremap(res->start, resource_size(res)); + if(!ich_data->pmc_base) { + pr_info("dell_ich pmc ioremap failed\n"); + ret = -ENOMEM; + goto probe_err; + } + + /* Register sysfs hooks for pmc */ + ret = sysfs_create_group(&dev->kobj, &pmc_attrs_group); + if (ret) { + pr_info("dell_ich cannot create sysfs for PMC %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + /* Register sysfs hooks for SCI interrupts*/ + ret = sysfs_create_group(&dev->kobj, &sci_attrs_group); + if (ret) { + pr_info("dell_ich cannot create sysfs for SCI %d\n",ret); + ret = -ENOMEM; + goto probe_err; + } + + if((ich_data->kind == z9100smf) || (ich_data->kind == s6100smf)) { + ret = setup_gpio_sus6_sci_interrupt(dev); + if (ret) { + pr_info("dell_ich unable to setup SCI interrupt %d\n",ret); + goto probe_err; + } + } + + return 0; + +probe_err: + pr_info("dell_ich dell_ich_probe failed with : %d\n",ret); + return ret; +} + +static int dell_ich_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct dell_ich_data *ich_data = dev_get_platdata(dev); + int i,ret; + + // Release GPIO regions + for(i=0; igpio_alloc & (1<gpio_base->start+avoton_gpio_regs[i], GPIO_REG_LEN); + } + } + + // Unmap and release PMC regions + if(ich_data->pmc_base) iounmap(ich_data->pmc_base); + if(ich_data->pmc_alloc) release_mem_region(pmc_res.start, PMC_REG_LEN); + + ret = acpi_remove_sci_handler(dell_ich_sci_handler); + if(ret) { + pr_info("dell_ich acpi_remove_sci_handler failed %d\n",ret); + return ret; + } + + pr_info("dell_ich : dell_ich_remove done.\n"); + + return 0; +} + +static struct platform_driver dell_ich_driver= { + .driver = { + .name = DRV_NAME, + }, + .probe = dell_ich_probe, + .remove = dell_ich_remove, +}; + +int __init +init_ich_data(int smf_address, struct dell_ich_data *ich_data) +{ + int val; + + memset(ich_data, 0, sizeof(struct dell_ich_data)); + + if (force_id) + val = force_id; + else + val = inb(smf_address + SIO_REG_DEVID); + + switch (val) { + case SIO_Z9100_ID: + ich_data->kind = z9100smf; + break; + case SIO_S6100_ID: + ich_data->kind = s6100smf; + break; + default: + if (val != 0xffff) + pr_debug("unsupported chip ID: 0x%04x\n", val); + return -ENODEV; + } + + pr_info("dell_ich: found SMF for ID %#x\n", ich_data->kind); + + return (0); +} + +static struct platform_device *pdev; + +static int __init dell_ich_init(void) +{ + int err; + struct dell_ich_data ich_data; + + if (init_ich_data(SMF_REG_ADDR, &ich_data)) + return -ENODEV; + + err = platform_driver_register(&dell_ich_driver); + if (err) + goto exit; + + pdev = platform_device_alloc(DRV_NAME, 0); + if (!pdev) { + err = -ENOMEM; + pr_err("dell_ich: Device allocation failed\n"); + goto exit_unregister; + } + + err = platform_device_add_data(pdev, &ich_data, + sizeof(struct dell_ich_data)); + if (err) { + pr_err("dell_ich: Platform data allocation failed\n"); + goto exit_device_put; + } + + /* platform_device_add calls probe() */ + err = platform_device_add(pdev); + if (err) { + pr_err("dell_ich: Device addition failed (%d)\n", err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit_unregister: + platform_driver_unregister(&dell_ich_driver); +exit: + pr_err("dell_ich: dell_ich_init failed (%d)\n", err); + return err; +} + +static void __exit dell_ich_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&dell_ich_driver); + + /*Remove sysfs dell_kobj*/ + kobject_put(dell_kobj); +} + +MODULE_AUTHOR("Padmanabhan Narayanan"); +MODULE_DESCRIPTION("ICH driver for Dell Avoton/Rangeley switches"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + +MODULE_SOFTDEP("pre: lpc_ich"); +module_init(dell_ich_init); +module_exit(dell_ich_exit); diff --git a/platform/broadcom/sonic-platform-modules-dell/common/dell_lpc_mon.sh b/platform/broadcom/sonic-platform-modules-dell/common/dell_lpc_mon.sh new file mode 100755 index 000000000000..0f8d24a7f515 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/dell_lpc_mon.sh @@ -0,0 +1,46 @@ +#!/bin/bash +REV=$(lspci -xxx -s 0:0.0 | grep rev | awk -F 'rev ' '{print $2}' | sed 's/)//') +if [ $REV -gt 2 ] +then + exit 0 +fi + +test_val=(55 aa) +num_val=${#test_val[@]} +index=0 +poll_interval=300 +cpld_scratch_reg=0x102 +smf_scratch_reg=0x202 + +function log_crit() { + local msg=$1 + + `logger -p user.crit -t DELL_LPC_BUS_MON $msg` +} + +function validate_lpc() { + local reg=$1 + local val=$2 + local reg_str="CPLD scratch register" + + if [ $reg == $smf_scratch_reg ] + then + reg_str="SMF scratch register" + fi + io_rd_wr.py --set --val $val --offset $reg + get_val=$(io_rd_wr.py --get --offset $reg | cut -d " " -f3) + if [ $val != $get_val ] + then + log_crit "LPC bus has deteriorated on this unit. \ + $reg_str has value $get_val while expected is $val \ + Please contact technical support" + fi +} +while true +do + val=${test_val[$index]} + validate_lpc $cpld_scratch_reg $val + validate_lpc $smf_scratch_reg $val + index=$(((index+1)%num_val)) + sleep $poll_interval +done diff --git a/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c b/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c new file mode 100644 index 000000000000..5712c0fbb552 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c @@ -0,0 +1,2384 @@ +/* Copyright (c) 2017 Dell Inc.* + * dell_s6100_smf.c - driver for Dell SMF + * + * Author: Per Fremrot + * Author: Paavaanan + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIO_DRVNAME "SMF" +#define DEBUG 1 +#define LABELS 1 +#define SMF_VERSION_ADDR 0x0000 + +#define FANIN_MAX 12 /* Counted from 1 */ +#define VSEN_MAX 48 /* VSEN1.. */ +#define CURR_MAX 6 +#define TCPU_MAX 15 +#define PSU_MAX 4 /* TODO change to actual sensors */ + +/* Where are the sensors address/data + registers relative to the region offset */ + +#define IOREGION_OFFSET 0x10 +#define IOREGION_LENGTH 0x4 +#define SMF_ADDR_REG_OFFSET 0 +#define SMF_READ_DATA_REG_OFFSET 2 +#define SMF_WRITE_DATA_REG_OFFSET 3 +#define SMF_REG_ADDR 0x200 +#define SMF_POR_SRC_REG 0x209 +#define SMF_RST_SRC_REG 0x20A +#define SMF_PROBE_ADDR 0x210 + +#define SIO_REG_DEVID 0x1 +#define SIO_Z9100_ID 0x1 +#define SIO_S6100_ID 0x2 +#define SIO_S4200_ID 0x3 +#define SIO_S5148_ID 0x4 + +/* IOM presence */ +#define IO_MODULE_STATUS 0x0310 +#define IO_MODULE_PRESENCE 0x0311 + +/* FAN Tray */ +#define S6100_MAX_NUM_FAN_TRAYS 4 +#define Z9100_MAX_NUM_FAN_TRAYS 5 + +#define MAX_NUM_FAN_TRAYS 0x00F0 +#define MAX_NUM_FANS_PER_TRAY 0x00F1 +#define FAN_TRAY_PRESENCE 0x0113 +#define FAN_STATUS_GROUP_A 0x0114 +#define FAN_STATUS_GROUP_B 0x0115 +#define FAN_TRAY_AIRFLOW 0x0116 + + +/* FAN */ +#define SMF_FAN_SPEED_ADDR 0x00F3 +#define FAN_TRAY_1_SPEED 0x00F3 +#define FAN_TRAY_1_FAN_2_SPEED 0x00F5 +#define FAN_TRAY_2_SPEED 0x00F7 +#define FAN_TRAY_2_FAN_2_SPEED 0x00F9 +#define FAN_TRAY_3_SPEED 0x00FB +#define FAN_TRAY_3_FAN_2_SPEED 0x00FD +#define FAN_TRAY_4_SPEED 0x00FF +#define FAN_TRAY_4_FAN_2_SPEED 0x0101 +#define FAN_TRAY_5_FAN_1_SPEED 0x0103 +#define FAN_TRAY_5_FAN_2_SPEED 0x0105 +#define FAN_TRAY_5 4 +#define FAN_1_SERIAL_CODE 0x0117 +#define FAN_2_SERIAL_CODE 0x013A +#define FAN_3_SERIAL_CODE 0x015D +#define FAN_4_SERIAL_CODE 0x0180 +#define FAN_5_SERIAL_CODE 0x01A3 +#define FAN_601_FAULT (2 + 1) +#define IN28_INPUT (27 + 1) +#define IN404_INPUT (43 + 1) +#define IOM_PRESENCE (44 + 1) +#define IOM_PRESENCE_MAX (45 + 1) +#define IN602_INPUT (1 + 1) +#define CURR22_INPUT (1 + 1) +#define CURR602_INPUT (3 + 1) +#define TEMP13_INPUT (12 + 1) +#define TEMP601_INPUT (13 + 1) + +/* PSUs */ +#define S6100_MAX_NUM_PSUS 2 +#define MAX_NUM_PSUS 0x0231 +#define CURRENT_TOTAL_POWER 0x0232 + +/* PSU1 */ +#define PSU_1_MAX_POWER 0x0234 +#define PSU_1_FUNCTION_SUPPORT 0x0236 +#define PSU_1_STATUS 0x0237 +#define PSU_1_TEMPERATURE 0x0239 +#define PSU_1_FAN_SPEED 0x023B +#define PSU_1_FAN_STATUS 0x023D +#define PSU_1_INPUT_VOLTAGE 0x023E +#define PSU_1_OUTPUT_VOLTAGE 0x0240 +#define PSU_1_INPUT_CURRENT 0x0242 +#define PSU_1_OUTPUT_CURRENT 0x0244 +#define PSU_1_INPUT_POWER 0x0246 +#define PSU_1_OUTPUT_POWER 0x0248 +#define PSU_1_COUNTRY_CODE 0x024A + +/* PSU2 */ +#define PSU_2_MAX_POWER 0x026D +#define PSU_2_FUNCTION_SUPPORT 0x026F +#define PSU_2_STATUS 0x0270 +#define PSU_2_TEMPERATURE 0x0272 +#define PSU_2_FAN_SPEED 0x0274 +#define PSU_2_FAN_STATUS 0x0276 +#define PSU_2_INPUT_VOLTAGE 0x0277 +#define PSU_2_OUTPUT_VOLTAGE 0x0279 +#define PSU_2_INPUT_CURRENT 0x027B +#define PSU_2_OUTPUT_CURRENT 0x027D +#define PSU_2_INPUT_POWER 0x027F +#define PSU_2_OUTPUT_POWER 0x0281 +#define PSU_2_COUNTRY_CODE 0x0283 + +/* TEMP */ +#define TEMP_SENSOR_1 0x0014 +#define TEMP_SENSOR_1_STATUS 0x00DC +#define TEMP_SENSOR_1_HW_LIMIT 0x003E + +/* VOLTAGE */ +#define CPU_1_VOLTAGE 0x02A8 +#define IO_MODULE_1_VOLTAGE 0x02E8 +#define SWITCH_CURRENT_S6100 0x02E4 +#define SWITCH_CURRENT_Z9100 0x02E2 + +/* VOLTAGE S6100 */ +#define CPU_1_MONITOR_STATUS 0x0308 +#define CPU_2_MONITOR_STATUS 0x0309 +#define CPU_3_MONITOR_STATUS 0x030A +#define CPU_4_MONITOR_STATUS 0x030B + +/* VOLTAGE Z9100 */ +#define CPU_5_MONITOR_STATUS 0x02E6 +#define CPU_6_MONITOR_STATUS 0x02E7 +#define CPU_7_MONITOR_STATUS 0x02E8 +#define CPU_8_MONITOR_STATUS 0x02E9 + +/* EEPROM PPID */ +/* FAN and PSU EEPROM PPID format is: + COUNTRY_CODE-PART_NO-MFG_ID-MFG_DATE_CODE-SERIAL_NO-LABEL_REV */ +#define EEPROM_COUNTRY_CODE_SIZE 2 +#define EEPROM_PART_NO_SIZE 6 +#define EEPROM_MFG_ID_SIZE 5 +#define EEPROM_MFG_DATE_SIZE 8 +#define EEPROM_DATE_CODE_SIZE 3 +#define EEPROM_SERIAL_NO_SIZE 4 +#define EEPROM_SERVICE_TAG_SIZE 7 +#define EEPROM_LABEL_REV_SIZE 3 +#define EEPROM_PPID_SIZE 28 + +/* Mailbox PowerOn Reason */ +#define TRACK_POWERON_REASON 0x05FF + +/* System Status LED */ +#define SYSTEM_STATUS_LED 0x04DF + +/* CPU Set IO Modules */ +#define CPU_IOM1_CTRL_FLAG 0x04D9 +#define CPU_IOM2_CTRL_FLAG 0x04DA +#define CPU_IOM3_CTRL_FLAG 0x04DB +#define CPU_IOM4_CTRL_FLAG 0x04DC + + +unsigned long *mmio; +static struct kobject *dell_kobj; +static unsigned short force_id; +module_param(force_id, ushort, 0); +int smf_ver; + + +enum kinds { + z9100smf, s6100smf +}; + + +struct smf_devices { + const char *name; + u64 tcpu_mask; + u64 vsen_mask; + u32 curr_mask; + u64 fanin_mask; + u64 psu_mask; + const char *const *temp_label; + const char *const *vsen_label; + const char *const *curr_label; + const char *const *fan_label; + const char *const *psu_label; +}; + + +static const char *const z9100_temp_label[] = { + "CPU On-board (U2900)", + "BCM Switch On-Board #1 (U44)", + "Front BCM On-Board (U4)", + "Front BCM On-Board (U2)", + "Unused", + "BCM Switch On-Board #1 (U38)", + "Unused", + "Unused", + "Rear (U2900)", + "", + "", + "", + "", + "", + "PSU 1", + "PSU 2" +}; + + +static const char *const s6100_temp_label[] = { + "CPU On-board (U2900)", + "BCM On-Board #1 (U44)", + "Front BCM On-board (U4)", + "Front BCM On-board (U2)", + "IOM #1", + "IOM #2", + "IOM #3", + "IOM #4", + "U2 Switch board?", + "Front GE", + "Front SFP+", + "BCM Internal", + "CPU Internal", + "", + "PSU 1", + "PSU 2" +}; + + +static const char *const z9100_vsen_label[] = { + /* CPU Board */ + "CPU XP3R3V_EARLY", + "CPU XP5R0V_CP", + "CPU XP3R3V_STD", + "CPU XP3R3V_CP ", + "CPU XP0R75V_VTT_A", + "CPU XP0R75V_VTT_B", + "CPU XP1R07V_CPU", + "CPU XP1R0V_CPU", + "CPU XP12R0V", + "CPU VDDR_CPU_2", + "CPU VDDR_CPU_1", + "CPU XP1R5V_CLK", + "CPU XP1R35V_CPU", + "CPU XP1R8V_CPU", + "CPU XP1R0V_CPU_VNN", + "CPU XP1R0V_CPU_VCC", + "CPU XP1R5V_EARLY", + /* Switch Board */ + "SW XP12R0V_MON", + "SW XP3R3V_MON", + "SW XP1R8V_MON", + "SW XP1R25V_MON", + "SW XP1R2V_MON", + "SW XP1R0V_SW_MON", + "SW XP1R0V_ROV_SW_MON", + "SW XP5V_MB_MON", + "SW XP1R8V_FPGA_MON", + "SW XP3R3V_FPGA_MON", + "SW XP3R3V_EARLY_MON", + /* PSU */ + "PSU1 VIN", + "PSU1 VOUT", + "PSU2 VIN", + "PSU2 VOUT", + /* IOM 1 */ + "", + "", + "", + "", + /* IOM 2 */ + "", + "", + "", + "", + /* IOM 3 */ + "", + "", + "", + "", + /* IOM 4 */ + "", + "", + "", + "" +}; + + +static const char *const s6100_vsen_label[] = { + /* CPU Board */ + "CPU XP3R3V_EARLY", + "CPU XP5R0V_CP", + "CPU XP3R3V_STD", + "CPU XP3R3V_CP ", + "CPU XP0R75V_VTT_A", + "CPU XP0R75V_VTT_B", + "CPU XP1R07V_CPU", + "CPU XP1R0V_CPU", + "CPU XP12R0V", + "CPU VDDR_CPU_2", + "CPU VDDR_CPU_1", + "CPU XP1R5V_CLK", + "CPU XP1R35V_CPU", + "CPU XP1R8V_CPU", + "CPU XP1R0V_CPU_VNN", + "CPU XP1R0V_CPU_VCC", + "CPU XP1R5V_EARLY", + /* Switch Board */ + "SW XP12R0V_MON", + "SW XP3R3V_MON", + "SW XP1R8V_MON", + "SW XP1R25V_MON", + "SW XP1R2V_MON", + "SW XP1R0V_SW_MON", + "SW XP1R0V_ROV_SW_MON", + "XR1R0V_BCM84752_MON", + "SW XP5V_MB_MON", + "SW XP1R8V_FPGA_MON", + "SW XP3R3V_FPGA_MON", + + /* PSU */ + "PSU1 VIN", + "PSU1 VOUT", + "PSU2 VIN", + "PSU2 VOUT", + + /* IOM 1 */ + "IOM 1 #1", + "IOM 1 #2", + "IOM 1 #3", + "IOM 1 #4", + /* IOM 2 */ + "IOM 2 #1", + "IOM 2 #2", + "IOM 2 #3", + "IOM 2 #4", + /* IOM 1 */ + "IOM 3 #1", + "IOM 3 #2", + "IOM 3 #3", + "IOM 3 #4", + /* IOM 1 */ + "IOM 4 #1", + "IOM 4 #2", + "IOM 4 #3", + "IOM 4 #4" +}; + + +static const char *const z9100_curr_label[] = { + "XP1R0V", + "XP1R0V_ROV" +}; + + +static const char *const s6100_fan_label[] = { + "Tray1 Fan1", + "", + "Tray2 Fan1", + "", + "Tray3 Fan1", + "", + "Tray4 Fan1", + "", + "", + "", + "Psu1 Fan", + "Psu2 Fan" +}; + +static const char *const z9100_fan_label[] = { + "Tray1 Fan1", + "Tray1 Fan2", + "Tray2 Fan1", + "Tray2 Fan2", + "Tray3 Fan1", + "Tray3 Fan2", + "Tray4 Fan1", + "Tray4 Fan2", + "Tray5 Fan1", + "Tray5 Fan2", + "Psu1 Fan", + "Psu2 Fan" +}; + + +static const char *const s6100_psu_label[] = { + "Psu1 Input", + "Psu1 Output", + "Psu2 Input", + "Psu2 Output", +}; + +static const struct smf_devices smf_devices[] = { + [z9100smf] = { + .name = "SMF_Z9100_ON", + .tcpu_mask=0xe1ff, + .vsen_mask=0xfffdffff, + .curr_mask=0x3f, + .fanin_mask=0xfff, + .psu_mask=0xf, + .temp_label = z9100_temp_label, + .vsen_label = z9100_vsen_label, + .curr_label = z9100_curr_label, + .fan_label = z9100_fan_label, + .psu_label = s6100_psu_label + }, + [s6100smf] = { + .name = "SMF_S6100_ON", + .tcpu_mask=0x7fff, + .vsen_mask=0xfffffefdffff, + .curr_mask=0x3f, + .fanin_mask=0xc55, + .psu_mask=0xf, + .temp_label = s6100_temp_label, + .vsen_label = s6100_vsen_label, + .curr_label = z9100_curr_label, + .fan_label = s6100_fan_label, + .psu_label = s6100_psu_label + + } +}; + + +/* + * For each registered chip, we need to keep some data in memory. + * The structure is dynamically allocated. + */ +struct smf_data { + enum kinds kind; /* Inherited from SuperIO kind */ + unsigned short addr; + struct device *hwmon_dev; + struct mutex lock; + u64 tcpu_mask; + u64 vsen_mask; + u32 curr_mask; + u64 fanin_mask; + u64 psu_mask; + const char * const *temp_label; + const char * const *vsen_label; + const char * const *curr_label; + const char * const *fan_label; + const char * const *psu_label; +}; + + +struct smf_sio_data { + int sioreg; + enum kinds kind; +}; + +static int smf_write_reg(struct smf_data *data, u16 reg, u16 dev_data) +{ + int res = 0; + + mutex_lock(&data->lock); + outb_p(reg>> 8, data->addr + SMF_ADDR_REG_OFFSET); + outb_p(reg & 0xff, data->addr + SMF_ADDR_REG_OFFSET + 1); + outb_p(dev_data & 0xff, data->addr + SMF_WRITE_DATA_REG_OFFSET); + mutex_unlock(&data->lock); + + return res; +} + +static int smf_read_reg(struct smf_data *data, u16 reg) +{ + int res; + + mutex_lock(&data->lock); + outb_p(reg>> 8, data->addr + SMF_ADDR_REG_OFFSET); + outb_p(reg & 0xff, data->addr + SMF_ADDR_REG_OFFSET + 1); + res = inb_p(data->addr + SMF_READ_DATA_REG_OFFSET); + mutex_unlock(&data->lock); + return res; +} + + +static int smf_read_reg16(struct smf_data *data, u16 reg) +{ + int res; + + mutex_lock(&data->lock); + outb_p(reg>> 8, data->addr + SMF_ADDR_REG_OFFSET); + outb_p(reg & 0xff, data->addr + SMF_ADDR_REG_OFFSET + 1); + + res = inb_p(data->addr + SMF_READ_DATA_REG_OFFSET); + + outb_p((reg + 1)>> 8, data->addr + SMF_ADDR_REG_OFFSET); + outb_p((reg + 1) & 0xff, data->addr + SMF_ADDR_REG_OFFSET + 1); + + res = (res << 8) + inb_p(data->addr + SMF_READ_DATA_REG_OFFSET); + + mutex_unlock(&data->lock); + return res; +} + +/* SMF Version */ +static ssize_t show_smf_version(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + unsigned int ret = 0; + unsigned int smf_version = 0; + unsigned int smf_firmware_major_ver = 0; + unsigned int smf_firmware_minor_ver = 0; + struct smf_data *data = dev_get_drvdata(dev); + + ret = smf_read_reg(data, (SMF_VERSION_ADDR + index*2)); + + printk("smf_firmware_details-->0x%x index[%d]", ret, index); + + if (index > 0) { + smf_firmware_major_ver = ((ret & (0xC0)) >> 6); + smf_firmware_minor_ver = (ret & (0x3F)); + + ret = sprintf(buf, "%u.%u\n", smf_firmware_major_ver, + smf_firmware_minor_ver); + } else { + smf_version = ret; + ret = sprintf(buf, "%u\n", smf_version); + } + + return ret; +} + + +/* SMF Reset Reason */ +static ssize_t show_reset_reason(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + unsigned int ret = 0; + + ret = inb(SMF_RST_SRC_REG); + + if(ret < 0) + return ret; + + return sprintf(buf, "%x\n", ret); +} + +/* SMF Power ON Reason */ +static ssize_t show_power_on_reason(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + unsigned int ret = 0; + + ret = inb(SMF_POR_SRC_REG); + + if(ret < 0) + return ret; + + return sprintf(buf, "%x\n", ret); +} + +/* SMF Mailbox Power ON Reason */ +static ssize_t set_mb_poweron_reason(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + int err = 0; + unsigned int dev_data = 0; + struct smf_data *data = dev_get_drvdata(dev); + + err = kstrtouint(buf, 16, &dev_data); + if (err) + return err; + + err = smf_write_reg(data, TRACK_POWERON_REASON, dev_data); + + if(err < 0) + return err; + + return count; +} + +static ssize_t show_mb_poweron_reason(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + unsigned int ret = 0; + struct smf_data *data = dev_get_drvdata(dev); + + ret = smf_read_reg(data, TRACK_POWERON_REASON); + + if(ret < 0) + return ret; + + return sprintf(buf, "0x%x\n", ret); +} + +/* System Status LED */ +static ssize_t set_sys_status_led(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + int err = 0; + unsigned int dev_data = 0; + struct smf_data *data = dev_get_drvdata(dev); + + if (data->kind == z9100smf) + return -1; + + err = kstrtouint(buf, 16, &dev_data); + if (err) + return err; + + err = smf_write_reg(data, SYSTEM_STATUS_LED, dev_data); + if(err < 0) + return err; + + return count; +} + +static ssize_t show_sys_status_led(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + unsigned int ret = 0; + struct smf_data *data = dev_get_drvdata(dev); + + if (data->kind == z9100smf) + return 0; + + ret = smf_read_reg(data, SYSTEM_STATUS_LED); + if(ret < 0) + return ret; + + return sprintf(buf, "0x%x\n", ret); +} + +/* FANIN ATTR */ +static ssize_t +show_fan_label(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct smf_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%s\n", data->fan_label[nr]); +} + + +static ssize_t show_fan(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int export_hex=0; + unsigned int ret = -1; + unsigned rpm; + + + if (index <10) + ret = smf_read_reg16(data, SMF_FAN_SPEED_ADDR + index * 2); + else switch (index) { + case 10: + ret = smf_read_reg16(data, PSU_1_FAN_SPEED); + break; + case 11: + ret = smf_read_reg16(data, PSU_2_FAN_SPEED); + break; + case 12: + ret = (~smf_read_reg(data, FAN_TRAY_PRESENCE) & 0xff); + export_hex = 1; + break; + + default: + return ret; + } + + + if (ret < 0) + return ret; + + if (ret & 0x8000) + ret = - (ret & 0x7fff); + + rpm = ret; + + if(export_hex) + return sprintf(buf, "%x\n", rpm); + else + return sprintf(buf, "%u\n", rpm); +} + + +static ssize_t show_fan_fault(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret=1, fan_status; + + index = index / 2; + fan_status = ~smf_read_reg(data, FAN_TRAY_PRESENCE); + + if (fan_status & (1 << (index))) + ret=0; + + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret); +} + + +static ssize_t show_fan_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret, psu_fan_status=0; + + 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; + else + ret=1; + + return sprintf(buf, "%d\n", ret); +} + + +static ssize_t show_fan_airflow(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret, fan_airflow; + + if (data->kind == s6100smf && index == FAN_TRAY_5) + return 0; + + fan_airflow = smf_read_reg(data, FAN_TRAY_AIRFLOW); + ret = (fan_airflow >> index) & 1; + + return sprintf(buf, "%d\n", ret); +} + + +static ssize_t show_psu_fan(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret=0, fan_status; + + if (index < FAN_601_FAULT){ + fan_status = smf_read_reg(data, PSU_1_FAN_STATUS); + ret = (fan_status >> index) & 1; + + } + else{ + fan_status = smf_read_reg(data, PSU_2_FAN_STATUS); + ret = (fan_status >> (index - 3)) & 1; + } + + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret); +} + +static ssize_t show_cpu_iom_control(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int cpu_iom_status; + + if(index == 0) + cpu_iom_status = smf_read_reg(data, CPU_IOM1_CTRL_FLAG); + else if (index == 1) + cpu_iom_status = smf_read_reg(data, CPU_IOM2_CTRL_FLAG); + else if (index == 2) + cpu_iom_status = smf_read_reg(data, CPU_IOM3_CTRL_FLAG); + else if (index == 3) + cpu_iom_status = smf_read_reg(data, CPU_IOM4_CTRL_FLAG); + + return sprintf(buf, "%x\n", cpu_iom_status); +} + + + +static umode_t smf_fanin_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct smf_data *data = dev_get_drvdata(dev); + + if (data->fanin_mask & (1 << (n % FANIN_MAX))) + return a->mode; + + return 0; +} + +static umode_t smf_dell_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + return a->mode; + +} + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); +static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO, show_fan, NULL, 8); +static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, show_fan, NULL,9); +/* PSU1 FAN */ +static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, show_fan, NULL, 10); +/* PSU2 FAN */ +static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, show_fan, NULL, 11); + +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(fan9_alarm, S_IRUGO, show_fan_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(fan10_alarm, S_IRUGO, show_fan_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(fan11_alarm, S_IRUGO, show_psu_fan, NULL, 1); +static SENSOR_DEVICE_ATTR(fan12_alarm, S_IRUGO, show_psu_fan, NULL, 4); + +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7); +static SENSOR_DEVICE_ATTR(fan9_fault, S_IRUGO, show_fan_fault, NULL, 8); +static SENSOR_DEVICE_ATTR(fan10_fault, S_IRUGO, show_fan_fault, NULL, 9); +static SENSOR_DEVICE_ATTR(fan11_fault, S_IRUGO, show_psu_fan, NULL, 2); +static SENSOR_DEVICE_ATTR(fan12_fault, S_IRUGO, show_psu_fan, NULL, 5); + +static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, show_fan_label, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, show_fan_label, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_label, S_IRUGO, show_fan_label, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_label, S_IRUGO, show_fan_label, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_label, S_IRUGO, show_fan_label, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_label, S_IRUGO, show_fan_label, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_label, S_IRUGO, show_fan_label, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_label, S_IRUGO, show_fan_label, NULL, 7); +static SENSOR_DEVICE_ATTR(fan9_label, S_IRUGO, show_fan_label, NULL, 8); +static SENSOR_DEVICE_ATTR(fan10_label, S_IRUGO, show_fan_label, NULL, 9); +static SENSOR_DEVICE_ATTR(fan11_label, S_IRUGO, show_fan_label, NULL, 10); +static SENSOR_DEVICE_ATTR(fan12_label, S_IRUGO, show_fan_label, NULL, 11); + + +static struct attribute *smf_fanin_attrs[] = { + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, + &sensor_dev_attr_fan9_input.dev_attr.attr, + &sensor_dev_attr_fan10_input.dev_attr.attr, + &sensor_dev_attr_fan11_input.dev_attr.attr, + &sensor_dev_attr_fan12_input.dev_attr.attr, + + &sensor_dev_attr_fan1_label.dev_attr.attr, + &sensor_dev_attr_fan2_label.dev_attr.attr, + &sensor_dev_attr_fan3_label.dev_attr.attr, + &sensor_dev_attr_fan4_label.dev_attr.attr, + &sensor_dev_attr_fan5_label.dev_attr.attr, + &sensor_dev_attr_fan6_label.dev_attr.attr, + &sensor_dev_attr_fan7_label.dev_attr.attr, + &sensor_dev_attr_fan8_label.dev_attr.attr, + &sensor_dev_attr_fan9_label.dev_attr.attr, + &sensor_dev_attr_fan10_label.dev_attr.attr, + &sensor_dev_attr_fan11_label.dev_attr.attr, + &sensor_dev_attr_fan12_label.dev_attr.attr, + + + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, + &sensor_dev_attr_fan4_alarm.dev_attr.attr, + &sensor_dev_attr_fan5_alarm.dev_attr.attr, + &sensor_dev_attr_fan6_alarm.dev_attr.attr, + &sensor_dev_attr_fan7_alarm.dev_attr.attr, + &sensor_dev_attr_fan8_alarm.dev_attr.attr, + &sensor_dev_attr_fan9_alarm.dev_attr.attr, + &sensor_dev_attr_fan10_alarm.dev_attr.attr, + &sensor_dev_attr_fan11_alarm.dev_attr.attr, + &sensor_dev_attr_fan12_alarm.dev_attr.attr, + + &sensor_dev_attr_fan1_fault.dev_attr.attr, + &sensor_dev_attr_fan2_fault.dev_attr.attr, + &sensor_dev_attr_fan3_fault.dev_attr.attr, + &sensor_dev_attr_fan4_fault.dev_attr.attr, + &sensor_dev_attr_fan5_fault.dev_attr.attr, + &sensor_dev_attr_fan6_fault.dev_attr.attr, + &sensor_dev_attr_fan7_fault.dev_attr.attr, + &sensor_dev_attr_fan8_fault.dev_attr.attr, + &sensor_dev_attr_fan9_fault.dev_attr.attr, + &sensor_dev_attr_fan10_fault.dev_attr.attr, + &sensor_dev_attr_fan11_fault.dev_attr.attr, + &sensor_dev_attr_fan12_fault.dev_attr.attr, + + NULL +}; + + + + +/* VSEN ATTR */ +static ssize_t +show_voltage_label(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct smf_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%s\n", data->vsen_label[nr]); +} + + +static ssize_t show_voltage(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int volt, ret=0; + int export_hex=0; + + /*0 to 27 */ + if (index < IN28_INPUT) /* Voltage sensors */ + ret = smf_read_reg16(data, CPU_1_VOLTAGE + index * 2); + else if ((data->kind == s6100smf) && (index < IN404_INPUT)) + ret = smf_read_reg16(data, IO_MODULE_1_VOLTAGE + index * 2); + else if ((data->kind == s6100smf) && (index < IOM_PRESENCE)) + ret = smf_read_reg(data, IO_MODULE_STATUS); + else if ((data->kind == s6100smf) && (index < IOM_PRESENCE_MAX)) + ret = smf_read_reg(data, IO_MODULE_PRESENCE); + + if (ret < 0) + return ret; + + if(index < 44) + volt = ret*10; + else + export_hex=1; + + if(export_hex) + return sprintf(buf, "%x\n", ret); + else + return sprintf(buf, "%d\n", volt); +} + + +static ssize_t show_psu_voltage(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret; + + if (index < 2) /* PSU1 */ + ret = smf_read_reg16(data, PSU_1_INPUT_VOLTAGE + index * 2); + else /* PSU2 */ + ret = smf_read_reg16(data, PSU_2_INPUT_VOLTAGE + ((index - 2) * 2)); + + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret*10); +} + + +static ssize_t show_voltage_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + unsigned status=0; + int ret; + + if (index < 8) { + + if (data->kind == s6100smf) + status = smf_read_reg16(data, CPU_1_MONITOR_STATUS); + else + status = smf_read_reg16(data, CPU_5_MONITOR_STATUS); + + ret = status & (1 << index); + } + else if (index < 15) { + + if (data->kind == s6100smf) + ret = smf_read_reg16(data, CPU_2_MONITOR_STATUS); + else + ret = smf_read_reg16(data, CPU_6_MONITOR_STATUS); + + ret = status & (1 << index); + } + else if (index < 23) { + + if (data->kind == s6100smf) + ret = smf_read_reg16(data, CPU_3_MONITOR_STATUS); + else + ret = smf_read_reg16(data, CPU_7_MONITOR_STATUS); + + ret = status & (1 << index); + } + else { + + if (data->kind == s6100smf) + ret = smf_read_reg16(data, CPU_4_MONITOR_STATUS); + else + ret = smf_read_reg16(data, CPU_8_MONITOR_STATUS); + + ret = status & (1 << index); + } + + + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", ret); +} + + +static umode_t smf_vsen_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct smf_data *data = dev_get_drvdata(dev); + + if (data->vsen_mask & (1 << (n % VSEN_MAX))) + return a->mode; + return 0; +} + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2); +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3); +static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4); +static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5); +static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6); +static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7); +static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8); +static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9); +static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10); +static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11); +static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12); +static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, show_voltage, NULL, 13); +static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, show_voltage, NULL, 14); +static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_voltage, NULL, 15); +static SENSOR_DEVICE_ATTR(in17_input, S_IRUGO, show_voltage, NULL, 16); +static SENSOR_DEVICE_ATTR(in18_input, S_IRUGO, show_voltage, NULL, 17); +static SENSOR_DEVICE_ATTR(in19_input, S_IRUGO, show_voltage, NULL, 18); +static SENSOR_DEVICE_ATTR(in20_input, S_IRUGO, show_voltage, NULL, 19); +static SENSOR_DEVICE_ATTR(in21_input, S_IRUGO, show_voltage, NULL, 20); +static SENSOR_DEVICE_ATTR(in22_input, S_IRUGO, show_voltage, NULL, 21); +static SENSOR_DEVICE_ATTR(in23_input, S_IRUGO, show_voltage, NULL, 22); +static SENSOR_DEVICE_ATTR(in24_input, S_IRUGO, show_voltage, NULL, 23); +static SENSOR_DEVICE_ATTR(in25_input, S_IRUGO, show_voltage, NULL, 24); +static SENSOR_DEVICE_ATTR(in26_input, S_IRUGO, show_voltage, NULL, 25); +static SENSOR_DEVICE_ATTR(in27_input, S_IRUGO, show_voltage, NULL, 26); +static SENSOR_DEVICE_ATTR(in28_input, S_IRUGO, show_voltage, NULL, 27); + +/* PSU1 Voltage*/ +static SENSOR_DEVICE_ATTR(in29_input, S_IRUGO, show_psu_voltage, NULL, 0); +static SENSOR_DEVICE_ATTR(in30_input, S_IRUGO, show_psu_voltage, NULL, 1); + +/* PSU2 Voltage*/ +static SENSOR_DEVICE_ATTR(in31_input, S_IRUGO, show_psu_voltage, NULL, 2); +static SENSOR_DEVICE_ATTR(in32_input, S_IRUGO, show_psu_voltage, NULL, 3); + +/*IO Modules Voltage*/ +static SENSOR_DEVICE_ATTR(in101_input, S_IRUGO, show_voltage, NULL, 28); +static SENSOR_DEVICE_ATTR(in102_input, S_IRUGO, show_voltage, NULL, 29); +static SENSOR_DEVICE_ATTR(in103_input, S_IRUGO, show_voltage, NULL, 30); +static SENSOR_DEVICE_ATTR(in104_input, S_IRUGO, show_voltage, NULL, 31); +static SENSOR_DEVICE_ATTR(in201_input, S_IRUGO, show_voltage, NULL, 32); +static SENSOR_DEVICE_ATTR(in202_input, S_IRUGO, show_voltage, NULL, 33); +static SENSOR_DEVICE_ATTR(in203_input, S_IRUGO, show_voltage, NULL, 34); +static SENSOR_DEVICE_ATTR(in204_input, S_IRUGO, show_voltage, NULL, 35); +static SENSOR_DEVICE_ATTR(in301_input, S_IRUGO, show_voltage, NULL, 36); +static SENSOR_DEVICE_ATTR(in302_input, S_IRUGO, show_voltage, NULL, 37); +static SENSOR_DEVICE_ATTR(in303_input, S_IRUGO, show_voltage, NULL, 38); +static SENSOR_DEVICE_ATTR(in304_input, S_IRUGO, show_voltage, NULL, 39); +static SENSOR_DEVICE_ATTR(in401_input, S_IRUGO, show_voltage, NULL, 40); +static SENSOR_DEVICE_ATTR(in402_input, S_IRUGO, show_voltage, NULL, 41); +static SENSOR_DEVICE_ATTR(in403_input, S_IRUGO, show_voltage, NULL, 42); +static SENSOR_DEVICE_ATTR(in404_input, S_IRUGO, show_voltage, NULL, 43); + + + +static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_voltage_label, NULL, 0); +static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_voltage_label, NULL, 1); +static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_voltage_label, NULL, 2); +static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_voltage_label, NULL, 3); +static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_voltage_label, NULL, 4); +static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_voltage_label, NULL, 5); +static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_voltage_label, NULL, 6); +static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_voltage_label, NULL, 7); +static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_voltage_label, NULL, 8); +static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_voltage_label, NULL, 9); +static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_voltage_label, NULL, 10); +static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_voltage_label, NULL, 11); +static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, show_voltage_label, NULL, 12); +static SENSOR_DEVICE_ATTR(in14_label, S_IRUGO, show_voltage_label, NULL, 13); +static SENSOR_DEVICE_ATTR(in15_label, S_IRUGO, show_voltage_label, NULL, 14); +static SENSOR_DEVICE_ATTR(in16_label, S_IRUGO, show_voltage_label, NULL, 15); +static SENSOR_DEVICE_ATTR(in17_label, S_IRUGO, show_voltage_label, NULL, 16); +static SENSOR_DEVICE_ATTR(in18_label, S_IRUGO, show_voltage_label, NULL, 17); +static SENSOR_DEVICE_ATTR(in19_label, S_IRUGO, show_voltage_label, NULL, 18); +static SENSOR_DEVICE_ATTR(in20_label, S_IRUGO, show_voltage_label, NULL, 19); +static SENSOR_DEVICE_ATTR(in21_label, S_IRUGO, show_voltage_label, NULL, 20); +static SENSOR_DEVICE_ATTR(in22_label, S_IRUGO, show_voltage_label, NULL, 21); +static SENSOR_DEVICE_ATTR(in23_label, S_IRUGO, show_voltage_label, NULL, 22); +static SENSOR_DEVICE_ATTR(in24_label, S_IRUGO, show_voltage_label, NULL, 23); +static SENSOR_DEVICE_ATTR(in25_label, S_IRUGO, show_voltage_label, NULL, 24); +static SENSOR_DEVICE_ATTR(in26_label, S_IRUGO, show_voltage_label, NULL, 25); +static SENSOR_DEVICE_ATTR(in27_label, S_IRUGO, show_voltage_label, NULL, 26); +static SENSOR_DEVICE_ATTR(in28_label, S_IRUGO, show_voltage_label, NULL, 27); + +/* PSU1 Voltage Label*/ +static SENSOR_DEVICE_ATTR(in29_label, S_IRUGO, show_voltage_label, NULL, 28); +static SENSOR_DEVICE_ATTR(in30_label, S_IRUGO, show_voltage_label, NULL, 29); + +/* PSU2 Voltage Label*/ +static SENSOR_DEVICE_ATTR(in31_label, S_IRUGO, show_voltage_label, NULL, 30); +static SENSOR_DEVICE_ATTR(in32_label, S_IRUGO, show_voltage_label, NULL, 31); + +/*IO Modules Labels*/ +static SENSOR_DEVICE_ATTR(in101_label, S_IRUGO, show_voltage_label, NULL, 32); +static SENSOR_DEVICE_ATTR(in102_label, S_IRUGO, show_voltage_label, NULL, 33); +static SENSOR_DEVICE_ATTR(in103_label, S_IRUGO, show_voltage_label, NULL, 34); +static SENSOR_DEVICE_ATTR(in104_label, S_IRUGO, show_voltage_label, NULL, 35); +static SENSOR_DEVICE_ATTR(in201_label, S_IRUGO, show_voltage_label, NULL, 36); +static SENSOR_DEVICE_ATTR(in202_label, S_IRUGO, show_voltage_label, NULL, 37); +static SENSOR_DEVICE_ATTR(in203_label, S_IRUGO, show_voltage_label, NULL, 38); +static SENSOR_DEVICE_ATTR(in204_label, S_IRUGO, show_voltage_label, NULL, 39); +static SENSOR_DEVICE_ATTR(in301_label, S_IRUGO, show_voltage_label, NULL, 40); +static SENSOR_DEVICE_ATTR(in302_label, S_IRUGO, show_voltage_label, NULL, 41); +static SENSOR_DEVICE_ATTR(in303_label, S_IRUGO, show_voltage_label, NULL, 42); +static SENSOR_DEVICE_ATTR(in304_label, S_IRUGO, show_voltage_label, NULL, 43); +static SENSOR_DEVICE_ATTR(in401_label, S_IRUGO, show_voltage_label, NULL, 44); +static SENSOR_DEVICE_ATTR(in402_label, S_IRUGO, show_voltage_label, NULL, 45); +static SENSOR_DEVICE_ATTR(in403_label, S_IRUGO, show_voltage_label, NULL, 46); +static SENSOR_DEVICE_ATTR(in404_label, S_IRUGO, show_voltage_label, NULL, 47); + + + +/* CPU Voltage Alarm */ +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_voltage_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_voltage_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_voltage_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_voltage_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_voltage_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_voltage_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_voltage_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_voltage_alarm, NULL, 7); + +static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_voltage_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_voltage_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_voltage_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_voltage_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_voltage_alarm, NULL, 12); +static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_voltage_alarm, NULL, 13); +static SENSOR_DEVICE_ATTR(in15_alarm, S_IRUGO, show_voltage_alarm, NULL, 14); +static SENSOR_DEVICE_ATTR(in16_alarm, S_IRUGO, show_voltage_alarm, NULL, 15); + +static SENSOR_DEVICE_ATTR(in17_alarm, S_IRUGO, show_voltage_alarm, NULL, 16); +static SENSOR_DEVICE_ATTR(in18_alarm, S_IRUGO, show_voltage_alarm, NULL, 17); +static SENSOR_DEVICE_ATTR(in19_alarm, S_IRUGO, show_voltage_alarm, NULL, 18); +static SENSOR_DEVICE_ATTR(in20_alarm, S_IRUGO, show_voltage_alarm, NULL, 19); +static SENSOR_DEVICE_ATTR(in21_alarm, S_IRUGO, show_voltage_alarm, NULL, 20); +static SENSOR_DEVICE_ATTR(in22_alarm, S_IRUGO, show_voltage_alarm, NULL, 21); +static SENSOR_DEVICE_ATTR(in23_alarm, S_IRUGO, show_voltage_alarm, NULL, 22); +static SENSOR_DEVICE_ATTR(in24_alarm, S_IRUGO, show_voltage_alarm, NULL, 23); + +static SENSOR_DEVICE_ATTR(in25_alarm, S_IRUGO, show_voltage_alarm, NULL, 24); +static SENSOR_DEVICE_ATTR(in26_alarm, S_IRUGO, show_voltage_alarm, NULL, 25); +static SENSOR_DEVICE_ATTR(in27_alarm, S_IRUGO, show_voltage_alarm, NULL, 26); +static SENSOR_DEVICE_ATTR(in28_alarm, S_IRUGO, show_voltage_alarm, NULL, 27); + + + +static struct attribute *smf_vsen_attrs[] = { + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in6_input.dev_attr.attr, + &sensor_dev_attr_in7_input.dev_attr.attr, + &sensor_dev_attr_in8_input.dev_attr.attr, + &sensor_dev_attr_in9_input.dev_attr.attr, + &sensor_dev_attr_in10_input.dev_attr.attr, + &sensor_dev_attr_in11_input.dev_attr.attr, + &sensor_dev_attr_in12_input.dev_attr.attr, + &sensor_dev_attr_in13_input.dev_attr.attr, + &sensor_dev_attr_in14_input.dev_attr.attr, + &sensor_dev_attr_in15_input.dev_attr.attr, + &sensor_dev_attr_in16_input.dev_attr.attr, + &sensor_dev_attr_in17_input.dev_attr.attr, + &sensor_dev_attr_in18_input.dev_attr.attr, + &sensor_dev_attr_in19_input.dev_attr.attr, + &sensor_dev_attr_in20_input.dev_attr.attr, + &sensor_dev_attr_in21_input.dev_attr.attr, + &sensor_dev_attr_in22_input.dev_attr.attr, + &sensor_dev_attr_in23_input.dev_attr.attr, + &sensor_dev_attr_in24_input.dev_attr.attr, + &sensor_dev_attr_in25_input.dev_attr.attr, + &sensor_dev_attr_in26_input.dev_attr.attr, + &sensor_dev_attr_in27_input.dev_attr.attr, + &sensor_dev_attr_in28_input.dev_attr.attr, + + &sensor_dev_attr_in29_input.dev_attr.attr, + &sensor_dev_attr_in30_input.dev_attr.attr, + &sensor_dev_attr_in31_input.dev_attr.attr, + &sensor_dev_attr_in32_input.dev_attr.attr, + + &sensor_dev_attr_in101_input.dev_attr.attr, + &sensor_dev_attr_in102_input.dev_attr.attr, + &sensor_dev_attr_in103_input.dev_attr.attr, + &sensor_dev_attr_in104_input.dev_attr.attr, + &sensor_dev_attr_in201_input.dev_attr.attr, + &sensor_dev_attr_in202_input.dev_attr.attr, + &sensor_dev_attr_in203_input.dev_attr.attr, + &sensor_dev_attr_in204_input.dev_attr.attr, + &sensor_dev_attr_in301_input.dev_attr.attr, + &sensor_dev_attr_in302_input.dev_attr.attr, + &sensor_dev_attr_in303_input.dev_attr.attr, + &sensor_dev_attr_in304_input.dev_attr.attr, + &sensor_dev_attr_in401_input.dev_attr.attr, + &sensor_dev_attr_in402_input.dev_attr.attr, + &sensor_dev_attr_in403_input.dev_attr.attr, + &sensor_dev_attr_in404_input.dev_attr.attr, + + + &sensor_dev_attr_in1_label.dev_attr.attr, + &sensor_dev_attr_in2_label.dev_attr.attr, + &sensor_dev_attr_in3_label.dev_attr.attr, + &sensor_dev_attr_in4_label.dev_attr.attr, + &sensor_dev_attr_in5_label.dev_attr.attr, + &sensor_dev_attr_in6_label.dev_attr.attr, + &sensor_dev_attr_in7_label.dev_attr.attr, + &sensor_dev_attr_in8_label.dev_attr.attr, + &sensor_dev_attr_in9_label.dev_attr.attr, + &sensor_dev_attr_in10_label.dev_attr.attr, + &sensor_dev_attr_in11_label.dev_attr.attr, + &sensor_dev_attr_in12_label.dev_attr.attr, + &sensor_dev_attr_in13_label.dev_attr.attr, + &sensor_dev_attr_in14_label.dev_attr.attr, + &sensor_dev_attr_in15_label.dev_attr.attr, + &sensor_dev_attr_in16_label.dev_attr.attr, + &sensor_dev_attr_in17_label.dev_attr.attr, + &sensor_dev_attr_in18_label.dev_attr.attr, + &sensor_dev_attr_in19_label.dev_attr.attr, + &sensor_dev_attr_in20_label.dev_attr.attr, + &sensor_dev_attr_in21_label.dev_attr.attr, + &sensor_dev_attr_in22_label.dev_attr.attr, + &sensor_dev_attr_in23_label.dev_attr.attr, + &sensor_dev_attr_in24_label.dev_attr.attr, + &sensor_dev_attr_in25_label.dev_attr.attr, + &sensor_dev_attr_in26_label.dev_attr.attr, + &sensor_dev_attr_in27_label.dev_attr.attr, + &sensor_dev_attr_in28_label.dev_attr.attr, + + &sensor_dev_attr_in29_label.dev_attr.attr, + &sensor_dev_attr_in30_label.dev_attr.attr, + &sensor_dev_attr_in31_label.dev_attr.attr, + &sensor_dev_attr_in32_label.dev_attr.attr, + + &sensor_dev_attr_in101_label.dev_attr.attr, + &sensor_dev_attr_in102_label.dev_attr.attr, + &sensor_dev_attr_in103_label.dev_attr.attr, + &sensor_dev_attr_in104_label.dev_attr.attr, + &sensor_dev_attr_in201_label.dev_attr.attr, + &sensor_dev_attr_in202_label.dev_attr.attr, + &sensor_dev_attr_in203_label.dev_attr.attr, + &sensor_dev_attr_in204_label.dev_attr.attr, + &sensor_dev_attr_in301_label.dev_attr.attr, + &sensor_dev_attr_in302_label.dev_attr.attr, + &sensor_dev_attr_in303_label.dev_attr.attr, + &sensor_dev_attr_in304_label.dev_attr.attr, + &sensor_dev_attr_in401_label.dev_attr.attr, + &sensor_dev_attr_in402_label.dev_attr.attr, + &sensor_dev_attr_in403_label.dev_attr.attr, + &sensor_dev_attr_in404_label.dev_attr.attr, + + + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, + &sensor_dev_attr_in6_alarm.dev_attr.attr, + &sensor_dev_attr_in7_alarm.dev_attr.attr, + &sensor_dev_attr_in8_alarm.dev_attr.attr, + &sensor_dev_attr_in9_alarm.dev_attr.attr, + &sensor_dev_attr_in10_alarm.dev_attr.attr, + &sensor_dev_attr_in11_alarm.dev_attr.attr, + &sensor_dev_attr_in12_alarm.dev_attr.attr, + &sensor_dev_attr_in13_alarm.dev_attr.attr, + &sensor_dev_attr_in14_alarm.dev_attr.attr, + &sensor_dev_attr_in15_alarm.dev_attr.attr, + &sensor_dev_attr_in16_alarm.dev_attr.attr, + &sensor_dev_attr_in17_alarm.dev_attr.attr, + &sensor_dev_attr_in18_alarm.dev_attr.attr, + &sensor_dev_attr_in19_alarm.dev_attr.attr, + &sensor_dev_attr_in20_alarm.dev_attr.attr, + &sensor_dev_attr_in21_alarm.dev_attr.attr, + &sensor_dev_attr_in22_alarm.dev_attr.attr, + &sensor_dev_attr_in23_alarm.dev_attr.attr, + &sensor_dev_attr_in24_alarm.dev_attr.attr, + &sensor_dev_attr_in25_alarm.dev_attr.attr, + &sensor_dev_attr_in26_alarm.dev_attr.attr, + &sensor_dev_attr_in27_alarm.dev_attr.attr, + &sensor_dev_attr_in28_alarm.dev_attr.attr, + + + NULL +}; + +static const struct attribute_group smf_vsen_group = { + .attrs = smf_vsen_attrs, + .is_visible = smf_vsen_is_visible, +}; + +/* CURRENT ATTR */ +static ssize_t +show_current_label(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct smf_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%s\n", data->curr_label[nr]); +} + +static ssize_t show_current(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret=0; + int curr; + + if (index < CURR22_INPUT) + if (data->kind == s6100smf) + ret = smf_read_reg16(data, SWITCH_CURRENT_S6100 + index * 2); + else + ret = smf_read_reg16(data, SWITCH_CURRENT_Z9100 + index * 2); + else if (index < CURR602_INPUT) + ret = smf_read_reg16(data, PSU_1_INPUT_CURRENT + (index % 2) * 2); + else + ret = smf_read_reg16(data, PSU_2_INPUT_CURRENT + (index % 4) * 2); + + + if (ret < 0) + return ret; + + curr = ret*10; + + return sprintf(buf, "%d\n", curr); +} + + +static umode_t smf_curr_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct smf_data *data = dev_get_drvdata(dev); + + if (data->curr_mask & (1 << (n % CURR_MAX))) + return a->mode; + return 0; +} + + +static SENSOR_DEVICE_ATTR(curr21_input, S_IRUGO, show_current, NULL, 0); +static SENSOR_DEVICE_ATTR(curr22_input, S_IRUGO, show_current, NULL, 1); + +static SENSOR_DEVICE_ATTR(curr601_input, S_IRUGO, show_current, NULL, 2); +static SENSOR_DEVICE_ATTR(curr602_input, S_IRUGO, show_current, NULL, 3); + +static SENSOR_DEVICE_ATTR(curr701_input, S_IRUGO, show_current, NULL, 4); +static SENSOR_DEVICE_ATTR(curr702_input, S_IRUGO, show_current, NULL, 5); + +static SENSOR_DEVICE_ATTR(curr21_label, S_IRUGO, show_current_label, NULL, 0); +static SENSOR_DEVICE_ATTR(curr22_label, S_IRUGO, show_current_label, NULL, 1); + +static SENSOR_DEVICE_ATTR(curr601_label, S_IRUGO, show_current_label, NULL, 2); +static SENSOR_DEVICE_ATTR(curr602_label, S_IRUGO, show_current_label, NULL, 3); + +static SENSOR_DEVICE_ATTR(curr701_label, S_IRUGO, show_current_label, NULL, 4); +static SENSOR_DEVICE_ATTR(curr702_label, S_IRUGO, show_current_label, NULL, 5); + + +static struct attribute *smf_curr_attrs[] = { + &sensor_dev_attr_curr21_input.dev_attr.attr, + &sensor_dev_attr_curr22_input.dev_attr.attr, + + &sensor_dev_attr_curr601_input.dev_attr.attr, + &sensor_dev_attr_curr602_input.dev_attr.attr, + + &sensor_dev_attr_curr701_input.dev_attr.attr, + &sensor_dev_attr_curr702_input.dev_attr.attr, + + &sensor_dev_attr_curr21_label.dev_attr.attr, + &sensor_dev_attr_curr22_label.dev_attr.attr, + + &sensor_dev_attr_curr601_label.dev_attr.attr, + &sensor_dev_attr_curr602_label.dev_attr.attr, + + &sensor_dev_attr_curr701_label.dev_attr.attr, + &sensor_dev_attr_curr702_label.dev_attr.attr, + + NULL +}; + + +static const struct attribute_group smf_curr_group = { + .attrs = smf_curr_attrs, + .is_visible = smf_curr_is_visible, +}; + + +/* CPU_TEMP ATTR */ +static ssize_t +show_temp_label(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct smf_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%s\n", data->temp_label[nr]); +} + + +static ssize_t show_tcpu(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret; + int temp; + + if (index < TEMP13_INPUT) /* Temp sensors */ + ret = smf_read_reg16(data, TEMP_SENSOR_1 + index * 2); + else if(index < TEMP601_INPUT) + ret = smf_read_reg16(data, PSU_1_TEMPERATURE); + else + ret = smf_read_reg16(data, PSU_2_TEMPERATURE); + + if (ret < 0) + return ret; + + if (ret > 65500) + ret = 0; + + if (ret & 0x8000) + ret = - (ret & 0x7fff); + + temp = ret*100; + + return sprintf(buf, "%d\n", temp); +} + + +static ssize_t show_temp_crit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret; + int temp; + + ret = smf_read_reg16(data, TEMP_SENSOR_1_HW_LIMIT + index * 2); + if (ret < 0) + return ret; + + if (ret == 65535) + ret = 0; + + if (ret & 0x8000) + ret = - (ret & 0x7fff); + + temp = ret*100; + + return sprintf(buf, "%d\n", temp); +} + + +static ssize_t show_temp_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret = 0; + int temp = 0; + + ret = smf_read_reg(data, TEMP_SENSOR_1_STATUS + index); + + if (ret < 0) { + return ret; + } + + if (ret == 0xff) { + ret = 0; + } + + temp = ret; + + return sprintf(buf, "%d\n", temp); +} + + +static umode_t smf_tcpu_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct smf_data *data = dev_get_drvdata(dev); + + if (data->tcpu_mask & (1 << (n % TCPU_MAX))) + return a->mode; + + return 0; +} + + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_tcpu, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_tcpu, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_tcpu, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_tcpu, NULL, 3); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_tcpu, NULL, 4); +static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_tcpu, NULL, 5); +static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_tcpu, NULL, 6); +static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_tcpu, NULL, 7); +static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_tcpu, NULL, 8); +static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_tcpu, NULL, 9); +static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, show_tcpu, NULL, 10); +static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, show_tcpu, NULL, 11); +static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO, show_tcpu, NULL, 12); + +/* PSU1 Fan Temp */ +static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO, show_tcpu, NULL, 13); + +/* PSU2 Fan Temp */ +static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO, show_tcpu, NULL, 14); + +static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3); +static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4); +static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5); +static SENSOR_DEVICE_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6); +static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7); +static SENSOR_DEVICE_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8); +static SENSOR_DEVICE_ATTR(temp10_label, S_IRUGO, show_temp_label, NULL, 9); +static SENSOR_DEVICE_ATTR(temp11_label, S_IRUGO, show_temp_label, NULL, 10); +static SENSOR_DEVICE_ATTR(temp12_label, S_IRUGO, show_temp_label, NULL, 11); +static SENSOR_DEVICE_ATTR(temp13_label, S_IRUGO, show_temp_label, NULL, 12); + +static SENSOR_DEVICE_ATTR(temp14_label, S_IRUGO, show_temp_label, NULL, 14); +static SENSOR_DEVICE_ATTR(temp15_label, S_IRUGO, show_temp_label, NULL, 15); + + +static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 1); +static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 5); +static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 9); +static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 13); +static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 17); +static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 21); +static SENSOR_DEVICE_ATTR(temp7_crit, S_IRUGO, show_temp_crit, NULL, 25); +static SENSOR_DEVICE_ATTR(temp8_crit, S_IRUGO, show_temp_crit, NULL, 29); +static SENSOR_DEVICE_ATTR(temp9_crit, S_IRUGO, show_temp_crit, NULL, 33); +static SENSOR_DEVICE_ATTR(temp10_crit, S_IRUGO, show_temp_crit, NULL, 37); +static SENSOR_DEVICE_ATTR(temp11_crit, S_IRUGO, show_temp_crit, NULL, 41); +static SENSOR_DEVICE_ATTR(temp12_crit, S_IRUGO, show_temp_crit, NULL, 45); +static SENSOR_DEVICE_ATTR(temp13_crit, S_IRUGO, show_temp_crit, NULL, 49); + +static SENSOR_DEVICE_ATTR(temp14_crit, S_IRUGO, show_temp_crit, NULL, 11); +static SENSOR_DEVICE_ATTR(temp15_crit, S_IRUGO, show_temp_crit, NULL, 11); + + +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_crit, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_crit, NULL, 6); +static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_crit, NULL, 10); +static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_crit, NULL, 14); +static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_crit, NULL, 18); +static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_crit, NULL, 22); +static SENSOR_DEVICE_ATTR(temp7_max, S_IRUGO, show_temp_crit, NULL, 26); +static SENSOR_DEVICE_ATTR(temp8_max, S_IRUGO, show_temp_crit, NULL, 30); +static SENSOR_DEVICE_ATTR(temp9_max, S_IRUGO, show_temp_crit, NULL, 34); +static SENSOR_DEVICE_ATTR(temp10_max, S_IRUGO, show_temp_crit, NULL, 38); +static SENSOR_DEVICE_ATTR(temp11_max, S_IRUGO, show_temp_crit, NULL, 42); +static SENSOR_DEVICE_ATTR(temp12_max, S_IRUGO, show_temp_crit, NULL, 46); +static SENSOR_DEVICE_ATTR(temp13_max, S_IRUGO, show_temp_crit, NULL, 50); + +static SENSOR_DEVICE_ATTR(temp14_max, S_IRUGO, show_temp_crit, NULL, 46); +static SENSOR_DEVICE_ATTR(temp15_max, S_IRUGO, show_temp_crit, NULL, 50); + +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_temp_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO, show_temp_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO, show_temp_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp7_alarm, S_IRUGO, show_temp_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(temp8_alarm, S_IRUGO, show_temp_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(temp9_alarm, S_IRUGO, show_temp_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(temp10_alarm, S_IRUGO, show_temp_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(temp11_alarm, S_IRUGO, show_temp_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(temp12_alarm, S_IRUGO, show_temp_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(temp13_alarm, S_IRUGO, show_temp_alarm, NULL, 12); + +static SENSOR_DEVICE_ATTR(temp14_alarm, S_IRUGO, show_temp_alarm, NULL, 13); +static SENSOR_DEVICE_ATTR(temp15_alarm, S_IRUGO, show_temp_alarm, NULL, 14); + + + + +static struct attribute *smf_tcpu_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + &sensor_dev_attr_temp6_input.dev_attr.attr, + &sensor_dev_attr_temp7_input.dev_attr.attr, + &sensor_dev_attr_temp8_input.dev_attr.attr, + &sensor_dev_attr_temp9_input.dev_attr.attr, + &sensor_dev_attr_temp10_input.dev_attr.attr, + &sensor_dev_attr_temp11_input.dev_attr.attr, + &sensor_dev_attr_temp12_input.dev_attr.attr, + &sensor_dev_attr_temp13_input.dev_attr.attr, + &sensor_dev_attr_temp14_input.dev_attr.attr, + &sensor_dev_attr_temp15_input.dev_attr.attr, + + &sensor_dev_attr_temp1_label.dev_attr.attr, + &sensor_dev_attr_temp2_label.dev_attr.attr, + &sensor_dev_attr_temp3_label.dev_attr.attr, + &sensor_dev_attr_temp4_label.dev_attr.attr, + &sensor_dev_attr_temp5_label.dev_attr.attr, + &sensor_dev_attr_temp6_label.dev_attr.attr, + &sensor_dev_attr_temp7_label.dev_attr.attr, + &sensor_dev_attr_temp8_label.dev_attr.attr, + &sensor_dev_attr_temp9_label.dev_attr.attr, + &sensor_dev_attr_temp10_label.dev_attr.attr, + &sensor_dev_attr_temp11_label.dev_attr.attr, + &sensor_dev_attr_temp12_label.dev_attr.attr, + &sensor_dev_attr_temp13_label.dev_attr.attr, + &sensor_dev_attr_temp14_label.dev_attr.attr, + &sensor_dev_attr_temp15_label.dev_attr.attr, + + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp2_crit.dev_attr.attr, + &sensor_dev_attr_temp3_crit.dev_attr.attr, + &sensor_dev_attr_temp4_crit.dev_attr.attr, + &sensor_dev_attr_temp5_crit.dev_attr.attr, + &sensor_dev_attr_temp6_crit.dev_attr.attr, + &sensor_dev_attr_temp7_crit.dev_attr.attr, + &sensor_dev_attr_temp8_crit.dev_attr.attr, + &sensor_dev_attr_temp9_crit.dev_attr.attr, + &sensor_dev_attr_temp10_crit.dev_attr.attr, + &sensor_dev_attr_temp11_crit.dev_attr.attr, + &sensor_dev_attr_temp12_crit.dev_attr.attr, + &sensor_dev_attr_temp13_crit.dev_attr.attr, + &sensor_dev_attr_temp14_crit.dev_attr.attr, + &sensor_dev_attr_temp15_crit.dev_attr.attr, + + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp4_max.dev_attr.attr, + &sensor_dev_attr_temp5_max.dev_attr.attr, + &sensor_dev_attr_temp6_max.dev_attr.attr, + &sensor_dev_attr_temp7_max.dev_attr.attr, + &sensor_dev_attr_temp8_max.dev_attr.attr, + &sensor_dev_attr_temp9_max.dev_attr.attr, + &sensor_dev_attr_temp10_max.dev_attr.attr, + &sensor_dev_attr_temp11_max.dev_attr.attr, + &sensor_dev_attr_temp12_max.dev_attr.attr, + &sensor_dev_attr_temp13_max.dev_attr.attr, + &sensor_dev_attr_temp14_max.dev_attr.attr, + &sensor_dev_attr_temp15_max.dev_attr.attr, + + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, + &sensor_dev_attr_temp4_alarm.dev_attr.attr, + &sensor_dev_attr_temp5_alarm.dev_attr.attr, + &sensor_dev_attr_temp6_alarm.dev_attr.attr, + &sensor_dev_attr_temp7_alarm.dev_attr.attr, + &sensor_dev_attr_temp8_alarm.dev_attr.attr, + &sensor_dev_attr_temp9_alarm.dev_attr.attr, + &sensor_dev_attr_temp10_alarm.dev_attr.attr, + &sensor_dev_attr_temp11_alarm.dev_attr.attr, + &sensor_dev_attr_temp12_alarm.dev_attr.attr, + &sensor_dev_attr_temp13_alarm.dev_attr.attr, + &sensor_dev_attr_temp14_alarm.dev_attr.attr, + &sensor_dev_attr_temp15_alarm.dev_attr.attr, + + + NULL +}; + + +static const struct attribute_group smf_tcpu_group = { + .attrs = smf_tcpu_attrs, + .is_visible = smf_tcpu_is_visible, +}; + + +/* PSU ATTR */ +static ssize_t +show_psu_label(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct smf_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%s\n", data->psu_label[nr]); +} + + +static ssize_t show_psu(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + int ret=0, export_hex=0; + int psu_status=0, pow; + int pow_val = 0; + + switch (index) { + + case 0: + pow = smf_read_reg16(data, PSU_1_MAX_POWER); + if (data->kind == s6100smf) + ret = 1000000 * 1100; + else + ret = 1000000 * 750; + break; + case 1: + ret = smf_read_reg(data, PSU_1_STATUS); + export_hex=1; + break; + case 2: + pow_val = smf_read_reg16(data, PSU_1_INPUT_POWER); + /* In case of absent psu, pow_val will be 0xffff */ + if (pow_val == 0xffff) { + pow_val = 0; + } + ret = 100000 * pow_val; + break; + case 3: + pow_val = smf_read_reg16(data, PSU_1_OUTPUT_POWER); + /* In case of absent psu, pow_val will be 0xffff */ + if (pow_val == 0xffff) { + pow_val = 0; + } + ret = 100000 * pow_val; + break; + case 4: + psu_status = smf_read_reg(data, PSU_1_STATUS); + if (psu_status &(1)) + ret=1; + break; + case 5: + pow = smf_read_reg16(data, PSU_2_MAX_POWER); + ret = 1000000 * pow; + if (data->kind == s6100smf) + ret = 1000000 * 1100; + else + ret = 1000000 * 750; + break; + case 6: + ret = smf_read_reg(data, PSU_2_STATUS); + export_hex=1; + break; + case 7: + pow_val = smf_read_reg16(data, PSU_2_INPUT_POWER); + /* In case of absent psu, pow_val will be 0xffff */ + if (pow_val == 0xffff) { + pow_val = 0; + } + ret = 100000 * pow_val; + break; + case 8: + pow_val = smf_read_reg16(data, PSU_2_OUTPUT_POWER); + /* In case of absent psu, pow_val will be 0xffff */ + if (pow_val == 0xffff) { + pow_val = 0; + } + ret = 100000 * pow_val; + break; + case 9: + psu_status = smf_read_reg(data, PSU_2_STATUS); + if (psu_status &(1)) + ret=1; + break; + case 10: + pow = smf_read_reg16(data, CURRENT_TOTAL_POWER); + /* In case of both psu absent, pow will be 0xffff */ + if (pow == 0xffff) { + pow = 0; + } + ret = pow/10; + break; + case 11: + psu_status = smf_read_reg(data, PSU_1_STATUS); + if (psu_status &(2)) + ret=1; + break; + case 12: + psu_status = smf_read_reg(data, PSU_2_STATUS); + if (psu_status &(2)) + ret=1; + break; + default: + return ret; + } + + if (ret < 0) + return ret; + + pow = ret; + + if(export_hex) + return sprintf(buf, "%x\n", pow); + else + return sprintf(buf, "%u\n", pow); +} + +/* FAN and PSU EEPROM PPID format is: + COUNTRY_CODE-PART_NO-MFG_ID-MFG_DATE_CODE-SERIAL_NO-LABEL_REV */ +static ssize_t show_ppid(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct smf_data *data = dev_get_drvdata(dev); + char ppid[EEPROM_PPID_SIZE + 1] = {0}; + char psu_mfg_date[EEPROM_MFG_DATE_SIZE + 1] = {0}; + char psu_mfg_date_code[EEPROM_DATE_CODE_SIZE + 1] = {0}; + char temp; + int i, reg, ret = 0, ppid_pos = 0; + + switch(index) { + + /* PPID starts from Country Code*/ + case 0: + reg = FAN_1_SERIAL_CODE; + break; + case 1: + reg = FAN_2_SERIAL_CODE; + break; + case 2: + reg = FAN_3_SERIAL_CODE; + break; + case 3: + reg = FAN_4_SERIAL_CODE; + break; + case 4: + reg = FAN_5_SERIAL_CODE; + break; + case 10: + reg = PSU_1_COUNTRY_CODE; + break; + case 11: + reg = PSU_2_COUNTRY_CODE; + break; + default: + return ret; +} + + // Get Country Code + for( i = 0; i < EEPROM_COUNTRY_CODE_SIZE; i++) { + ppid[ppid_pos++] = (char)smf_read_reg(data,reg++); + } + ppid[ppid_pos++] = '-'; + + // Get Part Number + for( i = 0; i < EEPROM_PART_NO_SIZE; i++) { + ppid[ppid_pos++] = (char)smf_read_reg(data,reg++); + } + ppid[ppid_pos++] = '-'; + + // Get Manufacture ID + for( i = 0; i < EEPROM_MFG_ID_SIZE; i++) { + ppid[ppid_pos++] = (char)smf_read_reg(data,reg++); + } + ppid[ppid_pos++] = '-'; + if(index > 9){ //Applicable only for PSU + // Get Manufacture date + for( i = 0; i < EEPROM_MFG_DATE_SIZE; i++) { + psu_mfg_date[i] = (char)smf_read_reg(data,reg++); + } + + /* Converting 6 digit date code [yymmdd] to 3 digit[ymd] + Year Starting from 2010 [0-9] , Day : 1-9 and A-V , Month : 1-9 and A-C */ + // Year Validation and Conversion + if( ( psu_mfg_date[0] == '1' ) && ( psu_mfg_date[1] >= '0' ) && ( psu_mfg_date[1] <= '9') ) + { + psu_mfg_date_code[0] = psu_mfg_date[1]; + } + else + { + psu_mfg_date_code[0] = ' '; + } + + // Month Validation and Conversion + temp = ( ( psu_mfg_date[2] - 0x30 ) * 10 ) + ( psu_mfg_date[3] - 0x30 ); + if( ( temp >= 1) && ( temp < 10) ) + { + psu_mfg_date_code[1] = temp + 0x30; // 0- 9 + } + else if ( ( temp >= 10) && ( temp <= 12) ) + { + psu_mfg_date_code[1] = temp + 0x37; // A-C + } + else + { + psu_mfg_date_code[1]= ' '; + } + + // Date Validation and Conversion + temp = ( ( psu_mfg_date[4] - 0x30 ) * 10 ) + ( psu_mfg_date[5] - 0x30 ); + if( ( temp >= 1) && ( temp < 10) ) + { + psu_mfg_date_code[2] = temp + 0x30; // 0- 9 + } + else if( ( temp >= 10) && ( temp <= 31) ) + { + psu_mfg_date_code[2] = temp + 0x37; // A-V + } + else + { + psu_mfg_date_code[2] = ' '; + } + for( i = 0; i < EEPROM_DATE_CODE_SIZE; i++) { + ppid[ppid_pos++] = psu_mfg_date_code[i]; + } + }else{ + for( i = 0; i < EEPROM_DATE_CODE_SIZE; i++) { + ppid[ppid_pos++] = (char)smf_read_reg(data,reg++); + } + } + + ppid[ppid_pos++] = '-'; + + // Get Serial Number + for( i = 0; i < EEPROM_SERIAL_NO_SIZE; i++) { + ppid[ppid_pos++] = (char)smf_read_reg(data,reg++); + } + ppid[ppid_pos++] = '-'; + + if(index > 9){ + // Skipping PSU service tag in PPID + reg += EEPROM_SERVICE_TAG_SIZE; + } + else{ + // Skipping FAN partno tag in PPID + reg += EEPROM_PART_NO_SIZE; + } + + // Get Label Revision + for( i = 0; i < EEPROM_LABEL_REV_SIZE; i++) { + ppid[ppid_pos++] = (char)smf_read_reg(data,reg++); + } + + return sprintf(buf, "%s\n",ppid); +} + +static umode_t smf_psu_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct smf_data *data = dev_get_drvdata(dev); + + if (data->psu_mask & (1 << (n % PSU_MAX))) + return a->mode; + return 0; +} + +/* PSU */ +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu, NULL, 2); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu, NULL, 3); +static SENSOR_DEVICE_ATTR(power3_input, S_IRUGO, show_psu, NULL, 7); +static SENSOR_DEVICE_ATTR(power4_input, S_IRUGO, show_psu, NULL, 8); + +static SENSOR_DEVICE_ATTR(power1_label, S_IRUGO, show_psu_label, NULL, 0); +static SENSOR_DEVICE_ATTR(power2_label, S_IRUGO, show_psu_label, NULL, 1); +static SENSOR_DEVICE_ATTR(power3_label, S_IRUGO, show_psu_label, NULL, 2); +static SENSOR_DEVICE_ATTR(power4_label, S_IRUGO, show_psu_label, NULL, 3); + +static SENSOR_DEVICE_ATTR(power1_max, S_IRUGO, show_psu, NULL, 0); +static SENSOR_DEVICE_ATTR(power2_max, S_IRUGO, show_psu, NULL, 0); +static SENSOR_DEVICE_ATTR(power3_max, S_IRUGO, show_psu, NULL, 5); +static SENSOR_DEVICE_ATTR(power4_max, S_IRUGO, show_psu, NULL, 5); + + +/* PSU2 */ +//static SENSOR_DEVICE_ATTR(power602_alarm, S_IRUGO, show_psu, NULL, 4); +//static SENSOR_DEVICE_ATTR(power702_alarm, S_IRUGO, show_psu, NULL, 9); + + + +static struct attribute *smf_psu_attrs[] = { + + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_power3_input.dev_attr.attr, + &sensor_dev_attr_power4_input.dev_attr.attr, + + &sensor_dev_attr_power1_label.dev_attr.attr, + &sensor_dev_attr_power2_label.dev_attr.attr, + &sensor_dev_attr_power3_label.dev_attr.attr, + &sensor_dev_attr_power4_label.dev_attr.attr, + + &sensor_dev_attr_power1_max.dev_attr.attr, + &sensor_dev_attr_power2_max.dev_attr.attr, + &sensor_dev_attr_power3_max.dev_attr.attr, + &sensor_dev_attr_power4_max.dev_attr.attr, + + NULL +}; + + +static const struct attribute_group smf_psu_group = { + .attrs = smf_psu_attrs, + .is_visible = smf_psu_is_visible, +}; + + +static const struct attribute_group smf_fanin_group = { + .attrs = smf_fanin_attrs, + .is_visible = smf_fanin_is_visible, +}; + + +static SENSOR_DEVICE_ATTR(fan_tray_presence, S_IRUGO, show_fan, NULL, 12); +static SENSOR_DEVICE_ATTR(fan1_airflow, S_IRUGO, show_fan_airflow, NULL, 0); +static SENSOR_DEVICE_ATTR(fan3_airflow, S_IRUGO, show_fan_airflow, NULL, 1); +static SENSOR_DEVICE_ATTR(fan5_airflow, S_IRUGO, show_fan_airflow, NULL, 2); +static SENSOR_DEVICE_ATTR(fan7_airflow, S_IRUGO, show_fan_airflow, NULL, 3); +static SENSOR_DEVICE_ATTR(fan9_airflow, S_IRUGO, show_fan_airflow, NULL, 4); +static SENSOR_DEVICE_ATTR(fan11_airflow, S_IRUGO, show_psu_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan12_airflow, S_IRUGO, show_psu_fan, NULL, 3); +static SENSOR_DEVICE_ATTR(fan1_serialno, S_IRUGO, show_ppid, NULL, 0); +static SENSOR_DEVICE_ATTR(fan3_serialno, S_IRUGO, show_ppid, NULL, 1); +static SENSOR_DEVICE_ATTR(fan5_serialno, S_IRUGO, show_ppid, NULL, 2); +static SENSOR_DEVICE_ATTR(fan7_serialno, S_IRUGO, show_ppid, NULL, 3); +static SENSOR_DEVICE_ATTR(fan9_serialno, S_IRUGO, show_ppid, NULL, 4); +/* IOM status */ +static SENSOR_DEVICE_ATTR(iom_status, S_IRUGO, show_voltage, NULL, 44); +static SENSOR_DEVICE_ATTR(iom_presence, S_IRUGO, show_voltage, NULL, 45); + +static SENSOR_DEVICE_ATTR(cpu_iom1_control, S_IRUGO, show_cpu_iom_control, NULL, 0); +static SENSOR_DEVICE_ATTR(cpu_iom2_control, S_IRUGO, show_cpu_iom_control, NULL, 1); +static SENSOR_DEVICE_ATTR(cpu_iom3_control, S_IRUGO, show_cpu_iom_control, NULL, 2); +static SENSOR_DEVICE_ATTR(cpu_iom4_control, S_IRUGO, show_cpu_iom_control, NULL, 3); + +static SENSOR_DEVICE_ATTR(psu1_presence, S_IRUGO, show_psu, NULL, 1); +static SENSOR_DEVICE_ATTR(psu2_presence, S_IRUGO, show_psu, NULL, 6); +static SENSOR_DEVICE_ATTR(psu1_serialno, S_IRUGO, show_ppid, NULL, 10); +static SENSOR_DEVICE_ATTR(psu2_serialno, S_IRUGO, show_ppid, NULL, 11); +static SENSOR_DEVICE_ATTR(psu1_type, S_IRUGO, show_psu, NULL, 11); +static SENSOR_DEVICE_ATTR(psu2_type, S_IRUGO, show_psu, NULL, 12); +static SENSOR_DEVICE_ATTR(current_total_power, S_IRUGO, show_psu, NULL, 10); + +/* SMF Version */ +static SENSOR_DEVICE_ATTR(smf_version, S_IRUGO, show_smf_version, NULL, 0); +static SENSOR_DEVICE_ATTR(smf_firmware_ver, S_IRUGO, show_smf_version, NULL, 1); + +/* SMF Reset Reason */ +static SENSOR_DEVICE_ATTR(smf_reset_reason, S_IRUGO, show_reset_reason, NULL, 1); + +/* SMF PowerOn Reason */ +static SENSOR_DEVICE_ATTR(smf_poweron_reason, S_IRUGO, + show_power_on_reason, NULL, 1); + +/* Mailbox Power tracking Reason */ +static SENSOR_DEVICE_ATTR(mb_poweron_reason, S_IRUGO|S_IWUSR, + show_mb_poweron_reason, set_mb_poweron_reason, 0); + +/* System Status LED */ +static SENSOR_DEVICE_ATTR(sys_status_led, S_IRUGO|S_IWUSR, + show_sys_status_led, set_sys_status_led, 0); + +static struct attribute *smf_dell_attrs[] = { + &sensor_dev_attr_smf_version.dev_attr.attr, + &sensor_dev_attr_smf_firmware_ver.dev_attr.attr, + &sensor_dev_attr_smf_reset_reason.dev_attr.attr, + &sensor_dev_attr_smf_poweron_reason.dev_attr.attr, + &sensor_dev_attr_mb_poweron_reason.dev_attr.attr, + &sensor_dev_attr_sys_status_led.dev_attr.attr, + &sensor_dev_attr_fan_tray_presence.dev_attr.attr, + &sensor_dev_attr_fan1_airflow.dev_attr.attr, + &sensor_dev_attr_fan3_airflow.dev_attr.attr, + &sensor_dev_attr_fan5_airflow.dev_attr.attr, + &sensor_dev_attr_fan7_airflow.dev_attr.attr, + &sensor_dev_attr_fan9_airflow.dev_attr.attr, + &sensor_dev_attr_fan11_airflow.dev_attr.attr, + &sensor_dev_attr_fan12_airflow.dev_attr.attr, + &sensor_dev_attr_iom_status.dev_attr.attr, + &sensor_dev_attr_iom_presence.dev_attr.attr, + &sensor_dev_attr_psu1_presence.dev_attr.attr, + &sensor_dev_attr_psu2_presence.dev_attr.attr, + &sensor_dev_attr_psu1_serialno.dev_attr.attr, + &sensor_dev_attr_psu2_serialno.dev_attr.attr, + &sensor_dev_attr_fan1_serialno.dev_attr.attr, + &sensor_dev_attr_fan3_serialno.dev_attr.attr, + &sensor_dev_attr_fan5_serialno.dev_attr.attr, + &sensor_dev_attr_fan7_serialno.dev_attr.attr, + &sensor_dev_attr_fan9_serialno.dev_attr.attr, + &sensor_dev_attr_current_total_power.dev_attr.attr, + &sensor_dev_attr_cpu_iom1_control.dev_attr.attr, + &sensor_dev_attr_cpu_iom2_control.dev_attr.attr, + &sensor_dev_attr_cpu_iom3_control.dev_attr.attr, + &sensor_dev_attr_cpu_iom4_control.dev_attr.attr, + NULL +}; + +static const struct attribute_group smf_dell_group = { + .attrs = smf_dell_attrs, + .is_visible = smf_dell_is_visible, +}; + + +static const struct attribute_group *smf_groups[] = { + &smf_psu_group, + &smf_fanin_group, + &smf_vsen_group, + &smf_curr_group, + &smf_tcpu_group, + &smf_dell_group, + NULL +}; + + + +static int smf_probe(struct platform_device *pdev) +{ + struct smf_data *data; + struct device *dev = &pdev->dev; + struct smf_sio_data *sio_data = dev_get_platdata(dev); + struct resource *res; + int err = 0; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, IOREGION_LENGTH, + smf_devices[sio_data->kind].name)) { + err = -EBUSY; + dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", + (unsigned long)res->start, + (unsigned long)res->start + IOREGION_LENGTH - 1); + return err; + } + + data = devm_kzalloc(dev, sizeof(struct smf_data), GFP_KERNEL); + /* TODO Use probe address value */ + data->addr = SMF_PROBE_ADDR; + data->kind = sio_data->kind; + + if (!data) + return -ENOMEM; + + mutex_init(&data->lock); + + /* PSU attributes */ + data->psu_mask = smf_devices[data->kind].psu_mask; + data->psu_label = smf_devices[data->kind].psu_label; + + /* FANIN attributes */ + data->fanin_mask = smf_devices[data->kind].fanin_mask; + data->fan_label = smf_devices[data->kind].fan_label; + + /* VSEN attributes */ + data->vsen_mask = smf_devices[data->kind].vsen_mask; + data->vsen_label = smf_devices[data->kind].vsen_label; + + /* CURR attributes */ + data->curr_mask = smf_devices[data->kind].curr_mask; + data->curr_label = smf_devices[data->kind].curr_label; + + /* CPU_TEMP attributes */ + data->tcpu_mask = smf_devices[data->kind].tcpu_mask; + data->temp_label = smf_devices[data->kind].temp_label; + + data->hwmon_dev = devm_hwmon_device_register_with_groups(dev, + smf_devices[data->kind].name, + data, smf_groups); + + return PTR_ERR_OR_ZERO(data->hwmon_dev); +} + + +static int smf_remove(struct platform_device *pdev) +{ + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + release_region(res->start, IOREGION_LENGTH); + return 0; +} + + +static struct platform_driver smf_driver = { + .driver = { + .name = "SMF", + }, + .probe = smf_probe, + .remove = smf_remove +}; + +int __init +smf_find(int sioaddr, unsigned short *addr, struct smf_sio_data *sio_data) +{ + + int val; + + if (force_id) + val = force_id; + else + val = inb(sioaddr + SIO_REG_DEVID); + + switch (val) { + case SIO_Z9100_ID: + sio_data->kind = z9100smf; + break; + case SIO_S6100_ID: + sio_data->kind = s6100smf; + break; + + default: + if (val != 0xffff) + pr_debug("unsupported chip ID: 0x%04x\n", val); + return -ENODEV; + } + + /* TODO Use define, should this be 0x200 or 0x210??? */ + *addr = sioaddr; + + pr_info("Found %s chip at %#x\n", smf_devices[sio_data->kind].name, *addr); + sio_data->sioreg = sioaddr; + + return (0); +} + + +/* + * when Super-I/O functions move to a separate file, the Super-I/O + * bus will manage the lifetime of the device and this module will only keep + * track of the smf driver. But since we platform_device_alloc(), we + * must keep track of the device + */ +static struct platform_device *pdev; + +static int __init sensors_smf_init(void) +{ + int err; + unsigned short address; + struct resource res; + struct smf_sio_data sio_data; + + /* + * initialize sio_data->kind and sio_data->sioreg. + * when Super-I/O functions move to a separate file, the Super-I/O + * driver will probe and auto-detect the presence of a + * smf hardware monitor, and call probe() + */ + + if (smf_find(SMF_REG_ADDR, &address, &sio_data)) + return -ENODEV; + + err = platform_driver_register(&smf_driver); + if (err) + goto exit; + + pdev = platform_device_alloc(SIO_DRVNAME, address); + if (!pdev) { + err = -ENOMEM; + pr_err("Device allocation failed\n"); + goto exit_unregister; + } + + err = platform_device_add_data(pdev, &sio_data, + sizeof(struct smf_sio_data)); + if (err) { + pr_err("Platform data allocation failed\n"); + goto exit_device_put; + } + + memset(&res, 0, sizeof(res)); + res.name = SIO_DRVNAME; + res.start = address + IOREGION_OFFSET; + res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; + res.flags = IORESOURCE_IO; + + err = acpi_check_resource_conflict(&res); + if (err) + goto exit_device_put; + + err = platform_device_add_resources(pdev, &res, 1); + if (err) { + pr_err("Device resource addition failed (%d)\n", err); + goto exit_device_put; + } + + /* platform_device_add calls probe() */ + err = platform_device_add(pdev); + if (err) { + pr_err("Device addition failed (%d)\n", err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit_unregister: + platform_driver_unregister(&smf_driver); +exit: + return err; +} + + +static void __exit sensors_smf_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&smf_driver); + + /*Remove sysfs dell_kobj*/ + kobject_put(dell_kobj); +} + + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SMF driver"); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); +MODULE_AUTHOR("Per Fremrot "); +MODULE_AUTHOR("Paavaanan "); + +module_init(sensors_smf_init); +module_exit(sensors_smf_exit); diff --git a/platform/broadcom/sonic-platform-modules-dell/common/fw-updater b/platform/broadcom/sonic-platform-modules-dell/common/fw-updater new file mode 100755 index 000000000000..baed0565234e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/fw-updater @@ -0,0 +1,87 @@ +#!/usr/bin/python3 + +# dell staging fw updater script + +import os +import subprocess +import argparse + + +onie_boot_folder = '/mnt/onie-boot/onie/tools/bin/onie-fwpkg' +onie_fwpkg_tool = '/mnt/onie-boot/onie/tools/bin/onie-fwpkg' +ONIE_BOOT_MODE_CMD = '/mnt/onie-boot/onie/tools/bin/onie-boot-mode' +HOST_GRUB_DIR = '/host' +HOST_GRUB_CFG = HOST_GRUB_DIR + '/grub/grub.cfg' +HOST_GRUB_ENV = HOST_GRUB_DIR + '/grub/grubenv' +HOST_GRUB_BOOT_DIR = '--boot-directory=' + HOST_GRUB_DIR +HOST_PLATFORM_INFO = HOST_GRUB_DIR + '/platform' +dell_reload_tool = '/usr/local/bin/reboot' + + +def set_onie_mode(option): + """Select the ONIE boot mode, and set the next_entry to point to ONIE""" + _set_env_option('next_entry', 'ONIE') + subprocess.check_call([ONIE_BOOT_MODE_CMD, '-o', option]) + +def set_onie_fw_update_env(): + """Select the ONIE boot mode, and set the next_entry to point to ONIE""" + + if not os.path.exists(onie_boot_folder): + os.makedirs(onie_boot_folder) + + try: + subprocess.check_call(['mount', '/dev/disk/by-label/ONIE-BOOT', '/mnt/onie-boot']) + except: + print("onie-boot not able to mount") + +def _set_env_option(option, value): + """Set an option in the GRUB environment block. Pass None to value to + unset the option""" + if value is None: + action = 'unset' + key_value = option + else: + action = 'set' + key_value = '%s=%s' % (option, value) + + subprocess.check_call(['grub-editenv', HOST_GRUB_ENV, action, key_value]) + + +def dell_firmware_update_staging(image_name): + + try: + p = subprocess.Popen([onie_fwpkg_tool, "purge"], stdout=subprocess.PIPE, stdin=subprocess.PIPE) + p.communicate("y") + except: + print("onie-fwpkg command not found for purging old fw updates") + + try: + subprocess.check_call([onie_fwpkg_tool, "add", str(image_name)]) + except: + print("onie-fwpkg is not found to stage fw updates") + + try: + set_onie_mode("update") + except: + print("dell-image command not found") + + try: + subprocess.check_call([dell_reload_tool]) + except: + print("reload command not found") + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Dell HOST Firmware updates') + opts = parser.add_mutually_exclusive_group(required=True) + opts.add_argument('-u', '--update', nargs=1, metavar='IMAGE', + help='update specified image') + + args = parser.parse_args() + + if os.getuid() != 0: + parser.exit(127, 'ERROR: Must be root\n') + + if args.update: + set_onie_fw_update_env() + dell_firmware_update_staging(args.update[0]) diff --git a/platform/broadcom/sonic-platform-modules-dell/common/io_rd_wr.py b/platform/broadcom/sonic-platform-modules-dell/common/io_rd_wr.py new file mode 100755 index 000000000000..a8bb096521be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/io_rd_wr.py @@ -0,0 +1,90 @@ +#!/usr/bin/python3 +# Script to read/write the io based registers + +import sys +import os +import getopt +import struct + +io_resource = '/dev/port' + +def usage(): + ''' This is the Usage Method ''' + + print('Utility for IO read/write') + print('\t\t io_rd_wr.py --get --offset ') + print('\t\t io_rd_wr.py --set --val --offset ') + sys.exit(1) + +def io_reg_read(io_resource, offset): + fd = os.open(io_resource, os.O_RDONLY) + if(fd < 0): + print('file open failed %s' % io_resource) + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print('lseek failed on %s' % io_resource) + return + buf = os.read(fd, 1) + reg_val1 = ord(buf) + print('reg value %x' % reg_val1) + os.close(fd) + +def io_reg_write(io_resource, offset, val): + fd = os.open(io_resource, os.O_RDWR) + if(fd < 0): + print('file open failed %s' % io_resource) + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print('lseek failed on %s' % io_resource) + return + ret = os.write(fd, struct.pack('B', val)) + if(ret != 1): + print('write failed %d' % ret) + return + os.close(fd) + +def main(argv): + + ''' The main function will read the user input from the + command line argument and process the request ''' + + opts = '' + val = '' + choice = '' + offset = '' + + try: + opts, args = getopt.getopt(argv, "hgs:", + ["val=", "offset=", "help", "get", "set"]) + except getopt.GetoptError: + usage() + + for opt, arg in opts: + + if opt in ('-h', '--help'): + choice = 'help' + + elif opt in ('-g', '--get'): + choice = 'get' + + elif opt in ('-s', '--set'): + choice = 'set' + + elif opt == '--offset': + offset = int(arg, 16) + + elif opt == '--val': + val = int(arg, 16) + + if choice == 'get' and offset != '': + io_reg_read(io_resource, offset) + + elif choice == 'set' and offset != '' and val != '': + io_reg_write(io_resource, offset, val) + + else: + usage() + +# Calling the main method +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-dell/common/ipmihelper.py b/platform/broadcom/sonic-platform-modules-dell/common/ipmihelper.py new file mode 100644 index 000000000000..d95329c40de2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/ipmihelper.py @@ -0,0 +1,269 @@ +#!/usr/bin/python3 + +######################################################################## +# DellEMC +# +# Module contains implementation of IpmiSensor and IpmiFru classes that +# provide Sensor's and FRU's information respectively. +# +######################################################################## + +import subprocess +import re + +# IPMI Request Network Function Codes +NetFn_SensorEvent = 0x04 +NetFn_Storage = 0x0A + +# IPMI Sensor Device Commands +Cmd_GetSensorReadingFactors = 0x23 +Cmd_GetSensorThreshold = 0x27 +Cmd_GetSensorReading = 0x2D + +# IPMI FRU Device Commands +Cmd_ReadFRUData = 0x11 + +def get_ipmitool_raw_output(args): + """ + Returns a list the elements of which are the individual bytes of + ipmitool raw command output. + """ + result_bytes = list() + result = "" + command = "ipmitool raw {}".format(args) + try: + proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE, + universal_newlines=True, stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + if not proc.returncode: + result = stdout.rstrip('\n') + except EnvironmentError: + pass + + for i in result.split(): + result_bytes.append(int(i, 16)) + + return result_bytes + +class IpmiSensor(object): + + # Sensor Threshold types and their respective bit masks + THRESHOLD_BIT_MASK = { + "LowerNonCritical" : 0, + "LowerCritical" : 1, + "LowerNonRecoverable" : 2, + "UpperNonCritical" : 3, + "UpperCritical" : 4, + "UpperNonRecoverable" : 5 + } + + def __init__(self, sensor_id, is_discrete=False): + self.id = sensor_id + self.is_discrete = is_discrete + + def _get_converted_sensor_reading(self, raw_value): + """ + Returns a 2 element tuple(bool, int) in which first element + provides the validity of the reading and the second element is + the converted sensor reading + """ + # Get Sensor Reading Factors + cmd_args = "{} {} {} {}".format(NetFn_SensorEvent, + Cmd_GetSensorReadingFactors, + self.id, raw_value) + factors = get_ipmitool_raw_output(cmd_args) + + if len(factors) != 7: + return False, 0 + + # Compute Twos complement + def get_twos_complement(val, bits): + if val & (1 << (bits - 1)): + val = val - (1 << bits) + return val + + # Calculate actual sensor value from the raw sensor value + # using the sensor reading factors. + M = get_twos_complement(((factors[2] & 0xC0) << 8) | factors[1], 10) + B = get_twos_complement(((factors[4] & 0xC0) << 8) | factors[3], 10) + R_exp = get_twos_complement((factors[6] & 0xF0) >> 4, 4) + B_exp = get_twos_complement(factors[6] & 0x0F, 4) + + converted_reading = ((M * raw_value) + (B * 10**B_exp)) * 10**R_exp + + return True, converted_reading + + def get_reading(self): + """ + For Threshold sensors, returns the sensor reading. + For Discrete sensors, returns the state value. + + Returns: + A tuple (bool, int) where the first element provides the + validity of the reading and the second element provides the + sensor reading/state value. + """ + # Get Sensor Reading + cmd_args = "{} {} {}".format(NetFn_SensorEvent, Cmd_GetSensorReading, + self.id) + output = get_ipmitool_raw_output(cmd_args) + if len(output) != 4: + return False, 0 + + # Check reading/state unavailable + if output[1] & 0x20: + return False, 0 + + if self.is_discrete: + state = ((output[3] & 0x7F) << 8) | output[2] + return True, state + else: + return self._get_converted_sensor_reading(output[0]) + + def get_threshold(self, threshold_type): + """ + Returns the sensor's threshold value for a given threshold type. + + Args: + threshold_type (str) - one of the below mentioned + threshold type strings + + "LowerNonCritical" + "LowerCritical" + "LowerNonRecoverable" + "UpperNonCritical" + "UpperCritical" + "UpperNonRecoverable" + Returns: + A tuple (bool, int) where the first element provides the + validity of that threshold and second element provides the + threshold value. + """ + # Thresholds are not valid for discrete sensors + if self.is_discrete: + raise TypeError("Threshold is not applicable for Discrete Sensor") + + if threshold_type not in list(self.THRESHOLD_BIT_MASK.keys()): + raise ValueError("Invalid threshold type {} provided. Valid types " + "are {}".format(threshold_type, + list(self.THRESHOLD_BIT_MASK.keys()))) + + bit_mask = self.THRESHOLD_BIT_MASK[threshold_type] + + # Get Sensor Threshold + cmd_args = "{} {} {}".format(NetFn_SensorEvent, Cmd_GetSensorThreshold, + self.id) + thresholds = get_ipmitool_raw_output(cmd_args) + if len(thresholds) != 7: + return False, 0 + + valid_thresholds = thresholds.pop(0) + # Check whether particular threshold is readable + if valid_thresholds & (1 << bit_mask): + return self._get_converted_sensor_reading(thresholds[bit_mask]) + else: + return False, 0 + +class IpmiFru(object): + + def __init__(self, fru_id): + self.id = fru_id + + def _get_ipmitool_fru_print(self): + result = "" + command = "ipmitool fru print {}".format(self.id) + try: + proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE, + universal_newlines=True, stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + if not proc.returncode: + result = stdout.rstrip('\n') + except EnvironmentError: + pass + + return result + + def _get_from_fru(self, info): + """ + Returns a string containing the info from FRU + """ + fru_output = self._get_ipmitool_fru_print() + if not fru_output: + return "NA" + + info_req = re.search(r"%s\s*:(.*)" % info, fru_output) + if not info_req: + return "NA" + + return info_req.group(1).strip() + + def get_board_serial(self): + """ + Returns a string containing the Serial Number of the device. + """ + return self._get_from_fru('Board Serial') + + def get_board_part_number(self): + """ + Returns a string containing the Part Number of the device. + """ + return self._get_from_fru('Board Part Number') + + def get_board_mfr_id(self): + """ + Returns a string containing the manufacturer id of the FRU. + """ + return self._get_from_fru('Board Mfg') + + def get_board_product(self): + """ + Returns a string containing the manufacturer id of the FRU. + """ + return self._get_from_fru('Board Product') + + def get_fru_data(self, offset, count=1): + """ + Reads and returns the FRU data at the provided offset. + + Args: + offset (int) - FRU offset to read + count (int) - Number of bytes to read [optional, default = 1] + Returns: + A tuple (bool, list(int)) where the first element provides + the validity of the data read and the second element is a + list, the elements of which are the individual bytes of the + FRU data read. + """ + result_bytes = list() + is_valid = True + result = "" + + offset_LSB = offset & 0xFF + offset_MSB = offset & 0xFF00 + command = "ipmitool raw {} {} {} {} {} {}".format(NetFn_Storage, + Cmd_ReadFRUData, + self.id, offset_LSB, + offset_MSB, count) + try: + proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE, + universal_newlines=True, stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + if not proc.returncode: + result = stdout.rstrip('\n') + except EnvironmentError: + is_valid = False + + if (not result) or (not is_valid): + return False, result_bytes + + for i in result.split(): + result_bytes.append(int(i, 16)) + + read_count = result_bytes.pop(0) + if read_count != count: + return False, result_bytes + else: + return True, result_bytes diff --git a/platform/broadcom/sonic-platform-modules-dell/common/nvram_rd_wr.py b/platform/broadcom/sonic-platform-modules-dell/common/nvram_rd_wr.py new file mode 100755 index 000000000000..527c531ddfb4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/nvram_rd_wr.py @@ -0,0 +1,94 @@ +#!/usr/bin/python3 +# Script to read/write the nvram + +import sys +import os +import getopt +import struct + +nvram_resource = '/dev/nvram' + +def usage(): + ''' This is the Usage Method ''' + + print('Utility for NVRAM read/write') + print('\t\t nvram_rd_wr.py --get --offset ') + print('\t\t nvram_rd_wr.py --set --val --offset ') + sys.exit(1) + +def nvram_reg_read(nvram_resource, offset): + fd = os.open(nvram_resource, os.O_RDONLY) + if(fd < 0): + print('file open failed %s' % nvram_resource) + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print('lseek failed on %s' % nvram_resource) + return + buf = os.read(fd, 1) + reg_val1 = ord(buf) + print('value %x' % reg_val1) + os.close(fd) + +def nvram_reg_write(nvram_resource, offset, val): + fd = os.open(nvram_resource, os.O_RDWR) + if(fd < 0): + print('file open failed %s' % nvram_resource) + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print('lseek failed on %s' % nvram_resource) + return + ret = os.write(fd, struct.pack('B', val)) + if(ret != 1): + print('write failed %d' % ret) + return + os.close(fd) + +def main(argv): + + ''' The main function will read the user input from the + command line argument and process the request ''' + + opts = '' + val = '' + choice = '' + offset = '' + + try: + opts, args = getopt.getopt(argv, "hgs:", + ["val=", "offset=", "help", "get", "set"]) + except getopt.GetoptError: + usage() + + if not os.path.exists(nvram_resource): + print('NVRAM is not initialized') + sys.exit(1) + + for opt, arg in opts: + + if opt in ('-h', '--help'): + choice = 'help' + + elif opt in ('-g', '--get'): + choice = 'get' + + elif opt in ('-s', '--set'): + choice = 'set' + + elif opt == '--offset': + offset = int(arg, 16) - 0xE + + elif opt == '--val': + val = int(arg, 16) + + if choice == 'get' and offset != '': + nvram_reg_read(nvram_resource, offset) + + elif choice == 'set' and offset != '' and val != '': + nvram_reg_write(nvram_resource, offset, val) + + else: + usage() + +# Calling the main method +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-dell/common/onie_mode_set b/platform/broadcom/sonic-platform-modules-dell/common/onie_mode_set new file mode 100755 index 000000000000..247dda5dcc8e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/onie_mode_set @@ -0,0 +1,90 @@ +#!/bin/bash +#scrit to set onie boot modes from NOS +# modes supported rescue/install/uninstall + +VERBOSE=no +ONIEPATH="/mnt/onie-boot" + +unset ONIE_MODE + +function set_onie_boot() +{ + # If reboot to ONIE is requested, set the ONIE boot mode (update/install/uninstall/rescue) + # and reboot. + + # Exit if not superuser + if [[ "$EUID" -ne 0 ]]; then + echo "This command must be run as root" >&2 + exit 1 + fi + + # Mount ONIE partition if not already mounted + if ! grep -qs '/mnt/onie-boot ' /proc/mounts; then + mkdir -p ${ONIEPATH} + mount LABEL=ONIE-BOOT ${ONIEPATH} || ERR=$? + if [[ ${ERR} -ne 0 ]]; then + VERBOSE=yes debug "Failed to mount ONIE partition." + exit 1 + fi + fi + + # Set mode + ${ONIEPATH}/onie/tools/bin/onie-boot-mode -o ${ONIE_MODE} || ERR=$? + if [[ ${ERR} -ne 0 ]]; then + VERBOSE=yes debug "Failed to set ONIE boot mode. Ensure that mode is valid" + exit 1 + fi + + # Set next boot to ONIE + grub-editenv /host/grub/grubenv set next_entry=ONIE || ERR=$? + if [[ ${ERR} -ne 0 ]]; then + VERBOSE=yes debug "Failed to set next boot to ONIE." + exit 1 + fi + echo "next boot mode set to onie - ${ONIE_MODE}" + +} + + +function debug() +{ + if [[ x"${VERBOSE}" == x"yes" ]]; then + echo `date` $@ + fi + logger "$@" +} + + +SCRIPT=$0 + +function show_help_and_exit() +{ + echo "Usage ${SCRIPT} [options]" + echo " This script will set modes in onie rescue/uninstall/install." + echo " " + echo " Available options:" + echo " -h, -? : getting this help" + echo " -o [mode] : boot into ONIE" + + exit 0 +} + +function parse_options() +{ + while getopts "h?vo:" opt; do + case $opt in + h|\? ) + show_help_and_exit + ;; + o ) + ONIE_MODE=$OPTARG + set_onie_boot + ;; + v ) + VERBOSE=yes + ;; + esac + done +} + +parse_options $@ diff --git a/platform/broadcom/sonic-platform-modules-dell/common/pcisysfs.py b/platform/broadcom/sonic-platform-modules-dell/common/pcisysfs.py new file mode 100755 index 000000000000..b305f54eca86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/pcisysfs.py @@ -0,0 +1,105 @@ +#!/usr/bin/python3 +# Copyright (c) 2015 Dell Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. + +import struct +import sys +import getopt +from os import * +from mmap import * + +def usage(): + ''' This is the Usage Method ''' + + print('\t\t pcisysfs.py --get --offset --res ') + print('\t\t pcisysfs.py --set --val --offset --res ') + sys.exit(1) + +def pci_mem_read(mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + print("") + reg_val = struct.unpack('I', read_data_stream) + print("reg_val read:%x" % reg_val) + return reg_val + +def pci_mem_write(mm, offset, data): + mm.seek(offset) + print("data to write:%x" % data) + mm.write(struct.pack('I', data)) + +def pci_set_value(resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + pci_mem_write(mm, offset, val) + mm.close() + close(fd) + +def pci_get_value(resource, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + pci_mem_read(mm, offset) + mm.close() + close(fd) + +def main(argv): + + ''' The main function will read the user input from the + command line argument and process the request ''' + + opts = '' + val = '' + choice = '' + resource = '' + offset = '' + + try: + opts, args = getopt.getopt(argv, "hgsv:", + ["val=", "res=", "offset=", "help", "get", "set"]) + + except getopt.GetoptError: + usage() + + for opt, arg in opts: + + if opt in ('-h', '--help'): + choice = 'help' + + elif opt in ('-g', '--get'): + choice = 'get' + + elif opt in ('-s', '--set'): + choice = 'set' + + elif opt == '--res': + resource = arg + + elif opt == '--val': + val = int(arg, 16) + + elif opt == '--offset': + offset = int(arg, 16) + + if choice == 'set' and val != '' and offset != '' and resource != '': + pci_set_value(resource, val, offset) + + elif choice == 'get' and offset != '' and resource != '': + pci_get_value(resource, offset) + + else: + usage() + +# Calling the main method +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-dell/common/platform_reboot b/platform/broadcom/sonic-platform-modules-dell/common/platform_reboot new file mode 100755 index 000000000000..ca04ac0635a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/platform_reboot @@ -0,0 +1,23 @@ +#!/usr/bin/python3 +import os +import struct + +PORT_RES = '/dev/port' + + +def portio_reg_write(resource, offset, val): + fd = os.open(resource, os.O_RDWR) + if(fd < 0): + print('file open failed %s' % resource) + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print('lseek failed on %s' % resource) + return + ret = os.write(fd, struct.pack('B', val)) + if(ret != 1): + print('write failed %d' % ret) + return + os.close(fd) + +if __name__ == "__main__": + portio_reg_write(PORT_RES, 0xcf9, 0xe) diff --git a/platform/broadcom/sonic-platform-modules-dell/common/sonic_platform/hwaccess.py b/platform/broadcom/sonic-platform-modules-dell/common/sonic_platform/hwaccess.py new file mode 100644 index 000000000000..567669d36fc0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/common/sonic_platform/hwaccess.py @@ -0,0 +1,53 @@ +# Helper functions to access hardware + +import os +import struct +import mmap +import subprocess + +# Read PCI device + +def pci_mem_read(mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + return struct.unpack('I',read_data_stream)[0] + +def pci_get_value(resource, offset): + with open(resource, 'r+b') as fd: + mm = mmap.mmap(fd.fileno(), 0) + val = pci_mem_read(mm, offset) + mm.close() + return val + +# Read I2C device + +def i2c_get(bus, i2caddr, ofs): + return int(subprocess.check_output(['/usr/sbin/i2cget', '-y', str(bus), str(i2caddr), str(ofs)]), 16) + +def io_reg_read(io_resource, offset): + fd = os.open(io_resource, os.O_RDONLY) + if fd < 0: + print('file open failed %s' % io_resource) + return -1 + if os.lseek(fd, offset, os.SEEK_SET) != offset: + print('lseek failed on %s' % io_resource) + return -1 + buf = os.read(fd, 1) + reg_val1 = ord(buf) + os.close(fd) + return reg_val1 + +def io_reg_write(io_resource, offset, val): + fd = os.open(io_resource, os.O_RDWR) + if fd < 0: + print('file open failed %s' % io_resource) + return False + if os.lseek(fd, offset, os.SEEK_SET) != offset: + print('lseek failed on %s' % io_resource) + return False + ret = os.write(fd, struct.pack('B', val)) + if ret != 1: + print('write failed %d' % ret) + return False + os.close(fd) + return True diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/changelog b/platform/broadcom/sonic-platform-modules-dell/debian/changelog new file mode 100644 index 000000000000..90fed6f6d847 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/changelog @@ -0,0 +1,11 @@ +sonic-dell-platform-modules (1.1) unstable; urgency=low + + * Add support for Dell S6100 + + -- Dell Team Wed, 08 Feb 2017 15:57:40 -0800 + +sonic-dell-platform-modules (1.0) unstable; urgency=low + + * Initial release + + -- Dell Team Mon, 6 Feb 2017 10:10:10 -0800 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/compat b/platform/broadcom/sonic-platform-modules-dell/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/control b/platform/broadcom/sonic-platform-modules-dell/debian/control new file mode 100644 index 000000000000..2920602fcd60 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/control @@ -0,0 +1,46 @@ +Source: sonic-dell-platform-modules +Section: main +Priority: extra +Maintainer: Dell Team +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-s6000 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-z9100 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-s6100 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-z9264f +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-s5232f +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-s5248f +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-z9332f +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-s5296f +Architecture: amd64 +Depends: linux-image-4.9.0-9-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-s5232f.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5232f.init new file mode 100755 index 000000000000..7a8df5a9e2e1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5232f.init @@ -0,0 +1,40 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Z9264f board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + # /usr/local/bin/iom_power_on.sh + /usr/local/bin/s5232f_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/s5232f_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-s5232f.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5232f.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5232f.install new file mode 100644 index 000000000000..25d2b84ad4ac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5232f.install @@ -0,0 +1,13 @@ +s5232f/scripts/s5232f_platform.sh usr/local/bin +s5232f/scripts/check_qsfp.sh usr/local/bin +s5232f/scripts/platform_sensors.py usr/local/bin +s5232f/scripts/sensors usr/bin +s5232f/scripts/qsfp_irq_enable.py usr/bin +s5232f/cfg/s5232f-modules.conf etc/modules-load.d +s5232f/systemd/platform-modules-s5232f.service etc/systemd/system +s5232f/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-dellemc_s5232f_c3538-r0 +s5232f/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-dellemc_s5232f_c3538-r0 +common/platform_reboot usr/share/sonic/device/x86_64-dellemc_s5232f_c3538-r0 +common/fw-updater usr/local/bin +common/onie_mode_set usr/local/bin +common/pcisysfs.py usr/bin diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5232f.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5232f.postinst new file mode 100644 index 000000000000..f9b7cd32fe9f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5232f.postinst @@ -0,0 +1,10 @@ +# postinst script for S5232f + +# Enable Dell-S5232f-platform-service +depmod -a +systemctl enable platform-modules-s5232f.service +systemctl start platform-modules-s5232f.service + + +#DEBHELPER# + diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5248f.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5248f.init new file mode 100755 index 000000000000..0e02b00bc38a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5248f.init @@ -0,0 +1,40 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S5248f board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + # /usr/local/bin/iom_power_on.sh + /usr/local/bin/s5248f_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/s5248f_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-s5248f.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5248f.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5248f.install new file mode 100644 index 000000000000..6e74fbec0ae5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5248f.install @@ -0,0 +1,11 @@ +s5248f/scripts/s5248f_platform.sh usr/local/bin +s5248f/scripts/check_qsfp.sh usr/local/bin +s5248f/scripts/platform_sensors.py usr/local/bin +s5248f/scripts/sensors usr/bin +s5248f/scripts/qsfp_irq_enable.py usr/bin +s5248f/cfg/s5248f-modules.conf etc/modules-load.d +s5248f/systemd/platform-modules-s5248f.service etc/systemd/system +common/platform_reboot usr/share/sonic/device/x86_64-dellemc_s5248f_c3538-r0 +common/fw-updater usr/local/bin +common/onie_mode_set usr/local/bin +common/pcisysfs.py usr/bin diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5248f.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5248f.postinst new file mode 100644 index 000000000000..f13e2f703130 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5248f.postinst @@ -0,0 +1,10 @@ +# postinst script for S5248f + +# Enable Dell-S5248f-platform-service +depmod -a +systemctl enable platform-modules-s5248f.service +systemctl start platform-modules-s5248f.service + + +#DEBHELPER# + diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5296f.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5296f.init new file mode 100755 index 000000000000..9276679ef004 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5296f.init @@ -0,0 +1,39 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S5296f board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + # /usr/local/bin/iom_power_on.sh + /usr/local/bin/s5296f_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/s5296f_platform.sh deinit + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-s5296f.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5296f.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5296f.install new file mode 100644 index 000000000000..497554a476c1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5296f.install @@ -0,0 +1,9 @@ +s5296f/scripts/s5296f_platform.sh usr/local/bin +s5296f/scripts/platform_sensors.py usr/local/bin +s5296f/scripts/sensors usr/bin +s5296f/scripts/pcisysfs.py usr/bin +s5296f/cfg/s5296f-modules.conf etc/modules-load.d +s5296f/systemd/platform-modules-s5296f.service etc/systemd/system +common/platform_reboot usr/share/sonic/device/x86_64-dellemc_s5296f_c3538-r0 +common/fw-updater usr/local/bin +common/onie_mode_set usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5296f.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5296f.postinst new file mode 100644 index 000000000000..21772eafdd02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s5296f.postinst @@ -0,0 +1,10 @@ +# postinst script for S5296f + +# Enable Dell-S5296f-platform-service +depmod -a +systemctl enable platform-modules-s5296f.service +systemctl start platform-modules-s5296f.service + + +#DEBHELPER# + diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.init new file mode 100755 index 000000000000..94bddb6afe20 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.init @@ -0,0 +1,39 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S6000 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + /usr/local/bin/s6000_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/s6000_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-s6000.init {start|stop}" + exit 1 + ;; +esac + +exit 0 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 new file mode 100644 index 000000000000..e67a59485136 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.install @@ -0,0 +1,12 @@ +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/scripts/platform_reboot_override usr/share/sonic/device/x86_64-dell_s6000_s1220-r0 +s6000/scripts/platform_update_reboot_cause usr/share/sonic/device/x86_64-dell_s6000_s1220-r0 +s6000/scripts/override.conf /etc/systemd/system/systemd-reboot.service.d +s6000/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-dell_s6000_s1220-r0 +s6000/modules/sonic_platform-1.0-py3-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 new file mode 100644 index 000000000000..052e5a6f574e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6000.postinst @@ -0,0 +1,12 @@ +# postinst script for S6000 + +# Enable Dell-S6000-platform-service +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/debian/platform-modules-s6100.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.init new file mode 100755 index 000000000000..c798b24ef235 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.init @@ -0,0 +1,40 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S6100 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + /usr/local/bin/iom_power_on.sh + /usr/local/bin/s6100_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/s6100_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-s6100.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.install new file mode 100644 index 000000000000..a9eb63eeea45 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.install @@ -0,0 +1,28 @@ +s6100/scripts/iom_power_*.sh usr/local/bin +s6100/scripts/s6100_platform.sh usr/local/bin +s6100/scripts/s6100_i2c_enumeration.sh usr/local/bin +s6100/scripts/s6100_bitbang_reset.sh usr/local/bin +s6100/scripts/pcisysfs.py usr/bin +common/dell_i2c_utils.sh usr/local/bin +common/io_rd_wr.py usr/local/bin +common/nvram_rd_wr.py usr/local/bin +s6100/scripts/platform_reboot_override usr/share/sonic/device/x86_64-dell_s6100_c2538-r0 +s6100/scripts/fast-reboot_plugin usr/share/sonic/device/x86_64-dell_s6100_c2538-r0 +s6100/scripts/track_reboot_reason.sh usr/share/sonic/device/x86_64-dell_s6100_c2538-r0 +s6100/scripts/warm-reboot_plugin usr/share/sonic/device/x86_64-dell_s6100_c2538-r0 +s6100/scripts/ssd-fw-upgrade usr/share/sonic/device/x86_64-dell_s6100_c2538-r0 +s6100/scripts/override.conf /etc/systemd/system/systemd-reboot.service.d +common/dell_lpc_mon.sh usr/local/bin +s6100/scripts/platform_sensors.py usr/local/bin +s6100/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-dell_s6100_c2538-r0 +s6100/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-dell_s6100_c2538-r0 +s6100/scripts/platform_watchdog_enable.sh usr/local/bin +s6100/scripts/platform_watchdog_disable.sh usr/local/bin +s6100/scripts/sensors usr/bin +s6100/systemd/platform-modules-s6100.service etc/systemd/system +s6100/systemd/s6100-lpc-monitor.service etc/systemd/system +s6100/systemd/s6100-reboot-cause.service etc/systemd/system +s6100/systemd/s6100-i2c-enumerate.service etc/systemd/system +tools/flashrom/flashrom usr/local/bin/ +common/fw-updater usr/local/bin +common/onie_mode_set usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.postinst new file mode 100644 index 000000000000..eda8f7c8a41a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-s6100.postinst @@ -0,0 +1,11 @@ +# postinst script for S6100 + +# Enable Dell-S6100-platform-service +depmod -a +systemctl enable platform-modules-s6100.service +systemctl start platform-modules-s6100.service + +systemctl enable s6100-lpc-monitor.service +systemctl start s6100-lpc-monitor.service + +#DEBHELPER# diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.init new file mode 100755 index 000000000000..aefecf1d8158 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.init @@ -0,0 +1,40 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Z9100 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + # /usr/local/bin/iom_power_on.sh + /usr/local/bin/z9100_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/z9100_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-z9100.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.install new file mode 100644 index 000000000000..28d77243d639 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.install @@ -0,0 +1,16 @@ +z9100/scripts/check_qsfp.sh usr/local/bin +z9100/scripts/z9100_platform.sh usr/local/bin +common/dell_i2c_utils.sh usr/local/bin +common/dell_lpc_mon.sh usr/local/bin +common/io_rd_wr.py usr/local/bin +z9100/scripts/platform_reboot_override usr/share/sonic/device/x86_64-dell_z9100_c2538-r0 +z9100/scripts/override.conf /etc/systemd/system/systemd-reboot.service.d +z9100/scripts/platform_sensors.py usr/local/bin +z9100/scripts/sensors usr/bin +z9100/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-dell_z9100_c2538-r0 +z9100/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-dell_z9100_c2538-r0 +z9100/cfg/z9100-modules.conf etc/modules-load.d +z9100/systemd/platform-modules-z9100.service etc/systemd/system +z9100/systemd/z9100-lpc-monitor.service etc/systemd/system +common/fw-updater usr/local/bin +common/onie_mode_set usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.postinst new file mode 100644 index 000000000000..77750fe626a4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9100.postinst @@ -0,0 +1,12 @@ +# postinst script for Z9100 + +# Enable Dell-Z9100-platform-service +depmod -a +systemctl enable platform-modules-z9100.service +systemctl start platform-modules-z9100.service + + +systemctl enable z9100-lpc-monitor.service +systemctl start z9100-lpc-monitor.service + +#DEBHELPER# diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.init new file mode 100755 index 000000000000..fb0b68117972 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.init @@ -0,0 +1,40 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Z9264f board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + # /usr/local/bin/iom_power_on.sh + /usr/local/bin/z9264f_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/z9264f_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-z9264f.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.install new file mode 100644 index 000000000000..9aa3793f5d29 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.install @@ -0,0 +1,13 @@ +z9264f/scripts/z9264f_platform.sh usr/local/bin +z9264f/scripts/check_qsfp.sh usr/local/bin +z9264f/scripts/platform_sensors.py usr/local/bin +z9264f/scripts/sensors usr/bin +z9264f/scripts/port_irq_enable.py usr/bin +z9264f/cfg/z9264f-modules.conf etc/modules-load.d +z9264f/systemd/platform-modules-z9264f.service etc/systemd/system +z9264f/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-dellemc_z9264f_c3538-r0 +z9264f/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-dellemc_z9264f_c3538-r0 +common/platform_reboot usr/share/sonic/device/x86_64-dellemc_z9264f_c3538-r0 +common/fw-updater usr/local/bin +common/onie_mode_set usr/local/bin +common/pcisysfs.py usr/bin diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.postinst new file mode 100644 index 000000000000..f5da0a818900 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9264f.postinst @@ -0,0 +1,10 @@ +# postinst script for Z9264f + +# Enable Dell-Z9264f-platform-service +depmod -a +systemctl enable platform-modules-z9264f.service +systemctl start platform-modules-z9264f.service + + +#DEBHELPER# + diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9332f.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9332f.init new file mode 100644 index 000000000000..f4fe9eb396fd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9332f.init @@ -0,0 +1,39 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Z9332f board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + /usr/local/bin/z9332f_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/z9332f_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-z9332f.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9332f.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9332f.install new file mode 100644 index 000000000000..9915b08b72ee --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9332f.install @@ -0,0 +1,11 @@ +z9332f/scripts/z9332f_platform.sh usr/local/bin +z9332f/scripts/platform_sensors.py usr/local/bin +z9332f/scripts/sensors usr/bin +z9332f/cfg/z9332f-modules.conf etc/modules-load.d +z9332f/systemd/platform-modules-z9332f.service etc/systemd/system +z9332f/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-dellemc_z9332f_d1508-r0 +z9332f/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-dellemc_z9332f_d1508-r0 +common/platform_reboot usr/share/sonic/device/x86_64-dellemc_z9332f_d1508-r0 +common/pcisysfs.py usr/bin +common/fw-updater usr/local/bin +common/onie_mode_set usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9332f.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9332f.postinst new file mode 100644 index 000000000000..3a3a72cb304a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9332f.postinst @@ -0,0 +1,10 @@ +# postinst script for Z9332f + +# Enable Dell-Z9332f-platform-service +depmod -a +systemctl enable platform-modules-z9332f.service +systemctl start platform-modules-z9332f.service + + +#DEBHELPER# + diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/rules b/platform/broadcom/sonic-platform-modules-dell/debian/rules new file mode 100755 index 000000000000..2c16f5561f98 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/rules @@ -0,0 +1,115 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= s6000 z9100 s6100 z9264f s5232f s5248f z9332f s5296f +COMMON_DIR := common + +%: + dh $@ + +override_dh_auto_build: + set -e; \ + (for mod in $(MODULE_DIRS); do \ + if [ $$mod = "s6100" ]; then \ + cp $(COMMON_DIR)/dell_pmc.c $(MOD_SRC_DIR)/$${mod}/modules/dell_s6100_lpc.c; \ + cp $(COMMON_DIR)/dell_ich.c $(MOD_SRC_DIR)/$${mod}/modules/dell_ich.c; \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd $(MOD_SRC_DIR); \ + elif [ $$mod = "z9100" ]; then \ + cp $(COMMON_DIR)/dell_pmc.c $(MOD_SRC_DIR)/$${mod}/modules/dell_mailbox.c; \ + cp $(COMMON_DIR)/dell_ich.c $(MOD_SRC_DIR)/$${mod}/modules/dell_ich.c; \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd $(MOD_SRC_DIR); \ + elif [ $$mod = "s6000" ]; then \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd $(MOD_SRC_DIR); \ + elif [ $$mod = "z9264f" ]; then \ + cp $(COMMON_DIR)/ipmihelper.py $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd $(MOD_SRC_DIR); \ + elif [ $$mod = "s5232f" ]; then \ + cp $(COMMON_DIR)/ipmihelper.py $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd $(MOD_SRC_DIR); \ + elif [ $$mod = "z9332f" ]; then \ + cp $(COMMON_DIR)/ipmihelper.py $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd $(MOD_SRC_DIR); \ + fi; \ + echo "making man page alias $$mod -> $$mod APIs";\ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done); \ + set +e + +override_dh_auto_install: + set -e; \ + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + if [ $$mod = "s6000" ]; then \ + dh_installdirs -pplatform-modules-$${mod} usr/local/bin ; \ + cp -r $(MOD_SRC_DIR)/$${mod}/scripts/* debian/platform-modules-$${mod}/usr/local/bin; \ + fi; \ + done); \ + set +e + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + set -e; \ + (for mod in $(MODULE_DIRS); do \ + if [ $$mod = "s6100" ]; then \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/dell_s6100_lpc.c; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/dell_ich.c; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \ + elif [ $$mod = "z9100" ]; then \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/dell_mailbox.c; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/dell_ich.c; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \ + elif [ $$mod = "s6000" ]; then \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \ + elif [ $$mod = "z9264f" ]; then \ + rm -f $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \ + elif [ $$mod = "s5232f" ]; then \ + rm -f $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \ + elif [ $$mod = "z9332f" ]; then \ + rm -f $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \ + fi; \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done); \ + set +e + diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/cfg/s5232f-modules.conf b/platform/broadcom/sonic-platform-modules-dell/s5232f/cfg/s5232f-modules.conf new file mode 100644 index 000000000000..950162b45f4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/cfg/s5232f-modules.conf @@ -0,0 +1,19 @@ +# /etc/modules: kernel modules to load at boot time. +# +# This file contains the names of kernel modules that should be loaded +# at boot time, one per line. Lines beginning with "#" are ignored. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x + +ipmi_devintf +ipmi_si +dell_s5232f_fpga_ocores +i2c_ocores diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/s5232f/modules/Makefile new file mode 100644 index 000000000000..2aa771f3df1d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_s5232f_fpga_ocores.o + 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 new file mode 100644 index 000000000000..1565d4f5c645 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/modules/dell_s5232f_fpga_ocores.c @@ -0,0 +1,1523 @@ +/* +* 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_i2ccore.c +* @brief This is a driver to interface with Linux Open Cores drivber for FPGA i2c access +* +************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include //siginfo +#include //rcu_read_lock +#include //kernel_version +#include +#include +#include +#include +#include + + +void __iomem * fpga_base_addr = NULL; +void __iomem * fpga_ctl_addr = NULL; + +#define DRIVER_NAME "fpgapci" +#define PCI_NUM_BARS 4 + +#ifdef DEBUG +# define PRINT(fmt, ...) printk(fmt, ##__VA_ARGS__) +#else +# define PRINT(fmt, ...) +#endif + +/* Maximum size of driver buffer (allocated with kalloc()). + * Needed to copy data from user to kernel space, among other + * things. */ +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; + + /* kernels virtual addr. for the mapped BARs */ + void * __iomem bar[PCI_NUM_BARS]; + + /* length of each memory region. Used for error checking. */ + size_t bar_length[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; + + unsigned int irq_first; + unsigned int irq_length; + unsigned int irq_assigned; +}; + +static int use_irq = 1; +module_param(use_irq, int, 0644); +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."); + + +/* Xilinx FPGA PCIE info: */ +/* Non-VGA unclassified device: Xilinx Corporation Device 7021*/ +/* Subsystem: Xilinx Corporation Device 0007 */ +//#define VENDOR 0x10EE +#define DEVICE 0x7021 +static phys_addr_t fpga_phys_addr; + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +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; +}; + +/* global variable declarations */ + +/* Static function declarations */ +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id); +static void fpgapci_remove(struct pci_dev *dev); + +static int scan_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +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; +}; +/* 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_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_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 */ + +enum { + STATE_DONE = 0, + STATE_INIT, + STATE_ADDR, + STATE_ADDR10, + STATE_START, + STATE_WRITE, + STATE_READ, + STATE_STOP, + STATE_ERROR, +}; + +#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 i2c_bus_controller_numb 1 +#define I2C_PCI_MAX_BUS (16) +#define I2C_PCI_MAX_BUS_REV00 (7) +#define DELL_I2C_CLOCK_LEGACY 0 +#define DELL_I2C_CLOCK_PRESERVE (~0U) +#define I2C_PCI_BUS_NUM_5 5 +#define I2C_PCI_BUS_NUM_7 7 +#define I2C_PCI_BUS_NUM_8 8 +#define I2C_PCI_BUS_NUM_10 10 +#define I2C_PCI_BUS_NUM_12 12 +#define I2C_PCI_BUS_NUM_16 16 + +#define MB_BRD_REV_TYPE 0x0008 +#define MB_BRD_REV_MASK 0x00f0 +#define MB_BRD_REV_00 0x0000 +#define MB_BRD_REV_01 0x0010 +#define MB_BRD_REV_02 0x0020 +#define MB_BRD_REV_03 0x0030 +#define MB_BRD_TYPE_MASK 0x000f +#define BRD_TYPE_Z9232_NON_NEBS 0x0 +#define BRD_TYPE_Z9232_NEBS 0x1 +#define BRD_TYPE_Z9264_NON_NEBS 0x2 +#define BRD_TYPE_Z9264_NEBS 0x3 +#define BRD_TYPE_S5212_NON_NEBS 0x4 +#define BRD_TYPE_S5212_NEBS 0x5 +#define BRD_TYPE_S5224_NON_NEBS 0x6 +#define BRD_TYPE_S5224_NEBS 0x7 +#define BRD_TYPE_S5248_NON_NEBS 0x8 +#define BRD_TYPE_S5248_NEBS 0x9 +#define BRD_TYPE_S5296_NON_NEBS 0xa +#define BRD_TYPE_S5296_NEBS 0xb +#define BRD_TYPE_S5232_NON_NEBS 0xc +#define BRD_TYPE_S5232_NEBS 0xd + +#define FPGA_CTL_REG_SIZE 0x6000 +#define MSI_VECTOR_MAP_MASK 0x1f +#define MSI_VECTOR_MAP1 0x58 +#define I2C_CH1_MSI_MAP_VECT_8 0x00000008 +#define I2C_CH2_MSI_MAP_VECT_9 0x00000120 +#define I2C_CH3_MSI_MAP_VECT_10 0x00002800 +#define I2C_CH4_MSI_MAP_VECT_11 0x00058000 +#define I2C_CH5_MSI_MAP_VECT_12 0x00c00000 +#define I2C_CH6_MSI_MAP_VECT_13 0x15000000 +#define MSI_VECTOR_MAP2 0x5c +#define I2C_CH7_MSI_MAP_VECT_14 0x0000000e +#define MSI_VECTOR_MAP3 0x9c +#define I2C_CH8_MSI_MAP_VECT_8 0x00800000 +#define I2C_CH8_MSI_MAP_VECT_16 0x01100000 +#define I2C_CH9_MSI_MAP_VECT_9 0x12000000 +#define I2C_CH9_MSI_MAP_VECT_17 0x24000000 +#define MSI_VECTOR_MAP4 0xa0 +#define I2C_CH10_MSI_MAP_VECT_10 0x0000000a +#define I2C_CH10_MSI_MAP_VECT_18 0x00000012 +#define I2C_CH11_MSI_MAP_VECT_11 0x00000120 +#define I2C_CH11_MSI_MAP_VECT_19 0x00000260 +#define I2C_CH12_MSI_MAP_VECT_12 0x00002800 +#define I2C_CH12_MSI_MAP_VECT_20 0x00005000 +#define I2C_CH13_MSI_MAP_VECT_13 0x00058000 +#define I2C_CH13_MSI_MAP_VECT_21 0x000a8000 +#define I2C_CH14_MSI_MAP_VECT_14 0x00c00000 +#define I2C_CH14_MSI_MAP_VECT_22 0x01600000 +#define I2C_CH15_MSI_MAP_VECT_8 0x10000000 +#define I2C_CH15_MSI_MAP_VECT_23 0x2e000000 +#define MSI_VECTOR_MAP5 0xa4 +#define I2C_CH16_MSI_MAP_VECT_9 0x00000009 +#define I2C_CH16_MSI_MAP_VECT_24 0x00000018 + +#define MSI_VECTOR_REV_00 16 +#define MSI_VECTOR_REV_01 32 + +#define FPGA_MSI_VECTOR_ID_8 8 +#define FPGA_MSI_VECTOR_ID_9 9 +#define FPGA_MSI_VECTOR_ID_10 10 +#define FPGA_MSI_VECTOR_ID_11 11 +#define FPGA_MSI_VECTOR_ID_12 12 +#define FPGA_MSI_VECTOR_ID_13 13 +#define FPGA_MSI_VECTOR_ID_14 14 +#define FPGA_MSI_VECTOR_ID_15 15 /*Note: this is external MSI vector id */ +#define FPGA_MSI_VECTOR_ID_16 16 +#define FPGA_MSI_VECTOR_ID_17 17 +#define FPGA_MSI_VECTOR_ID_18 18 +#define FPGA_MSI_VECTOR_ID_19 19 +#define FPGA_MSI_VECTOR_ID_20 20 +#define FPGA_MSI_VECTOR_ID_21 21 +#define FPGA_MSI_VECTOR_ID_22 22 +#define FPGA_MSI_VECTOR_ID_23 23 +#define FPGA_MSI_VECTOR_ID_24 24 + + + +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 void fpgai2c_reg_set_8(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static void fpgai2c_reg_set_32(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static void fpgai2c_reg_set_32be(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static inline u8 fpgai2c_reg_get_16(struct fpgalogic_i2c *i2c, int reg) +{ + 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)); +} + +static inline u8 fpgai2c_reg_get_16be(struct fpgalogic_i2c *i2c, int reg) +{ + 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)); +} + +static inline void fpgai2c_reg_set(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + i2c->reg_set(i2c, reg, value); + udelay(100); +} + +static inline u8 fpgai2c_reg_get(struct fpgalogic_i2c *i2c, int reg) +{ + udelay(100); + return i2c->reg_get(i2c, reg); +} + +static void fpgai2c_dump(struct fpgalogic_i2c *i2c) +{ + u8 tmp; + + 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_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_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); +} + +static void fpgai2c_stop(struct fpgalogic_i2c *i2c) +{ + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP); +} + +/* + * dell_get_mutex must be called prior to calling this function. + */ +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; + } + + /* 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); + + 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); + + 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 (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); + } + + return 0; +} + +static void fpgai2c_process(struct fpgalogic_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + u8 stat = fpgai2c_reg_get(i2c, FPGAI2C_REG_STATUS); + + PRINT("fpgai2c_process in. status reg :0x%x\n", stat); + + 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); + 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; + } + + + /* error? */ + if (stat & FPGAI2C_REG_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + PRINT("fpgai2c_process FPGAI2C_REG_STAT_ARBLOST FPGAI2C_REG_CMD_STOP\n"); + fpgai2c_stop(i2c); + return; + } + + 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_stop(i2c); + return; + } + } else + { + msg->buf[i2c->pos++] = fpgai2c_reg_get(i2c, FPGAI2C_REG_DATA); + } + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { /* end? */ + /* send start? */ + if (!(msg->flags & I2C_M_NOSTART)) { + + u8 addr = (msg->addr << 1); + + if (msg->flags & I2C_M_RD) + addr |= 1; + + i2c->state = STATE_START; + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, addr); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + return; + } else + { + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } + } else { + i2c->state = STATE_STOP; + fpgai2c_stop(i2c); + return; + } + } + + 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); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, i2c->pos == (msg->len-1) ? + 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++]); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE); + } +} + +static irqreturn_t fpgai2c_isr(int irq, void *dev_id) +{ + struct fpgalogic_i2c *i2c = dev_id; + fpgai2c_process(i2c); + + return IRQ_HANDLED; +} +void dell_get_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_lock(&i2c->lock); +} + +/** + * dell_release_mutex - release mutex + */ +void dell_release_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_unlock(&i2c->lock); +} + +static int fpgai2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct fpgalogic_i2c *i2c = i2c_get_adapdata(adap); + int ret; + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = (use_irq == 1) ? STATE_START : STATE_INIT; + + PRINT("i2c->msg->addr = 0x%x i2c->msg->flags = 0x%x\n",i2c->msg->addr,i2c->msg->flags); + PRINT("I2C_M_RD = 0x%x i2c->msg->addr << 1 = 0x%x\n",I2C_M_RD,i2c->msg->addr << 1); + + if (!use_irq) { + /* Handle the transfer */ + while (time_before(jiffies, timeout)) { + dell_get_mutex(i2c); + ret = fpgai2c_poll(i2c); + dell_release_mutex(i2c); + + if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) + return (i2c->state == STATE_DONE) ? num : ret; + + if (ret == 0) + timeout = jiffies + HZ; + + usleep_range(5, 15); + } + + i2c->state = STATE_ERROR; + + return -ETIMEDOUT; + + + } 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)); + + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, + (i2c->msg->addr << 1) | + ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + + /* Interrupt mode */ + if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || + (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; + } + } + + 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; + } + + fpgai2c_reg_set(i2c, FPGAI2C_REG_PRELOW, prescale & 0xff); + fpgai2c_reg_set(i2c, FPGAI2C_REG_PREHIGH, prescale >> 8); + + /* Init the device */ + 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_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK); + 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; +} + +static const struct i2c_algorithm fpgai2c_algorithm = { + .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; +} + +static int i2c_init_internal_data(void) +{ + 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; +} + + +static int i2c_pci_init (void) +{ + int i; + + if (num_bus == 0) { + board_rev_type = ioread32(fpga_ctl_addr + MB_BRD_REV_TYPE); + + 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)) { + switch (board_rev_type & MB_BRD_TYPE_MASK){ + case BRD_TYPE_S5212_NON_NEBS: + case BRD_TYPE_S5212_NEBS: + num_bus = I2C_PCI_BUS_NUM_5; + break; + case BRD_TYPE_S5224_NON_NEBS: + case BRD_TYPE_S5224_NEBS: + num_bus = I2C_PCI_BUS_NUM_7; + break; + case BRD_TYPE_Z9232_NON_NEBS: + case BRD_TYPE_Z9232_NEBS: + case BRD_TYPE_S5232_NON_NEBS: + case BRD_TYPE_S5232_NEBS: + num_bus = I2C_PCI_BUS_NUM_8; + break; + case BRD_TYPE_S5248_NON_NEBS: + case BRD_TYPE_S5248_NEBS: + num_bus = I2C_PCI_BUS_NUM_10; + break; + case BRD_TYPE_Z9264_NON_NEBS: + case BRD_TYPE_Z9264_NEBS: + num_bus = I2C_PCI_BUS_NUM_12; + break; + case BRD_TYPE_S5296_NON_NEBS: + case BRD_TYPE_S5296_NEBS: + num_bus = I2C_PCI_BUS_NUM_16; + break; + default: + num_bus = I2C_PCI_BUS_NUM_16; + printk("Wrong BRD_TYPE: 0x%x\n", board_rev_type); + break; + } + } else { + printk("unknown board_rev_type 0x%x\n", board_rev_type); + num_bus = I2C_PCI_BUS_NUM_8; + } + } + + 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]); + + /* Initialize driver's itnernal data structures */ + i2c_init_internal_data(); + + 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].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)); + } + + 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]); + } + +} + +/* Find upstream PCIe root node. + * 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; + } +} + + +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); + } + } + + return 0; +} + + +/** + * Map the device memory regions into kernel virtual address space + * after verifying their sizes respect the minimum sizes needed, given + * by the bar_min_len[] array. + */ +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + 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; + + + 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; + } + + 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); + + 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); + + 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; +} + +static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + int i; + + 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" + +/** + * @brief Register specific function with msi interrupt line + * @param dev Pointer to pci-device, which should be allocated + * @param int interrupt number relative to global interrupt number + * @return Returns error code or zero if success + * */ +static int register_intr_handler(struct pci_dev *dev, int irq_num_id) +{ + 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; + } + + 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 + * with flag IRQF_SHARED */ + switch(irq_num_id) { + 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 */ + switch (irq_num_id) { + 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; +} +/* Mask for MSI Multi message enable bits */ +#define MSI_MME 0x70 +/** + * These enums define the type of interrupt scheme that the overall + * system uses. + */ +enum fpga_irq_type { + INT_MSI_SINGLE, + INT_MSI_MULTI, + INT_MSIX, + INT_NONE, + INT_FENCE /* Last item to guard from loop run-overs */ +}; +/** + * @def PCI_DEVICE_STATUS + * define the offset for STS register + * from the start of PCI config space as specified in the + * NVME_Comliance 1.0b. offset 06h:STS - Device status. + * This register has error status for NVME PCI Exress + * Card. After reading data from this reagister, the driver + * will identify if any error is set during the operation and + * report as kernel alert message. + */ +#define PCI_DEVICE_STATUS 0x6 +/** + * @def NEXT_MASK + * This indicates the location of the next capability item + * in the list. + */ +#define NEXT_MASK 0xFF00 +/** + * @def MSIXCAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSIXCAP_ID 0x11 +/** + * @def MSICAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSICAP_ID 0x5 + +/** + * @def CL_MASK + * This bit position indicates Capabilities List of the controller + * The controller should support the PCI Power Management cap as a + * minimum. + */ +#define CL_MASK 0x0010 + +/** + * @def CAP_REG + * Set to offset defined in NVME Spec 1.0b. + */ +#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; + + 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; + + + /* + * 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); + + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + } +} +/** + * @brief Enables pcie-device and claims/remaps neccessary bar resources + * @param dev Pointer to pci-device, which should be allocated + * @return Returns error code or zero if success + * */ +static int fpgapci_setup_device(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + 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; + } + + /* 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); + + /* 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); + + if (map_bars(fpgapci, dev)) { + goto fail_map_bars; + } + + i2c_pci_init(); + + return 0; + /* ERROR HANDLING */ +fail_map_bars: + pci_release_regions(dev); +error_pci_req: + pci_disable_device(dev); +error_pci_en: + return -ENODEV; +} + +static int fpgapci_configure_msi(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + int err = 0, i; + int request_vec; + + 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); + + 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)) { + if (err < MSI_VECTOR_REV_01) { + goto error_disable_msi; + } + } + } + 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; + } + } + + 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); + 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); +error_no_msi: + return -ENOSPC; +} + +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct fpgapci_dev *fpgapci = 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)); +#endif + fpgapci = kzalloc(sizeof(struct fpgapci_dev), GFP_KERNEL); + + if (!fpgapci) { + PRINT( "Couldn't allocate memory!\n"); + goto fail_kzalloc; + } + + fpgapci->pci_dev = dev; + dev_set_drvdata(&dev->dev, (void*)fpgapci); + + + fpgapci->upstream = find_upstream_dev (dev); + + if(fpgapci_setup_device(fpgapci,dev)) { + goto error_no_device; + } + + printk("%s:MSI-irq disabled \n", __FUNCTION__); + if (use_irq) { + printk("%s:MSI-irq enabled\n", __FUNCTION__); + if(fpgapci_configure_msi(fpgapci,dev)) { + goto error_cannot_configure; + } + } + + + return 0; + /* ERROR HANDLING */ +error_cannot_configure: + 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"); +fail_kzalloc: + 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); + 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]); + } + } + pci_disable_msi(fpgapci->pci_dev); + free_bars (fpgapci, dev); + pci_disable_device(dev); + pci_release_regions(dev); + + kfree (fpgapci); +} + +static const struct pci_device_id fpgapci_ids[] = { + {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 */ +}; + +/* Initialize the driver module (but not any device) and register + * the module with the kernel PCI subsystem. */ +static int __init fpgapci_init(void) +{ + + if (pci_register_driver(&fpgapci_driver)) { + PRINT("pci_unregister_driver\n"); + pci_unregister_driver(&fpgapci_driver); + return -ENODEV; + } + + return 0; +} + +static void __exit fpgapci_exit(void) +{ + PRINT ("fpgapci_exit"); + + /* unregister this driver from the PCI bus driver */ + pci_unregister_driver(&fpgapci_driver); + +} + + +module_init (fpgapci_init); +module_exit (fpgapci_exit); +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/check_qsfp.sh b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/check_qsfp.sh new file mode 100755 index 000000000000..ebf2b600ddd6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/check_qsfp.sh @@ -0,0 +1,3 @@ +# Temporary dummy file for s5232f. +# Will be updated soon. + 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 new file mode 100755 index 000000000000..5db98374039d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/platform_sensors.py @@ -0,0 +1,333 @@ +#!/usr/bin/python3 +# On S5232F, the BaseBoard Management Controller is an +# autonomous subsystem provides monitoring and management +# facility independent of the host CPU. IPMI standard +# protocol is used with ipmitool to fetch sensor details. +# Current script support X00 board only. X01 support will +# be added soon. This provies support for the +# following objects: +# * Onboard temperature sensors +# * FAN trays +# * PSU + + +import sys +import logging + +S5232F_MAX_FAN_TRAYS = 4 +S5232F_MAX_PSUS = 2 +IPMI_SENSOR_DATA = "ipmitool sdr list" +IPMI_SENSOR_DUMP = "/tmp/sdr" + +PSU_PRESENCE = "PSU{0}_stat" +# Use this for older firmware +# PSU_PRESENCE="PSU{0}_prsnt" + +IPMI_FAN_PRESENCE = "ipmitool sensor get FAN{0}_prsnt" +IPMI_PSU1_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x31 | awk '{print substr($0,9,1)}'" +IPMI_PSU2_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x32 | awk '{print substr($0,9,1)}'" +IPMI_RAW_STORAGE_READ = "ipmitool raw 0x0a 0x11 {0} 0 0 0xa0" +IPMI_FRU = "ipmitool fru" +ipmi_sdr_list = "" + +# Dump sensor registers + + +def ipmi_sensor_dump(): + + status = 1 + global ipmi_sdr_list + ipmi_cmd = IPMI_SENSOR_DATA + status, ipmi_sdr_list = subprocess.getstatusoutput(ipmi_cmd) + + if status: + logging.error('Failed to execute: ' + ipmi_sdr_list) + sys.exit(0) + +# Fetch a Fan Status + +def get_fan_status(fan_id): + ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_FAN_PRESENCE.format(fan_id)) + if ret_status: + logging.error('Failed to execute : %s' % IPMI_FAN_PRESENCE.format(fan_id)) + sys.exit(0) + return(' ' + ipmi_cmd_ret.splitlines()[5].strip(' ').strip('[]')) + +# Fetch a BMC register + + +def get_pmc_register(reg_name): + + output = None + for item in ipmi_sdr_list.split("\n"): + if reg_name in item: + output = item.strip() + + if output is None: + print('\nFailed to fetch: ' + reg_name + ' sensor ') + sys.exit(0) + + output = output.split('|')[1] + + logging.basicConfig(level=logging.DEBUG) + return output + +# Fetch FRU Data for given fruid +def get_psu_airflow(psu_id): + fru_id = 'PSU' + str(psu_id) + '_fru' + ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_FRU) + if ret_status: + logging.error('Failed to execute ipmitool: ' + IPMI_FRU) + sys.exit(0) + found_fru = False + for line in ipmi_cmd_ret.splitlines(): + if line.startswith('FRU Device Description') and fru_id in line.split(':')[1]: + found_fru = True + if found_fru and line.startswith(' Board Product '): + return 'Intake' if 'PS/IO' in line else 'Exhaust' + return '' + +# Fetch FRU on given offset +def fetch_raw_fru(dev_id, offset): + ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_RAW_STORAGE_READ.format(dev_id)) + if ret_status: + logging.error('Failed to execute ipmitool :' + IPMI_RAW_STORAGE_READ.format(dev_id)) + sys.exit(0) + return int((ipmi_cmd_ret.splitlines()[offset//16]).split(' ')[(offset%16+1)]) + + +def get_fan_airflow(fan_id): + Airflow_Direction = ['Exhaust', 'Intake'] + return Airflow_Direction[fetch_raw_fru(fan_id+2, 0x46)] + +# Print the information for temperature sensors +def print_temperature_sensors(): + + print("\nOnboard Temperature Sensors:") + + print(' PT_Left_temp: ', + get_pmc_register('PT_Left_temp')) + print(' PT_Mid_temp: ', + get_pmc_register('PT_Mid_temp')) + print(' PT_Right_temp: ', + get_pmc_register('PT_Right_temp')) + print(' Broadcom Temp: ', + get_pmc_register('NPU_Near_temp')) + print(' Inlet Airflow Temp: ', + get_pmc_register('ILET_AF_temp')) + print(' CPU Temp: ', + get_pmc_register('CPU_temp')) + +subprocess.getstatusoutput('echo 0 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us') +ipmi_sensor_dump() + +print_temperature_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(tray): + + Fan_Status = [' Normal', ' Abnormal'] + + print(' Fan Tray ' + str(tray) + ':') + + if (tray == 1): + + fan1_status = int(get_pmc_register('FAN1_Front_stat'), 16) + fan2_status = int(get_pmc_register('FAN1_Rear_stat'), 16) + + print(' Fan1 Speed: ', + get_pmc_register('FAN1_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN1_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + elif (tray == 2): + + fan1_status = int(get_pmc_register('FAN2_Front_stat'), 16) + fan2_status = int(get_pmc_register('FAN2_Rear_stat'), 16) + + print(' Fan1 Speed: ', + get_pmc_register('FAN2_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN2_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + elif (tray == 3): + + fan1_status = int(get_pmc_register('FAN3_Front_stat'), 16) + fan2_status = int(get_pmc_register('FAN3_Rear_stat'), 16) + + print(' Fan1 Speed: ', + get_pmc_register('FAN3_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN3_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + elif (tray == 4): + + fan1_status = int(get_pmc_register('FAN4_Front_stat'), 16) + fan2_status = int(get_pmc_register('FAN4_Rear_stat'), 16) + + print(' Fan1 Speed: ', + get_pmc_register('FAN4_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN4_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + print(' Airflow: ', + get_fan_airflow(tray)) + + +print('\nFan Trays:') + +for tray in range(1, S5232F_MAX_FAN_TRAYS + 1): + if (get_fan_status(tray) == ' Present'): + print_fan_tray(tray) + else: + 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 = subprocess.getstatusoutput(IPMI_PSU1_DATA_DOCKER) + elif index == 2: + ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_PSU2_DATA_DOCKER) + + if ret_status: + logging.error('Failed to execute ipmitool :' + IPMI_PSU1_DATA_DOCKER) + sys.exit(0) + + psu_status = ipmi_cmd_ret + return (int(psu_status, 16) & 1) + + def get_psu_status(index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :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 = subprocess.getstatusoutput(IPMI_PSU1_DATA_DOCKER) + elif index == 2: + ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_PSU2_DATA_DOCKER) + + if ret_status: + logging.error('Failed to execute ipmitool : ' + IPMI_PSU2_DATA_DOCKER) + sys.exit(0) + + psu_status = ipmi_cmd_ret + + return (not int(psu_status, 16) > 1) + + +# Print the information for PSU1, PSU2 +def print_psu(psu): + Psu_Type = ['Normal', 'Mismatch'] + Psu_Input_Type = ['AC', 'DC'] + PSU_STATUS_TYPE_BIT = 4 + PSU_STATUS_INPUT_TYPE_BIT = 1 + PSU_FAN_PRESENT_BIT = 2 + PSU_FAN_STATUS_BIT = 1 + PSU_FAN_AIR_FLOW_BIT = 0 + Psu_Fan_Presence = ['Present', 'Absent'] + Psu_Fan_Status = ['Normal', 'Abnormal'] + + # print ' Input: ', Psu_Input_Type[psu_input_type] + # print ' Type: ', Psu_Type[psu_type] + + # PSU FAN details + if (psu == 1): + + # psu1_fan_status = int(get_pmc_register('PSU1_status'),16) + + print(' PSU1:') + print(' FAN Normal Temperature: ', + get_pmc_register('PSU1_temp')) + print(' FAN AirFlow Temperature: ', + get_pmc_register('PSU1_AF_temp')) + print(' FAN RPM: ', + get_pmc_register('PSU1_rpm')) + # print ' FAN Status: ', Psu_Fan_Status[psu1_fan_status] + + # PSU input & output monitors + print(' Input Voltage: ', + get_pmc_register('PSU1_In_volt')) + print(' Output Voltage: ', + get_pmc_register('PSU1_Out_volt')) + print(' Input Power: ', + get_pmc_register('PSU1_In_watt')) + print(' Output Power: ', + get_pmc_register('PSU1_Out_watt')) + print(' Input Current: ', + get_pmc_register('PSU1_In_amp')) + print(' Output Current: ', + get_pmc_register('PSU1_Out_amp')) + + else: + + # psu2_fan_status = int(get_pmc_register('PSU1_status'),16) + print(' PSU2:') + print(' FAN Normal Temperature: ', + get_pmc_register('PSU2_temp')) + print(' FAN AirFlow Temperature: ', + get_pmc_register('PSU2_AF_temp')) + print(' FAN RPM: ', + get_pmc_register('PSU2_rpm')) + # print ' FAN Status: ', Psu_Fan_Status[psu2_fan_status] + + # PSU input & output monitors + print(' Input Voltage: ', + get_pmc_register('PSU2_In_volt')) + print(' Output Voltage: ', + get_pmc_register('PSU2_Out_volt')) + print(' Input Power: ', + get_pmc_register('PSU2_In_watt')) + print(' Output Power: ', + get_pmc_register('PSU2_Out_watt')) + print(' Input Current: ', + get_pmc_register('PSU2_In_amp')) + print(' Output Current: ', + get_pmc_register('PSU2_Out_amp')) + print(' Airflow: ', + get_psu_airflow(psu)) + + +print('\nPSUs:') +for psu in range(1, S5232F_MAX_PSUS + 1): + #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_psu(psu) + +print('\n Total Power: ', + get_pmc_register('PSU_Total_watt')) + +subprocess.getstatusoutput('echo 1000 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us') diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/qsfp_irq_enable.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/qsfp_irq_enable.py new file mode 100755 index 000000000000..24bc07f041f8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/qsfp_irq_enable.py @@ -0,0 +1,31 @@ +#!/usr/bin/python3 + +try: + import struct + from os import * + from mmap import * + +except ImportError as e: + raise ImportError("%s - required module no found" % str(e)) + +BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" +PORT_START = 0 +PORT_END = 32 + + +def pci_mem_write(mm, offset, data): + mm.seek(offset) + mm.write(struct.pack('I', data)) + + +def pci_set_value(resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = pci_mem_write(mm, offset, val) + mm.close() + close(fd) + return val + +for port_num in range(PORT_START, PORT_END+1): + port_offset = 0x400c + ((port_num) * 16) + pci_set_value(BASE_RES_PATH, 0x30, port_offset) 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 new file mode 100755 index 000000000000..cdb3412b7899 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/s5232f_platform.sh @@ -0,0 +1,234 @@ +#!/bin/bash + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find iSMT" && exit 1 +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + case $1 in + "new_device") echo 24c16 0x50 > /sys/bus/i2c/devices/i2c-${devnum}/$1 + ;; + "delete_device") echo 0x50 > /sys/bus/i2c/devices/i2c-${devnum}/$1 + ;; + *) echo "s5232f_platform: sys_eeprom : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs +switch_board_qsfp_mux() { + case $1 in + "new_device") + for ((i=603;i<=607;i++)); + do + echo "Attaching PCA9548 @ 0x74" + echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-$i/$1 + done + + ;; + "delete_device") + for ((i=603;i<=607;i++)); + do + echo "Detaching PCA9548 @ 0x74" + echo 0x74 > /sys/bus/i2c/devices/i2c-$i/$1 + done + + ;; + *) echo "s5232f_platform: switch_board_qsfp_mux: invalid command !" + ;; + esac + sleep 2 +} + +#Attach/Detach 32 instances of EEPROM driver QSFP ports +#eeprom can dump data using below command +switch_board_qsfp() { + case $1 in + "new_device") + for ((i=2;i<=33;i++)); + do + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=2;i<=33;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "s5232f_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +#Attach 2 instances of EEPROM driver SFP ports +switch_board_sfp() { + case $1 in + "new_device") + for ((i=34;i<=35;i++)); + do + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=34;i<=35;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "s5232f_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +#Modsel 64 ports to applicable QSFP type modules +#This enables the adapter to respond for i2c commands +switch_board_modsel() { + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + for ((i=1;i<=64;i++)); + do + port_addr=$(( 16384 + ((i - 1) * 16))) + hex=$( printf "0x%x" $port_addr ) + /usr/bin/pcisysfs.py --set --offset $hex --val 0x10 --res $resource > /dev/null 2>&1 + done +} + +#This enables the led control for CPU and default states +switch_board_led_default() { + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + /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 + +} + +install_python_api_package() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip install $device/$platform/sonic_platform-1.0-py2-none-any.whl) + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) +} + +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) + fi + + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -eq 0 ]; then + rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null) + fi +} + +get_reboot_cause() { + REBOOT_REASON_FILE="/host/reboot-cause/platform/reboot_reason" + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + + mkdir -p $(dirname $REBOOT_REASON_FILE) + + # Handle First Boot into software version with reboot cause determination support + if [[ ! -e $REBOOT_REASON_FILE ]]; then + echo "0" > $REBOOT_REASON_FILE + else + /usr/bin/pcisysfs.py --get --offset 0x18 --res $resource | sed '1d; s/.*:\(.*\)$/\1/;' > $REBOOT_REASON_FILE + fi + /usr/bin/pcisysfs.py --set --val 0x0 --offset 0x18 --res $resource +} + +get_reboot_cause() { + REBOOT_REASON_FILE="/host/reboot-cause/platform/reboot_reason" + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + + mkdir -p $(dirname $REBOOT_REASON_FILE) + + # Handle First Boot into software version with reboot cause determination support + if [[ ! -e $REBOOT_REASON_FILE ]]; then + echo "0" > $REBOOT_REASON_FILE + else + /usr/bin/pcisysfs.py --get --offset 0x18 --res $resource | sed '1d; s/.*:\(.*\)$/\1/;' > $REBOOT_REASON_FILE + fi + /usr/bin/pcisysfs.py --set --val 0x0 --offset 0x18 --res $resource +} + +init_devnum + +if [ "$1" == "init" ]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe ipmi_devintf + modprobe ipmi_si kipmid_max_busy_us=1000 + modprobe i2c_ocores + modprobe dell_s5232f_fpga_ocores + sys_eeprom "new_device" + get_reboot_cause + switch_board_qsfp_mux "new_device" + switch_board_qsfp "new_device" + switch_board_sfp "new_device" + switch_board_modsel + switch_board_led_default + install_python_api_package + /usr/bin/qsfp_irq_enable.py + platform_firmware_versions + echo 1000 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us + +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 + modprobe -r i2c-dev + remove_python_api_package + modprobe -r ipmi_devintf + modprobe -r ipmi_si +else + echo "s5232f_platform : Invalid option !" +fi + diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/sensors new file mode 100755 index 000000000000..ee53f2b0f325 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/scripts/sensors @@ -0,0 +1,8 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" +docker exec -i pmon /usr/bin/platform_sensors.py "$@" + +#To probe sensors not part of lm-sensors +#if [ -r /usr/local/bin/platform_sensors.py ]; then +# python /usr/local/bin/platform_sensors.py +#fi diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/setup.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/setup.py new file mode 120000 index 000000000000..4f6de9941d96 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/setup.py @@ -0,0 +1 @@ +../s6100/setup.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/__init__.py new file mode 100644 index 000000000000..4f5d4f6e473d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer"] +from sonic_platform import * diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/chassis.py new file mode 100644 index 000000000000..356e69526d89 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/chassis.py @@ -0,0 +1,260 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC S5232F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +from __future__ import division + +try: + import sys + import time + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.eeprom import Eeprom + from sonic_platform.component import Component + from sonic_platform.psu import Psu + from sonic_platform.thermal import Thermal + from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.watchdog import Watchdog +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MAX_S5232F_COMPONENT = 6 # BIOS,BMC,FPGA,SYSTEM CPLD,2 SLAVE CPLDs +MAX_S5232F_FANTRAY =4 +MAX_S5232F_FAN = 2 +MAX_S5232F_PSU = 2 +MAX_S5232F_THERMAL = 8 + + +class Chassis(ChassisBase): + """ + DELLEMC Platform-specific Chassis class + """ + + oir_fd = -1 + epoll = -1 + + _global_port_pres_dict = {} + + def __init__(self): + ChassisBase.__init__(self) + # sfp.py will read eeprom contents and retrive the eeprom data. + # We pass the eeprom path from chassis.py + self.PORT_START = 1 + self.PORT_END = 34 + self.PORTS_IN_BLOCK = (self.PORT_END + 1) + _sfp_port = list(range(33, self.PORT_END + 1)) + eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for index in range(self.PORT_START, self.PORTS_IN_BLOCK): + port_num = index + 1 + eeprom_path = eeprom_base.format(port_num) + if index not in _sfp_port: + sfp_node = Sfp(index, 'QSFP', eeprom_path) + else: + sfp_node = Sfp(index, 'SFP', eeprom_path) + self._sfp_list.append(sfp_node) + + self._eeprom = Eeprom() + self._watchdog = Watchdog() + for i in range(MAX_S5232F_FANTRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + self._num_sfps = self.PORT_END + self._num_fans = MAX_S5232F_FANTRAY * MAX_S5232F_FAN + self._psu_list = [Psu(i) for i in range(MAX_S5232F_PSU)] + self._thermal_list = [Thermal(i) for i in range(MAX_S5232F_THERMAL)] + self._component_list = [Component(i) for i in range(MAX_S5232F_COMPONENT)] + + for port_num in range(self.PORT_START, self.PORTS_IN_BLOCK): + # sfp get uses zero-indexing, but port numbers start from 1 + presence = self.get_sfp(port_num).get_presence() + self._global_port_pres_dict[port_num] = '1' if presence else '0' + + def __del__(self): + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + +# check for this event change for sfp / do we need to handle timeout/sleep + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + """ + start_ms = time.time() * 1000 + port_dict = {} + change_dict = {} + change_dict['sfp'] = port_dict + while True: + time.sleep(0.5) + for port_num in range(self.PORT_START, (self.PORT_END + 1)): + presence = self.get_sfp(port_num).get_presence() + if(presence and self._global_port_pres_dict[port_num] == '0'): + self._global_port_pres_dict[port_num] = '1' + port_dict[port_num] = '1' + elif(not presence and + self._global_port_pres_dict[port_num] == '1'): + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + + if(len(port_dict) > 0): + return True, change_dict + + if timeout: + now_ms = time.time() * 1000 + if (now_ms - start_ms >= timeout): + return True, change_dict + + def get_sfp(self, index): + """ + Retrieves sfp represented by (0-based) index + + Args: + index: An integer, the index (0-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 0. + For example, 0 for Ethernet0, 1 for Ethernet4 and so on. + + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + + try: + # The index will start from 0 + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + return sfp + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr('') + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_eeprom(self): + """ + Retrieves the Sys Eeprom instance for the chassis. + Returns : + The instance of the Sys Eeprom + """ + return self._eeprom + + def get_num_fans(self): + """ + Retrives the number of Fans on the chassis. + Returns : + An integer represents the number of Fans on the chassis. + """ + return self._num_fans + + def get_num_sfps(self): + """ + Retrives the numnber of Media on the chassis. + Returns: + An integer represences the number of SFPs on the chassis. + """ + return self._num_sfps + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + try: + with open(self.REBOOT_CAUSE_PATH) as fd: + reboot_cause = int(fd.read(), 16) + except EnvironmentError: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + if reboot_cause & 0x1: + return (self.REBOOT_CAUSE_POWER_LOSS, None) + elif reboot_cause & 0x2: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + elif reboot_cause & 0x4: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "PSU Shutdown") + elif reboot_cause & 0x8: + return (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, None) + elif reboot_cause & 0x10: + return (self.REBOOT_CAUSE_WATCHDOG, None) + elif reboot_cause & 0x20: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "BMC Shutdown") + elif reboot_cause & 0x40: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Hot-Swap Shutdown") + elif reboot_cause & 0x80: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Shutdown") + elif reboot_cause & 0x100: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Cold Reboot") + else: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/component.py new file mode 100644 index 000000000000..f7fcc94662c1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/component.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC S5232F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, BMC etc.) available in +# the platform +# +######################################################################## + +try: + import subprocess + from sonic_platform_base.component_base import ComponentBase + import sonic_platform.hwaccess as hwaccess + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +def get_bios_version(): + return subprocess.check_output(['dmidecode', '-s', 'system-version']).decode('utf-8').strip() + +def get_fpga_version(): + val = hwaccess.pci_get_value('/sys/bus/pci/devices/0000:04:00.0/resource0', 0) + return '{}.{}'.format((val >> 8) & 0xff, val & 0xff) + +def get_bmc_version(): + return subprocess.check_output( + ['cat', '/sys/class/ipmi/ipmi0/device/bmc/firmware_revision'] + ).decode('utf-8').strip() + +def get_cpld_version(bus, i2caddr): + return '{}.{}'.format(hwaccess.i2c_get(bus, i2caddr, 1), + hwaccess.i2c_get(bus, i2caddr, 0) + ) + +def get_cpld0_version(): + return get_cpld_version(601, 0x31) + +def get_cpld1_version(): + return get_cpld_version(600, 0x30) + +def get_cpld2_version(): + return get_cpld_version(600, 0x31) + + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + CHASSIS_COMPONENTS = [ + ['BIOS', + 'Performs initialization of hardware components during booting', + get_bios_version + ], + + ['FPGA', + 'Used for managing the system LEDs', + get_fpga_version + ], + + ['BMC', + 'Platform management controller for on-board temperature monitoring, in-chassis power, Fan and LED control', + get_bmc_version + ], + + ['System CPLD', + 'Used for managing the CPU power sequence and CPU states', + get_cpld0_version + ], + + ['Slave CPLD 1', + 'Used for managing SFP28/QSFP28 port transceivers (SFP28 1-24, QSFP28 1-4)', + get_cpld1_version + ], + + ['Slave CPLD 2', + 'Used for managing SFP28/QSFP28 port transceivers (SFP28 25-48, QSFP28 5-8)', + get_cpld2_version + ] + + ] + + def __init__(self, component_index = 0): + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + self.version = self.CHASSIS_COMPONENTS[self.index][2]() + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + return self.version + + def install_firmware(self, image_path): + """ + Installs firmware to the component + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/eeprom.py new file mode 100644 index 000000000000..bf3434733f36 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/eeprom.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python + +############################################################################# +# DellEmc S5248F +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# +try: + import os.path + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.eeprom_path = None + for b in (0, 1): + f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b) + if os.path.exists(f): + self.eeprom_path = f + break + if self.eeprom_path is None: + return + super(Eeprom, self).__init__(self.eeprom_path, 0, '', True) + self.eeprom_tlv_dict = dict() + try: + self.eeprom_data = self.read_eeprom() + except: + self.eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + + eeprom = self.eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % tlv[0] + + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + """ + Returns the serial number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self, e): + """ + Returns the base mac address found in the system EEPROM + """ + (is_valid, t) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(eeprom_tlvinfo.TlvInfoDecoder, self).switchaddrstr(t) + + return ":".join(["{:02x}".format(T) for T in t[2]]).upper() + + def modelstr(self): + """ + Returns the Model name + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + """ + Returns the part number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_str(self): + """ + Returns the servicetag number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + """ + Returns the device revision + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/fan.py new file mode 100644 index 000000000000..1b624cb76eda --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/fan.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S5232F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fans' information which are available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_base import FanBase + from sonic_platform.ipmihelper import IpmiSensor, IpmiFru +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN1_MAX_SPEED_OFFSET = 71 +FAN2_MAX_SPEED_OFFSET = 73 +PSU_FAN_MAX_SPEED_OFFSET = 50 +FAN_DIRECTION_OFFSET = 69 +PSU_FAN_DIRECTION_OFFSET = 47 + + +class Fan(FanBase): + """DellEMC Platform-specific Fan class""" + # { FAN-ID: { Sensor-Name: Sensor-ID } } + FAN_SENSOR_MAPPING = { 1: {"Prsnt": 0x53, "State": 0x57, "Speed": 0x24}, + 2: {"Prsnt": 0x53, "State": 0x5b, "Speed": 0x20}, + 3: {"Prsnt": 0x54, "State": 0x58, "Speed": 0x25}, + 4: {"Prsnt": 0x54, "State": 0x5c, "Speed": 0x21}, + 5: {"Prsnt": 0x55, "State": 0x59, "Speed": 0x26}, + 6: {"Prsnt": 0x55, "State": 0x5d, "Speed": 0x22}, + 7: {"Prsnt": 0x56, "State": 0x5a, "Speed": 0x27}, + 8: {"Prsnt": 0x56, "State": 0x5e, "Speed": 0x23} } + PSU_FAN_SENSOR_MAPPING = { 1: {"State": 0x31, "Speed": 0x28}, + 2: {"State": 0x32, "Speed": 0x29} } + + # { FANTRAY-ID: FRU-ID } + FAN_FRU_MAPPING = { 1: 3, 2: 4, 3: 5, 4: 6 } + PSU_FRU_MAPPING = { 1: 1, 2: 2 } + + def __init__(self, fantray_index=1, fan_index=1, psu_fan=False, + dependency=None): + self.is_psu_fan = psu_fan + if not self.is_psu_fan: + # API index is starting from 0, DellEMC platform index is + # starting from 1 + self.fantrayindex = fantray_index + 1 + self.fanindex = fan_index + 1 + if (self.fanindex == 1): + self.max_speed_offset = FAN1_MAX_SPEED_OFFSET + else: + self.max_speed_offset = FAN2_MAX_SPEED_OFFSET + self.fan_direction_offset = FAN_DIRECTION_OFFSET + self.index = (self.fantrayindex - 1) * 2 + self.fanindex + self.prsnt_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Prsnt"], + is_discrete=True) + self.state_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["State"], + is_discrete=True) + self.speed_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Speed"]) + self.fru = IpmiFru(self.FAN_FRU_MAPPING[self.fantrayindex]) + else: + self.dependency = dependency + self.fanindex = fan_index + self.state_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["State"], + is_discrete=True) + self.speed_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["Speed"]) + self.fru = IpmiFru(self.PSU_FRU_MAPPING[self.fanindex]) + self.max_speed_offset = PSU_FAN_MAX_SPEED_OFFSET + self.fan_direction_offset = PSU_FAN_DIRECTION_OFFSET + self.max_speed = self.fru.get_fru_data(self.max_speed_offset,2)[1] + self.max_speed = self.max_speed[1] << 8 | self.max_speed[0] + + def get_name(self): + """ + Retrieves the name of the device + Returns: + String: The name of the device + """ + if self.is_psu_fan: + return "PSU{} Fan".format(self.fanindex) + else: + return "FanTray{}-Fan{}".format(self.fantrayindex, self.fanindex) + + def get_model(self): + """ + Retrieves the part number of the FAN + Returns: + String: Part number of FAN + """ + if self.is_psu_fan: + return 'NA' + else: + return self.fru.get_board_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the FAN + Returns: + String: Serial number of FAN + """ + if self.is_psu_fan: + return 'NA' + else: + return self.fru.get_board_serial() + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if fan is present, False if not + """ + presence = False + if self.is_psu_fan: + return self.dependency.get_presence() + else: + is_valid, state = self.prsnt_sensor.get_reading() + if is_valid: + if (state & 0b1): + presence = True + return presence + + def get_status(self): + """ + Retrieves the operational status of the FAN + Returns: + bool: True if FAN is operating properly, False if not + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if not state > 1: + status = True + return status + + def get_direction(self): + """ + Retrieves the fan airfow direction + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + In DellEMC platforms, + - Forward/Exhaust : Air flows from Port side to Fan side. + - Reverse/Intake : Air flows from Fan side to Port side. + """ + direction = [self.FAN_DIRECTION_EXHAUST, self.FAN_DIRECTION_INTAKE] + fan_status = self.get_presence() + if not fan_status: + return 'NA' + is_valid, fan_direction = self.fru.get_fru_data(self.fan_direction_offset) + if is_valid and fan_direction[0] < len(direction): + return direction[fan_direction[0]] + else: + return 'NA' + + def get_speed(self): + """ + Retrieves the speed of the fan + Returns: + int: percentage of the max fan speed + """ + if self.max_speed == 0: + self.max_speed = self.fru.get_fru_data(self.max_speed_offset,2)[1] + self.max_speed = self.max_speed[1] << 8 | self.max_speed[0] + is_valid, fan_speed = self.speed_sensor.get_reading() + if not is_valid or self.max_speed == 0: + speed = 0 + else: + speed = (100 * fan_speed)//self.max_speed + return speed + + def get_speed_rpm(self): + """ + Retrieves the speed of the fan + Returns: + int: percentage of the max fan speed + """ + fan_speed = 0 + is_valid, fan_speed = self.speed_sensor.get_reading() + return fan_speed diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..0fdc80e651ed --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/fan_drawer.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +Z9332F_FANS_PER_FANTRAY = 2 + + +class FanDrawer(FanDrawerBase): + """DellEMC Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + # FanTray is 1-based in DellEMC platforms + self.fantrayindex = fantray_index + 1 + for i in range(Z9332F_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/hwaccess.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/hwaccess.py new file mode 120000 index 000000000000..e8fa340a444d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/hwaccess.py @@ -0,0 +1 @@ +../../common/sonic_platform/hwaccess.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/platform.py new file mode 100644 index 000000000000..996d94cf5a6e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/platform.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """ + DELLEMC Platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/psu.py new file mode 100644 index 000000000000..a7e2add8bd08 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/psu.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S5232F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.ipmihelper import IpmiSensor, IpmiFru + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Psu(PsuBase): + """DellEMC Platform-specific PSU class""" + + # { PSU-ID: { Sensor-Name: Sensor-ID } } + SENSOR_MAPPING = { 1: { "State": 0x31, "Current": 0x39, + "Power": 0x37, "Voltage": 0x38 }, + 2: { "State": 0x32, "Current": 0x3F, + "Power": 0x3D, "Voltage": 0x3E } } + # ( PSU-ID: FRU-ID } + FRU_MAPPING = { 1: 1, 2: 2 } + + def __init__(self, psu_index): + PsuBase.__init__(self) + # PSU is 1-based in DellEMC platforms + self.index = psu_index + 1 + self.state_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["State"], + is_discrete=True) + self.voltage_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Voltage"]) + self.current_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Current"]) + self.power_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Power"]) + self.fru = IpmiFru(self.FRU_MAPPING[self.index]) + + self._fan_list.append(Fan(fan_index=self.index, psu_fan=True, + dependency=self)) + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + presence = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if (state & 0b1): + presence = True + + return presence + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + return self.fru.get_board_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + return self.fru.get_board_serial() + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if (state == 0x01): + status = True + + return status + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + is_valid, voltage = self.voltage_sensor.get_reading() + if not is_valid: + voltage = 0 + + return float(voltage) + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + is_valid, current = self.current_sensor.get_reading() + if not is_valid: + current = 0 + + return float(current) + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + is_valid, power = self.power_sensor.get_reading() + if not is_valid: + power = 0 + + return float(power) + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if (state == 0x01): + status = True + + return status + + def get_mfr_id(self): + """ + Retrives the Manufacturer Id of PSU + + Returns: + A string, the manunfacturer id. + """ + return self.fru.get_board_mfr_id() + + def get_type(self): + """ + Retrives the Power Type of PSU + + Returns : + A string, PSU power type + """ + info = self.fru.get_board_product().split(',') + if 'AC' in info : return 'AC' + if 'DC' in info : return 'DC' + return 'Unknown' diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/sfp.py new file mode 100644 index 000000000000..b2cceab9b08f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/sfp.py @@ -0,0 +1,1045 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import time + import struct + import mmap + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8472 import sffbase + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PAGE_OFFSET = 0 +KEY_OFFSET = 1 +KEY_WIDTH = 2 +FUNC_NAME = 3 + +QSFP_INFO_OFFSET = 128 +QSFP_DOM_OFFSET = 0 +QSFP_DOM_OFFSET1 = 384 + +SFP_INFO_OFFSET = 0 +SFP_DOM_OFFSET = 256 + +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 7 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', + 'Length OM1(m)', 'Length Cable Assembly(m)') + +qsfp_compliance_code_tup = ( + '10/40G Ethernet Compliance Code', + 'SONET Compliance codes', + 'SAS/SATA compliance codes', + 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', + 'Fibre Channel Speed') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthOM3(UnitsOf10m)', 'LengthCable(UnitsOfm)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +info_dict_keys = ['type', 'hardware_rev', 'serial', + 'manufacturer', 'model', 'connector', + 'encoding', 'ext_identifier', 'ext_rateselect_compliance', + 'cable_type', 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'type_abbrv_name','vendor_date', 'vendor_oui'] + +dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', + 'power_lpmode', 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', 'rx1power', + 'rx2power', 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', 'tx3bias', + 'tx4bias', 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + +threshold_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning'] + +sff8436_parser = { + 'reset_status': [QSFP_DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'], + 'rx_los': [QSFP_DOM_OFFSET, 3, 1, 'parse_dom_tx_rx_los'], + 'tx_fault': [QSFP_DOM_OFFSET, 4, 1, 'parse_dom_tx_fault'], + 'tx_disable': [QSFP_DOM_OFFSET, 86, 1, 'parse_dom_tx_disable'], + 'power_lpmode': [QSFP_DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'power_override': [QSFP_DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'Temperature': [QSFP_DOM_OFFSET, 22, 2, 'parse_temperature'], + 'Voltage': [QSFP_DOM_OFFSET, 26, 2, 'parse_voltage'], + 'ChannelMonitor': [QSFP_DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'], + 'ChannelMonitor_TxPower': + [QSFP_DOM_OFFSET, 34, 24, 'parse_channel_monitor_params_with_tx_power'], + + 'cable_type': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'encoding': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_identifier': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'specification_compliance': + [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type_abbrv_name': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'manufacturer': [QSFP_INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [QSFP_INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [QSFP_INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [QSFP_INFO_OFFSET, 56, 2, 'parse_vendor_rev'], + 'serial': [QSFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [QSFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'dom_capability': [QSFP_INFO_OFFSET, 92, 1, 'parse_dom_capability'], + 'dom_rev': [QSFP_DOM_OFFSET, 1, 1, 'parse_sfp_dom_rev'], + 'ModuleThreshold': [QSFP_DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'], + 'ChannelThreshold': [QSFP_DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'], +} + +sff8472_parser = { + 'Temperature': [SFP_DOM_OFFSET, 96, 2, 'parse_temperature'], + 'Voltage': [SFP_DOM_OFFSET, 98, 2, 'parse_voltage'], + 'ChannelMonitor': [SFP_DOM_OFFSET, 100, 6, 'parse_channel_monitor_params'], + + 'cable_type': [SFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [SFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'type': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'encoding': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'ext_identifier': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'specification_compliance': + [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'type_abbrv_name': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'manufacturer': [SFP_INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [SFP_INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [SFP_INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [SFP_INFO_OFFSET, 56, 4, 'parse_vendor_rev'], + 'serial': [SFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [SFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'ModuleThreshold': [SFP_DOM_OFFSET, 0, 56, 'parse_alarm_warning_threshold'], +} + + +class Sfp(SfpBase): + """ + DELLEMC Platform-specific Sfp class + """ + BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" + + def __init__(self, index=0, sfp_type=0, eeprom_path=''): + SfpBase.__init__(self) + self.sfp_type = sfp_type + self.index = index + self.eeprom_path = eeprom_path + self.qsfpInfo = sff8436InterfaceId() + self.qsfpDomInfo = sff8436Dom() + self.sfpInfo = sff8472InterfaceId() + self.sfpDomInfo = sff8472Dom(None,1) + + def pci_mem_read(self, mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + reg_val = struct.unpack('I', read_data_stream) + mem_val = str(reg_val)[1:-2] + # print "reg_val read:%x"%reg_val + return mem_val + + def pci_mem_write(self, mm, offset, data): + mm.seek(offset) + # print "data to write:%x"%data + mm.write(struct.pack('I', data)) + + def pci_set_value(self, resource, val, offset): + fd = os.open(resource, os.O_RDWR) + mm = mmap.mmap(fd, 0) + val = self.pci_mem_write(mm, offset, val) + mm.close() + os.close(fd) + return val + + def pci_get_value(self, resource, offset): + fd = os.open(resource, os.O_RDWR) + mm = mmap.mmap(fd, 0) + val = self.pci_mem_read(mm, offset) + mm.close() + os.close(fd) + return val + + def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes): + eeprom_raw = [] + try: + eeprom = open(eeprom_path, mode="rb", buffering=0) + except IOError: + return None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom.seek(offset) + raw = eeprom.read(num_bytes) + except IOError: + eeprom.close() + return None + + try: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except BaseException: + eeprom.close() + return None + + eeprom.close() + return eeprom_raw + + def _get_eeprom_data(self, eeprom_key): + eeprom_data = None + page_offset = None + + if(self.sfp_type == 'QSFP'): + page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8436_parser[eeprom_key][PAGE_OFFSET] + + sff8436_parser[eeprom_key][KEY_OFFSET]), + sff8436_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 128 is used to retrieve sff8436InterfaceId Info + # Offset 0 is used to retrieve sff8436Dom Info + if (page_offset == 128): + if ( self.qsfpInfo is None): + return None + eeprom_data = getattr( + self.qsfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + if ( self.qsfpDomInfo is None): + return None + eeprom_data = getattr( + self.qsfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + page_offset = sff8472_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8472_parser[eeprom_key][PAGE_OFFSET] + + sff8472_parser[eeprom_key][KEY_OFFSET]), + sff8472_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 0 is used to retrieve sff8472InterfaceId Info + # Offset 256 is used to retrieve sff8472Dom Info + if (page_offset == 0): + if ( self.sfpInfo is None): + return None + eeprom_data = getattr( + self.sfpInfo, sff8472_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + if ( self.sfpDomInfo is None): + return None + eeprom_data = getattr( + self.sfpDomInfo, sff8472_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + + return eeprom_data + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + """ + transceiver_info_dict = {} + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A') + # BaseInformation + iface_data = self._get_eeprom_data('type') + if (iface_data is not None): + connector = iface_data['data']['Connector']['value'] + encoding = iface_data['data']['EncodingCodes']['value'] + ext_id = iface_data['data']['Extended Identifier']['value'] + rate_identifier = iface_data['data']['RateIdentifier']['value'] + identifier = iface_data['data']['type']['value'] + type_abbrv_name=iface_data['data']['type_abbrv_name']['value'] + if(self.sfp_type == 'QSFP'): + bit_rate = str( + iface_data['data']['Nominal Bit Rate(100Mbs)']['value']) + for key in qsfp_compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in qsfp_cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + else: + bit_rate = str( + iface_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + for key in sfp_compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in sfp_cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + else: + return transceiver_info_dict + + # Vendor Date + vendor_date_data = self._get_eeprom_data('vendor_date') + if (vendor_date_data is not None): + vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + else: + return transceiver_info_dict + + # Vendor Name + vendor_name_data = self._get_eeprom_data('manufacturer') + if (vendor_name_data is not None): + vendor_name = vendor_name_data['data']['Vendor Name']['value'] + else: + return transceiver_info_dict + + # Vendor OUI + vendor_oui_data = self._get_eeprom_data('vendor_oui') + if (vendor_oui_data is not None): + vendor_oui = vendor_oui_data['data']['Vendor OUI']['value'] + else: + return transceiver_info_dict + + # Vendor PN + vendor_pn_data = self._get_eeprom_data('model') + if (vendor_pn_data is not None): + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + else: + return transceiver_info_dict + + # Vendor Revision + vendor_rev_data = self._get_eeprom_data('hardware_rev') + if (vendor_rev_data is not None): + vendor_rev = vendor_rev_data['data']['Vendor Rev']['value'] + else: + return transceiver_info_dict + + # Vendor Serial Number + vendor_sn_data = self._get_eeprom_data('serial') + if (vendor_sn_data is not None): + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + else: + return transceiver_info_dict + + # Fill The Dictionary and return + transceiver_info_dict['type'] = identifier + transceiver_info_dict['hardware_rev'] = vendor_rev + transceiver_info_dict['serial'] = vendor_sn + transceiver_info_dict['manufacturer'] = vendor_name + transceiver_info_dict['model'] = vendor_pn + transceiver_info_dict['connector'] = connector + transceiver_info_dict['encoding'] = encoding + transceiver_info_dict['ext_identifier'] = ext_id + transceiver_info_dict['ext_rateselect_compliance'] = rate_identifier + transceiver_info_dict['cable_type'] = cable_type + transceiver_info_dict['cable_length'] = cable_length + transceiver_info_dict['nominal_bit_rate'] = bit_rate + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['vendor_date'] = vendor_date + transceiver_info_dict['vendor_oui'] = vendor_oui + transceiver_info_dict['type_abbrv_name']=type_abbrv_name + + return transceiver_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + """ + transceiver_dom_threshold_dict = {} + transceiver_dom_threshold_dict = dict.fromkeys( + threshold_dict_keys, 'N/A') + + # Module Threshold + module_threshold_data = self._get_eeprom_data('ModuleThreshold') + if (self.sfp_type == 'QSFP'): + # Channel Threshold + channel_threshold_data = self._get_eeprom_data('ChannelThreshold') + + if (channel_threshold_data is not None and module_threshold_data is not None): + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['data']['VccLowWarning']['value'] + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['data']['TxBiasLowWarning']['value'] + + else: + return transceiver_dom_threshold_dict + else: + #SFP + if (module_threshold_data is not None): + #Threshold Data + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['data']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['data']['VoltageLowWarning']['value'] + transceiver_dom_threshold_dict['txbiashighalarm'] = module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = module_threshold_data['data']['BiasLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['txpowerlowalarm'] = module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['txpowerhighwarning'] = module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_dict['txpowerlowwarning'] = module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_dict['rxpowerhighalarm'] = module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = module_threshold_data['data']['RXPowerLowWarning']['value'] + else: + return transceiver_dom_threshold_dict + + return transceiver_dom_threshold_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + """ + tx_bias_list = [] + rx_power_list = [] + transceiver_dom_dict = {} + transceiver_dom_dict = dict.fromkeys(dom_dict_keys, 'N/A') + + # RxLos + rx_los = self.get_rx_los() + + # TxFault + tx_fault = self.get_tx_fault() + + # ResetStatus + reset_state = self.get_reset_status() + + # LowPower Mode + lp_mode = self.get_lpmode() + + # TxDisable + tx_disable = self.get_tx_disable() + + # TxDisable Channel + tx_disable_channel = self.get_tx_disable_channel() + + # Temperature + temperature = self.get_temperature() + + # Voltage + voltage = self.get_voltage() + + # Channel Monitor + tx_power_list = self.get_tx_power() + + # tx bias + tx_bias_list = self.get_tx_bias() + + # rx power + rx_power_list = self.get_rx_power() + + if (len(tx_bias_list) != 0): + transceiver_dom_dict['tx1bias'] = tx_bias_list[0] + transceiver_dom_dict['tx2bias'] = tx_bias_list[1] + transceiver_dom_dict['tx3bias'] = tx_bias_list[2] + transceiver_dom_dict['tx4bias'] = tx_bias_list[3] + + if (len(rx_power_list) != 0): + transceiver_dom_dict['rx1power'] = rx_power_list[0] + transceiver_dom_dict['rx2power'] = rx_power_list[1] + transceiver_dom_dict['rx3power'] = rx_power_list[2] + transceiver_dom_dict['rx4power'] = rx_power_list[3] + + if (len(tx_power_list) != 0): + transceiver_dom_dict['tx1power'] = tx_power_list[0] + transceiver_dom_dict['tx2power'] = tx_power_list[1] + transceiver_dom_dict['tx3power'] = tx_power_list[2] + transceiver_dom_dict['tx4power'] = tx_power_list[3] + + transceiver_dom_dict['rx_los'] = rx_los + transceiver_dom_dict['tx_fault'] = tx_fault + transceiver_dom_dict['reset_status'] = reset_state + transceiver_dom_dict['power_lpmode'] = lp_mode + transceiver_dom_dict['tx_disable'] = tx_disable + transceiver_dom_dict['tx_disable_channel'] = tx_disable_channel + transceiver_dom_dict['temperature'] = temperature + transceiver_dom_dict['voltage'] = voltage + + return transceiver_dom_dict + + def get_name(self): + """ + Retrieves the name of the sfp + Returns : QSFP or QSFP+ or QSFP28 + """ + + iface_data = self._get_eeprom_data('type') + if (iface_data is not None): + identifier = iface_data['data']['type']['value'] + else: + return None + + return identifier + + def get_presence(self): + """ + Retrieves the presence of the sfp + Returns : True if sfp is present and false if it is absent + """ + # Check for invalid port_num + + # Port offset starts with 0x4004 + port_offset = 16388 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + if(self.sfp_type == 'QSFP'): + mask = (1 << 4) + + # Mask off 1st bit for presence 65,66 + if (self.sfp_type == 'SFP'): + mask = (1 << 0) + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the sfp + """ + vendor_pn_data = self._get_eeprom_data('model') + if (vendor_pn_data is not None): + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + else: + return None + + return vendor_pn + + def get_serial(self): + """ + Retrieves the serial number of the sfp + """ + vendor_sn_data = self._get_eeprom_data('serial') + if (vendor_sn_data is not None): + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + else: + return None + + return vendor_sn + + def get_reset_status(self): + """ + Retrives the reset status of SFP + """ + reset_status = False + if (self.sfp_type == 'QSFP'): + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return reset_status + + # Mask off 4th bit for reset status + mask = (1 << 4) + + if ((reg_value & mask) == 0): + reset_status = True + else: + reset_status = False + + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + """ + rx_los = None + rx_los_list = [] + if (self.sfp_type == 'QSFP'): + rx_los_data = self._get_eeprom_data('rx_los') + if (rx_los_data is not None): + rx_los = rx_los_data['data']['Rx1LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx2LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx3LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx4LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + + if (rx_los_list[0] and rx_los_list[1] + and rx_los_list[2] and rx_los_list[3]): + rx_los = True + else: + rx_los = False + else: + rx_los_data = self._read_eeprom_bytes(self.eeprom_path, SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if (rx_los_data is not None): + data = int(rx_los_data[0], 16) + rx_los = (sffbase().test_bit(data, 1) != 0) + + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + """ + tx_fault = None + tx_fault_list = [] + if (self.sfp_type == 'QSFP'): + tx_fault_data = self._get_eeprom_data('tx_fault') + if (tx_fault_data is not None): + tx_fault = tx_fault_data['data']['Tx1Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx2Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx3Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx4Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + + if (tx_fault_list[0] and tx_fault_list[1] + and tx_fault_list[2] and tx_fault_list[3]): + tx_fault = True + else: + tx_fault = False + + else: + tx_fault_data = self._read_eeprom_bytes(self.eeprom_path, SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if (tx_fault_data is not None): + data = int(tx_fault_data[0], 16) + tx_fault = (sffbase().test_bit(data, 2) != 0) + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + """ + tx_disable = None + tx_disable_list = [] + if (self.sfp_type == 'QSFP'): + tx_disable_data = self._get_eeprom_data('tx_disable') + if (tx_disable_data is not None): + tx_disable = tx_disable_data['data']['Tx1Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx2Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx3Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx4Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + + if (tx_disable_list[0] and tx_disable_list[1] + and tx_disable_list[2] and tx_disable_list[3]): + tx_disable = True + else: + tx_disable = False + + else: + tx_disable_data = self._read_eeprom_bytes(self.eeprom_path, SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if (tx_disable_data is not None): + data = int(tx_disable_data[0], 16) + tx_disable_hard = (sffbase().test_bit(data, SFP_TX_DISABLE_HARD_BIT) != 0) + tx_disable_soft = (sffbase().test_bit(data, SFP_TX_DISABLE_SOFT_BIT) != 0) + tx_disable = tx_disable_hard | tx_disable_soft + + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + """ + tx_disable = None + tx_disable_list = [] + tx_disable_channel = 0 + + if (self.sfp_type == 'QSFP'): + tx_disable_data = self._get_eeprom_data('tx_disable') + if (tx_disable_data is not None): + tx_disable = tx_disable_data['data']['Tx1Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + tx_disable = tx_disable_data['data']['Tx2Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + tx_disable = tx_disable_data['data']['Tx3Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + tx_disable = tx_disable_data['data']['Tx4Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + + bit4 = int(tx_disable_list[3]) * 8 + bit3 = int(tx_disable_list[2]) * 4 + bit2 = int(tx_disable_list[1]) * 2 + bit1 = int(tx_disable_list[0]) * 1 + + tx_disable_channel = hex(bit4 + bit3 + bit2 + bit1) + + return tx_disable_channel + + def get_lpmode(self): + """ + Retrieves the lpmode(low power mode) of this SFP + """ + lpmode_state = False + if (self.sfp_type == 'QSFP'): + + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return lpmode_state + + # Mask off 6th bit for lpmode + mask = (1 << 6) + + # LPMode is active high + if reg_value & mask == 0: + lpmode_state = False + else: + lpmode_state = True + + return lpmode_state + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + """ + power_override_state = False + + if (self.sfp_type == 'QSFP'): + power_override_data = self._get_eeprom_data('power_override') + if (power_override_data is not None): + power_override = power_override_data['data']['PowerOverRide']['value'] + if (power_override is 'On'): + power_override_state = True + else: + power_override_state = False + + return power_override_state + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + """ + temperature = None + + temperature_data = self._get_eeprom_data('Temperature') + if (temperature_data is not None): + temperature = temperature_data['data']['Temperature']['value'] + + return temperature + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + """ + voltage = None + + voltage_data = self._get_eeprom_data('Voltage') + if (voltage_data is not None): + voltage = voltage_data['data']['Vcc']['value'] + + return voltage + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + """ + tx_bias = None + tx_bias_list = [] + + tx_bias_data = self._get_eeprom_data('ChannelMonitor') + if (tx_bias_data is not None): + if (self.sfp_type == 'QSFP'): + tx_bias = tx_bias_data['data']['TX1Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = tx_bias_data['data']['TX2Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = tx_bias_data['data']['TX3Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = tx_bias_data['data']['TX4Bias']['value'] + tx_bias_list.append(tx_bias) + else: + tx1_bias = tx_bias_data['data']['TXBias']['value'] + return [tx1_bias, "N/A", "N/A", "N/A"] + + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + """ + rx_power = None + rx_power_list = [] + + rx_power_data = self._get_eeprom_data('ChannelMonitor') + if (rx_power_data is not None): + if (self.sfp_type == 'QSFP'): + rx_power = rx_power_data['data']['RX1Power']['value'] + rx_power_list.append(rx_power) + rx_power = rx_power_data['data']['RX2Power']['value'] + rx_power_list.append(rx_power) + rx_power = rx_power_data['data']['RX3Power']['value'] + rx_power_list.append(rx_power) + rx_power = rx_power_data['data']['RX4Power']['value'] + rx_power_list.append(rx_power) + else: + rx1_pw = rx_power_data['data']['RXPower']['value'] + return [rx1_pw, "N/A", "N/A", "N/A"] + + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + """ + tx_power_list = [] + if(self.sfp_type == 'QSFP'): + # 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. + qspf_dom_capability_data = self._get_eeprom_data('dom_capability') + qsfp_dom_rev_data = self._get_eeprom_data('dom_rev') + if (qspf_dom_capability_data is not None and qsfp_dom_rev_data is not None): + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value'] + else: + return tx_power_list + + # 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. + if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')): + return tx_power_list + else: + channel_monitor_data = self._get_eeprom_data('ChannelMonitor_TxPower') + if (channel_monitor_data is not None): + tx1_pw = channel_monitor_data['data']['TX1Power']['value'] + tx2_pw = channel_monitor_data['data']['TX2Power']['value'] + tx3_pw = channel_monitor_data['data']['TX3Power']['value'] + tx4_pw = channel_monitor_data['data']['TX4Power']['value'] + else: + return tx_power_list + + else: + channel_monitor_data = self._get_eeprom_data('ChannelMonitor') + if (channel_monitor_data is not None): + tx1_pw = channel_monitor_data['data']['TXPower']['value'] + tx2_pw = 'N/A' + tx3_pw = 'N/A' + tx4_pw = 'N/A' + else: + return tx_power_list + + tx_power_list.append(tx1_pw) + tx_power_list.append(tx2_pw) + tx_power_list.append(tx3_pw) + tx_power_list.append(tx4_pw) + + return tx_power_list + + def reset(self): + """ + Reset the SFP and returns all user settings to their default state + """ + if (self.sfp_type == 'QSFP'): + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for reset + mask = (1 << 4) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + # Sleep 1 second to allow it to settle + time.sleep(1) + + reg_value = reg_value | mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + else: + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode(low power mode) of this SFP + """ + if (self.sfp_type == 'QSFP'): + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 6th bit for lowpower mode + mask = (1 << 6) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + else: + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + """ + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + """ + return False + + def get_status(self): + """ + Retrieves the operational status of the device + """ + reset = self.get_reset_status() + + if (reset == True): + status = False + else: + status = True + + return status diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/thermal.py new file mode 100644 index 000000000000..2a6ff8927e0a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/thermal.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S5232F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + from sonic_platform_base.thermal_base import ThermalBase + from sonic_platform.ipmihelper import IpmiSensor +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """DellEMC Platform-specific Thermal class""" + + # [ Sensor-Name, Sensor-ID ] + SENSOR_MAPPING = [ + ['CPU On-board', 0xe], + ['ASIC On-board', 0x2], + ['System Front Left', 0x3], + ['System Front Middle', 0x1], + ['System Front Right', 0x4], + ['Inlet Airflow Sensor', 0x5], + ['PSU1 Airflow Sensor', 0x7], + ['PSU2 Airflow Sensor', 0x8] + ] + + def __init__(self, thermal_index=0): + ThermalBase.__init__(self) + self.index = thermal_index + 1 + self.sensor = IpmiSensor(self.SENSOR_MAPPING[self.index - 1][1]) + + def get_name(self): + """ + Retrieves the name of the thermal + + Returns: + string: The name of the thermal + """ + return self.SENSOR_MAPPING[self.index - 1][0] + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return 'NA' + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + is_valid, temperature = self.sensor.get_reading() + if not is_valid: + temperature = 0 + + return float(temperature) + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + is_valid, high_threshold = self.sensor.get_threshold("UpperNonCritical") + if not is_valid: + return super(Thermal, self).get_high_threshold() + + return float(high_threshold) + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + is_valid, low_threshold = self.sensor.get_threshold("LowerNonRecoverable") + if not is_valid: + low_threshold = 0 + + return float(low_threshold) + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + Returns: + A float number, the high critical threshold temperature of + thermal in Celsius up to nearest thousandth of one degree + Celsius, e.g. 30.125 + """ + is_valid, high_crit_threshold = self.sensor.get_threshold("UpperCritical") + if not is_valid: + return super(Thermal, self).get_high_critical_threshold() + + return float(high_crit_threshold) + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/watchdog.py new file mode 100644 index 000000000000..14485decc896 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/watchdog.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python + +######################################################################## +# +# DELLEMC S5232f +# +# Abstract base class for implementing a platform-specific class with +# which to interact with a hardware watchdog module in SONiC +# +######################################################################## + +try: + import ctypes + import subprocess + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class _timespec(ctypes.Structure): + _fields_ = [ + ('tv_sec', ctypes.c_long), + ('tv_nsec', ctypes.c_long) + ] + + +class Watchdog(WatchdogBase): + """ + Abstract base class for interfacing with a hardware watchdog module + """ + + TIMERS = [15,20,30,40,50,60,65,70] + + armed_time = 0 + timeout = 0 + CLOCK_MONOTONIC = 1 + + def __init__(self): + self._librt = ctypes.CDLL('librt.so.1', use_errno=True) + self._clock_gettime = self._librt.clock_gettime + self._clock_gettime.argtypes=[ctypes.c_int, ctypes.POINTER(_timespec)] + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, universal_newlines=True) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + except OSError: + result = None + + return result + + def _get_reg_val(self): + # 0x31 = CPLD I2C Base Address + # 0x07 = Watchdog Function Register + value = self._get_command_result("/usr/sbin/i2cget -y 601 0x31 0x07") + if not value: + return None + else: + return int(value, 16) + + def _set_reg_val(self,val): + # 0x31 = CPLD I2C Base Address + # 0x07 = Watchdog Function Register + value = self._get_command_result("/usr/sbin/i2cset -y 601 0x31 0x07 %s" + % (val)) + return value + + def _get_time(self): + """ + To get clock monotonic time + """ + ts = _timespec() + if self._clock_gettime(self.CLOCK_MONOTONIC, ctypes.pointer(ts)) != 0: + self._errno = ctypes.get_errno() + return 0 + return ts.tv_sec + ts.tv_nsec * 1e-9 + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* + available value. + + Returns: + An integer specifying the *actual* number of seconds the + watchdog was armed with. On failure returns -1. + """ + timer_offset = -1 + for key,timer_seconds in enumerate(self.TIMERS): + if seconds <= timer_seconds: + timer_offset = key + seconds = timer_seconds + break + + if timer_offset == -1: + return -1 + + # Extracting 5th to 7th bits for WD timer values + # 000 - 15 sec + # 001 - 20 sec + # 010 - 30 sec + # 011 - 40 sec + # 100 - 50 sec + # 101 - 60 sec + # 110 - 65 sec + # 111 - 70 sec + reg_val = self._get_reg_val() + wd_timer_offset = (reg_val >> 4) & 0x7 + + if wd_timer_offset != timer_offset: + # Setting 5th to 7th bits + # value from timer_offset + self.disarm() + self._set_reg_val(reg_val | (timer_offset << 4)) + + if self.is_armed(): + # Setting last bit to WD Timer punch + # Last bit = WD Timer punch + self._set_reg_val(reg_val & 0xFE) + + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + else: + # Setting 4th bit to enable WD + # 4th bit = Enable WD + reg_val = self._get_reg_val() + self._set_reg_val(reg_val | 0x8) + + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + + def disarm(self): + """ + Disarm the hardware watchdog + + Returns: + A boolean, True if watchdog is disarmed successfully, False + if not + """ + if self.is_armed(): + # Setting 4th bit to disable WD + # 4th bit = Disable WD + reg_val = self._get_reg_val() + self._set_reg_val(reg_val & 0xF7) + + self.armed_time = 0 + self.timeout = 0 + return True + + return False + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + + Returns: + A boolean, True if watchdog is armed, False if not + """ + + # Extracting 4th bit to get WD Enable/Disable status + # 0 - Disabled WD + # 1 - Enabled WD + reg_val = self._get_reg_val() + wd_offset = (reg_val >> 3) & 1 + + return bool(wd_offset) + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds + remaining on the watchdog timer + + Returns: + An integer specifying the number of seconds remaining on + their watchdog timer. If the watchdog is not armed, returns + -1. + + S5232 doesnot have hardware support to show remaining time. + Due to this limitation, this API is implemented in software. + This API would return correct software time difference if it + is called from the process which armed the watchdog timer. + If this API called from any other process, it would return + 0. If the watchdog is not armed, this API would return -1. + """ + if not self.is_armed(): + return -1 + + if self.armed_time > 0 and self.timeout != 0: + cur_time = self._get_time() + + if cur_time <= 0: + return 0 + + diff_time = int(cur_time - self.armed_time) + + if diff_time > self.timeout: + return self.timeout + else: + return self.timeout - diff_time + + return 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/systemd/platform-modules-s5232f.service b/platform/broadcom/sonic-platform-modules-dell/s5232f/systemd/platform-modules-s5232f.service new file mode 100644 index 000000000000..0ca31b522bd4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/systemd/platform-modules-s5232f.service @@ -0,0 +1,13 @@ +[Unit] +Description=Dell S5232f Platform modules +Before=pmon.service determine-reboot-cause.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/s5232f_platform.sh init +ExecStop=/usr/local/bin/s5232f_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/s5248f/cfg/s5248f-modules.conf b/platform/broadcom/sonic-platform-modules-dell/s5248f/cfg/s5248f-modules.conf new file mode 100644 index 000000000000..94639bd3f6e5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5248f/cfg/s5248f-modules.conf @@ -0,0 +1,19 @@ +# /etc/modules: kernel modules to load at boot time. +# +# This file contains the names of kernel modules that should be loaded +# at boot time, one per line. Lines beginning with "#" are ignored. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x + +ipmi_devintf +ipmi_si +dell_s5248f_fpga_ocores +i2c_ocores diff --git a/platform/broadcom/sonic-platform-modules-dell/s5248f/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/s5248f/modules/Makefile new file mode 100644 index 000000000000..c179aa5dc931 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5248f/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_s5248f_fpga_ocores.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/s5248f/modules/dell_s5248f_fpga_ocores.c b/platform/broadcom/sonic-platform-modules-dell/s5248f/modules/dell_s5248f_fpga_ocores.c new file mode 100644 index 000000000000..b9a50c69b225 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5248f/modules/dell_s5248f_fpga_ocores.c @@ -0,0 +1,1626 @@ +/* +* 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_i2ccore.c +* @brief This is a driver to interface with Linux Open Cores drivber for FPGA i2c access +* +************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include //siginfo +#include //rcu_read_lock +#include //kernel_version +#include +#include +#include +#include +#include + + +void __iomem * fpga_base_addr = NULL; +void __iomem * fpga_ctl_addr = NULL; + +#define DRIVER_NAME "fpgapci" +#define PCI_NUM_BARS 4 + +#ifdef DEBUG +# define PRINT(fmt, ...) printk(fmt, ##__VA_ARGS__) +#else +# define PRINT(fmt, ...) +#endif + +/* Maximum size of driver buffer (allocated with kalloc()). + * Needed to copy data from user to kernel space, among other + * things. */ +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; + + /* kernels virtual addr. for the mapped BARs */ + void * __iomem bar[PCI_NUM_BARS]; + + /* length of each memory region. Used for error checking. */ + size_t bar_length[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; + + unsigned int irq_first; + unsigned int irq_length; + unsigned int irq_assigned; + unsigned int xcvr_intr_count; +}; + +static int use_irq = 1; +module_param(use_irq, int, 0644); +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."); + + +/* Xilinx FPGA PCIE info: */ +/* Non-VGA unclassified device: Xilinx Corporation Device 7021*/ +/* Subsystem: Xilinx Corporation Device 0007 */ +//#define VENDOR 0x10EE +#define DEVICE 0x7021 +static phys_addr_t fpga_phys_addr; + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +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; +}; + +/* global variable declarations */ + +/* Static function declarations */ +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id); +static void fpgapci_remove(struct pci_dev *dev); + +static int scan_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +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; +}; +/* 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_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_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 */ + +enum { + STATE_DONE = 0, + STATE_INIT, + STATE_ADDR, + STATE_ADDR10, + STATE_START, + STATE_WRITE, + STATE_READ, + STATE_STOP, + STATE_ERROR, +}; + +#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 i2c_bus_controller_numb 1 +#define I2C_PCI_MAX_BUS (16) +#define I2C_PCI_MAX_BUS_REV00 (7) +#define DELL_I2C_CLOCK_LEGACY 0 +#define DELL_I2C_CLOCK_PRESERVE (~0U) +#define I2C_PCI_BUS_NUM_5 5 +#define I2C_PCI_BUS_NUM_7 7 +#define I2C_PCI_BUS_NUM_8 8 +#define I2C_PCI_BUS_NUM_10 10 +#define I2C_PCI_BUS_NUM_12 12 +#define I2C_PCI_BUS_NUM_16 16 + +#define IRQ_LTCH_STS 0x20 +#define PRSNT_LTCH_STS 0x10 + +#define PORT_CTRL_OFFSET 0x4000 +#define PORT_STS_OFFSET 0x4004 +#define PORT_IRQ_STS_OFFSET 0x4008 +#define PORT_IRQ_EN_OFFSET 0x400C +#define MB_BRD_REV_TYPE 0x0008 +#define MB_BRD_REV_MASK 0x00f0 +#define MB_BRD_REV_00 0x0000 +#define MB_BRD_REV_01 0x0010 +#define MB_BRD_REV_02 0x0020 +#define MB_BRD_REV_03 0x0030 +#define MB_BRD_TYPE_MASK 0x000f +#define BRD_TYPE_Z9232_NON_NEBS 0x0 +#define BRD_TYPE_Z9232_NEBS 0x1 +#define BRD_TYPE_Z9264_NON_NEBS 0x2 +#define BRD_TYPE_Z9264_NEBS 0x3 +#define BRD_TYPE_S5212_NON_NEBS 0x4 +#define BRD_TYPE_S5212_NEBS 0x5 +#define BRD_TYPE_S5224_NON_NEBS 0x6 +#define BRD_TYPE_S5224_NEBS 0x7 +#define BRD_TYPE_S5248_NON_NEBS 0x8 +#define BRD_TYPE_S5248_NEBS 0x9 +#define BRD_TYPE_S5296_NON_NEBS 0xa +#define BRD_TYPE_S5296_NEBS 0xb +#define BRD_TYPE_S5232_NON_NEBS 0xc +#define BRD_TYPE_S5232_NEBS 0xd + +#define FPGA_CTL_REG_SIZE 0x6000 +#define MSI_VECTOR_MAP_MASK 0x1f +#define MSI_VECTOR_MAP1 0x58 +#define I2C_CH1_MSI_MAP_VECT_8 0x00000008 +#define I2C_CH2_MSI_MAP_VECT_9 0x00000120 +#define I2C_CH3_MSI_MAP_VECT_10 0x00002800 +#define I2C_CH4_MSI_MAP_VECT_11 0x00058000 +#define I2C_CH5_MSI_MAP_VECT_12 0x00c00000 +#define I2C_CH6_MSI_MAP_VECT_13 0x15000000 +#define MSI_VECTOR_MAP2 0x5c +#define I2C_CH7_MSI_MAP_VECT_14 0x0000000e +#define MSI_VECTOR_MAP3 0x9c +#define I2C_CH8_MSI_MAP_VECT_8 0x00800000 +#define I2C_CH8_MSI_MAP_VECT_16 0x01100000 +#define I2C_CH9_MSI_MAP_VECT_9 0x12000000 +#define I2C_CH9_MSI_MAP_VECT_17 0x24000000 +#define MSI_VECTOR_MAP4 0xa0 +#define I2C_CH10_MSI_MAP_VECT_10 0x0000000a +#define I2C_CH10_MSI_MAP_VECT_18 0x00000012 +#define I2C_CH11_MSI_MAP_VECT_11 0x00000120 +#define I2C_CH11_MSI_MAP_VECT_19 0x00000260 +#define I2C_CH12_MSI_MAP_VECT_12 0x00002800 +#define I2C_CH12_MSI_MAP_VECT_20 0x00005000 +#define I2C_CH13_MSI_MAP_VECT_13 0x00058000 +#define I2C_CH13_MSI_MAP_VECT_21 0x000a8000 +#define I2C_CH14_MSI_MAP_VECT_14 0x00c00000 +#define I2C_CH14_MSI_MAP_VECT_22 0x01600000 +#define I2C_CH15_MSI_MAP_VECT_8 0x10000000 +#define I2C_CH15_MSI_MAP_VECT_23 0x2e000000 +#define MSI_VECTOR_MAP5 0xa4 +#define I2C_CH16_MSI_MAP_VECT_9 0x00000009 +#define I2C_CH16_MSI_MAP_VECT_24 0x00000018 + +#define MSI_VECTOR_REV_00 16 +#define MSI_VECTOR_REV_01 32 + +#define FPGA_MSI_VECTOR_ID_4 4 +#define FPGA_MSI_VECTOR_ID_5 5 +#define FPGA_MSI_VECTOR_ID_8 8 +#define FPGA_MSI_VECTOR_ID_9 9 +#define FPGA_MSI_VECTOR_ID_10 10 +#define FPGA_MSI_VECTOR_ID_11 11 +#define FPGA_MSI_VECTOR_ID_12 12 +#define FPGA_MSI_VECTOR_ID_13 13 +#define FPGA_MSI_VECTOR_ID_14 14 +#define FPGA_MSI_VECTOR_ID_15 15 /*Note: this is external MSI vector id */ +#define FPGA_MSI_VECTOR_ID_16 16 +#define FPGA_MSI_VECTOR_ID_17 17 +#define FPGA_MSI_VECTOR_ID_18 18 +#define FPGA_MSI_VECTOR_ID_19 19 +#define FPGA_MSI_VECTOR_ID_20 20 +#define FPGA_MSI_VECTOR_ID_21 21 +#define FPGA_MSI_VECTOR_ID_22 22 +#define FPGA_MSI_VECTOR_ID_23 23 +#define FPGA_MSI_VECTOR_ID_24 24 + + + +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 void fpgai2c_reg_set_8(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static void fpgai2c_reg_set_32(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static void fpgai2c_reg_set_32be(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static inline u8 fpgai2c_reg_get_16(struct fpgalogic_i2c *i2c, int reg) +{ + 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)); +} + +static inline u8 fpgai2c_reg_get_16be(struct fpgalogic_i2c *i2c, int reg) +{ + 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)); +} + +static inline void fpgai2c_reg_set(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + i2c->reg_set(i2c, reg, value); + udelay(100); +} + +static inline u8 fpgai2c_reg_get(struct fpgalogic_i2c *i2c, int reg) +{ + udelay(100); + return i2c->reg_get(i2c, reg); +} + +static void fpgai2c_dump(struct fpgalogic_i2c *i2c) +{ + u8 tmp; + + 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_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_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); +} + +static void fpgai2c_stop(struct fpgalogic_i2c *i2c) +{ + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP); +} + +/* + * dell_get_mutex must be called prior to calling this function. + */ +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; + } + + /* 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); + + 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); + + 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 (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); + } + + 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); + 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)); + 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); +} +static DEVICE_ATTR(port_msi, S_IRUGO, get_mod_msi, NULL); + +static struct attribute *port_attrs[] = { + &dev_attr_port_msi.attr, + NULL, +}; + +static struct attribute_group port_attr_grp = { + .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); + 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)); + 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)); + } + } + 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; +} + +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); + 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)); + 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); + iowrite32( IRQ_LTCH_STS|PRSNT_LTCH_STS,fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16)); + } + } + 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; +} + +static void fpgai2c_process(struct fpgalogic_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + u8 stat = fpgai2c_reg_get(i2c, FPGAI2C_REG_STATUS); + + PRINT("fpgai2c_process in. status reg :0x%x\n", stat); + + 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); + 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; + } + + + /* error? */ + if (stat & FPGAI2C_REG_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + PRINT("fpgai2c_process FPGAI2C_REG_STAT_ARBLOST FPGAI2C_REG_CMD_STOP\n"); + fpgai2c_stop(i2c); + return; + } + + 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_stop(i2c); + return; + } + } else + { + msg->buf[i2c->pos++] = fpgai2c_reg_get(i2c, FPGAI2C_REG_DATA); + } + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { /* end? */ + /* send start? */ + if (!(msg->flags & I2C_M_NOSTART)) { + + u8 addr = (msg->addr << 1); + + if (msg->flags & I2C_M_RD) + addr |= 1; + + i2c->state = STATE_START; + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, addr); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + return; + } else + { + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } + } else { + i2c->state = STATE_STOP; + fpgai2c_stop(i2c); + return; + } + } + + 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); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, i2c->pos == (msg->len-1) ? + 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++]); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE); + } +} + +static irqreturn_t fpgai2c_isr(int irq, void *dev_id) +{ + struct fpgalogic_i2c *i2c = dev_id; + fpgai2c_process(i2c); + + return IRQ_HANDLED; +} +void dell_get_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_lock(&i2c->lock); +} + +/** + * dell_release_mutex - release mutex + */ +void dell_release_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_unlock(&i2c->lock); +} + +static int fpgai2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct fpgalogic_i2c *i2c = i2c_get_adapdata(adap); + int ret; + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = (use_irq == 1) ? STATE_START : STATE_INIT; + + PRINT("i2c->msg->addr = 0x%x i2c->msg->flags = 0x%x\n",i2c->msg->addr,i2c->msg->flags); + PRINT("I2C_M_RD = 0x%x i2c->msg->addr << 1 = 0x%x\n",I2C_M_RD,i2c->msg->addr << 1); + + if (!use_irq) { + /* Handle the transfer */ + while (time_before(jiffies, timeout)) { + dell_get_mutex(i2c); + ret = fpgai2c_poll(i2c); + dell_release_mutex(i2c); + + if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) + return (i2c->state == STATE_DONE) ? num : ret; + + if (ret == 0) + timeout = jiffies + HZ; + + usleep_range(5, 15); + } + + i2c->state = STATE_ERROR; + + return -ETIMEDOUT; + + + } 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)); + + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, + (i2c->msg->addr << 1) | + ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + + /* Interrupt mode */ + if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || + (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; + } + } + + 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; + } + + 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; +} + +static const struct i2c_algorithm fpgai2c_algorithm = { + .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; +} + +static int i2c_init_internal_data(void) +{ + 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; +} + + +static int i2c_pci_init (void) +{ + int i; + + if (num_bus == 0) { + board_rev_type = ioread32(fpga_ctl_addr + MB_BRD_REV_TYPE); + + 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)) { + switch (board_rev_type & MB_BRD_TYPE_MASK){ + case BRD_TYPE_S5212_NON_NEBS: + case BRD_TYPE_S5212_NEBS: + num_bus = I2C_PCI_BUS_NUM_5; + break; + case BRD_TYPE_S5224_NON_NEBS: + case BRD_TYPE_S5224_NEBS: + num_bus = I2C_PCI_BUS_NUM_7; + break; + case BRD_TYPE_Z9232_NON_NEBS: + case BRD_TYPE_Z9232_NEBS: + case BRD_TYPE_S5232_NON_NEBS: + case BRD_TYPE_S5232_NEBS: + num_bus = I2C_PCI_BUS_NUM_8; + break; + case BRD_TYPE_S5248_NON_NEBS: + case BRD_TYPE_S5248_NEBS: + num_bus = I2C_PCI_BUS_NUM_10; + break; + case BRD_TYPE_Z9264_NON_NEBS: + case BRD_TYPE_Z9264_NEBS: + num_bus = I2C_PCI_BUS_NUM_12; + break; + case BRD_TYPE_S5296_NON_NEBS: + case BRD_TYPE_S5296_NEBS: + num_bus = I2C_PCI_BUS_NUM_16; + break; + default: + num_bus = I2C_PCI_BUS_NUM_16; + printk("Wrong BRD_TYPE: 0x%x\n", board_rev_type); + break; + } + } else { + printk("Wrong board_rev_type 0x%x\n", board_rev_type); + } + } + + 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]); + + /* Initialize driver's itnernal data structures */ + i2c_init_internal_data(); + + 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].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)); + } + + 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]); + } + +} + +/* Find upstream PCIe root node. + * 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; + } +} + + +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); + } + } + + return 0; +} + + +/** + * Map the device memory regions into kernel virtual address space + * after verifying their sizes respect the minimum sizes needed, given + * by the bar_min_len[] array. + */ +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + 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; + + + 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; + } + + 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); + + 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); + + 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; +} + +static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + int i; + + 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" + +/** + * @brief Register specific function with msi interrupt line + * @param dev Pointer to pci-device, which should be allocated + * @param int interrupt number relative to global interrupt number + * @return Returns error code or zero if success + * */ +static int register_intr_handler(struct pci_dev *dev, int irq_num_id) +{ + 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; + } + + 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 + * 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; + } + } 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 */ + 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; + } + } + + return err; +} +/* Mask for MSI Multi message enable bits */ +#define MSI_MME 0x70 +/** + * These enums define the type of interrupt scheme that the overall + * system uses. + */ +enum fpga_irq_type { + INT_MSI_SINGLE, + INT_MSI_MULTI, + INT_MSIX, + INT_NONE, + INT_FENCE /* Last item to guard from loop run-overs */ +}; +/** + * @def PCI_DEVICE_STATUS + * define the offset for STS register + * from the start of PCI config space as specified in the + * NVME_Comliance 1.0b. offset 06h:STS - Device status. + * This register has error status for NVME PCI Exress + * Card. After reading data from this reagister, the driver + * will identify if any error is set during the operation and + * report as kernel alert message. + */ +#define PCI_DEVICE_STATUS 0x6 +/** + * @def NEXT_MASK + * This indicates the location of the next capability item + * in the list. + */ +#define NEXT_MASK 0xFF00 +/** + * @def MSIXCAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSIXCAP_ID 0x11 +/** + * @def MSICAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSICAP_ID 0x5 + +/** + * @def CL_MASK + * This bit position indicates Capabilities List of the controller + * The controller should support the PCI Power Management cap as a + * minimum. + */ +#define CL_MASK 0x0010 + +/** + * @def CAP_REG + * Set to offset defined in NVME Spec 1.0b. + */ +#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; + + 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; + + + /* + * 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); + + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + } +} +/** + * @brief Enables pcie-device and claims/remaps neccessary bar resources + * @param dev Pointer to pci-device, which should be allocated + * @return Returns error code or zero if success + * */ +static int fpgapci_setup_device(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + 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; + } + + /* 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); + + /* 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); + + if (map_bars(fpgapci, dev)) { + goto fail_map_bars; + } + + i2c_pci_init(); + + return 0; + /* ERROR HANDLING */ +fail_map_bars: + pci_release_regions(dev); +error_pci_req: + pci_disable_device(dev); +error_pci_en: + return -ENODEV; +} + +static int fpgapci_configure_msi(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + int err = 0, i; + int request_vec; + + 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); + + 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)) { + if (err < MSI_VECTOR_REV_01) { + goto error_disable_msi; + } + } + } + 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; + } + } + + 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); + 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); +error_no_msi: + return -ENOSPC; +} + +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + 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)); +#endif + fpgapci = kzalloc(sizeof(struct fpgapci_dev), GFP_KERNEL); + + if (!fpgapci) { + PRINT( "Couldn't allocate memory!\n"); + goto fail_kzalloc; + } + + fpgapci->pci_dev = dev; + dev_set_drvdata(&dev->dev, (void*)fpgapci); + + status = sysfs_create_group(&dev->dev.kobj, &port_attr_grp); + if (status) { + printk(KERN_INFO "%s:Cannot create sysfs\n", __FUNCTION__); + } + + fpgapci->upstream = find_upstream_dev (dev); + + 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 */ +error_cannot_configure: + 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"); +fail_kzalloc: + 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); + 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]); + } + } + pci_disable_msi(fpgapci->pci_dev); + free_bars (fpgapci, dev); + pci_disable_device(dev); + pci_release_regions(dev); + + kfree (fpgapci); +} + +static const struct pci_device_id fpgapci_ids[] = { + {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 */ +}; + +/* Initialize the driver module (but not any device) and register + * the module with the kernel PCI subsystem. */ +static int __init fpgapci_init(void) +{ + + if (pci_register_driver(&fpgapci_driver)) { + PRINT("pci_unregister_driver\n"); + pci_unregister_driver(&fpgapci_driver); + return -ENODEV; + } + + return 0; +} + +static void __exit fpgapci_exit(void) +{ + PRINT ("fpgapci_exit"); + + /* unregister this driver from the PCI bus driver */ + pci_unregister_driver(&fpgapci_driver); + +} + + +module_init (fpgapci_init); +module_exit (fpgapci_exit); +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/s5248f/scripts/check_qsfp.sh b/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/check_qsfp.sh new file mode 100755 index 000000000000..2028b8e65946 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/check_qsfp.sh @@ -0,0 +1,3 @@ +# Temporary dummy file for s5248f. +# Will be updated soon. + diff --git a/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/platform_sensors.py new file mode 100755 index 000000000000..f276e6879d2c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/platform_sensors.py @@ -0,0 +1,274 @@ +#!/usr/bin/python3 +# On S5248F, the BaseBoard Management Controller is an +# autonomous subsystem provides monitoring and management +# facility independent of the host CPU. IPMI standard +# protocol is used with ipmitool to fetch sensor details. +# Current script support X00 board only. X01 support will +# be added soon. This provies support for the +# following objects: +# * Onboard temperature sensors +# * FAN trays +# * PSU + + +import sys +import logging +import subprocess + +S5248F_MAX_FAN_TRAYS = 4 +S5248F_MAX_PSUS = 2 +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_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_sdr_list = "" + +# Dump sensor registers + + +def ipmi_sensor_dump(): + + status = 1 + global ipmi_sdr_list + ipmi_cmd = IPMI_SENSOR_DATA + status, ipmi_sdr_list = subprocess.getstatusoutput(ipmi_cmd) + + if status: + logging.error('Failed to execute:' + ipmi_sdr_list) + sys.exit(0) + +# Fetch a BMC register + + +def get_pmc_register(reg_name): + + output = None + for item in ipmi_sdr_list.split("\n"): + if reg_name in item: + output = item.strip() + + if output is None: + print('\nFailed to fetch: ' + reg_name + ' sensor ') + sys.exit(0) + + output = output.split('|')[1] + + logging.basicConfig(level=logging.DEBUG) + return output + + +# Print the information for temperature sensors + + +def print_temperature_sensors(): + + print("\nOnboard Temperature Sensors:") + + print(' PT_Left_temp: ', + get_pmc_register('PT_Left_temp')) + print(' PT_Mid_temp: ', + get_pmc_register('PT_Mid_temp')) + print(' PT_Right_temp: ', + get_pmc_register('PT_Right_temp')) + print(' Broadcom Temp: ', + get_pmc_register('NPU_Near_temp')) + print(' Inlet Airflow Temp: ', + get_pmc_register('ILET_AF_temp')) + print(' CPU Temp: ', + get_pmc_register('CPU_temp')) + +ipmi_sensor_dump() + +print_temperature_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(tray): + + Fan_Status = [' Normal', ' Abnormal'] + Airflow_Direction = ['B2F', 'F2B'] + + print(' Fan Tray ' + str(tray) + ':') + + if (tray == 1): + + fan1_status = int(get_pmc_register('FAN1_Front_stat'), 16) + fan2_status = int(get_pmc_register('FAN1_Rear_stat'), 16) + + print(' Fan1 Speed: ', + get_pmc_register('FAN1_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN1_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + elif (tray == 2): + + fan1_status = int(get_pmc_register('FAN2_Front_stat'), 16) + fan2_status = int(get_pmc_register('FAN2_Rear_stat'), 16) + + print(' Fan1 Speed: ', + get_pmc_register('FAN2_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN2_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + elif (tray == 3): + + fan1_status = int(get_pmc_register('FAN3_Front_stat'), 16) + fan2_status = int(get_pmc_register('FAN3_Rear_stat'), 16) + + print(' Fan1 Speed: ', + get_pmc_register('FAN3_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN3_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + elif (tray == 4): + + fan1_status = int(get_pmc_register('FAN4_Front_stat'), 16) + fan2_status = int(get_pmc_register('FAN4_Rear_stat'), 16) + + print(' Fan1 Speed: ', + get_pmc_register('FAN4_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN4_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + +print('\nFan Trays:') + +for tray in range(1, S5248F_MAX_FAN_TRAYS + 1): + fan_presence = FAN_PRESENCE.format(tray) + if (get_pmc_register(fan_presence)): + print_fan_tray(tray) + else: + print('\n Fan Tray ' + str(tray + 1) + ': Not present') + + 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 + """ + status = 0 + ret_status = 1 + + if index == 1: + status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_PSU1_DATA_DOCKER) + elif index == 2: + ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_PSU2_DATA_DOCKER) + + #if ret_status: + # print ipmi_cmd_ret + # logging.error('Failed to execute ipmitool') + # sys.exit(0) + + psu_status = ipmi_cmd_ret + + if psu_status == '1': + status = 1 + + return status + + +# Print the information for PSU1, PSU2 +def print_psu(psu): + Psu_Type = ['Normal', 'Mismatch'] + Psu_Input_Type = ['AC', 'DC'] + PSU_STATUS_TYPE_BIT = 4 + PSU_STATUS_INPUT_TYPE_BIT = 1 + PSU_FAN_PRESENT_BIT = 2 + PSU_FAN_STATUS_BIT = 1 + 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] + + # PSU FAN details + if (psu == 1): + + # psu1_fan_status = int(get_pmc_register('PSU1_status'),16) + + print(' PSU1:') + print(' FAN Normal Temperature: ', + get_pmc_register('PSU1_temp')) + print(' FAN AirFlow Temperature: ', + get_pmc_register('PSU1_AF_temp')) + print(' FAN RPM: ', + get_pmc_register('PSU1_rpm')) + # print ' FAN Status: ', Psu_Fan_Status[psu1_fan_status] + + # PSU input & output monitors + print(' Input Voltage: ', + get_pmc_register('PSU1_In_volt')) + print(' Output Voltage: ', + get_pmc_register('PSU1_Out_volt')) + print(' Input Power: ', + get_pmc_register('PSU1_In_watt')) + print(' Output Power: ', + get_pmc_register('PSU1_Out_watt')) + print(' Input Current: ', + get_pmc_register('PSU1_In_amp')) + print(' Output Current: ', + get_pmc_register('PSU1_Out_amp')) + + else: + + # psu2_fan_status = int(get_pmc_register('PSU1_status'),16) + print(' PSU2:') + print(' FAN Normal Temperature: ', + get_pmc_register('PSU2_temp')) + print(' FAN AirFlow Temperature: ', + get_pmc_register('PSU2_AF_temp')) + print(' FAN RPM: ', + get_pmc_register('PSU2_rpm')) + # print ' FAN Status: ', Psu_Fan_Status[psu2_fan_status] + + # PSU input & output monitors + print(' Input Voltage: ', + get_pmc_register('PSU2_In_volt')) + print(' Output Voltage: ', + get_pmc_register('PSU2_Out_volt')) + print(' Input Power: ', + get_pmc_register('PSU2_In_watt')) + print(' Output Power: ', + get_pmc_register('PSU2_Out_watt')) + print(' Input Current: ', + get_pmc_register('PSU2_In_amp')) + print(' Output Current: ', + get_pmc_register('PSU2_Out_amp')) + + +print('\nPSUs:') +for psu in range(1, S5248F_MAX_PSUS + 1): + #psu_presence = PSU_PRESENCE.format(psu) + if (get_psu_presence(psu)): + print_psu(psu) + else: + print('\n PSU ', psu, 'Not present') + +print('\n Total Power: ', + get_pmc_register('PSU_Total_watt')) diff --git a/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/qsfp_irq_enable.py b/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/qsfp_irq_enable.py new file mode 100755 index 000000000000..5050475f987e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/qsfp_irq_enable.py @@ -0,0 +1,32 @@ +#!/usr/bin/python + +try: + import struct + import sys + from os import * + from mmap import * + +except ImportError as e: + raise ImportError("%s - required module no found" % str(e)) + +BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" +PORT_START = 0 +PORT_END = 32 + + +def pci_mem_write(mm, offset, data): + mm.seek(offset) + mm.write(struct.pack('I', data)) + + +def pci_set_value(resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = pci_mem_write(mm, offset, val) + mm.close() + close(fd) + return val + +for port_num in range(PORT_START, PORT_END+1): + port_offset = 0x400c + ((port_num) * 16) + pci_set_value(BASE_RES_PATH, 0x30, port_offset) diff --git a/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/s5248f_platform.sh b/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/s5248f_platform.sh new file mode 100755 index 000000000000..e006e53cfc49 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/s5248f_platform.sh @@ -0,0 +1,161 @@ +#!/bin/bash + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find iSMT" && exit 1 +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + case $1 in + "new_device") echo 24c16 0x50 > /sys/bus/i2c/devices/i2c-${devnum}/$1 + ;; + "delete_device") echo 0x50 > /sys/bus/i2c/devices/i2c-${devnum}/$1 + ;; + *) echo "s5248f_platform: sys_eeprom : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs +switch_board_qsfp_mux() { + case $1 in + "new_device") + for ((i=603;i<=610;i++)); + do + echo "Attaching PCA9548 @ 0x74" + echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-$i/$1 + done + + ;; + "delete_device") + for ((i=603;i<=610;i++)); + do + echo "Detaching PCA9548 @ 0x74" + echo 0x74 > /sys/bus/i2c/devices/i2c-$i/$1 + done + + ;; + *) echo "s5248f_platform: switch_board_qsfp_mux: invalid command !" + ;; + esac + sleep 2 +} + +#Attach/Detach 64 instances of EEPROM driver QSFP ports +#eeprom can dump data using below command +switch_board_qsfp() { + case $1 in + "new_device") + for ((i=2;i<=57;i++)); + do + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=2;i<=57;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "s5248f_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +#Modsel 64 ports to applicable QSFP type modules +#This enables the adapter to respond for i2c commands +switch_board_modsel() { + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + for ((i=1;i<=64;i++)); + do + port_addr=$(( 16384 + ((i - 1) * 16))) + hex=$( printf "0x%x" $port_addr ) + /usr/bin/pcisysfs.py --set --offset $hex --val 0x10 --res $resource > /dev/null 2>&1 + done +} + +platform_firmware_versions() { + FIRMWARE_VERSION_FILE=/var/log/firmware_versions + rm -rf ${FIRMWARE_VERSION_FILE} + echo "BIOS: `dmidecode -s system-version `" > $FIRMWARE_VERSION_FILE + ## Get FPGA version + r=`/usr/bin/pcisysfs.py --get --offset 0x00 --res /sys/bus/pci/devices/0000\:04\:00.0/resource0 | sed '1d; s/.*\(....\)$/\1/; s/\(..\{1\}\)/\1./'` + r_min=$(echo $r | sed 's/.*\(..\)$/0x\1/') + r_maj=$(echo $r | sed 's/^\(..\).*/0x\1/') + echo "FPGA: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE + + ## Get BMC Firmware Revision + r=`cat /sys/class/ipmi/ipmi0/device/bmc/firmware_revision` + echo "BMC: $r" >> $FIRMWARE_VERSION_FILE + + #System CPLD 0x31 on i2c bus 601 ( physical FPGA I2C-2) + r_min=`/usr/sbin/i2cget -y 601 0x31 0x0 | sed ' s/.*\(0x..\)$/\1/'` + r_maj=`/usr/sbin/i2cget -y 601 0x31 0x1 | sed ' s/.*\(0x..\)$/\1/'` + echo "System CPLD: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE + + #Slave CPLD 1 0x30 on i2c bus 600 ( physical FPGA I2C-1) + r_min=`/usr/sbin/i2cget -y 600 0x30 0x0 | sed ' s/.*\(0x..\)$/\1/'` + r_maj=`/usr/sbin/i2cget -y 600 0x30 0x1 | sed ' s/.*\(0x..\)$/\1/'` + echo "Slave CPLD 1: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE + + #Slave CPLD 2 0x31 on i2c bus 600 ( physical FPGA I2C-1) + r_min=`/usr/sbin/i2cget -y 600 0x31 0x0 | sed ' s/.*\(0x..\)$/\1/'` + r_maj=`/usr/sbin/i2cget -y 600 0x31 0x1 | sed ' s/.*\(0x..\)$/\1/'` + echo "Slave CPLD 2: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE + + #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 +} + +#This enables the led control for CPU and default states +switch_board_led_default() { + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + /usr/bin/pcisysfs.py --set --offset 0x24 --val 0x194 --res $resource > /dev/null 2>&1 +} +init_devnum + +if [ "$1" == "init" ]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe ipmi_devintf + modprobe ipmi_si + modprobe i2c_ocores + modprobe dell_s5248f_fpga_ocores + sys_eeprom "new_device" + switch_board_qsfp_mux "new_device" + switch_board_qsfp "new_device" + switch_board_modsel + switch_board_led_default + #/usr/bin/qsfp_irq_enable.py + platform_firmware_versions + +elif [ "$1" == "deinit" ]; then + sys_eeprom "delete_device" + switch_board_qsfp "delete_device" + switch_board_qsfp_mux "delete_device" + + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev +else + echo "s5248f_platform : Invalid option !" +fi + diff --git a/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/sensors new file mode 100755 index 000000000000..ee53f2b0f325 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5248f/scripts/sensors @@ -0,0 +1,8 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" +docker exec -i pmon /usr/bin/platform_sensors.py "$@" + +#To probe sensors not part of lm-sensors +#if [ -r /usr/local/bin/platform_sensors.py ]; then +# python /usr/local/bin/platform_sensors.py +#fi diff --git a/platform/broadcom/sonic-platform-modules-dell/s5248f/systemd/platform-modules-s5248f.service b/platform/broadcom/sonic-platform-modules-dell/s5248f/systemd/platform-modules-s5248f.service new file mode 100644 index 000000000000..ec3ea09f00ae --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5248f/systemd/platform-modules-s5248f.service @@ -0,0 +1,13 @@ +[Unit] +Description=Dell S5248f Platform modules +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/s5248f_platform.sh init +ExecStop=/usr/local/bin/s5248f_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/s5296f/cfg/s5296f-modules.conf b/platform/broadcom/sonic-platform-modules-dell/s5296f/cfg/s5296f-modules.conf new file mode 100644 index 000000000000..17045f6b25ab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5296f/cfg/s5296f-modules.conf @@ -0,0 +1,19 @@ +# /etc/modules: kernel modules to load at boot time. +# +# This file contains the names of kernel modules that should be loaded +# at boot time, one per line. Lines beginning with "#" are ignored. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x + +ipmi_devintf +ipmi_si +dell_s5296f_fpga_ocores +i2c_ocores diff --git a/platform/broadcom/sonic-platform-modules-dell/s5296f/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/s5296f/modules/Makefile new file mode 100644 index 000000000000..d1d103b5f136 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5296f/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_s5296f_fpga_ocores.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/s5296f/modules/dell_s5296f_fpga_ocores.c b/platform/broadcom/sonic-platform-modules-dell/s5296f/modules/dell_s5296f_fpga_ocores.c new file mode 100644 index 000000000000..b9a50c69b225 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5296f/modules/dell_s5296f_fpga_ocores.c @@ -0,0 +1,1626 @@ +/* +* 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_i2ccore.c +* @brief This is a driver to interface with Linux Open Cores drivber for FPGA i2c access +* +************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include //siginfo +#include //rcu_read_lock +#include //kernel_version +#include +#include +#include +#include +#include + + +void __iomem * fpga_base_addr = NULL; +void __iomem * fpga_ctl_addr = NULL; + +#define DRIVER_NAME "fpgapci" +#define PCI_NUM_BARS 4 + +#ifdef DEBUG +# define PRINT(fmt, ...) printk(fmt, ##__VA_ARGS__) +#else +# define PRINT(fmt, ...) +#endif + +/* Maximum size of driver buffer (allocated with kalloc()). + * Needed to copy data from user to kernel space, among other + * things. */ +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; + + /* kernels virtual addr. for the mapped BARs */ + void * __iomem bar[PCI_NUM_BARS]; + + /* length of each memory region. Used for error checking. */ + size_t bar_length[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; + + unsigned int irq_first; + unsigned int irq_length; + unsigned int irq_assigned; + unsigned int xcvr_intr_count; +}; + +static int use_irq = 1; +module_param(use_irq, int, 0644); +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."); + + +/* Xilinx FPGA PCIE info: */ +/* Non-VGA unclassified device: Xilinx Corporation Device 7021*/ +/* Subsystem: Xilinx Corporation Device 0007 */ +//#define VENDOR 0x10EE +#define DEVICE 0x7021 +static phys_addr_t fpga_phys_addr; + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +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; +}; + +/* global variable declarations */ + +/* Static function declarations */ +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id); +static void fpgapci_remove(struct pci_dev *dev); + +static int scan_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +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; +}; +/* 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_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_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 */ + +enum { + STATE_DONE = 0, + STATE_INIT, + STATE_ADDR, + STATE_ADDR10, + STATE_START, + STATE_WRITE, + STATE_READ, + STATE_STOP, + STATE_ERROR, +}; + +#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 i2c_bus_controller_numb 1 +#define I2C_PCI_MAX_BUS (16) +#define I2C_PCI_MAX_BUS_REV00 (7) +#define DELL_I2C_CLOCK_LEGACY 0 +#define DELL_I2C_CLOCK_PRESERVE (~0U) +#define I2C_PCI_BUS_NUM_5 5 +#define I2C_PCI_BUS_NUM_7 7 +#define I2C_PCI_BUS_NUM_8 8 +#define I2C_PCI_BUS_NUM_10 10 +#define I2C_PCI_BUS_NUM_12 12 +#define I2C_PCI_BUS_NUM_16 16 + +#define IRQ_LTCH_STS 0x20 +#define PRSNT_LTCH_STS 0x10 + +#define PORT_CTRL_OFFSET 0x4000 +#define PORT_STS_OFFSET 0x4004 +#define PORT_IRQ_STS_OFFSET 0x4008 +#define PORT_IRQ_EN_OFFSET 0x400C +#define MB_BRD_REV_TYPE 0x0008 +#define MB_BRD_REV_MASK 0x00f0 +#define MB_BRD_REV_00 0x0000 +#define MB_BRD_REV_01 0x0010 +#define MB_BRD_REV_02 0x0020 +#define MB_BRD_REV_03 0x0030 +#define MB_BRD_TYPE_MASK 0x000f +#define BRD_TYPE_Z9232_NON_NEBS 0x0 +#define BRD_TYPE_Z9232_NEBS 0x1 +#define BRD_TYPE_Z9264_NON_NEBS 0x2 +#define BRD_TYPE_Z9264_NEBS 0x3 +#define BRD_TYPE_S5212_NON_NEBS 0x4 +#define BRD_TYPE_S5212_NEBS 0x5 +#define BRD_TYPE_S5224_NON_NEBS 0x6 +#define BRD_TYPE_S5224_NEBS 0x7 +#define BRD_TYPE_S5248_NON_NEBS 0x8 +#define BRD_TYPE_S5248_NEBS 0x9 +#define BRD_TYPE_S5296_NON_NEBS 0xa +#define BRD_TYPE_S5296_NEBS 0xb +#define BRD_TYPE_S5232_NON_NEBS 0xc +#define BRD_TYPE_S5232_NEBS 0xd + +#define FPGA_CTL_REG_SIZE 0x6000 +#define MSI_VECTOR_MAP_MASK 0x1f +#define MSI_VECTOR_MAP1 0x58 +#define I2C_CH1_MSI_MAP_VECT_8 0x00000008 +#define I2C_CH2_MSI_MAP_VECT_9 0x00000120 +#define I2C_CH3_MSI_MAP_VECT_10 0x00002800 +#define I2C_CH4_MSI_MAP_VECT_11 0x00058000 +#define I2C_CH5_MSI_MAP_VECT_12 0x00c00000 +#define I2C_CH6_MSI_MAP_VECT_13 0x15000000 +#define MSI_VECTOR_MAP2 0x5c +#define I2C_CH7_MSI_MAP_VECT_14 0x0000000e +#define MSI_VECTOR_MAP3 0x9c +#define I2C_CH8_MSI_MAP_VECT_8 0x00800000 +#define I2C_CH8_MSI_MAP_VECT_16 0x01100000 +#define I2C_CH9_MSI_MAP_VECT_9 0x12000000 +#define I2C_CH9_MSI_MAP_VECT_17 0x24000000 +#define MSI_VECTOR_MAP4 0xa0 +#define I2C_CH10_MSI_MAP_VECT_10 0x0000000a +#define I2C_CH10_MSI_MAP_VECT_18 0x00000012 +#define I2C_CH11_MSI_MAP_VECT_11 0x00000120 +#define I2C_CH11_MSI_MAP_VECT_19 0x00000260 +#define I2C_CH12_MSI_MAP_VECT_12 0x00002800 +#define I2C_CH12_MSI_MAP_VECT_20 0x00005000 +#define I2C_CH13_MSI_MAP_VECT_13 0x00058000 +#define I2C_CH13_MSI_MAP_VECT_21 0x000a8000 +#define I2C_CH14_MSI_MAP_VECT_14 0x00c00000 +#define I2C_CH14_MSI_MAP_VECT_22 0x01600000 +#define I2C_CH15_MSI_MAP_VECT_8 0x10000000 +#define I2C_CH15_MSI_MAP_VECT_23 0x2e000000 +#define MSI_VECTOR_MAP5 0xa4 +#define I2C_CH16_MSI_MAP_VECT_9 0x00000009 +#define I2C_CH16_MSI_MAP_VECT_24 0x00000018 + +#define MSI_VECTOR_REV_00 16 +#define MSI_VECTOR_REV_01 32 + +#define FPGA_MSI_VECTOR_ID_4 4 +#define FPGA_MSI_VECTOR_ID_5 5 +#define FPGA_MSI_VECTOR_ID_8 8 +#define FPGA_MSI_VECTOR_ID_9 9 +#define FPGA_MSI_VECTOR_ID_10 10 +#define FPGA_MSI_VECTOR_ID_11 11 +#define FPGA_MSI_VECTOR_ID_12 12 +#define FPGA_MSI_VECTOR_ID_13 13 +#define FPGA_MSI_VECTOR_ID_14 14 +#define FPGA_MSI_VECTOR_ID_15 15 /*Note: this is external MSI vector id */ +#define FPGA_MSI_VECTOR_ID_16 16 +#define FPGA_MSI_VECTOR_ID_17 17 +#define FPGA_MSI_VECTOR_ID_18 18 +#define FPGA_MSI_VECTOR_ID_19 19 +#define FPGA_MSI_VECTOR_ID_20 20 +#define FPGA_MSI_VECTOR_ID_21 21 +#define FPGA_MSI_VECTOR_ID_22 22 +#define FPGA_MSI_VECTOR_ID_23 23 +#define FPGA_MSI_VECTOR_ID_24 24 + + + +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 void fpgai2c_reg_set_8(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static void fpgai2c_reg_set_32(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static void fpgai2c_reg_set_32be(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static inline u8 fpgai2c_reg_get_16(struct fpgalogic_i2c *i2c, int reg) +{ + 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)); +} + +static inline u8 fpgai2c_reg_get_16be(struct fpgalogic_i2c *i2c, int reg) +{ + 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)); +} + +static inline void fpgai2c_reg_set(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + i2c->reg_set(i2c, reg, value); + udelay(100); +} + +static inline u8 fpgai2c_reg_get(struct fpgalogic_i2c *i2c, int reg) +{ + udelay(100); + return i2c->reg_get(i2c, reg); +} + +static void fpgai2c_dump(struct fpgalogic_i2c *i2c) +{ + u8 tmp; + + 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_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_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); +} + +static void fpgai2c_stop(struct fpgalogic_i2c *i2c) +{ + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP); +} + +/* + * dell_get_mutex must be called prior to calling this function. + */ +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; + } + + /* 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); + + 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); + + 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 (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); + } + + 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); + 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)); + 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); +} +static DEVICE_ATTR(port_msi, S_IRUGO, get_mod_msi, NULL); + +static struct attribute *port_attrs[] = { + &dev_attr_port_msi.attr, + NULL, +}; + +static struct attribute_group port_attr_grp = { + .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); + 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)); + 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)); + } + } + 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; +} + +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); + 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)); + 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); + iowrite32( IRQ_LTCH_STS|PRSNT_LTCH_STS,fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16)); + } + } + 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; +} + +static void fpgai2c_process(struct fpgalogic_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + u8 stat = fpgai2c_reg_get(i2c, FPGAI2C_REG_STATUS); + + PRINT("fpgai2c_process in. status reg :0x%x\n", stat); + + 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); + 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; + } + + + /* error? */ + if (stat & FPGAI2C_REG_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + PRINT("fpgai2c_process FPGAI2C_REG_STAT_ARBLOST FPGAI2C_REG_CMD_STOP\n"); + fpgai2c_stop(i2c); + return; + } + + 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_stop(i2c); + return; + } + } else + { + msg->buf[i2c->pos++] = fpgai2c_reg_get(i2c, FPGAI2C_REG_DATA); + } + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { /* end? */ + /* send start? */ + if (!(msg->flags & I2C_M_NOSTART)) { + + u8 addr = (msg->addr << 1); + + if (msg->flags & I2C_M_RD) + addr |= 1; + + i2c->state = STATE_START; + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, addr); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + return; + } else + { + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } + } else { + i2c->state = STATE_STOP; + fpgai2c_stop(i2c); + return; + } + } + + 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); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, i2c->pos == (msg->len-1) ? + 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++]); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE); + } +} + +static irqreturn_t fpgai2c_isr(int irq, void *dev_id) +{ + struct fpgalogic_i2c *i2c = dev_id; + fpgai2c_process(i2c); + + return IRQ_HANDLED; +} +void dell_get_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_lock(&i2c->lock); +} + +/** + * dell_release_mutex - release mutex + */ +void dell_release_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_unlock(&i2c->lock); +} + +static int fpgai2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct fpgalogic_i2c *i2c = i2c_get_adapdata(adap); + int ret; + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = (use_irq == 1) ? STATE_START : STATE_INIT; + + PRINT("i2c->msg->addr = 0x%x i2c->msg->flags = 0x%x\n",i2c->msg->addr,i2c->msg->flags); + PRINT("I2C_M_RD = 0x%x i2c->msg->addr << 1 = 0x%x\n",I2C_M_RD,i2c->msg->addr << 1); + + if (!use_irq) { + /* Handle the transfer */ + while (time_before(jiffies, timeout)) { + dell_get_mutex(i2c); + ret = fpgai2c_poll(i2c); + dell_release_mutex(i2c); + + if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) + return (i2c->state == STATE_DONE) ? num : ret; + + if (ret == 0) + timeout = jiffies + HZ; + + usleep_range(5, 15); + } + + i2c->state = STATE_ERROR; + + return -ETIMEDOUT; + + + } 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)); + + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, + (i2c->msg->addr << 1) | + ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + + /* Interrupt mode */ + if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || + (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; + } + } + + 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; + } + + 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; +} + +static const struct i2c_algorithm fpgai2c_algorithm = { + .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; +} + +static int i2c_init_internal_data(void) +{ + 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; +} + + +static int i2c_pci_init (void) +{ + int i; + + if (num_bus == 0) { + board_rev_type = ioread32(fpga_ctl_addr + MB_BRD_REV_TYPE); + + 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)) { + switch (board_rev_type & MB_BRD_TYPE_MASK){ + case BRD_TYPE_S5212_NON_NEBS: + case BRD_TYPE_S5212_NEBS: + num_bus = I2C_PCI_BUS_NUM_5; + break; + case BRD_TYPE_S5224_NON_NEBS: + case BRD_TYPE_S5224_NEBS: + num_bus = I2C_PCI_BUS_NUM_7; + break; + case BRD_TYPE_Z9232_NON_NEBS: + case BRD_TYPE_Z9232_NEBS: + case BRD_TYPE_S5232_NON_NEBS: + case BRD_TYPE_S5232_NEBS: + num_bus = I2C_PCI_BUS_NUM_8; + break; + case BRD_TYPE_S5248_NON_NEBS: + case BRD_TYPE_S5248_NEBS: + num_bus = I2C_PCI_BUS_NUM_10; + break; + case BRD_TYPE_Z9264_NON_NEBS: + case BRD_TYPE_Z9264_NEBS: + num_bus = I2C_PCI_BUS_NUM_12; + break; + case BRD_TYPE_S5296_NON_NEBS: + case BRD_TYPE_S5296_NEBS: + num_bus = I2C_PCI_BUS_NUM_16; + break; + default: + num_bus = I2C_PCI_BUS_NUM_16; + printk("Wrong BRD_TYPE: 0x%x\n", board_rev_type); + break; + } + } else { + printk("Wrong board_rev_type 0x%x\n", board_rev_type); + } + } + + 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]); + + /* Initialize driver's itnernal data structures */ + i2c_init_internal_data(); + + 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].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)); + } + + 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]); + } + +} + +/* Find upstream PCIe root node. + * 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; + } +} + + +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); + } + } + + return 0; +} + + +/** + * Map the device memory regions into kernel virtual address space + * after verifying their sizes respect the minimum sizes needed, given + * by the bar_min_len[] array. + */ +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + 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; + + + 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; + } + + 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); + + 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); + + 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; +} + +static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + int i; + + 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" + +/** + * @brief Register specific function with msi interrupt line + * @param dev Pointer to pci-device, which should be allocated + * @param int interrupt number relative to global interrupt number + * @return Returns error code or zero if success + * */ +static int register_intr_handler(struct pci_dev *dev, int irq_num_id) +{ + 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; + } + + 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 + * 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; + } + } 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 */ + 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; + } + } + + return err; +} +/* Mask for MSI Multi message enable bits */ +#define MSI_MME 0x70 +/** + * These enums define the type of interrupt scheme that the overall + * system uses. + */ +enum fpga_irq_type { + INT_MSI_SINGLE, + INT_MSI_MULTI, + INT_MSIX, + INT_NONE, + INT_FENCE /* Last item to guard from loop run-overs */ +}; +/** + * @def PCI_DEVICE_STATUS + * define the offset for STS register + * from the start of PCI config space as specified in the + * NVME_Comliance 1.0b. offset 06h:STS - Device status. + * This register has error status for NVME PCI Exress + * Card. After reading data from this reagister, the driver + * will identify if any error is set during the operation and + * report as kernel alert message. + */ +#define PCI_DEVICE_STATUS 0x6 +/** + * @def NEXT_MASK + * This indicates the location of the next capability item + * in the list. + */ +#define NEXT_MASK 0xFF00 +/** + * @def MSIXCAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSIXCAP_ID 0x11 +/** + * @def MSICAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSICAP_ID 0x5 + +/** + * @def CL_MASK + * This bit position indicates Capabilities List of the controller + * The controller should support the PCI Power Management cap as a + * minimum. + */ +#define CL_MASK 0x0010 + +/** + * @def CAP_REG + * Set to offset defined in NVME Spec 1.0b. + */ +#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; + + 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; + + + /* + * 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); + + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + } +} +/** + * @brief Enables pcie-device and claims/remaps neccessary bar resources + * @param dev Pointer to pci-device, which should be allocated + * @return Returns error code or zero if success + * */ +static int fpgapci_setup_device(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + 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; + } + + /* 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); + + /* 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); + + if (map_bars(fpgapci, dev)) { + goto fail_map_bars; + } + + i2c_pci_init(); + + return 0; + /* ERROR HANDLING */ +fail_map_bars: + pci_release_regions(dev); +error_pci_req: + pci_disable_device(dev); +error_pci_en: + return -ENODEV; +} + +static int fpgapci_configure_msi(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + int err = 0, i; + int request_vec; + + 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); + + 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)) { + if (err < MSI_VECTOR_REV_01) { + goto error_disable_msi; + } + } + } + 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; + } + } + + 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); + 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); +error_no_msi: + return -ENOSPC; +} + +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + 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)); +#endif + fpgapci = kzalloc(sizeof(struct fpgapci_dev), GFP_KERNEL); + + if (!fpgapci) { + PRINT( "Couldn't allocate memory!\n"); + goto fail_kzalloc; + } + + fpgapci->pci_dev = dev; + dev_set_drvdata(&dev->dev, (void*)fpgapci); + + status = sysfs_create_group(&dev->dev.kobj, &port_attr_grp); + if (status) { + printk(KERN_INFO "%s:Cannot create sysfs\n", __FUNCTION__); + } + + fpgapci->upstream = find_upstream_dev (dev); + + 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 */ +error_cannot_configure: + 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"); +fail_kzalloc: + 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); + 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]); + } + } + pci_disable_msi(fpgapci->pci_dev); + free_bars (fpgapci, dev); + pci_disable_device(dev); + pci_release_regions(dev); + + kfree (fpgapci); +} + +static const struct pci_device_id fpgapci_ids[] = { + {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 */ +}; + +/* Initialize the driver module (but not any device) and register + * the module with the kernel PCI subsystem. */ +static int __init fpgapci_init(void) +{ + + if (pci_register_driver(&fpgapci_driver)) { + PRINT("pci_unregister_driver\n"); + pci_unregister_driver(&fpgapci_driver); + return -ENODEV; + } + + return 0; +} + +static void __exit fpgapci_exit(void) +{ + PRINT ("fpgapci_exit"); + + /* unregister this driver from the PCI bus driver */ + pci_unregister_driver(&fpgapci_driver); + +} + + +module_init (fpgapci_init); +module_exit (fpgapci_exit); +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/s5296f/scripts/pcisysfs.py b/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/pcisysfs.py new file mode 100755 index 000000000000..047618e057c8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/pcisysfs.py @@ -0,0 +1,102 @@ +#!/usr/bin/python +# Copyright (c) 2015 Dell Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. + +import struct +import sys +import getopt +from os import * +from mmap import * + +def usage(): + ''' This is the Usage Method ''' + + print '\t\t pcisysfs.py --get --offset --res ' + print '\t\t pcisysfs.py --set --val --offset --res ' + sys.exit(1) + +def pci_mem_read(mm,offset): + mm.seek(offset) + read_data_stream=mm.read(4) + print "" + reg_val=struct.unpack('I',read_data_stream) + print "reg_val read:%x"%reg_val + return reg_val + +def pci_mem_write(mm,offset,data): + mm.seek(offset) + print "data to write:%x"%data + mm.write(struct.pack('I',data)) + +def pci_set_value(resource,val,offset): + fd=open(resource,O_RDWR) + mm=mmap(fd,0) + pci_mem_write(mm,offset,val) + +def pci_get_value(resource,offset): + fd=open(resource,O_RDWR) + mm=mmap(fd,0) + pci_mem_read(mm,offset) + +def main(argv): + + ''' The main function will read the user input from the + command line argument and process the request ''' + + opts = '' + val = '' + choice = '' + resource = '' + offset = '' + + try: + opts, args = getopt.getopt(argv, "hgsv:" , \ + ["val=","res=","offset=","help", "get", "set"]) + + except getopt.GetoptError: + usage() + + for opt,arg in opts: + + if opt in ('-h','--help'): + choice = 'help' + + elif opt in ('-g', '--get'): + choice = 'get' + + elif opt in ('-s', '--set'): + choice = 'set' + + elif opt == '--res': + resource = arg + + elif opt == '--val': + val = int(arg,16) + + elif opt == '--offset': + offset = int(arg,16) + + if choice == 'set' and val != '' and offset !='' and resource !='': + pci_set_value(resource,val,offset) + + elif choice == 'get' and offset != '' and resource !='': + pci_get_value(resource,offset) + + else: + usage() + +#Calling the main method +if __name__ == "__main__": + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/platform_sensors.py new file mode 100755 index 000000000000..4c6ef3b229ab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/platform_sensors.py @@ -0,0 +1,242 @@ +#!/usr/bin/python +# On S5296F, the BaseBoard Management Controller is an +# autonomous subsystem provides monitoring and management +# facility independent of the host CPU. IPMI standard +# protocol is used with ipmitool to fetch sensor details. +# Current script support X00 board only. X01 support will +# be added soon. This provies support for the +# following objects: +# * Onboard temperature sensors +# * FAN trays +# * PSU + + +import sys +import logging +import commands + +S5296F_MAX_FAN_TRAYS = 4 +S5296F_MAX_PSUS = 2 +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_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_sdr_list = "" + +# Dump sensor registers + + +def ipmi_sensor_dump(): + + global ipmi_sdr_list + ipmi_cmd = IPMI_SENSOR_DATA + status, ipmi_sdr_list = commands.getstatusoutput(ipmi_cmd) + + if status: + logging.error('Failed to execute:' + ipmi_sdr_list) + sys.exit(0) + +# Fetch a BMC register + + +def get_pmc_register(reg_name): + + output = None + for item in ipmi_sdr_list.split("\n"): + if reg_name in item: + output = item.strip() + + if output is None: + print('\nFailed to fetch: ' + reg_name + ' sensor ') + sys.exit(0) + + output = output.split('|')[1] + + logging.basicConfig(level=logging.DEBUG) + return output + + +# Print the information for temperature sensors + + +def print_temperature_sensors(): + + print("\nOnboard Temperature Sensors:") + + print ' PT_Left_temp: ',\ + (get_pmc_register('PT_Left_temp')) + print ' PT_Mid_temp: ',\ + (get_pmc_register('PT_Mid_temp')) + print ' PT_Right_temp: ',\ + (get_pmc_register('PT_Right_temp')) + print ' Broadcom Temp: ',\ + (get_pmc_register('NPU_Near_temp')) + print ' Inlet Airflow Temp: ',\ + (get_pmc_register('ILET_AF_temp')) + print ' CPU Temp: ',\ + (get_pmc_register('CPU_temp')) + +ipmi_sensor_dump() + +print_temperature_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(tray): + + Fan_Status = [' Normal', ' Abnormal'] + + print ' Fan Tray ' + str(tray) + ':' + + if (tray == 1): + + fan2_status = int(get_pmc_register('FAN1_Rear_stat'), 16) + + print ' Fan Speed: ',\ + get_pmc_register('FAN1_Rear_rpm') + print ' Fan State: ',\ + Fan_Status[fan2_status] + + elif (tray == 2): + + fan2_status = int(get_pmc_register('FAN2_Rear_stat'), 16) + + print ' Fan Speed: ',\ + get_pmc_register('FAN2_Rear_rpm') + print ' Fan State: ',\ + Fan_Status[fan2_status] + + elif (tray == 3): + + fan2_status = int(get_pmc_register('FAN3_Rear_stat'), 16) + + print ' Fan Speed: ',\ + get_pmc_register('FAN3_Rear_rpm') + print ' Fan State: ',\ + Fan_Status[fan2_status] + + elif (tray == 4): + + fan2_status = int(get_pmc_register('FAN4_Rear_stat'), 16) + + print ' Fan Speed: ',\ + get_pmc_register('FAN4_Rear_rpm') + print ' Fan State: ',\ + Fan_Status[fan2_status] + + +print('\nFan Trays:') + +for tray in range(1, S5296F_MAX_FAN_TRAYS + 1): + fan_presence = FAN_PRESENCE.format(tray) + if (get_pmc_register(fan_presence)): + print_fan_tray(tray) + else: + print '\n Fan Tray ' + str(tray + 1) + ': Not present' + + 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 + """ + status = 0 + + if index == 1: + 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: + # print ipmi_cmd_ret + # logging.error('Failed to execute ipmitool') + # sys.exit(0) + + psu_status = ipmi_cmd_ret + + if psu_status == '1': + status = 1 + + return status + + +# Print the information for PSU1, PSU2 +def print_psu(psu): + + # print ' Input: ', Psu_Input_Type[psu_input_type] + # print ' Type: ', Psu_Type[psu_type] + + # PSU FAN details + if (psu == 1): + + # psu1_fan_status = int(get_pmc_register('PSU1_status'),16) + + print ' PSU1:' + print ' FAN Normal Temperature: ',\ + get_pmc_register('PSU1_temp') + print ' FAN AirFlow Temperature: ',\ + get_pmc_register('PSU1_AF_temp') + print ' FAN RPM: ',\ + get_pmc_register('PSU1_rpm') + # print ' FAN Status: ', Psu_Fan_Status[psu1_fan_status] + + # PSU input & output monitors + print ' Input Voltage: ',\ + get_pmc_register('PSU1_In_volt') + print ' Output Voltage: ',\ + get_pmc_register('PSU1_Out_volt') + print ' Input Power: ',\ + get_pmc_register('PSU1_In_watt') + print ' Output Power: ',\ + get_pmc_register('PSU1_Out_watt') + print ' Input Current: ',\ + get_pmc_register('PSU1_In_amp') + print ' Output Current: ',\ + get_pmc_register('PSU1_Out_amp') + + else: + + # psu2_fan_status = int(get_pmc_register('PSU1_status'),16) + print ' PSU2:' + print ' FAN Normal Temperature: ',\ + get_pmc_register('PSU2_temp') + print ' FAN AirFlow Temperature: ',\ + get_pmc_register('PSU2_AF_temp') + print ' FAN RPM: ',\ + get_pmc_register('PSU2_rpm') + # print ' FAN Status: ', Psu_Fan_Status[psu2_fan_status] + + # PSU input & output monitors + print ' Input Voltage: ',\ + get_pmc_register('PSU2_In_volt') + print ' Output Voltage: ',\ + get_pmc_register('PSU2_Out_volt') + print ' Input Power: ',\ + get_pmc_register('PSU2_In_watt') + print ' Output Power: ',\ + get_pmc_register('PSU2_Out_watt') + print ' Input Current: ',\ + get_pmc_register('PSU2_In_amp') + print ' Output Current: ',\ + get_pmc_register('PSU2_Out_amp') + + +print('\nPSUs:') +for psu in range(1, S5296F_MAX_PSUS + 1): + #psu_presence = PSU_PRESENCE.format(psu) + if (get_psu_presence(psu)): + print_psu(psu) + else: + print '\n PSU ', psu, 'Not present' + +print '\n Total Power: ',\ + get_pmc_register('PSU_Total_watt') + diff --git a/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/qsfp_irq_enable.py b/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/qsfp_irq_enable.py new file mode 100755 index 000000000000..d9bf5b09411a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/qsfp_irq_enable.py @@ -0,0 +1,31 @@ +#!/usr/bin/python + +try: + import struct + from os import * + from mmap import * + +except ImportError as e: + raise ImportError("%s - required module no found" % str(e)) + +BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" +PORT_START = 0 +PORT_END = 32 + + +def pci_mem_write(mm, offset, data): + mm.seek(offset) + mm.write(struct.pack('I', data)) + + +def pci_set_value(resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + pci_mem_write(mm, offset, val) + mm.close() + close(fd) + return val + +for port_num in range(PORT_START, PORT_END+1): + port_offset = 0x400c + ((port_num) * 16) + pci_set_value(BASE_RES_PATH, 0x30, port_offset) diff --git a/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/s5296f_platform.sh b/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/s5296f_platform.sh new file mode 100755 index 000000000000..f69470756001 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/s5296f_platform.sh @@ -0,0 +1,176 @@ +#!/bin/bash + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find iSMT" && exit 1 +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + b='' + for bb in 0 1; do + if [ "$(cat /sys/bus/i2c/devices/i2c-${bb}/name)" = 'SMBus iSMT adapter at dff9f000' ]; then + b=$bb + break + fi + done + if [ "$b" = '' ]; then + echo "s5296f_platform: sys_eeprom : cannot find I2C bus!" + return + fi + + case $1 in + "new_device") echo 24c16 0x50 > /sys/bus/i2c/devices/i2c-${b}/$1 + ;; + + "delete_device") echo 0x50 > /sys/bus/i2c/devices/i2c-${b}/$1 + ;; + + *) echo "s5296f_platform: sys_eeprom : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs +switch_board_qsfp_mux() { + case $1 in + "new_device") + for ((i=603;i<=615;i++)); + do + echo "Attaching PCA9548 @ 0x74" + echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=603;i<=615;i++)); + do + echo "Detaching PCA9548 @ 0x74" + echo 0x74 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) + echo "s5296f_platform: switch_board_qsfp_mux: invalid command !" + ;; + esac + sleep 2 +} + +#Attach/Detach 64 instances of EEPROM driver QSFP ports +#eeprom can dump data using below command +switch_board_qsfp() { + case $1 in + "new_device") + for ((i=2;i<=105;i++)); + do + echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=2;i<=105;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "s5296f_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +#Modsel 64 ports to applicable QSFP type modules +#This enables the adapter to respond for i2c commands +switch_board_modsel() { + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + for ((i=1;i<=104;i++)); + do + port_addr=$(( 16384 + ((i - 1) * 16))) + hex=$( printf "0x%x" $port_addr ) + python /usr/bin/pcisysfs.py --set --offset $hex --val 0x10 --res $resource > /dev/null 2>&1 + done +} + +platform_firmware_versions() { + FIRMWARE_VERSION_FILE=/var/log/firmware_versions + rm -rf ${FIRMWARE_VERSION_FILE} + echo "BIOS: `dmidecode -s system-version `" > $FIRMWARE_VERSION_FILE + ## Get FPGA version + r=`/usr/bin/pcisysfs.py --get --offset 0x00 --res /sys/bus/pci/devices/0000\:04\:00.0/resource0 | sed '1d; s/.*\(....\)$/\1/; s/\(..\{1\}\)/\1./'` + r_min=$(echo $r | sed 's/.*\(..\)$/0x\1/') + r_maj=$(echo $r | sed 's/^\(..\).*/0x\1/') + echo "FPGA: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE + + ## Get BMC Firmware Revision + r=`cat /sys/class/ipmi/ipmi0/device/bmc/firmware_revision` + echo "BMC: $r" >> $FIRMWARE_VERSION_FILE + + #System CPLD 0x31 on i2c bus 601 ( physical FPGA I2C-2) + r_min=`/usr/sbin/i2cget -y 601 0x31 0x0 | sed ' s/.*\(0x..\)$/\1/'` + r_maj=`/usr/sbin/i2cget -y 601 0x31 0x1 | sed ' s/.*\(0x..\)$/\1/'` + echo "System CPLD: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE + + #Slave CPLD 1 0x30 on i2c bus 600 ( physical FPGA I2C-1) + r_min=`/usr/sbin/i2cget -y 600 0x30 0x0 | sed ' s/.*\(0x..\)$/\1/'` + r_maj=`/usr/sbin/i2cget -y 600 0x30 0x1 | sed ' s/.*\(0x..\)$/\1/'` + echo "Slave CPLD 1: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE + + #Slave CPLD 2 0x31 on i2c bus 600 ( physical FPGA I2C-1) + r_min=`/usr/sbin/i2cget -y 600 0x31 0x0 | sed ' s/.*\(0x..\)$/\1/'` + r_maj=`/usr/sbin/i2cget -y 600 0x31 0x1 | sed ' s/.*\(0x..\)$/\1/'` + echo "Slave CPLD 2: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE + + #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 +} + +#This enables the led control for CPU and default states +switch_board_led_default() { + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + python /usr/bin/pcisysfs.py --set --offset 0x24 --val 0x194 --res $resource > /dev/null 2>&1 +} +init_devnum + +if [ "$1" == "init" ]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe ipmi_devintf + modprobe ipmi_si + modprobe i2c_ocores + modprobe dell_s5296f_fpga_ocores + sys_eeprom "new_device" + switch_board_qsfp_mux "new_device" + switch_board_qsfp "new_device" + 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_qsfp_mux "delete_device" + + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev +else + echo "s5296f_platform : Invalid option !" +fi + diff --git a/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/sensors new file mode 100755 index 000000000000..d163a09cfc1b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5296f/scripts/sensors @@ -0,0 +1,3 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" +docker exec -i pmon /usr/bin/platform_sensors.py "$@" diff --git a/platform/broadcom/sonic-platform-modules-dell/s5296f/systemd/platform-modules-s5296f.service b/platform/broadcom/sonic-platform-modules-dell/s5296f/systemd/platform-modules-s5296f.service new file mode 100644 index 000000000000..b58673d505ac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s5296f/systemd/platform-modules-s5296f.service @@ -0,0 +1,13 @@ +[Unit] +Description=Dell S5296f Platform modules +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/s5296f_platform.sh init +ExecStop=/usr/local/bin/s5296f_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/LICENSE b/platform/broadcom/sonic-platform-modules-dell/s6000/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/MAINTAINERS b/platform/broadcom/sonic-platform-modules-dell/s6000/MAINTAINERS new file mode 100644 index 000000000000..65e3129fcc13 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/MAINTAINERS @@ -0,0 +1,7 @@ +# This file describes the maintainers for sonic-platform-modules-s6000 +# See the SONiC project governance document for more information + +Name = "Shuotian Cheng" +Email = "shuche@microsoft.com" +Github = stcheng +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/README.md b/platform/broadcom/sonic-platform-modules-dell/s6000/README.md new file mode 100644 index 000000000000..7913d168a30a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-s6000 +Device drivers for support of Dell S6000 for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/s6000/modules/Makefile new file mode 100644 index 000000000000..12e80d01010c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/modules/Makefile @@ -0,0 +1 @@ +obj-m := dell_s6000_platform.o diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/modules/dell_s6000_platform.c b/platform/broadcom/sonic-platform-modules-dell/s6000/modules/dell_s6000_platform.c new file mode 100644 index 000000000000..cbf506940ac9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/modules/dell_s6000_platform.c @@ -0,0 +1,1380 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define S6000_MUX_BASE_NR 10 +#define QSFP_MODULE_BASE_NR 20 + +/* 74CBTLV3253 Dual 1-of-4 multiplexer/demultiplexer */ +#define MUX_CHANNEL_NUM 2 + +#define CPLD_DEVICE_NUM 3 +#define QSFP_MODULE_NUM 16 +#define QSFP_DEVICE_NUM 2 + +#define GPIO_I2C_MUX_PIN 10 + +#define RTC_NVRAM_REBOOT_REASON_OFFSET 0x49 + +static void device_release(struct device *dev) +{ + return; +} + +/* + * S6000 74CBTLV3253 MUX + */ +static const unsigned s6000_mux_gpios[] = { + 1, 2 +}; + +static const unsigned s6000_mux_values[] = { + 0, 1, 2, 3 +}; + +static struct i2c_mux_gpio_platform_data s6000_mux_platform_data = { + .parent = 2, + .base_nr = S6000_MUX_BASE_NR, + .values = s6000_mux_values, + .n_values = ARRAY_SIZE(s6000_mux_values), + .gpios = s6000_mux_gpios, + .n_gpios = ARRAY_SIZE(s6000_mux_gpios), + .idle = 0, +}; + +static struct platform_device s6000_mux = { + .name = "i2c-mux-gpio", + .id = 0, + .dev = { + .platform_data = &s6000_mux_platform_data, + .release = device_release + }, +}; + +/* + * S6000 CPLD + */ + +enum cpld_type { + system_cpld, + master_cpld, + slave_cpld, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data s6000_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = 0x31, + }, + + [master_cpld] = { + .reg_addr = 0x32, + }, + + [slave_cpld] = { + .reg_addr = 0x33, + }, +}; + +static struct platform_device s6000_cpld = { + .name = "dell-s6000-cpld", + .id = 0, + .dev = { + .platform_data = s6000_cpld_platform_data, + .release = device_release + }, +}; + +/* + * S6000 QSFP MUX + */ + +struct qsfp_mux_platform_data { + int parent; + int base_nr; + int reg_addr; + struct i2c_client *cpld; +}; + +struct qsfp_mux { + struct qsfp_mux_platform_data data; +}; + +static struct qsfp_mux_platform_data s6000_qsfp_mux_platform_data[] = { + { + .parent = S6000_MUX_BASE_NR + 2, + .base_nr = QSFP_MODULE_BASE_NR, + .cpld = NULL, + .reg_addr = 0x0, + }, + { + .parent = S6000_MUX_BASE_NR + 3, + .base_nr = QSFP_MODULE_BASE_NR + QSFP_MODULE_NUM, + .cpld = NULL, + .reg_addr = 0xa, + }, +}; + +static struct platform_device s6000_qsfp_mux[] = { + { + .name = "dell-s6000-qsfp-mux", + .id = 0, + .dev = { + .platform_data = &s6000_qsfp_mux_platform_data[0], + .release = device_release, + }, + }, + { + .name = "dell-s6000-qsfp-mux", + .id = 1, + .dev = { + .platform_data = &s6000_qsfp_mux_platform_data[1], + .release = device_release, + }, + }, +}; + +static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); +} + +static int qsfp_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct qsfp_mux *mux = i2c_mux_priv(muxc); + unsigned short mask = ~(unsigned short)(1 << chan); + + cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(mask & 0xff)); + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr + 1, (u8)(mask >> 8)); +} + +static int __init qsfp_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct qsfp_mux *mux; + struct qsfp_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); + if (!mux) { + return -ENOMEM; + } + + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -EPROBE_DEFER; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, QSFP_MODULE_NUM, 0, 0, + qsfp_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + + platform_set_drvdata(pdev, muxc); + + for (i = 0; i < QSFP_MODULE_NUM; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + dev_info(&pdev->dev, "%d port mux on %s adapter\n", QSFP_MODULE_NUM, parent->name); + + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + i2c_put_adapter(parent); + + return ret; +} + +static int qsfp_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + + i2c_mux_del_adapters(muxc); + + i2c_put_adapter(muxc->parent); + + return 0; +} + +static struct platform_driver qsfp_mux_driver = { + .probe = qsfp_mux_probe, + .remove = qsfp_mux_remove, + .driver = { + .owner = THIS_MODULE, + .name = "dell-s6000-qsfp-mux", + }, +}; + +/* TODO */ +/* module_platform_driver */ + +static int dell_i2c_smbus_read_byte_data(const struct i2c_client *client, + u8 command) +{ + int ret = 0; + + ret = i2c_smbus_read_byte_data(client, command); + if(ret < 0) { + printk(KERN_WARNING "I2C smbus read failed. Resetting mux with gpio10"); + gpio_set_value(GPIO_I2C_MUX_PIN, 1); + gpio_set_value(GPIO_I2C_MUX_PIN, 0); + ret = i2c_smbus_read_byte_data(client, command); + } + return ret; +} + +static int dell_i2c_smbus_write_byte_data(const struct i2c_client *client, + u8 command, u8 value) +{ + int ret = 0; + + ret = i2c_smbus_write_byte_data(client, command, value); + if(ret < 0) + { + printk(KERN_WARNING "I2C smbus write failed. Resetting mux with gpio10"); + gpio_set_value(GPIO_I2C_MUX_PIN, 1); + gpio_set_value(GPIO_I2C_MUX_PIN, 0); + ret = i2c_smbus_write_byte_data(client, command, value); + } + return ret; +} + +static ssize_t get_modsel(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x0); + if (ret < 0) + return sprintf(buf, "na"); + data = (u32)ret & 0xff; + + ret = dell_i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x1); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 8; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xa); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 16; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xb); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x2); + if (ret < 0) + return sprintf(buf, "na"); + data = (u32)ret & 0xff; + + ret = dell_i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x3); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 8; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xc); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 16; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xd); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + dell_i2c_smbus_write_byte_data(pdata[slave_cpld].client, 0x2, (u8)(data & 0xff)); + dell_i2c_smbus_write_byte_data(pdata[slave_cpld].client, 0x3, (u8)((data >> 8) & 0xff)); + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0xc, (u8)((data >> 16) & 0xff)); + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0xd, (u8)((data >> 24) & 0xff)); + + return count; +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x6); + if (ret < 0) + return sprintf(buf, "na"); + data = (u32)ret & 0xff; + + ret = dell_i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 8; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x10); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 16; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x11); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + dell_i2c_smbus_write_byte_data(pdata[slave_cpld].client, 0x6, (u8)(data & 0xff)); + dell_i2c_smbus_write_byte_data(pdata[slave_cpld].client, 0x7, (u8)((data >> 8)& 0xff)); + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x10, (u8)((data >> 16) & 0xff)); + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x11, (u8)((data >> 24) & 0xff)); + + return count; +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x4); + if (ret < 0) + return sprintf(buf, "read error"); + data = (u32)ret & 0xff; + + ret = dell_i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0x5); + if (ret < 0) + return sprintf(buf, "read error"); + data |= (u32)(ret & 0xff) << 8; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xe); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 16; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0xf); + if (ret < 0) + return sprintf(buf, "na"); + data |= (u32)(ret & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); +} + +static ssize_t set_power_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 10, &data); + if (err) + return err; + + if (data) + { + dell_i2c_smbus_write_byte_data(pdata[system_cpld].client, 0x1, (u8)(0xfd)); + } + + return count; +} + +static ssize_t get_power_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + uint8_t ret = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[system_cpld].client, 0x1); + if (ret < 0) + return sprintf(buf, "read error"); + + return sprintf(buf, "0x%x\n", ret); +} + +static ssize_t get_fan_prs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return sprintf(buf, "read error"); + data = (u32)((ret & 0xc0) >> 6); + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x9); + if (ret < 0) + return sprintf(buf, "read error"); + data |= (u32)((ret & 0x01) << 2); + data = ~data & 0x7; + + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t get_psu0_prs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x3); + if (ret < 0) + return sprintf(buf, "read error"); + + if (!(ret & 0x80)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_psu1_prs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x3); + if (ret < 0) + return sprintf(buf, "read error"); + + if (!(ret & 0x08)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_psu0_status(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x3); + if (ret < 0) + return sprintf(buf, "read error"); + + if (!(ret & 0x40)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_psu1_status(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x3); + if (ret < 0) + return sprintf(buf, "read error"); + + if (!(ret & 0x04)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_powersupply_status(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int data; + struct cpld_platform_data *pdata = dev->platform_data; + + data = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x3); + if (data < 0) + return sprintf(buf, "read error"); + + return sprintf(buf, "%x\n", data); +} + +static ssize_t get_system_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x60) >> 5; + + switch (data) + { + case 0: + ret = sprintf(buf, "blink_green\n"); + break; + case 1: + ret = sprintf(buf, "green\n"); + break; + case 2: + ret = sprintf(buf, "yellow\n"); + break; + default: + ret = sprintf(buf, "blink_yellow\n"); + } + + return ret; +} + +static ssize_t set_system_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "blink_green", 11)) + { + data = 0; + } + else if (!strncmp(buf, "green", 5)) + { + data = 1; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 2; + } + else if (!strncmp(buf, "blink_yellow", 12)) + { + data = 3; + } + else + { + return -1; + } + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return ret; + + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x7, (u8)((ret & 0x9F) | (data << 5))); + + return count; +} + +static ssize_t get_locator_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x18) >> 3; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "blink_blue\n"); + break; + case 2: + ret = sprintf(buf, "blue\n"); + break; + default: + ret = sprintf(buf, "invalid\n"); + } + + return ret; +} + +static ssize_t set_locator_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "blink_blue", 10)) + { + data = 1; + } + else if (!strncmp(buf, "blue", 4)) + { + data = 2; + } + else + { + return -1; + } + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return ret; + + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x7, (u8)((ret & 0xE7) | (data << 3))); + + return count; +} + +static ssize_t get_power_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x06) >> 1; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "yellow\n"); + break; + case 2: + ret = sprintf(buf, "green\n"); + break; + default: + ret = sprintf(buf, "blink_yellow\n"); + } + + return ret; +} + +static ssize_t set_power_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 1; + } + else if (!strncmp(buf, "green", 5)) + { + data = 2; + } + else if (!strncmp(buf, "blink_yellow", 12)) + { + data = 3; + } + else + { + return -1; + } + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return ret; + + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x7, (u8)((ret & 0xF9) | (data << 1))); + + return count; +} + +static ssize_t get_master_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x1); + + switch (data) + { + case 0: + ret = sprintf(buf, "green\n"); + break; + default: + ret = sprintf(buf, "off\n"); + break; + } + + return ret; +} + +static ssize_t set_master_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "green", 5)) + { + data = 0; + } + else if (!strncmp(buf, "off", 3)) + { + data = 1; + } + else + { + return -1; + } + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x7); + if (ret < 0) + return ret; + + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x7, (u8)((ret & 0xFE) | data)); + + return count; +} + +static ssize_t get_fan_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x9); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x18) >> 3; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "yellow\n"); + break; + case 2: + ret = sprintf(buf, "green\n"); + break; + default: + ret = sprintf(buf, "blink_yellow\n"); + } + + return ret; +} + +static ssize_t set_fan_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 1; + } + else if (!strncmp(buf, "green", 5)) + { + data = 2; + } + else if (!strncmp(buf, "blink_yellow", 12)) + { + data = 3; + } + else + { + return -1; + } + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x9); + if (ret < 0) + return ret; + + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x9, (u8)((ret & 0xE7) | (data << 3))); + + return count; +} + +static ssize_t get_fan0_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x3); + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "green\n"); + break; + case 2: + ret = sprintf(buf, "yellow\n"); + break; + default: + ret = sprintf(buf, "unknown\n"); + } + + return ret; +} + +static ssize_t set_fan0_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 2; + } + else if (!strncmp(buf, "green", 5)) + { + data = 1; + } + else + { + return -1; + } + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return ret; + + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x8, (u8)((ret & 0xFC) | data)); + + return count; +} + + +static ssize_t get_fan1_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0xc) >> 2; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "green\n"); + break; + case 2: + ret = sprintf(buf, "yellow\n"); + break; + default: + ret = sprintf(buf, "unknown\n"); + } + + return ret; +} + +static ssize_t set_fan1_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 2; + } + else if (!strncmp(buf, "green", 5)) + { + data = 1; + } + else + { + return -1; + } + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return ret; + + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x8, (u8)((ret & 0xF3) | (data << 2))); + + return count; +} + +static ssize_t get_fan2_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x30) >> 4; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "green\n"); + break; + case 2: + ret = sprintf(buf, "yellow\n"); + break; + default: + ret = sprintf(buf, "unknown\n"); + } + + return ret; +} + +static ssize_t set_fan2_led(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 2; + } + else if (!strncmp(buf, "green", 5)) + { + data = 1; + } + else + { + return -1; + } + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x8); + if (ret < 0) + return ret; + + dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0x8, (u8)((ret & 0xCF) | (data << 4))); + + return count; +} + +static ssize_t get_system_cpld_ver(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + uint8_t ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[system_cpld].client, 0x0); + if (ret < 0) + return sprintf(buf, "read error"); + + data = ret & (0x0f); + + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t get_master_cpld_ver(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + uint8_t ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[master_cpld].client, 0x1); + if (ret < 0) + return sprintf(buf, "read error"); + + data = ret & (0x0f); + + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t get_slave_cpld_ver(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + uint8_t ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = dell_i2c_smbus_read_byte_data(pdata[slave_cpld].client, 0xa); + if (ret < 0) + return sprintf(buf, "read error"); + + data = ret & (0x0f); + + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t get_reboot_reason(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + uint8_t data = 0; + + /* Last Reboot reason in saved in RTC NVRAM offset 0x49 + * We write the reboot reason into nvram offset, + * as part of platform_reboot implementation from userspace. + + * COLD_RESET = 0xE # Cold Reset (value) + * WARM_RESET = 0x6 # Warm Reset (value) + */ + + /* Read it from this offset, and export it as last_reboot_reason */ + data = nvram_read_byte(RTC_NVRAM_REBOOT_REASON_OFFSET); + + return sprintf(buf, "0x%x\n", data); +} + +static DEVICE_ATTR(qsfp_modsel, S_IRUGO, get_modsel, NULL); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset); +static DEVICE_ATTR(power_reset, S_IRUGO | S_IWUSR, get_power_reset, set_power_reset); +static DEVICE_ATTR(fan_prs, S_IRUGO, get_fan_prs, NULL); +static DEVICE_ATTR(psu0_prs, S_IRUGO, get_psu0_prs, NULL); +static DEVICE_ATTR(psu1_prs, S_IRUGO, get_psu1_prs, NULL); +static DEVICE_ATTR(psu0_status, S_IRUGO, get_psu0_status, NULL); +static DEVICE_ATTR(psu1_status, S_IRUGO, get_psu1_status, NULL); +static DEVICE_ATTR(powersupply_status, S_IRUGO, get_powersupply_status, NULL); +static DEVICE_ATTR(system_led, S_IRUGO | S_IWUSR, get_system_led, set_system_led); +static DEVICE_ATTR(locator_led, S_IRUGO | S_IWUSR, get_locator_led, set_locator_led); +static DEVICE_ATTR(power_led, S_IRUGO | S_IWUSR, get_power_led, set_power_led); +static DEVICE_ATTR(master_led, S_IRUGO | S_IWUSR, get_master_led, set_master_led); +static DEVICE_ATTR(fan_led, S_IRUGO | S_IWUSR, get_fan_led, set_fan_led); +static DEVICE_ATTR(fan0_led, S_IRUGO | S_IWUSR, get_fan0_led, set_fan0_led); +static DEVICE_ATTR(fan1_led, S_IRUGO | S_IWUSR, get_fan1_led, set_fan1_led); +static DEVICE_ATTR(fan2_led, S_IRUGO | S_IWUSR, get_fan2_led, set_fan2_led); +static DEVICE_ATTR(system_cpld_ver, S_IRUGO, get_system_cpld_ver, NULL); +static DEVICE_ATTR(master_cpld_ver, S_IRUGO, get_master_cpld_ver, NULL); +static DEVICE_ATTR(slave_cpld_ver, S_IRUGO, get_slave_cpld_ver, NULL); +static DEVICE_ATTR(last_reboot_reason, S_IRUGO, get_reboot_reason, NULL); + +static struct attribute *s6000_cpld_attrs[] = { + &dev_attr_qsfp_modsel.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_power_reset.attr, + &dev_attr_fan_prs.attr, + &dev_attr_psu0_prs.attr, + &dev_attr_psu1_prs.attr, + &dev_attr_psu0_status.attr, + &dev_attr_psu1_status.attr, + &dev_attr_powersupply_status.attr, + &dev_attr_system_led.attr, + &dev_attr_locator_led.attr, + &dev_attr_power_led.attr, + &dev_attr_master_led.attr, + &dev_attr_fan_led.attr, + &dev_attr_fan0_led.attr, + &dev_attr_fan1_led.attr, + &dev_attr_fan2_led.attr, + &dev_attr_system_cpld_ver.attr, + &dev_attr_master_cpld_ver.attr, + &dev_attr_slave_cpld_ver.attr, + &dev_attr_last_reboot_reason.attr, + NULL, +}; + +static struct attribute_group s6000_cpld_attr_grp = { + .attrs = s6000_cpld_attrs, +}; + +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int i; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(S6000_MUX_BASE_NR); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", + S6000_MUX_BASE_NR); + return -ENODEV; + } + + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + pdata[i].client = i2c_new_dummy(parent, pdata[i].reg_addr); + if (!pdata[i].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[i].reg_addr); + goto error; + } + } + + ret = sysfs_create_group(&pdev->dev.kobj, &s6000_cpld_attr_grp); + if (ret) + goto error; + + return 0; + +error: + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + } + } + + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + int i; + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + + sysfs_remove_group(&pdev->dev.kobj, &s6000_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } else { + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + if (pdata[i].client) { + if (!parent) { + parent = (pdata[i].client)->adapter; + } + i2c_unregister_device(pdata[i].client); + } + } + } + + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "dell-s6000-cpld", + }, +}; + +static int __init dell_s6000_platform_init(void) +{ + int ret = 0; + struct cpld_platform_data *cpld_pdata; + struct qsfp_mux_platform_data *qsfp_pdata; + int i; + bool gpio_allocated = false; + + printk("dell_s6000_platform module initialization\n"); + + ret = gpio_request(GPIO_I2C_MUX_PIN, "gpio10"); + if(ret < 0) { + printk(KERN_WARNING "Failed to request gpio 10"); + goto error_gpio_init; + } + gpio_allocated = true; + + ret = gpio_export(GPIO_I2C_MUX_PIN, false); + if(ret < 0) { + printk(KERN_WARNING "Failed to export gpio 10"); + goto error_gpio_init; + } + + ret = gpio_direction_output(GPIO_I2C_MUX_PIN, 0); + if(ret < 0) { + printk(KERN_WARNING "Failed to set direction out on gpio 10"); + goto error_gpio_init; + } + + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + + ret = platform_driver_register(&qsfp_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register qsfp mux driver\n"); + goto error_qsfp_mux_driver; + } + + ret = platform_device_register(&s6000_mux); + if (ret) { + printk(KERN_WARNING "Fail to create gpio mux\n"); + goto error_mux; + } + + ret = platform_device_register(&s6000_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_cpld; + } + + cpld_pdata = s6000_cpld.dev.platform_data; + qsfp_pdata = s6000_qsfp_mux[0].dev.platform_data; + qsfp_pdata->cpld = cpld_pdata[slave_cpld].client; + qsfp_pdata = s6000_qsfp_mux[1].dev.platform_data; + qsfp_pdata->cpld = cpld_pdata[master_cpld].client; + + for (i = 0; i < QSFP_DEVICE_NUM; i++) { + ret = platform_device_register(&s6000_qsfp_mux[i]); + if (ret) { + printk(KERN_WARNING "fail to create qsfp mux %d\n", i); + goto error_qsfp_mux; + } + } + + if (ret) + goto error_qsfp_mux; + + return 0; + +error_qsfp_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&s6000_qsfp_mux[i]); + } + platform_device_unregister(&s6000_cpld); +error_cpld: + platform_device_unregister(&s6000_mux); +error_mux: + platform_driver_unregister(&qsfp_mux_driver); +error_qsfp_mux_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +error_gpio_init: + if(gpio_allocated) { + gpio_free(GPIO_I2C_MUX_PIN); + } + return ret; +} + +static void __exit dell_s6000_platform_exit(void) +{ + int i; + + for (i = 0; i < MUX_CHANNEL_NUM; i++) + platform_device_unregister(&s6000_qsfp_mux[i]); + platform_device_unregister(&s6000_cpld); + platform_device_unregister(&s6000_mux); + + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&qsfp_mux_driver); + gpio_free(GPIO_I2C_MUX_PIN); +} + +module_init(dell_s6000_platform_init); +module_exit(dell_s6000_platform_exit); + +MODULE_DESCRIPTION("DELL S6000 Platform Support"); +MODULE_AUTHOR("Guohan Lu "); +MODULE_LICENSE("GPL"); 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..665d5494b6b7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/fancontrol.sh @@ -0,0 +1,253 @@ +#!/bin/bash +trap 'cleanup' 0 1 2 3 6 9 10 11 13 15 + +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 + +LRR_FILE="/host/reboot-cause/reboot-cause.txt" +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" + +SENSOR1_MAX="$I2C_ADAPTER/11-004c/hwmon/hwmon*/temp1_max" +SENSOR2_MAX="$I2C_ADAPTER/11-004d/hwmon/hwmon*/temp1_max" +SENSOR3_MAX="$I2C_ADAPTER/11-004e/hwmon/hwmon*/temp1_max" + +SENSOR1_MAX_VAL=$(cat $SENSOR1_MAX) +SENSOR2_MAX_VAL=$(cat $SENSOR2_MAX) +SENSOR3_MAX_VAL=$(cat $SENSOR3_MAX) + +# Reducing by 63 to differentiate this temperature settings +# from pmon sensors configuration settings +SENSOR1_NEW_MAX=$(expr `echo $SENSOR1_MAX_VAL` + 5000 - 63) +SENSOR2_NEW_MAX=$(expr `echo $SENSOR2_MAX_VAL` + 5000 - 63) +SENSOR3_NEW_MAX=$(expr `echo $SENSOR3_MAX_VAL` + 5000 - 63) + +# 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 cleanup +{ + echo $SENSOR1_MAX_VAL > $SENSOR1_MAX + echo $SENSOR2_MAX_VAL > $SENSOR2_MAX + echo $SENSOR3_MAX_VAL > $SENSOR3_MAX + exit 1 +} + +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 +{ + SENSOR1_CUR_MAX_VAL=$(cat $SENSOR1_MAX) + SENSOR2_CUR_MAX_VAL=$(cat $SENSOR2_MAX) + SENSOR3_CUR_MAX_VAL=$(cat $SENSOR3_MAX) + if [ "$SENSOR1_CUR_MAX_VAL" -ne "$SENSOR1_NEW_MAX" ] + then + SENSOR1_NEW_MAX=$(expr `echo $SENSOR1_CUR_MAX_VAL` + 5000 - 63) + SENSOR1_MAX_VAL=$SENSOR1_CUR_MAX_VAL + echo $SENSOR1_NEW_MAX > $SENSOR1_MAX + fi + if [ "$SENSOR2_CUR_MAX_VAL" -ne "$SENSOR2_NEW_MAX" ] + then + SENSOR2_NEW_MAX=$(expr `echo $SENSOR2_CUR_MAX_VAL` + 5000 - 63) + SENSOR2_MAX_VAL=$SENSOR2_CUR_MAX_VAL + echo $SENSOR2_NEW_MAX > $SENSOR2_MAX + fi + if [ "$SENSOR3_CUR_MAX_VAL" -ne "$SENSOR3_NEW_MAX" ] + then + SENSOR3_NEW_MAX=$(expr `echo $SENSOR3_CUR_MAX_VAL` + 5000 - 63) + SENSOR3_MAX_VAL=$SENSOR3_CUR_MAX_VAL + echo $SENSOR3_NEW_MAX > $SENSOR3_MAX + fi + + # go through all temp sensor outputs + sensor1=$(expr `echo $(cat $SENSOR1)` / 1000) + sensor2=$(expr `echo $(cat $SENSOR2)` / 1000) + sensor3=$(expr `echo $(cat $SENSOR3)` / 1000) + # All sensors output in 1000's + s1=$(cat $SENSOR1) + s2=$(cat $SENSOR2) + s3=$(cat $SENSOR3) + + if [ "$s1" -ge "$SENSOR1_MAX_VAL" ] || [ "$s2" -ge "$SENSOR2_MAX_VAL" ] || [ "$s3" -ge "$SENSOR3_MAX_VAL" ] + then + # Thermal trip is about to happen + echo "Thermal Overload $sensor1 $sensor2 $sensor3" > $LRR_FILE + logger "Shutting down due to over temperature ($sensor1 degree, $sensor2 degree, $sensor3 degree)" + sync + sleep 1 # Give time to send logger message to server + # Assigning the original max values back in sensors + echo $SENSOR1_MAX_VAL > $SENSOR1_MAX + echo $SENSOR2_MAX_VAL > $SENSOR2_MAX + echo $SENSOR3_MAX_VAL > $SENSOR3_MAX + + ### Not Reached ### + # In case if HW fails to shutdown + /sbin/shutdown -P now + fi + 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 + +} + +# 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/scripts/override.conf b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/override.conf new file mode 100644 index 000000000000..4291afe0d249 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/override.conf @@ -0,0 +1,3 @@ +[Service] +ExecStart= +ExecStart=/usr/share/sonic/device/x86_64-dell_s6000_s1220-r0/platform_reboot_override diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/platform_reboot_override b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/platform_reboot_override new file mode 100755 index 000000000000..cae804f2cfb1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/platform_reboot_override @@ -0,0 +1,27 @@ +#!/usr/bin/python3 + +import os +import struct + +PORT_RES = '/dev/port' +COLD_RESET = 0xE # Cold Reset +WARM_RESET = 0x6 # Warm Reset +RESET_REG = 0xCF9 + +def io_reg_write(resource, offset, val): + fd = os.open(resource, os.O_RDWR) + if(fd < 0): + print('file open failed %s" % resource') + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print('lseek failed on %s' % resource) + return + ret = os.write(fd, struct.pack('B', val)) + if(ret != 1): + print('write failed %d' % ret) + return + os.close(fd) + + +if __name__ == "__main__": + io_reg_write(PORT_RES, RESET_REG, COLD_RESET) diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/platform_update_reboot_cause b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/platform_update_reboot_cause new file mode 100755 index 000000000000..ba6e3bbab539 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/platform_update_reboot_cause @@ -0,0 +1,25 @@ +#!/usr/bin/python3 + +import os +import struct + +NVRAM_RES = '/dev/nvram' +COLD_RESET = 0xE # Cold Reset +WARM_RESET = 0x6 # Warm Reset + +def io_reg_write(resource, offset, val): + fd = os.open(resource, os.O_RDWR) + if(fd < 0): + print('file open failed %s" % resource') + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print('lseek failed on %s' % resource) + return + ret = os.write(fd, struct.pack('B', val)) + if(ret != 1): + print('write failed %d' % ret) + return + os.close(fd) + +if __name__ == "__main__": + io_reg_write(NVRAM_RES, 0x49, COLD_RESET) diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/reset-qsfp b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/reset-qsfp new file mode 100755 index 000000000000..6b017ed37c26 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/reset-qsfp @@ -0,0 +1,25 @@ +#!/bin/bash + +# Usage: +# Reset QSFP manually by writing 1/0 to QSFP reset pin + +QSFP_RESET=/sys/bus/platform/devices/dell-s6000-cpld.0/qsfp_reset + +logger -t platform-modules "Reset QSFP modules" + +# Retry three times +for i in `seq 1 3` +do + if [ -w $QSFP_RESET ]; then + echo 0x00000000 > $QSFP_RESET + # Sleep 1 second to reset QSFP + sleep 1 + echo 0xffffffff > $QSFP_RESET + exit 0 + fi + # Sleep for 3 seconds to wait for device tree to be ready + sleep 3 +done + +logger -p user.error -t platform-modules "Failed to reset QSFP modules!" +exit 1 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/s6000_platform.sh b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/s6000_platform.sh new file mode 100755 index 000000000000..a98df43ef27b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/s6000_platform.sh @@ -0,0 +1,120 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S6000 board. +### END INIT INFO + +add_i2c_devices() { + + echo 24c02 0x50 > /sys/class/i2c-adapter/i2c-1/new_device + echo 24c02 0x51 > /sys/class/i2c-adapter/i2c-1/new_device + echo dni_dps460 0x58 > /sys/class/i2c-adapter/i2c-1/new_device + echo dni_dps460 0x59 > /sys/class/i2c-adapter/i2c-1/new_device + echo jc42 0x18 > /sys/class/i2c-adapter/i2c-10/new_device + echo emc1403 0x4d > /sys/class/i2c-adapter/i2c-10/new_device + echo spd 0x50 > /sys/class/i2c-adapter/i2c-10/new_device + echo 24c02 0x53 > /sys/class/i2c-adapter/i2c-10/new_device + echo max6620 0x29 > /sys/class/i2c-adapter/i2c-11/new_device + echo max6620 0x2a > /sys/class/i2c-adapter/i2c-11/new_device + echo ltc4215 0x40 > /sys/class/i2c-adapter/i2c-11/new_device + echo ltc4215 0x42 > /sys/class/i2c-adapter/i2c-11/new_device + echo tmp75 0x4c > /sys/class/i2c-adapter/i2c-11/new_device + echo tmp75 0x4d > /sys/class/i2c-adapter/i2c-11/new_device + echo tmp75 0x4e > /sys/class/i2c-adapter/i2c-11/new_device + echo 24c02 0x51 > /sys/class/i2c-adapter/i2c-11/new_device + echo 24c02 0x52 > /sys/class/i2c-adapter/i2c-11/new_device + echo 24c02 0x53 > /sys/class/i2c-adapter/i2c-11/new_device + for i in `seq 0 31`; do + echo optoe1 0x50 > /sys/class/i2c-adapter/i2c-$((20+i))/new_device + done +} + +remove_i2c_devices() { + echo 0x50 > /sys/class/i2c-adapter/i2c-1/delete_device + echo 0x51 > /sys/class/i2c-adapter/i2c-1/delete_device + echo 0x58 > /sys/class/i2c-adapter/i2c-1/delete_device + echo 0x59 > /sys/class/i2c-adapter/i2c-1/delete_device + echo 0x18 > /sys/class/i2c-adapter/i2c-10/delete_device + echo 0x4d > /sys/class/i2c-adapter/i2c-10/delete_device + echo 0x50 > /sys/class/i2c-adapter/i2c-10/delete_device + echo 0x53 > /sys/class/i2c-adapter/i2c-10/delete_device + echo 0x29 > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x2a > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x40 > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x42 > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x4c > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x4d > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x4e > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x51 > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x52 > /sys/class/i2c-adapter/i2c-11/delete_device + echo 0x53 > /sys/class/i2c-adapter/i2c-11/delete_device + for i in `seq 0 31`; do + echo 0x50 > /sys/class/i2c-adapter/i2c-$((20+i))/delete_device + done +} + +# Enable/Disable low power mode on all QSFP ports +switch_board_qsfp_lpmode() { + case $1 in + "enable") value=0xffff + ;; + "disable") value=0x0 + ;; + *) echo "s6000_platform: switch_board_qsfp_lpmode: invalid command $1!" + return + ;; + esac + echo $value > /sys/bus/platform/devices/dell-s6000-cpld.0/qsfp_lpmode +} + +install_python_api_package() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip install $device/$platform/sonic_platform-1.0-py2-none-any.whl) + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) +} + +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) + fi + + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -eq 0 ]; then + rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null) + fi +} + +# read SONiC immutable variables +[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment + +if [[ "$1" == "init" ]]; then + depmod -a + modprobe nvram + modprobe i2c_mux_gpio + modprobe dell_s6000_platform + install_python_api_package + + add_i2c_devices + + /usr/local/bin/set-fan-speed 15000 + switch_board_qsfp_lpmode "disable" + /usr/local/bin/reset-qsfp +elif [[ "$1" == "deinit" ]]; then + remove_i2c_devices + rmmod dell_s6000_platform + rmmod nvram + rmmod i2c_mux_gpio + remove_python_api_package +else + echo "s6000_platform : Invalid option !" +fi diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/set-fan-speed b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/set-fan-speed new file mode 100755 index 000000000000..00c738f23a8d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/scripts/set-fan-speed @@ -0,0 +1,58 @@ +#!/bin/bash + +# Usage: +# Set all fans speed to $1 + +usage() { + echo "This script must be run with super-user privilege." + echo "Warning! Wrongly set fan speed may result in physical damage to the device." + echo "" + echo "usage: set-fan-speed speed_in_rpm" + echo "example: set-fan-speed 15000" +} + +if [ $# -ne 1 ]; then + usage + exit 1 +fi + +PSU_FAN1=/sys/class/i2c-adapter/i2c-1/1-0058/fan1_target +PSU_FAN2=/sys/class/i2c-adapter/i2c-1/1-0059/fan1_target + +# Three fan trays with each contains two separate fans +# fan1-fan4 fan2-fan5 fan3-fan6 +FAN1=/sys/class/i2c-adapter/i2c-11/11-0029/fan1_target +FAN2=/sys/class/i2c-adapter/i2c-11/11-0029/fan2_target +FAN3=/sys/class/i2c-adapter/i2c-11/11-0029/fan3_target +FAN4=/sys/class/i2c-adapter/i2c-11/11-0029/fan4_target +FAN5=/sys/class/i2c-adapter/i2c-11/11-002a/fan1_target +FAN6=/sys/class/i2c-adapter/i2c-11/11-002a/fan2_target + +speed=$1 +logger -t platform-modules "Trying to set fan speed to $speed" + +# Retry three times +for i in `seq 1 3` +do + if [ -w $FAN1 -o -w $FAN2 -o -w $FAN3 ]; then + # set default psu fan speed + echo $speed > $PSU_FAN1 + echo $speed > $PSU_FAN2 + # set default fan speed + echo $speed > $FAN1 + echo $speed > $FAN2 + echo $speed > $FAN3 + echo $speed > $FAN4 + echo $speed > $FAN5 + echo $speed > $FAN6 + + logger -t platform-modules "Fan speed is set to $speed" + + exit 0 + fi + # Sleep for 3 seconds to wait for device tree to be ready + sleep 3 +done + +logger -p user.error -t platform-modules "Failed to set fan speed!" +exit 1 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/setup.py b/platform/broadcom/sonic-platform-modules-dell/s6000/setup.py new file mode 120000 index 000000000000..4f6de9941d96 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/setup.py @@ -0,0 +1 @@ +../s6100/setup.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/__init__.py new file mode 100755 index 000000000000..db8b45acb1b5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis", "fan", "fan_drawer", "sfp", "psu", "thermal"] +from sonic_platform import * 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 new file mode 100755 index 000000000000..08c128d678bc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py @@ -0,0 +1,384 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import time + import struct + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.eeprom import Eeprom, EepromS6000 + from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.psu import Psu + from sonic_platform.thermal import Thermal + from sonic_platform.component import Component +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +MAX_S6000_FANTRAY = 3 +MAX_S6000_PSU = 2 +MAX_S6000_THERMAL = 6 +MAX_S6000_COMPONENT = 4 + + +class Chassis(ChassisBase): + """ + DELLEMC Platform-specific Chassis class + """ + CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0" + + sfp_control = "" + PORT_START = 0 + PORT_END = 0 + reset_reason_dict = {} + reset_reason_dict[0xe] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE + reset_reason_dict[0x6] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE + reset_reason_dict[0x7] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER + + def __init__(self): + ChassisBase.__init__(self) + self.status_led_reg = "system_led" + self.supported_led_color = ['green', 'blinking green', 'amber', 'blinking amber'] + # Initialize SFP list + self.PORT_START = 0 + self.PORT_END = 31 + EEPROM_OFFSET = 20 + PORTS_IN_BLOCK = (self.PORT_END + 1) + + # sfp.py will read eeprom contents and retrive the eeprom data. + # It will also provide support sfp controls like reset and setting + # low power mode. + # We pass the eeprom path and sfp control path from chassis.py + # So that sfp.py implementation can be generic to all platforms + eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + self.sfp_control = "/sys/devices/platform/dell-s6000-cpld.0/" + + for index in range(0, PORTS_IN_BLOCK): + eeprom_path = eeprom_base.format(index + EEPROM_OFFSET) + sfp_node = Sfp(index, 'QSFP', eeprom_path, self.sfp_control, index) + self._sfp_list.append(sfp_node) + + # Get Transceiver status + self.modprs_register = self._get_transceiver_status() + + with open("/sys/class/dmi/id/product_name", "r") as fd: + board_type = fd.read() + + if 'S6000-ON' in board_type: + self._eeprom = Eeprom() + else: + self._eeprom = EepromS6000() + + for i in range(MAX_S6000_FANTRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + for i in range(MAX_S6000_PSU): + psu = Psu(i) + self._psu_list.append(psu) + + for i in range(MAX_S6000_THERMAL): + thermal = Thermal(i) + self._thermal_list.append(thermal) + + for i in range(MAX_S6000_COMPONENT): + component = Component(i) + self._component_list.append(component) + + def _get_cpld_register(self, reg_name): + rv = 'ERR' + mb_reg_file = self.CPLD_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except IOError: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _set_cpld_register(self, reg_name, value): + # On successful write, returns the value will be written on + # reg_name and on failure returns 'ERR' + rv = 'ERR' + cpld_reg_file = self.CPLD_DIR+'/'+reg_name + + if (not os.path.isfile(cpld_reg_file)): + return rv + + try: + with open(cpld_reg_file, 'w') as fd: + rv = fd.write(str(value)) + except IOError: + rv = 'ERR' + + return rv + + def _nvram_write(self, offset, val): + resource = "/dev/nvram" + fd = os.open(resource, os.O_RDWR) + if (fd < 0): + print('File open failed ',resource) + return + if (os.lseek(fd, offset, os.SEEK_SET) != offset): + print('lseek failed on ',resource) + return + ret = os.write(fd, struct.pack('B', val)) + if ret != 1: + print('Write failed ',str(ret)) + return + os.close(fd) + + def _get_thermal_reset(self): + reset_file = "/host/reboot-cause/reboot-cause.txt" + if (not os.path.isfile(reset_file)): + return False + try: + with open(reset_file, 'r') as fd: + rv = fd.read() + except Exception as error: + return False + + if "Thermal Overload" in rv: + return True + + return False + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.get_model() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.get_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.get_serial() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether Chassis is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + 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_base_mac() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the + chassis + + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their + corresponding values. + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + """ + # In S6000, We track the reboot reason by writing the reason in + # NVRAM. Only Warmboot and Coldboot reason are supported here. + # Since it does not support any hardware reason, we return + # non_hardware as default + if self._get_thermal_reset() == True: + self._nvram_write(0x49, 0x7) + + lrr = self._get_cpld_register('last_reboot_reason') + if (lrr != 'ERR'): + reset_reason = int(lrr, base=16) + if (reset_reason in self.reset_reason_dict): + return (self.reset_reason_dict[reset_reason], None) + + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) + + def _get_transceiver_status(self): + presence_ctrl = self.sfp_control + 'qsfp_modprs' + try: + reg_file = open(presence_ctrl) + + except IOError as e: + return False + + content = reg_file.readline().rstrip() + reg_file.close() + + return int(content, 16) + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the + format of {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + start_time = time.time() + port_dict = {} + ret_dict = {"sfp": port_dict} + port = self.PORT_START + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + return False, {} + end_time = start_time + timeout + + if (start_time > end_time): + return False, ret_dict # Time wrap or possibly incorrect timeout + + while (timeout >= 0): + # Check for OIR events and return updated port_dict + reg_value = self._get_transceiver_status() + if (reg_value != self.modprs_register): + changed_ports = (self.modprs_register ^ reg_value) + while (port >= self.PORT_START and port <= self.PORT_END): + # Mask off the bit corresponding to our port + mask = (1 << port) + if (changed_ports & mask): + # ModPrsL is active low + if reg_value & mask == 0: + port_dict[port] = '1' + else: + port_dict[port] = '0' + port += 1 + + # Update reg value + self.modprs_register = reg_value + return True, ret_dict + + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, ret_dict + return False, ret_dict + + def initizalize_system_led(self): + return True + + def set_status_led(self, color): + """ + Sets the state of the system LED + + Args: + color: A string representing the color with which to set the + system LED + + Returns: + bool: True if system LED state is set successfully, False if not + """ + if color not in self.supported_led_color: + return False + + # Change color string format to the one used by driver + color = color.replace('amber', 'yellow') + color = color.replace('blinking ', 'blink_') + rv = self._set_cpld_register(self.status_led_reg, color) + if (rv != 'ERR'): + return True + else: + return False + + def get_status_led(self): + """ + Gets the state of the system LED + + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + status_led = self._get_cpld_register(self.status_led_reg) + if (status_led != 'ERR'): + status_led = status_led.replace('yellow', 'amber') + status_led = status_led.replace('blink_', 'blinking ') + return status_led + else: + return None diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/component.py new file mode 100644 index 000000000000..d9459be47c4f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/component.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC S6000 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + import subprocess + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version" + + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0" + + CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["System-CPLD", "Used for managing CPU board devices and power"], + ["Master-CPLD", ("Used for managing Fan, PSU, system LEDs, QSFP " + "modules (17-32)")], + ["Slave-CPLD", "Used for managing QSFP modules (1-16)"] + ] + + def __init__(self, component_index): + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + + def _get_cpld_register(self, reg_name): + rv = 'ERR' + mb_reg_file = self.CPLD_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.decode('utf-8').rstrip('\n') + except OSError: + result = None + + return result + + def _get_cpld_version(self, cpld_number): + cpld_version_reg = { + 1: "system_cpld_ver", + 2: "master_cpld_ver", + 3: "slave_cpld_ver" + } + + cpld_version = self._get_cpld_register(cpld_version_reg[cpld_number]) + + if cpld_version != 'ERR': + return str(int(cpld_version, 16)) + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return self.name + + def get_model(self): + """ + Retrieves the part number of the component + Returns: + string: Part number of component + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the component + Returns: + string: Serial number of component + """ + return 'NA' + + def get_presence(self): + """ + Retrieves the presence of the component + Returns: + bool: True if present, False if not + """ + return True + + def get_status(self): + """ + Retrieves the operational status of the component + Returns: + bool: True if component is operating properly, False if not + """ + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether component is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + if self.index == 0: + bios_ver = self._get_command_result(BIOS_QUERY_VERSION_COMMAND) + + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index <= 3: + return self._get_cpld_version(self.index) + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + return False 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 new file mode 100644 index 000000000000..5afe0112441b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py @@ -0,0 +1,508 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S6000 +# +# Module contains platform specific implementation of SONiC Platform +# Base API and provides the EEPROMs' information. +# +# The different EEPROMs available are as follows: +# - System EEPROM : Contains Serial number, Service tag, Base MA +# address, etc. in ONIE TlvInfo EEPROM format. +# - PSU EEPROM : Contains Serial number, Part number, Service Tag, +# PSU type, Revision. +# - Fan EEPROM : Contains Serial number, Part number, Service Tag, +# Fan type, Number of Fans in Fantray, Revision. +######################################################################## + + +try: + import binascii + import redis + import struct + from collections import OrderedDict + from sonic_platform_base.sonic_eeprom.eeprom_base import EepromDecoder + from sonic_platform_base.sonic_eeprom.eeprom_tlvinfo import TlvInfoDecoder +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +STATE_DB_INDEX = 6 + +# PSU eeprom fields in format required by EepromDecoder +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), ('Redundant copy', 's', 83), ('PSU Type', 's', 1), + ('Fab Rev', 's', 2) + ] + +# FanTray eeprom fields in format required by EepromDecoder +fantray_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', 83), + ('Number of Fans', 's', 1), ('Fan Type', 's', 1), + ('Fab Rev', 's', 2) + ] + + +class Eeprom(TlvInfoDecoder): + """DellEMC Platform-specific EEPROM class""" + + I2C_DIR = "/sys/class/i2c-adapter/" + + def __init__(self, is_psu=False, psu_index=0, is_fantray=False, fantray_index=0): + self.is_psu_eeprom = is_psu + self.is_fantray_eeprom = is_fantray + self.is_sys_eeprom = not (is_psu | is_fantray) + + if self.is_sys_eeprom: + self.start_offset = 0 + self.eeprom_path = self.I2C_DIR + "i2c-10/10-0053/eeprom" + # System EEPROM is in ONIE TlvInfo EEPROM format + super(Eeprom, self).__init__(self.eeprom_path, + self.start_offset, '', True) + self._load_system_eeprom() + else: + self.start_offset = 6 + if self.is_psu_eeprom: + self.index = psu_index + self.eeprom_path = self.I2C_DIR \ + + "i2c-1/1-005{}/eeprom".format(2 - self.index) + self.format = psu_eeprom_format + else: + self.index = fantray_index + self.eeprom_path = self.I2C_DIR \ + + "i2c-11/11-005{}/eeprom".format(4 - self.index) + self.format = fantray_eeprom_format + EepromDecoder.__init__(self, self.eeprom_path, self.format, + self.start_offset, '', True) + self._load_device_eeprom() + + def _load_system_eeprom(self): + """ + Reads the system EEPROM and retrieves the values corresponding + to the codes defined as per ONIE TlvInfo EEPROM format and fills + them in a dictionary. + """ + try: + # Read System EEPROM as per ONIE TlvInfo EEPROM format. + self.eeprom_data = self.read_eeprom() + except: + self.base_mac = 'NA' + self.serial_number = 'NA' + self.part_number = 'NA' + self.model_str = 'NA' + self.serial = 'NA' + self.eeprom_tlv_dict = dict() + else: + eeprom = self.eeprom_data + self.eeprom_tlv_dict = dict() + + if not self.is_valid_tlvinfo_header(eeprom): + self.base_mac = 'NA' + self.serial_number = 'NA' + self.part_number = 'NA' + self.model_str = 'NA' + self.serial = 'NA' + return + + total_length = (eeprom[9] << 8) | (eeprom[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += tlv[6:6 + tlv[1]].decode('ascii') + else: + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + self.base_mac = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_MAC_BASE), 'NA') + self.serial_number = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_SERIAL_NUMBER), 'NA') + self.part_number = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_PART_NUMBER), 'NA') + self.model_str = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_PRODUCT_NAME), 'NA') + self.serial = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_SERVICE_TAG), 'NA') + + def _load_device_eeprom(self): + """ + Reads the Fan/PSU EEPROM and retrieves the serial number and + model number of the device. + """ + try: + # Read Fan/PSU EEPROM as per the specified format. + self.eeprom_data = EepromDecoder.read_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: + ppid = data + self.serial_number = (ppid[:2] + "-" + ppid[2:8] + "-" + + ppid[8:13] + "-" + ppid[13:16] + + "-" + ppid[16:]) + (valid, data) = self._get_eeprom_field("DPN Rev") + if valid: + self.serial_number += "-" + data + else: + self.serial_number = 'NA' + + (valid, data) = self._get_eeprom_field("Part Number") + if valid: + self.part_number = data + else: + self.part_number = 'NA' + + 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: + (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, decode=True): + """ + For a field name specified in the EEPROM format, returns the + presence of the field and the value for the same. + """ + field_start = 0 + for field in self.format: + field_end = field_start + field[2] + if field[0] == field_name: + if decode: + return (True, self.eeprom_data[field_start:field_end].decode('ascii')) + else: + return (True, self.eeprom_data[field_start:field_end]) + field_start = field_end + + return (False, None) + + def get_serial_number(self): + """ + Returns the serial number. + """ + return self.serial_number + + def get_part_number(self): + """ + Returns the part number. + """ + return self.part_number + + def airflow_fan_type(self): + """ + Returns the airflow fan type. + """ + if self.is_psu_eeprom: + return int(binascii.hexlify(self.psu_type.encode('utf-8')), 16) + else: + return int(binascii.hexlify(self.fan_type.encode('utf-8')), 16) + + # System EEPROM specific methods + def get_base_mac(self): + """ + Returns the base MAC address found in the system EEPROM. + """ + return self.base_mac + + def get_model(self): + """ + Returns the Model name. + """ + return self.model_str + + def get_serial(self): + """ + Returns the servicetag number. + """ + return self.serial + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict + + +class EepromS6000(EepromDecoder): + + _EEPROM_MAX_LEN = 128 + + _BLK_HDR_LEN = 6 + _BLK_HDR_MAGIC = b'\x3a\x29' + _BLK_HDR_REVID = 1 + + _BLK_CODE_MFG = 0x20 + _BLK_CODE_SW = 0x1F + _BLK_CODE_MAC = 0x21 + + _BLK_MFG_FORMAT = [ + ("PPID", 20), ("DPN Rev", 3), ("Service Tag", 7), ("Part Number", 10), + ("Part Number Rev", 3), ("Mfg Test Results", 2) + ] + + _BLK_SW_FORMAT = [("Card ID", 4), ("Module ID", 2)] + _BLK_MAC_FORMAT = [("Base MAC address", 6)] + + _BLK_INFO = OrderedDict([ + (_BLK_CODE_MFG, {"name": "MFG BLOCK", "size": 64, + "offset": 0x0, "format": _BLK_MFG_FORMAT}), + (_BLK_CODE_SW, {"name": "SW BLOCK", "size": 48, + "offset": 0x40, "format": _BLK_SW_FORMAT}), + (_BLK_CODE_MAC, {"name": "MAC BLOCK", "size": 16, + "offset": 0x70, "format": _BLK_MAC_FORMAT}) + ]) + + def __init__(self, is_plugin=False): + self.eeprom_path = "/sys/bus/i2c/devices/i2c-10/10-0053/eeprom" + super(EepromS6000, self).__init__(self.eeprom_path, None, 0, '', True) + + if not is_plugin: + self.eeprom_data = self.read_eeprom() + + def _is_valid_block_checksum(self, e): + crc = self.compute_dell_crc(e[:-2]) + return crc == struct.unpack('3d} {:3d} {: 1000): + status = True + + return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether Fan is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def get_direction(self): + """ + Retrieves the fan airflow direction + + Returns: + A string, either FAN_DIRECTION_INTAKE or + FAN_DIRECTION_EXHAUST depending on fan direction + + Notes: + In DellEMC platforms, + - Forward/Exhaust : Air flows from Port side to Fan side. + - Reverse/Intake : Air flows from Fan side to Port side. + """ + 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} + else: + direction = {1: self.FAN_DIRECTION_EXHAUST, 2: self.FAN_DIRECTION_INTAKE} + + fan_direction = self.dependency.eeprom.airflow_fan_type() + return direction.get(fan_direction, self.FAN_DIRECTION_NOT_APPLICABLE) + + def get_speed(self): + """ + Retrieves the speed of fan + + Returns: + int: percentage of the max fan speed + """ + fan_speed = self._get_i2c_register(self.get_fan_speed_reg) + if (fan_speed != 'ERR') and self.get_presence(): + speed_in_rpm = int(fan_speed, 10) + speed = (100 * speed_in_rpm)//self.max_fan_speed + else: + speed = 0 + + return speed + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + + Returns: + An integer, the percentage of variance from target speed + which is considered tolerable + """ + if self.get_presence(): + # The tolerance value is fixed as 20% for all the DellEmc platform + tolerance = 20 + else: + tolerance = 0 + + return tolerance + + def set_speed(self, speed): + """ + Set fan speed to expected value + Args: + speed: An integer, the percentage of full fan speed to set + fan to, in the range 0 (off) to 100 (full speed) + Returns: + bool: True if set success, False if fail. + """ + fan_set = (speed * self.max_fan_speed) // 100 + rv = self._set_i2c_register(self.set_fan_speed_reg, fan_set) + if (rv != 'ERR'): + return True + else: + return False + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if set success, False if fail. + """ + # No LED available for FanTray and PSU Fan + # Return True to avoid thermalctld alarm. + return True + + def get_status_led(self): + """ + Gets the state of the fan status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + # No LED available for FanTray and PSU Fan + return None + + 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) + """ + # Fan speeds are controlled by fancontrol.sh + return self.get_speed() diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..2e5e3446cd80 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan_drawer.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S6000 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + import os + + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.eeprom import Eeprom + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MAX_S6000_FANS_PER_FANTRAY = 2 + + +class FanDrawer(FanDrawerBase): + """DellEMC Platform-specific Fan Drawer class""" + + CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/" + + def __init__(self, fantray_index): + FanDrawerBase.__init__(self) + # FanTray is 1-based in DellEMC platforms + self.index = fantray_index + 1 + self.eeprom = Eeprom(is_fantray=True, fantray_index=self.index) + self.fantray_presence_reg = "fan_prs" + self.fantray_led_reg = "fan{}_led".format(self.index - 1) + self.supported_led_color = ['off', 'green', 'amber'] + + for i in range(1, MAX_S6000_FANS_PER_FANTRAY+1): + self._fan_list.append(Fan(fantray_index=self.index, fan_index=i, 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' + rv = 'ERR' + cpld_reg_file = self.CPLD_DIR + reg_name + + if (not os.path.isfile(cpld_reg_file)): + return rv + + try: + with open(cpld_reg_file, 'r') as fd: + rv = fd.read() + except IOError: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _set_cpld_register(self, reg_name, value): + # On successful write, returns the value will be written on + # reg_name and on failure returns 'ERR' + rv = 'ERR' + cpld_reg_file = self.CPLD_DIR + reg_name + + if (not os.path.isfile(cpld_reg_file)): + return rv + + try: + with open(cpld_reg_file, 'w') as fd: + rv = fd.write(str(value)) + except IOError: + rv = 'ERR' + + return rv + + def get_name(self): + """ + Retrieves the Fandrawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Fandrawer + + Returns: + bool: True if Fandrawer is present, False if not + """ + presence = False + + fantray_presence = self._get_cpld_register(self.fantray_presence_reg) + if (fantray_presence != 'ERR'): + fantray_presence = int(fantray_presence, 16) & (1 << (self.index - 1)) + if fantray_presence: + presence = True + + return presence + + def get_model(self): + """ + Retrieves the part number of the Fandrawer + + Returns: + string: Part number of Fandrawer + """ + return self.eeprom.get_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the Fandrawer + + Returns: + string: Serial number of Fandrawer + """ + # Sample Serial number format "US-01234D-54321-25A-0123-A00" + return self.eeprom.get_serial_number() + + def get_status(self): + """ + Retrieves the operational status of the Fandrawer + + Returns: + bool: True if Fandrawer is operating properly, False if not + """ + status = True + for fan in self.get_all_fans(): + status &= fan.get_status() + + return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this fan drawer is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fandrawer status LED + Returns: + bool: True if set success, False if fail. + """ + if color not in self.supported_led_color: + return False + if color == self.STATUS_LED_COLOR_AMBER: + color = 'yellow' + + rv = self._set_cpld_register(self.fantray_led_reg, color) + if (rv != 'ERR'): + return True + else: + return False + + def get_status_led(self): + """ + Gets the state of the fandrawer status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + fantray_led = self._get_cpld_register(self.fantray_led_reg) + if (fantray_led != 'ERR'): + if (fantray_led == 'yellow'): + return self.STATUS_LED_COLOR_AMBER + else: + return fantray_led + else: + return self.STATUS_LED_COLOR_OFF diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/platform.py new file mode 100755 index 000000000000..32230d9c92ce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/platform.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """ + DELLEMC Platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + 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 new file mode 100644 index 000000000000..e217c0a08c40 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/psu.py @@ -0,0 +1,338 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S6000 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + + +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 + from sonic_platform.thermal import Thermal +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MAX_S6000_THERMALS_PER_PSU = 2 + + +class Psu(PsuBase): + """DellEMC Platform-specific PSU class""" + + CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/" + I2C_DIR = "/sys/class/i2c-adapter/" + + def __init__(self, psu_index): + PsuBase.__init__(self) + # PSU is 1-based in DellEMC platforms + 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/" + + 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" + self.psu_current_reg = self.HWMON_DIR + "curr1_input" + self.psu_power_reg = self.HWMON_DIR + "power1_input" + + self.eeprom = Eeprom(is_psu=True, psu_index=self.index) + + self._fan_list.append(Fan(psu_index=self.index, psu_fan=True, dependency=self)) + for i in range(1, MAX_S6000_THERMALS_PER_PSU+1): + self._thermal_list.append(Thermal(psu_index=self.index, thermal_index=i, + psu_thermal=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' + rv = 'ERR' + cpld_reg_file = self.CPLD_DIR + reg_name + + if (not os.path.isfile(cpld_reg_file)): + return rv + + try: + with open(cpld_reg_file, 'r') as fd: + rv = fd.read() + except: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_i2c_register(self, reg_file): + # On successful read, returns the value read from given + # 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 + + try: + with open(reg_file, 'r') as fd: + rv = fd.read() + except: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + 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[0] + self.psu_current_reg = current_reg[0] + self.psu_power_reg = power_reg[0] + self.is_driver_initialized = True + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + status = False + psu_presence = self._get_cpld_register(self.psu_presence_reg) + if (psu_presence != 'ERR'): + psu_presence = int(psu_presence) + if psu_presence: + status = True + + return status + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + return self.eeprom.get_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + # Sample Serial number format "US-01234D-54321-25A-0123-A00" + return self.eeprom.get_serial_number() + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + status = False + psu_status = self._get_cpld_register(self.psu_status_reg) + if (psu_status != 'ERR'): + psu_status = (int(psu_status, 16) >> int((2 - self.index) * 4)) & 0xF + if (~psu_status & 0b1000) and (~psu_status & 0b0100): + status = True + + return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether PSU is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + psu_voltage = self._get_i2c_register(self.psu_voltage_reg) + if (psu_voltage != 'ERR') and self.get_status(): + # Converting the value returned by driver which is in + # millivolts to volts + psu_voltage = float(psu_voltage) / 1000 + else: + psu_voltage = 0.0 + + return psu_voltage + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + psu_current = self._get_i2c_register(self.psu_current_reg) + if (psu_current != 'ERR') and self.get_status(): + # Converting the value returned by driver which is in + # milliamperes to amperes + psu_current = float(psu_current) / 1000 + else: + psu_current = 0.0 + + return psu_current + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + psu_power = self._get_i2c_register(self.psu_power_reg) + if (psu_power != 'ERR') and self.get_status(): + # Converting the value returned by driver which is in + # microwatts to watts + psu_power = float(psu_power) / 1000000 + else: + psu_power = 0.0 + + return psu_power + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + status = False + psu_status = self._get_cpld_register(self.psu_status_reg) + if (psu_status != 'ERR'): + psu_status = (int(psu_status, 16) >> ((2 - self.index) * 4)) & 0xF + if (psu_status == 0x2): + status = True + + return status + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if + not + """ + # In S6000, the firmware running in the PSU controls the LED + # and the PSU LED state cannot be changed from CPU. + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.get_presence(): + return self.get_thermal(0).get_temperature() + else: + return 0.0 + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + + Returns: + A float number, the high threshold temperature of PSU in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + if self.get_presence(): + return self.get_thermal(0).get_high_threshold() + else: + return 0.0 + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return 12.6 + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return 11.4 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/sfp.py new file mode 100644 index 000000000000..b66cb31ec96b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/sfp.py @@ -0,0 +1,894 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import re + import struct + import time + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +PAGE_OFFSET = 0 +KEY_OFFSET = 1 +KEY_WIDTH = 2 +FUNC_NAME = 3 + +INFO_OFFSET = 128 +DOM_OFFSET = 0 +DOM_OFFSET1 = 384 + +QSFP_CONTROL_OFFSET = 86 +QSFP_POWEROVERRIDE_OFFSET = 93 + +cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', + 'Length OM1(m)', 'Length Cable Assembly(m)') + +compliance_code_tup = ( + '10/40G Ethernet Compliance Code', + 'SONET Compliance codes', + 'SAS/SATA compliance codes', + 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', + 'Fibre Channel Speed') + +info_dict_keys = ['type', 'hardware_rev', 'serial', + 'manufacturer', 'model', 'connector', + 'encoding', 'ext_identifier', 'ext_rateselect_compliance', + 'cable_type', 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'type_abbrv_name', 'vendor_date', + 'vendor_oui', 'application_advertisement'] + +dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', + 'power_lpmode', 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', 'rx1power', + 'rx2power', 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', 'tx3bias', + 'tx4bias', 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + +threshold_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning'] + +sff8436_parser = { + 'reset_status': [DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'], + 'rx_los': [DOM_OFFSET, 3, 1, 'parse_dom_tx_rx_los'], + 'tx_fault': [DOM_OFFSET, 4, 1, 'parse_dom_tx_fault'], + 'tx_disable': [DOM_OFFSET, 86, 1, 'parse_dom_tx_disable'], + 'power_lpmode': [DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'power_override': [DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'Temperature': [DOM_OFFSET, 22, 2, 'parse_temperature'], + 'Voltage': [DOM_OFFSET, 26, 2, 'parse_voltage'], + 'ChannelMonitor': [DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'], + + 'cable_type': [INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'encoding': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_identifier': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'specification_compliance': + [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type_abbrv_name': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'manufacturer': [INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [INFO_OFFSET, 56, 2, 'parse_vendor_rev'], + 'serial': [INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'ModuleThreshold': [DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'], + 'ChannelThreshold': [DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'], +} + + +class Sfp(SfpBase): + """ + DELLEMC Platform-specific Sfp class + """ + + def __init__(self, index, sfp_type, eeprom_path, + sfp_control, sfp_ctrl_idx): + SfpBase.__init__(self) + self.sfp_type = sfp_type + self.index = index + 1 + self.eeprom_path = eeprom_path + self.sfp_control = sfp_control + self.sfp_ctrl_idx = sfp_ctrl_idx + self.sfpInfo = sff8436InterfaceId() + self.sfpDomInfo = sff8436Dom() + + def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes): + eeprom_raw = [] + try: + eeprom = open(eeprom_path, mode="rb", buffering=0) + except IOError: + return None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom.seek(offset) + raw = eeprom.read(num_bytes) + except IOError: + eeprom.close() + return None + + raw = bytearray(raw) + try: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + except BaseException: + eeprom.close() + return None + + eeprom.close() + return eeprom_raw + + def _get_eeprom_data(self, eeprom_key): + eeprom_data = None + page_offset = None + + if (self.sfpInfo is None): + return None + + page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8436_parser[eeprom_key][PAGE_OFFSET] + + sff8436_parser[eeprom_key][KEY_OFFSET]), + sff8436_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 128 is used to retrieve sff8436InterfaceId Info + # Offset 0 is used to retrieve sff8436Dom Info + if (page_offset == 128): + eeprom_data = getattr( + self.sfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + eeprom_data = getattr( + self.sfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + + return eeprom_data + + def _strip_unit_from_str(self, value_str): + match = re.match(r'(.*)C$|(.*)Volts$|(.*)mA$|(.*)dBm$', value_str) + if match: + for value in match.groups(): + if value is not None: + return float(value) + + return None + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + """ + transceiver_info_dict = {} + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A') + + # BaseInformation + iface_data = self._get_eeprom_data('type') + if (iface_data is not None): + connector = iface_data['data']['Connector']['value'] + encoding = iface_data['data']['EncodingCodes']['value'] + ext_id = iface_data['data']['Extended Identifier']['value'] + rate_identifier = iface_data['data']['RateIdentifier']['value'] + identifier = iface_data['data']['type']['value'] + type_abbrv_name=iface_data['data']['type_abbrv_name']['value'] + bit_rate = str( + iface_data['data']['Nominal Bit Rate(100Mbs)']['value']) + + for key in compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + else: + return transceiver_info_dict + + # Vendor Date + vendor_date_data = self._get_eeprom_data('vendor_date') + if (vendor_date_data is not None): + vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + else: + return None + + # Vendor Name + vendor_name_data = self._get_eeprom_data('manufacturer') + if (vendor_name_data is not None): + vendor_name = vendor_name_data['data']['Vendor Name']['value'] + else: + return transceiver_info_dict + + # Vendor OUI + vendor_oui_data = self._get_eeprom_data('vendor_oui') + if (vendor_oui_data is not None): + vendor_oui = vendor_oui_data['data']['Vendor OUI']['value'] + else: + return transceiver_info_dict + + # Vendor PN + vendor_pn_data = self._get_eeprom_data('model') + if (vendor_pn_data is not None): + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + else: + return transceiver_info_dict + + # Vendor Revision + vendor_rev_data = self._get_eeprom_data('hardware_rev') + if (vendor_rev_data is not None): + vendor_rev = vendor_rev_data['data']['Vendor Rev']['value'] + else: + return transceiver_info_dict + + # Vendor Serial Number + vendor_sn_data = self._get_eeprom_data('serial') + if (vendor_sn_data is not None): + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + else: + return transceiver_info_dict + + # Fill The Dictionary and return + transceiver_info_dict['type'] = identifier + transceiver_info_dict['hardware_rev'] = vendor_rev + transceiver_info_dict['serial'] = vendor_sn + transceiver_info_dict['manufacturer'] = vendor_name + transceiver_info_dict['model'] = vendor_pn + transceiver_info_dict['connector'] = connector + transceiver_info_dict['encoding'] = encoding + transceiver_info_dict['ext_identifier'] = ext_id + transceiver_info_dict['ext_rateselect_compliance'] = rate_identifier + transceiver_info_dict['cable_type'] = cable_type + transceiver_info_dict['cable_length'] = cable_length + transceiver_info_dict['nominal_bit_rate'] = bit_rate + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + transceiver_info_dict['vendor_date'] = vendor_date + transceiver_info_dict['vendor_oui'] = vendor_oui + transceiver_info_dict['type_abbrv_name'] = type_abbrv_name + + return transceiver_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + """ + transceiver_dom_threshold_dict = {} + transceiver_dom_threshold_dict = dict.fromkeys( + threshold_dict_keys, 'N/A') + + # Module Threshold + module_threshold_data = self._get_eeprom_data('ModuleThreshold') + if (module_threshold_data is not None): + tempHighAlarm = module_threshold_data['data']['TempHighAlarm']['value'] + tempLowAlarm = module_threshold_data['data']['TempLowAlarm']['value'] + tempHighWarn = module_threshold_data['data']['TempHighWarning']['value'] + tempLowWarn = module_threshold_data['data']['TempLowWarning']['value'] + vccHighAlarm = module_threshold_data['data']['VccHighAlarm']['value'] + vccLowAlarm = module_threshold_data['data']['VccLowAlarm']['value'] + vccHighWarn = module_threshold_data['data']['VccHighWarning']['value'] + vccLowWarn = module_threshold_data['data']['VccLowWarning']['value'] + else: + return transceiver_dom_threshold_dict + + # Channel Threshold + channel_threshold_data = self._get_eeprom_data('ChannelThreshold') + if (channel_threshold_data is not None): + rxPowerHighAlarm = channel_threshold_data['data']['RxPowerHighAlarm']['value'] + rxPowerLowAlarm = channel_threshold_data['data']['RxPowerLowAlarm']['value'] + rxPowerHighWarn = channel_threshold_data['data']['RxPowerHighWarning']['value'] + rxPowerLowWarn = channel_threshold_data['data']['RxPowerLowWarning']['value'] + txBiasHighAlarm = channel_threshold_data['data']['TxBiasHighAlarm']['value'] + txBiasLowAlarm = channel_threshold_data['data']['TxBiasLowAlarm']['value'] + txBiasHighWarn = channel_threshold_data['data']['TxBiasHighWarning']['value'] + txBiasLowWarn = channel_threshold_data['data']['TxBiasLowWarning']['value'] + else: + return transceiver_dom_threshold_dict + + transceiver_dom_threshold_dict['temphighalarm'] = tempHighAlarm + transceiver_dom_threshold_dict['templowalarm'] = tempLowAlarm + transceiver_dom_threshold_dict['temphighwarning'] = tempHighWarn + transceiver_dom_threshold_dict['templowwarning'] = tempLowWarn + transceiver_dom_threshold_dict['vcchighalarm'] = vccHighAlarm + transceiver_dom_threshold_dict['vcclowalarm'] = vccLowAlarm + transceiver_dom_threshold_dict['vcchighwarning'] = vccHighWarn + transceiver_dom_threshold_dict['vcclowwarning'] = vccLowWarn + transceiver_dom_threshold_dict['rxpowerhighalarm'] = rxPowerHighAlarm + transceiver_dom_threshold_dict['rxpowerlowalarm'] = rxPowerLowAlarm + transceiver_dom_threshold_dict['rxpowerhighwarning'] = rxPowerHighWarn + transceiver_dom_threshold_dict['rxpowerlowwarning'] = rxPowerLowWarn + transceiver_dom_threshold_dict['txbiashighalarm'] = txBiasHighAlarm + transceiver_dom_threshold_dict['txbiaslowalarm'] = txBiasLowAlarm + transceiver_dom_threshold_dict['txbiashighwarning'] = txBiasHighWarn + transceiver_dom_threshold_dict['txbiaslowwarning'] = txBiasLowWarn + + return transceiver_dom_threshold_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + """ + tx_bias_list = [] + rx_power_list = [] + transceiver_dom_dict = {} + transceiver_dom_dict = dict.fromkeys(dom_dict_keys, 'N/A') + + # RxLos + rx_los = self.get_rx_los() + + # TxFault + tx_fault = self.get_tx_fault() + + # ResetStatus + reset_state = self.get_reset_status() + + # LowPower Mode + lp_mode = self.get_lpmode() + + # TxDisable + tx_disable = self.get_tx_disable() + + # TxDisable Channel + tx_disable_channel = self.get_tx_disable_channel() + + # Temperature + temperature = self.get_temperature() + + # Voltage + voltage = self.get_voltage() + + # Channel Monitor + channel_monitor_data = self._get_eeprom_data('ChannelMonitor') + if (channel_monitor_data is not None): + tx_bias = channel_monitor_data['data']['TX1Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = channel_monitor_data['data']['TX2Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = channel_monitor_data['data']['TX3Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = channel_monitor_data['data']['TX4Bias']['value'] + tx_bias_list.append(tx_bias) + rx_power = channel_monitor_data['data']['RX1Power']['value'] + rx_power_list.append(rx_power) + rx_power = channel_monitor_data['data']['RX2Power']['value'] + rx_power_list.append(rx_power) + rx_power = channel_monitor_data['data']['RX3Power']['value'] + rx_power_list.append(rx_power) + rx_power = channel_monitor_data['data']['RX4Power']['value'] + rx_power_list.append(rx_power) + else: + return transceiver_dom_dict + + transceiver_dom_dict['rx_los'] = rx_los + transceiver_dom_dict['tx_fault'] = tx_fault + transceiver_dom_dict['reset_status'] = reset_state + transceiver_dom_dict['power_lpmode'] = lp_mode + transceiver_dom_dict['tx_disable'] = tx_disable + transceiver_dom_dict['tx_disable_channel'] = tx_disable_channel + transceiver_dom_dict['temperature'] = temperature + transceiver_dom_dict['voltage'] = voltage + transceiver_dom_dict['tx1bias'] = tx_bias_list[0] + transceiver_dom_dict['tx2bias'] = tx_bias_list[1] + transceiver_dom_dict['tx3bias'] = tx_bias_list[2] + transceiver_dom_dict['tx4bias'] = tx_bias_list[3] + transceiver_dom_dict['rx1power'] = rx_power_list[0] + transceiver_dom_dict['rx2power'] = rx_power_list[1] + transceiver_dom_dict['rx3power'] = rx_power_list[2] + transceiver_dom_dict['rx4power'] = rx_power_list[3] + + return transceiver_dom_dict + + def get_name(self): + """ + Retrieves the name of the sfp + Returns : QSFP or QSFP+ or QSFP28 + """ + iface_data = self._get_eeprom_data('type') + if (iface_data is not None): + identifier = iface_data['data']['type']['value'] + else: + return None + + return identifier + + def get_presence(self): + """ + Retrieves the presence of the sfp + """ + presence_ctrl = self.sfp_control + 'qsfp_modprs' + try: + reg_file = open(presence_ctrl) + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + mask = (1 << self.sfp_ctrl_idx) + + # ModPrsL is active low + if ((reg_value & mask) == 0): + return True + + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the sfp + """ + vendor_pn_data = self._get_eeprom_data('model') + if (vendor_pn_data is not None): + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + else: + return None + + return vendor_pn + + def get_serial(self): + """ + Retrieves the serial number of the sfp + """ + vendor_sn_data = self._get_eeprom_data('serial') + if (vendor_sn_data is not None): + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + else: + return None + + return vendor_sn + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + """ + reset_status = None + reset_ctrl = self.sfp_control + 'qsfp_reset' + try: + reg_file = open(reset_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + index = self.sfp_ctrl_idx + + mask = (1 << index) + + if ((reg_value & mask) == 0): + reset_status = True + else: + reset_status = False + + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + """ + rx_los_list = [] + + rx_los_data = self._get_eeprom_data('rx_los') + if (rx_los_data is not None): + rx_los = rx_los_data['data']['Rx1LOS']['value'] + if (rx_los == 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx2LOS']['value'] + if (rx_los == 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx3LOS']['value'] + if (rx_los == 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx4LOS']['value'] + if (rx_los == 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + + return rx_los_list + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + """ + tx_fault_list = [] + + tx_fault_data = self._get_eeprom_data('tx_fault') + if (tx_fault_data is not None): + tx_fault = tx_fault_data['data']['Tx1Fault']['value'] + if (tx_fault == 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx2Fault']['value'] + if (tx_fault == 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx3Fault']['value'] + if (tx_fault == 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx4Fault']['value'] + if (tx_fault == 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + + return tx_fault_list + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + """ + tx_disable_list = [] + + tx_disable_data = self._get_eeprom_data('tx_disable') + if (tx_disable_data is not None): + tx_disable = tx_disable_data['data']['Tx1Disable']['value'] + if (tx_disable == 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx2Disable']['value'] + if (tx_disable == 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx3Disable']['value'] + if (tx_disable == 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx4Disable']['value'] + if (tx_disable == 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + + return tx_disable_list + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + """ + tx_disable_channel = 0 + + tx_disable = self.get_tx_disable() + for channel, disable in enumerate(tx_disable): + if disable: + tx_disable_channel |= 1 << channel + + return tx_disable_channel + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + """ + lpmode_ctrl = self.sfp_control + 'qsfp_lpmode' + try: + reg_file = open(lpmode_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + index = self.sfp_ctrl_idx + + mask = (1 << index) + + if ((reg_value & mask) == 0): + lpmode_state = False + else: + lpmode_state = True + + return lpmode_state + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + """ + power_override_state = None + + # Reset Status + power_override_data = self._get_eeprom_data('power_override') + if (power_override_data is not None): + power_override = power_override_data['data']['PowerOverRide']['value'] + if (power_override == 'On'): + power_override_state = True + else: + power_override_state = False + + return power_override_state + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + """ + temperature = None + + temperature_data = self._get_eeprom_data('Temperature') + if (temperature_data is not None): + temperature = self._strip_unit_from_str(temperature_data['data']['Temperature']['value']) + + return temperature + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + """ + voltage = None + + voltage_data = self._get_eeprom_data('Voltage') + if (voltage_data is not None): + voltage = self._strip_unit_from_str(voltage_data['data']['Vcc']['value']) + + return voltage + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + """ + tx_bias_list = [] + + tx_bias_data = self._get_eeprom_data('ChannelMonitor') + if (tx_bias_data is not None): + tx_bias_list.append(self._strip_unit_from_str(tx_bias_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._strip_unit_from_str(tx_bias_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._strip_unit_from_str(tx_bias_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._strip_unit_from_str(tx_bias_data['data']['TX4Bias']['value'])) + + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + """ + rx_power_list = [] + + rx_power_data = self._get_eeprom_data('ChannelMonitor') + if (rx_power_data is not None): + rx_power_list.append(self._strip_unit_from_str(rx_power_data['data']['RX1Power']['value'])) + rx_power_list.append(self._strip_unit_from_str(rx_power_data['data']['RX2Power']['value'])) + rx_power_list.append(self._strip_unit_from_str(rx_power_data['data']['RX3Power']['value'])) + rx_power_list.append(self._strip_unit_from_str(rx_power_data['data']['RX4Power']['value'])) + + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + """ + tx_power_list = [] + + tx_power_list.append(float('-inf')) + tx_power_list.append(float('-inf')) + tx_power_list.append(float('-inf')) + tx_power_list.append(float('-inf')) + + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + """ + reset_ctrl = self.sfp_control + 'qsfp_reset' + try: + # Open reset_ctrl in both read & write mode + reg_file = open(reset_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + index = self.sfp_ctrl_idx + + # Mask off the bit corresponding to our port + mask = (1 << index) + + # ResetL is active low + reg_value = (reg_value & ~mask) + + # Convert our register value back to a + # hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(reset_ctrl, "w") + except IOError as e: + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + """ + lpmode_ctrl = self.sfp_control + 'qsfp_lpmode' + try: + reg_file = open(lpmode_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + index = self.sfp_ctrl_idx + + mask = (1 << index) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = (reg_value | mask) + else: + reg_value = (reg_value & ~mask) + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + """ + eeprom = None + tx_disable_value = 0xf if tx_disable else 0x0 + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_CONTROL_OFFSET) + eeprom.write(struct.pack('B', tx_disable_value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + """ + eeprom = None + current_state = self.get_tx_disable_channel() + + if disable: + tx_disable_value = current_state | channel + else: + tx_disable_value = current_state & (~channel) + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_CONTROL_OFFSET) + eeprom.write(struct.pack('B', tx_disable_value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + """ + eeprom = None + power_override_bit = 0x1 if power_override else 0 + power_set_bit = 0x2 if power_set else 0 + value = power_override_bit | power_set_bit + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + eeprom.write(struct.pack('B', value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True + + def get_status(self): + """ + Retrieves the operational status of the device + """ + reset = self.get_reset_status() + + if (reset == True): + status = False + else: + status = True + + return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True 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 new file mode 100644 index 000000000000..ad089a8946a9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/thermal.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S6000 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + import os + import glob + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """DellEMC Platform-specific Thermal class""" + + I2C_DIR = "/sys/class/i2c-adapter/" + I2C_DEV_MAPPING = (['i2c-11/11-004c/hwmon/', 1], + ['i2c-11/11-004d/hwmon/', 1], + ['i2c-11/11-004e/hwmon/', 1], + ['i2c-10/10-0018/hwmon/', 1], + ['i2c-1/1-0059/hwmon/', 1], + ['i2c-1/1-0059/hwmon/', 2], + ['i2c-1/1-0058/hwmon/', 1], + ['i2c-1/1-0058/hwmon/', 2]) + THERMAL_NAME = ('ASIC On-board', 'NIC', 'System Front', 'DIMM', + 'PSU1-Sensor 1', 'PSU1-Sensor 2', 'PSU2-Sensor 1', + 'PSU2-Sensor 2', 'CPU Core 0', 'CPU Core 1') + + def __init__(self, thermal_index, + psu_index=1, psu_thermal=False, dependency=None): + self.is_psu_thermal = psu_thermal + self.dependency = dependency + self.is_driver_initialized = True + + if self.is_psu_thermal: + self.index = (2 * psu_index) + thermal_index + 2 + else: + # CPU thermal + if thermal_index > 3: + self.index = thermal_index + 5 + else: + self.index = thermal_index + 1 + + 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" + 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: + hwmon_temp_suffix = "crit" + else: + dev_path = "/sys/devices/platform/coretemp.0/hwmon/" + hwmon_temp_index = self.index - 7 + hwmon_temp_suffix = "crit" + 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 \ + + "temp{}_input".format(hwmon_temp_index) + self.thermal_high_threshold_file = self.HWMON_DIR \ + + "temp{}_{}".format(hwmon_temp_index, hwmon_temp_suffix) + self.thermal_low_threshold_file = self.HWMON_DIR \ + + "temp{}_min".format(hwmon_temp_index) + + def _read_sysfs_file(self, sysfs_file): + # On successful read, returns the value read from given + # 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 + + try: + with open(sysfs_file, 'r') as fd: + rv = fd.read() + except: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + 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 + + Returns: + string: The name of the thermal + """ + return self.THERMAL_NAME[self.index - 1] + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + if self.dependency: + return self.dependency.get_presence() + else: + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return 'NA' + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + if self.dependency: + return self.dependency.get_status() + else: + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether Thermal is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + thermal_temperature = self._read_sysfs_file( + self.thermal_temperature_file) + if (thermal_temperature != 'ERR'): + thermal_temperature = float(thermal_temperature) + else: + thermal_temperature = 0 + + return thermal_temperature / 1000.0 + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + thermal_high_threshold = self._read_sysfs_file( + self.thermal_high_threshold_file) + if (thermal_high_threshold != 'ERR'): + thermal_high_threshold = float(thermal_high_threshold) + else: + thermal_high_threshold = 0 + + return thermal_high_threshold / 1000.0 + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + thermal_low_threshold = self._read_sysfs_file( + self.thermal_low_threshold_file) + if (thermal_low_threshold != 'ERR'): + thermal_low_threshold = float(thermal_low_threshold) + else: + thermal_low_threshold = 0 + + return thermal_low_threshold / 1000.0 + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False 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/s6000/systemd/platform-modules-s6000.service b/platform/broadcom/sonic-platform-modules-dell/s6000/systemd/platform-modules-s6000.service new file mode 100644 index 000000000000..22de50ca929e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/systemd/platform-modules-s6000.service @@ -0,0 +1,13 @@ +[Unit] +Description=Dell S6000 Platform modules +After=local-fs.target +Before=pmon.service determine-reboot-cause.service + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/s6000_platform.sh init +ExecStop=/usr/local/bin/s6000_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/s6100/modules/Makefile new file mode 100644 index 000000000000..63242a5cf123 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_s6100_iom_cpld.o dell_s6100_lpc.o dell_ich.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/modules/dell_s6100_iom_cpld.c b/platform/broadcom/sonic-platform-modules-dell/s6100/modules/dell_s6100_iom_cpld.c new file mode 100644 index 000000000000..1ffa909ed70a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/modules/dell_s6100_iom_cpld.c @@ -0,0 +1,516 @@ + +#include // included for all kernel modules +#include // included for KERN_INFO +#include // included for __init and __exit macros +#include +#include +#include +#include + + +//iom cpld slave address +#define IOM_CPLD_SLAVE_ADD 0x3e + +#define CPLD_SEP_RST0 0x5 + +//iom cpld ver register +#define IOM_CPLD_SLAVE_VER 0x00 + +//qsfp reset cntrl reg on each iom +#define QSFP_RST_CRTL_REG0 0x10 +#define QSFP_RST_CRTL_REG1 0x11 + +//qsfp lp mode reg on each iom +#define QSFP_LPMODE_REG0 0x12 +#define QSFP_LPMODE_REG1 0x13 + +//qsfp mod presence reg on each iom +#define QSFP_MOD_PRS_REG0 0x16 +#define QSFP_MOD_PRS_REG1 0x17 + +//qsfp interrupt registers +#define QSFP_INT_STA_REG0 0x14 +#define QSFP_INT_STA_REG1 0x15 +#define QSFP_ABS_STA_REG0 0x16 +#define QSFP_ABS_STA_REG1 0x17 +#define QSFP_TRIG_MOD 0x20 +#define QSFP_INT_COMBINE 0x21 +#define QSFP_INT0 0x22 +#define QSFP_INT1 0x23 +#define QSFP_ABS_INT0 0x24 +#define QSFP_ABS_INT1 0x25 +#define QSFP_INT_MASK0 0x26 +#define QSFP_INT_MASK1 0x27 +#define QSFP_ABS_MASK0 0x28 +#define QSFP_ABS_MASK1 0x29 + +struct cpld_data { + struct i2c_client *client; + struct mutex update_lock; +}; + + +static void dell_s6100_iom_cpld_add_client(struct i2c_client *client) +{ + struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + + if (!data) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); +} + +static void dell_s6100_iom_cpld_remove_client(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + kfree(data); + return; +} + +int dell_s6100_iom_cpld_read(struct cpld_data *data,unsigned short cpld_addr, u8 reg) +{ + int ret = -EPERM; + u8 high_reg =0x00; + + mutex_lock(&data->update_lock); + ret = i2c_smbus_write_byte_data(data->client, high_reg,reg); + ret = i2c_smbus_read_byte(data->client); + mutex_unlock(&data->update_lock); + + return ret; +} + +int dell_s6100_iom_cpld_write(struct cpld_data *data,unsigned short cpld_addr, u8 reg, u8 value) +{ + int ret = -EIO; + u16 devdata=0; + u8 high_reg =0x00; + + mutex_lock(&data->update_lock); + devdata = (value << 8) | reg; + i2c_smbus_write_word_data(data->client,high_reg,devdata); + mutex_unlock(&data->update_lock); + + return ret; +} +static ssize_t get_cpldver(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,IOM_CPLD_SLAVE_VER); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"IOM CPLD Version:0x%02x\n",devdata); +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_MOD_PRS_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_MOD_PRS_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG0,(u8)(devdata & 0xff)); + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_LPMODE_REG1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG0,(u8)(devdata & 0xff)); + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_RST_CRTL_REG1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t get_int_sta(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_STA_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_STA_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_abs_sta(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_STA_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_STA_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_trig_mod(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_TRIG_MOD); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"0x%02x\n",devdata); +} + +static ssize_t set_trig_mod(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_TRIG_MOD,(u8)(devdata & 0xff)); + + return count; +} + +static ssize_t get_int_combine(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_COMBINE); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"0x%02x\n",devdata); +} + +static ssize_t get_int(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_abs_int(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_INT0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_INT1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_int_mask(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_MASK0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_MASK1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_int_mask(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_MASK0,(u8)(devdata & 0xff)); + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_INT_MASK1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t get_abs_mask(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_MASK0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_MASK1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_abs_mask(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_MASK0,(u8)(devdata & 0xff)); + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,QSFP_ABS_MASK1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t get_sep_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,CPLD_SEP_RST0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"0x%02x\n",devdata); +} + +static ssize_t set_sep_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,CPLD_SEP_RST0,(u8)(devdata & 0xff)); + + return count; +} + +static DEVICE_ATTR(iom_cpld_vers,S_IRUGO,get_cpldver, NULL); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO,get_modprs, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR,get_lpmode,set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR,get_reset, set_reset); +static DEVICE_ATTR(qsfp_int_sta, S_IRUGO, get_int_sta, NULL); +static DEVICE_ATTR(qsfp_abs_sta, S_IRUGO, get_abs_sta, NULL); +static DEVICE_ATTR(qsfp_trig_mod, S_IRUGO | S_IWUSR, get_trig_mod, set_trig_mod); +static DEVICE_ATTR(qsfp_int_combine, S_IRUGO, get_int_combine, NULL); +static DEVICE_ATTR(qsfp_int, S_IRUGO, get_int, NULL); +static DEVICE_ATTR(qsfp_abs_int, S_IRUGO, get_abs_int, NULL); +static DEVICE_ATTR(qsfp_int_mask, S_IRUGO | S_IWUSR, get_int_mask, set_int_mask); +static DEVICE_ATTR(qsfp_abs_mask, S_IRUGO | S_IWUSR, get_abs_mask, set_abs_mask); +static DEVICE_ATTR(sep_reset, S_IRUGO | S_IWUSR, get_sep_reset, set_sep_reset); + +static struct attribute *i2c_cpld_attrs[] = { + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_iom_cpld_vers.attr, + &dev_attr_qsfp_int_sta.attr, + &dev_attr_qsfp_abs_sta.attr, + &dev_attr_qsfp_trig_mod.attr, + &dev_attr_qsfp_int_combine.attr, + &dev_attr_qsfp_int.attr, + &dev_attr_qsfp_abs_int.attr, + &dev_attr_qsfp_int_mask.attr, + &dev_attr_qsfp_abs_mask.attr, + &dev_attr_sep_reset.attr, + NULL, +}; + +static struct attribute_group i2c_cpld_attr_grp = { + .attrs = i2c_cpld_attrs, +}; + +static int dell_s6100_iom_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + dell_s6100_iom_cpld_add_client(client); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &i2c_cpld_attr_grp); + if (status) { + printk(KERN_INFO "Cannot create sysfs\n"); + } + return 0; + +exit: + return status; +} + +static int dell_s6100_iom_cpld_remove(struct i2c_client *client) +{ + dell_s6100_iom_cpld_remove_client(client); + return 0; +} + + +static const struct i2c_device_id dell_s6100_iom_cpld_id[] = { + { "dell_s6100_iom_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dell_s6100_iom_cpld_id); + +static struct i2c_driver dell_s6100_iom_cpld_driver = { + .driver = { + .name = "dell_s6100_iom_cpld", + }, + .probe = dell_s6100_iom_cpld_probe, + .remove = dell_s6100_iom_cpld_remove, + .id_table = dell_s6100_iom_cpld_id, +}; + + + +static int __init dell_s6100_iom_cpld_init(void) +{ + return i2c_add_driver(&dell_s6100_iom_cpld_driver); +} + +static void __exit dell_s6100_iom_cpld_exit(void) +{ + i2c_del_driver(&dell_s6100_iom_cpld_driver); +} + +MODULE_AUTHOR("Srideep Devireddy "); +MODULE_DESCRIPTION("dell_s6100_iom_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(dell_s6100_iom_cpld_init); +module_exit(dell_s6100_iom_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/README b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/README new file mode 100644 index 000000000000..b141bb05e2e4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/README @@ -0,0 +1,146 @@ +Dell S6100 64x40G support +------------------------ + +summary:- +S6100 has 64 x 40G port capacity +S6100 supports 4 IO Modules which are pluggable. Below section covers how to power on IO modules +and initialize the device drivers and configure necessary mux to send traffic. + + +Necessary drivers and scripts to package + +1) Users are expected to build necessary drivers for kernel and package to acess it on the target + + a) Mgmt phy driver + This supports BCM 54616 phy driver ( enable CONFIG_IGB in kernel config) + b) driver-support-sff-8436-eeprom.patch + c) driver-support-sff-8436-eeprom-update.patch + This driver supports QSFP EEPROM + d) dell_s6100_iom_cpld.ko + This driver provides support for cpld on 4 x 40Gig-IOM modules + e) i2c_mux_pca954x.ko + This driver provides support for i2c mux/switch (pca954x) + f) dell_s6100_lpc.ko + This driver porivide support for reading all the platform info from SMF. + + +2) Users are also expected to package below scripts for platform initialization and i2c tree creation + + a) iom_power.sh + This script is used to power on IO modules on S6100 + b) io_rd_wr.py +This script is generic LPC/io read/write utility (can also access system cpld) + +steps to platform initialization (Tested with 3.16) + +1) After power up of S6100 + + a) power up the io modules by executing (./iom_power.sh) + b) insert i2c_mux_pca954x.ko,dell_s6100_iom_cpld.ko,dell_s6100_lpc.ko + + Above 2 steps can be called by including them in below 2 step + +2) Build i2c device tree/device initialization by calling below script + + ./s6100_platform_init.sh + +3) IOM cpld devices are created under "/sys/bus/i2c/drivers/dell_s6100_iom_cpld/" + QSFP handles via sysfs i2c bus #( 15,16,17,18-003e) + iom_cpld_vers -- Displays CPLD version(RO) + qsfp_lpmode -- lpmode settings(RW) + qsfp_modprs -- modules presence (RO) + qsfp_reset -- reset settings (RW) + + ls /sys/bus/i2c/drivers/dell_s6100_iom_cpld/15-003e/ + driver/ iom_cpld_vers modalias name power/ qsfp_lpmode qsfp_modprs qsfp_reset subsystem/ uevent + +4) step 2 script also builds/attach sfp device tress in sysfs + + Example for reading EEPROM data + + cat /sys/bus/i2c/devices/19-0050/eeprom | hexdump -C + 00000000 0d 00 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 |................| + 00000010 00 00 00 00 00 00 18 1b 00 00 82 20 00 00 00 00 |........... ....| + 00000020 00 00 00 00 00 00 00 00 00 00 16 4d 16 4d 16 4d |...........M.M.M| + 00000030 16 4d 34 bf 44 bf 54 bf 64 bf 00 00 00 00 00 00 |.M4.D.T.d.......| + 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| + * + 00000070 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff 00 |................| + 00000080 0d 00 0c 04 00 00 00 40 40 02 d5 05 69 00 00 32 |.......@@...i..2| + 00000090 00 00 00 00 46 49 4e 49 53 41 52 20 43 4f 52 50 |....FINISAR CORP| + 000000a0 20 20 20 20 07 00 90 65 46 54 4c 34 31 30 51 45 | ...eFTL410QE| + 000000b0 31 43 20 20 20 20 20 20 41 33 42 68 07 d0 46 70 |1C A3Bh..Fp| + 000000c0 00 01 04 d0 4d 4c 54 30 30 51 33 20 20 20 20 20 |....MLT00Q3 | + 000000d0 20 20 20 20 31 32 30 31 31 35 20 20 08 00 00 38 | 120115 ...8| + 000000e0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | + 000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| + * + 00000200 4b 00 fb 00 46 00 00 00 00 00 00 00 00 00 00 00 |K...F...........| + 00000210 94 70 6e f0 86 c4 7b 0c 00 00 00 00 00 00 00 00 |.pn...{.........| + 00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| + * + 00000260 00 00 11 11 00 00 00 00 00 00 00 00 00 00 22 22 |..............""| + 00000270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| + 00000280 + +5)SMF driver details/Readme are as below + + S6100 SMF + --------- + + S6100 has one SMF soc on CPU board. This is via LPC interface, provide access to all the below functionality + + a) Read sensors details on the system + b) Read PSU details on the system + c) Read fans/Fan tray details on the system + d) Read/Write to system led + + dell_s6100_lpc create entry for all the above necessary platform components as attributes in below path. + + /sys/devices/platform/dell_s6100_lpc/ + + + LED:- + ---- + + Get /set operations on sys_led + + Get operation + cat /sys/devices/platform/dell_s6100_lpc/sys_led + 0x80 + + Set operation + echo 83 > sys/devices/platform/dell_s6100_lpc/sys_led + + Sensors:- + -------- + + Max no of sensors on the system ( 11 sensors are available on fully loaded system) + + cat /sys/devices/platform/dell_s6100_lpc/max_num_temp_sensors + b + + cat /sys/devices/platform/dell_s6100_lpc/temp_sensor_1 ( temp_sensor_1 <85>.temp_sensor_11) + + Fan tray speed:- + -------------- + + /sys/devices/platform/dell_s6100_lpc/fan_tray_1_speed (fan_tray_1_speed - fan_tray_4_speed) + 13700 + + cat /sys/devices/platform/dell_s6100_lpc/psu1_max_pwr + 110 + cat /sys/devices/platform/dell_s6100_lpc/psu2_max_pwr + 110 + + cat /sys/devices/platform/dell_s6100_lpc/psu_total_pwr + 232 + + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/fast-reboot_plugin b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/fast-reboot_plugin new file mode 100755 index 000000000000..e32747c7fed5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/fast-reboot_plugin @@ -0,0 +1,7 @@ +#!/bin/bash + +if [[ -d /sys/devices/platform/SMF.512/hwmon/ ]]; then + cd /sys/devices/platform/SMF.512/hwmon/* + echo 0xcc > mb_poweron_reason +fi +/usr/local/bin/s6100_i2c_enumeration.sh deinit & > /dev/null diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_off.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_off.sh new file mode 100755 index 000000000000..077d760fdfc0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_off.sh @@ -0,0 +1,16 @@ +#!/bin/bash +#This script is used to power off IO modules +# IOM can be controlled via SMF using mailbox registers +# write 0x2 to 0x04D9 to power off IOM 1 +io_rd_wr.py --set --val 0x04 --offset 0x210 +io_rd_wr.py --set --val 0xd9 --offset 0x211 +io_rd_wr.py --set --val 0x2 --offset 0x213 +# write 0x2 to 0x04DA to power off IOM 2 +io_rd_wr.py --set --val 0xda --offset 0x211 +io_rd_wr.py --set --val 0x2 --offset 0x213 +# write 0x2 to 0x04DB to power off IOM 3 +io_rd_wr.py --set --val 0xdb --offset 0x211 +io_rd_wr.py --set --val 0x2 --offset 0x213 +# write 0x2 to 0x04DC to power off IOM 4 +io_rd_wr.py --set --val 0xdc --offset 0x211 +io_rd_wr.py --set --val 0x2 --offset 0x213 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_on.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_on.sh new file mode 100755 index 000000000000..80b876c216ec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/iom_power_on.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# This script is used to power on IO modules +# IOM can be controlled via SMF using mailbox registers + +# write 0x1 to 0x04D9 to power up IOM 1 +/usr/local/bin/io_rd_wr.py --set --val 0x04 --offset 0x210 +/usr/local/bin/io_rd_wr.py --set --val 0xd9 --offset 0x211 +/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213 +# write 0x1 to 0x04DA to power up IOM 2 +/usr/local/bin/io_rd_wr.py --set --val 0xda --offset 0x211 +/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213 +# write 0x1 to 0x04DB to power up IOM 3 +/usr/local/bin/io_rd_wr.py --set --val 0xdb --offset 0x211 +/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213 +# write 0x1 to 0x04DC to power up IOM 4 +/usr/local/bin/io_rd_wr.py --set --val 0xdc --offset 0x211 +/usr/local/bin/io_rd_wr.py --set --val 0x1 --offset 0x213 +#Delay for SMF to power on IOMs +sleep 3 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/override.conf b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/override.conf new file mode 100644 index 000000000000..cd7458e7a8b2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/override.conf @@ -0,0 +1,3 @@ +[Service] +ExecStart= +ExecStart=/usr/share/sonic/device/x86_64-dell_s6100_c2538-r0/platform_reboot_override diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/pcisysfs.py b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/pcisysfs.py new file mode 100755 index 000000000000..fd3564e75619 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/pcisysfs.py @@ -0,0 +1,92 @@ +#!/usr/bin/python3 + +import struct +import sys +import getopt +from os import * +from mmap import * + +def usage(): + ''' This is the Usage Method ''' + + print('\t\t pcisysfs.py --get --offset --res ') + print('\t\t pcisysfs.py --set --val --offset --res ') + sys.exit(1) + +def pci_mem_read(mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + print("") + reg_val = struct.unpack('I', read_data_stream) + print("reg_val read:%x" % reg_val) + return reg_val + +def pci_mem_write(mm, offset, data): + mm.seek(offset) + #print("data to write:%x" % data) + mm.write(struct.pack('I', data)) + +def pci_set_value(resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + pci_mem_write(mm, offset, val) + mm.close() + close(fd) + +def pci_get_value(resource, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + pci_mem_read(mm, offset) + mm.close() + close(fd) + +def main(argv): + + ''' The main function will read the user input from the + command line argument and process the request ''' + + opts = '' + val = '' + choice = '' + resource = '' + offset = '' + + try: + opts, args = getopt.getopt(argv, "hgsv:", + ["val=", "res=", "offset=", "help", "get", "set"]) + + except getopt.GetoptError: + usage() + + for opt, arg in opts: + + if opt in ('-h', '--help'): + choice = 'help' + + elif opt in ('-g', '--get'): + choice = 'get' + + elif opt in ('-s', '--set'): + choice = 'set' + + elif opt == '--res': + resource = arg + + elif opt == '--val': + val = int(arg, 16) + + elif opt == '--offset': + offset = int(arg, 16) + + if choice == 'set' and val != '' and offset != '' and resource != '': + pci_set_value(resource, val, offset) + + elif choice == 'get' and offset != '' and resource != '': + pci_get_value(resource, offset) + + else: + usage() + +# Calling the main method +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_reboot_override b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_reboot_override new file mode 100755 index 000000000000..dc681104dac1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_reboot_override @@ -0,0 +1,36 @@ +#!/usr/bin/python3 +import os +import subprocess +import struct + +PORT_RES = '/dev/port' + + +def log_software_reboot(): + # Run plugin script which will track the cli triggered reboot, fastboot, warmboot + res = subprocess.check_output(['/usr/share/sonic/device/x86_64-dell_s6100_c2538-r0/fast-reboot_plugin']) + return + +def ssd_hdparm_upgrade(): + if os.path.exists('/tmp/SSD/SYS_S.bin'): + res = subprocess.check_output(['/usr/share/sonic/device/x86_64-dell_s6100_c2538-r0/ssd-fw-upgrade', 'hdparm-upgrade']) + return + +def portio_reg_write(resource, offset, val): + fd = os.open(resource, os.O_RDWR) + if(fd < 0): + print('file open failed %s" % resource') + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print('lseek failed on %s' % resource) + return + ret = os.write(fd, struct.pack('B', val)) + if(ret != 1): + print('write failed %d' % ret) + return + os.close(fd) + +if __name__ == "__main__": + log_software_reboot() + ssd_hdparm_upgrade() + portio_reg_write(PORT_RES, 0xcf9, 0xe) 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 new file mode 100755 index 000000000000..089cf277551d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_sensors.py @@ -0,0 +1,323 @@ +#!/usr/bin/python3 + +# On S6100, the Platform Management Controller runs the +# thermal algorithm. It provides a mailbox for the Host +# to query relevant thermals. The dell_mailbox module +# provides the sysfs support for the following objects: +# * onboard temperature sensors +# * FAN trays +# * PSU +# +import os +import logging + +S6100_MAX_FAN_TRAYS = 4 +S6100_MAX_PSUS = 2 +S6100_MAX_IOMS = 4 + +HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" +HWMON_NODE = os.listdir(HWMON_DIR)[0] +MAILBOX_DIR = HWMON_DIR + HWMON_NODE +iom_status_list = [] + +# Get a mailbox register + + +def get_pmc_register(reg_name): + retval = 'ERR' + mb_reg_file = MAILBOX_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + print(mb_reg_file, 'not found !') + return retval + + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", mb_reg_file, "file !") + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + +logging.basicConfig(level=logging.DEBUG) + +if (os.path.isdir(MAILBOX_DIR)): + print('dell-s6100-lpc') + print('Adapter: S6100 Platform Management Controller') +else: + logging.error('S6100 Platform Management Controller module not loaded !') + # sys.exit(0) + +# Print the information for temperature sensors + + +def print_temperature_sensors(): + print("\nOnboard Temperature Sensors:") + print(' CPU: ', + int(get_pmc_register('temp1_input'))/1000, 'C') + print(' BCM56960 (PSU side): ', + int(get_pmc_register('temp2_input'))/1000, 'C') + print(' System Outlet 1 (switch board): ', + int(get_pmc_register('temp3_input'))/1000, 'C') + print(' BCM56960 (IO side): ', + int(get_pmc_register('temp4_input'))/1000, 'C') + print(' System Outlet 2 (CPU board): ', + int(get_pmc_register('temp9_input'))/1000, 'C') + print(' System Inlet Left (IO side): ', + int(get_pmc_register('temp10_input'))/1000, 'C') + print(' System Inlet Right (IO side): ', + int(get_pmc_register('temp11_input'))/1000, 'C') + + iom_status = get_pmc_register('iom_presence') + iom_status = int(iom_status, 16) + + iom_presence = get_pmc_register('iom_status') + + if (iom_presence != 'ERR'): + iom_presence = int(iom_presence, 16) + + # IOM presence : 0 => IOM present + # Temperature sensors 5..8 correspond to IOM 1..4 + for iom in range(0, S6100_MAX_IOMS): + if (~iom_presence & (1 << iom)): + iom_sensor_indx = iom + 5 + print(' IOM ' + str(iom + 1) + ':\t\t\t ', + int(get_pmc_register('temp' + str(iom_sensor_indx) + + '_input'))/1000, 'C') + + # Save the IOM Status for later use + if (~iom_status & (1 << iom)): + iom_status_list.append('ON') + else: + iom_status_list.append('OFF') + else: + iom_status_list.append('Not present') + print(' IOM ' + str(iom + 1) + ':\t\t\t ', 'Not present') + else: + logging.error('Unable to check IOM presence') + +print_temperature_sensors() + + +# Print the information for voltage sensors + + +def print_voltage_sensors(): + print("\nOnboard Voltage Sensors:") + + print(' CPU XP3R3V_EARLY ', + float(get_pmc_register('in1_input'))/1000, 'V') + print(' CPU XP5R0V_CP ', + float(get_pmc_register('in2_input'))/1000, 'V') + print(' CPU XP3R3V_STD ', + float(get_pmc_register('in3_input'))/1000, 'V') + print(' CPU XP3R3V_CP ', + float(get_pmc_register('in4_input'))/1000, 'V') + print(' CPU XP0R75V_VTT_A ', + float(get_pmc_register('in5_input'))/1000, 'V') + print(' CPU XPPR75V_VTT_B ', + float(get_pmc_register('in6_input'))/1000, 'V') + print(' CPU XP1R07V_CPU ', + float(get_pmc_register('in7_input'))/1000, 'V') + print(' CPU XP1R0V_CPU ', + float(get_pmc_register('in8_input'))/1000, 'V') + print(' CPU XP12R0V ', + float(get_pmc_register('in9_input'))/1000, 'V') + print(' CPU VDDR_CPU_2 ', + float(get_pmc_register('in10_input'))/1000, 'V') + print(' CPU VDDR_CPU_1 ', + float(get_pmc_register('in11_input'))/1000, 'V') + print(' CPU XP1R5V_CLK ', + float(get_pmc_register('in12_input'))/1000, 'V') + print(' CPU XP1R8V_CPU ', + float(get_pmc_register('in13_input'))/1000, 'V') + print(' CPU XP1R0V_CPU_VNN ', + float(get_pmc_register('in14_input'))/1000, 'V') + print(' CPU XP1R0V_CPU_VCC ', + float(get_pmc_register('in15_input'))/1000, 'V') + print(' CPU XP1R5V_EARLY ', + float(get_pmc_register('in16_input'))/1000, 'V') + print(' SW XP3R3V_MON ', + float(get_pmc_register('in17_input'))/1000, 'V') + print(' SW XP1R25V_MON ', + float(get_pmc_register('in19_input'))/1000, 'V') + print(' SW XP1R2V_MON ', + float(get_pmc_register('in20_input'))/1000, 'V') + print(' SW XP1R0V_SW_MON ', + float(get_pmc_register('in21_input'))/1000, 'V') + print(' SW XP1R0V_ROV_SW_MON ', + float(get_pmc_register('in22_input'))/1000, 'V') + print(' SW XR1R0V_BCM84752_MON ', + float(get_pmc_register('in23_input'))/1000, 'V') + print(' SW XP5V_MB_MON ', + float(get_pmc_register('in24_input'))/1000, 'V') + print(' SW XP3R3V_FPGA_MON ', + float(get_pmc_register('in26_input'))/1000, 'V') + print(' SW XP3R3V_EARLY_MON ', + float(get_pmc_register('in27_input'))/1000, 'V') + +print_voltage_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(tray): + + Fan_Status = ['Normal', 'Abnormal'] + Airflow_Direction = ['B2F', 'F2B'] + + print(' Fan Tray ' + str(tray) + ':') + + if (tray == 1): + fan1_speed = int(get_pmc_register('fan1_input')) + air_flow_reg = int(get_pmc_register('fan1_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + + print(' Fan Speed: ', fan1_speed, 'RPM') + print(' Fan State: ', Fan_Status[fan1_status]) + print(' Air Flow: ', Airflow_Direction[air_flow_reg]) + elif (tray == 2): + fan1_speed = int(get_pmc_register('fan3_input')) + air_flow_reg = int(get_pmc_register('fan3_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + + print(' Fan Speed: ', fan1_speed, 'RPM') + print(' Fan State: ', Fan_Status[fan1_status]) + print(' Air Flow: ', Airflow_Direction[air_flow_reg]) + elif (tray == 3): + fan1_speed = int(get_pmc_register('fan5_input')) + air_flow_reg = int(get_pmc_register('fan5_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + + print(' Fan Speed: ', fan1_speed, 'RPM') + print(' Fan State: ', Fan_Status[fan1_status]) + print(' Air Flow: ', Airflow_Direction[air_flow_reg]) + elif (tray == 4): + fan1_speed = int(get_pmc_register('fan7_input')) + air_flow_reg = int(get_pmc_register('fan7_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + + print(' Fan Speed: ', fan1_speed, 'RPM') + print(' Fan State: ', Fan_Status[fan1_status]) + print(' Air Flow: ', Airflow_Direction[air_flow_reg]) + +print('\nFan Trays:') +fan_tray_presence = get_pmc_register('fan_tray_presence') + +if (fan_tray_presence != 'ERR'): + fan_tray_presence = int(fan_tray_presence, 16) + + for tray in range(0, S6100_MAX_FAN_TRAYS): + if (fan_tray_presence & (1 << tray)): + print_fan_tray(tray + 1) + else: + print('\n Fan Tray ' + str(tray + 1) + ': Not present') +else: + logging.error('Unable to read FAN presence') + +# Print the information for PSU1, PSU2 + + +def print_psu(psu): + Psu_Type = ['Mismatch', 'Normal'] + Psu_Input_Type = ['AC', 'DC'] + PSU_STATUS_TYPE_BIT = 4 + PSU_STATUS_INPUT_TYPE_BIT = 1 + PSU_FAN_PRESENT_BIT = 2 + PSU_FAN_STATUS_BIT = 1 + PSU_FAN_AIR_FLOW_BIT = 0 + Psu_Fan_Presence = ['Present', 'Absent'] + Psu_Fan_Status = ['Normal', 'Abnormal'] + Psu_Fan_Airflow = ['B2F', 'F2B'] + + print(' PSU ' + str(psu) + ':') + if (psu == 1): + psu_status = int(get_pmc_register('psu1_presence'), 16) + else: + psu_status = int(get_pmc_register('psu2_presence'), 16) + + psu_input_type = (psu_status & (1 << PSU_STATUS_INPUT_TYPE_BIT)) >>\ + PSU_STATUS_INPUT_TYPE_BIT + psu_type = (psu_status & (1 << PSU_STATUS_TYPE_BIT)) >>\ + PSU_STATUS_TYPE_BIT + + print(' Input: ', Psu_Input_Type[psu_input_type]) + print(' Type: ', Psu_Type[psu_type]) + + # PSU FAN details + if (psu == 1): + print(' FAN Speed: ', get_pmc_register('fan11_input'), 'RPM') + psu_fan_airflow = int(get_pmc_register('fan11_airflow')) + psu_fan_status = int(get_pmc_register('fan11_alarm')) + 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')) / 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): + psu_fan_temp = int(get_pmc_register('temp14_input'))/1000 + else: + print(' FAN Speed: ', get_pmc_register('fan12_input'), 'RPM') + psu_fan_airflow = int(get_pmc_register('fan12_airflow')) + psu_fan_status = int(get_pmc_register('fan12_alarm')) + 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')) / 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): + psu_fan_temp = int(get_pmc_register('temp15_input'))/1000 + print(' FAN: ', Psu_Fan_Presence[psu_fan_present]) + print(' FAN Status: ', Psu_Fan_Status[psu_fan_status]) + print(' FAN AIRFLOW: ', Psu_Fan_Airflow[psu_fan_airflow]) + + # PSU input & output monitors + print(' Input Voltage: %6.2f' % (input_voltage), 'V') + + print(' Output Voltage: %6.2f' % (output_voltage), 'V') + + print(' Input Current: %6.2f' % (input_current), 'A') + + print(' Output Current: %6.2f' % (output_current), 'A') + + print(' Input Power: %6.2f' % (input_power), 'W') + + print(' Output Power: %6.2f' % (output_power), 'W') + + # PSU firmware gives spurious temperature reading without input power + if (input_power != 0): + print(' Temperature: ', psu_fan_temp, 'C') + else: + print(' Temperature: ', 'NA') + +print('\nPSUs:') +for psu in range(1, S6100_MAX_PSUS + 1): + + if (psu == 1): + psu_status = get_pmc_register('psu1_presence') + else: + psu_status = get_pmc_register('psu2_presence') + + if (psu_status != 'ERR'): + psu_status = int(psu_status, 16) + if (~psu_status & 0b1): + print_psu(psu) + else: + print('\n PSU ', psu, 'Not present') + else: + logging.error('Unable to check PSU presence') + +print('\n Total Power: ', get_pmc_register('current_total_power'), 'W') + +print('\nIO Modules:') + +for iom in range(1, S6100_MAX_IOMS+1): + print(' IOM ' + str(iom) + ' :' + iom_status_list[iom - 1]) + +print('\n') diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_watchdog_disable.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_watchdog_disable.sh new file mode 100755 index 000000000000..c3a90f3e89b2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_watchdog_disable.sh @@ -0,0 +1,13 @@ +#!/bin/bash +#This script is used to disable SMF Watchdog Timer + +wd_status=-1 +enabled=0 + +# Disable Watchdog if enabled +wd_status=$(io_rd_wr.py --get --offset 0x207 | cut -d " " -f3) + +if [[ $wd_status -eq $enabled ]]; then + echo "Disabling Watchdog Timer.." + io_rd_wr.py --set --val 1 --offset 0x207 +fi diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_watchdog_enable.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_watchdog_enable.sh new file mode 100755 index 000000000000..804627b5e2fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/platform_watchdog_enable.sh @@ -0,0 +1,8 @@ +#!/bin/bash +#This script is used to enable SMF Watchdog Timer + +# Set watchdog to 180 seconds +io_rd_wr.py --set --val 3 --offset 0x206 + +# Enable watchdog timer +io_rd_wr.py --set --val 0 --offset 0x207 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_bitbang_reset.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_bitbang_reset.sh new file mode 100755 index 000000000000..ff49c0a0f788 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_bitbang_reset.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Script to unfreeze a stuck I2C controller, by bit-banging a STOP cycle on the bus + +bit_bang_recovery() +{ + +# Clear the ERRSTS +pcisysfs.py --set --val 0xffffffff --offset 0x018 --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 + +#Enable I2C bit-banging +pcisysfs.py --set --val 0x80000000 --offset 0x388 --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 + +count=1 +while [ $count -le 9 ]; +do + # Bit-bang an I2C STOP cycle + + # SCL=0, SDA=0 + pcisysfs.py --set --val 0x80000000 --offset 0x388 --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 + + sleep 0.01 + + # SCL=1, SDA=0 + pcisysfs.py --set --val 0x80000002 --offset 0x388 --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 + + sleep 0.01 + + # SCL=1, SDA=1 + pcisysfs.py --set --val 0x80000003 --offset 0x388 --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 + + sleep 1 + + # Check I2C DBSTS register + mctrl=$((`pcisysfs.py --get --offset 0x108 --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 | sed 's/^.*:/0x/'`)) + msts=$((`pcisysfs.py --get --offset 0x10c --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 | sed 's/^.*:/0x/'`)) + dbsts=$((`pcisysfs.py --get --offset 0x38c --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 | sed 's/^.*:/0x/'`)) + msts_ip=$((msts&0x1)) + + mctrl=$((10#$mctrl)) + if [ $msts_ip = 0 ]; then + logger -p NOTICE "I2C_bitbang-Bit banging done on I2C bus" + logger -p NOTICE "After I2C_bitbang- MCTRL:$(printf "0x%x" $mctrl)","MSTS:$(printf "0x%x" $msts)","DBSTS:$(printf "0x%x" $dbsts)" + break + fi + count=$(( $count + 1 )) +done + +#Disable I2C bit-banging +pcisysfs.py --set --val 0x00000003 --offset 0x388 --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 + +} + +mctrl=$((`pcisysfs.py --get --offset 0x108 --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 | sed 's/^.*:/0x/'`)) +msts=$((`pcisysfs.py --get --offset 0x10c --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 | sed 's/^.*:/0x/'`)) +dbsts=$((`pcisysfs.py --get --offset 0x38c --res /sys/devices/pci0000\:00/0000\:00\:13.0/resource0 | sed 's/^.*:/0x/'`)) +logger -p NOTICE "Before I2C_bitbang- MCTRL:$(printf "0x%x" $mctrl)","MSTS:$(printf "0x%x" $msts)","DBSTS:$(printf "0x%x" $dbsts)" +sleep 2 +bit_bang_recovery diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_i2c_enumeration.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_i2c_enumeration.sh new file mode 100755 index 000000000000..d00fec233eaa --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_i2c_enumeration.sh @@ -0,0 +1,305 @@ +#!/bin/bash + +### DellEMC S6100 I2C MUX Enumeration script + +source dell_i2c_utils.sh + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [[ $found -eq 0 ]] && echo "cannot find iSMT" && exit 1 +} + +# Attach/Detach CPU board mux @ 0x70 +cpu_board_mux() { + case $1 in + "new_device") i2c_mux_create pca9547 0x70 $devnum 2 + ;; + "delete_device") i2c_mux_delete 0x70 $devnum + ;; + *) echo "s6100_platform: cpu_board_mux: invalid command !" + ;; + esac +} + +# Attach/Detach Switchboard MUX @ 0x71 +switch_board_mux() { + case $1 in + "new_device") i2c_mux_create pca9548 0x71 4 10 + ;; + "delete_device") i2c_mux_delete 0x71 4 + ;; + *) echo "s6100_platform: switch_board_mux : invalid command !" + ;; + esac +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + case $1 in + "new_device") i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-2/$1" + ;; + "delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-2/$1" + ;; + *) echo "s6100_platform: sys_eeprom : invalid command !" + ;; + 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 + "new_device") + for ((i=14;i<=17;i++)); + do + i2c_config "echo dell_s6100_iom_cpld 0x3e > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + "delete_device") + for ((i=14;i<=17;i++)); + do + i2c_config "echo 0x3e > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + *) echo "s6100_platform: switch_board_cpld : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs on each IOM @0x71 and 0x72 +switch_board_qsfp_mux() { + case $1 in + "new_device") + # The mux for the QSFPs spawn {18..25}, {26..33}... {74..81} + # starting at chennel 18 and 16 channels per IOM. + channel_first=18 + for ((i=9;i>=6;i--)); + do + # 0x71 mux on the IOM 1 + mux_index=$(expr $i - 5) + echo "Attaching PCA9548 $mux_index" + i2c_mux_create pca9548 0x71 $i $channel_first + i2c_mux_create pca9548 0x72 $i $(expr $channel_first + 8) + channel_first=$(expr $channel_first + 16) + done + ;; + "delete_device") + for ((i=9;i>=6;i--)); + do + # 0x71 mux on the IOM 1 + mux_index=$(expr $i - 5) + echo "Detaching PCA9548 $mux_index" + i2c_mux_delete 0x71 $i + i2c_mux_delete 0x72 $i + done + ;; + *) echo "s6100_platform: switch_board_qsfp_mux: invalid command !" + ;; + esac +} + +#Attach/Detach the SFP modules on PCA9548_2 +switch_board_sfp() { + case $1 in + "new_device") i2c_config "echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-11/$1" + i2c_config "echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-12/$1" + ;; + "delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-11/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-12/$1" + ;; + *) echo "s6100_platform: switch_board_sfp: invalid command !" + ;; + esac +} + +#Add/Delete ($1) a range ($2..$3) of QSFPs +qsfp_device_mod() { + case $1 in + "new_device") for ((i=$2;i<=$3;i++)); + do + i2c_config "echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + "delete_device") for ((i=$2;i<=$3;i++)); + do + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + *) echo "s6100_platform: qsfp_device_mod: invalid command $1:$2,$3!" + ;; + esac +} + +# Attach/Detach 16 instances of QSFP ports on each IO modules +# eeprom can dump data using below command +switch_board_qsfp() { + if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-18"; then + qsfp_device_mod $1 18 33 + fi + + if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-34"; then + qsfp_device_mod $1 34 49 + fi + + if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-50"; then + qsfp_device_mod $1 50 65 + fi + + if i2c_poll_bus_exists "/sys/bus/i2c/devices/i2c-66"; then + qsfp_device_mod $1 66 81 + fi +} + +# Enable/Disable low power mode on all QSFP ports +switch_board_qsfp_lpmode() { + case $1 in + "enable") value=0xffff + ;; + "disable") value=0x0 + ;; + *) echo "s6100_platform: switch_board_qsfp_lpmode: invalid command $1!" + return + ;; + esac + echo $value > /sys/class/i2c-adapter/i2c-14/14-003e/qsfp_lpmode + echo $value > /sys/class/i2c-adapter/i2c-15/15-003e/qsfp_lpmode + echo $value > /sys/class/i2c-adapter/i2c-16/16-003e/qsfp_lpmode + echo $value > /sys/class/i2c-adapter/i2c-17/17-003e/qsfp_lpmode +} + +# Enable/Disable xcvr presence interrupts +xcvr_presence_interrupts() { + case $1 in + "enable") + for ((i=14;i<=17;i++)); + do + echo 0x0 > /sys/class/i2c-adapter/i2c-$i/$i-003e/qsfp_abs_mask + done + ;; + "disable") + for ((i=14;i<=17;i++)); + do + echo 0xffff > /sys/class/i2c-adapter/i2c-$i/$i-003e/qsfp_abs_mask + done + ;; + *) echo "s6100_platform: xcvr_presence_interrupts: invalid command !" + ;; + esac +} + +# Reset the mux tree +reset_muxes() { + local i + + # Reset the IOM muxes (if they have been already instantiated) + for ((i=14;i<=17;i++)); + do + if [[ -e /sys/class/i2c-adapter/i2c-$i/$i-003e ]]; then + echo 0xfc > /sys/class/i2c-adapter/i2c-$i/$i-003e/sep_reset + echo 0xff > /sys/class/i2c-adapter/i2c-$i/$i-003e/sep_reset + fi + done + + # Reset the switch card PCA9548A + io_rd_wr.py --set --val 0xef --offset 0x110 + io_rd_wr.py --set --val 0xff --offset 0x110 + + # Reset the CPU Card PCA9547 + io_rd_wr.py --set --val 0xfd --offset 0x20b + io_rd_wr.py --set --val 0xff --offset 0x20b +} + +init_devnum + +check_iom_status() +{ + SMF_DIR="/sys/devices/platform/SMF.512/hwmon/*" + count=0 + iom_sta=0 + MAX_IOM_STARTUP_DELAY=50 + + if [ -d $SMF_DIR ]; then + iom_status=$(cat $SMF_DIR/iom_status) + cpu_iom1_sta=$(cat $SMF_DIR/cpu_iom1_control) + cpu_iom2_sta=$(cat $SMF_DIR/cpu_iom2_control) + cpu_iom3_sta=$(cat $SMF_DIR/cpu_iom3_control) + cpu_iom4_sta=$(cat $SMF_DIR/cpu_iom4_control) + cpu_iom_sta=$(( cpu_iom1_sta|cpu_iom2_sta|cpu_iom3_sta|cpu_iom4_sta )) + echo "Started polling IOM status" + while [ "$iom_status" != "f0" -o "$cpu_iom_sta" != "0" ]; + do + if [ "$count" -gt "$MAX_IOM_STARTUP_DELAY" ];then + echo "IOM is taking longer than expected to power up.Aborting. + iom_status- $iom_status cpu_iom_sta1- $cpu_iom1_sta cpu_iom_sta2- $cpu_iom2_sta + cpu_iom_sta3- $cpu_iom3_sta cpu_iom_sta4- $cpu_iom4_sta " + iom_sta=1 + break + fi + cpu_iom1_sta=$(cat $SMF_DIR/cpu_iom1_control) + cpu_iom2_sta=$(cat $SMF_DIR/cpu_iom2_control) + cpu_iom3_sta=$(cat $SMF_DIR/cpu_iom3_control) + cpu_iom4_sta=$(cat $SMF_DIR/cpu_iom4_control) + cpu_iom_sta=$(( cpu_iom1_sta|cpu_iom2_sta|cpu_iom3_sta|cpu_iom4_sta )) + iom_status=$(cat $SMF_DIR/iom_status) + sleep .1 + count=`expr $count + 1` + done + + if [ "$iom_sta" != "1" ];then + echo "All IOM's are UP" + fi + fi +} + +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" + check_iom_status + switch_board_qsfp_mux "new_device" + switch_board_sfp "new_device" + switch_board_qsfp "new_device" + switch_board_qsfp_lpmode "disable" + /usr/local/bin/s6100_bitbang_reset.sh + xcvr_presence_interrupts "enable" +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" + switch_board_qsfp_mux "delete_device" + cpu_board_mux "delete_device" +fi 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 new file mode 100755 index 000000000000..62a8c1a2812f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/s6100_platform.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +#platform init script for Dell S6100 + +install_python_api_package() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip install $device/$platform/sonic_platform-1.0-py2-none-any.whl) + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) +} + +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) + fi + + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -eq 0 ]; then + rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null) + fi +} + + +if [[ "$1" == "init" ]]; then + + pericom="/sys/bus/pci/devices/0000:08:00.0" + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe dell_ich + modprobe dell_s6100_iom_cpld + modprobe dell_s6100_lpc + modprobe nvram + systemctl start s6100-reboot-cause.service + + # Disable pericom/xilinx + echo 1 > /sys/bus/pci/devices/0000:02:00.0/remove + [ -d $pericom ] && echo 1 > $pericom/remove + + # Disable Watchdog Timer + if [[ -e /usr/local/bin/platform_watchdog_disable.sh ]]; then + /usr/local/bin/platform_watchdog_disable.sh + fi + + is_fast_warm=$(cat /proc/cmdline | grep SONIC_BOOT_TYPE | wc -l) + + if [[ "$is_fast_warm" == "1" ]]; then + systemctl start --no-block s6100-i2c-enumerate.service + else + systemctl start s6100-i2c-enumerate.service + fi + + install_python_api_package + +elif [[ "$1" == "deinit" ]]; then + /usr/local/bin/s6100_i2c_enumeration.sh deinit + + modprobe -r dell_s6100_lpc + modprobe -r dell_s6100_iom_cpld + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev + modprobe -r dell_ich + modprobe -r nvram + remove_python_api_package +else + echo "s6100_platform : Invalid option !" +fi diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/sensors new file mode 100755 index 000000000000..958cbdcb7bef --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/sensors @@ -0,0 +1,3 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/ssd-fw-upgrade b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/ssd-fw-upgrade new file mode 100755 index 000000000000..0db6b1f62c66 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/ssd-fw-upgrade @@ -0,0 +1,100 @@ +#!/bin/bash +# This script does the SSD firware upgrade +# This has been integrated as part of reboot/warm-reboot/fast-reboot script. +SKIP_UPGRADE=0 +CHECKSUM_VALUE="b9b6dbb362b7632837af9cd320c5d147" +unmount () { + exist=$(mount | grep " $1 " | wc -l) + if [ $exist -ne 0 ]; then + umount $1 + if [[ $? -ne 0 ]]; then + fuser -vm $1 + SKIP_UPGRADE=1 + fi + fi +} + +mp_tool_reboot() { + if [ ! -d /mnt/ramdisk ]; then + mkdir -p /mnt/ramdisk; + fi + mount -t tmpfs -o size=16m swap /mnt/ramdisk + cp /tmp/SSD.zip /mnt/ramdisk/ + cd /mnt/ramdisk + unzip -q SSD.zip + chmod +x SSD/mp_64 + + #stopped journal and syslog services to unmount /host + systemctl stop systemd-journald.service + systemctl stop systemd-journald.socket + systemctl stop systemd-journald-audit.socket + systemctl stop systemd-journald-dev-log.socket + systemctl stop syslog.service + systemctl stop syslog.socket + systemctl stop docker.socket + sleep 2 + unmount /var/log + loop_exist=$(losetup -a | grep loop1 | wc -l) + if [ $loop_exist -ne 0 ]; then + losetup -d /dev/loop1 + fi + unmount /boot + unmount /var/lib/docker + unmount /host + #start the services whichever we stopped for succesful /host unmount + systemctl start systemd-journald.service + systemctl start systemd-journald.socket + systemctl start systemd-journald-audit.socket + systemctl start systemd-journald-dev-log.socket + systemctl start syslog.service + systemctl start syslog.socket + if [ $SKIP_UPGRADE == 0 ]; then + echo 1 > /sys/class/scsi_device/4\:0\:0\:0/device/delete + echo "0 0 0" > /sys/class/scsi_host/host4/scan + sleep 3 + DEVICE=$(dmesg | grep "Attached SCSI disk" | sed -n \$p | + grep -o -P '(sd[a-z])') + cd /mnt/ramdisk/SSD + ./mp_64 -d /dev/${DEVICE} -c 1 -u -k -r + fi +} + +hdparm-upgrade() { + if [[ -x "$(command -v hdparm)" ]];then + hdparm --fwdownload /tmp/SSD/SYS_S.bin --yes-i-know-what-i-am-doing \ + --please-destroy-my-drive /dev/sda + fi +} + +platform_check() { + platform=$(sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + version_type=$(dmesg | grep "mSATA") + md5sum_value=$(md5sum /tmp/SSD.zip | cut -d ' ' -f1) + if [[ "$md5sum_value" != "$CHECKSUM_VALUE" || "$platform" != *"s6100"* || + "$version_type" != *"3IE3"* || "$version_type" != *"S16425c1"* ]];then + exit 1 + fi +} + +if [[ ! -f /tmp/SSD.zip ]];then + exit 1 +fi + +case "$1" in + fast-reboot|warm-reboot) + platform_check + mp_tool_reboot + ;; + reboot) + platform_check + cd /tmp + unzip -q SSD.zip + ;; + hdparm-upgrade) + $1 + ;; + *) + echo "Usage: $0 {fast-reboot|warm-reboot|reboot|hdparm-upgrade}" >&2 + exit 2 + ;; +esac diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/track_reboot_reason.sh b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/track_reboot_reason.sh new file mode 100755 index 000000000000..775c0c8d05f2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/track_reboot_reason.sh @@ -0,0 +1,197 @@ +#!/bin/bash + +reboot_dir_found=false +reboot_file_found=false +smf_dir_missing=0 +nvram_missing=0 + +REBOOT_CAUSE_FILE=/host/reboot-cause/reboot-cause.txt +REBOOT_REASON_FILE=/host/reboot-cause/platform/reboot_reason +BIOS_VERSION_FILE=/host/reboot-cause/platform/bios_minor_version +SMF_MSS_VERSION_FILE=/sys/devices/platform/SMF.512/hwmon/*/smf_firmware_ver +SMF_POWERON_REASON=/sys/devices/platform/SMF.512/hwmon/*/smf_poweron_reason +SMF_RESET_REASON=/sys/devices/platform/SMF.512/hwmon/*/smf_reset_reason +MAILBOX_POWERON_REASON=/sys/devices/platform/SMF.512/hwmon/*/mb_poweron_reason +NVRAM_DEVICE_FILE=/dev/nvram +RESET_REASON_FILE=/host/reboot-cause/platform/reset_reason +SMF_DIR=/sys/devices/platform/SMF.512/hwmon/ + +while [[ ! -d $SMF_DIR ]] +do + sleep 0.5 + let smf_dir_missing=$smf_dir_missing+1 + if [[ "$smf_dir_missing" = "5" ]]; then + echo "SMF is not initialized" + smf_dir_missing=0 + fi +done + +SMF_RESET=$(cat $SMF_RESET_REASON) + +if [[ -d /host/reboot-cause/platform ]]; then + reboot_dir_found=true + if [[ -f $REBOOT_REASON_FILE ]]; then + reboot_file_found=true + fi +fi + +SMF_FPGA_VERSION=$((16#$(io_rd_wr.py --get --offset 0x200 | cut -d " " -f 3))) +SMF_BIOS_REG=$(io_rd_wr.py --get --offset 0x203 | cut -d " " -f 3) +SMF_BIOS_REG=$((16#$SMF_BIOS_REG)) +bios_secondary_boot=$(($SMF_BIOS_REG & 1)) + +_get_smf_reset_register(){ + BIOS_VERSION=$(/usr/sbin/dmidecode -s system-version) + BIOS_VERSION_MINOR=$(echo $BIOS_VERSION | cut -d'-' -f 2) + + if [[ $BIOS_VERSION_MINOR -gt 7 ]]; then + echo $BIOS_VERSION > $BIOS_VERSION_FILE + elif [[ "$bios_secondary_boot" = "0" ]]; then + # For Primary BIOS with older version + if [[ -e $BIOS_VERSION_FILE ]]; then + rm $BIOS_VERSION_FILE + fi + fi + + if [[ -e $BIOS_VERSION_FILE ]]; then + while [[ ! -e $NVRAM_DEVICE_FILE ]] + do + sleep 1 + let nvram_missing=$nvram_missing+1 + if [[ "$nvram_missing" = "5" ]]; then + echo "NVRAM is not initialized" + nvram_missing=0 + fi + done + first_reset=$(nvram_rd_wr.py --get --offset 0x5c | cut -d " " -f 2) + second_reset=$(nvram_rd_wr.py --get --offset 0x5d | cut -d " " -f 2) + third_reset=$(nvram_rd_wr.py --get --offset 0x5e | cut -d " " -f 2) + fourth_reset=$(nvram_rd_wr.py --get --offset 0x5f | cut -d " " -f 2) + + if [[ "$first_reset" != "ee" ]]; then + SMF_RESET=$first_reset + fi + + # Saving NVRAM values for future debugging + if [[ $reboot_dir_found = true ]]; then + echo "First reset - $first_reset" > $RESET_REASON_FILE + echo "Second reset - $second_reset" >> $RESET_REASON_FILE + echo "Third reset - $third_reset" >> $RESET_REASON_FILE + echo "Fourth reset - $fourth_reset" >> $RESET_REASON_FILE + fi + logger -p user.info -t DELL_S6100_REBOOT_CAUSE "RST value in NVRAM: $first_reset, $second_reset, $third_reset, $fourth_reset" + # Clearing NVRAM values to holding next reset values + nvram_rd_wr.py --set --val 0xee --offset 0x58 + nvram_rd_wr.py --set --val 0xee --offset 0x5c + nvram_rd_wr.py --set --val 0xee --offset 0x5d + nvram_rd_wr.py --set --val 0xee --offset 0x5e + nvram_rd_wr.py --set --val 0xee --offset 0x5f + fi +} + +_is_thermal_reset() { + prev_thermal=$(cat $REBOOT_REASON_FILE) + curr_poweron_reason=$(cat $SMF_POWERON_REASON) + if [[ $curr_poweron_reason = "11" ]]; then + echo 0 + return + fi + if [[ $prev_thermal = $curr_poweron_reason ]]; then + echo 2 + return + else + echo "$curr_poweron_reason" > $REBOOT_REASON_FILE + echo 1 + return + fi + + echo 0 + return +} + +_is_watchdog_reset(){ + curr_reset_reason=$SMF_RESET + if [[ $curr_reset_reason = "33" ]]; then + echo 1 + return + fi + + echo 0 + return +} + +_is_unknown_reset(){ + if [[ -f $REBOOT_CAUSE_FILE ]]; then + if [[ $1 = 0 ]]; then + echo "Unknown software reboot" > $REBOOT_CAUSE_FILE + return + fi + curr_poweron_reason=$(cat $SMF_POWERON_REASON) + curr_reset_reason=$SMF_RESET + mb_poweron_reason=$(cat $MAILBOX_POWERON_REASON) + echo "Unknown POR: $curr_poweron_reason RST: $curr_reset_reason MBR: $mb_poweron_reason" > $REBOOT_CAUSE_FILE + fi + +} + +update_mailbox_register(){ + if [[ "$bios_secondary_boot" = "1" ]]; then + echo "Secondary BIOS booted" + fi + + if [[ $reboot_file_found = false ]]; then + echo "None" > $REBOOT_REASON_FILE + fi + + _get_smf_reset_register + if [[ -d /sys/devices/platform/SMF.512/hwmon/ ]]; then + por=$(cat $SMF_POWERON_REASON) + rst=$(cat $SMF_RESET_REASON) + mbr=$(cat $MAILBOX_POWERON_REASON) + reason=$(echo $mbr | cut -d 'x' -f2) + logger -p user.info -t DELL_S6100_REBOOT_CAUSE "POR: $por, RST: $rst, MBR: $mbr" + + SMF_MSS_VERSION=$(cat $SMF_MSS_VERSION_FILE) + SMF_MSS_VERSION_MAJOR=$(echo $SMF_MSS_VERSION | cut -d '.' -f1) + SMF_MSS_VERSION_MINOR=$(echo $SMF_MSS_VERSION | cut -d '.' -f2) + SMF_FPGA_VERSION_MAJOR=$(( (SMF_FPGA_VERSION & 0xF0) >> 4 )) + SMF_FPGA_VERSION_MINOR=$(( SMF_FPGA_VERSION & 0x0F )) + + if [[ -e $BIOS_VERSION_FILE ]] \ + && [[ $SMF_MSS_VERSION_MAJOR -ge 2 ]] && [[ $SMF_MSS_VERSION_MINOR -ge 7 ]] \ + && [[ $SMF_FPGA_VERSION_MAJOR -ge 1 ]] && [[ $SMF_FPGA_VERSION_MINOR -ge 4 ]]; then + + if [[ $reason = "cc" ]]; then + echo 0xaa > $MAILBOX_POWERON_REASON + elif [[ $SMF_RESET = "11" ]]; then + echo 0xee > $MAILBOX_POWERON_REASON + elif [[ $SMF_RESET = "33" ]]; then + echo 0xdd > $MAILBOX_POWERON_REASON + else + echo "Unknown software reboot" > $REBOOT_CAUSE_FILE + echo 0x99 > $MAILBOX_POWERON_REASON + fi + + else + is_thermal_reboot=$(_is_thermal_reset) + + is_wd_reboot=$(_is_watchdog_reset) + + if [[ $reason = "ff" ]]; then + echo "None" > $REBOOT_REASON_FILE + echo 0xbb > $MAILBOX_POWERON_REASON + elif [[ $is_thermal_reboot = 1 ]]; then + echo 0xee > $MAILBOX_POWERON_REASON + elif [[ $is_wd_reboot = 1 ]] && [[ $reason != "cc" ]]; then + echo 0xdd > $MAILBOX_POWERON_REASON + elif [[ $reason = "cc" ]]; then + echo 0xaa > $MAILBOX_POWERON_REASON + else + _is_unknown_reset $is_thermal_reboot + echo 0x99 > $MAILBOX_POWERON_REASON + fi + fi + fi +} + +update_mailbox_register diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/warm-reboot_plugin b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/warm-reboot_plugin new file mode 120000 index 000000000000..180742bbc4d5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/scripts/warm-reboot_plugin @@ -0,0 +1 @@ +fast-reboot_plugin \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/setup.py b/platform/broadcom/sonic-platform-modules-dell/s6100/setup.py new file mode 100755 index 000000000000..d031762fbeb8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/setup.py @@ -0,0 +1,31 @@ +from setuptools import setup + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on DellEmc Platforms', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + maintainer='DellEMC', + maintainer_email='dell-sonic@dell.com', + packages=[ + 'sonic_platform', + ], + 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', + 'Programming Language :: Python :: 3.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/__init__.py new file mode 100755 index 000000000000..2764c0c33007 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis", "module", "fan", "fan_drawer", "psu", "sfp", "thermal"] +from sonic_platform import * + 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 new file mode 100755 index 000000000000..4527f6947321 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py @@ -0,0 +1,411 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC S6100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.psu import Psu + from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.module import Module + from sonic_platform.thermal import Thermal + from sonic_platform.component import Component + from sonic_platform.watchdog import Watchdog + from sonic_platform.eeprom import Eeprom + import time +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MAX_S6100_MODULE = 4 +MAX_S6100_FANTRAY = 4 +MAX_S6100_PSU = 2 +MAX_S6100_THERMAL = 10 +MAX_S6100_COMPONENT = 3 + + +class Chassis(ChassisBase): + """ + DELLEMC Platform-specific Chassis class + """ + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + POLL_INTERVAL = 1 # Poll interval in seconds + + reset_reason_dict = {} + reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS + reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG + reset_reason_dict[44] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE + reset_reason_dict[55] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE + reset_reason_dict[66] = ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER + reset_reason_dict[77] = ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER + + power_reason_dict = {} + power_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS + power_reason_dict[22] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU + power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC + power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED + + status_led_reg_to_color = { + 0x00: 'green', 0x01: 'blinking green', 0x02: 'amber', + 0x04: 'amber', 0x08: 'blinking amber', 0x10: 'blinking amber' + } + + color_to_status_led_reg = { + 'green': 0x00, 'blinking green': 0x01, + 'amber': 0x02, 'blinking amber': 0x08 + } + + def __init__(self): + + ChassisBase.__init__(self) + self.status_led_reg = "sys_status_led" + self.supported_led_color = ['green', 'blinking green', 'amber', 'blinking amber'] + # Initialize 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_FANTRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + for i in range(MAX_S6100_PSU): + psu = Psu(i) + self._psu_list.append(psu) + + for i in range(MAX_S6100_THERMAL): + thermal = Thermal(i) + self._thermal_list.append(thermal) + + for i in range(MAX_S6100_COMPONENT): + component = Component(i) + self._component_list.append(component) + + self._watchdog = Watchdog() + self._transceiver_presence = self._get_transceiver_presence() + + def _get_reboot_reason_smf_register(self): + # In S6100, mb_poweron_reason register will + # Returns 0xaa or 0xcc on software reload + # Returns 0xff or 0xbb on power-cycle + # Returns 0xdd on Watchdog + # Returns 0xee on Thermal Shutdown + # Returns 0x99 on Unknown reset + smf_mb_reg_reason = self._get_pmc_register('mb_poweron_reason') + return int(smf_mb_reg_reason, 16) + + def _get_pmc_register(self, reg_name): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR + '/' + reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _set_pmc_register(self, reg_name, value): + # On successful write, returns the length of value written on + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR + '/' + reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + + try: + with open(mb_reg_file, 'w') as fd: + rv = fd.write(str(value)) + except IOError: + rv = 'ERR' + + return rv + + def _get_register(self, reg_file): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(reg_file)): + return rv + + try: + with open(reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether Chassis is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_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. + """ + + reset_reason = int(self._get_pmc_register('smf_reset_reason')) + power_reason = int(self._get_pmc_register('smf_poweron_reason')) + smf_mb_reg_reason = self._get_reboot_reason_smf_register() + + if ((smf_mb_reg_reason == 0xbb) or (smf_mb_reg_reason == 0xff)): + return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None) + elif ((smf_mb_reg_reason == 0xaa) or (smf_mb_reg_reason == 0xcc)): + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) + elif (smf_mb_reg_reason == 0xdd): + return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None) + elif (smf_mb_reg_reason == 0xee): + return (self.power_reason_dict[power_reason], None) + elif (reset_reason == 66): + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, + "Emulated Cold Reset") + elif (reset_reason == 77): + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, + "Emulated Warm Reset") + else: + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) + + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason") + + def _get_transceiver_presence(self): + + cpld2_modprs = self._get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_modprs") + cpld3_modprs = self._get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_modprs") + cpld4_modprs = self._get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_modprs") + cpld5_modprs = self._get_register( + "/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_modprs") + + # If IOM is not present, register read will fail. + # Handle the scenario gracefully + if (cpld2_modprs == 'read error') or (cpld2_modprs == 'ERR'): + cpld2_modprs = '0x0' + if (cpld3_modprs == 'read error') or (cpld3_modprs == 'ERR'): + cpld3_modprs = '0x0' + if (cpld4_modprs == 'read error') or (cpld4_modprs == 'ERR'): + cpld4_modprs = '0x0' + if (cpld5_modprs == 'read error') or (cpld5_modprs == 'ERR'): + cpld5_modprs = '0x0' + + # Make it contiguous + transceiver_presence = (int(cpld2_modprs, 16) & 0xffff) |\ + ((int(cpld4_modprs, 16) & 0xffff) << 16) |\ + ((int(cpld3_modprs, 16) & 0xffff) << 32) |\ + ((int(cpld5_modprs, 16) & 0xffff) << 48) + + return transceiver_presence + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the + format of {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + port_dict = {} + ret_dict = {'sfp': port_dict} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + return False, ret_dict # Incorrect timeout + + while True: + if forever: + timer = self.POLL_INTERVAL + else: + timer = min(timeout, self.POLL_INTERVAL) + start_time = time.time() + + time.sleep(timer) + cur_presence = self._get_transceiver_presence() + + # Update dict only if a change has been detected + if cur_presence != self._transceiver_presence: + changed_ports = self._transceiver_presence ^ cur_presence + for port in range(self.get_num_sfps()): + # Mask off the bit corresponding to particular port + mask = 1 << port + if changed_ports & mask: + # qsfp_modprs 1 => optics is removed + if cur_presence & mask: + port_dict[port] = '0' + # qsfp_modprs 0 => optics is inserted + else: + port_dict[port] = '1' + + # Update current presence + self._transceiver_presence = cur_presence + break + + if not forever: + elapsed_time = time.time() - start_time + timeout = round(timeout - elapsed_time, 3) + if timeout <= 0: + break + + return True, ret_dict + + def initizalize_system_led(self): + return True + + def set_status_led(self, color): + """ + Sets the state of the system LED + + Args: + color: A string representing the color with which to set the + system LED + + Returns: + bool: True if system LED state is set successfully, False if not + """ + if color not in self.supported_led_color: + return False + + value = self.color_to_status_led_reg[color] + rv = self._set_pmc_register(self.status_led_reg, value) + if (rv != 'ERR'): + return True + else: + return False + + def get_status_led(self): + """ + Gets the state of the system LED + + Returns: + A string, one of the valid LED color strings which could be + vendor specified. + """ + reg_val = self._get_pmc_register(self.status_led_reg) + if (reg_val != 'ERR'): + return self.status_led_reg_to_color.get(int(reg_val, 16), None) + else: + return None diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/component.py new file mode 100644 index 000000000000..bea180d440b5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/component.py @@ -0,0 +1,233 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC S6100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + import subprocess + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version" + + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["CPLD", "Used for managing IO modules, SFP+ modules and system LEDs"], + ["FPGA", ("Platform management controller for on-board temperature " + "monitoring, in-chassis power, Fan and LED control")] + ] + MODULE_COMPONENT = [ + "IOM{}-CPLD", + "Used for managing QSFP+ modules ({0}-{1})" + ] + + def __init__(self, component_index=0, + is_module=False, iom_index=0, i2c_line=0, dependency=None): + + self.is_module_component = is_module + self.dependency = dependency + + if self.is_module_component: + self.index = iom_index + self.name = self.MODULE_COMPONENT[0].format(self.index) + self.description = self.MODULE_COMPONENT[1].format( + ((self.index - 1) * 16) + 1, self.index * 16) + self.cpld_version_file = ("/sys/class/i2c-adapter/i2c-{0}/{0}-003e" + "/iom_cpld_vers").format(i2c_line) + else: + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + + def _read_sysfs_file(self, sysfs_file): + # On successful read, returns the value read from given + # sysfs_file and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(sysfs_file)): + return rv + + try: + with open(sysfs_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.decode('utf-8').rstrip('\n') + except OSError: + result = None + + return result + + def _get_cpld_version(self): + io_resource = "/dev/port" + CPLD_VERSION_ADDR = 0x100 + + fd = os.open(io_resource, os.O_RDONLY) + if (fd < 0): + return 'NA' + + if (os.lseek(fd, CPLD_VERSION_ADDR, os.SEEK_SET) != CPLD_VERSION_ADDR): + os.close(fd) + return 'NA' + + buf = os.read(fd, 1) + cpld_version = str(ord(buf)) + os.close(fd) + + return cpld_version + + def _get_iom_cpld_version(self): + ver_str = self._read_sysfs_file(self.cpld_version_file) + if (ver_str != 'ERR'): + if ver_str == 'read error': + return 'NA' + + ver_str = ver_str.rstrip('\r\n') + cpld_version = str(int(ver_str.split(':')[1], 16)) + return cpld_version + else: + return 'NA' + + def _get_fpga_version(self): + fpga_ver_file = self.MAILBOX_DIR + '/smf_firmware_ver' + fpga_ver = self._read_sysfs_file(fpga_ver_file) + if (fpga_ver != 'ERR'): + return fpga_ver + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return self.name + + def get_model(self): + """ + Retrieves the part number of the component + Returns: + string: Part number of component + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the component + Returns: + string: Serial number of component + """ + return 'NA' + + def get_presence(self): + """ + Retrieves the presence of the component + Returns: + bool: True if present, False if not + """ + if self.is_module_component: + return self.dependency.get_presence() + else: + return True + + def get_status(self): + """ + Retrieves the operational status of the component + Returns: + bool: True if component is operating properly, False if not + """ + if self.is_module_component: + return self.dependency.get_status() + else: + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether component is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + if self.is_module_component: # IOM CPLD + return self._get_iom_cpld_version() + else: + if self.index == 0: # BIOS + bios_ver = self._get_command_result(BIOS_QUERY_VERSION_COMMAND) + + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index == 1: # SwitchCard CPLD + return self._get_cpld_version() + elif self.index == 2: # FPGA + return self._get_fpga_version() + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + return False 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 new file mode 100644 index 000000000000..288c1a2ccfcf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/eeprom.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python + +############################################################################# +# DellEmc S6100 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + 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: + if self.is_module: + self.write_eeprom(b"\x00\x00") + self.eeprom_data = self.read_eeprom_bytes(256) + else: + self.eeprom_data = self.read_eeprom() + except: + if not self.is_module: + try: + self.eeprom_data = self.read_eeprom() + except: + raise RuntimeError("Eeprom is not Programmed") + else: + self.eeprom_data = "N/A" + else: + eeprom = self.eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % tlv[0] + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += tlv[6:6 + tlv[1]].decode('ascii') + else: + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + if self.is_module: + # In S6100, individual modules doesn't have MAC address + mac_code = "0x%02X" % self._TLV_CODE_MAC_BASE + self.eeprom_tlv_dict[mac_code] = '00:00:00:00:00:00' + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def base_mac_addr(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or results[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join(["{:02x}".format(T) for T in results[2]]).upper() + + def modelstr(self): + 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" + + return results[2].decode('ascii') + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict 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 new file mode 100644 index 000000000000..5b3c8977ac0a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S6100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fans' information which are available in the platform. +# +######################################################################## + +import os.path + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MAX_S6100_PSU_FAN_SPEED = 18000 +MAX_S6100_FAN_SPEED = 16000 + + +class Fan(FanBase): + """DellEMC Platform-specific Fan class""" + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + def __init__(self, fantray_index=1, psu_index=1, psu_fan=False, dependency=None): + self.is_psu_fan = psu_fan + if not self.is_psu_fan: + self.fantrayindex = fantray_index + self.dependency = dependency + 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( + 2 * self.fantrayindex - 1) + self.max_fan_speed = MAX_S6100_FAN_SPEED + else: + self.psuindex = psu_index + self.fan_presence_reg = "fan{}_fault".format(self.psuindex + 10) + self.get_fan_speed_reg = "fan{}_input".format(self.psuindex + 10) + self.get_fan_dir_reg = "fan{}_airflow".format(self.psuindex + 10) + self.max_fan_speed = MAX_S6100_PSU_FAN_SPEED + + def _get_pmc_register(self, reg_name): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the fan name + Returns: + string: The name of the device + """ + if not self.is_psu_fan: + return "FanTray{}-Fan1".format(self.fantrayindex) + else: + return "PSU{} Fan".format(self.psuindex) + + def get_model(self): + """ + Retrieves the part number of the FAN + Returns: + string: Part number of FAN + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the FAN + Returns: + string: Serial number of FAN + """ + return 'NA' + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if fan is present, False if not + """ + if not self.is_psu_fan: + return self.dependency.get_presence() + + presence = False + fan_presence = self._get_pmc_register(self.fan_presence_reg) + if (fan_presence != 'ERR'): + fan_presence = int(fan_presence, 10) + if (~fan_presence & 0b1): + presence = True + + return presence + + def get_status(self): + """ + Retrieves the operational status of the FAN + Returns: + bool: True if FAN is operating properly, False if not + """ + status = False + 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 + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return 1 + + def is_replaceable(self): + """ + Indicate whether Fan is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def get_direction(self): + """ + Retrieves the fan airflow direction + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + In DellEMC platforms, + - Forward/Exhaust : Air flows from Port side to Fan side. + - Reverse/Intake : Air flows from Fan side to Port side. + """ + direction = [self.FAN_DIRECTION_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 self.FAN_DIRECTION_NOT_APPLICABLE + return direction[fan_direction] + + def get_speed(self): + """ + Retrieves the speed of fan + Returns: + int: percentage of the max fan speed + """ + fan_speed = self._get_pmc_register(self.get_fan_speed_reg) + if (fan_speed != 'ERR') and self.get_presence(): + speed_in_rpm = int(fan_speed, 10) + speed = (100 * speed_in_rpm)//self.max_fan_speed + else: + speed = 0 + + return speed + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + if self.get_presence(): + # The tolerance value is fixed as 20% for all the DellEmc platform + tolerance = 20 + else: + tolerance = 0 + + return tolerance + + def set_speed(self, speed): + """ + Set fan speed to expected value + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + bool: True if set success, False if fail. + """ + # Fan speeds are controlled by Smart-fussion FPGA. + return False + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if set success, False if fail. + """ + # No LED available for FanTray and PSU Fan + # Return True to avoid thermalctld alarm. + return True + + def get_status_led(self): + """ + Gets the state of the Fan status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + # No LED available for FanTray and PSU Fan + return None + + 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) + """ + # Fan speeds are controlled by Smart-fussion FPGA. + # Return current speed to avoid false thermalctld alarm. + return self.get_speed() diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..41e870a63971 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan_drawer.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S6100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + import os + + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanDrawer(FanDrawerBase): + """DellEMC Platform-specific Fan Drawer class""" + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + def __init__(self, fantray_index): + FanDrawerBase.__init__(self) + # FanTray is 1-based in DellEMC platforms + self.index = fantray_index + 1 + self.presence_reg = "fan{}_fault".format(2 * self.index - 1) + self.serialno_reg = "fan{}_serialno".format(2 * self.index - 1) + + self._fan_list.append(Fan(self.index, dependency=self)) + + def _get_pmc_register(self, reg_name): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.index) + + def get_model(self): + """ + Retrieves the part number of Fandrawer + Returns: + string: Part number of Fandrawer + """ + # For Serial number "US-01234D-54321-25A-0123-A00", the part + # number is "01234D" + fantray_serialno = self._get_pmc_register(self.serialno_reg) + if (fantray_serialno != 'ERR') and self.get_presence(): + if (len(fantray_serialno.split('-')) > 1): + fantray_partno = fantray_serialno.split('-')[1] + else: + fantray_partno = 'NA' + else: + fantray_partno = 'NA' + + return fantray_partno + + def get_serial(self): + """ + Retrieves the serial number of Fandrawer + Returns: + string: Serial number of Fandrawer + """ + # Sample Serial number format "US-01234D-54321-25A-0123-A00" + fantray_serialno = self._get_pmc_register(self.serialno_reg) + if (fantray_serialno == 'ERR') or not self.get_presence(): + fantray_serialno = 'NA' + + return fantray_serialno + + def get_presence(self): + """ + Retrieves the presence of the Fandrawer + Returns: + bool: True if fan is present, False if not + """ + presence = False + fantray_presence = self._get_pmc_register(self.presence_reg) + if (fantray_presence != 'ERR'): + fantray_presence = int(fantray_presence, 10) + if (~fantray_presence & 0b1): + presence = True + + return presence + + def get_status(self): + """ + Retrieves the operational status of the Fandrawer + + Returns: + bool: True if Fandrawer is operating properly, False if not + """ + return self.get_fan(0).get_status() + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this Fandrawer is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if set success, False if fail. + """ + # Leds are controlled by Smart-fussion FPGA. + # Return True to avoid thermalctld alarm. + return True + + def get_status_led(self): + """ + Gets the state of the Fan status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + if self.get_presence(): + if self.get_fan(0).get_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_AMBER + else: + return self.STATUS_LED_COLOR_OFF 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 new file mode 100644 index 000000000000..923bb5c0550a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S6100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Modules' information which are available in the platform +# +######################################################################## + + +try: + import os + 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") + + +class Module(ModuleBase): + """DellEMC Platform-specific Module class""" + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + IOM_I2C_MAPPING = { 1: 14, 2: 16, 3: 15, 4: 17 } + EEPROM_I2C_MAPPING = { + # IOM 1 + 0: [6, 66], 1: [6, 67], 2: [6, 68], 3: [6, 69], + 4: [6, 70], 5: [6, 71], 6: [6, 72], 7: [6, 73], + 8: [6, 74], 9: [6, 75], 10: [6, 76], 11: [6, 77], + 12: [6, 78], 13: [6, 79], 14: [6, 80], 15: [6, 81], + # IOM 2 + 16: [8, 34], 17: [8, 35], 18: [8, 36], 19: [8, 37], + 20: [8, 38], 21: [8, 39], 22: [8, 40], 23: [8, 41], + 24: [8, 42], 25: [8, 43], 26: [8, 44], 27: [8, 45], + 28: [8, 46], 29: [8, 47], 30: [8, 48], 31: [8, 49], + # IOM 3 + 32: [7, 50], 33: [7, 51], 34: [7, 52], 35: [7, 53], + 36: [7, 54], 37: [7, 55], 38: [7, 56], 39: [7, 57], + 40: [7, 58], 41: [7, 59], 42: [7, 60], 43: [7, 61], + 44: [7, 62], 45: [7, 63], 46: [7, 64], 47: [7, 65], + # IOM 4 + 48: [9, 18], 49: [9, 19], 50: [9, 20], 51: [9, 21], + 52: [9, 22], 53: [9, 23], 54: [9, 24], 55: [9, 25], + 56: [9, 26], 57: [9, 27], 58: [9, 28], 59: [9, 29], + 60: [9, 30], 61: [9, 31], 62: [9, 32], 63: [9, 33] + } + + def __init__(self, module_index): + ModuleBase.__init__(self) + # Modules are 1-based in DellEMC platforms + self.index = module_index + 1 + 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 = Eeprom(iom_eeprom=True, i2c_line=self.port_i2c_line) + + self.iom_status_reg = "iom_status" + self.iom_presence_reg = "iom_presence" + + component = Component(is_module=True, iom_index=self.index, + i2c_line=self.port_i2c_line, dependency=self) + self._component_list.append(component) + + eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom" + sfp_ctrl_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/" + + # sfp.py will read eeprom contents and retrive the eeprom data. + # It will also provide support sfp controls like reset and setting + # low power mode. + for index in range(self.port_start, self.port_end + 1): + eeprom_path = eeprom_base.format(self.EEPROM_I2C_MAPPING[index][0], + self.EEPROM_I2C_MAPPING[index][1]) + sfp_control = sfp_ctrl_base.format(self.port_i2c_line) + sfp_node = Sfp(index, 'QSFP', eeprom_path, sfp_control, index) + self._sfp_list.append(sfp_node) + + def _get_pmc_register(self, reg_name): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR + '/' + reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "IOM{}: {}".format(self.index, self._eeprom.modelstr()) + + def get_presence(self): + """ + Retrieves the presence of the Module + + Returns: + bool: True if Module is present, False if not + """ + status = False + iom_presence = self._get_pmc_register(self.iom_presence_reg) + if (iom_presence != 'ERR'): + iom_presence = int(iom_presence,16) + if (~iom_presence & (1 << (self.index - 1))): + status = True + + return status + + def get_model(self): + """ + Retrieves the part number of the module + + Returns: + string: part number of module + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the module + + Returns: + string: Serial number of module + """ + return self._eeprom.serial_str() + + def get_status(self): + """ + Retrieves the operational status of the Module + + Returns: + bool: True if Module is operating properly, False if not + """ + status = False + iom_status = self._get_pmc_register(self.iom_status_reg) + if (iom_status != 'ERR'): + iom_status = int(iom_status,16) + if (~iom_status & (1 << (self.index - 1))): + status = True + + return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether Module is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the module + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + # In S6100, individual modules doesn't have MAC address + return '00:00:00:00:00:00' + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the module + + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + Ex. { ‘0x21’:’AG9064’, ‘0x22’:’V1.0’, ‘0x23’:’AG9064-0109867821’, + ‘0x24’:’001c0f000fcd0a’, ‘0x25’:’02/03/2018 16:22:00’, + ‘0x26’:’01’, ‘0x27’:’REV01’, ‘0x28’:’AG9064-C2358-16G’} + """ + return self._eeprom.system_eeprom_info() diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/platform.py new file mode 100755 index 000000000000..32230d9c92ce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/platform.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """ + DELLEMC Platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/psu.py new file mode 100644 index 000000000000..4e528b679e4a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/psu.py @@ -0,0 +1,320 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S6100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + + +try: + import os + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Psu(PsuBase): + """DellEMC Platform-specific PSU class""" + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + def __init__(self, psu_index): + PsuBase.__init__(self) + # PSU is 1-based in DellEMC platforms + self.index = psu_index + 1 + self.psu_presence_reg = "psu{}_presence".format(self.index) + self.psu_serialno_reg = "psu{}_serialno".format(self.index) + if self.index == 1: + self.psu_voltage_reg = "in30_input" + self.psu_current_reg = "curr602_input" + self.psu_power_reg = "power2_input" + self.psu_temperature_reg = "temp14_input" + elif self.index == 2: + self.psu_voltage_reg = "in32_input" + self.psu_current_reg = "curr702_input" + self.psu_power_reg = "power4_input" + self.psu_temperature_reg = "temp15_input" + + # Passing True to specify it is a PSU fan + psu_fan = Fan(psu_index=self.index, psu_fan=True) + self._fan_list.append(psu_fan) + + def _get_pmc_register(self, reg_name): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR + '/' + reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + status = False + psu_presence = self._get_pmc_register(self.psu_presence_reg) + if (psu_presence != 'ERR'): + psu_presence = int(psu_presence, 16) + # Checking whether bit 0 is not set + if (~psu_presence & 0b1): + status = True + + return status + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + # For Serial number "US-01234D-54321-25A-0123-A00", the part + # number is "01234D" + psu_serialno = self._get_pmc_register(self.psu_serialno_reg) + if (psu_serialno != 'ERR') and self.get_presence(): + if (len(psu_serialno.split('-')) > 1): + psu_partno = psu_serialno.split('-')[1] + else: + psu_partno = 'NA' + else: + psu_partno = 'NA' + + return psu_partno + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + # Sample Serial number format "US-01234D-54321-25A-0123-A00" + psu_serialno = self._get_pmc_register(self.psu_serialno_reg) + if (psu_serialno == 'ERR') or not self.get_presence(): + psu_serialno = 'NA' + + return psu_serialno + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + status = False + psu_status = self._get_pmc_register(self.psu_presence_reg) + if (psu_status != 'ERR'): + psu_status = int(psu_status, 16) + # Checking whether both bit 3 and bit 2 are not set + if (~psu_status & 0b1000) and (~psu_status & 0b0100): + status = True + + return status + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + psu_voltage = self._get_pmc_register(self.psu_voltage_reg) + if (psu_voltage != 'ERR') and self.get_presence(): + # Converting the value returned by driver which is in + # millivolts to volts + psu_voltage = float(psu_voltage) / 1000 + else: + psu_voltage = 0.0 + + return psu_voltage + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + psu_current = self._get_pmc_register(self.psu_current_reg) + if (psu_current != 'ERR') and self.get_presence(): + # Converting the value returned by driver which is in + # milliamperes to amperes + psu_current = float(psu_current) / 1000 + else: + psu_current = 0.0 + + return psu_current + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + psu_power = self._get_pmc_register(self.psu_power_reg) + if (psu_power != 'ERR') and self.get_presence(): + # Converting the value returned by driver which is in + # microwatts to watts + psu_power = float(psu_power) / 1000000 + else: + psu_power = 0.0 + + return psu_power + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + status = False + if self.get_status() and self._fan_list[0].get_status(): + status = True + + return status + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if + not + """ + # In S6100, SmartFusion FPGA controls the PSU LED and the PSU + # LED state cannot be changed from CPU. + return False + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this PSU is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + temperature = 0.0 + if self.get_presence(): + psu_temperature = self._get_pmc_register(self.psu_temperature_reg) + if (psu_temperature != 'ERR'): + temperature = float(psu_temperature) / 1000 + + return temperature + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + + Returns: + A float number, the high threshold temperature of PSU in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + return 90.0 + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + voltage_high_threshold = 0.0 + if self.get_presence(): + psu_type = self._get_pmc_register(self.psu_presence_reg) + if (psu_type != 'ERR'): + psu_type = int(psu_type, 16) + if (psu_type & 0b10): + voltage_high_threshold = 12.6 + else: + voltage_high_threshold = 12.8 + + return voltage_high_threshold + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + voltage_low_threshold = 0.0 + if self.get_presence(): + psu_type = self._get_pmc_register(self.psu_presence_reg) + if (psu_type != 'ERR'): + psu_type = int(psu_type, 16) + if (psu_type & 0b10): + voltage_low_threshold = 11.4 + else: + voltage_low_threshold = 11.6 + + return voltage_low_threshold diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/sfp.py new file mode 100755 index 000000000000..0b242ab74d71 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/sfp.py @@ -0,0 +1,909 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import re + import struct + import time + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +PAGE_OFFSET = 0 +KEY_OFFSET = 1 +KEY_WIDTH = 2 +FUNC_NAME = 3 + +INFO_OFFSET = 128 +DOM_OFFSET = 0 +DOM_OFFSET1 = 384 + +QSFP_CONTROL_OFFSET = 86 +QSFP_POWEROVERRIDE_OFFSET = 93 + +cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', + 'Length OM1(m)', 'Length Cable Assembly(m)') + +compliance_code_tup = ( + '10/40G Ethernet Compliance Code', + 'SONET Compliance codes', + 'SAS/SATA compliance codes', + 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', + 'Fibre Channel Speed') + +info_dict_keys = ['type', 'hardware_rev', 'serial', + 'manufacturer', 'model', 'connector', + 'encoding', 'ext_identifier', 'ext_rateselect_compliance', + 'cable_type', 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', 'vendor_oui', + 'application_advertisement'] + +dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', + 'power_lpmode', 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', 'rx1power', + 'rx2power', 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', 'tx3bias', + 'tx4bias', 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + +threshold_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning'] + +sff8436_parser = { + 'reset_status': [DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'], + 'rx_los': [DOM_OFFSET, 3, 1, 'parse_dom_tx_rx_los'], + 'tx_fault': [DOM_OFFSET, 4, 1, 'parse_dom_tx_fault'], + 'tx_disable': [DOM_OFFSET, 86, 1, 'parse_dom_tx_disable'], + 'power_lpmode': [DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'power_override': [DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'Temperature': [DOM_OFFSET, 22, 2, 'parse_temperature'], + 'Voltage': [DOM_OFFSET, 26, 2, 'parse_voltage'], + 'ChannelMonitor': [DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'], + + 'cable_type': [INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'encoding': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_identifier': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'specification_compliance': + [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'manufacturer': [INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [INFO_OFFSET, 56, 2, 'parse_vendor_rev'], + 'serial': [INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'ModuleThreshold': [DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'], + 'ChannelThreshold': [DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'], +} + + +class Sfp(SfpBase): + """ + DELLEMC Platform-specific Sfp class + """ + + def __init__(self, index, sfp_type, eeprom_path, + sfp_control, sfp_ctrl_idx): + SfpBase.__init__(self) + self.sfp_type = sfp_type + self.index = index + 1 + self.eeprom_path = eeprom_path + self.sfp_control = sfp_control + self.sfp_ctrl_idx = sfp_ctrl_idx + self.sfpInfo = sff8436InterfaceId() + self.sfpDomInfo = sff8436Dom() + + def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes): + eeprom_raw = [] + try: + eeprom = open(eeprom_path, mode="rb", buffering=0) + except IOError: + return None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom.seek(offset) + raw = eeprom.read(num_bytes) + except IOError: + eeprom.close() + return None + + raw = bytearray(raw) + try: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + except BaseException: + eeprom.close() + return None + + eeprom.close() + return eeprom_raw + + def _get_eeprom_data(self, eeprom_key): + eeprom_data = None + page_offset = None + + if (self.sfpInfo is None): + return None + + page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8436_parser[eeprom_key][PAGE_OFFSET] + + sff8436_parser[eeprom_key][KEY_OFFSET]), + sff8436_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 128 is used to retrieve sff8436InterfaceId Info + # Offset 0 is used to retrieve sff8436Dom Info + if (page_offset == 128): + eeprom_data = getattr( + self.sfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + eeprom_data = getattr( + self.sfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + + return eeprom_data + + def _strip_unit_from_str(self, value_str): + match = re.match(r'(.*)C$|(.*)Volts$|(.*)mA$|(.*)dBm$', value_str) + if match: + for value in match.groups(): + if value is not None: + return float(value) + + return None + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + """ + transceiver_info_dict = {} + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A') + + # BaseInformation + iface_data = self._get_eeprom_data('type') + if (iface_data is not None): + connector = iface_data['data']['Connector']['value'] + encoding = iface_data['data']['EncodingCodes']['value'] + ext_id = iface_data['data']['Extended Identifier']['value'] + rate_identifier = iface_data['data']['RateIdentifier']['value'] + identifier = iface_data['data']['type']['value'] + bit_rate = str( + iface_data['data']['Nominal Bit Rate(100Mbs)']['value']) + + for key in compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + else: + return transceiver_info_dict + + # Vendor Date + vendor_date_data = self._get_eeprom_data('vendor_date') + if (vendor_date_data is not None): + vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + else: + return transceiver_info_dict + + # Vendor Name + vendor_name_data = self._get_eeprom_data('manufacturer') + if (vendor_name_data is not None): + vendor_name = vendor_name_data['data']['Vendor Name']['value'] + else: + return transceiver_info_dict + + # Vendor OUI + vendor_oui_data = self._get_eeprom_data('vendor_oui') + if (vendor_oui_data is not None): + vendor_oui = vendor_oui_data['data']['Vendor OUI']['value'] + else: + return transceiver_info_dict + + # Vendor PN + vendor_pn_data = self._get_eeprom_data('model') + if (vendor_pn_data is not None): + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + else: + return transceiver_info_dict + + # Vendor Revision + vendor_rev_data = self._get_eeprom_data('hardware_rev') + if (vendor_rev_data is not None): + vendor_rev = vendor_rev_data['data']['Vendor Rev']['value'] + else: + return transceiver_info_dict + + # Vendor Serial Number + vendor_sn_data = self._get_eeprom_data('serial') + if (vendor_sn_data is not None): + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + else: + return transceiver_info_dict + + # Fill The Dictionary and return + transceiver_info_dict['type'] = identifier + transceiver_info_dict['hardware_rev'] = vendor_rev + transceiver_info_dict['serial'] = vendor_sn + transceiver_info_dict['manufacturer'] = vendor_name + transceiver_info_dict['model'] = vendor_pn + transceiver_info_dict['connector'] = connector + transceiver_info_dict['encoding'] = encoding + transceiver_info_dict['ext_identifier'] = ext_id + transceiver_info_dict['ext_rateselect_compliance'] = rate_identifier + transceiver_info_dict['cable_type'] = cable_type + transceiver_info_dict['cable_length'] = cable_length + transceiver_info_dict['nominal_bit_rate'] = bit_rate + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + transceiver_info_dict['vendor_date'] = vendor_date + transceiver_info_dict['vendor_oui'] = vendor_oui + + return transceiver_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + """ + transceiver_dom_threshold_dict = {} + transceiver_dom_threshold_dict = dict.fromkeys( + threshold_dict_keys, 'N/A') + + # Module Threshold + module_threshold_data = self._get_eeprom_data('ModuleThreshold') + if (module_threshold_data is not None): + tempHighAlarm = module_threshold_data['data']['TempHighAlarm']['value'] + tempLowAlarm = module_threshold_data['data']['TempLowAlarm']['value'] + tempHighWarn = module_threshold_data['data']['TempHighWarning']['value'] + tempLowWarn = module_threshold_data['data']['TempLowWarning']['value'] + vccHighAlarm = module_threshold_data['data']['VccHighAlarm']['value'] + vccLowAlarm = module_threshold_data['data']['VccLowAlarm']['value'] + vccHighWarn = module_threshold_data['data']['VccHighWarning']['value'] + vccLowWarn = module_threshold_data['data']['VccLowWarning']['value'] + else: + return transceiver_dom_threshold_dict + + # Channel Threshold + channel_threshold_data = self._get_eeprom_data('ChannelThreshold') + if (channel_threshold_data is not None): + rxPowerHighAlarm = channel_threshold_data['data']['RxPowerHighAlarm']['value'] + rxPowerLowAlarm = channel_threshold_data['data']['RxPowerLowAlarm']['value'] + rxPowerHighWarn = channel_threshold_data['data']['RxPowerHighWarning']['value'] + rxPowerLowWarn = channel_threshold_data['data']['RxPowerLowWarning']['value'] + txBiasHighAlarm = channel_threshold_data['data']['TxBiasHighAlarm']['value'] + txBiasLowAlarm = channel_threshold_data['data']['TxBiasLowAlarm']['value'] + txBiasHighWarn = channel_threshold_data['data']['TxBiasHighWarning']['value'] + txBiasLowWarn = channel_threshold_data['data']['TxBiasLowWarning']['value'] + else: + return transceiver_dom_threshold_dict + + transceiver_dom_threshold_dict['temphighalarm'] = tempHighAlarm + transceiver_dom_threshold_dict['templowalarm'] = tempLowAlarm + transceiver_dom_threshold_dict['temphighwarning'] = tempHighWarn + transceiver_dom_threshold_dict['templowwarning'] = tempLowWarn + transceiver_dom_threshold_dict['vcchighalarm'] = vccHighAlarm + transceiver_dom_threshold_dict['vcclowalarm'] = vccLowAlarm + transceiver_dom_threshold_dict['vcchighwarning'] = vccHighWarn + transceiver_dom_threshold_dict['vcclowwarning'] = vccLowWarn + transceiver_dom_threshold_dict['rxpowerhighalarm'] = rxPowerHighAlarm + transceiver_dom_threshold_dict['rxpowerlowalarm'] = rxPowerLowAlarm + transceiver_dom_threshold_dict['rxpowerhighwarning'] = rxPowerHighWarn + transceiver_dom_threshold_dict['rxpowerlowwarning'] = rxPowerLowWarn + transceiver_dom_threshold_dict['txbiashighalarm'] = txBiasHighAlarm + transceiver_dom_threshold_dict['txbiaslowalarm'] = txBiasLowAlarm + transceiver_dom_threshold_dict['txbiashighwarning'] = txBiasHighWarn + transceiver_dom_threshold_dict['txbiaslowwarning'] = txBiasLowWarn + + return transceiver_dom_threshold_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + """ + tx_bias_list = [] + rx_power_list = [] + transceiver_dom_dict = {} + transceiver_dom_dict = dict.fromkeys(dom_dict_keys, 'N/A') + + # RxLos + rx_los = self.get_rx_los() + + # TxFault + tx_fault = self.get_tx_fault() + + # ResetStatus + reset_state = self.get_reset_status() + + # LowPower Mode + lp_mode = self.get_lpmode() + + # TxDisable + tx_disable = self.get_tx_disable() + + # TxDisable Channel + tx_disable_channel = self.get_tx_disable_channel() + + # Temperature + temperature = self.get_temperature() + + # Voltage + voltage = self.get_voltage() + + # Channel Monitor + channel_monitor_data = self._get_eeprom_data('ChannelMonitor') + if (channel_monitor_data is not None): + tx_bias = channel_monitor_data['data']['TX1Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = channel_monitor_data['data']['TX2Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = channel_monitor_data['data']['TX3Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = channel_monitor_data['data']['TX4Bias']['value'] + tx_bias_list.append(tx_bias) + rx_power = channel_monitor_data['data']['RX1Power']['value'] + rx_power_list.append(rx_power) + rx_power = channel_monitor_data['data']['RX2Power']['value'] + rx_power_list.append(rx_power) + rx_power = channel_monitor_data['data']['RX3Power']['value'] + rx_power_list.append(rx_power) + rx_power = channel_monitor_data['data']['RX4Power']['value'] + rx_power_list.append(rx_power) + else: + return transceiver_dom_dict + + transceiver_dom_dict['rx_los'] = rx_los + transceiver_dom_dict['tx_fault'] = tx_fault + transceiver_dom_dict['reset_status'] = reset_state + transceiver_dom_dict['power_lpmode'] = lp_mode + transceiver_dom_dict['tx_disable'] = tx_disable + transceiver_dom_dict['tx_disable_channel'] = tx_disable_channel + transceiver_dom_dict['temperature'] = temperature + transceiver_dom_dict['voltage'] = voltage + transceiver_dom_dict['tx1bias'] = tx_bias_list[0] + transceiver_dom_dict['tx2bias'] = tx_bias_list[1] + transceiver_dom_dict['tx3bias'] = tx_bias_list[2] + transceiver_dom_dict['tx4bias'] = tx_bias_list[3] + transceiver_dom_dict['rx1power'] = rx_power_list[0] + transceiver_dom_dict['rx2power'] = rx_power_list[1] + transceiver_dom_dict['rx3power'] = rx_power_list[2] + transceiver_dom_dict['rx4power'] = rx_power_list[3] + + return transceiver_dom_dict + + def get_name(self): + """ + Retrieves the name of the sfp + Returns : QSFP or QSFP+ or QSFP28 + """ + iface_data = self._get_eeprom_data('type') + if (iface_data is not None): + identifier = iface_data['data']['type']['value'] + else: + return None + + return identifier + + def get_presence(self): + """ + Retrieves the presence of the sfp + """ + presence_ctrl = self.sfp_control + 'qsfp_modprs' + try: + reg_file = open(presence_ctrl) + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + if (self.sfp_ctrl_idx > 15): + index = self.sfp_ctrl_idx % 16 + else: + index = self.sfp_ctrl_idx + + # Mask off the bit corresponding to our port + mask = (1 << index) + + # ModPrsL is active low + if ((reg_value & mask) == 0): + return True + + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the sfp + """ + vendor_pn_data = self._get_eeprom_data('model') + if (vendor_pn_data is not None): + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + else: + return None + + return vendor_pn + + def get_serial(self): + """ + Retrieves the serial number of the sfp + """ + vendor_sn_data = self._get_eeprom_data('serial') + if (vendor_sn_data is not None): + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + else: + return None + + return vendor_sn + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + """ + reset_status = None + reset_ctrl = self.sfp_control + 'qsfp_reset' + try: + reg_file = open(reset_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + if (self.sfp_ctrl_idx > 15): + index = self.sfp_ctrl_idx % 16 + else: + index = self.sfp_ctrl_idx + + mask = (1 << index) + + if ((reg_value & mask) == 0): + reset_status = True + else: + reset_status = False + + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + """ + rx_los_list = [] + + rx_los_data = self._get_eeprom_data('rx_los') + if (rx_los_data is not None): + rx_los = rx_los_data['data']['Rx1LOS']['value'] + if (rx_los == 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx2LOS']['value'] + if (rx_los == 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx3LOS']['value'] + if (rx_los == 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx4LOS']['value'] + if (rx_los == 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + + return rx_los_list + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + """ + tx_fault_list = [] + + tx_fault_data = self._get_eeprom_data('tx_fault') + if (tx_fault_data is not None): + tx_fault = tx_fault_data['data']['Tx1Fault']['value'] + if (tx_fault == 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx2Fault']['value'] + if (tx_fault == 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx3Fault']['value'] + if (tx_fault == 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx4Fault']['value'] + if (tx_fault == 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + + return tx_fault_list + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + """ + tx_disable_list = [] + + tx_disable_data = self._get_eeprom_data('tx_disable') + if (tx_disable_data is not None): + tx_disable = tx_disable_data['data']['Tx1Disable']['value'] + if (tx_disable == 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx2Disable']['value'] + if (tx_disable == 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx3Disable']['value'] + if (tx_disable == 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx4Disable']['value'] + if (tx_disable == 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + + return tx_disable_list + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + """ + tx_disable_channel = 0 + + tx_disable = self.get_tx_disable() + for channel, disable in enumerate(tx_disable): + if disable: + tx_disable_channel |= 1 << channel + + return tx_disable_channel + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + """ + lpmode_ctrl = self.sfp_control + 'qsfp_lpmode' + try: + reg_file = open(lpmode_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + if (self.sfp_ctrl_idx > 15): + index = self.sfp_ctrl_idx % 16 + else: + index = self.sfp_ctrl_idx + + mask = (1 << index) + + if ((reg_value & mask) == 0): + lpmode_state = False + else: + lpmode_state = True + + return lpmode_state + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + """ + power_override_state = None + + # Reset Status + power_override_data = self._get_eeprom_data('power_override') + if (power_override_data is not None): + power_override = power_override_data['data']['PowerOverRide']['value'] + if (power_override == 'On'): + power_override_state = True + else: + power_override_state = False + + return power_override_state + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + """ + temperature = None + + temperature_data = self._get_eeprom_data('Temperature') + if (temperature_data is not None): + temperature = self._strip_unit_from_str(temperature_data['data']['Temperature']['value']) + + return temperature + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + """ + voltage = None + + voltage_data = self._get_eeprom_data('Voltage') + if (voltage_data is not None): + voltage = self._strip_unit_from_str(voltage_data['data']['Vcc']['value']) + + return voltage + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + """ + tx_bias_list = [] + + tx_bias_data = self._get_eeprom_data('ChannelMonitor') + if (tx_bias_data is not None): + tx_bias_list.append(self._strip_unit_from_str(tx_bias_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._strip_unit_from_str(tx_bias_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._strip_unit_from_str(tx_bias_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._strip_unit_from_str(tx_bias_data['data']['TX4Bias']['value'])) + + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + """ + rx_power_list = [] + + rx_power_data = self._get_eeprom_data('ChannelMonitor') + if (rx_power_data is not None): + rx_power_list.append(self._strip_unit_from_str(rx_power_data['data']['RX1Power']['value'])) + rx_power_list.append(self._strip_unit_from_str(rx_power_data['data']['RX2Power']['value'])) + rx_power_list.append(self._strip_unit_from_str(rx_power_data['data']['RX3Power']['value'])) + rx_power_list.append(self._strip_unit_from_str(rx_power_data['data']['RX4Power']['value'])) + + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + """ + tx_power_list = [] + + tx_power_list.append(float('-inf')) + tx_power_list.append(float('-inf')) + tx_power_list.append(float('-inf')) + tx_power_list.append(float('-inf')) + + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + """ + reset_ctrl = self.sfp_control + 'qsfp_reset' + try: + # Open reset_ctrl in both read & write mode + reg_file = open(reset_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + if (self.sfp_ctrl_idx > 15): + index = self.sfp_ctrl_idx % 16 + else: + index = self.sfp_ctrl_idx + + # Mask off the bit corresponding to our port + mask = (1 << index) + + # ResetL is active low + reg_value = (reg_value & ~mask) + + # Convert our register value back to a + # hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(reset_ctrl, "w") + except IOError as e: + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + """ + lpmode_ctrl = self.sfp_control + 'qsfp_lpmode' + try: + reg_file = open(lpmode_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + if (self.sfp_ctrl_idx > 15): + index = self.sfp_ctrl_idx % 16 + else: + index = self.sfp_ctrl_idx + + mask = (1 << index) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = (reg_value | mask) + else: + reg_value = (reg_value & ~mask) + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + """ + eeprom = None + tx_disable_value = 0xf if tx_disable else 0x0 + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_CONTROL_OFFSET) + eeprom.write(struct.pack('B', tx_disable_value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + """ + eeprom = None + current_state = self.get_tx_disable_channel() + + if disable: + tx_disable_value = current_state | channel + else: + tx_disable_value = current_state & (~channel) + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_CONTROL_OFFSET) + eeprom.write(struct.pack('B', tx_disable_value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + """ + eeprom = None + power_override_bit = 0x1 if power_override else 0 + power_set_bit = 0x2 if power_set else 0 + value = power_override_bit | power_set_bit + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + eeprom.write(struct.pack('B', value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True + + def get_status(self): + """ + Retrieves the operational status of the device + """ + reset = self.get_reset_status() + + if reset: + status = False + else: + status = True + + return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py new file mode 100644 index 000000000000..cac17f4b83aa --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S6100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + import os + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """DellEMC Platform-specific Thermal class""" + + THERMAL_NAME = ( + 'CPU On-board', 'ASIC On-board Front', 'System Front', + 'ASIC On-board Rear', 'Front GE board', 'Front SFP+ board', + 'CPU Core 0', 'CPU Core 1', 'CPU Core 2', 'CPU Core 3' + ) + + def __init__(self, thermal_index): + self.is_cpu_thermal = False + self.index = thermal_index + 1 + + if self.index < 7: + if self.index < 5: + hwmon_temp_index = self.index + else: + hwmon_temp_index = self.index + 5 + + dev_path = "/sys/devices/platform/SMF.512/hwmon/" + else: + hwmon_temp_index = self.index - 5 + self.is_cpu_thermal = True + dev_path = "/sys/devices/platform/coretemp.0/hwmon/" + + hwmon_node = os.listdir(dev_path)[0] + self.HWMON_DIR = dev_path + hwmon_node + '/' + + self.thermal_status_file = self.HWMON_DIR \ + + "temp{}_alarm".format(hwmon_temp_index) + self.thermal_temperature_file = self.HWMON_DIR \ + + "temp{}_input".format(hwmon_temp_index) + self.thermal_high_threshold_file = self.HWMON_DIR \ + + "temp{}_max".format(hwmon_temp_index) + self.thermal_low_threshold_file = self.HWMON_DIR \ + + "temp{}_min".format(hwmon_temp_index) + + if not self.is_cpu_thermal: + self.thermal_high_crit_threshold_file = self.HWMON_DIR \ + + "temp{}_crit".format(hwmon_temp_index) + + def _read_sysfs_file(self, sysfs_file): + # On successful read, returns the value read from given + # sysfs_file and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(sysfs_file)): + return rv + + try: + with open(sysfs_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the name of the thermal + + Returns: + string: The name of the thermal + """ + return self.THERMAL_NAME[self.index - 1] + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return 'NA' + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + status = False + if self.is_cpu_thermal: + status = True + else: + thermal_status = self._read_sysfs_file(self.thermal_status_file) + if (thermal_status != 'ERR'): + thermal_status = int(thermal_status, 16) + if thermal_status != 5: + status = True + + return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this Thermal is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + thermal_temperature = self._read_sysfs_file( + self.thermal_temperature_file) + if (thermal_temperature != 'ERR'): + thermal_temperature = float(thermal_temperature) + else: + thermal_temperature = 0 + + return thermal_temperature / 1000.0 + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + thermal_high_threshold = self._read_sysfs_file( + self.thermal_high_threshold_file) + if (thermal_high_threshold != 'ERR'): + thermal_high_threshold = float(thermal_high_threshold) + else: + thermal_high_threshold = 0 + + return thermal_high_threshold / 1000.0 + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + thermal_low_threshold = self._read_sysfs_file( + self.thermal_low_threshold_file) + if (thermal_low_threshold != 'ERR'): + thermal_low_threshold = float(thermal_low_threshold) + else: + thermal_low_threshold = 0 + + return thermal_low_threshold / 1000.0 + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of + thermal in Celsius up to nearest thousandth of one degree + Celsius, e.g. 30.125 + """ + if self.is_cpu_thermal: + return super(Thermal, self).get_high_critical_threshold() + + thermal_high_crit_threshold = self._read_sysfs_file( + self.thermal_high_crit_threshold_file) + if (thermal_high_crit_threshold != 'ERR'): + thermal_high_crit_threshold = float(thermal_high_crit_threshold) + else: + thermal_high_crit_threshold = 0 + + return thermal_high_crit_threshold / 1000.0 + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/watchdog.py new file mode 100644 index 000000000000..0e5e102b7b52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/watchdog.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python + +######################################################################## +# +# DELLEMC S6100 +# +# Abstract base class for implementing a platform-specific class with +# which to interact with a hardware watchdog module in SONiC +# +######################################################################## + +try: + import os + import struct + import ctypes + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class _timespec(ctypes.Structure): + _fields_ = [ + ('tv_sec', ctypes.c_long), + ('tv_nsec', ctypes.c_long) + ] + +class Watchdog(WatchdogBase): + """ + Abstract base class for interfacing with a hardware watchdog module + """ + + io_resource = '/dev/port' + + WD_STATUS_OFFSET = 0x207 + WD_TIMER_OFFSET = 0x206 + WD_ENABLE = 0 + WD_DISABLE = 1 + + armed_time = 0 + timeout = 0 + CLOCK_MONOTONIC = 1 + + def __init__(self): + self._librt = ctypes.CDLL('librt.so.1', use_errno=True) + self._clock_gettime = self._librt.clock_gettime + self._clock_gettime.argtypes=[ctypes.c_int, ctypes.POINTER(_timespec)] + + def _io_reg_read(self, offset): + """ + Read the resource file + """ + fd = os.open(self.io_resource, os.O_RDONLY) + if fd < 0: + return -1 + + if os.lseek(fd, offset, os.SEEK_SET) != offset: + os.close(fd) + return -1 + + buf = os.read(fd, 1) + reg_value = ord(buf) + + os.close(fd) + return reg_value + + def _io_reg_write(self, offset, val): + """ + Write in the resource file + """ + fd = os.open(self.io_resource, os.O_RDWR) + if fd < 0: + return -1 + + if os.lseek(fd, offset, os.SEEK_SET) != offset: + os.close(fd) + return -1 + + ret = os.write(fd, struct.pack('B', val)) + if ret != 1: + os.close(fd) + return -1 + + os.close(fd) + return ret + + def _read_gpio_file(self, file_path): + """ + Read the GPIO values + """ + fd = os.open(file_path, os.O_RDONLY) + read_str = os.read(fd, os.path.getsize(file_path)) + gpio_val = int(read_str, 16) + os.close(fd) + return gpio_val + + def _write_gpio_file(self, file_path, val): + """ + Write the GPIO values + """ + fd = os.open(file_path, os.O_RDWR) + ret = os.write(fd, val) + if ret < 0: + os.close(fd) + return -1 + + os.close(fd) + return 1 + + def _get_time(self): + """ + To get clock monotonic time + """ + ts = _timespec() + if self._clock_gettime(self.CLOCK_MONOTONIC, ctypes.pointer(ts)) != 0: + errno_ = ctypes.get_errno() + return 0 + return ts.tv_sec + ts.tv_nsec * 1e-9 + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* + available value. + + Returns: + An integer specifying the *actual* number of seconds the + watchdog was armed with. On failure returns -1. + """ + gpio = "/sys/devices/platform/dell_ich.0/sc_gp_lvl" + timer_offset = -1 + if seconds > 0 and seconds <= 30: + timer_offset = 1 + seconds = 30 + elif seconds > 30 and seconds <= 60: + timer_offset = 2 + seconds = 60 + elif seconds > 60 and seconds <= 180: + timer_offset = 3 + seconds = 180 + + if timer_offset == -1: + return -1 + if self._io_reg_read(self.WD_TIMER_OFFSET) != timer_offset: + if self._io_reg_write(self.WD_TIMER_OFFSET, timer_offset) == -1: + return -1 + self.disarm() + + if self.is_armed(): + gpio_val = self._read_gpio_file(gpio) + high_val = gpio_val | (1 << 15) + if self._write_gpio_file(gpio, hex(high_val).encode('utf-8')) != -1: + low_val = high_val & 0xFFFF7FFF + if self._write_gpio_file(gpio, hex(low_val).encode('utf-8')) != -1: + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + elif self._io_reg_write(self.WD_STATUS_OFFSET, self.WD_ENABLE) != -1: + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + + return -1 + + def disarm(self): + """ + Disarm the hardware watchdog + + Returns: + A boolean, True if watchdog is disarmed successfully, False + if not + """ + if self._io_reg_write(self.WD_STATUS_OFFSET, self.WD_DISABLE) != -1: + self.armed_time = 0 + self.timeout = 0 + return True + + return False + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + + Returns: + A boolean, True if watchdog is armed, False if not + """ + wd_status = self.WD_DISABLE + wd_status = self._io_reg_read(self.WD_STATUS_OFFSET) + if wd_status == self.WD_ENABLE: + return True + + return False + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds + remaining on the watchdog timer + + Returns: + An integer specifying the number of seconds remaining on + their watchdog timer. If the watchdog is not armed, returns + -1. + + S6100 doesnot have hardware support to show remaining time. + Due to this limitation, this API is implemented in software. + This API would return correct software time difference if it + is called from the process which armed the watchdog timer. + If this API called from any other process, it would return + 0. If the watchdog is not armed, this API would return -1. + """ + if not self.is_armed(): + return -1 + + if self.armed_time > 0 and self.timeout != 0: + cur_time = self._get_time() + if cur_time <= 0: + return 0 + diff_time = int(cur_time - self.armed_time) + if diff_time > self.timeout: + return self.timeout + else: + return self.timeout - diff_time + + return 0 + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/platform-modules-s6100.service b/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/platform-modules-s6100.service new file mode 100644 index 000000000000..4883ecf268fd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/platform-modules-s6100.service @@ -0,0 +1,14 @@ +[Unit] +Description=Dell S6100 Platform modules +Before=pmon.service determine-reboot-cause.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStartPre=/usr/local/bin/iom_power_on.sh +ExecStart=/usr/local/bin/s6100_platform.sh init +ExecStop=/usr/local/bin/s6100_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/s6100-i2c-enumerate.service b/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/s6100-i2c-enumerate.service new file mode 100644 index 000000000000..c63482831940 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/s6100-i2c-enumerate.service @@ -0,0 +1,12 @@ +[Unit] +Description=Dell S6100 I2C MUX Enumeration +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/s6100_i2c_enumeration.sh init +RemainAfterExit=no + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/s6100-lpc-monitor.service b/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/s6100-lpc-monitor.service new file mode 100644 index 000000000000..86dac18a310e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/s6100-lpc-monitor.service @@ -0,0 +1,12 @@ +[Unit] +Description=Dell S6100 LPC bus monitoring poller +DefaultDependencies=no + +[Service] +User=root +ExecStart=/usr/local/bin/dell_lpc_mon.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target + diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/s6100-reboot-cause.service b/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/s6100-reboot-cause.service new file mode 100644 index 000000000000..bcf903d56d80 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/systemd/s6100-reboot-cause.service @@ -0,0 +1,12 @@ +[Unit] +Description=Read Dell S6100 reboot cause +Before=process-reboot-cause.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/share/sonic/device/x86_64-dell_s6100_c2538-r0/track_reboot_reason.sh +RemainAfterExit=no + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/tools/0002-Flashrom-support-for-Intel-Rangeley-and-Denverton-CP.patch b/platform/broadcom/sonic-platform-modules-dell/tools/0002-Flashrom-support-for-Intel-Rangeley-and-Denverton-CP.patch new file mode 100644 index 000000000000..ab77df9c4d3b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/tools/0002-Flashrom-support-for-Intel-Rangeley-and-Denverton-CP.patch @@ -0,0 +1,8510 @@ +From 482e06109190eb918208820fd94c8f4a6963f77e Mon Sep 17 00:00:00 2001 +From: paavaanan +Date: Tue, 21 May 2019 10:40:59 -0400 +Subject: [PATCH] Intel-Rangeley-stripped-code-changes + +--- + 82802ab.c | 1 + + Makefile | 109 +++- + README | 26 +- + at45db.c | 562 ++++++++++++++++ + atahpt.c | 2 + + board_enable.c | 19 +- + buspirate_spi.c | 7 +- + cbtable.c | 7 +- + chipdrivers.h | 21 +- + chipset_enable.c | 610 +++++++++++------ + cli_classic.c | 40 +- + dmi.c | 332 ++++++++-- + dnv_smi_spi.c | 185 ++++++ + drkaiser.c | 14 +- + flash.h | 56 +- + flashchips.c | 791 +++++++++++++++++++---- + flashchips.h | 27 +- + flashrom.c | 162 ++++- + ft2232_spi.c | 6 + + gfxnvidia.c | 14 +- + hwaccess.h | 6 + + ich_descriptors.c | 104 +++ + ich_descriptors.h | 104 +++ + ichspi.c | 557 ++++++++++++++-- + internal.c | 5 +- + it85spi.c | 3 + + it87spi.c | 47 +- + layout.c | 126 +++- + linux_spi.c | 12 +- + mcp6x_spi.c | 15 +- + nic3com.c | 2 + + nicintel.c | 29 +- + nicintel_spi.c | 26 +- + nicnatsemi.c | 2 + + nicrealtek.c | 2 + + ogp_spi.c | 14 +- + pcidev.c | 2 +- + physmap.c | 170 +++-- + pony_spi.c | 1 + + print.c | 15 +- + programmer.h | 28 +- + rayer_spi.c | 196 ++++-- + satamv.c | 19 +- + satasii.c | 18 +- + sb600spi.c | 208 +++++- + serial.c | 113 ++-- + serprog.c | 165 +++-- + spi25.c | 35 +- + spi25_statusreg.c | 2 +- + stm50.c | 115 ++++ + udelay.c | 10 +- + util/getrevision.sh | 311 +++++++++ + util/ich_descriptors_tool/ich_descriptors_tool.c | 8 +- + util/z60_flashrom.rules | 4 + + 54 files changed, 4553 insertions(+), 912 deletions(-) + create mode 100644 at45db.c + create mode 100644 dnv_smi_spi.c + create mode 100644 stm50.c + create mode 100755 util/getrevision.sh + +diff --git a/82802ab.c b/82802ab.c +index 608995d..2a43813 100644 +--- a/82802ab.c ++++ b/82802ab.c +@@ -89,6 +89,7 @@ int probe_82802ab(struct flashctx *flash) + return 1; + } + ++/* FIXME: needs timeout */ + uint8_t wait_82802ab(struct flashctx *flash) + { + uint8_t status; +diff --git a/Makefile b/Makefile +index 6e41e5d..d66039a 100644 +--- a/Makefile ++++ b/Makefile +@@ -39,6 +39,7 @@ CFLAGS ?= -Os -Wall -Wshadow + EXPORTDIR ?= . + AR ?= ar + RANLIB ?= ranlib ++DOSLIBS_BASE ?= .. + # The following parameter changes the default programmer that will be used if there is no -p/--programmer + # argument given when running flashrom. The predefined setting does not enable any default so that every + # user has to declare the programmer he wants to use on every run. The rationale for this to be not set +@@ -50,7 +51,8 @@ RANLIB ?= ranlib + # values are those specified in enum programmer in programmer.h (which depend on other CONFIG_* options + # evaluated below, namely those that enable/disable the various programmers). + # Compilation will fail for unspecified values. +-CONFIG_DEFAULT_PROGRAMMER ?= PROGRAMMER_INVALID ++#CONFIG_DEFAULT_PROGRAMMER ?= PROGRAMMER_INVALID ++CONFIG_DEFAULT_PROGRAMMER ?= PROGRAMMER_INTERNAL + + # If your compiler spits out excessive warnings, run make WARNERROR=no + # You shouldn't have to change this flag. +@@ -61,10 +63,13 @@ CFLAGS += -Werror + endif + + ############################################################################### +-# General OS/architecture specific settings. ++# General OS-specific settings. ++# 1. Prepare for later by gathering information about host and target OS ++# 2. Set compiler flags and parameters according to OSes ++# 3. Likewise verify user-supplied CONFIG_* variables. + + # HOST_OS is only used to work around local toolchain issues. +-HOST_OS ?= $(shell uname) ++HOST_OS ?= $(shell uname) + ifeq ($(HOST_OS), MINGW32_NT-5.1) + # Explicitly set CC = gcc on MinGW, otherwise: "cc: command not found". + CC = gcc +@@ -94,13 +99,24 @@ CPPFLAGS += -I/usr/local/include + LDFLAGS += -L/usr/local/lib + endif + ++ifeq ($(TARGET_OS), NetBSD) ++CPPFLAGS += -I/usr/pkg/include ++LDFLAGS += -L/usr/pkg/lib ++endif ++ ++ifeq ($(TARGET_OS), DragonFlyBSD) ++CPPFLAGS += -I/usr/pkg/include ++LDFLAGS += -L/usr/pkg/lib ++endif ++ + ifeq ($(TARGET_OS), DOS) + EXEC_SUFFIX := .exe +-CPPFLAGS += -I../libgetopt ++CPPFLAGS += -I$(DOSLIBS_BASE)/libgetopt + # DJGPP has odd uint*_t definitions which cause lots of format string warnings. + CFLAGS += -Wno-format + # FIXME Check if we can achieve the same effect with -L../libgetopt -lgetopt +-LIBS += ../libgetopt/libgetopt.a ++LIBS += -lgetopt ++LDFLAGS += -L$(DOSLIBS_BASE)/libgetopt/ + # Bus Pirate, Serprog and PonyProg are not supported under DOS (missing serial support). + ifeq ($(CONFIG_BUSPIRATE_SPI), yes) + UNSUPPORTED_FEATURES += CONFIG_BUSPIRATE_SPI=yes +@@ -215,6 +231,10 @@ endif + endif + + ifeq ($(TARGET_OS), libpayload) ++ifeq ($(MAKECMDGOALS),) ++.DEFAULT_GOAL := libflashrom.a ++$(info Setting default goal to libflashrom.a) ++endif + FLASHROM_CFLAGS += -DSTANDALONE + ifeq ($(CONFIG_DUMMY), yes) + UNSUPPORTED_FEATURES += CONFIG_DUMMY=yes +@@ -263,6 +283,10 @@ override CONFIG_LINUX_SPI = no + endif + endif + ++############################################################################### ++# General architecture-specific settings. ++# Like above for the OS, below we verify user-supplied options depending on the target architecture. ++ + # Determine the destination processor architecture. + # IMPORTANT: The following line must be placed before ARCH is ever used + # (of course), but should come after any lines setting CC because the line +@@ -307,10 +331,10 @@ endif + ############################################################################### + # Flash chip drivers and bus support infrastructure. + +-CHIP_OBJS = jedec.o stm50flw0x0x.o w39.o w29ee011.o \ ++CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \ + sst28sf040.o m29f400bt.o 82802ab.o pm49fl00x.o \ + sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o spi25_statusreg.o \ +- opaque.o sfdp.o en29lv640b.o ++ opaque.o sfdp.o en29lv640b.o at45db.o + + ############################################################################### + # Library code. +@@ -322,18 +346,22 @@ LIB_OBJS = layout.o flashrom.o udelay.o programmer.o + + CLI_OBJS = cli_classic.o cli_output.o print.o + +-# Set the flashrom version string from the highest revision number +-# of the checked out flashrom files. ++# Set the flashrom version string from the highest revision number of the checked out flashrom files. + # Note to packagers: Any tree exported with "make export" or "make tarball" + # will not require subversion. The downloadable snapshots are already exported. +-SVNVERSION := $(shell LC_ALL=C svnversion -cn . 2>/dev/null | sed -e "s/.*://" -e "s/\([0-9]*\).*/\1/" | grep "[0-9]" || LC_ALL=C svn info . 2>/dev/null | awk '/^Revision:/ {print $$2 }' | grep "[0-9]" || LC_ALL=C git svn info . 2>/dev/null | awk '/^Revision:/ {print $$2 }' | grep "[0-9]" || echo unknown) ++SVNVERSION := r1781 + + RELEASE := 0.9.7 +-VERSION := $(RELEASE)-r$(SVNVERSION) ++VERSION := $(RELEASE)-$(SVNVERSION) + RELEASENAME ?= $(VERSION) + + SVNDEF := -D'FLASHROM_VERSION="$(VERSION)"' + ++F10FLAGS := -DFORCE10_SPI_CHANGE ++ ++############################################################################### ++# Default settings of CONFIG_* variables. ++ + # Always enable internal/onboard support for now. + CONFIG_INTERNAL ?= yes + +@@ -425,16 +453,39 @@ endif + endif + + ############################################################################### ++# Handle CONFIG_* variables that depend on others set (and verified) above. ++ ++# The external DMI decoder (dmidecode) does not work in libpayload. Bail out if the internal one got disabled. ++ifeq ($(TARGET_OS), libpayload) ++ifeq ($(CONFIG_INTERNAL), yes) ++ifeq ($(CONFIG_INTERNAL_DMI), no) ++UNSUPPORTED_FEATURES += CONFIG_INTERNAL_DMI=no ++else ++override CONFIG_INTERNAL_DMI = yes ++endif ++endif ++endif ++ ++# Use internal DMI/SMBIOS decoder by default instead of relying on dmidecode. ++CONFIG_INTERNAL_DMI ?= yes ++ ++############################################################################### + # Programmer drivers and programmer support infrastructure. ++# Depending on the CONFIG_* variables set and verified above we set compiler flags and parameters below. ++ ++FEATURE_CFLAGS += -DDELL_DENVERTON_SUPPORT -DDELL_AVOTON_SUPPORT + + FEATURE_CFLAGS += -D'CONFIG_DEFAULT_PROGRAMMER=$(CONFIG_DEFAULT_PROGRAMMER)' + + ifeq ($(CONFIG_INTERNAL), yes) + FEATURE_CFLAGS += -D'CONFIG_INTERNAL=1' +-PROGRAMMER_OBJS += processor_enable.o chipset_enable.o board_enable.o cbtable.o dmi.o internal.o ++PROGRAMMER_OBJS += processor_enable.o chipset_enable.o board_enable.o cbtable.o internal.o + ifeq ($(ARCH), x86) + PROGRAMMER_OBJS += it87spi.o it85spi.o sb600spi.o amd_imc.o wbsio_spi.o mcp6x_spi.o +-PROGRAMMER_OBJS += ichspi.o ich_descriptors.o ++PROGRAMMER_OBJS += ichspi.o ich_descriptors.o dmi.o dnv_smi_spi.o ++ifeq ($(CONFIG_INTERNAL_DMI), yes) ++FEATURE_CFLAGS += -D'CONFIG_INTERNAL_DMI=1' ++endif + else + endif + NEED_PCI := yes +@@ -597,9 +648,9 @@ PCILIBS += -lpciutils -lpci + PCILIBS += -l$(shell uname -p) + else + ifeq ($(TARGET_OS), DOS) +-# FIXME There needs to be a better way to do this +-CPPFLAGS += -I../libpci/include +-PCILIBS += ../libpci/lib/libpci.a ++CPPFLAGS += -I$(DOSLIBS_BASE)/libpci/include ++LDFLAGS += -L$(DOSLIBS_BASE)/libpci/lib/ ++PCILIBS += -lpci + else + PCILIBS += -lpci + ifeq ($(TARGET_OS), OpenBSD) +@@ -635,10 +686,11 @@ FEATURE_LIBS += $(shell LC_ALL=C grep -q "NEEDLIBZ := yes" .libdeps && printf "% + LIBFLASHROM_OBJS = $(CHIP_OBJS) $(PROGRAMMER_OBJS) $(LIB_OBJS) + OBJS = $(CLI_OBJS) $(LIBFLASHROM_OBJS) + +-all: hwlibs features $(PROGRAM)$(EXEC_SUFFIX) ++all: hwlibs features $(PROGRAM)$(EXEC_SUFFIX) $(PROGRAM).8 + ifeq ($(ARCH), x86) + @+$(MAKE) -C util/ich_descriptors_tool/ TARGET_OS=$(TARGET_OS) EXEC_SUFFIX=$(EXEC_SUFFIX) + endif ++default: all + + $(PROGRAM)$(EXEC_SUFFIX): $(OBJS) + $(CC) $(LDFLAGS) -o $(PROGRAM)$(EXEC_SUFFIX) $(OBJS) $(LIBS) $(PCILIBS) $(FEATURE_LIBS) $(USBLIBS) +@@ -653,13 +705,13 @@ libflashrom.a: $(LIBFLASHROM_OBJS) + TAROPTIONS = $(shell LC_ALL=C tar --version|grep -q GNU && echo "--owner=root --group=root") + + %.o: %.c .features +- $(CC) -MMD $(CFLAGS) $(CPPFLAGS) $(FLASHROM_CFLAGS) $(FEATURE_CFLAGS) $(SVNDEF) -o $@ -c $< ++ $(CC) -MMD $(CFLAGS) $(CPPFLAGS) $(FLASHROM_CFLAGS) $(FEATURE_CFLAGS) $(SVNDEF) $(F10FLAGS) -o $@ -c $< + + # Make sure to add all names of generated binaries here. + # This includes all frontends and libflashrom. + # We don't use EXEC_SUFFIX here because we want to clean everything. + clean: +- rm -f $(PROGRAM) $(PROGRAM).exe libflashrom.a *.o *.d ++ rm -f $(PROGRAM) $(PROGRAM).exe libflashrom.a *.o *.d $(PROGRAM).8 + @+$(MAKE) -C util/ich_descriptors_tool/ clean + + distclean: clean +@@ -698,11 +750,20 @@ compiler: featuresavailable + @echo $(TARGET_OS)|wc -w|grep -q '^[[:blank:]]*1[[:blank:]]*$$' || \ + ( echo "unknown. Aborting."; exit 1) + @printf "%s\n" '$(TARGET_OS)' ++ifeq ($(TARGET_OS), libpayload) ++ @$(CC) --version 2>&1 | grep -q coreboot || \ ++ ( echo "Warning: It seems you are not using coreboot's reference compiler."; \ ++ echo "This might work but usually does not, please beware." ) ++endif + + define LIBPCI_TEST + /* Avoid a failing test due to libpci header symbol shadowing breakage */ + #define index shadow_workaround_index ++#if !defined __NetBSD__ && !defined __DragonFly__ + #include ++#else ++#include ++#endif + struct pci_access *pacc; + int main(int argc, char **argv) + { +@@ -853,16 +914,20 @@ endif + @$(DIFF) -q .features.tmp .features >/dev/null 2>&1 && rm .features.tmp || mv .features.tmp .features + @rm -f .featuretest.c .featuretest$(EXEC_SUFFIX) + +-install: $(PROGRAM)$(EXEC_SUFFIX) ++$(PROGRAM).8: $(PROGRAM).8.tmpl ++ @sed -e '1 s#".*".*#"$(shell ./util/getrevision.sh -d $(PROGRAM).8.tmpl)" "$(VERSION)"#' <$< >$@ ++ ++install: $(PROGRAM)$(EXEC_SUFFIX) $(PROGRAM).8 + mkdir -p $(DESTDIR)$(PREFIX)/sbin + mkdir -p $(DESTDIR)$(MANDIR)/man8 + $(INSTALL) -m 0755 $(PROGRAM)$(EXEC_SUFFIX) $(DESTDIR)$(PREFIX)/sbin + $(INSTALL) -m 0644 $(PROGRAM).8 $(DESTDIR)$(MANDIR)/man8 + +-export: ++export: $(PROGRAM).8 + @rm -rf $(EXPORTDIR)/flashrom-$(RELEASENAME) + @svn export -r BASE . $(EXPORTDIR)/flashrom-$(RELEASENAME) + @sed "s/^SVNVERSION.*/SVNVERSION := $(SVNVERSION)/" Makefile >$(EXPORTDIR)/flashrom-$(RELEASENAME)/Makefile ++ @cp $(PROGRAM).8 "$(EXPORTDIR)/flashrom-$(RELEASENAME)/$(PROGRAM).8" + @LC_ALL=C svn log >$(EXPORTDIR)/flashrom-$(RELEASENAME)/ChangeLog + @echo Exported $(EXPORTDIR)/flashrom-$(RELEASENAME)/ + +@@ -876,6 +941,6 @@ djgpp-dos: clean + libpayload: clean + make CC="CC=i386-elf-gcc lpgcc" AR=i386-elf-ar RANLIB=i386-elf-ranlib + +-.PHONY: all clean distclean compiler hwlibs features export tarball dos featuresavailable ++.PHONY: all install clean distclean compiler hwlibs features export tarball dos featuresavailable + + -include $(OBJS:.o=.d) +diff --git a/README b/README +index 7f24cca..b3e50a6 100644 +--- a/README ++++ b/README +@@ -80,11 +80,9 @@ To compile on Solaris, use: + + gmake LDFLAGS="-L$pathtolibpci" CC="gcc -I$pathtopciheaders" CFLAGS=-O2 + +-To compile on NetBSD or DragonFly BSD, use: ++To compile on NetBSD or DragonFly BSD (with pciutils, libftdi, libusb installed in /usr/pkg/), use: + +- ln -s /usr/pkg/include/pciutils pci +- gmake CPPFLAGS="-I. -I/usr/pkg/include" \ +- LDFLAGS="-L/usr/pkg/lib -Wl,-rpath-link,/usr/pkg/lib" ++ gmake + + To compile on OpenBSD, use: + +@@ -105,20 +103,24 @@ To cross-compile on Linux for DOS: + djcrx-2.04pre_20090725-13ap.i386.rpm + The cross toolchain packages for your distribution may have slightly different + names (look for packages named *djgpp*). +- Download pciutils 3.1.5 and apply http://assembler.cz/flashrom/pciutils.patch +- Download and compile http://assembler.cz/flashrom/libgetopt/ ++ ++ You will need the following library source trees containing their compiled ++ static libraries either in the parent directory of the flashrom source or ++ specify the base folder on compile time with the DOSLIBS_BASE parameter. ++ The default as described above is equal to calling ++ 'make djgpp-dos DOSLIBS_BASE=..' ++ ++ To get and build said libraries... ++ Download pciutils 3.1.5 and apply http://flashrom.org/File:Pciutils.patch.gz + Compile pciutils, see README.DJGPP for instructions. ++ Download and compile http://flashrom.org/File:Libgetopt.tar.gz + Enter the flashrom directory. +- ../libpci should contain pciutils source and binaries. +- ../libgetopt should contain getopt.a from libgetopt. + Run either (change settings where appropriate) + make CC=i586-pc-msdosdjgpp-gcc STRIP=i586-pc-msdosdjgpp-strip + or (above settings hardcoded) + make djgpp-dos +- You might have to add WARNERROR=no to the make command line. +- To run flashrom.exe, download and unpack +- http://homer.rice.edu/~sandmann/cwsdpmi/csdpmi7b.zip and make sure +- CWSDPMI.EXE is in the current directory. ++ To run flashrom.exe, download http://flashrom.org/File:Csdpmi7b.zip and ++ unpack CWSDPMI.EXE into the current directory or one in PATH. + + To cross-compile on Linux for Windows: + +diff --git a/at45db.c b/at45db.c +new file mode 100644 +index 0000000..5c90418 +--- /dev/null ++++ b/at45db.c +@@ -0,0 +1,562 @@ ++/* ++ * Support for Atmel AT45DB series DataFlash chips. ++ * This file is part of the flashrom project. ++ * ++ * Copyright (C) 2012 Aidan Thornton ++ * Copyright (C) 2013 Stefan Tauner ++ * ++ * 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; 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. ++ * ++ * 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 ++ */ ++ ++#include ++#include "flash.h" ++#include "chipdrivers.h" ++#include "programmer.h" ++#include "spi.h" ++ ++/* Status register bits */ ++#define AT45DB_READY (1<<7) ++#define AT45DB_CMP (1<<6) ++#define AT45DB_PROT (1<<1) ++#define AT45DB_POWEROF2 (1<<0) ++ ++/* Opcodes */ ++#define AT45DB_STATUS 0xD7 /* NB: this is a block erase command on most other chips(!). */ ++#define AT45DB_DISABLE_PROTECT 0x3D, 0x2A, 0x7F, 0x9A ++#define AT45DB_READ_ARRAY 0xE8 ++#define AT45DB_READ_PROTECT 0x32 ++#define AT45DB_READ_LOCKDOWN 0x35 ++#define AT45DB_PAGE_ERASE 0x81 ++#define AT45DB_BLOCK_ERASE 0x50 ++#define AT45DB_SECTOR_ERASE 0x7C ++#define AT45DB_CHIP_ERASE 0xC7 ++#define AT45DB_CHIP_ERASE_ADDR 0x94809A /* Magic address. See usage. */ ++#define AT45DB_BUFFER1_WRITE 0x84 ++#define AT45DB_BUFFER1_PAGE_PROGRAM 0x88 ++/* Buffer 2 is unused yet. ++#define AT45DB_BUFFER2_WRITE 0x87 ++#define AT45DB_BUFFER2_PAGE_PROGRAM 0x89 ++*/ ++ ++static uint8_t at45db_read_status_register(struct flashctx *flash, uint8_t *status) ++{ ++ static const uint8_t cmd[] = { AT45DB_STATUS }; ++ ++ int ret = spi_send_command(flash, sizeof(cmd), 1, cmd, status); ++ if (ret != 0) ++ msg_cerr("Reading the status register failed!\n"); ++ else ++ msg_cspew("Status register: 0x%02x.\n", *status); ++ return ret; ++} ++ ++int spi_disable_blockprotect_at45db(struct flashctx *flash) ++{ ++ static const uint8_t cmd[4] = { AT45DB_DISABLE_PROTECT }; /* NB: 4 bytes magic number */ ++ int ret = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL); ++ if (ret != 0) { ++ msg_cerr("Sending disable lockdown failed!\n"); ++ return ret; ++ } ++ uint8_t status; ++ ret = at45db_read_status_register(flash, &status); ++ if (ret != 0 || ((status & AT45DB_PROT) != 0)) { ++ msg_cerr("Disabling lockdown failed!\n"); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static unsigned int at45db_get_sector_count(struct flashctx *flash) ++{ ++ unsigned int i, j; ++ unsigned int cnt = 0; ++ for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { ++ if (flash->chip->block_erasers[i].block_erase == &spi_erase_at45db_sector) { ++ for (j = 0; j < NUM_ERASEREGIONS; j++) { ++ cnt += flash->chip->block_erasers[i].eraseblocks[j].count; ++ } ++ } ++ } ++ msg_cspew("%s: number of sectors=%u\n", __func__, cnt); ++ return cnt; ++} ++ ++/* Reads and prettyprints protection/lockdown registers. ++ * Some elegance of the printouts had to be cut down a bit to share this code. */ ++static uint8_t at45db_prettyprint_protection_register(struct flashctx *flash, uint8_t opcode, const char *regname) ++{ ++ const uint8_t cmd[] = { opcode, 0, 0, 0 }; ++ /* The first two sectors share the first result byte. */ ++ uint8_t buf[at45db_get_sector_count(flash) - 1]; ++ ++ int ret = spi_send_command(flash, sizeof(cmd), sizeof(buf), cmd, buf); ++ if (ret != 0) { ++ msg_cerr("Reading the %s register failed!\n", regname); ++ return ret; ++ } ++ ++ unsigned int i; ++ for (i = 0; i < sizeof(buf); i++) { ++ if (buf[i] != 0x00) ++ break; ++ if (i == sizeof(buf) - 1) { ++ msg_cdbg("No Sector is %sed.\n", regname); ++ return 0; ++ } ++ } ++ ++ /* TODO: print which addresses are mapped to (un)locked sectors. */ ++ msg_cdbg("Sector 0a is %s%sed.\n", ((buf[0] & 0xC0) == 0x00) ? "un" : "", regname); ++ msg_cdbg("Sector 0b is %s%sed.\n", ((buf[0] & 0x30) == 0x00) ? "un" : "", regname); ++ for (i = 1; i < sizeof(buf); i++) ++ msg_cdbg("Sector %2u is %s%sed.\n", i, (buf[i] == 0x00) ? "un" : "", regname); ++ ++ return 0; ++} ++ ++/* bit 7: busy flag ++ * bit 6: memory/buffer compare result ++ * bit 5-2: density (encoding see below) ++ * bit 1: protection enabled (soft or hard) ++ * bit 0: "power of 2" page size indicator (e.g. 1 means 256B; 0 means 264B) ++ * ++ * 5-2 encoding: bit 2 is always 1, bits 3-5 encode the density as "2^(bits - 1)" in Mb e.g.: ++ * AT45DB161D 1011 16Mb */ ++int spi_prettyprint_status_register_at45db(struct flashctx *flash) ++{ ++ uint8_t status; ++ if (at45db_read_status_register(flash, &status) != 0) { ++ return 1; ++ } ++ ++ /* AT45DB321C does not support lockdown or a page size of a power of 2... */ ++ const bool isAT45DB321C = (strcmp(flash->chip->name, "AT45DB321C") == 0); ++ msg_cdbg("Chip status register is 0x%02x\n", status); ++ msg_cdbg("Chip status register: Bit 7 / Ready is %sset\n", (status & AT45DB_READY) ? "" : "not "); ++ msg_cdbg("Chip status register: Bit 6 / Compare match is %sset\n", (status & AT45DB_CMP) ? "" : "not "); ++ spi_prettyprint_status_register_bit(status, 5); ++ spi_prettyprint_status_register_bit(status, 4); ++ spi_prettyprint_status_register_bit(status, 3); ++ spi_prettyprint_status_register_bit(status, 2); ++ const uint8_t dens = (status >> 3) & 0x7; /* Bit 2 is always 1, we use the other bits only */ ++ msg_cdbg("Chip status register: Density is %u Mb\n", 1 << (dens - 1)); ++ msg_cdbg("Chip status register: Bit 1 / Protection is %sset\n", (status & AT45DB_PROT) ? "" : "not "); ++ ++ if (isAT45DB321C) ++ spi_prettyprint_status_register_bit(status, 0); ++ else ++ msg_cdbg("Chip status register: Bit 0 / \"Power of 2\" is %sset\n", ++ (status & AT45DB_POWEROF2) ? "" : "not "); ++ ++ if (status & AT45DB_PROT) ++ at45db_prettyprint_protection_register(flash, AT45DB_READ_PROTECT, "protect"); ++ ++ if (!isAT45DB321C) ++ at45db_prettyprint_protection_register(flash, AT45DB_READ_LOCKDOWN, "lock"); ++ ++ return 0; ++} ++ ++/* Probe function for AT45DB* chips that support multiple page sizes. */ ++int probe_spi_at45db(struct flashctx *flash) ++{ ++ uint8_t status; ++ struct flashchip *chip = flash->chip; ++ ++ if (!probe_spi_rdid(flash)) ++ return 0; ++ ++ /* Some AT45DB* chips support two different page sizes each (e.g. 264 and 256 B). In order to tell which ++ * page size this chip has we need to read the status register. */ ++ if (at45db_read_status_register(flash, &status) != 0) ++ return 0; ++ ++ /* We assume sane power-of-2 page sizes and adjust the chip attributes in case this is not the case. */ ++ if ((status & AT45DB_POWEROF2) == 0) { ++ chip->total_size = (chip->total_size / 32) * 33; ++ chip->page_size = (chip->page_size / 32) * 33; ++ ++ unsigned int i, j; ++ for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { ++ struct block_eraser *eraser = &chip->block_erasers[i]; ++ for (j = 0; j < NUM_ERASEREGIONS; j++) { ++ eraser->eraseblocks[j].size = (eraser->eraseblocks[j].size / 32) * 33; ++ } ++ } ++ } ++ ++ switch (chip->page_size) { ++ case 256: chip->gran = write_gran_256bytes; break; ++ case 264: chip->gran = write_gran_264bytes; break; ++ case 512: chip->gran = write_gran_512bytes; break; ++ case 528: chip->gran = write_gran_528bytes; break; ++ case 1024: chip->gran = write_gran_1024bytes; break; ++ case 1056: chip->gran = write_gran_1056bytes; break; ++ default: ++ msg_cerr("%s: unknown page size %d.\n", __func__, chip->page_size); ++ return 0; ++ } ++ ++ msg_cdbg2("%s: total size %i kB, page size %i B\n", __func__, chip->total_size * 1024, chip->page_size); ++ ++ return 1; ++} ++ ++/* Returns the minimum number of bits needed to represent the given address. ++ * FIXME: use mind-blowing implementation. ++ * FIXME: move to utility module. */ ++static uint32_t address_to_bits(uint32_t addr) ++{ ++ unsigned int lzb = 0; ++ while (((1 << (31 - lzb)) & ~addr) != 0) ++ lzb++; ++ return 32 - lzb; ++} ++ ++/* In case of non-power-of-two page sizes we need to convert the address flashrom uses to the address the ++ * DataFlash chips use. The latter uses a segmented address space where the page address is encoded in the ++ * more significant bits and the offset within the page is encoded in the less significant bits. The exact ++ * partition depends on the page size. ++ */ ++static unsigned int at45db_convert_addr(unsigned int addr, unsigned int page_size) ++{ ++ unsigned int page_bits = address_to_bits(page_size - 1); ++ unsigned int at45db_addr = ((addr / page_size) << page_bits) | (addr % page_size); ++ msg_cspew("%s: addr=0x%x, page_size=%u, page_bits=%u -> at45db_addr=0x%x\n", ++ __func__, addr, page_size, page_bits, at45db_addr); ++ return at45db_addr; ++} ++ ++int spi_read_at45db(struct flashctx *flash, uint8_t *buf, unsigned int addr, unsigned int len) ++{ ++ const unsigned int page_size = flash->chip->page_size; ++ const unsigned int total_size = flash->chip->total_size * 1024; ++ if ((addr + len) > total_size) { ++ msg_cerr("%s: tried to read beyond flash boundary: addr=%u, len=%u, size=%u\n", ++ __func__, addr, len, total_size); ++ return 1; ++ } ++ ++ /* We have to split this up into chunks to fit within the programmer's read size limit, but those ++ * chunks can cross page boundaries. */ ++ const unsigned int max_data_read = flash->pgm->spi.max_data_read; ++ const unsigned int max_chunk = (max_data_read > 0) ? max_data_read : page_size; ++ while (addr < len) { ++ unsigned int chunk = min(max_chunk, len); ++ int ret = spi_nbyte_read(flash, at45db_convert_addr(addr, page_size), buf + addr, chunk); ++ if (ret) { ++ msg_cerr("%s: error sending read command!\n", __func__); ++ return ret; ++ } ++ addr += chunk; ++ } ++ ++ return 0; ++} ++ ++/* Legacy continuous read, used where spi_read_at45db() is not available. ++ * The first 4 (dummy) bytes read need to be discarded. */ ++int spi_read_at45db_e8(struct flashctx *flash, uint8_t *buf, unsigned int addr, unsigned int len) ++{ ++ const unsigned int page_size = flash->chip->page_size; ++ const unsigned int total_size = flash->chip->total_size * 1024; ++ if ((addr + len) > total_size) { ++ msg_cerr("%s: tried to read beyond flash boundary: addr=%u, len=%u, size=%u\n", ++ __func__, addr, len, total_size); ++ return 1; ++ } ++ ++ /* We have to split this up into chunks to fit within the programmer's read size limit, but those ++ * chunks can cross page boundaries. */ ++ const unsigned int max_data_read = flash->pgm->spi.max_data_read; ++ const unsigned int max_chunk = (max_data_read > 0) ? max_data_read : page_size; ++ while (addr < len) { ++ const unsigned int addr_at45 = at45db_convert_addr(addr, page_size); ++ const unsigned char cmd[] = { ++ AT45DB_READ_ARRAY, ++ (addr_at45 >> 16) & 0xff, ++ (addr_at45 >> 8) & 0xff, ++ (addr_at45 >> 0) & 0xff ++ }; ++ /* We need to leave place for 4 dummy bytes and handle them explicitly. */ ++ unsigned int chunk = min(max_chunk, len + 4); ++ uint8_t tmp[chunk]; ++ int ret = spi_send_command(flash, sizeof(cmd), chunk, cmd, tmp); ++ if (ret) { ++ msg_cerr("%s: error sending read command!\n", __func__); ++ return ret; ++ } ++ /* Copy result without dummy bytes into buf and advance address counter respectively. */ ++ memcpy(buf + addr, tmp + 4, chunk - 4); ++ addr += chunk - 4; ++ } ++ return 0; ++} ++ ++/* Returns 0 when ready, 1 on errors and timeouts. */ ++static int at45db_wait_ready (struct flashctx *flash, unsigned int us, unsigned int retries) ++{ ++ while (true) { ++ uint8_t status; ++ int ret = at45db_read_status_register(flash, &status); ++ if ((status & AT45DB_READY) == AT45DB_READY) ++ return 0; ++ if (ret != 0 || retries-- == 0) ++ return 1; ++ programmer_delay(us); ++ } ++} ++ ++static int at45db_erase(struct flashctx *flash, uint8_t opcode, unsigned int at45db_addr, unsigned int stepsize, unsigned int retries) ++{ ++ const uint8_t cmd[] = { ++ opcode, ++ (at45db_addr >> 16) & 0xff, ++ (at45db_addr >> 8) & 0xff, ++ (at45db_addr >> 0) & 0xff ++ }; ++ ++ /* Send erase command. */ ++ int ret = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL); ++ if (ret != 0) { ++ msg_cerr("%s: error sending erase command!\n", __func__); ++ return ret; ++ } ++ ++ /* Wait for completion. */ ++ ret = at45db_wait_ready(flash, stepsize, retries); ++ if (ret != 0) ++ msg_cerr("%s: chip did not became ready again after sending the erase command!\n", __func__); ++ ++ return ret; ++} ++ ++int spi_erase_at45db_page(struct flashctx *flash, unsigned int addr, unsigned int blocklen) ++{ ++ const unsigned int page_size = flash->chip->page_size; ++ const unsigned int total_size = flash->chip->total_size * 1024; ++ ++ if ((addr % page_size) != 0 || (blocklen % page_size) != 0) { ++ msg_cerr("%s: cannot erase partial pages: addr=%u, blocklen=%u\n", __func__, addr, blocklen); ++ return 1; ++ } ++ ++ if ((addr + blocklen) > total_size) { ++ msg_cerr("%s: tried to erase a block beyond flash boundary: addr=%u, blocklen=%u, size=%u\n", ++ __func__, addr, blocklen, total_size); ++ return 1; ++ } ++ ++ /* Needs typically about 35 ms for completion, so let's wait 100 ms in 500 us steps. */ ++ return at45db_erase(flash, AT45DB_PAGE_ERASE, at45db_convert_addr(addr, page_size), 500, 200); ++} ++ ++int spi_erase_at45db_block(struct flashctx *flash, unsigned int addr, unsigned int blocklen) ++{ ++ const unsigned int page_size = flash->chip->page_size; ++ const unsigned int total_size = flash->chip->total_size * 1024; ++ ++ if ((addr % page_size) != 0 || (blocklen % page_size) != 0) { // FIXME: should check blocks not pages ++ msg_cerr("%s: cannot erase partial pages: addr=%u, blocklen=%u\n", __func__, addr, blocklen); ++ return 1; ++ } ++ ++ if ((addr + blocklen) > total_size) { ++ msg_cerr("%s: tried to erase a block beyond flash boundary: addr=%u, blocklen=%u, size=%u\n", ++ __func__, addr, blocklen, total_size); ++ return 1; ++ } ++ ++ /* Needs typically between 20 and 100 ms for completion, so let's wait 300 ms in 1 ms steps. */ ++ return at45db_erase(flash, AT45DB_BLOCK_ERASE, at45db_convert_addr(addr, page_size), 1000, 300); ++} ++ ++int spi_erase_at45db_sector(struct flashctx *flash, unsigned int addr, unsigned int blocklen) ++{ ++ const unsigned int page_size = flash->chip->page_size; ++ const unsigned int total_size = flash->chip->total_size * 1024; ++ ++ if ((addr % page_size) != 0 || (blocklen % page_size) != 0) { // FIXME: should check sectors not pages ++ msg_cerr("%s: cannot erase partial pages: addr=%u, blocklen=%u\n", __func__, addr, blocklen); ++ return 1; ++ } ++ ++ if ((addr + blocklen) > total_size) { ++ msg_cerr("%s: tried to erase a sector beyond flash boundary: addr=%u, blocklen=%u, size=%u\n", ++ __func__, addr, blocklen, total_size); ++ return 1; ++ } ++ ++ /* Needs typically about 5 s for completion, so let's wait 20 seconds in 200 ms steps. */ ++ return at45db_erase(flash, AT45DB_SECTOR_ERASE, at45db_convert_addr(addr, page_size), 200000, 100); ++} ++ ++int spi_erase_at45db_chip(struct flashctx *flash, unsigned int addr, unsigned int blocklen) ++{ ++ const unsigned int total_size = flash->chip->total_size * 1024; ++ ++ if ((addr + blocklen) > total_size) { ++ msg_cerr("%s: tried to erase beyond flash boundary: addr=%u, blocklen=%u, size=%u\n", ++ __func__, addr, blocklen, total_size); ++ return 1; ++ } ++ ++ /* Needs typically from about 5 to over 60 s for completion, so let's wait 100 s in 500 ms steps. ++ * NB: the address is not a real address but a magic number. This hack allows to share code. */ ++ return at45db_erase(flash, AT45DB_CHIP_ERASE, AT45DB_CHIP_ERASE_ADDR, 500000, 200); ++} ++ ++/* This one is really special and works only for AT45CS1282. It uses two different opcodes depending on the ++ * address and has an asymmetric layout. */ ++int spi_erase_at45cs_sector(struct flashctx *flash, unsigned int addr, unsigned int blocklen) ++{ ++ const unsigned int page_size = flash->chip->page_size; ++ const unsigned int total_size = flash->chip->total_size * 1024; ++ const struct block_eraser be = flash->chip->block_erasers[0]; ++ const unsigned int sec_0a_top = be.eraseblocks[0].size; ++ const unsigned int sec_0b_top = be.eraseblocks[0].size + be.eraseblocks[1].size; ++ ++ if ((addr + blocklen) > total_size) { ++ msg_cerr("%s: tried to erase a sector beyond flash boundary: addr=%u, blocklen=%u, size=%u\n", ++ __func__, addr, blocklen, total_size); ++ return 1; ++ } ++ ++ bool partial_range = false; ++ uint8_t opcode = 0x7C; /* Used for all but sector 0a. */ ++ if (addr < sec_0a_top) { ++ opcode = 0x50; ++ /* One single sector of 8 pages at address 0. */ ++ if (addr != 0 || blocklen != (8 * page_size)) ++ partial_range = true; ++ } else if (addr < sec_0b_top) { ++ /* One single sector of 248 pages adjacent to the first. */ ++ if (addr != sec_0a_top || blocklen != (248 * page_size)) ++ partial_range = true; ++ } else { ++ /* The rest is filled by 63 aligned sectors of 256 pages. */ ++ if ((addr % (256 * page_size)) != 0 || (blocklen % (256 * page_size)) != 0) ++ partial_range = true; ++ } ++ if (partial_range) { ++ msg_cerr("%s: cannot erase partial sectors: addr=%u, blocklen=%u\n", __func__, addr, blocklen); ++ return 1; ++ } ++ ++ /* Needs up to 4 s for completion, so let's wait 20 seconds in 200 ms steps. */ ++ return at45db_erase(flash, opcode, at45db_convert_addr(addr, page_size), 200000, 100); ++} ++ ++static int at45db_fill_buffer1(struct flashctx *flash, uint8_t *bytes, unsigned int off, unsigned int len) ++{ ++ const unsigned int page_size = flash->chip->page_size; ++ if ((off + len) > page_size) { ++ msg_cerr("Tried to write %u bytes at offset %u into a buffer of only %u B.\n", ++ len, off, page_size); ++ return 1; ++ } ++ ++ /* Create a suitable buffer to store opcode, address and data chunks for buffer1. */ ++ const unsigned int max_data_write = flash->pgm->spi.max_data_write; ++ const unsigned int max_chunk = (max_data_write > 0 && max_data_write <= page_size) ? ++ max_data_write : page_size; ++ uint8_t buf[4 + max_chunk]; ++ ++ buf[0] = AT45DB_BUFFER1_WRITE; ++ while (off < page_size) { ++ unsigned int cur_chunk = min(max_chunk, page_size - off); ++ buf[1] = (off >> 16) & 0xff; ++ buf[2] = (off >> 8) & 0xff; ++ buf[3] = (off >> 0) & 0xff; ++ memcpy(&buf[4], bytes + off, cur_chunk); ++ int ret = spi_send_command(flash, 4 + cur_chunk, 0, buf, NULL); ++ if (ret != 0) { ++ msg_cerr("%s: error sending buffer write!\n", __func__); ++ return ret; ++ } ++ off += cur_chunk; ++ } ++ return 0; ++} ++ ++static int at45db_commit_buffer1(struct flashctx *flash, unsigned int at45db_addr) ++{ ++ const uint8_t cmd[] = { ++ AT45DB_BUFFER1_PAGE_PROGRAM, ++ (at45db_addr >> 16) & 0xff, ++ (at45db_addr >> 8) & 0xff, ++ (at45db_addr >> 0) & 0xff ++ }; ++ ++ /* Send buffer to device. */ ++ int ret = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL); ++ if (ret != 0) { ++ msg_cerr("%s: error sending buffer to main memory command!\n", __func__); ++ return ret; ++ } ++ ++ /* Wait for completion (typically a few ms). */ ++ ret = at45db_wait_ready(flash, 250, 200); // 50 ms ++ if (ret != 0) { ++ msg_cerr("%s: chip did not became ready again!\n", __func__); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int at45db_program_page(struct flashctx *flash, uint8_t *buf, unsigned int at45db_addr) ++{ ++ int ret = at45db_fill_buffer1(flash, buf, 0, flash->chip->page_size); ++ if (ret != 0) { ++ msg_cerr("%s: filling the buffer failed!\n", __func__); ++ return ret; ++ } ++ ++ ret = at45db_commit_buffer1(flash, at45db_addr); ++ if (ret != 0) { ++ msg_cerr("%s: committing page failed!\n", __func__); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++int spi_write_at45db(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) ++{ ++ const unsigned int page_size = flash->chip->page_size; ++ const unsigned int total_size = flash->chip->total_size; ++ ++ if ((start % page_size) != 0 || (len % page_size) != 0) { ++ msg_cerr("%s: cannot write partial pages: start=%u, len=%u\n", __func__, start, len); ++ return 1; ++ } ++ ++ if ((start + len) > (total_size * 1024)) { ++ msg_cerr("%s: tried to write beyond flash boundary: start=%u, len=%u, size=%u\n", ++ __func__, start, len, total_size); ++ return 1; ++ } ++ ++ unsigned int i; ++ for (i = 0; i < len; i += page_size) { ++ if (at45db_program_page(flash, buf + i, at45db_convert_addr(start + i, page_size)) != 0) { ++ msg_cerr("Writing page %u failed!\n", i); ++ return 1; ++ } ++ } ++ return 0; ++} +diff --git a/atahpt.c b/atahpt.c +index f8be8c4..242e14a 100644 +--- a/atahpt.c ++++ b/atahpt.c +@@ -69,6 +69,8 @@ int atahpt_init(void) + return 1; + + io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_4); ++ if (!io_base_addr) ++ return 1; + + /* Enable flash access. */ + reg32 = pci_read_long(dev, REG_FLASH_ACCESS); +diff --git a/board_enable.c b/board_enable.c +index 074cabb..e2a5fe2 100644 +--- a/board_enable.c ++++ b/board_enable.c +@@ -1488,6 +1488,7 @@ static int intel_ich_gpio_set(int gpio, int raise) + {0x24D0, 0x58, 0x1BFF0000, 0x00030305, 0}, /* 82801EB/ER (ICH5/ICH5R) */ + {0x2640, 0x48, 0x1BFF0000, 0x00030307, 0}, /* 82801FB/FR (ICH6/ICH6R) */ + {0x2641, 0x48, 0x1BFF0000, 0x00030307, 0}, /* 82801FBM (ICH6M) */ ++ {0x27B0, 0x48, 0xFFFFFFFF, 0x000300FF, 0}, /* 82801GDH (ICH7 DH) */ + {0x27B8, 0x48, 0xFFFFFFFF, 0x000300FF, 0}, /* 82801GB/GR (ICH7 Family) */ + {0x27B9, 0x48, 0xFFEBFFFE, 0x000300FE, 0}, /* 82801GBM (ICH7-M) */ + {0x27BD, 0x48, 0xFFEBFFFE, 0x000300FE, 0}, /* 82801GHM (ICH7-M DH) */ +@@ -1665,6 +1666,7 @@ static int intel_ich_gpio_set(int gpio, int raise) + * - abit IP35 Pro: Intel P35 + ICH9R + * - ASUS P5LD2 + * - ASUS P5LD2-VM ++ * - ASUS P5LD2-VM DH + */ + static int intel_ich_gpio16_raise(void) + { +@@ -2266,13 +2268,13 @@ static int p2_whitelist_laptop(void) + * NOTE: Please add boards that _don't_ need such enables or don't work yet + * to the respective tables in print.c. Thanks! + * +- * We use 2 sets of IDs here, you're free to choose which is which. This ++ * We use 2 sets of PCI IDs here, you're free to choose which is which. This + * is to provide a very high degree of certainty when matching a board on + * the basis of subsystem/card IDs. As not every vendor handles + * subsystem/card IDs in a sane manner. + * + * Keep the second set NULLed if it should be ignored. Keep the subsystem IDs +- * NULLed if they don't identify the board fully and if you can't use DMI. ++ * and the dmi identifier NULLed if they don't identify the board fully to disable autodetection. + * But please take care to provide an as complete set of pci ids as possible; + * autodetection is the preferred behaviour and we would like to make sure that + * matches are unique. +@@ -2306,6 +2308,7 @@ const struct board_match board_matches[] = { + #if defined(__i386__) || defined(__x86_64__) + {0x10DE, 0x0547, 0x147B, 0x1C2F, 0x10DE, 0x0548, 0x147B, 0x1C2F, NULL, NULL, NULL, P3, "abit", "AN-M2", 0, NT, nvidia_mcp_gpio2_raise}, + {0x1106, 0x0282, 0x147B, 0x1415, 0x1106, 0x3227, 0x147B, 0x1415, "^AV8 ", NULL, NULL, P3, "abit", "AV8", 0, OK, board_abit_av8}, ++ {0x8086, 0x7190, 0, 0, 0x8086, 0x7110, 0, 0, NULL /* "^I440BX-W977$" */, "abit", "bf6", P3, "abit", "BF6", 0, OK, intel_piix4_gpo26_lower}, + {0x8086, 0x7190, 0, 0, 0x8086, 0x7110, 0, 0, "^i440BX-W977 (BM6)$", NULL, NULL, P3, "abit", "BM6", 0, OK, intel_piix4_gpo26_lower}, + {0x8086, 0x24d3, 0x147b, 0x1014, 0x8086, 0x2578, 0x147b, 0x1014, NULL, NULL, NULL, P3, "abit", "IC7", 0, NT, intel_ich_gpio23_raise}, + {0x8086, 0x2930, 0x147b, 0x1084, 0x11ab, 0x4364, 0x147b, 0x1084, NULL, NULL, NULL, P3, "abit", "IP35", 0, OK, intel_ich_gpio16_raise}, +@@ -2330,6 +2333,7 @@ const struct board_match board_matches[] = { + {0x8086, 0x2570, 0x1849, 0x2570, 0x8086, 0x24d3, 0x1849, 0x24d0, NULL, NULL, NULL, P3, "ASRock", "775i65G", 0, OK, intel_ich_gpio23_raise}, + {0x10DE, 0x0060, 0x1043, 0x80AD, 0x10DE, 0x01E0, 0x1043, 0x80C0, NULL, NULL, NULL, P3, "ASUS", "A7N8X-VM/400", 0, OK, it8712f_gpio12_raise}, + {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3065, 0x1043, 0x80ED, NULL, NULL, NULL, P3, "ASUS", "A7V600-X", 0, OK, it8712f_gpio31_raise}, ++ {0x1106, 0x3177, 0x1043, 0x80F9, 0x1106, 0x3205, 0x1043, 0x80F9, NULL, NULL, NULL, P3, "ASUS", "A7V8X-MX", 0, OK, w836xx_memw_enable_2e}, + {0x1106, 0x3177, 0x1043, 0x80A1, 0x1106, 0x3205, 0x1043, 0x8118, NULL, NULL, NULL, P3, "ASUS", "A7V8X-MX SE", 0, OK, w836xx_memw_enable_2e}, + {0x1106, 0x3189, 0x1043, 0x807F, 0x1106, 0x3177, 0x1043, 0x808C, NULL, NULL, NULL, P3, "ASUS", "A7V8X", 0, OK, it8703f_gpio51_raise}, + {0x1106, 0x3099, 0x1043, 0x807F, 0x1106, 0x3147, 0x1043, 0x808C, NULL, NULL, NULL, P3, "ASUS", "A7V333", 0, OK, it8703f_gpio51_raise}, +@@ -2372,12 +2376,14 @@ const struct board_match board_matches[] = { + {0x8086, 0x27b8, 0x1043, 0x2a22, 0x8086, 0x2770, 0x1043, 0x2a22, "^P5LP-LE$", NULL, NULL, P3, "ASUS", "P5LP-LE (Epson OEM)", 0, OK, intel_ich_gpio34_raise}, + {0x8086, 0x27da, 0x1043, 0x8179, 0x8086, 0x27b8, 0x1043, 0x8179, "^P5LD2$", NULL, NULL, P3, "ASUS", "P5LD2", 0, NT, intel_ich_gpio16_raise}, + {0x8086, 0x27da, 0x1043, 0x8179, 0x8086, 0x27b8, 0x1043, 0x8179, "^P5LD2-VM$", NULL, NULL, P3, "ASUS", "P5LD2-VM", 0, NT, intel_ich_gpio16_raise}, ++ {0x8086, 0x27b0, 0x1043, 0x8179, 0x8086, 0x2770, 0x1043, 0x817a, "^P5LD2-VM DH$", NULL, NULL, P3, "ASUS", "P5LD2-VM DH", 0, OK, intel_ich_gpio16_raise}, + {0x10DE, 0x0030, 0x1043, 0x818a, 0x8086, 0x100E, 0x1043, 0x80EE, NULL, NULL, NULL, P3, "ASUS", "P5ND2-SLI Deluxe", 0, OK, nvidia_mcp_gpio10_raise}, + {0x10DE, 0x0260, 0x1043, 0x81BC, 0x10DE, 0x026C, 0x1043, 0x829E, "^P5N-D$", NULL, NULL, P3, "ASUS", "P5N-D", 0, OK, it8718f_gpio63_raise}, + {0x10DE, 0x0260, 0x1043, 0x81BC, 0x10DE, 0x026C, 0x1043, 0x8249, "^P5N-E SLI$",NULL, NULL, P3, "ASUS", "P5N-E SLI", 0, NT, it8718f_gpio63_raise}, + {0x8086, 0x24dd, 0x1043, 0x80a6, 0x8086, 0x2570, 0x1043, 0x8157, NULL, NULL, NULL, P3, "ASUS", "P5PE-VM", 0, OK, intel_ich_gpio21_raise}, + {0x8086, 0x2443, 0x1043, 0x8027, 0x8086, 0x1130, 0x1043, 0x8027, "^CUSL2-C", NULL, NULL, P3, "ASUS", "CUSL2-C", 0, OK, intel_ich_gpio21_raise}, + {0x8086, 0x2443, 0x1043, 0x8027, 0x8086, 0x1130, 0x1043, 0x8027, "^TUSL2-C", NULL, NULL, P3, "ASUS", "TUSL2-C", 0, NT, intel_ich_gpio21_raise}, ++ {0x1106, 0x3059, 0x1106, 0x4161, 0x1106, 0x3065, 0x1106, 0x0102, NULL, NULL, NULL, P3, "Bcom/Clientron", "WinNET P680", 0, OK, w836xx_memw_enable_2e}, + {0x1106, 0x3177, 0x1106, 0x3177, 0x1106, 0x3116, 0x1106, 0x3116, "^KM266-8235$", "biostar", "m7viq", P3, "Biostar", "M7VIQ", 0, NT, w83697xx_memw_enable_2e}, + {0x10b7, 0x9055, 0x1028, 0x0082, 0x8086, 0x7190, 0, 0, NULL, NULL, NULL, P3, "Dell", "OptiPlex GX1", 0, OK, intel_piix4_gpo30_lower}, + {0x8086, 0x3590, 0x1028, 0x016c, 0x1000, 0x0030, 0x1028, 0x016c, NULL, NULL, NULL, P3, "Dell", "PowerEdge 1850", 0, OK, intel_ich_gpio23_raise}, +@@ -2452,6 +2458,12 @@ const struct board_match board_matches[] = { + {0x1106, 0x0259, 0x1106, 0xAA07, 0x1106, 0x3227, 0x1106, 0xAA07, NULL, NULL, NULL, P3, "VIA", "EPIA EK", 0, NT, via_vt823x_gpio9_raise}, + {0x1106, 0x3177, 0x1106, 0xAA01, 0x1106, 0x3123, 0x1106, 0xAA01, NULL, NULL, NULL, P3, "VIA", "EPIA M/MII/...", 0, OK, via_vt823x_gpio15_raise}, + {0x1106, 0x0259, 0x1106, 0x3227, 0x1106, 0x3065, 0x1106, 0x3149, NULL, NULL, NULL, P3, "VIA", "EPIA-N/NL", 0, OK, via_vt823x_gpio9_raise}, ++#ifdef DELL_AVOTON_SUPPORT ++ {0x8086, 0x1f38, 0x8086, 0x7270, 0, 0, 0, 0, NULL, NULL, NULL, P2, "DELL", "AVOTON", 0, OK, p2_not_a_laptop}, ++#endif ++#if DELL_DENVERTON_SUPPORT == 1 ++ {0x8086, 0x19dc, 0x8086, 0x7270, 0, 0, 0, 0, NULL, NULL, NULL, P2, "DELL", "DENVERTON", 0, OK, p2_not_a_laptop}, ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + #endif + { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, P3, NULL, NULL, 0, NT, NULL}, /* end marker */ + }; +@@ -2559,6 +2571,7 @@ const static struct board_match *board_match_pci_ids(enum board_match_phase phas + } + } + ++#if defined(__i386__) || defined(__x86_64__) + if (board->dmi_pattern) { + if (!has_dmi_support) { + msg_pwarn("Warning: Can't autodetect %s %s, DMI info unavailable.\n", +@@ -2571,7 +2584,7 @@ const static struct board_match *board_match_pci_ids(enum board_match_phase phas + continue; + } + } +- ++#endif // defined(__i386__) || defined(__x86_64__) + return board; + } + +diff --git a/buspirate_spi.c b/buspirate_spi.c +index 9d229f4..f0e84bc 100644 +--- a/buspirate_spi.c ++++ b/buspirate_spi.c +@@ -250,6 +250,7 @@ int buspirate_spi_init(void) + if (!bp_commbuf) { + bp_commbufsize = 0; + msg_perr("Out of memory!\n"); ++ free(dev); + return ERROR_OOM; + } + bp_commbufsize = DEFAULT_BUFSIZE; +@@ -263,8 +264,12 @@ int buspirate_spi_init(void) + return ret; + } + +- if (register_shutdown(buspirate_spi_shutdown, NULL)) ++ if (register_shutdown(buspirate_spi_shutdown, NULL) != 0) { ++ bp_commbufsize = 0; ++ free(bp_commbuf); ++ bp_commbuf = NULL; + return 1; ++ } + + /* This is the brute force version, but it should work. + * It is likely to fail if a previous flashrom run was aborted during a write with the new SPI commands +diff --git a/cbtable.c b/cbtable.c +index e262a84..c100bbb 100644 +--- a/cbtable.c ++++ b/cbtable.c +@@ -261,7 +261,7 @@ int cb_parse_table(const char **vendor, const char **model) + #else + start = 0x0; + #endif +- table_area = physmap_try_ro("low megabyte", start, BYTES_TO_MAP - start); ++ table_area = physmap_ro_unaligned("low megabyte", start, BYTES_TO_MAP - start); + if (ERROR_PTR == table_area) { + msg_perr("Failed getting access to coreboot low tables.\n"); + return -1; +@@ -276,8 +276,9 @@ int cb_parse_table(const char **vendor, const char **model) + if (forward->tag == LB_TAG_FORWARD) { + start = forward->forward; + start &= ~(getpagesize() - 1); +- physunmap(table_area, BYTES_TO_MAP); +- table_area = physmap_try_ro("high tables", start, BYTES_TO_MAP); ++ physunmap_unaligned(table_area, BYTES_TO_MAP); ++ // FIXME: table_area is never unmapped below, nor is it unmapped above in the no-forward case ++ table_area = physmap_ro_unaligned("high tables", start, BYTES_TO_MAP); + if (ERROR_PTR == table_area) { + msg_perr("Failed getting access to coreboot high tables.\n"); + return -1; +diff --git a/chipdrivers.h b/chipdrivers.h +index 091d14c..851e90a 100644 +--- a/chipdrivers.h ++++ b/chipdrivers.h +@@ -64,6 +64,7 @@ int spi_write_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, + /* spi25_statusreg.c */ + uint8_t spi_read_status_register(struct flashctx *flash); + int spi_write_status_register(struct flashctx *flash, int status); ++void spi_prettyprint_status_register_bit(uint8_t status, int bit); + int spi_prettyprint_status_register_plain(struct flashctx *flash); + int spi_prettyprint_status_register_default_welwip(struct flashctx *flash); + int spi_prettyprint_status_register_default_bp1(struct flashctx *flash); +@@ -109,6 +110,19 @@ int read_opaque(struct flashctx *flash, uint8_t *buf, unsigned int start, unsign + int write_opaque(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); + int erase_opaque(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen); + ++/* at45db.c */ ++int probe_spi_at45db(struct flashctx *flash); ++int spi_prettyprint_status_register_at45db(struct flashctx *flash); ++int spi_disable_blockprotect_at45db(struct flashctx *flash); ++int spi_read_at45db(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); ++int spi_read_at45db_e8(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); ++int spi_write_at45db(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); ++int spi_erase_at45db_page(struct flashctx *flash, unsigned int addr, unsigned int blocklen); ++int spi_erase_at45db_block(struct flashctx *flash, unsigned int addr, unsigned int blocklen); ++int spi_erase_at45db_sector(struct flashctx *flash, unsigned int addr, unsigned int blocklen); ++int spi_erase_at45db_chip(struct flashctx *flash, unsigned int addr, unsigned int blocklen); ++int spi_erase_at45cs_sector(struct flashctx *flash, unsigned int addr, unsigned int blocklen); ++ + /* 82802ab.c */ + uint8_t wait_82802ab(struct flashctx *flash); + int probe_82802ab(struct flashctx *flash); +@@ -179,9 +193,10 @@ int printlock_at49f(struct flashctx *flash); + /* w29ee011.c */ + int probe_w29ee011(struct flashctx *flash); + +-/* stm50flw0x0x.c */ +-int erase_sector_stm50flw0x0x(struct flashctx *flash, unsigned int block, unsigned int blocksize); +-int unlock_stm50flw0x0x(struct flashctx *flash); ++/* stm50.c */ ++int erase_sector_stm50(struct flashctx *flash, unsigned int block, unsigned int blocksize); ++int unlock_stm50_uniform(struct flashctx *flash); ++int unlock_stm50_nonuniform(struct flashctx *flash); + + /* en29lv640b.c */ + int probe_en29lv640b(struct flashctx *flash); +diff --git a/chipset_enable.c b/chipset_enable.c +index a2df263..8a8ab66 100644 +--- a/chipset_enable.c ++++ b/chipset_enable.c +@@ -41,6 +41,17 @@ + + #if defined(__i386__) || defined(__x86_64__) + ++#if DELL_AVOTON_SUPPORT == 1 ++uint8_t is_avoton = 0; ++#endif /* DELL_AVOTON_SUPPORT == 1 */ ++ ++#if DELL_DENVERTON_SUPPORT == 1 ++uint8_t is_dnv = 0; ++uint32_t dnv_bios_region_start = 0x00; ++uint32_t dnv_bios_region_size = 0x00; ++uint32_t dnv_bios_region_limit = 0x00; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + static int enable_flash_ali_m1533(struct pci_dev *dev, const char *name) + { + uint8_t tmp; +@@ -260,20 +271,44 @@ static int enable_flash_piix4(struct pci_dev *dev, const char *name) + return 0; + } + +-/* +- * See ie. page 375 of "Intel I/O Controller Hub 7 (ICH7) Family Datasheet" +- * http://download.intel.com/design/chipsets/datashts/30701303.pdf +- */ +-static int enable_flash_ich(struct pci_dev *dev, const char *name, uint8_t bios_cntl) ++/* Note: the ICH0-ICH5 BIOS_CNTL register is actually 16 bit wide, in Poulsbo, Tunnel Creek and other Atom ++ * chipsets/SoCs it is even 32b, but just treating it as 8 bit wide seems to work fine in practice. */ ++static int enable_flash_ich_bios_cntl(struct pci_dev *dev, enum ich_chipset ich_generation, uint8_t bios_cntl) + { + uint8_t old, new, wanted; + +- /* +- * Note: the ICH0-ICH5 BIOS_CNTL register is actually 16 bit wide, in Tunnel Creek it is even 32b, but +- * just treating it as 8 bit wide seems to work fine in practice. +- */ +- wanted = old = pci_read_byte(dev, bios_cntl); ++ switch (ich_generation) { ++ case CHIPSET_ICH_UNKNOWN: ++ return ERROR_FATAL; ++ /* Non-SPI-capable */ ++ case CHIPSET_ICH: ++ case CHIPSET_ICH2345: ++ break; ++ /* Atom chipsets are special: The second byte of BIOS_CNTL (D9h) contains a prefetch bit similar to what ++ * other SPI-capable chipsets have at DCh. ++ * The Tunnel Creek datasheet contains a lot of details about the SPI controller, among other things it ++ * mentions that the prefetching and caching does only happen for direct memory reads. ++ * Therefore - at least for Tunnel Creek - it should not matter to flashrom because we use the ++ * programmed access only and not memory mapping. */ ++ case CHIPSET_TUNNEL_CREEK: ++ case CHIPSET_POULSBO: ++ case CHIPSET_CENTERTON: ++ old = pci_read_byte(dev, bios_cntl + 1); ++ msg_pdbg("BIOS Prefetch Enable: %sabled, ", (old & 1) ? "en" : "dis"); ++ break; ++ case CHIPSET_ICH7: ++ default: /* Future version might behave the same */ ++ old = (pci_read_byte(dev, bios_cntl) >> 2) & 0x3; ++ msg_pdbg("SPI Read Configuration: "); ++ if (old == 3) ++ msg_pdbg("invalid prefetching/caching settings, "); ++ else ++ msg_pdbg("prefetching %sabled, caching %sabled, ", ++ (old & 0x2) ? "en" : "dis", ++ (old & 0x1) ? "dis" : "en"); ++ } + ++ wanted = old = pci_read_byte(dev, bios_cntl); + /* + * Quote from the 6 Series datasheet (Document Number: 324645-004): + * "Bit 5: SMM BIOS Write Protect Disable (SMM_BWP) +@@ -283,11 +318,23 @@ static int enable_flash_ich(struct pci_dev *dev, const char *name, uint8_t bios_ + * + * Try to unset it in any case. + * It won't hurt and makes sense in some cases according to Stefan Reinauer. ++ * ++ * At least in Centerton aforementioned bit is located at bit 7. It is unspecified in all other Atom ++ * and Desktop chipsets before Ibex Peak/5 Series, but we reset bit 5 anyway. + */ +- wanted &= ~(1 << 5); ++ int smm_bwp_bit; ++ if (ich_generation == CHIPSET_CENTERTON) ++ smm_bwp_bit = 7; ++ else ++ smm_bwp_bit = 5; ++ wanted &= ~(1 << smm_bwp_bit); + +- /* Set BIOS Write Enable */ +- wanted |= (1 << 0); ++ /* Tunnel Creek has a cache disable at bit 2 of the lowest BIOS_CNTL byte. */ ++ if (ich_generation == CHIPSET_TUNNEL_CREEK) ++ wanted |= (1 << 2); ++ ++ wanted |= (1 << 0); /* Set BIOS Write Enable */ ++ wanted &= ~(1 << 1); /* Disable lock (futile) */ + + /* Only write the register if it's necessary */ + if (wanted != old) { +@@ -299,64 +346,79 @@ static int enable_flash_ich(struct pci_dev *dev, const char *name, uint8_t bios_ + msg_pdbg("\nBIOS_CNTL = 0x%02x: ", new); + msg_pdbg("BIOS Lock Enable: %sabled, ", (new & (1 << 1)) ? "en" : "dis"); + msg_pdbg("BIOS Write Enable: %sabled\n", (new & (1 << 0)) ? "en" : "dis"); +- if (new & (1 << 5)) ++ if (new & (1 << smm_bwp_bit)) + msg_pwarn("Warning: BIOS region SMM protection is enabled!\n"); + +- + if (new != wanted) +- msg_pwarn("Warning: Setting Bios Control at 0x%x from 0x%02x to 0x%02x on %s failed.\n" +- "New value is 0x%02x.\n", bios_cntl, old, wanted, name, new); ++ msg_pwarn("Warning: Setting Bios Control at 0x%x from 0x%02x to 0x%02x failed.\n" ++ "New value is 0x%02x.\n", bios_cntl, old, wanted, new); + +- /* Return an error if we could not set the write enable */ ++ /* Return an error if we could not set the write enable only. */ + if (!(new & (1 << 0))) + return -1; + + return 0; + } + +-static int enable_flash_ich_4e(struct pci_dev *dev, const char *name) ++static int enable_flash_ich_fwh_decode(struct pci_dev *dev, enum ich_chipset ich_generation) + { +- /* +- * Note: ICH5 has registers similar to FWH_SEL1, FWH_SEL2 and +- * FWH_DEC_EN1, but they are called FB_SEL1, FB_SEL2, FB_DEC_EN1 and +- * FB_DEC_EN2. +- */ +- internal_buses_supported = BUS_FWH; +- return enable_flash_ich(dev, name, 0x4e); +-} +- +-static int enable_flash_ich_dc(struct pci_dev *dev, const char *name) +-{ +- uint32_t fwh_conf; +- int i, tmp; +- char *idsel = NULL; +- int max_decode_fwh_idsel = 0, max_decode_fwh_decode = 0; +- int contiguous = 1; ++ uint8_t fwh_sel1 = 0, fwh_sel2 = 0, fwh_dec_en_lo = 0, fwh_dec_en_hi = 0; /* silence compilers */ ++ bool implemented = 0; ++ switch (ich_generation) { ++ case CHIPSET_ICH: ++ /* FIXME: Unlike later chipsets, ICH and ICH-0 do only support mapping of the top-most 4MB ++ * and therefore do only feature FWH_DEC_EN (E3h, different default too) and FWH_SEL (E8h). */ ++ break; ++ case CHIPSET_ICH2345: ++ fwh_sel1 = 0xe8; ++ fwh_sel2 = 0xee; ++ fwh_dec_en_lo = 0xf0; ++ fwh_dec_en_hi = 0xe3; ++ implemented = 1; ++ break; ++ case CHIPSET_POULSBO: ++ case CHIPSET_TUNNEL_CREEK: ++ /* FIXME: Similar to ICH and ICH-0, Tunnel Creek and Poulsbo do only feature one register each, ++ * FWH_DEC_EN (D7h) and FWH_SEL (D0h). */ ++ break; ++ case CHIPSET_CENTERTON: ++ /* FIXME: Similar to above FWH_DEC_EN (D4h) and FWH_SEL (D0h). */ ++ break; ++ case CHIPSET_ICH6: ++ case CHIPSET_ICH7: ++ default: /* Future version might behave the same */ ++ fwh_sel1 = 0xd0; ++ fwh_sel2 = 0xd4; ++ fwh_dec_en_lo = 0xd8; ++ fwh_dec_en_hi = 0xd9; ++ implemented = 1; ++ break; ++ } + +- idsel = extract_programmer_param("fwh_idsel"); ++ char *idsel = extract_programmer_param("fwh_idsel"); + if (idsel && strlen(idsel)) { +- uint64_t fwh_idsel_old, fwh_idsel; ++ if (!implemented) { ++ msg_perr("Error: fwh_idsel= specified, but (yet) unsupported on this chipset.\n"); ++ goto idsel_garbage_out; ++ } + errno = 0; + /* Base 16, nothing else makes sense. */ +- fwh_idsel = (uint64_t)strtoull(idsel, NULL, 16); ++ uint64_t fwh_idsel = (uint64_t)strtoull(idsel, NULL, 16); + if (errno) { +- msg_perr("Error: fwh_idsel= specified, but value could " +- "not be converted.\n"); ++ msg_perr("Error: fwh_idsel= specified, but value could not be converted.\n"); + goto idsel_garbage_out; + } + if (fwh_idsel & 0xffff000000000000ULL) { +- msg_perr("Error: fwh_idsel= specified, but value had " +- "unused bits set.\n"); ++ msg_perr("Error: fwh_idsel= specified, but value had unused bits set.\n"); + goto idsel_garbage_out; + } +- fwh_idsel_old = pci_read_long(dev, 0xd0); ++ uint64_t fwh_idsel_old = pci_read_long(dev, fwh_sel1); + fwh_idsel_old <<= 16; +- fwh_idsel_old |= pci_read_word(dev, 0xd4); +- msg_pdbg("\nSetting IDSEL from 0x%012" PRIx64 " to " +- "0x%012" PRIx64 " for top 16 MB.", fwh_idsel_old, +- fwh_idsel); +- rpci_write_long(dev, 0xd0, (fwh_idsel >> 16) & 0xffffffff); +- rpci_write_word(dev, 0xd4, fwh_idsel & 0xffff); ++ fwh_idsel_old |= pci_read_word(dev, fwh_sel2); ++ msg_pdbg("\nSetting IDSEL from 0x%012" PRIx64 " to 0x%012" PRIx64 " for top 16 MB.", ++ fwh_idsel_old, fwh_idsel); ++ rpci_write_long(dev, fwh_sel1, (fwh_idsel >> 16) & 0xffffffff); ++ rpci_write_word(dev, fwh_sel2, fwh_idsel & 0xffff); + /* FIXME: Decode settings are not changed. */ + } else if (idsel) { + msg_perr("Error: fwh_idsel= specified, but no value given.\n"); +@@ -366,15 +428,23 @@ idsel_garbage_out: + } + free(idsel); + ++ if (!implemented) { ++ msg_pdbg2("FWH IDSEL handling is not implemented on this chipset."); ++ return 0; ++ } ++ + /* Ignore all legacy ranges below 1 MB. + * We currently only support flashing the chip which responds to + * IDSEL=0. To support IDSEL!=0, flashbase and decode size calculations + * have to be adjusted. + */ ++ int max_decode_fwh_idsel = 0, max_decode_fwh_decode = 0; ++ bool contiguous = 1; ++ uint32_t fwh_conf = pci_read_long(dev, fwh_sel1); ++ int i; + /* FWH_SEL1 */ +- fwh_conf = pci_read_long(dev, 0xd0); + for (i = 7; i >= 0; i--) { +- tmp = (fwh_conf >> (i * 4)) & 0xf; ++ int tmp = (fwh_conf >> (i * 4)) & 0xf; + msg_pdbg("\n0x%08x/0x%08x FWH IDSEL: 0x%x", + (0x1ff8 + i) * 0x80000, + (0x1ff0 + i) * 0x80000, +@@ -386,9 +456,9 @@ idsel_garbage_out: + } + } + /* FWH_SEL2 */ +- fwh_conf = pci_read_word(dev, 0xd4); ++ fwh_conf = pci_read_word(dev, fwh_sel2); + for (i = 3; i >= 0; i--) { +- tmp = (fwh_conf >> (i * 4)) & 0xf; ++ int tmp = (fwh_conf >> (i * 4)) & 0xf; + msg_pdbg("\n0x%08x/0x%08x FWH IDSEL: 0x%x", + (0xff4 + i) * 0x100000, + (0xff0 + i) * 0x100000, +@@ -401,9 +471,11 @@ idsel_garbage_out: + } + contiguous = 1; + /* FWH_DEC_EN1 */ +- fwh_conf = pci_read_word(dev, 0xd8); ++ fwh_conf = pci_read_byte(dev, fwh_dec_en_hi); ++ fwh_conf <<= 8; ++ fwh_conf |= pci_read_byte(dev, fwh_dec_en_lo); + for (i = 7; i >= 0; i--) { +- tmp = (fwh_conf >> (i + 0x8)) & 0x1; ++ int tmp = (fwh_conf >> (i + 0x8)) & 0x1; + msg_pdbg("\n0x%08x/0x%08x FWH decode %sabled", + (0x1ff8 + i) * 0x80000, + (0x1ff0 + i) * 0x80000, +@@ -415,7 +487,7 @@ idsel_garbage_out: + } + } + for (i = 3; i >= 0; i--) { +- tmp = (fwh_conf >> i) & 0x1; ++ int tmp = (fwh_conf >> i) & 0x1; + msg_pdbg("\n0x%08x/0x%08x FWH decode %sabled", + (0xff4 + i) * 0x100000, + (0xff0 + i) * 0x100000, +@@ -429,99 +501,66 @@ idsel_garbage_out: + max_rom_decode.fwh = min(max_decode_fwh_idsel, max_decode_fwh_decode); + msg_pdbg("\nMaximum FWH chip size: 0x%x bytes", max_rom_decode.fwh); + +- /* If we're called by enable_flash_ich_dc_spi, it will override +- * internal_buses_supported anyway. +- */ +- internal_buses_supported = BUS_FWH; +- return enable_flash_ich(dev, name, 0xdc); ++ return 0; + } + +-static int enable_flash_poulsbo(struct pci_dev *dev, const char *name) ++static int enable_flash_ich_fwh(struct pci_dev *dev, enum ich_chipset ich_generation, uint8_t bios_cntl) + { +- uint16_t old, new; + int err; + +- if ((err = enable_flash_ich(dev, name, 0xd8)) != 0) ++ /* Configure FWH IDSEL decoder maps. */ ++ if ((err = enable_flash_ich_fwh_decode(dev, ich_generation)) != 0) + return err; + +- old = pci_read_byte(dev, 0xd9); +- msg_pdbg("BIOS Prefetch Enable: %sabled, ", +- (old & 1) ? "en" : "dis"); +- new = old & ~1; +- +- if (new != old) +- rpci_write_byte(dev, 0xd9, new); +- + internal_buses_supported = BUS_FWH; +- return 0; ++ return enable_flash_ich_bios_cntl(dev, ich_generation, bios_cntl); + } + +-static int enable_flash_tunnelcreek(struct pci_dev *dev, const char *name) ++static int enable_flash_ich0(struct pci_dev *dev, const char *name) + { +- uint16_t old, new; +- uint32_t tmp, bnt; +- void *rcrb; +- int ret; +- +- /* Enable Flash Writes */ +- ret = enable_flash_ich(dev, name, 0xd8); +- if (ret == ERROR_FATAL) +- return ret; +- +- /* Make sure BIOS prefetch mechanism is disabled */ +- old = pci_read_byte(dev, 0xd9); +- msg_pdbg("BIOS Prefetch Enable: %sabled, ", (old & 1) ? "en" : "dis"); +- new = old & ~1; +- if (new != old) +- rpci_write_byte(dev, 0xd9, new); +- +- /* Get physical address of Root Complex Register Block */ +- tmp = pci_read_long(dev, 0xf0) & 0xffffc000; +- msg_pdbg("\nRoot Complex Register Block address = 0x%x\n", tmp); +- +- /* Map RCBA to virtual memory */ +- rcrb = physmap("ICH RCRB", tmp, 0x4000); +- +- /* Test Boot BIOS Strap Status */ +- bnt = mmio_readl(rcrb + 0x3410); +- if (bnt & 0x02) { +- /* If strapped to LPC, no SPI initialization is required */ +- internal_buses_supported = BUS_FWH; +- return 0; +- } ++ return enable_flash_ich_fwh(dev, CHIPSET_ICH, 0x4e); ++} + +- /* This adds BUS_SPI */ +- if (ich_init_spi(dev, tmp, rcrb, 7) != 0) { +- if (!ret) +- ret = ERROR_NONFATAL; +- } ++static int enable_flash_ich2345(struct pci_dev *dev, const char *name) ++{ ++ return enable_flash_ich_fwh(dev, CHIPSET_ICH2345, 0x4e); ++} + +- return ret; ++static int enable_flash_ich6(struct pci_dev *dev, const char *name) ++{ ++ return enable_flash_ich_fwh(dev, CHIPSET_ICH6, 0xdc); + } + +-static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name, +- enum ich_chipset ich_generation) ++static int enable_flash_poulsbo(struct pci_dev *dev, const char *name) + { +- int ret, ret_spi; +- uint8_t bbs, buc; +- uint32_t tmp, gcs; +- void *rcrb; +- const char *const *straps_names; ++ return enable_flash_ich_fwh(dev, CHIPSET_POULSBO, 0xd8); ++} + ++static int enable_flash_ich_spi(struct pci_dev *dev, enum ich_chipset ich_generation, uint8_t bios_cntl) ++{ + static const char *const straps_names_EP80579[] = { "SPI", "reserved", "reserved", "LPC" }; + static const char *const straps_names_ich7_nm10[] = { "reserved", "SPI", "PCI", "LPC" }; ++ static const char *const straps_names_tunnel_creek[] = { "SPI", "LPC" }; + static const char *const straps_names_ich8910[] = { "SPI", "SPI", "PCI", "LPC" }; + static const char *const straps_names_pch567[] = { "LPC", "reserved", "PCI", "SPI" }; + static const char *const straps_names_pch8[] = { "LPC", "reserved", "reserved", "SPI" }; +- static const char *const straps_names_pch8_lp[] = { "SPI", "LPC", "unknown", "unknown" }; ++ static const char *const straps_names_pch8_lp[] = { "SPI", "LPC" }; + static const char *const straps_names_unknown[] = { "unknown", "unknown", "unknown", "unknown" }; ++#ifdef DELL_AVOTON_SUPPORT ++ static const char *const straps_names_avoton[] = { "LPC", "reserved", "reserved", "SPI" }; ++ uint32_t tmp; ++ int ret_fwh = 0; ++ uint32_t new, old; ++ void *spibar; ++#endif + ++ const char *const *straps_names; + switch (ich_generation) { + case CHIPSET_ICH7: + /* EP80579 may need further changes, but this is the least + * intrusive way to get correct BOOT Strap printing without + * changing the rest of its code path). */ +- if (strcmp(name, "EP80579") == 0) ++ if (dev->device_id == 0x5031) + straps_names = straps_names_EP80579; + else + straps_names = straps_names_ich7_nm10; +@@ -531,6 +570,9 @@ static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name, + case CHIPSET_ICH10: + straps_names = straps_names_ich8910; + break; ++ case CHIPSET_TUNNEL_CREEK: ++ straps_names = straps_names_tunnel_creek; ++ break; + case CHIPSET_5_SERIES_IBEX_PEAK: + case CHIPSET_6_SERIES_COUGAR_POINT: + case CHIPSET_7_SERIES_PANTHER_POINT: +@@ -543,33 +585,41 @@ static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name, + straps_names = straps_names_pch8_lp; + break; + case CHIPSET_8_SERIES_WELLSBURG: // FIXME: check datasheet ++ case CHIPSET_CENTERTON: // FIXME: Datasheet does not mention GCS at all + straps_names = straps_names_unknown; + break; ++#ifdef DELL_AVOTON_SUPPORT ++ case CHIPSET_AVOTON: ++ straps_names = straps_names_avoton; ++ break; ++#endif + default: +- msg_gerr("%s: unknown ICH generation. Please report!\n", +- __func__); ++ msg_gerr("%s: unknown ICH generation. Please report!\n", __func__); + straps_names = straps_names_unknown; + break; + } + +- /* Enable Flash Writes */ +- ret = enable_flash_ich_dc(dev, name); +- if (ret == ERROR_FATAL) +- return ret; +- + /* Get physical address of Root Complex Register Block */ +- tmp = pci_read_long(dev, 0xf0) & 0xffffc000; +- msg_pdbg("Root Complex Register Block address = 0x%x\n", tmp); ++ uint32_t rcra = pci_read_long(dev, 0xf0) & 0xffffc000; ++ msg_pdbg("Root Complex Register Block address = 0x%x\n", rcra); + + /* Map RCBA to virtual memory */ +- rcrb = physmap("ICH RCRB", tmp, 0x4000); ++ void *rcrb = rphysmap("ICH RCRB", rcra, 0x4000); ++ if (rcrb == ERROR_PTR) ++ return ERROR_FATAL; + +- gcs = mmio_readl(rcrb + 0x3410); ++#ifdef DELL_AVOTON_SUPPORT ++ if (ich_generation != CHIPSET_AVOTON) { ++#endif ++ uint32_t gcs = mmio_readl(rcrb + 0x3410); + msg_pdbg("GCS = 0x%x: ", gcs); +- msg_pdbg("BIOS Interface Lock-Down: %sabled, ", +- (gcs & 0x1) ? "en" : "dis"); ++ msg_pdbg("BIOS Interface Lock-Down: %sabled, ", (gcs & 0x1) ? "en" : "dis"); + ++ uint8_t bbs; + switch (ich_generation) { ++ case CHIPSET_TUNNEL_CREEK: ++ bbs = (gcs >> 1) & 0x1; ++ break; + case CHIPSET_8_SERIES_LYNX_POINT_LP: + case CHIPSET_8_SERIES_WELLSBURG: // FIXME: check datasheet + /* Lynx Point LP uses a single bit for GCS */ +@@ -582,91 +632,187 @@ static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name, + } + msg_pdbg("Boot BIOS Straps: 0x%x (%s)\n", bbs, straps_names[bbs]); + +- buc = mmio_readb(rcrb + 0x3414); +- msg_pdbg("Top Swap : %s\n", +- (buc & 1) ? "enabled (A16 inverted)" : "not enabled"); ++ if (ich_generation != CHIPSET_TUNNEL_CREEK && ich_generation != CHIPSET_CENTERTON) { ++ uint8_t buc = mmio_readb(rcrb + 0x3414); ++ msg_pdbg("Top Swap : %s\n", (buc & 1) ? "enabled (A16(+) inverted)" : "not enabled"); ++ } + +- /* It seems the ICH7 does not support SPI and LPC chips at the same +- * time. At least not with our current code. So we prevent searching +- * on ICH7 when the southbridge is strapped to LPC +- */ +- internal_buses_supported = BUS_FWH; +- if (ich_generation == CHIPSET_ICH7) { +- if (bbs == 0x03) { +- /* If strapped to LPC, no further SPI initialization is +- * required. */ +- return ret; +- } else { +- /* Disable LPC/FWH if strapped to PCI or SPI */ +- internal_buses_supported = BUS_NONE; +- } ++ /* Handle FWH-related parameters and initialization */ ++#ifdef DELL_AVOTON_SUPPORT ++ ret_fwh = enable_flash_ich_fwh(dev, ich_generation, bios_cntl); ++#else ++ int ret_fwh = enable_flash_ich_fwh(dev, ich_generation, bios_cntl); ++#endif ++ if (ret_fwh == ERROR_FATAL) ++ return ret_fwh; ++ ++ /* SPIBAR is at RCRB+0x3020 for ICH[78], Tunnel Creek and Centerton, and RCRB+0x3800 for ICH9. */ ++ uint16_t spibar_offset; ++ switch (ich_generation) { ++ case CHIPSET_ICH_UNKNOWN: ++ return ERROR_FATAL; ++ case CHIPSET_ICH7: ++ case CHIPSET_ICH8: ++ case CHIPSET_TUNNEL_CREEK: ++ case CHIPSET_CENTERTON: ++ spibar_offset = 0x3020; ++ break; ++ case CHIPSET_ICH9: ++ default: /* Future version might behave the same */ ++ spibar_offset = 0x3800; ++ break; + } ++ msg_pdbg("SPIBAR = 0x%0*" PRIxPTR " + 0x%04x\n", PRIxPTR_WIDTH, (uintptr_t)rcrb, spibar_offset); ++#ifndef DELL_AVOTON_SUPPORT ++ void *spibar = rcrb + spibar_offset; ++#else ++ spibar = rcrb + spibar_offset; ++ } else { ++ tmp = pci_read_long(dev, 0x54) & 0xFFFFFE00; ++ spibar = rphysmap("ICH SPIBAR", tmp, 0x4000); ++ msg_pdbg("SPIBAR = 0x%x\n", tmp); ++ ++ /* BIOS Control Register */ ++ tmp = mmio_readl(spibar + bios_cntl); ++ msg_pdbg("0xFC: 0x%08x (BIOS_CONTROL_REGISTER_BIOS : BCR)\n", tmp); ++ msg_pdbg("BIOS Write Protect Disable : %sabled, \n", ++ (tmp & (1 << 0)) ? "en" : "dis"); ++ msg_pdbg("\nBIOS Lock Enable: %sabled, \n", ++ (tmp & (1 << 1)) ? "en" : "dis"); ++ if (tmp != 1) { ++ mmio_writel(0x1, (spibar + bios_cntl)); ++ } ++ tmp = mmio_readl(spibar + bios_cntl); ++ msg_pdbg("0xFC: 0x%08x (BIOS_CONTROL_REGISTER_BIOS : BCR)\n", tmp); ++ msg_pdbg("BIOS Write Protect Disable : %sabled, \n", ++ (tmp & (1 << 0)) ? "en" : "dis"); ++ if (tmp != 1) { ++ msg_perr("Reboot and change BIOS-> IntelRCSetup -> Relax Security Config -> Disabled to Enabled\n"); ++ return ERROR_FATAL; /* Signal error */ ++ } ++ old = mmio_readb(spibar + 0xFC); ++ msg_pdbg("SPI Read Configuration: \n"); ++ new = (old >> 2) & 0x3; ++ switch (new) { ++ case 0: ++ case 1: ++ case 2: ++ msg_pdbg("prefetching %sabled, caching %sabled, \n", ++ (new & 0x2) ? "en" : "dis", ++ (new & 0x1) ? "dis" : "en"); ++ break; ++ default: ++ msg_pdbg("invalid prefetching/caching settings, \n"); ++ break; ++ } ++ } ++#endif ++ + + /* This adds BUS_SPI */ +- ret_spi = ich_init_spi(dev, tmp, rcrb, ich_generation); ++ int ret_spi = ich_init_spi(dev, spibar, ich_generation); + if (ret_spi == ERROR_FATAL) + return ret_spi; + +- if (ret || ret_spi) +- ret = ERROR_NONFATAL; ++ if (ret_fwh || ret_spi) ++ return ERROR_NONFATAL; + +- return ret; ++ return 0; ++} ++ ++static int enable_flash_tunnelcreek(struct pci_dev *dev, const char *name) ++{ ++ return enable_flash_ich_spi(dev, CHIPSET_TUNNEL_CREEK, 0xd8); ++} ++ ++static int enable_flash_s12x0(struct pci_dev *dev, const char *name) ++{ ++ return enable_flash_ich_spi(dev, CHIPSET_CENTERTON, 0xd8); + } + + static int enable_flash_ich7(struct pci_dev *dev, const char *name) + { +- return enable_flash_ich_dc_spi(dev, name, CHIPSET_ICH7); ++ return enable_flash_ich_spi(dev, CHIPSET_ICH7, 0xdc); + } + + static int enable_flash_ich8(struct pci_dev *dev, const char *name) + { +- return enable_flash_ich_dc_spi(dev, name, CHIPSET_ICH8); ++ return enable_flash_ich_spi(dev, CHIPSET_ICH8, 0xdc); + } + + static int enable_flash_ich9(struct pci_dev *dev, const char *name) + { +- return enable_flash_ich_dc_spi(dev, name, CHIPSET_ICH9); ++ return enable_flash_ich_spi(dev, CHIPSET_ICH9, 0xdc); + } + + static int enable_flash_ich10(struct pci_dev *dev, const char *name) + { +- return enable_flash_ich_dc_spi(dev, name, CHIPSET_ICH10); ++ return enable_flash_ich_spi(dev, CHIPSET_ICH10, 0xdc); + } + ++#ifdef DELL_AVOTON_SUPPORT ++static int enable_flash_c2000(struct pci_dev *dev, const char *name) ++{ ++ is_avoton = 1; ++ return enable_flash_ich_spi(dev, CHIPSET_AVOTON, 0xfc); ++} ++#endif ++ ++#if DELL_DENVERTON_SUPPORT == 1 ++static int enable_flash_denverton(struct pci_dev *dev, const char *name) ++{ ++ void *spibar; ++ int32_t ret_spi; ++ uint32_t sbase; ++ enum ich_chipset ich_generation = CHIPSET_DENVERTON; ++ ++ is_dnv = 1; ++ internal_buses_supported = BUS_FWH; ++ ++ /* GET physical address of SPI Base Address and map it */ ++ sbase = pci_read_long(dev, 0x10) & 0xfffffe00; ++ msg_pdbg("SPI_BASE_ADDRESS = 0x%x\n", sbase); ++ spibar = rphysmap("DENVERTON SBASE", sbase, 512); ++ enable_flash_ich_bios_cntl(dev, ich_generation, 0xdc); ++ ret_spi = ich_init_spi(dev, spibar, ich_generation); ++ return ret_spi; ++} ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + /* Ibex Peak aka. 5 series & 3400 series */ + static int enable_flash_pch5(struct pci_dev *dev, const char *name) + { +- return enable_flash_ich_dc_spi(dev, name, CHIPSET_5_SERIES_IBEX_PEAK); ++ return enable_flash_ich_spi(dev, CHIPSET_5_SERIES_IBEX_PEAK, 0xdc); + } + + /* Cougar Point aka. 6 series & c200 series */ + static int enable_flash_pch6(struct pci_dev *dev, const char *name) + { +- return enable_flash_ich_dc_spi(dev, name, CHIPSET_6_SERIES_COUGAR_POINT); ++ return enable_flash_ich_spi(dev, CHIPSET_6_SERIES_COUGAR_POINT, 0xdc); + } + + /* Panther Point aka. 7 series */ + static int enable_flash_pch7(struct pci_dev *dev, const char *name) + { +- return enable_flash_ich_dc_spi(dev, name, CHIPSET_7_SERIES_PANTHER_POINT); ++ return enable_flash_ich_spi(dev, CHIPSET_7_SERIES_PANTHER_POINT, 0xdc); + } + + /* Lynx Point aka. 8 series */ + static int enable_flash_pch8(struct pci_dev *dev, const char *name) + { +- return enable_flash_ich_dc_spi(dev, name, CHIPSET_8_SERIES_LYNX_POINT); ++ return enable_flash_ich_spi(dev, CHIPSET_8_SERIES_LYNX_POINT, 0xdc); + } + +-/* Lynx Point aka. 8 series low-power */ ++/* Lynx Point LP aka. 8 series low-power */ + static int enable_flash_pch8_lp(struct pci_dev *dev, const char *name) + { +- return enable_flash_ich_dc_spi(dev, name, CHIPSET_8_SERIES_LYNX_POINT_LP); ++ return enable_flash_ich_spi(dev, CHIPSET_8_SERIES_LYNX_POINT_LP, 0xdc); + } + + /* Wellsburg (for Haswell-EP Xeons) */ + static int enable_flash_pch8_wb(struct pci_dev *dev, const char *name) + { +- return enable_flash_ich_dc_spi(dev, name, CHIPSET_8_SERIES_WELLSBURG); ++ return enable_flash_ich_spi(dev, CHIPSET_8_SERIES_WELLSBURG, 0xdc); + } + + static int via_no_byte_merge(struct pci_dev *dev, const char *name) +@@ -737,10 +883,8 @@ static int enable_flash_vt_vx(struct pci_dev *dev, const char *name) + case 0x8410: /* VX900 */ + mmio_base = pci_read_long(dev, 0xbc) << 8; + mmio_base_physmapped = physmap("VIA VX MMIO register", mmio_base, SPI_CNTL_LEN); +- if (mmio_base_physmapped == ERROR_PTR) { +- physunmap(mmio_base_physmapped, SPI_CNTL_LEN); ++ if (mmio_base_physmapped == ERROR_PTR) + return ERROR_FATAL; +- } + + /* Offset 0 - Bit 0 holds SPI Bus0 Enable Bit. */ + spi_cntl = mmio_readl(mmio_base_physmapped) + 0x00; +@@ -882,22 +1026,29 @@ static int enable_flash_sc1100(struct pci_dev *dev, const char *name) + return 0; + } + +-/* Works for AMD-8111, VIA VT82C586A/B, VIA VT82C686A/B. */ +-static int enable_flash_amd8111(struct pci_dev *dev, const char *name) ++/* Works for AMD-768, AMD-8111, VIA VT82C586A/B, VIA VT82C596, VIA VT82C686A/B. ++ * ++ * ROM decode control register matrix ++ * AMD-768 AMD-8111 VT82C586A/B VT82C596 VT82C686A/B ++ * 7 FFC0_0000h–FFFF_FFFFh <- FFFE0000h-FFFEFFFFh <- <- ++ * 6 FFB0_0000h–FFBF_FFFFh <- FFF80000h-FFFDFFFFh <- <- ++ * 5 00E8... <- <- FFF00000h-FFF7FFFFh <- ++ */ ++static int enable_flash_amd_via(struct pci_dev *dev, const char *name, uint8_t decode_val) + { + #define AMD_MAPREG 0x43 + #define AMD_ENREG 0x40 + uint8_t old, new; + +- /* Enable decoding at 0xffb00000 to 0xffffffff. */ + old = pci_read_byte(dev, AMD_MAPREG); +- new = old | 0xC0; ++ new = old | decode_val; + if (new != old) { + rpci_write_byte(dev, AMD_MAPREG, new); + if (pci_read_byte(dev, AMD_MAPREG) != new) { +- msg_pinfo("Setting register 0x%x to 0x%02x on %s failed (WARNING ONLY).\n", ++ msg_pwarn("Setting register 0x%x to 0x%02x on %s failed (WARNING ONLY).\n", + AMD_MAPREG, new, name); +- } ++ } else ++ msg_pdbg("Changed ROM decode range to 0x%02x successfully.\n", new); + } + + /* Enable 'ROM write' bit. */ +@@ -908,14 +1059,37 @@ static int enable_flash_amd8111(struct pci_dev *dev, const char *name) + rpci_write_byte(dev, AMD_ENREG, new); + + if (pci_read_byte(dev, AMD_ENREG) != new) { +- msg_pinfo("Setting register 0x%x to 0x%02x on %s failed (WARNING ONLY).\n", ++ msg_pwarn("Setting register 0x%x to 0x%02x on %s failed (WARNING ONLY).\n", + AMD_ENREG, new, name); +- return -1; ++ return ERROR_NONFATAL; + } ++ msg_pdbg2("Set ROM enable bit successfully.\n"); + + return 0; + } + ++static int enable_flash_amd_768_8111(struct pci_dev *dev, const char *name) ++{ ++ /* Enable decoding of 0xFFB00000 to 0xFFFFFFFF (5 MB). */ ++ max_rom_decode.lpc = 5 * 1024 * 1024; ++ return enable_flash_amd_via(dev, name, 0xC0); ++} ++ ++static int enable_flash_vt82c586(struct pci_dev *dev, const char *name) ++{ ++ /* Enable decoding of 0xFFF80000 to 0xFFFFFFFF. (512 kB) */ ++ max_rom_decode.parallel = 512 * 1024; ++ return enable_flash_amd_via(dev, name, 0xC0); ++} ++ ++/* Works for VT82C686A/B too. */ ++static int enable_flash_vt82c596(struct pci_dev *dev, const char *name) ++{ ++ /* Enable decoding of 0xFFF80000 to 0xFFFFFFFF. (1 MB) */ ++ max_rom_decode.parallel = 1024 * 1024; ++ return enable_flash_amd_via(dev, name, 0xE0); ++} ++ + static int enable_flash_sb600(struct pci_dev *dev, const char *name) + { + uint32_t prot; +@@ -1257,6 +1431,8 @@ static int get_flashbase_sc520(struct pci_dev *dev, const char *name) + + /* 1. Map MMCR */ + mmcr = physmap("Elan SC520 MMCR", 0xfffef000, getpagesize()); ++ if (mmcr == ERROR_PTR) ++ return ERROR_FATAL; + + /* 2. Scan PAR0 (0x88) - PAR15 (0xc4) for + * BOOTCS region (PARx[31:29] = 100b)e +@@ -1302,8 +1478,8 @@ const struct penable chipset_enables[] = { + {0x1022, 0x2080, OK, "AMD", "CS5536", enable_flash_cs5536}, + {0x1022, 0x2090, OK, "AMD", "CS5536", enable_flash_cs5536}, + {0x1022, 0x3000, OK, "AMD", "Elan SC520", get_flashbase_sc520}, +- {0x1022, 0x7440, OK, "AMD", "AMD-768", enable_flash_amd8111}, +- {0x1022, 0x7468, OK, "AMD", "AMD8111", enable_flash_amd8111}, ++ {0x1022, 0x7440, OK, "AMD", "AMD-768", enable_flash_amd_768_8111}, ++ {0x1022, 0x7468, OK, "AMD", "AMD-8111", enable_flash_amd_768_8111}, + {0x1022, 0x780e, OK, "AMD", "FCH", enable_flash_sb600}, + {0x1039, 0x0406, NT, "SiS", "501/5101/5501", enable_flash_sis501}, + {0x1039, 0x0496, NT, "SiS", "85C496+497", enable_flash_sis85c496}, +@@ -1388,9 +1564,9 @@ const struct penable chipset_enables[] = { + {0x1106, 0x0691, OK, "VIA", "VT82C69x", via_no_byte_merge}, + {0x1106, 0x8601, NT, "VIA", "VT8601T", via_no_byte_merge}, + /* VIA southbridges */ +- {0x1106, 0x0586, OK, "VIA", "VT82C586A/B", enable_flash_amd8111}, +- {0x1106, 0x0596, OK, "VIA", "VT82C596", enable_flash_amd8111}, +- {0x1106, 0x0686, OK, "VIA", "VT82C686A/B", enable_flash_amd8111}, ++ {0x1106, 0x0586, OK, "VIA", "VT82C586A/B", enable_flash_vt82c586}, ++ {0x1106, 0x0596, OK, "VIA", "VT82C596", enable_flash_vt82c596}, ++ {0x1106, 0x0686, OK, "VIA", "VT82C686A/B", enable_flash_vt82c596}, + {0x1106, 0x3074, OK, "VIA", "VT8233", enable_flash_vt823x}, + {0x1106, 0x3147, OK, "VIA", "VT8233A", enable_flash_vt823x}, + {0x1106, 0x3177, OK, "VIA", "VT8235", enable_flash_vt823x}, +@@ -1405,6 +1581,7 @@ const struct penable chipset_enables[] = { + {0x1166, 0x0200, OK, "Broadcom", "OSB4", enable_flash_osb4}, + {0x1166, 0x0205, OK, "Broadcom", "HT-1000", enable_flash_ht1000}, + {0x17f3, 0x6030, OK, "RDC", "R8610/R3210", enable_flash_rdc_r8610}, ++ {0x8086, 0x0c60, NT, "Intel", "S12x0", enable_flash_s12x0}, + {0x8086, 0x122e, OK, "Intel", "PIIX", enable_flash_piix4}, + {0x8086, 0x1234, NT, "Intel", "MPIIX", enable_flash_piix4}, + {0x8086, 0x1c44, OK, "Intel", "Z68", enable_flash_pch6}, +@@ -1441,21 +1618,21 @@ const struct penable chipset_enables[] = { + {0x8086, 0x1e5f, NT, "Intel", "NM70", enable_flash_pch7}, + {0x8086, 0x2310, NT, "Intel", "DH89xxCC", enable_flash_pch7}, + {0x8086, 0x2390, NT, "Intel", "Coleto Creek", enable_flash_pch7}, +- {0x8086, 0x2410, OK, "Intel", "ICH", enable_flash_ich_4e}, +- {0x8086, 0x2420, OK, "Intel", "ICH0", enable_flash_ich_4e}, +- {0x8086, 0x2440, OK, "Intel", "ICH2", enable_flash_ich_4e}, +- {0x8086, 0x244c, OK, "Intel", "ICH2-M", enable_flash_ich_4e}, +- {0x8086, 0x2450, NT, "Intel", "C-ICH", enable_flash_ich_4e}, +- {0x8086, 0x2480, OK, "Intel", "ICH3-S", enable_flash_ich_4e}, +- {0x8086, 0x248c, OK, "Intel", "ICH3-M", enable_flash_ich_4e}, +- {0x8086, 0x24c0, OK, "Intel", "ICH4/ICH4-L", enable_flash_ich_4e}, +- {0x8086, 0x24cc, OK, "Intel", "ICH4-M", enable_flash_ich_4e}, +- {0x8086, 0x24d0, OK, "Intel", "ICH5/ICH5R", enable_flash_ich_4e}, +- {0x8086, 0x25a1, OK, "Intel", "6300ESB", enable_flash_ich_4e}, +- {0x8086, 0x2640, OK, "Intel", "ICH6/ICH6R", enable_flash_ich_dc}, +- {0x8086, 0x2641, OK, "Intel", "ICH6-M", enable_flash_ich_dc}, +- {0x8086, 0x2642, NT, "Intel", "ICH6W/ICH6RW", enable_flash_ich_dc}, +- {0x8086, 0x2670, OK, "Intel", "631xESB/632xESB/3100", enable_flash_ich_dc}, ++ {0x8086, 0x2410, OK, "Intel", "ICH", enable_flash_ich0}, ++ {0x8086, 0x2420, OK, "Intel", "ICH0", enable_flash_ich0}, ++ {0x8086, 0x2440, OK, "Intel", "ICH2", enable_flash_ich2345}, ++ {0x8086, 0x244c, OK, "Intel", "ICH2-M", enable_flash_ich2345}, ++ {0x8086, 0x2450, NT, "Intel", "C-ICH", enable_flash_ich2345}, ++ {0x8086, 0x2480, OK, "Intel", "ICH3-S", enable_flash_ich2345}, ++ {0x8086, 0x248c, OK, "Intel", "ICH3-M", enable_flash_ich2345}, ++ {0x8086, 0x24c0, OK, "Intel", "ICH4/ICH4-L", enable_flash_ich2345}, ++ {0x8086, 0x24cc, OK, "Intel", "ICH4-M", enable_flash_ich2345}, ++ {0x8086, 0x24d0, OK, "Intel", "ICH5/ICH5R", enable_flash_ich2345}, ++ {0x8086, 0x25a1, OK, "Intel", "6300ESB", enable_flash_ich2345}, ++ {0x8086, 0x2640, OK, "Intel", "ICH6/ICH6R", enable_flash_ich6}, ++ {0x8086, 0x2641, OK, "Intel", "ICH6-M", enable_flash_ich6}, ++ {0x8086, 0x2642, NT, "Intel", "ICH6W/ICH6RW", enable_flash_ich6}, ++ {0x8086, 0x2670, OK, "Intel", "631xESB/632xESB/3100", enable_flash_ich6}, + {0x8086, 0x27b0, OK, "Intel", "ICH7DH", enable_flash_ich7}, + {0x8086, 0x27b8, OK, "Intel", "ICH7/ICH7R", enable_flash_ich7}, + {0x8086, 0x27b9, OK, "Intel", "ICH7M", enable_flash_ich7}, +@@ -1570,6 +1747,12 @@ const struct penable chipset_enables[] = { + {0x8086, 0x8d5d, NT, "Intel", "Wellsburg", enable_flash_pch8_wb}, + {0x8086, 0x8d5e, NT, "Intel", "Wellsburg", enable_flash_pch8_wb}, + {0x8086, 0x8d5f, NT, "Intel", "Wellsburg", enable_flash_pch8_wb}, ++#ifdef DELL_AVOTON_SUPPORT ++ {0x8086, 0x1f38, OK, "Intel", "C2000", enable_flash_c2000}, ++#endif ++#if DELL_DENVERTON_SUPPORT == 1 ++ {0x8086, 0x19e0, OK, "Intel", "Denverton", enable_flash_denverton}, ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + #endif + {0}, + }; +@@ -1597,14 +1780,23 @@ int chipset_flash_enable(void) + chipset_enables[i].device_name); + continue; + } ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("Found chipset \"%s %s\"", ++ chipset_enables[i].vendor_name, ++ chipset_enables[i].device_name); ++#else + msg_pinfo("Found chipset \"%s %s\"", + chipset_enables[i].vendor_name, + chipset_enables[i].device_name); ++#endif + msg_pdbg(" with PCI ID %04x:%04x", + chipset_enables[i].vendor_id, + chipset_enables[i].device_id); ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg(". "); ++#else + msg_pinfo(". "); +- ++#endif + if (chipset_enables[i].status == NT) { + msg_pinfo("\nThis chipset is marked as untested. If " + "you are using an up-to-date version\nof " +@@ -1614,20 +1806,44 @@ int chipset_flash_enable(void) + "flashrom@flashrom.org including a verbose " + "(-V) log.\nThank you!\n"); + } ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("Enabling flash write... "); ++#else + msg_pinfo("Enabling flash write... "); ++#endif + ret = chipset_enables[i].doit(dev, + chipset_enables[i].device_name); + if (ret == NOT_DONE_YET) { + ret = -2; ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("OK - searching further chips.\n"); ++#else + msg_pinfo("OK - searching further chips.\n"); ++#endif + } else if (ret < 0) ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("FAILED!\n"); ++#else + msg_pinfo("FAILED!\n"); ++#endif + else if (ret == 0) ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("OK.\n"); ++#else + msg_pinfo("OK.\n"); ++#endif + else if (ret == ERROR_NONFATAL) ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("PROBLEMS, continuing anyway\n"); ++#else + msg_pinfo("PROBLEMS, continuing anyway\n"); ++#endif + if (ret == ERROR_FATAL) { ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("FATAL ERROR!\n"); ++#else + msg_perr("FATAL ERROR!\n"); ++#endif + return ret; + } + } +diff --git a/cli_classic.c b/cli_classic.c +index 4c71d07..09565f4 100644 +--- a/cli_classic.c ++++ b/cli_classic.c +@@ -31,6 +31,10 @@ + #include "flashchips.h" + #include "programmer.h" + ++#if DELL_DENVERTON_SUPPORT == 1 ++extern int8_t is_dnv; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + static void cli_classic_usage(const char *name) + { + printf("Please note that the command line interface for flashrom has changed between\n" +@@ -136,9 +140,10 @@ int main(int argc, char *argv[]) + char *tempstr = NULL; + char *pparam = NULL; + ++#ifndef FORCE10_SPI_CHANGE + print_version(); + print_banner(); +- ++#endif + if (selfcheck()) + exit(1); + +@@ -221,8 +226,6 @@ int main(int argc, char *argv[]) + free(tempstr); + cli_classic_abort_usage(); + } +- /* FIXME: A pointer to the image name is saved in a static array (of size MAX_ROMLAYOUT) +- * by register_include_arg() and needs to be freed after processing them. */ + break; + case 'L': + if (++operation_specified > 1) { +@@ -295,6 +298,9 @@ int main(int argc, char *argv[]) + "specified. Aborting.\n"); + cli_classic_abort_usage(); + } ++#ifdef FORCE10_SPI_CHANGE ++ print_version(); ++#endif + exit(0); + break; + case 'h': +@@ -372,6 +378,12 @@ int main(int argc, char *argv[]) + ret = 1; + goto out; + } ++ if (layoutfile != NULL && !write_it) { ++ msg_gerr("Layout files are currently supported for write operations only.\n"); ++ ret = 1; ++ goto out; ++ } ++ + if (process_include_args()) { + ret = 1; + goto out; +@@ -393,8 +405,13 @@ int main(int argc, char *argv[]) + if (prog == PROGRAMMER_INVALID) { + if (CONFIG_DEFAULT_PROGRAMMER != PROGRAMMER_INVALID) { + prog = CONFIG_DEFAULT_PROGRAMMER; ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("Using default programmer \"%s\".\n", ++ programmer_table[CONFIG_DEFAULT_PROGRAMMER].name); ++#else + msg_pinfo("Using default programmer \"%s\".\n", + programmer_table[CONFIG_DEFAULT_PROGRAMMER].name); ++#endif + } else { + msg_perr("Please select a programmer with the --programmer parameter.\n" + "Previously this was not necessary because there was a default set.\n" +@@ -489,6 +506,10 @@ int main(int argc, char *argv[]) + tempstr = flashbuses_to_text(flashes[0].chip->bustype); + msg_gdbg("Found %s flash chip \"%s\" (%d kB, %s).\n", + flashes[0].chip->vendor, flashes[0].chip->name, flashes[0].chip->total_size, tempstr); ++ if ((flashes[0].chip->total_size > flashes[0].bios_size) && (flashes[0].bios_size != 0)) { ++ msg_gdbg("BIOS Size in flash chip: %d kB\n", flashes[0].bios_size); ++ flashes[0].chip->total_size = flashes[0].bios_size; ++ } + free(tempstr); + } + +@@ -517,7 +538,19 @@ int main(int argc, char *argv[]) + * Give the chip time to settle. + */ + programmer_delay(100000); ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) { ++ dnv_smi_open_res(); ++ dnv_smi_doit(0, NULL, SMI_ENABLE_SPI); ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + ret |= doit(fill_flash, force, filename, read_it, write_it, erase_it, verify_it); ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) { ++ dnv_smi_doit(0, NULL, SMI_DISABLE_SPI); ++ dnv_smi_release_res(); ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + /* Note: doit() already calls programmer_shutdown(). */ + goto out; + +@@ -527,6 +560,7 @@ out: + for (i = 0; i < chipcount; i++) + free(flashes[i].chip); + ++ layout_cleanup(); + free(filename); + free(layoutfile); + free(pparam); +diff --git a/dmi.c b/dmi.c +index 242889f..25ddd93 100644 +--- a/dmi.c ++++ b/dmi.c +@@ -1,7 +1,10 @@ + /* + * This file is part of the flashrom project. + * ++ * Copyright (C) 2000-2002 Alan Cox ++ * Copyright (C) 2002-2010 Jean Delvare + * Copyright (C) 2009,2010 Michael Karcher ++ * Copyright (C) 2011-2013 Stefan Tauner + * + * 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 +@@ -26,33 +29,28 @@ + #include "flash.h" + #include "programmer.h" + +-int has_dmi_support = 0; +- +-#if STANDALONE ++#if defined(__i386__) || defined(__x86_64__) + +-/* Stub to indicate missing DMI functionality. +- * has_dmi_support is 0 by default, so nothing to do here. +- * Because dmidecode is not available on all systems, the goal is to implement +- * the DMI subset we need directly in this file. +- */ +-void dmi_init(void) +-{ +-} ++/* Enable SMBIOS decoding. Currently legacy DMI decoding is enough. */ ++#define SM_SUPPORT 0 + +-int dmi_match(const char *pattern) +-{ +- return 0; +-} ++/* Strings longer than 4096 in DMI are just insane. */ ++#define DMI_MAX_ANSWER_LEN 4096 + +-#else /* STANDALONE */ ++int has_dmi_support = 0; + +-static const char *dmidecode_names[] = { +- "system-manufacturer", +- "system-product-name", +- "system-version", +- "baseboard-manufacturer", +- "baseboard-product-name", +- "baseboard-version", ++static struct { ++ const char *const keyword; ++ const uint8_t type; ++ const uint8_t offset; ++ char *value; ++} dmi_strings[] = { ++ { "system-manufacturer", 1, 0x04, NULL }, ++ { "system-product-name", 1, 0x05, NULL }, ++ { "system-version", 1, 0x06, NULL }, ++ { "baseboard-manufacturer", 2, 0x04, NULL }, ++ { "baseboard-product-name", 2, 0x05, NULL }, ++ { "baseboard-version", 2, 0x06, NULL }, + }; + + /* This list is used to identify supposed laptops. The is_laptop field has the +@@ -66,9 +64,9 @@ static const char *dmidecode_names[] = { + * The types below are the most common ones. + */ + static const struct { +- unsigned char type; +- unsigned char is_laptop; +- const char *name; ++ uint8_t type; ++ uint8_t is_laptop; ++ char *name; + } dmi_chassis_types[] = { + {0x01, 2, "Other"}, + {0x02, 2, "Unknown"}, +@@ -86,20 +84,206 @@ static const struct { + {0x18, 0, "Sealed-case PC"}, /* used by Supermicro (X8SIE) */ + }; + +-#define DMI_COMMAND_LEN_MAX 260 +-static const char *dmidecode_command = "dmidecode"; ++#if CONFIG_INTERNAL_DMI == 1 ++#if defined(__DJGPP__) || defined(FORCE10_SPI_CHANGE) /* There is no strnlen in DJGPP. FIXME: Move this to a common utility file. */ ++size_t strnlen(const char *str, size_t n) ++{ ++ size_t i; ++ for (i = 0; i < n && str[i] != '\0'; i++) ++ ; ++ return i; ++} ++#endif + +-static char *dmistrings[ARRAY_SIZE(dmidecode_names)]; ++static bool dmi_checksum(const uint8_t * const buf, size_t len) ++{ ++ uint8_t sum = 0; ++ size_t a; + +-/* Strings longer than 4096 in DMI are just insane. */ +-#define DMI_MAX_ANSWER_LEN 4096 ++ for (a = 0; a < len; a++) ++ sum += buf[a]; ++ return (sum == 0); ++} ++ ++static char *dmi_string(uint8_t *buf, uint8_t string_id, uint8_t *limit) ++{ ++ size_t i, len; ++ ++ if (string_id == 0) ++ return "Not Specified"; ++ ++ while (string_id > 1 && string_id--) { ++ if (buf > limit) { ++ msg_perr("DMI table is broken (string portion out of bounds)!\n"); ++ return ""; ++ } ++ buf += strnlen((char *)buf, limit - buf) + 1; ++ } ++ ++ if (!*buf) /* as long as the current byte we're on isn't null */ ++ return ""; ++ ++ len = strnlen((char *)buf, limit - buf); ++ if (len > DMI_MAX_ANSWER_LEN) ++ len = DMI_MAX_ANSWER_LEN; ++ ++ /* fix junk bytes in the string */ ++ for (i = 0; i < len && buf[i] != '\0'; i++) ++ if (buf[i] < 32 || buf[i] >= 127) ++ buf[i] = ' '; ++ ++ return (char *)buf; ++} ++ ++static void dmi_chassis_type(uint8_t code) ++{ ++ int i; ++ code &= 0x7f; /* bits 6:0 are chassis type, 7th bit is the lock bit */ ++ is_laptop = 2; ++ for (i = 0; i < ARRAY_SIZE(dmi_chassis_types); i++) { ++ if (code == dmi_chassis_types[i].type) { ++ msg_pdbg("DMI string chassis-type: \"%s\"\n", dmi_chassis_types[i].name); ++ is_laptop = dmi_chassis_types[i].is_laptop; ++ break; ++ } ++ } ++} ++ ++static void dmi_table(uint32_t base, uint16_t len, uint16_t num) ++{ ++ int i = 0, j = 0; ++ ++ uint8_t *dmi_table_mem = physmap_ro("DMI Table", base, len); ++ if (dmi_table_mem == NULL) { ++ msg_perr("Unable to access DMI Table\n"); ++ return; ++ } ++ ++ uint8_t *data = dmi_table_mem; ++ uint8_t *limit = dmi_table_mem + len; ++ ++ /* SMBIOS structure header is always 4 B long and contains: ++ * - uint8_t type; // see dmi_chassis_types's type ++ * - uint8_t length; // data section w/ header w/o strings ++ * - uint16_t handle; ++ */ ++ while (i < num && data + 4 <= limit) { ++ /* - If a short entry is found (less than 4 bytes), not only it ++ * is invalid, but we cannot reliably locate the next entry. ++ * - If the length value indicates that this structure spreads ++ * accross the table border, something is fishy too. ++ * Better stop at this point, and let the user know his/her ++ * table is broken. ++ */ ++ if (data[1] < 4 || data + data[1] > limit) { ++ msg_perr("DMI table is broken (bogus header)!\n"); ++ break; ++ } ++ ++ if(data[0] == 3) { ++ if (data + 5 <= limit) ++ dmi_chassis_type(data[5]); ++ /* else the table is broken, but laptop detection is optional, hence continue. */ ++ } else ++ for (j = 0; j < ARRAY_SIZE(dmi_strings); j++) { ++ uint8_t offset = dmi_strings[j].offset; ++ uint8_t type = dmi_strings[j].type; ++ ++ if (data[0] != type) ++ continue; ++ ++ if (data[1] <= offset || data+offset > limit) { ++ msg_perr("DMI table is broken (offset out of bounds)!\n"); ++ goto out; ++ } ++ ++ /* Table will be unmapped, hence fill the struct with duplicated strings. */ ++ dmi_strings[j].value = strdup(dmi_string(data + data[1], data[offset], limit)); ++ } ++ /* Find next structure by skipping data and string sections */ ++ data += data[1]; ++ while (data + 1 <= limit) { ++ if (data[0] == 0 && data[1] == 0) ++ break; ++ data++; ++ } ++ data += 2; ++ i++; ++ } ++out: ++ physunmap(dmi_table_mem, len); ++} ++ ++#if SM_SUPPORT ++static int smbios_decode(uint8_t *buf) ++{ ++ /* TODO: other checks mentioned in the conformance guidelines? */ ++ if (!dmi_checksum(buf, buf[0x05]) || ++ (memcmp(buf + 0x10, "_DMI_", 5) != 0) || ++ !dmi_checksum(buf + 0x10, 0x0F)) ++ return 0; ++ ++ dmi_table(mmio_readl(buf + 0x18), mmio_readw(buf + 0x16), mmio_readw(buf + 0x1C)); ++ ++ return 1; ++} ++#endif ++ ++static int legacy_decode(uint8_t *buf) ++{ ++ if (!dmi_checksum(buf, 0x0F)) ++ return 1; ++ ++ dmi_table(mmio_readl(buf + 0x08), mmio_readw(buf + 0x06), mmio_readw(buf + 0x0C)); ++ ++ return 0; ++} ++ ++int dmi_fill(void) ++{ ++ size_t fp; ++ uint8_t *dmi_mem; ++ int ret = 1; ++ ++ msg_pdbg("Using Internal DMI decoder.\n"); ++ /* There are two ways specified to gain access to the SMBIOS table: ++ * - EFI's configuration table contains a pointer to the SMBIOS table. On linux it can be obtained from ++ * sysfs. EFI's SMBIOS GUID is: {0xeb9d2d31,0x2d88,0x11d3,0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d} ++ * - Scanning physical memory address range 0x000F0000h to 0x000FFFFF for the anchor-string(s). */ ++ dmi_mem = physmap_ro("DMI", 0xF0000, 0x10000); ++ if (dmi_mem == ERROR_PTR) ++ return ret; ++ ++ for (fp = 0; fp <= 0xFFF0; fp += 16) { ++#if SM_SUPPORT ++ if (memcmp(dmi_mem + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) { ++ if (smbios_decode(dmi_mem + fp)) // FIXME: length check ++ goto out; ++ } else ++#endif ++ if (memcmp(dmi_mem + fp, "_DMI_", 5) == 0) ++ if (legacy_decode(dmi_mem + fp) == 0) { ++ ret = 0; ++ goto out; ++ } ++ } ++ msg_pinfo("No DMI table found.\n"); ++out: ++ physunmap(dmi_mem, 0x10000); ++ return ret; ++} ++ ++#else /* CONFIG_INTERNAL_DMI */ ++ ++#define DMI_COMMAND_LEN_MAX 300 ++static const char *dmidecode_command = "dmidecode"; + + static char *get_dmi_string(const char *string_name) + { + FILE *dmidecode_pipe; + char *result; +- char answerbuf[DMI_MAX_ANSWER_LEN]; +- char commandline[DMI_COMMAND_LEN_MAX + 40]; ++ char answerbuf[DMI_MAX_ANSWER_LEN + 1] = {'\0'}; ++ char commandline[DMI_COMMAND_LEN_MAX + 1] = {'\0'}; + + snprintf(commandline, sizeof(commandline), + "%s -s %s", dmidecode_command, string_name); +@@ -138,46 +322,31 @@ static char *get_dmi_string(const char *string_name) + /* Chomp trailing newline. */ + if (answerbuf[0] != 0 && answerbuf[strlen(answerbuf) - 1] == '\n') + answerbuf[strlen(answerbuf) - 1] = 0; +- msg_pdbg("DMI string %s: \"%s\"\n", string_name, answerbuf); + + result = strdup(answerbuf); +- if (!result) ++ if (result == NULL) + msg_pwarn("Warning: Out of memory - DMI support fails"); + + return result; + } + +-static int dmi_shutdown(void *data) +-{ +- int i; +- for (i = 0; i < ARRAY_SIZE(dmistrings); i++) { +- free(dmistrings[i]); +- dmistrings[i] = NULL; +- } +- return 0; +-} +- +-void dmi_init(void) ++int dmi_fill(void) + { + int i; + char *chassis_type; + +- if (register_shutdown(dmi_shutdown, NULL)) +- return; +- +- has_dmi_support = 1; +- for (i = 0; i < ARRAY_SIZE(dmidecode_names); i++) { +- dmistrings[i] = get_dmi_string(dmidecode_names[i]); +- if (!dmistrings[i]) { +- has_dmi_support = 0; +- return; +- } ++ msg_pdbg("Using External DMI decoder.\n"); ++ for (i = 0; i < ARRAY_SIZE(dmi_strings); i++) { ++ dmi_strings[i].value = get_dmi_string(dmi_strings[i].keyword); ++ if (dmi_strings[i].value == NULL) ++ return 1; + } + + chassis_type = get_dmi_string("chassis-type"); + if (chassis_type == NULL) +- return; ++ return 0; /* chassis-type handling is optional anyway */ + ++ msg_pdbg("DMI string chassis-type: \"%s\"\n", chassis_type); + is_laptop = 2; + for (i = 0; i < ARRAY_SIZE(dmi_chassis_types); i++) { + if (strcasecmp(chassis_type, dmi_chassis_types[i].name) == 0) { +@@ -185,6 +354,33 @@ void dmi_init(void) + break; + } + } ++ free(chassis_type); ++ return 0; ++} ++ ++#endif /* CONFIG_INTERNAL_DMI */ ++ ++static int dmi_shutdown(void *data) ++{ ++ int i; ++ for (i = 0; i < ARRAY_SIZE(dmi_strings); i++) { ++ free(dmi_strings[i].value); ++ dmi_strings[i].value = NULL; ++ } ++ return 0; ++} ++ ++void dmi_init(void) ++{ ++ /* Register shutdown function before we allocate anything. */ ++ if (register_shutdown(dmi_shutdown, NULL)) { ++ msg_pwarn("Warning: Could not register DMI shutdown function - continuing without DMI info.\n"); ++ return; ++ } ++ ++ /* dmi_fill fills the dmi_strings array, and if possible sets the global is_laptop variable. */ ++ if (dmi_fill() != 0) ++ return; + + switch (is_laptop) { + case 1: +@@ -194,7 +390,13 @@ void dmi_init(void) + msg_pdbg("DMI chassis-type is not specific enough.\n"); + break; + } +- free(chassis_type); ++ ++ has_dmi_support = 1; ++ int i; ++ for (i = 0; i < ARRAY_SIZE(dmi_strings); i++) { ++ msg_pdbg("DMI string %s: \"%s\"\n", dmi_strings[i].keyword, ++ (dmi_strings[i].value == NULL) ? "" : dmi_strings[i].value); ++ } + } + + /** +@@ -204,8 +406,8 @@ void dmi_init(void) + * at the beginning and '$' at the end. So you can look for "^prefix", + * "suffix$", "substring" or "^complete string$". + * +- * @param value The string to check. +- * @param pattern The pattern. ++ * @param value The non-NULL string to check. ++ * @param pattern The non-NULL pattern. + * @return Nonzero if pattern matches. + */ + static int dmi_compare(const char *value, const char *pattern) +@@ -252,11 +454,15 @@ int dmi_match(const char *pattern) + if (!has_dmi_support) + return 0; + +- for (i = 0; i < ARRAY_SIZE(dmidecode_names); i++) +- if (dmi_compare(dmistrings[i], pattern)) ++ for (i = 0; i < ARRAY_SIZE(dmi_strings); i++) { ++ if (dmi_strings[i].value == NULL) ++ continue; ++ ++ if (dmi_compare(dmi_strings[i].value, pattern)) + return 1; ++ } + + return 0; + } + +-#endif /* STANDALONE */ ++#endif // defined(__i386__) || defined(__x86_64__) +diff --git a/dnv_smi_spi.c b/dnv_smi_spi.c +new file mode 100644 +index 0000000..0317cc7 +--- /dev/null ++++ b/dnv_smi_spi.c +@@ -0,0 +1,185 @@ ++ ++/************************************************************************ ++* LEGALESE: "Copyright (c) 2018, Dell Inc. All rights reserved." ++* ++* This source code is confidential, proprietary, and contains trade ++* secrets that are the sole property of Dell Inc. ++* Copy and/or distribution of this source code or disassembly or reverse ++* engineering of the resultant object code are strictly forbidden without ++* the written consent of Dell Inc. ++* ++************************************************************************/ ++#if DELL_DENVERTON_SUPPORT == 1 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "flash.h" ++ ++#define MEM_MODULE "/dev/mem" ++ ++DELL_SPI_MAILBOX *mailbox; ++uint64_t phy_addr; ++ ++/** ++* @brief unmap a pagesize of physical memory into virtual memory. ++* @param[in] addr - virtual memory address that is unmaped. ++*/ ++static void free_virt_mapping(void *addr) ++{ ++ munmap(addr, getpagesize()); ++} ++ ++/** ++* @brief map a pagesize of physical memory into virtual memory. ++* @param[in] addr - physical memory address. ++* @param[out] buf - pointer to buffer which storages data. ++* @return = 0 for success, otherwise for error. ++*/ ++static uint32_t getData_phy_to_virt(uint32_t addr, void** buf) ++{ ++ uint8_t *tmp; ++ uint32_t pagesize, offset, index, fd; ++ ++ pagesize = getpagesize(); ++ if ( (fd = open(MEM_MODULE, O_RDWR)) < 0 ) { ++ printf("open() %s error\n", MEM_MODULE); ++ return 1; ++ } ++ ++ offset = addr & ~(pagesize - 1); ++ index = addr & (pagesize - 1); ++ if ( (tmp = mmap(0, pagesize*2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED ) { ++ printf("mmap() error\n"); ++ close(fd); ++ return 1; ++ } ++ *buf = tmp + index; ++ close(fd); ++ return 0; ++} ++ ++/** ++* @brief send "get communication buffer" requirement to SMM ++*/ ++uint32_t dnv_smi_open_res() ++{ ++ uint32_t mailboxAddress; ++ ++ ioperm(0xB2, 3, 1); ++ __asm__ __volatile__ ("push %%rcx" : :); ++ outb(0x27, 0xB2); ++ __asm__ __volatile__ ("movl %%ecx, %0" : "=r" (mailboxAddress)); ++ __asm__ __volatile__ ("pop %%rcx" : :); ++ ioperm(0xB2, 3, 0); ++ ++ getData_phy_to_virt(mailboxAddress, (void **)&mailbox); ++ phy_addr = mailboxAddress; ++ return 0; ++} ++ ++/** ++* @brief send "release communication buffer" requirement to SMM ++*/ ++void dnv_smi_release_res() ++{ ++ free_virt_mapping((void *)mailbox); ++} ++ ++/** ++* @brief disable SPI write protection. ++*/ ++static void dnv_trigger_smi_spi_unlock() ++{ ++ ioperm(0xB2, 3, 1); ++ __asm__ __volatile__ ("push %%rcx" : :); ++ __asm__ __volatile__ ("push %%rbx" : :); ++ __asm__ __volatile__ ("movl %0, %%ecx" : : "a" ((uint32_t)0)); ++ __asm__ __volatile__ ("movl %0, %%ebx" : : "a" ((uint32_t)phy_addr)); ++ outb(0x20, 0xB2); ++ __asm__ __volatile__ ("pop %%rbx" : :); ++ __asm__ __volatile__ ("pop %%rcx" : :); ++ ioperm(0xB2, 3, 0); ++} ++ ++/** ++* @brief enable SPI write protection. ++*/ ++static void dnv_trigger_smi_spi_lock() ++{ ++ ioperm(0xB2, 3, 1); ++ __asm__ __volatile__ ("push %%rcx" : :); ++ __asm__ __volatile__ ("push %%rbx" : :); ++ __asm__ __volatile__ ("movl %0, %%ecx" : : "a" ((uint32_t)0)); ++ __asm__ __volatile__ ("movl %0, %%ebx" : : "a" ((uint32_t)phy_addr)); ++ outb(0x24, 0xB2); ++ __asm__ __volatile__ ("pop %%rbx" : :); ++ __asm__ __volatile__ ("pop %%rcx" : :); ++ ioperm(0xB2, 3, 0); ++} ++ ++/** ++* @brief trigger smi ++*/ ++void run() ++{ ++ ioperm(0xB2, 3, 1); ++ outb(0x28, 0xB2); ++ ioperm(0xB2, 3, 0); ++} ++ ++/** ++* @brief This function is used to read/write and erase BIOS. ++* trigger SMI and send information to SMM(like requirement, address,and data) ++* @param[in] bios_offset - offset of bios region [0~size of bios region] ++* @param[in] buf - pointer to write data if cmd is "SMI_READ_SPI" ++* @param[in] cmd - enum SPI_SMI_CMD ++* @param[out] buf - pointer to read data if cmd is "SMI_WRITE_SPI" ++* @returns ret. This ret is returned from SMM. ++*/ ++int32_t dnv_smi_doit(uint32_t bios_offset, uint8_t *buf, SPI_SMI_CMD cmd) ++{ ++ ++ if (cmd == SMI_READ_SPI) { ++ mailbox->cmd = 0x1; ++ mailbox->offset = bios_offset; ++ mailbox->dlen = DELL_DENVERTON_BLOCK_SIZE; ++ run(); ++ memcpy (buf, mailbox->data, DELL_DENVERTON_BLOCK_SIZE); ++ return mailbox->ret; ++ } else if (cmd == SMI_ERASE_SPI) { ++ mailbox->cmd = 0x2; ++ mailbox->offset = bios_offset; ++ mailbox->dlen = DELL_DENVERTON_BLOCK_SIZE; ++ run(); ++ return mailbox->ret; ++ } else if (cmd == SMI_WRITE_SPI) { ++ memcpy (mailbox->data, buf, DELL_DENVERTON_BLOCK_SIZE); ++ mailbox->cmd = 0x3; ++ mailbox->offset = bios_offset; ++ mailbox->dlen = DELL_DENVERTON_BLOCK_SIZE; ++ run(); ++ return mailbox->ret; ++ } ++ ++ switch (cmd) ++ { ++ case SMI_ENABLE_SPI: ++ dnv_trigger_smi_spi_unlock(); ++ break; ++ case SMI_DISABLE_SPI: ++ dnv_trigger_smi_spi_lock(); ++ break; ++ default: ++ return -1; ++ } ++ ++ return 0; ++} ++ ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ +diff --git a/drkaiser.c b/drkaiser.c +index b94d6dd..0cf1fdb 100644 +--- a/drkaiser.c ++++ b/drkaiser.c +@@ -56,12 +56,6 @@ static const struct par_programmer par_programmer_drkaiser = { + .chip_writen = fallback_chip_writen, + }; + +-static int drkaiser_shutdown(void *data) +-{ +- physunmap(drkaiser_bar, DRKAISER_MEMMAP_SIZE); +- return 0; +-} +- + int drkaiser_init(void) + { + struct pci_dev *dev = NULL; +@@ -75,15 +69,15 @@ int drkaiser_init(void) + return 1; + + addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_2); ++ if (!addr) ++ return 1; + + /* Write magic register to enable flash write. */ + rpci_write_word(dev, PCI_MAGIC_DRKAISER_ADDR, PCI_MAGIC_DRKAISER_VALUE); + + /* Map 128kB flash memory window. */ +- drkaiser_bar = physmap("Dr. Kaiser PC-Waechter flash memory", +- addr, DRKAISER_MEMMAP_SIZE); +- +- if (register_shutdown(drkaiser_shutdown, NULL)) ++ drkaiser_bar = rphysmap("Dr. Kaiser PC-Waechter flash memory", addr, DRKAISER_MEMMAP_SIZE); ++ if (drkaiser_bar == ERROR_PTR) + return 1; + + max_rom_decode.parallel = 128 * 1024; +diff --git a/flash.h b/flash.h +index 63701ed..79fe8f4 100644 +--- a/flash.h ++++ b/flash.h +@@ -45,6 +45,14 @@ + typedef uintptr_t chipaddr; + #define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2)) + ++/* Types and macros regarding the maximum flash space size supported by generic code. */ ++typedef uint32_t chipoff_t; /* Able to store any addressable offset within a supported flash memory. */ ++typedef uint32_t chipsize_t; /* Able to store the number of bytes of any supported flash memory. */ ++#define FL_MAX_CHIPADDR_BITS (24) ++#define FL_MAX_CHIPADDR ((chipoff_t)(1ULL< 0) ++ programmer_table[programmer].delay(usecs); + } + + void map_flash_registers(struct flashctx *flash) +@@ -619,12 +629,29 @@ static unsigned int count_usable_erasers(const struct flashctx *flash) + return usable_erasefunctions; + } + ++#if DELL_DENVERTON_SUPPORT == 1 ++int8_t is_erase = 0; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + int compare_range(uint8_t *wantbuf, uint8_t *havebuf, unsigned int start, unsigned int len) + { + int ret = 0, failcount = 0; + unsigned int i; + for (i = 0; i < len; i++) { + if (wantbuf[i] != havebuf[i]) { ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv && is_erase) { ++ // _FVH ++ // At offset 0x28~0x2b of NVRAM, Main Bios and Boot Bios ++ // We can't read correct data after "erasing". ++ // But, We verified bios through SF100. The erase feature is work. ++ if (i == _FVH_OFFSET && ++ memcmp(&havebuf[i], _FVH_SIGNATURE, sizeof(_FVH_SIGNATURE) - 1) == 0) { ++ i += sizeof(_FVH_SIGNATURE) - 1; ++ continue; ++ } ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + /* Only print the first failure. */ + if (!failcount++) + msg_cerr("FAILED at 0x%08x! Expected=0x%02x, Found=0x%02x,", +@@ -651,7 +678,15 @@ int check_erased_range(struct flashctx *flash, unsigned int start, + exit(1); + } + memset(cmpbuf, 0xff, len); ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) ++ is_erase = 1; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + ret = verify_range(flash, cmpbuf, start, len); ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) ++ is_erase = 0; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + free(cmpbuf); + return ret; + } +@@ -695,6 +730,22 @@ int verify_range(struct flashctx *flash, uint8_t *cmpbuf, unsigned int start, un + return ret; + } + ++#if DELL_DENVERTON_SUPPORT == 1 ++ // NVRAM will be recovery even if use afulnx. ++ // skip NVRAM region. ++ if (is_dnv) { ++ // Do not hard-code the NVRAM region start address. It is located at different addresses for 16MB and 32MB BIOS image. ++ // For Denverton platform, NVRAM region start address is always located at dnv_bios_region_start. ++ // NVRAM backup region is located at (dnv_bios_region_start + DELL_DENVERTON_MAIN_NVRAM_LENGTH). ++ if ((start >= dnv_bios_region_start && ++ start < (dnv_bios_region_start + DELL_DENVERTON_MAIN_NVRAM_LENGTH)) || ++ (start >= (dnv_bios_region_start + DELL_DENVERTON_MAIN_NVRAM_LENGTH) && ++ start < ((dnv_bios_region_start + DELL_DENVERTON_MAIN_NVRAM_LENGTH) + DELL_DENVERTON_BACKUP_NVRAM_LENGTH))) { ++ return ret; ++ } ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + ret = compare_range(cmpbuf, readbuf, start, len); + out_free: + free(readbuf); +@@ -770,6 +821,11 @@ int need_erase(uint8_t *have, uint8_t *want, unsigned int len, enum write_granul + case write_gran_1056bytes: + result = need_erase_gran_bytes(have, want, len, 1056); + break; ++#if DELL_DENVERTON_SUPPORT == 1 ++ case write_gran_4096bytes: ++ result = need_erase_gran_bytes(have, want, len, 4096); ++ break; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + default: + msg_cerr("%s: Unsupported granularity! Please report a bug at " + "flashrom@flashrom.org\n", __func__); +@@ -831,6 +887,11 @@ static unsigned int get_next_write(uint8_t *have, uint8_t *want, unsigned int le + case write_gran_1056bytes: + stride = 1056; + break; ++#if DELL_DENVERTON_SUPPORT == 1 ++ case write_gran_4096bytes: ++ stride = 4096; ++ break; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + default: + msg_cerr("%s: Unsupported granularity! Please report a bug at " + "flashrom@flashrom.org\n", __func__); +@@ -1140,6 +1201,12 @@ notfound: + if (!flash->chip) + return -1; + ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) { ++ flash->chip->gran = write_gran_4096bytes; ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + #if CONFIG_INTERNAL == 1 + if (programmer_table[programmer].map_flash_region == physmap) + snprintf(location, sizeof(location), "at physical address 0x%lx", base); +@@ -1148,8 +1215,13 @@ notfound: + snprintf(location, sizeof(location), "on %s", programmer_table[programmer].name); + + tmp = flashbuses_to_text(flash->chip->bustype); ++#ifdef FORCE10_SPI_CHANGE ++ msg_cdbg("%s %s flash chip \"%s\" (%d kB, %s) %s.\n", force ? "Assuming" : "Found", ++ flash->chip->vendor, flash->chip->name, flash->chip->total_size, tmp, location); ++#else + msg_cinfo("%s %s flash chip \"%s\" (%d kB, %s) %s.\n", force ? "Assuming" : "Found", + flash->chip->vendor, flash->chip->name, flash->chip->total_size, tmp, location); ++#endif + free(tmp); + + /* Flash registers will not be mapped if the chip was forced. Lock info +@@ -1166,6 +1238,10 @@ notfound: + int read_buf_from_file(unsigned char *buf, unsigned long size, + const char *filename) + { ++#ifdef __LIBPAYLOAD__ ++ msg_gerr("Error: No file I/O support in libpayload\n"); ++ return 1; ++#else + unsigned long numbytes; + FILE *image; + struct stat image_stat; +@@ -1196,11 +1272,16 @@ int read_buf_from_file(unsigned char *buf, unsigned long size, + return 1; + } + return 0; ++#endif + } + + int write_buf_to_file(unsigned char *buf, unsigned long size, + const char *filename) + { ++#ifdef __LIBPAYLOAD__ ++ msg_gerr("Error: No file I/O support in libpayload\n"); ++ return 1; ++#else + unsigned long numbytes; + FILE *image; + +@@ -1221,6 +1302,7 @@ int write_buf_to_file(unsigned char *buf, unsigned long size, + return 1; + } + return 0; ++#endif + } + + int read_flash_to_file(struct flashctx *flash, const char *filename) +@@ -1229,6 +1311,16 @@ int read_flash_to_file(struct flashctx *flash, const char *filename) + unsigned char *buf = calloc(size, sizeof(char)); + int ret = 0; + ++#if DELL_DENVERTON_SUPPORT == 1 ++ uint64_t bios_start = 0; ++ uint64_t bios_size = size; ++ ++ if (is_dnv) { ++ bios_size = dnv_bios_region_size; ++ bios_start = dnv_bios_region_start; ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + msg_cinfo("Reading flash... "); + if (!buf) { + msg_gerr("Memory allocation failed!\n"); +@@ -1240,7 +1332,11 @@ int read_flash_to_file(struct flashctx *flash, const char *filename) + ret = 1; + goto out_free; + } ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (flash->chip->read(flash, (buf + bios_start), bios_start, bios_size)) { ++#else + if (flash->chip->read(flash, buf, 0, size)) { ++#endif /* #if DELL_DENVERTON__SUPPORT == 1 */ + msg_cerr("Read operation failed!\n"); + ret = 1; + goto out_free; +@@ -1388,6 +1484,11 @@ static int walk_eraseregions(struct flashctx *flash, int erasefunction, + { + int i, j; + unsigned int start = 0; ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) { ++ start = dnv_bios_region_start; ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + unsigned int len; + struct block_eraser eraser = flash->chip->block_erasers[erasefunction]; + +@@ -1897,6 +1998,10 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it, + uint8_t *newcontents; + int ret = 0; + unsigned long size = flash->chip->total_size * 1024; ++#if DELL_DENVERTON_SUPPORT == 1 ++ uint32_t bios_size = size; ++ uint32_t bios_start = 0; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + + if (chip_safety_check(flash, force, read_it, write_it, erase_it, verify_it)) { + msg_cerr("Aborting.\n"); +@@ -1904,6 +2009,12 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it, + goto out_nofree; + } + ++ if (normalize_romentries(flash)) { ++ msg_cerr("Requested regions can not be handled. Aborting.\n"); ++ ret = 1; ++ goto out_nofree; ++ } ++ + /* Given the existence of read locks, we want to unlock for read, + * erase and write. + */ +@@ -1936,6 +2047,13 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it, + */ + + if (erase_it) { ++ ++#if 0 // Since we dont have a layout, why set newcontents to 0?? ++#ifdef FORCE10_SPI_CHANGE ++ /* Build a new image taking the given layout into account. */ ++ build_new_image(flash, oldcontents, newcontents); ++#endif ++#endif + /* FIXME: Do we really want the scary warning if erase failed? + * After all, after erase the chip is either blank or partially + * blank or it has the old contents. A blank chip won't boot, +@@ -1975,25 +2093,47 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it, + * preserved, but in that case we might perform unneeded erase which + * takes time as well. + */ ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) { ++ bios_size = dnv_bios_region_size; ++ bios_start = dnv_bios_region_start; ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++#ifdef FORCE10_SPI_CHANGE ++ msg_cdbg("Reading old flash chip contents... "); ++#else + msg_cinfo("Reading old flash chip contents... "); ++#endif ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (flash->chip->read(flash, oldcontents + bios_start, bios_start, bios_size)) { ++#else + if (flash->chip->read(flash, oldcontents, 0, size)) { ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + ret = 1; + msg_cinfo("FAILED.\n"); + goto out; + } ++#ifdef FORCE10_SPI_CHANGE ++ msg_cdbg("done.\n"); ++#else + msg_cinfo("done.\n"); ++#endif + +- // This should be moved into each flash part's code to do it +- // cleanly. This does the job. +- handle_romentries(flash, oldcontents, newcontents); +- ++#if 0 ++ /* Build a new image taking the given layout into account. */ ++ build_new_image(flash, oldcontents, newcontents); ++#endif + // //////////////////////////////////////////////////////////// + + if (write_it) { + if (erase_and_write_flash(flash, oldcontents, newcontents)) { + msg_cerr("Uh oh. Erase/write failed. Checking if " + "anything changed.\n"); ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (!flash->chip->read(flash, newcontents, bios_start, bios_size)) { ++#else + if (!flash->chip->read(flash, newcontents, 0, size)) { ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + if (!memcmp(oldcontents, newcontents, size)) { + msg_cinfo("Good. It seems nothing was changed.\n"); + nonfatal_help_message(); +@@ -2014,14 +2154,22 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it, + if (write_it) { + /* Work around chips which need some time to calm down. */ + programmer_delay(1000*1000); ++#if DELL_DENVERTON_SUPPORT == 1 ++ ret = verify_range(flash, newcontents + bios_start, bios_start, bios_size); ++#else + ret = verify_range(flash, newcontents, 0, size); ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + /* If we tried to write, and verification now fails, we + * might have an emergency situation. + */ + if (ret) + emergency_help_message(); + } else { ++#if DELL_DENVERTON_SUPPORT == 1 ++ ret = compare_range(newcontents + bios_start, oldcontents + bios_start, bios_start, bios_size); ++#else + ret = compare_range(newcontents, oldcontents, 0, size); ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + } + if (!ret) + msg_cinfo("VERIFIED.\n"); +diff --git a/ft2232_spi.c b/ft2232_spi.c +index 81be051..44354fd 100644 +--- a/ft2232_spi.c ++++ b/ft2232_spi.c +@@ -43,6 +43,7 @@ + #define FTDI_FT4232H_PID 0x6011 + #define FTDI_FT232H_PID 0x6014 + #define TIAO_TUMPA_PID 0x8a98 ++#define TIAO_TUMPA_LITE_PID 0x8a99 + #define AMONTEC_JTAGKEY_PID 0xCFF8 + + #define GOEPEL_VID 0x096C +@@ -62,6 +63,7 @@ const struct dev_entry devs_ft2232spi[] = { + {FTDI_VID, FTDI_FT4232H_PID, OK, "FTDI", "FT4232H"}, + {FTDI_VID, FTDI_FT232H_PID, OK, "FTDI", "FT232H"}, + {FTDI_VID, TIAO_TUMPA_PID, OK, "TIAO", "USB Multi-Protocol Adapter"}, ++ {FTDI_VID, TIAO_TUMPA_LITE_PID, OK, "TIAO", "USB Multi-Protocol Adapter Lite"}, + {FTDI_VID, AMONTEC_JTAGKEY_PID, OK, "Amontec", "JTAGkey"}, + {GOEPEL_VID, GOEPEL_PICOTAP_PID, OK, "GOEPEL", "PicoTAP"}, + {FIC_VID, OPENMOKO_DBGBOARD_PID, OK, "FIC", "OpenMoko Neo1973 Debug board (V2+)"}, +@@ -208,6 +210,10 @@ int ft2232_spi_init(void) + /* Interface A is SPI1, B is SPI2. */ + ft2232_type = TIAO_TUMPA_PID; + channel_count = 2; ++ } else if (!strcasecmp(arg, "tumpalite")) { ++ /* Only one channel is used on lite edition */ ++ ft2232_type = TIAO_TUMPA_LITE_PID; ++ channel_count = 1; + } else if (!strcasecmp(arg, "busblaster")) { + /* In its default configuration it is a jtagkey clone */ + ft2232_type = FTDI_FT2232H_PID; +diff --git a/gfxnvidia.c b/gfxnvidia.c +index d0a9feb..d3ee14e 100644 +--- a/gfxnvidia.c ++++ b/gfxnvidia.c +@@ -77,12 +77,6 @@ static const struct par_programmer par_programmer_gfxnvidia = { + .chip_writen = fallback_chip_writen, + }; + +-static int gfxnvidia_shutdown(void *data) +-{ +- physunmap(nvidia_bar, GFXNVIDIA_MEMMAP_SIZE); +- return 0; +-} +- + int gfxnvidia_init(void) + { + struct pci_dev *dev = NULL; +@@ -96,12 +90,14 @@ int gfxnvidia_init(void) + return 1; + + io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); ++ if (!io_base_addr) ++ return 1; ++ + io_base_addr += 0x300000; + msg_pinfo("Detected NVIDIA I/O base address: 0x%x.\n", io_base_addr); + +- nvidia_bar = physmap("NVIDIA", io_base_addr, GFXNVIDIA_MEMMAP_SIZE); +- +- if (register_shutdown(gfxnvidia_shutdown, NULL)) ++ nvidia_bar = rphysmap("NVIDIA", io_base_addr, GFXNVIDIA_MEMMAP_SIZE); ++ if (nvidia_bar == ERROR_PTR) + return 1; + + /* Allow access to flash interface (will disable screen). */ +diff --git a/hwaccess.h b/hwaccess.h +index fd6eb12..83f349e 100644 +--- a/hwaccess.h ++++ b/hwaccess.h +@@ -37,7 +37,13 @@ + * or as builtin. + */ + #define index shadow_workaround_index ++ ++#if !defined (__NetBSD__) && !defined (__DragonFly__) + #include ++#else ++#include ++#endif ++ + #undef index + #endif + +diff --git a/ich_descriptors.c b/ich_descriptors.c +index 528717b..c007867 100644 +--- a/ich_descriptors.c ++++ b/ich_descriptors.c +@@ -45,6 +45,11 @@ + #define min(a, b) (a < b) ? a : b + #endif + ++#if DELL_DENVERTON_SUPPORT == 1 ++#define DELL_DENVERTON_MAX_DENSITY 7 ++extern int8_t is_dnv; // if 1 chipset is denverton serial, 0 otherwise ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity) + { + print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF); +@@ -100,6 +105,36 @@ void prettyprint_ich_descriptor_content(const struct ich_desc_content *cont) + + void prettyprint_ich_descriptor_component(const struct ich_descriptors *desc) + { ++#if DELL_DENVERTON_SUPPORT == 1 ++ static const char * const dnv_freq_str[8] = { ++ "reserved", /* 000 */ ++ "reserved", /* 001 */ ++ "48 MHz", /* 010 */ ++ "reserved", /* 011 */ ++ "30MHz", /* 100 */ ++ "reserved", /* 101 */ ++ "17 MHz", /* 110 */ ++ "reserved", /* 111 */ ++ }; ++ static const char * const dnv_size_str[16] = { ++ "512 kB", /* 0000 */ ++ " 1 MB", /* 0001 */ ++ " 2 MB", /* 0010 */ ++ " 4 MB", /* 0011 */ ++ " 8 MB", /* 0100 */ ++ " 16 MB", /* 0101 */ ++ " 32 MB", /* 0110 */ ++ " 64 MB", /* 0111 */ ++ "reserved", /* 1000 */ ++ "reserved", /* 1001 */ ++ "reserved", /* 1010 */ ++ "reserved", /* 1011 */ ++ "reserved", /* 1100 */ ++ "reserved", /* 1101 */ ++ "reserved", /* 1110 */ ++ "reserved", /* 1111 */ ++ }; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + static const char * const freq_str[8] = { + "20 MHz", /* 000 */ + "33 MHz", /* 001 */ +@@ -121,6 +156,47 @@ void prettyprint_ich_descriptor_component(const struct ich_descriptors *desc) + "reserved", /* 111 */ + }; + ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) { ++ msg_pdbg2("=== Component Section ===\n"); ++ msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP); ++ msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL ); ++ msg_pdbg2("\n"); ++ ++ msg_pdbg2("--- Details ---\n"); ++ msg_pdbg2("Component 1 density: %s\n", ++ dnv_size_str[desc->component.dnv_comp1_density]); ++ if (desc->content.NC) ++ msg_pdbg2("Component 2 density: %s\n", ++ dnv_size_str[desc->component.dnv_comp2_density]); ++ else ++ msg_pdbg2("Component 2 is not used.\n"); ++ msg_pdbg2("Read Clock Frequency: %s\n", ++ dnv_freq_str[desc->component.dnv_freq_read]); ++ msg_pdbg2("Read ID and Status Clock Freq.: %s\n", ++ dnv_freq_str[desc->component.dnv_freq_read_id]); ++ msg_pdbg2("Write and Erase Clock Freq.: %s\n", ++ dnv_freq_str[desc->component.dnv_freq_write]); ++ msg_pdbg2("Fast Read is %ssupported.\n", ++ desc->component.dnv_fastread ? "" : "not "); ++ if (desc->component.dnv_fastread) ++ msg_pdbg2("Fast Read Clock Frequency: %s\n", ++ dnv_freq_str[desc->component.dnv_freq_fastread]); ++ if (desc->component.FLILL == 0) ++ msg_pdbg2("No forbidden opcodes.\n"); ++ else { ++ msg_pdbg2("Invalid instruction 0: 0x%02x\n", ++ desc->component.invalid_instr0); ++ msg_pdbg2("Invalid instruction 1: 0x%02x\n", ++ desc->component.invalid_instr1); ++ msg_pdbg2("Invalid instruction 2: 0x%02x\n", ++ desc->component.invalid_instr2); ++ msg_pdbg2("Invalid instruction 3: 0x%02x\n", ++ desc->component.invalid_instr3); ++ } ++ } else { ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + msg_pdbg2("=== Component Section ===\n"); + msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP); + msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL ); +@@ -157,6 +233,9 @@ void prettyprint_ich_descriptor_component(const struct ich_descriptors *desc) + msg_pdbg2("Invalid instruction 3: 0x%02x\n", + desc->component.invalid_instr3); + } ++#if DELL_DENVERTON_SUPPORT == 1 ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + msg_pdbg2("\n"); + } + +@@ -171,6 +250,12 @@ static void pprint_freg(const struct ich_desc_region *reg, uint32_t i) + } + uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]); + uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]); ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) { ++ base = DELL_DENVERTON_FREG_BASE(reg->FLREGs[i]); ++ limit = DELL_DENVERTON_FREG_LIMIT(reg->FLREGs[i]); ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + msg_pdbg2("Region %d (%-6s) ", i, region_names[i]); + if (base > limit) + msg_pdbg2("is unused.\n"); +@@ -741,17 +826,36 @@ int getFCBA_component_density(const struct ich_descriptors *desc, uint8_t idx) + msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n"); + return 0; + } ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) { ++ if (size_enc > DELL_DENVERTON_MAX_DENSITY) { ++ msg_perr("Density of ICH SPI component with index %d is invalid. Encoded density is 0x%x.\n", idx, size_enc); ++ return 0; ++ } ++ } else { ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + if (size_enc > 5) { + msg_perr("Density of ICH SPI component with index %d is invalid. Encoded density is 0x%x.\n", + idx, size_enc); + return 0; + } ++#if DELL_DENVERTON_SUPPORT == 1 ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + return (1 << (19 + size_enc)); + } + + static uint32_t read_descriptor_reg(uint8_t section, uint16_t offset, void *spibar) + { + uint32_t control = 0; ++#if DELL_DENVERTON_SUPPORT == 1 ++ if (is_dnv) { ++ control |= (section << DENVERTON_FDOC_FDSS_OFF) & DENVERTON_FDOC_FDSS; ++ control |= (offset << DENVERTON_FDOC_FDSI_OFF) & DENVERTON_FDOC_FDSI; ++ mmio_le_writel(control, spibar + DENVERTON_REG_FDOC); ++ return mmio_le_readl(spibar + DENVERTON_REG_FDOD); ++ } ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS; + control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI; + mmio_le_writel(control, spibar + ICH9_REG_FDOC); +diff --git a/ich_descriptors.h b/ich_descriptors.h +index 3a44740..914a3cd 100644 +--- a/ich_descriptors.h ++++ b/ich_descriptors.h +@@ -64,6 +64,19 @@ + #define ICH_FREG_BASE(flreg) (((flreg) << 12) & 0x01fff000) + #define ICH_FREG_LIMIT(flreg) (((flreg) >> 4) & 0x01fff000) + ++#if DELL_DENVERTON_SUPPORT == 1 ++#define DENVERTON_REG_FDOC 0xB4 ++#define DENVERTON_FDOC_FDSI_OFF 2 ++#define DENVERTON_FDOC_FDSI (0x3ff << DENVERTON_FDOC_FDSI_OFF) ++#define DENVERTON_FDOC_FDSS_OFF 12 ++#define DENVERTON_FDOC_FDSS (0x3 << DENVERTON_FDOC_FDSS_OFF) ++ ++#define DENVERTON_REG_FDOD 0xB8 ++ ++#define DELL_DENVERTON_FREG_BASE(flreg) (((flreg) << 12) & 0x03fff000) ++#define DELL_DENVERTON_FREG_LIMIT(flreg) (((flreg) >> 4) & 0x03fff000) ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity); + + struct ich_desc_content { +@@ -78,6 +91,15 @@ struct ich_desc_content { + NR :3, /* Number Of Regions */ + :5; + }; ++#if DELL_DENVERTON_SUPPORT == 1 ++ struct { ++ int32_t dnv_FCBA :8, /* Flash Component Base Address */ ++ dnv_NC :2, /* Number Of Components */ ++ :6, ++ dnv_FRBA :8, /* Flash Region Base Address */ ++ :8; ++ }; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + }; + union { /* 0x08 */ + uint32_t FLMAP1; +@@ -113,6 +135,20 @@ struct ich_desc_component { + freq_read_id :3, + :2; + }; ++#if DELL_DENVERTON_SUPPORT == 1 ++ struct { ++ uint32_t dnv_comp1_density :4, ++ dnv_comp2_density :4, ++ :9, ++ dnv_freq_read :3, ++ dnv_fastread :1, ++ dnv_freq_fastread :3, ++ dnv_freq_write :3, ++ dnv_freq_read_id :3, ++ dnv_dualfastread :1, ++ :1; ++ }; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + }; + union { /* 0x04 */ + uint32_t FLILL; /* Flash Invalid Instructions Register */ +@@ -129,6 +165,15 @@ struct ich_desc_component { + uint32_t FPBA :13, /* Flash Partition Boundary Addr */ + :19; + }; ++#if DELL_DENVERTON_SUPPORT == 1 ++ uint32_t FLILL1; /* Flash Partition Boundary Register for dnv */ ++ struct { ++ uint32_t invalid_instr4 :8, ++ invalid_instr5 :8, ++ invalid_instr6 :8, ++ invalid_instr7 :8; ++ }; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + }; + }; + +@@ -167,6 +212,65 @@ struct ich_desc_region { + :3; + }; + }; ++#if DELL_DENVERTON_SUPPORT == 1 ++ struct { /* FLREG0 Flash Descriptor */ ++ uint32_t dnv_reg0_base :15, ++ :1, ++ dnv_reg0_limit :15, ++ :1; ++ }; ++ struct { /* FLREG1 BIOS */ ++ uint32_t dnv_reg1_base :15, ++ :1, ++ dnv_reg1_limit :15, ++ :1; ++ }; ++ struct { /* FLREG2 ME */ ++ uint32_t dnv_reg2_base :15, ++ :1, ++ dnv_reg2_limit :15, ++ :1; ++ }; ++ ++ /* FLREG3 - Reserved */ ++ ++ struct { /* FLREG4 Platform */ ++ uint32_t dnv_reg4_base :15, ++ :1, ++ dnv_reg4_limit :15, ++ :1; ++ }; ++ ++ /* FLREG5 - Reserved */ ++ /* FLREG6 - Reserved */ ++ /* FLREG7 - Reserved */ ++ /* FLREG8 - Reserved */ ++ /* FLREG9 - Reserved */ ++ ++ struct { /* FLREG10 IE */ ++ uint32_t dnv_reg10_base :15, ++ :1, ++ dnv_reg10_limit :15, ++ :1; ++ }; ++ struct { /* FLREG11 LAN CTRL0 */ ++ uint32_t dnv_reg11_base :15, ++ :1, ++ dnv_reg11_limit :15, ++ :1; ++ }; ++ struct { /* FLREG12 LAN CTRL1 */ ++ uint32_t dnv_reg12_base :15, ++ :1, ++ dnv_reg12_limit :15, ++ :1; ++ }; ++ ++ /* FLREG13 - Reserved */ ++ /* FLREG14 - Reserved */ ++ /* FLREG15 - Reserved */ ++ ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + }; + }; + +diff --git a/ichspi.c b/ichspi.c +index 6d1bd1a..742d424 100644 +--- a/ichspi.c ++++ b/ichspi.c +@@ -170,6 +170,52 @@ + #define ICH7_REG_OPTYPE 0x56 /* 16 Bits */ + #define ICH7_REG_OPMENU 0x58 /* 64 Bits */ + ++/* denverton controller register definition */ ++#if DELL_DENVERTON_SUPPORT == 1 ++#define DENVERTON_REG_BFPREG 0x00 /* 32 Bits SPI BIOS MMIO PRI */ ++#define DENVERTON_BFPREG_PRB_OFF 0 /* 0-14: BIOS Flash Promary Region Base */ ++#define DENVERTON_BFPREG_PRB (0x7FFF << DENVERTON_BFPREG_PRB_OFF) ++#define DENVERTON_BFPREG_PRL_OFF 16 /* 16-30: BIOS Flash Primary Region Limit */ ++#define DENVERTON_BFPREG_PRL (0xFFFF << DENVERTON_BFPREG_PRL_OFF) ++#define DENVERTON_REG_HSFS 0x04 /* 16 Bits Hardware Sequencing Flash Status */ ++#define DENVERTON_HSFS_FDONE_OFF 0 /* 0: Flash Cycle Done */ ++#define DENVERTON_HSFS_FDONE (0x1 << DENVERTON_HSFS_FDONE_OFF) ++#define DENVERTON_HSFS_FCERR_OFF 1 /* 1: Flash Cycle Error */ ++#define DENVERTON_HSFS_FCERR (0x1 << DENVERTON_HSFS_FCERR_OFF) ++#define DENVERTON_HSFS_FDOPSS_OFF 13 /* 13: Flash Descriptor Override Pin-Strap Status */ ++#define DENVERTON_HSFS_FDOPSS (0x1 << DENVERTON_HSFS_FDOPSS_OFF) ++#define DENVERTON_HSFS_FDV_OFF 14 /* 14: Flash Descriptor Valid */ ++#define DENVERTON_HSFS_FDV (0x1 << DENVERTON_HSFS_FDV_OFF) ++#define DENVERTON_HSFS_FLOCKDN_OFF 15 /* 15: Flash Configuration Lock-Down */ ++#define DENVERTON_HSFS_FLOCKDN (0x1 << DENVERTON_HSFS_FLOCKDN_OFF) ++#define DENVERTON_REG_HSFC 0x06 /* 16 Bits Hardware Sequencing Flash Control */ ++#define DENVERTON_HSFC_FGO_OFF 0 /* 0: Flash Cycle Go */ ++#define DENVERTON_HSFC_FGO (0x1 << DENVERTON_HSFC_FGO_OFF) ++#define DENVERTON_HSFC_FCYCLE_OFF 1 /* 1- 4: FLASH Cycle */ ++#define DENVERTON_HSFC_FCYCLE (0xF << DENVERTON_HSFC_FCYCLE_OFF) ++#define DENVERTON_HSFC_FDBC_OFF 8 /* 8-13: Flash Data Byte Count */ ++#define DENVERTON_HSFC_FDBC (0x3F << DENVERTON_HSFC_FDBC_OFF) ++#define DENVERTON_REG_FADDR 0x08 /* 32 Bits */ ++#define DENVERTON_REG_FDATA0 0x10 /* 32 Bits */ ++#define DENVERTON_REG_FRAP 0x50 /* 32 Bytes Flash Region Access Permissions */ ++#define DENVERTON_REG_FREG0 0x54 /* 32 Bytes Flash Region 0 */ ++#define DENVERTON_REG_PR0 0x84 /* 32 Bytes Protected Range 0 */ ++#define DENVERTON_PR_WP_OFF 31 /* 31: write protection enable */ ++#define DENVERTON_PR_RP_OFF 15 /* 15: read protection enable */ ++#define DENVERTON_REG_VSCC0 0xC4 /* 32 Bits Host Vendor Specific Component Capabilities for Component 0 */ ++#define DENVERTON_REG_VSCC1 0xC8 /* 32 Bits Host Vendor Specific Component Capabilities for Component 1 */ ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ ++#ifdef DELL_AVOTON_SUPPORT ++extern int8_t is_avoton; ++#endif /* DELL_AVOTON_SUPPORT */ ++ ++#if DELL_DENVERTON_SUPPORT == 1 ++extern uint32_t dnv_bios_region_start; ++extern uint32_t dnv_bios_region_size; ++extern uint32_t dnv_bios_region_limit; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + /* ICH SPI configuration lock-down. May be set during chipset enabling. */ + static int ichspi_lock = 0; + +@@ -466,6 +512,8 @@ static int generate_opcodes(OPCODES * op) + + switch (ich_generation) { + case CHIPSET_ICH7: ++ case CHIPSET_TUNNEL_CREEK: ++ case CHIPSET_CENTERTON: + preop = REGREAD16(ICH7_REG_PREOP); + optype = REGREAD16(ICH7_REG_OPTYPE); + opmenu[0] = REGREAD32(ICH7_REG_OPMENU); +@@ -529,7 +577,7 @@ static int program_opcodes(OPCODES *op, int enable_undo) + opmenu[0] |= ((uint32_t) op->opcode[a].opcode) << (a * 8); + } + +- /*Program Allowable Opcodes 4 - 7 */ ++ /* Program Allowable Opcodes 4 - 7 */ + opmenu[1] = 0; + for (a = 4; a < 8; a++) { + opmenu[1] |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8); +@@ -538,6 +586,8 @@ static int program_opcodes(OPCODES *op, int enable_undo) + msg_pdbg2("\n%s: preop=%04x optype=%04x opmenu=%08x%08x\n", __func__, preop, optype, opmenu[0], opmenu[1]); + switch (ich_generation) { + case CHIPSET_ICH7: ++ case CHIPSET_TUNNEL_CREEK: ++ case CHIPSET_CENTERTON: + /* Register undo only for enable_undo=1, i.e. first call. */ + if (enable_undo) { + rmmio_valw(ich_spibar + ICH7_REG_PREOP); +@@ -603,10 +653,19 @@ static void ich_set_bbar(uint32_t min_addr) + int bbar_off; + switch (ich_generation) { + case CHIPSET_ICH7: ++ case CHIPSET_TUNNEL_CREEK: ++ case CHIPSET_CENTERTON: + bbar_off = 0x50; + break; + case CHIPSET_ICH8: ++#ifdef DELL_AVOTON_SUPPORT ++ case CHIPSET_AVOTON: ++#endif ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("BBAR offset is unknown on ICH8!\n"); ++#else + msg_perr("BBAR offset is unknown on ICH8!\n"); ++#endif + return; + case CHIPSET_ICH9: + default: /* Future version might behave the same */ +@@ -817,11 +876,17 @@ static int ich7_run_opcode(OPCODE op, uint32_t offset, + /* FIXME: make sure we do not needlessly cause transaction errors. */ + temp16 = REGREAD16(ICH7_REG_SPIS); + if (temp16 & SPIS_FCERR) { ++#ifndef FORCE10_SPI_CHANGE + msg_perr("Transaction error!\n"); ++#endif + /* keep reserved bits */ + temp16 &= SPIS_RESERVED_MASK; + REGWRITE16(ICH7_REG_SPIS, temp16 | SPIS_FCERR); ++#ifndef FORCE10_SPI_CHANGE + return 1; ++#else ++ return 0; ++#endif + } + + if ((!write_cmd) && (datalength != 0)) +@@ -838,6 +903,22 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset, + uint32_t temp32; + uint64_t opmenu; + int opcode_index; ++/* skip unused region for Rangeley */ ++ if (offset >= 0x10000 && offset <= 0x9fffff) { ++ uint32_t i = 0; ++ for (i = 0; i < datalength; i++) ++ *(data + i) = 0xff; ++ return 0; ++ } ++#ifdef DELL_AVOTON_SUPPORT ++ /* skip unused region for Rangeley */ ++ if (is_avoton && offset >= 0x10000 && offset <= 0x9fffff) { ++ uint32_t i = 0; ++ for (i = 0; i < datalength; i++) ++ *(data + i) = 0xff; ++ return 0; ++ } ++#endif /* AVOTON */ + + /* Is it a write command? */ + if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) +@@ -939,14 +1020,20 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset, + /* FIXME make sure we do not needlessly cause transaction errors. */ + temp32 = REGREAD32(ICH9_REG_SSFS); + if (temp32 & SSFS_FCERR) { ++#ifndef FORCE10_SPI_CHANGE + msg_perr("Transaction error!\n"); ++#endif + prettyprint_ich9_reg_ssfs(temp32); + prettyprint_ich9_reg_ssfc(temp32); + /* keep reserved bits */ + temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK; + /* Clear the transaction error. */ + REGWRITE32(ICH9_REG_SSFS, temp32 | SSFS_FCERR); ++#ifndef FORCE10_SPI_CHANGE + return 1; ++#else ++ return 0; ++#endif + } + + if ((!write_cmd) && (datalength != 0)) +@@ -975,6 +1062,8 @@ static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset, + + switch (ich_generation) { + case CHIPSET_ICH7: ++ case CHIPSET_TUNNEL_CREEK: ++ case CHIPSET_CENTERTON: + return ich7_run_opcode(op, offset, datalength, data, maxlength); + case CHIPSET_ICH8: + default: /* Future version might behave the same */ +@@ -1418,6 +1507,191 @@ static int ich_spi_send_multicommand(struct flashctx *flash, + return ret; + } + ++#if DELL_DENVERTON_SUPPORT == 1 ++/* Sets FLA in FADDR to (addr & 0x01FFFFFF) without touching other bits. */ ++static void dnv_hwseq_set_addr(uint32_t addr) ++{ ++ uint32_t addr_old = REGREAD32(DENVERTON_REG_FADDR) & ~0x01FFFFFF; ++ REGWRITE32(DENVERTON_REG_FADDR, (addr & 0x01FFFFFF) | addr_old); ++} ++ ++/* Polls for Cycle Done Status, Flash Cycle Error or timeout in 8 us intervals. ++ Resets all error flags in HSFS. ++ Returns 0 if the cycle completes successfully without errors within ++ timeout us, 1 on errors. */ ++static int dnv_hwseq_wait_for_cycle_complete(uint32_t timeout, ++ uint32_t len) ++{ ++ uint16_t hsfs; ++ uint32_t addr; ++ ++ timeout /= 8; /* scale timeout duration to counter */ ++ while ((((hsfs = REGREAD16(DENVERTON_REG_HSFS)) & ++ (DENVERTON_HSFS_FDONE | DENVERTON_HSFS_FCERR)) == 0) && ++ --timeout) { ++ programmer_delay(8); ++ } ++ REGWRITE16(DENVERTON_REG_HSFS, REGREAD16(DENVERTON_REG_HSFS)); ++ if (!timeout) { ++ addr = REGREAD32(DENVERTON_REG_FADDR) & 0x01FFFFFF; ++ msg_perr("Timeout error between offset 0x%08x and " ++ "0x%08x (= 0x%08x + %d)!\n", ++ addr, addr + len - 1, addr, len - 1); ++ return 1; ++ } ++ ++ if (hsfs & DENVERTON_HSFS_FCERR) { ++ addr = REGREAD32(DENVERTON_REG_FADDR) & 0x01FFFFFF; ++ msg_perr("Transaction error between offset 0x%08x and " ++ "0x%08x (= 0x%08x + %d)!\n", ++ addr, addr + len - 1, addr, len - 1); ++ return 1; ++ } ++ return 0; ++} ++ ++int dnv_read_JEDEC_ID(uint8_t *buf) ++{ ++ uint16_t hsfc; ++ uint16_t timeout = 100 * 60; ++ uint8_t len = 3; ++ ++ /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */ ++ REGWRITE16(DENVERTON_REG_HSFS, REGREAD16(DENVERTON_REG_HSFS)); ++ ++ dnv_hwseq_set_addr(0); ++ hsfc = REGREAD16(DENVERTON_REG_HSFC); ++ hsfc &= ~DENVERTON_HSFC_FCYCLE; /* clear operation */ ++ hsfc |= (0x6 << DENVERTON_HSFC_FCYCLE_OFF); /* set read JEDEC ID operation */ ++ hsfc &= ~DENVERTON_HSFC_FDBC; /* clear byte count */ ++ /* set byte count */ ++ hsfc |= (((len - 1) << DENVERTON_HSFC_FDBC_OFF) & DENVERTON_HSFC_FDBC); ++ hsfc |= DENVERTON_HSFC_FGO; /* start */ ++ REGWRITE16(DENVERTON_REG_HSFC, hsfc); ++ ++ if (dnv_hwseq_wait_for_cycle_complete(timeout, len)) ++ return 1; ++ ich_read_data(buf, len, DENVERTON_REG_FDATA0); ++ return 0; ++} ++ ++static int dnv_hwseq_probe(struct flashctx *flash) ++{ ++ uint8_t jedec_id[3]; ++ uint32_t tmp, manufacture_id, model_id; ++ struct block_eraser *eraser; ++ const struct flashchip *chip; ++ ++ msg_gdbg("Using HW Sequency to read JEDEC ID and find SPI flash.\n"); ++ if (dnv_read_JEDEC_ID(jedec_id)) { ++ msg_cerr("Can't get JEDEC ID through HW Sequency\n"); ++ return -1; ++ } ++ ++ manufacture_id = (uint32_t)jedec_id[0]; ++ model_id = (uint32_t)(jedec_id[1] << 8 | jedec_id[2]); ++ ++ for (chip = flashchips; chip && chip->name; chip++) { ++ if (chip->manufacture_id == manufacture_id && chip->model_id == model_id) { ++ break; ++ } ++ } ++ ++ flash->bios_size = (hwseq_data.size_comp0 + hwseq_data.size_comp1) / 1024; ++ ++ /* We only replace base information. The functions still use hw sequency, like read and write */ ++ flash->chip->vendor = chip->vendor; ++ flash->chip->name = chip->name; ++ flash->chip->manufacture_id = chip->manufacture_id; ++ flash->chip->model_id = chip->model_id; ++ flash->chip->total_size = chip->total_size; ++ flash->chip->page_size = chip->page_size; ++ ++ msg_cdbg("Hardware sequencing reports %d attached SPI flash chip", ++ (hwseq_data.size_comp1 != 0) ? 2 : 1); ++ if (hwseq_data.size_comp1 != 0) ++ msg_cdbg("s with a combined"); ++ else ++ msg_cdbg(" with a"); ++ msg_cdbg(" density of %d kB.\n", flash->chip->total_size); ++ ++ eraser = &(flash->chip->block_erasers[0]); ++ tmp = mmio_readl(ich_spibar + DENVERTON_REG_BFPREG); ++ dnv_bios_region_start = ((tmp & DENVERTON_BFPREG_PRB) >> DENVERTON_BFPREG_PRB_OFF) << 12; ++ dnv_bios_region_limit = ((tmp & DENVERTON_BFPREG_PRL) >> ++ DENVERTON_BFPREG_PRL_OFF) << 12 | ((1 << 12) -1); ++ dnv_bios_region_size = dnv_bios_region_limit - dnv_bios_region_start + 1; ++ eraser->eraseblocks[0].size = 4 * 1024; // 4K ++ eraser->eraseblocks[0].count = dnv_bios_region_size / ++ eraser->eraseblocks[0].size; ++ ++ flash->chip->tested = TEST_OK_PREW; ++ return 1; ++} ++ ++static int dnv_block_check(struct flashctx *flash, uint32_t addr, uint32_t len, SPI_SMI_CMD cmd) ++{ ++ char msg[3][4][32] = { ++ {"Read", "read", "", "Reading"}, ++ {"Erase", "erase", "Not erasing anthing.", "Erasing"}, ++ {"Write", "write", "", "Writing"}}; ++ ++ /* Although the hardware supports this (it would erase the whole block ++ * containing the address) we play safe here. */ ++ if (addr % DELL_DENVERTON_BLOCK_SIZE != 0) { ++ msg_cerr("%s address 0x%06x is not aligned to the %s " ++ "block boundary (any multiple of %d). %s\n", ++ msg[cmd][0], addr, msg[cmd][1], DELL_DENVERTON_BLOCK_SIZE, msg[cmd][2]); ++ return -1; ++ } ++ ++ if (addr + len > flash->chip->total_size * 1024) { ++ msg_perr("Request to %s some inaccessible memory address(es)" ++ " (addr=0x%x, len=%d). %s\n", msg[cmd][1], ++ addr, len, msg[cmd][2]); ++ return -1; ++ } ++ ++ msg_pdbg("%s %d bytes starting at 0x%06x.\n", msg[cmd][3], len, addr); ++ return 0; ++} ++ ++static int dnv_smi_spi(struct flashctx *flash, uint8_t *buf, uint32_t addr, ++ uint32_t len, SPI_SMI_CMD cmd) ++{ ++ int32_t ret = 0; ++ uint32_t block_index = 0; ++ ++ ret = dnv_block_check(flash, addr, len, cmd); ++ if (ret == 0) { ++ for (block_index = 0; block_index * DELL_DENVERTON_BLOCK_SIZE < len; block_index++ ) { ++ if ((ret = dnv_smi_doit(addr - dnv_bios_region_start, buf, cmd)) != 0) { ++ break; ++ } ++ buf += DELL_DENVERTON_BLOCK_SIZE; ++ addr += DELL_DENVERTON_BLOCK_SIZE; ++ } ++ } ++ return ret; ++} ++ ++static int dnv_smi_erase_spi(struct flashctx *flash, uint32_t addr, uint32_t len) ++{ ++ return dnv_smi_spi(flash, NULL, addr, len, SMI_ERASE_SPI); ++} ++ ++static int dnv_smi_read_spi(struct flashctx *flash, uint8_t *buf, uint32_t addr, uint32_t len) ++{ ++ return dnv_smi_spi(flash, buf, addr, len, SMI_READ_SPI); ++} ++ ++static int dnv_smi_write_spi(struct flashctx *flash, uint8_t *buf, uint32_t addr, uint32_t len) ++{ ++ return dnv_smi_spi(flash, buf, addr, len, SMI_WRITE_SPI); ++} ++ ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + #define ICH_BMWAG(x) ((x >> 24) & 0xff) + #define ICH_BMRAG(x) ((x >> 16) & 0xff) + #define ICH_BRWA(x) ((x >> 8) & 0xff) +@@ -1452,6 +1726,9 @@ static int ich9_handle_frap(uint32_t frap, int i) + msg_pdbg("FREG%i: %s region (0x%08x-0x%08x) is %s.\n", i, + region_names[i], base, (limit | 0x0fff), + access_names[rwperms]); ++#ifdef FORCE10_SPI_CHANGE ++ add_romentry(base, (limit | 0x0fff), region_names[i]); ++#endif + return 0; + } + +@@ -1514,6 +1791,90 @@ static void ich9_set_pr(int i, int read_prot, int write_prot) + msg_gspew("resulted in 0x%08x.\n", mmio_readl(addr)); + } + ++#if DELL_DENVERTON_SUPPORT == 1 ++/* returns 0 if region is unused or r/w */ ++static int dnv_handle_frap(uint32_t frap, int32_t i) ++{ ++ static const char *const access_names[4] = { ++ "locked", "read-only", "write-only", "read-write" ++ }; ++ static const char *const region_names[5] = { ++ "Flash Descriptor", "BIOS", "Management Engine", ++ "Gigabit Ethernet", "Platform Data" ++ }; ++ uint32_t base, limit; ++ int32_t rwperms = (((ICH_BRWA(frap) >> i) & 1) << 1) | ++ (((ICH_BRRA(frap) >> i) & 1) << 0); ++ int32_t offset = DENVERTON_REG_FREG0 + i * 4; ++ uint32_t freg = mmio_readl(ich_spibar + offset); ++ ++ base = ICH_FREG_BASE(freg); ++ limit = ICH_FREG_LIMIT(freg); ++ if (base > limit || (freg == 0 && i > 0)) { ++ /* this FREG is disabled */ ++ msg_pdbg2("0x%02X: 0x%08x FREG%i: %s region is unused.\n", ++ offset, freg, i, region_names[i]); ++ return 0; ++ } ++ msg_pdbg("0x%02X: 0x%08x ", offset, freg); ++ if (rwperms == 0x3) { ++ msg_pdbg("FREG%i: %s region (0x%08x-0x%08x) is %s.\n", i, ++ region_names[i], base, (limit | 0x0fff), ++ access_names[rwperms]); ++ return 0; ++ } ++ ++ msg_pwarn("FREG%i: Warning: %s region (0x%08x-0x%08x) is %s.\n", i, ++ region_names[i], base, (limit | 0x0fff), ++ access_names[rwperms]); ++ return 1; ++} ++ ++/* returns 0 if range is unused (i.e. r/w) */ ++static int dnv_handle_pr(int32_t i) ++{ ++ static const char *const access_names[3] = { ++ "locked", "read-only", "write-only" ++ }; ++ uint8_t off = DENVERTON_REG_PR0 + (i * 4); ++ uint32_t pr = mmio_readl(ich_spibar + off); ++ uint32_t rwperms = ICH_PR_PERMS(pr); ++ ++ if (rwperms == 0x3) { ++ msg_pdbg2("0x%02X: 0x%08x (PR%u is unused)\n", off, pr, i); ++ return 0; ++ } ++ ++ msg_pdbg("0x%02X: 0x%08x ", off, pr); ++ msg_pwarn("PR%u: Warning: 0x%08x-0x%08x is %s.\n", i, ICH_FREG_BASE(pr), ++ ICH_FREG_LIMIT(pr) | 0x0fff, access_names[rwperms]); ++ return 1; ++} ++ ++/* Set/Clear the read and write protection enable bits of PR register @i ++ * according to @read_prot and @write_prot. */ ++static void dnv_set_pr(int32_t i, int32_t read_prot, int32_t write_prot) ++{ ++ void *addr = ich_spibar + DENVERTON_REG_PR0 + (i * 4); ++ uint32_t old = mmio_readl(addr); ++ uint32_t new; ++ ++ msg_gspew("PR%u is 0x%08x", i, old); ++ new = old & ~((1 << DENVERTON_PR_RP_OFF) | (1 << DENVERTON_PR_WP_OFF)); ++ if (read_prot) ++ new |= (1 << DENVERTON_PR_RP_OFF); ++ if (write_prot) ++ new |= (1 << DENVERTON_PR_WP_OFF); ++ if (old == new) { ++ msg_gspew(" already.\n"); ++ return; ++ } ++ msg_gspew(", trying to set it to 0x%08x ", new); ++ rmmio_writel(new, addr); ++ msg_gspew("resulted in 0x%08x.\n", mmio_readl(addr)); ++} ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ + static const struct spi_programmer spi_programmer_ich7 = { + .type = SPI_CONTROLLER_ICH7, + .max_data_read = 64, +@@ -1545,12 +1906,21 @@ static const struct opaque_programmer opaque_programmer_ich_hwseq = { + .erase = ich_hwseq_block_erase, + }; + +-int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb, +- enum ich_chipset ich_gen) ++#if DELL_DENVERTON_SUPPORT == 1 ++static const struct opaque_programmer opaque_master_dnv_hwseq = { ++ .max_data_read = 64, ++ .max_data_write = 64, ++ .probe = dnv_hwseq_probe, ++ .read = dnv_smi_read_spi, ++ .write = dnv_smi_write_spi, ++ .erase = dnv_smi_erase_spi, ++}; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ ++ ++int ich_init_spi(struct pci_dev *dev, void *spibar, enum ich_chipset ich_gen) + { + int i; +- uint8_t old, new; +- uint16_t spibar_offset, tmp2; ++ uint16_t tmp2; + uint32_t tmp; + char *arg; + int ich_spi_force = 0; +@@ -1564,42 +1934,18 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb, + } ich_spi_mode = ich_auto; + + ich_generation = ich_gen; +- +- switch (ich_generation) { +- case CHIPSET_ICH_UNKNOWN: +- return ERROR_FATAL; +- case CHIPSET_ICH7: +- case CHIPSET_ICH8: +- spibar_offset = 0x3020; +- break; +- case CHIPSET_ICH9: +- default: /* Future version might behave the same */ +- spibar_offset = 0x3800; +- break; +- } +- +- /* SPIBAR is at RCRB+0x3020 for ICH[78] and RCRB+0x3800 for ICH9. */ +- msg_pdbg("SPIBAR = 0x%x + 0x%04x\n", base, spibar_offset); +- +- /* Assign Virtual Address */ +- ich_spibar = rcrb + spibar_offset; ++ ich_spibar = spibar; + + switch (ich_generation) { + case CHIPSET_ICH7: ++ case CHIPSET_TUNNEL_CREEK: ++ case CHIPSET_CENTERTON: + msg_pdbg("0x00: 0x%04x (SPIS)\n", + mmio_readw(ich_spibar + 0)); + msg_pdbg("0x02: 0x%04x (SPIC)\n", + mmio_readw(ich_spibar + 2)); + msg_pdbg("0x04: 0x%08x (SPIA)\n", + mmio_readl(ich_spibar + 4)); +- for (i = 0; i < 8; i++) { +- int offs; +- offs = 8 + (i * 8); +- msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs, +- mmio_readl(ich_spibar + offs), i); +- msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4, +- mmio_readl(ich_spibar + offs + 4), i); +- } + ichspi_bbar = mmio_readl(ich_spibar + 0x50); + msg_pdbg("0x50: 0x%08x (BBAR)\n", + ichspi_bbar); +@@ -1625,7 +1971,123 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb, + ich_set_bbar(0); + register_spi_programmer(&spi_programmer_ich7); + break; ++#if DELL_DENVERTON_SUPPORT == 1 ++ case CHIPSET_DENVERTON: ++ ++ tmp2 = mmio_readw(ich_spibar + DENVERTON_REG_HSFS); ++ msg_pdbg("0x04: 0x%04x (HSFS)\n", tmp2); ++ if (tmp2 & DENVERTON_HSFS_FLOCKDN) { ++ msg_pwarn("Warning: SPI Configuration Lockdown activated.\n"); ++ ichspi_lock = 1; ++ } ++ if (tmp2 & DENVERTON_HSFS_FDV) ++ desc_valid = 1; ++ if (!(tmp2 & DENVERTON_HSFS_FDOPSS) && desc_valid) ++ msg_pinfo("The Flash Descriptor Override Strap-Pin is set. " ++ "Restrictions implied by\n" ++ "the Master Section of the flash descriptor are " ++ "NOT in effect. Please note\n" ++ "that Protected Range (PR) restrictions still apply.\n"); ++ if (desc_valid) { ++ tmp2 = mmio_readw(ich_spibar + DENVERTON_REG_HSFC); ++ msg_pdbg("0x06: 0x%04x (HSFC)\n", tmp2); ++ } ++ ++ tmp = mmio_readl(ich_spibar + DENVERTON_REG_FADDR); ++ msg_pdbg2("0x08: 0x%08x (FADDR)\n", tmp); ++ ++ if (desc_valid) { ++ tmp = mmio_readl(ich_spibar + DENVERTON_REG_FRAP); ++ msg_pdbg("0x50: 0x%08x (FRAP)", tmp); ++ ++ /* Handle FREGx and FRAP registers */ ++ for (i=0; i < 5; i++) ++ ich_spi_rw_restricted |= dnv_handle_frap(tmp, i); ++ if (ich_spi_rw_restricted) ++ msg_pwarn("Not all flash regions are freely accessible " ++ "by flashrom. This is most likely\n" ++ "due to an active ME. " ++ "Please see http://flashrom.org/ME for details.\n"); ++ } ++ ++ /* Handle PR registers */ ++ for (i = 0; i < 5; i++) { ++ if (!ichspi_lock) ++ dnv_set_pr(i, 0, 0); ++ ich_spi_rw_restricted |= dnv_handle_pr(i); ++ } ++ ++ if (ich_spi_force) ++ msg_pinfo("Continuing with write support because " ++ "the user forced us to!\n"); ++ ++ if (desc_valid) { ++ tmp = mmio_readl(ich_spibar + DENVERTON_REG_VSCC0); ++ msg_pdbg("0xC4: 0x%08x (VSCC0)\n", tmp); ++ ++ tmp = mmio_readl(ich_spibar + DENVERTON_REG_VSCC1); ++ msg_pdbg("0xC8: 0x%08x (VSCC1)\n", tmp); ++ ++ if (read_ich_descriptors_via_fdo(ich_spibar, &desc) == ICH_RET_OK) ++ prettyprint_ich_descriptors(ich_gen, &desc); ++ ++ /* If the descriptor is valid and indicates multiple ++ * flash devices we need to use hwseq to be able to ++ * access the second flash device. ++ */ ++ if (ich_spi_mode == ich_auto && desc.content.NC != 0) { ++ msg_pinfo("Enabling hardware sequencing due to " ++ "multiple flash chips detected.\n"); ++ ich_spi_mode = ich_hwseq; ++ } ++ } ++ ++ if (ich_spi_mode == ich_auto && ichspi_lock) { ++ msg_pinfo("Enabling hardware sequencing because " ++ "some important opcode is locked.\n"); ++ ich_spi_mode = ich_hwseq; ++ } ++ ++ if (ich_spi_mode == ich_auto && ichspi_lock) { ++ msg_pinfo("Enabling hardware sequencing because " ++ "some important opcode is locked.\n"); ++ ich_spi_mode = ich_hwseq; ++ } ++ ++ if (ich_spi_mode == ich_hwseq) { ++ if (!desc_valid) { ++ msg_perr("Hardware sequencing was requested " ++ "but the flash descriptor is not valid. Aborting.\n"); ++ return ERROR_FATAL; ++ } ++ ++ uint32_t tmpi = getFCBA_component_density(&desc, 0); ++ if (tmpi < 0) { ++ msg_perr("Could not determine density of " ++ "flash component %d.\n", 0); ++ return ERROR_FATAL; ++ } ++ hwseq_data.size_comp0 = tmpi; ++ ++ tmpi = getFCBA_component_density(&desc, 1); ++ if (tmpi < 0) { ++ msg_perr("Could not determine density of flash component %d.\n", 1); ++ return ERROR_FATAL; ++ } ++ hwseq_data.size_comp1 = tmpi; ++ ++ register_opaque_programmer(&opaque_master_dnv_hwseq); ++ } else { ++ msg_perr("[%s:%d] Error!!!\n", __func__, __LINE__); ++ return -1; ++ } ++ ++ break; ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + case CHIPSET_ICH8: ++#ifdef DELL_AVOTON_SUPPORT ++ case CHIPSET_AVOTON: ++#endif + default: /* Future version might behave the same */ + arg = extract_programmer_param("ich_spi_mode"); + if (arg && !strcmp(arg, "hwseq")) { +@@ -1669,7 +2131,11 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb, + msg_pdbg("0x04: 0x%04x (HSFS)\n", tmp2); + prettyprint_ich9_reg_hsfs(tmp2); + if (tmp2 & HSFS_FLOCKDN) { ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("Warning: SPI Configuration Lockdown activated.\n"); ++#else + msg_pwarn("Warning: SPI Configuration Lockdown activated.\n"); ++#endif + ichspi_lock = 1; + } + if (tmp2 & HSFS_FDV) +@@ -1690,6 +2156,7 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb, + msg_pdbg2("0x08: 0x%08x (FADDR)\n", tmp); + + if (desc_valid) { ++ + tmp = mmio_readl(ich_spibar + ICH9_REG_FRAP); + msg_pdbg("0x50: 0x%08x (FRAP)\n", tmp); + msg_pdbg("BMWAG 0x%02x, ", ICH_BMWAG(tmp)); +@@ -1750,10 +2217,15 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb, + msg_pdbg("VSCC: "); + prettyprint_ich_reg_vscc(tmp, MSG_DEBUG); + } else { ++#ifdef DELL_AVOTON_SUPPORT ++ if (ich_generation != CHIPSET_AVOTON) { ++#endif + ichspi_bbar = mmio_readl(ich_spibar + ICH9_REG_BBAR); + msg_pdbg("0xA0: 0x%08x (BBAR)\n", + ichspi_bbar); +- ++#ifdef DELL_AVOTON_SUPPORT ++ } ++#endif + if (desc_valid) { + tmp = mmio_readl(ich_spibar + ICH9_REG_LVSCC); + msg_pdbg("0xC4: 0x%08x (LVSCC)\n", tmp); +@@ -1811,21 +2283,6 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb, + break; + } + +- old = pci_read_byte(dev, 0xdc); +- msg_pdbg("SPI Read Configuration: "); +- new = (old >> 2) & 0x3; +- switch (new) { +- case 0: +- case 1: +- case 2: +- msg_pdbg("prefetching %sabled, caching %sabled, ", +- (new & 0x2) ? "en" : "dis", +- (new & 0x1) ? "dis" : "en"); +- break; +- default: +- msg_pdbg("invalid prefetching/caching settings, "); +- break; +- } + return 0; + } + +@@ -1844,7 +2301,9 @@ int via_init_spi(struct pci_dev *dev, uint32_t mmio_base) + { + int i; + +- ich_spibar = physmap("VIA SPI MMIO registers", mmio_base, 0x70); ++ ich_spibar = rphysmap("VIA SPI MMIO registers", mmio_base, 0x70); ++ if (ich_spibar == ERROR_PTR) ++ return ERROR_FATAL; + /* Do we really need no write enable? Like the LPC one at D17F0 0x40 */ + + /* Not sure if it speaks all these bus protocols. */ +diff --git a/internal.c b/internal.c +index ab3c81f..30b184f 100644 +--- a/internal.c ++++ b/internal.c +@@ -331,9 +331,8 @@ int internal_init(void) + return ret; + + #if defined(__i386__) || defined(__x86_64__) +- /* Probe unconditionally for IT87* LPC->SPI translation and for +- * IT87* Parallel write enable. +- */ ++ /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and ++ * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */ + init_superio_ite(); + #endif + +diff --git a/it85spi.c b/it85spi.c +index 0b074eb..7efc680 100644 +--- a/it85spi.c ++++ b/it85spi.c +@@ -262,6 +262,9 @@ static int it85xx_spi_common_init(struct superio s) + * Major TODO here, and it will be a lot of work. + */ + base = (chipaddr)physmap("it85 communication", 0xFFFFF000, 0x1000); ++ if (base == (chipaddr)ERROR_PTR) ++ return 1; ++ + msg_pdbg("%s():%d base=0x%08x\n", __func__, __LINE__, + (unsigned int)base); + ce_high = (unsigned char *)(base + 0xE00); /* 0xFFFFFE00 */ +diff --git a/it87spi.c b/it87spi.c +index 8e4e0ad..be7f234 100644 +--- a/it87spi.c ++++ b/it87spi.c +@@ -27,6 +27,7 @@ + + #include + #include ++#include + #include "flash.h" + #include "chipdrivers.h" + #include "programmer.h" +@@ -36,7 +37,7 @@ + #define ITE_SUPERIO_PORT1 0x2e + #define ITE_SUPERIO_PORT2 0x4e + +-uint16_t it8716f_flashport = 0; ++static uint16_t it8716f_flashport = 0; + /* use fast 33MHz SPI (<>0) or slow 16MHz (0) */ + static int fast_spi = 1; + +@@ -124,10 +125,40 @@ static const struct spi_programmer spi_programmer_it87xx = { + static uint16_t it87spi_probe(uint16_t port) + { + uint8_t tmp = 0; +- char *portpos = NULL; + uint16_t flashport = 0; + + enter_conf_mode_ite(port); ++ ++ char *param = extract_programmer_param("dualbiosindex"); ++ if (param != NULL) { ++ sio_write(port, 0x07, 0x07); /* Select GPIO LDN */ ++ tmp = sio_read(port, 0xEF); ++ if (*param == '\0') { /* Print current setting only. */ ++ free(param); ++ } else { ++ char *dualbiosindex_suffix; ++ errno = 0; ++ long chip_index = strtol(param, &dualbiosindex_suffix, 0); ++ free(param); ++ if (errno != 0 || *dualbiosindex_suffix != '\0' || chip_index < 0 || chip_index > 1) { ++ msg_perr("DualBIOS: Invalid chip index requested - choose 0 or 1.\n"); ++ exit_conf_mode_ite(port); ++ return 1; ++ } ++ if (chip_index != (tmp & 1)) { ++ msg_pdbg("DualBIOS: Previous chip index: %d\n", tmp & 1); ++ sio_write(port, 0xEF, (tmp & 0xFE) | chip_index); ++ tmp = sio_read(port, 0xEF); ++ if ((tmp & 1) != chip_index) { ++ msg_perr("DualBIOS: Chip selection failed.\n"); ++ exit_conf_mode_ite(port); ++ return 1; ++ } ++ } ++ } ++ msg_pinfo("DualBIOS: Selected chip: %d\n", tmp & 1); ++ } ++ + /* NOLDN, reg 0x24, mask out lowest bit (suspend) */ + tmp = sio_read(port, 0x24) & 0xFE; + /* Check if LPC->SPI translation is active. */ +@@ -163,11 +194,11 @@ static uint16_t it87spi_probe(uint16_t port) + flashport |= sio_read(port, 0x65); + msg_pdbg("Serial flash port 0x%04x\n", flashport); + /* Non-default port requested? */ +- portpos = extract_programmer_param("it87spiport"); +- if (portpos) { ++ param = extract_programmer_param("it87spiport"); ++ if (param) { + char *endptr = NULL; + unsigned long forced_flashport; +- forced_flashport = strtoul(portpos, &endptr, 0); ++ forced_flashport = strtoul(param, &endptr, 0); + /* Port 0, port >0x1000, unaligned ports and garbage strings + * are rejected. + */ +@@ -180,7 +211,8 @@ static uint16_t it87spi_probe(uint16_t port) + msg_perr("Error: it87spiport specified, but no valid " + "port specified.\nPort must be a multiple of " + "0x8 and lie between 0x100 and 0xff8.\n"); +- free(portpos); ++ exit_conf_mode_ite(port); ++ free(param); + return 1; + } else { + flashport = (uint16_t)forced_flashport; +@@ -190,7 +222,7 @@ static uint16_t it87spi_probe(uint16_t port) + sio_write(port, 0x65, (flashport & 0xff)); + } + } +- free(portpos); ++ free(param); + exit_conf_mode_ite(port); + it8716f_flashport = flashport; + if (internal_buses_supported & BUS_SPI) +@@ -228,6 +260,7 @@ int init_superio_ite(void) + case 0x8716: + case 0x8718: + case 0x8720: ++ case 0x8728: + ret |= it87spi_probe(superios[i].port); + break; + default: +diff --git a/layout.c b/layout.c +index 1bd3152..d00c16c 100644 +--- a/layout.c ++++ b/layout.c +@@ -3,6 +3,7 @@ + * + * Copyright (C) 2005-2008 coresystems GmbH + * (Written by Stefan Reinauer for coresystems GmbH) ++ * Copyright (C) 2011-2013 Stefan Tauner + * + * 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 +@@ -25,24 +26,23 @@ + #include "flash.h" + #include "programmer.h" + +-static int romimages = 0; +- + #define MAX_ROMLAYOUT 32 + + typedef struct { +- unsigned int start; +- unsigned int end; ++ chipoff_t start; ++ chipoff_t end; + unsigned int included; + char name[256]; +-} romlayout_t; ++} romentry_t; + +-/* include_args lists arguments specified at the command line with -i. They +- * must be processed at some point so that desired regions are marked as +- * "included" in the rom_entries list. +- */ ++/* rom_entries store the entries specified in a layout file and associated run-time data */ ++static romentry_t rom_entries[MAX_ROMLAYOUT]; ++static int num_rom_entries = 0; /* the number of successfully parsed rom_entries */ ++ ++/* include_args holds the arguments specified at the command line with -i. They must be processed at some point ++ * so that desired regions are marked as "included" in the rom_entries list. */ + static char *include_args[MAX_ROMLAYOUT]; +-static int num_include_args = 0; /* the number of valid entries. */ +-static romlayout_t rom_entries[MAX_ROMLAYOUT]; ++static int num_include_args = 0; /* the number of valid include_args. */ + + #ifndef __LIBPAYLOAD__ + int read_romlayout(char *name) +@@ -62,12 +62,13 @@ int read_romlayout(char *name) + while (!feof(romlayout)) { + char *tstr1, *tstr2; + +- if (romimages >= MAX_ROMLAYOUT) { ++ if (num_rom_entries >= MAX_ROMLAYOUT) { + msg_gerr("Maximum number of ROM images (%i) in layout " + "file reached.\n", MAX_ROMLAYOUT); ++ fclose(romlayout); + return 1; + } +- if (2 != fscanf(romlayout, "%s %s\n", tempstr, rom_entries[romimages].name)) ++ if (2 != fscanf(romlayout, "%s %s\n", tempstr, rom_entries[num_rom_entries].name)) + continue; + #if 0 + // fscanf does not like arbitrary comments like that :( later +@@ -82,13 +83,13 @@ int read_romlayout(char *name) + fclose(romlayout); + return 1; + } +- rom_entries[romimages].start = strtol(tstr1, (char **)NULL, 16); +- rom_entries[romimages].end = strtol(tstr2, (char **)NULL, 16); +- rom_entries[romimages].included = 0; +- romimages++; ++ rom_entries[num_rom_entries].start = strtol(tstr1, (char **)NULL, 16); ++ rom_entries[num_rom_entries].end = strtol(tstr2, (char **)NULL, 16); ++ rom_entries[num_rom_entries].included = 0; ++ num_rom_entries++; + } + +- for (i = 0; i < romimages; i++) { ++ for (i = 0; i < num_rom_entries; i++) { + msg_gdbg("romlayout %08x - %08x named %s\n", + rom_entries[i].start, + rom_entries[i].end, rom_entries[i].name); +@@ -100,6 +101,33 @@ int read_romlayout(char *name) + } + #endif + ++ ++#ifdef FORCE10_SPI_CHANGE ++int add_romentry(chipoff_t start, chipoff_t end, const char *name) ++{ ++ int len = 0; ++ ++ if (num_rom_entries >= MAX_ROMLAYOUT) { ++ msg_gerr("Maximum number of ROM images (%i) in layout " ++ "file reached.\n", MAX_ROMLAYOUT); ++ return 1; ++ } ++ rom_entries[num_rom_entries].start = start; ++ rom_entries[num_rom_entries].end = end; ++ rom_entries[num_rom_entries].included = 1; ++ len = strlen(name); ++ if (len > 256) { ++ msg_gdbg("terminating rom entry name to 256 as it exceeds max length\n"); ++ len = 255; ++ } ++ strncpy(rom_entries[num_rom_entries].name, name, len); ++ msg_gdbg("Adding rom entry: %08x - %08x named %s\n", rom_entries[num_rom_entries].start, ++ rom_entries[num_rom_entries].end, rom_entries[num_rom_entries].name); ++ num_rom_entries++; ++ return 0; ++} ++#endif ++ + /* returns the index of the entry (or a negative value if it is not found) */ + int find_include_arg(const char *const name) + { +@@ -139,11 +167,11 @@ static int find_romentry(char *name) + { + int i; + +- if (!romimages) ++ if (num_rom_entries == 0) + return -1; + + msg_gspew("Looking for region \"%s\"... ", name); +- for (i = 0; i < romimages; i++) { ++ for (i = 0; i < num_rom_entries; i++) { + if (!strcmp(rom_entries[i].name, name)) { + rom_entries[i].included = 1; + msg_gspew("found.\n"); +@@ -166,7 +194,7 @@ int process_include_args(void) + return 0; + + /* User has specified an area, but no layout file is loaded. */ +- if (!romimages) { ++ if (num_rom_entries == 0) { + msg_gerr("Region requested (with -i \"%s\"), " + "but no layout data is available.\n", + include_args[0]); +@@ -190,15 +218,30 @@ int process_include_args(void) + return 0; + } + +-romlayout_t *get_next_included_romentry(unsigned int start) ++void layout_cleanup(void) ++{ ++ int i; ++ for (i = 0; i < num_include_args; i++) { ++ free(include_args[i]); ++ include_args[i] = NULL; ++ } ++ num_include_args = 0; ++ ++ for (i = 0; i < num_rom_entries; i++) { ++ rom_entries[i].included = 0; ++ } ++ num_rom_entries = 0; ++} ++ ++romentry_t *get_next_included_romentry(unsigned int start) + { + int i; + unsigned int best_start = UINT_MAX; +- romlayout_t *best_entry = NULL; +- romlayout_t *cur; ++ romentry_t *best_entry = NULL; ++ romentry_t *cur; + + /* First come, first serve for overlapping regions. */ +- for (i = 0; i < romimages; i++) { ++ for (i = 0; i < num_rom_entries; i++) { + cur = &rom_entries[i]; + if (!cur->included) + continue; +@@ -217,18 +260,43 @@ romlayout_t *get_next_included_romentry(unsigned int start) + return best_entry; + } + +-int handle_romentries(const struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents) ++/* Validate and - if needed - normalize layout entries. */ ++int normalize_romentries(const struct flashctx *flash) ++{ ++ chipsize_t total_size = flash->chip->total_size * 1024; ++ int ret = 0; ++ ++ int i; ++ for (i = 0; i < num_rom_entries; i++) { ++ if (rom_entries[i].start >= total_size || rom_entries[i].end >= total_size) { ++ msg_gwarn("Warning: Address range of region \"%s\" exceeds the current chip's " ++ "address space.\n", rom_entries[i].name); ++ if (rom_entries[i].included) ++ ret = 1; ++ } ++ if (rom_entries[i].start > rom_entries[i].end) { ++ msg_gerr("Error: Size of the address range of region \"%s\" is not positive.\n", ++ rom_entries[i].name); ++ ret = 1; ++ } ++ } ++ ++ return ret; ++} ++ ++int build_new_image(const struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents) + { + unsigned int start = 0; +- romlayout_t *entry; ++ romentry_t *entry; + unsigned int size = flash->chip->total_size * 1024; + + /* If no regions were specified for inclusion, assume + * that the user wants to write the complete new image. + */ ++#ifndef FORCE10_SPI_CHANGE + if (num_include_args == 0) + return 0; +- ++#endif + /* Non-included romentries are ignored. + * The union of all included romentries is used from the new image. + */ +@@ -239,7 +307,7 @@ int handle_romentries(const struct flashctx *flash, uint8_t *oldcontents, uint8_ + memcpy(newcontents + start, oldcontents + start, + size - start); + break; +- } ++ } + /* For non-included region, copy from old content. */ + if (entry->start > start) + memcpy(newcontents + start, oldcontents + start, +diff --git a/linux_spi.c b/linux_spi.c +index d12fceb..f0c6404 100644 +--- a/linux_spi.c ++++ b/linux_spi.c +@@ -60,7 +60,7 @@ static const struct spi_programmer spi_programmer_linux = { + int linux_spi_init(void) + { + char *p, *endp, *dev; +- uint32_t speed = 0; ++ uint32_t speed_hz = 0; + /* FIXME: make the following configurable by CLI options. */ + /* SPI mode 0 (beware this also includes: MSB first, CS active low and others */ + const uint8_t mode = SPI_MODE_0; +@@ -68,7 +68,7 @@ int linux_spi_init(void) + + p = extract_programmer_param("spispeed"); + if (p && strlen(p)) { +- speed = (uint32_t)strtoul(p, &endp, 10) * 1024; ++ speed_hz = (uint32_t)strtoul(p, &endp, 10) * 1000; + if (p == endp) { + msg_perr("%s: invalid clock: %s kHz\n", __func__, p); + free(p); +@@ -98,14 +98,14 @@ int linux_spi_init(void) + return 1; + /* We rely on the shutdown function for cleanup from here on. */ + +- if (speed > 0) { +- if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) == -1) { ++ if (speed_hz > 0) { ++ if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed_hz) == -1) { + msg_perr("%s: failed to set speed to %d Hz: %s\n", +- __func__, speed, strerror(errno)); ++ __func__, speed_hz, strerror(errno)); + return 1; + } + +- msg_pdbg("Using %d kHz clock\n", speed); ++ msg_pdbg("Using %d kHz clock\n", speed_hz/1000); + } + + if (ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1) { +diff --git a/mcp6x_spi.c b/mcp6x_spi.c +index ac40557..20e9bd8 100644 +--- a/mcp6x_spi.c ++++ b/mcp6x_spi.c +@@ -135,25 +135,20 @@ int mcp6x_spi_init(int want_spi) + + /* Accessing a NULL pointer BAR is evil. Don't do it. */ + if (!mcp6x_spibaraddr && want_spi) { +- msg_perr("Error: Chipset is strapped for SPI, but MCP SPI BAR " +- "is invalid.\n"); ++ msg_perr("Error: Chipset is strapped for SPI, but MCP SPI BAR is invalid.\n"); + return 1; + } else if (!mcp6x_spibaraddr && !want_spi) { + msg_pdbg("MCP SPI is not used.\n"); + return 0; + } else if (mcp6x_spibaraddr && !want_spi) { +- msg_pdbg("Strange. MCP SPI BAR is valid, but chipset apparently" +- " doesn't have SPI enabled.\n"); ++ msg_pdbg("Strange. MCP SPI BAR is valid, but chipset apparently doesn't have SPI enabled.\n"); + /* FIXME: Should we enable SPI anyway? */ + return 0; + } + /* Map the BAR. Bytewise/wordwise access at 0x530 and 0x540. */ +- mcp6x_spibar = physmap("NVIDIA MCP6x SPI", mcp6x_spibaraddr, 0x544); +- +-#if 0 +- /* FIXME: Run the physunmap in a shutdown function. */ +- physunmap(mcp6x_spibar, 0x544); +-#endif ++ mcp6x_spibar = rphysmap("NVIDIA MCP6x SPI", mcp6x_spibaraddr, 0x544); ++ if (mcp6x_spibar == ERROR_PTR) ++ return 1; + + status = mmio_readw(mcp6x_spibar + 0x530); + msg_pdbg("SPI control is 0x%04x, req=%i, gnt=%i\n", +diff --git a/nic3com.c b/nic3com.c +index 8d67b54..27e28c7 100644 +--- a/nic3com.c ++++ b/nic3com.c +@@ -96,6 +96,8 @@ int nic3com_init(void) + return 1; + + io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); ++ if (!io_base_addr) ++ return 1; + + id = dev->device_id; + +diff --git a/nicintel.c b/nicintel.c +index 56678e7..98ba29f 100644 +--- a/nicintel.c ++++ b/nicintel.c +@@ -59,13 +59,6 @@ static const struct par_programmer par_programmer_nicintel = { + .chip_writen = fallback_chip_writen, + }; + +-static int nicintel_shutdown(void *data) +-{ +- physunmap(nicintel_control_bar, NICINTEL_CONTROL_MEMMAP_SIZE); +- physunmap(nicintel_bar, NICINTEL_MEMMAP_SIZE); +- return 0; +-} +- + int nicintel_init(void) + { + struct pci_dev *dev = NULL; +@@ -83,18 +76,19 @@ int nicintel_init(void) + return 1; + + addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_2); +- nicintel_bar = physmap("Intel NIC flash", addr, NICINTEL_MEMMAP_SIZE); ++ if (!addr) ++ return 1; ++ ++ nicintel_bar = rphysmap("Intel NIC flash", addr, NICINTEL_MEMMAP_SIZE); + if (nicintel_bar == ERROR_PTR) +- goto error_out_unmap; ++ return 1; + + addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); +- /* FIXME: This is not an aligned mapping. Use 4k? */ +- nicintel_control_bar = physmap("Intel NIC control/status reg", +- addr, NICINTEL_CONTROL_MEMMAP_SIZE); +- if (nicintel_control_bar == ERROR_PTR) +- goto error_out; ++ if (!addr) ++ return 1; + +- if (register_shutdown(nicintel_shutdown, NULL)) ++ nicintel_control_bar = rphysmap("Intel NIC control/status reg", addr, NICINTEL_CONTROL_MEMMAP_SIZE); ++ if (nicintel_control_bar == ERROR_PTR) + return 1; + + /* FIXME: This register is pretty undocumented in all publicly available +@@ -112,11 +106,6 @@ int nicintel_init(void) + register_par_programmer(&par_programmer_nicintel, BUS_PARALLEL); + + return 0; +- +-error_out_unmap: +- physunmap(nicintel_bar, NICINTEL_MEMMAP_SIZE); +-error_out: +- return 1; + } + + static void nicintel_chip_writeb(const struct flashctx *flash, uint8_t val, +diff --git a/nicintel_spi.c b/nicintel_spi.c +index 0045c09..1522c9b 100644 +--- a/nicintel_spi.c ++++ b/nicintel_spi.c +@@ -19,10 +19,16 @@ + */ + + /* +- * Datasheet: ++ * Datasheets: + * PCI/PCI-X Family of Gigabit Ethernet Controllers Software Developer's Manual + * 82540EP/EM, 82541xx, 82544GC/EI, 82545GM/EM, 82546GB/EB, and 82547xx +- * http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf ++ * http://www.intel.com/content/www/us/en/ethernet-controllers/pci-pci-x-family-gbe-controllers-software-dev-manual.html ++ * ++ * PCIe GbE Controllers Open Source Software Developer's Manual ++ * http://www.intel.com/content/www/us/en/ethernet-controllers/pcie-gbe-controllers-open-source-manual.html ++ * ++ * Intel 82574 Gigabit Ethernet Controller Family Datasheet ++ * http://www.intel.com/content/www/us/en/ethernet-controllers/82574l-gbe-controller-datasheet.html + */ + + #include +@@ -72,6 +78,7 @@ const struct dev_entry nics_intel_spi[] = { + {PCI_VENDOR_ID_INTEL, 0x1076, OK, "Intel", "82541GI Gigabit Ethernet Controller"}, + {PCI_VENDOR_ID_INTEL, 0x107c, OK, "Intel", "82541PI Gigabit Ethernet Controller"}, + {PCI_VENDOR_ID_INTEL, 0x10b9, OK, "Intel", "82572EI Gigabit Ethernet Controller"}, ++ {PCI_VENDOR_ID_INTEL, 0x10d3, OK, "Intel", "82574L Gigabit Ethernet Controller"}, + + {0}, + }; +@@ -151,16 +158,12 @@ static int nicintel_spi_shutdown(void *data) + { + uint32_t tmp; + +- /* Disable writes manually. See the comment about EECD in +- * nicintel_spi_init() for details. +- */ ++ /* Disable writes manually. See the comment about EECD in nicintel_spi_init() for details. */ + tmp = pci_mmio_readl(nicintel_spibar + EECD); + tmp &= ~FLASH_WRITES_ENABLED; + tmp |= FLASH_WRITES_DISABLED; + pci_mmio_writel(tmp, nicintel_spibar + EECD); + +- physunmap(nicintel_spibar, MEMMAP_SIZE); +- + return 0; + } + +@@ -177,8 +180,13 @@ int nicintel_spi_init(void) + return 1; + + io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); +- nicintel_spibar = physmap("Intel Gigabit NIC w/ SPI flash", +- io_base_addr, MEMMAP_SIZE); ++ if (!io_base_addr) ++ return 1; ++ ++ nicintel_spibar = rphysmap("Intel Gigabit NIC w/ SPI flash", io_base_addr, MEMMAP_SIZE); ++ if (nicintel_spibar == ERROR_PTR) ++ return 1; ++ + /* Automatic restore of EECD on shutdown is not possible because EECD + * does not only contain FLASH_WRITES_DISABLED|FLASH_WRITES_ENABLED, + * but other bits with side effects as well. Those other bits must be +diff --git a/nicnatsemi.c b/nicnatsemi.c +index d62a73f..cb8da6d 100644 +--- a/nicnatsemi.c ++++ b/nicnatsemi.c +@@ -64,6 +64,8 @@ int nicnatsemi_init(void) + return 1; + + io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); ++ if (!io_base_addr) ++ return 1; + + /* The datasheet shows address lines MA0-MA16 in one place and MA0-MA15 + * in another. My NIC has MA16 connected to A16 on the boot ROM socket +diff --git a/nicrealtek.c b/nicrealtek.c +index fb8e9e1..02fbd39 100644 +--- a/nicrealtek.c ++++ b/nicrealtek.c +@@ -69,6 +69,8 @@ int nicrealtek_init(void) + return 1; + + io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); ++ if (!io_base_addr) ++ return 1; + + /* Beware, this ignores the vendor ID! */ + switch (dev->device_id) { +diff --git a/ogp_spi.c b/ogp_spi.c +index 0c09d6a..23431d1 100644 +--- a/ogp_spi.c ++++ b/ogp_spi.c +@@ -97,12 +97,6 @@ static const struct bitbang_spi_master bitbang_spi_master_ogp = { + .half_period = 0, + }; + +-static int ogp_spi_shutdown(void *data) +-{ +- physunmap(ogp_spibar, 4096); +- return 0; +-} +- + int ogp_spi_init(void) + { + struct pci_dev *dev = NULL; +@@ -126,8 +120,10 @@ int ogp_spi_init(void) + ogp_reg_sck = OGA1_XP10_CPROM_SCK; + } else { + msg_perr("Invalid or missing rom= parameter.\n"); ++ free(type); + return 1; + } ++ free(type); + + if (rget_io_perms()) + return 1; +@@ -137,9 +133,11 @@ int ogp_spi_init(void) + return 1; + + io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); +- ogp_spibar = physmap("OGP registers", io_base_addr, 4096); ++ if (!io_base_addr) ++ return 1; + +- if (register_shutdown(ogp_spi_shutdown, NULL)) ++ ogp_spibar = rphysmap("OGP registers", io_base_addr, 4096); ++ if (ogp_spibar == ERROR_PTR) + return 1; + + if (bitbang_spi_init(&bitbang_spi_master_ogp)) +diff --git a/pcidev.c b/pcidev.c +index c7e9d78..3a3f77c 100644 +--- a/pcidev.c ++++ b/pcidev.c +@@ -94,7 +94,7 @@ uintptr_t pcidev_readbar(struct pci_dev *dev, int bar) + + supported_cycles = pci_read_word(dev, PCI_COMMAND); + +- msg_pdbg("Requested BAR is "); ++ msg_pdbg("Requested BAR is of type "); + switch (bartype) { + case TYPE_MEMBAR: + msg_pdbg("MEM"); +diff --git a/physmap.c b/physmap.c +index 932fe75..150c44a 100644 +--- a/physmap.c ++++ b/physmap.c +@@ -21,11 +21,13 @@ + */ + + #include ++#include + #include + #include + #include + #include + #include "flash.h" ++#include "programmer.h" + #include "hwaccess.h" + + #if !defined(__DJGPP__) && !defined(__LIBPAYLOAD__) +@@ -88,7 +90,7 @@ static void *sys_physmap(uintptr_t phys_addr, size_t len) + #define sys_physmap_rw_uncached sys_physmap + #define sys_physmap_ro_cached sys_physmap + +-void physunmap(void *virt_addr, size_t len) ++void sys_physunmap_unaligned(void *virt_addr, size_t len) + { + __dpmi_meminfo mi; + +@@ -117,7 +119,7 @@ void *sys_physmap(uintptr_t phys_addr, size_t len) + #define sys_physmap_rw_uncached sys_physmap + #define sys_physmap_ro_cached sys_physmap + +-void physunmap(void *virt_addr, size_t len) ++void sys_physunmap_unaligned(void *virt_addr, size_t len) + { + } + #elif defined(__MACH__) && defined(__APPLE__) +@@ -138,7 +140,7 @@ static void *sys_physmap(uintptr_t phys_addr, size_t len) + #define sys_physmap_rw_uncached sys_physmap + #define sys_physmap_ro_cached sys_physmap + +-void physunmap(void *virt_addr, size_t len) ++void sys_physunmap_unaligned(void *virt_addr, size_t len) + { + unmap_physical(virt_addr, len); + } +@@ -164,12 +166,11 @@ static void *sys_physmap_rw_uncached(uintptr_t phys_addr, size_t len) + /* Open the memory device UNCACHED. Important for MMIO. */ + if (-1 == (fd_mem = open(MEM_DEV, O_RDWR | O_SYNC))) { + msg_perr("Critical error: open(" MEM_DEV "): %s\n", strerror(errno)); +- exit(2); ++ return ERROR_PTR; + } + } + +- virt_addr = mmap(NULL, len, PROT_WRITE | PROT_READ, MAP_SHARED, +- fd_mem, (off_t)phys_addr); ++ virt_addr = mmap(NULL, len, PROT_WRITE | PROT_READ, MAP_SHARED, fd_mem, (off_t)phys_addr); + return MAP_FAILED == virt_addr ? ERROR_PTR : virt_addr; + } + +@@ -184,50 +185,77 @@ static void *sys_physmap_ro_cached(uintptr_t phys_addr, size_t len) + /* Open the memory device CACHED. */ + if (-1 == (fd_mem_cached = open(MEM_DEV, O_RDWR))) { + msg_perr("Critical error: open(" MEM_DEV "): %s\n", strerror(errno)); +- exit(2); ++ return ERROR_PTR; + } + } + +- virt_addr = mmap(NULL, len, PROT_READ, MAP_SHARED, +- fd_mem_cached, (off_t)phys_addr); ++ virt_addr = mmap(NULL, len, PROT_READ, MAP_SHARED, fd_mem_cached, (off_t)phys_addr); + return MAP_FAILED == virt_addr ? ERROR_PTR : virt_addr; + } + +-void physunmap(void *virt_addr, size_t len) ++void sys_physunmap_unaligned(void *virt_addr, size_t len) + { +- if (len == 0) { +- msg_pspew("Not unmapping zero size at %p\n", virt_addr); +- return; +- } +- + munmap(virt_addr, len); + } + #endif + +-#define PHYSMAP_NOFAIL 0 +-#define PHYSMAP_MAYFAIL 1 +-#define PHYSMAP_RW 0 +-#define PHYSMAP_RO 1 ++#define PHYSM_RW 0 ++#define PHYSM_RO 1 ++#define PHYSM_NOCLEANUP 0 ++#define PHYSM_CLEANUP 1 ++#define PHYSM_EXACT 0 ++#define PHYSM_ROUND 1 ++ ++/* Round start to nearest page boundary below and set len so that the resulting address range ends at the lowest ++ * possible page boundary where the original address range is still entirely contained. It returns the ++ * difference between the rounded start address and the original start address. */ ++static uintptr_t round_to_page_boundaries(uintptr_t *start, size_t *len) ++{ ++ uintptr_t page_size = getpagesize(); ++ uintptr_t page_mask = ~(page_size-1); ++ uintptr_t end = *start + *len; ++ uintptr_t old_start = *start; ++ msg_gspew("page_size=%" PRIxPTR "\n", page_size); ++ msg_gspew("pre-rounding: start=0x%0*" PRIxPTR ", len=0x%zx, end=0x%0*" PRIxPTR "\n", ++ PRIxPTR_WIDTH, *start, *len, PRIxPTR_WIDTH, end); ++ *start = *start & page_mask; ++ end = (end + page_size - 1) & page_mask; ++ *len = end - *start; ++ msg_gspew("post-rounding: start=0x%0*" PRIxPTR ", len=0x%zx, end=0x%0*" PRIxPTR "\n", ++ PRIxPTR_WIDTH, *start, *len, PRIxPTR_WIDTH, *start + *len); ++ return old_start - *start; ++} ++ ++struct undo_physmap_data { ++ void *virt_addr; ++ size_t len; ++}; ++ ++static int undo_physmap(void *data) ++{ ++ if (data == NULL) { ++ msg_perr("%s: tried to physunmap without valid data!\n", __func__); ++ return 1; ++ } ++ struct undo_physmap_data *d = data; ++ physunmap_unaligned(d->virt_addr, d->len); ++ free(data); ++ return 0; ++} + +-static void *physmap_common(const char *descr, uintptr_t phys_addr, +- size_t len, int mayfail, int readonly) ++static void *physmap_common(const char *descr, uintptr_t phys_addr, size_t len, bool readonly, bool autocleanup, ++ bool round) + { + void *virt_addr; ++ uintptr_t offset = 0; + + if (len == 0) { + msg_pspew("Not mapping %s, zero size at 0x%0*" PRIxPTR ".\n", descr, PRIxPTR_WIDTH, phys_addr); + return ERROR_PTR; + } + +- if ((getpagesize() - 1) & len) { +- msg_perr("Mapping %s at 0x%0*" PRIxPTR ", unaligned size 0x%zx.\n", +- descr, PRIxPTR_WIDTH, phys_addr, len); +- } +- +- if ((getpagesize() - 1) & phys_addr) { +- msg_perr("Mapping %s, 0x%zx bytes at unaligned 0x%0*" PRIxPTR ".\n", +- descr, len, PRIxPTR_WIDTH, phys_addr); +- } ++ if (round) ++ offset = round_to_page_boundaries(&phys_addr, &len); + + if (readonly) + virt_addr = sys_physmap_ro_cached(phys_addr, len); +@@ -253,23 +281,89 @@ static void *physmap_common(const char *descr, uintptr_t phys_addr, + "and reboot, or reboot into\n" + "single user mode.\n"); + #endif +- if (!mayfail) +- exit(3); ++ return ERROR_PTR; + } + +- return virt_addr; ++ if (autocleanup) { ++ struct undo_physmap_data *d = malloc(sizeof(struct undo_physmap_data)); ++ if (d == NULL) { ++ msg_perr("%s: Out of memory!\n", __func__); ++ physunmap_unaligned(virt_addr, len); ++ return ERROR_PTR; ++ } ++ ++ d->virt_addr = virt_addr; ++ d->len = len; ++ if (register_shutdown(undo_physmap, d) != 0) { ++ msg_perr("%s: Could not register shutdown function!\n", __func__); ++ physunmap_unaligned(virt_addr, len); ++ return ERROR_PTR; ++ } ++ } ++ ++ return virt_addr + offset; ++} ++ ++void physunmap_unaligned(void *virt_addr, size_t len) ++{ ++ /* No need to check for zero size, such mappings would have yielded ERROR_PTR. */ ++ if (virt_addr == ERROR_PTR) { ++#ifndef FORCE10_SPI_CHANGE ++ msg_perr("Trying to unmap a nonexisting mapping!\n" ++ "Please report a bug at flashrom@flashrom.org\n"); ++#else ++ msg_pdbg("Trying to unmap a nonexisting mapping!\n" ++ "Please report a bug at flashrom@flashrom.org\n"); ++#endif ++ return; ++ } ++ ++ sys_physunmap_unaligned(virt_addr, len); ++} ++ ++void physunmap(void *virt_addr, size_t len) ++{ ++ uintptr_t tmp; ++ ++ /* No need to check for zero size, such mappings would have yielded ERROR_PTR. */ ++ if (virt_addr == ERROR_PTR) { ++#ifndef FORCE10_SPI_CHANGE ++ msg_perr("Trying to unmap a nonexisting mapping!\n" ++ "Please report a bug at flashrom@flashrom.org\n"); ++#else ++ msg_pdbg("Trying to unmap a nonexisting mapping!\n" ++ "Please report a bug at flashrom@flashrom.org\n"); ++#endif ++ return; ++ } ++ tmp = (uintptr_t)virt_addr; ++ /* We assume that the virtual address of a page-aligned physical address is page-aligned as well. By ++ * extension, rounding a virtual unaligned address as returned by physmap should yield the same offset ++ * between rounded and original virtual address as between rounded and original physical address. ++ */ ++ round_to_page_boundaries(&tmp, &len); ++ virt_addr = (void *)tmp; ++ physunmap_unaligned(virt_addr, len); + } + + void *physmap(const char *descr, uintptr_t phys_addr, size_t len) + { +- return physmap_common(descr, phys_addr, len, PHYSMAP_NOFAIL, +- PHYSMAP_RW); ++ return physmap_common(descr, phys_addr, len, PHYSM_RW, PHYSM_NOCLEANUP, PHYSM_ROUND); ++} ++ ++void *rphysmap(const char *descr, uintptr_t phys_addr, size_t len) ++{ ++ return physmap_common(descr, phys_addr, len, PHYSM_RW, PHYSM_CLEANUP, PHYSM_ROUND); ++} ++ ++void *physmap_ro(const char *descr, uintptr_t phys_addr, size_t len) ++{ ++ return physmap_common(descr, phys_addr, len, PHYSM_RO, PHYSM_NOCLEANUP, PHYSM_ROUND); + } + +-void *physmap_try_ro(const char *descr, uintptr_t phys_addr, size_t len) ++void *physmap_ro_unaligned(const char *descr, uintptr_t phys_addr, size_t len) + { +- return physmap_common(descr, phys_addr, len, PHYSMAP_MAYFAIL, +- PHYSMAP_RO); ++ return physmap_common(descr, phys_addr, len, PHYSM_RO, PHYSM_NOCLEANUP, PHYSM_EXACT); + } + + /* MSR abstraction implementations for Linux, OpenBSD, FreeBSD/Dragonfly, OSX, libpayload +diff --git a/pony_spi.c b/pony_spi.c +index 101751f..2a3666f 100644 +--- a/pony_spi.c ++++ b/pony_spi.c +@@ -140,6 +140,7 @@ int pony_spi_init(void) + } else if (arg && !strlen(arg)) { + msg_perr("Error: Missing argument for programmer type.\n"); + free(arg); ++ return 1; + } else if (arg){ + msg_perr("Error: Invalid programmer type specified.\n"); + free(arg); +diff --git a/print.c b/print.c +index 6766eeb..6d2921b 100644 +--- a/print.c ++++ b/print.c +@@ -436,12 +436,13 @@ static void print_supported_boards_helper(const struct board_info *boards, + msg_ginfo("%s", b->name); + for (i = 0; i < maxboardlen - strlen(b->name); i++) + msg_ginfo(" "); +- if (b->working == OK) +- msg_ginfo("OK "); +- else if (b->working == NT) +- msg_ginfo("NT "); +- else +- msg_ginfo("BAD "); ++ ++ if (b->working == OK) ++ msg_ginfo("OK "); ++ else if (b->working == NT) ++ msg_ginfo("NT "); ++ else ++ msg_ginfo("BAD "); + + for (e = board_matches; e->vendor_name != NULL; e++) { + if (strcmp(e->vendor_name, b->vendor) +@@ -530,6 +531,7 @@ const struct board_info boards_known[] = { + B("abit", "AN-M2", OK, NULL, NULL), + B("abit", "AV8", OK, NULL, NULL), + B("abit", "AX8", OK, NULL, NULL), ++ B("abit", "BF6", OK, NULL, NULL), + B("abit", "BM6", OK, NULL, NULL), + B("abit", "Fatal1ty F-I90HD", OK, NULL, NULL), + B("abit", "IC7", OK, NULL, NULL), +@@ -695,6 +697,7 @@ const struct board_info boards_known[] = { + B("ASUS", "P5L-VM 1394", OK, "http://www.asus.com/Motherboards/Intel_Socket_775/P5LVM_1394/", NULL), + B("ASUS", "P5LD2", NT, NULL, "Untested board enable."), + B("ASUS", "P5LD2-VM", NT, "http://www.asus.com/Motherboards/Intel_Socket_775/P5LD2VM/", "Untested board enable."), ++ B("ASUS", "P5LD2-VM DH", OK, "http://www.asus.com/Motherboards/Intel_Socket_775/P5LD2VM_DH/", NULL), + B("ASUS", "P5LP-LE (Lithium-UL8E)", OK, "http://h10025.www1.hp.com/ewfrf/wc/document?docname=c00379616&tmp_task=prodinfoCategory&cc=us&dlc=en&lc=en&product=1159887", "This is an OEM board from HP."), + B("ASUS", "P5LP-LE (Epson OEM)", OK, NULL, "This is an OEM board from Epson (e.g. Endeavor MT7700)."), + B("ASUS", "P5LP-LE", NT, NULL, "This designation is used for OEM boards from HP, Epson and maybe others. The HP names vary and not all of them have been tested yet. Please report any success or failure, thanks."), +diff --git a/programmer.h b/programmer.h +index 4db8d58..d3cc557 100644 +--- a/programmer.h ++++ b/programmer.h +@@ -276,8 +276,11 @@ int processor_flash_enable(void); + + /* physmap.c */ + void *physmap(const char *descr, uintptr_t phys_addr, size_t len); +-void *physmap_try_ro(const char *descr, uintptr_t phys_addr, size_t len); ++void *rphysmap(const char *descr, uintptr_t phys_addr, size_t len); ++void *physmap_ro(const char *descr, uintptr_t phys_addr, size_t len); ++void *physmap_ro_unaligned(const char *descr, uintptr_t phys_addr, size_t len); + void physunmap(void *virt_addr, size_t len); ++void physunmap_unaligned(void *virt_addr, size_t len); + #if CONFIG_INTERNAL == 1 + int setup_cpu_msr(int cpu); + void cleanup_cpu_msr(void); +@@ -287,9 +290,11 @@ int cb_parse_table(const char **vendor, const char **model); + int cb_check_image(uint8_t *bios, int size); + + /* dmi.c */ ++#if defined(__i386__) || defined(__x86_64__) + extern int has_dmi_support; + void dmi_init(void); + int dmi_match(const char *pattern); ++#endif // defined(__i386__) || defined(__x86_64__) + + /* internal.c */ + struct superio { +@@ -550,10 +555,19 @@ int default_spi_write_256(struct flashctx *flash, uint8_t *buf, unsigned int sta + int default_spi_write_aai(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); + int register_spi_programmer(const struct spi_programmer *programmer); + +-/* The following enum is needed by ich_descriptor_tool and ich* code. */ ++/* The following enum is needed by ich_descriptor_tool and ich* code as well as in chipset_enable.c. */ + enum ich_chipset { + CHIPSET_ICH_UNKNOWN, +- CHIPSET_ICH7 = 7, ++#ifdef DELL_AVOTON_SUPPORT ++ CHIPSET_AVOTON, ++#endif ++ CHIPSET_ICH, ++ CHIPSET_ICH2345, ++ CHIPSET_ICH6, ++ CHIPSET_POULSBO, /* SCH U* */ ++ CHIPSET_TUNNEL_CREEK, /* Atom E6xx */ ++ CHIPSET_CENTERTON, /* Atom S1220 S1240 S1260 */ ++ CHIPSET_ICH7, + CHIPSET_ICH8, + CHIPSET_ICH9, + CHIPSET_ICH10, +@@ -563,13 +577,15 @@ enum ich_chipset { + CHIPSET_8_SERIES_LYNX_POINT, + CHIPSET_8_SERIES_LYNX_POINT_LP, + CHIPSET_8_SERIES_WELLSBURG, ++#if DELL_DENVERTON_SUPPORT == 1 ++ CHIPSET_DENVERTON, ++#endif /* #if DELL_DENVERTON_SUPPORT == 1 */ + }; + + /* ichspi.c */ + #if CONFIG_INTERNAL == 1 + extern uint32_t ichspi_bbar; +-int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb, +- enum ich_chipset ich_generation); ++int ich_init_spi(struct pci_dev *dev, void *spibar, enum ich_chipset ich_generation); + int via_init_spi(struct pci_dev *dev, uint32_t mmio_base); + + /* amd_imc.c */ +@@ -659,7 +675,7 @@ typedef int fdtype; + + void sp_flush_incoming(void); + fdtype sp_openserport(char *dev, unsigned int baud); +-void __attribute__((noreturn)) sp_die(char *msg); ++int serialport_config(fdtype fd, unsigned int baud); + extern fdtype sp_fd; + /* expose serialport_shutdown as it's currently used by buspirate */ + int serialport_shutdown(void *data); +diff --git a/rayer_spi.c b/rayer_spi.c +index b312610..189341a 100644 +--- a/rayer_spi.c ++++ b/rayer_spi.c +@@ -17,11 +17,9 @@ + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-/* Driver for the SPIPGM hardware by "RayeR" Martin Rehak. +- * See http://rayer.ic.cz/elektro/spipgm.htm for schematics and instructions. +- */ +- +-/* This driver uses non-portable direct I/O port accesses which won't work on ++/* Driver for various LPT adapters. ++ * ++ * This driver uses non-portable direct I/O port accesses which won't work on + * any non-x86 platform, and even on x86 there is a high chance there will be + * collisions with any loaded parallel port drivers. + * The big advantage of direct port I/O is OS independence and speed because +@@ -37,21 +35,87 @@ + #include "programmer.h" + #include "hwaccess.h" + +-enum rayer_type { +- TYPE_RAYER, +- TYPE_XILINX_DLC5, +-}; +- + /* We have two sets of pins, out and in. The numbers for both sets are + * independent and are bitshift values, not real pin numbers. + * Default settings are for the RayeR hardware. + */ +-/* Pins for master->slave direction */ +-static int rayer_cs_bit = 5; +-static int rayer_sck_bit = 6; +-static int rayer_mosi_bit = 7; +-/* Pins for slave->master direction */ +-static int rayer_miso_bit = 6; ++ ++struct rayer_programmer { ++ const char *type; ++ const enum test_state status; ++ const char *description; ++ const void *dev_data; ++}; ++ ++struct rayer_pinout { ++ uint8_t cs_bit; ++ uint8_t sck_bit; ++ uint8_t mosi_bit; ++ uint8_t miso_bit; ++ void (*preinit)(const void *); ++ int (*shutdown)(void *); ++}; ++ ++static const struct rayer_pinout rayer_spipgm = { ++ .cs_bit = 5, ++ .sck_bit = 6, ++ .mosi_bit = 7, ++ .miso_bit = 6, ++}; ++ ++static void dlc5_preinit(const void *); ++static int dlc5_shutdown(void *); ++ ++static const struct rayer_pinout xilinx_dlc5 = { ++ .cs_bit = 2, ++ .sck_bit = 1, ++ .mosi_bit = 0, ++ .miso_bit = 4, ++ .preinit = dlc5_preinit, ++ .shutdown = dlc5_shutdown, ++}; ++ ++static void byteblaster_preinit(const void *); ++static int byteblaster_shutdown(void *); ++ ++static const struct rayer_pinout altera_byteblastermv = { ++ .cs_bit = 1, ++ .sck_bit = 0, ++ .mosi_bit = 6, ++ .miso_bit = 7, ++ .preinit = byteblaster_preinit, ++ .shutdown = byteblaster_shutdown, ++}; ++ ++static void stk200_preinit(const void *); ++static int stk200_shutdown(void *); ++ ++static const struct rayer_pinout atmel_stk200 = { ++ .cs_bit = 7, ++ .sck_bit = 4, ++ .mosi_bit = 5, ++ .miso_bit = 6, ++ .preinit = stk200_preinit, ++ .shutdown = stk200_shutdown, ++}; ++ ++static const struct rayer_pinout wiggler_lpt = { ++ .cs_bit = 1, ++ .sck_bit = 2, ++ .mosi_bit = 3, ++ .miso_bit = 7, ++}; ++ ++static const struct rayer_programmer rayer_spi_types[] = { ++ {"rayer", NT, "RayeR SPIPGM", &rayer_spipgm}, ++ {"xilinx", NT, "Xilinx Parallel Cable III (DLC 5)", &xilinx_dlc5}, ++ {"byteblastermv", OK, "Altera ByteBlasterMV", &altera_byteblastermv}, ++ {"stk200", NT, "Atmel STK200/300 adapter", &atmel_stk200}, ++ {"wiggler", OK, "Wiggler LPT", &wiggler_lpt}, ++ {0}, ++}; ++ ++static const struct rayer_pinout *pinout = NULL; + + static uint16_t lpt_iobase; + +@@ -60,22 +124,22 @@ static uint8_t lpt_outbyte; + + static void rayer_bitbang_set_cs(int val) + { +- lpt_outbyte &= ~(1 << rayer_cs_bit); +- lpt_outbyte |= (val << rayer_cs_bit); ++ lpt_outbyte &= ~(1 << pinout->cs_bit); ++ lpt_outbyte |= (val << pinout->cs_bit); + OUTB(lpt_outbyte, lpt_iobase); + } + + static void rayer_bitbang_set_sck(int val) + { +- lpt_outbyte &= ~(1 << rayer_sck_bit); +- lpt_outbyte |= (val << rayer_sck_bit); ++ lpt_outbyte &= ~(1 << pinout->sck_bit); ++ lpt_outbyte |= (val << pinout->sck_bit); + OUTB(lpt_outbyte, lpt_iobase); + } + + static void rayer_bitbang_set_mosi(int val) + { +- lpt_outbyte &= ~(1 << rayer_mosi_bit); +- lpt_outbyte |= (val << rayer_mosi_bit); ++ lpt_outbyte &= ~(1 << pinout->mosi_bit); ++ lpt_outbyte |= (val << pinout->mosi_bit); + OUTB(lpt_outbyte, lpt_iobase); + } + +@@ -83,8 +147,8 @@ static int rayer_bitbang_get_miso(void) + { + uint8_t tmp; + +- tmp = INB(lpt_iobase + 1); +- tmp = (tmp >> rayer_miso_bit) & 0x1; ++ tmp = INB(lpt_iobase + 1) ^ 0x80; // bit.7 inverted ++ tmp = (tmp >> pinout->miso_bit) & 0x1; + return tmp; + } + +@@ -99,8 +163,8 @@ static const struct bitbang_spi_master bitbang_spi_master_rayer = { + + int rayer_spi_init(void) + { ++ const struct rayer_programmer *prog = rayer_spi_types; + char *arg = NULL; +- enum rayer_type rayer_type = TYPE_RAYER; + + /* Non-default port requested? */ + arg = extract_programmer_param("iobase"); +@@ -138,36 +202,20 @@ int rayer_spi_init(void) + + arg = extract_programmer_param("type"); + if (arg) { +- if (!strcasecmp(arg, "rayer")) { +- rayer_type = TYPE_RAYER; +- } else if (!strcasecmp(arg, "xilinx")) { +- rayer_type = TYPE_XILINX_DLC5; +- } else { ++ for (; prog->type != NULL; prog++) { ++ if (strcasecmp(arg, prog->type) == 0) { ++ break; ++ } ++ } ++ if (prog->type == NULL) { + msg_perr("Error: Invalid device type specified.\n"); + free(arg); + return 1; + } ++ free(arg); + } +- free(arg); +- switch (rayer_type) { +- case TYPE_RAYER: +- msg_pdbg("Using RayeR SPIPGM pinout.\n"); +- /* Bits for master->slave direction */ +- rayer_cs_bit = 5; +- rayer_sck_bit = 6; +- rayer_mosi_bit = 7; +- /* Bits for slave->master direction */ +- rayer_miso_bit = 6; +- break; +- case TYPE_XILINX_DLC5: +- msg_pdbg("Using Xilinx Parallel Cable III (DLC 5) pinout.\n"); +- /* Bits for master->slave direction */ +- rayer_cs_bit = 2; +- rayer_sck_bit = 1; +- rayer_mosi_bit = 0; +- /* Bits for slave->master direction */ +- rayer_miso_bit = 4; +- } ++ msg_pinfo("Using %s pinout.\n", prog->description); ++ pinout = (struct rayer_pinout *)prog->dev_data; + + if (rget_io_perms()) + return 1; +@@ -175,12 +223,60 @@ int rayer_spi_init(void) + /* Get the initial value before writing to any line. */ + lpt_outbyte = INB(lpt_iobase); + ++ if (pinout->shutdown) ++ register_shutdown(pinout->shutdown, (void*)pinout); ++ if (pinout->preinit) ++ pinout->preinit(pinout); ++ + if (bitbang_spi_init(&bitbang_spi_master_rayer)) + return 1; + + return 0; + } + ++static void byteblaster_preinit(const void *data){ ++ msg_pdbg("byteblaster_preinit\n"); ++ /* Assert #EN signal. */ ++ OUTB(2, lpt_iobase + 2 ); ++} ++ ++static int byteblaster_shutdown(void *data){ ++ msg_pdbg("byteblaster_shutdown\n"); ++ /* De-Assert #EN signal. */ ++ OUTB(0, lpt_iobase + 2 ); ++ return 0; ++} ++ ++static void stk200_preinit(const void *data) { ++ msg_pdbg("stk200_init\n"); ++ /* Assert #EN signals, set LED signal. */ ++ lpt_outbyte = (1 << 6) ; ++ OUTB(lpt_outbyte, lpt_iobase); ++} ++ ++static int stk200_shutdown(void *data) { ++ msg_pdbg("stk200_shutdown\n"); ++ /* Assert #EN signals, clear LED signal. */ ++ lpt_outbyte = (1 << 2) | (1 << 3); ++ OUTB(lpt_outbyte, lpt_iobase); ++ return 0; ++} ++ ++static void dlc5_preinit(const void *data) { ++ msg_pdbg("dlc5_preinit\n"); ++ /* Assert pin 6 to receive MISO. */ ++ lpt_outbyte |= (1<<4); ++ OUTB(lpt_outbyte, lpt_iobase); ++} ++ ++static int dlc5_shutdown(void *data) { ++ msg_pdbg("dlc5_shutdown\n"); ++ /* De-assert pin 6 to force MISO low. */ ++ lpt_outbyte &= ~(1<<4); ++ OUTB(lpt_outbyte, lpt_iobase); ++ return 0; ++} ++ + #else + #error PCI port I/O access is not supported on this architecture yet. + #endif +diff --git a/satamv.c b/satamv.c +index c3f27e7..e03508e 100644 +--- a/satamv.c ++++ b/satamv.c +@@ -57,12 +57,6 @@ static const struct par_programmer par_programmer_satamv = { + .chip_writen = fallback_chip_writen, + }; + +-static int satamv_shutdown(void *data) +-{ +- physunmap(mv_bar, 0x20000); +- return 0; +-} +- + /* + * Random notes: + * FCE# Flash Chip Enable +@@ -94,11 +88,11 @@ int satamv_init(void) + return 1; + + addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); +- mv_bar = physmap("Marvell 88SX7042 registers", addr, 0x20000); +- if (mv_bar == ERROR_PTR) ++ if (!addr) + return 1; + +- if (register_shutdown(satamv_shutdown, NULL)) ++ mv_bar = rphysmap("Marvell 88SX7042 registers", addr, 0x20000); ++ if (mv_bar == ERROR_PTR) + return 1; + + tmp = pci_mmio_readl(mv_bar + FLASH_PARAM); +@@ -144,12 +138,15 @@ int satamv_init(void) + pci_rmmio_writel(tmp, mv_bar + GPIO_PORT_CONTROL); + + /* Get I/O BAR location. */ +- tmp = pcidev_readbar(dev, PCI_BASE_ADDRESS_2); ++ addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_2); ++ if (!addr) ++ return 1; ++ + /* Truncate to reachable range. + * FIXME: Check if the I/O BAR is actually reachable. + * This is an arch specific check. + */ +- mv_iobar = tmp & 0xffff; ++ mv_iobar = addr & 0xffff; + msg_pspew("Activating I/O BAR at 0x%04x\n", mv_iobar); + + /* 512 kByte with two 8-bit latches, and +diff --git a/satasii.c b/satasii.c +index 72e35e5..83dc62c 100644 +--- a/satasii.c ++++ b/satasii.c +@@ -54,12 +54,6 @@ static const struct par_programmer par_programmer_satasii = { + .chip_writen = fallback_chip_writen, + }; + +-static int satasii_shutdown(void *data) +-{ +- physunmap(sii_bar, SATASII_MEMMAP_SIZE); +- return 0; +-} +- + static uint32_t satasii_wait_done(void) + { + uint32_t ctrl_reg; +@@ -91,21 +85,25 @@ int satasii_init(void) + + if ((id == 0x3132) || (id == 0x3124)) { + addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); ++ if (!addr) ++ return 1; + reg_offset = 0x70; + } else { + addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_5); ++ if (!addr) ++ return 1; + reg_offset = 0x50; + } + +- sii_bar = physmap("SATA SiI registers", addr, SATASII_MEMMAP_SIZE) + reg_offset; ++ sii_bar = rphysmap("SATA SiI registers", addr, SATASII_MEMMAP_SIZE); ++ if (sii_bar == ERROR_PTR) ++ return 1; ++ sii_bar += reg_offset; + + /* Check if ROM cycle are OK. */ + if ((id != 0x0680) && (!(pci_mmio_readl(sii_bar) & (1 << 26)))) + msg_pwarn("Warning: Flash seems unconnected.\n"); + +- if (register_shutdown(satasii_shutdown, NULL)) +- return 1; +- + register_par_programmer(&par_programmer_satasii, BUS_PARALLEL); + + return 0; +diff --git a/sb600spi.c b/sb600spi.c +index cb7c4ac..9523591 100644 +--- a/sb600spi.c ++++ b/sb600spi.c +@@ -57,7 +57,28 @@ static enum amd_chipset amd_gen = CHIPSET_AMD_UNKNOWN; + static void determine_generation(struct pci_dev *dev) + { + amd_gen = CHIPSET_AMD_UNKNOWN; +- if (dev->device_id == 0x780e) { ++ msg_pdbg2("Trying to determine the generation of the SPI interface... "); ++ if (dev->device_id == 0x438d) { ++ amd_gen = CHIPSET_SB6XX; ++ msg_pdbg("SB6xx detected.\n"); ++ } else if (dev->device_id == 0x439d) { ++ struct pci_dev *smbus_dev = pci_dev_find(0x1002, 0x4385); ++ if (smbus_dev == NULL) ++ return; ++ uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID); ++ if (rev >= 0x39 && rev <= 0x3D) { ++ amd_gen = CHIPSET_SB7XX; ++ msg_pdbg("SB7xx/SP5100 detected.\n"); ++ } else if (rev >= 0x40 && rev <= 0x42) { ++ amd_gen = CHIPSET_SB89XX; ++ msg_pdbg("SB8xx/SB9xx/Hudson-1 detected.\n"); ++ } else { ++ msg_pwarn("SB device found but SMBus revision 0x%02x does not match known values.\n" ++ "Assuming SB8xx/SB9xx/Hudson-1. Please send a log to flashrom@flashrom.org\n", ++ rev); ++ amd_gen = CHIPSET_SB89XX; ++ } ++ } else if (dev->device_id == 0x780e) { + /* The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash) + * although they use different SPI interfaces. */ + #ifdef USE_YANGTZE_HEURISTICS +@@ -94,7 +115,11 @@ static void determine_generation(struct pci_dev *dev) + "the output of lspci -nnvx, thanks!.\n", rev); + } + #endif +- } ++ } else ++ msg_pwarn("%s: Unknown LPC device %" PRIx16 ":%" PRIx16 ".\n" ++ "Please report this to flashrom@flashrom.org and include this log and\n" ++ "the output of lspci -nnvx, thanks!\n", ++ __func__, dev->vendor_id, dev->device_id); + } + + static void reset_internal_fifo_pointer(void) +@@ -247,10 +272,66 @@ static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt, + return 0; + } + ++struct spispeed { ++ const char *const name; ++ const uint8_t speed; ++}; ++ ++static const struct spispeed spispeeds[] = { ++ { "66 MHz", 0x00 }, ++ { "33 MHz", 0x01 }, ++ { "22 MHz", 0x02 }, ++ { "16.5 MHz", 0x03 }, ++}; ++ ++static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed) ++{ ++ bool success = false; ++ uint8_t speed = spispeed->speed; ++ ++ msg_pdbg("Setting SPI clock to %s (0x%x).\n", spispeed->name, speed); ++ if (amd_gen != CHIPSET_YANGTZE) { ++ rmmio_writeb((mmio_readb(sb600_spibar + 0xd) & ~(0x3 << 4)) | (speed << 4), sb600_spibar + 0xd); ++ success = (speed == ((mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3)); ++ } ++ ++ if (!success) { ++ msg_perr("Setting SPI clock failed.\n"); ++ return 1; ++ } ++ return 0; ++} ++ ++static int handle_speed(struct pci_dev *dev) ++{ ++ uint32_t tmp; ++ int8_t spispeed_idx = 3; /* Default to 16.5 MHz */ ++ ++ /* See the chipset support matrix for SPI Base_Addr below for an explanation of the symbols used. ++ * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson234 yangtze ++ * 18 rsvd <- fastReadEnable ? <- ? SpiReadMode[0] ++ * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1] ++ */ ++ if (amd_gen != CHIPSET_YANGTZE) { ++ if (amd_gen >= CHIPSET_SB89XX && amd_gen <= CHIPSET_HUDSON234) { ++ bool fast_read = (mmio_readl(sb600_spibar + 0x00) >> 18) & 0x1; ++ msg_pdbg("Fast Reads are %sabled\n", fast_read ? "en" : "dis"); ++ if (fast_read) { ++ msg_pdbg("Disabling them temporarily.\n"); ++ rmmio_writel(mmio_readl(sb600_spibar + 0x00) & ~(0x1 << 18), ++ sb600_spibar + 0x00); ++ } ++ } ++ tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3; ++ msg_pdbg("NormSpeed is %s\n", spispeeds[tmp].name); ++ } ++ return set_speed(dev, &spispeeds[spispeed_idx]); ++} ++ + static int sb600_handle_imc(struct pci_dev *dev, bool amd_imc_force) + { + /* Handle IMC everywhere but sb600 which does not have one. */ +- if (dev->device_id == 0x438d) ++ if (amd_gen == CHIPSET_SB6XX) + return 0; + + /* TODO: we should not only look at IntegratedImcPresent (LPC Dev 20, Func 3, 40h) but also at +@@ -297,9 +378,6 @@ int sb600_probe_spi(struct pci_dev *dev) + uint32_t tmp; + uint8_t reg; + bool amd_imc_force = false; +- static const char *const speed_names[4] = { +- "66/reserved", "33", "22", "16.5" +- }; + + char *arg = extract_programmer_param("amd_imc_force"); + if (arg && !strcmp(arg, "yes")) { +@@ -326,14 +404,20 @@ int sb600_probe_spi(struct pci_dev *dev) + return 0; + + /* Physical memory has to be mapped at page (4k) boundaries. */ +- sb600_spibar = physmap("SB600 SPI registers", tmp & 0xfffff000, +- 0x1000); ++ sb600_spibar = rphysmap("SB600 SPI registers", tmp & 0xfffff000, 0x1000); ++ if (sb600_spibar == ERROR_PTR) ++ return ERROR_FATAL; ++ + /* The low bits of the SPI base address are used as offset into + * the mapped page. + */ + sb600_spibar += tmp & 0xfff; + + determine_generation(dev); ++ if (amd_gen == CHIPSET_AMD_UNKNOWN) { ++ msg_perr("Could not determine chipset generation."); ++ return ERROR_NONFATAL; ++ } + + if (amd_gen == CHIPSET_YANGTZE) { + msg_perr("SPI on Kabini/Temash and newer chipsets are not yet supported.\n" +@@ -341,34 +425,87 @@ int sb600_probe_spi(struct pci_dev *dev) + return ERROR_NONFATAL; + } + +- tmp = pci_read_long(dev, 0xa0); +- msg_pdbg("AltSpiCSEnable=%i, SpiRomEnable=%i, " +- "AbortEnable=%i\n", tmp & 0x1, (tmp & 0x2) >> 1, +- (tmp & 0x4) >> 2); +- tmp = (pci_read_byte(dev, 0xba) & 0x4) >> 2; +- msg_pdbg("PrefetchEnSPIFromIMC=%i, ", tmp); +- +- tmp = pci_read_byte(dev, 0xbb); +- /* FIXME: Set bit 3,6,7 if not already set. +- * Set bit 5, otherwise SPI accesses are pointless in LPC mode. +- * See doc 42413 AMD SB700/710/750 RPR. ++ /* How to read the following table and similar ones in this file: ++ * "?" means we have no datasheet for this chipset generation or it doesn't have any relevant info. ++ * "<-" means the bit/register meaning is identical to the next non-"?" chipset to the left. "<-" thus ++ * never refers to another "?". ++ * If a "?" chipset is between two chipsets with identical meaning, we assume the meaning didn't change ++ * twice in between, i.e. the meaning is unchanged for the "?" chipset. Usually we assume that ++ * succeeding hardware supports the same functionality as its predecessor unless proven different by ++ * tests or documentation, hence "?" will often be implemented equally to "<-". ++ * ++ * Chipset support matrix for SPI Base_Addr (LPC PCI reg 0xa0) ++ * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze ++ * 3 rsvd <- <- ? <- ? RouteTpm2Spi ++ * 2 rsvd AbortEnable rsvd ? <- ? <- ++ * 1 rsvd SpiRomEnable <- ? <- ? <- ++ * 0 rsvd AltSpiCSEnable rsvd ? <- ? <- + */ +- msg_pdbg("PrefetchEnSPIFromHost=%i, SpiOpEnInLpcMode=%i\n", +- tmp & 0x1, (tmp & 0x20) >> 5); +- tmp = mmio_readl(sb600_spibar); +- /* FIXME: If SpiAccessMacRomEn or SpiHostAccessRomEn are zero on +- * SB700 or later, reads and writes will be corrupted. Abort in this +- * case. Make sure to avoid this check on SB600. ++ if (amd_gen >= CHIPSET_SB7XX) { ++ tmp = pci_read_long(dev, 0xa0); ++ msg_pdbg("SpiRomEnable=%i", (tmp >> 1) & 0x1); ++ if (amd_gen == CHIPSET_SB7XX) ++ msg_pdbg(", AltSpiCSEnable=%i, AbortEnable=%i", tmp & 0x1, (tmp >> 2) & 0x1); ++ ++ tmp = pci_read_byte(dev, 0xba); ++ msg_pdbg(", PrefetchEnSPIFromIMC=%i", (tmp & 0x4) >> 2); ++ ++ tmp = pci_read_byte(dev, 0xbb); ++ /* FIXME: Set bit 3,6,7 if not already set. ++ * Set bit 5, otherwise SPI accesses are pointless in LPC mode. ++ * See doc 42413 AMD SB700/710/750 RPR. ++ */ ++ if (amd_gen == CHIPSET_SB7XX) ++ msg_pdbg(", SpiOpEnInLpcMode=%i", (tmp >> 5) & 0x1); ++ msg_pdbg(", PrefetchEnSPIFromHost=%i\n", tmp & 0x1); ++ } ++ ++ /* Chipset support matrix for SPI_Cntrl0 (spibar + 0x0) ++ * See the chipset support matrix for SPI Base_Addr above for an explanation of the symbols used. ++ * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze ++ * 17 rsvd <- <- ? <- ? <- ++ * 18 rsvd <- fastReadEnable<1> ? <- ? SpiReadMode[0]<1> ++ * 19 SpiArbEnable <- <- ? <- ? <- ++ * 20 (FifoPtrClr) <- <- ? <- ? <- ++ * 21 (FifoPtrInc) <- <- ? <- ? IllegalAccess ++ * 22 SpiAccessMacRomEn <- <- ? <- ? <- ++ * 23 SpiHostAccessRomEn <- <- ? <- ? <- ++ * 24:26 ArbWaitCount <- <- ? <- ? <- ++ * 27 SpiBridgeDisable <- <- ? <- ? rsvd ++ * 28 rsvd DropOneClkOnRd = SPIClkGate ? <- ? <- ++ * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]<1> ++ * 31 rsvd <- SpiBusy ? <- ? <- ++ * ++ * <1> see handle_speed + */ +- msg_pdbg("(0x%08" PRIx32 ") fastReadEnable=%u, SpiArbEnable=%i, SpiAccessMacRomEn=%i, " +- "SpiHostAccessRomEn=%i, ArbWaitCount=%i, " +- "SpiBridgeDisable=%i, DropOneClkOnRd=%i\n", +- tmp, (tmp >> 18) & 0x1, +- (tmp >> 19) & 0x1, (tmp >> 22) & 0x1, +- (tmp >> 23) & 0x1, (tmp >> 24) & 0x7, +- (tmp >> 27) & 0x1, (tmp >> 28) & 0x1); +- tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3; +- msg_pdbg("NormSpeed is %s MHz\n", speed_names[tmp]); ++ tmp = mmio_readl(sb600_spibar + 0x00); ++ msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%i", tmp, (tmp >> 19) & 0x1); ++ ++ msg_pdbg(", SpiAccessMacRomEn=%i, SpiHostAccessRomEn=%i, ArbWaitCount=%i", ++ (tmp >> 22) & 0x1, (tmp >> 23) & 0x1, (tmp >> 24) & 0x7); ++ ++ if (amd_gen != CHIPSET_YANGTZE) ++ msg_pdbg(", SpiBridgeDisable=%i", (tmp >> 27) & 0x1); ++ ++ switch (amd_gen) { ++ case CHIPSET_SB7XX: ++ msg_pdbg(", DropOneClkOnRd/SpiClkGate=%i", (tmp >> 28) & 0x1); ++ case CHIPSET_SB89XX: ++ case CHIPSET_HUDSON234: ++ msg_pdbg(", SpiBusy=%i", (tmp >> 31) & 0x1); ++ default: break; ++ } ++ msg_pdbg("\n"); ++ ++ if (((tmp >> 22) & 0x1) == 0 || ((tmp >> 23) & 0x1) == 0) { ++ msg_perr("ERROR: State of SpiAccessMacRomEn or SpiHostAccessRomEn prohibits full access.\n"); ++ return ERROR_NONFATAL; ++ } ++ ++ if (amd_gen >= CHIPSET_SB89XX) { ++ tmp = mmio_readb(sb600_spibar + 0x1D); ++ msg_pdbg("Using SPI_CS%d\n", tmp & 0x3); ++ } + + /* Look for the SMBus device. */ + smbus_dev = pci_dev_find(0x1002, 0x4385); +@@ -409,6 +546,9 @@ int sb600_probe_spi(struct pci_dev *dev) + return 0; + } + ++ if (handle_speed(dev) != 0) ++ return ERROR_FATAL; ++ + if (sb600_handle_imc(dev, amd_imc_force) != 0) + return ERROR_FATAL; + +diff --git a/serial.c b/serial.c +index 1b394cd..126079a 100644 +--- a/serial.c ++++ b/serial.c +@@ -41,12 +41,6 @@ + + fdtype sp_fd = SER_INV_FD; + +-void __attribute__((noreturn)) sp_die(char *msg) +-{ +- perror(msg); +- exit(1); +-} +- + #ifdef _WIN32 + struct baudentry { + DWORD flag; +@@ -158,35 +152,18 @@ static void msg_perr_strerror(const char *msg) + #endif + } + +-fdtype sp_openserport(char *dev, unsigned int baud) ++int serialport_config(fdtype fd, unsigned int baud) + { +-#ifdef _WIN32 +- HANDLE fd; +- char *dev2 = dev; +- if ((strlen(dev) > 3) && +- (tolower((unsigned char)dev[0]) == 'c') && +- (tolower((unsigned char)dev[1]) == 'o') && +- (tolower((unsigned char)dev[2]) == 'm')) { +- dev2 = malloc(strlen(dev) + 5); +- if (!dev2) { +- msg_perr_strerror("Out of memory: "); +- return SER_INV_FD; +- } +- strcpy(dev2, "\\\\.\\"); +- strcpy(dev2 + 4, dev); +- } +- fd = CreateFile(dev2, GENERIC_READ | GENERIC_WRITE, 0, NULL, +- OPEN_EXISTING, 0, NULL); +- if (dev2 != dev) +- free(dev2); +- if (fd == INVALID_HANDLE_VALUE) { +- msg_perr_strerror("Cannot open serial port: "); +- return SER_INV_FD; ++ if (fd == SER_INV_FD) { ++ msg_perr("%s: File descriptor is invalid.\n", __func__); ++ return 1; + } ++ ++#ifdef _WIN32 + DCB dcb; + if (!GetCommState(fd, &dcb)) { + msg_perr_strerror("Could not fetch original serial port configuration: "); +- goto out_close; ++ return 1; + } + const struct baudentry *entry = round_baud(baud); + dcb.BaudRate = entry->flag; +@@ -195,35 +172,25 @@ fdtype sp_openserport(char *dev, unsigned int baud) + dcb.StopBits = ONESTOPBIT; + if (!SetCommState(fd, &dcb)) { + msg_perr_strerror("Could not change serial port configuration: "); +- goto out_close; ++ return 1; + } + if (!GetCommState(fd, &dcb)) { + msg_perr_strerror("Could not fetch new serial port configuration: "); +- goto out_close; ++ return 1; + } + msg_pdbg("Baud rate is %ld.\n", dcb.BaudRate); +- return fd; +-out_close: +- CloseHandle(sp_fd); +- return SER_INV_FD; + #else + struct termios wanted, observed; +- int fd; +- fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY); +- if (fd < 0) { +- msg_perr_strerror("Cannot open serial port: "); +- return SER_INV_FD; +- } + fcntl(fd, F_SETFL, 0); + if (tcgetattr(fd, &observed) != 0) { + msg_perr_strerror("Could not fetch original serial port configuration: "); +- goto out_close; ++ return 1; + } + wanted = observed; + const struct baudentry *entry = round_baud(baud); + if (cfsetispeed(&wanted, entry->flag) != 0 || cfsetospeed(&wanted, entry->flag) != 0) { + msg_perr_strerror("Could not set serial baud rate: "); +- goto out_close; ++ return 1; + } + wanted.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS); + wanted.c_cflag |= (CS8 | CLOCAL | CREAD); +@@ -232,11 +199,11 @@ out_close: + wanted.c_oflag &= ~OPOST; + if (tcsetattr(fd, TCSANOW, &wanted) != 0) { + msg_perr_strerror("Could not change serial port configuration: "); +- goto out_close; ++ return 1; + } + if (tcgetattr(fd, &observed) != 0) { + msg_perr_strerror("Could not fetch new serial port configuration: "); +- goto out_close; ++ return 1; + } + if (observed.c_cflag != wanted.c_cflag || + observed.c_lflag != wanted.c_lflag || +@@ -244,14 +211,54 @@ out_close: + observed.c_oflag != wanted.c_oflag || + cfgetispeed(&observed) != cfgetispeed(&wanted)) { + msg_perr("%s: Some requested options did not stick.\n", __func__); +- goto out_close; ++ return 1; + } +- msg_pdbg("Baud rate is %d.\n", entry->baud); +- return fd; ++ msg_pdbg("Baud rate is %d now.\n", entry->baud); ++#endif ++ return 0; ++} + +-out_close: +- close(sp_fd); +- return SER_INV_FD; ++fdtype sp_openserport(char *dev, unsigned int baud) ++{ ++ fdtype fd; ++#ifdef _WIN32 ++ char *dev2 = dev; ++ if ((strlen(dev) > 3) && ++ (tolower((unsigned char)dev[0]) == 'c') && ++ (tolower((unsigned char)dev[1]) == 'o') && ++ (tolower((unsigned char)dev[2]) == 'm')) { ++ dev2 = malloc(strlen(dev) + 5); ++ if (!dev2) { ++ msg_perr_strerror("Out of memory: "); ++ return SER_INV_FD; ++ } ++ strcpy(dev2, "\\\\.\\"); ++ strcpy(dev2 + 4, dev); ++ } ++ fd = CreateFile(dev2, GENERIC_READ | GENERIC_WRITE, 0, NULL, ++ OPEN_EXISTING, 0, NULL); ++ if (dev2 != dev) ++ free(dev2); ++ if (fd == INVALID_HANDLE_VALUE) { ++ msg_perr_strerror("Cannot open serial port: "); ++ return SER_INV_FD; ++ } ++ if (serialport_config(fd, baud) != 0) { ++ CloseHandle(fd); ++ return SER_INV_FD; ++ } ++ return fd; ++#else ++ fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY); ++ if (fd < 0) { ++ msg_perr_strerror("Cannot open serial port: "); ++ return SER_INV_FD; ++ } ++ if (serialport_config(fd, baud) != 0) { ++ close(fd); ++ return SER_INV_FD; ++ } ++ return fd; + #endif + } + +@@ -350,7 +357,7 @@ int serialport_write(unsigned char *buf, unsigned int writecnt) + if (!tmp) { + msg_pdbg2("Empty write\n"); + empty_writes--; +- programmer_delay(500); ++ internal_delay(500); + if (empty_writes == 0) { + msg_perr("Serial port is unresponsive!\n"); + return 1; +diff --git a/serprog.c b/serprog.c +index 3476315..35c4f32 100644 +--- a/serprog.c ++++ b/serprog.c +@@ -100,6 +100,7 @@ static int sp_opensocket(char *ip, unsigned int port) + if (NULL == hostPtr) { + hostPtr = gethostbyaddr(ip, strlen(ip), AF_INET); + if (NULL == hostPtr) { ++ close(sock); + msg_perr("Error: cannot resolve %s\n", ip); + return -1; + } +@@ -114,7 +115,11 @@ static int sp_opensocket(char *ip, unsigned int port) + } + /* We are latency limited, and sometimes do write-write-read * + * (write-n) - so enable TCP_NODELAY. */ +- setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int)); ++ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int))) { ++ close(sock); ++ msg_perr("Error: serprog cannot set socket options: %s\n", strerror(errno)); ++ return -1; ++ } + return sock; + } + #endif +@@ -237,43 +242,58 @@ static int sp_docommand(uint8_t command, uint32_t parmlen, + return 0; + } + +-static void sp_flush_stream(void) ++static int sp_flush_stream(void) + { + if (sp_streamed_transmit_ops) + do { + unsigned char c; + if (serialport_read(&c, 1) != 0) { +- sp_die("Error: cannot read from device (flushing stream)"); ++ msg_perr("Error: cannot read from device (flushing stream)"); ++ return 1; + } + if (c == S_NAK) { + msg_perr("Error: NAK to a stream buffer operation\n"); +- exit(1); ++ return 1; + } + if (c != S_ACK) { + msg_perr("Error: Invalid reply 0x%02X from device\n", c); +- exit(1); ++ return 1; + } + } while (--sp_streamed_transmit_ops); + sp_streamed_transmit_ops = 0; + sp_streamed_transmit_bytes = 0; ++ return 0; + } + +-static int sp_stream_buffer_op(uint8_t cmd, uint32_t parmlen, uint8_t * parms) ++static int sp_stream_buffer_op(uint8_t cmd, uint32_t parmlen, uint8_t *parms) + { + uint8_t *sp; + if (sp_automatic_cmdcheck(cmd)) + return 1; ++ + sp = malloc(1 + parmlen); +- if (!sp) sp_die("Error: cannot malloc command buffer"); ++ if (!sp) { ++ msg_perr("Error: cannot malloc command buffer\n"); ++ return 1; ++ } + sp[0] = cmd; + memcpy(&(sp[1]), parms, parmlen); +- if (sp_streamed_transmit_bytes >= (1 + parmlen + sp_device_serbuf_size)) +- sp_flush_stream(); +- if (serialport_write(sp, 1 + parmlen) != 0) +- sp_die("Error: cannot write command"); +- free(sp); ++ ++ if (sp_streamed_transmit_bytes >= (1 + parmlen + sp_device_serbuf_size)) { ++ if (sp_flush_stream() != 0) { ++ free(sp); ++ return 1; ++ } ++ } ++ if (serialport_write(sp, 1 + parmlen) != 0) { ++ msg_perr("Error: cannot write command\n"); ++ free(sp); ++ return 1; ++ } + sp_streamed_transmit_ops += 1; + sp_streamed_transmit_bytes += 1 + parmlen; ++ ++ free(sp); + return 0; + } + +@@ -656,16 +676,16 @@ int serprog_init(void) + return 0; + } + +-/* Move an in flashrom buffer existing write-n operation to * +- * the on-device operation buffer. */ +-static void sp_pass_writen(void) ++/* Move an in flashrom buffer existing write-n operation to the on-device operation buffer. */ ++static int sp_pass_writen(void) + { + unsigned char header[7]; +- msg_pspew(MSGHEADER "Passing write-n bytes=%d addr=0x%x\n", +- sp_write_n_bytes, sp_write_n_addr); +- if (sp_streamed_transmit_bytes >= +- (7 + sp_write_n_bytes + sp_device_serbuf_size)) +- sp_flush_stream(); ++ msg_pspew(MSGHEADER "Passing write-n bytes=%d addr=0x%x\n", sp_write_n_bytes, sp_write_n_addr); ++ if (sp_streamed_transmit_bytes >= (7 + sp_write_n_bytes + sp_device_serbuf_size)) { ++ if (sp_flush_stream() != 0) { ++ return 1; ++ } ++ } + /* In case it's just a single byte send it as a single write. */ + if (sp_write_n_bytes == 1) { + sp_write_n_bytes = 0; +@@ -673,9 +693,10 @@ static void sp_pass_writen(void) + header[1] = (sp_write_n_addr >> 8) & 0xFF; + header[2] = (sp_write_n_addr >> 16) & 0xFF; + header[3] = sp_write_n_buf[0]; +- sp_stream_buffer_op(S_CMD_O_WRITEB, 4, header); ++ if (sp_stream_buffer_op(S_CMD_O_WRITEB, 4, header) != 0) ++ return 1; + sp_opbuf_usage += 5; +- return; ++ return 0; + } + header[0] = S_CMD_O_WRITEN; + header[1] = (sp_write_n_bytes >> 0) & 0xFF; +@@ -684,39 +705,55 @@ static void sp_pass_writen(void) + header[4] = (sp_write_n_addr >> 0) & 0xFF; + header[5] = (sp_write_n_addr >> 8) & 0xFF; + header[6] = (sp_write_n_addr >> 16) & 0xFF; +- if (serialport_write(header, 7) != 0) +- sp_die("Error: cannot write write-n command\n"); +- if (serialport_write(sp_write_n_buf, sp_write_n_bytes) != 0) +- sp_die("Error: cannot write write-n data"); ++ if (serialport_write(header, 7) != 0) { ++ msg_perr(MSGHEADER "Error: cannot write write-n command\n"); ++ return 1; ++ } ++ if (serialport_write(sp_write_n_buf, sp_write_n_bytes) != 0) { ++ msg_perr(MSGHEADER "Error: cannot write write-n data"); ++ return 1; ++ } + sp_streamed_transmit_bytes += 7 + sp_write_n_bytes; + sp_streamed_transmit_ops += 1; + sp_opbuf_usage += 7 + sp_write_n_bytes; + sp_write_n_bytes = 0; + sp_prev_was_write = 0; ++ return 0; + } + +-static void sp_execute_opbuf_noflush(void) ++static int sp_execute_opbuf_noflush(void) + { +- if ((sp_max_write_n) && (sp_write_n_bytes)) +- sp_pass_writen(); +- sp_stream_buffer_op(S_CMD_O_EXEC, 0, NULL); +- msg_pspew(MSGHEADER "Executed operation buffer of %d bytes\n", +- sp_opbuf_usage); ++ if ((sp_max_write_n) && (sp_write_n_bytes)) { ++ if (sp_pass_writen() != 0) { ++ msg_perr("Error: could not transfer write buffer\n"); ++ return 1; ++ } ++ } ++ if (sp_stream_buffer_op(S_CMD_O_EXEC, 0, NULL) != 0) { ++ msg_perr("Error: could not execute command buffer\n"); ++ return 1; ++ } ++ msg_pspew(MSGHEADER "Executed operation buffer of %d bytes\n", sp_opbuf_usage); + sp_opbuf_usage = 0; + sp_prev_was_write = 0; +- return; ++ return 0; + } + +-static void sp_execute_opbuf(void) ++static int sp_execute_opbuf(void) + { +- sp_execute_opbuf_noflush(); +- sp_flush_stream(); ++ if (sp_execute_opbuf_noflush() != 0) ++ return 1; ++ if (sp_flush_stream() != 0) ++ return 1; ++ ++ return 0; + } + + static int serprog_shutdown(void *data) + { + if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) +- sp_execute_opbuf(); ++ if (sp_execute_opbuf() != 0) ++ msg_pwarn("Could not flush command buffer.\n"); + if (sp_check_commandavail(S_CMD_S_PIN_STATE)) { + uint8_t dis = 0; + if (sp_docommand(S_CMD_S_PIN_STATE, 1, &dis, 0, NULL) == 0) +@@ -731,14 +768,15 @@ static int serprog_shutdown(void *data) + return 0; + } + +-static void sp_check_opbuf_usage(int bytes_to_be_added) ++static int sp_check_opbuf_usage(int bytes_to_be_added) + { + if (sp_device_opbuf_size <= (sp_opbuf_usage + bytes_to_be_added)) { +- sp_execute_opbuf(); +- /* If this happens in the mid of an page load the page load * +- * will probably fail. */ +- msg_pdbg(MSGHEADER "Warning: executed operation buffer due to size reasons\n"); ++ /* If this happens in the middle of a page load the page load will probably fail. */ ++ msg_pwarn(MSGHEADER "Warning: executed operation buffer due to size reasons\n"); ++ if (sp_execute_opbuf() != 0) ++ return 1; + } ++ return 0; + } + + static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val, +@@ -768,7 +806,7 @@ static void serprog_chip_writeb(const struct flashctx *flash, uint8_t val, + writeb_parm[1] = (addr >> 8) & 0xFF; + writeb_parm[2] = (addr >> 16) & 0xFF; + writeb_parm[3] = val; +- sp_stream_buffer_op(S_CMD_O_WRITEB, 4, writeb_parm); ++ sp_stream_buffer_op(S_CMD_O_WRITEB, 4, writeb_parm); // FIXME: return error + sp_opbuf_usage += 5; + } + } +@@ -785,16 +823,16 @@ static uint8_t serprog_chip_readb(const struct flashctx *flash, + buf[0] = ((addr >> 0) & 0xFF); + buf[1] = ((addr >> 8) & 0xFF); + buf[2] = ((addr >> 16) & 0xFF); +- sp_stream_buffer_op(S_CMD_R_BYTE, 3, buf); +- sp_flush_stream(); ++ sp_stream_buffer_op(S_CMD_R_BYTE, 3, buf); // FIXME: return error ++ sp_flush_stream(); // FIXME: return error + if (serialport_read(&c, 1) != 0) +- sp_die("readb byteread"); ++ msg_perr(MSGHEADER "readb byteread"); // FIXME: return error + msg_pspew("%s addr=0x%" PRIxPTR " returning 0x%02X\n", __func__, addr, c); + return c; + } + + /* Local version that really does the job, doesn't care of max_read_n. */ +-static void sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len) ++static int sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len) + { + unsigned char sbuf[6]; + msg_pspew("%s: addr=0x%" PRIxPTR " len=%zu\n", __func__, addr, len); +@@ -808,10 +846,13 @@ static void sp_do_read_n(uint8_t * buf, const chipaddr addr, size_t len) + sbuf[4] = ((len >> 8) & 0xFF); + sbuf[5] = ((len >> 16) & 0xFF); + sp_stream_buffer_op(S_CMD_R_NBYTES, 6, sbuf); +- sp_flush_stream(); +- if (serialport_read(buf, len) != 0) +- sp_die("Error: cannot read read-n data"); +- return; ++ if (sp_flush_stream() != 0) ++ return 1; ++ if (serialport_read(buf, len) != 0) { ++ msg_perr(MSGHEADER "Error: cannot read read-n data"); ++ return 1; ++ } ++ return 0; + } + + /* The externally called version that makes sure that max_read_n is obeyed. */ +@@ -821,12 +862,12 @@ static void serprog_chip_readn(const struct flashctx *flash, uint8_t * buf, + size_t lenm = len; + chipaddr addrm = addr; + while ((sp_max_read_n != 0) && (lenm > sp_max_read_n)) { +- sp_do_read_n(&(buf[addrm-addr]), addrm, sp_max_read_n); ++ sp_do_read_n(&(buf[addrm-addr]), addrm, sp_max_read_n); // FIXME: return error + addrm += sp_max_read_n; + lenm -= sp_max_read_n; + } + if (lenm) +- sp_do_read_n(&(buf[addrm-addr]), addrm, lenm); ++ sp_do_read_n(&(buf[addrm-addr]), addrm, lenm); // FIXME: return error + } + + void serprog_delay(int usecs) +@@ -858,11 +899,18 @@ static int serprog_spi_send_command(struct flashctx *flash, + unsigned char *parmbuf; + int ret; + msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt); +- if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) +- sp_execute_opbuf(); ++ if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) { ++ if (sp_execute_opbuf() != 0) { ++ msg_perr("Error: could not execute command buffer before sending SPI commands.\n"); ++ return 1; ++ } ++ } ++ + parmbuf = malloc(writecnt + 6); +- if (!parmbuf) +- sp_die("Error: cannot malloc SPI send param buffer"); ++ if (!parmbuf) { ++ msg_perr("Error: could not allocate SPI send param buffer.\n"); ++ return 1; ++ } + parmbuf[0] = (writecnt >> 0) & 0xFF; + parmbuf[1] = (writecnt >> 8) & 0xFF; + parmbuf[2] = (writecnt >> 16) & 0xFF; +@@ -879,8 +927,7 @@ static int serprog_spi_send_command(struct flashctx *flash, + /* FIXME: This function is optimized so that it does not split each transaction + * into chip page_size long blocks unnecessarily like spi_read_chunked. This has + * the advantage that it is much faster for most chips, but breaks those with +- * non-contiguous address space (like AT45DB161D). When spi_read_chunked is +- * fixed this method can be removed. */ ++ * non-continuous reads. When spi_read_chunked is fixed this method can be removed. */ + static int serprog_spi_read(struct flashctx *flash, uint8_t *buf, + unsigned int start, unsigned int len) + { +diff --git a/spi25.c b/spi25.c +index e001196..862a865 100644 +--- a/spi25.c ++++ b/spi25.c +@@ -679,7 +679,7 @@ int spi_block_erase_20(struct flashctx *flash, unsigned int addr, + + result = spi_send_multicommand(flash, cmds); + if (result) { +- msg_cerr("%s failed during command execution at address 0x%x\n", ++ msg_pdbg("%s failed during command execution at address 0x%x\n", + __func__, addr); + return result; + } +@@ -1128,13 +1128,9 @@ int default_spi_write_aai(struct flashctx *flash, uint8_t *buf, unsigned int sta + + + result = spi_send_multicommand(flash, cmds); +- if (result) { +- msg_cerr("%s failed during start command execution\n", +- __func__); +- /* FIXME: Should we send WRDI here as well to make sure the chip +- * is not in AAI mode? +- */ +- return result; ++ if (result != 0) { ++ msg_cerr("%s failed during start command execution: %d\n", __func__, result); ++ goto bailout; + } + while (spi_read_status_register(flash) & SPI_SR_WIP) + programmer_delay(10); +@@ -1146,16 +1142,21 @@ int default_spi_write_aai(struct flashctx *flash, uint8_t *buf, unsigned int sta + while (pos < start + len - 1) { + cmd[1] = buf[pos++ - start]; + cmd[2] = buf[pos++ - start]; +- spi_send_command(flash, JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, +- cmd, NULL); ++ result = spi_send_command(flash, JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL); ++ if (result != 0) { ++ msg_cerr("%s failed during followup AAI command execution: %d\n", __func__, result); ++ goto bailout; ++ } + while (spi_read_status_register(flash) & SPI_SR_WIP) + programmer_delay(10); + } + +- /* Use WRDI to exit AAI mode. This needs to be done before issuing any +- * other non-AAI command. +- */ +- spi_write_disable(flash); ++ /* Use WRDI to exit AAI mode. This needs to be done before issuing any other non-AAI command. */ ++ result = spi_write_disable(flash); ++ if (result != 0) { ++ msg_cerr("%s failed to disable AAI mode.\n", __func__); ++ return SPI_GENERIC_ERROR; ++ } + + /* Write remaining byte (if any). */ + if (pos < start + len) { +@@ -1165,4 +1166,10 @@ int default_spi_write_aai(struct flashctx *flash, uint8_t *buf, unsigned int sta + } + + return 0; ++ ++bailout: ++ result = spi_write_disable(flash); ++ if (result != 0) ++ msg_cerr("%s failed to disable AAI mode.\n", __func__); ++ return SPI_GENERIC_ERROR; + } +diff --git a/spi25_statusreg.c b/spi25_statusreg.c +index 8fb7f2d..48fceb0 100644 +--- a/spi25_statusreg.c ++++ b/spi25_statusreg.c +@@ -270,7 +270,7 @@ static void spi_prettyprint_status_register_bp(uint8_t status, int bp) + } + + /* Unnamed bits. */ +-static void spi_prettyprint_status_register_bit(uint8_t status, int bit) ++void spi_prettyprint_status_register_bit(uint8_t status, int bit) + { + msg_cdbg("Chip status register: Bit %i is %sset\n", bit, (status & (1 << bit)) ? "" : "not "); + } +diff --git a/stm50.c b/stm50.c +new file mode 100644 +index 0000000..edcfdd2 +--- /dev/null ++++ b/stm50.c +@@ -0,0 +1,115 @@ ++/* ++ * This file is part of the flashrom project. ++ * ++ * Copyright (C) 2008 Claus Gindhart ++ * Copyright (C) 2009 Sean Nelson ++ * Copyright (C) 2013 Stefan Tauner ++ * ++ * 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. ++ * ++ * 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 ++ */ ++ ++/* ++ * All ST M50 chips are locked on startup. Most of them have a uniform 64 kB block layout, but some have ++ * a non-uniform block/sector segmentation which has to be handled with more care. Some of the non-uniform ++ * chips support erasing of the 4 kB sectors with another command. ++ */ ++ ++#include "flash.h" ++#include "flashchips.h" ++#include "chipdrivers.h" ++ ++static int stm50_unlock_address(struct flashctx *flash, int offset) ++{ ++ chipaddr wrprotect = flash->virtual_registers + 2; ++ static const uint8_t unlock_sector = 0x00; ++ msg_cdbg("unlocking at 0x%x\n", offset); ++ chip_writeb(flash, unlock_sector, wrprotect + offset); ++ if (chip_readb(flash, wrprotect + offset) != unlock_sector) { ++ msg_cerr("Cannot unlock address 0x%x\n", offset); ++ return -1; ++ } ++ return 0; ++} ++ ++/* Chips known to use a non-uniform block and sector layout for locking (as well as for erasing): ++ * Name Size Address range of lock registers ++ * M50FLW080A 1MB FFB00002 - FFBFF002 ++ * M50FLW080B 1MB FFB00002 - FFBFF002 ++ * M50FW002 256k FFBC0002 - FFBFC002 ++ * M50LPW116 2MB FFA00002 - FFBFC002 ++ */ ++int unlock_stm50_nonuniform(struct flashctx *flash) ++{ ++ int i; ++ struct eraseblock *eraseblocks = flash->chip->block_erasers[0].eraseblocks; ++ unsigned int done = 0; ++ for (i = 0; i < NUM_ERASEREGIONS && eraseblocks[i].count != 0; i++) { ++ unsigned int block_size = eraseblocks[i].size; ++ unsigned int block_count = eraseblocks[i].count; ++ ++ int j; ++ for (j = 0; j < block_count; j++) { ++ if (stm50_unlock_address(flash, done)) { ++ msg_cerr("UNLOCK FAILED!\n"); ++ return -1; ++ } ++ done += block_count * block_size; ++ } ++ } ++ return 0; ++} ++ ++/* Unlocking for uniform 64 kB blocks starting at offset 2 of the feature registers. */ ++int unlock_stm50_uniform(struct flashctx *flash) ++{ ++ int i; ++ for (i = 0; i < flash->chip->total_size * 1024; i+= 64 * 1024) { ++ if (stm50_unlock_address(flash, i)) { ++ msg_cerr("UNLOCK FAILED!\n"); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static int stm50_erase_sector(struct flashctx *flash, unsigned int addr) ++{ ++ chipaddr bios = flash->virtual_memory + addr; ++ ++ // clear status register ++ chip_writeb(flash, 0x50, bios); ++ // now start it ++ chip_writeb(flash, 0x32, bios); ++ chip_writeb(flash, 0xd0, bios); ++ programmer_delay(10); ++ ++ uint8_t status = wait_82802ab(flash); ++ print_status_82802ab(status); ++ ++ return status == 0x80; ++} ++ ++/* Some ST M50* chips do support erasing of sectors. This function will derive the erase function to use from ++ * the length of the of the block. For calls that apparently do not address a sector (but a block) we just call ++ * the block erase function instead. FIXME: This duplicates the behavior of the remaining erasers for blocks and ++ * might be fixed when flashrom supports multiple functions per eraser or erasers that do erase parts of the ++ * chip only. */ ++int erase_sector_stm50(struct flashctx *flash, unsigned int addr, unsigned int len) ++{ ++ if (len == 4096) ++ return stm50_erase_sector(flash, addr); ++ else ++ return erase_block_82802ab(flash, addr, len); ++} +diff --git a/udelay.c b/udelay.c +index e3cf3e3..9d3bfc2 100644 +--- a/udelay.c ++++ b/udelay.c +@@ -90,7 +90,11 @@ void myusec_calibrate_delay(void) + unsigned long timeusec, resolution; + int i, tries = 0; + ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("Calibrating delay loop... "); ++#else + msg_pinfo("Calibrating delay loop... "); ++#endif + resolution = measure_os_delay_resolution(); + if (resolution) { + msg_pdbg("OS timer resolution is %lu usecs, ", resolution); +@@ -151,7 +155,7 @@ recalibrate: + } + } + } else { +- msg_perr("delay loop is unreliable, trying to continue "); ++ msg_pdbg("delay loop is unreliable, trying to continue "); + } + + /* We're interested in the actual precision. */ +@@ -166,7 +170,11 @@ recalibrate: + timeusec = measure_delay(resolution * 4); + msg_pdbg("%ld myus = %ld us, ", resolution * 4, timeusec); + ++#ifdef FORCE10_SPI_CHANGE ++ msg_pdbg("OK.\n"); ++#else + msg_pinfo("OK.\n"); ++#endif + } + + /* Not very precise sleep. */ +diff --git a/util/getrevision.sh b/util/getrevision.sh +new file mode 100755 +index 0000000..709e45f +--- /dev/null ++++ b/util/getrevision.sh +@@ -0,0 +1,311 @@ ++#!/bin/sh ++# ++# This file is part of the flashrom project. ++# ++# Copyright (C) 2005 coresystems GmbH ++# Copyright (C) 2009,2010 Carl-Daniel Hailfinger ++# Copyright (C) 2010 Chromium OS Authors ++# Copyright (C) 2013 Stefan Tauner ++# ++# 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. ++# ++# 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 ++# ++ ++EXIT_SUCCESS=0 ++EXIT_FAILURE=1 ++ ++# Make sure we don't get translated output ++export LC_ALL=C ++# nor local times or dates ++export TZ=UTC0 ++ ++# Helper functions ++# First argument is the path to inspect (usually optional; w/o it the whole repository will be considered) ++svn_has_local_changes() { ++ svn status "$1" | egrep '^ *[ADMR] *' >/dev/null ++} ++ ++git_has_local_changes() { ++ git update-index -q --refresh >/dev/null ++ ! git diff-index --quiet HEAD -- "$1" ++} ++ ++git_last_commit() { ++ git log --pretty=format:"%h" -1 -- "$1" ++} ++ ++svn_is_file_tracked() { ++ svn info "$1" >/dev/null 2>&1 ++} ++ ++git_is_file_tracked() { ++ git ls-files --error-unmatch -- "$1" >/dev/null 2>&1 ++} ++ ++is_file_tracked() { ++ svn_is_file_tracked "$1" || git_is_file_tracked "$1" ++} ++ ++# Tries to find a remote source for the changes committed locally. ++# This includes the URL of the remote repository including the last commit and a suitable branch name. ++# Takes one optional argument: the path to inspect ++git_url() { ++ last_commit=$(git_last_commit "$1") ++ # get all remote branches containing the last commit (excluding origin/HEAD and git-svn branches/tags) ++ branches=$(git branch -r --contains $last_commit | sed '/\//!d;/.*->.*/d;s/[\t ]*//') ++ if [ -z "$branches" ] ; then ++ echo "No remote branch contains a suitable commit">&2 ++ return ++ fi ++ ++ # find "nearest" branch ++ local mindiff=9000 ++ local target= ++ for branch in $branches ; do ++ curdiff=$(git rev-list --count $last_commit..$branch) ++ if [ $curdiff -ge $mindiff ] ; then ++ continue ++ fi ++ mindiff=$curdiff ++ target=$branch ++ done ++ ++ echo "$(git ls-remote --exit-code --get-url ${target%/*}) ${target#*/}" ++} ++ ++# Returns a string indicating where others can get the current source code (excluding uncommitted changes) ++# Takes one optional argument: the path to inspect ++scm_url() { ++ local url= ++ ++ # for a primitive VCS like subversion finding the URL is easy: there is only one upstream host ++ if svn_is_file_tracked "$1" ; then ++ url="$(svn info "$1" 2>/dev/null | ++ grep URL: | ++ sed 's/.*URL:[[:blank:]]*//;s/:\/\/.*@/:\/\//' | ++ grep ^.)" ++ elif git_is_file_tracked "$1" ; then ++ url="$(git_url "$1")" ++ else ++ return ${EXIT_FAILURE} ++ fi ++ ++ echo "${url}" ++} ++ ++# Retrieve timestamp since last modification. If the sources are pristine, ++# then the timestamp will match that of the SCM's most recent modification ++# date. ++timestamp() { ++ local t ++ ++ # date syntaxes are manifold: ++ # gnu date [-d input]... [+FORMAT] ++ # netbsd date [-ajnu] [-d date] [-r seconds] [+format] [[[[[[CC]yy]mm]dd]HH]MM[.SS]] ++ # freebsd date [-jnu] [-d dst] [-r seconds] [-f fmt date | [[[[[cc]yy]mm]dd]HH]MM[.ss]] [+format] [...] ++ # dragonflybsd date [-jnu] [-d dst] [-r seconds] [-f fmt date | [[[[[cc]yy]mm]dd]HH]MM[.ss]] [+format] [...] ++ # openbsd date [-aju] [-d dst] [-r seconds] [+format] [[[[[[cc]yy]mm]dd]HH]MM[.SS]] [...] ++ if svn_is_file_tracked "$2" ; then ++ if svn_has_local_changes "$2"; then ++ t=$(date -u "$1") ++ else ++ # No local changes, get date of the last log record. Subversion provides that in ++ # ISO 8601 format when using the --xml switch. The sed call extracts that ignoring any ++ # fractional parts started by a comma or a dot. ++ local last_commit_date="$(svn info --xml "$2"| \ ++ sed -n -e 's/\([^,\.]*\)\([\.,].*\)*Z<\/date>/\1Z/p')" ++ ++ case $(uname) in ++ # Most BSD dates do not support parsing date values from user input with -d but all of ++ # them support parsing the syntax with [[[[[[cc]yy]mm]dd]HH]MM[.ss]]. We have to ++ # transform the ISO8601 date first though. ++ NetBSD|OpenBSD|DragonFly|FreeBSD) ++ last_commit_date="$(echo ${last_commit_date} | \ ++ sed -n -e 's/\(....\)-\(..\)-\(..\)T\(..\):\(..\):\(..\)Z/\1\2\3\4\5\.\6/p')" ++ t=$(date -u -j "${last_commit_date}" "$1" 2>/dev/null);; ++ *) ++ t=$(date -u -d "${last_commit_date}" "$1" 2>/dev/null);; ++ esac ++ fi ++ elif git_is_file_tracked "$2" ; then ++ # are there local changes? ++ if git_has_local_changes "$2" ; then ++ t=$(date -u "${1}") ++ else ++ # No local changes, get date of the last commit ++ case $(uname) in ++ # Most BSD dates do not support parsing date values from user input with -d but all of ++ # them support parsing epoch seconds with -r. Thanks to git we can easily use that: ++ NetBSD|OpenBSD|DragonFly|FreeBSD) ++ t=$(date -u -r "$(git log --pretty=format:%ct -1 -- $2)" "$1" 2>/dev/null);; ++ *) ++ t=$(date -d "$(git log --pretty=format:%cD -1 -- $2)" -u "$1" 2>/dev/null);; ++ esac ++ fi ++ else ++ t=$(date -u "$1") ++ fi ++ ++ if [ -z "$t" ]; then ++ echo "Warning: Could not determine timestamp." 2>/dev/null ++ fi ++ echo "${t}" ++} ++ ++# Retrieve local SCM revision info. This is useful if we're working in a different SCM than upstream and/or ++# have local changes. ++local_revision() { ++ local r= ++ ++ if svn_is_file_tracked "$1" ; then ++ r=$(svn_has_local_changes "$1" && echo "dirty") ++ elif git_is_file_tracked "$1" ; then ++ r=$(git_last_commit "$1") ++ ++ local svn_base=$(git log --grep git-svn-id -1 --format='%h') ++ if [ "$svn_base" != "" ] ; then ++ local diff_to_svn=$(git rev-list --count ${svn_base}..${r}) ++ if [ "$diff_to_svn" -gt 0 ] ; then ++ r="$r-$diff_to_svn" ++ fi ++ fi ++ ++ if git_has_local_changes "$1" ; then ++ r="$r-dirty" ++ fi ++ else ++ return ${EXIT_FAILURE} ++ fi ++ ++ echo "${r}" ++} ++ ++# Get the upstream flashrom revision stored in SVN metadata. ++upstream_revision() { ++ local r= ++ ++ if svn_is_file_tracked "$1" ; then ++ r=$(svn info "$1" 2>/dev/null | \ ++ grep "Last Changed Rev:" | \ ++ sed -e "s/^Last Changed Rev: *//" -e "s/\([0-9]*\).*/r\1/" | \ ++ grep "r[0-9]") ++ elif git_is_file_tracked "$1" ; then ++ # If this is a "native" git-svn clone we could use git svn log: ++ # git svn log --oneline -1 | sed 's/^r//;s/[[:blank:]].*//' or even git svn find-rev ++ # but it is easier to just grep for the git-svn-id unconditionally ++ r=$(git log --grep git-svn-id -1 -- "$1" | \ ++ grep git-svn-id | \ ++ sed 's/.*@/r/;s/[[:blank:]].*//') ++ fi ++ ++ if [ -z "$r" ]; then ++ r="unknown" # default to unknown ++ fi ++ echo "${r}" ++} ++ ++show_help() { ++ echo "Usage: ++ ${0} [path] ++ ++Commands ++ -h or --help ++ this message ++ -l or --local ++ local revision information including an indicator for uncommitted changes ++ -u or --upstream ++ upstream revision ++ -U or --url ++ URL associated with the latest commit ++ -d or --date ++ date of most recent modification ++ -t or --timestamp ++ timestamp of most recent modification ++" ++ return ++} ++ ++check_action() { ++ if [ -n "$action" ]; then ++ echo "Error: Multiple actions given.">&2 ++ exit ${EXIT_FAILURE} ++ fi ++} ++ ++main() { ++ local query_path= ++ local action= ++ ++ # The is the main loop ++ while [ $# -gt 0 ]; ++ do ++ case ${1} in ++ -h|--help) ++ action=show_help; ++ shift;; ++ -l|--local) ++ check_action $1 ++ action=local_revision ++ shift;; ++ -u|--upstream) ++ check_action $1 ++ action=upstream_revision ++ shift;; ++ -U|--url) ++ check_action $1 ++ action=scm_url ++ shift;; ++ -d|--date) ++ check_action $1 ++ action="timestamp +%Y-%m-%d" # refrain from suffixing 'Z' to indicate it's UTC ++ shift;; ++ -t|--timestamp) ++ check_action $1 ++ action="timestamp +%Y-%m-%dT%H:%M:%SZ" # There is only one valid time format! ISO 8601 ++ shift;; ++ -*) ++ show_help; ++ echo "Error: Invalid option: ${1}" ++ exit ${EXIT_FAILURE};; ++ *) ++ if [ -z "$query_path" ] ; then ++ if [ ! -e "$1" ] ; then ++ echo "Error: Path \"${1}\" does not exist.">&2 ++ exit ${EXIT_FAILURE} ++ fi ++ query_path=$1 ++ else ++ echo "Warning: Ignoring over-abundant paramter: \"${1}\"">&2 ++ fi ++ shift;; ++ esac; ++ done ++ ++ # default to current directory (usually equals the whole repository) ++ if [ -z "$query_path" ] ; then ++ query_path=. ++ fi ++ if ! is_file_tracked "$query_path" ; then ++ echo "Warning: Path \"${query_path}\" is not under version control.">&2 ++ fi ++ if [ -z "$action" ] ; then ++ show_help ++ echo "Error: No actions specified" ++ exit ${EXIT_FAILURE} ++ fi ++ ++ $action "$query_path" ++} ++ ++main $@ +diff --git a/util/ich_descriptors_tool/ich_descriptors_tool.c b/util/ich_descriptors_tool/ich_descriptors_tool.c +index c359913..dd35860 100644 +--- a/util/ich_descriptors_tool/ich_descriptors_tool.c ++++ b/util/ich_descriptors_tool/ich_descriptors_tool.c +@@ -77,12 +77,13 @@ static void dump_file(const char *prefix, const uint32_t *dump, unsigned int len + printf("Dumping %u bytes of the %s region from 0x%08x-0x%08x to %s... ", + file_len, region_names[i], base, limit, fn); + int fh = open(fn, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); +- free(fn); + if (fh < 0) { + fprintf(stderr, + "ERROR: couldn't open(%s): %s\n", fn, strerror(errno)); ++ free(fn); + exit(1); + } ++ free(fn); + + ret = write(fh, &dump[base >> 2], file_len); + if (ret != file_len) { +@@ -120,6 +121,7 @@ static void usage(char *argv[], char *error) + "\t- \"5\" or \"ibex\" for Intel's 5 series chipsets,\n" + "\t- \"6\" or \"cougar\" for Intel's 6 series chipsets,\n" + "\t- \"7\" or \"panther\" for Intel's 7 series chipsets.\n" ++"\t- \"avoton\",\n" + "If '-d' is specified some regions such as the BIOS image as seen by the CPU or\n" + "the GbE blob that is required to initialize the GbE are also dumped to files.\n", + argv[0], argv[0]); +@@ -197,6 +199,10 @@ int main(int argc, char *argv[]) + else if ((strcmp(csn, "7") == 0) || + (strcmp(csn, "panther") == 0)) + cs = CHIPSET_7_SERIES_PANTHER_POINT; ++#ifdef DELL_AVOTON_SUPPORT ++ else if (strcmp(csn, "avoton") == 0) ++ cs = CHIPSET_AVOTON; ++#endif + } + + ret = read_ich_descriptors_from_dump(buf, len, &desc); +diff --git a/util/z60_flashrom.rules b/util/z60_flashrom.rules +index 8456a04..948563c 100644 +--- a/util/z60_flashrom.rules ++++ b/util/z60_flashrom.rules +@@ -80,4 +80,8 @@ ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="664", GROUP="plugdev" + # http://www.diygadget.com/tiao-usb-multi-protocol-adapter-jtag-spi-i2c-serial.html + ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="664", GROUP="plugdev" + ++# TIAO/DIYGADGET USB Multi-Protocol Adapter (TUMPA) Lite ++# http://www.tiaowiki.com/w/TIAO_USB_Multi_Protocol_Adapter_Lite_User's_Manual ++ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="664", GROUP="plugdev" ++ + LABEL="flashrom_rules_end" +-- +2.7.4 + diff --git a/platform/broadcom/sonic-platform-modules-dell/tools/flashrom.sh b/platform/broadcom/sonic-platform-modules-dell/tools/flashrom.sh new file mode 100755 index 000000000000..c3af65fd6d84 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/tools/flashrom.sh @@ -0,0 +1,10 @@ +#!/bin/bash +export DELL_TOOLS_DIR="platform/broadcom/sonic-platform-modules-dell/tools" + +cd $DELL_TOOLS_DIR +rm -rf $DELL_TOOLS_DIR/flashrom +git clone https://github.com/flashrom/flashrom.git +cd flashrom +git checkout tags/0.9.7 +git apply ../0002-Flashrom-support-for-Intel-Rangeley-and-Denverton-CP.patch +make diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/cfg/z9100-modules.conf b/platform/broadcom/sonic-platform-modules-dell/z9100/cfg/z9100-modules.conf new file mode 100644 index 000000000000..66f002a5fc94 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/cfg/z9100-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-dell/z9100/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/z9100/modules/Makefile new file mode 100644 index 000000000000..24ef231b2a50 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_mailbox.o dell_z9100_cpld.o dell_ich.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/modules/dell_z9100_cpld.c b/platform/broadcom/sonic-platform-modules-dell/z9100/modules/dell_z9100_cpld.c new file mode 100644 index 000000000000..6198771ab45a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/modules/dell_z9100_cpld.c @@ -0,0 +1,491 @@ + + +/* Includes only 3 things. + * a. QSFP Reset control + * b. LP Mode + * c. Module Presence + */ +#include // included for all kernel modules +#include // included for KERN_INFO +#include // included for __init and __exit macros +#include +#include +#include +#include + + +//iom cpld slave address +#define IOM_CPLD_SLAVE_ADD 0x3e + +//iom cpld ver register +#define IOM_CPLD_SLAVE_VER 0x00 + +//qsfp reset cntrl reg on each iom +#define QSFP_RST_CRTL_REG0 0x10 +#define QSFP_RST_CRTL_REG1 0x11 + +//qsfp lp mode reg on each iom +#define QSFP_LPMODE_REG0 0x12 +#define QSFP_LPMODE_REG1 0x13 + +//qsfp mod presence reg on each iom +#define QSFP_MOD_PRS_REG0 0x16 +#define QSFP_MOD_PRS_REG1 0x17 + +//qsfp interrupt registers +#define QSFP_INT_STA_REG0 0x14 +#define QSFP_INT_STA_REG1 0x15 +#define QSFP_ABS_STA_REG0 0x16 +#define QSFP_ABS_STA_REG1 0x17 +#define QSFP_TRIG_MOD 0x20 +#define QSFP_INT_COMBINE 0x21 +#define QSFP_INT0 0x22 +#define QSFP_INT1 0x23 +#define QSFP_ABS_INT0 0x24 +#define QSFP_ABS_INT1 0x25 +#define QSFP_INT_MASK0 0x26 +#define QSFP_INT_MASK1 0x27 +#define QSFP_ABS_MASK0 0x28 +#define QSFP_ABS_MASK1 0x29 + +struct cpld_data { + struct i2c_client *client; + struct mutex update_lock; +}; + + +static void dell_z9100_iom_cpld_add_client(struct i2c_client *client) +{ + struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + + if (!data) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); +} + +static void dell_z9100_iom_cpld_remove_client(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + kfree(data); + return ; +} + +int dell_z9100_iom_cpld_read(struct cpld_data *data, u8 reg) +{ + int ret = -EPERM; + u8 high_reg =0x00; + + mutex_lock(&data->update_lock); + + ret = i2c_smbus_write_byte_data(data->client, high_reg,reg); + ret = i2c_smbus_read_byte(data->client); + mutex_unlock(&data->update_lock); + + return ret; +} + +int dell_z9100_iom_cpld_write(struct cpld_data *data,u8 reg, u8 value) +{ + int ret = -EIO; + u16 devdata=0; + u8 high_reg =0x00; + + mutex_lock(&data->update_lock); + devdata = (value << 8) | reg; + i2c_smbus_write_word_data(data->client,high_reg,devdata); + mutex_unlock(&data->update_lock); + + return ret; +} +static ssize_t get_cpldver(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,IOM_CPLD_SLAVE_VER); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"IOM CPLD Version:0x%02x\n",devdata); +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_MOD_PRS_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_MOD_PRS_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_LPMODE_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_LPMODE_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_RST_CRTL_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_RST_CRTL_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_z9100_iom_cpld_write(data,QSFP_LPMODE_REG0,(u8)(devdata & 0xff)); + dell_z9100_iom_cpld_write(data,QSFP_LPMODE_REG1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_z9100_iom_cpld_write(data,QSFP_RST_CRTL_REG0,(u8)(devdata & 0xff)); + dell_z9100_iom_cpld_write(data,QSFP_RST_CRTL_REG1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t get_int_sta(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT_STA_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT_STA_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_abs_sta(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_STA_REG0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_STA_REG1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_trig_mod(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_TRIG_MOD); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"0x%02x\n",devdata); +} + +static ssize_t set_trig_mod(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_z9100_iom_cpld_write(data,QSFP_TRIG_MOD,(u8)(devdata & 0xff)); + + return count; +} + +static ssize_t get_int_combine(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT_COMBINE); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u8)ret & 0xff; + return sprintf(buf,"0x%02x\n",devdata); +} + +static ssize_t get_int(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_abs_int(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_INT0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_INT1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t get_int_mask(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT_MASK0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_INT_MASK1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_int_mask(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_z9100_iom_cpld_write(data,QSFP_INT_MASK0,(u8)(devdata & 0xff)); + dell_z9100_iom_cpld_write(data,QSFP_INT_MASK1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static ssize_t get_abs_mask(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u16 devdata=0; + struct cpld_data *data = dev_get_drvdata(dev); + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_MASK0); + if(ret < 0) + return sprintf(buf, "read error"); + devdata = (u16)ret & 0xff; + + ret = dell_z9100_iom_cpld_read(data,QSFP_ABS_MASK1); + if(ret < 0) + return sprintf(buf, "read error"); + devdata |= (u16)(ret & 0xff) << 8; + + return sprintf(buf,"0x%04x\n",devdata); +} + +static ssize_t set_abs_mask(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long devdata; + int err; + struct cpld_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 16, &devdata); + if (err) + return err; + + dell_z9100_iom_cpld_write(data,QSFP_ABS_MASK0,(u8)(devdata & 0xff)); + dell_z9100_iom_cpld_write(data,QSFP_ABS_MASK1,(u8)((devdata >> 8) & 0xff)); + + return count; +} + +static DEVICE_ATTR(iom_cpld_vers,S_IRUGO,get_cpldver, NULL); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO,get_modprs, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR,get_lpmode,set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR,get_reset, set_reset); +static DEVICE_ATTR(qsfp_int_sta, S_IRUGO, get_int_sta, NULL); +static DEVICE_ATTR(qsfp_abs_sta, S_IRUGO, get_abs_sta, NULL); +static DEVICE_ATTR(qsfp_trig_mod, S_IRUGO | S_IWUSR, get_trig_mod, set_trig_mod); +static DEVICE_ATTR(qsfp_int_combine, S_IRUGO, get_int_combine, NULL); +static DEVICE_ATTR(qsfp_int, S_IRUGO, get_int, NULL); +static DEVICE_ATTR(qsfp_abs_int, S_IRUGO, get_abs_int, NULL); +static DEVICE_ATTR(qsfp_int_mask, S_IRUGO | S_IWUSR, get_int_mask, set_int_mask); +static DEVICE_ATTR(qsfp_abs_mask, S_IRUGO | S_IWUSR, get_abs_mask, set_abs_mask); + +static struct attribute *i2c_cpld_attrs[] = { + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_iom_cpld_vers.attr, + &dev_attr_qsfp_int_sta.attr, + &dev_attr_qsfp_abs_sta.attr, + &dev_attr_qsfp_trig_mod.attr, + &dev_attr_qsfp_int_combine.attr, + &dev_attr_qsfp_int.attr, + &dev_attr_qsfp_abs_int.attr, + &dev_attr_qsfp_int_mask.attr, + &dev_attr_qsfp_abs_mask.attr, + NULL, +}; + +static struct attribute_group i2c_cpld_attr_grp = { + .attrs = i2c_cpld_attrs, +}; + +static int dell_z9100_iom_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + dev_info(&client->dev, "chip found- New\n"); + dell_z9100_iom_cpld_add_client(client); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &i2c_cpld_attr_grp); + if (status) { + printk(KERN_INFO "Cannot create sysfs\n"); + } + return 0; + +exit: + return status; +} + +static int dell_z9100_iom_cpld_remove(struct i2c_client *client) +{ + dell_z9100_iom_cpld_remove_client(client); + return 0; +} + + +static const struct i2c_device_id dell_z9100_iom_cpld_id[] = { + { "dell_z9100_iom_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dell_z9100_iom_cpld_id); + +static struct i2c_driver dell_z9100_iom_cpld_driver = { + .driver = { + .name = "dell_z9100_iom_cpld", + }, + .probe = dell_z9100_iom_cpld_probe, + .remove = dell_z9100_iom_cpld_remove, + .id_table = dell_z9100_iom_cpld_id, +}; + + + +static int __init dell_z9100_iom_cpld_init(void) +{ + return i2c_add_driver(&dell_z9100_iom_cpld_driver); +} + +static void __exit dell_z9100_iom_cpld_exit(void) +{ + i2c_del_driver(&dell_z9100_iom_cpld_driver); +} + +MODULE_AUTHOR("Srideep Devireddy "); +MODULE_DESCRIPTION("dell_z9100_iom_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(dell_z9100_iom_cpld_init); +module_exit(dell_z9100_iom_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/check_qsfp.sh b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/check_qsfp.sh new file mode 100755 index 000000000000..38f62013e46b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/check_qsfp.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +#Usage: +# check_qsfp.sh qsfp10 +# check_qsfp.sh sffp2 + +# There are 34 optics ports. 32 QSFP28, 2 SFP+ +# QSFP28 is orgainized is 3 banks +# CPLD-2 QSFP-1-12 +# CPLD-3 QSFP-13-22 +# CPLD-4 QSFP-23-32 +# SFF+ 2 ports on CPLD-4 + +optics=$1 +cpld_addr="003e" + +if [ `expr match $optics qsfp` -ne 0 ] +then + type=qsfp + id=${optics:4} + + if [ $id -le 0 -o $id -gt 32 ] + then + echo "Invalid QSFP id" + return -1 + fi + if [ $id -le 12 ] + then + #cpld=2 + cpld_bus=15 + elif [ $id -le 22 ] + then + #cpld=3 + cpld_bus=16 + else + #cpld=4 + cpld_bus=17 + fi + + if [ $id -le 8 ] + then + let qsfp_bus=42+$id + elif [ $id -le 16 ] + then + let qsfp_bus=34+${id}-8 + elif [ $id -le 24 ] + then + let qsfp_bus=26+${id}-16 + else + let qsfp_bus=18+${id}-24 + fi +else + type=sff + id=${optics:3} + cpld=4 +fi + +echo "Preence:`cat /sys/class/i2c-dev/i2c-${cpld_bus}/device/${cpld_bus}-${cpld_addr}/qsfp_modprs`" +echo "Hexdump:" +cat /sys/bus/i2c/devices/${qsfp_bus}-0050/eeprom | hexdump -C diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/override.conf b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/override.conf new file mode 100644 index 000000000000..2b3b32546615 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/override.conf @@ -0,0 +1,3 @@ +[Service] +ExecStart= +ExecStart=/usr/share/sonic/device/x86_64-dell_z9100_c2538-r0/platform_reboot_override diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_reboot_override b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_reboot_override new file mode 100755 index 000000000000..0cc43644954d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_reboot_override @@ -0,0 +1,23 @@ +#!/usr/bin/python3 +import os +import struct + +PORT_RES = '/dev/port' + + +def portio_reg_write(resource, offset, val): + fd = os.open(resource, os.O_RDWR) + if(fd < 0): + print('file open failed %s" % resource') + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print('lseek failed on %s' % resource) + return + ret = os.write(fd, struct.pack('B', val)) + if(ret != 1): + print('write failed %d' % ret) + return + os.close(fd) + +if __name__ == "__main__": + portio_reg_write(PORT_RES, 0xcf9, 0xe) 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 new file mode 100755 index 000000000000..0caa533c3fa6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/platform_sensors.py @@ -0,0 +1,324 @@ +#!/usr/bin/python3 +# +# On Z9100, the Platform Management Controller runs the +# thermal algorithm. It provides a mailbox for the Host +# to query relevant thermals. The dell_mailbox module +# provides the sysfs support for the following objects: +# * onboard temperature sensors +# * FAN trays +# * PSU + +import os +import sys +import logging + +Z9100_MAX_FAN_TRAYS = 5 +Z9100_MAX_PSUS = 2 +S6100_MAX_IOMS = 4 + +HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" +HWMON_NODE = os.listdir(HWMON_DIR)[0] +MAILBOX_DIR = HWMON_DIR + HWMON_NODE + +# Get a mailbox register + + +def get_pmc_register(reg_name): + retval = 'ERR' + mb_reg_file = MAILBOX_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + print(mb_reg_file, 'not found !') + return retval + + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", mb_reg_file, "file !") + + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + +logging.basicConfig(level=logging.DEBUG) + +if (os.path.isdir(MAILBOX_DIR)): + print('dell-z9100-lpc') + print('Adapter: Z9100 Platform Management Controller') +else: + logging.error('Z9100 Platform Management Controller module not loaded !') + # sys.exit(0) + +# Print the information for temperature sensors + + +def print_temperature_sensors(): + print("\nOnboard Temperature Sensors:") + print(' CPU: ', + int(get_pmc_register('temp1_input'))/1000, 'C') + print(' BCM56960 (PSU side): ', + int(get_pmc_register('temp2_input'))/1000, 'C') + print(' System Outlet 1 (switch board): ', + int(get_pmc_register('temp3_input'))/1000, 'C') + print(' BCM56960 (IO side): ', + int(get_pmc_register('temp4_input'))/1000, 'C') + print(' System Outlet 2 (CPU board): ', + int(get_pmc_register('temp9_input'))/1000, 'C') + print(' System Inlet Left (IO side): ', + int(get_pmc_register('temp6_input'))/1000, 'C') + +print_temperature_sensors() + + +# Print the information for voltage sensors + + +def print_voltage_sensors(): + print("\nOnboard Voltage Sensors:") + + print(' CPU XP3R3V_EARLY ', + float(get_pmc_register('in1_input'))/1000, 'V') + print('\n CPU XP5R0V_CP ', + float(get_pmc_register('in2_input'))/1000, 'V') + print(' CPU XP3R3V_STD ', + float(get_pmc_register('in3_input'))/1000, 'V') + print(' CPU XP3R3V_CP ', + float(get_pmc_register('in4_input'))/1000, 'V') + print(' CPU XP0R75V_VTT_A ', + float(get_pmc_register('in5_input'))/1000, 'V') + print(' CPU XPPR75V_VTT_B ', + float(get_pmc_register('in6_input'))/1000, 'V') + print(' CPU XP1R07V_CPU ', + float(get_pmc_register('in7_input'))/1000, 'V') + print(' CPU XP1R0V_CPU ', + float(get_pmc_register('in8_input'))/1000, 'V') + print(' CPU XP12R0V ', + float(get_pmc_register('in9_input'))/1000, 'V') + print(' CPU VDDR_CPU_2 ', + float(get_pmc_register('in10_input'))/1000, 'V') + print(' CPU VDDR_CPU_1 ', + float(get_pmc_register('in11_input'))/1000, 'V') + print(' CPU XP1R5V_CLK ', + float(get_pmc_register('in12_input'))/1000, 'V') + print(' CPU XP1R8V_CPU ', + float(get_pmc_register('in13_input'))/1000, 'V') + print(' CPU XP1R0V_CPU_VNN ', + float(get_pmc_register('in14_input'))/1000, 'V') + print(' CPU XP1R0V_CPU_VCC ', + float(get_pmc_register('in15_input'))/1000, 'V') + print(' CPU XP1R5V_EARLY ', + float(get_pmc_register('in16_input'))/1000, 'V') + print(' SW XP3R3V_MON ', + float(get_pmc_register('in17_input'))/1000, 'V') + print(' SW XP1R8V_MON ', + float(get_pmc_register('in19_input'))/1000, 'V') + print(' SW XP1R2V_MON ', + float(get_pmc_register('in20_input'))/1000, 'V') + print(' SW XP1R0V_SW_MON ', + float(get_pmc_register('in21_input'))/1000, 'V') + print(' SW XP1R0V_ROV_SW_MON ', + float(get_pmc_register('in22_input'))/1000, 'V') + print(' SW XR1R0V_BCM84752_MON ', + float(get_pmc_register('in23_input'))/1000, 'V') + print(' SW XP5V_MB_MON ', + float(get_pmc_register('in24_input'))/1000, 'V') + print(' SW XP1R8V_FPGA_MON ', + float(get_pmc_register('in25_input'))/1000, 'V') + print(' SW XP3R3V_FPGA_MON ', + float(get_pmc_register('in26_input'))/1000, 'V') + print(' SW XP3R3V_EARLY_MON ', + float(get_pmc_register('in27_input'))/1000, 'V') + print(' SW XP1R0V_ ', + float(get_pmc_register('curr21_input'))/10000, 'A') + print(' SW XP1R0V_ROV ', + float(get_pmc_register('curr22_input'))/10000, 'A') + + +print_voltage_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(tray): + + Fan_Status = ['Normal', 'Abnormal'] + Airflow_Direction = ['B2F', 'F2B'] + + print(' Fan Tray ' + str(tray) + ':') + + if (tray == 1): + fan1_speed = int(get_pmc_register('fan1_input')) + fan2_speed = int(get_pmc_register('fan2_input')) + air_flow_reg = int(get_pmc_register('fan1_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + fan2_status = 0 if fan2_speed >= 1000 else 1 + + print(' Fan1 Speed: ', fan1_speed, 'RPM') + print(' Fan2 Speed: ', fan2_speed, 'RPM') + print(' Fan1 State: ', Fan_Status[fan1_status]) + print(' Fan2 State: ', Fan_Status[fan2_status]) + print(' Air Flow: ', Airflow_Direction[air_flow_reg]) + elif (tray == 2): + fan1_speed = int(get_pmc_register('fan3_input')) + fan2_speed = int(get_pmc_register('fan4_input')) + air_flow_reg = int(get_pmc_register('fan3_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + fan2_status = 0 if fan2_speed >= 1000 else 1 + + print(' Fan1 Speed: ', fan1_speed, 'RPM') + print(' Fan2 Speed: ', fan2_speed, 'RPM') + print(' Fan1 State: ', Fan_Status[fan1_status]) + print(' Fan2 State: ', Fan_Status[fan2_status]) + print(' Air Flow: ', Airflow_Direction[air_flow_reg]) + elif (tray == 3): + fan1_speed = int(get_pmc_register('fan5_input')) + fan2_speed = int(get_pmc_register('fan6_input')) + air_flow_reg = int(get_pmc_register('fan5_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + fan2_status = 0 if fan2_speed >= 1000 else 1 + + print(' Fan1 Speed: ', fan1_speed, 'RPM') + print(' Fan2 Speed: ', fan2_speed, 'RPM') + print(' Fan1 State: ', Fan_Status[fan1_status]) + print(' Fan2 State: ', Fan_Status[fan2_status]) + print(' Air Flow: ', Airflow_Direction[air_flow_reg]) + elif (tray == 4): + fan1_speed = int(get_pmc_register('fan7_input')) + fan2_speed = int(get_pmc_register('fan8_input')) + air_flow_reg = int(get_pmc_register('fan7_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + fan2_status = 0 if fan2_speed >= 1000 else 1 + + print(' Fan1 Speed: ', fan1_speed, 'RPM') + print(' Fan2 Speed: ', fan2_speed, 'RPM') + print(' Fan1 State: ', Fan_Status[fan1_status]) + print(' Fan2 State: ', Fan_Status[fan2_status]) + print(' Air Flow: ', Airflow_Direction[air_flow_reg]) + elif (tray == 5): + fan1_speed = int(get_pmc_register('fan9_input')) + fan2_speed = int(get_pmc_register('fan10_input')) + air_flow_reg = int(get_pmc_register('fan9_airflow'), 16) + fan1_status = 0 if fan1_speed >= 1000 else 1 + fan2_status = 0 if fan2_speed >= 1000 else 1 + + print(' Fan1 Speed: ', fan1_speed, 'RPM') + print(' Fan2 Speed: ', fan2_speed, 'RPM') + print(' Fan1 State: ', Fan_Status[fan1_status]) + print(' Fan2 State: ', Fan_Status[fan2_status]) + print(' Air Flow: ', Airflow_Direction[air_flow_reg]) + + +print('\nFan Trays:') +fan_tray_presence = get_pmc_register('fan_tray_presence') + +if (fan_tray_presence != 'ERR'): + fan_tray_presence = int(fan_tray_presence, 16) + + for tray in range(0, Z9100_MAX_FAN_TRAYS): + if (fan_tray_presence & (1 << tray)): + print_fan_tray(tray + 1) + else: + print('\n Fan Tray ' + str(tray + 1) + ': Not present') +else: + logging.error('Unable to read FAN presence') + +# Print the information for PSU1, PSU2 + + +def print_psu(psu): + Psu_Type = ['Normal', 'Mismatch'] + Psu_Input_Type = ['AC', 'DC'] + PSU_STATUS_TYPE_BIT = 4 + PSU_STATUS_INPUT_TYPE_BIT = 1 + PSU_FAN_PRESENT_BIT = 2 + PSU_FAN_STATUS_BIT = 1 + PSU_FAN_AIR_FLOW_BIT = 0 + Psu_Fan_Presence = ['Present', 'Absent'] + Psu_Fan_Status = ['Normal', 'Abnormal'] + Psu_Fan_Airflow = ['B2F', 'F2B'] + + print(' PSU ' + str(psu) + ':') + if (psu == 1): + psu_status = int(get_pmc_register('psu1_presence'), 16) + else: + psu_status = int(get_pmc_register('psu2_presence'), 16) + + psu_input_type = (psu_status & (1 << PSU_STATUS_INPUT_TYPE_BIT)) >>\ + PSU_STATUS_INPUT_TYPE_BIT + psu_type = (psu_status & (1 << PSU_STATUS_TYPE_BIT)) >>\ + PSU_STATUS_TYPE_BIT + + print(' Input: ', Psu_Input_Type[psu_input_type]) + print(' Type: ', Psu_Type[psu_type]) + + # PSU FAN details + if (psu == 1): + print(' FAN Speed: ', get_pmc_register('fan11_input'), 'RPM') + psu_fan_airflow = int(get_pmc_register('fan11_airflow')) + psu_fan_status = int(get_pmc_register('fan11_alarm')) + 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')) / 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): + psu_fan_temp = int(get_pmc_register('temp14_input'))/1000 + else: + print(' FAN Speed: ', get_pmc_register('fan12_input'), 'RPM') + psu_fan_airflow = int(get_pmc_register('fan12_airflow')) + psu_fan_status = int(get_pmc_register('fan12_alarm')) + 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')) / 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): + psu_fan_temp = int(get_pmc_register('temp15_input'))/1000 + + print(' FAN: ', Psu_Fan_Presence[psu_fan_present]) + print(' FAN Status: ', Psu_Fan_Status[psu_fan_status]) + print(' FAN AIRFLOW: ', Psu_Fan_Airflow[psu_fan_airflow]) + + # PSU input & output monitors + print(' Input Voltage: %6.2f' % (input_voltage), 'V') + + print(' Output Voltage: %6.2f' % (output_voltage), 'V') + + print(' Input Current: %6.2f' % (input_current), 'A') + + print(' Output Current: %6.2f' % (output_current), 'A') + + print(' Input Power: %6.2f' % (input_power), 'W') + + print(' Output Power: %6.2f' % (output_power), 'W') + + # PSU firmware gives spurious temperature reading without input power + if (input_power != 0): + print(' Temperature: ', psu_fan_temp, 'C') + else: + print(' Temperature: ', 'NA') + +print('\nPSUs:') +for psu in range(1, Z9100_MAX_PSUS + 1): + + if (psu == 1): + psu_status = get_pmc_register('psu1_presence') + else: + psu_status = get_pmc_register('psu2_presence') + + if (psu_status != 'ERR'): + psu_status = int(psu_status, 16) + + if (~psu_status & 0b1): + print_psu(psu) + else: + print('\n PSU ', psu, 'Not present') + else: + logging.error('Unable to check PSU presence') + +print('\n Total Power: ', get_pmc_register('current_total_power'), 'W') diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/sensors new file mode 100755 index 000000000000..958cbdcb7bef --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/sensors @@ -0,0 +1,3 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/z9100_platform.sh b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/z9100_platform.sh new file mode 100755 index 000000000000..8d564c6c2cd5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/scripts/z9100_platform.sh @@ -0,0 +1,268 @@ +#!/bin/bash + +#platform init script for Dell Z9100 + +source dell_i2c_utils.sh + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [[ $found -eq 0 ]] && echo "cannot find iSMT" && exit 1 +} + +# Attach/Detach CPU board mux @ 0x70 +cpu_board_mux() { + case $1 in + "new_device") i2c_mux_create pca9547 0x70 $devnum 2 + ;; + "delete_device") i2c_mux_delete 0x70 $devnum + ;; + *) echo "z9100_platform: cpu_board_mux: invalid command !" + ;; + esac +} + +# Attach/Detach switch board MUX to IOM CPLDs @ 0x71 +switch_board_mux() { + case $1 in + "new_device") i2c_mux_create pca9548 0x71 4 10 + ;; + "delete_device") i2c_mux_delete 0x71 4 + ;; + *) echo "z9100_platform: switch_board_mux : invalid command !" + ;; + esac +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + case $1 in + "new_device") i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-2/$1" + ;; + "delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-2/$1" + ;; + *) echo "z9100_platform: sys_eeprom : invalid command !" + ;; + esac +} + +#Attach/Detach cpld devices to drivers for each iom +switch_board_cpld() { + case $1 in + "new_device") + for ((i=14;i<=17;i++)); + do + i2c_config "echo dell_z9100_iom_cpld 0x3e > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + "delete_device") + for ((i=14;i<=17;i++)); + do + i2c_config "echo 0x3e > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + *) echo "z9100_platform: switch_board_cpld : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs +switch_board_qsfp_mux() { + case $1 in + "new_device") + # The mux for the QSFPs spawn {18..25}, {26..33}, {34..41} and {42..49} + # starting at chennel 18 and 8 channels per mux. + channel_first=18 + for ((i=9;i>=6;i--)); + do + # 0x71 mux on the IOM 1 + mux_index=$(expr $i - 5) + echo "Attaching PCA9548 $mux_index" + i2c_mux_create pca9548 0x71 $i $channel_first + channel_first=$(expr $channel_first + 8) + done + ;; + "delete_device") + for ((i=9;i>=6;i--)); + do + # 0x71 mux on the IOM 1 + mux_index=$(expr $i - 5) + echo "Detaching PCA9548 $mux_index" + i2c_mux_delete 0x71 $i + done + ;; + *) echo "z9100_platform: switch_board_qsfp_mux: invalid command !" + ;; + esac +} + +#Attach/Detach the SFP modules on PCA9548_2 +switch_board_sfp() { + case $1 in + "new_device") i2c_config "echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-11/$1" + i2c_config "echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-12/$1" + ;; + "delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-11/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-12/$1" + ;; + *) echo "z9100_platform: switch_board_sfp: invalid command !" + ;; + esac +} + +# Attach/Detach 32 instances of EEPROM driver QSFP ports on IO module 1 +#eeprom can dump data using below command +switch_board_qsfp() { + case $1 in + "new_device") + for ((i=18;i<=49;i++)); + do + i2c_config "echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + "delete_device") + for ((i=18;i<=49;i++)); + do + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1" + done + ;; + + *) echo "z9100_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +# Enable/Disable xcvr presence interrupts +xcvr_presence_interrupts() { + case $1 in + "enable") + for ((i=14;i<=16;i++)); + do + echo 0x0 > /sys/class/i2c-adapter/i2c-$i/$i-003e/qsfp_abs_mask + done + ;; + "disable") + for ((i=14;i<=16;i++)); + do + echo 0xffff > /sys/class/i2c-adapter/i2c-$i/$i-003e/qsfp_abs_mask + done + ;; + *) echo "z9100_platform: xcvr_presence_interrupts: invalid command !" + ;; + esac +} + +# Reset the mux tree +reset_muxes() { + # Reset the IOM muxes and the switch card mux + io_rd_wr.py --set --val 0xe0 --offset 0x110 + io_rd_wr.py --set --val 0xff --offset 0x110 + + # Reset the CPU Card PCA9547 + io_rd_wr.py --set --val 0xfd --offset 0x20b + io_rd_wr.py --set --val 0xff --offset 0x20b +} + +# Copy led_proc_init.soc file according to the HWSKU +init_switch_port_led() { + T0="Force10-Z9100-C8D48" + T1="Force10-Z9100-C32" + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + hwsku=$(cat /etc/sonic/config_db.json | grep -A2 "DEVICE_METADATA" | grep "hwsku" | cut -d ":" -f2 | sed 's/"//g' | sed 's/,//g'| xargs ) + + if [ -z "$hwsku" ]; then + #Check minigraph for hwsku + cat /etc/sonic/minigraph.xml | grep $T1 > /dev/null + if [ $? -eq 0 ]; then + hwsku=$T1 + else + hwsku=$T0 + fi + fi + + led_proc_init="$device/$platform/$hwsku/led_proc_init.soc" + + # Remove old HWSKU LED file.. + rm -rf $device/$platform/led_proc_init.soc + + if [ -e $led_proc_init ] && [ ! -e $device/$platform/led_proc_init.soc ]; then + cp $led_proc_init $device/$platform + fi + +} + +install_python_api_package() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip install $device/$platform/sonic_platform-1.0-py2-none-any.whl) + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) +} + +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) + fi + + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -eq 0 ]; then + rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null) + fi +} + +init_devnum + +if [[ "$1" == "init" ]]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe dell_ich + modprobe dell_mailbox + modprobe dell_z9100_cpld + + cpu_board_mux "new_device" + switch_board_mux "new_device" + sys_eeprom "new_device" + switch_board_cpld "new_device" + switch_board_qsfp_mux "new_device" + switch_board_sfp "new_device" + switch_board_qsfp "new_device" + xcvr_presence_interrupts "enable" + + #Copy led_proc_init.soc + init_switch_port_led + install_python_api_package + + value=0x0 + echo $value > /sys/class/i2c-adapter/i2c-14/14-003e/qsfp_lpmode + echo $value > /sys/class/i2c-adapter/i2c-15/15-003e/qsfp_lpmode + echo $value > /sys/class/i2c-adapter/i2c-16/16-003e/qsfp_lpmode + +elif [[ "$1" == "deinit" ]]; then + xcvr_presence_interrupts "disable" + switch_board_sfp "delete_device" + switch_board_cpld "delete_device" + switch_board_mux "delete_device" + sys_eeprom "delete_device" + switch_board_qsfp "delete_device" + switch_board_qsfp_mux "delete_device" + cpu_board_mux "delete_device" + + modprobe -r dell_z9100_cpld + modprobe -r dell_mailbox + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev + modprobe -r dell_ich + remove_python_api_package +else + echo "z9100_platform : Invalid option !" +fi diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/setup.py b/platform/broadcom/sonic-platform-modules-dell/z9100/setup.py new file mode 120000 index 000000000000..4f6de9941d96 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/setup.py @@ -0,0 +1 @@ +../s6100/setup.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/__init__.py new file mode 100755 index 000000000000..8b4def6e7884 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis", "fan", "fan_drawer", "psu", "sfp", "thermal"] +from sonic_platform import * + 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 new file mode 100755 index 000000000000..82f8ae60f9d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py @@ -0,0 +1,401 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC Z9100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import select + import sys + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.psu import Psu + from sonic_platform.thermal import Thermal + from sonic_platform.component import Component + from sonic_platform.eeprom import Eeprom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +MAX_Z9100_FANTRAY = 5 +MAX_Z9100_PSU = 2 +MAX_Z9100_THERMAL = 8 +MAX_Z9100_COMPONENT = 6 + + +class Chassis(ChassisBase): + """ + DELLEMC Platform-specific Chassis class + """ + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + EEPROM_I2C_MAPPING = { + 0: [9, 18], 1: [9, 19], 2: [9, 20], 3: [9, 21], + 4: [9, 22], 5: [9, 23], 6: [9, 24], 7: [9, 25], + 8: [8, 26], 9: [8, 27], 10: [8, 28], 11: [8, 29], + 12: [8, 31], 13: [8, 30], 14: [8, 33], 15: [8, 32], # Remapped 4 entries + 16: [7, 34], 17: [7, 35], 18: [7, 36], 19: [7, 37], + 20: [7, 38], 21: [7, 39], 22: [7, 40], 23: [7, 41], + 24: [6, 42], 25: [6, 43], 26: [6, 44], 27: [6, 45], + 28: [6, 46], 29: [6, 47], 30: [6, 48], 31: [6, 49] + } + PORT_I2C_MAPPING = { + # 0th Index = i2cLine, 1st Index = portIdx in i2cLine + 0: [14, 0], 1: [14, 1], 2: [14, 2], 3: [14, 3], + 4: [14, 4], 5: [14, 5], 6: [14, 6], 7: [14, 7], + 8: [14, 8], 9: [14, 9], 10: [14, 10], 11: [14, 11], + 12: [15, 0], 13: [15, 1], 14: [15, 2], 15: [15, 3], + 16: [15, 4], 17: [15, 5], 18: [15, 6], 19: [15, 7], + 20: [15, 8], 21: [15, 9], 22: [16, 0], 23: [16, 1], + 24: [16, 2], 25: [16, 3], 26: [16, 4], 27: [16, 5], + 28: [16, 6], 29: [16, 7], 30: [16, 8], 31: [16, 9] + } + + OIR_FD_PATH = "/sys/devices/platform/dell_ich.0/sci_int_gpio_sus6" + + reset_reason_dict = {} + reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS + reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG + reset_reason_dict[44] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE + reset_reason_dict[55] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE + + power_reason_dict = {} + power_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS + power_reason_dict[22] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU + power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC + power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED + + def __init__(self): + ChassisBase.__init__(self) + self.oir_fd = -1 + self.epoll = -1 + PORT_START = 0 + PORT_END = 31 + PORTS_IN_BLOCK = (PORT_END + 1) + + # sfp.py will read eeprom contents and retrive the eeprom data. + # It will also provide support sfp controls like reset and setting + # low power mode. + # We pass the eeprom path and sfp control path from chassis.py + # So that sfp.py implementation can be generic to all platforms + eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom" + sfp_ctrl_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/" + for index in range(0, PORTS_IN_BLOCK): + eeprom_path = eeprom_base.format(self.EEPROM_I2C_MAPPING[index][0], + self.EEPROM_I2C_MAPPING[index][1]) + sfp_control = sfp_ctrl_base.format(self.PORT_I2C_MAPPING[index][0]) + sfp_node = Sfp(index, 'QSFP', eeprom_path, sfp_control, + self.PORT_I2C_MAPPING[index][1]) + self._sfp_list.append(sfp_node) + + # Initialize EEPROM + self._eeprom = Eeprom() + for i in range(MAX_Z9100_FANTRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + for i in range(MAX_Z9100_PSU): + psu = Psu(i) + self._psu_list.append(psu) + + for i in range(MAX_Z9100_THERMAL): + thermal = Thermal(i) + self._thermal_list.append(thermal) + + for i in range(MAX_Z9100_COMPONENT): + component = Component(i) + self._component_list.append(component) + + def __del__(self): + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + + def _get_pmc_register(self, reg_name): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR + '/' + reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_register(self, reg_file): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(reg_file)): + return rv + + try: + with open(reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_str() + + def get_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): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_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. + """ + reset_reason = int(self._get_pmc_register('smf_reset_reason')) + power_reason = int(self._get_pmc_register('smf_poweron_reason')) + + # Reset_Reason = 11 ==> PowerLoss + # So return the reboot reason from Last Power_Reason Dictionary + # If Reset_Reason is not 11 return from Reset_Reason dictionary + # Also check if power_reason, reset_reason are valid values by + # checking key presence in dictionary else return + # REBOOT_CAUSE_HARDWARE_OTHER as the Power_Reason and Reset_Reason + # registers returned invalid data + if (reset_reason == 11): + if (power_reason in self.power_reason_dict): + return (self.power_reason_dict[power_reason], None) + else: + if (reset_reason in self.reset_reason_dict): + return (self.reset_reason_dict[reset_reason], None) + + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason") + + def _check_interrupts(self, port_dict): + is_port_dict_updated = False + + cpld2_abs_int = self._get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_int") + cpld2_abs_sta = self._get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_sta") + cpld3_abs_int = self._get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_int") + cpld3_abs_sta = self._get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_sta") + cpld4_abs_int = self._get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_int") + cpld4_abs_sta = self._get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_sta") + + if (cpld2_abs_int == 'ERR' or cpld2_abs_sta == 'ERR' or + cpld3_abs_int == 'ERR' or cpld3_abs_sta == 'ERR' or + cpld4_abs_int == 'ERR' or cpld4_abs_sta == 'ERR'): + return False, is_port_dict_updated + + cpld2_abs_int = int(cpld2_abs_int, 16) + cpld2_abs_sta = int(cpld2_abs_sta, 16) + cpld3_abs_int = int(cpld3_abs_int, 16) + cpld3_abs_sta = int(cpld3_abs_sta, 16) + cpld4_abs_int = int(cpld4_abs_int, 16) + cpld4_abs_sta = int(cpld4_abs_sta, 16) + + # Make it contiguous (discard reserved bits) + interrupt_reg = (cpld2_abs_int & 0xfff) |\ + ((cpld3_abs_int & 0x3ff) << 12) |\ + ((cpld4_abs_int & 0x3ff) << 22) + status_reg = (cpld2_abs_sta & 0xfff) |\ + ((cpld3_abs_sta & 0x3ff) << 12) |\ + ((cpld4_abs_sta & 0x3ff) << 22) + + for port in range(self.get_num_sfps()): + if interrupt_reg & (1 << port): + # update only if atleast one port has generated + # interrupt + is_port_dict_updated = True + if status_reg & (1 << port): + # status reg 1 => optics is removed + port_dict[port+1] = '0' + else: + # status reg 0 => optics is inserted + port_dict[port+1] = '1' + + return True, is_port_dict_updated + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the + format of {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + port_dict = {} + ret_dict = {'sfp': port_dict} + if timeout != 0: + timeout = timeout / 1000 + try: + # We get notified when there is an SCI interrupt from GPIO SUS6 + # Open the sysfs file and register the epoll object + self.oir_fd = open(self.OIR_FD_PATH, "r") + if self.oir_fd != -1: + # Do a dummy read before epoll register + self.oir_fd.read() + self.epoll = select.epoll() + self.epoll.register(self.oir_fd.fileno(), + select.EPOLLIN & select.EPOLLET) + else: + return False, ret_dict + + # Check for missed interrupts by invoking self.check_interrupts + # which will update the port_dict. + while True: + interrupt_count_start = self._get_register(self.OIR_FD_PATH) + + retval, is_port_dict_updated = \ + self._check_interrupts(port_dict) + if (retval is True) and (is_port_dict_updated is True): + return True, ret_dict + + interrupt_count_end = self._get_register(self.OIR_FD_PATH) + + if (interrupt_count_start == 'ERR' or + interrupt_count_end == 'ERR'): + break + + # check_interrupts() itself may take upto 100s of msecs. + # We detect a missed interrupt based on the count + if interrupt_count_start == interrupt_count_end: + break + + # Block until an xcvr is inserted or removed with timeout = -1 + events = self.epoll.poll(timeout=timeout if timeout != 0 else -1) + if events: + # check interrupts and return the port_dict + retval, is_port_dict_updated = \ + self._check_interrupts(port_dict) + + return retval, ret_dict + except Exception: + return False, ret_dict + finally: + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + self.oir_fd = -1 + self.epoll = -1 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/component.py new file mode 100644 index 000000000000..52dee31a524e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/component.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC Z9100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + import subprocess + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version" + + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["CPLD1", "Used for managing the system LEDs"], + ["CPLD2", "Used for managing QSFP28 modules (1-12)"], + ["CPLD3", "Used for managing QSFP28 modules (13-22)"], + ["CPLD4", ("Used for managing QSFP28 modules (23-32) and SFP+ " + "modules")], + ["FPGA", ("Platform management controller for on-board temperature " + "monitoring, in-chassis power, Fan and LED control")] + ] + + def __init__(self, component_index=0): + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + + def _read_sysfs_file(self, sysfs_file): + # On successful read, returns the value read from given + # sysfs_file and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(sysfs_file)): + return rv + + try: + with open(sysfs_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.decode('utf-8').rstrip('\n') + except OSError: + result = None + + return result + + def _get_cpld_version(self, cpld_number): + io_resource = "/dev/port" + CPLD1_VERSION_ADDR = 0x100 + + if (cpld_number == 1): + fd = os.open(io_resource, os.O_RDONLY) + if (fd < 0): + return 'NA' + + if (os.lseek(fd, CPLD1_VERSION_ADDR, os.SEEK_SET) + != CPLD1_VERSION_ADDR): + os.close(fd) + return 'NA' + + buf = os.read(fd, 1) + cpld_version = str(ord(buf)) + os.close(fd) + + return cpld_version + else: + cpld_version_file = ("/sys/class/i2c-adapter/i2c-{0}/{0}-003e" + "/iom_cpld_vers").format(12 + cpld_number) + ver_str = self._read_sysfs_file(cpld_version_file) + + if (ver_str == "read error") or (ver_str == 'ERR'): + return 'NA' + + ver_str = ver_str.rstrip("\r\n") + cpld_version = str(int(ver_str.split(":")[1], 16)) + + return cpld_version + + def _get_fpga_version(self): + fpga_ver_file = self.MAILBOX_DIR + '/smf_firmware_ver' + fpga_ver = self._read_sysfs_file(fpga_ver_file) + if (fpga_ver != 'ERR'): + return fpga_ver + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + if self.index == 0: # BIOS + bios_ver = self._get_command_result(BIOS_QUERY_VERSION_COMMAND) + + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index < 5: # CPLD + return self._get_cpld_version(self.index) + elif self.index == 5: # FPGA + return self._get_fpga_version() + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/eeprom.py new file mode 100644 index 000000000000..f5dd5477be3e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/eeprom.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python + +############################################################################# +# DellEmc Z9100 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + 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() + except: + self.eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % tlv[0] + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += tlv[6:6 + tlv[1]].decode('ascii') + else: + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def base_mac_addr(self): + (is_valid, t) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join(["{:02x}".format(T) for T in t[2]]).upper() + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict 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 new file mode 100755 index 000000000000..31bda2f4cefb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py @@ -0,0 +1,265 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fans' information which are available in the platform. +# +######################################################################## + +import os.path + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MAX_Z9100_PSU_FAN_SPEED = 18000 +MAX_Z9100_FAN_SPEED = 16000 + + +class Fan(FanBase): + """DellEMC Platform-specific Fan class""" + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + def __init__(self, fantray_index=1, fan_index=1, psu_fan=False): + self.is_psu_fan = psu_fan + if not self.is_psu_fan: + # API index is starting from 0, DellEMC platform index is starting + # from 1 + self.fantrayindex = fantray_index + 1 + self.fanindex = fan_index + 1 + 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( + 2 * self.fantrayindex - 1) + self.fan_serialno_reg = "fan{}_serialno".format( + 2 * self.fantrayindex - 1) + self.max_fan_speed = MAX_Z9100_FAN_SPEED + 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): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the fan name + Returns: + string: The name of the device + """ + if not self.is_psu_fan: + return "FanTray{}-Fan{}".format(self.fantrayindex, self.fanindex) + else: + return "PSU{} Fan".format(self.fanindex - 10) + + def get_model(self): + """ + Retrieves the part number of the FAN + Returns: + string: Part number of FAN + """ + # 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): + fan_partno = fan_serialno.split('-')[1] + else: + fan_partno = 'NA' + else: + fan_partno = 'NA' + + return fan_partno + + def get_serial(self): + """ + Retrieves the serial number of the FAN + Returns: + 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' + + return fan_serialno + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if fan is present, False if not + """ + status = False + fantray_presence = self._get_pmc_register(self.fan_presence_reg) + if (fantray_presence != 'ERR'): + fantray_presence = int(fantray_presence, 10) + if (~fantray_presence & 0b1): + status = True + + return status + + def get_status(self): + """ + Retrieves the operational status of the FAN + Returns: + bool: True if FAN is operating properly, False if not + """ + status = False + 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 + + def get_direction(self): + """ + Retrieves the fan airflow direction + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + In DellEMC platforms, + - Forward/Exhaust : Air flows from Port side to Fan side. + - Reverse/Intake : Air flows from Fan side to Port side. + """ + direction = [self.FAN_DIRECTION_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 self.FAN_DIRECTION_NOT_APPLICABLE + return direction[fan_direction] + + def get_speed(self): + """ + Retrieves the speed of fan + Returns: + int: percentage of the max fan speed + """ + fan_speed = self._get_pmc_register(self.get_fan_speed_reg) + if (fan_speed != 'ERR') and self.get_presence(): + speed_in_rpm = int(fan_speed, 10) + speed = (100 * speed_in_rpm)//self.max_fan_speed + else: + speed = 0 + + return speed + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + if self.get_presence(): + # The tolerance value is fixed as 20% for all the DellEmc platform + tolerance = 20 + else: + tolerance = 0 + + return tolerance + + def set_speed(self, speed): + """ + Set fan speed to expected value + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + bool: True if set success, False if fail. + """ + + # Fan speeds are controlled by Smart-fussion FPGA. + return False + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if set success, False if fail. + """ + # Leds are controlled by Smart-fussion FPGA. + status = False + return status + + def get_status_led(self): + """ + Gets the state of the Fan status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + if self.is_psu_fan: + # No LED available for PSU Fan + return None + else: + 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): + """ + 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) + """ + return 0 + + + + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..b74931dd92d3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan_drawer.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +Z9100_FANS_PER_FANTRAY = 2 + + +class FanDrawer(FanDrawerBase): + """DellEMC Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + # FanTray is 1-based in DellEMC platforms + self.fantrayindex = fantray_index + 1 + for i in range(Z9100_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/platform.py new file mode 100755 index 000000000000..426db717281b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/platform.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """ + DELLEMC Platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/psu.py new file mode 100644 index 000000000000..f76d0ac1bec6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/psu.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + + +try: + import os + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Psu(PsuBase): + """DellEMC Platform-specific PSU class""" + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + def __init__(self, psu_index): + # PSU is 1-based in DellEMC platforms + self.index = psu_index + 1 + self.psu_presence_reg = "psu{}_presence".format(self.index) + self.psu_serialno_reg = "psu{}_serialno".format(self.index) + if self.index == 1: + self.psu_voltage_reg = "in30_input" + self.psu_current_reg = "curr602_input" + self.psu_power_reg = "power2_input" + elif self.index == 2: + self.psu_voltage_reg = "in32_input" + self.psu_current_reg = "curr702_input" + self.psu_power_reg = "power4_input" + + # Overriding _fan_list class variable defined in PsuBase, to + # make it unique per Psu object + self._fan_list = [] + + # Passing True to specify it is a PSU fan + psu_fan = Fan(fan_index=self.index, psu_fan=True) + self._fan_list.append(psu_fan) + + def _get_pmc_register(self, reg_name): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR + '/' + reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + status = False + psu_presence = self._get_pmc_register(self.psu_presence_reg) + if (psu_presence != 'ERR'): + psu_presence = int(psu_presence, 16) + # Checking whether bit 0 is not set + if (~psu_presence & 0b1): + status = True + + return status + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + # For Serial number "US-01234D-54321-25A-0123-A00", the part + # number is "01234D" + psu_serialno = self._get_pmc_register(self.psu_serialno_reg) + if (psu_serialno != 'ERR') and self.get_presence(): + if (len(psu_serialno.split('-')) > 1): + psu_partno = psu_serialno.split('-')[1] + else: + psu_partno = 'NA' + else: + psu_partno = 'NA' + + return psu_partno + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + # Sample Serial number format "US-01234D-54321-25A-0123-A00" + psu_serialno = self._get_pmc_register(self.psu_serialno_reg) + if (psu_serialno == 'ERR') or not self.get_presence(): + psu_serialno = 'NA' + + return psu_serialno + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + status = False + psu_status = self._get_pmc_register(self.psu_presence_reg) + if (psu_status != 'ERR'): + psu_status = int(psu_status, 16) + # Checking whether both bit 3 and bit 2 are not set + if (~psu_status & 0b1000) and (~psu_status & 0b0100): + status = True + + return status + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + psu_voltage = self._get_pmc_register(self.psu_voltage_reg) + if (psu_voltage != 'ERR') and self.get_presence(): + # Converting the value returned by driver which is in + # millivolts to volts + psu_voltage = float(psu_voltage) / 1000 + else: + psu_voltage = 0.0 + + return psu_voltage + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + psu_current = self._get_pmc_register(self.psu_current_reg) + if (psu_current != 'ERR') and self.get_presence(): + # Converting the value returned by driver which is in + # milliamperes to amperes + psu_current = float(psu_current) / 1000 + else: + psu_current = 0.0 + + return psu_current + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + psu_power = self._get_pmc_register(self.psu_power_reg) + if (psu_power != 'ERR') and self.get_presence(): + # Converting the value returned by driver which is in + # microwatts to watts + psu_power = float(psu_power) / 1000000 + else: + psu_power = 0.0 + + return psu_power + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + status = False + if self.get_status() and self._fan_list[0].get_status(): + status = True + + return status + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if + not + """ + # In Z9100, SmartFusion FPGA controls the PSU LED and the PSU + # LED state cannot be changed from CPU. + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/sfp.py new file mode 100644 index 000000000000..7abe73c2be3d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/sfp.py @@ -0,0 +1,882 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import time + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +PAGE_OFFSET = 0 +KEY_OFFSET = 1 +KEY_WIDTH = 2 +FUNC_NAME = 3 + +INFO_OFFSET = 128 +DOM_OFFSET = 0 +DOM_OFFSET1 = 384 + +cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', + 'Length OM1(m)', 'Length Cable Assembly(m)') + +compliance_code_tup = ( + '10/40G Ethernet Compliance Code', + 'SONET Compliance codes', + 'SAS/SATA compliance codes', + 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', + 'Fibre Channel Speed') + +info_dict_keys = ['type', 'hardware_rev', 'serial', + 'manufacturer', 'model', 'connector', + 'encoding', 'ext_identifier', 'ext_rateselect_compliance', + 'cable_type', 'cable_length', 'nominal_bit_rate', + 'specification_compliance','type_abbrv_name','vendor_date', 'vendor_oui'] + +dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', + 'power_lpmode', 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', 'rx1power', + 'rx2power', 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', 'tx3bias', + 'tx4bias', 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + +threshold_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning'] + +sff8436_parser = { + 'reset_status': [DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'], + 'rx_los': [DOM_OFFSET, 3, 1, 'parse_dom_tx_rx_los'], + 'tx_fault': [DOM_OFFSET, 4, 1, 'parse_dom_tx_fault'], + 'tx_disable': [DOM_OFFSET, 86, 1, 'parse_dom_tx_disable'], + 'power_lpmode': [DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'power_override': [DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'Temperature': [DOM_OFFSET, 22, 2, 'parse_temperature'], + 'Voltage': [DOM_OFFSET, 26, 2, 'parse_voltage'], + 'ChannelMonitor': [DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'], + + 'cable_type': [INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'encoding': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_identifier': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'specification_compliance': + [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type_abbrv_name': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'manufacturer': [INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [INFO_OFFSET, 56, 2, 'parse_vendor_rev'], + 'serial': [INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'ModuleThreshold': [DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'], + 'ChannelThreshold': [DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'], +} + + +class Sfp(SfpBase): + """ + DELLEMC Platform-specific Sfp class + """ + + def __init__(self, index, sfp_type, eeprom_path, + sfp_control, sfp_ctrl_idx): + SfpBase.__init__(self) + self.sfp_type = sfp_type + self.index = index + self.eeprom_path = eeprom_path + self.sfp_control = sfp_control + self.sfp_ctrl_idx = sfp_ctrl_idx + self.sfpInfo = sff8436InterfaceId() + self.sfpDomInfo = sff8436Dom() + + def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes): + eeprom_raw = [] + try: + eeprom = open(eeprom_path, mode="rb", buffering=0) + except IOError: + return None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom.seek(offset) + raw = eeprom.read(num_bytes) + except IOError: + eeprom.close() + return None + + try: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except BaseException: + eeprom.close() + return None + + eeprom.close() + return eeprom_raw + + def _get_eeprom_data(self, eeprom_key): + eeprom_data = None + page_offset = None + + if (self.sfpInfo is None): + return None + + page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8436_parser[eeprom_key][PAGE_OFFSET] + + sff8436_parser[eeprom_key][KEY_OFFSET]), + sff8436_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 128 is used to retrieve sff8436InterfaceId Info + # Offset 0 is used to retrieve sff8436Dom Info + if (page_offset == 128): + eeprom_data = getattr( + self.sfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + eeprom_data = getattr( + self.sfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + + return eeprom_data + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + """ + transceiver_info_dict = {} + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A') + + # BaseInformation + iface_data = self._get_eeprom_data('type') + if (iface_data is not None): + connector = iface_data['data']['Connector']['value'] + encoding = iface_data['data']['EncodingCodes']['value'] + ext_id = iface_data['data']['Extended Identifier']['value'] + rate_identifier = iface_data['data']['RateIdentifier']['value'] + identifier = iface_data['data']['type']['value'] + bit_rate = str( + iface_data['data']['Nominal Bit Rate(100Mbs)']['value']) + type_abbrv_name=iface_data['data']['type_abbrv_name']['value'] + + for key in compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + else: + return transceiver_info_dict + + # Vendor Date + vendor_date_data = self._get_eeprom_data('vendor_date') + if (vendor_date_data is not None): + vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + else: + return transceiver_info_dict + + # Vendor Name + vendor_name_data = self._get_eeprom_data('manufacturer') + if (vendor_name_data is not None): + vendor_name = vendor_name_data['data']['Vendor Name']['value'] + else: + return transceiver_info_dict + + # Vendor OUI + vendor_oui_data = self._get_eeprom_data('vendor_oui') + if (vendor_oui_data is not None): + vendor_oui = vendor_oui_data['data']['Vendor OUI']['value'] + else: + return transceiver_info_dict + + # Vendor PN + vendor_pn_data = self._get_eeprom_data('model') + if (vendor_pn_data is not None): + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + else: + return transceiver_info_dict + + # Vendor Revision + vendor_rev_data = self._get_eeprom_data('hardware_rev') + if (vendor_rev_data is not None): + vendor_rev = vendor_rev_data['data']['Vendor Rev']['value'] + else: + return transceiver_info_dict + + # Vendor Serial Number + vendor_sn_data = self._get_eeprom_data('serial') + if (vendor_sn_data is not None): + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + else: + return transceiver_info_dict + + # Fill The Dictionary and return + transceiver_info_dict['type'] = identifier + transceiver_info_dict['hardware_rev'] = vendor_rev + transceiver_info_dict['serial'] = vendor_sn + transceiver_info_dict['manufacturer'] = vendor_name + transceiver_info_dict['model'] = vendor_pn + transceiver_info_dict['connector'] = connector + transceiver_info_dict['encoding'] = encoding + transceiver_info_dict['ext_identifier'] = ext_id + transceiver_info_dict['ext_rateselect_compliance'] = rate_identifier + transceiver_info_dict['cable_type'] = cable_type + transceiver_info_dict['cable_length'] = cable_length + transceiver_info_dict['nominal_bit_rate'] = bit_rate + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + transceiver_info_dict['vendor_date'] = vendor_date + transceiver_info_dict['vendor_oui'] = vendor_oui + transceiver_info_dict['type_abbrv_name'] = type_abbrv_name + + return transceiver_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + """ + transceiver_dom_threshold_dict = {} + transceiver_dom_threshold_dict = dict.fromkeys( + threshold_dict_keys, 'N/A') + + # Module Threshold + module_threshold_data = self._get_eeprom_data('ModuleThreshold') + if (module_threshold_data is not None): + tempHighAlarm = module_threshold_data['data']['TempHighAlarm']['value'] + tempLowAlarm = module_threshold_data['data']['TempLowAlarm']['value'] + tempHighWarn = module_threshold_data['data']['TempHighWarning']['value'] + tempLowWarn = module_threshold_data['data']['TempLowWarning']['value'] + vccHighAlarm = module_threshold_data['data']['VccHighAlarm']['value'] + vccLowAlarm = module_threshold_data['data']['VccLowAlarm']['value'] + vccHighWarn = module_threshold_data['data']['VccHighWarning']['value'] + vccLowWarn = module_threshold_data['data']['VccLowWarning']['value'] + else: + return transceiver_dom_threshold_dict + + # Channel Threshold + channel_threshold_data = self._get_eeprom_data('ChannelThreshold') + if (channel_threshold_data is not None): + rxPowerHighAlarm = channel_threshold_data['data']['RxPowerHighAlarm']['value'] + rxPowerLowAlarm = channel_threshold_data['data']['RxPowerLowAlarm']['value'] + rxPowerHighWarn = channel_threshold_data['data']['RxPowerHighWarning']['value'] + rxPowerLowWarn = channel_threshold_data['data']['RxPowerLowWarning']['value'] + txBiasHighAlarm = channel_threshold_data['data']['TxBiasHighAlarm']['value'] + txBiasLowAlarm = channel_threshold_data['data']['TxBiasLowAlarm']['value'] + txBiasHighWarn = channel_threshold_data['data']['TxBiasHighWarning']['value'] + txBiasLowWarn = channel_threshold_data['data']['TxBiasLowWarning']['value'] + else: + return transceiver_dom_threshold_dict + + transceiver_dom_threshold_dict['temphighalarm'] = tempHighAlarm + transceiver_dom_threshold_dict['templowalarm'] = tempLowAlarm + transceiver_dom_threshold_dict['temphighwarning'] = tempHighWarn + transceiver_dom_threshold_dict['templowwarning'] = tempLowWarn + transceiver_dom_threshold_dict['vcchighalarm'] = vccHighAlarm + transceiver_dom_threshold_dict['vcclowalarm'] = vccLowAlarm + transceiver_dom_threshold_dict['vcchighwarning'] = vccHighWarn + transceiver_dom_threshold_dict['vcclowwarning'] = vccLowWarn + transceiver_dom_threshold_dict['rxpowerhighalarm'] = rxPowerHighAlarm + transceiver_dom_threshold_dict['rxpowerlowalarm'] = rxPowerLowAlarm + transceiver_dom_threshold_dict['rxpowerhighwarning'] = rxPowerHighWarn + transceiver_dom_threshold_dict['rxpowerlowwarning'] = rxPowerLowWarn + transceiver_dom_threshold_dict['txbiashighalarm'] = txBiasHighAlarm + transceiver_dom_threshold_dict['txbiaslowalarm'] = txBiasLowAlarm + transceiver_dom_threshold_dict['txbiashighwarning'] = txBiasHighWarn + transceiver_dom_threshold_dict['txbiaslowwarning'] = txBiasLowWarn + + return transceiver_dom_threshold_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + """ + tx_bias_list = [] + rx_power_list = [] + transceiver_dom_dict = {} + transceiver_dom_dict = dict.fromkeys(dom_dict_keys, 'N/A') + + # RxLos + rx_los = self.get_rx_los() + + # TxFault + tx_fault = self.get_tx_fault() + + # ResetStatus + reset_state = self.get_reset_status() + + # LowPower Mode + lp_mode = self.get_lpmode() + + # TxDisable + tx_disable = self.get_tx_disable() + + # TxDisable Channel + tx_disable_channel = self.get_tx_disable_channel() + + # Temperature + temperature = self.get_temperature() + + # Voltage + voltage = self.get_voltage() + + # Channel Monitor + channel_monitor_data = self._get_eeprom_data('ChannelMonitor') + if (channel_monitor_data is not None): + tx_bias = channel_monitor_data['data']['TX1Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = channel_monitor_data['data']['TX2Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = channel_monitor_data['data']['TX3Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = channel_monitor_data['data']['TX4Bias']['value'] + tx_bias_list.append(tx_bias) + rx_power = channel_monitor_data['data']['RX1Power']['value'] + rx_power_list.append(rx_power) + rx_power = channel_monitor_data['data']['RX2Power']['value'] + rx_power_list.append(rx_power) + rx_power = channel_monitor_data['data']['RX3Power']['value'] + rx_power_list.append(rx_power) + rx_power = channel_monitor_data['data']['RX4Power']['value'] + rx_power_list.append(rx_power) + else: + return transceiver_dom_dict + + transceiver_dom_dict['rx_los'] = rx_los + transceiver_dom_dict['tx_fault'] = tx_fault + transceiver_dom_dict['reset_status'] = reset_state + transceiver_dom_dict['power_lpmode'] = lp_mode + transceiver_dom_dict['tx_disable'] = tx_disable + transceiver_dom_dict['tx_disable_channel'] = tx_disable_channel + transceiver_dom_dict['temperature'] = temperature + transceiver_dom_dict['voltage'] = voltage + transceiver_dom_dict['tx1bias'] = tx_bias_list[0] + transceiver_dom_dict['tx2bias'] = tx_bias_list[1] + transceiver_dom_dict['tx3bias'] = tx_bias_list[2] + transceiver_dom_dict['tx4bias'] = tx_bias_list[3] + transceiver_dom_dict['rx1power'] = rx_power_list[0] + transceiver_dom_dict['rx2power'] = rx_power_list[1] + transceiver_dom_dict['rx3power'] = rx_power_list[2] + transceiver_dom_dict['rx4power'] = rx_power_list[3] + + return transceiver_dom_dict + + def get_name(self): + """ + Retrieves the name of the sfp + Returns : QSFP or QSFP+ or QSFP28 + """ + iface_data = self._get_eeprom_data('type') + if (iface_data is not None): + identifier = iface_data['data']['type']['value'] + else: + return None + + return identifier + + def get_presence(self): + """ + Retrieves the presence of the sfp + """ + presence_ctrl = self.sfp_control + 'qsfp_modprs' + try: + reg_file = open(presence_ctrl) + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + index = self.sfp_ctrl_idx + + # Mask off the bit corresponding to our port + mask = (1 << index) + + # ModPrsL is active low + if ((reg_value & mask) == 0): + return True + + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the sfp + """ + vendor_pn_data = self._get_eeprom_data('model') + if (vendor_pn_data is not None): + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + else: + return None + + return vendor_pn + + def get_serial(self): + """ + Retrieves the serial number of the sfp + """ + vendor_sn_data = self._get_eeprom_data('serial') + if (vendor_sn_data is not None): + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + else: + return None + + return vendor_sn + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + """ + reset_status = None + reset_ctrl = self.sfp_control + 'qsfp_reset' + try: + reg_file = open(reset_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + index = self.sfp_ctrl_idx + + mask = (1 << index) + + if ((reg_value & mask) == 0): + reset_status = True + else: + reset_status = False + + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + """ + rx_los = None + rx_los_list = [] + + rx_los_data = self._get_eeprom_data('rx_los') + if (rx_los_data is not None): + rx_los = rx_los_data['data']['Rx1LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx2LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx3LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx4LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + + if (rx_los_list[0] and rx_los_list[1] + and rx_los_list[2] and rx_los_list[3]): + rx_los = True + else: + rx_los = False + + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + """ + tx_fault = None + tx_fault_list = [] + + tx_fault_data = self._get_eeprom_data('tx_fault') + if (tx_fault_data is not None): + tx_fault = tx_fault_data['data']['Tx1Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx2Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx3Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx4Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + + if (tx_fault_list[0] and tx_fault_list[1] + and tx_fault_list[2] and tx_fault_list[3]): + tx_fault = True + else: + tx_fault = False + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + """ + tx_disable = None + tx_disable_list = [] + + tx_disable_data = self._get_eeprom_data('tx_disable') + if (tx_disable_data is not None): + tx_disable = tx_disable_data['data']['Tx1Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx2Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx3Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx4Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + + if (tx_disable_list[0] and tx_disable_list[1] + and tx_disable_list[2] and tx_disable_list[3]): + tx_disable = True + else: + tx_disable = False + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + """ + tx_disable = None + tx_disable_list = [] + + tx_disable_data = self._get_eeprom_data('tx_disable') + if (tx_disable_data is not None): + tx_disable = tx_disable_data['data']['Tx1Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + tx_disable = tx_disable_data['data']['Tx2Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + tx_disable = tx_disable_data['data']['Tx3Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + tx_disable = tx_disable_data['data']['Tx4Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + + bit4 = int(tx_disable_list[3]) * 8 + bit3 = int(tx_disable_list[2]) * 4 + bit2 = int(tx_disable_list[1]) * 2 + bit1 = int(tx_disable_list[0]) * 1 + + tx_disable_channel = hex(bit4 + bit3 + bit2 + bit1) + + return tx_disable_channel + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + """ + lpmode_ctrl = self.sfp_control + 'qsfp_lpmode' + try: + reg_file = open(lpmode_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + index = self.sfp_ctrl_idx + + mask = (1 << index) + + if ((reg_value & mask) == 0): + lpmode_state = False + else: + lpmode_state = True + + return lpmode_state + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + """ + power_override_state = None + + # Reset Status + power_override_data = self._get_eeprom_data('power_override') + if (power_override_data is not None): + power_override = power_override_data['data']['PowerOverRide']['value'] + if (power_override is 'On'): + power_override_state = True + else: + power_override_state = False + + return power_override_state + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + """ + temperature = None + + temperature_data = self._get_eeprom_data('Temperature') + if (temperature_data is not None): + temperature = temperature_data['data']['Temperature']['value'] + + return temperature + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + """ + voltage = None + + voltage_data = self._get_eeprom_data('Voltage') + if (voltage_data is not None): + voltage = voltage_data['data']['Vcc']['value'] + + return voltage + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + """ + tx_bias = None + tx_bias_list = [] + + tx_bias_data = self._get_eeprom_data('ChannelMonitor') + if (tx_bias_data is not None): + tx_bias = tx_bias_data['data']['TX1Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = tx_bias_data['data']['TX2Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = tx_bias_data['data']['TX3Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = tx_bias_data['data']['TX4Bias']['value'] + tx_bias_list.append(tx_bias) + + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + """ + rx_power = None + rx_power_list = [] + + rx_power_data = self._get_eeprom_data('ChannelMonitor') + if (rx_power_data is not None): + rx_power = rx_power_data['data']['RX1Power']['value'] + rx_power_list.append(rx_power) + rx_power = rx_power_data['data']['RX2Power']['value'] + rx_power_list.append(rx_power) + rx_power = rx_power_data['data']['RX3Power']['value'] + rx_power_list.append(rx_power) + rx_power = rx_power_data['data']['RX4Power']['value'] + rx_power_list.append(rx_power) + + return rx_power_list + + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + """ + tx_power = None + tx_power_list = [] + + tx_power_list.append('-infdBm') + tx_power_list.append('-infdBm') + tx_power_list.append('-infdBm') + tx_power_list.append('-infdBm') + + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + """ + reset_ctrl = self.sfp_control + 'qsfp_reset' + try: + # Open reset_ctrl in both read & write mode + reg_file = open(reset_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + index = self.sfp_ctrl_idx + + # Mask off the bit corresponding to our port + mask = (1 << index) + + # ResetL is active low + reg_value = (reg_value & ~mask) + + # Convert our register value back to a + # hex string and write back + reg_file.seek(0) + reg_file.write(hex(reg_value)) + 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(reset_ctrl, "w") + except IOError as e: + return False + + reg_value = reg_value | mask + reg_file.seek(0) + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + """ + lpmode_ctrl = self.sfp_control + 'qsfp_lpmode' + try: + reg_file = open(lpmode_ctrl, "r+") + except IOError as e: + return False + + reg_hex = reg_file.readline().rstrip() + + # content is a string containing the hex + # representation of the register + reg_value = int(reg_hex, 16) + + # Mask off the bit corresponding to our port + index = self.sfp_ctrl_idx + + mask = (1 << index) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = (reg_value | mask) + else: + reg_value = (reg_value & ~mask) + + # Convert our register value back to a hex string and write back + content = hex(reg_value) + + reg_file.seek(0) + reg_file.write(content) + reg_file.close() + + return True + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + """ + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + """ + return False + + def get_status(self): + """ + Retrieves the operational status of the device + """ + reset = self.get_reset_status() + + if (reset == True): + status = False + else: + status = True + + return status diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/thermal.py new file mode 100644 index 000000000000..942934ed7638 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/thermal.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + import os + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """DellEMC Platform-specific Thermal class""" + + THERMAL_NAME = ( + 'CPU On-board', 'ASIC On-board Rear', 'System Front Left', + 'System Front Right', 'CPU Core 0', 'CPU Core 1', 'CPU Core 2', + 'CPU Core 3' + ) + + def __init__(self, thermal_index): + self.is_cpu_thermal = False + self.index = thermal_index + 1 + + if self.index < 5: + hwmon_temp_index = self.index + dev_path = "/sys/devices/platform/SMF.512/hwmon/" + else: + hwmon_temp_index = self.index - 3 + self.is_cpu_thermal = True + dev_path = "/sys/devices/platform/coretemp.0/hwmon/" + + hwmon_node = os.listdir(dev_path)[0] + self.HWMON_DIR = dev_path + hwmon_node + '/' + + self.thermal_status_file = self.HWMON_DIR \ + + "temp{}_alarm".format(hwmon_temp_index) + self.thermal_temperature_file = self.HWMON_DIR \ + + "temp{}_input".format(hwmon_temp_index) + self.thermal_high_threshold_file = self.HWMON_DIR \ + + "temp{}_max".format(hwmon_temp_index) + self.thermal_low_threshold_file = self.HWMON_DIR \ + + "temp{}_min".format(hwmon_temp_index) + + if not self.is_cpu_thermal: + self.thermal_high_crit_threshold_file = self.HWMON_DIR \ + + "temp{}_crit".format(hwmon_temp_index) + + def _read_sysfs_file(self, sysfs_file): + # On successful read, returns the value read from given + # sysfs_file and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(sysfs_file)): + return rv + + try: + with open(sysfs_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the name of the thermal + + Returns: + string: The name of the thermal + """ + return self.THERMAL_NAME[self.index - 1] + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return 'NA' + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + status = False + if self.is_cpu_thermal: + status = True + else: + thermal_status = self._read_sysfs_file(self.thermal_status_file) + if (thermal_status != 'ERR'): + thermal_status = int(thermal_status, 16) + if thermal_status != 5: + status = True + + return status + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + thermal_temperature = self._read_sysfs_file( + self.thermal_temperature_file) + if (thermal_temperature != 'ERR'): + thermal_temperature = float(thermal_temperature) + else: + thermal_temperature = 0 + + return thermal_temperature / 1000.0 + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + thermal_high_threshold = self._read_sysfs_file( + self.thermal_high_threshold_file) + if (thermal_high_threshold != 'ERR'): + thermal_high_threshold = float(thermal_high_threshold) + else: + thermal_high_threshold = 0 + + return thermal_high_threshold / 1000.0 + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + thermal_low_threshold = self._read_sysfs_file( + self.thermal_low_threshold_file) + if (thermal_low_threshold != 'ERR'): + thermal_low_threshold = float(thermal_low_threshold) + else: + thermal_low_threshold = 0 + + return thermal_low_threshold / 1000.0 + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of + thermal in Celsius up to nearest thousandth of one degree + Celsius, e.g. 30.125 + """ + if self.is_cpu_thermal: + return super(Thermal, self).get_high_critical_threshold() + + thermal_high_crit_threshold = self._read_sysfs_file( + self.thermal_high_crit_threshold_file) + if (thermal_high_crit_threshold != 'ERR'): + thermal_high_crit_threshold = float(thermal_high_crit_threshold) + else: + thermal_high_crit_threshold = 0 + + return thermal_high_crit_threshold / 1000.0 + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/systemd/platform-modules-z9100.service b/platform/broadcom/sonic-platform-modules-dell/z9100/systemd/platform-modules-z9100.service new file mode 100644 index 000000000000..390cb6e0f567 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/systemd/platform-modules-z9100.service @@ -0,0 +1,13 @@ +[Unit] +Description=Dell Z9100 Platform modules +Before=pmon.service determine-reboot-cause.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/z9100_platform.sh init +ExecStop=/usr/local/bin/z9100_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/systemd/z9100-lpc-monitor.service b/platform/broadcom/sonic-platform-modules-dell/z9100/systemd/z9100-lpc-monitor.service new file mode 100644 index 000000000000..136081a63f3e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/systemd/z9100-lpc-monitor.service @@ -0,0 +1,12 @@ +[Unit] +Description=Dell Z9100 LPC bus monitoring poller +DefaultDependencies=no + +[Service] +User=root +ExecStart=/usr/local/bin/dell_lpc_mon.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/cfg/z9264f-modules.conf b/platform/broadcom/sonic-platform-modules-dell/z9264f/cfg/z9264f-modules.conf new file mode 100644 index 000000000000..959ac8290642 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/cfg/z9264f-modules.conf @@ -0,0 +1,19 @@ +# /etc/modules: kernel modules to load at boot time. +# +# This file contains the names of kernel modules that should be loaded +# at boot time, one per line. Lines beginning with "#" are ignored. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x + +ipmi_devintf +ipmi_si +dell_z9264f_fpga_ocores +i2c_ocores diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/Makefile new file mode 100644 index 000000000000..a162f0d34bfc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_z9264f_fpga_ocores.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/dell_z9264f_fpga_ocores.c b/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/dell_z9264f_fpga_ocores.c new file mode 100644 index 000000000000..c3bd78131e87 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/modules/dell_z9264f_fpga_ocores.c @@ -0,0 +1,1663 @@ +/* + * 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 + * + * 2019/5/9 - PCIe Interrupt supported is added for OIR Events. + ************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include //siginfo +#include //rcu_read_lock +#include //kernel_version +#include +#include +#include +#include +#include + + +void __iomem * fpga_base_addr = NULL; +void __iomem * fpga_ctl_addr = NULL; + +#define DRIVER_NAME "fpgapci" +#define PCI_NUM_BARS 4 + +#ifdef DEBUG +# define PRINT(fmt, ...) printk(fmt, ##__VA_ARGS__) +#else +# define PRINT(fmt, ...) +#endif + +/* Maximum size of driver buffer (allocated with kalloc()). + * Needed to copy data from user to kernel space, among other + * things. */ +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; + + /* kernels virtual addr. for the mapped BARs */ + void * __iomem bar[PCI_NUM_BARS]; + + /* length of each memory region. Used for error checking. */ + size_t bar_length[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; + + unsigned int irq_first; + unsigned int irq_length; + unsigned int irq_assigned; + unsigned int xcvr_intr_count; +}; + +static int use_irq = 1; +module_param(use_irq, int, 0644); +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."); + + +/* Xilinx FPGA PCIE info: */ +/* Non-VGA unclassified device: Xilinx Corporation Device 7021*/ +/* Subsystem: Xilinx Corporation Device 0007 */ +//#define VENDOR 0x10EE +#define DEVICE 0x7021 +static phys_addr_t fpga_phys_addr; + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +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; +}; + +/* global variable declarations */ + +/* Static function declarations */ +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id); +static void fpgapci_remove(struct pci_dev *dev); + +static int scan_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +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; +}; +/* 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_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_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 */ + +enum { + STATE_DONE = 0, + STATE_INIT, + STATE_ADDR, + STATE_ADDR10, + STATE_START, + STATE_WRITE, + STATE_READ, + STATE_STOP, + STATE_ERROR, +}; + +#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 i2c_bus_controller_numb 1 +#define I2C_PCI_MAX_BUS (16) +#define I2C_PCI_MAX_BUS_REV00 (7) +#define DELL_I2C_CLOCK_LEGACY 0 +#define DELL_I2C_CLOCK_PRESERVE (~0U) +#define I2C_PCI_BUS_NUM_5 5 +#define I2C_PCI_BUS_NUM_7 7 +#define I2C_PCI_BUS_NUM_8 8 +#define I2C_PCI_BUS_NUM_10 10 +#define I2C_PCI_BUS_NUM_12 12 +#define I2C_PCI_BUS_NUM_16 16 + + +#define IRQ_LTCH_STS 0x20 +#define PRSNT_LTCH_STS 0x10 +#define MODABS_STS 0x01 + +#define PORT_CTRL_OFFSET 0x4000 +#define PORT_STS_OFFSET 0x4004 +#define PORT_IRQ_STS_OFFSET 0x4008 +#define PORT_IRQ_EN_OFFSET 0x400C +#define MB_BRD_REV_TYPE 0x0008 +#define MB_BRD_REV_MASK 0x00f0 +#define MB_BRD_REV_00 0x0000 +#define MB_BRD_REV_01 0x0010 +#define MB_BRD_REV_02 0x0020 +#define MB_BRD_REV_03 0x0030 +#define MB_BRD_TYPE_MASK 0x000f +#define BRD_TYPE_Z9232_NON_NEBS 0x0 +#define BRD_TYPE_Z9232_NEBS 0x1 +#define BRD_TYPE_Z9264_NON_NEBS 0x2 +#define BRD_TYPE_Z9264_NEBS 0x3 +#define BRD_TYPE_S5212_NON_NEBS 0x4 +#define BRD_TYPE_S5212_NEBS 0x5 +#define BRD_TYPE_S5224_NON_NEBS 0x6 +#define BRD_TYPE_S5224_NEBS 0x7 +#define BRD_TYPE_S5248_NON_NEBS 0x8 +#define BRD_TYPE_S5248_NEBS 0x9 +#define BRD_TYPE_S5296_NON_NEBS 0xa +#define BRD_TYPE_S5296_NEBS 0xb +#define BRD_TYPE_S5232_NON_NEBS 0xc +#define BRD_TYPE_S5232_NEBS 0xd + +#define FPGA_CTL_REG_SIZE 0x6000 +#define MSI_VECTOR_MAP_MASK 0x1f +#define MSI_VECTOR_MAP1 0x58 +#define I2C_CH1_MSI_MAP_VECT_8 0x00000008 +#define I2C_CH2_MSI_MAP_VECT_9 0x00000120 +#define I2C_CH3_MSI_MAP_VECT_10 0x00002800 +#define I2C_CH4_MSI_MAP_VECT_11 0x00058000 +#define I2C_CH5_MSI_MAP_VECT_12 0x00c00000 +#define I2C_CH6_MSI_MAP_VECT_13 0x15000000 +#define MSI_VECTOR_MAP2 0x5c +#define I2C_CH7_MSI_MAP_VECT_14 0x0000000e +#define MSI_VECTOR_MAP3 0x9c +#define I2C_CH8_MSI_MAP_VECT_8 0x00800000 +#define I2C_CH8_MSI_MAP_VECT_16 0x01100000 +#define I2C_CH9_MSI_MAP_VECT_9 0x12000000 +#define I2C_CH9_MSI_MAP_VECT_17 0x24000000 +#define MSI_VECTOR_MAP4 0xa0 +#define I2C_CH10_MSI_MAP_VECT_10 0x0000000a +#define I2C_CH10_MSI_MAP_VECT_18 0x00000012 +#define I2C_CH11_MSI_MAP_VECT_11 0x00000120 +#define I2C_CH11_MSI_MAP_VECT_19 0x00000260 +#define I2C_CH12_MSI_MAP_VECT_12 0x00002800 +#define I2C_CH12_MSI_MAP_VECT_20 0x00005000 +#define I2C_CH13_MSI_MAP_VECT_13 0x00058000 +#define I2C_CH13_MSI_MAP_VECT_21 0x000a8000 +#define I2C_CH14_MSI_MAP_VECT_14 0x00c00000 +#define I2C_CH14_MSI_MAP_VECT_22 0x01600000 +#define I2C_CH15_MSI_MAP_VECT_8 0x10000000 +#define I2C_CH15_MSI_MAP_VECT_23 0x2e000000 +#define MSI_VECTOR_MAP5 0xa4 +#define I2C_CH16_MSI_MAP_VECT_9 0x00000009 +#define I2C_CH16_MSI_MAP_VECT_24 0x00000018 + +#define MSI_VECTOR_REV_00 16 +#define MSI_VECTOR_REV_01 32 + +#define FPGA_MSI_VECTOR_ID_4 4 +#define FPGA_MSI_VECTOR_ID_5 5 +#define FPGA_MSI_VECTOR_ID_6 6 +#define FPGA_MSI_VECTOR_ID_8 8 +#define FPGA_MSI_VECTOR_ID_9 9 +#define FPGA_MSI_VECTOR_ID_10 10 +#define FPGA_MSI_VECTOR_ID_11 11 +#define FPGA_MSI_VECTOR_ID_12 12 +#define FPGA_MSI_VECTOR_ID_13 13 +#define FPGA_MSI_VECTOR_ID_14 14 +#define FPGA_MSI_VECTOR_ID_15 15 /*Note: this is external MSI vector id */ +#define FPGA_MSI_VECTOR_ID_16 16 +#define FPGA_MSI_VECTOR_ID_17 17 +#define FPGA_MSI_VECTOR_ID_18 18 +#define FPGA_MSI_VECTOR_ID_19 19 +#define FPGA_MSI_VECTOR_ID_20 20 +#define FPGA_MSI_VECTOR_ID_21 21 +#define FPGA_MSI_VECTOR_ID_22 22 +#define FPGA_MSI_VECTOR_ID_23 23 +#define FPGA_MSI_VECTOR_ID_24 24 + + + +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 void fpgai2c_reg_set_8(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static void fpgai2c_reg_set_32(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static void fpgai2c_reg_set_32be(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + 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)); +} + +static inline u8 fpgai2c_reg_get_16(struct fpgalogic_i2c *i2c, int reg) +{ + 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)); +} + +static inline u8 fpgai2c_reg_get_16be(struct fpgalogic_i2c *i2c, int reg) +{ + 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)); +} + +static inline void fpgai2c_reg_set(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + i2c->reg_set(i2c, reg, value); + udelay(100); +} + +static inline u8 fpgai2c_reg_get(struct fpgalogic_i2c *i2c, int reg) +{ + udelay(100); + return i2c->reg_get(i2c, reg); +} + +static void fpgai2c_dump(struct fpgalogic_i2c *i2c) +{ + u8 tmp; + + 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_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_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); +} + +static void fpgai2c_stop(struct fpgalogic_i2c *i2c) +{ + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP); +} + +/* + * dell_get_mutex must be called prior to calling this function. + */ +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; + } + + /* 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); + + 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); + + 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 (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); + } + + 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); + PRINT("%s:xcvr_intr_count:%u\n", __FUNCTION__, fpgapci->xcvr_intr_count); + for(ind=0;ind<66;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)); + 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); +} +static DEVICE_ATTR(port_msi, S_IRUGO, get_mod_msi, NULL); + +static struct attribute *port_attrs[] = { + &dev_attr_port_msi.attr, + NULL, +}; + +static struct attribute_group port_attr_grp = { + .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); + 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)); + 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)); + } + } + 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; +} + +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); + 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)); + 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)); + } + } + 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; +} + + +static irqreturn_t fpgaport_65_66_isr(int irq, void *dev) +{ + struct pci_dev *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=64;ind<66;ind++) + { + port_irq_status = ioread32(fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16)); + if(port_irq_status| (MODABS_STS)) + { + PRINT("%s:port:%d, port_status:%#x, port_irq_status:%#x\n", __FUNCTION__, ind, port_status, port_irq_status); + //write on clear + iowrite32( MODABS_STS,fpga_ctl_addr + PORT_IRQ_STS_OFFSET + (ind*16)); + } + } + 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; +} + +static void fpgai2c_process(struct fpgalogic_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + u8 stat = fpgai2c_reg_get(i2c, FPGAI2C_REG_STATUS); + + PRINT("fpgai2c_process in. status reg :0x%x\n", stat); + + 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); + 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; + } + + + /* error? */ + if (stat & FPGAI2C_REG_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + PRINT("fpgai2c_process FPGAI2C_REG_STAT_ARBLOST FPGAI2C_REG_CMD_STOP\n"); + fpgai2c_stop(i2c); + return; + } + + 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_stop(i2c); + return; + } + } else + { + msg->buf[i2c->pos++] = fpgai2c_reg_get(i2c, FPGAI2C_REG_DATA); + } + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { /* end? */ + /* send start? */ + if (!(msg->flags & I2C_M_NOSTART)) { + + u8 addr = (msg->addr << 1); + + if (msg->flags & I2C_M_RD) + addr |= 1; + + i2c->state = STATE_START; + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, addr); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + return; + } else + { + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } + } else { + i2c->state = STATE_STOP; + fpgai2c_stop(i2c); + return; + } + } + + 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); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, i2c->pos == (msg->len-1) ? + 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++]); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE); + } +} + +static irqreturn_t fpgai2c_isr(int irq, void *dev_id) +{ + struct fpgalogic_i2c *i2c = dev_id; + fpgai2c_process(i2c); + + return IRQ_HANDLED; +} +void dell_get_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_lock(&i2c->lock); +} + +/** + * dell_release_mutex - release mutex + */ +void dell_release_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_unlock(&i2c->lock); +} + +static int fpgai2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct fpgalogic_i2c *i2c = i2c_get_adapdata(adap); + int ret; + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = (use_irq == 1) ? STATE_START : STATE_INIT; + + PRINT("i2c->msg->addr = 0x%x i2c->msg->flags = 0x%x\n",i2c->msg->addr,i2c->msg->flags); + PRINT("I2C_M_RD = 0x%x i2c->msg->addr << 1 = 0x%x\n",I2C_M_RD,i2c->msg->addr << 1); + + if (!use_irq) { + /* Handle the transfer */ + while (time_before(jiffies, timeout)) { + dell_get_mutex(i2c); + ret = fpgai2c_poll(i2c); + dell_release_mutex(i2c); + + if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) + return (i2c->state == STATE_DONE) ? num : ret; + + if (ret == 0) + timeout = jiffies + HZ; + + usleep_range(5, 15); + } + + i2c->state = STATE_ERROR; + + return -ETIMEDOUT; + + + } 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)); + + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, + (i2c->msg->addr << 1) | + ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + + /* Interrupt mode */ + if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || + (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; + } + } + + 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; + } + + 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; +} + +static const struct i2c_algorithm fpgai2c_algorithm = { + .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; +} + +static int i2c_init_internal_data(void) +{ + 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; +} + + +static int i2c_pci_init (void) +{ + int i; + + if (num_bus == 0) { + board_rev_type = ioread32(fpga_ctl_addr + MB_BRD_REV_TYPE); + + 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)) { + switch (board_rev_type & MB_BRD_TYPE_MASK){ + case BRD_TYPE_S5212_NON_NEBS: + case BRD_TYPE_S5212_NEBS: + num_bus = I2C_PCI_BUS_NUM_5; + break; + case BRD_TYPE_S5224_NON_NEBS: + case BRD_TYPE_S5224_NEBS: + num_bus = I2C_PCI_BUS_NUM_7; + break; + case BRD_TYPE_Z9232_NON_NEBS: + case BRD_TYPE_Z9232_NEBS: + case BRD_TYPE_S5232_NON_NEBS: + case BRD_TYPE_S5232_NEBS: + num_bus = I2C_PCI_BUS_NUM_8; + break; + case BRD_TYPE_S5248_NON_NEBS: + case BRD_TYPE_S5248_NEBS: + num_bus = I2C_PCI_BUS_NUM_10; + break; + case BRD_TYPE_Z9264_NON_NEBS: + case BRD_TYPE_Z9264_NEBS: + num_bus = I2C_PCI_BUS_NUM_12; + break; + case BRD_TYPE_S5296_NON_NEBS: + case BRD_TYPE_S5296_NEBS: + num_bus = I2C_PCI_BUS_NUM_16; + break; + default: + num_bus = I2C_PCI_BUS_NUM_16; + printk("Wrong BRD_TYPE: 0x%x\n", board_rev_type); + break; + } + } else { + printk("Wrong board_rev_type 0x%x\n", board_rev_type); + } + } + + 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]); + + /* Initialize driver's itnernal data structures */ + i2c_init_internal_data(); + + 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].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)); + } + + 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]); + } + +} + +/* Find upstream PCIe root node. + * 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; + } +} + + +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); + } + } + + return 0; +} + + +/** + * Map the device memory regions into kernel virtual address space + * after verifying their sizes respect the minimum sizes needed, given + * by the bar_min_len[] array. + */ +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + 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; + + + 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; + } + + 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); + + 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); + + 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; +} + +static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + int i; + + 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" + +/** + * @brief Register specific function with msi interrupt line + * @param dev Pointer to pci-device, which should be allocated + * @param int interrupt number relative to global interrupt number + * @return Returns error code or zero if success + * */ +static int register_intr_handler(struct pci_dev *dev, int irq_num_id) +{ + 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; + } + + 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 + * 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_6: + err = request_irq(dev->irq + irq_num_id, fpgaport_65_66_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 */ + 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_6: + err = request_irq(dev->irq + irq_num_id, fpgaport_65_66_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; +} +/* Mask for MSI Multi message enable bits */ +#define MSI_MME 0x70 +/** + * These enums define the type of interrupt scheme that the overall + * system uses. + */ +enum fpga_irq_type { + INT_MSI_SINGLE, + INT_MSI_MULTI, + INT_MSIX, + INT_NONE, + INT_FENCE /* Last item to guard from loop run-overs */ +}; +/** + * @def PCI_DEVICE_STATUS + * define the offset for STS register + * from the start of PCI config space as specified in the + * NVME_Comliance 1.0b. offset 06h:STS - Device status. + * This register has error status for NVME PCI Exress + * Card. After reading data from this reagister, the driver + * will identify if any error is set during the operation and + * report as kernel alert message. + */ +#define PCI_DEVICE_STATUS 0x6 +/** + * @def NEXT_MASK + * This indicates the location of the next capability item + * in the list. + */ +#define NEXT_MASK 0xFF00 +/** + * @def MSIXCAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSIXCAP_ID 0x11 +/** + * @def MSICAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSICAP_ID 0x5 + +/** + * @def CL_MASK + * This bit position indicates Capabilities List of the controller + * The controller should support the PCI Power Management cap as a + * minimum. + */ +#define CL_MASK 0x0010 + +/** + * @def CAP_REG + * Set to offset defined in NVME Spec 1.0b. + */ +#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; + + 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; + + + /* + * 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); + + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + } +} +/** + * @brief Enables pcie-device and claims/remaps neccessary bar resources + * @param dev Pointer to pci-device, which should be allocated + * @return Returns error code or zero if success + * */ +static int fpgapci_setup_device(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + 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; + } + + /* 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); + + /* 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); + + if (map_bars(fpgapci, dev)) { + goto fail_map_bars; + } + + i2c_pci_init(); + + return 0; + /* ERROR HANDLING */ +fail_map_bars: + pci_release_regions(dev); +error_pci_req: + pci_disable_device(dev); +error_pci_en: + return -ENODEV; +} + +static int fpgapci_configure_msi(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + int err = 0, i; + int request_vec; + + 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); + + 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)) { + if (err < MSI_VECTOR_REV_01) { + goto error_disable_msi; + } + } + } + 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; + } + } + + 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); + 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); +error_no_msi: + return -ENOSPC; +} + +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + 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)); +#endif + fpgapci = kzalloc(sizeof(struct fpgapci_dev), GFP_KERNEL); + + if (!fpgapci) { + PRINT( "Couldn't allocate memory!\n"); + goto fail_kzalloc; + } + + 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__); + } + + 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 */ +error_cannot_configure: + 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"); +fail_kzalloc: + 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); + 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]); + } + } + pci_disable_msi(fpgapci->pci_dev); + free_bars (fpgapci, dev); + pci_disable_device(dev); + pci_release_regions(dev); + + kfree (fpgapci); +} + +static const struct pci_device_id fpgapci_ids[] = { + {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 */ +}; + +/* Initialize the driver module (but not any device) and register + * the module with the kernel PCI subsystem. */ +static int __init fpgapci_init(void) +{ + + if (pci_register_driver(&fpgapci_driver)) { + PRINT("pci_unregister_driver\n"); + pci_unregister_driver(&fpgapci_driver); + return -ENODEV; + } + + return 0; +} + +static void __exit fpgapci_exit(void) +{ + PRINT ("fpgapci_exit"); + + /* unregister this driver from the PCI bus driver */ + pci_unregister_driver(&fpgapci_driver); + +} + + +module_init (fpgapci_init); +module_exit (fpgapci_exit); +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/z9264f/scripts/check_qsfp.sh b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/check_qsfp.sh new file mode 100755 index 000000000000..7e7f1636a186 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/check_qsfp.sh @@ -0,0 +1,3 @@ +# Temporary dummy file for z9264f. +# Will be updated soon. + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/platform_sensors.py new file mode 100755 index 000000000000..bcc13452a828 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/platform_sensors.py @@ -0,0 +1,263 @@ +#!/usr/bin/python3 +# On Z9264f, the BaseBoard Management Controller is an +# autonomous subsystem provides monitoring and management +# facility independent of the host CPU. IPMI standard +# protocol is used with ipmitool to fetch sensor details. +# Current script support X00 board only. X01 support will +# be added soon. This provies support for the +# following objects: +# * Onboard temperature sensors +# * FAN trays +# * PSU + + +import sys +import logging +import subprocess + +Z9264F_MAX_FAN_TRAYS = 4 +Z9264F_MAX_PSUS = 2 +IPMI_SENSOR_DATA = "ipmitool sdr list" +IPMI_SENSOR_DUMP = "/tmp/sdr" + +FAN_PRESENCE = "FAN{0}_prsnt" +PSU_PRESENCE = "PSU{0}_state" +# Use this for older firmware +# PSU_PRESENCE="PSU{0}_prsnt" +ipmi_sdr_list = "" + +# Dump sensor registers + + +def ipmi_sensor_dump(): + + status = 1 + global ipmi_sdr_list + ipmi_cmd = IPMI_SENSOR_DATA + status, ipmi_sdr_list = subprocess.getstatusoutput(ipmi_cmd) + + if status: + logging.error('Failed to execute:' + ipmi_sdr_list) + sys.exit(0) + +# Fetch a BMC register + + +def get_pmc_register(reg_name): + + for item in ipmi_sdr_list.split("\n"): + if reg_name in item: + output = item.strip() + + if not output: + print('\nFailed to fetch: ' + reg_name + ' sensor ') + sys.exit(0) + + output = output.split('|')[1] + + logging.basicConfig(level=logging.DEBUG) + return output + + +# Print the information for temperature sensors + + +def print_temperature_sensors(): + + print("\nOnboard Temperature Sensors:") + + print(' PT_Left_temp: ', + get_pmc_register('PT_Left_temp')) + print(' PT_Mid_temp: ', + get_pmc_register('PT_Mid_temp')) + print(' PT_Right_temp: ', + get_pmc_register('PT_Right_temp')) + print(' Broadcom Temp: ', + get_pmc_register('TC_Near_temp')) + print(' Inlet Airflow Temp: ', + get_pmc_register('ILET_AF_temp')) + print(' CPU Temp: ', + get_pmc_register('CPU_Near_temp')) + print(' CPU Near Temp: ', + get_pmc_register('CPU_temp')) + print(' PSU FAN AirFlow Temperature 1: ', + get_pmc_register('PSU1_AF_temp')) + print(' PSU FAN AirFlow Temperature 2: ', + get_pmc_register('PSU2_AF_temp')) + +ipmi_sensor_dump() + +print_temperature_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(tray): + + Fan_Status = [' Normal', ' Abnormal', ' no reading'] + Airflow_Direction = ['B2F', 'F2B'] + + print(' Fan Tray ' + str(tray) + ':') + + if (tray == 1): + + if(int(get_pmc_register('FAN1_prsnt'), 16)): + fan1_status = int(get_pmc_register('Fan1_Front_state'), 16) + fan2_status = int(get_pmc_register('Fan1_Rear_state'), 16) + # BMC taking some time to update + if(fan1_status > 2 or fan2_status > 2): + fan1_status = 2 + fan2_status = 2 + else: + fan1_status = 2 + fan2_status = 2 + + print(' Fan1 Speed: ', + get_pmc_register('FAN1_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN1_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + elif (tray == 2): + + if(int(get_pmc_register('FAN2_prsnt'), 16)): + fan1_status = int(get_pmc_register('Fan2_Front_state'), 16) + fan2_status = int(get_pmc_register('Fan2_Rear_state'), 16) + # BMC taking some time to update + if(fan1_status > 2 or fan2_status > 2): + fan1_status = 2 + fan2_status = 2 + else: + fan1_status = 2 + fan2_status = 2 + + print(' Fan1 Speed: ', + get_pmc_register('FAN2_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN2_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + elif (tray == 3): + + if(int(get_pmc_register('FAN3_prsnt'), 16)): + fan1_status = int(get_pmc_register('Fan3_Front_state'), 16) + fan2_status = int(get_pmc_register('Fan3_Rear_state'), 16) + # BMC taking some time to update + if(fan1_status > 2 or fan2_status > 2): + fan1_status = 2 + fan2_status = 2 + else: + fan1_status = 2 + fan2_status = 2 + + print(' Fan1 Speed: ', + get_pmc_register('FAN3_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN3_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + elif (tray == 4): + + if(int(get_pmc_register('FAN4_prsnt'), 16)): + fan1_status = int(get_pmc_register('Fan4_Front_state'), 16) + fan2_status = int(get_pmc_register('Fan4_Rear_state'), 16) + # BMC taking some time to update + if(fan1_status > 2 or fan2_status > 2): + fan1_status = 2 + fan2_status = 2 + else: + fan1_status = 2 + fan2_status = 2 + + print(' Fan1 Speed: ', + get_pmc_register('FAN4_Front_rpm')) + print(' Fan2 Speed: ', + get_pmc_register('FAN4_Rear_rpm')) + print(' Fan1 State: ', + Fan_Status[fan1_status]) + print(' Fan2 State: ', + Fan_Status[fan2_status]) + + +print('\nFan Trays:') + +for tray in range(1, Z9264F_MAX_FAN_TRAYS + 1): + fan_presence = FAN_PRESENCE.format(tray) + if (get_pmc_register(fan_presence)): + print_fan_tray(tray) + else: + print('\n Fan Tray ' + str(tray + 1) + ': Not present') + + +# Print the information for PSU1, PSU2 +def print_psu(psu): + + # PSU FAN details + if (psu == 1): + + print(' PSU1:') + print(' FAN Normal Temperature: ', + get_pmc_register('PSU1_Normal_temp')) + print(' Chassis Temperature: ', + get_pmc_register('PSU1_Chass_temp')) + print(' System Temperature: ', + get_pmc_register('PSU1_Sys_temp')) + print(' FAN RPM: ', + get_pmc_register('PSU1_rpm')) + print(' Input Voltage: ', + get_pmc_register('PSU1_In_volt')) + print(' Output Voltage: ', + get_pmc_register('PSU1_Out_volt')) + print(' Input Power: ', + get_pmc_register('PSU1_In_watt')) + print(' Output Power: ', + get_pmc_register('PSU1_Out_watt')) + print(' Input Current: ', + get_pmc_register('PSU1_In_amp')) + print(' Output Current: ', + get_pmc_register('PSU1_Out_amp')) + + else: + + print(' PSU2:') + print(' FAN Normal Temperature: ', + get_pmc_register('PSU2_Normal_temp')) + print(' Chassis Temperature: ', + get_pmc_register('PSU2_Chass_temp')) + print(' System Temperature: ', + get_pmc_register('PSU2_Sys_temp')) + print(' FAN RPM: ', + get_pmc_register('PSU2_rpm')) + print(' Input Voltage: ', + get_pmc_register('PSU2_In_volt')) + print(' Output Voltage: ', + get_pmc_register('PSU2_Out_volt')) + print(' Input Power: ', + get_pmc_register('PSU2_In_watt')) + print(' Output Power: ', + get_pmc_register('PSU2_Out_watt')) + print(' Input Current: ', + get_pmc_register('PSU2_In_amp')) + print(' Output Current: ', + get_pmc_register('PSU2_Out_amp')) + + +print('\nPSUs:') +for psu in range(1, Z9264F_MAX_PSUS + 1): + psu_presence = PSU_PRESENCE.format(psu) + if (get_pmc_register(psu_presence)): + print_psu(psu) + else: + print('\n PSU ', psu, 'Not present') + +print('\n Total Power: ', + get_pmc_register('PSU_Total_watt')) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/port_irq_enable.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/port_irq_enable.py new file mode 100755 index 000000000000..ff9d9ce8d723 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/port_irq_enable.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +try: + import struct + from os import * + from mmap import * + +except ImportError as e: + raise ImportError("%s - required module no found" % str(e)) + +BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" +PORT_START = 0 +PORT_END = 64 + + +def pci_mem_write(mm, offset, data): + mm.seek(offset) + mm.write(struct.pack('I', data)) + + +def pci_set_value(resource, val, offset): + fd = open(resource, O_RDWR) + mm = mmap(fd, 0) + val = pci_mem_write(mm, offset, val) + mm.close() + close(fd) + return val + +# Enabled interrupt for qsfp and sfp +for port_num in range(PORT_START, PORT_END+1): + port_offset = 0x400c + ((port_num) * 16) + pci_set_value(BASE_RES_PATH, 0x31, port_offset) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/sensors new file mode 100755 index 000000000000..ee53f2b0f325 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/sensors @@ -0,0 +1,8 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" +docker exec -i pmon /usr/bin/platform_sensors.py "$@" + +#To probe sensors not part of lm-sensors +#if [ -r /usr/local/bin/platform_sensors.py ]; then +# python /usr/local/bin/platform_sensors.py +#fi diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/z9264f_platform.sh b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/z9264f_platform.sh new file mode 100755 index 000000000000..8469b844757b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/scripts/z9264f_platform.sh @@ -0,0 +1,249 @@ +#!/bin/bash + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find iSMT" && exit 1 +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + case $1 in + "new_device") echo 24c16 0x50 > /sys/bus/i2c/devices/i2c-${devnum}/$1 + ;; + "delete_device") echo 0x50 > /sys/bus/i2c/devices/i2c-${devnum}/$1 + ;; + *) echo "z9264f_platform: sys_eeprom : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs +switch_board_qsfp_mux() { + case $1 in + "new_device") + for ((i=603;i<=611;i++)); + do + echo "Attaching PCA9548 @ 0x74" + echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-$i/$1 + done + + ;; + "delete_device") + for ((i=603;i<=611;i++)); + do + echo "Detaching PCA9548 @ 0x74" + echo 0x74 > /sys/bus/i2c/devices/i2c-$i/$1 + done + + ;; + *) echo "z9264f_platform: switch_board_qsfp_mux: invalid command !" + ;; + esac + sleep 2 +} + +#Attach/Detach 64 instances of EEPROM driver QSFP ports +#eeprom can dump data using below command +switch_board_qsfp() { + case $1 in + "new_device") + for ((i=2;i<=65;i++)); + do + echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=2;i<=65;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "z9264f_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +#Attach/Detach 2 instances of EEPROM driver SFP+ ports +#eeprom can dump data using below command +switch_board_sfp() { + case $1 in + "new_device") + for ((i=66;i<=67;i++)); + do + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=66;i<=67;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "z9264f_platform: switch_board_sfp: invalid command !" + ;; + esac +} + +#Modsel 64 ports to applicable QSFP type modules +#This enables the adapter to respond for i2c commands +switch_board_modsel() { + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + for ((i=1;i<=64;i++)); + do + port_addr=$(( 16384 + ((i - 1) * 16))) + hex=$( printf "0x%x" $port_addr ) + /usr/bin/pcisysfs.py --set --offset $hex --val 0x10 --res $resource > /dev/null 2>&1 + done + + # Disabling low power mode for last two 10G ports + # From last 6th bit: Disable - 0; Enable - 1 + reg_offset=$(/usr/bin/pcisysfs.py --get --offset 0x4400 --res $resource | cut -d':' -f 2) + reg_offset=$( printf '0x%s' $reg_offset) + reg_offset=$( printf '0x%x' $(( $reg_offset & 0xbf )) ) + /usr/bin/pcisysfs.py --set --offset 0x4400 --val $reg_offset --res $resource > /dev/null 2>&1 + + reg_offset=$(/usr/bin/pcisysfs.py --get --offset 0x4410 --res $resource | cut -d':' -f 2) + reg_offset=$( printf '0x%s' $reg_offset) + reg_offset=$( printf '0x%x' $(( $reg_offset & 0xbf )) ) + /usr/bin/pcisysfs.py --set --offset 0x4410 --val $reg_offset --res $resource > /dev/null 2>&1 +} + +# Copy led_proc_init.soc file according to the HWSKU +init_switch_port_led() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + hwsku=$(cat /etc/sonic/config_db.json | grep -A10 "DEVICE_METADATA" | grep "hwsku" | cut -d ":" -f2 | sed 's/"//g' | sed 's/,//g'| xargs ) + + led_proc_init="$device/$platform/$hwsku/led_proc_init.soc" + + # Remove old HWSKU LED file.. + rm -rf $device/$platform/led_proc_init.soc + + if [ -e $led_proc_init ] && [ ! -e $device/$platform/led_proc_init.soc ]; then + cp $led_proc_init $device/$platform/ + fi +} + +install_python_api_package() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip install $device/$platform/sonic_platform-1.0-py2-none-any.whl) + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) +} + +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) + fi + + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -eq 0 ]; then + rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null) + fi +} + +# 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 4 0x33 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 +} + +get_reboot_cause() { + REBOOT_REASON_FILE="/host/reboot-cause/platform/reboot_reason" + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + + # Handle First Boot into software version with reboot cause determination support + if [[ ! -e $REBOOT_REASON_FILE ]]; then + echo "0" > $REBOOT_REASON_FILE + else + /usr/bin/pcisysfs.py --get --offset 0x18 --res $resource | sed '1d; s/.*:\(.*\)$/\1/;' > $REBOOT_REASON_FILE + fi + /usr/bin/pcisysfs.py --set --val 0x0 --offset 0x18 --res $resource +} + +init_devnum + +if [ "$1" == "init" ]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe ipmi_devintf + modprobe ipmi_si + modprobe i2c_ocores + modprobe dell_z9264f_fpga_ocores + sys_eeprom "new_device" + get_reboot_cause + switch_board_qsfp_mux "new_device" + switch_board_qsfp "new_device" + switch_board_sfp "new_device" + switch_board_modsel + init_switch_port_led + install_python_api_package + /usr/bin/port_irq_enable.py + platform_firmware_versions + + +elif [ "$1" == "deinit" ]; then + sys_eeprom "delete_device" + switch_board_qsfp "delete_device" + switch_board_qsfp_mux "delete_device" + switch_board_sfp "delete_device" + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev + remove_python_api_package +else + echo "z9264f_platform : Invalid option !" +fi + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/setup.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/setup.py new file mode 120000 index 000000000000..4f6de9941d96 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/setup.py @@ -0,0 +1 @@ +../s6100/setup.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/__init__.py new file mode 100644 index 000000000000..4f5d4f6e473d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer"] +from sonic_platform import * diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/chassis.py new file mode 100644 index 000000000000..78e8dea999c8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/chassis.py @@ -0,0 +1,307 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC Z9264F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import select + import sys + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.eeprom import Eeprom + from sonic_platform.component import Component + from sonic_platform.psu import Psu + from sonic_platform.watchdog import Watchdog + from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.thermal import Thermal +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MAX_Z9264F_FANTRAY =4 +MAX_Z9264F_COMPONENT = 8 # BIOS,BMC,FPGA,SYSTEM CPLD,4 SLAVE CPLDs +MAX_Z9264F_PSU = 2 +MAX_Z9264F_THERMAL = 8 + + +class Chassis(ChassisBase): + """ + DELLEMC Platform-specific Chassis class + """ + + REBOOT_CAUSE_PATH = "/host/reboot-cause/platform/reboot_reason" + OIR_FD_PATH = "/sys/bus/pci/devices/0000:04:00.0/port_msi" + + oir_fd = -1 + epoll = -1 + + _global_port_pres_dict = {} + + def __init__(self): + ChassisBase.__init__(self) + # sfp.py will read eeprom contents and retrive the eeprom data. + # We pass the eeprom path from chassis.py + self.PORT_START = 1 + self.PORT_END = 66 + PORTS_IN_BLOCK = (self.PORT_END + 1) + _sfp_port = list(range(65, self.PORT_END + 1)) + eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for index in range(self.PORT_START, PORTS_IN_BLOCK): + port_num = index + 1 + eeprom_path = eeprom_base.format(port_num) + if index not in _sfp_port: + sfp_node = Sfp(index, 'QSFP', eeprom_path) + else: + sfp_node = Sfp(index, 'SFP', eeprom_path) + self._sfp_list.append(sfp_node) + + self._eeprom = Eeprom() + + self._watchdog = Watchdog() + + for i in range(MAX_Z9264F_COMPONENT): + component = Component(i) + self._component_list.append(component) + + for i in range(MAX_Z9264F_PSU): + psu = Psu(i) + self._psu_list.append(psu) + + for i in range(MAX_Z9264F_FANTRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + for i in range(MAX_Z9264F_THERMAL): + thermal = Thermal(i) + self._thermal_list.append(thermal) + + for port_num in range(self.PORT_START, (self.PORT_END + 1)): + presence = self.get_sfp(port_num).get_presence() + if presence: + self._global_port_pres_dict[port_num] = '1' + else: + self._global_port_pres_dict[port_num] = '0' + + def __del__(self): + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + + def _get_register(self, reg_file): + retval = 'ERR' + if (not os.path.isfile(reg_file)): + print(reg_file, 'not found !') + return retval + + try: + with os.fdopen(os.open(reg_file, os.O_RDONLY)) as fd: + retval = fd.read() + except Exception: + pass + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + + def _check_interrupts(self, port_dict): + retval = 0 + is_port_dict_updated = False + for port_num in range(self.PORT_START, (self.PORT_END + 1)): + sfp = self.get_sfp(port_num) + presence = sfp.get_presence() + if(presence and (self._global_port_pres_dict[port_num] == '0')): + is_port_dict_updated = True + 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')): + is_port_dict_updated = True + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + return retval, is_port_dict_updated + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + """ + port_dict = {} + change_dict = {} + change_dict['sfp'] = port_dict + if timeout != 0: + timeout = timeout / 1000 + try: + # We get notified when there is a MSI interrupt (vector 4/5)CVR + # Open the sysfs file and register the epoll object + self.oir_fd = os.fdopen(os.open(self.OIR_FD_PATH, os.O_RDONLY)) + if self.oir_fd != -1: + # Do a dummy read before epoll register + self.oir_fd.read() + self.epoll = select.epoll() + self.epoll.register( + self.oir_fd.fileno(), select.EPOLLIN & select.EPOLLET) + else: + print("get_transceiver_change_event : unable to create fd") + return False, change_dict + # Check for missed interrupts by invoking self._check_interrupts + # which will update the port_dict. + while True: + interrupt_count_start = self._get_register(self.OIR_FD_PATH) + retval, is_port_dict_updated = self._check_interrupts(port_dict) + if ((retval == 0) and (is_port_dict_updated is True)): + return True, change_dict + interrupt_count_end = self._get_register(self.OIR_FD_PATH) + if (interrupt_count_start == 'ERR' or + interrupt_count_end == 'ERR'): + print("get_transceiver_change_event : \ + unable to retrive interrupt count") + break + # check_interrupts() itself may take upto 100s of msecs. + # We detect a missed interrupt based on the count + if interrupt_count_start == interrupt_count_end: + break + # Block until an xcvr is inserted or removed with timeout = -1 + events = self.epoll.poll( + timeout=timeout if timeout != 0 else -1) + if events: + # check interrupts and return the change_dict + retval, is_port_dict_updated = \ + self._check_interrupts(port_dict) + if (retval != 0): + return False, change_dict + return True, change_dict + except Exception: + return False, change_dict + finally: + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + self.oir_fd = -1 + self.epoll = -1 + + 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, 1 for Ethernet0, 2 for Ethernet4 and so on. + + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + + try: + # The index will start from 1 + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + return sfp + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + try: + with open(self.REBOOT_CAUSE_PATH) as fd: + reboot_cause = int(fd.read(), 16) + except Exception: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + if reboot_cause & 0x1: + return (self.REBOOT_CAUSE_POWER_LOSS, None) + elif reboot_cause & 0x2: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + elif reboot_cause & 0x4: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "PSU Shutdown") + elif reboot_cause & 0x8: + return (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, None) + elif reboot_cause & 0x10: + return (self.REBOOT_CAUSE_WATCHDOG, None) + elif reboot_cause & 0x20: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "BMC Shutdown") + elif reboot_cause & 0x40: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Hot-Swap Shutdown") + elif reboot_cause & 0x80: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Shutdown") + elif reboot_cause & 0x100: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Cold Reboot") + else: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/component.py new file mode 100644 index 000000000000..c4e2c06b135c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/component.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC Z9264F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, BMC etc.) available in +# the platform +# +######################################################################## + +try: + import re + from sonic_platform_base.component_base import ComponentBase + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FIRMWARE_VERSION_FILE="/var/log/firmware_versions" + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["FPGA", ("Used for managing the system LEDs")], + ["BMC", ("Platform management controller for on-board temperature " + "monitoring, in-chassis power, Fan and LED control")], + ["System CPLD", ("Used for managing the CPU power sequence and CPU states")], + ["Slave CPLD 1", ("Used for managing QSFP/QSFP28 port transceivers (1-16)")], + ["Slave CPLD 2", ("Used for managing QSFP/QSFP28 port transceivers (17-32)")], + ["Slave CPLD 3", ("Used for managing QSFP/QSFP28 port transceivers (33-48)")], + ["Slave CPLD 4", ("Used for managing QSFP/QSFP28 port transceivers (49-64) and SFP/SFP28 " + "port transceivers (65 and 66)")], + ] + + def __init__(self, component_index=0): + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + rv = "" + try: + fd = open(FIRMWARE_VERSION_FILE,"r") + except IOError: + return rv + version_contents = fd.read() + fd.close() + if not version_contents: + return rv + if self.index < 8: + version = re.search(r''+self.CHASSIS_COMPONENTS[self.index][0]+':(.*)',version_contents) + if version: + rv = version.group(1).strip() + return rv + + def install_firmware(self, image_path): + """ + Installs firmware to the component + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/eeprom.py new file mode 100644 index 000000000000..a1b51b8b41fe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/eeprom.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python + +############################################################################# +# DellEmc Z9264F +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import os.path + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.eeprom_path = None + for b in (0, 1): + f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b) + if os.path.exists(f): + self.eeprom_path = f + break + if self.eeprom_path is None: + return + super(Eeprom, self).__init__(self.eeprom_path, 0, '', True) + self.eeprom_tlv_dict = dict() + try: + self.eeprom_data = self.read_eeprom() + except: + self.eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % tlv[0] + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += tlv[6:6 + tlv[1]].decode('ascii') + else: + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + """ + Returns the serial number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self): + """ + Returns the base mac address found in the system EEPROM + """ + (is_valid, t) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join(["{:02x}".format(T) for T in t[2]]).upper() + + def modelstr(self): + """ + Returns the Model name + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + """ + Returns the part number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_str(self): + """ + Returns the servicetag number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + """ + Returns the device revision + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/fan.py new file mode 100644 index 000000000000..39307d453486 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/fan.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9264F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fans' information which are available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_base import FanBase + from sonic_platform.ipmihelper import IpmiSensor, IpmiFru +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +#Derived the offset from BMC management information +FAN1_MAX_SPEED_OFFSET = 71 +FAN2_MAX_SPEED_OFFSET = 73 +PSU_FAN_MAX_SPEED_OFFSET = 50 +FAN_DIRECTION_OFFSET = 69 +PSU_FAN_DIRECTION_OFFSET = 47 + + +class Fan(FanBase): + """DellEMC Platform-specific Fan class""" + #Derived the sensor IDs from BMC + # { FAN-ID: { Sensor-Name: Sensor-ID } } + FAN_SENSOR_MAPPING = { 1: {"Prsnt": 0x51, "State": 0x64, "Speed": 0x24}, + 2: {"Prsnt": 0x51, "State": 0x60, "Speed": 0x20}, + 3: {"Prsnt": 0x52, "State": 0x65, "Speed": 0x25}, + 4: {"Prsnt": 0x52, "State": 0x61, "Speed": 0x21}, + 5: {"Prsnt": 0x53, "State": 0x66, "Speed": 0x26}, + 6: {"Prsnt": 0x53, "State": 0x62, "Speed": 0x22}, + 7: {"Prsnt": 0x54, "State": 0x67, "Speed": 0x27}, + 8: {"Prsnt": 0x54, "State": 0x63, "Speed": 0x23} } + PSU_FAN_SENSOR_MAPPING = { 1: {"State": 0x46, "Speed": 0x2e}, + 2: {"State": 0x47, "Speed": 0x2f} } + + # { FANTRAY-ID: FRU-ID } + FAN_FRU_MAPPING = { 1: 1, 2: 2, 3: 3, 4: 4 } + PSU_FRU_MAPPING = { 1: 6, 2: 7 } + + def __init__(self, fantray_index=1, fan_index=1, psu_fan=False, + dependency=None): + self.is_psu_fan = psu_fan + if not self.is_psu_fan: + # API index is starting from 0, DellEMC platform index is + # starting from 1 + self.fantrayindex = fantray_index + 1 + self.fanindex = fan_index + 1 + if (self.fanindex == 1): + self.max_speed_offset = FAN1_MAX_SPEED_OFFSET + else: + self.max_speed_offset = FAN2_MAX_SPEED_OFFSET + self.fan_direction_offset = FAN_DIRECTION_OFFSET + self.index = (self.fantrayindex - 1) * 2 + self.fanindex + self.prsnt_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Prsnt"], + is_discrete=True) + self.state_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["State"], + is_discrete=True) + self.speed_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Speed"]) + self.fru = IpmiFru(self.FAN_FRU_MAPPING[self.fantrayindex]) + else: + self.dependency = dependency + self.fanindex = fan_index + self.state_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["State"], + is_discrete=True) + self.speed_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["Speed"]) + self.fru = IpmiFru(self.PSU_FRU_MAPPING[self.fanindex]) + self.max_speed_offset = PSU_FAN_MAX_SPEED_OFFSET + self.fan_direction_offset = PSU_FAN_DIRECTION_OFFSET + self.max_speed = self.fru.get_fru_data(self.max_speed_offset,2)[1] + self.max_speed = self.max_speed[1] << 8 | self.max_speed[0] + + def get_name(self): + """ + Retrieves the name of the device + Returns: + String: The name of the device + """ + if self.is_psu_fan: + return "PSU{} Fan".format(self.fanindex) + else: + return "FanTray{}-Fan{}".format(self.fantrayindex, self.fanindex) + + def get_model(self): + """ + Retrieves the part number of the FAN + Returns: + String: Part number of FAN + """ + if self.is_psu_fan: + return 'NA' + else: + return self.fru.get_board_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the FAN + Returns: + String: Serial number of FAN + """ + if self.is_psu_fan: + return 'NA' + else: + return self.fru.get_board_serial() + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if fan is present, False if not + """ + presence = False + if self.is_psu_fan: + return self.dependency.get_presence() + else: + is_valid, state = self.prsnt_sensor.get_reading() + if is_valid: + if (state & 0b1): + presence = True + return presence + + def get_status(self): + """ + Retrieves the operational status of the FAN + Returns: + bool: True if FAN is operating properly, False if not + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if (state == 0x00): + status = True + return status + + def get_direction(self): + """ + Retrieves the fan airfow direction + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + In DellEMC platforms, + - Forward/Exhaust : Air flows from Port side to Fan side. + - Reverse/Intake : Air flows from Fan side to Port side. + """ + direction = [self.FAN_DIRECTION_EXHAUST, self.FAN_DIRECTION_INTAKE] + fan_status = self.get_status() + if not fan_status: + return 'NA' + is_valid, fan_direction = self.fru.get_fru_data(self.fan_direction_offset) + if is_valid: + return direction[fan_direction[0]] + else: + return 'NA' + + def get_speed(self): + """ + Retrieves the speed of the fan + Returns: + int: percentage of the max fan speed + """ + if self.max_speed == 0: + self.max_speed = self.fru.get_fru_data(self.max_speed_offset,2)[1] + self.max_speed = self.max_speed[1] << 8 | self.max_speed[0] + is_valid, fan_speed = self.speed_sensor.get_reading() + if not is_valid or self.max_speed == 0: + speed = 0 + else: + speed = (100 * fan_speed)//self.max_speed + return speed diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..6e8acfa720a4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/fan_drawer.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9264F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +Z9264F_FANS_PER_FANTRAY = 2 + + +class FanDrawer(FanDrawerBase): + """DellEMC Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + # FanTray is 1-based in DellEMC platforms + self.fantrayindex = fantray_index + 1 + for i in range(Z9264F_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/platform.py new file mode 100644 index 000000000000..996d94cf5a6e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/platform.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """ + DELLEMC Platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/psu.py new file mode 100644 index 000000000000..d46d24d0cb91 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/psu.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9264 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.ipmihelper import IpmiSensor, IpmiFru + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Psu(PsuBase): + """DellEMC Platform-specific PSU class""" + + # { PSU-ID: { Sensor-Name: Sensor-ID } } + SENSOR_MAPPING = { 1: { "State": 0x31, "Current": 0x39, + "Power": 0x37, "Voltage": 0x38 }, + 2: { "State": 0x32, "Current": 0x3F, + "Power": 0x3D, "Voltage": 0x3E } } + # ( PSU-ID: FRU-ID } + FRU_MAPPING = { 1: 6, 2: 7 } + + def __init__(self, psu_index): + PsuBase.__init__(self) + # PSU is 1-based in DellEMC platforms + self.index = psu_index + 1 + self.state_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["State"], + is_discrete=True) + self.voltage_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Voltage"]) + self.current_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Current"]) + self.power_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Power"]) + self.fru = IpmiFru(self.FRU_MAPPING[self.index]) + + self._fan_list.append(Fan(fan_index=self.index, psu_fan=True, + dependency=self)) + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + presence = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if (state & 0b1): + presence = True + + return presence + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + return self.fru.get_board_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + return self.fru.get_board_serial() + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if (state == 0x01): + status = True + + return status + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + is_valid, voltage = self.voltage_sensor.get_reading() + if not is_valid: + voltage = 0 + + return float(voltage) + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + is_valid, current = self.current_sensor.get_reading() + if not is_valid: + current = 0 + + return float(current) + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + is_valid, power = self.power_sensor.get_reading() + if not is_valid: + power = 0 + + return float(power) + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if (state == 0x01): + status = True + + return status diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/sfp.py new file mode 100644 index 000000000000..bdd7d0278ca2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/sfp.py @@ -0,0 +1,1046 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import time + import struct + import mmap + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8472 import sffbase + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PAGE_OFFSET = 0 +KEY_OFFSET = 1 +KEY_WIDTH = 2 +FUNC_NAME = 3 + +QSFP_INFO_OFFSET = 128 +QSFP_DOM_OFFSET = 0 +QSFP_DOM_OFFSET1 = 384 + +SFP_INFO_OFFSET = 0 +SFP_DOM_OFFSET = 256 + +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 7 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', + 'Length OM1(m)', 'Length Cable Assembly(m)') + +qsfp_compliance_code_tup = ( + '10/40G Ethernet Compliance Code', + 'SONET Compliance codes', + 'SAS/SATA compliance codes', + 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', + 'Fibre Channel Speed') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthOM3(UnitsOf10m)', 'LengthCable(UnitsOfm)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +info_dict_keys = ['type', 'hardware_rev', 'serial', + 'manufacturer', 'model', 'connector', + 'encoding', 'ext_identifier', 'ext_rateselect_compliance', + 'cable_type', 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'type_abbrv_name','vendor_date', 'vendor_oui'] + +dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', + 'power_lpmode', 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', 'rx1power', + 'rx2power', 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', 'tx3bias', + 'tx4bias', 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + +threshold_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning'] + +sff8436_parser = { + 'reset_status': [QSFP_DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'], + 'rx_los': [QSFP_DOM_OFFSET, 3, 1, 'parse_dom_tx_rx_los'], + 'tx_fault': [QSFP_DOM_OFFSET, 4, 1, 'parse_dom_tx_fault'], + 'tx_disable': [QSFP_DOM_OFFSET, 86, 1, 'parse_dom_tx_disable'], + 'power_lpmode': [QSFP_DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'power_override': [QSFP_DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'Temperature': [QSFP_DOM_OFFSET, 22, 2, 'parse_temperature'], + 'Voltage': [QSFP_DOM_OFFSET, 26, 2, 'parse_voltage'], + 'ChannelMonitor': [QSFP_DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'], + 'ChannelMonitor_TxPower': + [QSFP_DOM_OFFSET, 34, 24, 'parse_channel_monitor_params_with_tx_power'], + + 'cable_type': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'encoding': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_identifier': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'specification_compliance': + [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type_abbrv_name': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'manufacturer': [QSFP_INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [QSFP_INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [QSFP_INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [QSFP_INFO_OFFSET, 56, 2, 'parse_vendor_rev'], + 'serial': [QSFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [QSFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'dom_capability': [QSFP_INFO_OFFSET, 92, 1, 'parse_dom_capability'], + 'dom_rev': [QSFP_DOM_OFFSET, 1, 1, 'parse_sfp_dom_rev'], + 'ModuleThreshold': [QSFP_DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'], + 'ChannelThreshold': [QSFP_DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'], +} + +sff8472_parser = { + 'Temperature': [SFP_DOM_OFFSET, 96, 2, 'parse_temperature'], + 'Voltage': [SFP_DOM_OFFSET, 98, 2, 'parse_voltage'], + 'ChannelMonitor': [SFP_DOM_OFFSET, 100, 6, 'parse_channel_monitor_params'], + + 'cable_type': [SFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [SFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'type': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'encoding': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'ext_identifier': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'specification_compliance': + [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'type_abbrv_name': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'manufacturer': [SFP_INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [SFP_INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [SFP_INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [SFP_INFO_OFFSET, 56, 4, 'parse_vendor_rev'], + 'serial': [SFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [SFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'ModuleThreshold': [SFP_DOM_OFFSET, 0, 56, 'parse_alarm_warning_threshold'], +} + + +class Sfp(SfpBase): + """ + DELLEMC Platform-specific Sfp class + """ + BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" + OIR_FD_PATH = "/sys/bus/pci/devices/0000:04:00.0/port_msi" + + def __init__(self, index, sfp_type, eeprom_path): + SfpBase.__init__(self) + self.sfp_type = sfp_type + self.index = index + self.eeprom_path = eeprom_path + self.qsfpInfo = sff8436InterfaceId() + self.qsfpDomInfo = sff8436Dom() + self.sfpInfo = sff8472InterfaceId() + self.sfpDomInfo = sff8472Dom(None,1) + + def pci_mem_read(self, mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + reg_val = struct.unpack('I', read_data_stream) + mem_val = str(reg_val)[1:-2] + # print "reg_val read:%x"%reg_val + return mem_val + + def pci_mem_write(self, mm, offset, data): + mm.seek(offset) + # print "data to write:%x"%data + mm.write(struct.pack('I', data)) + + def pci_set_value(self, resource, val, offset): + fd = os.open(resource, os.O_RDWR) + mm = mmap.mmap(fd, 0) + val = self.pci_mem_write(mm, offset, val) + mm.close() + os.close(fd) + return val + + def pci_get_value(self, resource, offset): + fd = os.open(resource, os.O_RDWR) + mm = mmap.mmap(fd, 0) + val = self.pci_mem_read(mm, offset) + mm.close() + os.close(fd) + return val + + def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes): + eeprom_raw = [] + try: + eeprom = open(eeprom_path, mode="rb", buffering=0) + except IOError: + return None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom.seek(offset) + raw = eeprom.read(num_bytes) + except IOError: + eeprom.close() + return None + + try: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except BaseException: + eeprom.close() + return None + + eeprom.close() + return eeprom_raw + + def _get_eeprom_data(self, eeprom_key): + eeprom_data = None + page_offset = None + + if(self.sfp_type == 'QSFP'): + page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8436_parser[eeprom_key][PAGE_OFFSET] + + sff8436_parser[eeprom_key][KEY_OFFSET]), + sff8436_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 128 is used to retrieve sff8436InterfaceId Info + # Offset 0 is used to retrieve sff8436Dom Info + if (page_offset == 128): + if ( self.qsfpInfo is None): + return None + eeprom_data = getattr( + self.qsfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + if ( self.qsfpDomInfo is None): + return None + eeprom_data = getattr( + self.qsfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + page_offset = sff8472_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8472_parser[eeprom_key][PAGE_OFFSET] + + sff8472_parser[eeprom_key][KEY_OFFSET]), + sff8472_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 0 is used to retrieve sff8472InterfaceId Info + # Offset 256 is used to retrieve sff8472Dom Info + if (page_offset == 0): + if ( self.sfpInfo is None): + return None + eeprom_data = getattr( + self.sfpInfo, sff8472_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + if ( self.sfpDomInfo is None): + return None + eeprom_data = getattr( + self.sfpDomInfo, sff8472_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + + return eeprom_data + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + """ + transceiver_info_dict = {} + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A') + # BaseInformation + iface_data = self._get_eeprom_data('type') + if (iface_data is not None): + connector = iface_data['data']['Connector']['value'] + encoding = iface_data['data']['EncodingCodes']['value'] + ext_id = iface_data['data']['Extended Identifier']['value'] + rate_identifier = iface_data['data']['RateIdentifier']['value'] + identifier = iface_data['data']['type']['value'] + type_abbrv_name=iface_data['data']['type_abbrv_name']['value'] + if(self.sfp_type == 'QSFP'): + bit_rate = str( + iface_data['data']['Nominal Bit Rate(100Mbs)']['value']) + for key in qsfp_compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in qsfp_cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + else: + bit_rate = str( + iface_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + for key in sfp_compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in sfp_cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + else: + return transceiver_info_dict + + # Vendor Date + vendor_date_data = self._get_eeprom_data('vendor_date') + if (vendor_date_data is not None): + vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + else: + return transceiver_info_dict + + # Vendor Name + vendor_name_data = self._get_eeprom_data('manufacturer') + if (vendor_name_data is not None): + vendor_name = vendor_name_data['data']['Vendor Name']['value'] + else: + return transceiver_info_dict + + # Vendor OUI + vendor_oui_data = self._get_eeprom_data('vendor_oui') + if (vendor_oui_data is not None): + vendor_oui = vendor_oui_data['data']['Vendor OUI']['value'] + else: + return transceiver_info_dict + + # Vendor PN + vendor_pn_data = self._get_eeprom_data('model') + if (vendor_pn_data is not None): + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + else: + return transceiver_info_dict + + # Vendor Revision + vendor_rev_data = self._get_eeprom_data('hardware_rev') + if (vendor_rev_data is not None): + vendor_rev = vendor_rev_data['data']['Vendor Rev']['value'] + else: + return transceiver_info_dict + + # Vendor Serial Number + vendor_sn_data = self._get_eeprom_data('serial') + if (vendor_sn_data is not None): + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + else: + return transceiver_info_dict + + # Fill The Dictionary and return + transceiver_info_dict['type'] = identifier + transceiver_info_dict['hardware_rev'] = vendor_rev + transceiver_info_dict['serial'] = vendor_sn + transceiver_info_dict['manufacturer'] = vendor_name + transceiver_info_dict['model'] = vendor_pn + transceiver_info_dict['connector'] = connector + transceiver_info_dict['encoding'] = encoding + transceiver_info_dict['ext_identifier'] = ext_id + transceiver_info_dict['ext_rateselect_compliance'] = rate_identifier + transceiver_info_dict['cable_type'] = cable_type + transceiver_info_dict['cable_length'] = cable_length + transceiver_info_dict['nominal_bit_rate'] = bit_rate + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + transceiver_info_dict['vendor_date'] = vendor_date + transceiver_info_dict['vendor_oui'] = vendor_oui + transceiver_info_dict['type_abbrv_name']=type_abbrv_name + + return transceiver_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + """ + transceiver_dom_threshold_dict = {} + transceiver_dom_threshold_dict = dict.fromkeys( + threshold_dict_keys, 'N/A') + + # Module Threshold + module_threshold_data = self._get_eeprom_data('ModuleThreshold') + if (self.sfp_type == 'QSFP'): + # Channel Threshold + channel_threshold_data = self._get_eeprom_data('ChannelThreshold') + + if (channel_threshold_data is not None and module_threshold_data is not None): + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['data']['VccLowWarning']['value'] + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['data']['TxBiasLowWarning']['value'] + + else: + return transceiver_dom_threshold_dict + else: + #SFP + if (module_threshold_data is not None): + #Threshold Data + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['data']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['data']['VoltageLowWarning']['value'] + transceiver_dom_threshold_dict['txbiashighalarm'] = module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = module_threshold_data['data']['BiasLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['txpowerlowalarm'] = module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['txpowerhighwarning'] = module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_dict['txpowerlowwarning'] = module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_dict['rxpowerhighalarm'] = module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = module_threshold_data['data']['RXPowerLowWarning']['value'] + else: + return transceiver_dom_threshold_dict + + return transceiver_dom_threshold_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + """ + tx_bias_list = [] + rx_power_list = [] + transceiver_dom_dict = {} + transceiver_dom_dict = dict.fromkeys(dom_dict_keys, 'N/A') + + # RxLos + rx_los = self.get_rx_los() + + # TxFault + tx_fault = self.get_tx_fault() + + # ResetStatus + reset_state = self.get_reset_status() + + # LowPower Mode + lp_mode = self.get_lpmode() + + # TxDisable + tx_disable = self.get_tx_disable() + + # TxDisable Channel + tx_disable_channel = self.get_tx_disable_channel() + + # Temperature + temperature = self.get_temperature() + + # Voltage + voltage = self.get_voltage() + + # Channel Monitor + tx_power_list = self.get_tx_power() + + # tx bias + tx_bias_list = self.get_tx_bias() + + # rx power + rx_power_list = self.get_rx_power() + + if (len(tx_bias_list) != 0): + transceiver_dom_dict['tx1bias'] = tx_bias_list[0] + transceiver_dom_dict['tx2bias'] = tx_bias_list[1] + transceiver_dom_dict['tx3bias'] = tx_bias_list[2] + transceiver_dom_dict['tx4bias'] = tx_bias_list[3] + + if (len(rx_power_list) != 0): + transceiver_dom_dict['rx1power'] = rx_power_list[0] + transceiver_dom_dict['rx2power'] = rx_power_list[1] + transceiver_dom_dict['rx3power'] = rx_power_list[2] + transceiver_dom_dict['rx4power'] = rx_power_list[3] + + if (len(tx_power_list) != 0): + transceiver_dom_dict['tx1power'] = tx_power_list[0] + transceiver_dom_dict['tx2power'] = tx_power_list[1] + transceiver_dom_dict['tx3power'] = tx_power_list[2] + transceiver_dom_dict['tx4power'] = tx_power_list[3] + + transceiver_dom_dict['rx_los'] = rx_los + transceiver_dom_dict['tx_fault'] = tx_fault + transceiver_dom_dict['reset_status'] = reset_state + transceiver_dom_dict['power_lpmode'] = lp_mode + transceiver_dom_dict['tx_disable'] = tx_disable + transceiver_dom_dict['tx_disable_channel'] = tx_disable_channel + transceiver_dom_dict['temperature'] = temperature + transceiver_dom_dict['voltage'] = voltage + + return transceiver_dom_dict + + def get_name(self): + """ + Retrieves the name of the sfp + Returns : QSFP or QSFP+ or QSFP28 + """ + + iface_data = self._get_eeprom_data('type') + if (iface_data is not None): + identifier = iface_data['data']['type']['value'] + else: + return None + + return identifier + + def get_presence(self): + """ + Retrieves the presence of the sfp + Returns : True if sfp is present and false if it is absent + """ + # Check for invalid port_num + + # Port offset starts with 0x4004 + port_offset = 16388 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for presence + if(self.sfp_type == 'QSFP'): + mask = (1 << 4) + + # Mask off 1st bit for presence 65,66 + if (self.sfp_type == 'SFP'): + mask = (1 << 0) + # ModPrsL is active low + if reg_value & mask == 0: + return True + + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the sfp + """ + vendor_pn_data = self._get_eeprom_data('model') + if (vendor_pn_data is not None): + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + else: + return None + + return vendor_pn + + def get_serial(self): + """ + Retrieves the serial number of the sfp + """ + vendor_sn_data = self._get_eeprom_data('serial') + if (vendor_sn_data is not None): + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + else: + return None + + return vendor_sn + + def get_reset_status(self): + """ + Retrives the reset status of SFP + """ + reset_status = False + if (self.sfp_type == 'QSFP'): + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return reset_status + + # Mask off 4th bit for reset status + mask = (1 << 4) + + if ((reg_value & mask) == 0): + reset_status = True + else: + reset_status = False + + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + """ + rx_los = None + rx_los_list = [] + if (self.sfp_type == 'QSFP'): + rx_los_data = self._get_eeprom_data('rx_los') + if (rx_los_data is not None): + rx_los = rx_los_data['data']['Rx1LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx2LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx3LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + rx_los = rx_los_data['data']['Rx4LOS']['value'] + if (rx_los is 'On'): + rx_los_list.append(True) + else: + rx_los_list.append(False) + + if (rx_los_list[0] and rx_los_list[1] + and rx_los_list[2] and rx_los_list[3]): + rx_los = True + else: + rx_los = False + else: + rx_los_data = self._read_eeprom_bytes(self.eeprom_path, SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if (rx_los_data is not None): + data = int(rx_los_data[0], 16) + rx_los = (sffbase().test_bit(data, 1) != 0) + + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + """ + tx_fault = None + tx_fault_list = [] + if (self.sfp_type == 'QSFP'): + tx_fault_data = self._get_eeprom_data('tx_fault') + if (tx_fault_data is not None): + tx_fault = tx_fault_data['data']['Tx1Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx2Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx3Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + tx_fault = tx_fault_data['data']['Tx4Fault']['value'] + if (tx_fault is 'On'): + tx_fault_list.append(True) + else: + tx_fault_list.append(False) + + if (tx_fault_list[0] and tx_fault_list[1] + and tx_fault_list[2] and tx_fault_list[3]): + tx_fault = True + else: + tx_fault = False + + else: + tx_fault_data = self._read_eeprom_bytes(self.eeprom_path, SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if (tx_fault_data is not None): + data = int(tx_fault_data[0], 16) + tx_fault = (sffbase().test_bit(data, 2) != 0) + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + """ + tx_disable = None + tx_disable_list = [] + if (self.sfp_type == 'QSFP'): + tx_disable_data = self._get_eeprom_data('tx_disable') + if (tx_disable_data is not None): + tx_disable = tx_disable_data['data']['Tx1Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx2Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx3Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + tx_disable = tx_disable_data['data']['Tx4Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(True) + else: + tx_disable_list.append(False) + + if (tx_disable_list[0] and tx_disable_list[1] + and tx_disable_list[2] and tx_disable_list[3]): + tx_disable = True + else: + tx_disable = False + + else: + tx_disable_data = self._read_eeprom_bytes(self.eeprom_path, SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if (tx_disable_data is not None): + data = int(tx_disable_data[0], 16) + tx_disable_hard = (sffbase().test_bit(data, SFP_TX_DISABLE_HARD_BIT) != 0) + tx_disable_soft = (sffbase().test_bit(data, SFP_TX_DISABLE_SOFT_BIT) != 0) + tx_disable = tx_disable_hard | tx_disable_soft + + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + """ + tx_disable = None + tx_disable_list = [] + tx_disable_channel = 0 + + if (self.sfp_type == 'QSFP'): + tx_disable_data = self._get_eeprom_data('tx_disable') + if (tx_disable_data is not None): + tx_disable = tx_disable_data['data']['Tx1Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + tx_disable = tx_disable_data['data']['Tx2Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + tx_disable = tx_disable_data['data']['Tx3Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + tx_disable = tx_disable_data['data']['Tx4Disable']['value'] + if (tx_disable is 'On'): + tx_disable_list.append(1) + else: + tx_disable_list.append(0) + + bit4 = int(tx_disable_list[3]) * 8 + bit3 = int(tx_disable_list[2]) * 4 + bit2 = int(tx_disable_list[1]) * 2 + bit1 = int(tx_disable_list[0]) * 1 + + tx_disable_channel = hex(bit4 + bit3 + bit2 + bit1) + + return tx_disable_channel + + def get_lpmode(self): + """ + Retrieves the lpmode(low power mode) of this SFP + """ + lpmode_state = False + if (self.sfp_type == 'QSFP'): + + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return lpmode_state + + # Mask off 6th bit for lpmode + mask = (1 << 6) + + # LPMode is active high + if reg_value & mask == 0: + lpmode_state = False + else: + lpmode_state = True + + return lpmode_state + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + """ + power_override_state = False + + if (self.sfp_type == 'QSFP'): + power_override_data = self._get_eeprom_data('power_override') + if (power_override_data is not None): + power_override = power_override_data['data']['PowerOverRide']['value'] + if (power_override is 'On'): + power_override_state = True + else: + power_override_state = False + + return power_override_state + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + """ + temperature = None + + temperature_data = self._get_eeprom_data('Temperature') + if (temperature_data is not None): + temperature = temperature_data['data']['Temperature']['value'] + + return temperature + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + """ + voltage = None + + voltage_data = self._get_eeprom_data('Voltage') + if (voltage_data is not None): + voltage = voltage_data['data']['Vcc']['value'] + + return voltage + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + """ + tx_bias = None + tx_bias_list = [] + + tx_bias_data = self._get_eeprom_data('ChannelMonitor') + if (tx_bias_data is not None): + if (self.sfp_type == 'QSFP'): + tx_bias = tx_bias_data['data']['TX1Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = tx_bias_data['data']['TX2Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = tx_bias_data['data']['TX3Bias']['value'] + tx_bias_list.append(tx_bias) + tx_bias = tx_bias_data['data']['TX4Bias']['value'] + tx_bias_list.append(tx_bias) + else: + tx1_bias = tx_bias_data['data']['TXBias']['value'] + return [tx1_bias, "N/A", "N/A", "N/A"] + + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + """ + rx_power = None + rx_power_list = [] + + rx_power_data = self._get_eeprom_data('ChannelMonitor') + if (rx_power_data is not None): + if (self.sfp_type == 'QSFP'): + rx_power = rx_power_data['data']['RX1Power']['value'] + rx_power_list.append(rx_power) + rx_power = rx_power_data['data']['RX2Power']['value'] + rx_power_list.append(rx_power) + rx_power = rx_power_data['data']['RX3Power']['value'] + rx_power_list.append(rx_power) + rx_power = rx_power_data['data']['RX4Power']['value'] + rx_power_list.append(rx_power) + else: + rx1_pw = rx_power_data['data']['RXPower']['value'] + return [rx1_pw, "N/A", "N/A", "N/A"] + + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + """ + tx_power_list = [] + if(self.sfp_type == 'QSFP'): + # 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. + qspf_dom_capability_data = self._get_eeprom_data('dom_capability') + qsfp_dom_rev_data = self._get_eeprom_data('dom_rev') + if (qspf_dom_capability_data is not None and qsfp_dom_rev_data is not None): + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value'] + else: + return tx_power_list + + # 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. + if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')): + return tx_power_list + else: + channel_monitor_data = self._get_eeprom_data('ChannelMonitor_TxPower') + if (channel_monitor_data is not None): + tx1_pw = channel_monitor_data['data']['TX1Power']['value'] + tx2_pw = channel_monitor_data['data']['TX2Power']['value'] + tx3_pw = channel_monitor_data['data']['TX3Power']['value'] + tx4_pw = channel_monitor_data['data']['TX4Power']['value'] + else: + return tx_power_list + + else: + channel_monitor_data = self._get_eeprom_data('ChannelMonitor') + if (channel_monitor_data is not None): + tx1_pw = channel_monitor_data['data']['TXPower']['value'] + tx2_pw = 'N/A' + tx3_pw = 'N/A' + tx4_pw = 'N/A' + else: + return tx_power_list + + tx_power_list.append(tx1_pw) + tx_power_list.append(tx2_pw) + tx_power_list.append(tx3_pw) + tx_power_list.append(tx4_pw) + + return tx_power_list + + def reset(self): + """ + Reset the SFP and returns all user settings to their default state + """ + if (self.sfp_type == 'QSFP'): + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 4th bit for reset + mask = (1 << 4) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + # Sleep 1 second to allow it to settle + time.sleep(1) + + reg_value = reg_value | mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + else: + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode(low power mode) of this SFP + """ + if (self.sfp_type == 'QSFP'): + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Absence of status throws error + if (reg_value == ""): + return False + + # Mask off 6th bit for lowpower mode + mask = (1 << 6) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + else: + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + """ + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + """ + return False + + def get_status(self): + """ + Retrieves the operational status of the device + """ + reset = self.get_reset_status() + + if (reset == True): + status = False + else: + status = True + + return status diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/thermal.py new file mode 100644 index 000000000000..d6432f66bcab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/thermal.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9264 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + from sonic_platform_base.thermal_base import ThermalBase + from sonic_platform.ipmihelper import IpmiSensor +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """DellEMC Platform-specific Thermal class""" + + # [ Sensor-Name, Sensor-ID ] + SENSOR_MAPPING = [ + ['CPU On-board', 0x6], + ['ASIC On-board', 0x8], + ['System Front Left', 0x3], + ['System Front Middle', 0x7], + ['System Front Right', 0x4], + ['Inlet Airflow Sensor', 0x5], + ['PSU1 Airflow Sensor', 0x2], + ['PSU2 Airflow Sensor', 0x1] + ] + + def __init__(self, thermal_index): + ThermalBase.__init__(self) + self.index = thermal_index + 1 + self.sensor = IpmiSensor(self.SENSOR_MAPPING[self.index - 1][1]) + + def get_name(self): + """ + Retrieves the name of the thermal + + Returns: + string: The name of the thermal + """ + return self.SENSOR_MAPPING[self.index - 1][0] + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return 'NA' + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + is_valid, temperature = self.sensor.get_reading() + if not is_valid: + temperature = 0 + + return float(temperature) + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + is_valid, high_threshold = self.sensor.get_threshold("UpperNonCritical") + if not is_valid: + return super(Thermal, self).get_high_threshold() + + return float(high_threshold) + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + is_valid, low_threshold = self.sensor.get_threshold("LowerNonRecoverable") + if not is_valid: + low_threshold = 0 + + return float(low_threshold) + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of + thermal in Celsius up to nearest thousandth of one degree + Celsius, e.g. 30.125 + """ + is_valid, high_crit_threshold = self.sensor.get_threshold("UpperCritical") + if not is_valid: + return super(Thermal, self).get_high_critical_threshold() + + return float(high_crit_threshold) + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/watchdog.py new file mode 100644 index 000000000000..0ecb42685c6d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/watchdog.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python + +######################################################################## +# +# DELLEMC Z9264f +# +# Abstract base class for implementing a platform-specific class with +# which to interact with a hardware watchdog module in SONiC +# +######################################################################## + +try: + import ctypes + import subprocess + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class _timespec(ctypes.Structure): + _fields_ = [ + ('tv_sec', ctypes.c_long), + ('tv_nsec', ctypes.c_long) + ] + + +class Watchdog(WatchdogBase): + """ + Abstract base class for interfacing with a hardware watchdog module + """ + + TIMERS = [15,20,30,40,50,60,65,70] + + armed_time = 0 + timeout = 0 + CLOCK_MONOTONIC = 1 + + def __init__(self): + self._librt = ctypes.CDLL('librt.so.1', use_errno=True) + self._clock_gettime = self._librt.clock_gettime + self._clock_gettime.argtypes=[ctypes.c_int, ctypes.POINTER(_timespec)] + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, universal_newlines=True) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + except OSError: + result = None + + return result + + def _get_reg_val(self): + # 0x31 = CPLD I2C Base Address + # 0x07 = Watchdog Function Register + value = self._get_command_result("/usr/sbin/i2cget -y 601 0x31 0x07") + if not value: + return None + else: + return int(value, 16) + + def _set_reg_val(self,val): + # 0x31 = CPLD I2C Base Address + # 0x07 = Watchdog Function Register + value = self._get_command_result("/usr/sbin/i2cset -y 601 0x31 0x07 %s" + % (val)) + return value + + def _get_time(self): + """ + To get clock monotonic time + """ + ts = _timespec() + if self._clock_gettime(self.CLOCK_MONOTONIC, ctypes.pointer(ts)) != 0: + self._errno = ctypes.get_errno() + return 0 + return ts.tv_sec + ts.tv_nsec * 1e-9 + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* + available value. + + Returns: + An integer specifying the *actual* number of seconds the + watchdog was armed with. On failure returns -1. + """ + timer_offset = -1 + for key,timer_seconds in enumerate(self.TIMERS): + if seconds <= timer_seconds: + timer_offset = key + seconds = timer_seconds + break + + if timer_offset == -1: + return -1 + + # Extracting 5th to 7th bits for WD timer values + # 000 - 15 sec + # 001 - 20 sec + # 010 - 30 sec + # 011 - 40 sec + # 100 - 50 sec + # 101 - 60 sec + # 110 - 65 sec + # 111 - 70 sec + reg_val = self._get_reg_val() + wd_timer_offset = (reg_val >> 4) & 0x7 + + if wd_timer_offset != timer_offset: + # Setting 5th to 7th bits + # value from timer_offset + self.disarm() + self._set_reg_val((reg_val & 0x87) | (timer_offset << 4)) + + if self.is_armed(): + # Setting last bit to WD Timer punch + # Last bit = WD Timer punch + self._set_reg_val(reg_val & 0xFE) + + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + else: + # Setting 4th bit to enable WD + # 4th bit = Enable WD + reg_val = self._get_reg_val() + self._set_reg_val(reg_val | 0x8) + + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + + def disarm(self): + """ + Disarm the hardware watchdog + + Returns: + A boolean, True if watchdog is disarmed successfully, False + if not + """ + if self.is_armed(): + # Setting 4th bit to disable WD + # 4th bit = Disable WD + reg_val = self._get_reg_val() + self._set_reg_val(reg_val & 0xF7) + + self.armed_time = 0 + self.timeout = 0 + return True + + return False + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + + Returns: + A boolean, True if watchdog is armed, False if not + """ + + # Extracting 4th bit to get WD Enable/Disable status + # 0 - Disabled WD + # 1 - Enabled WD + reg_val = self._get_reg_val() + wd_offset = (reg_val >> 3) & 1 + + return bool(wd_offset) + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds + remaining on the watchdog timer + + Returns: + An integer specifying the number of seconds remaining on + their watchdog timer. If the watchdog is not armed, returns + -1. + + Z9264 doesnot have hardware support to show remaining time. + Due to this limitation, this API is implemented in software. + This API would return correct software time difference if it + is called from the process which armed the watchdog timer. + If this API called from any other process, it would return + 0. If the watchdog is not armed, this API would return -1. + """ + if not self.is_armed(): + return -1 + + if self.armed_time > 0 and self.timeout != 0: + cur_time = self._get_time() + + if cur_time <= 0: + return 0 + + diff_time = int(cur_time - self.armed_time) + + if diff_time > self.timeout: + return self.timeout + else: + return self.timeout - diff_time + + return 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/systemd/platform-modules-z9264f.service b/platform/broadcom/sonic-platform-modules-dell/z9264f/systemd/platform-modules-z9264f.service new file mode 100644 index 000000000000..05d920a8502b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/systemd/platform-modules-z9264f.service @@ -0,0 +1,13 @@ +[Unit] +Description=Dell Z9264f Platform modules +Before=pmon.service determine-reboot-cause.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/z9264f_platform.sh init +ExecStop=/usr/local/bin/z9264f_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/cfg/z9332f-modules.conf b/platform/broadcom/sonic-platform-modules-dell/z9332f/cfg/z9332f-modules.conf new file mode 100644 index 000000000000..b6d4fe4fb00a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/cfg/z9332f-modules.conf @@ -0,0 +1,17 @@ +# /etc/modules: kernel modules to load at boot time. +# +# This file contains the names of kernel modules that should be loaded +# at boot time, one per line. Lines beginning with "#" are ignored. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x + +ipmi_devintf +ipmi_si diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/Makefile new file mode 100644 index 000000000000..bb71bb0d9185 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/Makefile @@ -0,0 +1,4 @@ +obj-m += cls-switchboard.o +obj-m += cls-i2c-ocore.o +obj-m += mc24lc64t.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/cls-i2c-ocore.c b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/cls-i2c-ocore.c new file mode 100644 index 000000000000..c80757e6619d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/cls-i2c-ocore.c @@ -0,0 +1,845 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * cls-i2c-ocores.c: I2C bus driver for OpenCores I2C controller + * (https://opencores.org/project/i2c/overview) + * + * Peter Korsgaard + * + * Support for the GRLIB port of the controller by + * Andreas Larsson + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +#include +#include +#include +#include +#include +#include "cls-i2c-ocore.h" + +#define OCORES_FLAG_POLL BIT(0) + +/* + * 'process_lock' exists because ocores_process() and ocores_process_timeout() + * can't run in parallel. + */ +struct ocores_i2c { + void __iomem *base; + int iobase; + u32 reg_shift; + u32 reg_io_width; + unsigned long flags; + wait_queue_head_t wait; + struct i2c_adapter adap; + struct i2c_msg *msg; + int pos; + int nmsgs; + int state; /* see STATE_ */ + int nack_retry; + spinlock_t process_lock; + struct clk *clk; + int ip_clock_khz; + int bus_clock_khz; + void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value); + u8 (*getreg)(struct ocores_i2c *i2c, int reg); +}; + +/* registers */ +#define OCI2C_PRELOW 0 +#define OCI2C_PREHIGH 1 +#define OCI2C_CONTROL 2 +#define OCI2C_DATA 3 +#define OCI2C_CMD 4 /* write only */ +#define OCI2C_STATUS 4 /* read only, same address as OCI2C_CMD */ + +#define OCI2C_CTRL_IEN 0x40 +#define OCI2C_CTRL_EN 0x80 + +#define OCI2C_CMD_START 0x91 +#define OCI2C_CMD_STOP 0x41 +#define OCI2C_CMD_READ 0x21 +#define OCI2C_CMD_WRITE 0x11 +#define OCI2C_CMD_READ_ACK 0x21 +#define OCI2C_CMD_READ_NACK 0x29 +#define OCI2C_CMD_IACK 0x01 + +#define OCI2C_STAT_IF 0x01 +#define OCI2C_STAT_TIP 0x02 +#define OCI2C_STAT_ARBLOST 0x20 +#define OCI2C_STAT_BUSY 0x40 +#define OCI2C_STAT_NACK 0x80 + +#define STATE_DONE 0 +#define STATE_START 1 +#define STATE_WRITE 2 +#define STATE_READ 3 +#define STATE_ERROR 4 + +#define TYPE_OCORES 0 +#define TYPE_GRLIB 1 + +static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite8(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite16(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite32(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_16be(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite16be(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_32be(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite32be(value, i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg) +{ + return ioread8(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg) +{ + return ioread16(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg) +{ + return ioread32(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_16be(struct ocores_i2c *i2c, int reg) +{ + return ioread16be(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 oc_getreg_32be(struct ocores_i2c *i2c, int reg) +{ + return ioread32be(i2c->base + (reg << i2c->reg_shift)); +} + +static void oc_setreg_io_8(struct ocores_i2c *i2c, int reg, u8 value) +{ + outb(value, i2c->iobase + reg); +} + +static inline u8 oc_getreg_io_8(struct ocores_i2c *i2c, int reg) +{ + return inb(i2c->iobase + reg); +} + +static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) +{ + i2c->setreg(i2c, reg, value); +} + +static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) +{ + return i2c->getreg(i2c, reg); +} + +static void ocores_process(struct ocores_i2c *i2c, u8 stat) +{ + struct i2c_msg *msg = i2c->msg; + unsigned long flags; + + /* + * If we spin here is because we are in timeout, so we are going + * to be in STATE_ERROR. See ocores_process_timeout() + */ + spin_lock_irqsave(&i2c->process_lock, flags); + + dev_dbg(&i2c->adap.dev, "STATE: %d\n", i2c->state); + + if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) { + /* stop has been sent */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + wake_up(&i2c->wait); + goto out; + } + + /* error? */ + if (stat & OCI2C_STAT_ARBLOST) { + // i2c->state = STATE_ERROR; + i2c->state = STATE_START; + // i2c->nack_retry = 1; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + dev_dbg(&i2c->adap.dev, "ERR: AL\n"); + goto out; + } + + if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) { + i2c->state = + (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + + if (stat & OCI2C_STAT_NACK) { + dev_dbg(&i2c->adap.dev, "ERR: NACK\n"); + // printk(KERN_INFO "ERR: NACK\n"); + i2c->state = STATE_ERROR; + if(!(msg->flags & I2C_M_RD)) + i2c->nack_retry = 1; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + goto out; + } + } else { + msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA); + } + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { /* end? */ + /* send start? */ + if (!(msg->flags & I2C_M_NOSTART)) { + u8 addr = i2c_8bit_addr_from_msg(msg); + + i2c->state = STATE_START; + + oc_setreg(i2c, OCI2C_DATA, addr); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + goto out; + } + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } else { + i2c->state = STATE_DONE; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + goto out; + } + } + + if (i2c->state == STATE_READ) { + oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ? + OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK); + } else { + oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE); + } + +out: + spin_unlock_irqrestore(&i2c->process_lock, flags); +} + +static irqreturn_t ocores_isr(int irq, void *dev_id) +{ + struct ocores_i2c *i2c = dev_id; + u8 stat = oc_getreg(i2c, OCI2C_STATUS); + + dev_dbg(&i2c->adap.dev, "STATUS: 0x%x\n", stat); + // printk(KERN_INFO "STATUS: 0x%x\n", stat); + + if (!(stat & OCI2C_STAT_IF)) + return IRQ_NONE; + + ocores_process(i2c, stat); + + return IRQ_HANDLED; +} + +/** + * Process timeout event + * @i2c: ocores I2C device instance + */ +static void ocores_process_timeout(struct ocores_i2c *i2c) +{ + unsigned long flags; + + spin_lock_irqsave(&i2c->process_lock, flags); + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + spin_unlock_irqrestore(&i2c->process_lock, flags); +} + +/** + * Wait until something change in a given register + * @i2c: ocores I2C device instance + * @reg: register to query + * @mask: bitmask to apply on register value + * @val: expected result + * @timeout: timeout in jiffies + * + * Timeout is necessary to avoid to stay here forever when the chip + * does not answer correctly. + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int ocores_wait(struct ocores_i2c *i2c, + int reg, u8 mask, u8 val, + const unsigned long timeout) +{ + unsigned long j; + + j = jiffies + timeout; + while (1) { + u8 status = oc_getreg(i2c, reg); + + if ((status & mask) == val) + break; + + if (time_after(jiffies, j)) + return -ETIMEDOUT; + cpu_relax(); + cond_resched(); + } + return 0; +} + +/** + * Wait until is possible to process some data + * @i2c: ocores I2C device instance + * + * Used when the device is in polling mode (interrupts disabled). + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int ocores_poll_wait(struct ocores_i2c *i2c) +{ + u8 mask; + int err; + + if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) { + /* transfer is over */ + mask = OCI2C_STAT_BUSY; + } else { + /* on going transfer */ + mask = OCI2C_STAT_TIP; + /* + * We wait for the data to be transferred (8bit), + * then we start polling on the ACK/NACK bit + */ + udelay((8 * 1000) / i2c->bus_clock_khz); + } + + dev_dbg(&i2c->adap.dev, "Wait for: 0x%x\n", mask); + // printk(KERN_INFO "Wait for: 0x%x\n", mask); + + /* + * once we are here we expect to get the expected result immediately + * so if after 1ms we timeout then something is broken. + */ + err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, msecs_to_jiffies(30)); + if (err) + dev_warn(i2c->adap.dev.parent, + "%s: STATUS timeout, bit 0x%x did not clear in 1ms\n", + __func__, mask); + return err; +} + +/** + * It handles an IRQ-less transfer + * @i2c: ocores I2C device instance + * + * Even if IRQ are disabled, the I2C OpenCore IP behavior is exactly the same + * (only that IRQ are not produced). This means that we can re-use entirely + * ocores_isr(), we just add our polling code around it. + * + * It can run in atomic context + */ +static void ocores_process_polling(struct ocores_i2c *i2c) +{ + while (1) { + irqreturn_t ret; + int err; + + err = ocores_poll_wait(i2c); + if (err) { + i2c->state = STATE_ERROR; + break; /* timeout */ + } + + ret = ocores_isr(-1, i2c); + if (ret == IRQ_NONE) + break; /* all messages have been transferred */ + } +} + +static int ocores_xfer_core(struct ocores_i2c *i2c, + struct i2c_msg *msgs, int num, + bool polling) +{ + int ret; + u8 ctrl; + + ctrl = oc_getreg(i2c, OCI2C_CONTROL); + if (polling) + oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~OCI2C_CTRL_IEN); + else + oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = STATE_START; + + dev_dbg(&i2c->adap.dev, "STATE: %d\n", i2c->state); + // printk(KERN_INFO "STATE: %d\n", i2c->state); + + oc_setreg(i2c, OCI2C_DATA, i2c_8bit_addr_from_msg(i2c->msg)); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + + if (polling) { + ocores_process_polling(i2c); + } else { + ret = wait_event_timeout(i2c->wait, + (i2c->state == STATE_ERROR) || + (i2c->state == STATE_DONE), HZ); + if (ret == 0) { + ocores_process_timeout(i2c); + return -ETIMEDOUT; + } + } + + return (i2c->state == STATE_DONE) ? num : -EIO; +} + +static int ocores_xfer_polling(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return ocores_xfer_core(i2c_get_adapdata(adap), msgs, num, true); +} + +static int ocores_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + int ret; + int retry=0; + int max_retry = 0; + struct ocores_i2c *i2c = i2c_get_adapdata(adap); + + i2c->nack_retry = 0; + + if (i2c->flags & OCORES_FLAG_POLL) + { + //return ocores_xfer_polling(adap, msgs, num); + ret = ocores_xfer_polling(adap, msgs, num); + // Fix i2cdetect issue + if(num == 1) + max_retry = 5; + else + max_retry = 5; + + while((i2c->nack_retry == 1)&&(retry < max_retry)) + { + retry++; + i2c->nack_retry = 0; + ret = ocores_xfer_polling(adap, msgs, num); + // printk("nack retry polling = %d\n",retry); + } + // if(i2c->nack_retry!=0){ + // printk("nack retry = %d, ret=%d\n",retry, ret); + // } + i2c->nack_retry = 0; + return ret; + } + return ocores_xfer_core(i2c, msgs, num, false); +} + +static int ocores_init(struct device *dev, struct ocores_i2c *i2c) +{ + int prescale; + int diff; + u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); + + /* make sure the device is disabled */ + ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); + oc_setreg(i2c, OCI2C_CONTROL, ctrl); + + prescale = (i2c->ip_clock_khz / (5 * i2c->bus_clock_khz)) - 1; + prescale = clamp(prescale, 0, 0xffff); + + dev_info(dev, "Prescale: %d\n", prescale); + + diff = i2c->ip_clock_khz / (5 * (prescale + 1)) - i2c->bus_clock_khz; + if (abs(diff) > i2c->bus_clock_khz / 10) { + dev_err(dev, + "Unsupported clock settings: core: %d KHz, bus: %d KHz\n", + i2c->ip_clock_khz, i2c->bus_clock_khz); + return -EINVAL; + } + + oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff); + oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); + + /* Init the device */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_EN); + + return 0; +} + + +static u32 ocores_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm ocores_algorithm = { + .master_xfer = ocores_xfer, + .functionality = ocores_func, +}; + +static const struct i2c_adapter ocores_adapter = { + .owner = THIS_MODULE, + .name = "i2c-goodcores", + .class = I2C_CLASS_DEPRECATED, + .algo = &ocores_algorithm, +}; + +static const struct of_device_id ocores_i2c_match[] = { + { + .compatible = "opencores,i2c-ocores", + .data = (void *)TYPE_OCORES, + }, + { + .compatible = "aeroflexgaisler,i2cmst", + .data = (void *)TYPE_GRLIB, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, ocores_i2c_match); + +#ifdef CONFIG_OF +/* + * Read and write functions for the GRLIB port of the controller. Registers are + * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one + * register. The subsequent registers have their offsets decreased accordingly. + */ +static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg) +{ + u32 rd; + int rreg = reg; + + if (reg != OCI2C_PRELOW) + rreg--; + rd = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PREHIGH) + return (u8)(rd >> 8); + else + return (u8)rd; +} + +static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value) +{ + u32 curr, wr; + int rreg = reg; + + if (reg != OCI2C_PRELOW) + rreg--; + if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) { + curr = ioread32be(i2c->base + (rreg << i2c->reg_shift)); + if (reg == OCI2C_PRELOW) + wr = (curr & 0xff00) | value; + else + wr = (((u32)value) << 8) | (curr & 0xff); + } else { + wr = value; + } + iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift)); +} + +static int ocores_i2c_of_probe(struct platform_device *pdev, + struct ocores_i2c *i2c) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + u32 val; + u32 clock_frequency; + bool clock_frequency_present; + + if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) { + /* no 'reg-shift', check for deprecated 'regstep' */ + if (!of_property_read_u32(np, "regstep", &val)) { + if (!is_power_of_2(val)) { + dev_err(&pdev->dev, "invalid regstep %d\n", + val); + return -EINVAL; + } + i2c->reg_shift = ilog2(val); + dev_warn(&pdev->dev, + "regstep property deprecated, use reg-shift\n"); + } + } + + clock_frequency_present = !of_property_read_u32(np, "clock-frequency", + &clock_frequency); + i2c->bus_clock_khz = 100; + + i2c->clk = devm_clk_get(&pdev->dev, NULL); + + if (!IS_ERR(i2c->clk)) { + int ret = clk_prepare_enable(i2c->clk); + + if (ret) { + dev_err(&pdev->dev, + "clk_prepare_enable failed: %d\n", ret); + return ret; + } + i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000; + if (clock_frequency_present) + i2c->bus_clock_khz = clock_frequency / 1000; + } + + if (i2c->ip_clock_khz == 0) { + if (of_property_read_u32(np, "opencores,ip-clock-frequency", + &val)) { + if (!clock_frequency_present) { + dev_err(&pdev->dev, + "Missing required parameter 'opencores,ip-clock-frequency'\n"); + clk_disable_unprepare(i2c->clk); + return -ENODEV; + } + i2c->ip_clock_khz = clock_frequency / 1000; + dev_warn(&pdev->dev, + "Deprecated usage of the 'clock-frequency' property, please update to 'opencores,ip-clock-frequency'\n"); + } else { + i2c->ip_clock_khz = val / 1000; + if (clock_frequency_present) + i2c->bus_clock_khz = clock_frequency / 1000; + } + } + + of_property_read_u32(pdev->dev.of_node, "reg-io-width", + &i2c->reg_io_width); + + match = of_match_node(ocores_i2c_match, pdev->dev.of_node); + if (match && (long)match->data == TYPE_GRLIB) { + dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n"); + // printk(KERN_INFO "GRLIB variant of i2c-ocores\n"); + i2c->setreg = oc_setreg_grlib; + i2c->getreg = oc_getreg_grlib; + } + + return 0; +} +#else +#define ocores_i2c_of_probe(pdev, i2c) -ENODEV +#endif + +static int ocores_i2c_probe(struct platform_device *pdev) +{ + struct ocores_i2c *i2c; + struct ocores_i2c_platform_data *pdata; + struct resource *res; + int irq; + int ret; + int i; + + i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + spin_lock_init(&i2c->process_lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) { + i2c->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(i2c->base)) + return PTR_ERR(i2c->base); + } else { + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!res) + return -EINVAL; + i2c->iobase = res->start; + if (!devm_request_region(&pdev->dev, res->start, + resource_size(res), + pdev->name)) { + dev_err(&pdev->dev, "Can't get I/O resource.\n"); + return -EBUSY; + } + i2c->setreg = oc_setreg_io_8; + i2c->getreg = oc_getreg_io_8; + } + + pdata = dev_get_platdata(&pdev->dev); + if (pdata) { + i2c->reg_shift = pdata->reg_shift; + i2c->reg_io_width = pdata->reg_io_width; + i2c->ip_clock_khz = pdata->clock_khz; + if (pdata->bus_khz) + i2c->bus_clock_khz = pdata->bus_khz; + else + i2c->bus_clock_khz = 100; + } else { + ret = ocores_i2c_of_probe(pdev, i2c); + if (ret) + return ret; + } + + if (i2c->reg_io_width == 0) + i2c->reg_io_width = 1; /* Set to default value */ + + if (!i2c->setreg || !i2c->getreg) { + bool be = pdata ? pdata->big_endian : + of_device_is_big_endian(pdev->dev.of_node); + + switch (i2c->reg_io_width) { + case 1: + i2c->setreg = oc_setreg_8; + i2c->getreg = oc_getreg_8; + break; + + case 2: + i2c->setreg = be ? oc_setreg_16be : oc_setreg_16; + i2c->getreg = be ? oc_getreg_16be : oc_getreg_16; + break; + + case 4: + i2c->setreg = be ? oc_setreg_32be : oc_setreg_32; + i2c->getreg = be ? oc_getreg_32be : oc_getreg_32; + break; + + default: + dev_err(&pdev->dev, "Unsupported I/O width (%d)\n", + i2c->reg_io_width); + ret = -EINVAL; + goto err_clk; + } + } + + init_waitqueue_head(&i2c->wait); + + irq = platform_get_irq(pdev, 0); + if (irq == -ENXIO) { + i2c->flags |= OCORES_FLAG_POLL; + } else { + if (irq < 0) + return irq; + } + + if (!(i2c->flags & OCORES_FLAG_POLL)) { + ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, + pdev->name, i2c); + if (ret) { + dev_err(&pdev->dev, "Cannot claim IRQ\n"); + goto err_clk; + } + } + + ret = ocores_init(&pdev->dev, i2c); + if (ret) + goto err_clk; + + /* hook up driver to tree */ + platform_set_drvdata(pdev, i2c); + i2c->adap = ocores_adapter; + i2c_set_adapdata(&i2c->adap, i2c); + i2c->adap.dev.parent = &pdev->dev; + i2c->adap.dev.of_node = pdev->dev.of_node; + + /* add i2c adapter to i2c tree */ + ret = i2c_add_adapter(&i2c->adap); + if (ret) + goto err_clk; + + /* add in known devices to the bus */ + if (pdata) { + for (i = 0; i < pdata->num_devices; i++) + i2c_new_device(&i2c->adap, pdata->devices + i); + } + + return 0; + +err_clk: + clk_disable_unprepare(i2c->clk); + return ret; +} + +static int ocores_i2c_remove(struct platform_device *pdev) +{ + struct ocores_i2c *i2c = platform_get_drvdata(pdev); + u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); + + /* disable i2c logic */ + ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); + oc_setreg(i2c, OCI2C_CONTROL, ctrl); + + /* remove adapter & data */ + i2c_del_adapter(&i2c->adap); + + if (!IS_ERR(i2c->clk)) + clk_disable_unprepare(i2c->clk); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int ocores_i2c_suspend(struct device *dev) +{ + struct ocores_i2c *i2c = dev_get_drvdata(dev); + u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); + + /* make sure the device is disabled */ + ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); + oc_setreg(i2c, OCI2C_CONTROL, ctrl); + + if (!IS_ERR(i2c->clk)) + clk_disable_unprepare(i2c->clk); + return 0; +} + +static int ocores_i2c_resume(struct device *dev) +{ + struct ocores_i2c *i2c = dev_get_drvdata(dev); + + if (!IS_ERR(i2c->clk)) { + unsigned long rate; + int ret = clk_prepare_enable(i2c->clk); + + if (ret) { + dev_err(dev, + "clk_prepare_enable failed: %d\n", ret); + return ret; + } + rate = clk_get_rate(i2c->clk) / 1000; + if (rate) + i2c->ip_clock_khz = rate; + } + return ocores_init(dev, i2c); +} + +static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume); +#define OCORES_I2C_PM (&ocores_i2c_pm) +#else +#define OCORES_I2C_PM NULL +#endif + +static struct platform_driver ocores_i2c_driver = { + .probe = ocores_i2c_probe, + .remove = ocores_i2c_remove, + .driver = { + .name = "goodcores-i2c", + .of_match_table = ocores_i2c_match, + .pm = OCORES_I2C_PM, + }, +}; + +module_platform_driver(ocores_i2c_driver); + +MODULE_AUTHOR("Peter Korsgaard "); +MODULE_DESCRIPTION("OpenCores I2C bus driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ocores-i2c"); diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/cls-i2c-ocore.h b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/cls-i2c-ocore.h new file mode 100644 index 000000000000..bc2a53cd6832 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/cls-i2c-ocore.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * cls-i2c-ocores.h - definitions for the i2c-ocores interface + * + * Peter Korsgaard + */ + +#ifndef _LINUX_I2C_OCORES_H +#define _LINUX_I2C_OCORES_H + +struct ocores_i2c_platform_data { + u32 reg_shift; /* register offset shift value */ + u32 reg_io_width; /* register io read/write width */ + u32 clock_khz; /* input clock in kHz */ + u32 bus_khz; /* bus clock in kHz */ + bool big_endian; /* registers are big endian */ + u8 num_devices; /* number of devices in the devices list */ + struct i2c_board_info const *devices; /* devices connected to the bus */ +}; + +#endif /* _LINUX_I2C_OCORES_H */ + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/cls-switchboard.c b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/cls-switchboard.c new file mode 100644 index 000000000000..dc1cf8874e39 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/cls-switchboard.c @@ -0,0 +1,447 @@ +/* + * cls_switchboard.c - PCI device driver for Silverstone Switch board FPGA. + * + * Author: Pradchaya Phucharoen + * + * Copyright (C) 2019 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 "cls-i2c-ocore.h" + +#define MOD_VERSION "2.1.0-1" +#define DRV_NAME "cls-switchboard" + +#define I2C_MUX_CHANNEL(_ch, _adap_id, _deselect) \ + [_ch] = { .adap_id = _adap_id, .deselect_on_exit = _deselect } + +#define FPGA_PCIE_DEVICE_ID 0x7021 +#define MMIO_BAR 0 +#define I2C_BUS_OFS 9 + +/* I2C ocore configurations */ +#define OCORE_REGSHIFT 2 +#define OCORE_IP_CLK_khz 62500 //TODO: check fpga's `wb_clk_i` +#define OCORE_BUS_CLK_khz 100 +#define OCORE_REG_IO_WIDTH 1 + +/* Optical port xcvr configuration */ +#define XCVR_REG_SHIFT 2 +#define XCVR_NUM_PORT 34 +#define XCVR_PORT_REG_SIZE 0x10 + +/* i2c_bus_config - an i2c-core resource and platform data + * @id - I2C bus device ID, for identification. + * @res - resources for an i2c-core device. + * @num_res - size of the resources. + * @pdata - a platform data of an i2c-core device. + */ +struct i2c_bus_config { + int id; + struct resource *res; + ssize_t num_res; + struct ocores_i2c_platform_data pdata; +}; + +/* switchbrd_priv - switchboard private data */ +struct switchbrd_priv { + unsigned long base; + int num_i2c_bus; + struct platform_device **i2cbuses_pdev; + struct platform_device *regio_pdev; + struct platform_device *spiflash_pdev; + //struct platform_device *xcvr_pdev; +}; + + +// NOTE: Silverstone i2c channel mapping is very wierd!!! +/* PCA9548 channel config on MASTER BUS 3 */ +static struct pca954x_platform_mode i2c_mux_70_modes[] = { + I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 23, true), + I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 26, true), + I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 27, true), + I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 28, true), + I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 29, true), + I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 30, true), + I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 31, true), + I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 32, true), +}; + +static struct pca954x_platform_mode i2c_mux_71_modes[] = { + I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 1, true), + I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 2, true), + I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 3, true), + I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 4, true), + I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 5, true), + I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 6, true), + I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 15, true), + I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 8, true), +}; + +static struct pca954x_platform_mode i2c_mux_72_modes[] = { + I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 17, true), + I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 18, true), + I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 19, true), + I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 20, true), + I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 21, true), + I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 22, true), + I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 25, true), + I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 24, true), +}; + +static struct pca954x_platform_mode i2c_mux_73_modes[] = { + I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 9, true), + I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 10, true), + I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 11, true), + I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 12, true), + I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 13, true), + I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 14, true), + I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 7, true), + I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 16, true), +}; + +static struct pca954x_platform_data om_muxes[] = { + { + .modes = i2c_mux_70_modes, + .num_modes = ARRAY_SIZE(i2c_mux_70_modes), + }, + { + .modes = i2c_mux_71_modes, + .num_modes = ARRAY_SIZE(i2c_mux_71_modes), + }, + { + .modes = i2c_mux_72_modes, + .num_modes = ARRAY_SIZE(i2c_mux_72_modes), + }, + { + .modes = i2c_mux_73_modes, + .num_modes = ARRAY_SIZE(i2c_mux_73_modes), + }, +}; + +/* Optical Module bus 3 i2c muxes info */ +static struct i2c_board_info i2c_info_3[] = { + { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &om_muxes[0], + }, + { + I2C_BOARD_INFO("pca9548", 0x71), + .platform_data = &om_muxes[1], + }, + { + I2C_BOARD_INFO("pca9548", 0x72), + .platform_data = &om_muxes[2], + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &om_muxes[3], + }, +}; + +/* RESOURCE SEPERATES BY FUNCTION */ +/* Resource IOMEM for i2c bus 1 */ +static struct resource cls_i2c_res_1[] = { + { + .start = 0x800, .end = 0x81F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for i2c bus 2 */ +static struct resource cls_i2c_res_2[] = { + { + .start = 0x820, .end = 0x83F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for i2c bus 3 */ +static struct resource cls_i2c_res_3[] = { + { + .start = 0x840, .end = 0x85F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for i2c bus 4 */ +static struct resource cls_i2c_res_4[] = { + { + .start = 0x860, .end = 0x87F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for i2c bus 5 */ +static struct resource cls_i2c_res_5[] = { + { + .start = 0x880, .end = 0x89F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for reg access */ +static struct resource reg_io_res[] = { + { + .start = 0x00, .end = 0xFF, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for spi flash firmware upgrade */ +static struct resource spi_flash_res[] = { + { + .start = 0x1200, .end = 0x121F, + .flags = IORESOURCE_MEM,}, +}; + +/* Resource IOMEM for front panel XCVR */ +// static struct resource xcvr_res[] = { +// { +// .start = 0x4000, .end = 0x421F, +// .flags = IORESOURCE_MEM,}, +// }; + +static struct i2c_bus_config i2c_bus_configs[] = { + { + .id = 1, + .res = cls_i2c_res_1, + .num_res = ARRAY_SIZE(cls_i2c_res_1), + .pdata = { + .reg_shift = OCORE_REGSHIFT, + .reg_io_width = OCORE_REG_IO_WIDTH, + .clock_khz = OCORE_IP_CLK_khz, + .bus_khz = OCORE_BUS_CLK_khz, + .big_endian = false, + .num_devices = 0, + .devices = NULL, + }, + }, + { + .id = 2, + .res = cls_i2c_res_2, + .num_res = ARRAY_SIZE(cls_i2c_res_2), + .pdata = { + .reg_shift = OCORE_REGSHIFT, + .reg_io_width = OCORE_REG_IO_WIDTH, + .clock_khz = OCORE_IP_CLK_khz, + .bus_khz = OCORE_BUS_CLK_khz, + .big_endian = false, + .num_devices = 0, + .devices = NULL, + }, + }, + { + .id = 3, + .res = cls_i2c_res_3, + .num_res = ARRAY_SIZE(cls_i2c_res_3), + .pdata = { + .reg_shift = OCORE_REGSHIFT, + .reg_io_width = OCORE_REG_IO_WIDTH, + .clock_khz = OCORE_IP_CLK_khz, + .bus_khz = OCORE_BUS_CLK_khz, + .big_endian = false, + .num_devices = ARRAY_SIZE(i2c_info_3), + .devices = i2c_info_3, + }, + }, + { + .id = 4, + .res = cls_i2c_res_4, + .num_res = ARRAY_SIZE(cls_i2c_res_4), + .pdata = { + .reg_shift = OCORE_REGSHIFT, + .reg_io_width = OCORE_REG_IO_WIDTH, + .clock_khz = OCORE_IP_CLK_khz, + .bus_khz = OCORE_BUS_CLK_khz, + .big_endian = false, + .num_devices = 0, + .devices = NULL, + }, + }, + { + .id = 5, + .res = cls_i2c_res_5, + .num_res = ARRAY_SIZE(cls_i2c_res_5), + .pdata = { + .reg_shift = OCORE_REGSHIFT, + .reg_io_width = OCORE_REG_IO_WIDTH, + .clock_khz = OCORE_IP_CLK_khz, + .bus_khz = OCORE_BUS_CLK_khz, + .big_endian = false, + .num_devices = 0, + .devices = NULL, + }, + }, +}; + +// TODO: Add a platform configuration struct, and use probe as a factory, +// so xcvr, fwupgrade device can configured as options. + +static int cls_fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + + struct switchbrd_priv *priv; + struct platform_device **i2cbuses_pdev; + struct platform_device *regio_pdev; + struct platform_device *spiflash_pdev; + //struct platform_device *xcvr_pdev; + unsigned long rstart; + int num_i2c_bus, i; + int err; + + err = pci_enable_device(dev); + if (err){ + dev_err(&dev->dev, "Failed to enable PCI device\n"); + goto err_exit; + } + + /* Check for valid MMIO address */ + rstart = pci_resource_start(dev, MMIO_BAR); + if (!rstart) { + dev_err(&dev->dev, "Switchboard base address uninitialized, " + "check FPGA\n"); + err = -ENODEV; + goto err_disable_device; + } + + dev_dbg(&dev->dev, "BAR%d res: 0x%lx-0x%llx\n", MMIO_BAR, + rstart, pci_resource_end(dev, MMIO_BAR)); + + priv = devm_kzalloc(&dev->dev, + sizeof(struct switchbrd_priv), GFP_KERNEL); + if (!priv){ + err = -ENOMEM; + goto err_disable_device; + } + + pci_set_drvdata(dev, priv); + num_i2c_bus = ARRAY_SIZE(i2c_bus_configs); + i2cbuses_pdev = devm_kzalloc( + &dev->dev, + num_i2c_bus * sizeof(struct platform_device*), + GFP_KERNEL); + + reg_io_res[0].start += rstart; + reg_io_res[0].end += rstart; + + spi_flash_res[0].start += rstart; + spi_flash_res[0].end += rstart; + + regio_pdev = platform_device_register_resndata( + &dev->dev, "cls-swbrd-io", + -1, + reg_io_res, ARRAY_SIZE(reg_io_res), + NULL, 0); + + if (IS_ERR(regio_pdev)) { + dev_err(&dev->dev, "Failed to register cls-swbrd-io\n"); + err = PTR_ERR(regio_pdev); + goto err_disable_device; + } + + spiflash_pdev = platform_device_register_resndata( + &dev->dev, "cls-swbrd-fwug", + -1, + spi_flash_res, ARRAY_SIZE(spi_flash_res), + NULL, 0); + + if (IS_ERR(spiflash_pdev)) { + dev_err(&dev->dev, "Failed to register firmware upgrade node\n"); + err = PTR_ERR(spiflash_pdev); + goto err_unregister_regio; + } + + for(i = 0; i < num_i2c_bus; i++){ + + i2c_bus_configs[i].res[0].start += rstart; + i2c_bus_configs[i].res[0].end += rstart; + + dev_dbg(&dev->dev, "i2c-bus.%d: 0x%llx - 0x%llx\n", + i2c_bus_configs[i].id, + i2c_bus_configs[i].res[0].start, + i2c_bus_configs[i].res[0].end); + + i2cbuses_pdev[i] = platform_device_register_resndata( + &dev->dev, "goodcores-i2c", + i2c_bus_configs[i].id, + i2c_bus_configs[i].res, + i2c_bus_configs[i].num_res, + &i2c_bus_configs[i].pdata, + sizeof(i2c_bus_configs[i].pdata)); + + if (IS_ERR(i2cbuses_pdev[i])) { + dev_err(&dev->dev, "Failed to register goodcores-i2c.%d\n", + i2c_bus_configs[i].id); + err = PTR_ERR(i2cbuses_pdev[i]); + goto err_unregister_ocore; + } + } + + priv->base = rstart; + priv->num_i2c_bus = num_i2c_bus; + priv->i2cbuses_pdev = i2cbuses_pdev; + priv->regio_pdev = regio_pdev; + priv->spiflash_pdev = spiflash_pdev; + return 0; + +err_unregister_ocore: + for(i = 0; i < num_i2c_bus; i++){ + if(priv->i2cbuses_pdev[i]){ + platform_device_unregister(priv->i2cbuses_pdev[i]); + } + } +// err_unregister_spiflash: +// platform_device_unregister(spiflash_pdev); +err_unregister_regio: + platform_device_unregister(regio_pdev); +err_disable_device: + pci_disable_device(dev); +err_exit: + return err; +} + +static void cls_fpga_remove(struct pci_dev *dev) +{ + int i; + struct switchbrd_priv *priv = pci_get_drvdata(dev); + + for(i = 0; i < priv->num_i2c_bus; i++){ + if(priv->i2cbuses_pdev[i]) + platform_device_unregister(priv->i2cbuses_pdev[i]); + } + platform_device_unregister(priv->spiflash_pdev); + platform_device_unregister(priv->regio_pdev); + pci_disable_device(dev); + return; +}; + +static const struct pci_device_id pci_clsswbrd[] = { + { PCI_VDEVICE(XILINX, FPGA_PCIE_DEVICE_ID) }, + {0, } +}; + +MODULE_DEVICE_TABLE(pci, pci_clsswbrd); + +static struct pci_driver clsswbrd_pci_driver = { + .name = DRV_NAME, + .id_table = pci_clsswbrd, + .probe = cls_fpga_probe, + .remove = cls_fpga_remove, +}; + +module_pci_driver(clsswbrd_pci_driver); + +MODULE_AUTHOR("Pradchaya P."); +MODULE_DESCRIPTION("Celestica Silverstone switchboard driver"); +MODULE_VERSION(MOD_VERSION); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/mc24lc64t.c new file mode 100644 index 000000000000..a391056d09a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/mc24lc64t.c @@ -0,0 +1,142 @@ +/* + * 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 + +struct mc24lc64t_data { + struct i2c_client *fake_client; + 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 struct bin_attribute mc24lc64t_bit_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = 65536, + .read = mc24lc64t_read, +}; + +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; + + drvdata->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); + if (!drvdata->fake_client) + return -ENOMEM; + + i2c_set_clientdata(client, drvdata); + mutex_init(&drvdata->update_lock); + + err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + if (err) + i2c_unregister_device(drvdata->fake_client); + + return err; +} + +static int mc24lc64t_remove(struct i2c_client *client) +{ + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + + i2c_unregister_device(drvdata->fake_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-dell/z9332f/modules/z9332f-modules.conf b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/z9332f-modules.conf new file mode 100644 index 000000000000..b6d4fe4fb00a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/modules/z9332f-modules.conf @@ -0,0 +1,17 @@ +# /etc/modules: kernel modules to load at boot time. +# +# This file contains the names of kernel modules that should be loaded +# at boot time, one per line. Lines beginning with "#" are ignored. + +i2c-i801 +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-gpio +i2c-mux-pca954x + +ipmi_devintf +ipmi_si diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/scripts/platform_sensors.py new file mode 100755 index 000000000000..1a5778525db2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/scripts/platform_sensors.py @@ -0,0 +1,196 @@ +#!/usr/bin/python3 +# On Z9332F, the BaseBoard Management Controller is an +# autonomous subsystem provides monitoring and management +# facility independent of the host CPU. IPMI standard +# protocol is used with ipmitool to fetch sensor details. +# Current script support X00 board only. X01 support will +# be added soon. This provies support for the +# following objects: +# * Onboard temperature sensors +# * FAN trays +# * PSU + + +import sys +import logging +import subprocess + +Z9332F_MAX_FAN_TRAYS = 7 +Z9332F_MAX_PSUS = 2 +IPMI_SENSOR_DATA = "ipmitool sdr list" +IPMI_SENSOR_DUMP = "/tmp/sdr" + +FAN_PRESENCE = "Fan{0}_Status" +PSU_PRESENCE = "PSU{0}_Status" +# Use this for older firmware +# PSU_PRESENCE="PSU{0}_prsnt" + +IPMI_PSU1_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x2f | awk '{print substr($0,9,1)}'" +IPMI_PSU2_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x39 | awk '{print substr($0,9,1)}'" + +ipmi_sdr_list = "" + +# Dump sensor registers + + +def ipmi_sensor_dump(): + + status = 1 + global ipmi_sdr_list + ipmi_cmd = IPMI_SENSOR_DATA + status, ipmi_sdr_list = subprocess.getstatusoutput(ipmi_cmd) + + if status: + logging.error('Failed to execute:' + ipmi_sdr_list) + sys.exit(0) + +# Fetch a BMC register + + +def get_pmc_register(reg_name): + + output = None + for item in ipmi_sdr_list.split("\n"): + if reg_name in item: + output = item.strip() + + if output is None: + print('\nFailed to fetch: ' + reg_name + ' sensor ') + sys.exit(0) + + output = output.split('|')[1] + + logging.basicConfig(level=logging.DEBUG) + return output + + +# Print the information for temperature sensors + + +def print_temperature_sensors(): + + print("\nOnboard Temperature Sensors:") + + for x in (('TEMP_FAN_U52', 'Fan U52'), + ('TEMP_FAN_U17', 'Fan U17'), + ('TEMP_SW_U52', 'SW U52'), + ('TEMP_SW_U16', 'SW U16'), + ('TEMP_BB_U3', 'Baseboard U3'), + ('TEMP_CPU', 'Near CPU'), + ('TEMP_SW_Internal', 'SW interal'), + ('PSU1_Temp1', 'PSU1 inlet'), + ('PSU1_Temp2', 'PSU1 hotspot'), + ('PSU2_Temp1', 'PSU2 inlet'), + ('PSU2_Temp2', 'PSU2 hotspot'), + ('SW_U04_Temp', 'SW U04'), + ('SW_U14_Temp', 'SW U14'), + ('SW_U4403_Temp', 'SW U4403') + ): + print(' {0:32}{1}'.format(x[1] + ':', get_pmc_register(x[0]))) + +ipmi_sensor_dump() + +print_temperature_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(tray): + + Fan_Status = [' Normal', ' Abnormal'] + Airflow_Direction = ['B2F', 'F2B'] + + print(' Fan Tray ' + str(tray) + ':') + + print(' Fan1 Speed: ', + get_pmc_register('Fan{}_Front'.format(tray))) + print(' Fan2 Speed: ', + get_pmc_register('Fan{}_Rear'.format(tray))) + print(' Fan State: ', + Fan_Status[int(get_pmc_register('Fan{}_Status'.format(tray)), 16)]) + + +print('\nFan Trays:') + +for tray in range(1, Z9332F_MAX_FAN_TRAYS + 1): + fan_presence = FAN_PRESENCE.format(tray) + if (get_pmc_register(fan_presence)): + print_fan_tray(tray) + else: + print('\n Fan Tray ' + str(tray + 1) + ': Not present') + + 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 + """ + status = 0 + ret_status = 1 + + if index == 1: + status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_PSU1_DATA_DOCKER) + elif index == 2: + ret_status, ipmi_cmd_ret = subprocess.getstatusoutput(IPMI_PSU2_DATA_DOCKER) + + #if ret_status: + # print ipmi_cmd_ret + # logging.error('Failed to execute ipmitool') + # sys.exit(0) + + psu_status = ipmi_cmd_ret + + if psu_status == '1': + status = 1 + + return status + + +# Print the information for PSU1, PSU2 +def print_psu(psu): + Psu_Type = ['Normal', 'Mismatch'] + Psu_Input_Type = ['AC', 'DC'] + PSU_STATUS_TYPE_BIT = 4 + PSU_STATUS_INPUT_TYPE_BIT = 1 + PSU_FAN_PRESENT_BIT = 2 + PSU_FAN_STATUS_BIT = 1 + 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] + + print(' PSU{}:'.format(psu)) + print(' Inlet Temperature: ', + get_pmc_register('PSU{}_Temp1'.format(psu))) + print(' Hotspot Temperature: ', + get_pmc_register('PSU{}_Temp2'.format(psu))) + print(' FAN RPM: ', + get_pmc_register('PSU{}_Fan'.format(psu))) + # print ' FAN Status: ', Psu_Fan_Status[psu1_fan_status] + + # PSU input & output monitors + print(' Input Voltage: ', + get_pmc_register('PSU{}_VIn'.format(psu))) + print(' Output Voltage: ', + get_pmc_register('PSU{}_VOut'.format(psu))) + print(' Input Power: ', + get_pmc_register('PSU{}_PIn'.format(psu))) + print(' Output Power: ', + get_pmc_register('PSU{}_POut'.format(psu))) + print(' Input Current: ', + get_pmc_register('PSU{}_CIn'.format(psu))) + print(' Output Current: ', + get_pmc_register('PSU{}_COut'.format(psu))) + + +print('\nPSUs:') +for psu in range(1, Z9332F_MAX_PSUS + 1): + #psu_presence = PSU_PRESENCE.format(psu) + if (get_psu_presence(psu)): + print_psu(psu) + else: + print('\n PSU ', psu, 'Not present') diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/z9332f/scripts/sensors new file mode 100755 index 000000000000..ee53f2b0f325 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/scripts/sensors @@ -0,0 +1,8 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" +docker exec -i pmon /usr/bin/platform_sensors.py "$@" + +#To probe sensors not part of lm-sensors +#if [ -r /usr/local/bin/platform_sensors.py ]; then +# python /usr/local/bin/platform_sensors.py +#fi diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/scripts/z9332f_platform.sh b/platform/broadcom/sonic-platform-modules-dell/z9332f/scripts/z9332f_platform.sh new file mode 100755 index 000000000000..f80207df8ea2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/scripts/z9332f_platform.sh @@ -0,0 +1,220 @@ +#!/bin/bash + +init_devnum() { + found=0 + for devnum in 0; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # I801 adapter f000 + if [[ $devname == 'SMBus I801 adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find I801" && exit 1 +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + case $1 in + "new_device") echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-0/$1 + ;; + "delete_device") echo 0x56 > /sys/bus/i2c/devices/i2c-0/$1 + ;; + *) echo "z9332f_platform: sys_eeprom : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs +switch_board_qsfp_mux() { + case $1 in + "new_device") + for ((i=603;i<=607;i++)); + do + echo "Attaching PCA9548 @ 0x74" + echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-$i/$1 + done + + ;; + "delete_device") + for ((i=603;i<=607;i++)); + do + echo "Detaching PCA9548 @ 0x74" + echo 0x74 > /sys/bus/i2c/devices/i2c-$i/$1 + done + + ;; + *) echo "z9332f_platform: switch_board_qsfp_mux: invalid command !" + ;; + esac + sleep 2 +} + +#Attach/Detach 64 instances of EEPROM driver QSFP ports +#eeprom can dump data using below command +switch_board_qsfp() { + case $1 in + "new_device") + for ((i=10;i<=41;i++)); + do + echo optoe3 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=10;i<=41;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "z9332f_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +#Attach/Detach 2 instances of EEPROM driver SFP+ ports +#eeprom can dump data using below command +switch_board_sfp() { + case $1 in + "new_device") + for ((i=1;i<=2;i++)); + do + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=1;i<=2;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "z9332f_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +#Modsel 64 ports to applicable QSFP type modules +#This enables the adapter to respond for i2c commands +#Low Power mode enabled by default +switch_board_modsel() { + resource="/sys/bus/pci/devices/0000:09:00.0/resource0" + for ((i=1;i<=32;i++)); + do + port_addr=$(( 16384 + ((i - 1) * 16))) + hex=$( printf "0x%x" $port_addr ) + /usr/bin/pcisysfs.py --set --offset $hex --val 0x50 --res $resource > /dev/null 2>&1 + done +} + +#This enables the led control for CPU and default states +switch_board_led_default() { + /usr/sbin/i2cset -y 5 0x0d 0x62 0xd0 +} + +# 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 -t bios | grep Version | awk -F":" '{print $2}'`" > $FIRMWARE_VERSION_FILE + # Get FPGA version + r=`/usr/bin/pcisysfs.py --get --offset 0x00 --res /sys/bus/pci/devices/0000\:09\: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=`docker exec -it pmon ipmitool mc info | awk '/Firmware Revision/ { print $NF }'` + r=`cat /sys/class/ipmi/ipmi0/device/bmc/firmware_revision` + echo "BMC: $r" >> $FIRMWARE_VERSION_FILE + + #BaseBoard CPLD 0x0d on i2c bus 5 ( physical FPGA I2C-5) + ver=`/usr/sbin/i2cget -y 5 0x0d 0x0` + echo "Baseboard CPLD: $((ver))" >> $FIRMWARE_VERSION_FILE + + #Switch CPLD 1 0x30 on i2c bus 4 ( physical FPGA I2C-4) + ver=`/usr/sbin/i2cget -y 4 0x30 0x0` + echo "Switch CPLD 1: $((ver))" >> $FIRMWARE_VERSION_FILE + + #Switch CPLD 1 0x30 on i2c bus 4 ( physical FPGA I2C-4) + ver=`/usr/sbin/i2cget -y 4 0x31 0x0` + echo "Switch CPLD 2: $((ver))" >> $FIRMWARE_VERSION_FILE +} + +install_python_api_package() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip install $device/$platform/sonic_platform-1.0-py2-none-any.whl) + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) +} + +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) + fi + + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -eq 0 ]; then + rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null) + fi +} + +get_reboot_cause() { + REBOOT_REASON_FILE="/host/reboot-cause/platform/reboot_reason" + + mkdir -p $(dirname $REBOOT_REASON_FILE) + + # Handle First Boot into software version with reboot cause determination support + if [[ ! -e $REBOOT_REASON_FILE ]]; then + echo "0" > $REBOOT_REASON_FILE + else + /usr/sbin/i2cget -y 5 0x0d 0x06 > $REBOOT_REASON_FILE + fi +} + + +init_devnum + +if [ "$1" == "init" ]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe ipmi_devintf + modprobe ipmi_si kipmid_max_busy_us=1000 + modprobe cls-i2c-ocore + modprobe cls-switchboard + modprobe mc24lc64t + #insmod /lib/modules/`uname -r`/extra/mc24lc64t.ko + sys_eeprom "new_device" + switch_board_qsfp "new_device" + switch_board_sfp "new_device" + switch_board_led_default + install_python_api_package + # /usr/bin/qsfp_irq_enable.py + platform_firmware_versions + get_reboot_cause + echo 1000 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us + +elif [ "$1" == "deinit" ]; then + sys_eeprom "delete_device" + switch_board_qsfp "delete_device" + switch_board_sfp "delete_device" + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev + modprobe -r ipmi_devintf + modprobe -r ipmi_si + modprobe -r cls-i2c-ocore + modprobe -r cls-switchboard + modprobe -r mc24lc64t + remove_python_api_package +else + echo "z9332f_platform : Invalid option !" +fi + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/setup.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/setup.py new file mode 120000 index 000000000000..4f6de9941d96 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/setup.py @@ -0,0 +1 @@ +../s6100/setup.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/__init__.py new file mode 100755 index 000000000000..4f5d4f6e473d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer"] +from sonic_platform import * diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py new file mode 100755 index 000000000000..8ac97943cc09 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py @@ -0,0 +1,368 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import time + import sys + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.eeprom import Eeprom + from sonic_platform.component import Component + from sonic_platform.psu import Psu + from sonic_platform.thermal import Thermal + from sonic_platform.fan_drawer import FanDrawer + from sonic_platform.watchdog import Watchdog + import sonic_platform.hwaccess as hwaccess +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +MAX_Z9332F_FANTRAY = 7 +MAX_Z9332F_FAN = 2 +MAX_Z9332F_PSU = 2 +MAX_Z9332F_THERMAL = 14 +MAX_Z9332F_COMPONENT = 6 # BIOS,FPGA,BMC,BB CPLD and 2 Switch CPLDs + +media_part_num_list = set([ \ +"8T47V","XTY28","MHVPK","GF76J","J6FGD","F1KMV","9DN5J","H4DHD","6MCNV","0WRX0","X7F70","5R2PT","WTRD1","WTRD1","WTRD1","WTRD1","5250G","WTRD1","C5RNH","C5RNH","FTLX8571D3BCL-FC", +"C5RNH","5250G","N8TDR","7D64H","7D64H","RN84N","RN84N","HMTNW","6K3Y6","6K3Y6","TY5FM","50M0R","PGYJT","WP2PP","85Y13","1HCGH","FP9R1","FYD0M","C6Y7M","C6Y7M","V250M","V250M", +"5CWK6","5CWK6","53HVN","53HVN","358VV","358VV","MV799","MV799","YJF03","P9GND","T1KCN","1DXKP","MT7R2","K0T7R","W5G04","7TCDN","7TCDN","7TCDN","7TCDN","7TCDN","V3XJK","0MV31", +"5FVP7","N6KM9","C41MF","77KC3","XW7J0","V4NJV","2XJHY","H93DH","H93DH","F8CG0","F8CG0","F8CG0","119N6","WFMF5","794RX","288F6","1M31V","1M31V","5NP8R","5NP8R","4TC09","4TC09", +"FC6KV","FC6KV","J90VN","J90VN","05RH0","05RH0","YDN52","0C2YV","YDN52","0C2YV","9JT65","D7M6H","6GW14","FYVFW","0VF5H","P4YPY","P4YPY","TCPM2","TCPM2","JNPF8","JNPF8","27GG5", +"27GG5","P8T4W","P8T4W","JR54Y","M6N0J","XJYD0","K44H9","035KG","P7C7N","76V43","3CC35","FN4FC","26FN3","YFNDD","YFNDD","7R9N9","035KG","P7C7N","76V43","3CC35","PLRXPLSCS43811", +"FN4FC","26FN3","YFNDD","YFNDD","7R9N9","G86YJ","V407F","V407F","9KH6T","G86YJ","V407F","9KH6T","2JVDD","D0R73","VXFJY","9X8JP","2JVDD","D0R73","VXFJY","9X8JP","2JVDD","D0R73","VXFJY", +"9X8JP","GMFC5","GMFC5","GMFC5","D7P80","3MFXG","3MFXG","0GWXJ","THPF3","THPF3","THPF3","THPF3","THPF3","PJ62G","3XCX1","JJYKG","RRRTK","16K56","86JM2","K5R6C","7MG2C","WTPPN","9HTT2", +"NKM4F","VXGGG","JC9W6","6MR8M","RP3GV","M5PPJ","XKY55","TKCXT","05J8P","5WGKD","XFDRT","NW8DM","YPKH3","5WGKD","XFDRT","NW8DM","YPKH3","71XXK","MVCX6","0XYP6","HPPVW","3GHRT","71XXK", +"MVCX6","0XYP6","HPPVW","3GHRT","2X5T6","135V2","KD5MV","2X5T6","KD5MV","HHFK0","3YWG7","5CMT2","RCVP5","X5DH4","HHFK0","3YWG7","5CMT2","RCVP5","X5DH4","3YWG7","5CMT2","RCVP5","X5DH4", +"4WJ41","4WJ41","14NV5","14NV5","14NV5","4WGYD","YKMH7","X7CCC","X7CCC","0X9CT","0CY8V","P7D7R","W4GPP","W4GPP","W4GPP","HHHCHC","07RN7","07RN7","0YR96","0YR96","JCYM9","FTLX8571D3BCL", +"DDW0X","VPFDJ","229KM","9FC7D","DDW0X","VPFDJ","6FMR5","J7K20","N3K9W","6FMR5","8R4VM","7VN5T","D9YM8","8R4VM","VYXPW","87TPX","WY6FK","VYXPW","87TPX","WY6FK","WG8C4","N8K82","2DV6Y", +"77C3C","RC0HM","77C3C","RC0HM","JHXTN","3P3PG","92YVM","4VX5M","4VX5M","6RRGD","W4JWV","22V6R","XR11M","9GMDY","JMCWK","TP2F0","6MGDY","78RHK", "C0TP5","0WDNV","FCLF8522P2BTL"\ +]) + +class Chassis(ChassisBase): + """ + DELLEMC Platform-specific Chassis class + """ + + REBOOT_CAUSE_PATH = "/host/reboot-cause/platform/reboot_reason" + oir_fd = -1 + epoll = -1 + io_res = "/dev/port" + sysled_offset = 0xA162 + SYSLED_COLOR_TO_REG = { + "green": 0xd0, + "yellow": 0xe0, + "flash_green": 0xd2, + "flash_yellow": 0xe2 + } + + REG_TO_SYSLED_COLOR = { + 0xd0 : "green", + 0xe0 : "yellow", + 0xd2 : "flash_green", + 0xd1 : "flash_green", + 0xe2 : "flash_yellow", + 0xe1 : "flash_yellow" + } + + _global_port_pres_dict = {} + _port_to_i2c_mapping = { + 1: 10, + 2: 11, + 3: 12, + 4: 13, + 5: 14, + 6: 15, + 7: 16, + 8: 17, + 9: 18, + 10: 19, + 11: 20, + 12: 21, + 13: 22, + 14: 23, + 15: 24, + 16: 25, + 17: 26, + 18: 27, + 19: 28, + 20: 29, + 21: 30, + 22: 31, + 23: 32, + 24: 33, + 25: 34, + 26: 35, + 27: 36, + 28: 37, + 29: 38, + 30: 39, + 31: 40, + 32: 41, + 33: 1, + 34: 2, + } + + def __init__(self): + ChassisBase.__init__(self) + # sfp.py will read eeprom contents and retrive the eeprom data. + # We pass the eeprom path from chassis.py + self.PORT_START = 1 + self.PORT_END = 34 + self.PORTS_IN_BLOCK = (self.PORT_END + 1) + _sfp_port = range(33, self.PORTS_IN_BLOCK) + eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + for index in range(self.PORT_START, self.PORTS_IN_BLOCK): + eeprom_path = eeprom_base.format(self._port_to_i2c_mapping[index]) + port_type = 'SFP' if index in _sfp_port else 'QSFP' + sfp_node = Sfp(index, port_type, eeprom_path) + self._sfp_list.append(sfp_node) + + self._eeprom = Eeprom() + self._watchdog = Watchdog() + for i in range(MAX_Z9332F_FANTRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + self._num_sfps = self.PORT_END + self._num_fans = MAX_Z9332F_FANTRAY * MAX_Z9332F_FAN + self._psu_list = [Psu(i) for i in range(MAX_Z9332F_PSU)] + self._thermal_list = [Thermal(i) for i in range(MAX_Z9332F_THERMAL)] + self._component_list = [Component(i) for i in range(MAX_Z9332F_COMPONENT)] + for port_num in range(self.PORT_START, self.PORTS_IN_BLOCK): + # sfp get uses zero-indexing, but port numbers start from 1 + presence = self.get_sfp(port_num).get_presence() + self._global_port_pres_dict[port_num] = '1' if presence else '0' + + self._watchdog = Watchdog() + def __del__(self): + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + +# check for this event change for sfp / do we need to handle timeout/sleep + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + """ + start_ms = time.time() * 1000 + port_dict = {} + change_dict = {} + change_dict['sfp'] = port_dict + while True: + time.sleep(0.5) + for port_num in range(self.PORT_START, (self.PORT_END + 1)): + presence = self.get_sfp(port_num).get_presence() + if(presence and self._global_port_pres_dict[port_num] == '0'): + self._global_port_pres_dict[port_num] = '1' + port_dict[port_num] = '1' + elif(not presence and + self._global_port_pres_dict[port_num] == '1'): + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + + if(len(port_dict) > 0): + return True, change_dict + + if timeout: + now_ms = time.time() * 1000 + if (now_ms - start_ms >= timeout): + return True, change_dict + + + def get_sfp(self, index): + """ + Retrieves sfp represented by (0-based) index + + Args: + index: An integer, the index (0-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 0. + For example, 0 for Ethernet0, 1 for Ethernet4 and so on. + + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + + try: + # The index will start from 0 + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + return sfp + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.serial_number_str() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_eeprom(self): + """ + Retrieves the Sys Eeprom instance for the chassis. + Returns : + The instance of the Sys Eeprom + """ + return self._eeprom + + def get_num_fans(self): + """ + Retrives the number of Fans on the chassis. + Returns : + An integer represents the number of Fans on the chassis. + """ + return self._num_fans + + def get_num_sfps(self): + """ + Retrives the numnber of Media on the chassis. + Returns: + An integer represences the number of SFPs on the chassis. + """ + return self._num_sfps + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + try: + with open(self.REBOOT_CAUSE_PATH) as fd: + reboot_cause = int(fd.read(), 16) + except EnvironmentError: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + if reboot_cause & 0x1: + return (self.REBOOT_CAUSE_POWER_LOSS, None) + elif reboot_cause & 0x2: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + elif reboot_cause & 0x44: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "CPU warm reset") + elif reboot_cause & 0x8: + return (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, None) + elif reboot_cause & 0x66: + return (self.REBOOT_CAUSE_WATCHDOG, None) + elif reboot_cause & 0x55: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "CPU cold reset") + elif reboot_cause & 0x11: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Power on reset") + elif reboot_cause & 0x77: + return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Power Cycle reset") + else: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + + def get_qualified_media_list(self): + return media_part_num_list + + def initizalize_system_led(self): + self.sys_ledcolor = "green" + + def get_status_led(self): + """ + Gets the current system LED color + + Returns: + A string that represents the supported color + """ + val = hwaccess.io_reg_read(self.io_res, self.sysled_offset) + if val != -1: + return self.REG_TO_SYSLED_COLOR.get(val) + return self.sys_ledcolor + + def set_status_led(self, color): + """ + Set system LED status based on the color type passed in the argument. + Argument: Color to be set + Returns: + bool: True is specified color is set, Otherwise return False + """ + + if color not in list(self.SYSLED_COLOR_TO_REG.keys()): + return False + + if(not hwaccess.io_reg_write(self.io_res, self.sysled_offset, self.SYSLED_COLOR_TO_REG[color])): + return False + self.sys_ledcolor = color + return True + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/component.py new file mode 100644 index 000000000000..58c944cd6eb3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/component.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, BMC etc.) available in +# the platform +# +######################################################################## + +try: + import subprocess + from sonic_platform_base.component_base import ComponentBase + import sonic_platform.hwaccess as hwaccess + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +def get_bios_version(): + return subprocess.check_output(['dmidecode', '-s', 'bios-version']).strip() + +def get_fpga_version(): + val = hwaccess.pci_get_value('/sys/bus/pci/devices/0000:09:00.0/resource0', 0) + return '{}.{}'.format((val >> 8) & 0xff, val & 0xff) + +def get_bmc_version(): + return subprocess.check_output( + ['cat', '/sys/class/ipmi/ipmi0/device/bmc/firmware_revision'] + ).strip() + +def get_cpld_version(bus, i2caddr): + return '{}'.format(hwaccess.i2c_get(bus, i2caddr, 0)) + +def get_cpld0_version(): + return get_cpld_version(5, 0x0d) + +def get_cpld1_version(): + return get_cpld_version(4, 0x30) + +def get_cpld2_version(): + return get_cpld_version(4, 0x31) + + + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + CHASSIS_COMPONENTS = [ + ['BIOS', + 'Performs initialization of hardware components during booting', + get_bios_version + ], + + ['FPGA', + 'Used for managing the system LEDs', + get_fpga_version + ], + + ['BMC', + 'Platform management controller for on-board temperature monitoring,in-chassis power, Fan and LED control', + get_bmc_version + ], + + ['Baseboard CPLD', + 'Used for managing the CPU power sequence and CPU states', + get_cpld0_version + ], + + ['Switch CPLD 1', + 'Used for managing QSFP28/SFP port transceivers ', + get_cpld1_version + ], + + ['Switch CPLD 2', + 'Used for managing QSFP28/SFP port transceivers', + get_cpld2_version + ] + + ] + + def __init__(self, component_index = 0): + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + self.version = self.CHASSIS_COMPONENTS[self.index][2]() + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + return self.version + + def install_firmware(self, image_path): + """ + Installs firmware to the component + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py new file mode 100644 index 000000000000..eda04ae3bd8e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python + +############################################################################# +# DellEmc Z9332F +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import os.path + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.eeprom_path = None + for b in (0, 1): + f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0056/eeprom'.format(b) + if os.path.exists(f): + self.eeprom_path = f + break + if self.eeprom_path is None: + return + super(Eeprom, self).__init__(self.eeprom_path, 0, '', True) + self.eeprom_tlv_dict = dict() + try: + self.eeprom_data = self.read_eeprom() + except: + self.eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % tlv[0] + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str((tlv[2] << 24) | (tlv[3] << 16) | + (tlv[4] << 8) | tlv[5]) + value += tlv[6:6 + tlv[1]].decode('ascii') + else: + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + """ + Returns the serial number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self): + """ + Returns the base mac address found in the system EEPROM + """ + (is_valid, t) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join(["{:02x}".format(T) for T in t[2]]).upper() + + def modelstr(self): + """ + Returns the Model name + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + """ + Returns the part number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def serial_str(self): + """ + Returns the servicetag number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + """ + Returns the device revision + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan.py new file mode 100755 index 000000000000..ff7a08bdd1ad --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fans' information which are available in the platform. +# +######################################################################## +try: + from sonic_platform_base.fan_base import FanBase + from sonic_platform.ipmihelper import IpmiSensor, IpmiFru, get_ipmitool_raw_output +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Fan(FanBase): + """DellEMC Platform-specific Fan class""" + # { FAN-ID: { Sensor-Name: Sensor-ID } } + FAN_SENSOR_MAPPING = { 1: {"Prsnt": 0x6, "State": 0x6, "Speed": 0xd}, + 2: {"Prsnt": 0x6, "State": 0x6, "Speed": 0x45}, + 3: {"Prsnt": 0x7, "State": 0x7, "Speed": 0xe}, + 4: {"Prsnt": 0x7, "State": 0x7, "Speed": 0x46}, + 5: {"Prsnt": 0x8, "State": 0x8, "Speed": 0xf}, + 6: {"Prsnt": 0x8, "State": 0x8, "Speed": 0x47}, + 7: {"Prsnt": 0x9, "State": 0x9, "Speed": 0x10}, + 8: {"Prsnt": 0x9, "State": 0x9, "Speed": 0x48}, + 9: {"Prsnt": 0xa, "State": 0xa, "Speed": 0x11}, + 10: {"Prsnt": 0xa, "State": 0xa, "Speed": 0x49}, + 11: {"Prsnt": 0xb, "State": 0xb, "Speed": 0x12}, + 12: {"Prsnt": 0xb, "State": 0xb, "Speed": 0x4a}, + 13: {"Prsnt": 0xc, "State": 0xc, "Speed": 0x13}, + 14: {"Prsnt": 0xc, "State": 0xc, "Speed": 0x4b} } + PSU_FAN_SENSOR_MAPPING = { 1: {"State": 0x2f, "Speed": 0x33}, + 2: {"State": 0x39, "Speed": 0x3d} } + + # { FANTRAY-ID: FRU-ID } + FAN_FRU_MAPPING = { 1: 6, 2: 7, 3: 8, 4: 9, 5: 10, 6: 11, 7: 12 } + PSU_FRU_MAPPING = { 1: 3, 2: 4 } + + def __init__(self, fantray_index=1, fan_index=1, psu_fan=False, dependency=None): + self.is_psu_fan = psu_fan + if not self.is_psu_fan: + # API index is starting from 0, DellEMC platform index is + # starting from 1 + self.fantrayindex = fantray_index + 1 + self.fanindex = fan_index + 1 + self.index = (self.fantrayindex - 1) * 2 + self.fanindex + self.prsnt_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Prsnt"], + is_discrete=True) + self.state_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["State"], + is_discrete=True) + self.speed_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Speed"]) + self.fru = IpmiFru(self.FAN_FRU_MAPPING[self.fantrayindex]) + self.fan_dir_raw_cmd = "0x3a 0x0a {}".format(fantray_index) + else: + self.dependency = dependency + self.fanindex = fan_index + self.state_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["State"], + is_discrete=True) + self.speed_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["Speed"]) + self.fru = IpmiFru(self.PSU_FRU_MAPPING[self.fanindex]) + self.fan_dir_raw_cmd = "0x3a 0x0a {}".format(7+(fan_index-1)) + self.max_speed = 23500 + + def get_name(self): + """ + Retrieves the name of the device + Returns: + String: The name of the device + """ + if self.is_psu_fan: + return "PSU{} Fan".format(self.fanindex) + else: + return "FanTray{}-Fan{}".format(self.fantrayindex, self.fanindex) + + def get_model(self): + """ + Retrieves the part number of the FAN + Returns: + String: Part number of FAN + """ + if self.is_psu_fan: + return None + else: + return self.fru.get_board_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the FAN + Returns: + String: Serial number of FAN + """ + if self.is_psu_fan: + return None + else: + return self.fru.get_board_serial() + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if fan is present, False if not + """ + presence = False + if self.is_psu_fan: + return self.dependency.get_presence() + else: + is_valid, state = self.prsnt_sensor.get_reading() + if is_valid: + if (state & 0b1): + presence = True + return presence + + def get_status(self): + """ + Retrieves the operational status of the FAN + Returns: + bool: True if FAN is operating properly, False if not + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if state & 0b1: + status = True + return status + + def get_direction(self): + """ + Retrieves the fan airfow direction + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + In DellEMC platforms, + - Forward/Exhaust : Air flows from Port side to Fan side. + - Reverse/Intake : Air flows from Fan side to Port side. + """ + direction = [self.FAN_DIRECTION_EXHAUST, self.FAN_DIRECTION_INTAKE] + fan_status = self.get_presence() + if not fan_status: + return None + dir_res = get_ipmitool_raw_output(self.fan_dir_raw_cmd) + if dir_res is not None and len(dir_res) == 1 : + return direction[dir_res[0]] + else: + return None + + def get_speed(self): + """ + Retrieves the speed of the fan + Returns: + int: percentage of the max fan speed + """ + if self.max_speed == 0: + self.max_speed = 23500 + is_valid, fan_speed = self.speed_sensor.get_reading() + if not is_valid or self.max_speed == 0: + return None + else: + speed = (100 * fan_speed)/self.max_speed + return speed + + def get_speed_rpm(self): + """ + Retrieves the speed of the fan + Returns: + int: percentage of the max fan speed + """ + is_valid, fan_speed = self.speed_sensor.get_reading() + return fan_speed if is_valid else None diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..0fdc80e651ed --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan_drawer.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +Z9332F_FANS_PER_FANTRAY = 2 + + +class FanDrawer(FanDrawerBase): + """DellEMC Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + # FanTray is 1-based in DellEMC platforms + self.fantrayindex = fantray_index + 1 + for i in range(Z9332F_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/hwaccess.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/hwaccess.py new file mode 120000 index 000000000000..e8fa340a444d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/hwaccess.py @@ -0,0 +1 @@ +../../common/sonic_platform/hwaccess.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/platform.py new file mode 100644 index 000000000000..996d94cf5a6e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/platform.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """ + DELLEMC Platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py new file mode 100644 index 000000000000..afd9c5a26a64 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.ipmihelper import IpmiSensor, IpmiFru, get_ipmitool_raw_output + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Psu(PsuBase): + """DellEMC Platform-specific PSU class""" + + # { PSU-ID: { Sensor-Name: Sensor-ID } } + SENSOR_MAPPING = { 1: { "State": 0x2f, "Current": 0x37, + "Power": 0x38, "Voltage": 0x36, + "Temperature": 0x35 }, + 2: { "State": 0x39, "Current": 0x41, + "Power": 0x42, "Voltage": 0x40, + "Temperature": 0x3F } } + # ( PSU-ID: FRU-ID } + FRU_MAPPING = { 1: 3, 2: 4 } + + def __init__(self, psu_index): + PsuBase.__init__(self) + # PSU is 1-based in DellEMC platforms + self.index = psu_index + 1 + self.state_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["State"], + is_discrete=True) + self.voltage_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Voltage"]) + self.current_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Current"]) + self.power_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Power"]) + self.temp_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index ]["Temperature"]) + self.fru = IpmiFru(self.FRU_MAPPING[self.index]) + self.psu_type_raw_cmd = "0x3A 0x0B {}".format(psu_index+1) + + self._fan_list.append(Fan(fan_index=self.index, psu_fan=True, dependency=self)) + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + presence = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if state & 0b1: + presence = True + + return presence + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + return self.fru.get_board_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + return self.fru.get_board_serial() + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if (state & 0b1010) == 0: + status = True + + return status + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + is_valid, voltage = self.voltage_sensor.get_reading() + if not is_valid: + return None + + return float(voltage) + + def get_voltage_low_threshold(self): + """ + Returns PSU low threshold in Volts + """ + return 11.4 + + def get_voltage_high_threshold(self): + """ + Returns PSU high threshold in Volts + """ + return 12.6 + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + is_valid, temperature = self.temp_sensor.get_reading() + if not is_valid: + temperature = 0 + + return float(temperature) + + def get_temperature_high_threshold(self): + """ + Returns the high temperature threshold for PSU in Celsius + """ + return 45.0 + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + is_valid, current = self.current_sensor.get_reading() + if not is_valid: + return None + + return float(current) + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + is_valid, power = self.power_sensor.get_reading() + if not is_valid: + return None + + return float(power) + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if (state & 0b1010) == 0: + status = True + + return status + + def get_mfr_id(self): + """ + Retrives the Manufacturer Id of PSU + + Returns: + A string, the manunfacturer id. + """ + return self.fru.get_board_mfr_id() + + def get_type(self): + """ + Retrives the Power Type of PSU + + Returns : + A string, PSU power type + """ + psu_type = [None, 'AC', 'AC', 'DC'] + type_res = get_ipmitool_raw_output(self.psu_type_raw_cmd) + if type_res is not None and len(type_res) == 1 : + return psu_type[type_res[0]] + return None diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py new file mode 100644 index 000000000000..ef6a2c5d339a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py @@ -0,0 +1,1030 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import time + import subprocess + import struct + import mmap + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8472 import sffbase + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +# Enabled when ext_media is available +#ext_media_module = None +#try: +# import ext_media_api as ext_media_module +#except : +# ext_media_module = None +# pass + +PAGE_OFFSET = 0 +KEY_OFFSET = 1 +KEY_WIDTH = 2 +FUNC_NAME = 3 + +QSFP_INFO_OFFSET = 128 +QSFP_DOM_OFFSET = 0 +QSFP_DOM_OFFSET1 = 384 + +SFP_INFO_OFFSET = 0 +SFP_DOM_OFFSET = 256 + +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 7 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', + 'Length OM1(m)', 'Length Cable Assembly(m)') + +qsfp_compliance_code_tup = ( + '10/40G Ethernet Compliance Code', + 'SONET Compliance codes', + 'SAS/SATA compliance codes', + 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', + 'Fibre Channel Speed') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthOM3(UnitsOf10m)', 'LengthCable(UnitsOfm)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +info_dict_keys = ['type', 'hardware_rev', 'serial', + 'manufacturer', 'model', 'connector', + 'encoding', 'ext_identifier', 'ext_rateselect_compliance', + 'cable_type', 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'type_abbrv_name','vendor_date', 'vendor_oui'] + +dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', + 'power_lpmode', 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', 'rx1power', + 'rx2power', 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', 'tx3bias', + 'tx4bias', 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + +threshold_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning'] + +sff8436_parser = { + 'reset_status': [QSFP_DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'], + 'rx_los': [QSFP_DOM_OFFSET, 3, 1, 'parse_dom_tx_rx_los'], + 'tx_fault': [QSFP_DOM_OFFSET, 4, 1, 'parse_dom_tx_fault'], + 'tx_disable': [QSFP_DOM_OFFSET, 86, 1, 'parse_dom_tx_disable'], + 'power_lpmode': [QSFP_DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'power_override': [QSFP_DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'Temperature': [QSFP_DOM_OFFSET, 22, 2, 'parse_temperature'], + 'Voltage': [QSFP_DOM_OFFSET, 26, 2, 'parse_voltage'], + 'ChannelMonitor': [QSFP_DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'], + 'ChannelMonitor_TxPower': + [QSFP_DOM_OFFSET, 34, 24, 'parse_channel_monitor_params_with_tx_power'], + + 'cable_type': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'encoding': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_identifier': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'specification_compliance': + [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type_abbrv_name': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'manufacturer': [QSFP_INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [QSFP_INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [QSFP_INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [QSFP_INFO_OFFSET, 56, 2, 'parse_vendor_rev'], + 'serial': [QSFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [QSFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'dom_capability': [QSFP_INFO_OFFSET, 92, 1, 'parse_dom_capability'], + 'dom_rev': [QSFP_DOM_OFFSET, 1, 1, 'parse_sfp_dom_rev'], + 'ModuleThreshold': [QSFP_DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'], + 'ChannelThreshold': [QSFP_DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'], +} + +sff8472_parser = { + 'Temperature': [SFP_DOM_OFFSET, 96, 2, 'parse_temperature'], + 'Voltage': [SFP_DOM_OFFSET, 98, 2, 'parse_voltage'], + 'ChannelMonitor': [SFP_DOM_OFFSET, 100, 6, 'parse_channel_monitor_params'], + + 'cable_type': [SFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [SFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'type': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'encoding': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'ext_identifier': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'specification_compliance': + [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'type_abbrv_name': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'manufacturer': [SFP_INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [SFP_INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [SFP_INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [SFP_INFO_OFFSET, 56, 4, 'parse_vendor_rev'], + 'serial': [SFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [SFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'ModuleThreshold': [SFP_DOM_OFFSET, 0, 56, 'parse_alarm_warning_threshold'], +} +MEDIA_TYPE_OFFSET = 0 +MEDIA_TYPE_WIDTH = 1 + +SFP_TYPE_LIST = [ + '03' # SFP/SFP+/SFP28 and later +] +QSFP_TYPE_LIST = [ + '0c', # QSFP + '0d', # QSFP+ or later + '11' # QSFP28 or later +] +QSFP_DD_TYPE_LIST = [ + '18' #QSFP-DD Type +] +OSFP_TYPE_LIST=[ + '19' # OSFP 8X Type +] + + + +class Sfp(SfpBase): + """ + DELLEMC Platform-specific Sfp class + """ + BASE_RES_PATH = "/sys/bus/pci/devices/0000:09:00.0/resource0" + _port_to_i2c_mapping = { + 1: 10, + 2: 11, + 3: 12, + 4: 13, + 5: 14, + 6: 15, + 7: 16, + 8: 17, + 9: 18, + 10: 19, + 11: 20, + 12: 21, + 13: 22, + 14: 23, + 15: 24, + 16: 25, + 17: 26, + 18: 27, + 19: 28, + 20: 29, + 21: 30, + 22: 31, + 23: 32, + 24: 33, + 25: 34, + 26: 35, + 27: 36, + 28: 37, + 29: 38, + 30: 39, + 31: 40, + 32: 41, + 33: 1, + 34: 2 + } + + def __init__(self, index, sfp_type, eeprom_path): + SfpBase.__init__(self) + self.index = index + self.eeprom_path = eeprom_path + #sfp_type is the native port type and media_type is the transceiver type + #media_type will be detected in get_transceiver_info + self.sfp_type = sfp_type + self.media_type = self.sfp_type + self.qsfpInfo = sff8436InterfaceId() + self.qsfpDomInfo = sff8436Dom() + self.sfpInfo = sff8472InterfaceId() + self.sfpDomInfo = sff8472Dom(None,1) + + def get_eeprom_sysfs_path(self): + return self.eeprom_path + + def pci_mem_read(self, mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + reg_val = struct.unpack('I', read_data_stream) + mem_val = str(reg_val)[1:-2] + # print "reg_val read:%x"%reg_val + return mem_val + + def pci_mem_write(self, mm, offset, data): + mm.seek(offset) + # print "data to write:%x"%data + mm.write(struct.pack('I', data)) + + def pci_set_value(self, resource, val, offset): + fd = os.open(resource, os.O_RDWR) + mm = mmap.mmap(fd, 0) + val = self.pci_mem_write(mm, offset, val) + mm.close() + os.close(fd) + return val + + def pci_get_value(self, resource, offset): + fd = os.open(resource, os.O_RDWR) + mm = mmap.mmap(fd, 0) + val = self.pci_mem_read(mm, offset) + mm.close() + os.close(fd) + return val + + def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes): + eeprom_raw = [] + try: + eeprom = open(eeprom_path, mode="rb", buffering=0) + except IOError: + return None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom.seek(offset) + raw = eeprom.read(num_bytes) + except IOError: + eeprom.close() + return None + + try: + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except BaseException: + eeprom.close() + return None + + eeprom.close() + return eeprom_raw + + def _get_eeprom_data(self, eeprom_key): + eeprom_data = None + page_offset = None + + if(self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8436_parser[eeprom_key][PAGE_OFFSET] + + sff8436_parser[eeprom_key][KEY_OFFSET]), + sff8436_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 128 is used to retrieve sff8436InterfaceId Info + # Offset 0 is used to retrieve sff8436Dom Info + if (page_offset == 128): + if ( self.qsfpInfo is None): + return None + eeprom_data = getattr( + self.qsfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + if ( self.qsfpDomInfo is None): + return None + eeprom_data = getattr( + self.qsfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + page_offset = sff8472_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8472_parser[eeprom_key][PAGE_OFFSET] + + sff8472_parser[eeprom_key][KEY_OFFSET]), + sff8472_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 0 is used to retrieve sff8472InterfaceId Info + # Offset 256 is used to retrieve sff8472Dom Info + if (page_offset == 0): + if ( self.sfpInfo is None): + return None + eeprom_data = getattr( + self.sfpInfo, sff8472_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + if ( self.sfpDomInfo is None): + return None + eeprom_data = getattr( + self.sfpDomInfo, sff8472_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + + return eeprom_data + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + """ + transceiver_info_dict = {} + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A') + self.media_type = self.set_media_type() + self.reinit_sfp_driver() + + # BaseInformation + try: + iface_data = self._get_eeprom_data('type') + connector = iface_data['data']['Connector']['value'] + encoding = iface_data['data']['EncodingCodes']['value'] + ext_id = iface_data['data']['Extended Identifier']['value'] + rate_identifier = iface_data['data']['RateIdentifier']['value'] + identifier = iface_data['data']['type']['value'] + type_abbrv_name=iface_data['data']['type_abbrv_name']['value'] + if(self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + bit_rate = str( + iface_data['data']['Nominal Bit Rate(100Mbs)']['value']) + for key in qsfp_compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in qsfp_cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + else: + bit_rate = str( + iface_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + for key in sfp_compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in sfp_cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + + transceiver_info_dict['type_abbrv_name']=type_abbrv_name + transceiver_info_dict['type'] = identifier + transceiver_info_dict['connector'] = connector + transceiver_info_dict['encoding'] = encoding + transceiver_info_dict['ext_identifier'] = ext_id + transceiver_info_dict['ext_rateselect_compliance'] = rate_identifier + transceiver_info_dict['cable_type'] = cable_type + transceiver_info_dict['cable_length'] = cable_length + transceiver_info_dict['nominal_bit_rate'] = bit_rate + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + except (ValueError, TypeError) : pass + + # Vendor Date + try: + vendor_date_data = self._get_eeprom_data('vendor_date') + vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['vendor_date'] = vendor_date + except (ValueError, TypeError) : pass + + # Vendor Name + try: + vendor_name_data = self._get_eeprom_data('manufacturer') + vendor_name = vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['manufacturer'] = vendor_name + except (ValueError, TypeError) : pass + + # Vendor OUI + try: + vendor_oui_data = self._get_eeprom_data('vendor_oui') + vendor_oui = vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_oui'] = vendor_oui + except (ValueError, TypeError) : pass + + # Vendor PN + try: + vendor_pn_data = self._get_eeprom_data('model') + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['model'] = vendor_pn + except (ValueError, TypeError) : pass + + # Vendor Revision + try: + vendor_rev_data = self._get_eeprom_data('hardware_rev') + vendor_rev = vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['hardware_rev'] = vendor_rev + except (ValueError, TypeError) : pass + + # Vendor Serial Number + try: + vendor_sn_data = self._get_eeprom_data('serial') + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['serial'] = vendor_sn + except (ValueError, TypeError) : pass + + # Attempt ext_media read +# if ext_media_module is not None: +# ext_media_dict = ext_media_module.get_ext_media_info(self) +# for key in ext_media_dict: +# value = ext_media_dict[key] +# if value in [None, 'None', 'none','n/a', '']: +# value = 'N/A' +# transceiver_info_dict[key] = str(value) + + return transceiver_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + """ + transceiver_dom_threshold_dict = {} + transceiver_dom_threshold_dict = dict.fromkeys( + threshold_dict_keys, 'N/A') + + try: + # Module Threshold + module_threshold_data = self._get_eeprom_data('ModuleThreshold') + if (self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['data']['VccLowWarning']['value'] + else: #SFP + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['data']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['data']['VoltageLowWarning']['value'] + transceiver_dom_threshold_dict['txbiashighalarm'] = module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = module_threshold_data['data']['BiasLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['txpowerlowalarm'] = module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['txpowerhighwarning'] = module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_dict['txpowerlowwarning'] = module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_dict['rxpowerhighalarm'] = module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = module_threshold_data['data']['RXPowerLowWarning']['value'] + except (ValueError, TypeError) : pass + + try: + if (self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + channel_threshold_data = self._get_eeprom_data('ChannelThreshold') + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['data']['TxBiasLowWarning']['value'] + + except (ValueError, TypeError) : pass + return transceiver_dom_threshold_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + """ + tx_bias_list = [] + rx_power_list = [] + transceiver_dom_dict = {} + transceiver_dom_dict = dict.fromkeys(dom_dict_keys, 'N/A') + + # RxLos + rx_los = self.get_rx_los() + + # TxFault + tx_fault = self.get_tx_fault() + + # ResetStatus + reset_state = self.get_reset_status() + + # LowPower Mode + lp_mode = self.get_lpmode() + + # TxDisable + tx_disable = self.get_tx_disable() + + # TxDisable Channel + tx_disable_channel = self.get_tx_disable_channel() + + # Temperature + temperature = self.get_temperature() + + # Voltage + voltage = self.get_voltage() + + # Channel Monitor + tx_power_list = self.get_tx_power() + + # tx bias + tx_bias_list = self.get_tx_bias() + + # rx power + rx_power_list = self.get_rx_power() + + if tx_bias_list is not None: + transceiver_dom_dict['tx1bias'] = tx_bias_list[0] + transceiver_dom_dict['tx2bias'] = tx_bias_list[1] + transceiver_dom_dict['tx3bias'] = tx_bias_list[2] + transceiver_dom_dict['tx4bias'] = tx_bias_list[3] + + if rx_power_list is not None: + transceiver_dom_dict['rx1power'] = rx_power_list[0] + transceiver_dom_dict['rx2power'] = rx_power_list[1] + transceiver_dom_dict['rx3power'] = rx_power_list[2] + transceiver_dom_dict['rx4power'] = rx_power_list[3] + + if tx_power_list is not None: + transceiver_dom_dict['tx1power'] = tx_power_list[0] + transceiver_dom_dict['tx2power'] = tx_power_list[1] + transceiver_dom_dict['tx3power'] = tx_power_list[2] + transceiver_dom_dict['tx4power'] = tx_power_list[3] + + transceiver_dom_dict['rx_los'] = rx_los + transceiver_dom_dict['tx_fault'] = tx_fault + transceiver_dom_dict['reset_status'] = reset_state + transceiver_dom_dict['power_lpmode'] = lp_mode + transceiver_dom_dict['tx_disable'] = tx_disable + transceiver_dom_dict['tx_disable_channel'] = tx_disable_channel + transceiver_dom_dict['temperature'] = temperature + transceiver_dom_dict['voltage'] = voltage + + return transceiver_dom_dict + + def get_name(self): + """ + Retrieves the name of the sfp + Returns : QSFP or QSFP+ or QSFP28 + """ + try: + iface_data = self._get_eeprom_data('type') + identifier = iface_data['data']['type']['value'] + except (TypeError, ValueError): + return 'N/A' + return identifier + + def get_presence(self): + """ + Retrieves the presence of the sfp + Returns : True if sfp is present and false if it is absent + """ + # Check for invalid port_num + mask = {'QSFP' : (1 << 4), 'SFP' : (1 << 0)} + # Port offset starts with 0x4004 + port_offset = 16388 + ((self.index-1) * 16) + + try: + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + # ModPrsL is active low + if reg_value & mask[self.sfp_type] == 0: + return True + except ValueError: pass + + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the sfp + """ + try: + vendor_pn_data = self._get_eeprom_data('model') + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + except (TypeError, ValueError): + return 'N/A' + + return vendor_pn + + def get_serial(self): + """ + Retrieves the serial number of the sfp + """ + try: + vendor_sn_data = self._get_eeprom_data('serial') + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + except (TypeError, ValueError): + return 'N/A' + + return vendor_sn + + def get_reset_status(self): + """ + Retrives the reset status of SFP + """ + reset_status = False + try: + if (self.sfp_type == 'QSFP'): + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Mask off 4th bit for reset status + mask = (1 << 4) + reset_status = not (reg_value & mask) + except ValueError: pass + + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + """ + rx_los = False + try: + if (self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + rx_los_data = self._get_eeprom_data('rx_los') + # As the function expects a single boolean, if any one channel experience LOS, + # is considered LOS for QSFP + for rx_los_id in ('Rx1LOS', 'Rx2LOS', 'Rx3LOS', 'Rx4LOS') : + rx_los |= (rx_los_data['data'][rx_los_id]['value'] is 'On') + else: + rx_los_data = self._read_eeprom_bytes(self.eeprom_path, SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + data = int(rx_los_data[0], 16) + rx_los = sffbase().test_bit(data, 1) != 0 + except (TypeError, ValueError): + return 'N/A' + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + """ + tx_fault = False + try: + if (self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + tx_fault_data = self._get_eeprom_data('tx_fault') + for tx_fault_id in ('Tx1Fault', 'Tx2Fault', 'Tx3Fault', 'Tx4Fault') : + tx_fault |= (tx_fault_data['data'][tx_fault_id]['value'] is 'On') + else: + tx_fault_data = self._read_eeprom_bytes(self.eeprom_path, SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + data = int(tx_fault_data[0], 16) + tx_fault = (sffbase().test_bit(data, 2) != 0) + except (TypeError, ValueError): + return 'N/A' + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + """ + tx_disable = False + try: + if (self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + tx_disable_data = self._get_eeprom_data('tx_disable') + for tx_disable_id in ('Tx1Disable', 'Tx2Disable', 'Tx3Disable', 'Tx4Disable'): + tx_disable |= (tx_disable_data['data'][tx_disable_id]['value'] is 'On') + else: + tx_disable_data = self._read_eeprom_bytes(self.eeprom_path, SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + data = int(tx_disable_data[0], 16) + tx_disable_hard = (sffbase().test_bit(data, SFP_TX_DISABLE_HARD_BIT) != 0) + tx_disable_soft = (sffbase().test_bit(data, SFP_TX_DISABLE_SOFT_BIT) != 0) + tx_disable = tx_disable_hard | tx_disable_soft + except (TypeError, ValueError): + return 'N/A' + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + """ + tx_disable_channel = 0 + try: + if (self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + tx_disable_data = self._get_eeprom_data('tx_disable') + for tx_disable_id in ('Tx1Disable', 'Tx2Disable', 'Tx3Disable', 'Tx4Disable'): + tx_disable_channel <<= 1 + tx_disable_channel |= (tx_disable_data['data']['Tx1Disable']['value'] is 'On') + except (TypeError, ValueError): + return 'N/A' + return tx_disable_channel + + def get_lpmode(self): + """ + Retrieves the lpmode(low power mode) of this SFP + """ + lpmode_state = False + try: + if (self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Mask off 6th bit for lpmode + mask = (1 << 6) + + lpmode_state = (reg_value & mask) + except ValueError: pass + return lpmode_state + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + """ + power_override_state = False + + try: + if (self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + power_override_data = self._get_eeprom_data('power_override') + power_override = power_override_data['data']['PowerOverRide']['value'] + power_override_state = (power_override is 'On') + except (TypeError, ValueError): pass + return power_override_state + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + """ + temperature = None + try : + temperature_data = self._get_eeprom_data('Temperature') + temperature = temperature_data['data']['Temperature']['value'] + except (TypeError, ValueError): + return None + return temperature + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + """ + voltage = None + try: + voltage_data = self._get_eeprom_data('Voltage') + voltage = voltage_data['data']['Vcc']['value'] + except (TypeError, ValueError): + return None + return voltage + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + """ + tx_bias_list = [] + try: + tx_bias_data = self._get_eeprom_data('ChannelMonitor') + if (self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + for tx_bias_id in ('TX1Bias', 'TX2Bias', 'TX3Bias', 'TX4Bias') : + tx_bias = tx_bias_data['data'][tx_bias_id]['value'] + tx_bias_list.append(tx_bias) + else: + tx1_bias = tx_bias_data['data']['TXBias']['value'] + tx_bias_list = [tx1_bias, "N/A", "N/A", "N/A"] + except (TypeError, ValueError): + return None + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + """ + rx_power_list = [] + try: + rx_power_data = self._get_eeprom_data('ChannelMonitor') + if (self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + for rx_power_id in ('RX1Power', 'RX2Power', 'RX3Power', 'RX4Power'): + rx_power = rx_power_data['data'][rx_power_id]['value'] + rx_power_list.append(rx_power) + else: + rx1_pw = rx_power_data['data']['RXPower']['value'] + rx_power_list = [rx1_pw, "N/A", "N/A", "N/A"] + except (TypeError, ValueError): + return None + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + """ + tx_power_list = [] + try: + if(self.media_type == 'QSFP' or self.media_type == 'QSFP-DD'): + # 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. + qspf_dom_capability_data = self._get_eeprom_data('dom_capability') + qsfp_dom_rev_data = self._get_eeprom_data('dom_rev') + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['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. + if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')): + return None + channel_monitor_data = self._get_eeprom_data('ChannelMonitor_TxPower') + for tx_power_id in ('TX1Power', 'TX2Power', 'TX3Power', 'TX4Power'): + tx_pw = channel_monitor_data['data'][tx_power_id]['value'] + tx_power_list.append(tx_pw) + else: + channel_monitor_data = self._get_eeprom_data('ChannelMonitor') + tx1_pw = channel_monitor_data['data']['TXPower']['value'] + tx_power_list = [tx1_pw, 'N/A', 'N/A', 'N/A'] + except (TypeError, ValueError): + return None + return tx_power_list + + def reset(self): + """ + Reset the SFP and returns all user settings to their default state + """ + try: + if (self.sfp_type == 'QSFP'): + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Mask off 4th bit for reset + mask = (1 << 4) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + # Sleep 1 second to allow it to settle + time.sleep(1) + + reg_value = reg_value | mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + except ValueError: + return False + return True + + def set_lpmode(self, lpmode): + """ + Sets the lpmode(low power mode) of this SFP + """ + try: + if (self.sfp_type == 'QSFP'): + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Mask off 6th bit for lowpower mode + mask = (1 << 6) + + # LPMode is active high; set or clear the bit accordingly + if lpmode is True: + reg_value = reg_value | mask + else: + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + except ValueError: + return False + return True + + def get_intl_state(self): + """ + Sets the intL (interrupt; active low) pin of this SFP + """ + intl_state = True + try: + if (self.sfp_type == 'QSFP'): + # Port offset starts with 0x4004 + port_offset = 16388 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Mask off 4th bit for intL + mask = (1 << 4) + + intl_state = (reg_value & mask) + except ValueError: pass + return intl_state + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + """ + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + """ + return False + + def get_status(self): + """ + Retrieves the operational status of the device + """ + reset = self.get_reset_status() + return (not reset) + + def get_port_form_factor(self): + """ + Retrieves the native port type + """ + return self.sfp_type + + def get_max_port_power(self): + """ + Retrieves the maximum power allowed on the port in watts + + *** + This method of fetching power values is not ideal. + TODO: enhance by placing power limits in config file + *** + """ + return (12.0 if self.sfp_type=='QSFP' else 2.5) + + def set_media_type(self): + """ + Reads optic eeprom byte to determine media type inserted + """ + eeprom_raw = [] + eeprom_raw = self._read_eeprom_bytes(self.eeprom_path, MEDIA_TYPE_OFFSET, MEDIA_TYPE_WIDTH) + if eeprom_raw is not None: + if eeprom_raw[0] in SFP_TYPE_LIST: + self.media_type = 'SFP' + elif eeprom_raw[0] in QSFP_TYPE_LIST: + self.media_type = 'QSFP' + elif eeprom_raw[0] in QSFP_DD_TYPE_LIST: + self.media_type = 'QSFP-DD' + else: + #Set native port type if EEPROM type is not recognized/readable + self.media_type = self.sfp_type + else: + self.media_type = self.sfp_type + + return self.media_type + + def reinit_sfp_driver(self): + """ + Changes the driver based on media type detected + """ + del_sfp_path = "/sys/class/i2c-adapter/i2c-{0}/delete_device".format(self._port_to_i2c_mapping[self.index]) + new_sfp_path = "/sys/class/i2c-adapter/i2c-{0}/new_device".format(self._port_to_i2c_mapping[self.index]) + driver_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/name".format(self._port_to_i2c_mapping[self.index]) + delete_device = "echo 0x50 >" + del_sfp_path + + try: + with os.fdopen(os.open(driver_path, os.O_RDONLY)) as fd: + driver_name = fd.read() + driver_name = driver_name.rstrip('\r\n') + driver_name = driver_name.lstrip(" ") + + #Avoid re-initialization of the QSFP/SFP optic on QSFP/SFP port. + if (self.media_type == 'SFP' and (driver_name == 'optoe1' or driver_name == 'optoe3')): + subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE) + new_device = "echo optoe2 0x50 >" + new_sfp_path + subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE) + time.sleep(2) + elif (self.media_type == 'QSFP' and (driver_name == 'optoe2' or driver_name == 'optoe3')): + subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE) + new_device = "echo optoe1 0x50 >" + new_sfp_path + subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE) + time.sleep(2) + elif (self.media_type == 'QSFP-DD' and (driver_name == 'optoe1' or driver_name == 'optoe2')): + subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE) + new_device = "echo optoe3 0x50 >" + new_sfp_path + subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE) + time.sleep(2) + + except IOError as e: + print("Error: Unable to open file: %s" % str(e)) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/thermal.py new file mode 100644 index 000000000000..1c7fe59857a3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/thermal.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + from sonic_platform_base.thermal_base import ThermalBase + from sonic_platform.ipmihelper import IpmiSensor +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """DellEMC Platform-specific Thermal class""" + + # [ Sensor-Name, Sensor-ID ] + SENSOR_MAPPING = [ + ['CPU On-board', 0x5], + ['Baseboard U3', 0x4], + ['SW Internal', 0x61], + ['Fan U52', 0x0], + ['Fan U17', 0x1], + ['SW U52', 0x2], + ['SW U16', 0x3], + ['PSU1 Inlet', 0x34], + ['PSU1 Hotspot', 0x35], + ['PSU2 Inlet', 0x3E], + ['PSU2 Hotspot', 0x3F], + ['SW U04', 0x4F], + ['SW U14', 0x56], + ['SW U4403', 0x5D] + ] + + def __init__(self, thermal_index=0): + ThermalBase.__init__(self) + self.index = thermal_index + 1 + self.sensor = IpmiSensor(self.SENSOR_MAPPING[self.index - 1][1]) + + def get_name(self): + """ + Retrieves the name of the thermal + + Returns: + string: The name of the thermal + """ + return self.SENSOR_MAPPING[self.index - 1][0] + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return 'NA' + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + is_valid, temperature = self.sensor.get_reading() + if not is_valid: + temperature = 0 + + return float(temperature) + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + is_valid, high_threshold = self.sensor.get_threshold("UpperNonCritical") + if not is_valid: + return super(Thermal, self).get_high_threshold() + + return float(high_threshold) + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + is_valid, low_threshold = self.sensor.get_threshold("LowerNonRecoverable") + if not is_valid: + low_threshold = 0 + + return float(low_threshold) + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + Returns: + A float number, the high critical threshold temperature of + thermal in Celsius up to nearest thousandth of one degree + Celsius, e.g. 30.125 + """ + is_valid, high_crit_threshold = self.sensor.get_threshold("UpperCritical") + if not is_valid: + return super(Thermal, self).get_high_critical_threshold() + + return float(high_crit_threshold) + + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/watchdog.py new file mode 100644 index 000000000000..265fab66d922 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/watchdog.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python + +######################################################################## +# +# DELLEMC Z9332F +# +# Abstract base class for implementing a platform-specific class with +# which to interact with a hardware watchdog module in SONiC +# +######################################################################## + +try: + import ctypes + import subprocess + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class _timespec(ctypes.Structure): + _fields_ = [ + ('tv_sec', ctypes.c_long), + ('tv_nsec', ctypes.c_long) + ] + + +class Watchdog(WatchdogBase): + """ + Abstract base class for interfacing with a hardware watchdog module + """ + + TIMERS = [15,20,30,40,50,60,65,70] + + armed_time = 0 + timeout = 0 + CLOCK_MONOTONIC = 1 + + def __init__(self): + self._librt = ctypes.CDLL('librt.so.1', use_errno=True) + self._clock_gettime = self._librt.clock_gettime + self._clock_gettime.argtypes=[ctypes.c_int, ctypes.POINTER(_timespec)] + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + except OSError: + result = None + + return result + + def _get_reg_val(self): + # 0x31 = CPLD I2C Base Address + # 0x07 = Watchdog Function Register + value = self._get_command_result("/usr/sbin/i2cget -y 601 0x31 0x07") + if not value: + return None + else: + return int(value, 16) + + def _set_reg_val(self,val): + # 0x31 = CPLD I2C Base Address + # 0x07 = Watchdog Function Register + value = self._get_command_result("/usr/sbin/i2cset -y 601 0x31 0x07 %s" + % (val)) + return value + + def _get_time(self): + """ + To get clock monotonic time + """ + ts = _timespec() + if self._clock_gettime(self.CLOCK_MONOTONIC, ctypes.pointer(ts)) != 0: + self._errno = ctypes.get_errno() + return 0 + return ts.tv_sec + ts.tv_nsec * 1e-9 + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* + available value. + + Returns: + An integer specifying the *actual* number of seconds the + watchdog was armed with. On failure returns -1. + """ + timer_offset = -1 + for key,timer_seconds in enumerate(self.TIMERS): + if seconds <= timer_seconds: + timer_offset = key + seconds = timer_seconds + break + + if timer_offset == -1: + return -1 + + # Extracting 5th to 7th bits for WD timer values + # 000 - 15 sec + # 001 - 20 sec + # 010 - 30 sec + # 011 - 40 sec + # 100 - 50 sec + # 101 - 60 sec + # 110 - 65 sec + # 111 - 70 sec + reg_val = self._get_reg_val() + wd_timer_offset = (reg_val >> 4) & 0x7 + + if wd_timer_offset != timer_offset: + # Setting 5th to 7th bits + # value from timer_offset + self.disarm() + self._set_reg_val(reg_val | (timer_offset << 4)) + + if self.is_armed(): + # Setting last bit to WD Timer punch + # Last bit = WD Timer punch + self._set_reg_val(reg_val & 0xFE) + + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + else: + # Setting 4th bit to enable WD + # 4th bit = Enable WD + reg_val = self._get_reg_val() + self._set_reg_val(reg_val | 0x8) + + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + + + def disarm(self): + """ + Disarm the hardware watchdog + + Returns: + A boolean, True if watchdog is disarmed successfully, False + if not + """ + if self.is_armed(): + # Setting 4th bit to disable WD + # 4th bit = Disable WD + reg_val = self._get_reg_val() + self._set_reg_val(reg_val & 0xF7) + + self.armed_time = 0 + self.timeout = 0 + return True + + return False + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + + Returns: + A boolean, True if watchdog is armed, False if not + """ + + # Extracting 4th bit to get WD Enable/Disable status + # 0 - Disabled WD + # 1 - Enabled WD + reg_val = self._get_reg_val() + wd_offset = (reg_val >> 3) & 1 + + return bool(wd_offset) + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds + remaining on the watchdog timer + + Returns: + An integer specifying the number of seconds remaining on + their watchdog timer. If the watchdog is not armed, returns + -1. + + S5232 doesnot have hardware support to show remaining time. + Due to this limitation, this API is implemented in software. + This API would return correct software time difference if it + is called from the process which armed the watchdog timer. + If this API called from any other process, it would return + 0. If the watchdog is not armed, this API would return -1. + """ + if not self.is_armed(): + return -1 + + if self.armed_time > 0 and self.timeout != 0: + cur_time = self._get_time() + + if cur_time <= 0: + return 0 + + diff_time = int(cur_time - self.armed_time) + + if diff_time > self.timeout: + return self.timeout + else: + return self.timeout - diff_time + + return 0 + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/systemd/platform-modules-z9332f.service b/platform/broadcom/sonic-platform-modules-dell/z9332f/systemd/platform-modules-z9332f.service new file mode 100644 index 000000000000..348313718a70 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/systemd/platform-modules-z9332f.service @@ -0,0 +1,13 @@ +[Unit] +Description=Dell Z9332f Platform modules +Before=pmon.service determine-reboot-cause.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/z9332f_platform.sh init +ExecStop=/usr/local/bin/z9332f_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-delta/.gitignore b/platform/broadcom/sonic-platform-modules-delta/.gitignore new file mode 100644 index 000000000000..2490baa9d1e2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/.gitignore @@ -0,0 +1,59 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-delta/LICENSE b/platform/broadcom/sonic-platform-modules-delta/LICENSE new file mode 100644 index 000000000000..ea87fe9caabe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Delta Networks, Inc. + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/cfg/ag5648-modules.conf b/platform/broadcom/sonic-platform-modules-delta/ag5648/cfg/ag5648-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/cfg/ag5648-modules.conf @@ -0,0 +1,13 @@ +# /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-delta/ag5648/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/Makefile new file mode 100644 index 000000000000..012f708ec46a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dni_ag5648_psu.o dni_emc2305.o delta_ag5648_platform.o + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/delta_ag5648_platform.c b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/delta_ag5648_platform.c new file mode 100644 index 000000000000..1ebcaa39d026 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/delta_ag5648_platform.c @@ -0,0 +1,1644 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUS4_DEV_NUM 54 +#define DEFAULT_NUM 1 +#define BUS4_BASE_NUM 10 +#define BUS4_MUX_REG 0x18 + +#define TEMP_FAN_VAL 0x06 +#define FANIO_CTL_VAL 0x07 +#define FAN_CTRL_VAL 0x05 +#define PSU1_VAL 0x00 +#define PSU2_VAL 0x20 +#define HOT_SWAP1_VAL 0x10 +#define HOT_SWAP2_VAL 0x30 + +#define SYSTEM_CPLD_REG 0x31 +#define MASTER_CPLD_REG 0x35 +#define SLAVE_CPLD_REG 0x39 + +#define FAN_LED_REG 0x05 +#define LED_REG 0x04 + +#define SFP_PRESENCE_1 0x08 +#define SFP_PRESENCE_2 0x09 +#define SFP_PRESENCE_3 0x0a +#define SFP_PRESENCE_4 0x0b +#define SFP_PRESENCE_5 0x0c +#define SFP_PRESENCE_6 0x08 +#define SFP_PRESENCE_7 0x09 +#define QSFP_PRESENCE 0x12 + +#define QSFP_RESPONSE 0x10 +#define QSFP_LP_MODE 0x11 +#define QSFP_RESET 0x13 + + +#define SFF8436_INFO(data) \ + .type = "sff8436", .addr = 0x50, .platform_data = (data) + +#define SFF_8436_PORT(eedata) \ + .byte_len = 256, .page_size = 1, .flags = SFF_8436_FLAG_READONLY + +#define ag5648_i2c_device_num(NUM){ \ + .name = "delta-ag5648-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &ag5648_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +/*Define struct to get client of i2c_new_deivce */ +struct i2c_client * i2c_client_9548; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, +}; + +unsigned char reverse_8bits(unsigned char c) +{ + unsigned char s = 0; + int i; + for (i = 0; i < 8; ++i) { + s <<= 1; + s |= c & 1; + c >>= 1; + } + return s; +} +/*---------------- I2C device - start ------------- */ +static void device_release(struct device *dev) +{ + return; +} + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; +/* pca9548 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = { + { .adap_id = 2, + .deselect_on_exit = 1, + }, + { .adap_id = 3, + .deselect_on_exit = 1, + }, + { .adap_id = 4, + .deselect_on_exit = 1, + }, + { .adap_id = 5, + .deselect_on_exit = 1, + }, + { .adap_id = 6, + .deselect_on_exit = 1, + }, + { .adap_id = 7, + .deselect_on_exit = 1, + }, + { .adap_id = 8, + .deselect_on_exit = 1, + }, + { .adap_id = 9, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = { + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct i2c_board_info __initdata i2c_info_pca9548[] = +{ + { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &pca954x_data, + }, +}; + + +static struct sff_8436_platform_data sff_8436_port[] = { + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, + { SFF_8436_PORT() }, +}; + + +static struct i2c_device_platform_data ag5648_i2c_device_platform_data[] = { + { + /* id eeprom (0x53) */ + .parent = 2, + .info = { I2C_BOARD_INFO("24c02", 0x53) }, + .client = NULL, + }, + { + /* tmp75 (0x4d) */ + .parent = 2, + .info = { I2C_BOARD_INFO("tmp75", 0x4d) }, + .client = NULL, + }, + { + /* tmp75 (0x49) */ + .parent = 3, + .info = { I2C_BOARD_INFO("tmp75", 0x49) }, + .client = NULL, + }, + { + /* tmp75 (0x4b) */ + .parent = 3, + .info = { I2C_BOARD_INFO("tmp75", 0x4b) }, + }, + { + /* tmp75 (0x4c) */ + .parent = 3, + .info = { I2C_BOARD_INFO("tmp75", 0x4c) }, + .client = NULL, + }, + { + /* tmp75 (0x4e) */ + .parent = 3, + .info = { I2C_BOARD_INFO("tmp75", 0x4e) }, + .client = NULL, + }, + { + /* tmp75 (0x4f) */ + .parent = 3, + .info = { I2C_BOARD_INFO("tmp75", 0x4f) }, + }, + { + /* tmp75 (0x4d) */ + .parent = 3, + .info = { I2C_BOARD_INFO("emc2305", 0x4d) }, + .client = NULL, + }, + { + /* tmp75 (0x4d) */ + .parent = 5, + .info = { I2C_BOARD_INFO("emc2305", 0x4d) }, + .client = NULL, + }, + { + /* tmp75 (0x40) */ + .parent = 3, + .info = { I2C_BOARD_INFO("ltc4215", 0x40) }, + .client = NULL, + }, + { + /* tmp75 (0x42) */ + .parent = 3, + .info = { I2C_BOARD_INFO("ltc4215", 0x42) }, + }, + { + /* psu1 (0x59) */ + .parent = 6, + .info = { I2C_BOARD_INFO("dni_ag5648_psu", 0x59) }, + .client = NULL, + }, + { + /* psu2 (0x58) */ + .parent = 6, + .info = { I2C_BOARD_INFO("dni_ag5648_psu", 0x58) }, + }, + { + /* qsfp 1 (0x50) */ + .parent = 10, + .info = { SFF8436_INFO(&sff_8436_port[0]) }, + .client = NULL, + }, + { + /* qsfp 2 (0x50) */ + .parent = 11, + .info = { SFF8436_INFO(&sff_8436_port[1]) }, + .client = NULL, + }, + { + /* qsfp 3 (0x50) */ + .parent = 12, + .info = { SFF8436_INFO(&sff_8436_port[2]) }, + .client = NULL, + }, + { + /* qsfp 4 (0x50) */ + .parent = 13, + .info = { SFF8436_INFO(&sff_8436_port[3]) }, + .client = NULL, + }, + { + /* qsfp 5 (0x50) */ + .parent = 14, + .info = { SFF8436_INFO(&sff_8436_port[4]) }, + .client = NULL, + }, + { + /* qsfp 6 (0x50) */ + .parent = 15, + .info = { SFF8436_INFO(&sff_8436_port[5]) }, + .client = NULL, + }, + { + /* qsfp 7 (0x50) */ + .parent = 16, + .info = { SFF8436_INFO(&sff_8436_port[6]) }, + .client = NULL, + }, + { + /* qsfp 8 (0x50) */ + .parent = 17, + .info = { SFF8436_INFO(&sff_8436_port[7]) }, + .client = NULL, + }, + { + /* qsfp 9 (0x50) */ + .parent = 18, + .info = { SFF8436_INFO(&sff_8436_port[8]) }, + .client = NULL, + }, + { + /* qsfp 10 (0x50) */ + .parent = 19, + .info = { SFF8436_INFO(&sff_8436_port[9]) }, + .client = NULL, + }, + { + /* qsfp 11 (0x50) */ + .parent = 20, + .info = { SFF8436_INFO(&sff_8436_port[10]) }, + .client = NULL, + }, + { + /* qsfp 12 (0x50) */ + .parent = 21, + .info = { SFF8436_INFO(&sff_8436_port[11]) }, + .client = NULL, + }, + { + /* qsfp 13 (0x50) */ + .parent = 22, + .info = { SFF8436_INFO(&sff_8436_port[12]) }, + .client = NULL, + }, + { + /* qsfp 14 (0x50) */ + .parent = 23, + .info = { SFF8436_INFO(&sff_8436_port[13]) }, + .client = NULL, + }, + { + /* qsfp 15 (0x50) */ + .parent = 24, + .info = { SFF8436_INFO(&sff_8436_port[14]) }, + .client = NULL, + }, + { + /* qsfp 16 (0x50) */ + .parent = 25, + .info = { SFF8436_INFO(&sff_8436_port[15]) }, + .client = NULL, + }, + { + /* qsfp 17 (0x50) */ + .parent = 26, + .info = { SFF8436_INFO(&sff_8436_port[16]) }, + .client = NULL, + }, + { + /* qsfp 18 (0x50) */ + .parent = 27, + .info = { SFF8436_INFO(&sff_8436_port[17]) }, + .client = NULL, + }, + { + /* qsfp 19 (0x50) */ + .parent = 28, + .info = { SFF8436_INFO(&sff_8436_port[18]) }, + .client = NULL, + }, + { + /* qsfp 20 (0x50) */ + .parent = 29, + .info = { SFF8436_INFO(&sff_8436_port[19]) }, + .client = NULL, + }, + { + /* qsfp 21 (0x50) */ + .parent = 30, + .info = { SFF8436_INFO(&sff_8436_port[20]) }, + .client = NULL, + }, + { + /* qsfp 22 (0x50) */ + .parent = 31, + .info = { SFF8436_INFO(&sff_8436_port[21]) }, + .client = NULL, + }, + { + /* qsfp 23 (0x50) */ + .parent = 32, + .info = { SFF8436_INFO(&sff_8436_port[22]) }, + .client = NULL, + }, + { + /* qsfp 24 (0x50) */ + .parent = 33, + .info = { SFF8436_INFO(&sff_8436_port[23]) }, + .client = NULL, + }, + { + /* qsfp 25 (0x50) */ + .parent = 34, + .info = { SFF8436_INFO(&sff_8436_port[24]) }, + .client = NULL, + }, + { + /* qsfp 26 (0x50) */ + .parent = 35, + .info = { SFF8436_INFO(&sff_8436_port[25]) }, + .client = NULL, + }, + { + /* qsfp 27 (0x50) */ + .parent = 36, + .info = { SFF8436_INFO(&sff_8436_port[26]) }, + .client = NULL, + }, + { + /* qsfp 28 (0x50) */ + .parent = 37, + .info = { SFF8436_INFO(&sff_8436_port[27]) }, + .client = NULL, + }, + { + /* qsfp 29 (0x50) */ + .parent = 38, + .info = { SFF8436_INFO(&sff_8436_port[28]) }, + .client = NULL, + }, + { + /* qsfp 30 (0x50) */ + .parent = 39, + .info = { SFF8436_INFO(&sff_8436_port[29]) }, + .client = NULL, + }, + { + /* qsfp 31 (0x50) */ + .parent = 40, + .info = { SFF8436_INFO(&sff_8436_port[30]) }, + .client = NULL, + }, + { + /* qsfp 32 (0x50) */ + .parent = 41, + .info = { SFF8436_INFO(&sff_8436_port[31]) }, + .client = NULL, + }, + { + /* qsfp 33 (0x50) */ + .parent = 42, + .info = { SFF8436_INFO(&sff_8436_port[32]) }, + .client = NULL, + }, + { + /* qsfp 34 (0x50) */ + .parent = 43, + .info = { SFF8436_INFO(&sff_8436_port[33]) }, + .client = NULL, + }, + { + /* qsfp 35 (0x50) */ + .parent = 44, + .info = { SFF8436_INFO(&sff_8436_port[34]) }, + .client = NULL, + }, + { + /* qsfp 36 (0x50) */ + .parent = 45, + .info = { SFF8436_INFO(&sff_8436_port[35]) }, + .client = NULL, + }, + { + /* qsfp 37 (0x50) */ + .parent = 46, + .info = { SFF8436_INFO(&sff_8436_port[36]) }, + .client = NULL, + }, + { + /* qsfp 38 (0x50) */ + .parent = 47, + .info = { SFF8436_INFO(&sff_8436_port[37]) }, + .client = NULL, + }, + { + /* qsfp 39 (0x50) */ + .parent = 48, + .info = { SFF8436_INFO(&sff_8436_port[38]) }, + .client = NULL, + }, + { + /* qsfp 40 (0x50) */ + .parent = 49, + .info = { SFF8436_INFO(&sff_8436_port[39]) }, + .client = NULL, + }, + { + /* qsfp 41 (0x50) */ + .parent = 50, + .info = { SFF8436_INFO(&sff_8436_port[40]) }, + .client = NULL, + }, + { + /* qsfp 42 (0x50) */ + .parent = 51, + .info = { SFF8436_INFO(&sff_8436_port[41]) }, + .client = NULL, + }, + { + /* qsfp 43 (0x50) */ + .parent = 52, + .info = { SFF8436_INFO(&sff_8436_port[42]) }, + .client = NULL, + }, + { + /* qsfp 44 (0x50) */ + .parent = 53, + .info = { SFF8436_INFO(&sff_8436_port[43]) }, + .client = NULL, + }, + { + /* qsfp 45 (0x50) */ + .parent = 54, + .info = { SFF8436_INFO(&sff_8436_port[44]) }, + .client = NULL, + }, + { + /* qsfp 46 (0x50) */ + .parent = 55, + .info = { SFF8436_INFO(&sff_8436_port[45]) }, + .client = NULL, + }, + { + /* qsfp 47 (0x50) */ + .parent = 56, + .info = { SFF8436_INFO(&sff_8436_port[46]) }, + .client = NULL, + }, + { + /* qsfp 48 (0x50) */ + .parent = 57, + .info = { SFF8436_INFO(&sff_8436_port[47]) }, + .client = NULL, + }, + { + /* qsfp 49 (0x50) */ + .parent = 58, + .info = { SFF8436_INFO(&sff_8436_port[48]) }, + .client = NULL, + }, + { + /* qsfp 50 (0x50) */ + .parent = 59, + .info = { SFF8436_INFO(&sff_8436_port[49]) }, + .client = NULL, + }, + { + /* qsfp 51 (0x50) */ + .parent = 60, + .info = { SFF8436_INFO(&sff_8436_port[50]) }, + .client = NULL, + }, + { + /* qsfp 52 (0x50) */ + .parent = 61, + .info = { SFF8436_INFO(&sff_8436_port[51]) }, + .client = NULL, + }, + { + /* qsfp 53 (0x50) */ + .parent = 62, + .info = { SFF8436_INFO(&sff_8436_port[52]) }, + .client = NULL, + }, + { + /* qsfp 54 (0x50) */ + .parent = 63, + .info = { SFF8436_INFO(&sff_8436_port[53]) }, + .client = NULL, + }, +}; + + +static struct platform_device ag5648_i2c_device[] = { + ag5648_i2c_device_num(0), + ag5648_i2c_device_num(1), + ag5648_i2c_device_num(2), + ag5648_i2c_device_num(3), + ag5648_i2c_device_num(4), + ag5648_i2c_device_num(5), + ag5648_i2c_device_num(6), + ag5648_i2c_device_num(7), + ag5648_i2c_device_num(8), + ag5648_i2c_device_num(9), + ag5648_i2c_device_num(10), + ag5648_i2c_device_num(11), + ag5648_i2c_device_num(12), + ag5648_i2c_device_num(13), + ag5648_i2c_device_num(14), + ag5648_i2c_device_num(15), + ag5648_i2c_device_num(16), + ag5648_i2c_device_num(17), + ag5648_i2c_device_num(18), + ag5648_i2c_device_num(19), + ag5648_i2c_device_num(20), + ag5648_i2c_device_num(21), + ag5648_i2c_device_num(22), + ag5648_i2c_device_num(23), + ag5648_i2c_device_num(24), + ag5648_i2c_device_num(25), + ag5648_i2c_device_num(26), + ag5648_i2c_device_num(27), + ag5648_i2c_device_num(28), + ag5648_i2c_device_num(29), + ag5648_i2c_device_num(30), + ag5648_i2c_device_num(31), + ag5648_i2c_device_num(32), + ag5648_i2c_device_num(33), + ag5648_i2c_device_num(34), + ag5648_i2c_device_num(35), + ag5648_i2c_device_num(36), + ag5648_i2c_device_num(37), + ag5648_i2c_device_num(38), + ag5648_i2c_device_num(39), + ag5648_i2c_device_num(40), + ag5648_i2c_device_num(41), + ag5648_i2c_device_num(42), + ag5648_i2c_device_num(43), + ag5648_i2c_device_num(44), + ag5648_i2c_device_num(45), + ag5648_i2c_device_num(46), + ag5648_i2c_device_num(47), + ag5648_i2c_device_num(48), + ag5648_i2c_device_num(49), + ag5648_i2c_device_num(50), + ag5648_i2c_device_num(51), + ag5648_i2c_device_num(52), + ag5648_i2c_device_num(53), + ag5648_i2c_device_num(54), + ag5648_i2c_device_num(55), + ag5648_i2c_device_num(56), + ag5648_i2c_device_num(57), + ag5648_i2c_device_num(58), + ag5648_i2c_device_num(59), + ag5648_i2c_device_num(60), + ag5648_i2c_device_num(61), + ag5648_i2c_device_num(62), + ag5648_i2c_device_num(63), + ag5648_i2c_device_num(64), + ag5648_i2c_device_num(65), + ag5648_i2c_device_num(66), +}; + +/*---------------- I2C device - end ------------- */ + +/*---------------- I2C driver - start ------------- */ +static int __init i2c_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag5648-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- CPLD - start ------------- */ + +/* CPLD -- device */ + +enum cpld_type { + system_cpld, + master_cpld, + slave_cpld, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data ag5648_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = SYSTEM_CPLD_REG, + }, + [master_cpld] = { + .reg_addr = MASTER_CPLD_REG, + }, + [slave_cpld] = { + .reg_addr = SLAVE_CPLD_REG, + }, +}; + +static struct platform_device ag5648_cpld = { + .name = "delta-ag5648-cpld", + .id = 0, + .dev = { + .platform_data = ag5648_cpld_platform_data, + .release = device_release + }, +}; + +static ssize_t get_present(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u32 data = 0; + u32 data2 = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, SFP_PRESENCE_1); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u32)(ret & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, SFP_PRESENCE_2); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(ret & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, SFP_PRESENCE_3); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(ret & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, SFP_PRESENCE_4); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(ret & 0xff) << 24; + + ret = i2c_smbus_read_byte_data(pdata[slave_cpld].client, SFP_PRESENCE_5); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data2 = ((u32)(ret & 0xf)) ; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, SFP_PRESENCE_6); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data2 |= (u32)(ret & 0xff) << 4; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, SFP_PRESENCE_7); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data2 |= (u32)((ret >> 4) & 0xf) << 12; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, QSFP_PRESENCE); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data2 |= (u32)(ret & 0x3f) << 16; + + return sprintf(buf, "0x%06x%x\n", data2, data); +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, QSFP_LP_MODE); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = ((u8)ret & 0x3f) ; + + return sprintf(buf, "0x%02x%012x\n", data, 0); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + data = data >> 48; + i2c_smbus_write_byte_data(pdata[master_cpld].client, QSFP_LP_MODE, (u8)(data & 0xff)); + + return count; +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, QSFP_RESET); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + + data = ((u8)ret & 0x3f); + + return sprintf(buf, "0x%02x%012x\n", data, 0); +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + data = data >> 48; + i2c_smbus_write_byte_data(pdata[master_cpld].client, QSFP_RESET, (u8)(data & 0xff)); + + return count; +} + +static ssize_t get_response(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[master_cpld].client, QSFP_RESPONSE); + + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u8)ret & 0x3f; + + return sprintf(buf, "0x%02x%012x\n", data, 0); +} + +static ssize_t set_response(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + data = data >> 48; + i2c_smbus_write_byte_data(pdata[master_cpld].client, QSFP_RESPONSE, (u8)(data & 0xff)); + + return count; +} + +struct platform_led_status{ + int reg_data; + char *led_status; + int led_id; +}; + +static struct platform_led_status led_info[] = { + { + .reg_data = 0x00,//0000 0000 + .led_status = "fan_off", + .led_id = 0, + }, + { + .reg_data = 1 << 6,//0100 0000 + .led_status = "fan_Amber", + .led_id = 0, + }, + { + .reg_data = 2 << 6,//1000 0000 + .led_status = "fan_green", + .led_id = 0, + }, + { + .reg_data = 3 << 6,//1100 0000 + .led_status = "fan_Blinking_yellow", + .led_id = 0, + }, + { + .reg_data = 0x00, + .led_status = "sys_Blinking_green", + .led_id = 1, + }, + { + .reg_data = 1 << 4, + .led_status = "sys_green", + .led_id = 1, + }, + { + .reg_data = 2 << 4, + .led_status = "sys_Amber", + .led_id = 1, + }, + { + .reg_data = 3 << 4 , + .led_status = "sys_Amber", + .led_id = 1, + }, + { + .reg_data = 0x00, + .led_status = "pwr_off", + .led_id = 2, + }, + { + .reg_data = 1 << 1, + .led_status = "pwr_Amber", + .led_id = 2, + }, + { + .reg_data = 2 << 1, + .led_status = "pwr_green", + .led_id = 2, + }, + { + .reg_data = 3 << 1, + .led_status = "pwr_Blinking_Amber", + .led_id = 2, + }, + { + .reg_data = 0x00, + .led_status = "fan4_off", + .led_id = 3, + }, + { + .reg_data = 1 << 6, + .led_status = "fan4_green", + .led_id = 3, + }, + { + .reg_data = 2 << 6, + .led_status = "fan4_Amber", + .led_id = 3, + }, + { + .reg_data = 0x00, + .led_status = "fan3_off", + .led_id = 4, + }, + { + .reg_data = 1 << 4, + .led_status = "fan3_green", + .led_id = 4, + }, + { + .reg_data = 2 << 4, + .led_status = "fan3_Amber", + .led_id = 4, + }, + { + .reg_data = 0x00, + .led_status = "fan2_off", + .led_id = 5, + }, + { + .reg_data = 1 << 2, + .led_status = "fan2_green", + .led_id = 5, + }, + { + .reg_data = 1 << 3, + .led_status = "fan2_Amber", + .led_id = 5, + }, + { + .reg_data = 0x00, + .led_status = "fan1_off", + .led_id = 6, + }, + { + .reg_data = 1, + .led_status = "fan1_green", + .led_id = 6, + }, + { + .reg_data = 2, + .led_status = "fan1_Amber", + .led_id = 6, + }, +}; + +struct platform_led_data{ + int reg_addr; + int mask; +}; + +static struct platform_led_data led_data[] = { + { + .reg_addr = LED_REG, //0x04 + .mask = 0xc0,//1100 0000 + }, + { + .reg_addr = LED_REG, + .mask = 0x30,//0011 0000 + }, + { + .reg_addr = LED_REG, + .mask = 0x06,//0000 0110 + }, + { + .reg_addr = FAN_LED_REG,//0x05 + .mask = 0xc0,//1100 0000 + }, + { + .reg_addr = FAN_LED_REG, + .mask = 0x30,//0011 0000 + }, + { + .reg_addr = FAN_LED_REG, + .mask = 0x0c,//0000 1100 + }, + { + .reg_addr = FAN_LED_REG, + .mask = 0x03,//0000 0011 + }, +}; + + +static ssize_t get_led_color(struct device *dev, struct device_attribute *devattr, char *buf) +{ + char str[9][20] = {0}; + int board_data; + int led_data_number; + int led_info_number; + struct cpld_platform_data *pdata = dev->platform_data; + + for(led_data_number = 0; led_data_number < ARRAY_SIZE(led_data); led_data_number++){ + board_data = i2c_smbus_read_byte_data(pdata[slave_cpld].client, led_data[led_data_number].reg_addr); + if(board_data >= 0){ + board_data &= led_data[led_data_number].mask; + for(led_info_number = 0; led_info_number < ARRAY_SIZE(led_info); led_info_number++){ + if (led_data_number == led_info[led_info_number].led_id \ + && board_data == led_info[led_info_number].reg_data){ + sprintf(str[led_data_number], "%s", led_info[led_info_number].led_status); + } + } + } + else + printk( KERN_ERR "Missing LED board data\n"); + } + return sprintf(buf,"%s\n%s\n%s\n%s\n%s\n%s\n%s\n",str[0],str[1],str[2],str[3],str[4],str[5],str[6]); +} + +static ssize_t set_led_color(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int led_info_number; + int led_data_number; + int str_compar; + int led_reg_value; + struct cpld_platform_data *pdata = dev->platform_data; + + for(led_info_number = 0; led_info_number < ARRAY_SIZE(led_info); led_info_number++){ + str_compar = strncmp(buf,led_info[led_info_number].led_status,strlen(led_info[led_info_number].led_status)); + if(str_compar == 0){ + for(led_data_number = 0; led_data_number < ARRAY_SIZE(led_data); led_data_number++){ + if(led_info[led_info_number].led_id == led_data_number){ + led_reg_value = i2c_smbus_read_byte_data(pdata[slave_cpld].client, led_data[led_data_number].reg_addr); + if(led_reg_value >= 0){ + led_reg_value &= (~led_data[led_data_number].mask); + led_reg_value |= led_info[led_info_number].reg_data; + i2c_smbus_write_byte_data(pdata[slave_cpld].client, (u8)(led_data[led_data_number].reg_addr & 0xff), (u8)(led_reg_value & 0xff)); + } + else + printk( KERN_ERR "Missing LED reg. data\n"); + } + } + } + } + return count; +} + +static DEVICE_ATTR(sfp_response, S_IWUSR | S_IRUGO, get_response, set_response ); +static DEVICE_ATTR(sfp_present, S_IRUGO, get_present, NULL ); +static DEVICE_ATTR(sfp_lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode ); +static DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, get_reset, set_reset ); + +static DEVICE_ATTR(led_control, S_IRUGO | S_IWUSR, get_led_color, set_led_color); + +static struct attribute *ag5648_cpld_attrs[] = { + &dev_attr_sfp_response.attr, + &dev_attr_sfp_present.attr, + &dev_attr_sfp_lpmode.attr, + &dev_attr_sfp_reset.attr, + &dev_attr_led_control.attr, + NULL, +}; + +static struct attribute_group ag5648_cpld_attr_grp = { + .attrs = ag5648_cpld_attrs, +}; + +/* CPLD -- driver */ +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret,i; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS2); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n",BUS2); + return -ENODEV; + } + + for (i = 0; i < ARRAY_SIZE(ag5648_cpld_platform_data); i++) { + pdata[i].client = i2c_new_dummy(parent, pdata[i].reg_addr); + if (!pdata[i].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[i].reg_addr); + goto error; + } + } + + ret = sysfs_create_group(&pdev->dev.kobj, &ag5648_cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; + +error: + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + } + } + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + int i; + sysfs_remove_group(&pdev->dev.kobj, &ag5648_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + for (i = 0; i < ARRAY_SIZE(ag5648_cpld_platform_data); i++) { + if (pdata[i].client) { + if (!parent) { + parent = (pdata[i].client)->adapter; + } + i2c_unregister_device(pdata[i].client); + } + } + } + + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag5648-cpld", + }, +}; + +/*---------------- CPLD - end ------------- */ + +/*---------------- MUX - start ------------- */ + +struct swpld_mux_platform_data { + int parent; + int base_nr; + int reg_addr; + struct i2c_client *cpld; +}; + +struct swpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct swpld_mux_platform_data data; +}; + +static struct swpld_mux_platform_data ag5648_swpld_mux_platform_data[] = { + { + .parent = BUS4, + .base_nr = BUS4_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS4_MUX_REG , + }, +}; + + +static struct platform_device ag5648_swpld_mux[] = { + { + .name = "delta-ag5648-swpld-mux", + .id = 0, + .dev = { + .platform_data = &ag5648_swpld_mux_platform_data[0], + .release = device_release, + }, + }, +}; + + +static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int swpld_mux_select(struct i2c_adapter *adap, void *data, u8 chan) +{ + struct swpld_mux *mux = data; + u8 swpld_mux_val=0; + if ( mux->data.base_nr == BUS4_BASE_NUM ) + { + swpld_mux_val = (chan + 0x01); + } + else + { + swpld_mux_val = 0x00; + } + swpld_mux_val=swpld_mux_val & (u8)0x3F; + + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int swpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct swpld_mux *mux = i2c_mux_priv(muxc); + u8 swpld_mux_val=0; + if ( mux->data.base_nr == BUS4_BASE_NUM ) + { + swpld_mux_val = (chan + 0x01); + } + else + { + swpld_mux_val = 0x00; + } + swpld_mux_val=swpld_mux_val & (u8)0x3F; + + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for mux\n"); + goto alloc_failed; + } + + mux->parent = parent; + mux->data = *pdata; + mux->child = kzalloc(sizeof(struct i2c_adapter *) * dev_num, GFP_KERNEL); + if (!mux->child) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for device on mux\n"); + goto alloc_failed2; + } + + for (i = 0; i < dev_num; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + mux->child[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, + nr, i, class, + swpld_mux_select, NULL); + if (!mux->child[i]) { + ret = -ENODEV; + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + platform_set_drvdata(pdev, mux); + return 0; + +add_adapter_failed: + for (; i > 0; i--) + i2c_del_mux_adapter(mux->child[i - 1]); + kfree(mux->child); +alloc_failed2: + kfree(mux); +alloc_failed: + i2c_put_adapter(parent); + + return ret; +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + printk(KERN_ERR "Failed to allocate memory for mux\n"); + return -ENOMEM; + } + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + kfree(mux); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, + swpld_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + platform_set_drvdata(pdev, muxc); + + + for (i = 0; i < dev_num; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_num, parent->name); + + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + kfree(mux); + i2c_put_adapter(parent); + + return ret; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + int i; + struct swpld_mux *mux = platform_get_drvdata(pdev); + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + switch (pdata->parent) { + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + for (i = 0; i < dev_num; i++) + i2c_del_mux_adapter(mux->child[i]); + + platform_set_drvdata(pdev, NULL); + i2c_put_adapter(mux->parent); + kfree(mux->child); + kfree(mux); + + return 0; +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(muxc->parent); + + return 0; +} +#endif + +static struct platform_driver swpld_mux_driver = { + .probe = swpld_mux_probe, + .remove = __exit_p(swpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag5648-swpld-mux", + }, +}; +/*---------------- MUX - end ------------- */ + + +/*---------------- module initialization ------------- */ +static int __init delta_ag5648_platform_init(void) +{ + //struct i2c_client *client; + struct i2c_adapter *adapter; + struct cpld_platform_data *cpld_pdata; + struct swpld_mux_platform_data *swpld_pdata; + int ret,i = 0; + + //Use pca9548 in i2c_mux_pca954x.c + adapter = i2c_get_adapter(BUS1); + + i2c_client_9548 = i2c_new_device(adapter, &i2c_info_pca9548[0]); + i2c_put_adapter(adapter); + + // set the CPLD prob and remove + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + + // register the mux prob which call the CPLD + ret = platform_driver_register(&swpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_swpld_mux_driver; + } + + // register the i2c devices + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + // register the CPLD + ret = platform_device_register(&ag5648_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_ag5648_cpld; + } + // link the CPLD and the Mux + cpld_pdata = ag5648_cpld.dev.platform_data; + + + swpld_pdata = ag5648_swpld_mux[0].dev.platform_data; + swpld_pdata->cpld = cpld_pdata[master_cpld].client; + ret = platform_device_register(&ag5648_swpld_mux[0]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_ag5648_swpld_mux; + } + + for (i = 0; i < ARRAY_SIZE(ag5648_i2c_device); i++) + { + ret = platform_device_register(&ag5648_i2c_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_ag5648_i2c_device; + } + } + + if (ret) + goto error_ag5648_swpld_mux; + return 0; + +error_ag5648_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag5648_i2c_device[i]); + } + i = ARRAY_SIZE(ag5648_swpld_mux); +error_ag5648_swpld_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag5648_swpld_mux[0]); + } + platform_device_unregister(&ag5648_cpld); +error_ag5648_cpld: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld_mux_driver); +error_swpld_mux_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit delta_ag5648_platform_exit(void) +{ + int i = 0; + + for ( i = 0; i < ARRAY_SIZE(ag5648_i2c_device); i++ ) { + platform_device_unregister(&ag5648_i2c_device[i]); + } + + for (i = 0; i < ARRAY_SIZE(ag5648_swpld_mux); i++) { + platform_device_unregister(&ag5648_swpld_mux[i]); + } + + platform_device_unregister(&ag5648_cpld); + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&swpld_mux_driver); + i2c_unregister_device(i2c_client_9548); +} + +module_init(delta_ag5648_platform_init); +module_exit(delta_ag5648_platform_exit); + +MODULE_DESCRIPTION("DNI ag5648 Platform Support"); +MODULE_AUTHOR("Neal Tai "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_ag5648_psu.c b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_ag5648_psu.c new file mode 100644 index 000000000000..d7e8a3bf8e7c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_ag5648_psu.c @@ -0,0 +1,552 @@ +/* + * An hwmon driver for delta AG5648 PSU + * dps_800ab_16_d.c - Support for DPS-800AB-16 D Power Supply Module + * + * Copyright (C) 2016 Delta Network Technology Corporation + * + * DNI + * + * Based on ym2651y.c + * Based on ad7414.c + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 +#define SWPLD_REG 0x31 +#define SWPLD_PSU_MUX_REG 0x21 +#define SELECT_PSU1_EEPROM 0x00 +#define SELECT_PSU2_EEPROM 0x20 + +u8 psu_member_data = 0x00; + +/* Address scanned */ +static const unsigned short normal_i2c[] = { 0x59, 0x58, I2C_CLIENT_END }; + +/* This is additional data */ +struct dps_800ab_16_d_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; /* In jiffies */ + + /* Registers value */ + u8 vout_mode; + u16 in1_input; + u16 in2_input; + u16 curr1_input; + u16 curr2_input; + u16 power1_input; + u16 power2_input; + u16 temp_input[2]; + u8 fan_target; + u16 fan_duty_cycle_input[2]; + u16 fan_speed_input[2]; + u8 mfr_model[14]; + u8 mfr_serial[16]; +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count); +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_fan_target(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static int dps_800ab_16_d_read_byte(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value); +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len); +static struct dps_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev); +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +/* +static ssize_t set_w_member_data(struct device *dev, struct device_attribute \ + *dev_att, const char *buf, size_t count); +static ssize_t for_r_member_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +*/ +enum dps_800ab_16_d_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_MFR_MODEL, + PSU_MFR_SERIAL, + PSU_SELECT_MEMBER, +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + /* Select SWPLD PSU offset */ + + mutex_lock(&data->update_lock); + data->fan_duty_cycle_input[nr] = speed; + dps_800ab_16_d_write_word(client, 0x3B + nr, data->fan_duty_cycle_input[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->in1_input; + break; + case PSU_I_IN: + value = data->curr1_input; + break; + case PSU_I_OUT: + value = data->curr2_input; + break; + case PSU_P_IN: + value = data->power1_input; + multiplier = 1000*1000; + break; + case PSU_P_OUT: + value = data->power2_input; + multiplier = 1000*1000; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle_input[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed_input[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_fan_target(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_target >> shift); +} + +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->in2_input; + + return (exponent > 0) ? sprintf(buf, "%d\n", \ + (mantissa * multiplier) / (1 << exponent)): \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + +} + +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) + return 0; + + switch (attr->index) { + case PSU_MFR_MODEL: + ptr = data->mfr_model + 1; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial + 1; + break; + default: + return 0; + } + return sprintf(buf, "%s\n", ptr); +} +static int dps_800ab_16_d_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags |= I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, reg, + I2C_SMBUS_WORD_DATA, &data); + +} + +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, + data); + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; +abort: + return result; + +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct dps_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + /* Select SWPLD PSU offset */ + + if (time_after(jiffies, data->last_updated)) { + int i, status; + u8 command; + struct reg_data_byte regs_byte[] = { + {0x20, &data->vout_mode}, + {0x81, &data->fan_target} + }; + struct reg_data_word regs_word[] = { + {0x88, &data->in1_input}, + {0x8b, &data->in2_input}, + {0x89, &data->curr1_input}, + {0x8c, &data->curr2_input}, + {0x97, &data->power1_input}, + {0x96, &data->power2_input}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle_input[0])}, + {0x90, &(data->fan_speed_input[0])}, + }; + + dev_dbg(&client->dev, "start data update\n"); + /* one milliseconds from now */ + data->last_updated = jiffies + HZ / 1000; + + data->in1_input = 0; + data->in2_input = 0; + data->curr1_input = 0; + data->curr2_input = 0; + data->power1_input = 0; + data->power2_input = 0; + data->temp_input[0] = 0; + data->temp_input[1] = 0; + data->fan_duty_cycle_input[0] = 0; + data->fan_speed_input[0] = 0; + + data->mfr_model[0] = '\0'; + data->mfr_serial[0] = '\0'; + + command = 0x9a; /* PSU mfr_model */ + status = dps_800ab_16_d_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, + status); + } + + command = 0x9e; /* PSU mfr_serial */ + status = dps_800ab_16_d_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, + status); + } + + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = dps_800ab_16_d_read_byte(client, + regs_byte[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } else { + *(regs_byte[i].value) = status; + } + } + + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = dps_800ab_16_d_read_word(client, + regs_word[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } else { + *(regs_word[i].value) = status; + } + } +/* + command = 0x9a; / PSU mfr_model / + status = dps_800ab_16_d_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, + status); + } + + command = 0x9e; / PSU mfr_serial / + status = dps_800ab_16_d_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, + status); + } + */ + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(temp1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_target, \ + S_IRUGO, for_fan_target, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(fan1_set_percentage, S_IWUSR | S_IRUGO, \ + for_linear_data, set_fan_duty_cycle_input, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(fan1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_model, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); +/* +static SENSOR_DEVICE_ATTR(psu_select_member, S_IWUGO | S_IRUGO, \ + for_r_member_data, set_w_member_data, PSU_SELECT_MEMBER); +*/ +static struct attribute *dps_800ab_16_d_attributes[] = { + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_target.dev_attr.attr, + &sensor_dev_attr_fan1_set_percentage.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + //&sensor_dev_attr_psu_select_member.dev_attr.attr, + NULL +}; + +static const struct attribute_group dps_800ab_16_d_group = { + .attrs = dps_800ab_16_d_attributes, +}; + +static int dps_800ab_16_d_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct dps_800ab_16_d_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "new chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &dps_800ab_16_d_group); + if (status) + goto exit_sysfs_create_group; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_hwmon_device_register; + } + + return 0; + +exit_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); +exit_sysfs_create_group: + kfree(data); +exit: + return status; +} + +static int dps_800ab_16_d_remove(struct i2c_client *client) +{ + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); + kfree(data); + + return 0; +} + +enum id_name { + dni_ag5648_psu, + dps_800ab_16_d +}; + +static const struct i2c_device_id dps_800ab_16_d_id[] = { + { "dni_ag5648_psu", dni_ag5648_psu }, + { "dps_800ab_16_d", dps_800ab_16_d }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dps_800ab_16_d_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver dps_800ab_16_d_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "dps_800ab_16_d", + }, + .probe = dps_800ab_16_d_probe, + .remove = dps_800ab_16_d_remove, + .id_table = dps_800ab_16_d_id, + .address_list = normal_i2c, +}; + +static int __init dps_800ab_16_d_init(void) +{ + return i2c_add_driver(&dps_800ab_16_d_driver); +} + +static void __exit dps_800ab_16_d_exit(void) +{ + i2c_del_driver(&dps_800ab_16_d_driver); +} + + +MODULE_AUTHOR("Aries Lin "); +MODULE_DESCRIPTION("DPS_800AB_16_D Driver"); +MODULE_LICENSE("GPL"); + +module_init(dps_800ab_16_d_init); +module_exit(dps_800ab_16_d_exit); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_emc2305.c b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_emc2305.c new file mode 120000 index 000000000000..e8f7ae6b3f4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/modules/dni_emc2305.c @@ -0,0 +1 @@ +../../common/modules/dni_emc2305.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/ag5648_platform_init.sh b/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/ag5648_platform_init.sh new file mode 100755 index 000000000000..753649f01abe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/ag5648_platform_init.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +#platform init script for Delta ag5648 + +#fan speed monitor start +/usr/share/sonic/device/x86_64-delta_ag5648-r0/fancontrol.service /usr/share/sonic/device/x86_64-delta_ag5648-r0/fancontrol & + +#led control +/usr/local/bin/led_control & + + +exit 0 + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/led_control b/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/led_control new file mode 100755 index 000000000000..bc1417f9ba5e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/scripts/led_control @@ -0,0 +1,221 @@ +#!/bin/bash + +FAN1_EEPROM="-y 3 0x51 0x0a" +FAN2_EEPROM="-y 3 0x52 0x0a" +FAN3_EEPROM="-y 3 0x53 0x0a" +FAN4_EEPROM="-y 3 0x54 0x0a" +LED_CONTROL="/sys/devices/platform/delta-ag5648-cpld.0/led_control" + +FAN1_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/3-004d/fan1_input" +FAN2_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/3-004d/fan2_input" +FAN3_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/3-004d/fan3_input" +FAN4_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/3-004d/fan4_input" + +FAN1_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-004d/fan1_input" +FAN2_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-004d/fan2_input" +FAN3_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-004d/fan3_input" +FAN4_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-004d/fan4_input" + +PSU1_EEPROM="-y 6 0x51 0x00" +PSU2_EEPROM="-y 6 0x50 0x00" +PSU1_FAN_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-6/6-0059/fan1_input" +PSU2_FAN_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-6/6-0058/fan1_input" + +catfaneeprom(){ + fan_eeprom_num=0 + fan1_eeprom_num=0 + i2cget $FAN1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan1_eeprom_num=$((fan1_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan1_eeprom_num=$((fan1_eeprom_num)) + fi + + fan2_eeprom_num=0 + i2cget $FAN2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan2_eeprom_num=$((fan2_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan2_eeprom_num=$((fan2_eeprom_num)) + fi + + fan3_eeprom_num=0 + i2cget $FAN3_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan3_eeprom_num=$((fan3_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan3_eeprom_num=$((fan3_eeprom_num)) + fi + + fan4_eeprom_num=0 + i2cget $FAN4_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan4_eeprom_num=$((fan4_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan4_eeprom_num=$((fan4_eeprom_num)) + fi + + fan_eeprom_num=$((fan1_eeprom_num+fan2_eeprom_num+fan3_eeprom_num+fan4_eeprom_num)) +} + +catfanspeed(){ + fan_rpm_normal_num=0 + fan1_rpm_normal_num=0 + fan1_front_rpm=`cat $FAN1_FRONT_RPM` + fan1_rear_rpm=`cat $FAN1_REAR_RPM` + if [ "${fan1_front_rpm}" -ne "960" ] && [ "${fan1_rear_rpm}" -ne "960" ] && [ "${fan1_front_rpm}" -ne "0" ] && [ "${fan1_rear_rpm}" -ne "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num+1)) + elif [ "${fan1_front_rpm}" -eq "960" ] || [ "${fan1_rear_rpm}" -eq "960" ] || [ "${fan1_front_rpm}" -eq "0" ] || [ "${fan1_rear_rpm}" -eq "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num)) + fi + + fan2_rpm_normal_num=0 + fan2_front_rpm=`cat $FAN2_FRONT_RPM` + fan2_rear_rpm=`cat $FAN2_REAR_RPM` + if [ "${fan2_front_rpm}" -ne "960" ] && [ "${fan2_rear_rpm}" -ne "960" ] && [ "${fan2_front_rpm}" -ne "0" ] && [ "${fan2_rear_rpm}" -ne "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num+1)) + elif [ "${fan2_front_rpm}" -eq "960" ] || [ "${fan2_rear_rpm}" -eq "960" ] || [ "${fan2_front_rpm}" -eq "0" ] || [ "${fan2_rear_rpm}" -eq "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num)) + fi + + fan3_rpm_normal_num=0 + fan3_front_rpm=`cat $FAN3_FRONT_RPM` + fan3_rear_rpm=`cat $FAN3_REAR_RPM` + if [ "${fan3_front_rpm}" -ne "960" ] && [ "${fan3_rear_rpm}" -ne "960" ] && [ "${fan3_front_rpm}" -ne "0" ] && [ "${fan3_rear_rpm}" -ne "0" ]; then + fan3_rpm_normal_num=$((fan3_rpm_normal_num+1)) + elif [ "${fan3_front_rpm}" -eq "960" ] || [ "${fan3_rear_rpm}" -eq "960" ] || [ "${fan3_front_rpm}" -eq "0" ] || [ "${fan3_rear_rpm}" -eq "0" ]; then + fan3_rpm_normal_num=$((fan3_rpm_normal_num)) + fi + + fan4_rpm_normal_num=0 + fan4_front_rpm=`cat $FAN4_FRONT_RPM` + fan4_rear_rpm=`cat $FAN4_REAR_RPM` + if [ "${fan4_front_rpm}" -ne "960" ] && [ "${fan4_rear_rpm}" -ne "960" ] && [ "${fan4_front_rpm}" -ne "0" ] && [ "${fan4_rear_rpm}" -ne "0" ]; then + fan4_rpm_normal_num=$((fan4_rpm_normal_num+1)) + elif [ "${fan4_front_rpm}" -eq "960" ] || [ "${fan4_rear_rpm}" -eq "960" ] || [ "${fan4_front_rpm}" -eq "0" ] || [ "${fan4_rear_rpm}" -eq "0" ]; then + fan4_rpm_normal_num=$((fan4_rpm_normal_num)) + fi + + fan_rpm_normal_num=$((fan1_rpm_normal_num+fan2_rpm_normal_num+fan3_rpm_normal_num+fan4_rpm_normal_num)) + +} + +catpsueeprom(){ + psu1_eeprom_num=0 + i2cget $PSU1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu1_eeprom_num=$((psu1_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + psu1_eeprom_num=$((psu1_eeprom_num)) + fi + + psu2_eeprom_num=0 + i2cget $PSU2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu2_eeprom_num=$((psu2_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + psu2_eeprom_num=$((psu2_eeprom_num)) + fi +} + +catpsufanspeed(){ + + psu1_rpm_normal_num=0 + psu1_rpm=`cat $PSU1_FAN_RPM` + + if [ "${psu1_rpm}" -ne "960" ] && [ "${psu1_rpm}" -ne "0" ]; then + psu1_rpm_normal_num=$((psu1_rpm_normal_num+1)) + elif [ "${psu1_rpm}" -eq "960" ] || [ "${psu1_rpm}" -eq "0" ]; then + psu1_rpm_normal_num=$((psu1_rpm_normal_num)) + fi + + psu2_rpm_normal_num=0 + psu2_rpm=`cat $PSU2_FAN_RPM` + + if [ "${psu2_rpm}" -ne "960" ] && [ "${psu2_rpm}" -ne "0" ]; then + psu2_rpm_normal_num=$((psu2_rpm_normal_num+1)) + elif [ "${psu2_rpm}" -eq "960" ] || [ "${psu2_rpm}" -eq "0" ]; then + psu2_rpm_normal_num=$((psu2_rpm_normal_num)) + fi + +} + +setfanled(){ + if [ "${fan_eeprom_num}" -eq "4" ] && [ "${fan_rpm_normal_num}" -eq "4" ]; then + echo "fan_green" > $LED_CONTROL + elif [ "${fan_eeprom_num}" -lt "4" ] && [ "${fan_rpm_normal_num}" -eq "4" ]; then + echo "fan_Amber" > $LED_CONTROL + elif [ "${psu1_eeprom_num}" -eq "0" ] && [ "${psu2_eeprom_num}" -eq "0" ]; then + echo "fan_off" > $LED_CONTROL + else + echo "fan_Blinking_yellow" > $LED_CONTROL + fi +} + +setpsuled(){ + if [ "${psu1_rpm_normal_num}" -eq "1" ] && [ "${psu2_rpm_normal_num}" -eq "1" ]; then + echo "pwr_green" > $LED_CONTROL + elif [ "${psu1_eeprom_num}" -eq "1" ] && [ "${psu2_eeprom_num}" -eq "1" ]; then + echo "pwr_Blinking_Amber" > $LED_CONTROL + elif [ "${psu1_eeprom_num}" -eq "0" ] || [ "${psu2_eeprom_num}" -eq "0" ]; then + echo "pwr_Amber" > $LED_CONTROL + else + echo "pwr_off" > $LED_CONTROL + fi + +} + +setfantrayled(){ + if [ "${fan1_rpm_normal_num}" -eq "1" ]; then + echo "fan1_green" > $LED_CONTROL + elif [ "${fan1_eeprom_num}" -eq "1" ]; then + echo "fan1_Amber" > $LED_CONTROL + else + echo "fan1_off" > $LED_CONTROL + fi + + if [ "${fan2_rpm_normal_num}" -eq "1" ]; then + echo "fan2_green" > $LED_CONTROL + elif [ "${fan2_eeprom_num}" -eq "1" ]; then + echo "fan2_Amber" > $LED_CONTROL + else + echo "fan2_off" > $LED_CONTROL + fi + + if [ "${fan3_rpm_normal_num}" -eq "1" ]; then + echo "fan3_green" > $LED_CONTROL + elif [ "${fan3_eeprom_num}" -eq "1" ]; then + echo "fan3_Amber" > $LED_CONTROL + else + echo "fan3_off" > $LED_CONTROL + fi + + if [ "${fan4_rpm_normal_num}" -eq "1" ]; then + echo "fan4_green" > $LED_CONTROL + elif [ "${fan4_eeprom_num}" -eq "1" ]; then + echo "fan4_Amber" > $LED_CONTROL + else + echo "fan4_off" > $LED_CONTROL + fi + +} + +platformstatus(){ + + echo "sys_green" > $LED_CONTROL + catfaneeprom + catfanspeed + setfanled + setfantrayled + + catpsueeprom + catpsufanspeed + setpsuled +} + +while true +do + platformstatus + sleep 5 +done + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag5648/sensors.conf b/platform/broadcom/sonic-platform-modules-delta/ag5648/sensors.conf new file mode 100644 index 000000000000..c69567997a27 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag5648/sensors.conf @@ -0,0 +1,94 @@ +# libsensors configuration file for AG5648 +# ------------------------------------------------ +# + +bus "i2c-2" "i2c-1-mux (chan_id 0)" +bus "i2c-3" "i2c-1-mux (chan_id 1)" +bus "i2c-4" "i2c-1-mux (chan_id 2)" +bus "i2c-5" "i2c-1-mux (chan_id 3)" +bus "i2c-6" "i2c-1-mux (chan_id 4)" +bus "i2c-7" "i2c-1-mux (chan_id 5)" + +# tmp75-i2c-2-4d board sensor near Left of front vents. +# tmp75-i2c-3-49 board sensor near MAC. +# tmp75-i2c-3-4b board sensor near Middle of front vents. +# tmp75-i2c-3-4c board sensor near Right of front vents. +# tmp75-i2c-3-4e board sensor near DC fan. +# tmp75-i2c-3-4f board sensor near CPU. + +chip "tmp75-i2c-*-4d" + label temp1 "board sensor near Left of front vents" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-*-49" + label temp1 "board sensor near MAC" + set temp1_max 85 + set temp1_max_hyst 80 + +chip "tmp75-i2c-*-4b" + label temp1 "board sensor near Middle of front vents" + set temp1_max 70 + set temp1_max_hyst 65 + +chip "tmp75-i2c-*-4c" + label temp1 "board sensor near Right of front vents" + set temp1_max 65 + set temp1_max_hyst 60 + +chip "tmp75-i2c-*-4e" + label temp1 "board sensor near DC fan" + set temp1_max 60 + set temp1_max_hyst 55 + +chip "tmp75-i2c-*-4f" + label temp1 "board sensor near CPU" + set temp1_max 80 + set temp1_max_hyst 75 + +chip "emc2305-i2c-3-4d" + label fan1 "FANTRAY 1 REAR" + label fan2 "FANTRAY 2 REAR" + label fan3 "FANTRAY 3 REAR" + label fan4 "FANTRAY 4 REAR" + label fan5 "FANTRAY 5 REAR" + +chip "emc2305-i2c-5-4d" + label fan1 "FANTRAY 1 FRONT" + label fan2 "FANTRAY 2 FRONT" + label fan3 "FANTRAY 3 FRONT" + label fan4 "FANTRAY 4 FRONT" + label fan5 "FANTRAY 5 FRONT" + +chip "ltc4215-i2c-*-40" + label in1 "PSU Hot-Swap voltage 1" + label in2 "PSU Hot-Swap voltage 2" + label power1 "PSU Hot-Swap power" + label curr1 "PSU Hot-Swap current" + +chip "ltc4215-i2c-*-42" + label in1 "PSU Hot-Swap voltage 1" + label in2 "PSU Hot-Swap voltage 2" + label power1 "PSU Hot-Swap power" + label curr1 "PSU Hot-Swap current" + +chip "dni_ag5648_psu-i2c-*-59" + label in1 "PSU voltage 1" + label in2 "PSU voltage 2" + label fan1 "PSU fan" + label temp1 "PSU temperature" + label power1 "PSU power1" + label power2 "PSU power2" + label curr1 "PSU current1" + label curr2 "PSU current2" + +chip "dni_ag5648_psu-i2c-*-58" + label in1 "PSU voltage 1" + label in2 "PSU voltage 2" + label fan1 "PSU fan" + label temp1 "PSU temperature" + label power1 "PSU power1" + label power2 "PSU power2" + label curr1 "PSU current1" + label curr2 "PSU current2" + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/cfg/ag9032v1-modules.conf b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/cfg/ag9032v1-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/cfg/ag9032v1-modules.conf @@ -0,0 +1,13 @@ +# /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-delta/ag9032v1/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile new file mode 100644 index 000000000000..d77d3b78408f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/Makefile @@ -0,0 +1 @@ +obj-m := dni_ag9032v1_psu.o dni_emc2305.o delta_ag9032v1_platform.o delta_ag9032v1_cpupld.o diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_cpupld.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_cpupld.c new file mode 100644 index 000000000000..22f997e71fab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_cpupld.c @@ -0,0 +1,387 @@ +#include +#include +#include +#include +#include +#include + +#define CPUPLD_REG 0x31 + +enum cpld_type { + cpld, +}; + +struct platform_data { + int reg_addr; + struct i2c_client *client; +}; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, +}; + +enum cpld_attributes { + CPLD_VER, + CPU_BOARD_VER, + CPU_ID, + CPLD_RST, + MB_RST, + I2C_SW_RST, + MB_PWR, + PSU_FAN_INT, + SPI_WP_GBE, + EEPROM_WP, +}; + +static void device_release(struct device *dev) +{ + return; +} + +/*---------------- CPUPLD - start ------------- */ +static struct platform_data ag9032v1_cpld_platform_data[] = { + [cpld] = { + .reg_addr = CPUPLD_REG, + }, +}; + +static struct platform_device ag9032v1_cpld = { + .name = "delta-ag9032v1-cpupld", + .id = 0, + .dev = { + .platform_data = ag9032v1_cpld_platform_data, + .release = device_release + }, +}; +static unsigned char cpld_reg_addr; +static ssize_t get_cpld_reg_value(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + struct platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[cpld].client, cpld_reg_addr); + + return sprintf(buf, "0x%02x\n", ret); +} + +static ssize_t set_cpld_reg_value(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long data; + int err; + struct platform_data *pdata = dev->platform_data; + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + i2c_smbus_write_byte_data(pdata[cpld].client, cpld_reg_addr, data); + + return count; +} + +static ssize_t get_cpld_reg_addr(struct device *dev, struct device_attribute *devattr, char *buf) +{ + + return sprintf(buf, "0x%02x\n", cpld_reg_addr); +} + +static ssize_t set_cpld_reg_addr(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long data; + int err; + + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + cpld_reg_addr = data; + + return count; +} + +static ssize_t get_cpld_data(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct platform_data *pdata = dev->platform_data; + unsigned char reg; + int mask; + int value; + char note[180]; + switch (attr->index) { + case CPLD_VER: + reg = 0x01; + value = i2c_smbus_read_byte_data(pdata[cpld].client, reg); + sprintf(note, "\nCPLD Version, controlled by CPLD editor.\n"); + return sprintf(buf, "0x%02x%s", value, note); + break; + case CPU_BOARD_VER: + reg = 0x02; + ret = i2c_smbus_read_byte_data(pdata[cpld].client, reg); + value = ret >> 4; + sprintf(note, "\n“0x00”: proto A1\n“0x01”: proto A2\n“0x02”: proto B\n"); + return sprintf(buf, "0x%02x%s", value, note); + break; + case CPU_ID: + reg = 0x02; + ret = i2c_smbus_read_byte_data(pdata[cpld].client, reg); + value = ret & 0x0F; + sprintf(note, "\n“0x00”: P2041 ECC\n“0x01”: Rangeley ECC\n“0x02”: T2080 ECC\n"); + return sprintf(buf, "0x%02x%s", value, note); + break; + case CPLD_RST: + reg = 0x05; + mask = 7; + sprintf(note, "\n“1” = Normal operation\n“0” = Reset\n"); + break; + case MB_RST: + reg = 0x05; + mask = 1; + sprintf(note, "\n“1” = Normal operation\n“0” = Reset\n"); + break; + case I2C_SW_RST: + reg = 0x05; + mask = 0; + sprintf(note, "\n“1” = Normal operation\n“0” = Reset\n"); + break; + case MB_PWR: + reg = 0x08; + mask = 4; + sprintf(note, "\n“1” = Power rail is good\n“0” = Power rail is failed\n"); + break; + case PSU_FAN_INT: + reg = 0x0A; + mask = 0; + sprintf(note, "\n“1” = Interrupt doesn’t occur\n“0” = Interrupt occurs\n"); + break; + case SPI_WP_GBE: + reg = 0x10; + mask = 3; + sprintf(note, "\n“1” = overrides the lock-down function enabling blocks to be erased or programmed using software commands.\n“0” = enables the lock-down mechanism.\n"); + break; + case EEPROM_WP: + reg = 0x10; + mask = 2; + sprintf(note, "\n“1” = overrides the lock-down function enabling blocks to be erased or programmed using software commands.\n“0” = enables the lock-down mechanism.\n"); + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + ret = i2c_smbus_read_byte_data(pdata[cpld].client, reg); + value = (ret & (1 << mask)) >> mask; + return sprintf(buf, "%d%s", value, note); +} + +static ssize_t set_cpld_data(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + int mask; + int err; + int ret; + unsigned long data; + unsigned char reg; + unsigned char mask_shift; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct platform_data *pdata = dev->platform_data; + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + switch (attr->index) { + case CPLD_RST: + reg = 0x05; + mask = 7; + break; + case MB_RST: + reg = 0x05; + mask = 1; + break; + case I2C_SW_RST: + reg = 0x05; + mask = 0; + break; + case SPI_WP_GBE: + reg = 0x10; + mask = 3; + break; + case EEPROM_WP: + reg = 0x10; + mask = 2; + break; + default: + return count; + } + + ret = i2c_smbus_read_byte_data(pdata[cpld].client, reg); + mask_shift = 1 << mask; + data = (ret & ~mask_shift) | (data << mask); + i2c_smbus_write_byte_data(pdata[cpld].client, cpld_reg_addr, data); + + return count; +} + +static DEVICE_ATTR(cpld_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg_value, set_cpld_reg_value); +static DEVICE_ATTR(cpld_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg_addr, set_cpld_reg_addr); + +static SENSOR_DEVICE_ATTR(cpld_ver, S_IRUGO, get_cpld_data, NULL, CPLD_VER); +static SENSOR_DEVICE_ATTR(cpu_board_ver, S_IRUGO, get_cpld_data, NULL, CPU_BOARD_VER); +static SENSOR_DEVICE_ATTR(cpu_id, S_IRUGO, get_cpld_data, NULL, CPU_ID); +static SENSOR_DEVICE_ATTR(cpld_rst, S_IRUGO | S_IWUSR, get_cpld_data, set_cpld_data, CPLD_RST); +static SENSOR_DEVICE_ATTR(mb_rst, S_IRUGO | S_IWUSR, get_cpld_data, set_cpld_data, MB_RST); +static SENSOR_DEVICE_ATTR(i2c_sw_rst, S_IRUGO | S_IWUSR, get_cpld_data, set_cpld_data, I2C_SW_RST); +static SENSOR_DEVICE_ATTR(mb_pwr, S_IRUGO, get_cpld_data, NULL, MB_PWR); +static SENSOR_DEVICE_ATTR(psu_fan_int, S_IRUGO, get_cpld_data, NULL, PSU_FAN_INT); +static SENSOR_DEVICE_ATTR(spi_wp_gbe, S_IRUGO | S_IWUSR, get_cpld_data, set_cpld_data, SPI_WP_GBE); +static SENSOR_DEVICE_ATTR(eeprom_wp, S_IRUGO | S_IWUSR, get_cpld_data, set_cpld_data, EEPROM_WP); + +static struct attribute *ag9032v1_cpld_attrs[] = { + &dev_attr_cpld_reg_value.attr, + &dev_attr_cpld_reg_addr.attr, + &sensor_dev_attr_cpld_ver.dev_attr.attr, + &sensor_dev_attr_cpu_board_ver.dev_attr.attr, + &sensor_dev_attr_cpu_id.dev_attr.attr, + &sensor_dev_attr_cpld_rst.dev_attr.attr, + &sensor_dev_attr_mb_rst.dev_attr.attr, + &sensor_dev_attr_i2c_sw_rst.dev_attr.attr, + &sensor_dev_attr_mb_pwr.dev_attr.attr, + &sensor_dev_attr_psu_fan_int.dev_attr.attr, + &sensor_dev_attr_spi_wp_gbe.dev_attr.attr, + &sensor_dev_attr_eeprom_wp.dev_attr.attr, + NULL, +}; + +static struct attribute_group ag9032v1_cpld_attr_group = { + .attrs = ag9032v1_cpld_attrs, +}; + +static int __init cpld_probe(struct platform_device *pdev) +{ + struct platform_data *pdata; + struct i2c_adapter *parent; + int ret; + int retval; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPUPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS2); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n",BUS2); + return -ENODEV; + } + + pdata[cpld].client = i2c_new_dummy(parent, pdata[cpld].reg_addr); + if (!pdata[cpld].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[cpld].reg_addr); + goto error; + } + + retval = sysfs_create_group(&pdev->dev.kobj, &ag9032v1_cpld_attr_group); + if (retval){ + printk(KERN_WARNING "Fail to create cpupld attribute group"); + goto error; + } + return 0; + +error: + i2c_unregister_device(pdata[cpld].client); + i2c_put_adapter(parent); + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &ag9032v1_cpld_attr_group); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[cpld].client) { + if (!parent) { + parent = (pdata[cpld].client)->adapter; + } + i2c_unregister_device(pdata[cpld].client); + } + } + i2c_put_adapter(parent); + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v1-cpupld", + }, +}; +/*---------------- CPUPLD - end ------------- */ + + +/*---------------- module initialization ------------- */ +static int __init delta_ag9032v1_cpupld_init(void) +{ + int ret; + printk(KERN_WARNING "ag9032v1_platform_cpupld module initialization\n"); + + // set the CPUPLD prob and remove + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpupld driver\n"); + goto error_cpupld_driver; + } + + // register the CPUPLD + ret = platform_device_register(&ag9032v1_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpupld device\n"); + goto error_ag9032v1_cpupld; + } + return 0; + +error_ag9032v1_cpupld: + platform_driver_unregister(&cpld_driver); +error_cpupld_driver: + return ret; +} + +static void __exit delta_ag9032v1_cpupld_exit(void) +{ + platform_device_unregister(&ag9032v1_cpld); + platform_driver_unregister(&cpld_driver); +} +module_init(delta_ag9032v1_cpupld_init); +module_exit(delta_ag9032v1_cpupld_exit); + +MODULE_DESCRIPTION("DNI ag9032v1 CPLD Platform Support"); +MODULE_AUTHOR("Stanley Chi "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c new file mode 100644 index 000000000000..70cd8b581df4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/delta_ag9032v1_platform.c @@ -0,0 +1,2554 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUS3_DEV_NUM 9 +#define BUS4_DEV_NUM 6 +#define BUS5_DEV_NUM 32 +#define DEFAULT_NUM 1 +#define BUS3_BASE_NUM 30 +#define BUS4_BASE_NUM 40 +#define BUS5_BASE_NUM 50 + +#define BUS3_MUX_REG 0x21 +#define BUS4_MUX_REG 0x21 +#define BUS5_MUX_REG 0x20 + +#define TEMP_FAN_VAL 0x06 +#define FANIO_CTL_VAL 0x07 +#define FAN_CTRL_VAL 0x05 +#define PSU1_VAL 0x00 +#define PSU2_VAL 0x20 +#define HOT_SWAP1_VAL 0x10 +#define HOT_SWAP2_VAL 0x30 +#define FAN_EEPROM1_VAL 0x00 +#define FAN_EEPROM2_VAL 0x01 +#define FAN_EEPROM3_VAL 0x02 +#define FAN_EEPROM4_VAL 0x03 +#define FAN_EEPROM5_VAL 0x04 + +#define SWPLD_REG 0x31 +#define SWPLD_SFP_MUX_REG 0x20 + +#define SYS_LED_REG 0x1C +#define FAN1_LED_REG 0x1D +#define FAN2_LED_REG 0x1E + +#define SFP_PRESENCE_1 0x38 +#define SFP_PRESENCE_2 0x39 +#define SFP_PRESENCE_3 0x3A +#define SFP_PRESENCE_4 0x3B + +#define SFP_LP_MODE_1 0x34 +#define SFP_LP_MODE_2 0x35 +#define SFP_LP_MODE_3 0x36 +#define SFP_LP_MODE_4 0x37 + +#define SFP_RESET_1 0x3C +#define SFP_RESET_2 0x3D +#define SFP_RESET_3 0x3E +#define SFP_RESET_4 0x3F + +#define SFP_RESPONSE_1 0x30 +#define SFP_RESPONSE_2 0x31 +#define SFP_RESPONSE_3 0x32 +#define SFP_RESPONSE_4 0x33 + +#define SFF8436_INFO(data) \ + .type = "sff8436", .addr = 0x50, .platform_data = (data) + +#define SFF_8346_PORT(eedata) \ + .byte_len = 256, .page_size = 1, .flags = SFF_8436_FLAG_READONLY + +#define ag9032v1_i2c_device_num(NUM){ \ + .name = "delta-ag9032v1-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &ag9032v1_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +/*Define struct to get client of i2c_new_deivce */ +struct i2c_client * i2c_client_9547; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, +}; + +unsigned char reverse_8bits(unsigned char c) +{ + unsigned char s = 0; + int i; + for (i = 0; i < 8; ++i) { + s <<= 1; + s |= c & 1; + c >>= 1; + } + return s; +} +/*---------------- I2C device - start ------------- */ +static void device_release(struct device *dev) +{ + return; +} + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; +/* pca9547 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = { + { .adap_id = 2, + .deselect_on_exit = 1, + }, + { .adap_id = 3, + .deselect_on_exit = 1, + }, + { .adap_id = 4, + .deselect_on_exit = 1, + }, + { .adap_id = 5, + .deselect_on_exit = 1, + }, + { .adap_id = 6, + .deselect_on_exit = 1, + }, + { .adap_id = 7, + .deselect_on_exit = 1, + }, + { .adap_id = 8, + .deselect_on_exit = 1, + }, + { .adap_id = 9, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = { + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct i2c_board_info __initdata i2c_info_pca9547[] = +{ + { + I2C_BOARD_INFO("pca9547", 0x71), + .platform_data = &pca954x_data, + }, +}; + + +static struct sff_8436_platform_data sff_8436_port[] = { + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, + { SFF_8346_PORT() }, +}; + +static struct i2c_device_platform_data ag9032v1_i2c_device_platform_data[] = { + { + /* tmp75 (0x4d) */ + .parent = 2, + .info = { I2C_BOARD_INFO("tmp75", 0x4d) }, + .client = NULL, + }, + { + /* id eeprom (0x53) */ + .parent = 2, + .info = { I2C_BOARD_INFO("24c02", 0x53) }, + .client = NULL, + }, + { + /* tmp75 (0x4c) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x4c) }, + .client = NULL, + }, + { + /* tmp75 (0x4d) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x4d) }, + .client = NULL, + }, + { + /* tmp75 (0x4e) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x4e) }, + .client = NULL, + }, + { + /* tmp75 (0x4f) */ + .parent = 30, + .info = { I2C_BOARD_INFO("tmp75", 0x4f) }, + .client = NULL, + }, + { + /* FAN 1 Controller (0x2c) */ + .parent = 37, + .info = { I2C_BOARD_INFO("emc2305", 0x2c) }, + .client = NULL, + }, + { + /* FAN 2 Controller (0x2d) */ + .parent = 38, + .info = { I2C_BOARD_INFO("emc2305", 0x2d) }, + .client = NULL, + }, + { + /* psu 1 (0x58) */ + .parent = 40, + .info = { .type = "dni_ag9032v1_psu", .addr = 0x58, .platform_data = (void *) 0 }, + .client = NULL, + }, + { + /* psu 2 (0x58) */ + .parent = 41, + .info = { .type = "dni_ag9032v1_psu", .addr = 0x58, .platform_data = (void *) 1 }, + .client = NULL, + }, + { + /* hot-swap 1 (0x40) */ + .parent = 42, + .info = { .type = "ltc4215", .addr = 0x40, .platform_data = (void *) 0 }, + .client = NULL, + }, + { + /* hot-swap 2 (0x40) */ + .parent = 43, + .info = { .type = "ltc4215", .addr = 0x40, .platform_data = (void *) 1 }, + .client = NULL, + }, + { + /* qsfp 1 (0x50) */ + .parent = 50, + .info = { SFF8436_INFO(&sff_8436_port[0]) }, + .client = NULL, + }, + { + /* qsfp 2 (0x50) */ + .parent = 51, + .info = { SFF8436_INFO(&sff_8436_port[1]) }, + .client = NULL, + }, + { + /* qsfp 3 (0x50) */ + .parent = 52, + .info = { SFF8436_INFO(&sff_8436_port[2]) }, + .client = NULL, + }, + { + /* qsfp 4 (0x50) */ + .parent = 53, + .info = { SFF8436_INFO(&sff_8436_port[3]) }, + .client = NULL, + }, + { + /* qsfp 5 (0x50) */ + .parent = 54, + .info = { SFF8436_INFO(&sff_8436_port[4]) }, + .client = NULL, + }, + { + /* qsfp 6 (0x50) */ + .parent = 55, + .info = { SFF8436_INFO(&sff_8436_port[5]) }, + .client = NULL, + }, + { + /* qsfp 7 (0x50) */ + .parent = 56, + .info = { SFF8436_INFO(&sff_8436_port[6]) }, + .client = NULL, + }, + { + /* qsfp 8 (0x50) */ + .parent = 57, + .info = { SFF8436_INFO(&sff_8436_port[7]) }, + .client = NULL, + }, + { + /* qsfp 9 (0x50) */ + .parent = 58, + .info = { SFF8436_INFO(&sff_8436_port[8]) }, + .client = NULL, + }, + { + /* qsfp 10 (0x50) */ + .parent = 59, + .info = { SFF8436_INFO(&sff_8436_port[9]) }, + .client = NULL, + }, + { + /* qsfp 11 (0x50) */ + .parent = 60, + .info = { SFF8436_INFO(&sff_8436_port[10]) }, + .client = NULL, + }, + { + /* qsfp 12 (0x50) */ + .parent = 61, + .info = { SFF8436_INFO(&sff_8436_port[11]) }, + .client = NULL, + }, + { + /* qsfp 13 (0x50) */ + .parent = 62, + .info = { SFF8436_INFO(&sff_8436_port[12]) }, + .client = NULL, + }, + { + /* qsfp 14 (0x50) */ + .parent = 63, + .info = { SFF8436_INFO(&sff_8436_port[13]) }, + .client = NULL, + }, + { + /* qsfp 15 (0x50) */ + .parent = 64, + .info = { SFF8436_INFO(&sff_8436_port[14]) }, + .client = NULL, + }, + { + /* qsfp 16 (0x50) */ + .parent = 65, + .info = { SFF8436_INFO(&sff_8436_port[15]) }, + .client = NULL, + }, + { + /* qsfp 17 (0x50) */ + .parent = 66, + .info = { SFF8436_INFO(&sff_8436_port[16]) }, + .client = NULL, + }, + { + /* qsfp 18 (0x50) */ + .parent = 67, + .info = { SFF8436_INFO(&sff_8436_port[17]) }, + .client = NULL, + }, + { + /* qsfp 19 (0x50) */ + .parent = 68, + .info = { SFF8436_INFO(&sff_8436_port[18]) }, + .client = NULL, + }, + { + /* qsfp 20 (0x50) */ + .parent = 69, + .info = { SFF8436_INFO(&sff_8436_port[19]) }, + .client = NULL, + }, + { + /* qsfp 21 (0x50) */ + .parent = 70, + .info = { SFF8436_INFO(&sff_8436_port[20]) }, + .client = NULL, + }, + { + /* qsfp 22 (0x50) */ + .parent = 71, + .info = { SFF8436_INFO(&sff_8436_port[21]) }, + .client = NULL, + }, + { + /* qsfp 23 (0x50) */ + .parent = 72, + .info = { SFF8436_INFO(&sff_8436_port[22]) }, + .client = NULL, + }, + { + /* qsfp 24 (0x50) */ + .parent = 73, + .info = { SFF8436_INFO(&sff_8436_port[23]) }, + .client = NULL, + }, + { + /* qsfp 25 (0x50) */ + .parent = 74, + .info = { SFF8436_INFO(&sff_8436_port[24]) }, + .client = NULL, + }, + { + /* qsfp 26 (0x50) */ + .parent = 75, + .info = { SFF8436_INFO(&sff_8436_port[25]) }, + .client = NULL, + }, + { + /* qsfp 27 (0x50) */ + .parent = 76, + .info = { SFF8436_INFO(&sff_8436_port[26]) }, + .client = NULL, + }, + { + /* qsfp 28 (0x50) */ + .parent = 77, + .info = { SFF8436_INFO(&sff_8436_port[27]) }, + .client = NULL, + }, + { + /* qsfp 29 (0x50) */ + .parent = 78, + .info = { SFF8436_INFO(&sff_8436_port[28]) }, + .client = NULL, + }, + { + /* qsfp 30 (0x50) */ + .parent = 79, + .info = { SFF8436_INFO(&sff_8436_port[29]) }, + .client = NULL, + }, + { + /* qsfp 31 (0x50) */ + .parent = 80, + .info = { SFF8436_INFO(&sff_8436_port[30]) }, + .client = NULL, + }, + { + /* qsfp 32 (0x50) */ + .parent = 81, + .info = { SFF8436_INFO(&sff_8436_port[31]) }, + .client = NULL, + }, +}; + + +static struct platform_device ag9032v1_i2c_device[] = { + ag9032v1_i2c_device_num(0), + ag9032v1_i2c_device_num(1), + ag9032v1_i2c_device_num(2), + ag9032v1_i2c_device_num(3), + ag9032v1_i2c_device_num(4), + ag9032v1_i2c_device_num(5), + ag9032v1_i2c_device_num(6), + ag9032v1_i2c_device_num(7), + ag9032v1_i2c_device_num(8), + ag9032v1_i2c_device_num(9), + ag9032v1_i2c_device_num(10), + ag9032v1_i2c_device_num(11), + ag9032v1_i2c_device_num(12), + ag9032v1_i2c_device_num(13), + ag9032v1_i2c_device_num(14), + ag9032v1_i2c_device_num(15), + ag9032v1_i2c_device_num(16), + ag9032v1_i2c_device_num(17), + ag9032v1_i2c_device_num(18), + ag9032v1_i2c_device_num(19), + ag9032v1_i2c_device_num(20), + ag9032v1_i2c_device_num(21), + ag9032v1_i2c_device_num(22), + ag9032v1_i2c_device_num(23), + ag9032v1_i2c_device_num(24), + ag9032v1_i2c_device_num(25), + ag9032v1_i2c_device_num(26), + ag9032v1_i2c_device_num(27), + ag9032v1_i2c_device_num(28), + ag9032v1_i2c_device_num(29), + ag9032v1_i2c_device_num(30), + ag9032v1_i2c_device_num(31), + ag9032v1_i2c_device_num(32), + ag9032v1_i2c_device_num(33), + ag9032v1_i2c_device_num(34), + ag9032v1_i2c_device_num(35), + ag9032v1_i2c_device_num(36), + ag9032v1_i2c_device_num(37), + ag9032v1_i2c_device_num(38), + ag9032v1_i2c_device_num(39), + ag9032v1_i2c_device_num(40), + ag9032v1_i2c_device_num(41), + ag9032v1_i2c_device_num(42), + ag9032v1_i2c_device_num(43), +}; + +/*---------------- I2C device - end ------------- */ + +/*---------------- I2C driver - start ------------- */ +static int __init i2c_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v1-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- CPLD - start ------------- */ + +/* CPLD -- device */ + +enum cpld_type { + system_cpld, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +enum swpld_attributes { + SW_BOARD_ID, + SW_BOARD_VER, + SWPLD_VER, + SYS_RST, + B56960_RST, + MB_A_PLD_RST, + MB_B_PLD_RST, + PSU1_PWR_OK, + PSU2_PWR_OK, + HS1_PWR_OK, + HS2_PWR_OK, + B54616_RST, + B54616_INT, + B54616_MASK_INT, + PB_HS_INT, + MB_HS_INT, + PB_PWR_INT, + MB_PWR_INT, + FAN_INT, + PB_HS_MASK_INT, + MB_HS_MASK_INT, + PB_PWR1_MASK_INT, + PB_PWR2_MASK_INT, + FAN_MASK_INT, + QSFP_01TO08_INT, + QSFP_08TO16_INT, + QSFP_17TO24_INT, + QSFP_25TO32_INT, + QSFP_01TO08_ABS, + QSFP_08TO16_ABS, + QSFP_17TO24_ABS, + QSFP_25TO32_ABS, + QSFP_01TO08_MASK_INT, + QSFP_08TO16_MASK_INT, + QSFP_17TO24_MASK_INT, + QSFP_25TO32_MASK_INT, + QSFP_01TO08_MASK_ABS, + QSFP_08TO16_MASK_ABS, + QSFP_17TO24_MASK_ABS, + QSFP_25TO32_MASK_ABS, + QSFP01_MOD_INT, + QSFP02_MOD_INT, + QSFP03_MOD_INT, + QSFP04_MOD_INT, + QSFP05_MOD_INT, + QSFP06_MOD_INT, + QSFP07_MOD_INT, + QSFP08_MOD_INT, + QSFP09_MOD_INT, + QSFP10_MOD_INT, + QSFP11_MOD_INT, + QSFP12_MOD_INT, + QSFP13_MOD_INT, + QSFP14_MOD_INT, + QSFP15_MOD_INT, + QSFP16_MOD_INT, + QSFP17_MOD_INT, + QSFP18_MOD_INT, + QSFP19_MOD_INT, + QSFP20_MOD_INT, + QSFP21_MOD_INT, + QSFP22_MOD_INT, + QSFP23_MOD_INT, + QSFP24_MOD_INT, + QSFP25_MOD_INT, + QSFP26_MOD_INT, + QSFP27_MOD_INT, + QSFP28_MOD_INT, + QSFP29_MOD_INT, + QSFP30_MOD_INT, + QSFP31_MOD_INT, + QSFP32_MOD_INT, +}; + +static struct cpld_platform_data ag9032v1_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = SWPLD_REG, + }, +}; + +static struct platform_device ag9032v1_cpld = { + .name = "delta-ag9032v1-swpld", + .id = 0, + .dev = { + .platform_data = ag9032v1_cpld_platform_data, + .release = device_release, + }, +}; + +static struct swpld_attribute_data { + int reg_addr; + int reg_mask; + char reg_note[150]; +}; + +static struct swpld_attribute_data controller_interrupt_data[] = { +//BOARD + [SYS_RST] = { + .reg_addr = 0x04, + .reg_mask = 7, + .reg_note = "“1” = Normal operation\n“0” = Reset" + }, + [B56960_RST] = { + .reg_addr = 0x04, + .reg_mask = 6, + .reg_note = "“1” = Normal operation\n“0” = Reset" + }, + [MB_A_PLD_RST] = { + .reg_addr = 0x04, + .reg_mask = 4, + .reg_note = "“1” = Normal operation\n“0” = Reset" + }, + [MB_B_PLD_RST] = { + .reg_addr = 0x04, + .reg_mask = 3, + .reg_note = "“1” = Normal operation\n“0” = Reset" + }, +//PSU + [PSU1_PWR_OK] = { + .reg_addr = 0x0a, + .reg_mask = 7, + .reg_note = "‘0’ = Power rail is failed\n‘1’ = Power rail is good" + }, + [PSU2_PWR_OK] = { + .reg_addr = 0x0a, + .reg_mask = 6, + .reg_note = "‘0’ = Power rail is failed\n‘1’ = Power rail is good" + }, +//HOT SWAP + [HS1_PWR_OK] = { + .reg_addr = 0x08, + .reg_mask = 5, + .reg_note = "‘0’ = Hot swap controller disabled\n‘1’ = Hot swap controller enabled" + }, + [HS2_PWR_OK] = { + .reg_addr = 0x08, + .reg_mask = 4, + .reg_note = "‘0’ = Hot swap controller disabled\n‘1’ = Hot swap controller enabled" + }, +//BCM54616S + [B54616_RST] = { + .reg_addr = 0x04, + .reg_mask = 5, + .reg_note = "“0” = Reset\n“1” = Normal operation" + }, + [B54616_INT] = { + .reg_addr = 0x16, + .reg_mask = 7, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [B54616_MASK_INT] = { + .reg_addr = 0x17, + .reg_mask = 7, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, +//QSFP + [PB_HS_INT] = { + .reg_addr = 0x10, + .reg_mask = 7, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [MB_HS_INT] = { + .reg_addr = 0x10, + .reg_mask = 6, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [PB_PWR_INT] = { + .reg_addr = 0x10, + .reg_mask = 5, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [MB_PWR_INT] = { + .reg_addr = 0x10, + .reg_mask = 4, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [FAN_INT] = { + .reg_addr = 0x10, + .reg_mask = 3, + .reg_note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [PB_HS_MASK_INT] = { + .reg_addr = 0x11, + .reg_mask = 7, + .reg_note = "‘0’ = Interrupt doesn’t masked\n‘1’ = Interrupt masked" + }, + [MB_HS_MASK_INT] = { + .reg_addr = 0x11, + .reg_mask = 6, + .reg_note = "‘0’ = Interrupt doesn’t masked\n‘1’ = Interrupt masked" + }, + [PB_PWR1_MASK_INT] = { + .reg_addr = 0x11, + .reg_mask = 5, + .reg_note = "‘0’ = Interrupt doesn’t masked\n‘1’ = Interrupt masked" + }, + [PB_PWR2_MASK_INT] = { + .reg_addr = 0x11, + .reg_mask = 4, + .reg_note = "‘0’ = Interrupt doesn’t masked\n‘1’ = Interrupt masked" + }, + [FAN_MASK_INT] = { + .reg_addr = 0x11, + .reg_mask = 3, + .reg_note = "‘0’ = Interrupt doesn’t masked\n‘1’ = Interrupt masked" + }, + [QSFP_01TO08_INT] = { + .reg_addr = 0x12, + .reg_mask = 7, + .reg_note = "“0” = Interrupt occurs\n“1” = Interrupt doesn’t occur" + }, + [QSFP_08TO16_INT] = { + .reg_addr = 0x12, + .reg_mask = 6, + .reg_note = "“0” = Interrupt occurs\n“1” = Interrupt doesn’t occur" + }, + [QSFP_17TO24_INT] = { + .reg_addr = 0x12, + .reg_mask = 5, + .reg_note = "“0” = Interrupt occurs\n“1” = Interrupt doesn’t occur" + }, + [QSFP_25TO32_INT] = { + .reg_addr = 0x12, + .reg_mask = 4, + .reg_note = "“0” = Interrupt occurs\n“1” = Interrupt doesn’t occur" + }, + [QSFP_01TO08_ABS] = { + .reg_addr = 0x12, + .reg_mask = 3, + .reg_note = "“0” = Absence status change\n“1” = Absence status not changes" + }, + [QSFP_08TO16_ABS] = { + .reg_addr = 0x12, + .reg_mask = 2, + .reg_note = "“0” = Absence status change\n“1” = Absence status not changes" + }, + [QSFP_17TO24_ABS] = { + .reg_addr = 0x12, + .reg_mask = 1, + .reg_note = "“0” = Absence status change\n“1” = Absence status not changes" + }, + [QSFP_25TO32_ABS] = { + .reg_addr = 0x12, + .reg_mask = 0, + .reg_note = "“0” = Absence status change\n“1” = Absence status not changes" + }, + [QSFP_01TO08_MASK_INT] = { + .reg_addr = 0x13, + .reg_mask = 7, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_08TO16_MASK_INT] = { + .reg_addr = 0x13, + .reg_mask = 6, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_17TO24_MASK_INT] = { + .reg_addr = 0x13, + .reg_mask = 5, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_25TO32_MASK_INT] = { + .reg_addr = 0x13, + .reg_mask = 4, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_01TO08_MASK_ABS] = { + .reg_addr = 0x13, + .reg_mask = 3, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_08TO16_MASK_ABS] = { + .reg_addr = 0x13, + .reg_mask = 2, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_17TO24_MASK_ABS] = { + .reg_addr = 0x13, + .reg_mask = 1, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP_25TO32_MASK_ABS] = { + .reg_addr = 0x13, + .reg_mask = 0, + .reg_note = "“0” = Interrupt doesn’t masked\n“1” = Interrupt masked" + }, + [QSFP01_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 7, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP02_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 6, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP03_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 5, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP04_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 4, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP05_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 3, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP06_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 2, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP07_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 1, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP08_MOD_INT] = { + .reg_addr = 0x40, + .reg_mask = 0, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP09_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 7, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP10_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 6, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP11_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 5, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP12_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 4, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP13_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 3, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP14_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 2, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP15_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 1, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP16_MOD_INT] = { + .reg_addr = 0x41, + .reg_mask = 0, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP17_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 7, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP18_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 6, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP19_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 5, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP20_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 4, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP21_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 3, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP22_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 2, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP23_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 1, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP24_MOD_INT] = { + .reg_addr = 0x42, + .reg_mask = 0, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP25_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 7, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP26_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 6, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP27_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 5, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP28_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 4, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP29_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 3, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP30_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 2, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP31_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 1, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, + [QSFP32_MOD_INT] = { + .reg_addr = 0x43, + .reg_mask = 0, + .reg_note = "“0” = The module issue the interrupt\n“1” = The module NOT issue the interrupt" + }, +}; + +static ssize_t get_present(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_1); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u32)reverse_8bits(ret) & 0xff; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_2); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_3); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_PRESENCE_4); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_1); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u32)(reverse_8bits(ret) & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_2); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_3); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_LP_MODE_4); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_1, (u8)reverse_8bits(data & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_2, (u8)(reverse_8bits(data >> 8) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_3, (u8)(reverse_8bits(data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_LP_MODE_4, (u8)(reverse_8bits(data >> 24) & 0xff)); + + return count; +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_1); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u32)(reverse_8bits(ret) & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_2); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_3); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESET_4); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_1, (u8)reverse_8bits(data & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_2, (u8)reverse_8bits((data >> 8)& 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_3, (u8)reverse_8bits((data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESET_4, (u8)reverse_8bits((data >> 24) & 0xff)); + + return count; +} + +static ssize_t get_response(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + u32 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_1); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data = (u32)(reverse_8bits(ret) & 0xff); + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_2); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 8; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_3); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 16; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, SFP_RESPONSE_4); + if (ret < 0) + return sprintf(buf, "error number(%d)",ret); + data |= (u32)(reverse_8bits(ret) & 0xff) << 24; + + return sprintf(buf, "0x%08x\n", data); //return 32bits data +} + +static ssize_t set_response(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_1, (u8)reverse_8bits(data & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_2, (u8)reverse_8bits((data >> 8)& 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_3, (u8)reverse_8bits((data >> 16) & 0xff)); + i2c_smbus_write_byte_data(pdata[system_cpld].client, SFP_RESPONSE_4, (u8)reverse_8bits((data >> 24) & 0xff)); + + return count; +} + +struct platform_led_status{ + int reg_data; + char *led_status; + int led_id; +}; + +static struct platform_led_status led_info[] = { + { + .reg_data = 0x40, + .led_status = "pwr1_green", + .led_id = 0, + }, + { + .reg_data = 0x80, + .led_status = "pwr1_amber", + .led_id = 0, + }, + { + .reg_data = 0x00, + .led_status = "pwr1_off", + .led_id = 0, + }, + { + .reg_data = 0xc0, + .led_status = "pwr1_off", + .led_id = 0, + }, + { + .reg_data = 0x10, + .led_status = "pwr2_green", + .led_id = 1, + }, + { + .reg_data = 0x20, + .led_status = "pwr2_amber", + .led_id = 1, + }, + { + .reg_data = 0x00, + .led_status = "pwr2_off", + .led_id = 1, + }, + { + .reg_data = 0x30, + .led_status = "pwr2_off", + .led_id = 1, + }, + { + .reg_data = 0x04, + .led_status = "sys_green", + .led_id = 2, + }, + { + .reg_data = 0x08, + .led_status = "sys_blinking_green", + .led_id = 2, + }, + { + .reg_data = 0x0c, + .led_status = "sys_red", + .led_id = 2, + }, + { + .reg_data = 0x00, + .led_status = "sys_off", + .led_id = 2, + }, + { + .reg_data = 0x01, + .led_status = "fan_green", + .led_id = 3, + }, + { + .reg_data = 0x02, + .led_status = "fan_amber", + .led_id = 3, + }, + { + .reg_data = 0x00, + .led_status = "fan_off", + .led_id = 3, + }, + { + .reg_data = 0x03, + .led_status = "fan_off", + .led_id = 3, + }, + { + .reg_data = 0x40, + .led_status = "fan1_green", + .led_id = 4, + }, + { + .reg_data = 0x80, + .led_status = "fan1_red", + .led_id = 4, + }, + { + .reg_data = 0x00, + .led_status = "fan1_off", + .led_id = 4, + }, + { + .reg_data = 0x10, + .led_status = "fan2_green", + .led_id = 5, + }, + { + .reg_data = 0x20, + .led_status = "fan2_red", + .led_id = 5, + }, + { + .reg_data = 0x00, + .led_status = "fan2_off", + .led_id = 5, + }, + { + .reg_data = 0x04, + .led_status = "fan3_green", + .led_id = 6, + }, + { + .reg_data = 0x08, + .led_status = "fan3_red", + .led_id = 6, + }, + { + .reg_data = 0x00, + .led_status = "fan3_off", + .led_id = 6, + }, + { + .reg_data = 0x01, + .led_status = "fan4_green", + .led_id = 7, + }, + { + .reg_data = 0x02, + .led_status = "fan4_red", + .led_id = 7, + }, + { + .reg_data = 0x00, + .led_status = "fan4_off", + .led_id = 7, + }, + { + .reg_data = 0x40, + .led_status = "fan5_green", + .led_id = 8, + }, + { + .reg_data = 0x80, + .led_status = "fan5_red", + .led_id = 8, + }, + { + .reg_data = 0x00, + .led_status = "fan5_off", + .led_id = 8, + }, +}; + +struct platform_led_data{ + int reg_addr; + int mask; +}; + +static struct platform_led_data led_data[] = { + { + .reg_addr = SYS_LED_REG, + .mask = 0xc0, + }, + { + .reg_addr = SYS_LED_REG, + .mask = 0x30, + }, + { + .reg_addr = SYS_LED_REG, + .mask = 0x0c, + }, + { + .reg_addr = SYS_LED_REG, + .mask = 0x03, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0xc0, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0x30, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0x0c, + }, + { + .reg_addr = FAN1_LED_REG, + .mask = 0x03, + }, + { + .reg_addr = FAN2_LED_REG, + .mask = 0xc0, + }, +}; + +static ssize_t get_led_color(struct device *dev, struct device_attribute *devattr, char *buf) +{ + char str[9][20] = {0}; + int board_data; + int led_data_number; + int led_info_number; + struct cpld_platform_data *pdata = dev->platform_data; + + for(led_data_number = 0; led_data_number < ARRAY_SIZE(led_data); led_data_number++){ + board_data = i2c_smbus_read_byte_data(pdata[system_cpld].client, led_data[led_data_number].reg_addr); + if(board_data >= 0){ + board_data &= led_data[led_data_number].mask; + for(led_info_number = 0; led_info_number < ARRAY_SIZE(led_info); led_info_number++){ + if (led_data_number == led_info[led_info_number].led_id){ + if(board_data == led_info[led_info_number].reg_data){ + sprintf(str[led_data_number], "%s", led_info[led_info_number].led_status); + } + } + } + } + else + printk( KERN_ERR "Missing LED board data\n"); + } + return sprintf(buf,"%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",str[0],str[1],str[2],str[3],str[4],str[5],str[6],str[7],str[8]); +} + +static ssize_t set_led_color(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + int led_info_number; + int led_data_number; + int str_compar; + int led_reg_value; + struct cpld_platform_data *pdata = dev->platform_data; + + for(led_info_number = 0; led_info_number < ARRAY_SIZE(led_info); led_info_number++){ + str_compar = strncmp(buf,led_info[led_info_number].led_status,strlen(led_info[led_info_number].led_status)); + if(str_compar == 0){ + for(led_data_number = 0; led_data_number < ARRAY_SIZE(led_data); led_data_number++){ + if(led_info[led_info_number].led_id == led_data_number){ + led_reg_value = i2c_smbus_read_byte_data(pdata[system_cpld].client, led_data[led_data_number].reg_addr); + if(led_reg_value >= 0){ + led_reg_value &= (~led_data[led_data_number].mask); + led_reg_value |= led_info[led_info_number].reg_data; + i2c_smbus_write_byte_data(pdata[system_cpld].client, (u8)(led_data[led_data_number].reg_addr & 0xff), (u8)(led_reg_value & 0xff)); + } + else + printk( KERN_ERR "Missing LED reg. data\n"); + } + } + } + } + return count; +} + +static unsigned char swpld_reg_addr; +static ssize_t get_swpld_reg_value(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, swpld_reg_addr); + return sprintf(buf, "0x%02x\n", ret); +} + +static ssize_t set_swpld_reg_value(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + i2c_smbus_write_byte_data(pdata[system_cpld].client, swpld_reg_addr, data); + + return count; +} + +static ssize_t get_swpld_reg_addr(struct device *dev, struct device_attribute *devattr, char *buf) +{ + + return sprintf(buf, "0x%02x\n", swpld_reg_addr); +} + +static ssize_t set_swpld_reg_addr(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long data; + int err; + + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + swpld_reg_addr = data; + + return count; +} + +static DEVICE_ATTR(swpld_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg_value, set_swpld_reg_value); +static DEVICE_ATTR(swpld_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg_addr, set_swpld_reg_addr); +static DEVICE_ATTR(sfp_present, S_IRUGO, get_present, NULL ); +static DEVICE_ATTR(sfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode ); +static DEVICE_ATTR(sfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset ); +static DEVICE_ATTR(sfp_response, S_IRUGO | S_IWUSR, get_response, set_response ); +static DEVICE_ATTR(led_control, S_IRUGO | S_IWUSR, get_led_color, set_led_color); + +static struct attribute *ag9032v1_cpld_attrs[] = { + &dev_attr_swpld_reg_value.attr, + &dev_attr_swpld_reg_addr.attr, + &dev_attr_sfp_response.attr, + &dev_attr_sfp_present.attr, + &dev_attr_sfp_lpmode.attr, + &dev_attr_sfp_reset.attr, + &dev_attr_led_control.attr, + NULL, +}; + +static struct attribute_group ag9032v1_cpld_attr_grp = { + .attrs = ag9032v1_cpld_attrs, +}; + +static struct kobject *kobj_swpld; +static struct kobject *kobj_board; +static struct kobject *kobj_psu; +static struct kobject *kobj_hot_swap; +static struct kobject *kobj_controller_interrupt; +static struct kobject *kobj_BCM54616S; + +static ssize_t get_swpld_data(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_swpld); + struct cpld_platform_data *pdata = i2cdev->platform_data; + + + unsigned char reg; + int mask; + int value; + char note[150]; + + switch (attr->index) { + //attributes on BOARD + case SW_BOARD_ID: + reg = 0x00; + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + value = ret >> 4; + sprintf(note, "\n“0x00”: L9032NB-AL-R\n“0x01”: AK9032-R\n“0x02”: AG9032-R\n“0x03”: AG9032R-R\n“0x04”: AG9032 V1-R\n"); + return sprintf(buf, "0x%02x%s", value, note); + case SW_BOARD_VER: + reg = 0x00; + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + value = ret & 0x0F; + sprintf(note, "\n“0x00”: proto-A\n“0x01”: proto-B\n"); + return sprintf(buf, "0x%02x%s", value, note); + case SWPLD_VER: + reg = 0x01; + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + value = ret & 0xFF; + sprintf(note, " "); + return sprintf(buf, "0x%02x%s", value, note); + //other attributes + case SYS_RST ... QSFP32_MOD_INT: + reg = controller_interrupt_data[attr->index].reg_addr; + mask = controller_interrupt_data[attr->index].reg_mask; + sprintf(note, "\n%s\n",controller_interrupt_data[attr->index].reg_note); + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + value = (ret & (1 << mask)) >> mask; + return sprintf(buf, "%d%s", value, note); + default: + return sprintf(buf, "%d not found", attr->index); + } +} + +static ssize_t set_swpld_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + int ret; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_board->parent); + struct cpld_platform_data *pdata = i2cdev->platform_data; + unsigned char reg; + int mask; + int value; + char note[180]; + int data; + int val; + u8 mask_out; + + ret = kstrtoint(buf, 0, &val); + + if (ret) + { + return ret; + } + if (val > 1) + { + return -EINVAL; + } + + switch (attr->index) { + case SYS_RST ... MB_B_PLD_RST: + case HS1_PWR_OK ... HS2_PWR_OK: + case B54616_RST: + case QSFP_01TO08_MASK_INT... QSFP_25TO32_MASK_ABS: + reg = controller_interrupt_data[attr->index].reg_addr; + mask = controller_interrupt_data[attr->index].reg_mask; + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + mask_out = ret & ~((u8)(1 << mask)); + data = mask_out | (val << mask); + i2c_smbus_write_byte_data(pdata[system_cpld].client, reg, (u8)(data & 0xff)); + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + return count; +} + +static SENSOR_DEVICE_ATTR(sw_board_id, S_IRUGO, get_swpld_data, NULL, SW_BOARD_ID); +static SENSOR_DEVICE_ATTR(sw_board_ver, S_IRUGO, get_swpld_data, NULL, SW_BOARD_VER); +static SENSOR_DEVICE_ATTR(swpld_ver, S_IRUGO, get_swpld_data, NULL, SWPLD_VER); +static SENSOR_DEVICE_ATTR(sys_rst, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, SYS_RST); +static SENSOR_DEVICE_ATTR(B56960_rst, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, B56960_RST); +static SENSOR_DEVICE_ATTR(mb_a_pld_rst, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, MB_A_PLD_RST); +static SENSOR_DEVICE_ATTR(mb_b_pld_rst, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, MB_B_PLD_RST); + +static struct attribute *ag9032v1_swpld_attrs_board[] = { + &sensor_dev_attr_sw_board_id.dev_attr.attr, + &sensor_dev_attr_sw_board_ver.dev_attr.attr, + &sensor_dev_attr_swpld_ver.dev_attr.attr, + &sensor_dev_attr_sys_rst.dev_attr.attr, + &sensor_dev_attr_B56960_rst.dev_attr.attr, + &sensor_dev_attr_mb_a_pld_rst.dev_attr.attr, + &sensor_dev_attr_mb_b_pld_rst.dev_attr.attr, + NULL, +}; + +static SENSOR_DEVICE_ATTR(psu1_pwr_ok, S_IRUGO, get_swpld_data, NULL, PSU1_PWR_OK); +static SENSOR_DEVICE_ATTR(psu2_pwr_ok, S_IRUGO, get_swpld_data, NULL, PSU2_PWR_OK); + +static struct attribute *ag9032v1_swpld_attrs_psu[] = { + &sensor_dev_attr_psu1_pwr_ok.dev_attr.attr, + &sensor_dev_attr_psu2_pwr_ok.dev_attr.attr, + NULL, +}; + +static SENSOR_DEVICE_ATTR(hs1_pwr_ok, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, HS1_PWR_OK); +static SENSOR_DEVICE_ATTR(hs2_pwr_ok, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, HS2_PWR_OK); + +static struct attribute *ag9032v1_swpld_attrs_hot_swap[] = { + &sensor_dev_attr_hs1_pwr_ok.dev_attr.attr, + &sensor_dev_attr_hs2_pwr_ok.dev_attr.attr, + NULL, +}; + +static SENSOR_DEVICE_ATTR(B54616_rst, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, B54616_RST ); +static SENSOR_DEVICE_ATTR(B54616_int, S_IRUGO, get_swpld_data, NULL, B54616_INT ); +static SENSOR_DEVICE_ATTR(B54616_mask_int, S_IRUGO, get_swpld_data, NULL, B54616_MASK_INT); + +static struct attribute *ag9032v1_swpld_attrs_BCM54616S[] = { + &sensor_dev_attr_B54616_rst.dev_attr.attr, + &sensor_dev_attr_B54616_int.dev_attr.attr, + &sensor_dev_attr_B54616_mask_int.dev_attr.attr, + NULL, +}; + +static SENSOR_DEVICE_ATTR(pb_hs_int, S_IRUGO, get_swpld_data, NULL, PB_HS_INT); +static SENSOR_DEVICE_ATTR(mb_hs_int, S_IRUGO, get_swpld_data, NULL, MB_HS_INT); +static SENSOR_DEVICE_ATTR(pb_pwr_int, S_IRUGO, get_swpld_data, NULL, PB_PWR_INT); +static SENSOR_DEVICE_ATTR(mb_pwr_int, S_IRUGO, get_swpld_data, NULL, MB_PWR_INT); +static SENSOR_DEVICE_ATTR(fan_int, S_IRUGO, get_swpld_data, NULL, FAN_INT); +static SENSOR_DEVICE_ATTR(pb_hs_mask_int, S_IRUGO, get_swpld_data, NULL, PB_HS_MASK_INT); +static SENSOR_DEVICE_ATTR(mb_hs_mask_int, S_IRUGO, get_swpld_data, NULL, MB_HS_MASK_INT); +static SENSOR_DEVICE_ATTR(pb_pwr1_mask_int, S_IRUGO, get_swpld_data, NULL, PB_PWR1_MASK_INT); +static SENSOR_DEVICE_ATTR(pb_pwr2_mask_int, S_IRUGO, get_swpld_data, NULL, PB_PWR2_MASK_INT); +static SENSOR_DEVICE_ATTR(fan_mask_int, S_IRUGO, get_swpld_data, NULL, FAN_MASK_INT); +static SENSOR_DEVICE_ATTR(qsfp_01to08_int, S_IRUGO, get_swpld_data, NULL, QSFP_01TO08_INT); +static SENSOR_DEVICE_ATTR(qsfp_08to16_int, S_IRUGO, get_swpld_data, NULL, QSFP_08TO16_INT); +static SENSOR_DEVICE_ATTR(qsfp_17to24_int, S_IRUGO, get_swpld_data, NULL, QSFP_17TO24_INT); +static SENSOR_DEVICE_ATTR(qsfp_25to32_int, S_IRUGO, get_swpld_data, NULL, QSFP_25TO32_INT); +static SENSOR_DEVICE_ATTR(qsfp_01to08_abs, S_IRUGO, get_swpld_data, NULL, QSFP_01TO08_ABS); +static SENSOR_DEVICE_ATTR(qsfp_08to16_abs, S_IRUGO, get_swpld_data, NULL, QSFP_08TO16_ABS); +static SENSOR_DEVICE_ATTR(qsfp_17to24_abs, S_IRUGO, get_swpld_data, NULL, QSFP_17TO24_ABS); +static SENSOR_DEVICE_ATTR(qsfp_25to32_abs, S_IRUGO, get_swpld_data, NULL, QSFP_25TO32_ABS); +static SENSOR_DEVICE_ATTR(qsfp_01to08_mask_int, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_01TO08_MASK_INT); +static SENSOR_DEVICE_ATTR(qsfp_08to16_mask_int, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_08TO16_MASK_INT); +static SENSOR_DEVICE_ATTR(qsfp_17to24_mask_int, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_17TO24_MASK_INT); +static SENSOR_DEVICE_ATTR(qsfp_25to32_mask_int, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_25TO32_MASK_INT); +static SENSOR_DEVICE_ATTR(qsfp_01to08_mask_abs, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_01TO08_MASK_ABS); +static SENSOR_DEVICE_ATTR(qsfp_08to16_mask_abs, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_08TO16_MASK_ABS); +static SENSOR_DEVICE_ATTR(qsfp_17to24_mask_abs, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_17TO24_MASK_ABS); +static SENSOR_DEVICE_ATTR(qsfp_25to32_mask_abs, S_IRUGO | S_IWUSR, get_swpld_data, set_swpld_data, QSFP_25TO32_MASK_ABS); +static SENSOR_DEVICE_ATTR(qsfp01_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP01_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp02_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP02_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp03_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP03_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp04_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP04_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp05_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP05_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp06_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP06_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp07_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP07_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp08_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP08_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp09_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP09_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp10_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP10_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp11_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP11_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp12_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP12_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp13_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP13_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp14_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP14_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp15_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP15_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp16_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP16_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp17_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP17_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp18_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP18_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp19_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP19_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp20_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP20_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp21_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP21_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp22_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP22_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp23_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP23_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp24_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP24_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp25_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP25_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp26_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP26_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp27_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP27_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp28_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP28_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp29_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP29_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp30_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP30_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp31_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP31_MOD_INT); +static SENSOR_DEVICE_ATTR(qsfp32_mod_int, S_IRUGO, get_swpld_data, NULL, QSFP32_MOD_INT); + +static struct attribute *ag9032v1_swpld_attrs_controller_interrupt[] = { + &sensor_dev_attr_pb_hs_int.dev_attr.attr, + &sensor_dev_attr_mb_hs_int.dev_attr.attr, + &sensor_dev_attr_pb_pwr_int.dev_attr.attr, + &sensor_dev_attr_mb_pwr_int.dev_attr.attr, + &sensor_dev_attr_fan_int.dev_attr.attr, + &sensor_dev_attr_pb_hs_mask_int.dev_attr.attr, + &sensor_dev_attr_mb_hs_mask_int.dev_attr.attr, + &sensor_dev_attr_pb_pwr1_mask_int.dev_attr.attr, + &sensor_dev_attr_pb_pwr2_mask_int.dev_attr.attr, + &sensor_dev_attr_fan_mask_int.dev_attr.attr, + &sensor_dev_attr_qsfp_01to08_int.dev_attr.attr, + &sensor_dev_attr_qsfp_08to16_int.dev_attr.attr, + &sensor_dev_attr_qsfp_17to24_int.dev_attr.attr, + &sensor_dev_attr_qsfp_25to32_int.dev_attr.attr, + &sensor_dev_attr_qsfp_01to08_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_08to16_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_17to24_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_25to32_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_01to08_mask_int.dev_attr.attr, + &sensor_dev_attr_qsfp_08to16_mask_int.dev_attr.attr, + &sensor_dev_attr_qsfp_17to24_mask_int.dev_attr.attr, + &sensor_dev_attr_qsfp_25to32_mask_int.dev_attr.attr, + &sensor_dev_attr_qsfp_01to08_mask_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_08to16_mask_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_17to24_mask_abs.dev_attr.attr, + &sensor_dev_attr_qsfp_25to32_mask_abs.dev_attr.attr, + &sensor_dev_attr_qsfp01_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp02_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp03_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp04_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp05_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp06_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp07_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp08_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp09_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp10_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp11_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp12_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp13_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp14_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp15_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp16_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp17_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp18_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp19_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp20_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp21_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp22_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp23_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp24_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp25_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp26_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp27_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp28_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp29_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp30_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp31_mod_int.dev_attr.attr, + &sensor_dev_attr_qsfp32_mod_int.dev_attr.attr, + NULL, +}; + +static struct attribute_group ag9032v1_swpld_attr_grp_board = { + .attrs = ag9032v1_swpld_attrs_board, +}; +static struct attribute_group ag9032v1_swpld_attr_grp_psu = { + .attrs = ag9032v1_swpld_attrs_psu, +}; +static struct attribute_group ag9032v1_swpld_attr_grp_hot_swap = { + .attrs = ag9032v1_swpld_attrs_hot_swap, +}; +static struct attribute_group ag9032v1_swpld_attr_grp_BCM54616S = { + .attrs = ag9032v1_swpld_attrs_BCM54616S, +}; +static struct attribute_group ag9032v1_swpld_attr_grp_controller_interrupt = { + .attrs = ag9032v1_swpld_attrs_controller_interrupt, +}; + +/* CPLD -- driver */ +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS6); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS6); + return -ENODEV; + } + + pdata[system_cpld].client = i2c_new_dummy(parent, pdata[system_cpld].reg_addr); + if (!pdata[system_cpld].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[system_cpld].reg_addr); + goto error; + } + + kobj_swpld = &pdev->dev.kobj; + kobj_board = kobject_create_and_add("Board", &pdev->dev.kobj); + if (!kobj_board){ + printk(KERN_WARNING "Fail to create directory"); + goto error; + } + + kobj_psu = kobject_create_and_add("PSU", &pdev->dev.kobj); + if (!kobj_psu){ + printk(KERN_WARNING "Fail to create directory"); + goto error; + } + + kobj_hot_swap = kobject_create_and_add("HOT_SWAP", &pdev->dev.kobj); + if (!kobj_hot_swap){ + printk(KERN_WARNING "Fail to create directory"); + goto error; + } + + kobj_controller_interrupt = kobject_create_and_add("Controller_interrupt", &pdev->dev.kobj); + if (!kobj_controller_interrupt){ + printk(KERN_WARNING "Fail to create directory"); + goto error; + } + + kobj_BCM54616S = kobject_create_and_add("BCM54616S", &pdev->dev.kobj); + if (!kobj_BCM54616S){ + printk(KERN_WARNING "Fail to create directory"); + goto error; + } + + ret = sysfs_create_group(kobj_board, &ag9032v1_swpld_attr_grp_board); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + ret = sysfs_create_group(kobj_psu, &ag9032v1_swpld_attr_grp_psu); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + ret = sysfs_create_group(kobj_hot_swap, &ag9032v1_swpld_attr_grp_hot_swap); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + ret = sysfs_create_group(kobj_BCM54616S, &ag9032v1_swpld_attr_grp_BCM54616S); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + ret = sysfs_create_group(kobj_controller_interrupt, &ag9032v1_swpld_attr_grp_controller_interrupt); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &ag9032v1_cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_swpld); + kobject_put(kobj_board); + kobject_put(kobj_psu); + kobject_put(kobj_hot_swap); + kobject_put(kobj_controller_interrupt); + kobject_put(kobj_BCM54616S); + i2c_unregister_device(pdata[system_cpld].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &ag9032v1_cpld_attr_grp); + sysfs_remove_group(kobj_board, &ag9032v1_swpld_attr_grp_board); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + kobject_put(kobj_swpld); + kobject_put(kobj_board); + kobject_put(kobj_psu); + kobject_put(kobj_hot_swap); + kobject_put(kobj_controller_interrupt); + kobject_put(kobj_BCM54616S); + if (pdata[system_cpld].client) { + if (!parent) { + parent = (pdata[system_cpld].client)->adapter; + } + i2c_unregister_device(pdata[system_cpld].client); + } + } + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v1-swpld", + }, +}; + +/*---------------- CPLD - end ------------- */ + +/*---------------- MUX - start ------------- */ + +struct swpld_mux_platform_data { + int parent; + int base_nr; + int reg_addr; + struct i2c_client *cpld; +}; + +struct swpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct swpld_mux_platform_data data; +}; +static struct swpld_mux_platform_data ag9032v1_swpld_mux_platform_data[] = { + { + .parent = BUS3, + .base_nr = BUS3_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS3_MUX_REG ,// the i2c register address which for select mux TEMP(FAN) + }, + { + .parent = BUS4, + .base_nr = BUS4_BASE_NUM , + .cpld = NULL, + .reg_addr = BUS4_MUX_REG , + }, + { + .parent = BUS5, + .base_nr = BUS5_BASE_NUM , + .cpld = NULL, + .reg_addr = BUS5_MUX_REG , + }, +}; + +static struct platform_device ag9032v1_swpld_mux[] = { + { + .name = "delta-ag9032v1-swpld-mux", + .id = 0, + .dev = { + .platform_data = &ag9032v1_swpld_mux_platform_data[0], + .release = device_release, + }, + }, + { + .name = "delta-ag9032v1-swpld-mux", + .id = 1, + .dev = { + .platform_data = &ag9032v1_swpld_mux_platform_data[1], + .release = device_release, + }, + }, + { + .name = "delta-ag9032v1-swpld-mux", + .id = 2, + .dev = { + .platform_data = &ag9032v1_swpld_mux_platform_data[2], + .release = device_release, + }, + }, +}; + +static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int swpld_mux_select(struct i2c_adapter *adap, void *data, u8 chan) +{ + struct swpld_mux *mux = data; + u8 swpld_mux_val=0; + + if ( mux->data.base_nr == BUS3_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = TEMP_FAN_VAL; + break; + case 1: + swpld_mux_val = FAN_EEPROM1_VAL; + break; + case 2: + swpld_mux_val = FAN_EEPROM2_VAL; + break; + case 3: + swpld_mux_val = FAN_EEPROM3_VAL; + break; + case 4: + swpld_mux_val = FAN_EEPROM4_VAL; + break; + case 5: + swpld_mux_val = FAN_EEPROM5_VAL; + break; + case 6: + swpld_mux_val = FANIO_CTL_VAL; + break; + case 7: + case 8: + swpld_mux_val = FAN_CTRL_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS4_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = PSU1_VAL; + break; + case 1: + swpld_mux_val = PSU2_VAL; + break; + case 2: + swpld_mux_val = HOT_SWAP1_VAL; + break; + case 3: + swpld_mux_val = HOT_SWAP2_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS5_BASE_NUM ){ + if (chan < 9){ + swpld_mux_val = (u8)(chan) + 0x01; + } + else if (8 < chan && chan < 19){ + swpld_mux_val = (u8)(chan - 9) + 0x10; + } + else if (18 < chan && chan < 29){ + swpld_mux_val = (u8)(chan - 19) + 0x20; + } + else if (28 < chan && chan < 39){ + swpld_mux_val = (u8)(chan - 29) + 0x30; + } + else{ + swpld_mux_val = 0x00; + } + } + else + { + swpld_mux_val = 0x00; + } + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int swpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct swpld_mux *mux = i2c_mux_priv(muxc); + u8 swpld_mux_val=0; + + if ( mux->data.base_nr == BUS3_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = TEMP_FAN_VAL; + break; + case 1: + swpld_mux_val = FAN_EEPROM1_VAL; + break; + case 2: + swpld_mux_val = FAN_EEPROM2_VAL; + break; + case 3: + swpld_mux_val = FAN_EEPROM3_VAL; + break; + case 4: + swpld_mux_val = FAN_EEPROM4_VAL; + break; + case 5: + swpld_mux_val = FAN_EEPROM5_VAL; + break; + case 6: + swpld_mux_val = FANIO_CTL_VAL; + break; + case 7: + case 8: + swpld_mux_val = FAN_CTRL_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS4_BASE_NUM ) + { + switch (chan) { + case 0: + swpld_mux_val = PSU1_VAL; + break; + case 1: + swpld_mux_val = PSU2_VAL; + break; + case 2: + swpld_mux_val = HOT_SWAP1_VAL; + break; + case 3: + swpld_mux_val = HOT_SWAP2_VAL; + break; + } + } + else if ( mux->data.base_nr == BUS5_BASE_NUM ){ + if (chan < 9){ + swpld_mux_val = (u8)(chan) + 0x01; + } + else if (8 < chan && chan < 19){ + swpld_mux_val = (u8)(chan - 9) + 0x10; + } + else if (18 < chan && chan < 29){ + swpld_mux_val = (u8)(chan - 19) + 0x20; + } + else if (28 < chan && chan < 39){ + swpld_mux_val = (u8)(chan - 29) + 0x30; + } + else{ + swpld_mux_val = 0x00; + } + } + else + { + swpld_mux_val = 0x00; + } + + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); +} +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS3: + dev_num = BUS3_DEV_NUM; + break; + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + case BUS5: + dev_num = BUS5_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for mux\n"); + goto alloc_failed; + } + + mux->parent = parent; + mux->data = *pdata; + mux->child = kzalloc(sizeof(struct i2c_adapter *) * dev_num, GFP_KERNEL); + if (!mux->child) { + ret = -ENOMEM; + printk(KERN_ERR "Failed to allocate memory for device on mux\n"); + goto alloc_failed2; + } + + for (i = 0; i < dev_num; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + mux->child[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, + nr, i, class, + swpld_mux_select, NULL); + if (!mux->child[i]) { + ret = -ENODEV; + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + platform_set_drvdata(pdev, mux); + return 0; + +add_adapter_failed: + for (; i > 0; i--) + i2c_del_mux_adapter(mux->child[i - 1]); + kfree(mux->child); +alloc_failed2: + kfree(mux); +alloc_failed: + i2c_put_adapter(parent); + + return ret; +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + printk(KERN_ERR "Failed to allocate memory for mux\n"); + return -ENOMEM; + } + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + kfree(mux); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS3: + dev_num = BUS3_DEV_NUM; + break; + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + case BUS5: + dev_num = BUS5_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, + swpld_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + platform_set_drvdata(pdev, muxc); + + + for (i = 0; i < dev_num; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_num, parent->name); + + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + kfree(mux); + i2c_put_adapter(parent); + + return ret; +} +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + int i; + struct swpld_mux *mux = platform_get_drvdata(pdev); + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + switch (pdata->parent) { + case BUS3: + dev_num = BUS3_DEV_NUM; + break; + case BUS4: + dev_num = BUS4_DEV_NUM; + break; + case BUS5: + dev_num = BUS5_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + for (i = 0; i < dev_num; i++) + i2c_del_mux_adapter(mux->child[i]); + + platform_set_drvdata(pdev, NULL); + i2c_put_adapter(mux->parent); + kfree(mux->child); + kfree(mux); + + return 0; +} +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + struct i2c_adapter *parent=muxc->parent; + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(parent); + + return 0; +} +#endif + +static struct platform_driver swpld_mux_driver = { + .probe = swpld_mux_probe, + .remove = __exit_p(swpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v1-swpld-mux", + }, +}; +/*---------------- MUX - end ------------- */ + +/*---------------- module initialization ------------- */ +static int __init delta_ag9032v1_platform_init(void) +{ +// struct i2c_client *client; + struct i2c_adapter *adapter; + struct cpld_platform_data *cpld_pdata; + struct swpld_mux_platform_data *swpld_mux_pdata; + int ret,i = 0; + printk("ag9032v1_platform module initialization\n"); + + //Use pca9547 in i2c_mux_pca954x.c + adapter = i2c_get_adapter(BUS1); + //client = i2c_new_device(adapter, &i2c_info_pca9547[0]); + i2c_client_9547 = i2c_new_device(adapter, &i2c_info_pca9547[0]); + + i2c_put_adapter(adapter); + + // set the CPLD prob and remove + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + // register the mux prob which call the CPLD + ret = platform_driver_register(&swpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_swpld_mux_driver; + } + + // register the i2c devices + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + // register the CPLD + ret = platform_device_register(&ag9032v1_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_ag9032v1_cpld; + } + // link the CPLD and the Mux + cpld_pdata = ag9032v1_cpld.dev.platform_data; + + for (i = 0; i < ARRAY_SIZE(ag9032v1_swpld_mux); i++) + { + swpld_mux_pdata = ag9032v1_swpld_mux[i].dev.platform_data; + swpld_mux_pdata->cpld = cpld_pdata[system_cpld].client; + ret = platform_device_register(&ag9032v1_swpld_mux[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_ag9032v1_swpld_mux; + } + } + + for (i = 0; i < ARRAY_SIZE(ag9032v1_i2c_device); i++) + { + ret = platform_device_register(&ag9032v1_i2c_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_ag9032v1_i2c_device; + } + } + + if (ret) + goto error_ag9032v1_swpld_mux; + + return 0; + +error_ag9032v1_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag9032v1_i2c_device[i]); + } + i = ARRAY_SIZE(ag9032v1_swpld_mux); +error_ag9032v1_swpld_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag9032v1_swpld_mux[i]); + } + platform_driver_unregister((struct platform_driver *) &ag9032v1_cpld); +error_ag9032v1_cpld: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld_mux_driver); +error_swpld_mux_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit delta_ag9032v1_platform_exit(void) +{ + int i = 0; + + for ( i = 0; i < ARRAY_SIZE(ag9032v1_i2c_device); i++ ) { + platform_device_unregister(&ag9032v1_i2c_device[i]); + } + + for (i = 0; i < ARRAY_SIZE(ag9032v1_swpld_mux); i++) { + platform_device_unregister(&ag9032v1_swpld_mux[i]); + } + + platform_device_unregister(&ag9032v1_cpld); + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&swpld_mux_driver); + + i2c_unregister_device(i2c_client_9547); +} + +module_init(delta_ag9032v1_platform_init); +module_exit(delta_ag9032v1_platform_exit); + +MODULE_DESCRIPTION("DNI ag9032v1 Platform Support"); +MODULE_AUTHOR("Neal Tai "); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c new file mode 100644 index 000000000000..7d9350bc55bd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_ag9032v1_psu.c @@ -0,0 +1,550 @@ +/* + * An hwmon driver for delta AG9032v1 PSU + * dps_800ab_16_d.c - Support for DPS-800AB-16 D Power Supply Module + * + * Copyright (C) 2016 Delta Network Technology Corporation + * + * DNI + * + * Based on ym2651y.c + * Based on ad7414.c + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 +#define SWPLD_REG 0x31 +#define SWPLD_PSU_MUX_REG 0x21 +#define SELECT_PSU1_EEPROM 0x00 +#define SELECT_PSU2_EEPROM 0x20 + +u8 psu_member_data = 0x00; + + +/* Address scanned */ +static const unsigned short normal_i2c[] = { 0x58, I2C_CLIENT_END }; + +/* This is additional data */ +struct dps_800ab_16_d_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; /* In jiffies */ + + /* Registers value */ + u8 vout_mode; + u16 in1_input; + u16 in2_input; + u16 curr1_input; + u16 curr2_input; + u16 power1_input; + u16 power2_input; + u16 temp_input[2]; + u8 fan_target; + u16 fan_duty_cycle_input[2]; + u16 fan_speed_input[2]; + u8 mfr_model[16]; + u8 mfr_serial[16]; +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count); +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_fan_target(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static int dps_800ab_16_d_read_byte(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value); +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len); +static struct dps_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev); +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t set_w_member_data(struct device *dev, struct device_attribute \ + *dev_att, const char *buf, size_t count); +static ssize_t for_r_member_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); + +enum dps_800ab_16_d_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_MFR_MODEL, + PSU_MFR_SERIAL, + PSU_SELECT_MEMBER, +}; + +static ssize_t set_w_member_data(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + long data; + int error; + if (attr->index == PSU_SELECT_MEMBER) { + error = kstrtol(buf, 16, &data); + if (error) + return error; + if (SELECT_PSU1_EEPROM == data) { + psu_member_data = SELECT_PSU1_EEPROM; + } else if (SELECT_PSU2_EEPROM == data) { + psu_member_data = SELECT_PSU2_EEPROM; + } else { + return -EINVAL; + } + } + return count; +} + +static ssize_t for_r_member_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + return sprintf(buf, "0x%02X\n", psu_member_data); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + /* Select SWPLD PSU offset */ + + mutex_lock(&data->update_lock); + data->fan_duty_cycle_input[nr] = speed; + dps_800ab_16_d_write_word(client, 0x3B + nr, data->fan_duty_cycle_input[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->in1_input; + break; + case PSU_I_IN: + value = data->curr1_input; + break; + case PSU_I_OUT: + value = data->curr2_input; + break; + case PSU_P_IN: + value = data->power1_input; + multiplier = 1000*1000; + break; + case PSU_P_OUT: + value = data->power2_input; + multiplier = 1000*1000; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle_input[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed_input[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_fan_target(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_target >> shift); +} + +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->in2_input; + + return (exponent > 0) ? sprintf(buf, "%d\n", \ + (mantissa * multiplier) / (1 << exponent)): \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) + return 0; + + switch (attr->index) { + case PSU_MFR_MODEL: + ptr = data->mfr_model + 1; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial + 1; + break; + default: + return 0; + } + return sprintf(buf, "%s\n", ptr); +} +static int dps_800ab_16_d_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags |= I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, reg, + I2C_SMBUS_WORD_DATA, &data); + +} + +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, + data); + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; +abort: + return result; + +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct dps_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + /* Select SWPLD PSU offset */ + + if (time_after(jiffies, data->last_updated)) { + int i, status; + u8 command; + struct reg_data_byte regs_byte[] = { + {0x20, &data->vout_mode}, + {0x81, &data->fan_target} + }; + struct reg_data_word regs_word[] = { + {0x88, &data->in1_input}, + {0x8b, &data->in2_input}, + {0x89, &data->curr1_input}, + {0x8c, &data->curr2_input}, + {0x96, &data->power2_input}, + {0x97, &data->power1_input}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle_input[0])}, + {0x90, &(data->fan_speed_input[0])}, + }; + + dev_dbg(&client->dev, "start data update\n"); + + /* one milliseconds from now */ + data->last_updated = jiffies + HZ / 1000; + + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = dps_800ab_16_d_read_byte(client, + regs_byte[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + } else { + *(regs_byte[i].value) = status; + } + } + + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = dps_800ab_16_d_read_word(client, + regs_word[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + } else { + *(regs_word[i].value) = status; + } + } + + command = 0x9a; /* PSU mfr_model */ + //data->mfr_model[1] = '\0'; + status = dps_800ab_16_d_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command,status); + data->mfr_model[1] = '\0'; + } + + command = 0x9e; /* PSU mfr_serial */ + //data->mfr_serial[1] = '\0'; + status = dps_800ab_16_d_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command,status); + data->mfr_serial[1] = '\0'; + } + + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(temp1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_target, \ + S_IRUGO, for_fan_target, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(fan1_set_percentage, S_IWUSR | S_IRUGO, \ + for_linear_data, set_fan_duty_cycle_input, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(fan1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_model, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); +static SENSOR_DEVICE_ATTR(psu_select_member, S_IWUSR | S_IRUGO, \ + for_r_member_data, set_w_member_data, PSU_SELECT_MEMBER); + +static struct attribute *dps_800ab_16_d_attributes[] = { + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_target.dev_attr.attr, + &sensor_dev_attr_fan1_set_percentage.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + &sensor_dev_attr_psu_select_member.dev_attr.attr, + NULL +}; + +static const struct attribute_group dps_800ab_16_d_group = { + .attrs = dps_800ab_16_d_attributes, +}; + +static int dps_800ab_16_d_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct dps_800ab_16_d_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "new chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &dps_800ab_16_d_group); + if (status) + goto exit_sysfs_create_group; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_hwmon_device_register; + } + + return 0; + +exit_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); +exit_sysfs_create_group: + kfree(data); +exit: + return status; +} + +static int dps_800ab_16_d_remove(struct i2c_client *client) +{ + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); + kfree(data); + + return 0; +} + +enum id_name { + dni_ag9032v1_psu, + dps_800ab_16_d +}; + +static const struct i2c_device_id dps_800ab_16_d_id[] = { + { "dni_ag9032v1_psu", dni_ag9032v1_psu }, + { "dps_800ab_16_d", dps_800ab_16_d }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dps_800ab_16_d_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver dps_800ab_16_d_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "dps_800ab_16_d", + }, + .probe = dps_800ab_16_d_probe, + .remove = dps_800ab_16_d_remove, + .id_table = dps_800ab_16_d_id, + .address_list = normal_i2c, +}; + +static int __init dps_800ab_16_d_init(void) +{ + return i2c_add_driver(&dps_800ab_16_d_driver); +} + +static void __exit dps_800ab_16_d_exit(void) +{ + i2c_del_driver(&dps_800ab_16_d_driver); +} + + +MODULE_AUTHOR("Aries Lin "); +MODULE_DESCRIPTION("DPS_800AB_16_D Driver"); +MODULE_LICENSE("GPL"); + +module_init(dps_800ab_16_d_init); +module_exit(dps_800ab_16_d_exit); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_emc2305.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_emc2305.c new file mode 120000 index 000000000000..e8f7ae6b3f4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/modules/dni_emc2305.c @@ -0,0 +1 @@ +../../common/modules/dni_emc2305.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/ag9032v1_platform_init.sh b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/ag9032v1_platform_init.sh new file mode 100755 index 000000000000..b199ff349446 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/ag9032v1_platform_init.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +#platform init script for Delta ag9032v1 + +#fan speed monitol start +/usr/share/sonic/device/x86_64-delta_ag9032v1-r0/fancontrol.service /usr/share/sonic/device/x86_64-delta_ag9032v1-r0/fancontrol & + +#set led status +/usr/local/bin/led_status.sh & + +exit 0 + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/led_status.sh b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/led_status.sh new file mode 100755 index 000000000000..825e09aa4cfb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v1/scripts/led_status.sh @@ -0,0 +1,225 @@ +#!/bin/bash + +FAN1_EEPROM="-y 31 0x51 0x0a" +FAN2_EEPROM="-y 32 0x52 0x0a" +FAN3_EEPROM="-y 33 0x53 0x0a" +FAN4_EEPROM="-y 34 0x54 0x0a" +FAN5_EEPROM="-y 35 0x55 0x0a" +LED_CONTROL="/sys/devices/platform/delta-ag9032v1-swpld.0/led_control" +FAN1_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan5_input" +FAN1_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan5_input" +FAN2_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan4_input" +FAN2_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan4_input" +FAN3_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan3_input" +FAN3_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan3_input" +FAN4_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan2_input" +FAN4_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan2_input" +FAN5_FRONT_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-37/37-002c/fan1_input" +FAN5_REAR_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-3/i2c-38/38-002d/fan1_input" + +PSU1_EEPROM="-y 40 0x50 0x00" +PSU2_EEPROM="-y 41 0x50 0x00" +PSU1_FAN_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-4/i2c-40/40-0058/fan1_input" +PSU2_FAN_RPM="/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-4/i2c-41/41-0058/fan1_input" + +catfaneeprom(){ + fan_eeprom_num=0 + i2cget $FAN1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + i2cget $FAN2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num_num)) + fi + + i2cget $FAN3_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + + i2cget $FAN4_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + + i2cget $FAN5_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi +} + +catfanspeed(){ + fan_rpm_normal_num=0 + fan1_rpm_normal_num=0 + fan1_front_rpm=`cat $FAN1_FRONT_RPM` + fan1_rear_rpm=`cat $FAN1_REAR_RPM` + if [ "${fan1_front_rpm}" -ne "960" ] && [ "${fan1_rear_rpm}" -ne "960" ] && [ "${fan1_front_rpm}" -ne "0" ] && [ "${fan1_rear_rpm}" -ne "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num+1)) + elif [ "${fan1_front_rpm}" -eq "960" ] || [ "${fan1_rear_rpm}" -eq "960" ] || [ "${fan1_front_rpm}" -eq "0" ] || [ "${fan1_rear_rpm}" -eq "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num)) + fi + + fan2_rpm_normal_num=0 + fan2_front_rpm=`cat $FAN2_FRONT_RPM` + fan2_rear_rpm=`cat $FAN2_REAR_RPM` + if [ "${fan2_front_rpm}" -ne "960" ] && [ "${fan2_rear_rpm}" -ne "960" ] && [ "${fan2_front_rpm}" -ne "0" ] && [ "${fan2_rear_rpm}" -ne "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num+1)) + elif [ "${fan2_front_rpm}" -eq "960" ] || [ "${fan2_rear_rpm}" -eq "960" ] || [ "${fan2_front_rpm}" -eq "0" ] || [ "${fan2_rear_rpm}" -eq "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num)) + fi + + fan3_rpm_normal_num=0 + fan3_front_rpm=`cat $FAN3_FRONT_RPM` + fan3_rear_rpm=`cat $FAN3_REAR_RPM` + if [ "${fan3_front_rpm}" -ne "960" ] && [ "${fan3_rear_rpm}" -ne "960" ] && [ "${fan3_front_rpm}" -ne "0" ] && [ "${fan3_rear_rpm}" -ne "0" ]; then + fan3_rpm_normal_num=$((fan3_rpm_normal_num+1)) + elif [ "${fan3_front_rpm}" -eq "960" ] || [ "${fan3_rear_rpm}" -eq "960" ] || [ "${fan3_front_rpm}" -eq "0" ] || [ "${fan3_rear_rpm}" -eq "0" ]; then + fan3_rpm_normal_num=$((fan3_rpm_normal_num)) + fi + + fan4_rpm_normal_num=0 + fan4_front_rpm=`cat $FAN4_FRONT_RPM` + fan4_rear_rpm=`cat $FAN4_REAR_RPM` + if [ "${fan4_front_rpm}" -ne "960" ] && [ "${fan4_rear_rpm}" -ne "960" ] && [ "${fan4_front_rpm}" -ne "0" ] && [ "${fan4_rear_rpm}" -ne "0" ]; then + fan4_rpm_normal_num=$((fan4_rpm_normal_num+1)) + elif [ "${fan4_front_rpm}" -eq "960" ] || [ "${fan4_rear_rpm}" -eq "960" ] || [ "${fan4_front_rpm}" -eq "0" ] || [ "${fan4_rear_rpm}" -eq "0" ]; then + fan4_rpm_normal_num=$((fan4_rpm_normal_num)) + fi + + fan5_rpm_normal_num=0 + fan5_front_rpm=`cat $FAN5_FRONT_RPM` + fan5_rear_rpm=`cat $FAN5_REAR_RPM` + if [ "${fan5_front_rpm}" -ne "960" ] && [ "${fan5_rear_rpm}" -ne "960" ] && [ "${fan5_front_rpm}" -ne "0" ] && [ "${fan5_rear_rpm}" -ne "0" ]; then + fan5_rpm_normal_num=$((fan5_rpm_normal_num+1)) + elif [ "${fan5_front_rpm}" -eq "960" ] || [ "${fan5_rear_rpm}" -eq "960" ] || [ "${fan5_front_rpm}" -eq "0" ] || [ "${fan5_rear_rpm}" -eq "0" ]; then + fan5_rpm_normal_num=$((fan5_rpm_normal_num)) + fi + + fan_rpm_normal_num=$((fan1_rpm_normal_num+fan2_rpm_normal_num+fan3_rpm_normal_num+fan4_rpm_normal_num+fan5_rpm_normal_num)) + +} + +catpsueeprom(){ + psu1_eeprom_num=0 + i2cget $PSU1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu1_eeprom_num=$((psu1_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + psu1_eeprom_num=$((psu1_eeprom_num)) + fi + + psu2_eeprom_num=0 + i2cget $PSU2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu2_eeprom_num=$((psu2_eeprom_num+1)) + elif [ "`echo $?`" -eq "2" ]; then + psu2_eeprom_num=$((psu2_eeprom_num)) + fi +} + +catpsufanspeed(){ + + psu1_rpm_normal_num=0 + psu1_rpm=`cat $PSU1_FAN_RPM` + + if [ "${psu1_rpm}" -ne "960" ] && [ "${psu1_rpm}" -ne "0" ]; then + psu1_rpm_normal_num=$((psu1_rpm_normal_num+1)) + elif [ "${psu1_rpm}" -eq "960" ] || [ "${psu1_rpm}" -eq "0" ]; then + psu1_rpm_normal_num=$((psu1_rpm_normal_num)) + fi + + psu2_rpm_normal_num=0 + psu2_rpm=`cat $PSU2_FAN_RPM` + + if [ "${psu2_rpm}" -ne "960" ] && [ "${psu2_rpm}" -ne "0" ]; then + psu2_rpm_normal_num=$((psu2_rpm_normal_num+1)) + elif [ "${psu2_rpm}" -eq "960" ] || [ "${psu2_rpm}" -eq "0" ]; then + psu2_rpm_normal_num=$((psu2_rpm_normal_num)) + fi + +} + +setfanled(){ + if [ "${fan_eeprom_num}" -eq "5" ] && [ "${fan_rpm_normal_num}" -eq "5" ]; then + echo "fan_green" > $LED_CONTROL + elif [ "${fan_eeprom_num}" -lt "5" ] || [ "${fan_rpm_normal_num}" -lt "5" ]; then + echo "fan_amber" > $LED_CONTROL + fi +} + +setpsuled(){ + if [ "${psu1_eeprom_num}" -eq "1" ] && [ "${psu1_rpm_normal_num}" -eq "1" ]; then + echo "pwr1_green" > $LED_CONTROL + elif [ "${psu1_eeprom_num}" -eq "0" ] || [ "${psu1_rpm_normal_num}" -eq "0" ]; then + echo "pwr1_amber" > $LED_CONTROL + fi + + if [ "${psu2_eeprom_num}" -eq "1" ] && [ "${psu2_rpm_normal_num}" -eq "1" ]; then + echo "pwr2_green" > $LED_CONTROL + elif [ "${psu2_eeprom_num}" -eq "0" ] || [ "${psu2_rpm_normal_num}" -eq "0" ]; then + echo "pwr2_amber" > $LED_CONTROL + fi +} + +setfantrayled(){ + if [ "${fan1_rpm_normal_num}" -eq "1" ]; then + echo "fan1_green" > $LED_CONTROL + else + echo "fan1_red" > $LED_CONTROL + fi + + if [ "${fan2_rpm_normal_num}" -eq "1" ]; then + echo "fan2_green" > $LED_CONTROL + else + echo "fan2_red" > $LED_CONTROL + fi + + if [ "${fan3_rpm_normal_num}" -eq "1" ]; then + echo "fan3_green" > $LED_CONTROL + else + echo "fan3_red" > $LED_CONTROL + fi + + if [ "${fan4_rpm_normal_num}" -eq "1" ]; then + echo "fan4_green" > $LED_CONTROL + else + echo "fan4_red" > $LED_CONTROL + fi + + if [ "${fan5_rpm_normal_num}" -eq "1" ]; then + echo "fan5_green" > $LED_CONTROL + else + echo "fan5_red" > $LED_CONTROL + fi +} + +platformstatus(){ + + echo "sys_green" > $LED_CONTROL + catfaneeprom + catfanspeed + setfanled + setfantrayled + + catpsueeprom + catpsufanspeed + setpsuled +} + +while true +do + platformstatus + sleep 1 +done + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/cfg/ag9032v2a-modules.conf b/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/cfg/ag9032v2a-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/cfg/ag9032v2a-modules.conf @@ -0,0 +1,13 @@ +# /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-delta/ag9032v2a/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/modules/Makefile new file mode 100644 index 000000000000..185357033dff --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/modules/Makefile @@ -0,0 +1 @@ +obj-m += delta_ag9032v2a_platform.o diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/modules/delta_ag9032v2a_platform.c b/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/modules/delta_ag9032v2a_platform.c new file mode 100644 index 000000000000..5345ae86e7f9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/modules/delta_ag9032v2a_platform.c @@ -0,0 +1,1781 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPUPLD_ADDR 0x31 +#define SWPLD1_ADDR 0x6a +#define SWPLD2_ADDR 0x73 +#define SWPLD3_ADDR 0x75 +#define MUX_VAL_SWPLD 0xff +#define MUX_VAL_IDEEPROM 0xfc +#define MUX_VAL_PCA9548 0xfd +#define DEF_DEV_NUM 1 +#define BUS0_DEV_NUM 3 +#define BUS0_BASE_NUM 1 +#define BUS0_MUX_REG 0x14 +#define BUS3_DEV_NUM 33 +#define BUS3_BASE_NUM 20 +#define BUS3_MUX_REG 0x1f +#define QSFP_PRESENCE_1 0x12 +#define QSFP_PRESENCE_2 0x13 +#define QSFP_PRESENCE_3 0x14 +#define QSFP_PRESENCE_4 0x15 +#define SFP_PRESENCE_5 0x02 +#define QSFP_LPMODE_1 0x0E +#define QSFP_LPMODE_2 0x0F +#define QSFP_LPMODE_3 0x10 +#define QSFP_LPMODE_4 0x11 +#define QSFP_RESET_1 0x16 +#define QSFP_RESET_2 0x17 +#define QSFP_RESET_3 0x18 +#define QSFP_RESET_4 0x19 + + +struct mutex dni_lock; +void device_release(struct device *dev) +{ + return; +} + +unsigned char dni_log2 (unsigned char num){ + unsigned char num_log2 = 0; + while(num > 0){ + num = num >> 1; + num_log2 += 1; + } + return num_log2 -1; +} + +unsigned char reverse_8bits(unsigned char c) +{ + unsigned char s = 0; + int i; + for (i = 0; i < 8; ++i) { + s <<= 1; + s |= c & 1; + c >>= 1; + } + return s; +} + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, + BUS9, + BUS10, + BUS11, + BUS12, + BUS13, + BUS14, +}; + +#define ag9032v2a_i2c_device_num(NUM){ \ + .name = "delta-ag9032v2a-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &ag9032v2a_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +struct cpld_attribute_data { + uint8_t bus; + uint8_t addr; + uint8_t reg; + uint8_t mask; + char note[200]; +}; + +enum cpld_type { + system_cpld, +}; + +enum swpld1_type { + swpld1, +}; + +enum swpld2_type { + swpld2, +}; + +enum swpld3_type { + swpld3, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +enum cpld_attributes { + CPLD_REG_ADDR, + CPLD_REG_VALUE, + SWPLD1_REG_ADDR, + SWPLD1_REG_VALUE, + SWPLD2_REG_ADDR, + SWPLD2_REG_VALUE, + SWPLD3_REG_ADDR, + SWPLD3_REG_VALUE, +}; + +enum ag9032v2a_sfp_sysfs_attributes +{ + SFP_IS_PRESENT, + QSFP_LPMODE, + QSFP_RESET, +}; + +static struct cpld_attribute_data attribute_data[] = { + [CPLD_REG_ADDR] = { + }, + [CPLD_REG_VALUE] = { + }, + [SWPLD1_REG_ADDR] = { + }, + [SWPLD1_REG_VALUE] = { + }, + [SWPLD2_REG_ADDR] = { + }, + [SWPLD2_REG_VALUE] = { + }, + [SWPLD3_REG_ADDR] = { + }, +}; +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; + +struct i2c_client * i2c_client_9548; + +static struct cpld_platform_data ag9032v2a_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = CPUPLD_ADDR, + }, +}; + +static struct cpld_platform_data ag9032v2a_swpld1_platform_data[] = { + [swpld1] = { + .reg_addr = SWPLD1_ADDR, + }, +}; + +static struct cpld_platform_data ag9032v2a_swpld2_platform_data[] = { + [swpld2] = { + .reg_addr = SWPLD2_ADDR, + }, +}; + +static struct cpld_platform_data ag9032v2a_swpld3_platform_data[] = { + [swpld3] = { + .reg_addr = SWPLD3_ADDR, + }, +}; + +// pca9548 - add 8 bus +static struct pca954x_platform_mode pca954x_mode[] = +{ + { + .adap_id = 10, + .deselect_on_exit = 1, + }, + { + .adap_id = 11, + .deselect_on_exit = 1, + }, + { + .adap_id = 12, + .deselect_on_exit = 1, + }, + { + .adap_id = 13, + .deselect_on_exit = 1, + }, + { + .adap_id = 14, + .deselect_on_exit = 1, + }, + { + .adap_id = 15, + .deselect_on_exit = 1, + }, + { + .adap_id = 16, + .deselect_on_exit = 1, + }, + { + .adap_id = 17, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = +{ + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct i2c_board_info __initdata i2c_info_pca9548[] = +{ + { + I2C_BOARD_INFO("pca9548", 0x71), + .platform_data = &pca954x_data, + }, +}; + +/*---------------- I2C device - start ------------- */ +static struct i2c_device_platform_data ag9032v2a_i2c_device_platform_data[] = { + { + // id eeprom + .parent = 1, + .info = { I2C_BOARD_INFO("24c02", 0x53) }, + .client = NULL, + }, + { + // qsfp 1 (0x50) + .parent = 20, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 2 (0x50) + .parent = 21, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 3 (0x50) + .parent = 22, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 4 (0x50) + .parent = 23, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 5 (0x50) + .parent = 24, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 6 (0x50) + .parent = 25, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 7 (0x50) + .parent = 26, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 8 (0x50) + .parent = 27, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 9 (0x50) + .parent = 28, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 10 (0x50) + .parent = 29, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 11 (0x50) + .parent = 30, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 12 (0x50) + .parent = 31, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 13 (0x50) + .parent = 32, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 14 (0x50) + .parent = 33, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 15 (0x50) + .parent = 34, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 16 (0x50) + .parent = 35, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 17 (0x50) + .parent = 36, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 18 (0x50) + .parent = 37, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 19 (0x50) + .parent = 38, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 20 (0x50) + .parent = 39, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 21 (0x50) + .parent = 40, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 22 (0x50) + .parent = 41, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 23 (0x50) + .parent = 42, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 24 (0x50) + .parent = 43, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 25 (0x50) + .parent = 44, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 26 (0x50) + .parent = 45, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 27 (0x50) + .parent = 46, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 28 (0x50) + .parent = 47, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 29 (0x50) + .parent = 48, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 30 (0x50) + .parent = 49, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 31 (0x50) + .parent = 50, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 32 (0x50) + .parent = 51, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // sfp 1 (0x50) + .parent = 52, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, +}; + +static struct platform_device ag9032v2a_i2c_device[] = { + ag9032v2a_i2c_device_num(0), + ag9032v2a_i2c_device_num(1), + ag9032v2a_i2c_device_num(2), + ag9032v2a_i2c_device_num(3), + ag9032v2a_i2c_device_num(4), + ag9032v2a_i2c_device_num(5), + ag9032v2a_i2c_device_num(6), + ag9032v2a_i2c_device_num(7), + ag9032v2a_i2c_device_num(8), + ag9032v2a_i2c_device_num(9), + ag9032v2a_i2c_device_num(10), + ag9032v2a_i2c_device_num(11), + ag9032v2a_i2c_device_num(12), + ag9032v2a_i2c_device_num(13), + ag9032v2a_i2c_device_num(14), + ag9032v2a_i2c_device_num(15), + ag9032v2a_i2c_device_num(16), + ag9032v2a_i2c_device_num(17), + ag9032v2a_i2c_device_num(18), + ag9032v2a_i2c_device_num(19), + ag9032v2a_i2c_device_num(20), + ag9032v2a_i2c_device_num(21), + ag9032v2a_i2c_device_num(22), + ag9032v2a_i2c_device_num(23), + ag9032v2a_i2c_device_num(24), + ag9032v2a_i2c_device_num(25), + ag9032v2a_i2c_device_num(26), + ag9032v2a_i2c_device_num(27), + ag9032v2a_i2c_device_num(28), + ag9032v2a_i2c_device_num(29), + ag9032v2a_i2c_device_num(30), + ag9032v2a_i2c_device_num(31), + ag9032v2a_i2c_device_num(32), + ag9032v2a_i2c_device_num(33), +}; + +/*---------------- I2C device - end ------------- */ + +/*---------------- I2C driver - start ------------- */ + +static int __init i2c_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- SFP attribute read/write - start -------- */ +static struct kobject *kobj_swpld1; +static struct kobject *kobj_swpld2; +static struct kobject *kobj_swpld3; + +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf){ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev_1 = kobj_to_dev(kobj_swpld1); + struct device *i2cdev_2 = kobj_to_dev(kobj_swpld2); + struct cpld_platform_data *pdata1 = i2cdev_1->platform_data; + struct cpld_platform_data *pdata2 = i2cdev_2->platform_data; + int ret; + int ret_sfp; + u64 data = 0; + + mutex_lock(&dni_lock); + switch (attr->index) { + case SFP_IS_PRESENT: + /*QSFP25~32*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_PRESENCE_4); + data = (u32)ret & 0xff; + /*QSFP17~24*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_PRESENCE_3); + data |= ((u32)ret & 0xff) << 8; + /*QSFP9~16*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_PRESENCE_2); + data |= (u32)(ret & 0xff) << 16; + /*QSFP1~8*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_PRESENCE_1); + data |= (u32)(ret & 0xff) << 24; + + ret = i2c_smbus_read_byte_data(pdata2[swpld2].client, SFP_PRESENCE_5); + ret_sfp = (ret & (0x80)); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%x%02x\n", data, ret_sfp); + + case QSFP_LPMODE: + /*QSFP25~32*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_LPMODE_4); + data = (u32)(ret & 0xff); + /*QSFP17~24*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_LPMODE_3); + data |= (u32)(ret & 0xff) << 8; + /*QSFP9~16*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_LPMODE_2); + data |= (u32)(ret & 0xff) << 16; + /*QSFP1~8*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_LPMODE_1); + data |= (u32)(ret & 0xff) << 24; + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%x\n", data); + + case QSFP_RESET: + /*QSFP25~32*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_RESET_4); + data = (u32)(ret & 0xff); + /*QSFP17~24*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_RESET_3); + data |= (u32)(ret & 0xff) << 8; + /*QSFP9~16*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_RESET_2); + data |= (u32)(ret & 0xff) << 16; + /*QSFP1~8*/ + ret = i2c_smbus_read_byte_data(pdata1[swpld1].client, QSFP_RESET_1); + data |= (u32)(ret & 0xff) << 24; + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%x\n", data); + + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } +} + +static ssize_t set_lpmode_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev = kobj_to_dev(kobj_swpld1); + struct cpld_platform_data *pdata = i2cdev->platform_data; + unsigned long long set_data; + int err; + int status = 0; + unsigned char set_bytes; + + + err = kstrtoull(buf, 16, &set_data); + if (err){ + return err; + } + mutex_lock(&dni_lock); + /*QSFP25~32*/ + set_bytes = set_data & 0xff; + status = i2c_smbus_write_byte_data(pdata[swpld1].client, QSFP_LPMODE_4, set_bytes); + if(status < 0) + { + goto ERROR; + } + + /*QSFP17~24*/ + set_bytes = (set_data >> 8 ) & 0xff; + status = i2c_smbus_write_byte_data(pdata[swpld1].client, QSFP_LPMODE_3, set_bytes); + if(status < 0) + { + goto ERROR; + } + + /*QSFP9~16*/ + set_bytes = (set_data >> 16 ) & 0xff; + status = i2c_smbus_write_byte_data(pdata[swpld1].client, QSFP_LPMODE_2, set_bytes); + if(status < 0) + { + goto ERROR; + } + + /*QSFP1~8*/ + set_bytes = (set_data >> 24 ) & 0xff; + status = i2c_smbus_write_byte_data(pdata[swpld1].client, QSFP_LPMODE_1, set_bytes); + if(status < 0) + { + goto ERROR; + } + + mutex_unlock(&dni_lock); + return count; + +ERROR: + mutex_unlock(&dni_lock); + return status; + +} + +static ssize_t set_reset_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev = kobj_to_dev(kobj_swpld1); + struct cpld_platform_data *pdata = i2cdev->platform_data; + unsigned long long set_data; + int err; + int status = 0; + unsigned char set_bytes; + + err = kstrtoull(buf, 16, &set_data); + if (err){ + return err; + } + + mutex_lock(&dni_lock); + /*QSFP25~32*/ + set_bytes = set_data & 0xff; + status = i2c_smbus_write_byte_data(pdata[swpld1].client, QSFP_RESET_4, set_bytes); + if(status < 0) + { + goto ERROR; + } + + /*QSFP17~24*/ + set_bytes = (set_data >> 8 ) & 0xff; + status = i2c_smbus_write_byte_data(pdata[swpld1].client, QSFP_RESET_3, set_bytes); + if(status < 0) + { + goto ERROR; + } + + /*QSFP9~16*/ + set_bytes = (set_data >> 16 ) & 0xff; + status = i2c_smbus_write_byte_data(pdata[swpld1].client, QSFP_RESET_2, set_bytes); + if(status < 0) + { + goto ERROR; + } + + /*QSFP1~8*/ + set_bytes = (set_data >> 24 ) & 0xff; + status = i2c_smbus_write_byte_data(pdata[swpld1].client, QSFP_RESET_1, set_bytes); + if(status < 0) + { + goto ERROR; + } + + mutex_unlock(&dni_lock); + return count; +ERROR: + mutex_unlock(&dni_lock); + return status; +} + + +/*---------------- SFP attribute read/write - end -------- */ + +/*---------------- CPLD - start ------------- */ +unsigned char cpupld_reg_addr; +unsigned char swpld1_reg_addr; +unsigned char swpld2_reg_addr; +unsigned char swpld3_reg_addr; +/* CPLD -- device */ +static struct platform_device cpld_device = { + .name = "delta-ag9032v2a-cpld", + .id = 0, + .dev = { + .platform_data = ag9032v2a_cpld_platform_data, + .release = device_release + }, + +}; + +static struct platform_device swpld1_device = { + .name = "delta-ag9032v2a-swpld1", + .id = 0, + .dev = { + .platform_data = ag9032v2a_swpld1_platform_data, + .release = device_release + }, +}; + +static struct platform_device swpld2_device = { + .name = "delta-ag9032v2a-swpld2", + .id = 0, + .dev = { + .platform_data = ag9032v2a_swpld2_platform_data, + .release = device_release + }, +}; + +static struct platform_device swpld3_device = { + .name = "delta-ag9032v2a-swpld3", + .id = 0, + .dev = { + .platform_data = ag9032v2a_swpld3_platform_data, + .release = device_release + }, +}; + +static ssize_t get_cpld_reg(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + int mask; + int value; + char note[200]; + unsigned char reg; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cpld_platform_data *pdata = dev->platform_data; + + mutex_lock(&dni_lock); + switch (attr->index) { + case CPLD_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", cpupld_reg_addr); + case SWPLD1_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld1_reg_addr); + case SWPLD2_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld2_reg_addr); + case SWPLD3_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld3_reg_addr); + case SWPLD1_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld1].client, swpld1_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case SWPLD2_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld2].client, swpld2_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case SWPLD3_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld3].client, swpld3_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) + { + case 0xff: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x%s", value, note); + case 0x0f: + case 0x03: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%01x%s", value, note); + case 0x0c: + mutex_unlock(&dni_lock); + value = value >> 2; + return sprintf(buf, "0x%01x%s", value, note); + case 0xf0: + mutex_unlock(&dni_lock); + value = value >> 4; + return sprintf(buf, "0x%01x%s", value, note); + case 0xe0: + mutex_unlock(&dni_lock); + value = value >> 5; + return sprintf(buf, "0x%01x%s", value, note); + default : + value = value >> dni_log2(mask); + mutex_unlock(&dni_lock); + return sprintf(buf, "%d%s", value, note); + } +} + +static ssize_t set_cpld_reg(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + int err; + int value; + int set_data; + unsigned long set_data_ul; + unsigned char reg; + unsigned char mask; + unsigned char mask_out; + + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 0, &set_data_ul); + if (err){ + return err; + } + + set_data = (int)set_data_ul; + if (set_data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + mutex_lock(&dni_lock); + switch (attr->index) + { + case CPLD_REG_ADDR: + cpupld_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD1_REG_ADDR: + swpld1_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD2_REG_ADDR: + swpld2_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD3_REG_ADDR: + swpld3_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case CPLD_REG_VALUE: + i2c_smbus_write_byte_data(pdata[system_cpld].client, cpupld_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD1_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld1].client, swpld1_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD2_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld2].client, swpld2_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD3_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld3].client, swpld3_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0x03: + case 0x0C: + case 0x0F: + case 0xFF: + set_data = mask_out | (set_data & mask); + break; + case 0xF0: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + case 0xE0: + set_data = set_data << 5; + set_data = mask_out | (set_data & mask); + break; + default : + set_data = mask_out | (set_data << dni_log2(mask) ); + } + + switch (attr->index) { + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "cpld not found"); + } + mutex_unlock(&dni_lock); + return count; +} + +//address and value +static SENSOR_DEVICE_ATTR(cpld_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_REG_ADDR); +static SENSOR_DEVICE_ATTR(cpld_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld1_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD1_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld1_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD1_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld2_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD2_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld2_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD2_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld3_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD3_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld3_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD3_REG_VALUE); + +//QSFP +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, for_status, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, for_status, set_lpmode_data, QSFP_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, for_status, set_reset_data, QSFP_RESET); + +static struct attribute *cpld_attrs[] = { + &sensor_dev_attr_cpld_reg_value.dev_attr.attr, + &sensor_dev_attr_cpld_reg_addr.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld1_attrs[] = { + //SWPLD1 + &sensor_dev_attr_swpld1_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld1_reg_addr.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_qsfp_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_reset.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld2_attrs[] = { + &sensor_dev_attr_swpld2_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld2_reg_addr.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld3_attrs[] = { + &sensor_dev_attr_swpld3_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld3_reg_addr.dev_attr.attr, + NULL, +}; + +static struct attribute_group cpld_attr_grp = { + .attrs = cpld_attrs, +}; + +static struct attribute_group swpld1_attr_grp = { + .attrs = swpld1_attrs, +}; + +static struct attribute_group swpld2_attr_grp = { + .attrs = swpld2_attrs, +}; + +static struct attribute_group swpld3_attr_grp = { + .attrs = swpld3_attrs, +}; + +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS0); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS0); + return -ENODEV; + } + + pdata[system_cpld].client = i2c_new_dummy(parent, pdata[system_cpld].reg_addr); + if (!pdata[system_cpld].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[system_cpld].reg_addr); + goto error; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; + +error: + i2c_unregister_device(pdata[system_cpld].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __init swpld1_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD1 platform data not found\n"); + return -ENODEV; + } + parent = i2c_get_adapter(BUS3); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS1); + return -ENODEV; + } + + pdata[swpld1].client = i2c_new_dummy(parent, pdata[swpld1].reg_addr); + if (!pdata[swpld1].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld1].reg_addr); + goto error; + } + + kobj_swpld1 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld1_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + return 0; + +error: + kobject_put(kobj_swpld1); + i2c_unregister_device(pdata[swpld1].client); + i2c_put_adapter(parent); + return -ENODEV; +} + +static int __init swpld2_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD2 platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS3); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS1); + return -ENODEV; + } + + pdata[swpld2].client = i2c_new_dummy(parent, pdata[swpld2].reg_addr); + if (!pdata[swpld2].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld2].reg_addr); + goto error; + } + + kobj_swpld2 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld2_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_swpld2); + i2c_unregister_device(pdata[swpld2].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __init swpld3_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD3 platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS3); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS1); + return -ENODEV; + } + + pdata[swpld3].client = i2c_new_dummy(parent, pdata[swpld3].reg_addr); + if (!pdata[swpld3].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld3].reg_addr); + goto error; + } + + kobj_swpld3 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld3_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_swpld3); + i2c_unregister_device(pdata[swpld3].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[system_cpld].client) { + if (!parent) { + parent = (pdata[system_cpld].client)->adapter; + } + i2c_unregister_device(pdata[system_cpld].client); + } + } + i2c_put_adapter(parent); + + return 0; +} + +static int __exit swpld1_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &swpld1_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld1].client) { + if (!parent) { + parent = (pdata[swpld1].client)->adapter; + } + i2c_unregister_device(pdata[swpld1].client); + } + } + i2c_put_adapter(parent); + return 0; +} + +static int __exit swpld2_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &swpld2_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld2].client) { + if (!parent) { + parent = (pdata[swpld2].client)->adapter; + } + i2c_unregister_device(pdata[swpld2].client); + } + } + i2c_put_adapter(parent); + return 0; +} + +static int __exit swpld3_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &swpld3_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld3].client) { + if (!parent) { + parent = (pdata[swpld3].client)->adapter; + } + i2c_unregister_device(pdata[swpld3].client); + } + } + i2c_put_adapter(parent); + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-cpld", + }, +}; + +static struct platform_driver swpld1_driver = { + .probe = swpld1_probe, + .remove = __exit_p(swpld1_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-swpld1", + }, +}; + +static struct platform_driver swpld2_driver = { + .probe = swpld2_probe, + .remove = __exit_p(swpld2_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-swpld2", + }, +}; + +static struct platform_driver swpld3_driver = { + .probe = swpld3_probe, + .remove = __exit_p(swpld3_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-swpld3", + }, +}; +/*---------------- CPLD - end ------------- */ +/*---------------- MUX - start ------------- */ + +struct cpld_mux_platform_data { + int parent; + int base_nr; + struct i2c_client *cpld; + int reg_addr; +}; + +struct cpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct cpld_mux_platform_data data; +}; + +static struct cpld_mux_platform_data ag9032v2a_cpld_mux_platform_data[] = { + { + .parent = BUS0, + .base_nr = BUS0_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS0_MUX_REG, + }, +}; + +static struct cpld_mux_platform_data ag9032v2a_swpld_mux_platform_data[] = { + { + .parent = BUS3, + .base_nr = BUS3_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS3_MUX_REG, + }, +}; + +static struct platform_device cpld_mux_device[] = +{ + { + .name = "delta-ag9032v2a-cpld-mux", + .id = 0, + .dev = { + .platform_data = &ag9032v2a_cpld_mux_platform_data[0], + .release = device_release, + }, + }, +}; + +static struct platform_device swpld1_mux_device[] = +{ + { + .name = "delta-ag9032v2a-swpld1-mux", + .id = 0, + .dev = { + .platform_data = &ag9032v2a_swpld_mux_platform_data[0], + .release = device_release, + }, + }, +}; + +static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); +} + +static int cpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct cpld_mux *mux = i2c_mux_priv(muxc); + u8 cpld_mux_val = 0; + int ret = 0; + if ( mux->data.base_nr == BUS0_BASE_NUM ){ + switch (chan) { + case 0: + cpld_mux_val = MUX_VAL_IDEEPROM; + break; + case 1: + cpld_mux_val = MUX_VAL_PCA9548; + break; + case 2: + cpld_mux_val = MUX_VAL_SWPLD; + break; + default: + cpld_mux_val = 0x0; + break; + } + } + else + { + printk(KERN_ERR "CPLD mux select error\n"); + return 0; + } + ret = cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(cpld_mux_val & 0xff)); + return ret; +} + +static int swpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct cpld_mux *mux = i2c_mux_priv(muxc); + u8 swpld_mux_val = 0; + int ret =0; + + if ( mux->data.base_nr == BUS3_BASE_NUM ){ + swpld_mux_val = chan; + } + else + { + printk(KERN_ERR "SWPLD mux select error\n"); + return 0; + } + ret = cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(swpld_mux_val & 0xff)); + return ret; +} + +static int __init cpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct cpld_mux *mux; + struct cpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + printk(KERN_ERR "Failed to allocate memory for mux\n"); + return -ENOMEM; + } + mux->data = *pdata; + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + kfree(mux); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS0: + dev_num = BUS0_DEV_NUM; + break; + default : + dev_num = DEF_DEV_NUM; + break; + } + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, cpld_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + platform_set_drvdata(pdev, muxc); + + for (i = 0; i < dev_num; i++) + { + int nr = pdata->base_nr + i; + unsigned int class = 0; + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_num, parent->name); + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + kfree(mux); + i2c_put_adapter(parent); + return ret; +} + +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct cpld_mux *mux; + struct cpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + printk(KERN_ERR "Failed to allocate memory for mux\n"); + return -ENOMEM; + } + mux->data = *pdata; + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + kfree(mux); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS3: + dev_num = BUS3_DEV_NUM; + break; + default : + dev_num = DEF_DEV_NUM; + break; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0, swpld_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + platform_set_drvdata(pdev, muxc); + for (i = 0; i < dev_num; i++) + { + int nr = pdata->base_nr + i; + unsigned int class = 0; + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_num, parent->name); + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + kfree(mux); + i2c_put_adapter(parent); + + return ret; +} + +static int __exit cpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + struct i2c_adapter *parent = muxc->parent; + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(parent); + + return 0; +} + +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + struct i2c_adapter *parent = muxc->parent; + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_mux_driver = { + .probe = cpld_mux_probe, + .remove = __exit_p(cpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-cpld-mux", + }, +}; + +static struct platform_driver swpld1_mux_driver = { + .probe = swpld_mux_probe, + .remove = __exit_p(swpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9032v2a-swpld1-mux", + }, +}; +/*---------------- MUX - end ------------- */ + +/*---------------- module initialization ------------- */ + +static int __init delta_ag9032v2a_platform_init(void) +{ +// struct i2c_client *client; + struct i2c_adapter *adapter; + struct cpld_mux_platform_data *cpld_mux_pdata; + struct cpld_platform_data *cpld_pdata; + struct cpld_mux_platform_data *swpld_mux_pdata; + struct cpld_platform_data *swpld_pdata; + int ret,i = 0; + + mutex_init(&dni_lock); + printk("ag9032v2a_platform module initialization\n"); + + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpupld driver\n"); + goto error_cpld_driver; + } + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld1_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld1_driver; + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld2_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld2_driver; + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld3_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld3_driver; + } + + // register the mux prob which call the SWPLD + ret = platform_driver_register(&cpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_cpld_mux_driver; + } + + // register the mux prob which call the SWPLD + ret = platform_driver_register(&swpld1_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld1 mux driver\n"); + goto error_swpld1_mux_driver; + } + + // register the i2c devices + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + // register the CPUPLD + ret = platform_device_register(&cpld_device); + if (ret) { + printk(KERN_WARNING "Fail to create cpupld device\n"); + goto error_cpld_device; + } + + // link the CPLD and the Mux + cpld_pdata = ag9032v2a_cpld_platform_data; + for (i = 0; i < ARRAY_SIZE(cpld_mux_device); i++) + { + cpld_mux_pdata = cpld_mux_device[i].dev.platform_data; + cpld_mux_pdata->cpld = cpld_pdata[system_cpld].client; + ret = platform_device_register(&cpld_mux_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_cpld_mux; + } + } + + adapter = i2c_get_adapter(BUS2); + i2c_client_9548 = i2c_new_device(adapter, &i2c_info_pca9548[0]); + i2c_put_adapter(adapter); + + // register the SWPLD + ret = platform_device_register(&swpld1_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld1 device\n"); + goto error_swpld1_device; + } + + // register the SWPLD + ret = platform_device_register(&swpld2_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld2 device\n"); + goto error_swpld2_device; + } + + // register the SWPLD + ret = platform_device_register(&swpld3_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld3 device\n"); + goto error_swpld3_device; + } + + // link the SWPLD1 and the Mux + swpld_pdata = ag9032v2a_swpld1_platform_data; + for (i = 0; i < ARRAY_SIZE(swpld1_mux_device); i++) + { + swpld_mux_pdata = swpld1_mux_device[i].dev.platform_data; + swpld_mux_pdata->cpld = swpld_pdata[swpld1].client; + ret = platform_device_register(&swpld1_mux_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux %d\n", i); + goto error_ag9032v2a_swpld1_mux; + } + } + + for (i = 0; i < ARRAY_SIZE(ag9032v2a_i2c_device); i++) + { + ret = platform_device_register(&ag9032v2a_i2c_device[i]); + if (ret) + { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_ag9032v2a_i2c_device; + } + } + if (ret) + goto error_cpld_mux; + return 0; + +error_ag9032v2a_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag9032v2a_i2c_device[i]); + } + i = ARRAY_SIZE(swpld1_mux_device); +error_ag9032v2a_swpld1_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&swpld1_mux_device[i]); + } + platform_device_unregister(&swpld3_device); +error_swpld3_device: + platform_device_unregister(&swpld2_device); +error_swpld2_device: + platform_device_unregister(&swpld1_device); +error_swpld1_device: + i2c_unregister_device(i2c_client_9548); + i = ARRAY_SIZE(cpld_mux_device); +error_cpld_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&cpld_mux_device[i]); + } + platform_device_unregister(&cpld_device); +error_cpld_device: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld1_mux_driver); +error_swpld1_mux_driver: + platform_driver_unregister(&cpld_mux_driver); +error_cpld_mux_driver: + platform_driver_unregister(&swpld3_driver); +error_swpld3_driver: + platform_driver_unregister(&swpld2_driver); +error_swpld2_driver: + platform_driver_unregister(&swpld1_driver); +error_swpld1_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit delta_ag9032v2a_platform_exit(void) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(ag9032v2a_i2c_device); i++) { + platform_device_unregister(&ag9032v2a_i2c_device[i]); + } + + for (i = 0; i < ARRAY_SIZE(swpld1_mux_device); i++) { + platform_device_unregister(&swpld1_mux_device[i]); + } + + platform_device_unregister(&swpld1_device); + platform_driver_unregister(&swpld1_driver); + + platform_device_unregister(&swpld2_device); + platform_driver_unregister(&swpld2_driver); + + platform_device_unregister(&swpld3_device); + platform_driver_unregister(&swpld3_driver); + + i2c_unregister_device(i2c_client_9548); + + for (i = 0; i < ARRAY_SIZE(cpld_mux_device); i++) { + platform_device_unregister(&cpld_mux_device[i]); + } + + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&swpld1_mux_driver); + platform_driver_unregister(&cpld_mux_driver); + platform_device_unregister(&cpld_device); + platform_driver_unregister(&cpld_driver); +} + +module_init(delta_ag9032v2a_platform_init); +module_exit(delta_ag9032v2a_platform_exit); + +MODULE_DESCRIPTION("DELTA ag9032v2a Platform Support"); +MODULE_AUTHOR("Johnson Lu "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/scripts/ag9032v2a_platform_init.sh b/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/scripts/ag9032v2a_platform_init.sh new file mode 100755 index 000000000000..af5d5f0c7b52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9032v2a/scripts/ag9032v2a_platform_init.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +#platform init script for Delta ag9032v2a + + +exit 0 + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/cfg/ag9064-modules.conf b/platform/broadcom/sonic-platform-modules-delta/ag9064/cfg/ag9064-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/cfg/ag9064-modules.conf @@ -0,0 +1,13 @@ +# /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-delta/ag9064/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/Makefile new file mode 100644 index 000000000000..5642e82fa058 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/Makefile @@ -0,0 +1,5 @@ +obj-m += delta_ag9064_platform.o +obj-m += delta_ag9064_cpld.o +obj-m += delta_ag9064_swpld.o +obj-m += i2c-mei.o +i2c-mei-objs := i2c-mei_io.o i2c-mei_main.o i2c-mei_rw.o \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/client.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/client.h new file mode 100644 index 000000000000..04e1aa39243f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/client.h @@ -0,0 +1,255 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, Intel Corporation. + * + * 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. + * + */ + +#ifndef _MEI_CLIENT_H_ +#define _MEI_CLIENT_H_ + +#include +#include +#include +#include + +#include "mei_dev.h" + +/* + * reference counting base function + */ +void mei_me_cl_init(struct mei_me_client *me_cl); +void mei_me_cl_put(struct mei_me_client *me_cl); +struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl); + +void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl); +void mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl); + +struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev, + const uuid_le *uuid); +struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id); +struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev, + const uuid_le *uuid, u8 client_id); +void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid); +void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, + const uuid_le *uuid, u8 id); +void mei_me_cl_rm_all(struct mei_device *dev); + +/** + * mei_me_cl_is_active - check whether me client is active in the fw + * + * @me_cl: me client + * + * Return: true if the me client is active in the firmware + */ +static inline bool mei_me_cl_is_active(const struct mei_me_client *me_cl) +{ + return !list_empty_careful(&me_cl->list); +} + +/** + * mei_me_cl_uuid - return me client protocol name (uuid) + * + * @me_cl: me client + * + * Return: me client protocol name + */ +static inline const uuid_le *mei_me_cl_uuid(const struct mei_me_client *me_cl) +{ + return &me_cl->props.protocol_name; +} + +/** + * mei_me_cl_ver - return me client protocol version + * + * @me_cl: me client + * + * Return: me client protocol version + */ +static inline u8 mei_me_cl_ver(const struct mei_me_client *me_cl) +{ + return me_cl->props.protocol_version; +} + +/* + * MEI IO Functions + */ +struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, + struct file *fp); +void mei_io_cb_free(struct mei_cl_cb *priv_cb); +int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length); + + +/** + * mei_io_list_init - Sets up a queue list. + * + * @list: An instance cl callback structure + */ +static inline void mei_io_list_init(struct mei_cl_cb *list) +{ + INIT_LIST_HEAD(&list->list); +} +void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl); + +/* + * MEI Host Client Functions + */ + +struct mei_cl *mei_cl_allocate(struct mei_device *dev); +void mei_cl_init(struct mei_cl *cl, struct mei_device *dev); + + +int mei_cl_link(struct mei_cl *cl, int id); +int mei_cl_unlink(struct mei_cl *cl); + +struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id); + +struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, + const struct file *fp); +void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp); +struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, + enum mei_cb_file_ops type, struct file *fp); +int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp); + +int mei_cl_flow_ctrl_creds(struct mei_cl *cl); + +int mei_cl_flow_ctrl_reduce(struct mei_cl *cl); +/* + * MEI input output function prototype + */ + +/** + * mei_cl_is_connected - host client is connected + * + * @cl: host client + * + * Return: true if the host client is connected + */ +static inline bool mei_cl_is_connected(struct mei_cl *cl) +{ + return cl->state == MEI_FILE_CONNECTED; +} + +/** + * mei_cl_me_id - me client id + * + * @cl: host client + * + * Return: me client id or 0 if client is not connected + */ +static inline u8 mei_cl_me_id(const struct mei_cl *cl) +{ + return cl->me_cl ? cl->me_cl->client_id : 0; +} + +/** + * mei_cl_mtu - maximal message that client can send and receive + * + * @cl: host client + * + * Return: mtu + */ +static inline size_t mei_cl_mtu(const struct mei_cl *cl) +{ + return cl->me_cl->props.max_msg_length; +} + +/** + * mei_cl_is_fixed_address - check whether the me client uses fixed address + * + * @cl: host client + * + * Return: true if the client is connected and it has fixed me address + */ +static inline bool mei_cl_is_fixed_address(const struct mei_cl *cl) +{ + return cl->me_cl && cl->me_cl->props.fixed_address; +} + +/** + * mei_cl_is_single_recv_buf- check whether the me client + * uses single receiving buffer + * + * @cl: host client + * + * Return: true if single_recv_buf == 1; 0 otherwise + */ +static inline bool mei_cl_is_single_recv_buf(const struct mei_cl *cl) +{ + return cl->me_cl->props.single_recv_buf; +} + +/** + * mei_cl_uuid - client's uuid + * + * @cl: host client + * + * Return: return uuid of connected me client + */ +static inline const uuid_le *mei_cl_uuid(const struct mei_cl *cl) +{ + return mei_me_cl_uuid(cl->me_cl); +} + +/** + * mei_cl_host_addr - client's host address + * + * @cl: host client + * + * Return: 0 for fixed address client, host address for dynamic client + */ +static inline u8 mei_cl_host_addr(const struct mei_cl *cl) +{ + return mei_cl_is_fixed_address(cl) ? 0 : cl->host_client_id; +} + +int mei_cl_disconnect(struct mei_cl *cl); +void mei_cl_set_disconnected(struct mei_cl *cl); +int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb, + struct mei_cl_cb *cmpl_list); +int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl, + struct file *file); +int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, + struct mei_cl_cb *cmpl_list); +int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp); +int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr, + struct mei_cl_cb *cmpl_list); +int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking); +int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, + struct mei_cl_cb *cmpl_list); + +void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb); + +void mei_host_client_init(struct work_struct *work); + +u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop); +enum mei_cb_file_ops mei_cl_notify_req2fop(u8 request); +int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request); +int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb, + struct mei_cl_cb *cmpl_list); +int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev); +void mei_cl_notify(struct mei_cl *cl); + +void mei_cl_all_disconnect(struct mei_device *dev); +void mei_cl_all_wakeup(struct mei_device *dev); +void mei_cl_all_write_clear(struct mei_device *dev); + +#define MEI_CL_FMT "cl:host=%02d me=%02d " +#define MEI_CL_PRM(cl) (cl)->host_client_id, mei_cl_me_id(cl) + +#define cl_dbg(dev, cl, format, arg...) \ + dev_dbg((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg) + +#define cl_err(dev, cl, format, arg...) \ + dev_err((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg) + +#endif /* _MEI_CLIENT_H_ */ diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_common.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_common.h new file mode 100644 index 000000000000..40eba7e241a3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_common.h @@ -0,0 +1,568 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IPMI_MAX_INTF (4) +#define DELTA_NETFN 0x38 +#define BMC_BUS_5 0x04 +#define BMC_BUS_1 0x00 +#define CMD_SETDATA 0x03 +#define CMD_GETDATA 0x02 +#define CMD_DEVICE_SCAN 0x01 + +#define CPUPLD_ADDR 0x31 +#define SWPLD1_ADDR 0x35 +#define SWPLD2_ADDR 0x34 +#define SWPLD3_ADDR 0x33 +#define SWPLD4_ADDR 0x32 +#define QSFP_PORT_MUX_REG 0x13 +#define PSU1_EEPROM_ADDR 0x50 +#define PSU2_EEPROM_ADDR 0x51 + +#define DEFAULT_NUM 1 +#define BUS9_DEV_NUM 64 +#define BUS9_BASE_NUM 20 +#define EEPROM_SIZE 640 +#define EEPROM_ARCH_SIZE 256 +#define EEPROM_MASK 20 +#define ATTR_R 1 +#define ATTR_W 2 + +extern int dni_bmc_cmd(char set_cmd, char *cmd_data, int cmd_data_len); +extern int dni_create_user(void); +extern unsigned char dni_log2 (unsigned char num); +extern void device_release(struct device *dev); +extern void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data); +extern void dummy_smi_free(struct ipmi_smi_msg *msg); +extern void dummy_recv_free(struct ipmi_recv_msg *msg); +extern void dni_klock(void); +extern void dni_kunlock(void); + +static ipmi_user_t ipmi_mh_user = NULL; +static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,}; +static atomic_t dummy_count = ATOMIC_INIT(0); + +static struct ipmi_smi_msg halt_smi_msg = { + .done = dummy_smi_free +}; +static struct ipmi_recv_msg halt_recv_msg = { + .done = dummy_recv_free +}; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, + BUS9, + BUS10, + BUS11, + BUS12, + BUS13, + BUS14, +}; + +static struct cpld_attribute_data { + uint8_t bus; + uint8_t addr; + uint8_t reg; + uint8_t mask; + char note[200]; +}; + + +enum cpld_type { + system_cpld, + swpld1, + swpld2, + swpld3, + swpld4, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data ag9064_cpld_platform_data[] = { + [system_cpld] = { + .reg_addr = CPUPLD_ADDR, + }, +}; + +static struct cpld_platform_data ag9064_swpld1_platform_data[] = { + [swpld1] = { + .reg_addr = SWPLD1_ADDR, + }, +}; + +static struct cpld_platform_data ag9064_swpld2_platform_data[] = { + [swpld2] = { + .reg_addr = SWPLD2_ADDR, + }, +}; + +static struct cpld_platform_data ag9064_swpld3_platform_data[] = { + [swpld3] = { + .reg_addr = SWPLD3_ADDR, + }, +}; + +static struct cpld_platform_data ag9064_swpld4_platform_data[] = { + [swpld4] = { + .reg_addr = SWPLD4_ADDR, + }, +}; + +enum cpld_attributes { + CPLD_REG_ADDR, + CPLD_REG_VALUE, + SWPLD1_REG_ADDR, + SWPLD1_REG_VALUE, + SWPLD2_REG_ADDR, + SWPLD2_REG_VALUE, + SWPLD3_REG_ADDR, + SWPLD3_REG_VALUE, + SWPLD4_REG_ADDR, + SWPLD4_REG_VALUE, + PSU1_SCAN, + PSU2_SCAN, + //CPLD + CPLD_VER, + CPU_BOARD_VER, + CPU_ID, + MB_ID, + MB_VER, + CPU0_PWR_OK, + PWR_RAIL_OVER_TEMP, + CPU_DISOMIC_OVER_TEMP, + DDR_OVER_TEMP, + CPLD_PWR_ON_RST, + CPLD_HARD_RST, + CPLD_RST, + MB_RST, + PSU_FAN_INT, + OP_MODULE_INT, +//SWPLD1 + SWPLD1_MAJOR_VER, + SWPLD1_MINOR_VER, + SWPLD1_SCRTCH_REG, + PSU1_PWR_OK, + PSU1_INT, + PSU2_PWR_OK, + PSU2_INT, + PSU1_GREEN_LED, + PSU1_RED_LED, + PSU2_GREEN_LED, + PSU2_RED_LED, + PSU_LED_MODE, +//SWPLD2 + SWPLD2_MAJOR_VER, + SWPLD2_MINOR_VER, + SWPLD2_SCRTCH_REG, + FAN_LED, + SYS_LED, + FAN_MOD1_LED, + FAN_MOD2_LED, + FAN_MOD3_LED, + FAN_MOD4_LED, +//SWPLD3 + SWPLD3_MAJOR_VER, + SWPLD3_MINOR_VER, + SWPLD3_SCRTCH_REG, + SB_VER, + PLATFORM_TYPE, +//SWPLD4 + SW_BOARD_ID1, + SW_BOARD_ID2, + SWBD_VER, + SWPLD4_VER, + PSU_FAN_EVENT, + CPU_THERMAL_INT, + FAN_INT, + CPLD_SPI_WP, + RJ45_CONSOLE_SEL, + SYSTEM_INT, + CPLD_MB_RST_DONE, + MB_PWR_OK, + FAN_EEPROM_WP, +}; + +enum sfp_attributes{ + EEPROM_SFP_1, + EEPROM_SFP_2, + EEPROM_SFP_3, + EEPROM_SFP_4, + EEPROM_SFP_5, + EEPROM_SFP_6, + EEPROM_SFP_7, + EEPROM_SFP_8, + EEPROM_SFP_9, + EEPROM_SFP_10, + EEPROM_SFP_11, + EEPROM_SFP_12, + EEPROM_SFP_13, + EEPROM_SFP_14, + EEPROM_SFP_15, + EEPROM_SFP_16, + EEPROM_SFP_17, + EEPROM_SFP_18, + EEPROM_SFP_19, + EEPROM_SFP_20, + EEPROM_SFP_21, + EEPROM_SFP_22, + EEPROM_SFP_23, + EEPROM_SFP_24, + EEPROM_SFP_25, + EEPROM_SFP_26, + EEPROM_SFP_27, + EEPROM_SFP_28, + EEPROM_SFP_29, + EEPROM_SFP_30, + EEPROM_SFP_31, + EEPROM_SFP_32, + EEPROM_SFP_33, + EEPROM_SFP_34, + EEPROM_SFP_35, + EEPROM_SFP_36, + EEPROM_SFP_37, + EEPROM_SFP_38, + EEPROM_SFP_39, + EEPROM_SFP_40, + EEPROM_SFP_41, + EEPROM_SFP_42, + EEPROM_SFP_43, + EEPROM_SFP_44, + EEPROM_SFP_45, + EEPROM_SFP_46, + EEPROM_SFP_47, + EEPROM_SFP_48, + EEPROM_SFP_49, + EEPROM_SFP_50, + EEPROM_SFP_51, + EEPROM_SFP_52, + EEPROM_SFP_53, + EEPROM_SFP_54, + EEPROM_SFP_55, + EEPROM_SFP_56, + EEPROM_SFP_57, + EEPROM_SFP_58, + EEPROM_SFP_59, + EEPROM_SFP_60, + EEPROM_SFP_61, + EEPROM_SFP_62, + EEPROM_SFP_63, + EEPROM_SFP_64, +}; + +static struct cpld_attribute_data attribute_data[] = { + [CPLD_REG_ADDR] = { + }, + [CPLD_REG_VALUE] = { + }, + [SWPLD1_REG_ADDR] = { + }, + [SWPLD1_REG_VALUE] = { + }, + [SWPLD2_REG_ADDR] = { + }, + [SWPLD2_REG_VALUE] = { + }, + [SWPLD3_REG_ADDR] = { + }, + [SWPLD3_REG_VALUE] = { + }, + [SWPLD4_REG_ADDR] = { + }, + [SWPLD4_REG_VALUE] = { + }, +//CPLD + [CPLD_VER] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x01, .mask = 0xFF, + .note = "CPLD Version, controlled by CPLD editor" + }, + [CPU_BOARD_VER] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x02, .mask = 0xF0, + .note = "“0x0”: proto A1\n“0x1”: proto A2\n“0x2”: PR (Production)" + }, + [CPU_ID] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x02, .mask = 0x0F, + .note = "“0x0”: C2558 ECC\n“0x1”: Rangeley ECC\n“0x2”: BROADWELL-DE ECC" + }, + [MB_ID] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x03, .mask = 0xFF, + .note = "“0x00”: proto A1\n“0x01”: proto A2\n“0x02”: PR (Production)" + }, + [MB_VER] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x04, .mask = 0x0F, + .note = "“0x0”: proto-A\n“0x1”: proto-B" + }, + [CPU0_PWR_OK] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x08, .mask = 1 << 3, + .note = "“1” =Power rail is good\n“0” = Power rail is failed" + }, + [PWR_RAIL_OVER_TEMP] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 3, + .note = "“1” = Not over temperature\n“0” = Over temperature" + }, + [CPU_DISOMIC_OVER_TEMP] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 1, + .note = "“1” = Not over temperature\n“0” = Over temperature" + }, + [DDR_OVER_TEMP] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x0b, .mask = 1 << 0, + .note = "“1” = Not over temperature\n“0” = Over temperature" + }, + [CPLD_PWR_ON_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x11, .mask = 1 << 4, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [CPLD_HARD_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x11, .mask = 1 << 2, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [CPLD_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x11, .mask = 1 << 0, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [MB_RST] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x12, .mask = 1 << 0, + .note = "“0” = Reset\n“1” = Normal operation" + }, + [PSU_FAN_INT] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x15, .mask = 1 << 1, + .note = "“0” = Interrupt occurs\n“1” = Interrupt doesn't occur" + }, + [OP_MODULE_INT] = { + .bus = BUS0, .addr = CPUPLD_ADDR, + .reg = 0x15, .mask = 1 << 0, + .note = "“0” = Interrupt occurs\n“1” = Interrupt doesn't occur" + }, +//SWPLD1 + [SWPLD1_MAJOR_VER] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x00, .mask = 0xF0, + .note = "CPLD Major Version, controlled by CPLD editor." + }, + [SWPLD1_MINOR_VER] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x00, .mask = 0x0F, + .note = "CPLD Minor Version, controlled by CPLD editor." + }, + [SWPLD1_SCRTCH_REG] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x01, .mask = 0xFF, + .note = "CPLD read/write test register, to provide a way to test CPLD access." + }, + [PSU1_PWR_OK] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 1 << 6, + .note = "‘0’ = Power rail is good\n‘1’ = Power rail is failed" + }, + [PSU1_INT] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 1 << 5, + .note = "‘0’ = Interrupt doesn’t occur\n‘1’ = Interrupt occurs" + }, + [PSU2_PWR_OK] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 1 << 2, + .note = "‘0’ = Power rail is good\n‘1’ = Power rail is failed" + }, + [PSU2_INT] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x02, .mask = 1 << 1, + .note = "‘0’ = Interrupt doesn’t occur\n‘1’ = Interrupt occurs" + }, + [PSU1_GREEN_LED] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x13, .mask = 1 << 7, + .note = "“0”: Solid Green – Power Supply 1 is supplied to the switch & operating normally\n“1”: OFF" + }, + [PSU1_RED_LED] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x13, .mask = 1 << 6, + .note = "“0”: Solid Red – Power Supply 1 is supplied to the switch & operating normally\n“1”: OFF" + }, + [PSU2_GREEN_LED] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x13, .mask = 1 << 5, + .note = "“0”: Solid Green – Power Supply 2 is supplied to the switch & operating normally\n“1”: OFF" + }, + [PSU2_RED_LED] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x13, .mask = 1 << 4, + .note = "“0”: Solid Red – Power Supply 1=2 is supplied to the switch & operating normally\n“1”: OFF" + }, + [PSU_LED_MODE] = { + .bus = BUS0, .addr = SWPLD1_ADDR, + .reg = 0x13, .mask = 1 << 0, + .note = "“0”: PSU LED can be changed manually\n“1”: PSU LED can’t be changed manually" + }, +//SWPLD2 + [SWPLD2_MAJOR_VER] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x00, .mask =0xF0 , + .note = "CPLD Major Version, controlled by CPLD editor." + }, + [SWPLD2_MINOR_VER] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x00, .mask = 0x0F, + .note = "CPLD Minor Version, controlled by CPLD editor." + }, + [SWPLD2_SCRTCH_REG] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x01, .mask = 0xFF, + .note = "CPLD read/write test register, to provide a way to test CPLD access." + }, + [FAN_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x02, .mask = 0xC0, + .note = "“00’/”11”: OFF\n“01”: Solid Green – FANs are operating normally\n“10”: Solid Amber – FANs are Error" + }, + [SYS_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x02, .mask = 0x30, + .note = "‘00’: Off\n‘01’: Solid Green – Normal operation\n‘10’: Blinking Green – Booting Progress\n‘11’: Solid Red – System Fail" + }, + [FAN_MOD1_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x1b, .mask = 1 << 7, + .note = "‘0’ = Amber\n‘1’ = Green" + }, + [FAN_MOD2_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x1b, .mask = 1 << 6, + .note = "‘0’ = Amber\n‘1’ = Green" + }, + [FAN_MOD3_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x1b, .mask = 1 << 5, + .note = "‘0’ = Amber\n‘1’ = Green" + }, + [FAN_MOD4_LED] = { + .bus = BUS0, .addr = SWPLD2_ADDR, + .reg = 0x1b, .mask = 1 << 4, + .note = "‘0’ = Amber\n‘1’ = Green" + }, +//SWPLD3 + [SWPLD3_MAJOR_VER] = { + .bus = BUS0, .addr = SWPLD3_ADDR, + .reg = 0x00, .mask = 0xF0, + .note = "CPLD Major Version, controlled by CPLD editor." + }, + [SWPLD3_MINOR_VER] = { + .bus = BUS0, .addr = SWPLD3_ADDR, + .reg = 0x00, .mask = 0x0F, + .note = "CPLD Minor Version, controlled by CPLD editor." + }, + [SWPLD3_SCRTCH_REG] = { + .bus = BUS0, .addr = SWPLD3_ADDR, + .reg = 0x01, .mask = 0xFF, + .note = "CPLD read/write test register, to provide a way to test CPLD access." + }, + [SB_VER] = { + .bus = BUS0, .addr = SWPLD3_ADDR, + .reg = 0x02, .mask = 0xF0, + .note = "“0x0”: proto-A\n“0x1”: proto-B" + }, + [PLATFORM_TYPE] = { + .bus = BUS0, .addr = SWPLD3_ADDR, + .reg = 0x02, .mask = 0x0F, + .note = "“0x0”: 64X100G_2U\n“0x1”~”0xF” Reserved" + }, +//SWPLD4 + [SW_BOARD_ID1] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x00, .mask = 0xFF, + .note = "0x00" + }, + [SW_BOARD_ID2] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x01, .mask = 0xFF, + .note = "Configured by PLD Editor\n0x03: AG9064" + }, + [SWBD_VER] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x02, .mask = 0xFF, + .note = "Configured by external resistor\n0x01:EVT1\n0x02:EVT2\n0x03:EVT3\n0x04:EVT4\n0x10:DVT\n0x20:PVT" + }, + [SWPLD4_VER] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x03, .mask = 0xFF, + .note = "-" + }, + [PSU_FAN_EVENT] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x04, .mask = 1 << 4, + .note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [CPU_THERMAL_INT] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x04, .mask = 1 << 1, + .note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [FAN_INT] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x04, .mask = 1 << 0, + .note = "‘0’ = Interrupt occurs\n‘1’ = Interrupt doesn’t occur" + }, + [CPLD_SPI_WP] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x06, .mask = 1 << 3, + .note = "“0” = SPI write operation is disabled\n“1” = SPI write operation is enabled" + }, + [RJ45_CONSOLE_SEL] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x06, .mask = 1 << 2, + .note = "“0” = Use BCM UART\n“1” = Use CPU UART" + }, + [SYSTEM_INT] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x07, .mask = 1 << 2, + .note = "“0” = Interrupt is asserted\n“1” = Interrupt is deasserted" + }, + [CPLD_MB_RST_DONE] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x07, .mask = 1 << 1, + .note = "“0” = Is done\n“1” = Is not done" + }, + [MB_PWR_OK] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x07, .mask = 1 << 0, + .note = "‘0’ = Power is failed\n‘1’ = Power is good" + }, + [FAN_EEPROM_WP] = { + .bus = BUS0, .addr = SWPLD4_ADDR, + .reg = 0x15, .mask = 1 << 2, + .note = "“1” = enables the lock-down mechanism.\n“0” = overrides the lock-down function enabling blocks to be erased or programmed using software commands." + }, +}; diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_cpld.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_cpld.c new file mode 100644 index 000000000000..a1c275209b05 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_cpld.c @@ -0,0 +1,928 @@ +#include "delta_ag9064_common.h" + +#define QSFP_PRESENCE_1 0x03 +#define QSFP_PRESENCE_2 0x03 +#define QSFP_PRESENCE_3 0x24 +#define QSFP_PRESENCE_4 0x24 +#define QSFP_PRESENCE_5 0x04 +#define QSFP_PRESENCE_6 0x04 +#define QSFP_PRESENCE_7 0x25 +#define QSFP_PRESENCE_8 0x25 + +#define QSFP_LP_MODE_1 0x0c +#define QSFP_LP_MODE_2 0x0c +#define QSFP_LP_MODE_3 0x2a +#define QSFP_LP_MODE_4 0x2a +#define QSFP_LP_MODE_5 0x0d +#define QSFP_LP_MODE_6 0x0d +#define QSFP_LP_MODE_7 0x2b +#define QSFP_LP_MODE_8 0x2b + +#define QSFP_RESET_1 0x06 +#define QSFP_RESET_2 0x06 +#define QSFP_RESET_3 0x26 +#define QSFP_RESET_4 0x26 +#define QSFP_RESET_5 0x07 +#define QSFP_RESET_6 0x07 +#define QSFP_RESET_7 0x27 +#define QSFP_RESET_8 0x27 + +#define QSFP_RESPONSE_1 0x09 +#define QSFP_RESPONSE_2 0x09 +#define QSFP_RESPONSE_3 0x28 +#define QSFP_RESPONSE_4 0x28 +#define QSFP_RESPONSE_5 0x0a +#define QSFP_RESPONSE_6 0x0a +#define QSFP_RESPONSE_7 0x29 +#define QSFP_RESPONSE_8 0x29 + +#define QSFP_INTERRUPT_1 0x0f +#define QSFP_INTERRUPT_2 0x0f +#define QSFP_INTERRUPT_3 0x2c +#define QSFP_INTERRUPT_4 0x2c +#define QSFP_INTERRUPT_5 0x10 +#define QSFP_INTERRUPT_6 0x10 +#define QSFP_INTERRUPT_7 0x2d +#define QSFP_INTERRUPT_8 0x2d + +unsigned char cpupld_reg_addr; +/*---------------- CPLD - start ------------- */ +/* CPLD -- device */ +static struct platform_device ag9064_cpld = { + .name = "delta-ag9064-cpld", + .id = 0, + .dev = { + .platform_data = ag9064_cpld_platform_data, + .release = device_release + }, +}; + +static ssize_t get_present(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u64 data = 0; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + set_cmd = CMD_GETDATA; + + dni_klock(); + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_PRESENCE_1; + cmd_data[3] = 1; + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data = (u64)(ret & 0xff); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_PRESENCE_2; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 8; + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_PRESENCE_3; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 16; + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_PRESENCE_4; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 24; + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_PRESENCE_5; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 32; + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_PRESENCE_6; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 40; + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_PRESENCE_7; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 48; + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_PRESENCE_8; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 56; + + dni_kunlock(); + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u64 data = 0; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + set_cmd = CMD_GETDATA; + + dni_klock(); + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_LP_MODE_1; + cmd_data[3] = 1; + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data = (u64)(ret & 0xff); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_LP_MODE_2; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 8; + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_LP_MODE_3; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 16; + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_LP_MODE_4; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 24; + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_LP_MODE_5; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 32; + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_LP_MODE_6; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 40; + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_LP_MODE_7; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 48; + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_LP_MODE_8; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 56; + + dni_kunlock(); + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t get_reset(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u64 data = 0; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + set_cmd = CMD_GETDATA; + + dni_klock(); + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESET_1; + cmd_data[3] = 1; + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data = (u64)(ret & 0xff); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESET_2; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 8; + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESET_3; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 16; + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESET_4; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 24; + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESET_5; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 32; + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESET_6; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 40; + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESET_7; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 48; + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESET_8; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 56; + + dni_kunlock(); + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t get_response(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u64 data = 0; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + set_cmd = CMD_GETDATA; + + dni_klock(); + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESPONSE_1; + cmd_data[3] = 1; + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data = (u64)(ret & 0xff); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESPONSE_2; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 8; + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESPONSE_3; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 16; + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESPONSE_4; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 24; + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESPONSE_5; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 32; + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESPONSE_6; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 40; + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESPONSE_7; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 48; + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESPONSE_8; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 56; + + dni_kunlock(); + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t get_interrupt(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + int ret; + u64 data = 0; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + set_cmd = CMD_GETDATA; + + dni_klock(); + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_INTERRUPT_1; + cmd_data[3] = 1; + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data = (u64)(ret & 0xff); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_INTERRUPT_2; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 8; + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_INTERRUPT_3; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 16; + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_INTERRUPT_4; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 24; + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_INTERRUPT_5; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 32; + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_INTERRUPT_6; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 40; + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_INTERRUPT_7; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 48; + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_INTERRUPT_8; + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + data |= (u64)(ret & 0xff) << 56; + + dni_kunlock(); + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long long set_data; + int err; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + set_cmd = CMD_SETDATA; + + dni_klock(); + + err = kstrtoull(buf, 16, &set_data); + if (err){ + dni_kunlock(); + return err; + } + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_LP_MODE_1; + cmd_data[3] = (set_data & 0xff); + cmd_data_len = sizeof(cmd_data); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_LP_MODE_2; + cmd_data[3] = ((set_data >> 8 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_LP_MODE_3; + cmd_data[3] = ((set_data >> 16 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_LP_MODE_4; + cmd_data[3] = ((set_data >> 24 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_LP_MODE_5; + cmd_data[3] = ((set_data >> 32 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_LP_MODE_6; + cmd_data[3] = ((set_data >> 40 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_LP_MODE_7; + cmd_data[3] = ((set_data >> 48 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_LP_MODE_8; + cmd_data[3] = ((set_data >> 56 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + dni_kunlock(); + + return count; +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long long set_data; + int err; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + set_cmd = CMD_SETDATA; + + dni_klock(); + + err = kstrtoull(buf, 16, &set_data); + if (err){ + dni_kunlock(); + return err; + } + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESET_1; + cmd_data[3] = (set_data & 0xff); + cmd_data_len = sizeof(cmd_data); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESET_2; + cmd_data[3] = ((set_data >> 8 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESET_3; + cmd_data[3] = ((set_data >> 16 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESET_4; + cmd_data[3] = ((set_data >> 24 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESET_5; + cmd_data[3] = ((set_data >> 32 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESET_6; + cmd_data[3] = ((set_data >> 40 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESET_7; + cmd_data[3] = ((set_data >> 48 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESET_8; + cmd_data[3] = ((set_data >> 56 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + dni_kunlock(); + + return count; +} + +static ssize_t set_response(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + unsigned long long set_data; + int err; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + int cmd_data_len; + set_cmd = CMD_SETDATA; + + dni_klock(); + + err = kstrtoull(buf, 16, &set_data); + if (err){ + dni_kunlock(); + return err; + } + + /*QSFP1~8*/ + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESPONSE_1; + cmd_data[3] = (set_data & 0xff); + cmd_data_len = sizeof(cmd_data); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP9~16*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESPONSE_2; + cmd_data[3] = ((set_data >> 8 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP17~24*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESPONSE_3; + cmd_data[3] = ((set_data >> 16 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP25~32*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESPONSE_4; + cmd_data[3] = ((set_data >> 24 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP33~40*/ + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = QSFP_RESPONSE_5; + cmd_data[3] = ((set_data >> 32 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP41~48*/ + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_RESPONSE_6; + cmd_data[3] = ((set_data >> 40 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP49~56*/ + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = QSFP_RESPONSE_7; + cmd_data[3] = ((set_data >> 48 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + /*QSFP57~64*/ + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = QSFP_RESPONSE_8; + cmd_data[3] = ((set_data >> 56 ) & 0xff); + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + + dni_kunlock(); + + return count; +} + +static ssize_t psu_scan(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + int ret; + uint8_t cmd_data[2]={0}; + uint8_t set_cmd; + int cmd_data_len; + set_cmd = CMD_DEVICE_SCAN; + + dni_klock(); + cmd_data[0] = BMC_BUS_1; + switch (attr->index) + { + case PSU1_SCAN: + cmd_data[1] = PSU1_EEPROM_ADDR; + break; + case PSU2_SCAN: + cmd_data[1] = PSU2_EEPROM_ADDR; + break; + } + cmd_data_len = sizeof(cmd_data); + ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + dni_kunlock(); + return sprintf(buf, "0x%x\n", ret); +} + +static ssize_t get_cpld_reg(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + int mask; + int value; + char note[200]; + unsigned char reg; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cpld_platform_data *pdata = dev->platform_data; + + dni_klock(); + + switch (attr->index) { + case CPLD_REG_ADDR: + dni_kunlock(); + return sprintf(buf, "0x%02x\n", cpupld_reg_addr); + case CPLD_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, cpupld_reg_addr); + dni_kunlock(); + return sprintf(buf, "0x%02x\n", ret); + case CPLD_VER ... OP_MODULE_INT: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + sprintf(note, "\n%s\n",attribute_data[attr->index].note); + value = (value & mask); + break; + default: + dni_kunlock(); + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xFF: + dni_kunlock(); + return sprintf(buf, "0x%02x%s", value, note); + case 0x0F: + dni_kunlock(); + return sprintf(buf, "0x%01x%s", value, note); + case 0xF0: + value = value >> 4; + dni_kunlock(); + return sprintf(buf, "0x%01x%s", value, note); + default : + value = value >> dni_log2(mask); + dni_kunlock(); + return sprintf(buf, "%d%s", value, note); + } + dni_kunlock(); + return sprintf(buf, "%d not found", attr->index); +} + +static ssize_t set_cpld_reg(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + int err; + int value; + int set_data; + unsigned long set_data_ul; + unsigned char reg; + unsigned char mask; + unsigned char mask_out; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cpld_platform_data *pdata = dev->platform_data; + + dni_klock(); + + err = kstrtoul(buf, 0, &set_data_ul); + if (err){ + dni_kunlock(); + return err; + } + + set_data = (int)set_data_ul; + if (set_data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + dni_kunlock(); + return count; + } + + switch (attr->index) { + case CPLD_REG_ADDR: + cpupld_reg_addr = set_data; + dni_kunlock(); + return count; + case CPLD_REG_VALUE: + i2c_smbus_write_byte_data(pdata[system_cpld].client, cpupld_reg_addr, set_data); + dni_kunlock(); + return count; + case CPLD_VER ... OP_MODULE_INT: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg); + mask_out = value & ~(mask); + break; + default: + dni_kunlock(); + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xFF: + set_data = mask_out | (set_data & mask); + break; + case 0x0F: + set_data = mask_out | (set_data & mask); + break; + case 0xF0: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + default : + set_data = mask_out | (set_data << dni_log2(mask) ); + } + + i2c_smbus_write_byte_data(pdata[system_cpld].client, reg, set_data); + dni_kunlock(); + return count; +} + +static DEVICE_ATTR(qsfp_present, S_IRUGO, get_present, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IWUSR | S_IRUGO, get_reset, set_reset); +static DEVICE_ATTR(qsfp_modsel, S_IWUSR | S_IRUGO, get_response, set_response); +static DEVICE_ATTR(qsfp_interrupt, S_IRUGO, get_interrupt, NULL); + +static SENSOR_DEVICE_ATTR(cpld_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_REG_ADDR); +static SENSOR_DEVICE_ATTR(cpld_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_REG_VALUE); +static SENSOR_DEVICE_ATTR(cpld_ver, S_IRUGO, get_cpld_reg, NULL, CPLD_VER); +static SENSOR_DEVICE_ATTR(cpu_board_ver, S_IRUGO, get_cpld_reg, NULL, CPU_BOARD_VER); +static SENSOR_DEVICE_ATTR(cpu_id, S_IRUGO, get_cpld_reg, NULL, CPU_ID); +static SENSOR_DEVICE_ATTR(mb_id, S_IRUGO, get_cpld_reg, NULL, MB_ID); +static SENSOR_DEVICE_ATTR(mb_ver, S_IRUGO, get_cpld_reg, NULL, MB_VER); +static SENSOR_DEVICE_ATTR(cpu0_pwr_ok, S_IRUGO, get_cpld_reg, NULL, CPU0_PWR_OK); +static SENSOR_DEVICE_ATTR(pwr_rail_over_temp, S_IRUGO, get_cpld_reg, NULL, PWR_RAIL_OVER_TEMP); +static SENSOR_DEVICE_ATTR(cpu_disomic_over_temp, S_IRUGO, get_cpld_reg, NULL, CPU_DISOMIC_OVER_TEMP); +static SENSOR_DEVICE_ATTR(ddr_over_temp, S_IRUGO, get_cpld_reg, NULL, DDR_OVER_TEMP); +static SENSOR_DEVICE_ATTR(cpld_pwr_on_rst, S_IRUGO, get_cpld_reg, NULL, CPLD_PWR_ON_RST); +static SENSOR_DEVICE_ATTR(cpld_hard_rst, S_IRUGO, get_cpld_reg, NULL, CPLD_HARD_RST); +static SENSOR_DEVICE_ATTR(cpld_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_RST); +static SENSOR_DEVICE_ATTR(mb_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, MB_RST); +static SENSOR_DEVICE_ATTR(psu_fan_int, S_IRUGO, get_cpld_reg, NULL, PSU_FAN_INT); +static SENSOR_DEVICE_ATTR(op_module_int, S_IRUGO, get_cpld_reg, NULL, OP_MODULE_INT); +static SENSOR_DEVICE_ATTR(psu1_scan, S_IRUGO, psu_scan, NULL, PSU1_SCAN); +static SENSOR_DEVICE_ATTR(psu2_scan, S_IRUGO, psu_scan, NULL, PSU2_SCAN); + +static struct attribute *ag9064_cpld_attrs[] = { + &dev_attr_qsfp_present.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modsel.attr, + &dev_attr_qsfp_interrupt.attr, + &sensor_dev_attr_cpld_reg_value.dev_attr.attr, + &sensor_dev_attr_cpld_reg_addr.dev_attr.attr, + &sensor_dev_attr_cpld_ver.dev_attr.attr, + &sensor_dev_attr_cpu_board_ver.dev_attr.attr, + &sensor_dev_attr_cpu_id.dev_attr.attr, + &sensor_dev_attr_mb_id.dev_attr.attr, + &sensor_dev_attr_mb_ver.dev_attr.attr, + &sensor_dev_attr_cpu0_pwr_ok.dev_attr.attr, + &sensor_dev_attr_pwr_rail_over_temp.dev_attr.attr, + &sensor_dev_attr_cpu_disomic_over_temp.dev_attr.attr, + &sensor_dev_attr_ddr_over_temp.dev_attr.attr, + &sensor_dev_attr_cpld_pwr_on_rst.dev_attr.attr, + &sensor_dev_attr_cpld_hard_rst.dev_attr.attr, + &sensor_dev_attr_cpld_rst.dev_attr.attr, + &sensor_dev_attr_mb_rst.dev_attr.attr, + &sensor_dev_attr_psu_fan_int.dev_attr.attr, + &sensor_dev_attr_op_module_int.dev_attr.attr, + &sensor_dev_attr_psu1_scan.dev_attr.attr, + &sensor_dev_attr_psu2_scan.dev_attr.attr, + NULL, +}; + +static struct attribute_group ag9064_cpld_attr_grp = { + .attrs = ag9064_cpld_attrs, +}; + +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS7); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n",BUS7); + return -ENODEV; + } + + pdata[system_cpld].client = i2c_new_dummy(parent, pdata[system_cpld].reg_addr); + if (!pdata[system_cpld].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[system_cpld].reg_addr); + goto error; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &ag9064_cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; + +error: + i2c_unregister_device(pdata[system_cpld].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &ag9064_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[system_cpld].client) { + if (!parent) { + parent = (pdata[system_cpld].client)->adapter; + } + i2c_unregister_device(pdata[system_cpld].client); + } + } + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-cpld", + }, +}; + +/*---------------- CPLD - end ------------- */ + +/*---------------- module initialization ------------- */ +static int __init delta_ag9064_cpupld_init(void) +{ + int ret; + printk(KERN_WARNING "ag9064_platform_cpupld module initialization\n"); + + // set the CPUPLD prob and remove + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpupld driver\n"); + goto error_cpupld_driver; + } + + // register the CPUPLD + ret = platform_device_register(&ag9064_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpupld device\n"); + goto error_ag9064_cpupld; + } + return 0; + +error_ag9064_cpupld: + platform_driver_unregister(&cpld_driver); +error_cpupld_driver: + return ret; +} + +static void __exit delta_ag9064_cpupld_exit(void) +{ + platform_device_unregister(&ag9064_cpld); + platform_driver_unregister(&cpld_driver); +} +module_init(delta_ag9064_cpupld_init); +module_exit(delta_ag9064_cpupld_exit); + +MODULE_DESCRIPTION("DNI ag9064 CPLD Platform Support"); +MODULE_AUTHOR("Stanley Chi "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_platform.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_platform.c new file mode 100644 index 000000000000..bdf4f1e07e3d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_platform.c @@ -0,0 +1,1384 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "delta_ag9064_common.h" + +#define ag9064_i2c_device_num(NUM){ \ + .name = "delta-ag9064-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &ag9064_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +struct i2c_client * i2c_client_9548; +static struct kobject *kobj_sfp; +struct mutex dni_lock;; + +void dni_klock(void) +{ + mutex_lock(&dni_lock); +} +EXPORT_SYMBOL(dni_klock); +void dni_kunlock(void) +{ + mutex_unlock(&dni_lock); +} +EXPORT_SYMBOL(dni_kunlock); + +/* pca9548 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = +{ + { + .adap_id = 7, + .deselect_on_exit = 1, + }, + { + .adap_id = 8, + .deselect_on_exit = 1, + }, + { + .adap_id = 9, + .deselect_on_exit = 1, + }, + { + .adap_id = 10, + .deselect_on_exit = 1, + }, + { + .adap_id = 11, + .deselect_on_exit = 1, + }, + { + .adap_id = 12, + .deselect_on_exit = 1, + }, + { + .adap_id = 13, + .deselect_on_exit = 1, + }, + { + .adap_id = 14, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = +{ + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct i2c_board_info __initdata i2c_info_pca9548[] = +{ + { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &pca954x_data, + }, +}; + +void device_release(struct device *dev) +{ + return; +} +EXPORT_SYMBOL(device_release); +void msg_handler(struct ipmi_recv_msg *recv_msg, void* handler_data) +{ + struct completion *comp = recv_msg->user_msg_data; + if (comp) + complete(comp); + else + ipmi_free_recv_msg(recv_msg); + return; +} +EXPORT_SYMBOL(msg_handler); +void dummy_smi_free(struct ipmi_smi_msg *msg) +{ + atomic_dec(&dummy_count); +} +EXPORT_SYMBOL(dummy_smi_free); +void dummy_recv_free(struct ipmi_recv_msg *msg) +{ + atomic_dec(&dummy_count); +} +EXPORT_SYMBOL(dummy_recv_free); +unsigned char dni_log2 (unsigned char num){ + unsigned char num_log2 = 0; + while(num > 0){ + num = num >> 1; + num_log2 += 1; + } + return num_log2 -1; +} +EXPORT_SYMBOL(dni_log2); + +/*---------------- IPMI - start ------------- */ + +int dni_create_user(void) +{ + int rv, i; + + for (i=0,rv=1; idev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; + +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- MUX - start ------------- */ + +struct swpld_mux_platform_data { + int parent; + int base_nr; +}; + +struct swpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct swpld_mux_platform_data data; +}; + +static struct swpld_mux_platform_data ag9064_swpld_mux_platform_data[] = { + { + .parent = BUS9, + .base_nr = BUS9_BASE_NUM, + }, +}; + +static struct platform_device ag9064_swpld_mux[] = +{ + { + .name = "delta-ag9064-swpld-mux", + .id = 0, + .dev = { + .platform_data = &ag9064_swpld_mux_platform_data[0], + .release = device_release, + }, + }, +}; + +static int swpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + uint8_t cmd_data[4]={0}; + struct swpld_mux *mux = i2c_mux_priv(muxc); + uint8_t set_cmd; + int cmd_data_len; + + if ( mux->data.base_nr == BUS9_BASE_NUM ) + { + set_cmd = CMD_SETDATA; + cmd_data[0] = BMC_BUS_5; + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = QSFP_PORT_MUX_REG; + cmd_data[3] = chan + 1; + cmd_data_len = sizeof(cmd_data); + return dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + } + else + { + printk(KERN_ERR "Swpld mux QSFP select port error\n"); + return 0; + } + +} + +static int __init swpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct swpld_mux *mux; + struct swpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + printk(KERN_ERR "Failed to allocate memory for mux\n"); + return -ENOMEM; + } + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + kfree(mux); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS9: + dev_num = BUS9_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0,swpld_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + platform_set_drvdata(pdev, muxc); + + for (i = 0; i < dev_num; i++) + { + int nr = pdata->base_nr + i; + unsigned int class = 0; + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_num, parent->name); + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + i2c_put_adapter(parent); + kfree(mux); + + return ret; +} + +static int __exit swpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + struct i2c_adapter *parent=muxc->parent; + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver swpld_mux_driver = { + .probe = swpld_mux_probe, + .remove = __exit_p(swpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-swpld-mux", + }, +}; + +/*---------------- MUX - end ------------- */ + +/*---------------- SFP - start ------------- */ + +struct delta_bin_attribute { + struct bin_attribute attr; + int index; +}; + +#define to_delta_attr(x) container_of(x, struct delta_bin_attribute, attr) + +#define BIN_ATTR(_name, _mode, _read, _write, _size, _index) { \ + .attr = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .read = _read, \ + .write = _write, \ + .size = _size, \ + }, \ + .index = _index, \ +} + +#define DELTA_BIN_ATTR(_name, _mode, _read, _write, _size, _index) \ +struct delta_bin_attribute delta_attr_##_name \ + = BIN_ATTR(_name, _mode, _read, _write, _size, _index) + +static char eeprom_data[EEPROM_SIZE]; + +static ssize_t access_user_space(const char *name, char *buf, size_t len, loff_t offset, int mode) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + ssize_t vfs_ret = 0; + int i = 0; + + fs = get_fs(); + set_fs(get_ds()); + + switch(mode) + { + case ATTR_W: + fp = filp_open(name, O_WRONLY, S_IWUGO); + if (IS_ERR(fp)){ + return -ENOENT; + } + for(i = 0; i < ((len / EEPROM_ARCH_SIZE) + 1); i++) + { + len = len - pos; + vfs_ret = vfs_write(fp, buf + pos, len, &pos); + } + break; + case ATTR_R: + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)){ + return -ENOENT; + } + vfs_ret = vfs_read(fp, buf, len, &pos); + break; + } + + set_fs(fs); + filp_close(fp, NULL); + return vfs_ret; +} + +static ssize_t delta_bin_attr_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct delta_bin_attribute *delta_attr = to_delta_attr(attr); + char attr_path[100]; + + dni_klock(); + + memset(buf, 0, count); + switch(delta_attr->index) { + case EEPROM_SFP_1: + case EEPROM_SFP_2: + case EEPROM_SFP_3: + case EEPROM_SFP_4: + case EEPROM_SFP_5: + case EEPROM_SFP_6: + case EEPROM_SFP_7: + case EEPROM_SFP_8: + case EEPROM_SFP_9: + case EEPROM_SFP_10: + case EEPROM_SFP_11: + case EEPROM_SFP_12: + case EEPROM_SFP_13: + case EEPROM_SFP_14: + case EEPROM_SFP_15: + case EEPROM_SFP_16: + case EEPROM_SFP_17: + case EEPROM_SFP_18: + case EEPROM_SFP_19: + case EEPROM_SFP_20: + case EEPROM_SFP_21: + case EEPROM_SFP_22: + case EEPROM_SFP_23: + case EEPROM_SFP_24: + case EEPROM_SFP_25: + case EEPROM_SFP_26: + case EEPROM_SFP_27: + case EEPROM_SFP_28: + case EEPROM_SFP_29: + case EEPROM_SFP_30: + case EEPROM_SFP_31: + case EEPROM_SFP_32: + case EEPROM_SFP_33: + case EEPROM_SFP_34: + case EEPROM_SFP_35: + case EEPROM_SFP_36: + case EEPROM_SFP_37: + case EEPROM_SFP_38: + case EEPROM_SFP_39: + case EEPROM_SFP_40: + case EEPROM_SFP_41: + case EEPROM_SFP_42: + case EEPROM_SFP_43: + case EEPROM_SFP_44: + case EEPROM_SFP_45: + case EEPROM_SFP_46: + case EEPROM_SFP_47: + case EEPROM_SFP_48: + case EEPROM_SFP_49: + case EEPROM_SFP_50: + case EEPROM_SFP_51: + case EEPROM_SFP_52: + case EEPROM_SFP_53: + case EEPROM_SFP_54: + case EEPROM_SFP_55: + case EEPROM_SFP_56: + case EEPROM_SFP_57: + case EEPROM_SFP_58: + case EEPROM_SFP_59: + case EEPROM_SFP_60: + case EEPROM_SFP_61: + case EEPROM_SFP_62: + case EEPROM_SFP_63: + case EEPROM_SFP_64: + sprintf(attr_path, "/sys/bus/i2c/devices/%d-0050/eeprom", delta_attr->index + EEPROM_MASK); + if (access_user_space(attr_path, eeprom_data, EEPROM_SIZE, off, ATTR_R) < 0) { + goto ACCESS_ERROR; + } + count = (count <= EEPROM_SIZE) ? count : EEPROM_SIZE; + memcpy(buf, eeprom_data + off, count); + break; + default: + goto ACCESS_ERROR; + } + dni_kunlock(); + return count; + +ACCESS_ERROR: + dni_kunlock(); + return -ETIMEDOUT; +} + +static ssize_t delta_bin_attr_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct delta_bin_attribute *delta_attr = to_delta_attr(attr); + char attr_path[100]; + + dni_klock(); + + switch(delta_attr->index){ + case EEPROM_SFP_1: + case EEPROM_SFP_2: + case EEPROM_SFP_3: + case EEPROM_SFP_4: + case EEPROM_SFP_5: + case EEPROM_SFP_6: + case EEPROM_SFP_7: + case EEPROM_SFP_8: + case EEPROM_SFP_9: + case EEPROM_SFP_10: + case EEPROM_SFP_11: + case EEPROM_SFP_12: + case EEPROM_SFP_13: + case EEPROM_SFP_14: + case EEPROM_SFP_15: + case EEPROM_SFP_16: + case EEPROM_SFP_17: + case EEPROM_SFP_18: + case EEPROM_SFP_19: + case EEPROM_SFP_20: + case EEPROM_SFP_21: + case EEPROM_SFP_22: + case EEPROM_SFP_23: + case EEPROM_SFP_24: + case EEPROM_SFP_25: + case EEPROM_SFP_26: + case EEPROM_SFP_27: + case EEPROM_SFP_28: + case EEPROM_SFP_29: + case EEPROM_SFP_30: + case EEPROM_SFP_31: + case EEPROM_SFP_32: + case EEPROM_SFP_33: + case EEPROM_SFP_34: + case EEPROM_SFP_35: + case EEPROM_SFP_36: + case EEPROM_SFP_37: + case EEPROM_SFP_38: + case EEPROM_SFP_39: + case EEPROM_SFP_40: + case EEPROM_SFP_41: + case EEPROM_SFP_42: + case EEPROM_SFP_43: + case EEPROM_SFP_44: + case EEPROM_SFP_45: + case EEPROM_SFP_46: + case EEPROM_SFP_47: + case EEPROM_SFP_48: + case EEPROM_SFP_49: + case EEPROM_SFP_50: + case EEPROM_SFP_51: + case EEPROM_SFP_52: + case EEPROM_SFP_53: + case EEPROM_SFP_54: + case EEPROM_SFP_55: + case EEPROM_SFP_56: + case EEPROM_SFP_57: + case EEPROM_SFP_58: + case EEPROM_SFP_59: + case EEPROM_SFP_60: + case EEPROM_SFP_61: + case EEPROM_SFP_62: + case EEPROM_SFP_63: + case EEPROM_SFP_64: + sprintf(attr_path, "/sys/bus/i2c/devices/%d-0050/eeprom", delta_attr->index + EEPROM_MASK); + if (access_user_space(attr_path, buf, count, off, ATTR_W) < 0) { + goto ACCESS_ERROR; + } + break; + default: + goto ACCESS_ERROR; + } + + dni_kunlock(); + return count; +ACCESS_ERROR: + dni_kunlock(); + return -ETIMEDOUT; +} + +DELTA_BIN_ATTR(eeprom_sfp_1, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_1); +DELTA_BIN_ATTR(eeprom_sfp_2, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_2); +DELTA_BIN_ATTR(eeprom_sfp_3, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_3); +DELTA_BIN_ATTR(eeprom_sfp_4, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_4); +DELTA_BIN_ATTR(eeprom_sfp_5, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_5); +DELTA_BIN_ATTR(eeprom_sfp_6, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_6); +DELTA_BIN_ATTR(eeprom_sfp_7, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_7); +DELTA_BIN_ATTR(eeprom_sfp_8, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_8); +DELTA_BIN_ATTR(eeprom_sfp_9, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_9); +DELTA_BIN_ATTR(eeprom_sfp_10, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_10); +DELTA_BIN_ATTR(eeprom_sfp_11, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_11); +DELTA_BIN_ATTR(eeprom_sfp_12, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_12); +DELTA_BIN_ATTR(eeprom_sfp_13, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_13); +DELTA_BIN_ATTR(eeprom_sfp_14, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_14); +DELTA_BIN_ATTR(eeprom_sfp_15, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_15); +DELTA_BIN_ATTR(eeprom_sfp_16, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_16); +DELTA_BIN_ATTR(eeprom_sfp_17, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_17); +DELTA_BIN_ATTR(eeprom_sfp_18, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_18); +DELTA_BIN_ATTR(eeprom_sfp_19, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_19); +DELTA_BIN_ATTR(eeprom_sfp_20, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_20); +DELTA_BIN_ATTR(eeprom_sfp_21, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_21); +DELTA_BIN_ATTR(eeprom_sfp_22, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_22); +DELTA_BIN_ATTR(eeprom_sfp_23, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_23); +DELTA_BIN_ATTR(eeprom_sfp_24, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_24); +DELTA_BIN_ATTR(eeprom_sfp_25, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_25); +DELTA_BIN_ATTR(eeprom_sfp_26, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_26); +DELTA_BIN_ATTR(eeprom_sfp_27, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_27); +DELTA_BIN_ATTR(eeprom_sfp_28, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_28); +DELTA_BIN_ATTR(eeprom_sfp_29, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_29); +DELTA_BIN_ATTR(eeprom_sfp_30, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_30); +DELTA_BIN_ATTR(eeprom_sfp_31, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_31); +DELTA_BIN_ATTR(eeprom_sfp_32, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_32); +DELTA_BIN_ATTR(eeprom_sfp_33, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_33); +DELTA_BIN_ATTR(eeprom_sfp_34, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_34); +DELTA_BIN_ATTR(eeprom_sfp_35, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_35); +DELTA_BIN_ATTR(eeprom_sfp_36, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_36); +DELTA_BIN_ATTR(eeprom_sfp_37, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_37); +DELTA_BIN_ATTR(eeprom_sfp_38, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_38); +DELTA_BIN_ATTR(eeprom_sfp_39, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_39); +DELTA_BIN_ATTR(eeprom_sfp_40, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_40); +DELTA_BIN_ATTR(eeprom_sfp_41, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_41); +DELTA_BIN_ATTR(eeprom_sfp_42, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_42); +DELTA_BIN_ATTR(eeprom_sfp_43, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_43); +DELTA_BIN_ATTR(eeprom_sfp_44, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_44); +DELTA_BIN_ATTR(eeprom_sfp_45, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_45); +DELTA_BIN_ATTR(eeprom_sfp_46, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_46); +DELTA_BIN_ATTR(eeprom_sfp_47, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_47); +DELTA_BIN_ATTR(eeprom_sfp_48, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_48); +DELTA_BIN_ATTR(eeprom_sfp_49, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_49); +DELTA_BIN_ATTR(eeprom_sfp_50, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_50); +DELTA_BIN_ATTR(eeprom_sfp_51, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_51); +DELTA_BIN_ATTR(eeprom_sfp_52, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_52); +DELTA_BIN_ATTR(eeprom_sfp_53, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_53); +DELTA_BIN_ATTR(eeprom_sfp_54, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_54); +DELTA_BIN_ATTR(eeprom_sfp_55, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_55); +DELTA_BIN_ATTR(eeprom_sfp_56, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_56); +DELTA_BIN_ATTR(eeprom_sfp_57, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_57); +DELTA_BIN_ATTR(eeprom_sfp_58, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_58); +DELTA_BIN_ATTR(eeprom_sfp_59, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_59); +DELTA_BIN_ATTR(eeprom_sfp_60, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_60); +DELTA_BIN_ATTR(eeprom_sfp_61, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_61); +DELTA_BIN_ATTR(eeprom_sfp_62, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_62); +DELTA_BIN_ATTR(eeprom_sfp_63, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_63); +DELTA_BIN_ATTR(eeprom_sfp_64, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_64); + +static struct bin_attribute *sfp_attrs[] = { + &delta_attr_eeprom_sfp_1.attr, + &delta_attr_eeprom_sfp_2.attr, + &delta_attr_eeprom_sfp_3.attr, + &delta_attr_eeprom_sfp_4.attr, + &delta_attr_eeprom_sfp_5.attr, + &delta_attr_eeprom_sfp_6.attr, + &delta_attr_eeprom_sfp_7.attr, + &delta_attr_eeprom_sfp_8.attr, + &delta_attr_eeprom_sfp_9.attr, + &delta_attr_eeprom_sfp_10.attr, + &delta_attr_eeprom_sfp_11.attr, + &delta_attr_eeprom_sfp_12.attr, + &delta_attr_eeprom_sfp_13.attr, + &delta_attr_eeprom_sfp_14.attr, + &delta_attr_eeprom_sfp_15.attr, + &delta_attr_eeprom_sfp_16.attr, + &delta_attr_eeprom_sfp_17.attr, + &delta_attr_eeprom_sfp_18.attr, + &delta_attr_eeprom_sfp_19.attr, + &delta_attr_eeprom_sfp_20.attr, + &delta_attr_eeprom_sfp_21.attr, + &delta_attr_eeprom_sfp_22.attr, + &delta_attr_eeprom_sfp_23.attr, + &delta_attr_eeprom_sfp_24.attr, + &delta_attr_eeprom_sfp_25.attr, + &delta_attr_eeprom_sfp_26.attr, + &delta_attr_eeprom_sfp_27.attr, + &delta_attr_eeprom_sfp_28.attr, + &delta_attr_eeprom_sfp_29.attr, + &delta_attr_eeprom_sfp_30.attr, + &delta_attr_eeprom_sfp_31.attr, + &delta_attr_eeprom_sfp_32.attr, + &delta_attr_eeprom_sfp_33.attr, + &delta_attr_eeprom_sfp_34.attr, + &delta_attr_eeprom_sfp_35.attr, + &delta_attr_eeprom_sfp_36.attr, + &delta_attr_eeprom_sfp_37.attr, + &delta_attr_eeprom_sfp_38.attr, + &delta_attr_eeprom_sfp_39.attr, + &delta_attr_eeprom_sfp_40.attr, + &delta_attr_eeprom_sfp_41.attr, + &delta_attr_eeprom_sfp_42.attr, + &delta_attr_eeprom_sfp_43.attr, + &delta_attr_eeprom_sfp_44.attr, + &delta_attr_eeprom_sfp_45.attr, + &delta_attr_eeprom_sfp_46.attr, + &delta_attr_eeprom_sfp_47.attr, + &delta_attr_eeprom_sfp_48.attr, + &delta_attr_eeprom_sfp_49.attr, + &delta_attr_eeprom_sfp_50.attr, + &delta_attr_eeprom_sfp_51.attr, + &delta_attr_eeprom_sfp_52.attr, + &delta_attr_eeprom_sfp_53.attr, + &delta_attr_eeprom_sfp_54.attr, + &delta_attr_eeprom_sfp_55.attr, + &delta_attr_eeprom_sfp_56.attr, + &delta_attr_eeprom_sfp_57.attr, + &delta_attr_eeprom_sfp_58.attr, + &delta_attr_eeprom_sfp_59.attr, + &delta_attr_eeprom_sfp_60.attr, + &delta_attr_eeprom_sfp_61.attr, + &delta_attr_eeprom_sfp_62.attr, + &delta_attr_eeprom_sfp_63.attr, + &delta_attr_eeprom_sfp_64.attr, + NULL, /* need to NULL terminate the list of attributes */ +}; + +static struct attribute_group sfp_attr_grp = { + .bin_attrs = sfp_attrs, +}; +/*---------------- SFP - end ------------- */ + + +/*---------------- module initialization ------------- */ + +static int __init delta_ag9064_platform_init(void) +{ + struct i2c_adapter *adapter; + struct swpld_mux_platform_data *swpld_pdata; + int ret,i = 0; + + printk("ag9064_platform module initialization\n"); + + mutex_init(&dni_lock); + + adapter = i2c_get_adapter(BUS2); + i2c_client_9548 = i2c_new_device(adapter, &i2c_info_pca9548[0]); + i2c_put_adapter(adapter); + + ret = dni_create_user(); + if (ret != 0){ + printk(KERN_WARNING "Fail to create IPMI user\n"); + } + + // register the mux prob which call the SWPLD + ret = platform_driver_register(&swpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_swpld_mux_driver; + } + + // register the i2c devices + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + swpld_pdata = ag9064_swpld_mux[0].dev.platform_data; + ret = platform_device_register(&ag9064_swpld_mux[0]); + if (ret) { + printk(KERN_WARNING "Fail to create swpld mux\n"); + goto error_ag9064_swpld_mux; + } + + for (i = 0; i < ARRAY_SIZE(ag9064_i2c_device); i++) + { + ret = platform_device_register(&ag9064_i2c_device[i]); + if (ret) + { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_ag9064_i2c_device; + } + } + + kobj_sfp = kobject_create_and_add("sfp", kernel_kobj); + if(!kobj_sfp) + { + return -ENOMEM; + } + ret = sysfs_create_group(kobj_sfp, &sfp_attr_grp); + if (ret) + { + printk(KERN_WARNING "Fail to create sysfs of sfp group\n"); + goto error_create_sfp_group; + } + + if (ret) + goto error_create_sfp_group; + + return 0; + +error_create_sfp_group: + kobject_put(kobj_sfp); +error_ag9064_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&ag9064_i2c_device[i]); + } + i = ARRAY_SIZE(ag9064_swpld_mux); +error_ag9064_swpld_mux: + platform_device_unregister(&ag9064_swpld_mux[0]); + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld_mux_driver); +error_swpld_mux_driver: + return ret; +} + +static void __exit delta_ag9064_platform_exit(void) +{ + int i = 0; + + kobject_put(kobj_sfp); + for ( i = 0; i < ARRAY_SIZE(ag9064_i2c_device); i++ ) { + platform_device_unregister(&ag9064_i2c_device[i]); + } + + platform_device_unregister(&ag9064_swpld_mux[0]); + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&swpld_mux_driver); + i2c_unregister_device(i2c_client_9548); +} + +module_init(delta_ag9064_platform_init); +module_exit(delta_ag9064_platform_exit); + +MODULE_DESCRIPTION("DELTA ag9064 Platform Support"); +MODULE_AUTHOR("Johnson Lu "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_swpld.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_swpld.c new file mode 100644 index 000000000000..fd17a28378aa --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/delta_ag9064_swpld.c @@ -0,0 +1,622 @@ +#include "delta_ag9064_common.h" + +unsigned char swpld1_reg_addr; +unsigned char swpld2_reg_addr; +unsigned char swpld3_reg_addr; +unsigned char swpld4_reg_addr; + +/*---------------- CPLD - start ------------- */ +/* SWPLD1 -- device */ +static struct platform_device swpld1_device = { + .name = "delta-ag9064-swpld1", + .id = 0, + .dev = { + .platform_data = ag9064_swpld1_platform_data, + .release = device_release + }, +}; + +static struct platform_device swpld2_device = { + .name = "delta-ag9064-swpld2", + .id = 0, + .dev = { + .platform_data = ag9064_swpld2_platform_data, + .release = device_release + }, +}; +static struct platform_device swpld3_device = { + .name = "delta-ag9064-swpld3", + .id = 0, + .dev = { + .platform_data = ag9064_swpld3_platform_data, + .release = device_release + }, +}; +static struct platform_device swpld4_device = { + .name = "delta-ag9064-swpld4", + .id = 0, + .dev = { + .platform_data = ag9064_swpld4_platform_data, + .release = device_release + }, +}; + +static ssize_t get_swpld_reg(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + int mask; + int value; + int cmd_data_len; + char note[200]; + uint8_t cmd_data[4]={0}; + uint8_t get_cmd; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + + dni_klock(); + cmd_data_len = sizeof(cmd_data); + get_cmd = CMD_GETDATA; + cmd_data[0] = BMC_BUS_5; + cmd_data[3] = 1; + mask = attribute_data[attr->index].mask; + sprintf(note, "\n%s\n",attribute_data[attr->index].note); + + if (attr->index <= SWPLD4_REG_VALUE){ + switch (attr->index) { + case SWPLD1_REG_ADDR: + dni_kunlock(); + return sprintf(buf, "0x%02x\n", swpld1_reg_addr); + case SWPLD2_REG_ADDR: + dni_kunlock(); + return sprintf(buf, "0x%02x\n", swpld2_reg_addr); + case SWPLD3_REG_ADDR: + dni_kunlock(); + return sprintf(buf, "0x%02x\n", swpld3_reg_addr); + case SWPLD4_REG_ADDR: + dni_kunlock(); + return sprintf(buf, "0x%02x\n", swpld4_reg_addr); + case SWPLD1_REG_VALUE: + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = swpld1_reg_addr; + break; + case SWPLD2_REG_VALUE: + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = swpld2_reg_addr; + break; + case SWPLD3_REG_VALUE: + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = swpld3_reg_addr; + break; + case SWPLD4_REG_VALUE: + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = swpld4_reg_addr; + break; + default: + dni_kunlock(); + return sprintf(buf, "%d not found", attr->index); + } + ret = dni_bmc_cmd(get_cmd, cmd_data, cmd_data_len); + ret = ret & 0xff; + dni_kunlock(); + return sprintf(buf, "0x%02x\n", ret); + }else{ + + switch (attr->index) { + case SWPLD1_MAJOR_VER ... PSU_LED_MODE : + cmd_data[1] = SWPLD1_ADDR; + break; + case SWPLD2_MAJOR_VER ... FAN_MOD4_LED : + cmd_data[1] = SWPLD2_ADDR; + break; + case SWPLD3_MAJOR_VER ... PLATFORM_TYPE : + cmd_data[1] = SWPLD3_ADDR; + break; + case SW_BOARD_ID1 ... FAN_EEPROM_WP : + cmd_data[1] = SWPLD4_ADDR; + break; + default: + dni_kunlock(); + return sprintf(buf, "%d not found", attr->index); + } + cmd_data[2] = attribute_data[attr->index].reg; + value = dni_bmc_cmd(get_cmd, cmd_data, cmd_data_len); + value = value & mask; + switch (mask) { + case 0xFF: + dni_kunlock(); + return sprintf(buf, "0x%02x%s", value, note); + case 0x0F: + dni_kunlock(); + return sprintf(buf, "0x%01x%s", value, note); + case 0xF0: + value = value >> 4; + dni_kunlock(); + return sprintf(buf, "0x%01x%s", value, note); + case 0xC0: + value = value >> 6; + dni_kunlock(); + return sprintf(buf, "0x%01x%s", value, note); + case 0x30: + value = value >> 4; + dni_kunlock(); + return sprintf(buf, "0x%01x%s", value, note); + default : + value = value >> dni_log2(mask); + dni_kunlock(); + return sprintf(buf, "%d%s", value, note); + } + } + dni_kunlock(); + return sprintf(buf, "%d not found", attr->index); +} + +static ssize_t set_swpld_reg(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + int err; + int value; + int set_data; + int cmd_data_len; + uint8_t cmd_data[4]={0}; + uint8_t set_cmd; + uint8_t get_cmd; + unsigned long set_data_ul; + unsigned char mask; + unsigned char mask_out; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + + cmd_data_len = sizeof(cmd_data); + set_cmd = CMD_SETDATA; + get_cmd = CMD_GETDATA; + + dni_klock(); + + err = kstrtoul(buf, 0, &set_data_ul); + if (err){ + dni_kunlock(); + return err; + } + + if (set_data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + dni_kunlock(); + return count; + } + + set_data = (int)set_data_ul; + if (attr->index <= SWPLD4_REG_VALUE){ + cmd_data[0] = BMC_BUS_5; + cmd_data[3] = set_data; + switch (attr->index) { + //reg_addr + case SWPLD1_REG_ADDR: + swpld1_reg_addr = set_data; + dni_kunlock(); + return count; + case SWPLD2_REG_ADDR: + swpld2_reg_addr = set_data; + dni_kunlock(); + return count; + case SWPLD3_REG_ADDR: + swpld3_reg_addr = set_data; + dni_kunlock(); + return count; + case SWPLD4_REG_ADDR: + swpld4_reg_addr = set_data; + dni_kunlock(); + return count; + //reg_value + case SWPLD1_REG_VALUE: + cmd_data[1] = SWPLD1_ADDR; + cmd_data[2] = swpld1_reg_addr; + break; + case SWPLD2_REG_VALUE: + cmd_data[1] = SWPLD2_ADDR; + cmd_data[2] = swpld2_reg_addr; + break; + case SWPLD3_REG_VALUE: + cmd_data[1] = SWPLD3_ADDR; + cmd_data[2] = swpld3_reg_addr; + break; + case SWPLD4_REG_VALUE: + cmd_data[1] = SWPLD4_ADDR; + cmd_data[2] = swpld4_reg_addr; + break; + default : + dni_kunlock(); + return sprintf(buf, "%d not found", attr->index); + } + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + dni_kunlock(); + return count; + } + else{ + cmd_data[0] = BMC_BUS_5; + cmd_data[2] = attribute_data[attr->index].reg; + cmd_data[3] = 1; + switch (attr->index) { + //attributes + case SWPLD1_MAJOR_VER ... PSU_LED_MODE://SWPLD1 + cmd_data[1] = SWPLD1_ADDR; + break; + case SWPLD2_MAJOR_VER ... FAN_MOD4_LED://SWPLD2 + cmd_data[1] = SWPLD2_ADDR; + break; + case SWPLD3_MAJOR_VER ... PLATFORM_TYPE://SWPLD3 + cmd_data[1] = SWPLD3_ADDR; + break; + case SW_BOARD_ID1 ... FAN_EEPROM_WP://SWPLD4 + cmd_data[1] = SWPLD4_ADDR; + break; + default: + dni_kunlock(); + return sprintf(buf, "%d not found", attr->index); + } + + value = dni_bmc_cmd(get_cmd, cmd_data, cmd_data_len); + mask = attribute_data[attr->index].mask; + mask_out = value & ~(mask); + cmd_data[3] = set_data; + switch (mask) { + case 0xFF: + set_data = mask_out | (set_data & mask); + break; + case 0x0F: + set_data = mask_out | (set_data & mask); + break; + case 0xF0: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + case 0xC0: + set_data = set_data << 6; + set_data = mask_out | (set_data & mask); + break; + case 0x30: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + default : + set_data = mask_out | (set_data << dni_log2(mask) ); + } + dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len); + dni_kunlock(); + return count; + } + dni_kunlock(); + return count; +} + +//SWPLD +static SENSOR_DEVICE_ATTR(swpld1_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD1_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld1_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD1_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld2_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD2_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld2_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD2_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld3_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD3_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld3_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD3_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld4_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD4_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld4_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD4_REG_VALUE); +//SWPLD1 +static SENSOR_DEVICE_ATTR(swpld1_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD1_MAJOR_VER); +static SENSOR_DEVICE_ATTR(swpld1_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD1_MINOR_VER); +static SENSOR_DEVICE_ATTR(swpld1_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD1_SCRTCH_REG); +static SENSOR_DEVICE_ATTR(psu1_pwr_ok, S_IRUGO, get_swpld_reg, NULL, PSU1_PWR_OK); +static SENSOR_DEVICE_ATTR(psu1_int, S_IRUGO, get_swpld_reg, NULL, PSU1_INT); +static SENSOR_DEVICE_ATTR(psu2_pwr_ok, S_IRUGO, get_swpld_reg, NULL, PSU2_PWR_OK); +static SENSOR_DEVICE_ATTR(psu2_int, S_IRUGO, get_swpld_reg, NULL, PSU2_INT); +static SENSOR_DEVICE_ATTR(psu1_green_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU1_GREEN_LED); +static SENSOR_DEVICE_ATTR(psu1_red_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU1_RED_LED); +static SENSOR_DEVICE_ATTR(psu2_green_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU2_GREEN_LED); +static SENSOR_DEVICE_ATTR(psu2_red_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU2_RED_LED); +static SENSOR_DEVICE_ATTR(psu_led_mode, S_IRUGO, get_swpld_reg, NULL, PSU_LED_MODE); +//SWPLD2 +static SENSOR_DEVICE_ATTR(swpld2_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD2_MAJOR_VER); +static SENSOR_DEVICE_ATTR(swpld2_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD2_MINOR_VER); +static SENSOR_DEVICE_ATTR(swpld2_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD2_SCRTCH_REG); +static SENSOR_DEVICE_ATTR(fan_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_LED); +static SENSOR_DEVICE_ATTR(sys_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SYS_LED); +static SENSOR_DEVICE_ATTR(fan_mod1_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD1_LED); +static SENSOR_DEVICE_ATTR(fan_mod2_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD2_LED); +static SENSOR_DEVICE_ATTR(fan_mod3_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD3_LED); +static SENSOR_DEVICE_ATTR(fan_mod4_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD4_LED); +//SWPLD3 +static SENSOR_DEVICE_ATTR(swpld3_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD3_MAJOR_VER); +static SENSOR_DEVICE_ATTR(swpld3_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD3_MINOR_VER); +static SENSOR_DEVICE_ATTR(swpld3_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD3_SCRTCH_REG); +static SENSOR_DEVICE_ATTR(sb_ver, S_IRUGO, get_swpld_reg, NULL, SB_VER); +static SENSOR_DEVICE_ATTR(platform_type, S_IRUGO, get_swpld_reg, NULL, PLATFORM_TYPE); + +//SWPLD4 +static SENSOR_DEVICE_ATTR(sw_board_id1, S_IRUGO, get_swpld_reg, NULL, SW_BOARD_ID1); +static SENSOR_DEVICE_ATTR(sw_board_id2, S_IRUGO, get_swpld_reg, NULL, SW_BOARD_ID2); +static SENSOR_DEVICE_ATTR(swbd_ver, S_IRUGO, get_swpld_reg, NULL, SWBD_VER); +static SENSOR_DEVICE_ATTR(swpld4_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD4_VER); +static SENSOR_DEVICE_ATTR(psu_fan_event, S_IRUGO, get_swpld_reg, NULL, PSU_FAN_EVENT); +static SENSOR_DEVICE_ATTR(cpu_thermal_int, S_IRUGO, get_swpld_reg, NULL, CPU_THERMAL_INT); +static SENSOR_DEVICE_ATTR(fan_int, S_IRUGO, get_swpld_reg, NULL, FAN_INT); +static SENSOR_DEVICE_ATTR(cpld_spi_wp, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, CPLD_SPI_WP); +static SENSOR_DEVICE_ATTR(rj45_console_sel, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, RJ45_CONSOLE_SEL); +static SENSOR_DEVICE_ATTR(system_int, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SYSTEM_INT); +static SENSOR_DEVICE_ATTR(cpld_mb_rst_done, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, CPLD_MB_RST_DONE); +static SENSOR_DEVICE_ATTR(mb_pwr_ok, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, MB_PWR_OK); +static SENSOR_DEVICE_ATTR(fan_eeprom_wp, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_EEPROM_WP); + +static struct attribute *swpld1_device_attrs[] = { + &sensor_dev_attr_swpld1_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld1_reg_addr.dev_attr.attr, + &sensor_dev_attr_swpld1_major_ver.dev_attr.attr, + &sensor_dev_attr_swpld1_minor_ver.dev_attr.attr, + &sensor_dev_attr_swpld1_scrtch_reg.dev_attr.attr, + &sensor_dev_attr_psu1_pwr_ok.dev_attr.attr, + &sensor_dev_attr_psu1_int.dev_attr.attr, + &sensor_dev_attr_psu2_pwr_ok.dev_attr.attr, + &sensor_dev_attr_psu2_int.dev_attr.attr, + &sensor_dev_attr_psu1_green_led.dev_attr.attr, + &sensor_dev_attr_psu1_red_led.dev_attr.attr, + &sensor_dev_attr_psu2_green_led.dev_attr.attr, + &sensor_dev_attr_psu2_red_led.dev_attr.attr, + &sensor_dev_attr_psu_led_mode.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld2_device_attrs[] = { + &sensor_dev_attr_swpld2_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld2_reg_addr.dev_attr.attr, + &sensor_dev_attr_swpld2_major_ver.dev_attr.attr, + &sensor_dev_attr_swpld2_minor_ver.dev_attr.attr, + &sensor_dev_attr_swpld2_scrtch_reg.dev_attr.attr, + &sensor_dev_attr_fan_led.dev_attr.attr, + &sensor_dev_attr_sys_led.dev_attr.attr, + &sensor_dev_attr_fan_mod1_led.dev_attr.attr, + &sensor_dev_attr_fan_mod2_led.dev_attr.attr, + &sensor_dev_attr_fan_mod3_led.dev_attr.attr, + &sensor_dev_attr_fan_mod4_led.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld3_device_attrs[] = { + &sensor_dev_attr_swpld3_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld3_reg_addr.dev_attr.attr, + &sensor_dev_attr_swpld3_major_ver.dev_attr.attr, + &sensor_dev_attr_swpld3_minor_ver.dev_attr.attr, + &sensor_dev_attr_swpld3_scrtch_reg.dev_attr.attr, + &sensor_dev_attr_sb_ver.dev_attr.attr, + &sensor_dev_attr_platform_type.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld4_device_attrs[] = { + &sensor_dev_attr_sw_board_id1.dev_attr.attr, + &sensor_dev_attr_sw_board_id2.dev_attr.attr, + &sensor_dev_attr_swbd_ver.dev_attr.attr, + &sensor_dev_attr_swpld4_ver.dev_attr.attr, + &sensor_dev_attr_psu_fan_event.dev_attr.attr, + &sensor_dev_attr_cpu_thermal_int.dev_attr.attr, + &sensor_dev_attr_fan_int.dev_attr.attr, + &sensor_dev_attr_cpld_spi_wp.dev_attr.attr, + &sensor_dev_attr_rj45_console_sel.dev_attr.attr, + &sensor_dev_attr_system_int.dev_attr.attr, + &sensor_dev_attr_cpld_mb_rst_done.dev_attr.attr, + &sensor_dev_attr_mb_pwr_ok.dev_attr.attr, + &sensor_dev_attr_fan_eeprom_wp.dev_attr.attr, + NULL, +}; + +static struct attribute_group swpld1_device_attr_grp = { + .attrs = swpld1_device_attrs, +}; + +static struct attribute_group swpld2_device_attr_grp = { + .attrs = swpld2_device_attrs, +}; + +static struct attribute_group swpld3_device_attr_grp = { + .attrs = swpld3_device_attrs, +}; + +static struct attribute_group swpld4_device_attr_grp = { + .attrs = swpld4_device_attrs, +}; + +static int __init swpld1_probe(struct platform_device *pdev) +{ + int ret; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld1_device_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + return -ENODEV; + } + return 0; +} + +static int __init swpld2_probe(struct platform_device *pdev) +{ + int ret; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld2_device_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + return -ENODEV; + } + return 0; +} + +static int __init swpld3_probe(struct platform_device *pdev) +{ + int ret; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld3_device_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + return -ENODEV; + } + return 0; +} + +static int __init swpld4_probe(struct platform_device *pdev) +{ + int ret; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld4_device_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + return -ENODEV; + } + return 0; +} + +static int __exit swpld1_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &swpld1_device_attr_grp); + return 0; +} + +static int __exit swpld2_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &swpld2_device_attr_grp); + return 0; +} + +static int __exit swpld3_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &swpld3_device_attr_grp); + return 0; +} + +static int __exit swpld4_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &swpld4_device_attr_grp); + return 0; +} + +static struct platform_driver swpld1_driver = { + .probe = swpld1_probe, + .remove = __exit_p(swpld1_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-swpld1", + }, +}; + +static struct platform_driver swpld2_driver = { + .probe = swpld2_probe, + .remove = __exit_p(swpld2_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-swpld2", + }, +}; + +static struct platform_driver swpld3_driver = { + .probe = swpld3_probe, + .remove = __exit_p(swpld3_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-swpld3", + }, +}; + +static struct platform_driver swpld4_driver = { + .probe = swpld4_probe, + .remove = __exit_p(swpld4_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-ag9064-swpld4", + }, +}; +/*---------------- CPLD - end ------------- */ + +/*---------------- module initialization ------------- */ +static int __init delta_ag9064_swpld_init(void) +{ + int ret; + printk(KERN_WARNING "ag9064_platform_swpld module initialization\n"); + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld1_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld1_driver; + } + + // register the SWPLD + ret = platform_device_register(&swpld1_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld device\n"); + goto error_swpld1_device; + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld2_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld2_driver; + } + + // register the SWPLD + ret = platform_device_register(&swpld2_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld device\n"); + goto error_swpld2_device; + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld3_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld3_driver; + } + + // register the SWPLD + ret = platform_device_register(&swpld3_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld device\n"); + goto error_swpld3_device; + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld4_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld4_driver; + } + + // register the SWPLD + ret = platform_device_register(&swpld4_device); + if (ret) { + printk(KERN_WARNING "Fail to create swpld device\n"); + goto error_swpld4_device; + } + return 0; + +error_swpld4_device: + platform_driver_unregister(&swpld4_driver); +error_swpld4_driver: + platform_device_unregister(&swpld3_device); +error_swpld3_device: + platform_driver_unregister(&swpld3_driver); +error_swpld3_driver: + platform_device_unregister(&swpld2_device); +error_swpld2_device: + platform_driver_unregister(&swpld2_driver); +error_swpld2_driver: + platform_device_unregister(&swpld1_device); +error_swpld1_device: + platform_driver_unregister(&swpld1_driver); +error_swpld1_driver: + return ret; +} + +static void __exit delta_ag9064_swpld_exit(void) +{ + platform_device_unregister(&swpld1_device); + platform_driver_unregister(&swpld1_driver); + platform_device_unregister(&swpld2_device); + platform_driver_unregister(&swpld2_driver); + platform_device_unregister(&swpld3_device); + platform_driver_unregister(&swpld3_driver); + platform_device_unregister(&swpld4_device); + platform_driver_unregister(&swpld4_driver); +} +module_init(delta_ag9064_swpld_init); +module_exit(delta_ag9064_swpld_exit); + +MODULE_DESCRIPTION("DNI ag9064 CPLD Platform Support"); +MODULE_AUTHOR("Stanley Chi "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hbm.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hbm.h new file mode 100644 index 000000000000..a2025a5083a3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hbm.h @@ -0,0 +1,62 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, Intel Corporation. + * + * 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. + * + */ + +#ifndef _MEI_HBM_H_ +#define _MEI_HBM_H_ + +struct mei_device; +struct mei_msg_hdr; +struct mei_cl; + +/** + * enum mei_hbm_state - host bus message protocol state + * + * @MEI_HBM_IDLE : protocol not started + * @MEI_HBM_STARTING : start request message was sent + * @MEI_HBM_ENUM_CLIENTS : enumeration request was sent + * @MEI_HBM_CLIENT_PROPERTIES : acquiring clients properties + * @MEI_HBM_STARTED : enumeration was completed + * @MEI_HBM_STOPPED : stopping exchange + */ +enum mei_hbm_state { + MEI_HBM_IDLE = 0, + MEI_HBM_STARTING, + MEI_HBM_ENUM_CLIENTS, + MEI_HBM_CLIENT_PROPERTIES, + MEI_HBM_STARTED, + MEI_HBM_STOPPED, +}; + +const char *mei_hbm_state_str(enum mei_hbm_state state); + +int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr); + +void mei_hbm_idle(struct mei_device *dev); +void mei_hbm_reset(struct mei_device *dev); +int mei_hbm_start_req(struct mei_device *dev); +int mei_hbm_start_wait(struct mei_device *dev); +int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl); +int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl); +int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl); +int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl); +bool mei_hbm_version_is_supported(struct mei_device *dev); +int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd); +void mei_hbm_pg_resume(struct mei_device *dev); +int mei_hbm_cl_notify_req(struct mei_device *dev, + struct mei_cl *cl, u8 request); + +#endif /* _MEI_HBM_H_ */ + diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hw.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hw.h new file mode 100644 index 000000000000..4cebde85924f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/hw.h @@ -0,0 +1,426 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, Intel Corporation. + * + * 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. + * + */ + +#ifndef _MEI_HW_TYPES_H_ +#define _MEI_HW_TYPES_H_ + +#include + +/* + * Timeouts in Seconds + */ +#define MEI_HW_READY_TIMEOUT 2 /* Timeout on ready message */ +#define MEI_CONNECT_TIMEOUT 3 /* HPS: at least 2 seconds */ + +#define MEI_CL_CONNECT_TIMEOUT 15 /* HPS: Client Connect Timeout */ +#define MEI_CLIENTS_INIT_TIMEOUT 15 /* HPS: Clients Enumeration Timeout */ + +#define MEI_IAMTHIF_STALL_TIMER 12 /* HPS */ +#define MEI_IAMTHIF_READ_TIMER 10 /* HPS */ + +#define MEI_PGI_TIMEOUT 1 /* PG Isolation time response 1 sec */ +#define MEI_D0I3_TIMEOUT 5 /* D0i3 set/unset max response time */ +#define MEI_HBM_TIMEOUT 1 /* 1 second */ + +/* + * MEI Version + */ +#define HBM_MINOR_VERSION 0 +#define HBM_MAJOR_VERSION 2 + +/* + * MEI version with PGI support + */ +#define HBM_MINOR_VERSION_PGI 1 +#define HBM_MAJOR_VERSION_PGI 1 + +/* + * MEI version with Dynamic clients support + */ +#define HBM_MINOR_VERSION_DC 0 +#define HBM_MAJOR_VERSION_DC 2 + +/* + * MEI version with disconnect on connection timeout support + */ +#define HBM_MINOR_VERSION_DOT 0 +#define HBM_MAJOR_VERSION_DOT 2 + +/* + * MEI version with notifcation support + */ +#define HBM_MINOR_VERSION_EV 0 +#define HBM_MAJOR_VERSION_EV 2 + +/* Host bus message command opcode */ +#define MEI_HBM_CMD_OP_MSK 0x7f +/* Host bus message command RESPONSE */ +#define MEI_HBM_CMD_RES_MSK 0x80 + +/* + * MEI Bus Message Command IDs + */ +#define HOST_START_REQ_CMD 0x01 +#define HOST_START_RES_CMD 0x81 + +#define HOST_STOP_REQ_CMD 0x02 +#define HOST_STOP_RES_CMD 0x82 + +#define ME_STOP_REQ_CMD 0x03 + +#define HOST_ENUM_REQ_CMD 0x04 +#define HOST_ENUM_RES_CMD 0x84 + +#define HOST_CLIENT_PROPERTIES_REQ_CMD 0x05 +#define HOST_CLIENT_PROPERTIES_RES_CMD 0x85 + +#define CLIENT_CONNECT_REQ_CMD 0x06 +#define CLIENT_CONNECT_RES_CMD 0x86 + +#define CLIENT_DISCONNECT_REQ_CMD 0x07 +#define CLIENT_DISCONNECT_RES_CMD 0x87 + +#define MEI_FLOW_CONTROL_CMD 0x08 + +#define MEI_PG_ISOLATION_ENTRY_REQ_CMD 0x0a +#define MEI_PG_ISOLATION_ENTRY_RES_CMD 0x8a +#define MEI_PG_ISOLATION_EXIT_REQ_CMD 0x0b +#define MEI_PG_ISOLATION_EXIT_RES_CMD 0x8b + +#define MEI_HBM_ADD_CLIENT_REQ_CMD 0x0f +#define MEI_HBM_ADD_CLIENT_RES_CMD 0x8f + +#define MEI_HBM_NOTIFY_REQ_CMD 0x10 +#define MEI_HBM_NOTIFY_RES_CMD 0x90 +#define MEI_HBM_NOTIFICATION_CMD 0x11 + +/* + * MEI Stop Reason + * used by hbm_host_stop_request.reason + */ +enum mei_stop_reason_types { + DRIVER_STOP_REQUEST = 0x00, + DEVICE_D1_ENTRY = 0x01, + DEVICE_D2_ENTRY = 0x02, + DEVICE_D3_ENTRY = 0x03, + SYSTEM_S1_ENTRY = 0x04, + SYSTEM_S2_ENTRY = 0x05, + SYSTEM_S3_ENTRY = 0x06, + SYSTEM_S4_ENTRY = 0x07, + SYSTEM_S5_ENTRY = 0x08 +}; + + +/** + * enum mei_hbm_status - mei host bus messages return values + * + * @MEI_HBMS_SUCCESS : status success + * @MEI_HBMS_CLIENT_NOT_FOUND : client not found + * @MEI_HBMS_ALREADY_EXISTS : connection already established + * @MEI_HBMS_REJECTED : connection is rejected + * @MEI_HBMS_INVALID_PARAMETER : invalid parameter + * @MEI_HBMS_NOT_ALLOWED : operation not allowed + * @MEI_HBMS_ALREADY_STARTED : system is already started + * @MEI_HBMS_NOT_STARTED : system not started + * + * @MEI_HBMS_MAX : sentinel + */ +enum mei_hbm_status { + MEI_HBMS_SUCCESS = 0, + MEI_HBMS_CLIENT_NOT_FOUND = 1, + MEI_HBMS_ALREADY_EXISTS = 2, + MEI_HBMS_REJECTED = 3, + MEI_HBMS_INVALID_PARAMETER = 4, + MEI_HBMS_NOT_ALLOWED = 5, + MEI_HBMS_ALREADY_STARTED = 6, + MEI_HBMS_NOT_STARTED = 7, + + MEI_HBMS_MAX +}; + + +/* + * Client Connect Status + * used by hbm_client_connect_response.status + */ +enum mei_cl_connect_status { + MEI_CL_CONN_SUCCESS = MEI_HBMS_SUCCESS, + MEI_CL_CONN_NOT_FOUND = MEI_HBMS_CLIENT_NOT_FOUND, + MEI_CL_CONN_ALREADY_STARTED = MEI_HBMS_ALREADY_EXISTS, + MEI_CL_CONN_OUT_OF_RESOURCES = MEI_HBMS_REJECTED, + MEI_CL_CONN_MESSAGE_SMALL = MEI_HBMS_INVALID_PARAMETER, + MEI_CL_CONN_NOT_ALLOWED = MEI_HBMS_NOT_ALLOWED, +}; + +/* + * Client Disconnect Status + */ +enum mei_cl_disconnect_status { + MEI_CL_DISCONN_SUCCESS = MEI_HBMS_SUCCESS +}; + +/* + * MEI BUS Interface Section + */ +struct mei_msg_hdr { + u32 me_addr:8; + u32 host_addr:8; + u32 length:9; + u32 reserved:5; + u32 internal:1; + u32 msg_complete:1; +} __packed; + + +struct mei_bus_message { + u8 hbm_cmd; + u8 data[0]; +} __packed; + +/** + * struct hbm_cl_cmd - client specific host bus command + * CONNECT, DISCONNECT, and FlOW CONTROL + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: address of the client in the driver + * @data: generic data + */ +struct mei_hbm_cl_cmd { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 data; +}; + +struct hbm_version { + u8 minor_version; + u8 major_version; +} __packed; + +struct hbm_host_version_request { + u8 hbm_cmd; + u8 reserved; + struct hbm_version host_version; +} __packed; + +struct hbm_host_version_response { + u8 hbm_cmd; + u8 host_version_supported; + struct hbm_version me_max_version; +} __packed; + +struct hbm_host_stop_request { + u8 hbm_cmd; + u8 reason; + u8 reserved[2]; +} __packed; + +struct hbm_host_stop_response { + u8 hbm_cmd; + u8 reserved[3]; +} __packed; + +struct hbm_me_stop_request { + u8 hbm_cmd; + u8 reason; + u8 reserved[2]; +} __packed; + +/** + * struct hbm_host_enum_request - enumeration request from host to fw + * + * @hbm_cmd: bus message command header + * @allow_add: allow dynamic clients add HBM version >= 2.0 + * @reserved: reserved + */ +struct hbm_host_enum_request { + u8 hbm_cmd; + u8 allow_add; + u8 reserved[2]; +} __packed; + +struct hbm_host_enum_response { + u8 hbm_cmd; + u8 reserved[3]; + u8 valid_addresses[32]; +} __packed; + +struct mei_client_properties { + uuid_le protocol_name; + u8 protocol_version; + u8 max_number_of_connections; + u8 fixed_address; + u8 single_recv_buf; + u32 max_msg_length; +} __packed; + +struct hbm_props_request { + u8 hbm_cmd; + u8 me_addr; + u8 reserved[2]; +} __packed; + +struct hbm_props_response { + u8 hbm_cmd; + u8 me_addr; + u8 status; + u8 reserved[1]; + struct mei_client_properties client_properties; +} __packed; + +/** + * struct hbm_add_client_request - request to add a client + * might be sent by fw after enumeration has already completed + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @reserved: reserved + * @client_properties: client properties + */ +struct hbm_add_client_request { + u8 hbm_cmd; + u8 me_addr; + u8 reserved[2]; + struct mei_client_properties client_properties; +} __packed; + +/** + * struct hbm_add_client_response - response to add a client + * sent by the host to report client addition status to fw + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @status: if HBMS_SUCCESS then the client can now accept connections. + * @reserved: reserved + */ +struct hbm_add_client_response { + u8 hbm_cmd; + u8 me_addr; + u8 status; + u8 reserved[1]; +} __packed; + +/** + * struct hbm_power_gate - power gate request/response + * + * @hbm_cmd: bus message command header + * @reserved: reserved + */ +struct hbm_power_gate { + u8 hbm_cmd; + u8 reserved[3]; +} __packed; + +/** + * struct hbm_client_connect_request - connect/disconnect request + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: address of the client in the driver + * @reserved: reserved + */ +struct hbm_client_connect_request { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 reserved; +} __packed; + +/** + * struct hbm_client_connect_response - connect/disconnect response + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: address of the client in the driver + * @status: status of the request + */ +struct hbm_client_connect_response { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 status; +} __packed; + + +#define MEI_FC_MESSAGE_RESERVED_LENGTH 5 + +struct hbm_flow_control { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 reserved[MEI_FC_MESSAGE_RESERVED_LENGTH]; +} __packed; + +#define MEI_HBM_NOTIFICATION_START 1 +#define MEI_HBM_NOTIFICATION_STOP 0 +/** + * struct hbm_notification_request - start/stop notification request + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: address of the client in the driver + * @start: start = 1 or stop = 0 asynchronous notifications + */ +struct hbm_notification_request { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 start; +} __packed; + +/** + * struct hbm_notification_response - start/stop notification response + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: - address of the client in the driver + * @status: (mei_hbm_status) response status for the request + * - MEI_HBMS_SUCCESS: successful stop/start + * - MEI_HBMS_CLIENT_NOT_FOUND: if the connection could not be found. + * - MEI_HBMS_ALREADY_STARTED: for start requests for a previously + * started notification. + * - MEI_HBMS_NOT_STARTED: for stop request for a connected client for whom + * asynchronous notifications are currently disabled. + * + * @start: start = 1 or stop = 0 asynchronous notifications + * @reserved: reserved + */ +struct hbm_notification_response { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 status; + u8 start; + u8 reserved[3]; +} __packed; + +/** + * struct hbm_notification - notification event + * + * @hbm_cmd: bus message command header + * @me_addr: address of the client in ME + * @host_addr: address of the client in the driver + * @reserved: reserved for alignment + */ +struct hbm_notification { + u8 hbm_cmd; + u8 me_addr; + u8 host_addr; + u8 reserved[1]; +} __packed; + +#endif diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.c new file mode 100644 index 000000000000..97c93c6122bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.c @@ -0,0 +1,636 @@ + +#include "i2c-mei_rw.h" + + +/* ========== IoLibGcc.c ========= */ + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +//__inline__ +UINT8 +IoRead8 ( + IN UINTN Port + ) +{ + UINT8 Data; + + __asm__ __volatile__ ("inb %w1,%b0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +//__inline__ +UINT8 +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + __asm__ __volatile__ ("outb %b0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value;; +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +//__inline__ +UINT16 +IoRead16 ( + IN UINTN Port + ) +{ + UINT16 Data; + + if((Port & 1) != 0) + printk("Failed\n"); + __asm__ __volatile__ ("inw %w1,%w0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 16-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +//__inline__ +UINT16 +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + if((Port & 1) != 0) + printk("Failed\n"); + __asm__ __volatile__ ("outw %w0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value;; +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +//__inline__ +UINT32 +IoRead32 ( + IN UINTN Port + ) +{ + UINT32 Data; + + if((Port & 3) != 0) + printk("Failed\n"); + __asm__ __volatile__ ("inl %w1,%0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +//__inline__ +UINT32 +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + if((Port & 3) != 0) + printk("Failed\n"); + __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value; +} + + + +/* ========== GccInline.c ========= */ + +/** + Enables CPU interrupts. + + Enables CPU interrupts. + +**/ +VOID +EnableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("sti"::: "memory"); +} + +/** + Disables CPU interrupts. + + Disables CPU interrupts. + +**/ +VOID +DisableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("cli"::: "memory"); +} + +/** + Reads the current value of the EFLAGS register. + + Reads and returns the current value of the EFLAGS register. This function is + only available on IA-32 and X64. This returns a 32-bit value on IA-32 and a + 64-bit value on X64. + + @return EFLAGS on IA-32 or RFLAGS on X64. + +**/ +UINTN +AsmReadEflags ( + VOID + ) +{ + UINTN Eflags; + + __asm__ __volatile__ ( + "pushfq \n\t" + "pop %0 " + : "=r" (Eflags) // %0 + ); + + return Eflags; +} + + + +/* ========== X86GetInterruptState.c ========= */ + +/** + Retrieves the current CPU interrupt state. + + Returns TRUE is interrupts are currently enabled. Otherwise + returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +GetInterruptState ( + VOID + ) +{ + IA32_EFLAGS32 EFlags; + + EFlags.UintN = AsmReadEflags (); + return (BOOLEAN)(1 == EFlags.Bits.IF); +} + + + +/* ========== Cpu.c ========= */ + +/** + Disables CPU interrupts and returns the interrupt state prior to the disable + operation. + + @retval TRUE CPU interrupts were enabled on entry to this call. + @retval FALSE CPU interrupts were disabled on entry to this call. + +**/ +BOOLEAN +SaveAndDisableInterrupts ( + VOID + ) +{ + BOOLEAN InterruptState; + + InterruptState = GetInterruptState (); + DisableInterrupts (); + return InterruptState; +} + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should be enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +SetInterruptState ( + IN BOOLEAN InterruptState + ) +{ + if (InterruptState) { + EnableInterrupts (); + } else { + DisableInterrupts (); + } + return InterruptState; +} + + + +/* ========== pciLib.c ========= */ + +// +// Declare I/O Ports used to perform PCI Confguration Cycles +// +#define PCI_CONFIGURATION_ADDRESS_PORT 0xCF8 +#define PCI_CONFIGURATION_DATA_PORT 0xCFC + +/** + Convert a PCI Library address to PCI CF8 formatted address. + + Declare macro to convert PCI Library address to PCI CF8 formatted address. + Bit fields of PCI Library and CF8 formatted address is as follows: + PCI Library formatted address CF8 Formatted Address + ============================= ====================== + Bits 00..11 Register Bits 00..07 Register + Bits 12..14 Function Bits 08..10 Function + Bits 15..19 Device Bits 11..15 Device + Bits 20..27 Bus Bits 16..23 Bus + Bits 28..31 Reserved(MBZ) Bits 24..30 Reserved(MBZ) + Bits 31..31 Must be 1 + + @param A The address to convert. + + @retval The coverted address. + +**/ +#define PCI_TO_CF8_ADDRESS(A) \ + ((UINT32) ((((A) >> 4) & 0x00ffff00) | ((A) & 0xfc) | 0x80000000)) + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +PciCf8Read8 ( + IN UINTN Address + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoRead8 (PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3)); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +PciCf8Write8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT8 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoWrite8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +PciCf8Read16 ( + IN UINTN Address + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoRead16 (PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2)); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +PciCf8Write16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT16 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoWrite16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +PciCf8Read32 ( + IN UINTN Address + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoRead32 (PCI_CONFIGURATION_DATA_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address The address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +PciCf8Write32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + BOOLEAN InterruptState; + UINT32 AddressPort; + UINT32 Result; + + InterruptState = SaveAndDisableInterrupts (); + AddressPort = IoRead32 (PCI_CONFIGURATION_ADDRESS_PORT); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + Result = IoWrite32 ( + PCI_CONFIGURATION_DATA_PORT, + Value + ); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, AddressPort); + SetInterruptState (InterruptState); + return Result; +} + + + +/* ========== Other ========= */ + +// UINT8 PciRead8(UINT64 addr) +// { +// printf("[%s] addr: %8X.\n", __func__, addr); +// return 0x01; +// } + +// UINT8 PciWrite8(UINT64 addr, UINT8 data) +// { +// printf("[%s] addr: %8X data: %2X.\n", __func__, addr, data); +// return 0x02; +// } + + +// UINT16 PciRead16(UINT64 addr) +// { +// printf("[%s] addr: %8X.\n", __func__, addr); +// return 0x03; +// } + +// UINT16 PciWrite16(UINT64 addr, UINT8 data) +// { +// printf("[%s] addr: %8X data: %2X.\n", __func__, addr, data); +// return 0x04; +// } + + +// UINT32 PciRead32(UINT64 addr) +// { +// printf("[%s] addr: %8X.\n", __func__, addr); +// return 0x05; +// } + +// UINT32 PciWrite32(UINT64 addr, UINT8 data) +// { +// printf("[%s] addr: %8X data: %2X.\n", __func__, addr, data); +// return 0x06; +// } + +UINT8 PciRead8(UINT64 addr) +{ + return PciCf8Read8 (addr); +} + +UINT8 PciWrite8(UINT64 addr, UINT8 data) +{ + return PciCf8Write8 (addr, data); +} + + +UINT16 PciRead16(UINT64 addr) +{ + return PciCf8Read16 (addr); +} + +UINT16 PciWrite16(UINT64 addr, UINT8 data) +{ + return PciCf8Write16 (addr, data); +} + + +UINT32 PciRead32(UINT64 addr) +{ + return PciCf8Read32 (addr); +} + +UINT32 PciWrite32(UINT64 addr, UINT8 data) +{ + return PciCf8Write32 (addr, data); +} diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.h new file mode 100644 index 000000000000..5180cc47e736 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_io.h @@ -0,0 +1,46 @@ + +#include "i2c-mei_type.h" + + + +/* ========== PciLib.h ========= */ + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + address that can be passed to the PCI Library functions. + + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..255 for PCI. Range 0..4095 + for PCI Express. + + @return The encoded PCI address. + +**/ +#define PCI_LIB_ADDRESS(Bus,Device,Function,Register) \ + (((Register) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20)) + + + +/* ========== Qubbing ========= */ + +UINT8 PciRead8(UINT64 addr); + +UINT8 PciWrite8(UINT64 addr, UINT8 data); + +UINT16 PciRead16(UINT64 addr); + +UINT16 PciWrite16(UINT64 addr, UINT8 data); + +UINT32 PciRead32(UINT64 addr); + +UINT32 PciWrite32(UINT64 addr, UINT8 data); + + +void I2C_Set(UINT8 smbus, UINT8 daddr, INT32 reg, UINT8 *data, UINT8 dlen); + +void I2C_Read(UINT8 smbus, UINT8 daddr, INT32 reg, UINT8 dlen); + +void VersionRead(void); +void I2C_Probe(void); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_main.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_main.c new file mode 100644 index 000000000000..811877fa8ead --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_main.c @@ -0,0 +1,579 @@ +/* + * MEI-I2C driver + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mei_dev.h" +#include "client.h" +#include "i2c-mei_rw.h" + +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI +#include +#include +#endif + +/* PCI Address Constants */ +#define SMBBAR 0 +#define SMBPCICTL 0x004 +#define SMBPCISTS 0x006 +#define SMBHSTCFG 0x040 +#define TCOBASE 0x050 +#define TCOCTL 0x054 + +/* Other settings */ +#define MAX_RETRIES 400 + +/* I801 command constants */ +#define I801_QUICK 0x00 +#define I801_BYTE 0x04 +#define I801_BYTE_DATA 0x08 +#define I801_WORD_DATA 0x0C +#define I801_PROC_CALL 0x10 /* unimplemented */ +#define I801_BLOCK_DATA 0x14 +#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ + +#define HECI_PEC_FLAG 0x80 + +#define PCI_DEVICE_ID_INTEL_LPT_H 0x8C3A /* Lynx Point H */ + +struct mei_i2c_mux_config { + char *gpio_chip; + unsigned values[3]; + int n_values; + unsigned classes[3]; + unsigned gpios[2]; /* Relative to gpio_chip->base */ + int n_gpios; +}; + +#define FEATURE_SMBUS_PEC (1 << 0) +#define FEATURE_BLOCK_BUFFER (1 << 1) +#define FEATURE_BLOCK_PROC (1 << 2) +#define FEATURE_I2C_BLOCK_READ (1 << 3) +#define FEATURE_IRQ (1 << 4) +/* Not really a feature, but it's convenient to handle it as such */ +#define FEATURE_IDF (1 << 15) +#define FEATURE_TCO (1 << 16) + +static const char *mei_i2c_feature_names[] = { + "SMBus PEC", + "Block buffer", + "Block process call", + "I2C block read", + "Interrupt", +}; + +static unsigned int disable_features; +module_param(disable_features, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(disable_features, "Disable selected driver features:\n" + "\t\t 0x01 disable SMBus PEC\n" + "\t\t 0x02 disable the block buffer\n" + "\t\t 0x08 disable the I2C block read functionality\n" + "\t\t 0x10 don't use interrupts "); + + +/*MEI SMB Sensor Bus (when MEI_FLAG_SMB_DEV_ADD_FMAT_EXT)*/ +#define MEI_SMB_BUS_SMBUS 0x0 +#define MEI_SMB_BUS_SMLINK0 0x1 +#define MEI_SMB_BUS_SMLINK1 0x2 +#define MEI_SMB_BUS_SMLINK2 0x3 +#define MEI_SMB_BUS_SMLINK3 0x4 +#define MEI_SMB_BUS_SMLINK4 0x5 + +struct mei_smb_priv{ + struct i2c_adapter adapter; + unsigned long smba; + unsigned char original_hstcfg; + struct pci_dev *pci_dev; + unsigned int features; + unsigned char sensorbus; + /* isr processing */ + wait_queue_head_t waitq; + u8 status; + /* Command state used by isr for byte-by-byte block transactions */ + u8 cmd; + bool is_read; + int count; + int len; + u8 *data; +}; + + +struct mei_i2c_data_ext{ + char Cmd; + char Flag; + char Sensor_Bus; + char Psu_Addr; + char Mux_Addr; + char Mux_Channel; + char Mux_Conf; + char Reserved; + char W_Length; + char R_Length; + char PMbus_data[21]; +}; + +struct mei_msg{ + struct mei_msg_hdr hdr; + struct mei_i2c_data_ext data; +}; + +#define DEBUG_MSG 0 +static int mei_TxRx(u8 sensor_bus, u16 addr, u8 command, char read_write, int size, union i2c_smbus_data * data, int pec) +{ + struct mei_msg_hdr mei_hdr; + int rets; + unsigned char * recv_buf; + int retry = 0; + int len = 0; + int i = 0; + + struct mei_msg * msg; +// unsigned char blen; + + UINT32 timeout, dwTimeout; + UINT32 blen; + HECI_DEVICE sHeciDev; + + recv_buf = kmalloc(sizeof(unsigned char) * (32), GFP_KERNEL); + msg = kmalloc(sizeof(struct mei_msg), GFP_KERNEL); + + dwTimeout = 2000000 / HECI_TIMEOUT_UNIT; + + sHeciDev.Bus = HECI_BUS; + sHeciDev.Dev = HECI_DEV; + sHeciDev.Fun = HECI_FUN; + sHeciDev.Hidm = HECI_HIDM_MSI; + sHeciDev.Mbar = HECI_MBAR_DEFAULT; + HeciInit(&sHeciDev, &dwTimeout); + + msg->data.Cmd = 0x0A; + if(read_write){ + if(size == I2C_SMBUS_WORD_DATA){ + msg->data.Flag = 0x56; + msg->data.W_Length = 1; + msg->data.R_Length = 2; + } + else if(size == I2C_SMBUS_BYTE_DATA || size == I2C_SMBUS_QUICK){ + msg->data.Flag = 0x52; + msg->data.W_Length = 1; + msg->data.R_Length = 1; + }else if(size == I2C_SMBUS_BYTE){ + msg->data.Flag = 0x50; + msg->data.W_Length = 0; + msg->data.R_Length = 1; + }else if(size == I2C_SMBUS_BLOCK_DATA){ + msg->data.Flag = 0x5A; + msg->data.W_Length = 1; + } + + } + else{ + if(size == I2C_SMBUS_WORD_DATA){ + msg->data.Flag = 0x58; + msg->data.W_Length = 3; + } + else if(size == I2C_SMBUS_BYTE_DATA){ + msg->data.Flag = 0x54; + msg->data.W_Length = 2; + } + else if((size == I2C_SMBUS_BYTE) || (size == I2C_SMBUS_QUICK)){ + msg->data.Flag = 0x50; + msg->data.W_Length = 1; + }else if(size == I2C_SMBUS_BLOCK_DATA){ + msg->data.Flag = 0x5C; + msg->data.W_Length = data->block[0]; + } + + msg->data.R_Length = 0x0; + if(data !=NULL){ + if(size == I2C_SMBUS_WORD_DATA){ + msg->data.PMbus_data[1] = data->word & 0xff; + msg->data.PMbus_data[2] = (data->word & 0xff00) >> 8; + }else if(size == I2C_SMBUS_BYTE_DATA){ + msg->data.PMbus_data[1] = data->byte; + }else if(size == I2C_SMBUS_BLOCK_DATA){ + for (i = 0; i < msg->data.W_Length; i++) + msg->data.PMbus_data[i+1] = data->block[i+1]; + } + + }else{ + msg->data.PMbus_data[1] = 0; + } + } + + if (pec == 1) + msg->data.Flag |= HECI_PEC_FLAG; + + msg->data.Sensor_Bus = sensor_bus; + msg->data.Psu_Addr =(char) addr << 1; + msg->data.Mux_Addr = 0x0; + msg->data.Mux_Channel = 0x0; + msg->data.Mux_Conf = 0x0; + msg->data.Reserved = 0x0; + msg->data.PMbus_data[0] = command; + + + msg->hdr.host_addr = 0;//mei_cl_host_addr(cl); + msg->hdr.me_addr = 0x20; + msg->hdr.reserved = 0; + msg->hdr.msg_complete = 0; + msg->hdr.internal = 0; //cb->internal; + msg->hdr.length = 10 + msg->data.W_Length; + msg->hdr.msg_complete = 1; + +#if (DEBUG_MSG) + printk("Cmd : 0x%02x , Flag : 0x%02x , Sensor_Bus : 0x%02x , Psu_Addr : 0x%02x\n" , msg->data.Cmd, msg->data.Flag, msg->data.Sensor_Bus, msg->data.Psu_Addr); + printk("Mux_Addr : 0x%02x , Mux_Channel : 0x%02x , Mux_Conf : 0x%02x , W_Length : 0x%02x\n" , msg->data.Mux_Addr, msg->data.Mux_Channel, msg->data.Mux_Conf, msg->data.W_Length); + printk("R_Length : 0x%02x , PMbus_data[0] : 0x%02x , size : 0x%x\n" , msg->data.R_Length, msg->data.PMbus_data[0], size); + if(!read_write){ + if(size == I2C_SMBUS_BLOCK_DATA){ + for (i = 0; i < msg->data.W_Length; i++){ + printk("PMbus_data[%d] : 0x%02x , ", i, msg->data.PMbus_data[i]); + } + printk("\n"); + }else{ + printk("PMbus_data[1] : 0x%02x , PMbus_data[2] : 0x%02x\n", msg->data.PMbus_data[1], msg->data.PMbus_data[2]); + } + } +#endif + retry = 3; + while(retry){ + timeout = HECI_SEND_TIMEOUT / HECI_TIMEOUT_UNIT; + rets = HeciMsgSend(&sHeciDev, &timeout, (HECI_MSG_HEADER *)msg); + if (rets != 0){ + printk("HeciMsgSend ret: %d\n",rets); + retry --; + continue; + }else{ + break; + } + } + if(read_write) + { + if(size == I2C_SMBUS_WORD_DATA){ + blen = 8; + HeciMsgRecv(&sHeciDev, &timeout, (HECI_MSG_HEADER *)recv_buf, &blen); + } + else if(size == I2C_SMBUS_BYTE_DATA || size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE){ + blen = 7; + HeciMsgRecv(&sHeciDev, &timeout, (HECI_MSG_HEADER *)recv_buf, &blen); + } +#if (DEBUG_MSG) + if(size == I2C_SMBUS_BLOCK_DATA){ + printk("recv_len %d hdr: 0x%02x%02x%02x%02x\n", blen, recv_buf[3], recv_buf[2], recv_buf[1], recv_buf[0]); + for (i = 0; i < blen ; i++){ + printk("0x%02x , ", recv_buf[4 + i]); + } + printk("\n"); + }else{ + printk("recv_len %d recv: 0x%02x%02x%02x%02x\n0x%02x , 0x%02x , 0x%02x, 0x%02x \n", blen, recv_buf[3], recv_buf[2], recv_buf[1], recv_buf[0], recv_buf[4], recv_buf[5], recv_buf[6], recv_buf[7]); + } +#endif + if(data !=NULL){ + if(size == I2C_SMBUS_WORD_DATA){ + data->word = ((recv_buf[7] << 8) & 0xff00) | (recv_buf[6] & 0xff); + } + else if(size == I2C_SMBUS_BYTE_DATA){ + data->byte = recv_buf[6] & 0xff; + } + else if(size == I2C_SMBUS_BLOCK_DATA){ + for (i = 0; i < blen; i++){ + data->block[i] = recv_buf[6+i] & 0xff; + } + } + } + } + else + { + blen = 6; + HeciMsgRecv(&sHeciDev, &timeout, (HECI_MSG_HEADER *)recv_buf, &blen); +#if (DEBUG_MSG) + printk("recv: 0x%02x%02x%02x%02x , 0x%02x , 0x%02x \n", recv_buf[3], recv_buf[2], recv_buf[1], recv_buf[0], recv_buf[4], recv_buf[5]); +#endif + } + + rets = recv_buf[5]; + + kfree(recv_buf); + kfree(msg); + if(rets) + return -1; + else + return 0; +} + +/* Return negative errno on error. */ +static s32 mei_i2c_access(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data *data) +{ + int hwpec; + int block = 0; + int ret = 0, xact = 0; + int pec = 0; + char byte = 0; + struct mei_smb_priv *priv = i2c_get_adapdata(adap); + + if (flags & I2C_CLIENT_PEC) + pec = 1; + + switch (size) { + case I2C_SMBUS_QUICK: + + command = 0; + read_write = 1; + ret = mei_TxRx(priv->sensorbus, addr, command, read_write, size, NULL, pec); + xact = I801_QUICK; + break; + case I2C_SMBUS_BYTE: + if (read_write == I2C_SMBUS_READ) + command = 0; + ret = mei_TxRx(priv->sensorbus, addr, command, read_write, size, data, pec); + xact = I801_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + ret = mei_TxRx(priv->sensorbus, addr, command, read_write, size, data, pec); + xact = I801_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + ret = mei_TxRx(priv->sensorbus, addr, command, read_write, size, data, pec); + xact = I801_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + ret = mei_TxRx(priv->sensorbus, addr, command, read_write, size, data, pec); + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + printk("I2C_SMBUS_I2C_BLOCK_DATA unsupported!!%d\n",size); + break; + default: + dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n", + size); + return -EOPNOTSUPP; + } + + if (ret) + return ret; + return 0; +} + +static u32 mei_i2c_func(struct i2c_adapter *adapter) +{ + struct mei_smb_priv *priv = i2c_get_adapdata(adapter); + + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA ; +} + +static const struct i2c_algorithm smbus_algorithm = { + .smbus_xfer = mei_i2c_access, + .functionality = mei_i2c_func, +}; + +static const struct pci_device_id mei_i2c_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LPT_H) }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, mei_i2c_ids); + +/* richard + priv_table */ +struct mei_smb_priv_table { + struct mei_smb_priv *priv_tbl[MEI_SMB_BUS_SMLINK4]; + int count; +}; + +static int mei_i2c_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + unsigned char temp; + int err, i; + struct mei_smb_priv *priv_sml_0, *priv_sml_1, *priv_sml_2, *priv_sml_3, *priv_sml_4, *priv_smb; + +//richard + priv_table + struct mei_smb_priv_table *priv_table; + + priv_table = kzalloc(sizeof(*priv_table), GFP_KERNEL); + if(!priv_table) + return -ENOMEM; + + priv_sml_0= kzalloc(sizeof(struct mei_smb_priv), GFP_KERNEL); + if (!priv_sml_0) + return -ENOMEM; + i2c_set_adapdata(&priv_sml_0->adapter, priv_sml_0); + priv_sml_0->adapter.owner = THIS_MODULE; + priv_sml_0->adapter.algo = &smbus_algorithm; + priv_sml_0->adapter.dev.parent = &pdev->dev; + priv_sml_0->adapter.retries = 3; + priv_sml_0->sensorbus = MEI_SMB_BUS_SMLINK0; + priv_sml_0->pci_dev = pdev; + + priv_sml_1 = kzalloc(sizeof(*priv_sml_1), GFP_KERNEL); + if (!priv_sml_1) + return -ENOMEM; + i2c_set_adapdata(&priv_sml_1->adapter, priv_sml_1); + priv_sml_1->adapter.owner = THIS_MODULE; + priv_sml_1->adapter.algo = &smbus_algorithm; + priv_sml_1->adapter.dev.parent = &pdev->dev; + priv_sml_1->adapter.retries = 3; + priv_sml_1->sensorbus = MEI_SMB_BUS_SMLINK1; + priv_sml_1->pci_dev = pdev; + + priv_sml_2 = kzalloc(sizeof(*priv_sml_2), GFP_KERNEL); + if (!priv_sml_2) + return -ENOMEM; + i2c_set_adapdata(&priv_sml_2->adapter, priv_sml_2); + priv_sml_2->adapter.owner = THIS_MODULE; + priv_sml_2->adapter.algo = &smbus_algorithm; + priv_sml_2->adapter.dev.parent = &pdev->dev; + priv_sml_2->adapter.retries = 3; + priv_sml_2->sensorbus = MEI_SMB_BUS_SMLINK2; + priv_sml_2->pci_dev = pdev; + + priv_sml_3 = kzalloc(sizeof(*priv_sml_3), GFP_KERNEL); + if (!priv_sml_3) + return -ENOMEM; + i2c_set_adapdata(&priv_sml_3->adapter, priv_sml_3); + priv_sml_3->adapter.owner = THIS_MODULE; + priv_sml_3->adapter.algo = &smbus_algorithm; + priv_sml_3->adapter.dev.parent = &pdev->dev; + priv_sml_3->adapter.retries = 3; + priv_sml_3->sensorbus = MEI_SMB_BUS_SMLINK3; + priv_sml_3->pci_dev = pdev; + + priv_sml_4 = kzalloc(sizeof(*priv_sml_4), GFP_KERNEL); + if (!priv_sml_4) + return -ENOMEM; + i2c_set_adapdata(&priv_sml_4->adapter, priv_sml_4); + priv_sml_4->adapter.owner = THIS_MODULE; + priv_sml_4->adapter.algo = &smbus_algorithm; + priv_sml_4->adapter.dev.parent = &pdev->dev; + priv_sml_4->adapter.retries = 3; + priv_sml_4->sensorbus = MEI_SMB_BUS_SMLINK4; + priv_sml_4->pci_dev = pdev; + + printk("mei_i2c_probe 0x%x 0x%x\n", pdev->device, pdev->dev.id); + + snprintf(priv_sml_0->adapter.name, sizeof(priv_sml_0->adapter.name), + "ME-SMLINK0"); + err = i2c_add_adapter(&priv_sml_0->adapter); + printk("i2c nr : %d \n", priv_sml_0->adapter.nr); + if (err) { + dev_err(&pdev->dev, "Failed to add SMBus adapter ME-SMLINK0\n"); + return err; + } + + snprintf(priv_sml_1->adapter.name, sizeof(priv_sml_1->adapter.name), + "ME-SMLINK1"); + err = i2c_add_adapter(&priv_sml_1->adapter); + if (err) { + dev_err(&pdev->dev, "Failed to add SMBus adapter ME-SMLINK1\n"); + return err; + } + + snprintf(priv_sml_2->adapter.name, sizeof(priv_sml_2->adapter.name), + "ME-SMLINK2"); + err = i2c_add_adapter(&priv_sml_2->adapter); + if (err) { + dev_err(&pdev->dev, "Failed to add SMBus adapter ME-SMLINK2\n"); + return err; + } + + snprintf(priv_sml_3->adapter.name, sizeof(priv_sml_3->adapter.name), + "ME-SMLINK3"); + err = i2c_add_adapter(&priv_sml_3->adapter); + if (err) { + dev_err(&pdev->dev, "Failed to add SMBus adapter ME-SMLINK3\n"); + return err; + } + + snprintf(priv_sml_4->adapter.name, sizeof(priv_sml_4->adapter.name), + "ME-SMLINK4"); + err = i2c_add_adapter(&priv_sml_4->adapter); + if (err) { + dev_err(&pdev->dev, "Failed to add SMBus adapter ME-SMLINK4\n"); + return err; + } + + priv_table->count = 0; + priv_table->priv_tbl[priv_table->count++] = priv_sml_0; + priv_table->priv_tbl[priv_table->count++] = priv_sml_1; + priv_table->priv_tbl[priv_table->count++] = priv_sml_2; + priv_table->priv_tbl[priv_table->count++] = priv_sml_3; + priv_table->priv_tbl[priv_table->count++] = priv_sml_4; + + pci_set_drvdata(pdev, priv_table); + + return 0; +} + +static void mei_i2c_remove(struct pci_dev *dev) +{ + struct mei_smb_priv *priv = pci_get_drvdata(dev); + // richard + priv_table + struct mei_smb_priv_table *priv_table = pci_get_drvdata(dev); + int i; + + for(i=0; icount; i++) { + i2c_del_adapter(&priv_table->priv_tbl[i]->adapter); + } + pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); + + /* + * do not call pci_disable_device(dev) since it can cause hard hangs on + * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010) + */ +} + +#define mei_i2c_suspend NULL +#define mei_i2c_resume NULL + +static struct pci_driver mei_i2c_driver = { + .name = "mei_i2c", + .id_table = mei_i2c_ids, + .probe = mei_i2c_probe, + .remove = mei_i2c_remove, + .suspend = mei_i2c_suspend, + .resume = mei_i2c_resume, +}; + +static int __init mei_i2c_init(void) +{ + int ret = 16; + u32 status = 0; + struct pci_dev *pdev = NULL; + struct mei_device *dev; + struct pci_driver *pci_drv; + + return pci_register_driver(&mei_i2c_driver); +} + +static void __exit mei_i2c_exit(void) +{ + pci_unregister_driver(&mei_i2c_driver); +} + +MODULE_AUTHOR("Delta Networks, Inc."); +MODULE_DESCRIPTION("MEI SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(mei_i2c_init); +module_exit(mei_i2c_exit); diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.c b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.c new file mode 100644 index 000000000000..215df220f096 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.c @@ -0,0 +1,591 @@ +#include "i2c-mei_rw.h" + +#define MicroSecondDelay(time) udelay(time) + +/****** Parameter *****/ + +/****** Struct *****/ +typedef struct +{ + volatile UINT32 CB_WW; // Circular Buffer Write Window + volatile UINT32 H_CSR; // Host Control and Status Register + volatile UINT32 CB_RW; // Circular Buffer Read Window + volatile UINT32 ME_CSR; // ME Control and Status Register (read only) +} HECI_MBAR_REGS; + + +typedef union +{ + UINT32 DWord; + struct + { + UINT32 H_IE : 1, // 0 - Interrupt Enable ME + H_IS : 1, // 1 - Interrupt Status ME + H_IG : 1, // 2 - Interrupt Generate + H_RDY : 1, // 3 - Ready + H_RST : 1, // 4 - Reset + Reserved: 3, // 5~7 + H_CBRP : 8, // 8~15 - CB Read Pointer + H_CBWP : 8, // 16~23 - CB Write Pointer + H_CBD : 8; // 24~31 - Circular Buffer Depth + } Bits; +} HECI_HOST_CSR; + +// HECI_MBAR_REGS::ME_CSR - ME Control and Status Register +typedef union +{ + UINT32 DWord; + struct + { + UINT32 ME_IE : 1, // 0 - Interrupt Enable (Host Read Access) + ME_IS : 1, // 1 - Interrupt Status (Host Read Access) + ME_IG : 1, // 2 - Interrupt Generate (Host Read Access) + ME_RDY : 1, // 3 - Ready (Host Read Access) + ME_RST : 1, // 4 - Reset (Host Read Access) + Reserved: 3, // 5~7 + ME_CBRP : 8, // 8~15 - CB Read Pointer (Host Read Access) + ME_CBWP : 8, // 16~23 - CB Write Pointer (Host Read Access) + ME_CBD : 8; // 24~31 - Circular Buffer Depth (Host Read Access) + } Bits; +} HECI_ME_CSR; + +/****** Function *****/ +VOID* HeciMbarRead(IN HECI_DEVICE *pThis); +VOID HeciTrace(IN HECI_DEVICE*, IN CHAR8*, IN HECI_MSG_HEADER*, IN INT32); + +EFI_STATUS HeciInit ( HECI_DEVICE *pThis, + UINT32 *pTimeout) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 Timeout = 0; + HECI_HOST_CSR sHCsr; + HECI_ME_CSR sMeCsr; + HECI_MBAR_REGS *pMbarRegs; + VOID *pAddrPoint; + + if (pThis == NULL || (pThis->Mbar & 0xF) != 0 || pThis->Hidm > HECI_HIDM_LAST) + { + printk("Heci Init Failed"); + return EFI_INVALID_PARAMETER; + } + if (pTimeout != NULL) + { + Timeout = *pTimeout; + } + + // HECI vendor and device information away + pThis->PciCfg = PCI_LIB_ADDRESS(pThis->Bus, pThis->Dev, pThis->Fun, 0); + pThis->Vid = PciRead16(pThis->PciCfg + HECI_REG_VENDORID); + pThis->Did = PciRead16(pThis->PciCfg + HECI_REG_DEVICEID); + + if (pThis->Vid != 0x8086) + { + printk("[HECI] Init failed, PCI device %d/%d/%d not valid HECI (%2X-%2X)\n", + pThis->Bus, pThis->Dev, pThis->Fun, pThis->Vid, pThis->Did); + return EFI_DEVICE_ERROR; + } + + // Check MBAR, + pAddrPoint = HeciMbarRead(pThis); + pMbarRegs = (HECI_MBAR_REGS*)ioremap_nocache(pAddrPoint, 0x1000); + if (pMbarRegs == NULL) + { + printk("[HECI-%d] Init failed (device disabled)\n", pThis->Fun); + printk("Check MBAR Failed"); + Status = EFI_DEVICE_ERROR; + goto GO_FAIL; + } + + // Set HECI interrupt delivery mode. + sHCsr.DWord = pMbarRegs->H_CSR; + sHCsr.Bits.H_IE = 0; + pMbarRegs->H_CSR = sHCsr.DWord; + PciWrite8(pThis->PciCfg + HECI_REG_HIDM, pThis->Hidm); + + // Check HECI was free + sMeCsr.DWord = pMbarRegs->ME_CSR; + if (!sMeCsr.Bits.ME_RDY) + { + Status = HecClearQue(pThis, &Timeout); + } + else + { + if (!sHCsr.Bits.H_RDY) + { + sHCsr.Bits.H_IG = 1; + sHCsr.Bits.H_RDY = 1; + sHCsr.Bits.H_RST = 0; + pMbarRegs->H_CSR = sHCsr.DWord; + } + pThis->HMtu = sHCsr.Bits.H_CBD * sizeof(UINT32) - sizeof(HECI_MSG_HEADER); + pThis->MeMtu = sMeCsr.Bits.ME_CBD * sizeof(UINT32) - sizeof(HECI_MSG_HEADER); + } + + GO_FAIL: + if (pTimeout != NULL) + { + *pTimeout = Timeout; + } + pThis->Mefs1.DWord = HeciPciReadMefs1(); + iounmap((VOID *)pMbarRegs); + return Status; +} + +EFI_STATUS HecClearQue ( HECI_DEVICE *pThis, + UINT32 *pTimeout) +{ + EFI_STATUS Status; + UINT32 Timeout = 0; + HECI_HOST_CSR sHCsr; + HECI_ME_CSR sMeCsr; + HECI_MBAR_REGS *pMbarRegs; + VOID *pAddrPoint; + + if (pThis == NULL) + { + printk("Failed"); + return EFI_INVALID_PARAMETER; + } + + // Check for HECI availability on PCI + pAddrPoint = HeciMbarRead(pThis); + pMbarRegs = (HECI_MBAR_REGS*)ioremap_nocache(pAddrPoint, 0x1000); + printk("pMbarRegs: %x\n", pMbarRegs); + + if (pMbarRegs == NULL) + { + printk("[HECI-%d] Reset failed (device disabled)\n", pThis->Fun); + printk("Failed"); + return EFI_DEVICE_ERROR; + } + if (pTimeout != NULL) + { + Timeout = *pTimeout; + } + printk("[HECI-%d] Resetting HECI interface (CSR %X/%X)\n", + pThis->Fun, pMbarRegs->H_CSR, pMbarRegs->ME_CSR); + + sHCsr.DWord = pMbarRegs->H_CSR; + if (!sHCsr.Bits.H_RST) + { + sHCsr.Bits.H_RST = 1; + sHCsr.Bits.H_IG = 1; + pMbarRegs->H_CSR = sHCsr.DWord; + } + + // Wait for H_RDY cleared to make sure that the reset started. + while (1) + { + sHCsr.DWord = pMbarRegs->H_CSR; + if (!sHCsr.Bits.H_RDY) + { + break; + } + if (Timeout == 0) + { + printk("[HECI-%d] Reset failed (timeout)(CSR %X/%X)\n", + pThis->Fun, pMbarRegs->H_CSR, pMbarRegs->ME_CSR); + Status = EFI_TIMEOUT; + goto GO_FAIL; + } + MicroSecondDelay(HECI_TIMEOUT_UNIT); + Timeout--; + } + + // Wait for ME to perform reset and signal it is ready. + while (1) + { + sMeCsr.DWord = pMbarRegs->ME_CSR; + if (sMeCsr.Bits.ME_RDY) + { + break; + } + if (Timeout == 0) + { + printk("[HECI-%d] Reset failed (timeout)(CSR %X/%X)\n", + pThis->Fun, pMbarRegs->H_CSR, pMbarRegs->ME_CSR); + Status = EFI_TIMEOUT; + goto GO_FAIL; + } + MicroSecondDelay(HECI_TIMEOUT_UNIT); + Timeout--; + } + + // ME side is ready, signal host side is ready too. + sHCsr.DWord = pMbarRegs->H_CSR; + sHCsr.Bits.H_RST = 0; + sHCsr.Bits.H_RDY = 1; + sHCsr.Bits.H_IG = 1; + pMbarRegs->H_CSR = sHCsr.DWord; + + // Update MTU, ME could change it during reset. + pThis->HMtu = sHCsr.Bits.H_CBD * sizeof(UINT32) - sizeof(HECI_MSG_HEADER); + pThis->MeMtu = sMeCsr.Bits.ME_CBD * sizeof(UINT32) - sizeof(HECI_MSG_HEADER); + Status = EFI_SUCCESS; + +GO_FAIL: + if (pTimeout != NULL) + { + *pTimeout = Timeout; + } + pThis->Mefs1.DWord = HeciPciReadMefs1(); + iounmap((VOID *)pMbarRegs); + return Status; +} + +EFI_STATUS HeciMsgRecv ( HECI_DEVICE *pThis, + UINT32 *pTimeout, + HECI_MSG_HEADER *pMsgBuf, + UINT32 *pBufLen ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINT32 Timeout = 0; + UINT32 DWord, dwDataReads, dwBufLen; + UINT8 bFilledSlots, bMsgLen = 0; + HECI_HOST_CSR sHCsr; + HECI_ME_CSR sMeCsr; + HECI_MBAR_REGS *pMbarRegs; + VOID *pAddrPoint; + + if (pThis == NULL || pMsgBuf == NULL || + pBufLen == NULL || *pBufLen < sizeof(HECI_MSG_HEADER)) + { + printk("Heci MsgRecv Failed\n"); + return EFI_INVALID_PARAMETER; + } + + // Check for HECI availability on PCI + pAddrPoint = HeciMbarRead(pThis); + pMbarRegs = (HECI_MBAR_REGS*)ioremap_nocache(pAddrPoint, 0x1000); + if (pMbarRegs == NULL) + { + printk("[HECI-%d] Receive failed (device disabled)\n", pThis->Fun); + printk("pMbarRegs Failed\n"); + return EFI_DEVICE_ERROR; + } + if (pTimeout != NULL) + { + Timeout = *pTimeout; + } + + + // read from queue. + dwBufLen = *pBufLen; + *pBufLen = dwDataReads = 0; + while (1) + { + sHCsr.DWord = pMbarRegs->H_CSR; + sMeCsr.DWord = pMbarRegs->ME_CSR; + + bFilledSlots = (UINT8)((INT8)sMeCsr.Bits.ME_CBWP - (INT8)sMeCsr.Bits.ME_CBRP); + // Is it ready ? + if (!sMeCsr.Bits.ME_RDY || !sHCsr.Bits.H_RDY || bFilledSlots > sHCsr.Bits.H_CBD) + { + Status = HecClearQue(pThis, &Timeout); + if (EFI_ERROR(Status)) + { + goto GO_FAIL; + } + continue; + } + + // Read queue + while (bFilledSlots-- > 0) + { + + DWord = pMbarRegs->CB_RW; + if (*pBufLen < dwBufLen) + { + + if (dwDataReads < dwBufLen / sizeof(UINT32)) + { + ((UINT32*)pMsgBuf)[dwDataReads] = DWord; + *pBufLen += sizeof(UINT32); + } + else + { + switch (dwBufLen % sizeof(UINT32)) + { + case 3: ((UINT8*)pMsgBuf)[*pBufLen + 2] = (UINT8)(DWord >> 16); + case 2: ((UINT8*)pMsgBuf)[*pBufLen + 1] = (UINT8)(DWord >> 8); + case 1: ((UINT8*)pMsgBuf)[*pBufLen + 0] = (UINT8)DWord; + } + *pBufLen += dwBufLen % sizeof(UINT32); + } + } + else + { + printk("[HECI-%d] Message 0x%08X exceeds buffer size (%dB)\n", + pThis->Fun, pMsgBuf[0].DWord, dwBufLen); + } + dwDataReads++; + + // Read message length. + if (bMsgLen == 0) + { + bMsgLen = (UINT8)((pMsgBuf[0].Bits.Length + sizeof(UINT32) - 1) / sizeof(UINT32)); + bMsgLen++; // One more double word for message header + // + // Sanity check. If message length exceeds queue length this is + // not valid header. We are out of synch, let's reset the queue. + // + if (bMsgLen > sMeCsr.Bits.ME_CBD) + { + printk("[HECI-%d] 0x%08X does not seem to be msg header, reseting...\n", + pThis->Fun, pMsgBuf[0].DWord); + Status = HecClearQue(pThis, &Timeout); + if (EFI_ERROR(Status)) + { + goto GO_FAIL; + } + *pBufLen = dwDataReads = bMsgLen = 0; + break; // while (bFilledSlots) + } + } + + // If message is complete set interrupt to ME to let it know that next + // message can be sent and exit. + if (dwDataReads >= bMsgLen) + { + + sMeCsr.DWord = pMbarRegs->ME_CSR; + sHCsr.DWord = pMbarRegs->H_CSR; + if (!sMeCsr.Bits.ME_RDY) + { + HecClearQue(pThis, &Timeout); + Status = EFI_ABORTED; + } + else + { + HeciTrace(pThis, " Got msg: ", pMsgBuf, *pBufLen); + sHCsr.Bits.H_IG = 1; + pMbarRegs->H_CSR = sHCsr.DWord; + } + goto GO_FAIL; + } + } + if (Timeout == 0) + { + printk("[HECI-%d] Receive failed (timeout)\n", pThis->Fun); + Status = EFI_TIMEOUT; + goto GO_FAIL; + } + MicroSecondDelay(HECI_TIMEOUT_UNIT); + Timeout--; + } + GO_FAIL: + if (pTimeout != NULL) + { + *pTimeout = Timeout; + } + pThis->Mefs1.DWord = HeciPciReadMefs1(); + iounmap((VOID *)pMbarRegs); + return Status; +} + +EFI_STATUS HeciMsgSend ( HECI_DEVICE *pThis, + UINT32 *pTimeout, + HECI_MSG_HEADER *pMessage) +{ + EFI_STATUS Status; + UINT32 Timeout = 0; + UINT8 bEmptySlots; + UINT8 i, bMsgLen; + HECI_HOST_CSR sHCsr; + HECI_ME_CSR sMeCsr; + HECI_MBAR_REGS *pMbarRegs; + VOID *pAddrPoint; + + if (pThis == NULL || pMessage == NULL) + { + printk("HeciMsgSend Failed\n"); + return EFI_INVALID_PARAMETER; + } + HeciTrace(pThis, "Send msg: ", pMessage, sizeof(HECI_MSG_HEADER) + pMessage->Bits.Length); + + // Check for HECI availability + pAddrPoint = HeciMbarRead(pThis); + pMbarRegs = (HECI_MBAR_REGS*)ioremap_nocache(pAddrPoint, 0x1000); + if (pMbarRegs == NULL) + { + printk("[HECI-%d] Send failed (device disabled)\n", pThis->Fun); + printk("Failed\n"); + return EFI_DEVICE_ERROR; + } + if (pTimeout != NULL) + { + Timeout = *pTimeout; + } + + bMsgLen = (UINT8)((pMessage->Bits.Length + sizeof(UINT32) - 1) / sizeof(UINT32)); + bMsgLen++; //message header + while (1) + { + sHCsr.DWord = pMbarRegs->H_CSR; + sMeCsr.DWord = pMbarRegs->ME_CSR; + + // If message is more than queue length go fail. + if (bMsgLen > sHCsr.Bits.H_CBD) + { + printk("[HECI-%d] Send failed (msg %d B, queue %d B only)\n", + pThis->Fun, pMessage->Bits.Length, sHCsr.Bits.H_CBD * sizeof(UINT32)); + Status = EFI_BAD_BUFFER_SIZE; + goto GO_FAIL; + } + bEmptySlots = (UINT8)sHCsr.Bits.H_CBD - + (UINT8)((INT8)sHCsr.Bits.H_CBWP - (INT8)sHCsr.Bits.H_CBRP); + + // Is it ready ? + if (!sMeCsr.Bits.ME_RDY || !sHCsr.Bits.H_RDY || bEmptySlots > sHCsr.Bits.H_CBD) + { + Status = HecClearQue(pThis, &Timeout); + if (EFI_ERROR(Status)) + { + goto GO_FAIL; + } + continue; + } + + if (bMsgLen <= bEmptySlots) + { + for (i = 0; i < bMsgLen; i++) + { + pMbarRegs->CB_WW = ((UINT32*)pMessage)[i]; + } + + + sMeCsr.DWord = pMbarRegs->ME_CSR; + if (!sMeCsr.Bits.ME_RDY) + { + printk("[HECI-%d] Queue has been reset while sending\n", pThis->Fun); + continue; + } + + sHCsr.DWord = pMbarRegs->H_CSR; + sHCsr.Bits.H_IS = 0; + sHCsr.Bits.H_IG = 1; + pMbarRegs->H_CSR = sHCsr.DWord; + Status = EFI_SUCCESS; + goto GO_FAIL; + } + + + if (Timeout == 0) + { + printk("[HECI-%d] Send failed (timeout)\n", pThis->Fun); + Status = EFI_TIMEOUT; + goto GO_FAIL; + } + MicroSecondDelay(HECI_TIMEOUT_UNIT); + Timeout--; + } + GO_FAIL: + if (pTimeout != NULL) + { + *pTimeout = Timeout; + } + pThis->Mefs1.DWord = HeciPciReadMefs1(); + iounmap((VOID *)pMbarRegs); + return Status; +} + + +VOID *HeciMbarRead(HECI_DEVICE *pThis) +{ + VOID *start; + + UINT16 Cmd; + union + { + UINT64 QWord; + struct + { + UINT32 DWordL; + UINT32 DWordH; + } Bits; + } Mbar; + + // + // Read MBAR. + Mbar.QWord = 0; + Mbar.Bits.DWordL = PciRead32(pThis->PciCfg + HECI_REG_MBAR); + if (Mbar.Bits.DWordL == 0xFFFFFFFF) + { + printk("[HECI-%d] Device disabled\n", pThis->Fun); + Mbar.Bits.DWordL = 0; + goto GO_FAIL; + } + if (Mbar.Bits.DWordL & 0x4) // if 64-bit address add the upper half + { + Mbar.Bits.DWordH = PciRead32(pThis->PciCfg + HECI_REG_MBAR + 4); + } + Mbar.Bits.DWordL &= 0xFFFFFFF0; + if (Mbar.QWord == 0) + { + if (pThis->Mbar == 0) + { + printk("[HECI-%d] MBAR not programmed\n", pThis->Fun); + goto GO_FAIL; + } + else + { + Mbar.QWord = pThis->Mbar; + printk("[HECI-%d] MBAR not programmed, using default 0x%08X%08X\n", + pThis->Fun, Mbar.Bits.DWordH, Mbar.Bits.DWordL); + + // Programm the MBAR, set the 64-bit support bit regardless of the size + // of the address currently used. + PciWrite32(pThis->PciCfg + HECI_REG_MBAR + 4, Mbar.Bits.DWordH); + PciWrite32(pThis->PciCfg + HECI_REG_MBAR, Mbar.Bits.DWordL | 4); + } + } + else + { + pThis->Mbar = Mbar.QWord; + } + + // Enable the MBAR + Cmd = PciRead16(pThis->PciCfg + HECI_REG_COMMAND); + if (!(Cmd & HECI_CMD_MSE)) + { + PciWrite16(pThis->PciCfg + HECI_REG_COMMAND, Cmd | HECI_CMD_BME | HECI_CMD_MSE); + } + GO_FAIL: + return (VOID*)(INTN)Mbar.QWord; +} + + + +VOID HeciTrace( HECI_DEVICE *pThis, + CHAR8 *pPrefix, + HECI_MSG_HEADER *pMsg, + INT32 MsgLen) +{ +#if 0 /// Trace Enable or Disable + if (MsgLen > 4) + { + UINT32 dwLineBreak = 0; + UINT32 dwIndex = 0; + UINT8 *pMsgBody = (UINT8*)&pMsg[1]; + + MsgLen -= 4; + while (MsgLen-- > 0) + { + if (dwLineBreak == 0) + printk("%02x: ", (dwIndex & 0xF0)); + printk("%02x ", pMsgBody[dwIndex++]); + dwLineBreak++; + if (dwLineBreak == 16) + { + printk("\n"); + dwLineBreak = 0; + } + if (dwLineBreak == 8) + { + printk("-"); + } + } + printk("\n"); + } +#endif +} \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.h new file mode 100644 index 000000000000..a22728c058fe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_rw.h @@ -0,0 +1,143 @@ + +#include "i2c-mei_io.h" + +/****** Parameter *****/ + +#define HECI_READ_TIMEOUT 12500000 // 12.5sec +#define HECI_SEND_TIMEOUT 12500000 // 12.5sec +#define HECI_TIMEOUT_UNIT 10 + + +// HECI functions location +#define HECI_BUS 0 +#define HECI_DEV 22 +#define HECI_FUN 0 + +// HECI register +#define HECI_REG_VENDORID 0x00 +#define HECI_REG_DEVICEID 0x02 +#define HECI_REG_COMMAND 0x04 +#define HECI_REG_REVID 0x08 +#define HECI_REG_MBAR 0x10 +#define HECI_REG_IRQ 0x3C +#define HECI_REG_HIDM 0xA0 +#define HECI_REG_HFS 0x40 +#define HECI_REG_MISC_SHDW 0x44 +#define HECI_REG_GS_SHDW 0x48 +#define HECI_REG_H_GS 0x4C +#define HECI_REG_GS_SHDW2 0x60 +#define HECI_REG_GS_SHDW3 0x64 +#define HECI_REG_GS_SHDW4 0x68 +#define HECI_REG_GS_SHDW5 0x6C +#define HECI_REG_H_GS2 0x70 +#define HECI_REG_H_GS3 0x74 +#define HECI_REG_MEFS1 HECI_REG_HFS +#define HECI_REG_MEFS2 HECI_REG_GS_SHDW + +#define HECI_MBAR_DEFAULT 0xFEDB0000 + +// HECI Interrupt Delivery Mode to be set in HECI_REG_HIDM. +#define HECI_HIDM_MSI 0 +#define HECI_HIDM_SCI 1 +#define HECI_HIDM_SMI 2 +#define HECI_HIDM_LAST HECI_HIDM_SMI + +// HECI command register bits +#define HECI_CMD_BME 0x04 // Bus master enable +#define HECI_CMD_MSE 0x02 // Memory space enable + + +/****** Struct *****/ + +typedef union +{ + UINT32 DWord; + struct + { + UINT32 MeAddress : 8, // Addressee on ME side + HostAddress: 8, // Addressee on host siede, zero for BIOS + Length : 9, // Number of bytes following the header + Reserved : 6, + MsgComplete: 1; // Whether this is last fragment of a message + } Bits; +} HECI_MSG_HEADER; + +// ME Firmware Status 1 register basics. offset:40h +typedef union +{ + UINT32 DWord; + struct + { + UINT32 CurrentState : 4, // 0~3 Current ME firmware state + Reserved_5 : 5, // 4~8 + InitComplete : 1, // 9 ME firmware finished initialization + Reserved_10 : 2, // 10~11 + ErrorCode : 4, // 12~15 If set means fatal error + OperatingMode: 4, // 16~19 Current ME operating mode + Reserved_20 : 5, // 20~24 + MsgAckData : 3, // 25~27 MSG ACK Data specific for acknowledged BIOS message + MsgAck : 4; // 28~31 Acknowledge for register based BIOS message + } Bits; +} HECI_MEFS1; + + +typedef struct +{ + + UINT8 Bus; // PCI bus + UINT8 Dev; // PCI device + UINT8 Fun; // PCI function number + + UINTN PciCfg; + UINT16 Vid; // Device ID + UINT16 Did; // Vendor ID + UINT8 Hidm; // interrupt mode + UINT64 Mbar; + UINT32 HMtu; // Max transfer unit configured by ME minus header + UINT32 MeMtu; // Max transfer unit configured by ME minus header + HECI_MEFS1 Mefs1; // ME Firmware Status at recent operation +} HECI_DEVICE; + +/****** Function *****/ + + + +/** + * @param pThis Pointer to HECI device structure + * @param pTimeout On input timeout in ms, on exit time left + */ +EFI_STATUS HeciInit ( HECI_DEVICE *pThis, + UINT32 *pTimeout); + +/** + * @param pThis Pointer to HECI device structure + * @param pTimeout On input timeout in ms, on exit time left + */ +EFI_STATUS HecClearQue ( HECI_DEVICE *pThis, + UINT32 *pTimeout); + +/** + * @param pThis Pointer to HECI device structure + * @param pTimeout On input timeout in ms, on exit time left + * @param pMsgBuf Buffer for the received message + * @param pBufLen On input buffer size, on exit message, in bytes + */ +EFI_STATUS HeciMsgRecv ( HECI_DEVICE *pThis, + UINT32 *pTimeout, + HECI_MSG_HEADER *pMsgBuf, + UINT32 *pBufLen ); + + + +/** + * @param pThis Pointer to HECI device structure + * @param pTimeout On input timeout in ms, on exit time left + * @param pMessage The header of the message to send + */ +EFI_STATUS HeciMsgSend ( HECI_DEVICE *pThis, + UINT32 *pTimeout, + HECI_MSG_HEADER *pMessage); + + + +#define HeciPciReadMefs1() PciRead32(PCI_LIB_ADDRESS(HECI_BUS, HECI_DEV, HECI_FUN, HECI_REG_MEFS1)) \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_type.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_type.h new file mode 100644 index 000000000000..e9b60c7573d5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/i2c-mei_type.h @@ -0,0 +1,448 @@ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef EFIAPI +#define EFIAPI +#endif + + // + // Assume standard AARCH64 alignment. + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef signed char INT8; + +/// +/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// + typedef UINT64 UINTN; + +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// + typedef INT64 INTN; + + + +/* ========== ProcessBind.h ========= */ + +/// +/// A value of native width with the highest bit set. +/// +#define MAX_BIT 0x8000000000000000ULL + + + +/* ========== Base.h ========= */ + +// +// Modifiers to abstract standard types to aid in debug of problems +// + +/// +/// Datum is read-only. +/// +#define CONST const + +/// +/// Datum is scoped to the current file or function. +/// +#define STATIC static + +/// +/// Undeclared type. +/// +#define VOID void + +// +// Modifiers for Data Types used to self document code. +// This concept is borrowed for UEFI specification. +// + +/// +/// Datum is passed to the function. +/// +#define IN + +/// +/// Datum is returned from the function. +/// +#define OUT + +/// +/// Passing the datum to the function is optional, and a NULL +/// is passed if the value is not supplied. +/// +#define OPTIONAL + +// +// UEFI specification claims 1 and 0. We are concerned about the +// complier portability so we did it this way. +// + +/// +/// Boolean true value. UEFI Specification defines this value to be 1, +/// but this form is more portable. +/// +#define TRUE ((BOOLEAN)(1==1)) + +/// +/// Boolean false value. UEFI Specification defines this value to be 0, +/// but this form is more portable. +/// +#define FALSE ((BOOLEAN)(0==1)) + +/// +/// NULL pointer (VOID *) +/// +#define NULL ((VOID *) 0) + +// +// Status codes common to all execution phases +// +typedef UINTN RETURN_STATUS; + +/** + Produces a RETURN_STATUS code with the highest bit set. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit set. + +**/ +#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode))) + +/** + Produces a RETURN_STATUS code with the highest bit clear. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit clear. + +**/ +#define ENCODE_WARNING(StatusCode) ((RETURN_STATUS)(StatusCode)) + +/** + Returns TRUE if a specified RETURN_STATUS code is an error code. + + This function returns TRUE if StatusCode has the high bit set. Otherwise, FALSE is returned. + + @param StatusCode The status code value to evaluate. + + @retval TRUE The high bit of StatusCode is set. + @retval FALSE The high bit of StatusCode is clear. + +**/ +#define RETURN_ERROR(StatusCode) (((INTN)(RETURN_STATUS)(StatusCode)) < 0) + +/// +/// The operation completed successfully. +/// +#define RETURN_SUCCESS 0 + +/// +/// The image failed to load. +/// +#define RETURN_LOAD_ERROR ENCODE_ERROR (1) + +/// +/// The parameter was incorrect. +/// +#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2) + +/// +/// The operation is not supported. +/// +#define RETURN_UNSUPPORTED ENCODE_ERROR (3) + +/// +/// The buffer was not the proper size for the request. +/// +#define RETURN_BAD_BUFFER_SIZE ENCODE_ERROR (4) + +/// +/// The buffer was not large enough to hold the requested data. +/// The required buffer size is returned in the appropriate +/// parameter when this error occurs. +/// +#define RETURN_BUFFER_TOO_SMALL ENCODE_ERROR (5) + +/// +/// There is no data pending upon return. +/// +#define RETURN_NOT_READY ENCODE_ERROR (6) + +/// +/// The physical device reported an error while attempting the +/// operation. +/// +#define RETURN_DEVICE_ERROR ENCODE_ERROR (7) + +/// +/// The device can not be written to. +/// +#define RETURN_WRITE_PROTECTED ENCODE_ERROR (8) + +/// +/// The resource has run out. +/// +#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9) + +/// +/// An inconsistency was detected on the file system causing the +/// operation to fail. +/// +#define RETURN_VOLUME_CORRUPTED ENCODE_ERROR (10) + +/// +/// There is no more space on the file system. +/// +#define RETURN_VOLUME_FULL ENCODE_ERROR (11) + +/// +/// The device does not contain any medium to perform the +/// operation. +/// +#define RETURN_NO_MEDIA ENCODE_ERROR (12) + +/// +/// The medium in the device has changed since the last +/// access. +/// +#define RETURN_MEDIA_CHANGED ENCODE_ERROR (13) + +/// +/// The item was not found. +/// +#define RETURN_NOT_FOUND ENCODE_ERROR (14) + +/// +/// Access was denied. +/// +#define RETURN_ACCESS_DENIED ENCODE_ERROR (15) + +/// +/// The server was not found or did not respond to the request. +/// +#define RETURN_NO_RESPONSE ENCODE_ERROR (16) + +/// +/// A mapping to the device does not exist. +/// +#define RETURN_NO_MAPPING ENCODE_ERROR (17) + +/// +/// A timeout time expired. +/// +#define RETURN_TIMEOUT ENCODE_ERROR (18) + +/// +/// The protocol has not been started. +/// +#define RETURN_NOT_STARTED ENCODE_ERROR (19) + +/// +/// The protocol has already been started. +/// +#define RETURN_ALREADY_STARTED ENCODE_ERROR (20) + +/// +/// The operation was aborted. +/// +#define RETURN_ABORTED ENCODE_ERROR (21) + +/// +/// An ICMP error occurred during the network operation. +/// +#define RETURN_ICMP_ERROR ENCODE_ERROR (22) + +/// +/// A TFTP error occurred during the network operation. +/// +#define RETURN_TFTP_ERROR ENCODE_ERROR (23) + +/// +/// A protocol error occurred during the network operation. +/// +#define RETURN_PROTOCOL_ERROR ENCODE_ERROR (24) + +/// +/// A function encountered an internal version that was +/// incompatible with a version requested by the caller. +/// +#define RETURN_INCOMPATIBLE_VERSION ENCODE_ERROR (25) + +/// +/// The function was not performed due to a security violation. +/// +#define RETURN_SECURITY_VIOLATION ENCODE_ERROR (26) + +/// +/// A CRC error was detected. +/// +#define RETURN_CRC_ERROR ENCODE_ERROR (27) + +/// +/// The beginning or end of media was reached. +/// +#define RETURN_END_OF_MEDIA ENCODE_ERROR (28) + +/// +/// The end of the file was reached. +/// +#define RETURN_END_OF_FILE ENCODE_ERROR (31) + +/// +/// The language specified was invalid. +/// +#define RETURN_INVALID_LANGUAGE ENCODE_ERROR (32) + +/// +/// The security status of the data is unknown or compromised +/// and the data must be updated or replaced to restore a valid +/// security status. +/// +#define RETURN_COMPROMISED_DATA ENCODE_ERROR (33) + +/// +/// The string contained one or more characters that +/// the device could not render and were skipped. +/// +#define RETURN_WARN_UNKNOWN_GLYPH ENCODE_WARNING (1) + +/// +/// The handle was closed, but the file was not deleted. +/// +#define RETURN_WARN_DELETE_FAILURE ENCODE_WARNING (2) + +/// +/// The handle was closed, but the data to the file was not +/// flushed properly. +/// +#define RETURN_WARN_WRITE_FAILURE ENCODE_WARNING (3) + +/// +/// The resulting buffer was too small, and the data was +/// truncated to the buffer size. +/// +#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4) + +/// +/// The data has not been updated within the timeframe set by +/// local policy for this type of data. +/// +#define RETURN_WARN_STALE_DATA ENCODE_WARNING (5) + + + +/* ========== UefiBaseType.h ========= */ + +/// +/// Function return status for EFI API. +/// +typedef RETURN_STATUS EFI_STATUS; + +/// +/// Enumeration of EFI_STATUS. +///@{ +#define EFI_SUCCESS RETURN_SUCCESS +#define EFI_LOAD_ERROR RETURN_LOAD_ERROR +#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER +#define EFI_UNSUPPORTED RETURN_UNSUPPORTED +#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE +#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL +#define EFI_NOT_READY RETURN_NOT_READY +#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR +#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED +#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES +#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED +#define EFI_VOLUME_FULL RETURN_VOLUME_FULL +#define EFI_NO_MEDIA RETURN_NO_MEDIA +#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED +#define EFI_NOT_FOUND RETURN_NOT_FOUND +#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED +#define EFI_NO_RESPONSE RETURN_NO_RESPONSE +#define EFI_NO_MAPPING RETURN_NO_MAPPING +#define EFI_TIMEOUT RETURN_TIMEOUT +#define EFI_NOT_STARTED RETURN_NOT_STARTED +#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED +#define EFI_ABORTED RETURN_ABORTED +#define EFI_ICMP_ERROR RETURN_ICMP_ERROR +#define EFI_TFTP_ERROR RETURN_TFTP_ERROR +#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR +#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION +#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION +#define EFI_CRC_ERROR RETURN_CRC_ERROR +#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA +#define EFI_END_OF_FILE RETURN_END_OF_FILE +#define EFI_INVALID_LANGUAGE RETURN_INVALID_LANGUAGE +#define EFI_COMPROMISED_DATA RETURN_COMPROMISED_DATA + +#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH +#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE +#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE +#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL +#define EFI_WARN_STALE_DATA RETURN_WARN_STALE_DATA +///@} + +/// +/// Define macro to encode the status code. +/// +#define EFIERR(_a) ENCODE_ERROR(_a) + +#define EFI_ERROR(A) RETURN_ERROR(A) + + + +/* ========== BaseLib.h ========= */ + +/// +/// Byte packed structure for EFLAGS/RFLAGS. +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 CF:1; ///< Carry Flag. + UINT32 Reserved_0:1; ///< Reserved. + UINT32 PF:1; ///< Parity Flag. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AF:1; ///< Auxiliary Carry Flag. + UINT32 Reserved_2:1; ///< Reserved. + UINT32 ZF:1; ///< Zero Flag. + UINT32 SF:1; ///< Sign Flag. + UINT32 TF:1; ///< Trap Flag. + UINT32 IF:1; ///< Interrupt Enable Flag. + UINT32 DF:1; ///< Direction Flag. + UINT32 OF:1; ///< Overflow Flag. + UINT32 IOPL:2; ///< I/O Privilege Level. + UINT32 NT:1; ///< Nested Task. + UINT32 Reserved_3:1; ///< Reserved. + UINT32 RF:1; ///< Resume Flag. + UINT32 VM:1; ///< Virtual 8086 Mode. + UINT32 AC:1; ///< Alignment Check. + UINT32 VIF:1; ///< Virtual Interrupt Flag. + UINT32 VIP:1; ///< Virtual Interrupt Pending. + UINT32 ID:1; ///< ID Flag. + UINT32 Reserved_4:10; ///< Reserved. + } Bits; + UINTN UintN; +} IA32_EFLAGS32; \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/mei_dev.h b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/mei_dev.h new file mode 100644 index 000000000000..4250555d5e72 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/ag9064/modules/mei_dev.h @@ -0,0 +1,832 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, Intel Corporation. + * + * 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. + * + */ + +#ifndef _MEI_DEV_H_ +#define _MEI_DEV_H_ + +#include +#include +#include +#include +#include + +#include "hw.h" +#include "hbm.h" + +/* + * watch dog definition + */ +#define MEI_WD_HDR_SIZE 4 +#define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE +#define MEI_WD_START_MSG_SIZE (MEI_WD_HDR_SIZE + 16) + +#define MEI_WD_DEFAULT_TIMEOUT 120 /* seconds */ +#define MEI_WD_MIN_TIMEOUT 120 /* seconds */ +#define MEI_WD_MAX_TIMEOUT 65535 /* seconds */ + +#define MEI_WD_STOP_TIMEOUT 10 /* msecs */ + +#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) + +#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) + + +/* + * AMTHI Client UUID + */ +extern const uuid_le mei_amthif_guid; + +/* + * Watchdog Client UUID + */ +extern const uuid_le mei_wd_guid; + +/* + * Number of Maximum MEI Clients + */ +#define MEI_CLIENTS_MAX 256 + +/* + * maximum number of consecutive resets + */ +#define MEI_MAX_CONSEC_RESET 3 + +/* + * Number of File descriptors/handles + * that can be opened to the driver. + * + * Limit to 255: 256 Total Clients + * minus internal client for MEI Bus Messages + */ +#define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 1) + +/* + * Internal Clients Number + */ +#define MEI_HOST_CLIENT_ID_ANY (-1) +#define MEI_HBM_HOST_CLIENT_ID 0 /* not used, just for documentation */ +#define MEI_WD_HOST_CLIENT_ID 1 +#define MEI_IAMTHIF_HOST_CLIENT_ID 2 + + +/* File state */ +enum file_state { + MEI_FILE_INITIALIZING = 0, + MEI_FILE_CONNECTING, + MEI_FILE_CONNECTED, + MEI_FILE_DISCONNECTING, + MEI_FILE_DISCONNECT_REPLY, + MEI_FILE_DISCONNECT_REQUIRED, + MEI_FILE_DISCONNECTED, +}; + +/* MEI device states */ +enum mei_dev_state { + MEI_DEV_INITIALIZING = 0, + MEI_DEV_INIT_CLIENTS, + MEI_DEV_ENABLED, + MEI_DEV_RESETTING, + MEI_DEV_DISABLED, + MEI_DEV_POWER_DOWN, + MEI_DEV_POWER_UP +}; + +const char *mei_dev_state_str(int state); + +enum iamthif_states { + MEI_IAMTHIF_IDLE, + MEI_IAMTHIF_WRITING, + MEI_IAMTHIF_FLOW_CONTROL, + MEI_IAMTHIF_READING, + MEI_IAMTHIF_READ_COMPLETE +}; + +enum mei_file_transaction_states { + MEI_IDLE, + MEI_WRITING, + MEI_WRITE_COMPLETE, + MEI_FLOW_CONTROL, + MEI_READING, + MEI_READ_COMPLETE +}; + +enum mei_wd_states { + MEI_WD_IDLE, + MEI_WD_RUNNING, + MEI_WD_STOPPING, +}; + +/** + * enum mei_cb_file_ops - file operation associated with the callback + * @MEI_FOP_READ: read + * @MEI_FOP_WRITE: write + * @MEI_FOP_CONNECT: connect + * @MEI_FOP_DISCONNECT: disconnect + * @MEI_FOP_DISCONNECT_RSP: disconnect response + * @MEI_FOP_NOTIFY_START: start notification + * @MEI_FOP_NOTIFY_STOP: stop notification + */ +enum mei_cb_file_ops { + MEI_FOP_READ = 0, + MEI_FOP_WRITE, + MEI_FOP_CONNECT, + MEI_FOP_DISCONNECT, + MEI_FOP_DISCONNECT_RSP, + MEI_FOP_NOTIFY_START, + MEI_FOP_NOTIFY_STOP, +}; + +/* + * Intel MEI message data struct + */ +struct mei_msg_data { + u32 size; + unsigned char *data; +}; + +/* Maximum number of processed FW status registers */ +#define MEI_FW_STATUS_MAX 6 +/* Minimal buffer for FW status string (8 bytes in dw + space or '\0') */ +#define MEI_FW_STATUS_STR_SZ (MEI_FW_STATUS_MAX * (8 + 1)) + + +/* + * struct mei_fw_status - storage of FW status data + * + * @count: number of actually available elements in array + * @status: FW status registers + */ +struct mei_fw_status { + int count; + u32 status[MEI_FW_STATUS_MAX]; +}; + +/** + * struct mei_me_client - representation of me (fw) client + * + * @list: link in me client list + * @refcnt: struct reference count + * @props: client properties + * @client_id: me client id + * @mei_flow_ctrl_creds: flow control credits + * @connect_count: number connections to this client + * @bus_added: added to bus + */ +struct mei_me_client { + struct list_head list; + struct kref refcnt; + struct mei_client_properties props; + u8 client_id; + u8 mei_flow_ctrl_creds; + u8 connect_count; + u8 bus_added; +}; + + +struct mei_cl; + +/** + * struct mei_cl_cb - file operation callback structure + * + * @list: link in callback queue + * @cl: file client who is running this operation + * @fop_type: file operation type + * @buf: buffer for data associated with the callback + * @buf_idx: last read index + * @read_time: last read operation time stamp (iamthif) + * @file_object: pointer to file structure + * @status: io status of the cb + * @internal: communication between driver and FW flag + * @completed: the transfer or reception has completed + */ +struct mei_cl_cb { + struct list_head list; + struct mei_cl *cl; + enum mei_cb_file_ops fop_type; + struct mei_msg_data buf; + unsigned long buf_idx; + unsigned long read_time; + struct file *file_object; + int status; + u32 internal:1; + u32 completed:1; +}; + +/** + * struct mei_cl - me client host representation + * carried in file->private_data + * + * @link: link in the clients list + * @dev: mei parent device + * @state: file operation state + * @tx_wait: wait queue for tx completion + * @rx_wait: wait queue for rx completion + * @wait: wait queue for management operation + * @ev_wait: notification wait queue + * @ev_async: event async notification + * @status: connection status + * @me_cl: fw client connected + * @host_client_id: host id + * @mei_flow_ctrl_creds: transmit flow credentials + * @timer_count: watchdog timer for operation completion + * @reserved: reserved for alignment + * @notify_en: notification - enabled/disabled + * @notify_ev: pending notification event + * @writing_state: state of the tx + * @rd_pending: pending read credits + * @rd_completed: completed read + * + * @cldev: device on the mei client bus + */ +struct mei_cl { + struct list_head link; + struct mei_device *dev; + enum file_state state; + wait_queue_head_t tx_wait; + wait_queue_head_t rx_wait; + wait_queue_head_t wait; + wait_queue_head_t ev_wait; + struct fasync_struct *ev_async; + int status; + struct mei_me_client *me_cl; + u8 host_client_id; + u8 mei_flow_ctrl_creds; + u8 timer_count; + u8 reserved; + u8 notify_en; + u8 notify_ev; + enum mei_file_transaction_states writing_state; + struct list_head rd_pending; + struct list_head rd_completed; + + struct mei_cl_device *cldev; +}; + +/** + * struct mei_hw_ops - hw specific ops + * + * @host_is_ready : query for host readiness + * + * @hw_is_ready : query if hw is ready + * @hw_reset : reset hw + * @hw_start : start hw after reset + * @hw_config : configure hw + * + * @fw_status : get fw status registers + * @pg_state : power gating state of the device + * @pg_in_transition : is device now in pg transition + * @pg_is_enabled : is power gating enabled + * + * @intr_clear : clear pending interrupts + * @intr_enable : enable interrupts + * @intr_disable : disable interrupts + * + * @hbuf_free_slots : query for write buffer empty slots + * @hbuf_is_ready : query if write buffer is empty + * @hbuf_max_len : query for write buffer max len + * + * @write : write a message to FW + * + * @rdbuf_full_slots : query how many slots are filled + * + * @read_hdr : get first 4 bytes (header) + * @read : read a buffer from the FW + */ +struct mei_hw_ops { + + bool (*host_is_ready)(struct mei_device *dev); + + bool (*hw_is_ready)(struct mei_device *dev); + int (*hw_reset)(struct mei_device *dev, bool enable); + int (*hw_start)(struct mei_device *dev); + void (*hw_config)(struct mei_device *dev); + + + int (*fw_status)(struct mei_device *dev, struct mei_fw_status *fw_sts); + enum mei_pg_state (*pg_state)(struct mei_device *dev); + bool (*pg_in_transition)(struct mei_device *dev); + bool (*pg_is_enabled)(struct mei_device *dev); + + void (*intr_clear)(struct mei_device *dev); + void (*intr_enable)(struct mei_device *dev); + void (*intr_disable)(struct mei_device *dev); + + int (*hbuf_free_slots)(struct mei_device *dev); + bool (*hbuf_is_ready)(struct mei_device *dev); + size_t (*hbuf_max_len)(const struct mei_device *dev); + + int (*write)(struct mei_device *dev, + struct mei_msg_hdr *hdr, + unsigned char *buf); + + int (*rdbuf_full_slots)(struct mei_device *dev); + + u32 (*read_hdr)(const struct mei_device *dev); + int (*read)(struct mei_device *dev, + unsigned char *buf, unsigned long len); +}; + +/* MEI bus API*/ +void mei_cl_bus_rescan(struct mei_device *bus); +void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); +ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, + bool blocking); +ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); +void mei_cl_bus_rx_event(struct mei_cl *cl); +void mei_cl_bus_notify_event(struct mei_cl *cl); +void mei_cl_bus_remove_devices(struct mei_device *bus); +int mei_cl_bus_init(void); +void mei_cl_bus_exit(void); + +/** + * enum mei_pg_event - power gating transition events + * + * @MEI_PG_EVENT_IDLE: the driver is not in power gating transition + * @MEI_PG_EVENT_WAIT: the driver is waiting for a pg event to complete + * @MEI_PG_EVENT_RECEIVED: the driver received pg event + * @MEI_PG_EVENT_INTR_WAIT: the driver is waiting for a pg event interrupt + * @MEI_PG_EVENT_INTR_RECEIVED: the driver received pg event interrupt + */ +enum mei_pg_event { + MEI_PG_EVENT_IDLE, + MEI_PG_EVENT_WAIT, + MEI_PG_EVENT_RECEIVED, + MEI_PG_EVENT_INTR_WAIT, + MEI_PG_EVENT_INTR_RECEIVED, +}; + +/** + * enum mei_pg_state - device internal power gating state + * + * @MEI_PG_OFF: device is not power gated - it is active + * @MEI_PG_ON: device is power gated - it is in lower power state + */ +enum mei_pg_state { + MEI_PG_OFF = 0, + MEI_PG_ON = 1, +}; + +const char *mei_pg_state_str(enum mei_pg_state state); + +/** + * struct mei_device - MEI private device struct + * + * @dev : device on a bus + * @cdev : character device + * @minor : minor number allocated for device + * + * @write_list : write pending list + * @write_waiting_list : write completion list + * @ctrl_wr_list : pending control write list + * @ctrl_rd_list : pending control read list + * + * @file_list : list of opened handles + * @open_handle_count: number of opened handles + * + * @device_lock : big device lock + * @timer_work : MEI timer delayed work (timeouts) + * + * @recvd_hw_ready : hw ready message received flag + * + * @wait_hw_ready : wait queue for receive HW ready message form FW + * @wait_pg : wait queue for receive PG message from FW + * @wait_hbm_start : wait queue for receive HBM start message from FW + * @wait_stop_wd : wait queue for receive WD stop message from FW + * + * @reset_count : number of consecutive resets + * @dev_state : device state + * @hbm_state : state of host bus message protocol + * @init_clients_timer : HBM init handshake timeout + * + * @pg_event : power gating event + * @pg_domain : runtime PM domain + * + * @rd_msg_buf : control messages buffer + * @rd_msg_hdr : read message header storage + * + * @hbuf_depth : depth of hardware host/write buffer is slots + * @hbuf_is_ready : query if the host host/write buffer is ready + * @wr_msg : the buffer for hbm control messages + * + * @version : HBM protocol version in use + * @hbm_f_pg_supported : hbm feature pgi protocol + * @hbm_f_dc_supported : hbm feature dynamic clients + * @hbm_f_dot_supported : hbm feature disconnect on timeout + * @hbm_f_ev_supported : hbm feature event notification + * + * @me_clients_rwsem: rw lock over me_clients list + * @me_clients : list of FW clients + * @me_clients_map : FW clients bit map + * @host_clients_map : host clients id pool + * @me_client_index : last FW client index in enumeration + * + * @allow_fixed_address: allow user space to connect a fixed client + * + * @wd_cl : watchdog client + * @wd_state : watchdog client state + * @wd_pending : watchdog command is pending + * @wd_timeout : watchdog expiration timeout + * @wd_data : watchdog message buffer + * + * @amthif_cmd_list : amthif list for cmd waiting + * @amthif_rd_complete_list : amthif list for reading completed cmd data + * @iamthif_file_object : file for current amthif operation + * @iamthif_cl : amthif host client + * @iamthif_current_cb : amthif current operation callback + * @iamthif_open_count : number of opened amthif connections + * @iamthif_timer : time stamp of current amthif command completion + * @iamthif_stall_timer : timer to detect amthif hang + * @iamthif_state : amthif processor state + * @iamthif_canceled : current amthif command is canceled + * + * @init_work : work item for the device init + * @reset_work : work item for the device reset + * + * @device_list : mei client bus list + * @cl_bus_lock : client bus list lock + * + * @dbgfs_dir : debugfs mei root directory + * + * @ops: : hw specific operations + * @hw : hw specific data + */ +struct mei_device { + struct device *dev; + struct cdev cdev; + int minor; + + struct mei_cl_cb write_list; + struct mei_cl_cb write_waiting_list; + struct mei_cl_cb ctrl_wr_list; + struct mei_cl_cb ctrl_rd_list; + + struct list_head file_list; + long open_handle_count; + + struct mutex device_lock; + struct delayed_work timer_work; + + bool recvd_hw_ready; + /* + * waiting queue for receive message from FW + */ + wait_queue_head_t wait_hw_ready; + wait_queue_head_t wait_pg; + wait_queue_head_t wait_hbm_start; + wait_queue_head_t wait_stop_wd; + + /* + * mei device states + */ + unsigned long reset_count; + enum mei_dev_state dev_state; + enum mei_hbm_state hbm_state; + u16 init_clients_timer; + + /* + * Power Gating support + */ + enum mei_pg_event pg_event; +#ifdef CONFIG_PM + struct dev_pm_domain pg_domain; +#endif /* CONFIG_PM */ + + unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; + u32 rd_msg_hdr; + + /* write buffer */ + u8 hbuf_depth; + bool hbuf_is_ready; + + /* used for control messages */ + struct { + struct mei_msg_hdr hdr; + unsigned char data[128]; + } wr_msg; + + struct hbm_version version; + unsigned int hbm_f_pg_supported:1; + unsigned int hbm_f_dc_supported:1; + unsigned int hbm_f_dot_supported:1; + unsigned int hbm_f_ev_supported:1; + + struct rw_semaphore me_clients_rwsem; + struct list_head me_clients; + DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX); + DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX); + unsigned long me_client_index; + + bool allow_fixed_address; + + struct mei_cl wd_cl; + enum mei_wd_states wd_state; + bool wd_pending; + u16 wd_timeout; + unsigned char wd_data[MEI_WD_START_MSG_SIZE]; + + + /* amthif list for cmd waiting */ + struct mei_cl_cb amthif_cmd_list; + /* driver managed amthif list for reading completed amthif cmd data */ + struct mei_cl_cb amthif_rd_complete_list; + struct file *iamthif_file_object; + struct mei_cl iamthif_cl; + struct mei_cl_cb *iamthif_current_cb; + long iamthif_open_count; + unsigned long iamthif_timer; + u32 iamthif_stall_timer; + enum iamthif_states iamthif_state; + bool iamthif_canceled; + + struct work_struct init_work; + struct work_struct reset_work; + + /* List of bus devices */ + struct list_head device_list; + struct mutex cl_bus_lock; + +#if IS_ENABLED(CONFIG_DEBUG_FS) + struct dentry *dbgfs_dir; +#endif /* CONFIG_DEBUG_FS */ + + + const struct mei_hw_ops *ops; + char hw[0] __aligned(sizeof(void *)); +}; + +static inline unsigned long mei_secs_to_jiffies(unsigned long sec) +{ + return msecs_to_jiffies(sec * MSEC_PER_SEC); +} + +/** + * mei_data2slots - get slots - number of (dwords) from a message length + * + size of the mei header + * + * @length: size of the messages in bytes + * + * Return: number of slots + */ +static inline u32 mei_data2slots(size_t length) +{ + return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); +} + +/** + * mei_slots2data - get data in slots - bytes from slots + * + * @slots: number of available slots + * + * Return: number of bytes in slots + */ +static inline u32 mei_slots2data(int slots) +{ + return slots * 4; +} + +/* + * mei init function prototypes + */ +void mei_device_init(struct mei_device *dev, + struct device *device, + const struct mei_hw_ops *hw_ops); +int mei_reset(struct mei_device *dev); +int mei_start(struct mei_device *dev); +int mei_restart(struct mei_device *dev); +void mei_stop(struct mei_device *dev); +void mei_cancel_work(struct mei_device *dev); + +/* + * MEI interrupt functions prototype + */ + +void mei_timer(struct work_struct *work); +int mei_irq_read_handler(struct mei_device *dev, + struct mei_cl_cb *cmpl_list, s32 *slots); + +int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list); +void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list); + +/* + * AMTHIF - AMT Host Interface Functions + */ +void mei_amthif_reset_params(struct mei_device *dev); + +int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl); + +int mei_amthif_read(struct mei_device *dev, struct file *file, + char __user *ubuf, size_t length, loff_t *offset); + +unsigned int mei_amthif_poll(struct mei_device *dev, + struct file *file, poll_table *wait); + +int mei_amthif_release(struct mei_device *dev, struct file *file); + +struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, + struct file *file); + +int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb); +int mei_amthif_run_next_cmd(struct mei_device *dev); +int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, + struct mei_cl_cb *cmpl_list); + +void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); +int mei_amthif_irq_read_msg(struct mei_cl *cl, + struct mei_msg_hdr *mei_hdr, + struct mei_cl_cb *complete_list); +int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); + +/* + * NFC functions + */ +int mei_nfc_host_init(struct mei_device *dev, struct mei_me_client *me_cl); +void mei_nfc_host_exit(struct mei_device *dev); + +/* + * NFC Client UUID + */ +extern const uuid_le mei_nfc_guid; + +int mei_wd_send(struct mei_device *dev); +int mei_wd_stop(struct mei_device *dev); +int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl); +/* + * mei_watchdog_register - Registering watchdog interface + * once we got connection to the WD Client + * @dev: mei device + */ +int mei_watchdog_register(struct mei_device *dev); +/* + * mei_watchdog_unregister - Unregistering watchdog interface + * @dev: mei device + */ +void mei_watchdog_unregister(struct mei_device *dev); + +/* + * Register Access Function + */ + + +static inline void mei_hw_config(struct mei_device *dev) +{ + dev->ops->hw_config(dev); +} + +static inline enum mei_pg_state mei_pg_state(struct mei_device *dev) +{ + return dev->ops->pg_state(dev); +} + +static inline bool mei_pg_in_transition(struct mei_device *dev) +{ + return dev->ops->pg_in_transition(dev); +} + +static inline bool mei_pg_is_enabled(struct mei_device *dev) +{ + return dev->ops->pg_is_enabled(dev); +} + +static inline int mei_hw_reset(struct mei_device *dev, bool enable) +{ + return dev->ops->hw_reset(dev, enable); +} + +static inline int mei_hw_start(struct mei_device *dev) +{ + return dev->ops->hw_start(dev); +} + +static inline void mei_clear_interrupts(struct mei_device *dev) +{ + dev->ops->intr_clear(dev); +} + +static inline void mei_enable_interrupts(struct mei_device *dev) +{ + dev->ops->intr_enable(dev); +} + +static inline void mei_disable_interrupts(struct mei_device *dev) +{ + dev->ops->intr_disable(dev); +} + +static inline bool mei_host_is_ready(struct mei_device *dev) +{ + return dev->ops->host_is_ready(dev); +} +static inline bool mei_hw_is_ready(struct mei_device *dev) +{ + return dev->ops->hw_is_ready(dev); +} + +static inline bool mei_hbuf_is_ready(struct mei_device *dev) +{ + return dev->ops->hbuf_is_ready(dev); +} + +static inline int mei_hbuf_empty_slots(struct mei_device *dev) +{ + return dev->ops->hbuf_free_slots(dev); +} + +static inline size_t mei_hbuf_max_len(const struct mei_device *dev) +{ + return dev->ops->hbuf_max_len(dev); +} + +static inline int mei_write_message(struct mei_device *dev, + struct mei_msg_hdr *hdr, + unsigned char *buf) +{ + return dev->ops->write(dev, hdr, buf); +} + +static inline u32 mei_read_hdr(const struct mei_device *dev) +{ + return dev->ops->read_hdr(dev); +} + +static inline void mei_read_slots(struct mei_device *dev, + unsigned char *buf, unsigned long len) +{ + dev->ops->read(dev, buf, len); +} + +static inline int mei_count_full_read_slots(struct mei_device *dev) +{ + return dev->ops->rdbuf_full_slots(dev); +} + +static inline int mei_fw_status(struct mei_device *dev, + struct mei_fw_status *fw_status) +{ + return dev->ops->fw_status(dev, fw_status); +} + +bool mei_hbuf_acquire(struct mei_device *dev); + +bool mei_write_is_idle(struct mei_device *dev); + +#if IS_ENABLED(CONFIG_DEBUG_FS) +int mei_dbgfs_register(struct mei_device *dev, const char *name); +void mei_dbgfs_deregister(struct mei_device *dev); +#else +static inline int mei_dbgfs_register(struct mei_device *dev, const char *name) +{ + return 0; +} +static inline void mei_dbgfs_deregister(struct mei_device *dev) {} +#endif /* CONFIG_DEBUG_FS */ + +int mei_register(struct mei_device *dev, struct device *parent); +void mei_deregister(struct mei_device *dev); + +#define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d internal=%1d comp=%1d" +#define MEI_HDR_PRM(hdr) \ + (hdr)->host_addr, (hdr)->me_addr, \ + (hdr)->length, (hdr)->internal, (hdr)->msg_complete + +ssize_t mei_fw_status2str(struct mei_fw_status *fw_sts, char *buf, size_t len); +/** + * mei_fw_status_str - fetch and convert fw status registers to printable string + * + * @dev: the device structure + * @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ + * @len: buffer len must be >= MEI_FW_STATUS_STR_SZ + * + * Return: number of bytes written or < 0 on failure + */ +static inline ssize_t mei_fw_status_str(struct mei_device *dev, + char *buf, size_t len) +{ + struct mei_fw_status fw_status; + int ret; + + buf[0] = '\0'; + + ret = mei_fw_status(dev, &fw_status); + if (ret) + return ret; + + ret = mei_fw_status2str(&fw_status, buf, MEI_FW_STATUS_STR_SZ); + + return ret; +} + + +#endif diff --git a/platform/broadcom/sonic-platform-modules-delta/agc032/cfg/agc032-modules.conf b/platform/broadcom/sonic-platform-modules-delta/agc032/cfg/agc032-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/agc032/cfg/agc032-modules.conf @@ -0,0 +1,13 @@ +# /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-delta/agc032/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/Makefile new file mode 100644 index 000000000000..93bd96998409 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/Makefile @@ -0,0 +1 @@ +obj-m := dni_agc032_psu.o dni_emc2305.o delta_agc032_platform.o delta_agc032_cpupld.o dni_emc2302.o delta_agc032_swpld.o delta_agc032_qsfp.o diff --git a/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_cpupld.c b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_cpupld.c new file mode 100644 index 000000000000..76ae53d314de --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_cpupld.c @@ -0,0 +1,746 @@ +#include +#include +#include +#include +#include +#include + +#define CPUPLD_I2C_ADDR 0x31 + +enum cpld_type { + cpld, +}; + +struct platform_data { + int reg_addr; + struct i2c_client *client; +}; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, +}; + +enum{ + CPU_PCB_NUM = 0, + CPUPLD_VER_TYPE, + CPUPLD_VER, + BDXDE_PLAT_RST, + BDXDE_SLP3_STAT, + BDXDE_SLP4_STAT, + BDXDE_CPU_RST, + CPLD_DEBUG_MODE, + APWROK_STAT, + EDGE_PROCHOT_SIG_DIS, + PSU_THERMAL_STAT, + PR_THERMAL_STAT, + ME_DRIVE_SIG_EN, + CPU_THERMAL_STAT, + DDR_THERMAL_STAT, + SYS_THERMAL_STAT, + DEBUG_LED3_EN, + DEBUG_LED2_EN, + DEBUG_LED1_EN, + DEBUG_LED0_EN, + CPU_STANDBY_MODE, + CPLD_RST, + MB_POWER_STAT, + BIOS1_SPI_WP, + BIOS2_SPI_WP, + BIOS_MUX_SEL, + GBE_SPI_WP, + PCH_THERMTRIP_EN, + ID_EEPROM_EN, + CPU_I2C_MUX_EN, + CPU_I2C_MUX_SEL, + PSU_FAN_INTR, + WD_TIMER, + WD_EN, + WD_CLEAR_FLAG, +}; + + +static unsigned char cpupld_reg_addr; + +static ssize_t cpupld_reg_value_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int ret; + struct platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[cpld].client, cpupld_reg_addr); + + return scnprintf(buf, PAGE_SIZE, "0x%02x\n", ret); +} + +static ssize_t cpupld_reg_value_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long data; + int err; + struct platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + i2c_smbus_write_byte_data(pdata[cpld].client, cpupld_reg_addr, data); + + return count; +} + +static ssize_t cpupld_reg_addr_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + + return scnprintf(buf, PAGE_SIZE, "0x%02x\n", cpupld_reg_addr); +} + +static ssize_t cpupld_reg_addr_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long data; + int err; + + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + cpupld_reg_addr = data; + + return count; +} + + +static ssize_t cpupld_data_show(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct platform_data *pdata = dev->platform_data; + unsigned int select = 0; + unsigned char offset = 0; + int mask = 0xFF; + int shift = 0; + int value = 0; + bool hex_fmt = 0; + char desc[256] = {0}; + + select = attr->index; + switch(select) { + case CPU_PCB_NUM: + offset = 0x0; + hex_fmt = 1; + scnprintf(desc, PAGE_SIZE, "\nCPU Borad PCB Number.\n"); + break; + case CPUPLD_VER_TYPE: + offset = 0x1; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nCPUPLD Version Type.\n"); + break; + case CPUPLD_VER: + offset = 0x1; + mask = 0x7F; + scnprintf(desc, PAGE_SIZE, "\nCPUPLD Version.\n"); + break; + case BDXDE_PLAT_RST: + offset = 0x9; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Platform Reset State\n“0” = Platform Not Reset State.\n"); + break; + case BDXDE_SLP3_STAT: + offset = 0x9; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = CPU at S3 State\n“0” = CPU Not at S3 State.\n"); + break; + case BDXDE_SLP4_STAT: + offset = 0x9; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = CPU at S4Sstate\n“0” = CPU Not at S4 State.\n"); + break; + case BDXDE_CPU_RST: + offset = 0x9; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = CPU Not Reset State\n“0” = CPU Reset State.\n"); + break; + case CPLD_DEBUG_MODE: + offset = 0x9; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nCPLD Power Sequence\n“1” = Debug Mode\n“0” = Normal Mode.\n"); + break; + case APWROK_STAT: + offset = 0xA; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = APWROK Stable\n“0” = APWROK Unstable.\n"); + break; + case EDGE_PROCHOT_SIG_DIS: + offset = 0xB; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Power Supply Thermal Signal\n“0” = Enable Power Supply Thermal Signal.\n"); + break; + case PSU_THERMAL_STAT: + offset = 0xB; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Power Supply Normal Temperature\n“0” = Power Supply Over Temperature.\n"); + break; + case PR_THERMAL_STAT: + offset = 0xB; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Power Rail Normal Temperature\n“0” = Power Rail Over Temperature.\n"); + break; + case ME_DRIVE_SIG_EN: + offset = 0xB; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable System Thermal Alarm to CPU\n“0” = System Thermal Alarm to CPU.\n"); + break; + case CPU_THERMAL_STAT: + offset = 0xB; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = CPU Disomic Normal Temperature\n“0” = CPU Disomic Over Temperatur.\n"); + break; + case DDR_THERMAL_STAT: + offset = 0xB; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = DDR Normal Temperature\n“0” = DDR Over Temperature.\n"); + break; + case SYS_THERMAL_STAT: + offset = 0xC; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = System Normal Temperature.\n“0” = System Over Temperature.\n"); + break; + case DEBUG_LED3_EN: + offset = 0xD; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Debug LED3\n“0” = Enable Debug LED3.\n"); + break; + case DEBUG_LED2_EN: + offset = 0xD; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Debug LED2\n“0” = Enable Debug LED2.\n"); + break; + case DEBUG_LED1_EN: + offset = 0xD; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Debug LED1\n“0” = Enable Debug LED1.\n"); + break; + case DEBUG_LED0_EN: + offset = 0xD; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Debug LED0\n“0” = Enable Debug LED0.\n"); + break; + case CPU_STANDBY_MODE: + offset = 0x11; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = CPU Power Stanby Not Ready\n“0” = CPU Power Stanby Ready.\n"); + break; + case CPLD_RST: + offset = 0x11; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation\n“0” = CPLD Reset.\n"); + break; + case MB_POWER_STAT: + offset = 0x12; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Power Rail Good\n“0” = Power Rail Failed.\n"); + break; + case BIOS2_SPI_WP: + offset = 0x13; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable BIOS2 SPI Write Protect\n“0” = Enable BIOS2 SPI Write Protect.\n"); + break; + case BIOS1_SPI_WP: + offset = 0x13; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable BIOS1 SPI Write Protect\n“0” = Enable BIOS1 SPI Write Protect.\n"); + break; + case BIOS_MUX_SEL: + offset = 0x13; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Primary BIOS\n“0” = Backup BIOS.\n"); + break; + case GBE_SPI_WP: + offset = 0x13; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable GBE SPI Write Protect\n“0” = Enable GBE SPI Write Protect.\n"); + break; + case PCH_THERMTRIP_EN: + offset = 0x14; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Thermal Trip Not Occured\n“0” = Thermal Trip Occured.\n"); + break; + case ID_EEPROM_EN: + offset = 0x14; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable ID EEPROM Write Protect\n“0” = Enable ID EEPROM Write Protect.\n"); + break; + case CPU_I2C_MUX_EN: + offset = 0x14; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable CPU I2C Mux\n“0” = Disable CPU I2C Mux.\n"); + break; + case CPU_I2C_MUX_SEL: + offset = 0x14; + shift = 0; + mask = 0x3; + scnprintf(desc, PAGE_SIZE, "\n“3” = Select MB Panel Port.\n“2” = Select MB SWPLD.\n“1” = Select MB Mux.\n“0” = Select ONIE EEPROM.\n"); + break; + case PSU_FAN_INTR: + offset = 0x15; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = PSU Fan Interrupt Occured\n“0” = PSU Fan Interrupt Not Occured.\n"); + break; + case WD_TIMER: + offset = 0x1E; + shift = 3; + mask = 0x38; + scnprintf(desc, PAGE_SIZE, "\n“5” = Timer 60 sec.\n“4” = Timer 50 sec.\n“3” = Timer 40 sec.\n“2” = Timer 30 sec.\n“1” = Timer 20 sec.\n“0” = Timer 15 sec.\n"); + break; + case WD_EN: + offset = 0x1E; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable Watchdog Function\n“0” = Enable Watchdog Function.\n"); + break; + case WD_CLEAR_FLAG: + offset = 0x1E; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Watchdog Timer Flag Clear\n“0” = Watchdog Timer Flag Not Clear.\n"); + break; + } + + value = i2c_smbus_read_byte_data(pdata[cpld].client, offset); + value = (value & mask) >> shift; + if(hex_fmt) { + return scnprintf(buf, PAGE_SIZE, "0x%02x%s", value, desc); + } else { + return scnprintf(buf, PAGE_SIZE, "%d%s", value, desc); + } +} + +static ssize_t cpupld_data_store(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct platform_data *pdata = dev->platform_data; + unsigned int select = 0; + unsigned char offset = 0; + int mask = 0xFF; + int shift = 0; + int value = 0; + int err = 0; + unsigned long data; + + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + switch (attr->index) { + case DEBUG_LED3_EN: + offset = 0xD; + shift = 3; + mask = (1 << shift); + break; + case DEBUG_LED2_EN: + offset = 0xD; + shift = 2; + mask = (1 << shift); + break; + case DEBUG_LED1_EN: + offset = 0xD; + shift = 1; + mask = (1 << shift); + break; + case DEBUG_LED0_EN: + offset = 0xD; + shift = 0; + mask = (1 << shift); + break; + case CPLD_RST: + offset = 0x11; + shift = 0; + mask = (1 << shift); + break; + case MB_POWER_STAT: + offset = 0x12; + shift = 2; + mask = (1 << shift); + break; + case BIOS2_SPI_WP: + offset = 0x13; + shift = 3; + mask = (1 << shift); + break; + case BIOS1_SPI_WP: + offset = 0x13; + shift = 2; + mask = (1 << shift); + break; + case BIOS_MUX_SEL: + offset = 0x13; + shift = 1; + mask = (1 << shift); + break; + case GBE_SPI_WP: + offset = 0x13; + shift = 0; + mask = (1 << shift); + break; + case PCH_THERMTRIP_EN: + offset = 0x14; + shift = 4; + mask = (1 << shift); + break; + case ID_EEPROM_EN: + offset = 0x14; + shift = 3; + mask = (1 << shift); + break; + case CPU_I2C_MUX_EN: + offset = 0x14; + shift = 2; + mask = (1 << shift); + break; + case CPU_I2C_MUX_SEL: + offset = 0x14; + shift = 0; + mask = 0x3; + break; + case WD_TIMER: + offset = 0x1E; + shift = 3; + mask = 0x38; + break; + case WD_EN: + offset = 0x1E; + shift = 2; + mask = (1 << shift); + break; + case WD_CLEAR_FLAG: + offset = 0x1E; + shift = 0; + mask = (1 << shift); + break; + } + + value = i2c_smbus_read_byte_data(pdata[cpld].client, offset); + data = (value & ~mask) | (data << shift); + i2c_smbus_write_byte_data(pdata[cpld].client, offset, data); + + return count; +} + +static DEVICE_ATTR(cpupld_reg_value, S_IRUGO | S_IWUSR, cpupld_reg_value_show, cpupld_reg_value_store); +static DEVICE_ATTR(cpupld_reg_addr, S_IRUGO | S_IWUSR, cpupld_reg_addr_show, cpupld_reg_addr_store); + +/* offset 0x0 */ +static SENSOR_DEVICE_ATTR(cpu_pcb_num, S_IRUGO, cpupld_data_show, NULL, CPU_PCB_NUM ); +/* offset 0x1 */ +static SENSOR_DEVICE_ATTR(cpupld_ver_type, S_IRUGO, cpupld_data_show, NULL, CPUPLD_VER_TYPE ); +static SENSOR_DEVICE_ATTR(cpupld_ver, S_IRUGO, cpupld_data_show, NULL, CPUPLD_VER ); +#if 0 +/* offset 0x5 */ +static SENSOR_DEVICE_ATTR(p1v2_vddq_en, S_IRUGO, cpupld_data_show, NULL, P1V2_VDDQ_EN ); +static SENSOR_DEVICE_ATTR(p1v5_pch_en, S_IRUGO, cpupld_data_show, NULL, P1V5_PCH_EN ); +static SENSOR_DEVICE_ATTR(p2v5_vpp_en, S_IRUGO, cpupld_data_show, NULL, P2V5_VPP_EN ); +static SENSOR_DEVICE_ATTR(pvccin_en, S_IRUGO, cpupld_data_show, NULL, PVCCIN_EN ); +static SENSOR_DEVICE_ATTR(pvccioin_en, S_IRUGO, cpupld_data_show, NULL, PVCCIOIN_EN ); +static SENSOR_DEVICE_ATTR(pvcckrhv_en, S_IRUGO, cpupld_data_show, NULL, PVCCKRHV_EN ); +static SENSOR_DEVICE_ATTR(pvccscfusesus_en, S_IRUGO, cpupld_data_show, NULL, PVCCSCFUSESUS_EN ); +static SENSOR_DEVICE_ATTR(vr_p3v3_en, S_IRUGO, cpupld_data_show, NULL, VR_P3V3_EN ); +/* offset 0x6 */ +static SENSOR_DEVICE_ATTR(cpu_sys_power, S_IRUGO, cpupld_data_show, NULL, CPU_SYS_POWER ); +static SENSOR_DEVICE_ATTR(p0v6_vtt_dimm_en, S_IRUGO, cpupld_data_show, NULL, P0V6_VTT_DIMM_EN ); +static SENSOR_DEVICE_ATTR(p1v05_pch_en, S_IRUGO, cpupld_data_show, NULL, P1V05_PCH_EN ); +/* offser 0x7 */ +static SENSOR_DEVICE_ATTR(p1v5_pch_pwrgd, S_IRUGO, cpupld_data_show, NULL, P1V5_PCH_GOOD ); +static SENSOR_DEVICE_ATTR(p2v5_vpp_pwrgd, S_IRUGO, cpupld_data_show, NULL, P2V5_VPP_GOOD ); +static SENSOR_DEVICE_ATTR(pch_pwr_pwrgd, S_IRUGO, cpupld_data_show, NULL, PCH_PWR_GOOD ); +static SENSOR_DEVICE_ATTR(pvccin_pwrgd, S_IRUGO, cpupld_data_show, NULL, PVCCIN_GOOD ); +static SENSOR_DEVICE_ATTR(pvccioin_pwrgd, S_IRUGO, cpupld_data_show, NULL, PVCCIOIN_GOOD ); +static SENSOR_DEVICE_ATTR(pvcckrhv_pwrgd, S_IRUGO, cpupld_data_show, NULL, PVCCKRHV_GOOD ); +static SENSOR_DEVICE_ATTR(pvccscfusesus_pwrgd, S_IRUGO, cpupld_data_show, NULL, PVCCSCFUSESUS_GOOD ); +static SENSOR_DEVICE_ATTR(vr_p3v3_pwrgd, S_IRUGO, cpupld_data_show, NULL, VR_P3V3_GOOD ); +/* offset 0x8 */ +static SENSOR_DEVICE_ATTR(bdxde_lan_pwrgd, S_IRUGO, cpupld_data_show, NULL, BDXDE_LAN_GOOD ); +static SENSOR_DEVICE_ATTR(CPU0_pwrgd, S_IRUGO, cpupld_data_show, NULL, CPU0_GOOD ); +static SENSOR_DEVICE_ATTR(p0v6_vtt_dimm_pwrgd, S_IRUGO, cpupld_data_show, NULL, P0V6_VTT_DIMM_GOOD ); +static SENSOR_DEVICE_ATTR(p1v05_procio_pwrgd, S_IRUGO, cpupld_data_show, NULL, P1V05_PROCIO_GOOD ); +static SENSOR_DEVICE_ATTR(p1v2_vddq_pwrgd, S_IRUGO, cpupld_data_show, NULL, P1V2_VDDQ_GOOD ); +#endif +/* offset 0x9 */ +static SENSOR_DEVICE_ATTR(bdxde_plat_rst, S_IRUGO, cpupld_data_show, NULL, BDXDE_PLAT_RST ); +static SENSOR_DEVICE_ATTR(bdxde_slp3_stat, S_IRUGO, cpupld_data_show, NULL, BDXDE_SLP3_STAT ); +static SENSOR_DEVICE_ATTR(bdxde_slp4_stat, S_IRUGO, cpupld_data_show, NULL, BDXDE_SLP4_STAT ); +static SENSOR_DEVICE_ATTR(bdxde_cpu_rst, S_IRUGO, cpupld_data_show, NULL, BDXDE_CPU_RST ); +static SENSOR_DEVICE_ATTR(cpld_debug_mode, S_IRUGO, cpupld_data_show, NULL, CPLD_DEBUG_MODE ); +/* offset 0xA */ +static SENSOR_DEVICE_ATTR(apwrok_stat, S_IRUGO, cpupld_data_show, NULL, APWROK_STAT ); +//static SENSOR_DEVICE_ATTR(cpu_standby_mode, S_IRUGO, cpupld_data_show, NULL, CPU_STANDBY_MODE ); +/* offset 0xB */ +static SENSOR_DEVICE_ATTR(edge_prochot_sig_dis, S_IRUGO, cpupld_data_show, NULL, EDGE_PROCHOT_SIG_DIS ); +static SENSOR_DEVICE_ATTR(psu_thermal_stat, S_IRUGO, cpupld_data_show, NULL, PSU_THERMAL_STAT ); +static SENSOR_DEVICE_ATTR(pr_thermal_stat, S_IRUGO, cpupld_data_show, NULL, PR_THERMAL_STAT ); +static SENSOR_DEVICE_ATTR(me_drv_sig_en, S_IRUGO, cpupld_data_show, NULL, ME_DRIVE_SIG_EN ); +static SENSOR_DEVICE_ATTR(cpu_thermal_stat, S_IRUGO, cpupld_data_show, NULL, CPU_THERMAL_STAT ); +static SENSOR_DEVICE_ATTR(ddr_thermal_stat, S_IRUGO, cpupld_data_show, NULL, DDR_THERMAL_STAT ); +/* offset 0xC */ +static SENSOR_DEVICE_ATTR(sys_thermal_stat, S_IRUGO, cpupld_data_show, NULL, SYS_THERMAL_STAT ); +/* offset 0xD */ +static SENSOR_DEVICE_ATTR(debug_led3_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, DEBUG_LED3_EN ); +static SENSOR_DEVICE_ATTR(debug_led2_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, DEBUG_LED2_EN ); +static SENSOR_DEVICE_ATTR(debug_led1_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, DEBUG_LED1_EN ); +static SENSOR_DEVICE_ATTR(debug_led0_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, DEBUG_LED0_EN ); +/* offset 0x11 */ +static SENSOR_DEVICE_ATTR(cpu_standby_mode, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, CPU_STANDBY_MODE ); +static SENSOR_DEVICE_ATTR(cpld_rst, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, CPLD_RST ); +/* offset 0x12 */ +static SENSOR_DEVICE_ATTR(mb_power_stat, S_IRUGO, cpupld_data_show, NULL, MB_POWER_STAT ); +/* offset 0x13 */ +static SENSOR_DEVICE_ATTR(bios1_spi_wp, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, BIOS1_SPI_WP ); +static SENSOR_DEVICE_ATTR(bios2_spi_wp, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, BIOS2_SPI_WP ); +static SENSOR_DEVICE_ATTR(bios_mux_sel, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, BIOS_MUX_SEL ); +static SENSOR_DEVICE_ATTR(gbe_spi_wp, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, GBE_SPI_WP ); +/* offset 0x14 */ +static SENSOR_DEVICE_ATTR(pch_thermtrip_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, PCH_THERMTRIP_EN ); +static SENSOR_DEVICE_ATTR(id_eeprom_wp, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, ID_EEPROM_EN ); +static SENSOR_DEVICE_ATTR(cpu_i2c_mux_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, CPU_I2C_MUX_EN ); +static SENSOR_DEVICE_ATTR(cpu_i2c_mux_sel, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, CPU_I2C_MUX_SEL ); +/* offset 0x15 */ +static SENSOR_DEVICE_ATTR(psu_fan_intr, S_IRUGO, cpupld_data_show, NULL, PSU_FAN_INTR ); +/* offset 0x1E */ +static SENSOR_DEVICE_ATTR(wd_timer, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, WD_TIMER ); +static SENSOR_DEVICE_ATTR(wd_en, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, WD_EN ); +static SENSOR_DEVICE_ATTR(wd_clear_flag, S_IRUGO|S_IWUSR, cpupld_data_show, cpupld_data_store, WD_CLEAR_FLAG ); + + +static struct attribute *agc032_cpupld_attrs[] = { + &dev_attr_cpupld_reg_value.attr, + &dev_attr_cpupld_reg_addr.attr, + &sensor_dev_attr_cpu_pcb_num.dev_attr.attr, + &sensor_dev_attr_cpupld_ver_type.dev_attr.attr, + &sensor_dev_attr_cpupld_ver.dev_attr.attr, + &sensor_dev_attr_bdxde_plat_rst.dev_attr.attr, + &sensor_dev_attr_bdxde_slp3_stat.dev_attr.attr, + &sensor_dev_attr_bdxde_slp4_stat.dev_attr.attr, + &sensor_dev_attr_bdxde_cpu_rst.dev_attr.attr, + &sensor_dev_attr_cpld_debug_mode.dev_attr.attr, + &sensor_dev_attr_apwrok_stat.dev_attr.attr, + &sensor_dev_attr_edge_prochot_sig_dis.dev_attr.attr, + &sensor_dev_attr_psu_thermal_stat.dev_attr.attr, + &sensor_dev_attr_pr_thermal_stat.dev_attr.attr, + &sensor_dev_attr_me_drv_sig_en.dev_attr.attr, + &sensor_dev_attr_cpu_thermal_stat.dev_attr.attr, + &sensor_dev_attr_ddr_thermal_stat.dev_attr.attr, + &sensor_dev_attr_sys_thermal_stat.dev_attr.attr, + &sensor_dev_attr_debug_led3_en.dev_attr.attr, + &sensor_dev_attr_debug_led2_en.dev_attr.attr, + &sensor_dev_attr_debug_led1_en.dev_attr.attr, + &sensor_dev_attr_debug_led0_en.dev_attr.attr, + &sensor_dev_attr_cpu_standby_mode.dev_attr.attr, + &sensor_dev_attr_cpld_rst.dev_attr.attr, + &sensor_dev_attr_mb_power_stat.dev_attr.attr, + &sensor_dev_attr_bios1_spi_wp.dev_attr.attr, + &sensor_dev_attr_bios2_spi_wp.dev_attr.attr, + &sensor_dev_attr_bios_mux_sel.dev_attr.attr, + &sensor_dev_attr_gbe_spi_wp.dev_attr.attr, + &sensor_dev_attr_pch_thermtrip_en.dev_attr.attr, + &sensor_dev_attr_id_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_cpu_i2c_mux_en.dev_attr.attr, + &sensor_dev_attr_cpu_i2c_mux_sel.dev_attr.attr, + &sensor_dev_attr_psu_fan_intr.dev_attr.attr, + &sensor_dev_attr_wd_timer.dev_attr.attr, + &sensor_dev_attr_wd_en.dev_attr.attr, + &sensor_dev_attr_wd_clear_flag.dev_attr.attr, + NULL, +}; + +static struct attribute_group agc032_cpupld_attr_group = { + .attrs = agc032_cpupld_attrs, +}; + +static int __init cpupld_probe(struct platform_device *pdev) +{ + struct platform_data *pdata; + struct i2c_adapter *parent; + int rv; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPUPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS0); + if (!parent) { + printk(KERN_ERR "Parent adapter (%d) not found\n",BUS0); + return -ENODEV; + } + + pdata[cpld].client = i2c_new_dummy(parent, pdata[cpld].reg_addr); + if (!pdata[cpld].client) { + printk(KERN_ERR "Fail to create dummy i2c client for addr %d\n", pdata[cpld].reg_addr); + goto error; + } +#if 0 + /* set default cpu_i2c_mux 0x14 be 0x1 */ + rv = i2c_smbus_write_byte_data(pdata[cpld].client, 0x14, 0x1); + if (rv < 0) { + printk(KERN_WARNING, "Error: Failed to set addr 0x14.\n"); + goto error; + } +#endif + /* /sys/device/platform */ + rv = sysfs_create_group(&pdev->dev.kobj, &agc032_cpupld_attr_group); + if (rv){ + printk(KERN_ERR "Fail to create cpupld attribute group"); + goto error; + } + return 0; + +error: + i2c_unregister_device(pdata[cpld].client); + i2c_put_adapter(parent); + return -ENODEV; +} + + +static int __exit cpupld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &agc032_cpupld_attr_group); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[cpld].client) { + if (!parent) { + parent = (pdata[cpld].client)->adapter; + } + i2c_unregister_device(pdata[cpld].client); + } + } + i2c_put_adapter(parent); + return 0; +} + + +static struct platform_driver cpupld_driver = { + .probe = cpupld_probe, + .remove = __exit_p(cpupld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc032-cpupld", + }, +}; + + +static struct platform_data agc032_cpupld_platform_data[] = { + [cpld] = { + .reg_addr = CPUPLD_I2C_ADDR, + }, +}; + +static void device_release(struct device *dev) +{ + return; +} + +static struct platform_device cpupld_agc032 = { + .name = "delta-agc032-cpupld", + .id = 0, + .dev = { + .platform_data = agc032_cpupld_platform_data, + .release = device_release + }, +}; + +/* module initialization */ +static int __init delta_agc032_cpupld_init(void) +{ + int rc = 0; + printk(KERN_INFO "CPUPLD module initializating\n"); + + /* register CPUPLD driver */ + rc = platform_driver_register(&cpupld_driver); + if (rc < 0) { + printk(KERN_ERR "Fail to register CPUPLD driver, rc = %d\n", rc); + goto error_register_driver; + } + + /* register CPUPLD device */ + rc = platform_device_register(&cpupld_agc032); + if (rc) { + printk(KERN_ERR "Fail to create cpupld device, rc = %d\n", rc); + goto error_register_device; + } + return 0; + +error_register_device: + platform_driver_unregister(&cpupld_driver); +error_register_driver: + return rc; +} + +static void __exit delta_agc032_cpupld_exit(void) +{ + platform_device_unregister(&cpupld_agc032); + platform_driver_unregister(&cpupld_driver); +} + +module_init(delta_agc032_cpupld_init); +module_exit(delta_agc032_cpupld_exit); + +MODULE_DESCRIPTION("DNI agc032 CPLD Platform Support"); +MODULE_AUTHOR("James Ke "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_platform.c b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_platform.c new file mode 100644 index 000000000000..121ccc4d8b2d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_platform.c @@ -0,0 +1,299 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#define agc032_i2c_device_num(c){ \ + .name = "delta-agc032-i2c-device", \ + .id = c, \ + .dev = { \ + .platform_data = &agc032_i2c_device_platform_data[c], \ + .release = device_release, \ + }, \ +} + + + +/* Define struct to get client of i2c_new_deivce at 0x70 */ +struct i2c_client * i2c_client_9548; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, +}; + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; + +/* pca9548 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = { + { .adap_id = 1, + .deselect_on_exit = 1, + }, + { .adap_id = 2, + .deselect_on_exit = 1, + }, + { .adap_id = 3, + .deselect_on_exit = 1, + }, + { .adap_id = 4, + .deselect_on_exit = 1, + }, + { .adap_id = 5, + .deselect_on_exit = 1, + }, + { .adap_id = 6, + .deselect_on_exit = 1, + }, + { .adap_id = 7, + .deselect_on_exit = 1, + }, + { .adap_id = 8, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = { + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct i2c_board_info __initdata i2c_info_pca9548[] = +{ + { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &pca954x_data, + }, +}; + +static struct i2c_device_platform_data agc032_i2c_device_platform_data[] = { + { + /* psu 1 (0x58) */ + .parent = 1, + .info = { .type = "dni_agc032_psu", .addr = 0x58, .platform_data = (void *) 0 }, + .client = NULL, + }, + { + /* psu 2 (0x58) */ + .parent = 2, + .info = { .type = "dni_agc032_psu", .addr = 0x58, .platform_data = (void *) 1 }, + .client = NULL, + }, + { + /* FAN 1 Controller (0x2e) */ + .parent = 4, + .info = { I2C_BOARD_INFO("emc2302", 0x2e) }, + .client = NULL, + }, + { + /* FAN 2 Controller (0x4c) */ + .parent = 4, + .info = { I2C_BOARD_INFO("emc2305", 0x4c) }, + .client = NULL, + }, + { + /* FAN 3 Controller (0x2d) */ + .parent = 4, + .info = { I2C_BOARD_INFO("emc2305", 0x2d) }, + .client = NULL, + }, + { + /* tmp75 (0x4f) */ + .parent = 4, + .info = { I2C_BOARD_INFO("tmp75", 0x4f) }, + .client = NULL, + }, + { + /* tmp75 (0x49) */ + .parent = 5, + .info = { I2C_BOARD_INFO("tmp75", 0x49) }, + .client = NULL, + }, + { + /* tmp75 (0x4a) */ + .parent = 5, + .info = { I2C_BOARD_INFO("tmp75", 0x4a) }, + .client = NULL, + }, + { + /* tmp75 (0x4b) */ + .parent = 5, + .info = { I2C_BOARD_INFO("tmp75", 0x4b) }, + .client = NULL, + }, + { + /* tmp75 (0x4d) */ + .parent = 5, + .info = { I2C_BOARD_INFO("tmp75", 0x4d) }, + .client = NULL, + }, + { + /* tmp75 (0x4e) */ + .parent = 5, + .info = { I2C_BOARD_INFO("tmp75", 0x4e) }, + .client = NULL, + }, +}; + +static void device_release(struct device *dev) +{ + return; +} + +static struct platform_device agc032_i2c_device[] = { + agc032_i2c_device_num(0), + agc032_i2c_device_num(1), + agc032_i2c_device_num(2), + agc032_i2c_device_num(3), + agc032_i2c_device_num(4), + agc032_i2c_device_num(5), + agc032_i2c_device_num(6), + agc032_i2c_device_num(7), + agc032_i2c_device_num(8), + agc032_i2c_device_num(9), + agc032_i2c_device_num(10), +}; + +static int __init i2c_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} + + +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc032-i2c-device", + } +}; + +static int __init delta_agc032_platform_init(void) +{ + struct i2c_adapter *adapter; + struct cpld_platform_data *cpld_pdata; + int ret = 0; + int cnt = 0; + + printk("agc032_platform module initialization\n"); + + adapter = i2c_get_adapter(BUS0); +// i2c_client_9548 = i2c_new_device(adapter, &i2c_info_pca9548[0]); + + i2c_put_adapter(adapter); + + /* register the i2c devices */ + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + for (cnt = 0; cnt < ARRAY_SIZE(agc032_i2c_device); cnt++) + { + ret = platform_device_register(&agc032_i2c_device[cnt]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", cnt); + goto error_agc032_i2c_device; + } + } + + return 0; + +error_agc032_i2c_device: + for (; cnt >= 0; cnt--) { + platform_device_unregister(&agc032_i2c_device[cnt]); + } + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + return ret; +} + +static void __exit delta_agc032_platform_exit(void) +{ + int i = 0; + + for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device); i++ ) { + platform_device_unregister(&agc032_i2c_device[i]); + } + + platform_driver_unregister(&i2c_device_driver); +// i2c_unregister_device(i2c_client_9548); +} + + +module_init(delta_agc032_platform_init); +module_exit(delta_agc032_platform_exit); + +MODULE_DESCRIPTION("DNI agc032 Platform Support"); +MODULE_AUTHOR("James Ke "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_qsfp.c b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_qsfp.c new file mode 100644 index 000000000000..df58430b6aa6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_qsfp.c @@ -0,0 +1,819 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#define agc032_i2c_device1_num(c){ \ + .name = "delta-agc032-i2c-pca9548-1", \ + .id = c, \ + .dev = { \ + .platform_data = &agc032_i2c_device_pca9548_1_data[c], \ + .release = device_release, \ + }, \ +} + +#define agc032_i2c_device2_num(c){ \ + .name = "delta-agc032-i2c-pca9548-2", \ + .id = c, \ + .dev = { \ + .platform_data = &agc032_i2c_device_pca9548_2_data[c], \ + .release = device_release, \ + }, \ +} + +#define agc032_i2c_device3_num(c){ \ + .name = "delta-agc032-i2c-pca9548-3", \ + .id = c, \ + .dev = { \ + .platform_data = &agc032_i2c_device_pca9548_3_data[c], \ + .release = device_release, \ + }, \ +} + +#define agc032_i2c_device4_num(c){ \ + .name = "delta-agc032-i2c-pca9548-4", \ + .id = c, \ + .dev = { \ + .platform_data = &agc032_i2c_device_pca9548_4_data[c], \ + .release = device_release, \ + }, \ +} + +#define agc032_i2c_device5_num(c){ \ + .name = "delta-agc032-i2c-pca9548-5", \ + .id = c, \ + .dev = { \ + .platform_data = &agc032_i2c_device_pca9548_5_data[c], \ + .release = device_release, \ + }, \ +} + +/* Define struct to get client of i2c_new_deivce at 0x70, 0x71, 0x72, 0x73 */ +struct i2c_client * i2c_client_9548_1; +struct i2c_client * i2c_client_9548_2; +struct i2c_client * i2c_client_9548_3; +struct i2c_client * i2c_client_9548_4; +struct i2c_client * i2c_client_9548_5; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, +}; + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; + +/* pca9548-1 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = { + { .adap_id = 1, + .deselect_on_exit = 1, + }, + { .adap_id = 2, + .deselect_on_exit = 1, + }, + { .adap_id = 3, + .deselect_on_exit = 1, + }, + { .adap_id = 4, + .deselect_on_exit = 1, + }, + { .adap_id = 5, + .deselect_on_exit = 1, + }, + { .adap_id = 6, + .deselect_on_exit = 1, + }, + { .adap_id = 7, + .deselect_on_exit = 1, + }, + { .adap_id = 8, + .deselect_on_exit = 1, + }, +}; + +/* pca9548-2 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode2[] = { + { .adap_id = 9, + .deselect_on_exit = 1, + }, + { .adap_id = 10, + .deselect_on_exit = 1, + }, + { .adap_id = 11, + .deselect_on_exit = 1, + }, + { .adap_id = 12, + .deselect_on_exit = 1, + }, + { .adap_id = 13, + .deselect_on_exit = 1, + }, + { .adap_id = 14, + .deselect_on_exit = 1, + }, + { .adap_id = 15, + .deselect_on_exit = 1, + }, + { .adap_id = 16, + .deselect_on_exit = 1, + }, +}; + +/* pca9548-3 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode3[] = { + { .adap_id = 17, + .deselect_on_exit = 1, + }, + { .adap_id = 18, + .deselect_on_exit = 1, + }, + { .adap_id = 19, + .deselect_on_exit = 1, + }, + { .adap_id = 20, + .deselect_on_exit = 1, + }, + { .adap_id = 21, + .deselect_on_exit = 1, + }, + { .adap_id = 22, + .deselect_on_exit = 1, + }, + { .adap_id = 23, + .deselect_on_exit = 1, + }, + { .adap_id = 24, + .deselect_on_exit = 1, + }, +}; + +/* pca9548-4 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode4[] = { + { .adap_id = 25, + .deselect_on_exit = 1, + }, + { .adap_id = 26, + .deselect_on_exit = 1, + }, + { .adap_id = 27, + .deselect_on_exit = 1, + }, + { .adap_id = 28, + .deselect_on_exit = 1, + }, + { .adap_id = 29, + .deselect_on_exit = 1, + }, + { .adap_id = 30, + .deselect_on_exit = 1, + }, + { .adap_id = 31, + .deselect_on_exit = 1, + }, + { .adap_id = 32, + .deselect_on_exit = 1, + }, +}; + +/* pca9548-5 - add 2 bus */ +static struct pca954x_platform_mode pca954x_mode5[] = { + { .adap_id = 33, + .deselect_on_exit = 1, + }, + { .adap_id = 34, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = { + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct pca954x_platform_data pca954x_data2 = { + .modes = pca954x_mode2, + .num_modes = ARRAY_SIZE(pca954x_mode2), +}; + +static struct pca954x_platform_data pca954x_data3 = { + .modes = pca954x_mode3, + .num_modes = ARRAY_SIZE(pca954x_mode3), +}; + +static struct pca954x_platform_data pca954x_data4 = { + .modes = pca954x_mode4, + .num_modes = ARRAY_SIZE(pca954x_mode4), +}; + +static struct pca954x_platform_data pca954x_data5 = { + .modes = pca954x_mode5, + .num_modes = ARRAY_SIZE(pca954x_mode5), +}; + +static struct i2c_board_info __initdata i2c_info_pca9548[] = +{ + { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &pca954x_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x71), + .platform_data = &pca954x_data2, + }, + { + I2C_BOARD_INFO("pca9548", 0x72), + .platform_data = &pca954x_data3, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca954x_data4, + }, + { + I2C_BOARD_INFO("pca9548", 0x74), + .platform_data = &pca954x_data5, + }, +}; + +static struct i2c_device_platform_data agc032_i2c_device_pca9548_1_data[] = { + { + // qsfp 1 (0x50) + .parent = 1, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 2 (0x50) + .parent = 2, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 3 (0x50) + .parent = 3, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 4 (0x50) + .parent = 4, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 5 (0x50) + .parent = 5, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 6 (0x50) + .parent = 6, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 7 (0x50) + .parent = 7, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 8 (0x50) + .parent = 8, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, +}; + +static struct i2c_device_platform_data agc032_i2c_device_pca9548_2_data[] = { + { + // qsfp 9 (0x50) + .parent = 9, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 10 (0x50) + .parent = 10, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 11 (0x50) + .parent = 11, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 12 (0x50) + .parent = 12, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 13 (0x50) + .parent = 13, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 14 (0x50) + .parent = 14, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 15 (0x50) + .parent = 15, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 16 (0x50) + .parent = 16, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, +}; + +static struct i2c_device_platform_data agc032_i2c_device_pca9548_3_data[] = { + { + // qsfp 17 (0x50) + .parent = 17, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 18 (0x50) + .parent = 18, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 19 (0x50) + .parent = 19, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 20 (0x50) + .parent = 20, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 21 (0x50) + .parent = 21, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 22 (0x50) + .parent = 22, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 23 (0x50) + .parent = 23, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 24 (0x50) + .parent = 24, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, +}; + +static struct i2c_device_platform_data agc032_i2c_device_pca9548_4_data[] = { + { + // qsfp 25 (0x50) + .parent = 25, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 26 (0x50) + .parent = 26, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 27 (0x50) + .parent = 27, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 28 (0x50) + .parent = 28, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 29 (0x50) + .parent = 29, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 30 (0x50) + .parent = 30, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 31 (0x50) + .parent = 31, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 32 (0x50) + .parent = 32, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, +}; + +static struct i2c_device_platform_data agc032_i2c_device_pca9548_5_data[] = { + { + // qsfp 33 (0x50) + .parent = 33, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + // qsfp 34 (0x50) + .parent = 34, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, +}; + +static void device_release(struct device *dev) +{ + return; +} + +static struct platform_device agc032_i2c_device1[] = { + agc032_i2c_device1_num(0), + agc032_i2c_device1_num(1), + agc032_i2c_device1_num(2), + agc032_i2c_device1_num(3), + agc032_i2c_device1_num(4), + agc032_i2c_device1_num(5), + agc032_i2c_device1_num(6), + agc032_i2c_device1_num(7), +}; + +static struct platform_device agc032_i2c_device2[] = { + agc032_i2c_device2_num(0), + agc032_i2c_device2_num(1), + agc032_i2c_device2_num(2), + agc032_i2c_device2_num(3), + agc032_i2c_device2_num(4), + agc032_i2c_device2_num(5), + agc032_i2c_device2_num(6), + agc032_i2c_device2_num(7), +}; + +static struct platform_device agc032_i2c_device3[] = { + agc032_i2c_device3_num(0), + agc032_i2c_device3_num(1), + agc032_i2c_device3_num(2), + agc032_i2c_device3_num(3), + agc032_i2c_device3_num(4), + agc032_i2c_device3_num(5), + agc032_i2c_device3_num(6), + agc032_i2c_device3_num(7), +}; + +static struct platform_device agc032_i2c_device4[] = { + agc032_i2c_device4_num(0), + agc032_i2c_device4_num(1), + agc032_i2c_device4_num(2), + agc032_i2c_device4_num(3), + agc032_i2c_device4_num(4), + agc032_i2c_device4_num(5), + agc032_i2c_device4_num(6), + agc032_i2c_device4_num(7), +}; + +static struct platform_device agc032_i2c_device5[] = { + agc032_i2c_device5_num(0), + agc032_i2c_device5_num(1), +}; + + +static int __init i2c_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} + + +static struct platform_driver i2c_device_pca9548_1_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc032-i2c-pca9548-1", + } +}; + +static struct platform_driver i2c_device_pca9548_2_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc032-i2c-pca9548-2", + } +}; + +static struct platform_driver i2c_device_pca9548_3_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc032-i2c-pca9548-3", + } +}; + +static struct platform_driver i2c_device_pca9548_4_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc032-i2c-pca9548-4", + } +}; + +static struct platform_driver i2c_device_pca9548_5_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc032-i2c-pca9548-5", + } +}; + +static int __init delta_agc032_platform_init(void) +{ + struct i2c_adapter *adapter; + int ret = 0; + int device1_cnt = 0; + int device2_cnt = 0; + int device3_cnt = 0; + int device4_cnt = 0; + int device5_cnt = 0; + + printk("agc032_qsfp module initialization\n"); + + adapter = i2c_get_adapter(BUS0); + i2c_client_9548_1 = i2c_new_device(adapter, &i2c_info_pca9548[0]); + i2c_client_9548_2 = i2c_new_device(adapter, &i2c_info_pca9548[1]); + i2c_client_9548_3 = i2c_new_device(adapter, &i2c_info_pca9548[2]); + i2c_client_9548_4 = i2c_new_device(adapter, &i2c_info_pca9548[3]); + i2c_client_9548_5 = i2c_new_device(adapter, &i2c_info_pca9548[4]); + i2c_put_adapter(adapter); + + /* pca9548-0x70 */ + ret = platform_driver_register(&i2c_device_pca9548_1_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_pca9548_1_driver; + } + + for (device1_cnt = 0; device1_cnt < ARRAY_SIZE(agc032_i2c_device1); device1_cnt++) + { + ret = platform_device_register(&agc032_i2c_device1[device1_cnt]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", device1_cnt); + goto error_agc032_i2c_device; + } + } + + + /* pca9548-0x71 */ + ret = platform_driver_register(&i2c_device_pca9548_2_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_pca9548_2_driver; + } + + for (device2_cnt = 0; device2_cnt < ARRAY_SIZE(agc032_i2c_device2); device2_cnt++) + { + ret = platform_device_register(&agc032_i2c_device2[device2_cnt]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", device2_cnt); + goto error_agc032_i2c_device2; + } + } + + /* pca9548-0x72 */ + ret = platform_driver_register(&i2c_device_pca9548_3_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_pca9548_3_driver; + } + + for (device3_cnt = 0; device3_cnt < ARRAY_SIZE(agc032_i2c_device3); device3_cnt++) + { + ret = platform_device_register(&agc032_i2c_device3[device3_cnt]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", device3_cnt); + goto error_agc032_i2c_device3; + } + } + + /* pca9548-0x73 */ + ret = platform_driver_register(&i2c_device_pca9548_4_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_pca9548_4_driver; + } + + for (device4_cnt = 0; device4_cnt < ARRAY_SIZE(agc032_i2c_device4); device4_cnt++) + { + ret = platform_device_register(&agc032_i2c_device4[device4_cnt]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", device4_cnt); + goto error_agc032_i2c_device4; + } + } + + /* pca9548-0x74 */ + ret = platform_driver_register(&i2c_device_pca9548_5_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_pca9548_5_driver; + } + + for (device5_cnt = 0; device5_cnt < ARRAY_SIZE(agc032_i2c_device5); device5_cnt++) + { + ret = platform_device_register(&agc032_i2c_device5[device5_cnt]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", device5_cnt); + goto error_agc032_i2c_device5; + } + } + + + return 0; + +/* Error handling */ +error_agc032_i2c_device5: + for (; device5_cnt >= 0; device5_cnt--) { + platform_device_unregister(&agc032_i2c_device5[device5_cnt]); + } + platform_driver_unregister(&i2c_device_pca9548_5_driver); +error_i2c_device_pca9548_5_driver: +error_agc032_i2c_device4: + for (; device4_cnt >= 0; device4_cnt--) { + platform_device_unregister(&agc032_i2c_device4[device4_cnt]); + } + platform_driver_unregister(&i2c_device_pca9548_4_driver); +error_i2c_device_pca9548_4_driver: +error_agc032_i2c_device3: + for (; device3_cnt >= 0; device3_cnt--) { + platform_device_unregister(&agc032_i2c_device3[device3_cnt]); + } + platform_driver_unregister(&i2c_device_pca9548_3_driver); +error_i2c_device_pca9548_3_driver: +error_agc032_i2c_device2: + for (; device2_cnt >= 0; device2_cnt--) { + platform_device_unregister(&agc032_i2c_device2[device2_cnt]); + } + platform_driver_unregister(&i2c_device_pca9548_2_driver); +error_i2c_device_pca9548_2_driver: +error_agc032_i2c_device: + for (; device1_cnt >= 0; device1_cnt--) { + platform_device_unregister(&agc032_i2c_device1[device1_cnt]); + } + platform_driver_unregister(&i2c_device_pca9548_1_driver); +error_i2c_device_pca9548_1_driver: + return ret; +} + +static void __exit delta_agc032_platform_exit(void) +{ + int i = 0; + + // unregister pca9548-1 (0x70) + for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device1); i++ ) { + platform_device_unregister(&agc032_i2c_device1[i]); + } + + platform_driver_unregister(&i2c_device_pca9548_1_driver); + i2c_unregister_device(i2c_client_9548_1); + + // unregister pca9548-2 (0x71) + for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device2); i++ ) { + platform_device_unregister(&agc032_i2c_device2[i]); + } + + platform_driver_unregister(&i2c_device_pca9548_2_driver); + i2c_unregister_device(i2c_client_9548_2); + + // unregister pca9548-3 (0x72) + for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device3); i++ ) { + platform_device_unregister(&agc032_i2c_device3[i]); + } + + platform_driver_unregister(&i2c_device_pca9548_3_driver); + i2c_unregister_device(i2c_client_9548_3); + + // unregister pca9548-4 (0x73) + for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device4); i++ ) { + platform_device_unregister(&agc032_i2c_device4[i]); + } + + platform_driver_unregister(&i2c_device_pca9548_4_driver); + i2c_unregister_device(i2c_client_9548_4); + + // unregister pca9548-5 (0x74) + for ( i = 0; i < ARRAY_SIZE(agc032_i2c_device5); i++ ) { + platform_device_unregister(&agc032_i2c_device5[i]); + } + + platform_driver_unregister(&i2c_device_pca9548_5_driver); + i2c_unregister_device(i2c_client_9548_5); +} + + +module_init(delta_agc032_platform_init); +module_exit(delta_agc032_platform_exit); + +MODULE_DESCRIPTION("Delta agc032 QSFP-DD eeprom Support"); +MODULE_AUTHOR("Zoe Kuan "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_swpld.c b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_swpld.c new file mode 100644 index 000000000000..2396dfff8b48 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/delta_agc032_swpld.c @@ -0,0 +1,2841 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#define SWPLD1_ADDR 0x32 +#define SWPLD2_ADDR 0x34 +#define SWPLD3_ADDR 0x35 + + + +enum cpld_type { + swpld1 = 0, + swpld2, + swpld3, +}; + +enum { + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, +}; + +enum swpld1_attr{ + BOARD_ID = 0, + BOARD_VER, + SWPLD1_VER_TYPE, + SWPLD1_VER, + USB_HUB_RST, + SYNCE_RST, + BMC_RST, + LPC_RST, + OOB_PCIE_RST, + MAC_PCIE_RST, + MAC_RST, + VR_3V3_RST, + VR_0V8_RST, + FAN_MUX_RST, + QSFP5_MUX_RST, + QSFP4_MUX_RST, + QSFP3_MUX_RST, + QSFP2_MUX_RST, + QSFP1_MUX_RST, + PSU1_PRESENT, + PSU1_STATE, + PSU1_ALERT, + PSU2_PRESENT, + PSU2_STATE, + PSU2_ALERT, + PSU1_EN, + PSU1_EEPROM_WP, + PSU2_EN, + PSU2_EEPROM_WP, + VCC_5V_EN, + VCC_3V3_EN, + VCC_VCORE_EN, + VCC_MAC_1V8_EN, + VCC_MAC_1V2_EN, + VCC_MAC_0V8_EN, + VCC_PLL_0V8_EN, + VCC_SYS_EN, + OOB_PWR_STATE, + OOB_OP_EN, + USB1_OP_EN, + PSU_INTR, + FAN_ALERT, + SWPLD2_INTR, + SWPLD3_INTR, + PSU1_LED, + PSU2_LED, + SYS_LED, + FAN_LED, + FAN1_LED, + FAN2_LED, + FAN3_LED, + FAN4_LED, + FAN5_LED, + FAN6_LED, + SYNCE_EEPROM_WB, + CONSOLE_SEL, + SYS_EEPROM_WB, +}; + +/* SWPLD2 */ +enum swpld2_attr{ + SWPLD2_VER_TYPE = 0, + SWPLD2_VER, + QSFP_P01_RST, + QSFP_P02_RST, + QSFP_P03_RST, + QSFP_P04_RST, + QSFP_P05_RST, + QSFP_P06_RST, + QSFP_P07_RST, + QSFP_P08_RST, + QSFP_P09_RST, + QSFP_P10_RST, + QSFP_P11_RST, + QSFP_P12_RST, + QSFP_P13_RST, + QSFP_P14_RST, + QSFP_P15_RST, + QSFP_P16_RST, + QSFP_P01_LPMODE, + QSFP_P02_LPMODE, + QSFP_P03_LPMODE, + QSFP_P04_LPMODE, + QSFP_P05_LPMODE, + QSFP_P06_LPMODE, + QSFP_P07_LPMODE, + QSFP_P08_LPMODE, + QSFP_P09_LPMODE, + QSFP_P10_LPMODE, + QSFP_P11_LPMODE, + QSFP_P12_LPMODE, + QSFP_P13_LPMODE, + QSFP_P14_LPMODE, + QSFP_P15_LPMODE, + QSFP_P16_LPMODE, + QSFP_P01_MODPRS, + QSFP_P02_MODPRS, + QSFP_P03_MODPRS, + QSFP_P04_MODPRS, + QSFP_P05_MODPRS, + QSFP_P06_MODPRS, + QSFP_P07_MODPRS, + QSFP_P08_MODPRS, + QSFP_P09_MODPRS, + QSFP_P10_MODPRS, + QSFP_P11_MODPRS, + QSFP_P12_MODPRS, + QSFP_P13_MODPRS, + QSFP_P14_MODPRS, + QSFP_P15_MODPRS, + QSFP_P16_MODPRS, + QSFP_P01_INTR, + QSFP_P02_INTR, + QSFP_P03_INTR, + QSFP_P04_INTR, + QSFP_P05_INTR, + QSFP_P06_INTR, + QSFP_P07_INTR, + QSFP_P08_INTR, + QSFP_P09_INTR, + QSFP_P10_INTR, + QSFP_P11_INTR, + QSFP_P12_INTR, + QSFP_P13_INTR, + QSFP_P14_INTR, + QSFP_P15_INTR, + QSFP_P16_INTR, +}; + +/* SWPLD3 */ +enum swpld3_attr{ + SWPLD3_VER_TYPE = 160, + SWPLD3_VER, + QSFP_P17_RST, + QSFP_P18_RST, + QSFP_P19_RST, + QSFP_P20_RST, + QSFP_P21_RST, + QSFP_P22_RST, + QSFP_P23_RST, + QSFP_P24_RST, + QSFP_P25_RST, + QSFP_P26_RST, + QSFP_P27_RST, + QSFP_P28_RST, + QSFP_P29_RST, + QSFP_P30_RST, + QSFP_P31_RST, + QSFP_P32_RST, + QSFP_P17_LPMODE, + QSFP_P18_LPMODE, + QSFP_P19_LPMODE, + QSFP_P20_LPMODE, + QSFP_P21_LPMODE, + QSFP_P22_LPMODE, + QSFP_P23_LPMODE, + QSFP_P24_LPMODE, + QSFP_P25_LPMODE, + QSFP_P26_LPMODE, + QSFP_P27_LPMODE, + QSFP_P28_LPMODE, + QSFP_P29_LPMODE, + QSFP_P30_LPMODE, + QSFP_P31_LPMODE, + QSFP_P32_LPMODE, + QSFP_P17_MODPRS, + QSFP_P18_MODPRS, + QSFP_P19_MODPRS, + QSFP_P20_MODPRS, + QSFP_P21_MODPRS, + QSFP_P22_MODPRS, + QSFP_P23_MODPRS, + QSFP_P24_MODPRS, + QSFP_P25_MODPRS, + QSFP_P26_MODPRS, + QSFP_P27_MODPRS, + QSFP_P28_MODPRS, + QSFP_P29_MODPRS, + QSFP_P30_MODPRS, + QSFP_P31_MODPRS, + QSFP_P32_MODPRS, + QSFP_P17_INTR, + QSFP_P18_INTR, + QSFP_P19_INTR, + QSFP_P20_INTR, + QSFP_P21_INTR, + QSFP_P22_INTR, + QSFP_P23_INTR, + QSFP_P24_INTR, + QSFP_P25_INTR, + QSFP_P26_INTR, + QSFP_P27_INTR, + QSFP_P28_INTR, + QSFP_P29_INTR, + QSFP_P30_INTR, + QSFP_P31_INTR, + QSFP_P32_INTR, + SFP_P0_MODPRS, + SFP_P0_RXLOS, + SFP_P0_TXFAULT, + SFP_P1_MODPRS, + SFP_P1_RXLOS, + SFP_P1_TXFAULT, + SFP_P0_TXDIS, + SFP_P1_TXDIS, +}; + + +struct platform_data { + int reg_addr; + struct i2c_client *client; +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct kobject *kobj_swpld1; +static struct kobject *kobj_swpld2; +static struct kobject *kobj_swpld3; + +static struct kobject *kobj_test1; +static struct kobject *kobj_test2; + +unsigned char swpld1_reg_addr; +unsigned char swpld2_reg_addr; +unsigned char swpld3_reg_addr; + + + +static ssize_t swpld1_data_show(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_swpld1->parent); + struct platform_data *pdata = i2cdev->platform_data; + unsigned int select = 0; + unsigned char offset = 0; + int mask = 0xFF; + int shift = 0; + int value = 0; + bool hex_fmt = 0; + char desc[256] = {0}; + + select = attr->index; + switch(select) { + case BOARD_ID: + offset = 0x1; + hex_fmt = 1; + scnprintf(desc, PAGE_SIZE, "\nBorad ID.\n"); + break; + case BOARD_VER: + offset = 0x2; + hex_fmt = 1; + scnprintf(desc, PAGE_SIZE, "\nBorad Version.\n"); + break; + case SWPLD1_VER_TYPE: + offset = 0x3; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nSWPLD1 Version Type.\n"); + break; + case SWPLD1_VER: + offset = 0x3; + mask = 0x7f; + scnprintf(desc, PAGE_SIZE, "\nSWPLD1 Version.\n"); + break; + case USB_HUB_RST: + offset = 0x6; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nUSB Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case SYNCE_RST: + offset = 0x6; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nSynce Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case BMC_RST: + offset = 0x6; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nBMC Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case LPC_RST: + offset = 0x6; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nBMC LPC Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case OOB_PCIE_RST: + offset = 0x6; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nOOB PCIE Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case MAC_PCIE_RST: + offset = 0x6; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nMAC PCIE Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case MAC_RST: + offset = 0x6; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nMAC Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case VR_3V3_RST: + offset = 0x7; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nVR 3V3 Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case VR_0V8_RST: + offset = 0x7; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nVR 0V8 Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case FAN_MUX_RST: + offset = 0x8; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nFAN I2C Mux Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case QSFP5_MUX_RST: + offset = 0x8; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nQSFP5 Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case QSFP4_MUX_RST: + offset = 0x8; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nQSFP4 Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case QSFP3_MUX_RST: + offset = 0x8; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nQSFP3 Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case QSFP2_MUX_RST: + offset = 0x8; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nQSFP2 Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case QSFP1_MUX_RST: + offset = 0x8; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nQSFP1 Reset.\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case PSU1_PRESENT: + offset = 0x11; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = PSU1 Not Present.\n“0” = PSU1 Present.\n"); + break; + case PSU1_STATE: + offset = 0x11; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = PSU1 Power Not Good.\n“0” = PSU1 Power Good.\n"); + break; + case PSU1_ALERT: + offset = 0x11; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = PSU1 Alert Active.\n“0” = PSU1 Alert Not Active.\n"); + break; + case PSU2_PRESENT: + offset = 0x11; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = PSU2 Not Present.\n“0” = PSU2 Present.\n"); + break; + case PSU2_STATE: + offset = 0x11; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case PSU2_ALERT: + offset = 0x11; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = PSU2 Alert Active.\n“0” = PSU2 Alert Not Active.\n"); + break; + case PSU1_EN: + offset = 0x12; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable PSU1.\n“0” = Enable PSU1.\n"); + break; + case PSU1_EEPROM_WP: + offset = 0x12; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable PSU1 EEPROM Write Protect.\n“0” = Disable PSU1 EEPROM Write Protect.\n"); + break; + case PSU2_EN: + offset = 0x12; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable PSU2.\n“0” = Enable PSU2.\n"); + break; + case PSU2_EEPROM_WP: + offset = 0x12; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable PSU2 EEPROM Write Protect.\n“0” = Disable PSU2 EEPROM Write Protect.\n"); + break; + case VCC_5V_EN: + offset = 0x23; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable VCC 5V.\n“0” = Disable VCC 5V.\n"); + break; + case VCC_3V3_EN: + offset = 0x23; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable VCC 3V3.\n“0” = Disable VCC 3V3.\n"); + break; + case VCC_VCORE_EN: + offset = 0x23; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable AVS 0V91.\n“0” = Disable AVS 0V91.\n"); + break; + case VCC_MAC_1V8_EN: + offset = 0x23; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable MAC 1V8.\n“0” = Disable MAC 1V8.\n"); + break; + case VCC_MAC_1V2_EN: + offset = 0x23; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable MAC 1V2.\n“0” = Disable MAC 1V2.\n"); + break; + case VCC_MAC_0V8_EN: + offset = 0x23; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable MAC 0V8.\n“0” = Disable MAC 0V8.\n"); + break; + case VCC_PLL_0V8_EN: + offset = 0x23; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable PLL 0V8.\n“0” = Disable PLL 0V8.\n"); + break; + case VCC_SYS_EN: + offset = 0x23; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable System Power.\n“0” = Disable System Power.\n"); + break; + case OOB_PWR_STATE: + offset = 0x24; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = OOB Power Rail Good.\n“0” = OOB Power Rail Not Good.\n"); + break; + case OOB_OP_EN: + offset = 0x24; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Enable OOB Operation.\n“0” = Disable OOB Operation.\n"); + break; + case USB1_OP_EN: + offset = 0x24; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable USB Operation.\n“0” = Enable USB Operation.\n"); + break; + case PSU_INTR: + offset = 0x26; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = PSU Interrupt Not Occured.\n“0” = PSU Interrupt Occured.\n"); + break; + case FAN_ALERT: + offset = 0x26; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Fan Interrupt Not Occured.\n“0” = Fan Interrupt Occured.\n"); + break; + case SWPLD2_INTR: + offset = 0x27; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = SWPLD2 Interrupt Not Occured.\n“0” = SWPLD2 Interrupt Occured.\n"); + break; + case SWPLD3_INTR: + offset = 0x27; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = SWPLD3 Interrupt Not Occured.\n“0” = SWPLD3 Interrupt Occured.\n)"); + break; + case PSU1_LED: + offset = 0x41; + shift = 2; + mask = 0x0C; + scnprintf(desc, PAGE_SIZE, "\n“3” = LED Off\n“2” = LED Red.\n“1” = LED Green\n“0” = Auto.\n"); + break; + case PSU2_LED: + offset = 0x41; + shift = 0; + mask = 0x03; + scnprintf(desc, PAGE_SIZE, "\n“3” = LED Off\n“2” = LED Red.\n“1” = LED Green\n“0” = Auto.\n"); + break; + case SYS_LED: + offset = 0x42; + shift = 2; + mask = 0x0C; + scnprintf(desc, PAGE_SIZE, "\n“3” = LED Red\n“2” = LED Blink Green.\n“1” = LED Green\n“0” = LED Off.\n"); + break; + case FAN_LED: + offset = 0x42; + shift = 0; + mask = 0x03; + scnprintf(desc, PAGE_SIZE, "\n“3” = LED Off\n“2” = LED Amber.\n“1” = LED Green\n“0” = LED Off.\n"); + break; + case FAN1_LED: + offset = 0x46; + shift = 6; + mask = 0xc0; + scnprintf(desc, PAGE_SIZE, "\n“3” = LED Off\n“2” = LED Red.\n“1” = LED Green\n“0” = LED Off.\n"); + break; + case FAN2_LED: + offset = 0x46; + shift = 4; + mask = 0x30; + scnprintf(desc, PAGE_SIZE, "\n“3” = LED Off\n“2” = LED Red.\n“1” = LED Green\n“0” = LED Off.\n"); + break; + case FAN3_LED: + offset = 0x46; + shift = 2; + mask = 0x0c; + scnprintf(desc, PAGE_SIZE, "\n“3” = LED Off\n“2” = LED Red.\n“1” = LED Green\n“0” = LED Off.\n"); + break; + case FAN4_LED: + offset = 0x46; + shift = 0; + mask = 0x03; + scnprintf(desc, PAGE_SIZE, "\n“3” = LED Off\n“2” = LED Red.\n“1” = LED Green\n“0” = LED Off.\n"); + break; + case FAN5_LED: + offset = 0x47; + shift = 6; + mask = 0xc0; + scnprintf(desc, PAGE_SIZE, "\n“3” = LED Off\n“2” = LED Red.\n“1” = LED Green\n“0” = LED Off.\n"); + break; + case FAN6_LED: + offset = 0x47; + shift = 4; + mask = 0x30; + scnprintf(desc, PAGE_SIZE, "\n“3” = LED Off\n“2” = LED Red.\n“1” = LED Green\n“0” = LED Off.\n"); + break; + case SYNCE_EEPROM_WB: + offset = 0x51; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case CONSOLE_SEL: + offset = 0x51; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + case SYS_EEPROM_WB: + offset = 0x51; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation\n“0” = Reset.\n"); + break; + } + + value = i2c_smbus_read_byte_data(pdata[swpld1].client, offset); + value = (value & mask) >> shift; + if(hex_fmt) { + return scnprintf(buf, PAGE_SIZE, "0x%02x%s", value, desc); + } else { + return scnprintf(buf, PAGE_SIZE, "%d%s", value, desc); + } +} + + +static ssize_t swpld1_data_store(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_swpld1->parent); + struct platform_data *pdata = i2cdev->platform_data; + unsigned int select = 0; + unsigned char offset = 0; + int mask = 0xFF; + int shift = 0; + int value = 0; + int err = 0; + unsigned long data; + + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + switch (attr->index) { + case USB_HUB_RST: + offset = 0x6; + shift = 6; + mask = (1 << shift); + break; + case SYNCE_RST: + offset = 0x6; + shift = 5; + mask = (1 << shift); + break; + case BMC_RST: + offset = 0x6; + shift = 4; + mask = (1 << shift); + break; + case LPC_RST: + offset = 0x6; + shift = 3; + mask = (1 << shift); + break; + case OOB_PCIE_RST: + offset = 0x6; + shift = 2; + mask = (1 << shift); + break; + case MAC_PCIE_RST: + offset = 0x6; + shift = 1; + mask = (1 << shift); + break; + case MAC_RST: + offset = 0x6; + shift = 0; + mask = (1 << shift); + break; + case VR_3V3_RST: + offset = 0x7; + shift = 3; + mask = (1 << shift); + break; + case VR_0V8_RST: + offset = 0x7; + shift = 2; + mask = (1 << shift); + break; + case FAN_MUX_RST: + offset = 0x8; + shift = 6; + mask = (1 << shift); + break; + case QSFP5_MUX_RST: + offset = 0x8; + shift = 5; + mask = (1 << shift); + break; + case QSFP4_MUX_RST: + offset = 0x8; + shift = 4; + mask = (1 << shift); + break; + case QSFP3_MUX_RST: + offset = 0x8; + shift = 3; + mask = (1 << shift); + break; + case QSFP2_MUX_RST: + offset = 0x8; + shift = 2; + mask = (1 << shift); + break; + case QSFP1_MUX_RST: + offset = 0x8; + shift = 1; + mask = (1 << shift); + break; + case PSU1_EN: + offset = 0x12; + shift = 7; + mask = (1 << shift); + break; + case PSU1_EEPROM_WP: + offset = 0x12; + shift = 6; + mask = (1 << shift); + break; + case PSU2_EN: + offset = 0x12; + shift = 3; + mask = (1 << shift); + break; + case PSU2_EEPROM_WP: + offset = 0x12; + shift = 2; + mask = (1 << shift); + break; + case VCC_5V_EN: + offset = 0x23; + shift = 7; + mask = (1 << shift); + break; + case VCC_3V3_EN: + offset = 0x23; + shift = 6; + mask = (1 << shift); + break; + case VCC_VCORE_EN: + offset = 0x23; + shift = 5; + mask = (1 << shift); + break; + case VCC_MAC_1V8_EN: + offset = 0x23; + shift = 4; + mask = (1 << shift); + break; + case VCC_MAC_1V2_EN: + offset = 0x23; + shift = 3; + mask = (1 << shift); + break; + case VCC_MAC_0V8_EN: + offset = 0x23; + shift = 2; + mask = (1 << shift); + break; + case VCC_PLL_0V8_EN: + offset = 0x23; + shift = 1; + mask = (1 << shift); + break; + case VCC_SYS_EN: + offset = 0x23; + shift = 0; + mask = (1 << shift); + break; + case OOB_OP_EN: + offset = 0x24; + shift = 6; + mask = (1 << shift); + break; + case USB1_OP_EN: + offset = 0x24; + shift = 1; + mask = (1 << shift); + break; + case PSU1_LED: + offset = 0x41; + shift = 2; + mask = 0x0C; + break; + case PSU2_LED: + offset = 0x41; + shift = 0; + mask = 0x03; + break; + case SYS_LED: + offset = 0x42; + shift = 2; + mask = 0x0C; + break; + case FAN_LED: + offset = 0x42; + shift = 0; + mask = 0x03; + break; + case FAN1_LED: + offset = 0x46; + shift = 6; + mask = 0xc0; + break; + case FAN2_LED: + offset = 0x46; + shift = 4; + mask = 0x30; + break; + case FAN3_LED: + offset = 0x46; + shift = 2; + mask = 0x0c; + break; + case FAN4_LED: + offset = 0x46; + shift = 0; + mask = 0x03; + break; + case FAN5_LED: + offset = 0x47; + shift = 6; + mask = 0xc0; + break; + case FAN6_LED: + offset = 0x47; + shift = 4; + mask = 0x30; + break; + case SYNCE_EEPROM_WB: + offset = 0x51; + shift = 5; + mask = (1 << shift); + break; + case CONSOLE_SEL: + offset = 0x51; + shift = 5; + mask = (1 << shift); + break; + case SYS_EEPROM_WB: + offset = 0x51; + shift = 5; + mask = (1 << shift); + break; + } + + value = i2c_smbus_read_byte_data(pdata[swpld1].client, offset); + data = (value & ~mask) | (data << shift); + i2c_smbus_write_byte_data(pdata[swpld1].client, offset, data); + + return count; +} + + +/* offset 0x01 */ +static SENSOR_DEVICE_ATTR(board_id, S_IRUGO, swpld1_data_show, NULL, BOARD_ID); +/* offser 0x02 */ +static SENSOR_DEVICE_ATTR(board_ver, S_IRUGO, swpld1_data_show, NULL, BOARD_VER); +/* offset 0x03 */ +static SENSOR_DEVICE_ATTR(swpld1_ver_type, S_IRUGO, swpld1_data_show, NULL, SWPLD1_VER_TYPE); +static SENSOR_DEVICE_ATTR(swpld1_ver, S_IRUGO, swpld1_data_show, NULL, SWPLD1_VER); +/* offset 0x06 */ +static SENSOR_DEVICE_ATTR(usb_hub_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, USB_HUB_RST); +static SENSOR_DEVICE_ATTR(synce_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, SYNCE_RST); +static SENSOR_DEVICE_ATTR(bmc_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, BMC_RST); +static SENSOR_DEVICE_ATTR(lpc_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, LPC_RST); +static SENSOR_DEVICE_ATTR(oob_pcie_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, OOB_PCIE_RST); +static SENSOR_DEVICE_ATTR(mac_pcie_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, MAC_PCIE_RST); +static SENSOR_DEVICE_ATTR(mac_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, MAC_RST); +/* offset 0x07 */ +static SENSOR_DEVICE_ATTR(vr_3v3_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, VR_3V3_RST); +static SENSOR_DEVICE_ATTR(vr_0v8_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, VR_0V8_RST); +/* offset 0x08 */ +static SENSOR_DEVICE_ATTR(fan_mux_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, FAN_MUX_RST); +static SENSOR_DEVICE_ATTR(qsfp5_mux_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, QSFP5_MUX_RST); +static SENSOR_DEVICE_ATTR(qsfp4_mux_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, QSFP4_MUX_RST); +static SENSOR_DEVICE_ATTR(qsfp3_mux_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, QSFP3_MUX_RST); +static SENSOR_DEVICE_ATTR(qsfp2_mux_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, QSFP2_MUX_RST); +static SENSOR_DEVICE_ATTR(qsfp1_mux_rst, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, QSFP1_MUX_RST); +/* offset 0x11 */ +static SENSOR_DEVICE_ATTR(psu1_present, S_IRUGO, swpld1_data_show, NULL, PSU1_PRESENT); +static SENSOR_DEVICE_ATTR(psu1_state, S_IRUGO, swpld1_data_show, NULL, PSU1_STATE); +static SENSOR_DEVICE_ATTR(psu1_alert, S_IRUGO, swpld1_data_show, NULL, PSU1_ALERT); +static SENSOR_DEVICE_ATTR(psu2_present, S_IRUGO, swpld1_data_show, NULL, PSU2_PRESENT); +static SENSOR_DEVICE_ATTR(psu2_state, S_IRUGO, swpld1_data_show, NULL, PSU2_STATE); +static SENSOR_DEVICE_ATTR(psu2_alert, S_IRUGO, swpld1_data_show, NULL, PSU2_ALERT); +/* offset 0x12 */ +static SENSOR_DEVICE_ATTR(psu1_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, PSU1_EN); +static SENSOR_DEVICE_ATTR(psu1_eeprom_wp, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, PSU1_EEPROM_WP); +static SENSOR_DEVICE_ATTR(psu2_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, PSU2_EN); +static SENSOR_DEVICE_ATTR(psu2_eeprom_wp, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, PSU2_EEPROM_WP); +/* offset 0x23 */ +static SENSOR_DEVICE_ATTR(vcc_5v_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, VCC_5V_EN); +static SENSOR_DEVICE_ATTR(vcc_3v3_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, VCC_3V3_EN); +static SENSOR_DEVICE_ATTR(vcc_vcore_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, VCC_VCORE_EN); +static SENSOR_DEVICE_ATTR(vcc_mac_1v8_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, VCC_MAC_1V8_EN); +static SENSOR_DEVICE_ATTR(vcc_mac_1v2_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, VCC_MAC_1V2_EN); +static SENSOR_DEVICE_ATTR(vcc_mac_0v8_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, VCC_MAC_0V8_EN); +static SENSOR_DEVICE_ATTR(vcc_pll_0v8_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, VCC_PLL_0V8_EN); +static SENSOR_DEVICE_ATTR(vcc_sys_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, VCC_SYS_EN); +/* offset 0x24 */ +static SENSOR_DEVICE_ATTR(oob_pwr_state, S_IRUGO, swpld1_data_show, NULL, OOB_PWR_STATE); +static SENSOR_DEVICE_ATTR(oob_op_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, OOB_OP_EN); +static SENSOR_DEVICE_ATTR(usb1_op_en, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, USB1_OP_EN); +/* offset 0x26 */ +static SENSOR_DEVICE_ATTR(psu_intr, S_IRUGO, swpld1_data_show, NULL, PSU_INTR); +static SENSOR_DEVICE_ATTR(fan_alert, S_IRUGO, swpld1_data_show, NULL, FAN_ALERT); +/* offset 0x27 */ +static SENSOR_DEVICE_ATTR(swpld2_intr, S_IRUGO, swpld1_data_show, NULL, SWPLD2_INTR); +static SENSOR_DEVICE_ATTR(swpld3_intr, S_IRUGO, swpld1_data_show, NULL, SWPLD3_INTR); +/* offset 0x41 */ +static SENSOR_DEVICE_ATTR(psu1_led, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, PSU1_LED); +static SENSOR_DEVICE_ATTR(psu2_led, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, PSU2_LED); +/* offset 0x42 */ +static SENSOR_DEVICE_ATTR(sys_led, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, SYS_LED); +static SENSOR_DEVICE_ATTR(fan_led, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, FAN_LED); +/* offset 0x46 */ +static SENSOR_DEVICE_ATTR(fan1_led, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, FAN1_LED); +static SENSOR_DEVICE_ATTR(fan2_led, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, FAN2_LED); +static SENSOR_DEVICE_ATTR(fan3_led, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, FAN3_LED); +static SENSOR_DEVICE_ATTR(fan4_led, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, FAN4_LED); +/* offset 0x47 */ +static SENSOR_DEVICE_ATTR(fan5_led, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, FAN5_LED); +static SENSOR_DEVICE_ATTR(fan6_led, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, FAN6_LED); +/* offset 0x51*/ +static SENSOR_DEVICE_ATTR(synce_eeprom_wb, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, SYNCE_EEPROM_WB); +static SENSOR_DEVICE_ATTR(console_sel, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, CONSOLE_SEL); +static SENSOR_DEVICE_ATTR(sys_eeprom_wb, S_IRUGO | S_IWUSR, swpld1_data_show, swpld1_data_store, SYS_EEPROM_WB); + +static struct attribute *swpld1_device_attrs[] = { + &sensor_dev_attr_board_id.dev_attr.attr, + &sensor_dev_attr_board_ver.dev_attr.attr, + &sensor_dev_attr_swpld1_ver_type.dev_attr.attr, + &sensor_dev_attr_swpld1_ver.dev_attr.attr, + &sensor_dev_attr_usb_hub_rst.dev_attr.attr, + &sensor_dev_attr_synce_rst.dev_attr.attr, + &sensor_dev_attr_bmc_rst.dev_attr.attr, + &sensor_dev_attr_lpc_rst.dev_attr.attr, + &sensor_dev_attr_oob_pcie_rst.dev_attr.attr, + &sensor_dev_attr_mac_pcie_rst.dev_attr.attr, + &sensor_dev_attr_mac_rst.dev_attr.attr, + &sensor_dev_attr_vr_3v3_rst.dev_attr.attr, + &sensor_dev_attr_vr_0v8_rst.dev_attr.attr, + &sensor_dev_attr_fan_mux_rst.dev_attr.attr, + &sensor_dev_attr_qsfp5_mux_rst.dev_attr.attr, + &sensor_dev_attr_qsfp4_mux_rst.dev_attr.attr, + &sensor_dev_attr_qsfp3_mux_rst.dev_attr.attr, + &sensor_dev_attr_qsfp2_mux_rst.dev_attr.attr, + &sensor_dev_attr_qsfp1_mux_rst.dev_attr.attr, + &sensor_dev_attr_psu1_present.dev_attr.attr, + &sensor_dev_attr_psu1_state.dev_attr.attr, + &sensor_dev_attr_psu1_alert.dev_attr.attr, + &sensor_dev_attr_psu2_present.dev_attr.attr, + &sensor_dev_attr_psu2_state.dev_attr.attr, + &sensor_dev_attr_psu2_alert.dev_attr.attr, + &sensor_dev_attr_psu1_en.dev_attr.attr, + &sensor_dev_attr_psu1_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_psu2_en.dev_attr.attr, + &sensor_dev_attr_psu2_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_vcc_5v_en.dev_attr.attr, + &sensor_dev_attr_vcc_3v3_en.dev_attr.attr, + &sensor_dev_attr_vcc_vcore_en.dev_attr.attr, + &sensor_dev_attr_vcc_mac_1v8_en.dev_attr.attr, + &sensor_dev_attr_vcc_mac_1v2_en.dev_attr.attr, + &sensor_dev_attr_vcc_mac_0v8_en.dev_attr.attr, + &sensor_dev_attr_vcc_pll_0v8_en.dev_attr.attr, + &sensor_dev_attr_vcc_sys_en.dev_attr.attr, + &sensor_dev_attr_oob_pwr_state.dev_attr.attr, + &sensor_dev_attr_oob_op_en.dev_attr.attr, + &sensor_dev_attr_usb1_op_en.dev_attr.attr, + &sensor_dev_attr_psu_intr.dev_attr.attr, + &sensor_dev_attr_fan_alert.dev_attr.attr, + &sensor_dev_attr_swpld2_intr.dev_attr.attr, + &sensor_dev_attr_swpld3_intr.dev_attr.attr, + &sensor_dev_attr_psu1_led.dev_attr.attr, + &sensor_dev_attr_psu2_led.dev_attr.attr, + &sensor_dev_attr_sys_led.dev_attr.attr, + &sensor_dev_attr_fan_led.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &sensor_dev_attr_fan3_led.dev_attr.attr, + &sensor_dev_attr_fan4_led.dev_attr.attr, + &sensor_dev_attr_fan5_led.dev_attr.attr, + &sensor_dev_attr_fan6_led.dev_attr.attr, + &sensor_dev_attr_synce_eeprom_wb.dev_attr.attr, + &sensor_dev_attr_console_sel.dev_attr.attr, + &sensor_dev_attr_sys_eeprom_wb.dev_attr.attr, +}; + + +static ssize_t swpld2_data_show(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_swpld2->parent); + struct platform_data *pdata = i2cdev->platform_data; + unsigned int select = 0; + unsigned char offset = 0; + int mask = 0xFF; + int shift = 0; + int value = 0; + bool hex_fmt = 0; + char desc[256] = {0}; + + select = attr->index; + switch(select) { + case SWPLD2_VER_TYPE: + offset = 0x1; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nSWPLD2 Version Type.\n"); + break; + case SWPLD2_VER: + offset = 0x1; + mask = 0x7f; + scnprintf(desc, PAGE_SIZE, "\nSWPLD2 Version.\n"); + break; + case QSFP_P01_RST: + offset = 0x11; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P02_RST: + offset = 0x11; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P03_RST: + offset = 0x11; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P04_RST: + offset = 0x11; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P05_RST: + offset = 0x11; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P06_RST: + offset = 0x11; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P07_RST: + offset = 0x11; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P08_RST: + offset = 0x11; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P09_RST: + offset = 0x12; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P10_RST: + offset = 0x12; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P11_RST: + offset = 0x12; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P12_RST: + offset = 0x12; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P13_RST: + offset = 0x12; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P14_RST: + offset = 0x12; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P15_RST: + offset = 0x12; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P16_RST: + offset = 0x12; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P01_LPMODE: + offset = 0x21; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P02_LPMODE: + offset = 0x21; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P03_LPMODE: + offset = 0x21; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P04_LPMODE: + offset = 0x21; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P05_LPMODE: + offset = 0x21; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P06_LPMODE: + offset = 0x21; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P07_LPMODE: + offset = 0x21; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P08_LPMODE: + offset = 0x21; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P09_LPMODE: + offset = 0x22; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P10_LPMODE: + offset = 0x22; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P11_LPMODE: + offset = 0x22; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P12_LPMODE: + offset = 0x22; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P13_LPMODE: + offset = 0x22; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P14_LPMODE: + offset = 0x22; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P15_LPMODE: + offset = 0x22; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P16_LPMODE: + offset = 0x22; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P01_MODPRS: + offset = 0x51; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P02_MODPRS: + offset = 0x51; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P03_MODPRS: + offset = 0x51; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P04_MODPRS: + offset = 0x51; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P05_MODPRS: + offset = 0x51; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P06_MODPRS: + offset = 0x51; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P07_MODPRS: + offset = 0x51; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P08_MODPRS: + offset = 0x51; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P09_MODPRS: + offset = 0x52; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P10_MODPRS: + offset = 0x52; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P11_MODPRS: + offset = 0x52; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P12_MODPRS: + offset = 0x52; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P13_MODPRS: + offset = 0x52; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P14_MODPRS: + offset = 0x52; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P15_MODPRS: + offset = 0x52; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P16_MODPRS: + offset = 0x52; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P01_INTR: + offset = 0x61; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P02_INTR: + offset = 0x61; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P03_INTR: + offset = 0x61; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P04_INTR: + offset = 0x61; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P05_INTR: + offset = 0x61; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P06_INTR: + offset = 0x61; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P07_INTR: + offset = 0x61; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P08_INTR: + offset = 0x61; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P09_INTR: + offset = 0x62; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P10_INTR: + offset = 0x62; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P11_INTR: + offset = 0x62; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P12_INTR: + offset = 0x62; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P13_INTR: + offset = 0x62; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P14_INTR: + offset = 0x62; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P15_INTR: + offset = 0x62; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P16_INTR: + offset = 0x62; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + } + + value = i2c_smbus_read_byte_data(pdata[swpld2].client, offset); + value = (value & mask) >> shift; + if(hex_fmt) { + return scnprintf(buf, PAGE_SIZE, "0x%02x%s", value, desc); + } else { + return scnprintf(buf, PAGE_SIZE, "%d%s", value, desc); + } +} + +static ssize_t swpld2_data_store(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_swpld2->parent); + struct platform_data *pdata = i2cdev->platform_data; + unsigned int select = 0; + unsigned char offset = 0; + int mask = 0xFF; + int shift = 0; + int value = 0; + int err = 0; + unsigned long data; + + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + switch (attr->index) { + case QSFP_P01_RST: + offset = 0x11; + shift = 7; + mask = (1 << shift); + break; + case QSFP_P02_RST: + offset = 0x11; + shift = 6; + mask = (1 << shift); + break; + case QSFP_P03_RST: + offset = 0x11; + shift = 5; + mask = (1 << shift); + break; + case QSFP_P04_RST: + offset = 0x11; + shift = 4; + mask = (1 << shift); + break; + case QSFP_P05_RST: + offset = 0x11; + shift = 3; + mask = (1 << shift); + break; + case QSFP_P06_RST: + offset = 0x11; + shift = 2; + mask = (1 << shift); + break; + case QSFP_P07_RST: + offset = 0x11; + shift = 1; + mask = (1 << shift); + break; + case QSFP_P08_RST: + offset = 0x11; + shift = 0; + mask = (1 << shift); + break; + case QSFP_P09_RST: + offset = 0x12; + shift = 7; + mask = (1 << shift); + break; + case QSFP_P10_RST: + offset = 0x12; + shift = 6; + mask = (1 << shift); + break; + case QSFP_P11_RST: + offset = 0x12; + shift = 5; + mask = (1 << shift); + break; + case QSFP_P12_RST: + offset = 0x12; + shift = 4; + mask = (1 << shift); + break; + case QSFP_P13_RST: + offset = 0x12; + shift = 3; + mask = (1 << shift); + break; + case QSFP_P14_RST: + offset = 0x12; + shift = 2; + mask = (1 << shift); + break; + case QSFP_P15_RST: + offset = 0x12; + shift = 1; + mask = (1 << shift); + break; + case QSFP_P16_RST: + offset = 0x12; + shift = 0; + mask = (1 << shift); + break; + case QSFP_P01_LPMODE: + offset = 0x21; + shift = 7; + mask = (1 << shift); + break; + case QSFP_P02_LPMODE: + offset = 0x21; + shift = 6; + mask = (1 << shift); + break; + case QSFP_P03_LPMODE: + offset = 0x21; + shift = 5; + mask = (1 << shift); + break; + case QSFP_P04_LPMODE: + offset = 0x21; + shift = 4; + mask = (1 << shift); + break; + case QSFP_P05_LPMODE: + offset = 0x21; + shift = 3; + mask = (1 << shift); + break; + case QSFP_P06_LPMODE: + offset = 0x21; + shift = 2; + mask = (1 << shift); + break; + case QSFP_P07_LPMODE: + offset = 0x21; + shift = 1; + mask = (1 << shift); + break; + case QSFP_P08_LPMODE: + offset = 0x21; + shift = 0; + mask = (1 << shift); + break; + case QSFP_P09_LPMODE: + offset = 0x22; + shift = 7; + mask = (1 << shift); + break; + case QSFP_P10_LPMODE: + offset = 0x22; + shift = 6; + mask = (1 << shift); + break; + case QSFP_P11_LPMODE: + offset = 0x22; + shift = 5; + mask = (1 << shift); + break; + case QSFP_P12_LPMODE: + offset = 0x22; + shift = 4; + mask = (1 << shift); + break; + case QSFP_P13_LPMODE: + offset = 0x22; + shift = 3; + mask = (1 << shift); + break; + case QSFP_P14_LPMODE: + offset = 0x22; + shift = 2; + mask = (1 << shift); + break; + case QSFP_P15_LPMODE: + offset = 0x22; + shift = 1; + mask = (1 << shift); + break; + case QSFP_P16_LPMODE: + offset = 0x22; + shift = 0; + mask = (1 << shift); + break; + } + + value = i2c_smbus_read_byte_data(pdata[swpld2].client, offset); + data = (value & ~mask) | (data << shift); + i2c_smbus_write_byte_data(pdata[swpld2].client, offset, data); + + return count; +} + + +/* offset 0x01 */ +static SENSOR_DEVICE_ATTR(swpld2_ver_type, S_IRUGO, swpld2_data_show, NULL, SWPLD2_VER_TYPE); +static SENSOR_DEVICE_ATTR(swpld2_ver, S_IRUGO, swpld2_data_show, NULL, SWPLD2_VER); +/* offset 0x11 */ +static SENSOR_DEVICE_ATTR(qsfp_p01_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P01_RST); +static SENSOR_DEVICE_ATTR(qsfp_p02_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P02_RST); +static SENSOR_DEVICE_ATTR(qsfp_p03_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P03_RST); +static SENSOR_DEVICE_ATTR(qsfp_p04_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P04_RST); +static SENSOR_DEVICE_ATTR(qsfp_p05_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P05_RST); +static SENSOR_DEVICE_ATTR(qsfp_p06_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P06_RST); +static SENSOR_DEVICE_ATTR(qsfp_p07_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P07_RST); +static SENSOR_DEVICE_ATTR(qsfp_p08_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P08_RST); +/* offset 0x12 */ +static SENSOR_DEVICE_ATTR(qsfp_p09_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P09_RST); +static SENSOR_DEVICE_ATTR(qsfp_p10_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P10_RST); +static SENSOR_DEVICE_ATTR(qsfp_p11_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P11_RST); +static SENSOR_DEVICE_ATTR(qsfp_p12_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P12_RST); +static SENSOR_DEVICE_ATTR(qsfp_p13_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P13_RST); +static SENSOR_DEVICE_ATTR(qsfp_p14_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P14_RST); +static SENSOR_DEVICE_ATTR(qsfp_p15_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P15_RST); +static SENSOR_DEVICE_ATTR(qsfp_p16_rst, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P16_RST); +/* offset 0x21 */ +static SENSOR_DEVICE_ATTR(qsfp_p01_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P01_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p02_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P02_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p03_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P03_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p04_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P04_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p05_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P05_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p06_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P06_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p07_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P07_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p08_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P08_LPMODE); +/* offset 0x22 */ +static SENSOR_DEVICE_ATTR(qsfp_p09_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P09_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p10_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P10_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p11_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P11_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p12_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P12_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p13_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P13_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p14_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P14_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p15_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P15_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p16_lpmode, S_IRUGO | S_IWUSR, swpld2_data_show, swpld2_data_store, QSFP_P16_LPMODE); +/* offset 0x51 */ +static SENSOR_DEVICE_ATTR(qsfp_p01_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P01_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p02_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P02_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p03_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P03_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p04_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P04_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p05_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P05_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p06_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P06_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p07_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P07_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p08_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P08_MODPRS); +/* offset 0x52 */ +static SENSOR_DEVICE_ATTR(qsfp_p09_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P09_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p10_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P10_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p11_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P11_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p12_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P12_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p13_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P13_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p14_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P14_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p15_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P15_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p16_modprs, S_IRUGO, swpld2_data_show, NULL, QSFP_P16_MODPRS); +/* offset 0x61 */ +static SENSOR_DEVICE_ATTR(qsfp_p01_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P01_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p02_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P02_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p03_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P03_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p04_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P04_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p05_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P05_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p06_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P06_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p07_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P07_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p08_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P08_INTR); +/* offset 0x62 */ +static SENSOR_DEVICE_ATTR(qsfp_p09_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P09_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p10_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P10_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p11_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P11_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p12_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P12_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p13_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P13_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p14_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P14_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p15_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P15_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p16_intr, S_IRUGO, swpld2_data_show, NULL, QSFP_P16_INTR); + + +static struct attribute *swpld2_device_attrs[] = { + &sensor_dev_attr_swpld2_ver_type.dev_attr.attr, + &sensor_dev_attr_swpld2_ver.dev_attr.attr, + &sensor_dev_attr_qsfp_p01_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p02_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p03_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p04_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p05_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p06_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p07_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p08_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p09_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p10_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p11_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p12_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p13_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p14_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p15_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p16_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p01_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p02_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p03_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p04_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p05_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p06_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p07_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p08_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p09_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p10_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p11_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p12_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p13_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p14_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p15_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p16_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p01_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p02_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p03_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p04_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p05_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p06_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p07_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p08_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p09_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p10_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p11_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p12_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p13_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p14_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p15_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p16_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p01_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p02_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p03_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p04_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p05_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p06_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p07_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p08_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p09_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p10_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p11_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p12_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p13_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p14_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p15_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p16_intr.dev_attr.attr, +}; + + +static ssize_t swpld3_data_show(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_swpld3->parent); + struct platform_data *pdata = i2cdev->platform_data; + unsigned int select = 0; + unsigned char offset = 0; + int mask = 0xFF; + int shift = 0; + int value = 0; + bool hex_fmt = 0; + char desc[256] = {0}; + + select = attr->index; + switch(select) { + case SWPLD3_VER_TYPE: + offset = 0x1; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\nSWPLD3 Version Type.\n"); + break; + case SWPLD3_VER: + offset = 0x1; + mask = 0x7f; + scnprintf(desc, PAGE_SIZE, "\nSWPLD3 Version.\n"); + break; + case QSFP_P17_RST: + offset = 0x11; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P18_RST: + offset = 0x11; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P19_RST: + offset = 0x11; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P20_RST: + offset = 0x11; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P21_RST: + offset = 0x11; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P22_RST: + offset = 0x11; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P23_RST: + offset = 0x11; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P24_RST: + offset = 0x11; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P25_RST: + offset = 0x12; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P26_RST: + offset = 0x12; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P27_RST: + offset = 0x12; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P28_RST: + offset = 0x12; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P29_RST: + offset = 0x12; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P30_RST: + offset = 0x12; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P31_RST: + offset = 0x12; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P32_RST: + offset = 0x12; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Normal Operation.\n“0” = Reset.\n"); + break; + case QSFP_P17_LPMODE: + offset = 0x21; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P18_LPMODE: + offset = 0x21; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P19_LPMODE: + offset = 0x21; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P20_LPMODE: + offset = 0x21; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P21_LPMODE: + offset = 0x21; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P22_LPMODE: + offset = 0x21; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P23_LPMODE: + offset = 0x21; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P24_LPMODE: + offset = 0x21; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P25_LPMODE: + offset = 0x22; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P26_LPMODE: + offset = 0x22; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P27_LPMODE: + offset = 0x22; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P28_LPMODE: + offset = 0x22; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P29_LPMODE: + offset = 0x22; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P30_LPMODE: + offset = 0x22; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P31_LPMODE: + offset = 0x22; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P32_LPMODE: + offset = 0x22; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = LP Mode.\n“0” = Not LP Mode.\n"); + break; + case QSFP_P17_MODPRS: + offset = 0x51; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P18_MODPRS: + offset = 0x51; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P19_MODPRS: + offset = 0x51; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P20_MODPRS: + offset = 0x51; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P21_MODPRS: + offset = 0x51; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P22_MODPRS: + offset = 0x51; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P23_MODPRS: + offset = 0x51; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P24_MODPRS: + offset = 0x51; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P25_MODPRS: + offset = 0x52; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P26_MODPRS: + offset = 0x52; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P27_MODPRS: + offset = 0x52; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P28_MODPRS: + offset = 0x52; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P29_MODPRS: + offset = 0x52; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P30_MODPRS: + offset = 0x52; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P31_MODPRS: + offset = 0x52; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P32_MODPRS: + offset = 0x52; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Present.\n“0” = Present.\n"); + break; + case QSFP_P17_INTR: + offset = 0x61; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P18_INTR: + offset = 0x61; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P19_INTR: + offset = 0x61; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P20_INTR: + offset = 0x61; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P21_INTR: + offset = 0x61; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P22_INTR: + offset = 0x61; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P23_INTR: + offset = 0x61; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P24_INTR: + offset = 0x61; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P25_INTR: + offset = 0x62; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P26_INTR: + offset = 0x62; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P27_INTR: + offset = 0x62; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P28_INTR: + offset = 0x62; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P29_INTR: + offset = 0x62; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P30_INTR: + offset = 0x62; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P31_INTR: + offset = 0x62; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case QSFP_P32_INTR: + offset = 0x62; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Not Assert Intrrupt.\n“0” = Assert Intrrupt.\n"); + break; + case SFP_P0_MODPRS: + offset = 0x71; + shift = 6; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Absent.\n“0” = Present.\n"); + break; + case SFP_P0_RXLOS: + offset = 0x71; + shift = 5; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Receive Loss.\n“0” = Normal Operation.\n"); + break; + case SFP_P0_TXFAULT: + offset = 0x71; + shift = 4; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Transmit Fault.\n“0” = Normal Operation.\n"); + break; + case SFP_P1_MODPRS: + offset = 0x71; + shift = 2; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Absent.\n“0” = Present.\n"); + break; + case SFP_P1_RXLOS: + offset = 0x71; + shift = 1; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Receive Loss.\n“0” = Normal Operation.\n"); + break; + case SFP_P1_TXFAULT: + offset = 0x71; + shift = 0; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Transmit Fault.\n“0” = Normal Operation.\n"); + break; + case SFP_P0_TXDIS: + offset = 0x72; + shift = 7; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable.\n“0” = Normal Operation.\n"); + break; + case SFP_P1_TXDIS: + offset = 0x72; + shift = 3; + mask = (1 << shift); + scnprintf(desc, PAGE_SIZE, "\n“1” = Disable.\n“0” = Normal Operation.\n"); + break; + } + + value = i2c_smbus_read_byte_data(pdata[swpld3].client, offset); + value = (value & mask) >> shift; + if(hex_fmt) { + return scnprintf(buf, PAGE_SIZE, "0x%02x%s", value, desc); + } else { + return scnprintf(buf, PAGE_SIZE, "%d%s", value, desc); + } +} + + +static ssize_t swpld3_data_store(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_swpld3->parent); + struct platform_data *pdata = i2cdev->platform_data; + unsigned int select = 0; + unsigned char offset = 0; + int mask = 0xFF; + int shift = 0; + int value = 0; + int err = 0; + unsigned long data; + + err = kstrtoul(buf, 0, &data); + if (err){ + return err; + } + + if (data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + switch (attr->index) { + case QSFP_P17_RST: + offset = 0x11; + shift = 7; + mask = (1 << shift); + break; + case QSFP_P18_RST: + offset = 0x11; + shift = 6; + mask = (1 << shift); + break; + case QSFP_P19_RST: + offset = 0x11; + shift = 5; + mask = (1 << shift); + break; + case QSFP_P20_RST: + offset = 0x11; + shift = 4; + mask = (1 << shift); + break; + case QSFP_P21_RST: + offset = 0x11; + shift = 3; + mask = (1 << shift); + break; + case QSFP_P22_RST: + offset = 0x11; + shift = 2; + mask = (1 << shift); + break; + case QSFP_P23_RST: + offset = 0x11; + shift = 1; + mask = (1 << shift); + break; + case QSFP_P24_RST: + offset = 0x11; + shift = 0; + mask = (1 << shift); + break; + case QSFP_P25_RST: + offset = 0x12; + shift = 7; + mask = (1 << shift); + break; + case QSFP_P26_RST: + offset = 0x12; + shift = 6; + mask = (1 << shift); + break; + case QSFP_P27_RST: + offset = 0x12; + shift = 5; + mask = (1 << shift); + break; + case QSFP_P28_RST: + offset = 0x12; + shift = 4; + mask = (1 << shift); + break; + case QSFP_P29_RST: + offset = 0x12; + shift = 3; + mask = (1 << shift); + break; + case QSFP_P30_RST: + offset = 0x12; + shift = 2; + mask = (1 << shift); + break; + case QSFP_P31_RST: + offset = 0x12; + shift = 1; + mask = (1 << shift); + break; + case QSFP_P32_RST: + offset = 0x12; + shift = 0; + mask = (1 << shift); + break; + case QSFP_P17_LPMODE: + offset = 0x21; + shift = 7; + mask = (1 << shift); + break; + case QSFP_P18_LPMODE: + offset = 0x21; + shift = 6; + mask = (1 << shift); + break; + case QSFP_P19_LPMODE: + offset = 0x21; + shift = 5; + mask = (1 << shift); + break; + case QSFP_P20_LPMODE: + offset = 0x21; + shift = 4; + mask = (1 << shift); + break; + case QSFP_P21_LPMODE: + offset = 0x21; + shift = 3; + mask = (1 << shift); + break; + case QSFP_P22_LPMODE: + offset = 0x21; + shift = 2; + mask = (1 << shift); + break; + case QSFP_P23_LPMODE: + offset = 0x21; + shift = 1; + mask = (1 << shift); + break; + case QSFP_P24_LPMODE: + offset = 0x21; + shift = 0; + mask = (1 << shift); + break; + case QSFP_P25_LPMODE: + offset = 0x22; + shift = 7; + mask = (1 << shift); + break; + case QSFP_P26_LPMODE: + offset = 0x22; + shift = 6; + mask = (1 << shift); + break; + case QSFP_P27_LPMODE: + offset = 0x22; + shift = 5; + mask = (1 << shift); + break; + case QSFP_P28_LPMODE: + offset = 0x22; + shift = 4; + mask = (1 << shift); + break; + case QSFP_P29_LPMODE: + offset = 0x22; + shift = 3; + mask = (1 << shift); + break; + case QSFP_P30_LPMODE: + offset = 0x22; + shift = 2; + mask = (1 << shift); + break; + case QSFP_P31_LPMODE: + offset = 0x22; + shift = 1; + mask = (1 << shift); + break; + case QSFP_P32_LPMODE: + offset = 0x22; + shift = 0; + mask = (1 << shift); + break; + case SFP_P0_TXDIS: + offset = 0x72; + shift = 7; + break; + case SFP_P1_TXDIS: + offset = 0x72; + shift = 3; + mask = (1 << shift); + break; + + } + + value = i2c_smbus_read_byte_data(pdata[swpld3].client, offset); + data = (value & ~mask) | (data << shift); + i2c_smbus_write_byte_data(pdata[swpld3].client, offset, data); + + return count; +} + +/* offset 0x01 */ +static SENSOR_DEVICE_ATTR(swpld3_ver_type, S_IRUGO, swpld3_data_show, NULL, SWPLD3_VER_TYPE); +static SENSOR_DEVICE_ATTR(swpld3_ver, S_IRUGO, swpld3_data_show, NULL, SWPLD3_VER); +/* offset 0x11 */ +static SENSOR_DEVICE_ATTR(qsfp_p17_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P17_RST); +static SENSOR_DEVICE_ATTR(qsfp_p18_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P18_RST); +static SENSOR_DEVICE_ATTR(qsfp_p19_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P19_RST); +static SENSOR_DEVICE_ATTR(qsfp_p20_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P20_RST); +static SENSOR_DEVICE_ATTR(qsfp_p21_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P21_RST); +static SENSOR_DEVICE_ATTR(qsfp_p22_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P22_RST); +static SENSOR_DEVICE_ATTR(qsfp_p23_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P23_RST); +static SENSOR_DEVICE_ATTR(qsfp_p24_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P24_RST); +/* offset 0x12 */ +static SENSOR_DEVICE_ATTR(qsfp_p25_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P25_RST); +static SENSOR_DEVICE_ATTR(qsfp_p26_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P26_RST); +static SENSOR_DEVICE_ATTR(qsfp_p27_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P27_RST); +static SENSOR_DEVICE_ATTR(qsfp_p28_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P28_RST); +static SENSOR_DEVICE_ATTR(qsfp_p29_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P29_RST); +static SENSOR_DEVICE_ATTR(qsfp_p30_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P30_RST); +static SENSOR_DEVICE_ATTR(qsfp_p31_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P31_RST); +static SENSOR_DEVICE_ATTR(qsfp_p32_rst, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P32_RST); +/* offset 0x21 */ +static SENSOR_DEVICE_ATTR(qsfp_p17_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P17_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p18_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P18_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p19_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P19_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p20_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P20_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p21_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P21_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p22_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P22_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p23_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P23_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p24_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P24_LPMODE); +/* offset 0x22 */ +static SENSOR_DEVICE_ATTR(qsfp_p25_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P25_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p26_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P26_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p27_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P27_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p28_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P28_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p29_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P29_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p30_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P30_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p31_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P31_LPMODE); +static SENSOR_DEVICE_ATTR(qsfp_p32_lpmode, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, QSFP_P32_LPMODE); +/* offset 0x51 */ +static SENSOR_DEVICE_ATTR(qsfp_p17_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P17_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p18_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P18_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p19_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P19_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p20_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P20_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p21_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P21_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p22_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P22_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p23_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P23_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p24_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P24_MODPRS); +/* offset 0x52 */ +static SENSOR_DEVICE_ATTR(qsfp_p25_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P25_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p26_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P26_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p27_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P27_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p28_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P28_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p29_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P29_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p30_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P30_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p31_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P31_MODPRS); +static SENSOR_DEVICE_ATTR(qsfp_p32_modprs, S_IRUGO, swpld3_data_show, NULL, QSFP_P32_MODPRS); +/* offset 0x61 */ +static SENSOR_DEVICE_ATTR(qsfp_p17_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P17_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p18_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P18_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p19_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P19_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p20_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P20_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p21_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P21_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p22_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P22_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p23_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P23_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p24_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P24_INTR); +/* offset 0x62 */ +static SENSOR_DEVICE_ATTR(qsfp_p25_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P25_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p26_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P26_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p27_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P27_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p28_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P28_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p29_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P29_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p30_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P30_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p31_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P31_INTR); +static SENSOR_DEVICE_ATTR(qsfp_p32_intr, S_IRUGO, swpld3_data_show, NULL, QSFP_P32_INTR); +/* offset 0x71 */ +static SENSOR_DEVICE_ATTR(sfp_p0_modprs, S_IRUGO, swpld3_data_show, NULL, SFP_P0_MODPRS); +static SENSOR_DEVICE_ATTR(sfp_p0_rxlos, S_IRUGO, swpld3_data_show, NULL, SFP_P0_RXLOS); +static SENSOR_DEVICE_ATTR(sfp_p0_txfault, S_IRUGO, swpld3_data_show, NULL, SFP_P0_TXFAULT); +static SENSOR_DEVICE_ATTR(sfp_p1_modprs, S_IRUGO, swpld3_data_show, NULL, SFP_P1_MODPRS); +static SENSOR_DEVICE_ATTR(sfp_p1_rxlos, S_IRUGO, swpld3_data_show, NULL, SFP_P1_RXLOS); +static SENSOR_DEVICE_ATTR(sfp_p1_txfault, S_IRUGO, swpld3_data_show, NULL, SFP_P1_TXFAULT); +/* offset 0x72 */ +static SENSOR_DEVICE_ATTR(sfp_p0_txdis, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, SFP_P0_TXDIS); +static SENSOR_DEVICE_ATTR(sfp_p1_txdis, S_IRUGO | S_IWUSR, swpld3_data_show, swpld3_data_store, SFP_P1_TXDIS); + +static struct attribute *swpld3_device_attrs[] = { + &sensor_dev_attr_swpld3_ver_type.dev_attr.attr, + &sensor_dev_attr_swpld3_ver.dev_attr.attr, + &sensor_dev_attr_qsfp_p17_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p18_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p19_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p20_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p21_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p22_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p23_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p24_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p25_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p26_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p27_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p28_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p29_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p30_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p31_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p32_rst.dev_attr.attr, + &sensor_dev_attr_qsfp_p17_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p18_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p19_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p20_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p21_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p22_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p23_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p24_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p25_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p26_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p27_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p28_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p29_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p30_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p31_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p32_lpmode.dev_attr.attr, + &sensor_dev_attr_qsfp_p17_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p18_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p19_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p20_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p21_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p22_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p23_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p24_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p25_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p26_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p27_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p28_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p29_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p30_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p31_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p32_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_p17_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p18_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p19_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p20_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p21_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p22_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p23_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p24_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p25_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p26_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p27_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p28_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p29_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p30_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p31_intr.dev_attr.attr, + &sensor_dev_attr_qsfp_p32_intr.dev_attr.attr, + &sensor_dev_attr_sfp_p0_modprs.dev_attr.attr, + &sensor_dev_attr_sfp_p0_rxlos.dev_attr.attr, + &sensor_dev_attr_sfp_p0_txfault.dev_attr.attr, + &sensor_dev_attr_sfp_p1_modprs.dev_attr.attr, + &sensor_dev_attr_sfp_p1_rxlos.dev_attr.attr, + &sensor_dev_attr_sfp_p1_txfault.dev_attr.attr, + &sensor_dev_attr_sfp_p0_txdis.dev_attr.attr, + &sensor_dev_attr_sfp_p1_txdis.dev_attr.attr, +}; + +static struct attribute_group swpld1_device_attr_group = { + .attrs = swpld1_device_attrs, +}; + +static struct attribute_group swpld2_device_attr_group = { + .attrs = swpld2_device_attrs, +}; + +static struct attribute_group swpld3_device_attr_group = { + .attrs = swpld3_device_attrs, +}; + + +static struct cpld_platform_data agc032_swpld_platform_data[] = { + [swpld1] = { + .reg_addr = SWPLD1_ADDR, + }, + [swpld2] = { + .reg_addr = SWPLD2_ADDR, + }, + [swpld3] = { + .reg_addr = SWPLD3_ADDR, + }, +}; + +static void device_release(struct device *dev) +{ + return; +} + + +static struct platform_device swpld_device = { + .name = "delta-agc032-swpld", + .id = 0, + .dev = { + .platform_data = agc032_swpld_platform_data, + .release = device_release + }, +}; + + +static int __init swpld_probe(struct platform_device *pdev) +{ + int ret; + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS8); + if (!parent) { + printk(KERN_ERR "Parent adapter (%d) not found\n", BUS8); + return -ENODEV; + } + + pdata[swpld1].client = i2c_new_dummy(parent, pdata[swpld1].reg_addr); + if (!pdata[swpld1].client) { + printk(KERN_ERR "Fail to create dummy i2c client for addr %d\n", pdata[swpld1].reg_addr); + goto error_swpld1; + } + + pdata[swpld2].client = i2c_new_dummy(parent, pdata[swpld2].reg_addr); + if (!pdata[swpld2].client) { + printk(KERN_ERR "Fail to create dummy i2c client for addr %d\n", pdata[swpld2].reg_addr); + goto error_swpld2; + } + + pdata[swpld3].client = i2c_new_dummy(parent, pdata[swpld3].reg_addr); + if (!pdata[swpld3].client) { + printk(KERN_ERR "Fail to create dummy i2c client for addr %d\n", pdata[swpld3].reg_addr); + goto error_swpld3; + } +#if 1 + kobj_swpld1 = kobject_create_and_add("SWPLD1", &pdev->dev.kobj); + if (!kobj_swpld1){ + printk(KERN_ERR "Fail to create directory"); + goto error_swpld3; + } + + kobj_swpld2 = kobject_create_and_add("SWPLD2", &pdev->dev.kobj); + if (!kobj_swpld2){ + printk(KERN_ERR "Fail to create directory"); + goto error_swpld3; + } + + kobj_swpld3 = kobject_create_and_add("SWPLD3", &pdev->dev.kobj); + if (!kobj_swpld3){ + printk(KERN_ERR "Fail to create directory"); + goto error_swpld3; + } +#endif +#if 1 + ret = sysfs_create_group(kobj_swpld1, &swpld1_device_attr_group); + if (ret) { + printk(KERN_ERR "Fail to create SWPLD1 attribute group"); + goto error_add_swpld1; + } +#endif +#if 1 + ret = sysfs_create_group(kobj_swpld2, &swpld2_device_attr_group); + if (ret) { + printk(KERN_ERR "Fail to create SWPLD2 attribute group"); + goto error_add_swpld2; + } +#endif +#if 1 + ret = sysfs_create_group(kobj_swpld3, &swpld3_device_attr_group); + if (ret) { + printk(KERN_ERR "Fail to create SWPLD3 attribute group"); + goto error_add_swpld3; + } +#endif + return 0; + +error_add_swpld3: + kobject_put(kobj_swpld2); +error_add_swpld2: + kobject_put(kobj_swpld1); +error_add_swpld1: + i2c_unregister_device(pdata[swpld3].client); +error_swpld3: + i2c_unregister_device(pdata[swpld2].client); +error_swpld2: + i2c_unregister_device(pdata[swpld1].client); +error_swpld1: + i2c_put_adapter(parent); +} + +static int __exit swpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + + if (!kobj_swpld1){ + sysfs_remove_group(kobj_swpld1, &swpld1_device_attr_group); + } + if (!kobj_swpld2){ + sysfs_remove_group(kobj_swpld2, &swpld2_device_attr_group); + } + if (!kobj_swpld3){ + sysfs_remove_group(kobj_swpld3, &swpld3_device_attr_group); + } + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld1].client) { + if (!parent) { + parent = (pdata[swpld1].client)->adapter; + } + i2c_unregister_device(pdata[swpld1].client); + } + if (pdata[swpld2].client) { + if (!parent) { + parent = (pdata[swpld2].client)->adapter; + } + i2c_unregister_device(pdata[swpld2].client); + } + if (pdata[swpld3].client) { + if (!parent) { + parent = (pdata[swpld3].client)->adapter; + } + i2c_unregister_device(pdata[swpld3].client); + } + } + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver swpld_driver = { + .probe = swpld_probe, + .remove = __exit_p(swpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-agc032-swpld", + }, +}; + +static int __init delta_agc032_swpld_init(void) +{ + int ret; + int i = 0; + + printk(KERN_INFO "agc032_platform_swpld module initialization\n"); + + /* Register SWPLD driver */ + ret = platform_driver_register(&swpld_driver); + if (ret) { + printk(KERN_ERR "Fail to register swpld driver\n"); + goto error_swpld1_driver; + } + + /* Register SWPLD Device */ + ret = platform_device_register(&swpld_device); + if (ret) { + printk(KERN_ERR "Fail to create swpld device\n"); + goto error_swpld1_device; + } + + return 0; + +error_swpld1_device: + platform_driver_unregister(&swpld_driver); +error_swpld1_driver: + return ret; +} + +static void __exit delta_agc032_swpld_exit(void) +{ + + platform_device_unregister(&swpld_device); + platform_driver_unregister(&swpld_driver); +} + +module_init(delta_agc032_swpld_init); +module_exit(delta_agc032_swpld_exit); + +MODULE_DESCRIPTION("DNI agc032 SWPLD Platform Support"); +MODULE_AUTHOR("James Ke "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/agc032/modules/dni_agc032_psu.c b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/dni_agc032_psu.c new file mode 100644 index 000000000000..ee46769fd311 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/dni_agc032_psu.c @@ -0,0 +1,549 @@ +/* + * An hwmon driver for delta AGC032 PSU + * dps_1600ab_29_a.c - Support for DPS-1600AB-29 A Power Supply Module + * + * Copyright (C) 2016 Delta Network Technology Corporation + * + * DNI + * + * Based on ym2651y.c + * Based on ad7414.c + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 +#define SWPLD_REG 0x31 +#define SWPLD_PSU_MUX_REG 0x21 +#define SELECT_PSU1_EEPROM 0x00 +#define SELECT_PSU2_EEPROM 0x20 + +u8 psu_member_data = 0x00; + + +/* Address scanned */ +static const unsigned short normal_i2c[] = { 0x58, I2C_CLIENT_END }; + +/* This is additional data */ +struct dps_1600ab_29_a_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; /* In jiffies */ + + /* Registers value */ + u8 vout_mode; + u16 in1_input; + u16 in2_input; + u16 curr1_input; + u16 curr2_input; + u16 power1_input; + u16 power2_input; + u16 temp_input[2]; + u8 fan_target; + u16 fan_duty_cycle_input[2]; + u16 fan_speed_input[2]; + u8 mfr_model[16]; + u8 mfr_serial[16]; +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count); +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_fan_target(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static int dps_1600ab_29_a_read_byte(struct i2c_client *client, u8 reg); +static int dps_1600ab_29_a_read_word(struct i2c_client *client, u8 reg); +static int dps_1600ab_29_a_write_word(struct i2c_client *client, u8 reg, \ + u16 value); +static int dps_1600ab_29_a_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len); +static struct dps_1600ab_29_a_data *dps_1600ab_29_a_update_device( \ + struct device *dev); +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t set_w_member_data(struct device *dev, struct device_attribute \ + *dev_att, const char *buf, size_t count); +static ssize_t for_r_member_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); + +enum dps_1600ab_29_a_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_MFR_MODEL, + PSU_MFR_SERIAL, + PSU_SELECT_MEMBER, +}; + +static ssize_t set_w_member_data(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + long data; + int error; + if (attr->index == PSU_SELECT_MEMBER) { + error = kstrtol(buf, 16, &data); + if (error) + return error; + if (SELECT_PSU1_EEPROM == data) { + psu_member_data = SELECT_PSU1_EEPROM; + } else if (SELECT_PSU2_EEPROM == data) { + psu_member_data = SELECT_PSU2_EEPROM; + } else { + return -EINVAL; + } + } + return count; +} + +static ssize_t for_r_member_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + return sprintf(buf, "0x%02X\n", psu_member_data); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle_input(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct i2c_client *client = to_i2c_client(dev); + struct dps_1600ab_29_a_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + /* Select SWPLD PSU offset */ + + mutex_lock(&data->update_lock); + data->fan_duty_cycle_input[nr] = speed; + dps_1600ab_29_a_write_word(client, 0x3B + nr, data->fan_duty_cycle_input[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_1600ab_29_a_data *data = dps_1600ab_29_a_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->in1_input; + break; + case PSU_I_IN: + value = data->curr1_input; + break; + case PSU_I_OUT: + value = data->curr2_input; + break; + case PSU_P_IN: + value = data->power1_input; + multiplier = 1000*1000; + break; + case PSU_P_OUT: + value = data->power2_input; + multiplier = 1000*1000; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle_input[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed_input[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_fan_target(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_1600ab_29_a_data *data = dps_1600ab_29_a_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_target >> shift); +} + +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct dps_1600ab_29_a_data *data = dps_1600ab_29_a_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->in2_input; + + return (exponent > 0) ? sprintf(buf, "%d\n", \ + (mantissa * multiplier) / (1 << exponent)): \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_1600ab_29_a_data *data = dps_1600ab_29_a_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) + return 0; + + switch (attr->index) { + case PSU_MFR_MODEL: + ptr = data->mfr_model + 1; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial + 1; + break; + default: + return 0; + } + return sprintf(buf, "%s\n", ptr); +} +static int dps_1600ab_29_a_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int dps_1600ab_29_a_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int dps_1600ab_29_a_write_word(struct i2c_client *client, u8 reg, \ + u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags |= I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, reg, + I2C_SMBUS_WORD_DATA, &data); + +} + +static int dps_1600ab_29_a_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, + data); + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; +abort: + return result; + +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct dps_1600ab_29_a_data *dps_1600ab_29_a_update_device( \ + struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct dps_1600ab_29_a_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + /* Select SWPLD PSU offset */ + + if (time_after(jiffies, data->last_updated)) { + int i, status; + u8 command; + struct reg_data_byte regs_byte[] = { + {0x20, &data->vout_mode}, + {0x81, &data->fan_target} + }; + struct reg_data_word regs_word[] = { + {0x88, &data->in1_input}, + {0x8b, &data->in2_input}, + {0x89, &data->curr1_input}, + {0x8c, &data->curr2_input}, + {0x96, &data->power2_input}, + {0x97, &data->power1_input}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle_input[0])}, + {0x90, &(data->fan_speed_input[0])}, + }; + + dev_dbg(&client->dev, "start data update\n"); + + /* one milliseconds from now */ + data->last_updated = jiffies + HZ / 1000; + + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = dps_1600ab_29_a_read_byte(client, + regs_byte[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + } else { + *(regs_byte[i].value) = status; + } + } + + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = dps_1600ab_29_a_read_word(client, + regs_word[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + } else { + *(regs_word[i].value) = status; + } + } + + command = 0x9a; /* PSU mfr_model */ + //data->mfr_model[1] = '\0'; + status = dps_1600ab_29_a_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command,status); + data->mfr_model[1] = '\0'; + } + + command = 0x9e; /* PSU mfr_serial */ + //data->mfr_serial[1] = '\0'; + status = dps_1600ab_29_a_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command,status); + data->mfr_serial[1] = '\0'; + } + + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(temp1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_target, \ + S_IRUGO, for_fan_target, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(fan1_set_percentage, S_IWUSR | S_IRUGO, \ + for_linear_data, set_fan_duty_cycle_input, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(fan1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_model, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); +static SENSOR_DEVICE_ATTR(psu_select_member, S_IWUSR | S_IRUGO, \ + for_r_member_data, set_w_member_data, PSU_SELECT_MEMBER); + +static struct attribute *dps_1600ab_29_a_attributes[] = { + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_target.dev_attr.attr, + &sensor_dev_attr_fan1_set_percentage.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + &sensor_dev_attr_psu_select_member.dev_attr.attr, + NULL +}; + +static const struct attribute_group dps_1600ab_29_a_group = { + .attrs = dps_1600ab_29_a_attributes, +}; + +static int dps_1600ab_29_a_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct dps_1600ab_29_a_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "new chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &dps_1600ab_29_a_group); + if (status) + goto exit_sysfs_create_group; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_hwmon_device_register; + } + + return 0; + +exit_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &dps_1600ab_29_a_group); +exit_sysfs_create_group: + kfree(data); +exit: + return status; +} + +static int dps_1600ab_29_a_remove(struct i2c_client *client) +{ + struct dps_1600ab_29_a_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &dps_1600ab_29_a_group); + kfree(data); + + return 0; +} + +enum id_name { + dni_agc032_psu, + dps_1600ab_29_a +}; + +static const struct i2c_device_id dps_1600ab_29_a_id[] = { + { "dni_agc032_psu", dni_agc032_psu }, + { "dps_1600ab_29_a", dps_1600ab_29_a }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dps_1600ab_29_a_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver dps_1600ab_29_a_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "dps_1600ab_29_a", + }, + .probe = dps_1600ab_29_a_probe, + .remove = dps_1600ab_29_a_remove, + .id_table = dps_1600ab_29_a_id, + .address_list = normal_i2c, +}; + +static int __init dps_1600ab_29_a_init(void) +{ + return i2c_add_driver(&dps_1600ab_29_a_driver); +} + +static void __exit dps_1600ab_29_a_exit(void) +{ + i2c_del_driver(&dps_1600ab_29_a_driver); +} + + +MODULE_DESCRIPTION("DPS_1600AB_29_A Driver"); +MODULE_LICENSE("GPL"); + +module_init(dps_1600ab_29_a_init); +module_exit(dps_1600ab_29_a_exit); diff --git a/platform/broadcom/sonic-platform-modules-delta/agc032/modules/dni_emc2302.c b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/dni_emc2302.c new file mode 100644 index 000000000000..c947db1e96c5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/dni_emc2302.c @@ -0,0 +1,363 @@ +/* + * + * + * Copyright (C) 2017 Delta Networks, Inc. + * + * This program is free software; you can redistribute it + * and/or modify it under the terms ofthe GNU General Public License as + * published by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * + * + * + * + * A hwmon driver for the SMSC EMC2302 fan controller + * Complete datasheet is available (6/2013) at: + * + */ + +#include +#include +#include +#include +#include + + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t set_fan_percentage(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_fan_percentage(struct device *dev, struct device_attribute * devattr, + char *buf); +static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, 0x2F, 0x4C, + 0x4D, I2C_CLIENT_END + }; + + +#define EMC2302_REG_DEVICE 0xFD +#define EMC2302_REG_VENDOR 0xFE + +//#define FAN_MINIMUN 0x33 /*20%*/ +#define FAN_MINIMUN 0x0 /*0%*/ +#define FAN_RPM_BASED 0xAB + +#define EMC2302_REG_FAN_DRIVE(n) (0x30 + 0x10 * n) +#define EMC2302_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * n) +#define EMC2302_REG_FAN_TACH(n) (0x3E + 0x10 * n) +#define EMC2302_REG_FAN_CONF(n) (0x32 + 0x10 * n) +#define EMC2302_REG_FAN_REAR_H_RPM(n) (0x3D + 0x10 * n) +#define EMC2302_REG_FAN_REAR_L_RPM(n) (0x3C + 0x10 * n) + +#define EMC2302_DEVICE 0x36 +#define EMC2302_VENDOR 0x5D +#define MAX_FAN_SPEED 23000 + +struct emc2302_data +{ + struct device *hwmon_dev; + struct attribute_group attrs; + struct mutex lock; +}; + +static int emc2302_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int emc2302_detect(struct i2c_client *client, + struct i2c_board_info *info); +static int emc2302_remove(struct i2c_client *client); + +static const struct i2c_device_id emc2302_id[] = +{ + { "emc2302", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2302_id); + +static struct i2c_driver emc2302_driver = +{ + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2302", + }, + .probe = emc2302_probe, + .remove = emc2302_remove, + .id_table = emc2302_id, + .detect = emc2302_detect, + .address_list = normal_i2c, +}; + +static SENSOR_DEVICE_ATTR(fan1_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 1); +static SENSOR_DEVICE_ATTR(fan1_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 0); +static SENSOR_DEVICE_ATTR(fan2_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 1); +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); + +static struct attribute *emc2302_attr[] = +{ + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan1_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan2_input_percentage.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + NULL +}; + +static ssize_t show_fan_percentage(struct device *dev, struct device_attribute * devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2302_data *data = i2c_get_clientdata(client); + int val; + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2302_REG_FAN_TACH(attr->index)); + mutex_unlock(&data->lock); + /* Left shift 3 bits for showing correct RPM */ + val = val >> 3; + if ((int)(3932160 * 2 / (val > 0 ? val : 1) == 960))return sprintf(buf, "%d\n", 0); + return sprintf(buf, "%d\n", (int)(3932160 * 2 / (val > 0 ? val : 1) * 100 / MAX_FAN_SPEED)); +} + + +static ssize_t set_fan_percentage(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2302_data *data = i2c_get_clientdata(client); + unsigned long hsb, lsb; + unsigned long tech; + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 100) + { + return -EINVAL; + } + + if (val <= 5) + { + hsb = 0xff; /*high bit*/ + lsb = 0xe0; /*low bit*/ + } + else + { + val = val * 230; + tech = (3932160 * 2) / (val > 0 ? val : 1); + hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff); + lsb = (uint8_t)((tech << 3) & 0x0f8); + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_REAR_L_RPM(attr->index), lsb); + mutex_unlock(&data->lock); + return count; +} + + +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2302_data *data = i2c_get_clientdata(client); + int val; + + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2302_REG_FAN_TACH(attr->index)); + mutex_unlock(&data->lock); + /* Left shift 3 bits for showing correct RPM */ + val = val >> 3; + return sprintf(buf, "%d\n", 3932160 * 2 / (val > 0 ? val : 1)); +} + +static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2302_data *data = i2c_get_clientdata(client); + unsigned long hsb, lsb; + unsigned long tech; + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 23000) + { + return -EINVAL; + } + + if (val <= 960) + { + hsb = 0xff; /*high bit*/ + lsb = 0xe0; /*low bit*/ + } + else + { + tech = (3932160 * 2) / (val > 0 ? val : 1); + hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff); + lsb = (uint8_t)((tech << 3) & 0x0f8); + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_REAR_L_RPM(attr->index), lsb); + mutex_unlock(&data->lock); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2302_data *data = i2c_get_clientdata(client); + int val; + + mutex_lock(&data->lock); + val = i2c_smbus_read_byte_data(client, + EMC2302_REG_FAN_DRIVE(attr->index)); + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", val); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2302_data *data = i2c_get_clientdata(client); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 255) + { + return -EINVAL; + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, + EMC2302_REG_FAN_DRIVE(attr->index), + val); + mutex_unlock(&data->lock); + return count; +} + +static int emc2302_detect(struct i2c_client *client, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + int vendor, device; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + { + return -ENODEV; + } + + vendor = i2c_smbus_read_byte_data(client, EMC2302_REG_VENDOR); + if (vendor != EMC2302_VENDOR) + { + return -ENODEV; + } + + device = i2c_smbus_read_byte_data(client, EMC2302_REG_DEVICE); + if (device != EMC2302_DEVICE) + { + return -ENODEV; + } + + strlcpy(info->type, "emc2302", I2C_NAME_SIZE); + + return 0; +} + +static int emc2302_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct emc2302_data *data; + int err; + int i; + + data = devm_kzalloc(&client->dev, sizeof(struct emc2302_data), + GFP_KERNEL); + if (!data) + { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s chip found\n", client->name); + + data->attrs.attrs = emc2302_attr; + err = sysfs_create_group(&client->dev.kobj, &data->attrs); + if (err) + { + return err; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) + { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + for (i = 0; i < 2; i++) + { + /* set minimum drive to 0% */ + i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_MIN_DRIVE(i), FAN_MINIMUN); + i2c_smbus_write_byte_data(client, EMC2302_REG_FAN_CONF(i), FAN_RPM_BASED); + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +} + +static int emc2302_remove(struct i2c_client *client) +{ + struct emc2302_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return 0; +} + +module_i2c_driver(emc2302_driver); + +MODULE_AUTHOR("Zoe Kuan"); +MODULE_DESCRIPTION("SMSC EMC2302 fan controller driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/agc032/modules/dni_emc2305.c b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/dni_emc2305.c new file mode 120000 index 000000000000..e8f7ae6b3f4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/agc032/modules/dni_emc2305.c @@ -0,0 +1 @@ +../../common/modules/dni_emc2305.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-delta/agc032/scripts/agc032_platform_init.sh b/platform/broadcom/sonic-platform-modules-delta/agc032/scripts/agc032_platform_init.sh new file mode 100755 index 000000000000..e14470a4c908 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/agc032/scripts/agc032_platform_init.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +#platform init script for Delta agc032 + +#fan speed monitor start +/usr/share/sonic/device/x86_64-delta_agc032-r0/fancontrol.service /usr/share/sonic/device/x86_64-delta_agc032-r0/fancontrol & + +# On Delta-agc032 platform, +# syseeprom is on the different mux with main board after CPLD, +# we have to switch CPLD mux from main board to syseeprom before getting syseeprom data. +# +# The purpose of switching CPLD mux and getting syseeprom information here +# is to store data in syseeprom_cache. +# After that, we can read "syseeprom_cache" directly when executing command +# "show platform syseeprom", "sudo decode-syseeprom", "show version". + +echo 0 |sudo tee /sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel +decode-syseeprom +echo 1 |sudo tee /sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel + +exit 0 + diff --git a/platform/broadcom/sonic-platform-modules-delta/common/modules/dni_emc2305.c b/platform/broadcom/sonic-platform-modules-delta/common/modules/dni_emc2305.c new file mode 100644 index 000000000000..73d9900af5b4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/common/modules/dni_emc2305.c @@ -0,0 +1,381 @@ +/* + * + * + * Copyright (C) 2017 Delta Networks, Inc. + * + * This program is free software; you can redistribute it + * and/or modify it under the terms ofthe GNU General Public License as + * published by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * + * + * + * + * A hwmon driver for the SMSC EMC2305 fan controller + * Complete datasheet is available (6/2013) at: + * http://www.smsc.com/media/Downloads_Public/Data_Sheets/2305.pdf + */ + +#include +#include +#include +#include +#include + + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t set_fan_percentage(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_fan_percentage(struct device *dev, struct device_attribute * devattr, + char *buf); +static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, 0x2F, 0x4C, + 0x4D, I2C_CLIENT_END + }; + + +#define EMC2305_REG_DEVICE 0xFD +#define EMC2305_REG_VENDOR 0xFE + +//#define FAN_MINIMUN 0x33 /*20%*/ +#define FAN_MINIMUN 0x0 /*0%*/ +#define FAN_RPM_BASED 0xAB + +#define EMC2305_REG_FAN_DRIVE(n) (0x30 + 0x10 * n) +#define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * n) +#define EMC2305_REG_FAN_TACH(n) (0x3E + 0x10 * n) +#define EMC2305_REG_FAN_CONF(n) (0x32 + 0x10 * n) +#define EMC2305_REG_FAN_REAR_H_RPM(n) (0x3D + 0x10 * n) +#define EMC2305_REG_FAN_REAR_L_RPM(n) (0x3C + 0x10 * n) + +#define EMC2305_DEVICE 0x34 +#define EMC2305_VENDOR 0x5D +#define MAX_FAN_SPEED 23000 + +struct emc2305_data +{ + struct device *hwmon_dev; + struct attribute_group attrs; + struct mutex lock; +}; + +static int emc2305_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int emc2305_detect(struct i2c_client *client, + struct i2c_board_info *info); +static int emc2305_remove(struct i2c_client *client); + +static const struct i2c_device_id emc2305_id[] = +{ + { "emc2305", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2305_id); + +static struct i2c_driver emc2305_driver = +{ + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", + }, + .probe = emc2305_probe, + .remove = emc2305_remove, + .id_table = emc2305_id, + .detect = emc2305_detect, + .address_list = normal_i2c, +}; + +static SENSOR_DEVICE_ATTR(fan1_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 4); +static SENSOR_DEVICE_ATTR(fan1_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 0); +static SENSOR_DEVICE_ATTR(fan2_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 1); +static SENSOR_DEVICE_ATTR(fan3_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 2); +static SENSOR_DEVICE_ATTR(fan4_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 3); +static SENSOR_DEVICE_ATTR(fan5_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 4); +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 4); + +static struct attribute *emc2305_attr[] = +{ + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan1_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan2_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan3_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan4_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan5_input_percentage.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm5.dev_attr.attr, + NULL +}; + +static ssize_t show_fan_percentage(struct device *dev, struct device_attribute * devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2305_REG_FAN_TACH(attr->index)); + mutex_unlock(&data->lock); + /* Left shift 3 bits for showing correct RPM */ + val = val >> 3; + if ((int)(3932160 * 2 / (val > 0 ? val : 1) == 960))return sprintf(buf, "%d\n", 0); + return sprintf(buf, "%d\n", (int)(3932160 * 2 / (val > 0 ? val : 1) * 100 / MAX_FAN_SPEED)); +} + + +static ssize_t set_fan_percentage(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + unsigned long hsb, lsb; + unsigned long tech; + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 100) + { + return -EINVAL; + } + + if (val <= 5) + { + hsb = 0xff; /*high bit*/ + lsb = 0xe0; /*low bit*/ + } + else + { + val = val * 230; + tech = (3932160 * 2) / (val > 0 ? val : 1); + hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff); + lsb = (uint8_t)((tech << 3) & 0x0f8); + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_L_RPM(attr->index), lsb); + mutex_unlock(&data->lock); + return count; +} + + +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2305_REG_FAN_TACH(attr->index)); + mutex_unlock(&data->lock); + /* Left shift 3 bits for showing correct RPM */ + val = val >> 3; + return sprintf(buf, "%d\n", 3932160 * 2 / (val > 0 ? val : 1)); +} + +static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + unsigned long hsb, lsb; + unsigned long tech; + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 23000) + { + return -EINVAL; + } + + if (val <= 960) + { + hsb = 0xff; /*high bit*/ + lsb = 0xe0; /*low bit*/ + } + else + { + tech = (3932160 * 2) / (val > 0 ? val : 1); + hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff); + lsb = (uint8_t)((tech << 3) & 0x0f8); + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_L_RPM(attr->index), lsb); + mutex_unlock(&data->lock); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + mutex_lock(&data->lock); + val = i2c_smbus_read_byte_data(client, + EMC2305_REG_FAN_DRIVE(attr->index)); + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", val); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 255) + { + return -EINVAL; + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, + EMC2305_REG_FAN_DRIVE(attr->index), + val); + mutex_unlock(&data->lock); + return count; +} + +static int emc2305_detect(struct i2c_client *client, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + int vendor, device; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + { + return -ENODEV; + } + + vendor = i2c_smbus_read_byte_data(client, EMC2305_REG_VENDOR); + if (vendor != EMC2305_VENDOR) + { + return -ENODEV; + } + + device = i2c_smbus_read_byte_data(client, EMC2305_REG_DEVICE); + if (device != EMC2305_DEVICE) + { + return -ENODEV; + } + + strlcpy(info->type, "emc2305", I2C_NAME_SIZE); + + return 0; +} + +static int emc2305_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct emc2305_data *data; + int err; + int i; + + data = devm_kzalloc(&client->dev, sizeof(struct emc2305_data), + GFP_KERNEL); + if (!data) + { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s chip found\n", client->name); + + data->attrs.attrs = emc2305_attr; + err = sysfs_create_group(&client->dev.kobj, &data->attrs); + if (err) + { + return err; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) + { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + for (i = 0; i < 5; i++) + { + /* set minimum drive to 0% */ + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_MIN_DRIVE(i), FAN_MINIMUN); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_CONF(i), FAN_RPM_BASED); + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +} + +static int emc2305_remove(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return 0; +} + +module_i2c_driver(emc2305_driver); + +MODULE_AUTHOR("Neal Tai"); +MODULE_DESCRIPTION("SMSC EMC2305 fan controller driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/changelog b/platform/broadcom/sonic-platform-modules-delta/debian/changelog new file mode 100644 index 000000000000..ec8327e8ae7a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/changelog @@ -0,0 +1,5 @@ +sonic-delta-platform-modules (1.1) unstable; urgency=low + + * Initial release + + -- Neal Tai Fri, 21 APR 2017 11:11:11 -0800 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/compat b/platform/broadcom/sonic-platform-modules-delta/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/control b/platform/broadcom/sonic-platform-modules-delta/debian/control new file mode 100644 index 000000000000..809c58b0c0b1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/control @@ -0,0 +1,36 @@ +Source: sonic-delta-platform-modules +Section: main +Priority: extra +Maintainer: Neal Tai +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-ag9032v1 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-ag9064 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-ag5648 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-et-6248brb +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-ag9032v2a +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as syseeprom, sfp + +Package: platform-modules-agc032 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.init new file mode 100755 index 000000000000..d69534035a54 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.init @@ -0,0 +1,49 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ag5648 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + depmod -a + rmmod i2c-i801 + rmmod i2c-ismt + modprobe i2c-dev + modprobe i2c-i801 + modprobe i2c-ismt + modprobe i2c-mux-pca954x + modprobe dni_ag5648_psu + modprobe dni_emc2305 + modprobe at24 + modprobe delta_ag5648_platform + + /usr/local/bin/ag5648_platform_init.sh + + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-ag5648.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.install new file mode 100644 index 000000000000..06d536770167 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag5648.install @@ -0,0 +1,4 @@ +ag5648/scripts/ag5648_platform_init.sh usr/local/bin +ag5648/cfg/ag5648-modules.conf etc/modules-load.d +ag5648/scripts/led_control usr/local/bin +systemd/platform-modules-ag5648.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.init new file mode 100755 index 000000000000..3734ab362a2f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v1.init @@ -0,0 +1,49 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ag9032v1 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + depmod -a + rmmod i2c-i801 + rmmod i2c-ismt + modprobe i2c-dev + modprobe i2c-i801 + modprobe i2c-ismt + modprobe i2c-mux-pca954x + modprobe dni_ag9032v1_psu + modprobe dni_emc2305 + modprobe at24 + modprobe delta_ag9032v1_platform + modprobe delta_ag9032v1_cpupld + + /usr/local/bin/ag9032v1_platform_init.sh + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-ag9032v1.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v2a.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v2a.init new file mode 100755 index 000000000000..8ff27a87d9ca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v2a.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ag9032v2a board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + modprobe ipmi_devintf + modprobe ipmi_si ports=0xca2 + modprobe optoe + modprobe delta_ag9032v2a_platform + /usr/local/bin/ag9032v2a_platform_init.sh + + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-ag9032v2a.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v2a.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v2a.install new file mode 100644 index 000000000000..691480c34687 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9032v2a.install @@ -0,0 +1,3 @@ +ag9032v2a/scripts/ag9032v2a_platform_init.sh usr/local/bin +ag9032v2a/cfg/ag9032v2a-modules.conf etc/modules-load.d +systemd/platform-modules-ag9032v2a.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.init new file mode 100755 index 000000000000..74137b8b2dc3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.init @@ -0,0 +1,64 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ag9064 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + if [ `grep -c usemsi /etc/init.d/opennsl-modules` = "0" ]; then + sed -i "s/debug=4 dma_debug=1/debug=4 dma_debug=1 usemsi=1/g" /etc/init.d/opennsl-modules + rmmod linux_knet_cb + rmmod linux_bcm_knet + rmmod linux_user_bde + rmmod linux_kernel_bde + /etc/init.d/opennsl-modules start + modprobe linux_kernel_bde + modprobe linux_user_bde + modprobe linux_bcm_knet + modprobe linux_knet_cb + fi + depmod -a + rmmod i2c-i801 + rmmod i2c-ismt + modprobe i2c-dev + modprobe i2c-i801 + modprobe i2c-ismt + modprobe ipmi_devintf + modprobe ipmi_si ports=0xca2 + modprobe i2c-mei + modprobe i2c-mux-pca954x + modprobe at24 + modprobe delta_ag9064_platform + modprobe delta_ag9064_cpld + modprobe delta_ag9064_swpld + + /usr/local/bin/ag9064_platform_init.sh + + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-ag9064.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.install new file mode 100644 index 000000000000..ad7c793da3c0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.install @@ -0,0 +1,2 @@ +ag9064/cfg/ag9064-modules.conf etc/modules-load.d +systemd/platform-modules-ag9064.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.postinst b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.postinst new file mode 100644 index 000000000000..6044de232776 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-ag9064.postinst @@ -0,0 +1,19 @@ +# postinst script for ag9064 + +# Insert kernel module +depmod -a +modprobe i2c-dev +modprobe i2c-i801 +modprobe i2c-ismt +modprobe ipmi_devintf +modprobe ipmi_si ports=0xca2 +modprobe i2c-mei +modprobe i2c-mux-pca954x +modprobe at24 +modprobe optoe +modprobe delta_ag9064_platform +modprobe delta_ag9064_cpld +modprobe delta_ag9064_swpld + +#DEBHELPER# + diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-agc032.init b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-agc032.init new file mode 100644 index 000000000000..5c106f87f919 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-agc032.init @@ -0,0 +1,62 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup agc032 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + depmod -a + rmmod i2c-i801 + rmmod i2c-ismt + modprobe i2c-dev + modprobe i2c-i801 + modprobe i2c-ismt + modprobe i2c-mux-pca954x + modprobe dni_agc032_psu + modprobe dni_emc2305 + modprobe dni_emc2302 + modprobe at24 + modprobe optoe + modprobe delta_agc032_cpupld +# Switch CPUPLD to ONIE EEPROM Mux + echo 0 |sudo tee /sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel + modprobe eeprom + +# Switch CPUPLD to Front Port Mux + echo 3 |sudo tee /sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel + modprobe delta_agc032_qsfp + +# Switch CPUPLD to MainBoard Mux + echo 1 |sudo tee /sys/devices/platform/delta-agc032-cpupld.0/cpu_i2c_mux_sel + modprobe delta_agc032_platform + modprobe delta_agc032_swpld + + /usr/local/bin/agc032_platform_init.sh + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-agc032.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-agc032.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-agc032.install new file mode 100644 index 000000000000..e05e3694fd3e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-agc032.install @@ -0,0 +1,3 @@ +agc032/scripts/agc032_platform_init.sh usr/local/bin +agc032/cfg/agc032-modules.conf etc/modules-load.d +systemd/platform-modules-agc032.service lib/systemd/system 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 new file mode 100755 index 000000000000..58681208ef6c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.init @@ -0,0 +1,80 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup et-6248brb board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + depmod -a + rmmod i2c-i801 + rmmod i2c-ismt + modprobe i2c-dev + modprobe i2c-i801 + modprobe i2c-ismt + modprobe i2c-mux-pca954x + modprobe i2c-mux-gpio + modprobe dni_gpio + modprobe delta_et-6248brb_platform + + 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" + echo "485" > "/sys/class/gpio/export" + echo "489" > "/sys/class/gpio/export" + echo "494" > "/sys/class/gpio/export" + echo "out" > "/sys/class/gpio/gpio453/direction" + echo "out" > "/sys/class/gpio/gpio454/direction" + echo "out" > "/sys/class/gpio/gpio455/direction" + echo "out" > "/sys/class/gpio/gpio485/direction" + echo "out" > "/sys/class/gpio/gpio489/direction" + echo "out" > "/sys/class/gpio/gpio494/direction" + else + echo "197" > "/sys/class/gpio/export" + echo "198" > "/sys/class/gpio/export" + echo "199" > "/sys/class/gpio/export" + echo "229" > "/sys/class/gpio/export" + echo "233" > "/sys/class/gpio/export" + echo "238" > "/sys/class/gpio/export" + echo "out" > "/sys/class/gpio/gpio197/direction" + echo "out" > "/sys/class/gpio/gpio198/direction" + echo "out" > "/sys/class/gpio/gpio199/direction" + echo "out" > "/sys/class/gpio/gpio229/direction" + echo "out" > "/sys/class/gpio/gpio233/direction" + echo "out" > "/sys/class/gpio/gpio238/direction" + fi + + /usr/local/bin/et-6248brb_platform_init.sh + + sleep 1 + echo "Ethernet48" > "/sys/bus/i2c/devices/4-0050/port_name" + echo "Ethernet49" > "/sys/bus/i2c/devices/5-0050/port_name" + + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-et-6248brb.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.install b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.install new file mode 100644 index 000000000000..936c43679d5c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/platform-modules-et-6248brb.install @@ -0,0 +1,4 @@ +et-6248brb/scripts/et-6248brb_platform_init.sh usr/local/bin +et-6248brb/cfg/et-6248brb-modules.conf etc/modules-load.d +et-6248brb/scripts/led_status.sh usr/local/bin +systemd/platform-modules-et-6248brb.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/rules b/platform/broadcom/sonic-platform-modules-delta/debian/rules new file mode 100755 index 000000000000..39126ff76729 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/debian/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= ag9032v1 ag9064 ag5648 et-6248brb ag9032v2a agc032 + +%: + dh $@ --with=systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/cfg/et-6248brb-modules.conf b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/cfg/et-6248brb-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/cfg/et-6248brb-modules.conf @@ -0,0 +1,13 @@ +# /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-delta/et-6248brb/modules/Makefile b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/Makefile new file mode 100644 index 000000000000..fb5b18ed5b4c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := delta_et-6248brb_platform.o dni_gpio.o + diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/delta_et-6248brb_platform.c b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/delta_et-6248brb_platform.c new file mode 100644 index 000000000000..7cbe161e62b2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/delta_et-6248brb_platform.c @@ -0,0 +1,918 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define OPTOE_INFO(data) \ + .type = "optoe2", .addr = 0x50 + +#define et6248brb_i2c_device_num(NUM){ \ + .name = "delta-et6248brb-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &et6248brb_i2c_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +#define et6248brb_gpio_num(NUM){ \ + .name = "delta-et6248brb-gpio", \ + .id = NUM, \ + .dev = { \ + .platform_data = &et6248brb_gpio_device_platform_data[NUM], \ + .release = device_release, \ + }, \ +} + +#define PCA9555_A 0x20 +#define PCA9555_B 0x21 +#define PCA9555_C 0x23 + +static struct kobject *kobj_gpio; +static struct kobject *kobj_psu; +static struct kobject *kobj_fan; +static struct kobject *kobj_sfp; +static struct kobject *kobj_others; + +/*Define struct to get client of i2c_new_deivce */ +struct i2c_client * i2c_client_9547; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, + BUS9, + BUS10, +}; + +/*---------------- I2C device - start ------------- */ +static void device_release(struct device *dev) +{ + return; +} + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; +/* pca9547 - add 8 bus */ +static struct pca954x_platform_mode pca954x_mode[] = { + { .adap_id = 2, + .deselect_on_exit = 1, + }, + { .adap_id = 3, + .deselect_on_exit = 1, + }, + { .adap_id = 4, + .deselect_on_exit = 1, + }, + { .adap_id = 5, + .deselect_on_exit = 1, + }, + { .adap_id = 6, + .deselect_on_exit = 1, + }, + { .adap_id = 7, + .deselect_on_exit = 1, + }, + { .adap_id = 8, + .deselect_on_exit = 1, + }, + { .adap_id = 9, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data = { + .modes = pca954x_mode, + .num_modes = ARRAY_SIZE(pca954x_mode), +}; + +static struct i2c_board_info __initdata i2c_info_pca9547[] = +{ + { + I2C_BOARD_INFO("pca9547", 0x71), + .platform_data = &pca954x_data, + }, +}; + +static struct i2c_device_platform_data et6248brb_i2c_device_platform_data[] = { + { + /* FAN controller (0x2e) */ + .parent = 0, + .info = { I2C_BOARD_INFO("adt7473", 0x2e) }, + .client = NULL, + }, + { + /* tmp75 (0x48) */ + .parent = 0, + .info = { I2C_BOARD_INFO("tmp75", 0x48) }, + .client = NULL, + }, + { + /* EEPROM (0x54) */ + .parent = 1, + .info = { I2C_BOARD_INFO("24c08", 0x54) }, + .client = NULL, + }, + { + /* sfp 1 (0x50) */ + .parent = 4, + .info = { OPTOE_INFO() }, + .client = NULL, + }, + { + /* sfp 2 (0x50) */ + .parent = 5, + .info = { OPTOE_INFO() }, + .client = NULL, + }, + { + /* tmp75 (0x49) */ + .parent = 7, + .info = { I2C_BOARD_INFO("tmp75", 0x49) }, + .client = NULL, + }, + { + /* tmp75 (0x4a) */ + .parent = 8, + .info = { I2C_BOARD_INFO("tmp75", 0x4a) }, + .client = NULL, + }, +}; + +static struct platform_device et6248brb_i2c_device[] = { + et6248brb_i2c_device_num(0), + et6248brb_i2c_device_num(1), + et6248brb_i2c_device_num(2), + et6248brb_i2c_device_num(3), + et6248brb_i2c_device_num(4), + et6248brb_i2c_device_num(5), + et6248brb_i2c_device_num(6), +}; + +/*---------------- I2C device - end ------------- */ +/*---------------- I2C driver - start ------------- */ +static int __init i2c_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + + return 0; +} +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-et6248brb-i2c-device", + } +}; +/*---------------- I2C driver - end ------------- */ + +/*---------------- gpio device - start ----------- */ +static struct pca953x_platform_data pca9555_data_0 = { + .gpio_base = 200, +}; +static struct pca953x_platform_data pca9555_data_1 = { + .gpio_base = 216, +}; +static struct pca953x_platform_data pca9555_data_2 = { + .gpio_base = 232, +}; + +static struct i2c_board_info __initdata i2c_info_pca9555[] = +{ + { + I2C_BOARD_INFO("pca9555", 0x20), + .platform_data = &pca9555_data_0, + }, + { + I2C_BOARD_INFO("pca9555", 0x21), + .platform_data = &pca9555_data_1, + }, + { + I2C_BOARD_INFO("pca9555", 0x23), + .platform_data = &pca9555_data_2, + }, +}; + +static struct i2c_device_platform_data et6248brb_gpio_device_platform_data[] = { + { + /* GPIO expander A (0x20) */ + .parent = 0, + .info = { I2C_BOARD_INFO("pca9555", 0x20) }, + .client = NULL, + }, + { + /* GPIO expander B (0x21) */ + .parent = 0, + .info = { I2C_BOARD_INFO("pca9555", 0x21) }, + .client = NULL, + }, + { + /* GPIO expander C (0x23) */ + .parent = 0, + .info = { I2C_BOARD_INFO("pca9555", 0x23) }, + .client = NULL, + }, +}; + +static struct platform_device et6248brb_gpio_device[] = { + et6248brb_gpio_num(0), + et6248brb_gpio_num(1), + et6248brb_gpio_num(2), +}; + +static struct gpio_attribute_data { + uint8_t bus; + uint8_t addr; + uint8_t reg; + uint8_t mask; + char note[150]; +}; + +enum gpio_attributes { + PSU1_SMB_ALERT, + PSU2_SMB_ALERT, + EEPROM_WP, + FAN1_LED_AG, + FAN2_LED_AG, + D_FAN_ALERT, + PSU1_PRES, + PSU2_PRES, + FAN_EEPROM_WP, + D_FAN_M_PRESENT2, + D_FAN_M_PRESENT1, + PSU1_PG, + PSU2_PG, + BCM54282_INT, + SFP_MOD_P1, + SFP_RXLOS_P1, + SFP_MOD_P2, + SFP_RXLOS_P2, + SFP_TX_FAULT_P1, + SFP_TX_FAULT_P2, + SFP_TX_DIS_P1, + SFP_TX_DIS_P2, + OOB_BCM54616S_INT, +}; + +static struct gpio_attribute_data attribute_data[] = { +//PCA9555_A + [PSU1_SMB_ALERT] = { + .bus = BUS0, .addr = PCA9555_A, + .reg = 0x00, .mask = 1 << 0, + .note = "0=PSU1 interrupt is occurr\n1=PSU1 interrupt is NOT occurr" + }, + [PSU2_SMB_ALERT] = { + .bus = BUS0, .addr = PCA9555_A, + .reg = 0x00, .mask = 1 << 3, + .note = "0=PSU2 interrupt is occurr\n1=PSU2 interrupt is NOT occurr" + }, + [EEPROM_WP] = { + .bus = BUS0, .addr = PCA9555_A, + .reg = 0x03, .mask = 1 << 3, + .note = "0=SYS eeprom write protect is disable\n1=SYS eeprom write protect is enable and can not be programmed" + + }, + [FAN1_LED_AG] = { + .bus = BUS0, .addr = PCA9555_A, + .reg = 0x03, .mask = 0x30, + .note = "00=LED off or FAN tray1 is not present\n01=LED Red,FAN tray1 fail\n10=LED Green,FAN tray1 is present\n11=reserved" + }, + [FAN2_LED_AG] = { + .bus = BUS0, .addr = PCA9555_A, + .reg = 0x03, .mask = 0xc0, + .note = "00=LED off or FAN tray1 is not present\n01=LED Red,FAN tray1 fail\n10=LED Green,FAN tray1 is present\n11=reserved" + }, +//PCA9555_B + [D_FAN_ALERT] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x00, .mask = 1 << 0, + .note ="0=FAN is NOT issue the alram\n1=FAN issue the alarm" + + }, + [PSU1_PRES] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x00, .mask = 1 << 2, + .note ="0=PSU1 is present\n1=PSU1 is NOT present" + }, + [PSU2_PRES] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x00, .mask = 1 << 3, + .note ="0=PSU2 is present\n1=PSU2 is NOT present" + }, + [FAN_EEPROM_WP] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 1, + .note ="0=FAN eeprom write protect is disable\n1=FAN eeprom write protect is enable and can not be programmed" + }, + [D_FAN_M_PRESENT2] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 2, + .note ="0=FAN2 module is present\n1=FAN2 module is NOT present" + }, + [D_FAN_M_PRESENT1] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 3, + .note ="0=FAN1 moduel is present\n1=FAN1 module is NOT present" + }, + [PSU1_PG] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 4, + .note ="0=PSU1 is FAIL or not present\n1=PSU1 is GOOD" + }, + [PSU2_PG] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 5, + .note ="0=PSU2 is FAIL or not present\n1=PSU2 is GOOD" + }, + [BCM54282_INT] = { + .bus = BUS0, .addr = PCA9555_B, + .reg = 0x01, .mask = 1 << 6, + .note ="0=BCM54282 PHY interrupt occurrs\n1=BCM54282 PHY interrupt is not occurrs" + }, +//PCA9555_C + [SFP_MOD_P1] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 0, + .note ="0=SFP1 transceiver is present\n1=SFP1 transceiver is NOT present" + }, + [SFP_RXLOS_P1] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 1, + .note ="0=SFP1 transceiver is NOT asserted Loss of signal\n1=SFP1 transceiver is asserted Loss of signal" + }, + [SFP_MOD_P2] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 2, + .note ="0=SFP1 transceiver is present\n1=SFP1 transceiver is NOT present" + }, + [SFP_RXLOS_P2] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 3, + .note ="0=SFP1 transceiver is NOT asserted Loss of signal\n1=SFP1 transceiver is asserted Loss of signal" + }, + [SFP_TX_FAULT_P1] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 4, + .note ="0=SFP1 transceiver is NOT asserted TXFAULT signal\n1=SFP1 transceiver is asserted TXFAULT signal" + }, + [SFP_TX_FAULT_P2] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x00, .mask = 1 << 5, + .note ="0=SFP1 transceiver is NOT asserted TXFAULT signal\n1=SFP1 transceiver is asserted TXFAULT signal" + }, + [SFP_TX_DIS_P1] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x02, .mask = 1 << 6, + .note ="0=SFP1 transceiver is turn ON\n1=SFP1 transceiver is turn OFF" + }, + [SFP_TX_DIS_P2] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x02, .mask = 1 << 7, + .note ="0=SFP2 transceiver is turn ON\n1=SFP2 transceiver is turn OFF" + }, + [OOB_BCM54616S_INT] = { + .bus = BUS0, .addr = PCA9555_C, + .reg = 0x01, .mask = 1 << 3, + .note ="0=BCM54616S PHY interrupt occurrs\n1=BCM54616S PHY interrupt is not occurrs" + }, +}; + +unsigned char dni_log2 (unsigned char num){ + unsigned char num_log2 = 0; + while(num > 0){ + num = num >> 1; + num_log2 += 1; + } + return num_log2 -1; +} + +void set_direction(struct i2c_device_platform_data *pdata, unsigned char reg, unsigned char mask){ + + int value; + int read_only; + unsigned char mask_out; + unsigned char set_data; + + read_only = 1; //Configuration:GPI + if (reg > 0x1){ + reg = reg - 0x02; + read_only = 0; //Configuration:GPO + } + + value = i2c_smbus_read_byte_data(pdata->client, reg + 0x06); + mask_out = value & ~(mask); + + if(read_only){ + set_data = mask_out | mask; + } + else{ + set_data = mask_out; + } + + i2c_smbus_write_byte_data(pdata->client, reg + 0x06, set_data); + return; +} + +static ssize_t get_gpio_reg(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + int mask; + int value; + char note[150]; + unsigned char pca9555_num; + unsigned char reg; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_gpio); + struct i2c_device_platform_data *pdata = i2cdev->platform_data; + + switch(attribute_data[attr->index].addr){ + case PCA9555_A: + pca9555_num = 0; + break; + case PCA9555_B: + pca9555_num = 1; + break; + case PCA9555_C: + pca9555_num = 2; + break; + default: + return sprintf(buf, "attribute address error"); + } + + set_direction(&pdata[pca9555_num], attribute_data[attr->index].reg, attribute_data[attr->index].mask); + + switch (attr->index) { + case PSU1_SMB_ALERT ... OOB_BCM54616S_INT: + reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[pca9555_num].client, reg); + sprintf(note, "\n%s\n",attribute_data[attr->index].note); + value = (value & mask); + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xFF: + return sprintf(buf, "0x%02x%s", value, note); + case 0x0F: + return sprintf(buf, "0x%01x%s", value, note); + case 0xF0: + value = value >> 4; + return sprintf(buf, "0x%01x%s", value, note); + case 0xC0: + value = value >> 6; + return sprintf(buf, "0x%01x%s", value, note); + case 0x30: + value = value >> 4; + return sprintf(buf, "0x%01x%s", value, note); + default : + value = value >> dni_log2(mask); + return sprintf(buf, "%d%s", value, note); + } +} + + +static ssize_t set_gpio_reg(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + int err; + int value; + unsigned long set_data; + unsigned char set_reg; + unsigned char mask; + unsigned char mask_out; + unsigned char pca9555_num; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev = kobj_to_dev(kobj_gpio); + struct i2c_device_platform_data *pdata = i2cdev->platform_data; + + err = kstrtoul(buf, 0, &set_data); + if (err){ + return err; + } + + if (set_data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + return count; + } + + switch(attribute_data[attr->index].addr){ + case PCA9555_A: + pca9555_num = 0; + break; + case PCA9555_B: + pca9555_num = 1; + break; + case PCA9555_C: + pca9555_num = 2; + break; + default: + return sprintf(buf, "attribute address error"); + } + + set_direction(&pdata[pca9555_num], attribute_data[attr->index].reg, attribute_data[attr->index].mask); + + switch (attr->index) { + case PSU1_SMB_ALERT ... OOB_BCM54616S_INT: + set_reg = attribute_data[attr->index].reg; + mask = attribute_data[attr->index].mask; + value = i2c_smbus_read_byte_data(pdata[pca9555_num].client, set_reg); + mask_out = value & ~(mask); + break; + default: + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xFF: + set_data = mask_out | (set_data & mask); + break; + case 0x0F: + set_data = mask_out | (set_data & mask); + break; + case 0xF0: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + case 0xC0: + set_data = set_data << 6; + set_data = mask_out | (set_data & mask); + break; + case 0x30: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + default : + set_data = mask_out | (set_data << dni_log2(mask) ); + } + + i2c_smbus_write_byte_data(pdata[pca9555_num].client, set_reg, set_data); + return count; +} +static SENSOR_DEVICE_ATTR(psu1_smb_alert, S_IRUGO, get_gpio_reg, NULL, PSU1_SMB_ALERT); +static SENSOR_DEVICE_ATTR(psu2_smb_alert, S_IRUGO, get_gpio_reg, NULL, PSU2_SMB_ALERT); +static SENSOR_DEVICE_ATTR(eeprom_wp, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, EEPROM_WP); +static SENSOR_DEVICE_ATTR(fan1_led_ag, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, FAN1_LED_AG); +static SENSOR_DEVICE_ATTR(fan2_led_ag, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, FAN2_LED_AG); +static SENSOR_DEVICE_ATTR(d_fan_alert, S_IRUGO, get_gpio_reg, NULL, D_FAN_ALERT); +static SENSOR_DEVICE_ATTR(psu1_pres, S_IRUGO, get_gpio_reg, NULL, PSU1_PRES); +static SENSOR_DEVICE_ATTR(psu2_pres, S_IRUGO, get_gpio_reg, NULL, PSU2_PRES); +static SENSOR_DEVICE_ATTR(fan_eeprom_wp, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, FAN_EEPROM_WP); +static SENSOR_DEVICE_ATTR(d_fan_m_present2, S_IRUGO, get_gpio_reg, NULL, D_FAN_M_PRESENT2); +static SENSOR_DEVICE_ATTR(d_fan_m_present1, S_IRUGO, get_gpio_reg, NULL, D_FAN_M_PRESENT1); +static SENSOR_DEVICE_ATTR(psu1_pg, S_IRUGO, get_gpio_reg, NULL, PSU1_PG); +static SENSOR_DEVICE_ATTR(psu2_pg, S_IRUGO, get_gpio_reg, NULL, PSU2_PG); +static SENSOR_DEVICE_ATTR(bcm54282_int, S_IRUGO, get_gpio_reg, NULL, BCM54282_INT); + +static SENSOR_DEVICE_ATTR(sfp_mod_p1, S_IRUGO, get_gpio_reg, NULL, SFP_MOD_P1); +static SENSOR_DEVICE_ATTR(sfp_rxlos_p1, S_IRUGO, get_gpio_reg, NULL, SFP_RXLOS_P1); +static SENSOR_DEVICE_ATTR(sfp_mod_p2, S_IRUGO, get_gpio_reg, NULL, SFP_MOD_P2); +static SENSOR_DEVICE_ATTR(sfp_rxlos_p2, S_IRUGO, get_gpio_reg, NULL, SFP_RXLOS_P2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault_p1, S_IRUGO, get_gpio_reg, NULL, SFP_TX_FAULT_P1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault_p2, S_IRUGO , get_gpio_reg, NULL, SFP_TX_FAULT_P2); +static SENSOR_DEVICE_ATTR(sfp_tx_dis_p1, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, SFP_TX_DIS_P1); +static SENSOR_DEVICE_ATTR(sfp_tx_dis_p2, S_IRUGO | S_IWUSR, get_gpio_reg, set_gpio_reg, SFP_TX_DIS_P2); +static SENSOR_DEVICE_ATTR(oob_bcm54616s_int, S_IRUGO, get_gpio_reg, NULL, OOB_BCM54616S_INT); + +static struct attribute *et6248brb_psu_attrs[] = { + &sensor_dev_attr_psu1_smb_alert.dev_attr.attr, + &sensor_dev_attr_psu2_smb_alert.dev_attr.attr, + &sensor_dev_attr_psu1_pres.dev_attr.attr, + &sensor_dev_attr_psu2_pres.dev_attr.attr, + &sensor_dev_attr_psu1_pg.dev_attr.attr, + &sensor_dev_attr_psu2_pg.dev_attr.attr, + NULL, +}; + +static struct attribute *et6248brb_fan_attrs[] = { + &sensor_dev_attr_fan1_led_ag.dev_attr.attr, + &sensor_dev_attr_fan2_led_ag.dev_attr.attr, + &sensor_dev_attr_d_fan_alert.dev_attr.attr, + &sensor_dev_attr_fan_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_d_fan_m_present1.dev_attr.attr, + &sensor_dev_attr_d_fan_m_present2.dev_attr.attr, + NULL, +}; + +static struct attribute *et6248brb_sfp_attrs[] = { + &sensor_dev_attr_sfp_mod_p1.dev_attr.attr, + &sensor_dev_attr_sfp_rxlos_p1.dev_attr.attr, + &sensor_dev_attr_sfp_mod_p2.dev_attr.attr, + &sensor_dev_attr_sfp_rxlos_p2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault_p1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault_p2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_dis_p1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_dis_p2.dev_attr.attr, + NULL, +}; + +static struct attribute *et6248brb_others_attrs[] = { + &sensor_dev_attr_eeprom_wp.dev_attr.attr, + &sensor_dev_attr_bcm54282_int.dev_attr.attr, + &sensor_dev_attr_oob_bcm54616s_int.dev_attr.attr, + NULL, +}; + +static struct attribute_group et6248brb_psu_attr_grp = { + .attrs = et6248brb_psu_attrs, +}; + +static struct attribute_group et6248brb_fan_attr_grp = { + .attrs = et6248brb_fan_attrs, + +}; +static struct attribute_group et6248brb_sfp_attr_grp = { + .attrs = et6248brb_sfp_attrs, +}; + +static struct attribute_group et6248brb_others_attr_grp = { + .attrs = et6248brb_others_attrs, +}; +/*---------------- gpio device - end ------------- */ + +/*---------------- gpio driver - start ----------- */ +static int __init gpio_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + if(pdata->info.addr == PCA9555_A){ + kobj_gpio = &pdev->dev.kobj; + kobj_psu = kobject_create_and_add("PSU", &pdev->dev.kobj); + if (!kobj_psu){ + printk(KERN_WARNING "Fail to create 'PSU' directory"); + goto error; + } + + kobj_fan = kobject_create_and_add("FAN", &pdev->dev.kobj); + if (!kobj_fan){ + printk(KERN_WARNING "Fail to create 'FAN' directory"); + goto error; + } + + kobj_sfp = kobject_create_and_add("SFP", &pdev->dev.kobj); + if (!kobj_sfp){ + printk(KERN_WARNING "Fail to create 'SFP' directory"); + goto error; + } + kobj_others = kobject_create_and_add("Others", &pdev->dev.kobj); + if (!kobj_others){ + printk(KERN_WARNING "Fail to create 'Others' directory"); + goto error; + } + ret = sysfs_create_group(kobj_psu, &et6248brb_psu_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create 'psu' attribute group"); + goto error; + } + ret = sysfs_create_group(kobj_fan, &et6248brb_fan_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create 'fan' attribute group"); + goto error; + } + ret = sysfs_create_group(kobj_sfp, &et6248brb_sfp_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create 'sfp' attribute group"); + goto error; + } + ret = sysfs_create_group(kobj_others, &et6248brb_others_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create 'others' attribute group"); + goto error; + } + } + return 0; + +error: + kobject_put(kobj_gpio); + kobject_put(kobj_psu); + kobject_put(kobj_fan); + kobject_put(kobj_sfp); + kobject_put(kobj_others); + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit gpio_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else if(pdata->info.addr == PCA9555_A){ + sysfs_remove_group(kobj_gpio, &et6248brb_psu_attr_grp); + sysfs_remove_group(kobj_fan, &et6248brb_fan_attr_grp); + sysfs_remove_group(kobj_sfp, &et6248brb_sfp_attr_grp); + sysfs_remove_group(kobj_others, &et6248brb_others_attr_grp); + kobject_put(kobj_gpio); + kobject_put(kobj_fan); + kobject_put(kobj_psu); + kobject_put(kobj_sfp); + kobject_put(kobj_others); + } + + if (pdata->client) { + if (!parent) { + parent = (pdata->client)->adapter; + } + i2c_unregister_device(pdata->client); + } + + i2c_put_adapter(parent); + return 0; +} + +static struct platform_driver gpio_device_driver = { + .probe = gpio_device_probe, + .remove = __exit_p(gpio_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-et6248brb-gpio", + } +}; +/*---------------- gpio driver - end ------------- */ + +/*---------------- module initialization ------------- */ +static int __init delta_et6248brb_platform_init(void) +{ + struct i2c_adapter *adapter; + + int ret, i = 0, j = 0; + printk("et6248brb_platform module initialization\n"); + + //Use pca9547 in i2c_mux_pca954x.c + adapter = i2c_get_adapter(BUS1); + i2c_client_9547 = i2c_new_device(adapter, &i2c_info_pca9547[0]); + i2c_put_adapter(adapter); + + // register the i2c devices + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + // register the i2c devices + ret = platform_driver_register(&gpio_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_gpio_device_driver; + } + + for (i = 0; i < ARRAY_SIZE(et6248brb_i2c_device); i++) + { + ret = platform_device_register(&et6248brb_i2c_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_et6248brb_i2c_device; + } + } + + for (j = 0; j < ARRAY_SIZE(et6248brb_gpio_device); j++) + { + ret = platform_device_register(&et6248brb_gpio_device[j]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", j); + goto error_et6248brb_gpio_device; + } + } + + return 0; +error_et6248brb_gpio_device: + j--; + for (; j >= 0; j--) { + platform_device_unregister(&et6248brb_gpio_device[j]); + } +error_et6248brb_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&et6248brb_i2c_device[i]); + } + platform_driver_unregister(&gpio_device_driver); +error_gpio_device_driver: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + return ret; +} + +static void __exit delta_et6248brb_platform_exit(void) +{ + int i = 0; + + for ( i = 0; i < ARRAY_SIZE(et6248brb_i2c_device); i++ ) { + platform_device_unregister(&et6248brb_i2c_device[i]); + } + + for ( i = 0; i < ARRAY_SIZE(et6248brb_gpio_device); i++ ) { + platform_device_unregister(&et6248brb_gpio_device[i]); + } + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&gpio_device_driver); + i2c_unregister_device(i2c_client_9547); +} + +module_init(delta_et6248brb_platform_init); +module_exit(delta_et6248brb_platform_exit); + +MODULE_DESCRIPTION("DNI et6248brb Platform Support"); +MODULE_AUTHOR("Jacky Liu "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/dni_gpio.c b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/dni_gpio.c new file mode 100644 index 000000000000..127cf6af13ab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/modules/dni_gpio.c @@ -0,0 +1,697 @@ +/* + * Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver + * + * Copyright (C) 2010 Extreme Engineering Solutions. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +#include +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +#include +#include +#include +#include +#include + +#define DRV_NAME "gpio_ich" + +/* + * GPIO register offsets in GPIO I/O space. + * Each chunk of 32 GPIOs is manipulated via its own USE_SELx, IO_SELx, and + * LVLx registers. Logic in the read/write functions takes a register and + * an absolute bit number and determines the proper register offset and bit + * number in that register. For example, to read the value of GPIO bit 50 + * the code would access offset ichx_regs[2(=GPIO_LVL)][1(=50/32)], + * bit 18 (50%32). + */ +enum GPIO_REG { + GPIO_USE_SEL = 0, + GPIO_IO_SEL, + GPIO_LVL, + GPO_BLINK +}; + +static const u8 ichx_regs[4][3] = { + {0x00, 0x30, 0x40}, /* USE_SEL[1-3] offsets */ + {0x04, 0x34, 0x44}, /* IO_SEL[1-3] offsets */ + {0x0c, 0x38, 0x48}, /* LVL[1-3] offsets */ + {0x18, 0x18, 0x18}, /* BLINK offset */ +}; + +static const u8 ichx_reglen[3] = { + 0x30, 0x10, 0x10, +}; + +static const u8 avoton_regs[4][3] = { + {0x00, 0x80, 0x00}, + {0x04, 0x84, 0x00}, + {0x08, 0x88, 0x00}, +}; + +static const u8 avoton_reglen[3] = { + 0x10, 0x10, 0x00, +}; + +#define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start) +#define ICHX_READ(reg, base_res) inl((reg) + (base_res)->start) + +struct ichx_desc { + /* Max GPIO pins the chipset can have */ + uint ngpio; + + /* chipset registers */ + const u8 (*regs)[3]; + const u8 *reglen; + + /* GPO_BLINK is available on this chipset */ + bool have_blink; + + /* Whether the chipset has GPIO in GPE0_STS in the PM IO region */ + bool uses_gpe0; + + /* USE_SEL is bogus on some chipsets, eg 3100 */ + u32 use_sel_ignore[3]; + + /* Some chipsets have quirks, let these use their own request/get */ + int (*request)(struct gpio_chip *chip, unsigned offset); + int (*get)(struct gpio_chip *chip, unsigned offset); + + /* + * Some chipsets don't let reading output values on GPIO_LVL register + * this option allows driver caching written output values + */ + bool use_outlvl_cache; +}; + +static struct { + spinlock_t lock; + struct platform_device *dev; + struct gpio_chip chip; + struct resource *gpio_base; /* GPIO IO base */ + struct resource *pm_base; /* Power Mangagment IO base */ + struct ichx_desc *desc; /* Pointer to chipset-specific description */ + u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */ + u8 use_gpio; /* Which GPIO groups are usable */ + int outlvl_cache[3]; /* cached output values */ +} ichx_priv; + +static int modparam_gpiobase = -1; /* dynamic */ +module_param_named(gpiobase, modparam_gpiobase, int, 0444); +MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, " + "which is the default."); + +static int ichx_write_bit(int reg, unsigned nr, int val, int verify) +{ + unsigned long flags; + u32 data, tmp; + int reg_nr = nr / 32; + int bit = nr & 0x1f; + int ret = 0; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + { + data = ichx_priv.outlvl_cache[reg_nr]; + } + else + { + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + } + if (val) + data |= 1 << bit; + else + data &= ~(1 << bit); + + ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + ichx_priv.outlvl_cache[reg_nr] = data; + + tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + if (verify && data != tmp) + ret = -EPERM; + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return ret; +} + +static int ichx_read_bit(int reg, unsigned nr) +{ + unsigned long flags; + u32 data; + int reg_nr = nr / 32; + int bit = nr & 0x1f; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + data = ichx_priv.outlvl_cache[reg_nr] | data; + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return data & (1 << bit) ? 1 : 0; +} + +static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) +{ + return !!(ichx_priv.use_gpio & (1 << (nr / 32))); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr) +{ + return ichx_read_bit(GPIO_IO_SEL, nr) ? GPIOF_DIR_IN : GPIOF_DIR_OUT; +} +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) +{ + /* + * Try setting pin as an input and verify it worked since many pins + * are output-only. + */ + if (ichx_write_bit(GPIO_IO_SEL, nr, 1, 1)) + return -EINVAL; + + return 0; +} + +static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, + int val) +{ + /* Disable blink hardware which is available for GPIOs from 0 to 31. */ + if (nr < 32 && ichx_priv.desc->have_blink) + ichx_write_bit(GPO_BLINK, nr, 0, 0); + + /* Set GPIO output value. */ + ichx_write_bit(GPIO_LVL, nr, val, 0); + + /* + * Try setting pin as an output and verify it worked since many pins + * are input-only. + */ + if (ichx_write_bit(GPIO_IO_SEL, nr, 0, 1)) + return -EINVAL; + + return 0; +} + +static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + return ichx_read_bit(GPIO_LVL, nr); +} + +static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + unsigned long flags; + u32 data; + + /* + * GPI 0 - 15 need to be read from the power management registers on + * a ICH6/3100 bridge. + */ + if (nr < 16) { + if (!ichx_priv.pm_base) + return -ENXIO; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + /* GPI 0 - 15 are latched, write 1 to clear*/ + ICHX_WRITE(1 << (16 + nr), 0, ichx_priv.pm_base); + data = ICHX_READ(0, ichx_priv.pm_base); + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return (data >> 16) & (1 << nr) ? 1 : 0; + } else { + return ichx_gpio_get(chip, nr); + } +} + +static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr) +{ + if (!ichx_gpio_check_available(chip, nr)) + return -ENXIO; + + /* + * Note we assume the BIOS properly set a bridge's USE value. Some + * chips (eg Intel 3100) have bogus USE values though, so first see if + * the chipset's USE value can be trusted for this specific bit. + * If it can't be trusted, assume that the pin can be used as a GPIO. + */ + if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f))) + return 0; + + return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV; +} + +static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr) +{ + /* + * Fixups for bits 16 and 17 are necessary on the Intel ICH6/3100 + * bridge as they are controlled by USE register bits 0 and 1. See + * "Table 704 GPIO_USE_SEL1 register" in the i3100 datasheet for + * additional info. + */ + if (nr == 16 || nr == 17) + nr -= 16; + + return ichx_gpio_request(chip, nr); +} + +static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val) +{ + ichx_write_bit(GPIO_LVL, nr, val, 0); +} + +static void ichx_gpiolib_setup(struct gpio_chip *chip) +{ + chip->owner = THIS_MODULE; + chip->label = DRV_NAME; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + chip->dev = &ichx_priv.dev->dev; +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) + chip->parent = &ichx_priv.dev->dev; + chip->get_direction = ichx_gpio_get_direction; +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + + /* Allow chip-specific overrides of request()/get() */ + chip->request = ichx_priv.desc->request ? + ichx_priv.desc->request : ichx_gpio_request; + chip->get = ichx_priv.desc->get ? + ichx_priv.desc->get : ichx_gpio_get; + + chip->set = ichx_gpio_set; + chip->direction_input = ichx_gpio_direction_input; + chip->direction_output = ichx_gpio_direction_output; + chip->base = modparam_gpiobase; + chip->ngpio = ichx_priv.desc->ngpio; + chip->can_sleep = false; + chip->dbg_show = NULL; +} + +/* ICH6-based, 631xesb-based */ +static struct ichx_desc ich6_desc = { + /* Bridges using the ICH6 controller need fixups for GPIO 0 - 17 */ + .request = ich6_gpio_request, + .get = ich6_gpio_get, + + /* GPIO 0-15 are read in the GPE0_STS PM register */ + .uses_gpe0 = true, + + .ngpio = 50, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Intel 3100 */ +static struct ichx_desc i3100_desc = { + /* + * Bits 16,17, 20 of USE_SEL and bit 16 of USE_SEL2 always read 0 on + * the Intel 3100. See "Table 712. GPIO Summary Table" of 3100 + * Datasheet for more info. + */ + .use_sel_ignore = {0x00130000, 0x00010000, 0x0}, + + /* The 3100 needs fixups for GPIO 0 - 17 */ + .request = ich6_gpio_request, + .get = ich6_gpio_get, + + /* GPIO 0-15 are read in the GPE0_STS PM register */ + .uses_gpe0 = true, + + .ngpio = 50, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH7 and ICH8-based */ +static struct ichx_desc ich7_desc = { + .ngpio = 50, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH9-based */ +static struct ichx_desc ich9_desc = { + .ngpio = 61, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH10-based - Consumer/corporate versions have different amount of GPIO */ +static struct ichx_desc ich10_cons_desc = { + .ngpio = 61, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; +static struct ichx_desc ich10_corp_desc = { + .ngpio = 72, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Intel 5 series, 6 series, 3400 series, and C200 series */ +static struct ichx_desc intel5_desc = { + .ngpio = 76, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Avoton */ +static struct ichx_desc avoton_desc = { + /* Avoton has only 59 GPIOs, but we assume the first set of register + * (Core) has 32 instead of 31 to keep gpio-ich compliance + */ + .ngpio = 60, + .regs = avoton_regs, + .reglen = avoton_reglen, + .use_outlvl_cache = true, +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static int ichx_gpio_request_regions(struct resource *res_base, + const char *name, u8 use_gpio) +{ + int i; + + if (!res_base || !res_base->start || !res_base->end) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { + if (!(use_gpio & (1 << i))) + continue; + if (!request_region( + res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i], name)) + goto request_err; + } + return 0; + +request_err: + /* Clean up: release already requested regions, if any */ + for (i--; i >= 0; i--) { + if (!(use_gpio & (1 << i))) + continue; + release_region(res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i]); + } + return -EBUSY; +} + +static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { + if (!(use_gpio & (1 << i))) + continue; + release_region(res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i]); + } +} + +static int ichx_gpio_probe(struct platform_device *pdev) +{ + struct resource *res_base, *res_pm; + int err; + struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev); + + if (!ich_info) + return -ENODEV; + + ichx_priv.dev = pdev; + + switch (ich_info->gpio_version) { + case ICH_I3100_GPIO: + ichx_priv.desc = &i3100_desc; + break; + case ICH_V5_GPIO: + ichx_priv.desc = &intel5_desc; + break; + case ICH_V6_GPIO: + ichx_priv.desc = &ich6_desc; + break; + case ICH_V7_GPIO: + ichx_priv.desc = &ich7_desc; + break; + case ICH_V9_GPIO: + ichx_priv.desc = &ich9_desc; + break; + case ICH_V10CORP_GPIO: + ichx_priv.desc = &ich10_corp_desc; + break; + case ICH_V10CONS_GPIO: + ichx_priv.desc = &ich10_cons_desc; + break; + case AVOTON_GPIO: + ichx_priv.desc = &avoton_desc; + ichx_priv.outlvl_cache[0] = 0x06; /*core output values*/ + ichx_priv.outlvl_cache[1] = 0x7c0008; /*sus output values*/ + ichx_priv.outlvl_cache[2] = 0x0; /*no used*/ + + break; + default: + return -ENODEV; + } + + spin_lock_init(&ichx_priv.lock); + res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); + ichx_priv.use_gpio = ich_info->use_gpio; + err = ichx_gpio_request_regions(res_base, pdev->name, + ichx_priv.use_gpio); + if (err) + return err; + + ichx_priv.gpio_base = res_base; + + /* + * If necessary, determine the I/O address of ACPI/power management + * registers which are needed to read the the GPE0 register for GPI pins + * 0 - 15 on some chipsets. + */ + if (!ichx_priv.desc->uses_gpe0) + goto init; + + res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0); + if (!res_pm) { + pr_warn("ACPI BAR is unavailable, GPI 0 - 15 unavailable\n"); + goto init; + } + + if (!request_region(res_pm->start, resource_size(res_pm), + pdev->name)) { + pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n"); + goto init; + } + + ichx_priv.pm_base = res_pm; + +init: + ichx_gpiolib_setup(&ichx_priv.chip); + err = gpiochip_add(&ichx_priv.chip); + if (err) { + pr_err("Failed to register GPIOs\n"); + goto add_err; + } + + pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base, + ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME); + + return 0; + +add_err: + ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio); + if (ichx_priv.pm_base) + release_region(ichx_priv.pm_base->start, + resource_size(ichx_priv.pm_base)); + return err; +} + +static int ichx_gpio_remove(struct platform_device *pdev) +{ + int err; + + err = gpiochip_remove(&ichx_priv.chip); + if (err) { + dev_err(&pdev->dev, "%s failed, %d\n", + "gpiochip_remove()", err); + return err; + } + + ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio); + if (ichx_priv.pm_base) + release_region(ichx_priv.pm_base->start, + resource_size(ichx_priv.pm_base)); + + return 0; +} + +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +static int ichx_gpio_request_regions(struct device *dev, + struct resource *res_base, const char *name, u8 use_gpio) +{ + int i; + + if (!res_base || !res_base->start || !res_base->end) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { + if (!(use_gpio & (1 << i))) + continue; + if (!devm_request_region(dev, + res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i], name)) + return -EBUSY; + } + return 0; +} + +static int ichx_gpio_probe(struct platform_device *pdev) +{ + struct resource *res_base, *res_pm; + int err; + struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev); + + if (!ich_info) + return -ENODEV; + + ichx_priv.dev = pdev; + + switch (ich_info->gpio_version) { + case ICH_I3100_GPIO: + ichx_priv.desc = &i3100_desc; + break; + case ICH_V5_GPIO: + ichx_priv.desc = &intel5_desc; + break; + case ICH_V6_GPIO: + ichx_priv.desc = &ich6_desc; + break; + case ICH_V7_GPIO: + ichx_priv.desc = &ich7_desc; + break; + case ICH_V9_GPIO: + ichx_priv.desc = &ich9_desc; + break; + case ICH_V10CORP_GPIO: + ichx_priv.desc = &ich10_corp_desc; + break; + case ICH_V10CONS_GPIO: + ichx_priv.desc = &ich10_cons_desc; + break; + case AVOTON_GPIO: + ichx_priv.desc = &avoton_desc; + ichx_priv.outlvl_cache[0] = 0x06; /*core output values*/ + ichx_priv.outlvl_cache[1] = 0x7c0008; /*sus output values*/ + ichx_priv.outlvl_cache[2] = 0x0; /*no used*/ + break; + default: + return -ENODEV; + } + + spin_lock_init(&ichx_priv.lock); + res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); + ichx_priv.use_gpio = ich_info->use_gpio; + err = ichx_gpio_request_regions(&pdev->dev, res_base, pdev->name, + ichx_priv.use_gpio); + if (err) + return err; + + ichx_priv.gpio_base = res_base; + + /* + * If necessary, determine the I/O address of ACPI/power management + * registers which are needed to read the the GPE0 register for GPI pins + * 0 - 15 on some chipsets. + */ + if (!ichx_priv.desc->uses_gpe0) + goto init; + + res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0); + if (!res_pm) { + pr_warn("ACPI BAR is unavailable, GPI 0 - 15 unavailable\n"); + goto init; + } + + if (!devm_request_region(&pdev->dev, res_pm->start, + resource_size(res_pm), pdev->name)) { + pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n"); + goto init; + } + + ichx_priv.pm_base = res_pm; + +init: + ichx_gpiolib_setup(&ichx_priv.chip); + err = gpiochip_add_data(&ichx_priv.chip, NULL); + if (err) { + pr_err("Failed to register GPIOs\n"); + return err; + } + + pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base, + ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME); + + return 0; +} + +static int ichx_gpio_remove(struct platform_device *pdev) +{ + gpiochip_remove(&ichx_priv.chip); + + return 0; +} +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + +static struct platform_driver ichx_gpio_driver = { + .driver = { +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + .owner = THIS_MODULE, +#else // #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +#endif // #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) + .name = DRV_NAME, + }, + .probe = ichx_gpio_probe, + .remove = ichx_gpio_remove, +}; + +module_platform_driver(ichx_gpio_driver); + +MODULE_AUTHOR("Johnson Lu "); +MODULE_DESCRIPTION("GPIO interface for Intel ICH series"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/et-6248brb_platform_init.sh b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/et-6248brb_platform_init.sh new file mode 100755 index 000000000000..3779e4684d84 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/et-6248brb_platform_init.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +#platform init script for Delta et-6248brb + +#fan speed monitol start +/usr/share/sonic/device/x86_64-delta_et-6248brb-r0/fancontrol.service /usr/share/sonic/device/x86_64-delta_et-6248brb-r0/fancontrol & +sh /usr/local/bin/led_status.sh & + + +exit 0 + 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 new file mode 100644 index 000000000000..573af2156661 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/et-6248brb/scripts/led_status.sh @@ -0,0 +1,165 @@ +#!/bin/bash + +FAN1_EEPROM="-y 0 0x55 0x0a" +FAN2_EEPROM="-y 0 0x56 0x0a" +FAN1_RPM="/sys/bus/i2c/devices/0-002e/fan1_input" +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-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" + PWR_LED_R="/sys/class/gpio/gpio489/value" + FAN_LED_G="/sys/class/gpio/gpio485/value" + FAN_LED_R="/sys/class/gpio/gpio494/value" +else + SYS_LED_G="/sys/class/gpio/gpio197/value" + SYS_LED_R="/sys/class/gpio/gpio198/value" + PWR_LED_G="/sys/class/gpio/gpio199/value" + PWR_LED_R="/sys/class/gpio/gpio233/value" + FAN_LED_G="/sys/class/gpio/gpio229/value" + FAN_LED_R="/sys/class/gpio/gpio238/value" +fi + +PSU1_EEPROM="-y 2 0x50 0x00" +PSU2_EEPROM="-y 3 0x51 0x00" +PSU1_PG="/sys/devices/platform/delta-et6248brb-gpio.0/PSU/psu1_pg" +PSU2_PG="/sys/devices/platform/delta-et6248brb-gpio.0/PSU/psu2_pg" + +catfaneeprom(){ + fan_eeprom_num=0 + i2cget $FAN1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -ne "0" ]; then + fan_eeprom_num=$((fan_eeprom_num)) + fi + + i2cget $FAN2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + fan_eeprom_num=$((fan_eeprom_num+1)) + elif [ "`echo $?`" -ne "0" ]; then + fan_eeprom_num=$((fan_eeprom_num_num)) + fi +} + +catfanspeed(){ + + fan_rpm_normal_num=0 + fan1_rpm_normal_num=0 + fan1_rpm=`cat $FAN1_RPM` + + if [ "${fan1_rpm}" -ne "960" ] && [ "${fan1_rpm}" -ne "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num+1)) + elif [ "${fan1_rpm}" -eq "960" ] || [ "${fan1_rpm}" -eq "0" ]; then + fan1_rpm_normal_num=$((fan1_rpm_normal_num)) + fi + + fan2_rpm_normal_num=0 + fan2_rpm=`cat $FAN2_RPM` + + if [ "${fan2_rpm}" -ne "960" ] && [ "${fan2_rpm}" -ne "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num+1)) + elif [ "${fan2_rpm}" -eq "960" ] || [ "${fan2_rpm}" -eq "0" ]; then + fan2_rpm_normal_num=$((fan2_rpm_normal_num)) + fi + + fan_rpm_normal_num=$((fan1_rpm_normal_num+fan2_rpm_normal_num)) +} + +setfanled(){ + if [ "${fan_eeprom_num}" -eq "2" ] && [ "${fan_rpm_normal_num}" -eq "2" ]; then + echo "1" > $FAN_LED_G + echo "0" > $FAN_LED_R + elif [ "${fan_eeprom_num}" -lt "2" ] || [ "${fan_rpm_normal_num}" -lt "2" ]; then + echo "1" > $FAN_LED_R + echo "0" > $FAN_LED_G + fi +} + +setfantrayled(){ + if [ "${fan1_rpm_normal_num}" -eq "1" ]; then + echo "0x02" > $FAN_TRAY1_LED + else + echo "0x01" > $FAN_TRAY1_LED + fi + + if [ "${fan2_rpm_normal_num}" -eq "1" ]; then + echo "0x02" > $FAN_TRAY2_LED + else + echo "0x01" > $FAN_TRAY2_LED + fi +} + +catpsueeprom(){ + psu_eeprom_num=0 + i2cget $PSU1_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu_eeprom_num=$((psu_eeprom_num+1)) + elif [ "`echo $?`" -ne "0" ]; then + psu_eeprom_num=$((psu_eeprom_num)) + fi + + i2cget $PSU2_EEPROM > /dev/null 2>&1 + if [ "`echo $?`" -eq "0" ]; then + psu_eeprom_num=$((psu_eeprom_num+1)) + elif [ "`echo $?`" -ne "0" ]; then + psu_eeprom_num=$((psu_eeprom_num)) + fi +} + +catpsupowergood(){ + + psu_normal_num=0 + psu1_normal_num=0 + psu1_good=`cat $PSU1_PG | head -n 1` + + if [ "${psu1_good}" -eq "1" ]; then + psu1_normal_num=$((psu1_normal_num+1)) + elif [ "${psu1_good}" -eq "0" ]; then + psu1_normal_num=$((psu1_normal_num)) + fi + + psu2_normal_num=0 + psu2_good=`cat $PSU2_PG | head -n 1` + + if [ "${psu2_good}" -eq "1" ]; then + psu2_normal_num=$((psu2_normal_num+1)) + elif [ "${psu2_good}" -eq "0" ]; then + psu2_normal_num=$((psu2_normal_num)) + fi + + psu_normal_num=$((psu1_normal_num+psu2_normal_num)) +} + +setpsuled(){ + if [ "${psu_eeprom_num}" -eq "2" ] && [ "${psu_normal_num}" -eq "2" ]; then + echo "1" > $PWR_LED_G + echo "0" > $PWR_LED_R + elif [ "${psu_eeprom_num}" -lt "2" ] || [ "${psu_normal_num}" -lt "2" ]; then + echo "1" > $PWR_LED_R + echo "0" > $PWR_LED_G + fi +} + +platformstatus(){ + echo "1" > $SYS_LED_G + echo "0" > $SYS_LED_R + catfaneeprom + catfanspeed + setfanled + setfantrayled + + catpsueeprom + catpsupowergood + setpsuled +} + +while true +do + platformstatus + sleep 1 +done + diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag5648.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag5648.service new file mode 100644 index 000000000000..7a74c0155473 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag5648.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta ag5648 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-ag5648 start +ExecStop=-/etc/init.d/platform-modules-ag5648 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v1.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v1.service new file mode 100644 index 000000000000..bfa0fd296f59 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v1.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta ag9032v1 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-ag9032v1 start +ExecStop=-/etc/init.d/platform-modules-ag9032v1 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v2a.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v2a.service new file mode 100644 index 000000000000..0012dbfcbde2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9032v2a.service @@ -0,0 +1,14 @@ +[Unit] +Description=Delta ag9032v2a Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-ag9032v2a start +ExecStop=-/etc/init.d/platform-modules-ag9032v2a stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target + diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9064.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9064.service new file mode 100644 index 000000000000..80f6836bfdbc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-ag9064.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta ag9064 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-ag9064 start +ExecStop=-/etc/init.d/platform-modules-ag9064 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-agc032.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-agc032.service new file mode 100644 index 000000000000..b84b6fba0aeb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-agc032.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta agc032 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-agc032 start +ExecStop=-/etc/init.d/platform-modules-agc032 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-et-6248brb.service b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-et-6248brb.service new file mode 100644 index 000000000000..901bcffaea8e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-delta/systemd/platform-modules-et-6248brb.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta et-6248brb Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-et-6248brb start +ExecStop=-/etc/init.d/platform-modules-et-6248brb stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/.gitignore b/platform/broadcom/sonic-platform-modules-ingrasys/.gitignore new file mode 100644 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/LICENSE b/platform/broadcom/sonic-platform-modules-ingrasys/LICENSE new file mode 100644 index 000000000000..9cecc1d4669e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/changelog b/platform/broadcom/sonic-platform-modules-ingrasys/debian/changelog new file mode 100644 index 000000000000..338234f97c45 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/changelog @@ -0,0 +1,22 @@ +platform-driver (1.1.0) unstable; urgency=low + + * Add support for s9200-64x + + -- developer Fri, 26 May 2017 11:00:00 +0800 + +platform-driver (1.1.0) unstable; urgency=low + + * Add support for s8810-32q + + -- developer Fri, 26 May 2017 11:00:00 +0800 +platform-driver (1.1.0) unstable; urgency=low + + * Add support for s8900 series + + -- developer Wed, 29 Mar 2017 11:00:00 +0800 + +platform-driver (1.0.0) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- developer Wed, 05 Oct 2016 16:30:45 +0800 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/compat b/platform/broadcom/sonic-platform-modules-ingrasys/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/control b/platform/broadcom/sonic-platform-modules-ingrasys/debian/control new file mode 100644 index 000000000000..99c87f772ed5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/control @@ -0,0 +1,26 @@ +Source: platform-driver +Section: unknown +Priority: optional +Maintainer: Wade He +Build-Depends: debhelper (>= 9), dh-systemd +Standards-Version: 1.0.0 + +Package: sonic-platform-ingrasys-s9100 +Architecture: amd64 +Description: This package contains S9100 platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s8900-64xc +Architecture: amd64 +Description: This package contains S8900-64XC platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s8900-54xc +Architecture: amd64 +Description: This package contains S8900-54XC platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s8810-32q +Architecture: amd64 +Description: This package contains S8810-32Q platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s9200-64x +Architecture: amd64 +Description: This package contains S9200-64X platform driver utility for SONiC project. diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/rules b/platform/broadcom/sonic-platform-modules-ingrasys/debian/rules new file mode 100755 index 000000000000..759d26c5c4d1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/rules @@ -0,0 +1,42 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_PRE_NAME := sonic-platform-ingrasys +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= s9100 s8900-64xc s8900-54xc s8810-32q s9200-64x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CONF_DIR := conf + +%: + dh $@ --with systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/sbin; \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.sh \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/sbin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + done) + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8810-32q.init b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8810-32q.init new file mode 100644 index 000000000000..19f51c0a9666 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8810-32q.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S8810-32Q board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s8810-32q.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-54xc.init b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-54xc.init new file mode 100644 index 000000000000..f2e4932b3294 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-54xc.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S8900-54XC board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s8900-54xc.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-64xc.init b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-64xc.init new file mode 100644 index 000000000000..2790ca3517c6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s8900-64xc.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S8900-64XC board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s8900-64xc.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9100.init b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9100.init new file mode 100644 index 000000000000..017708708786 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9100.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9100 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9100.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9200-64x.init b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9200-64x.init new file mode 100644 index 000000000000..076838e1aa0d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9200-64x.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9200-64X board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9200-64x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/README.md b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/README.md new file mode 100644 index 000000000000..dec38cb33393 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/README.md @@ -0,0 +1,185 @@ +# Ingrasys S8810-32Q Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S8810-32Q is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S8810-32Q platform. + +### I2C i801 + +The I2C i801 on Ingrasys S8810-32Q can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S8810-32Q. + +### I2C iSMT + +The I2C iSMT module on S8810-32Q can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S8810-32Q. + +### I2C PCA9548 +The PCA9548 module on S8810-32Q can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S8810-32Q. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S8810-32Q platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s8810-32q package is installed on the S8810-32Q, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/Makefile b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/Makefile new file mode 100755 index 000000000000..7c782163f402 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := eeprom_mb.o +obj-m += ingrasys_s8810_32q_psu.o diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/eeprom_mb.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/eeprom_mb.c new file mode 100755 index 000000000000..2040e3cfc5db --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/eeprom_mb.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, (u8)((addr >> 8) & 0xFF), (u8)(addr & 0xFF)); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys S8810-32Q Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_platform.h b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_platform.h new file mode 100644 index 000000000000..a88755946e9a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_platform.h @@ -0,0 +1,148 @@ +#ifndef _S8810_32Q_PLATFORM_H +#define _S8810_32Q_PLATFORM_H + +#include + +// remove debug before release +#define DEBUG + +enum bus_order { + I2C_BUS_MAIN, + MUX_9548_0_CH0, + MUX_9548_0_CH1, + MUX_9548_0_CH2, + MUX_9548_0_CH3, + MUX_9548_0_CH4, + MUX_9548_0_CH5, + MUX_9548_0_CH6, + MUX_9548_0_CH7, + MUX_9548_1_CH0, + MUX_9548_1_CH1, + MUX_9548_1_CH2, + MUX_9548_1_CH3, + MUX_9548_1_CH4, + MUX_9548_1_CH5, + MUX_9548_1_CH6, + MUX_9548_1_CH7, + MUX_9546_0_CH0, + MUX_9546_0_CH1, + MUX_9546_0_CH2, + MUX_9546_0_CH3, + MUX_9546_1_CH0, + MUX_9546_1_CH1, + MUX_9546_1_CH2, + MUX_9546_1_CH3, + MUX_9548_2_CH0, + MUX_9548_2_CH1, + MUX_9548_2_CH2, + MUX_9548_2_CH3, + MUX_9548_2_CH4, + MUX_9548_2_CH5, + MUX_9548_2_CH6, + MUX_9548_2_CH7, + MUX_9548_3_CH0, + MUX_9548_3_CH1, + MUX_9548_3_CH2, + MUX_9548_3_CH3, + MUX_9548_3_CH4, + MUX_9548_3_CH5, + MUX_9548_3_CH6, + MUX_9548_3_CH7, + MUX_9548_4_CH0, + MUX_9548_4_CH1, + MUX_9548_4_CH2, + MUX_9548_4_CH3, + MUX_9548_4_CH4, + MUX_9548_4_CH5, + MUX_9548_4_CH6, + MUX_9548_4_CH7, + MUX_9548_5_CH0, + MUX_9548_5_CH1, + MUX_9548_5_CH2, + MUX_9548_5_CH3, + MUX_9548_5_CH4, + MUX_9548_5_CH5, + MUX_9548_5_CH6, + MUX_9548_5_CH7, + MUX_9548_6_CH0, + MUX_9548_6_CH1, + MUX_9548_6_CH2, + MUX_9548_6_CH3, + MUX_9548_6_CH4, + MUX_9548_6_CH5, + MUX_9548_6_CH6, + MUX_9548_6_CH7, + MUX_9548_7_CH0, + MUX_9548_7_CH1, + MUX_9548_7_CH2, + MUX_9548_7_CH3, + MUX_9548_7_CH4, + MUX_9548_7_CH5, + MUX_9548_7_CH6, + MUX_9548_7_CH7, + MUX_9548_8_CH0, + MUX_9548_8_CH1, + MUX_9548_8_CH2, + MUX_9548_8_CH3, + MUX_9548_8_CH4, + MUX_9548_8_CH5, + MUX_9548_8_CH6, + MUX_9548_8_CH7, + MUX_9548_9_CH0, + MUX_9548_9_CH1, + MUX_9548_9_CH2, + MUX_9548_9_CH3, + MUX_9548_9_CH4, + MUX_9548_9_CH5, + MUX_9548_9_CH6, + MUX_9548_9_CH7, + MUX_9548_10_CH0, + MUX_9548_10_CH1, + MUX_9548_10_CH2, + MUX_9548_10_CH3, + MUX_9548_10_CH4, + MUX_9548_10_CH5, + MUX_9548_10_CH6, + MUX_9548_10_CH7, +}; + +#define I2C_ADDR_MUX_9555_0 (0x20) +#define I2C_ADDR_MUX_9555_1 (0x24) +#define I2C_ADDR_MUX_9555_2 (0x25) +#define I2C_ADDR_MUX_9555_3 (0x26) +#define I2C_ADDR_MUX_9539_0 (0x76) +#define I2C_ADDR_MUX_9539_1 (0x76) +#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN) +#define I2C_BUS_SYS_LED (MUX_9548_1_CH1) + +#define NUM_OF_I2C_MUX (11) +#define NUM_OF_CPLD (5) +#define NUM_OF_QSFP_PORT (64) +#define NUM_OF_SFP_PORT (2) +#define QSFP_EEPROM_I2C_ADDR (0x50) + +enum gpio_reg { + REG_PORT0_IN, + REG_PORT1_IN, + REG_PORT0_OUT, + REG_PORT1_OUT, + REG_PORT0_POL, + REG_PORT1_POL, + REG_PORT0_DIR, + REG_PORT1_DIR, +}; + +struct ing_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +struct i2c_init_data { + __u16 ch; + __u16 addr; + __u8 reg; + __u8 value; +}; + +#endif diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_psu.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_psu.c new file mode 100644 index 000000000000..ae34c8eb33ed --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/modules/ingrasys_s8810_32q_psu.c @@ -0,0 +1,393 @@ +/* + * S8810-32Q PSU driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s8810_32q_platform.h" + +static ssize_t show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf); +static struct s8810_psu_data *s8810_psu_update_status(struct device *dev); +static struct s8810_psu_data *s8810_psu_update_eeprom(struct device *dev); +static int s8810_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len); + + +#define DRIVER_NAME "psu" + +// Addresses scanned +static const unsigned short normal_i2c[] = { 0x51, I2C_CLIENT_END }; + +/* PSU EEPROM SIZE */ +#define EEPROM_SZ 256 +#define READ_EEPROM 1 +#define NREAD_EEPROM 0 + +static struct i2c_client cpld_client; + +/* CPLD Registers */ +#define REG_PSU_PG 0x02 +#define REG_PSU_PRSNT 0x03 + +/* CPLD Pins */ +#define PSU1_PRSNT_L 0 +#define PSU2_PRSNT_L 1 +#define PSU1_PWROK 3 +#define PSU2_PWROK 4 + + +/* Driver Private Data */ +struct s8810_psu_data { + struct mutex lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + char eeprom[EEPROM_SZ]; /* psu eeprom data */ + char psuABS; /* PSU absent */ + char psuPG; /* PSU power good */ +}; + +enum psu_index +{ + s8810_psu1, + s8810_psu2 +}; + +/* + * display power good attribute + */ +static ssize_t +show_psu_pg(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s8810_psu_data *data = s8810_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuPG; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + +/* + * display power absent attribute + */ +static ssize_t +show_psu_abs(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s8810_psu_data *data = s8810_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuABS; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + + +/* + * sysfs attributes for psu + */ +static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL); +static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL); +static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL); + +static struct attribute *s8810_psu_attributes[] = { + &dev_attr_psu_pg.attr, + &dev_attr_psu_abs.attr, + &dev_attr_psu_eeprom.attr, + NULL +}; + +/* + * display psu eeprom content + */ +static ssize_t +show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct s8810_psu_data *data = s8810_psu_update_eeprom(dev); + + memcpy(buf, (char *)data->eeprom, EEPROM_SZ); + return EEPROM_SZ; +} + +static const struct attribute_group s8810_psu_group = { + .attrs = s8810_psu_attributes, +}; + +/* + * check gpio expander is accessible + */ +static int +cpld_detect(struct i2c_client *client) +{ + if (i2c_smbus_read_byte_data(client, REG_PSU_PG) < 0) { + return -ENODEV; + } + + return 0; +} + +/* + * client address init + */ +static void +i2c_devices_client_address_init(struct i2c_client *client) +{ + cpld_client = *client; + cpld_client.addr = 0x33; +} + +static int +s8810_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct s8810_psu_data *data; + int status, err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct s8810_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct s8810_psu_data)); + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + i2c_devices_client_address_init(client); + + err = cpld_detect(&cpld_client); + if (err) { + dev_info(&client->dev, "cpld detect failure\n"); + return err; + } + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &s8810_psu_group); + if (status) { + goto exit_free; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &s8810_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int +s8810_psu_remove(struct i2c_client *client) +{ + struct s8810_psu_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &s8810_psu_group); + kfree(data); + + return 0; +} + + +/* + * psu eeprom read utility + */ +static int +s8810_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len) +{ + int i=0, ret=0; + int blk_max = 32; //max block read size + + /* read eeprom, 32 * 8 = 256 bytes */ + for (i=0; i < EEPROM_SZ/blk_max; i++) { + ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max, + data + (i*blk_max)); + if (ret < 0) { + return ret; + } + } + return ret; +} + +/* + * update eeprom content + */ +static struct s8810_psu_data +*s8810_psu_update_eeprom(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s8810_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + char psu_pg = 0; + char psu_prsnt = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->last_updated + 300 * HZ) + || !data->valid) { + + /* Read psu status */ + + psu_pg = i2c_smbus_read_byte_data(&(cpld_client), REG_PSU_PG); + psu_prsnt = i2c_smbus_read_byte_data(&(cpld_client), REG_PSU_PRSNT); + + /*read psu status from io expander*/ + + if (data->index == s8810_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (psu_pg >> psu_pwrok) & 0x1; + data->psuABS = (psu_prsnt >> psu_prsnt_l) & 0x1; + + /* Read eeprom */ + if (!data->psuABS) { + //clear local eeprom data + memset(data->eeprom, 0, EEPROM_SZ); + + //read eeprom + status = s8810_psu_read_block(client, 0, data->eeprom, + ARRAY_SIZE(data->eeprom)); + + if (status < 0) { + memset(data->eeprom, 0, EEPROM_SZ); + dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status); + } else { + data->valid = 1; + } + } else { + memset(data->eeprom, 0, EEPROM_SZ); + } + data->last_updated = jiffies; + } + + mutex_unlock(&data->lock); + + return data; +} + +/* + * update psu status + */ +static struct s8810_psu_data +*s8810_psu_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s8810_psu_data *data = i2c_get_clientdata(client); + char psu_pg = 0; + char psu_prsnt = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + /* Read psu status */ + + psu_pg = i2c_smbus_read_byte_data(&(cpld_client), REG_PSU_PG); + psu_prsnt = i2c_smbus_read_byte_data(&(cpld_client), REG_PSU_PRSNT); + + /*read psu status from io expander*/ + + if (data->index == s8810_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (psu_pg >> psu_pwrok) & 0x1; + data->psuABS = (psu_prsnt >> psu_prsnt_l) & 0x1; + + mutex_unlock(&data->lock); + + return data; +} + +static const struct i2c_device_id s8810_psu_id[] = { + { "psu1", s8810_psu1 }, + { "psu2", s8810_psu2 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, s8810_psu_id); + +static struct i2c_driver s8810_psu_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = s8810_psu_probe, + .remove = s8810_psu_remove, + .id_table = s8810_psu_id, + .address_list = normal_i2c, +}; + +static int __init s8810_psu_init(void) +{ + return i2c_add_driver(&s8810_psu_driver); +} + +static void __exit s8810_psu_exit(void) +{ + i2c_del_driver(&s8810_psu_driver); +} + +module_init(s8810_psu_init); +module_exit(s8810_psu_exit); + +MODULE_AUTHOR("Jason Tsai "); +MODULE_DESCRIPTION("S8810-32Q psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/qsfp-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/qsfp-monitor.service new file mode 100644 index 000000000000..3d69fdae0f87 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s8810-32q-monitor.service +After=s8810-32q-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/s8810-32q-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/s8810-32q-monitor.service new file mode 100644 index 000000000000..644efe443256 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/service/s8810-32q-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s8810_32q_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/i2c_utils.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/i2c_utils.sh new file mode 100644 index 000000000000..416e631423a7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/i2c_utils.sh @@ -0,0 +1,1489 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.1.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +QSFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 +NUM_ISMT_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) + +#MUX PCA9548#0 +NUM_MUX_9548_0_CHAN0=$(( ${NUM_I801_DEVICE} + 2 )) +NUM_MUX_9548_0_CHAN1=$(( ${NUM_I801_DEVICE} + 3 )) +NUM_MUX_9548_0_CHAN2=$(( ${NUM_I801_DEVICE} + 4 )) +#NUM_MUX_9548_0_CHAN3=$(( ${NUM_I801_DEVICE} + 5 )) +#NUM_MUX_9548_0_CHAN4=$(( ${NUM_I801_DEVICE} + 6 )) +#NUM_MUX_9548_0_CHAN5=$(( ${NUM_I801_DEVICE} + 7 )) +#NUM_MUX_9548_0_CHAN6=$(( ${NUM_I801_DEVICE} + 8 )) +#NUM_MUX_9548_0_CHAN7=$(( ${NUM_I801_DEVICE} + 9 )) + +#MUX PCA9548#1 +NUM_MUX_9548_1_CHAN0=$(( ${NUM_I801_DEVICE} + 10 )) +NUM_MUX_9548_1_CHAN1=$(( ${NUM_I801_DEVICE} + 11 )) +NUM_MUX_9548_1_CHAN2=$(( ${NUM_I801_DEVICE} + 12 )) +NUM_MUX_9548_1_CHAN3=$(( ${NUM_I801_DEVICE} + 13 )) +NUM_MUX_9548_1_CHAN4=$(( ${NUM_I801_DEVICE} + 14 )) +NUM_MUX_9548_1_CHAN5=$(( ${NUM_I801_DEVICE} + 15 )) +NUM_MUX_9548_1_CHAN6=$(( ${NUM_I801_DEVICE} + 16 )) +NUM_MUX_9548_1_CHAN7=$(( ${NUM_I801_DEVICE} + 17 )) + +NUM_MUX_9548_2_CHAN0=$(( ${NUM_I801_DEVICE} + 18 )) +NUM_MUX_9548_3_CHAN0=$(( ${NUM_I801_DEVICE} + 26 )) +NUM_MUX_9548_4_CHAN0=$(( ${NUM_I801_DEVICE} + 34 )) +NUM_MUX_9548_5_CHAN0=$(( ${NUM_I801_DEVICE} + 42 )) + +#MUX Alias +I2C_BUS_PSU1_EEPROM=${NUM_MUX_9548_0_CHAN1} +I2C_BUS_PSU2_EEPROM=${NUM_MUX_9548_0_CHAN2} +I2C_BUS_FAN_STATUS=${NUM_MUX_9548_1_CHAN0} +I2C_BUS_LED_BOARD=${NUM_MUX_9548_1_CHAN0} +I2C_BUS_MB_EEPROM=${NUM_MUX_9548_1_CHAN2} + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_SYS_GPIO="/sys/class/gpio" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +#PATH for MUX PCA9548#0 +PATH_MUX_9548_0_CHAN0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CHAN0}" +PATH_MUX_9548_0_CHAN1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CHAN1}" +PATH_MUX_9548_0_CHAN2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CHAN2}" +#PATH for MUX PCA9548#1 +PATH_MUX_9548_1_CHAN0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN0}" +PATH_MUX_9548_1_CHAN1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}" +PATH_MUX_9548_1_CHAN2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}" +PATH_MUX_9548_1_CHAN3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN3}" +PATH_MUX_9548_1_CHAN4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN4}" +PATH_MUX_9548_1_CHAN5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN5}" +PATH_MUX_9548_1_CHAN6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN6}" +PATH_MUX_9548_1_CHAN7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN7}" + +#i2cmap and gpiomap path +PATH_GPIOMAP=/tmp/gpiomap +PATH_I2CMAP=/tmp/i2cmap + +I2C_ADDR_MUX_9548_0=0x70 +I2C_ADDR_MUX_9548_1=0x70 +I2C_ADDR_MUX_9548_2=0x71 +I2C_ADDR_MUX_9548_3=0x71 +I2C_ADDR_MUX_9548_4=0x71 +I2C_ADDR_MUX_9548_5=0x71 +I2C_ADDR_DDR3=0x50 +I2C_ADDR_RTC=0x68 +I2C_ADDR_CPLD=0x33 +I2C_ADDR_HWM=0x2F +I2C_ADDR_MUX_9535_FAN=0x20 +I2C_ADDR_MUX_9535_LED=0x22 +I2C_ADDR_MUX_9535_0=0x20 +I2C_ADDR_MUX_9535_1=0x21 +I2C_ADDR_MUX_9535_2=0x22 +I2C_ADDR_MUX_9535_3=0x23 +I2C_ADDR_MUX_9535_4=0x20 +I2C_ADDR_MUX_9535_5=0x21 +I2C_ADDR_MUX_9535_6=0x22 +I2C_ADDR_MUX_9535_7=0x23 +I2C_ADDR_MUX_9535_8=0x20 +I2C_ADDR_MUX_9535_9=0x21 +I2C_ADDR_MUX_9535_10=0x22 +I2C_ADDR_MB_EEPROM=0x56 +I2C_ADDR_QSFP_EEPROM=0x50 +I2C_ADDR_PSU_EEPROM=0x51 + +#sysfs +PATH_SYSFS_PSU1="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU1_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU_EEPROM)" +PATH_SYSFS_PSU2="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU2_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU_EEPROM)" + +#Active High/Low +ACTIVE_LOW=1 +ACTIVE_HIGH=0 +#GPIO Direction In/Out +DIR_IN=in +DIR_OUT=out + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +#W83795 Registers +REG_BANK_SEL=0x00 +REG_VOLT_CTRL1=0x02 +REG_VOLT_CTRL2=0x03 +REG_TEMP_CTRL1=0x04 +REG_TEMP_CTRL2=0x05 + +#PCA9535 Registers +REG_IN_0=0 +REG_IN_1=1 +REG_OUT_0=2 +REG_OUT_1=3 +REG_POLARITY_0=4 +REG_POLARITY_1=5 +REG_CFG_0=6 +REG_CFG_1=7 + +#Bit Mask +BIT_MASK=(1 2 4 8 16 32 64 128) + +#GPIO Offset +GPIO_OFFSET=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "# Version : ${VERSION}" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-32]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-32]" + echo " : ${0} i2c_qsfp_type_get [1-32]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_led_fan_tray_test" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_sys_led green|amber on|off" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber on|off" + echo " : ${0} i2c_psu2_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#set i2cmap +function _set_i2cmap { + local i2c_n=$1 + local alias=$2 + + #create i2cmap dir if not exist + mkdir -p $PATH_I2CMAP + + #check i2c_n exists in sysfs + if [ ! -L ${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} ]; then + echo "${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} does not exist." + return + fi + + #create or update link + ln -sf ${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} ${PATH_I2CMAP}/${alias} +} + +#clear i2cmap +function _clear_i2cmap { + #delete i2cmap dir + rm -rf ${PATH_I2CMAP}/ +} + + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod i2c_ismt + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_ismt + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + #add MUX PCA9548#0 on I801 + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_0}' > ${PATH_I801_DEVICE}/new_device" + _set_i2cmap ${NUM_MUX_9548_0_CHAN0} "PCA9548_0" + else + echo "pca9548#0 ${I2C_ADDR_MUX_9548_0} already init." + fi + #add MUX PCA9548#1 on ISMT + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_1}' > ${PATH_ISMT_DEVICE}/new_device" + _set_i2cmap ${NUM_MUX_9548_1_CHAN0} "PCA9548_1" + else + echo "pca9548#1 ${I2C_ADDR_MUX_9548_1} already init." + fi + #add MUX PCA9548#2 on PCA9548#1 + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_2}' > ${PATH_MUX_9548_1_CHAN4}/new_device" + _set_i2cmap ${NUM_MUX_9548_2_CHAN0} "PCA9548_2" + else + echo "pca9548#2 ${I2C_ADDR_MUX_9548_2} already init." + fi + #add MUX PCA9548#3 on PCA9548#1 + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_3_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_3}' > ${PATH_MUX_9548_1_CHAN5}/new_device" + _set_i2cmap ${NUM_MUX_9548_3_CHAN0} "PCA9548_3" + else + echo "pca9548#3 ${I2C_ADDR_MUX_9548_3} already init." + fi + #add MUX PCA9548#4 on PCA9548#1 + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_4_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_4}' > ${PATH_MUX_9548_1_CHAN6}/new_device" + _set_i2cmap ${NUM_MUX_9548_4_CHAN0} "PCA9548_4" + else + echo "pca9548#4 ${I2C_ADDR_MUX_9548_4} already init." + fi + #add MUX PCA9548#5 on PCA9548#1 + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_5_CHAN0}" ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_5}' > ${PATH_MUX_9548_1_CHAN7}/new_device" + _set_i2cmap ${NUM_MUX_9548_5_CHAN0} "PCA9548_5" + else + echo "pca9548#5 ${I2C_ADDR_MUX_9548_5} already init." + fi + #Init CPLD LED_CLR Register (Front Port LED) + i2cset -y ${NUM_I801_DEVICE} ${I2C_ADDR_CPLD} 0x34 0x10 + + rmmod coretemp + rmmod jc42 + rmmod w83795 + _i2c_temp_init + _i2c_volmon_init + modprobe coretemp + modprobe w83795 + modprobe jc42 + modprobe eeprom + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_fan_init + _i2c_io_exp_init + rmmod gpio_ich + _i2c_gpio_init + modprobe gpio_ich + _i2c_psu_init + _i2c_qsfp_eeprom_init "new" + _i2c_mb_eeprom_init "new" + _i2c_led_psu_status_set + _i2c_led_fan_status_set + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + _i2c_gpio_deinit + for mod in coretemp jc42 w83795 eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_ismt i2c_i801 ingrasys_s8810_32q_psu; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done + _clear_i2cmap +} + +#Temperature sensor Init +function _i2c_temp_init { + echo -n "TEMP INIT..." + #select bank0 + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_BANK_SEL} 0x80 + #enable TR1, TR2, TR3 temperature monitoring + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_TEMP_CTRL2} 0x7F + + # CLKIN clock frequency set as 48Mhz + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} 0x01 0x1C +} + +#FAN Init +function _i2c_fan_init { + + local init_fan_speed=120 + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + #Init Fan Speed + echo $init_fan_speed > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo $init_fan_speed > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + fi +} + +#VOLMON Init +function _i2c_volmon_init { + #3.3V 3VDD + #VSEN1 ROV + #VSEN4 1V + #VSEN5 1.8V + #VSEN7 5V + echo -n "VOLMON INIT..." + #select bank0 + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_BANK_SEL} 0x80 + #enable voltage monitoring VSEN1-8 + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_VOLT_CTRL1} 0xFF + #enable voltage monitoring 3VDD and 3VBAT + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_VOLT_CTRL2} 0x50 + #disable voltage monitoring VSEN12 and VSEN13 + i2cset -y -r ${NUM_I801_DEVICE} ${I2C_ADDR_HWM} ${REG_TEMP_CTRL1} 0x00 + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expander Init" + echo "=========================================================" + + #SMBUS1 + + echo "Init FAN Status IO Expander" + #PCA9535_FAN FAN_STATUS + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is input + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_OUT_0} 0x11 + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_OUT_1} 0x11 + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_CFG_0} 0xCC + i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} ${REG_CFG_1} 0xCC + + echo "Init LED Status IO Expander" + #PCA9535_LED LED_BOARD + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is output + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_OUT_0} 0xFF #active low + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_OUT_1} 0xFF #active low + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_CFG_0} 0x00 + i2cset -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_CFG_1} 0x00 + + #PCA9535#0-10 zQSFP + + echo "Init ZQSFP IO Expander" + + echo "set ZQSFP ABS" + #zQSFP 0-31 ABS + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is input + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_0} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_0} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_0} ${REG_CFG_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_0} ${REG_CFG_1} 0xFF + + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_1} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_1} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_1} ${REG_CFG_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_1} ${REG_CFG_1} 0xFF + + echo "set ZQSFP INT" + #zQSFP 0-31 INT + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is input + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_2} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_2} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_2} ${REG_CFG_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_2} ${REG_CFG_1} 0xFF + + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_3} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_3} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_3} ${REG_CFG_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN1} ${I2C_ADDR_MUX_9535_3} ${REG_CFG_1} 0xFF + + echo "set ZQSFP LP_MODE" + #zQSFP 0-31 LP_MODE + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is output + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_OUT_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_OUT_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_4} ${REG_CFG_1} 0x00 + + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_OUT_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_OUT_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_5} ${REG_CFG_1} 0x00 + + echo "set ZQSFP RST" + #zQSFP 0-31 RST + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is output + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_OUT_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_OUT_1} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_6} ${REG_CFG_1} 0x00 + + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_OUT_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_OUT_1} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN2} ${I2C_ADDR_MUX_9535_7} ${REG_CFG_1} 0x00 + + echo "set ZQSFP Mode Select" + #zQSFP 0-31 Mode Select + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, direction is output + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_OUT_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_OUT_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_8} ${REG_CFG_1} 0x00 + + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_OUT_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_OUT_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_CFG_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_9} ${REG_CFG_1} 0x00 + + #ZQSFP ABS0_15, ABS16_31, INT0_15, INT16_31, PSU1_PWROFF, PSU2_PWROFF + #command byte 2/3, output logic level is 0 + #command byte 4/5, polarity is not inverted + #command byte 6/7, I/O 1.0 and I/O 1.1 are output, others are input + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_OUT_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_OUT_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_CFG_0} 0xFF + i2cset -y -r ${NUM_MUX_9548_1_CHAN3} ${I2C_ADDR_MUX_9535_10} ${REG_CFG_1} 0xFC +} + +#GPIO Init Utility Function +function _gpio_export { + local gpio_n=$1 + local direction=$2 + local active_low=$3 + local value=$4 + + if [ -z "${gpio_n}" ]; then + echo "[_gpio_init] gpio_n(${gpio_n}) is not provided" + return + fi + if [ "${gpio_n}" -lt "0" ] || [ "${gpio_n}" -gt "255" ]; then + echo "[_gpio_init] gpio_n(${gpio_n}) is invalid value" + return + fi + + #export gpio + echo ${gpio_n} > ${PATH_SYS_GPIO}/export + + #set gpio direction + echo ${direction} > ${PATH_SYS_GPIO}/gpio${gpio_n}/direction + + #set gpio active_low + echo ${active_low} > ${PATH_SYS_GPIO}/gpio${gpio_n}/active_low + + #set value + if [ ! -z "${value}" ]; then + echo ${value} > ${PATH_SYS_GPIO}/gpio${gpio_n}/value + fi +} + +#set gpiomap +function _set_gpiomap { + local gpio_n=$1 + local alias=$2 + + #create gpiomap dir if not exist + mkdir -p $PATH_GPIOMAP + + #check gpio_n exists in sysfs + if [ ! -L ${PATH_SYS_GPIO}/gpio${gpio_n} ]; then + echo "${PATH_SYS_GPIO}/gpio${gpio_n} does not exist." + return + fi + + #create or update link + ln -sf ${PATH_SYS_GPIO}/gpio${gpio_n} ${PATH_GPIOMAP}/${alias} +} + +#clear gpiomap +function _clear_gpiomap { + #delete gpiomap dir + rm -rf ${PATH_GPIOMAP} +} + +# To set the global variable GPIO_OFFSET +function _set_gpio_offset { + GPIO_OFFSET=0 + for d in `ls /sys/class/gpio/ | grep gpiochip` + do + gpiochip_no=${d##gpiochip} + if [ $gpiochip_no -gt 255 ]; then + GPIO_OFFSET=256 + break + fi + done + #echo "set GPIO_OFFSET=${GPIO_OFFSET}" +} + +#GPIO Init +function _i2c_gpio_init { + local i=0 + + #ABS Port 0-31 + echo "pca9535 ${I2C_ADDR_MUX_9535_1}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/new_device + _set_gpio_offset + echo "pca9535 ${I2C_ADDR_MUX_9535_0}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/new_device + #for i in {224..255} + for((i=${GPIO_OFFSET}+224;i<=${GPIO_OFFSET}+255;i++)); + do + _gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW} + _set_gpiomap ${i} "QSFP$(( i - 223 ))_ABS" + done + + #INT Port 0-31 + echo "pca9535 ${I2C_ADDR_MUX_9535_3}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/new_device + echo "pca9535 ${I2C_ADDR_MUX_9535_2}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/new_device + #for i in {192..223} + for((i=${GPIO_OFFSET}+192;i<=${GPIO_OFFSET}+223;i++)); + do + _gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW} + _set_gpiomap ${i} "QSFP$(( i - 191 ))_INT" + done + + #LP Mode Port 0-31 + echo "pca9535 ${I2C_ADDR_MUX_9535_5}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/new_device + echo "pca9535 ${I2C_ADDR_MUX_9535_4}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/new_device + #for i in {160..191} + for((i=${GPIO_OFFSET}+160;i<=${GPIO_OFFSET}+191;i++)); + do + _gpio_export ${i} ${DIR_OUT} ${ACTIVE_HIGH} + _set_gpiomap ${i} "QSFP$(( i - 159 ))_LPMODE" + done + + #RST Port 0-31 + echo "pca9535 ${I2C_ADDR_MUX_9535_7}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/new_device + echo "pca9535 ${I2C_ADDR_MUX_9535_6}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/new_device + #for i in {128..159} + for((i=${GPIO_OFFSET}+128;i<=${GPIO_OFFSET}+159;i++)); + do + _gpio_export ${i} ${DIR_OUT} ${ACTIVE_LOW} + _set_gpiomap ${i} "QSFP$(( i - 127 ))_RST" + #Reset QSFP + echo "${ACTIVE_LOW}" > ${PATH_SYS_GPIO}/gpio${i}/value + echo "${ACTIVE_HIGH}" > ${PATH_SYS_GPIO}/gpio${i}/value + done + + #MODSEL Port 0-31 + echo "pca9535 ${I2C_ADDR_MUX_9535_9}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN3}/new_device + echo "pca9535 ${I2C_ADDR_MUX_9535_8}" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN3}/new_device + #for i in {96..127} + for((i=${GPIO_OFFSET}+96;i<=${GPIO_OFFSET}+127;i++)); + do + _gpio_export ${i} ${DIR_OUT} ${ACTIVE_LOW} + _set_gpiomap ${i} "QSFP$(( i - 95 ))_MODSEL" + done +} + +#GPIO DeInit +function _i2c_gpio_deinit { + echo ${I2C_ADDR_MUX_9535_0} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/delete_device + echo ${I2C_ADDR_MUX_9535_1} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/delete_device + echo ${I2C_ADDR_MUX_9535_2} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/delete_device + echo ${I2C_ADDR_MUX_9535_3} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN1}/delete_device + echo ${I2C_ADDR_MUX_9535_4} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/delete_device + echo ${I2C_ADDR_MUX_9535_5} > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CHAN2}/delete_device + _clear_gpiomap +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + + #check W83795 exists in hwmon2 + if [ ! -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + return + fi + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + FAN_TRAY=1 + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + FAN_TRAY=2 + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + FAN_TRAY=3 + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + FAN_TRAY=4 + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Test FAN Tray LED +function _i2c_led_fan_tray_test { + echo "FAN Tray LED Test" + + for i in {1..4} + do + FAN_TRAY=$i + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + _pause 'Check Fan Tray ${FAN_TRAY} LED green light and Press [Enter] key to continue...' + + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + _pause 'Check Fan Tray ${FAN_TRAY} LED amber light and Press [Enter] key to continue...' + done +} +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + + #check W83795 exists in hwmon2 + if [ ! -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + return + fi + + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C LED TEST..." + echo "=========================================================" + #sys led (green) + _i2c_reset_led + COLOR_LED="green" + ONOFF_LED="on" + _i2c_sys_led + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + _i2c_reset_led + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_sys_led + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + _i2c_reset_led + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_led + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + _i2c_reset_led + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_led + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + _i2c_reset_led + COLOR_LED="green" + ONOFF_LED="on" + _i2c_psu2_led + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + _i2c_reset_led + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_psu2_led + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + _i2c_reset_led + COLOR_LED="green" + ONOFF_LED="on" + _i2c_psu1_led + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + _i2c_reset_led + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_psu1_led + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED + _i2c_reset_led + _pause 'Check turn off all LEDs and Press [Enter] key to continue...' + echo "done..." + + #sys led (green) + COLOR_LED="green" + ONOFF_LED="on" + _i2c_sys_led +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX_9548_1_CHAN1} + regAddr=0x20 + dataAddr=0 + eeprombusbase=${NUM_MUX_9548_2_CHAN0} + gpioBase=$((${GPIO_OFFSET}+224)) + #gpioBase=224 + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX_9548_1_CHAN1} + regAddr=0x20 + dataAddr=1 + eeprombusbase=${NUM_MUX_9548_3_CHAN0} + gpioBase=$((${GPIO_OFFSET}+224)) + #gpioBase=224 + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX_9548_1_CHAN1} + regAddr=0x21 + dataAddr=0 + eeprombusbase=${NUM_MUX_9548_4_CHAN0} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX_9548_1_CHAN1} + regAddr=0x21 + dataAddr=1 + eeprombusbase=${NUM_MUX_9548_5_CHAN0} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + *) + echo "Please input 1~32" + exit + ;; + esac +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + local port=$1 + eeprombusidx=$(( ${port} % 8)) + case $eeprombusidx in + 1) + eeprombus=$(( $eeprombusbase + 0 )) + ;; + 2) + eeprombus=$(( $eeprombusbase + 1 )) + ;; + 3) + eeprombus=$(( $eeprombusbase + 2 )) + ;; + 4) + eeprombus=$(( $eeprombusbase + 3 )) + ;; + 5) + eeprombus=$(( $eeprombusbase + 4 )) + ;; + 6) + eeprombus=$(( $eeprombusbase + 5 )) + ;; + 7) + eeprombus=$(( $eeprombusbase + 6 )) + ;; + 0) + eeprombus=$(( $eeprombusbase + 7 )) + ;; + esac + eepromAddr=${I2C_ADDR_QSFP_EEPROM} +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat ${PATH_SYS_GPIO}/gpio$(( gpioBase + (QSFP_PORT-1)%16 ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo -n "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + local i + for i in {1..32}; + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done + echo "DONE" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init MB EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_MB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "${I2C_ADDR_MB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/delete_device + fi + echo "DONE" +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + + status=`cat ${PATH_SYS_GPIO}/gpio$(( gpioBase + (QSFP_PORT-1)%16 ))/value` + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + _qsfp_eeprom_var_set ${QSFP_PORT} + + #Get QSFP EEPROM info + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Init PSU Kernel Module +function _i2c_psu_init { + echo "=========================================================" + echo "# Description: I2C PSU Init" + echo "=========================================================" + modprobe ingrasys_s8810_32q_psu + + echo "psu1 ${I2C_ADDR_PSU_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/new_device + echo "psu2 ${I2C_ADDR_PSU_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/new_device +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + local eeprom_psu1="" + local eeprom_psu2="" + + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + eeprom_psu1="${PATH_SYSFS_PSU1}/psu_eeprom" + cat ${eeprom_psu1} | hexdump -C + + eeprom_psu2="${PATH_SYSFS_PSU2}/psu_eeprom" + cat ${eeprom_psu2} | hexdump -C +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom | hexdump -C + echo "done..." +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + local value=0 + case ${FAN_TRAY} in + 1) + ioPort=$REG_OUT_0 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + ioPort=$REG_OUT_0 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + ioPort=$REG_OUT_1 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + ioPort=$REG_OUT_1 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${ONOFF_LED}" == "on" ]; then + value=0xFF + elif [ "${ONOFF_LED}" == "off" ]; then + value=0x00 + else + echo "Invalid Parameters ${ONOFF_LED}, Exit!!!" + _help + exit ${FALSE} + fi + i2cset -m $mask -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_FAN} $ioPort $value + + #echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + local green_mask=${BIT_MASK[7]} + local amber_mask=${BIT_MASK[6]} + + _i2c_set_led $green_mask $amber_mask +} + +#Set FAN LED +function _i2c_fan_led { + local green_mask=${BIT_MASK[3]} + local amber_mask=${BIT_MASK[2]} + + _i2c_set_led $green_mask $amber_mask +} + +#Set PSU1 LED +function _i2c_psu1_led { + local green_mask=${BIT_MASK[1]} + local amber_mask=${BIT_MASK[0]} + + _i2c_set_led $green_mask $amber_mask +} + +#Set PSU2 LED +function _i2c_psu2_led { + local green_mask=${BIT_MASK[5]} + local amber_mask=${BIT_MASK[4]} + + _i2c_set_led $green_mask $amber_mask +} + +#Set LEDs in LED Board +function _i2c_set_led { + local green_mask=$1 + local amber_mask=$2 + local mask=0 + local value=0 + + + if [ "${COLOR_LED}" == "green" ]; then + mask=$green_mask + elif [ "${COLOR_LED}" == "amber" ]; then + mask=$amber_mask + else + echo "Invalid Parameters ${COLOR_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + # Singals are active_low + if [ "${ONOFF_LED}" == "on" ]; then + value=0x00 + elif [ "${ONOFF_LED}" == "off" ]; then + value=0xFF + else + echo "Invalid Parameters ${ONOFF_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + i2cset -m $mask -y -r ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_OUT_0} $value +} + +#Reset all system leds +function _i2c_reset_led { + i2cset -y ${I2C_BUS_LED_BOARD} ${I2C_ADDR_MUX_9535_LED} ${REG_OUT_0} 0xFF +} + +#Get Board Version and Type +function _i2c_board_type_get { + local reg_board=0x00 + local reg_ext_board=0x07 + local boardType=0 + local boardBuildRev=0 + local boardHwRev=0 + local boardId=0 + local extBoardType=0 + + boardType=`i2cget -y ${NUM_I801_DEVICE} ${I2C_ADDR_CPLD} ${reg_board}` + #Bit 0-1 + boardBuildRev=$((($boardType) & 0x03)) + #Bit 2-3 + boardHwRev=$((($boardType) >> 2 & 0x03)) + #Bit 4-7 + boardId=$((($boardType) >> 4)) + + extBoardType=`i2cget -y ${NUM_I801_DEVICE} ${I2C_ADDR_CPLD} ${reg_ext_board}` + #Bit 0-3 + extBoardType=$((($extBoardType) & 0x0F)) + + printf "BOARD_ID=0x%02x, HW Rev=%d, Build Rev=%d, Ext_BOARD_ID=0x%02x\n" $boardId $boardHwRev $boardBuildRev $extBoardType + +} + +#Get CPLD Version +function _i2c_cpld_version { + local reg_cpld_rev=0x01 + cpldRev=`i2cget -y ${NUM_I801_DEVICE} ${I2C_ADDR_CPLD} ${reg_cpld_rev}` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Get PSU Status +function _i2c_psu_status { + local psu_abs="" + + psu1PwGood=`cat ${PATH_SYSFS_PSU1}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU1}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu1Exist=1 + else + psu1Exist=0 + fi + + psu2PwGood=`cat ${PATH_SYSFS_PSU2}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU2}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu2Exist=1 + else + psu2Exist=0 + fi + + printf "PSU1 Exist:%x PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + start_time_str=`date` + start_time_sec=$(date +%s) + + _set_gpio_offset + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_test" ]; then + _i2c_led_fan_tray_test + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_deinit + _i2c_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main 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 new file mode 100755 index 000000000000..7776493bc20a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..31}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`sonic-db-cli ASIC_DB HLEN HIDDEN` + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/s8810_32q_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/s8810_32q_monitor.sh new file mode 100755 index 000000000000..974da6d5001f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8810-32q/utils/s8810_32q_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/README.md b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/README.md new file mode 100644 index 000000000000..2042625f631c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/README.md @@ -0,0 +1,185 @@ +# Ingrasys S8900-54XC Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S8900-54XC is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S8900-54XC platform. + +### I2C i801 + +The I2C i801 on Ingrasys S8900-54XC can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S8900-54XC. + +### I2C iSMT + +The I2C iSMT module on S8900-54XC can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S8900-54XC. + +### I2C PCA9548 +The PCA9548 module on S8900-54XC can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S8900-54XC. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S8900-54XC platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s8900-54xc package is installed on the S8900-54XC, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/Makefile b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/Makefile new file mode 100644 index 000000000000..a0042543dff5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := eeprom_mb.o +obj-m+= i2c_cpld.o diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/eeprom_mb.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/eeprom_mb.c new file mode 100644 index 000000000000..0886cad58eb3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/eeprom_mb.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys S8900 Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.c new file mode 100644 index 000000000000..626c63177b50 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.c @@ -0,0 +1,448 @@ +/* + * S9100-32X I2C CPLD driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c_cpld.h" + +#ifdef DEBUG + #define DEBUG_PRINT(fmt, args...) \ + printk(KERN_INFO "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define I2C_READ_BYTE_DATA(ret, lock, i2c_client, reg) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_read_byte_data(i2c_client, reg); \ + mutex_unlock(lock); \ +} +#define I2C_WRITE_BYTE_DATA(ret, lock, i2c_client, reg, val) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_write_byte_data(i2c_client, reg, val); \ + mutex_unlock(lock); \ +} + +/* CPLD sysfs attributes index */ +enum i2c_cpld_sysfs_attributes { + CPLD_ACCESS_REG, + CPLD_REGISTER_VAL, + CPLD_PORT_START, + CPLD_PORTS, + CPLD_VERSION, + CPLD_ID, + CPLD_BOARD_TYPE, + CPLD_EXT_BOARD_TYPE, + CPLD_PW_GOOD, + CPLD_PW_ABS, +}; + +/* CPLD sysfs attributes hook functions */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, char *buf); + +static LIST_HEAD(cpld_client_list); /* client list for cpld */ +static struct mutex list_lock; /* mutex for client list */ + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +struct cpld_data { + int index; /* CPLD index */ + struct mutex access_lock; /* mutex for cpld access */ + u8 access_reg; /* register to access */ +}; + +/* CPLD device id and data */ +static const struct i2c_device_id i2c_cpld_id[] = { + { "i2c_cpld", i2c_cpld }, + {} +}; + +/* Addresses scanned for i2c_cpld */ +static const unsigned short cpld_i2c_addr[] = { 0x33, I2C_CLIENT_END }; +/* platform sysfs object */ +extern struct kobject *s9230_64x_kobj; + + +/* define all support register access of cpld in attribute */ +static SENSOR_DEVICE_ATTR(cpld_access_register, S_IWUSR | S_IRUGO, + read_access_register, write_access_register, CPLD_ACCESS_REG); +static SENSOR_DEVICE_ATTR(cpld_register_value, S_IWUSR | S_IRUGO, + read_register_value, write_register_value, CPLD_REGISTER_VAL); +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, + read_cpld_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(cpld_board_type, S_IRUGO, + read_board_type, NULL, CPLD_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_ext_board_type, S_IRUGO, + read_ext_board_type, NULL, CPLD_EXT_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_pw_good, S_IRUGO, + read_pw_good, NULL, CPLD_PW_GOOD); +static SENSOR_DEVICE_ATTR(cpld_pw_abs, S_IRUGO, + read_pw_abs, NULL, CPLD_PW_ABS); + + +/* define support attributes of cpldx , total 5 */ +/* cpld 1 */ +static struct attribute *i2c_cpld_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_ext_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_pw_good.dev_attr.attr, + &sensor_dev_attr_cpld_pw_abs.dev_attr.attr, + NULL +}; + +/* cpld 1 attributes group */ +static const struct attribute_group i2c_cpld_group = { + .attrs = i2c_cpld_attributes, +}; + +/* read access register from cpld data */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + + return sprintf(buf, "0x%x\n", reg); +} + +/* write access register to cpld data */ +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + + if (kstrtou8(buf, 0, ®) < 0) + return -EINVAL; + + data->access_reg = reg; + return count; +} + +/* read the value of access register in cpld data */ +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + int reg_val; + + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + + if (reg_val < 0) + return -1; + + return sprintf(buf, "0x%x\n", reg_val); +} + +/* wrtie the value to access register in cpld data */ +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ret = -EIO; + u8 reg = data->access_reg; + u8 reg_val; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, client, reg, reg_val); + + return count; +} + +/* get cpdl version register value */ +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_VERSION) { + reg = CPLD_VERSION_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get board type register value */ +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BOARD_TYPE) { + reg = CPLD_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_EXT_BOARD_TYPE) { + reg = CPLD_EXT_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_GOOD) { + reg = CPLD_PW_GOOD_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_ABS) { + reg = CPLD_PW_ABS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* add valid cpld client to list */ +static void i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = NULL; + + node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + if (!node) { + dev_info(&client->dev, + "Can't allocate cpld_client_node for index %d\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +/* remove exist cpld client in list */ +static void i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + mutex_unlock(&list_lock); +} + +/* cpld drvier probe */ +static int i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* init cpld data for client */ + i2c_set_clientdata(client, data); + mutex_init(&data->access_lock); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_info(&client->dev, + "i2c_check_functionality failed (0x%x)\n", + client->addr); + status = -EIO; + goto exit; + } + + + status = sysfs_create_group(&client->dev.kobj,&i2c_cpld_group); + + if (status) + goto exit; + + dev_info(&client->dev, "chip found\n"); + + /* add probe chip to client list */ + i2c_cpld_add_client(client); + + return 0; +exit: + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + return status; +} + +/* cpld drvier remove */ +static int i2c_cpld_remove(struct i2c_client *client) +{ + + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + + i2c_cpld_remove_client(client); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, i2c_cpld_id); + +static struct i2c_driver i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "i2c_cpld", + }, + .probe = i2c_cpld_probe, + .remove = i2c_cpld_remove, + .id_table = i2c_cpld_id, + .address_list = cpld_i2c_addr, +}; + +static int __init i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&i2c_cpld_driver); +} + +static void __exit i2c_cpld_exit(void) +{ + i2c_del_driver(&i2c_cpld_driver); +} + +MODULE_AUTHOR("Wade He "); +MODULE_DESCRIPTION("Ingrasys S9100-32X Platform i2c cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_cpld_init); +module_exit(i2c_cpld_exit); + + + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.h b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.h new file mode 100644 index 000000000000..e103b05c717a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/modules/i2c_cpld.h @@ -0,0 +1,197 @@ +/* + * + * S9100-32X I2C CPLD driver header file + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef I2C_CPLD_H +#define I2C_CPLD_H + +// remove debug before release +#define DEBUG + +/* CPLD device index value */ +enum cpld_id { + i2c_cpld +}; + +/* port number on CPLD */ +#define CPLD_1_PORT_NUM 12 +#define CPLD_2_PORT_NUM 13 + +/* QSFP port number */ +#define QSFP_MAX_PORT_NUM 64 +#define QSFP_MIN_PORT_NUM 1 + +/* SFP+ port number */ +#define SFP_MAX_PORT_NUM 2 +#define SFP_MIN_PORT_NUM 1 + + +/* CPLD registers */ +#define CPLD_BOARD_TYPE_REG 0x0 +#define CPLD_EXT_BOARD_TYPE_REG 0x7 +#define CPLD_VERSION_REG 0x1 +#define CPLD_PW_GOOD_REG 0x2 +#define CPLD_PW_ABS_REG 0x3 + + +/* bit definition for register value */ + +enum CPLD_RESET_CONTROL_BITS { + CPLD_RESET_CONTROL_SWRST_BIT, + CPLD_RESET_CONTROL_CP2104RST_BIT, + CPLD_RESET_CONTROL_82P33814RST_BIT, + CPLD_RESET_CONTROL_BMCRST_BIT, +}; + +/* bit field structure for register value */ +struct cpld_reg_board_type_t { + u8 build_rev:2; + u8 hw_rev:2; + u8 board_id:4; +}; + +struct cpld_reg_version_t { + u8 revision:6; + u8 release:1; + u8 reserve:1; +}; + +struct cpld_reg_pw_good_t { + u8 reserve1:3; + u8 psu1:1; + u8 psu2:1; + u8 reserve2:3; +}; + +struct cpld_reg_pw_abs_t { + u8 psu1:1; + u8 psu2:1; + u8 reserve:6; +}; + +/* common manipulation */ +#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u) +#define READ_BIT(val, bit) ((0u == (val & (1<bf_name) +#define READ_BF_1(bf_struct, val, bf_name, bf_value) \ + bf_struct bf; \ + bf.data = val; \ + bf_value = bf.bf_name +#define BOARD_TYPE_BUILD_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, build_rev, res) +#define BOARD_TYPE_HW_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, hw_rev, res) +#define BOARD_TYPE_BOARD_ID_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, board_id, res) +#define CPLD_VERSION_REV_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, revision, res) +#define CPLD_VERSION_REL_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, release, res) +#define CPLD_PSU1_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu1, res) +#define CPLD_PSU2_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu2, res) +#define CPLD_PSU1_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu1, res) +#define CPLD_PSU2_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu2, res) +/* QSFP/SFP registers manipulation */ +#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \ +{ \ + if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \ + cpld_index = cpld1; \ + cpld_port = qsfp_port - 1; \ + } else if (CPLD_1_PORT_NUM < qsfp_port \ + && qsfp_port <= QSFP_MAX_PORT_NUM) { \ + cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \ + / CPLD_2_PORT_NUM; \ + cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \ + CPLD_2_PORT_NUM; \ + } else { \ + cpld_index = 0; \ + cpld_port = 0; \ + } \ +} +#define SFP_TO_CPLD_IDX(sfp_port, cpld_index) \ + (cpld_index = sfp_port - SFP_MIN_PORT_NUM) +#define QSFP_PORT_STATUS_REG(cpld_port) \ + (CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port) +#define QSFP_PORT_CONFIG_REG(cpld_port) \ + (CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port) +#define QSFP_PORT_INT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT) +#define QSFP_PORT_ABS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT) +#define QSFP_PORT_RESET_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_RESET_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define SFP_PORT_PRESENT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_PRESENT_BIT) + + #define SFP_PORT_TXFAULT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_TXFAULT_BIT) + #define SFP_PORT_RXLOS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_RXLOS_BIT) + #define SFP_PORT_TXDIS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TXDIS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_TXDIS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_RS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) + +/* CPLD access functions */ +extern int i2c_cpld_get_qsfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_qsfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val); +extern int i2c_cpld_get_sfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_sfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_sfp_port_config_val(u8 port_num, u8 reg_val); +extern u8 fp_port_to_phy_port(u8 fp_port); +#endif + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/qsfp-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/qsfp-monitor.service new file mode 100644 index 000000000000..e33c2fdae122 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s8900-54xc-monitor.service +After=s8900-54xc-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/s8900-54xc-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/s8900-54xc-monitor.service new file mode 100644 index 000000000000..e43fddc9b857 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/service/s8900-54xc-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s8900_54xc_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/i2c_utils.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/i2c_utils.sh new file mode 100644 index 000000000000..dbea63786621 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/i2c_utils.sh @@ -0,0 +1,1561 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.1.0" +TRUE=200 +FALSE=404 +PORT_START=1 +PORT_END=54 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_IGB_DEVICE=0 +NUM_I801_DEVICE=0 +NUM_ISMT_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) +NUM_MUX1_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 2 )) +NUM_MUX1_CHAN1_DEVICE=$(( ${NUM_I801_DEVICE} + 3 )) +NUM_MUX1_CHAN2_DEVICE=$(( ${NUM_I801_DEVICE} + 4 )) +NUM_MUX1_CHAN3_DEVICE=$(( ${NUM_I801_DEVICE} + 5 )) +NUM_MUX1_CHAN4_DEVICE=$(( ${NUM_I801_DEVICE} + 6 )) +NUM_MUX1_CHAN5_DEVICE=$(( ${NUM_I801_DEVICE} + 7 )) +NUM_MUX1_CHAN6_DEVICE=$(( ${NUM_I801_DEVICE} + 8 )) +NUM_MUX1_CHAN7_DEVICE=$(( ${NUM_I801_DEVICE} + 9 )) +NUM_MUX2_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 10 )) +NUM_MUX2_CHAN1_DEVICE=$(( ${NUM_I801_DEVICE} + 11 )) +NUM_MUX2_CHAN2_DEVICE=$(( ${NUM_I801_DEVICE} + 12 )) +NUM_MUX2_CHAN3_DEVICE=$(( ${NUM_I801_DEVICE} + 13 )) +NUM_MUX2_CHAN4_DEVICE=$(( ${NUM_I801_DEVICE} + 14 )) +NUM_MUX2_CHAN5_DEVICE=$(( ${NUM_I801_DEVICE} + 15 )) +NUM_MUX2_CHAN6_DEVICE=$(( ${NUM_I801_DEVICE} + 16 )) +NUM_MUX2_CHAN7_DEVICE=$(( ${NUM_I801_DEVICE} + 17 )) +NUM_MUX3_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 18 )) +NUM_MUX4_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 26 )) +NUM_MUX5_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 34 )) +NUM_MUX6_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 42 )) +NUM_MUX7_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 50 )) +NUM_MUX8_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 58 )) +NUM_MUX9_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 66 )) + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +PATH_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" +PATH_MUX_CHAN1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN1_DEVICE}" +PATH_MUX_CHAN2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN2_DEVICE}" +PATH_MUX_CHAN3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}" +PATH_MUX_CHAN4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN4_DEVICE}" +PATH_MUX_CHAN5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN5_DEVICE}" +PATH_MUX_CHAN6_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}" +PATH_MUX_CHAN7_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}" + +#SFP/QSFP EEPROM i2c bus index +SFP_EEPROM_BUS_IDX=0 + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +#GPIO Index for QSFP +ZQSFP_PORT0_15_ABS_GPIO_IDX=192 +ZQSFP_PORT16_31_ABS_GPIO_IDX=176 +ZQSFP_PORT32_47_ABS_GPIO_IDX=160 + +#GPIO Offset +GPIO_OFFSET=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "# Version : ${VERSION}" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-54]" + echo " : ${0} i2c_qsfp_status_get [1-54]" + echo " : ${0} i2c_qsfp_type_get [1-54]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_front_temp" + echo " : ${0} i2c_rear_temp" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber on|off" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber on|off" + echo " : ${0} i2c_psu2_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod i2c_ismt + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_ismt + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x70' > ${PATH_ISMT_DEVICE}/new_device" + else + echo "pca9548 0x70 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX2_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x72' > ${PATH_ISMT_DEVICE}/new_device" + else + echo "pca9548 0x72 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX3_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN0_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX4_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN1_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX5_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN2_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX6_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN3_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX7_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN4_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX8_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN5_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX9_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN6_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + + #Init CPLD LED_CLR Register (Front Port LED) + i2cset -y ${NUM_I801_DEVICE} 0x33 0x34 0x10 + + rmmod coretemp + rmmod jc42 + rmmod w83795 + _i2c_temp_init + _i2c_volmon_init + _i2c_hwmon_init + modprobe coretemp + modprobe w83795 + modprobe jc42 + modprobe sff_8436_eeprom + modprobe eeprom + modprobe eeprom_mb + _i2c_fan_init + _i2c_io_exp_init + rmmod gpio_ich + _i2c_gpio_init + modprobe gpio_ich + _i2c_cpld_init + _i2c_psu_eeprom_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + echo "Mount Main Board EEPROM" + echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-17/new_device + for (( i=$PORT_START; i<=$PORT_END; i++ )) + do + _i2c_mount_sfp_eeprom $i + done + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + _i2c_gpio_deinit + for mod in coretemp jc42 w83795 eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_ismt i2c_i801; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done +} + +#Temperature sensor Init +function _i2c_temp_init { + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x05 0x7F + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x04 0x0A + echo "TEMP INIT Done" +} + +#FAN Init +function _i2c_fan_init { + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi + +} + +#VOLMON Init +function _i2c_volmon_init { + echo -n "VOLMON INIT..." + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x02 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x03 0x50 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x04 0x0A + echo "Done" +} + +#HWMON Init +function _i2c_hwmon_init { + echo -n "HWMON INIT..." + i2cset -y ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y ${NUM_I801_DEVICE} 0x2F 0x06 0xFF + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + #SMBUS0 IO_EXPENDER + i2cset -y -r ${NUM_I801_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x27 7 0xFF + + #SMBUS1 + #SFP+ ABS + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x20 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x21 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x22 7 0xFF + + #QSFP/ZQSFP ABS + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x23 6 0xFF + + #QSFP/ZQSFP INT + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN0_DEVICE} 0x23 7 0xFF + + #SFP+ RX_LOS + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x20 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x21 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN1_DEVICE} 0x22 7 0xFF + + #SFP+ TX_FAULT + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x20 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x21 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN2_DEVICE} 0x22 7 0xFF + + #SFP+ TX_RS + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 3 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 3 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 3 0xFF + + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x20 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x21 7 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x22 7 0xFF + + #QSFP/zQSFP LPMODE + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 2 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 6 0x00 + + #QSFP/zQSFP MODSEL + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 3 0x00 + i2cset -y -r ${NUM_MUX2_CHAN3_DEVICE} 0x23 7 0x00 + + #SFP+ RX_RS + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 3 0xFF + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 3 0xFF + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 3 0xFF + + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x20 7 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x21 7 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN4_DEVICE} 0x22 7 0x00 + + #SFP+ TX_DIS + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 5 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 2 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 2 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 3 0x00 + + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x20 7 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x21 7 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x22 7 0x00 + + #QSFP/zQSFP RST + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x23 2 0xFF + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x23 6 0x00 + + #SFP/QSFP/zQSFP I/O + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x24 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x24 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x24 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN5_DEVICE} 0x24 7 0xFF + + #ZQSFP/SFP+/E-Card General + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 6 0xF4 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x21 7 0xF4 + + #LED board after PVT (S8900_IO_EXP_LED_ID) + echo "Init LED IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 7 0x00 + + #PSU I/O (S8900_IO_EXP_PSU_ID) + echo "Init PSU IO Expender" + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX2_CHAN6_DEVICE} 0x20 7 0xFF + + #FAN I/O (S8900_IO_EXP_FAN_ID) + echo "Init FAN IO Expender" + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 2 0x11 + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 3 0x11 + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 6 0xCC + i2cset -y -r ${NUM_MUX2_CHAN7_DEVICE} 0x20 7 0xCC +} + +function _get_sfp_eeprom_bus_idx { + case $1 in + 1|2|3|4|5|6|7|8) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX3_CHAN0_DEVICE} + $1 - 1) )) + ;; + 9|10|11|12|13|14|15|16) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX4_CHAN0_DEVICE} + $1 - 9) )) + ;; + 17|18|19|20|21|22|23|24) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX5_CHAN0_DEVICE} + $1 - 17) )) + ;; + 25|26|27|28|29|30|31|32) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX6_CHAN0_DEVICE} + $1 - 25) )) + ;; + 33|34|35|36|37|38|39|40) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX7_CHAN0_DEVICE} + $1 - 33) )) + ;; + 41|42|43|44|45|46|47|48) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX8_CHAN0_DEVICE} + $1 - 41) )) + ;; + 49|50|51|52|53|54) + SFP_EEPROM_BUS_IDX=$(( (${NUM_MUX9_CHAN0_DEVICE} + $1 - 49) )) + ;; + *) + SFP_EEPROM_BUS_IDX=-1 + ;; + esac +} + +#Mount SFP/QSFP EEPROM +function _i2c_mount_sfp_eeprom { + _get_sfp_eeprom_bus_idx $1 + eeprombus=${SFP_EEPROM_BUS_IDX} + eepromAddr=0x50 + echo "sff8436 $eepromAddr" > /sys/bus/i2c/devices/i2c-$eeprombus/new_device + echo "Mount Port $1 EEPROM" +} + +#Unmount SFP/QSFP EEPROM +function _i2c_unmount_sfp_eeprom { + _get_sfp_eeprom_bus_idx $1 + eeprombus=${SFP_EEPROM_BUS_IDX} + eepromAddr=0x50 + echo "$eepromAddr" > /sys/bus/i2c/devices/i2c-$eeprombus/new_device + echo "Unmount Port $1 EEPROM" +} + +# To set the global variable GPIO_OFFSET +function _set_gpio_offset { + GPIO_OFFSET=0 + for d in `ls /sys/class/gpio/ | grep gpiochip` + do + gpiochip_no=${d##gpiochip} + if [ $gpiochip_no -gt 255 ]; then + GPIO_OFFSET=256 + break + fi + done + #echo "set GPIO_OFFSET=${GPIO_OFFSET}" +} + +#GPIO Init +function _i2c_gpio_init { + + #QSFP/ZQSFP ABS+INT + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/new_device + _set_gpio_offset + for((i=${GPIO_OFFSET}+240;i<=${GPIO_OFFSET}+255;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #_retry "echo 240 > /sys/class/gpio/export" + #echo 241 > /sys/class/gpio/export + #echo 242 > /sys/class/gpio/export + #echo 243 > /sys/class/gpio/export + #echo 244 > /sys/class/gpio/export + #echo 245 > /sys/class/gpio/export + #echo 246 > /sys/class/gpio/export + #echo 247 > /sys/class/gpio/export + #echo 248 > /sys/class/gpio/export + #echo 249 > /sys/class/gpio/export + #echo 250 > /sys/class/gpio/export + #echo 251 > /sys/class/gpio/export + #echo 252 > /sys/class/gpio/export + #echo 253 > /sys/class/gpio/export + #echo 254 > /sys/class/gpio/export + #echo 255 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio241/active_low #QSFP49 ABS + #echo 1 > /sys/class/gpio/gpio240/active_low #QSFP48 ABS + #echo 1 > /sys/class/gpio/gpio243/active_low #QSFP51 ABS + #echo 1 > /sys/class/gpio/gpio242/active_low #QSFP50 ABS + #echo 1 > /sys/class/gpio/gpio245/active_low #QSFP53 ABS + #echo 1 > /sys/class/gpio/gpio244/active_low #QSFP52 ABS + #echo 1 > /sys/class/gpio/gpio247/active_low #NA + #echo 1 > /sys/class/gpio/gpio246/active_low #NA + #echo 1 > /sys/class/gpio/gpio249/active_low #QSFP49 INT + #echo 1 > /sys/class/gpio/gpio248/active_low #QSFP48 INT + #echo 1 > /sys/class/gpio/gpio251/active_low #QSFP51 INT + #echo 1 > /sys/class/gpio/gpio250/active_low #QSFP50 INT + #echo 1 > /sys/class/gpio/gpio253/active_low #QSFP53 INT + #echo 1 > /sys/class/gpio/gpio252/active_low #QSFP52 INT + #echo 1 > /sys/class/gpio/gpio255/active_low #NA + #echo 1 > /sys/class/gpio/gpio254/active_low #NA + + #QSFP/zQSFP LPMODE+MODSEL + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN3_DEVICE}/new_device + for((i=${GPIO_OFFSET}+224;i<=${GPIO_OFFSET}+239;i++)); + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #echo 224 > /sys/class/gpio/export #QSFP0 LPMODE + #echo 225 > /sys/class/gpio/export #QSFP1 LPMODE + #echo 226 > /sys/class/gpio/export #QSFP2 LPMODE + #echo 227 > /sys/class/gpio/export #QSFP3 LPMODE + #echo 228 > /sys/class/gpio/export #QSFP4 LPMODE + #echo 229 > /sys/class/gpio/export #QSFP5 LPMODE + #echo 230 > /sys/class/gpio/export #NA + #echo 231 > /sys/class/gpio/export #NA + #echo 232 > /sys/class/gpio/export #QSFP0 MODSEL + #echo 233 > /sys/class/gpio/export #QSFP1 MODSEL + #echo 234 > /sys/class/gpio/export #QSFP2 MODSEL + #echo 235 > /sys/class/gpio/export #QSFP3 MODSEL + #echo 236 > /sys/class/gpio/export #QSFP4 MODSEL + #echo 237 > /sys/class/gpio/export #QSFP5 MODSEL + #echo 238 > /sys/class/gpio/export #NA + #echo 239 > /sys/class/gpio/export #NA + #echo out > /sys/class/gpio/gpio224/direction + #echo out > /sys/class/gpio/gpio225/direction + #echo out > /sys/class/gpio/gpio226/direction + #echo out > /sys/class/gpio/gpio227/direction + #echo out > /sys/class/gpio/gpio228/direction + #echo out > /sys/class/gpio/gpio229/direction + #echo out > /sys/class/gpio/gpio230/direction + #echo out > /sys/class/gpio/gpio231/direction + #echo out > /sys/class/gpio/gpio232/direction + #echo out > /sys/class/gpio/gpio233/direction + #echo out > /sys/class/gpio/gpio234/direction + #echo out > /sys/class/gpio/gpio235/direction + #echo out > /sys/class/gpio/gpio236/direction + #echo out > /sys/class/gpio/gpio237/direction + #echo out > /sys/class/gpio/gpio238/direction + #echo out > /sys/class/gpio/gpio239/direction + + #QSFP RST + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN5_DEVICE}/new_device + for((i=${GPIO_OFFSET}+208;i<=${GPIO_OFFSET}+213;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo low > /sys/class/gpio/gpio${i}/direction + #echo out > /sys/class/gpio/gpio${i}/direction + #echo 0 > /sys/class/gpio/gpio${i}/value + done + for((i=${GPIO_OFFSET}+214;i<=${GPIO_OFFSET}+223;i++)); + do + echo $i > /sys/class/gpio/export + done + + #echo 208 > /sys/class/gpio/export #QSFP0 RST + #echo 209 > /sys/class/gpio/export #QSFP1 RST + #echo 210 > /sys/class/gpio/export #QSFP2 RST + #echo 211 > /sys/class/gpio/export #QSFP3 RST + #echo 212 > /sys/class/gpio/export #QSFP4 RST + #echo 213 > /sys/class/gpio/export #QSFP5 RST + #echo 214 > /sys/class/gpio/export #NA + #echo 215 > /sys/class/gpio/export #NA + #echo 216 > /sys/class/gpio/export #NA + #echo 217 > /sys/class/gpio/export #NA + #echo 218 > /sys/class/gpio/export #NA + #echo 219 > /sys/class/gpio/export #NA + #echo 220 > /sys/class/gpio/export #NA + #echo 221 > /sys/class/gpio/export #NA + #echo 222 > /sys/class/gpio/export #NA + #echo 223 > /sys/class/gpio/export #NA + #echo out > /sys/class/gpio/gpio208/direction + #echo out > /sys/class/gpio/gpio209/direction + #echo out > /sys/class/gpio/gpio210/direction + #echo out > /sys/class/gpio/gpio211/direction + #echo out > /sys/class/gpio/gpio212/direction + #echo out > /sys/class/gpio/gpio213/direction + #echo 1 > /sys/class/gpio/gpio208/active_low + #echo 1 > /sys/class/gpio/gpio209/active_low + #echo 1 > /sys/class/gpio/gpio210/active_low + #echo 1 > /sys/class/gpio/gpio211/active_low + #echo 1 > /sys/class/gpio/gpio212/active_low + #echo 1 > /sys/class/gpio/gpio213/active_low + #echo 0 > /sys/class/gpio/gpio208/value + #echo 0 > /sys/class/gpio/gpio209/value + #echo 0 > /sys/class/gpio/gpio210/value + #echo 0 > /sys/class/gpio/gpio211/value + #echo 0 > /sys/class/gpio/gpio212/value + #echo 0 > /sys/class/gpio/gpio213/value + + + #SFP+ ABS 0-15 + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/new_device + for((i=${GPIO_OFFSET}+192;i<=${GPIO_OFFSET}+207;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 192 > /sys/class/gpio/export + #echo 193 > /sys/class/gpio/export + #echo 194 > /sys/class/gpio/export + #echo 195 > /sys/class/gpio/export + #echo 196 > /sys/class/gpio/export + #echo 197 > /sys/class/gpio/export + #echo 198 > /sys/class/gpio/export + #echo 199 > /sys/class/gpio/export + #echo 200 > /sys/class/gpio/export + #echo 201 > /sys/class/gpio/export + #echo 202 > /sys/class/gpio/export + #echo 203 > /sys/class/gpio/export + #echo 204 > /sys/class/gpio/export + #echo 205 > /sys/class/gpio/export + #echo 206 > /sys/class/gpio/export + #echo 207 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio192/active_low #SFP+00 + #echo 1 > /sys/class/gpio/gpio193/active_low #SFP+01 + #echo 1 > /sys/class/gpio/gpio194/active_low #SFP+02 + #echo 1 > /sys/class/gpio/gpio195/active_low #SFP+03 + #echo 1 > /sys/class/gpio/gpio196/active_low #SFP+04 + #echo 1 > /sys/class/gpio/gpio197/active_low #SFP+05 + #echo 1 > /sys/class/gpio/gpio198/active_low #SFP+06 + #echo 1 > /sys/class/gpio/gpio199/active_low #SFP+07 + #echo 1 > /sys/class/gpio/gpio200/active_low #SFP+08 + #echo 1 > /sys/class/gpio/gpio201/active_low #SFP+09 + #echo 1 > /sys/class/gpio/gpio202/active_low #SFP+10 + #echo 1 > /sys/class/gpio/gpio203/active_low #SFP+11 + #echo 1 > /sys/class/gpio/gpio204/active_low #SFP+12 + #echo 1 > /sys/class/gpio/gpio205/active_low #SFP+13 + #echo 1 > /sys/class/gpio/gpio206/active_low #SFP+14 + #echo 1 > /sys/class/gpio/gpio207/active_low #SFP+15 + + #SFP+ ABS 16-31 + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/new_device + for((i=${GPIO_OFFSET}+176;i<=${GPIO_OFFSET}+191;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 176 > /sys/class/gpio/export + #echo 177 > /sys/class/gpio/export + #echo 178 > /sys/class/gpio/export + #echo 179 > /sys/class/gpio/export + #echo 180 > /sys/class/gpio/export + #echo 181 > /sys/class/gpio/export + #echo 182 > /sys/class/gpio/export + #echo 183 > /sys/class/gpio/export + #echo 184 > /sys/class/gpio/export + #echo 185 > /sys/class/gpio/export + #echo 186 > /sys/class/gpio/export + #echo 187 > /sys/class/gpio/export + #echo 188 > /sys/class/gpio/export + #echo 189 > /sys/class/gpio/export + #echo 190 > /sys/class/gpio/export + #echo 191 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio176/active_low #SFP+16 + #echo 1 > /sys/class/gpio/gpio177/active_low #SFP+17 + #echo 1 > /sys/class/gpio/gpio178/active_low #SFP+18 + #echo 1 > /sys/class/gpio/gpio179/active_low #SFP+19 + #echo 1 > /sys/class/gpio/gpio180/active_low #SFP+20 + #echo 1 > /sys/class/gpio/gpio181/active_low #SFP+21 + #echo 1 > /sys/class/gpio/gpio182/active_low #SFP+22 + #echo 1 > /sys/class/gpio/gpio183/active_low #SFP+23 + #echo 1 > /sys/class/gpio/gpio184/active_low #SFP+24 + #echo 1 > /sys/class/gpio/gpio185/active_low #SFP+25 + #echo 1 > /sys/class/gpio/gpio186/active_low #SFP+26 + #echo 1 > /sys/class/gpio/gpio187/active_low #SFP+27 + #echo 1 > /sys/class/gpio/gpio188/active_low #SFP+28 + #echo 1 > /sys/class/gpio/gpio189/active_low #SFP+29 + #echo 1 > /sys/class/gpio/gpio190/active_low #SFP+30 + #echo 1 > /sys/class/gpio/gpio191/active_low #SFP+31 + + #SFP+ ABS 32-47 + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/new_device + for((i=${GPIO_OFFSET}+160;i<=${GPIO_OFFSET}+175;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 160 > /sys/class/gpio/export + #echo 161 > /sys/class/gpio/export + #echo 162 > /sys/class/gpio/export + #echo 163 > /sys/class/gpio/export + #echo 164 > /sys/class/gpio/export + #echo 165 > /sys/class/gpio/export + #echo 166 > /sys/class/gpio/export + #echo 167 > /sys/class/gpio/export + #echo 168 > /sys/class/gpio/export + #echo 169 > /sys/class/gpio/export + #echo 170 > /sys/class/gpio/export + #echo 171 > /sys/class/gpio/export + #echo 172 > /sys/class/gpio/export + #echo 173 > /sys/class/gpio/export + #echo 174 > /sys/class/gpio/export + #echo 175 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio160/active_low #SFP+32 + #echo 1 > /sys/class/gpio/gpio161/active_low #SFP+33 + #echo 1 > /sys/class/gpio/gpio162/active_low #SFP+34 + #echo 1 > /sys/class/gpio/gpio163/active_low #SFP+35 + #echo 1 > /sys/class/gpio/gpio164/active_low #SFP+36 + #echo 1 > /sys/class/gpio/gpio165/active_low #SFP+37 + #echo 1 > /sys/class/gpio/gpio166/active_low #SFP+38 + #echo 1 > /sys/class/gpio/gpio167/active_low #SFP+39 + #echo 1 > /sys/class/gpio/gpio168/active_low #SFP+40 + #echo 1 > /sys/class/gpio/gpio169/active_low #SFP+41 + #echo 1 > /sys/class/gpio/gpio170/active_low #SFP+42 + #echo 1 > /sys/class/gpio/gpio171/active_low #SFP+43 + #echo 1 > /sys/class/gpio/gpio172/active_low #SFP+44 + #echo 1 > /sys/class/gpio/gpio173/active_low #SFP+45 + #echo 1 > /sys/class/gpio/gpio174/active_low #SFP+46 + #echo 1 > /sys/class/gpio/gpio175/active_low #SFP+47 + +} + +#GPIO DeInit +function _i2c_gpio_deinit { + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN3_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN5_DEVICE}/delete_device + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX2_CHAN0_DEVICE}/delete_device +} + +#I2C CPLD init +function _i2c_cpld_init { + echo "=========================================================" + echo "# Description: I2C CPLD Init..." + echo "=========================================================" + + ## modprobe i2c_cpld + modprobe i2c_cpld + ## Add CPLD device + echo "i2c_cpld 0x33" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}/new_device + + echo "done..." +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C LED TEST..." + echo "=========================================================" + #sys led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x7F + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xBF + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xF7 + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFB + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xDF + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xEF + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFD + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFE + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + _pause 'Check turn off all LEDs and Press [Enter] key to continue...' + echo "done..." +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x20 + dataAddr=0 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT0_15_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT0_15_ABS_GPIO_IDX} + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x20 + dataAddr=1 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT0_15_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT0_15_ABS_GPIO_IDX} + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x21 + dataAddr=0 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT16_31_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT16_31_ABS_GPIO_IDX} + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x21 + dataAddr=1 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT16_31_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT16_31_ABS_GPIO_IDX} + ;; + 33|34|35|36|37|38|39|40) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x22 + dataAddr=0 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT32_47_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT32_47_ABS_GPIO_IDX} + ;; + 41|42|43|44|45|46|47|48) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x22 + dataAddr=1 + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT32_47_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT32_47_ABS_GPIO_IDX} + ;; + 49|50|51|52|53|54) + i2cbus=${NUM_MUX2_CHAN0_DEVICE} + regAddr=0x23 + dataAddr=0 + gpioBase=$((${GPIO_OFFSET}+240-48)) + #gpioBase=$((240 - 48)) + ;; + *) + echo "Please input 1~54" + exit ${FALSE} + ;; + esac +} + +#Get QSFP present +function _i2c_qsfp_status_get { + local status + _qsfp_port_i2c_var_set ${QSFP_PORT} + if [ ${QSFP_PORT} -lt 49 ] && [ ${QSFP_PORT} -gt 0 ]; then + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) % 16 )) ))/value` + elif [ ${QSFP_PORT} -ge 49 ] && [ ${QSFP_PORT} -le 54 ]; then + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1))) ))/value` + fi + + echo "status=$status" +} + +#Get QSFP type +function _i2c_qsfp_type_get { + _get_sfp_eeprom_bus_idx ${QSFP_PORT} + eeprombus=${SFP_EEPROM_BUS_IDX} + eepromAddr=0x50 + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + if [ ${QSFP_PORT} -ge 1 ] && [ ${QSFP_PORT} -le 48 ]; then + echo "sfp" + # 1~48 port is sfp port + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 0 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 2 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 3 -n 1 -e '"%x"') + else + echo "qsfp" + # 49~54 port is qsfp port + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + fi + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + if [ ${QSFP_PORT} -lt 49 ] && [ ${QSFP_PORT} -gt 0 ]; then + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) % 16 )) ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + + _get_sfp_eeprom_bus_idx ${QSFP_PORT} + eeprombus=${SFP_EEPROM_BUS_IDX} + eepromAddr=0x50 + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C + elif [ ${QSFP_PORT} -ge 49 ] && [ ${QSFP_PORT} -le 54 ]; then + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1))) ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + _get_sfp_eeprom_bus_idx ${QSFP_PORT} + eeprombus=${SFP_EEPROM_BUS_IDX} + eepromAddr=0x50 + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi +} + +#PSU EEPROM init +function _i2c_psu_eeprom_init { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Init..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX2_CHAN6_DEVICE}/new_device + + ## PUS(1) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX2_CHAN7_DEVICE}/new_device + + echo "done..." +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX2_CHAN6_DEVICE}-0050/eeprom | hexdump -C + + ## PUS(1) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX2_CHAN7_DEVICE}-0050/eeprom | hexdump -C + + echo "done..." +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom_mb + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX2_CHAN7_DEVICE}-0054/eeprom | hexdump -C + echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + case ${FAN_TRAY} in + 1) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX2_CHAN7_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX2_CHAN7_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX2_CHAN7_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX2_CHAN7_DEVICE} $i2cAddr $ioPort 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Get Board Version and Type +function _i2c_board_type_get { + boardType=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_board_type` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev + +} + +#Get CPLD Version +function _i2c_cpld_version { + cpldRev=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_version` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Get PSU Status +function _i2c_psu_status { + psuPresent=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_abs` + psu1Exist=$(($((($psuPresent) & 0x01))?0:1)) + psu2Exist=$(($((($psuPresent) & 0x02))?0:1)) + psuPwGood=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_good` + psu1PwGood=$(($((($psuPwGood) >> 3 & 0x01))?1:0)) + psu2PwGood=$(($((($psuPwGood) >> 3 & 0x02))?1:0)) + printf "PSU1 Exist:%d PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Get Front Sensor Temperature +function _i2c_front_temp { + #Front MAC + sensors | grep 'Front MAC Temp' -A 1 +} + +#Get Rear Sensor Temperature +function _i2c_rear_temp { + #Rear MAC + sensors | grep 'Rear MAC Temp' -A 1 +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + _set_gpio_offset + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_front_temp" ]; then + _i2c_front_temp + elif [ "${EXEC_FUNC}" == "i2c_rear_temp" ]; then + _i2c_rear_temp + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_temp_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main 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 new file mode 100644 index 000000000000..0a4ba20ab767 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_monitor.sh @@ -0,0 +1,106 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..53}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + # identifier 11 for qsfp, 3 for sfp + if [ "${identifier}" == "11" ] || [ "${identifier}" == "3" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #AOC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to AOC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} aoc $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`sonic-db-cli ASIC_DB HLEN HIDDEN` + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_si_cfg.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_si_cfg.sh new file mode 100644 index 000000000000..6ded3e522bce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/qsfp_si_cfg.sh @@ -0,0 +1,331 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +TYPE=${1} +PORT=${2} + +# port number +MIN_PORT=0 +MAX_PORT=53 + +# INDEX of value field in array +SI_PRE_IDX=1 +SI_POST_IDX=2 +SI_MAIN_IDX=3 +SI_AMP_IDX=4 +SI_DRI_IDX=5 + +# type string +AOC_TYPE="aoc" +DAC_TYPE="dac" + +# si value for bcm command +SI_VAL="" + +# "PRE POST MAIN AMP DRIVERMODE" for each port in array +# TODO: need to change aoc si value when available +xe_aoc_si_value=( + "0x00 0x3e 0x32 0xf 0x0" #port 0 + "0x00 0x3a 0x36 0xf 0x0" #port 1 + "0x00 0x3a 0x36 0xf 0x0" #port 2 + "0x00 0x38 0x38 0xf 0x0" #port 3 + "0x00 0x37 0x39 0xf 0x0" #port 4 + "0x00 0x2e 0x42 0xf 0x0" #port 5 + "0x00 0x33 0x3d 0xf 0x0" #port 6 + "0x00 0x30 0x40 0xc 0x0" #port 7 + "0x00 0x2f 0x43 0xe 0x0" #port 8 + "0x00 0x2d 0x43 0xc 0x0" #port 9 + "0x00 0x2c 0x44 0xc 0x0" #port 10 + "0x00 0x2d 0x43 0xc 0x0" #port 11 + "0x00 0x29 0x47 0xc 0x0" #port 12 + "0x00 0x28 0x48 0xc 0x0" #port 13 + "0x00 0x29 0x47 0xa 0x0" #port 14 + "0x00 0x29 0x47 0xf 0x0" #port 15 + "0x00 0x18 0x58 0x9 0x0" #port 16 + "0x00 0x1d 0x53 0x9 0x0" #port 17 + "0x00 0x1c 0x54 0x9 0x0" #port 18 + "0x00 0x1c 0x54 0x9 0x0" #port 19 + "0x00 0x1c 0x54 0x9 0x0" #port 20 + "0x00 0x1c 0x54 0x9 0x0" #port 21 + "0x00 0x1c 0x54 0x9 0x0" #port 22 + "0x00 0x1c 0x54 0x9 0x0" #port 23 + "0x00 0x1c 0x54 0x8 0x0" #port 24 + "0x00 0x1c 0x54 0x8 0x0" #port 25 + "0x00 0x18 0x58 0x8 0x0" #port 26 + "0x00 0x18 0x58 0x8 0x0" #port 27 + "0x00 0x14 0x5c 0x8 0x0" #port 28 + "0x00 0x19 0x57 0x8 0x0" #port 29 + "0x00 0x19 0x57 0x8 0x0" #port 30 + "0x00 0x19 0x57 0x8 0x0" #port 31 + "0x00 0x19 0x57 0xc 0x0" #port 32 + "0x00 0x20 0x50 0x9 0x0" #port 33 + "0x00 0x21 0x4f 0xc 0x0" #port 34 + "0x00 0x24 0x4c 0xc 0x0" #port 35 + "0x00 0x24 0x4c 0xc 0x0" #port 36 + "0x00 0x24 0x4c 0xc 0x0" #port 37 + "0x00 0x24 0x4c 0xc 0x0" #port 38 + "0x00 0x24 0x4c 0xc 0x0" #port 39 + "0x00 0x28 0x48 0xd 0x0" #port 40 + "0x00 0x28 0x48 0xc 0x0" #port 41 + "0x00 0x29 0x47 0xe 0x0" #port 42 + "0x00 0x29 0x47 0xe 0x0" #port 43 + "0x00 0x29 0x47 0xe 0x0" #port 44 + "0x00 0x28 0x48 0xf 0x0" #port 45 + "0x00 0x28 0x48 0xf 0x0" #port 46 + "0x00 0x30 0x40 0xf 0x0" #port 47 +) + +# TODO: need to change aoc si value when available +ce_aoc_si_value=( + "0x00 0x28 0x48 0xc 0x0" #port 0 lane 0 + "0x00 0x29 0x41 0xc 0x0" #port 0 lane 1 + "0x00 0x29 0x41 0xf 0x0" #port 0 lane 2 + "0x00 0x29 0x41 0xc 0x0" #port 0 lane 3 + "0x00 0x28 0x42 0xc 0x0" #port 1 lane 0 + "0x00 0x3a 0x36 0xf 0x0" #port 1 lane 1 + "0x00 0x2c 0x44 0xc 0x0" #port 1 lane 2 + "0x00 0x2c 0x44 0xc 0x0" #port 1 lane 3 + "0x00 0x2f 0x41 0xc 0x0" #port 2 lane 0 + "0x00 0x38 0x38 0xc 0x0" #port 2 lane 1 + "0x00 0x2f 0x41 0xc 0x0" #port 2 lane 2 + "0x00 0x30 0x40 0xc 0x0" #port 2 lane 3 + "0x00 0x30 0x40 0xc 0x0" #port 3 lane 0 + "0x00 0x3f 0x31 0xf 0x0" #port 3 lane 1 + "0x00 0x31 0x3f 0xc 0x0" #port 3 lane 2 + "0x00 0x30 0x40 0xa 0x0" #port 3 lane 3 + "0x00 0x30 0x40 0xc 0x0" #port 4 lane 0 + "0x00 0x31 0x3f 0xf 0x0" #port 4 lane 1 + "0x00 0x2f 0x41 0xc 0x0" #port 4 lane 2 + "0x00 0x2e 0x42 0xc 0x0" #port 4 lane 3 + "0x00 0x30 0x40 0xe 0x0" #port 5 lane 0 + "0x00 0x3f 0x31 0xf 0x0" #port 5 lane 1 + "0x00 0x38 0x38 0xf 0x0" #port 5 lane 2 + "0x00 0x3f 0x31 0xf 0x0" #port 5 lane 3 +) + +xe_dac_si_value=( + "0x00 0x3e 0x32 0xf 0x0" #port 0 + "0x00 0x3a 0x36 0xf 0x0" #port 1 + "0x00 0x3a 0x36 0xf 0x0" #port 2 + "0x00 0x38 0x38 0xf 0x0" #port 3 + "0x00 0x37 0x39 0xf 0x0" #port 4 + "0x00 0x2e 0x42 0xf 0x0" #port 5 + "0x00 0x33 0x3d 0xf 0x0" #port 6 + "0x00 0x30 0x40 0xc 0x0" #port 7 + "0x00 0x2f 0x43 0xe 0x0" #port 8 + "0x00 0x2d 0x43 0xc 0x0" #port 9 + "0x00 0x2c 0x44 0xc 0x0" #port 10 + "0x00 0x2d 0x43 0xc 0x0" #port 11 + "0x00 0x29 0x47 0xc 0x0" #port 12 + "0x00 0x28 0x48 0xc 0x0" #port 13 + "0x00 0x29 0x47 0xa 0x0" #port 14 + "0x00 0x29 0x47 0xf 0x0" #port 15 + "0x00 0x18 0x58 0x9 0x0" #port 16 + "0x00 0x1d 0x53 0x9 0x0" #port 17 + "0x00 0x1c 0x54 0x9 0x0" #port 18 + "0x00 0x1c 0x54 0x9 0x0" #port 19 + "0x00 0x1c 0x54 0x9 0x0" #port 20 + "0x00 0x1c 0x54 0x9 0x0" #port 21 + "0x00 0x1c 0x54 0x9 0x0" #port 22 + "0x00 0x1c 0x54 0x9 0x0" #port 23 + "0x00 0x1c 0x54 0x8 0x0" #port 24 + "0x00 0x1c 0x54 0x8 0x0" #port 25 + "0x00 0x18 0x58 0x8 0x0" #port 26 + "0x00 0x18 0x58 0x8 0x0" #port 27 + "0x00 0x14 0x5c 0x8 0x0" #port 28 + "0x00 0x19 0x57 0x8 0x0" #port 29 + "0x00 0x19 0x57 0x8 0x0" #port 30 + "0x00 0x19 0x57 0x8 0x0" #port 31 + "0x00 0x19 0x57 0xc 0x0" #port 32 + "0x00 0x20 0x50 0x9 0x0" #port 33 + "0x00 0x21 0x4f 0xc 0x0" #port 34 + "0x00 0x24 0x4c 0xc 0x0" #port 35 + "0x00 0x24 0x4c 0xc 0x0" #port 36 + "0x00 0x24 0x4c 0xc 0x0" #port 37 + "0x00 0x24 0x4c 0xc 0x0" #port 38 + "0x00 0x24 0x4c 0xc 0x0" #port 39 + "0x00 0x28 0x48 0xd 0x0" #port 40 + "0x00 0x28 0x48 0xc 0x0" #port 41 + "0x00 0x29 0x47 0xe 0x0" #port 42 + "0x00 0x29 0x47 0xe 0x0" #port 43 + "0x00 0x29 0x47 0xe 0x0" #port 44 + "0x00 0x28 0x48 0xf 0x0" #port 45 + "0x00 0x28 0x48 0xf 0x0" #port 46 + "0x00 0x30 0x40 0xf 0x0" #port 47 +) + +ce_dac_si_value=( + "0x00 0x28 0x48 0xc 0x0" #port 0 lane 0 + "0x00 0x29 0x41 0xc 0x0" #port 0 lane 1 + "0x00 0x29 0x41 0xf 0x0" #port 0 lane 2 + "0x00 0x29 0x41 0xc 0x0" #port 0 lane 3 + "0x00 0x28 0x42 0xc 0x0" #port 1 lane 0 + "0x00 0x3a 0x36 0xf 0x0" #port 1 lane 1 + "0x00 0x2c 0x44 0xc 0x0" #port 1 lane 2 + "0x00 0x2c 0x44 0xc 0x0" #port 1 lane 3 + "0x00 0x2f 0x41 0xc 0x0" #port 2 lane 0 + "0x00 0x38 0x38 0xc 0x0" #port 2 lane 1 + "0x00 0x2f 0x41 0xc 0x0" #port 2 lane 2 + "0x00 0x30 0x40 0xc 0x0" #port 2 lane 3 + "0x00 0x30 0x40 0xc 0x0" #port 3 lane 0 + "0x00 0x3f 0x31 0xf 0x0" #port 3 lane 1 + "0x00 0x31 0x3f 0xc 0x0" #port 3 lane 2 + "0x00 0x30 0x40 0xa 0x0" #port 3 lane 3 + "0x00 0x30 0x40 0xc 0x0" #port 4 lane 0 + "0x00 0x31 0x3f 0xf 0x0" #port 4 lane 1 + "0x00 0x2f 0x41 0xc 0x0" #port 4 lane 2 + "0x00 0x2e 0x42 0xc 0x0" #port 4 lane 3 + "0x00 0x30 0x40 0xe 0x0" #port 5 lane 0 + "0x00 0x3f 0x31 0xf 0x0" #port 5 lane 1 + "0x00 0x38 0x38 0xf 0x0" #port 5 lane 2 + "0x00 0x3f 0x31 0xf 0x0" #port 5 lane 3 +) + +#get field value in si value array for xe port +function get_xe_si { + local port=$1 + local field=$2 + local type=$3 + local index=$port + if [ "$type" == "${AOC_TYPE}" ]; then + SI_VAL=$(echo "${xe_aoc_si_value[$index]}" | awk '{print $'$field'}') + else + SI_VAL=$(echo "${xe_dac_si_value[$index]}" | awk '{print $'$field'}') + fi +} + +#get field value in si value array for ce port +function get_ce_si { + local port=$1 + local lane=$2 + local field=$3 + local type=$4 + index=$(( (${port}-1)*4+${lane} )) + if [ "$type" == "${AOC_TYPE}" ]; then + SI_VAL=$(echo "${ce_aoc_si_value[$index]}" | awk '{print $'$field'}') + else + SI_VAL=$(echo "${ce_dac_si_value[$index]}" | awk '{print $'$field'}') + fi +} + +# set si value for xe port +function _qsfp_xe_si_set { + # convert PORT to xe port index + local xe_port=$PORT + # generate command for SI PRE value + get_xe_si $xe_port $SI_PRE_IDX $TYPE + local pre_cmd="phy xe${xe_port} CL93N72_UT_CTL2r CL93N72_TXFIR_PRE=${SI_VAL}" + # generate command for SI POST value + get_xe_si $xe_port $SI_POST_IDX $TYPE + local post_cmd="phy xe${xe_port} CL93N72_UT_CTL2r CL93N72_TXFIR_POST=${SI_VAL}" + # generate command for SI MAIN value + get_xe_si $xe_port $SI_MAIN_IDX $TYPE + local main_cmd="phy xe${xe_port} CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=${SI_VAL}" + # generate command for SI AMP CONTROL value + get_xe_si $xe_port $SI_AMP_IDX $TYPE + local amp_val=$SI_VAL + get_xe_si $xe_port $SI_DRI_IDX $TYPE + local dri_val=$SI_VAL + local amp_cmd="phy xe${xe_port} AMS_TX_CTL2r AMS_TX_AMP_CTL=${amp_val} AMS_TX_DRIVERMODE=${dri_val}" + # apply bcmcmd + bcmcmd "${pre_cmd};${post_cmd};${main_cmd};${amp_cmd}" +} + +# set aoc si value for ce port +function _qsfp_ce_si_set { + # convert PORT to ce port index + local ce_port=$(( $PORT - 48 )) + for lane in {0..3}; + do + # generate command for SI PRE value + get_ce_si $ce_port $lane $SI_PRE_IDX $TYPE + local pre_cmd="phy ce${ce_port} CL93N72_UT_CTL2r.${lane} CL93N72_TXFIR_PRE=${SI_VAL}" + # generate command for SI POST value + get_ce_si $ce_port $lane $SI_POST_IDX $TYPE + local post_cmd="phy ce${ce_port} CL93N72_UT_CTL2r.${lane} CL93N72_TXFIR_POST=${SI_VAL}" + # generate command for SI MAIN value + get_ce_si $ce_port $lane $SI_MAIN_IDX $TYPE + local main_cmd="phy ce${ce_port} CL93N72_UT_CTL3r.${lane} CL93N72_TXFIR_MAIN=${SI_VAL}" + # generate command for SI AMP CONTROL value + get_ce_si $ce_port $lane $SI_AMP_IDX $TYPE + local amp_val=$SI_VAL + get_ce_si $ce_port $lane $SI_AMP_IDX $TYPE + local dri_val=$SI_VAL + local amp_cmd="phy ce${ce_port} AMS_TX_CTL2r.${lane} AMS_TX_AMP_CTL=${amp_val} AMS_TX_DRIVERMODE=${dri_val}" + # apply bcmcmd + bcmcmd "${pre_cmd};${post_cmd};${main_cmd};${amp_cmd}" + done +} + +#QSFP SI value set +function _qsfp_si_set { + if [[ $PORT -le 47 && $PORT -ge 0 ]]; then + # xe port + _qsfp_xe_si_set + else + # ce port + _qsfp_ce_si_set + fi +} + +function _util_input_check { + # input parameter validation + if [[ $1 -lt $2 || $1 -gt $3 ]]; then + echo "Please input number $2~$3" + exit + fi +} + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} ${AOC_TYPE} [${MIN_PORT}-${MAX_PORT}]" + echo " : ${0} ${DAC_TYPE} [${MIN_PORT}-${MAX_PORT}]" + echo "----------------------------------------------------" +} + +#Main Function +function _main { + + # TODO: remove after SI value ready + #exit ${TRUE} + + if [ -z $PORT ]; then + _help + exit ${FALSE} + fi + + if [ "${TYPE}" == "help" ]; then + _help + elif [ "${TYPE}" == "${AOC_TYPE}" ] || [ "${TYPE}" == "${DAC_TYPE}" ]; then + _util_input_check "$PORT" "$MIN_PORT" "$MAX_PORT" + _qsfp_si_set + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/s8900_54xc_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/s8900_54xc_monitor.sh new file mode 100755 index 000000000000..974da6d5001f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-54xc/utils/s8900_54xc_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/README.md b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/README.md new file mode 100644 index 000000000000..28f395216e3c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/README.md @@ -0,0 +1,185 @@ +# Ingrasys S8900-64XC Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S8900-64XC is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S8900-64XC platform. + +### I2C i801 + +The I2C i801 on Ingrasys S8900-64XC can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S8900-64XC. + +### I2C iSMT + +The I2C iSMT module on S8900-64XC can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S8900-64XC. + +### I2C PCA9548 +The PCA9548 module on S8900-64XC can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S8900-64XC. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S8900-64XC platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s8900-64xc package is installed on the S8900-64XC, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/Makefile b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/Makefile new file mode 100644 index 000000000000..bf7d4baed71b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/Makefile @@ -0,0 +1,4 @@ +#ccflags-y += -DDEBUG +obj-m := eeprom_mb.o +obj-m+= qsfp_cpld.o +obj-m+= i2c_cpld.o diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/eeprom_mb.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/eeprom_mb.c new file mode 100644 index 000000000000..0886cad58eb3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/eeprom_mb.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys S8900 Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.c new file mode 100644 index 000000000000..626c63177b50 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.c @@ -0,0 +1,448 @@ +/* + * S9100-32X I2C CPLD driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c_cpld.h" + +#ifdef DEBUG + #define DEBUG_PRINT(fmt, args...) \ + printk(KERN_INFO "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define I2C_READ_BYTE_DATA(ret, lock, i2c_client, reg) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_read_byte_data(i2c_client, reg); \ + mutex_unlock(lock); \ +} +#define I2C_WRITE_BYTE_DATA(ret, lock, i2c_client, reg, val) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_write_byte_data(i2c_client, reg, val); \ + mutex_unlock(lock); \ +} + +/* CPLD sysfs attributes index */ +enum i2c_cpld_sysfs_attributes { + CPLD_ACCESS_REG, + CPLD_REGISTER_VAL, + CPLD_PORT_START, + CPLD_PORTS, + CPLD_VERSION, + CPLD_ID, + CPLD_BOARD_TYPE, + CPLD_EXT_BOARD_TYPE, + CPLD_PW_GOOD, + CPLD_PW_ABS, +}; + +/* CPLD sysfs attributes hook functions */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, char *buf); + +static LIST_HEAD(cpld_client_list); /* client list for cpld */ +static struct mutex list_lock; /* mutex for client list */ + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +struct cpld_data { + int index; /* CPLD index */ + struct mutex access_lock; /* mutex for cpld access */ + u8 access_reg; /* register to access */ +}; + +/* CPLD device id and data */ +static const struct i2c_device_id i2c_cpld_id[] = { + { "i2c_cpld", i2c_cpld }, + {} +}; + +/* Addresses scanned for i2c_cpld */ +static const unsigned short cpld_i2c_addr[] = { 0x33, I2C_CLIENT_END }; +/* platform sysfs object */ +extern struct kobject *s9230_64x_kobj; + + +/* define all support register access of cpld in attribute */ +static SENSOR_DEVICE_ATTR(cpld_access_register, S_IWUSR | S_IRUGO, + read_access_register, write_access_register, CPLD_ACCESS_REG); +static SENSOR_DEVICE_ATTR(cpld_register_value, S_IWUSR | S_IRUGO, + read_register_value, write_register_value, CPLD_REGISTER_VAL); +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, + read_cpld_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(cpld_board_type, S_IRUGO, + read_board_type, NULL, CPLD_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_ext_board_type, S_IRUGO, + read_ext_board_type, NULL, CPLD_EXT_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_pw_good, S_IRUGO, + read_pw_good, NULL, CPLD_PW_GOOD); +static SENSOR_DEVICE_ATTR(cpld_pw_abs, S_IRUGO, + read_pw_abs, NULL, CPLD_PW_ABS); + + +/* define support attributes of cpldx , total 5 */ +/* cpld 1 */ +static struct attribute *i2c_cpld_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_ext_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_pw_good.dev_attr.attr, + &sensor_dev_attr_cpld_pw_abs.dev_attr.attr, + NULL +}; + +/* cpld 1 attributes group */ +static const struct attribute_group i2c_cpld_group = { + .attrs = i2c_cpld_attributes, +}; + +/* read access register from cpld data */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + + return sprintf(buf, "0x%x\n", reg); +} + +/* write access register to cpld data */ +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + + if (kstrtou8(buf, 0, ®) < 0) + return -EINVAL; + + data->access_reg = reg; + return count; +} + +/* read the value of access register in cpld data */ +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + int reg_val; + + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + + if (reg_val < 0) + return -1; + + return sprintf(buf, "0x%x\n", reg_val); +} + +/* wrtie the value to access register in cpld data */ +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ret = -EIO; + u8 reg = data->access_reg; + u8 reg_val; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, client, reg, reg_val); + + return count; +} + +/* get cpdl version register value */ +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_VERSION) { + reg = CPLD_VERSION_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get board type register value */ +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BOARD_TYPE) { + reg = CPLD_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_EXT_BOARD_TYPE) { + reg = CPLD_EXT_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_GOOD) { + reg = CPLD_PW_GOOD_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_ABS) { + reg = CPLD_PW_ABS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* add valid cpld client to list */ +static void i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = NULL; + + node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + if (!node) { + dev_info(&client->dev, + "Can't allocate cpld_client_node for index %d\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +/* remove exist cpld client in list */ +static void i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + mutex_unlock(&list_lock); +} + +/* cpld drvier probe */ +static int i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* init cpld data for client */ + i2c_set_clientdata(client, data); + mutex_init(&data->access_lock); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_info(&client->dev, + "i2c_check_functionality failed (0x%x)\n", + client->addr); + status = -EIO; + goto exit; + } + + + status = sysfs_create_group(&client->dev.kobj,&i2c_cpld_group); + + if (status) + goto exit; + + dev_info(&client->dev, "chip found\n"); + + /* add probe chip to client list */ + i2c_cpld_add_client(client); + + return 0; +exit: + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + return status; +} + +/* cpld drvier remove */ +static int i2c_cpld_remove(struct i2c_client *client) +{ + + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + + i2c_cpld_remove_client(client); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, i2c_cpld_id); + +static struct i2c_driver i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "i2c_cpld", + }, + .probe = i2c_cpld_probe, + .remove = i2c_cpld_remove, + .id_table = i2c_cpld_id, + .address_list = cpld_i2c_addr, +}; + +static int __init i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&i2c_cpld_driver); +} + +static void __exit i2c_cpld_exit(void) +{ + i2c_del_driver(&i2c_cpld_driver); +} + +MODULE_AUTHOR("Wade He "); +MODULE_DESCRIPTION("Ingrasys S9100-32X Platform i2c cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_cpld_init); +module_exit(i2c_cpld_exit); + + + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.h b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.h new file mode 100644 index 000000000000..e103b05c717a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/i2c_cpld.h @@ -0,0 +1,197 @@ +/* + * + * S9100-32X I2C CPLD driver header file + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef I2C_CPLD_H +#define I2C_CPLD_H + +// remove debug before release +#define DEBUG + +/* CPLD device index value */ +enum cpld_id { + i2c_cpld +}; + +/* port number on CPLD */ +#define CPLD_1_PORT_NUM 12 +#define CPLD_2_PORT_NUM 13 + +/* QSFP port number */ +#define QSFP_MAX_PORT_NUM 64 +#define QSFP_MIN_PORT_NUM 1 + +/* SFP+ port number */ +#define SFP_MAX_PORT_NUM 2 +#define SFP_MIN_PORT_NUM 1 + + +/* CPLD registers */ +#define CPLD_BOARD_TYPE_REG 0x0 +#define CPLD_EXT_BOARD_TYPE_REG 0x7 +#define CPLD_VERSION_REG 0x1 +#define CPLD_PW_GOOD_REG 0x2 +#define CPLD_PW_ABS_REG 0x3 + + +/* bit definition for register value */ + +enum CPLD_RESET_CONTROL_BITS { + CPLD_RESET_CONTROL_SWRST_BIT, + CPLD_RESET_CONTROL_CP2104RST_BIT, + CPLD_RESET_CONTROL_82P33814RST_BIT, + CPLD_RESET_CONTROL_BMCRST_BIT, +}; + +/* bit field structure for register value */ +struct cpld_reg_board_type_t { + u8 build_rev:2; + u8 hw_rev:2; + u8 board_id:4; +}; + +struct cpld_reg_version_t { + u8 revision:6; + u8 release:1; + u8 reserve:1; +}; + +struct cpld_reg_pw_good_t { + u8 reserve1:3; + u8 psu1:1; + u8 psu2:1; + u8 reserve2:3; +}; + +struct cpld_reg_pw_abs_t { + u8 psu1:1; + u8 psu2:1; + u8 reserve:6; +}; + +/* common manipulation */ +#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u) +#define READ_BIT(val, bit) ((0u == (val & (1<bf_name) +#define READ_BF_1(bf_struct, val, bf_name, bf_value) \ + bf_struct bf; \ + bf.data = val; \ + bf_value = bf.bf_name +#define BOARD_TYPE_BUILD_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, build_rev, res) +#define BOARD_TYPE_HW_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, hw_rev, res) +#define BOARD_TYPE_BOARD_ID_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, board_id, res) +#define CPLD_VERSION_REV_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, revision, res) +#define CPLD_VERSION_REL_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, release, res) +#define CPLD_PSU1_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu1, res) +#define CPLD_PSU2_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu2, res) +#define CPLD_PSU1_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu1, res) +#define CPLD_PSU2_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu2, res) +/* QSFP/SFP registers manipulation */ +#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \ +{ \ + if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \ + cpld_index = cpld1; \ + cpld_port = qsfp_port - 1; \ + } else if (CPLD_1_PORT_NUM < qsfp_port \ + && qsfp_port <= QSFP_MAX_PORT_NUM) { \ + cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \ + / CPLD_2_PORT_NUM; \ + cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \ + CPLD_2_PORT_NUM; \ + } else { \ + cpld_index = 0; \ + cpld_port = 0; \ + } \ +} +#define SFP_TO_CPLD_IDX(sfp_port, cpld_index) \ + (cpld_index = sfp_port - SFP_MIN_PORT_NUM) +#define QSFP_PORT_STATUS_REG(cpld_port) \ + (CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port) +#define QSFP_PORT_CONFIG_REG(cpld_port) \ + (CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port) +#define QSFP_PORT_INT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT) +#define QSFP_PORT_ABS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT) +#define QSFP_PORT_RESET_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_RESET_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define SFP_PORT_PRESENT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_PRESENT_BIT) + + #define SFP_PORT_TXFAULT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_TXFAULT_BIT) + #define SFP_PORT_RXLOS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_RXLOS_BIT) + #define SFP_PORT_TXDIS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TXDIS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_TXDIS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_RS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) + +/* CPLD access functions */ +extern int i2c_cpld_get_qsfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_qsfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val); +extern int i2c_cpld_get_sfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_sfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_sfp_port_config_val(u8 port_num, u8 reg_val); +extern u8 fp_port_to_phy_port(u8 fp_port); +#endif + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/qsfp_cpld.c b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/qsfp_cpld.c new file mode 100644 index 000000000000..66ae8d558507 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/modules/qsfp_cpld.c @@ -0,0 +1,1771 @@ +/* + * S8900-64XC QSFP CPLD driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef DEBUG + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define ERROR_MSG(fmt, args...) \ + printk(KERN_ERR "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) + + + + +#define SFF_8436_MMAP_SIZE (256) +#define EEPROM_SIZE (5 * 128) /* 640 byte eeprom */ +#define EEPROM_PAGE_SIZE (128) +#define EEPROM_DEFAULT_PAGE (0) +#define I2C_RW_RETRY_COUNT (3) +#define I2C_RW_RETRY_INTERVAL (100) /* ms */ +#define USE_I2C_BLOCK_READ (1) + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) + +#define SFF_8436_PAGE_PROV_ADDR (0xC3) /* Memory Page 01/02 Provided */ +#define SFF_8436_PAGE_01_PRESENT (1 << 6) /* Memory Page 01 present */ +#define SFF_8436_PAGE_02_PRESENT (1 << 7) /* Memory Page 02 present */ +#define SFF_8436_PAGE_SELECT_ADDR (0x7F) +#define SFF_8436_STATUS_ADDR (0x02) +#define SFF_8436_STATUS_PAGE_03_PRESENT_L (1 << 2) /* Flat Memory:0-Paging, 1-Page 0 only */ + +#define S8900_64XC_MUX_BASE_NR 1 +#define S8900_64XC_SFP_EEPROM_BASE_NR 2 +#define CPLD_DEVICE_NUM 3 +#define SFP_CPLD_DEVICE_NUM 2 +#define QSFP_EEPROM_DEVICE_NUM 3 +#define TOTAL_PORT_NUM 64 +#define CPLD_MUX_OFFSET 24 +#define SFP_EEPROM_DEV_NUM 3 +#define SFP_EEPROM_NAME_LEN 16 +/* CPLD registers */ +#define CPLD_REG_REV 0x01 +#define CPLD_REG_ID 0x02 +#define CPLD_MUX_REG 0x4a + +/* QSFP signal bit in register */ +#define BIT_RST 0 +#define BIT_LPM 2 +#define BIT_INT 0 +#define BIT_ABS 1 +#define BIT_ABS_2 5 + +static ssize_t sfp_eeprom_read(struct i2c_client *, loff_t, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, loff_t, const char *,int); + + +enum port_numbers { + sfp1, sfp2, sfp3, sfp4, sfp5, sfp6, sfp7, sfp8, + sfp9, sfp10, sfp11, sfp12, sfp13, sfp14, sfp15, sfp16, + sfp17, sfp18, sfp19, sfp20, sfp21, sfp22, sfp23, sfp24, + sfp25, sfp26, sfp27, sfp28, sfp29, sfp30, sfp31, sfp32, + sfp33, sfp34, sfp35, sfp36, sfp37, sfp38, sfp39, sfp40, + sfp41, sfp42, sfp43, sfp44, sfp45, sfp46, sfp47, sfp48, + qsfp49, qsfp50, qsfp51, qsfp52, qsfp53, qsfp54, qsfp55, qsfp56, + qsfp57, qsfp58, qsfp59, qsfp60, qsfp61, qsfp62, qsfp63, qsfp64 +}; + +static const struct platform_device_id qsfp_device_id[] = { + {"sfp1", sfp1}, {"sfp2", sfp2}, {"sfp3", sfp3}, {"sfp4", sfp4}, + {"sfp5", sfp5}, {"sfp6", sfp6}, {"sfp7", sfp7}, {"sfp8", sfp8}, + {"sfp9", sfp9}, {"sfp10", sfp10}, {"sfp11", sfp11}, {"sfp12", sfp12}, + {"sfp13", sfp13}, {"sfp14", sfp14}, {"sfp15", sfp15}, {"sfp16", sfp16}, + {"sfp17", sfp17}, {"sfp18", sfp18}, {"sfp19", sfp19}, {"sfp20", sfp20}, + {"sfp21", sfp21}, {"sfp22", sfp22}, {"sfp23", sfp23}, {"sfp24", sfp24}, + {"sfp25", sfp25}, {"sfp26", sfp26}, {"sfp27", sfp27}, {"sfp28", sfp28}, + {"sfp29", sfp29}, {"sfp30", sfp30}, {"sfp31", sfp31}, {"sfp32", sfp32}, + {"sfp33", sfp33}, {"sfp34", sfp34}, {"sfp35", sfp35}, {"sfp36", sfp36}, + {"sfp37", sfp37}, {"sfp38", sfp38}, {"sfp39", sfp39}, {"sfp40", sfp40}, + {"sfp41", sfp41}, {"sfp42", sfp42}, {"sfp43", sfp43}, {"sfp44", sfp44}, + {"sfp45", sfp45}, {"sfp46", sfp46}, {"sfp47", sfp47}, {"sfp48", sfp48}, + {"qsfp49", qsfp49}, {"qsfp50", qsfp50}, {"qsfp51", qsfp51}, {"qsfp52", qsfp52}, + {"qsfp53", qsfp53}, {"qsfp54", qsfp54}, {"qsfp55", qsfp55}, {"qsfp56", qsfp56}, + {"qsfp57", qsfp57}, {"qsfp58", qsfp58}, {"qsfp59", qsfp59}, {"qsfp60", qsfp60}, + {"qsfp61", qsfp61}, {"qsfp62", qsfp62}, {"qsfp63", qsfp63}, {"qsfp64", qsfp64}, + {} +}; +MODULE_DEVICE_TABLE(platform, qsfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +typedef enum eeprom_operation_e { + EEPROM_READ, + EEPROM_WRITE +} eeprom_operation_t; + +/* + * Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss + */ + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + TX_DISABLE_ALL, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL, +}; + +static void device_release(struct device *dev) +{ + return; +} + +/* + * S8900-64XC CPLD register addresses + */ +static const int int_abs_reg[CPLD_DEVICE_NUM][2]= { + {0x20, 0x31}, + {0x20, 0x31}, + {0x20, 0x2F}, +}; + +static const int rst_lp_reg[CPLD_DEVICE_NUM][2]= { + {0xFF, 0xFF}, /*dummy*/ + {0xFF, 0xFF}, /*dummy*/ + {0x30, 0x3F}, +}; + +/* + * S8900-64XC CPLD + */ + +enum cpld_type { + cpld_1, + cpld_2, + cpld_3, +}; + +enum qsfp_signal { + sig_int, + sig_abs, + sig_rst, + sig_lpm +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +struct sfp_platform_data { + int reg_addr; + int parent; + int cpld_reg; + struct i2c_client *client; +}; + +static struct cpld_platform_data s8900_64xc_cpld_platform_data[] = { + [cpld_1] = { + .reg_addr = 0x33, + }, + + [cpld_2] = { + .reg_addr = 0x33, + }, + + [cpld_3] = { + .reg_addr = 0x33, + } +}; + +static struct sfp_platform_data s8900_64xc_sfp_platform_data[] = { + [sfp1] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x01, + }, + + [sfp2] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x02, + }, + + [sfp3] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x03, + }, + [sfp4] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x04, + }, + + [sfp5] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x05, + }, + + [sfp6] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x06, + }, + [sfp7] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x07, + }, + + [sfp8] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x08, + }, + + [sfp9] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x09, + }, + [sfp10] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0A, + }, + + [sfp11] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0B, + }, + + [sfp12] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0C, + }, + [sfp13] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0D, + }, + + [sfp14] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0E, + }, + + [sfp15] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x0F, + }, + [sfp16] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x10, + }, + + [sfp17] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x11, + }, + + [sfp18] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x12, + }, + [sfp19] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x13, + }, + + [sfp20] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x14, + }, + + [sfp21] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x15, + }, + [sfp22] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x16, + }, + + [sfp23] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x17, + }, + + [sfp24] = { + .reg_addr = 0x50, + .parent = 2, + .cpld_reg = 0x18, + }, + [sfp25] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x01, + }, + + [sfp26] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x02, + }, + [sfp27] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x03, + }, + + [sfp28] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x04, + }, + + [sfp29] = { + .reg_addr = 0x50, + + .parent = 3, + .cpld_reg = 0x05, + }, + [sfp30] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x06, + }, + [sfp31] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x07, + }, + [sfp32] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x08, + }, + [sfp33] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x09, + }, + [sfp34] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0A, + }, + [sfp35] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0B, + }, + [sfp36] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0C, + }, + [sfp37] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0D, + }, + [sfp38] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0E, + }, + [sfp39] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x0F, + }, + [sfp40] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x10, + }, + [sfp41] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x11, + }, + [sfp42] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x12, + }, + [sfp43] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x13, + }, + [sfp44] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x14, + }, + [sfp45] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x15, + }, + [sfp46] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x16, + }, + [sfp47] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x17, + }, + [sfp48] = { + .reg_addr = 0x50, + .parent = 3, + .cpld_reg = 0x18, + }, + [qsfp49] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x01, + }, + [qsfp50] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x02, + }, + [qsfp51] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x03, + }, + [qsfp52] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x04, + }, + [qsfp53] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x05, + }, + [qsfp54] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x06, + }, + [qsfp55] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x07, + }, + [qsfp56] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x08, + }, + [qsfp57] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x09, + }, + [qsfp58] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0A, + }, + [qsfp59] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0B, + }, + [qsfp60] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0C, + }, + [qsfp61] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0D, + }, + [qsfp62] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0E, + }, + [qsfp63] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x0F, + }, + [qsfp64] = { + .reg_addr = 0x50, + .parent = 4, + .cpld_reg = 0x10, + } +}; + +static struct platform_device s8900_64xc_cpld = { + .name = "ingrasys-s8900-64xc-cpld", + .id = 0, + .dev = { + .platform_data = s8900_64xc_cpld_platform_data, + .release = device_release + }, +}; + +static struct platform_device s8900_64xc_sfp = { + .name = "ingrasys-s8900-64xc-sfp", + .id = 0, + .dev = { + .platform_data = s8900_64xc_sfp_platform_data, + .release = device_release + }, +}; + +/* + * S8900-64XC I2C DEVICES + */ + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; + +/* module_platform_driver */ +static ssize_t +get_prs_cpld_reg(struct device *dev, + struct device_attribute *devattr, + char *buf, int signal) +{ + int ret; + u64 data = 0; + u64 shift = 0; + int i = 0; + int j = 0; + int port = 0; + int bit = 0; + int bit_mask = 0; + int bit_mask_2 = 0; + int (*reg)[CPLD_DEVICE_NUM][2]; + struct cpld_platform_data *pdata = NULL; + + pdata = dev->platform_data; + + switch(signal) { + case sig_int: + bit = BIT_INT; + reg = (typeof(reg)) &int_abs_reg; + break; + case sig_abs: + bit = BIT_ABS; + reg = (typeof(reg)) &int_abs_reg; + break; + default: + return sprintf(buf, "signal/na"); + } + bit_mask = 0x1 << bit; + bit_mask_2 = 0x1 << BIT_ABS_2; + + for (i=0; i= 0x2a && j <= 0x2f && i < SFP_CPLD_DEVICE_NUM) { + continue; + } + ret = i2c_smbus_read_byte_data(pdata[i].client, j); + if (ret < 0) { + return sprintf((char *)buf, "i2c_smbus_read_byte_data/na"); + } + shift = ((u64) ((ret & bit_mask) >> bit)) << port; + data |= shift; + DEBUG_PRINT("port=%d, shift=0x%016llx, ret=%x, bit_mask=%08x, bit=%08x, data=0x%016llx\n", port, shift, ret, bit_mask, bit, data); + /* CPLD2 and CPLD3 have BIT 1 and BIT 5 for present */ + if (i < SFP_CPLD_DEVICE_NUM) { + port++; + shift = ((u64) ((ret & bit_mask_2) >> BIT_ABS_2)) << port; + data |= shift; + DEBUG_PRINT("port=%d, shift=0x%016llx, ret=%x, bit_mask_2=0x%x, bit=%x, data=0x%016llx\n", port, shift, ret, bit_mask_2, bit, data); + } + + port++; + } + } + + return sprintf((char *)buf, "0x%016llx\n", data); +} + +/* module_platform_driver */ +static ssize_t +get_rst_lp_cpld_reg(struct device *dev, + struct device_attribute *devattr, + char *buf, int signal) +{ + int ret; + u64 data = 0; + u64 shift = 0; + int i = 0; + int j = 0; + int port = 0; + int bit = 0; + int bit_mask = 0; + int (*reg)[CPLD_DEVICE_NUM][2]; + struct cpld_platform_data *pdata = NULL; + + pdata = dev->platform_data; + + switch(signal) { + case sig_rst: + bit = BIT_RST; + reg = (typeof(reg)) &rst_lp_reg; + break; + case sig_lpm: + bit = BIT_LPM; + reg = (typeof(reg)) &rst_lp_reg; + break; + default: + return sprintf(buf, "na"); + } + bit_mask = 0x1 << bit; + + for (i=2; i> bit)) << port; + data |= shift; + port++; + } + } + + return sprintf(buf, "0x%04llx\n", data); +} + +static ssize_t +set_rst_lp_cpld_reg(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count, int signal) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + u8 current_reg_val = 0; + u8 new_reg_val = 0; + int value; + int i = 0; + int j = 0; + int port = 0; + int ret = 0; + int bit = 0; + int (*reg)[CPLD_DEVICE_NUM][2]; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + switch(signal) { + case sig_rst: + bit = BIT_RST; + reg = (typeof(reg)) &rst_lp_reg; + break; + case sig_lpm: + bit = BIT_LPM; + reg = (typeof(reg)) &rst_lp_reg; + break; + default: + return sprintf((char *)buf, "signal/na"); + } + + for (i=2; i> port) & 0x1; + + //set value on bit N of new_reg_val + if (value > 0) { + new_reg_val = current_reg_val | (u8) (0x1 << bit); + } else { + new_reg_val = current_reg_val & (u8) ~(0x1 << bit); + } + //write reg value if changed + if (current_reg_val != new_reg_val) { + ret = i2c_smbus_write_byte_data(pdata[i].client, j, + (u8)(new_reg_val)); + if (ret < 0){ + return ret; + } + } + port++; + } + } + + return count; +} + +static ssize_t +get_lpmode(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return get_rst_lp_cpld_reg(dev, devattr, buf, sig_lpm); +} + +static ssize_t +set_lpmode(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + return set_rst_lp_cpld_reg(dev, devattr, buf, count, sig_lpm); +} + +static ssize_t +get_reset(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return get_rst_lp_cpld_reg(dev, devattr, buf, sig_rst); +} + +static ssize_t +set_reset(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + return set_rst_lp_cpld_reg(dev, devattr, buf, count, sig_rst); +} + +static ssize_t +get_modprs(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return get_prs_cpld_reg(dev, devattr, buf, sig_abs); +} + +static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset); + +static struct attribute *s8900_64xc_cpld_attrs[] = { + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modprs.attr, + NULL, +}; + +static struct attribute_group s8900_64xc_cpld_attr_grp = { + .attrs = s8900_64xc_cpld_attrs, +}; + +/* + * Assumes that sanity checks for offset happened at sysfs-layer. + * Offset within Lower Page 00h and Upper Page 00h are not recomputed + */ +static uint8_t +sff_8436_translate_offset(loff_t *offset) +{ + unsigned page = 0; + + if (*offset < SFF_8436_MMAP_SIZE) { + return 0; + } + + page = (*offset >> 7)-1; + + if (page > 0 ) { + *offset = 0x80 + (*offset & 0x7f); + } else { + *offset &= 0xff; + } + + return page; +} + +static ssize_t +eeprom_read(struct i2c_client *client, + u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_read_i2c_block_data(client, command, + data_len, (u8 *)data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + goto abort; + } + + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + +abort: + return result; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_read_byte_data(client, command); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, " \\ + "command(0x%2x), data(0x%2x)\r\n", + command, result); + goto abort; + } + + *data = (u8)result; + result = 1; + +abort: + return result; +#endif +} + +static ssize_t +eeprom_write(struct i2c_client *client, + u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int result, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + result = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return data_len; +#else + int result, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + result = i2c_smbus_write_byte_data(client, command, *data); + if (result < 0) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(result < 0)) { + return result; + } + + return 1; +#endif +} + +static ssize_t +sfp_eeprom_read_write(struct i2c_client *client, + eeprom_operation_t op, + loff_t off, + const char *data, + int data_len) +{ + u8 page, phy_page; + u8 val, refresh_page = 0; + int ret; + ssize_t retval = 0; + size_t pending_len = 0, page_len = 0; + loff_t page_offset = 0, page_start_offset = 0; + loff_t phy_offset; + + + if (off > EEPROM_SIZE) { + return 0; + } + + if (off + data_len > EEPROM_SIZE) { + data_len = EEPROM_SIZE - off; + } + + /* + * Refresh pages which covers the requested data + * from offset to off + len + * Only refresh pages which contain requested bytes + * + */ + + pending_len = data_len; + + for (page = off >> 7; page <= (off + data_len - 1) >> 7; page++) { + refresh_page = 0; + switch (page) { + case 0: + /* Lower page 00h */ + refresh_page = 1; + break; + case 1: + /* Upper page 00h */ + refresh_page = 1; + break; + case 2: + /* Upper page 01h */ + ret = eeprom_read(client, SFF_8436_PAGE_PROV_ADDR, &val, sizeof(val)); + if (ret < 0) { + DEBUG_PRINT("Can't read EEPROM offset %d.\n", + SFF_8436_PAGE_PROV_ADDR); + goto error; + } + if (val & SFF_8436_PAGE_01_PRESENT) { + DEBUG_PRINT("Offset:%d Value:(0x%02x & 0x%02x)", + SFF_8436_PAGE_PROV_ADDR, val, + SFF_8436_PAGE_01_PRESENT); + refresh_page = 1; + } + break; + case 3: + /* Upper page 02h */ + ret = eeprom_read(client, SFF_8436_PAGE_PROV_ADDR, &val, sizeof(val)); + if (ret < 0) { + ERROR_MSG("Can't read EEPROM offset %d.\n", + SFF_8436_PAGE_PROV_ADDR); + goto error; + } + if (val & SFF_8436_PAGE_02_PRESENT) { + DEBUG_PRINT("Offset:%d Value:(0x%02x & 0x%02x)", + SFF_8436_PAGE_PROV_ADDR, val, + SFF_8436_PAGE_02_PRESENT); + refresh_page = 1; + } + break; + case 4: + /* Upper page 03h */ + ret = eeprom_read(client, SFF_8436_STATUS_ADDR, &val, sizeof(val)); + if (ret < 0) { + ERROR_MSG("Can't read EEPROM offset %d.\n", + SFF_8436_STATUS_ADDR); + goto error; + } + if (!(val & SFF_8436_STATUS_PAGE_03_PRESENT_L)) { + DEBUG_PRINT("Offset:%d Value:(0x%02x & 0x%02x)", + SFF_8436_STATUS_ADDR, val, + SFF_8436_STATUS_PAGE_03_PRESENT_L); + refresh_page = 1; + } + break; + default: + DEBUG_PRINT("Invalid Page %d\n", page); + ret = retval; + goto error; + break; + } + + if (!refresh_page) { + /* if page is not valid or already refreshed */ + continue; + } + + /* + * Compute the offset and number of bytes to be read/write + * w.r.t requested page + * + * 1. start at offset 0 (within the page), and read/write the entire page + * 2. start at offset 0 (within the page) and read/write less than entire page + * 3. start at an offset not equal to 0 and read/write the rest of the page + * 4. start at an offset not equal to 0 and read/write less than (end of page - offset) + * + */ + page_start_offset = page * EEPROM_PAGE_SIZE; + + if (page_start_offset < off) { + page_offset = off; + if (off + pending_len < page_start_offset + EEPROM_PAGE_SIZE) { + page_len = pending_len; + } else { + page_len = EEPROM_PAGE_SIZE - off; + } + } else { + page_offset = page_start_offset; + if (pending_len > EEPROM_PAGE_SIZE) { + page_len = EEPROM_PAGE_SIZE; + } else { + page_len = pending_len; + } + } + + pending_len = pending_len - page_len; + + /* Change current EEPROM page */ + phy_offset = page_offset; + phy_page = sff_8436_translate_offset(&phy_offset); + if (phy_page > 0) { + ret = eeprom_write(client, SFF_8436_PAGE_SELECT_ADDR, + &phy_page, sizeof(phy_page)); + if (ret < 0) { + ERROR_MSG("Can't write EEPROM offset %d.\n", + SFF_8436_PAGE_SELECT_ADDR); + goto error; + } + } + + /* + * If page_len > 32, I2C client continue read or write EEPROM. + */ + while (page_len) { + if (op == EEPROM_READ) { + ret = eeprom_read(client, phy_offset, data, page_len); + } else if (op == EEPROM_WRITE) { + ret = eeprom_write(client, phy_offset, data, page_len); + } else { + ERROR_MSG("Bad EEPROM operation %d.\n", op); + break; + } + + if (ret <= 0) { + if (retval == 0) { + retval = ret; + } + break; + } + phy_offset += ret; + off += ret; + data += ret; + page_len -= ret; + retval += ret; + } + + /* Restore EEPROM page to default */ + if (phy_page > 0) { + phy_page = EEPROM_DEFAULT_PAGE; + ret = eeprom_write(client, SFF_8436_PAGE_SELECT_ADDR, + &phy_page, sizeof(phy_page)); + if (ret < 0) { + ERROR_MSG("Can't write EEPROM offset %d.\n", + SFF_8436_PAGE_SELECT_ADDR); + goto error; + } + } + } + + return retval; + +error: + return ret; +} + + +static inline ssize_t +sfp_eeprom_read(struct i2c_client *client, + loff_t off, u8 *data, + int data_len) +{ + return sfp_eeprom_read_write(client, EEPROM_READ, + off, data, data_len); +} + + +static inline ssize_t +sfp_eeprom_write(struct i2c_client *client, + loff_t off, const char *data, + int data_len) +{ + return sfp_eeprom_read_write(client, EEPROM_WRITE, + off, data, data_len); +} + +static struct i2c_client * +cpld_sfp_port_client(int port, + int *data_reg) +{ + *data_reg = s8900_64xc_sfp_platform_data[port].cpld_reg; + if (port >= sfp1 && port <= sfp24) { + return s8900_64xc_cpld_platform_data[cpld_1].client; + } else if (port >= sfp25 && port <= sfp48) { + return s8900_64xc_cpld_platform_data[cpld_2].client; + } else if (port >= qsfp49 && port <= qsfp64) { + return s8900_64xc_cpld_platform_data[cpld_3].client; + } else { + ERROR_MSG("Unknown port: %d", port); + return NULL; + } +} + +static ssize_t +sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, + size_t count, int port) +{ + ssize_t retval = 0; + int data_reg = 0; + struct i2c_client *cpld_client = NULL; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + //CPLD MUX select + cpld_client = cpld_sfp_port_client(port, &data_reg); + DEBUG_PRINT("data_reg=%d, port=%d", data_reg, port); + if (!cpld_client) { + ERROR_MSG("Error i2c client for port %d", port); + return 0; + } + i2c_smbus_write_byte_data(cpld_client, CPLD_MUX_REG ,data_reg); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + //CPLD MUX deselect + i2c_smbus_write_byte_data(cpld_client, CPLD_MUX_REG ,0x0); + + mutex_unlock(&data->update_lock); + return retval; +} + +static ssize_t +sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + struct platform_device_id *dev_id = NULL; + + dev_id = (struct platform_device_id *)attr->private; + + DEBUG_PRINT("offset = (%lld), count = (%ld) dev_port=%d", off, count, (int)dev_id->driver_data); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + return sfp_port_read(data, buf, off, count, (int)dev_id->driver_data); +} + +static ssize_t +sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, + size_t count, int port) +{ + ssize_t retval = 0; + int data_reg = 0; + struct i2c_client *cpld_client = NULL; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + //CPLD MUX select + cpld_client = cpld_sfp_port_client(port, &data_reg); + DEBUG_PRINT("data_reg=%d, port=%d", data_reg, port); + if (!cpld_client) { + ERROR_MSG("Error i2c client for port %d", port); + } + i2c_smbus_write_byte_data(cpld_client, CPLD_MUX_REG ,data_reg); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + //CPLD MUX deselect + i2c_smbus_write_byte_data(cpld_client, CPLD_MUX_REG ,0x0); + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t +sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct sfp_port_data *data; + struct platform_device_id *dev_id = NULL; + + dev_id = (struct platform_device_id *)attr->private; + + DEBUG_PRINT("offset = (%lld), count = (%ld) dev_port=%d", + off, count, (int)dev_id->driver_data); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + return sfp_port_write(data, buf, off, count, (int)dev_id->driver_data); +} + +static int +sfp_sysfs_eeprom_init(struct kobject *kobj, + struct bin_attribute *eeprom, + const struct platform_device_id *dev_id) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = dev_id->name; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->private = (void *)dev_id; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + DEBUG_PRINT("err=%d", err); + return err; + } + + return 0; +} + +static int +sfp_sysfs_eeprom_cleanup(struct kobject *kobj, + struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + + return 0; +} + +static int +sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int +qsfp_probe(struct i2c_client *client, + const struct platform_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + DEBUG_PRINT("No memory."); + goto exit; + } + + /* Register sysfs hooks */ //TBD: must remove + /* status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } */ + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, dev_id); + if (status) { + DEBUG_PRINT("sfp_sysfs_eeprom_init error"); + goto exit_free; + } + + //TBD: Must remove + /*if (s9130_32x_kobj) { + status = sysfs_create_link(s9130_32x_kobj, &client->dev.kobj, client->name); + if (status) { + goto exit_remove; + } + }*/ + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_free: + kfree(qsfp); +exit: + + return status; +} + +static int +qsfp_device_probe(struct platform_device *pdev) +{ + struct sfp_platform_data *pdata; + struct sfp_port_data *data[TOTAL_PORT_NUM]; + struct i2c_adapter *parent[SFP_EEPROM_DEV_NUM]; + struct i2c_client *sfp_client[SFP_EEPROM_DEV_NUM]; + int i; + int ret=0; + + DEBUG_PRINT("Start"); + + pdata = pdev->dev.platform_data; + if (!pdata) { + ERROR_MSG("Missing platform data\n"); + return -ENODEV; + } + + //New eeprom device + for (i=0; i < SFP_EEPROM_DEV_NUM; i++) { + parent[i] = i2c_get_adapter(i+S8900_64XC_SFP_EEPROM_BASE_NR); + if (!parent[i]) { + ERROR_MSG("Parent adapter (%d) not found\n", i+S8900_64XC_SFP_EEPROM_BASE_NR); + ret=-ENODEV; + goto error; + } + sfp_client[i] = i2c_new_dummy(parent[i], SFP_EEPROM_A0_I2C_ADDR); + if (!sfp_client[i]) { + ERROR_MSG("[%d]: Fail to create dummy i2c client for parent %d addr 0x%x\n", i, i+S8900_64XC_SFP_EEPROM_BASE_NR, SFP_EEPROM_A0_I2C_ADDR); + ret=-ENODEV; + goto error; + } + } + + //Assign client to dummy device + for (i = 0; i < TOTAL_PORT_NUM; i++) { + switch (pdata[i].parent) { + case 2: + pdata[i].client = sfp_client[0]; + break; + case 3: + pdata[i].client = sfp_client[1]; + break; + case 4: + pdata[i].client = sfp_client[2]; + break; + default: + ERROR_MSG("Error parent number: %d, ", i); + break; + } + + if (!pdata[i].client) { + ERROR_MSG("[%d]: Fail to create dummy i2c client for parent %d addr 0x%x\n", i, pdata[i].parent, pdata[i].reg_addr); + ret=-ENODEV; + goto error; + } + } + + + for (i = 0; i < TOTAL_PORT_NUM; i++) { + data[i] = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data[i]) { + ret=-ENOMEM; + ERROR_MSG("No memory"); + goto error; + } + + i2c_set_clientdata(pdata[i].client, data[i]); + mutex_init(&data[i]->update_lock); + data[i]->port = qsfp_device_id[i].driver_data; + data[i]->client = pdata[i].client; + + DEBUG_PRINT("data[%d]->port=%d", i, data[i]->port); + + if (pdata[i].client->addr != SFP_EEPROM_A0_I2C_ADDR) { + ret=-ENODEV; + ERROR_MSG("Not approve device address"); + goto error; + } + + data[i]->driver_type = DRIVER_TYPE_QSFP; + + ret |= qsfp_probe(pdata[i].client, &qsfp_device_id[i], &data[i]->qsfp); + } + + if (ret) { + ERROR_MSG("qsfp_probe failed someone."); + //goto error; + } + return 0; +error: + DEBUG_PRINT("error start"); + i2c_put_adapter(parent[i]); + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent[i]); + } + } + + return ret; +} + +static int +qsfp_remove(struct i2c_client *client, + struct qsfp_data *data) +{ + //TBD: Must remove + /*if (s9130_32x_kobj) { + sysfs_remove_link(s9130_32x_kobj, client->name); + }*/ + + //TBD: Must remove all ports EEPROM BIN + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + //TBD: Must remove sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + + return 0; +} + +static int __exit +qsfp_device_remove(struct platform_device *pdev) +{ + struct sfp_port_data *data = NULL; + struct sfp_platform_data *pdata = pdev->dev.platform_data; + struct i2c_adapter *parent = NULL; + int i; + + + + if (!pdata) { + ERROR_MSG("Missing platform data\n"); + return -ENOENT; + } + + for (i = 0; i < TOTAL_PORT_NUM; i+=CPLD_MUX_OFFSET) { + data = i2c_get_clientdata(pdata[i].client); + if (!data) { + ERROR_MSG("Empty data. skip. i=%d", i); + continue; + } + qsfp_remove(pdata[i].client, data->qsfp); + if (pdata[i].client) { + parent = (pdata[i].client)->adapter; + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent); + } + kfree(data); + } + + + return 0; +} + +static int +cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent[CPLD_DEVICE_NUM]; + int i; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + ERROR_MSG("Missing platform data\n"); + return -ENODEV; + } + + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + parent[i] = i2c_get_adapter(S8900_64XC_MUX_BASE_NR + i + 1); + if (!parent[i]) { + ERROR_MSG("Parent adapter (%d) not found\n", + S8900_64XC_MUX_BASE_NR + i + 1); + return -ENODEV; + } + pdata[i].client = i2c_new_dummy(parent[i], pdata[i].reg_addr); + if (!pdata[i].client) { + ERROR_MSG("Fail to create dummy i2c client for addr %d\n", pdata[i].reg_addr); + goto error; + } + } + + ret = sysfs_create_group(&pdev->dev.kobj, &s8900_64xc_cpld_attr_grp); + if (ret) + goto error; + + return 0; + +error: + if (i < CPLD_DEVICE_NUM) { + i2c_put_adapter(parent[i]); + } + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent[i]); + } + } + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + int i; + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + + sysfs_remove_group(&pdev->dev.kobj, &s8900_64xc_cpld_attr_grp); + + if (!pdata) { + ERROR_MSG("Missing platform data\n"); + } else { + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + if (pdata[i].client) { + parent = (pdata[i].client)->adapter; + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent); + } + } + } + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "ingrasys-s8900-64xc-cpld", + }, +}; + +static struct platform_driver qsfp_driver = { + .probe = qsfp_device_probe, + .remove = __exit_p(qsfp_device_remove), + //.id_table = qsfp_device_id, + .driver = { + .owner = THIS_MODULE, + .name = "ingrasys-s8900-64xc-sfp", + }, +}; + + +static int __init ingrasys_s8900_64xc_platform_init(void) +{ + int ret = 0; + + DEBUG_PRINT("ingrasysl_s8900_64xc_platform module initialization\n"); + + //mdelay(10000); + + ret = platform_driver_register(&cpld_driver); + if (ret) { + ERROR_MSG("Fail to register cpld driver\n"); + goto error_cpld_driver; + } + ret = platform_device_register(&s8900_64xc_cpld); + if (ret) { + ERROR_MSG("Fail to create cpld device\n"); + goto error_cpld; + } + + ret = platform_driver_register(&qsfp_driver); + if (ret) { + ERROR_MSG("Fail to register sfp driver\n"); + goto error_cpld_driver; + } + + ret = platform_device_register(&s8900_64xc_sfp); + if (ret) { + ERROR_MSG("Fail to create sfp device\n"); + goto error_cpld; + } + + return 0; + +error_cpld: + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&qsfp_driver); +error_cpld_driver: + return ret; +} + +static void __exit ingrasys_s8900_64xc_platform_exit(void) +{ + platform_device_unregister(&s8900_64xc_sfp); + platform_device_unregister(&s8900_64xc_cpld); + platform_driver_unregister(&qsfp_driver); + platform_driver_unregister(&cpld_driver); +} + +module_init(ingrasys_s8900_64xc_platform_init); +module_exit(ingrasys_s8900_64xc_platform_exit); + +MODULE_DESCRIPTION("Ingrasys S8900-64XC Platform Support"); +MODULE_AUTHOR("Wade He "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/qsfp-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/qsfp-monitor.service new file mode 100644 index 000000000000..99c91b98ab52 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s8900-64xc-monitor.service +After=s8900-64xc-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/s8900-64xc-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/s8900-64xc-monitor.service new file mode 100644 index 000000000000..decb0f943a9d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/service/s8900-64xc-monitor.service @@ -0,0 +1,18 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s8900_64xc_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/i2c_utils.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/i2c_utils.sh new file mode 100644 index 000000000000..e1df54ad0fe2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/i2c_utils.sh @@ -0,0 +1,1163 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_IGB_DEVICE=0 +NUM_I801_DEVICE=0 +NUM_ISMT_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) +NUM_MUX1_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 2 )) +NUM_MUX1_CHAN1_DEVICE=$(( ${NUM_I801_DEVICE} + 3 )) +NUM_MUX1_CHAN2_DEVICE=$(( ${NUM_I801_DEVICE} + 4 )) +NUM_MUX1_CHAN3_DEVICE=$(( ${NUM_I801_DEVICE} + 5 )) +NUM_MUX1_CHAN4_DEVICE=$(( ${NUM_I801_DEVICE} + 6 )) +NUM_MUX1_CHAN5_DEVICE=$(( ${NUM_I801_DEVICE} + 7 )) +NUM_MUX1_CHAN6_DEVICE=$(( ${NUM_I801_DEVICE} + 8 )) +NUM_MUX1_CHAN7_DEVICE=$(( ${NUM_I801_DEVICE} + 9 )) + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +PATH_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" +PATH_MUX_CHAN1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN1_DEVICE}" +PATH_MUX_CHAN2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN2_DEVICE}" +PATH_MUX_CHAN3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}" +PATH_MUX_CHAN4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN4_DEVICE}" +PATH_MUX_CHAN5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN5_DEVICE}" +PATH_MUX_CHAN6_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}" +PATH_MUX_CHAN7_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}" + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-64]" + echo " : ${0} i2c_qsfp_status_get [1-64]" + echo " : ${0} i2c_qsfp_type_get [1-64]" + echo " : ${0} i2c_qsfp_abs_get [1-64]" + echo " : ${0} i2c_qsfp_rst_get [49-64]" + echo " : ${0} i2c_qsfp_lpmode_get [49-64]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_front_temp" + echo " : ${0} i2c_rear_temp" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber on|off" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber on|off" + echo " : ${0} i2c_psu2_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-5]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod i2c_ismt + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_ismt + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x72' > ${PATH_ISMT_DEVICE}/new_device" + else + echo "pca9548 0x72 already init." + fi + #Init CPLD LED_CLR Register (Front Port LED) + i2cset -y ${NUM_I801_DEVICE} 0x33 0x34 0x10 + + rmmod coretemp + rmmod jc42 + rmmod w83795 + rmmod lm75 + _i2c_temp_init + _i2c_volmon_init + _i2c_hwmon_init + modprobe coretemp + modprobe w83795 + modprobe lm75 + modprobe jc42 + modprobe sff_8436_eeprom + modprobe eeprom + modprobe eeprom_mb + modprobe qsfp_cpld + _i2c_fan_init + _i2c_io_exp_init + _i2c_cpld_init + _i2c_psu_eeprom_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + + echo "tmp75 0x48" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}/new_device + echo "tmp75 0x49" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}/new_device + echo "Mount Main Board EEPROM" + echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-7/new_device + + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + for mod in coretemp jc42 w83795 lm75 eeprom_mb i2c_mux_pca954x i2c_ismt i2c_i801; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done +} + +#Temperature sensor Init +function _i2c_temp_init { + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x05 0xFF + echo "TEMP INIT Done" +} + +#FAN Init +function _i2c_fan_init { + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi + +} + +#VOLMON Init +function _i2c_volmon_init { + echo -n "VOLMON INIT..." + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x02 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x03 0x50 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x04 0x0A + echo "Done" +} + +#HWMON Init +function _i2c_hwmon_init { + echo -n "HWMON INIT..." + i2cset -y ${NUM_I801_DEVICE} 0x2f 0x00 0x80 + i2cset -y ${NUM_I801_DEVICE} 0x2f 0x06 0xFF + i2cset -y ${NUM_I801_DEVICE} 0x2f 0x07 0x03 + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + #SMBUS0 IO_EXPENDER + i2cset -y -r ${NUM_I801_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 2 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 3 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x27 7 0xFF + + #LED board after PVT (S8900_IO_EXP_LED_ID) + echo "Init LED IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 7 0xFF + + #PSU I/O (S8900_IO_EXP_PSU_ID) + echo "Init PSU IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 2 0x44 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 6 0xBB + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 7 0xFF + + #FAN I/O (S8900_IO_EXP_FAN_ID) + echo "Init FAN1 IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 2 0x11 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 3 0x11 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 6 0xCC + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x20 7 0xCC + + #FAN I/O (S8900_IO_EXP_FAN_ID) + echo "Init FAN2 IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 2 0x10 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 6 0xCC + i2cset -y -r ${NUM_MUX1_CHAN3_DEVICE} 0x21 7 0xFF +} + +#I2C CPLD init +function _i2c_cpld_init { + echo "=========================================================" + echo "# Description: I2C CPLD Init..." + echo "=========================================================" + + ## modprobe i2c_cpld + modprobe i2c_cpld + ## Add CPLD device + echo "i2c_cpld 0x33" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}/new_device + + echo "done..." +} +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + FAN9_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan9_alarm` + FAN10_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan10_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + if [ "${FAN9_ALARM}" == "0" ] && [ "${FAN10_ALARM}" == "0" ]; then + FAN_TRAY=5 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=5 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + FAN9_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan9_alarm` + FAN10_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan10_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ] \ + && [ "${FAN9_ALARM}" == "0" ] && [ "${FAN10_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C LED TEST..." + echo "=========================================================" + #sys led (green) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xBF + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x7F + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xEF + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xDF + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFB + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xF7 + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFE + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFD + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED + i2cset -y ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + _pause 'Check turn off all LEDs and Press [Enter] key to continue...' + echo "done..." +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX1_CHAN0_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 1) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN0_DEVICE} + eepromidx=${port} + eepromAddr=0x50 + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX1_CHAN0_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 1) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN0_DEVICE} + eepromidx=${port} + eepromAddr=0x50 + ;; + 17|18|19|20) + i2cbus=${NUM_MUX1_CHAN0_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 1) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN0_DEVICE} + eepromidx=${port} + eepromAddr=0x50 + ;; + 21|22|23|24) + i2cbus=${NUM_MUX1_CHAN0_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 1) / 2) )) + dataAddr=$(( (38 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN0_DEVICE} + eepromidx=${port} + eepromAddr=0x50 + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX1_CHAN1_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 25) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN1_DEVICE} + eepromidx=$(( (${port} - 24) )) + eepromAddr=0x50 + ;; + 33|34|35|36|37|38|39|40) + i2cbus=${NUM_MUX1_CHAN1_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 25) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN1_DEVICE} + eepromidx=$(( (${port} - 24) )) + eepromAddr=0x50 + ;; + 41|42|43|44) + i2cbus=${NUM_MUX1_CHAN1_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 25) / 2) )) + dataAddr=$(( (32 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN1_DEVICE} + eepromidx=$(( (${port} - 24) )) + eepromAddr=0x50 + ;; + 45|46|47|48) + i2cbus=${NUM_MUX1_CHAN1_DEVICE} + regAddr=0x33 + idx=$(( ((${port} - 25) / 2) )) + dataAddr=$(( (38 + $idx) )) + presentChan=$(( $((${port} % 2)) == 1 ? 0x1 : 0x5 )) + eeprombus=${NUM_MUX1_CHAN1_DEVICE} + eepromidx=$(( (${port} - 24) )) + eepromAddr=0x50 + ;; + 49|50|51|52|53|54|55|56) + i2cbus=${NUM_MUX1_CHAN2_DEVICE} + regAddr=0x33 + idx=$(( (${port} - 49) )) + dataAddr=$(( (32 + $idx) )) + rstsellpdataAddr=$(( (48 + $idx) )) + intChan=0x0 + rstChan=0x0 + presentChan=0x1 + modselChan=0x1 + lpmodeChan=0x2 + eeprombus=${NUM_MUX1_CHAN2_DEVICE} + eepromidx=$(( (${port} - 48) )) + intabsidx=$(( (${port} - 28) )) + rstsellpidx=$(( (${port} - 18) )) + eepromAddr=0x50 + ;; + 57|58|59|60|61|62|63|64) + i2cbus=${NUM_MUX1_CHAN2_DEVICE} + regAddr=0x33 + idx=$(( (${port} - 49) )) + dataAddr=$(( (32 + $idx) )) + rstsellpdataAddr=$(( (48 + $idx) )) + intChan=0x0 + rstChan=0x0 + presentChan=0x1 + modselChan=0x1 + lpmodeChan=0x2 + eeprombus=${NUM_MUX1_CHAN2_DEVICE} + eepromidx=$(( (${port} - 48) )) + intabsidx=$(( (${port} - 28) )) + rstsellpidx=$(( (${port} - 18) )) + eepromAddr=0x50 + ;; + *) + echo "Please input 1~64" + exit + ;; + esac +} + +#Get SFP/QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + _qsfp_port_i2c_var_set ${QSFP_PORT} + + regData=`cat /sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_modprs` + port_num=$(( ${QSFP_PORT} - 1 )) + + #status: 0 -> Down, 1 -> Up + status=$(( $(($regData & ( 1 << $port_num))) != 0 ? 0 : 1 )) + + + if [ $status = 0 ]; then + echo "Module not present." + exit + fi + + #Read SFP/QSFP EEPROM + if [ ${QSFP_PORT} -lt 49 ]; then + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/sfp${QSFP_PORT} | hexdump -C + elif [ ${QSFP_PORT} -ge 49 ]; then + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/qsfp${QSFP_PORT} | hexdump -C + fi +} + +#Get QSFP Status for QSFP monitor service +function _i2c_qsfp_status_get { + _i2c_qsfp_abs_get + echo "status=$status" +} + +#Get QSFP type for QSFP monitor server +function _i2c_qsfp_type_get { + _qsfp_port_i2c_var_set ${QSFP_PORT} + + regData=`cat /sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_modprs` + port_num=$(( ${QSFP_PORT} - 1 )) + + #status: 0 -> Down, 1 -> Up + status=$(( $(($regData & ( 1 << $port_num))) != 0 ? 0 : 1 )) + + if [ $status = 0 ]; then + echo "Module not present." + exit + fi + + #Read SFP/QSFP EEPROM + if [ ${QSFP_PORT} -lt 49 ]; then + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/sfp${QSFP_PORT}) + elif [ ${QSFP_PORT} -ge 49 ]; then + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/qsfp${QSFP_PORT}) + fi + + if [ ${QSFP_PORT} -ge 1 ] && [ ${QSFP_PORT} -le 48 ]; then + echo "sfp" + # 1~48 port is sfp port + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 0 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 2 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 3 -n 1 -e '"%x"') + else + echo "qsfp" + # 49~64 port is qsfp port + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + fi + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get QSFP ABS +function _i2c_qsfp_abs_get { + _qsfp_port_i2c_var_set ${QSFP_PORT} + + regData=`cat /sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_modprs` + port_num=$(( ${QSFP_PORT} - 1 )) + + #status: 0 -> Down, 1 -> Up + status=$(( $(($regData & ( 1 << $port_num))) != 0 ? 0 : 1 )) + echo "ABS=$status regData=$regData" + + +} + +#Get QSFP RST +function _i2c_qsfp_rst_get { + + if [ ${QSFP_PORT} -lt 49 ] || [ ${QSFP_PORT} -gt 64 ]; then + echo "Please input 49~64" + exit + fi + _qsfp_port_i2c_var_set ${QSFP_PORT} + + + regData=`cat /sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_reset` + port_num=$(( ${QSFP_PORT} - 49 )) + + #status: 0 -> Down, 1 -> Up + status=$(( $(($regData & ( 1 << $port_num))) != 0 ? 0 : 1 )) + echo "RST=$status regData=$regData" + +} + +#Get QSFP LPMODE +function _i2c_qsfp_lpmode_get { + + if [ ${QSFP_PORT} -lt 49 ] || [ ${QSFP_PORT} -gt 64 ]; then + echo "Please input 49~64" + exit + fi + _qsfp_port_i2c_var_set ${QSFP_PORT} + + + regData=`cat /sys/devices/platform/ingrasys-s8900-64xc-cpld.0/qsfp_lpmode` + port_num=$(( ${QSFP_PORT} - 49 )) + + #status: 0 -> Down, 1 -> Up + status=$(( $(($regData & ( 1 << $port_num))) != 0 ? 1 : 0 )) + echo "LPMODE=$status regData=$regData" + +} +#PSU EEPROM init +function _i2c_psu_eeprom_init { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Init..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}/new_device + + ## PUS(1) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}/new_device + + echo "done..." +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN6_DEVICE}-0050/eeprom | hexdump -C + + ## PUS(1) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN7_DEVICE}-0050/eeprom | hexdump -C + echo "done..." +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom_mb + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN5_DEVICE}-0054/eeprom | hexdump -C + echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + + case ${FAN_TRAY} in + 1) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 5) + i2cAddr=0x21 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~5" + exit + ;; + esac + + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN3_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN3_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN3_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN3_DEVICE} $i2cAddr $ioPort 0x33 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Get Board Version and Type +function _i2c_board_type_get { + boardType=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_board_type` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev + +} + +#Get CPLD Version +function _i2c_cpld_version { + cpldRev=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_version` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Get PSU Status +function _i2c_psu_status { + psuPresent=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_abs` + psu1Exist=$(($((($psuPresent) & 0x01))?0:1)) + psu2Exist=$(($((($psuPresent) & 0x02))?0:1)) + psuPwGood=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_good` + psu1PwGood=$(($((($psuPwGood) >> 2 & 0x01))?1:0)) + psu2PwGood=$(($((($psuPwGood) >> 2 & 0x02))?1:0)) + printf "PSU1 Exist:%d PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Get Front Sensor Temperature +function _i2c_front_temp { + #Front MAC + sensors | grep 'Front MAC Temp' -A 1 +} + +#Get Rear Sensor Temperature +function _i2c_rear_temp { + #Rear MAC + sensors | grep 'Rear MAC Temp' -A 1 +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_abs_get" ]; then + _i2c_qsfp_abs_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_rst_get" ]; then + _i2c_qsfp_rst_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_lpmode_get" ]; then + _i2c_qsfp_lpmode_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_front_temp" ]; then + _i2c_front_temp + elif [ "${EXEC_FUNC}" == "i2c_rear_temp" ]; then + _i2c_rear_temp + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_temp_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main 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 new file mode 100644 index 000000000000..b3192f2efb7a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_monitor.sh @@ -0,0 +1,106 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..63}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + # identifier 11 for qsfp, 3 for sfp + if [ "${identifier}" == "11" ] || [ "${identifier}" == "3" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #AOC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to AOC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} aoc $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`sonic-db-cli ASIC_DB HLEN HIDDEN` + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_si_cfg.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_si_cfg.sh new file mode 100644 index 000000000000..3d132641f516 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/qsfp_si_cfg.sh @@ -0,0 +1,409 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +TYPE=${1} +PORT=${2} + +# port number +MIN_PORT=0 +MAX_PORT=63 + +# INDEX of value field in array +SI_PRE_IDX=1 +SI_POST_IDX=2 +SI_MAIN_IDX=3 +SI_AMP_IDX=4 +SI_DRI_IDX=5 + +# type string +AOC_TYPE="aoc" +DAC_TYPE="dac" + +# si value for bcm command +SI_VAL="" + +# "PRE POST MAIN AMP DRIVERMODE" for each port in array +xe_aoc_si_value=( + "0x00 0x30 0x40 0x9 0x0" #port 0 + "0x00 0x30 0x40 0x9 0x0" #port 1 + "0x00 0x30 0x40 0x9 0x0" #port 2 + "0x00 0x2c 0x44 0x9 0x0" #port 3 + "0x00 0x30 0x40 0x9 0x0" #port 4 + "0x00 0x30 0x40 0x9 0x0" #port 5 + "0x00 0x2c 0x44 0x9 0x0" #port 6 + "0x00 0x2c 0x44 0x9 0x0" #port 7 + "0x00 0x2c 0x44 0x9 0x0" #port 8 + "0x00 0x28 0x48 0x9 0x0" #port 9 + "0x00 0x2c 0x44 0x9 0x0" #port 10 + "0x00 0x2c 0x44 0x9 0x0" #port 11 + "0x00 0x2c 0x44 0x9 0x0" #port 12 + "0x00 0x2c 0x44 0x9 0x0" #port 13 + "0x00 0x2c 0x44 0x9 0x0" #port 14 + "0x00 0x2c 0x44 0x9 0x0" #port 15 + "0x00 0x2c 0x44 0xb 0x0" #port 16 + "0x00 0x30 0x40 0xb 0x0" #port 17 + "0x00 0x2c 0x44 0xa 0x0" #port 18 + "0x00 0x2c 0x44 0x9 0x0" #port 19 + "0x00 0x30 0x40 0xa 0x0" #port 20 + "0x00 0x2c 0x44 0x9 0x0" #port 21 + "0x00 0x2c 0x44 0x9 0x0" #port 22 + "0x00 0x30 0x40 0xc 0x0" #port 23 + "0x00 0x30 0x40 0xc 0x0" #port 24 + "0x00 0x2c 0x44 0x9 0x0" #port 25 + "0x00 0x30 0x40 0x9 0x0" #port 26 + "0x00 0x30 0x40 0x9 0x0" #port 27 + "0x00 0x30 0x40 0xa 0x0" #port 28 + "0x00 0x28 0x48 0x9 0x0" #port 29 + "0x00 0x2c 0x44 0x9 0x0" #port 30 + "0x00 0x2c 0x44 0xa 0x0" #port 31 + "0x00 0x28 0x48 0x9 0x0" #port 32 + "0x00 0x28 0x48 0x7 0x0" #port 33 + "0x00 0x28 0x48 0x9 0x0" #port 34 + "0x00 0x28 0x48 0x9 0x0" #port 35 + "0x00 0x28 0x48 0x9 0x0" #port 36 + "0x00 0x2c 0x44 0x9 0x0" #port 37 + "0x00 0x28 0x48 0x9 0x0" #port 38 + "0x00 0x28 0x48 0x9 0x0" #port 39 + "0x00 0x28 0x48 0xa 0x0" #port 40 + "0x00 0x2c 0x44 0x9 0x0" #port 41 + "0x00 0x2c 0x44 0x9 0x0" #port 42 + "0x00 0x2e 0x42 0xa 0x0" #port 43 + "0x00 0x2e 0x42 0xa 0x0" #port 44 + "0x00 0x2c 0x44 0xa 0x0" #port 45 + "0x00 0x2c 0x44 0x9 0x0" #port 46 + "0x00 0x2c 0x44 0x9 0x0" #port 47 +) + +ce_aoc_si_value=( + "0x00 0x2c 0x44 0x9 0x0" #port 0 lane 0 + "0x00 0x34 0x3c 0xf 0x0" #port 0 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 0 lane 2 + "0x00 0x2c 0x44 0x9 0x0" #port 0 lane 3 + "0x00 0x28 0x48 0x9 0x0" #port 1 lane 0 + "0x00 0x28 0x48 0x9 0x0" #port 1 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 1 lane 2 + "0x00 0x2c 0x44 0xe 0x0" #port 1 lane 3 + "0x00 0x28 0x48 0x9 0x0" #port 2 lane 0 + "0x00 0x34 0x3c 0xf 0x0" #port 2 lane 1 + "0x00 0x28 0x48 0x9 0x0" #port 2 lane 2 + "0x00 0x30 0x40 0xd 0x0" #port 2 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 3 lane 0 + "0x00 0x30 0x40 0xd 0x0" #port 3 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 3 lane 2 + "0x00 0x30 0x40 0xd 0x0" #port 3 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 4 lane 0 + "0x00 0x2c 0x44 0x9 0x0" #port 4 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 4 lane 2 + "0x00 0x30 0x40 0xd 0x0" #port 4 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 5 lane 0 + "0x00 0x38 0x38 0xf 0x0" #port 5 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 5 lane 2 + "0x00 0x2c 0x44 0x9 0x0" #port 5 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 6 lane 0 + "0x00 0x2c 0x44 0x9 0x0" #port 6 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 6 lane 2 + "0x00 0x30 0x40 0xe 0x0" #port 6 lane 3 + "0x00 0x28 0x48 0x9 0x0" #port 7 lane 0 + "0x00 0x30 0x40 0xa 0x0" #port 7 lane 1 + "0x00 0x2c 0x44 0x9 0x0" #port 7 lane 2 + "0x00 0x34 0x3c 0xe 0x0" #port 7 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 8 lane 0 + "0x00 0x30 0x40 0xe 0x0" #port 8 lane 1 + "0x00 0x34 0x3c 0xf 0x0" #port 8 lane 2 + "0x00 0x30 0x40 0xe 0x0" #port 8 lane 3 + "0x00 0x2c 0x44 0x9 0x0" #port 9 lane 0 + "0x00 0x34 0x3c 0xd 0x0" #port 9 lane 1 + "0x00 0x34 0x3c 0xd 0x0" #port 9 lane 2 + "0x00 0x34 0x3c 0xf 0x0" #port 9 lane 3 + "0x00 0x34 0x3c 0xd 0x0" #port 10 lane 0 + "0x00 0x34 0x3c 0xe 0x0" #port 10 lane 1 + "0x00 0x34 0x3c 0xd 0x0" #port 10 lane 2 + "0x00 0x34 0x3c 0xd 0x0" #port 10 lane 3 + "0x00 0x34 0x3c 0xd 0x0" #port 11 lane 0 + "0x00 0x34 0x3c 0xd 0x0" #port 11 lane 1 + "0x00 0x30 0x40 0xd 0x0" #port 11 lane 2 + "0x00 0x30 0x40 0xd 0x0" #port 11 lane 3 + "0x00 0x34 0x3c 0xd 0x0" #port 12 lane 0 + "0x00 0x34 0x3c 0xd 0x0" #port 12 lane 1 + "0x00 0x34 0x3c 0xd 0x0" #port 12 lane 2 + "0x00 0x34 0x3c 0xd 0x0" #port 12 lane 3 + "0x00 0x34 0x3c 0xd 0x0" #port 13 lane 0 + "0x00 0x34 0x3c 0xd 0x0" #port 13 lane 1 + "0x00 0x34 0x3c 0xd 0x0" #port 13 lane 2 + "0x00 0x34 0x3c 0xf 0x0" #port 13 lane 3 + "0x00 0x38 0x38 0xe 0x0" #port 14 lane 0 + "0x00 0x34 0x3c 0xd 0x0" #port 14 lane 1 + "0x00 0x34 0x3c 0xd 0x0" #port 14 lane 2 + "0x00 0x38 0x38 0xe 0x0" #port 14 lane 3 + "0x00 0x34 0x3c 0xd 0x0" #port 15 lane 0 + "0x00 0x30 0x40 0xc 0x0" #port 15 lane 1 + "0x00 0x30 0x40 0xc 0x0" #port 15 lane 2 + "0x00 0x34 0x3c 0xd 0x0" #port 15 lane 3 +) + +xe_dac_si_value=( + "0x14 0x00 0x3c 0xf 0x0" #port 0 + "0x1c 0x00 0x3c 0xf 0x0" #port 1 + "0x08 0x00 0x3c 0xf 0x0" #port 2 + "0x08 0x00 0x3c 0xf 0x0" #port 3 + "0x08 0x00 0x3c 0xf 0x0" #port 4 + "0x10 0x00 0x3c 0xf 0x0" #port 5 + "0x08 0x08 0x3c 0xf 0x0" #port 6 + "0x10 0x04 0x3c 0xf 0x0" #port 7 + "0x08 0x00 0x3c 0x9 0x0" #port 8 + "0x08 0x00 0x3c 0x9 0x0" #port 9 + "0x08 0x00 0x3c 0x9 0x0" #port 10 + "0x08 0x00 0x3c 0x9 0x0" #port 11 + "0x08 0x00 0x3c 0x9 0x0" #port 12 + "0x08 0x00 0x3c 0x9 0x0" #port 13 + "0x08 0x00 0x3c 0x9 0x0" #port 14 + "0x08 0x00 0x3c 0x9 0x0" #port 15 + "0x08 0x0c 0x3c 0xb 0x0" #port 16 + "0x10 0x0c 0x3c 0xb 0x0" #port 17 + "0x08 0x08 0x3c 0xa 0x0" #port 18 + "0x10 0x0c 0x3c 0x9 0x0" #port 19 + "0x08 0x04 0x3c 0xc 0x0" #port 20 + "0x08 0x08 0x3c 0x9 0x0" #port 21 + "0x08 0x08 0x3c 0xc 0x0" #port 22 + "0x10 0x08 0x3c 0xa 0x0" #port 23 + "0x08 0x08 0x3c 0x9 0x0" #port 24 + "0x08 0x04 0x3c 0x9 0x0" #port 25 + "0x08 0x00 0x3c 0x9 0x0" #port 26 + "0x08 0x08 0x3c 0xc 0x0" #port 27 + "0x10 0x00 0x3c 0xa 0x0" #port 28 + "0x10 0x04 0x3c 0x9 0x0" #port 29 + "0x14 0x00 0x3c 0x9 0x0" #port 30 + "0x14 0x00 0x3c 0xa 0x0" #port 31 + "0x08 0x00 0x3c 0x9 0x0" #port 32 + "0x08 0x00 0x3c 0x7 0x0" #port 33 + "0x08 0x00 0x3c 0x9 0x0" #port 34 + "0x08 0x00 0x3c 0x9 0x0" #port 35 + "0x08 0x00 0x3c 0x9 0x0" #port 36 + "0x0c 0x00 0x3c 0x9 0x0" #port 37 + "0x08 0x00 0x3c 0x9 0x0" #port 38 + "0x08 0x00 0x3c 0x9 0x0" #port 39 + "0x10 0x00 0x3c 0xa 0x0" #port 40 + "0x10 0x00 0x3c 0x9 0x0" #port 41 + "0x08 0x08 0x3c 0xc 0x0" #port 42 + "0x10 0x00 0x3c 0xa 0x0" #port 43 + "0x08 0x00 0x3c 0xa 0x0" #port 44 + "0x10 0x00 0x3c 0x9 0x0" #port 45 + "0x08 0x04 0x3c 0x9 0x0" #port 46 + "0x08 0x00 0x3c 0xa 0x0" #port 47 +) + +ce_dac_si_value=( + "0x08 0x00 0x3c 0x9 0x0" #port 0 lane 0 + "0x08 0x00 0x3c 0xf 0x0" #port 0 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 0 lane 2 + "0x08 0x00 0x3c 0x9 0x0" #port 0 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 1 lane 0 + "0x08 0x00 0x3c 0x9 0x0" #port 1 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 1 lane 2 + "0x08 0x00 0x3c 0xe 0x0" #port 1 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 2 lane 0 + "0x08 0x00 0x3c 0xf 0x0" #port 2 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 2 lane 2 + "0x08 0x00 0x3c 0xd 0x0" #port 2 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 3 lane 0 + "0x08 0x00 0x3c 0xd 0x0" #port 3 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 3 lane 2 + "0x08 0x00 0x3c 0xd 0x0" #port 3 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 4 lane 0 + "0x08 0x00 0x3c 0x9 0x0" #port 4 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 4 lane 2 + "0x08 0x00 0x3c 0xd 0x0" #port 4 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 5 lane 0 + "0x08 0x00 0x3c 0xf 0x0" #port 5 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 5 lane 2 + "0x08 0x00 0x3c 0x9 0x0" #port 5 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 6 lane 0 + "0x08 0x00 0x3c 0x9 0x0" #port 6 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 6 lane 2 + "0x08 0x00 0x3c 0xe 0x0" #port 6 lane 3 + "0x08 0x00 0x3c 0x9 0x0" #port 7 lane 0 + "0x08 0x00 0x3c 0xa 0x0" #port 7 lane 1 + "0x08 0x00 0x3c 0x9 0x0" #port 7 lane 2 + "0x08 0x00 0x3c 0xe 0x0" #port 7 lane 3 + "0x08 0x04 0x3c 0xf 0x0" #port 8 lane 0 + "0x08 0x00 0x3c 0xf 0x0" #port 8 lane 1 + "0x08 0x04 0x3c 0xf 0x0" #port 8 lane 2 + "0x08 0x00 0x3c 0xf 0x0" #port 8 lane 3 + "0x08 0x04 0x3c 0xf 0x0" #port 9 lane 0 + "0x08 0x04 0x3c 0xf 0x0" #port 9 lane 1 + "0x08 0x04 0x3c 0xf 0x0" #port 9 lane 2 + "0x08 0x04 0x3c 0xf 0x0" #port 9 lane 3 + "0x08 0x04 0x3c 0xf 0x0" #port 10 lane 0 + "0x10 0x08 0x3c 0xf 0x0" #port 10 lane 1 + "0x08 0x04 0x3c 0xf 0x0" #port 10 lane 2 + "0x08 0x04 0x3c 0xf 0x0" #port 10 lane 3 + "0x08 0x08 0x3c 0xf 0x0" #port 11 lane 0 + "0x08 0x04 0x3c 0xf 0x0" #port 11 lane 1 + "0x08 0x04 0x3c 0xf 0x0" #port 11 lane 2 + "0x08 0x04 0x3c 0xf 0x0" #port 11 lane 3 + "0x08 0x0c 0x3c 0xf 0x0" #port 12 lane 0 + "0x08 0x08 0x3c 0xf 0x0" #port 12 lane 1 + "0x08 0x0c 0x3c 0xf 0x0" #port 12 lane 2 + "0x08 0x08 0x3c 0xf 0x0" #port 12 lane 3 + "0x08 0x08 0x3c 0xf 0x0" #port 13 lane 0 + "0x08 0x0c 0x3c 0xf 0x0" #port 13 lane 1 + "0x08 0x08 0x3c 0xf 0x0" #port 13 lane 2 + "0x08 0x0c 0x3c 0xf 0x0" #port 13 lane 3 + "0x10 0x10 0x3c 0xf 0x0" #port 14 lane 0 + "0x08 0x0c 0x3c 0xf 0x0" #port 14 lane 1 + "0x08 0x0c 0x3c 0xf 0x0" #port 14 lane 2 + "0x08 0x0c 0x3c 0xf 0x0" #port 14 lane 3 + "0x08 0x14 0x3c 0xf 0x0" #port 15 lane 0 + "0x08 0x10 0x3c 0xf 0x0" #port 15 lane 1 + "0x08 0x10 0x3c 0xf 0x0" #port 15 lane 2 + "0x08 0x10 0x3c 0xf 0x0" #port 15 lane 3 +) + +#get field value in si value array for xe port +function get_xe_si { + local port=$1 + local field=$2 + local type=$3 + local index=$port + if [ "$type" == "${AOC_TYPE}" ]; then + SI_VAL=$(echo "${xe_aoc_si_value[$index]}" | awk '{print $'$field'}') + else + SI_VAL=$(echo "${xe_dac_si_value[$index]}" | awk '{print $'$field'}') + fi +} + +#get field value in si value array for ce port +function get_ce_si { + local port=$1 + local lane=$2 + local field=$3 + local type=$4 + index=$(( (${port}-1)*4+${lane} )) + if [ "$type" == "${AOC_TYPE}" ]; then + SI_VAL=$(echo "${ce_aoc_si_value[$index]}" | awk '{print $'$field'}') + else + SI_VAL=$(echo "${ce_dac_si_value[$index]}" | awk '{print $'$field'}') + fi +} + +# set si value for xe port +function _qsfp_xe_si_set { + # convert PORT to xe port index + local xe_port=$PORT + # generate command for SI PRE value + get_xe_si $xe_port $SI_PRE_IDX $TYPE + local pre_cmd="phy xe${xe_port} CL93N72_UT_CTL2r CL93N72_TXFIR_PRE=${SI_VAL}" + # generate command for SI POST value + get_xe_si $xe_port $SI_POST_IDX $TYPE + local post_cmd="phy xe${xe_port} CL93N72_UT_CTL2r CL93N72_TXFIR_POST=${SI_VAL}" + # generate command for SI MAIN value + get_xe_si $xe_port $SI_MAIN_IDX $TYPE + local main_cmd="phy xe${xe_port} CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=${SI_VAL}" + # generate command for SI AMP CONTROL value + get_xe_si $xe_port $SI_AMP_IDX $TYPE + local amp_val=$SI_VAL + get_xe_si $xe_port $SI_DRI_IDX $TYPE + local dri_val=$SI_VAL + local amp_cmd="phy xe${xe_port} AMS_TX_CTL2r AMS_TX_AMP_CTL=${amp_val} AMS_TX_DRIVERMODE=${dri_val}" + # apply bcmcmd + bcmcmd "${pre_cmd};${post_cmd};${main_cmd};${amp_cmd}" +} + +# set aoc si value for ce port +function _qsfp_ce_si_set { + # convert PORT to ce port index + local ce_port=$(( $PORT - 48 )) + for lane in {0..3}; + do + # generate command for SI PRE value + get_ce_si $ce_port $lane $SI_PRE_IDX $TYPE + local pre_cmd="phy ce${ce_port} CL93N72_UT_CTL2r.${lane} CL93N72_TXFIR_PRE=${SI_VAL}" + # generate command for SI POST value + get_ce_si $ce_port $lane $SI_POST_IDX $TYPE + local post_cmd="phy ce${ce_port} CL93N72_UT_CTL2r.${lane} CL93N72_TXFIR_POST=${SI_VAL}" + # generate command for SI MAIN value + get_ce_si $ce_port $lane $SI_MAIN_IDX $TYPE + local main_cmd="phy ce${ce_port} CL93N72_UT_CTL3r.${lane} CL93N72_TXFIR_MAIN=${SI_VAL}" + # generate command for SI AMP CONTROL value + get_ce_si $ce_port $lane $SI_AMP_IDX $TYPE + local amp_val=$SI_VAL + get_ce_si $ce_port $lane $SI_AMP_IDX $TYPE + local dri_val=$SI_VAL + local amp_cmd="phy ce${ce_port} AMS_TX_CTL2r.${lane} AMS_TX_AMP_CTL=${amp_val} AMS_TX_DRIVERMODE=${dri_val}" + # apply bcmcmd + bcmcmd "${pre_cmd};${post_cmd};${main_cmd};${amp_cmd}" + done +} + +#QSFP SI value set +function _qsfp_si_set { + if [[ $PORT -le 47 && $PORT -ge 0 ]]; then + # xe port + _qsfp_xe_si_set + else + # ce port + _qsfp_ce_si_set + fi +} + +function _util_input_check { + # input parameter validation + if [[ $1 -lt $2 || $1 -gt $3 ]]; then + echo "Please input number $2~$3" + exit + fi +} + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} ${AOC_TYPE} [${MIN_PORT}-${MAX_PORT}]" + echo " : ${0} ${DAC_TYPE} [${MIN_PORT}-${MAX_PORT}]" + echo "----------------------------------------------------" +} + +#Main Function +function _main { + + # TODO: remove after SI value ready + #exit ${TRUE} + + if [ -z $PORT ]; then + _help + exit ${FALSE} + fi + + if [ "${TYPE}" == "help" ]; then + _help + elif [ "${TYPE}" == "${AOC_TYPE}" ] || [ "${TYPE}" == "${DAC_TYPE}" ]; then + _util_input_check "$PORT" "$MIN_PORT" "$MAX_PORT" + _qsfp_si_set + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/s8900_64xc_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/s8900_64xc_monitor.sh new file mode 100755 index 000000000000..8bfb22328003 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s8900-64xc/utils/s8900_64xc_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/README.md b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/README.md new file mode 100644 index 000000000000..78f828e25310 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/README.md @@ -0,0 +1,185 @@ +# Ingrasys S9100-32X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9100-32X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9100-32X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9100-32X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S9100-32X. + +### I2C iSMT + +The I2C iSMT module on S9100-32X can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S9100-32X. + +### I2C PCA9548 +The PCA9548 module on S9100-32X can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9100-32X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9100-32X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9100 package is installed on the S9100-32X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon1/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/Makefile b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/Makefile new file mode 100755 index 000000000000..0247bd586f63 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := eeprom_mb.o +obj-m+= i2c_cpld.o \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/eeprom_mb.c b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/eeprom_mb.c new file mode 100755 index 000000000000..01ce44ad3fee --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/eeprom_mb.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys S9100 Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.c b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.c new file mode 100755 index 000000000000..626c63177b50 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.c @@ -0,0 +1,448 @@ +/* + * S9100-32X I2C CPLD driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c_cpld.h" + +#ifdef DEBUG + #define DEBUG_PRINT(fmt, args...) \ + printk(KERN_INFO "%s[%d]: " fmt "\r\n", \ + __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define I2C_READ_BYTE_DATA(ret, lock, i2c_client, reg) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_read_byte_data(i2c_client, reg); \ + mutex_unlock(lock); \ +} +#define I2C_WRITE_BYTE_DATA(ret, lock, i2c_client, reg, val) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_write_byte_data(i2c_client, reg, val); \ + mutex_unlock(lock); \ +} + +/* CPLD sysfs attributes index */ +enum i2c_cpld_sysfs_attributes { + CPLD_ACCESS_REG, + CPLD_REGISTER_VAL, + CPLD_PORT_START, + CPLD_PORTS, + CPLD_VERSION, + CPLD_ID, + CPLD_BOARD_TYPE, + CPLD_EXT_BOARD_TYPE, + CPLD_PW_GOOD, + CPLD_PW_ABS, +}; + +/* CPLD sysfs attributes hook functions */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, char *buf); + +static LIST_HEAD(cpld_client_list); /* client list for cpld */ +static struct mutex list_lock; /* mutex for client list */ + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +struct cpld_data { + int index; /* CPLD index */ + struct mutex access_lock; /* mutex for cpld access */ + u8 access_reg; /* register to access */ +}; + +/* CPLD device id and data */ +static const struct i2c_device_id i2c_cpld_id[] = { + { "i2c_cpld", i2c_cpld }, + {} +}; + +/* Addresses scanned for i2c_cpld */ +static const unsigned short cpld_i2c_addr[] = { 0x33, I2C_CLIENT_END }; +/* platform sysfs object */ +extern struct kobject *s9230_64x_kobj; + + +/* define all support register access of cpld in attribute */ +static SENSOR_DEVICE_ATTR(cpld_access_register, S_IWUSR | S_IRUGO, + read_access_register, write_access_register, CPLD_ACCESS_REG); +static SENSOR_DEVICE_ATTR(cpld_register_value, S_IWUSR | S_IRUGO, + read_register_value, write_register_value, CPLD_REGISTER_VAL); +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, + read_cpld_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(cpld_board_type, S_IRUGO, + read_board_type, NULL, CPLD_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_ext_board_type, S_IRUGO, + read_ext_board_type, NULL, CPLD_EXT_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_pw_good, S_IRUGO, + read_pw_good, NULL, CPLD_PW_GOOD); +static SENSOR_DEVICE_ATTR(cpld_pw_abs, S_IRUGO, + read_pw_abs, NULL, CPLD_PW_ABS); + + +/* define support attributes of cpldx , total 5 */ +/* cpld 1 */ +static struct attribute *i2c_cpld_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_ext_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_pw_good.dev_attr.attr, + &sensor_dev_attr_cpld_pw_abs.dev_attr.attr, + NULL +}; + +/* cpld 1 attributes group */ +static const struct attribute_group i2c_cpld_group = { + .attrs = i2c_cpld_attributes, +}; + +/* read access register from cpld data */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + + return sprintf(buf, "0x%x\n", reg); +} + +/* write access register to cpld data */ +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + + if (kstrtou8(buf, 0, ®) < 0) + return -EINVAL; + + data->access_reg = reg; + return count; +} + +/* read the value of access register in cpld data */ +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + int reg_val; + + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + + if (reg_val < 0) + return -1; + + return sprintf(buf, "0x%x\n", reg_val); +} + +/* wrtie the value to access register in cpld data */ +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ret = -EIO; + u8 reg = data->access_reg; + u8 reg_val; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, client, reg, reg_val); + + return count; +} + +/* get cpdl version register value */ +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_VERSION) { + reg = CPLD_VERSION_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get board type register value */ +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BOARD_TYPE) { + reg = CPLD_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_EXT_BOARD_TYPE) { + reg = CPLD_EXT_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_good(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_GOOD) { + reg = CPLD_PW_GOOD_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_pw_abs(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_PW_ABS) { + reg = CPLD_PW_ABS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* add valid cpld client to list */ +static void i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = NULL; + + node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + if (!node) { + dev_info(&client->dev, + "Can't allocate cpld_client_node for index %d\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +/* remove exist cpld client in list */ +static void i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + mutex_unlock(&list_lock); +} + +/* cpld drvier probe */ +static int i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* init cpld data for client */ + i2c_set_clientdata(client, data); + mutex_init(&data->access_lock); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_info(&client->dev, + "i2c_check_functionality failed (0x%x)\n", + client->addr); + status = -EIO; + goto exit; + } + + + status = sysfs_create_group(&client->dev.kobj,&i2c_cpld_group); + + if (status) + goto exit; + + dev_info(&client->dev, "chip found\n"); + + /* add probe chip to client list */ + i2c_cpld_add_client(client); + + return 0; +exit: + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + return status; +} + +/* cpld drvier remove */ +static int i2c_cpld_remove(struct i2c_client *client) +{ + + sysfs_remove_group(&client->dev.kobj, &i2c_cpld_group); + + i2c_cpld_remove_client(client); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, i2c_cpld_id); + +static struct i2c_driver i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "i2c_cpld", + }, + .probe = i2c_cpld_probe, + .remove = i2c_cpld_remove, + .id_table = i2c_cpld_id, + .address_list = cpld_i2c_addr, +}; + +static int __init i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&i2c_cpld_driver); +} + +static void __exit i2c_cpld_exit(void) +{ + i2c_del_driver(&i2c_cpld_driver); +} + +MODULE_AUTHOR("Wade He "); +MODULE_DESCRIPTION("Ingrasys S9100-32X Platform i2c cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_cpld_init); +module_exit(i2c_cpld_exit); + + + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.h b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.h new file mode 100755 index 000000000000..e103b05c717a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/modules/i2c_cpld.h @@ -0,0 +1,197 @@ +/* + * + * S9100-32X I2C CPLD driver header file + * + * Copyright (C) 2017 Ingrasys, Inc. + * Wade He + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef I2C_CPLD_H +#define I2C_CPLD_H + +// remove debug before release +#define DEBUG + +/* CPLD device index value */ +enum cpld_id { + i2c_cpld +}; + +/* port number on CPLD */ +#define CPLD_1_PORT_NUM 12 +#define CPLD_2_PORT_NUM 13 + +/* QSFP port number */ +#define QSFP_MAX_PORT_NUM 64 +#define QSFP_MIN_PORT_NUM 1 + +/* SFP+ port number */ +#define SFP_MAX_PORT_NUM 2 +#define SFP_MIN_PORT_NUM 1 + + +/* CPLD registers */ +#define CPLD_BOARD_TYPE_REG 0x0 +#define CPLD_EXT_BOARD_TYPE_REG 0x7 +#define CPLD_VERSION_REG 0x1 +#define CPLD_PW_GOOD_REG 0x2 +#define CPLD_PW_ABS_REG 0x3 + + +/* bit definition for register value */ + +enum CPLD_RESET_CONTROL_BITS { + CPLD_RESET_CONTROL_SWRST_BIT, + CPLD_RESET_CONTROL_CP2104RST_BIT, + CPLD_RESET_CONTROL_82P33814RST_BIT, + CPLD_RESET_CONTROL_BMCRST_BIT, +}; + +/* bit field structure for register value */ +struct cpld_reg_board_type_t { + u8 build_rev:2; + u8 hw_rev:2; + u8 board_id:4; +}; + +struct cpld_reg_version_t { + u8 revision:6; + u8 release:1; + u8 reserve:1; +}; + +struct cpld_reg_pw_good_t { + u8 reserve1:3; + u8 psu1:1; + u8 psu2:1; + u8 reserve2:3; +}; + +struct cpld_reg_pw_abs_t { + u8 psu1:1; + u8 psu2:1; + u8 reserve:6; +}; + +/* common manipulation */ +#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u) +#define READ_BIT(val, bit) ((0u == (val & (1<bf_name) +#define READ_BF_1(bf_struct, val, bf_name, bf_value) \ + bf_struct bf; \ + bf.data = val; \ + bf_value = bf.bf_name +#define BOARD_TYPE_BUILD_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, build_rev, res) +#define BOARD_TYPE_HW_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, hw_rev, res) +#define BOARD_TYPE_BOARD_ID_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, board_id, res) +#define CPLD_VERSION_REV_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, revision, res) +#define CPLD_VERSION_REL_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, release, res) +#define CPLD_PSU1_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu1, res) +#define CPLD_PSU2_PW_GOOD_GET(val, res) \ + READ_BF(cpld_reg_pw_good_t, val, psu2, res) +#define CPLD_PSU1_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu1, res) +#define CPLD_PSU2_PW_ABS_GET(val, res) \ + READ_BF(cpld_reg_pw_abs_t, val, psu2, res) +/* QSFP/SFP registers manipulation */ +#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \ +{ \ + if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \ + cpld_index = cpld1; \ + cpld_port = qsfp_port - 1; \ + } else if (CPLD_1_PORT_NUM < qsfp_port \ + && qsfp_port <= QSFP_MAX_PORT_NUM) { \ + cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \ + / CPLD_2_PORT_NUM; \ + cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \ + CPLD_2_PORT_NUM; \ + } else { \ + cpld_index = 0; \ + cpld_port = 0; \ + } \ +} +#define SFP_TO_CPLD_IDX(sfp_port, cpld_index) \ + (cpld_index = sfp_port - SFP_MIN_PORT_NUM) +#define QSFP_PORT_STATUS_REG(cpld_port) \ + (CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port) +#define QSFP_PORT_CONFIG_REG(cpld_port) \ + (CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port) +#define QSFP_PORT_INT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT) +#define QSFP_PORT_ABS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT) +#define QSFP_PORT_RESET_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_RESET_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define SFP_PORT_PRESENT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_PRESENT_BIT) + + #define SFP_PORT_TXFAULT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_TXFAULT_BIT) + #define SFP_PORT_RXLOS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_RXLOS_BIT) + #define SFP_PORT_TXDIS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TXDIS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_TXDIS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_RS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) + +/* CPLD access functions */ +extern int i2c_cpld_get_qsfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_qsfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val); +extern int i2c_cpld_get_sfp_port_status_val(u8 port_num); +extern int i2c_cpld_get_sfp_port_config_val(u8 port_num); +extern int i2c_cpld_set_sfp_port_config_val(u8 port_num, u8 reg_val); +extern u8 fp_port_to_phy_port(u8 fp_port); +#endif + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/qsfp-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/qsfp-monitor.service new file mode 100644 index 000000000000..584d6fcae895 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9100-monitor.service +After=s9100-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/s9100-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/s9100-monitor.service new file mode 100644 index 000000000000..5e074782a852 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/service/s9100-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9100_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/i2c_utils.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/i2c_utils.sh new file mode 100755 index 000000000000..4aefe153a67b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/i2c_utils.sh @@ -0,0 +1,1607 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.1.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +QSFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_IGB_DEVICE=0 +NUM_I801_DEVICE=0 +NUM_ISMT_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) +NUM_MUX1_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 2 )) +NUM_MUX1_CHAN1_DEVICE=$(( ${NUM_I801_DEVICE} + 3 )) +NUM_MUX1_CHAN2_DEVICE=$(( ${NUM_I801_DEVICE} + 4 )) +NUM_MUX1_CHAN3_DEVICE=$(( ${NUM_I801_DEVICE} + 5 )) +NUM_MUX1_CHAN4_DEVICE=$(( ${NUM_I801_DEVICE} + 6 )) +NUM_MUX1_CHAN5_DEVICE=$(( ${NUM_I801_DEVICE} + 7 )) +NUM_MUX1_CHAN6_DEVICE=$(( ${NUM_I801_DEVICE} + 8 )) +NUM_MUX1_CHAN7_DEVICE=$(( ${NUM_I801_DEVICE} + 9 )) +NUM_MUX3_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 10 )) +NUM_MUX4_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 18 )) +NUM_MUX5_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 26 )) +NUM_MUX6_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 34 )) + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +PATH_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" +PATH_MUX_CHAN1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN1_DEVICE}" +PATH_MUX_CHAN2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN2_DEVICE}" +PATH_MUX_CHAN3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}" +PATH_MUX_CHAN4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN4_DEVICE}" +PATH_MUX_CHAN5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN5_DEVICE}" +PATH_MUX_CHAN6_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}" +PATH_MUX_CHAN7_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}" + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +#GPIO Offset +GPIO_OFFSET=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "# Version : ${VERSION}" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-32]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-32]" + echo " : ${0} i2c_qsfp_type_get [1-32]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_front_temp" + echo " : ${0} i2c_rear_temp" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber on|off" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber on|off" + echo " : ${0} i2c_psu2_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod i2c_ismt + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_ismt + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x70' > ${PATH_ISMT_DEVICE}/new_device" + else + echo "pca9548 0x70 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX3_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN0_DEVICE}/new_device" + else + echo "pca9548 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX4_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x72' > ${PATH_MUX_CHAN1_DEVICE}/new_device" + else + echo "pca9548 0x72 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX5_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x73' > ${PATH_MUX_CHAN2_DEVICE}/new_device" + else + echo "pca9548 0x73 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX6_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x74' > ${PATH_MUX_CHAN3_DEVICE}/new_device" + else + echo "pca9548 0x74 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN6_DEVICE}-0075" ]; then + _retry "echo 'pca9546 0x75' > ${PATH_MUX_CHAN6_DEVICE}/new_device" + else + echo "pca9548 0x75 already init." + fi + #Init CPLD LED_CLR Register (Front Port LED) + i2cset -y ${NUM_I801_DEVICE} 0x33 0x34 0x10 + + rmmod coretemp + rmmod jc42 + rmmod w83795 + _i2c_temp_init + _i2c_volmon_init + modprobe coretemp + modprobe w83795 + modprobe jc42 + modprobe eeprom + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_fan_init + _i2c_io_exp_init + rmmod gpio_ich + _i2c_gpio_init + modprobe gpio_ich + _i2c_cpld_init + _i2c_qsfp_eeprom_init "new" + _i2c_mb_eeprom_init "new" + _i2c_psu_eeprom_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + _i2c_gpio_deinit + for mod in i2c_cpld coretemp jc42 w83795 eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_ismt i2c_i801; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done +} + +#Temperature sensor Init +function _i2c_temp_init { + echo -n "TEMP INIT..." + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x05 0x7F + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x04 0x0A + echo "Done" +} + +#FAN Init +function _i2c_fan_init { + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi + +} + +#VOLMON Init +function _i2c_volmon_init { + echo -n "VOLMON INIT..." + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x02 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x03 0x50 + i2cset -y -r ${NUM_I801_DEVICE} 0x2F 0x04 0x0A + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + #SMBUS0 IO_EXPENDER + i2cset -y -r ${NUM_I801_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 2 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 3 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x27 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x27 7 0xFF + + #SMBUS1 + #ABS + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 7 0xFF + + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 7 0xFF + + #Transcevior INT + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 7 0xFF + + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 7 0xFF + + echo "Init ZQSFP IO Expender" + echo "set ZQSFP LP_MODE = 0" + #set ZQSFP LP_MODE = 0 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 7 0x00 + + echo "set ZQSFP RST = 1" + #set ZQSFP RST = 1 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 3 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 3 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 7 0x00 + + echo "set ZQSFP mode" + #ZQSFP mode + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x24 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x25 7 0x00 + + #ZQSFP/SFP+/E-Card General + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x20 7 0xFF + + #LED board after PVT (S9100_IO_EXP_LED_ID) + echo "Init LED IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 7 0x00 + + #PSU I/O (S9100_IO_EXP_PSU_ID) + echo "Init PSU IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 6 0xBB + i2cset -y -r ${NUM_MUX1_CHAN6_DEVICE} 0x23 7 0xFF + + #FAN I/O (S9100_IO_EXP_FAN_ID) + echo "Init FAN IO Expender" + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 6 0xCC + i2cset -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x20 7 0xCC +} + +# To set the global variable GPIO_OFFSET +function _set_gpio_offset { + GPIO_OFFSET=0 + for d in `ls /sys/class/gpio/ | grep gpiochip` + do + gpiochip_no=${d##gpiochip} + if [ $gpiochip_no -gt 255 ]; then + GPIO_OFFSET=256 + break + fi + done + #echo "set GPIO_OFFSET=${GPIO_OFFSET}" +} + +#GPIO Init +function _i2c_gpio_init { + #ABS Port 0-15 (zQSFP00 ~ zQSFP15) + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + _set_gpio_offset + for((i=${GPIO_OFFSET}+240;i<=${GPIO_OFFSET}+255;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 240 > /sys/class/gpio/export + #echo 241 > /sys/class/gpio/export + #echo 242 > /sys/class/gpio/export + #echo 243 > /sys/class/gpio/export + #echo 244 > /sys/class/gpio/export + #echo 245 > /sys/class/gpio/export + #echo 246 > /sys/class/gpio/export + #echo 247 > /sys/class/gpio/export + #echo 248 > /sys/class/gpio/export + #echo 249 > /sys/class/gpio/export + #echo 250 > /sys/class/gpio/export + #echo 251 > /sys/class/gpio/export + #echo 252 > /sys/class/gpio/export + #echo 253 > /sys/class/gpio/export + #echo 254 > /sys/class/gpio/export + #echo 255 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio241/active_low #zQSFP00 + #echo 1 > /sys/class/gpio/gpio240/active_low #zQSFP01 + #echo 1 > /sys/class/gpio/gpio243/active_low #zQSFP02 + #echo 1 > /sys/class/gpio/gpio242/active_low #zQSFP03 + #echo 1 > /sys/class/gpio/gpio245/active_low #zQSFP04 + #echo 1 > /sys/class/gpio/gpio244/active_low #zQSFP05 + #echo 1 > /sys/class/gpio/gpio247/active_low #zQSFP06 + #echo 1 > /sys/class/gpio/gpio246/active_low #zQSFP07 + #echo 1 > /sys/class/gpio/gpio249/active_low #zQSFP08 + #echo 1 > /sys/class/gpio/gpio248/active_low #zQSFP09 + #echo 1 > /sys/class/gpio/gpio251/active_low #zQSFP10 + #echo 1 > /sys/class/gpio/gpio250/active_low #zQSFP11 + #echo 1 > /sys/class/gpio/gpio253/active_low #zQSFP12 + #echo 1 > /sys/class/gpio/gpio252/active_low #zQSFP13 + #echo 1 > /sys/class/gpio/gpio255/active_low #zQSFP14 + #echo 1 > /sys/class/gpio/gpio254/active_low #zQSFP15 + + #ABS Port 16-31 (zQSFP16 ~ zQSFP31) + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for((i=${GPIO_OFFSET}+224;i<=${GPIO_OFFSET}+239;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 224 > /sys/class/gpio/export + #echo 225 > /sys/class/gpio/export + #echo 226 > /sys/class/gpio/export + #echo 227 > /sys/class/gpio/export + #echo 228 > /sys/class/gpio/export + #echo 229 > /sys/class/gpio/export + #echo 230 > /sys/class/gpio/export + #echo 231 > /sys/class/gpio/export + #echo 232 > /sys/class/gpio/export + #echo 233 > /sys/class/gpio/export + #echo 234 > /sys/class/gpio/export + #echo 235 > /sys/class/gpio/export + #echo 236 > /sys/class/gpio/export + #echo 237 > /sys/class/gpio/export + #echo 238 > /sys/class/gpio/export + #echo 239 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio225/active_low #zQSFP16 + #echo 1 > /sys/class/gpio/gpio224/active_low #zQSFP17 + #echo 1 > /sys/class/gpio/gpio227/active_low #zQSFP18 + #echo 1 > /sys/class/gpio/gpio226/active_low #zQSFP19 + #echo 1 > /sys/class/gpio/gpio229/active_low #zQSFP20 + #echo 1 > /sys/class/gpio/gpio228/active_low #zQSFP21 + #echo 1 > /sys/class/gpio/gpio231/active_low #zQSFP22 + #echo 1 > /sys/class/gpio/gpio230/active_low #zQSFP23 + #echo 1 > /sys/class/gpio/gpio233/active_low #zQSFP24 + #echo 1 > /sys/class/gpio/gpio232/active_low #zQSFP25 + #echo 1 > /sys/class/gpio/gpio235/active_low #zQSFP26 + #echo 1 > /sys/class/gpio/gpio234/active_low #zQSFP27 + #echo 1 > /sys/class/gpio/gpio237/active_low #zQSFP28 + #echo 1 > /sys/class/gpio/gpio236/active_low #zQSFP29 + #echo 1 > /sys/class/gpio/gpio239/active_low #zQSFP30 + #echo 1 > /sys/class/gpio/gpio238/active_low #zQSFP31 + + #INT Port 0-15 (zQSFP00 ~ zQSFP15) + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for((i=${GPIO_OFFSET}+208;i<=${GPIO_OFFSET}+223;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 208 > /sys/class/gpio/export + #echo 209 > /sys/class/gpio/export + #echo 210 > /sys/class/gpio/export + #echo 211 > /sys/class/gpio/export + #echo 212 > /sys/class/gpio/export + #echo 213 > /sys/class/gpio/export + #echo 214 > /sys/class/gpio/export + #echo 215 > /sys/class/gpio/export + #echo 216 > /sys/class/gpio/export + #echo 217 > /sys/class/gpio/export + #echo 218 > /sys/class/gpio/export + #echo 219 > /sys/class/gpio/export + #echo 220 > /sys/class/gpio/export + #echo 221 > /sys/class/gpio/export + #echo 222 > /sys/class/gpio/export + #echo 223 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio208/active_low + #echo 1 > /sys/class/gpio/gpio209/active_low + #echo 1 > /sys/class/gpio/gpio210/active_low + #echo 1 > /sys/class/gpio/gpio211/active_low + #echo 1 > /sys/class/gpio/gpio212/active_low + #echo 1 > /sys/class/gpio/gpio213/active_low + #echo 1 > /sys/class/gpio/gpio214/active_low + #echo 1 > /sys/class/gpio/gpio215/active_low + #echo 1 > /sys/class/gpio/gpio216/active_low + #echo 1 > /sys/class/gpio/gpio217/active_low + #echo 1 > /sys/class/gpio/gpio218/active_low + #echo 1 > /sys/class/gpio/gpio219/active_low + #echo 1 > /sys/class/gpio/gpio220/active_low + #echo 1 > /sys/class/gpio/gpio221/active_low + #echo 1 > /sys/class/gpio/gpio222/active_low + #echo 1 > /sys/class/gpio/gpio223/active_low + + #INT Port 16-31 (zQSFP16 ~ zQSFP31) + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for((i=${GPIO_OFFSET}+192;i<=${GPIO_OFFSET}+207;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #echo 192 > /sys/class/gpio/export + #echo 193 > /sys/class/gpio/export + #echo 194 > /sys/class/gpio/export + #echo 195 > /sys/class/gpio/export + #echo 196 > /sys/class/gpio/export + #echo 197 > /sys/class/gpio/export + #echo 198 > /sys/class/gpio/export + #echo 199 > /sys/class/gpio/export + #echo 200 > /sys/class/gpio/export + #echo 201 > /sys/class/gpio/export + #echo 202 > /sys/class/gpio/export + #echo 203 > /sys/class/gpio/export + #echo 204 > /sys/class/gpio/export + #echo 205 > /sys/class/gpio/export + #echo 206 > /sys/class/gpio/export + #echo 207 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio192/active_low + #echo 1 > /sys/class/gpio/gpio193/active_low + #echo 1 > /sys/class/gpio/gpio194/active_low + #echo 1 > /sys/class/gpio/gpio195/active_low + #echo 1 > /sys/class/gpio/gpio196/active_low + #echo 1 > /sys/class/gpio/gpio197/active_low + #echo 1 > /sys/class/gpio/gpio198/active_low + #echo 1 > /sys/class/gpio/gpio199/active_low + #echo 1 > /sys/class/gpio/gpio200/active_low + #echo 1 > /sys/class/gpio/gpio201/active_low + #echo 1 > /sys/class/gpio/gpio202/active_low + #echo 1 > /sys/class/gpio/gpio203/active_low + #echo 1 > /sys/class/gpio/gpio204/active_low + #echo 1 > /sys/class/gpio/gpio205/active_low + #echo 1 > /sys/class/gpio/gpio206/active_low + #echo 1 > /sys/class/gpio/gpio207/active_low + + #LP Mode Port 0-15 + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for((i=${GPIO_OFFSET}+176;i<=${GPIO_OFFSET}+191;i++)); + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #echo 176 > /sys/class/gpio/export + #echo 177 > /sys/class/gpio/export + #echo 178 > /sys/class/gpio/export + #echo 179 > /sys/class/gpio/export + #echo 180 > /sys/class/gpio/export + #echo 181 > /sys/class/gpio/export + #echo 182 > /sys/class/gpio/export + #echo 183 > /sys/class/gpio/export + #echo 184 > /sys/class/gpio/export + #echo 185 > /sys/class/gpio/export + #echo 186 > /sys/class/gpio/export + #echo 187 > /sys/class/gpio/export + #echo 188 > /sys/class/gpio/export + #echo 189 > /sys/class/gpio/export + #echo 190 > /sys/class/gpio/export + #echo 191 > /sys/class/gpio/export + #echo out > /sys/class/gpio/gpio176/direction + #echo out > /sys/class/gpio/gpio177/direction + #echo out > /sys/class/gpio/gpio178/direction + #echo out > /sys/class/gpio/gpio179/direction + #echo out > /sys/class/gpio/gpio180/direction + #echo out > /sys/class/gpio/gpio181/direction + #echo out > /sys/class/gpio/gpio182/direction + #echo out > /sys/class/gpio/gpio183/direction + #echo out > /sys/class/gpio/gpio184/direction + #echo out > /sys/class/gpio/gpio185/direction + #echo out > /sys/class/gpio/gpio186/direction + #echo out > /sys/class/gpio/gpio187/direction + #echo out > /sys/class/gpio/gpio188/direction + #echo out > /sys/class/gpio/gpio189/direction + #echo out > /sys/class/gpio/gpio190/direction + #echo out > /sys/class/gpio/gpio191/direction + + #LP Mode Port 16-31 + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for((i=${GPIO_OFFSET}+160;i<=${GPIO_OFFSET}+175;i++)); + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #echo 160 > /sys/class/gpio/export + #echo 161 > /sys/class/gpio/export + #echo 162 > /sys/class/gpio/export + #echo 163 > /sys/class/gpio/export + #echo 164 > /sys/class/gpio/export + #echo 165 > /sys/class/gpio/export + #echo 166 > /sys/class/gpio/export + #echo 167 > /sys/class/gpio/export + #echo 168 > /sys/class/gpio/export + #echo 169 > /sys/class/gpio/export + #echo 170 > /sys/class/gpio/export + #echo 171 > /sys/class/gpio/export + #echo 172 > /sys/class/gpio/export + #echo 173 > /sys/class/gpio/export + #echo 174 > /sys/class/gpio/export + #echo 175 > /sys/class/gpio/export + #echo out > /sys/class/gpio/gpio160/direction + #echo out > /sys/class/gpio/gpio161/direction + #echo out > /sys/class/gpio/gpio162/direction + #echo out > /sys/class/gpio/gpio163/direction + #echo out > /sys/class/gpio/gpio164/direction + #echo out > /sys/class/gpio/gpio165/direction + #echo out > /sys/class/gpio/gpio166/direction + #echo out > /sys/class/gpio/gpio167/direction + #echo out > /sys/class/gpio/gpio168/direction + #echo out > /sys/class/gpio/gpio169/direction + #echo out > /sys/class/gpio/gpio170/direction + #echo out > /sys/class/gpio/gpio171/direction + #echo out > /sys/class/gpio/gpio172/direction + #echo out > /sys/class/gpio/gpio173/direction + #echo out > /sys/class/gpio/gpio174/direction + #echo out > /sys/class/gpio/gpio175/direction + + #RST Port 0-15 + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for((i=${GPIO_OFFSET}+144;i<=${GPIO_OFFSET}+159;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo low > /sys/class/gpio/gpio${i}/direction + #echo out > /sys/class/gpio/gpio${i}/direction + #echo 0 > /sys/class/gpio/gpio${i}/value + done + + #echo 144 > /sys/class/gpio/export + #echo 145 > /sys/class/gpio/export + #echo 146 > /sys/class/gpio/export + #echo 147 > /sys/class/gpio/export + #echo 148 > /sys/class/gpio/export + #echo 149 > /sys/class/gpio/export + #echo 150 > /sys/class/gpio/export + #echo 151 > /sys/class/gpio/export + #echo 152 > /sys/class/gpio/export + #echo 153 > /sys/class/gpio/export + #echo 154 > /sys/class/gpio/export + #echo 155 > /sys/class/gpio/export + #echo 156 > /sys/class/gpio/export + #echo 157 > /sys/class/gpio/export + #echo 158 > /sys/class/gpio/export + #echo 159 > /sys/class/gpio/export + #echo out > /sys/class/gpio/gpio144/direction + #echo out > /sys/class/gpio/gpio145/direction + #echo out > /sys/class/gpio/gpio146/direction + #echo out > /sys/class/gpio/gpio147/direction + #echo out > /sys/class/gpio/gpio148/direction + #echo out > /sys/class/gpio/gpio149/direction + #echo out > /sys/class/gpio/gpio150/direction + #echo out > /sys/class/gpio/gpio151/direction + #echo out > /sys/class/gpio/gpio152/direction + #echo out > /sys/class/gpio/gpio153/direction + #echo out > /sys/class/gpio/gpio154/direction + #echo out > /sys/class/gpio/gpio155/direction + #echo out > /sys/class/gpio/gpio156/direction + #echo out > /sys/class/gpio/gpio157/direction + #echo out > /sys/class/gpio/gpio158/direction + #echo out > /sys/class/gpio/gpio159/direction + #echo 1 > /sys/class/gpio/gpio144/active_low + #echo 1 > /sys/class/gpio/gpio145/active_low + #echo 1 > /sys/class/gpio/gpio146/active_low + #echo 1 > /sys/class/gpio/gpio147/active_low + #echo 1 > /sys/class/gpio/gpio148/active_low + #echo 1 > /sys/class/gpio/gpio149/active_low + #echo 1 > /sys/class/gpio/gpio150/active_low + #echo 1 > /sys/class/gpio/gpio151/active_low + #echo 1 > /sys/class/gpio/gpio152/active_low + #echo 1 > /sys/class/gpio/gpio153/active_low + #echo 1 > /sys/class/gpio/gpio154/active_low + #echo 1 > /sys/class/gpio/gpio155/active_low + #echo 1 > /sys/class/gpio/gpio156/active_low + #echo 1 > /sys/class/gpio/gpio157/active_low + #echo 1 > /sys/class/gpio/gpio158/active_low + #echo 1 > /sys/class/gpio/gpio159/active_low + #echo 0 > /sys/class/gpio/gpio144/value + #echo 0 > /sys/class/gpio/gpio145/value + #echo 0 > /sys/class/gpio/gpio146/value + #echo 0 > /sys/class/gpio/gpio147/value + #echo 0 > /sys/class/gpio/gpio148/value + #echo 0 > /sys/class/gpio/gpio149/value + #echo 0 > /sys/class/gpio/gpio150/value + #echo 0 > /sys/class/gpio/gpio151/value + #echo 0 > /sys/class/gpio/gpio152/value + #echo 0 > /sys/class/gpio/gpio153/value + #echo 0 > /sys/class/gpio/gpio154/value + #echo 0 > /sys/class/gpio/gpio155/value + #echo 0 > /sys/class/gpio/gpio156/value + #echo 0 > /sys/class/gpio/gpio157/value + #echo 0 > /sys/class/gpio/gpio158/value + #echo 0 > /sys/class/gpio/gpio159/value + + #RST Port 16-31 + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for((i=${GPIO_OFFSET}+128;i<=${GPIO_OFFSET}+143;i++)); + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo low > /sys/class/gpio/gpio${i}/direction + #echo out > /sys/class/gpio/gpio${i}/direction + #echo 0 > /sys/class/gpio/gpio${i}/value + done + + #echo 128 > /sys/class/gpio/export + #echo 129 > /sys/class/gpio/export + #echo 130 > /sys/class/gpio/export + #echo 131 > /sys/class/gpio/export + #echo 132 > /sys/class/gpio/export + #echo 133 > /sys/class/gpio/export + #echo 134 > /sys/class/gpio/export + #echo 135 > /sys/class/gpio/export + #echo 136 > /sys/class/gpio/export + #echo 137 > /sys/class/gpio/export + #echo 138 > /sys/class/gpio/export + #echo 139 > /sys/class/gpio/export + #echo 140 > /sys/class/gpio/export + #echo 141 > /sys/class/gpio/export + #echo 142 > /sys/class/gpio/export + #echo 143 > /sys/class/gpio/export + #echo out > /sys/class/gpio/gpio128/direction + #echo out > /sys/class/gpio/gpio129/direction + #echo out > /sys/class/gpio/gpio130/direction + #echo out > /sys/class/gpio/gpio131/direction + #echo out > /sys/class/gpio/gpio132/direction + #echo out > /sys/class/gpio/gpio133/direction + #echo out > /sys/class/gpio/gpio134/direction + #echo out > /sys/class/gpio/gpio135/direction + #echo out > /sys/class/gpio/gpio136/direction + #echo out > /sys/class/gpio/gpio137/direction + #echo out > /sys/class/gpio/gpio138/direction + #echo out > /sys/class/gpio/gpio139/direction + #echo out > /sys/class/gpio/gpio140/direction + #echo out > /sys/class/gpio/gpio141/direction + #echo out > /sys/class/gpio/gpio142/direction + #echo out > /sys/class/gpio/gpio143/direction + #echo 1 > /sys/class/gpio/gpio128/active_low + #echo 1 > /sys/class/gpio/gpio129/active_low + #echo 1 > /sys/class/gpio/gpio130/active_low + #echo 1 > /sys/class/gpio/gpio131/active_low + #echo 1 > /sys/class/gpio/gpio132/active_low + #echo 1 > /sys/class/gpio/gpio133/active_low + #echo 1 > /sys/class/gpio/gpio134/active_low + #echo 1 > /sys/class/gpio/gpio135/active_low + #echo 1 > /sys/class/gpio/gpio136/active_low + #echo 1 > /sys/class/gpio/gpio137/active_low + #echo 1 > /sys/class/gpio/gpio138/active_low + #echo 1 > /sys/class/gpio/gpio139/active_low + #echo 1 > /sys/class/gpio/gpio140/active_low + #echo 1 > /sys/class/gpio/gpio141/active_low + #echo 1 > /sys/class/gpio/gpio142/active_low + #echo 1 > /sys/class/gpio/gpio143/active_low + #echo 0 > /sys/class/gpio/gpio128/value + #echo 0 > /sys/class/gpio/gpio129/value + #echo 0 > /sys/class/gpio/gpio130/value + #echo 0 > /sys/class/gpio/gpio131/value + #echo 0 > /sys/class/gpio/gpio132/value + #echo 0 > /sys/class/gpio/gpio133/value + #echo 0 > /sys/class/gpio/gpio134/value + #echo 0 > /sys/class/gpio/gpio135/value + #echo 0 > /sys/class/gpio/gpio136/value + #echo 0 > /sys/class/gpio/gpio137/value + #echo 0 > /sys/class/gpio/gpio138/value + #echo 0 > /sys/class/gpio/gpio139/value + #echo 0 > /sys/class/gpio/gpio140/value + #echo 0 > /sys/class/gpio/gpio141/value + #echo 0 > /sys/class/gpio/gpio142/value + #echo 0 > /sys/class/gpio/gpio143/value + +} + +#GPIO DeInit +function _i2c_gpio_deinit { + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device +} + +#I2C CPLD init +function _i2c_cpld_init { + echo "=========================================================" + echo "# Description: I2C CPLD Init..." + echo "=========================================================" + + ## modprobe i2c_cpld + modprobe i2c_cpld + ## Add CPLD device + echo "i2c_cpld 0x33" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}/new_device + + echo "done..." +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C LED TEST..." + echo "=========================================================" + #sys led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x7F + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xBF + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xF7 + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFB + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xDF + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xEF + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFD + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFE + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED + i2cset -y ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + _pause 'Check turn off all LEDs and Press [Enter] key to continue...' + echo "done..." +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x20 + dataAddr=0 + eeprombusbase=${NUM_MUX3_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x20 + dataAddr=1 + eeprombusbase=${NUM_MUX4_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+240)) + #gpioBase=240 + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x21 + dataAddr=0 + eeprombusbase=${NUM_MUX5_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+224-16)) + #gpioBase=$((224 - 16)) + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x21 + dataAddr=1 + eeprombusbase=${NUM_MUX6_CHAN0_DEVICE} + gpioBase=$((${GPIO_OFFSET}+224-16)) + #gpioBase=$((224 - 16)) + ;; + #33) + # i2cbus=${NUM_MUX1_CHAN7_DEVICE} + # regAddr=0x22 + # dataAddr=0 + # gpioBase=${GPIO_OFFSET} + #;; + #34) + # i2cbus=${NUM_MUX1_CHAN7_DEVICE} + # regAddr=0x22 + # dataAddr=1 + # gpioBase=${GPIO_OFFSET} + #;; + *) + echo "Please input 1~32" + exit + ;; + esac +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + local port=$1 + eeprombusidx=$(( ${port} % 8)) + case $eeprombusidx in + 1) + eeprombus=$(( $eeprombusbase + 1 )) + eepromAddr=0x50 + ;; + 2) + eeprombus=$(( $eeprombusbase + 0 )) + eepromAddr=0x50 + ;; + 3) + eeprombus=$(( $eeprombusbase + 3 )) + eepromAddr=0x50 + ;; + 4) + eeprombus=$(( $eeprombusbase + 2 )) + eepromAddr=0x50 + ;; + 5) + eeprombus=$(( $eeprombusbase + 5 )) + eepromAddr=0x50 + ;; + 6) + eeprombus=$(( $eeprombusbase + 4 )) + eepromAddr=0x50 + ;; + 7) + eeprombus=$(( $eeprombusbase + 7 )) + eepromAddr=0x50 + ;; + 0) + eeprombus=$(( $eeprombusbase + 6 )) + eepromAddr=0x50 + ;; + esac +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo -n "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + local i + for i in {1..32}; + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done + echo "DONE" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN7_DEVICE}-0054 ]; then + echo "mb_eeprom 0x54" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN7_DEVICE}-0054 ]; then + echo "0x54" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}/delete_device + fi + echo "DONE" +} + +#PSU EEPROM init +function _i2c_psu_eeprom_init { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Init..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}/new_device + + ## PUS(1) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}/new_device + + echo "done..." +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + _qsfp_eeprom_var_set ${QSFP_PORT} + + #Get QSFP EEPROM info + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + ## modprobe eeprom + modprobe eeprom + ## PUS(0) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN6_DEVICE}-0050/eeprom | hexdump -C + + ## PUS(1) EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN7_DEVICE}-0050/eeprom | hexdump -C + + echo "done..." +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_MUX1_CHAN7_DEVICE}-0054/eeprom | hexdump -C + echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x80 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x40 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x20 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x10 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + case ${FAN_TRAY} in + 1) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN7_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN7_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN7_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_MUX1_CHAN7_DEVICE} $i2cAddr $ioPort 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x08 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x04 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x02 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x01 -y -r ${NUM_MUX1_CHAN7_DEVICE} 0x22 2 0xFF + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Get Board Version and Type +function _i2c_board_type_get { + boardType=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_board_type` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev + +} + +#Get CPLD Version +function _i2c_cpld_version { + cpldRev=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_version` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Get PSU Status +function _i2c_psu_status { + psuPresent=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_abs` + psu1Exist=$(($((($psuPresent) & 0x01))?0:1)) + psu2Exist=$(($((($psuPresent) & 0x02))?0:1)) + psuPwGood=`cat ${PATH_SYS_I2C_DEVICES}/0-0033/cpld_pw_good` + psu1PwGood=$(($((($psuPwGood) >> 3 & 0x01))?1:0)) + psu2PwGood=$(($((($psuPwGood) >> 3 & 0x02))?1:0)) + printf "PSU1 Exist:%d PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Get Front Sensor Temperature +function _i2c_front_temp { + #Front MAC + sensors | grep 'Front MAC Temp' -A 1 +} + +#Get Rear Sensor Temperature +function _i2c_rear_temp { + #Rear MAC + sensors | grep 'Rear MAC Temp' -A 1 +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + _set_gpio_offset + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_front_temp" ]; then + _i2c_front_temp + elif [ "${EXEC_FUNC}" == "i2c_rear_temp" ]; then + _i2c_rear_temp + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_temp_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main 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 new file mode 100755 index 000000000000..7776493bc20a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..31}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`sonic-db-cli ASIC_DB HLEN HIDDEN` + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_si_cfg.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_si_cfg.sh new file mode 100755 index 000000000000..f2bf35bc7715 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/qsfp_si_cfg.sh @@ -0,0 +1,339 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +TYPE=${1} +PORT=${2} + +#QSFP Optical +function _qsfp_optical_si_set { + case ${PORT} in + 0) + bcmcmd "phy ce0 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x39;phy ce0 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x37;phy ce0 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce0 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x39" + bcmcmd "phy ce0 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x37;phy ce0 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce0 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x35;phy ce0 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x37" + bcmcmd "phy ce0 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce0 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce0 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce0 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + ;; + 1) + bcmcmd "phy ce1 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x3E;phy ce1 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x32;phy ce1 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce1 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x38" + bcmcmd "phy ce1 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x38;phy ce1 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xE AMS_TX_DRIVERMODE=0x0;phy ce1 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x33;phy ce1 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3D" + bcmcmd "phy ce1 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce1 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x35;phy ce1 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3B;phy ce1 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xE AMS_TX_DRIVERMODE=0x0" + ;; + 2) + bcmcmd "phy ce2 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x35;phy ce2 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x3B;phy ce2 AMS_TX_CTL2r AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0" + ;; + 3) + bcmcmd "phy ce3 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x3B;phy ce3 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x35;phy ce3 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce3 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x35" + bcmcmd "phy ce3 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x37;phy ce3 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0;phy ce3 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x35;phy ce3 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x37" + bcmcmd "phy ce3 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0;phy ce3 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x35;phy ce3 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x37;phy ce3 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0" + ;; + 4) + bcmcmd "phy ce4 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce4 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce4 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce4 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x33" + bcmcmd "phy ce4 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3D;phy ce4 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce4 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce4 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce4 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce4 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce4 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce4 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 5) + bcmcmd "phy ce5 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce5 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce5 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce5 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x35" + bcmcmd "phy ce5 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3B;phy ce5 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce5 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce5 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce5 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce5 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce5 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce5 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 6) + bcmcmd "phy ce6 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce6 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce6 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce6 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x36" + bcmcmd "phy ce6 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3A;phy ce6 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0;phy ce6 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce6 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce6 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce6 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce6 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce6 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 7) + bcmcmd "phy ce7 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce7 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce7 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce7 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce7 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce7 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce7 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce7 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce7 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce7 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce7 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce7 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 8) + bcmcmd "phy ce8 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce8 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce8 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce8 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x2C" + bcmcmd "phy ce8 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x44;phy ce8 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce8 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce8 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce8 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce8 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce8 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce8 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 9) + bcmcmd "phy ce9 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce9 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce9 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce9 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x2B" + bcmcmd "phy ce9 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x45;phy ce9 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce9 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce9 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce9 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce9 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce9 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce9 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 10) + bcmcmd "phy ce10 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce10 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce10 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce10 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x2B" + bcmcmd "phy ce10 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x45;phy ce10 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0;phy ce10 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce10 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce10 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce10 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce10 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce10 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 11) + bcmcmd "phy ce11 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce11 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce11 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce11 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x2C" + bcmcmd "phy ce11 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x44;phy ce11 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce11 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce11 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce11 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce11 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce11 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce11 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 12) + bcmcmd "phy ce12 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce12 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce12 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce12 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x25" + bcmcmd "phy ce12 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x4B;phy ce12 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x5 AMS_TX_DRIVERMODE=0x0;phy ce12 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce12 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce12 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce12 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce12 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce12 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 13) + bcmcmd "phy ce13 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x25;phy ce13 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x4B;phy ce13 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 14) + bcmcmd "phy ce14 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x25;phy ce14 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x4B;phy ce14 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0" + ;; + 15) + bcmcmd "phy ce15 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce15 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce15 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0;phy ce15 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x25" + bcmcmd "phy ce15 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x4B;phy ce15 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x5 AMS_TX_DRIVERMODE=0x0;phy ce15 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x25;phy ce15 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x4B" + bcmcmd "phy ce15 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0;phy ce15 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x25;phy ce15 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x4B;phy ce15 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0" + ;; + 16) + bcmcmd "phy ce16 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x27;phy ce16 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x49;phy ce16 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0" + ;; + 17) + bcmcmd "phy ce17 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x25;phy ce17 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4B;phy ce17 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce17 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce17 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce17 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce17 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce17 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce17 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce17 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce17 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40;phy ce17 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + ;; + 18) + bcmcmd "phy ce18 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x20;phy ce18 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x50;phy ce18 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0" + ;; + 19) + bcmcmd "phy ce19 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x20;phy ce19 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x50;phy ce19 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0" + ;; + 20) + bcmcmd "phy ce20 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x20;phy ce20 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x50;phy ce20 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0" + ;; + 21) + bcmcmd "phy ce21 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x17;phy ce21 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x59;phy ce21 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0;phy ce21 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x17" + bcmcmd "phy ce21 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x59;phy ce21 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0;phy ce21 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x20;phy ce21 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x50" + bcmcmd "phy ce21 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0;phy ce21 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x20;phy ce21 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x50;phy ce21 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x2 AMS_TX_DRIVERMODE=0x0" + ;; + 22) + bcmcmd "phy ce22 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x25;phy ce22 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x4B;phy ce22 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0" + ;; + 23) + bcmcmd "phy ce23 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x25;phy ce23 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x4B;phy ce23 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x7 AMS_TX_DRIVERMODE=0x0" + ;; + 24) + bcmcmd "phy ce24 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x23;phy ce24 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x4D;phy ce24 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce24 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x29" + bcmcmd "phy ce24 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x47;phy ce24 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce24 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x29;phy ce24 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x47" + bcmcmd "phy ce24 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0;phy ce24 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x29;phy ce24 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x47;phy ce24 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0" + ;; + 25) + bcmcmd "phy ce25 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x29;phy ce25 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x47;phy ce25 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce25 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x29" + bcmcmd "phy ce25 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x47;phy ce25 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce25 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x29;phy ce25 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x47" + bcmcmd "phy ce25 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0;phy ce25 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x29;phy ce25 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x47;phy ce25 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0" + ;; + 26) + bcmcmd "phy ce26 CL93N72_UT_CTL2r CL93N72_TXFIR_POST=0x30;phy ce26 CL93N72_UT_CTL3r CL93N72_TXFIR_MAIN=0x40;phy ce26 AMS_TX_CTL2r AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 27) + bcmcmd "phy ce27 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce27 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce27 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce27 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce27 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce27 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce27 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce27 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce27 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0;phy ce27 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce27 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce27 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 28) + bcmcmd "phy ce28 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce28 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce28 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce28 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce28 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce28 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce28 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce28 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce28 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce28 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce28 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce28 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 29) + bcmcmd "phy ce29 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce29 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce29 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce29 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce29 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce29 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce29 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce29 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce29 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0;phy ce29 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce29 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce29 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 30) + bcmcmd "phy ce30 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x30;phy ce30 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x40;phy ce30 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce30 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30" + bcmcmd "phy ce30 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce30 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0;phy ce30 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce30 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce30 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0;phy ce30 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce30 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce30 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 31) + bcmcmd "phy ce31 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x39;phy ce31 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x37;phy ce31 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0;phy ce31 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x39" + bcmcmd "phy ce31 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x37;phy ce31 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0;phy ce31 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x30;phy ce31 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x40" + bcmcmd "phy ce31 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0;phy ce31 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce31 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce31 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + *) + echo "Unknown Port" + return + ;; + esac +} + +function _qsfp_dac_si_set { + case ${PORT} in + 0) + bcmcmd "phy ce0 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce0 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce0 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce0 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce0 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x1C;phy ce0 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x20;phy ce0 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x34;phy ce0 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce0 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce0 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce0 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce0 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce0 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x18;phy ce0 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x24;phy ce0 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x34;phy ce0 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + ;; + 1) + bcmcmd "phy ce1 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce1 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce1 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce1 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce1 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x1C;phy ce1 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x20;phy ce1 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x34;phy ce1 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce1 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce1 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce1 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce1 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce1 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x1C;phy ce1 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x20;phy ce1 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x34;phy ce1 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + ;; + 2) + bcmcmd "phy ce2 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce2 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce2 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce2 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce2 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x18;phy ce2 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x24;phy ce2 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x34;phy ce2 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xD AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce2 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce2 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce2 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce2 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce2 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x14;phy ce2 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x20;phy ce2 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3C;phy ce2 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xD AMS_TX_DRIVERMODE=0x0" + ;; + 3) + bcmcmd "phy ce3 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce3 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce3 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce3 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce3 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x14;phy ce3 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x20;phy ce3 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3C;phy ce3 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xD AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce3 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce3 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce3 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce3 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce3 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x18;phy ce3 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x24;phy ce3 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x34;phy ce3 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xD AMS_TX_DRIVERMODE=0x0" + ;; + 4) + bcmcmd "phy ce4 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce4 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce4 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce4 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce4 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce4 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x33;phy ce4 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3D;phy ce4 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce4 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce4 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce4 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce4 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce4 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce4 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce4 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce4 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 5) + bcmcmd "phy ce5 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce5 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce5 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce5 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce5 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce5 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30;phy ce5 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce5 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xB AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce5 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce5 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce5 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce5 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce5 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce5 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce5 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce5 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 6) + bcmcmd "phy ce6 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce6 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce6 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce6 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce6 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce6 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x36;phy ce6 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3A;phy ce6 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce6 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce6 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce6 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce6 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce6 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce6 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce6 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce6 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + ;; + 7) + bcmcmd "phy ce7 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce7 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce7 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce7 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce7 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce7 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30;phy ce7 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce7 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce7 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce7 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce7 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce7 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce7 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce7 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce7 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce7 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + ;; + 8) + ;; + 9) + ;; + 10) + ;; + 11) + ;; + 12) + ;; + 13) + ;; + 14) + ;; + 15) + ;; + 16) + ;; + 17) + ;; + 18) + ;; + 19) + ;; + 20) + ;; + 21) + ;; + 22) + ;; + 23) + ;; + 24) + bcmcmd "phy ce24 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce24 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce24 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce24 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce24 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce24 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x29;phy ce24 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x47;phy ce24 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce24 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0X1F;phy ce24 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce24 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce24 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce24 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce24 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x29;phy ce24 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x47;phy ce24 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0" + ;; + 25) + bcmcmd "phy ce25 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce25 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce25 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce25 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce25 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce25 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x29;phy ce25 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x47;phy ce25 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x8 AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce25 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce25 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce25 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce25 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce25 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce25 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x29;phy ce25 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x47;phy ce25 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x4 AMS_TX_DRIVERMODE=0x0" + ;; + 26) + bcmcmd "phy ce26 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce26 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce26 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce26 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce26 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce26 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30;phy ce26 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce26 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xA AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce26 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce26 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce26 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce26 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce26 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce26 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce26 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce26 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 27) + bcmcmd "phy ce27 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce27 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce27 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce27 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce27 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x0;phy ce27 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x30;phy ce27 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x40;phy ce27 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce27 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce27 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce27 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce27 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce27 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x0;phy ce27 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x30;phy ce27 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x40;phy ce27 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0x9 AMS_TX_DRIVERMODE=0x0" + ;; + 28) + bcmcmd "phy ce28 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce28 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce28 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce28 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce28 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x10;phy ce28 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x18;phy ce28 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3C;phy ce28 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce28 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce28 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce28 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce28 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce28 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x10;phy ce28 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x1C;phy ce28 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3C;phy ce28 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + ;; + 29) + bcmcmd "phy ce29 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce29 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce29 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce29 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce29 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x10;phy ce29 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x20;phy ce29 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3C;phy ce29 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce29 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce29 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce29 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce29 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce29 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x10;phy ce29 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x20;phy ce29 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3C;phy ce29 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + ;; + 30) + bcmcmd "phy ce30 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce30 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce30 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce30 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce30 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x10;phy ce30 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x24;phy ce30 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3C;phy ce30 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce30 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce30 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce30 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce30 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce30 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x8;phy ce30 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x24;phy ce30 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3C;phy ce30 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + ;; + 31) + bcmcmd "phy ce31 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_PRE=0x1F;phy ce31 CL93N72_UT_CTL2r.0 CL93N72_TXFIR_POST=0x15;phy ce31 CL93N72_UT_CTL3r.0 CL93N72_TXFIR_MAIN=0x3C;phy ce31 AMS_TX_CTL2r.0 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce31 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_PRE=0x10;phy ce31 CL93N72_UT_CTL2r.1 CL93N72_TXFIR_POST=0x24;phy ce31 CL93N72_UT_CTL3r.1 CL93N72_TXFIR_MAIN=0x3C;phy ce31 AMS_TX_CTL2r.1 AMS_TX_AMP_CTL=0xC AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce31 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_PRE=0x1F;phy ce31 CL93N72_UT_CTL2r.2 CL93N72_TXFIR_POST=0x15;phy ce31 CL93N72_UT_CTL3r.2 CL93N72_TXFIR_MAIN=0x3C;phy ce31 AMS_TX_CTL2r.2 AMS_TX_AMP_CTL=0xF AMS_TX_DRIVERMODE=0x0" + bcmcmd "phy ce31 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_PRE=0x14;phy ce31 CL93N72_UT_CTL2r.3 CL93N72_TXFIR_POST=0x20;phy ce31 CL93N72_UT_CTL3r.3 CL93N72_TXFIR_MAIN=0x3C;phy ce31 AMS_TX_CTL2r.3 AMS_TX_AMP_CTL=0xE AMS_TX_DRIVERMODE=0x0" + ;; + *) + echo "Unknown Port" + return + ;; + esac +} + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} optical [0-31]" + echo " : ${0} dac [0-31]" + echo "----------------------------------------------------" +} + +#Main Function +function _main { + + if [ "${TYPE}" == "help" ]; then + _help + elif [ "${TYPE}" == "optical" ]; then + _qsfp_optical_si_set + elif [ "${TYPE}" == "dac" ]; then + _qsfp_dac_si_set + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/s9100_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/s9100_monitor.sh new file mode 100755 index 000000000000..974da6d5001f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9100/utils/s9100_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/README.md b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/README.md new file mode 100644 index 000000000000..940d15f497c9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/README.md @@ -0,0 +1,184 @@ +# Ingrasys S9200-64X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9200-64X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9200-64X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9200-64X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S9200-64X. + +### I2C iSMT + +The I2C iSMT module on S9200-64X can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S9200-64X. + +### I2C PCA9548 +The PCA9548 module on S9200-64X can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9200-64X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9200-64X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9200-64x package is installed on the S9200-64X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon5/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm2` setting fan1/fan3/fan5/fan7. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon5/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-64] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-64] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/Makefile b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/Makefile new file mode 100755 index 000000000000..1a9e4e314e8e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m := eeprom_mb.o +obj-m += cpld.o +obj-m += ingrasys_s9200_64x_psu.o diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/cpld.c b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/cpld.c new file mode 100755 index 000000000000..b15ee836b187 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/cpld.c @@ -0,0 +1,498 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define S9200_MUX_BASE_NR 0 +#define CPLD_DEVICE_NUM 5 + +/* CPLD registers */ +#define CPLD_REG_REV 0x01 +#define CPLD_REG_ID 0x02 +#define CPLD_REG_10G_MUX 0x41 + +/* QSFP signal bit in register */ +#define BIT_RST 0 +#define BIT_LPM 2 +#define BIT_INT 0 +#define BIT_ABS 1 + +static void device_release(struct device *dev) +{ + return; +} + +/* + * S9200 CPLD register addresses + */ +static const int int_abs_reg[CPLD_DEVICE_NUM][2]= { + {0x20, 0x2B}, + {0x20, 0x2C}, + {0x20, 0x2C}, + {0x20, 0x2C}, + {0x20, 0x2C} +}; + +static const int rst_lp_reg[CPLD_DEVICE_NUM][2]= { + {0x30, 0x3B}, + {0x30, 0x3C}, + {0x30, 0x3C}, + {0x30, 0x3C}, + {0x30, 0x3C} +}; + +/* + * S9200 CPLD + */ + +enum cpld_type { + cpld_1, + cpld_2, + cpld_3, + cpld_4, + cpld_5, +}; + +enum qsfp_signal { + sig_int, + sig_abs, + sig_rst, + sig_lpm +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data s9200_cpld_platform_data[] = { + [cpld_1] = { + .reg_addr = 0x33, + }, + + [cpld_2] = { + .reg_addr = 0x33, + }, + + [cpld_3] = { + .reg_addr = 0x33, + }, + + [cpld_4] = { + .reg_addr = 0x33, + }, + + [cpld_5] = { + .reg_addr = 0x33, + }, +}; + +static struct platform_device s9200_cpld = { + .name = "ingrasys-s9200-cpld", + .id = 0, + .dev = { + .platform_data = s9200_cpld_platform_data, + .release = device_release + }, +}; + +/* + * S9200 I2C DEVICES + */ + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; + +/* module_platform_driver */ +static ssize_t get_cpld_reg(struct device *dev, struct device_attribute *devattr, char *buf, int signal) +{ + int ret; + u64 data = 0; + u64 shift = 0; + int i = 0; + int j = 0; + int port = 0; + int bit = 0; + int bit_mask = 0; + int (*reg)[CPLD_DEVICE_NUM][2]; + struct cpld_platform_data *pdata = NULL; + + pdata = dev->platform_data; + + switch(signal) { + case sig_int: + bit = BIT_INT; + reg = (typeof(reg)) &int_abs_reg; + break; + case sig_abs: + bit = BIT_ABS; + reg = (typeof(reg)) &int_abs_reg; + break; + case sig_rst: + bit = BIT_RST; + reg = (typeof(reg)) &rst_lp_reg; + break; + case sig_lpm: + bit = BIT_LPM; + reg = (typeof(reg)) &rst_lp_reg; + break; + default: + return sprintf(buf, "na"); + } + bit_mask = 0x1 << bit; + + for (i=0; i> bit)) << port; + data |= shift; + port++; + } + } + + return sprintf(buf, "0x%016llx\n", data); +} + +static ssize_t set_cpld_reg(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count, int signal) +{ + unsigned long data; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + u8 current_reg_val = 0; + u8 new_reg_val = 0; + int value; + int i = 0; + int j = 0; + int port = 0; + int ret = 0; + int bit = 0; + int (*reg)[CPLD_DEVICE_NUM][2]; + + err = kstrtoul(buf, 16, &data); + if (err) + return err; + + switch(signal) { + case sig_int: + bit = BIT_INT; + reg = (typeof(reg)) &int_abs_reg; + break; + case sig_abs: + bit = BIT_ABS; + reg = (typeof(reg)) &int_abs_reg; + break; + case sig_rst: + bit = BIT_RST; + reg = (typeof(reg)) &rst_lp_reg; + break; + case sig_lpm: + bit = BIT_LPM; + reg = (typeof(reg)) &rst_lp_reg; + break; + default: + return sprintf(buf, "na"); + } + + for (i=0; i> port) & 0x1; + + //set value on bit N of new_reg_val + if (value > 0) { + new_reg_val = current_reg_val | (u8) (0x1 << bit); + } else { + new_reg_val = current_reg_val & (u8) ~(0x1 << bit); + } + //write reg value if changed + if (current_reg_val != new_reg_val) { + ret = i2c_smbus_write_byte_data(pdata[i].client, j, + (u8)(new_reg_val)); + if (ret < 0){ + return ret; + } + } + port++; + } + } + + return count; +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf) +{ + return get_cpld_reg(dev, devattr, buf, sig_lpm); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + return set_cpld_reg(dev, devattr, buf, count, sig_lpm); +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, char *buf) +{ + return get_cpld_reg(dev, devattr, buf, sig_rst); +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + return set_cpld_reg(dev, devattr, buf, count, sig_rst); +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, char *buf) +{ + return get_cpld_reg(dev, devattr, buf, sig_abs); +} + +static ssize_t get_int(struct device *dev, struct device_attribute *devattr, char *buf) +{ + return get_cpld_reg(dev, devattr, buf, sig_int); +} + +static ssize_t get_cpld_version(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int i = 0; + int cnt = 0; + u8 reg_val_rev[CPLD_DEVICE_NUM]; + u8 reg_val_id[CPLD_DEVICE_NUM]; + + struct cpld_platform_data *pdata = dev->platform_data; + + //get reg value + for (i=0; i> 6 & 0x1, + reg_val_id[i] & 0x7); + } + + return cnt; +} + +static ssize_t set_10g_mux(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + u8 data; + u8 current_reg_val = 0; + u8 new_reg_val = 0; + int cpld_dev_num=cpld_1; + int reg_offset=CPLD_REG_10G_MUX; + int err; + struct cpld_platform_data *pdata = dev->platform_data; + int value; + int i = 0; + int port = 0; + int ret = 0; + int bit = 0; + + err = kstrtou8(buf, 16, &new_reg_val); + if (err) + return err; + + //read reg value + current_reg_val = i2c_smbus_read_byte_data(pdata[cpld_dev_num].client, reg_offset); + if (current_reg_val < 0) { + return current_reg_val; + } + + //write reg value if changed + if (current_reg_val != new_reg_val) { + ret = i2c_smbus_write_byte_data(pdata[cpld_dev_num].client, reg_offset, + (u8)(new_reg_val)); + if (ret < 0){ + return ret; + } + } + + return count; +} + +static ssize_t get_10g_mux(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int cpld_dev_num=cpld_1; + int reg_offset=CPLD_REG_10G_MUX; + u8 reg_val=0; + struct cpld_platform_data *pdata = dev->platform_data; + + //read 10G mux register + reg_val = i2c_smbus_read_byte_data(pdata[cpld_dev_num].client, reg_offset); + if (reg_val < 0) { + return sprintf(buf, "na"); + } + + return sprintf(buf, "0x%x\n", reg_val); +} + +static DEVICE_ATTR(qsfp_int, S_IRUGO, get_int, NULL); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset); +static DEVICE_ATTR(cpld_version, S_IRUGO, get_cpld_version, NULL); +static DEVICE_ATTR(cpld_10g_mux, S_IRUGO | S_IWUSR, get_10g_mux, set_10g_mux); + +static struct attribute *s9200_cpld_attrs[] = { + &dev_attr_qsfp_int.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_cpld_version.attr, + &dev_attr_cpld_10g_mux.attr, + NULL, +}; + +static struct attribute_group s9200_cpld_attr_grp = { + .attrs = s9200_cpld_attrs, +}; + +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent[CPLD_DEVICE_NUM]; + int i; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + parent[i] = i2c_get_adapter(S9200_MUX_BASE_NR + i + 1); + if (!parent[i]) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", + S9200_MUX_BASE_NR + i + 1); + return -ENODEV; + } + pdata[i].client = i2c_new_dummy(parent[i], pdata[i].reg_addr); + if (!pdata[i].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[i].reg_addr); + goto error; + } + } + + ret = sysfs_create_group(&pdev->dev.kobj, &s9200_cpld_attr_grp); + if (ret) + goto error; + + return 0; + +error: + i2c_put_adapter(parent[i]); + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent[i]); + } + } + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + int i; + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + + sysfs_remove_group(&pdev->dev.kobj, &s9200_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } else { + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + if (pdata[i].client) { + parent = (pdata[i].client)->adapter; + i2c_unregister_device(pdata[i].client); + i2c_put_adapter(parent); + } + } + } + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "ingrasys-s9200-cpld", + }, +}; + +static int __init ingrasys_s9200_platform_init(void) +{ + int ret = 0; + + printk("ingrasysl_s9200_platform module initialization\n"); + + mdelay(10000); + + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + ret = platform_device_register(&s9200_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_cpld; + } + + return 0; + +error_cpld: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit ingrasys_s9200_platform_exit(void) +{ + platform_device_unregister(&s9200_cpld); + platform_driver_unregister(&cpld_driver); +} + +module_init(ingrasys_s9200_platform_init); +module_exit(ingrasys_s9200_platform_exit); + +MODULE_DESCRIPTION("Ingrasys S9200 Platform Support"); +MODULE_AUTHOR("Jason Tsai "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/eeprom_mb.c b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/eeprom_mb.c new file mode 100755 index 000000000000..1cdb26658f5a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/eeprom_mb.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +/* enable dev_dbg print out */ +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { /*0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57,*/ I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 512 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, (u8)((addr >> 8) & 0xFF), (u8)(addr & 0xFF)); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static ssize_t mb_eeprom_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + int ret; + int i; + u8 cmd; + u16 value16; + + dev_dbg(&client->dev, "mb_eeprom_write off=%d, count=%d\n", (int)off, (int)count); + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + mutex_lock(&data->update_lock); + + for(i=0; i < count; i++) { + /* write command */ + cmd = (off >> 8) & 0xff; + value16 = off & 0xff; + value16 |= buf[i] << 8; + ret = i2c_smbus_write_word_data(client, cmd, value16); + + if (ret < 0) { + dev_err(&client->dev, "write address failed at %d \n", (int)off); + goto exit; + } + + off++; + + /* need to wait for write complete */ + udelay(10000); + } +exit: + mutex_unlock(&data->update_lock); + /* force to update client when reading */ + for(i=0; i < SLICE_NUM; i++) { + data->last_updated[i] = 0; + } + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUSR, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, + .write = mb_eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x51 and 0x55. So decline + attaching to addresses >= 0x56 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_platform.h b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_platform.h new file mode 100644 index 000000000000..8a38965e7932 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_platform.h @@ -0,0 +1,148 @@ +#ifndef _S9200_64X_PLATFORM_H +#define _S9200_64X_PLATFORM_H + +#include + +// remove debug before release +#define DEBUG + +enum bus_order { + I2C_BUS_MAIN, + MUX_9548_0_CH0, + MUX_9548_0_CH1, + MUX_9548_0_CH2, + MUX_9548_0_CH3, + MUX_9548_0_CH4, + MUX_9548_0_CH5, + MUX_9548_0_CH6, + MUX_9548_0_CH7, + MUX_9548_1_CH0, + MUX_9548_1_CH1, + MUX_9548_1_CH2, + MUX_9548_1_CH3, + MUX_9548_1_CH4, + MUX_9548_1_CH5, + MUX_9548_1_CH6, + MUX_9548_1_CH7, + MUX_9546_0_CH0, + MUX_9546_0_CH1, + MUX_9546_0_CH2, + MUX_9546_0_CH3, + MUX_9546_1_CH0, + MUX_9546_1_CH1, + MUX_9546_1_CH2, + MUX_9546_1_CH3, + MUX_9548_2_CH0, + MUX_9548_2_CH1, + MUX_9548_2_CH2, + MUX_9548_2_CH3, + MUX_9548_2_CH4, + MUX_9548_2_CH5, + MUX_9548_2_CH6, + MUX_9548_2_CH7, + MUX_9548_3_CH0, + MUX_9548_3_CH1, + MUX_9548_3_CH2, + MUX_9548_3_CH3, + MUX_9548_3_CH4, + MUX_9548_3_CH5, + MUX_9548_3_CH6, + MUX_9548_3_CH7, + MUX_9548_4_CH0, + MUX_9548_4_CH1, + MUX_9548_4_CH2, + MUX_9548_4_CH3, + MUX_9548_4_CH4, + MUX_9548_4_CH5, + MUX_9548_4_CH6, + MUX_9548_4_CH7, + MUX_9548_5_CH0, + MUX_9548_5_CH1, + MUX_9548_5_CH2, + MUX_9548_5_CH3, + MUX_9548_5_CH4, + MUX_9548_5_CH5, + MUX_9548_5_CH6, + MUX_9548_5_CH7, + MUX_9548_6_CH0, + MUX_9548_6_CH1, + MUX_9548_6_CH2, + MUX_9548_6_CH3, + MUX_9548_6_CH4, + MUX_9548_6_CH5, + MUX_9548_6_CH6, + MUX_9548_6_CH7, + MUX_9548_7_CH0, + MUX_9548_7_CH1, + MUX_9548_7_CH2, + MUX_9548_7_CH3, + MUX_9548_7_CH4, + MUX_9548_7_CH5, + MUX_9548_7_CH6, + MUX_9548_7_CH7, + MUX_9548_8_CH0, + MUX_9548_8_CH1, + MUX_9548_8_CH2, + MUX_9548_8_CH3, + MUX_9548_8_CH4, + MUX_9548_8_CH5, + MUX_9548_8_CH6, + MUX_9548_8_CH7, + MUX_9548_9_CH0, + MUX_9548_9_CH1, + MUX_9548_9_CH2, + MUX_9548_9_CH3, + MUX_9548_9_CH4, + MUX_9548_9_CH5, + MUX_9548_9_CH6, + MUX_9548_9_CH7, + MUX_9548_10_CH0, + MUX_9548_10_CH1, + MUX_9548_10_CH2, + MUX_9548_10_CH3, + MUX_9548_10_CH4, + MUX_9548_10_CH5, + MUX_9548_10_CH6, + MUX_9548_10_CH7, +}; + +#define I2C_ADDR_MUX_9555_0 (0x20) +#define I2C_ADDR_MUX_9555_1 (0x24) +#define I2C_ADDR_MUX_9555_2 (0x25) +#define I2C_ADDR_MUX_9555_3 (0x26) +#define I2C_ADDR_MUX_9539_0 (0x76) +#define I2C_ADDR_MUX_9539_1 (0x76) +#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN) +#define I2C_BUS_SYS_LED (MUX_9548_1_CH1) + +#define NUM_OF_I2C_MUX (11) +#define NUM_OF_CPLD (5) +#define NUM_OF_QSFP_PORT (64) +#define NUM_OF_SFP_PORT (2) +#define QSFP_EEPROM_I2C_ADDR (0x50) + +enum gpio_reg { + REG_PORT0_IN, + REG_PORT1_IN, + REG_PORT0_OUT, + REG_PORT1_OUT, + REG_PORT0_POL, + REG_PORT1_POL, + REG_PORT0_DIR, + REG_PORT1_DIR, +}; + +struct ing_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +struct i2c_init_data { + __u16 ch; + __u16 addr; + __u8 reg; + __u8 value; +}; + +#endif diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_psu.c b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_psu.c new file mode 100644 index 000000000000..46642f1271ca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/modules/ingrasys_s9200_64x_psu.c @@ -0,0 +1,389 @@ +/* + * S9200-64X PSU driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9200_64x_platform.h" + +static ssize_t show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf); +static struct s9200_psu_data *s9200_psu_update_status(struct device *dev); +static struct s9200_psu_data *s9200_psu_update_eeprom(struct device *dev); +static int s9200_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len); + + +#define DRIVER_NAME "psu" + +// Addresses scanned +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* PSU EEPROM SIZE */ +#define EEPROM_SZ 256 +#define READ_EEPROM 1 +#define NREAD_EEPROM 0 + +static struct i2c_client pca9555_client; + +/* pca9555 gpio pin mapping */ +#define PSU2_PWROK 0 +#define PSU2_PRSNT_L 1 +#define PSU2_PWRON_L 2 +#define PSU1_PWROK 3 +#define PSU1_PRSNT_L 4 +#define PSU1_PWRON_L 5 +#define TMP_75_INT_L 6 + +/* Driver Private Data */ +struct s9200_psu_data { + struct mutex lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + s32 status; /* IO expander value */ + char eeprom[EEPROM_SZ]; /* psu eeprom data */ + char psuABS; /* PSU absent */ + char psuPG; /* PSU power good */ +}; + +enum psu_index +{ + s9200_psu1, + s9200_psu2 +}; + +/* + * display power good attribute + */ +static ssize_t +show_psu_pg(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9200_psu_data *data = s9200_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuPG; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + +/* + * display power absent attribute + */ +static ssize_t +show_psu_abs(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9200_psu_data *data = s9200_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuABS; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + + +/* + * sysfs attributes for psu + */ +static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL); +static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL); +static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL); + +static struct attribute *s9200_psu_attributes[] = { + &dev_attr_psu_pg.attr, + &dev_attr_psu_abs.attr, + &dev_attr_psu_eeprom.attr, + NULL +}; + +/* + * display psu eeprom content + */ +static ssize_t +show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct s9200_psu_data *data = s9200_psu_update_eeprom(dev); + + memcpy(buf, (char *)data->eeprom, EEPROM_SZ); + return EEPROM_SZ; +} + +static const struct attribute_group s9200_psu_group = { + .attrs = s9200_psu_attributes, +}; + +/* + * check gpio expander is accessible + */ +static int +pca9555_detect(struct i2c_client *client) +{ + if (i2c_smbus_read_byte_data(client, REG_PORT0_DIR) < 0) { + return -ENODEV; + } + + return 0; +} + +/* + * client address init + */ +static void +i2c_devices_client_address_init(struct i2c_client *client) +{ + pca9555_client = *client; + pca9555_client.addr = 0x25; +} + +static int +s9200_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct s9200_psu_data *data; + int status, err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct s9200_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct s9200_psu_data)); + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + i2c_devices_client_address_init(client); + + err = pca9555_detect(&pca9555_client); + if (err) { + dev_info(&client->dev, "pca9555_detect failed\n"); + return err; + } + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &s9200_psu_group); + if (status) { + goto exit_free; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &s9200_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int +s9200_psu_remove(struct i2c_client *client) +{ + struct s9200_psu_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &s9200_psu_group); + kfree(data); + + return 0; +} + + +/* + * psu eeprom read utility + */ +static int +s9200_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len) +{ + int i=0, ret=0; + int blk_max = 32; //max block read size + + /* read eeprom, 32 * 8 = 256 bytes */ + for (i=0; i < EEPROM_SZ/blk_max; i++) { + ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max, + data + (i*blk_max)); + if (ret < 0) { + return ret; + } + } + return ret; +} + +/* + * update eeprom content + */ +static struct s9200_psu_data +*s9200_psu_update_eeprom(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9200_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->last_updated + 300 * HZ) + || !data->valid) { + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9200_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + /* Read eeprom */ + if (!data->psuABS) { + //clear local eeprom data + memset(data->eeprom, 0, EEPROM_SZ); + + //read eeprom + status = s9200_psu_read_block(client, 0, data->eeprom, + ARRAY_SIZE(data->eeprom)); + + if (status < 0) { + memset(data->eeprom, 0, EEPROM_SZ); + dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status); + } else { + data->valid = 1; + } + } else { + memset(data->eeprom, 0, EEPROM_SZ); + } + data->last_updated = jiffies; + } + + mutex_unlock(&data->lock); + + return data; +} + +/* + * update psu status + */ +static struct s9200_psu_data +*s9200_psu_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9200_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9200_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + mutex_unlock(&data->lock); + + return data; +} + +static const struct i2c_device_id s9200_psu_id[] = { + { "psu1", s9200_psu1 }, + { "psu2", s9200_psu2 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, s9200_psu_id); + +static struct i2c_driver s9200_psu_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = s9200_psu_probe, + .remove = s9200_psu_remove, + .id_table = s9200_psu_id, + .address_list = normal_i2c, +}; + +static int __init s9200_psu_init(void) +{ + return i2c_add_driver(&s9200_psu_driver); +} + +static void __exit s9200_psu_exit(void) +{ + i2c_del_driver(&s9200_psu_driver); +} + +module_init(s9200_psu_init); +module_exit(s9200_psu_exit); + +MODULE_AUTHOR("Jason Tsai "); +MODULE_DESCRIPTION("S9200-64X psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/qsfp-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/qsfp-monitor.service new file mode 100644 index 000000000000..bcb9beb6a999 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9200-64x-monitor.service +After=s9200-64x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/s9200-64x-monitor.service b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/s9200-64x-monitor.service new file mode 100644 index 000000000000..bd92628a6c3f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/service/s9200-64x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9200_64x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/i2c_utils.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/i2c_utils.sh new file mode 100644 index 000000000000..dcb6b9167982 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/i2c_utils.sh @@ -0,0 +1,1951 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +QSFP_INIT_ACTION=${2} +MB_EEPROM_ACTION=${2} +TARGET_10G_MUX=${2} +QSFP_ACTION=${3} +QSFP_VALUE=${4} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +I2C_NUM=0 +NUM_I801_DEVICE=$((I2C_NUM++)) #0 + +#MUX PCA9548#0 CPLD (I2C_NUM 1~8) +NUM_MUX_9548_CPLD_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_CPLD_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548#1 UCD (I2C_NUM 9~16) +NUM_MUX_9548_UCD_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_UCD_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9545 PSU (I2C_NUM 17~20) +NUM_MUX_9545_PSU_CHAN=() +for (( i=0; i<4; ++i )) +do + NUM_MUX_9545_PSU_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP ROOT (I2C_NUM 21~28) +NUM_MUX_9548_QSFP_ROOT_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_ROOT_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 0~7 (I2C_NUM 29~36) +NUM_MUX_9548_QSFP_0_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_0_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 8~15 (I2C_NUM 37~44) +NUM_MUX_9548_QSFP_1_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_1_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 16~23 (I2C_NUM 45~52) +NUM_MUX_9548_QSFP_2_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_2_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 24~31 (I2C_NUM 53~60) +NUM_MUX_9548_QSFP_3_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_3_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 32~39 (I2C_NUM 61~68) +NUM_MUX_9548_QSFP_4_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_4_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 40~47 (I2C_NUM 69~76) +NUM_MUX_9548_QSFP_5_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_5_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 48~55 (I2C_NUM 77~84) +NUM_MUX_9548_QSFP_6_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_6_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 QSFP Port 56~63 (I2C_NUM 85~92) +NUM_MUX_9548_QSFP_7_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_QSFP_7_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9545 SFP (I2C_NUM 93~96) +NUM_MUX_9545_SFP_CHAN=() +for (( i=0; i<4; ++i )) +do + NUM_MUX_9545_SFP_CHAN[i]=$((I2C_NUM++)) +done + +#MUX PCA9548 CPLD SW Upgrade (I2C_NUM 97~104) +NUM_MUX_9548_CPLD_SW_CHAN=() +for (( i=0; i<8; ++i )) +do + NUM_MUX_9548_CPLD_SW_CHAN[i]=$((I2C_NUM++)) +done + +#MUX Alias +I2C_BUS_PSU1_EEPROM=${NUM_MUX_9545_PSU_CHAN[1]} +I2C_BUS_PSU2_EEPROM=${NUM_MUX_9545_PSU_CHAN[0]} +I2C_BUS_LED_BOARD=${NUM_MUX_9548_UCD_CHAN[1]} +I2C_BUS_ID_GPIO=${NUM_MUX_9548_UCD_CHAN[2]} +I2C_BUS_10GMUX=${NUM_MUX_9548_UCD_CHAN[4]} +I2C_BUS_HWM=${NUM_MUX_9548_UCD_CHAN[7]} +I2C_BUS_FAN_BOARD=${NUM_I801_DEVICE} +I2C_BUS_MB_EEPROM=${NUM_I801_DEVICE} +I2C_BUS_TH_RESET=${NUM_I801_DEVICE} +I2C_BUS_BOARD_TYPE=${NUM_I801_DEVICE} +I2C_BUS_BMC_BOARD_TYPE=${NUM_I801_DEVICE} +I2C_BUS_LM75_MAC=${NUM_MUX_9548_CPLD_CHAN[5]} +I2C_BUS_LM75_FRONT=${NUM_MUX_9548_CPLD_CHAN[6]} +I2C_BUS_LM75_REAR=${NUM_MUX_9548_CPLD_CHAN[5]} +I2C_BUS_PSU_INT=${NUM_I801_DEVICE} +I2C_BUS_PSU_STATUS=${NUM_I801_DEVICE} +I2C_BUS_MUX_RST=${NUM_I801_DEVICE} +#CPU Board +I2C_BUS_CPU_EEPROM=${NUM_I801_DEVICE} +I2C_BUS_CPU_TMP75=${NUM_I801_DEVICE} +I2C_BUS_MUX_CPU_CPLD=${NUM_I801_DEVICE} + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_SYS_CPLD="/sys/devices/platform/ingrasys-s9200-cpld.0" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon5" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_LM75_MAC="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_LM75_MAC}" +PATH_LM75_FRONT="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_LM75_FRONT}" +PATH_LM75_REAR="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_LM75_REAR}" +PATH_CPU_TMP75="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_BMC_TMP75="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_HWM}" +PATH_PSU1_EERPOM=${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM} +PATH_PSU2_EEPROM=${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM} +PATH_10GMUX=${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_10GMUX} +#PATH for MUX PCA9548_QSFP_ROOT +PATH_MUX_9548_QSFP_ROOT="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_PSU_CHAN[2]}" +PATH_MUX_9548_QSFP_ROOT_CHAN=() +for (( i=0; i<8; ++i )) +do + PATH_MUX_9548_QSFP_ROOT_CHAN[i]="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_QSFP_ROOT_CHAN[i]}" +done +PATH_MUX_9545_SFP="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_PSU_CHAN[3]}" +PATH_MUX_9545_SFP_CHAN=() +for (( i=0; i<4; ++i )) +do + PATH_MUX_9545_SFP_CHAN[i]="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_SFP_CHAN[i]}" +done + +#i2cmap and gpiomap path +PATH_I2CMAP=/tmp/i2cmap + +#Mother Board +I2C_ADDR_MUX_9539_TH_RST=0x74 +I2C_ADDR_LED_BOARD=0x75 +I2C_ADDR_FAN_BOARD=0x20 +I2C_ADDR_ID_GPIO=0x27 +I2C_ADDR_MUX_9548_CPLD=0x70 +I2C_ADDR_MUX_9548_UCD=0x76 +I2C_ADDR_MUX_9545_PSU=0x72 +I2C_ADDR_MUX_9548_QSFP_ROOT=0x71 +I2C_ADDR_MUX_9548_QSFP=0x73 +I2C_ADDR_MUX_9545_SFP=0x73 +I2C_ADDR_CPLD=0x33 +I2C_ADDR_MB_EEPROM=0x55 +I2C_ADDR_QSFP_EEPROM=0x50 +I2C_ADDR_PSU_EEPROM=0x50 +I2C_ADDR_LM75_MAC=0x4E +I2C_ADDR_LM75_FRONT=0x4D +I2C_ADDR_LM75_REAR=0x4D +I2C_ADDR_10GMUX=0x67 +#Dummy BMC Board +I2C_ADDR_HWM=0x2F +I2C_ADDR_PSU_INT=0x24 #PSU Interrup on Dummy BMC Board +I2C_ADDR_BMC_BOARD_TYPE=0x24 #PSU Status on Dummy BMC Board +I2C_ADDR_PSU_STATUS=0x25 #PSU Status on Dummy BMC Board +I2C_ADDR_MUX_RST=0x26 #MUX RST on Dummy BMC Board +I2C_ADDR_TMP75_BB=0x4A +#CPU Board +I2C_ADDR_CPU_EEPROM=0x51 +I2C_ADDR_CPU_TMP75=0x4F +I2C_ADDR_MUX_CPU_CPLD=0x77 + +#sysfs +PATH_SYSFS_PSU1="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU1_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU_EEPROM)" +PATH_SYSFS_PSU2="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU2_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU_EEPROM)" + +#Active High/Low +ACTIVE_LOW=1 +ACTIVE_HIGH=0 +#GPIO Direction In/Out +DIR_IN=in +DIR_OUT=out + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +#W83795 Registers +REG_BANK_SEL=0x00 +REG_VOLT_CTRL1=0x02 +REG_VOLT_CTRL2=0x03 +REG_TEMP_CTRL1=0x04 +REG_TEMP_CTRL2=0x05 + +#PCA9535 Registers +REG_IN_0=0 +REG_IN_1=1 +REG_OUT_0=2 +REG_OUT_1=3 +REG_POLARITY_0=4 +REG_POLARITY_1=5 +REG_CFG_0=6 +REG_CFG_1=7 + +#LM75 Registers +LM75_REG_TEMP=0x00 +LM75_REG_CONF=0x01 +LM75_REG_HYST=0x02 +LM75_REG_TOS=0x03 + +#Bit Mask +BIT_MASK=(1 2 4 8 16 32 64 128) + +#MUX Type +PCA9545="pca9545" +PCA9548="pca9548" + +#PLATFORM Variables +PORT_NUM=64 + +#CPLD Variables +CPLD_QSFP_GROUP=(12 25 38 51 64) +CPLD_QSFP_STATUS_REG_BASE=0x20 +CPLD_QSFP_MODE_SELECT_REG_BASE=0x30 +CPLD_QSFP_ABS="abs" +CPLD_QSFP_INT="int" +CPLD_QSFP_RST="rst" +CPLD_QSFP_LP="lp" + + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cpu_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-${PORT_NUM}]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_cpu_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-${PORT_NUM}]" + echo " : ${0} i2c_qsfp_type_get [1-${PORT_NUM}]" + echo " : ${0} i2c_qsfp_signal_get [1-${PORT_NUM}] [abs|int|rst|lp]" + echo " : ${0} i2c_qsfp_signal_set [1-${PORT_NUM}] [rst|lp] [0|1] (low_active)" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_bmc_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_led_fan_tray_test" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber" + echo " : ${0} i2c_psu1_led green|amber" + echo " : ${0} i2c_psu2_led green|amber" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo " : ${0} i2c_10g_mux cpu|fp" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#logical(front panel) to physical (falcon core) port mapping +function _port_logic2phy { + + local logic_port=$1 + local phy_port=0 + + if (( $logic_port >=1 && $logic_port <= 32 )) ; then + phy_port=$(( (logic_port-1)/2*4 + (logic_port-1)%2 + 1)) + elif (( $logic_port >=33 && $logic_port <= 64 )) ; then + phy_port=$(( (((logic_port-1)%32))/2*4 + (logic_port-1)%2 + 3)) + fi + + echo $phy_port +} + +#set i2cmap +function _set_i2cmap { + local i2c_n=$1 + local alias=$2 + + #create i2cmap dir if not exist + mkdir -p $PATH_I2CMAP + + #check i2c_n exists in sysfs + if [ ! -L ${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} ]; then + echo "${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} does not exist." + return + fi + + #create or update link + ln -sf ${PATH_SYS_I2C_DEVICES}/i2c-${i2c_n} ${PATH_I2CMAP}/${alias} +} + +#clear i2cmap +function _clear_i2cmap { + #delete i2cmap dir + rm -rf ${PATH_I2CMAP}/ +} + +#remove kernel module if exists +function _util_rmmod { + local mod=$1 + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod +} + +function _create_i2c_mux_device { + local mux_type=$1 + local mux_addr=$2 + local mux_parent_chan=$3 + local mux_chan0=$4 + local mux_desc=$5 + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${mux_chan0}" ]; then + _retry "echo '$mux_type ${mux_addr}' > ${mux_parent_chan}/new_device" + _set_i2cmap ${mux_chan0} "${mux_desc}" + else + echo "${mux_desc} ${mux_addr} already init." + fi +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + _util_rmmod i2c_i801 + modprobe i2c_i801 #disable_features=0x10 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + #add MUX_9548_CPLD on I801 + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_CPLD ${PATH_I801_DEVICE} ${NUM_MUX_9548_CPLD_CHAN[0]} "PCA9548_CPLD" + + #add MUX_9548_UCD on I801 + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_UCD ${PATH_I801_DEVICE} ${NUM_MUX_9548_UCD_CHAN[0]} "PCA9548_UCD" + + #add MUX_9545_PSU on I801 + _create_i2c_mux_device $PCA9545 $I2C_ADDR_MUX_9545_PSU ${PATH_I801_DEVICE} ${NUM_MUX_9545_PSU_CHAN[0]} "PCA9545_PSU" + + #add MUX_9548_QSFP_ROOT on MUX_9545_PSU_CHAN[2] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP_ROOT ${PATH_MUX_9548_QSFP_ROOT} ${NUM_MUX_9548_QSFP_ROOT_CHAN[0]} "PCA9548_QSPF_ROOT" + + #add MUX_9548_QSFP_0 on MUX_9548_QSFP_ROOT_CHAN[0] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[0]} ${NUM_MUX_9548_QSFP_0_CHAN[0]} "PCA9548_QSPF_0" + + #add MUX_9548_QSFP_1 on MUX_9548_QSFP_ROOT_CHAN[1] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[1]} ${NUM_MUX_9548_QSFP_1_CHAN[0]} "PCA9548_QSPF_1" + + #add MUX_9548_QSFP_2 on MUX_9548_QSFP_ROOT_CHAN[2] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[2]} ${NUM_MUX_9548_QSFP_2_CHAN[0]} "PCA9548_QSPF_2" + + #add MUX_9548_QSFP_3 on MUX_9548_QSFP_ROOT_CHAN[3] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[3]} ${NUM_MUX_9548_QSFP_3_CHAN[0]} "PCA9548_QSPF_3" + + #add MUX_9548_QSFP_4 on MUX_9548_QSFP_ROOT_CHAN[4] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[4]} ${NUM_MUX_9548_QSFP_4_CHAN[0]} "PCA9548_QSPF_4" + + #add MUX_9548_QSFP_5 on MUX_9548_QSFP_ROOT_CHAN[5] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[5]} ${NUM_MUX_9548_QSFP_5_CHAN[0]} "PCA9548_QSPF_5" + + #add MUX_9548_QSFP_6 on MUX_9548_QSFP_ROOT_CHAN[6] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[6]} ${NUM_MUX_9548_QSFP_6_CHAN[0]} "PCA9548_QSPF_6" + + #add MUX_9548_QSFP_7 on MUX_9548_QSFP_ROOT_CHAN[7] + _create_i2c_mux_device $PCA9548 $I2C_ADDR_MUX_9548_QSFP ${PATH_MUX_9548_QSFP_ROOT_CHAN[7]} ${NUM_MUX_9548_QSFP_7_CHAN[0]} "PCA9548_QSPF_7" + + #add MUX_9545_SFP on QSFP_ROOT + _create_i2c_mux_device $PCA9545 $I2C_ADDR_MUX_9545_SFP ${PATH_MUX_9545_SFP} ${NUM_MUX_9545_SFP_CHAN[0]} "PCA9545_SPF" + + #Init CPLD LED_CLR Register (QSFP LED) + i2cset -y -m ${BIT_MASK[2]} ${NUM_I801_DEVICE} ${I2C_ADDR_MUX_9539_TH_RST} ${REG_OUT_0} 0xFF + + _util_rmmod coretemp + _util_rmmod jc42 + _util_rmmod w83795 + _util_rmmod lm75 + + _i2c_temp_init + _i2c_volmon_init + modprobe coretemp + modprobe lm75 + modprobe jc42 + modprobe eeprom_mb + _i2c_mb_eeprom_init "new" + _i2c_cpu_eeprom_init "new" + modprobe eeprom + modprobe gpio-pca953x + _i2c_sensors_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_psu_init + _i2c_qsfp_eeprom_init "new" + _i2c_led_psu_status_set + _i2c_led_fan_status_set + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_sys_led + modprobe cpld + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + for mod in cpld coretemp jc42 w83795 lm75 eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_i801 ingrasys_s9200_64x_psu; + do + _util_rmmod $mod + done + _clear_i2cmap +} + +#Temperature sensor Init +function _i2c_temp_init { + local lm="lm75" + local tmp="tmp75" + local i2c_bus=${I2C_BUS_HWM} + local i2c_addr=${I2C_ADDR_HWM} + + echo "=========================================================" + echo "# Description: TEMP INIT" + echo "=========================================================" + + # select bank0 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_BANK_SEL} 0x80 + echo "enable VDSEN14, VDSEN15, VDSEN16, and TR4 temperature monitoring" + i2cset -y -r ${i2c_bus=} ${i2c_addr} ${REG_TEMP_CTRL2} 0x6A + + echo "export CPU sensor TMP75 to sysfs" + echo "${tmp} ${I2C_ADDR_CPU_TMP75}" > ${PATH_CPU_TMP75}/new_device + + echo "Add Dummy Board LM75 to sysfs" + echo "${lm} ${I2C_ADDR_LM75_MAC}" > ${PATH_LM75_MAC}/new_device + echo "${lm} ${I2C_ADDR_LM75_FRONT}" > ${PATH_LM75_FRONT}/new_device + echo "${lm} ${I2C_ADDR_LM75_REAR}" > ${PATH_LM75_REAR}/new_device + + echo "CLKIN clock frequency set as 48Mhz" + i2cset -y -r ${i2c_bus} ${i2c_addr} 0x01 0x1C + + # select bank 2 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_BANK_SEL} 0x82 + echo "set PWM mode in FOMC" + i2cset -y -r ${i2c_bus} ${i2c_addr} 0x0F 0x00 +} + +#FAN Init +function _i2c_fan_init { + local init_fan_speed=120 + + echo "=========================================================" + echo "# Description: FAN INIT" + echo "=========================================================" + + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo "Init Fan Speed to ${init_fan_speed} (MAX is 255)" + echo $init_fan_speed > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo $init_fan_speed > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + else + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + fi +} + +#VOLMON Init +function _i2c_volmon_init { + echo -n "VOLMON INIT" + local i2c_bus=${I2C_BUS_HWM} + local i2c_addr=${I2C_ADDR_HWM} + + #select bank0 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_BANK_SEL} 0x80 + #enable voltage monitoring VSEN 1~8 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_VOLT_CTRL1} 0xFF + #enable voltage monitoring 3VDD and 3VBAT + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_VOLT_CTRL2} 0x50 + #eable voltage monitoring VSEN12 and VSEN13 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_TEMP_CTRL1} 0x0A + + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + local i2c_bus=0 + local i2c_addr=0 + + echo "=========================================================" + echo "# Description: I2C IO Expander Init" + echo "=========================================================" + + echo "Init PCA9539 TH RESET IO Expander" + #PCA9539 TH RESET + #0.0 TH_RST_L OUT 1 + #0.1 TH_PCIE_RST_L OUT 1 + #0.2 LED_CLR OUT 1 + #0.3 HOST_TO_BMC_I2C_GPIO OUT 0 + #0.4 USB_MUX_SEL OUT 0 + #0.5 UART_MUX_SEL OUT 0 + #0.6 FIN0 OUT 0 + #0.7 FIN7 OUT 0 + #1.0 TH_INT_L IN + #1.1 CPLD4_TO_CPU_INT_L IN + #1.2 CPLD3_TO_CPU_INT_L IN + #1.3 CPLD2_TO_CPU_INT_L IN + #1.4 CPLD1_TO_CPU_INT_L IN + #1.5 REF_SEL OUT 0 + #1.6 I210_PE_RST_L OUT 1 + #1.7 I210_RST_L OUT 1 + i2c_bus=${I2C_BUS_TH_RESET} + i2c_addr=${I2C_ADDR_MUX_9539_TH_RST} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_0} $((2#00000111)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_1} $((2#11000000)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} $((2#00011111)) + + #PCA9555 on BMC Dummy Board + #set SYSTEM_LED_RST_L before init PCA9539 LED BOARD IO Expander + echo "Init PCA9555 MUX RST IO Expander" + #PCA9555 MUX RST Expander + #0.0 FRU_I2C_MUX_RST_L OUT 1 + #0.1 MAIN_I2C_MUX_RST_L OUT 1 + #0.2 SYSTEM_LED_RST_L OUT 1 + #0.3 BMC_TO_UCD_RST_L OUT 1 + #0.4 BMC_TO_HOST_RST_L OUT 1 + #0.5 ETHX_RST_L OUT 1 + #0.6 GPIOF4 IN + #0.7 N/A + #1.0 CPU_to_FRU_I2C_EN OUT 1 + #1.1 CPU_to_MAIN_I2C_EN OUT 1 + #1.2 P3V3_FAN_EN OUT 1 + #1.3 P3V3_I2C_EN OUT 1 + #1.4 UCD9090_CNTRL OUT 1 + #1.5 UART_MUX_SEL OUT 0 + #1.6 USB_MUX_SEL OUT 0 + #1.7 ETHX_CPU_EEPROM_SEL OUT 0 + i2c_bus=${I2C_BUS_MUX_RST} + i2c_addr=${I2C_ADDR_MUX_RST} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_0} $((2#00111111)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_1} $((2#00011111)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} $((2#01000000)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} 0x00 + + echo "Init PCA9539 LED BOARD IO Expander" + #PCA9539 LED BOARD + #0.0 SYS_LED_G OUT 1 + #0.1 FAN_LED_EN OUT 1 + #0.2 FAN_LED_Y OUT 0 + #0.3 PSU1_LED_Y OUT 0 + #0.4 PSU0_LED_Y OUT 0 + #0.5~0.7 X + #1.0 PSU1_PWROK OUT 1 + #1.1 PSU0_PWROK OUT 1 + i2c_bus=${I2C_BUS_LED_BOARD} + i2c_addr=${I2C_ADDR_LED_BOARD} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_0} $((2#00000011)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_1} $((2#00000011)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} 0x00 + + echo "Init PCA9535 ID_GPIO IO Expander" + #PCA9535 ID_GPIO + #0.0 ~ 0.7 X + #1.0 Build_REV_0 IN + #1.1 Build_REV_1 IN + #1.2 HW_REV_0 IN + #1.3 HW_REV_1 IN + #1.4 Board_ID_0 IN + #1.5 Board_ID_1 IN + #1.6 Board_ID_2 IN + #1.7 Board_ID_3 IN + i2c_bus=${I2C_BUS_ID_GPIO} + i2c_addr=${I2C_ADDR_ID_GPIO} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} 0xFF + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} 0xFF + + #I2C_ADDR_FAN_BOARD + echo "Init PCA9535 FAN_BOARD IO Expander" + #PCA9535 FAN_BOARD + #0.0 EN_FAN1_LED_G_H OUT 1 + #0.1 EN_FAN1_LED_Y_H OUT 0 + #0.2 FAN1_ABS# IN 0 + #0.3 FAN1_DIR# IN 0 + #0.4 EN_FAN2_LED_G_H OUT 1 + #0.5 EN_FAN2_LED_Y_H OUT 0 + #0.6 FAN2_ABS# IN 0 + #0.7 FAN2_DIR# IN 0 + #1.0 EN_FAN3_LED_G_H OUT 1 + #1.1 EN_FAN3_LED_Y_H OUT 0 + #1.2 FAN3_ABS# IN 0 + #1.3 FAN3_DIR# IN 0 + #1.4 EN_FAN4_LED_G_H OUT 1 + #1.5 EN_FAN4_LED_Y_H OUT 0 + #1.6 FAN4_ABS# IN 0 + #1.7 FAN4_DIR# IN 0 + i2c_bus=${I2C_BUS_FAN_BOARD} + i2c_addr=${I2C_ADDR_FAN_BOARD} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_0} $((2#00010001)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_1} $((2#00010001)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} $((2#11001100)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} $((2#11001100)) + + #PCA9555 on BMC Dummy Board + echo "Init PCA9555 Interrupt IO Expander" + #PCA9555 Interrupt Expander + #0.0 HWM_INT_L IN + #0.1 UCD9090_INT_L IN + #0.2 ETHX_INT_L IN + #0.3 HOST_TO_BMC_INT_L IN + #0.4 THERMAL_ALT1# IN + #0.5 FAN_STATUS_INT_L IN + #0.6 PSU0_INT_L IN + #0.7 PSU1_INT_L IN + #1.0 Build_REV_0 IN + #1.1 Build_REV_1 IN + #1.2 HW_REV_0 IN + #1.3 HW_REV_1 IN + #1.4 Board_ID_0 IN + #1.5 Board_ID_1 IN + #1.6 Board_ID_2 IN + #1.7 Board_ID_3 IN + i2c_bus=${I2C_BUS_PSU_INT} + i2c_addr=${I2C_ADDR_PSU_INT} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} 0xFF + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} 0xFF + + #PCA9555 on BMC Dummy Board + echo "Init PCA9555 PSU0_PWROK IO Expander" + #PCA9555 PSU0_PWROK Expander + #0.0 PSU0_PWROK IN + #0.1 PSU0_PRSNT_L IN + #0.2 PSU0_PWRON_L OUT 0 + #0.3 PSU1_PWROK IN + #0.4 PSU1_PRSNT_L IN + #0.5 PSU1_PWRON_L OUT 0 + #0.6 TMP75_INT_L IN + #0.7 GPIOF7 IN + #1.0 ALL_PWR_GOOD IN + #1.1 CPU_PRSNT_L IN + #1.2 FP_BTN_UARTSEL_EN_L OUT 0 + #1.3 HOST_TO_BMC_I2C_GPIO OUT 0 + #1.4 HOST_CPU_PWRBTN_L OUT 1 + #1.5 N/A + #1.6 N/A + #1.7 N/A + i2c_bus=${I2C_BUS_PSU_STATUS} + i2c_addr=${I2C_ADDR_PSU_STATUS} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_OUT_1} $((2#00010000)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_0} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_POLARITY_1} 0x00 + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} $((2#11011011)) + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} $((2#11100011)) + + #PCA9539 on CPU Board + echo "Init PCA9539 CPLD IO Expander on CPU" + i2c_bus=${I2C_BUS_MUX_CPU_CPLD} + i2c_addr=${I2C_ADDR_MUX_CPU_CPLD} + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_0} 0xFF + i2cset -y -r ${i2c_bus} ${i2c_addr} ${REG_CFG_1} 0xFF +} + +function _i2c_sensors_init { + echo "SENSORS init" + local dev_path + + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_HWM}-$(printf "%04x" ${I2C_ADDR_HWM})" + if ! [ -L ${dev_path} ]; then + echo "w83795adg ${I2C_ADDR_HWM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_HWM}/new_device + while [ ! -e "${PATH_HWMON_W83795_DEVICE}" ]; do + sleep 1 + done + else + echo "${dev_path} already exist (w83795)" + fi + + # BMC board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-$(printf "%04x" ${I2C_ADDR_TMP75_BB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_BB}" > ${PATH_BMC_TMP75}/new_device + else + echo "${dev_path} already exist" + fi + + echo "Done" +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "=========================================================" + echo "# Description: FAN Tray Status Setup" + echo "=========================================================" + + #check W83795 exists + if [ ! -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + return + fi + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + FAN_TRAY=1 + if [ "${FAN1_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY 1] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY 1] [Green]=off [Amber]=on" + fi + + FAN_TRAY=2 + if [ "${FAN3_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY 2] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY 2] [Green]=off [Amber]=on" + fi + + FAN_TRAY=3 + if [ "${FAN5_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY 3] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY 3] [Green]=off [Amber]=on" + fi + + FAN_TRAY=4 + if [ "${FAN7_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY 4] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY 4] [Green]=off [Amber]=on" + fi +} + +#Test FAN Tray LED +function _i2c_led_fan_tray_test { + echo "=========================================================" + echo "# Description: FAN Tray LED Test" + echo "=========================================================" + + for i in {1..4} + do + FAN_TRAY=$i + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + _pause "Check [Fan Tray ${i} LED] = Green and Press [Enter] key to continue..." + + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + _pause "Check [Fan Tray ${i} LED] = Amber and Press [Enter] key to continue..." + done +} +#Set FAN LED +function _i2c_led_fan_status_set { + echo "=========================================================" + echo "# Description: FAN Status Setup" + echo "=========================================================" + + #check W83795 exists in hwmon2 + if [ ! -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo "FAIL, W83795 not found in path ${PATH_HWMON_W83795_DEVICE}" + return + fi + + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + if [ "${FAN1_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] ; then + COLOR_LED="green" + _i2c_fan_led + else + COLOR_LED="amber" + _i2c_fan_led + fi + echo "set [FAN LED] = ${COLOR_LED}" +} + +#Set PSU LED on LED Board +function _i2c_led_psu_status_set { + + echo "=========================================================" + echo "# Description: PSU LED Status Setup" + echo "=========================================================" + + #Get PSU Status + _i2c_psu_status + + #PSU1 Status + echo "------------------------------" + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + _i2c_psu1_led + else + COLOR_LED="amber" + _i2c_psu1_led + fi + else + COLOR_LED="amber" + _i2c_psu1_led + fi + echo "set [PSU1 LED] = ${COLOR_LED}" + + #PSU2 Status + echo "------------------------------" + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + _i2c_psu2_led + else + COLOR_LED="amber" + #ONOFF_LED="on" + _i2c_psu2_led + fi + else + COLOR_LED="amber" + _i2c_psu2_led + fi + echo "set [PSU2 LED] = ${COLOR_LED}" +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C LED TEST" + echo "=========================================================" + #sys led (green) + _i2c_reset_led + COLOR_LED="green" + _i2c_sys_led + _pause 'Check [SYS LED] = Green and Press [Enter] key to continue...' + #sys led (amber) + _i2c_reset_led + COLOR_LED="amber" + _i2c_sys_led + _pause 'Check [SYS LED] = Amber and Press [Enter] key to continue...' + + #FAN led (green) + _i2c_reset_led + COLOR_LED="green" + _i2c_fan_led + _pause 'Check [FAN LED] Green and Press [Enter] key to continue...' + #FAN led (amber) + _i2c_reset_led + COLOR_LED="amber" + _i2c_fan_led + _pause 'Check [FAN LED] = Amber and Press [Enter] key to continue...' + + #PSU1 led (green) + _i2c_reset_led + COLOR_LED="green" + _i2c_psu1_led + _pause 'Check [PSU1 LED] = Green and Press [Enter] key to continue...' + #PSU1 led (amber) + _i2c_reset_led + COLOR_LED="amber" + _i2c_psu1_led + _pause 'Check [PSU1 LED] = Amber and Press [Enter] key to continue...' + + #PSU2 led (green) + _i2c_reset_led + COLOR_LED="green" + _i2c_psu2_led + _pause 'Check [PSU2 LED] = Green and Press [Enter] key to continue...' + #PSU2 led (amber) + _i2c_reset_led + COLOR_LED="amber" + _i2c_psu2_led + _pause 'Check [PSU2 LED] = Amber and Press [Enter] key to continue...' + + #Turn OFF All LED + _i2c_reset_led + _pause 'Check turn off all LEDs and Press [Enter] key to continue...' +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + #global variables + cpld_group=0 + cpld_i2c_bus=0 + cpld_i2c_addr=$I2C_ADDR_CPLD + cpld_qsfp_status_reg_offset=0 + cpld_qsfp_mode_reg_offset=0 + + #local variables + local i=0 + local port=$1 + local port_group=$(( (port - 1)/8 )) + + case ${port_group} in + 0) + #the i2c expander base bus num to read qsfp eeprom + eeprombusbase=${NUM_MUX_9548_QSFP_0_CHAN[0]} + ;; + 1) + eeprombusbase=${NUM_MUX_9548_QSFP_1_CHAN[0]} + ;; + 2) + eeprombusbase=${NUM_MUX_9548_QSFP_2_CHAN[0]} + ;; + 3) + eeprombusbase=${NUM_MUX_9548_QSFP_3_CHAN[0]} + ;; + 4) + eeprombusbase=${NUM_MUX_9548_QSFP_4_CHAN[0]} + ;; + 5) + eeprombusbase=${NUM_MUX_9548_QSFP_5_CHAN[0]} + ;; + 6) + eeprombusbase=${NUM_MUX_9548_QSFP_6_CHAN[0]} + ;; + 7) + eeprombusbase=${NUM_MUX_9548_QSFP_7_CHAN[0]} + ;; + *) + echo "Please input 1~${PORT_NUM}" + exit + ;; + esac + + #set cpld_group and cpld_i2c_bus according to port + for ((i=0; i<5; ++i)) + do + if (("${port}" <= "${CPLD_QSFP_GROUP[i]}")); + then + local port_offset=0 + cpld_group=$i + cpld_i2c_bus=${NUM_MUX_9548_CPLD_CHAN[i]} + + if ((i>0)) + then + port_offset=$(( port - CPLD_QSFP_GROUP[i-1] )) + else + port_offset=$port + fi + cpld_qsfp_status_reg_offset=$((CPLD_QSFP_STATUS_REG_BASE + port_offset)) + cpld_qsfp_mode_reg_offset=$((CPLD_QSFP_MODE_SELECT_REG_BASE + port_offset)) + + break + fi + done +} + +function _i2c_get { + local i2c_bus=$1 + local i2c_addr=$2 + local reg=$3 + echo `i2cget -y ${i2c_bus} ${i2c_addr} ${reg}` +} + +function _i2c_set { + local i2c_bus=$1 + local i2c_addr=$2 + local reg=$3 + local mask=$4 + local value=$5 + + echo `i2cset -m $mask -y -r ${i2c_bus} ${i2c_addr} ${reg} ${value}` +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + #local variables + local port=$1 + + #global variables + eeprombusidx=$(( (port - 1)%8 )) + + case $eeprombusidx in + 0) + eeprombus=$(( $eeprombusbase + 0 )) + ;; + 1) + eeprombus=$(( $eeprombusbase + 1 )) + ;; + 2) + eeprombus=$(( $eeprombusbase + 2 )) + ;; + 3) + eeprombus=$(( $eeprombusbase + 3 )) + ;; + 4) + eeprombus=$(( $eeprombusbase + 4 )) + ;; + 5) + eeprombus=$(( $eeprombusbase + 5 )) + ;; + 6) + eeprombus=$(( $eeprombusbase + 6 )) + ;; + 7) + eeprombus=$(( $eeprombusbase + 7 )) + ;; + esac + eepromAddr=${I2C_ADDR_QSFP_EEPROM} +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + local value=0 + local status=0 + + echo "=========================================================" + echo "# Description: QSFP EEPROM GET" + echo "=========================================================" + + #status: 0 -> Down, 1 -> Up + _i2c_qsfp_signal_get ${QSFP_PORT} ${CPLD_QSFP_ABS} + + value=$qsfp_signal + status=$(( value?0:1 )) + + if [ $status = 0 ]; then + echo "[Fail] QSFP ${QSFP_PORT} is not present" + exit + fi + + echo "------------------------------" + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo "=========================================================" + echo "# Description: QSFP EEPROM INIT" + echo "=========================================================" + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init EEPROM + local i + for (( i=1; i<=${PORT_NUM}; i++ )) + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done +} + +#get qsfp singals (ABS, INT, RST, LP) from CPLD +function _i2c_qsfp_signal_get { + local port=$1 #port start from 1 + local signal=$2 + local attr_file="" + local phy_port=0 + local active="low_active" + + #global + qsfp_signal=0 + qsfp_signals=0 + + #verify port + if [ -z "${port}" ]; then + echo "No port, skip" + return + fi + + #verify port + if (( $port < 1 || $port > $PORT_NUM )) ; then + echo "invalid port, skip" + fi + + #get physical port + phy_port=$(_port_logic2phy $port) + + _qsfp_port_i2c_var_set ${phy_port} + _qsfp_eeprom_var_set ${phy_port} + + #verify signal + if [ -z "${signal}" ]; then + echo "No signal, skip" + return + elif [ "${signal}" == "${CPLD_QSFP_ABS}" ]; then + attr_file="qsfp_modprs" + elif [ "${signal}" == "${CPLD_QSFP_INT}" ]; then + attr_file="qsfp_int" + elif [ "${signal}" == "${CPLD_QSFP_RST}" ]; then + attr_file="qsfp_reset" + elif [ "${signal}" == "${CPLD_QSFP_LP}" ]; then + attr_file="qsfp_lpmode" + active="high_active" + else + echo "invalid signal ${signal}, skip" + return + fi + + mask=${BIT_MASK[bit_shift]} + + #signals of all ports + qsfp_signals=`cat ${PATH_SYS_CPLD}/${attr_file}` + #signal of single port + qsfp_signal=$(( (qsfp_signals >> (phy_port-1)) & 0x1)) + #print signals + printf "[port]=%d, [signal]=%s, [value]=%d (${active}), [qsfp_signals]=%016x\n" $port $signal $qsfp_signal $qsfp_signals +} + +#set qsfp singals (RST, LP) via CPLD +function _i2c_qsfp_signal_set { + local port=$1 #port start from 1 + local signal=$2 + local value=$3 + local values_ori=0 + local value_ori=0 + local values=0 + local attr_file="" + + #verify port + if [ -z "${port}" ]; then + echo "No port, skip" + return + fi + + #verify port + if (( $port < 1 || $port > $PORT_NUM )) ; then + echo "invalid port, skip" + fi + + #verify signal + if [ -z "${signal}" ]; then + echo "No signal, skip" + return + elif [ "${signal}" == "${CPLD_QSFP_RST}" ]; then + attr_file="qsfp_reset" + elif [ "${signal}" == "${CPLD_QSFP_LP}" ]; then + attr_file="qsfp_lpmode" + else + echo "invalid signal ${signal}, skip" + return + fi + + #get current signal values + _i2c_qsfp_signal_get $port $signal + value_ori=$qsfp_signal + values_ori=$qsfp_signals + + #if signal value is not changed, return + if [ "${value}" == "${value_ori}" ]; then + echo "value not changed, skip set operation" + return + fi + + #toggle the bit for update + values=$(( values_ori ^ (1 << (port-1)))) + + #set value to register + echo "$(printf "%016x" $values)" > ${PATH_SYS_CPLD}/${attr_file} + + #get updated signal values + _i2c_qsfp_signal_get $port $signal + values=$qsfp_signals + + #result + printf "Before: %016x\n" $values_ori + printf "After: %016x\n" $values +} + +#Init EEPROM +function _i2c_eeprom_init { + local i2c_bus=$1 + local i2c_addr=$2 + local action=$3 + local desc=$4 + local sys_i2c_dev=$PATH_SYS_I2C_DEVICES + + echo -n "${desc} EEPROM INIT" + + #Action check + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${sys_i2c_dev}/${i2c_bus}-$(printf "%04x" $i2c_addr) ]; then + echo "mb_eeprom ${i2c_addr}" > ${sys_i2c_dev}/i2c-${i2c_bus}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${sys_i2c_dev}/${i2c_bus}-$(printf "%04x" $i2c_addr) ]; then + echo "${i2c_addr}" > ${sys_i2c_dev}/i2c-${i2c_bus}/delete_device + fi + echo "DONE" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + local action=$1 + local i2c_bus=$I2C_BUS_MB_EEPROM + local i2c_addr=$I2C_ADDR_MB_EEPROM + local desc="Main Board" + + _i2c_eeprom_init $i2c_bus $i2c_addr $action $desc +} + +#Init CPU EEPROM +function _i2c_cpu_eeprom_init { + local action=$1 + local i2c_bus=$I2C_BUS_CPU_EEPROM + local i2c_addr=$I2C_ADDR_CPU_EEPROM + local desc="CPU Board" + + _i2c_eeprom_init $i2c_bus $i2c_addr $action $desc +} + +#get QSFP Status +function _i2c_qsfp_status_get { + local value=0 + local status=0 + + #status: 0 -> Down, 1 -> Up + _i2c_qsfp_signal_get ${QSFP_PORT} ${CPLD_QSFP_ABS} + value=$qsfp_signal + status=$(( value?0:1 )) + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + local phy_port=0 + local value=0 + local status=0 + + echo "=========================================================" + echo "# Description: QSFP TYPE Get" + echo "=========================================================" + + phy_port=$(_port_logic2phy ${QSFP_PORT}) + _qsfp_port_i2c_var_set ${phy_port} + _qsfp_eeprom_var_set ${phy_port} + + #get abs signal + _i2c_qsfp_signal_get ${QSFP_PORT} ${CPLD_QSFP_ABS} + value=$qsfp_signal + status=$(( value?0:1 )) + + #check qsfp is present + if [ $status = 0 ]; then + echo "[Fail] QSFP ${QSFP_PORT} is not present" + exit + fi + + #Get QSFP EEPROM info + if [ ! -e "${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf '%04x' $eepromAddr)/eeprom" ]; then + echo "FAIL, qsfp eeprom file does not exist. " + echo "qsfp eeprom file path: ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf '%04x' $eepromAddr)/eeprom" + return + fi + + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "------------------------------" + echo "identifier = $identifier" + echo "connector = $connector" + echo "transceiver = $transceiver" +} + +#Init PSU Kernel Module +function _i2c_psu_init { + echo "=========================================================" + echo "# Description: I2C PSU Init" + echo "=========================================================" + modprobe ingrasys_s9200_64x_psu + + echo "psu1 ${I2C_ADDR_PSU_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/new_device + echo "psu2 ${I2C_ADDR_PSU_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/new_device +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + local eeprom_psu1="" + local eeprom_psu2="" + + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + echo "PUS1 EEPROM" + eeprom_psu1="${PATH_SYSFS_PSU1}/psu_eeprom" + cat ${eeprom_psu1} | hexdump -C + + echo "------------------------------" + echo "PUS2 EEPROM" + eeprom_psu2="${PATH_SYSFS_PSU2}/psu_eeprom" + cat ${eeprom_psu2} | hexdump -C +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + local path_i2c_dev=${PATH_SYS_I2C_DEVICES} + local i2c_bus=${I2C_BUS_MB_EEPROM} + local i2c_addr=${I2C_ADDR_MB_EEPROM} + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get" + echo "=========================================================" + + ## MB EEPROM + cat ${path_i2c_dev}/${i2c_bus}-$(printf "%04x" ${i2c_addr})/eeprom | hexdump -v -C +} + +#Get CPU EEPROM Information +function _i2c_cpu_eeprom_get { + local path_i2c_dev=${PATH_SYS_I2C_DEVICES} + local i2c_bus=${I2C_BUS_CPU_EEPROM} + local i2c_addr=${I2C_ADDR_CPU_EEPROM} + echo "=========================================================" + echo "# Description: I2C CPU EEPROM Get" + echo "=========================================================" + + ## CPU EEPROM + cat ${path_i2c_dev}/${i2c_bus}-$(printf "%04x" ${i2c_addr})/eeprom | hexdump -v -C +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + local value=0 + + echo "=========================================================" + echo "# Description: Set Fan Tray LED" + echo "=========================================================" + + case ${FAN_TRAY} in + 1) + ioPort=$REG_OUT_0 + if [ "${COLOR_LED}" == "green" ]; then + mask=${BIT_MASK[0]} + elif [ "${COLOR_LED}" == "amber" ]; then + mask=${BIT_MASK[1]} + fi + ;; + 2) + ioPort=$REG_OUT_0 + if [ "${COLOR_LED}" == "green" ]; then + mask=${BIT_MASK[4]} + elif [ "${COLOR_LED}" == "amber" ]; then + mask=${BIT_MASK[5]} + fi + ;; + 3) + ioPort=$REG_OUT_1 + if [ "${COLOR_LED}" == "green" ]; then + mask=${BIT_MASK[0]} + elif [ "${COLOR_LED}" == "amber" ]; then + mask=${BIT_MASK[1]} + fi + ;; + 4) + ioPort=$REG_OUT_1 + if [ "${COLOR_LED}" == "green" ]; then + mask=${BIT_MASK[4]} + elif [ "${COLOR_LED}" == "amber" ]; then + mask=${BIT_MASK[5]} + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${ONOFF_LED}" == "on" ]; then + value=0xFF + elif [ "${ONOFF_LED}" == "off" ]; then + value=0x00 + else + echo "Invalid Parameters ${ONOFF_LED}, Exit!!!" + _help + exit ${FALSE} + fi + i2cset -m $mask -y -r ${I2C_BUS_FAN_BOARD} ${I2C_ADDR_FAN_BOARD} $ioPort $value + +} + +#Set System Status LED +function _i2c_sys_led { + local value=0 + local mask=${BIT_MASK[0]} + + if [ "${COLOR_LED}" == "green" ]; then + value=0xFF + elif [ "${COLOR_LED}" == "amber" ]; then + value=0x00 + else + echo "Invalid Parameters ${COLOR_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + _i2c_set_led $value $mask +} + +#Set FAN LED +function _i2c_fan_led { + local value=0 + local mask=${BIT_MASK[2]} + + if [ "${COLOR_LED}" == "green" ]; then + value=0x00 + elif [ "${COLOR_LED}" == "amber" ]; then + value=0xFF + else + echo "Invalid Parameters ${COLOR_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + _i2c_set_led $value $mask +} + +#Set PSU1 LED +function _i2c_psu1_led { + local value=0 + local mask=${BIT_MASK[3]} + + if [ "${COLOR_LED}" == "green" ]; then + value=0x00 + elif [ "${COLOR_LED}" == "amber" ]; then + value=0xFF + else + echo "Invalid Parameters ${COLOR_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + _i2c_set_led $value $mask +} + +#Set PSU2 LED +function _i2c_psu2_led { + local reg=${REG_OUT_0} + local value=0 + local mask=${BIT_MASK[4]} + + if [ "${COLOR_LED}" == "green" ]; then + value=0x00 + elif [ "${COLOR_LED}" == "amber" ]; then + value=0xFF + else + echo "Invalid Parameters ${COLOR_LED}, Exit!!!" + _help + exit ${FALSE} + fi + + _i2c_set_led $value $mask +} + +#Set LEDs in LED Board +function _i2c_set_led { + local value=$1 + local mask=$2 + local reg=${REG_OUT_0} + local i2c_bus=$I2C_BUS_LED_BOARD + local i2c_addr=$I2C_ADDR_LED_BOARD + + _i2c_set $i2c_bus $i2c_addr $reg $mask $value +} + +#Reset all system leds +function _i2c_reset_led { + local mask=0xFF + local value=$((2#00000011)) + local reg=${REG_OUT_0} + local i2c_bus=$I2C_BUS_LED_BOARD + local i2c_addr=$I2C_ADDR_LED_BOARD + + _i2c_set $i2c_bus $i2c_addr $reg $mask $value +} + +#Get Mother Board Version and Type +function _i2c_board_type_get { + echo "=========================================================" + echo "# Description: I2C MB Board Type Get" + echo "=========================================================" + local i2c_bus=${I2C_BUS_ID_GPIO} + local i2c_addr=${I2C_ADDR_ID_GPIO} + local reg=${REG_IN_1} + local value=0 + + value=$(_i2c_get $i2c_bus $i2c_addr $reg) + + #Bit 0-1 + boardBuildRev=$((value & 0x03)) + #Bit 2-3 + boardHwRev=$((value >> 2 & 0x03)) + #Bit 4-7 + boardId=$((value>>4)) + printf "[MB BOARD_ID] = 0x%02x, [HW Rev] = %d, [Build Rev] = %d\n" $boardId $boardHwRev $boardBuildRev +} + +#Get Board Version and Type from Dummy BMC Board +function _i2c_bmc_board_type_get { + echo "=========================================================" + echo "# Description: I2C BMC Board Type Get" + echo "=========================================================" + + local i2c_bus=${I2C_BUS_BMC_BOARD_TYPE} + local i2c_addr=${I2C_ADDR_BMC_BOARD_TYPE} + local reg=${REG_IN_1} + local value=0 + + value=$(_i2c_get $i2c_bus $i2c_addr $reg) + + #Bit 0-1 + boardBuildRev=$((($value) & 0x03)) + #Bit 2-3 + boardHwRev=$((($value) >> 2 & 0x03)) + #Bit 4-7 + boardId=$((($value) >> 4)) + printf "[BMC BOARD_ID] = 0x%02x, [HW Rev] = %d, [Build Rev] = %d\n" $boardId $boardHwRev $boardBuildRev +} + +#Get CPLD Version +function _i2c_cpld_version { + echo "=========================================================" + echo "# Description: CPLD Version" + echo "=========================================================" + cat ${PATH_SYS_CPLD}/cpld_version +} + +#Get PSU Status +function _i2c_psu_status { + local psu_abs="" + + psu1PwGood=`cat ${PATH_SYSFS_PSU1}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU1}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu1Exist=1 + else + psu1Exist=0 + fi + + psu2PwGood=`cat ${PATH_SYSFS_PSU2}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU2}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu2Exist=1 + else + psu2Exist=0 + fi + + printf "PSU1 Exist:%x PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Set 10G Mux to CPU or Front Panel +function _i2c_10g_mux { + + echo "=========================================================" + echo "# Description: 10G Mux" + echo "=========================================================" + + local target=${TARGET_10G_MUX} + local i2c_bus=${I2C_BUS_10GMUX} + local i2c_addr=${I2C_ADDR_10GMUX} + local reg=0 + local mask=0xff + local value=0 + local file_10g_mux="${PATH_SYS_CPLD}/cpld_10g_mux" + + #get current 10g mux register value on CPLD + value=`cat ${file_10g_mux}` + + if [ "${target}" == "cpu" ]; then + #Set XE0: slave address access + _i2c_set $i2c_bus $i2c_addr 0x06 $mask 0x18 + #Set XE0: CH4 D_IN0-S_OUTA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x2c $mask 0x00 + #Set XE0: CH5 NC-S_OUTB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x35 $mask 0x80 + #Set XE0: CH5 NC-S_OUTB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x34 $mask 0xab + #Set XE0: CH1 D_OUT0-S_INB0 EQ + _i2c_set $i2c_bus $i2c_addr 0x16 $mask 0x01 + #Set XE0: CH1 D_OUT0-S_INB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x18 $mask 0x80 + #Set XE0: CH1 D_OUT0-S_INB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x17 $mask 0xab + #Set XE1: CH6 D_IN1-S_OUTA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x3a $mask 0x00 + #Set XE1: CH7 NC-S_OUTB1 EQ + _i2c_set $i2c_bus $i2c_addr 0x41 $mask 0x00 + #Set XE1: CH7 NC-S_OUTB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x43 $mask 0x80 + #Set XE1: CH7 NC-S_OUTB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x42 $mask 0xab + #Set XE1: CH3 D_OUT1-S_INB1 EQ + _i2c_set $i2c_bus $i2c_addr 0x24 $mask 0x01 + #Set XE1: CH3 D_OUT1-S_INB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x26 $mask 0x80 + #Set XE1: CH3 D_OUT1-S_INB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x25 $mask 0xab + #Enable auto negotiation of XE ports + eval "bcmcmd 'port xe0,xe1 an=1 if=kr en=1'" + #delay 1 sec + sleep 1 + + #switch 10G MUX to cpu on CPLD + value=$(( value & 0xf3 )) + echo "$(printf "%x" ${value})" > ${file_10g_mux} + + echo "Switch 10G Mux to [CPU]" + + elif [ "${COLOR_LED}" == "fp" ]; then + #Set XE0: slave address access + _i2c_set $i2c_bus $i2c_addr 0x06 $mask 0x18 + #Set XE0: CH4 D_IN0-S_OUTA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x2c $mask 0x00 + #Set XE0: CH4 D_IN0-S_OUTA0 DEM + _i2c_set $i2c_bus $i2c_addr 0x2e $mask 0x80 + #Set XE0: CH4 D_IN0-S_OUTA0 VOD + _i2c_set $i2c_bus $i2c_addr 0x2d $mask 0xab + #Set XE0: CH0 NC-S_INA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x0f $mask 0x00 + #Set XE0: CH1 D_OUT0-S_INB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x18 $mask 0x80 + #Set XE0: CH1 D_OUT0-S_INB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x17 $mask 0xab + #Set XE1: CH6 D_IN1-S_OUTA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x3a $mask 0x00 + #Set XE1: CH6 D_IN1-S_OUTA1 DEM + _i2c_set $i2c_bus $i2c_addr 0x3c $mask 0x80 + #Set XE1: CH6 D_IN1-S_OUTA1 VOD + _i2c_set $i2c_bus $i2c_addr 0x3b $mask 0xab + #Set XE1: CH2 NC-S_INA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x1d $mask 0x00 + #Set XE1: CH3 D_OUT1-S_INB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x26 $mask 0x80 + #Set XE1: CH3 D_OUT1-S_INB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x25 $mask 0xab + #Enable auto negotiation of XE ports + eval "bcmcmd 'port xe0,xe1 an=0 if=kr en=1'" + #delay 1 sec + sleep 1 + + #switch 10G MUX to front panel on CPLD + value=$(( value | 0x0c )) + echo "$(printf "%x" ${value})" > ${file_10g_mux} + + echo "Switch 10G Mux to [Front Panel]" + else + echo "invalid target, please set target to cpu/fp" + fi +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + start_time_str=`date` + start_time_sec=$(date +%s) + + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cpu_eeprom_get" ]; then + _i2c_cpu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_INIT_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_cpu_eeprom_init" ]; then + _i2c_cpu_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_signal_get" ]; then + _i2c_qsfp_signal_get ${QSFP_PORT} ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_signal_set" ]; then + _i2c_qsfp_signal_set ${QSFP_PORT} ${QSFP_ACTION} ${QSFP_VALUE} + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_test" ]; then + _i2c_led_fan_tray_test + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_bmc_board_type_get" ]; then + _i2c_bmc_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_deinit + _i2c_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cpu_eeprom_get + _i2c_board_type_get + _i2c_bmc_board_type_get + _i2c_cpld_version + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_10g_mux" ]; then + _i2c_10g_mux + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main 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 new file mode 100755 index 000000000000..47cfbb3ea008 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..63}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1) ` + local identifier=`echo "$qsfp_type" | egrep -o 'identifier = .*$' | sed -e 's/identifier = //g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | egrep -o 'connector = .*$' | sed -e 's/connector = //g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`sonic-db-cli ASIC_DB HLEN HIDDEN` + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_si_cfg.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_si_cfg.sh new file mode 100755 index 000000000000..ba59c50ca7bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/qsfp_si_cfg.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +TYPE=${1} +PORT=${2} + +#FIXME update SI values +#QSFP Optical +function _qsfp_optical_si_set { + local idx=0 + #FIXME + local si=(11 68 13 15 68 15 11 68 9 11 68 13 + 11 68 17 11 68 13 13 68 11 11 68 15 + 11 68 13 11 68 17 11 68 17 13 68 13 + 11 68 15 11 68 9 11 68 9 11 68 7 + 9 68 13 13 68 7 11 68 7 11 68 11 + 11 68 13 11 68 13 9 68 7 11 68 11 + 11 68 9 11 68 15 11 68 9 11 68 9 + 11 68 9 11 68 7 11 68 9 11 68 9 + 13 68 9 13 68 13 13 68 7 13 68 11 + 13 68 5 13 68 11 13 68 5 13 68 11 + + 11 68 3 11 68 9 11 68 5 11 68 13 + 11 68 9 11 68 9 11 68 11 13 68 5 + 13 68 3 11 68 7 11 68 5 11 68 9 + 11 68 9 13 68 9 13 68 1 11 68 11 + 5 68 1 11 68 7 11 68 1 13 68 3 + 11 68 5 11 68 3 11 68 7 11 68 3 + 11 68 3 13 68 11 13 68 1 13 68 3 + 11 68 1 13 68 1 13 68 1 11 68 7 + 11 68 1 11 68 5 11 68 1 9 68 5 + 5 68 1 13 68 1 11 68 5 11 68 3 + + 11 68 1 11 68 11 11 68 1 13 68 7 + 13 68 1 15 68 1 11 68 1 13 68 7 + 13 68 1 11 68 5 11 68 1 11 68 1 + 11 68 5 13 68 3 11 68 5 9 68 1 + 11 68 5 13 68 5 13 68 1 11 68 9 + 13 68 1 11 68 13 13 68 1 11 68 7 + 11 68 1 11 68 1 9 68 1 11 68 1 + 11 68 1 11 68 1 11 68 5 11 68 1 + 13 68 1 11 68 11 11 68 1 11 68 1 + 11 68 1 11 68 15 11 68 1 13 68 5 + + 11 68 1 11 68 1 9 68 1 13 68 1 + 11 68 1 11 68 1 9 68 1 11 68 1 + 11 68 1 13 68 3 11 68 1 13 68 1 + 11 68 1 13 68 1 11 68 1 11 68 13 + 11 68 1 11 68 1 11 68 1 11 68 1 + 11 68 11 11 68 1 13 68 1 11 68 1 + 11 68 1 11 68 9 11 68 1 11 68 7 + 11 68 1 13 68 1 13 68 1 11 68 1 + 11 68 1 11 68 5 11 68 1 13 68 3 + 11 68 3 9 68 1 11 68 3 11 68 1 + + 11 68 7 11 68 9 11 68 1 11 68 9 + 11 68 3 11 68 15 11 68 3 9 68 9 + 9 68 1 11 68 3 11 68 1 11 68 5 + 11 68 5 5 68 5 11 68 5 11 68 1 + 13 68 5 13 68 5 11 68 1 11 68 9 + 11 68 1 11 68 1 11 68 1 13 68 7 + 11 68 1 11 68 5 11 68 1 11 68 3 + 11 68 5 11 68 1 11 68 5 11 68 1 + 11 68 3 11 68 7 11 68 3 11 68 9 + 11 68 1 13 68 7 11 68 1 9 68 9 + + 13 68 1 11 68 5 11 68 3 13 68 5 + 11 68 7 11 68 11 13 68 5 9 68 5 + 11 68 5 11 68 13 13 68 7 11 68 13 + 11 68 7 11 68 11 11 68 5 11 68 11 + 11 68 11 11 68 11 11 68 7 11 68 11 + 11 68 13 11 68 11 11 68 9 15 68 9 + 11 68 11 11 68 5 11 68 7 13 68 11 + 11 68 9 13 68 17 11 68 7 11 68 13 + 11 68 11 11 68 17 11 68 13 11 68 15 + 13 68 9 13 68 11 11 68 11 13 68 7 + + 11 68 13 13 68 9 11 68 9 11 68 9 + 11 68 19 11 68 15 11 68 9 11 68 11 + 13 68 13 13 68 17 13 68 11 11 68 11 + 13 68 9 13 68 13 11 68 11 11 68 9) + + idx=$(( PORT * 12 )) + #FIXEME + #for j in {0..3} + #do + # bcmcmd "phy ce${PORT} CL93N72_UT_CTL2r.${j} CL93N72_TXFIR_POST=${si[idx++]}; phy ce${PORT} CL93N72_UT_CTL3r.${j} CL93N72_TXFIR_MAIN=${si[idx++]}; phy ce${PORT} CL93N72_UT_CTL2r.${j} CL93N72_TXFIR_PRE=${si[idx++]};" + #done +} + +function _qsfp_dac_si_set { + local idx=0 + # each port has 4 lanes, each lane has 3 SI values (post,main,pre), total 4*3=12 + local port_si=12 + + #si[0]: txfir_post for port0 lane0 + #si[1]: txfir_main for port0 lane0 + #si[2]: txfir_pre for port0 lane0 + + #si[3]: txfir_post for port0 lane1 + #si[4]: txfir_main for port0 lane1 + #si[5]: txfir_pre for port0 lane1 + + local si=(11 68 13 15 68 15 11 68 9 11 68 13 + 11 68 17 11 68 13 13 68 11 11 68 15 + 11 68 13 11 68 17 11 68 17 13 68 13 + 11 68 15 11 68 9 11 68 9 11 68 7 + 9 68 13 13 68 7 11 68 7 11 68 11 + 11 68 13 11 68 13 9 68 7 11 68 11 + 11 68 9 11 68 15 11 68 9 11 68 9 + 11 68 9 11 68 7 11 68 9 11 68 9 + 13 68 9 13 68 13 13 68 7 13 68 11 + 13 68 5 13 68 11 13 68 5 13 68 11 + + 11 68 3 11 68 9 11 68 5 11 68 13 + 11 68 9 11 68 9 11 68 11 13 68 5 + 13 68 3 11 68 7 11 68 5 11 68 9 + 11 68 9 13 68 9 13 68 1 11 68 11 + 5 68 1 11 68 7 11 68 1 13 68 3 + 11 68 5 11 68 3 11 68 7 11 68 3 + 11 68 3 13 68 11 13 68 1 13 68 3 + 11 68 1 13 68 1 13 68 1 11 68 7 + 11 68 1 11 68 5 11 68 1 9 68 5 + 5 68 1 13 68 1 11 68 5 11 68 3 + + 11 68 1 11 68 11 11 68 1 13 68 7 + 13 68 1 15 68 1 11 68 1 13 68 7 + 13 68 1 11 68 5 11 68 1 11 68 1 + 11 68 5 13 68 3 11 68 5 9 68 1 + 11 68 5 13 68 5 13 68 1 11 68 9 + 13 68 1 11 68 13 13 68 1 11 68 7 + 11 68 1 11 68 1 9 68 1 11 68 1 + 11 68 1 11 68 1 11 68 5 11 68 1 + 13 68 1 11 68 11 11 68 1 11 68 1 + 11 68 1 11 68 15 11 68 1 13 68 5 + + 11 68 1 11 68 1 9 68 1 13 68 1 + 11 68 1 11 68 1 9 68 1 11 68 1 + 11 68 1 13 68 3 11 68 1 13 68 1 + 11 68 1 13 68 1 11 68 1 11 68 13 + 11 68 1 11 68 1 11 68 1 11 68 1 + 11 68 11 11 68 1 13 68 1 11 68 1 + 11 68 1 11 68 9 11 68 1 11 68 7 + 11 68 1 13 68 1 13 68 1 11 68 1 + 11 68 1 11 68 5 11 68 1 13 68 3 + 11 68 3 9 68 1 11 68 3 11 68 1 + + 11 68 7 11 68 9 11 68 1 11 68 9 + 11 68 3 11 68 15 11 68 3 9 68 9 + 9 68 1 11 68 3 11 68 1 11 68 5 + 11 68 5 5 68 5 11 68 5 11 68 1 + 13 68 5 13 68 5 11 68 1 11 68 9 + 11 68 1 11 68 1 11 68 1 13 68 7 + 11 68 1 11 68 5 11 68 1 11 68 3 + 11 68 5 11 68 1 11 68 5 11 68 1 + 11 68 3 11 68 7 11 68 3 11 68 9 + 11 68 1 13 68 7 11 68 1 9 68 9 + + 13 68 1 11 68 5 11 68 3 13 68 5 + 11 68 7 11 68 11 13 68 5 9 68 5 + 11 68 5 11 68 13 13 68 7 11 68 13 + 11 68 7 11 68 11 11 68 5 11 68 11 + 11 68 11 11 68 11 11 68 7 11 68 11 + 11 68 13 11 68 11 11 68 9 15 68 9 + 11 68 11 11 68 5 11 68 7 13 68 11 + 11 68 9 13 68 17 11 68 7 11 68 13 + 11 68 11 11 68 17 11 68 13 11 68 15 + 13 68 9 13 68 11 11 68 11 13 68 7 + + 11 68 13 13 68 9 11 68 9 11 68 9 + 11 68 19 11 68 15 11 68 9 11 68 11 + 13 68 13 13 68 17 13 68 11 11 68 11 + 13 68 9 13 68 13 11 68 11 11 68 9) + + # get first si index for this port + idx=$(( PORT * port_si )) + + # loop for 4 lanes + for j in {0..3} + do + bcmcmd "phy ce${PORT} CL93N72_UT_CTL2r.${j} CL93N72_TXFIR_POST=${si[idx++]}; phy ce${PORT} CL93N72_UT_CTL3r.${j} CL93N72_TXFIR_MAIN=${si[idx++]}; phy ce${PORT} CL93N72_UT_CTL2r.${j} CL93N72_TXFIR_PRE=${si[idx++]};" + done +} + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} optical [0-63]" + echo " : ${0} dac [0-63]" + echo "----------------------------------------------------" +} + +#Main Function +function _main { + + if [ "${TYPE}" == "help" ]; then + _help + elif [ "${TYPE}" == "optical" ]; then + _qsfp_optical_si_set + elif [ "${TYPE}" == "dac" ]; then + _qsfp_dac_si_set + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi +} + +_main diff --git a/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/s9200_64x_monitor.sh b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/s9200_64x_monitor.sh new file mode 100755 index 000000000000..974da6d5001f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ingrasys/s9200-64x/utils/s9200_64x_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-inventec/.gitignore b/platform/broadcom/sonic-platform-modules-inventec/.gitignore new file mode 100644 index 000000000000..2490baa9d1e2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/.gitignore @@ -0,0 +1,59 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-inventec/LICENSE b/platform/broadcom/sonic-platform-modules-inventec/LICENSE new file mode 100644 index 000000000000..9cecc1d4669e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/asic_monitor.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/asic_monitor.py new file mode 100755 index 000000000000..bcb05b9cb845 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/asic_monitor.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Inventec, Inc. +# +# Editor: James Huang ( Huang.James@inventec.com ) +# +""" +Usage: %(scriptName)s [options] command object + +Auto detecting the Chipset temperature and update + +options: + -h | --help : this help message + -d | --debug : run with debug mode + +""" + +try: + import os + import commands + import sys, getopt + import logging + import re + import time + import syslog + from sonic_sfp.bcmshell import bcmshell + +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +args = [] +INV_REDWOOD_PLATFORM = "SONiC-Inventec-d7032-100" +INV_CYPRESS_PLATFORM = "SONiC-Inventec-d7054" +INV_SEQUOIA_PLATFORM = "SONiC-Inventec-d7264" +INV_MAPLE_PLATFORM = "SONiC-Inventec-d6556" +INV_MAGNOLIA_PLATFORM = "SONiC-Inventec-d6254qs" + +PSOC_NAME = "name" +HWMON_PATH = "/sys/class/hwmon/" +SWITCH_TEMP_FILE_NAME = "switch_tmp" + +def log_message( level, string ): + syslog.openlog("asic_monitor", syslog.LOG_PID, facility=syslog.LOG_DAEMON) + syslog.syslog( level, string ) + +def initialLoop(): + + global bcm_obj + initialNotOK = True + + while initialNotOK : + try: + bcm_obj = BCMUtil() + bcm_obj.execute_command("echo") + initialNotOK = False + print bcm_obj + log_message( syslog.LOG_INFO, "BCMUtil Object initialed successfully" ) + except Exception, e: + print "Exception. The warning is {0}".format(str(e)) + time.sleep(10) + +class BCMUtil(bcmshell): + + asic_temperature = 0 + platform = None + + def get_platform(self): + if self.platform is None: + self.platform = os.popen("uname -n").read().strip() + return self.platform + + def get_asic_temperature( self ): + return self.asic_temperature + + def set_asic_temperature( self, temp ): + self.asic_temperature = temp + + def parsing_asic_temp(self): + content = self.run("show temp") + for line in content.split("\n"): + TempObject = re.search(r"(average current temperature is)\s+(?P\d+)\.(?P\d+)",line) + if TempObject is not None: + self.set_asic_temperature( int( TempObject.group("temperature_high") ) ) + + def execute_command(self, cmd): + return self.run(cmd) + + +def main(): + + global bcm_obj + initialLoop() + log_message( syslog.LOG_INFO, "Object initialed successfully" ) + + while 1 : + try: + bcm_obj.parsing_asic_temp() + for index in os.listdir(HWMON_PATH): + file_list = os.listdir("{0}/{1}/device/".format(HWMON_PATH,index)) + if PSOC_NAME in file_list : + with open( "{0}/{1}/device/{2}".format(HWMON_PATH, index, PSOC_NAME), 'rb') as readPtr: + content = readPtr.read().strip() + if bcm_obj.get_platform() == INV_SEQUOIA_PLATFORM : + if content == "inv_bmc" and SWITCH_TEMP_FILE_NAME in file_list : + os.system("echo {0} > {1}/{2}/device/{3}".format( ( bcm_obj.get_asic_temperature() * 1000 ), HWMON_PATH, index, SWITCH_TEMP_FILE_NAME )) + break + else : + if content == "inv_psoc" and SWITCH_TEMP_FILE_NAME in file_list : + print "echo {0} > {1}/{2}/device/{3}".format( ( bcm_obj.get_asic_temperature() * 1000 ), HWMON_PATH, index, SWITCH_TEMP_FILE_NAME ) + os.system("echo {0} > {1}/{2}/device/{3}".format( ( bcm_obj.get_asic_temperature() * 1000 ), HWMON_PATH, index, SWITCH_TEMP_FILE_NAME )) + break + except Exception, e: + log_message( syslog.LOG_WARNING, "Exception. The warning is {0}".format(str(e)) ) + initialLoop() + time.sleep(5) + + syslog.closelog() + del bcm_obj + +if __name__ == "__main__": + main() + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py new file mode 100755 index 000000000000..bab0e2dafe76 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py @@ -0,0 +1,372 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Inventec, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import time +import syslog +import re +from sonic_sfp.bcmshell import bcmshell + + +# ===================================================================== +# global variable init +# ===================================================================== +# port object +PORT_LIST = [] +# object is to execute bcm shell command +BCM_SHELL = None +SHELL_READY = False +# port status that is auto update by chip in data ram +STATUS_RX = 1<<0 +STATUS_TX = 1<<1 +# define data ram address +PORT_DATA_OFFSET_ADDR = 0xA0 +# define board type +INV_MAGNOLIA = "SONiC-Inventec-d6254qs" +INV_REDWOOD = "SONiC-Inventec-d7032-100" +INV_CYPRESS = "SONiC-Inventec-d7054" +INV_MAPLE = "SONiC-Inventec-d6556" +INV_SEQUOIA = "" +BOARD_TPYE = "" +EAGLE_CORE = [] +# define port data for bit streaming +BIT_LINK = None +BIT_FAULT = None +BIT_TX = None +BIT_RX = None +BIT_SPEED0 = None +BIT_SPEED1 = None +# define port speed +SPEED_100G = 100 +SPEED_40G = 40 +SPEED_25G = 25 +SPEED_10G = 10 + + +# ===================================================================== +# class object +# ===================================================================== +class Port(): + + port_num = None + name = None + bcm_id = None + led_up = None + s_addr = None + write2_up = None + led_index = None + link_status = None + speed = None + + def write_data_ram(self, data): + BCM_SHELL.cmd("setreg CMIC_LEDUP{0}_DATA_RAM({1}) {2}".format(self.write2_up, self.led_index, data)) + + def read_data_ram(self): + r_string = BCM_SHELL.run("getreg CMIC_LEDUP{0}_DATA_RAM({1})".format(self.led_up, self.s_addr)) + for line in r_string.split("\n"): + re_obj = re.search(r"\.+)\>", line) + if re_obj is not None: + #syslog.syslog(syslog.LOG_DEBUG, "Read Led({0}) data_ram({1}): {2}".format(self.up, addr, re_obj.group("data"))) + return int(re_obj.group("data"), 16) + + + +# ===================================================================== +# Function +# ===================================================================== +def _remap_registers(fp): + + content = fp.readlines() + fp.close() + err = False + + for line in content: + try: + BCM_SHELL.cmd(line.rstrip()) + except Exception, e: + err = True + syslog.syslog(syslog.LOG_ERR, "remap register abnormal: {0}".format(str(e))) + + if not err: + syslog.syslog(syslog.LOG_INFO, "remap Led registers successfully") + + + +def _board_init(): + + global BOARD_TPYE + global BIT_LINK + global BIT_FAULT + global BIT_TX + global BIT_RX + global BIT_SPEED0 + global BIT_SPEED1 + global EAGLE_CORE + global TOTAL_SCAN_BITS + global SYNC_S + global SYNC_P + + cmd = "uname -n" + platform = os.popen(cmd).read() + + if platform.rstrip() == INV_MAGNOLIA: + BOARD_TPYE = "inventec_d6254qs" + BIT_RX = 1<<0 #0x01 + BIT_TX = 1<<1 #0x02 + BIT_SPEED1 = 1<<4 #0x10 + BIT_LINK = 1<<7 #0x80 + fp = open('/usr/share/sonic/device/x86_64-inventec_d6254qs-r0/led_proc_init.soc', "r") + _remap_registers(fp) + + elif platform.rstrip() == INV_REDWOOD: + BOARD_TPYE = "inventec_d7032q28b" + BIT_RX = 1<<0 #0x01 + BIT_TX = 1<<1 #0x02 + BIT_SPEED0 = 1<<3 #0x08 + BIT_SPEED1 = 1<<4 #0x10 + BIT_FAULT = 1<<6 #0x40 + BIT_LINK = 1<<7 #0x80 + EAGLE_CORE = [66, 100] + fp = open('/usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/led_proc_init.soc', "r") + _remap_registers(fp) + + elif platform.rstrip() == INV_CYPRESS: + BOARD_TPYE = "inventec_d7054q28b" + BIT_LINK = 1<<0 #0x01 + BIT_FAULT = 1<<1 #0x02 + BIT_SPEED0 = 1<<2 #0x04 + EAGLE_CORE = [66, 100] + + elif platform.rstrip() == INV_SEQUOIA: + BOARD_TPYE = "inventec_d7264q28b" + + elif platform.rstrip() == INV_MAPLE: + BOARD_TPYE = "inventec_d6556" + fp = open('/usr/share/sonic/device/x86_64-inventec_d6556-r0/led_proc_init.soc', "r") + _remap_registers(fp) + #led process: m0 led process that is controlled by linkscan_led_fw.bin and custom_led.bin + syslog.syslog(syslog.LOG_INFO, "Found device: {0}".format(BOARD_TPYE)) + exit(0) + + else: + BOARD_TPYE = "not found" + syslog.syslog(syslog.LOG_ERR, "Found device: {0}".format(BOARD_TPYE)) + exit(0) + + syslog.syslog(syslog.LOG_INFO, "Found device: {0}".format(BOARD_TPYE)) + + + +def _lookup_led_index(p): + + index = 0 + if BOARD_TPYE == "inventec_d6254qs": + if 0 <= p.port_num <= 47: + index = p.port_num + (p.port_num / 4) + p.write2_up = 0 + elif 48 <= p.port_num <= 71: + index = p.port_num - 48 + p.write2_up = 1 + if p.led_up == 0: + p.s_addr = p.port_num * 2 + elif p.led_up == 1: + p.s_addr = (p.port_num - 36) * 2 + + elif BOARD_TPYE == "inventec_d7032q28b": + p.write2_up = 0 + index = p.port_num + if 0 <= p.port_num <= 7: + p.s_addr = p.port_num * 8 + elif 8 <= p.port_num <= 23: + p.s_addr = (p.port_num - 8) * 8 + elif 24 <= p.port_num <= 31: + p.s_addr = (p.port_num - 16) * 8 + + else: + p.write2_up = p.led_up + for port in PORT_LIST: + if p.bcm_id == port.bcm_id: + break + if p.led_up == port.led_up: + index += 1 + + return PORT_DATA_OFFSET_ADDR + index + + +def _update_port_list(only_update): + + global PORT_LIST + number = 0 + count = 0 + + content = BCM_SHELL.run("ps") + for line in content.split("\n"): + re_obj = re.search(r"(?P(xe|ce)\d+)\(\s*(?P\d+)\)\s+(?P(up|down|!ena)).+\s+(?P\d+)G", line) + if re_obj is not None: + if int(re_obj.group("bcm_id")) not in EAGLE_CORE: + if only_update: + PORT_LIST[number].link_status = re_obj.group("link") + else: + # create port object while first time + port_obj = Port() + port_obj.port_num = number + port_obj.name = re_obj.group("port_name") + port_obj.bcm_id = int(re_obj.group("bcm_id")) + port_obj.link_status = re_obj.group("link") + port_obj.speed = int(re_obj.group("speed")) + PORT_LIST.append(port_obj) + number += 1 + + if not only_update: + content = BCM_SHELL.run("led status") + for line in content.split("\n"): + re_obj = re.search(r"(?P\d+).+(?P\d)\:", line) + if re_obj is not None: + if int(re_obj.group("bcm_id")) not in EAGLE_CORE: + PORT_LIST[count].led_up = int(re_obj.group("led_up")) + PORT_LIST[count].led_index = _lookup_led_index(PORT_LIST[count]) + count += 1 + + if number is not count: + PORT_LIST = [] + syslog.syslog(syslog.LOG_ERR, "The amount of port is not match") + + + +def sync_bcmsh_socket(): + + global BCM_SHELL + global SHELL_READY + waitSyncd = True + retryCount = 0 + + while waitSyncd: + time.sleep(10) + try: + BCM_SHELL = bcmshell() + BCM_SHELL.run("Echo") + waitSyncd = False + except Exception, e: + print "{0}, Retry times({1})".format(str(e),retryCount) + #syslog.syslog(syslog.LOG_DEBUG, "{0}, Retry times({1})".format(str(e),retryCount)) + retryCount += 1 + + syslog.syslog(syslog.LOG_INFO, "bcmshell socket create successfully") + + if SHELL_READY is False: + SHELL_READY = True + return + elif SHELL_READY is True: + update_led_status() + + + +def update_led_status(): + + led_thread = True # True/False (gate to turn on/off) + reset_sec = 2 + count_down = 0 + queue_active = [] + port_data = None + s_byte = None + + + # thread for keeping update port status in data ram + while led_thread: + try: + if count_down == 0: + queue_active = [] + _update_port_list(1) + for port in PORT_LIST: + if port.link_status == "up": + queue_active.append(port) + else: + port_data = 0 + port.write_data_ram(port_data) + count_down = reset_sec + else: + for port in queue_active: + port_data = 0 + + if BOARD_TPYE == "inventec_d6254qs": + s_byte = port.read_data_ram() + if s_byte&STATUS_RX: + port_data |= BIT_RX + if s_byte&STATUS_TX: + port_data |= BIT_TX + port_data |= BIT_LINK + + elif BOARD_TPYE == "inventec_d7032q28b": + s_byte = port.read_data_ram() + if s_byte&STATUS_RX: + port_data |= BIT_RX + if s_byte&STATUS_TX: + port_data |= BIT_TX + if port.speed == SPEED_100G: + port_data |= BIT_SPEED0 + port_data |= BIT_SPEED1 + elif port.speed == SPEED_40G: + port_data |= BIT_SPEED1 + elif port.speed == SPEED_25G: + port_data |= BIT_SPEED0 + else: + pass + port_data |= BIT_LINK + + elif BOARD_TPYE == "inventec_d7054q28b": + if port.speed != SPEED_100G and port.speed != SPEED_25G: + port_data |= BIT_SPEED0 + + # write data to update data ram for specific port + port.write_data_ram(port_data) + + time.sleep(0.5) + count_down -= 1 + + except Exception, e: + syslog.syslog(syslog.LOG_WARNING, "{0}".format(str(e))) + sync_bcmsh_socket() + + + +def debug_print(): + + for port in PORT_LIST: + output = "" + output += "name:{0} | ".format(port.name) + output += "port_num:{0} | ".format(port.port_num) + output += "bcm_id:{0} | ".format(port.bcm_id) + output += "link_status:{0} | ".format(port.link_status) + output += "speed:{0} | ".format(port.speed) + output += "led_up:{0} | ".format(port.led_up) + output += "s_addr:{0} | ".format(port.s_addr) + output += "write2_up:{0} | ".format(port.write2_up) + output += "led_index:{0} | ".format(port.led_index) + print output + + +if __name__ == "__main__": + + syslog.openlog("led_proc", syslog.LOG_PID, facility=syslog.LOG_DAEMON) + + sync_bcmsh_socket() + _board_init() + _update_port_list(0) + #debug_print() + update_led_status() + + syslog.closelog() diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/platform_status.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/platform_status.py new file mode 100755 index 000000000000..f1e7f7fece77 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/platform_status.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +import os +import socket +from collections import OrderedDict + +# Purpose: Shutdown DUT upon receiving thermaltrip event from kernel (inv_pthread) + +NETLINK_KOBJECT_UEVENT = 15 + +class KernelEventMonitor(object): + + def __init__(self): + self.received_events = OrderedDict() + self.socket = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT) + + def start(self): + self.socket.bind((os.getpid(), -1)) + + def stop(self): + self.socket.close() + + def __enter__(self): + self.start() + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.stop() + + def __iter__(self): + while True: + for item in monitor.next_events(): + yield item + + def next_events(self): + data = self.socket.recv(16384) + event = {} + for item in data.split(b'\x00'): + if not item: + #check if we have an event and if we already received it + if event and event['SEQNUM'] not in self.received_events: + self.received_events[event['SEQNUM']] = None + if (len(self.received_events) > 100): + self.received_events.popitem(last=False) + yield event + event = {} + else: + try: + k, v = item.split(b'=', 1) + event[k.decode('ascii')] = v.decode('ascii') + except ValueError: + pass + +if __name__ == '__main__': + with KernelEventMonitor() as monitor: + for event in monitor: + if event['SUBSYSTEM'] == 'platform_status': + print('subsystem is platform_status') + + # Receive thermaltrip event + if event['ACTION'] == 'remove' and event['DEVPATH'] == '/kernel/platform_status/fan': + os.system("shutdown -h now") + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/transceiver_monitor.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/transceiver_monitor.py new file mode 100755 index 000000000000..9e4a44c167fe --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/transceiver_monitor.py @@ -0,0 +1,378 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Inventec, Inc. +# +# Editor: James Huang ( Huang.James@inventec.com ) +# +# + +""" +Usage: %(scriptName)s [options] command object + +Auto detecting the transceiver and set the correct if_type value + +options: + -h | --help : this help message + -d | --debug : run with debug mode + +""" + +try: + import os + import commands + import sys, getopt + import logging + import re + import time + import datetime + import syslog + from sfputil import SfpUtil + from sonic_sfp.bcmshell import bcmshell + +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +DEBUG = False +args = [] +INV_REDWOOD_PLATFORM = "SONiC-Inventec-d7032-100" +INV_CYPRESS_PLATFORM = "SONiC-Inventec-d7054" +INV_SEQUOIA_PLATFORM = "SONiC-Inventec-d7264" +INV_MAPLE_PLATFORM = "SONiC-Inventec-d6556" +INV_MAGNOLIA_PLATFORM = "SONiC-Inventec-d6254qs" + +transceiver_type_dict = { + "FCBG110SD1C03": "SR", + "FCBG110SD1C05": "SR", + "FTLX8571D3BCL": "SR", + "FTLX8574D3BCL": "SR", + "AFBR-709DMZ": "SR", + "AFBR-709SMZ": "SR", + "FTLX8571D3BCV": "SR", + "FTLX1471D3BCL": "SR", + "FTLX1871M3BCL": "SR", + "FTLF8536P4BCL": "SR", + "FCBG125SD1C05": "SR", + "FCBG125SD1C30": "SR", + "FCBG125SD1C03": "SR", + "FCBG410QB1C03-1E": "SR4", + "FCBG4100QB1C030-1E": "SR4", + "885350163": "SR4", + "88535017": "SR4", + "FTL410QE2C": "SR4", + "FTL410QD3C": "SR4", + "FTL410QD2C": "SR4", + "AFBR-79E3PZ": "SR4", + "AFBR-79Q4Z": "SR4", + "FTL4C1QE1C": "SR4", + "FTLC9551REPM": "SR4", + "FTLC1151RDPL": "SR4", + "DAC-010SS-X50" : "KR", + "DAC-010QQ-X50": "KR4", + "DAC-040QS-007": "KR4", + "DAC-040QQ-007": "KR4", + "DAC-040QQ-005": "KR4", + "DAC-040QS-005": "KR4", + "NDAAFF-0001": "KR4", + "L0HQF001-SD-R": "KR4", + "DAC-Q28/Q28-28-01": "KR4", + "NDAAFF-0003": "KR4", + "NDAQGF0001": "KR4", + "L0HQF003-SD-R": "KR4", + "NDAQGJ-0003": "KR4", + "L0HQF004-SD-R": "KR4", + "L0HSF006-SD-R": "KR", + "L0HSF007-SD-R": "KR", + "L0HSF008-SD-R": "KR", + "L0HQF009-SD-R": "KR4", + "FSPP-H7-M85-X3D": "SR", + "PT0-M3-4D33K-C2": "SR", + "RTXM228-551": "SR", + "RTXM330-003": "SR", + "RTXM330-030": "SR", + "MFA2P10-A005": "SR", + "QAB-OA03MC": "SR4", + "QAB-OA05MC": "SR4", + "RTXM320-571": "SR4", + "AFBR-89CDDZ": "SR4", + "RTXM420-550": "SR4", + "MMA1B00-C100D": "SR4", + "RTXM420-551": "SR4", + "E04025QTXA000": "SR4", + "LQ210PR-Oxxx": "SR4", + "TR-FC13L-N00": "SR4", + "SPQ-CE-LR-CDFL": "SR4", + "FIM37700/170": "SR4", + "FCBN425QE1C03": "SR4", + "TQS-Q14H8-XCAXX": "SR4", + "FPD-203R008-10/3": "SR4", + "LTA8531-PC+": "SR4" + } + +initial_command = [] + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def log_message( string ): + syslog.openlog("transceiver_monitor", syslog.LOG_PID, facility=syslog.LOG_DAEMON) + syslog.syslog(syslog.LOG_NOTICE, string) + +class BCMUtil(bcmshell): + + port_to_bcm_mapping = dict() + sal_config_list = dict() + eagle_list = [] + platform = None + + def get_platform(self): + if self.platform is None: + self.platform = os.popen("uname -n").read().strip() + return self.platform + + def get_port_to_bcm_mapping(self): + if self.port_to_bcm_mapping is None: + return dict() + else: + return self.port_to_bcm_mapping + + def show_port_to_bcm_mapping(self): + for key,value in self.port_to_bcm_mapping.iteritems(): + print "{0}---{1}".format(key, value) + + def get_eagle_port(self): + return self.eagle_list + + def parsing_eagle_port(self): + name = self.get_platform() + if name is not None: + if name == INV_REDWOOD_PLATFORM: + self.eagle_list = [66,100] + elif name == INV_CYPRESS_PLATFORM: + self.eagle_list = [66,100] + elif name == INV_SEQUOIA_PLATFORM: + self.eagle_list = [66,100] + elif name == INV_MAPLE_PLATFORM: + self.eagle_list = [66,130] + else: + self.eagle_list = [] + + def get_sal_config_list(self): + return self.sal_config_list + + def show_sal_config_list(self): + for key,value in self.sal_config_list.iteritems(): + print "{0}---{1}".format(key, value) + + def initial_sal_config_list( self ): + content = self.run("config") + for line in content.split("\n"): + ConfigObject = re.search(r"portmap\_(?P\d+)\=(?P\d+)\:\d+",line) + if ConfigObject is not None: + if int(ConfigObject.group("bcm_id")) not in self.get_eagle_port(): + self.get_sal_config_list()[int(ConfigObject.group("bcm_id"))]={"lane": int(ConfigObject.group("lane_id")), "speed": None, "portname": None} + + def parsing_port_list(self): + content = self.run("ps") + count = 0 + for line in content.split("\n"): + PSObject = re.search(r"(?P(xe|ce)\d+)\(\s*(?P\d+)\).+\s+(?P\d+)G",line) + if PSObject is not None: + if int(PSObject.group("bcm_id")) not in self.get_eagle_port(): + if self.get_sal_config_list().has_key(int(PSObject.group("bcm_id"))): + self.get_sal_config_list()[int(PSObject.group("bcm_id"))]["portname"] = PSObject.group("port_name") + self.get_sal_config_list()[int(PSObject.group("bcm_id"))]["speed"] = int(PSObject.group("speed"))*1000 + self.port_to_bcm_mapping[count] = int(PSObject.group("bcm_id")) + count = count +1 + + + def execute_command(self, cmd): + self.cmd(cmd) + +class TransceiverUtil(SfpUtil): + + transceiver_port_mapping = dict() + + def get_transceiver_port_mapping(self): + return self.transceiver_port_mapping + + def show_transceiver_port_mapping(self): + for key,value in self.transceiver_port_mapping.iteritems(): + print "{0}---{1}".format(key, value) + + def get_bcm_port_name(self, index): + if self.transceiver_port_mapping.has_key(index) and bcm_obj.get_sal_config_list().has_key(self.transceiver_port_mapping[index]["bcm"]): + return bcm_obj.get_sal_config_list()[self.transceiver_port_mapping[index]["bcm"]]["portname"] + else: + return "" + + def get_port_to_i2c_mapping(self): + if self.port_to_i2c_mapping is None: + return dict() + else: + return self.port_to_i2c_mapping + + def show_port_to_i2c_mapping(self): + for key,value in self.port_to_i2c_mapping.iteritems(): + print "{0}---{1}".format(key, value) + + def get_eeprom_partNum(self, portNum): + tempdict = dict() + tempdict = self.get_eeprom_dict(portNum) + self.get_eeprom_partNum_from_parser_eeprom_dict(tempdict) + + def get_eeprom_dict_info(self, portNum): + return self.get_eeprom_dict(portNum) + + def get_eeprom_partNum_from_parser_eeprom_dict(self, tempdict ): + if tempdict is not None: + if tempdict["interface"]["data"].has_key("VendorPN"): + return tempdict["interface"]["data"]["VendorPN"] + elif tempdict["interface"]["data"].has_key("Vendor PN"): + return tempdict["interface"]["data"]["Vendor PN"] + else: + return None + else: + return None + + def get_transceiver_type(self, pn ): + if pn is not None: + if transceiver_type_dict.has_key(pn.upper()): + return transceiver_type_dict[pn.upper()] + else: + return None + + def set_transceiver_type( self, portNum, pn ): + type = self.get_transceiver_type( pn ) + if type is not None: + if bcm_obj.get_platform() == INV_SEQUOIA_PLATFORM or bcm_obj.get_platform() == INV_MAPLE_PLATFORM : + speed = bcm_obj.get_sal_config_list()[self.transceiver_port_mapping[portNum]["bcm"]]["speed"] + bcm_obj.execute_command( "port %s if=%s speed=%d" % ( self.get_bcm_port_name(portNum), type, speed ) ) + else: + bcm_obj.execute_command( "port %s if=%s" % ( self.get_bcm_port_name(portNum), type ) ) + print "Detecting port {0}({1}) need to change interface type {2} ({3})".format( self.get_bcm_port_name(portNum), portNum, type, self.get_transceiver_port_mapping()[portNum]["pn"]) + log_message("Detecting port {0} need to change interface type {1} ({2})".format(self.get_bcm_port_name(portNum), type, self.get_transceiver_port_mapping()[portNum]["pn"]) ) + + def initial_transceiver_port_mapping(self): + for index in self.get_port_to_i2c_mapping().keys(): + if self.transceiver_port_mapping.has_key(index) is False : + i2cValue = self.get_port_to_i2c_mapping()[index] + bcmValue = bcm_obj.get_port_to_bcm_mapping()[index] + self.transceiver_port_mapping[index]={"i2c": i2cValue, "bcm": bcmValue , "pn": None} + + def set_power_mode_for_QSFP(self): + for index in self.get_port_to_i2c_mapping().keys(): + if index >= self.qsfp_port_start and index <= self.qsfp_port_end : + self.set_low_power_mode(index, False) + else: + # To set tx_disable + self.set_tx_disable(index) + + def set_tx_disable(self, port_num): + if port_num >= self.qsfp_port_start and port_num <= self.qsfp_port_end : + pass + else: + try: + tx_file = open("/sys/class/swps/port"+str(port_num)+"/tx_disable", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = int(tx_file.readline().rstrip()) + + # always set 0 to tx_disable field + if reg_value == 1 : + reg_value = 0 + tx_file.write(hex(reg_value)) + tx_file.close() + + +def main(): + + global DEBUG + global transceiver_obj + global bcm_obj + + initalNotOK = True + retestCount = 0 + while initalNotOK : + try: + transceiver_obj = TransceiverUtil() + bcm_obj = BCMUtil() + initalNotOK = False + except Exception, e: + log_message("Exception. The warning is {0}, Retry again ({1})".format(str(e),retestCount) ) + retestCount = retestCount + 1 + time.sleep(5) + + log_message( "Object initialed successfully" ) + options, args = getopt.getopt(sys.argv[1:], 'hd', ['help', + 'debug' + ]) + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + else: + logging.info("no option") + + initalNotOK = True + while initalNotOK : + try : + # Before loop, You could execute specific command to initial chip + for cmd_index in initial_command : + bcm_obj.execute_command(cmd_index) + + # Initial the sal config list + bcm_obj.parsing_eagle_port() + bcm_obj.initial_sal_config_list() + # bcm_obj.show_sal_config_list() + bcm_obj.parsing_port_list() + #bcm_obj.show_port_to_bcm_mapping() + #bcm_obj.show_sal_config_list() + # transceiver_obj.show_port_to_i2c_mapping() + + # Initial the transceiver_obj + transceiver_obj.initial_transceiver_port_mapping() + # transceiver_obj.show_transceiver_port_mapping() + + initalNotOK = False + except Exception, e: + log_message("Exception. The warning is {0}".format(str(e)) ) + time.sleep(5) + + # Improve the power mode for QSFP ports + transceiver_obj.set_power_mode_for_QSFP() + + while 1 : + try: + if bcm_obj.get_platform() == INV_SEQUOIA_PLATFORM: + bcm_obj.parsing_port_list() + for index in transceiver_obj.get_port_to_i2c_mapping().keys(): + info = transceiver_obj.get_eeprom_dict_info(index) + value = transceiver_obj.get_eeprom_partNum_from_parser_eeprom_dict(info) + if transceiver_obj.get_transceiver_port_mapping().has_key(index) is not False and transceiver_obj.get_transceiver_port_mapping()[index]["pn"] <> value: + transceiver_obj.get_transceiver_port_mapping()[index]["pn"] = value + transceiver_obj.set_transceiver_type(index,value) + transceiver_obj.set_tx_disable(index) + #transceiver_obj.show_transceiver_port_mapping() + # transceiver_obj.show_transceiver_port_mapping() + except Exception, e: + log_message("Exception. The warning is {0}".format(str(e)) ) + time.sleep(1) + + syslog.closelog() + del transceiver_obj + del bcm_obj + +if __name__ == "__main__": + main() + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/Makefile new file mode 100644 index 000000000000..13fc34c230c5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/Makefile @@ -0,0 +1,7 @@ +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += inv_eeprom.o +obj-m += swps.o +obj-m += inv_pthread.o +swps-objs := inv_swps.o io_expander.o transceiver.o + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_cpld.c new file mode 100644 index 000000000000..683ffa0ff3ce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_cpld.c @@ -0,0 +1,415 @@ +/* + * 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 "I2CHostCommunication.h" + +#define USE_SMBUS 1 + +/* definition */ +#define CPLD_INFO_OFFSET 0x00 +#define CPLD_PSU_OFFSET 0x08 +#define CPLD_LED_OFFSET 0x0E +#define CPLD_LED_STATU_OFFSET 0x0D +#define CPLD_CTL_OFFSET 0x0C + + + +/* Each client has this additional data */ +struct cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +} + +static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t show_info(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[4]; + + memset(b, 0, 4); + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4); + mutex_unlock(&data->update_lock); + + if(status != 4) return sprintf(buf, "read cpld info fail\n"); + + status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/ + status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf); + status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf); + + return strlen(buf); +} + + +static ssize_t show_ctl(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[1]; + + mutex_lock(&data->update_lock); + + status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld ctl fail\n"); + + + status = sprintf (buf, "0x%X\n", b[0]); + + return strlen(buf); +} + +static ssize_t set_ctl(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1); + if(temp) byte |= (1<<0); + else byte &= ~(1<<0); + cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + + +static char* led_str[] = { + "OFF", //000 + "0.5 Hz", //001 + "1 Hz", //010 + "2 Hz", //011 + "NA", //100 + "NA", //101 + "NA", //110 + "ON", //111 +}; + +static ssize_t show_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET); + + byte = (byte >> shift) & 0x7; + + /* + 0: off + 1: 0.5hz + 2: 1 hz + 3: 2 hz + 4~6: not define + 7: on + */ + + status = sprintf (buf, "%d: %s\n", byte, led_str[byte]); + + return strlen(buf); +} + +static ssize_t set_led(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 16); + u8 byte; + int shift = (attr->index == 0)?3:0; + + temp &= 0x7; + //validate temp value: 0,1,2,3,7, TBD + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + byte &= ~(0x7<update_lock); + + return count; +} + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu0 | psu1 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 1)?0:3; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + + +static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0); +static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0); + +static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0); +static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1); + +static struct attribute *cpld_attributes[] = { + //info + &sensor_dev_attr_info.dev_attr.attr, + &sensor_dev_attr_ctl.dev_attr.attr, + + &sensor_dev_attr_grn_led.dev_attr.attr, + &sensor_dev_attr_red_led.dev_attr.attr, + + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + NULL +}; + +static const struct attribute_group cpld_group = { + .attrs = cpld_attributes, +}; + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int +cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + + printk("+%s\n", __func__); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld_group); + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpld_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpld_group); + i2c_set_clientdata(client, NULL); + kfree(data); + return 0; +} + +static const struct i2c_device_id cpld_ids[] = { + { "inv_cpld", 0, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, cpld_ids); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_cpld_init(void) +{ + return i2c_add_driver(&cpld_driver); +} + +static void __exit inv_cpld_exit(void) +{ + i2c_del_driver(&cpld_driver); +} + +MODULE_AUTHOR("eddie.lan "); +MODULE_DESCRIPTION("inv cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_cpld_init); +module_exit(inv_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_eeprom.c new file mode 100644 index 000000000000..3d13f3b04719 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_eeprom.c @@ -0,0 +1,181 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void inv_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } + +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + inv_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute inv_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = inv_eeprom_read, +}; + +static int inv_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int inv_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id inv_eeprom_id[] = { + { "inv_eeprom", 0 }, + { } +}; + +static struct i2c_driver inv_eeprom_driver = { + .driver = { + .name = "inv_eeprom", + }, + .probe = inv_eeprom_probe, + .remove = inv_eeprom_remove, + .id_table = inv_eeprom_id, +}; + +module_i2c_driver(inv_eeprom_driver); + +MODULE_AUTHOR("Inventec"); +MODULE_DESCRIPTION("Inventec D7054 Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.c new file mode 100644 index 000000000000..a8a9a3c3df79 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.c @@ -0,0 +1,280 @@ +/* + * 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 "io_expander.h" +#include "inv_mux.h" + +static struct mux_obj_s *mux_head_p = NULL; + + +/* ========== MUX object functions ========== + */ +int +_common_force_pull_gpio(int mem_addr, + int input, + int bit_offset){ + + unsigned int val = 0; + unsigned int targ = 0; + + /* Get current value */ + val = inl(mem_addr); + if (val == 0) { + SWPS_ERR("%s: inl:%d fail!\n", __func__, val); + return -1; + } + /* Count target value */ + switch (input) { + case 0: /* Pull Low */ + targ = (val & (~(1 << bit_offset))); + break; + case 1: /* Pull high */ + targ = (val | (1 << bit_offset)); + break; + default: + SWPS_ERR("%s: input state:%d incorrect!\n", + __func__, input); + return -1; + } + /* Setup gpio */ + outl(targ, mem_addr); + if (targ != inl(mem_addr)){ + SWPS_ERR("%s: outl:%d fail!\n", __func__, targ); + return -1; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + + +int +rangeley_force_pull_high(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +rangeley_force_pull_low(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +hedera_force_pull_high(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 1, 5); +} + + +int +hedera_force_pull_low(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 0, 5); +} + + +int +normal_gpio_pull_high(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 1); +} + + +int +normal_gpio_pull_low(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 0); +} + + +int +pca9548_reset_mux_all(struct mux_obj_s *self){ + /* [Note] Power-on reset (PCA9548A-NXP) + * When power is applied to VDD, an internal Power-On Reset (POR) + * holds the PCA9548A in a reset condition until VDD has reached + * VPOR. At this point, the reset condition is released and the + * PCA9548A register and I2C-bus state machine are initialized to + * their default states (all zeroes) causing all the channels to + * be deselected. Thereafter, VDD must be lowered below 0.2 V for + * at least 5 us in order to reset the device. + */ + if (self->_pull_low(self) < 0) { + SWPS_ERR("%s: _pull_low fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS); + if (self->_pull_high(self) < 0) { + SWPS_ERR("%s: _pull_high fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS); + return 0; +} + + +int +common_reset_mux_all(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +init_gpio_4_force(struct mux_obj_s *self){ + return 0; +} + + +int +init_gpio_4_normal(struct mux_obj_s *self){ + + int err = 0; + + if (!gpio_is_valid(self->gpio_num)) { + SWPS_ERR("%s: GIPO:%d isn't valid\n", __func__, self->gpio_num); + return -1; + } + err = gpio_request(self->gpio_num, MUX_GPIO_LABEL); + if (err < 0) { + SWPS_ERR("%s: gpio_request fail :%d :%d\n", + __func__, err, self->gpio_num); + return -1; + } + SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num); + return 0; +} + + +static int +_setup_muxctl_cb(struct mux_obj_s *self, + unsigned gpio){ + + char mod_dsc[32] = "ERR"; + + switch (gpio) { + case MUX_RST_GPIO_FORCE_RANGELEY: + self->gpio_num = gpio; + self->_pull_low = rangeley_force_pull_low; + self->_pull_high = rangeley_force_pull_high; + self->_init = init_gpio_4_force; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Rangeley force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_FORCE_HEDERA: + self->gpio_num = gpio; + self->_pull_low = hedera_force_pull_low; + self->_pull_high = hedera_force_pull_high; + self->_init = init_gpio_4_force; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Hedera force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_48_PAC9548: + case MUX_RST_GPIO_69_PAC9548: + case MUX_RST_GPIO_249_PCA9548: + case MUX_RST_GPIO_505_PCA9548: + self->gpio_num = gpio; + self->_pull_low = normal_gpio_pull_low; + self->_pull_high = normal_gpio_pull_high; + self->_init = init_gpio_4_normal; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Normal mode :%d", (int)gpio); + goto ok_setup_muxctl_cb; + + default: + break; + } + SWPS_ERR("%s: Unexpected GPIO:%d\n", __func__, gpio); + return -1; + +ok_setup_muxctl_cb: + SWPS_INFO("muxctl: %s.\n", mod_dsc); + return 0; +} + + +/* ========== MUX public functions ========== + */ +void +clean_mux_gpio(void){ + + if (!mux_head_p) { + SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__); + return; + } + if (gpio_is_valid(mux_head_p->gpio_num)) { + gpio_free(mux_head_p->gpio_num); + } + kfree(mux_head_p); + mux_head_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} + + +int +reset_mux_gpio(void){ + + if (!mux_head_p) { + SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__); + return -1; + } + if (mux_head_p->reset(mux_head_p) < 0){ + SWPS_ERR("%s: reset fail!\n", __func__); + return -1; + } + return 0; +} + + +int +init_mux_gpio(unsigned gpio){ + + /* Create MUX control object */ + if (mux_head_p) { + SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__); + clean_mux_gpio(); + } + /* Currently, it is using single muxctl architecture. + * In the future, it may use the multi-muxctl if HW add new features. + * (Ex: Port power-status control) + */ + mux_head_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL); + if (!mux_head_p) { + SWPS_ERR("%s: kzalloc fail!\n", __func__); + return -1; + } + /* Initial MUX controller */ + if (_setup_muxctl_cb(mux_head_p, gpio) < 0){ + SWPS_ERR("%s: _setup_muxctl_cb fail!\n", __func__); + return -1; + } + if (mux_head_p->_init(mux_head_p) < 0) { + SWPS_ERR("%s: init() fail\n", __func__); + goto err_init_mux_gpio; + } + /* Setup default value */ + if (mux_head_p->_pull_high(mux_head_p) < 0) { + SWPS_ERR("%s: setup default fail!\n", __func__); + goto err_init_mux_gpio; + } + return 0; + +err_init_mux_gpio: + clean_mux_gpio(); + return -1; +} + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.h new file mode 100644 index 000000000000..687a11b4e5be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.h @@ -0,0 +1,45 @@ +/* + * 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. + */ +#ifndef INV_MUX_H +#define INV_MUX_H + + +/* MUX basic information */ +#define MUX_GPIO_LABEL "SWPS_RST_MUX" + +/* MUX reset GPIO define */ +#define MUX_RST_GPIO_FORCE (30100) +#define MUX_RST_GPIO_FORCE_RANGELEY (30101) +#define MUX_RST_GPIO_FORCE_HEDERA (30102) +#define MUX_RST_GPIO_48_PAC9548 (48) +#define MUX_RST_GPIO_69_PAC9548 (69) +#define MUX_RST_GPIO_249_PCA9548 (249) +#define MUX_RST_GPIO_505_PCA9548 (505) + +/* MUX relate value define */ +#define MUX_RST_WAIT_MS (1) +#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD +#define MUX_RST_MEM_ADDR_HEDERA (0x548) + +struct mux_obj_s { + unsigned gpio_num; + int (*_pull_high)(struct mux_obj_s *self); + int (*_pull_low)(struct mux_obj_s *self); + int (*_init)(struct mux_obj_s *self); + int (*reset)(struct mux_obj_s *self); +}; + + +void clean_mux_gpio(void); +int reset_mux_gpio(void); +int init_mux_gpio(unsigned gpio); + + +#endif /* INV_MUX_H */ + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_platform.c new file mode 100644 index 000000000000..e6cb4c3d173d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_platform.c @@ -0,0 +1,243 @@ +/* + * 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 + +struct inv_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +static struct pca954x_platform_mode mux_modes_0[] = { + {.adap_id = 2,}, {.adap_id = 3,}, + {.adap_id = 4,}, {.adap_id = 5,}, + {.adap_id = 6,}, {.adap_id = 7,}, + {.adap_id = 8,}, {.adap_id = 9,}, +}; +static struct pca954x_platform_mode mux_modes_0_0[] = { + {.adap_id = 10,}, {.adap_id = 11,}, + {.adap_id = 12,}, {.adap_id = 13,}, + {.adap_id = 14,}, {.adap_id = 15,}, + {.adap_id = 16,}, {.adap_id = 17,}, +}; + +static struct pca954x_platform_mode mux_modes_0_1[] = { + {.adap_id = 18,}, {.adap_id = 19,}, + {.adap_id = 20,}, {.adap_id = 21,}, + {.adap_id = 22,}, {.adap_id = 23,}, + {.adap_id = 24,}, {.adap_id = 25,}, +}; + +static struct pca954x_platform_mode mux_modes_0_2[] = { + {.adap_id = 26,}, {.adap_id = 27,}, + {.adap_id = 28,}, {.adap_id = 29,}, + {.adap_id = 30,}, {.adap_id = 31,}, + {.adap_id = 32,}, {.adap_id = 33,}, +}; + +static struct pca954x_platform_mode mux_modes_0_3[] = { + {.adap_id = 34,}, {.adap_id = 35,}, + {.adap_id = 36,}, {.adap_id = 37,}, + {.adap_id = 38,}, {.adap_id = 39,}, + {.adap_id = 40,}, {.adap_id = 41,}, +}; + +static struct pca954x_platform_mode mux_modes_0_4[] = { + {.adap_id = 42,}, {.adap_id = 43,}, + {.adap_id = 44,}, {.adap_id = 45,}, + {.adap_id = 46,}, {.adap_id = 47,}, + {.adap_id = 48,}, {.adap_id = 49,}, +}; + +static struct pca954x_platform_mode mux_modes_0_5[] = { + {.adap_id = 50,}, {.adap_id = 51,}, + {.adap_id = 52,}, {.adap_id = 53,}, + {.adap_id = 54,}, {.adap_id = 55,}, + {.adap_id = 56,}, {.adap_id = 57,}, +}; + +static struct pca954x_platform_mode mux_modes_0_6[] = { + {.adap_id = 58,}, {.adap_id = 59,}, + {.adap_id = 60,}, {.adap_id = 61,}, + {.adap_id = 62,}, {.adap_id = 63,}, + {.adap_id = 64,}, {.adap_id = 65,}, +}; + +//no i2c device driver attach to mux 7 + + +static struct pca954x_platform_data mux_data_0 = { + .modes = mux_modes_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_0 = { + .modes = mux_modes_0_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_1 = { + .modes = mux_modes_0_1, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_2 = { + .modes = mux_modes_0_2, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_3 = { + .modes = mux_modes_0_3, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_4 = { + .modes = mux_modes_0_4, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_5 = { + .modes = mux_modes_0_5, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_6 = { + .modes = mux_modes_0_6, + .num_modes = 8, +}; + + +static struct i2c_board_info xlp_i2c_device_info0[] __initdata = { + {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc + {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld + {"pca9548", 0, 0x71, &mux_data_0, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info1[] __initdata = { + {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc + {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld +}; + +static struct i2c_board_info xlp_i2c_device_info2[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info3[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info4[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, +}; + +static struct i2c_board_info xlp_i2c_device_info5[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, +}; +static struct i2c_board_info xlp_i2c_device_info6[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0}, +}; +static struct i2c_board_info xlp_i2c_device_info7[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0}, +}; +static struct i2c_board_info xlp_i2c_device_info8[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0}, +}; + + +static struct inv_i2c_board_info i2cdev_list[] = { + {0, ARRAY_SIZE(xlp_i2c_device_info0), xlp_i2c_device_info0 }, //smbus 0 + + {2, ARRAY_SIZE(xlp_i2c_device_info2), xlp_i2c_device_info2 }, //mux 0 + {3, ARRAY_SIZE(xlp_i2c_device_info3), xlp_i2c_device_info3 }, //mux 1 + {4, ARRAY_SIZE(xlp_i2c_device_info4), xlp_i2c_device_info4 }, //mux 2 + {5, ARRAY_SIZE(xlp_i2c_device_info5), xlp_i2c_device_info5 }, //mux 3 + {6, ARRAY_SIZE(xlp_i2c_device_info6), xlp_i2c_device_info6 }, //mux 4 + {7, ARRAY_SIZE(xlp_i2c_device_info7), xlp_i2c_device_info7 }, //mux 5 + {8, ARRAY_SIZE(xlp_i2c_device_info8), xlp_i2c_device_info8 }, //mux 6 +}; + +///////////////////////////////////////////////////////////////////////////////////////// +static struct i2c_gpio_platform_data i2c_gpio_platdata = { + .scl_pin = 8, + .sda_pin = 9, + + .udelay = 5, //5:100kHz + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, + .scl_is_output_only = 0 +}; + +static struct platform_device magnolia_device_i2c_gpio = { + .name = "i2c-gpio", + .id = 0, // adapter number + .dev.platform_data = &i2c_gpio_platdata, +}; + +#define PLAT_MAX_I2C_CLIENTS 32 +static struct i2c_client *plat_i2c_client[PLAT_MAX_I2C_CLIENTS]; +static int num_i2c_clients = 0; +static int plat_i2c_client_add(struct i2c_client *e) +{ + if (num_i2c_clients >= PLAT_MAX_I2C_CLIENTS) + return -1; + + plat_i2c_client[num_i2c_clients] = e; + num_i2c_clients++; + return num_i2c_clients; +} + +static void plat_i2c_client_remove_all(void) +{ + int i; + for (i = num_i2c_clients-1; i >= 0; i--) + i2c_unregister_device(plat_i2c_client[i]); +} + +static int __init plat_magnolia_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j; + + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "I2CHostCommunication.h" + +#define USE_SMBUS 1 + +#define FAN_NUM 4 +#define PSU_NUM 2 + +struct __attribute__ ((__packed__)) psoc_psu_layout { + u16 psu1_iin; + u16 psu2_iin; + u16 psu1_iout; + u16 psu2_iout; + + u16 psu1_pin; + u16 psu2_pin; + u16 psu1_pout; + u16 psu2_pout; + + u16 psu1_vin; + u16 psu2_vin; + u16 psu1_vout; + u16 psu2_vout; + + u8 psu1_vendor[16]; + u8 psu2_vendor[16]; + u8 psu1_model[20]; + u8 psu2_model[20]; + u8 psu1_version[8]; + u8 psu2_version[8]; + u8 psu1_date[6]; + u8 psu2_date[6]; + u8 psu1_sn[20]; + u8 psu2_sn[20]; +}; + +struct __attribute__ ((__packed__)) psoc_layout { + u8 ctl; //offset: 0 + u16 switch_temp; //offset: 1 + u8 reserve0; //offset: 3 + + u8 fw_upgrade; //offset: 4 + + //i2c bridge + u8 i2c_st; //offset: 5 + u8 i2c_ctl; //offset: 6 + u8 i2c_addr; //offset: 7 + u8 i2c_data[0x20]; //offset: 8 + + //gpo + u8 led_ctl; //offset: 28 + + u8 gpio; //offset: 29 + + //pwm duty + u8 pwm[FAN_NUM]; //offset: 2a + u8 pwm_psu[PSU_NUM]; //offset: 2e + + //fan rpm + u16 fan[FAN_NUM*2]; //offset: 30 + + u8 reserve1[4]; //offset: 40 + + //gpi + u8 gpi_fan; //offset: 44 + + //psu state + u8 psu_state; //offset: 45 + + //temperature + u16 temp[5]; //offset: 46 + u16 temp_psu[PSU_NUM]; //offset: 50 + + //version + u8 version[2]; //offset: 54 + + u8 reserve2[4]; //offset: 56 + struct psoc_psu_layout psu_info; //offset: 5a +}; + +/* definition */ +/* definition */ +#define PSOC_OFF(m) offsetof(struct psoc_layout, m) +#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m) + +#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp) +#define PWM_OFFSET PSOC_OFF(pwm) +#define THERMAL_OFFSET PSOC_OFF(temp) +#define RPM_OFFSET PSOC_OFF(fan) +#define DIAG_FLAG_OFFSET PSOC_OFF(ctl) +#define FAN_LED_OFFSET PSOC_OFF(led_ctl) +#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan) +#define PSOC_PSU_OFFSET PSOC_OFF(psu_state) +#define VERSION_OFFSET PSOC_OFF(version) +#define PSU_INFO_OFFSET PSOC_OFF(psu_info) + +/* Each client has this additional data */ +struct psoc_data { + struct device *hwmon_dev; + struct mutex update_lock; + u32 diag; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t psoc_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +} + +static ssize_t psoc_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +} + +#if 0 +static u32 psoc_read32(struct i2c_client *client, u8 offset) +{ + u32 value = 0; + u8 buf[4]; + + if( psoc_i2c_read(client, buf, offset, 4) == 4) + value = (buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]); + + return value; +} +#endif + +static u16 psoc_read16(struct i2c_client *client, u8 offset) +{ + u16 value = 0; + u8 buf[2]; + + if(psoc_i2c_read(client, buf, offset, 2) == 2) + value = (buf[0]<<8 | buf[1]<<0); + + return value; +} + +static u8 psoc_read8(struct i2c_client *client, u8 offset) +{ + u8 value = 0; + u8 buf = 0; + + if(psoc_i2c_read(client, &buf, offset, 1) == 1) + value = buf; + + return value; +} + +//PSOC i2c bridge regsters +#define PSOC_I2C_STATUS 0x05 +#define PSOC_I2C_CNTRL 0x06 +#define PSOC_I2C_ADDR 0x07 +#define PSOC_I2C_DATA 0x08 + +//status bit definition +#define PSOC_I2C_START (1 << 0) +#define PSOC_PMB_SEL (1 << 7) + +//addr bits definition +#define PSOC_I2C_READ (1 << 0) + +//PMBUS registers definition +#define PMBUS_READ_VIN (0x88) +#define PMBUS_READ_IIN (0x89) +#define PMBUS_READ_VOUT (0x8B) +#define PMBUS_READ_IOUT (0x8C) +#define PMBUS_READ_POUT (0x96) +#define PMBUS_READ_PIN (0x97) + +#define PMBUS_MFR_ID (0x99) +#define PMBUS_MFR_MODEL (0x9A) +#define PMBUS_MFR_REVISION (0x9B) +#define PMBUS_MFR_DATE (0x9D) +#define PMBUS_MFR_SERIAL (0x9E) + +static int psoc_i2c_bridge_read(struct i2c_client *client, + unsigned char bus, + unsigned char chip, + char *addr, int alen, + unsigned char *data, int len ) +{ + unsigned char txdata[28], rxdata[28]; + int index, timeout; + + txdata[PSOC_I2C_STATUS] = 0; /* the status */ + txdata[PSOC_I2C_CNTRL] = ((alen & 3) << 5) | (len & 0x1f); /* the sizes */ + txdata[PSOC_I2C_ADDR] = (chip << 1) | PSOC_I2C_READ; /* read address */ + for(index = 0; index < alen; index++) + txdata[PSOC_I2C_DATA + index] = addr[index]; /* the chip address */ + for(; index < alen+len; index++) + txdata[PSOC_I2C_DATA + index] = 0; /* clear the chip data */ + + psoc_i2c_write(client, &txdata[PSOC_I2C_CNTRL], PSOC_I2C_CNTRL, 2 + alen + len); + + //delay a while ??? + //--------------------------------------------------------------------- + //start write + txdata[PSOC_I2C_STATUS] = PSOC_I2C_START | PSOC_PMB_SEL; /* the start bit for the PM bus */ + psoc_i2c_write(client, &txdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1); + + //delay a while + timeout = 40; //40*20==>800 ms + do { + psoc_i2c_read(client, &rxdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1); + + //check rxdata[5] error bit(1) and complete bit(0) ,TBD + if((rxdata[PSOC_I2C_STATUS] & 0x2) == 0x2) { + //printk("i2c bridge fail!!!\n"); + timeout = 0; + break; + } + if((rxdata[PSOC_I2C_STATUS] & PSOC_I2C_START) == 0) { + /* comand complete */ + psoc_i2c_read(client, &rxdata[PSOC_I2C_DATA+alen], PSOC_I2C_DATA+alen, len); + break; + } + + //delay + msleep(20); + } while(timeout--); + + if(timeout <= 0) { + return -1; + } + + //--------------------------------------------------------------------- + + for(index=0; index < len; index++) { + data[index] = rxdata[PSOC_I2C_DATA + alen + index]; + } + + return 0; +} + + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu1 | psu0 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu_st(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, &byte, PSOC_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t show_thermal(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index * 2 + THERMAL_OFFSET; + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + (s8)(status>>8) * 1000 ); +} + + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index + PWM_OFFSET; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t set_pwm(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index + PWM_OFFSET; + + u8 pwm = simple_strtol(buf, NULL, 10); + if(pwm > 255) pwm = 255; + + if(data->diag) { + mutex_lock(&data->update_lock); + psoc_i2c_write(client, &pwm, offset, 1); + mutex_unlock(&data->update_lock); + } + + return count; +} + + +static ssize_t show_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index*2 + RPM_OFFSET; + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u16 temp = 0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, (u8*)&temp, SWITCH_TMP_OFFSET, 2); + mutex_unlock(&data->update_lock); + + status = sprintf (buf, "%d\n", (s8)(temp>>8) * 1000 ); + + return strlen(buf); +} + +static ssize_t set_switch_tmp(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + + long temp = simple_strtol(buf, NULL, 10); + u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ; + + //printk("set_switch_tmp temp=%d, temp2=0x%x (%x,%x)\n", temp, temp2, ( ( (temp/1000) <<8 ) & 0xFF00 ), (( (temp%1000) / 10 ) & 0xFF)); + + mutex_lock(&data->update_lock); + psoc_i2c_write(client, (u8*)&temp2, SWITCH_TMP_OFFSET, 2); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_diag(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 diag_flag = 0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, (u8*)&diag_flag, DIAG_FLAG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + data->diag = (diag_flag & 0x80)?1:0; + status = sprintf (buf, "%d\n", data->diag); + + return strlen(buf); +} + +static ssize_t set_diag(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 value = 0; + u8 diag = simple_strtol(buf, NULL, 10); + + diag = diag?1:0; + data->diag = diag; + + mutex_lock(&data->update_lock); + psoc_i2c_read(client, (u8*)&value, DIAG_FLAG_OFFSET, 1); + if(diag) value |= (1<<7); + else value &= ~(1<<7); + psoc_i2c_write(client, (u8*)&value, DIAG_FLAG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, VERSION_OFFSET); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) ); +} + + +static ssize_t show_fan_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 bit = attr->index; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, FAN_LED_OFFSET); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + (status & (1<index; + u8 led_state = 0; + + u8 v = simple_strtol(buf, NULL, 10); + + if(data->diag) { + mutex_lock(&data->update_lock); + led_state = psoc_read8(client, FAN_LED_OFFSET); + if(v) led_state |= (1<update_lock); + } + + return count; +} + +static ssize_t show_value8(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "0x%02X\n", status ); +} + +static long pmbus_reg2data_linear(int data, int linear16) +{ + s16 exponent; + s32 mantissa; + long val; + + if (linear16) { /* LINEAR16 */ + exponent = -9; + mantissa = (u16) data; + } else { /* LINEAR11 */ + exponent = ((s16)data) >> 11; + exponent = ((s16)( data & 0xF800) ) >> 11; + mantissa = ((s32)((data & 0x7ff) << 5)) >> 5; + } + + //printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa); + val = mantissa; + + /* scale result to micro-units for power sensors */ + val = val * 1000L; + + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 reg = attr->index & 0xFF; + u8 len = ((attr->index & 0xFF00) >> 8); + u8 chip = (attr->index >> 16)? 0x59:0x58; + u8 bus = 1; + unsigned char value[2] = {0,0};; + + if (len == 2) + { + mutex_lock(&data->update_lock); + psoc_i2c_bridge_read(client, bus, chip, ®, 1, value, 2); + mutex_unlock(&data->update_lock); + + status = value[1]<<8 | value[0]; + //status1 = value[1]<<8 | value[0]; + + return sprintf(buf, "%ld\n", pmbus_reg2data_linear(status, (reg==PMBUS_READ_VOUT)?1:0) ); + } + else + { //len is not defined. + u8 tmpbuf[32]; + mutex_lock(&data->update_lock); + //length of block read + psoc_i2c_bridge_read(client, bus, chip, ®, 1, &len, 1); + //data included length + psoc_i2c_bridge_read(client, bus, chip, ®, 1, tmpbuf, len+1); + mutex_unlock(&data->update_lock); + + memcpy(buf, tmpbuf+1, len); + buf[len]='\n'; + + return len+1; + } +} + +static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = (attr->index & 0xFF) + PSU_INFO_OFFSET; + u8 len = (attr->index >> 8)& 0xFF; + u8 rxbuf[21] = {0}; + if (len == 2) + { + mutex_lock(&data->update_lock); + status = psoc_read16(client, offset); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, strstr(attr->dev_attr.attr.name, "vout")? 1:0 )); + } + else + { + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client,rxbuf,offset,len); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s \n",rxbuf); + } +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4); +static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5); +static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 6); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4); +static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu_st, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 1); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7); +static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8); +static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9); + +static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); +static SENSOR_DEVICE_ATTR(temp6_input, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); + +static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0); +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0); + +static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0); +static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1); +static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2); +static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3); +static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4); +static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5); +static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6); +static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7); + +static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET); + +static SENSOR_DEVICE_ATTR(psu1_vin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VIN); +static SENSOR_DEVICE_ATTR(psu1_vout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VOUT); +static SENSOR_DEVICE_ATTR(psu1_iin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IIN); +static SENSOR_DEVICE_ATTR(psu1_iout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IOUT); +static SENSOR_DEVICE_ATTR(psu1_pin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_PIN); +static SENSOR_DEVICE_ATTR(psu1_pout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_POUT); + +static SENSOR_DEVICE_ATTR(psu1_vendor, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_ID); +static SENSOR_DEVICE_ATTR(psu1_model, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu1_version, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu1_date, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_DATE); +static SENSOR_DEVICE_ATTR(psu1_sn, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_SERIAL); + +static SENSOR_DEVICE_ATTR(psu2_vin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VIN); +static SENSOR_DEVICE_ATTR(psu2_vout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VOUT); +static SENSOR_DEVICE_ATTR(psu2_iin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IIN); +static SENSOR_DEVICE_ATTR(psu2_iout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IOUT); +static SENSOR_DEVICE_ATTR(psu2_pin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_PIN); +static SENSOR_DEVICE_ATTR(psu2_pout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_POUT); + +static SENSOR_DEVICE_ATTR(psu2_vendor, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_ID); +static SENSOR_DEVICE_ATTR(psu2_model, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu2_version, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu2_date, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_DATE); +static SENSOR_DEVICE_ATTR(psu2_sn, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_SERIAL); + +static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_pout)); + + +static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_pout)); + +static SENSOR_DEVICE_ATTR(psoc_psu1_vendor, S_IRUGO, show_psu_psoc, 0, (0x10<<8)|PSOC_PSU_OFF(psu1_vendor)); +static SENSOR_DEVICE_ATTR(psoc_psu1_model, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu1_model)); +static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_psu_psoc, 0, (0x08<<8)|PSOC_PSU_OFF(psu1_version)); +static SENSOR_DEVICE_ATTR(psoc_psu1_date, S_IRUGO, show_psu_psoc, 0, (0x06<<8)|PSOC_PSU_OFF(psu1_date)); +static SENSOR_DEVICE_ATTR(psoc_psu1_sn, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu1_sn)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vendor, S_IRUGO, show_psu_psoc, 0, (0x10<<8)|PSOC_PSU_OFF(psu2_vendor)); +static SENSOR_DEVICE_ATTR(psoc_psu2_model, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu2_model)); +static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_psu_psoc, 0, (0x08<<8)|PSOC_PSU_OFF(psu2_version)); +static SENSOR_DEVICE_ATTR(psoc_psu2_date, S_IRUGO, show_psu_psoc, 0, (0x06<<8)|PSOC_PSU_OFF(psu2_date)); +static SENSOR_DEVICE_ATTR(psoc_psu2_sn, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu2_sn)); + +static struct attribute *psoc_attributes[] = { + //thermal + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + + &sensor_dev_attr_thermal_psu1.dev_attr.attr, + &sensor_dev_attr_thermal_psu2.dev_attr.attr, + + + //pwm + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm_psu1.dev_attr.attr, + &sensor_dev_attr_pwm_psu2.dev_attr.attr, + + //rpm + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, + + &sensor_dev_attr_rpm_psu1.dev_attr.attr, + &sensor_dev_attr_rpm_psu2.dev_attr.attr, + + //switch temperature + &sensor_dev_attr_switch_tmp.dev_attr.attr, + &sensor_dev_attr_temp6_input.dev_attr.attr, + //diag flag + &sensor_dev_attr_diag.dev_attr.attr, + + //version + &sensor_dev_attr_version.dev_attr.attr, + + //fan led + &sensor_dev_attr_fan_led_grn1.dev_attr.attr, + &sensor_dev_attr_fan_led_grn2.dev_attr.attr, + &sensor_dev_attr_fan_led_grn3.dev_attr.attr, + &sensor_dev_attr_fan_led_grn4.dev_attr.attr, + &sensor_dev_attr_fan_led_red1.dev_attr.attr, + &sensor_dev_attr_fan_led_red2.dev_attr.attr, + &sensor_dev_attr_fan_led_red3.dev_attr.attr, + &sensor_dev_attr_fan_led_red4.dev_attr.attr, + + //fan GPI + &sensor_dev_attr_fan_gpi.dev_attr.attr, + + //psu + &sensor_dev_attr_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psu2_pout.dev_attr.attr, + + &sensor_dev_attr_psu1_vendor.dev_attr.attr, + &sensor_dev_attr_psu1_model.dev_attr.attr, + &sensor_dev_attr_psu1_version.dev_attr.attr, + &sensor_dev_attr_psu1_date.dev_attr.attr, + &sensor_dev_attr_psu1_sn.dev_attr.attr, + &sensor_dev_attr_psu2_vendor.dev_attr.attr, + &sensor_dev_attr_psu2_model.dev_attr.attr, + &sensor_dev_attr_psu2_version.dev_attr.attr, + &sensor_dev_attr_psu2_date.dev_attr.attr, + &sensor_dev_attr_psu2_sn.dev_attr.attr, + + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + + //psu_psoc, new added on psoc 1.9 + &sensor_dev_attr_psoc_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pout.dev_attr.attr, + + //add info + &sensor_dev_attr_psoc_psu1_vendor.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_model.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_version.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_date.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_sn.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vendor.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_model.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_version.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_date.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_sn.dev_attr.attr, + NULL +}; + +static const struct attribute_group psoc_group = { + .attrs = psoc_attributes, +}; + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int +psoc_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct psoc_data *data; + int status; + + printk("+%s\n", __func__); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct psoc_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->diag = 0; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &psoc_group); + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &psoc_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int psoc_remove(struct i2c_client *client) +{ + struct psoc_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &psoc_group); + i2c_set_clientdata(client, NULL); + kfree(data); + return 0; +} + +static const struct i2c_device_id psoc_ids[] = { + { "inv_psoc", 0, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, psoc_ids); + +static struct i2c_driver psoc_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_psoc", + }, + .probe = psoc_probe, + .remove = psoc_remove, + .id_table = psoc_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_psoc_init(void) +{ + return i2c_add_driver(&psoc_driver); +} + +static void __exit inv_psoc_exit(void) +{ + i2c_del_driver(&psoc_driver); +} + +MODULE_AUTHOR("eddie.lan "); +MODULE_DESCRIPTION("inv psoc driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_psoc_init); +module_exit(inv_psoc_exit); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_pthread.c new file mode 100644 index 000000000000..7d3287a591c6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_pthread.c @@ -0,0 +1,1312 @@ +/* + * 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. + */ + +/***************************** + Magnolia platform +******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SHOW_ATTR_WARNING ("N/A") +#define SHOW_ATTR_NOTPRINT ("Not Available") +#define SHOW_ATTR_NOTSUPPORT ("Not Support") + +#define INV_HWMID_MAX (10) +#define INV_HWMID_INIT (-1) + +/*access userspace data to kernel space*/ +#define ACC_R (0) +#define ACC_W (1) + +#define TINY_BUF_SIZE (8) +#define MAX_PATH_SIZE (64) +#define MIN_ACC_SIZE (32) +#define MAX_ACC_SIZE (256) + +/* + * LED definitions + */ +#define STATUS_LED_MODE_AUTO 0 +#define STATUS_LED_MODE_DIAG 1 +#define STATUS_LED_MODE_MANU 2 + +#define STATUS_LED_GRN0 10 // 0 - 000: off +#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz +#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz +#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz +#define STATUS_LED_GRN7 17 // 7 - 111: on +#define STATUS_LED_RED0 20 // 0 - 000: off +#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz +#define STATUS_LED_RED2 22 // 2 - 010: 1 hz +#define STATUS_LED_RED3 23 // 3 - 011: 2 hz +#define STATUS_LED_RED7 27 // 7 - 111: on +#define STATUS_LED_INVALID 0 // Invalid + +ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2); +ssize_t status_led_grn(const char *freq); +ssize_t status_led_red(const char *freq); +ssize_t status_led_diag_mode_enable(void); +ssize_t status_led_diag_mode_disable(void); +int status_led_check_color(void); +int status_led_check_diag_mode(void); + +#if 1 +/* For timestamps in SYSFS_LOG */ +#define SYSFS_LOG printk +#else +//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args) +#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args) +#endif + +#define INV_PTHREAD_KERNEL_MODULE (1) +#define SWITCH_HEALTH_LED_CHANGE_VIA_GPIO (1) + +/* inventec_class *********************************/ +static struct kobject *status_kobj; +static struct kset *status_kset; + + +static struct mutex rw_lock; + +static int hwm_psoc = INV_HWMID_INIT; +static int hwm_cpld = INV_HWMID_INIT; + +int get_hwm_psoc(void) +{ + return hwm_psoc; +} + +int get_hwm_cpld(void) +{ + return hwm_cpld; +} + +static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + char *mark = NULL; + ssize_t vfs_ret = 0; + + if (mode == ACC_R) { + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_read(fp, buf, len, &pos); + + mark = strpbrk(buf, "\n"); + if (mark) + *mark = '\0'; + + filp_close(fp, NULL); + set_fs(fs); + } else if (mode == ACC_W) { + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_write(fp, buf, len, &pos); + filp_close(fp, NULL); + set_fs(fs); + } + + return vfs_ret; +} + +int inventec_strtol(const char *sbufp, char **endp, unsigned int base) +{ + char *endptr; + int value = simple_strtol(sbufp, &endptr, base); + if (value == 0 && sbufp == endptr) { + *endp = NULL; + return value; + } + *endp = (char*)1; + return value; +} + +int inventec_singlechar_to_int(const char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + else + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + else + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } + return -1; +} + +int inventec_store_input(char *inputp, int count) +{ + int i = 0; + while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) { + i++; + } + inputp[i] = '\0'; + return strlen(inputp); +} + +#if 0 +/* + * Time stamps for kernel log on yocto + */ +#include + +void SYSFS_LOG(char *fmt, ...) +{ + char buf[80], ts[32]; + va_list args; + int hlen; + + inventec_tmstmp(&ts[0]); + hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line + + va_start(args, fmt); + vsprintf(&buf[hlen-1], fmt, args); + va_end(args); + printk(KERN_WARNING "[p_thread] %s\n", buf); +} +#endif + +ssize_t +inventec_show_attr(char *buf_p, const char *invdevp) +{ + int inv_len = MAX_ACC_SIZE; /* INV driver return max length */ + char tmp_buf[MAX_ACC_SIZE]; + char *str_negative = "-", *mark = NULL; + + /* [Step2] Get data by uaccess */ + memset(tmp_buf, 0, sizeof(tmp_buf)); + mutex_lock(&rw_lock); + if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + mutex_unlock(&rw_lock); + + /* [Step3] Check return value + * - Ex: When transceiver not plugged + * => SWPS return error code "-202" + * => Pic8 need return "NA" (assume) + */ + if (strcspn(tmp_buf, str_negative) == 0) { + /* error case: "-202" */ + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + + /* OK case:*/ + mark = strpbrk(tmp_buf, "\n"); + if (mark) { *mark = '\0'; } + + return sprintf(buf_p, "%s\n", tmp_buf); +} + +ssize_t +inventec_store_attr(const char *buf_p, size_t count, const char *invdevp) +{ + ssize_t ret = 0; + + /* [Step2] Get data by uaccess */ + mutex_lock(&rw_lock); + if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return -EINVAL; + } + mutex_unlock(&rw_lock); + + /* OK case:*/ + return ret; +} + +int sysfs_detect_hwmon_index(void) +{ + char hwmon_buf[MAX_ACC_SIZE]; + char hwmon_path[MAX_PATH_SIZE]; + int hwid = 0; + + for (hwid = 0; + hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT); + hwid++) { + memset(hwmon_buf, 0, sizeof(hwmon_buf)); + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/device/name", hwid); + + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) { + hwm_cpld = hwid; + } + } + if (hwid >= INV_HWMID_MAX) { + printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return -1; + } + printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return 0; +} + +static int __init +inventec_class_init(void) +{ + mutex_init(&rw_lock); + +#ifdef INV_PTHREAD_KERNEL_MODULE + if (sysfs_detect_hwmon_index() < 0) { + return -1; + } +#endif + + printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__); + + return 0; +} + +static void __exit +inventec_class_exit(void) +{ + printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__); +} + +/* fan device *************************************/ +#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/device/fan_gpi" +#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/device/fan1_input" +#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/device/fan2_input" +#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/device/fan3_input" +#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/device/fan4_input" +#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/device/fan5_input" +#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/device/fan6_input" +#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/device/fan7_input" +#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/device/fan8_input" + +static char fan_dev_path_state[MAX_PATH_SIZE]; +static char fan_dev_path_fan1_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan2_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan3_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan4_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan5_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan6_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan7_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan8_input[MAX_PATH_SIZE]; + +void sysfs_fan_path_init(void) +{ + sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc()); + sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc()); +} + +#define FAN_STATE_NORMAL "normal" +#define FAN_STATE_FAULTY "faulty" +#define FAN_STATE_UNINSTALLED "uninstalled" +#define FAN_STATE_UNKNOW "unknown state" +#define FAN_STATE_INVALID "Invalid state value" +#define FAN_STATE_READ_ERROR "state read error" + +#define FAN_LOG_UNINSTALLED "removed" +#define FAN_LOG_NORMAL "inserted" + +//#define FAN_STATE_BIT_NORMAL 0 +#define FAN_STATE_BIT_FAULTY 0 +#define FAN_STATE_BIT_UNINSTALLED 1 +#define FAN_STATE_BIT_UNKNOW 2 +#define FAN_STATE_BIT_INVALID 3 +#define FAN_STATE_BIT_READ_ERROR 4 + +static struct fans_tbl_s { + char *fan_name; + char *fan_front; + char *fan_rear; + unsigned int fan_state; +} fans_tbl[] = { + {"fan1", fan_dev_path_fan1_input, + fan_dev_path_fan2_input, 0}, + {"fan2", fan_dev_path_fan3_input, + fan_dev_path_fan4_input, 0}, + {"fan3", fan_dev_path_fan5_input, + fan_dev_path_fan6_input, 0}, + {"fan4", fan_dev_path_fan7_input, + fan_dev_path_fan8_input, 0}, +}; +#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) ) + +#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0) + { + printk(KERN_ERR "[p_thread] All fans failed.\n"); + printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown); + } + cd_shutdown -= 1; + } + return ret; +} + +/* End of faninfo_device */ + +static int __init +fan_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_fan_path_init(); +#endif + return 0; +} + + +static void __exit +fan_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove fan module.\n"); +} + +/* psu device *************************************/ +static unsigned int psu_voltin = 0; +#define PSU_VOLTIN_ACDC (70000) + +/* + * normal/unpower/uninstall/fault are PSU states output from driver level + * checkpsu/error are defined by sysfs + */ +#define PSU_STATE_VAL_NORMAL (0) +#define PSU_STATE_VAL_UNPOWER (2) +#define PSU_STATE_VAL_FAULT (4) +#define PSU_STATE_VAL_UNINSTALL (7) +#define PSU_STATE_VAL_CHECKPSU (8) +#define PSU_STATE_VAL_ERROR (9) + +#define PSU_STATE_NORMAL ("0 : normal") +#define PSU_STATE_UNPOWER ("2 : unpowered") +#define PSU_STATE_FAULT ("4 : fault") +#define PSU_STATE_UNINSTALL ("7 : not installed") +#define PSU_STATE_CHECKPSU ("8 : check psu") +#define PSU_STATE_ERROR ("9 : state error") + +#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL)) +#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER)) +#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT)) +#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL)) +#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU)) + +typedef struct { + char *inv_dev_attrp; + char *inv_dev_pathp; +} psu_dev_t; + +typedef struct { + const char *psu_name; + int psu_major; + dev_t psu_devt; + struct device *psu_dev_p; + psu_dev_t *psu_dev_namep; + int psu_dev_total; + char *psu_inv_pathp; + void *psu_tracking; + char *psu_currentin; + char *psu_currentout; + char *psu_powerin; + char *psu_powerout; + char *psu_voltin; + char *psu_voltout; +} psu_dev_group_t; + +#define PSU_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s" + +static char psu_dev_path_state[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltin[MAX_PATH_SIZE]; +#if 0 +static char psu_dev_path_vendor[MAX_PATH_SIZE]; +static char psu_dev_path_version[MAX_PATH_SIZE]; +static char psu_dev_path_sn[MAX_PATH_SIZE]; +static char psu_dev_path_temperature[MAX_PATH_SIZE]; +static char psu_dev_path_fan_speed[MAX_PATH_SIZE]; +static char psu_dev_path_fan_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_fan_faulty[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_psu_rpm[MAX_PATH_SIZE]; +#endif + +void sysfs_psu_path_init(void) +{ + sprintf(&psu_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" ); + sprintf(&psu_dev_path_psu_voltin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#if 0 + sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#endif +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +#if 0 + { "vendor", psu_dev_path_vendor }, + { "version", psu_dev_path_version }, + { "sn", psu_dev_path_sn }, + { "temperature", psu_dev_path_temperature }, + { "fan_speed", psu_dev_path_fan_speed }, + { "fan_pwm", psu_dev_path_fan_pwm }, + { "fan_faulty", psu_dev_path_fan_faulty }, + { "psu_currentin", psu_dev_path_psu_currentin }, + { "psu_currentout", psu_dev_path_psu_currentout }, + { "psu_powerin", psu_dev_path_psu_powerin }, + { "psu_powerout", psu_dev_path_psu_powerout }, + { "psu_voltout", psu_dev_path_psu_voltout }, + { "psu_pwm", psu_dev_path_psu_pwm }, + { "psu_rpm", psu_dev_path_psu_rpm }, +#endif +}; +#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) ) + +static psu_dev_group_t psu_dev_group[] = { + { + .psu_name = "psu1", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, + { + .psu_name = "psu2", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, +}; +#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) ) + +static char psu_state[4][MIN_ACC_SIZE]; + +static struct psu_wire_tbl_s { + char *psu_attr; + char *psu_name; + char *psu_wire; + char *psu_state; +} psu_wire_tbl[] = { + { "state", "psu1", "psu0", psu_state[0] }, // Using cpld + { "state", "psu2", "psu1", psu_state[1] }, + { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] }, + { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] }, +}; +#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) ) + +static char * +psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp) +{ + int i; + + for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) { + if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 && + strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) { + if (psu_statepp) { + *psu_statepp = psu_wire_tbl[i].psu_state; + } + return psu_wire_tbl[i].psu_wire; + } + } + return NULL; +} + +int psu_check_state_normal(char *statep) +{ + if (strstr(statep, "normal")) { + return 1; + } + return 0; +} + +#define PSU_ATTR_VOLTIN ("psu_voltin") +#define PSU_ATTR_VOLTIN_LEN (10) + +/* Get PSU voltin for determon AC(110v) or DC(48v) */ +void psu_get_voltin(void) +{ + char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE]; + psu_dev_t *devnamep; + unsigned int voltin; + char *invwirep; + int i, j; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + //psu_dev_group[i].psu_name; + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(volt, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + continue; + } + else { + voltin = simple_strtol(&volt[0], NULL, 10); + printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin); + if (voltin > psu_voltin) { + psu_voltin = voltin; + } + } + } + } + } + + SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin); +} + +#define PSU_ATTR_STATE ("state") +#define PSU_ATTR_STATE_LEN (5) + +/* psus_control() by inv_thread */ +int psus_control(int log_only) +{ + char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE]; + psu_dev_t *devnamep = NULL; + char *invwirep = NULL; + char *psu_statep = NULL; + int i, j, flag = 0; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(state, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) { + strcpy(psu_statep, PSU_STATE_ERROR); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR); + } + flag = 1; + } + else + if (strstr(state, "normal")) { + //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + } + else + if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */ + //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + flag = 1; + } + else { /* DC PSUS */ + if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) { + strcpy(psu_statep, PSU_STATE_CHECKPSU); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU); + } + flag = 1; + } + } + } + } + + if (log_only) { + return 0; + } + + //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag); + if (flag == 1) { + status_led_grn("3"); + return 1; + } + return 0; +} + +/* End of psuinfo_device */ + +static int __init +psu_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_psu_path_init(); +#endif + return 0; +} + + +static void __exit +psu_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove psu module.\n"); +} + +/* led device *************************************/ +#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led" +#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led" + +#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1" +#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2" +#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3" +#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4" +#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1" +#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2" +#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3" +#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4" + +#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag" +#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl" + +static char status_led_grn_path[MAX_PATH_SIZE]; +static char status_led_red_path[MAX_PATH_SIZE]; +static char fan_led_grn1_path[MAX_PATH_SIZE]; +static char fan_led_grn2_path[MAX_PATH_SIZE]; +static char fan_led_grn3_path[MAX_PATH_SIZE]; +static char fan_led_grn4_path[MAX_PATH_SIZE]; +static char fan_led_red1_path[MAX_PATH_SIZE]; +static char fan_led_red2_path[MAX_PATH_SIZE]; +static char fan_led_red3_path[MAX_PATH_SIZE]; +static char fan_led_red4_path[MAX_PATH_SIZE]; +static char hwmon_device_diag_path[MAX_PATH_SIZE]; +static char hwmon_device_ctrl_path[MAX_PATH_SIZE]; + +void sysfs_led_path_init(void) +{ + sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld()); + sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld()); + sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc()); + sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc()); + sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc()); + sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc()); + sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld()); +} + +/* return 0/off 1/green 2/red */ +int +status_led_check_color(void) +{ + char tmpbuf[MIN_ACC_SIZE]; + int ret = STATUS_LED_INVALID; + + if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_GRN0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_GRN1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_GRN2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_GRN3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_GRN7; + } + return ret; + } + + if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_RED0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_RED1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_RED2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_RED3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_RED7; + } + return ret; + } + return ret; +} + +/* + * Store attr Section + */ +static DEFINE_MUTEX(diag_mutex); + +ssize_t status_led_diag_mode_enable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '0') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("1", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + mutex_unlock(&diag_mutex); + } + + return ret; +} + +ssize_t status_led_diag_mode_disable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '1') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("0", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + mutex_unlock(&diag_mutex); + } + return 1; +} + +ssize_t +status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2) +{ + ssize_t ret; + + ret = inventec_store_attr(tmp1, strlen(tmp1), path1); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(tmp2, strlen(tmp2), path2); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_red(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_grn_path[0]); + + if (ret < 0) { + return ret; + } + + ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]); + + if (ret < 0) { + return ret; + } + + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_grn(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +static int status_led_diag_mode = STATUS_LED_MODE_AUTO; + +int status_led_check_diag_mode(void) +{ + return status_led_diag_mode; +} + +/* End of ledinfo_device */ + +static int __init +led_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); +#endif + return 0; +} + + +static void __exit +led_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove led module.\n"); +} + +/* sensor device **********************************/ +#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp" + +static char sensor_dev_path_switch_temp[MAX_PATH_SIZE]; + +void sysfs_sensor_path_init(void) +{ + sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc()); +} + +void switch_temp_update(void) +{ + char buf[MIN_ACC_SIZE]; + ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp"); + if (count > 0) { + //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp); + inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp); + } +} + +/**************************************************/ +/* From system_device */ +static int inv_pthread_control = 1; + +int thread_control(void) +{ + return inv_pthread_control; +} + +void thread_control_set(int val) +{ + inv_pthread_control = val; +} +/* End system_device */ + +#define THREAD_SLEEP_MINS (3) +#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1) + +extern void psu_get_voltin(void); + +static struct task_struct *thread_st; +static int thread_data; + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO +void led_set_gpio_to_change_status_led(void) +{ + ssize_t ret = inventec_store_attr("253", 3, "/sys/class/gpio/export"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 253 to /sys/class/gpio/export failed\n"); + return; + } + + printk("[p_thread] Write 253 to /sys/class/gpio/export\n"); + + ret = inventec_store_attr("out", 3, "/sys/class/gpio/gpio253/direction"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio253/direction failed\n"); + return; + } + + //pull high and then low + ret = inventec_store_attr("1", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 1 to sys/class/gpio/gpio253/value failed\n"); + } + + //pull low + ret = inventec_store_attr("0", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 0 to sys/class/gpio/gpio253/value failed\n"); + } + + SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n"); +} +#endif + +// Function executed by kernel thread +static int thread_fn(void *unused) +{ + /* Delay for guarantee HW ready */ + ssleep(THREAD_DELAY_MINS); + +#ifndef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sysfs_fan_path_init(); + sysfs_psu_path_init(); +#endif + //sysfs_sensor_path_init(); + + /* Default status init */ + status_led_grn("7"); + + psu_get_voltin(); + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO + led_set_gpio_to_change_status_led(); +#endif + + while (1) + { + ssleep(THREAD_SLEEP_MINS); + + if (thread_control() == 0) { + printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__); + break; + } + + if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) { + /* status led in change color/freq mode, higher priority. Ignore fans sttaus */ + continue; + } + + //switch_temp_update(); + + if (fans_control() > 0) { + psus_control(1); + continue; + } + else + if (psus_control(0) > 0) { + continue; + } + + if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */ + status_led_grn("7"); + } + } + +#ifndef INV_PTHREAD_KERNEL_MODULE +err_inv_pthread_fn_1: +#endif + do_exit(0); + printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__); + return 0; +} + + +static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int fan_absence; + size_t count; + + fan_absence = fans_control(); + count += sprintf(&buf[count], "%d\n", fan_absence); + return count; +} + +static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static struct attribute status_att = { + .name = "fan_absence", + .mode = 0777, +}; + +static const struct sysfs_ops status_ops = { + .show = s_show, + .store = s_store, +}; + +static struct kobj_type status_ktype = { + .sysfs_ops = &status_ops, +}; + + +static int __init inv_pthread_init(void) +{ + int retval; + + status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL); + if(!status_kobj) + return PTR_ERR(status_kobj); + + status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj); + if(!status_kset) + return -1; + + status_kobj->kset = status_kset; + + retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan"); + if(retval) + return retval; + + retval = sysfs_create_file(status_kobj, &status_att); + + + inventec_class_init(); + fan_device_init(); + psu_device_init(); + led_device_init(); + + thread_control_set(1); + + printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__); + //Create the kernel thread with name 'inv_pthread' + thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread"); + if (thread_st) + printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n"); + else + printk(KERN_ERR "[p_thread] inv_pthread creation failed\n"); + + return retval; +} + +static void __exit inv_pthread_exit(void) +{ + thread_control_set(0); + /* Delay for guarantee thread exit */ + ssleep(THREAD_DELAY_MINS); + + fan_device_exit(); + psu_device_exit(); + led_device_exit(); + inventec_class_exit(); + + sysfs_remove_file(status_kobj, &status_att); + kset_unregister(status_kset); + kobject_del(status_kobj); + + printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n"); +} + +module_init(inv_pthread_init); +module_exit(inv_pthread_exit); + +MODULE_AUTHOR("Robert "); +MODULE_DESCRIPTION("Inventec Platform Management Thread"); +MODULE_VERSION("version 1.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.c new file mode 100644 index 000000000000..eff030df0a8a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.c @@ -0,0 +1,3027 @@ +/* + * 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 "inv_swps.h" + +static int ctl_major; +static int port_major; +static int ioexp_total; +static int port_total; +static int auto_config; +static int flag_i2c_reset; +static int flag_mod_state; +static unsigned gpio_rest_mux; +static struct class *swp_class_p = NULL; +static struct inv_platform_s *platform_p = NULL; +static struct inv_ioexp_layout_s *ioexp_layout = NULL; +static struct inv_port_layout_s *port_layout = NULL; + +static void swp_polling_worker(struct work_struct *work); +static DECLARE_DELAYED_WORK(swp_polling, swp_polling_worker); + +static int reset_i2c_topology(void); + + +static int +__swp_match(struct device *dev, +#ifdef SWPS_KERN_VER_AF_3_10 + + const void *data){ +#else + void *data){ +#endif + + char *name = (char *)data; + if (strcmp(dev_name(dev), name) == 0) + return 1; + return 0; +} + + +struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(swp_class_p, + NULL, + name, + __swp_match); + return dev; +} + + +static int +sscanf_2_int(const char *buf) { + + int result = -EBFONT; + char *hex_tag = "0x"; + + if (strcspn(buf, hex_tag) == 0) { + if (sscanf(buf,"%x",&result)) { + return result; + } + } else { + if (sscanf(buf,"%d",&result)) { + return result; + } + if(sscanf(buf,"-%d",&result)) { + return -result; + } + if (sscanf(buf,"%x",&result)) { + return result; + } + } + return -EBFONT; +} + + +static int +sscanf_2_binary(const char *buf) { + + int result = sscanf_2_int(buf); + + if (result < 0){ + return -EBFONT; + } + switch (result) { + case 0: + case 1: + return result; + default: + break; + } + return -EBFONT; +} + + +static int +_get_polling_period(void) { + + int retval = 0; + + if (SWP_POLLING_PERIOD == 0) { + return 0; + } + retval = ((SWP_POLLING_PERIOD * HZ) / 1000); + if (retval == 0) { + return 1; + } + return retval; +} + + +static struct transvr_obj_s * +_get_transvr_obj(char *dev_name) { + + struct device *dev_p = NULL; + struct transvr_obj_s *transvr_obj_p = NULL; + + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + return NULL; + } + transvr_obj_p = dev_get_drvdata(dev_p); + if (!transvr_obj_p){ + return NULL; + } + return transvr_obj_p; +} + + +static void +unlock_tobj_all(void) { + + struct transvr_obj_s *tobj_p; + char port_name[32]; + int port_id = 0; + int minor_curr = 0; + + for (minor_curr=0; minor_currauto_config = auto_config; + unlock_transvr_obj(tobj_p); + SWPS_DEBUG("%s: Set %s auto_config=%d\n", + __func__, tobj_p->swp_name, auto_config); + } + return retval; +} + + +/* ========== R/W Functions module control attribute ========== + */ +static ssize_t +show_attr_platform(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 32, "%s\n", platform_p->name); +} + + +static ssize_t +show_attr_version(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%s\n", SWP_VERSION); +} + + +static ssize_t +show_attr_status(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", flag_mod_state); +} + + +static ssize_t +show_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", auto_config); +} + + +static int +_check_reset_pwd(const char *buf_p, + size_t count) { + + int in_max = 64; + int in_len = (int)count; + char in_val[64] = "ERR"; + char *emsg = "ERR"; + + if (in_len >= in_max) { + emsg = "input too much"; + goto err_check_reset_pwd; + } + if (!sscanf(buf_p,"%s",in_val)) { + emsg = "format incorrect"; + goto err_check_reset_pwd; + } + if (strcmp(in_val, SWP_RESET_PWD) != 0) { + emsg = "password incorrect"; + goto err_check_reset_pwd; + } + return 0; + +err_check_reset_pwd: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + +static ssize_t +store_attr_reset_i2c(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + /* Polling mode */ + if (SWP_POLLING_ENABLE) { + SWPS_INFO("%s: reset I2C :polling\n", __func__); + flag_i2c_reset = 1; + return count; + } + /* Direct mode */ + SWPS_INFO("%s: reset I2C go. :direct\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset fail!\n", __func__); + return -EIO; + } + SWPS_INFO("%s: reset I2C ok. :direct\n", __func__); + return count; +} + + +static ssize_t +store_attr_reset_swps(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p; + char port_name[32] = "ERR"; + int port_id = 0; + int minor_curr = 0; + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + for (minor_curr=0; minor_currstate = STATE_TRANSVR_DISCONNECTED; + unlock_transvr_obj(tobj_p); + SWPS_INFO("%s: reset:%s\n", __func__, tobj_p->swp_name); + } + return count; +} + + +static ssize_t +store_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if (input_val < 0){ + return -EBFONT; + } + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + auto_config = input_val; + _update_auto_config_2_trnasvr(); + return count; +} + + +/* ========== Show functions: For transceiver attribute ========== + */ +static ssize_t +_show_transvr_hex_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + int result; + + lock_transvr_obj(tobj_p); + result = get_func(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 8, "%d\n", result); + } else { + len = snprintf(buf_p, 8, "0x%02x\n", result); + } + return len; +} + + +static ssize_t +_show_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = snprintf(buf_p, 16, "%d\n", get_func(tobj_p)); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +_show_transvr_str_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p, char* buf), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = get_func(tobj_p, buf_p); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +show_attr_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_id, + buf_p); +} + + +static ssize_t +show_attr_ext_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_ext_id, + buf_p); +} + + +static ssize_t +show_attr_connector(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_connector, + buf_p); +} + + +static ssize_t +show_attr_vendor_name(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_name, + buf_p); +} + + +static ssize_t +show_attr_vendor_pn(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_pn, + buf_p); +} + + +static ssize_t +show_attr_vendor_rev(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_rev, + buf_p); +} + + +static ssize_t +show_attr_vendor_sn(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_sn, + buf_p); +} + + +static ssize_t +show_attr_power_cls(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + size_t len; + int result; + struct transvr_obj_s *tobj_p; + + tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + lock_transvr_obj(tobj_p); + result = tobj_p->get_power_cls(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 16, "%d\n", result); + } else { + len = snprintf(buf_p, 16, "Power Class %d\n", result); + } + return len; +} + + +static ssize_t +show_attr_br(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_br, + buf_p); +} + + +static ssize_t +show_attr_len_sm(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_sm, + buf_p); +} + + +static ssize_t +show_attr_len_smf(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_smf, + buf_p); +} + + +static ssize_t +show_attr_len_om1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om1, + buf_p); +} + + +static ssize_t +show_attr_len_om2(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om2, + buf_p); +} + + +static ssize_t +show_attr_len_om3(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om3, + buf_p); +} + + +static ssize_t +show_attr_len_om4(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om4, + buf_p); +} + + +static ssize_t +show_attr_comp_rev(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_rev, + buf_p); +} + + +static ssize_t +show_attr_comp_eth(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_1, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10_40(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10_40, + buf_p); +} + + +static ssize_t +show_attr_comp_extend(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_extend, + buf_p); +} + + +static ssize_t +show_attr_rate_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_rate_id, + buf_p); +} + + +static ssize_t +show_attr_temperature(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_curr_temp, + buf_p); +} + + +static ssize_t +show_attr_voltage(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_curr_vol, + buf_p); +} + + +static ssize_t +show_attr_tx_bias(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_bias, + buf_p); +} + + +static ssize_t +show_attr_tx_power(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_power, + buf_p); +} + + +static ssize_t +show_attr_tx_eq(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_eq, + buf_p); +} + + +static ssize_t +show_attr_rx_power(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_power, + buf_p); +} + + +static ssize_t +show_attr_rx_am(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_am, + buf_p); +} + + +static ssize_t +show_attr_rx_em(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_em, + buf_p); +} + + +static ssize_t +show_attr_wavelength(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_wavelength, + buf_p); +} + + +static ssize_t +show_attr_extphy_offset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_extphy_offset, + buf_p); +} + + +static ssize_t +show_attr_extphy_reg(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_extphy_reg, + buf_p); +} + + +static ssize_t +show_attr_info(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_info, + buf_p); +} + + +static ssize_t +show_attr_if_type(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_type, + buf_p); +} + + +static ssize_t +show_attr_if_speed(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_speed, + buf_p); +} + + +static ssize_t +show_attr_if_lane(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_lane, + buf_p); +} + + +static ssize_t +show_attr_cdr(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_cdr, + buf_p); +} + + +static ssize_t +show_attr_soft_rs0(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs0, + buf_p); +} + + +static ssize_t +show_attr_soft_rs1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs1, + buf_p); +} + + +static ssize_t +show_attr_soft_rx_los(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_rx_los, + buf_p); +} + + +static ssize_t +show_attr_soft_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_disable, + buf_p); +} + + +static ssize_t +show_attr_soft_tx_fault(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_fault, + buf_p); +} + + +static ssize_t +show_attr_auto_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_auto_tx_disable, + buf_p); +} + + +/* ========== Store functions: transceiver (R/W) attribute ========== + */ +static ssize_t +_store_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_byte_hex_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if ((input < 0) || (input > 0xff)){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_binary_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_binary(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_cdr(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_byte_hex_attr(tobj_p, + tobj_p->set_cdr, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs0(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs1(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs1, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int check = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((check < 0) || (check > 0xf)){ + return -EBFONT; + } + return _store_transvr_byte_hex_attr(tobj_p, + tobj_p->set_soft_tx_disable, + buf_p, + count); +} + + +static ssize_t +store_attr_auto_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int err = -EPERM; + int input = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((input < 0) || (input > 0xf)){ + if (input != VAL_TRANSVR_FUNCTION_DISABLE) { + return -EBFONT; + } + } + lock_transvr_obj(tobj_p); + err = tobj_p->set_auto_tx_disable(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_tx_eq(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_tx_eq, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_am(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_rx_am, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_em(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_rx_em, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_offset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_extphy_offset, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_reg(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_extphy_reg, + buf_p, + count); +} + +/* ========== Show functions: For I/O Expander attribute ========== + */ +static ssize_t +_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset), + char *buf_p) { + size_t len; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR(" %s: data corruption! :%s\n", __func__, tobj_p->swp_name); + return -ENODATA; + } + mutex_lock(&ioexp_p->lock); + len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset)); + mutex_unlock(&ioexp_p->lock); + return len; +} + + +static ssize_t +show_attr_present(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_present, + buf_p); +} + + +static ssize_t +show_attr_tx_fault(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_fault, + buf_p); +} + + +static ssize_t +show_attr_rxlos(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_rxlos, + buf_p); +} + + +static ssize_t +show_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_disable, + buf_p); +} + + +static ssize_t +show_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_reset, + buf_p); +} + + +static ssize_t +show_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_lpmod, + buf_p); +} + + +static ssize_t +show_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_modsel, + buf_p); +} + + +static ssize_t +show_attr_hard_rs0(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_hard_rs0, + buf_p); +} + + +static ssize_t +show_attr_hard_rs1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_hard_rs1, + buf_p); +} + + +/* ========== Store functions: For I/O Expander (R/W) attribute ========== + */ +static ssize_t +_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*set_func)(struct ioexp_obj_s *ioexp_p, + int virt_offset, int input_val), + const char *buf_p, + size_t count) { + + int input, err; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR("%s: data corruption! :%s\n", + __func__, tobj_p->swp_name); + return -ENODATA; + } + input = sscanf_2_binary(buf_p); + if (input < 0) { + return -EBFONT; + } + mutex_lock(&ioexp_p->lock); + err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input); + mutex_unlock(&ioexp_p->lock); + if (err < 0){ + return err; + } + return count; +} + +static ssize_t +store_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_tx_disable, + buf_p, + count); +} + + +static ssize_t +store_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_reset, + buf_p, + count); +} + + +static ssize_t +store_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_lpmod, + buf_p, + count); +} + + +static ssize_t +store_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_modsel, + buf_p, + count); +} + + +static ssize_t +store_attr_hard_rs0(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_hard_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_hard_rs1(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_hard_rs1, + buf_p, + count); +} + + +/* ========== SWPS attribute: For module control ========== + */ +static DEVICE_ATTR(platform, S_IRUGO, show_attr_platform, NULL); +static DEVICE_ATTR(version, S_IRUGO, show_attr_version, NULL); +static DEVICE_ATTR(status, S_IRUGO, show_attr_status, NULL); +static DEVICE_ATTR(reset_i2c, S_IWUSR, NULL, store_attr_reset_i2c); +static DEVICE_ATTR(reset_swps, S_IWUSR, NULL, store_attr_reset_swps); +static DEVICE_ATTR(auto_config, S_IRUGO|S_IWUSR, show_attr_auto_config, store_attr_auto_config); + +/* ========== Transceiver attribute: from eeprom ========== + */ +static DEVICE_ATTR(id, S_IRUGO, show_attr_id, NULL); +static DEVICE_ATTR(ext_id, S_IRUGO, show_attr_ext_id, NULL); +static DEVICE_ATTR(connector, S_IRUGO, show_attr_connector, NULL); +static DEVICE_ATTR(vendor_name, S_IRUGO, show_attr_vendor_name, NULL); +static DEVICE_ATTR(vendor_pn, S_IRUGO, show_attr_vendor_pn, NULL); +static DEVICE_ATTR(vendor_rev, S_IRUGO, show_attr_vendor_rev, NULL); +static DEVICE_ATTR(vendor_sn, S_IRUGO, show_attr_vendor_sn, NULL); +static DEVICE_ATTR(power_cls, S_IRUGO, show_attr_power_cls, NULL); +static DEVICE_ATTR(br, S_IRUGO, show_attr_br, NULL); +static DEVICE_ATTR(len_sm, S_IRUGO, show_attr_len_sm, NULL); +static DEVICE_ATTR(len_smf, S_IRUGO, show_attr_len_smf, NULL); +static DEVICE_ATTR(len_om1, S_IRUGO, show_attr_len_om1, NULL); +static DEVICE_ATTR(len_om2, S_IRUGO, show_attr_len_om2, NULL); +static DEVICE_ATTR(len_om3, S_IRUGO, show_attr_len_om3, NULL); +static DEVICE_ATTR(len_om4, S_IRUGO, show_attr_len_om4, NULL); +static DEVICE_ATTR(comp_rev, S_IRUGO, show_attr_comp_rev, NULL); +static DEVICE_ATTR(comp_eth, S_IRUGO, show_attr_comp_eth, NULL); +static DEVICE_ATTR(comp_eth_10, S_IRUGO, show_attr_comp_eth_10, NULL); +static DEVICE_ATTR(comp_eth_10_40, S_IRUGO, show_attr_comp_eth_10_40, NULL); +static DEVICE_ATTR(comp_extend, S_IRUGO, show_attr_comp_extend, NULL); +static DEVICE_ATTR(rate_id, S_IRUGO, show_attr_rate_id, NULL); +static DEVICE_ATTR(temperature, S_IRUGO, show_attr_temperature, NULL); +static DEVICE_ATTR(voltage, S_IRUGO, show_attr_voltage, NULL); +static DEVICE_ATTR(tx_bias, S_IRUGO, show_attr_tx_bias, NULL); +static DEVICE_ATTR(tx_power, S_IRUGO, show_attr_tx_power, NULL); +static DEVICE_ATTR(rx_power, S_IRUGO, show_attr_rx_power, NULL); +static DEVICE_ATTR(info, S_IRUGO, show_attr_info, NULL); +static DEVICE_ATTR(if_type, S_IRUGO, show_attr_if_type, NULL); +static DEVICE_ATTR(if_speed, S_IRUGO, show_attr_if_speed, NULL); +static DEVICE_ATTR(if_lane, S_IRUGO, show_attr_if_lane, NULL); +static DEVICE_ATTR(soft_rx_los, S_IRUGO, show_attr_soft_rx_los, NULL); +static DEVICE_ATTR(soft_tx_fault, S_IRUGO, show_attr_soft_tx_fault, NULL); +static DEVICE_ATTR(wavelength, S_IRUGO, show_attr_wavelength, NULL); +static DEVICE_ATTR(tx_eq, S_IRUGO|S_IWUSR, show_attr_tx_eq, store_attr_tx_eq); +static DEVICE_ATTR(rx_am, S_IRUGO|S_IWUSR, show_attr_rx_am, store_attr_rx_am); +static DEVICE_ATTR(rx_em, S_IRUGO|S_IWUSR, show_attr_rx_em, store_attr_rx_em); +static DEVICE_ATTR(cdr, S_IRUGO|S_IWUSR, show_attr_cdr, store_attr_cdr); +static DEVICE_ATTR(soft_rs0, S_IRUGO|S_IWUSR, show_attr_soft_rs0, store_attr_soft_rs0); +static DEVICE_ATTR(soft_rs1, S_IRUGO|S_IWUSR, show_attr_soft_rs1, store_attr_soft_rs1); +static DEVICE_ATTR(soft_tx_disable, S_IRUGO|S_IWUSR, show_attr_soft_tx_disable, store_attr_soft_tx_disable); +static DEVICE_ATTR(auto_tx_disable, S_IRUGO|S_IWUSR, show_attr_auto_tx_disable, store_attr_auto_tx_disable); +static DEVICE_ATTR(extphy_offset, S_IRUGO|S_IWUSR, show_attr_extphy_offset, store_attr_extphy_offset); +static DEVICE_ATTR(extphy_reg, S_IRUGO|S_IWUSR, show_attr_extphy_reg, store_attr_extphy_reg); + +/* ========== IO Expander attribute: from expander ========== + */ +static DEVICE_ATTR(present, S_IRUGO, show_attr_present, NULL); +static DEVICE_ATTR(tx_fault, S_IRUGO, show_attr_tx_fault, NULL); +static DEVICE_ATTR(rxlos, S_IRUGO, show_attr_rxlos, NULL); +static DEVICE_ATTR(tx_disable, S_IRUGO|S_IWUSR, show_attr_tx_disable, store_attr_tx_disable); +static DEVICE_ATTR(reset, S_IRUGO|S_IWUSR, show_attr_reset, store_attr_reset); +static DEVICE_ATTR(lpmod, S_IRUGO|S_IWUSR, show_attr_lpmod, store_attr_lpmod); +static DEVICE_ATTR(modsel, S_IRUGO|S_IWUSR, show_attr_modsel, store_attr_modsel); +static DEVICE_ATTR(hard_rs0, S_IRUGO|S_IWUSR, show_attr_hard_rs0, store_attr_hard_rs0); +static DEVICE_ATTR(hard_rs1, S_IRUGO|S_IWUSR, show_attr_hard_rs1, store_attr_hard_rs1); + +/* ========== Functions for module handling ========== + */ +static void +clean_port_obj(void){ + + dev_t dev_num; + char dev_name[32]; + struct device *device_p; + struct transvr_obj_s *transvr_obj_p; + int minor_curr, port_id; + + for (minor_curr=0; minor_curri2c_client_p); + kfree(transvr_obj_p->vendor_name); + kfree(transvr_obj_p->vendor_pn); + kfree(transvr_obj_p->vendor_rev); + kfree(transvr_obj_p->vendor_sn); + kfree(transvr_obj_p->worker_p); + kfree(transvr_obj_p); + } + dev_num = MKDEV(port_major, minor_curr); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static void +clean_swps_common(void){ + + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(SWP_DEV_MODCTL); + if (device_p){ + dev_num = MKDEV(ctl_major, 1); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + cancel_delayed_work_sync(&swp_polling); + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static int +get_platform_type(void){ + + int i; + int pf_total = ARRAY_SIZE(platform_map); + char log_msg[64] = "ERROR"; + + platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL); + if (!platform_p){ + snprintf(log_msg, sizeof(log_msg), "kzalloc fail"); + goto err_get_platform_type_1; + } + memset(platform_p->name, 0, sizeof(platform_p->name)); + + switch (PLATFORM_SETTINGS) { + case PLATFORM_TYPE_AUTO: + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", dmi_get_system_info(DMI_BOARD_NAME)); + for (i=0; iname, platform_map[i].name) == 0) { + platform_p->id = platform_map[i].id; + snprintf(log_msg, sizeof(log_msg), + "Auto detect platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Auto detect fail! detect platform: %s", + platform_p->name); + goto err_get_platform_type_2; + + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + case PLATFORM_TYPE_REDWOOD: + case PLATFORM_TYPE_REDWOOD_FSL: + case PLATFORM_TYPE_HUDSON32I_GA: + case PLATFORM_TYPE_SPRUCE: + case PLATFORM_TYPE_CYPRESS_GA1: + case PLATFORM_TYPE_CYPRESS_GA2: + case PLATFORM_TYPE_CYPRESS_BAI: + case PLATFORM_TYPE_TAHOE: + case PLATFORM_TYPE_SEQUOIA_GA: + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + platform_p->id = PLATFORM_SETTINGS; + for (i=0; iname, (sizeof(platform_p->name) - 1), + "%s", platform_map[i].name); + snprintf(log_msg, sizeof(log_msg), + "User setup platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Internal error, can not map id:%d", + PLATFORM_SETTINGS); + goto err_get_platform_type_2; + + default: + break; + } + snprintf(log_msg, sizeof(log_msg), + "PLATFORM_SETTINGS:%d undefined", PLATFORM_SETTINGS); + goto err_get_platform_type_2; + +ok_get_platform_type_1: + SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return 0; + +err_get_platform_type_2: + kfree(platform_p); +err_get_platform_type_1: + SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return -1; +} + + +static int +get_layout_info(void){ + + switch (platform_p->id) { +#ifdef SWPS_MAGNOLIA + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + gpio_rest_mux = magnolia_gpio_rest_mux; + ioexp_layout = magnolia_ioexp_layout; + port_layout = magnolia_port_layout; + ioexp_total = ARRAY_SIZE(magnolia_ioexp_layout); + port_total = ARRAY_SIZE(magnolia_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD + case PLATFORM_TYPE_REDWOOD: + gpio_rest_mux = redwood_gpio_rest_mux; + ioexp_layout = redwood_ioexp_layout; + port_layout = redwood_port_layout; + ioexp_total = ARRAY_SIZE(redwood_ioexp_layout); + port_total = ARRAY_SIZE(redwood_port_layout); + break; +#endif +#ifdef SWPS_HUDSON32I_GA + case PLATFORM_TYPE_HUDSON32I_GA: + gpio_rest_mux = hudsin32iga_gpio_rest_mux; + ioexp_layout = hudson32iga_ioexp_layout; + port_layout = hudson32iga_port_layout; + ioexp_total = ARRAY_SIZE(hudson32iga_ioexp_layout); + port_total = ARRAY_SIZE(hudson32iga_port_layout); + break; +#endif +#ifdef SWPS_SPRUCE + case PLATFORM_TYPE_SPRUCE: + gpio_rest_mux = spruce_gpio_rest_mux; + ioexp_layout = spruce_ioexp_layout; + port_layout = spruce_port_layout; + ioexp_total = ARRAY_SIZE(spruce_ioexp_layout); + port_total = ARRAY_SIZE(spruce_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA1 + case PLATFORM_TYPE_CYPRESS_GA1: + gpio_rest_mux = cypress_ga1_gpio_rest_mux; + ioexp_layout = cypress_ga1_ioexp_layout; + port_layout = cypress_ga1_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga1_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga1_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA2 + case PLATFORM_TYPE_CYPRESS_GA2: + gpio_rest_mux = cypress_ga2_gpio_rest_mux; + ioexp_layout = cypress_ga2_ioexp_layout; + port_layout = cypress_ga2_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga2_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga2_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_BAI + case PLATFORM_TYPE_CYPRESS_BAI: + gpio_rest_mux = cypress_b_gpio_rest_mux; + ioexp_layout = cypress_b_ioexp_layout; + port_layout = cypress_b_port_layout; + ioexp_total = ARRAY_SIZE(cypress_b_ioexp_layout); + port_total = ARRAY_SIZE(cypress_b_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD_FSL + case PLATFORM_TYPE_REDWOOD_FSL: + gpio_rest_mux = redwood_fsl_gpio_rest_mux; + ioexp_layout = redwood_fsl_ioexp_layout; + port_layout = redwood_fsl_port_layout; + ioexp_total = ARRAY_SIZE(redwood_fsl_ioexp_layout); + port_total = ARRAY_SIZE(redwood_fsl_port_layout); + break; +#endif +#ifdef SWPS_TAHOE + case PLATFORM_TYPE_TAHOE: + gpio_rest_mux = tahoe_gpio_rest_mux; + ioexp_layout = tahoe_ioexp_layout; + port_layout = tahoe_port_layout; + ioexp_total = ARRAY_SIZE(tahoe_ioexp_layout); + port_total = ARRAY_SIZE(tahoe_port_layout); + break; +#endif +#ifdef SWPS_SEQUOIA + case PLATFORM_TYPE_SEQUOIA_GA: + gpio_rest_mux = sequoia_gpio_rest_mux; + ioexp_layout = sequoia_ioexp_layout; + port_layout = sequoia_port_layout; + ioexp_total = ARRAY_SIZE(sequoia_ioexp_layout); + port_total = ARRAY_SIZE(sequoia_port_layout); + break; +#endif +#ifdef SWPS_LAVENDER + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + gpio_rest_mux = lavender_gpio_rest_mux; + ioexp_layout = lavender_ioexp_layout; + port_layout = lavender_port_layout; + ioexp_total = ARRAY_SIZE(lavender_ioexp_layout); + port_total = ARRAY_SIZE(lavender_port_layout); + break; +#endif + default: + SWPS_ERR(" Invalid platform: %d (%s)\n", + platform_p->id, platform_p->name); + return -1; + } + SWPS_INFO("Start to initial platform: %d (%s)\n", + platform_p->id, platform_p->name); + return 0; +} + + +/* ========== Functions for objects operations ========== + */ +static int +__detect_issues_port(int minor_num) { + + struct transvr_obj_s *tobj_p; + int port_id = port_layout[minor_num].port_id; + char port_name[32] = "ERR"; + char *i2c_emsg = "detected bad transceiver/cable"; + + memset(port_name, 0, sizeof(port_name)); + snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id); + tobj_p = _get_transvr_obj(port_name); + if (!tobj_p) { + SWPS_INFO("%s: tobj_p is NULL :%d\n", __func__, minor_num); + return -1; + } + if (resync_channel_tier_2(tobj_p) < 0) { + if (check_channel_tier_1() < 0) { + alarm_msg_2_user(tobj_p, i2c_emsg); + return -2;; + } + } + return 0; +} + + +static int +_detect_issues_port(void) { + /* OK : retrun -1; + * Fail: return fail at which minor number (0~N) + */ + char *emsg = "ERR"; + int minor = 0; + int minor_2st = 1; + + /* Force moving the initial channel pointer + * Filter out case of fail at minor-0 port + */ + while (minor_2st < port_total) { + minor = minor_2st; + if (__detect_issues_port(minor_2st) < 0) { + emsg = "detect minor_2st fail"; + goto err_p_detect_issues_port; + } + minor_2st += 8; + } + /* Scan all port */ + for (minor=0; minor:%d\n", __func__, emsg, minor_err); + return -1; +} + + +static int +check_transvr_obj_one(char *dev_name){ + /* [Return] + * 0 : Doesn't need to take care + * -1 : Single error + * -2 : Critical error (I2C topology die) + * -9 : Internal error + */ + struct transvr_obj_s *tobj_p = NULL; + int retval = -9; + + tobj_p = _get_transvr_obj(dev_name); + if (!tobj_p) { + SWPS_ERR("%s: %s _get_transvr_obj fail\n", + __func__, dev_name); + return -9; + } + /* Check transceiver current status */ + lock_transvr_obj(tobj_p); + retval = tobj_p->check(tobj_p); + unlock_transvr_obj(tobj_p); + switch (retval) { + case 0: + case ERR_TRANSVR_UNPLUGGED: + case ERR_TRNASVR_BE_ISOLATED: + case ERR_TRANSVR_TASK_BUSY: + return 0; + + case ERR_TRANSVR_I2C_CRASH: + default: + break; + } + /* Identify abnormal case */ + if (check_channel_tier_1() < 0) { + SWPS_DEBUG("%s: %s critical error :%d\n", + __func__, dev_name, retval); + return -2; + } + SWPS_DEBUG("%s: %s single error :%d\n", + __func__, dev_name, retval); + return -1; +} + + +static int +check_transvr_objs(void){ + + char dev_name[32]; + int port_id, err_code; + int minor_curr = 0; + + for (minor_curr=0; minor_curr:%d\n", + __func__, dev_name, err_code); + break; + } + } + return 0; + +err_check_transvr_objs: + SWPS_ERR("%s: %s reset_i2c_topology fail.\n", + __func__, dev_name); + return -1; +} + + +static void +swp_polling_worker(struct work_struct *work){ + + /* Reset I2C */ + if (flag_i2c_reset) { + goto polling_reset_i2c; + } + /* Check IOEXP */ + if (check_ioexp_objs() < 0) { + goto polling_reset_i2c; + } + /* Check transceiver */ + if (check_transvr_objs() < 0) { + SWPS_DEBUG("%s: check_transvr_objs fail.\n", __func__); + flag_i2c_reset = 1; + } + goto polling_schedule_round; + +polling_reset_i2c: + SWPS_DEBUG("%s: reset_i2c_topology start.\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset i2c fail!\n", __func__); + flag_i2c_reset = 1; + } else { + SWPS_DEBUG("%s: reset_i2c_topology OK.\n", __func__); + flag_i2c_reset = 0; + } +polling_schedule_round: + schedule_delayed_work(&swp_polling, _get_polling_period()); +} + + +/* ========== Functions for register something ========== + */ +static int +register_transvr_common_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_id) < 0) { + err_attr = "dev_attr_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_ext_id) < 0) { + err_attr = "dev_attr_ext_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_connector) < 0) { + err_attr = "dev_attr_connector"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_name) < 0) { + err_attr = "dev_attr_vendor_name"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_pn) < 0) { + err_attr = "dev_attr_vendor_pn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_rev) < 0) { + err_attr = "dev_attr_vendor_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_sn) < 0) { + err_attr = "dev_attr_vendor_sn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_br) < 0) { + err_attr = "dev_attr_br"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_smf) < 0) { + err_attr = "dev_attr_len_smf"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om1) < 0) { + err_attr = "dev_attr_len_om1"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om2) < 0) { + err_attr = "dev_attr_len_om2"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om3) < 0) { + err_attr = "dev_attr_len_om3"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om4) < 0) { + err_attr = "dev_attr_len_om4"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_extend) < 0) { + err_attr = "dev_attr_comp_extend"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth) < 0) { + err_attr = "dev_attr_comp_eth"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_rev) < 0) { + err_attr = "dev_attr_comp_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_info) < 0) { + err_attr = "dev_attr_info"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_type) < 0) { + err_attr = "dev_attr_if_type"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_speed) < 0) { + err_attr = "dev_attr_if_speed"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_lane) < 0) { + err_attr = "dev_attr_if_lane"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_temperature) < 0) { + err_attr = "dev_attr_temperature"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_voltage) < 0) { + err_attr = "dev_attr_voltage"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_bias) < 0) { + err_attr = "dev_attr_tx_bias"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_power) < 0) { + err_attr = "dev_attr_tx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_power) < 0) { + err_attr = "dev_attr_rx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_eq) < 0) { + err_attr = "dev_attr_tx_eq"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_em) < 0) { + err_attr = "dev_attr_rx_em"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_wavelength) < 0) { + err_attr = "dev_attr_wavelength"; + goto err_transvr_comm_attr; + } + return 0; + +err_transvr_comm_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + +static int +register_transvr_sfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10) < 0) { + err_attr = "dev_attr_comp_eth_10"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_len_sm) < 0) { + err_attr = "dev_attr_len_sm"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_rate_id) < 0) { + err_attr = "dev_attr_rate_id"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs0) < 0) { + err_attr = "dev_attr_soft_rs0"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs1) < 0) { + err_attr = "dev_attr_soft_rs1"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_offset) < 0) { + err_attr = "dev_attr_extphy_offset"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_reg) < 0) { + err_attr = "dev_attr_extphy_reg"; + goto err_transvr_sfp_attr; + } + return 0; + +err_transvr_sfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10_40) < 0) { + err_attr = "dev_attr_comp_eth_10_40"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_power_cls) < 0) { + err_attr = "dev_attr_power_cls"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rx_los) < 0) { + err_attr = "soft_rx_los"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_disable) < 0) { + err_attr = "soft_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_auto_tx_disable) < 0) { + err_attr = "auto_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_fault) < 0) { + err_attr = "soft_tx_fault"; + goto err_transvr_qsfp_attr; + } + return 0; + +err_transvr_qsfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp28_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_qsfp_attr(device_p) < 0){ + err_attr = "register_transvr_qsfp_attr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_cdr) < 0) { + err_attr = "dev_attr_cdr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_rx_am) < 0) { + err_attr = "dev_attr_rx_am"; + goto err_transvr_qsfp28_attr; + } + return 0; + +err_transvr_qsfp28_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + switch (transvr_obj->layout){ + case TRANSVR_TYPE_SFP: + if (register_transvr_sfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + if (register_transvr_qsfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP_28: + if (register_transvr_qsfp28_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + default: + goto err_reg_tvr_attr; + } + return 0; + +err_reg_tvr_attr: + SWPS_ERR("%s: fail! type=%d \n", __func__, transvr_obj->type); + return -1; +} + + +static int +register_ioexp_attr_sfp_1(struct device *device_p){ + /* Support machine type: + * - SFP : Magnolia + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_fault) < 0) { + err_attr = "dev_attr_tx_fault"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_rxlos) < 0) { + err_attr = "dev_attr_rxlos"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_disable) < 0) { + err_attr = "dev_attr_tx_disable"; + goto err_ioexp_sfp1_attr; + } + return 0; + +err_ioexp_sfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_ioexp_attr_sfp_2(struct device *device_p){ + /* Support machine type: + * - SFP28 : Cypress + */ + char *err_attr = NULL; + + if (register_ioexp_attr_sfp_1(device_p) < 0){ + goto err_ioexp_sfp2_attr; + } + if (device_create_file(device_p, &dev_attr_hard_rs0) < 0) { + err_attr = "dev_attr_hard_rs0"; + goto err_ioexp_sfp2_attr; + } + if (device_create_file(device_p, &dev_attr_hard_rs1) < 0) { + err_attr = "dev_attr_hard_rs1"; + goto err_ioexp_sfp2_attr; + } + return 0; + +err_ioexp_sfp2_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_ioexp_attr_qsfp_1(struct device *device_p){ + /* Support machine type: + * - QSFP : Magnolia, Redwood, Hudson32i + * - QSFP+ : Magnolia, Redwood, Hudson32i + * - QSFP28: Redwood + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_reset) < 0) { + err_attr = "dev_attr_reset"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_lpmod) < 0) { + err_attr = "dev_attr_lpmod"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_modsel) < 0) { + err_attr = "dev_attr_modsel"; + goto err_ioexp_qsfp1_attr; + } + return 0; + +err_ioexp_qsfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_modctl_attr(struct device *device_p){ + + char *err_msg = NULL; + + if (device_create_file(device_p, &dev_attr_platform) < 0) { + err_msg = "dev_attr_platform"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_version) < 0) { + err_msg = "dev_attr_version"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_status) < 0) { + err_msg = "dev_attr_status"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_i2c) < 0) { + err_msg = "dev_attr_reset_i2c"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_swps) < 0) { + err_msg = "dev_attr_reset_swps"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_auto_config) < 0) { + err_msg = "dev_attr_auto_config"; + goto err_reg_modctl_attr; + } + return 0; + +err_reg_modctl_attr: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int +register_ioexp_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + char *err_msg = "ERR"; + + switch (transvr_obj->ioexp_obj_p->ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + if (register_ioexp_attr_sfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + case IOEXP_TYPE_CYPRESS_NABC: + if (register_ioexp_attr_sfp_2(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_2 fail"; + goto err_reg_ioexp_attr; + } + break; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + if (register_ioexp_attr_qsfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_qsfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + + default: + err_msg = "Unknow type"; + goto err_reg_ioexp_attr; + } + return 0; + +err_reg_ioexp_attr: + SWPS_ERR("%s: %s :%d \n", + __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type); + return -1; +} + + +static int +register_modctl_device(void) { + + struct device *device_p = NULL; + int minor_comm = 0; /* Default minor number for common device */ + dev_t dev_num = MKDEV(ctl_major, minor_comm); + char *err_msg = "ERROR"; + + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + NULL, /* void *private_data */ + SWP_DEV_MODCTL); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_modctl_device_1; + } + if (register_modctl_attr(device_p) < 0) { + err_msg = "register_modctl_attr fail"; + goto err_register_modctl_device_2; + } + return 0; + +err_register_modctl_device_2: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_register_modctl_device_1: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int +register_port_device(char *dev_name, + dev_t dev_num, + struct transvr_obj_s *transvr_obj){ + + struct device *device_p = NULL; + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + transvr_obj, /* void *private_data */ + dev_name); /* const char *fmt */ + if (IS_ERR(device_p)){ + goto err_regswp_create_dev; + } + if (register_transvr_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + if (register_ioexp_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + return 0; + +err_regswp_reg_attr: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_regswp_create_dev: + SWPS_ERR("%s fail! :%s\n", __func__, dev_name); + return -1; +} + + +static int +register_swp_module(void){ + + dev_t ctl_devt = 0; + dev_t port_devt = 0; + int dev_total = port_total + 1; /* char_dev for module control */ + + /* Register device number */ + if (alloc_chrdev_region(&ctl_devt, 0, 1, SWP_DEV_MODCTL) < 0){ + SWPS_WARN("Allocate CTL MAJOR failure! \n"); + goto err_register_swp_module_1; + } + if (alloc_chrdev_region(&port_devt, 0, dev_total, SWP_CLS_NAME) < 0){ + SWPS_WARN("Allocate PORT MAJOR failure! \n"); + goto err_register_swp_module_2; + } + ctl_major = MAJOR(ctl_devt); + port_major = MAJOR(port_devt); + + /* Create class object */ + swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME); + if (IS_ERR(swp_class_p)) { + SWPS_ERR("Create class failure! \n"); + goto err_register_swp_module_3; + } + return 0; + +err_register_swp_module_3: + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_register_swp_module_2: + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); +err_register_swp_module_1: + return -1; +} + + +/* ========== Module initial relate ========== + */ +static int +create_ioexp_objs(void) { + + int i, run_mod; + + /* Clean IOEXP object */ + clean_ioexp_objs(); + /* Get running mode */ + run_mod = IOEXP_MODE_DIRECT; + if (SWP_POLLING_ENABLE){ + run_mod = IOEXP_MODE_POLLING; + } + /* Create IOEXP object */ + for(i=0; i devlen_max) { + snprintf(err_msg, sizeof(err_msg), + "SWP_DEV_PORT too long!"); + goto err_initport_create_tranobj; + } + memset(dev_name, 0, sizeof(dev_name)); + snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id); + /* Create transceiver object */ + ioexp_obj_p = get_ioexp_obj(ioexp_id); + if (!ioexp_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "IOEXP object:%d not exist", ioexp_id); + goto err_initport_create_tranobj; + } + transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p, + ioexp_virt_offset, transvr_type, + chipset_type, run_mod); + if (!transvr_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "Create transceiver object fail :%s", dev_name); + goto err_initport_create_tranobj; + } + /* Setup Lane_ID mapping */ + i = ARRAY_SIZE(port_layout[minor_curr].lane_id); + j = ARRAY_SIZE(transvr_obj_p->lane_id); + if (i != j) { + snprintf(err_msg, sizeof(err_msg), + "Lane_id size inconsistent %d/%d", i, j); + goto err_initport_reg_device; + } + memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int)); + /* Create and register device object */ + if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){ + snprintf(err_msg, sizeof(err_msg), + "register_port_device fail"); + goto err_initport_reg_device; + } + /* Setup device_ptr of transvr_obj */ + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + snprintf(err_msg, sizeof(err_msg), + "get_swpdev_by_name fail"); + goto err_initport_reg_device; + } + transvr_obj_p->transvr_dev_p = dev_p; + /* Success */ + ok_count++; + } + SWPS_INFO("%s: initialed %d port-dev",__func__, ok_count); + return 0; + +err_initport_reg_device: + kfree(transvr_obj_p); +err_initport_create_tranobj: + clean_port_obj(); + SWPS_ERR("%s: %s", __func__, err_msg); + SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n", + port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod); + return -1; +} + + +static int +init_dev_topology(void){ + + int err; + char *emsg = "ERR"; + flag_mod_state = SWP_STATE_NORMAL; + + err = init_ioexp_objs(); + switch(err){ + case 0: /* Normal */ + SWPS_DEBUG("%s: normal case\n", __func__); + break; + + case -1: /* topology error */ + SWPS_DEBUG("%s: detect tier-1 topology initial failure :%d\n", + __func__, err); + /* Reset and isolate */ + err = reset_i2c_topology(); + if (err < 0) { + emsg = "reset i2c topology fail"; + goto err_init_dev_topology; + } + /* Re-initial again */ + err = init_ioexp_objs(); + if (err < 0) { + emsg = "re-init ioexp objects fail"; + goto err_init_dev_topology; + } + break; + + case -2: /* Internal error */ + SWPS_DEBUG("%s: internal error case\n", __func__); + err = -2; + emsg = "internal error"; + goto err_init_dev_topology; + + default: + SWPS_DEBUG("%s: undefined error case\n", __func__); + emsg = "undefined error case"; + goto err_init_dev_topology; + } + SWPS_DEBUG("%s: initial I2C topology success\n", __func__); + return 0; + +err_init_dev_topology: + SWPS_ERR("%s: %s :%d\n", __func__, emsg, err); + return -1; +} + + +static int +init_polling_task(void){ + + if (SWP_POLLING_ENABLE){ + schedule_delayed_work(&swp_polling, _get_polling_period()); + } + return 0; +} + + +static int +init_swps_common(void){ + + char *err_msg = "ERR"; + + auto_config = 0; + if ((SWP_AUTOCONFIG_ENABLE) && (SWP_POLLING_ENABLE)){ + auto_config = 1; + } + if (register_modctl_device() < 0) { + err_msg = "register_modctl_device fail"; + goto err_init_swps_common_1; + } + if (_update_auto_config_2_trnasvr() < 0) { + err_msg = "_update_auto_config_2_trnasvr fail"; + goto err_init_swps_common_1; + } + if (init_polling_task() < 0){ + err_msg = "init_polling_task fail"; + goto err_init_swps_common_1; + } + return 0; + +err_init_swps_common_1: + clean_swps_common(); + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int __init +swp_module_init(void){ + + if (get_platform_type() < 0){ + goto err_init_out; + } + if (get_layout_info() < 0){ + goto err_init_out; + } + if (register_swp_module() < 0){ + goto err_init_out; + } + if (create_ioexp_objs() < 0){ + goto err_init_ioexp; + } + if (create_port_objs() < 0){ + goto err_init_portobj; + } + if (init_mux_gpio(gpio_rest_mux) < 0){ + goto err_init_mux; + } + if (init_dev_topology() < 0){ + goto err_init_topology; + } + if (init_swps_common() < 0){ + goto err_init_topology; + } + SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION); + return 0; + + +err_init_topology: + clean_mux_gpio(); +err_init_mux: + clean_port_obj(); +err_init_portobj: + clean_ioexp_objs(); +err_init_ioexp: + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_init_out: + SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION); + return -1; +} + + +static void __exit +swp_module_exit(void){ + + clean_swps_common(); + clean_port_obj(); + clean_ioexp_objs(); + clean_mux_gpio(); + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); + SWPS_INFO("Remove Inventec switch-port module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(SWP_AUTHOR); +MODULE_DESCRIPTION(SWP_DESC); +MODULE_VERSION(SWP_VERSION); +MODULE_LICENSE(SWP_LICENSE); + +module_init(swp_module_init); +module_exit(swp_module_exit); + + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.h new file mode 100644 index 000000000000..8e1451d6149a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.h @@ -0,0 +1,1033 @@ +/* + * 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. + */ + +#ifndef INV_SWPS_H +#define INV_SWPS_H + +#include "transceiver.h" +#include "io_expander.h" +#include "inv_mux.h" + +/* Module settings */ +#define SWP_CLS_NAME "swps" +#define SWP_DEV_PORT "port" +#define SWP_DEV_MODCTL "module" +#define SWP_RESET_PWD "inventec" +#define SWP_POLLING_PERIOD (300) /* msec */ +#define SWP_POLLING_ENABLE (1) +#define SWP_AUTOCONFIG_ENABLE (1) + +/* Module information */ +#define SWP_AUTHOR "Neil " +#define SWP_DESC "Inventec port and transceiver driver" +#define SWP_VERSION "4.2.7" +#define SWP_LICENSE "GPL" + +/* Module status define */ +#define SWP_STATE_NORMAL (0) +#define SWP_STATE_I2C_DIE (-91) + +/* [Note]: + * Functions and mechanism for auto-detect platform type is ready, + * But HW and BIOS not ready! We need to wait them. + * So, please do not use PLATFORM_TYPE_AUTO until they are ready. + * (2016.06.13) + */ +#define PLATFORM_TYPE_AUTO (100) +#define PLATFORM_TYPE_MAGNOLIA (111) +#define PLATFORM_TYPE_MAGNOLIA_FNC (112) +#define PLATFORM_TYPE_REDWOOD (121) +#define PLATFORM_TYPE_REDWOOD_FSL (122) +#define PLATFORM_TYPE_HUDSON32I_GA (131) +#define PLATFORM_TYPE_SPRUCE (141) +#define PLATFORM_TYPE_CYPRESS_GA1 (151) /* Up -> Down */ +#define PLATFORM_TYPE_CYPRESS_GA2 (152) /* Down -> Up */ +#define PLATFORM_TYPE_CYPRESS_BAI (153) /* Down -> Up */ +#define PLATFORM_TYPE_TAHOE (161) +#define PLATFORM_TYPE_SEQUOIA_GA (171) +#define PLATFORM_TYPE_LAVENDER_GA (181) +#define PLATFORM_TYPE_LAVENDER_ONL (182) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_MAGNOLIA + +/* Define platform flag and kernel version */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA_FNC) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD) + #define SWPS_REDWOOD (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD_FSL) + #define SWPS_REDWOOD_FSL (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_HUDSON32I_GA) + #define SWPS_HUDSON32I_GA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SPRUCE) + #define SWPS_SPRUCE (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA1) + #define SWPS_CYPRESS_GA1 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA2) + #define SWPS_CYPRESS_GA2 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_BAI) + #define SWPS_CYPRESS_BAI (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_TAHOE) + #define SWPS_TAHOE (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA) + #define SWPS_SEQUOIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#endif + + +struct inv_platform_s { + int id; + char name[64]; +}; + +struct inv_ioexp_layout_s { + int ioexp_id; + int ioexp_type; + struct ioexp_addr_s addr[4]; +}; + +struct inv_port_layout_s { + int port_id; + int chan_id; + int ioexp_id; + int ioexp_offset; + int transvr_type; + int chipset_type; + int lane_id[8]; +}; + + +/* ========================================== + * Inventec Platform Settings + * ========================================== + */ +struct inv_platform_s platform_map[] = { + {PLATFORM_TYPE_AUTO, "Auto-Detect" }, + {PLATFORM_TYPE_MAGNOLIA, "Magnolia" }, + {PLATFORM_TYPE_MAGNOLIA_FNC, "Magnolia_FNC" }, + {PLATFORM_TYPE_REDWOOD, "Redwood" }, + {PLATFORM_TYPE_REDWOOD_FSL, "Redwood_FSL" }, + {PLATFORM_TYPE_HUDSON32I_GA, "Hudson32i" }, + {PLATFORM_TYPE_SPRUCE, "Spruce" }, + {PLATFORM_TYPE_CYPRESS_GA1, "Cypress_GA1" }, + {PLATFORM_TYPE_CYPRESS_GA2, "Cypress_GA2" }, + {PLATFORM_TYPE_CYPRESS_BAI, "Cypress_BAI" }, + {PLATFORM_TYPE_TAHOE, "Tahoe" }, + {PLATFORM_TYPE_SEQUOIA_GA, "Sequoia_GA" }, + {PLATFORM_TYPE_LAVENDER_GA, "Lavender_GA" }, + {PLATFORM_TYPE_LAVENDER_ONL, "Lavender_ONL" }, +}; + + +/* ========================================== + * Magnolia Layout configuration + * ========================================== + */ +#ifdef SWPS_MAGNOLIA +unsigned magnolia_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s magnolia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAGINOLIA_NAB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {1, IOEXP_TYPE_MAGINOLIA_NAB, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {2, IOEXP_TYPE_MAGINOLIA_NAB, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {3, IOEXP_TYPE_MAGINOLIA_4AB, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf0, 0xff}, {0xf0, 0xff}, }, }, /* addr[1] = I/O Expander 4 B */ + }, + {4, IOEXP_TYPE_MAGINOLIA_NAB, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {5, IOEXP_TYPE_MAGINOLIA_NAB, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {6, IOEXP_TYPE_MAGINOLIA_7AB, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[1] = I/O Expander 7 B */ + }, +}; + +struct inv_port_layout_s magnolia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 16} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 15} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 14} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 13} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 24} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 23} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 22} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 21} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 28} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 27} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 26} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 25} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 32} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 31} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 30} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 29} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 48} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 47} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 46} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 45} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 52} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 51} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 50} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 49} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 56} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 55} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 54} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 53} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 60} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 59} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 58} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 57} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 64} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 63} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 62} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 61} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 68} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 67} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 66} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 65} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 72} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 71} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 70} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 69} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 76} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 75} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 74} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 73} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD +unsigned redwood_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s redwood_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, +}; + +struct inv_port_layout_s redwood_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + { 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + { 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + { 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + { 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + {11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + {13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + {15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + {19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} }, + {29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} }, + {31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Hudson32i Layout configuration + * ========================================== + */ +#ifdef SWPS_HUDSON32I_GA +unsigned hudsin32iga_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s hudson32iga_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_HUDSON32IGA_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {1, IOEXP_TYPE_HUDSON32IGA_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {2, IOEXP_TYPE_HUDSON32IGA_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, + {3, IOEXP_TYPE_HUDSON32IGA_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, +}; + +struct inv_port_layout_s hudson32iga_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 1, 2, 3, 4} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 5, 6, 7, 8} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 9, 10, 11, 12} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 13, 14, 15, 16} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 17, 18, 19, 20} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 21, 22, 23, 24} }, + { 6, 12, 0, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 25, 26, 27, 28} }, + { 7, 13, 0, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 29, 30, 31, 32} }, + { 8, 14, 1, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 33, 34, 35, 36} }, + { 9, 15, 1, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 37, 38, 39, 40} }, + {10, 16, 1, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 41, 42, 43, 44} }, + {11, 17, 1, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 45, 46, 47, 48} }, + {12, 18, 1, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 49, 50, 51, 52} }, + {13, 19, 1, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 53, 54, 55, 56} }, + {14, 20, 1, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 57, 58, 59, 60} }, + {15, 21, 1, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 61, 62, 63, 64} }, + {16, 22, 2, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 65, 66, 67, 68} }, + {17, 23, 2, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 69, 70, 71, 72} }, + {18, 24, 2, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 73, 74, 75, 76} }, + {19, 25, 2, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + {20, 26, 2, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + {21, 27, 2, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 85, 86, 87, 88} }, + {22, 28, 2, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 89, 90, 91, 92} }, + {23, 29, 2, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 93, 94, 95, 96} }, + {24, 30, 3, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + {25, 31, 3, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + {26, 32, 3, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + {27, 33, 3, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, + {28, 34, 3, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {113,114,115,116} }, + {29, 35, 3, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {117,118,119,120} }, + {30, 36, 3, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {121,122,123,124} }, + {31, 37, 3, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Spruce Layout configuration + * ========================================== + */ +#ifdef SWPS_SPRUCE +unsigned spruce_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s spruce_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SPRUCE_7AB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[2] = I/O Expander 7B */ + }, +}; + +struct inv_port_layout_s spruce_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Up->Down]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA1 +unsigned cypress_ga1_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; + +struct inv_ioexp_layout_s cypress_ga1_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_ga1_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Down->Up]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA2 +unsigned cypress_ga2_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +struct inv_ioexp_layout_s cypress_ga2_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_ga2_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 1, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 2, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 3, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 4, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 5, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 6, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 7, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 8, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + { 9, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + {10, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {11, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {12, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {13, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {14, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {15, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {16, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {17, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {18, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {19, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {20, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {21, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {22, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {23, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {24, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {25, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {26, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {27, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {28, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {29, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {30, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {31, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {32, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {33, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {34, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {35, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {36, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {37, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {38, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {39, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {40, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {41, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {42, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {43, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {44, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {45, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {46, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {47, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {48, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {49, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {50, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {51, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {52, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {53, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (BaiDu version) + * ========================================== + */ +#ifdef SWPS_CYPRESS_BAI +unsigned cypress_b_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +struct inv_ioexp_layout_s cypress_b_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_b_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 2, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 4, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 6, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 8, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + {10, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {12, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {14, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {16, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {18, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {20, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {22, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {24, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {26, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {28, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {30, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {32, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {34, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {36, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {38, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {40, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {42, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {44, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {46, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {48, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {50, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {52, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {54, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood_fsl Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD_FSL +unsigned redwood_fsl_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s redwood_fsl_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, +}; + + +struct inv_port_layout_s redwood_fsl_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + { 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + { 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + { 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + { 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + {11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + {13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + {15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + {19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} }, + {29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} }, + {31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Tahoe Layout configuration + * ========================================== + */ +#ifdef SWPS_TAHOE +unsigned tahoe_gpio_rest_mux = MUX_RST_GPIO_249_PCA9548; + +struct inv_ioexp_layout_s tahoe_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_TAHOE_6ABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {1, IOEXP_TYPE_TAHOE_5A, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[0] = I/O Expander 5 A */ + }, +}; + + +struct inv_port_layout_s tahoe_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 12, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + { 1, 11, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + { 2, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + { 3, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + { 4, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + { 5, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + { 6, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + { 7, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + { 8, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + { 9, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, +}; +#endif + + +/* ========================================== + * Sequoia Layout configuration + * ========================================== + */ +#ifdef SWPS_SEQUOIA +unsigned sequoia_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; + +struct inv_ioexp_layout_s sequoia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { {1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + +struct inv_port_layout_s sequoia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 9, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 1, 10, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 2, 11, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 3, 12, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 4, 13, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + { 5, 14, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 6, 15, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + { 7, 16, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + { 8, 17, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + { 9, 18, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {10, 19, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {11, 20, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {12, 21, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + {13, 22, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + {14, 23, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121, 122, 123, 124} }, + {15, 24, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + {16, 25, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {137, 138, 139, 140} }, + {17, 26, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {129, 130, 131, 132} }, + {18, 27, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {153, 154, 155, 156} }, + {19, 28, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {145, 146, 147, 148} }, + {20, 29, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {169, 170, 171, 172} }, + {21, 30, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {161, 162, 163, 164} }, + {22, 31, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {185, 186, 187, 188} }, + {23, 32, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {177, 178, 179, 180} }, + {24, 33, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {201, 202, 203, 204} }, + {25, 34, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {193, 194, 195, 196} }, + {26, 35, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {217, 218, 219, 220} }, + {27, 36, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {209, 210, 211, 212} }, + {28, 37, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {233, 234, 235, 236} }, + {29, 38, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {225, 226, 227, 228} }, + {30, 39, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {249, 250, 251, 252} }, + {31, 40, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {241, 242, 243, 244} }, + {32, 44, 4, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + {33, 43, 4, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + {34, 42, 4, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + {35, 41, 4, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + {36, 48, 4, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {37, 47, 4, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {38, 46, 4, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {39, 45, 4, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {40, 52, 5, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {41, 51, 5, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {42, 50, 5, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {43, 49, 5, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {44, 56, 5, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, + {45, 55, 5, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + {46, 54, 5, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125, 126, 127, 128} }, + {47, 53, 5, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117, 118, 119, 120} }, + {48, 60, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {141, 142, 143, 144} }, + {49, 59, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {133, 134, 135, 136} }, + {50, 58, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {157, 158, 159, 160} }, + {51, 57, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {149, 150, 151, 152} }, + {52, 64, 6, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {173, 174, 175, 176} }, + {53, 63, 6, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {165, 166, 167, 168} }, + {54, 62, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {189, 190, 191, 192} }, + {55, 61, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {181, 182, 183, 184} }, + {56, 68, 7, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {205, 206, 207, 208} }, + {57, 67, 7, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {197, 198, 199, 200} }, + {58, 66, 7, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {221, 222, 223, 224} }, + {59, 65, 7, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {213, 214, 215, 216} }, + {60, 72, 7, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {237, 238, 239, 240} }, + {61, 71, 7, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {229, 230, 231, 232} }, + {62, 70, 7, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {253, 254, 255, 256} }, + {63, 69, 7, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {245, 246, 247, 248} }, +}; +#endif + + +/* ========================================== + * Lavender Layout configuration + * ========================================== + */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; +#endif + +#ifdef SWPS_LAVENDER +struct inv_ioexp_layout_s lavender_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { { 1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + { 1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { { 2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + { 2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + { 2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { { 3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + { 3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + { 3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { { 4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + { 4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + { 4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, + {8, IOEXP_TYPE_LAVENDER_P65, { { 5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xF6, 0xff}, {0xF8, 0xff}, }, }, /* addr[0] = I/O Expander CPU */ + }, +}; + + +struct inv_port_layout_s lavender_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {188, 189, 190, 191} }, + { 1, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {184, 185, 186, 187} }, + { 2, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {180, 181, 182, 183} }, + { 3, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {176, 177, 178, 179} }, + { 4, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {172, 173, 174, 175} }, + { 5, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {168, 169, 170, 171} }, + { 6, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {164, 165, 166, 167} }, + { 7, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {160, 161, 162, 163} }, + { 8, 25, 1, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {156, 157, 158, 159} }, + { 9, 26, 1, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {152, 153, 154, 155} }, + {10, 27, 1, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {148, 149, 150, 151} }, + {11, 28, 1, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {144, 145, 146, 147} }, + {12, 29, 1, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {140, 141, 142, 143} }, + {13, 30, 1, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {136, 137, 138, 139} }, + {14, 31, 1, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {132, 133, 134, 135} }, + {15, 32, 1, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {128, 129, 130, 131} }, + {16, 33, 2, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 0, 1, 2, 3} }, + {17, 34, 2, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 4, 5, 6, 7} }, + {18, 35, 2, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 8, 9, 10, 11} }, + {19, 36, 2, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 12, 13, 14, 15} }, + {20, 37, 2, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 16, 17, 18, 19} }, + {21, 38, 2, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 20, 21, 22, 23} }, + {22, 39, 2, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 24, 25, 26, 27} }, + {23, 40, 2, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 28, 29, 30, 31} }, + {24, 41, 3, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 32, 33, 34, 35} }, + {25, 42, 3, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 36, 37, 38, 39} }, + {26, 43, 3, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 40, 41, 42, 43} }, + {27, 44, 3, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 44, 45, 46, 47} }, + {28, 45, 3, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 48, 49, 50, 51} }, + {29, 46, 3, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 52, 53, 54, 55} }, + {30, 47, 3, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 56, 57, 58, 59} }, + {31, 48, 3, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 60, 61, 62, 63} }, + {32, 49, 4, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {256, 257, 258, 259} }, + {33, 50, 4, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {260, 261, 262, 263} }, + {34, 51, 4, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {264, 265, 266, 267} }, + {35, 52, 4, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {268, 269, 270, 271} }, + {36, 53, 4, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {272, 273, 274, 275} }, + {37, 54, 4, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {276, 277, 278, 279} }, + {38, 55, 4, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {280, 281, 282, 283} }, + {39, 56, 4, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {284, 285, 286, 287} }, + {40, 57, 5, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {288, 289, 290, 291} }, + {41, 58, 5, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {292, 293, 294, 295} }, + {42, 59, 5, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {296, 297, 298, 299} }, + {43, 60, 5, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {300, 301, 302, 303} }, + {44, 61, 5, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {304, 305, 306, 307} }, + {45, 62, 5, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {308, 309, 310, 311} }, + {46, 63, 5, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {312, 313, 314, 315} }, + {47, 64, 5, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {316, 317, 318, 319} }, + {48, 65, 6, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {444, 445, 446, 447} }, + {49, 66, 6, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {440, 441, 442, 443} }, + {50, 67, 6, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {436, 437, 438, 439} }, + {51, 68, 6, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {432, 433, 434, 435} }, + {52, 69, 6, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {428, 429, 430, 431} }, + {53, 70, 6, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {424, 425, 426, 427} }, + {54, 71, 6, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {420, 421, 422, 423} }, + {55, 72, 6, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {416, 417, 418, 419} }, + {56, 73, 7, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {412, 413, 414, 415} }, + {57, 74, 7, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {408, 409, 410, 411} }, + {58, 75, 7, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {404, 405, 406, 407} }, + {59, 76, 7, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {400, 401, 402, 403} }, + {60, 77, 7, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {396, 397, 398, 399} }, + {61, 78, 7, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {392, 393, 394, 395} }, + {62, 79, 7, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {388, 389, 390, 391} }, + {63, 80, 7, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {384, 385, 386, 387} }, + {64, 5, 8, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 64, 65, 66, 67} }, +}; +#endif + + +#endif /* INV_SWPS_H */ + + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.c new file mode 100644 index 000000000000..9f1bbd0e4f2f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.c @@ -0,0 +1,1885 @@ +/* + * 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 "io_expander.h" + +static struct ioexp_obj_s *ioexp_head_p = NULL; +static struct ioexp_obj_s *ioexp_tail_p = NULL; + + +/* ========== Register IOEXP layout ========== + */ +struct ioexp_map_s ioexp_map_magnolia_nab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_magnolia_4ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_magnolia_7ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {1, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {1, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {1, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 2}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 3}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 0, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 0, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 0, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 0, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 0, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 0, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 0, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 1, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 1, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 1, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 1, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 1, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 1, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 1, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_cypress_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_cypress_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 1, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 1, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 1, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {0, 1, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {0, 1, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {1, 1, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {1, 1, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {1, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {1, 1, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_5a = { + + .chip_amount = 1, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_6abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 0}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 3}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 0}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + {2, 1, 5}, /* map_present[8] = MOD_ABS_PORT(X+8) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + {2, 1, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + {2, 1, 4}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+8) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + {2, 1, 2}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_sequoia_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_lavender_p65 = { + + .chip_amount = 1, + .data_width = 1, + + .map_present = { {0, 0, 4}, }, /* map_present[0] = MOD_ABS_PORT(X) */ + .map_reset = { {0, 0, 1}, }, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + .map_lpmod = { {0, 0, 2}, }, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + .map_modsel = { {0, 0, 0}, }, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ +}; + + +/* ========== Private functions ========== + */ +int check_channel_tier_1(void); + +struct i2c_client * +_get_i2c_client(struct ioexp_obj_s *self, + int chip_id){ + + struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p; + + if (!(i2c_curr_p)){ + SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__); + return NULL; + } + while (i2c_curr_p){ + if ((i2c_curr_p->chip_id) == chip_id){ + return i2c_curr_p->i2c_client_p; + } + i2c_curr_p = i2c_curr_p->next; + } + SWPS_ERR("%s: not exist! :%d\n", __func__, chip_id); + return NULL; +} + + +static int +_common_ioexp_update_one(struct ioexp_obj_s *self, + struct ioexp_addr_s *ioexp_addr, + int chip_id, + int data_width, + int show_err, + char *caller_name) { + int buf = 0; + int err = 0; + int data_id = 0; + int r_offset = 0; + + for(data_id=0; data_idread_offset[data_id]; + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset); + /* Check error */ + if (buf < 0) { + err = 1; + if (show_err) { + SWPS_INFO("IOEXP-%d read fail! :%d \n", self->ioexp_id, buf); + SWPS_INFO("Dump: :%d :0x%02x :%d, :%s\n", + ioexp_addr->chan_id, ioexp_addr->chip_addr, + ioexp_addr->read_offset[data_id], caller_name); + } + continue; + } + /* Update IOEXP object */ + self->chip_data[chip_id].data[data_id] = (uint8_t)buf; + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +common_ioexp_update_all(struct ioexp_obj_s *self, + int show_err, + char *caller_name){ + + int err = 0; + int chip_id = 0; + int chip_amount = self->ioexp_map_p->chip_amount; + + for (chip_id=0; chip_idioexp_map_p->map_addr[chip_id]), + chip_id, + self->ioexp_map_p->data_width, + show_err, + caller_name) < 0) { + err = 1; + } + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +_common_check_by_mode(struct ioexp_obj_s *self){ + + switch (self->mode){ + case IOEXP_MODE_DIRECT: + return self->fsm_4_direct(self); + + case IOEXP_MODE_POLLING: + if (self->state >= 0){ + return 0; + } + switch (self->state){ + case STATE_IOEXP_INIT: + return ERR_IOEXP_UNINIT; + case STATE_IOEXP_ABNORMAL: + return ERR_IOEXP_ABNORMAL; + default: + return ERR_IOEXP_NOSTATE; + } + break; + + default: + break; + } + SWPS_ERR("%s: Exception occurs. :%d \n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +static int +_common_get_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + char *func_mane){ + uint8_t buf; + int err_code; + + /* Check and get address */ + err_code = _common_check_by_mode(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Get data form cache */ + buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + return (int)(buf >> bitmap_obj_p->bit_shift & 0x01); +} + + +static int +_common_set_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + int input_val, + char *func_mane){ + int err_code, target_offset; + uint8_t origin_byte; + uint8_t modify_byte; + + /* Check and get address */ + err_code = _common_check_by_mode(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Prepare write date */ + origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + switch (input_val) { + case 0: + modify_byte = origin_byte; + SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift); + break; + case 1: + modify_byte = origin_byte; + SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift); + break; + default: + SWPS_ERR("Input value incorrect! :%d :%d :%s\n", + input_val, self->ioexp_id, func_mane); + return ERR_IOEXP_BADINPUT; + } + /* Setup i2c client */ + target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset]; + /* Write byte to chip via I2C */ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id), + target_offset, + modify_byte); + /* Update or bollback object */ + if (err_code < 0){ + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte; + SWPS_ERR("I2C write fail! :%d :%d :%s :%d\n", + input_val, self->ioexp_id, func_mane, err_code); + return err_code; + } + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte; + return 0; +} + + +/* ========== Object public functions ========== + */ +int +common_get_present(struct ioexp_obj_s *self, + int virt_offset){ + + int UNPLUG = 1; + int retval = ERR_IOEXP_UNEXCPT; + + retval = _common_get_bit(self, + &(self->ioexp_map_p->map_present[virt_offset]), + "common_get_present"); + if (retval < 0) { + /* [Note] + * => Transceiver object does not need to handle IOEXP layer issues. + */ + return UNPLUG; + } + return retval; +} + + +int +common_get_tx_fault(struct ioexp_obj_s *self, + int virt_offset){ + /* [Transmit Fault (Tx_Fault)] + * A catastrophic laser fault will activate the transmitter signal, + * TX_FAULT, and disable the laser. This signal is an open collector + * output (pull-up required on the host board). A low signal indicates + * normal laser operation and a high signal indicates a fault. The + * TX_FAULT will be latched high when a laser fault occurs and is + * cleared by toggling the TX_DISABLE input or power cycling the + * transceiver. The transmitter fault condition can also be monitored + * via the two-wire serial interface. + * (address A2, byte 110, bit 2). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_fault[virt_offset]), + "common_get_tx_fault"); +} + + +int +common_get_rxlos(struct ioexp_obj_s *self, + int virt_offset){ + /* [Receiver Loss of Signal (Rx_LOS)] + * The post-amplification IC also includes transition detection circuitry + * which monitors the ac level of incoming optical signals and provides a + * TTL/CMOS compatible status signal to the host (pin 8). An adequate optical + * input results in a low Rx_LOS output while a high Rx_LOS output indicates + * an unusable optical input. The Rx_LOS thresholds are factory set so that + * a high output indicates a definite optical fault has occurred. Rx_LOS can + * also be monitored via the two-wire serial interface + * (address A2h, byte 110, bit 1). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_rxlos[virt_offset]), + "common_get_rxlos"); +} + + +int +common_get_tx_disable(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + "common_get_tx_disable"); +} + + +int +common_get_reset(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + "common_get_reset"); +} + + +int +common_get_lpmod(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + "common_get_lpmod"); +} + + +int +common_get_modsel(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + "common_get_modsel"); +} + + +int +common_get_hard_rs0(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + "common_get_hard_rs0"); +} + + +int +common_get_hard_rs1(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + "common_get_hard_rs1"); +} + + +int +common_set_tx_disable(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + input_val, + "common_set_tx_disable"); +} + + +int +common_set_reset(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + input_val, + "common_set_reset"); +} + + +int +common_set_lpmod(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + input_val, + "common_set_lpmod"); +} + + +int +common_set_modsel(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + input_val, + "common_set_modsel"); +} + + +int +common_set_hard_rs0(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + input_val, + "common_set_hard_rs0"); +} + + +int +common_set_hard_rs1(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + input_val, + "common_set_hard_rs1"); +} + + +int +ioexp_get_not_support(struct ioexp_obj_s *self, + int virt_offset){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +ioexp_set_not_support(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +fake_ioexp_init(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_ioexp_update(struct ioexp_obj_s *self){ + return 1; +} + + +int +fake_update_func(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_get_func(struct ioexp_obj_s *self, + int virt_offset){ + SWPS_WARN("Someone called fake_get_func\n"); + return -1; +} + +int +fake_set_func(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + SWPS_WARN("Someone called fake_set_func\n"); + return -1; +} + + +/* ========== Initial functions for IO Expander ========== + */ +int +common_ioexp_init(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + if (self->mode == IOEXP_MODE_DIRECT) { + goto update_common_ioexp_init; + } + /* Setup default value to each physical IO Expander */ + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + /* Get address mapping */ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("%s: IOEXP config incorrect! :%d \n", + __func__, chip_id); + return -1; + } + /* Setup default value */ + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->write_offset[offset], + addr_p->data_default[offset]); + if (err_code < 0){ + SWPS_ERR("%s: set default fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + } + } +update_common_ioexp_init: + /* Check and update info to object */ + err_code = self->update_all(self, 1, "common_ioexp_init"); + if (err_code < 0) { + SWPS_ERR("%s: update_all() fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +/* ========== Object functions for Final State Machine ========== + */ +int +_is_channel_ready(struct ioexp_obj_s *self){ + + int buf = 0; + int chip_id = 0; /* Use first chip which be registered */ + int data_id = 0; /* Use first byte which be registered */ + struct ioexp_addr_s *ioexp_addr = NULL; + + ioexp_addr = &(self->ioexp_map_p->map_addr[chip_id]); + if (!ioexp_addr){ + SWPS_ERR("%s: config incorrect!\n", __func__); + return ERR_IOEXP_UNEXCPT; + } + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), + ioexp_addr->read_offset[data_id]); + if (buf >= 0){ + return 1; + } + return 0; +} + +int +_ioexp_init_handler(struct ioexp_obj_s *self){ + + int return_val; + + switch (self->mode) { + case IOEXP_MODE_DIRECT: + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + + case IOEXP_MODE_POLLING: + /* Check system and channel is ready */ + if (self->state == STATE_IOEXP_INIT){ + if (!_is_channel_ready(self)){ + self->state = STATE_IOEXP_INIT; + SWPS_WARN("%s: IOEXP:%d channel not ready.\n", + __func__, self->ioexp_id); + return 0; + } + } + /* Execute initial callback */ + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + + default: + break; + } + SWPS_ERR("%s: exception occur :%d\n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){ + + int result_val; + int show_err = 1; + char *func_mane = "common_ioexp_fsm_4_direct"; + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, and return error */ + return ERR_IOEXP_UNINIT; + } + /* Case: Initial done */ + return 0; + + case STATE_IOEXP_NORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + SWPS_INFO("%s: NORMAL -> ABNORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + self->state = STATE_IOEXP_NORMAL; + return 0; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_DEBUG("%s: ABNORMAL -> NORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("%s: Exception occurs :%d\n", + __func__, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_polling(struct ioexp_obj_s *self){ + + int result_val, i, show_e; + int fail_retry = 3; + char *func_name = "common_ioexp_fsm_4_polling"; + +#ifdef DEBUG_SWPS + show_e = 1; +#else + show_e = 0; +#endif + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + /* Case: System (Channel) not ready */ + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, wait and retry */ + return 0; + } + /* Case: Initial done */ + SWPS_INFO("IOEXP-%d: initial done. :%d\n", + self->ioexp_id, self->ioexp_type); + return result_val; + + case STATE_IOEXP_NORMAL: + /* Retry mechanism for case of i2c topology not stable */ + for (i=0; iupdate_all(self, show_e, func_name); + if (result_val >= 0) { + self->state = STATE_IOEXP_NORMAL; + return 0; + } + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: detect I2C crash :%d\n", + __func__, self->ioexp_id); + break; + } + SWPS_DEBUG("IOEXP-%d: unstable :%d\n", + self->ioexp_id, result_val); + } + SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_e, func_name); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_INFO("IOEXP-%d: ABNORMAL -> NORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("IOEXP-%d: Exception occurs :%d\n", + self->ioexp_id, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +/* ========== Object private functions for check & update ========== + */ +int +common_ioexp_check(struct ioexp_obj_s *self){ + + int result; + + if (self->mode != IOEXP_MODE_POLLING){ + SWPS_ERR("%s: not polling mode :%d\n", + __func__, self->mode); + return ERR_IOEXP_NOTSUPPORT; + } + mutex_lock(&self->lock); + result = self->fsm_4_polling(self); + mutex_unlock(&self->lock); + return result; +} + + +/* ========== Functions for Factory pattern ========== + */ +static struct ioexp_map_s * +get_ioexp_map(int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + return &ioexp_map_magnolia_nab; + case IOEXP_TYPE_MAGINOLIA_4AB: + return &ioexp_map_magnolia_4ab; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + return &ioexp_map_magnolia_7ab; + case IOEXP_TYPE_REDWOOD_P01P08: + return &ioexp_map_redwood_p01p08_p17p24; + case IOEXP_TYPE_REDWOOD_P09P16: + return &ioexp_map_redwood_p09p16_p25p32; + case IOEXP_TYPE_HUDSON32IGA_P01P08: + return &ioexp_map_hudson32iga_p01p08_p17p24; + case IOEXP_TYPE_HUDSON32IGA_P09P16: + return &ioexp_map_hudson32iga_p09p16_p25p32; + case IOEXP_TYPE_CYPRESS_NABC: + return &ioexp_map_cypress_nabc; + case IOEXP_TYPE_CYPRESS_7ABC: + return &ioexp_map_cypress_7abc; + case IOEXP_TYPE_TAHOE_5A: + return &ioexp_map_tahoe_5a; + case IOEXP_TYPE_TAHOE_6ABC: + return &ioexp_map_tahoe_6abc; + case IOEXP_TYPE_SEQUOIA_NABC: + return &ioexp_map_sequoia_nabc; + case IOEXP_TYPE_LAVENDER_P65: + return &ioexp_map_lavender_p65; + default: + return NULL; + } +} + + +int +setup_ioexp_ssize_attr(struct ioexp_obj_s *self, + struct ioexp_map_s *ioexp_map_p, + int ioexp_id, + int ioexp_type, + int run_mode){ + switch (run_mode){ + case IOEXP_MODE_POLLING: /* Direct access device mode */ + case IOEXP_MODE_DIRECT: /* Polling mode, read from cache */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = ERR_IOEXP_UNEXCPT; + return ERR_IOEXP_UNEXCPT; + } + /* Setup mapping structure */ + self->ioexp_map_p = kzalloc(sizeof(*ioexp_map_p), GFP_KERNEL); + if (!(self->ioexp_map_p)) { + SWPS_ERR("%s: kzalloc ioexp_map_p fail\n", __func__); + return -1; + } + memcpy(self->ioexp_map_p, ioexp_map_p, sizeof(*ioexp_map_p)); + /* Setup attributes */ + self->ioexp_id = ioexp_id; + self->ioexp_type = ioexp_type; + self->state = STATE_IOEXP_INIT; + mutex_init(&self->lock); + return 0; +} + + +static int +setup_addr_mapping(struct ioexp_obj_s *self, + struct ioexp_addr_s *addr_map_p, + int chip_amount){ + struct ioexp_addr_s *tmp_p; + if (!addr_map_p){ + SWPS_ERR("%s: map is null\n", __func__); + return -1; + } + tmp_p = kzalloc((sizeof(*addr_map_p) * chip_amount), GFP_KERNEL); + if (!tmp_p){ + SWPS_ERR("%s: kzalloc fail.\n", __func__); + return -1; + } + memcpy(tmp_p, addr_map_p, (sizeof(*addr_map_p) * chip_amount)); + self->ioexp_map_p->map_addr = tmp_p; + + return 0; +} + + +static int +setup_ioexp_public_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + case IOEXP_TYPE_CYPRESS_NABC: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->get_hard_rs0 = common_get_hard_rs0; + self->get_hard_rs1 = common_get_hard_rs1; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + self->set_hard_rs0 = common_set_hard_rs0; + self->set_hard_rs1 = common_set_hard_rs1; + return 0; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + self->get_present = common_get_present; + self->get_tx_fault = ioexp_get_not_support; + self->get_rxlos = ioexp_get_not_support; + self->get_tx_disable = ioexp_get_not_support; + self->get_reset = common_get_reset; + self->get_lpmod = common_get_lpmod; + self->get_modsel = common_get_modsel; + self->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + self->set_tx_disable = ioexp_set_not_support; + self->set_reset = common_set_reset; + self->set_lpmod = common_set_lpmod; + self->set_modsel = common_set_modsel; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_ioexp_private_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + self->init = common_ioexp_init; + self->check = common_ioexp_check; + self->update_all = common_ioexp_update_all; + self->fsm_4_direct = common_ioexp_fsm_4_direct; + self->fsm_4_polling = common_ioexp_fsm_4_polling; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_i2c_client_one(struct ioexp_obj_s *self, + int chip_id){ + + char *err_msg = "ERROR"; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + struct ioexp_i2c_s *i2c_obj_p = NULL; + struct ioexp_i2c_s *i2c_curr_p = NULL; + + int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id; + adap = i2c_get_adapter(chan_id); + if(!adap){ + err_msg = "Can not get adap!"; + goto err_ioexp_setup_i2c_1; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + err_msg = "Can not kzalloc client!"; + goto err_ioexp_setup_i2c_1; + } + i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL); + if (!i2c_obj_p){ + err_msg = "Can not kzalloc i2c_obj_p!"; + goto err_ioexp_setup_i2c_2; + } + client->adapter = adap; + client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr; + i2c_obj_p->i2c_client_p = client; + i2c_obj_p->chip_id = chip_id; + i2c_obj_p->next = NULL; + if (!self->i2c_head_p){ + self->i2c_head_p = i2c_obj_p; + } else { + i2c_curr_p = self->i2c_head_p; + while (i2c_curr_p->next){ + i2c_curr_p = i2c_curr_p->next; + } + i2c_curr_p->next = i2c_obj_p; + } + return 0; + +err_ioexp_setup_i2c_2: + kfree(client); +err_ioexp_setup_i2c_1: + SWPS_ERR("%s: %s :%d\n", __func__, err_msg, chan_id); + return -1; +} + + +static int +setup_i2c_client(struct ioexp_obj_s* self){ + + int result; + int chip_id = 0; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + result = setup_i2c_client_one(self, chip_id); + if (result < 0){ + SWPS_ERR("%s fail! :%d\n", __func__, chip_id); + return -1; + } + } + return 0; +} + + +static int +setup_ioexp_config(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("IOEXP config incorrect! :%d \n",chip_id); + return -1; + } + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->conf_offset[offset], + addr_p->conf_default[offset]); + + if (err_code < 0){ + SWPS_INFO("%s: set conf fail! :%d \n", __func__, err_code); + return -2; + } + } + } + return 0; +} + + +struct ioexp_obj_s * +_create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_map_s* ioexp_map_p; + struct ioexp_obj_s* result_p; + struct ioexp_i2c_s *i2c_curr_p; + struct ioexp_i2c_s *i2c_next_p; + + /* Get layout */ + ioexp_map_p = get_ioexp_map(ioexp_type); + if (!ioexp_map_p){ + SWPS_ERR("%s: Invalid ioexp_type\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare IOEXP object */ + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + SWPS_ERR("%s: kzalloc failure!\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare static size attributes */ + if (setup_ioexp_ssize_attr(result_p, + ioexp_map_p, + ioexp_id, + ioexp_type, + run_mode) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + /* Prepare address mapping */ + if (setup_addr_mapping(result_p, addr_map_p, ioexp_map_p->chip_amount) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + if (setup_i2c_client(result_p) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + /* Prepare call back functions of object */ + if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + return result_p; + +err_create_ioexp_setup_i2c_fail: + i2c_curr_p = result_p->i2c_head_p; + i2c_next_p = result_p->i2c_head_p; + while (i2c_curr_p){ + i2c_next_p = i2c_curr_p->next; + kfree(i2c_curr_p->i2c_client_p); + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } +err_create_ioexp_setup_attr_fail: + kfree(result_p); +err_create_ioexp_fail: + SWPS_ERR("%s: fail! :%d :%d \n", + __func__, ioexp_id, ioexp_type); + return NULL; +} + + +int +create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_obj_s *ioexp_p = NULL; + + ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type, + addr_map_p, run_mode); + if (!ioexp_p){ + return -1; + } + if (ioexp_head_p == NULL){ + ioexp_head_p = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; + } + ioexp_tail_p->next = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; +} + + +static int +_init_ioexp_obj(struct ioexp_obj_s* self) { + + char *err_msg = "ERR"; + char *func_name = "_init_ioexp_obj"; + + /* Setup IOEXP configure byte */ + if (setup_ioexp_config(self) < 0){ + err_msg = "setup_ioexp_config fail"; + goto err_init_ioexp_obj; + } + /* Setup default data */ + if (_ioexp_init_handler(self) < 0){ + err_msg = "_ioexp_init_handler fail"; + goto err_init_ioexp_obj; + } + /* Update all */ + if (self->state == STATE_IOEXP_NORMAL){ + if (self->update_all(self, 1, func_name) < 0){ + err_msg = "update_all() fail"; + goto err_init_ioexp_obj; + } + } + return 0; + +err_init_ioexp_obj: + SWPS_DEBUG("%s: %s\n", __func__, err_msg); + return -1; +} + + +int +init_ioexp_objs(void){ + /* Return value: + * 0: Success + * -1: Detect topology error + * -2: SWPS internal error + */ + + struct ioexp_obj_s *curr_p = ioexp_head_p; + + if (!curr_p) { + SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__); + return -2; + } + while (curr_p) { + if (_init_ioexp_obj(curr_p) < 0) { + SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__); + return -1; + } + curr_p = curr_p->next; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + + +void +clean_ioexp_objs(void){ + + struct ioexp_i2c_s *i2c_curr_p = NULL; + struct ioexp_i2c_s *i2c_next_p = NULL; + struct ioexp_obj_s *ioexp_next_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + if (ioexp_head_p == NULL){ + ioexp_tail_p = NULL; + return; + } + while(ioexp_curr_p){ + ioexp_next_p = ioexp_curr_p->next; + if (ioexp_curr_p->ioexp_map_p) { + if (ioexp_curr_p->ioexp_map_p->map_addr) { + kfree(ioexp_curr_p->ioexp_map_p->map_addr); + } + kfree(ioexp_curr_p->ioexp_map_p); + } + + i2c_curr_p = ioexp_curr_p->i2c_head_p; + while (i2c_curr_p) { + i2c_next_p = i2c_curr_p->next; + kfree(i2c_curr_p->i2c_client_p); + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } + kfree(ioexp_curr_p); + ioexp_curr_p = ioexp_next_p; + } + ioexp_tail_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} + + +int +check_ioexp_objs(void){ + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while (ioexp_curr_p){ + if ( (ioexp_curr_p->check(ioexp_curr_p)) < 0){ + SWPS_INFO("check IOEXP-%d fail! :%d\n", + ioexp_curr_p->ioexp_id, ioexp_curr_p->ioexp_type); + return -1; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +struct ioexp_obj_s * +get_ioexp_obj(int ioexp_id){ + + struct ioexp_obj_s *result_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + if (ioexp_curr_p->ioexp_id == ioexp_id){ + result_p = ioexp_curr_p; + break; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return result_p; +} + + +void +unlock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_unlock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } +} + + +int +lock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_lock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} + + +static int +_scan_channel_tier_1(int force, + int show_err) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + int ready = 0; + + if (!ioexp_curr_p) { + goto err_scan_tier_1_channel; + } + while(ioexp_curr_p) { + ready = _is_channel_ready(ioexp_curr_p); + if ((!ready) && (!force)) { + goto err_scan_tier_1_channel; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; + +err_scan_tier_1_channel: + if (show_err) { + if (ioexp_curr_p) { + SWPS_INFO("%s: IOEXP-%d fail\n", __func__, ioexp_curr_p->ioexp_id); + } else { + SWPS_INFO("%s: IOEXP is null.\n", __func__); + } + } + return -1; +} + + +static int +_scan_channel_tier_1_single(void) { + + int ret = 0; + int chan_id = 0; + int fake_cid = 0; + int fake_offs = 0; + int fake_addr = 0; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + + if (ioexp_head_p->ioexp_id != ioexp_tail_p->ioexp_id) { + return 0; + } + /* Setup i2c_client */ + chan_id = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chan_id; + fake_addr = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chip_addr; + adap = i2c_get_adapter((chan_id + 1)); + if(!adap){ + SWPS_INFO("%s: Can not get adap!\n", __func__); + return 0; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + SWPS_INFO("%s: Can not kzalloc client!\n", __func__); + return 0; + } + client->adapter = adap; + client->addr = fake_addr; + /* Fouce move ioexp ptr to next */ + ret = i2c_smbus_read_byte_data(client, fake_offs); + SWPS_DEBUG("%s: move ioexp_ptr done. :%d\n", __func__, ret); + kfree(client); + return 1; +} + + +int +resync_channel_tier_1(void) { + + char *emsg = "ERR"; + + if (!ioexp_head_p) { + emsg = "ioexp_head_p is NULL"; + goto err_resync_ioexp_status_1; + } + /* Run all */ + if (ioexp_head_p->ioexp_id == ioexp_tail_p->ioexp_id) { + _scan_channel_tier_1_single(); + } else { + _scan_channel_tier_1(1, 0); + } + /* Check all */ + if (_scan_channel_tier_1(0, 1) < 0) { + emsg = "resync tier-1 channel fail"; + goto err_resync_ioexp_status_1; + } + return 0; + +err_resync_ioexp_status_1: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.h new file mode 100644 index 000000000000..82fef3f7febc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.h @@ -0,0 +1,183 @@ +/* + * 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. + */ + +#ifndef IO_EXPANDER_H +#define IO_EXPANDER_H + +#include + + +/* IOEXP type define (SFP series) */ +#define IOEXP_TYPE_MAGINOLIA_NAB (10101) +#define IOEXP_TYPE_MAGINOLIA_4AB (10102) +#define IOEXP_TYPE_CYPRESS_NABC (10103) + +/* IOEXP type define (QSFP series) */ +#define IOEXP_TYPE_MAGINOLIA_7AB (10201) +#define IOEXP_TYPE_REDWOOD_P01P08 (10202) +#define IOEXP_TYPE_REDWOOD_P09P16 (10203) +#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204) +#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205) +#define IOEXP_TYPE_SPRUCE_7AB (10206) +#define IOEXP_TYPE_CYPRESS_7ABC (10207) +#define IOEXP_TYPE_TAHOE_5A (10208) +#define IOEXP_TYPE_TAHOE_6ABC (10209) +#define IOEXP_TYPE_SEQUOIA_NABC (10210) +#define IOEXP_TYPE_LAVENDER_P65 (10211) + +/* IOEXP mode define */ +#define IOEXP_MODE_POLLING (19000) +#define IOEXP_MODE_DIRECT (19001) + +/* IOEXP state define */ +#define STATE_IOEXP_NORMAL (0) +#define STATE_IOEXP_INIT (-1) +#define STATE_IOEXP_ABNORMAL (-2) + +/* IOEXP error code define */ +#define ERR_IOEXP_NOTSUPPORT (-100) +#define ERR_IOEXP_UNINIT (-101) +#define ERR_IOEXP_BADCONF (-102) +#define ERR_IOEXP_ABNORMAL (-103) +#define ERR_IOEXP_NOSTATE (-104) +#define ERR_IOEXP_BADINPUT (-105) +#define ERR_IOEXP_UNEXCPT (-199) + + +#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args) +#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args) +#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args) + +#ifdef DEBUG_SWPS +# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args) +#else +# define SWPS_DEBUG(fmt, args...) +#endif + + +struct ioexp_addr_s { + int chan_id; + int chip_addr; + int read_offset[8]; + int write_offset[8]; + int conf_offset[8]; + uint8_t data_default[8]; + uint8_t conf_default[8]; +}; + +struct ioexp_i2c_s { + int chip_id; + struct i2c_client *i2c_client_p; + struct ioexp_i2c_s *next; +}; + + +struct ioexp_bitmap_s { + int chip_id; /* IOEXP chip id */ + int ioexp_voffset; /* IOEXP virtual offset */ + int bit_shift; +}; + +struct ioexp_map_s { + int chip_amount; /* Number of chips that IOEXP object content */ + int data_width; /* Number of (Read/Write/Config) bytes */ + struct ioexp_addr_s *map_addr; /* Chip address info */ + struct ioexp_bitmap_s map_present[10]; /* IOEXP for SFP / QSFP */ + struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[10]; /* IOEXP for QSFP */ +}; + +struct ioexp_data_s { + uint8_t data[8]; +}; + +struct ioexp_obj_s { + + /* ============================ + * Object public property + * ============================ + */ + int ioexp_id; + int ioexp_type; + + /* ============================ + * Object private property + * ============================ + */ + struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */ + struct ioexp_map_s *ioexp_map_p; + struct ioexp_obj_s *next; + struct ioexp_i2c_s *i2c_head_p; + struct mutex lock; + int mode; + int state; + + /* =========================================== + * Object public functions + * =========================================== + */ + int (*get_present)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset); + int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset); + int (*get_reset)(struct ioexp_obj_s *self, int virt_offset); + int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset); + int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs1)(struct ioexp_obj_s *self, int virt_offset); + int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val); + + /* =========================================== + * Object private functions + * =========================================== + */ + int (*init)(struct ioexp_obj_s *self); + int (*check)(struct ioexp_obj_s *self); + int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name); + int (*fsm_4_direct)(struct ioexp_obj_s* self); + int (*fsm_4_polling)(struct ioexp_obj_s* self); +}; + + +struct ioexp_obj_s* get_ioexp_obj(int ioexp_id); +int create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode); +int init_ioexp_objs(void); +int check_ioexp_objs(void); +void clean_ioexp_objs(void); + +void unlock_ioexp_all(void); +int lock_ioexp_all(void); + +int check_channel_tier_1(void); +int resync_channel_tier_1(void); + +/* Macro for bit control */ +#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift))) +#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift))) + + +#endif /* IO_EXPANDER_H */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.c new file mode 100644 index 000000000000..e7f3cf70fa68 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.c @@ -0,0 +1,8388 @@ +/* + * 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 "io_expander.h" +#include "transceiver.h" + + +/* ========== Register EEPROM address mapping ========== + */ +struct eeprom_map_s eeprom_map_sfp = { + .addr_br =0x50, .page_br =-1, .offset_br =12, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =94, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =-1, .offset_connector =2, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =-1, .offset_diag_type =92 , .length_diag_type =1, + .addr_extbr =-1, .page_extbr =-1, .offset_extbr =-1, .length_extbr =-1, + .addr_ext_id =0x50, .page_ext_id =-1, .offset_ext_id =1, .length_ext_id =1, + .addr_id =0x50, .page_id =-1, .offset_id =0, .length_id =1, + .addr_len_sm =0x50, .page_len_sm =-1, .offset_len_sm =15, .length_len_sm =1, + .addr_len_smf =0x50, .page_len_smf =-1, .offset_len_smf =14, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =-1, .offset_len_om1 =17, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =-1, .offset_len_om2 =16, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =-1, .offset_len_om3 =19, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =-1, .offset_len_om4 =18, .length_len_om4 =1, + .addr_option =0x50, .page_option =-1, .offset_option =64, .length_option =2, + .addr_rate_id =0x50, .page_rate_id =-1, .offset_rate_id =13, .length_rate_id =1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =0x51, .page_rx_em =-1, .offset_rx_em =115, .length_rx_em =1, + .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1, + .addr_rx_power =0x51, .page_rx_power =-1, .offset_rx_power =104, .length_rx_power =2, + .addr_soft_rs0 =0x51, .page_soft_rs0 =-1, .offset_soft_rs0 =110, .length_soft_rs0 =1, + .addr_soft_rs1 =0x51, .page_soft_rs1 =-1, .offset_soft_rs1 =118, .length_soft_rs0 =1, + .addr_temp =0x51, .page_temp =-1, .offset_temp =96, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =-1, .offset_trancomp =3, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =-1, .offset_trancomp_ext =36, .length_trancomp_ext =1, + .addr_tx_bias =0x51, .page_tx_bias =-1, .offset_tx_bias =100, .length_tx_bias =2, + .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1, + .addr_tx_eq =0x51, .page_tx_eq =-1, .offset_tx_eq =114, .length_tx_eq =1, + .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1, + .addr_tx_power =0x51, .page_tx_power =-1, .offset_tx_power =102, .length_tx_power =2, + .addr_vendor_name =0x50, .page_vendor_name =-1, .offset_vendor_name =20, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =-1, .offset_vendor_pn =40, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =-1, .offset_vendor_rev =56, .length_vendor_rev =4, + .addr_vendor_sn =0x50, .page_vendor_sn =-1, .offset_vendor_sn =68, .length_vendor_sn =16, + .addr_voltage =0x51, .page_voltage =-1, .offset_voltage =98, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =-1, .offset_wavelength =60, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =-1, .page_rx_em =-1, .offset_rx_em =-1, .length_rx_em =-1, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =-1, .page_tx_eq =-1, .offset_tx_eq =-1, .length_tx_eq =-1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp28 = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =0x50, .page_cdr =-1, .offset_cdr =98, .length_cdr =1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =0x50, .page_rx_am =3, .offset_rx_am =238, .length_rx_am =2, + .addr_rx_em =0x50, .page_rx_em =3, .offset_rx_em =236, .length_rx_em =2, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =0x50, .page_tx_eq =3, .offset_tx_eq =234, .length_tx_eq =2, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + + +/* ========== Utility Functions ========== + */ +static int +get_bit(uint8_t origin_byte, int bit_shift) { + return (int)((origin_byte >> bit_shift) & 0x1); +} + +static int +transform_word_to_int(uint8_t hight_byte, + uint8_t low_byte) { + return ((((int)hight_byte) << 8) + (int)low_byte); +} + + +void +alarm_msg_2_user(struct transvr_obj_s *self, + char *emsg) { + + SWPS_ERR("%s on %s.\n", emsg, self->swp_name); +} + + +/* ========== Private functions ========== + */ +static int +_reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +_is_transvr_support_ctle(struct transvr_obj_s *self); + +static int +_transvr_init_handler(struct transvr_obj_s *self); + +int +_transvr_clean_handler(struct transvr_obj_s *self); + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self); + + +void +lock_transvr_obj(struct transvr_obj_s *self) { + + mutex_lock(&self->lock); + self->curr_page = VAL_TRANSVR_PAGE_FREE; +} + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} + + +static int +_check_by_mode(struct transvr_obj_s *self, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + char *caller_name){ + + int return_val = ERR_TRANSVR_UNEXCPT; + + switch (self->mode){ + case TRANSVR_MODE_POLLING: + switch (self->state){ + case STATE_TRANSVR_CONNECTED: + goto ok_check_by_mode_1; + case STATE_TRANSVR_NEW: + case STATE_TRANSVR_INIT: + return ERR_TRANSVR_UNINIT; + case STATE_TRANSVR_DISCONNECTED: + return ERR_TRANSVR_UNPLUGGED; + case STATE_TRANSVR_UNEXCEPTED: + return ERR_TRANSVR_ABNORMAL; + case STATE_TRANSVR_ISOLATED: + return ERR_TRNASVR_BE_ISOLATED; + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + + case TRANSVR_MODE_DIRECT: + return_val = self->fsm_4_direct(self, caller_name); + if (return_val < 0){ + return return_val; + } + goto ok_check_by_mode_1; + + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + +ok_check_by_mode_1: + return attr_update_func(self, 0); + +err_check_by_mode_1: + SWPS_INFO("_check_by_mode: mode:%d state:%d\n", self->mode, self->state); + return ERR_TRANSVR_UNEXCPT; +} + + +static void +_transvr_clean_retry(struct transvr_obj_s *self) { + self->retry = 0; +} + + +static int +_transvr_handle_retry(struct transvr_obj_s *self, int retry) { + /* Return: 0: keep retry + * -1: stop retry + */ + if (self->retry == 0) { + self->retry = retry; + } + self->retry -= 1; + if (self->retry <= 0) { + _transvr_clean_retry(self); + return -1; + } + return 0; +} + + +static int +_common_setup_page(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int show_e) { + /* return: + * 0 : OK + * -1 : EEPROM settings incorrect + * -2 : I2C R/W failure + * -3 : Undefined case + */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Check */ + if ((addr < 0) || (offset < 0) || (len < 0)) { + emsg = "EEPROM settings incorrect"; + retval = -1; + goto err_common_setup_page; + } + /* Case1: continue access */ + if ((self->i2c_client_p->addr == addr) && + (self->curr_page == page)) { + return 0; + } + self->i2c_client_p->addr = addr; + /* Case2: select lower page */ + if (page == -1) { + self->curr_page = page; + return 0; + } + /* Case3: select upper page */ + if (page >= 0) { + goto upper_common_setup_page; + } + /* Unexpected case */ + show_e = 1; + emsg = "Unexpected case"; + retval = -3; + goto err_common_setup_page; + +upper_common_setup_page: + if (i2c_smbus_write_byte_data(self->i2c_client_p, + VAL_TRANSVR_PAGE_SELECT_OFFSET, + page) < 0) { + emsg = "I2C R/W failure"; + retval = -2; + goto err_common_setup_page; + } + self->curr_page = page; + mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY); + return 0; + +err_common_setup_page: + if (show_e) { + SWPS_INFO("%s: %s", __func__, emsg); + SWPS_INFO("%s: :0x%02x :%d :%d :%d\n", + __func__, addr, page, offset, len); + } + return retval; +} + +/* +static int +_common_setup_password(struct transvr_obj_s *self, + int addr, + int page, + int offs, + uint8_t pwd[4], + int show_e) { + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, 4, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_setup_password; + } + for (i=0; i<4; i++) { + err = i2c_smbus_write_byte_data(self->i2c_client_p, + (offs + i), + pwd[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_setup_password; + } + } + return 0; + +err_common_setup_password: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} +*/ + +static int +_common_update_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + uint8_t *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_uint8_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_uint8_attr; + } + buf[i] = err; + } + return 0; + +err_common_update_uint8_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_int_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_int_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_int_attr; + } + buf[i] = (int)err; + } + return 0; + +err_common_update_int_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_INT_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_string_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + char buf[], + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_string_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_string_attr; + } + buf[i] = (char)err; + } + return 0; + +err_common_update_string_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = 'e'; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + uint8_t update, + uint8_t *buf, + char *caller, + int show_e){ + int len = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + if ((*buf) == update){ + return 0; + } + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + err = i2c_smbus_write_byte_data(self->i2c_client_p, + offset, + update); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + (*buf) = update; + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_array(struct transvr_obj_s *self, + int addr, + int page, + int offs, + int len, + uint8_t update[], + uint8_t buf[], + char *caller, + int show_e){ + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + for (i=0; ii2c_client_p, + (offs + i), + update[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + buf[i] = update[i]; + } + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, emsg, caller, err, i); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_attr_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_id, + self->eeprom_map_p->page_id, + self->eeprom_map_p->offset_id, + self->eeprom_map_p->length_id, + &(self->id), + "_common_update_attr_id", + show_err); +} + + +static int +_common_update_attr_extended_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_ext_id, + self->eeprom_map_p->page_ext_id, + self->eeprom_map_p->offset_ext_id, + self->eeprom_map_p->length_ext_id, + &(self->ext_id), + "_common_update_attr_extended_id", + show_err); +} + + +static int +_common_update_attr_connector(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_connector, + self->eeprom_map_p->page_connector, + self->eeprom_map_p->offset_connector, + self->eeprom_map_p->length_connector, + &(self->connector), + "_common_update_attr_connector", + show_err); +} + + +static int +_common_update_attr_transvr_comp(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp, + self->eeprom_map_p->page_trancomp, + self->eeprom_map_p->offset_trancomp, + self->eeprom_map_p->length_trancomp, + self->transvr_comp, + "_common_update_attr_transvr_comp", + show_err); +} + + +static int +_common_update_attr_transvr_comp_ext(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp_ext, + self->eeprom_map_p->page_trancomp_ext, + self->eeprom_map_p->offset_trancomp_ext, + self->eeprom_map_p->length_trancomp_ext, + &(self->transvr_comp_ext), + "_common_update_attr_transvr_comp_ext", + show_err); +} + + +static int +_common_update_attr_vendor_name(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_name, + self->eeprom_map_p->page_vendor_name, + self->eeprom_map_p->offset_vendor_name, + self->eeprom_map_p->length_vendor_name, + self->vendor_name, + "_common_update_attr_vendor_name", + show_err); +} + + +static int +_common_update_attr_vendor_pn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_pn, + self->eeprom_map_p->page_vendor_pn, + self->eeprom_map_p->offset_vendor_pn, + self->eeprom_map_p->length_vendor_pn, + self->vendor_pn, + "_common_update_attr_vendor_pn", + show_err); +} + + +static int +_common_update_attr_vendor_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_rev, + self->eeprom_map_p->page_vendor_rev, + self->eeprom_map_p->offset_vendor_rev, + self->eeprom_map_p->length_vendor_rev, + self->vendor_rev, + "_common_update_attr_vendor_rev", + show_err); +} + + +static int +_common_update_attr_vendor_sn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_sn, + self->eeprom_map_p->page_vendor_sn, + self->eeprom_map_p->offset_vendor_sn, + self->eeprom_map_p->length_vendor_sn, + self->vendor_sn, + "_common_update_attr_vendor_sn", + show_err); +} + + +static int +_common_update_attr_br(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_br, + self->eeprom_map_p->page_br, + self->eeprom_map_p->offset_br, + self->eeprom_map_p->length_br, + &(self->br), + "_common_update_attr_br", + show_err); +} + + +static int +_common_update_attr_len_smf(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_smf, + self->eeprom_map_p->page_len_smf, + self->eeprom_map_p->offset_len_smf, + self->eeprom_map_p->length_len_smf, + &(self->len_smf), + "_common_update_attr_len_smf", + show_err); +} + + +static int +_common_update_attr_len_om1(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om1, + self->eeprom_map_p->page_len_om1, + self->eeprom_map_p->offset_len_om1, + self->eeprom_map_p->length_len_om1, + &(self->len_om1), + "_common_update_attr_len_om1", + show_err); +} + +static int +_common_update_attr_len_om2(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om2, + self->eeprom_map_p->page_len_om2, + self->eeprom_map_p->offset_len_om2, + self->eeprom_map_p->length_len_om2, + &(self->len_om2), + "_common_update_attr_len_om2", + show_err); +} + +static int +_common_update_attr_len_om3(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om3, + self->eeprom_map_p->page_len_om3, + self->eeprom_map_p->offset_len_om3, + self->eeprom_map_p->length_len_om3, + &(self->len_om3), + "_common_update_attr_len_om3", + show_err); +} + + +static int +_common_update_attr_len_om4(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om4, + self->eeprom_map_p->page_len_om4, + self->eeprom_map_p->offset_len_om4, + self->eeprom_map_p->length_len_om4, + &(self->len_om4), + "_common_update_attr_len_om4", + show_err); +} + + +static int +_common_update_attr_option(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_option, + self->eeprom_map_p->page_option, + self->eeprom_map_p->offset_option, + self->eeprom_map_p->length_option, + self->option, + "_common_update_attr_option", + show_err); +} + + +static int +_common_update_attr_comp_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_comp_rev, + self->eeprom_map_p->page_comp_rev, + self->eeprom_map_p->offset_comp_rev, + self->eeprom_map_p->length_comp_rev, + &(self->comp_rev), + "_common_update_attr_comp_rev", + show_err); +} + + +static int +_common_update_attr_diag_type(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_diag_type, + self->eeprom_map_p->page_diag_type, + self->eeprom_map_p->offset_diag_type, + self->eeprom_map_p->length_diag_type, + &(self->diag_type), + "_common_update_attr_diag_type", + show_err); +} + + +static int +_common_update_attr_wavelength(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_wavelength, + self->eeprom_map_p->page_wavelength, + self->eeprom_map_p->offset_wavelength, + self->eeprom_map_p->length_wavelength, + self->wavelength, + "_common_update_attr_wavelength", + show_err); +} + + +int +_common_get_option_value(struct transvr_obj_s *self, + int offset, + int bit_shift) { + /* SFP: + * - option[0] = A0h / 64 + * - option[1] = A0h / 65 + * QSFP: + * - option[0] = 00h / 193 + * - option[1] = 00h / 194 + * - option[2] = 00h / 195 + */ + return (self->option[offset] & (1 << bit_shift)); +} + + +static int +_sfp_update_attr_len_sm(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_sm, + self->eeprom_map_p->page_len_sm, + self->eeprom_map_p->offset_len_sm, + self->eeprom_map_p->length_len_sm, + &(self->len_sm), + "_common_update_attr_len_sm", + show_err); +} + + +static int +_sfp_update_attr_rate_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_rate_id, + self->eeprom_map_p->page_rate_id, + self->eeprom_map_p->offset_rate_id, + self->eeprom_map_p->length_rate_id, + &(self->rate_id), + "_sfp_update_attr_rate_id", + show_err); +} + + +static int +_sfp_update_attr_soft_rs0(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + self->eeprom_map_p->length_soft_rs0, + &(self->soft_rs0), + "_sfp_update_attr_soft_rs0", + show_err); +} + + +static int +_sfp_update_attr_soft_rs1(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + self->eeprom_map_p->length_soft_rs1, + &(self->soft_rs1), + "_sfp_update_attr_soft_rs1", + show_err); +} + + +int +_sfp_is_diag_support(struct transvr_obj_s *self){ + + uint8_t bit_mask = 0xC0; /* 1100 0000 */ + uint8_t en_val = 0x40; /* 0100 0000 */ + uint8_t checkval = (self->diag_type & bit_mask); + + if (checkval == en_val) { + return 1; + } + return 0; +} + + +static int +_sfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_sfp_update_attr_curr_temp", + show_err); +} + + +static int +_sfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_sfp_update_attr_curr_voltage", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_sfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_sfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_sfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_sfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_sfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_sfp_update_attr_rx_em", + show_err); +} + + +static int +_sfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_sfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_cdr(struct transvr_obj_s *self, + int show_err){ + if (self->type != TRANSVR_TYPE_QSFP_28){ + self->cdr = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + self->eeprom_map_p->length_cdr, + &(self->cdr), + "_common_update_attr_cdr", + show_err); +} + + +static int +_qsfg_update_attr_extbr(struct transvr_obj_s *self, + int show_err) { + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_extbr, + self->eeprom_map_p->page_extbr, + self->eeprom_map_p->offset_extbr, + self->eeprom_map_p->length_extbr, + &(self->extbr), + "_common_update_attr_extbr", + show_err); +} + + +static int +_qsfp_is_diag_support(struct transvr_obj_s *self, + int diag_type) { + /* Input Parm: diag_type + * => 1 : temperature + * => 2 : voltage + * => 3 : tx relate + * => 4 : rx relate + */ + uint8_t mask_b2 = 0x04; /* 0000 0100 */ + uint8_t mask_b3 = 0x08; /* 0000 1000 */ + + switch (diag_type) { + case 1: /* temperature */ + case 2: /* voltage */ + /* Direct access target, because of spec not defined */ + return 1; + case 3: + case 4: + /* [Note] + * Due to lot of transceiver vendor defined it not rigorously and + * consider of general support, we seem it as supported if there + * are bit-2 OR bit-3 defined by transceiver vendor. + */ + if ( ((self->diag_type & mask_b2) == mask_b2 ) || + ((self->diag_type & mask_b3) == mask_b3 ) ){ + return 1; + } + return 0; + default: + SWPS_INFO("%s: undefined diag_type:%d\n", + __func__, diag_type); + break; + } + return 0; +} + + +int +_qsfp_is_implement_tx_disable(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-4 + */ + int byte = 2; + int bit = 4; + return _common_get_option_value(self, byte, bit); +} + + +int +_qsfp_is_implement_tx_fault(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-3 + */ + int byte = 2; + int bit = 3; + return _common_get_option_value(self, byte, bit); +} + + +static int +_qsfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + int diag_type = 1; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_qsfp_update_attr_curr_temp", + show_err); +} + + +static int +_qsfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + int diag_type = 2; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_qsfp_update_attr_curr_voltage", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_qsfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_qsfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_qsfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 4; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_qsfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_qsfp_update_attr_soft_rx_los(struct transvr_obj_s *self, + int show_err){ + + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_los, + self->eeprom_map_p->page_rx_los, + self->eeprom_map_p->offset_rx_los, + self->eeprom_map_p->length_rx_los, + &(self->rx_los), + "_qsfp_update_attr_soft_rx_los", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_disable(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_disable(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_update_attr_soft_tx_disable", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_fault(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_fault(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_fault, + self->eeprom_map_p->page_tx_fault, + self->eeprom_map_p->offset_tx_fault, + self->eeprom_map_p->length_tx_fault, + &(self->tx_fault), + "_qsfp_update_attr_soft_tx_fault", + show_err); +} + + +static int +_qsfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_qsfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_rx_am(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + self->rx_am, + "_qsfp_update_attr_rx_am", + show_err); +} + + +static int +_qsfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_qsfp_update_attr_rx_em", + show_err); +} + + +int +_common_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = "err"; + + if (_common_update_attr_id(self, show_err) < 0) { + err_str = "_common_update_attr_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_extended_id(self, show_err) < 0) { + err_str = "_common_update_attr_extended_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_connector(self, show_err) < 0) { + err_str = "_common_update_attr_connector"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp_ext(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp_ext"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_name(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_name"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_pn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_pn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_rev(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_sn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_sn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_br(self, show_err) < 0) { + err_str = "_common_update_attr_br"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_smf(self, show_err) < 0) { + err_str = "_common_update_attr_len_smf"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om1(self, show_err) < 0) { + err_str = "_common_update_attr_len_om1"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om2(self, show_err) < 0) { + err_str = "_common_update_attr_len_om2"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om3(self, show_err) < 0) { + err_str = "_common_update_attr_len_om3"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om4(self, show_err) < 0) { + err_str = "_common_update_attr_len_om4"; + goto err_common_update_attr_all; + } + if (_common_update_attr_option(self, show_err) < 0) { + err_str = "_common_update_attr_option"; + goto err_common_update_attr_all; + } + if (_common_update_attr_comp_rev(self, show_err) < 0) { + err_str = "_common_update_attr_comp_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_diag_type(self, show_err) < 0) { + err_str = "_common_update_attr_diag_type"; + goto err_common_update_attr_all; + } + if (_common_update_attr_wavelength(self, show_err) < 0) { + err_str = "_common_update_attr_wavelength"; + goto err_common_update_attr_all; + } + return 0; + +err_common_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_sfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_len_sm(self, show_err) < 0) { + err_str = "_sfp_update_attr_len_sm"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_rate_id(self, show_err) < 0) { + err_str = "_sfp_update_attr_rate_id"; + goto err_sfp_update_attr_all; + } + if ((self->rate_id) > 0) { + if (_sfp_update_attr_soft_rs0(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs0"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_soft_rs1(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs1"; + goto err_sfp_update_attr_all; + } + } + return 0; + +err_sfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_qsfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_qsfp_update_attr_all; + } + if (_qsfg_update_attr_extbr(self, show_err) < 0) { + err_str = "_qsfg_update_attr_extbr"; + goto err_qsfp_update_attr_all; + } + if (self->type == TRANSVR_TYPE_QSFP_28) { + if (_qsfp_update_attr_cdr(self, 1) < 0) { + err_str = "_qsfp_update_attr_cdr"; + goto err_qsfp_update_attr_all; + } + } + return 0; + +err_qsfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +/* ========== Object functions for common type ========== + */ +int +_common_count_temp(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + int sign = 0; + int high = 0; + int low = 0; + int lmax = 8; + + /* Count high */ + sign = get_bit(high_byte,7); + SWP_BIT_CLEAR(high_byte, 7); + high = (int)high_byte; + if (sign == 1) { + high = 0 - high; + } + /* Count low */ + low = (get_bit(low_byte, 7) * 500); + low += (get_bit(low_byte, 6) * 250); + low += (get_bit(low_byte, 5) * 125); + low += (get_bit(low_byte, 4) * 62); + low = (low / 100); + /* Integrate High and Low */ + return snprintf(buf_p, lmax, "%d.%d\n", high, low); +} + + +int +_common_count_voltage(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note]: + * Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts. Practical + * considerations to be defined by transceiver manufacturer will + * tend to limit the actual bounds of the supply voltage measurement. + * Accuracy is vendor specific but must be better than 3% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. Note that in some transceivers, transmitter supply + * voltage and receiver supply voltage are isolated. In that case, + * only one supply is monitored. Refer to the device specification + * for more detail. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 100 uV (1mV=1000uV) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 Volt */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_tx_bias(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 2 uA (1mA=1000uA) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total*2) / 1000); + val_f = (((total*2) - (val_i*1000)) / 100); + /* Return Unit: 1 mA */ + return snprintf(buf_p, lmax, "%d.%01d\n", val_i, val_f); +} + + +int +_common_count_tx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_rx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_wavelength(struct transvr_obj_s *self, + uint8_t high_byte, + uint8_t low_byte) { + /* [Note] + * SFP : uint 1 um. + * QSFP: unit 0.05 um. + */ + int total = 0; + + total = transform_word_to_int(high_byte, low_byte); + switch (self->type) { + case TRANSVR_TYPE_SFP: + return total; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + return (total/20); + + default: + break; + } + return ERR_TRANSVR_UNDEFINED; +} + + +int +common_get_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_id, + "common_get_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->id; +} + + +int +common_get_ext_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "common_get_ext_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->ext_id; +} + + +int +common_get_connector(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_connector, + "common_get_connector"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->connector; +} + + +int +common_get_vendor_name(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_name, + "common_get_vendor_name"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); +} + + +int +common_get_vendor_pn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_pn, + "common_get_vendor_pn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); +} + + +int +common_get_vendor_rev(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_rev, + "common_get_vendor_rev"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); +} + + +int +common_get_vendor_sn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_sn, + "common_get_vendor_sn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); +} + + +int +common_get_br(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return (int)self->br; + } + err = _check_by_mode(self, + &_common_update_attr_br, + "common_get_br"); + if (err < 0){ + return err; + } + /* Transform to INT to show error case */ + return (int)self->br; +} + + +int +common_get_len_smf(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_smf; + } + err = _check_by_mode(self, + &_common_update_attr_len_smf, + "common_get_len_smf"); + if (err < 0){ + return err; + } + return self->len_smf; +} + + +int +common_get_len_om1(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om1; + } + err = _check_by_mode(self, + &_common_update_attr_len_om1, + "common_get_len_om1"); + if (err < 0){ + return err; + } + return self->len_om1; +} + + +int +common_get_len_om2(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om2; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om2, + "common_get_len_om2"); + if (err < 0){ + return err; + } + return self->len_om2; +} + + +int +common_get_len_om3(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om3; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om3, + "common_get_len_om3"); + if (err < 0){ + return err; + } + return self->len_om3; +} + + +int +common_get_len_om4(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om4; + } + err = _check_by_mode(self, + &_common_update_attr_len_om4, + "common_get_len_om4"); + if (err < 0){ + return err; + } + return self->len_om4; +} + + +int +common_get_comp_extended(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp_ext, + "common_get_comp_extended"); + if (err_code < 0){ + return err_code; + } + return self->transvr_comp_ext; +} + + +int +common_get_comp_rev(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_comp_rev, + "common_get_comp_rev"); + if (err_code < 0){ + return err_code; + } + return self->comp_rev; +} + + +int +common_get_info(struct transvr_obj_s *self){ + + if (self->state != STATE_TRANSVR_CONNECTED) { + return self->state; + } + return self->info; +} + + +int +_common_get_if_lane(struct transvr_obj_s *self, + char *result){ + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_M_STR); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + memset(tmp_str, 0, LEN_TRANSVR_M_STR); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_M_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_M_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_M_STR); + } + if (i == 0) { + return EVENT_TRANSVR_TASK_FAIL; + } + return 0; +} + + +int +common_get_if_lane(struct transvr_obj_s *self, + char *buf_p){ + + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + if (self->ioexp_obj_p->state != STATE_IOEXP_NORMAL) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n", ERR_TRANSVR_ABNORMAL); + } + if (_common_get_if_lane(self, tmp_str) < 0) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n" ,ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%s\n" ,tmp_str); +} + + +int +sfp_get_len_sm(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_len_sm, + "sfp_get_len_sm"); + if (err_code < 0){ + return err_code; + } + return self->len_sm; +} + + +int +sfp_get_rate_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_rate_id, + "sfp_get_rate_id"); + if (err_code < 0){ + return err_code; + } + return self->rate_id; +} + + +int +sfp_get_soft_rs0(struct transvr_obj_s *self){ + /* Note: + * SFP Soft Rate_Select Select [aka. "RS(0)"] address + * A2h, offset: 110, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs0, + "sfp_get_soft_rs0"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs0 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_soft_rs1(struct transvr_obj_s *self){ + /* Note: + * SFP Soft RS(1) Select address + * A2h, offset: 118, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs1, + "sfp_get_soft_rs1"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs1 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_temp, + "sfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +sfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_voltage, + "sfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +sfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_bias, + "sfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _common_count_tx_bias(self->curr_tx_bias[0], + self->curr_tx_bias[1], + buf_p); +} + + +int +sfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_power, + "sfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_tx_power(self->curr_tx_power[0], + self->curr_tx_power[1], + buf_p); +} + + +int +sfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_rx_power, + "sfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_rx_power(self->curr_rx_power[0], + self->curr_rx_power[0], + buf_p); +} + + +int +sfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->rx_em[0]); +} + + +int +sfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->tx_eq[0]); +} + + +int +_sfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: A0h / 36 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +__sfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* SFP Specification Compliance: A0h / 3-10 + * transvr_comp[0-7] = 3 - 10 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_get_comp_10g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[0] = address A0h / 3 + * + * 3 7: 10G Base-ER + * 3 6: 10GBASE-LRM + * 3 5: 10GBASE-LR + * 3 4: 10GBASE-SR + */ + int bitmask = 0xf0; /* 11110000 */ + return (__sfp_get_comp_attr(self, 0) & bitmask); +} + + +int +_sfp_get_comp_1g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[3] = address A0h / 6 + * + * 6 7: BASE-PX *3 + * 6 6: BASE-BX10 *3 + * 6 5: 100BASE-FX + * 6 4: 100BASE-LX/LX10 + * 6 3: 1000BASE-T + * 6 2: 1000BASE-CX + * 6 1: 1000BASE-LX *3 + * 6 0: 1000BASE-SX + */ + return __sfp_get_comp_attr(self, 3); +} + + +int +_sfp_get_cable_tech(struct transvr_obj_s *self) { + /* transvr_comp[5] = address A0h / 8 + * + * 8 3: Active Cable *8 + * 8 2: Passive Cable *8 + */ + int bitmask = 0x0c; /* 00001100 */ + return (__sfp_get_comp_attr(self, 5) & bitmask); +} + + +int +sfp_get_comp_eth_1(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_1"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_1g_eth_comp(self); +} + + +int +sfp_get_comp_eth_10(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_10"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_10g_eth_comp(self); +} + + +int +_sfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: A0h / 2 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Note] Optical and Cable Variants Specification Compliance (SFF-8472) + * [Addr] A0h, Bytes 60-61 + * [Note] For optical variants, as defined by having zero's in A0h Byte 8 + * bits 2 and 3, Bytes 60 and 61 denote nominal transmitter output + * wavelength at room temperature. 16 bit value with byte 60 as high + * order byte and byte 61 as low order byte. The laser wavelength is + * equal to the 16 bit integer value in nm. This field allows the user + * to read the laser wavelength directly, so it is not necessary to + * infer it from the Transceiver Codes A0h Bytes 3 to 10 (see Table + * 5-3). This also allows specification of wavelengths not covered + * in the Transceiver Codes, such as those used in coarse WDM systems. + * + * For passive and active cable variants, a value of 00h for both A0h + * Byte 60 and Byte 61 denotes laser wavelength or cable specification + * compliance is unspecified. + */ + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +int +sfp_get_1g_rj45_extphy_offset(struct transvr_obj_s *self, char *buf) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%02x\n", self->extphy_offset); +} + + +int +sfp_get_1g_rj45_extphy_reg(struct transvr_obj_s *self, char *buf) { + + int i = 0; + int ret = 0; + int retry = 3; + int delay = 200; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; ii2c_client_p, self->extphy_offset); + if (ret >=0) { + goto ok_sfp_get_1g_rj45_extphy_reg; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; + +ok_sfp_get_1g_rj45_extphy_reg: + ret = ((ret & 0x00ff) << 8) | ((ret & 0xff00) >> 8); + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%04x\n", ret); +} + + +int +__qsfp_get_power_cls(struct transvr_obj_s *self, + int direct_access){ + + int err_code; + uint8_t detect_val; + + /* Detect and Update power class attribute */ + if (direct_access){ + err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_power_cls"); + } else { + err_code = self->ext_id; + } + if (err_code <0){ + return err_code; + } + if (err_code == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data */ + detect_val = self->ext_id; + SWP_BIT_CLEAR(detect_val, 2); /* Bit2: CDR RX present */ + SWP_BIT_CLEAR(detect_val, 3); /* Bit3: CDR TX present */ + SWP_BIT_CLEAR(detect_val, 4); /* Bit4: CLEI present */ + SWP_BIT_CLEAR(detect_val, 5); /* Bit5: reserved */ + /* Identify power class */ + switch (detect_val) { + case 0: /* Class_1: 00000000 */ + return 1; + case 64: /* Class_2: 01000000 */ + return 2; + case 128: /* Class_3: 10000000 */ + return 3; + case 192: /* Class_4: 11000000 */ + return 4; + case 1: /* Class_5: 00000001 */ + case 193: /* Class_5: 11000001 */ + return 5; + case 2: /* Class_6: 00000010 */ + case 194: /* Class_6: 11000010 */ + return 6; + case 3: /* Class_7: 00000011 */ + case 195: /* Class_7: 11000011 */ + return 7; + default: + break; + } + SWPS_INFO("%s: Detect undefined power class:%d\n", __func__, detect_val); + return ERR_TRANSVR_UNDEFINED; +} + + +int +qsfp_get_power_cls(struct transvr_obj_s *self) { + return __qsfp_get_power_cls(self, 1); +} + + +int +__qsfp_get_cdr_present(struct transvr_obj_s *self, + int direct_access){ + + int retval; + int BIT_SHIFT = 2; + int BIT_MASK = 0x3; + + /* Detect and Update power class attribute */ + if (direct_access) { + retval = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_cdr_present"); + if (retval < 0){ + return retval; + } + } + retval = self->ext_id; + if (retval == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data and return */ + return (int)(retval >> BIT_SHIFT & BIT_MASK); +} + + +int +qsfp_get_cdr_present(struct transvr_obj_s *self) { + return __qsfp_get_cdr_present(self, 1); +} + + +int +qsfp_get_cdr(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + "qsfp_get_cdr"); + if (err_code <0){ + return err_code; + } + + return self->cdr; +} + + +int +__qsfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* QSFP Specification Compliance: 00h / 131-138 + * transvr_comp[0-7] = 131 - 138 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_get_comp_10_40_100_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[0] = address 00h / 131 + * + * 131 7: Extended: See section 6.3.23. The Extended Specification Compliance + * Codes are maintained in the Transceiver Management section of SFF- + * 8024. + * 131 6: 10GBASE-LRM + * 131 5: 10GBASE-LR + * 131 4: 10GBASE-SR + * 131 3: 40GBASE-CR4 + * 131 2: 40GBASE-SR4 + * 131 1: 40GBASE-LR4 + * 131 0: 40G Active Cable (XLPPI) + */ + return __qsfp_get_comp_attr(self, 0); +} + + +int +_qsfp_get_comp_sonet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 132 7-3: Reserved + * 132 2: OC 48, long reach + * 132 1: OC 48, intermediate reach + * 132 0: OC 48 short reach + */ + return __qsfp_get_comp_attr(self, 1); +} + + +int +_qsfp_get_comp_sas_sata(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 133 7: SAS 24.0 Gb/s + * 133 6: SAS 12.0 Gb/s + * 133 5: SAS 6.0 Gb/s + * 133 4: SAS 3.0 Gb/s + * 133 3-0: Reserved + */ + return __qsfp_get_comp_attr(self, 2); +} + + +int +_qsfp_get_comp_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 134 7-4: Reserved + * 134 3: 1000BASE-T + * 134 2: 1000BASE-CX + * 134 1: 1000BASE-LX + * 134 0: 1000BASE-SX + */ + return __qsfp_get_comp_attr(self, 3); +} + + +int +_qsfp_get_comp_fc_link_length(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 7: Very long distance (V) + * 135 6: Short distance (S) + * 135 5: Intermediate distance (I) + * 135 4: Long distance (L) + * 135 3: Medium (M) + */ + int mask = 0xFC; /* 11111100 */ + return (__qsfp_get_comp_attr(self, 4) & mask); +} + + +int +_qsfp_get_comp_fc_trans_tech(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 2: Reserved + * 135 1: Longwave laser (LC) + * 135 0: Electrical inter-enclosure (EL) + * + * 136 7: Electrical intra-enclosure + * 136 6: Shortwave laser w/o OFC (SN) + * 136 5: Shortwave laser w OFC (SL) + * 136 4: Longwave Laser (LL) + * 136 3-0: Reserved + * + * return value = [bit 8-15:addr 135][bit 0-7:addr 136] + */ + int mask_135 = 7; /* 00000111 */ + int val_135 = (__qsfp_get_comp_attr(self, 4) & mask_135); + int val_136 = __qsfp_get_comp_attr(self, 5); + return ((val_135 << 7) + val_136); +} + + +int +_qsfp_get_comp_fc_trans_media(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 137 7: Twin Axial Pair (TW) + * 137 6: Shielded Twisted Pair (TP) + * 137 5: Miniature Coax (MI) + * 137 4: Video Coax (TV) + * 137 3: Multi-mode 62.5 m (M6) + * 137 2: Multi-mode 50 m (M5) + * 137 1: Multi-mode 50 um (OM3) + * 137 0: Single Mode (SM) + */ + return __qsfp_get_comp_attr(self, 6); +} + + +int +_qsfp_get_comp_fc_speed(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 138 7: 1200 MBps (per channel) + * 138 6: 800 MBps + * 138 5: 1600 MBps (per channel) + * 138 4: 400 MBps + * 138 3: 3200 MBps (per channel) + * 138 2: 200 MBps + * 138 1: Extended: See section 6.3.23. The Extended Specification + * Compliance Codes are maintained in the Transceiver Management + * section of SFF-8024. + * 138 0: 100 MBps + */ + return __qsfp_get_comp_attr(self, 7); +} + + +int +_qsfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: 00h / 192 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_comp_eth(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_eth"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_ethernet(self); +} + + +int +qsfp_get_comp_10_40(struct transvr_obj_s *self) { + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_10_40"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_10_40_100_ethernet(self); +} + + +int +_qsfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: 00h / 130 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_temp, + "qsfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +qsfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_voltage, + "qsfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +qsfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->tx_eq[0], self->tx_eq[1]); +} + + +int +qsfp_get_transvr_rx_am(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_get_transvr_rx_am"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_am[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_am[0], self->rx_am[1]); +} + + +int +qsfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_em[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_em[0], self->rx_em[1]); +} + + +int +_qsfp_get_channel_diag(uint8_t *data_array, + int (*count_func)(uint8_t high_byte, uint8_t low_byte, char *buf_p), + char *ch_name, + char *result_p) { + int i, high, low; + int len_max = 128; + char ch_buf[4][16] = { DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL }; + + for (i=0; i<4; i++) { + high = (i*2); + low = ((i*2) + 1); + count_func(data_array[high], data_array[low], ch_buf[i]); + } + return snprintf(result_p, len_max, + "%s-%d:%s%s-%d:%s%s-%d:%s%s-%d:%s", + ch_name, 1, ch_buf[0], + ch_name, 2, ch_buf[1], + ch_name, 3, ch_buf[2], + ch_name, 4, ch_buf[3]); +} + + +int +qsfp_get_soft_rx_los(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_rx_los, + "qsfp_get_soft_rx_los"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->rx_los & mask)); +} + + +int +qsfp_get_soft_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_get_soft_tx_disable"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_disable & mask)); +} + + +int +qsfp_get_soft_tx_fault(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_fault, + "qsfp_get_soft_tx_fault"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_fault & mask)); +} + + +int +qsfp_get_auto_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + if (self->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "%d\n", ERR_TRANSVR_FUNC_DISABLE); + } + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "0x%02x\n", self->auto_tx_disable); +} + + +int +qsfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_bias, + "qsfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _qsfp_get_channel_diag(self->curr_tx_bias, + _common_count_tx_bias, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_power, + "qsfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_tx_power, + _common_count_tx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "RX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_rx_power, + "qsfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_rx_power, + _common_count_rx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Desc] Wavelength or Copper Cable Attenuation (SFF-8636) + * [Addr] 00h 186-187 + * [Note] + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is + * a 16-bit hex value with Byte 186 as high order byte and Byte 187 as + * low order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. + * If the free side device is identified as copper cable these registers will + * be used to define the cable attenuation. An indication of 0 dB attenuation + * refers to the case where the attenuation is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +/* Public Function for Setup Features + */ +static int +__sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + uint8_t update_val = (*attr_p); + + switch (input_val) { + case 0: + SWP_BIT_CLEAR(update_val, bit_shift); + break; + case 1: + SWP_BIT_SET(update_val, bit_shift); + break; + default: + retval = ERR_TRANSVR_UNEXCPT; + err_code = ERR_TRANSVR_UNEXCPT; + err_msg = "Exception occurs"; + goto err_private_sfp_set_soft_rs_1; + } + err_code = _common_set_uint8_attr(self, + address, + page, + offset, + update_val, + attr_p, + caller, + show_err); + if (err_code < 0) { + retval = err_code; + err_msg = "Write data via i2c fail!"; + goto err_private_sfp_set_soft_rs_1; + } + (*attr_p) = update_val; + return 0; + +err_private_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +static int +_sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + /* Check input value */ + if ((input_val != 0) && (input_val != 1)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + switch (err_code) { + case 0: + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "Not support this feature"; + break; + case ERR_TRANSVR_UNINIT: + retval = ERR_TRANSVR_UNINIT; + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + retval = ERR_TRANSVR_UNPLUGGED; + err_msg = "Transceiver unplugged!"; + break; + default: + retval = err_code; + err_msg = "Check Rate_ID fail!"; + break; + } + goto err_common_sfp_set_soft_rs_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + attr_update_func, + caller); + if ( (err_code < 0) || + ((*attr_p) == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Generate and update value */ + return __sfp_set_soft_rs(self, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + +err_common_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +sfp_set_soft_rs0(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(0)"] address + * A2h, offset: 110, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + bit_shift, + &_sfp_update_attr_soft_rs0, + &(self->soft_rs0), + "sfp_set_soft_rs0", + show_err); +} + + +int +sfp_set_soft_rs1(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(1)"] address + * A2h, offset: 118, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + bit_shift, + &_sfp_update_attr_soft_rs1, + &(self->soft_rs1), + "sfp_set_soft_rs1", + show_err); +} + + +int +__sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_tx_eq; + } + setv = (uint8_t)input; + if (self->tx_eq[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + setv, + &(self->tx_eq[0]), + "_sfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_tx_eq; + } + return 0; + +err_sfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; itx_eq[0]; + if (_sfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if (self->tx_eq[0] == tmp){ + return 0; + } + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +sfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_tx_eq(self, input, 1); +} + + +int +__sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_rx_em; + } + setv = (uint8_t)input; + if (self->rx_em[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + setv, + &(self->rx_em[0]), + "_sfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_rx_em; + } + return 0; + +err_sfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; irx_em[0]; + if (_sfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if (self->rx_em[0] == tmp){ + return 0; + } + } + return -1; +} + + +int +sfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_rx_em(self, input, 1); +} + + +int +sfp_set_1g_rj45_extphy_offset(struct transvr_obj_s *self, + int input) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xff)) { + return ERR_TRANSVR_BADINPUT; + } + self->extphy_offset = (uint8_t)input; + return 0; +} + + +int +sfp_set_1g_rj45_extphy_reg(struct transvr_obj_s *self, + int input) { + + int i = 0; + int retry = 3; + int delay = 200; + uint16_t tmp = 0; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xffff)) { + return ERR_TRANSVR_BADINPUT; + } + tmp = ((input & 0x00ff) << 8) | ((input & 0xff00) >> 8); + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; i<=retry; i++) { + if (i2c_smbus_write_word_data(self->i2c_client_p, + self->extphy_offset, + tmp) >= 0) { + return 0; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; +} + + +static int +__qsfp_set_cdr(struct transvr_obj_s *self, + int input_val, + int show_err) { + + uint8_t update_val; + int CDR_FEATURE_SUPPORTED = 0x3; + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_name = "__qsfp_set_cdr"; + + /* Check input value */ + if ((input_val < 0) || (input_val > 0xff)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_qsfp_set_cdr_1; + } + update_val = (uint8_t)input_val; + /* Check CDR supported by transceiver */ + err_code = qsfp_get_cdr_present(self); + if (err_code < 0) { + retval = err_code; + switch (err_code) { + case ERR_TRANSVR_UNINIT: + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + err_msg = "Transceiver unplugged!"; + break; + default: + err_msg = "Check CDR present fail!"; + break; + } + goto err_qsfp_set_cdr_1; + } + if (err_code != CDR_FEATURE_SUPPORTED) { + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "This transceiver not support CDR!"; + goto err_qsfp_set_cdr_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + func_name); + if ( (err_code < 0) || + (self->cdr == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_qsfp_set_cdr_1; + } + /* Write input value to transceiver */ + return _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + update_val, + &(self->cdr), + func_name, + show_err); + +err_qsfp_set_cdr_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +qsfp_set_cdr(struct transvr_obj_s *self, + int input_val) { + return __qsfp_set_cdr(self, input_val, 1); +} + + +int +qsfp_set_soft_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int show_err = 1; + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + int update_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_soft_tx_disable"); + if (retval < 0) { + snprintf(err_msg, 63, "Not ready. err:%d", retval); + goto err_qsfp_set_soft_tx_disable; + } + if ((input_val > in_max) || + (input_val < in_min) ){ + retval = ERR_TRANSVR_BADINPUT; + snprintf(err_msg, 63, "Input value:%d incorrect!", input_val); + goto err_qsfp_set_soft_tx_disable; + } + if ((self->tx_disable & 0x0f) == input_val) { + return 0; + } + update_val = ((self->tx_disable & 0xf0) & input_val); + retval = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + input_val, + &(self->tx_disable), + "qsfp_set_tx_disable", + show_err); + if (retval < 0) { + snprintf(err_msg, 63, "_common_set_uint8_attr:%d fail!", retval); + goto err_qsfp_set_soft_tx_disable; + } + return 0; + +err_qsfp_set_soft_tx_disable: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return retval; +} + + +int +_qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + uint8_t update) { + + uint8_t tx_enable = 0x0; + int show_e = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Handle timing issues */ + if (update != tx_enable) { + /* Note: + * Because there are some txvr has timing issues, + * therefore we need to execute reset cycle first. + * (enable -> other settings) + */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + tx_enable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set reset value fail"; + goto err_qsfp_set_auto_tx_disable; + } + mdelay(10); + } + /* Setup target value */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->auto_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set target value fail"; + goto err_qsfp_set_auto_tx_disable; + } + /* Check and update */ + err = _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C get value fail"; + goto err_qsfp_set_auto_tx_disable; + } + if (self->tx_disable != update) { + emsg = "data not become effective"; + goto err_qsfp_set_auto_tx_disable; + } + return 0; + +err_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s\n", + __func__, emsg, self->swp_name); + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Update settings*/ + if (input_val == VAL_TRANSVR_FUNCTION_DISABLE) { + emsg = "User disable auto tx_disable"; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + goto out_qsfp_set_auto_tx_disable; + } + if ((input_val > in_max) || (input_val < in_min) ){ + SWPS_INFO("%s: Input value:%d incorrect! :%s\n", + __func__, input_val, self->swp_name); + return ERR_TRANSVR_BADINPUT; + } + self->auto_tx_disable = input_val; + /* Check current soft tx_disable */ + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_auto_tx_disable"); + switch (retval) { + case 0: + break; + case ERR_TRANSVR_UNPLUGGED: + emsg = "Doesn't need to update"; + goto out_qsfp_set_auto_tx_disable; + default: + SWPS_INFO("%s: setup fail :%d :%s\n", + __func__, retval, self->swp_name); + return retval; + } + return _qsfp_set_auto_tx_disable(self, input_val); + +out_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s :%d\n :%d", + __func__, emsg, self->swp_name, input_val, retval); + return 0; +} + + +int +__qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_tx_eq; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->tx_eq[0] == setv[0]) && + (self->tx_eq[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + setv, + self->tx_eq, + "_qsfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_tx_eq; + } + return 0; + +err_qsfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; itx_eq[0]; + tmp[1] = self->tx_eq[1]; + if (_qsfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if ((self->tx_eq[0] == tmp[0]) && + (self->tx_eq[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_tx_eq(self, input, 1); +} + + +int +__qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_am; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_am[0] == setv[0]) && + (self->rx_am[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + setv, + self->rx_am, + "_qsfp_set_rx_am", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_am; + } + return 0; + +err_qsfp_set_rx_am: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_am[0]; + tmp[1] = self->rx_am[1]; + if (_qsfp_update_attr_rx_am(self, show_e) < 0){ + continue; + } + if ((self->rx_am[0] == tmp[0]) && + (self->rx_am[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_am(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_set_rx_am"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_am(self, input, 1); +} + + +int +__qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_em; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_em[0] == setv[0]) && + (self->rx_em[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + setv, + self->rx_em, + "_qsfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_em; + } + return 0; + +err_qsfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_em[0]; + tmp[1] = self->rx_em[1]; + if (_qsfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if ((self->rx_em[0] == tmp[0]) && + (self->rx_em[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_em(self, input, 1); +} + + +int +common_transvr_dump(struct transvr_obj_s* self){ + + char *type_name = "Undefined"; + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + switch (self->type) { + case TRANSVR_TYPE_SFP: + type_name = STR_TRANSVR_SFP; + break; + case TRANSVR_TYPE_QSFP: + type_name = STR_TRANSVR_QSFP; + break; + case TRANSVR_TYPE_QSFP_PLUS: + type_name = STR_TRANSVR_QSFP_PLUS; + break; + case TRANSVR_TYPE_QSFP_28: + type_name = STR_TRANSVR_QSFP28; + break; + case TRANSVR_TYPE_FAKE: + type_name = "FAKE"; + goto ok_common_transvr_dump; + case TRANSVR_TYPE_UNPLUGGED: + type_name = "UNPLUGGED"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_INCONSISTENT: + type_name = "INCONSISTENT"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_ERROR: + type_name = "ERROR"; + goto err_common_transvr_dump; + + default: + type_name = "UNEXPECTED"; + goto err_common_transvr_dump; + } + printk(KERN_INFO "[SWPS] Dump %s information:\n", self->swp_name); + printk(KERN_INFO " |- :%s\n", type_name); + printk(KERN_INFO " |- :%s\n", self->vendor_name); + printk(KERN_INFO " |- :%s\n", self->vendor_pn); + printk(KERN_INFO " |- :%s\n", self->vendor_rev); + printk(KERN_INFO " |- :%s\n", self->vendor_sn); + printk(KERN_INFO " |- :0x%02x\n", self->br); + printk(KERN_INFO " |- :0x%02x\n", self->comp_rev); + printk(KERN_INFO " |- :%d\n", self->len_om1); + printk(KERN_INFO " |- :%d\n", self->len_om2); + printk(KERN_INFO " |- :%d\n", self->len_om3); + printk(KERN_INFO " |- :%d\n", self->len_om4); + return 0; + +ok_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return 0; + +err_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return -1; +} + + +int +sfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_sm); + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :0x%02x\n", self->rate_id); + return 0; +} + + +int +qsfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :Class_%d\n", __qsfp_get_power_cls(self, 0)); + return 0; +} + + +int +fake_transvr_dump(struct transvr_obj_s* self) { + + printk(KERN_INFO "[SWPS] Dump transceiver information: %s\n", self->swp_name); + printk(KERN_INFO " |- :FAKE\n"); + printk(KERN_INFO " |- :FAKE_VENDER_NAME\n"); + printk(KERN_INFO " |- :FAKE_VENDER_PN\n"); + printk(KERN_INFO " |- :FAKE_VENDER_REV\n"); + printk(KERN_INFO " |- :FAKE_VENDER_SN\n"); + printk(KERN_INFO " |- :0x99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " '- :0x99\n"); + return 0; +} + + +/* ========== Object functions for fake type ========== + */ +int +fake_transvr_update(struct transvr_obj_s *self, + int show_err){ + self->state = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +fake_get_binary(struct transvr_obj_s *self){ + return 1; +} + +int +fake_get_int(struct transvr_obj_s *self){ + return 99; +} + + +int +fake_get_hex(struct transvr_obj_s *self){ + return 0x0f; +} + + +int +fake_get_str(struct transvr_obj_s *self, char *buf) { + return snprintf(buf, 16, "fake_get_str\n"); +} + + +int +fake_set_int(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: %d\n", __func__, input); + return 0; +} + + +int +fake_set_hex(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: 0x%02x\n", __func__, input); + return 0; +} + + +/* ========== Object functions for unsupported ========== + */ +int +unsupported_get_func(struct transvr_obj_s *self){ + return ERR_TRANSVR_NOTSUPPORT; +} + + +int +unsupported_get_func2(struct transvr_obj_s *self, + char *buf_p) { + int len = snprintf(buf_p, 8, "%d\n", ERR_TRANSVR_NOTSUPPORT); + return len; +} + + +int +unsupported_set_func(struct transvr_obj_s *self, + int input_val){ + return ERR_TRANSVR_NOTSUPPORT; +} + + + +/* ========== Object functions for long term task ========== + * + * [Note] + * SWPS transceiver worker is likely the green-thread (coroutine). + * Due to resource and performance considerations. SWPS run all + * features in one kthread at the same time, and handle by it self. + */ + +/* For Transceiver Task Handling + */ +static struct transvr_worker_s * +transvr_task_get(struct transvr_obj_s *self, + char *func_name) { + + struct transvr_worker_s *curr_p = self->worker_p; + + while(curr_p != NULL){ + if (strcmp((curr_p->func_name), func_name) == 0 ) { + return curr_p; + } + curr_p = curr_p->next_p; + } + return NULL; +} + + +static struct transvr_worker_s* +transvr_task_creat(struct transvr_obj_s *self, + int (*main_task)(struct transvr_worker_s *task), + int (*post_task)(struct transvr_worker_s *task), + char *caller) { + + struct transvr_worker_s *task_p = NULL; + struct transvr_worker_s *curr_p = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check task not exist */ + task_p = transvr_task_get(self, caller); + if (task_p) { + snprintf(err_msg, sizeof(err_msg), "Task already created!"); + goto err_transvr_task_creat; + } + /* Create task worker */ + task_p = kzalloc(sizeof(struct transvr_worker_s), GFP_KERNEL); + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_transvr_task_creat; + } + /* Setup task data */ + task_p->transvr_p = self; + task_p->next_p = NULL; + task_p->trigger_time = 0; + task_p->retry = 1; + task_p->state = STATE_T_TASK_INIT; + task_p->main_task = main_task; + task_p->post_task = post_task; + task_p->p_data = NULL; + snprintf(task_p->func_name, sizeof(task_p->func_name), "%s", caller); + /* Setup Link List */ + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p->next_p != NULL) { + curr_p = curr_p->next_p; + } + curr_p->next_p = task_p; + task_p->pre_p = curr_p; + } else { + self->worker_p = task_p; + task_p->pre_p = NULL; + } + return task_p; + +err_transvr_task_creat: + SWPS_ERR("%s: %s :%s :%s\n", + __func__, err_msg, caller, self->swp_name); + return NULL; +} + + +static void +transvr_task_free_one(struct transvr_worker_s *task_p){ + + struct transvr_worker_s *pre_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (task_p) { + pre_p = task_p->pre_p; + next_p = task_p->next_p; + + if ((pre_p) && (next_p)) { + pre_p->next_p = next_p; + next_p->pre_p = pre_p; + + } else if ((!pre_p) && (next_p)) { + next_p->pre_p = NULL; + + } else if ((pre_p) && (!next_p)) { + pre_p->next_p = NULL; + + } else if ((!pre_p) && (!next_p)) { + task_p->transvr_p->worker_p = NULL; + } else { + SWPS_ERR("%s: Unexcept case!\n :%s", + __func__, task_p->transvr_p->swp_name); + } + kfree(task_p->p_data); + kfree(task_p); + } +} + + +static void +transvr_task_free_all(struct transvr_obj_s *self) { + + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p) { + next_p = curr_p->next_p; + transvr_task_free_one(curr_p); + curr_p = next_p; + } + self->worker_p = NULL; + } +} + + +static void +transvr_cache_free_all(struct transvr_obj_s *self) { + + memset(self->vendor_name, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_rev, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_pn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_sn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + self->extphy_offset = 0; +} + +static int +_transvr_task_run_main(struct transvr_worker_s *task_p) { + + int retval = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "main_task is NULL!"); + goto main_transvr_task_err; + } + if ((task_p->trigger_time) == 0){ + goto main_transvr_task_run; + } + if (time_before(jiffies, task_p->trigger_time)){ + goto main_transvr_task_wait; + } + goto main_transvr_task_run; + +main_transvr_task_run: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + task_p->retry -= 1; + } + retval = task_p->main_task(task_p); + if (retval < 0) { + if (task_p->retry > 0) { + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + } + goto main_transvr_task_identify; + +main_transvr_task_identify: + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + + case EVENT_TRANSVR_TASK_DONE: + task_p->state = STATE_T_TASK_DONE; + return EVENT_TRANSVR_TASK_DONE; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + +main_transvr_task_wait: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + +main_transvr_task_err: + task_p->state = STATE_T_TASK_FAIL; + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, retval, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_transvr_task_run_post(struct transvr_worker_s *task_p) { + + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if ((task_p->post_task) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + switch (task_p->state) { + case STATE_T_TASK_WAIT: + case STATE_T_TASK_INIT: + goto post_transvr_task_wait; + + case STATE_T_TASK_DONE: + case STATE_T_TASK_FAIL: + goto post_transvr_task_run; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Unexcept task state"); + goto post_transvr_task_err; + +post_transvr_task_run: + task_p->post_task(task_p); + return EVENT_TRANSVR_TASK_DONE; + +post_transvr_task_wait: + return EVENT_TRANSVR_TASK_WAIT; + +post_transvr_task_err: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, task_p->state, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_one(struct transvr_worker_s *task_p) { + + int retval_main = DEBUG_TRANSVR_INT_VAL; + int retval_post = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval_main = _transvr_task_run_main(task_p); + if (retval_main < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute main_task fail!"); + goto err_transvr_task_run_one; + } + retval_post = _transvr_task_run_post(task_p); + if (retval_post < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute post_task fail!"); + goto err_transvr_task_run_one; + } + return retval_main; + +err_transvr_task_run_one: + SWPS_INFO("%s: %s
:%d :%d :%s :%s\n", + __func__, err_msg, retval_main, retval_post, + task_p->func_name, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_all(struct transvr_obj_s *self) { + + int haserr = 0; + int retval = DEBUG_TRANSVR_INT_VAL; + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if ((self->worker_p) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + curr_p = self->worker_p; + while (curr_p != NULL) { + next_p = curr_p->next_p; + retval = transvr_task_run_one(curr_p); + if (curr_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + curr_p = next_p; + continue; + } + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + break; + case EVENT_TRANSVR_TASK_DONE: + transvr_task_free_one(curr_p); + break; + case EVENT_TRANSVR_TASK_FAIL: + + default: + haserr = 1; + transvr_task_free_one(curr_p); + break; + } + curr_p = next_p; + } + if (haserr) { + return EVENT_TRANSVR_TASK_FAIL; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +static void +transvr_task_set_delay(struct transvr_worker_s *task_p, + unsigned long delay_msec) { + + task_p->trigger_time = (jiffies + (delay_msec * (HZ/1000))); +} + + +static void +transvr_task_set_retry(struct transvr_worker_s *task_p, + unsigned long retry_times) { + + task_p->retry = retry_times; +} + + +/* For Transceiver Post Task + */ +int +taskfunc_post_do_nothing(struct transvr_worker_s *task_p) { + + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_post_handle_task_state(struct transvr_worker_s *task_p) { + + struct transvr_obj_s* tp = task_p->transvr_p; + + switch (task_p->state) { + case STATE_T_TASK_INIT: + case STATE_T_TASK_WAIT: + return EVENT_TRANSVR_TASK_WAIT; + + case STATE_T_TASK_DONE: + tp->state = STATE_TRANSVR_CONNECTED; + tp->send_uevent(tp, KOBJ_ADD); + return EVENT_TRANSVR_TASK_DONE; + + case STATE_T_TASK_FAIL: + tp->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_TASK_FAIL; + + default: + break; + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +/* For Transceiver Main Task + */ +int +_taskfunc_sfp_setup_soft_rs(struct transvr_worker_s *task_p, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller) { + + int show_err = 0; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_soft_rs"; + + err_code = _sfp_update_attr_soft_rs0(task_p->transvr_p, 0); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + err_code = __sfp_set_soft_rs(task_p->transvr_p, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_setup_soft_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_code); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +__taskfunc_sfp_setup_hard_rs(struct transvr_worker_s *task_p, + int input_val, + int (*get_func)(struct ioexp_obj_s *self, int virt_offset), + int (*set_func)(struct ioexp_obj_s *self, int virt_offset, int input_val)) { + + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + + err_val = get_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset); + + if (err_val < 0) { + if (err_val == ERR_IOEXP_NOTSUPPORT) { + return EVENT_TRANSVR_TASK_DONE; + } + err_str = "Get current hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + if (err_val == input_val) { + return EVENT_TRANSVR_TASK_DONE; + } + err_val = set_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_p_taskfunc_sfp_setup_hard_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_hard_rs0(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs0, + task_p->transvr_p->ioexp_obj_p->set_hard_rs0); +} + + +int +_taskfunc_sfp_setup_hard_rs1(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs1, + task_p->transvr_p->ioexp_obj_p->set_hard_rs1); +} + + +int +_taskfunc_sfp_setup_rs0(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs0"; + + err_val = _taskfunc_sfp_setup_hard_rs0(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs0, + task_p->transvr_p->eeprom_map_p->page_soft_rs0, + task_p->transvr_p->eeprom_map_p->offset_soft_rs0, + bit_shift, + &(task_p->transvr_p->soft_rs0), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs0_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs0(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_rs1(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs1"; + + err_val = _taskfunc_sfp_setup_hard_rs1(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs1, + task_p->transvr_p->eeprom_map_p->page_soft_rs1, + task_p->transvr_p->eeprom_map_p->offset_soft_rs1, + bit_shift, + &(task_p->transvr_p->soft_rs1), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs1_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs1(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_sfp_setup_SFF8431_case1(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs0(task_p, update_val); +} + + + +int +taskfunc_sfp_setup_SFF8431_case2(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs1(task_p, update_val); +} + + +int +taskfunc_sfp_setup_SFF8431_case3(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + int update_rs0 = 1; + int update_rs1 = 1; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _taskfunc_sfp_setup_rs0(task_p, update_rs0); + if (err_code < 0) { + return err_code; + } + return _taskfunc_sfp_setup_rs1(task_p, update_rs1); +} + + +int +taskfunc_sfp_handle_1g_rj45(struct transvr_worker_s *task_p) { + + /* Not all of platform support 0x56 for transceiver + * external PHY, Support list as below: + * => 1. Magnolia-PVT (PS: EVT & DVT not ready) + */ + int ext_phy_addr = 0x56; + int ext_phy_page = -1; + int ext_phy_offs = 0x11; + int ext_phy_len = 1; + int lstate_mask = 0x04; /* 00000100 */ + int show_err = 0; + int fail_retry = 5; + int fail_delay = 1000; /* msec */ + int err_code = DEBUG_TRANSVR_INT_VAL; + uint8_t detect_val = DEBUG_TRANSVR_HEX_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + int *tmp_p = NULL; + char *func_name = "taskfunc_sfp_handle_1g_rj45"; + + if (task_p->transvr_p->state != STATE_TRANSVR_CONNECTED) { + return EVENT_TRANSVR_TASK_DONE; + } + if ( (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000) && + (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000_up) ) { + goto err_taskfunc_sfp_handle_1g_rj45_1; + } + err_code = _common_update_uint8_attr(task_p->transvr_p, + ext_phy_addr, + ext_phy_page, + ext_phy_offs, + ext_phy_len, + &detect_val, + func_name, + show_err); + if ( (err_code < 0) || + (detect_val == DEBUG_TRANSVR_HEX_VAL) ) { + snprintf(err_str, sizeof(err_str), "Detect external link status fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + if ((detect_val & lstate_mask) == lstate_mask) { + goto ok_taskfunc_sfp_handle_1g_rj45_link_up; + } + goto ok_taskfunc_sfp_handle_1g_rj45_link_down; + +ok_taskfunc_sfp_handle_1g_rj45_link_up: + /* Filter out noise */ + if (!(task_p->p_data)) { + tmp_p = kzalloc(sizeof(int), GFP_KERNEL); + if (!tmp_p) { + snprintf(err_str, sizeof(err_str), "kzalloc p_data fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + *tmp_p = TRANSVR_CLASS_BASE_T_1000_up; + task_p->p_data = tmp_p; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + } + if ((*(int *)(task_p->p_data)) != TRANSVR_CLASS_BASE_T_1000_up) { + kfree(task_p->p_data); + task_p->p_data = NULL; + snprintf(err_str, sizeof(err_str), "Internal error"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + kfree(task_p->p_data); + task_p->p_data = NULL; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_link_down: + if (task_p->p_data) { + kfree(task_p->p_data); + task_p->p_data = NULL; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_done: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_1: + snprintf(err_str, sizeof(err_str), "Detect transceiver:%d not Base-T, remove task.", + task_p->transvr_p->info); + SWPS_INFO("%s: %s :%s\n", __func__, err_str, task_p->transvr_p->swp_name); + transvr_task_set_retry(task_p, 0); + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_2: + if (task_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, fail_retry); + } + if ((task_p->retry) == 0) { + /* Error case: + * => In this case, SWPS will stop external Link state monitor features + * and keeps transvr_p->info on TRANSVR_CLASS_BASE_T_1000_up. + * Upper layer will see it always Linkup that because of these type of + * transceiver has external phy, BCM chip see it as Loopback transceiver. + */ + SWPS_WARN("%s can not access external PHY of Base-T SFP transceiver\n", + task_p->transvr_p->swp_name); + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + return EVENT_TRANSVR_TASK_DONE; + } else { + transvr_task_set_delay(task_p, fail_delay); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self, + int setup_val) { + + int curr_val = DEBUG_TRANSVR_INT_VAL; + int err_val = DEBUG_TRANSVR_INT_VAL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset); + if (curr_val < 0){ + err_msg = "Get current value fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + if (curr_val == setup_val){ + return EVENT_TRANSVR_TASK_DONE; + } + err_val = self->ioexp_obj_p->set_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset, + setup_val); + if (err_val < 0){ + err_msg = "Setup power mode fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_qsfp_setup_power_mod_1: + SWPS_INFO("%s: %s :%d :%d :%d\n", + __func__, err_msg, err_val, curr_val, setup_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_qsfp_handle_tx_disable(struct transvr_worker_s *task_p) { + + int i = 0; + int retry = 5; + int delay_ms = 100; + + if (task_p->transvr_p->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return EVENT_TRANSVR_TASK_DONE; + } + if (!_qsfp_is_implement_tx_disable(task_p->transvr_p)) { + return EVENT_TRANSVR_TASK_DONE; + } + for (i=0; itransvr_p, + task_p->transvr_p->auto_tx_disable) + == EVENT_TRANSVR_TASK_DONE) { + goto ok_taskfunc_qsfp_handle_tx_disable; + } + mdelay(delay_ms); + } + SWPS_INFO("%s auto setup tx_disable:0x%02x fail.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_INIT_FAIL; + +ok_taskfunc_qsfp_handle_tx_disable: + SWPS_INFO("%s auto setup tx_disable:0x%02x ok.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_qsfp_set_hpmod(struct transvr_worker_s *task_p) { + + int err = DEBUG_TRANSVR_INT_VAL; + int HIGH_POWER_MODE = 0; + + /* Handle power mode */ + err = _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + HIGH_POWER_MODE); + if (err < 0) { + SWPS_INFO("%s: setup hpmod fail :%d :%s\n", + __func__, err, task_p->transvr_p->swp_name); + return err; + } + /* Handle auto tx_disable + * [Note] + * => Because there are some transceiver have timing issues or + * setup sequence issues, therefore we handle auto tx_disable + * after handle power mode. + */ + mdelay(100); + return taskfunc_qsfp_handle_tx_disable(task_p); +} + + +int +taskfunc_qsfp_set_lpmod(struct transvr_worker_s *task_p) { + + int LOW_POWER_MODE = 1; + return _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + LOW_POWER_MODE); +} + + +static int +initfunc_sfp_handle_multi_rate_mode(struct transvr_obj_s *self) { + + int task_retry = 3; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "sfp_handle_multi_rate_mode"; + struct transvr_worker_s *task_p = NULL; + + switch (self->rate_id) { + case 0x00: /* Unspecified */ + case 0x03: /* Unspecified */ + case 0x05: /* Unspecified */ + case 0x07: /* Unspecified */ + case 0x09: /* Unspecified */ + case 0x0B: /* Unspecified */ + case 0x0D: /* Unspecified */ + case 0x0F: /* Unspecified */ + goto sfp_handle_multi_rate_mode_4_unspecified; + + case 0x02: /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case1, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x04: /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case2, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x06: /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case3, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x01: /* SFF-8079 (4/2/1G Rate_Select & AS0/AS1) */ + err_str = "SFF-8079 (4/2/1G Rate_Select & AS0/AS1)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x08: /* FC-PI-5 (16/8/4G Rx Rate_select only) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Rx Rate_select only)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0A: /* FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0C: /* FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + */ + err_str = "FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0E: /* 10/8G Rx and Tx Rate_Select controlling the operation or + * locking modes of the internal signal conditioner, retimer + * or CDR, according to the logic table defined in Table 10-2, + * High Bit Rate (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = + * 8.5 Gb/s. In this mode, the default value of bit 110.3 (Soft + * Rate Select RS(0), Table 9-11) and of bit 118.3 (Soft Rate + * Select RS(1), Table 10-1) is 1. + */ + err_str = "cable type: 0x0E"; + goto sfp_handle_multi_rate_mode_4_not_support; + + default: + err_str = "cable type: UNKNOW"; + goto sfp_handle_multi_rate_mode_4_not_support; + } + +sfp_handle_multi_rate_mode_4_sff8431: + if (!task_p) { + err_str = "Create task fail!"; + goto sfp_handle_multi_rate_mode_4_fail_1; + } + transvr_task_set_retry(task_p, task_retry); + return EVENT_TRANSVR_TASK_WAIT; + +sfp_handle_multi_rate_mode_4_unspecified: + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_not_support: + SWPS_INFO("%s: Does not support %s :%s :0x%02x\n", + func_str, err_str, self->swp_name, self->rate_id); + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_fail_1: + SWPS_INFO("%s: %s :%s :0x%02x, :%d\n", + func_str, err_str, self->swp_name, self->rate_id, err_code); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +initfunc_sfp_handle_1g_rj45(struct transvr_obj_s *self) { + + struct transvr_worker_s *task_p = NULL; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_sfp_handle_1g_rj45"; + + + if (self->info == TRANSVR_CLASS_BASE_T_1000) { + task_p = transvr_task_creat(self, + taskfunc_sfp_handle_1g_rj45, + taskfunc_post_do_nothing, + func_str); + if (!task_p) { + snprintf(err_str, sizeof(err_str), "Create task fail"); + goto err_initfunc_sfp_handle_1g_rj45; + } + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_initfunc_sfp_handle_1g_rj45: + SWPS_INFO("%s: %s :%s :%d\n", + __func__, err_str, self->swp_name, detect_cls); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +initfunc_qsfp_handle_power_mode(struct transvr_obj_s *self) { + + int err_code = EVENT_TRANSVR_EXCEP_INIT; + int power_class = DEBUG_TRANSVR_INT_VAL; + int hpmod_retry = 3; + int lpower_config = 1; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + unsigned long hpmod_delay = 500; /* msec */ + struct transvr_worker_s *task_p = NULL; + + /* Handle power mode for IOEXP */ + power_class = __qsfp_get_power_cls(self, 0); + switch (power_class) { + case 1: /* Case: Low power mode (Class = 1) */ + err_code = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (err_code < 0){ + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + return EVENT_TRANSVR_TASK_DONE; + + case 2: /* Case: High power mode (Class > 1) */ + case 3: + case 4: + case 5: + case 6: + case 7: + task_p = transvr_task_creat(self, + taskfunc_qsfp_set_hpmod, + taskfunc_post_handle_task_state, + "transvr_init_qsfp"); + if (!task_p) { + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + transvr_task_set_retry(task_p, hpmod_retry); + transvr_task_set_delay(task_p, hpmod_delay); + return EVENT_TRANSVR_TASK_WAIT; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Exception case"); + goto err_initfunc_qsfp_handle_power_mode; + +err_initfunc_qsfp_handle_power_mode: + SWPS_INFO("%s: %s :%s \n", __func__, err_msg, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +initfunc_qsfp28_handle_cdr(struct transvr_obj_s *self) { + + uint8_t DEFAULT_VAL_CDR = 0xff; + int CDR_FUNC_EXISTED = 0x3; + int show_err = 1; + int err_val = EVENT_TRANSVR_TASK_FAIL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_qsfp28_handle_cdr"; + + err_val = __qsfp_get_cdr_present(self, 0); + if ( (err_val < 0) || + (err_val == DEBUG_TRANSVR_HEX_VAL) ) { + err_msg = "detect cdr_present fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + if (err_val == CDR_FUNC_EXISTED) { + err_val = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->offset_cdr, + DEFAULT_VAL_CDR, + &(self->cdr), + func_str, + show_err); + if (err_val < 0) { + err_msg = "set CDR fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_qsfp_handle_cdr_1: + SWPS_INFO("%s: %s :%d :%s\n", + func_str, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + +/* ========== Object functions for Final State Machine ========== + */ +int +is_plugged(struct transvr_obj_s *self){ + + int limit = 63; + int present = DEBUG_TRANSVR_INT_VAL; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p; + + if (!ioexp_p) { + snprintf(emsg, limit, "ioexp_p is null!"); + goto err_is_plugged_1; + } + present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset); + switch (present){ + case 0: + return 1; + case 1: + return 0; + case ERR_IOEXP_UNINIT: + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + default: + if (ioexp_p->state == STATE_IOEXP_INIT){ + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + } + break; + } + SWPS_INFO("%s: Exception case! :%d :%d\n", + __func__, present, ioexp_p->state); + return 0; + +err_is_plugged_1: + SWPS_DEBUG("%s: %s\n", __func__, emsg); + return 0; +} + + +static int +detect_transvr_type(struct transvr_obj_s* self){ + + int type = TRANSVR_TYPE_ERROR; + + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + type = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + + /* Case: 1. Wait transceiver I2C module. + * 2. Transceiver I2C module failure. + * Note: 1. SFF allow maximum transceiver initial time is 2 second. So, there + * are exist some case that we need to wait transceiver. + * For these case, we keeps status on "TRANSVR_TYPE_UNPLUGGED", than + * state machine will keep trace with it. + * 2. There exist some I2C failure case we need to handle. Such as user + * insert the failure transceiver, or any reason cause it abnormal. + */ + if (type < 0){ + switch (type) { + case -EIO: + SWPS_DEBUG("%s: %s smbus return:-5 (I/O error)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + case -ENXIO: + SWPS_DEBUG("%s: %s smbus return:-6 (No such device or address)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + default: + break; + } + SWPS_INFO("%s: %s unexpected smbus return:%d \n", + __func__, self->swp_name, type); + return TRANSVR_TYPE_ERROR; + } + /* Identify valid transceiver type */ + switch (type){ + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + break; + case TRANSVR_TYPE_UNKNOW_1: + case TRANSVR_TYPE_UNKNOW_2: + type = TRANSVR_TYPE_UNKNOW_2; + break; + default: + SWPS_DEBUG("%s: unknow type:0x%02x \n", __func__, type); + type = TRANSVR_TYPE_ERROR; + break; + } + return type; +} + + +static int +detect_transvr_state(struct transvr_obj_s *self, + int result[2]){ + /* [return] [result-0] [result-1] + * 0 STATE_TRANSVR_CONNECTED TRANSVR_TYPE_FAKE + * 0 STATE_TRANSVR_DISCONNECTED TRANSVR_TYPE_UNPLUGGED + * 0 STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * 0 STATE_TRANSVR_INIT / + * 0 STATE_TRANSVR_SWAPPED + * 0 STATE_TRANSVR_CONNECTED + * ERR_TRNASVR_BE_ISOLATED STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_I2C_CRASH STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_UNEXCPT STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_UNKNOW_1/2 + */ + result[0] = STATE_TRANSVR_UNEXCEPTED; /* For return state */ + result[1] = TRANSVR_TYPE_ERROR; /* For return type */ + + /* Case1: Fake type */ + if (self->type == TRANSVR_TYPE_FAKE){ + result[0] = STATE_TRANSVR_CONNECTED; + result[1] = TRANSVR_TYPE_FAKE; + return 0; + } + /* Case2: Transceiver unplugged */ + if (!is_plugged(self)){ + result[0] = STATE_TRANSVR_DISCONNECTED; + result[1] = TRANSVR_TYPE_UNPLUGGED; + return 0; + } + /* Case3: Transceiver be isolated */ + if (self->state == STATE_TRANSVR_ISOLATED){ + result[0] = STATE_TRANSVR_ISOLATED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case4: Transceiver plugged */ + result[1] = detect_transvr_type(self); + /* Case4.1: I2C topology crash + * Note : There are some I2C issues cause by transceiver/cables. + * We need to check topology status when user insert it. + * But in this step, we can't not ensure this is the issues + * port. So, it return the ERR_TRANSVR_I2C_CRASH, then upper + * layer will diagnostic I2C topology. + */ + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: %s detect I2C crash :%d\n", + __func__, self->swp_name, self->state); + result[0] = STATE_TRANSVR_UNEXCEPTED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_I2C_CRASH; + } + /* Case4.2: System initial not ready, + * Note : Sometime i2c channel or transceiver EEPROM will delay that will + * cause system in inconsistent state between EEPROM and IOEXP. + * In this case, SWP transceiver object keep state at LINK_DOWN + * to wait system ready. + * By the way, State Machine will handle these case. + */ + if (result[1] == TRANSVR_TYPE_UNPLUGGED){ + result[0] = STATE_TRANSVR_DISCONNECTED; + return 0; + } + /* Case4.3: Error transceiver type */ + if (result[1] == TRANSVR_TYPE_ERROR){ + result[0] = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s detect error type\n", __func__, self->swp_name); + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard!"); + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case3.3: Unknow transceiver type */ + if ((result[1] == TRANSVR_TYPE_UNKNOW_1) || + (result[1] == TRANSVR_TYPE_UNKNOW_2) ){ + result[0] = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + /* Case3.4: During initial process */ + if (self->state == STATE_TRANSVR_INIT){ + result[0] = STATE_TRANSVR_INIT; + return 0; + } + /* Case3.5: Transceiver be swapped */ + if (self->type != result[1]){ + result[0] = STATE_TRANSVR_SWAPPED; + return 0; + } + /* Case3.6: Link up state */ + result[0] = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +_sfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = _sfp_get_comp_extended(self); + + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_25G_AOC; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_25G_SR; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_25G_LR; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_25G_ER; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x0c: /* 25GBASE-CR CA-S */ + case 0x0d: /* 25GBASE-CR CA-N */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L1_25G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_10_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _sfp_get_comp_10g_eth_comp(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 10G Optical (x1) */ + if ((detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + } + if ((detect_val & 0x80) == 0x80) { /* 10000000 : 10GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_1g = 0x0b; + int upper_bound_1g = 0x1A; + int lower_bound_10g = 0x60; + int upper_bound_10g = 0x75; + int lower_bound_25g = 0xf0; + int upper_bound_25g = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 25G */ + if ((notmal_br >= lower_bound_25g) && + (notmal_br <= upper_bound_25g) ) { + return TRANSVR_CLASS_25G; + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + /* Check 1G */ + if ((notmal_br >= lower_bound_1g) && + (notmal_br <= upper_bound_1g) ) { + return TRANSVR_CLASS_1G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + int speed_br = DEBUG_TRANSVR_INT_VAL; + int speed_tmp = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + + speed_br = _sfp_detect_if_sp_by_br(self); + detect_val = _sfp_get_comp_1g_eth_comp(self); + + if (detect_val < 0) { + snprintf(err_str, sizeof(err_str), "Detect abnormal value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + } + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 1G (x1) */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 1000BASE-SX */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_SX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x02) == 0x02) { /* 00000010 : 1000BASE-LX *3 */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_LX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 1000BASE-CX */ + speed_tmp = TRANSVR_CLASS_COPPER_L1_1G; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + /* Case: 1000 Base-T (x1) */ + if ((detect_val & 0x08) == 0x08) { /* 00001000 : 1000BASE-T */ + return TRANSVR_CLASS_BASE_T_1000; + } + /* Case: 100 Base */ + if ( ((detect_val & 0x10) == 0x10) || /* 00010000 : 100BASE-LX/LX10 */ + ((detect_val & 0x20) == 0x20) || /* 00100000 : 100BASE-FX */ + ((detect_val & 0x40) == 0x40) || /* 01000000 : BASE-BX10 *3 */ + ((detect_val & 0x80) == 0x80) ){ /* 10000000 : BASE-PX *3 */ + return TRANSVR_CLASS_OPTICAL_100; + } + /* Case: ERROR */ + snprintf(err_str, sizeof(err_str), "Case:ERROR, value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + +ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g: + switch (speed_br) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_1G: + return speed_tmp; + case TRANSVR_CLASS_10G: + goto ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G; + } + +ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G: + switch (speed_tmp) { + case TRANSVR_CLASS_OPTICAL_1G_SX: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case TRANSVR_CLASS_OPTICAL_1G_LX: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case TRANSVR_CLASS_COPPER_L1_1G: + return TRANSVR_CLASS_COPPER_L1_10G; + default: + break; + } + snprintf(err_str, sizeof(err_str), "transfer_1to10 fail, speed:%d", speed_tmp); + goto err_p_sfp_detect_class_by_1g_ethernet; + +err_p_sfp_detect_class_by_1g_ethernet: + SWPS_INFO("%s: %s :%s", __func__, err_str, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int is_active = 0; + int conn_val = DEBUG_TRANSVR_INT_VAL; + int check_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _sfp_detect_if_sp_by_br(self); + conn_val = _sfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 */ + case 0x0d: /* MPO 2x16 */ + /* + * ToDo: Need verify Optical Pigtail + */ + goto ok_sfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + /* + * ToDo: Need check ACC use case + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x23: /* No separable connector */ + /* + * ToDo: Standard not clear, not all transceiver vendor + * have the same defined + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_check_active_passive: + check_val = _sfp_get_cable_tech(self); + switch(check_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_unknow; + case 0x04: /* Passive */ + goto ok_sfp_detect_class_by_feature_4_copper; + case 0x08: /* Active */ + is_active = 1; + goto ok_sfp_detect_class_by_feature_4_aoc; + default: + snprintf(err_msg, sizeof(err_msg), + "_sfp_get_cable_tech return Non define value:%d", + check_val); + break; + } + goto err_sfp_detect_class_by_feature_1; + +ok_sfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_25G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_25G_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_25G_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_25G_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_25G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + case TRANSVR_CLASS_1G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_1G_SX; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_1G_LX; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_1G_EX; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_1G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_sfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_OPTICAL_25G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_S_AOC; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_OPTICAL_1G_AOC; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_COPPER_L1_25G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L1_10G; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_COPPER_L1_1G; + default: + return TRANSVR_CLASS_COPPER; + } + +ok_sfp_detect_class_by_feature_4_unknow: + return TRANSVR_CLASS_UNSPECIFIED; + +err_sfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +sft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _sfp_detect_class_by_extend_comp(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 10G Compliance */ + detect_val = _sfp_detect_class_by_10_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 1G Compliance */ + detect_val = _sfp_detect_class_by_1g_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_BASE_T_1000: + case TRANSVR_CLASS_OPTICAL_100: + /* + * ToDo: Need Check 0.1G + */ + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_COPPER_L1_10G: + /* Transfer speed case + * => Example: Raycom 10G DAC + */ + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 1G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check by connector, br, wavelength */ + detect_val = _sfp_detect_class_by_feature(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_OPTICAL_1G: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_COPPER: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_COPPER_L1_10G: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined get_connector:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sft_detect_transceiver_class_1; + +err_sft_detect_transceiver_class_1: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_trident2_if_type_1; + +err_sfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SR); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_KR); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_tomahawk_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_tomahawk_if_type_1; + +err_sfp_set_tomahawk_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_bf_tofino_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to BF looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_sfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = sft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _sfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TOMAHAWK: + return _sfp_set_tomahawk_if_type(self, detect_cls, result); + + case BF_CHIP_TYPE_TOFINO: + return _sfp_set_bf_tofino_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_sfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = sft_detect_transvr_class(self); + switch(detect_val) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_SP_100); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + detect_val); + goto err_sfp_detect_if_speed_1; + } + /* Check by BR */ + detect_val = _sfp_detect_if_sp_by_br(self); + switch (detect_val) { + case TRANSVR_CLASS_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + default: + break; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_detect_if_speed_1; + +err_sfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_extended(self); + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_100G_AOC; + + case 0x06: /* 100G CWDM4 */ + case 0x09: /* Obsolete (assigned before 100G CWDM4 MSA required FEC) */ + case 0x17: /* 100G CLR4 */ + case 0x1A: /* 100GE-DWDM2 */ + return TRANSVR_CLASS_OPTICAL_100G; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_100G_SR4; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_100G_LR4; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_100G_ER4; + + case 0x07: /* 100G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_100G_PSM4; + + case 0x12: /* 40G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_40G; + + case 0x11: /* 4 x 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + + case 0x10: /* 40GBASE-ER4 */ + return TRANSVR_CLASS_OPTICAL_40G_ER4; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L4_100G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_class_by_10_40_100_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_10_40_100_ethernet(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 40G Optical */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 40G Active Cable (XLPPI) */ + return TRANSVR_CLASS_OPTICAL_40G_AOC; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 40GBASE-SR4 */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + } + if ( (detect_val & 0x02) == 0x02) { /* 00000010 : 40GBASE-LR4 */ + return TRANSVR_CLASS_OPTICAL_40G_LR4; + } + if ( (detect_val & 0x08) == 0x08) { /* 00001000 : 40GBASE-CR4 */ + return TRANSVR_CLASS_COPPER_L4_40G; + } + /* Case: 10G Optical */ + if ( (detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + } + /* Case: Extend Compliance */ + if ( ((detect_val & 0x80) == 0x80) ){ /* 10000000 : Use Extend Compliance */ + return TRANSVR_CLASS_EXTEND_COMP; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_10g = 0x10; + int upper_bound_10g = 0x25; + int lower_bound_40g = 0x60; + int upper_bound_40g = 0x75; + int lower_bound_100g = 0x60; + int upper_bound_100g = 0x75; + int used_extend_br = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + int extend_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 40G */ + if ((notmal_br >= lower_bound_40g) && + (notmal_br <= upper_bound_40g) ) { + return TRANSVR_CLASS_40G; + } + /* Check 100G */ + if (notmal_br == used_extend_br) { + extend_br = (int)(self->extbr); /* updated by update_all() */ + if ((extend_br >= lower_bound_100g) && + (extend_br <= upper_bound_100g) ) { + return TRANSVR_CLASS_100G; + } + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_qsfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int conn_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _qsfp_detect_if_sp_by_br(self); + conn_val = _qsfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 (Multifiber Parallel Optic) */ + case 0x0d: /* MPO 2x16 */ + goto ok_qsfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + goto ok_qsfp_detect_class_by_feature_4_copper; + case 0x23: /* No separable connector */ + if ((_qsfp_get_comp_fc_link_length(self) > 0) || + (_qsfp_get_comp_fc_trans_tech(self) > 0) || + (_qsfp_get_comp_fc_trans_media(self) > 0) || + (_qsfp_get_comp_fc_speed(self) > 0) ) { + goto ok_qsfp_detect_class_by_feature_4_aoc; + } + goto ok_qsfp_detect_class_by_feature_4_copper; + default: + snprintf(err_msg, sizeof(err_msg), + "_qsfp_get_connector_type return Non define value:%d", + conn_val); + goto err_qsfp_detect_class_by_feature_1; + } + return TRANSVR_CLASS_UNSPECIFIED; + +ok_qsfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_100G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_100G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_100G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_100G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_100G; + + case TRANSVR_CLASS_40G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_40G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_40G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_40G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_40G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_Q_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_OPTICAL_100G_AOC; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_OPTICAL_40G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_Q_AOC; + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_COPPER_L4_100G; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_COPPER_L4_40G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L4_10G; + default: + return TRANSVR_CLASS_COPPER; + } + +err_qsfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", + __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +qsft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _qsfp_detect_class_by_extend_comp(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_COPPER_L4_100G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check 10/40G/100G Ethernet Compliance */ + detect_val = _qsfp_detect_class_by_10_40_100_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_COPPER_L4_40G: + return detect_val; + case TRANSVR_CLASS_EXTEND_COMP: + /* Format incorrect case (We already checked the Extend + * Compliance is 0 + */ + snprintf(err_msg, sizeof(err_msg), + "Transceiver format incorrect"); + goto err_qsft_detect_transvr_class_1; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10/40/100:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check by Connector type, BR and wavelength */ + detect_val = _qsfp_detect_class_by_feature(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_COPPER_L4_100G: + case TRANSVR_CLASS_COPPER_L4_40G: + case TRANSVR_CLASS_COPPER_L4_10G: + case TRANSVR_CLASS_COPPER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined connector:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), + "Can not identify!"); + goto err_qsft_detect_transvr_class_1; + +err_qsft_detect_transvr_class_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: LR4 or LR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: /* Need Check: ER4 or ER */ + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_KR4); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_bf_tofino_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to BF looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_qsfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = qsft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _qsfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TOMAHAWK: + return _qsfp_set_tomahawk_if_type(self, detect_cls, result); + + case BF_CHIP_TYPE_TOFINO: + return _qsfp_set_bf_tofino_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 8; + char tmp_result[8] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = qsft_detect_transvr_class(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G Copper */ + case TRANSVR_CLASS_COPPER_L4_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + break; + /* Copper */ + case TRANSVR_CLASS_COPPER: + break; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined class case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Check br and extbr */ + detect_val = _qsfp_detect_if_sp_by_br(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + case TRANSVR_CLASS_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined BR case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_detect_if_speed_1; + +err_qsfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_common_set_lane_map_str(struct transvr_obj_s* self, + char *result) { + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + char err_msg[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_L_STR); + snprintf(result, LEN_TRANSVR_L_STR, "%s=", TRANSVR_UEVENT_KEY_LANE); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + if (tmp_val > 256) { + snprintf(err_msg, sizeof(err_msg), + "detect abnormal value:%d", tmp_val); + goto err_common_set_lane_map_str_1; + } + memset(tmp_str, 0, sizeof(tmp_str)); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_L_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_L_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_L_STR); + } + if (i == 0) { + goto err_common_set_lane_map_str_2; + } + return 0; + +err_common_set_lane_map_str_1: + SWPS_INFO("%s: %s", __func__, err_msg); +err_common_set_lane_map_str_2: + snprintf(result, LEN_TRANSVR_L_STR, "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_common_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action, + int (*detect_if_type)(struct transvr_obj_s *self, char *result), + int (*detect_if_speed)(struct transvr_obj_s *self, char *result), + int send_anyway) { + + char *uevent_envp[4]; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + char tmp_str[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_1[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_2[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_3[64] = DEBUG_TRANSVR_STR_VAL; + + if (TRANSVR_UEVENT_ENABLE != 1) { + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_get_if_lane(self, tmp_str) < 0) { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + } else { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, tmp_str); + } + switch (u_action) { + case KOBJ_ADD: + /* Detect type */ + if (detect_if_type(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface type fail!"); + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, tmp_str); + uevent_envp[0] = tmp_str_1; + /* Detect speed */ + if (detect_if_speed(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface speed fail!"); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, tmp_str); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + case KOBJ_REMOVE: + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + default: + snprintf(err_msg, sizeof(err_msg), "kobject_action:%d not support", u_action); + goto private_common_send_uevent_4_fail; + } + snprintf(err_msg, sizeof(err_msg), "%s", "Exception case"); + goto private_common_send_uevent_4_fail; + +private_common_send_uevent_4_fail: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + if (send_anyway) { + goto private_common_send_uevent_4_send; + } + return ERR_TRANSVR_UEVENT_FAIL; + +private_common_send_uevent_4_send: + return kobject_uevent_env(&(self->transvr_dev_p->kobj), + u_action, + uevent_envp); +} + +int +sfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_sfp_detect_if_type, + &_sfp_detect_if_speed, + send_anyway); +} + + +int +qsfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_qsfp_detect_if_type, + &_qsfp_detect_if_speed, + send_anyway); +} + + +int +fake_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + + int err; + int detect_result[2]; + int current_state = STATE_TRANSVR_UNEXCEPTED; + int current_type = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_NEW) { + if (_transvr_init_handler(self) < 0){ + return ERR_TRANSVR_INIT_FAIL; + } + } + err = detect_transvr_state(self, detect_result); + if (err < 0) { + return err; + } + /* In Direct mode, driver only detect transceiver when user call driver interface + * which on sysfs. So it only need consider the state of Transceiver. + */ + current_state = detect_result[0]; + current_type = detect_result[1]; + + switch (current_state){ + + case STATE_TRANSVR_DISCONNECTED: /* Transceiver is not plugged */ + self->state = current_state; + self->type = current_type; + return ERR_TRANSVR_UNPLUGGED; + + case STATE_TRANSVR_INIT: /* Transceiver is plugged, system not ready */ + return ERR_TRANSVR_UNINIT; + + case STATE_TRANSVR_ISOLATED: /* Transceiver is plugged, but has some issues */ + return ERR_TRNASVR_BE_ISOLATED; + + case STATE_TRANSVR_CONNECTED: /* Transceiver is plugged, system is ready */ + self->state = current_state; + self->type = current_type; + return 0; + + case STATE_TRANSVR_SWAPPED: /* Transceiver is plugged, system detect user changed */ + self->type = current_type; + if (reload_transvr_obj(self, current_type) < 0){ + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + self->state = current_state; + return 0; + + case STATE_TRANSVR_UNEXCEPTED: /* Transceiver type or state is unexpected case */ + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_UNEXCPT; + + default: + SWPS_INFO("%s: state:%d not in define.\n", __func__, current_state); + break; + } + return ERR_TRANSVR_UNEXCPT; +} + + +static int +_is_except_happened_4_pmode(struct transvr_obj_s* self, + int new_state) { + + int event_chk = 0; + + if (self->temp == 0){ + return 0; + } + switch (new_state) { + case STATE_TRANSVR_INIT: + event_chk = EVENT_TRANSVR_EXCEP_INIT; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_CONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_UP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_DISCONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_DOWN; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_SWAPPED: + event_chk = EVENT_TRANSVR_EXCEP_SWAP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_UNEXCEPTED: + event_chk = EVENT_TRANSVR_EXCEP_EXCEP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_ISOLATED: + event_chk = EVENT_TRANSVR_EXCEP_ISOLATED; + goto check_event_happened_4_pmode; + + default: + SWPS_INFO("%s: unexcepted case:%d\n", __func__, new_state); + break; + } + return 0; + +check_event_happened_4_pmode: + if (self->temp == event_chk){ + return 1; + } + return 0; +} + + +int +common_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + /* [Return Value]: + * ERR_TRANSVR_UNINIT : (1) Initial not ready + * ERR_TRANSVR_UNPLUGGED : (1) Any -> Down + * ERR_TRANSVR_TASK_BUSY : (1) Wait Initial task + * ERR_TRANSVR_UNEXCPT : (1) Initial fail + * (2) Task fail + * (3) Reload fail + * ERR_TRNASVR_BE_ISOLATED : (1) Already be isolated + * OK Case (return 0) : (1) action_4_connected + * (2) action_4_nothing (initial retry) + */ + int curr_state[2]; + int old_state = self->state; + int old_type = self->type; + int new_state = STATE_TRANSVR_UNEXCEPTED; + int new_type = TRANSVR_TYPE_ERROR; + int return_val = ERR_TRANSVR_UNEXCPT; + + /* Never initial */ + if (self->state == STATE_TRANSVR_NEW) { + goto comfsm_action_4_reinit_obj; + } + /* Detect current state */ + switch (detect_transvr_state(self, curr_state)) { + case 0: + new_state = curr_state[0]; + new_type = curr_state[1]; + break; + + case ERR_TRNASVR_BE_ISOLATED: + new_state = STATE_TRANSVR_ISOLATED; + new_type = old_type; + break; + + case ERR_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case ERR_TRANSVR_UNEXCPT: + default: + new_state = STATE_TRANSVR_UNEXCEPTED; + new_type = old_type; + } + /* State handling */ + switch (old_state) { + case STATE_TRANSVR_INIT: /* INIT -> */ + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 1-1: UP -> INIT */ + SWPS_INFO("Detect %s is present. :1-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 1-2: UP -> UP */ + return_val = 0; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 1-3: UP -> DOWN */ + SWPS_INFO("Detect %s is removed. :1-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 1-4: UP -> SWAP */ + SWPS_INFO("Detect %s is swapped. :1-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 1-5: UP -> UNEXPET */ + SWPS_INFO("Detect %s has error. :1-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 1-6: UP -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :1-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_DISCONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 2-1: DOWN -> INIT */ + SWPS_INFO("Detect %s is present. :2-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 2-2: DOWN -> UP */ + SWPS_INFO("Detect %s is present. :2-2\n",self->swp_name); + goto comfsm_action_4_reinit_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 2-3: DOWN -> DOWN */ + return_val = ERR_TRANSVR_UNPLUGGED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_SWAPPED: /* Case 2-4: DOWN -> SWAP */ + SWPS_INFO("Detect %s is swapped. :2-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 2-5: DOWN -> UNEXPET */ + SWPS_INFO("Detect %s has error. :2-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 2-6: DOWN -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :2-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_UNEXCEPTED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 3-1: UNEXPET -> INIT */ + SWPS_INFO("Detect %s is present. :3-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 3-2: UNEXPET -> UP */ + SWPS_INFO("Detect %s is present. :3-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 3-3: UNEXPET -> DOWN */ + SWPS_INFO("Detect %s is removed. :3-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 3-4: UNEXPET -> SWAP */ + SWPS_INFO("Detect %s is swapped. :3-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 3-5: UNEXPET -> UNEXPET */ + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRANSVR_UNEXCPT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 3-6: UNEXPET -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :3-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 4-1: ISOLATE -> INIT */ + SWPS_INFO("Detect %s internal error. :4-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 4-2: ISOLATE -> UP */ + SWPS_INFO("Detect %s internal error. :4-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 4-3: ISOLATE -> DOWN */ + SWPS_INFO("Detect %s is removed. :4-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 4-4: ISOLATE -> SWAP */ + SWPS_INFO("Detect %s internal error. :4-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 4-5: ISOLATE -> UNEXPET */ + SWPS_INFO("Detect %s internal error. :4-5\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 4-6: ISOLATE -> ISOLATE */ + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + default: + break; + } + goto comfsm_action_4_unexpected; + + default: + break; + } + goto comfsm_action_4_unexpected; + + +comfsm_action_4_keep_state: + return return_val; + +comfsm_action_4_reinit_obj: + SWPS_DEBUG("FSM action: %s re-initial.\n", self->swp_name); + return_val = _transvr_init_handler(self); + goto comfsm_action_4_identify_event; + +comfsm_action_4_reload_obj: + SWPS_DEBUG("FSM action: %s reload.\n", self->swp_name); + self->type = new_type; + return_val = reload_transvr_obj(self, new_type); + goto comfsm_action_4_identify_event; + +comfsm_action_4_identify_event: + switch (return_val) { + case EVENT_TRANSVR_INIT_UP: + case EVENT_TRANSVR_TASK_DONE: + goto comfsm_action_4_connected; + + case EVENT_TRANSVR_INIT_DOWN: + goto comfsm_action_4_disconnected; + + case EVENT_TRANSVR_INIT_REINIT: + goto comfsm_action_4_nothing; + + case EVENT_TRANSVR_TASK_WAIT: + self->state = STATE_TRANSVR_INIT; + return ERR_TRANSVR_TASK_BUSY; + + case EVENT_TRANSVR_TASK_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_TASK_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_INIT_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_INIT_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_RELOAD_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_RELOAD_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case EVENT_TRANSVR_EXCEP_ISOLATED: + goto comfsm_action_4_isolate_obj; + + default: + SWPS_INFO("%s detect undefined event:%d.\n", self->swp_name, return_val); + goto comfsm_action_4_unexpected; + } + +comfsm_action_4_nothing: + SWPS_DEBUG("FSM action: %s do nothing.\n", self->swp_name); + return 0; + +comfsm_action_4_connected: + SWPS_DEBUG("FSM action: %s Connected.\n", self->swp_name); + self->state = STATE_TRANSVR_CONNECTED; + self->type = new_type; + self->send_uevent(self, KOBJ_ADD); + _transvr_clean_retry(self); + return 0; + +comfsm_action_4_disconnected: + SWPS_DEBUG("FSM action: %s Disconnected. \n", self->swp_name); + self->state = STATE_TRANSVR_DISCONNECTED; + self->temp = EVENT_TRANSVR_TASK_DONE; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_retry(self); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNPLUGGED; + +comfsm_action_4_report_i2c_crash: + SWPS_DEBUG("FSM action: %s report I2C crash.\n", self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_I2C_CRASH; + +comfsm_action_4_isolate_obj: + SWPS_DEBUG("FSM action: %s isolate.\n", self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return ERR_TRNASVR_BE_ISOLATED; + +comfsm_action_4_unexpected: + SWPS_INFO("FSM action: %s unexpected.\n", self->swp_name); + SWPS_INFO("Dump: :%d :0x%02x :%d :0x%02x\n", + old_state, old_type, new_state, new_type); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNEXCPT; +} + + +int +fake_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +int +fake_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +/* ========== Object functions for Initial procedure ========== + */ +int +transvr_init_common(struct transvr_obj_s *self){ + /* Nothing to update */ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_fake(struct transvr_obj_s *self){ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_sfp(struct transvr_obj_s *self){ + + int tmp_val = DEBUG_TRANSVR_INT_VAL; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_msg = "ERR"; + + self->info = sft_detect_transvr_class(self); + /* Disable auto_config */ + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + /* Handle multi-rate */ + err_code = initfunc_sfp_handle_multi_rate_mode(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_multi_rate_mode fail!"; + goto err_transvr_init_sfp_1; + } + /* Handle 1G- RJ45 */ + tmp_val = err_code; + err_code = initfunc_sfp_handle_1g_rj45(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_1g_rj45 fail!"; + goto err_transvr_init_sfp_1; + } + tmp_val = (tmp_val > err_code ? tmp_val : err_code); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_sfp_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_code, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp(struct transvr_obj_s *self){ + + int err = EVENT_TRANSVR_EXCEP_EXCEP; + char *emsg = "ERR"; + + self->info = qsft_detect_transvr_class(self); + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + err = initfunc_qsfp_handle_power_mode(self); + if (err < 0){ + emsg = "initfunc_qsfp_handle_tx_disable fail!"; + goto err_transvr_init_qsfp; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, emsg, err, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp28(struct transvr_obj_s *self){ + + int tmp_val = EVENT_TRANSVR_EXCEP_EXCEP; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_msg = "ERR"; + + /* Handle QSFP common */ + err_val = transvr_init_qsfp(self); + if (err_val < 0){ + err_msg = "transvr_init_qsfp fail!"; + goto err_transvr_init_qsfp28_1; + } + /* Disable auto_config */ + if (!self->auto_config) { + return err_val; + } + /* Handle CDR */ + tmp_val = err_val; + err_val = initfunc_qsfp28_handle_cdr(self); + if (err_val < 0){ + err_msg = "Handle CDR fail!"; + goto err_transvr_init_qsfp28_1; + } + tmp_val = (tmp_val > err_val ? tmp_val : err_val); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp28_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== Object Initial handler ========== + */ +static int +_is_transvr_valid(struct transvr_obj_s *self, + int type, + int state) { + /* [Return] + * 0 : OK, inserted + * EVENT_TRANSVR_INIT_DOWN : OK, removed + * EVENT_TRANSVR_INIT_FAIL : Outside error, type doesn't supported + * EVENT_TRANSVR_EXCEP_INIT : Internal error, state undefined + */ + switch (type) { + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + break; + default: + SWPS_INFO("detect undefined type:0x%02x on %s\n", + type, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; + } + switch (state) { + case STATE_TRANSVR_DISCONNECTED: + return EVENT_TRANSVR_INIT_DOWN; + case STATE_TRANSVR_INIT: + case STATE_TRANSVR_CONNECTED: + case STATE_TRANSVR_SWAPPED: + break; + default: + SWPS_INFO("detect undefined state:%d on %s\n", + state, self->swp_name); + return EVENT_TRANSVR_EXCEP_INIT; + } + return 0; +} + + +static int +_is_transvr_hw_ready(struct transvr_obj_s *self, + int type){ + /* [Return] + * EVENT_TRANSVR_TASK_DONE : Ready + * EVENT_TRANSVR_TASK_WAIT : Not ready + * EVENT_TRANSVR_INIT_FAIL : Error + */ + int addr = DEBUG_TRANSVR_INT_VAL; + int page = DEBUG_TRANSVR_INT_VAL; + int offs = DEBUG_TRANSVR_INT_VAL; + int bit = DEBUG_TRANSVR_INT_VAL; + int ready = DEBUG_TRANSVR_INT_VAL; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t ab_val = DEBUG_TRANSVR_HEX_VAL; + + switch (type) { + case TRANSVR_TYPE_SFP: + addr = VAL_TRANSVR_8472_READY_ADDR; + page = VAL_TRANSVR_8472_READY_PAGE; + offs = VAL_TRANSVR_8472_READY_OFFSET; + bit = VAL_TRANSVR_8472_READY_BIT; + ready = VAL_TRANSVR_8472_READY_VALUE; + ab_val = VAL_TRANSVR_8472_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + addr = VAL_TRANSVR_8436_READY_ADDR; + page = VAL_TRANSVR_8436_READY_PAGE; + offs = VAL_TRANSVR_8436_READY_OFFSET; + bit = VAL_TRANSVR_8436_READY_BIT; + ready = VAL_TRANSVR_8436_READY_VALUE; + ab_val = VAL_TRANSVR_8436_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + return EVENT_TRANSVR_TASK_DONE; + + default: + emsg = "unexpected case"; + goto err_is_transvr_hw_ready; + } + /* Select target page */ + err = _common_setup_page(self, addr, page, offs, 1, 0); + if (err < 0) { + emsg = "setup page fail"; + goto err_is_transvr_hw_ready; + } + /* Check feature supported + * [Note] + * Some of transceiver/cables doesn't support "Status Indicators" + * (ex:DAC, RJ45 copper SFP ...etc). In these case, we bypass the + * step of checking Status Indicators, then state machine will take + * the following handle procedure. + */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (err < 0) { + emsg = "doesn't support Status Indicators"; + goto bypass_is_transvr_hw_ready; + } + /* Filter abnormal case */ + if (err == ab_val) { + emsg = "detect using unusual definition."; + goto bypass_is_transvr_hw_ready; + } + /* Get Status Indicators */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, offs); + if (err < 0) { + emsg = "detect current value fail"; + goto err_is_transvr_hw_ready; + } + if ((err & (1<:%d\n", __func__, emsg, type); + return EVENT_TRANSVR_TASK_DONE; + +err_is_transvr_hw_ready: + SWPS_DEBUG("%s: %s :%d\n", __func__, emsg, type); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_is_transvr_support_ctle(struct transvr_obj_s *self) { + + switch (self->info) { + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return 1; + default: + break; + } + return 0; +} + + +static int +_transvr_init_handler(struct transvr_obj_s *self){ + + int detect[2]; + int d_state = STATE_TRANSVR_UNEXCEPTED; + int d_type = TRANSVR_TYPE_ERROR; + int result = ERR_TRANSVR_UNINIT; + int retry = 6; /* (6+1) x 0.3 = 2.1s > spec:2.0s */ + int elimit = 63; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Clean and check callback */ + self->state = STATE_TRANSVR_INIT; + if (self->init == NULL) { + snprintf(emsg, elimit, "init() is null"); + goto initer_err_case_unexcept_0; + } + if (self->clean == NULL) { + snprintf(emsg, elimit, "clean() is null"); + goto initer_err_case_unexcept_0; + } + self->clean(self); + + /* Detect transceiver information */ + result = detect_transvr_state(self, detect); + if (result < 0) { + snprintf(emsg, elimit, "detect_transvr_state() fail"); + switch (result) { + case ERR_TRANSVR_I2C_CRASH: + goto initer_err_case_i2c_ceash; + case ERR_TRNASVR_BE_ISOLATED: + goto initer_err_case_be_isolated; + + case ERR_TRANSVR_UNEXCPT: + default: + break; + } + goto initer_err_case_retry_1; + } + d_state = detect[0]; + d_type = detect[1]; + + /* Verify transceiver type and state */ + switch (_is_transvr_valid(self, d_type, d_state)) { + case 0: + break; + case EVENT_TRANSVR_INIT_DOWN: + goto initer_ok_case_down;; + case EVENT_TRANSVR_INIT_FAIL: + snprintf(emsg, elimit, "transceiver type doesn't support"); + goto initer_err_case_alarm_to_user; + case EVENT_TRANSVR_EXCEP_INIT: + default: + goto initer_err_case_unexcept_1; + } + + /* Handle reload case */ + if (self->type != d_type){ + /* This is the protect mechanism. Normally, This case will not happen. + * When State machine detect swap event during initial, It will trigger + * reload function to ensure type correct. */ + if (_reload_transvr_obj(self, d_type) < 0){ + snprintf(emsg, elimit, "reload object fail"); + goto initer_err_case_unexcept_1; + } + } + + /* Check transceiver HW initial ready */ + switch (_is_transvr_hw_ready(self, d_type)) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_err_case_retry_1; + case EVENT_TRANSVR_INIT_FAIL: + default: + goto initer_err_case_unexcept_1; + } + + /* Try to update all and check */ + if (self->update_all(self, 1) < 0){ + /* For some transceiver, EEPROME has lag issues during initial stage. + * In this case, we set status back to STATE_TRANSVR_NEW, than it will + * be checked in next polling cycle. */ + goto initer_err_case_retry_1; + } + + /* Execute init() call back */ + result = self->init(self); + switch (result) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_ok_case_wait; + + default: + snprintf(emsg, elimit, "undefined init() return:%d\n", result); + goto initer_err_case_unexcept_1; + } + goto initer_ok_case_up; + + +initer_ok_case_wait: + self->dump_all(self); + return EVENT_TRANSVR_TASK_WAIT; + +initer_ok_case_up: + self->state = STATE_TRANSVR_CONNECTED; + self->temp = 0; + self->dump_all(self); + return EVENT_TRANSVR_INIT_UP; + +initer_ok_case_down: + self->temp = 0; + self->state = STATE_TRANSVR_DISCONNECTED; + return EVENT_TRANSVR_INIT_DOWN; + +initer_err_case_i2c_ceash: + SWPS_DEBUG("%s: %s :%s :I2C crash\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_I2C_CRASH; + +initer_err_case_be_isolated: + SWPS_DEBUG("%s: %s :%s :isolated\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return EVENT_TRANSVR_EXCEP_ISOLATED; + +initer_err_case_retry_1: + SWPS_DEBUG("%s: %s :%s :retry\n", + __func__, emsg, self->swp_name); + if (_transvr_handle_retry(self, retry) == 0) { + self->state = STATE_TRANSVR_NEW; + return EVENT_TRANSVR_INIT_REINIT; + } + goto initer_err_case_alarm_to_user; + +initer_err_case_unexcept_1: + self->clean(self); +initer_err_case_unexcept_0: + self->state = STATE_TRANSVR_UNEXCEPTED; + if (_is_except_happened_4_pmode(self, d_state) && + (self->mode == TRANSVR_MODE_POLLING) ){ + SWPS_INFO("%s: %s :%s\n", __func__, emsg, self->swp_name); + SWPS_INFO("Dump: :%d :%d :%d :%d\n", + self->state, self->type, d_state, d_type); + } + return EVENT_TRANSVR_INIT_FAIL; + +initer_err_case_alarm_to_user: + SWPS_DEBUG("%s: %s :%s :alarm_to_user\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard"); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== Object functions for Clean procedure ========== + */ +int +_transvr_clean_handler(struct transvr_obj_s *self){ + + int retval = DEBUG_TRANSVR_INT_VAL; + + if (!self->clean) { + SWPS_ERR("%s: %s clean() is NULL.\n", + __func__, self->swp_name); + return EVENT_TRANSVR_TASK_FAIL; + } + retval = self->clean(self); + if (retval != EVENT_TRANSVR_TASK_DONE){ + SWPS_ERR("%s: %s clean() fail. [ERR]:%d\n", + __func__, self->swp_name, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_transvr_clean(struct transvr_obj_s *self){ + + transvr_task_free_all(self); + transvr_cache_free_all(self); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +qsfp_transvr_clean(struct transvr_obj_s *self){ + + int retval; + int lpower_config = 1; + + retval = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (retval < 0){ + SWPS_ERR("%s: Set lpmod fail! :%d\n", + __func__, retval); + return retval; + } + retval = common_transvr_clean(self); + if (retval < 0){ + SWPS_ERR("%s: common_transvr_clean fail! :%d\n", + __func__, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +fake_transvr_clean(struct transvr_obj_s *self){ + + return EVENT_TRANSVR_TASK_DONE; +} + + +/* ========== Object functions for check and update ========== + */ +int +common_transvr_check(struct transvr_obj_s *self){ + + char fun_str[32] = "common_transvr_check"; + + if (self->mode != TRANSVR_MODE_POLLING) { + SWPS_ERR("%s: mode:%d is not TRANSVR_MODE_POLLING\n", + fun_str, self->mode); + return ERR_TRANSVR_UNEXCPT; + } + /* Trigger delay task */ + transvr_task_run_all(self); + /* Trigger state machine to check and update */ + return self->fsm_4_polling(self, fun_str); +} + + +int +fake_transvr_check(struct transvr_obj_s *self){ + return 0; +} + + +/* ========== Functions for Factory pattern ========== + */ +static int +setup_transvr_public_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = unsupported_get_func; + self->get_br = common_get_br; + self->get_len_sm = sfp_get_len_sm; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = sfp_get_comp_eth_1; + self->get_comp_eth_10 = sfp_get_comp_eth_10; + self->get_comp_eth_10_40 = unsupported_get_func; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = sfp_get_rate_id; + self->get_soft_rs0 = sfp_get_soft_rs0; + self->get_soft_rs1 = sfp_get_soft_rs1; + self->get_info = common_get_info; + self->get_if_type = sfp_get_if_type; + self->get_if_speed = sfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = sfp_get_transvr_temp; + self->get_curr_vol = sfp_get_transvr_voltage; + self->get_soft_rx_los = unsupported_get_func2; + self->get_soft_tx_disable = unsupported_get_func2; + self->get_soft_tx_fault = unsupported_get_func2; + self->get_auto_tx_disable = unsupported_get_func2; + self->get_tx_bias = sfp_get_transvr_tx_bias; + self->get_tx_power = sfp_get_transvr_tx_power; + self->get_rx_power = sfp_get_transvr_rx_power; + self->get_tx_eq = sfp_get_transvr_tx_eq; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = sfp_get_transvr_rx_em; + self->get_wavelength = sfp_get_wavelength; + self->get_extphy_offset = sfp_get_1g_rj45_extphy_offset; + self->get_extphy_reg = sfp_get_1g_rj45_extphy_reg; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = sfp_set_soft_rs0; + self->set_soft_rs1 = sfp_set_soft_rs1; + self->set_soft_tx_disable = unsupported_set_func; + self->set_auto_tx_disable = unsupported_set_func; + self->set_tx_eq = sfp_set_tx_eq; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = sfp_set_rx_em; + self->set_extphy_offset = sfp_set_1g_rj45_extphy_offset; + self->set_extphy_reg = sfp_set_1g_rj45_extphy_reg; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = unsupported_get_func2; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = unsupported_get_func2; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = unsupported_set_func; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = unsupported_set_func; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = qsfp_get_cdr; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = qsfp_get_transvr_tx_eq; + self->get_rx_am = qsfp_get_transvr_rx_am; + self->get_rx_em = qsfp_get_transvr_rx_em; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = qsfp_set_cdr; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = qsfp_set_tx_eq; + self->set_rx_am = qsfp_set_rx_am; + self->set_rx_em = qsfp_set_rx_em; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_FAKE: + self->get_id = fake_get_hex; + self->get_ext_id = fake_get_hex; + self->get_connector = fake_get_hex; + self->get_vendor_name = fake_get_str; + self->get_vendor_pn = fake_get_str; + self->get_vendor_rev = fake_get_str; + self->get_vendor_sn = fake_get_str; + self->get_power_cls = fake_get_int; + self->get_br = fake_get_hex; + self->get_len_sm = fake_get_int; + self->get_len_smf = fake_get_int; + self->get_len_om1 = fake_get_int; + self->get_len_om2 = fake_get_int; + self->get_len_om3 = fake_get_int; + self->get_len_om4 = fake_get_int; + self->get_comp_rev = fake_get_hex; + self->get_comp_eth_1 = fake_get_hex; + self->get_comp_eth_10 = fake_get_hex; + self->get_comp_eth_10_40 = fake_get_hex; + self->get_comp_extend = fake_get_hex; + self->get_cdr = fake_get_hex; + self->get_rate_id = fake_get_hex; + self->get_soft_rs0 = fake_get_binary; + self->get_soft_rs1 = fake_get_binary; + self->get_info = fake_get_int; + self->get_if_type = fake_get_str; + self->get_if_speed = fake_get_str; + self->get_if_lane = fake_get_str; + self->get_curr_temp = fake_get_str; + self->get_curr_vol = fake_get_str; + self->get_soft_rx_los = fake_get_str; + self->get_soft_tx_disable = fake_get_str; + self->get_soft_tx_fault = fake_get_str; + self->get_auto_tx_disable = fake_get_str; + self->get_tx_bias = fake_get_str; + self->get_tx_power = fake_get_str; + self->get_rx_power = fake_get_str; + self->get_tx_eq = fake_get_str; + self->get_rx_am = fake_get_str; + self->get_rx_em = fake_get_str; + self->get_wavelength = fake_get_str; + self->get_extphy_offset = fake_get_str; + self->get_extphy_reg = fake_get_str; + self->set_cdr = fake_set_hex; + self->set_soft_rs0 = fake_set_int; + self->set_soft_rs1 = fake_set_int; + self->set_soft_tx_disable = fake_set_int; + self->set_auto_tx_disable = fake_set_int; + self->set_tx_eq = fake_set_int; + self->set_rx_am = fake_set_int; + self->set_rx_em = fake_set_int; + self->set_extphy_offset = fake_set_hex; + self->set_extphy_reg = fake_set_hex; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_transvr_private_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->init = transvr_init_sfp; + self->clean = common_transvr_clean; + self->check = common_transvr_check; + self->update_all = _sfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = sfp_send_uevent; + self->dump_all = sfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->init = transvr_init_qsfp; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->init = transvr_init_qsfp28; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_FAKE: + self->init = transvr_init_fake; + self->clean = fake_transvr_clean; + self->check = fake_transvr_check; + self->update_all = fake_transvr_update; + self->fsm_4_direct = fake_fsm_4_direct_mode; + self->fsm_4_polling = fake_fsm_4_polling_mode; + self->send_uevent = fake_send_uevent; + self->dump_all = fake_transvr_dump; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static struct eeprom_map_s * +get_eeprom_map(int transvr_type){ + + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + return &eeprom_map_sfp; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + return &eeprom_map_qsfp; + case TRANSVR_TYPE_QSFP_28: + return &eeprom_map_qsfp28; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return NULL; +} + + +static int +setup_transvr_ssize_attr(char *swp_name, + struct transvr_obj_s *self, + struct eeprom_map_s *map_p, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int chan_id, + int run_mode){ + switch (run_mode){ + case TRANSVR_MODE_DIRECT: /* Direct access device mode */ + case TRANSVR_MODE_POLLING: /* Polling mode, read from cache */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = DEBUG_TRANSVR_INT_VAL; + return -1; + } + self->eeprom_map_p = map_p; + self->ioexp_obj_p = ioexp_obj_p; + self->ioexp_virt_offset = ioexp_virt_offset; + self->chan_id = chan_id; + self->layout = transvr_type; + self->type = transvr_type; + self->chipset_type = chipset_type; + self->state = STATE_TRANSVR_NEW; + self->info = STATE_TRANSVR_NEW; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + strncpy(self->swp_name, swp_name, 32); + mutex_init(&self->lock); + return 0; +} + + +static int +setup_transvr_dsize_attr(struct transvr_obj_s *self){ + + char *emsg = DEBUG_TRANSVR_STR_VAL; + + self->vendor_name = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_name){ + emsg = "vendor_name"; + goto err_setup_d_attr; + } + self->vendor_pn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_pn){ + emsg = "vendor_pn"; + goto err_setup_d_attr; + } + self->vendor_rev = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_rev){ + emsg = "vendor_rev"; + goto err_setup_d_attr; + } + self->vendor_sn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_sn){ + emsg = "vendor_sn"; + goto err_setup_d_attr; + } + self->worker_p = NULL; + return 0; + +err_setup_d_attr: + SWPS_ERR("%s: %s kzalloc fail!", __func__, emsg); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_i2c_client(struct transvr_obj_s *self){ + + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + adap = i2c_get_adapter(self->chan_id); + if(!adap){ + snprintf(err_msg, sizeof(err_msg), + "can not get adap:%d", self->chan_id); + goto err_setup_i2c_client; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + snprintf(err_msg, sizeof(err_msg), + "can not kzalloc client:%d", self->chan_id); + goto err_setup_i2c_client; + } + client->adapter = adap; + self->i2c_client_p = client; + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + return 0; + +err_setup_i2c_client: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return ERR_TRANSVR_UNEXCPT; +} + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode){ + + struct transvr_obj_s *result_p; + struct eeprom_map_s *map_p; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Allocate transceiver object */ + map_p = get_eeprom_map(transvr_type); + if (!map_p){ + snprintf(err_msg, sizeof(err_msg), + "Invalid transvr_type:%d", transvr_type); + goto err_create_transvr_fail; + } + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_create_transvr_fail; + } + /* Prepare static size attributes */ + if (setup_transvr_ssize_attr(swp_name, + result_p, + map_p, + ioexp_obj_p, + ioexp_virt_offset, + transvr_type, + chipset_type, + chan_id, + run_mode) < 0){ + goto err_create_transvr_sattr_fail; + } + /* Prepare dynamic size attributes */ + if (setup_transvr_dsize_attr(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_public_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_private_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare i2c client object */ + if (setup_i2c_client(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + return result_p; + +err_create_transvr_dattr_fail: + kfree(result_p->vendor_sn); + kfree(result_p->vendor_rev); + kfree(result_p->vendor_pn); + kfree(result_p->vendor_name); +err_create_transvr_sattr_fail: + kfree(result_p); +err_create_transvr_fail: + SWPS_ERR("%s: %s :%d :%d :%d\n", + __func__, err_msg, chan_id, ioexp_virt_offset, transvr_type); + return NULL; +} + + +static int +_reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + struct eeprom_map_s *new_map_p; + struct eeprom_map_s *old_map_p = self->eeprom_map_p; + struct i2c_client *old_i2c_p = self->i2c_client_p; + int old_type = self->type; + + /* Change state to STATE_TRANSVR_INIT */ + self->state = STATE_TRANSVR_INIT; + self->type = new_type; + /* Replace EEPROME map */ + new_map_p = get_eeprom_map(new_type); + if (!new_map_p){ + goto err_private_reload_func_1; + } + self->eeprom_map_p = new_map_p; + /* Reload i2c client */ + if (setup_i2c_client(self) < 0){ + goto err_private_reload_func_2; + } + /* Replace call back functions */ + if (setup_transvr_public_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + if (setup_transvr_private_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + kfree(old_i2c_p); + return 0; + +err_private_reload_func_3: + SWPS_INFO("%s: init() fail!\n", __func__); + kfree(old_i2c_p); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return -2; + +err_private_reload_func_2: + self->eeprom_map_p = old_map_p; + self->i2c_client_p = old_i2c_p; +err_private_reload_func_1: + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = old_type; + SWPS_INFO("%s fail! :0x%02x\n", __func__, new_type); + return -1; +} + + +static int +reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + int result_val = ERR_TRANSVR_UNEXCPT; + + /* Reload phase */ + result_val = _reload_transvr_obj(self, new_type); + if (result_val < 0){ + SWPS_INFO("%s: reload phase fail! :%d\n", + __func__, result_val); + return EVENT_TRANSVR_RELOAD_FAIL; + } + /* Initial phase */ + result_val = _transvr_init_handler(self); + if (result_val < 0){ + SWPS_INFO("%s: initial phase fail! :%d\n", + __func__, result_val); + } + return result_val; +} + + +int +isolate_transvr_obj(struct transvr_obj_s *self) { + + self->state = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s be isolated\n", __func__, self->swp_name); + return 0; +} + + +int +resync_channel_tier_2(struct transvr_obj_s *self) { + + int val = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_ISOLATED) { + return 0; + } + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + val = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (val < 0) { + return -1; + } + return 0; +} + + +/* ----------------------------------------- + * ToDo List + * ----------------------------------------- + * 1. _sfp_detect_class_by_feature() + * => Need check ACC use case. + * 2. _sfp_detect_class_by_1g_ethernet() + * => Need check 0.1G use case. + * 3. Loopback transceiver use case. + * => Less much data + * 4. _qsfp_detect_class_by_extend_comp() + * => Verify 100G CWDM4 + * => Verify Obsolete (assigned before 100G CWDM4 MSA required FEC) + * => Verify 100G CLR4 + * => Verify 100GE-DWDM2 + * => Verify 40G PSM4 Parallel SMF + * => Verify 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. + * => Verify 100G ACC or 25GAUI C2M ACC. + * => Verify 25GBASE-LR + * => Verify 40G Active Cable (XLPPI) + */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.h new file mode 100644 index 000000000000..42e1938670fb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.h @@ -0,0 +1,814 @@ +/* + * 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. + */ + +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* advanced features control */ +#define TRANSVR_INFO_DUMP_ENABLE (1) +#define TRANSVR_INFO_CACHE_ENABLE (1) +#define TRANSVR_UEVENT_ENABLE (1) + +/* Transceiver type define */ +#define TRANSVR_TYPE_UNKNOW_1 (0x00) +#define TRANSVR_TYPE_UNKNOW_2 (0xff) +#define TRANSVR_TYPE_SFP (0x03) /* Define for SFP, SFP+, SFP28 */ +#define TRANSVR_TYPE_QSFP (0x0c) +#define TRANSVR_TYPE_QSFP_PLUS (0x0d) +#define TRANSVR_TYPE_QSFP_28 (0x11) +#define TRANSVR_TYPE_UNPLUGGED (0xfa) /* Define for ERROR handle */ +#define TRANSVR_TYPE_FAKE (0xfc) /* Define for ERROR handle */ +#define TRANSVR_TYPE_INCONSISTENT (0xfd) /* Define for ERROR handle */ +#define TRANSVR_TYPE_ERROR (0xfe) /* Define for ERROR handle */ + +/* Transceiver class for base info */ +#define TRANSVR_CLASS_UNSPECIFIED (0) +#define TRANSVR_CLASS_ERROR (-26001) +#define TRANSVR_CLASS_1G (26001) +#define TRANSVR_CLASS_10G (26011) +#define TRANSVR_CLASS_25G (26021) +#define TRANSVR_CLASS_40G (26041) +#define TRANSVR_CLASS_100G (26101) +#define TRANSVR_CLASS_NO_SPERARABLE (26901) +#define TRANSVR_CLASS_EXTEND_COMP (26902) +/* Transceiver class for Optical 1G */ +#define TRANSVR_CLASS_OPTICAL (27000) +#define TRANSVR_CLASS_OPTICAL_100 (27001) +#define TRANSVR_CLASS_OPTICAL_1G (27002) +#define TRANSVR_CLASS_OPTICAL_1G_AOC (27003) +#define TRANSVR_CLASS_OPTICAL_1G_SX (27004) +#define TRANSVR_CLASS_OPTICAL_1G_LX (27005) +#define TRANSVR_CLASS_OPTICAL_1G_EX (27006) +/* Transceiver class for Optical 10G */ +#define TRANSVR_CLASS_OPTICAL_10G (27010) +#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011) +#define TRANSVR_CLASS_OPTICAL_10G_S_SR (27012) +#define TRANSVR_CLASS_OPTICAL_10G_S_LR (27013) +#define TRANSVR_CLASS_OPTICAL_10G_S_ER (27014) +#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015) +#define TRANSVR_CLASS_OPTICAL_10G_Q_SR (27016) +#define TRANSVR_CLASS_OPTICAL_10G_Q_LR (27017) +#define TRANSVR_CLASS_OPTICAL_10G_Q_ER (27018) +/* Transceiver class for Optical 25G */ +#define TRANSVR_CLASS_OPTICAL_25G (27020) +#define TRANSVR_CLASS_OPTICAL_25G_AOC (27021) +#define TRANSVR_CLASS_OPTICAL_25G_SR (27022) +#define TRANSVR_CLASS_OPTICAL_25G_LR (27023) +#define TRANSVR_CLASS_OPTICAL_25G_ER (27024) +/* Transceiver class for Optical 40G */ +#define TRANSVR_CLASS_OPTICAL_40G (27040) +#define TRANSVR_CLASS_OPTICAL_40G_AOC (27041) +#define TRANSVR_CLASS_OPTICAL_40G_SR4 (27042) +#define TRANSVR_CLASS_OPTICAL_40G_LR4 (27043) +#define TRANSVR_CLASS_OPTICAL_40G_ER4 (27044) +/* Transceiver class for Optical 100G */ +#define TRANSVR_CLASS_OPTICAL_100G (27100) +#define TRANSVR_CLASS_OPTICAL_100G_AOC (27101) +#define TRANSVR_CLASS_OPTICAL_100G_SR4 (27102) +#define TRANSVR_CLASS_OPTICAL_100G_LR4 (27103) +#define TRANSVR_CLASS_OPTICAL_100G_ER4 (27104) +#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105) +/* Transceiver class for Copper */ +#define TRANSVR_CLASS_COPPER (28000) +#define TRANSVR_CLASS_COPPER_L1_1G (28001) +#define TRANSVR_CLASS_COPPER_L1_10G (28011) +#define TRANSVR_CLASS_COPPER_L4_10G (28012) +#define TRANSVR_CLASS_COPPER_L1_25G (28021) +#define TRANSVR_CLASS_COPPER_L4_40G (28041) +#define TRANSVR_CLASS_COPPER_L4_100G (28101) +/* Transceiver class for Base-T */ +#define TRANSVR_CLASS_BASE_T_1000 (29001) +#define TRANSVR_CLASS_BASE_T_1000_up (29002) +/* For uevent message */ +#define TRANSVR_UEVENT_KEY_IF "IF_TYPE" +#define TRANSVR_UEVENT_KEY_SP "IF_SPEED" +#define TRANSVR_UEVENT_KEY_LANE "IF_LANE" +#define TRANSVR_UEVENT_UNKNOW "UNKNOW" +#define TRANSVR_IF_KR "KR" +#define TRANSVR_IF_KR4 "KR4" +#define TRANSVR_IF_SR "SR" +#define TRANSVR_IF_SR4 "SR4" +#define TRANSVR_IF_SFI "SFI" +#define TRANSVR_IF_IF_GMII "GMII" +#define TRANSVR_IF_IF_XGMII "XGMII" +#define TRANSVR_IF_SP_100 "100" +#define TRANSVR_IF_SP_1G "1000" +#define TRANSVR_IF_SP_10G "10000" +#define TRANSVR_IF_SP_25G "25000" +#define TRANSVR_IF_SP_40G "40000" +#define TRANSVR_IF_SP_100G "100000" + +/* Transceiver mode define */ +#define TRANSVR_MODE_DIRECT (21000) +#define TRANSVR_MODE_POLLING (21001) + +/* Transceiver state define + * [Note] + * 1. State is used to represent the state of "Transceiver" and "Object". + * 2. State for different target has different means. The description as following: + */ +#define STATE_TRANSVR_CONNECTED (0) /* [Transvr]:Be plugged in. [Obj]:Link up, and work normally. */ +#define STATE_TRANSVR_NEW (-100) /* [Transvr]:(Not used) [Obj]:Create */ +#define STATE_TRANSVR_INIT (-101) /* [Transvr]:Be plugged in. [Obj]:Link up, and in initial process. */ +#define STATE_TRANSVR_ISOLATED (-102) /* [Transvr]:Be plugged in. [Obj]:Isolate, and not provide service. */ +#define STATE_TRANSVR_SWAPPED (-200) /* [Transvr]:Be plugged in. [Obj]:(Not used) */ +#define STATE_TRANSVR_DISCONNECTED (-300) /* [Transvr]:Un-plugged. [Obj]:Link down, and not provide service. */ +#define STATE_TRANSVR_UNEXCEPTED (-901) /* [Transvr]:Any [Obj]:Any, and not in expect case. */ + +/* Task state define */ +#define STATE_T_TASK_WAIT (110) +#define STATE_T_TASK_DONE (0) +#define STATE_T_TASK_INIT (-110) +#define STATE_T_TASK_FAIL (-410) + + +/* Event for task handling */ +#define EVENT_TRANSVR_TASK_WAIT (2101) +#define EVENT_TRANSVR_TASK_DONE (0) +#define EVENT_TRANSVR_TASK_FAIL (-2101) +/* Event for initial handling */ +#define EVENT_TRANSVR_INIT_UP (2201) +#define EVENT_TRANSVR_INIT_DOWN (1) +#define EVENT_TRANSVR_INIT_REINIT (-2201) +#define EVENT_TRANSVR_INIT_FAIL (-2202) +/* Event for others */ +#define EVENT_TRANSVR_RELOAD_FAIL (-2301) +#define EVENT_TRANSVR_EXCEP_INIT (-2401) +#define EVENT_TRANSVR_EXCEP_UP (-2402) +#define EVENT_TRANSVR_EXCEP_DOWN (-2403) +#define EVENT_TRANSVR_EXCEP_SWAP (-2404) +#define EVENT_TRANSVR_EXCEP_EXCEP (-2405) +#define EVENT_TRANSVR_EXCEP_ISOLATED (-2406) +#define EVENT_TRANSVR_I2C_CRASH (-2501) + +/* Transceiver error code define */ +#define ERR_TRANSVR_UNINIT (-201) +#define ERR_TRANSVR_UNPLUGGED (-202) +#define ERR_TRANSVR_ABNORMAL (-203) +#define ERR_TRANSVR_NOSTATE (-204) +#define ERR_TRANSVR_NOTSUPPORT (-205) +#define ERR_TRANSVR_BADINPUT (-206) +#define ERR_TRANSVR_UPDATE_FAIL (-207) +#define ERR_TRANSVR_RELOAD_FAIL (-208) +#define ERR_TRANSVR_INIT_FAIL (-209) +#define ERR_TRANSVR_UNDEFINED (-210) +#define ERR_TRANSVR_TASK_FAIL (-211) +#define ERR_TRANSVR_TASK_BUSY (-212) +#define ERR_TRANSVR_UEVENT_FAIL (-213) +#define ERR_TRANSVR_FUNC_DISABLE (-214) +#define ERR_TRANSVR_I2C_CRASH (-297) +#define ERR_TRNASVR_BE_ISOLATED (-298) +#define ERR_TRANSVR_UNEXCPT (-299) + +/* For debug */ +#define DEBUG_TRANSVR_INT_VAL (-99) +#define DEBUG_TRANSVR_HEX_VAL (0xfe) +#define DEBUG_TRANSVR_STR_VAL "ERROR" + +/* For system internal */ +#define VAL_TRANSVR_COMID_ARREESS (0x50) +#define VAL_TRANSVR_COMID_OFFSET (0x00) +#define VAL_TRANSVR_EXTPHY_ADDR_56 (0x56) +#define VAL_TRANSVR_8472_READY_ADDR (0x51) +#define VAL_TRANSVR_8472_READY_PAGE (-1) +#define VAL_TRANSVR_8472_READY_OFFSET (110) +#define VAL_TRANSVR_8472_READY_BIT (0) +#define VAL_TRANSVR_8472_READY_VALUE (0) +#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_READY_ADDR (0x50) +#define VAL_TRANSVR_8436_READY_PAGE (-1) +#define VAL_TRANSVR_8436_READY_OFFSET (2) +#define VAL_TRANSVR_8436_READY_BIT (0) +#define VAL_TRANSVR_8436_READY_VALUE (0) +#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_PWD_ADDR (0x50) +#define VAL_TRANSVR_8436_PWD_PAGE (-1) +#define VAL_TRANSVR_8436_PWD_OFFSET (123) +#define VAL_TRANSVR_PAGE_FREE (-99) +#define VAL_TRANSVR_PAGE_SELECT_OFFSET (127) +#define VAL_TRANSVR_PAGE_SELECT_DELAY (5) +#define VAL_TRANSVR_TASK_RETRY_FOREVER (-999) +#define VAL_TRANSVR_FUNCTION_DISABLE (-1) +#define STR_TRANSVR_SFP "SFP" +#define STR_TRANSVR_QSFP "QSFP" +#define STR_TRANSVR_QSFP_PLUS "QSFP+" +#define STR_TRANSVR_QSFP28 "QSFP28" + +/* For transvr buf len */ +#define LEN_TRANSVR_S_STR (16) +#define LEN_TRANSVR_M_STR (32) +#define LEN_TRANSVR_L_STR (64) + +/* Optical wavelength */ +#define VAL_OPTICAL_WAVELENGTH_SR (850) +#define VAL_OPTICAL_WAVELENGTH_LR (1310) +#define VAL_OPTICAL_WAVELENGTH_ER (1550) + +/* BCM chip type define */ +#define BCM_CHIP_TYPE_TRIDENT_2 (31001) /* Magnolia, Hudson32i, Spruce */ +#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress, Sequoia */ + +#define BF_CHIP_TYPE_TOFINO (31011) /* Lavender */ + +/* Info from transceiver EEPROM */ +struct eeprom_map_s { + int addr_br; int page_br; int offset_br; int length_br; + int addr_cdr; int page_cdr; int offset_cdr; int length_cdr; + int addr_comp_rev; int page_comp_rev; int offset_comp_rev; int length_comp_rev; + int addr_connector; int page_connector; int offset_connector; int length_connector; + int addr_diag_type; int page_diag_type; int offset_diag_type; int length_diag_type; + int addr_extbr; int page_extbr; int offset_extbr; int length_extbr; + int addr_ext_id; int page_ext_id; int offset_ext_id; int length_ext_id; + int addr_id; int page_id; int offset_id; int length_id; + int addr_len_sm; int page_len_sm; int offset_len_sm; int length_len_sm; + int addr_len_smf; int page_len_smf; int offset_len_smf; int length_len_smf; + int addr_len_om1; int page_len_om1; int offset_len_om1; int length_len_om1; + int addr_len_om2; int page_len_om2; int offset_len_om2; int length_len_om2; + int addr_len_om3; int page_len_om3; int offset_len_om3; int length_len_om3; + int addr_len_om4; int page_len_om4; int offset_len_om4; int length_len_om4; + int addr_option; int page_option; int offset_option; int length_option; + int addr_rate_id; int page_rate_id; int offset_rate_id; int length_rate_id; + int addr_rx_am; int page_rx_am; int offset_rx_am; int length_rx_am; + int addr_rx_em; int page_rx_em; int offset_rx_em; int length_rx_em; + int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los; + int addr_rx_power; int page_rx_power; int offset_rx_power; int length_rx_power; + int addr_soft_rs0; int page_soft_rs0; int offset_soft_rs0; int length_soft_rs0; + int addr_soft_rs1; int page_soft_rs1; int offset_soft_rs1; int length_soft_rs1; + int addr_temp; int page_temp; int offset_temp; int length_temp; + int addr_trancomp; int page_trancomp; int offset_trancomp; int length_trancomp; + int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext; + int addr_tx_bias; int page_tx_bias; int offset_tx_bias; int length_tx_bias; + int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable; + int addr_tx_eq; int page_tx_eq; int offset_tx_eq; int length_tx_eq; + int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault; + int addr_tx_power; int page_tx_power; int offset_tx_power; int length_tx_power; + int addr_vendor_name; int page_vendor_name; int offset_vendor_name; int length_vendor_name; + int addr_vendor_pn; int page_vendor_pn; int offset_vendor_pn; int length_vendor_pn; + int addr_vendor_rev; int page_vendor_rev; int offset_vendor_rev; int length_vendor_rev; + int addr_vendor_sn; int page_vendor_sn; int offset_vendor_sn; int length_vendor_sn; + int addr_voltage; int page_voltage; int offset_voltage; int length_voltage; + int addr_wavelength; int page_wavelength; int offset_wavelength; int length_wavelength; +}; + + +struct transvr_worker_s; + +/* Class of transceiver object */ +struct transvr_obj_s { + + /* ========== Object private property ========== + * [Prop]: id + * [Desc]: Type of serial transceiver. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h + */ + uint8_t id; + + /* [Prop]: connector + * [Desc]: Connector type. + * [Note]: SFP : A0h / 2 + * QSFP: 00h / 130 + */ + uint8_t connector; + + /* [Prop]: transvr_comp + * [Desc]: Transceiver compliance code. + * [Note]: SFP: SFF-8472 + * - Normal : A0h / offset 3-10 + * - Extended: A0h / offset 36 + * QSFP: SFF-8436 & SFF-8636 + * - Normal : 00h / offset 131-138 + * - Extended: 00h / offset 192 + */ + uint8_t transvr_comp[8]; + uint8_t transvr_comp_ext; + + /* [Prop]: vendor_name + * [Desc]: SFP vendor name (ASCII 16 byte char). + * [Note]: ex:FINISAR CORP. + */ + char *vendor_name; + + /* [Prop]: vendor_pn + * [Desc]: Part number provided by SFP vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_pn; + + /* [Prop]: vendor_rev + * [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char). + * [Note]: + */ + char *vendor_rev; + + /* [Prop]: vendor_sn + * [Desc]: Serial number provided by vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_sn; + + /* [Prop]: Extended identifier + * [Desc]: SFP: + * => None + * + * QSFP: + * => This byte contained two information: + * (1) Power consumption class + * (2) CDR function present + * [Note]: Bit description as below: + * [SFP] + * None + * + * [QSFP] + * (1) Power consumption class: + * Class 1: 1.5W (Bit6-7 = 00:) + * Class 2: 2.0W (Bit6-7 = 01:) + * Class 3: 2.5W (Bit6-7 = 10:) + * Class 4: 3.5W (Bit6-7 = 11:) + * Class 5: 4.0W (Bit0-1 = 01:) + * Class 6: 4.5W (Bit0-1 = 10:) + * Class 7: 5.0W (Bit0-1 = 11:) + * (2) CDR function present: + * Bit2: 0 = No CDR in RX + * 1 = CDR present in RX + * Bit3: 0 = No CDR in TX + * 1 = CDR present in TX + */ + uint8_t ext_id; + + /* [Prop]: br + * [Desc]: Nominal bit rate, units of 100 MBits/sec. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh + * has val: 0x67 + * no val : + */ + uint8_t br; + + /* [Prop]: extbr + * [Desc]: Extended br (00h/222) + * [Desc]: Nominal bit rate per channel, units of 250 Mbps. + * Complements. Byte 140. See Table 32A. + */ + uint8_t extbr; + + /* [Prop]: len_sm + * [Desc]: Length (single mode)-(100's)m + * [Note]: This value specifies the link length that is supported by the transceiver + * while operating in compliance with the applicable standards using single mode + * fiber. The value is in units of 100 meters. A value of 255 means that the + * transceiver supports a link length greater than 25.4 km. A value of zero means + * that the transceiver does not support single mode fiber or that the length + * information must be determined from the transceiver technology. + */ + int len_sm; + + /* [Prop]: len_smf + * [Desc]: Length (single mode)-km + * [Note]: Addition to EEPROM data from original GBIC definition. This value specifies + * the link length that is supported by the transceiver while operating in + * compliance with the applicable standards using single mode fiber. The value + * is in units of kilometers. A value of 255 means that the transceiver supports + * a link length greater than 254 km. A value of zero means that the transceiver + * does not support single mode fiber or that the length information must be + * determined from the transceiver technology. + */ + int len_smf; + + /* [Prop]: len_om1 + * [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om1; + + /* [Prop]: len_om2 + * [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om2; + + /* [Prop]: len_om3 + * [Desc]: Length (50um, OM3) + * [Note]: This value specifies link length that is supported by the transceiver while + * operating in compliance with applicable standards using 50 micron multimode + * OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255 + * means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber + * or that the length information must be determined from the transceiver technology. + */ + int len_om3; + + /* [Prop]: len_om4 + * [Desc]: Length (50um, OM4) and Length (Active Cable or Copper) + * [Note]: For optical links, this value specifies link length that is supported by the + * transceiver while operating in compliance with applicable standards using 50 micron + * multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of + * 255 means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber or that + * the length information must be determined from the transceiver codes specified in Table 5-3. + * + * For copper links, this value specifies minimum link length supported by the transceiver + * while operating in compliance with applicable standards using copper cable. For active + * cable, this value represents actual length. The value is in units of 1 meter. A value of 255 + * means the transceiver supports a link length greater than 254 meters. A value of zero means + * the transceiver does not support copper or active cables or the length information must be + * determined from transceiver technology. Further information about cable design, equalization, + * and connectors is usually required to guarantee meeting a particular length requirement. + */ + int len_om4; + + /* [Prop]: comp_rev + * [Desc]: SFF spec revision compliance + * [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver + * complies with. (unsigned integer) + */ + uint8_t comp_rev; + + /* [Prop]: CDR + * [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal + * retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which + * directs traffic around the internal CDR. (Reference: SFF-8636) + * [Note]: value=0xff: ON. + * value=0x00: OFF. + */ + uint8_t cdr; + + /* [Prop]: rate_id + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Addr: A0h / Offset: 13 + * 2. Value description: + * 00h Unspecified + * 01h SFF-8079 (4/2/1G Rate_Select & AS0/AS1) + * 02h SFF-8431 (8/4/2G Rx Rate_Select only) + * 03h Unspecified * + * 04h SFF-8431 (8/4/2G Tx Rate_Select only) + * 05h Unspecified * + * 06h SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) + * 07h Unspecified * + * 08h FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G + * 09h Unspecified * + * 0Ah FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only, + * Low=8G/4G + * 0Bh Unspecified * + * 0Ch FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + * 0Dh Unspecified * + * 0Eh 10/8G Rx and Tx Rate_Select controlling the operation or locking + * modes of the internal signal conditioner, retimer or CDR, according + * to the logic table defined in Table 10-2, High Bit Rate + * (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode, + * the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11) + * and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1. + * 0Fh Unspecified * + * 10h-FFh Unallocated + */ + int rate_id; + + /* [Prop]: soft_rs0 + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Writing '1' selects full bandwidth operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 110 / Bit: 3 + */ + uint8_t soft_rs0; + + /* [Prop]: soft_rs1 + * [Desc]: Soft Rate Select 1(TX). + * [Note]: 1. Writing '1' selects full bandwidth TX operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 118 / Bit: 3 + */ + uint8_t soft_rs1; + + /* [Prop]: diag_type + * [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92) + * [Note]: Description in SFF-8472 as below: + * Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance + * with this document. + * Bit6: Digital diagnostic monitoring implemented (described in this document). + * Must be '1' for compliance with this document. + * Bit5 Internally calibrated + * Bit4 Externally calibrated + * Bit3 Received power measurement type.0 = OMA, 1 = average power + * Bit2 Address change required see section above, "addressing modes" + * Bit1-0 Unallocated + */ + uint8_t diag_type; + + /* [Prop]: curr_temp + * [Desc]: Transceiver Current Temperature (A2h/96-97) + * [Note]: 1. Dependent on diag_type. + * 2. 96: High byte + * 3. 97: Low byte + * 4. This feature only for SFP + */ + uint8_t curr_temp[2]; + + /* [Prop]: curr_vol + * [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23) + * [Note]: 1. Dependent on diag_type. + * 2. 98: High byte + * 3. 99: Low byte + * 4. This feature only for SFP + * 5. Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts + */ + uint8_t curr_voltage[2]; + + /* [Prop]: curr_tx_bias + * [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27) + * [Note]: 1. Dependent on diag_type. + * 2. 100: High byte + * 3. 101: Low byte + * 4. This feature only for SFP + * 5. Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + uint8_t curr_tx_bias[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + uint8_t curr_tx_power[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + uint8_t curr_rx_power[8]; + + /* [Prop]: wavelength + * [Desc]: Wavelength or Copper Cable Attenuation + * [Note]: (Following is info from SFF-8636) + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is a + * 16-bit hex value with Byte 186 as high order byte and Byte 187 as low + * order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. If the free side device is identified as + * copper cable these registers will be used to define the cable attenuation. + * An indication of 0 dB attenuation refers to the case where the attenuation + * is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + uint8_t wavelength[2]; + + /* [Prop]: Amplitude control + * [Desc]: Amplitude control + * [Note]: QSFP28 => SFF-8636 03H Byte-238/239 + */ + uint8_t rx_am[2]; + + /* [Prop]: Emphasis control + * [Desc]: Emphasis control + * [Note]: SFP+/28 => SFF-8472 A2H Byte-115 + * QSFP28 => SFF-8636 03H Byte-236/237 + */ + uint8_t rx_em[2]; + + /* [Prop]: Soft Rx LOS + * [Desc]: Soft Rx LOS which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 3: + * - Bit 0: L-Rx1 LOS + * - Bit 1: L-Rx2 LOS + * - Bit 2: L-Rx3 LOS + * - Bit 3: L-Rx4 LOS + */ + uint8_t rx_los; + + /* [Prop]: Soft Tx Disable + * [Desc]: Soft Tx Disable which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Disable + * - Bit 1: Tx2 Disable + * - Bit 2: Tx3 Disable + * - Bit 3: Tx4 Disable + */ + uint8_t tx_disable; + + /* [Prop]: Soft Tx Fault + * [Desc]: Soft Tx Fault which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Fault + * - Bit 1: Tx2 Fault + * - Bit 2: Tx3 Fault + * - Bit 3: Tx4 Fault + */ + uint8_t tx_fault; + + /* [Prop]: Transceiver EQUALIZATION + * [Desc]: Transceiver EQUALIZATION + * [Note]: SFP+/28 => SFF-8472 A2H Byte-114 + * QSFP28 => SFF-8636 03H Byte-234/235 + */ + uint8_t tx_eq[2]; + + /* [Prop]: OPTION VALUES + * [Desc]: The bits in the option field shall specify the options implemented in the transceiver. + * [Note]: SFP+/28 => SFF-8472 A0H Byte-64/65 + * QSFP+/28 => SFF-8636 00H Byte-193/195 + */ + uint8_t option[3]; + + /* [Prop]: External PHY offset + * [Desc]: It needs to be setup first if you want to access transceiver external phy. + * [Note]: This feature dependent on transceiver. + * Currently, only 1G-RJ45 transceiver supported it. + */ + uint8_t extphy_offset; + + /* ========== Object private property ========== + */ + struct device *transvr_dev_p; + struct eeprom_map_s *eeprom_map_p; + struct i2c_client *i2c_client_p; + struct ioexp_obj_s *ioexp_obj_p; + struct transvr_worker_s *worker_p; + struct mutex lock; + char swp_name[32]; + int auto_config; + int auto_tx_disable; + int chan_id; + int chipset_type; + int curr_page; + int info; + int ioexp_virt_offset; + int lane_id[8]; + int layout; + int mode; + int retry; + int state; + int temp; + int type; + + /* ========== Object public functions ========== + */ + int (*get_id)(struct transvr_obj_s *self); + int (*get_ext_id)(struct transvr_obj_s *self); + int (*get_connector)(struct transvr_obj_s *self); + int (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p); + int (*get_power_cls)(struct transvr_obj_s *self); + int (*get_br)(struct transvr_obj_s *self); + int (*get_len_sm)(struct transvr_obj_s *self); + int (*get_len_smf)(struct transvr_obj_s *self); + int (*get_len_om1)(struct transvr_obj_s *self); + int (*get_len_om2)(struct transvr_obj_s *self); + int (*get_len_om3)(struct transvr_obj_s *self); + int (*get_len_om4)(struct transvr_obj_s *self); + int (*get_comp_rev)(struct transvr_obj_s *self); + int (*get_comp_eth_1)(struct transvr_obj_s *self); + int (*get_comp_eth_10)(struct transvr_obj_s *self); + int (*get_comp_eth_10_40)(struct transvr_obj_s *self); + int (*get_comp_extend)(struct transvr_obj_s *self); + int (*get_cdr)(struct transvr_obj_s *self); + int (*get_rate_id)(struct transvr_obj_s *self); + int (*get_soft_rs0)(struct transvr_obj_s *self); + int (*get_soft_rs1)(struct transvr_obj_s *self); + int (*get_info)(struct transvr_obj_s *self); + int (*get_if_type)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_speed)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_lane)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p); + int (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_am)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_em)(struct transvr_obj_s *self, char *buf_p); + int (*get_wavelength)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_offset)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_reg)(struct transvr_obj_s *self, char *buf_p); + int (*set_cdr)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs0)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs1)(struct transvr_obj_s *self, int input_val); + int (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_tx_eq)(struct transvr_obj_s *self, int input_val); + int (*set_rx_am)(struct transvr_obj_s *self, int input_val); + int (*set_rx_em)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_offset)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_reg)(struct transvr_obj_s *self, int input_val); + + /* ========== Object private functions ========== + */ + int (*init)(struct transvr_obj_s *self); + int (*clean)(struct transvr_obj_s *self); + int (*check)(struct transvr_obj_s *self); + int (*update_all)(struct transvr_obj_s *self, int show_err); + int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name); + int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name); + int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action); + int (*dump_all)(struct transvr_obj_s* self); +}; + + +/* For AVL Mapping */ +struct transvr_avl_s { + char vendor_name[32]; + char vendor_pn[32]; + int (*init)(struct transvr_obj_s *self); +}; + + +/* Worker for long term task of transceiver */ +struct transvr_worker_s { + /* Task Parameter */ + struct transvr_obj_s *transvr_p; + struct transvr_worker_s *next_p; + struct transvr_worker_s *pre_p; + unsigned long trigger_time; + char func_name[64]; + int retry; + int state; + + /* Task private data */ + void *p_data; + + /* Call back function */ + int (*main_task)(struct transvr_worker_s *task); + int (*post_task)(struct transvr_worker_s *task); +}; + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode); + +void lock_transvr_obj(struct transvr_obj_s *self); +void unlock_transvr_obj(struct transvr_obj_s *self); +int isolate_transvr_obj(struct transvr_obj_s *self); + +int resync_channel_tier_2(struct transvr_obj_s *self); + +void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + +#endif /* TRANSCEIVER_H */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/utils/inventec_d6254_util.py b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/utils/inventec_d6254_util.py new file mode 100644 index 000000000000..31cf736dafb4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/utils/inventec_d6254_util.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Inventec, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[D6254]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +"with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +instantiate =[ +#'echo pca9548 0x71> /sys/bus/i2c/devices/i2c-0/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-2/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-3/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-4/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-5/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-6/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-7/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-8/new_device', +'echo inv_eeprom 0x53 > /sys/bus/i2c/devices/i2c-0/new_device'] +#'echo inv_psoc 0x66> /sys/bus/i2c/devices/i2c-0/new_device', +#'echo inv_cpld 0x55> /sys/bus/i2c/devices/i2c-0/new_device'] + +drivers =[ +'gpio_ich', +'lpc_ich', +'i2c-i801', +'i2c-mux', +'i2c-mux-pca954x', +'i2c-dev', +'inv_eeprom', +'inv_platform', +'inv_psoc', +'inv_cpld', +'swps', +'inv_pthread'] + + + +def system_install(): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("rmmod i2c_ismt ", 1) + status, output = exec_cmd("rmmod i2c-i801 ", 1) + #install drivers + for i in range(0,len(drivers)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #instantiate devices + for i in range(0,len(instantiate)): + #time.sleep(1) + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(10,18): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-2/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(18,26): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-3/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(26,34): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-4/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(34,42): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-5/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(42,50): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-6/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(50,58): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-7/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(58,64): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-8/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print " D6254 devices detected...." + return + +def uninstall(): + global FORCE + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0) + ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/Makefile new file mode 100755 index 000000000000..7cb80a281baf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/Makefile @@ -0,0 +1,8 @@ +obj-m += gpio-ich.o +obj-m += lpc_ich.o +obj-m += inv_cpld.o +obj-m += inv_platform.o +obj-m += inv_eeprom.o +obj-m += i2c-mux-pca9541.o +obj-m += swps.o +swps-objs := inv_swps.o inv_mux.o io_expander.o transceiver.o diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/gpio-ich.c b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/gpio-ich.c new file mode 100644 index 000000000000..687834e3c561 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/gpio-ich.c @@ -0,0 +1,513 @@ +/* + * Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver + * + * Copyright (C) 2010 Extreme Engineering Solutions. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "gpio_ich" + +/* + * GPIO register offsets in GPIO I/O space. + * Each chunk of 32 GPIOs is manipulated via its own USE_SELx, IO_SELx, and + * LVLx registers. Logic in the read/write functions takes a register and + * an absolute bit number and determines the proper register offset and bit + * number in that register. For example, to read the value of GPIO bit 50 + * the code would access offset ichx_regs[2(=GPIO_LVL)][1(=50/32)], + * bit 18 (50%32). + */ +enum GPIO_REG { + GPIO_USE_SEL = 0, + GPIO_IO_SEL, + GPIO_LVL, + GPO_BLINK +}; + +static const u8 ichx_regs[4][3] = { + {0x00, 0x30, 0x40}, /* USE_SEL[1-3] offsets */ + {0x04, 0x34, 0x44}, /* IO_SEL[1-3] offsets */ + {0x0c, 0x38, 0x48}, /* LVL[1-3] offsets */ + {0x18, 0x18, 0x18}, /* BLINK offset */ +}; + +static const u8 ichx_reglen[3] = { + 0x30, 0x10, 0x10, +}; + +static const u8 avoton_regs[4][3] = { + {0x00, 0x80, 0x00}, + {0x04, 0x84, 0x00}, + {0x08, 0x88, 0x00}, +}; + +static const u8 avoton_reglen[3] = { + 0x10, 0x10, 0x00, +}; + +#define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start) +#define ICHX_READ(reg, base_res) inl((reg) + (base_res)->start) + +struct ichx_desc { + /* Max GPIO pins the chipset can have */ + uint ngpio; + + /* chipset registers */ + const u8 (*regs)[3]; + const u8 *reglen; + + /* GPO_BLINK is available on this chipset */ + bool have_blink; + + /* Whether the chipset has GPIO in GPE0_STS in the PM IO region */ + bool uses_gpe0; + + /* USE_SEL is bogus on some chipsets, eg 3100 */ + u32 use_sel_ignore[3]; + + /* Some chipsets have quirks, let these use their own request/get */ + int (*request)(struct gpio_chip *chip, unsigned offset); + int (*get)(struct gpio_chip *chip, unsigned offset); + + /* + * Some chipsets don't let reading output values on GPIO_LVL register + * this option allows driver caching written output values + */ + bool use_outlvl_cache; +}; + +static struct { + spinlock_t lock; + struct platform_device *dev; + struct gpio_chip chip; + struct resource *gpio_base; /* GPIO IO base */ + struct resource *pm_base; /* Power Mangagment IO base */ + struct ichx_desc *desc; /* Pointer to chipset-specific description */ + u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */ + u8 use_gpio; /* Which GPIO groups are usable */ + int outlvl_cache[3]; /* cached output values */ +} ichx_priv; + +static int modparam_gpiobase = 0; /* dynamic */ +module_param_named(gpiobase, modparam_gpiobase, int, 0444); +MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, " + "which is the default."); + +static int ichx_write_bit(int reg, unsigned nr, int val, int verify) +{ + unsigned long flags; + u32 data, tmp; + int reg_nr = nr / 32; + int bit = nr & 0x1f; + int ret = 0; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + data = ichx_priv.outlvl_cache[reg_nr]; + else + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + + if (val) + data |= 1 << bit; + else + data &= ~(1 << bit); + ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + ichx_priv.outlvl_cache[reg_nr] = data; + + tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + if (verify && data != tmp) + ret = -EPERM; + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return ret; +} + +static int ichx_read_bit(int reg, unsigned nr) +{ + unsigned long flags; + u32 data; + int reg_nr = nr / 32; + int bit = nr & 0x1f; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + data = ichx_priv.outlvl_cache[reg_nr] | data; + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return data & (1 << bit) ? 1 : 0; +} + +static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) +{ + return !!(ichx_priv.use_gpio & (1 << (nr / 32))); +} + +static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr) +{ + return ichx_read_bit(GPIO_IO_SEL, nr) ? GPIOF_DIR_IN : GPIOF_DIR_OUT; +} + +static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) +{ + /* + * Try setting pin as an input and verify it worked since many pins + * are output-only. + */ + if (ichx_write_bit(GPIO_IO_SEL, nr, 1, 1)) + return -EINVAL; + + return 0; +} + +static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, + int val) +{ + /* Disable blink hardware which is available for GPIOs from 0 to 31. */ + if (nr < 32 && ichx_priv.desc->have_blink) + ichx_write_bit(GPO_BLINK, nr, 0, 0); + + /* Set GPIO output value. */ + ichx_write_bit(GPIO_LVL, nr, val, 0); + + /* + * Try setting pin as an output and verify it worked since many pins + * are input-only. + */ + if (ichx_write_bit(GPIO_IO_SEL, nr, 0, 1)) + return -EINVAL; + + return 0; +} + +static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + return ichx_read_bit(GPIO_LVL, nr); +} + +static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + unsigned long flags; + u32 data; + + /* + * GPI 0 - 15 need to be read from the power management registers on + * a ICH6/3100 bridge. + */ + if (nr < 16) { + if (!ichx_priv.pm_base) + return -ENXIO; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + /* GPI 0 - 15 are latched, write 1 to clear*/ + ICHX_WRITE(1 << (16 + nr), 0, ichx_priv.pm_base); + data = ICHX_READ(0, ichx_priv.pm_base); + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return (data >> 16) & (1 << nr) ? 1 : 0; + } else { + return ichx_gpio_get(chip, nr); + } +} + +static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr) +{ + if (!ichx_gpio_check_available(chip, nr)) + return -ENXIO; + + /* + * Note we assume the BIOS properly set a bridge's USE value. Some + * chips (eg Intel 3100) have bogus USE values though, so first see if + * the chipset's USE value can be trusted for this specific bit. + * If it can't be trusted, assume that the pin can be used as a GPIO. + */ + if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f))) + return 0; + + return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV; +} + +static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr) +{ + /* + * Fixups for bits 16 and 17 are necessary on the Intel ICH6/3100 + * bridge as they are controlled by USE register bits 0 and 1. See + * "Table 704 GPIO_USE_SEL1 register" in the i3100 datasheet for + * additional info. + */ + if (nr == 16 || nr == 17) + nr -= 16; + + return ichx_gpio_request(chip, nr); +} + +static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val) +{ + ichx_write_bit(GPIO_LVL, nr, val, 0); +} + +static void ichx_gpiolib_setup(struct gpio_chip *chip) +{ + chip->owner = THIS_MODULE; + chip->label = DRV_NAME; + chip->parent = &ichx_priv.dev->dev; + + /* Allow chip-specific overrides of request()/get() */ + chip->request = ichx_priv.desc->request ? + ichx_priv.desc->request : ichx_gpio_request; + chip->get = ichx_priv.desc->get ? + ichx_priv.desc->get : ichx_gpio_get; + + chip->set = ichx_gpio_set; + chip->get_direction = ichx_gpio_get_direction; + chip->direction_input = ichx_gpio_direction_input; + chip->direction_output = ichx_gpio_direction_output; + chip->base = modparam_gpiobase; + chip->ngpio = ichx_priv.desc->ngpio; + chip->can_sleep = false; + chip->dbg_show = NULL; +} + +/* ICH6-based, 631xesb-based */ +static struct ichx_desc ich6_desc = { + /* Bridges using the ICH6 controller need fixups for GPIO 0 - 17 */ + .request = ich6_gpio_request, + .get = ich6_gpio_get, + + /* GPIO 0-15 are read in the GPE0_STS PM register */ + .uses_gpe0 = true, + + .ngpio = 50, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Intel 3100 */ +static struct ichx_desc i3100_desc = { + /* + * Bits 16,17, 20 of USE_SEL and bit 16 of USE_SEL2 always read 0 on + * the Intel 3100. See "Table 712. GPIO Summary Table" of 3100 + * Datasheet for more info. + */ + .use_sel_ignore = {0x00130000, 0x00010000, 0x0}, + + /* The 3100 needs fixups for GPIO 0 - 17 */ + .request = ich6_gpio_request, + .get = ich6_gpio_get, + + /* GPIO 0-15 are read in the GPE0_STS PM register */ + .uses_gpe0 = true, + + .ngpio = 50, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH7 and ICH8-based */ +static struct ichx_desc ich7_desc = { + .ngpio = 50, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH9-based */ +static struct ichx_desc ich9_desc = { + .ngpio = 61, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH10-based - Consumer/corporate versions have different amount of GPIO */ +static struct ichx_desc ich10_cons_desc = { + .ngpio = 61, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; +static struct ichx_desc ich10_corp_desc = { + .ngpio = 72, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Intel 5 series, 6 series, 3400 series, and C200 series */ +static struct ichx_desc intel5_desc = { + .ngpio = 76, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Avoton */ +static struct ichx_desc avoton_desc = { + /* Avoton has only 59 GPIOs, but we assume the first set of register + * (Core) has 32 instead of 31 to keep gpio-ich compliance + */ + .ngpio = 60, + .regs = avoton_regs, + .reglen = avoton_reglen, + .use_outlvl_cache = true, +}; + +static int ichx_gpio_request_regions(struct device *dev, + struct resource *res_base, const char *name, u8 use_gpio) +{ + int i; + + if (!res_base || !res_base->start || !res_base->end) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { + if (!(use_gpio & (1 << i))) + continue; + if (!devm_request_region(dev, + res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i], name)) + return -EBUSY; + } + return 0; +} + +static int ichx_gpio_probe(struct platform_device *pdev) +{ + struct resource *res_base, *res_pm; + int err; + struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev); + + if (!ich_info) + return -ENODEV; + + ichx_priv.dev = pdev; + + switch (ich_info->gpio_version) { + case ICH_I3100_GPIO: + ichx_priv.desc = &i3100_desc; + break; + case ICH_V5_GPIO: + ichx_priv.desc = &intel5_desc; + break; + case ICH_V6_GPIO: + ichx_priv.desc = &ich6_desc; + break; + case ICH_V7_GPIO: + ichx_priv.desc = &ich7_desc; + break; + case ICH_V9_GPIO: + ichx_priv.desc = &ich9_desc; + break; + case ICH_V10CORP_GPIO: + ichx_priv.desc = &ich10_corp_desc; + break; + case ICH_V10CONS_GPIO: + ichx_priv.desc = &ich10_cons_desc; + break; + case AVOTON_GPIO: + ichx_priv.desc = &avoton_desc; + break; + default: + return -ENODEV; + } + + spin_lock_init(&ichx_priv.lock); + res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); + ichx_priv.use_gpio = ich_info->use_gpio; + err = ichx_gpio_request_regions(&pdev->dev, res_base, pdev->name, + ichx_priv.use_gpio); + if (err) + return err; + + ichx_priv.gpio_base = res_base; + + /* + * If necessary, determine the I/O address of ACPI/power management + * registers which are needed to read the the GPE0 register for GPI pins + * 0 - 15 on some chipsets. + */ + if (!ichx_priv.desc->uses_gpe0) + goto init; + + res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0); + if (!res_pm) { + pr_warn("ACPI BAR is unavailable, GPI 0 - 15 unavailable\n"); + goto init; + } + + if (!devm_request_region(&pdev->dev, res_pm->start, + resource_size(res_pm), pdev->name)) { + pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n"); + goto init; + } + + ichx_priv.pm_base = res_pm; + +init: + ichx_gpiolib_setup(&ichx_priv.chip); + err = gpiochip_add_data(&ichx_priv.chip, NULL); + if (err) { + pr_err("Failed to register GPIOs\n"); + return err; + } + + pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base, + ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME); + + return 0; +} + +static int ichx_gpio_remove(struct platform_device *pdev) +{ + gpiochip_remove(&ichx_priv.chip); + + return 0; +} + +static struct platform_driver ichx_gpio_driver = { + .driver = { + .name = DRV_NAME, + }, + .probe = ichx_gpio_probe, + .remove = ichx_gpio_remove, +}; + +module_platform_driver(ichx_gpio_driver); + +MODULE_AUTHOR("Peter Tyser "); +MODULE_DESCRIPTION("GPIO interface for Intel ICH series"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/i2c-gpio.c b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/i2c-gpio.c new file mode 100644 index 000000000000..9b4aa7ec9e6c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/i2c-gpio.c @@ -0,0 +1,290 @@ +/* + * Bitbanging I2C bus driver using the GPIO API + * + * Copyright (C) 2007 Atmel Corporation + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct i2c_gpio_private_data { + struct i2c_adapter adap; + struct i2c_algo_bit_data bit_data; + struct i2c_gpio_platform_data pdata; +}; + +/* Toggle SDA by changing the direction of the pin */ +static void i2c_gpio_setsda_dir(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + if (state) + gpio_direction_input(pdata->sda_pin); + else + gpio_direction_output(pdata->sda_pin, 0); +} + +/* + * Toggle SDA by changing the output value of the pin. This is only + * valid for pins configured as open drain (i.e. setting the value + * high effectively turns off the output driver.) + */ +static void i2c_gpio_setsda_val(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + gpio_set_value(pdata->sda_pin, state); +} + +/* Toggle SCL by changing the direction of the pin. */ +static void i2c_gpio_setscl_dir(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + if (state) + gpio_direction_input(pdata->scl_pin); + else + gpio_direction_output(pdata->scl_pin, 0); +} + +/* + * Toggle SCL by changing the output value of the pin. This is used + * for pins that are configured as open drain and for output-only + * pins. The latter case will break the i2c protocol, but it will + * often work in practice. + */ +static void i2c_gpio_setscl_val(void *data, int state) +{ + struct i2c_gpio_platform_data *pdata = data; + + gpio_set_value(pdata->scl_pin, state); +} + +static int i2c_gpio_getsda(void *data) +{ + struct i2c_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata->sda_pin); +} + +static int i2c_gpio_getscl(void *data) +{ + struct i2c_gpio_platform_data *pdata = data; + + return gpio_get_value(pdata->scl_pin); +} + +static int of_i2c_gpio_get_pins(struct device_node *np, + unsigned int *sda_pin, unsigned int *scl_pin) +{ + if (of_gpio_count(np) < 2) + return -ENODEV; + + *sda_pin = of_get_gpio(np, 0); + *scl_pin = of_get_gpio(np, 1); + + if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER) + return -EPROBE_DEFER; + + if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) { + pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n", + np->full_name, *sda_pin, *scl_pin); + return -ENODEV; + } + + return 0; +} + +static void of_i2c_gpio_get_props(struct device_node *np, + struct i2c_gpio_platform_data *pdata) +{ + u32 reg; + + of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay); + + if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®)) + pdata->timeout = msecs_to_jiffies(reg); + + pdata->sda_is_open_drain = + of_property_read_bool(np, "i2c-gpio,sda-open-drain"); + pdata->scl_is_open_drain = + of_property_read_bool(np, "i2c-gpio,scl-open-drain"); + pdata->scl_is_output_only = + of_property_read_bool(np, "i2c-gpio,scl-output-only"); +} + +static int i2c_gpio_probe(struct platform_device *pdev) +{ + struct i2c_gpio_private_data *priv; + struct i2c_gpio_platform_data *pdata; + struct i2c_algo_bit_data *bit_data; + struct i2c_adapter *adap; + unsigned int sda_pin, scl_pin; + int ret; + + /* First get the GPIO pins; if it fails, we'll defer the probe. */ + if (pdev->dev.of_node) { + ret = of_i2c_gpio_get_pins(pdev->dev.of_node, + &sda_pin, &scl_pin); + if (ret) + return ret; + } else { + if (!dev_get_platdata(&pdev->dev)) + return -ENXIO; + pdata = dev_get_platdata(&pdev->dev); + sda_pin = pdata->sda_pin; + scl_pin = pdata->scl_pin; + } + + ret = devm_gpio_request(&pdev->dev, sda_pin, "sda"); + if (ret) { + if (ret == -EINVAL) + ret = -EPROBE_DEFER; /* Try again later */ + return ret; + } + ret = devm_gpio_request(&pdev->dev, scl_pin, "scl"); + if (ret) { + if (ret == -EINVAL) + ret = -EPROBE_DEFER; /* Try again later */ + return ret; + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + adap = &priv->adap; + bit_data = &priv->bit_data; + pdata = &priv->pdata; + + if (pdev->dev.of_node) { + pdata->sda_pin = sda_pin; + pdata->scl_pin = scl_pin; + of_i2c_gpio_get_props(pdev->dev.of_node, pdata); + } else { + memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata)); + } + + if (pdata->sda_is_open_drain) { + gpio_direction_output(pdata->sda_pin, 1); + bit_data->setsda = i2c_gpio_setsda_val; + } else { + gpio_direction_input(pdata->sda_pin); + bit_data->setsda = i2c_gpio_setsda_dir; + } + + if (pdata->scl_is_open_drain || pdata->scl_is_output_only) { + gpio_direction_output(pdata->scl_pin, 1); + bit_data->setscl = i2c_gpio_setscl_val; + } else { + gpio_direction_input(pdata->scl_pin); + bit_data->setscl = i2c_gpio_setscl_dir; + } + + if (!pdata->scl_is_output_only) + bit_data->getscl = i2c_gpio_getscl; + bit_data->getsda = i2c_gpio_getsda; + + if (pdata->udelay) + bit_data->udelay = pdata->udelay; + else if (pdata->scl_is_output_only) + bit_data->udelay = 50; /* 10 kHz */ + else + bit_data->udelay = 5; /* 100 kHz */ + + if (pdata->timeout) + bit_data->timeout = pdata->timeout; + else + bit_data->timeout = HZ / 10; /* 100 ms */ + + bit_data->data = pdata; + + adap->owner = THIS_MODULE; + if (pdev->dev.of_node) + strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); + else + snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); + + adap->algo_data = bit_data; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; + + adap->nr = pdev->id; + ret = i2c_bit_add_numbered_bus(adap); + if (ret) + return ret; + + platform_set_drvdata(pdev, priv); + + dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", + pdata->sda_pin, pdata->scl_pin, + pdata->scl_is_output_only + ? ", no clock stretching" : ""); + + return 0; +} + +static int i2c_gpio_remove(struct platform_device *pdev) +{ + struct i2c_gpio_private_data *priv; + struct i2c_adapter *adap; + + priv = platform_get_drvdata(pdev); + adap = &priv->adap; + + i2c_del_adapter(adap); + + return 0; +} + +#if defined(CONFIG_OF) +static const struct of_device_id i2c_gpio_dt_ids[] = { + { .compatible = "i2c-gpio", }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids); +#endif + +static struct platform_driver i2c_gpio_driver = { + .driver = { + .name = "i2c-gpio", + .of_match_table = of_match_ptr(i2c_gpio_dt_ids), + }, + .probe = i2c_gpio_probe, + .remove = i2c_gpio_remove, +}; + +static int __init i2c_gpio_init(void) +{ + int ret; + + ret = platform_driver_register(&i2c_gpio_driver); + if (ret) + printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret); + + return ret; +} +subsys_initcall(i2c_gpio_init); + +static void __exit i2c_gpio_exit(void) +{ + platform_driver_unregister(&i2c_gpio_driver); +} +module_exit(i2c_gpio_exit); + +MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); +MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:i2c-gpio"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/i2c-mux-pca9541.c b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/i2c-mux-pca9541.c new file mode 100644 index 000000000000..9e75d6b9140b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/i2c-mux-pca9541.c @@ -0,0 +1,355 @@ +/* + * I2C multiplexer driver for PCA9541 bus master selector + * + * Copyright (c) 2010 Ericsson AB. + * + * Author: Guenter Roeck + * + * Derived from: + * pca954x.c + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The PCA9541 is a bus master selector. It supports two I2C masters connected + * to a single slave bus. + * + * Before each bus transaction, a master has to acquire bus ownership. After the + * transaction is complete, bus ownership has to be released. This fits well + * into the I2C multiplexer framework, which provides select and release + * functions for this purpose. For this reason, this driver is modeled as + * single-channel I2C bus multiplexer. + * + * This driver assumes that the two bus masters are controlled by two different + * hosts. If a single host controls both masters, platform code has to ensure + * that only one of the masters is instantiated at any given time. + */ + +#define PCA9541_CONTROL 0x01 +#define PCA9541_ISTAT 0x02 + +#define PCA9541_CTL_MYBUS (1 << 0) +#define PCA9541_CTL_NMYBUS (1 << 1) +#define PCA9541_CTL_BUSON (1 << 2) +#define PCA9541_CTL_NBUSON (1 << 3) +#define PCA9541_CTL_BUSINIT (1 << 4) +#define PCA9541_CTL_TESTON (1 << 6) +#define PCA9541_CTL_NTESTON (1 << 7) + +#define PCA9541_ISTAT_INTIN (1 << 0) +#define PCA9541_ISTAT_BUSINIT (1 << 1) +#define PCA9541_ISTAT_BUSOK (1 << 2) +#define PCA9541_ISTAT_BUSLOST (1 << 3) +#define PCA9541_ISTAT_MYTEST (1 << 6) +#define PCA9541_ISTAT_NMYTEST (1 << 7) + +#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) +#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) +#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) +#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) + +/* arbitration timeouts, in jiffies */ +#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ +#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ + +/* arbitration retry delays, in us */ +#define SELECT_DELAY_SHORT 50 +#define SELECT_DELAY_LONG 1000 + +struct pca9541 { + struct i2c_client *client; + unsigned long select_timeout; + unsigned long arb_timeout; +}; + +static const struct i2c_device_id pca9541_id[] = { + {"pca9541", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, pca9541_id); + +#ifdef CONFIG_OF +static const struct of_device_id pca9541_of_match[] = { + { .compatible = "nxp,pca9541" }, + {} +}; +MODULE_DEVICE_TABLE(of, pca9541_of_match); +#endif + +/* + * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock the adapter a second time. + */ +static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) +{ + struct i2c_adapter *adap = client->adapter; + union i2c_smbus_data data = { .byte = val }; + + return __i2c_smbus_xfer(adap, client->addr, client->flags, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_BYTE_DATA, &data); +} + +/* + * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock adapter a second time. + */ +static int pca9541_reg_read(struct i2c_client *client, u8 command) +{ + struct i2c_adapter *adap = client->adapter; + union i2c_smbus_data data; + int ret; + + ret = __i2c_smbus_xfer(adap, client->addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data); + + return ret ?: data.byte; +} + +/* + * Arbitration management functions + */ + +/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ +static void pca9541_release_bus(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg >= 0 && !busoff(reg) && mybus(reg)) + pca9541_reg_write(client, PCA9541_CONTROL, + (reg & PCA9541_CTL_NBUSON) >> 1); +} + +/* + * Arbitration is defined as a two-step process. A bus master can only activate + * the slave bus if it owns it; otherwise it has to request ownership first. + * This multi-step process ensures that access contention is resolved + * gracefully. + * + * Bus Ownership Other master Action + * state requested access + * ---------------------------------------------------- + * off - yes wait for arbitration timeout or + * for other master to drop request + * off no no take ownership + * off yes no turn on bus + * on yes - done + * on no - wait for arbitration timeout or + * for other master to release bus + * + * The main contention point occurs if the slave bus is off and both masters + * request ownership at the same time. In this case, one master will turn on + * the slave bus, believing that it owns it. The other master will request + * bus ownership. Result is that the bus is turned on, and master which did + * _not_ own the slave bus before ends up owning it. + */ + +/* Control commands per PCA9541 datasheet */ +static const u8 pca9541_control[16] = { + 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 +}; + +/* + * Channel arbitration + * + * Return values: + * <0: error + * 0 : bus not acquired + * 1 : bus acquired + */ +static int pca9541_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg < 0) + return reg; + + if (busoff(reg)) { + int istat; + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + istat = pca9541_reg_read(client, PCA9541_ISTAT); + if (!(istat & PCA9541_ISTAT_NMYTEST) + || time_is_before_eq_jiffies(data->arb_timeout)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_NTESTON); + data->select_timeout = SELECT_DELAY_SHORT; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (mybus(reg)) { + /* + * Bus is on, and we own it. We are done with acquisition. + * Reset NTESTON and BUSINIT, then return success. + */ + if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg & ~(PCA9541_CTL_NTESTON + | PCA9541_CTL_BUSINIT)); + return 1; + } else { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + if (time_is_before_eq_jiffies(data->arb_timeout)) { + /* Time is up, take the bus and reset it. */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_BUSINIT + | PCA9541_CTL_NTESTON); + } else { + /* Request bus ownership if needed */ + if (!(reg & PCA9541_CTL_NTESTON)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg | PCA9541_CTL_NTESTON); + } + } + return 0; +} + +static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + + do { + ret = pca9541_arbitrate(client); + if (ret) + return ret < 0 ? ret : 0; + + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + pca9541_release_bus(client); + return 0; +} + +/* + * I2C init/probing/exit functions + */ +static int pca9541_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = client->adapter; + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct i2c_mux_core *muxc; + struct pca9541 *data; + int force; + int ret; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + /* + * I2C accesses are unprotected here. + * We have to lock the I2C segment before releasing the bus. + */ + i2c_lock_bus(adap, I2C_LOCK_SEGMENT); + pca9541_release_bus(client); + i2c_unlock_bus(adap, I2C_LOCK_SEGMENT); + + /* Create mux adapter */ + + force = 0; + if (pdata) + force = pdata->modes[0].adap_id; + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9541_select_chan, pca9541_release_chan); + if (!muxc) + return -ENOMEM; + + data = i2c_mux_priv(muxc); + data->client = client; + + i2c_set_clientdata(client, muxc); + + ret = i2c_mux_add_adapter(muxc, force, 0, 0); + if (ret) + return ret; + + dev_info(&client->dev, "registered master selector for I2C %s\n", + client->name); + + return 0; +} + +static int pca9541_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + + i2c_mux_del_adapters(muxc); + return 0; +} + +static struct i2c_driver pca9541_driver = { + .driver = { + .name = "pca9541", + .of_match_table = of_match_ptr(pca9541_of_match), + }, + .probe = pca9541_probe, + .remove = pca9541_remove, + .id_table = pca9541_id, +}; + +module_i2c_driver(pca9541_driver); + +MODULE_AUTHOR("Guenter Roeck "); +MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_cpld.c new file mode 100644 index 000000000000..883c8b7b00e9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_cpld.c @@ -0,0 +1,1571 @@ +/* + * 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 + +#define USE_SMBUS 1 +#define CPLD_POLLING_PERIOD 1000 +#define ENABLE_SIMULATE 0 +#define ENABLE_AUTOFAN 1 + +#define CPLD2_ADDRESS 0x33 +static struct i2c_client *client2; +static u8 hasCPLD2 = 1; + +#if ENABLE_SIMULATE + u8 sim_register[0x90]; +#endif + +/* definition */ +#define CPLD_INFO_OFFSET 0x00 +#define CPLD_BIOSCS_OFFSET 0x04 +#define CPLD_CTL_OFFSET 0x0C +#define CPLD_LED_OFFSET 0x2E +#define CPLD_INT_OFFSET 0x30 +#define CPLD_INTMASK_OFFSET 0x31 +#define CPLD_INT2_OFFSET 0x32 +#define CPLD_INTMASK2_OFFSET 0x33 +#define CPLD_PSU_OFFSET 0x40 +#define CPLD_POWERSTATUS_OFFSET 0x41 +#define CPLD_PWM_OFFSET 0x50 +#define CPLD_RPM_OFFSET 0x55 +#define CPLD_FANSTATUS_OFFSET 0x69 +#define CPLD_FANLED_OFFSET 0x6B +#define CPLD_RESETBUTTONSTATUS_OFFSET 0x75 +#define CPLD_RSTCAUSE_OFFSET 0x76 +#define CPLD_WATCHDOGCOUNTER_OFFSET 0x77 +#define CPLD_WATCHDOGCONFIG_OFFSET 0x78 +#define CPLD_WATCHDOGENABLE_OFFSET 0x79 +#define CPLD_PANICCODE_OFFSET 0x7E +#define FAN_NUM 5 +#define PWM_MIN 30 +#define PWM_DEFAULT 150 + +/* Each client has this additional data */ +struct cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; + struct task_struct *cpld_thread; + u8 diag; + u8 model; + u8 fan_direction; + u8 operation_command; + u8 stack_mode; +}; + +/*-----------------------------------------------------------------------*/ +static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ +#if ENABLE_SIMULATE + memcpy(buf,&sim_register[offset],count); + return count; +#else +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +#endif +} + +static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if ENABLE_SIMULATE + memcpy(&sim_register[offset],buf,count); + return count; +#else +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +#endif +} + +/*-----------------------------------------------------------------------*/ +/* sysfs attributes for hwmon */ + +static char* model_str[] = { + "10GBaseT", //0 + "SFP", //1 +}; + +static char* fandirection_str[] = { + "Rear-to-Front", //0 + "Front-to-Rear", //1 +}; + +static ssize_t show_info(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte[4] = {0,0,0,0}; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, byte, CPLD_INFO_OFFSET, 4); + mutex_unlock(&data->update_lock); + + sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", + byte[2] & 0xf, (byte[3] & 0x1f), 2014+(byte[2] >> 4)); /* mm/dd/yyyy*/ + sprintf (buf, "%sThe Model is %s %s\n", buf, model_str[(byte[0]>>5) & 0x01],fandirection_str[(byte[0]>>7) & 0x01]); + sprintf (buf, "%sThe PCB version is %X\n", buf, byte[0]&0xf); + sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, byte[1]>>4, byte[1]&0xf); + + if(hasCPLD2) { + mutex_lock(&data->update_lock); + cpld_i2c_read(client2, byte, CPLD_INFO_OFFSET, 4); + mutex_unlock(&data->update_lock); + + sprintf (buf, "%s\nThe CPLD2 release date is %02d/%02d/%d.\n", buf, + byte[2] & 0xf, (byte[3] & 0x1f), 2014+(byte[2] >> 4)); /* mm/dd/yyyy*/ + sprintf (buf, "%sThe CPLD2 version is %d.%d\n", buf, byte[1]>>4, byte[1]&0xf); + } + + return strlen(buf); +} + +static char* powerstatus_str[] = { + "Failed", //0 + "Good", //1 +}; + +static ssize_t show_powerstatus(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte[2] = {0,0}; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client2, byte, CPLD_POWERSTATUS_OFFSET, 2); + mutex_unlock(&data->update_lock); + + sprintf (buf, "PGD_P5V: %s\n", powerstatus_str[(byte[0]>>7) & 0x01]); + sprintf (buf, "%sPGD_P3V3_STBY: %s\n", buf, powerstatus_str[(byte[0]>>6) & 0x01]); + //if(data->model==0) sprintf (buf, "%sPGD_P1V88: %s\n", buf, powerstatus_str[(byte[0]>>5) & 0x01]); + sprintf (buf, "%sPGD_P1V8_A: %s\n", buf, powerstatus_str[(byte[0]>>4) & 0x01]); + sprintf (buf, "%sPGD_P3V3_SYS: %s\n", buf, powerstatus_str[(byte[0]>>3) & 0x01]); + sprintf (buf, "%sPGD_P3V3_A: %s\n", buf, powerstatus_str[(byte[0]>>2) & 0x01]); + sprintf (buf, "%sPGD_P3V3_B: %s\n", buf, powerstatus_str[(byte[0]>>1) & 0x01]); + sprintf (buf, "%sPGD_P1V2: %s\n", buf, powerstatus_str[(byte[0]>>0) & 0x01]); + sprintf (buf, "%sPGD_P0V8_A: %s\n", buf,powerstatus_str[(byte[1]>>7) & 0x01]); + sprintf (buf, "%sPGD_P0V89_ROV: %s\n", buf, powerstatus_str[(byte[1]>>6) & 0x01]); + //if(data->model==0) sprintf (buf, "%sPGD_P1V0_A: %s\n", buf, powerstatus_str[(byte[1]>>5) & 0x01]); + //if(data->model==0) sprintf (buf, "%sPGD_P1V0_B: %s\n", buf, powerstatus_str[(byte[1]>>4) & 0x01]); + sprintf (buf, "%sSW_PWR_READY: %s\n", buf, powerstatus_str[(byte[1]>>3) & 0x01]); + //sprintf (buf, "%sCORE_PWRGD_TO_CPLD: %s\n", buf, powerstatus_str[(byte[1]>>2) & 0x01]); + //sprintf (buf, "%sCPU_STBY_PWROK: %s\n", buf, powerstatus_str[(byte[1]>>1) & 0x01]); + sprintf (buf, "%sPGD_P1V8_A_STBY: %s\n", buf, powerstatus_str[(byte[1]>>0) & 0x01]); + + return strlen(buf); +} + +static ssize_t show_diag(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + return sprintf (buf, "%d\n", data->diag); +} + +static ssize_t set_diag(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 diag = simple_strtol(buf, NULL, 10); + data->diag = diag?1:0; + return count; +} + +static char* stackmode_str[] = { + "Non-Stack member", //0 + "Stack Master", //1 + "Stack Backup/Member", //2 + "Stack Error", //3 +}; + +static ssize_t show_stackmode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + return sprintf (buf, "%d: %s\n", data->stack_mode,stackmode_str[data->stack_mode]); +} + +static ssize_t set_stackmode(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 stackmode = simple_strtol(buf, NULL, 10); + + if(stackmode<4) data->stack_mode = stackmode; + + return count; +} + +static char* resetbutton_str[] = { + "No press", //0 + "Reserved", //1 + "Press and hold <5s", //2 + "Press and hold >5s", //3 +}; + +static ssize_t show_resetbuttonstatus(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte = 0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_RESETBUTTONSTATUS_OFFSET, 1); + mutex_unlock(&data->update_lock); + byte &=0x03; + + return sprintf (buf, "0x%02X:%s\n", byte,resetbutton_str[byte]); +} + +static char* resetcause_str[] = { + "Power-On", //0 + "Watchdog", //1 + "SoftwareReboot", //2 + "ResetButton", //3 + "Panic", //4 + "ThermalTrip" //5 +}; + +static ssize_t show_resetcause(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte = 0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_RSTCAUSE_OFFSET, 1); + mutex_unlock(&data->update_lock); + + sprintf (buf, "0x%02X:", byte); + if(byte==0) sprintf (buf, "%sNone",buf); + if(byte&0x01) sprintf (buf, "%s%s ",buf,resetcause_str[0]); + if(byte&0x02) sprintf (buf, "%s%s ",buf,resetcause_str[1]); + if(byte&0x04) sprintf (buf, "%s%s ",buf,resetcause_str[2]); + if(byte&0x08) sprintf (buf, "%s%s ",buf,resetcause_str[3]); + if(byte&0x10) sprintf (buf, "%s%s ",buf,resetcause_str[4]); + if(byte&0x20) sprintf (buf, "%s%s ",buf,resetcause_str[5]); + return sprintf (buf, "%s\n", buf); +} + +static ssize_t set_resetcause(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte = 0; + + mutex_lock(&data->update_lock); + cpld_i2c_write(client, &byte, CPLD_RSTCAUSE_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static char* interrupt_str[] = { + "PCIE_INTR_L", //0 + "EXT_USB_OC_N", //1 + "PS2_ALERT_N", //2 + "PS1_ALERT_N", //3 + "PLD_SEN5_ALERT_N", //4 + "PLD_SEN4_ALERT_N", //5 + "PLD_SEN3_ALERT_N", //6 + "UCD90160_TEMP_INT_N", //7 + "RSTBTN_INT_N", //8 + "WDT_IRQ_N", //9 + "RSTBTN_5s_INT_N", //10 + "Reserved" //11 +}; + +static ssize_t show_interrupt(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte[4] = {0,0,0,0}; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, byte, CPLD_INT_OFFSET, 4); + mutex_unlock(&data->update_lock); + + sprintf (buf, "0x%02X 0x%02X:", byte[0],byte[2]); + if(byte[0]==0xff && byte[2]==0x07) sprintf (buf, "%sNone",buf); + if(!(byte[0]&0x01)) sprintf (buf, "%s%s ",buf,interrupt_str[0]); + if(!(byte[0]&0x02)) sprintf (buf, "%s%s ",buf,interrupt_str[1]); + //if(!(byte[0]&0x04)) sprintf (buf, "%s%s ",buf,interrupt_str[2]); + //if(!(byte[0]&0x08)) sprintf (buf, "%s%s ",buf,interrupt_str[3]); + if(!(byte[0]&0x10)) sprintf (buf, "%s%s ",buf,interrupt_str[4]); + if(!(byte[0]&0x20)) sprintf (buf, "%s%s ",buf,interrupt_str[5]); + if(!(byte[0]&0x40)) sprintf (buf, "%s%s ",buf,interrupt_str[6]); + if(!(byte[0]&0x80)) sprintf (buf, "%s%s ",buf,interrupt_str[7]); + if(!(byte[2]&0x01)) sprintf (buf, "%s%s%s ",buf,interrupt_str[8] ,(byte[3]&0x01)?"(Blocked)":""); + if(!(byte[2]&0x02)) sprintf (buf, "%s%s%s ",buf,interrupt_str[9] ,(byte[3]&0x02)?"(Blocked)":""); + if(!(byte[2]&0x04)) sprintf (buf, "%s%s%s ",buf,interrupt_str[10],(byte[3]&0x04)?"(Blocked)":""); + + return sprintf (buf, "%s\n", buf); +} + +static ssize_t show_operationcommand(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + return sprintf (buf, "%d\n", data->operation_command); +} + +static ssize_t set_operationcommand(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 operationcommand = simple_strtol(buf, NULL, 10); + + data->operation_command = operationcommand?1:0; + + return count; +} + +static char* bios_str[] = { + "BIOS1", //0 + "BIOS2", //1 +}; + +static ssize_t show_bios_cs(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte = 0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte &= 0x01; + + return sprintf (buf, "%d:%s\n", byte,bios_str[byte]); +} + +static ssize_t set_bios_cs(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte = 0; + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1); + if(temp) byte |= 0x01; else byte &= ~(0x01); + cpld_i2c_write(client, &byte, CPLD_BIOSCS_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static char* led_str[] = { + "OFF", //000 + "ON", //001 + "1 Hz", //010 + "2 Hz", //011 +}; + +static ssize_t show_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte = 0; + int shift = attr->index; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + mutex_unlock(&data->update_lock); + byte = (byte >> shift) & 0x3; + + return sprintf (buf, "%d: %s\n", byte, led_str[byte]); +} + +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 16); + u8 byte = 0; + int shift = attr->index; + temp &= 0x3; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + byte &= ~(0x3<update_lock); + + return count; +} + +static char* psu_str[] = { + "unpowered", //00 + "normal", //01 + "not installed", //10 + "not installed", //11 +}; + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte=0; + int shift = (attr->index == 0)?0:4; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client2, &byte, CPLD_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + byte = (byte >> shift) & 0x3; + + return sprintf (buf, "%d:%s\n", byte, psu_str[byte]); +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte=0; + u8 offset = attr->index + CPLD_PWM_OFFSET; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client2, &byte, offset, 1); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", byte); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 offset = attr->index + CPLD_PWM_OFFSET; + u8 byte = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_write(client2, &byte, offset, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 offset = attr->index*2 + CPLD_RPM_OFFSET; + u8 byte[2] = {0,0}; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client2, byte, offset, 2); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", (byte[0]<<8 | byte[1])); +} + +static char* fantype_str[] = { + "Normal Type", //00 + "REVERSAL Type", //01 + "UNPLUGGED", //10 + "UNPLUGGED", //11 +}; + +static ssize_t show_fantype(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 offset = CPLD_FANSTATUS_OFFSET; + u8 byte[2] = {0,0}; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client2, byte, offset, 2); + mutex_unlock(&data->update_lock); + status = (((byte[0] >> attr->index) & 0x01)) | (((byte[1] >> attr->index) & 0x01)<<1); + + return sprintf(buf, "%d:%s\n",status,fantype_str[status]); +} + +static char* fanled_str[] = { + "None", //00 + "Green", //01 + "Red", //10 + "Both", //11 +}; + +static ssize_t show_fanled(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte[2] = {0,0}; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client2, byte, CPLD_FANLED_OFFSET, 2); + mutex_unlock(&data->update_lock); + status = (((byte[0] >> attr->index) & 0x01)) | (((byte[1] >> attr->index) & 0x01)<<1); + + return sprintf(buf, "%d:%s\n",status,fanled_str[status]); +} + +static ssize_t set_fanled(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte[2] = {0,0}; + u8 temp = simple_strtol(buf, NULL, 16); + int shift = attr->index; + + temp &= 0x3; + mutex_lock(&data->update_lock); + cpld_i2c_read(client2, byte, CPLD_FANLED_OFFSET, 2); + byte[0] &= ~(1<> 1) & 0x01)<update_lock); + + return count; +} + +static ssize_t set_watchdog_feed(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte=0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1); + byte |= 0x02; + cpld_i2c_write(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t set_watchdog_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte=0x03; + + mutex_lock(&data->update_lock); + cpld_i2c_write(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_watchdog_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte=0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n",(byte&0x01)); +} + +static ssize_t set_watchdog_config(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte = simple_strtol(buf, NULL, 10); + + if (byte<6) byte=6; + mutex_lock(&data->update_lock); + cpld_i2c_write(client, &byte, CPLD_WATCHDOGCONFIG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_watchdog_config(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte=0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_WATCHDOGCONFIG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d seconds\n",byte); +} + +static ssize_t show_watchdog_counter(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte=0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_WATCHDOGCOUNTER_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d seconds\n",byte); +} + +static ssize_t show_paniccode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte = 0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_PANICCODE_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return sprintf (buf, "0x%02X\n", byte); +} + +#if ENABLE_SIMULATE +static ssize_t show_simdump(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 i, j; + sprintf(buf,"usage: echo 0xAABB > sim_buffer (AA is address, BB is value)\n\n"); + sprintf(buf,"%s 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n",buf); + sprintf(buf,"%s======================================================\n",buf); + sprintf(buf,"%s0000: ",buf); + for (j = 0, i = 0; j < sizeof(sim_register); j++, i++) + { + sprintf(buf,"%s%02x ", buf, (int)sim_register[i]); + if ((i & 0x0F) == 0x0F) sprintf(buf,"%s\n%04x: ", buf, (i+1)); + } + return sprintf(buf,"%s\n",buf); +} + +static ssize_t set_simbuffer(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + u16 byte = simple_strtol(buf, NULL, 16); + u8 address = (byte >> 8); + u8 value = (byte & 0xff); + + sim_register[address]=value; + + return count; +} +#endif +static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0); +static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0); +static SENSOR_DEVICE_ATTR(interrupt, S_IRUGO, show_interrupt, 0, 0); + +static SENSOR_DEVICE_ATTR(stacking_led, S_IWUSR|S_IRUGO, show_led, set_led, 0); +static SENSOR_DEVICE_ATTR(fan_led, S_IWUSR|S_IRUGO, show_led, set_led, 2); +static SENSOR_DEVICE_ATTR(power_led, S_IWUSR|S_IRUGO, show_led, set_led, 4); +static SENSOR_DEVICE_ATTR(service_led, S_IWUSR|S_IRUGO, show_led, set_led, 6); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4); + +static SENSOR_DEVICE_ATTR(fanmodule1_type, S_IRUGO, show_fantype, 0, 0); +static SENSOR_DEVICE_ATTR(fanmodule2_type, S_IRUGO, show_fantype, 0, 1); +static SENSOR_DEVICE_ATTR(fanmodule3_type, S_IRUGO, show_fantype, 0, 2); +static SENSOR_DEVICE_ATTR(fanmodule4_type, S_IRUGO, show_fantype, 0, 3); +static SENSOR_DEVICE_ATTR(fanmodule5_type, S_IRUGO, show_fantype, 0, 4); + +static SENSOR_DEVICE_ATTR(fanmodule1_led, S_IWUSR|S_IRUGO, show_fanled, set_fanled, 0); +static SENSOR_DEVICE_ATTR(fanmodule2_led, S_IWUSR|S_IRUGO, show_fanled, set_fanled, 1); +static SENSOR_DEVICE_ATTR(fanmodule3_led, S_IWUSR|S_IRUGO, show_fanled, set_fanled, 2); +static SENSOR_DEVICE_ATTR(fanmodule4_led, S_IWUSR|S_IRUGO, show_fanled, set_fanled, 3); +static SENSOR_DEVICE_ATTR(fanmodule5_led, S_IWUSR|S_IRUGO, show_fanled, set_fanled, 4); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7); +static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO, show_rpm, 0, 8); +static SENSOR_DEVICE_ATTR(fan10_input,S_IRUGO, show_rpm, 0, 9); + +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 0); +static SENSOR_DEVICE_ATTR(psu2, S_IRUGO, show_psu, 0, 1); +static SENSOR_DEVICE_ATTR(power_status, S_IRUGO, show_powerstatus, 0, 0); +static SENSOR_DEVICE_ATTR(reset_cause, S_IWUSR|S_IRUGO, show_resetcause, set_resetcause, 0); +static SENSOR_DEVICE_ATTR(resetbutton_status, S_IRUGO, show_resetbuttonstatus, 0, 0); +static SENSOR_DEVICE_ATTR(panic_code, S_IRUGO, show_paniccode, 0, 0); + +static SENSOR_DEVICE_ATTR(watchdog_feed, S_IWUSR, 0, set_watchdog_feed, 0); +static SENSOR_DEVICE_ATTR(watchdog_enable, S_IWUSR|S_IRUGO, show_watchdog_enable, set_watchdog_enable, 0); +static SENSOR_DEVICE_ATTR(watchdog_config, S_IWUSR|S_IRUGO, show_watchdog_config, set_watchdog_config, 0); +static SENSOR_DEVICE_ATTR(watchdog_counter, S_IRUGO, show_watchdog_counter, 0, 0); + +static SENSOR_DEVICE_ATTR(stack_mode, S_IWUSR|S_IRUGO, show_stackmode, set_stackmode, 0); +static SENSOR_DEVICE_ATTR(operation_command, S_IWUSR|S_IRUGO, show_operationcommand, set_operationcommand, 0); +#if ENABLE_SIMULATE + static SENSOR_DEVICE_ATTR(sim_buffer, S_IWUSR|S_IRUGO, show_simdump, set_simbuffer, 0); +#endif +static SENSOR_DEVICE_ATTR(bios_cs, S_IWUSR|S_IRUGO, show_bios_cs, set_bios_cs, 0); + +static struct attribute *cpld_attributes[] = { + &sensor_dev_attr_info.dev_attr.attr, + &sensor_dev_attr_diag.dev_attr.attr, + + &sensor_dev_attr_stacking_led.dev_attr.attr, + &sensor_dev_attr_fan_led.dev_attr.attr, + &sensor_dev_attr_power_led.dev_attr.attr, + &sensor_dev_attr_service_led.dev_attr.attr, + + &sensor_dev_attr_interrupt.dev_attr.attr, + + &sensor_dev_attr_psu1.dev_attr.attr, + &sensor_dev_attr_psu2.dev_attr.attr, + &sensor_dev_attr_power_status.dev_attr.attr, + &sensor_dev_attr_reset_cause.dev_attr.attr, + &sensor_dev_attr_resetbutton_status.dev_attr.attr, + &sensor_dev_attr_panic_code.dev_attr.attr, + + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm5.dev_attr.attr, + + &sensor_dev_attr_fanmodule1_type.dev_attr.attr, + &sensor_dev_attr_fanmodule2_type.dev_attr.attr, + &sensor_dev_attr_fanmodule3_type.dev_attr.attr, + &sensor_dev_attr_fanmodule4_type.dev_attr.attr, + &sensor_dev_attr_fanmodule5_type.dev_attr.attr, + + &sensor_dev_attr_fanmodule1_led.dev_attr.attr, + &sensor_dev_attr_fanmodule2_led.dev_attr.attr, + &sensor_dev_attr_fanmodule3_led.dev_attr.attr, + &sensor_dev_attr_fanmodule4_led.dev_attr.attr, + &sensor_dev_attr_fanmodule5_led.dev_attr.attr, + + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, + &sensor_dev_attr_fan9_input.dev_attr.attr, + &sensor_dev_attr_fan10_input.dev_attr.attr, + + &sensor_dev_attr_watchdog_feed.dev_attr.attr, + &sensor_dev_attr_watchdog_enable.dev_attr.attr, + &sensor_dev_attr_watchdog_config.dev_attr.attr, + &sensor_dev_attr_watchdog_counter.dev_attr.attr, + + &sensor_dev_attr_stack_mode.dev_attr.attr, + &sensor_dev_attr_operation_command.dev_attr.attr, + + &sensor_dev_attr_bios_cs.dev_attr.attr, +#if ENABLE_SIMULATE + &sensor_dev_attr_sim_buffer.dev_attr.attr, +#endif + NULL +}; + +struct i2c_client *client_notifier; + +static const struct attribute_group cpld_group = { + .attrs = cpld_attributes, +}; + +static int log_reboot_to_cpld (struct notifier_block *self, unsigned long event, void *ptr) +{ + u8 byte=0; + if (event == SYS_DOWN || event == SYS_HALT) + { + cpld_i2c_read(client_notifier, &byte, CPLD_RSTCAUSE_OFFSET, 1); + byte |= 0x04; + cpld_i2c_write(client_notifier, &byte, CPLD_RSTCAUSE_OFFSET, 1); + } + return NOTIFY_DONE; +} + +static int log_panic_to_cpld(struct notifier_block *self, unsigned long event, void *ptr) +{ +#if 1 +// Can't use SMBus if smp is stopped (need patch the panic.c) + if (client_notifier != NULL) + { + u8 byte=0; + cpld_i2c_read(client_notifier, &byte, CPLD_RSTCAUSE_OFFSET, 1); + byte |= 0x10; + cpld_i2c_write(client_notifier, &byte, CPLD_RSTCAUSE_OFFSET, 1); + } +#endif + return NOTIFY_DONE; +} + +static struct notifier_block reboot_notifier = { + .notifier_call = log_reboot_to_cpld, +}; + +static struct notifier_block panic_notifier = { + .notifier_call = log_panic_to_cpld, +}; + +#if ENABLE_AUTOFAN +#define SWITCH_ADDRESS 3-004e +#define ENV_ADDRESS 3-004a +#define CPU_ADDRESS 3-0048 +#define PSU1_ADDRESS 2-0058 +#define PSU2_ADDRESS 2-0059 +#define PSU1_ADDRESS_DVT 2-005a +#define PSU2_ADDRESS_DVT 2-005b + +#define _STR(s) #s +#define __STR(s) _STR(s) +#define __File_input(__file) __STR(/sys/bus/i2c/devices/__file/hwmon/hwmon%d/temp1_input) +#define __File_max(__file) __STR(/sys/bus/i2c/devices/__file/hwmon/hwmon%d/temp1_max) +#define __File_max_hyst(__file) __STR(/sys/bus/i2c/devices/__file/hwmon/hwmon%d/temp1_max_hyst) +#define __File_pwm(__file) __STR(/sys/bus/i2c/devices/__file/hwmon/hwmon%d/pwm1) + +#define SWITCH_TEMPERATURE __File_input(SWITCH_ADDRESS) +#define ENV_TEMPERATURE __File_input(ENV_ADDRESS) +#define CPU_TEMPERATURE __File_input(CPU_ADDRESS) +#define SWITCH_MAX __File_max(SWITCH_ADDRESS) +#define ENV_MAX __File_max(ENV_ADDRESS) +#define CPU_MAX __File_max(CPU_ADDRESS) +#define SWITCH_MAX_HYST __File_max_hyst(SWITCH_ADDRESS) +#define ENV_MAX_HYST __File_max_hyst(ENV_ADDRESS) +#define CPU_MAX_HYST __File_max_hyst(CPU_ADDRESS) +#define PSU1_PWM __File_pwm(PSU1_ADDRESS) +#define PSU2_PWM __File_pwm(PSU2_ADDRESS) +#define PSU1_PWM_DVT __File_pwm(PSU1_ADDRESS_DVT) +#define PSU2_PWM_DVT __File_pwm(PSU2_ADDRESS_DVT) + +#define n_entries 9 +#define temp_hysteresis 2 +#define MAX_HWMON 9 + +//[Model:10G/SFP][FanDirection:R2F/F2R][Type:CPU/ASIC/ENV] +u8 Thermaltrip[2][2][3] ={{{64,68,64},{64,68,64}},{{64,68,64},{64,68,64}}}; +u8 FanTable[2][2][3][n_entries][2]={ +{//10GBastT + {//Rear-to-Front + {//CPU + { 45, 255 }, \ + { 40, 201 }, \ + { 38, 170 }, \ + { 35, 130 }, \ + { 31, 105 }, \ + { 27, 85 }, \ + { 24, 80 }, \ + { 20, 70 }, \ + { 18, 65 } + } + ,{//ASIC + { 52, 255 }, \ + { 47, 201 }, \ + { 44, 170 }, \ + { 42, 130 }, \ + { 39, 105 }, \ + { 36, 85 }, \ + { 33, 80 }, \ + { 30, 70 }, \ + { 28, 65 } + } + ,{//ENV + { 47, 255 }, \ + { 43, 201 }, \ + { 41, 170 }, \ + { 39, 130 }, \ + { 36, 105 }, \ + { 32, 85 }, \ + { 30, 80 }, \ + { 28, 70 }, \ + { 19, 65 } + } + }, + {//Front-to-Rear + {//CPU + { 45, 255 }, \ + { 40, 201 }, \ + { 38, 170 }, \ + { 35, 130 }, \ + { 31, 105 }, \ + { 27, 85 }, \ + { 24, 80 }, \ + { 20, 70 }, \ + { 18, 65 } + } + ,{//ASIC + { 52, 255 }, \ + { 47, 201 }, \ + { 44, 170 }, \ + { 42, 130 }, \ + { 39, 105 }, \ + { 36, 85 }, \ + { 33, 80 }, \ + { 30, 70 }, \ + { 28, 65 } + } + ,{//ENV + { 47, 255 }, \ + { 43, 201 }, \ + { 41, 170 }, \ + { 39, 130 }, \ + { 36, 105 }, \ + { 32, 85 }, \ + { 30, 80 }, \ + { 28, 70 }, \ + { 19, 65 } + } + }, +}, +{//SFP28 + {//Rear-to-Front + {//CPU + { 45, 255 }, \ + { 40, 201 }, \ + { 38, 170 }, \ + { 35, 130 }, \ + { 31, 105 }, \ + { 27, 85 }, \ + { 24, 80 }, \ + { 20, 70 }, \ + { 18, 65 } + } + ,{//ASIC + { 52, 255 }, \ + { 47, 201 }, \ + { 44, 170 }, \ + { 42, 130 }, \ + { 39, 105 }, \ + { 36, 85 }, \ + { 33, 80 }, \ + { 30, 70 }, \ + { 28, 65 } + } + ,{//ENV + { 47, 255 }, \ + { 43, 201 }, \ + { 41, 170 }, \ + { 39, 130 }, \ + { 36, 105 }, \ + { 32, 85 }, \ + { 30, 80 }, \ + { 28, 70 }, \ + { 19, 65 } + } + }, + {//Front-to-Rear + {//CPU + { 45, 255 }, \ + { 40, 201 }, \ + { 38, 170 }, \ + { 35, 130 }, \ + { 31, 105 }, \ + { 27, 85 }, \ + { 24, 80 }, \ + { 20, 70 }, \ + { 18, 65 } + } + ,{//ASIC + { 52, 255 }, \ + { 47, 201 }, \ + { 44, 170 }, \ + { 42, 130 }, \ + { 39, 105 }, \ + { 36, 85 }, \ + { 33, 80 }, \ + { 30, 70 }, \ + { 28, 65 } + } + ,{//ENV + { 47, 255 }, \ + { 43, 201 }, \ + { 41, 170 }, \ + { 39, 130 }, \ + { 36, 105 }, \ + { 32, 85 }, \ + { 30, 80 }, \ + { 28, 70 }, \ + { 19, 65 } + } + } +} +}; + +//type 0:CPU,1:ASIC,2:ENV +static u8 find_duty(u8 model, u8 fan_direction, u8 type, u8 temp) +{ + static u8 fantable_index[3]={n_entries-1, n_entries-1, n_entries-1}; + while(1) + { + if(fantable_index[type] >= 1 && temp > FanTable[model][fan_direction][type][fantable_index[type]-1][0]) + fantable_index[type]--; + else if(fantable_index[type] < (n_entries-1) && temp < (FanTable[model][fan_direction][type][fantable_index[type]][0]-temp_hysteresis)) + fantable_index[type]++; + else + break; + } + return FanTable[model][fan_direction][type][fantable_index[type]][1]; +} + +static u32 getvalue(char *path) +{ + static struct file *f; + mm_segment_t old_fs; + u16 temp = 0; + char temp_str[]={0,0,0,0,0,0,0,0,0}; + loff_t pos = 0; + + f = filp_open(path,O_RDONLY,0644); + if(IS_ERR(f)) return -1; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + vfs_read(f, temp_str,8,&pos); + temp = simple_strtoul(temp_str,NULL,10); + filp_close(f,NULL); + set_fs(old_fs); + + if(temp<0) temp=0; + return temp; +} + +static u8 setvalue(char *path, u32 value) +{ + static struct file *f; + mm_segment_t old_fs; + char temp_str[]={0,0,0,0,0,0,0,0,0}; + u8 len=0; + loff_t pos = 0; + + f = filp_open(path,O_WRONLY,0644); + if(IS_ERR(f)) return -1; + + len = sprintf(temp_str,"%d",value); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + vfs_write(f, temp_str, len, &pos); + filp_close(f,NULL); + set_fs(old_fs); + + return 0; +} + +static u8 probe_gettemp(char *path) +{ + u8 temp_path[64],i; + u32 value; + + for(i=0;imodel,data->fan_direction,0,temp_cpu); + if(temp_switch!=0xff) duty_switch=find_duty(data->model,data->fan_direction,1,temp_switch); + if(temp_env!=0xff) duty_env=find_duty(data->model,data->fan_direction,2,temp_env); + + if(temp_cpu==0xff && temp_switch==0xff && temp_env==0xff) + { + duty=PWM_DEFAULT; + } + else + { + duty=(duty>duty_cpu)?duty:duty_cpu; + duty=(duty>duty_switch)?duty:duty_switch; + duty=(duty>duty_env)?duty:duty_env; + } + + memset(fanpwm,duty,FAN_NUM); + for(i=0;i 200) + psu_duty = 80; + else if (duty <= 200 && duty > 150) + if(data->fan_direction==0) psu_duty = 70; else psu_duty = 65; + else if (duty <= 150 && duty > 100) + if(data->fan_direction==0) psu_duty = 60; else psu_duty = 55; + else + if(data->fan_direction==0) psu_duty = 50; else psu_duty = 35; + probe_setvalue(PSU1_PWM, psu_duty); + probe_setvalue(PSU2_PWM, psu_duty); + probe_setvalue(PSU1_PWM_DVT, psu_duty); + probe_setvalue(PSU2_PWM_DVT, psu_duty); + + mutex_lock(&data->update_lock); + cpld_i2c_write(client2,fanpwm,CPLD_PWM_OFFSET,FAN_NUM); + mutex_unlock(&data->update_lock); +} +#endif + +/*-----------------------------------------------------------------------*/ +static int cpld_polling(void *p) +{ + struct i2c_client *client = p; + struct cpld_data *data = i2c_get_clientdata(client); + u8 fanrpm[22],fanled[2],frontled,i; + u8 fandir=0,fanpresent=0,fanfront,fanrear,fanerror; + u8 fanfail,fanturnoff,psufail,lastStack,retry; + u8 psustatus=0; + u8 initial_thermaltrip[3] = {0,0,0}; + + while (!kthread_should_stop()) + { + //initial tmp75's thermaltrip value + if(initial_thermaltrip[0]==0) + { + if((probe_setvalue(CPU_MAX, Thermaltrip[data->model][data->fan_direction][0]*1000)!=0xff) + && (probe_setvalue(CPU_MAX_HYST, (Thermaltrip[data->model][data->fan_direction][0]-temp_hysteresis)*1000)!=0xff)) + initial_thermaltrip[0]=1; + } + if(initial_thermaltrip[1]==0) + { + if((probe_setvalue(SWITCH_MAX, Thermaltrip[data->model][data->fan_direction][1]*1000)!=0xff) + && (probe_setvalue(SWITCH_MAX_HYST, (Thermaltrip[data->model][data->fan_direction][1]-temp_hysteresis)*1000)!=0xff)) + initial_thermaltrip[1]=1; + } + if(initial_thermaltrip[2]==0) + { + if((probe_setvalue(ENV_MAX, Thermaltrip[data->model][data->fan_direction][2]*1000)!=0xff) + && (probe_setvalue(ENV_MAX_HYST, (Thermaltrip[data->model][data->fan_direction][2]-temp_hysteresis)*1000)!=0xff)) + initial_thermaltrip[2]=1; + } + + //LED control + if (data->diag==0 && i2c_smbus_read_byte_data(client, 0)>=0) + { + for(retry=0;retry<2;retry++) + { + fanfail=0; + fanled[0]=0; //clean green led + fanled[1]=0; //clean red led + fanfront=0; + fanrear=0; + fanerror=0; + fanturnoff=0; + + //------ Fan Check ------- + cpld_i2c_read(client2, fanrpm, CPLD_RPM_OFFSET, 22); + fandir=fanrpm[20]; + fanpresent=fanrpm[21]; + + //Count the fan's direction + for (i=0;i 23500) || (rpm2 < 3000 || rpm2 > 23500)) + fanerror++; + else if(fandir&(1<>i)&0x01)!=data->fan_direction) + fanled[0] |= (1<stack_mode==0) frontled&=~(0x3); //0: Non-Stack member => off + if(data->stack_mode==1) frontled|=0x2; //1: Stack Master => Flash green + if(data->stack_mode==2) frontled|=0x1; //2: Stack Backup/Member => Steady green + if(data->stack_mode==3) frontled|=lastStack;//3: Stack Error => last status + lastStack=frontled; + + if(fanpresent!=0x00) //Fan LED in bit2 bit3 + { + frontled|=(0x02<<2); //Some fan unpresent => 0x02 + } + else + { + if(fanturnoff||fanfail) //some fan no speed => 0x03 + frontled|=(0x03<<2); //some fan dir different => 0x03 + else + frontled|=(0x01<<2); //Normal => 0x01 + } + + if(psustatus&0x22) //POW LED in bit4 bit5 + frontled|=(0x02<<4); //not all psu plug-in => 0x02 + else if (psustatus!=0x11) + frontled|=(0x03<<4); //some power is not ok => 0x03 + else + frontled|=(0x01<<4); //Normal => 0x01 + + if(data->operation_command==1) //Service LED in bit6 bit7 + frontled|=(0x01<<6); //Steady if operation + else if(fanfail>0||psufail>0||data->stack_mode==3) + frontled|=(0x02<<6); //Flash if any error + else if(data->stack_mode==2) + frontled|=(0x01<<6); //Steady if mode in Stack Backup/Member + else + frontled&=~(0x3<<6); //Off if mode in Non-Stack member or Stack Master with no operation and error + cpld_i2c_write(client, &frontled, CPLD_LED_OFFSET, 1); + } + set_current_state(TASK_INTERRUPTIBLE); + if(kthread_should_stop()) break; + schedule_timeout(msecs_to_jiffies(CPLD_POLLING_PERIOD)); + } + return 0; +} + +/*-----------------------------------------------------------------------*/ +/* device probe and removal */ + +static int +cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + u8 byte[5]={PWM_DEFAULT,PWM_DEFAULT,PWM_DEFAULT,PWM_DEFAULT,PWM_DEFAULT}; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld_group); + + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + //Check CPLD2 exist or not + client2 = i2c_new_dummy(client->adapter, CPLD2_ADDRESS); + if(!client2) { + hasCPLD2 = 0; + client2 = client; + } else { + status = i2c_smbus_read_byte_data(client2, CPLD_INFO_OFFSET); + if(status<0) { + i2c_unregister_device(client2); + i2c_set_clientdata(client2, NULL); + hasCPLD2 = 0; + client2 = client; + } + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + //initial PWM to 60% + cpld_i2c_write(client2, byte, CPLD_PWM_OFFSET, 5); + + //Handle LED control by the driver + byte[0]=0x01; + cpld_i2c_write(client, byte, CPLD_CTL_OFFSET, 1); + cpld_i2c_write(client2, byte, CPLD_CTL_OFFSET, 1); + + //Get Model type + cpld_i2c_read(client, byte, CPLD_INFO_OFFSET, 1); + data->model = (byte[0]>>5) & 0x01; + data->fan_direction = (byte[0]>>7) & 0x01; + + //kernel panic notifier + atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier); + + //soft reboot notifier + register_reboot_notifier(&reboot_notifier); + + client_notifier=client; + + data->cpld_thread = kthread_run(cpld_polling,client,"%s",dev_name(data->hwmon_dev)); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpld_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + //Return LED control to the CPLD + u8 byte=0x00; + cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1); + cpld_i2c_write(client2, &byte, CPLD_CTL_OFFSET, 1); + + //unregister soft reboot notifier + unregister_reboot_notifier(&reboot_notifier); + + //unregister kernel panic notifier + atomic_notifier_chain_unregister(&panic_notifier_list, &panic_notifier); + + //stop cpld thread + kthread_stop(data->cpld_thread); + + sysfs_remove_group(&client->dev.kobj, &cpld_group); + hwmon_device_unregister(data->hwmon_dev); + i2c_set_clientdata(client, NULL); + if(hasCPLD2) { + i2c_unregister_device(client2); + i2c_set_clientdata(client2, NULL); + } + + kfree(data); + return 0; +} + +static const struct i2c_device_id cpld_ids[] = { + { "inv_cpld" , 0, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, cpld_ids); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_cpld_init(void) +{ + return i2c_add_driver(&cpld_driver); +} + +static void __exit inv_cpld_exit(void) +{ + i2c_del_driver(&cpld_driver); +} + +MODULE_AUTHOR("jack.ting "); +MODULE_DESCRIPTION("cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_cpld_init); +module_exit(inv_cpld_exit); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_eeprom.c new file mode 100644 index 000000000000..781ef27671c1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_eeprom.c @@ -0,0 +1,180 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void inv_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } + +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + inv_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute inv_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = inv_eeprom_read, +}; + +static int inv_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int inv_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id inv_eeprom_id[] = { + { "inv_eeprom", 0 }, + { } +}; + +static struct i2c_driver inv_eeprom_driver = { + .driver = { + .name = "inv_eeprom", + }, + .probe = inv_eeprom_probe, + .remove = inv_eeprom_remove, + .id_table = inv_eeprom_id, +}; + +module_i2c_driver(inv_eeprom_driver); + +MODULE_AUTHOR("Inventec"); +MODULE_DESCRIPTION("Inventec D6556 Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_mux.c b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_mux.c new file mode 100644 index 000000000000..40593a96eeb7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_mux.c @@ -0,0 +1,545 @@ +#include +#include +#include +#include +#include +#include +#include "io_expander.h" +#include "inv_mux.h" + +/* For build single module using (Ex: ONL platform) */ +#include +//#include +//#include + +static struct mux_obj_s *mux_head_p = NULL; + +/* ========== MUX object functions ========== + */ +static int +_setup_i2c_value(struct mux_obj_s *self, int offset, int value){ + + return i2c_smbus_write_byte_data(self->i2c_client_p, offset, value); +} + + +static int +_setup_i2c_client(struct mux_obj_s *self, int chan_id, int addr){ + + struct i2c_adapter *adap = NULL; + char *emsg = "ERR"; + + adap = i2c_get_adapter(chan_id); + if (!adap){ + emsg = "can't get adapter"; + goto err_setup_i2c_client; + } + self->i2c_client_p = kzalloc(sizeof(*self->i2c_client_p), GFP_KERNEL); + if (!self->i2c_client_p){ + emsg = "can't kzalloc client"; + goto err_setup_i2c_client; + } + self->i2c_client_p->adapter = adap; + self->i2c_client_p->addr = addr; + return 0; + +err_setup_i2c_client: + SWPS_ERR("%s: %s\n", __func__, emsg); + return ERR_MUX_UNEXCPT; +} + + +int +_common_force_pull_gpio(int mem_addr, + int input, + int bit_offset){ + + unsigned int val = 0; + unsigned int targ = 0; + + /* Get current value */ + val = inl(mem_addr); + if (val == 0) { + SWPS_ERR("%s: inl:%d fail!\n", __func__, val); + return -1; + } + /* Count target value */ + switch (input) { + case 0: /* Pull Low */ + targ = (val & (~(1 << bit_offset))); + break; + case 1: /* Pull high */ + targ = (val | (1 << bit_offset)); + break; + default: + SWPS_ERR("%s: input state:%d incorrect!\n", + __func__, input); + return -1; + } + /* Setup gpio */ + outl(targ, mem_addr); + if (targ != inl(mem_addr)){ + SWPS_ERR("%s: outl:%d fail!\n", __func__, targ); + return -1; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + + +int +rangeley_force_pull_high(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +rangeley_force_pull_low(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +hedera_force_pull_high(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 1, 5); +} + + +int +hedera_force_pull_low(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 0, 5); +} + + +int +normal_gpio_pull_high(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 1); +} + + +int +normal_gpio_pull_low(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 0); +} + + +int +cpld_rst_all_4_pull_low(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto setlow_cpld_rst_all_4_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_cpld_rst_all_4_pull_low; + +setlow_cpld_rst_all_4_c0_a77_70_74_rst_all: + err = _setup_i2c_value(self, 0x70, 0x0); + if (err < 0) { + emsg = "setup 0x70 fail"; + goto err_cpld_rst_all_4_pull_low; + } + err = _setup_i2c_value(self, 0x74, 0x01); + if (err < 0) { + emsg = "setup 0x74 fail"; + goto err_cpld_rst_all_4_pull_low; + } + return 0; + +err_cpld_rst_all_4_pull_low: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + +int +cpld_rst_all_4_pull_high(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto sethigh_cpld_rst_all_4_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_cpld_rst_all_4_pull_high; + +sethigh_cpld_rst_all_4_c0_a77_70_74_rst_all: + err = _setup_i2c_value(self, 0x70, 0xfe); + if (err < 0) { + emsg = "setup 0x70 fail"; + goto err_cpld_rst_all_4_pull_high; + } + err = _setup_i2c_value(self, 0x74, 0x03); + if (err < 0) { + emsg = "setup 0x74 fail"; + goto err_cpld_rst_all_4_pull_high; + } + return 0; + +err_cpld_rst_all_4_pull_high: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + +int +pca9548_reset_mux_all(struct mux_obj_s *self){ + /* [Note] Power-on reset (PCA9548A-NXP) + * When power is applied to VDD, an internal Power-On Reset (POR) + * holds the PCA9548A in a reset condition until VDD has reached + * VPOR. At this point, the reset condition is released and the + * PCA9548A register and I2C-bus state machine are initialized to + * their default states (all zeroes) causing all the channels to + * be deselected. Thereafter, VDD must be lowered below 0.2 V for + * at least 5 us in order to reset the device. + */ + if (self->_pull_low(self) < 0) { + SWPS_ERR("%s: _pull_low fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS_PCA9548); + if (self->_pull_high(self) < 0) { + SWPS_ERR("%s: _pull_high fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS_PCA9548); + return 0; +} + + +int +cpld_reset_mux_all(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto reset_cpld_rst_all_4_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_cpld_reset_mux_all; + +reset_cpld_rst_all_4_c0_a77_70_74_rst_all: + if (self->_pull_low(self) < 0) { + emsg = "_pull_low fail"; + goto err_cpld_reset_mux_all; + } + mdelay(MUX_RST_WAIT_MS_CPLD); + return 0; + +err_cpld_reset_mux_all: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + +int +common_reset_mux_all(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +init_gpio_4_force(struct mux_obj_s *self){ + + if (self->_pull_high(self) < 0) { + SWPS_ERR("%s: setup default fail!\n", __func__); + return -1; + } + return 0; +} + + +int +init_gpio_4_normal(struct mux_obj_s *self){ + + int err = 0; + char *emsg = "ERR"; + + if (!gpio_is_valid(self->gpio_num)) { + emsg = "GPIO invalid"; + goto err_init_gpio_4_normal; + } + err = gpio_request(self->gpio_num, MUX_GPIO_LABEL); + if (err < 0) { + emsg = "gpio_request fail"; + goto err_init_gpio_4_normal; + } + err = self->_pull_high(self); + if (err < 0) { + emsg = "setup default fail"; + goto err_init_gpio_4_normal; + } + SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num); + return 0; + +err_init_gpio_4_normal: + SWPS_ERR("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return -1; +} + + +int +init_cpld_4_rst_all(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + int chan = ERR_MUX_UNEXCPT; + int addr = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto init_cpld_i2c_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_init_cpld_4_rst_all; + +init_cpld_i2c_c0_a77_70_74_rst_all: + chan = 0; + addr = 0x77; + err = _setup_i2c_client(self, chan, addr); + if (err < 0) { + emsg = "_setup_i2c_client fail"; + goto err_init_cpld_4_rst_all; + } + err = self->_pull_high(self); + if (err < 0) { + emsg = "setup default value fail"; + goto err_init_cpld_4_rst_all; + } + SWPS_DEBUG("%s: init_cpld_i2c_c0_a77_70_74_rst_all ok", __func__); + return 0; + +err_init_cpld_4_rst_all: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + +int +clean_gpio_4_common(struct mux_obj_s *self){ + + if (!self) return 0; + if (!gpio_is_valid(self->gpio_num)) return 0; + self->_pull_high(self); + gpio_free(mux_head_p->gpio_num); + return 0; +} + + +int +clean_cpld_4_rst_all(struct mux_obj_s *self){ + + if (!self) return 0; + self->_pull_high(self); + if (self->i2c_client_p) { + i2c_put_adapter(self->i2c_client_p->adapter); + kfree(self->i2c_client_p); + } + return 0; +} + + +static int +_setup_muxctl_cb(struct mux_obj_s *self, + unsigned gpio){ + + char mod_dsc[32] = "ERR"; + + switch (gpio) { + case MUX_RST_GPIO_FORCE_RANGELEY: + self->gpio_num = gpio; + self->_pull_low = rangeley_force_pull_low; + self->_pull_high = rangeley_force_pull_high; + self->_init = init_gpio_4_force; + self->_clean = clean_gpio_4_common; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Rangeley force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_FORCE_HEDERA: + self->gpio_num = gpio; + self->_pull_low = hedera_force_pull_low; + self->_pull_high = hedera_force_pull_high; + self->_init = init_gpio_4_force; + self->_clean = clean_gpio_4_common; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Hedera force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_48_PCA9548: + case MUX_RST_GPIO_69_PCA9548: + case MUX_RST_GPIO_249_PCA9548: + case MUX_RST_GPIO_500_PCA9548: + case MUX_RST_GPIO_505_PCA9548: + self->gpio_num = gpio; + self->_pull_low = normal_gpio_pull_low; + self->_pull_high = normal_gpio_pull_high; + self->_init = init_gpio_4_normal; + self->_clean = clean_gpio_4_common; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Normal mode :%d", (int)gpio); + goto ok_setup_muxctl_cb; + + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + self->gpio_num = gpio; + self->_pull_low = cpld_rst_all_4_pull_low; + self->_pull_high = cpld_rst_all_4_pull_high; + self->_init = init_cpld_4_rst_all; + self->_clean = clean_cpld_4_rst_all; + self->reset = cpld_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "CPLD mode :%d", (int)gpio); + goto ok_setup_muxctl_cb; + + default: + break; + } + SWPS_ERR("%s: Unexpected GPIO:%d\n", __func__, gpio); + return -1; + +ok_setup_muxctl_cb: + SWPS_INFO("muxctl: %s.\n", mod_dsc); + return 0; +} + + +/* ========== MUX public functions ========== + */ +void +clean_mux_objs(void){ + + struct mux_obj_s *curr_p = mux_head_p; + struct mux_obj_s *next_p = NULL; + + if (!curr_p) { + SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__); + return; + } + while (curr_p) { + next_p = curr_p->next; + curr_p->_clean(curr_p); + kfree(curr_p); + curr_p = next_p; + } + SWPS_DEBUG("%s: done.\n", __func__); +} +EXPORT_SYMBOL(clean_mux_objs); + + +int +reset_mux_objs(void){ + + if (!mux_head_p) { + SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__); + return -1; + } + if (mux_head_p->reset(mux_head_p) < 0){ + SWPS_ERR("%s: reset fail!\n", __func__); + return -1; + } + return 0; +} +EXPORT_SYMBOL(reset_mux_objs); + + +struct mux_obj_s * +_create_mux_obj(unsigned gpio){ + + char *emsg = "ERR"; + struct mux_obj_s *obj_p = NULL; + + obj_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL); + if (!obj_p) { + emsg = "kzalloc fail!"; + goto err_create_mux_obj_1; + } + if (_setup_muxctl_cb(obj_p, gpio) < 0){ + emsg = "_setup_muxctl_cb fail!"; + goto err_create_mux_obj_2; + } + if (obj_p->_init(obj_p) < 0) { + emsg = "_init() fail!"; + goto err_create_mux_obj_2; + } + SWPS_DEBUG("%s: created MUX object :%d\n", __func__, gpio); + return obj_p; + +err_create_mux_obj_2: + kfree(obj_p); +err_create_mux_obj_1: + SWPS_ERR("%s: %s :%d\n", __func__, emsg, gpio); + return NULL; +} + + +int +init_mux_objs(unsigned gpio){ + + struct mux_obj_s *curr_p = NULL; + char *emsg = "ERR"; + + /* Create MUX control object */ + if (mux_head_p) { + SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__); + clean_mux_objs(); + } + /* Currently, it is using single muxctl architecture. + * In the future, it may use the multi-muxctl. + * (Ex: Gulmohar's advance I2C control / Peony's reset single mux) + */ + curr_p = _create_mux_obj(gpio); + if (!curr_p) { + emsg = "_create_mux_obj fail"; + goto err_init_mux_objs; + } + curr_p->next = NULL; + mux_head_p = curr_p; + SWPS_DEBUG("%s: all done. :%d\n", __func__, gpio); + return 0; + +err_init_mux_objs: + clean_mux_objs(); + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} +EXPORT_SYMBOL(init_mux_objs); + + +/* For single ko module + * => You need to declare MODULE_LICENSE If you want to build single module along. + * => Ex: For ONL platform + */ +MODULE_LICENSE("GPL"); + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_mux.h b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_mux.h new file mode 100644 index 000000000000..a6b9d98d6e7e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_mux.h @@ -0,0 +1,50 @@ +#ifndef INV_MUX_H +#define INV_MUX_H + +#include + +/* MUX basic information */ +#define MUX_GPIO_LABEL "SWPS_RST_MUX" + +/* MUX reset GPIO define */ +#define MUX_RST_GPIO_FORCE (30100) +#define MUX_RST_GPIO_FORCE_RANGELEY (30101) +#define MUX_RST_GPIO_FORCE_HEDERA (30102) +#define MUX_RST_GPIO_48_PCA9548 (48) +#define MUX_RST_GPIO_69_PCA9548 (69) +#define MUX_RST_GPIO_249_PCA9548 (249) +#define MUX_RST_GPIO_500_PCA9548 (500) +#define MUX_RST_GPIO_505_PCA9548 (505) +#define MUX_RST_CPLD_C0_A77_70_74_RST_ALL (30201) + +/* MUX relate value define */ +#define MUX_RST_WAIT_MS_PCA9548 (1) +#define MUX_RST_WAIT_MS_CPLD (10) +#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD +#define MUX_RST_MEM_ADDR_HEDERA (0x548) + +/* MUX error code define */ +#define ERR_MUX_UNEXCPT (-399) + +struct mux_obj_s { + struct i2c_client *i2c_client_p; + struct mux_obj_s *next; + unsigned gpio_num; + int (*_pull_high)(struct mux_obj_s *self); + int (*_pull_low)(struct mux_obj_s *self); + int (*_init)(struct mux_obj_s *self); + int (*_clean)(struct mux_obj_s *self); + int (*reset)(struct mux_obj_s *self); +}; + + +void clean_mux_objs(void); +int reset_mux_objs(void); +int init_mux_objs(unsigned gpio); + + +#endif /* INV_MUX_H */ + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_platform.c new file mode 100644 index 000000000000..c5331ab7319c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_platform.c @@ -0,0 +1,228 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct inv_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; + int probe; +}; + +#define bus_id(id) (id) +#define SCL_PIN 58 +#define SDA_PIN 75 + +static struct pca954x_platform_mode mux_modes_0[] = { + {.adap_id = bus_id(2),}, {.adap_id = bus_id(3),}, +}; + +static struct pca954x_platform_mode mux_modes_1[] = { + {.adap_id = bus_id(4),}, {.adap_id = bus_id(5),}, + {.adap_id = bus_id(6),}, {.adap_id = bus_id(7),}, + {.adap_id = bus_id(8),}, {.adap_id = bus_id(9),}, + {.adap_id = bus_id(10),}, {.adap_id = bus_id(11),}, +}; + +static struct pca954x_platform_mode mux_modes_2_0[] = { + {.adap_id = bus_id(12),}, {.adap_id = bus_id(13),}, + {.adap_id = bus_id(14),}, {.adap_id = bus_id(15),}, + {.adap_id = bus_id(16),}, {.adap_id = bus_id(17),}, + {.adap_id = bus_id(18),}, {.adap_id = bus_id(19),}, +}; + +static struct pca954x_platform_mode mux_modes_2_1[] = { + {.adap_id = bus_id(20),}, {.adap_id = bus_id(21),}, + {.adap_id = bus_id(22),}, {.adap_id = bus_id(23),}, + {.adap_id = bus_id(24),}, {.adap_id = bus_id(25),}, + {.adap_id = bus_id(26),}, {.adap_id = bus_id(27),}, +}; + +static struct pca954x_platform_mode mux_modes_2_2[] = { + {.adap_id = bus_id(28),}, {.adap_id = bus_id(29),}, + {.adap_id = bus_id(30),}, {.adap_id = bus_id(31),}, + {.adap_id = bus_id(32),}, {.adap_id = bus_id(33),}, + {.adap_id = bus_id(34),}, {.adap_id = bus_id(35),}, +}; + +static struct pca954x_platform_mode mux_modes_2_3[] = { + {.adap_id = bus_id(36),}, {.adap_id = bus_id(37),}, + {.adap_id = bus_id(38),}, {.adap_id = bus_id(39),}, + {.adap_id = bus_id(40),}, {.adap_id = bus_id(41),}, + {.adap_id = bus_id(42),}, {.adap_id = bus_id(43),}, +}; + + +static struct pca954x_platform_data mux_data_0 = { + .modes = mux_modes_0, + .num_modes = 2, +}; + +static struct pca954x_platform_data mux_data_1 = { + .modes = mux_modes_1, + .num_modes = 8, +}; + +static struct pca954x_platform_data mux_data_2_0 = { + .modes = mux_modes_2_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_2_1 = { + .modes = mux_modes_2_1, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_2_2 = { + .modes = mux_modes_2_2, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_2_3 = { + .modes = mux_modes_2_3, + .num_modes = 8, +}; + +static struct i2c_board_info i2c_device_info0[] __initdata = { + {"inv_cpld", 0, 0x77, "inv_cpld", 0, 0, 0}, // CPLD driver +// {"24c512", 0, 0x55, 0, 0, 0}, // OEM1 VPD +// {"24c512", 0, 0x54, 0, 0, 0}, // OEM2 VPD + {"pca9543", 0, 0x73, "pca9543", &mux_data_0, 0, 0}, // MUX +}; + +static struct i2c_board_info i2c_device_info1[] __initdata = { + {"pca9548", 0, 0x70, "pca9548-1", &mux_data_1, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info2[] __initdata ={ + {"ucd90160", 0, 0x34, "ucd90160", 0, 0 ,0}, +}; + +static struct i2c_board_info i2c_device_info11[] __initdata ={ + {"pmbus", 0, 0x5A, "pmbus-1", 0, 0 ,0}, //PSU1 DVT + {"pmbus", 0, 0x5B, "pmbus-2", 0, 0 ,0}, //PSU2 DVT +}; + +static struct i2c_board_info i2c_device_info3[] __initdata ={ + {"tmp75", 0, 0x48, "tmp75-1", 0, 0 ,0}, //CPU Board Temperature + {"tmp75", 0, 0x4A, "tmp75-2", 0, 0 ,0}, //Front Panel Inlet Temperature + {"tmp75", 0, 0x4D, "tmp75-3", 0, 0 ,0}, + {"tmp75", 0, 0x4E, "tmp75-4", 0, 0 ,0}, //Near ASIC Temperature +}; + +static struct i2c_board_info i2c_device_info4[] __initdata = { + {"pca9548", 0, 0x72, "pca9548-2", &mux_data_2_0, 0, 0}, +}; +static struct i2c_board_info i2c_device_info5[] __initdata = { + {"pca9548", 0, 0x72, "pca9548-3", &mux_data_2_1, 0, 0}, +}; +static struct i2c_board_info i2c_device_info6[] __initdata = { + {"pca9548", 0, 0x72, "pca9548-4", &mux_data_2_2, 0, 0}, +}; +static struct i2c_board_info i2c_device_info7[] __initdata = { + {"pca9548", 0, 0x72, "pca9548-5", &mux_data_2_3, 0, 0}, +}; + +static struct inv_i2c_board_info i2cdev_list[] = { + {bus_id(0), ARRAY_SIZE(i2c_device_info0), i2c_device_info0 , 0}, //i2c-0 smbus + {bus_id(0), ARRAY_SIZE(i2c_device_info1), i2c_device_info1 , 1}, //i2c-0 smbus (for DVT) + {bus_id(1), ARRAY_SIZE(i2c_device_info1), i2c_device_info1 , 1}, //i2c-1 i2c-gpio (for EVT) + {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 , 0}, //mux 0x73 channel 1 + {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 , 0}, //mux 0x73 channel 0 + {bus_id(2), ARRAY_SIZE(i2c_device_info11), i2c_device_info11, 1}, //mux 0x73 channel 0 + {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 , 1}, //mux 0x70 channel 0 + {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 , 1}, //mux 0x70 channel 1 + {bus_id(6), ARRAY_SIZE(i2c_device_info6), i2c_device_info6 , 1}, //mux 0x70 channel 2 + {bus_id(7), ARRAY_SIZE(i2c_device_info7), i2c_device_info7 , 1}, //mux 0x70 channel 3 +}; + +static struct gpiod_lookup_table inv_i2c_gpiod_table = { + .dev_id = "i2c-gpio.1", + .table = { + GPIO_LOOKUP_IDX("gpio_ich", SDA_PIN, NULL, 0, GPIO_OPEN_DRAIN), //I2C_SDA + GPIO_LOOKUP_IDX("gpio_ich", SCL_PIN, NULL, 1, GPIO_OPEN_DRAIN), //I2C_SCL + }, +}; + +static struct i2c_gpio_platform_data i2c_platform_data = { + .udelay = 5, //5:100kHz + //.sda_is_open_drain = 0, + //.scl_is_open_drain = 0, + //.scl_is_output_only = 0, +}; + +static void i2cgpio_device_release(struct device *dev) +{ + gpiod_remove_lookup_table(&inv_i2c_gpiod_table); +} + +static struct platform_device device_i2c_gpio0 = { + .name = "i2c-gpio", + .id = 1, + .dev = { + .platform_data = &i2c_platform_data, + .release = i2cgpio_device_release, + }, +}; + +static int __init inv_platform_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j,k; + + //use i2c-gpio + //register gpio + outl( inl(0x533) | (1<<2), 0x533); //i2c-gpio sdl(58) + outl( inl(0x541) | (1<<3), 0x541); //i2c gpio sda(75) + outl( inl(0x540) | (1<<5), 0x540); //RST_I2C_MUX_N(69) + outl( inl(0x503) | (1)|(1<<2)|(1<<3), 0x503); //WDT_IRQ_N(24) PSOC_HEART_BEAT(26) CPLD_HEART_BEAT(27) + outl( inl(0x501) | (1<<4), 0x501); //RSTBTN_IN_N(12) + outl( inl(0x533) | (1<<5), 0x533); //RST_BTN_5S_N(61) + + gpiod_add_lookup_table(&inv_i2c_gpiod_table); + + ret = platform_device_register(&device_i2c_gpio0); + if (ret) { + printk(KERN_ERR "i2c-gpio: platform_device_register fail %d\n", ret); + } + msleep(10); + + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_swps.h" + +static int ctl_major; +static int port_major; +static int ioexp_total; +static int port_total; +static int block_polling; +static int auto_config; +static int flag_i2c_reset; +static int flag_mod_state; +static unsigned gpio_rest_mux; +static int gpio_base = 0; +static struct class *swp_class_p = NULL; +static struct inv_platform_s *platform_p = NULL; +static struct inv_ioexp_layout_s *ioexp_layout = NULL; +static struct inv_port_layout_s *port_layout = NULL; +int io_no_init = 0; +module_param(io_no_init, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); +static void swp_polling_worker(struct work_struct *work); +static DECLARE_DELAYED_WORK(swp_polling, swp_polling_worker); + +static int reset_i2c_topology(void); + +static int +__swp_match(struct device *dev, +#ifdef SWPS_KERN_VER_AF_3_10 + + const void *data){ +#else + void *data){ +#endif + + char *name = (char *)data; + if (strcmp(dev_name(dev), name) == 0) + return 1; + return 0; +} + + +struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(swp_class_p, + NULL, + name, + __swp_match); + return dev; +} + + +static int +sscanf_2_int(const char *buf) { + + int result = -EBFONT; + char *hex_tag = "0x"; + + if (strcspn(buf, hex_tag) == 0) { + if (sscanf(buf,"%x",&result)) { + return result; + } + } else { + if (sscanf(buf,"%d",&result)) { + return result; + } + if(sscanf(buf,"-%d",&result)) { + return -result; + } + if (sscanf(buf,"%x",&result)) { + return result; + } + } + return -EBFONT; +} + + +static int +sscanf_2_binary(const char *buf) { + + int result = sscanf_2_int(buf); + + if (result < 0){ + return -EBFONT; + } + switch (result) { + case 0: + case 1: + return result; + default: + break; + } + return -EBFONT; +} + + +static int +_get_polling_period(void) { + + int retval = 0; + + if (SWP_POLLING_PERIOD == 0) { + return 0; + } + retval = ((SWP_POLLING_PERIOD * HZ) / 1000); + if (retval == 0) { + return 1; + } + return retval; +} + + +static struct transvr_obj_s * +_get_transvr_obj(char *dev_name) { + + struct device *dev_p = NULL; + struct transvr_obj_s *transvr_obj_p = NULL; + + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + return NULL; + } + transvr_obj_p = dev_get_drvdata(dev_p); + if (!transvr_obj_p){ + return NULL; + } + return transvr_obj_p; +} + + +static int +_is_i2c_target_exist(int chan, int addr) { + /* retval: Exist = 1 / Not exist = 0 / Error < 0 + */ + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + int retval = -1; + int err = -1; + int d_offs = 0; + + adap = i2c_get_adapter(chan); + if (!adap) { + SWPS_DEBUG("%s: can't get adapter\n", __func__); + retval = 0; + goto out_is_i2c_target_exist_1; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) { + SWPS_ERR("%s: kzalloc fail\n", __func__); + retval = -1; + goto out_is_i2c_target_exist_2; + } + client->adapter = adap; + client->addr = addr; + err = i2c_smbus_read_byte_data(client, d_offs); + if (err < 0) { + retval = 0; + } else { + retval = 1; + } + i2c_put_adapter(adap); + kfree(client); + return retval; + +out_is_i2c_target_exist_2: + i2c_put_adapter(adap); +out_is_i2c_target_exist_1: + return retval; +} + + +static void +unlock_tobj_all(void) { + + struct transvr_obj_s *tobj_p; + char port_name[32]; + int port_id = 0; + int minor_curr = 0; + + for (minor_curr=0; minor_currauto_config = auto_config; + unlock_transvr_obj(tobj_p); + SWPS_DEBUG("%s: Set %s auto_config=%d\n", + __func__, tobj_p->swp_name, auto_config); + } + return retval; +} + + +/* ========== R/W Functions module control attribute ========== + */ +static ssize_t +show_attr_platform(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 32, "%s\n", platform_p->name); +} + + +static ssize_t +show_attr_version(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%s\n", SWP_VERSION); +} + + +static ssize_t +show_attr_status(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", flag_mod_state); +} + + +static ssize_t +show_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", auto_config); +} + + +static ssize_t +show_attr_block_poll(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", block_polling); +} +static ssize_t +show_attr_io_no_init(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", io_no_init); +} + + +static int +_check_reset_pwd(const char *buf_p, + size_t count) { + + int in_max = 64; + int in_len = (int)count; + char in_val[64] = "ERR"; + char *emsg = "ERR"; + + if (in_len >= in_max) { + emsg = "input too much"; + goto err_check_reset_pwd; + } + if (!sscanf(buf_p,"%s",in_val)) { + emsg = "format incorrect"; + goto err_check_reset_pwd; + } + if (strcmp(in_val, SWP_RESET_PWD) != 0) { + emsg = "password incorrect"; + goto err_check_reset_pwd; + } + return 0; + +err_check_reset_pwd: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + +static ssize_t +store_attr_reset_i2c(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + /* Polling mode */ + if (SWP_POLLING_ENABLE) { + SWPS_INFO("%s: reset I2C :polling\n", __func__); + flag_i2c_reset = 1; + return count; + } + /* Direct mode */ + SWPS_INFO("%s: reset I2C go. :direct\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset fail!\n", __func__); + return -EIO; + } + SWPS_INFO("%s: reset I2C ok. :direct\n", __func__); + return count; +} + + +static ssize_t +store_attr_reset_swps(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p; + char port_name[32] = "ERR"; + int port_id = 0; + int minor_curr = 0; + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + for (minor_curr=0; minor_currstate = STATE_TRANSVR_DISCONNECTED; + unlock_transvr_obj(tobj_p); + SWPS_INFO("%s: reset:%s\n", __func__, tobj_p->swp_name); + } + return count; +} + + +static ssize_t +store_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if (input_val < 0){ + return -EBFONT; + } + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + auto_config = input_val; + _update_auto_config_2_trnasvr(); + return count; +} + + +static ssize_t +store_attr_block_poll( struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if (input_val < 0){ + return -EBFONT; + } + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + + if(input_val != block_polling){ + block_polling = input_val; + if(block_polling){ + cancel_delayed_work_sync(&swp_polling); + } + else{ + schedule_delayed_work(&swp_polling, _get_polling_period()); + } + } + + return count; +} + +static ssize_t +store_attr_io_no_init( struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + + if(input_val != io_no_init){ + io_no_init = input_val; + } + + return count; +} + +/* ========== Show functions: For transceiver attribute ========== + */ +static ssize_t +_show_transvr_hex_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + int result; + + lock_transvr_obj(tobj_p); + result = get_func(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 8, "%d\n", result); + } else { + len = snprintf(buf_p, 8, "0x%02x\n", result); + } + return len; +} + + +static ssize_t +_show_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = snprintf(buf_p, 16, "%d\n", get_func(tobj_p)); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +_show_transvr_str_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p, char* buf), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = get_func(tobj_p, buf_p); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +show_attr_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_id, + buf_p); +} + + +static ssize_t +show_attr_ext_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_ext_id, + buf_p); +} + + +static ssize_t +show_attr_connector(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_connector, + buf_p); +} + + +static ssize_t +show_attr_vendor_name(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_name, + buf_p); +} + + +static ssize_t +show_attr_vendor_pn(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_pn, + buf_p); +} + + +static ssize_t +show_attr_vendor_rev(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_rev, + buf_p); +} + + +static ssize_t +show_attr_vendor_sn(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_sn, + buf_p); +} + + +static ssize_t +show_attr_power_cls(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + size_t len; + int result; + struct transvr_obj_s *tobj_p; + + tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + lock_transvr_obj(tobj_p); + result = tobj_p->get_power_cls(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 16, "%d\n", result); + } else { + len = snprintf(buf_p, 16, "Power Class %d\n", result); + } + return len; +} + + +static ssize_t +show_attr_br(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_br, + buf_p); +} + + +static ssize_t +show_attr_len_sm(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_sm, + buf_p); +} + + +static ssize_t +show_attr_len_smf(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_smf, + buf_p); +} + + +static ssize_t +show_attr_len_om1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om1, + buf_p); +} + + +static ssize_t +show_attr_len_om2(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om2, + buf_p); +} + + +static ssize_t +show_attr_len_om3(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om3, + buf_p); +} + + +static ssize_t +show_attr_len_om4(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om4, + buf_p); +} + + +static ssize_t +show_attr_comp_rev(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_rev, + buf_p); +} + + +static ssize_t +show_attr_comp_eth(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_1, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10_40(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10_40, + buf_p); +} + + +static ssize_t +show_attr_comp_extend(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_extend, + buf_p); +} + + +static ssize_t +show_attr_rate_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_rate_id, + buf_p); +} + + +static ssize_t +show_attr_temperature(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_curr_temp, + buf_p); +} + + +static ssize_t +show_attr_voltage(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_curr_vol, + buf_p); +} + + +static ssize_t +show_attr_tx_bias(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_bias, + buf_p); +} + + +static ssize_t +show_attr_tx_power(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_power, + buf_p); +} + + +static ssize_t +show_attr_tx_eq(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_eq, + buf_p); +} + + +static ssize_t +show_attr_rx_power(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_power, + buf_p); +} + + +static ssize_t +show_attr_rx_am(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_am, + buf_p); +} + + +static ssize_t +show_attr_rx_em(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_em, + buf_p); +} + + +static ssize_t +show_attr_wavelength(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_wavelength, + buf_p); +} + + +static ssize_t +show_attr_extphy_offset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_extphy_offset, + buf_p); +} + + +static ssize_t +show_attr_extphy_reg(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_extphy_reg, + buf_p); +} + + +static ssize_t +show_attr_info(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_info, + buf_p); +} + + +static ssize_t +show_attr_if_type(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_type, + buf_p); +} + + +static ssize_t +show_attr_if_speed(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_speed, + buf_p); +} + + +static ssize_t +show_attr_if_lane(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_lane, + buf_p); +} + + +static ssize_t +show_attr_cdr(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_cdr, + buf_p); +} + + +static ssize_t +show_attr_soft_rs0(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs0, + buf_p); +} + + +static ssize_t +show_attr_soft_rs1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs1, + buf_p); +} + + +static ssize_t +show_attr_soft_rx_los(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_rx_los, + buf_p); +} + + +static ssize_t +show_attr_soft_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_disable, + buf_p); +} + + +static ssize_t +show_attr_soft_tx_fault(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_fault, + buf_p); +} + + +static ssize_t +show_attr_auto_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_auto_tx_disable, + buf_p); +} + + +/* ========== Store functions: transceiver (R/W) attribute ========== + */ +static ssize_t +_store_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_byte_hex_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if ((input < 0) || (input > 0xff)){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_binary_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_binary(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_cdr(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_byte_hex_attr(tobj_p, + tobj_p->set_cdr, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs0(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs1(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs1, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int check = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((check < 0) || (check > 0xf)){ + return -EBFONT; + } + return _store_transvr_byte_hex_attr(tobj_p, + tobj_p->set_soft_tx_disable, + buf_p, + count); +} + + +static ssize_t +store_attr_auto_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int err = -EPERM; + int input = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((input < 0) || (input > 0xf)){ + if (input != VAL_TRANSVR_FUNCTION_DISABLE) { + return -EBFONT; + } + } + lock_transvr_obj(tobj_p); + err = tobj_p->set_auto_tx_disable(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_tx_eq(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_tx_eq, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_am(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_rx_am, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_em(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_rx_em, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_offset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_extphy_offset, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_reg(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_extphy_reg, + buf_p, + count); +} + +/* ========== Show functions: For I/O Expander attribute ========== + */ +static ssize_t +_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset), + char *buf_p) { + size_t len; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR(" %s: data corruption! :%s\n", __func__, tobj_p->swp_name); + return -ENODATA; + } + mutex_lock(&ioexp_p->lock); + len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset)); + mutex_unlock(&ioexp_p->lock); + return len; +} + + +static ssize_t +show_attr_present(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_present, + buf_p); +} + + +static ssize_t +show_attr_tx_fault(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_fault, + buf_p); +} + + +static ssize_t +show_attr_rxlos(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_rxlos, + buf_p); +} + + +static ssize_t +show_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_disable, + buf_p); +} + + +static ssize_t +show_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_reset, + buf_p); +} + + +static ssize_t +show_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_lpmod, + buf_p); +} + + +static ssize_t +show_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_modsel, + buf_p); +} + + +static ssize_t +show_attr_hard_rs0(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_hard_rs0, + buf_p); +} + + +static ssize_t +show_attr_hard_rs1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_hard_rs1, + buf_p); +} + + +/* ========== Store functions: For I/O Expander (R/W) attribute ========== + */ +static ssize_t +_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*set_func)(struct ioexp_obj_s *ioexp_p, + int virt_offset, int input_val), + const char *buf_p, + size_t count) { + + int input, err; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR("%s: data corruption! :%s\n", + __func__, tobj_p->swp_name); + return -ENODATA; + } + input = sscanf_2_binary(buf_p); + if (input < 0) { + return -EBFONT; + } + mutex_lock(&ioexp_p->lock); + err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input); + mutex_unlock(&ioexp_p->lock); + if (err < 0){ + return err; + } + return count; +} + +static ssize_t +store_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_tx_disable, + buf_p, + count); +} + + +static ssize_t +store_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_reset, + buf_p, + count); +} + + +static ssize_t +store_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_lpmod, + buf_p, + count); +} + + +static ssize_t +store_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_modsel, + buf_p, + count); +} + + +static ssize_t +store_attr_hard_rs0(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_hard_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_hard_rs1(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_hard_rs1, + buf_p, + count); +} + + +/* ========== SWPS attribute: For module control ========== + */ +static DEVICE_ATTR(platform, S_IRUGO, show_attr_platform, NULL); +static DEVICE_ATTR(version, S_IRUGO, show_attr_version, NULL); +static DEVICE_ATTR(status, S_IRUGO, show_attr_status, NULL); +static DEVICE_ATTR(reset_i2c, S_IWUSR, NULL, store_attr_reset_i2c); +static DEVICE_ATTR(reset_swps, S_IWUSR, NULL, store_attr_reset_swps); +static DEVICE_ATTR(auto_config, S_IRUGO|S_IWUSR, show_attr_auto_config, store_attr_auto_config); +static DEVICE_ATTR(block_poll, S_IRUGO|S_IWUSR, show_attr_block_poll, store_attr_block_poll); +static DEVICE_ATTR(io_no_init, S_IRUGO|S_IWUSR, show_attr_io_no_init, store_attr_io_no_init); + + +/* ========== Transceiver attribute: from eeprom ========== + */ +static DEVICE_ATTR(id, S_IRUGO, show_attr_id, NULL); +static DEVICE_ATTR(ext_id, S_IRUGO, show_attr_ext_id, NULL); +static DEVICE_ATTR(connector, S_IRUGO, show_attr_connector, NULL); +static DEVICE_ATTR(vendor_name, S_IRUGO, show_attr_vendor_name, NULL); +static DEVICE_ATTR(vendor_pn, S_IRUGO, show_attr_vendor_pn, NULL); +static DEVICE_ATTR(vendor_rev, S_IRUGO, show_attr_vendor_rev, NULL); +static DEVICE_ATTR(vendor_sn, S_IRUGO, show_attr_vendor_sn, NULL); +static DEVICE_ATTR(power_cls, S_IRUGO, show_attr_power_cls, NULL); +static DEVICE_ATTR(br, S_IRUGO, show_attr_br, NULL); +static DEVICE_ATTR(len_sm, S_IRUGO, show_attr_len_sm, NULL); +static DEVICE_ATTR(len_smf, S_IRUGO, show_attr_len_smf, NULL); +static DEVICE_ATTR(len_om1, S_IRUGO, show_attr_len_om1, NULL); +static DEVICE_ATTR(len_om2, S_IRUGO, show_attr_len_om2, NULL); +static DEVICE_ATTR(len_om3, S_IRUGO, show_attr_len_om3, NULL); +static DEVICE_ATTR(len_om4, S_IRUGO, show_attr_len_om4, NULL); +static DEVICE_ATTR(comp_rev, S_IRUGO, show_attr_comp_rev, NULL); +static DEVICE_ATTR(comp_eth, S_IRUGO, show_attr_comp_eth, NULL); +static DEVICE_ATTR(comp_eth_10, S_IRUGO, show_attr_comp_eth_10, NULL); +static DEVICE_ATTR(comp_eth_10_40, S_IRUGO, show_attr_comp_eth_10_40, NULL); +static DEVICE_ATTR(comp_extend, S_IRUGO, show_attr_comp_extend, NULL); +static DEVICE_ATTR(rate_id, S_IRUGO, show_attr_rate_id, NULL); +static DEVICE_ATTR(temperature, S_IRUGO, show_attr_temperature, NULL); +static DEVICE_ATTR(voltage, S_IRUGO, show_attr_voltage, NULL); +static DEVICE_ATTR(tx_bias, S_IRUGO, show_attr_tx_bias, NULL); +static DEVICE_ATTR(tx_power, S_IRUGO, show_attr_tx_power, NULL); +static DEVICE_ATTR(rx_power, S_IRUGO, show_attr_rx_power, NULL); +static DEVICE_ATTR(info, S_IRUGO, show_attr_info, NULL); +static DEVICE_ATTR(if_type, S_IRUGO, show_attr_if_type, NULL); +static DEVICE_ATTR(if_speed, S_IRUGO, show_attr_if_speed, NULL); +static DEVICE_ATTR(if_lane, S_IRUGO, show_attr_if_lane, NULL); +static DEVICE_ATTR(soft_rx_los, S_IRUGO, show_attr_soft_rx_los, NULL); +static DEVICE_ATTR(soft_tx_fault, S_IRUGO, show_attr_soft_tx_fault, NULL); +static DEVICE_ATTR(wavelength, S_IRUGO, show_attr_wavelength, NULL); +static DEVICE_ATTR(tx_eq, S_IRUGO|S_IWUSR, show_attr_tx_eq, store_attr_tx_eq); +static DEVICE_ATTR(rx_am, S_IRUGO|S_IWUSR, show_attr_rx_am, store_attr_rx_am); +static DEVICE_ATTR(rx_em, S_IRUGO|S_IWUSR, show_attr_rx_em, store_attr_rx_em); +static DEVICE_ATTR(cdr, S_IRUGO|S_IWUSR, show_attr_cdr, store_attr_cdr); +static DEVICE_ATTR(soft_rs0, S_IRUGO|S_IWUSR, show_attr_soft_rs0, store_attr_soft_rs0); +static DEVICE_ATTR(soft_rs1, S_IRUGO|S_IWUSR, show_attr_soft_rs1, store_attr_soft_rs1); +static DEVICE_ATTR(soft_tx_disable, S_IRUGO|S_IWUSR, show_attr_soft_tx_disable, store_attr_soft_tx_disable); +static DEVICE_ATTR(auto_tx_disable, S_IRUGO|S_IWUSR, show_attr_auto_tx_disable, store_attr_auto_tx_disable); +static DEVICE_ATTR(extphy_offset, S_IRUGO|S_IWUSR, show_attr_extphy_offset, store_attr_extphy_offset); +static DEVICE_ATTR(extphy_reg, S_IRUGO|S_IWUSR, show_attr_extphy_reg, store_attr_extphy_reg); + +/* ========== IO Expander attribute: from expander ========== + */ +static DEVICE_ATTR(present, S_IRUGO, show_attr_present, NULL); +static DEVICE_ATTR(tx_fault, S_IRUGO, show_attr_tx_fault, NULL); +static DEVICE_ATTR(rxlos, S_IRUGO, show_attr_rxlos, NULL); +static DEVICE_ATTR(tx_disable, S_IRUGO|S_IWUSR, show_attr_tx_disable, store_attr_tx_disable); +static DEVICE_ATTR(reset, S_IRUGO|S_IWUSR, show_attr_reset, store_attr_reset); +static DEVICE_ATTR(lpmod, S_IRUGO|S_IWUSR, show_attr_lpmod, store_attr_lpmod); +static DEVICE_ATTR(modsel, S_IRUGO|S_IWUSR, show_attr_modsel, store_attr_modsel); +static DEVICE_ATTR(hard_rs0, S_IRUGO|S_IWUSR, show_attr_hard_rs0, store_attr_hard_rs0); +static DEVICE_ATTR(hard_rs1, S_IRUGO|S_IWUSR, show_attr_hard_rs1, store_attr_hard_rs1); + +/* ========== Functions for module handling ========== + */ +static void +clean_port_objs(void){ + + dev_t dev_num; + char dev_name[32]; + struct device *device_p; + struct transvr_obj_s *tobj_p; + int minor_curr, port_id; + + for (minor_curr=0; minor_curri2c_client_p) { + i2c_put_adapter(tobj_p->i2c_client_p->adapter); + kfree(tobj_p->i2c_client_p); + } + kfree(tobj_p->vendor_name); + kfree(tobj_p->vendor_pn); + kfree(tobj_p->vendor_rev); + kfree(tobj_p->vendor_sn); + kfree(tobj_p->worker_p); + kfree(tobj_p); + } + dev_num = MKDEV(port_major, minor_curr); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static void +clean_swps_common(void){ + + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(SWP_DEV_MODCTL); + if (device_p){ + dev_num = MKDEV(ctl_major, 1); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + cancel_delayed_work_sync(&swp_polling); + if (platform_p) { + kfree(platform_p); + } + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static int +get_platform_type(void){ + + int i, tmp; + int auto_chan = -1; + int auto_addr = -1; + int pf_total = ARRAY_SIZE(platform_map); + char log_msg[64] = "ERROR"; + + platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL); + if (!platform_p){ + snprintf(log_msg, sizeof(log_msg), "kzalloc fail"); + goto err_get_platform_type_1; + } + memset(platform_p->name, 0, sizeof(platform_p->name)); + + switch (PLATFORM_SETTINGS) { + case PLATFORM_TYPE_AUTO: + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", dmi_get_system_info(DMI_BOARD_NAME)); + for (i=0; iname, platform_map[i].name) == 0) { + platform_p->id = platform_map[i].id; + snprintf(log_msg, sizeof(log_msg), + "Auto detect platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Auto detect fail! detect platform: %s", + platform_p->name); + goto err_get_platform_type_2; + + case PLATFORM_TYPE_PEONY_AUTO: +#ifdef SWPS_PEONY_SFP + auto_chan = peony_sfp_ioexp_layout[0].addr[0].chan_id; + auto_addr = peony_sfp_ioexp_layout[0].addr[0].chip_addr; +#endif + tmp = _is_i2c_target_exist(auto_chan, auto_addr); + switch (tmp) { + case 0: /* Copper SKU */ + SWPS_INFO("Auto-detected :Peony :Copper\n"); + platform_p->id = PLATFORM_TYPE_PEONY_COPPER_GA; + goto map_platform_name; + + case 1: /* SFP SKU */ + SWPS_INFO("Auto-detected :Peony :SFP\n"); + platform_p->id = PLATFORM_TYPE_PEONY_SFP_GA; + goto map_platform_name; + + default: + break; + } + snprintf(log_msg, sizeof(log_msg), + "Auto detect Peony SKU fail! :%d", tmp); + goto err_get_platform_type_2; + + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + case PLATFORM_TYPE_REDWOOD: + case PLATFORM_TYPE_REDWOOD_FSL: + case PLATFORM_TYPE_HUDSON32I_GA: + case PLATFORM_TYPE_SPRUCE: + case PLATFORM_TYPE_CYPRESS_GA1: + case PLATFORM_TYPE_CYPRESS_GA2: + case PLATFORM_TYPE_CYPRESS_BAI: + case PLATFORM_TYPE_TAHOE: + case PLATFORM_TYPE_SEQUOIA_GA: + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + case PLATFORM_TYPE_COTTONWOOD_RANGELEY: + case PLATFORM_TYPE_MAPLE_GA: + case PLATFORM_TYPE_MAPLE_B: + case PLATFORM_TYPE_MAPLE_J: + case PLATFORM_TYPE_GULMOHAR_GA: + case PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA: + case PLATFORM_TYPE_PEONY_SFP_GA: + case PLATFORM_TYPE_PEONY_COPPER_GA: + case PLATFORM_TYPE_CEDAR_GA: + platform_p->id = PLATFORM_SETTINGS; + goto map_platform_name; + + default: + break; + } + snprintf(log_msg, sizeof(log_msg), + "PLATFORM_SETTINGS:%d undefined", PLATFORM_SETTINGS); + goto err_get_platform_type_2; + +map_platform_name: + for (i=0; iid == platform_map[i].id) { + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", platform_map[i].name); + snprintf(log_msg, sizeof(log_msg), + "User setup platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Internal error, can not map id:%d", + platform_p->id ); + goto err_get_platform_type_2; + +ok_get_platform_type_1: + SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return 0; + +err_get_platform_type_2: + kfree(platform_p); +err_get_platform_type_1: + SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return -1; +} + + +static int +get_layout_info(void){ + + switch (platform_p->id) { +#ifdef SWPS_MAGNOLIA + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + gpio_rest_mux = gpio_base + magnolia_gpio_rest_mux; + ioexp_layout = magnolia_ioexp_layout; + port_layout = magnolia_port_layout; + ioexp_total = ARRAY_SIZE(magnolia_ioexp_layout); + port_total = ARRAY_SIZE(magnolia_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD + case PLATFORM_TYPE_REDWOOD: + gpio_rest_mux = gpio_base + redwood_gpio_rest_mux; + ioexp_layout = redwood_ioexp_layout; + port_layout = redwood_port_layout; + ioexp_total = ARRAY_SIZE(redwood_ioexp_layout); + port_total = ARRAY_SIZE(redwood_port_layout); + break; +#endif +#ifdef SWPS_HUDSON32I_GA + case PLATFORM_TYPE_HUDSON32I_GA: + gpio_rest_mux = gpio_base + hudsin32iga_gpio_rest_mux; + ioexp_layout = hudson32iga_ioexp_layout; + port_layout = hudson32iga_port_layout; + ioexp_total = ARRAY_SIZE(hudson32iga_ioexp_layout); + port_total = ARRAY_SIZE(hudson32iga_port_layout); + break; +#endif +#ifdef SWPS_SPRUCE + case PLATFORM_TYPE_SPRUCE: + gpio_rest_mux = gpio_base + spruce_gpio_rest_mux; + ioexp_layout = spruce_ioexp_layout; + port_layout = spruce_port_layout; + ioexp_total = ARRAY_SIZE(spruce_ioexp_layout); + port_total = ARRAY_SIZE(spruce_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA1 + case PLATFORM_TYPE_CYPRESS_GA1: + gpio_rest_mux = gpio_base + cypress_ga1_gpio_rest_mux; + ioexp_layout = cypress_ga1_ioexp_layout; + port_layout = cypress_ga1_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga1_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga1_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA2 + case PLATFORM_TYPE_CYPRESS_GA2: + gpio_rest_mux = gpio_base + cypress_ga2_gpio_rest_mux; + ioexp_layout = cypress_ga2_ioexp_layout; + port_layout = cypress_ga2_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga2_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga2_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_BAI + case PLATFORM_TYPE_CYPRESS_BAI: + gpio_rest_mux = gpio_base + cypress_b_gpio_rest_mux; + ioexp_layout = cypress_b_ioexp_layout; + port_layout = cypress_b_port_layout; + ioexp_total = ARRAY_SIZE(cypress_b_ioexp_layout); + port_total = ARRAY_SIZE(cypress_b_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD_FSL + case PLATFORM_TYPE_REDWOOD_FSL: + gpio_rest_mux = gpio_base + redwood_fsl_gpio_rest_mux; + ioexp_layout = redwood_fsl_ioexp_layout; + port_layout = redwood_fsl_port_layout; + ioexp_total = ARRAY_SIZE(redwood_fsl_ioexp_layout); + port_total = ARRAY_SIZE(redwood_fsl_port_layout); + break; +#endif +#ifdef SWPS_TAHOE + case PLATFORM_TYPE_TAHOE: + gpio_rest_mux = gpio_base + tahoe_gpio_rest_mux; + ioexp_layout = tahoe_ioexp_layout; + port_layout = tahoe_port_layout; + ioexp_total = ARRAY_SIZE(tahoe_ioexp_layout); + port_total = ARRAY_SIZE(tahoe_port_layout); + break; +#endif +#ifdef SWPS_SEQUOIA + case PLATFORM_TYPE_SEQUOIA_GA: + gpio_rest_mux = gpio_base + sequoia_gpio_rest_mux; + ioexp_layout = sequoia_ioexp_layout; + port_layout = sequoia_port_layout; + ioexp_total = ARRAY_SIZE(sequoia_ioexp_layout); + port_total = ARRAY_SIZE(sequoia_port_layout); + break; +#endif +#ifdef SWPS_LAVENDER + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + gpio_rest_mux = gpio_base + lavender_gpio_rest_mux; + ioexp_layout = lavender_ioexp_layout; + port_layout = lavender_port_layout; + ioexp_total = ARRAY_SIZE(lavender_ioexp_layout); + port_total = ARRAY_SIZE(lavender_port_layout); + break; +#endif +#ifdef SWPS_COTTONWOOD_RANGELEY + case PLATFORM_TYPE_COTTONWOOD_RANGELEY: + gpio_rest_mux = gpio_base + cottonwood_rangeley_gpio_rest_mux; + ioexp_layout = cottonwood_rangeley_ioexp_layout; + port_layout = cottonwood_rangeley_port_layout; + ioexp_total = ARRAY_SIZE(cottonwood_rangeley_ioexp_layout); + port_total = ARRAY_SIZE(cottonwood_rangeley_port_layout); + break; +#endif +#ifdef SWPS_MAPLE_GA + case PLATFORM_TYPE_MAPLE_GA: + gpio_rest_mux = gpio_base + maple_ga_gpio_rest_mux; + ioexp_layout = maple_ga_ioexp_layout; + port_layout = maple_ga_port_layout; + ioexp_total = ARRAY_SIZE(maple_ga_ioexp_layout); + port_total = ARRAY_SIZE(maple_ga_port_layout); + break; +#endif +#ifdef SWPS_MAPLE_B + case PLATFORM_TYPE_MAPLE_B: + gpio_rest_mux = gpio_base + maple_b_gpio_rest_mux; + ioexp_layout = maple_b_ioexp_layout; + port_layout = maple_b_port_layout; + ioexp_total = ARRAY_SIZE(maple_b_ioexp_layout); + port_total = ARRAY_SIZE(maple_b_port_layout); + break; +#endif +#ifdef SWPS_MAPLE_J + case PLATFORM_TYPE_MAPLE_J: + gpio_rest_mux = gpio_base + maple_j_gpio_rest_mux; + ioexp_layout = maple_j_ioexp_layout; + port_layout = maple_j_port_layout; + ioexp_total = ARRAY_SIZE(maple_j_ioexp_layout); + port_total = ARRAY_SIZE(maple_j_port_layout); + break; +#endif +#ifdef SWPS_GULMOHAR + case PLATFORM_TYPE_GULMOHAR_GA: + gpio_rest_mux = gpio_base + gulmohar_gpio_rest_mux; + ioexp_layout = gulmohar_ioexp_layout; + port_layout = gulmohar_port_layout; + ioexp_total = ARRAY_SIZE(gulmohar_ioexp_layout); + port_total = ARRAY_SIZE(gulmohar_port_layout); + break; +#endif +#ifdef SWPS_GULMOHAR_2T_EVT1 + case PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA: + gpio_rest_mux = gpio_base + gulmohar_2t_evt1_gpio_rest_mux; + ioexp_layout = gulmohar_2t_evt1_ioexp_layout; + port_layout = gulmohar_2t_evt1_port_layout; + ioexp_total = ARRAY_SIZE(gulmohar_2t_evt1_ioexp_layout); + port_total = ARRAY_SIZE(gulmohar_2t_evt1_port_layout); + break; +#endif +#ifdef SWPS_PEONY_SFP + case PLATFORM_TYPE_PEONY_SFP_GA: + gpio_rest_mux = gpio_base + peony_sfp_gpio_rest_mux; + ioexp_layout = peony_sfp_ioexp_layout; + port_layout = peony_sfp_port_layout; + ioexp_total = ARRAY_SIZE(peony_sfp_ioexp_layout); + port_total = ARRAY_SIZE(peony_sfp_port_layout); + break; +#endif +#ifdef SWPS_PEONY_COPPER + case PLATFORM_TYPE_PEONY_COPPER_GA: + gpio_rest_mux = gpio_base + peony_copper_gpio_rest_mux; + ioexp_layout = peony_copper_ioexp_layout; + port_layout = peony_copper_port_layout; + ioexp_total = ARRAY_SIZE(peony_copper_ioexp_layout); + port_total = ARRAY_SIZE(peony_copper_port_layout); + break; +#endif +#ifdef SWPS_CEDAR_GA + case PLATFORM_TYPE_CEDAR_GA: + gpio_rest_mux = gpio_base + cedar_ga_gpio_rest_mux; + ioexp_layout = cedar_ga_ioexp_layout; + port_layout = cedar_ga_port_layout; + ioexp_total = ARRAY_SIZE(cedar_ga_ioexp_layout); + port_total = ARRAY_SIZE(cedar_ga_port_layout); + break; +#endif + + default: + SWPS_ERR(" Invalid platform: %d (%s)\n", + platform_p->id, platform_p->name); + return -1; + } + SWPS_INFO("Start to initial platform: %d (%s)\n", + platform_p->id, platform_p->name); + return 0; +} + + +/* ========== Functions for objects operations ========== + */ +static int +__detect_issues_port(int minor_num) { + + struct transvr_obj_s *tobj_p; + int port_id = port_layout[minor_num].port_id; + char port_name[32] = "ERR"; + char *i2c_emsg = "detected bad transceiver/cable"; + + memset(port_name, 0, sizeof(port_name)); + snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id); + tobj_p = _get_transvr_obj(port_name); + if (!tobj_p) { + SWPS_INFO("%s: tobj_p is NULL :%d\n", __func__, minor_num); + return -1; + } + if (resync_channel_tier_2(tobj_p) < 0) { + if (check_channel_tier_1() < 0) { + goto get_target_issues_port; + } + } + /* Re-check again for i2c-gpio special case */ + if (check_channel_tier_1() < 0) { + goto get_target_issues_port; + } + return 0; + +get_target_issues_port: + alarm_msg_2_user(tobj_p, i2c_emsg); + return -2; +} + + +static int +_detect_issues_port(void) { + /* OK : retrun -1; + * Fail: return fail at which minor number (0~N) + */ + char *emsg = "ERR"; + int minor = 0; + int minor_2st = 1; + + /* Force moving the initial channel pointer + * Filter out case of fail at minor-0 port + */ + while (minor_2st < port_total) { + minor = minor_2st; + if (__detect_issues_port(minor_2st) < 0) { + emsg = "detect minor_2st fail"; + goto err_p_detect_issues_port; + } + minor_2st += 8; + } + /* Scan all port */ + for (minor=0; minor:%d\n", __func__, emsg, minor_err); + return -1; +} + + +static int +check_transvr_obj_one(char *dev_name){ + /* [Return] + * 0 : Doesn't need to take care + * -1 : Single error + * -2 : Critical error (I2C topology die) + * -9 : Internal error + */ + struct transvr_obj_s *tobj_p = NULL; + int retval = -9; + + tobj_p = _get_transvr_obj(dev_name); + if (!tobj_p) { + SWPS_ERR("%s: %s _get_transvr_obj fail\n", + __func__, dev_name); + return -9; + } + /* Check transceiver current status */ + lock_transvr_obj(tobj_p); + retval = tobj_p->check(tobj_p); + unlock_transvr_obj(tobj_p); + switch (retval) { + case 0: + case ERR_TRANSVR_UNPLUGGED: + case ERR_TRNASVR_BE_ISOLATED: + case ERR_TRANSVR_TASK_BUSY: + return 0; + + case ERR_TRANSVR_I2C_CRASH: + default: + break; + } + /* Identify abnormal case */ + if (check_channel_tier_1() < 0) { + SWPS_DEBUG("%s: %s critical error :%d\n", + __func__, dev_name, retval); + return -2; + } + SWPS_DEBUG("%s: %s single error :%d\n", + __func__, dev_name, retval); + return -1; +} + + +static int +check_transvr_objs(void){ + + char dev_name[32]; + int port_id, err_code; + int minor_curr = 0; + + for (minor_curr=0; minor_curr:%d\n", + __func__, dev_name, err_code); + break; + } + } + return 0; + +err_check_transvr_objs: + SWPS_ERR("%s: %s reset_i2c_topology fail.\n", + __func__, dev_name); + return -1; +} + + +static void +swp_polling_worker(struct work_struct *work){ + + /* Reset I2C */ + if (flag_i2c_reset) { + goto polling_reset_i2c; + } + /* Check IOEXP */ + if (check_ioexp_objs() < 0) { + goto polling_reset_i2c; + } + /* Check transceiver */ + if (check_transvr_objs() < 0) { + SWPS_DEBUG("%s: check_transvr_objs fail.\n", __func__); + flag_i2c_reset = 1; + } + goto polling_schedule_round; + +polling_reset_i2c: + SWPS_DEBUG("%s: reset_i2c_topology start.\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset i2c fail!\n", __func__); + flag_i2c_reset = 1; + } else { + SWPS_DEBUG("%s: reset_i2c_topology OK.\n", __func__); + flag_i2c_reset = 0; + } +polling_schedule_round: + schedule_delayed_work(&swp_polling, _get_polling_period()); +} + + +/* ========== Functions for register something ========== + */ +static int +register_transvr_common_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_id) < 0) { + err_attr = "dev_attr_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_ext_id) < 0) { + err_attr = "dev_attr_ext_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_connector) < 0) { + err_attr = "dev_attr_connector"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_name) < 0) { + err_attr = "dev_attr_vendor_name"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_pn) < 0) { + err_attr = "dev_attr_vendor_pn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_rev) < 0) { + err_attr = "dev_attr_vendor_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_sn) < 0) { + err_attr = "dev_attr_vendor_sn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_br) < 0) { + err_attr = "dev_attr_br"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_smf) < 0) { + err_attr = "dev_attr_len_smf"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om1) < 0) { + err_attr = "dev_attr_len_om1"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om2) < 0) { + err_attr = "dev_attr_len_om2"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om3) < 0) { + err_attr = "dev_attr_len_om3"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om4) < 0) { + err_attr = "dev_attr_len_om4"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_extend) < 0) { + err_attr = "dev_attr_comp_extend"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth) < 0) { + err_attr = "dev_attr_comp_eth"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_rev) < 0) { + err_attr = "dev_attr_comp_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_info) < 0) { + err_attr = "dev_attr_info"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_type) < 0) { + err_attr = "dev_attr_if_type"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_speed) < 0) { + err_attr = "dev_attr_if_speed"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_lane) < 0) { + err_attr = "dev_attr_if_lane"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_temperature) < 0) { + err_attr = "dev_attr_temperature"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_voltage) < 0) { + err_attr = "dev_attr_voltage"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_bias) < 0) { + err_attr = "dev_attr_tx_bias"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_power) < 0) { + err_attr = "dev_attr_tx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_power) < 0) { + err_attr = "dev_attr_rx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_eq) < 0) { + err_attr = "dev_attr_tx_eq"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_em) < 0) { + err_attr = "dev_attr_rx_em"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_wavelength) < 0) { + err_attr = "dev_attr_wavelength"; + goto err_transvr_comm_attr; + } + return 0; + +err_transvr_comm_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + +static int +register_transvr_sfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10) < 0) { + err_attr = "dev_attr_comp_eth_10"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_len_sm) < 0) { + err_attr = "dev_attr_len_sm"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_rate_id) < 0) { + err_attr = "dev_attr_rate_id"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs0) < 0) { + err_attr = "dev_attr_soft_rs0"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs1) < 0) { + err_attr = "dev_attr_soft_rs1"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_offset) < 0) { + err_attr = "dev_attr_extphy_offset"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_reg) < 0) { + err_attr = "dev_attr_extphy_reg"; + goto err_transvr_sfp_attr; + } + return 0; + +err_transvr_sfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10_40) < 0) { + err_attr = "dev_attr_comp_eth_10_40"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_power_cls) < 0) { + err_attr = "dev_attr_power_cls"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rx_los) < 0) { + err_attr = "soft_rx_los"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_disable) < 0) { + err_attr = "soft_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_auto_tx_disable) < 0) { + err_attr = "auto_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_fault) < 0) { + err_attr = "soft_tx_fault"; + goto err_transvr_qsfp_attr; + } + return 0; + +err_transvr_qsfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp28_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_qsfp_attr(device_p) < 0){ + err_attr = "register_transvr_qsfp_attr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_cdr) < 0) { + err_attr = "dev_attr_cdr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_rx_am) < 0) { + err_attr = "dev_attr_rx_am"; + goto err_transvr_qsfp28_attr; + } + return 0; + +err_transvr_qsfp28_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + switch (transvr_obj->layout){ + case TRANSVR_TYPE_SFP: + if (register_transvr_sfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + if (register_transvr_qsfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP_28: + if (register_transvr_qsfp28_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + default: + goto err_reg_tvr_attr; + } + return 0; + +err_reg_tvr_attr: + SWPS_ERR("%s: fail! type=%d \n", __func__, transvr_obj->type); + return -1; +} + + +static int +register_ioexp_attr_sfp_1(struct device *device_p){ + /* Support machine type: + * - SFP : Magnolia + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_fault) < 0) { + err_attr = "dev_attr_tx_fault"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_rxlos) < 0) { + err_attr = "dev_attr_rxlos"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_disable) < 0) { + err_attr = "dev_attr_tx_disable"; + goto err_ioexp_sfp1_attr; + } + return 0; + +err_ioexp_sfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_ioexp_attr_sfp_2(struct device *device_p){ + /* Support machine type: + * - SFP28 : Cypress + */ + char *err_attr = NULL; + + if (register_ioexp_attr_sfp_1(device_p) < 0){ + goto err_ioexp_sfp2_attr; + } + if (device_create_file(device_p, &dev_attr_hard_rs0) < 0) { + err_attr = "dev_attr_hard_rs0"; + goto err_ioexp_sfp2_attr; + } + if (device_create_file(device_p, &dev_attr_hard_rs1) < 0) { + err_attr = "dev_attr_hard_rs1"; + goto err_ioexp_sfp2_attr; + } + return 0; + +err_ioexp_sfp2_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_ioexp_attr_qsfp_1(struct device *device_p){ + /* Support machine type: + * - QSFP : Magnolia, Redwood, Hudson32i + * - QSFP+ : Magnolia, Redwood, Hudson32i + * - QSFP28: Redwood + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_reset) < 0) { + err_attr = "dev_attr_reset"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_lpmod) < 0) { + err_attr = "dev_attr_lpmod"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_modsel) < 0) { + err_attr = "dev_attr_modsel"; + goto err_ioexp_qsfp1_attr; + } + return 0; + +err_ioexp_qsfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_modctl_attr(struct device *device_p){ + + char *err_msg = NULL; + + if (device_create_file(device_p, &dev_attr_platform) < 0) { + err_msg = "dev_attr_platform"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_version) < 0) { + err_msg = "dev_attr_version"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_status) < 0) { + err_msg = "dev_attr_status"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_i2c) < 0) { + err_msg = "dev_attr_reset_i2c"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_swps) < 0) { + err_msg = "dev_attr_reset_swps"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_auto_config) < 0) { + err_msg = "dev_attr_auto_config"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_block_poll) < 0) { + err_msg = "dev_attr_block_poll"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_io_no_init) < 0) { + err_msg = "dev_attr_io_no_init"; + goto err_reg_modctl_attr; + } + + return 0; + +err_reg_modctl_attr: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int +register_ioexp_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + char *err_msg = "ERR"; + + switch (transvr_obj->ioexp_obj_p->ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case CPLD_TYPE_COTTONWOOD: + if (register_ioexp_attr_sfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + + case IOEXP_TYPE_MAPLE_NABC: + case IOEXP_TYPE_GULMOHAR_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + case IOEXP_TYPE_SFP_8P_LAYOUT_1: + if (register_ioexp_attr_sfp_2(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_2 fail"; + goto err_reg_ioexp_attr; + } + break; + + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case IOEXP_TYPE_MAPLE_0ABC: + case IOEXP_TYPE_GULMOHAR_7ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: + case IOEXP_TYPE_CEDAR_0ABC: + if (register_ioexp_attr_qsfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_qsfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + + default: + err_msg = "Unknow type"; + goto err_reg_ioexp_attr; + } + return 0; + +err_reg_ioexp_attr: + SWPS_ERR("%s: %s :%d \n", + __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type); + return -1; +} + + +static int +register_modctl_device(void) { + + struct device *device_p = NULL; + int minor_comm = 0; /* Default minor number for common device */ + dev_t dev_num = MKDEV(ctl_major, minor_comm); + char *err_msg = "ERROR"; + + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + NULL, /* void *private_data */ + SWP_DEV_MODCTL); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_modctl_device_1; + } + if (register_modctl_attr(device_p) < 0) { + err_msg = "register_modctl_attr fail"; + goto err_register_modctl_device_2; + } + return 0; + +err_register_modctl_device_2: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_register_modctl_device_1: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int +register_port_device(char *dev_name, + dev_t dev_num, + struct transvr_obj_s *transvr_obj){ + + struct device *device_p = NULL; + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + transvr_obj, /* void *private_data */ + dev_name); /* const char *fmt */ + if (IS_ERR(device_p)){ + goto err_regswp_create_dev; + } + if (register_transvr_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + if (register_ioexp_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + return 0; + +err_regswp_reg_attr: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_regswp_create_dev: + SWPS_ERR("%s fail! :%s\n", __func__, dev_name); + return -1; +} + + +static int +register_swp_module(void){ + + dev_t ctl_devt = 0; + dev_t port_devt = 0; + //int dev_total = port_total + 1; /* char_dev for module control */ + + /* Register device number */ + if (alloc_chrdev_region(&ctl_devt, 0, 1, SWP_DEV_MODCTL) < 0){ + SWPS_WARN("Allocate CTL MAJOR failure! \n"); + goto err_register_swp_module_1; + } + if (alloc_chrdev_region(&port_devt, 0, port_total, SWP_CLS_NAME) < 0){ + SWPS_WARN("Allocate PORT MAJOR failure! \n"); + goto err_register_swp_module_2; + } + ctl_major = MAJOR(ctl_devt); + port_major = MAJOR(port_devt); + + /* Create class object */ + swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME); + if (IS_ERR(swp_class_p)) { + SWPS_ERR("Create class failure! \n"); + goto err_register_swp_module_3; + } + return 0; + +err_register_swp_module_3: + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_register_swp_module_2: + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); +err_register_swp_module_1: + return -1; +} + + +/* ========== Module initial relate ========== + */ +static int +create_ioexp_objs(void) { + + int i, run_mod; + + /* Clean IOEXP object */ + clean_ioexp_objs(); + /* Get running mode */ + run_mod = IOEXP_MODE_DIRECT; + if (SWP_POLLING_ENABLE){ + run_mod = IOEXP_MODE_POLLING; + } + /* Create IOEXP object */ + for(i=0; i devlen_max) { + snprintf(err_msg, sizeof(err_msg), + "SWP_DEV_PORT too long!"); + goto err_initport_create_tranobj; + } + memset(dev_name, 0, sizeof(dev_name)); + snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id); + /* Create transceiver object */ + ioexp_obj_p = get_ioexp_obj(ioexp_id); + if (!ioexp_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "IOEXP object:%d not exist", ioexp_id); + goto err_initport_create_tranobj; + } + transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p, + ioexp_virt_offset, transvr_type, + chipset_type, run_mod); + if (!transvr_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "Create transceiver object fail :%s", dev_name); + goto err_initport_create_tranobj; + } + /* Setup Lane_ID mapping */ + i = ARRAY_SIZE(port_layout[minor_curr].lane_id); + j = ARRAY_SIZE(transvr_obj_p->lane_id); + if (i != j) { + snprintf(err_msg, sizeof(err_msg), + "Lane_id size inconsistent %d/%d", i, j); + goto err_initport_reg_device; + } + memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int)); + /* Create and register device object */ + if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){ + snprintf(err_msg, sizeof(err_msg), + "register_port_device fail"); + goto err_initport_reg_device; + } + /* Setup device_ptr of transvr_obj */ + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + snprintf(err_msg, sizeof(err_msg), + "get_swpdev_by_name fail"); + goto err_initport_reg_device; + } + transvr_obj_p->transvr_dev_p = dev_p; + /* Success */ + ok_count++; + } + SWPS_INFO("%s: initialed %d port-dev\n",__func__, ok_count); + return 0; + +err_initport_reg_device: + kfree(transvr_obj_p); +err_initport_create_tranobj: + clean_port_objs(); + SWPS_ERR("%s: %s", __func__, err_msg); + SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n", + port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod); + return -1; +} + + +static int +init_dev_topology(void){ + + int err; + char *emsg = "ERR"; + flag_mod_state = SWP_STATE_NORMAL; + + err = init_ioexp_objs(); + switch(err){ + case 0: /* Normal */ + SWPS_DEBUG("%s: normal case\n", __func__); + break; + + case -1: /* topology error */ + SWPS_DEBUG("%s: detect tier-1 topology initial failure :%d\n", + __func__, err); + /* Reset and isolate */ + err = reset_i2c_topology(); + if (err < 0) { + emsg = "reset i2c topology fail"; + goto err_init_dev_topology; + } + /* Re-initial again */ + err = init_ioexp_objs(); + if (err < 0) { + emsg = "re-init ioexp objects fail"; + goto err_init_dev_topology; + } + break; + + case -2: /* Internal error */ + SWPS_DEBUG("%s: internal error case\n", __func__); + err = -2; + emsg = "internal error"; + goto err_init_dev_topology; + + default: + SWPS_DEBUG("%s: undefined error case\n", __func__); + emsg = "undefined error case"; + goto err_init_dev_topology; + } + SWPS_DEBUG("%s: initial I2C topology success\n", __func__); + return 0; + +err_init_dev_topology: + SWPS_ERR("%s: %s :%d\n", __func__, emsg, err); + return -1; +} + + +static int +init_polling_task(void){ + + if (SWP_POLLING_ENABLE){ + schedule_delayed_work(&swp_polling, _get_polling_period()); + } + return 0; +} + + +static int +init_swps_common(void){ + + char *err_msg = "ERR"; + + block_polling = 0; + auto_config = 0; + if ((SWP_AUTOCONFIG_ENABLE) && (SWP_POLLING_ENABLE)){ + auto_config = 1; + } + if (register_modctl_device() < 0) { + err_msg = "register_modctl_device fail"; + goto err_init_swps_common_1; + } + if (_update_auto_config_2_trnasvr() < 0) { + err_msg = "_update_auto_config_2_trnasvr fail"; + goto err_init_swps_common_1; + } + if (init_polling_task() < 0){ + err_msg = "init_polling_task fail"; + goto err_init_swps_common_1; + } + return 0; + +err_init_swps_common_1: + clean_swps_common(); + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int __init +swp_module_init(void){ + + if (get_platform_type() < 0){ + goto err_init_out; + } + if (get_layout_info() < 0){ + goto err_init_out; + } + if (register_swp_module() < 0){ + goto err_init_out; + } + if (create_ioexp_objs() < 0){ + goto err_init_ioexp; + } + if (create_port_objs() < 0){ + goto err_init_portobj; + } + if (init_mux_objs(gpio_rest_mux) < 0){ + goto err_init_mux; + } + if (init_dev_topology() < 0){ + goto err_init_topology; + } + if (init_swps_common() < 0){ + goto err_init_topology; + } + SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION); + return 0; + + +err_init_topology: + clean_mux_objs(); +err_init_mux: + clean_port_objs(); +err_init_portobj: + clean_ioexp_objs(); +err_init_ioexp: + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_init_out: + SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION); + return -1; +} + + +static void __exit +swp_module_exit(void){ + + clean_swps_common(); + clean_port_objs(); + clean_ioexp_objs(); + clean_mux_objs(); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); + SWPS_INFO("Remove Inventec switch-port module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(SWP_AUTHOR); +MODULE_DESCRIPTION(SWP_DESC); +MODULE_VERSION(SWP_VERSION); +MODULE_LICENSE(SWP_LICENSE); +MODULE_SOFTDEP("pre: inv_platform"); +module_param(gpio_base, int, S_IRUGO); + +module_init(swp_module_init); +module_exit(swp_module_exit); + + + + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_swps.h new file mode 100644 index 000000000000..00dc1fde0d8e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/inv_swps.h @@ -0,0 +1,1791 @@ +#ifndef INV_SWPS_H +#define INV_SWPS_H + +#include "transceiver.h" +#include "io_expander.h" +#include "inv_mux.h" + +/* Module settings */ +#define SWP_CLS_NAME "swps" +#define SWP_DEV_PORT "port" +#define SWP_DEV_MODCTL "module" +#define SWP_RESET_PWD "inventec" +#define SWP_POLLING_PERIOD (300) /* msec */ +#define SWP_POLLING_ENABLE (1) +#define SWP_AUTOCONFIG_ENABLE (1) + +/* Module information */ +#define SWP_AUTHOR "Neil " +#define SWP_DESC "Inventec port and transceiver driver" +#define SWP_VERSION "4.3.10" +#define SWP_LICENSE "GPL" + +/* Module status define */ +#define SWP_STATE_NORMAL (0) +#define SWP_STATE_I2C_DIE (-91) + +/* [Note]: + * Functions and mechanism for auto-detect platform type is ready, + * But HW and BIOS not ready! We need to wait them. + * So, please do not use PLATFORM_TYPE_AUTO until they are ready. + * (2016.06.13) + */ +#define PLATFORM_TYPE_AUTO (100) +#define PLATFORM_TYPE_MAGNOLIA (111) +#define PLATFORM_TYPE_MAGNOLIA_FNC (112) +#define PLATFORM_TYPE_REDWOOD (121) +#define PLATFORM_TYPE_REDWOOD_FSL (122) +#define PLATFORM_TYPE_HUDSON32I_GA (131) +#define PLATFORM_TYPE_SPRUCE (141) +#define PLATFORM_TYPE_CYPRESS_GA1 (151) /* Up -> Down */ +#define PLATFORM_TYPE_CYPRESS_GA2 (152) /* Down -> Up */ +#define PLATFORM_TYPE_CYPRESS_BAI (153) /* Down -> Up */ +#define PLATFORM_TYPE_TAHOE (161) +#define PLATFORM_TYPE_SEQUOIA_GA (171) +#define PLATFORM_TYPE_LAVENDER_GA (181) +#define PLATFORM_TYPE_LAVENDER_ONL (182) +#define PLATFORM_TYPE_COTTONWOOD_RANGELEY (191) +#define PLATFORM_TYPE_MAPLE_GA (201) +#define PLATFORM_TYPE_GULMOHAR_GA (202) +#define PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA (203) +#define PLATFORM_TYPE_PEONY_SFP_GA (204) +#define PLATFORM_TYPE_PEONY_COPPER_GA (205) +#define PLATFORM_TYPE_PEONY_AUTO (206) +#define PLATFORM_TYPE_MAPLE_B (207) +#define PLATFORM_TYPE_MAPLE_J (208) +#define PLATFORM_TYPE_CEDAR_GA (209) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_CEDAR_GA + +/* Define platform flag and kernel version */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA_FNC) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD) + #define SWPS_REDWOOD (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD_FSL) + #define SWPS_REDWOOD_FSL (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_HUDSON32I_GA) + #define SWPS_HUDSON32I_GA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SPRUCE) + #define SWPS_SPRUCE (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA1) + #define SWPS_CYPRESS_GA1 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA2) + #define SWPS_CYPRESS_GA2 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_BAI) + #define SWPS_CYPRESS_BAI (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_TAHOE) + #define SWPS_TAHOE (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA) + #define SWPS_SEQUOIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_COTTONWOOD_RANGELEY) + #define SWPS_COTTONWOOD_RANGELEY (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE_GA) + #define SWPS_MAPLE_GA (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE_B) + #define SWPS_MAPLE_B (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE_J) + #define SWPS_MAPLE_J (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_GULMOHAR_GA) + #define SWPS_GULMOHAR (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA) + #define SWPS_GULMOHAR_2T_EVT1 (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_PEONY_SFP_GA) + #define SWPS_PEONY_SFP (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_PEONY_COPPER_GA) + #define SWPS_PEONY_COPPER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_PEONY_AUTO) + #define SWPS_PEONY_SFP (1) + #define SWPS_PEONY_COPPER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CEDAR_GA) + #define SWPS_CEDAR_GA (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#endif + +struct inv_platform_s { + int id; + char name[64]; +}; + +struct inv_ioexp_layout_s { + int ioexp_id; + int ioexp_type; + struct ioexp_addr_s addr[4]; +}; + +struct inv_port_layout_s { + int port_id; + int chan_id; + int ioexp_id; + int ioexp_offset; + int transvr_type; + int chipset_type; + int lane_id[8]; +}; + + +/* ========================================== + * Inventec Platform Settings + * ========================================== + */ +struct inv_platform_s platform_map[] = { + {PLATFORM_TYPE_AUTO, "Auto-Detect" }, + {PLATFORM_TYPE_MAGNOLIA, "Magnolia" }, + {PLATFORM_TYPE_MAGNOLIA_FNC, "Magnolia_FNC" }, + {PLATFORM_TYPE_REDWOOD, "Redwood" }, + {PLATFORM_TYPE_REDWOOD_FSL, "Redwood_FSL" }, + {PLATFORM_TYPE_HUDSON32I_GA, "Hudson32i" }, + {PLATFORM_TYPE_SPRUCE, "Spruce" }, + {PLATFORM_TYPE_CYPRESS_GA1, "Cypress_GA1" }, + {PLATFORM_TYPE_CYPRESS_GA2, "Cypress_GA2" }, + {PLATFORM_TYPE_CYPRESS_BAI, "Cypress_BAI" }, + {PLATFORM_TYPE_TAHOE, "Tahoe" }, + {PLATFORM_TYPE_SEQUOIA_GA, "Sequoia_GA" }, + {PLATFORM_TYPE_LAVENDER_GA, "Lavender_GA" }, + {PLATFORM_TYPE_LAVENDER_ONL, "Lavender_ONL" }, + {PLATFORM_TYPE_COTTONWOOD_RANGELEY, "Cottonwood_RANGELEY" }, + {PLATFORM_TYPE_MAPLE_GA, "Maple_GA" }, + {PLATFORM_TYPE_MAPLE_B, "Maple_B" }, + {PLATFORM_TYPE_MAPLE_J, "Maple_J" }, + {PLATFORM_TYPE_GULMOHAR_GA, "Gulmohar_GA" }, + {PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA, "Gulmohar_2T_EVT1_GA" }, + {PLATFORM_TYPE_PEONY_SFP_GA, "Peony_SFP_GA" }, + {PLATFORM_TYPE_PEONY_COPPER_GA, "Peony_Copper_GA" }, + {PLATFORM_TYPE_PEONY_AUTO, "Peony_Auto_Detect" }, + {PLATFORM_TYPE_CEDAR_GA, "Cedar_GA" }, +}; + + +/* ========================================== + * Magnolia Layout configuration + * ========================================== + */ +#ifdef SWPS_MAGNOLIA +unsigned magnolia_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; + +struct inv_ioexp_layout_s magnolia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAGINOLIA_NAB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {1, IOEXP_TYPE_MAGINOLIA_NAB, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {2, IOEXP_TYPE_MAGINOLIA_NAB, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {3, IOEXP_TYPE_MAGINOLIA_4AB, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf0, 0xff}, {0xf0, 0xff}, }, }, /* addr[1] = I/O Expander 4 B */ + }, + {4, IOEXP_TYPE_MAGINOLIA_NAB, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {5, IOEXP_TYPE_MAGINOLIA_NAB, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {6, IOEXP_TYPE_MAGINOLIA_7AB, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[1] = I/O Expander 7 B */ + }, +}; + +struct inv_port_layout_s magnolia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 16} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 15} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 14} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 13} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 24} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 23} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 22} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 21} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 28} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 27} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 26} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 25} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 32} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 31} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 30} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 29} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 48} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 47} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 46} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 45} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 52} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 51} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 50} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 49} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 56} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 55} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 54} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 53} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 60} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 59} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 58} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 57} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 64} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 63} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 62} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 61} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 68} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 67} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 66} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 65} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 72} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 71} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 70} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 69} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 76} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 75} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 74} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAGNOLIA, { 73} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP, CHIP_TYPE_MAGNOLIA, { 81, 82, 83, 84} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP, CHIP_TYPE_MAGNOLIA, { 77, 78, 79, 80} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP, CHIP_TYPE_MAGNOLIA, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP, CHIP_TYPE_MAGNOLIA, {101,102,103,104} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP, CHIP_TYPE_MAGNOLIA, {105,106,107,108} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP, CHIP_TYPE_MAGNOLIA, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD +unsigned redwood_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; + +struct inv_ioexp_layout_s redwood_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, +}; + +struct inv_port_layout_s redwood_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 1, 2, 3, 4} }, + { 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 5, 6, 7, 8} }, + { 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 9, 10, 11, 12} }, + { 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 13, 14, 15, 16} }, + { 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 17, 18, 19, 20} }, + { 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 21, 22, 23, 24} }, + { 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 25, 26, 27, 28} }, + { 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 29, 30, 31, 32} }, + { 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 33, 34, 35, 36} }, + { 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 37, 38, 39, 40} }, + {10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 41, 42, 43, 44} }, + {11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 45, 46, 47, 48} }, + {12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 49, 50, 51, 52} }, + {13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 53, 54, 55, 56} }, + {14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 57, 58, 59, 60} }, + {15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 61, 62, 63, 64} }, + {16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 65, 66, 67, 68} }, + {17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 69, 70, 71, 72} }, + {18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 73, 74, 75, 76} }, + {19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 77, 78, 79, 80} }, + {20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 81, 82, 83, 84} }, + {21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 85, 86, 87, 88} }, + {22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 89, 90, 91, 92} }, + {23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 93, 94, 95, 96} }, + {24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 97, 98, 99,100} }, + {25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {101,102,103,104} }, + {26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {105,106,107,108} }, + {27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {109,110,111,112} }, + {28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {113,114,115,116} }, + {29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {117,118,119,120} }, + {30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {121,122,123,124} }, + {31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Hudson32i Layout configuration + * ========================================== + */ +#ifdef SWPS_HUDSON32I_GA +unsigned hudsin32iga_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; + +struct inv_ioexp_layout_s hudson32iga_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_HUDSON32IGA_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {1, IOEXP_TYPE_HUDSON32IGA_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {2, IOEXP_TYPE_HUDSON32IGA_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, + {3, IOEXP_TYPE_HUDSON32IGA_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, +}; + +struct inv_port_layout_s hudson32iga_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 1, 2, 3, 4} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 5, 6, 7, 8} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 9, 10, 11, 12} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 13, 14, 15, 16} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 17, 18, 19, 20} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 21, 22, 23, 24} }, + { 6, 12, 0, 6, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 25, 26, 27, 28} }, + { 7, 13, 0, 7, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 29, 30, 31, 32} }, + { 8, 14, 1, 0, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 33, 34, 35, 36} }, + { 9, 15, 1, 1, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 37, 38, 39, 40} }, + {10, 16, 1, 2, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 41, 42, 43, 44} }, + {11, 17, 1, 3, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 45, 46, 47, 48} }, + {12, 18, 1, 4, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 49, 50, 51, 52} }, + {13, 19, 1, 5, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 53, 54, 55, 56} }, + {14, 20, 1, 6, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 57, 58, 59, 60} }, + {15, 21, 1, 7, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 61, 62, 63, 64} }, + {16, 22, 2, 0, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 65, 66, 67, 68} }, + {17, 23, 2, 1, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 69, 70, 71, 72} }, + {18, 24, 2, 2, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 73, 74, 75, 76} }, + {19, 25, 2, 3, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 77, 78, 79, 80} }, + {20, 26, 2, 4, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 81, 82, 83, 84} }, + {21, 27, 2, 5, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 85, 86, 87, 88} }, + {22, 28, 2, 6, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 89, 90, 91, 92} }, + {23, 29, 2, 7, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 93, 94, 95, 96} }, + {24, 30, 3, 0, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 97, 98, 99,100} }, + {25, 31, 3, 1, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, {101,102,103,104} }, + {26, 32, 3, 2, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, {105,106,107,108} }, + {27, 33, 3, 3, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, {109,110,111,112} }, + {28, 34, 3, 4, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, {113,114,115,116} }, + {29, 35, 3, 5, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, {117,118,119,120} }, + {30, 36, 3, 6, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, {121,122,123,124} }, + {31, 37, 3, 7, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Spruce Layout configuration + * ========================================== + */ +#ifdef SWPS_SPRUCE +unsigned spruce_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; + +struct inv_ioexp_layout_s spruce_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SPRUCE_7AB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[2] = I/O Expander 7B */ + }, +}; + +struct inv_port_layout_s spruce_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 81, 82, 83, 84} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 77, 78, 79, 80} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, { 97, 98, 99,100} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, {101,102,103,104} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, {105,106,107,108} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, CHIP_TYPE_MAGNOLIA, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Up->Down]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA1 +unsigned cypress_ga1_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; + +struct inv_ioexp_layout_s cypress_ga1_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_ga1_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 1} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 2} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 3} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 4} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 5} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 6} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 7} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 8} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 9} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 10} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 11} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 12} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 21} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 22} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 23} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 24} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 33} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 34} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 35} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 36} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 37} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 38} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 39} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 40} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 41} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 42} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 43} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 44} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 49} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 50} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 51} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 52} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 53} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 54} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 55} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 56} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 65} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 66} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 67} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 68} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 69} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 70} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 71} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 72} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 81} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 82} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 83} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 84} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 97, 98, 99,100} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 85, 86, 87, 88} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {101,102,103,104} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {105,106,107,108} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {109,110,111,112} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {117,118,119,120} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Down->Up]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA2 +unsigned cypress_ga2_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +struct inv_ioexp_layout_s cypress_ga2_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_ga2_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 11, 0, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 2} }, + { 1, 10, 0, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 1} }, + { 2, 13, 0, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 4} }, + { 3, 12, 0, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 3} }, + { 4, 15, 0, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 6} }, + { 5, 14, 0, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 5} }, + { 6, 17, 0, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 8} }, + { 7, 16, 0, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 7} }, + { 8, 19, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 10} }, + { 9, 18, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 9} }, + {10, 21, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 12} }, + {11, 20, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 11} }, + {12, 23, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 22} }, + {13, 22, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 21} }, + {14, 25, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 24} }, + {15, 24, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 23} }, + {16, 27, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 34} }, + {17, 26, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 33} }, + {18, 29, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 36} }, + {19, 28, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 35} }, + {20, 31, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 38} }, + {21, 30, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 37} }, + {22, 33, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 40} }, + {23, 32, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 39} }, + {24, 35, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 42} }, + {25, 34, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 41} }, + {26, 37, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 44} }, + {27, 36, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 43} }, + {28, 39, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 50} }, + {29, 38, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 49} }, + {30, 41, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 52} }, + {31, 40, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 51} }, + {32, 43, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 54} }, + {33, 42, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 53} }, + {34, 45, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 56} }, + {35, 44, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 55} }, + {36, 47, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 66} }, + {37, 46, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 65} }, + {38, 49, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 68} }, + {39, 48, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 67} }, + {40, 51, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 70} }, + {41, 50, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 69} }, + {42, 53, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 72} }, + {43, 52, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 71} }, + {44, 55, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 82} }, + {45, 54, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 81} }, + {46, 57, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 84} }, + {47, 56, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 83} }, + {48, 59, 6, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 85, 86, 87, 88} }, + {49, 58, 6, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 97, 98, 99,100} }, + {50, 61, 6, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {105,106,107,108} }, + {51, 60, 6, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {101,102,103,104} }, + {52, 63, 6, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {117,118,119,120} }, + {53, 62, 6, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (C1 version) + * ========================================== + */ +#ifdef SWPS_CYPRESS_BAI +unsigned cypress_b_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +struct inv_ioexp_layout_s cypress_b_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_b_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 2} }, + { 2, 10, 0, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 1} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 4} }, + { 4, 12, 0, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 3} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 6} }, + { 6, 14, 0, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 5} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 8} }, + { 8, 16, 0, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 7} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 10} }, + {10, 18, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 9} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 12} }, + {12, 20, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 11} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 22} }, + {14, 22, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 21} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 24} }, + {16, 24, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 23} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 34} }, + {18, 26, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 33} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 36} }, + {20, 28, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 35} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 38} }, + {22, 30, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 37} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 40} }, + {24, 32, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 39} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 42} }, + {26, 34, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 41} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 44} }, + {28, 36, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 43} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 50} }, + {30, 38, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 49} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 52} }, + {32, 40, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 51} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 54} }, + {34, 42, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 53} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 56} }, + {36, 44, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 55} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 66} }, + {38, 46, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 65} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 68} }, + {40, 48, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 67} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 70} }, + {42, 50, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 69} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 72} }, + {44, 52, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 71} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 82} }, + {46, 54, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 81} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 84} }, + {48, 56, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 83} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 85, 86, 87, 88} }, + {50, 58, 6, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {105,106,107,108} }, + {52, 60, 6, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {101,102,103,104} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {117,118,119,120} }, + {54, 62, 6, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood_fsl Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD_FSL +unsigned redwood_fsl_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; + +struct inv_ioexp_layout_s redwood_fsl_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, +}; + + +struct inv_port_layout_s redwood_fsl_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 1, 2, 3, 4} }, + { 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 5, 6, 7, 8} }, + { 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 9, 10, 11, 12} }, + { 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 13, 14, 15, 16} }, + { 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 17, 18, 19, 20} }, + { 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 21, 22, 23, 24} }, + { 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 25, 26, 27, 28} }, + { 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 29, 30, 31, 32} }, + { 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 33, 34, 35, 36} }, + { 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 37, 38, 39, 40} }, + {10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 41, 42, 43, 44} }, + {11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 45, 46, 47, 48} }, + {12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 49, 50, 51, 52} }, + {13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 53, 54, 55, 56} }, + {14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 57, 58, 59, 60} }, + {15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 61, 62, 63, 64} }, + {16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 65, 66, 67, 68} }, + {17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 69, 70, 71, 72} }, + {18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 73, 74, 75, 76} }, + {19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 77, 78, 79, 80} }, + {20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 81, 82, 83, 84} }, + {21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 85, 86, 87, 88} }, + {22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 89, 90, 91, 92} }, + {23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 93, 94, 95, 96} }, + {24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 97, 98, 99,100} }, + {25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {101,102,103,104} }, + {26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {105,106,107,108} }, + {27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {109,110,111,112} }, + {28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {113,114,115,116} }, + {29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {117,118,119,120} }, + {30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {121,122,123,124} }, + {31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Tahoe Layout configuration + * ========================================== + */ +#ifdef SWPS_TAHOE +unsigned tahoe_gpio_rest_mux = MUX_RST_GPIO_249_PCA9548; + +struct inv_ioexp_layout_s tahoe_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_TAHOE_6ABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {1, IOEXP_TYPE_TAHOE_5A, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[0] = I/O Expander 5 A */ + }, +}; + + +struct inv_port_layout_s tahoe_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 12, 1, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 65, 66, 67, 68} }, + { 1, 11, 1, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 53, 54, 55, 56} }, + { 2, 22, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 69, 70, 71, 72} }, + { 3, 21, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 81, 82, 83, 84} }, + { 4, 24, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 97, 98, 99, 100} }, + { 5, 23, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 85, 86, 87, 88} }, + { 6, 18, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {101, 102, 103, 104} }, + { 7, 17, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {105, 106, 107, 108} }, + { 8, 20, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {113, 114, 115, 116} }, + { 9, 19, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {109, 110, 111, 112} }, +}; +#endif + + +/* ========================================== + * Sequoia Layout configuration + * ========================================== + */ +#ifdef SWPS_SEQUOIA +unsigned sequoia_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; + +struct inv_ioexp_layout_s sequoia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { {1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + +struct inv_port_layout_s sequoia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 9, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 9, 10, 11, 12} }, + { 1, 10, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 1, 2, 3, 4} }, + { 2, 11, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 25, 26, 27, 28} }, + { 3, 12, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 17, 18, 19, 20} }, + { 4, 13, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 41, 42, 43, 44} }, + { 5, 14, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 33, 34, 35, 36} }, + { 6, 15, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 57, 58, 59, 60} }, + { 7, 16, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 49, 50, 51, 52} }, + { 8, 17, 1, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 73, 74, 75, 76} }, + { 9, 18, 1, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 65, 66, 67, 68} }, + {10, 19, 1, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 89, 90, 91, 92} }, + {11, 20, 1, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 81, 82, 83, 84} }, + {12, 21, 1, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {105, 106, 107, 108} }, + {13, 22, 1, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 97, 98, 99, 100} }, + {14, 23, 1, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {121, 122, 123, 124} }, + {15, 24, 1, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {113, 114, 115, 116} }, + {16, 25, 2, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {137, 138, 139, 140} }, + {17, 26, 2, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {129, 130, 131, 132} }, + {18, 27, 2, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {153, 154, 155, 156} }, + {19, 28, 2, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {145, 146, 147, 148} }, + {20, 29, 2, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {169, 170, 171, 172} }, + {21, 30, 2, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {161, 162, 163, 164} }, + {22, 31, 2, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {185, 186, 187, 188} }, + {23, 32, 2, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {177, 178, 179, 180} }, + {24, 33, 3, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {201, 202, 203, 204} }, + {25, 34, 3, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {193, 194, 195, 196} }, + {26, 35, 3, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {217, 218, 219, 220} }, + {27, 36, 3, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {209, 210, 211, 212} }, + {28, 37, 3, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {233, 234, 235, 236} }, + {29, 38, 3, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {225, 226, 227, 228} }, + {30, 39, 3, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {249, 250, 251, 252} }, + {31, 40, 3, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {241, 242, 243, 244} }, + {32, 44, 4, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 13, 14, 15, 16} }, + {33, 43, 4, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 5, 6, 7, 8} }, + {34, 42, 4, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 29, 30, 31, 32} }, + {35, 41, 4, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 21, 22, 23, 24} }, + {36, 48, 4, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 45, 46, 47, 48} }, + {37, 47, 4, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 37, 38, 39, 40} }, + {38, 46, 4, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 61, 62, 63, 64} }, + {39, 45, 4, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 53, 54, 55, 56} }, + {40, 52, 5, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 77, 78, 79, 80} }, + {41, 51, 5, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 69, 70, 71, 72} }, + {42, 50, 5, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 93, 94, 95, 96} }, + {43, 49, 5, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, { 85, 86, 87, 88} }, + {44, 56, 5, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {109, 110, 111, 112} }, + {45, 55, 5, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {101, 102, 103, 104} }, + {46, 54, 5, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {125, 126, 127, 128} }, + {47, 53, 5, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {117, 118, 119, 120} }, + {48, 60, 6, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {141, 142, 143, 144} }, + {49, 59, 6, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {133, 134, 135, 136} }, + {50, 58, 6, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {157, 158, 159, 160} }, + {51, 57, 6, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {149, 150, 151, 152} }, + {52, 64, 6, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {173, 174, 175, 176} }, + {53, 63, 6, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {165, 166, 167, 168} }, + {54, 62, 6, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {189, 190, 191, 192} }, + {55, 61, 6, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {181, 182, 183, 184} }, + {56, 68, 7, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {205, 206, 207, 208} }, + {57, 67, 7, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {197, 198, 199, 200} }, + {58, 66, 7, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {221, 222, 223, 224} }, + {59, 65, 7, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {213, 214, 215, 216} }, + {60, 72, 7, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {237, 238, 239, 240} }, + {61, 71, 7, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {229, 230, 231, 232} }, + {62, 70, 7, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {253, 254, 255, 256} }, + {63, 69, 7, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_REDWOOD, {245, 246, 247, 248} }, +}; +#endif + + +/* ========================================== + * Lavender Layout configuration + * ========================================== + */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; +#endif + +#ifdef SWPS_LAVENDER +struct inv_ioexp_layout_s lavender_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { { 1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + { 1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { { 2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + { 2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + { 2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { { 3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + { 3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + { 3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { { 4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + { 4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + { 4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, + {8, IOEXP_TYPE_LAVENDER_P65, { { 5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xF6, 0xff}, {0xF8, 0xff}, }, }, /* addr[0] = I/O Expander CPU */ + }, +}; + + +struct inv_port_layout_s lavender_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 17, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {188, 189, 190, 191} }, + { 1, 18, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {184, 185, 186, 187} }, + { 2, 19, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {180, 181, 182, 183} }, + { 3, 20, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {176, 177, 178, 179} }, + { 4, 21, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {172, 173, 174, 175} }, + { 5, 22, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {168, 169, 170, 171} }, + { 6, 23, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {164, 165, 166, 167} }, + { 7, 24, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {160, 161, 162, 163} }, + { 8, 25, 1, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {156, 157, 158, 159} }, + { 9, 26, 1, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {152, 153, 154, 155} }, + {10, 27, 1, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {148, 149, 150, 151} }, + {11, 28, 1, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {144, 145, 146, 147} }, + {12, 29, 1, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {140, 141, 142, 143} }, + {13, 30, 1, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {136, 137, 138, 139} }, + {14, 31, 1, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {132, 133, 134, 135} }, + {15, 32, 1, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {128, 129, 130, 131} }, + {16, 33, 2, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 0, 1, 2, 3} }, + {17, 34, 2, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 4, 5, 6, 7} }, + {18, 35, 2, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 8, 9, 10, 11} }, + {19, 36, 2, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 12, 13, 14, 15} }, + {20, 37, 2, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 16, 17, 18, 19} }, + {21, 38, 2, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 20, 21, 22, 23} }, + {22, 39, 2, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 24, 25, 26, 27} }, + {23, 40, 2, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 28, 29, 30, 31} }, + {24, 41, 3, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 32, 33, 34, 35} }, + {25, 42, 3, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 36, 37, 38, 39} }, + {26, 43, 3, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 40, 41, 42, 43} }, + {27, 44, 3, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 44, 45, 46, 47} }, + {28, 45, 3, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 48, 49, 50, 51} }, + {29, 46, 3, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 52, 53, 54, 55} }, + {30, 47, 3, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 56, 57, 58, 59} }, + {31, 48, 3, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 60, 61, 62, 63} }, + {32, 49, 4, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {256, 257, 258, 259} }, + {33, 50, 4, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {260, 261, 262, 263} }, + {34, 51, 4, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {264, 265, 266, 267} }, + {35, 52, 4, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {268, 269, 270, 271} }, + {36, 53, 4, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {272, 273, 274, 275} }, + {37, 54, 4, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {276, 277, 278, 279} }, + {38, 55, 4, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {280, 281, 282, 283} }, + {39, 56, 4, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {284, 285, 286, 287} }, + {40, 57, 5, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {288, 289, 290, 291} }, + {41, 58, 5, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {292, 293, 294, 295} }, + {42, 59, 5, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {296, 297, 298, 299} }, + {43, 60, 5, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {300, 301, 302, 303} }, + {44, 61, 5, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {304, 305, 306, 307} }, + {45, 62, 5, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {308, 309, 310, 311} }, + {46, 63, 5, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {312, 313, 314, 315} }, + {47, 64, 5, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {316, 317, 318, 319} }, + {48, 65, 6, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {444, 445, 446, 447} }, + {49, 66, 6, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {440, 441, 442, 443} }, + {50, 67, 6, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {436, 437, 438, 439} }, + {51, 68, 6, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {432, 433, 434, 435} }, + {52, 69, 6, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {428, 429, 430, 431} }, + {53, 70, 6, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {424, 425, 426, 427} }, + {54, 71, 6, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {420, 421, 422, 423} }, + {55, 72, 6, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {416, 417, 418, 419} }, + {56, 73, 7, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {412, 413, 414, 415} }, + {57, 74, 7, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {408, 409, 410, 411} }, + {58, 75, 7, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {404, 405, 406, 407} }, + {59, 76, 7, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {400, 401, 402, 403} }, + {60, 77, 7, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {396, 397, 398, 399} }, + {61, 78, 7, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {392, 393, 394, 395} }, + {62, 79, 7, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {388, 389, 390, 391} }, + {63, 80, 7, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {384, 385, 386, 387} }, + {64, 5, 8, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 64, 65, 66, 67} }, +}; +#endif + +/* =========================================================== + * Cottonwood Layout configuration Rangeley (Rangeley CPU board) + * =========================================================== + */ +#ifdef SWPS_COTTONWOOD_RANGELEY +unsigned cottonwood_rangeley_gpio_rest_mux = MUX_RST_GPIO_500_PCA9548; + +struct inv_ioexp_layout_s cottonwood_rangeley_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, CPLD_TYPE_COTTONWOOD,{ {1, 0x55, {22, 23, 24, 25}, {22, 23, 24, 25}, {-1, -1, -1, -1}, {0xee, 0xee, 0x99, 0x99}, {0x00, 0x00, 0x00, 0x00}, }, + }, + }, +}; + + +struct inv_port_layout_s cottonwood_rangeley_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 2, 0, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 75} }, + { 1, 3, 0, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 77} }, + { 2, 4, 0, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 79} }, + { 3, 5, 0, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_REDWOOD, { 81} }, +}; +#endif + +/* =========================================================== + * Maple Layout configuration (Old) + * =========================================================== + */ +#ifdef SWPS_MAPLE_GA +unsigned maple_ga_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; + +struct inv_ioexp_layout_s maple_ga_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAPLE_0ABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_MAPLE_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_MAPLE_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_MAPLE_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_MAPLE_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_MAPLE_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_MAPLE_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s maple_ga_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 18, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 1} }, + { 1, 19, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 2} }, + { 2, 20, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 3} }, + { 3, 21, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 4} }, + { 4, 22, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 5} }, + { 5, 23, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 6} }, + { 6, 24, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 7} }, + { 7, 25, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 8} }, + { 8, 26, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 13} }, + { 9, 27, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 14} }, + {10, 28, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 15} }, + {11, 29, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 16} }, + {12, 30, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 21} }, + {13, 31, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 22} }, + {14, 32, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 23} }, + {15, 33, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 24} }, + {16, 34, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 29} }, + {17, 35, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 30} }, + {18, 36, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 31} }, + {19, 37, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 32} }, + {20, 38, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 33} }, + {21, 39, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 34} }, + {22, 40, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 35} }, + {23, 41, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 36} }, + {24, 42, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 41} }, + {25, 43, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 42} }, + {26, 44, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 43} }, + {27, 45, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 44} }, + {28, 46, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 49} }, + {29, 47, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 50} }, + {30, 48, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 51} }, + {31, 49, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 52} }, + {32, 50, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 57} }, + {33, 51, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 58} }, + {34, 52, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 59} }, + {35, 53, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 60} }, + {36, 54, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 61} }, + {37, 55, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 62} }, + {38, 56, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 63} }, + {39, 57, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 64} }, + {40, 58, 6, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 65} }, + {41, 59, 6, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 66} }, + {42, 60, 6, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 67} }, + {43, 61, 6, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 68} }, + {44, 62, 6, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 69} }, + {45, 63, 6, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 70} }, + {46, 64, 6, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 71} }, + {47, 65, 6, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 72} }, + {48, 10, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 77, 78, 79, 80} }, + {49, 11, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 85, 86, 87, 88} }, + {50, 12, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 93, 94, 95, 96} }, + {51, 13, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 97, 98, 99,100} }, + {52, 14, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {105,106,107,108} }, + {53, 15, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {113,114,115,116} }, + {54, 16, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {121,122,123,124} }, + {55, 17, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {125,126,127,128} }, +}; +#endif + +/* =========================================================== + * Maple Layout configuration (B version) + * =========================================================== + */ +#ifdef SWPS_MAPLE_B +unsigned maple_b_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; + +struct inv_ioexp_layout_s maple_b_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAPLE_0ABC, { { 6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + { 6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_MAPLE_NABC, { { 7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_MAPLE_NABC, { { 8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_MAPLE_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_MAPLE_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_MAPLE_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_MAPLE_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s maple_b_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 1, 23, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 2} }, + { 2, 22, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 1} }, + { 3, 25, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 4} }, + { 4, 24, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 3} }, + { 5, 27, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 6} }, + { 6, 26, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 5} }, + { 7, 29, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 8} }, + { 8, 28, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 7} }, + { 9, 31, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 14} }, + {10, 30, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 13} }, + {11, 33, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 16} }, + {12, 32, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 15} }, + {13, 35, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 22} }, + {14, 34, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 21} }, + {15, 37, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 24} }, + {16, 36, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 23} }, + {17, 39, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 30} }, + {18, 38, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 29} }, + {19, 41, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 32} }, + {20, 40, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 31} }, + {21, 43, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 34} }, + {22, 42, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 33} }, + {23, 45, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 36} }, + {24, 44, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 35} }, + {25, 47, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 42} }, + {26, 46, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 41} }, + {27, 49, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 44} }, + {28, 48, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 43} }, + {29, 51, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 50} }, + {30, 50, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 49} }, + {31, 53, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 52} }, + {32, 52, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 51} }, + {33, 55, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 58} }, + {34, 54, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 57} }, + {35, 57, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 60} }, + {36, 56, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 59} }, + {37, 59, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 62} }, + {38, 58, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 61} }, + {39, 61, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 64} }, + {40, 60, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 63} }, + {41, 63, 6, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 66} }, + {42, 62, 6, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 65} }, + {43, 65, 6, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 68} }, + {44, 64, 6, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 67} }, + {45, 67, 6, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 70} }, + {46, 66, 6, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 69} }, + {47, 69, 6, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 72} }, + {48, 68, 6, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 71} }, + {49, 15, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 77, 78, 79, 80} }, + {50, 14, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 85, 86, 87, 88} }, + {51, 17, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 97, 98, 99,100} }, + {52, 16, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 93, 94, 95, 96} }, + {53, 19, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {105,106,107,108} }, + {54, 18, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {113,114,115,116} }, + {55, 21, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {125,126,127,128} }, + {56, 20, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {121,122,123,124} }, +}; +#endif + +/* =========================================================== + * Maple Layout configuration (J version) + * =========================================================== + */ +#ifdef SWPS_MAPLE_J +unsigned maple_j_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; + +struct inv_ioexp_layout_s maple_j_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAPLE_0ABC, { { 6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + { 6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_MAPLE_NABC, { { 7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_MAPLE_NABC, { { 8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_MAPLE_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_MAPLE_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_MAPLE_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_MAPLE_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s maple_j_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 22, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 1} }, + { 1, 23, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 2} }, + { 2, 24, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 3} }, + { 3, 25, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 4} }, + { 4, 26, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 5} }, + { 5, 27, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 6} }, + { 6, 28, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 7} }, + { 7, 29, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 8} }, + { 8, 30, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 13} }, + { 9, 31, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 14} }, + {10, 32, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 15} }, + {11, 33, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 16} }, + {12, 34, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 21} }, + {13, 35, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 22} }, + {14, 36, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 23} }, + {15, 37, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 24} }, + {16, 38, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 29} }, + {17, 39, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 30} }, + {18, 40, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 31} }, + {19, 41, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 32} }, + {20, 42, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 33} }, + {21, 43, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 34} }, + {22, 44, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 35} }, + {23, 45, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 36} }, + {24, 46, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 41} }, + {25, 47, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 42} }, + {26, 48, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 43} }, + {27, 49, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 44} }, + {28, 50, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 49} }, + {29, 51, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 50} }, + {30, 52, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 51} }, + {31, 53, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 52} }, + {32, 54, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 57} }, + {33, 55, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 58} }, + {34, 56, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 59} }, + {35, 57, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 60} }, + {36, 58, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 61} }, + {37, 59, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 62} }, + {38, 60, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 63} }, + {39, 61, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 64} }, + {40, 62, 6, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 65} }, + {41, 63, 6, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 66} }, + {42, 64, 6, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 67} }, + {43, 65, 6, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 68} }, + {44, 66, 6, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 69} }, + {45, 67, 6, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 70} }, + {46, 68, 6, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 71} }, + {47, 69, 6, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 72} }, + {48, 14, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 85, 86, 87, 88} }, + {49, 15, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 77, 78, 79, 80} }, + {50, 16, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 93, 94, 95, 96} }, + {51, 17, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 97, 98, 99,100} }, + {52, 18, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {113,114,115,116} }, + {53, 19, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {105,106,107,108} }, + {54, 20, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {121,122,123,124} }, + {55, 21, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, {125,126,127,128} }, +}; +#endif + +/* ========================================== + * Gulmohar Layout configuration + * ========================================== + */ +#ifdef SWPS_GULMOHAR +unsigned gulmohar_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; + +struct inv_ioexp_layout_s gulmohar_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_GULMOHAR_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_GULMOHAR_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_GULMOHAR_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_GULMOHAR_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_GULMOHAR_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_GULMOHAR_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_GULMOHAR_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + + +struct inv_port_layout_s gulmohar_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 1} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 2} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 3} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 4} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 5} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 6} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 7} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 8} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 9} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 10} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 11} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 12} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 21} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 22} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 23} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 24} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 33} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 34} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 35} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 36} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 37} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 38} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 39} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 40} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 41} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 42} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 43} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 44} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 49} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 50} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 51} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 52} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 53} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 54} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 55} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 56} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 65} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 66} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 67} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 68} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 69} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 70} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 71} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 72} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 81} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 82} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 83} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, { 84} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 97, 98, 99,100} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, { 85, 86, 87, 88} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {101,102,103,104} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {105,106,107,108} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {109,110,111,112} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Gulmohar_2T EVT1 Layout configuration + * ========================================== + */ +#ifdef SWPS_GULMOHAR_2T_EVT1 +unsigned gulmohar_2t_evt1_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; + +struct inv_ioexp_layout_s gulmohar_2t_evt1_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC,{ {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC,{ {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC,{ {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xd6, 0xda}, {0x18, 0xe3}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xd6, 0xda}, {0x18, 0xe3}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xd6, 0xff}, {0x18, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + + +struct inv_port_layout_s gulmohar_2t_evt1_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_LAVENDER, {-99} }, + {48, 59, 6, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {-99,-99,-99,-99} }, + {49, 58, 6, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {-99,-99,-99,-99} }, + {50, 61, 6, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {-99,-99,-99,-99} }, + {51, 60, 6, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {-99,-99,-99,-99} }, + {52, 63, 6, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {-99,-99,-99,-99} }, + {53, 62, 6, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {-99,-99,-99,-99} }, + {54, 65, 6, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {-99,-99,-99,-99} }, + {55, 64, 6, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_LAVENDER, {-99,-99,-99,-99} }, +}; +#endif + + +/* =========================================================== + * Peony-SFP Layout configuration + * =========================================================== + */ +#ifdef SWPS_PEONY_SFP +unsigned peony_sfp_gpio_rest_mux = MUX_RST_CPLD_C0_A77_70_74_RST_ALL; + +struct inv_ioexp_layout_s peony_sfp_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_QSFP_6P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 0 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s peony_sfp_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 20, 1, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 1} }, + { 1, 21, 1, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 2} }, + { 2, 22, 1, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 3} }, + { 3, 23, 1, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 4} }, + { 4, 24, 1, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 5} }, + { 5, 25, 1, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 6} }, + { 6, 26, 1, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 7} }, + { 7, 27, 1, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 8} }, + { 8, 28, 2, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 13} }, + { 9, 29, 2, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 14} }, + {10, 30, 2, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 15} }, + {11, 31, 2, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 16} }, + {12, 32, 2, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 21} }, + {13, 33, 2, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 22} }, + {14, 34, 2, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 23} }, + {15, 35, 2, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 24} }, + {16, 36, 3, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 29} }, + {17, 37, 3, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 30} }, + {18, 38, 3, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 31} }, + {19, 39, 3, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 32} }, + {20, 40, 3, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 33} }, + {21, 41, 3, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 34} }, + {22, 42, 3, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 35} }, + {23, 43, 3, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 36} }, + {24, 44, 4, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 65} }, + {25, 45, 4, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 66} }, + {26, 46, 4, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 67} }, + {27, 47, 4, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 68} }, + {28, 48, 4, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 69} }, + {29, 49, 4, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 70} }, + {30, 50, 4, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 71} }, + {31, 51, 4, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 72} }, + {32, 52, 5, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 97} }, + {33, 53, 5, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 98} }, + {34, 54, 5, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, { 99} }, + {35, 55, 5, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {100} }, + {36, 56, 5, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {105} }, + {37, 57, 5, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {106} }, + {38, 58, 5, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {107} }, + {39, 59, 5, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {108} }, + {40, 60, 6, 0, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {113} }, + {41, 61, 6, 1, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {114} }, + {42, 62, 6, 2, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {115} }, + {43, 63, 6, 3, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {116} }, + {44, 64, 6, 4, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {121} }, + {45, 65, 6, 5, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {122} }, + {46, 66, 6, 6, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {123} }, + {47, 67, 6, 7, TRANSVR_TYPE_SFP, CHIP_TYPE_MAPLE, {124} }, + {48, 12, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 49, 50, 51, 52} }, + {49, 13, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 57, 58, 59, 60} }, + {50, 14, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 61, 62, 63, 64} }, + {51, 15, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 77, 78, 79, 80} }, + {52, 16, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 85, 86, 87, 88} }, + {53, 17, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 93, 94, 95, 96} }, +}; +#endif + + +/* =========================================================== + * Peony-Copper Layout configuration + * =========================================================== + */ +#ifdef SWPS_PEONY_COPPER +unsigned peony_copper_gpio_rest_mux = MUX_RST_CPLD_C0_A77_70_74_RST_ALL; + +struct inv_ioexp_layout_s peony_copper_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_QSFP_6P_LAYOUT_1, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 0 A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, +}; + +struct inv_port_layout_s peony_copper_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + {48, 4, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 49, 50, 51, 52} }, + {49, 5, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 57, 58, 59, 60} }, + {50, 6, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 61, 62, 63, 64} }, + {51, 7, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 77, 78, 79, 80} }, + {52, 8, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 85, 86, 87, 88} }, + {53, 9, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 93, 94, 95, 96} }, +}; +#endif + + +/* =========================================================== + * Cedar Layout configuration + * =========================================================== + */ +#ifdef SWPS_CEDAR_GA +unsigned cedar_ga_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; + +struct inv_ioexp_layout_s cedar_ga_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_CEDAR_0ABC, { { 4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 4, 0x21, {0,-1}, {1,-1}, {3,-1}, {0xff }, {0x00 }, }, /* addr[1] = I/O Expander 0 B */ + { 4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_CEDAR_0ABC, { { 5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 5, 0x21, {0,-1}, {1,-1}, {3,-1}, {0xff }, {0x00 }, }, /* addr[1] = I/O Expander 0 B */ + { 5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {2, IOEXP_TYPE_CEDAR_0ABC, { { 6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 6, 0x21, {0,-1}, {1,-1}, {3,-1}, {0xff }, {0x00 }, }, /* addr[1] = I/O Expander 0 B */ + { 6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {3, IOEXP_TYPE_CEDAR_0ABC, { { 7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 7, 0x21, {0,-1}, {1,-1}, {3,-1}, {0xff }, {0x00 }, }, /* addr[1] = I/O Expander 0 B */ + { 7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, +}; + +struct inv_port_layout_s cedar_ga_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / CHIP_TYPE / LANE_ID */ + { 0, 12, 0, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 21, 22, 23, 24} }, + { 1, 13, 0, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 17, 18, 19, 20} }, + { 2, 14, 0, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 25, 26, 27, 28} }, + { 3, 15, 0, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 29, 30, 31, 32} }, + { 4, 16, 0, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 37, 38, 39, 40} }, + { 5, 17, 0, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 33, 34, 35, 36} }, + { 6, 18, 0, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 41, 42, 43, 44} }, + { 7, 19, 0, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 45, 46, 47, 48} }, + { 8, 20, 1, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 5, 6, 7, 8} }, + { 9, 21, 1, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 1, 2, 3, 4} }, + {10, 22, 1, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 9, 10, 11, 12} }, + {11, 23, 1, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 13, 14, 15, 16} }, + {12, 24, 1, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 53, 54, 55, 56} }, + {13, 25, 1, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 49, 50, 51, 52} }, + {14, 26, 1, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 57, 58, 59, 60} }, + {15, 27, 1, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 61, 62, 63, 64} }, + {16, 28, 2, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 71, 72, 73, 74} }, + {17, 29, 2, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 67, 68, 69, 70} }, + {18, 30, 2, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 75, 76, 77, 78} }, + {19, 31, 2, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 79, 80, 81, 82} }, + {20, 32, 2, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 119, 120, 121, 122} }, + {21, 33, 2, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 115, 116, 117, 118} }, + {22, 34, 2, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 123, 124, 125, 126} }, + {23, 35, 2, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 127, 128, 129, 130} }, + {24, 36, 3, 0, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 87, 88, 89, 90} }, + {25, 37, 3, 1, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 83, 84, 85, 86} }, + {26, 38, 3, 2, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 91, 92, 93, 94} }, + {27, 39, 3, 3, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 95, 96, 97, 98} }, + {28, 40, 3, 4, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 103, 104, 105, 106} }, + {29, 41, 3, 5, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 99, 100, 101, 102} }, + {30, 42, 3, 6, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 107, 108, 109, 110} }, + {31, 43, 3, 7, TRANSVR_TYPE_QSFP_28, CHIP_TYPE_MAPLE, { 111, 112, 113, 114} }, +}; +#endif + + +#endif /* INV_SWPS_H */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/io_expander.c new file mode 100644 index 000000000000..6867bbc6030e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/io_expander.c @@ -0,0 +1,2579 @@ +#include +#include +#include "io_expander.h" + +/* For build single module using (Ex: ONL platform) */ +#include +//#include + + +static struct ioexp_obj_s *ioexp_head_p = NULL; +static struct ioexp_obj_s *ioexp_tail_p = NULL; +extern int io_no_init; + +/* ========== Register IOEXP layout ========== + */ +struct ioexp_map_s ioexp_map_magnolia_nab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_magnolia_4ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_magnolia_7ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {1, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {1, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {1, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 2}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 3}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 0, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 0, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 0, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 0, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 0, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 0, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 0, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 1, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 1, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 1, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 1, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 1, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 1, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 1, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_cypress_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_cypress_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 1, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 1, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 1, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {0, 1, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {0, 1, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {1, 1, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {1, 1, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {1, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {1, 1, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_5a = { + + .chip_amount = 1, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_6abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 0}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 3}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 0}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + {2, 1, 5}, /* map_present[8] = MOD_ABS_PORT(X+8) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + {2, 1, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + {2, 1, 4}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+8) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + {2, 1, 2}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_sequoia_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_lavender_p65 = { + + .chip_amount = 1, + .data_width = 1, + + .map_present = { {0, 0, 4}, }, /* map_present[0] = MOD_ABS_PORT(X) */ + .map_reset = { {0, 0, 1}, }, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + .map_lpmod = { {0, 0, 2}, }, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + .map_modsel = { {0, 0, 0}, }, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ +}; + + +struct ioexp_map_s cpld_map_cottonwood = { + + .chip_amount = 1, + .data_width = 4, + + .map_present = { {0, 2, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 2, 4}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 3, 0}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 3, 4}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + }, + .map_tx_disable = { {0, 0, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 4}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 4}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + }, + .map_tx_fault = { {0, 2, 2}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 2, 6}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 3, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 3, 6}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + }, + .map_rxlos = { {0, 2, 1}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 2, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 3, 1}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 3, 5}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + }, + .map_hard_rs0 = { {0, 0, 2}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {0, 0, 6}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {0, 1, 2}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {0, 1, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + }, + .map_hard_rs1 = { {0, 0, 2}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {0, 0, 6}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {0, 1, 2}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {0, 1, 6}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + }, +}; + + +struct ioexp_map_s ioexp_map_maple_0abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_maple_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 4}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 5}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 4}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 5}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 2}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 3}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 2}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 3}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 1}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 1}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 6}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 6}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 2}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 6}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 6}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 2}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 6}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 2}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 6}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 1}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 5}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 1}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 5}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 1}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 5}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 1}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 5}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 4}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 4}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 4}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 4}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 3}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 3}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 3}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 3}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_1abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 2}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 6}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 6}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 4}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 5}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 1}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 5}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 1}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 5}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 2}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 3}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 4}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 4}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 1}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 3}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 3}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 6}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_3abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 4}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 5}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 2}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 6}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 2}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 6}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 2}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 3}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 1}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 5}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 1}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 5}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 1}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 4}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 4}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 6}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 3}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 3}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 4}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 1}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 6}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 4}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 1}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP_N_P(X+7) */ + }, +}; + + +/* PortType: SFP / 8 port + * Platform: Cypress, Peony_SFP + */ +struct ioexp_map_s ioexp_map_sfp_8p_layout_1 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +/* PortType: QSFP / 6 port + * Platform: Gulmohar, Peony_SFP, Peony_Copper + */ +struct ioexp_map_s ioexp_map_6p_qsfp_type_1 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +/* ========== Private functions ========== + */ +int check_channel_tier_1(void); + +struct i2c_client * +_get_i2c_client(struct ioexp_obj_s *self, + int chip_id){ + + struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p; + + if (!(i2c_curr_p)){ + SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__); + return NULL; + } + while (i2c_curr_p){ + if ((i2c_curr_p->chip_id) == chip_id){ + return i2c_curr_p->i2c_client_p; + } + i2c_curr_p = i2c_curr_p->next; + } + SWPS_ERR("%s: not exist! :%d\n", __func__, chip_id); + return NULL; +} + + +static int +_common_ioexp_update_one(struct ioexp_obj_s *self, + struct ioexp_addr_s *ioexp_addr, + int chip_id, + int data_width, + int show_err, + char *caller_name) { + int buf = 0; + int err = 0; + int data_id = 0; + int r_offset = 0; + + for(data_id=0; data_idread_offset[data_id]; + if (r_offset < 0) { + SWPS_DEBUG("skip a read_offset <%d>\n", r_offset); + continue; + } + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset); + /* Check error */ + if (buf < 0) { + err = 1; + if (show_err) { + SWPS_INFO("IOEXP-%d read fail! :%d \n", self->ioexp_id, buf); + SWPS_INFO("Dump: :%d :0x%02x :%d, :%s\n", + ioexp_addr->chan_id, ioexp_addr->chip_addr, + ioexp_addr->read_offset[data_id], caller_name); + } + continue; + } + /* Update IOEXP object */ + self->chip_data[chip_id].data[data_id] = (uint8_t)buf; + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +common_ioexp_update_all(struct ioexp_obj_s *self, + int show_err, + char *caller_name){ + + int err = 0; + int chip_id = 0; + int chip_amount = self->ioexp_map_p->chip_amount; + + for (chip_id=0; chip_idioexp_map_p->map_addr[chip_id]), + chip_id, + self->ioexp_map_p->data_width, + show_err, + caller_name) < 0) { + err = 1; + } + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +_common_check_by_mode(struct ioexp_obj_s *self){ + + switch (self->mode){ + case IOEXP_MODE_DIRECT: + return self->fsm_4_direct(self); + + case IOEXP_MODE_POLLING: + if (self->state >= 0){ + return 0; + } + switch (self->state){ + case STATE_IOEXP_INIT: + return ERR_IOEXP_UNINIT; + case STATE_IOEXP_ABNORMAL: + return ERR_IOEXP_ABNORMAL; + default: + return ERR_IOEXP_NOSTATE; + } + break; + + default: + break; + } + SWPS_ERR("%s: Exception occurs. :%d \n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +static int +_common_get_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + char *func_mane){ + uint8_t buf; + int err_code; + + /* Check and get address */ + err_code = _common_check_by_mode(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Get data form cache */ + buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + return (int)(buf >> bitmap_obj_p->bit_shift & 0x01); +} + + +static int +_common_set_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + int input_val, + char *func_mane){ + int err_code, target_offset; + uint8_t origin_byte; + uint8_t modify_byte; + + /* Check and get address */ + err_code = _common_check_by_mode(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Prepare write date */ + origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + switch (input_val) { + case 0: + modify_byte = origin_byte; + SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift); + break; + case 1: + modify_byte = origin_byte; + SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift); + break; + default: + SWPS_ERR("Input value incorrect! :%d :%d :%s\n", + input_val, self->ioexp_id, func_mane); + return ERR_IOEXP_BADINPUT; + } + /* Setup i2c client */ + target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset]; + /* Write byte to chip via I2C */ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id), + target_offset, + modify_byte); + /* Update or bollback object */ + if (err_code < 0){ + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte; + SWPS_ERR("I2C write fail! :%d :%d :%s :%d\n", + input_val, self->ioexp_id, func_mane, err_code); + return err_code; + } + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte; + return 0; +} + + +/* ========== Object public functions ========== + */ +int +common_get_present(struct ioexp_obj_s *self, + int virt_offset){ + + int UNPLUG = 1; + int retval = ERR_IOEXP_UNEXCPT; + + retval = _common_get_bit(self, + &(self->ioexp_map_p->map_present[virt_offset]), + "common_get_present"); + if (retval < 0) { + /* [Note] + * => Transceiver object does not need to handle IOEXP layer issues. + */ + return UNPLUG; + } + return retval; +} + + +int +common_get_tx_fault(struct ioexp_obj_s *self, + int virt_offset){ + /* [Transmit Fault (Tx_Fault)] + * A catastrophic laser fault will activate the transmitter signal, + * TX_FAULT, and disable the laser. This signal is an open collector + * output (pull-up required on the host board). A low signal indicates + * normal laser operation and a high signal indicates a fault. The + * TX_FAULT will be latched high when a laser fault occurs and is + * cleared by toggling the TX_DISABLE input or power cycling the + * transceiver. The transmitter fault condition can also be monitored + * via the two-wire serial interface. + * (address A2, byte 110, bit 2). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_fault[virt_offset]), + "common_get_tx_fault"); +} + + +int +common_get_rxlos(struct ioexp_obj_s *self, + int virt_offset){ + /* [Receiver Loss of Signal (Rx_LOS)] + * The post-amplification IC also includes transition detection circuitry + * which monitors the ac level of incoming optical signals and provides a + * TTL/CMOS compatible status signal to the host (pin 8). An adequate optical + * input results in a low Rx_LOS output while a high Rx_LOS output indicates + * an unusable optical input. The Rx_LOS thresholds are factory set so that + * a high output indicates a definite optical fault has occurred. Rx_LOS can + * also be monitored via the two-wire serial interface + * (address A2h, byte 110, bit 1). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_rxlos[virt_offset]), + "common_get_rxlos"); +} + + +int +common_get_tx_disable(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + "common_get_tx_disable"); +} + + +int +common_get_reset(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + "common_get_reset"); +} + + +int +common_get_lpmod(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + "common_get_lpmod"); +} + + +int +common_get_modsel(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + "common_get_modsel"); +} + + +int +common_get_hard_rs0(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + "common_get_hard_rs0"); +} + + +int +common_get_hard_rs1(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + "common_get_hard_rs1"); +} + + +int +common_set_tx_disable(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + input_val, + "common_set_tx_disable"); +} + + +int +common_set_reset(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + input_val, + "common_set_reset"); +} + + +int +common_set_lpmod(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + input_val, + "common_set_lpmod"); +} + + +int +common_set_modsel(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + input_val, + "common_set_modsel"); +} + + +int +common_set_hard_rs0(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + input_val, + "common_set_hard_rs0"); +} + + +int +common_set_hard_rs1(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + input_val, + "common_set_hard_rs1"); +} + + +int +ioexp_get_not_support(struct ioexp_obj_s *self, + int virt_offset){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +ioexp_set_not_support(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +fake_ioexp_init(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_ioexp_update(struct ioexp_obj_s *self){ + return 1; +} + + +int +fake_update_func(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_get_func(struct ioexp_obj_s *self, + int virt_offset){ + SWPS_WARN("Someone called fake_get_func\n"); + return -1; +} + +int +fake_set_func(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + SWPS_WARN("Someone called fake_set_func\n"); + return -1; +} + + +/* ========== Initial functions for IO Expander ========== + */ +int +common_ioexp_init(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + if (self->mode == IOEXP_MODE_DIRECT) { + goto update_common_ioexp_init; + } + if (!io_no_init) { /*normal init*/ + + /* Setup default value to each physical IO Expander */ + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + /* Get address mapping */ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("%s: IOEXP config incorrect! :%d \n", + __func__, chip_id); + return -1; + } + /* Setup default value */ + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + /* [Desc] Skip the setup default value behavior + [Note] Setup default value = -1 if you don't want to write the value to IOEXP or CPLD + */ + if(addr_p->write_offset[offset] < 0){ + SWPS_DEBUG("skip a write_offset <%d>\n", addr_p->conf_offset[offset]); + continue; + } + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->write_offset[offset], + addr_p->data_default[offset]); + if (err_code < 0){ + SWPS_ERR("%s: set default fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + } + } + } +update_common_ioexp_init: + /* Check and update info to object */ + err_code = self->update_all(self, 1, "common_ioexp_init"); + if (err_code < 0) { + SWPS_ERR("%s: update_all() fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +/* ========== Object functions for Final State Machine ========== + */ +int +_is_channel_ready(struct ioexp_obj_s *self){ + + int chip_id = 0; + int byte_id = 0; + int getval = ERR_IOEXP_UNEXCPT; + int chkval = ERR_IOEXP_UNEXCPT; + char *emsg = "ERR"; + struct ioexp_addr_s *addr_p = NULL; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++) { + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + emsg = "IOEXP config incorrect"; + goto err_is_channel_ready; + } + for (byte_id=0; byte_id<(self->ioexp_map_p->data_width); byte_id++) { + if (addr_p->conf_offset[byte_id] < 0) { + continue; + } + if ((addr_p->conf_default[byte_id]) != 0) { + goto go_is_channel_ready; + } + } + if (chip_id == ((self->ioexp_map_p->chip_amount) - 1)) { + SWPS_DEBUG("%s: no non-zero config", __func__); + break; + } + } + chip_id = 0; + byte_id = 0; + +go_is_channel_ready: + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + chkval = addr_p->conf_default[byte_id]; + getval = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), + addr_p->conf_offset[byte_id]); + + SWPS_DEBUG("%s: target info :%d :%d :%d :%d :%d\n", + __func__, self->ioexp_id, chip_id, byte_id, chkval, getval); + + if ((getval >= 0) && (getval == chkval)) { + return 1; + } + return 0; + +err_is_channel_ready: + SWPS_ERR("%s: %s :%d :%d :%d :%d :%d\n", + __func__, emsg, self->ioexp_id, chip_id, byte_id, chkval, getval); + return ERR_IOEXP_UNEXCPT; +} + + +int +_ioexp_init_handler(struct ioexp_obj_s *self){ + + int return_val; + + switch (self->mode) { + case IOEXP_MODE_DIRECT: + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + + case IOEXP_MODE_POLLING: + /* Check system and channel is ready */ + if (self->state == STATE_IOEXP_INIT){ + if (!_is_channel_ready(self)){ + self->state = STATE_IOEXP_INIT; + SWPS_WARN("%s: IOEXP:%d channel not ready.\n", + __func__, self->ioexp_id); + return 0; + } + } + /* Execute initial callback */ + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + + default: + break; + } + SWPS_ERR("%s: exception occur :%d\n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){ + + int result_val; + int show_err = 1; + char *func_mane = "common_ioexp_fsm_4_direct"; + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, and return error */ + return ERR_IOEXP_UNINIT; + } + /* Case: Initial done */ + return 0; + + case STATE_IOEXP_NORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + SWPS_INFO("%s: NORMAL -> ABNORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + self->state = STATE_IOEXP_NORMAL; + return 0; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_DEBUG("%s: ABNORMAL -> NORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("%s: Exception occurs :%d\n", + __func__, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_polling(struct ioexp_obj_s *self){ + + int result_val, i, show_e; + int fail_retry = 3; + char *func_name = "common_ioexp_fsm_4_polling"; + +#ifdef DEBUG_SWPS + show_e = 1; +#else + show_e = 0; +#endif + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + /* Case: System (Channel) not ready */ + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, wait and retry */ + return 0; + } + /* Case: Initial done */ + SWPS_INFO("IOEXP-%d: initial done. :%d\n", + self->ioexp_id, self->ioexp_type); + return result_val; + + case STATE_IOEXP_NORMAL: + /* Retry mechanism for case of i2c topology not stable */ + for (i=0; iupdate_all(self, show_e, func_name); + if (result_val >= 0) { + self->state = STATE_IOEXP_NORMAL; + return 0; + } + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: detect I2C crash :%d\n", + __func__, self->ioexp_id); + break; + } + SWPS_DEBUG("IOEXP-%d: unstable :%d\n", + self->ioexp_id, result_val); + } + SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_e, func_name); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_INFO("IOEXP-%d: ABNORMAL -> NORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("IOEXP-%d: Exception occurs :%d\n", + self->ioexp_id, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +/* ========== Object private functions for check & update ========== + */ +int +common_ioexp_check(struct ioexp_obj_s *self){ + + int result; + + if (self->mode != IOEXP_MODE_POLLING){ + SWPS_ERR("%s: not polling mode :%d\n", + __func__, self->mode); + return ERR_IOEXP_NOTSUPPORT; + } + mutex_lock(&self->lock); + result = self->fsm_4_polling(self); + mutex_unlock(&self->lock); + return result; +} + + +/* ========== Functions for Factory pattern ========== + */ +static struct ioexp_map_s * +get_ioexp_map(int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + return &ioexp_map_magnolia_nab; + case IOEXP_TYPE_MAGINOLIA_4AB: + return &ioexp_map_magnolia_4ab; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + return &ioexp_map_magnolia_7ab; + case IOEXP_TYPE_REDWOOD_P01P08: + return &ioexp_map_redwood_p01p08_p17p24; + case IOEXP_TYPE_REDWOOD_P09P16: + return &ioexp_map_redwood_p09p16_p25p32; + case IOEXP_TYPE_HUDSON32IGA_P01P08: + return &ioexp_map_hudson32iga_p01p08_p17p24; + case IOEXP_TYPE_HUDSON32IGA_P09P16: + return &ioexp_map_hudson32iga_p09p16_p25p32; + case IOEXP_TYPE_CYPRESS_7ABC: + return &ioexp_map_cypress_7abc; + case IOEXP_TYPE_TAHOE_5A: + return &ioexp_map_tahoe_5a; + case IOEXP_TYPE_TAHOE_6ABC: + return &ioexp_map_tahoe_6abc; + case IOEXP_TYPE_SEQUOIA_NABC: + return &ioexp_map_sequoia_nabc; + case IOEXP_TYPE_LAVENDER_P65: + return &ioexp_map_lavender_p65; + case CPLD_TYPE_COTTONWOOD: + return &cpld_map_cottonwood; + case IOEXP_TYPE_MAPLE_0ABC: + case IOEXP_TYPE_CEDAR_0ABC: + return &ioexp_map_maple_0abc; + case IOEXP_TYPE_MAPLE_NABC: + return &ioexp_map_maple_nabc; + case IOEXP_TYPE_GULMOHAR_NABC: + return &ioexp_map_gulmohar_nabc; + case IOEXP_TYPE_GULMOHAR_7ABC: + return &ioexp_map_gulmohar_7abc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + return &ioexp_map_gulmohar_2t_evt1_nabc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + return &ioexp_map_gulmohar_2t_evt1_1abc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + return &ioexp_map_gulmohar_2t_evt1_3abc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + return &ioexp_map_gulmohar_2t_evt1_7abc; + case IOEXP_TYPE_SFP_8P_LAYOUT_1: + return &ioexp_map_sfp_8p_layout_1; + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: + return &ioexp_map_6p_qsfp_type_1; + default: + return NULL; + } +} + + +int +setup_ioexp_ssize_attr(struct ioexp_obj_s *self, + struct ioexp_map_s *ioexp_map_p, + int ioexp_id, + int ioexp_type, + int run_mode){ + switch (run_mode){ + case IOEXP_MODE_POLLING: /* Direct access device mode */ + case IOEXP_MODE_DIRECT: /* Polling mode, read from cache */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = ERR_IOEXP_UNEXCPT; + return ERR_IOEXP_UNEXCPT; + } + /* Setup mapping structure */ + self->ioexp_map_p = kzalloc(sizeof(*ioexp_map_p), GFP_KERNEL); + if (!(self->ioexp_map_p)) { + SWPS_ERR("%s: kzalloc ioexp_map_p fail\n", __func__); + return -1; + } + memcpy(self->ioexp_map_p, ioexp_map_p, sizeof(*ioexp_map_p)); + /* Setup attributes */ + self->ioexp_id = ioexp_id; + self->ioexp_type = ioexp_type; + self->state = STATE_IOEXP_INIT; + mutex_init(&self->lock); + return 0; +} + + +static int +setup_addr_mapping(struct ioexp_obj_s *self, + struct ioexp_addr_s *addr_map_p, + int chip_amount){ + struct ioexp_addr_s *tmp_p; + if (!addr_map_p){ + SWPS_ERR("%s: map is null\n", __func__); + return -1; + } + tmp_p = kzalloc((sizeof(*addr_map_p) * chip_amount), GFP_KERNEL); + if (!tmp_p){ + SWPS_ERR("%s: kzalloc fail.\n", __func__); + return -1; + } + memcpy(tmp_p, addr_map_p, (sizeof(*addr_map_p) * chip_amount)); + self->ioexp_map_p->map_addr = tmp_p; + + return 0; +} + + +static int +setup_ioexp_public_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case CPLD_TYPE_COTTONWOOD: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + + case IOEXP_TYPE_MAPLE_NABC: + case IOEXP_TYPE_GULMOHAR_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + case IOEXP_TYPE_SFP_8P_LAYOUT_1: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->get_hard_rs0 = common_get_hard_rs0; + self->get_hard_rs1 = common_get_hard_rs1; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + self->set_hard_rs0 = common_set_hard_rs0; + self->set_hard_rs1 = common_set_hard_rs1; + return 0; + + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case IOEXP_TYPE_MAPLE_0ABC: + case IOEXP_TYPE_GULMOHAR_7ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: + case IOEXP_TYPE_CEDAR_0ABC: + self->get_present = common_get_present; + self->get_tx_fault = ioexp_get_not_support; + self->get_rxlos = ioexp_get_not_support; + self->get_tx_disable = ioexp_get_not_support; + self->get_reset = common_get_reset; + self->get_lpmod = common_get_lpmod; + self->get_modsel = common_get_modsel; + self->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + self->set_tx_disable = ioexp_set_not_support; + self->set_reset = common_set_reset; + self->set_lpmod = common_set_lpmod; + self->set_modsel = common_set_modsel; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_ioexp_private_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case CPLD_TYPE_COTTONWOOD: + case IOEXP_TYPE_MAPLE_NABC: + case IOEXP_TYPE_MAPLE_0ABC: + case IOEXP_TYPE_GULMOHAR_NABC: + case IOEXP_TYPE_GULMOHAR_7ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + case IOEXP_TYPE_SFP_8P_LAYOUT_1: + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: + case IOEXP_TYPE_CEDAR_0ABC: + self->init = common_ioexp_init; + self->check = common_ioexp_check; + self->update_all = common_ioexp_update_all; + self->fsm_4_direct = common_ioexp_fsm_4_direct; + self->fsm_4_polling = common_ioexp_fsm_4_polling; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_i2c_client_one(struct ioexp_obj_s *self, + int chip_id){ + + char *err_msg = "ERROR"; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + struct ioexp_i2c_s *i2c_obj_p = NULL; + struct ioexp_i2c_s *i2c_curr_p = NULL; + + int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id; + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + err_msg = "Can not kzalloc client!"; + goto err_ioexp_setup_i2c_1; + } + i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL); + if (!i2c_obj_p){ + err_msg = "Can not kzalloc i2c_obj_p!"; + goto err_ioexp_setup_i2c_2; + } + adap = i2c_get_adapter(chan_id); + if(!adap){ + err_msg = "Can not get adap!"; + goto err_ioexp_setup_i2c_3; + } + client->adapter = adap; + client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr; + i2c_obj_p->i2c_client_p = client; + i2c_obj_p->chip_id = chip_id; + i2c_obj_p->next = NULL; + if (!self->i2c_head_p){ + self->i2c_head_p = i2c_obj_p; + } else { + i2c_curr_p = self->i2c_head_p; + while (i2c_curr_p->next){ + i2c_curr_p = i2c_curr_p->next; + } + i2c_curr_p->next = i2c_obj_p; + } + return 0; + +err_ioexp_setup_i2c_3: + kfree(i2c_obj_p); +err_ioexp_setup_i2c_2: + kfree(client); +err_ioexp_setup_i2c_1: + SWPS_ERR("%s: %s :%d\n", __func__, err_msg, chan_id); + return -1; +} + + +static int +setup_i2c_client(struct ioexp_obj_s* self){ + + int result; + int chip_id = 0; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + result = setup_i2c_client_one(self, chip_id); + if (result < 0){ + SWPS_ERR("%s fail! :%d\n", __func__, chip_id); + return -1; + } + } + return 0; +} + + +static int +setup_ioexp_config(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + if (io_no_init) { + + SWPS_INFO("io_no_init:%d \n", io_no_init); + return 0; + } + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("IOEXP config incorrect! :%d \n",chip_id); + return -1; + } + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + /* [Desc] Skip the setup config value behavior + [Note] Setup config value = -1 if you don't want to write the value to IOEXP or CPLD + */ + if(addr_p->conf_offset[offset] < 0){ + SWPS_DEBUG("skip a config_offset <%d>\n", addr_p->conf_offset[offset]); + continue; + } + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->conf_offset[offset], + addr_p->conf_default[offset]); + + if (err_code < 0){ + SWPS_INFO("%s: set conf fail! :%d \n", __func__, err_code); + return -2; + } + } + } + return 0; +} + + +struct ioexp_obj_s * +_create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_map_s* ioexp_map_p; + struct ioexp_obj_s* result_p; + struct ioexp_i2c_s *i2c_curr_p; + struct ioexp_i2c_s *i2c_next_p; + + /* Get layout */ + ioexp_map_p = get_ioexp_map(ioexp_type); + if (!ioexp_map_p){ + SWPS_ERR("%s: Invalid ioexp_type\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare IOEXP object */ + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + SWPS_ERR("%s: kzalloc failure!\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare static size attributes */ + if (setup_ioexp_ssize_attr(result_p, + ioexp_map_p, + ioexp_id, + ioexp_type, + run_mode) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + /* Prepare address mapping */ + if (setup_addr_mapping(result_p, addr_map_p, ioexp_map_p->chip_amount) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + if (setup_i2c_client(result_p) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + /* Prepare call back functions of object */ + if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + return result_p; + +err_create_ioexp_setup_i2c_fail: + i2c_curr_p = result_p->i2c_head_p; + i2c_next_p = result_p->i2c_head_p; + while (i2c_curr_p){ + i2c_next_p = i2c_curr_p->next; + if (i2c_curr_p->i2c_client_p) { + i2c_put_adapter(i2c_curr_p->i2c_client_p->adapter); + kfree(i2c_curr_p->i2c_client_p); + } + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } +err_create_ioexp_setup_attr_fail: + kfree(result_p); +err_create_ioexp_fail: + SWPS_ERR("%s: fail! :%d :%d \n", + __func__, ioexp_id, ioexp_type); + return NULL; +} + + +int +create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_obj_s *ioexp_p = NULL; + + ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type, + addr_map_p, run_mode); + if (!ioexp_p){ + return -1; + } + if (ioexp_head_p == NULL){ + ioexp_head_p = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; + } + ioexp_tail_p->next = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; +} +EXPORT_SYMBOL(create_ioexp_obj); + + +static int +_init_ioexp_obj(struct ioexp_obj_s* self) { + + char *err_msg = "ERR"; + char *func_name = "_init_ioexp_obj"; + + /* Setup IOEXP configure byte */ + if (setup_ioexp_config(self) < 0){ + err_msg = "setup_ioexp_config fail"; + goto err_init_ioexp_obj; + } + /* Setup default data */ + if (_ioexp_init_handler(self) < 0){ + err_msg = "_ioexp_init_handler fail"; + goto err_init_ioexp_obj; + } + /* Update all */ + if (self->state == STATE_IOEXP_NORMAL){ + if (self->update_all(self, 1, func_name) < 0){ + err_msg = "update_all() fail"; + goto err_init_ioexp_obj; + } + } + return 0; + +err_init_ioexp_obj: + SWPS_DEBUG("%s: %s\n", __func__, err_msg); + return -1; +} + + +int +init_ioexp_objs(void){ + /* Return value: + * 0: Success + * -1: Detect topology error + * -2: SWPS internal error + */ + struct ioexp_obj_s *curr_p = ioexp_head_p; + + if (!curr_p) { + SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__); + return -2; + } + while (curr_p) { + if (_init_ioexp_obj(curr_p) < 0) { + SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__); + return -1; + } + curr_p = curr_p->next; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} +EXPORT_SYMBOL(init_ioexp_objs); + + +void +clean_ioexp_objs(void){ + + struct ioexp_i2c_s *i2c_curr_p = NULL; + struct ioexp_i2c_s *i2c_next_p = NULL; + struct ioexp_obj_s *ioexp_next_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + if (ioexp_head_p == NULL){ + ioexp_tail_p = NULL; + return; + } + while(ioexp_curr_p){ + ioexp_next_p = ioexp_curr_p->next; + if (ioexp_curr_p->ioexp_map_p) { + if (ioexp_curr_p->ioexp_map_p->map_addr) { + kfree(ioexp_curr_p->ioexp_map_p->map_addr); + } + kfree(ioexp_curr_p->ioexp_map_p); + } + + i2c_curr_p = ioexp_curr_p->i2c_head_p; + while (i2c_curr_p) { + i2c_next_p = i2c_curr_p->next; + if (i2c_curr_p->i2c_client_p) { + i2c_put_adapter(i2c_curr_p->i2c_client_p->adapter); + kfree(i2c_curr_p->i2c_client_p); + } + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } + kfree(ioexp_curr_p); + ioexp_curr_p = ioexp_next_p; + } + ioexp_tail_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} +EXPORT_SYMBOL(clean_ioexp_objs); + + +int +check_ioexp_objs(void){ + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while (ioexp_curr_p){ + if ( (ioexp_curr_p->check(ioexp_curr_p)) < 0){ + SWPS_INFO("check IOEXP-%d fail! :%d\n", + ioexp_curr_p->ioexp_id, ioexp_curr_p->ioexp_type); + return -1; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} +EXPORT_SYMBOL(check_ioexp_objs); + + +struct ioexp_obj_s * +get_ioexp_obj(int ioexp_id){ + + struct ioexp_obj_s *result_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + if (ioexp_curr_p->ioexp_id == ioexp_id){ + result_p = ioexp_curr_p; + break; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return result_p; +} +EXPORT_SYMBOL(get_ioexp_obj); + + +void +unlock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_unlock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } +} +EXPORT_SYMBOL(unlock_ioexp_all); + +int +lock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_lock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} +EXPORT_SYMBOL(lock_ioexp_all); + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} +EXPORT_SYMBOL(check_channel_tier_1); + + +static int +_scan_channel_tier_1(int force, + int show_err) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + int ready = 0; + + if (!ioexp_curr_p) { + goto err_scan_tier_1_channel; + } + while(ioexp_curr_p) { + ready = _is_channel_ready(ioexp_curr_p); + if ((!ready) && (!force)) { + goto err_scan_tier_1_channel; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; + +err_scan_tier_1_channel: + if (show_err) { + if (ioexp_curr_p) { + SWPS_INFO("%s: IOEXP-%d fail\n", __func__, ioexp_curr_p->ioexp_id); + } else { + SWPS_INFO("%s: IOEXP is null.\n", __func__); + } + } + return -1; +} + + +static int +_scan_channel_tier_1_single(void) { + + int ret = 0; + int chan_id = 0; + int fake_cid = 0; + int fake_offs = 0; + int fake_addr = 0; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + + if (ioexp_head_p->ioexp_id != ioexp_tail_p->ioexp_id) { + return 0; + } + /* Setup i2c_client */ + chan_id = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chan_id; + fake_addr = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chip_addr; + adap = i2c_get_adapter((chan_id + 1)); + if(!adap){ + SWPS_INFO("%s: Can not get adap!\n", __func__); + return 0; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + SWPS_INFO("%s: Can not kzalloc client!\n", __func__); + return 0; + } + client->adapter = adap; + client->addr = fake_addr; + /* Fouce move ioexp ptr to next */ + ret = i2c_smbus_read_byte_data(client, fake_offs); + SWPS_DEBUG("%s: move ioexp_ptr done. :%d\n", __func__, ret); + kfree(client); + return 1; +} + + +int +resync_channel_tier_1(void) { + + char *emsg = "ERR"; + + if (!ioexp_head_p) { + emsg = "ioexp_head_p is NULL"; + goto err_resync_ioexp_status_1; + } + /* Run all */ + if (ioexp_head_p->ioexp_id == ioexp_tail_p->ioexp_id) { + _scan_channel_tier_1_single(); + } else { + _scan_channel_tier_1(1, 0); + } + /* Check all */ + if (_scan_channel_tier_1(0, 1) < 0) { + emsg = "resync tier-1 channel fail"; + goto err_resync_ioexp_status_1; + } + return 0; + +err_resync_ioexp_status_1: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} +EXPORT_SYMBOL(resync_channel_tier_1); + + +/* For build single module using (Ex: ONL platform) */ +MODULE_LICENSE("GPL"); + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/io_expander.h new file mode 100644 index 000000000000..43a8c290f5da --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/io_expander.h @@ -0,0 +1,189 @@ +#ifndef IO_EXPANDER_H +#define IO_EXPANDER_H + +#include + + +/* IOEXP type define (SFP series) */ +#define IOEXP_TYPE_MAGINOLIA_NAB (10101) +#define IOEXP_TYPE_MAGINOLIA_4AB (10102) +#define IOEXP_TYPE_MAPLE_NABC (10104) +#define IOEXP_TYPE_GULMOHAR_NABC (10105) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC (10106) +#define IOEXP_TYPE_SFP_8P_LAYOUT_1 (10107) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC (10108) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC (10109) + +/* IOEXP type define (QSFP series) */ +#define IOEXP_TYPE_MAGINOLIA_7AB (10201) +#define IOEXP_TYPE_REDWOOD_P01P08 (10202) +#define IOEXP_TYPE_REDWOOD_P09P16 (10203) +#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204) +#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205) +#define IOEXP_TYPE_SPRUCE_7AB (10206) +#define IOEXP_TYPE_CYPRESS_7ABC (10207) +#define IOEXP_TYPE_TAHOE_5A (10208) +#define IOEXP_TYPE_TAHOE_6ABC (10209) +#define IOEXP_TYPE_SEQUOIA_NABC (10210) +#define IOEXP_TYPE_LAVENDER_P65 (10211) +#define IOEXP_TYPE_MAPLE_0ABC (10212) +#define IOEXP_TYPE_GULMOHAR_7ABC (10213) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC (10214) +#define IOEXP_TYPE_QSFP_6P_LAYOUT_1 (10215) +#define IOEXP_TYPE_CEDAR_0ABC (10216) + +/* CPLD type define */ +#define CPLD_TYPE_COTTONWOOD (10301) + +/* IOEXP mode define */ +#define IOEXP_MODE_POLLING (19000) +#define IOEXP_MODE_DIRECT (19001) + +/* IOEXP state define */ +#define STATE_IOEXP_NORMAL (0) +#define STATE_IOEXP_INIT (-1) +#define STATE_IOEXP_ABNORMAL (-2) + +/* IOEXP error code define */ +#define ERR_IOEXP_NOTSUPPORT (-100) +#define ERR_IOEXP_UNINIT (-101) +#define ERR_IOEXP_BADCONF (-102) +#define ERR_IOEXP_ABNORMAL (-103) +#define ERR_IOEXP_NOSTATE (-104) +#define ERR_IOEXP_BADINPUT (-105) +#define ERR_IOEXP_UNEXCPT (-199) + +#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args) +#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args) +#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args) + +#ifdef DEBUG_SWPS +# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args) +#else +# define SWPS_DEBUG(fmt, args...) +#endif + +struct ioexp_addr_s { + int chan_id; + int chip_addr; + int read_offset[8]; + int write_offset[8]; + int conf_offset[8]; + uint8_t data_default[8]; + uint8_t conf_default[8]; +}; + +struct ioexp_i2c_s { + int chip_id; + struct i2c_client *i2c_client_p; + struct ioexp_i2c_s *next; +}; + + +struct ioexp_bitmap_s { + int chip_id; /* IOEXP chip id */ + int ioexp_voffset; /* IOEXP virtual offset */ + int bit_shift; +}; + +struct ioexp_map_s { + int chip_amount; /* Number of chips that IOEXP object content */ + int data_width; /* Number of (Read/Write/Config) bytes */ + struct ioexp_addr_s *map_addr; /* Chip address info */ + struct ioexp_bitmap_s map_present[10]; /* IOEXP for SFP / QSFP */ + struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[10]; /* IOEXP for QSFP */ +}; + +struct ioexp_data_s { + uint8_t data[8]; +}; + +struct ioexp_obj_s { + + /* ============================ + * Object public property + * ============================ + */ + int ioexp_id; + int ioexp_type; + + /* ============================ + * Object private property + * ============================ + */ + struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */ + struct ioexp_map_s *ioexp_map_p; + struct ioexp_obj_s *next; + struct ioexp_i2c_s *i2c_head_p; + struct mutex lock; + int mode; + int state; + + /* =========================================== + * Object public functions + * =========================================== + */ + int (*get_present)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset); + int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset); + int (*get_reset)(struct ioexp_obj_s *self, int virt_offset); + int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset); + int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs1)(struct ioexp_obj_s *self, int virt_offset); + int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val); + + /* =========================================== + * Object private functions + * =========================================== + */ + int (*init)(struct ioexp_obj_s *self); + int (*check)(struct ioexp_obj_s *self); + int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name); + int (*fsm_4_direct)(struct ioexp_obj_s* self); + int (*fsm_4_polling)(struct ioexp_obj_s* self); +}; + + +struct ioexp_obj_s* get_ioexp_obj(int ioexp_id); +int create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode); +int init_ioexp_objs(void); +int check_ioexp_objs(void); +void clean_ioexp_objs(void); + +void unlock_ioexp_all(void); +int lock_ioexp_all(void); + +int check_channel_tier_1(void); +int resync_channel_tier_1(void); + +/* Macro for bit control */ +#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift))) +#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift))) + + +#endif /* IO_EXPANDER_H */ + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/lpc_ich.c b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/lpc_ich.c new file mode 100644 index 000000000000..21e4824d6e33 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/lpc_ich.c @@ -0,0 +1,1149 @@ +/* + * lpc_ich.c - LPC interface for Intel ICH + * + * LPC bridge function of the Intel ICH contains many other + * functional units, such as Interrupt controllers, Timers, + * Power Management, System Management, GPIO, RTC, and LPC + * Configuration Registers. + * + * This driver is derived from lpc_sch. + + * Copyright (c) 2011 Extreme Engineering Solution, Inc. + * Author: Aaron Sierra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This driver supports the following I/O Controller hubs: + * (See the intel documentation on http://developer.intel.com.) + * document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO) + * document number 290687-002, 298242-027: 82801BA (ICH2) + * document number 290733-003, 290739-013: 82801CA (ICH3-S) + * document number 290716-001, 290718-007: 82801CAM (ICH3-M) + * document number 290744-001, 290745-025: 82801DB (ICH4) + * document number 252337-001, 252663-008: 82801DBM (ICH4-M) + * document number 273599-001, 273645-002: 82801E (C-ICH) + * document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R) + * document number 300641-004, 300884-013: 6300ESB + * document number 301473-002, 301474-026: 82801F (ICH6) + * document number 313082-001, 313075-006: 631xESB, 632xESB + * document number 307013-003, 307014-024: 82801G (ICH7) + * document number 322896-001, 322897-001: NM10 + * document number 313056-003, 313057-017: 82801H (ICH8) + * document number 316972-004, 316973-012: 82801I (ICH9) + * document number 319973-002, 319974-002: 82801J (ICH10) + * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) + * document number 320066-003, 320257-008: EP80597 (IICH) + * document number 324645-001, 324646-001: Cougar Point (CPT) + * document number TBD : Patsburg (PBG) + * document number TBD : DH89xxCC + * document number TBD : Panther Point + * document number TBD : Lynx Point + * document number TBD : Lynx Point-LP + * document number TBD : Wellsburg + * document number TBD : Avoton SoC + * document number TBD : Coleto Creek + * document number TBD : Wildcat Point-LP + * document number TBD : 9 Series + * document number TBD : Lewisburg + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define ACPIBASE 0x40 +#define ACPIBASE_GPE_OFF 0x28 +#define ACPIBASE_GPE_END 0x2f +#define ACPIBASE_SMI_OFF 0x30 +#define ACPIBASE_SMI_END 0x33 +#define ACPIBASE_PMC_OFF 0x08 +#define ACPIBASE_PMC_END 0x0c +#define ACPIBASE_TCO_OFF 0x60 +#define ACPIBASE_TCO_END 0x7f +#define ACPICTRL_PMCBASE 0x44 + +#define ACPIBASE_GCS_OFF 0x3410 +#define ACPIBASE_GCS_END 0x3414 + +#define GPIOBASE_ICH0 0x58 +#define GPIOCTRL_ICH0 0x5C +#define GPIOBASE_ICH6 0x48 +#define GPIOCTRL_ICH6 0x4C + +#define RCBABASE 0xf0 + +#define wdt_io_res(i) wdt_res(0, i) +#define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i) +#define wdt_res(b, i) (&wdt_ich_res[(b) + (i)]) + +struct lpc_ich_priv { + int chipset; + + int abase; /* ACPI base */ + int actrl_pbase; /* ACPI control or PMC base */ + int gbase; /* GPIO base */ + int gctrl; /* GPIO control */ + + int abase_save; /* Cached ACPI base value */ + int actrl_pbase_save; /* Cached ACPI control or PMC base value */ + int gctrl_save; /* Cached GPIO control value */ +}; + +static struct resource wdt_ich_res[] = { + /* ACPI - TCO */ + { + .flags = IORESOURCE_IO, + }, + /* ACPI - SMI */ + { + .flags = IORESOURCE_IO, + }, + /* GCS or PMC */ + { + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource gpio_ich_res[] = { + /* GPIO */ + { + .flags = IORESOURCE_IO, + }, + /* ACPI - GPE0 */ + { + .flags = IORESOURCE_IO, + }, +}; + +static struct mfd_cell lpc_ich_wdt_cell = { + .name = "iTCO_wdt", + .num_resources = ARRAY_SIZE(wdt_ich_res), + .resources = wdt_ich_res, + .ignore_resource_conflicts = true, +}; + +static struct mfd_cell lpc_ich_gpio_cell = { + .name = "gpio_ich", + .num_resources = ARRAY_SIZE(gpio_ich_res), + .resources = gpio_ich_res, + .ignore_resource_conflicts = true, +}; + +/* chipset related info */ +enum lpc_chipsets { + LPC_ICH = 0, /* ICH */ + LPC_ICH0, /* ICH0 */ + LPC_ICH2, /* ICH2 */ + LPC_ICH2M, /* ICH2-M */ + LPC_ICH3, /* ICH3-S */ + LPC_ICH3M, /* ICH3-M */ + LPC_ICH4, /* ICH4 */ + LPC_ICH4M, /* ICH4-M */ + LPC_CICH, /* C-ICH */ + LPC_ICH5, /* ICH5 & ICH5R */ + LPC_6300ESB, /* 6300ESB */ + LPC_ICH6, /* ICH6 & ICH6R */ + LPC_ICH6M, /* ICH6-M */ + LPC_ICH6W, /* ICH6W & ICH6RW */ + LPC_631XESB, /* 631xESB/632xESB */ + LPC_ICH7, /* ICH7 & ICH7R */ + LPC_ICH7DH, /* ICH7DH */ + LPC_ICH7M, /* ICH7-M & ICH7-U */ + LPC_ICH7MDH, /* ICH7-M DH */ + LPC_NM10, /* NM10 */ + LPC_ICH8, /* ICH8 & ICH8R */ + LPC_ICH8DH, /* ICH8DH */ + LPC_ICH8DO, /* ICH8DO */ + LPC_ICH8M, /* ICH8M */ + LPC_ICH8ME, /* ICH8M-E */ + LPC_ICH9, /* ICH9 */ + LPC_ICH9R, /* ICH9R */ + LPC_ICH9DH, /* ICH9DH */ + LPC_ICH9DO, /* ICH9DO */ + LPC_ICH9M, /* ICH9M */ + LPC_ICH9ME, /* ICH9M-E */ + LPC_ICH10, /* ICH10 */ + LPC_ICH10R, /* ICH10R */ + LPC_ICH10D, /* ICH10D */ + LPC_ICH10DO, /* ICH10DO */ + LPC_PCH, /* PCH Desktop Full Featured */ + LPC_PCHM, /* PCH Mobile Full Featured */ + LPC_P55, /* P55 */ + LPC_PM55, /* PM55 */ + LPC_H55, /* H55 */ + LPC_QM57, /* QM57 */ + LPC_H57, /* H57 */ + LPC_HM55, /* HM55 */ + LPC_Q57, /* Q57 */ + LPC_HM57, /* HM57 */ + LPC_PCHMSFF, /* PCH Mobile SFF Full Featured */ + LPC_QS57, /* QS57 */ + LPC_3400, /* 3400 */ + LPC_3420, /* 3420 */ + LPC_3450, /* 3450 */ + LPC_EP80579, /* EP80579 */ + LPC_CPT, /* Cougar Point */ + LPC_CPTD, /* Cougar Point Desktop */ + LPC_CPTM, /* Cougar Point Mobile */ + LPC_PBG, /* Patsburg */ + LPC_DH89XXCC, /* DH89xxCC */ + LPC_PPT, /* Panther Point */ + LPC_LPT, /* Lynx Point */ + LPC_LPT_LP, /* Lynx Point-LP */ + LPC_WBG, /* Wellsburg */ + LPC_AVN, /* Avoton SoC */ + LPC_BAYTRAIL, /* Bay Trail SoC */ + LPC_COLETO, /* Coleto Creek */ + LPC_WPT_LP, /* Wildcat Point-LP */ + LPC_BRASWELL, /* Braswell SoC */ + LPC_LEWISBURG, /* Lewisburg */ + LPC_9S, /* 9 Series */ + LPC_APL, /* Apollo Lake SoC */ + LPC_GLK, /* Gemini Lake SoC */ + LPC_COUGARMOUNTAIN,/* Cougar Mountain SoC*/ +}; + +static struct lpc_ich_info lpc_chipset_info[] = { + [LPC_ICH] = { + .name = "ICH", + .iTCO_version = 1, + }, + [LPC_ICH0] = { + .name = "ICH0", + .iTCO_version = 1, + }, + [LPC_ICH2] = { + .name = "ICH2", + .iTCO_version = 1, + }, + [LPC_ICH2M] = { + .name = "ICH2-M", + .iTCO_version = 1, + }, + [LPC_ICH3] = { + .name = "ICH3-S", + .iTCO_version = 1, + }, + [LPC_ICH3M] = { + .name = "ICH3-M", + .iTCO_version = 1, + }, + [LPC_ICH4] = { + .name = "ICH4", + .iTCO_version = 1, + }, + [LPC_ICH4M] = { + .name = "ICH4-M", + .iTCO_version = 1, + }, + [LPC_CICH] = { + .name = "C-ICH", + .iTCO_version = 1, + }, + [LPC_ICH5] = { + .name = "ICH5 or ICH5R", + .iTCO_version = 1, + }, + [LPC_6300ESB] = { + .name = "6300ESB", + .iTCO_version = 1, + }, + [LPC_ICH6] = { + .name = "ICH6 or ICH6R", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_ICH6M] = { + .name = "ICH6-M", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_ICH6W] = { + .name = "ICH6W or ICH6RW", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_631XESB] = { + .name = "631xESB/632xESB", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_ICH7] = { + .name = "ICH7 or ICH7R", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH7DH] = { + .name = "ICH7DH", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH7M] = { + .name = "ICH7-M or ICH7-U", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH7MDH] = { + .name = "ICH7-M DH", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_NM10] = { + .name = "NM10", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8] = { + .name = "ICH8 or ICH8R", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8DH] = { + .name = "ICH8DH", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8DO] = { + .name = "ICH8DO", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8M] = { + .name = "ICH8M", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8ME] = { + .name = "ICH8M-E", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH9] = { + .name = "ICH9", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9R] = { + .name = "ICH9R", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9DH] = { + .name = "ICH9DH", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9DO] = { + .name = "ICH9DO", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9M] = { + .name = "ICH9M", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9ME] = { + .name = "ICH9M-E", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH10] = { + .name = "ICH10", + .iTCO_version = 2, + .gpio_version = ICH_V10CONS_GPIO, + }, + [LPC_ICH10R] = { + .name = "ICH10R", + .iTCO_version = 2, + .gpio_version = ICH_V10CONS_GPIO, + }, + [LPC_ICH10D] = { + .name = "ICH10D", + .iTCO_version = 2, + .gpio_version = ICH_V10CORP_GPIO, + }, + [LPC_ICH10DO] = { + .name = "ICH10DO", + .iTCO_version = 2, + .gpio_version = ICH_V10CORP_GPIO, + }, + [LPC_PCH] = { + .name = "PCH Desktop Full Featured", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PCHM] = { + .name = "PCH Mobile Full Featured", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_P55] = { + .name = "P55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PM55] = { + .name = "PM55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_H55] = { + .name = "H55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_QM57] = { + .name = "QM57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_H57] = { + .name = "H57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_HM55] = { + .name = "HM55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_Q57] = { + .name = "Q57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_HM57] = { + .name = "HM57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PCHMSFF] = { + .name = "PCH Mobile SFF Full Featured", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_QS57] = { + .name = "QS57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_3400] = { + .name = "3400", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_3420] = { + .name = "3420", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_3450] = { + .name = "3450", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_EP80579] = { + .name = "EP80579", + .iTCO_version = 2, + }, + [LPC_CPT] = { + .name = "Cougar Point", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_CPTD] = { + .name = "Cougar Point Desktop", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_CPTM] = { + .name = "Cougar Point Mobile", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PBG] = { + .name = "Patsburg", + .iTCO_version = 2, + }, + [LPC_DH89XXCC] = { + .name = "DH89xxCC", + .iTCO_version = 2, + }, + [LPC_PPT] = { + .name = "Panther Point", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_LPT] = { + .name = "Lynx Point", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_LPT_LP] = { + .name = "Lynx Point_LP", + .iTCO_version = 2, + }, + [LPC_WBG] = { + .name = "Wellsburg", + .iTCO_version = 2, + }, + [LPC_AVN] = { + .name = "Avoton SoC", + .iTCO_version = 3, + .gpio_version = AVOTON_GPIO, + }, + [LPC_BAYTRAIL] = { + .name = "Bay Trail SoC", + .iTCO_version = 3, + }, + [LPC_COLETO] = { + .name = "Coleto Creek", + .iTCO_version = 2, + }, + [LPC_WPT_LP] = { + .name = "Wildcat Point_LP", + .iTCO_version = 2, + }, + [LPC_BRASWELL] = { + .name = "Braswell SoC", + .iTCO_version = 3, + }, + [LPC_LEWISBURG] = { + .name = "Lewisburg", + .iTCO_version = 2, + }, + [LPC_9S] = { + .name = "9 Series", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_APL] = { + .name = "Apollo Lake SoC", + .iTCO_version = 5, + }, + [LPC_GLK] = { + .name = "Gemini Lake SoC", + }, + [LPC_COUGARMOUNTAIN] = { + .name = "Cougar Mountain SoC", + .iTCO_version = 3, + }, +}; + +/* + * This data only exists for exporting the supported PCI ids + * via MODULE_DEVICE_TABLE. We do not actually register a + * pci_driver, because the I/O Controller Hub has also other + * functions that probably will be registered by other drivers. + */ +static const struct pci_device_id lpc_ich_ids[] = { + { PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL}, + { PCI_VDEVICE(INTEL, 0x1c41), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c42), LPC_CPTD}, + { PCI_VDEVICE(INTEL, 0x1c43), LPC_CPTM}, + { PCI_VDEVICE(INTEL, 0x1c44), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c45), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c46), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c47), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c48), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c49), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4a), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4b), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4c), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4d), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4e), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4f), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c50), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c51), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c52), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c53), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c54), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c55), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c56), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c57), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c58), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c59), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5a), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5b), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5c), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5d), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5e), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5f), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1d40), LPC_PBG}, + { PCI_VDEVICE(INTEL, 0x1d41), LPC_PBG}, + { PCI_VDEVICE(INTEL, 0x1e40), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e41), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e42), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e43), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e44), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e45), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e46), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e47), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e48), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e49), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4a), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4b), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4c), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4d), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4e), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4f), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e50), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e51), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e52), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e53), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e54), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e55), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e56), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e57), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e58), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e59), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5a), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5b), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5c), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5d), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5e), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5f), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x229c), LPC_BRASWELL}, + { PCI_VDEVICE(INTEL, 0x2310), LPC_DH89XXCC}, + { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO}, + { PCI_VDEVICE(INTEL, 0x2410), LPC_ICH}, + { PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0}, + { PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2}, + { PCI_VDEVICE(INTEL, 0x244c), LPC_ICH2M}, + { PCI_VDEVICE(INTEL, 0x2450), LPC_CICH}, + { PCI_VDEVICE(INTEL, 0x2480), LPC_ICH3}, + { PCI_VDEVICE(INTEL, 0x248c), LPC_ICH3M}, + { PCI_VDEVICE(INTEL, 0x24c0), LPC_ICH4}, + { PCI_VDEVICE(INTEL, 0x24cc), LPC_ICH4M}, + { PCI_VDEVICE(INTEL, 0x24d0), LPC_ICH5}, + { PCI_VDEVICE(INTEL, 0x25a1), LPC_6300ESB}, + { PCI_VDEVICE(INTEL, 0x2640), LPC_ICH6}, + { PCI_VDEVICE(INTEL, 0x2641), LPC_ICH6M}, + { PCI_VDEVICE(INTEL, 0x2642), LPC_ICH6W}, + { PCI_VDEVICE(INTEL, 0x2670), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2671), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2672), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2673), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2674), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2675), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2676), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2677), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2678), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2679), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267a), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267b), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267c), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267d), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267e), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267f), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x27b0), LPC_ICH7DH}, + { PCI_VDEVICE(INTEL, 0x27b8), LPC_ICH7}, + { PCI_VDEVICE(INTEL, 0x27b9), LPC_ICH7M}, + { PCI_VDEVICE(INTEL, 0x27bc), LPC_NM10}, + { PCI_VDEVICE(INTEL, 0x27bd), LPC_ICH7MDH}, + { PCI_VDEVICE(INTEL, 0x2810), LPC_ICH8}, + { PCI_VDEVICE(INTEL, 0x2811), LPC_ICH8ME}, + { PCI_VDEVICE(INTEL, 0x2812), LPC_ICH8DH}, + { PCI_VDEVICE(INTEL, 0x2814), LPC_ICH8DO}, + { PCI_VDEVICE(INTEL, 0x2815), LPC_ICH8M}, + { PCI_VDEVICE(INTEL, 0x2912), LPC_ICH9DH}, + { PCI_VDEVICE(INTEL, 0x2914), LPC_ICH9DO}, + { PCI_VDEVICE(INTEL, 0x2916), LPC_ICH9R}, + { PCI_VDEVICE(INTEL, 0x2917), LPC_ICH9ME}, + { PCI_VDEVICE(INTEL, 0x2918), LPC_ICH9}, + { PCI_VDEVICE(INTEL, 0x2919), LPC_ICH9M}, + { PCI_VDEVICE(INTEL, 0x3197), LPC_GLK}, + { PCI_VDEVICE(INTEL, 0x2b9c), LPC_COUGARMOUNTAIN}, + { PCI_VDEVICE(INTEL, 0x3a14), LPC_ICH10DO}, + { PCI_VDEVICE(INTEL, 0x3a16), LPC_ICH10R}, + { PCI_VDEVICE(INTEL, 0x3a18), LPC_ICH10}, + { PCI_VDEVICE(INTEL, 0x3a1a), LPC_ICH10D}, + { PCI_VDEVICE(INTEL, 0x3b00), LPC_PCH}, + { PCI_VDEVICE(INTEL, 0x3b01), LPC_PCHM}, + { PCI_VDEVICE(INTEL, 0x3b02), LPC_P55}, + { PCI_VDEVICE(INTEL, 0x3b03), LPC_PM55}, + { PCI_VDEVICE(INTEL, 0x3b06), LPC_H55}, + { PCI_VDEVICE(INTEL, 0x3b07), LPC_QM57}, + { PCI_VDEVICE(INTEL, 0x3b08), LPC_H57}, + { PCI_VDEVICE(INTEL, 0x3b09), LPC_HM55}, + { PCI_VDEVICE(INTEL, 0x3b0a), LPC_Q57}, + { PCI_VDEVICE(INTEL, 0x3b0b), LPC_HM57}, + { PCI_VDEVICE(INTEL, 0x3b0d), LPC_PCHMSFF}, + { PCI_VDEVICE(INTEL, 0x3b0f), LPC_QS57}, + { PCI_VDEVICE(INTEL, 0x3b12), LPC_3400}, + { PCI_VDEVICE(INTEL, 0x3b14), LPC_3420}, + { PCI_VDEVICE(INTEL, 0x3b16), LPC_3450}, + { PCI_VDEVICE(INTEL, 0x5031), LPC_EP80579}, + { PCI_VDEVICE(INTEL, 0x5ae8), LPC_APL}, + { PCI_VDEVICE(INTEL, 0x8c40), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c41), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c42), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c43), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c44), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c45), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c46), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c47), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c48), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c49), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4a), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4b), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4c), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4d), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4e), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4f), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c50), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c51), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c52), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c53), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c54), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c55), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c56), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c57), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c58), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c59), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5a), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5b), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5c), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5d), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5e), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5f), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8cc1), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc2), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc3), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc4), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc6), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8d40), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d41), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d42), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d43), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d44), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d45), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d46), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d47), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d48), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d49), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4a), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4b), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4c), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4d), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4e), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4f), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d50), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d51), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d52), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d53), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d54), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d55), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d56), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d57), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d58), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d59), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5a), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5b), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5c), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x9c40), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c41), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c42), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c43), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c44), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc1), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc2), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc3), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc5), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc6), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc7), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc9), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0xa1c1), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c2), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c3), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c4), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c5), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c6), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c7), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa242), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa243), LPC_LEWISBURG}, + { 0, }, /* End of list */ +}; +MODULE_DEVICE_TABLE(pci, lpc_ich_ids); + +static void lpc_ich_restore_config_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + + if (priv->abase_save >= 0) { + pci_write_config_byte(dev, priv->abase, priv->abase_save); + priv->abase_save = -1; + } + + if (priv->actrl_pbase_save >= 0) { + pci_write_config_byte(dev, priv->actrl_pbase, + priv->actrl_pbase_save); + priv->actrl_pbase_save = -1; + } + + if (priv->gctrl_save >= 0) { + pci_write_config_byte(dev, priv->gctrl, priv->gctrl_save); + priv->gctrl_save = -1; + } +} + +static void lpc_ich_enable_acpi_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u8 reg_save; + + switch (lpc_chipset_info[priv->chipset].iTCO_version) { + case 3: + /* + * Some chipsets (eg Avoton) enable the ACPI space in the + * ACPI BASE register. + */ + pci_read_config_byte(dev, priv->abase, ®_save); + pci_write_config_byte(dev, priv->abase, reg_save | 0x2); + priv->abase_save = reg_save; + break; + default: + /* + * Most chipsets enable the ACPI space in the ACPI control + * register. + */ + pci_read_config_byte(dev, priv->actrl_pbase, ®_save); + pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x80); + priv->actrl_pbase_save = reg_save; + break; + } +} + +static void lpc_ich_enable_gpio_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u8 reg_save; + + pci_read_config_byte(dev, priv->gctrl, ®_save); + pci_write_config_byte(dev, priv->gctrl, reg_save | 0x10); + priv->gctrl_save = reg_save; +} + +static void lpc_ich_enable_pmc_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u8 reg_save; + + pci_read_config_byte(dev, priv->actrl_pbase, ®_save); + pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x2); + + priv->actrl_pbase_save = reg_save; +} + +static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev) +{ + struct itco_wdt_platform_data *pdata; + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + struct lpc_ich_info *info; + struct mfd_cell *cell = &lpc_ich_wdt_cell; + + pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + info = &lpc_chipset_info[priv->chipset]; + + pdata->version = info->iTCO_version; + strlcpy(pdata->name, info->name, sizeof(pdata->name)); + + cell->platform_data = pdata; + cell->pdata_size = sizeof(*pdata); + return 0; +} + +static void lpc_ich_finalize_gpio_cell(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + struct mfd_cell *cell = &lpc_ich_gpio_cell; + + cell->platform_data = &lpc_chipset_info[priv->chipset]; + cell->pdata_size = sizeof(struct lpc_ich_info); +} + +/* + * We don't check for resource conflict globally. There are 2 or 3 independent + * GPIO groups and it's enough to have access to one of these to instantiate + * the device. + */ +static int lpc_ich_check_conflict_gpio(struct resource *res) +{ + int ret; + u8 use_gpio = 0; + + if (resource_size(res) >= 0x50 && + !acpi_check_region(res->start + 0x40, 0x10, "LPC ICH GPIO3")) + use_gpio |= 1 << 2; + + if (!acpi_check_region(res->start + 0x30, 0x10, "LPC ICH GPIO2")) + use_gpio |= 1 << 1; + + ret = acpi_check_region(res->start + 0x00, 0x30, "LPC ICH GPIO1"); + if (!ret) + use_gpio |= 1 << 0; + + return use_gpio ? use_gpio : ret; +} + +static int lpc_ich_init_gpio(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u32 base_addr_cfg; + u32 base_addr; + int ret; + bool acpi_conflict = false; + struct resource *res; + + /* Setup power management base register */ + pci_read_config_dword(dev, priv->abase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); + lpc_ich_gpio_cell.num_resources--; + goto gpe0_done; + } + + res = &gpio_ich_res[ICH_RES_GPE0]; + res->start = base_addr + ACPIBASE_GPE_OFF; + res->end = base_addr + ACPIBASE_GPE_END; + ret = acpi_check_resource_conflict(res); + if (ret) { + /* + * This isn't fatal for the GPIO, but we have to make sure that + * the platform_device subsystem doesn't see this resource + * or it will register an invalid region. + */ + lpc_ich_gpio_cell.num_resources--; + acpi_conflict = true; + } else { + lpc_ich_enable_acpi_space(dev); + } + +gpe0_done: + /* Setup GPIO base register */ + pci_read_config_dword(dev, priv->gbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n"); + ret = -ENODEV; + goto gpio_done; + } + + /* Older devices provide fewer GPIO and have a smaller resource size. */ + res = &gpio_ich_res[ICH_RES_GPIO]; + res->start = base_addr; + switch (lpc_chipset_info[priv->chipset].gpio_version) { + case ICH_V5_GPIO: + case ICH_V10CORP_GPIO: + res->end = res->start + 128 - 1; + break; + default: + res->end = res->start + 64 - 1; + break; + } + + ret = lpc_ich_check_conflict_gpio(res); + if (ret < 0) { + /* this isn't necessarily fatal for the GPIO */ + acpi_conflict = true; + goto gpio_done; + } + lpc_chipset_info[priv->chipset].use_gpio = ret; + lpc_ich_enable_gpio_space(dev); + + lpc_ich_finalize_gpio_cell(dev); + ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, + &lpc_ich_gpio_cell, 1, NULL, 0, NULL); + +gpio_done: + if (acpi_conflict) + pr_warn("Resource conflict(s) found affecting %s\n", + lpc_ich_gpio_cell.name); + return ret; +} + +static int lpc_ich_init_wdt(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u32 base_addr_cfg; + u32 base_addr; + int ret; + struct resource *res; + + /* If we have ACPI based watchdog use that instead */ + if (acpi_has_watchdog()) + return -ENODEV; + + /* Setup power management base register */ + pci_read_config_dword(dev, priv->abase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); + ret = -ENODEV; + goto wdt_done; + } + + res = wdt_io_res(ICH_RES_IO_TCO); + res->start = base_addr + ACPIBASE_TCO_OFF; + res->end = base_addr + ACPIBASE_TCO_END; + + res = wdt_io_res(ICH_RES_IO_SMI); + res->start = base_addr + ACPIBASE_SMI_OFF; + res->end = base_addr + ACPIBASE_SMI_END; + + lpc_ich_enable_acpi_space(dev); + + /* + * iTCO v2: + * Get the Memory-Mapped GCS register. To get access to it + * we have to read RCBA from PCI Config space 0xf0 and use + * it as base. GCS = RCBA + ICH6_GCS(0x3410). + * + * iTCO v3: + * Get the Power Management Configuration register. To get access + * to it we have to read the PMC BASE from config space and address + * the register at offset 0x8. + */ + if (lpc_chipset_info[priv->chipset].iTCO_version == 1) { + /* Don't register iomem for TCO ver 1 */ + lpc_ich_wdt_cell.num_resources--; + } else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) { + pci_read_config_dword(dev, RCBABASE, &base_addr_cfg); + base_addr = base_addr_cfg & 0xffffc000; + if (!(base_addr_cfg & 1)) { + dev_notice(&dev->dev, "RCBA is disabled by " + "hardware/BIOS, device disabled\n"); + ret = -ENODEV; + goto wdt_done; + } + res = wdt_mem_res(ICH_RES_MEM_GCS_PMC); + res->start = base_addr + ACPIBASE_GCS_OFF; + res->end = base_addr + ACPIBASE_GCS_END; + } else if (lpc_chipset_info[priv->chipset].iTCO_version == 3) { + lpc_ich_enable_pmc_space(dev); + pci_read_config_dword(dev, ACPICTRL_PMCBASE, &base_addr_cfg); + base_addr = base_addr_cfg & 0xfffffe00; + + res = wdt_mem_res(ICH_RES_MEM_GCS_PMC); + res->start = base_addr + ACPIBASE_PMC_OFF; + res->end = base_addr + ACPIBASE_PMC_END; + } + + ret = lpc_ich_finalize_wdt_cell(dev); + if (ret) + goto wdt_done; + + ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, + &lpc_ich_wdt_cell, 1, NULL, 0, NULL); + +wdt_done: + return ret; +} + +static int lpc_ich_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + struct lpc_ich_priv *priv; + int ret; + bool cell_added = false; + + priv = devm_kzalloc(&dev->dev, + sizeof(struct lpc_ich_priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->chipset = id->driver_data; + + priv->actrl_pbase_save = -1; + priv->abase_save = -1; + + priv->abase = ACPIBASE; + priv->actrl_pbase = ACPICTRL_PMCBASE; + + priv->gctrl_save = -1; + if (priv->chipset <= LPC_ICH5) { + priv->gbase = GPIOBASE_ICH0; + priv->gctrl = GPIOCTRL_ICH0; + } else { + priv->gbase = GPIOBASE_ICH6; + priv->gctrl = GPIOCTRL_ICH6; + } + + pci_set_drvdata(dev, priv); + + if (lpc_chipset_info[priv->chipset].iTCO_version) { + ret = lpc_ich_init_wdt(dev); + if (!ret) + cell_added = true; + } + + if (lpc_chipset_info[priv->chipset].gpio_version) { + ret = lpc_ich_init_gpio(dev); + if (!ret) + cell_added = true; + } + + /* + * We only care if at least one or none of the cells registered + * successfully. + */ + if (!cell_added) { + dev_warn(&dev->dev, "No MFD cells added\n"); + lpc_ich_restore_config_space(dev); + return -ENODEV; + } + + return 0; +} + +static void lpc_ich_remove(struct pci_dev *dev) +{ + mfd_remove_devices(&dev->dev); + lpc_ich_restore_config_space(dev); +} + +static struct pci_driver lpc_ich_driver = { + .name = "lpc_ich", + .id_table = lpc_ich_ids, + .probe = lpc_ich_probe, + .remove = lpc_ich_remove, +}; + +module_pci_driver(lpc_ich_driver); + +MODULE_AUTHOR("Aaron Sierra "); +MODULE_DESCRIPTION("LPC interface for Intel ICH"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/transceiver.c new file mode 100644 index 000000000000..251ada569ed6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/transceiver.c @@ -0,0 +1,8409 @@ +#include +#include +#include +#include +#include "io_expander.h" +#include "transceiver.h" + +/* For build single module using (Ex: ONL platform) */ +#include +//#include +//#include + +extern int io_no_init; +/* ========== Register EEPROM address mapping ========== + */ +struct eeprom_map_s eeprom_map_sfp = { + .addr_br =0x50, .page_br =-1, .offset_br =12, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =94, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =-1, .offset_connector =2, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =-1, .offset_diag_type =92 , .length_diag_type =1, + .addr_extbr =-1, .page_extbr =-1, .offset_extbr =-1, .length_extbr =-1, + .addr_ext_id =0x50, .page_ext_id =-1, .offset_ext_id =1, .length_ext_id =1, + .addr_id =0x50, .page_id =-1, .offset_id =0, .length_id =1, + .addr_len_sm =0x50, .page_len_sm =-1, .offset_len_sm =15, .length_len_sm =1, + .addr_len_smf =0x50, .page_len_smf =-1, .offset_len_smf =14, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =-1, .offset_len_om1 =17, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =-1, .offset_len_om2 =16, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =-1, .offset_len_om3 =19, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =-1, .offset_len_om4 =18, .length_len_om4 =1, + .addr_option =0x50, .page_option =-1, .offset_option =64, .length_option =2, + .addr_rate_id =0x50, .page_rate_id =-1, .offset_rate_id =13, .length_rate_id =1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =0x51, .page_rx_em =-1, .offset_rx_em =115, .length_rx_em =1, + .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1, + .addr_rx_power =0x51, .page_rx_power =-1, .offset_rx_power =104, .length_rx_power =2, + .addr_soft_rs0 =0x51, .page_soft_rs0 =-1, .offset_soft_rs0 =110, .length_soft_rs0 =1, + .addr_soft_rs1 =0x51, .page_soft_rs1 =-1, .offset_soft_rs1 =118, .length_soft_rs0 =1, + .addr_temp =0x51, .page_temp =-1, .offset_temp =96, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =-1, .offset_trancomp =3, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =-1, .offset_trancomp_ext =36, .length_trancomp_ext =1, + .addr_tx_bias =0x51, .page_tx_bias =-1, .offset_tx_bias =100, .length_tx_bias =2, + .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1, + .addr_tx_eq =0x51, .page_tx_eq =-1, .offset_tx_eq =114, .length_tx_eq =1, + .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1, + .addr_tx_power =0x51, .page_tx_power =-1, .offset_tx_power =102, .length_tx_power =2, + .addr_vendor_name =0x50, .page_vendor_name =-1, .offset_vendor_name =20, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =-1, .offset_vendor_pn =40, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =-1, .offset_vendor_rev =56, .length_vendor_rev =4, + .addr_vendor_sn =0x50, .page_vendor_sn =-1, .offset_vendor_sn =68, .length_vendor_sn =16, + .addr_voltage =0x51, .page_voltage =-1, .offset_voltage =98, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =-1, .offset_wavelength =60, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =-1, .page_rx_em =-1, .offset_rx_em =-1, .length_rx_em =-1, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =-1, .page_tx_eq =-1, .offset_tx_eq =-1, .length_tx_eq =-1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp28 = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =0x50, .page_cdr =-1, .offset_cdr =98, .length_cdr =1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =0x50, .page_rx_am =3, .offset_rx_am =238, .length_rx_am =2, + .addr_rx_em =0x50, .page_rx_em =3, .offset_rx_em =236, .length_rx_em =2, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =0x50, .page_tx_eq =3, .offset_tx_eq =234, .length_tx_eq =2, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + + +/* ========== Utility Functions ========== + */ +static int +get_bit(uint8_t origin_byte, int bit_shift) { + return (int)((origin_byte >> bit_shift) & 0x1); +} + +static int +transform_word_to_int(uint8_t hight_byte, + uint8_t low_byte) { + return ((((int)hight_byte) << 8) + (int)low_byte); +} + +void +alarm_msg_2_user(struct transvr_obj_s *self, + char *emsg) { + + SWPS_ERR("%s on %s.\n", emsg, self->swp_name); +} +EXPORT_SYMBOL(alarm_msg_2_user); + +/* ========== Private functions ========== + */ +static int +_reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +_is_transvr_support_ctle(struct transvr_obj_s *self); + +static int +_transvr_init_handler(struct transvr_obj_s *self); + +int +_transvr_clean_handler(struct transvr_obj_s *self); + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self); + + +void +lock_transvr_obj(struct transvr_obj_s *self) { + + mutex_lock(&self->lock); + self->curr_page = VAL_TRANSVR_PAGE_FREE; +} +EXPORT_SYMBOL(lock_transvr_obj); + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} +EXPORT_SYMBOL(unlock_transvr_obj); + + +static int +_check_by_mode(struct transvr_obj_s *self, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + char *caller_name){ + + int return_val = ERR_TRANSVR_UNEXCPT; + + switch (self->mode){ + case TRANSVR_MODE_POLLING: + switch (self->state){ + case STATE_TRANSVR_CONNECTED: + goto ok_check_by_mode_1; + case STATE_TRANSVR_NEW: + case STATE_TRANSVR_INIT: + return ERR_TRANSVR_UNINIT; + case STATE_TRANSVR_DISCONNECTED: + return ERR_TRANSVR_UNPLUGGED; + case STATE_TRANSVR_UNEXCEPTED: + return ERR_TRANSVR_ABNORMAL; + case STATE_TRANSVR_ISOLATED: + return ERR_TRNASVR_BE_ISOLATED; + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + + case TRANSVR_MODE_DIRECT: + return_val = self->fsm_4_direct(self, caller_name); + if (return_val < 0){ + return return_val; + } + goto ok_check_by_mode_1; + + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + +ok_check_by_mode_1: + return attr_update_func(self, 0); + +err_check_by_mode_1: + SWPS_INFO("_check_by_mode: mode:%d state:%d\n", self->mode, self->state); + return ERR_TRANSVR_UNEXCPT; +} + + +static void +_transvr_clean_retry(struct transvr_obj_s *self) { + self->retry = 0; +} + + +static int +_transvr_handle_retry(struct transvr_obj_s *self, int retry) { + /* Return: 0: keep retry + * -1: stop retry + */ + if (self->retry == 0) { + self->retry = retry; + } + self->retry -= 1; + if (self->retry <= 0) { + _transvr_clean_retry(self); + return -1; + } + return 0; +} + + +static int +_common_setup_page(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int show_e) { + /* return: + * 0 : OK + * -1 : EEPROM settings incorrect + * -2 : I2C R/W failure + * -3 : Undefined case + */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Check */ + if ((addr < 0) || (offset < 0) || (len < 0)) { + emsg = "EEPROM settings incorrect"; + retval = -1; + goto err_common_setup_page; + } + /* Case1: continue access */ + if ((self->i2c_client_p->addr == addr) && + (self->curr_page == page)) { + return 0; + } + self->i2c_client_p->addr = addr; + /* Case2: select lower page */ + if (page == -1) { + self->curr_page = page; + return 0; + } + /* Case3: select upper page */ + if (page >= 0) { + goto upper_common_setup_page; + } + /* Unexpected case */ + show_e = 1; + emsg = "Unexpected case"; + retval = -3; + goto err_common_setup_page; + +upper_common_setup_page: + if (i2c_smbus_write_byte_data(self->i2c_client_p, + VAL_TRANSVR_PAGE_SELECT_OFFSET, + page) < 0) { + emsg = "I2C R/W failure"; + retval = -2; + goto err_common_setup_page; + } + self->curr_page = page; + mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY); + return 0; + +err_common_setup_page: + if (show_e) { + SWPS_INFO("%s: %s", __func__, emsg); + SWPS_INFO("%s: :0x%02x :%d :%d :%d\n", + __func__, addr, page, offset, len); + } + return retval; +} + +/* +static int +_common_setup_password(struct transvr_obj_s *self, + int addr, + int page, + int offs, + uint8_t pwd[4], + int show_e) { + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, 4, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_setup_password; + } + for (i=0; i<4; i++) { + err = i2c_smbus_write_byte_data(self->i2c_client_p, + (offs + i), + pwd[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_setup_password; + } + } + return 0; + +err_common_setup_password: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} +*/ + +static int +_common_update_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + uint8_t *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_uint8_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_uint8_attr; + } + buf[i] = err; + } + return 0; + +err_common_update_uint8_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_int_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_int_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_int_attr; + } + buf[i] = (int)err; + } + return 0; + +err_common_update_int_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_INT_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_string_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + char buf[], + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_string_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_string_attr; + } + buf[i] = (char)err; + } + return 0; + +err_common_update_string_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = 'e'; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + uint8_t update, + uint8_t *buf, + char *caller, + int show_e){ + int len = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + if ((*buf) == update){ + return 0; + } + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + err = i2c_smbus_write_byte_data(self->i2c_client_p, + offset, + update); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + (*buf) = update; + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_array(struct transvr_obj_s *self, + int addr, + int page, + int offs, + int len, + uint8_t update[], + uint8_t buf[], + char *caller, + int show_e){ + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + for (i=0; ii2c_client_p, + (offs + i), + update[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + buf[i] = update[i]; + } + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, emsg, caller, err, i); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_attr_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_id, + self->eeprom_map_p->page_id, + self->eeprom_map_p->offset_id, + self->eeprom_map_p->length_id, + &(self->id), + "_common_update_attr_id", + show_err); +} + + +static int +_common_update_attr_extended_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_ext_id, + self->eeprom_map_p->page_ext_id, + self->eeprom_map_p->offset_ext_id, + self->eeprom_map_p->length_ext_id, + &(self->ext_id), + "_common_update_attr_extended_id", + show_err); +} + + +static int +_common_update_attr_connector(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_connector, + self->eeprom_map_p->page_connector, + self->eeprom_map_p->offset_connector, + self->eeprom_map_p->length_connector, + &(self->connector), + "_common_update_attr_connector", + show_err); +} + + +static int +_common_update_attr_transvr_comp(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp, + self->eeprom_map_p->page_trancomp, + self->eeprom_map_p->offset_trancomp, + self->eeprom_map_p->length_trancomp, + self->transvr_comp, + "_common_update_attr_transvr_comp", + show_err); +} + + +static int +_common_update_attr_transvr_comp_ext(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp_ext, + self->eeprom_map_p->page_trancomp_ext, + self->eeprom_map_p->offset_trancomp_ext, + self->eeprom_map_p->length_trancomp_ext, + &(self->transvr_comp_ext), + "_common_update_attr_transvr_comp_ext", + show_err); +} + + +static int +_common_update_attr_vendor_name(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_name, + self->eeprom_map_p->page_vendor_name, + self->eeprom_map_p->offset_vendor_name, + self->eeprom_map_p->length_vendor_name, + self->vendor_name, + "_common_update_attr_vendor_name", + show_err); +} + + +static int +_common_update_attr_vendor_pn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_pn, + self->eeprom_map_p->page_vendor_pn, + self->eeprom_map_p->offset_vendor_pn, + self->eeprom_map_p->length_vendor_pn, + self->vendor_pn, + "_common_update_attr_vendor_pn", + show_err); +} + + +static int +_common_update_attr_vendor_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_rev, + self->eeprom_map_p->page_vendor_rev, + self->eeprom_map_p->offset_vendor_rev, + self->eeprom_map_p->length_vendor_rev, + self->vendor_rev, + "_common_update_attr_vendor_rev", + show_err); +} + + +static int +_common_update_attr_vendor_sn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_sn, + self->eeprom_map_p->page_vendor_sn, + self->eeprom_map_p->offset_vendor_sn, + self->eeprom_map_p->length_vendor_sn, + self->vendor_sn, + "_common_update_attr_vendor_sn", + show_err); +} + + +static int +_common_update_attr_br(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_br, + self->eeprom_map_p->page_br, + self->eeprom_map_p->offset_br, + self->eeprom_map_p->length_br, + &(self->br), + "_common_update_attr_br", + show_err); +} + + +static int +_common_update_attr_len_smf(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_smf, + self->eeprom_map_p->page_len_smf, + self->eeprom_map_p->offset_len_smf, + self->eeprom_map_p->length_len_smf, + &(self->len_smf), + "_common_update_attr_len_smf", + show_err); +} + + +static int +_common_update_attr_len_om1(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om1, + self->eeprom_map_p->page_len_om1, + self->eeprom_map_p->offset_len_om1, + self->eeprom_map_p->length_len_om1, + &(self->len_om1), + "_common_update_attr_len_om1", + show_err); +} + +static int +_common_update_attr_len_om2(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om2, + self->eeprom_map_p->page_len_om2, + self->eeprom_map_p->offset_len_om2, + self->eeprom_map_p->length_len_om2, + &(self->len_om2), + "_common_update_attr_len_om2", + show_err); +} + +static int +_common_update_attr_len_om3(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om3, + self->eeprom_map_p->page_len_om3, + self->eeprom_map_p->offset_len_om3, + self->eeprom_map_p->length_len_om3, + &(self->len_om3), + "_common_update_attr_len_om3", + show_err); +} + + +static int +_common_update_attr_len_om4(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om4, + self->eeprom_map_p->page_len_om4, + self->eeprom_map_p->offset_len_om4, + self->eeprom_map_p->length_len_om4, + &(self->len_om4), + "_common_update_attr_len_om4", + show_err); +} + + +static int +_common_update_attr_option(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_option, + self->eeprom_map_p->page_option, + self->eeprom_map_p->offset_option, + self->eeprom_map_p->length_option, + self->option, + "_common_update_attr_option", + show_err); +} + + +static int +_common_update_attr_comp_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_comp_rev, + self->eeprom_map_p->page_comp_rev, + self->eeprom_map_p->offset_comp_rev, + self->eeprom_map_p->length_comp_rev, + &(self->comp_rev), + "_common_update_attr_comp_rev", + show_err); +} + + +static int +_common_update_attr_diag_type(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_diag_type, + self->eeprom_map_p->page_diag_type, + self->eeprom_map_p->offset_diag_type, + self->eeprom_map_p->length_diag_type, + &(self->diag_type), + "_common_update_attr_diag_type", + show_err); +} + + +static int +_common_update_attr_wavelength(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_wavelength, + self->eeprom_map_p->page_wavelength, + self->eeprom_map_p->offset_wavelength, + self->eeprom_map_p->length_wavelength, + self->wavelength, + "_common_update_attr_wavelength", + show_err); +} + + +int +_common_get_option_value(struct transvr_obj_s *self, + int offset, + int bit_shift) { + /* SFP: + * - option[0] = A0h / 64 + * - option[1] = A0h / 65 + * QSFP: + * - option[0] = 00h / 193 + * - option[1] = 00h / 194 + * - option[2] = 00h / 195 + */ + return (self->option[offset] & (1 << bit_shift)); +} + + +static int +_sfp_update_attr_len_sm(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_sm, + self->eeprom_map_p->page_len_sm, + self->eeprom_map_p->offset_len_sm, + self->eeprom_map_p->length_len_sm, + &(self->len_sm), + "_common_update_attr_len_sm", + show_err); +} + + +static int +_sfp_update_attr_rate_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_rate_id, + self->eeprom_map_p->page_rate_id, + self->eeprom_map_p->offset_rate_id, + self->eeprom_map_p->length_rate_id, + &(self->rate_id), + "_sfp_update_attr_rate_id", + show_err); +} + + +static int +_sfp_update_attr_soft_rs0(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + self->eeprom_map_p->length_soft_rs0, + &(self->soft_rs0), + "_sfp_update_attr_soft_rs0", + show_err); +} + + +static int +_sfp_update_attr_soft_rs1(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + self->eeprom_map_p->length_soft_rs1, + &(self->soft_rs1), + "_sfp_update_attr_soft_rs1", + show_err); +} + + +int +_sfp_is_diag_support(struct transvr_obj_s *self){ + + uint8_t bit_mask = 0xC0; /* 1100 0000 */ + uint8_t en_val = 0x40; /* 0100 0000 */ + uint8_t checkval = (self->diag_type & bit_mask); + + if (checkval == en_val) { + return 1; + } + return 0; +} + + +static int +_sfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_sfp_update_attr_curr_temp", + show_err); +} + + +static int +_sfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_sfp_update_attr_curr_voltage", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_sfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_sfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_sfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_sfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_sfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_sfp_update_attr_rx_em", + show_err); +} + + +static int +_sfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_sfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_cdr(struct transvr_obj_s *self, + int show_err){ + if (self->type != TRANSVR_TYPE_QSFP_28){ + self->cdr = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + self->eeprom_map_p->length_cdr, + &(self->cdr), + "_common_update_attr_cdr", + show_err); +} + + +static int +_qsfg_update_attr_extbr(struct transvr_obj_s *self, + int show_err) { + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_extbr, + self->eeprom_map_p->page_extbr, + self->eeprom_map_p->offset_extbr, + self->eeprom_map_p->length_extbr, + &(self->extbr), + "_common_update_attr_extbr", + show_err); +} + + +static int +_qsfp_is_diag_support(struct transvr_obj_s *self, + int diag_type) { + /* Input Parm: diag_type + * => 1 : temperature + * => 2 : voltage + * => 3 : tx relate + * => 4 : rx relate + */ + uint8_t mask_b2 = 0x04; /* 0000 0100 */ + uint8_t mask_b3 = 0x08; /* 0000 1000 */ + + switch (diag_type) { + case 1: /* temperature */ + case 2: /* voltage */ + /* Direct access target, because of spec not defined */ + return 1; + case 3: + case 4: + /* [Note] + * Due to lot of transceiver vendor defined it not rigorously and + * consider of general support, we seem it as supported if there + * are bit-2 OR bit-3 defined by transceiver vendor. + */ + if ( ((self->diag_type & mask_b2) == mask_b2 ) || + ((self->diag_type & mask_b3) == mask_b3 ) ){ + return 1; + } + return 0; + default: + SWPS_INFO("%s: undefined diag_type:%d\n", + __func__, diag_type); + break; + } + return 0; +} + + +int +_qsfp_is_implement_tx_disable(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-4 + */ + int byte = 2; + int bit = 4; + return _common_get_option_value(self, byte, bit); +} + + +int +_qsfp_is_implement_tx_fault(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-3 + */ + int byte = 2; + int bit = 3; + return _common_get_option_value(self, byte, bit); +} + + +static int +_qsfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + int diag_type = 1; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_qsfp_update_attr_curr_temp", + show_err); +} + + +static int +_qsfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + int diag_type = 2; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_qsfp_update_attr_curr_voltage", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_qsfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_qsfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_qsfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 4; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_qsfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_qsfp_update_attr_soft_rx_los(struct transvr_obj_s *self, + int show_err){ + + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_los, + self->eeprom_map_p->page_rx_los, + self->eeprom_map_p->offset_rx_los, + self->eeprom_map_p->length_rx_los, + &(self->rx_los), + "_qsfp_update_attr_soft_rx_los", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_disable(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_disable(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_update_attr_soft_tx_disable", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_fault(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_fault(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_fault, + self->eeprom_map_p->page_tx_fault, + self->eeprom_map_p->offset_tx_fault, + self->eeprom_map_p->length_tx_fault, + &(self->tx_fault), + "_qsfp_update_attr_soft_tx_fault", + show_err); +} + + +static int +_qsfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_qsfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_rx_am(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + self->rx_am, + "_qsfp_update_attr_rx_am", + show_err); +} + + +static int +_qsfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_qsfp_update_attr_rx_em", + show_err); +} + + +int +_common_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = "err"; + + if (_common_update_attr_id(self, show_err) < 0) { + err_str = "_common_update_attr_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_extended_id(self, show_err) < 0) { + err_str = "_common_update_attr_extended_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_connector(self, show_err) < 0) { + err_str = "_common_update_attr_connector"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp_ext(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp_ext"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_name(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_name"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_pn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_pn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_rev(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_sn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_sn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_br(self, show_err) < 0) { + err_str = "_common_update_attr_br"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_smf(self, show_err) < 0) { + err_str = "_common_update_attr_len_smf"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om1(self, show_err) < 0) { + err_str = "_common_update_attr_len_om1"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om2(self, show_err) < 0) { + err_str = "_common_update_attr_len_om2"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om3(self, show_err) < 0) { + err_str = "_common_update_attr_len_om3"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om4(self, show_err) < 0) { + err_str = "_common_update_attr_len_om4"; + goto err_common_update_attr_all; + } + if (_common_update_attr_option(self, show_err) < 0) { + err_str = "_common_update_attr_option"; + goto err_common_update_attr_all; + } + if (_common_update_attr_comp_rev(self, show_err) < 0) { + err_str = "_common_update_attr_comp_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_diag_type(self, show_err) < 0) { + err_str = "_common_update_attr_diag_type"; + goto err_common_update_attr_all; + } + if (_common_update_attr_wavelength(self, show_err) < 0) { + err_str = "_common_update_attr_wavelength"; + goto err_common_update_attr_all; + } + return 0; + +err_common_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_sfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_len_sm(self, show_err) < 0) { + err_str = "_sfp_update_attr_len_sm"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_rate_id(self, show_err) < 0) { + err_str = "_sfp_update_attr_rate_id"; + goto err_sfp_update_attr_all; + } + if ((self->rate_id) > 0) { + if (_sfp_update_attr_soft_rs0(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs0"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_soft_rs1(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs1"; + goto err_sfp_update_attr_all; + } + } + return 0; + +err_sfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_qsfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_qsfp_update_attr_all; + } + if (_qsfg_update_attr_extbr(self, show_err) < 0) { + err_str = "_qsfg_update_attr_extbr"; + goto err_qsfp_update_attr_all; + } + if (self->type == TRANSVR_TYPE_QSFP_28) { + if (_qsfp_update_attr_cdr(self, 1) < 0) { + err_str = "_qsfp_update_attr_cdr"; + goto err_qsfp_update_attr_all; + } + } + return 0; + +err_qsfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +/* ========== Object functions for common type ========== + */ +int +_common_count_temp(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + int sign = 0; + int high = 0; + int low = 0; + int lmax = 8; + + /* Count high */ + sign = get_bit(high_byte,7); + SWP_BIT_CLEAR(high_byte, 7); + high = (int)high_byte; + if (sign == 1) { + high = 0 - high; + } + /* Count low */ + low = (get_bit(low_byte, 7) * 500); + low += (get_bit(low_byte, 6) * 250); + low += (get_bit(low_byte, 5) * 125); + low += (get_bit(low_byte, 4) * 62); + low = (low / 100); + /* Integrate High and Low */ + return snprintf(buf_p, lmax, "%d.%d\n", high, low); +} + + +int +_common_count_voltage(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note]: + * Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts. Practical + * considerations to be defined by transceiver manufacturer will + * tend to limit the actual bounds of the supply voltage measurement. + * Accuracy is vendor specific but must be better than 3% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. Note that in some transceivers, transmitter supply + * voltage and receiver supply voltage are isolated. In that case, + * only one supply is monitored. Refer to the device specification + * for more detail. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 100 uV (1mV=1000uV) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 Volt */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_tx_bias(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 2 uA (1mA=1000uA) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total*2) / 1000); + val_f = (((total*2) - (val_i*1000)) / 100); + /* Return Unit: 1 mA */ + return snprintf(buf_p, lmax, "%d.%01d\n", val_i, val_f); +} + + +int +_common_count_tx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_rx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_wavelength(struct transvr_obj_s *self, + uint8_t high_byte, + uint8_t low_byte) { + /* [Note] + * SFP : uint 1 um. + * QSFP: unit 0.05 um. + */ + int total = 0; + + total = transform_word_to_int(high_byte, low_byte); + switch (self->type) { + case TRANSVR_TYPE_SFP: + return total; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + return (total/20); + + default: + break; + } + return ERR_TRANSVR_UNDEFINED; +} + + +int +common_get_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_id, + "common_get_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->id; +} + + +int +common_get_ext_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "common_get_ext_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->ext_id; +} + + +int +common_get_connector(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_connector, + "common_get_connector"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->connector; +} + + +int +common_get_vendor_name(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_name, + "common_get_vendor_name"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); +} + + +int +common_get_vendor_pn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_pn, + "common_get_vendor_pn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); +} + + +int +common_get_vendor_rev(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_rev, + "common_get_vendor_rev"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); +} + + +int +common_get_vendor_sn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_sn, + "common_get_vendor_sn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); +} + + +int +common_get_br(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return (int)self->br; + } + err = _check_by_mode(self, + &_common_update_attr_br, + "common_get_br"); + if (err < 0){ + return err; + } + /* Transform to INT to show error case */ + return (int)self->br; +} + + +int +common_get_len_smf(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_smf; + } + err = _check_by_mode(self, + &_common_update_attr_len_smf, + "common_get_len_smf"); + if (err < 0){ + return err; + } + return self->len_smf; +} + + +int +common_get_len_om1(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om1; + } + err = _check_by_mode(self, + &_common_update_attr_len_om1, + "common_get_len_om1"); + if (err < 0){ + return err; + } + return self->len_om1; +} + + +int +common_get_len_om2(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om2; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om2, + "common_get_len_om2"); + if (err < 0){ + return err; + } + return self->len_om2; +} + + +int +common_get_len_om3(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om3; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om3, + "common_get_len_om3"); + if (err < 0){ + return err; + } + return self->len_om3; +} + + +int +common_get_len_om4(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om4; + } + err = _check_by_mode(self, + &_common_update_attr_len_om4, + "common_get_len_om4"); + if (err < 0){ + return err; + } + return self->len_om4; +} + + +int +common_get_comp_extended(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp_ext, + "common_get_comp_extended"); + if (err_code < 0){ + return err_code; + } + return self->transvr_comp_ext; +} + + +int +common_get_comp_rev(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_comp_rev, + "common_get_comp_rev"); + if (err_code < 0){ + return err_code; + } + return self->comp_rev; +} + + +int +common_get_info(struct transvr_obj_s *self){ + + if (self->state != STATE_TRANSVR_CONNECTED) { + return self->state; + } + return self->info; +} + + +int +_common_get_if_lane(struct transvr_obj_s *self, + char *result){ + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_M_STR); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + memset(tmp_str, 0, LEN_TRANSVR_M_STR); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_M_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_M_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_M_STR); + } + if (i == 0) { + return EVENT_TRANSVR_TASK_FAIL; + } + return 0; +} + + +int +common_get_if_lane(struct transvr_obj_s *self, + char *buf_p){ + + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + if (self->ioexp_obj_p->state != STATE_IOEXP_NORMAL) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n", ERR_TRANSVR_ABNORMAL); + } + if (_common_get_if_lane(self, tmp_str) < 0) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n" ,ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%s\n" ,tmp_str); +} + + +int +sfp_get_len_sm(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_len_sm, + "sfp_get_len_sm"); + if (err_code < 0){ + return err_code; + } + return self->len_sm; +} + + +int +sfp_get_rate_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_rate_id, + "sfp_get_rate_id"); + if (err_code < 0){ + return err_code; + } + return self->rate_id; +} + + +int +sfp_get_soft_rs0(struct transvr_obj_s *self){ + /* Note: + * SFP Soft Rate_Select Select [aka. "RS(0)"] address + * A2h, offset: 110, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs0, + "sfp_get_soft_rs0"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs0 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_soft_rs1(struct transvr_obj_s *self){ + /* Note: + * SFP Soft RS(1) Select address + * A2h, offset: 118, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs1, + "sfp_get_soft_rs1"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs1 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_temp, + "sfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +sfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_voltage, + "sfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +sfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_bias, + "sfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _common_count_tx_bias(self->curr_tx_bias[0], + self->curr_tx_bias[1], + buf_p); +} + + +int +sfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_power, + "sfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_tx_power(self->curr_tx_power[0], + self->curr_tx_power[1], + buf_p); +} + + +int +sfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_rx_power, + "sfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_rx_power(self->curr_rx_power[0], + self->curr_rx_power[1], + buf_p); +} + + +int +sfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->rx_em[0]); +} + + +int +sfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->tx_eq[0]); +} + + +int +_sfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: A0h / 36 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +__sfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* SFP Specification Compliance: A0h / 3-10 + * transvr_comp[0-7] = 3 - 10 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_get_comp_10g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[0] = address A0h / 3 + * + * 3 7: 10G Base-ER + * 3 6: 10GBASE-LRM + * 3 5: 10GBASE-LR + * 3 4: 10GBASE-SR + */ + int bitmask = 0xf0; /* 11110000 */ + return (__sfp_get_comp_attr(self, 0) & bitmask); +} + + +int +_sfp_get_comp_1g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[3] = address A0h / 6 + * + * 6 7: BASE-PX *3 + * 6 6: BASE-BX10 *3 + * 6 5: 100BASE-FX + * 6 4: 100BASE-LX/LX10 + * 6 3: 1000BASE-T + * 6 2: 1000BASE-CX + * 6 1: 1000BASE-LX *3 + * 6 0: 1000BASE-SX + */ + return __sfp_get_comp_attr(self, 3); +} + + +int +_sfp_get_cable_tech(struct transvr_obj_s *self) { + /* transvr_comp[5] = address A0h / 8 + * + * 8 3: Active Cable *8 + * 8 2: Passive Cable *8 + */ + int bitmask = 0x0c; /* 00001100 */ + return (__sfp_get_comp_attr(self, 5) & bitmask); +} + + +int +sfp_get_comp_eth_1(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_1"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_1g_eth_comp(self); +} + + +int +sfp_get_comp_eth_10(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_10"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_10g_eth_comp(self); +} + + +int +_sfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: A0h / 2 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Note] Optical and Cable Variants Specification Compliance (SFF-8472) + * [Addr] A0h, Bytes 60-61 + * [Note] For optical variants, as defined by having zero's in A0h Byte 8 + * bits 2 and 3, Bytes 60 and 61 denote nominal transmitter output + * wavelength at room temperature. 16 bit value with byte 60 as high + * order byte and byte 61 as low order byte. The laser wavelength is + * equal to the 16 bit integer value in nm. This field allows the user + * to read the laser wavelength directly, so it is not necessary to + * infer it from the Transceiver Codes A0h Bytes 3 to 10 (see Table + * 5-3). This also allows specification of wavelengths not covered + * in the Transceiver Codes, such as those used in coarse WDM systems. + * + * For passive and active cable variants, a value of 00h for both A0h + * Byte 60 and Byte 61 denotes laser wavelength or cable specification + * compliance is unspecified. + */ + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +int +sfp_get_1g_rj45_extphy_offset(struct transvr_obj_s *self, char *buf) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%02x\n", self->extphy_offset); +} + + +int +sfp_get_1g_rj45_extphy_reg(struct transvr_obj_s *self, char *buf) { + + int i = 0; + int ret = 0; + int retry = 3; + int delay = 200; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; ii2c_client_p, self->extphy_offset); + if (ret >=0) { + goto ok_sfp_get_1g_rj45_extphy_reg; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; + +ok_sfp_get_1g_rj45_extphy_reg: + ret = ((ret & 0x00ff) << 8) | ((ret & 0xff00) >> 8); + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%04x\n", ret); +} + + +int +__qsfp_get_power_cls(struct transvr_obj_s *self, + int direct_access){ + + int err_code; + uint8_t detect_val; + + /* Detect and Update power class attribute */ + if (direct_access){ + err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_power_cls"); + } else { + err_code = self->ext_id; + } + if (err_code <0){ + return err_code; + } + if (err_code == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data */ + detect_val = self->ext_id; + SWP_BIT_CLEAR(detect_val, 2); /* Bit2: CDR RX present */ + SWP_BIT_CLEAR(detect_val, 3); /* Bit3: CDR TX present */ + SWP_BIT_CLEAR(detect_val, 4); /* Bit4: CLEI present */ + SWP_BIT_CLEAR(detect_val, 5); /* Bit5: reserved */ + /* Identify power class */ + switch (detect_val) { + case 0: /* Class_1: 00000000 */ + return 1; + case 64: /* Class_2: 01000000 */ + return 2; + case 128: /* Class_3: 10000000 */ + return 3; + case 192: /* Class_4: 11000000 */ + return 4; + case 1: /* Class_5: 00000001 */ + case 193: /* Class_5: 11000001 */ + return 5; + case 2: /* Class_6: 00000010 */ + case 194: /* Class_6: 11000010 */ + return 6; + case 3: /* Class_7: 00000011 */ + case 195: /* Class_7: 11000011 */ + return 7; + default: + break; + } + SWPS_INFO("%s: Detect undefined power class:%d\n", __func__, detect_val); + return ERR_TRANSVR_UNDEFINED; +} + + +int +qsfp_get_power_cls(struct transvr_obj_s *self) { + return __qsfp_get_power_cls(self, 1); +} + + +int +__qsfp_get_cdr_present(struct transvr_obj_s *self, + int direct_access){ + + int retval; + int BIT_SHIFT = 2; + int BIT_MASK = 0x3; + + /* Detect and Update power class attribute */ + if (direct_access) { + retval = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_cdr_present"); + if (retval < 0){ + return retval; + } + } + retval = self->ext_id; + if (retval == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data and return */ + return (int)(retval >> BIT_SHIFT & BIT_MASK); +} + + +int +qsfp_get_cdr_present(struct transvr_obj_s *self) { + return __qsfp_get_cdr_present(self, 1); +} + + +int +qsfp_get_cdr(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + "qsfp_get_cdr"); + if (err_code <0){ + return err_code; + } + + return self->cdr; +} + + +int +__qsfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* QSFP Specification Compliance: 00h / 131-138 + * transvr_comp[0-7] = 131 - 138 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_get_comp_10_40_100_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[0] = address 00h / 131 + * + * 131 7: Extended: See section 6.3.23. The Extended Specification Compliance + * Codes are maintained in the Transceiver Management section of SFF- + * 8024. + * 131 6: 10GBASE-LRM + * 131 5: 10GBASE-LR + * 131 4: 10GBASE-SR + * 131 3: 40GBASE-CR4 + * 131 2: 40GBASE-SR4 + * 131 1: 40GBASE-LR4 + * 131 0: 40G Active Cable (XLPPI) + */ + return __qsfp_get_comp_attr(self, 0); +} + + +int +_qsfp_get_comp_sonet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 132 7-3: Reserved + * 132 2: OC 48, long reach + * 132 1: OC 48, intermediate reach + * 132 0: OC 48 short reach + */ + return __qsfp_get_comp_attr(self, 1); +} + + +int +_qsfp_get_comp_sas_sata(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 133 7: SAS 24.0 Gb/s + * 133 6: SAS 12.0 Gb/s + * 133 5: SAS 6.0 Gb/s + * 133 4: SAS 3.0 Gb/s + * 133 3-0: Reserved + */ + return __qsfp_get_comp_attr(self, 2); +} + + +int +_qsfp_get_comp_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 134 7-4: Reserved + * 134 3: 1000BASE-T + * 134 2: 1000BASE-CX + * 134 1: 1000BASE-LX + * 134 0: 1000BASE-SX + */ + return __qsfp_get_comp_attr(self, 3); +} + + +int +_qsfp_get_comp_fc_link_length(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 7: Very long distance (V) + * 135 6: Short distance (S) + * 135 5: Intermediate distance (I) + * 135 4: Long distance (L) + * 135 3: Medium (M) + */ + int mask = 0xFC; /* 11111100 */ + return (__qsfp_get_comp_attr(self, 4) & mask); +} + + +int +_qsfp_get_comp_fc_trans_tech(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 2: Reserved + * 135 1: Longwave laser (LC) + * 135 0: Electrical inter-enclosure (EL) + * + * 136 7: Electrical intra-enclosure + * 136 6: Shortwave laser w/o OFC (SN) + * 136 5: Shortwave laser w OFC (SL) + * 136 4: Longwave Laser (LL) + * 136 3-0: Reserved + * + * return value = [bit 8-15:addr 135][bit 0-7:addr 136] + */ + int mask_135 = 7; /* 00000111 */ + int val_135 = (__qsfp_get_comp_attr(self, 4) & mask_135); + int val_136 = __qsfp_get_comp_attr(self, 5); + return ((val_135 << 7) + val_136); +} + + +int +_qsfp_get_comp_fc_trans_media(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 137 7: Twin Axial Pair (TW) + * 137 6: Shielded Twisted Pair (TP) + * 137 5: Miniature Coax (MI) + * 137 4: Video Coax (TV) + * 137 3: Multi-mode 62.5 m (M6) + * 137 2: Multi-mode 50 m (M5) + * 137 1: Multi-mode 50 um (OM3) + * 137 0: Single Mode (SM) + */ + return __qsfp_get_comp_attr(self, 6); +} + + +int +_qsfp_get_comp_fc_speed(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 138 7: 1200 MBps (per channel) + * 138 6: 800 MBps + * 138 5: 1600 MBps (per channel) + * 138 4: 400 MBps + * 138 3: 3200 MBps (per channel) + * 138 2: 200 MBps + * 138 1: Extended: See section 6.3.23. The Extended Specification + * Compliance Codes are maintained in the Transceiver Management + * section of SFF-8024. + * 138 0: 100 MBps + */ + return __qsfp_get_comp_attr(self, 7); +} + + +int +_qsfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: 00h / 192 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_comp_eth(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_eth"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_ethernet(self); +} + + +int +qsfp_get_comp_10_40(struct transvr_obj_s *self) { + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_10_40"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_10_40_100_ethernet(self); +} + + +int +_qsfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: 00h / 130 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_temp, + "qsfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +qsfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_voltage, + "qsfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +qsfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->tx_eq[0], self->tx_eq[1]); +} + + +int +qsfp_get_transvr_rx_am(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_get_transvr_rx_am"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_am[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_am[0], self->rx_am[1]); +} + + +int +qsfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_em[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_em[0], self->rx_em[1]); +} + + +int +_qsfp_get_channel_diag(uint8_t *data_array, + int (*count_func)(uint8_t high_byte, uint8_t low_byte, char *buf_p), + char *ch_name, + char *result_p) { + int i, high, low; + int len_max = 128; + char ch_buf[4][16] = { DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL }; + + for (i=0; i<4; i++) { + high = (i*2); + low = ((i*2) + 1); + count_func(data_array[high], data_array[low], ch_buf[i]); + } + return snprintf(result_p, len_max, + "%s-%d:%s%s-%d:%s%s-%d:%s%s-%d:%s", + ch_name, 1, ch_buf[0], + ch_name, 2, ch_buf[1], + ch_name, 3, ch_buf[2], + ch_name, 4, ch_buf[3]); +} + + +int +qsfp_get_soft_rx_los(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_rx_los, + "qsfp_get_soft_rx_los"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->rx_los & mask)); +} + + +int +qsfp_get_soft_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_get_soft_tx_disable"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_disable & mask)); +} + + +int +qsfp_get_soft_tx_fault(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_fault, + "qsfp_get_soft_tx_fault"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_fault & mask)); +} + + +int +qsfp_get_auto_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + if (self->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "%d\n", ERR_TRANSVR_FUNC_DISABLE); + } + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "0x%02x\n", self->auto_tx_disable); +} + + +int +qsfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_bias, + "qsfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _qsfp_get_channel_diag(self->curr_tx_bias, + _common_count_tx_bias, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_power, + "qsfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_tx_power, + _common_count_tx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "RX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_rx_power, + "qsfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_rx_power, + _common_count_rx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Desc] Wavelength or Copper Cable Attenuation (SFF-8636) + * [Addr] 00h 186-187 + * [Note] + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is + * a 16-bit hex value with Byte 186 as high order byte and Byte 187 as + * low order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. + * If the free side device is identified as copper cable these registers will + * be used to define the cable attenuation. An indication of 0 dB attenuation + * refers to the case where the attenuation is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +/* Public Function for Setup Features + */ +static int +__sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + uint8_t update_val = (*attr_p); + + switch (input_val) { + case 0: + SWP_BIT_CLEAR(update_val, bit_shift); + break; + case 1: + SWP_BIT_SET(update_val, bit_shift); + break; + default: + retval = ERR_TRANSVR_UNEXCPT; + err_code = ERR_TRANSVR_UNEXCPT; + err_msg = "Exception occurs"; + goto err_private_sfp_set_soft_rs_1; + } + err_code = _common_set_uint8_attr(self, + address, + page, + offset, + update_val, + attr_p, + caller, + show_err); + if (err_code < 0) { + retval = err_code; + err_msg = "Write data via i2c fail!"; + goto err_private_sfp_set_soft_rs_1; + } + (*attr_p) = update_val; + return 0; + +err_private_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +static int +_sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + /* Check input value */ + if ((input_val != 0) && (input_val != 1)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + switch (err_code) { + case 0: + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "Not support this feature"; + break; + case ERR_TRANSVR_UNINIT: + retval = ERR_TRANSVR_UNINIT; + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + retval = ERR_TRANSVR_UNPLUGGED; + err_msg = "Transceiver unplugged!"; + break; + default: + retval = err_code; + err_msg = "Check Rate_ID fail!"; + break; + } + goto err_common_sfp_set_soft_rs_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + attr_update_func, + caller); + if ( (err_code < 0) || + ((*attr_p) == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Generate and update value */ + return __sfp_set_soft_rs(self, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + +err_common_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +sfp_set_soft_rs0(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(0)"] address + * A2h, offset: 110, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + bit_shift, + &_sfp_update_attr_soft_rs0, + &(self->soft_rs0), + "sfp_set_soft_rs0", + show_err); +} + + +int +sfp_set_soft_rs1(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(1)"] address + * A2h, offset: 118, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + bit_shift, + &_sfp_update_attr_soft_rs1, + &(self->soft_rs1), + "sfp_set_soft_rs1", + show_err); +} + + +int +__sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_tx_eq; + } + setv = (uint8_t)input; + if (self->tx_eq[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + setv, + &(self->tx_eq[0]), + "_sfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_tx_eq; + } + return 0; + +err_sfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; itx_eq[0]; + if (_sfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if (self->tx_eq[0] == tmp){ + return 0; + } + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +sfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_tx_eq(self, input, 1); +} + + +int +__sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_rx_em; + } + setv = (uint8_t)input; + if (self->rx_em[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + setv, + &(self->rx_em[0]), + "_sfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_rx_em; + } + return 0; + +err_sfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; irx_em[0]; + if (_sfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if (self->rx_em[0] == tmp){ + return 0; + } + } + return -1; +} + + +int +sfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_rx_em(self, input, 1); +} + + +int +sfp_set_1g_rj45_extphy_offset(struct transvr_obj_s *self, + int input) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xff)) { + return ERR_TRANSVR_BADINPUT; + } + self->extphy_offset = (uint8_t)input; + return 0; +} + + +int +sfp_set_1g_rj45_extphy_reg(struct transvr_obj_s *self, + int input) { + + int i = 0; + int retry = 3; + int delay = 200; + uint16_t tmp = 0; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xffff)) { + return ERR_TRANSVR_BADINPUT; + } + tmp = ((input & 0x00ff) << 8) | ((input & 0xff00) >> 8); + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; i<=retry; i++) { + if (i2c_smbus_write_word_data(self->i2c_client_p, + self->extphy_offset, + tmp) >= 0) { + return 0; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; +} + + +static int +__qsfp_set_cdr(struct transvr_obj_s *self, + int input_val, + int show_err) { + + uint8_t update_val; + int CDR_FEATURE_SUPPORTED = 0x3; + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_name = "__qsfp_set_cdr"; + + /* Check input value */ + if ((input_val < 0) || (input_val > 0xff)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_qsfp_set_cdr_1; + } + update_val = (uint8_t)input_val; + /* Check CDR supported by transceiver */ + err_code = qsfp_get_cdr_present(self); + if (err_code < 0) { + retval = err_code; + switch (err_code) { + case ERR_TRANSVR_UNINIT: + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + err_msg = "Transceiver unplugged!"; + break; + default: + err_msg = "Check CDR present fail!"; + break; + } + goto err_qsfp_set_cdr_1; + } + if (err_code != CDR_FEATURE_SUPPORTED) { + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "This transceiver not support CDR!"; + goto err_qsfp_set_cdr_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + func_name); + if ( (err_code < 0) || + (self->cdr == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_qsfp_set_cdr_1; + } + /* Write input value to transceiver */ + return _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + update_val, + &(self->cdr), + func_name, + show_err); + +err_qsfp_set_cdr_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +qsfp_set_cdr(struct transvr_obj_s *self, + int input_val) { + return __qsfp_set_cdr(self, input_val, 1); +} + + +int +qsfp_set_soft_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int show_err = 1; + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + int update_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_soft_tx_disable"); + if (retval < 0) { + snprintf(err_msg, 63, "Not ready. err:%d", retval); + goto err_qsfp_set_soft_tx_disable; + } + if ((input_val > in_max) || + (input_val < in_min) ){ + retval = ERR_TRANSVR_BADINPUT; + snprintf(err_msg, 63, "Input value:%d incorrect!", input_val); + goto err_qsfp_set_soft_tx_disable; + } + if ((self->tx_disable & 0x0f) == input_val) { + return 0; + } + update_val = ((self->tx_disable & 0xf0) & input_val); + retval = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + input_val, + &(self->tx_disable), + "qsfp_set_tx_disable", + show_err); + if (retval < 0) { + snprintf(err_msg, 63, "_common_set_uint8_attr:%d fail!", retval); + goto err_qsfp_set_soft_tx_disable; + } + return 0; + +err_qsfp_set_soft_tx_disable: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return retval; +} + + +int +_qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + uint8_t update) { + + uint8_t tx_enable = 0x0; + int show_e = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Handle timing issues */ + if (update != tx_enable) { + /* Note: + * Because there are some txvr has timing issues, + * therefore we need to execute reset cycle first. + * (enable -> other settings) + */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + tx_enable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set reset value fail"; + goto err_qsfp_set_auto_tx_disable; + } + mdelay(10); + } + /* Setup target value */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->auto_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set target value fail"; + goto err_qsfp_set_auto_tx_disable; + } + /* Check and update */ + err = _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C get value fail"; + goto err_qsfp_set_auto_tx_disable; + } + if (self->tx_disable != update) { + emsg = "data not become effective"; + goto err_qsfp_set_auto_tx_disable; + } + return 0; + +err_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s\n", + __func__, emsg, self->swp_name); + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Update settings*/ + if (input_val == VAL_TRANSVR_FUNCTION_DISABLE) { + emsg = "User disable auto tx_disable"; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + goto out_qsfp_set_auto_tx_disable; + } + if ((input_val > in_max) || (input_val < in_min) ){ + SWPS_INFO("%s: Input value:%d incorrect! :%s\n", + __func__, input_val, self->swp_name); + return ERR_TRANSVR_BADINPUT; + } + self->auto_tx_disable = input_val; + /* Check current soft tx_disable */ + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_auto_tx_disable"); + switch (retval) { + case 0: + break; + case ERR_TRANSVR_UNPLUGGED: + emsg = "Doesn't need to update"; + goto out_qsfp_set_auto_tx_disable; + default: + SWPS_INFO("%s: setup fail :%d :%s\n", + __func__, retval, self->swp_name); + return retval; + } + return _qsfp_set_auto_tx_disable(self, input_val); + +out_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s :%d\n :%d", + __func__, emsg, self->swp_name, input_val, retval); + return 0; +} + + +int +__qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_tx_eq; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->tx_eq[0] == setv[0]) && + (self->tx_eq[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + setv, + self->tx_eq, + "_qsfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_tx_eq; + } + return 0; + +err_qsfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; itx_eq[0]; + tmp[1] = self->tx_eq[1]; + if (_qsfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if ((self->tx_eq[0] == tmp[0]) && + (self->tx_eq[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_tx_eq(self, input, 1); +} + + +int +__qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_am; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_am[0] == setv[0]) && + (self->rx_am[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + setv, + self->rx_am, + "_qsfp_set_rx_am", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_am; + } + return 0; + +err_qsfp_set_rx_am: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_am[0]; + tmp[1] = self->rx_am[1]; + if (_qsfp_update_attr_rx_am(self, show_e) < 0){ + continue; + } + if ((self->rx_am[0] == tmp[0]) && + (self->rx_am[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_am(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_set_rx_am"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_am(self, input, 1); +} + + +int +__qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_em; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_em[0] == setv[0]) && + (self->rx_em[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + setv, + self->rx_em, + "_qsfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_em; + } + return 0; + +err_qsfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_em[0]; + tmp[1] = self->rx_em[1]; + if (_qsfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if ((self->rx_em[0] == tmp[0]) && + (self->rx_em[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_em(self, input, 1); +} + + +int +common_transvr_dump(struct transvr_obj_s* self){ + + char *type_name = "Undefined"; + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + switch (self->type) { + case TRANSVR_TYPE_SFP: + type_name = STR_TRANSVR_SFP; + break; + case TRANSVR_TYPE_QSFP: + type_name = STR_TRANSVR_QSFP; + break; + case TRANSVR_TYPE_QSFP_PLUS: + type_name = STR_TRANSVR_QSFP_PLUS; + break; + case TRANSVR_TYPE_QSFP_28: + type_name = STR_TRANSVR_QSFP28; + break; + case TRANSVR_TYPE_FAKE: + type_name = "FAKE"; + goto ok_common_transvr_dump; + case TRANSVR_TYPE_UNPLUGGED: + type_name = "UNPLUGGED"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_INCONSISTENT: + type_name = "INCONSISTENT"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_ERROR: + type_name = "ERROR"; + goto err_common_transvr_dump; + + default: + type_name = "UNEXPECTED"; + goto err_common_transvr_dump; + } + printk(KERN_INFO "[SWPS] Dump %s information:\n", self->swp_name); + printk(KERN_INFO " |- :%s\n", type_name); + printk(KERN_INFO " |- :%s\n", self->vendor_name); + printk(KERN_INFO " |- :%s\n", self->vendor_pn); + printk(KERN_INFO " |- :%s\n", self->vendor_rev); + printk(KERN_INFO " |- :%s\n", self->vendor_sn); + printk(KERN_INFO " |- :0x%02x\n", self->br); + printk(KERN_INFO " |- :0x%02x\n", self->comp_rev); + printk(KERN_INFO " |- :%d\n", self->len_om1); + printk(KERN_INFO " |- :%d\n", self->len_om2); + printk(KERN_INFO " |- :%d\n", self->len_om3); + printk(KERN_INFO " |- :%d\n", self->len_om4); + return 0; + +ok_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return 0; + +err_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return -1; +} + + +int +sfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_sm); + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :0x%02x\n", self->rate_id); + return 0; +} + + +int +qsfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :Class_%d\n", __qsfp_get_power_cls(self, 0)); + return 0; +} + + +int +fake_transvr_dump(struct transvr_obj_s* self) { + + printk(KERN_INFO "[SWPS] Dump transceiver information: %s\n", self->swp_name); + printk(KERN_INFO " |- :FAKE\n"); + printk(KERN_INFO " |- :FAKE_VENDER_NAME\n"); + printk(KERN_INFO " |- :FAKE_VENDER_PN\n"); + printk(KERN_INFO " |- :FAKE_VENDER_REV\n"); + printk(KERN_INFO " |- :FAKE_VENDER_SN\n"); + printk(KERN_INFO " |- :0x99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " '- :0x99\n"); + return 0; +} + + +/* ========== Object functions for fake type ========== + */ +int +fake_transvr_update(struct transvr_obj_s *self, + int show_err){ + self->state = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +fake_get_binary(struct transvr_obj_s *self){ + return 1; +} + +int +fake_get_int(struct transvr_obj_s *self){ + return 99; +} + + +int +fake_get_hex(struct transvr_obj_s *self){ + return 0x0f; +} + + +int +fake_get_str(struct transvr_obj_s *self, char *buf) { + return snprintf(buf, 16, "fake_get_str\n"); +} + + +int +fake_set_int(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: %d\n", __func__, input); + return 0; +} + + +int +fake_set_hex(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: 0x%02x\n", __func__, input); + return 0; +} + + +/* ========== Object functions for unsupported ========== + */ +int +unsupported_get_func(struct transvr_obj_s *self){ + return ERR_TRANSVR_NOTSUPPORT; +} + + +int +unsupported_get_func2(struct transvr_obj_s *self, + char *buf_p) { + int len = snprintf(buf_p, 8, "%d\n", ERR_TRANSVR_NOTSUPPORT); + return len; +} + + +int +unsupported_set_func(struct transvr_obj_s *self, + int input_val){ + return ERR_TRANSVR_NOTSUPPORT; +} + + + +/* ========== Object functions for long term task ========== + * + * [Note] + * SWPS transceiver worker is likely the green-thread (coroutine). + * Due to resource and performance considerations. SWPS run all + * features in one kthread at the same time, and handle by it self. + */ + +/* For Transceiver Task Handling + */ +static struct transvr_worker_s * +transvr_task_get(struct transvr_obj_s *self, + char *func_name) { + + struct transvr_worker_s *curr_p = self->worker_p; + + while(curr_p != NULL){ + if (strcmp((curr_p->func_name), func_name) == 0 ) { + return curr_p; + } + curr_p = curr_p->next_p; + } + return NULL; +} + + +static struct transvr_worker_s* +transvr_task_creat(struct transvr_obj_s *self, + int (*main_task)(struct transvr_worker_s *task), + int (*post_task)(struct transvr_worker_s *task), + char *caller) { + + struct transvr_worker_s *task_p = NULL; + struct transvr_worker_s *curr_p = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check task not exist */ + task_p = transvr_task_get(self, caller); + if (task_p) { + snprintf(err_msg, sizeof(err_msg), "Task already created!"); + goto err_transvr_task_creat; + } + /* Create task worker */ + task_p = kzalloc(sizeof(struct transvr_worker_s), GFP_KERNEL); + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_transvr_task_creat; + } + /* Setup task data */ + task_p->transvr_p = self; + task_p->next_p = NULL; + task_p->trigger_time = 0; + task_p->retry = 1; + task_p->state = STATE_T_TASK_INIT; + task_p->main_task = main_task; + task_p->post_task = post_task; + task_p->p_data = NULL; + snprintf(task_p->func_name, sizeof(task_p->func_name), "%s", caller); + /* Setup Link List */ + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p->next_p != NULL) { + curr_p = curr_p->next_p; + } + curr_p->next_p = task_p; + task_p->pre_p = curr_p; + } else { + self->worker_p = task_p; + task_p->pre_p = NULL; + } + return task_p; + +err_transvr_task_creat: + SWPS_ERR("%s: %s :%s :%s\n", + __func__, err_msg, caller, self->swp_name); + return NULL; +} + + +static void +transvr_task_free_one(struct transvr_worker_s *task_p){ + + struct transvr_worker_s *pre_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (task_p) { + pre_p = task_p->pre_p; + next_p = task_p->next_p; + + if ((pre_p) && (next_p)) { + pre_p->next_p = next_p; + next_p->pre_p = pre_p; + + } else if ((!pre_p) && (next_p)) { + next_p->pre_p = NULL; + + } else if ((pre_p) && (!next_p)) { + pre_p->next_p = NULL; + + } else if ((!pre_p) && (!next_p)) { + task_p->transvr_p->worker_p = NULL; + } else { + SWPS_ERR("%s: Unexcept case!\n :%s", + __func__, task_p->transvr_p->swp_name); + } + kfree(task_p->p_data); + kfree(task_p); + } +} + + +static void +transvr_task_free_all(struct transvr_obj_s *self) { + + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p) { + next_p = curr_p->next_p; + transvr_task_free_one(curr_p); + curr_p = next_p; + } + self->worker_p = NULL; + } +} + + +static void +transvr_cache_free_all(struct transvr_obj_s *self) { + + memset(self->vendor_name, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_rev, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_pn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_sn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + self->extphy_offset = 0; +} + +static int +_transvr_task_run_main(struct transvr_worker_s *task_p) { + + int retval = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "main_task is NULL!"); + goto main_transvr_task_err; + } + if ((task_p->trigger_time) == 0){ + goto main_transvr_task_run; + } + if (time_before(jiffies, task_p->trigger_time)){ + goto main_transvr_task_wait; + } + goto main_transvr_task_run; + +main_transvr_task_run: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + task_p->retry -= 1; + } + retval = task_p->main_task(task_p); + if (retval < 0) { + if (task_p->retry > 0) { + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + } + goto main_transvr_task_identify; + +main_transvr_task_identify: + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + + case EVENT_TRANSVR_TASK_DONE: + task_p->state = STATE_T_TASK_DONE; + return EVENT_TRANSVR_TASK_DONE; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + +main_transvr_task_wait: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + +main_transvr_task_err: + task_p->state = STATE_T_TASK_FAIL; + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, retval, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_transvr_task_run_post(struct transvr_worker_s *task_p) { + + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if ((task_p->post_task) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + switch (task_p->state) { + case STATE_T_TASK_WAIT: + case STATE_T_TASK_INIT: + goto post_transvr_task_wait; + + case STATE_T_TASK_DONE: + case STATE_T_TASK_FAIL: + goto post_transvr_task_run; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Unexcept task state"); + goto post_transvr_task_err; + +post_transvr_task_run: + task_p->post_task(task_p); + return EVENT_TRANSVR_TASK_DONE; + +post_transvr_task_wait: + return EVENT_TRANSVR_TASK_WAIT; + +post_transvr_task_err: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, task_p->state, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_one(struct transvr_worker_s *task_p) { + + int retval_main = DEBUG_TRANSVR_INT_VAL; + int retval_post = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval_main = _transvr_task_run_main(task_p); + if (retval_main < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute main_task fail!"); + goto err_transvr_task_run_one; + } + retval_post = _transvr_task_run_post(task_p); + if (retval_post < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute post_task fail!"); + goto err_transvr_task_run_one; + } + return retval_main; + +err_transvr_task_run_one: + SWPS_INFO("%s: %s
:%d :%d :%s :%s\n", + __func__, err_msg, retval_main, retval_post, + task_p->func_name, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_all(struct transvr_obj_s *self) { + + int haserr = 0; + int retval = DEBUG_TRANSVR_INT_VAL; + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if ((self->worker_p) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + curr_p = self->worker_p; + while (curr_p != NULL) { + next_p = curr_p->next_p; + retval = transvr_task_run_one(curr_p); + if (curr_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + curr_p = next_p; + continue; + } + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + break; + case EVENT_TRANSVR_TASK_DONE: + transvr_task_free_one(curr_p); + break; + case EVENT_TRANSVR_TASK_FAIL: + + default: + haserr = 1; + transvr_task_free_one(curr_p); + break; + } + curr_p = next_p; + } + if (haserr) { + return EVENT_TRANSVR_TASK_FAIL; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +static void +transvr_task_set_delay(struct transvr_worker_s *task_p, + unsigned long delay_msec) { + + task_p->trigger_time = (jiffies + (delay_msec * (HZ/1000))); +} + + +static void +transvr_task_set_retry(struct transvr_worker_s *task_p, + unsigned long retry_times) { + + task_p->retry = retry_times; +} + + +/* For Transceiver Post Task + */ +int +taskfunc_post_do_nothing(struct transvr_worker_s *task_p) { + + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_post_handle_task_state(struct transvr_worker_s *task_p) { + + struct transvr_obj_s* tp = task_p->transvr_p; + + switch (task_p->state) { + case STATE_T_TASK_INIT: + case STATE_T_TASK_WAIT: + return EVENT_TRANSVR_TASK_WAIT; + + case STATE_T_TASK_DONE: + tp->state = STATE_TRANSVR_CONNECTED; + tp->send_uevent(tp, KOBJ_ADD); + return EVENT_TRANSVR_TASK_DONE; + + case STATE_T_TASK_FAIL: + tp->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_TASK_FAIL; + + default: + break; + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +/* For Transceiver Main Task + */ +int +_taskfunc_sfp_setup_soft_rs(struct transvr_worker_s *task_p, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller) { + + int show_err = 0; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_soft_rs"; + + err_code = _sfp_update_attr_soft_rs0(task_p->transvr_p, 0); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + err_code = __sfp_set_soft_rs(task_p->transvr_p, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_setup_soft_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_code); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +__taskfunc_sfp_setup_hard_rs(struct transvr_worker_s *task_p, + int input_val, + int (*get_func)(struct ioexp_obj_s *self, int virt_offset), + int (*set_func)(struct ioexp_obj_s *self, int virt_offset, int input_val)) { + + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + + err_val = get_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset); + + if (err_val < 0) { + if (err_val == ERR_IOEXP_NOTSUPPORT) { + return EVENT_TRANSVR_TASK_DONE; + } + err_str = "Get current hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + if (err_val == input_val) { + return EVENT_TRANSVR_TASK_DONE; + } + err_val = set_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_p_taskfunc_sfp_setup_hard_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_hard_rs0(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs0, + task_p->transvr_p->ioexp_obj_p->set_hard_rs0); +} + + +int +_taskfunc_sfp_setup_hard_rs1(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs1, + task_p->transvr_p->ioexp_obj_p->set_hard_rs1); +} + + +int +_taskfunc_sfp_setup_rs0(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs0"; + + err_val = _taskfunc_sfp_setup_hard_rs0(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs0, + task_p->transvr_p->eeprom_map_p->page_soft_rs0, + task_p->transvr_p->eeprom_map_p->offset_soft_rs0, + bit_shift, + &(task_p->transvr_p->soft_rs0), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs0_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs0(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_rs1(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs1"; + + err_val = _taskfunc_sfp_setup_hard_rs1(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs1, + task_p->transvr_p->eeprom_map_p->page_soft_rs1, + task_p->transvr_p->eeprom_map_p->offset_soft_rs1, + bit_shift, + &(task_p->transvr_p->soft_rs1), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs1_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs1(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_sfp_setup_SFF8431_case1(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs0(task_p, update_val); +} + + + +int +taskfunc_sfp_setup_SFF8431_case2(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs1(task_p, update_val); +} + + +int +taskfunc_sfp_setup_SFF8431_case3(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + int update_rs0 = 1; + int update_rs1 = 1; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _taskfunc_sfp_setup_rs0(task_p, update_rs0); + if (err_code < 0) { + return err_code; + } + return _taskfunc_sfp_setup_rs1(task_p, update_rs1); +} + + +int +taskfunc_sfp_handle_1g_rj45(struct transvr_worker_s *task_p) { + + /* Not all of platform support 0x56 for transceiver + * external PHY, Support list as below: + * => 1. Magnolia-PVT (PS: EVT & DVT not ready) + */ + int ext_phy_addr = 0x56; + int ext_phy_page = -1; + int ext_phy_offs = 0x11; + int ext_phy_len = 1; + int lstate_mask = 0x04; /* 00000100 */ + int show_err = 0; + int fail_retry = 5; + int fail_delay = 1000; /* msec */ + int err_code = DEBUG_TRANSVR_INT_VAL; + uint8_t detect_val = DEBUG_TRANSVR_HEX_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + int *tmp_p = NULL; + char *func_name = "taskfunc_sfp_handle_1g_rj45"; + + if (task_p->transvr_p->state != STATE_TRANSVR_CONNECTED) { + return EVENT_TRANSVR_TASK_DONE; + } + if ( (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000) && + (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000_up) ) { + goto err_taskfunc_sfp_handle_1g_rj45_1; + } + err_code = _common_update_uint8_attr(task_p->transvr_p, + ext_phy_addr, + ext_phy_page, + ext_phy_offs, + ext_phy_len, + &detect_val, + func_name, + show_err); + if ( (err_code < 0) || + (detect_val == DEBUG_TRANSVR_HEX_VAL) ) { + snprintf(err_str, sizeof(err_str), "Detect external link status fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + if ((detect_val & lstate_mask) == lstate_mask) { + goto ok_taskfunc_sfp_handle_1g_rj45_link_up; + } + goto ok_taskfunc_sfp_handle_1g_rj45_link_down; + +ok_taskfunc_sfp_handle_1g_rj45_link_up: + /* Filter out noise */ + if (!(task_p->p_data)) { + tmp_p = kzalloc(sizeof(int), GFP_KERNEL); + if (!tmp_p) { + snprintf(err_str, sizeof(err_str), "kzalloc p_data fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + *tmp_p = TRANSVR_CLASS_BASE_T_1000_up; + task_p->p_data = tmp_p; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + } + if ((*(int *)(task_p->p_data)) != TRANSVR_CLASS_BASE_T_1000_up) { + kfree(task_p->p_data); + task_p->p_data = NULL; + snprintf(err_str, sizeof(err_str), "Internal error"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + kfree(task_p->p_data); + task_p->p_data = NULL; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_link_down: + if (task_p->p_data) { + kfree(task_p->p_data); + task_p->p_data = NULL; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_done: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_1: + snprintf(err_str, sizeof(err_str), "Detect transceiver:%d not Base-T, remove task.", + task_p->transvr_p->info); + SWPS_INFO("%s: %s :%s\n", __func__, err_str, task_p->transvr_p->swp_name); + transvr_task_set_retry(task_p, 0); + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_2: + if (task_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, fail_retry); + } + if ((task_p->retry) == 0) { + /* Error case: + * => In this case, SWPS will stop external Link state monitor features + * and keeps transvr_p->info on TRANSVR_CLASS_BASE_T_1000_up. + * Upper layer will see it always Linkup that because of these type of + * transceiver has external phy, switch chip see it as Loopback transceiver. + */ + SWPS_WARN("%s can not access external PHY of Base-T SFP transceiver\n", + task_p->transvr_p->swp_name); + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + return EVENT_TRANSVR_TASK_DONE; + } else { + transvr_task_set_delay(task_p, fail_delay); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self, + int setup_val) { + + int curr_val = DEBUG_TRANSVR_INT_VAL; + int err_val = DEBUG_TRANSVR_INT_VAL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + if (io_no_init) { + + SWPS_INFO("%s no_io_init\n",__func__); + return EVENT_TRANSVR_TASK_DONE; + } + + curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset); + if (curr_val < 0){ + err_msg = "Get current value fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + if (curr_val == setup_val){ + return EVENT_TRANSVR_TASK_DONE; + } + err_val = self->ioexp_obj_p->set_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset, + setup_val); + if (err_val < 0){ + err_msg = "Setup power mode fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_qsfp_setup_power_mod_1: + SWPS_INFO("%s: %s :%d :%d :%d\n", + __func__, err_msg, err_val, curr_val, setup_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_qsfp_handle_tx_disable(struct transvr_worker_s *task_p) { + + int i = 0; + int retry = 5; + int delay_ms = 100; + + if (task_p->transvr_p->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return EVENT_TRANSVR_TASK_DONE; + } + if (!_qsfp_is_implement_tx_disable(task_p->transvr_p)) { + return EVENT_TRANSVR_TASK_DONE; + } + for (i=0; itransvr_p, + task_p->transvr_p->auto_tx_disable) + == EVENT_TRANSVR_TASK_DONE) { + goto ok_taskfunc_qsfp_handle_tx_disable; + } + mdelay(delay_ms); + } + SWPS_INFO("%s auto setup tx_disable:0x%02x fail.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_INIT_FAIL; + +ok_taskfunc_qsfp_handle_tx_disable: + SWPS_INFO("%s auto setup tx_disable:0x%02x ok.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_qsfp_set_hpmod(struct transvr_worker_s *task_p) { + + int err = DEBUG_TRANSVR_INT_VAL; + int HIGH_POWER_MODE = 0; + + /* Handle power mode */ + err = _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + HIGH_POWER_MODE); + if (err < 0) { + SWPS_INFO("%s: setup hpmod fail :%d :%s\n", + __func__, err, task_p->transvr_p->swp_name); + return err; + } + /* Handle auto tx_disable + * [Note] + * => Because there are some transceiver have timing issues or + * setup sequence issues, therefore we handle auto tx_disable + * after handle power mode. + */ + mdelay(100); + return taskfunc_qsfp_handle_tx_disable(task_p); +} + + +int +taskfunc_qsfp_set_lpmod(struct transvr_worker_s *task_p) { + + int LOW_POWER_MODE = 1; + return _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + LOW_POWER_MODE); +} + + +static int +initfunc_sfp_handle_multi_rate_mode(struct transvr_obj_s *self) { + + int task_retry = 3; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "sfp_handle_multi_rate_mode"; + struct transvr_worker_s *task_p = NULL; + + switch (self->rate_id) { + case 0x00: /* Unspecified */ + case 0x03: /* Unspecified */ + case 0x05: /* Unspecified */ + case 0x07: /* Unspecified */ + case 0x09: /* Unspecified */ + case 0x0B: /* Unspecified */ + case 0x0D: /* Unspecified */ + case 0x0F: /* Unspecified */ + goto sfp_handle_multi_rate_mode_4_unspecified; + + case 0x02: /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case1, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x04: /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case2, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x06: /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case3, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x01: /* SFF-8079 (4/2/1G Rate_Select & AS0/AS1) */ + err_str = "SFF-8079 (4/2/1G Rate_Select & AS0/AS1)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x08: /* FC-PI-5 (16/8/4G Rx Rate_select only) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Rx Rate_select only)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0A: /* FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0C: /* FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + */ + err_str = "FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0E: /* 10/8G Rx and Tx Rate_Select controlling the operation or + * locking modes of the internal signal conditioner, retimer + * or CDR, according to the logic table defined in Table 10-2, + * High Bit Rate (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = + * 8.5 Gb/s. In this mode, the default value of bit 110.3 (Soft + * Rate Select RS(0), Table 9-11) and of bit 118.3 (Soft Rate + * Select RS(1), Table 10-1) is 1. + */ + err_str = "cable type: 0x0E"; + goto sfp_handle_multi_rate_mode_4_not_support; + + default: + err_str = "cable type: UNKNOW"; + goto sfp_handle_multi_rate_mode_4_not_support; + } + +sfp_handle_multi_rate_mode_4_sff8431: + if (!task_p) { + err_str = "Create task fail!"; + goto sfp_handle_multi_rate_mode_4_fail_1; + } + transvr_task_set_retry(task_p, task_retry); + return EVENT_TRANSVR_TASK_WAIT; + +sfp_handle_multi_rate_mode_4_unspecified: + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_not_support: + SWPS_INFO("%s: Does not support %s :%s :0x%02x\n", + func_str, err_str, self->swp_name, self->rate_id); + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_fail_1: + SWPS_INFO("%s: %s :%s :0x%02x, :%d\n", + func_str, err_str, self->swp_name, self->rate_id, err_code); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +initfunc_sfp_handle_1g_rj45(struct transvr_obj_s *self) { + + struct transvr_worker_s *task_p = NULL; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_sfp_handle_1g_rj45"; + + + if (self->info == TRANSVR_CLASS_BASE_T_1000) { + task_p = transvr_task_creat(self, + taskfunc_sfp_handle_1g_rj45, + taskfunc_post_do_nothing, + func_str); + if (!task_p) { + snprintf(err_str, sizeof(err_str), "Create task fail"); + goto err_initfunc_sfp_handle_1g_rj45; + } + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_initfunc_sfp_handle_1g_rj45: + SWPS_INFO("%s: %s :%s :%d\n", + __func__, err_str, self->swp_name, detect_cls); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +initfunc_qsfp_handle_power_mode(struct transvr_obj_s *self) { + + int err_code = EVENT_TRANSVR_EXCEP_INIT; + int power_class = DEBUG_TRANSVR_INT_VAL; + int hpmod_retry = 3; + int lpower_config = 1; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + unsigned long hpmod_delay = 500; /* msec */ + struct transvr_worker_s *task_p = NULL; + + /* Handle power mode for IOEXP */ + power_class = __qsfp_get_power_cls(self, 0); + switch (power_class) { + case 1: /* Case: Low power mode (Class = 1) */ + err_code = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (err_code < 0){ + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + return EVENT_TRANSVR_TASK_DONE; + + case 2: /* Case: High power mode (Class > 1) */ + case 3: + case 4: + case 5: + case 6: + case 7: + task_p = transvr_task_creat(self, + taskfunc_qsfp_set_hpmod, + taskfunc_post_handle_task_state, + "transvr_init_qsfp"); + if (!task_p) { + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + transvr_task_set_retry(task_p, hpmod_retry); + transvr_task_set_delay(task_p, hpmod_delay); + return EVENT_TRANSVR_TASK_WAIT; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Exception case"); + goto err_initfunc_qsfp_handle_power_mode; + +err_initfunc_qsfp_handle_power_mode: + SWPS_INFO("%s: %s :%s \n", __func__, err_msg, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +initfunc_qsfp28_handle_cdr(struct transvr_obj_s *self) { + + uint8_t DEFAULT_VAL_CDR = 0xff; + int CDR_FUNC_EXISTED = 0x3; + int show_err = 1; + int err_val = EVENT_TRANSVR_TASK_FAIL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_qsfp28_handle_cdr"; + + err_val = __qsfp_get_cdr_present(self, 0); + if ( (err_val < 0) || + (err_val == DEBUG_TRANSVR_HEX_VAL) ) { + err_msg = "detect cdr_present fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + if (err_val == CDR_FUNC_EXISTED) { + err_val = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->offset_cdr, + DEFAULT_VAL_CDR, + &(self->cdr), + func_str, + show_err); + if (err_val < 0) { + err_msg = "set CDR fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_qsfp_handle_cdr_1: + SWPS_INFO("%s: %s :%d :%s\n", + func_str, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + +/* ========== Object functions for Final State Machine ========== + */ +int +is_plugged(struct transvr_obj_s *self){ + + int limit = 63; + int present = DEBUG_TRANSVR_INT_VAL; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p; + + if (!ioexp_p) { + snprintf(emsg, limit, "ioexp_p is null!"); + goto err_is_plugged_1; + } + present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset); + switch (present){ + case 0: + return 1; + case 1: + return 0; + case ERR_IOEXP_UNINIT: + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + default: + if (ioexp_p->state == STATE_IOEXP_INIT){ + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + } + break; + } + SWPS_INFO("%s: Exception case! :%d :%d\n", + __func__, present, ioexp_p->state); + return 0; + +err_is_plugged_1: + SWPS_DEBUG("%s: %s\n", __func__, emsg); + return 0; +} + + +static int +detect_transvr_type(struct transvr_obj_s* self){ + + int type = TRANSVR_TYPE_ERROR; + + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + type = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + + /* Case: 1. Wait transceiver I2C module. + * 2. Transceiver I2C module failure. + * Note: 1. SFF allow maximum transceiver initial time is 2 second. So, there + * are exist some case that we need to wait transceiver. + * For these case, we keeps status on "TRANSVR_TYPE_UNPLUGGED", than + * state machine will keep trace with it. + * 2. There exist some I2C failure case we need to handle. Such as user + * insert the failure transceiver, or any reason cause it abnormal. + */ + if (type < 0){ + switch (type) { + case -EIO: + SWPS_DEBUG("%s: %s smbus return:-5 (I/O error)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + case -ENXIO: + SWPS_DEBUG("%s: %s smbus return:-6 (No such device or address)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + default: + break; + } + SWPS_INFO("%s: %s unexpected smbus return:%d \n", + __func__, self->swp_name, type); + return TRANSVR_TYPE_ERROR; + } + /* Identify valid transceiver type */ + switch (type){ + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + break; + case TRANSVR_TYPE_UNKNOW_1: + case TRANSVR_TYPE_UNKNOW_2: + type = TRANSVR_TYPE_UNKNOW_2; + break; + default: + SWPS_DEBUG("%s: unknow type:0x%02x \n", __func__, type); + type = TRANSVR_TYPE_ERROR; + break; + } + return type; +} + + +static int +detect_transvr_state(struct transvr_obj_s *self, + int result[2]){ + /* [return] [result-0] [result-1] + * 0 STATE_TRANSVR_CONNECTED TRANSVR_TYPE_FAKE + * 0 STATE_TRANSVR_DISCONNECTED TRANSVR_TYPE_UNPLUGGED + * 0 STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * 0 STATE_TRANSVR_INIT / + * 0 STATE_TRANSVR_SWAPPED + * 0 STATE_TRANSVR_CONNECTED + * ERR_TRNASVR_BE_ISOLATED STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_I2C_CRASH STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_UNEXCPT STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_UNKNOW_1/2 + */ + result[0] = STATE_TRANSVR_UNEXCEPTED; /* For return state */ + result[1] = TRANSVR_TYPE_ERROR; /* For return type */ + + /* Case1: Fake type */ + if (self->type == TRANSVR_TYPE_FAKE){ + result[0] = STATE_TRANSVR_CONNECTED; + result[1] = TRANSVR_TYPE_FAKE; + return 0; + } + /* Case2: Transceiver unplugged */ + if (!is_plugged(self)){ + result[0] = STATE_TRANSVR_DISCONNECTED; + result[1] = TRANSVR_TYPE_UNPLUGGED; + return 0; + } + /* Case3: Transceiver be isolated */ + if (self->state == STATE_TRANSVR_ISOLATED){ + result[0] = STATE_TRANSVR_ISOLATED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case4: Transceiver plugged */ + result[1] = detect_transvr_type(self); + /* Case4.1: I2C topology crash + * Note : There are some I2C issues cause by transceiver/cables. + * We need to check topology status when user insert it. + * But in this step, we can't not ensure this is the issues + * port. So, it return the ERR_TRANSVR_I2C_CRASH, then upper + * layer will diagnostic I2C topology. + */ + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: %s detect I2C crash :%d\n", + __func__, self->swp_name, self->state); + result[0] = STATE_TRANSVR_UNEXCEPTED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_I2C_CRASH; + } + /* Case4.2: System initial not ready, + * Note : Sometime i2c channel or transceiver EEPROM will delay that will + * cause system in inconsistent state between EEPROM and IOEXP. + * In this case, SWP transceiver object keep state at LINK_DOWN + * to wait system ready. + * By the way, State Machine will handle these case. + */ + if (result[1] == TRANSVR_TYPE_UNPLUGGED){ + result[0] = STATE_TRANSVR_DISCONNECTED; + return 0; + } + /* Case4.3: Error transceiver type */ + if (result[1] == TRANSVR_TYPE_ERROR){ + result[0] = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s detect error type\n", __func__, self->swp_name); + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard!"); + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case3.3: Unknow transceiver type */ + if ((result[1] == TRANSVR_TYPE_UNKNOW_1) || + (result[1] == TRANSVR_TYPE_UNKNOW_2) ){ + result[0] = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + /* Case3.4: During initial process */ + if (self->state == STATE_TRANSVR_INIT){ + result[0] = STATE_TRANSVR_INIT; + return 0; + } + /* Case3.5: Transceiver be swapped */ + if (self->type != result[1]){ + result[0] = STATE_TRANSVR_SWAPPED; + return 0; + } + /* Case3.6: Link up state */ + result[0] = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +_sfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = _sfp_get_comp_extended(self); + + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_25G_AOC; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_25G_SR; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_25G_LR; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_25G_ER; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x0c: /* 25GBASE-CR CA-S */ + case 0x0d: /* 25GBASE-CR CA-N */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L1_25G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_10_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _sfp_get_comp_10g_eth_comp(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 10G Optical (x1) */ + if ((detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + } + if ((detect_val & 0x80) == 0x80) { /* 10000000 : 10GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_1g = 0x0b; + int upper_bound_1g = 0x1A; + int lower_bound_10g = 0x60; + int upper_bound_10g = 0x75; + int lower_bound_25g = 0xf0; + int upper_bound_25g = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 25G */ + if ((notmal_br >= lower_bound_25g) && + (notmal_br <= upper_bound_25g) ) { + return TRANSVR_CLASS_25G; + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + /* Check 1G */ + if ((notmal_br >= lower_bound_1g) && + (notmal_br <= upper_bound_1g) ) { + return TRANSVR_CLASS_1G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + int speed_br = DEBUG_TRANSVR_INT_VAL; + int speed_tmp = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + + speed_br = _sfp_detect_if_sp_by_br(self); + detect_val = _sfp_get_comp_1g_eth_comp(self); + + if (detect_val < 0) { + snprintf(err_str, sizeof(err_str), "Detect abnormal value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + } + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 1G (x1) */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 1000BASE-SX */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_SX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x02) == 0x02) { /* 00000010 : 1000BASE-LX *3 */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_LX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 1000BASE-CX */ + speed_tmp = TRANSVR_CLASS_COPPER_L1_1G; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + /* Case: 1000 Base-T (x1) */ + if ((detect_val & 0x08) == 0x08) { /* 00001000 : 1000BASE-T */ + return TRANSVR_CLASS_BASE_T_1000; + } + /* Case: 100 Base */ + if ( ((detect_val & 0x10) == 0x10) || /* 00010000 : 100BASE-LX/LX10 */ + ((detect_val & 0x20) == 0x20) || /* 00100000 : 100BASE-FX */ + ((detect_val & 0x40) == 0x40) || /* 01000000 : BASE-BX10 *3 */ + ((detect_val & 0x80) == 0x80) ){ /* 10000000 : BASE-PX *3 */ + return TRANSVR_CLASS_OPTICAL_100; + } + /* Case: ERROR */ + snprintf(err_str, sizeof(err_str), "Case:ERROR, value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + +ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g: + switch (speed_br) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_1G: + return speed_tmp; + case TRANSVR_CLASS_10G: + goto ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G; + } + +ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G: + switch (speed_tmp) { + case TRANSVR_CLASS_OPTICAL_1G_SX: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case TRANSVR_CLASS_OPTICAL_1G_LX: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case TRANSVR_CLASS_COPPER_L1_1G: + return TRANSVR_CLASS_COPPER_L1_10G; + default: + break; + } + snprintf(err_str, sizeof(err_str), "transfer_1to10 fail, speed:%d", speed_tmp); + goto err_p_sfp_detect_class_by_1g_ethernet; + +err_p_sfp_detect_class_by_1g_ethernet: + SWPS_INFO("%s: %s :%s", __func__, err_str, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int is_active = 0; + int conn_val = DEBUG_TRANSVR_INT_VAL; + int check_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _sfp_detect_if_sp_by_br(self); + conn_val = _sfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 */ + case 0x0d: /* MPO 2x16 */ + /* + * ToDo: Need verify Optical Pigtail + */ + goto ok_sfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + /* + * ToDo: Need check ACC use case + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x23: /* No separable connector */ + /* + * ToDo: Standard not clear, not all transceiver vendor + * have the same defined + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_check_active_passive: + check_val = _sfp_get_cable_tech(self); + switch(check_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_unknow; + case 0x04: /* Passive */ + goto ok_sfp_detect_class_by_feature_4_copper; + case 0x08: /* Active */ + is_active = 1; + goto ok_sfp_detect_class_by_feature_4_aoc; + default: + snprintf(err_msg, sizeof(err_msg), + "_sfp_get_cable_tech return Non define value:%d", + check_val); + break; + } + goto err_sfp_detect_class_by_feature_1; + +ok_sfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_25G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_25G_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_25G_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_25G_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_25G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + case TRANSVR_CLASS_1G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_1G_SX; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_1G_LX; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_1G_EX; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_1G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_sfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_OPTICAL_25G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_S_AOC; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_OPTICAL_1G_AOC; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_COPPER_L1_25G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L1_10G; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_COPPER_L1_1G; + default: + return TRANSVR_CLASS_COPPER; + } + +ok_sfp_detect_class_by_feature_4_unknow: + return TRANSVR_CLASS_UNSPECIFIED; + +err_sfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +sft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _sfp_detect_class_by_extend_comp(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 10G Compliance */ + detect_val = _sfp_detect_class_by_10_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 1G Compliance */ + detect_val = _sfp_detect_class_by_1g_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_BASE_T_1000: + case TRANSVR_CLASS_OPTICAL_100: + /* + * ToDo: Need Check 0.1G + */ + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_COPPER_L1_10G: + /* Transfer speed case + * => Example: Raycom 10G DAC + */ + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 1G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check by connector, br, wavelength */ + detect_val = _sfp_detect_class_by_feature(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_OPTICAL_1G: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_COPPER: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_COPPER_L1_10G: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined get_connector:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sft_detect_transceiver_class_1; + +err_sft_detect_transceiver_class_1: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_set_magnolia_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_magnolia_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_magnolia_if_type_1; + +err_sfp_set_magnolia_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_redwood_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SR); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_KR); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_redwood_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_redwood_if_type_1; + +err_sfp_set_redwood_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_lavender_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to 'LAV' looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_sfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = sft_detect_transvr_class(self); + switch (self->chipset_type) { + case CHIP_TYPE_MAGNOLIA: + return _sfp_set_magnolia_if_type(self, detect_cls, result); + + case CHIP_TYPE_MAPLE: + case CHIP_TYPE_REDWOOD: + return _sfp_set_redwood_if_type(self, detect_cls, result); + + case CHIP_TYPE_LAVENDER: + return _sfp_set_lavender_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_sfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = sft_detect_transvr_class(self); + switch(detect_val) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_SP_100); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + detect_val); + goto err_sfp_detect_if_speed_1; + } + /* Check by BR */ + detect_val = _sfp_detect_if_sp_by_br(self); + switch (detect_val) { + case TRANSVR_CLASS_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + default: + break; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_detect_if_speed_1; + +err_sfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_extended(self); + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_100G_AOC; + + case 0x06: /* 100G CWDM4 */ + case 0x09: /* Obsolete (assigned before 100G CWDM4 MSA required FEC) */ + case 0x17: /* 100G CLR4 */ + case 0x1A: /* 100GE-DWDM2 */ + return TRANSVR_CLASS_OPTICAL_100G; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_100G_SR4; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_100G_LR4; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_100G_ER4; + + case 0x07: /* 100G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_100G_PSM4; + + case 0x12: /* 40G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_40G; + + case 0x11: /* 4 x 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + + case 0x10: /* 40GBASE-ER4 */ + return TRANSVR_CLASS_OPTICAL_40G_ER4; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L4_100G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_class_by_10_40_100_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_10_40_100_ethernet(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 40G Optical */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 40G Active Cable (XLPPI) */ + return TRANSVR_CLASS_OPTICAL_40G_AOC; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 40GBASE-SR4 */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + } + if ( (detect_val & 0x02) == 0x02) { /* 00000010 : 40GBASE-LR4 */ + return TRANSVR_CLASS_OPTICAL_40G_LR4; + } + if ( (detect_val & 0x08) == 0x08) { /* 00001000 : 40GBASE-CR4 */ + return TRANSVR_CLASS_COPPER_L4_40G; + } + /* Case: 10G Optical */ + if ( (detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + } + /* Case: Extend Compliance */ + if ( ((detect_val & 0x80) == 0x80) ){ /* 10000000 : Use Extend Compliance */ + return TRANSVR_CLASS_EXTEND_COMP; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_10g = 0x10; + int upper_bound_10g = 0x25; + int lower_bound_40g = 0x60; + int upper_bound_40g = 0x75; + int lower_bound_100g = 0x60; + int upper_bound_100g = 0x75; + int used_extend_br = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + int extend_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 40G */ + if ((notmal_br >= lower_bound_40g) && + (notmal_br <= upper_bound_40g) ) { + return TRANSVR_CLASS_40G; + } + /* Check 100G */ + if (notmal_br == used_extend_br) { + extend_br = (int)(self->extbr); /* updated by update_all() */ + if ((extend_br >= lower_bound_100g) && + (extend_br <= upper_bound_100g) ) { + return TRANSVR_CLASS_100G; + } + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_qsfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int conn_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _qsfp_detect_if_sp_by_br(self); + conn_val = _qsfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 (Multifiber Parallel Optic) */ + case 0x0d: /* MPO 2x16 */ + goto ok_qsfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + goto ok_qsfp_detect_class_by_feature_4_copper; + case 0x23: /* No separable connector */ + if ((_qsfp_get_comp_fc_link_length(self) > 0) || + (_qsfp_get_comp_fc_trans_tech(self) > 0) || + (_qsfp_get_comp_fc_trans_media(self) > 0) || + (_qsfp_get_comp_fc_speed(self) > 0) ) { + goto ok_qsfp_detect_class_by_feature_4_aoc; + } + goto ok_qsfp_detect_class_by_feature_4_copper; + default: + snprintf(err_msg, sizeof(err_msg), + "_qsfp_get_connector_type return Non define value:%d", + conn_val); + goto err_qsfp_detect_class_by_feature_1; + } + return TRANSVR_CLASS_UNSPECIFIED; + +ok_qsfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_100G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_100G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_100G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_100G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_100G; + + case TRANSVR_CLASS_40G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_40G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_40G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_40G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_40G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_Q_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_OPTICAL_100G_AOC; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_OPTICAL_40G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_Q_AOC; + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_COPPER_L4_100G; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_COPPER_L4_40G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L4_10G; + default: + return TRANSVR_CLASS_COPPER; + } + +err_qsfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", + __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +qsft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _qsfp_detect_class_by_extend_comp(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_COPPER_L4_100G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check 10/40G/100G Ethernet Compliance */ + detect_val = _qsfp_detect_class_by_10_40_100_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_COPPER_L4_40G: + return detect_val; + case TRANSVR_CLASS_EXTEND_COMP: + /* Format incorrect case (We already checked the Extend + * Compliance is 0 + */ + snprintf(err_msg, sizeof(err_msg), + "Transceiver format incorrect"); + goto err_qsft_detect_transvr_class_1; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10/40/100:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check by Connector type, BR and wavelength */ + detect_val = _qsfp_detect_class_by_feature(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_COPPER_L4_100G: + case TRANSVR_CLASS_COPPER_L4_40G: + case TRANSVR_CLASS_COPPER_L4_10G: + case TRANSVR_CLASS_COPPER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined connector:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), + "Can not identify!"); + goto err_qsft_detect_transvr_class_1; + +err_qsft_detect_transvr_class_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_set_magnolia_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: LR4 or LR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: /* Need Check: ER4 or ER */ + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_magnolia_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_magnolia_if_type_1; + +err_qsfp_set_magnolia_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_redwood_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_KR4); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_magnolia_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_magnolia_if_type_1; + +err_qsfp_set_magnolia_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_lavender_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to 'LAV' looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_qsfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = qsft_detect_transvr_class(self); + switch (self->chipset_type) { + case CHIP_TYPE_MAGNOLIA: + return _qsfp_set_magnolia_if_type(self, detect_cls, result); + + case CHIP_TYPE_MAPLE: + case CHIP_TYPE_REDWOOD: + return _qsfp_set_redwood_if_type(self, detect_cls, result); + + case CHIP_TYPE_LAVENDER: + return _qsfp_set_lavender_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 8; + char tmp_result[8] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = qsft_detect_transvr_class(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G Copper */ + case TRANSVR_CLASS_COPPER_L4_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + break; + /* Copper */ + case TRANSVR_CLASS_COPPER: + break; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined class case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Check br and extbr */ + detect_val = _qsfp_detect_if_sp_by_br(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + case TRANSVR_CLASS_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined BR case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_detect_if_speed_1; + +err_qsfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_common_set_lane_map_str(struct transvr_obj_s* self, + char *result) { + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + char err_msg[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_L_STR); + snprintf(result, LEN_TRANSVR_L_STR, "%s=", TRANSVR_UEVENT_KEY_LANE); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + if (tmp_val > 256) { + snprintf(err_msg, sizeof(err_msg), + "detect abnormal value:%d", tmp_val); + goto err_common_set_lane_map_str_1; + } + memset(tmp_str, 0, sizeof(tmp_str)); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_L_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_L_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_L_STR); + } + if (i == 0) { + goto err_common_set_lane_map_str_2; + } + return 0; + +err_common_set_lane_map_str_1: + SWPS_INFO("%s: %s", __func__, err_msg); +err_common_set_lane_map_str_2: + snprintf(result, LEN_TRANSVR_L_STR, "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_common_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action, + int (*detect_if_type)(struct transvr_obj_s *self, char *result), + int (*detect_if_speed)(struct transvr_obj_s *self, char *result), + int send_anyway) { + + char *uevent_envp[4]; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + char tmp_str[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_1[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_2[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_3[64] = DEBUG_TRANSVR_STR_VAL; + + if (TRANSVR_UEVENT_ENABLE != 1) { + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_get_if_lane(self, tmp_str) < 0) { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + } else { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, tmp_str); + } + switch (u_action) { + case KOBJ_ADD: + /* Detect type */ + if (detect_if_type(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface type fail!"); + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, tmp_str); + uevent_envp[0] = tmp_str_1; + /* Detect speed */ + if (detect_if_speed(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface speed fail!"); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, tmp_str); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + case KOBJ_REMOVE: + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + default: + snprintf(err_msg, sizeof(err_msg), "kobject_action:%d not support", u_action); + goto private_common_send_uevent_4_fail; + } + snprintf(err_msg, sizeof(err_msg), "%s", "Exception case"); + goto private_common_send_uevent_4_fail; + +private_common_send_uevent_4_fail: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + if (send_anyway) { + goto private_common_send_uevent_4_send; + } + return ERR_TRANSVR_UEVENT_FAIL; + +private_common_send_uevent_4_send: + return kobject_uevent_env(&(self->transvr_dev_p->kobj), + u_action, + uevent_envp); +} + +int +sfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_sfp_detect_if_type, + &_sfp_detect_if_speed, + send_anyway); +} + + +int +qsfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_qsfp_detect_if_type, + &_qsfp_detect_if_speed, + send_anyway); +} + + +int +fake_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + + int err; + int detect_result[2]; + int current_state = STATE_TRANSVR_UNEXCEPTED; + int current_type = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_NEW) { + if (_transvr_init_handler(self) < 0){ + return ERR_TRANSVR_INIT_FAIL; + } + } + err = detect_transvr_state(self, detect_result); + if (err < 0) { + return err; + } + /* In Direct mode, driver only detect transceiver when user call driver interface + * which on sysfs. So it only need consider the state of Transceiver. + */ + current_state = detect_result[0]; + current_type = detect_result[1]; + + switch (current_state){ + + case STATE_TRANSVR_DISCONNECTED: /* Transceiver is not plugged */ + self->state = current_state; + self->type = current_type; + return ERR_TRANSVR_UNPLUGGED; + + case STATE_TRANSVR_INIT: /* Transceiver is plugged, system not ready */ + return ERR_TRANSVR_UNINIT; + + case STATE_TRANSVR_ISOLATED: /* Transceiver is plugged, but has some issues */ + return ERR_TRNASVR_BE_ISOLATED; + + case STATE_TRANSVR_CONNECTED: /* Transceiver is plugged, system is ready */ + self->state = current_state; + self->type = current_type; + return 0; + + case STATE_TRANSVR_SWAPPED: /* Transceiver is plugged, system detect user changed */ + self->type = current_type; + if (reload_transvr_obj(self, current_type) < 0){ + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + self->state = current_state; + return 0; + + case STATE_TRANSVR_UNEXCEPTED: /* Transceiver type or state is unexpected case */ + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_UNEXCPT; + + default: + SWPS_INFO("%s: state:%d not in define.\n", __func__, current_state); + break; + } + return ERR_TRANSVR_UNEXCPT; +} + + +static int +_is_except_happened_4_pmode(struct transvr_obj_s* self, + int new_state) { + + int event_chk = 0; + + if (self->temp == 0){ + return 0; + } + switch (new_state) { + case STATE_TRANSVR_INIT: + event_chk = EVENT_TRANSVR_EXCEP_INIT; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_CONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_UP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_DISCONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_DOWN; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_SWAPPED: + event_chk = EVENT_TRANSVR_EXCEP_SWAP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_UNEXCEPTED: + event_chk = EVENT_TRANSVR_EXCEP_EXCEP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_ISOLATED: + event_chk = EVENT_TRANSVR_EXCEP_ISOLATED; + goto check_event_happened_4_pmode; + + default: + SWPS_INFO("%s: unexcepted case:%d\n", __func__, new_state); + break; + } + return 0; + +check_event_happened_4_pmode: + if (self->temp == event_chk){ + return 1; + } + return 0; +} + + +int +common_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + /* [Return Value]: + * ERR_TRANSVR_UNINIT : (1) Initial not ready + * ERR_TRANSVR_UNPLUGGED : (1) Any -> Down + * ERR_TRANSVR_TASK_BUSY : (1) Wait Initial task + * ERR_TRANSVR_UNEXCPT : (1) Initial fail + * (2) Task fail + * (3) Reload fail + * ERR_TRNASVR_BE_ISOLATED : (1) Already be isolated + * OK Case (return 0) : (1) action_4_connected + * (2) action_4_nothing (initial retry) + */ + int curr_state[2]; + int old_state = self->state; + int old_type = self->type; + int new_state = STATE_TRANSVR_UNEXCEPTED; + int new_type = TRANSVR_TYPE_ERROR; + int return_val = ERR_TRANSVR_UNEXCPT; + + /* Never initial */ + if (self->state == STATE_TRANSVR_NEW) { + goto comfsm_action_4_reinit_obj; + } + /* Detect current state */ + switch (detect_transvr_state(self, curr_state)) { + case 0: + new_state = curr_state[0]; + new_type = curr_state[1]; + break; + + case ERR_TRNASVR_BE_ISOLATED: + new_state = STATE_TRANSVR_ISOLATED; + new_type = old_type; + break; + + case ERR_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case ERR_TRANSVR_UNEXCPT: + default: + new_state = STATE_TRANSVR_UNEXCEPTED; + new_type = old_type; + } + /* State handling */ + switch (old_state) { + case STATE_TRANSVR_INIT: /* INIT -> */ + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 1-1: UP -> INIT */ + SWPS_INFO("Detect %s is present. :1-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 1-2: UP -> UP */ + return_val = 0; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 1-3: UP -> DOWN */ + SWPS_INFO("Detect %s is removed. :1-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 1-4: UP -> SWAP */ + SWPS_INFO("Detect %s is swapped. :1-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 1-5: UP -> UNEXPET */ + SWPS_INFO("Detect %s has error. :1-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 1-6: UP -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :1-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_DISCONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 2-1: DOWN -> INIT */ + SWPS_INFO("Detect %s is present. :2-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 2-2: DOWN -> UP */ + SWPS_INFO("Detect %s is present. :2-2\n",self->swp_name); + goto comfsm_action_4_reinit_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 2-3: DOWN -> DOWN */ + return_val = ERR_TRANSVR_UNPLUGGED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_SWAPPED: /* Case 2-4: DOWN -> SWAP */ + SWPS_INFO("Detect %s is swapped. :2-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 2-5: DOWN -> UNEXPET */ + SWPS_INFO("Detect %s has error. :2-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 2-6: DOWN -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :2-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_UNEXCEPTED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 3-1: UNEXPET -> INIT */ + SWPS_INFO("Detect %s is present. :3-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 3-2: UNEXPET -> UP */ + SWPS_INFO("Detect %s is present. :3-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 3-3: UNEXPET -> DOWN */ + SWPS_INFO("Detect %s is removed. :3-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 3-4: UNEXPET -> SWAP */ + SWPS_INFO("Detect %s is swapped. :3-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 3-5: UNEXPET -> UNEXPET */ + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRANSVR_UNEXCPT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 3-6: UNEXPET -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :3-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 4-1: ISOLATE -> INIT */ + SWPS_INFO("Detect %s internal error. :4-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 4-2: ISOLATE -> UP */ + SWPS_INFO("Detect %s internal error. :4-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 4-3: ISOLATE -> DOWN */ + SWPS_INFO("Detect %s is removed. :4-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 4-4: ISOLATE -> SWAP */ + SWPS_INFO("Detect %s internal error. :4-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 4-5: ISOLATE -> UNEXPET */ + SWPS_INFO("Detect %s internal error. :4-5\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 4-6: ISOLATE -> ISOLATE */ + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + default: + break; + } + goto comfsm_action_4_unexpected; + + default: + break; + } + goto comfsm_action_4_unexpected; + + +comfsm_action_4_keep_state: + return return_val; + +comfsm_action_4_reinit_obj: + SWPS_DEBUG("FSM action: %s re-initial.\n", self->swp_name); + return_val = _transvr_init_handler(self); + goto comfsm_action_4_identify_event; + +comfsm_action_4_reload_obj: + SWPS_DEBUG("FSM action: %s reload.\n", self->swp_name); + self->type = new_type; + return_val = reload_transvr_obj(self, new_type); + goto comfsm_action_4_identify_event; + +comfsm_action_4_identify_event: + switch (return_val) { + case EVENT_TRANSVR_INIT_UP: + case EVENT_TRANSVR_TASK_DONE: + goto comfsm_action_4_connected; + + case EVENT_TRANSVR_INIT_DOWN: + goto comfsm_action_4_disconnected; + + case EVENT_TRANSVR_INIT_REINIT: + goto comfsm_action_4_nothing; + + case EVENT_TRANSVR_TASK_WAIT: + self->state = STATE_TRANSVR_INIT; + return ERR_TRANSVR_TASK_BUSY; + + case EVENT_TRANSVR_TASK_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_TASK_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_INIT_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_INIT_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_RELOAD_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_RELOAD_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case EVENT_TRANSVR_EXCEP_ISOLATED: + goto comfsm_action_4_isolate_obj; + + default: + SWPS_INFO("%s detect undefined event:%d.\n", self->swp_name, return_val); + goto comfsm_action_4_unexpected; + } + +comfsm_action_4_nothing: + SWPS_DEBUG("FSM action: %s do nothing.\n", self->swp_name); + return 0; + +comfsm_action_4_connected: + SWPS_DEBUG("FSM action: %s Connected.\n", self->swp_name); + self->state = STATE_TRANSVR_CONNECTED; + self->type = new_type; + self->send_uevent(self, KOBJ_ADD); + _transvr_clean_retry(self); + return 0; + +comfsm_action_4_disconnected: + SWPS_DEBUG("FSM action: %s Disconnected. \n", self->swp_name); + self->state = STATE_TRANSVR_DISCONNECTED; + self->temp = EVENT_TRANSVR_TASK_DONE; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_retry(self); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNPLUGGED; + +comfsm_action_4_report_i2c_crash: + SWPS_DEBUG("FSM action: %s report I2C crash.\n", self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_I2C_CRASH; + +comfsm_action_4_isolate_obj: + SWPS_DEBUG("FSM action: %s isolate.\n", self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return ERR_TRNASVR_BE_ISOLATED; + +comfsm_action_4_unexpected: + SWPS_INFO("FSM action: %s unexpected.\n", self->swp_name); + SWPS_INFO("Dump: :%d :0x%02x :%d :0x%02x\n", + old_state, old_type, new_state, new_type); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNEXCPT; +} + + +int +fake_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +int +fake_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +/* ========== Object functions for Initial procedure ========== + */ +int +transvr_init_common(struct transvr_obj_s *self){ + /* Nothing to update */ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_fake(struct transvr_obj_s *self){ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_sfp(struct transvr_obj_s *self){ + + int tmp_val = DEBUG_TRANSVR_INT_VAL; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_msg = "ERR"; + + self->info = sft_detect_transvr_class(self); + /* Disable auto_config */ + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + /* Handle multi-rate */ + err_code = initfunc_sfp_handle_multi_rate_mode(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_multi_rate_mode fail!"; + goto err_transvr_init_sfp_1; + } + /* Handle 1G- RJ45 */ + tmp_val = err_code; + err_code = initfunc_sfp_handle_1g_rj45(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_1g_rj45 fail!"; + goto err_transvr_init_sfp_1; + } + tmp_val = (tmp_val > err_code ? tmp_val : err_code); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_sfp_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_code, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp(struct transvr_obj_s *self){ + + int err = EVENT_TRANSVR_EXCEP_EXCEP; + char *emsg = "ERR"; + + self->info = qsft_detect_transvr_class(self); + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + err = initfunc_qsfp_handle_power_mode(self); + if (err < 0){ + emsg = "initfunc_qsfp_handle_tx_disable fail!"; + goto err_transvr_init_qsfp; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, emsg, err, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp28(struct transvr_obj_s *self){ + + int tmp_val = EVENT_TRANSVR_EXCEP_EXCEP; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_msg = "ERR"; + + /* Handle QSFP common */ + err_val = transvr_init_qsfp(self); + if (err_val < 0){ + err_msg = "transvr_init_qsfp fail!"; + goto err_transvr_init_qsfp28_1; + } + /* Disable auto_config */ + if (!self->auto_config) { + return err_val; + } + /* Handle CDR */ + tmp_val = err_val; + err_val = initfunc_qsfp28_handle_cdr(self); + if (err_val < 0){ + err_msg = "Handle CDR fail!"; + goto err_transvr_init_qsfp28_1; + } + tmp_val = (tmp_val > err_val ? tmp_val : err_val); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp28_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== Object Initial handler ========== + */ +static int +_is_transvr_valid(struct transvr_obj_s *self, + int type, + int state) { + /* [Return] + * 0 : OK, inserted + * EVENT_TRANSVR_INIT_DOWN : OK, removed + * EVENT_TRANSVR_INIT_FAIL : Outside error, type doesn't supported + * EVENT_TRANSVR_EXCEP_INIT : Internal error, state undefined + */ + switch (type) { + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + break; + default: + SWPS_INFO("detect undefined type:0x%02x on %s\n", + type, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; + } + switch (state) { + case STATE_TRANSVR_DISCONNECTED: + return EVENT_TRANSVR_INIT_DOWN; + case STATE_TRANSVR_INIT: + case STATE_TRANSVR_CONNECTED: + case STATE_TRANSVR_SWAPPED: + break; + default: + SWPS_INFO("detect undefined state:%d on %s\n", + state, self->swp_name); + return EVENT_TRANSVR_EXCEP_INIT; + } + return 0; +} + + +static int +_is_transvr_hw_ready(struct transvr_obj_s *self, + int type){ + /* [Return] + * EVENT_TRANSVR_TASK_DONE : Ready + * EVENT_TRANSVR_TASK_WAIT : Not ready + * EVENT_TRANSVR_INIT_FAIL : Error + */ + int addr = DEBUG_TRANSVR_INT_VAL; + int page = DEBUG_TRANSVR_INT_VAL; + int offs = DEBUG_TRANSVR_INT_VAL; + int bit = DEBUG_TRANSVR_INT_VAL; + int ready = DEBUG_TRANSVR_INT_VAL; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t ab_val = DEBUG_TRANSVR_HEX_VAL; + + switch (type) { + case TRANSVR_TYPE_SFP: + addr = VAL_TRANSVR_8472_READY_ADDR; + page = VAL_TRANSVR_8472_READY_PAGE; + offs = VAL_TRANSVR_8472_READY_OFFSET; + bit = VAL_TRANSVR_8472_READY_BIT; + ready = VAL_TRANSVR_8472_READY_VALUE; + ab_val = VAL_TRANSVR_8472_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + addr = VAL_TRANSVR_8436_READY_ADDR; + page = VAL_TRANSVR_8436_READY_PAGE; + offs = VAL_TRANSVR_8436_READY_OFFSET; + bit = VAL_TRANSVR_8436_READY_BIT; + ready = VAL_TRANSVR_8436_READY_VALUE; + ab_val = VAL_TRANSVR_8436_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + return EVENT_TRANSVR_TASK_DONE; + + default: + emsg = "unexpected case"; + goto err_is_transvr_hw_ready; + } + /* Select target page */ + err = _common_setup_page(self, addr, page, offs, 1, 0); + if (err < 0) { + emsg = "setup page fail"; + goto err_is_transvr_hw_ready; + } + /* Check feature supported + * [Note] + * Some of transceiver/cables doesn't support "Status Indicators" + * (ex:DAC, RJ45 copper SFP ...etc). In these case, we bypass the + * step of checking Status Indicators, then state machine will take + * the following handle procedure. + */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (err < 0) { + emsg = "doesn't support Status Indicators"; + goto bypass_is_transvr_hw_ready; + } + /* Filter abnormal case */ + if (err == ab_val) { + emsg = "detect using unusual definition."; + goto bypass_is_transvr_hw_ready; + } + /* Get Status Indicators */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, offs); + if (err < 0) { + emsg = "detect current value fail"; + goto err_is_transvr_hw_ready; + } + + if ((err & (1<:%d\n", __func__, emsg, type); + return EVENT_TRANSVR_TASK_DONE; + +err_is_transvr_hw_ready: + SWPS_DEBUG("%s: %s :%d\n", __func__, emsg, type); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_is_transvr_support_ctle(struct transvr_obj_s *self) { + + switch (self->info) { + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return 1; + default: + break; + } + return 0; +} + + +static int +_transvr_init_handler(struct transvr_obj_s *self){ + + int detect[2]; + int d_state = STATE_TRANSVR_UNEXCEPTED; + int d_type = TRANSVR_TYPE_ERROR; + int result = ERR_TRANSVR_UNINIT; + int retry = 6; /* (6+1) x 0.3 = 2.1s > spec:2.0s */ + int elimit = 63; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Clean and check callback */ + self->state = STATE_TRANSVR_INIT; + if (self->init == NULL) { + snprintf(emsg, elimit, "init() is null"); + goto initer_err_case_unexcept_0; + } + if (self->clean == NULL) { + snprintf(emsg, elimit, "clean() is null"); + goto initer_err_case_unexcept_0; + } + self->clean(self); + + /* Detect transceiver information */ + result = detect_transvr_state(self, detect); + if (result < 0) { + snprintf(emsg, elimit, "detect_transvr_state() fail"); + switch (result) { + case ERR_TRANSVR_I2C_CRASH: + goto initer_err_case_i2c_ceash; + case ERR_TRNASVR_BE_ISOLATED: + goto initer_err_case_be_isolated; + + case ERR_TRANSVR_UNEXCPT: + default: + break; + } + goto initer_err_case_retry_1; + } + d_state = detect[0]; + d_type = detect[1]; + + /* Verify transceiver type and state */ + switch (_is_transvr_valid(self, d_type, d_state)) { + case 0: + break; + case EVENT_TRANSVR_INIT_DOWN: + goto initer_ok_case_down;; + case EVENT_TRANSVR_INIT_FAIL: + snprintf(emsg, elimit, "transceiver type doesn't support"); + goto initer_err_case_alarm_to_user; + case EVENT_TRANSVR_EXCEP_INIT: + default: + goto initer_err_case_unexcept_1; + } + + /* Handle reload case */ + if (self->type != d_type){ + /* This is the protect mechanism. Normally, This case will not happen. + * When State machine detect swap event during initial, It will trigger + * reload function to ensure type correct. */ + if (_reload_transvr_obj(self, d_type) < 0){ + snprintf(emsg, elimit, "reload object fail"); + goto initer_err_case_unexcept_1; + } + } + + /* Check transceiver HW initial ready */ + switch (_is_transvr_hw_ready(self, d_type)) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_err_case_retry_1; + case EVENT_TRANSVR_INIT_FAIL: + default: + goto initer_err_case_unexcept_1; + } + + /* Try to update all and check */ + if (self->update_all(self, 1) < 0){ + /* For some transceiver, EEPROME has lag issues during initial stage. + * In this case, we set status back to STATE_TRANSVR_NEW, than it will + * be checked in next polling cycle. */ + goto initer_err_case_retry_1; + } + + /* Execute init() call back */ + result = self->init(self); + switch (result) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_ok_case_wait; + + default: + snprintf(emsg, elimit, "undefined init() return:%d\n", result); + goto initer_err_case_unexcept_1; + } + goto initer_ok_case_up; + + +initer_ok_case_wait: + self->dump_all(self); + return EVENT_TRANSVR_TASK_WAIT; + +initer_ok_case_up: + self->state = STATE_TRANSVR_CONNECTED; + self->temp = 0; + self->dump_all(self); + return EVENT_TRANSVR_INIT_UP; + +initer_ok_case_down: + self->temp = 0; + self->state = STATE_TRANSVR_DISCONNECTED; + return EVENT_TRANSVR_INIT_DOWN; + +initer_err_case_i2c_ceash: + SWPS_DEBUG("%s: %s :%s :I2C crash\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_I2C_CRASH; + +initer_err_case_be_isolated: + SWPS_DEBUG("%s: %s :%s :isolated\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return EVENT_TRANSVR_EXCEP_ISOLATED; + +initer_err_case_retry_1: + SWPS_DEBUG("%s: %s :%s :retry\n", + __func__, emsg, self->swp_name); + if (_transvr_handle_retry(self, retry) == 0) { + self->state = STATE_TRANSVR_NEW; + return EVENT_TRANSVR_INIT_REINIT; + } + goto initer_err_case_alarm_to_user; + +initer_err_case_unexcept_1: + self->clean(self); +initer_err_case_unexcept_0: + self->state = STATE_TRANSVR_UNEXCEPTED; + if (_is_except_happened_4_pmode(self, d_state) && + (self->mode == TRANSVR_MODE_POLLING) ){ + SWPS_INFO("%s: %s :%s\n", __func__, emsg, self->swp_name); + SWPS_INFO("Dump: :%d :%d :%d :%d\n", + self->state, self->type, d_state, d_type); + } + return EVENT_TRANSVR_INIT_FAIL; + +initer_err_case_alarm_to_user: + SWPS_DEBUG("%s: %s :%s :alarm_to_user\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard"); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== Object functions for Clean procedure ========== + */ +int +_transvr_clean_handler(struct transvr_obj_s *self){ + + int retval = DEBUG_TRANSVR_INT_VAL; + + if (!self->clean) { + SWPS_ERR("%s: %s clean() is NULL.\n", + __func__, self->swp_name); + return EVENT_TRANSVR_TASK_FAIL; + } + retval = self->clean(self); + if (retval != EVENT_TRANSVR_TASK_DONE){ + SWPS_ERR("%s: %s clean() fail. [ERR]:%d\n", + __func__, self->swp_name, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_transvr_clean(struct transvr_obj_s *self){ + + transvr_task_free_all(self); + transvr_cache_free_all(self); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +qsfp_transvr_clean(struct transvr_obj_s *self){ + + int retval; + int lpower_config = 1; + + retval = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (retval < 0){ + SWPS_ERR("%s: Set lpmod fail! :%d\n", + __func__, retval); + return retval; + } + retval = common_transvr_clean(self); + if (retval < 0){ + SWPS_ERR("%s: common_transvr_clean fail! :%d\n", + __func__, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +fake_transvr_clean(struct transvr_obj_s *self){ + + return EVENT_TRANSVR_TASK_DONE; +} + + +/* ========== Object functions for check and update ========== + */ +int +common_transvr_check(struct transvr_obj_s *self){ + + char fun_str[32] = "common_transvr_check"; + + if (self->mode != TRANSVR_MODE_POLLING) { + SWPS_ERR("%s: mode:%d is not TRANSVR_MODE_POLLING\n", + fun_str, self->mode); + return ERR_TRANSVR_UNEXCPT; + } + /* Trigger delay task */ + transvr_task_run_all(self); + /* Trigger state machine to check and update */ + return self->fsm_4_polling(self, fun_str); +} + + +int +fake_transvr_check(struct transvr_obj_s *self){ + return 0; +} + + +/* ========== Functions for Factory pattern ========== + */ +static int +setup_transvr_public_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = unsupported_get_func; + self->get_br = common_get_br; + self->get_len_sm = sfp_get_len_sm; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = sfp_get_comp_eth_1; + self->get_comp_eth_10 = sfp_get_comp_eth_10; + self->get_comp_eth_10_40 = unsupported_get_func; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = sfp_get_rate_id; + self->get_soft_rs0 = sfp_get_soft_rs0; + self->get_soft_rs1 = sfp_get_soft_rs1; + self->get_info = common_get_info; + self->get_if_type = sfp_get_if_type; + self->get_if_speed = sfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = sfp_get_transvr_temp; + self->get_curr_vol = sfp_get_transvr_voltage; + self->get_soft_rx_los = unsupported_get_func2; + self->get_soft_tx_disable = unsupported_get_func2; + self->get_soft_tx_fault = unsupported_get_func2; + self->get_auto_tx_disable = unsupported_get_func2; + self->get_tx_bias = sfp_get_transvr_tx_bias; + self->get_tx_power = sfp_get_transvr_tx_power; + self->get_rx_power = sfp_get_transvr_rx_power; + self->get_tx_eq = sfp_get_transvr_tx_eq; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = sfp_get_transvr_rx_em; + self->get_wavelength = sfp_get_wavelength; + self->get_extphy_offset = sfp_get_1g_rj45_extphy_offset; + self->get_extphy_reg = sfp_get_1g_rj45_extphy_reg; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = sfp_set_soft_rs0; + self->set_soft_rs1 = sfp_set_soft_rs1; + self->set_soft_tx_disable = unsupported_set_func; + self->set_auto_tx_disable = unsupported_set_func; + self->set_tx_eq = sfp_set_tx_eq; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = sfp_set_rx_em; + self->set_extphy_offset = sfp_set_1g_rj45_extphy_offset; + self->set_extphy_reg = sfp_set_1g_rj45_extphy_reg; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = unsupported_get_func2; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = unsupported_get_func2; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = unsupported_set_func; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = unsupported_set_func; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = qsfp_get_cdr; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = qsfp_get_transvr_tx_eq; + self->get_rx_am = qsfp_get_transvr_rx_am; + self->get_rx_em = qsfp_get_transvr_rx_em; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = qsfp_set_cdr; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = qsfp_set_tx_eq; + self->set_rx_am = qsfp_set_rx_am; + self->set_rx_em = qsfp_set_rx_em; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_FAKE: + self->get_id = fake_get_hex; + self->get_ext_id = fake_get_hex; + self->get_connector = fake_get_hex; + self->get_vendor_name = fake_get_str; + self->get_vendor_pn = fake_get_str; + self->get_vendor_rev = fake_get_str; + self->get_vendor_sn = fake_get_str; + self->get_power_cls = fake_get_int; + self->get_br = fake_get_hex; + self->get_len_sm = fake_get_int; + self->get_len_smf = fake_get_int; + self->get_len_om1 = fake_get_int; + self->get_len_om2 = fake_get_int; + self->get_len_om3 = fake_get_int; + self->get_len_om4 = fake_get_int; + self->get_comp_rev = fake_get_hex; + self->get_comp_eth_1 = fake_get_hex; + self->get_comp_eth_10 = fake_get_hex; + self->get_comp_eth_10_40 = fake_get_hex; + self->get_comp_extend = fake_get_hex; + self->get_cdr = fake_get_hex; + self->get_rate_id = fake_get_hex; + self->get_soft_rs0 = fake_get_binary; + self->get_soft_rs1 = fake_get_binary; + self->get_info = fake_get_int; + self->get_if_type = fake_get_str; + self->get_if_speed = fake_get_str; + self->get_if_lane = fake_get_str; + self->get_curr_temp = fake_get_str; + self->get_curr_vol = fake_get_str; + self->get_soft_rx_los = fake_get_str; + self->get_soft_tx_disable = fake_get_str; + self->get_soft_tx_fault = fake_get_str; + self->get_auto_tx_disable = fake_get_str; + self->get_tx_bias = fake_get_str; + self->get_tx_power = fake_get_str; + self->get_rx_power = fake_get_str; + self->get_tx_eq = fake_get_str; + self->get_rx_am = fake_get_str; + self->get_rx_em = fake_get_str; + self->get_wavelength = fake_get_str; + self->get_extphy_offset = fake_get_str; + self->get_extphy_reg = fake_get_str; + self->set_cdr = fake_set_hex; + self->set_soft_rs0 = fake_set_int; + self->set_soft_rs1 = fake_set_int; + self->set_soft_tx_disable = fake_set_int; + self->set_auto_tx_disable = fake_set_int; + self->set_tx_eq = fake_set_int; + self->set_rx_am = fake_set_int; + self->set_rx_em = fake_set_int; + self->set_extphy_offset = fake_set_hex; + self->set_extphy_reg = fake_set_hex; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_transvr_private_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->init = transvr_init_sfp; + self->clean = common_transvr_clean; + self->check = common_transvr_check; + self->update_all = _sfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = sfp_send_uevent; + self->dump_all = sfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->init = transvr_init_qsfp; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->init = transvr_init_qsfp28; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_FAKE: + self->init = transvr_init_fake; + self->clean = fake_transvr_clean; + self->check = fake_transvr_check; + self->update_all = fake_transvr_update; + self->fsm_4_direct = fake_fsm_4_direct_mode; + self->fsm_4_polling = fake_fsm_4_polling_mode; + self->send_uevent = fake_send_uevent; + self->dump_all = fake_transvr_dump; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static struct eeprom_map_s * +get_eeprom_map(int transvr_type){ + + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + return &eeprom_map_sfp; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + return &eeprom_map_qsfp; + case TRANSVR_TYPE_QSFP_28: + return &eeprom_map_qsfp28; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return NULL; +} + + +static int +setup_transvr_ssize_attr(char *swp_name, + struct transvr_obj_s *self, + struct eeprom_map_s *map_p, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int chan_id, + int run_mode){ + switch (run_mode){ + case TRANSVR_MODE_DIRECT: /* Direct access device mode */ + case TRANSVR_MODE_POLLING: /* Polling mode, read from cache */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = DEBUG_TRANSVR_INT_VAL; + return -1; + } + self->eeprom_map_p = map_p; + self->ioexp_obj_p = ioexp_obj_p; + self->ioexp_virt_offset = ioexp_virt_offset; + self->chan_id = chan_id; + self->layout = transvr_type; + self->type = transvr_type; + self->chipset_type = chipset_type; + self->state = STATE_TRANSVR_NEW; + self->info = STATE_TRANSVR_NEW; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + strncpy(self->swp_name, swp_name, 32); + mutex_init(&self->lock); + return 0; +} + + +static int +setup_transvr_dsize_attr(struct transvr_obj_s *self){ + + char *emsg = DEBUG_TRANSVR_STR_VAL; + + self->vendor_name = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_name){ + emsg = "vendor_name"; + goto err_setup_d_attr; + } + self->vendor_pn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_pn){ + emsg = "vendor_pn"; + goto err_setup_d_attr; + } + self->vendor_rev = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_rev){ + emsg = "vendor_rev"; + goto err_setup_d_attr; + } + self->vendor_sn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_sn){ + emsg = "vendor_sn"; + goto err_setup_d_attr; + } + self->worker_p = NULL; + return 0; + +err_setup_d_attr: + SWPS_ERR("%s: %s kzalloc fail!", __func__, emsg); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_i2c_client(struct transvr_obj_s *self){ + + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + adap = i2c_get_adapter(self->chan_id); + if(!adap){ + snprintf(err_msg, sizeof(err_msg), + "can not get adap:%d", self->chan_id); + goto err_setup_i2c_client; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + snprintf(err_msg, sizeof(err_msg), + "can not kzalloc client:%d", self->chan_id); + goto err_setup_i2c_client; + } + client->adapter = adap; + self->i2c_client_p = client; + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + return 0; + +err_setup_i2c_client: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return ERR_TRANSVR_UNEXCPT; +} + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode){ + + struct transvr_obj_s *result_p; + struct eeprom_map_s *map_p; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Allocate transceiver object */ + map_p = get_eeprom_map(transvr_type); + if (!map_p){ + snprintf(err_msg, sizeof(err_msg), + "Invalid transvr_type:%d", transvr_type); + goto err_create_transvr_fail; + } + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_create_transvr_fail; + } + /* Prepare static size attributes */ + if (setup_transvr_ssize_attr(swp_name, + result_p, + map_p, + ioexp_obj_p, + ioexp_virt_offset, + transvr_type, + chipset_type, + chan_id, + run_mode) < 0){ + goto err_create_transvr_sattr_fail; + } + /* Prepare dynamic size attributes */ + if (setup_transvr_dsize_attr(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_public_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_private_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare i2c client object */ + if (setup_i2c_client(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + return result_p; + +err_create_transvr_dattr_fail: + kfree(result_p->vendor_sn); + kfree(result_p->vendor_rev); + kfree(result_p->vendor_pn); + kfree(result_p->vendor_name); +err_create_transvr_sattr_fail: + kfree(result_p); +err_create_transvr_fail: + SWPS_ERR("%s: %s :%d :%d :%d\n", + __func__, err_msg, chan_id, ioexp_virt_offset, transvr_type); + return NULL; +} +EXPORT_SYMBOL(create_transvr_obj); + + +static int +_reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + struct eeprom_map_s *new_map_p; + struct eeprom_map_s *old_map_p = self->eeprom_map_p; + struct i2c_client *old_i2c_p = self->i2c_client_p; + int old_type = self->type; + + /* Change state to STATE_TRANSVR_INIT */ + self->state = STATE_TRANSVR_INIT; + self->type = new_type; + /* Replace EEPROME map */ + new_map_p = get_eeprom_map(new_type); + if (!new_map_p){ + goto err_private_reload_func_1; + } + self->eeprom_map_p = new_map_p; + /* Reload i2c client */ + if (setup_i2c_client(self) < 0){ + goto err_private_reload_func_2; + } + /* Replace call back functions */ + if (setup_transvr_public_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + if (setup_transvr_private_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + if(old_i2c_p){ + i2c_put_adapter(old_i2c_p->adapter); + } + kfree(old_i2c_p); + return 0; + +err_private_reload_func_3: + SWPS_INFO("%s: init() fail!\n", __func__); + if(old_i2c_p){ + i2c_put_adapter(old_i2c_p->adapter); + } + kfree(old_i2c_p); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return -2; + +err_private_reload_func_2: + self->eeprom_map_p = old_map_p; + self->i2c_client_p = old_i2c_p; +err_private_reload_func_1: + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = old_type; + SWPS_INFO("%s fail! :0x%02x\n", __func__, new_type); + return -1; +} + + +static int +reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + int result_val = ERR_TRANSVR_UNEXCPT; + + /* Reload phase */ + result_val = _reload_transvr_obj(self, new_type); + if (result_val < 0){ + SWPS_INFO("%s: reload phase fail! :%d\n", + __func__, result_val); + return EVENT_TRANSVR_RELOAD_FAIL; + } + /* Initial phase */ + result_val = _transvr_init_handler(self); + if (result_val < 0){ + SWPS_INFO("%s: initial phase fail! :%d\n", + __func__, result_val); + } + return result_val; +} + + +int +isolate_transvr_obj(struct transvr_obj_s *self) { + + self->state = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s be isolated\n", __func__, self->swp_name); + return 0; +} +EXPORT_SYMBOL(isolate_transvr_obj); + + +int +resync_channel_tier_2(struct transvr_obj_s *self) { + + int val = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_ISOLATED) { + return 0; + } + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + val = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (val < 0) { + return -1; + } + return 0; +} +EXPORT_SYMBOL(resync_channel_tier_2); + +/* For build single module using (Ex: ONL platform) */ +MODULE_LICENSE("GPL"); + + +/* ----------------------------------------- + * ToDo List + * ----------------------------------------- + * 1. _sfp_detect_class_by_feature() + * => Need check ACC use case. + * 2. _sfp_detect_class_by_1g_ethernet() + * => Need check 0.1G use case. + * 3. Loopback transceiver use case. + * => Less much data + * 4. _qsfp_detect_class_by_extend_comp() + * => Verify 100G CWDM4 + * => Verify Obsolete (assigned before 100G CWDM4 MSA required FEC) + * => Verify 100G CLR4 + * => Verify 100GE-DWDM2 + * => Verify 40G PSM4 Parallel SMF + * => Verify 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. + * => Verify 100G ACC or 25GAUI C2M ACC. + * => Verify 25GBASE-LR + * => Verify 40G Active Cable (XLPPI) + */ + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/transceiver.h new file mode 100644 index 000000000000..a2a503402142 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/modules/transceiver.h @@ -0,0 +1,804 @@ +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* advanced features control */ +#define TRANSVR_INFO_DUMP_ENABLE (1) +#define TRANSVR_INFO_CACHE_ENABLE (1) +#define TRANSVR_UEVENT_ENABLE (1) + +/* Transceiver type define */ +#define TRANSVR_TYPE_UNKNOW_1 (0x00) +#define TRANSVR_TYPE_UNKNOW_2 (0xff) +#define TRANSVR_TYPE_SFP (0x03) /* Define for SFP, SFP+, SFP28 */ +#define TRANSVR_TYPE_QSFP (0x0c) +#define TRANSVR_TYPE_QSFP_PLUS (0x0d) +#define TRANSVR_TYPE_QSFP_28 (0x11) +#define TRANSVR_TYPE_UNPLUGGED (0xfa) /* Define for ERROR handle */ +#define TRANSVR_TYPE_FAKE (0xfc) /* Define for ERROR handle */ +#define TRANSVR_TYPE_INCONSISTENT (0xfd) /* Define for ERROR handle */ +#define TRANSVR_TYPE_ERROR (0xfe) /* Define for ERROR handle */ + +/* Transceiver class for base info */ +#define TRANSVR_CLASS_UNSPECIFIED (0) +#define TRANSVR_CLASS_ERROR (-26001) +#define TRANSVR_CLASS_1G (26001) +#define TRANSVR_CLASS_10G (26011) +#define TRANSVR_CLASS_25G (26021) +#define TRANSVR_CLASS_40G (26041) +#define TRANSVR_CLASS_100G (26101) +#define TRANSVR_CLASS_NO_SPERARABLE (26901) +#define TRANSVR_CLASS_EXTEND_COMP (26902) +/* Transceiver class for Optical 1G */ +#define TRANSVR_CLASS_OPTICAL (27000) +#define TRANSVR_CLASS_OPTICAL_100 (27001) +#define TRANSVR_CLASS_OPTICAL_1G (27002) +#define TRANSVR_CLASS_OPTICAL_1G_AOC (27003) +#define TRANSVR_CLASS_OPTICAL_1G_SX (27004) +#define TRANSVR_CLASS_OPTICAL_1G_LX (27005) +#define TRANSVR_CLASS_OPTICAL_1G_EX (27006) +/* Transceiver class for Optical 10G */ +#define TRANSVR_CLASS_OPTICAL_10G (27010) +#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011) +#define TRANSVR_CLASS_OPTICAL_10G_S_SR (27012) +#define TRANSVR_CLASS_OPTICAL_10G_S_LR (27013) +#define TRANSVR_CLASS_OPTICAL_10G_S_ER (27014) +#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015) +#define TRANSVR_CLASS_OPTICAL_10G_Q_SR (27016) +#define TRANSVR_CLASS_OPTICAL_10G_Q_LR (27017) +#define TRANSVR_CLASS_OPTICAL_10G_Q_ER (27018) +/* Transceiver class for Optical 25G */ +#define TRANSVR_CLASS_OPTICAL_25G (27020) +#define TRANSVR_CLASS_OPTICAL_25G_AOC (27021) +#define TRANSVR_CLASS_OPTICAL_25G_SR (27022) +#define TRANSVR_CLASS_OPTICAL_25G_LR (27023) +#define TRANSVR_CLASS_OPTICAL_25G_ER (27024) +/* Transceiver class for Optical 40G */ +#define TRANSVR_CLASS_OPTICAL_40G (27040) +#define TRANSVR_CLASS_OPTICAL_40G_AOC (27041) +#define TRANSVR_CLASS_OPTICAL_40G_SR4 (27042) +#define TRANSVR_CLASS_OPTICAL_40G_LR4 (27043) +#define TRANSVR_CLASS_OPTICAL_40G_ER4 (27044) +/* Transceiver class for Optical 100G */ +#define TRANSVR_CLASS_OPTICAL_100G (27100) +#define TRANSVR_CLASS_OPTICAL_100G_AOC (27101) +#define TRANSVR_CLASS_OPTICAL_100G_SR4 (27102) +#define TRANSVR_CLASS_OPTICAL_100G_LR4 (27103) +#define TRANSVR_CLASS_OPTICAL_100G_ER4 (27104) +#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105) +/* Transceiver class for Copper */ +#define TRANSVR_CLASS_COPPER (28000) +#define TRANSVR_CLASS_COPPER_L1_1G (28001) +#define TRANSVR_CLASS_COPPER_L1_10G (28011) +#define TRANSVR_CLASS_COPPER_L4_10G (28012) +#define TRANSVR_CLASS_COPPER_L1_25G (28021) +#define TRANSVR_CLASS_COPPER_L4_40G (28041) +#define TRANSVR_CLASS_COPPER_L4_100G (28101) +/* Transceiver class for Base-T */ +#define TRANSVR_CLASS_BASE_T_1000 (29001) +#define TRANSVR_CLASS_BASE_T_1000_up (29002) +/* For uevent message */ +#define TRANSVR_UEVENT_KEY_IF "IF_TYPE" +#define TRANSVR_UEVENT_KEY_SP "IF_SPEED" +#define TRANSVR_UEVENT_KEY_LANE "IF_LANE" +#define TRANSVR_UEVENT_UNKNOW "UNKNOW" +#define TRANSVR_IF_KR "KR" +#define TRANSVR_IF_KR4 "KR4" +#define TRANSVR_IF_SR "SR" +#define TRANSVR_IF_SR4 "SR4" +#define TRANSVR_IF_SFI "SFI" +#define TRANSVR_IF_IF_GMII "GMII" +#define TRANSVR_IF_IF_XGMII "XGMII" +#define TRANSVR_IF_SP_100 "100" +#define TRANSVR_IF_SP_1G "1000" +#define TRANSVR_IF_SP_10G "10000" +#define TRANSVR_IF_SP_25G "25000" +#define TRANSVR_IF_SP_40G "40000" +#define TRANSVR_IF_SP_100G "100000" + +/* Transceiver mode define */ +#define TRANSVR_MODE_DIRECT (21000) +#define TRANSVR_MODE_POLLING (21001) + +/* Transceiver state define + * [Note] + * 1. State is used to represent the state of "Transceiver" and "Object". + * 2. State for different target has different means. The description as following: + */ +#define STATE_TRANSVR_CONNECTED (0) /* [Transvr]:Be plugged in. [Obj]:Link up, and work normally. */ +#define STATE_TRANSVR_NEW (-100) /* [Transvr]:(Not used) [Obj]:Create */ +#define STATE_TRANSVR_INIT (-101) /* [Transvr]:Be plugged in. [Obj]:Link up, and in initial process. */ +#define STATE_TRANSVR_ISOLATED (-102) /* [Transvr]:Be plugged in. [Obj]:Isolate, and not provide service. */ +#define STATE_TRANSVR_SWAPPED (-200) /* [Transvr]:Be plugged in. [Obj]:(Not used) */ +#define STATE_TRANSVR_DISCONNECTED (-300) /* [Transvr]:Un-plugged. [Obj]:Link down, and not provide service. */ +#define STATE_TRANSVR_UNEXCEPTED (-901) /* [Transvr]:Any [Obj]:Any, and not in expect case. */ + +/* Task state define */ +#define STATE_T_TASK_WAIT (110) +#define STATE_T_TASK_DONE (0) +#define STATE_T_TASK_INIT (-110) +#define STATE_T_TASK_FAIL (-410) + + +/* Event for task handling */ +#define EVENT_TRANSVR_TASK_WAIT (2101) +#define EVENT_TRANSVR_TASK_DONE (0) +#define EVENT_TRANSVR_TASK_FAIL (-2101) +/* Event for initial handling */ +#define EVENT_TRANSVR_INIT_UP (2201) +#define EVENT_TRANSVR_INIT_DOWN (1) +#define EVENT_TRANSVR_INIT_REINIT (-2201) +#define EVENT_TRANSVR_INIT_FAIL (-2202) +/* Event for others */ +#define EVENT_TRANSVR_RELOAD_FAIL (-2301) +#define EVENT_TRANSVR_EXCEP_INIT (-2401) +#define EVENT_TRANSVR_EXCEP_UP (-2402) +#define EVENT_TRANSVR_EXCEP_DOWN (-2403) +#define EVENT_TRANSVR_EXCEP_SWAP (-2404) +#define EVENT_TRANSVR_EXCEP_EXCEP (-2405) +#define EVENT_TRANSVR_EXCEP_ISOLATED (-2406) +#define EVENT_TRANSVR_I2C_CRASH (-2501) + +/* Transceiver error code define */ +#define ERR_TRANSVR_UNINIT (-201) +#define ERR_TRANSVR_UNPLUGGED (-202) +#define ERR_TRANSVR_ABNORMAL (-203) +#define ERR_TRANSVR_NOSTATE (-204) +#define ERR_TRANSVR_NOTSUPPORT (-205) +#define ERR_TRANSVR_BADINPUT (-206) +#define ERR_TRANSVR_UPDATE_FAIL (-207) +#define ERR_TRANSVR_RELOAD_FAIL (-208) +#define ERR_TRANSVR_INIT_FAIL (-209) +#define ERR_TRANSVR_UNDEFINED (-210) +#define ERR_TRANSVR_TASK_FAIL (-211) +#define ERR_TRANSVR_TASK_BUSY (-212) +#define ERR_TRANSVR_UEVENT_FAIL (-213) +#define ERR_TRANSVR_FUNC_DISABLE (-214) +#define ERR_TRANSVR_I2C_CRASH (-297) +#define ERR_TRNASVR_BE_ISOLATED (-298) +#define ERR_TRANSVR_UNEXCPT (-299) + +/* For debug */ +#define DEBUG_TRANSVR_INT_VAL (-99) +#define DEBUG_TRANSVR_HEX_VAL (0xfe) +#define DEBUG_TRANSVR_STR_VAL "ERROR" + +/* For system internal */ +#define VAL_TRANSVR_COMID_ARREESS (0x50) +#define VAL_TRANSVR_COMID_OFFSET (0x00) +#define VAL_TRANSVR_EXTPHY_ADDR_56 (0x56) +#define VAL_TRANSVR_8472_READY_ADDR (0x51) +#define VAL_TRANSVR_8472_READY_PAGE (-1) +#define VAL_TRANSVR_8472_READY_OFFSET (110) +#define VAL_TRANSVR_8472_READY_BIT (0) +#define VAL_TRANSVR_8472_READY_VALUE (0) +#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_READY_ADDR (0x50) +#define VAL_TRANSVR_8436_READY_PAGE (-1) +#define VAL_TRANSVR_8436_READY_OFFSET (2) +#define VAL_TRANSVR_8436_READY_BIT (0) +#define VAL_TRANSVR_8436_READY_VALUE (0) +#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_PWD_ADDR (0x50) +#define VAL_TRANSVR_8436_PWD_PAGE (-1) +#define VAL_TRANSVR_8436_PWD_OFFSET (123) +#define VAL_TRANSVR_PAGE_FREE (-99) +#define VAL_TRANSVR_PAGE_SELECT_OFFSET (127) +#define VAL_TRANSVR_PAGE_SELECT_DELAY (5) +#define VAL_TRANSVR_TASK_RETRY_FOREVER (-999) +#define VAL_TRANSVR_FUNCTION_DISABLE (-1) +#define STR_TRANSVR_SFP "SFP" +#define STR_TRANSVR_QSFP "QSFP" +#define STR_TRANSVR_QSFP_PLUS "QSFP+" +#define STR_TRANSVR_QSFP28 "QSFP28" + +/* For transvr buf len */ +#define LEN_TRANSVR_S_STR (16) +#define LEN_TRANSVR_M_STR (32) +#define LEN_TRANSVR_L_STR (64) + +/* Optical wavelength */ +#define VAL_OPTICAL_WAVELENGTH_SR (850) +#define VAL_OPTICAL_WAVELENGTH_LR (1310) +#define VAL_OPTICAL_WAVELENGTH_ER (1550) + +/* Switch chip type define */ +#define CHIP_TYPE_MAGNOLIA (31001) /* Magnolia, Hudson32i, Spruce */ +#define CHIP_TYPE_REDWOOD (31002) /* Redwood, Cypress, Sequoia */ +#define CHIP_TYPE_MAPLE (31003) /* Maple */ + +#define CHIP_TYPE_LAVENDER (31011) /* Lavender */ + +/* Info from transceiver EEPROM */ +struct eeprom_map_s { + int addr_br; int page_br; int offset_br; int length_br; + int addr_cdr; int page_cdr; int offset_cdr; int length_cdr; + int addr_comp_rev; int page_comp_rev; int offset_comp_rev; int length_comp_rev; + int addr_connector; int page_connector; int offset_connector; int length_connector; + int addr_diag_type; int page_diag_type; int offset_diag_type; int length_diag_type; + int addr_extbr; int page_extbr; int offset_extbr; int length_extbr; + int addr_ext_id; int page_ext_id; int offset_ext_id; int length_ext_id; + int addr_id; int page_id; int offset_id; int length_id; + int addr_len_sm; int page_len_sm; int offset_len_sm; int length_len_sm; + int addr_len_smf; int page_len_smf; int offset_len_smf; int length_len_smf; + int addr_len_om1; int page_len_om1; int offset_len_om1; int length_len_om1; + int addr_len_om2; int page_len_om2; int offset_len_om2; int length_len_om2; + int addr_len_om3; int page_len_om3; int offset_len_om3; int length_len_om3; + int addr_len_om4; int page_len_om4; int offset_len_om4; int length_len_om4; + int addr_option; int page_option; int offset_option; int length_option; + int addr_rate_id; int page_rate_id; int offset_rate_id; int length_rate_id; + int addr_rx_am; int page_rx_am; int offset_rx_am; int length_rx_am; + int addr_rx_em; int page_rx_em; int offset_rx_em; int length_rx_em; + int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los; + int addr_rx_power; int page_rx_power; int offset_rx_power; int length_rx_power; + int addr_soft_rs0; int page_soft_rs0; int offset_soft_rs0; int length_soft_rs0; + int addr_soft_rs1; int page_soft_rs1; int offset_soft_rs1; int length_soft_rs1; + int addr_temp; int page_temp; int offset_temp; int length_temp; + int addr_trancomp; int page_trancomp; int offset_trancomp; int length_trancomp; + int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext; + int addr_tx_bias; int page_tx_bias; int offset_tx_bias; int length_tx_bias; + int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable; + int addr_tx_eq; int page_tx_eq; int offset_tx_eq; int length_tx_eq; + int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault; + int addr_tx_power; int page_tx_power; int offset_tx_power; int length_tx_power; + int addr_vendor_name; int page_vendor_name; int offset_vendor_name; int length_vendor_name; + int addr_vendor_pn; int page_vendor_pn; int offset_vendor_pn; int length_vendor_pn; + int addr_vendor_rev; int page_vendor_rev; int offset_vendor_rev; int length_vendor_rev; + int addr_vendor_sn; int page_vendor_sn; int offset_vendor_sn; int length_vendor_sn; + int addr_voltage; int page_voltage; int offset_voltage; int length_voltage; + int addr_wavelength; int page_wavelength; int offset_wavelength; int length_wavelength; +}; + + +struct transvr_worker_s; + +/* Class of transceiver object */ +struct transvr_obj_s { + + /* ========== Object private property ========== + * [Prop]: id + * [Desc]: Type of serial transceiver. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h + */ + uint8_t id; + + /* [Prop]: connector + * [Desc]: Connector type. + * [Note]: SFP : A0h / 2 + * QSFP: 00h / 130 + */ + uint8_t connector; + + /* [Prop]: transvr_comp + * [Desc]: Transceiver compliance code. + * [Note]: SFP: SFF-8472 + * - Normal : A0h / offset 3-10 + * - Extended: A0h / offset 36 + * QSFP: SFF-8436 & SFF-8636 + * - Normal : 00h / offset 131-138 + * - Extended: 00h / offset 192 + */ + uint8_t transvr_comp[8]; + uint8_t transvr_comp_ext; + + /* [Prop]: vendor_name + * [Desc]: SFP vendor name (ASCII 16 byte char). + * [Note]: ex:FINISAR CORP. + */ + char *vendor_name; + + /* [Prop]: vendor_pn + * [Desc]: Part number provided by SFP vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_pn; + + /* [Prop]: vendor_rev + * [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char). + * [Note]: + */ + char *vendor_rev; + + /* [Prop]: vendor_sn + * [Desc]: Serial number provided by vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_sn; + + /* [Prop]: Extended identifier + * [Desc]: SFP: + * => None + * + * QSFP: + * => This byte contained two information: + * (1) Power consumption class + * (2) CDR function present + * [Note]: Bit description as below: + * [SFP] + * None + * + * [QSFP] + * (1) Power consumption class: + * Class 1: 1.5W (Bit6-7 = 00:) + * Class 2: 2.0W (Bit6-7 = 01:) + * Class 3: 2.5W (Bit6-7 = 10:) + * Class 4: 3.5W (Bit6-7 = 11:) + * Class 5: 4.0W (Bit0-1 = 01:) + * Class 6: 4.5W (Bit0-1 = 10:) + * Class 7: 5.0W (Bit0-1 = 11:) + * (2) CDR function present: + * Bit2: 0 = No CDR in RX + * 1 = CDR present in RX + * Bit3: 0 = No CDR in TX + * 1 = CDR present in TX + */ + uint8_t ext_id; + + /* [Prop]: br + * [Desc]: Nominal bit rate, units of 100 MBits/sec. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh + * has val: 0x67 + * no val : + */ + uint8_t br; + + /* [Prop]: extbr + * [Desc]: Extended br (00h/222) + * [Desc]: Nominal bit rate per channel, units of 250 Mbps. + * Complements. Byte 140. See Table 32A. + */ + uint8_t extbr; + + /* [Prop]: len_sm + * [Desc]: Length (single mode)-(100's)m + * [Note]: This value specifies the link length that is supported by the transceiver + * while operating in compliance with the applicable standards using single mode + * fiber. The value is in units of 100 meters. A value of 255 means that the + * transceiver supports a link length greater than 25.4 km. A value of zero means + * that the transceiver does not support single mode fiber or that the length + * information must be determined from the transceiver technology. + */ + int len_sm; + + /* [Prop]: len_smf + * [Desc]: Length (single mode)-km + * [Note]: Addition to EEPROM data from original GBIC definition. This value specifies + * the link length that is supported by the transceiver while operating in + * compliance with the applicable standards using single mode fiber. The value + * is in units of kilometers. A value of 255 means that the transceiver supports + * a link length greater than 254 km. A value of zero means that the transceiver + * does not support single mode fiber or that the length information must be + * determined from the transceiver technology. + */ + int len_smf; + + /* [Prop]: len_om1 + * [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om1; + + /* [Prop]: len_om2 + * [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om2; + + /* [Prop]: len_om3 + * [Desc]: Length (50um, OM3) + * [Note]: This value specifies link length that is supported by the transceiver while + * operating in compliance with applicable standards using 50 micron multimode + * OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255 + * means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber + * or that the length information must be determined from the transceiver technology. + */ + int len_om3; + + /* [Prop]: len_om4 + * [Desc]: Length (50um, OM4) and Length (Active Cable or Copper) + * [Note]: For optical links, this value specifies link length that is supported by the + * transceiver while operating in compliance with applicable standards using 50 micron + * multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of + * 255 means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber or that + * the length information must be determined from the transceiver codes specified in Table 5-3. + * + * For copper links, this value specifies minimum link length supported by the transceiver + * while operating in compliance with applicable standards using copper cable. For active + * cable, this value represents actual length. The value is in units of 1 meter. A value of 255 + * means the transceiver supports a link length greater than 254 meters. A value of zero means + * the transceiver does not support copper or active cables or the length information must be + * determined from transceiver technology. Further information about cable design, equalization, + * and connectors is usually required to guarantee meeting a particular length requirement. + */ + int len_om4; + + /* [Prop]: comp_rev + * [Desc]: SFF spec revision compliance + * [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver + * complies with. (unsigned integer) + */ + uint8_t comp_rev; + + /* [Prop]: CDR + * [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal + * retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which + * directs traffic around the internal CDR. (Reference: SFF-8636) + * [Note]: value=0xff: ON. + * value=0x00: OFF. + */ + uint8_t cdr; + + /* [Prop]: rate_id + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Addr: A0h / Offset: 13 + * 2. Value description: + * 00h Unspecified + * 01h SFF-8079 (4/2/1G Rate_Select & AS0/AS1) + * 02h SFF-8431 (8/4/2G Rx Rate_Select only) + * 03h Unspecified * + * 04h SFF-8431 (8/4/2G Tx Rate_Select only) + * 05h Unspecified * + * 06h SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) + * 07h Unspecified * + * 08h FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G + * 09h Unspecified * + * 0Ah FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only, + * Low=8G/4G + * 0Bh Unspecified * + * 0Ch FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + * 0Dh Unspecified * + * 0Eh 10/8G Rx and Tx Rate_Select controlling the operation or locking + * modes of the internal signal conditioner, retimer or CDR, according + * to the logic table defined in Table 10-2, High Bit Rate + * (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode, + * the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11) + * and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1. + * 0Fh Unspecified * + * 10h-FFh Unallocated + */ + int rate_id; + + /* [Prop]: soft_rs0 + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Writing '1' selects full bandwidth operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 110 / Bit: 3 + */ + uint8_t soft_rs0; + + /* [Prop]: soft_rs1 + * [Desc]: Soft Rate Select 1(TX). + * [Note]: 1. Writing '1' selects full bandwidth TX operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 118 / Bit: 3 + */ + uint8_t soft_rs1; + + /* [Prop]: diag_type + * [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92) + * [Note]: Description in SFF-8472 as below: + * Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance + * with this document. + * Bit6: Digital diagnostic monitoring implemented (described in this document). + * Must be '1' for compliance with this document. + * Bit5 Internally calibrated + * Bit4 Externally calibrated + * Bit3 Received power measurement type.0 = OMA, 1 = average power + * Bit2 Address change required see section above, "addressing modes" + * Bit1-0 Unallocated + */ + uint8_t diag_type; + + /* [Prop]: curr_temp + * [Desc]: Transceiver Current Temperature (A2h/96-97) + * [Note]: 1. Dependent on diag_type. + * 2. 96: High byte + * 3. 97: Low byte + * 4. This feature only for SFP + */ + uint8_t curr_temp[2]; + + /* [Prop]: curr_vol + * [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23) + * [Note]: 1. Dependent on diag_type. + * 2. 98: High byte + * 3. 99: Low byte + * 4. This feature only for SFP + * 5. Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts + */ + uint8_t curr_voltage[2]; + + /* [Prop]: curr_tx_bias + * [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27) + * [Note]: 1. Dependent on diag_type. + * 2. 100: High byte + * 3. 101: Low byte + * 4. This feature only for SFP + * 5. Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + uint8_t curr_tx_bias[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + uint8_t curr_tx_power[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + uint8_t curr_rx_power[8]; + + /* [Prop]: wavelength + * [Desc]: Wavelength or Copper Cable Attenuation + * [Note]: (Following is info from SFF-8636) + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is a + * 16-bit hex value with Byte 186 as high order byte and Byte 187 as low + * order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. If the free side device is identified as + * copper cable these registers will be used to define the cable attenuation. + * An indication of 0 dB attenuation refers to the case where the attenuation + * is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + uint8_t wavelength[2]; + + /* [Prop]: Amplitude control + * [Desc]: Amplitude control + * [Note]: QSFP28 => SFF-8636 03H Byte-238/239 + */ + uint8_t rx_am[2]; + + /* [Prop]: Emphasis control + * [Desc]: Emphasis control + * [Note]: SFP+/28 => SFF-8472 A2H Byte-115 + * QSFP28 => SFF-8636 03H Byte-236/237 + */ + uint8_t rx_em[2]; + + /* [Prop]: Soft Rx LOS + * [Desc]: Soft Rx LOS which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 3: + * - Bit 0: L-Rx1 LOS + * - Bit 1: L-Rx2 LOS + * - Bit 2: L-Rx3 LOS + * - Bit 3: L-Rx4 LOS + */ + uint8_t rx_los; + + /* [Prop]: Soft Tx Disable + * [Desc]: Soft Tx Disable which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Disable + * - Bit 1: Tx2 Disable + * - Bit 2: Tx3 Disable + * - Bit 3: Tx4 Disable + */ + uint8_t tx_disable; + + /* [Prop]: Soft Tx Fault + * [Desc]: Soft Tx Fault which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Fault + * - Bit 1: Tx2 Fault + * - Bit 2: Tx3 Fault + * - Bit 3: Tx4 Fault + */ + uint8_t tx_fault; + + /* [Prop]: Transceiver EQUALIZATION + * [Desc]: Transceiver EQUALIZATION + * [Note]: SFP+/28 => SFF-8472 A2H Byte-114 + * QSFP28 => SFF-8636 03H Byte-234/235 + */ + uint8_t tx_eq[2]; + + /* [Prop]: OPTION VALUES + * [Desc]: The bits in the option field shall specify the options implemented in the transceiver. + * [Note]: SFP+/28 => SFF-8472 A0H Byte-64/65 + * QSFP+/28 => SFF-8636 00H Byte-193/195 + */ + uint8_t option[3]; + + /* [Prop]: External PHY offset + * [Desc]: It needs to be setup first if you want to access transceiver external phy. + * [Note]: This feature dependent on transceiver. + * Currently, only 1G-RJ45 transceiver supported it. + */ + uint8_t extphy_offset; + + /* ========== Object private property ========== + */ + struct device *transvr_dev_p; + struct eeprom_map_s *eeprom_map_p; + struct i2c_client *i2c_client_p; + struct ioexp_obj_s *ioexp_obj_p; + struct transvr_worker_s *worker_p; + struct mutex lock; + char swp_name[32]; + int auto_config; + int auto_tx_disable; + int chan_id; + int chipset_type; + int curr_page; + int info; + int ioexp_virt_offset; + int lane_id[8]; + int layout; + int mode; + int retry; + int state; + int temp; + int type; + + /* ========== Object public functions ========== + */ + int (*get_id)(struct transvr_obj_s *self); + int (*get_ext_id)(struct transvr_obj_s *self); + int (*get_connector)(struct transvr_obj_s *self); + int (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p); + int (*get_power_cls)(struct transvr_obj_s *self); + int (*get_br)(struct transvr_obj_s *self); + int (*get_len_sm)(struct transvr_obj_s *self); + int (*get_len_smf)(struct transvr_obj_s *self); + int (*get_len_om1)(struct transvr_obj_s *self); + int (*get_len_om2)(struct transvr_obj_s *self); + int (*get_len_om3)(struct transvr_obj_s *self); + int (*get_len_om4)(struct transvr_obj_s *self); + int (*get_comp_rev)(struct transvr_obj_s *self); + int (*get_comp_eth_1)(struct transvr_obj_s *self); + int (*get_comp_eth_10)(struct transvr_obj_s *self); + int (*get_comp_eth_10_40)(struct transvr_obj_s *self); + int (*get_comp_extend)(struct transvr_obj_s *self); + int (*get_cdr)(struct transvr_obj_s *self); + int (*get_rate_id)(struct transvr_obj_s *self); + int (*get_soft_rs0)(struct transvr_obj_s *self); + int (*get_soft_rs1)(struct transvr_obj_s *self); + int (*get_info)(struct transvr_obj_s *self); + int (*get_if_type)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_speed)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_lane)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p); + int (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_am)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_em)(struct transvr_obj_s *self, char *buf_p); + int (*get_wavelength)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_offset)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_reg)(struct transvr_obj_s *self, char *buf_p); + int (*set_cdr)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs0)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs1)(struct transvr_obj_s *self, int input_val); + int (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_tx_eq)(struct transvr_obj_s *self, int input_val); + int (*set_rx_am)(struct transvr_obj_s *self, int input_val); + int (*set_rx_em)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_offset)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_reg)(struct transvr_obj_s *self, int input_val); + + /* ========== Object private functions ========== + */ + int (*init)(struct transvr_obj_s *self); + int (*clean)(struct transvr_obj_s *self); + int (*check)(struct transvr_obj_s *self); + int (*update_all)(struct transvr_obj_s *self, int show_err); + int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name); + int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name); + int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action); + int (*dump_all)(struct transvr_obj_s* self); +}; + + +/* For AVL Mapping */ +struct transvr_avl_s { + char vendor_name[32]; + char vendor_pn[32]; + int (*init)(struct transvr_obj_s *self); +}; + + +/* Worker for long term task of transceiver */ +struct transvr_worker_s { + /* Task Parameter */ + struct transvr_obj_s *transvr_p; + struct transvr_worker_s *next_p; + struct transvr_worker_s *pre_p; + unsigned long trigger_time; + char func_name[64]; + int retry; + int state; + + /* Task private data */ + void *p_data; + + /* Call back function */ + int (*main_task)(struct transvr_worker_s *task); + int (*post_task)(struct transvr_worker_s *task); +}; + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode); + +void lock_transvr_obj(struct transvr_obj_s *self); +void unlock_transvr_obj(struct transvr_obj_s *self); +int isolate_transvr_obj(struct transvr_obj_s *self); + +int resync_channel_tier_2(struct transvr_obj_s *self); + +void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + +#endif /* TRANSCEIVER_H */ + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/setup.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/setup.py new file mode 100644 index 000000000000..c48f6ef8da07 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize Ivnetec D6332 platforms', + + packages=['sonic_platform'], +) + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/__init__.py new file mode 100644 index 000000000000..4bfefa0fb636 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/chassis.py new file mode 100644 index 000000000000..b9e0afd8501f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/chassis.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import re + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.eeprom import Eeprom + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu + from sonic_platform.qsfp import QSfp + from sonic_platform.event_monitor import EventMonitor + from sonic_platform.thermal import Thermal + from sonic_platform.component import Component + from sonic_platform.watchdog import Watchdog +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/reboot-cause/" +REBOOT_CAUSE_FILE = "reboot-cause.txt" +PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt" +monitor = None + +class Chassis(ChassisBase): + + __num_of_fans = 5 + __num_of_psus = 2 + __num_of_sfps = 32 + __start_of_qsfp = 1 + __num_of_thermals = 15 + __num_of_components= 4 + + def __init__(self): + ChassisBase.__init__(self) + + # Initialize EEPROM + self._eeprom = Eeprom() + self._eeprom_data = self._eeprom.get_eeprom_data() + + # Initialize FAN + for index in range(self.__num_of_fans): + fan = Fan(index) + self._fan_list.append(fan) + + # Initialize PSU + for index in range(self.__num_of_psus): + psu = Psu(index) + self._psu_list.append(psu) + + # Initialize SFP + for index in range(self.__num_of_sfps): + sfp = QSfp(index) #only qsfp on platform D6332 + self._sfp_list.append(sfp) + + # Initialize THERMAL + for index in range(self.__num_of_thermals): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + # Initialize COMPONENT + for index in range(self.__num_of_components): + component = Component(index) + self._component_list.append(component) + + # Initialize WATCHDOG + self._watchdog = Watchdog() + + + 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 + + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr(self._eeprom_data) + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_str(self._eeprom_data) + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + +############################################## +# Chassis methods +############################################## + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr(self._eeprom_data) + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.serial_number_str(self._eeprom_data) + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + description = 'None' + reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER + + reboot_cause_path = PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE + prev_reboot_cause_path = PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE + + sw_reboot_cause = self.__read_txt_file(reboot_cause_path) or "Unknown" + prev_sw_reboot_cause = self.__read_txt_file(prev_reboot_cause_path) or "Unknown" + + if sw_reboot_cause == "Unknown" and (prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause == self.REBOOT_CAUSE_POWER_LOSS): + reboot_cause = self.REBOOT_CAUSE_POWER_LOSS + description = prev_sw_reboot_cause + elif sw_reboot_cause != "Unknown": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = sw_reboot_cause + elif prev_reboot_cause_path != "Unknown": + reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE + description = prev_sw_reboot_cause + + return (reboot_cause, description) + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + global monitor + port_dict = {} + while True: + with EventMonitor(timeout) as monitor: + while True: + event = monitor.get_events() + + if not bool(event): + return True, {'sfp':port_dict} + else: + if event['SUBSYSTEM'] == 'swps': + portname = event['DEVPATH'].split("/")[-1] + rc = re.match(r"port(?P\d+)",portname) + if rc is not None: + if event['ACTION'] == "remove": + remove_num = int(rc.group("num")) + port_dict[remove_num] = "0" + elif event['ACTION'] == "add": + add_num = int(rc.group("num")) + port_dict[add_num] = "1" + return True, {'sfp':port_dict} + else: + return False, {'sfp':port_dict} + else: + pass diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/component.py new file mode 100644 index 000000000000..116daa8d30f8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/component.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python + +try: + import os + import logging + from sonic_platform_base.component_base import ComponentBase + from sonic_platform.inv_const import Common + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +OS_SYSTEM_SUCCESS = 0 + +CPLD1_INFO_PATH = Common.I2C_PREFIX+"/0-0077/info" +CPLD2_INFO_PATH = Common.I2C_PREFIX+"/0-0077/info" #info of 2 cpld are combined by inv_cpld under this path +BIOS_VER_PATH = "/sys/class/dmi/id/bios_version" +BIOS_CS_PATH = Common.I2C_PREFIX+"/0-0077/bios_cs" + +CPLD1_INDEX = 0 +CPLD2_INDEX = 1 +MAIN_BIOS_INDEX = 2 +BACKUP_BIOS_INDEX = 3 + + +COMPONENT_NAME_LIST = [ + "CPLD1", + "CPLD2", + "Main BIOS", + "Backup BIOS", +] + +COMPONENT_DESC_LIST = [ + "platform management and control LED", + "platform management and control LED", + "Main Basic Input/Output System", + "Backup Basic Input/Output System", +] + + +BIOS_ID_MAPPING_TABLE = { + 0: MAIN_BIOS_INDEX, + 1: BACKUP_BIOS_INDEX +} + +class Component(ComponentBase): + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def __set_attr_value(self, attr_path, value): + try: + with open(attr_path, 'r+') as reg_file: + reg_file.write(value) + except IOError as e: + logging.error("Error: unable to open file: %s" % str(e)) + return False + + return True + + def __get_current_bios(self): + current_bios=self.__get_attr_value(BIOS_CS_PATH) + if current_bios != 'ERR': + ''' + Get first char to convert to bios ID + ''' + current_bios = int(current_bios[:1]) + else: + current_bios = None + + return current_bios + + def __get_cpld_version(self): + ''' + The info output would be like: + The CPLD release date is 06/13/2019. + The PCB version is 5 + The CPLD version is 1.1 + ''' + cpld_version = None + ret_str = None + path = None + target="" + + if self.index == CPLD1_INDEX: + path = CPLD1_INFO_PATH + target="The CPLD version is " + elif self.index == CPLD2_INDEX: + path = CPLD2_INFO_PATH + target="The CPLD2 version is " + else: + logging.error("Unable support index %d", self.index) + + if path !=None: + try: + with open(path, 'r') as file: + ret_str = file.read() + except Exception as error: + logging.error("Unable to open file %s", path) + + if ret_str!=None: + start_idx=ret_str.find(target) + if start_idx > 0: + start_idx = start_idx+len(target) + offset = ret_str[start_idx:].find('\n') + if offset > 0: + end_idx=start_idx+offset + cpld_version=ret_str[start_idx:end_idx].strip('\n') + + if cpld_version is None: + logging.error("Unable to parse cpld info %d", self.index) + + return cpld_version + + + def __get_bios_version(self): + bios_version = None + current_bios_id=self.__get_current_bios() + + if current_bios_id != None : + if self.index == BIOS_ID_MAPPING_TABLE[current_bios_id]: + try: + with open(BIOS_VER_PATH, 'r') as file: + bios_version = file.read().strip('\n') + except Exception as error: + logging.error("Unable to open file %s", BIOS_VER_PATH) + else: + logging.error("Only support bios version of current running BIOS") + bios_version = "N/A" + + return bios_version + + def __install_cpld_firmware(self,image_path): + logging.error("[Component][__install_cpld_firmware] Currently not support FW update on platform D6332") + raise NotImplementedError + + def __install_bios_firmware(self,image_path): + logging.error("[Component][__install_bios_firmware] Currently not support FW update on platform D6332") + raise NotImplementedError + + __get_version_callback_list = { + CPLD1_INDEX:__get_cpld_version, + CPLD2_INDEX:__get_cpld_version, + MAIN_BIOS_INDEX:__get_bios_version, + BACKUP_BIOS_INDEX:__get_bios_version, + } + + def __init__(self, component_index): + self.index = component_index + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return COMPONENT_NAME_LIST[self.index] + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return COMPONENT_DESC_LIST[self.index] + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + return self.__get_version_callback_list[self.index](self) + + 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 + """ + logging.error("[Component][install_firmware] Currently not support FW update on platform D6332") + raise NotImplementedError \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/eeprom.py new file mode 100644 index 000000000000..0d210b47beb2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/eeprom.py @@ -0,0 +1,77 @@ +# +# Name: eeprom.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +EEPROM_TOTAL_LEN_HIGH_OFFSET = 9 +EEPROM_TOTAL_LEN_LOW_OFFSET = 10 +EEPROM_TLV_TYPE_OFFSET = 0 +EEPROM_TLV_LEN_OFFSET = 1 +EEPROM_TLV_VALUE_OFFSET = 2 + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.__eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0055/eeprom" + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + self.__eeprom_tlv_dict = dict() + try: + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (ord(eeprom[EEPROM_TOTAL_LEN_HIGH_OFFSET]) << 8) | ord(eeprom[EEPROM_TOTAL_LEN_LOW_OFFSET]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + EEPROM_TLV_VALUE_OFFSET) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + EEPROM_TLV_VALUE_OFFSET + + ord(eeprom[tlv_index + EEPROM_TLV_LEN_OFFSET])] + code = "0x%02X" % (ord(tlv[EEPROM_TLV_TYPE_OFFSET])) + + if ord(tlv[EEPROM_TLV_TYPE_OFFSET]) == self._TLV_CODE_VENDOR_EXT: + value = str((ord(tlv[EEPROM_TLV_VALUE_OFFSET]) << 24) | (ord(tlv[EEPROM_TLV_VALUE_OFFSET+1]) << 16) | + (ord(tlv[EEPROM_TLV_VALUE_OFFSET+2]) << 8) | ord(tlv[EEPROM_TLV_VALUE_OFFSET+3])) + value += str(tlv[6:6 + ord(tlv[EEPROM_TLV_LEN_OFFSET])]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32: + break + + tlv_index += ord(eeprom[tlv_index+EEPROM_TLV_LEN_OFFSET]) + EEPROM_TLV_VALUE_OFFSET + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2] + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.__eeprom_tlv_dict + + def get_eeprom_data(self): + return self.__eeprom_data diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/event_monitor.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/event_monitor.py new file mode 100644 index 000000000000..247943075934 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/event_monitor.py @@ -0,0 +1,94 @@ +# +# event_monitor.py +# Description: module to minitor events +# + +try: + import socket + from collections import OrderedDict + import os +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +NETLINK_KOBJECT_UEVENT = 15 + +class EventMonitor(object): + + def __init__(self, timeout): + self.recieved_events = OrderedDict() + self.socket = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT) + self.timeout = timeout + + def start(self): + self.socket.bind((os.getpid(), -1)) + + if 0 == self.timeout: + self.socket.settimeout(None) + else: + self.socket.settimeout(self.timeout/1000.0) + + def stop(self): + self.socket.close() + + def __enter__(self): + self.start() + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.stop() + + def __iter__(self): + while True: + for item in self.next_events(): + yield item + + def next_events(self): + try: + data = self.socket.recv(16384) + event = {} + for item in data.split(b'\x00'): + if not item: + # check if we have an event and if we already received it + if event and event['SEQNUM'] not in self.recieved_events: + self.recieved_events[event['SEQNUM']] = None + if (len(self.recieved_events) > 100): + self.recieved_events.popitem(last=False) + yield event + event = {} + else: + try: + k, v = item.split(b'=', 1) + event[k.decode('ascii')] = v.decode('ascii') + except ValueError: + pass + except socket.timeout: + yield event + + def get_events(self): + event = {} + while True: + try: + data = self.socket.recv(16384) + + for item in data.split(b'\x00'): + if not item: + # check if we have an event and if we already received it + # if no item and event empty, means received garbled + if bool(event): + if event['SEQNUM'] not in self.recieved_events: + self.recieved_events[event['SEQNUM']] = None + if (len(self.recieved_events) > 100): + self.recieved_events.popitem(last=False) + return event + else: + event = {} + else: + try: + k, v = item.split(b'=', 1) + event[k] = v + except ValueError: + pass + except socket.timeout: + return event + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/fan.py new file mode 100644 index 000000000000..4f62ccaafd56 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/fan.py @@ -0,0 +1,330 @@ +#!/usr/bin/env python +# +# Name: fan.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import math + import os + import logging + from sonic_platform_base.fan_base import FanBase + from sonic_platform.inv_const import FanConst , PsuConst, Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +MAX_SPEED_OF_FAN_FRONT = 23500 +MAX_SPEED_OF_FAN_BACK = 19900 +MAX_SPEED_OF_FAN_PSU = 26000 +MAX_PWM_OF_FAN = 255 + +class Fan(FanBase): + + __name_of_fans = ['FAN1','FAN2','FAN3','FAN4','FAN5','PSU1_FAN1','PSU2_FAN1'] + __start_of_psu_fans = FanConst().PSU_FAN_START_INDEX + + def __init__(self, index): + self.__index = index + + if self.__index >= self.__start_of_psu_fans: + psu_id=self.__index- self.__start_of_psu_fans + self.__presence_attr = "{}/i2c-inv_cpld/psu{}".format(Common.I2C_PREFIX,psu_id+1) + self.__rpm1_attr = "{}/psu{}/fan1_input".format(Common.INFO_PREFIX, psu_id+1) + else: + self.__fan_type = "{}/i2c-inv_cpld/fanmodule{}_type".format(Common.I2C_PREFIX, self.__index + 1) + self.__rpm1_attr = "{}/i2c-inv_cpld/fan{}_input".format(Common.I2C_PREFIX, 2*self.__index + 1) + self.__rpm2_attr = "{}/i2c-inv_cpld/fan{}_input".format(Common.I2C_PREFIX, 2*self.__index + 2) + self.__pwm_attr = "{}/i2c-inv_cpld/pwm{}".format(Common.I2C_PREFIX, self.__index + 1) + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def read_fru(self, attr_type): + fan_addr=FanConst.FAN_VPD_ADDR_BASE+self.__index + path="/sys/bus/i2c/devices/{}-00{}/eeprom".format(FanConst.FAN_VPD_CHANNEL, hex(fan_addr)[2:] ) + content=[] + attr_idx=0 + attr_length=0 + + if(os.path.exists(path)): + with open(path,'rw') as f: + content=f.read() + target_offset=ord(content[FanConst.TLV_PRODUCT_INFO_OFFSET_IDX-1]) + target_offset*=8 #spec defined: offset are in multiples of 8 bytes + + attr_idx=target_offset+FanConst.TLV_PRODUCT_INFO_AREA_START + for i in range(1,attr_type): + if attr_idx > len(content): + raise SyntaxError + attr_length=(ord(content[attr_idx]))&(0x3f) + attr_idx+=(attr_length+1); + + attr_length=(ord(content[attr_idx]))&(0x3f) + attr_idx+=1 + else: + logging.error("[FAN] Can't find path to eeprom : %s" % path) + return SyntaxError + + return content[attr_idx:attr_idx+attr_length] + + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return self.__name_of_fans[self.__index] + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + + if self.__index >= self.__start_of_psu_fans: + #check fan of psu presence if psu presence + attr_path = self.__presence_attr + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (attr_rv == PsuConst.PSU_TYPE_LIST[0] or attr_rv == PsuConst.PSU_TYPE_LIST[1]): + presence = True + else: + raise SyntaxError + else: + attr_path = self.__fan_type + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if(attr_rv==FanConst.FAN_TYPE_LIST[0] or attr_rv==FanConst.FAN_TYPE_LIST[1]): + presence = True + else: + raise SyntaxError + + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + if self.__index >= self.__start_of_psu_fans: + return NotImplementedError + else: + model=self.read_fru(FanConst.TLV_ATTR_TYPE_MODEL) + if not model: + return NotImplementedError + + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + if self.__index >= self.__start_of_psu_fans: + return NotImplementedError + else: + serial=self.read_fru(FanConst.TLV_ATTR_TYPE_SERIAL) + if not serial: + return NotImplementedError + + 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 + """ + status = False + + if self.__index >= self.__start_of_psu_fans: + #check fan of psu presence if psu presence + attr_path = self.__presence_attr + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (attr_rv == PsuConst.PSU_TYPE_LIST[1]): + status = True + else: + raise SyntaxError + else: + status = self.get_presence() + + return status + +############################################## +# FAN methods +############################################## + + 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 = 'N/A' + + if self.__index >= self.__start_of_psu_fans: + raise NotImplementedError + else: + attr_path = self.__fan_type + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + + #"Normal Type", //00 + #"REVERSAL Type", //01 + #"UNPLUGGED", //10 + #"UNPLUGGED", //11 + + if(attr_rv==FanConst.FAN_TYPE_LIST[0]): + direction = 'FAN_DIRECTION_EXHAUST' + elif(attr_rv==FanConst.FAN_TYPE_LIST[1]): + direction = 'FAN_DIRECTION_INTAKE' + else: + raise SyntaxError + + 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) + """ + speed = 0 + + if self.__index >= self.__start_of_psu_fans: + attr_rv1 = self.__get_attr_value(self.__presence_attr) + if( attr_rv1 == PsuConst.PSU_TYPE_LIST[0] or attr_rv1 == PsuConst.PSU_TYPE_LIST[1] ): + attr_path1 = self.__rpm1_attr + attr_rv1 = self.__get_attr_value(attr_path1) + if (attr_rv1 != 'ERR' ): + speed = int(attr_rv1) * 100 / MAX_SPEED_OF_FAN_PSU + elif(attr_rv1 == 'ERR' ): + raise SyntaxError + else: + attr_path1 = self.__rpm1_attr + attr_path2 = self.__rpm2_attr + + if self.get_presence() and None != attr_path1: + attr_rv1 = self.__get_attr_value(attr_path1) + attr_rv2 = self.__get_attr_value(attr_path2) + if (attr_rv1 != 'ERR' and attr_rv2 != 'ERR'): + fan1_input = int(attr_rv1) + speed = math.ceil(float(fan1_input * 100 / MAX_SPEED_OF_FAN_FRONT)) + fan2_input = int(attr_rv2) + speed += math.ceil(float(fan2_input * 100 / MAX_SPEED_OF_FAN_BACK)) + speed /= 2 + elif (attr_rv1 != 'ERR'): + fan1_input = int(attr_rv1) + if self.__index >= self.__start_of_psu_fans: + speed = speed = math.ceil(float(fan1_input * 100 / MAX_SPEED_OF_FAN_PSU)) + else: + speed = math.ceil(float(fan1_input * 100 / MAX_SPEED_OF_FAN_FRONT)) + elif (attr_rv2 != 'ERR'): + fan2_input = int(attr_rv2) + speed += math.ceil(float(fan2_input * 100 / MAX_SPEED_OF_FAN_BACK)) + else: + raise SyntaxError + + 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) + """ + speed = 0 + + if self.__index >= self.__start_of_psu_fans: + return NotImplementedError + else: + attr_path = self.__pwm_attr + + if self.get_presence() and None != attr_path: + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + pwm = int(attr_rv) + speed = math.ceil(float(pwm * 100 / MAX_PWM_OF_FAN)) + else: + raise SyntaxError + + return speed + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + raise NotImplementedError + + 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 + """ + raise NotImplementedError + + 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 + """ + raise NotImplementedError + + 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 + """ + raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/inv_const.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/inv_const.py new file mode 100644 index 000000000000..ace488f551da --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/inv_const.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +class Common(): + INFO_PREFIX = "/usr/share/sonic/platform" + I2C_PREFIX = "/sys/bus/i2c/devices" + +class FanConst(): + #fan vpd info + FAN_VPD_CHANNEL= 1 + FAN_VPD_ADDR_BASE=0x52 + #fru status + TLV_PRODUCT_INFO_OFFSET_IDX=5 + TLV_PRODUCT_INFO_AREA_START=3 + TLV_ATTR_TYPE_SERIAL=5 + TLV_ATTR_TYPE_MODEL=2 + + PSU_FAN_START_INDEX = 5 + FAN_TYPE_LIST=["0:Normal Type","1:REVERSAL Type","2:UNPLUGGED","3:UNPLUGGED"] #defined in inv_cpld + +class PsuConst(): + PSU_TYPE_LIST=["0:unpowered","1:normal","2:not installed","3:not installed"] #defined in inv_cpld + PSU_I2C_ADDR=["2-005a","2-005b"] \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/platform.py new file mode 100644 index 000000000000..7d6bda4502de --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/platform.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/psu.py new file mode 100644 index 000000000000..93352636078d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/psu.py @@ -0,0 +1,254 @@ +#!/usr/bin/env python +# +# Name: psu.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import logging + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan + from sonic_platform.inv_const import FanConst , PsuConst, Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +VOLTAGE_UPPER_LIMIT = 14 +VOLTAGE_LOWER_LIMIT = 10 + +class Psu(PsuBase): + + __num_of_fans = 1 + __name_of_psus = ['PSU1','PSU2'] + + def __init__(self, index): + self.__index = index + psu_id = self.__index + 1 + + self.__psu_presence_attr = "{}/i2c-inv_cpld/psu{}".format(Common.I2C_PREFIX,psu_id) + self.__psu_voltage_out_attr = "{}/psu{}/in2_input".format(Common.INFO_PREFIX, psu_id) + self.__psu_current_out_attr = "{}/psu{}/curr2_input".format(Common.INFO_PREFIX, psu_id) + self.__psu_power_out_attr = "{}/psu{}/power2_input".format(Common.INFO_PREFIX, psu_id) + + # Get the start index of fan list + self.__fan_psu_start_index = self.__index + FanConst().PSU_FAN_START_INDEX + + # Overriding _fan_list class variable defined in PsuBase, to make it unique per Psu object + self._fan_list = [] + + # Initialize FAN + for x in range(self.__fan_psu_start_index, self.__fan_psu_start_index + self.__num_of_fans): + fan = Fan(x) + self._fan_list.append(fan) + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return self.__name_of_psus[self.__index] + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = self.__psu_presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (attr_rv == PsuConst.PSU_TYPE_LIST[0] or attr_rv == PsuConst.PSU_TYPE_LIST[1]): + presence = True + else: + raise SyntaxError + + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + #model = 'Unknow' + #attr_path = self.__psu_model_attr + + #attr_rv = self.__get_attr_value(attr_path) + #if (attr_rv != 'ERR'): + # if (attr_rv != ''): + # model = attr_rv + #else: + # raise SyntaxError + + #return model + raise NotImplementedError + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + """ + serial = 'Unknow' + attr_path = self.__psu_serial_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (attr_rv != ''): + serial = attr_rv + else: + raise SyntaxError + + return serial + """ + raise NotImplementedError + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + status = False + attr_path = self.__psu_presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (attr_rv == PsuConst.PSU_TYPE_LIST[1]): + status = True + else: + raise SyntaxError + + return status + + +############################################## +# PSU methods +############################################## + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + voltage_out = 0.0 + attr_path = self.__psu_voltage_out_attr + + if(self.get_presence()): + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + voltage_out = float(attr_rv) / 1000 + else: + raise SyntaxError + + return voltage_out + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + current_out = 0.0 + attr_path = self.__psu_current_out_attr + + if(self.get_presence()): + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + current_out = float(attr_rv) / 1000 + else: + raise SyntaxError + + return current_out + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, e.g. 302.6 + """ + power_out = 0.0 + attr_path = self.__psu_power_out_attr + + if(self.get_presence()): + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + power_out = float(attr_rv) / 1000 + else: + raise SyntaxError + + return power_out + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + powergood_status = False + voltage_out = self.get_voltage() + + #Check the voltage out with 12V, plus or minus 20 percentage. + if (VOLTAGE_LOWER_LIMIT <= voltage_out and voltage_out <= VOLTAGE_UPPER_LIMIT ): + powergood_status = True + + return powergood_status + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + + Args: + color: A string representing the color with which to set the + PSU status LED + + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/qsfp.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/qsfp.py new file mode 100644 index 000000000000..17763cd1264f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/qsfp.py @@ -0,0 +1,1023 @@ +#!/usr/bin/env python +# +# Name: qsfp.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import logging + from ctypes import create_string_buffer + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from sonic_platform.inv_const import Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +INFO_OFFSET = 128 +THRE_OFFSET = 384 #128*3 +DOM_OFFSET = 0 + +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNEL_THRESHOLD_OFFSET = 176 +QSFP_CHANNEL_THRESHOLD_WIDTH = 16 + +QSFP_REG_VALUE_ENABLE = "0x1" +QSFP_REG_VALUE_DISABLE = "0x0" + +class QSfp(SfpBase): + + __platform = "x86_64-inventec_d6332-r0" + __hwsku = "INVENTEC-D6332" + __port_to_i2c_mapping = { + 0:12, 1:13, 2:14, 3:15, 4:16, 5:17, 6:18, 7:19, + 8:20, 9:21, 10:22, 11:23, 12:24, 13:25, 14:26, 15:27, + 16:28, 17:29, 18:30, 19:31, 20:32, 21:33, 22:34, 23:35, + 24:36, 25:37, 26:38, 27:39, 28:40, 29:41, 30:42, 31:43, + } + + + def __init__(self, index): + self.__index = index + + self.__port_end = len(self.__port_to_i2c_mapping) - 1 + + self.__presence_attr = None + self.__eeprom_path = None + if self.__index in range(0, self.__port_end + 1): + self.__presence_attr = "/sys/class/swps/port{}/present".format(self.__index) + self.__lpmode_attr = "/sys/class/swps/port{}/lpmod".format(self.__index) + self.__reset_attr = "/sys/class/swps/port{}/reset".format(self.__index) + self.__eeprom_path = "{}/{}-0050/eeprom".format(Common.I2C_PREFIX, self.__port_to_i2c_mapping[self.__index]) + + SfpBase.__init__(self) + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def __set_attr_value(self, attr_path, value): + + try: + with open(attr_path, 'r+') as reg_file: + reg_file.write(value) + except IOError as e: + logging.error("Error: unable to open file: '%s'" % str(e)) + return False + + return True + + def __is_host(self): + return os.system("docker > /dev/null 2>&1") == 0 + + def __get_path_to_port_config_file(self): + host_platform_root_path = '/usr/share/sonic/device' + docker_hwsku_path = '/usr/share/sonic/hwsku' + + host_platform_path = "/".join([host_platform_root_path, self.__platform]) + hwsku_path = "/".join([host_platform_path, self.__hwsku]) if self.__is_host() else docker_hwsku_path + + return "/".join([hwsku_path, "port_config.ini"]) + + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + eeprom_raw = [] + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_eeprom_path = self.__eeprom_path + try: + with open(sysfs_eeprom_path, mode="rb", buffering=0) as sysfsfile_eeprom: + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + raw_len = len(raw) + for n in range(0, raw_len): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except (OSError, IOError): + logging.error("File error: %s", sysfs_eeprom_path) + return None + + return eeprom_raw + + def __write_eeprom_specific_bytes(self, offset, buffer): + sysfs_eeprom_path = self.__eeprom_path + + try: + with open(sysfs_eeprom_path, "r+b") as sysfsfile_eeprom: + sysfsfile_eeprom.seek(offset) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + logging.error("Error: unable to open file: '%s'" % str(e)) + return False + + return True + + def __convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + name = None + + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings(self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.__index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = self.__presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 0): + presence = True + else: + raise SyntaxError + + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + model = "N/A" + offset = INFO_OFFSET + sfpi_obj = sff8436InterfaceId() + if not self.get_presence() or not sfpi_obj: + return model + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + model = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + serial = "N/A" + offset = INFO_OFFSET + sfpi_obj = sff8436InterfaceId() + if not self.get_presence() or not sfpi_obj: + return serial + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + serial = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + + 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 + """ + status = False + tx_fault = self.get_tx_fault() + + if self.get_presence() and tx_fault and not any(tx_fault): + status = True + + return status + +############################################## +# SFP methods +############################################## + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardwarerev |1*255VCHAR |hardware version of SFP + serialnum |1*255VCHAR |serial number of the SFP + manufacturename |1*255VCHAR |SFP vendor name + modelname |1*255VCHAR |SFP model name + Connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + mominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + transceiver_info_dict_keys = ['type', 'hardwarerev', + 'serialnum', 'manufacturename', + 'modelname', 'Connector', + 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', + 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', + 'vendor_oui'] + + qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', 'Length Cable Assembly(m)') + + qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', 'Fibre Channel transmission media', + 'Fibre Channel Speed') + + sfpi_obj = sff8436InterfaceId() + if not self.get_presence() or not sfpi_obj: + return {} + + offset = INFO_OFFSET + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes((offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_QSFP) + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes((offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_QSFP) + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + + sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + + sfp_vendor_date_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + + transceiver_info_dict = dict.fromkeys(transceiver_info_dict_keys, 'N/A') + + if sfp_interface_bulk_data: + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' + + transceiver_info_dict['cable_type'] = "Unknown" + transceiver_info_dict['cable_length'] = "Unknown" + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + compliance_code_dict = dict() + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict_keys = ['rx_los', 'tx_fault', + 'reset_status', 'power_lpmode', + 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + + if not self.get_presence() or not sfpi_obj or not sfpd_obj: + return {} + + transceiver_dom_info_dict = dict.fromkeys(transceiver_dom_info_dict_keys, 'N/A') + offset = DOM_OFFSET + offset_xcvr = INFO_OFFSET + + # 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((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_dom_capability(qsfp_dom_capability_raw, 0) + else: + return None + + dom_temperature_raw = self.__read_eeprom_specific_bytes((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) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes((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) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes((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) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['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 = {} + dom_channel_monitor_raw = None + 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((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: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((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) + 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'] + + if dom_channel_monitor_raw: + 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'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self.__convert_string_to_num(transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['tx_disable'] = self.get_tx_disable() + transceiver_dom_info_dict['tx_disable_channel'] = self.get_tx_disable_channel() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + transceiver_dom_threshold_info_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + sfpd_obj = sff8436Dom() + if not self.get_presence() or not sfpd_obj: + return {} + + transceiver_dom_threshold_dict = dict.fromkeys(transceiver_dom_threshold_info_dict_keys, 'N/A') + offset = THRE_OFFSET + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw: + module_threshold_values = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + module_threshold_data = module_threshold_values.get('data') + if module_threshold_data: + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value'] + + dom_channel_thres_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNEL_THRESHOLD_OFFSET), QSFP_CHANNEL_THRESHOLD_WIDTH) + channel_threshold_values = sfpd_obj.parse_channel_threshold_values(dom_channel_thres_raw, 0) + channel_threshold_data = channel_threshold_values.get('data') + if channel_threshold_data: + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerhighwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value'] + + for key in transceiver_dom_threshold_dict: + transceiver_dom_threshold_dict[key] = self.__convert_string_to_num(transceiver_dom_threshold_dict[key]) + + return transceiver_dom_threshold_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + reset_status = False + attr_path = self.__reset_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 0): + reset_status = True + else: + raise SyntaxError + + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + rx_los_list = [] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(QSFP_CHANNL_RX_LOS_STATUS_OFFSET, QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + + return rx_los_list + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + tx_fault_list = [] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(QSFP_CHANNL_TX_FAULT_STATUS_OFFSET, QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + + return tx_fault_list + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + tx_disable = False + tx_disable_list = [] + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return tx_disable + + dom_control_raw = self.__read_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + tx_disable_list.append('On' == dom_control_data['data']['TX1Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX2Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX3Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX4Disable']['value']) + tx_disable = tx_disable_list[0] or tx_disable_list[1] or tx_disable_list[2] or tx_disable_list[3] + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_channel = 0 + tx_disable_list = [] + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return tx_disable_channel + + dom_control_raw = self.__read_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + tx_disable_list.append('On' == dom_control_data['data']['TX1Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX2Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX3Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX4Disable']['value']) + + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disable_channel |= 1 << i + + return tx_disable_channel + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + lpmode = False + attr_path = self.__lpmode_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 1): + lpmode = True + else: + raise SyntaxError + + return lpmode + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + power_override = False + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return power_override + + dom_control_raw = self.__read_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + power_override = ('On' == dom_control_data['data']['PowerOverride']['value']) + + return power_override + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + temp = "N/A" + sfpd_obj = sff8436Dom() + offset = DOM_OFFSET + + if not self.get_presence() or not sfpd_obj: + return temp + + dom_temperature_raw = self.__read_eeprom_specific_bytes((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) + temp = self.__convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + + return temp + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + voltage = "N/A" + sfpd_obj = sff8436Dom() + offset = DOM_OFFSET + + if not self.get_presence() or not sfpd_obj: + return voltage + + dom_voltage_raw = self.__read_eeprom_specific_bytes((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) + voltage = self.__convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + + return voltage + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + tx_bias_list = [] + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + offset = DOM_OFFSET + offset_xcvr = INFO_OFFSET + + if not self.get_presence() or not sfpd_obj: + return [] + + qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes((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_dom_capability(qsfp_dom_capability_raw, 0) + else: + return None + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes((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) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + + dom_channel_monitor_data = {} + dom_channel_monitor_raw = None + 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((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: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((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) + + + if dom_channel_monitor_raw is not None: + tx_bias_list.append(self.__convert_string_to_num(dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self.__convert_string_to_num(dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self.__convert_string_to_num(dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self.__convert_string_to_num(dom_channel_monitor_data['data']['TX4Bias']['value'])) + + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + rx_power_list = [] + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + offset = DOM_OFFSET + offset_xcvr = INFO_OFFSET + + if not self.get_presence() or not sfpd_obj: + return [] + + qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes((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_dom_capability(qsfp_dom_capability_raw, 0) + else: + return None + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes((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) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + + dom_channel_monitor_data = {} + dom_channel_monitor_raw = None + 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((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: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((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) + + + if dom_channel_monitor_raw is not None: + rx_power_list.append(self.__convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self.__convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self.__convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self.__convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value'])) + + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + tx_power_list = [] + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + offset = DOM_OFFSET + offset_xcvr = INFO_OFFSET + + if not self.get_presence() or not sfpd_obj: + return [] + + qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes((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_dom_capability(qsfp_dom_capability_raw, 0) + else: + return None + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes((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) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + + dom_channel_monitor_data = {} + dom_channel_monitor_raw = None + 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')): + pass + + else: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((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) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value'])) + + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + + return self.__set_attr_value(self.__reset_attr, QSFP_REG_VALUE_ENABLE) + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + tx_disable_ctl = 0xf if tx_disable else 0x0 + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + + return self.__write_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, buffer) + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + channel_state = self.get_tx_disable_channel() + if disable: + tx_disable_ctl = channel_state | channel + else: + tx_disable_ctl = channel_state & (~channel & 0xf) + + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + + return self.__write_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, buffer) + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if lpmode is True: + reg_value = QSFP_REG_VALUE_ENABLE + else: + reg_value = QSFP_REG_VALUE_DISABLE + + return self.__set_attr_value(self.__lpmode_attr, reg_value) + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + + return self.__write_eeprom_specific_bytes(QSFP_POWEROVERRIDE_OFFSET, buffer) diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/thermal.py new file mode 100644 index 000000000000..ee1220a6c9fa --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/thermal.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python +# +# Name: thermal.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import logging + from sonic_platform_base.thermal_base import ThermalBase + from sonic_platform.inv_const import PsuConst, Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PSU1_THERMAL_START=9 +PSU2_THERMAL_START=12 + +class Thermal(ThermalBase): + + __core_temp_path = Common.INFO_PREFIX+"/coretemp/temp{}_input" + __switch_thermal_path = Common.INFO_PREFIX+"/board_thermal_{}/temp1_input" + __psu_thermal_path = Common.INFO_PREFIX+"/psu{}/temp{}_input" + __max_temp_path = Common.INFO_PREFIX+"/coretemp/temp{}_max" + __name_of_thermal = [ + "Core 0 Temperature", + "Core 1 Temperature", + "Core 2 Temperature", + "Core 3 Temperature", + "Core 4 Temperature", + "CPU Board Temperature", + "FrontSide Temperature", + "RearSide Temperature", + "NearASIC Temperature", + "PSU1 Temperature1", + "PSU1 Temperature2", + "PSU1 Temperature3", + "PSU2 Temperature1", + "PSU2 Temperature2", + "PSU2 Temperature3" + ] + __thermal_path_list = [ + __core_temp_path.format(1), + __core_temp_path.format(2), + __core_temp_path.format(3), + __core_temp_path.format(4), + __core_temp_path.format(5), + __switch_thermal_path.format(1), + __switch_thermal_path.format(2), + __switch_thermal_path.format(3), + __switch_thermal_path.format(4), + __psu_thermal_path.format(1,1), + __psu_thermal_path.format(1,2), + __psu_thermal_path.format(1,3), + __psu_thermal_path.format(2,1), + __psu_thermal_path.format(2,2), + __psu_thermal_path.format(2,3) + ] + __max_temp_path_list = [ + __max_temp_path.format(1), + __max_temp_path.format(2), + __max_temp_path.format(3), + __max_temp_path.format(4), + __max_temp_path.format(5), + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + + + def __init__(self, index): + self.__index = index + + self.__thermal_temp_attr = self.__thermal_path_list[self.__index] + self.__max_temp_attr = self.__max_temp_path_list[self.__index] + + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return self.__name_of_thermal[self.__index] + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence=False + + if (self.__index < PSU1_THERMAL_START): + attr_path = self.__thermal_temp_attr + presence=os.path.isfile(attr_path) + elif(self.__index < PSU2_THERMAL_START): + path="{}/i2c-inv_cpld/psu1".format(Common.I2C_PREFIX) + psu_state=self.__get_attr_value(path) + if (psu_state != 'ERR'): + if (psu_state == PsuConst.PSU_TYPE_LIST[0] or psu_state == PsuConst.PSU_TYPE_LIST[1]): + presence = True + else: + path="{}/i2c-inv_cpld/psu2".format(Common.I2C_PREFIX) + psu_state=self.__get_attr_value(path) + if (psu_state != 'ERR'): + if (psu_state == PsuConst.PSU_TYPE_LIST[0] or psu_state == PsuConst.PSU_TYPE_LIST[1]): + 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 + """ + raise NotImplementedError + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + raise NotImplementedError + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + status = False + if self.get_presence(): + status = True + + return status + +############################################## +# THERMAL methods +############################################## + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temperature = 0.0 + attr_path = self.__thermal_temp_attr + + if(self.get_presence()): + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + temperature = float(attr_rv) / 1000 + else: + raise SyntaxError + + return temperature + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + attr_path = self.__max_temp_attr + + if attr_path == '': + raise NotImplementedError + else: + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + high_threshold = float(attr_rv) / 1000 + else: + raise SyntaxError + + return high_threshold + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + raise NotImplementedError + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/watchdog.py new file mode 100644 index 000000000000..42718541f5c2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/watchdog.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +try: + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Watchdog(WatchdogBase): + def __init__(self): + print('init Watchdog()') + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* available + value. + Returns: + An integer specifying the *actual* number of seconds the watchdog + was armed with. On failure returns -1. + """ + raise NotImplementedError + + def disarm(self): + """ + Disarm the hardware watchdog + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + raise NotImplementedError + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + Returns: + A boolean, True if watchdog is armed, False if not + """ + raise NotImplementedError + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds remaining on + the watchdog timer + Returns: + An integer specifying the number of seconds remaining on thei + watchdog timer. If the watchdog is not armed, returns -1. + """ + raise NotImplementedError + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/utils/inventec_d6332_util.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/utils/inventec_d6332_util.py new file mode 100755 index 000000000000..a468a323d6fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/utils/inventec_d6332_util.py @@ -0,0 +1,325 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Inventec, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import syslog +import time + +DEBUG = False +args = [] +FORCE = 0 +FAN_VPD_CHANNEL= 1 +FAN_VPD_ADDR_BASE=0x52 +FAN_NUM=5 +RETRY_LIMIT = 5 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV: ', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[D6332]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +" with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def link_dir(prefix,dst): + retry=0 + ret=False + while(ret==False and retry /sys/bus/i2c/devices/i2c-0/new_device' +#'echo inv_cpld 0x33 > /sys/bus/i2c/devices/i2c-0/i2c-2/new_device', +#'echo inv_cpld 0x77 > /sys/bus/i2c/devices/i2c-0/i2c-2/new_device' +] + + +drivers =[ +#kernel-dirvers +'gpio_ich', +'lpc_ich', +'i2c-i801', +'i2c-mux', +'i2c-mux-pca954x', +'i2c-mux-pca9541', +'i2c-dev', +'ucd9000', +#inv-modules +'inv_eeprom', +'inv_cpld', +'lm75', +'inv_platform', +#'monitor', +'swps'] + + +# Modify for fast-reboot +def system_install(boot_option): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("rmmod i2c_ismt ", 1) + if status: + print output + if FORCE == 0: + return status + + status, output = exec_cmd("rmmod i2c-i801 ", 1) + if status: + print output + if FORCE == 0: + return status + + status, output = exec_cmd("rmmod gpio_ich ", 1) + if status: + print output + if FORCE == 0: + return status + + status, output = exec_cmd("rmmod lpc_ich ", 1) + if status: + print output + if FORCE == 0: + return status + + #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) + + #install drivers + ''' boot_option: 0 - normal, 1 - fast-reboot''' + for i in range(0,len(drivers)): + if drivers[i] == "swps": + if boot_option == 1: + status, output = exec_cmd("modprobe swps io_no_init=1", 1) + else: + status, output = exec_cmd("modprobe "+drivers[i], 1) + else: + status, output = exec_cmd("modprobe "+drivers[i], 1) + + if status: + print output + if FORCE == 0: + return status + + #instantiate devices + for i in range(0,len(instantiate)): + #time.sleep(1) + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + for addr_offset in range (0,FAN_NUM): + addr=FAN_VPD_ADDR_BASE+addr_offset + cmd = "i2cdetect -y "+str(FAN_VPD_CHANNEL)+" "+str(addr)+" "+str(addr)+" | grep "+str(hex(addr)).replace('0x','') + result=os.system(cmd) + if( result==0 ): + cmd="echo inv_eeprom "+str(addr)+" > /sys/bus/i2c/devices/i2c-"+FAN_VPD_CHANNEL + status, output = exec_cmd(cmd,1) + if status: + print output + if FORCE == 0: + return status +# +# INV_FIX-4037 +# It replaces the original sff8436 driver with the optoe driver +# + #optoe map to i2c-bus\ + for i in range(12,20): + cmd="echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-4/i2c-"+str(i)+"/new_device" + status, output =exec_cmd(cmd,1) + if status: + print output + if FORCE == 0: + return status + for i in range(20,28): + status, output =exec_cmd("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-5/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(28,36): + status, output =exec_cmd("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-6/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(36,44): + status, output =exec_cmd("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-7/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + #make softlink for device info + for i in range(0,len(_path_prefix_list)): + if( os.path.islink(_path_dst_list[i]) ): + os.unlink(_path_dst_list[i]) + syslog.syslog(syslog.LOG_WARNING, "Path %s exists, remove before link again" % _path_dst_list[i] ) + link_dir(_path_prefix_list[i],_path_dst_list[i]) + + return + + +def system_ready(): + if not device_found(): + return False + return True + +def install(boot_option=0): + ''' boot_option: 0 - normal, 1 - fast-reboot ''' + if not device_found(): + print "No device, installing...." + status = system_install(boot_option) + if status: + if FORCE == 0: + return status + else: + print "D6332 devices detected...." + return + +def uninstall(): + global FORCE + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0) + ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-5", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/Makefile new file mode 100755 index 000000000000..6c1acbc88a71 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/Makefile @@ -0,0 +1,9 @@ +obj-m += ucd9000.o +obj-m += i2c-mux-pca9541.o +obj-m += gpio-ich.o +obj-m += lpc_ich.o +obj-m += inv_cpld.o +obj-m += inv_platform.o +obj-m += inv_eeprom.o +obj-m += swps.o +swps-objs := inv_swps.o inv_mux.o io_expander.o transceiver.o diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/gpio-ich.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/gpio-ich.c new file mode 100644 index 000000000000..4f6d643516b7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/gpio-ich.c @@ -0,0 +1,513 @@ +/* + * Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver + * + * Copyright (C) 2010 Extreme Engineering Solutions. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "gpio_ich" + +/* + * GPIO register offsets in GPIO I/O space. + * Each chunk of 32 GPIOs is manipulated via its own USE_SELx, IO_SELx, and + * LVLx registers. Logic in the read/write functions takes a register and + * an absolute bit number and determines the proper register offset and bit + * number in that register. For example, to read the value of GPIO bit 50 + * the code would access offset ichx_regs[2(=GPIO_LVL)][1(=50/32)], + * bit 18 (50%32). + */ +enum GPIO_REG { + GPIO_USE_SEL = 0, + GPIO_IO_SEL, + GPIO_LVL, + GPO_BLINK +}; + +static const u8 ichx_regs[4][3] = { + {0x00, 0x30, 0x40}, /* USE_SEL[1-3] offsets */ + {0x04, 0x34, 0x44}, /* IO_SEL[1-3] offsets */ + {0x0c, 0x38, 0x48}, /* LVL[1-3] offsets */ + {0x18, 0x18, 0x18}, /* BLINK offset */ +}; + +static const u8 ichx_reglen[3] = { + 0x30, 0x10, 0x10, +}; + +static const u8 avoton_regs[4][3] = { + {0x00, 0x80, 0x00}, + {0x04, 0x84, 0x00}, + {0x08, 0x88, 0x00}, +}; + +static const u8 avoton_reglen[3] = { + 0x10, 0x10, 0x00, +}; + +#define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start) +#define ICHX_READ(reg, base_res) inl((reg) + (base_res)->start) + +struct ichx_desc { + /* Max GPIO pins the chipset can have */ + uint ngpio; + + /* chipset registers */ + const u8 (*regs)[3]; + const u8 *reglen; + + /* GPO_BLINK is available on this chipset */ + bool have_blink; + + /* Whether the chipset has GPIO in GPE0_STS in the PM IO region */ + bool uses_gpe0; + + /* USE_SEL is bogus on some chipsets, eg 3100 */ + u32 use_sel_ignore[3]; + + /* Some chipsets have quirks, let these use their own request/get */ + int (*request)(struct gpio_chip *chip, unsigned offset); + int (*get)(struct gpio_chip *chip, unsigned offset); + + /* + * Some chipsets don't let reading output values on GPIO_LVL register + * this option allows driver caching written output values + */ + bool use_outlvl_cache; +}; + +static struct { + spinlock_t lock; + struct platform_device *dev; + struct gpio_chip chip; + struct resource *gpio_base; /* GPIO IO base */ + struct resource *pm_base; /* Power Mangagment IO base */ + struct ichx_desc *desc; /* Pointer to chipset-specific description */ + u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */ + u8 use_gpio; /* Which GPIO groups are usable */ + int outlvl_cache[3]; /* cached output values */ +} ichx_priv; + +static int modparam_gpiobase = -1; /* dynamic */ +module_param_named(gpiobase, modparam_gpiobase, int, 0444); +MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, " + "which is the default."); + +static int ichx_write_bit(int reg, unsigned nr, int val, int verify) +{ + unsigned long flags; + u32 data, tmp; + int reg_nr = nr / 32; + int bit = nr & 0x1f; + int ret = 0; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + data = ichx_priv.outlvl_cache[reg_nr]; + else + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + + if (val) + data |= 1 << bit; + else + data &= ~(1 << bit); + ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + ichx_priv.outlvl_cache[reg_nr] = data; + + tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + if (verify && data != tmp) + ret = -EPERM; + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return ret; +} + +static int ichx_read_bit(int reg, unsigned nr) +{ + unsigned long flags; + u32 data; + int reg_nr = nr / 32; + int bit = nr & 0x1f; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + data = ichx_priv.outlvl_cache[reg_nr] | data; + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return data & (1 << bit) ? 1 : 0; +} + +static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) +{ + return !!(ichx_priv.use_gpio & (1 << (nr / 32))); +} + +static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr) +{ + return ichx_read_bit(GPIO_IO_SEL, nr) ? GPIOF_DIR_IN : GPIOF_DIR_OUT; +} + +static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) +{ + /* + * Try setting pin as an input and verify it worked since many pins + * are output-only. + */ + if (ichx_write_bit(GPIO_IO_SEL, nr, 1, 1)) + return -EINVAL; + + return 0; +} + +static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, + int val) +{ + /* Disable blink hardware which is available for GPIOs from 0 to 31. */ + if (nr < 32 && ichx_priv.desc->have_blink) + ichx_write_bit(GPO_BLINK, nr, 0, 0); + + /* Set GPIO output value. */ + ichx_write_bit(GPIO_LVL, nr, val, 0); + + /* + * Try setting pin as an output and verify it worked since many pins + * are input-only. + */ + if (ichx_write_bit(GPIO_IO_SEL, nr, 0, 1)) + return -EINVAL; + + return 0; +} + +static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + return ichx_read_bit(GPIO_LVL, nr); +} + +static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + unsigned long flags; + u32 data; + + /* + * GPI 0 - 15 need to be read from the power management registers on + * a ICH6/3100 bridge. + */ + if (nr < 16) { + if (!ichx_priv.pm_base) + return -ENXIO; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + /* GPI 0 - 15 are latched, write 1 to clear*/ + ICHX_WRITE(1 << (16 + nr), 0, ichx_priv.pm_base); + data = ICHX_READ(0, ichx_priv.pm_base); + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return (data >> 16) & (1 << nr) ? 1 : 0; + } else { + return ichx_gpio_get(chip, nr); + } +} + +static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr) +{ + if (!ichx_gpio_check_available(chip, nr)) + return -ENXIO; + + /* + * Note we assume the BIOS properly set a bridge's USE value. Some + * chips (eg Intel 3100) have bogus USE values though, so first see if + * the chipset's USE value can be trusted for this specific bit. + * If it can't be trusted, assume that the pin can be used as a GPIO. + */ + if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f))) + return 0; + + return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV; +} + +static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr) +{ + /* + * Fixups for bits 16 and 17 are necessary on the Intel ICH6/3100 + * bridge as they are controlled by USE register bits 0 and 1. See + * "Table 704 GPIO_USE_SEL1 register" in the i3100 datasheet for + * additional info. + */ + if (nr == 16 || nr == 17) + nr -= 16; + + return ichx_gpio_request(chip, nr); +} + +static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val) +{ + ichx_write_bit(GPIO_LVL, nr, val, 0); +} + +static void ichx_gpiolib_setup(struct gpio_chip *chip) +{ + chip->owner = THIS_MODULE; + chip->label = DRV_NAME; + chip->parent = &ichx_priv.dev->dev; + + /* Allow chip-specific overrides of request()/get() */ + chip->request = ichx_priv.desc->request ? + ichx_priv.desc->request : ichx_gpio_request; + chip->get = ichx_priv.desc->get ? + ichx_priv.desc->get : ichx_gpio_get; + + chip->set = ichx_gpio_set; + chip->get_direction = ichx_gpio_get_direction; + chip->direction_input = ichx_gpio_direction_input; + chip->direction_output = ichx_gpio_direction_output; + chip->base = modparam_gpiobase; + chip->ngpio = ichx_priv.desc->ngpio; + chip->can_sleep = false; + chip->dbg_show = NULL; +} + +/* ICH6-based, 631xesb-based */ +static struct ichx_desc ich6_desc = { + /* Bridges using the ICH6 controller need fixups for GPIO 0 - 17 */ + .request = ich6_gpio_request, + .get = ich6_gpio_get, + + /* GPIO 0-15 are read in the GPE0_STS PM register */ + .uses_gpe0 = true, + + .ngpio = 50, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Intel 3100 */ +static struct ichx_desc i3100_desc = { + /* + * Bits 16,17, 20 of USE_SEL and bit 16 of USE_SEL2 always read 0 on + * the Intel 3100. See "Table 712. GPIO Summary Table" of 3100 + * Datasheet for more info. + */ + .use_sel_ignore = {0x00130000, 0x00010000, 0x0}, + + /* The 3100 needs fixups for GPIO 0 - 17 */ + .request = ich6_gpio_request, + .get = ich6_gpio_get, + + /* GPIO 0-15 are read in the GPE0_STS PM register */ + .uses_gpe0 = true, + + .ngpio = 50, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH7 and ICH8-based */ +static struct ichx_desc ich7_desc = { + .ngpio = 50, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH9-based */ +static struct ichx_desc ich9_desc = { + .ngpio = 61, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH10-based - Consumer/corporate versions have different amount of GPIO */ +static struct ichx_desc ich10_cons_desc = { + .ngpio = 61, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; +static struct ichx_desc ich10_corp_desc = { + .ngpio = 72, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Intel 5 series, 6 series, 3400 series, and C200 series */ +static struct ichx_desc intel5_desc = { + .ngpio = 76, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Avoton */ +static struct ichx_desc avoton_desc = { + /* Avoton has only 59 GPIOs, but we assume the first set of register + * (Core) has 32 instead of 31 to keep gpio-ich compliance + */ + .ngpio = 60, + .regs = avoton_regs, + .reglen = avoton_reglen, + .use_outlvl_cache = true, +}; + +static int ichx_gpio_request_regions(struct device *dev, + struct resource *res_base, const char *name, u8 use_gpio) +{ + int i; + + if (!res_base || !res_base->start || !res_base->end) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { + if (!(use_gpio & (1 << i))) + continue; + if (!devm_request_region(dev, + res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i], name)) + return -EBUSY; + } + return 0; +} + +static int ichx_gpio_probe(struct platform_device *pdev) +{ + struct resource *res_base, *res_pm; + int err; + struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev); + + if (!ich_info) + return -ENODEV; + + ichx_priv.dev = pdev; + + switch (ich_info->gpio_version) { + case ICH_I3100_GPIO: + ichx_priv.desc = &i3100_desc; + break; + case ICH_V5_GPIO: + ichx_priv.desc = &intel5_desc; + break; + case ICH_V6_GPIO: + ichx_priv.desc = &ich6_desc; + break; + case ICH_V7_GPIO: + ichx_priv.desc = &ich7_desc; + break; + case ICH_V9_GPIO: + ichx_priv.desc = &ich9_desc; + break; + case ICH_V10CORP_GPIO: + ichx_priv.desc = &ich10_corp_desc; + break; + case ICH_V10CONS_GPIO: + ichx_priv.desc = &ich10_cons_desc; + break; + case AVOTON_GPIO: + ichx_priv.desc = &avoton_desc; + break; + default: + return -ENODEV; + } + + spin_lock_init(&ichx_priv.lock); + res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); + ichx_priv.use_gpio = ich_info->use_gpio; + err = ichx_gpio_request_regions(&pdev->dev, res_base, pdev->name, + ichx_priv.use_gpio); + if (err) + return err; + + ichx_priv.gpio_base = res_base; + + /* + * If necessary, determine the I/O address of ACPI/power management + * registers which are needed to read the the GPE0 register for GPI pins + * 0 - 15 on some chipsets. + */ + if (!ichx_priv.desc->uses_gpe0) + goto init; + + res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0); + if (!res_pm) { + pr_warn("ACPI BAR is unavailable, GPI 0 - 15 unavailable\n"); + goto init; + } + + if (!devm_request_region(&pdev->dev, res_pm->start, + resource_size(res_pm), pdev->name)) { + pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n"); + goto init; + } + + ichx_priv.pm_base = res_pm; + +init: + ichx_gpiolib_setup(&ichx_priv.chip); + err = gpiochip_add_data(&ichx_priv.chip, NULL); + if (err) { + pr_err("Failed to register GPIOs\n"); + return err; + } + + pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base, + ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME); + + return 0; +} + +static int ichx_gpio_remove(struct platform_device *pdev) +{ + gpiochip_remove(&ichx_priv.chip); + + return 0; +} + +static struct platform_driver ichx_gpio_driver = { + .driver = { + .name = DRV_NAME, + }, + .probe = ichx_gpio_probe, + .remove = ichx_gpio_remove, +}; + +module_platform_driver(ichx_gpio_driver); + +MODULE_AUTHOR("Peter Tyser "); +MODULE_DESCRIPTION("GPIO interface for Intel ICH series"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/i2c-mux-pca9541.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/i2c-mux-pca9541.c new file mode 100644 index 000000000000..fa78379858e3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/i2c-mux-pca9541.c @@ -0,0 +1,573 @@ +/* + * I2C multiplexer driver for PCA9541 bus master selector + * + * Copyright (c) 2010 Ericsson AB. + * + * Author: Guenter Roeck + * + * Derived from: + * pca954x.c + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * The PCA9541 is a bus master selector. It supports two I2C masters connected + * to a single slave bus. + * + * Before each bus transaction, a master has to acquire bus ownership. After the + * transaction is complete, bus ownership has to be released. This fits well + * into the I2C multiplexer framework, which provides select and release + * functions for this purpose. For this reason, this driver is modeled as + * single-channel I2C bus multiplexer. + * + * This driver assumes that the two bus masters are controlled by two different + * hosts. If a single host controls both masters, platform code has to ensure + * that only one of the masters is instantiated at any given time. + */ + +#define PCA9541_CONTROL 0x01 +#define PCA9541_ISTAT 0x02 + +#define PCA9541_CTL_MYBUS (1 << 0) +#define PCA9541_CTL_NMYBUS (1 << 1) +#define PCA9541_CTL_BUSON (1 << 2) +#define PCA9541_CTL_NBUSON (1 << 3) +#define PCA9541_CTL_BUSINIT (1 << 4) +#define PCA9541_CTL_TESTON (1 << 6) +#define PCA9541_CTL_NTESTON (1 << 7) + +#define PCA9541_ISTAT_INTIN (1 << 0) +#define PCA9541_ISTAT_BUSINIT (1 << 1) +#define PCA9541_ISTAT_BUSOK (1 << 2) +#define PCA9541_ISTAT_BUSLOST (1 << 3) +#define PCA9541_ISTAT_MYTEST (1 << 6) +#define PCA9541_ISTAT_NMYTEST (1 << 7) + +#define PCA9641_ID 0x00 +#define PCA9641_ID_MAGIC 0x38 + +#define PCA9641_CONTROL 0x01 +#define PCA9641_STATUS 0x02 +#define PCA9641_TIME 0x03 + +#define PCA9641_CTL_LOCK_REQ BIT(0) +#define PCA9641_CTL_LOCK_GRANT BIT(1) +#define PCA9641_CTL_BUS_CONNECT BIT(2) +#define PCA9641_CTL_BUS_INIT BIT(3) +#define PCA9641_CTL_SMBUS_SWRST BIT(4) +#define PCA9641_CTL_IDLE_TIMER_DIS BIT(5) +#define PCA9641_CTL_SMBUS_DIS BIT(6) +#define PCA9641_CTL_PRIORITY BIT(7) + +#define PCA9641_STS_OTHER_LOCK BIT(0) +#define PCA9641_STS_BUS_INIT_FAIL BIT(1) +#define PCA9641_STS_BUS_HUNG BIT(2) +#define PCA9641_STS_MBOX_EMPTY BIT(3) +#define PCA9641_STS_MBOX_FULL BIT(4) +#define PCA9641_STS_TEST_INT BIT(5) +#define PCA9641_STS_SCL_IO BIT(6) +#define PCA9641_STS_SDA_IO BIT(7) + +#define PCA9641_RES_TIME 0x03 + + +#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) +#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) +#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) +#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) + +#define BUSOFF(x, y) (!((x) & PCA9641_CTL_LOCK_GRANT) && \ + !((y) & PCA9641_STS_OTHER_LOCK)) +#define other_lock(x) ((x) & PCA9641_STS_OTHER_LOCK) +#define lock_grant(x) ((x) & PCA9641_CTL_LOCK_GRANT) + +/* arbitration timeouts, in jiffies */ +#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ +#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ + +/* arbitration retry delays, in us */ +#define SELECT_DELAY_SHORT 50 +#define SELECT_DELAY_LONG 1000 + +struct pca9541 { + struct i2c_client *client; + unsigned long select_timeout; + unsigned long arb_timeout; +}; + +static const struct i2c_device_id pca9541_id[] = { + {"pca9541", 0}, + {"pca9641", 1}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, pca9541_id); + +#ifdef CONFIG_OF +static const struct of_device_id pca9541_of_match[] = { + { .compatible = "nxp,pca9541" }, + { .compatible = "nxp,pca9641" }, + {} +}; +#endif + +/* + * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock the adapter a second time. + */ +static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[2]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + buf[0] = command; + buf[1] = val; + msg.buf = buf; + ret = __i2c_transfer(adap, &msg, 1); + } else { + union i2c_smbus_data data; + + data.byte = val; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + command, + I2C_SMBUS_BYTE_DATA, &data); + } + + return ret; +} + +/* + * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock adapter a second time. + */ +static int pca9541_reg_read(struct i2c_client *client, u8 command) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + u8 val; + + if (adap->algo->master_xfer) { + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &command + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = &val + } + }; + ret = __i2c_transfer(adap, msg, 2); + if (ret == 2) + ret = val; + else if (ret >= 0) + ret = -EIO; + } else { + union i2c_smbus_data data; + + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_READ, + command, + I2C_SMBUS_BYTE_DATA, &data); + if (!ret) + ret = data.byte; + } + return ret; +} + +/* + * Arbitration management functions + */ + +/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ +static void pca9541_release_bus(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg >= 0 && !busoff(reg) && mybus(reg)) + pca9541_reg_write(client, PCA9541_CONTROL, + (reg & PCA9541_CTL_NBUSON) >> 1); +} + +/* + * Arbitration is defined as a two-step process. A bus master can only activate + * the slave bus if it owns it; otherwise it has to request ownership first. + * This multi-step process ensures that access contention is resolved + * gracefully. + * + * Bus Ownership Other master Action + * state requested access + * ---------------------------------------------------- + * off - yes wait for arbitration timeout or + * for other master to drop request + * off no no take ownership + * off yes no turn on bus + * on yes - done + * on no - wait for arbitration timeout or + * for other master to release bus + * + * The main contention point occurs if the slave bus is off and both masters + * request ownership at the same time. In this case, one master will turn on + * the slave bus, believing that it owns it. The other master will request + * bus ownership. Result is that the bus is turned on, and master which did + * _not_ own the slave bus before ends up owning it. + */ + +/* Control commands per PCA9541 datasheet */ +static const u8 pca9541_control[16] = { + 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 +}; + +/* + * Channel arbitration + * + * Return values: + * <0: error + * 0 : bus not acquired + * 1 : bus acquired + */ +static int pca9541_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg < 0) + return reg; + + if (busoff(reg)) { + int istat; + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + istat = pca9541_reg_read(client, PCA9541_ISTAT); + if (!(istat & PCA9541_ISTAT_NMYTEST) + || time_is_before_eq_jiffies(data->arb_timeout)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_NTESTON); + data->select_timeout = SELECT_DELAY_SHORT; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (mybus(reg)) { + /* + * Bus is on, and we own it. We are done with acquisition. + * Reset NTESTON and BUSINIT, then return success. + */ + if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg & ~(PCA9541_CTL_NTESTON + | PCA9541_CTL_BUSINIT)); + return 1; + } else { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + if (time_is_before_eq_jiffies(data->arb_timeout)) { + /* Time is up, take the bus and reset it. */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_BUSINIT + | PCA9541_CTL_NTESTON); + } else { + /* Request bus ownership if needed */ + if (!(reg & PCA9541_CTL_NTESTON)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg | PCA9541_CTL_NTESTON); + } + } + return 0; +} + +static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + + do { + ret = pca9541_arbitrate(client); + if (ret) + return ret < 0 ? ret : 0; + + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + pca9541_release_bus(client); + return 0; +} + +/* + * Arbitration management functions + */ +static void pca9641_release_bus(struct i2c_client *client) +{ + pca9541_reg_write(client, PCA9641_CONTROL, 0); +} + +/* + * Channel arbitration + * + * Return values: + * <0: error + * 0 : bus not acquired + * 1 : bus acquired + */ +static int pca9641_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg_ctl, reg_sts; + + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); + if (reg_ctl < 0) + return reg_ctl; + reg_sts = pca9541_reg_read(client, PCA9641_STATUS); + + if (BUSOFF(reg_ctl, reg_sts)) { + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + reg_ctl |= PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); + + if (lock_grant(reg_ctl)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + reg_ctl |= PCA9641_CTL_BUS_CONNECT + | PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + data->select_timeout = SELECT_DELAY_SHORT; + + return 1; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (lock_grant(reg_ctl)) { + /* + * Bus is on, and we own it. We are done with acquisition. + */ + reg_ctl |= PCA9641_CTL_BUS_CONNECT | PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + + return 1; + } else if (other_lock(reg_sts)) { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + reg_ctl |= PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + } + return 0; +} + +static int pca9641_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + + do { + ret = pca9641_arbitrate(client); + if (ret) + return ret < 0 ? ret : 0; + + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +static int pca9641_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + pca9641_release_bus(client); + return 0; +} + +static int pca9641_detect_id(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9641_ID); + if (reg == PCA9641_ID_MAGIC) + return 1; + else + return 0; +} + +/* + * I2C init/probing/exit functions + */ +static int pca9541_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = client->adapter; + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct i2c_mux_core *muxc; + struct pca9541 *data; + int force; + int ret; + int detect_id; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + detect_id = pca9641_detect_id(client); + /* + * I2C accesses are unprotected here. + * We have to lock the adapter before releasing the bus. + */ + if (detect_id == 0) { + i2c_lock_adapter(adap); + pca9541_release_bus(client); + i2c_unlock_adapter(adap); + } else { + i2c_lock_adapter(adap); + pca9641_release_bus(client); + i2c_unlock_adapter(adap); + } + + /* Create mux adapter */ + + force = 0; + if (pdata) + force = pdata->modes[0].adap_id; + if (detect_id == 0) { + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9541_select_chan, pca9541_release_chan); + } else { + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9641_select_chan, pca9641_release_chan); + } + if (!muxc) + return -ENOMEM; + + data = i2c_mux_priv(muxc); + data->client = client; + + i2c_set_clientdata(client, muxc); + + ret = i2c_mux_add_adapter(muxc, force, 0, 0); + if (ret) { + dev_err(&client->dev, "failed to register master selector\n"); + return ret; + } + + dev_info(&client->dev, "registered master selector for I2C %s\n", + client->name); + + return 0; +} + +static int pca9541_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + + i2c_mux_del_adapters(muxc); + return 0; +} + +static struct i2c_driver pca9541_driver = { + .driver = { + .name = "pca9541", + .of_match_table = of_match_ptr(pca9541_of_match), + }, + .probe = pca9541_probe, + .remove = pca9541_remove, + .id_table = pca9541_id, +}; + +module_i2c_driver(pca9541_driver); + +MODULE_AUTHOR("Guenter Roeck "); +MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_cpld.c new file mode 100644 index 000000000000..8e2693d2e251 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_cpld.c @@ -0,0 +1,1011 @@ +/* + * 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 +#include + +/* definition */ +#define CPLD_INFO_OFFSET 0x00 +#define CPLD_BIOSCS_OFFSET 0x04 +#define CPLD_CTL_OFFSET 0x0C +#define CPLD_SYSLED_OFFSET 0x0E +#define CPLD_LED_OFFSET 0x2E +#define CPLD_INT_OFFSET 0x30 +#define CPLD_INTMASK_OFFSET 0x31 +#define CPLD_INT2_OFFSET 0x32 +#define CPLD_INTMASK2_OFFSET 0x33 +#define CPLD_PSU_OFFSET 0x40 +#define CPLD_POWERSTATUS_OFFSET 0x41 +#define CPLD_PWM_OFFSET 0x50 +#define CPLD_RPM_OFFSET 0x55 +#define CPLD_FANSTATUS_OFFSET 0x69 +#define CPLD_FANLED_OFFSET 0x6B +#define CPLD_RESETBUTTONSTATUS_OFFSET 0x75 +#define CPLD_RSTCAUSE_OFFSET 0x76 +#define CPLD_WATCHDOGCOUNTER_OFFSET 0x77 +#define CPLD_WATCHDOGCONFIG_OFFSET 0x78 +#define CPLD_WATCHDOGENABLE_OFFSET 0x79 +#define CPLD_PANICCODE_OFFSET 0x7E +#define CPLD2_ADDRESS 0x33 + +#define FAN_NUM 4 +static u8 hasCPLD2 = 1; +static struct i2c_client *client2; + +/* Each client has this additional data */ +struct cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; + u8 diag; + struct task_struct *tsk; +}; + +/*-----------------------------------------------------------------------*/ +static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ + int i; + s32 temp = 0; + + for(i=0; iuser_msg_data; + + if(recv_msg->msg.data[0]==0 && recv_msg->msg.data_len>0) { + msg_result->result_length=recv_msg->msg.data_len-1; + memcpy(msg_result->result, &recv_msg->msg.data[1], recv_msg->msg.data_len-1); + } + ipmi_free_recv_msg(recv_msg); + mutex_unlock(&ipmi_mutex); + + return; +} + +int start_ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length) +{ + int rv=0,i; + int timeout; + + //wait previous command finish at least 50msec + timeout=50; + while((mutex_is_locked(&ipmi_mutex) == 1 || (mutex_is_locked(&ipmi2_mutex) == 1)) && (--timeout)>0) { usleep_range(1000,1010); } + if(timeout==0) { return -1; } + mutex_lock(&ipmi_mutex); + mutex_lock(&ipmi2_mutex); + + if(ipmi_mh_user == NULL) { + for (i=0,rv=1; i0) { usleep_range(1000,1100);} + if(timeout==0) { + mutex_unlock(&ipmi2_mutex); + return -1; + } + else { + *result_length=ipmiresult.result_length; + memcpy(result,ipmiresult.result,*result_length); + mutex_unlock(&ipmi2_mutex); + return 0; + } + } + return 0; +} +EXPORT_SYMBOL(start_ipmi_command); + +static int cpld_thread(void *p) +{ +#ifndef XORP + struct i2c_client *client = p; + + u8 byte[9]; + uint8_t result[MAX_IPMI_RECV_LENGTH]; + int result_len=0; + + //Handle LED control by the driver + byte[0]=0x01; + cpld_i2c_write(client, byte, CPLD_CTL_OFFSET, 1); + + //Disable BMC Watchdog + byte[0]=0x04; + byte[1]=0x00; + byte[2]=0x00; + byte[3]=0x00; + byte[4]=0x2C; + byte[5]=0x01; + start_ipmi_command(0x06, 0x24, byte, 6, result, &result_len); +#endif + return 0; +} +/*-----------------------------------------------------------------------*/ +/* sysfs attributes for hwmon */ +static ssize_t show_info(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + + u8 byte[4] = {0,0,0,0}; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client, byte, CPLD_INFO_OFFSET, 4); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", + byte[2] & 0xf, (byte[3] & 0x1f), 2014+(byte[2] >> 4)); /* mm/dd/yyyy*/ + sprintf (buf, "%sThe PCB version is %X\n", buf, byte[0]&0xf); + sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, byte[1]>>4, byte[1]&0xf); + + if(hasCPLD2) { + mutex_lock(&data->update_lock); + cpld_i2c_read(client2, byte, CPLD_INFO_OFFSET, 4); + mutex_unlock(&data->update_lock); + + sprintf (buf, "%s\nThe CPLD2 release date is %02d/%02d/%d.\n", buf, + byte[2] & 0xf, (byte[3] & 0x1f), 2014+(byte[2] >> 4)); /* mm/dd/yyyy*/ + sprintf (buf, "%sThe CPLD2 version is %d.%d\n", buf, byte[1]>>4, byte[1]&0xf); + } + + return strlen(buf); +} + +static char* powerstatus_str[] = { + "Failed", //0 + "Good", //1 +}; + +static ssize_t show_powerstatus(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 byte[2] = {0,0}; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client2, byte, CPLD_POWERSTATUS_OFFSET, 2); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + sprintf (buf, "PGD_P5V_STBY: %s\n", powerstatus_str[(byte[0]>>7) & 0x01]); + sprintf (buf, "%sPGD_P3V3_STBY: %s\n", buf, powerstatus_str[(byte[0]>>6) & 0x01]);; + sprintf (buf, "%sPGD_P1V8_A: %s\n", buf, powerstatus_str[(byte[0]>>4) & 0x01]); + sprintf (buf, "%sPGD_P3V3_SYS: %s\n", buf, powerstatus_str[(byte[0]>>3) & 0x01]); + sprintf (buf, "%sPGD_P3V3_A: %s\n", buf, powerstatus_str[(byte[0]>>2) & 0x01]); + sprintf (buf, "%sPGD_P3V3_B: %s\n", buf, powerstatus_str[(byte[0]>>1) & 0x01]); + sprintf (buf, "%sPGD_P1V2: %s\n", buf, powerstatus_str[(byte[0]>>0) & 0x01]); + sprintf (buf, "%sPGD_P0V8_A: %s\n", buf,powerstatus_str[(byte[1]>>7) & 0x01]); + sprintf (buf, "%sPGD_P0V89_ROV: %s\n", buf, powerstatus_str[(byte[1]>>6) & 0x01]); + sprintf (buf, "%sSW_PWR_READY: %s\n", buf, powerstatus_str[(byte[1]>>3) & 0x01]); + sprintf (buf, "%sCPU_STBY_PWROK: %s\n", buf, powerstatus_str[(byte[1]>>0) & 0x01]); + + return strlen(buf); +} + +static ssize_t show_diag(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + uint8_t ipmisend[]= { IPMI_DIAGFLAG_OFFSET, 1}; + uint8_t result[MAX_IPMI_RECV_LENGTH]; + int result_len=0; + start_ipmi_command(NETFN_OEM, CMD_GETDATA,ipmisend, 2, result, &result_len); + data->diag = (result[0] & 0x80) !=0; + return sprintf (buf, "%d\n", data->diag); +} + +static ssize_t set_diag(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + uint8_t ipmisend[]= { IPMI_DIAGFLAG_OFFSET, 0x80}; + uint8_t result[MAX_IPMI_RECV_LENGTH]; + int result_len=0; + u8 diag = simple_strtol(buf, NULL, 10); + data->diag = diag?1:0; + if (data->diag==0) ipmisend[1] = 0x00; + + start_ipmi_command(NETFN_OEM, CMD_SETDATA,ipmisend, 2, result, &result_len); + + return count; +} + +static ssize_t show_thermal(struct device *dev, struct device_attribute *da, + char *buf) +{ + uint8_t ipmisend[]= { IPMI_SWITCHTEMP_OFFSET, 1}; + uint8_t result[MAX_IPMI_RECV_LENGTH]; + int result_len=0; + start_ipmi_command(NETFN_OEM, CMD_GETDATA,ipmisend, 2, result, &result_len); + return sprintf(buf, "%d\n", result[0] * 1000 ); +} + +static char* interrupt_str[] = { + "CPU_SEN_ALERT_N", //0 + "EXT_USB_OC_N", //1 + "", //2 + "", //3 + "PLD_SEN5_ALERT_N", //4 + "PLD_SEN4_ALERT_N", //5 + "PLD_SEN3_ALERT_N", //6 + "UCD90160_TEMP_INT_N", //7 + "RSTBTN_INT_N", //8 + "WDT_IRQ_N", //9 +}; + +static ssize_t show_interrupt(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 byte[4] = {0,0,0,0}; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client, byte, CPLD_INT_OFFSET, 4); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + sprintf (buf, "0x%02X 0x%02X:", byte[0],byte[2]); + if(byte[0]==0xff && byte[2]==0x07) sprintf (buf, "%sNone",buf); + if(!(byte[0]&0x01)) sprintf (buf, "%s%s ",buf,interrupt_str[0]); + if(!(byte[0]&0x02)) sprintf (buf, "%s%s ",buf,interrupt_str[1]); + if(!(byte[0]&0x10)) sprintf (buf, "%s%s ",buf,interrupt_str[4]); + if(!(byte[0]&0x20)) sprintf (buf, "%s%s ",buf,interrupt_str[5]); + if(!(byte[0]&0x40)) sprintf (buf, "%s%s ",buf,interrupt_str[6]); + if(!(byte[0]&0x80)) sprintf (buf, "%s%s ",buf,interrupt_str[7]); + if(!(byte[2]&0x01)) sprintf (buf, "%s%s%s ",buf,interrupt_str[8] ,(byte[3]&0x01)?"(Blocked)":""); + if(!(byte[2]&0x02)) sprintf (buf, "%s%s%s ",buf,interrupt_str[9] ,(byte[3]&0x02)?"(Blocked)":""); + + return sprintf (buf, "%s\n", buf); +} + +static char* bios_str[] = { + "BIOS1", //0 + "BIOS2", //1 +}; + +static ssize_t show_bios_cs(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 byte = 0; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + byte &= 0x01; + + return sprintf (buf, "%d:%s\n", byte,bios_str[byte]); +} + +static ssize_t set_bios_cs(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte = 0; + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1); + if(temp) byte |= 0x01; else byte &= ~(0x01); + cpld_i2c_write(client, &byte, CPLD_BIOSCS_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static char* led_str[] = { + "OFF", //00 + "Green/Blue", //01 + "Yellow/Orange", //10 + "Red", //11 +}; + +static ssize_t show_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 byte = 0; + int shift = attr->index; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + byte = (byte >> shift) & 0x3; + + return sprintf (buf, "%d:%s\n", byte, led_str[byte]); +} + +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 16); + u8 byte = 0; + int shift = attr->index; + temp &= 0x3; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + byte &= ~(0x3<update_lock); + + return count; +} + +static char* sysled_str[] = { + "OFF", //000 + "0.5 Hz", //001 + "1 Hz", //010 + "2 Hz", //011 + "4 Hz", //100 + "NA", //101 + "NA", //110 + "ON", //111 +}; + +static ssize_t show_sysled(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_SYSLED_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + status = sprintf (buf, "%d:%s\n", byte, sysled_str[byte]); + + return strlen(buf); +} + +static ssize_t set_sysled(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 16); + u8 byte; + int shift = (attr->index == 0)?3:0; + + temp &= 0x7; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_SYSLED_OFFSET, 1); + byte &= ~(0x7<update_lock); + + return count; +} + +static char* psu_str[] = { + "unpowered", //00 + "normal", //01 + "not installed", //10 + "not installed", //11 +}; + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 byte=0; + int shift = (attr->index == 0)?0:4; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client2, &byte, CPLD_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + byte = (byte >> shift) & 0x3; + + return sprintf (buf, "%d:%s\n", byte, psu_str[byte]); +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 byte=0; + u8 offset = attr->index + CPLD_PWM_OFFSET; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client2, &byte, offset, 1); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + return sprintf(buf, "%d\n", byte); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 offset = attr->index + CPLD_PWM_OFFSET; + u8 byte = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_write(client2, &byte, offset, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 offset = attr->index*2 + CPLD_RPM_OFFSET; + u8 byte[2] = {0,0}; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client2, byte, offset, 2); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + return sprintf(buf, "%d\n", (byte[0]<<8 | byte[1])); +} + +static char* fantype_str[] = { + "Normal Type", //00 + "REVERSAL Type", //01 + "UNPLUGGED", //10 + "UNPLUGGED", //11 +}; + +static ssize_t show_fantype(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 offset = CPLD_FANSTATUS_OFFSET; + u8 byte[2] = {0,0}; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client2, byte, offset, 2); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + status = (((byte[0] >> attr->index) & 0x01)) | (((byte[1] >> attr->index) & 0x01)<<1); + + return sprintf(buf, "%d:%s\n",status,fantype_str[status]); +} + +static char* fanled_str[] = { + "None", //00 + "Green", //01 + "Red", //10 + "Both", //11 +}; + +static ssize_t show_fanled(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 byte[2] = {0,0}; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client2, byte, CPLD_FANLED_OFFSET, 2); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + status = (((byte[0] >> attr->index) & 0x01)) | (((byte[1] >> attr->index) & 0x01)<<1); + + return sprintf(buf, "%d:%s\n",status,fanled_str[status]); +} + +static ssize_t set_fanled(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte[2] = {0,0}; + u8 temp = simple_strtol(buf, NULL, 16); + int shift = attr->index; + + temp &= 0x3; + mutex_lock(&data->update_lock); + cpld_i2c_read(client2, byte, CPLD_FANLED_OFFSET, 2); + byte[0] &= ~(1<> 1) & 0x01)<update_lock); + + return count; +} + +static ssize_t set_watchdog_feed(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte=0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1); + byte |= 0x02; + cpld_i2c_write(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t set_watchdog_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte=0x03; + + mutex_lock(&data->update_lock); + cpld_i2c_write(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_watchdog_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 byte=0; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + return sprintf(buf, "%d\n",(byte&0x01)); +} + +static ssize_t set_watchdog_config(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte = simple_strtol(buf, NULL, 10); + + if (byte<6) byte=6; + mutex_lock(&data->update_lock); + cpld_i2c_write(client, &byte, CPLD_WATCHDOGCONFIG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_watchdog_config(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 byte=0; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client, &byte, CPLD_WATCHDOGCONFIG_OFFSET, 1); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + return sprintf(buf, "%d seconds\n",byte); +} + +static ssize_t show_watchdog_counter(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + ssize_t len = 0; + u8 byte=0; + + mutex_lock(&data->update_lock); + len = cpld_i2c_read(client, &byte, CPLD_WATCHDOGCOUNTER_OFFSET, 1); + mutex_unlock(&data->update_lock); + if (len==0) return 0; + + return sprintf(buf, "%d seconds\n",byte); +} + +static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0); +static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0); +static SENSOR_DEVICE_ATTR(interrupt, S_IRUGO, show_interrupt, 0, 0); + +static SENSOR_DEVICE_ATTR(fan_led, S_IWUSR|S_IRUGO, show_led, set_led, 2); +static SENSOR_DEVICE_ATTR(power_led, S_IWUSR|S_IRUGO, show_led, set_led, 4); +static SENSOR_DEVICE_ATTR(location_led, S_IWUSR|S_IRUGO, show_led, set_led, 6); + +static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_sysled, set_sysled, 0); +static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_sysled, set_sysled, 1); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3); +#if FAN_NUM>4 +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4); +#endif + +static SENSOR_DEVICE_ATTR(fanmodule1_type, S_IRUGO, show_fantype, 0, 0); +static SENSOR_DEVICE_ATTR(fanmodule2_type, S_IRUGO, show_fantype, 0, 1); +static SENSOR_DEVICE_ATTR(fanmodule3_type, S_IRUGO, show_fantype, 0, 2); +static SENSOR_DEVICE_ATTR(fanmodule4_type, S_IRUGO, show_fantype, 0, 3); +#if FAN_NUM>4 +static SENSOR_DEVICE_ATTR(fanmodule5_type, S_IRUGO, show_fantype, 0, 4); +#endif + +static SENSOR_DEVICE_ATTR(fanmodule1_led, S_IWUSR|S_IRUGO, show_fanled, set_fanled, 0); +static SENSOR_DEVICE_ATTR(fanmodule2_led, S_IWUSR|S_IRUGO, show_fanled, set_fanled, 1); +static SENSOR_DEVICE_ATTR(fanmodule3_led, S_IWUSR|S_IRUGO, show_fanled, set_fanled, 2); +static SENSOR_DEVICE_ATTR(fanmodule4_led, S_IWUSR|S_IRUGO, show_fanled, set_fanled, 3); +#if FAN_NUM>4 +static SENSOR_DEVICE_ATTR(fanmodule5_led, S_IWUSR|S_IRUGO, show_fanled, set_fanled, 4); +#endif + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7); +#if FAN_NUM>4 +static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO, show_rpm, 0, 8); +static SENSOR_DEVICE_ATTR(fan10_input,S_IRUGO, show_rpm, 0, 9); +#endif + +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 0); +static SENSOR_DEVICE_ATTR(psu2, S_IRUGO, show_psu, 0, 1); +static SENSOR_DEVICE_ATTR(power_status, S_IRUGO, show_powerstatus, 0, 0); + +static SENSOR_DEVICE_ATTR(watchdog_feed, S_IWUSR, 0, set_watchdog_feed, 0); +static SENSOR_DEVICE_ATTR(watchdog_enable, S_IWUSR|S_IRUGO, show_watchdog_enable, set_watchdog_enable, 0); +static SENSOR_DEVICE_ATTR(watchdog_config, S_IWUSR|S_IRUGO, show_watchdog_config, set_watchdog_config, 0); +static SENSOR_DEVICE_ATTR(watchdog_counter, S_IRUGO, show_watchdog_counter, 0, 0); + +static SENSOR_DEVICE_ATTR(bios_cs, S_IWUSR|S_IRUGO, show_bios_cs, set_bios_cs, 0); + +static struct attribute *cpld_attributes[] = { + &sensor_dev_attr_info.dev_attr.attr, + &sensor_dev_attr_diag.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + + &sensor_dev_attr_fan_led.dev_attr.attr, + &sensor_dev_attr_power_led.dev_attr.attr, + &sensor_dev_attr_location_led.dev_attr.attr, + + &sensor_dev_attr_grn_led.dev_attr.attr, + &sensor_dev_attr_red_led.dev_attr.attr, + + &sensor_dev_attr_interrupt.dev_attr.attr, + + &sensor_dev_attr_psu1.dev_attr.attr, + &sensor_dev_attr_psu2.dev_attr.attr, + &sensor_dev_attr_power_status.dev_attr.attr, + + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, +#if FAN_NUM>4 + &sensor_dev_attr_pwm5.dev_attr.attr, +#endif + &sensor_dev_attr_fanmodule1_type.dev_attr.attr, + &sensor_dev_attr_fanmodule2_type.dev_attr.attr, + &sensor_dev_attr_fanmodule3_type.dev_attr.attr, + &sensor_dev_attr_fanmodule4_type.dev_attr.attr, +#if FAN_NUM>4 + &sensor_dev_attr_fanmodule5_type.dev_attr.attr, +#endif + &sensor_dev_attr_fanmodule1_led.dev_attr.attr, + &sensor_dev_attr_fanmodule2_led.dev_attr.attr, + &sensor_dev_attr_fanmodule3_led.dev_attr.attr, + &sensor_dev_attr_fanmodule4_led.dev_attr.attr, +#if FAN_NUM>4 + &sensor_dev_attr_fanmodule5_led.dev_attr.attr, +#endif + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, +#if FAN_NUM>4 + &sensor_dev_attr_fan9_input.dev_attr.attr, + &sensor_dev_attr_fan10_input.dev_attr.attr, +#endif + &sensor_dev_attr_watchdog_feed.dev_attr.attr, + &sensor_dev_attr_watchdog_enable.dev_attr.attr, + &sensor_dev_attr_watchdog_config.dev_attr.attr, + &sensor_dev_attr_watchdog_counter.dev_attr.attr, + + &sensor_dev_attr_bios_cs.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld_group = { + .attrs = cpld_attributes, +}; + +/*-----------------------------------------------------------------------*/ +/* device probe and removal */ +static int +cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld_group); + + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + //Check CPLD2 exist or not + client2 = i2c_new_dummy(client->adapter, CPLD2_ADDRESS); + if(!client2) { + hasCPLD2 = 0; + client2 = client; + } else { + status = i2c_smbus_read_byte_data(client2, CPLD_INFO_OFFSET); + if(status<0) { + i2c_unregister_device(client2); + i2c_set_clientdata(client2, NULL); + hasCPLD2 = 0; + client2 = client; + } + } + + data->tsk = kthread_run(cpld_thread,client,"%s",dev_name(data->hwmon_dev)); + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpld_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &cpld_group); + hwmon_device_unregister(data->hwmon_dev); + i2c_set_clientdata(client, NULL); + if(hasCPLD2) { + i2c_unregister_device(client2); + i2c_set_clientdata(client2, NULL); + } + + kfree(data); + return 0; +} + +static const struct i2c_device_id cpld_ids[] = { + { "inv_cpld" , 0, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, cpld_ids); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_cpld_init(void) +{ + return i2c_add_driver(&cpld_driver); +} + +static void __exit inv_cpld_exit(void) +{ + i2c_del_driver(&cpld_driver); +} + +MODULE_AUTHOR("jack.ting "); +MODULE_DESCRIPTION("cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_cpld_init); +module_exit(inv_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_eeprom.c new file mode 100644 index 000000000000..7bb167d2e74e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_eeprom.c @@ -0,0 +1,181 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void inv_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } + +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + inv_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute inv_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = inv_eeprom_read, +}; + +static int inv_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int inv_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id inv_eeprom_id[] = { + { "inv_eeprom", 0 }, + { } +}; + +static struct i2c_driver inv_eeprom_driver = { + .driver = { + .name = "inv_eeprom", + }, + .probe = inv_eeprom_probe, + .remove = inv_eeprom_remove, + .id_table = inv_eeprom_id, +}; + +module_i2c_driver(inv_eeprom_driver); + +MODULE_AUTHOR("Inventec"); +MODULE_DESCRIPTION("Inventec D6556 Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.c new file mode 100644 index 000000000000..143aee309dba --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.c @@ -0,0 +1,547 @@ +#include +#include +#include +#include +#include +#include +#include "io_expander.h" +#include "inv_mux.h" + +/* For build single module using (Ex: ONL platform) */ +#include +//#include +//#include + + +static struct mux_obj_s *mux_head_p = NULL; + +/* ========== MUX object functions ========== + */ +static int +_setup_i2c_value(struct mux_obj_s *self, int offset, int value){ + + return i2c_smbus_write_byte_data(self->i2c_client_p, offset, value); +} + + +static int +_setup_i2c_client(struct mux_obj_s *self, int chan_id, int addr){ + + struct i2c_adapter *adap = NULL; + char *emsg = "ERR"; + + adap = i2c_get_adapter(chan_id); + if (!adap){ + emsg = "can't get adapter"; + goto err_setup_i2c_client; + } + self->i2c_client_p = kzalloc(sizeof(*self->i2c_client_p), GFP_KERNEL); + if (!self->i2c_client_p){ + emsg = "can't kzalloc client"; + goto err_setup_i2c_client; + } + self->i2c_client_p->adapter = adap; + self->i2c_client_p->addr = addr; + return 0; + +err_setup_i2c_client: + SWPS_ERR("%s: %s\n", __func__, emsg); + return ERR_MUX_UNEXCPT; +} + + +int +_common_force_pull_gpio(int mem_addr, + int input, + int bit_offset){ + + unsigned int val = 0; + unsigned int targ = 0; + + /* Get current value */ + val = inl(mem_addr); + if (val == 0) { + SWPS_ERR("%s: inl:%d fail!\n", __func__, val); + return -1; + } + /* Count target value */ + switch (input) { + case 0: /* Pull Low */ + targ = (val & (~(1 << bit_offset))); + break; + case 1: /* Pull high */ + targ = (val | (1 << bit_offset)); + break; + default: + SWPS_ERR("%s: input state:%d incorrect!\n", + __func__, input); + return -1; + } + /* Setup gpio */ + outl(targ, mem_addr); + if (targ != inl(mem_addr)){ + SWPS_ERR("%s: outl:%d fail!\n", __func__, targ); + return -1; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + + +int +rangeley_force_pull_high(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +rangeley_force_pull_low(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +hedera_force_pull_high(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 1, 5); +} + + +int +hedera_force_pull_low(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 0, 5); +} + + +int +normal_gpio_pull_high(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 1); +} + + +int +normal_gpio_pull_low(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 0); +} + + +int +cpld_rst_all_4_pull_low(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto setlow_cpld_rst_all_4_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_cpld_rst_all_4_pull_low; + +setlow_cpld_rst_all_4_c0_a77_70_74_rst_all: + err = _setup_i2c_value(self, 0x70, 0x0); + if (err < 0) { + emsg = "setup 0x70 fail"; + goto err_cpld_rst_all_4_pull_low; + } + err = _setup_i2c_value(self, 0x74, 0x01); + if (err < 0) { + emsg = "setup 0x74 fail"; + goto err_cpld_rst_all_4_pull_low; + } + return 0; + +err_cpld_rst_all_4_pull_low: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + +int +cpld_rst_all_4_pull_high(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto sethigh_cpld_rst_all_4_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_cpld_rst_all_4_pull_high; + +sethigh_cpld_rst_all_4_c0_a77_70_74_rst_all: + err = _setup_i2c_value(self, 0x70, 0xfe); + if (err < 0) { + emsg = "setup 0x70 fail"; + goto err_cpld_rst_all_4_pull_high; + } + err = _setup_i2c_value(self, 0x74, 0x03); + if (err < 0) { + emsg = "setup 0x74 fail"; + goto err_cpld_rst_all_4_pull_high; + } + return 0; + +err_cpld_rst_all_4_pull_high: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + +int +pca9548_reset_mux_all(struct mux_obj_s *self){ + /* [Note] Power-on reset (PCA9548A-NXP) + * When power is applied to VDD, an internal Power-On Reset (POR) + * holds the PCA9548A in a reset condition until VDD has reached + * VPOR. At this point, the reset condition is released and the + * PCA9548A register and I2C-bus state machine are initialized to + * their default states (all zeroes) causing all the channels to + * be deselected. Thereafter, VDD must be lowered below 0.2 V for + * at least 5 us in order to reset the device. + */ + if (self->_pull_low(self) < 0) { + SWPS_ERR("%s: _pull_low fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS_PCA9548); + if (self->_pull_high(self) < 0) { + SWPS_ERR("%s: _pull_high fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS_PCA9548); + return 0; +} + + +int +cpld_reset_mux_all(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto reset_cpld_rst_all_4_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_cpld_reset_mux_all; + +reset_cpld_rst_all_4_c0_a77_70_74_rst_all: + if (self->_pull_low(self) < 0) { + emsg = "_pull_low fail"; + goto err_cpld_reset_mux_all; + } + mdelay(MUX_RST_WAIT_MS_CPLD); + return 0; + +err_cpld_reset_mux_all: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + +int +common_reset_mux_all(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +init_gpio_4_force(struct mux_obj_s *self){ + + if (self->_pull_high(self) < 0) { + SWPS_ERR("%s: setup default fail!\n", __func__); + return -1; + } + return 0; +} + + +int +init_gpio_4_normal(struct mux_obj_s *self){ + + int err = 0; + char *emsg = "ERR"; + + if (!gpio_is_valid(self->gpio_num)) { + emsg = "GPIO invalid"; + goto err_init_gpio_4_normal; + } + err = gpio_request(self->gpio_num, MUX_GPIO_LABEL); + if (err < 0) { + emsg = "gpio_request fail"; + goto err_init_gpio_4_normal; + } + err = self->_pull_high(self); + if (err < 0) { + emsg = "setup default fail"; + goto err_init_gpio_4_normal; + } + SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num); + return 0; + +err_init_gpio_4_normal: + SWPS_ERR("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return -1; +} + + +int +init_cpld_4_rst_all(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + int chan = ERR_MUX_UNEXCPT; + int addr = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto init_cpld_i2c_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_init_cpld_4_rst_all; + +init_cpld_i2c_c0_a77_70_74_rst_all: + chan = 0; + addr = 0x77; + err = _setup_i2c_client(self, chan, addr); + if (err < 0) { + emsg = "_setup_i2c_client fail"; + goto err_init_cpld_4_rst_all; + } + err = self->_pull_high(self); + if (err < 0) { + emsg = "setup default value fail"; + goto err_init_cpld_4_rst_all; + } + SWPS_DEBUG("%s: init_cpld_i2c_c0_a77_70_74_rst_all ok", __func__); + return 0; + +err_init_cpld_4_rst_all: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + +int +clean_gpio_4_common(struct mux_obj_s *self){ + + if (!self) return 0; + if (!gpio_is_valid(self->gpio_num)) return 0; + self->_pull_high(self); + gpio_free(mux_head_p->gpio_num); + return 0; +} + + +int +clean_cpld_4_rst_all(struct mux_obj_s *self){ + + if (!self) return 0; + self->_pull_high(self); + if (self->i2c_client_p) { + i2c_put_adapter(self->i2c_client_p->adapter); + kfree(self->i2c_client_p); + } + return 0; +} + + +static int +_setup_muxctl_cb(struct mux_obj_s *self, + unsigned gpio){ + + char mod_dsc[32] = "ERR"; + + switch (gpio) { + case MUX_RST_GPIO_FORCE_RANGELEY: + self->gpio_num = gpio; + self->_pull_low = rangeley_force_pull_low; + self->_pull_high = rangeley_force_pull_high; + self->_init = init_gpio_4_force; + self->_clean = clean_gpio_4_common; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Rangeley force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_FORCE_HEDERA: + self->gpio_num = gpio; + self->_pull_low = hedera_force_pull_low; + self->_pull_high = hedera_force_pull_high; + self->_init = init_gpio_4_force; + self->_clean = clean_gpio_4_common; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Hedera force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_48_PCA9548: + case MUX_RST_GPIO_69_PCA9548: + case MUX_RST_GPIO_249_PCA9548: + case MUX_RST_GPIO_500_PCA9548: + case MUX_RST_GPIO_505_PCA9548: + self->gpio_num = gpio; + self->_pull_low = normal_gpio_pull_low; + self->_pull_high = normal_gpio_pull_high; + self->_init = init_gpio_4_normal; + self->_clean = clean_gpio_4_common; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Normal mode :%d", (int)gpio); + goto ok_setup_muxctl_cb; + + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + self->gpio_num = gpio; + self->_pull_low = cpld_rst_all_4_pull_low; + self->_pull_high = cpld_rst_all_4_pull_high; + self->_init = init_cpld_4_rst_all; + self->_clean = clean_cpld_4_rst_all; + self->reset = cpld_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "CPLD mode :%d", (int)gpio); + goto ok_setup_muxctl_cb; + + default: + break; + } + SWPS_ERR("%s: Unexpected GPIO:%d\n", __func__, gpio); + return -1; + +ok_setup_muxctl_cb: + SWPS_INFO("muxctl: %s.\n", mod_dsc); + return 0; +} + + +/* ========== MUX public functions ========== + */ +void +clean_mux_objs(void){ + + struct mux_obj_s *curr_p = mux_head_p; + struct mux_obj_s *next_p = NULL; + + if (!curr_p) { + SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__); + return; + } + while (curr_p) { + next_p = curr_p->next; + curr_p->_clean(curr_p); + kfree(curr_p); + curr_p = next_p; + } + SWPS_DEBUG("%s: done.\n", __func__); +} +EXPORT_SYMBOL(clean_mux_objs); + + +int +reset_mux_objs(void){ + + if (!mux_head_p) { + SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__); + return -1; + } + if (mux_head_p->reset(mux_head_p) < 0){ + SWPS_ERR("%s: reset fail!\n", __func__); + return -1; + } + return 0; +} +EXPORT_SYMBOL(reset_mux_objs); + + +struct mux_obj_s * +_create_mux_obj(unsigned gpio){ + + char *emsg = "ERR"; + struct mux_obj_s *obj_p = NULL; + + obj_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL); + if (!obj_p) { + emsg = "kzalloc fail!"; + goto err_create_mux_obj_1; + } + if (_setup_muxctl_cb(obj_p, gpio) < 0){ + emsg = "_setup_muxctl_cb fail!"; + goto err_create_mux_obj_2; + } + if (obj_p->_init(obj_p) < 0) { + emsg = "_init() fail!"; + goto err_create_mux_obj_2; + } + SWPS_DEBUG("%s: created MUX object :%d\n", __func__, gpio); + return obj_p; + +err_create_mux_obj_2: + kfree(obj_p); +err_create_mux_obj_1: + SWPS_ERR("%s: %s :%d\n", __func__, emsg, gpio); + return NULL; +} + + +int +init_mux_objs(unsigned gpio){ + + struct mux_obj_s *curr_p = NULL; + char *emsg = "ERR"; + + /* Create MUX control object */ + if (mux_head_p) { + SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__); + clean_mux_objs(); + } + /* Currently, it is using single muxctl architecture. + * In the future, it may use the multi-muxctl. + * (Ex: Gulmohar's advance I2C control / Peony's reset single mux) + */ + curr_p = _create_mux_obj(gpio); + if (!curr_p) { + emsg = "_create_mux_obj fail"; + goto err_init_mux_objs; + } + curr_p->next = NULL; + mux_head_p = curr_p; + SWPS_DEBUG("%s: all done. :%d\n", __func__, gpio); + return 0; + +err_init_mux_objs: + clean_mux_objs(); + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} +EXPORT_SYMBOL(init_mux_objs); + + +/* For single ko module + * => You need to declare MODULE_LICENSE If you want to build single module along. + * => Ex: For ONL platform + */ +MODULE_LICENSE("GPL"); + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.h new file mode 100644 index 000000000000..a913b24c6053 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.h @@ -0,0 +1,51 @@ +#ifndef INV_MUX_H +#define INV_MUX_H + +#include + +/* MUX basic information */ +#define MUX_GPIO_LABEL "SWPS_RST_MUX" + +/* MUX reset GPIO define */ +#define MUX_RST_GPIO_FORCE (30100) +#define MUX_RST_GPIO_FORCE_RANGELEY (30101) +#define MUX_RST_GPIO_FORCE_HEDERA (30102) +#define MUX_RST_GPIO_48_PCA9548 (48) +#define MUX_RST_GPIO_69_PCA9548 (69) +#define MUX_RST_GPIO_249_PCA9548 (249) +#define MUX_RST_GPIO_500_PCA9548 (500) +#define MUX_RST_GPIO_505_PCA9548 (505) +#define MUX_RST_CPLD_C0_A77_70_74_RST_ALL (30201) + +/* MUX relate value define */ +#define MUX_RST_WAIT_MS_PCA9548 (1) +#define MUX_RST_WAIT_MS_CPLD (10) +#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD +#define MUX_RST_MEM_ADDR_HEDERA (0x548) + +/* MUX error code define */ +#define ERR_MUX_UNEXCPT (-399) + +struct mux_obj_s { + struct i2c_client *i2c_client_p; + struct mux_obj_s *next; + unsigned gpio_num; + int (*_pull_high)(struct mux_obj_s *self); + int (*_pull_low)(struct mux_obj_s *self); + int (*_init)(struct mux_obj_s *self); + int (*_clean)(struct mux_obj_s *self); + int (*reset)(struct mux_obj_s *self); +}; + + +void clean_mux_objs(void); +int reset_mux_objs(void); +int init_mux_objs(unsigned gpio); + + +#endif /* INV_MUX_H */ + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_platform.c new file mode 100644 index 000000000000..811ed5e18e58 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_platform.c @@ -0,0 +1,297 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct inv_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +#define bus_id(id) (id) +static struct pca954x_platform_mode pca9641_modes_1[] = { + {.adap_id = bus_id(2),}, +}; + +static struct pca954x_platform_mode pca9641_modes_2[] = { + {.adap_id = bus_id(5),}, +}; + +static struct pca954x_platform_mode pca9641_modes_3[] = { + {.adap_id = bus_id(3),}, +}; + +static struct pca954x_platform_mode pca9641_modes_4[] = { + {.adap_id = bus_id(4),}, +}; + +static struct pca954x_platform_mode mux_modes_0[] = { + {.adap_id = bus_id(6),}, {.adap_id = bus_id(7),}, + {.adap_id = bus_id(8),}, {.adap_id = bus_id(9),}, + {.adap_id = bus_id(10),}, {.adap_id = bus_id(11),}, + {.adap_id = bus_id(12),}, {.adap_id = bus_id(13),}, +}; +static struct pca954x_platform_mode mux_modes_0_0[] = { + {.adap_id = bus_id(14),}, {.adap_id = bus_id(15),}, + {.adap_id = bus_id(16),}, {.adap_id = bus_id(17),}, + {.adap_id = bus_id(18),}, {.adap_id = bus_id(19),}, + {.adap_id = bus_id(20),}, {.adap_id = bus_id(21),}, +}; + +static struct pca954x_platform_mode mux_modes_0_1[] = { + {.adap_id = bus_id(22),}, {.adap_id = bus_id(23),}, + {.adap_id = bus_id(24),}, {.adap_id = bus_id(25),}, + {.adap_id = bus_id(26),}, {.adap_id = bus_id(27),}, + {.adap_id = bus_id(28),}, {.adap_id = bus_id(29),}, +}; + +static struct pca954x_platform_mode mux_modes_0_2[] = { + {.adap_id = bus_id(30),}, {.adap_id = bus_id(31),}, + {.adap_id = bus_id(32),}, {.adap_id = bus_id(33),}, + {.adap_id = bus_id(34),}, {.adap_id = bus_id(35),}, + {.adap_id = bus_id(36),}, {.adap_id = bus_id(37),}, +}; + +static struct pca954x_platform_mode mux_modes_0_3[] = { + {.adap_id = bus_id(38),}, {.adap_id = bus_id(39),}, + {.adap_id = bus_id(40),}, {.adap_id = bus_id(41),}, + {.adap_id = bus_id(42),}, {.adap_id = bus_id(43),}, + {.adap_id = bus_id(44),}, {.adap_id = bus_id(45),}, +}; + +static struct pca954x_platform_mode mux_modes_0_4[] = { + {.adap_id = bus_id(46),}, {.adap_id = bus_id(47),}, + {.adap_id = bus_id(48),}, {.adap_id = bus_id(49),}, + {.adap_id = bus_id(50),}, {.adap_id = bus_id(51),}, + {.adap_id = bus_id(52),}, {.adap_id = bus_id(53),}, +}; + +static struct pca954x_platform_mode mux_modes_0_5[] = { + {.adap_id = bus_id(54),}, {.adap_id = bus_id(55),}, + {.adap_id = bus_id(56),}, {.adap_id = bus_id(57),}, + {.adap_id = bus_id(58),}, {.adap_id = bus_id(59),}, + {.adap_id = bus_id(60),}, {.adap_id = bus_id(61),}, +}; + +static struct pca954x_platform_mode mux_modes_0_6[] = { + {.adap_id = bus_id(62),}, {.adap_id = bus_id(63),}, + {.adap_id = bus_id(64),}, {.adap_id = bus_id(65),}, + {.adap_id = bus_id(66),}, {.adap_id = bus_id(67),}, + {.adap_id = bus_id(68),}, {.adap_id = bus_id(69),}, +}; + +//no i2c device driver attach to mux 7 + +static struct pca954x_platform_data pca9641_data_1 = { + .modes = pca9641_modes_1, + .num_modes = 1, +}; +static struct pca954x_platform_data pca9641_data_2 = { + .modes = pca9641_modes_2, + .num_modes = 1, +}; +static struct pca954x_platform_data pca9641_data_3 = { + .modes = pca9641_modes_3, + .num_modes = 1, +}; +static struct pca954x_platform_data pca9641_data_4 = { + .modes = pca9641_modes_4, + .num_modes = 1, +}; +static struct pca954x_platform_data mux_data_0 = { + .modes = mux_modes_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_0 = { + .modes = mux_modes_0_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_1 = { + .modes = mux_modes_0_1, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_2 = { + .modes = mux_modes_0_2, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_3 = { + .modes = mux_modes_0_3, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_4 = { + .modes = mux_modes_0_4, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_5 = { + .modes = mux_modes_0_5, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_6 = { + .modes = mux_modes_0_6, + .num_modes = 8, +}; + +static struct i2c_board_info i2c_device_info0[] __initdata = { + {"pca9641", 0, 0x76, &pca9641_data_1, 0, 0}, //PCA9641-1 + {"pca9641", 0, 0x73, &pca9641_data_3, 0, 0}, //PCA9641-3 + {"pca9641", 0, 0x09, &pca9641_data_4, 0, 0}, //PCA9641-4 +}; +static struct i2c_board_info i2c_device_info1[] __initdata = { + {"pca9641", 0, 0x0A, &pca9641_data_2, 0, 0}, //PCA9641-2 +}; +static struct i2c_board_info i2c_device_info2[] __initdata = { + {"inv_cpld", 0, 0x77, 0, 0, 0}, //CPLD +}; +static struct i2c_board_info i2c_device_info3[] __initdata = { + {"tmp75", 0, 0x48, 0, 0, 0}, //CPU Board Temp + {"tmp75", 0, 0x4A, 0, 0, 0}, //Temp + {"tmp75", 0, 0x4D, 0, 0, 0}, //Temp + {"tmp75", 0, 0x4E, 0, 0, 0}, //Temp +}; +static struct i2c_board_info i2c_device_info4[] __initdata = { + {"pmbus", 0, 0x5B, 0, 0, 0}, //PSU1 + {"pmbus", 0, 0x5A, 0, 0, 0}, //PSU2 +}; +static struct i2c_board_info i2c_device_info5[] __initdata = { + {"pca9548", 0, 0x70, &mux_data_0, 0, 0}, //mux root +}; +static struct i2c_board_info i2c_device_info6[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, +}; +static struct i2c_board_info i2c_device_info7[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, +}; +static struct i2c_board_info i2c_device_info8[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, +}; +static struct i2c_board_info i2c_device_info9[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, +}; +static struct i2c_board_info i2c_device_info10[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0}, +}; +static struct i2c_board_info i2c_device_info11[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0}, +}; +static struct i2c_board_info i2c_device_info12[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0}, +}; + + +static struct inv_i2c_board_info i2cdev_list[] = { + {bus_id(0), ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //SMBus + {bus_id(1), ARRAY_SIZE(i2c_device_info1), i2c_device_info1 }, //pca9641-2 + {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //pca9641-1 + {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //pca9641-3 + {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //pca9641-4 + {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux root + {bus_id(6), ARRAY_SIZE(i2c_device_info6), i2c_device_info6 }, //mux CH0 + {bus_id(7), ARRAY_SIZE(i2c_device_info7), i2c_device_info7 }, //mux CH1 + {bus_id(8), ARRAY_SIZE(i2c_device_info8), i2c_device_info8 }, //mux CH2 + {bus_id(9), ARRAY_SIZE(i2c_device_info9), i2c_device_info9 }, //mux CH3 + {bus_id(10),ARRAY_SIZE(i2c_device_info10), i2c_device_info10}, //mux CH4 + {bus_id(11),ARRAY_SIZE(i2c_device_info11), i2c_device_info11}, //mux CH5 + {bus_id(12),ARRAY_SIZE(i2c_device_info12), i2c_device_info12}, //mux CH6 +}; + +#define INV_PLATFORM_CLIENT_MAX_NUM 50 /*A big enough number for sum of i2cdev_list[i].size */ +static int client_list_index = 0; +static struct i2c_client *client_list[INV_PLATFORM_CLIENT_MAX_NUM] = {0}; + +///////////////////////////////////////////////////////////////////////////////////////// +static struct platform_device *device_i2c_gpio0; +static struct i2c_gpio_platform_data i2c_gpio_platdata0 = { + .scl_pin = 58, //494, + .sda_pin = 75, //511, + + .udelay = 5, //5:100kHz + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, + .scl_is_output_only = 0 +}; + +static int __init inv_platform_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j,k; + + //printk("%s \n", __func__); + + //use i2c-gpio + //register i2c gpio + //config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 gpio69=32*2+8*0+5 + outl( inl(0x533) | (1<<2), 0x533); //i2c-gpio sdl (GPIO58) + outl( inl(0x541) | (1<<3), 0x541); //i2c-gpio sda (GPIO75) + outl( inl(0x540) | (1<<5), 0x540); //RST_I2C_MUX_N (GPIO69) + outl( inl(0x500) | (1<<7), 0x500); //SYS_RDY_N (GPIO7) + outl( inl(0x501) | (1<<7), 0x501); //BMC_HEART_BEAT (GPIO15) + outl( inl(0x503) | (1<<2)|(1<<3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27) + + device_i2c_gpio0 = platform_device_alloc("i2c-gpio", 1); + if (!device_i2c_gpio0) { + printk(KERN_ERR "i2c-gpio: platform_device_alloc fail\n"); + return -ENOMEM; + } + device_i2c_gpio0->name = "i2c-gpio"; + device_i2c_gpio0->id = 1; + device_i2c_gpio0->dev.platform_data = &i2c_gpio_platdata0; + + ret = platform_device_add(device_i2c_gpio0); + if (ret) { + printk(KERN_ERR "i2c-gpio: platform_device_add fail %d\n", ret); + } + msleep(10); + + for(i=0; i=0; i--) { + i2c_unregister_device(client_list[i]); + } + device_i2c_gpio0->dev.platform_data = NULL; + platform_device_unregister(device_i2c_gpio0); + printk("inv_platform_exit done\n"); +} + +module_init(inv_platform_init); +module_exit(inv_platform_exit); + +MODULE_AUTHOR("Inventec"); +MODULE_DESCRIPTION("Platform devices"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.c new file mode 100644 index 000000000000..11b60f78ae90 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.c @@ -0,0 +1,3266 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_swps.h" + +static int ctl_major; +static int port_major; +static int ioexp_total; +static int port_total; +static int block_polling; +static int auto_config; +static int flag_i2c_reset; +static int flag_mod_state; +static unsigned gpio_rest_mux; +static struct class *swp_class_p = NULL; +static struct inv_platform_s *platform_p = NULL; +static struct inv_ioexp_layout_s *ioexp_layout = NULL; +static struct inv_port_layout_s *port_layout = NULL; +int io_no_init = 0; +module_param(io_no_init, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); +static void swp_polling_worker(struct work_struct *work); +static DECLARE_DELAYED_WORK(swp_polling, swp_polling_worker); + +static int reset_i2c_topology(void); + + +static int +__swp_match(struct device *dev, +#ifdef SWPS_KERN_VER_AF_3_10 + + const void *data){ +#else + void *data){ +#endif + + char *name = (char *)data; + if (strcmp(dev_name(dev), name) == 0) + return 1; + return 0; +} + + +struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(swp_class_p, + NULL, + name, + __swp_match); + return dev; +} + + +static int +sscanf_2_int(const char *buf) { + + int result = -EBFONT; + char *hex_tag = "0x"; + + if (strcspn(buf, hex_tag) == 0) { + if (sscanf(buf,"%x",&result)) { + return result; + } + } else { + if (sscanf(buf,"%d",&result)) { + return result; + } + if(sscanf(buf,"-%d",&result)) { + return -result; + } + if (sscanf(buf,"%x",&result)) { + return result; + } + } + return -EBFONT; +} + + +static int +sscanf_2_binary(const char *buf) { + + int result = sscanf_2_int(buf); + + if (result < 0){ + return -EBFONT; + } + switch (result) { + case 0: + case 1: + return result; + default: + break; + } + return -EBFONT; +} + + +static int +_get_polling_period(void) { + + int retval = 0; + + if (SWP_POLLING_PERIOD == 0) { + return 0; + } + retval = ((SWP_POLLING_PERIOD * HZ) / 1000); + if (retval == 0) { + return 1; + } + return retval; +} + + +static struct transvr_obj_s * +_get_transvr_obj(char *dev_name) { + + struct device *dev_p = NULL; + struct transvr_obj_s *transvr_obj_p = NULL; + + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + return NULL; + } + transvr_obj_p = dev_get_drvdata(dev_p); + if (!transvr_obj_p){ + return NULL; + } + return transvr_obj_p; +} + + +static int +_is_i2c_target_exist(int chan, int addr) { + /* retval: Exist = 1 / Not exist = 0 / Error < 0 + */ + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + int retval = -1; + int err = -1; + int d_offs = 0; + + adap = i2c_get_adapter(chan); + if (!adap) { + SWPS_DEBUG("%s: can't get adapter\n", __func__); + retval = 0; + goto out_is_i2c_target_exist_1; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) { + SWPS_ERR("%s: kzalloc fail\n", __func__); + retval = -1; + goto out_is_i2c_target_exist_2; + } + client->adapter = adap; + client->addr = addr; + err = i2c_smbus_read_byte_data(client, d_offs); + if (err < 0) { + retval = 0; + } else { + retval = 1; + } + i2c_put_adapter(adap); + kfree(client); + return retval; + +out_is_i2c_target_exist_2: + i2c_put_adapter(adap); +out_is_i2c_target_exist_1: + return retval; +} + + +static void +unlock_tobj_all(void) { + + struct transvr_obj_s *tobj_p; + char port_name[32]; + int port_id = 0; + int minor_curr = 0; + + for (minor_curr=0; minor_currauto_config = auto_config; + unlock_transvr_obj(tobj_p); + SWPS_DEBUG("%s: Set %s auto_config=%d\n", + __func__, tobj_p->swp_name, auto_config); + } + return retval; +} + + +/* ========== R/W Functions module control attribute ========== + */ +static ssize_t +show_attr_platform(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 32, "%s\n", platform_p->name); +} + + +static ssize_t +show_attr_version(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%s\n", SWP_VERSION); +} + + +static ssize_t +show_attr_status(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", flag_mod_state); +} + + +static ssize_t +show_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", auto_config); +} + + +static ssize_t +show_attr_block_poll(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", block_polling); +} +static ssize_t +show_attr_io_no_init(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", io_no_init); +} + + +static int +_check_reset_pwd(const char *buf_p, + size_t count) { + + int in_max = 64; + int in_len = (int)count; + char in_val[64] = "ERR"; + char *emsg = "ERR"; + + if (in_len >= in_max) { + emsg = "input too much"; + goto err_check_reset_pwd; + } + if (!sscanf(buf_p,"%s",in_val)) { + emsg = "format incorrect"; + goto err_check_reset_pwd; + } + if (strcmp(in_val, SWP_RESET_PWD) != 0) { + emsg = "password incorrect"; + goto err_check_reset_pwd; + } + return 0; + +err_check_reset_pwd: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + +static ssize_t +store_attr_reset_i2c(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + /* Polling mode */ + if (SWP_POLLING_ENABLE) { + SWPS_INFO("%s: reset I2C :polling\n", __func__); + flag_i2c_reset = 1; + return count; + } + /* Direct mode */ + SWPS_INFO("%s: reset I2C go. :direct\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset fail!\n", __func__); + return -EIO; + } + SWPS_INFO("%s: reset I2C ok. :direct\n", __func__); + return count; +} + + +static ssize_t +store_attr_reset_swps(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p; + char port_name[32] = "ERR"; + int port_id = 0; + int minor_curr = 0; + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + for (minor_curr=0; minor_currstate = STATE_TRANSVR_DISCONNECTED; + unlock_transvr_obj(tobj_p); + SWPS_INFO("%s: reset:%s\n", __func__, tobj_p->swp_name); + } + return count; +} + + +static ssize_t +store_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if (input_val < 0){ + return -EBFONT; + } + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + auto_config = input_val; + _update_auto_config_2_trnasvr(); + return count; +} + + +static ssize_t +store_attr_block_poll( struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if (input_val < 0){ + return -EBFONT; + } + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + + if(input_val != block_polling){ + block_polling = input_val; + if(block_polling){ + cancel_delayed_work_sync(&swp_polling); + } + else{ + schedule_delayed_work(&swp_polling, _get_polling_period()); + } + } + + return count; +} + +static ssize_t +store_attr_io_no_init( struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + + if(input_val != io_no_init){ + io_no_init = input_val; + } + + return count; +} + +/* ========== Show functions: For transceiver attribute ========== + */ +static ssize_t +_show_transvr_hex_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + int result; + + lock_transvr_obj(tobj_p); + result = get_func(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 8, "%d\n", result); + } else { + len = snprintf(buf_p, 8, "0x%02x\n", result); + } + return len; +} + + +static ssize_t +_show_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = snprintf(buf_p, 16, "%d\n", get_func(tobj_p)); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +_show_transvr_str_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p, char* buf), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = get_func(tobj_p, buf_p); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +show_attr_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_id, + buf_p); +} + + +static ssize_t +show_attr_ext_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_ext_id, + buf_p); +} + + +static ssize_t +show_attr_connector(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_connector, + buf_p); +} + + +static ssize_t +show_attr_vendor_name(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_name, + buf_p); +} + + +static ssize_t +show_attr_vendor_pn(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_pn, + buf_p); +} + + +static ssize_t +show_attr_vendor_rev(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_rev, + buf_p); +} + + +static ssize_t +show_attr_vendor_sn(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_sn, + buf_p); +} + + +static ssize_t +show_attr_power_cls(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + size_t len; + int result; + struct transvr_obj_s *tobj_p; + + tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + lock_transvr_obj(tobj_p); + result = tobj_p->get_power_cls(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 16, "%d\n", result); + } else { + len = snprintf(buf_p, 16, "Power Class %d\n", result); + } + return len; +} + + +static ssize_t +show_attr_br(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_br, + buf_p); +} + + +static ssize_t +show_attr_len_sm(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_sm, + buf_p); +} + + +static ssize_t +show_attr_len_smf(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_smf, + buf_p); +} + + +static ssize_t +show_attr_len_om1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om1, + buf_p); +} + + +static ssize_t +show_attr_len_om2(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om2, + buf_p); +} + + +static ssize_t +show_attr_len_om3(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om3, + buf_p); +} + + +static ssize_t +show_attr_len_om4(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om4, + buf_p); +} + + +static ssize_t +show_attr_comp_rev(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_rev, + buf_p); +} + + +static ssize_t +show_attr_comp_eth(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_1, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10_40(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10_40, + buf_p); +} + + +static ssize_t +show_attr_comp_extend(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_extend, + buf_p); +} + + +static ssize_t +show_attr_rate_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_rate_id, + buf_p); +} + + +static ssize_t +show_attr_temperature(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_curr_temp, + buf_p); +} + + +static ssize_t +show_attr_voltage(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_curr_vol, + buf_p); +} + + +static ssize_t +show_attr_tx_bias(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_bias, + buf_p); +} + + +static ssize_t +show_attr_tx_power(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_power, + buf_p); +} + + +static ssize_t +show_attr_tx_eq(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_eq, + buf_p); +} + + +static ssize_t +show_attr_rx_power(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_power, + buf_p); +} + + +static ssize_t +show_attr_rx_am(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_am, + buf_p); +} + + +static ssize_t +show_attr_rx_em(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_em, + buf_p); +} + + +static ssize_t +show_attr_wavelength(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_wavelength, + buf_p); +} + + +static ssize_t +show_attr_extphy_offset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_extphy_offset, + buf_p); +} + + +static ssize_t +show_attr_extphy_reg(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_extphy_reg, + buf_p); +} + + +static ssize_t +show_attr_info(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_info, + buf_p); +} + + +static ssize_t +show_attr_if_type(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_type, + buf_p); +} + + +static ssize_t +show_attr_if_speed(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_speed, + buf_p); +} + + +static ssize_t +show_attr_if_lane(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_lane, + buf_p); +} + + +static ssize_t +show_attr_cdr(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_cdr, + buf_p); +} + + +static ssize_t +show_attr_soft_rs0(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs0, + buf_p); +} + + +static ssize_t +show_attr_soft_rs1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs1, + buf_p); +} + + +static ssize_t +show_attr_soft_rx_los(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_rx_los, + buf_p); +} + + +static ssize_t +show_attr_soft_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_disable, + buf_p); +} + + +static ssize_t +show_attr_soft_tx_fault(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_fault, + buf_p); +} + + +static ssize_t +show_attr_auto_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_auto_tx_disable, + buf_p); +} + + +/* ========== Store functions: transceiver (R/W) attribute ========== + */ +static ssize_t +_store_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_byte_hex_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if ((input < 0) || (input > 0xff)){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_binary_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_binary(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_cdr(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_byte_hex_attr(tobj_p, + tobj_p->set_cdr, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs0(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs1(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs1, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int check = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((check < 0) || (check > 0xf)){ + return -EBFONT; + } + return _store_transvr_byte_hex_attr(tobj_p, + tobj_p->set_soft_tx_disable, + buf_p, + count); +} + + +static ssize_t +store_attr_auto_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int err = -EPERM; + int input = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((input < 0) || (input > 0xf)){ + if (input != VAL_TRANSVR_FUNCTION_DISABLE) { + return -EBFONT; + } + } + lock_transvr_obj(tobj_p); + err = tobj_p->set_auto_tx_disable(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_tx_eq(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_tx_eq, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_am(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_rx_am, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_em(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_rx_em, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_offset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_extphy_offset, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_reg(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_extphy_reg, + buf_p, + count); +} + +/* ========== Show functions: For I/O Expander attribute ========== + */ +static ssize_t +_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset), + char *buf_p) { + size_t len; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR(" %s: data corruption! :%s\n", __func__, tobj_p->swp_name); + return -ENODATA; + } + mutex_lock(&ioexp_p->lock); + len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset)); + mutex_unlock(&ioexp_p->lock); + return len; +} + + +static ssize_t +show_attr_present(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_present, + buf_p); +} + + +static ssize_t +show_attr_tx_fault(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_fault, + buf_p); +} + + +static ssize_t +show_attr_rxlos(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_rxlos, + buf_p); +} + + +static ssize_t +show_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_disable, + buf_p); +} + + +static ssize_t +show_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_reset, + buf_p); +} + + +static ssize_t +show_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_lpmod, + buf_p); +} + + +static ssize_t +show_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_modsel, + buf_p); +} + + +static ssize_t +show_attr_hard_rs0(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_hard_rs0, + buf_p); +} + + +static ssize_t +show_attr_hard_rs1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_hard_rs1, + buf_p); +} + + +/* ========== Store functions: For I/O Expander (R/W) attribute ========== + */ +static ssize_t +_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*set_func)(struct ioexp_obj_s *ioexp_p, + int virt_offset, int input_val), + const char *buf_p, + size_t count) { + + int input, err; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR("%s: data corruption! :%s\n", + __func__, tobj_p->swp_name); + return -ENODATA; + } + input = sscanf_2_binary(buf_p); + if (input < 0) { + return -EBFONT; + } + mutex_lock(&ioexp_p->lock); + err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input); + mutex_unlock(&ioexp_p->lock); + if (err < 0){ + return err; + } + return count; +} + +static ssize_t +store_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_tx_disable, + buf_p, + count); +} + + +static ssize_t +store_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_reset, + buf_p, + count); +} + + +static ssize_t +store_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_lpmod, + buf_p, + count); +} + + +static ssize_t +store_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_modsel, + buf_p, + count); +} + + +static ssize_t +store_attr_hard_rs0(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_hard_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_hard_rs1(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_hard_rs1, + buf_p, + count); +} + + +/* ========== SWPS attribute: For module control ========== + */ +static DEVICE_ATTR(platform, S_IRUGO, show_attr_platform, NULL); +static DEVICE_ATTR(version, S_IRUGO, show_attr_version, NULL); +static DEVICE_ATTR(status, S_IRUGO, show_attr_status, NULL); +static DEVICE_ATTR(reset_i2c, S_IWUSR, NULL, store_attr_reset_i2c); +static DEVICE_ATTR(reset_swps, S_IWUSR, NULL, store_attr_reset_swps); +static DEVICE_ATTR(auto_config, S_IRUGO|S_IWUSR, show_attr_auto_config, store_attr_auto_config); +static DEVICE_ATTR(block_poll, S_IRUGO|S_IWUSR, show_attr_block_poll, store_attr_block_poll); +static DEVICE_ATTR(io_no_init, S_IRUGO|S_IWUSR, show_attr_io_no_init, store_attr_io_no_init); + + +/* ========== Transceiver attribute: from eeprom ========== + */ +static DEVICE_ATTR(id, S_IRUGO, show_attr_id, NULL); +static DEVICE_ATTR(ext_id, S_IRUGO, show_attr_ext_id, NULL); +static DEVICE_ATTR(connector, S_IRUGO, show_attr_connector, NULL); +static DEVICE_ATTR(vendor_name, S_IRUGO, show_attr_vendor_name, NULL); +static DEVICE_ATTR(vendor_pn, S_IRUGO, show_attr_vendor_pn, NULL); +static DEVICE_ATTR(vendor_rev, S_IRUGO, show_attr_vendor_rev, NULL); +static DEVICE_ATTR(vendor_sn, S_IRUGO, show_attr_vendor_sn, NULL); +static DEVICE_ATTR(power_cls, S_IRUGO, show_attr_power_cls, NULL); +static DEVICE_ATTR(br, S_IRUGO, show_attr_br, NULL); +static DEVICE_ATTR(len_sm, S_IRUGO, show_attr_len_sm, NULL); +static DEVICE_ATTR(len_smf, S_IRUGO, show_attr_len_smf, NULL); +static DEVICE_ATTR(len_om1, S_IRUGO, show_attr_len_om1, NULL); +static DEVICE_ATTR(len_om2, S_IRUGO, show_attr_len_om2, NULL); +static DEVICE_ATTR(len_om3, S_IRUGO, show_attr_len_om3, NULL); +static DEVICE_ATTR(len_om4, S_IRUGO, show_attr_len_om4, NULL); +static DEVICE_ATTR(comp_rev, S_IRUGO, show_attr_comp_rev, NULL); +static DEVICE_ATTR(comp_eth, S_IRUGO, show_attr_comp_eth, NULL); +static DEVICE_ATTR(comp_eth_10, S_IRUGO, show_attr_comp_eth_10, NULL); +static DEVICE_ATTR(comp_eth_10_40, S_IRUGO, show_attr_comp_eth_10_40, NULL); +static DEVICE_ATTR(comp_extend, S_IRUGO, show_attr_comp_extend, NULL); +static DEVICE_ATTR(rate_id, S_IRUGO, show_attr_rate_id, NULL); +static DEVICE_ATTR(temperature, S_IRUGO, show_attr_temperature, NULL); +static DEVICE_ATTR(voltage, S_IRUGO, show_attr_voltage, NULL); +static DEVICE_ATTR(tx_bias, S_IRUGO, show_attr_tx_bias, NULL); +static DEVICE_ATTR(tx_power, S_IRUGO, show_attr_tx_power, NULL); +static DEVICE_ATTR(rx_power, S_IRUGO, show_attr_rx_power, NULL); +static DEVICE_ATTR(info, S_IRUGO, show_attr_info, NULL); +static DEVICE_ATTR(if_type, S_IRUGO, show_attr_if_type, NULL); +static DEVICE_ATTR(if_speed, S_IRUGO, show_attr_if_speed, NULL); +static DEVICE_ATTR(if_lane, S_IRUGO, show_attr_if_lane, NULL); +static DEVICE_ATTR(soft_rx_los, S_IRUGO, show_attr_soft_rx_los, NULL); +static DEVICE_ATTR(soft_tx_fault, S_IRUGO, show_attr_soft_tx_fault, NULL); +static DEVICE_ATTR(wavelength, S_IRUGO, show_attr_wavelength, NULL); +static DEVICE_ATTR(tx_eq, S_IRUGO|S_IWUSR, show_attr_tx_eq, store_attr_tx_eq); +static DEVICE_ATTR(rx_am, S_IRUGO|S_IWUSR, show_attr_rx_am, store_attr_rx_am); +static DEVICE_ATTR(rx_em, S_IRUGO|S_IWUSR, show_attr_rx_em, store_attr_rx_em); +static DEVICE_ATTR(cdr, S_IRUGO|S_IWUSR, show_attr_cdr, store_attr_cdr); +static DEVICE_ATTR(soft_rs0, S_IRUGO|S_IWUSR, show_attr_soft_rs0, store_attr_soft_rs0); +static DEVICE_ATTR(soft_rs1, S_IRUGO|S_IWUSR, show_attr_soft_rs1, store_attr_soft_rs1); +static DEVICE_ATTR(soft_tx_disable, S_IRUGO|S_IWUSR, show_attr_soft_tx_disable, store_attr_soft_tx_disable); +static DEVICE_ATTR(auto_tx_disable, S_IRUGO|S_IWUSR, show_attr_auto_tx_disable, store_attr_auto_tx_disable); +static DEVICE_ATTR(extphy_offset, S_IRUGO|S_IWUSR, show_attr_extphy_offset, store_attr_extphy_offset); +static DEVICE_ATTR(extphy_reg, S_IRUGO|S_IWUSR, show_attr_extphy_reg, store_attr_extphy_reg); + +/* ========== IO Expander attribute: from expander ========== + */ +static DEVICE_ATTR(present, S_IRUGO, show_attr_present, NULL); +static DEVICE_ATTR(tx_fault, S_IRUGO, show_attr_tx_fault, NULL); +static DEVICE_ATTR(rxlos, S_IRUGO, show_attr_rxlos, NULL); +static DEVICE_ATTR(tx_disable, S_IRUGO|S_IWUSR, show_attr_tx_disable, store_attr_tx_disable); +static DEVICE_ATTR(reset, S_IRUGO|S_IWUSR, show_attr_reset, store_attr_reset); +static DEVICE_ATTR(lpmod, S_IRUGO|S_IWUSR, show_attr_lpmod, store_attr_lpmod); +static DEVICE_ATTR(modsel, S_IRUGO|S_IWUSR, show_attr_modsel, store_attr_modsel); +static DEVICE_ATTR(hard_rs0, S_IRUGO|S_IWUSR, show_attr_hard_rs0, store_attr_hard_rs0); +static DEVICE_ATTR(hard_rs1, S_IRUGO|S_IWUSR, show_attr_hard_rs1, store_attr_hard_rs1); + +/* ========== Functions for module handling ========== + */ +static void +clean_port_objs(void){ + + dev_t dev_num; + char dev_name[32]; + struct device *device_p; + struct transvr_obj_s *tobj_p; + int minor_curr, port_id; + + for (minor_curr=0; minor_curri2c_client_p) { + i2c_put_adapter(tobj_p->i2c_client_p->adapter); + kfree(tobj_p->i2c_client_p); + } + kfree(tobj_p->vendor_name); + kfree(tobj_p->vendor_pn); + kfree(tobj_p->vendor_rev); + kfree(tobj_p->vendor_sn); + kfree(tobj_p->worker_p); + kfree(tobj_p); + } + dev_num = MKDEV(port_major, minor_curr); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static void +clean_swps_common(void){ + + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(SWP_DEV_MODCTL); + if (device_p){ + dev_num = MKDEV(ctl_major, 1); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + cancel_delayed_work_sync(&swp_polling); + if (platform_p) { + kfree(platform_p); + } + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static int +get_platform_type(void){ + + int i, tmp; + int auto_chan = -1; + int auto_addr = -1; + int pf_total = ARRAY_SIZE(platform_map); + char log_msg[64] = "ERROR"; + + platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL); + if (!platform_p){ + snprintf(log_msg, sizeof(log_msg), "kzalloc fail"); + goto err_get_platform_type_1; + } + memset(platform_p->name, 0, sizeof(platform_p->name)); + + switch (PLATFORM_SETTINGS) { + case PLATFORM_TYPE_AUTO: + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", dmi_get_system_info(DMI_BOARD_NAME)); + for (i=0; iname, platform_map[i].name) == 0) { + platform_p->id = platform_map[i].id; + snprintf(log_msg, sizeof(log_msg), + "Auto detect platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Auto detect fail! detect platform: %s", + platform_p->name); + goto err_get_platform_type_2; + + case PLATFORM_TYPE_PEONY_AUTO: +#ifdef SWPS_PEONY_SFP + auto_chan = peony_sfp_ioexp_layout[0].addr[0].chan_id; + auto_addr = peony_sfp_ioexp_layout[0].addr[0].chip_addr; +#endif + tmp = _is_i2c_target_exist(auto_chan, auto_addr); + switch (tmp) { + case 0: /* Copper SKU */ + SWPS_INFO("Auto-detected :Peony :Copper\n"); + platform_p->id = PLATFORM_TYPE_PEONY_COPPER_GA; + goto map_platform_name; + + case 1: /* SFP SKU */ + SWPS_INFO("Auto-detected :Peony :SFP\n"); + platform_p->id = PLATFORM_TYPE_PEONY_SFP_GA; + goto map_platform_name; + + default: + break; + } + snprintf(log_msg, sizeof(log_msg), + "Auto detect Peony SKU fail! :%d", tmp); + goto err_get_platform_type_2; + + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + case PLATFORM_TYPE_REDWOOD: + case PLATFORM_TYPE_REDWOOD_FSL: + case PLATFORM_TYPE_HUDSON32I_GA: + case PLATFORM_TYPE_SPRUCE: + case PLATFORM_TYPE_CYPRESS_GA1: + case PLATFORM_TYPE_CYPRESS_GA2: + case PLATFORM_TYPE_CYPRESS_BAI: + case PLATFORM_TYPE_TAHOE: + case PLATFORM_TYPE_SEQUOIA_GA: + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + case PLATFORM_TYPE_COTTONWOOD_RANGELEY: + case PLATFORM_TYPE_MAPLE_GA: + case PLATFORM_TYPE_MAPLE_B: + case PLATFORM_TYPE_GULMOHAR_GA: + case PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA: + case PLATFORM_TYPE_PEONY_SFP_GA: + case PLATFORM_TYPE_PEONY_COPPER_GA: + platform_p->id = PLATFORM_SETTINGS; + goto map_platform_name; + + default: + break; + } + snprintf(log_msg, sizeof(log_msg), + "PLATFORM_SETTINGS:%d undefined", PLATFORM_SETTINGS); + goto err_get_platform_type_2; + +map_platform_name: + for (i=0; iid == platform_map[i].id) { + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", platform_map[i].name); + snprintf(log_msg, sizeof(log_msg), + "User setup platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Internal error, can not map id:%d", + platform_p->id ); + goto err_get_platform_type_2; + +ok_get_platform_type_1: + SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return 0; + +err_get_platform_type_2: + kfree(platform_p); +err_get_platform_type_1: + SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return -1; +} + + +static int +get_layout_info(void){ + + switch (platform_p->id) { +#ifdef SWPS_MAGNOLIA + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + gpio_rest_mux = magnolia_gpio_rest_mux; + ioexp_layout = magnolia_ioexp_layout; + port_layout = magnolia_port_layout; + ioexp_total = ARRAY_SIZE(magnolia_ioexp_layout); + port_total = ARRAY_SIZE(magnolia_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD + case PLATFORM_TYPE_REDWOOD: + gpio_rest_mux = redwood_gpio_rest_mux; + ioexp_layout = redwood_ioexp_layout; + port_layout = redwood_port_layout; + ioexp_total = ARRAY_SIZE(redwood_ioexp_layout); + port_total = ARRAY_SIZE(redwood_port_layout); + break; +#endif +#ifdef SWPS_HUDSON32I_GA + case PLATFORM_TYPE_HUDSON32I_GA: + gpio_rest_mux = hudsin32iga_gpio_rest_mux; + ioexp_layout = hudson32iga_ioexp_layout; + port_layout = hudson32iga_port_layout; + ioexp_total = ARRAY_SIZE(hudson32iga_ioexp_layout); + port_total = ARRAY_SIZE(hudson32iga_port_layout); + break; +#endif +#ifdef SWPS_SPRUCE + case PLATFORM_TYPE_SPRUCE: + gpio_rest_mux = spruce_gpio_rest_mux; + ioexp_layout = spruce_ioexp_layout; + port_layout = spruce_port_layout; + ioexp_total = ARRAY_SIZE(spruce_ioexp_layout); + port_total = ARRAY_SIZE(spruce_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA1 + case PLATFORM_TYPE_CYPRESS_GA1: + gpio_rest_mux = cypress_ga1_gpio_rest_mux; + ioexp_layout = cypress_ga1_ioexp_layout; + port_layout = cypress_ga1_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga1_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga1_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA2 + case PLATFORM_TYPE_CYPRESS_GA2: + gpio_rest_mux = cypress_ga2_gpio_rest_mux; + ioexp_layout = cypress_ga2_ioexp_layout; + port_layout = cypress_ga2_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga2_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga2_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_BAI + case PLATFORM_TYPE_CYPRESS_BAI: + gpio_rest_mux = cypress_b_gpio_rest_mux; + ioexp_layout = cypress_b_ioexp_layout; + port_layout = cypress_b_port_layout; + ioexp_total = ARRAY_SIZE(cypress_b_ioexp_layout); + port_total = ARRAY_SIZE(cypress_b_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD_FSL + case PLATFORM_TYPE_REDWOOD_FSL: + gpio_rest_mux = redwood_fsl_gpio_rest_mux; + ioexp_layout = redwood_fsl_ioexp_layout; + port_layout = redwood_fsl_port_layout; + ioexp_total = ARRAY_SIZE(redwood_fsl_ioexp_layout); + port_total = ARRAY_SIZE(redwood_fsl_port_layout); + break; +#endif +#ifdef SWPS_TAHOE + case PLATFORM_TYPE_TAHOE: + gpio_rest_mux = tahoe_gpio_rest_mux; + ioexp_layout = tahoe_ioexp_layout; + port_layout = tahoe_port_layout; + ioexp_total = ARRAY_SIZE(tahoe_ioexp_layout); + port_total = ARRAY_SIZE(tahoe_port_layout); + break; +#endif +#ifdef SWPS_SEQUOIA + case PLATFORM_TYPE_SEQUOIA_GA: + gpio_rest_mux = sequoia_gpio_rest_mux; + ioexp_layout = sequoia_ioexp_layout; + port_layout = sequoia_port_layout; + ioexp_total = ARRAY_SIZE(sequoia_ioexp_layout); + port_total = ARRAY_SIZE(sequoia_port_layout); + break; +#endif +#ifdef SWPS_LAVENDER + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + gpio_rest_mux = lavender_gpio_rest_mux; + ioexp_layout = lavender_ioexp_layout; + port_layout = lavender_port_layout; + ioexp_total = ARRAY_SIZE(lavender_ioexp_layout); + port_total = ARRAY_SIZE(lavender_port_layout); + break; +#endif +#ifdef SWPS_COTTONWOOD_RANGELEY + case PLATFORM_TYPE_COTTONWOOD_RANGELEY: + gpio_rest_mux = cottonwood_rangeley_gpio_rest_mux; + ioexp_layout = cottonwood_rangeley_ioexp_layout; + port_layout = cottonwood_rangeley_port_layout; + ioexp_total = ARRAY_SIZE(cottonwood_rangeley_ioexp_layout); + port_total = ARRAY_SIZE(cottonwood_rangeley_port_layout); + break; +#endif +#ifdef SWPS_MAPLE_GA + case PLATFORM_TYPE_MAPLE_GA: + gpio_rest_mux = maple_ga_gpio_rest_mux; + ioexp_layout = maple_ga_ioexp_layout; + port_layout = maple_ga_port_layout; + ioexp_total = ARRAY_SIZE(maple_ga_ioexp_layout); + port_total = ARRAY_SIZE(maple_ga_port_layout); + break; +#endif +#ifdef SWPS_MAPLE_B + case PLATFORM_TYPE_MAPLE_B: + gpio_rest_mux = maple_b_gpio_rest_mux; + ioexp_layout = maple_b_ioexp_layout; + port_layout = maple_b_port_layout; + ioexp_total = ARRAY_SIZE(maple_b_ioexp_layout); + port_total = ARRAY_SIZE(maple_b_port_layout); + break; +#endif +#ifdef SWPS_GULMOHAR + case PLATFORM_TYPE_GULMOHAR_GA: + gpio_rest_mux = gulmohar_gpio_rest_mux; + ioexp_layout = gulmohar_ioexp_layout; + port_layout = gulmohar_port_layout; + ioexp_total = ARRAY_SIZE(gulmohar_ioexp_layout); + port_total = ARRAY_SIZE(gulmohar_port_layout); + break; +#endif +#ifdef SWPS_GULMOHAR_2T_EVT1 + case PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA: + gpio_rest_mux = gulmohar_2t_evt1_gpio_rest_mux; + ioexp_layout = gulmohar_2t_evt1_ioexp_layout; + port_layout = gulmohar_2t_evt1_port_layout; + ioexp_total = ARRAY_SIZE(gulmohar_2t_evt1_ioexp_layout); + port_total = ARRAY_SIZE(gulmohar_2t_evt1_port_layout); + break; +#endif +#ifdef SWPS_PEONY_SFP + case PLATFORM_TYPE_PEONY_SFP_GA: + gpio_rest_mux = peony_sfp_gpio_rest_mux; + ioexp_layout = peony_sfp_ioexp_layout; + port_layout = peony_sfp_port_layout; + ioexp_total = ARRAY_SIZE(peony_sfp_ioexp_layout); + port_total = ARRAY_SIZE(peony_sfp_port_layout); + break; +#endif +#ifdef SWPS_PEONY_COPPER + case PLATFORM_TYPE_PEONY_COPPER_GA: + gpio_rest_mux = peony_copper_gpio_rest_mux; + ioexp_layout = peony_copper_ioexp_layout; + port_layout = peony_copper_port_layout; + ioexp_total = ARRAY_SIZE(peony_copper_ioexp_layout); + port_total = ARRAY_SIZE(peony_copper_port_layout); + break; +#endif + + default: + SWPS_ERR(" Invalid platform: %d (%s)\n", + platform_p->id, platform_p->name); + return -1; + } + SWPS_INFO("Start to initial platform: %d (%s)\n", + platform_p->id, platform_p->name); + return 0; +} + + +/* ========== Functions for objects operations ========== + */ +static int +__detect_issues_port(int minor_num) { + + struct transvr_obj_s *tobj_p; + int port_id = port_layout[minor_num].port_id; + char port_name[32] = "ERR"; + char *i2c_emsg = "detected bad transceiver/cable"; + + memset(port_name, 0, sizeof(port_name)); + snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id); + tobj_p = _get_transvr_obj(port_name); + if (!tobj_p) { + SWPS_INFO("%s: tobj_p is NULL :%d\n", __func__, minor_num); + return -1; + } + if (resync_channel_tier_2(tobj_p) < 0) { + if (check_channel_tier_1() < 0) { + goto get_target_issues_port; + } + } + /* Re-check again for i2c-gpio special case */ + if (check_channel_tier_1() < 0) { + goto get_target_issues_port; + } + return 0; + +get_target_issues_port: + alarm_msg_2_user(tobj_p, i2c_emsg); + return -2; +} + + +static int +_detect_issues_port(void) { + /* OK : retrun -1; + * Fail: return fail at which minor number (0~N) + */ + char *emsg = "ERR"; + int minor = 0; + int minor_2st = 1; + + /* Force moving the initial channel pointer + * Filter out case of fail at minor-0 port + */ + while (minor_2st < port_total) { + minor = minor_2st; + if (__detect_issues_port(minor_2st) < 0) { + emsg = "detect minor_2st fail"; + goto err_p_detect_issues_port; + } + minor_2st += 8; + } + /* Scan all port */ + for (minor=0; minor:%d\n", __func__, emsg, minor_err); + return -1; +} + + +static int +check_transvr_obj_one(char *dev_name){ + /* [Return] + * 0 : Doesn't need to take care + * -1 : Single error + * -2 : Critical error (I2C topology die) + * -9 : Internal error + */ + struct transvr_obj_s *tobj_p = NULL; + int retval = -9; + + tobj_p = _get_transvr_obj(dev_name); + if (!tobj_p) { + SWPS_ERR("%s: %s _get_transvr_obj fail\n", + __func__, dev_name); + return -9; + } + /* Check transceiver current status */ + lock_transvr_obj(tobj_p); + retval = tobj_p->check(tobj_p); + unlock_transvr_obj(tobj_p); + switch (retval) { + case 0: + case ERR_TRANSVR_UNPLUGGED: + case ERR_TRNASVR_BE_ISOLATED: + case ERR_TRANSVR_TASK_BUSY: + return 0; + + case ERR_TRANSVR_I2C_CRASH: + default: + break; + } + /* Identify abnormal case */ + if (check_channel_tier_1() < 0) { + SWPS_DEBUG("%s: %s critical error :%d\n", + __func__, dev_name, retval); + return -2; + } + SWPS_DEBUG("%s: %s single error :%d\n", + __func__, dev_name, retval); + return -1; +} + + +static int +check_transvr_objs(void){ + + char dev_name[32]; + int port_id, err_code; + int minor_curr = 0; + + for (minor_curr=0; minor_curr:%d\n", + __func__, dev_name, err_code); + break; + } + } + return 0; + +err_check_transvr_objs: + SWPS_ERR("%s: %s reset_i2c_topology fail.\n", + __func__, dev_name); + return -1; +} + + +static void +swp_polling_worker(struct work_struct *work){ + + /* Reset I2C */ + if (flag_i2c_reset) { + goto polling_reset_i2c; + } + /* Check IOEXP */ + if (check_ioexp_objs() < 0) { + goto polling_reset_i2c; + } + /* Check transceiver */ + if (check_transvr_objs() < 0) { + SWPS_DEBUG("%s: check_transvr_objs fail.\n", __func__); + flag_i2c_reset = 1; + } + goto polling_schedule_round; + +polling_reset_i2c: + SWPS_DEBUG("%s: reset_i2c_topology start.\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset i2c fail!\n", __func__); + flag_i2c_reset = 1; + } else { + SWPS_DEBUG("%s: reset_i2c_topology OK.\n", __func__); + flag_i2c_reset = 0; + } +polling_schedule_round: + schedule_delayed_work(&swp_polling, _get_polling_period()); +} + + +/* ========== Functions for register something ========== + */ +static int +register_transvr_common_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_id) < 0) { + err_attr = "dev_attr_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_ext_id) < 0) { + err_attr = "dev_attr_ext_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_connector) < 0) { + err_attr = "dev_attr_connector"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_name) < 0) { + err_attr = "dev_attr_vendor_name"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_pn) < 0) { + err_attr = "dev_attr_vendor_pn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_rev) < 0) { + err_attr = "dev_attr_vendor_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_sn) < 0) { + err_attr = "dev_attr_vendor_sn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_br) < 0) { + err_attr = "dev_attr_br"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_smf) < 0) { + err_attr = "dev_attr_len_smf"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om1) < 0) { + err_attr = "dev_attr_len_om1"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om2) < 0) { + err_attr = "dev_attr_len_om2"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om3) < 0) { + err_attr = "dev_attr_len_om3"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om4) < 0) { + err_attr = "dev_attr_len_om4"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_extend) < 0) { + err_attr = "dev_attr_comp_extend"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth) < 0) { + err_attr = "dev_attr_comp_eth"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_rev) < 0) { + err_attr = "dev_attr_comp_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_info) < 0) { + err_attr = "dev_attr_info"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_type) < 0) { + err_attr = "dev_attr_if_type"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_speed) < 0) { + err_attr = "dev_attr_if_speed"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_lane) < 0) { + err_attr = "dev_attr_if_lane"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_temperature) < 0) { + err_attr = "dev_attr_temperature"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_voltage) < 0) { + err_attr = "dev_attr_voltage"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_bias) < 0) { + err_attr = "dev_attr_tx_bias"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_power) < 0) { + err_attr = "dev_attr_tx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_power) < 0) { + err_attr = "dev_attr_rx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_eq) < 0) { + err_attr = "dev_attr_tx_eq"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_em) < 0) { + err_attr = "dev_attr_rx_em"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_wavelength) < 0) { + err_attr = "dev_attr_wavelength"; + goto err_transvr_comm_attr; + } + return 0; + +err_transvr_comm_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + +static int +register_transvr_sfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10) < 0) { + err_attr = "dev_attr_comp_eth_10"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_len_sm) < 0) { + err_attr = "dev_attr_len_sm"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_rate_id) < 0) { + err_attr = "dev_attr_rate_id"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs0) < 0) { + err_attr = "dev_attr_soft_rs0"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs1) < 0) { + err_attr = "dev_attr_soft_rs1"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_offset) < 0) { + err_attr = "dev_attr_extphy_offset"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_reg) < 0) { + err_attr = "dev_attr_extphy_reg"; + goto err_transvr_sfp_attr; + } + return 0; + +err_transvr_sfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10_40) < 0) { + err_attr = "dev_attr_comp_eth_10_40"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_power_cls) < 0) { + err_attr = "dev_attr_power_cls"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rx_los) < 0) { + err_attr = "soft_rx_los"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_disable) < 0) { + err_attr = "soft_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_auto_tx_disable) < 0) { + err_attr = "auto_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_fault) < 0) { + err_attr = "soft_tx_fault"; + goto err_transvr_qsfp_attr; + } + return 0; + +err_transvr_qsfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp28_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_qsfp_attr(device_p) < 0){ + err_attr = "register_transvr_qsfp_attr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_cdr) < 0) { + err_attr = "dev_attr_cdr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_rx_am) < 0) { + err_attr = "dev_attr_rx_am"; + goto err_transvr_qsfp28_attr; + } + return 0; + +err_transvr_qsfp28_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + switch (transvr_obj->layout){ + case TRANSVR_TYPE_SFP: + if (register_transvr_sfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + if (register_transvr_qsfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP_28: + if (register_transvr_qsfp28_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + default: + goto err_reg_tvr_attr; + } + return 0; + +err_reg_tvr_attr: + SWPS_ERR("%s: fail! type=%d \n", __func__, transvr_obj->type); + return -1; +} + + +static int +register_ioexp_attr_sfp_1(struct device *device_p){ + /* Support machine type: + * - SFP : Magnolia + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_fault) < 0) { + err_attr = "dev_attr_tx_fault"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_rxlos) < 0) { + err_attr = "dev_attr_rxlos"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_disable) < 0) { + err_attr = "dev_attr_tx_disable"; + goto err_ioexp_sfp1_attr; + } + return 0; + +err_ioexp_sfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_ioexp_attr_sfp_2(struct device *device_p){ + /* Support machine type: + * - SFP28 : Cypress + */ + char *err_attr = NULL; + + if (register_ioexp_attr_sfp_1(device_p) < 0){ + goto err_ioexp_sfp2_attr; + } + if (device_create_file(device_p, &dev_attr_hard_rs0) < 0) { + err_attr = "dev_attr_hard_rs0"; + goto err_ioexp_sfp2_attr; + } + if (device_create_file(device_p, &dev_attr_hard_rs1) < 0) { + err_attr = "dev_attr_hard_rs1"; + goto err_ioexp_sfp2_attr; + } + return 0; + +err_ioexp_sfp2_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_ioexp_attr_qsfp_1(struct device *device_p){ + /* Support machine type: + * - QSFP : Magnolia, Redwood, Hudson32i + * - QSFP+ : Magnolia, Redwood, Hudson32i + * - QSFP28: Redwood + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_reset) < 0) { + err_attr = "dev_attr_reset"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_lpmod) < 0) { + err_attr = "dev_attr_lpmod"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_modsel) < 0) { + err_attr = "dev_attr_modsel"; + goto err_ioexp_qsfp1_attr; + } + return 0; + +err_ioexp_qsfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_modctl_attr(struct device *device_p){ + + char *err_msg = NULL; + + if (device_create_file(device_p, &dev_attr_platform) < 0) { + err_msg = "dev_attr_platform"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_version) < 0) { + err_msg = "dev_attr_version"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_status) < 0) { + err_msg = "dev_attr_status"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_i2c) < 0) { + err_msg = "dev_attr_reset_i2c"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_swps) < 0) { + err_msg = "dev_attr_reset_swps"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_auto_config) < 0) { + err_msg = "dev_attr_auto_config"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_block_poll) < 0) { + err_msg = "dev_attr_block_poll"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_io_no_init) < 0) { + err_msg = "dev_attr_io_no_init"; + goto err_reg_modctl_attr; + } + + return 0; + +err_reg_modctl_attr: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int +register_ioexp_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + char *err_msg = "ERR"; + + switch (transvr_obj->ioexp_obj_p->ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case CPLD_TYPE_COTTONWOOD: + if (register_ioexp_attr_sfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + + case IOEXP_TYPE_MAPLE_NABC: + case IOEXP_TYPE_GULMOHAR_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + case IOEXP_TYPE_SFP_8P_LAYOUT_1: + if (register_ioexp_attr_sfp_2(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_2 fail"; + goto err_reg_ioexp_attr; + } + break; + + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case IOEXP_TYPE_MAPLE_0ABC: + case IOEXP_TYPE_GULMOHAR_7ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: + if (register_ioexp_attr_qsfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_qsfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + + default: + err_msg = "Unknow type"; + goto err_reg_ioexp_attr; + } + return 0; + +err_reg_ioexp_attr: + SWPS_ERR("%s: %s :%d \n", + __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type); + return -1; +} + + +static int +register_modctl_device(void) { + + struct device *device_p = NULL; + int minor_comm = 0; /* Default minor number for common device */ + dev_t dev_num = MKDEV(ctl_major, minor_comm); + char *err_msg = "ERROR"; + + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + NULL, /* void *private_data */ + SWP_DEV_MODCTL); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_modctl_device_1; + } + if (register_modctl_attr(device_p) < 0) { + err_msg = "register_modctl_attr fail"; + goto err_register_modctl_device_2; + } + return 0; + +err_register_modctl_device_2: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_register_modctl_device_1: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int +register_port_device(char *dev_name, + dev_t dev_num, + struct transvr_obj_s *transvr_obj){ + + struct device *device_p = NULL; + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + transvr_obj, /* void *private_data */ + dev_name); /* const char *fmt */ + if (IS_ERR(device_p)){ + goto err_regswp_create_dev; + } + if (register_transvr_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + if (register_ioexp_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + return 0; + +err_regswp_reg_attr: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_regswp_create_dev: + SWPS_ERR("%s fail! :%s\n", __func__, dev_name); + return -1; +} + + +static int +register_swp_module(void){ + + dev_t ctl_devt = 0; + dev_t port_devt = 0; + int dev_total = port_total + 1; /* char_dev for module control */ + + /* Register device number */ + if (alloc_chrdev_region(&ctl_devt, 0, 1, SWP_DEV_MODCTL) < 0){ + SWPS_WARN("Allocate CTL MAJOR failure! \n"); + goto err_register_swp_module_1; + } + if (alloc_chrdev_region(&port_devt, 0, port_total, SWP_CLS_NAME) < 0){ + SWPS_WARN("Allocate PORT MAJOR failure! \n"); + goto err_register_swp_module_2; + } + ctl_major = MAJOR(ctl_devt); + port_major = MAJOR(port_devt); + + /* Create class object */ + swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME); + if (IS_ERR(swp_class_p)) { + SWPS_ERR("Create class failure! \n"); + goto err_register_swp_module_3; + } + return 0; + +err_register_swp_module_3: + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_register_swp_module_2: + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); +err_register_swp_module_1: + return -1; +} + + +/* ========== Module initial relate ========== + */ +static int +create_ioexp_objs(void) { + + int i, run_mod; + + /* Clean IOEXP object */ + clean_ioexp_objs(); + /* Get running mode */ + run_mod = IOEXP_MODE_DIRECT; + if (SWP_POLLING_ENABLE){ + run_mod = IOEXP_MODE_POLLING; + } + /* Create IOEXP object */ + for(i=0; i devlen_max) { + snprintf(err_msg, sizeof(err_msg), + "SWP_DEV_PORT too long!"); + goto err_initport_create_tranobj; + } + memset(dev_name, 0, sizeof(dev_name)); + snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id); + /* Create transceiver object */ + ioexp_obj_p = get_ioexp_obj(ioexp_id); + if (!ioexp_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "IOEXP object:%d not exist", ioexp_id); + goto err_initport_create_tranobj; + } + transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p, + ioexp_virt_offset, transvr_type, + chipset_type, run_mod); + if (!transvr_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "Create transceiver object fail :%s", dev_name); + goto err_initport_create_tranobj; + } + /* Setup Lane_ID mapping */ + i = ARRAY_SIZE(port_layout[minor_curr].lane_id); + j = ARRAY_SIZE(transvr_obj_p->lane_id); + if (i != j) { + snprintf(err_msg, sizeof(err_msg), + "Lane_id size inconsistent %d/%d", i, j); + goto err_initport_reg_device; + } + memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int)); + /* Create and register device object */ + if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){ + snprintf(err_msg, sizeof(err_msg), + "register_port_device fail"); + goto err_initport_reg_device; + } + /* Setup device_ptr of transvr_obj */ + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + snprintf(err_msg, sizeof(err_msg), + "get_swpdev_by_name fail"); + goto err_initport_reg_device; + } + transvr_obj_p->transvr_dev_p = dev_p; + /* Success */ + ok_count++; + } + SWPS_INFO("%s: initialed %d port-dev\n",__func__, ok_count); + return 0; + +err_initport_reg_device: + kfree(transvr_obj_p); +err_initport_create_tranobj: + clean_port_objs(); + SWPS_ERR("%s: %s", __func__, err_msg); + SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n", + port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod); + return -1; +} + + +static int +init_dev_topology(void){ + + int err; + char *emsg = "ERR"; + flag_mod_state = SWP_STATE_NORMAL; + + err = init_ioexp_objs(); + switch(err){ + case 0: /* Normal */ + SWPS_DEBUG("%s: normal case\n", __func__); + break; + + case -1: /* topology error */ + SWPS_DEBUG("%s: detect tier-1 topology initial failure :%d\n", + __func__, err); + /* Reset and isolate */ + err = reset_i2c_topology(); + if (err < 0) { + emsg = "reset i2c topology fail"; + goto err_init_dev_topology; + } + /* Re-initial again */ + err = init_ioexp_objs(); + if (err < 0) { + emsg = "re-init ioexp objects fail"; + goto err_init_dev_topology; + } + break; + + case -2: /* Internal error */ + SWPS_DEBUG("%s: internal error case\n", __func__); + err = -2; + emsg = "internal error"; + goto err_init_dev_topology; + + default: + SWPS_DEBUG("%s: undefined error case\n", __func__); + emsg = "undefined error case"; + goto err_init_dev_topology; + } + SWPS_DEBUG("%s: initial I2C topology success\n", __func__); + return 0; + +err_init_dev_topology: + SWPS_ERR("%s: %s :%d\n", __func__, emsg, err); + return -1; +} + + +static int +init_polling_task(void){ + + if (SWP_POLLING_ENABLE){ + schedule_delayed_work(&swp_polling, _get_polling_period()); + } + return 0; +} + + +static int +init_swps_common(void){ + + char *err_msg = "ERR"; + + block_polling = 0; + auto_config = 0; + if ((SWP_AUTOCONFIG_ENABLE) && (SWP_POLLING_ENABLE)){ + auto_config = 1; + } + if (register_modctl_device() < 0) { + err_msg = "register_modctl_device fail"; + goto err_init_swps_common_1; + } + if (_update_auto_config_2_trnasvr() < 0) { + err_msg = "_update_auto_config_2_trnasvr fail"; + goto err_init_swps_common_1; + } + if (init_polling_task() < 0){ + err_msg = "init_polling_task fail"; + goto err_init_swps_common_1; + } + return 0; + +err_init_swps_common_1: + clean_swps_common(); + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int __init +swp_module_init(void){ + + if (get_platform_type() < 0){ + goto err_init_out; + } + if (get_layout_info() < 0){ + goto err_init_out; + } + if (register_swp_module() < 0){ + goto err_init_out; + } + if (create_ioexp_objs() < 0){ + goto err_init_ioexp; + } + if (create_port_objs() < 0){ + goto err_init_portobj; + } + if (init_mux_objs(gpio_rest_mux) < 0){ + goto err_init_mux; + } + if (init_dev_topology() < 0){ + goto err_init_topology; + } + if (init_swps_common() < 0){ + goto err_init_topology; + } + SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION); + return 0; + + +err_init_topology: + clean_mux_objs(); +err_init_mux: + clean_port_objs(); +err_init_portobj: + clean_ioexp_objs(); +err_init_ioexp: + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_init_out: + SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION); + return -1; +} + + +static void __exit +swp_module_exit(void){ + + clean_swps_common(); + clean_port_objs(); + clean_ioexp_objs(); + clean_mux_objs(); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); + SWPS_INFO("Remove Inventec switch-port module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(SWP_AUTHOR); +MODULE_DESCRIPTION(SWP_DESC); +MODULE_VERSION(SWP_VERSION); +MODULE_LICENSE(SWP_LICENSE); +MODULE_SOFTDEP("pre: inv_platform"); + +module_init(swp_module_init); +module_exit(swp_module_exit); + + + + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.h new file mode 100644 index 000000000000..ad1f337b0c06 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.h @@ -0,0 +1,1621 @@ +#ifndef INV_SWPS_H +#define INV_SWPS_H + +#include "transceiver.h" +#include "io_expander.h" +#include "inv_mux.h" + +/* Module settings */ +#define SWP_CLS_NAME "swps" +#define SWP_DEV_PORT "port" +#define SWP_DEV_MODCTL "module" +#define SWP_RESET_PWD "inventec" +#define SWP_POLLING_PERIOD (300) /* msec */ +#define SWP_POLLING_ENABLE (1) +#define SWP_AUTOCONFIG_ENABLE (1) + +/* Module information */ +#define SWP_AUTHOR "Neil " +#define SWP_DESC "Inventec port and transceiver driver" +#define SWP_VERSION "C1-4.3.5" +#define SWP_LICENSE "GPL" + +/* Module status define */ +#define SWP_STATE_NORMAL (0) +#define SWP_STATE_I2C_DIE (-91) + +/* [Note]: + * Functions and mechanism for auto-detect platform type is ready, + * But HW and BIOS not ready! We need to wait them. + * So, please do not use PLATFORM_TYPE_AUTO until they are ready. + * (2016.06.13) + */ +#define PLATFORM_TYPE_AUTO (100) +#define PLATFORM_TYPE_MAGNOLIA (111) +#define PLATFORM_TYPE_MAGNOLIA_FNC (112) +#define PLATFORM_TYPE_REDWOOD (121) +#define PLATFORM_TYPE_REDWOOD_FSL (122) +#define PLATFORM_TYPE_HUDSON32I_GA (131) +#define PLATFORM_TYPE_SPRUCE (141) +#define PLATFORM_TYPE_CYPRESS_GA1 (151) /* Up -> Down */ +#define PLATFORM_TYPE_CYPRESS_GA2 (152) /* Down -> Up */ +#define PLATFORM_TYPE_CYPRESS_BAI (153) /* Down -> Up */ +#define PLATFORM_TYPE_TAHOE (161) +#define PLATFORM_TYPE_SEQUOIA_GA (171) +#define PLATFORM_TYPE_LAVENDER_GA (181) +#define PLATFORM_TYPE_LAVENDER_ONL (182) +#define PLATFORM_TYPE_COTTONWOOD_RANGELEY (191) +#define PLATFORM_TYPE_MAPLE_GA (201) +#define PLATFORM_TYPE_GULMOHAR_GA (202) +#define PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA (203) +#define PLATFORM_TYPE_PEONY_SFP_GA (204) +#define PLATFORM_TYPE_PEONY_COPPER_GA (205) +#define PLATFORM_TYPE_PEONY_AUTO (206) +#define PLATFORM_TYPE_MAPLE_B (207) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_MAPLE_B + +/* Define platform flag and kernel version */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA_FNC) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD) + #define SWPS_REDWOOD (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD_FSL) + #define SWPS_REDWOOD_FSL (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_HUDSON32I_GA) + #define SWPS_HUDSON32I_GA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SPRUCE) + #define SWPS_SPRUCE (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA1) + #define SWPS_CYPRESS_GA1 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA2) + #define SWPS_CYPRESS_GA2 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_BAI) + #define SWPS_CYPRESS_BAI (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_TAHOE) + #define SWPS_TAHOE (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA) + #define SWPS_SEQUOIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_COTTONWOOD_RANGELEY) + #define SWPS_COTTONWOOD_RANGELEY (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE_GA) + #define SWPS_MAPLE_GA (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE_B) + #define SWPS_MAPLE_B (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_GULMOHAR_GA) + #define SWPS_GULMOHAR (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA) + #define SWPS_GULMOHAR_2T_EVT1 (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_PEONY_SFP_GA) + #define SWPS_PEONY_SFP (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_PEONY_COPPER_GA) + #define SWPS_PEONY_COPPER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_PEONY_AUTO) + #define SWPS_PEONY_SFP (1) + #define SWPS_PEONY_COPPER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#endif + +struct inv_platform_s { + int id; + char name[64]; +}; + +struct inv_ioexp_layout_s { + int ioexp_id; + int ioexp_type; + struct ioexp_addr_s addr[4]; +}; + +struct inv_port_layout_s { + int port_id; + int chan_id; + int ioexp_id; + int ioexp_offset; + int transvr_type; + int chipset_type; + int lane_id[8]; +}; + + +/* ========================================== + * Inventec Platform Settings + * ========================================== + */ +struct inv_platform_s platform_map[] = { + {PLATFORM_TYPE_AUTO, "Auto-Detect" }, + {PLATFORM_TYPE_MAGNOLIA, "Magnolia" }, + {PLATFORM_TYPE_MAGNOLIA_FNC, "Magnolia_FNC" }, + {PLATFORM_TYPE_REDWOOD, "Redwood" }, + {PLATFORM_TYPE_REDWOOD_FSL, "Redwood_FSL" }, + {PLATFORM_TYPE_HUDSON32I_GA, "Hudson32i" }, + {PLATFORM_TYPE_SPRUCE, "Spruce" }, + {PLATFORM_TYPE_CYPRESS_GA1, "Cypress_GA1" }, + {PLATFORM_TYPE_CYPRESS_GA2, "Cypress_GA2" }, + {PLATFORM_TYPE_CYPRESS_BAI, "Cypress_BAI" }, + {PLATFORM_TYPE_TAHOE, "Tahoe" }, + {PLATFORM_TYPE_SEQUOIA_GA, "Sequoia_GA" }, + {PLATFORM_TYPE_LAVENDER_GA, "Lavender_GA" }, + {PLATFORM_TYPE_LAVENDER_ONL, "Lavender_ONL" }, + {PLATFORM_TYPE_COTTONWOOD_RANGELEY, "Cottonwood_RANGELEY" }, + {PLATFORM_TYPE_MAPLE_GA, "Maple_GA" }, + {PLATFORM_TYPE_MAPLE_B, "Maple_B" }, + {PLATFORM_TYPE_GULMOHAR_GA, "Gulmohar_GA" }, + {PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA, "Gulmohar_2T_EVT1_GA" }, + {PLATFORM_TYPE_PEONY_SFP_GA, "Peony_SFP_GA" }, + {PLATFORM_TYPE_PEONY_COPPER_GA, "Peony_Copper_GA" }, + {PLATFORM_TYPE_PEONY_AUTO, "Peony_Auto_Detect" }, +}; + + +/* ========================================== + * Magnolia Layout configuration + * ========================================== + */ +#ifdef SWPS_MAGNOLIA +unsigned magnolia_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; + +struct inv_ioexp_layout_s magnolia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAGINOLIA_NAB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {1, IOEXP_TYPE_MAGINOLIA_NAB, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {2, IOEXP_TYPE_MAGINOLIA_NAB, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {3, IOEXP_TYPE_MAGINOLIA_4AB, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf0, 0xff}, {0xf0, 0xff}, }, }, /* addr[1] = I/O Expander 4 B */ + }, + {4, IOEXP_TYPE_MAGINOLIA_NAB, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {5, IOEXP_TYPE_MAGINOLIA_NAB, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {6, IOEXP_TYPE_MAGINOLIA_7AB, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[1] = I/O Expander 7 B */ + }, +}; + +struct inv_port_layout_s magnolia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 16} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 15} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 14} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 13} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 24} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 23} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 22} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 21} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 28} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 27} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 26} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 25} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 32} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 31} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 30} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 29} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 48} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 47} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 46} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 45} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 52} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 51} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 50} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 49} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 56} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 55} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 54} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 53} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 60} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 59} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 58} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 57} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 64} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 63} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 62} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 61} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 68} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 67} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 66} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 65} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 72} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 71} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 70} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 69} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 76} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 75} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 74} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 73} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD +unsigned redwood_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; + +struct inv_ioexp_layout_s redwood_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, +}; + +struct inv_port_layout_s redwood_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + { 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + { 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + { 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + { 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + {11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + {13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + {15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + {19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} }, + {29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} }, + {31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Hudson32i Layout configuration + * ========================================== + */ +#ifdef SWPS_HUDSON32I_GA +unsigned hudsin32iga_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; + +struct inv_ioexp_layout_s hudson32iga_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_HUDSON32IGA_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {1, IOEXP_TYPE_HUDSON32IGA_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {2, IOEXP_TYPE_HUDSON32IGA_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, + {3, IOEXP_TYPE_HUDSON32IGA_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, +}; + +struct inv_port_layout_s hudson32iga_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 1, 2, 3, 4} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 5, 6, 7, 8} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 9, 10, 11, 12} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 13, 14, 15, 16} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 17, 18, 19, 20} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 21, 22, 23, 24} }, + { 6, 12, 0, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 25, 26, 27, 28} }, + { 7, 13, 0, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 29, 30, 31, 32} }, + { 8, 14, 1, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 33, 34, 35, 36} }, + { 9, 15, 1, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 37, 38, 39, 40} }, + {10, 16, 1, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 41, 42, 43, 44} }, + {11, 17, 1, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 45, 46, 47, 48} }, + {12, 18, 1, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 49, 50, 51, 52} }, + {13, 19, 1, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 53, 54, 55, 56} }, + {14, 20, 1, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 57, 58, 59, 60} }, + {15, 21, 1, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 61, 62, 63, 64} }, + {16, 22, 2, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 65, 66, 67, 68} }, + {17, 23, 2, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 69, 70, 71, 72} }, + {18, 24, 2, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 73, 74, 75, 76} }, + {19, 25, 2, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + {20, 26, 2, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + {21, 27, 2, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 85, 86, 87, 88} }, + {22, 28, 2, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 89, 90, 91, 92} }, + {23, 29, 2, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 93, 94, 95, 96} }, + {24, 30, 3, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + {25, 31, 3, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + {26, 32, 3, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + {27, 33, 3, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, + {28, 34, 3, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {113,114,115,116} }, + {29, 35, 3, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {117,118,119,120} }, + {30, 36, 3, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {121,122,123,124} }, + {31, 37, 3, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Spruce Layout configuration + * ========================================== + */ +#ifdef SWPS_SPRUCE +unsigned spruce_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; + +struct inv_ioexp_layout_s spruce_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SPRUCE_7AB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[2] = I/O Expander 7B */ + }, +}; + +struct inv_port_layout_s spruce_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Up->Down]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA1 +unsigned cypress_ga1_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; + +struct inv_ioexp_layout_s cypress_ga1_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_ga1_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Down->Up]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA2 +unsigned cypress_ga2_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +struct inv_ioexp_layout_s cypress_ga2_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_ga2_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 1, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 2, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 3, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 4, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 5, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 6, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 7, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 8, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + { 9, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + {10, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {11, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {12, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {13, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {14, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {15, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {16, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {17, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {18, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {19, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {20, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {21, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {22, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {23, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {24, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {25, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {26, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {27, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {28, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {29, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {30, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {31, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {32, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {33, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {34, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {35, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {36, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {37, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {38, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {39, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {40, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {41, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {42, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {43, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {44, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {45, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {46, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {47, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {48, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {49, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {50, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {51, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {52, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {53, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (BaiDu version) + * ========================================== + */ +#ifdef SWPS_CYPRESS_BAI +unsigned cypress_b_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +struct inv_ioexp_layout_s cypress_b_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_b_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 2, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 4, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 6, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 8, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + {10, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {12, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {14, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {16, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {18, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {20, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {22, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {24, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {26, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {28, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {30, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {32, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {34, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {36, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {38, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {40, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {42, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {44, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {46, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {48, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {50, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {52, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {54, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood_fsl Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD_FSL +unsigned redwood_fsl_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; + +struct inv_ioexp_layout_s redwood_fsl_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, +}; + + +struct inv_port_layout_s redwood_fsl_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + { 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + { 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + { 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + { 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + {11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + {13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + {15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + {19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} }, + {29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} }, + {31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Tahoe Layout configuration + * ========================================== + */ +#ifdef SWPS_TAHOE +unsigned tahoe_gpio_rest_mux = MUX_RST_GPIO_249_PCA9548; + +struct inv_ioexp_layout_s tahoe_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_TAHOE_6ABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {1, IOEXP_TYPE_TAHOE_5A, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[0] = I/O Expander 5 A */ + }, +}; + + +struct inv_port_layout_s tahoe_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 12, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + { 1, 11, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + { 2, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + { 3, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + { 4, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + { 5, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + { 6, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + { 7, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + { 8, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + { 9, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, +}; +#endif + + +/* ========================================== + * Sequoia Layout configuration + * ========================================== + */ +#ifdef SWPS_SEQUOIA +unsigned sequoia_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; + +struct inv_ioexp_layout_s sequoia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { {1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + +struct inv_port_layout_s sequoia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 9, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 1, 10, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 2, 11, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 3, 12, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 4, 13, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + { 5, 14, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 6, 15, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + { 7, 16, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + { 8, 17, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + { 9, 18, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {10, 19, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {11, 20, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {12, 21, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + {13, 22, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + {14, 23, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121, 122, 123, 124} }, + {15, 24, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + {16, 25, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {137, 138, 139, 140} }, + {17, 26, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {129, 130, 131, 132} }, + {18, 27, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {153, 154, 155, 156} }, + {19, 28, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {145, 146, 147, 148} }, + {20, 29, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {169, 170, 171, 172} }, + {21, 30, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {161, 162, 163, 164} }, + {22, 31, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {185, 186, 187, 188} }, + {23, 32, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {177, 178, 179, 180} }, + {24, 33, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {201, 202, 203, 204} }, + {25, 34, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {193, 194, 195, 196} }, + {26, 35, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {217, 218, 219, 220} }, + {27, 36, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {209, 210, 211, 212} }, + {28, 37, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {233, 234, 235, 236} }, + {29, 38, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {225, 226, 227, 228} }, + {30, 39, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {249, 250, 251, 252} }, + {31, 40, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {241, 242, 243, 244} }, + {32, 44, 4, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + {33, 43, 4, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + {34, 42, 4, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + {35, 41, 4, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + {36, 48, 4, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {37, 47, 4, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {38, 46, 4, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {39, 45, 4, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {40, 52, 5, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {41, 51, 5, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {42, 50, 5, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {43, 49, 5, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {44, 56, 5, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, + {45, 55, 5, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + {46, 54, 5, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125, 126, 127, 128} }, + {47, 53, 5, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117, 118, 119, 120} }, + {48, 60, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {141, 142, 143, 144} }, + {49, 59, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {133, 134, 135, 136} }, + {50, 58, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {157, 158, 159, 160} }, + {51, 57, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {149, 150, 151, 152} }, + {52, 64, 6, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {173, 174, 175, 176} }, + {53, 63, 6, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {165, 166, 167, 168} }, + {54, 62, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {189, 190, 191, 192} }, + {55, 61, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {181, 182, 183, 184} }, + {56, 68, 7, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {205, 206, 207, 208} }, + {57, 67, 7, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {197, 198, 199, 200} }, + {58, 66, 7, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {221, 222, 223, 224} }, + {59, 65, 7, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {213, 214, 215, 216} }, + {60, 72, 7, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {237, 238, 239, 240} }, + {61, 71, 7, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {229, 230, 231, 232} }, + {62, 70, 7, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {253, 254, 255, 256} }, + {63, 69, 7, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {245, 246, 247, 248} }, +}; +#endif + + +/* ========================================== + * Lavender Layout configuration + * ========================================== + */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; +#endif + +#ifdef SWPS_LAVENDER +struct inv_ioexp_layout_s lavender_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { { 1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + { 1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { { 2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + { 2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + { 2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { { 3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + { 3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + { 3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { { 4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + { 4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + { 4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, + {8, IOEXP_TYPE_LAVENDER_P65, { { 5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xF6, 0xff}, {0xF8, 0xff}, }, }, /* addr[0] = I/O Expander CPU */ + }, +}; + + +struct inv_port_layout_s lavender_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {188, 189, 190, 191} }, + { 1, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {184, 185, 186, 187} }, + { 2, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {180, 181, 182, 183} }, + { 3, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {176, 177, 178, 179} }, + { 4, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {172, 173, 174, 175} }, + { 5, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {168, 169, 170, 171} }, + { 6, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {164, 165, 166, 167} }, + { 7, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {160, 161, 162, 163} }, + { 8, 25, 1, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {156, 157, 158, 159} }, + { 9, 26, 1, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {152, 153, 154, 155} }, + {10, 27, 1, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {148, 149, 150, 151} }, + {11, 28, 1, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {144, 145, 146, 147} }, + {12, 29, 1, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {140, 141, 142, 143} }, + {13, 30, 1, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {136, 137, 138, 139} }, + {14, 31, 1, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {132, 133, 134, 135} }, + {15, 32, 1, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {128, 129, 130, 131} }, + {16, 33, 2, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 0, 1, 2, 3} }, + {17, 34, 2, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 4, 5, 6, 7} }, + {18, 35, 2, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 8, 9, 10, 11} }, + {19, 36, 2, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 12, 13, 14, 15} }, + {20, 37, 2, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 16, 17, 18, 19} }, + {21, 38, 2, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 20, 21, 22, 23} }, + {22, 39, 2, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 24, 25, 26, 27} }, + {23, 40, 2, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 28, 29, 30, 31} }, + {24, 41, 3, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 32, 33, 34, 35} }, + {25, 42, 3, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 36, 37, 38, 39} }, + {26, 43, 3, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 40, 41, 42, 43} }, + {27, 44, 3, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 44, 45, 46, 47} }, + {28, 45, 3, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 48, 49, 50, 51} }, + {29, 46, 3, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 52, 53, 54, 55} }, + {30, 47, 3, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 56, 57, 58, 59} }, + {31, 48, 3, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 60, 61, 62, 63} }, + {32, 49, 4, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {256, 257, 258, 259} }, + {33, 50, 4, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {260, 261, 262, 263} }, + {34, 51, 4, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {264, 265, 266, 267} }, + {35, 52, 4, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {268, 269, 270, 271} }, + {36, 53, 4, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {272, 273, 274, 275} }, + {37, 54, 4, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {276, 277, 278, 279} }, + {38, 55, 4, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {280, 281, 282, 283} }, + {39, 56, 4, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {284, 285, 286, 287} }, + {40, 57, 5, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {288, 289, 290, 291} }, + {41, 58, 5, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {292, 293, 294, 295} }, + {42, 59, 5, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {296, 297, 298, 299} }, + {43, 60, 5, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {300, 301, 302, 303} }, + {44, 61, 5, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {304, 305, 306, 307} }, + {45, 62, 5, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {308, 309, 310, 311} }, + {46, 63, 5, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {312, 313, 314, 315} }, + {47, 64, 5, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {316, 317, 318, 319} }, + {48, 65, 6, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {444, 445, 446, 447} }, + {49, 66, 6, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {440, 441, 442, 443} }, + {50, 67, 6, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {436, 437, 438, 439} }, + {51, 68, 6, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {432, 433, 434, 435} }, + {52, 69, 6, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {428, 429, 430, 431} }, + {53, 70, 6, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {424, 425, 426, 427} }, + {54, 71, 6, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {420, 421, 422, 423} }, + {55, 72, 6, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {416, 417, 418, 419} }, + {56, 73, 7, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {412, 413, 414, 415} }, + {57, 74, 7, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {408, 409, 410, 411} }, + {58, 75, 7, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {404, 405, 406, 407} }, + {59, 76, 7, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {400, 401, 402, 403} }, + {60, 77, 7, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {396, 397, 398, 399} }, + {61, 78, 7, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {392, 393, 394, 395} }, + {62, 79, 7, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {388, 389, 390, 391} }, + {63, 80, 7, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {384, 385, 386, 387} }, + {64, 5, 8, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 64, 65, 66, 67} }, +}; +#endif + +/* =========================================================== + * Cottonwood Layout configuration Rangeley (Rangeley CPU board) + * =========================================================== + */ +#ifdef SWPS_COTTONWOOD_RANGELEY +unsigned cottonwood_rangeley_gpio_rest_mux = MUX_RST_GPIO_500_PCA9548; + +struct inv_ioexp_layout_s cottonwood_rangeley_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, CPLD_TYPE_COTTONWOOD,{ {1, 0x55, {22, 23, 24, 25}, {22, 23, 24, 25}, {-1, -1, -1, -1}, {0xee, 0xee, 0x99, 0x99}, {0x00, 0x00, 0x00, 0x00}, }, + }, + }, +}; + + +struct inv_port_layout_s cottonwood_rangeley_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHI_TYPE / LANE_ID */ + { 0, 2, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 75} }, + { 1, 3, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 77} }, + { 2, 4, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 79} }, + { 3, 5, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, +}; +#endif + +/* =========================================================== + * Maple Layout configuration (Old) + * =========================================================== + */ +#ifdef SWPS_MAPLE_GA +unsigned maple_ga_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; + +struct inv_ioexp_layout_s maple_ga_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAPLE_0ABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_MAPLE_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_MAPLE_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_MAPLE_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_MAPLE_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_MAPLE_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_MAPLE_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s maple_ga_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 1} }, + { 1, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 2} }, + { 2, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 3} }, + { 3, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 4} }, + { 4, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 5} }, + { 5, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 6} }, + { 6, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 7} }, + { 7, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 8} }, + { 8, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 13} }, + { 9, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 14} }, + {10, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 15} }, + {11, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 16} }, + {12, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 21} }, + {13, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 22} }, + {14, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 23} }, + {15, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 24} }, + {16, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 29} }, + {17, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 30} }, + {18, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 31} }, + {19, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 32} }, + {20, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 33} }, + {21, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 34} }, + {22, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 35} }, + {23, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 36} }, + {24, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 41} }, + {25, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 42} }, + {26, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 43} }, + {27, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 44} }, + {28, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 49} }, + {29, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 50} }, + {30, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 51} }, + {31, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 52} }, + {32, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 57} }, + {33, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 58} }, + {34, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 59} }, + {35, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 60} }, + {36, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 61} }, + {37, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 62} }, + {38, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 63} }, + {39, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 64} }, + {40, 58, 6, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 65} }, + {41, 59, 6, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 66} }, + {42, 60, 6, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 67} }, + {43, 61, 6, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 68} }, + {44, 62, 6, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 69} }, + {45, 63, 6, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 70} }, + {46, 64, 6, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 71} }, + {47, 65, 6, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 72} }, + {48, 10, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 77, 78, 79, 80} }, + {49, 11, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 85, 86, 87, 88} }, + {50, 12, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 93, 94, 95, 96} }, + {51, 13, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 97, 98, 99,100} }, + {52, 14, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {105,106,107,108} }, + {53, 15, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {113,114,115,116} }, + {54, 16, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {121,122,123,124} }, + {55, 17, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {125,126,127,128} }, +}; +#endif + +/* =========================================================== + * Maple Layout configuration (B version) + * =========================================================== + */ +#ifdef SWPS_MAPLE_B +unsigned maple_b_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; + +struct inv_ioexp_layout_s maple_b_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAPLE_0ABC, { { 6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + { 6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_MAPLE_NABC, { { 7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_MAPLE_NABC, { { 8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_MAPLE_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_MAPLE_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_MAPLE_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_MAPLE_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s maple_b_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 1, 23, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 2} }, + { 0, 22, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 1} }, + { 3, 25, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 4} }, + { 2, 24, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 3} }, + { 5, 27, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 6} }, + { 4, 26, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 5} }, + { 7, 29, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 8} }, + { 6, 28, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 7} }, + { 9, 31, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 14} }, + { 8, 30, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 13} }, + {11, 33, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 16} }, + {10, 32, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 15} }, + {13, 35, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 22} }, + {12, 34, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 21} }, + {15, 37, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 24} }, + {14, 36, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 23} }, + {17, 39, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 30} }, + {16, 38, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 29} }, + {19, 41, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 32} }, + {18, 40, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 31} }, + {21, 43, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 34} }, + {20, 42, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 33} }, + {23, 45, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 36} }, + {22, 44, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 35} }, + {25, 47, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 42} }, + {24, 46, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 41} }, + {27, 49, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 44} }, + {26, 48, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 43} }, + {29, 51, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 50} }, + {28, 50, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 49} }, + {31, 53, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 52} }, + {30, 52, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 51} }, + {33, 55, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 58} }, + {32, 54, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 57} }, + {35, 57, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 60} }, + {34, 56, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 59} }, + {37, 59, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 62} }, + {36, 58, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 61} }, + {39, 61, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 64} }, + {38, 60, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 63} }, + {41, 63, 6, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 66} }, + {40, 62, 6, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 65} }, + {43, 65, 6, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 68} }, + {42, 64, 6, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 67} }, + {45, 67, 6, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 70} }, + {44, 66, 6, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 69} }, + {47, 69, 6, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 72} }, + {46, 68, 6, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 71} }, + {49, 15, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 77, 78, 79, 80} }, + {48, 14, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 85, 86, 87, 88} }, + {51, 17, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 97, 98, 99,100} }, + {50, 16, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 93, 94, 95, 96} }, + {53, 19, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {105,106,107,108} }, + {52, 18, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {113,114,115,116} }, + {55, 21, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {125,126,127,128} }, + {54, 20, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {121,122,123,124} }, +}; +#endif + + +/* ========================================== + * Gulmohar Layout configuration + * ========================================== + */ +#ifdef SWPS_GULMOHAR +unsigned gulmohar_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; + +struct inv_ioexp_layout_s gulmohar_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_GULMOHAR_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_GULMOHAR_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_GULMOHAR_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_GULMOHAR_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_GULMOHAR_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_GULMOHAR_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_GULMOHAR_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + + +struct inv_port_layout_s gulmohar_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 1} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 2} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 3} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 4} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 5} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 6} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 7} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 8} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 9} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 10} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 11} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 12} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 21} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 22} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 23} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 24} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 33} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 34} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 35} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 36} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 37} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 38} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 39} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 40} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 41} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 42} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 43} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 44} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 49} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 50} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 51} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 52} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 53} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 54} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 55} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 56} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 65} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 66} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 67} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 68} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 69} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 70} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 71} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 72} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 81} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 82} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 83} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 84} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 97, 98, 99,100} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 85, 86, 87, 88} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {101,102,103,104} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {105,106,107,108} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {109,110,111,112} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Gulmohar_2T EVT1 Layout configuration + * ========================================== + */ +#ifdef SWPS_GULMOHAR_2T_EVT1 +unsigned gulmohar_2t_evt1_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; + +struct inv_ioexp_layout_s gulmohar_2t_evt1_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC,{ {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC,{ {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC,{ {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xd6, 0xda}, {0x18, 0xe3}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xd6, 0xda}, {0x18, 0xe3}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xd6, 0xff}, {0x18, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + + +struct inv_port_layout_s gulmohar_2t_evt1_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {48, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {49, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {50, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {51, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {52, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {53, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {54, 65, 6, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {55, 64, 6, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, +}; +#endif + + +/* =========================================================== + * Peony-SFP Layout configuration + * =========================================================== + */ +#ifdef SWPS_PEONY_SFP +unsigned peony_sfp_gpio_rest_mux = MUX_RST_CPLD_C0_A77_70_74_RST_ALL; + +struct inv_ioexp_layout_s peony_sfp_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_QSFP_6P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 0 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s peony_sfp_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 20, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 1} }, + { 1, 21, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 2} }, + { 2, 22, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 3} }, + { 3, 23, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 4} }, + { 4, 24, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 5} }, + { 5, 25, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 6} }, + { 6, 26, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 7} }, + { 7, 27, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 8} }, + { 8, 28, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 13} }, + { 9, 29, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 14} }, + {10, 30, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 15} }, + {11, 31, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 16} }, + {12, 32, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 21} }, + {13, 33, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 22} }, + {14, 34, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 23} }, + {15, 35, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 24} }, + {16, 36, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 29} }, + {17, 37, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 30} }, + {18, 38, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 31} }, + {19, 39, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 32} }, + {20, 40, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 33} }, + {21, 41, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 34} }, + {22, 42, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 35} }, + {23, 43, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 36} }, + {24, 44, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 65} }, + {25, 45, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 66} }, + {26, 46, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 67} }, + {27, 47, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 68} }, + {28, 48, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 69} }, + {29, 49, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 70} }, + {30, 50, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 71} }, + {31, 51, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 72} }, + {32, 52, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 97} }, + {33, 53, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 98} }, + {34, 54, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 99} }, + {35, 55, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {100} }, + {36, 56, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {105} }, + {37, 57, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {106} }, + {38, 58, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {107} }, + {39, 59, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {108} }, + {40, 60, 6, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {113} }, + {41, 61, 6, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {114} }, + {42, 62, 6, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {115} }, + {43, 63, 6, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {116} }, + {44, 64, 6, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {121} }, + {45, 65, 6, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {122} }, + {46, 66, 6, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {123} }, + {47, 67, 6, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {124} }, + {48, 12, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 49, 50, 51, 52} }, + {49, 13, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 57, 58, 59, 60} }, + {50, 14, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 61, 62, 63, 64} }, + {51, 15, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 77, 78, 79, 80} }, + {52, 16, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 85, 86, 87, 88} }, + {53, 17, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 93, 94, 95, 96} }, +}; +#endif + + +/* =========================================================== + * Peony-Copper Layout configuration + * =========================================================== + */ +#ifdef SWPS_PEONY_COPPER +unsigned peony_copper_gpio_rest_mux = MUX_RST_CPLD_C0_A77_70_74_RST_ALL; + +struct inv_ioexp_layout_s peony_copper_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_QSFP_6P_LAYOUT_1, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 0 A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, +}; + +struct inv_port_layout_s peony_copper_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + {48, 4, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 49, 50, 51, 52} }, + {49, 5, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 57, 58, 59, 60} }, + {50, 6, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 61, 62, 63, 64} }, + {51, 7, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 77, 78, 79, 80} }, + {52, 8, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 85, 86, 87, 88} }, + {53, 9, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 93, 94, 95, 96} }, +}; +#endif + + + +#endif /* INV_SWPS_H */ + + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.c new file mode 100644 index 000000000000..985bfbb45eb8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.c @@ -0,0 +1,2572 @@ +#include +#include +#include "io_expander.h" + +/* For build single module using (Ex: ONL platform) */ +#include +//#include + + +static struct ioexp_obj_s *ioexp_head_p = NULL; +static struct ioexp_obj_s *ioexp_tail_p = NULL; +extern int io_no_init; + +/* ========== Register IOEXP layout ========== + */ +struct ioexp_map_s ioexp_map_magnolia_nab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_magnolia_4ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_magnolia_7ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {1, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {1, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {1, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 2}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 3}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 0, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 0, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 0, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 0, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 0, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 0, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 0, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 1, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 1, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 1, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 1, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 1, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 1, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 1, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_cypress_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_cypress_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 1, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 1, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 1, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {0, 1, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {0, 1, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {1, 1, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {1, 1, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {1, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {1, 1, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_5a = { + + .chip_amount = 1, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_6abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 0}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 3}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 0}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + {2, 1, 5}, /* map_present[8] = MOD_ABS_PORT(X+8) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + {2, 1, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + {2, 1, 4}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+8) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + {2, 1, 2}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_sequoia_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_lavender_p65 = { + + .chip_amount = 1, + .data_width = 1, + + .map_present = { {0, 0, 4}, }, /* map_present[0] = MOD_ABS_PORT(X) */ + .map_reset = { {0, 0, 1}, }, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + .map_lpmod = { {0, 0, 2}, }, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + .map_modsel = { {0, 0, 0}, }, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ +}; + + +struct ioexp_map_s cpld_map_cottonwood = { + + .chip_amount = 1, + .data_width = 4, + + .map_present = { {0, 2, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 2, 4}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 3, 0}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 3, 4}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + }, + .map_tx_disable = { {0, 0, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 4}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 4}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + }, + .map_tx_fault = { {0, 2, 2}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 2, 6}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 3, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 3, 6}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + }, + .map_rxlos = { {0, 2, 1}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 2, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 3, 1}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 3, 5}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + }, + .map_hard_rs0 = { {0, 0, 2}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {0, 0, 6}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {0, 1, 2}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {0, 1, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + }, + .map_hard_rs1 = { {0, 0, 2}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {0, 0, 6}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {0, 1, 2}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {0, 1, 6}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + }, +}; + + +struct ioexp_map_s ioexp_map_maple_0abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_maple_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 4}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 5}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 4}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 5}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 2}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 3}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 2}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 3}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 1}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 1}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 6}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 6}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 2}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 6}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 6}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 2}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 6}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 2}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 6}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 1}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 5}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 1}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 5}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 1}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 5}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 1}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 5}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 4}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 4}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 4}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 4}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 3}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 3}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 3}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 3}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_1abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 2}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 6}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 6}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 4}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 5}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 1}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 5}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 1}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 5}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 2}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 3}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 4}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 4}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 1}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 3}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 3}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 6}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_3abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 4}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 5}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 2}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 6}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 2}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 6}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 2}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 3}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 1}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 5}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 1}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 5}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 1}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 4}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 4}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 6}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 3}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 3}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 4}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 1}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 6}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 4}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 1}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP_N_P(X+7) */ + }, +}; + + +/* PortType: SFP / 8 port + * Platform: Cypress, Peony_SFP + */ +struct ioexp_map_s ioexp_map_sfp_8p_layout_1 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +/* PortType: QSFP / 6 port + * Platform: Gulmohar, Peony_SFP, Peony_Copper + */ +struct ioexp_map_s ioexp_map_6p_qsfp_type_1 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +/* ========== Private functions ========== + */ +int check_channel_tier_1(void); + +struct i2c_client * +_get_i2c_client(struct ioexp_obj_s *self, + int chip_id){ + + struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p; + + if (!(i2c_curr_p)){ + SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__); + return NULL; + } + while (i2c_curr_p){ + if ((i2c_curr_p->chip_id) == chip_id){ + return i2c_curr_p->i2c_client_p; + } + i2c_curr_p = i2c_curr_p->next; + } + SWPS_ERR("%s: not exist! :%d\n", __func__, chip_id); + return NULL; +} + + +static int +_common_ioexp_update_one(struct ioexp_obj_s *self, + struct ioexp_addr_s *ioexp_addr, + int chip_id, + int data_width, + int show_err, + char *caller_name) { + int buf = 0; + int err = 0; + int data_id = 0; + int r_offset = 0; + + for(data_id=0; data_idread_offset[data_id]; + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset); + /* Check error */ + if (buf < 0) { + err = 1; + if (show_err) { + SWPS_INFO("IOEXP-%d read fail! :%d \n", self->ioexp_id, buf); + SWPS_INFO("Dump: :%d :0x%02x :%d, :%s\n", + ioexp_addr->chan_id, ioexp_addr->chip_addr, + ioexp_addr->read_offset[data_id], caller_name); + } + continue; + } + /* Update IOEXP object */ + self->chip_data[chip_id].data[data_id] = (uint8_t)buf; + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +common_ioexp_update_all(struct ioexp_obj_s *self, + int show_err, + char *caller_name){ + + int err = 0; + int chip_id = 0; + int chip_amount = self->ioexp_map_p->chip_amount; + + for (chip_id=0; chip_idioexp_map_p->map_addr[chip_id]), + chip_id, + self->ioexp_map_p->data_width, + show_err, + caller_name) < 0) { + err = 1; + } + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +_common_check_by_mode(struct ioexp_obj_s *self){ + + switch (self->mode){ + case IOEXP_MODE_DIRECT: + return self->fsm_4_direct(self); + + case IOEXP_MODE_POLLING: + if (self->state >= 0){ + return 0; + } + switch (self->state){ + case STATE_IOEXP_INIT: + return ERR_IOEXP_UNINIT; + case STATE_IOEXP_ABNORMAL: + return ERR_IOEXP_ABNORMAL; + default: + return ERR_IOEXP_NOSTATE; + } + break; + + default: + break; + } + SWPS_ERR("%s: Exception occurs. :%d \n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +static int +_common_get_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + char *func_mane){ + uint8_t buf; + int err_code; + + /* Check and get address */ + err_code = _common_check_by_mode(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Get data form cache */ + buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + return (int)(buf >> bitmap_obj_p->bit_shift & 0x01); +} + + +static int +_common_set_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + int input_val, + char *func_mane){ + int err_code, target_offset; + uint8_t origin_byte; + uint8_t modify_byte; + + /* Check and get address */ + err_code = _common_check_by_mode(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Prepare write date */ + origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + switch (input_val) { + case 0: + modify_byte = origin_byte; + SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift); + break; + case 1: + modify_byte = origin_byte; + SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift); + break; + default: + SWPS_ERR("Input value incorrect! :%d :%d :%s\n", + input_val, self->ioexp_id, func_mane); + return ERR_IOEXP_BADINPUT; + } + /* Setup i2c client */ + target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset]; + /* Write byte to chip via I2C */ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id), + target_offset, + modify_byte); + /* Update or bollback object */ + if (err_code < 0){ + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte; + SWPS_ERR("I2C write fail! :%d :%d :%s :%d\n", + input_val, self->ioexp_id, func_mane, err_code); + return err_code; + } + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte; + return 0; +} + + +/* ========== Object public functions ========== + */ +int +common_get_present(struct ioexp_obj_s *self, + int virt_offset){ + + int UNPLUG = 1; + int retval = ERR_IOEXP_UNEXCPT; + + retval = _common_get_bit(self, + &(self->ioexp_map_p->map_present[virt_offset]), + "common_get_present"); + if (retval < 0) { + /* [Note] + * => Transceiver object does not need to handle IOEXP layer issues. + */ + return UNPLUG; + } + return retval; +} + + +int +common_get_tx_fault(struct ioexp_obj_s *self, + int virt_offset){ + /* [Transmit Fault (Tx_Fault)] + * A catastrophic laser fault will activate the transmitter signal, + * TX_FAULT, and disable the laser. This signal is an open collector + * output (pull-up required on the host board). A low signal indicates + * normal laser operation and a high signal indicates a fault. The + * TX_FAULT will be latched high when a laser fault occurs and is + * cleared by toggling the TX_DISABLE input or power cycling the + * transceiver. The transmitter fault condition can also be monitored + * via the two-wire serial interface. + * (address A2, byte 110, bit 2). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_fault[virt_offset]), + "common_get_tx_fault"); +} + + +int +common_get_rxlos(struct ioexp_obj_s *self, + int virt_offset){ + /* [Receiver Loss of Signal (Rx_LOS)] + * The post-amplification IC also includes transition detection circuitry + * which monitors the ac level of incoming optical signals and provides a + * TTL/CMOS compatible status signal to the host (pin 8). An adequate optical + * input results in a low Rx_LOS output while a high Rx_LOS output indicates + * an unusable optical input. The Rx_LOS thresholds are factory set so that + * a high output indicates a definite optical fault has occurred. Rx_LOS can + * also be monitored via the two-wire serial interface + * (address A2h, byte 110, bit 1). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_rxlos[virt_offset]), + "common_get_rxlos"); +} + + +int +common_get_tx_disable(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + "common_get_tx_disable"); +} + + +int +common_get_reset(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + "common_get_reset"); +} + + +int +common_get_lpmod(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + "common_get_lpmod"); +} + + +int +common_get_modsel(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + "common_get_modsel"); +} + + +int +common_get_hard_rs0(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + "common_get_hard_rs0"); +} + + +int +common_get_hard_rs1(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + "common_get_hard_rs1"); +} + + +int +common_set_tx_disable(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + input_val, + "common_set_tx_disable"); +} + + +int +common_set_reset(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + input_val, + "common_set_reset"); +} + + +int +common_set_lpmod(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + input_val, + "common_set_lpmod"); +} + + +int +common_set_modsel(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + input_val, + "common_set_modsel"); +} + + +int +common_set_hard_rs0(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + input_val, + "common_set_hard_rs0"); +} + + +int +common_set_hard_rs1(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + input_val, + "common_set_hard_rs1"); +} + + +int +ioexp_get_not_support(struct ioexp_obj_s *self, + int virt_offset){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +ioexp_set_not_support(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +fake_ioexp_init(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_ioexp_update(struct ioexp_obj_s *self){ + return 1; +} + + +int +fake_update_func(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_get_func(struct ioexp_obj_s *self, + int virt_offset){ + SWPS_WARN("Someone called fake_get_func\n"); + return -1; +} + +int +fake_set_func(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + SWPS_WARN("Someone called fake_set_func\n"); + return -1; +} + + +/* ========== Initial functions for IO Expander ========== + */ +int +common_ioexp_init(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + if (self->mode == IOEXP_MODE_DIRECT) { + goto update_common_ioexp_init; + } + if (!io_no_init) { /*normal init*/ + + /* Setup default value to each physical IO Expander */ + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + /* Get address mapping */ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("%s: IOEXP config incorrect! :%d \n", + __func__, chip_id); + return -1; + } + /* Setup default value */ + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + /* [Desc] Skip the setup default value behavior + [Note] Setup default value = -1 if you don't want to write the value to IOEXP or CPLD + */ + if(addr_p->write_offset[offset] < 0){ + SWPS_DEBUG("skip a write_offset <%d>\n", addr_p->conf_offset[offset]); + continue; + } + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->write_offset[offset], + addr_p->data_default[offset]); + if (err_code < 0){ + SWPS_ERR("%s: set default fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + } + } + } +update_common_ioexp_init: + /* Check and update info to object */ + err_code = self->update_all(self, 1, "common_ioexp_init"); + if (err_code < 0) { + SWPS_ERR("%s: update_all() fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +/* ========== Object functions for Final State Machine ========== + */ +int +_is_channel_ready(struct ioexp_obj_s *self){ + + int chip_id = 0; + int byte_id = 0; + int getval = ERR_IOEXP_UNEXCPT; + int chkval = ERR_IOEXP_UNEXCPT; + char *emsg = "ERR"; + struct ioexp_addr_s *addr_p = NULL; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++) { + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + emsg = "IOEXP config incorrect"; + goto err_is_channel_ready; + } + for (byte_id=0; byte_id<(self->ioexp_map_p->data_width); byte_id++) { + if (addr_p->conf_offset[byte_id] < 0) { + continue; + } + if ((addr_p->conf_default[byte_id]) != 0) { + goto go_is_channel_ready; + } + } + if (chip_id == ((self->ioexp_map_p->chip_amount) - 1)) { + SWPS_DEBUG("%s: no non-zero config", __func__); + break; + } + } + chip_id = 0; + byte_id = 0; + +go_is_channel_ready: + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + chkval = addr_p->conf_default[byte_id]; + getval = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), + addr_p->conf_offset[byte_id]); + + SWPS_DEBUG("%s: target info :%d :%d :%d :%d :%d\n", + __func__, self->ioexp_id, chip_id, byte_id, chkval, getval); + + if ((getval >= 0) && (getval == chkval)) { + return 1; + } + return 0; + +err_is_channel_ready: + SWPS_ERR("%s: %s :%d :%d :%d :%d :%d\n", + __func__, emsg, self->ioexp_id, chip_id, byte_id, chkval, getval); + return ERR_IOEXP_UNEXCPT; +} + + +int +_ioexp_init_handler(struct ioexp_obj_s *self){ + + int return_val; + + switch (self->mode) { + case IOEXP_MODE_DIRECT: + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + + case IOEXP_MODE_POLLING: + /* Check system and channel is ready */ + if (self->state == STATE_IOEXP_INIT){ + if (!_is_channel_ready(self)){ + self->state = STATE_IOEXP_INIT; + SWPS_WARN("%s: IOEXP:%d channel not ready.\n", + __func__, self->ioexp_id); + return 0; + } + } + /* Execute initial callback */ + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + + default: + break; + } + SWPS_ERR("%s: exception occur :%d\n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){ + + int result_val; + int show_err = 1; + char *func_mane = "common_ioexp_fsm_4_direct"; + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, and return error */ + return ERR_IOEXP_UNINIT; + } + /* Case: Initial done */ + return 0; + + case STATE_IOEXP_NORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + SWPS_INFO("%s: NORMAL -> ABNORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + self->state = STATE_IOEXP_NORMAL; + return 0; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_DEBUG("%s: ABNORMAL -> NORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("%s: Exception occurs :%d\n", + __func__, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_polling(struct ioexp_obj_s *self){ + + int result_val, i, show_e; + int fail_retry = 3; + char *func_name = "common_ioexp_fsm_4_polling"; + +#ifdef DEBUG_SWPS + show_e = 1; +#else + show_e = 0; +#endif + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + /* Case: System (Channel) not ready */ + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, wait and retry */ + return 0; + } + /* Case: Initial done */ + SWPS_INFO("IOEXP-%d: initial done. :%d\n", + self->ioexp_id, self->ioexp_type); + return result_val; + + case STATE_IOEXP_NORMAL: + /* Retry mechanism for case of i2c topology not stable */ + for (i=0; iupdate_all(self, show_e, func_name); + if (result_val >= 0) { + self->state = STATE_IOEXP_NORMAL; + return 0; + } + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: detect I2C crash :%d\n", + __func__, self->ioexp_id); + break; + } + SWPS_DEBUG("IOEXP-%d: unstable :%d\n", + self->ioexp_id, result_val); + } + SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_e, func_name); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_INFO("IOEXP-%d: ABNORMAL -> NORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("IOEXP-%d: Exception occurs :%d\n", + self->ioexp_id, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +/* ========== Object private functions for check & update ========== + */ +int +common_ioexp_check(struct ioexp_obj_s *self){ + + int result; + + if (self->mode != IOEXP_MODE_POLLING){ + SWPS_ERR("%s: not polling mode :%d\n", + __func__, self->mode); + return ERR_IOEXP_NOTSUPPORT; + } + mutex_lock(&self->lock); + result = self->fsm_4_polling(self); + mutex_unlock(&self->lock); + return result; +} + + +/* ========== Functions for Factory pattern ========== + */ +static struct ioexp_map_s * +get_ioexp_map(int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + return &ioexp_map_magnolia_nab; + case IOEXP_TYPE_MAGINOLIA_4AB: + return &ioexp_map_magnolia_4ab; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + return &ioexp_map_magnolia_7ab; + case IOEXP_TYPE_REDWOOD_P01P08: + return &ioexp_map_redwood_p01p08_p17p24; + case IOEXP_TYPE_REDWOOD_P09P16: + return &ioexp_map_redwood_p09p16_p25p32; + case IOEXP_TYPE_HUDSON32IGA_P01P08: + return &ioexp_map_hudson32iga_p01p08_p17p24; + case IOEXP_TYPE_HUDSON32IGA_P09P16: + return &ioexp_map_hudson32iga_p09p16_p25p32; + case IOEXP_TYPE_CYPRESS_7ABC: + return &ioexp_map_cypress_7abc; + case IOEXP_TYPE_TAHOE_5A: + return &ioexp_map_tahoe_5a; + case IOEXP_TYPE_TAHOE_6ABC: + return &ioexp_map_tahoe_6abc; + case IOEXP_TYPE_SEQUOIA_NABC: + return &ioexp_map_sequoia_nabc; + case IOEXP_TYPE_LAVENDER_P65: + return &ioexp_map_lavender_p65; + case CPLD_TYPE_COTTONWOOD: + return &cpld_map_cottonwood; + case IOEXP_TYPE_MAPLE_0ABC: + return &ioexp_map_maple_0abc; + case IOEXP_TYPE_MAPLE_NABC: + return &ioexp_map_maple_nabc; + case IOEXP_TYPE_GULMOHAR_NABC: + return &ioexp_map_gulmohar_nabc; + case IOEXP_TYPE_GULMOHAR_7ABC: + return &ioexp_map_gulmohar_7abc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + return &ioexp_map_gulmohar_2t_evt1_nabc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + return &ioexp_map_gulmohar_2t_evt1_1abc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + return &ioexp_map_gulmohar_2t_evt1_3abc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + return &ioexp_map_gulmohar_2t_evt1_7abc; + case IOEXP_TYPE_SFP_8P_LAYOUT_1: + return &ioexp_map_sfp_8p_layout_1; + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: + return &ioexp_map_6p_qsfp_type_1; + default: + return NULL; + } +} + + +int +setup_ioexp_ssize_attr(struct ioexp_obj_s *self, + struct ioexp_map_s *ioexp_map_p, + int ioexp_id, + int ioexp_type, + int run_mode){ + switch (run_mode){ + case IOEXP_MODE_POLLING: /* Direct access device mode */ + case IOEXP_MODE_DIRECT: /* Polling mode, read from cache */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = ERR_IOEXP_UNEXCPT; + return ERR_IOEXP_UNEXCPT; + } + /* Setup mapping structure */ + self->ioexp_map_p = kzalloc(sizeof(*ioexp_map_p), GFP_KERNEL); + if (!(self->ioexp_map_p)) { + SWPS_ERR("%s: kzalloc ioexp_map_p fail\n", __func__); + return -1; + } + memcpy(self->ioexp_map_p, ioexp_map_p, sizeof(*ioexp_map_p)); + /* Setup attributes */ + self->ioexp_id = ioexp_id; + self->ioexp_type = ioexp_type; + self->state = STATE_IOEXP_INIT; + mutex_init(&self->lock); + return 0; +} + + +static int +setup_addr_mapping(struct ioexp_obj_s *self, + struct ioexp_addr_s *addr_map_p, + int chip_amount){ + struct ioexp_addr_s *tmp_p; + if (!addr_map_p){ + SWPS_ERR("%s: map is null\n", __func__); + return -1; + } + tmp_p = kzalloc((sizeof(*addr_map_p) * chip_amount), GFP_KERNEL); + if (!tmp_p){ + SWPS_ERR("%s: kzalloc fail.\n", __func__); + return -1; + } + memcpy(tmp_p, addr_map_p, (sizeof(*addr_map_p) * chip_amount)); + self->ioexp_map_p->map_addr = tmp_p; + + return 0; +} + + +static int +setup_ioexp_public_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case CPLD_TYPE_COTTONWOOD: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + + case IOEXP_TYPE_MAPLE_NABC: + case IOEXP_TYPE_GULMOHAR_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + case IOEXP_TYPE_SFP_8P_LAYOUT_1: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->get_hard_rs0 = common_get_hard_rs0; + self->get_hard_rs1 = common_get_hard_rs1; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + self->set_hard_rs0 = common_set_hard_rs0; + self->set_hard_rs1 = common_set_hard_rs1; + return 0; + + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case IOEXP_TYPE_MAPLE_0ABC: + case IOEXP_TYPE_GULMOHAR_7ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: + self->get_present = common_get_present; + self->get_tx_fault = ioexp_get_not_support; + self->get_rxlos = ioexp_get_not_support; + self->get_tx_disable = ioexp_get_not_support; + self->get_reset = common_get_reset; + self->get_lpmod = common_get_lpmod; + self->get_modsel = common_get_modsel; + self->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + self->set_tx_disable = ioexp_set_not_support; + self->set_reset = common_set_reset; + self->set_lpmod = common_set_lpmod; + self->set_modsel = common_set_modsel; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_ioexp_private_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case CPLD_TYPE_COTTONWOOD: + case IOEXP_TYPE_MAPLE_NABC: + case IOEXP_TYPE_MAPLE_0ABC: + case IOEXP_TYPE_GULMOHAR_NABC: + case IOEXP_TYPE_GULMOHAR_7ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + case IOEXP_TYPE_SFP_8P_LAYOUT_1: + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: + self->init = common_ioexp_init; + self->check = common_ioexp_check; + self->update_all = common_ioexp_update_all; + self->fsm_4_direct = common_ioexp_fsm_4_direct; + self->fsm_4_polling = common_ioexp_fsm_4_polling; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_i2c_client_one(struct ioexp_obj_s *self, + int chip_id){ + + char *err_msg = "ERROR"; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + struct ioexp_i2c_s *i2c_obj_p = NULL; + struct ioexp_i2c_s *i2c_curr_p = NULL; + + int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id; + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + err_msg = "Can not kzalloc client!"; + goto err_ioexp_setup_i2c_1; + } + i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL); + if (!i2c_obj_p){ + err_msg = "Can not kzalloc i2c_obj_p!"; + goto err_ioexp_setup_i2c_2; + } + adap = i2c_get_adapter(chan_id); + if(!adap){ + err_msg = "Can not get adap!"; + goto err_ioexp_setup_i2c_3; + } + client->adapter = adap; + client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr; + i2c_obj_p->i2c_client_p = client; + i2c_obj_p->chip_id = chip_id; + i2c_obj_p->next = NULL; + if (!self->i2c_head_p){ + self->i2c_head_p = i2c_obj_p; + } else { + i2c_curr_p = self->i2c_head_p; + while (i2c_curr_p->next){ + i2c_curr_p = i2c_curr_p->next; + } + i2c_curr_p->next = i2c_obj_p; + } + return 0; + +err_ioexp_setup_i2c_3: + kfree(i2c_obj_p); +err_ioexp_setup_i2c_2: + kfree(client); +err_ioexp_setup_i2c_1: + SWPS_ERR("%s: %s :%d\n", __func__, err_msg, chan_id); + return -1; +} + + +static int +setup_i2c_client(struct ioexp_obj_s* self){ + + int result; + int chip_id = 0; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + result = setup_i2c_client_one(self, chip_id); + if (result < 0){ + SWPS_ERR("%s fail! :%d\n", __func__, chip_id); + return -1; + } + } + return 0; +} + + +static int +setup_ioexp_config(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + if (io_no_init) { + + SWPS_INFO("io_no_init:%d \n", io_no_init); + return 0; + } + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("IOEXP config incorrect! :%d \n",chip_id); + return -1; + } + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + /* [Desc] Skip the setup config value behavior + [Note] Setup config value = -1 if you don't want to write the value to IOEXP or CPLD + */ + if(addr_p->conf_offset[offset] < 0){ + SWPS_DEBUG("skip a config_offset <%d>\n", addr_p->conf_offset[offset]); + continue; + } + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->conf_offset[offset], + addr_p->conf_default[offset]); + + if (err_code < 0){ + SWPS_INFO("%s: set conf fail! :%d \n", __func__, err_code); + return -2; + } + } + } + return 0; +} + + +struct ioexp_obj_s * +_create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_map_s* ioexp_map_p; + struct ioexp_obj_s* result_p; + struct ioexp_i2c_s *i2c_curr_p; + struct ioexp_i2c_s *i2c_next_p; + + /* Get layout */ + ioexp_map_p = get_ioexp_map(ioexp_type); + if (!ioexp_map_p){ + SWPS_ERR("%s: Invalid ioexp_type\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare IOEXP object */ + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + SWPS_ERR("%s: kzalloc failure!\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare static size attributes */ + if (setup_ioexp_ssize_attr(result_p, + ioexp_map_p, + ioexp_id, + ioexp_type, + run_mode) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + /* Prepare address mapping */ + if (setup_addr_mapping(result_p, addr_map_p, ioexp_map_p->chip_amount) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + if (setup_i2c_client(result_p) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + /* Prepare call back functions of object */ + if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + return result_p; + +err_create_ioexp_setup_i2c_fail: + i2c_curr_p = result_p->i2c_head_p; + i2c_next_p = result_p->i2c_head_p; + while (i2c_curr_p){ + i2c_next_p = i2c_curr_p->next; + if (i2c_curr_p->i2c_client_p) { + i2c_put_adapter(i2c_curr_p->i2c_client_p->adapter); + kfree(i2c_curr_p->i2c_client_p); + } + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } +err_create_ioexp_setup_attr_fail: + kfree(result_p); +err_create_ioexp_fail: + SWPS_ERR("%s: fail! :%d :%d \n", + __func__, ioexp_id, ioexp_type); + return NULL; +} + + +int +create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_obj_s *ioexp_p = NULL; + + ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type, + addr_map_p, run_mode); + if (!ioexp_p){ + return -1; + } + if (ioexp_head_p == NULL){ + ioexp_head_p = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; + } + ioexp_tail_p->next = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; +} +EXPORT_SYMBOL(create_ioexp_obj); + + +static int +_init_ioexp_obj(struct ioexp_obj_s* self) { + + char *err_msg = "ERR"; + char *func_name = "_init_ioexp_obj"; + + /* Setup IOEXP configure byte */ + if (setup_ioexp_config(self) < 0){ + err_msg = "setup_ioexp_config fail"; + goto err_init_ioexp_obj; + } + /* Setup default data */ + if (_ioexp_init_handler(self) < 0){ + err_msg = "_ioexp_init_handler fail"; + goto err_init_ioexp_obj; + } + /* Update all */ + if (self->state == STATE_IOEXP_NORMAL){ + if (self->update_all(self, 1, func_name) < 0){ + err_msg = "update_all() fail"; + goto err_init_ioexp_obj; + } + } + return 0; + +err_init_ioexp_obj: + SWPS_DEBUG("%s: %s\n", __func__, err_msg); + return -1; +} + + +int +init_ioexp_objs(void){ + /* Return value: + * 0: Success + * -1: Detect topology error + * -2: SWPS internal error + */ + struct ioexp_obj_s *curr_p = ioexp_head_p; + + if (!curr_p) { + SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__); + return -2; + } + while (curr_p) { + if (_init_ioexp_obj(curr_p) < 0) { + SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__); + return -1; + } + curr_p = curr_p->next; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} +EXPORT_SYMBOL(init_ioexp_objs); + + +void +clean_ioexp_objs(void){ + + struct ioexp_i2c_s *i2c_curr_p = NULL; + struct ioexp_i2c_s *i2c_next_p = NULL; + struct ioexp_obj_s *ioexp_next_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + if (ioexp_head_p == NULL){ + ioexp_tail_p = NULL; + return; + } + while(ioexp_curr_p){ + ioexp_next_p = ioexp_curr_p->next; + if (ioexp_curr_p->ioexp_map_p) { + if (ioexp_curr_p->ioexp_map_p->map_addr) { + kfree(ioexp_curr_p->ioexp_map_p->map_addr); + } + kfree(ioexp_curr_p->ioexp_map_p); + } + + i2c_curr_p = ioexp_curr_p->i2c_head_p; + while (i2c_curr_p) { + i2c_next_p = i2c_curr_p->next; + if (i2c_curr_p->i2c_client_p) { + i2c_put_adapter(i2c_curr_p->i2c_client_p->adapter); + kfree(i2c_curr_p->i2c_client_p); + } + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } + kfree(ioexp_curr_p); + ioexp_curr_p = ioexp_next_p; + } + ioexp_tail_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} +EXPORT_SYMBOL(clean_ioexp_objs); + + +int +check_ioexp_objs(void){ + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while (ioexp_curr_p){ + if ( (ioexp_curr_p->check(ioexp_curr_p)) < 0){ + SWPS_INFO("check IOEXP-%d fail! :%d\n", + ioexp_curr_p->ioexp_id, ioexp_curr_p->ioexp_type); + return -1; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} +EXPORT_SYMBOL(check_ioexp_objs); + + +struct ioexp_obj_s * +get_ioexp_obj(int ioexp_id){ + + struct ioexp_obj_s *result_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + if (ioexp_curr_p->ioexp_id == ioexp_id){ + result_p = ioexp_curr_p; + break; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return result_p; +} +EXPORT_SYMBOL(get_ioexp_obj); + + +void +unlock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_unlock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } +} +EXPORT_SYMBOL(unlock_ioexp_all); + +int +lock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_lock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} +EXPORT_SYMBOL(lock_ioexp_all); + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} +EXPORT_SYMBOL(check_channel_tier_1); + + +static int +_scan_channel_tier_1(int force, + int show_err) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + int ready = 0; + + if (!ioexp_curr_p) { + goto err_scan_tier_1_channel; + } + while(ioexp_curr_p) { + ready = _is_channel_ready(ioexp_curr_p); + if ((!ready) && (!force)) { + goto err_scan_tier_1_channel; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; + +err_scan_tier_1_channel: + if (show_err) { + if (ioexp_curr_p) { + SWPS_INFO("%s: IOEXP-%d fail\n", __func__, ioexp_curr_p->ioexp_id); + } else { + SWPS_INFO("%s: IOEXP is null.\n", __func__); + } + } + return -1; +} + + +static int +_scan_channel_tier_1_single(void) { + + int ret = 0; + int chan_id = 0; + int fake_cid = 0; + int fake_offs = 0; + int fake_addr = 0; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + + if (ioexp_head_p->ioexp_id != ioexp_tail_p->ioexp_id) { + return 0; + } + /* Setup i2c_client */ + chan_id = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chan_id; + fake_addr = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chip_addr; + adap = i2c_get_adapter((chan_id + 1)); + if(!adap){ + SWPS_INFO("%s: Can not get adap!\n", __func__); + return 0; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + SWPS_INFO("%s: Can not kzalloc client!\n", __func__); + return 0; + } + client->adapter = adap; + client->addr = fake_addr; + /* Fouce move ioexp ptr to next */ + ret = i2c_smbus_read_byte_data(client, fake_offs); + SWPS_DEBUG("%s: move ioexp_ptr done. :%d\n", __func__, ret); + kfree(client); + return 1; +} + + +int +resync_channel_tier_1(void) { + + char *emsg = "ERR"; + + if (!ioexp_head_p) { + emsg = "ioexp_head_p is NULL"; + goto err_resync_ioexp_status_1; + } + /* Run all */ + if (ioexp_head_p->ioexp_id == ioexp_tail_p->ioexp_id) { + _scan_channel_tier_1_single(); + } else { + _scan_channel_tier_1(1, 0); + } + /* Check all */ + if (_scan_channel_tier_1(0, 1) < 0) { + emsg = "resync tier-1 channel fail"; + goto err_resync_ioexp_status_1; + } + return 0; + +err_resync_ioexp_status_1: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} +EXPORT_SYMBOL(resync_channel_tier_1); + + +/* For build single module using (Ex: ONL platform) */ +MODULE_LICENSE("GPL"); + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.h new file mode 100644 index 000000000000..6f9f7b46291e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.h @@ -0,0 +1,189 @@ +#ifndef IO_EXPANDER_H +#define IO_EXPANDER_H + +#include + + +/* IOEXP type define (SFP series) */ +#define IOEXP_TYPE_MAGINOLIA_NAB (10101) +#define IOEXP_TYPE_MAGINOLIA_4AB (10102) +#define IOEXP_TYPE_MAPLE_NABC (10104) +#define IOEXP_TYPE_GULMOHAR_NABC (10105) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC (10106) +#define IOEXP_TYPE_SFP_8P_LAYOUT_1 (10107) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC (10108) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC (10109) + +/* IOEXP type define (QSFP series) */ +#define IOEXP_TYPE_MAGINOLIA_7AB (10201) +#define IOEXP_TYPE_REDWOOD_P01P08 (10202) +#define IOEXP_TYPE_REDWOOD_P09P16 (10203) +#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204) +#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205) +#define IOEXP_TYPE_SPRUCE_7AB (10206) +#define IOEXP_TYPE_CYPRESS_7ABC (10207) +#define IOEXP_TYPE_TAHOE_5A (10208) +#define IOEXP_TYPE_TAHOE_6ABC (10209) +#define IOEXP_TYPE_SEQUOIA_NABC (10210) +#define IOEXP_TYPE_LAVENDER_P65 (10211) +#define IOEXP_TYPE_MAPLE_0ABC (10212) +#define IOEXP_TYPE_GULMOHAR_7ABC (10213) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC (10214) +#define IOEXP_TYPE_QSFP_6P_LAYOUT_1 (10215) + +/* CPLD type define */ +#define CPLD_TYPE_COTTONWOOD (10301) + +/* IOEXP mode define */ +#define IOEXP_MODE_POLLING (19000) +#define IOEXP_MODE_DIRECT (19001) + +/* IOEXP state define */ +#define STATE_IOEXP_NORMAL (0) +#define STATE_IOEXP_INIT (-1) +#define STATE_IOEXP_ABNORMAL (-2) + +/* IOEXP error code define */ +#define ERR_IOEXP_NOTSUPPORT (-100) +#define ERR_IOEXP_UNINIT (-101) +#define ERR_IOEXP_BADCONF (-102) +#define ERR_IOEXP_ABNORMAL (-103) +#define ERR_IOEXP_NOSTATE (-104) +#define ERR_IOEXP_BADINPUT (-105) +#define ERR_IOEXP_UNEXCPT (-199) + +#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args) +#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args) +#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args) + +#ifdef DEBUG_SWPS +# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args) +#else +# define SWPS_DEBUG(fmt, args...) +#endif + + +struct ioexp_addr_s { + int chan_id; + int chip_addr; + int read_offset[8]; + int write_offset[8]; + int conf_offset[8]; + uint8_t data_default[8]; + uint8_t conf_default[8]; +}; + +struct ioexp_i2c_s { + int chip_id; + struct i2c_client *i2c_client_p; + struct ioexp_i2c_s *next; +}; + + +struct ioexp_bitmap_s { + int chip_id; /* IOEXP chip id */ + int ioexp_voffset; /* IOEXP virtual offset */ + int bit_shift; +}; + +struct ioexp_map_s { + int chip_amount; /* Number of chips that IOEXP object content */ + int data_width; /* Number of (Read/Write/Config) bytes */ + struct ioexp_addr_s *map_addr; /* Chip address info */ + struct ioexp_bitmap_s map_present[10]; /* IOEXP for SFP / QSFP */ + struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[10]; /* IOEXP for QSFP */ +}; + +struct ioexp_data_s { + uint8_t data[8]; +}; + +struct ioexp_obj_s { + + /* ============================ + * Object public property + * ============================ + */ + int ioexp_id; + int ioexp_type; + + /* ============================ + * Object private property + * ============================ + */ + struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */ + struct ioexp_map_s *ioexp_map_p; + struct ioexp_obj_s *next; + struct ioexp_i2c_s *i2c_head_p; + struct mutex lock; + int mode; + int state; + + /* =========================================== + * Object public functions + * =========================================== + */ + int (*get_present)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset); + int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset); + int (*get_reset)(struct ioexp_obj_s *self, int virt_offset); + int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset); + int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs1)(struct ioexp_obj_s *self, int virt_offset); + int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val); + + /* =========================================== + * Object private functions + * =========================================== + */ + int (*init)(struct ioexp_obj_s *self); + int (*check)(struct ioexp_obj_s *self); + int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name); + int (*fsm_4_direct)(struct ioexp_obj_s* self); + int (*fsm_4_polling)(struct ioexp_obj_s* self); +}; + + +struct ioexp_obj_s* get_ioexp_obj(int ioexp_id); +int create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode); +int init_ioexp_objs(void); +int check_ioexp_objs(void); +void clean_ioexp_objs(void); + +void unlock_ioexp_all(void); +int lock_ioexp_all(void); + +int check_channel_tier_1(void); +int resync_channel_tier_1(void); + +/* Macro for bit control */ +#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift))) +#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift))) + + +#endif /* IO_EXPANDER_H */ + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/lpc_ich.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/lpc_ich.c new file mode 100644 index 000000000000..66ff6e694d6f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/lpc_ich.c @@ -0,0 +1,1131 @@ +/* + * lpc_ich.c - LPC interface for Intel ICH + * + * LPC bridge function of the Intel ICH contains many other + * functional units, such as Interrupt controllers, Timers, + * Power Management, System Management, GPIO, RTC, and LPC + * Configuration Registers. + * + * This driver is derived from lpc_sch. + + * Copyright (c) 2011 Extreme Engineering Solution, Inc. + * Author: Aaron Sierra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This driver supports the following I/O Controller hubs: + * (See the intel documentation on http://developer.intel.com.) + * document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO) + * document number 290687-002, 298242-027: 82801BA (ICH2) + * document number 290733-003, 290739-013: 82801CA (ICH3-S) + * document number 290716-001, 290718-007: 82801CAM (ICH3-M) + * document number 290744-001, 290745-025: 82801DB (ICH4) + * document number 252337-001, 252663-008: 82801DBM (ICH4-M) + * document number 273599-001, 273645-002: 82801E (C-ICH) + * document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R) + * document number 300641-004, 300884-013: 6300ESB + * document number 301473-002, 301474-026: 82801F (ICH6) + * document number 313082-001, 313075-006: 631xESB, 632xESB + * document number 307013-003, 307014-024: 82801G (ICH7) + * document number 322896-001, 322897-001: NM10 + * document number 313056-003, 313057-017: 82801H (ICH8) + * document number 316972-004, 316973-012: 82801I (ICH9) + * document number 319973-002, 319974-002: 82801J (ICH10) + * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) + * document number 320066-003, 320257-008: EP80597 (IICH) + * document number 324645-001, 324646-001: Cougar Point (CPT) + * document number TBD : Patsburg (PBG) + * document number TBD : DH89xxCC + * document number TBD : Panther Point + * document number TBD : Lynx Point + * document number TBD : Lynx Point-LP + * document number TBD : Wellsburg + * document number TBD : Avoton SoC + * document number TBD : Coleto Creek + * document number TBD : Wildcat Point-LP + * document number TBD : 9 Series + * document number TBD : Lewisburg + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define ACPIBASE 0x40 +#define ACPIBASE_GPE_OFF 0x28 +#define ACPIBASE_GPE_END 0x2f +#define ACPIBASE_SMI_OFF 0x30 +#define ACPIBASE_SMI_END 0x33 +#define ACPIBASE_PMC_OFF 0x08 +#define ACPIBASE_PMC_END 0x0c +#define ACPIBASE_TCO_OFF 0x60 +#define ACPIBASE_TCO_END 0x7f +#define ACPICTRL_PMCBASE 0x44 + +#define ACPIBASE_GCS_OFF 0x3410 +#define ACPIBASE_GCS_END 0x3414 + +#define GPIOBASE_ICH0 0x58 +#define GPIOCTRL_ICH0 0x5C +#define GPIOBASE_ICH6 0x48 +#define GPIOCTRL_ICH6 0x4C + +#define RCBABASE 0xf0 + +#define wdt_io_res(i) wdt_res(0, i) +#define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i) +#define wdt_res(b, i) (&wdt_ich_res[(b) + (i)]) + +struct lpc_ich_priv { + int chipset; + + int abase; /* ACPI base */ + int actrl_pbase; /* ACPI control or PMC base */ + int gbase; /* GPIO base */ + int gctrl; /* GPIO control */ + + int abase_save; /* Cached ACPI base value */ + int actrl_pbase_save; /* Cached ACPI control or PMC base value */ + int gctrl_save; /* Cached GPIO control value */ +}; + +static struct resource wdt_ich_res[] = { + /* ACPI - TCO */ + { + .flags = IORESOURCE_IO, + }, + /* ACPI - SMI */ + { + .flags = IORESOURCE_IO, + }, + /* GCS or PMC */ + { + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource gpio_ich_res[] = { + /* GPIO */ + { + .flags = IORESOURCE_IO, + }, + /* ACPI - GPE0 */ + { + .flags = IORESOURCE_IO, + }, +}; + +static struct mfd_cell lpc_ich_wdt_cell = { + .name = "iTCO_wdt", + .num_resources = ARRAY_SIZE(wdt_ich_res), + .resources = wdt_ich_res, + .ignore_resource_conflicts = true, +}; + +static struct mfd_cell lpc_ich_gpio_cell = { + .name = "gpio_ich", + .num_resources = ARRAY_SIZE(gpio_ich_res), + .resources = gpio_ich_res, + .ignore_resource_conflicts = true, +}; + +/* chipset related info */ +enum lpc_chipsets { + LPC_ICH = 0, /* ICH */ + LPC_ICH0, /* ICH0 */ + LPC_ICH2, /* ICH2 */ + LPC_ICH2M, /* ICH2-M */ + LPC_ICH3, /* ICH3-S */ + LPC_ICH3M, /* ICH3-M */ + LPC_ICH4, /* ICH4 */ + LPC_ICH4M, /* ICH4-M */ + LPC_CICH, /* C-ICH */ + LPC_ICH5, /* ICH5 & ICH5R */ + LPC_6300ESB, /* 6300ESB */ + LPC_ICH6, /* ICH6 & ICH6R */ + LPC_ICH6M, /* ICH6-M */ + LPC_ICH6W, /* ICH6W & ICH6RW */ + LPC_631XESB, /* 631xESB/632xESB */ + LPC_ICH7, /* ICH7 & ICH7R */ + LPC_ICH7DH, /* ICH7DH */ + LPC_ICH7M, /* ICH7-M & ICH7-U */ + LPC_ICH7MDH, /* ICH7-M DH */ + LPC_NM10, /* NM10 */ + LPC_ICH8, /* ICH8 & ICH8R */ + LPC_ICH8DH, /* ICH8DH */ + LPC_ICH8DO, /* ICH8DO */ + LPC_ICH8M, /* ICH8M */ + LPC_ICH8ME, /* ICH8M-E */ + LPC_ICH9, /* ICH9 */ + LPC_ICH9R, /* ICH9R */ + LPC_ICH9DH, /* ICH9DH */ + LPC_ICH9DO, /* ICH9DO */ + LPC_ICH9M, /* ICH9M */ + LPC_ICH9ME, /* ICH9M-E */ + LPC_ICH10, /* ICH10 */ + LPC_ICH10R, /* ICH10R */ + LPC_ICH10D, /* ICH10D */ + LPC_ICH10DO, /* ICH10DO */ + LPC_PCH, /* PCH Desktop Full Featured */ + LPC_PCHM, /* PCH Mobile Full Featured */ + LPC_P55, /* P55 */ + LPC_PM55, /* PM55 */ + LPC_H55, /* H55 */ + LPC_QM57, /* QM57 */ + LPC_H57, /* H57 */ + LPC_HM55, /* HM55 */ + LPC_Q57, /* Q57 */ + LPC_HM57, /* HM57 */ + LPC_PCHMSFF, /* PCH Mobile SFF Full Featured */ + LPC_QS57, /* QS57 */ + LPC_3400, /* 3400 */ + LPC_3420, /* 3420 */ + LPC_3450, /* 3450 */ + LPC_EP80579, /* EP80579 */ + LPC_CPT, /* Cougar Point */ + LPC_CPTD, /* Cougar Point Desktop */ + LPC_CPTM, /* Cougar Point Mobile */ + LPC_PBG, /* Patsburg */ + LPC_DH89XXCC, /* DH89xxCC */ + LPC_PPT, /* Panther Point */ + LPC_LPT, /* Lynx Point */ + LPC_LPT_LP, /* Lynx Point-LP */ + LPC_WBG, /* Wellsburg */ + LPC_AVN, /* Avoton SoC */ + LPC_BAYTRAIL, /* Bay Trail SoC */ + LPC_COLETO, /* Coleto Creek */ + LPC_WPT_LP, /* Wildcat Point-LP */ + LPC_BRASWELL, /* Braswell SoC */ + LPC_LEWISBURG, /* Lewisburg */ + LPC_9S, /* 9 Series */ +}; + +static struct lpc_ich_info lpc_chipset_info[] = { + [LPC_ICH] = { + .name = "ICH", + .iTCO_version = 1, + }, + [LPC_ICH0] = { + .name = "ICH0", + .iTCO_version = 1, + }, + [LPC_ICH2] = { + .name = "ICH2", + .iTCO_version = 1, + }, + [LPC_ICH2M] = { + .name = "ICH2-M", + .iTCO_version = 1, + }, + [LPC_ICH3] = { + .name = "ICH3-S", + .iTCO_version = 1, + }, + [LPC_ICH3M] = { + .name = "ICH3-M", + .iTCO_version = 1, + }, + [LPC_ICH4] = { + .name = "ICH4", + .iTCO_version = 1, + }, + [LPC_ICH4M] = { + .name = "ICH4-M", + .iTCO_version = 1, + }, + [LPC_CICH] = { + .name = "C-ICH", + .iTCO_version = 1, + }, + [LPC_ICH5] = { + .name = "ICH5 or ICH5R", + .iTCO_version = 1, + }, + [LPC_6300ESB] = { + .name = "6300ESB", + .iTCO_version = 1, + }, + [LPC_ICH6] = { + .name = "ICH6 or ICH6R", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_ICH6M] = { + .name = "ICH6-M", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_ICH6W] = { + .name = "ICH6W or ICH6RW", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_631XESB] = { + .name = "631xESB/632xESB", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_ICH7] = { + .name = "ICH7 or ICH7R", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH7DH] = { + .name = "ICH7DH", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH7M] = { + .name = "ICH7-M or ICH7-U", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH7MDH] = { + .name = "ICH7-M DH", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_NM10] = { + .name = "NM10", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8] = { + .name = "ICH8 or ICH8R", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8DH] = { + .name = "ICH8DH", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8DO] = { + .name = "ICH8DO", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8M] = { + .name = "ICH8M", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8ME] = { + .name = "ICH8M-E", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH9] = { + .name = "ICH9", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9R] = { + .name = "ICH9R", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9DH] = { + .name = "ICH9DH", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9DO] = { + .name = "ICH9DO", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9M] = { + .name = "ICH9M", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9ME] = { + .name = "ICH9M-E", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH10] = { + .name = "ICH10", + .iTCO_version = 2, + .gpio_version = ICH_V10CONS_GPIO, + }, + [LPC_ICH10R] = { + .name = "ICH10R", + .iTCO_version = 2, + .gpio_version = ICH_V10CONS_GPIO, + }, + [LPC_ICH10D] = { + .name = "ICH10D", + .iTCO_version = 2, + .gpio_version = ICH_V10CORP_GPIO, + }, + [LPC_ICH10DO] = { + .name = "ICH10DO", + .iTCO_version = 2, + .gpio_version = ICH_V10CORP_GPIO, + }, + [LPC_PCH] = { + .name = "PCH Desktop Full Featured", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PCHM] = { + .name = "PCH Mobile Full Featured", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_P55] = { + .name = "P55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PM55] = { + .name = "PM55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_H55] = { + .name = "H55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_QM57] = { + .name = "QM57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_H57] = { + .name = "H57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_HM55] = { + .name = "HM55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_Q57] = { + .name = "Q57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_HM57] = { + .name = "HM57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PCHMSFF] = { + .name = "PCH Mobile SFF Full Featured", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_QS57] = { + .name = "QS57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_3400] = { + .name = "3400", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_3420] = { + .name = "3420", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_3450] = { + .name = "3450", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_EP80579] = { + .name = "EP80579", + .iTCO_version = 2, + }, + [LPC_CPT] = { + .name = "Cougar Point", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_CPTD] = { + .name = "Cougar Point Desktop", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_CPTM] = { + .name = "Cougar Point Mobile", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PBG] = { + .name = "Patsburg", + .iTCO_version = 2, + }, + [LPC_DH89XXCC] = { + .name = "DH89xxCC", + .iTCO_version = 2, + }, + [LPC_PPT] = { + .name = "Panther Point", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_LPT] = { + .name = "Lynx Point", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_LPT_LP] = { + .name = "Lynx Point_LP", + .iTCO_version = 2, + }, + [LPC_WBG] = { + .name = "Wellsburg", + .iTCO_version = 2, + }, + [LPC_AVN] = { + .name = "Avoton SoC", + .iTCO_version = 3, + .gpio_version = AVOTON_GPIO, + }, + [LPC_BAYTRAIL] = { + .name = "Bay Trail SoC", + .iTCO_version = 3, + }, + [LPC_COLETO] = { + .name = "Coleto Creek", + .iTCO_version = 2, + }, + [LPC_WPT_LP] = { + .name = "Wildcat Point_LP", + .iTCO_version = 2, + }, + [LPC_BRASWELL] = { + .name = "Braswell SoC", + .iTCO_version = 3, + }, + [LPC_LEWISBURG] = { + .name = "Lewisburg", + .iTCO_version = 2, + }, + [LPC_9S] = { + .name = "9 Series", + .iTCO_version = 2, + }, +}; + +/* + * This data only exists for exporting the supported PCI ids + * via MODULE_DEVICE_TABLE. We do not actually register a + * pci_driver, because the I/O Controller Hub has also other + * functions that probably will be registered by other drivers. + */ +static const struct pci_device_id lpc_ich_ids[] = { + { PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL}, + { PCI_VDEVICE(INTEL, 0x1c41), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c42), LPC_CPTD}, + { PCI_VDEVICE(INTEL, 0x1c43), LPC_CPTM}, + { PCI_VDEVICE(INTEL, 0x1c44), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c45), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c46), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c47), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c48), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c49), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4a), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4b), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4c), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4d), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4e), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4f), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c50), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c51), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c52), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c53), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c54), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c55), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c56), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c57), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c58), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c59), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5a), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5b), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5c), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5d), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5e), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5f), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1d40), LPC_PBG}, + { PCI_VDEVICE(INTEL, 0x1d41), LPC_PBG}, + { PCI_VDEVICE(INTEL, 0x1e40), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e41), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e42), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e43), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e44), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e45), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e46), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e47), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e48), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e49), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4a), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4b), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4c), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4d), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4e), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4f), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e50), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e51), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e52), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e53), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e54), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e55), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e56), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e57), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e58), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e59), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5a), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5b), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5c), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5d), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5e), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5f), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x229c), LPC_BRASWELL}, + { PCI_VDEVICE(INTEL, 0x2310), LPC_DH89XXCC}, + { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO}, + { PCI_VDEVICE(INTEL, 0x2410), LPC_ICH}, + { PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0}, + { PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2}, + { PCI_VDEVICE(INTEL, 0x244c), LPC_ICH2M}, + { PCI_VDEVICE(INTEL, 0x2450), LPC_CICH}, + { PCI_VDEVICE(INTEL, 0x2480), LPC_ICH3}, + { PCI_VDEVICE(INTEL, 0x248c), LPC_ICH3M}, + { PCI_VDEVICE(INTEL, 0x24c0), LPC_ICH4}, + { PCI_VDEVICE(INTEL, 0x24cc), LPC_ICH4M}, + { PCI_VDEVICE(INTEL, 0x24d0), LPC_ICH5}, + { PCI_VDEVICE(INTEL, 0x25a1), LPC_6300ESB}, + { PCI_VDEVICE(INTEL, 0x2640), LPC_ICH6}, + { PCI_VDEVICE(INTEL, 0x2641), LPC_ICH6M}, + { PCI_VDEVICE(INTEL, 0x2642), LPC_ICH6W}, + { PCI_VDEVICE(INTEL, 0x2670), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2671), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2672), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2673), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2674), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2675), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2676), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2677), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2678), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2679), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267a), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267b), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267c), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267d), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267e), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267f), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x27b0), LPC_ICH7DH}, + { PCI_VDEVICE(INTEL, 0x27b8), LPC_ICH7}, + { PCI_VDEVICE(INTEL, 0x27b9), LPC_ICH7M}, + { PCI_VDEVICE(INTEL, 0x27bc), LPC_NM10}, + { PCI_VDEVICE(INTEL, 0x27bd), LPC_ICH7MDH}, + { PCI_VDEVICE(INTEL, 0x2810), LPC_ICH8}, + { PCI_VDEVICE(INTEL, 0x2811), LPC_ICH8ME}, + { PCI_VDEVICE(INTEL, 0x2812), LPC_ICH8DH}, + { PCI_VDEVICE(INTEL, 0x2814), LPC_ICH8DO}, + { PCI_VDEVICE(INTEL, 0x2815), LPC_ICH8M}, + { PCI_VDEVICE(INTEL, 0x2912), LPC_ICH9DH}, + { PCI_VDEVICE(INTEL, 0x2914), LPC_ICH9DO}, + { PCI_VDEVICE(INTEL, 0x2916), LPC_ICH9R}, + { PCI_VDEVICE(INTEL, 0x2917), LPC_ICH9ME}, + { PCI_VDEVICE(INTEL, 0x2918), LPC_ICH9}, + { PCI_VDEVICE(INTEL, 0x2919), LPC_ICH9M}, + { PCI_VDEVICE(INTEL, 0x3a14), LPC_ICH10DO}, + { PCI_VDEVICE(INTEL, 0x3a16), LPC_ICH10R}, + { PCI_VDEVICE(INTEL, 0x3a18), LPC_ICH10}, + { PCI_VDEVICE(INTEL, 0x3a1a), LPC_ICH10D}, + { PCI_VDEVICE(INTEL, 0x3b00), LPC_PCH}, + { PCI_VDEVICE(INTEL, 0x3b01), LPC_PCHM}, + { PCI_VDEVICE(INTEL, 0x3b02), LPC_P55}, + { PCI_VDEVICE(INTEL, 0x3b03), LPC_PM55}, + { PCI_VDEVICE(INTEL, 0x3b06), LPC_H55}, + { PCI_VDEVICE(INTEL, 0x3b07), LPC_QM57}, + { PCI_VDEVICE(INTEL, 0x3b08), LPC_H57}, + { PCI_VDEVICE(INTEL, 0x3b09), LPC_HM55}, + { PCI_VDEVICE(INTEL, 0x3b0a), LPC_Q57}, + { PCI_VDEVICE(INTEL, 0x3b0b), LPC_HM57}, + { PCI_VDEVICE(INTEL, 0x3b0d), LPC_PCHMSFF}, + { PCI_VDEVICE(INTEL, 0x3b0f), LPC_QS57}, + { PCI_VDEVICE(INTEL, 0x3b12), LPC_3400}, + { PCI_VDEVICE(INTEL, 0x3b14), LPC_3420}, + { PCI_VDEVICE(INTEL, 0x3b16), LPC_3450}, + { PCI_VDEVICE(INTEL, 0x5031), LPC_EP80579}, + { PCI_VDEVICE(INTEL, 0x8c40), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c41), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c42), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c43), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c44), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c45), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c46), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c47), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c48), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c49), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4a), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4b), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4c), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4d), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4e), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4f), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c50), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c51), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c52), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c53), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c54), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c55), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c56), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c57), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c58), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c59), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5a), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5b), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5c), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5d), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5e), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5f), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8cc1), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc2), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc3), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc4), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc6), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8d40), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d41), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d42), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d43), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d44), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d45), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d46), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d47), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d48), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d49), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4a), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4b), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4c), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4d), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4e), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4f), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d50), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d51), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d52), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d53), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d54), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d55), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d56), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d57), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d58), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d59), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5a), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5b), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5c), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x9c40), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c41), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c42), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c43), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c44), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc1), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc2), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc3), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc5), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc6), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc7), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc9), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0xa1c1), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c2), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c3), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c4), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c5), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c6), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c7), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa242), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa243), LPC_LEWISBURG}, + { 0, }, /* End of list */ +}; +MODULE_DEVICE_TABLE(pci, lpc_ich_ids); + +static void lpc_ich_restore_config_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + + if (priv->abase_save >= 0) { + pci_write_config_byte(dev, priv->abase, priv->abase_save); + priv->abase_save = -1; + } + + if (priv->actrl_pbase_save >= 0) { + pci_write_config_byte(dev, priv->actrl_pbase, + priv->actrl_pbase_save); + priv->actrl_pbase_save = -1; + } + + if (priv->gctrl_save >= 0) { + pci_write_config_byte(dev, priv->gctrl, priv->gctrl_save); + priv->gctrl_save = -1; + } +} + +static void lpc_ich_enable_acpi_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u8 reg_save; + + switch (lpc_chipset_info[priv->chipset].iTCO_version) { + case 3: + /* + * Some chipsets (eg Avoton) enable the ACPI space in the + * ACPI BASE register. + */ + pci_read_config_byte(dev, priv->abase, ®_save); + pci_write_config_byte(dev, priv->abase, reg_save | 0x2); + priv->abase_save = reg_save; + break; + default: + /* + * Most chipsets enable the ACPI space in the ACPI control + * register. + */ + pci_read_config_byte(dev, priv->actrl_pbase, ®_save); + pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x80); + priv->actrl_pbase_save = reg_save; + break; + } +} + +static void lpc_ich_enable_gpio_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u8 reg_save; + + pci_read_config_byte(dev, priv->gctrl, ®_save); + pci_write_config_byte(dev, priv->gctrl, reg_save | 0x10); + priv->gctrl_save = reg_save; +} + +static void lpc_ich_enable_pmc_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u8 reg_save; + + pci_read_config_byte(dev, priv->actrl_pbase, ®_save); + pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x2); + + priv->actrl_pbase_save = reg_save; +} + +static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev) +{ + struct itco_wdt_platform_data *pdata; + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + struct lpc_ich_info *info; + struct mfd_cell *cell = &lpc_ich_wdt_cell; + + pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + info = &lpc_chipset_info[priv->chipset]; + + pdata->version = info->iTCO_version; + strlcpy(pdata->name, info->name, sizeof(pdata->name)); + + cell->platform_data = pdata; + cell->pdata_size = sizeof(*pdata); + return 0; +} + +static void lpc_ich_finalize_gpio_cell(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + struct mfd_cell *cell = &lpc_ich_gpio_cell; + + cell->platform_data = &lpc_chipset_info[priv->chipset]; + cell->pdata_size = sizeof(struct lpc_ich_info); +} + +/* + * We don't check for resource conflict globally. There are 2 or 3 independent + * GPIO groups and it's enough to have access to one of these to instantiate + * the device. + */ +static int lpc_ich_check_conflict_gpio(struct resource *res) +{ + int ret; + u8 use_gpio = 0; + + if (resource_size(res) >= 0x50 && + !acpi_check_region(res->start + 0x40, 0x10, "LPC ICH GPIO3")) + use_gpio |= 1 << 2; + + if (!acpi_check_region(res->start + 0x30, 0x10, "LPC ICH GPIO2")) + use_gpio |= 1 << 1; + + ret = acpi_check_region(res->start + 0x00, 0x30, "LPC ICH GPIO1"); + if (!ret) + use_gpio |= 1 << 0; + + return use_gpio ? use_gpio : ret; +} + +static int lpc_ich_init_gpio(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u32 base_addr_cfg; + u32 base_addr; + int ret; + bool acpi_conflict = false; + struct resource *res; + + /* Setup power management base register */ + pci_read_config_dword(dev, priv->abase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); + lpc_ich_gpio_cell.num_resources--; + goto gpe0_done; + } + + res = &gpio_ich_res[ICH_RES_GPE0]; + res->start = base_addr + ACPIBASE_GPE_OFF; + res->end = base_addr + ACPIBASE_GPE_END; + ret = acpi_check_resource_conflict(res); + if (ret) { + /* + * This isn't fatal for the GPIO, but we have to make sure that + * the platform_device subsystem doesn't see this resource + * or it will register an invalid region. + */ + lpc_ich_gpio_cell.num_resources--; + acpi_conflict = true; + } else { + lpc_ich_enable_acpi_space(dev); + } + +gpe0_done: + /* Setup GPIO base register */ + pci_read_config_dword(dev, priv->gbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n"); + ret = -ENODEV; + goto gpio_done; + } + + /* Older devices provide fewer GPIO and have a smaller resource size. */ + res = &gpio_ich_res[ICH_RES_GPIO]; + res->start = base_addr; + switch (lpc_chipset_info[priv->chipset].gpio_version) { + case ICH_V5_GPIO: + case ICH_V10CORP_GPIO: + res->end = res->start + 128 - 1; + break; + default: + res->end = res->start + 64 - 1; + break; + } + + ret = lpc_ich_check_conflict_gpio(res); + if (ret < 0) { + /* this isn't necessarily fatal for the GPIO */ + acpi_conflict = true; + goto gpio_done; + } + lpc_chipset_info[priv->chipset].use_gpio = ret; + lpc_ich_enable_gpio_space(dev); + + lpc_ich_finalize_gpio_cell(dev); + ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, + &lpc_ich_gpio_cell, 1, NULL, 0, NULL); + +gpio_done: + if (acpi_conflict) + pr_warn("Resource conflict(s) found affecting %s\n", + lpc_ich_gpio_cell.name); + return ret; +} + +static int lpc_ich_init_wdt(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u32 base_addr_cfg; + u32 base_addr; + int ret; + struct resource *res; + + /* If we have ACPI based watchdog use that instead */ + if (acpi_has_watchdog()) + return -ENODEV; + + /* Setup power management base register */ + pci_read_config_dword(dev, priv->abase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); + ret = -ENODEV; + goto wdt_done; + } + + res = wdt_io_res(ICH_RES_IO_TCO); + res->start = base_addr + ACPIBASE_TCO_OFF; + res->end = base_addr + ACPIBASE_TCO_END; + + res = wdt_io_res(ICH_RES_IO_SMI); + res->start = base_addr + ACPIBASE_SMI_OFF; + res->end = base_addr + ACPIBASE_SMI_END; + + lpc_ich_enable_acpi_space(dev); + + /* + * iTCO v2: + * Get the Memory-Mapped GCS register. To get access to it + * we have to read RCBA from PCI Config space 0xf0 and use + * it as base. GCS = RCBA + ICH6_GCS(0x3410). + * + * iTCO v3: + * Get the Power Management Configuration register. To get access + * to it we have to read the PMC BASE from config space and address + * the register at offset 0x8. + */ + if (lpc_chipset_info[priv->chipset].iTCO_version == 1) { + /* Don't register iomem for TCO ver 1 */ + lpc_ich_wdt_cell.num_resources--; + } else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) { + pci_read_config_dword(dev, RCBABASE, &base_addr_cfg); + base_addr = base_addr_cfg & 0xffffc000; + if (!(base_addr_cfg & 1)) { + dev_notice(&dev->dev, "RCBA is disabled by " + "hardware/BIOS, device disabled\n"); + ret = -ENODEV; + goto wdt_done; + } + res = wdt_mem_res(ICH_RES_MEM_GCS_PMC); + res->start = base_addr + ACPIBASE_GCS_OFF; + res->end = base_addr + ACPIBASE_GCS_END; + } else if (lpc_chipset_info[priv->chipset].iTCO_version == 3) { + lpc_ich_enable_pmc_space(dev); + pci_read_config_dword(dev, ACPICTRL_PMCBASE, &base_addr_cfg); + base_addr = base_addr_cfg & 0xfffffe00; + + res = wdt_mem_res(ICH_RES_MEM_GCS_PMC); + res->start = base_addr + ACPIBASE_PMC_OFF; + res->end = base_addr + ACPIBASE_PMC_END; + } + + ret = lpc_ich_finalize_wdt_cell(dev); + if (ret) + goto wdt_done; + + ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, + &lpc_ich_wdt_cell, 1, NULL, 0, NULL); + +wdt_done: + return ret; +} + +static int lpc_ich_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + struct lpc_ich_priv *priv; + int ret; + bool cell_added = false; + + priv = devm_kzalloc(&dev->dev, + sizeof(struct lpc_ich_priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->chipset = id->driver_data; + + priv->actrl_pbase_save = -1; + priv->abase_save = -1; + + priv->abase = ACPIBASE; + priv->actrl_pbase = ACPICTRL_PMCBASE; + + priv->gctrl_save = -1; + if (priv->chipset <= LPC_ICH5) { + priv->gbase = GPIOBASE_ICH0; + priv->gctrl = GPIOCTRL_ICH0; + } else { + priv->gbase = GPIOBASE_ICH6; + priv->gctrl = GPIOCTRL_ICH6; + } + + pci_set_drvdata(dev, priv); + + if (lpc_chipset_info[priv->chipset].iTCO_version) { + ret = lpc_ich_init_wdt(dev); + if (!ret) + cell_added = true; + } + + if (lpc_chipset_info[priv->chipset].gpio_version) { + ret = lpc_ich_init_gpio(dev); + if (!ret) + cell_added = true; + } + + /* + * We only care if at least one or none of the cells registered + * successfully. + */ + if (!cell_added) { + dev_warn(&dev->dev, "No MFD cells added\n"); + lpc_ich_restore_config_space(dev); + return -ENODEV; + } + + return 0; +} + +static void lpc_ich_remove(struct pci_dev *dev) +{ + mfd_remove_devices(&dev->dev); + lpc_ich_restore_config_space(dev); +} + +static struct pci_driver lpc_ich_driver = { + .name = "lpc_ich", + .id_table = lpc_ich_ids, + .probe = lpc_ich_probe, + .remove = lpc_ich_remove, +}; + +module_pci_driver(lpc_ich_driver); + +MODULE_AUTHOR("Aaron Sierra "); +MODULE_DESCRIPTION("LPC interface for Intel ICH"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/pmbus.h new file mode 100644 index 000000000000..4efa2bd4f6d8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/pmbus.h @@ -0,0 +1,425 @@ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PMBUS_H +#define PMBUS_H + +#include +#include + +/* + * Registers + */ +enum pmbus_regs { + PMBUS_PAGE = 0x00, + PMBUS_OPERATION = 0x01, + PMBUS_ON_OFF_CONFIG = 0x02, + PMBUS_CLEAR_FAULTS = 0x03, + PMBUS_PHASE = 0x04, + + PMBUS_CAPABILITY = 0x19, + PMBUS_QUERY = 0x1A, + + PMBUS_VOUT_MODE = 0x20, + PMBUS_VOUT_COMMAND = 0x21, + PMBUS_VOUT_TRIM = 0x22, + PMBUS_VOUT_CAL_OFFSET = 0x23, + PMBUS_VOUT_MAX = 0x24, + PMBUS_VOUT_MARGIN_HIGH = 0x25, + PMBUS_VOUT_MARGIN_LOW = 0x26, + PMBUS_VOUT_TRANSITION_RATE = 0x27, + PMBUS_VOUT_DROOP = 0x28, + PMBUS_VOUT_SCALE_LOOP = 0x29, + PMBUS_VOUT_SCALE_MONITOR = 0x2A, + + PMBUS_COEFFICIENTS = 0x30, + PMBUS_POUT_MAX = 0x31, + + PMBUS_FAN_CONFIG_12 = 0x3A, + PMBUS_FAN_COMMAND_1 = 0x3B, + PMBUS_FAN_COMMAND_2 = 0x3C, + PMBUS_FAN_CONFIG_34 = 0x3D, + PMBUS_FAN_COMMAND_3 = 0x3E, + PMBUS_FAN_COMMAND_4 = 0x3F, + + PMBUS_VOUT_OV_FAULT_LIMIT = 0x40, + PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41, + PMBUS_VOUT_OV_WARN_LIMIT = 0x42, + PMBUS_VOUT_UV_WARN_LIMIT = 0x43, + PMBUS_VOUT_UV_FAULT_LIMIT = 0x44, + PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45, + PMBUS_IOUT_OC_FAULT_LIMIT = 0x46, + PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47, + PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48, + PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49, + PMBUS_IOUT_OC_WARN_LIMIT = 0x4A, + PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B, + PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C, + + PMBUS_OT_FAULT_LIMIT = 0x4F, + PMBUS_OT_FAULT_RESPONSE = 0x50, + PMBUS_OT_WARN_LIMIT = 0x51, + PMBUS_UT_WARN_LIMIT = 0x52, + PMBUS_UT_FAULT_LIMIT = 0x53, + PMBUS_UT_FAULT_RESPONSE = 0x54, + PMBUS_VIN_OV_FAULT_LIMIT = 0x55, + PMBUS_VIN_OV_FAULT_RESPONSE = 0x56, + PMBUS_VIN_OV_WARN_LIMIT = 0x57, + PMBUS_VIN_UV_WARN_LIMIT = 0x58, + PMBUS_VIN_UV_FAULT_LIMIT = 0x59, + + PMBUS_IIN_OC_FAULT_LIMIT = 0x5B, + PMBUS_IIN_OC_WARN_LIMIT = 0x5D, + + PMBUS_POUT_OP_FAULT_LIMIT = 0x68, + PMBUS_POUT_OP_WARN_LIMIT = 0x6A, + PMBUS_PIN_OP_WARN_LIMIT = 0x6B, + + PMBUS_STATUS_BYTE = 0x78, + PMBUS_STATUS_WORD = 0x79, + PMBUS_STATUS_VOUT = 0x7A, + PMBUS_STATUS_IOUT = 0x7B, + PMBUS_STATUS_INPUT = 0x7C, + PMBUS_STATUS_TEMPERATURE = 0x7D, + PMBUS_STATUS_CML = 0x7E, + PMBUS_STATUS_OTHER = 0x7F, + PMBUS_STATUS_MFR_SPECIFIC = 0x80, + PMBUS_STATUS_FAN_12 = 0x81, + PMBUS_STATUS_FAN_34 = 0x82, + + PMBUS_READ_VIN = 0x88, + PMBUS_READ_IIN = 0x89, + PMBUS_READ_VCAP = 0x8A, + PMBUS_READ_VOUT = 0x8B, + PMBUS_READ_IOUT = 0x8C, + PMBUS_READ_TEMPERATURE_1 = 0x8D, + PMBUS_READ_TEMPERATURE_2 = 0x8E, + PMBUS_READ_TEMPERATURE_3 = 0x8F, + PMBUS_READ_FAN_SPEED_1 = 0x90, + PMBUS_READ_FAN_SPEED_2 = 0x91, + PMBUS_READ_FAN_SPEED_3 = 0x92, + PMBUS_READ_FAN_SPEED_4 = 0x93, + PMBUS_READ_DUTY_CYCLE = 0x94, + PMBUS_READ_FREQUENCY = 0x95, + PMBUS_READ_POUT = 0x96, + PMBUS_READ_PIN = 0x97, + + PMBUS_REVISION = 0x98, + PMBUS_MFR_ID = 0x99, + PMBUS_MFR_MODEL = 0x9A, + PMBUS_MFR_REVISION = 0x9B, + PMBUS_MFR_LOCATION = 0x9C, + PMBUS_MFR_DATE = 0x9D, + PMBUS_MFR_SERIAL = 0x9E, + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ + PMBUS_VIRT_BASE = 0x100, + PMBUS_VIRT_READ_TEMP_AVG, + PMBUS_VIRT_READ_TEMP_MIN, + PMBUS_VIRT_READ_TEMP_MAX, + PMBUS_VIRT_RESET_TEMP_HISTORY, + PMBUS_VIRT_READ_VIN_AVG, + PMBUS_VIRT_READ_VIN_MIN, + PMBUS_VIRT_READ_VIN_MAX, + PMBUS_VIRT_RESET_VIN_HISTORY, + PMBUS_VIRT_READ_IIN_AVG, + PMBUS_VIRT_READ_IIN_MIN, + PMBUS_VIRT_READ_IIN_MAX, + PMBUS_VIRT_RESET_IIN_HISTORY, + PMBUS_VIRT_READ_PIN_AVG, + PMBUS_VIRT_READ_PIN_MIN, + PMBUS_VIRT_READ_PIN_MAX, + PMBUS_VIRT_RESET_PIN_HISTORY, + PMBUS_VIRT_READ_POUT_AVG, + PMBUS_VIRT_READ_POUT_MIN, + PMBUS_VIRT_READ_POUT_MAX, + PMBUS_VIRT_RESET_POUT_HISTORY, + PMBUS_VIRT_READ_VOUT_AVG, + PMBUS_VIRT_READ_VOUT_MIN, + PMBUS_VIRT_READ_VOUT_MAX, + PMBUS_VIRT_RESET_VOUT_HISTORY, + PMBUS_VIRT_READ_IOUT_AVG, + PMBUS_VIRT_READ_IOUT_MIN, + PMBUS_VIRT_READ_IOUT_MAX, + PMBUS_VIRT_RESET_IOUT_HISTORY, + PMBUS_VIRT_READ_TEMP2_AVG, + PMBUS_VIRT_READ_TEMP2_MIN, + PMBUS_VIRT_READ_TEMP2_MAX, + PMBUS_VIRT_RESET_TEMP2_HISTORY, + + PMBUS_VIRT_READ_VMON, + PMBUS_VIRT_VMON_UV_WARN_LIMIT, + PMBUS_VIRT_VMON_OV_WARN_LIMIT, + PMBUS_VIRT_VMON_UV_FAULT_LIMIT, + PMBUS_VIRT_VMON_OV_FAULT_LIMIT, + PMBUS_VIRT_STATUS_VMON, +}; + +/* + * OPERATION + */ +#define PB_OPERATION_CONTROL_ON BIT(7) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT BIT(4) +#define PB_CAPABILITY_ERROR_CHECK BIT(7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1)) +#define PB_FAN_2_RPM BIT(2) +#define PB_FAN_2_INSTALLED BIT(3) +#define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5)) +#define PB_FAN_1_RPM BIT(6) +#define PB_FAN_1_INSTALLED BIT(7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE BIT(0) +#define PB_STATUS_CML BIT(1) +#define PB_STATUS_TEMPERATURE BIT(2) +#define PB_STATUS_VIN_UV BIT(3) +#define PB_STATUS_IOUT_OC BIT(4) +#define PB_STATUS_VOUT_OV BIT(5) +#define PB_STATUS_OFF BIT(6) +#define PB_STATUS_BUSY BIT(7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN BIT(8) +#define PB_STATUS_OTHER BIT(9) +#define PB_STATUS_FANS BIT(10) +#define PB_STATUS_POWER_GOOD_N BIT(11) +#define PB_STATUS_WORD_MFR BIT(12) +#define PB_STATUS_INPUT BIT(13) +#define PB_STATUS_IOUT_POUT BIT(14) +#define PB_STATUS_VOUT BIT(15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING BIT(0) +#define PB_POUT_OP_FAULT BIT(1) +#define PB_POWER_LIMITING BIT(2) +#define PB_CURRENT_SHARE_FAULT BIT(3) +#define PB_IOUT_UC_FAULT BIT(4) +#define PB_IOUT_OC_WARNING BIT(5) +#define PB_IOUT_OC_LV_FAULT BIT(6) +#define PB_IOUT_OC_FAULT BIT(7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT BIT(4) +#define PB_VOLTAGE_UV_WARNING BIT(5) +#define PB_VOLTAGE_OV_WARNING BIT(6) +#define PB_VOLTAGE_OV_FAULT BIT(7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING BIT(0) +#define PB_IIN_OC_WARNING BIT(1) +#define PB_IIN_OC_FAULT BIT(2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT BIT(4) +#define PB_TEMP_UT_WARNING BIT(5) +#define PB_TEMP_OT_WARNING BIT(6) +#define PB_TEMP_OT_FAULT BIT(7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING BIT(0) +#define PB_FAN_AIRFLOW_FAULT BIT(1) +#define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2) +#define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3) +#define PB_FAN_FAN2_WARNING BIT(4) +#define PB_FAN_FAN1_WARNING BIT(5) +#define PB_FAN_FAN2_FAULT BIT(6) +#define PB_FAN_FAN1_FAULT BIT(7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0) +#define PB_CML_FAULT_OTHER_COMM BIT(1) +#define PB_CML_FAULT_PROCESSOR BIT(3) +#define PB_CML_FAULT_MEMORY BIT(4) +#define PB_CML_FAULT_PACKET_ERROR BIT(5) +#define PB_CML_FAULT_INVALID_DATA BIT(6) +#define PB_CML_FAULT_INVALID_COMMAND BIT(7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN BIT(0) +#define PMBUS_HAVE_VCAP BIT(1) +#define PMBUS_HAVE_VOUT BIT(2) +#define PMBUS_HAVE_IIN BIT(3) +#define PMBUS_HAVE_IOUT BIT(4) +#define PMBUS_HAVE_PIN BIT(5) +#define PMBUS_HAVE_POUT BIT(6) +#define PMBUS_HAVE_FAN12 BIT(7) +#define PMBUS_HAVE_FAN34 BIT(8) +#define PMBUS_HAVE_TEMP BIT(9) +#define PMBUS_HAVE_TEMP2 BIT(10) +#define PMBUS_HAVE_TEMP3 BIT(11) +#define PMBUS_HAVE_STATUS_VOUT BIT(12) +#define PMBUS_HAVE_STATUS_IOUT BIT(13) +#define PMBUS_HAVE_STATUS_INPUT BIT(14) +#define PMBUS_HAVE_STATUS_TEMP BIT(15) +#define PMBUS_HAVE_STATUS_FAN12 BIT(16) +#define PMBUS_HAVE_STATUS_FAN34 BIT(17) +#define PMBUS_HAVE_VMON BIT(18) +#define PMBUS_HAVE_STATUS_VMON BIT(19) + +enum pmbus_data_format { linear = 0, direct, vid }; +enum vrm_version { vr11 = 0, vr12, vr13 }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + enum vrm_version vrm_version; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); + + /* Regulator functionality, if supported by this chip driver. */ + int num_regulators; + const struct regulator_desc *reg_desc; +}; + +/* Regulator ops */ + +extern const struct regulator_ops pmbus_regulator_ops; + +/* Macro for filling in array of struct regulator_desc */ +#define PMBUS_REGULATOR(_name, _id) \ + [_id] = { \ + .name = (_name # _id), \ + .id = (_id), \ + .of_match = of_match_ptr(_name # _id), \ + .regulators_node = of_match_ptr("regulators"), \ + .ops = &pmbus_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, + u8 value); +int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg, + u8 mask, u8 value); +void pmbus_clear_faults(struct i2c_client *client); +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); + +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.c new file mode 100644 index 000000000000..27c45173eef5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.c @@ -0,0 +1,8408 @@ +#include +#include +#include +#include +#include "io_expander.h" +#include "transceiver.h" + +/* For build single module using (Ex: ONL platform) */ +#include +//#include +//#include + +extern int io_no_init; +/* ========== Register EEPROM address mapping ========== + */ +struct eeprom_map_s eeprom_map_sfp = { + .addr_br =0x50, .page_br =-1, .offset_br =12, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =94, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =-1, .offset_connector =2, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =-1, .offset_diag_type =92 , .length_diag_type =1, + .addr_extbr =-1, .page_extbr =-1, .offset_extbr =-1, .length_extbr =-1, + .addr_ext_id =0x50, .page_ext_id =-1, .offset_ext_id =1, .length_ext_id =1, + .addr_id =0x50, .page_id =-1, .offset_id =0, .length_id =1, + .addr_len_sm =0x50, .page_len_sm =-1, .offset_len_sm =15, .length_len_sm =1, + .addr_len_smf =0x50, .page_len_smf =-1, .offset_len_smf =14, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =-1, .offset_len_om1 =17, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =-1, .offset_len_om2 =16, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =-1, .offset_len_om3 =19, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =-1, .offset_len_om4 =18, .length_len_om4 =1, + .addr_option =0x50, .page_option =-1, .offset_option =64, .length_option =2, + .addr_rate_id =0x50, .page_rate_id =-1, .offset_rate_id =13, .length_rate_id =1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =0x51, .page_rx_em =-1, .offset_rx_em =115, .length_rx_em =1, + .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1, + .addr_rx_power =0x51, .page_rx_power =-1, .offset_rx_power =104, .length_rx_power =2, + .addr_soft_rs0 =0x51, .page_soft_rs0 =-1, .offset_soft_rs0 =110, .length_soft_rs0 =1, + .addr_soft_rs1 =0x51, .page_soft_rs1 =-1, .offset_soft_rs1 =118, .length_soft_rs0 =1, + .addr_temp =0x51, .page_temp =-1, .offset_temp =96, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =-1, .offset_trancomp =3, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =-1, .offset_trancomp_ext =36, .length_trancomp_ext =1, + .addr_tx_bias =0x51, .page_tx_bias =-1, .offset_tx_bias =100, .length_tx_bias =2, + .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1, + .addr_tx_eq =0x51, .page_tx_eq =-1, .offset_tx_eq =114, .length_tx_eq =1, + .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1, + .addr_tx_power =0x51, .page_tx_power =-1, .offset_tx_power =102, .length_tx_power =2, + .addr_vendor_name =0x50, .page_vendor_name =-1, .offset_vendor_name =20, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =-1, .offset_vendor_pn =40, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =-1, .offset_vendor_rev =56, .length_vendor_rev =4, + .addr_vendor_sn =0x50, .page_vendor_sn =-1, .offset_vendor_sn =68, .length_vendor_sn =16, + .addr_voltage =0x51, .page_voltage =-1, .offset_voltage =98, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =-1, .offset_wavelength =60, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =-1, .page_rx_em =-1, .offset_rx_em =-1, .length_rx_em =-1, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =-1, .page_tx_eq =-1, .offset_tx_eq =-1, .length_tx_eq =-1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp28 = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =0x50, .page_cdr =-1, .offset_cdr =98, .length_cdr =1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =0x50, .page_rx_am =3, .offset_rx_am =238, .length_rx_am =2, + .addr_rx_em =0x50, .page_rx_em =3, .offset_rx_em =236, .length_rx_em =2, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =0x50, .page_tx_eq =3, .offset_tx_eq =234, .length_tx_eq =2, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + + +/* ========== Utility Functions ========== + */ +static int +get_bit(uint8_t origin_byte, int bit_shift) { + return (int)((origin_byte >> bit_shift) & 0x1); +} + +static int +transform_word_to_int(uint8_t hight_byte, + uint8_t low_byte) { + return ((((int)hight_byte) << 8) + (int)low_byte); +} + +void +alarm_msg_2_user(struct transvr_obj_s *self, + char *emsg) { + + SWPS_ERR("%s on %s.\n", emsg, self->swp_name); +} +EXPORT_SYMBOL(alarm_msg_2_user); + +/* ========== Private functions ========== + */ +static int +_reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +_is_transvr_support_ctle(struct transvr_obj_s *self); + +static int +_transvr_init_handler(struct transvr_obj_s *self); + +int +_transvr_clean_handler(struct transvr_obj_s *self); + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self); + + +void +lock_transvr_obj(struct transvr_obj_s *self) { + + mutex_lock(&self->lock); + self->curr_page = VAL_TRANSVR_PAGE_FREE; +} +EXPORT_SYMBOL(lock_transvr_obj); + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} +EXPORT_SYMBOL(unlock_transvr_obj); + + +static int +_check_by_mode(struct transvr_obj_s *self, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + char *caller_name){ + + int return_val = ERR_TRANSVR_UNEXCPT; + + switch (self->mode){ + case TRANSVR_MODE_POLLING: + switch (self->state){ + case STATE_TRANSVR_CONNECTED: + goto ok_check_by_mode_1; + case STATE_TRANSVR_NEW: + case STATE_TRANSVR_INIT: + return ERR_TRANSVR_UNINIT; + case STATE_TRANSVR_DISCONNECTED: + return ERR_TRANSVR_UNPLUGGED; + case STATE_TRANSVR_UNEXCEPTED: + return ERR_TRANSVR_ABNORMAL; + case STATE_TRANSVR_ISOLATED: + return ERR_TRNASVR_BE_ISOLATED; + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + + case TRANSVR_MODE_DIRECT: + return_val = self->fsm_4_direct(self, caller_name); + if (return_val < 0){ + return return_val; + } + goto ok_check_by_mode_1; + + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + +ok_check_by_mode_1: + return attr_update_func(self, 0); + +err_check_by_mode_1: + SWPS_INFO("_check_by_mode: mode:%d state:%d\n", self->mode, self->state); + return ERR_TRANSVR_UNEXCPT; +} + + +static void +_transvr_clean_retry(struct transvr_obj_s *self) { + self->retry = 0; +} + + +static int +_transvr_handle_retry(struct transvr_obj_s *self, int retry) { + /* Return: 0: keep retry + * -1: stop retry + */ + if (self->retry == 0) { + self->retry = retry; + } + self->retry -= 1; + if (self->retry <= 0) { + _transvr_clean_retry(self); + return -1; + } + return 0; +} + + +static int +_common_setup_page(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int show_e) { + /* return: + * 0 : OK + * -1 : EEPROM settings incorrect + * -2 : I2C R/W failure + * -3 : Undefined case + */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Check */ + if ((addr < 0) || (offset < 0) || (len < 0)) { + emsg = "EEPROM settings incorrect"; + retval = -1; + goto err_common_setup_page; + } + /* Case1: continue access */ + if ((self->i2c_client_p->addr == addr) && + (self->curr_page == page)) { + return 0; + } + self->i2c_client_p->addr = addr; + /* Case2: select lower page */ + if (page == -1) { + self->curr_page = page; + return 0; + } + /* Case3: select upper page */ + if (page >= 0) { + goto upper_common_setup_page; + } + /* Unexpected case */ + show_e = 1; + emsg = "Unexpected case"; + retval = -3; + goto err_common_setup_page; + +upper_common_setup_page: + if (i2c_smbus_write_byte_data(self->i2c_client_p, + VAL_TRANSVR_PAGE_SELECT_OFFSET, + page) < 0) { + emsg = "I2C R/W failure"; + retval = -2; + goto err_common_setup_page; + } + self->curr_page = page; + mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY); + return 0; + +err_common_setup_page: + if (show_e) { + SWPS_INFO("%s: %s", __func__, emsg); + SWPS_INFO("%s: :0x%02x :%d :%d :%d\n", + __func__, addr, page, offset, len); + } + return retval; +} + +/* +static int +_common_setup_password(struct transvr_obj_s *self, + int addr, + int page, + int offs, + uint8_t pwd[4], + int show_e) { + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, 4, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_setup_password; + } + for (i=0; i<4; i++) { + err = i2c_smbus_write_byte_data(self->i2c_client_p, + (offs + i), + pwd[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_setup_password; + } + } + return 0; + +err_common_setup_password: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} +*/ + +static int +_common_update_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + uint8_t *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_uint8_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_uint8_attr; + } + buf[i] = err; + } + return 0; + +err_common_update_uint8_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_int_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_int_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_int_attr; + } + buf[i] = (int)err; + } + return 0; + +err_common_update_int_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_INT_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_string_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + char buf[], + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_string_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_string_attr; + } + buf[i] = (char)err; + } + return 0; + +err_common_update_string_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = 'e'; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + uint8_t update, + uint8_t *buf, + char *caller, + int show_e){ + int len = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + if ((*buf) == update){ + return 0; + } + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + err = i2c_smbus_write_byte_data(self->i2c_client_p, + offset, + update); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + (*buf) = update; + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_array(struct transvr_obj_s *self, + int addr, + int page, + int offs, + int len, + uint8_t update[], + uint8_t buf[], + char *caller, + int show_e){ + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + for (i=0; ii2c_client_p, + (offs + i), + update[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + buf[i] = update[i]; + } + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, emsg, caller, err, i); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_attr_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_id, + self->eeprom_map_p->page_id, + self->eeprom_map_p->offset_id, + self->eeprom_map_p->length_id, + &(self->id), + "_common_update_attr_id", + show_err); +} + + +static int +_common_update_attr_extended_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_ext_id, + self->eeprom_map_p->page_ext_id, + self->eeprom_map_p->offset_ext_id, + self->eeprom_map_p->length_ext_id, + &(self->ext_id), + "_common_update_attr_extended_id", + show_err); +} + + +static int +_common_update_attr_connector(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_connector, + self->eeprom_map_p->page_connector, + self->eeprom_map_p->offset_connector, + self->eeprom_map_p->length_connector, + &(self->connector), + "_common_update_attr_connector", + show_err); +} + + +static int +_common_update_attr_transvr_comp(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp, + self->eeprom_map_p->page_trancomp, + self->eeprom_map_p->offset_trancomp, + self->eeprom_map_p->length_trancomp, + self->transvr_comp, + "_common_update_attr_transvr_comp", + show_err); +} + + +static int +_common_update_attr_transvr_comp_ext(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp_ext, + self->eeprom_map_p->page_trancomp_ext, + self->eeprom_map_p->offset_trancomp_ext, + self->eeprom_map_p->length_trancomp_ext, + &(self->transvr_comp_ext), + "_common_update_attr_transvr_comp_ext", + show_err); +} + + +static int +_common_update_attr_vendor_name(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_name, + self->eeprom_map_p->page_vendor_name, + self->eeprom_map_p->offset_vendor_name, + self->eeprom_map_p->length_vendor_name, + self->vendor_name, + "_common_update_attr_vendor_name", + show_err); +} + + +static int +_common_update_attr_vendor_pn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_pn, + self->eeprom_map_p->page_vendor_pn, + self->eeprom_map_p->offset_vendor_pn, + self->eeprom_map_p->length_vendor_pn, + self->vendor_pn, + "_common_update_attr_vendor_pn", + show_err); +} + + +static int +_common_update_attr_vendor_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_rev, + self->eeprom_map_p->page_vendor_rev, + self->eeprom_map_p->offset_vendor_rev, + self->eeprom_map_p->length_vendor_rev, + self->vendor_rev, + "_common_update_attr_vendor_rev", + show_err); +} + + +static int +_common_update_attr_vendor_sn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_sn, + self->eeprom_map_p->page_vendor_sn, + self->eeprom_map_p->offset_vendor_sn, + self->eeprom_map_p->length_vendor_sn, + self->vendor_sn, + "_common_update_attr_vendor_sn", + show_err); +} + + +static int +_common_update_attr_br(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_br, + self->eeprom_map_p->page_br, + self->eeprom_map_p->offset_br, + self->eeprom_map_p->length_br, + &(self->br), + "_common_update_attr_br", + show_err); +} + + +static int +_common_update_attr_len_smf(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_smf, + self->eeprom_map_p->page_len_smf, + self->eeprom_map_p->offset_len_smf, + self->eeprom_map_p->length_len_smf, + &(self->len_smf), + "_common_update_attr_len_smf", + show_err); +} + + +static int +_common_update_attr_len_om1(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om1, + self->eeprom_map_p->page_len_om1, + self->eeprom_map_p->offset_len_om1, + self->eeprom_map_p->length_len_om1, + &(self->len_om1), + "_common_update_attr_len_om1", + show_err); +} + +static int +_common_update_attr_len_om2(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om2, + self->eeprom_map_p->page_len_om2, + self->eeprom_map_p->offset_len_om2, + self->eeprom_map_p->length_len_om2, + &(self->len_om2), + "_common_update_attr_len_om2", + show_err); +} + +static int +_common_update_attr_len_om3(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om3, + self->eeprom_map_p->page_len_om3, + self->eeprom_map_p->offset_len_om3, + self->eeprom_map_p->length_len_om3, + &(self->len_om3), + "_common_update_attr_len_om3", + show_err); +} + + +static int +_common_update_attr_len_om4(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om4, + self->eeprom_map_p->page_len_om4, + self->eeprom_map_p->offset_len_om4, + self->eeprom_map_p->length_len_om4, + &(self->len_om4), + "_common_update_attr_len_om4", + show_err); +} + + +static int +_common_update_attr_option(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_option, + self->eeprom_map_p->page_option, + self->eeprom_map_p->offset_option, + self->eeprom_map_p->length_option, + self->option, + "_common_update_attr_option", + show_err); +} + + +static int +_common_update_attr_comp_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_comp_rev, + self->eeprom_map_p->page_comp_rev, + self->eeprom_map_p->offset_comp_rev, + self->eeprom_map_p->length_comp_rev, + &(self->comp_rev), + "_common_update_attr_comp_rev", + show_err); +} + + +static int +_common_update_attr_diag_type(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_diag_type, + self->eeprom_map_p->page_diag_type, + self->eeprom_map_p->offset_diag_type, + self->eeprom_map_p->length_diag_type, + &(self->diag_type), + "_common_update_attr_diag_type", + show_err); +} + + +static int +_common_update_attr_wavelength(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_wavelength, + self->eeprom_map_p->page_wavelength, + self->eeprom_map_p->offset_wavelength, + self->eeprom_map_p->length_wavelength, + self->wavelength, + "_common_update_attr_wavelength", + show_err); +} + + +int +_common_get_option_value(struct transvr_obj_s *self, + int offset, + int bit_shift) { + /* SFP: + * - option[0] = A0h / 64 + * - option[1] = A0h / 65 + * QSFP: + * - option[0] = 00h / 193 + * - option[1] = 00h / 194 + * - option[2] = 00h / 195 + */ + return (self->option[offset] & (1 << bit_shift)); +} + + +static int +_sfp_update_attr_len_sm(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_sm, + self->eeprom_map_p->page_len_sm, + self->eeprom_map_p->offset_len_sm, + self->eeprom_map_p->length_len_sm, + &(self->len_sm), + "_common_update_attr_len_sm", + show_err); +} + + +static int +_sfp_update_attr_rate_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_rate_id, + self->eeprom_map_p->page_rate_id, + self->eeprom_map_p->offset_rate_id, + self->eeprom_map_p->length_rate_id, + &(self->rate_id), + "_sfp_update_attr_rate_id", + show_err); +} + + +static int +_sfp_update_attr_soft_rs0(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + self->eeprom_map_p->length_soft_rs0, + &(self->soft_rs0), + "_sfp_update_attr_soft_rs0", + show_err); +} + + +static int +_sfp_update_attr_soft_rs1(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + self->eeprom_map_p->length_soft_rs1, + &(self->soft_rs1), + "_sfp_update_attr_soft_rs1", + show_err); +} + + +int +_sfp_is_diag_support(struct transvr_obj_s *self){ + + uint8_t bit_mask = 0xC0; /* 1100 0000 */ + uint8_t en_val = 0x40; /* 0100 0000 */ + uint8_t checkval = (self->diag_type & bit_mask); + + if (checkval == en_val) { + return 1; + } + return 0; +} + + +static int +_sfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_sfp_update_attr_curr_temp", + show_err); +} + + +static int +_sfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_sfp_update_attr_curr_voltage", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_sfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_sfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_sfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_sfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_sfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_sfp_update_attr_rx_em", + show_err); +} + + +static int +_sfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_sfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_cdr(struct transvr_obj_s *self, + int show_err){ + if (self->type != TRANSVR_TYPE_QSFP_28){ + self->cdr = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + self->eeprom_map_p->length_cdr, + &(self->cdr), + "_common_update_attr_cdr", + show_err); +} + + +static int +_qsfg_update_attr_extbr(struct transvr_obj_s *self, + int show_err) { + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_extbr, + self->eeprom_map_p->page_extbr, + self->eeprom_map_p->offset_extbr, + self->eeprom_map_p->length_extbr, + &(self->extbr), + "_common_update_attr_extbr", + show_err); +} + + +static int +_qsfp_is_diag_support(struct transvr_obj_s *self, + int diag_type) { + /* Input Parm: diag_type + * => 1 : temperature + * => 2 : voltage + * => 3 : tx relate + * => 4 : rx relate + */ + uint8_t mask_b2 = 0x04; /* 0000 0100 */ + uint8_t mask_b3 = 0x08; /* 0000 1000 */ + + switch (diag_type) { + case 1: /* temperature */ + case 2: /* voltage */ + /* Direct access target, because of spec not defined */ + return 1; + case 3: + case 4: + /* [Note] + * Due to lot of transceiver vendor defined it not rigorously and + * consider of general support, we seem it as supported if there + * are bit-2 OR bit-3 defined by transceiver vendor. + */ + if ( ((self->diag_type & mask_b2) == mask_b2 ) || + ((self->diag_type & mask_b3) == mask_b3 ) ){ + return 1; + } + return 0; + default: + SWPS_INFO("%s: undefined diag_type:%d\n", + __func__, diag_type); + break; + } + return 0; +} + + +int +_qsfp_is_implement_tx_disable(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-4 + */ + int byte = 2; + int bit = 4; + return _common_get_option_value(self, byte, bit); +} + + +int +_qsfp_is_implement_tx_fault(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-3 + */ + int byte = 2; + int bit = 3; + return _common_get_option_value(self, byte, bit); +} + + +static int +_qsfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + int diag_type = 1; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_qsfp_update_attr_curr_temp", + show_err); +} + + +static int +_qsfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + int diag_type = 2; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_qsfp_update_attr_curr_voltage", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_qsfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_qsfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_qsfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 4; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_qsfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_qsfp_update_attr_soft_rx_los(struct transvr_obj_s *self, + int show_err){ + + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_los, + self->eeprom_map_p->page_rx_los, + self->eeprom_map_p->offset_rx_los, + self->eeprom_map_p->length_rx_los, + &(self->rx_los), + "_qsfp_update_attr_soft_rx_los", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_disable(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_disable(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_update_attr_soft_tx_disable", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_fault(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_fault(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_fault, + self->eeprom_map_p->page_tx_fault, + self->eeprom_map_p->offset_tx_fault, + self->eeprom_map_p->length_tx_fault, + &(self->tx_fault), + "_qsfp_update_attr_soft_tx_fault", + show_err); +} + + +static int +_qsfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_qsfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_rx_am(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + self->rx_am, + "_qsfp_update_attr_rx_am", + show_err); +} + + +static int +_qsfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_qsfp_update_attr_rx_em", + show_err); +} + + +int +_common_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = "err"; + + if (_common_update_attr_id(self, show_err) < 0) { + err_str = "_common_update_attr_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_extended_id(self, show_err) < 0) { + err_str = "_common_update_attr_extended_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_connector(self, show_err) < 0) { + err_str = "_common_update_attr_connector"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp_ext(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp_ext"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_name(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_name"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_pn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_pn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_rev(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_sn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_sn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_br(self, show_err) < 0) { + err_str = "_common_update_attr_br"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_smf(self, show_err) < 0) { + err_str = "_common_update_attr_len_smf"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om1(self, show_err) < 0) { + err_str = "_common_update_attr_len_om1"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om2(self, show_err) < 0) { + err_str = "_common_update_attr_len_om2"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om3(self, show_err) < 0) { + err_str = "_common_update_attr_len_om3"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om4(self, show_err) < 0) { + err_str = "_common_update_attr_len_om4"; + goto err_common_update_attr_all; + } + if (_common_update_attr_option(self, show_err) < 0) { + err_str = "_common_update_attr_option"; + goto err_common_update_attr_all; + } + if (_common_update_attr_comp_rev(self, show_err) < 0) { + err_str = "_common_update_attr_comp_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_diag_type(self, show_err) < 0) { + err_str = "_common_update_attr_diag_type"; + goto err_common_update_attr_all; + } + if (_common_update_attr_wavelength(self, show_err) < 0) { + err_str = "_common_update_attr_wavelength"; + goto err_common_update_attr_all; + } + return 0; + +err_common_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_sfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_len_sm(self, show_err) < 0) { + err_str = "_sfp_update_attr_len_sm"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_rate_id(self, show_err) < 0) { + err_str = "_sfp_update_attr_rate_id"; + goto err_sfp_update_attr_all; + } + if ((self->rate_id) > 0) { + if (_sfp_update_attr_soft_rs0(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs0"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_soft_rs1(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs1"; + goto err_sfp_update_attr_all; + } + } + return 0; + +err_sfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_qsfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_qsfp_update_attr_all; + } + if (_qsfg_update_attr_extbr(self, show_err) < 0) { + err_str = "_qsfg_update_attr_extbr"; + goto err_qsfp_update_attr_all; + } + if (self->type == TRANSVR_TYPE_QSFP_28) { + if (_qsfp_update_attr_cdr(self, 1) < 0) { + err_str = "_qsfp_update_attr_cdr"; + goto err_qsfp_update_attr_all; + } + } + return 0; + +err_qsfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +/* ========== Object functions for common type ========== + */ +int +_common_count_temp(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + int sign = 0; + int high = 0; + int low = 0; + int lmax = 8; + + /* Count high */ + sign = get_bit(high_byte,7); + SWP_BIT_CLEAR(high_byte, 7); + high = (int)high_byte; + if (sign == 1) { + high = 0 - high; + } + /* Count low */ + low = (get_bit(low_byte, 7) * 500); + low += (get_bit(low_byte, 6) * 250); + low += (get_bit(low_byte, 5) * 125); + low += (get_bit(low_byte, 4) * 62); + low = (low / 100); + /* Integrate High and Low */ + return snprintf(buf_p, lmax, "%d.%d\n", high, low); +} + + +int +_common_count_voltage(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note]: + * Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts. Practical + * considerations to be defined by transceiver manufacturer will + * tend to limit the actual bounds of the supply voltage measurement. + * Accuracy is vendor specific but must be better than 3% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. Note that in some transceivers, transmitter supply + * voltage and receiver supply voltage are isolated. In that case, + * only one supply is monitored. Refer to the device specification + * for more detail. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 100 uV (1mV=1000uV) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 Volt */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_tx_bias(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 2 uA (1mA=1000uA) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total*2) / 1000); + val_f = (((total*2) - (val_i*1000)) / 100); + /* Return Unit: 1 mA */ + return snprintf(buf_p, lmax, "%d.%01d\n", val_i, val_f); +} + + +int +_common_count_tx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_rx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_wavelength(struct transvr_obj_s *self, + uint8_t high_byte, + uint8_t low_byte) { + /* [Note] + * SFP : uint 1 um. + * QSFP: unit 0.05 um. + */ + int total = 0; + + total = transform_word_to_int(high_byte, low_byte); + switch (self->type) { + case TRANSVR_TYPE_SFP: + return total; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + return (total/20); + + default: + break; + } + return ERR_TRANSVR_UNDEFINED; +} + + +int +common_get_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_id, + "common_get_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->id; +} + + +int +common_get_ext_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "common_get_ext_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->ext_id; +} + + +int +common_get_connector(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_connector, + "common_get_connector"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->connector; +} + + +int +common_get_vendor_name(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_name, + "common_get_vendor_name"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); +} + + +int +common_get_vendor_pn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_pn, + "common_get_vendor_pn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); +} + + +int +common_get_vendor_rev(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_rev, + "common_get_vendor_rev"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); +} + + +int +common_get_vendor_sn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_sn, + "common_get_vendor_sn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); +} + + +int +common_get_br(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return (int)self->br; + } + err = _check_by_mode(self, + &_common_update_attr_br, + "common_get_br"); + if (err < 0){ + return err; + } + /* Transform to INT to show error case */ + return (int)self->br; +} + + +int +common_get_len_smf(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_smf; + } + err = _check_by_mode(self, + &_common_update_attr_len_smf, + "common_get_len_smf"); + if (err < 0){ + return err; + } + return self->len_smf; +} + + +int +common_get_len_om1(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om1; + } + err = _check_by_mode(self, + &_common_update_attr_len_om1, + "common_get_len_om1"); + if (err < 0){ + return err; + } + return self->len_om1; +} + + +int +common_get_len_om2(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om2; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om2, + "common_get_len_om2"); + if (err < 0){ + return err; + } + return self->len_om2; +} + + +int +common_get_len_om3(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om3; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om3, + "common_get_len_om3"); + if (err < 0){ + return err; + } + return self->len_om3; +} + + +int +common_get_len_om4(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om4; + } + err = _check_by_mode(self, + &_common_update_attr_len_om4, + "common_get_len_om4"); + if (err < 0){ + return err; + } + return self->len_om4; +} + + +int +common_get_comp_extended(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp_ext, + "common_get_comp_extended"); + if (err_code < 0){ + return err_code; + } + return self->transvr_comp_ext; +} + + +int +common_get_comp_rev(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_comp_rev, + "common_get_comp_rev"); + if (err_code < 0){ + return err_code; + } + return self->comp_rev; +} + + +int +common_get_info(struct transvr_obj_s *self){ + + if (self->state != STATE_TRANSVR_CONNECTED) { + return self->state; + } + return self->info; +} + + +int +_common_get_if_lane(struct transvr_obj_s *self, + char *result){ + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_M_STR); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + memset(tmp_str, 0, LEN_TRANSVR_M_STR); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_M_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_M_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_M_STR); + } + if (i == 0) { + return EVENT_TRANSVR_TASK_FAIL; + } + return 0; +} + + +int +common_get_if_lane(struct transvr_obj_s *self, + char *buf_p){ + + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + if (self->ioexp_obj_p->state != STATE_IOEXP_NORMAL) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n", ERR_TRANSVR_ABNORMAL); + } + if (_common_get_if_lane(self, tmp_str) < 0) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n" ,ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%s\n" ,tmp_str); +} + + +int +sfp_get_len_sm(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_len_sm, + "sfp_get_len_sm"); + if (err_code < 0){ + return err_code; + } + return self->len_sm; +} + + +int +sfp_get_rate_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_rate_id, + "sfp_get_rate_id"); + if (err_code < 0){ + return err_code; + } + return self->rate_id; +} + + +int +sfp_get_soft_rs0(struct transvr_obj_s *self){ + /* Note: + * SFP Soft Rate_Select Select [aka. "RS(0)"] address + * A2h, offset: 110, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs0, + "sfp_get_soft_rs0"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs0 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_soft_rs1(struct transvr_obj_s *self){ + /* Note: + * SFP Soft RS(1) Select address + * A2h, offset: 118, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs1, + "sfp_get_soft_rs1"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs1 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_temp, + "sfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +sfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_voltage, + "sfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +sfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_bias, + "sfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _common_count_tx_bias(self->curr_tx_bias[0], + self->curr_tx_bias[1], + buf_p); +} + + +int +sfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_power, + "sfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_tx_power(self->curr_tx_power[0], + self->curr_tx_power[1], + buf_p); +} + + +int +sfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_rx_power, + "sfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_rx_power(self->curr_rx_power[0], + self->curr_rx_power[0], + buf_p); +} + + +int +sfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->rx_em[0]); +} + + +int +sfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->tx_eq[0]); +} + + +int +_sfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: A0h / 36 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +__sfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* SFP Specification Compliance: A0h / 3-10 + * transvr_comp[0-7] = 3 - 10 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_get_comp_10g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[0] = address A0h / 3 + * + * 3 7: 10G Base-ER + * 3 6: 10GBASE-LRM + * 3 5: 10GBASE-LR + * 3 4: 10GBASE-SR + */ + int bitmask = 0xf0; /* 11110000 */ + return (__sfp_get_comp_attr(self, 0) & bitmask); +} + + +int +_sfp_get_comp_1g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[3] = address A0h / 6 + * + * 6 7: BASE-PX *3 + * 6 6: BASE-BX10 *3 + * 6 5: 100BASE-FX + * 6 4: 100BASE-LX/LX10 + * 6 3: 1000BASE-T + * 6 2: 1000BASE-CX + * 6 1: 1000BASE-LX *3 + * 6 0: 1000BASE-SX + */ + return __sfp_get_comp_attr(self, 3); +} + + +int +_sfp_get_cable_tech(struct transvr_obj_s *self) { + /* transvr_comp[5] = address A0h / 8 + * + * 8 3: Active Cable *8 + * 8 2: Passive Cable *8 + */ + int bitmask = 0x0c; /* 00001100 */ + return (__sfp_get_comp_attr(self, 5) & bitmask); +} + + +int +sfp_get_comp_eth_1(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_1"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_1g_eth_comp(self); +} + + +int +sfp_get_comp_eth_10(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_10"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_10g_eth_comp(self); +} + + +int +_sfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: A0h / 2 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Note] Optical and Cable Variants Specification Compliance (SFF-8472) + * [Addr] A0h, Bytes 60-61 + * [Note] For optical variants, as defined by having zero's in A0h Byte 8 + * bits 2 and 3, Bytes 60 and 61 denote nominal transmitter output + * wavelength at room temperature. 16 bit value with byte 60 as high + * order byte and byte 61 as low order byte. The laser wavelength is + * equal to the 16 bit integer value in nm. This field allows the user + * to read the laser wavelength directly, so it is not necessary to + * infer it from the Transceiver Codes A0h Bytes 3 to 10 (see Table + * 5-3). This also allows specification of wavelengths not covered + * in the Transceiver Codes, such as those used in coarse WDM systems. + * + * For passive and active cable variants, a value of 00h for both A0h + * Byte 60 and Byte 61 denotes laser wavelength or cable specification + * compliance is unspecified. + */ + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +int +sfp_get_1g_rj45_extphy_offset(struct transvr_obj_s *self, char *buf) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%02x\n", self->extphy_offset); +} + + +int +sfp_get_1g_rj45_extphy_reg(struct transvr_obj_s *self, char *buf) { + + int i = 0; + int ret = 0; + int retry = 3; + int delay = 200; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; ii2c_client_p, self->extphy_offset); + if (ret >=0) { + goto ok_sfp_get_1g_rj45_extphy_reg; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; + +ok_sfp_get_1g_rj45_extphy_reg: + ret = ((ret & 0x00ff) << 8) | ((ret & 0xff00) >> 8); + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%04x\n", ret); +} + + +int +__qsfp_get_power_cls(struct transvr_obj_s *self, + int direct_access){ + + int err_code; + uint8_t detect_val; + + /* Detect and Update power class attribute */ + if (direct_access){ + err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_power_cls"); + } else { + err_code = self->ext_id; + } + if (err_code <0){ + return err_code; + } + if (err_code == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data */ + detect_val = self->ext_id; + SWP_BIT_CLEAR(detect_val, 2); /* Bit2: CDR RX present */ + SWP_BIT_CLEAR(detect_val, 3); /* Bit3: CDR TX present */ + SWP_BIT_CLEAR(detect_val, 4); /* Bit4: CLEI present */ + SWP_BIT_CLEAR(detect_val, 5); /* Bit5: reserved */ + /* Identify power class */ + switch (detect_val) { + case 0: /* Class_1: 00000000 */ + return 1; + case 64: /* Class_2: 01000000 */ + return 2; + case 128: /* Class_3: 10000000 */ + return 3; + case 192: /* Class_4: 11000000 */ + return 4; + case 1: /* Class_5: 00000001 */ + case 193: /* Class_5: 11000001 */ + return 5; + case 2: /* Class_6: 00000010 */ + case 194: /* Class_6: 11000010 */ + return 6; + case 3: /* Class_7: 00000011 */ + case 195: /* Class_7: 11000011 */ + return 7; + default: + break; + } + SWPS_INFO("%s: Detect undefined power class:%d\n", __func__, detect_val); + return ERR_TRANSVR_UNDEFINED; +} + + +int +qsfp_get_power_cls(struct transvr_obj_s *self) { + return __qsfp_get_power_cls(self, 1); +} + + +int +__qsfp_get_cdr_present(struct transvr_obj_s *self, + int direct_access){ + + int retval; + int BIT_SHIFT = 2; + int BIT_MASK = 0x3; + + /* Detect and Update power class attribute */ + if (direct_access) { + retval = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_cdr_present"); + if (retval < 0){ + return retval; + } + } + retval = self->ext_id; + if (retval == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data and return */ + return (int)(retval >> BIT_SHIFT & BIT_MASK); +} + + +int +qsfp_get_cdr_present(struct transvr_obj_s *self) { + return __qsfp_get_cdr_present(self, 1); +} + + +int +qsfp_get_cdr(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + "qsfp_get_cdr"); + if (err_code <0){ + return err_code; + } + + return self->cdr; +} + + +int +__qsfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* QSFP Specification Compliance: 00h / 131-138 + * transvr_comp[0-7] = 131 - 138 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_get_comp_10_40_100_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[0] = address 00h / 131 + * + * 131 7: Extended: See section 6.3.23. The Extended Specification Compliance + * Codes are maintained in the Transceiver Management section of SFF- + * 8024. + * 131 6: 10GBASE-LRM + * 131 5: 10GBASE-LR + * 131 4: 10GBASE-SR + * 131 3: 40GBASE-CR4 + * 131 2: 40GBASE-SR4 + * 131 1: 40GBASE-LR4 + * 131 0: 40G Active Cable (XLPPI) + */ + return __qsfp_get_comp_attr(self, 0); +} + + +int +_qsfp_get_comp_sonet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 132 7-3: Reserved + * 132 2: OC 48, long reach + * 132 1: OC 48, intermediate reach + * 132 0: OC 48 short reach + */ + return __qsfp_get_comp_attr(self, 1); +} + + +int +_qsfp_get_comp_sas_sata(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 133 7: SAS 24.0 Gb/s + * 133 6: SAS 12.0 Gb/s + * 133 5: SAS 6.0 Gb/s + * 133 4: SAS 3.0 Gb/s + * 133 3-0: Reserved + */ + return __qsfp_get_comp_attr(self, 2); +} + + +int +_qsfp_get_comp_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 134 7-4: Reserved + * 134 3: 1000BASE-T + * 134 2: 1000BASE-CX + * 134 1: 1000BASE-LX + * 134 0: 1000BASE-SX + */ + return __qsfp_get_comp_attr(self, 3); +} + + +int +_qsfp_get_comp_fc_link_length(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 7: Very long distance (V) + * 135 6: Short distance (S) + * 135 5: Intermediate distance (I) + * 135 4: Long distance (L) + * 135 3: Medium (M) + */ + int mask = 0xFC; /* 11111100 */ + return (__qsfp_get_comp_attr(self, 4) & mask); +} + + +int +_qsfp_get_comp_fc_trans_tech(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 2: Reserved + * 135 1: Longwave laser (LC) + * 135 0: Electrical inter-enclosure (EL) + * + * 136 7: Electrical intra-enclosure + * 136 6: Shortwave laser w/o OFC (SN) + * 136 5: Shortwave laser w OFC (SL) + * 136 4: Longwave Laser (LL) + * 136 3-0: Reserved + * + * return value = [bit 8-15:addr 135][bit 0-7:addr 136] + */ + int mask_135 = 7; /* 00000111 */ + int val_135 = (__qsfp_get_comp_attr(self, 4) & mask_135); + int val_136 = __qsfp_get_comp_attr(self, 5); + return ((val_135 << 7) + val_136); +} + + +int +_qsfp_get_comp_fc_trans_media(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 137 7: Twin Axial Pair (TW) + * 137 6: Shielded Twisted Pair (TP) + * 137 5: Miniature Coax (MI) + * 137 4: Video Coax (TV) + * 137 3: Multi-mode 62.5 m (M6) + * 137 2: Multi-mode 50 m (M5) + * 137 1: Multi-mode 50 um (OM3) + * 137 0: Single Mode (SM) + */ + return __qsfp_get_comp_attr(self, 6); +} + + +int +_qsfp_get_comp_fc_speed(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 138 7: 1200 MBps (per channel) + * 138 6: 800 MBps + * 138 5: 1600 MBps (per channel) + * 138 4: 400 MBps + * 138 3: 3200 MBps (per channel) + * 138 2: 200 MBps + * 138 1: Extended: See section 6.3.23. The Extended Specification + * Compliance Codes are maintained in the Transceiver Management + * section of SFF-8024. + * 138 0: 100 MBps + */ + return __qsfp_get_comp_attr(self, 7); +} + + +int +_qsfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: 00h / 192 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_comp_eth(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_eth"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_ethernet(self); +} + + +int +qsfp_get_comp_10_40(struct transvr_obj_s *self) { + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_10_40"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_10_40_100_ethernet(self); +} + + +int +_qsfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: 00h / 130 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_temp, + "qsfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +qsfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_voltage, + "qsfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +qsfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->tx_eq[0], self->tx_eq[1]); +} + + +int +qsfp_get_transvr_rx_am(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_get_transvr_rx_am"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_am[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_am[0], self->rx_am[1]); +} + + +int +qsfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_em[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_em[0], self->rx_em[1]); +} + + +int +_qsfp_get_channel_diag(uint8_t *data_array, + int (*count_func)(uint8_t high_byte, uint8_t low_byte, char *buf_p), + char *ch_name, + char *result_p) { + int i, high, low; + int len_max = 128; + char ch_buf[4][16] = { DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL }; + + for (i=0; i<4; i++) { + high = (i*2); + low = ((i*2) + 1); + count_func(data_array[high], data_array[low], ch_buf[i]); + } + return snprintf(result_p, len_max, + "%s-%d:%s%s-%d:%s%s-%d:%s%s-%d:%s", + ch_name, 1, ch_buf[0], + ch_name, 2, ch_buf[1], + ch_name, 3, ch_buf[2], + ch_name, 4, ch_buf[3]); +} + + +int +qsfp_get_soft_rx_los(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_rx_los, + "qsfp_get_soft_rx_los"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->rx_los & mask)); +} + + +int +qsfp_get_soft_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_get_soft_tx_disable"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_disable & mask)); +} + + +int +qsfp_get_soft_tx_fault(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_fault, + "qsfp_get_soft_tx_fault"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_fault & mask)); +} + + +int +qsfp_get_auto_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + if (self->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "%d\n", ERR_TRANSVR_FUNC_DISABLE); + } + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "0x%02x\n", self->auto_tx_disable); +} + + +int +qsfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_bias, + "qsfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _qsfp_get_channel_diag(self->curr_tx_bias, + _common_count_tx_bias, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_power, + "qsfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_tx_power, + _common_count_tx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "RX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_rx_power, + "qsfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_rx_power, + _common_count_rx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Desc] Wavelength or Copper Cable Attenuation (SFF-8636) + * [Addr] 00h 186-187 + * [Note] + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is + * a 16-bit hex value with Byte 186 as high order byte and Byte 187 as + * low order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. + * If the free side device is identified as copper cable these registers will + * be used to define the cable attenuation. An indication of 0 dB attenuation + * refers to the case where the attenuation is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +/* Public Function for Setup Features + */ +static int +__sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + uint8_t update_val = (*attr_p); + + switch (input_val) { + case 0: + SWP_BIT_CLEAR(update_val, bit_shift); + break; + case 1: + SWP_BIT_SET(update_val, bit_shift); + break; + default: + retval = ERR_TRANSVR_UNEXCPT; + err_code = ERR_TRANSVR_UNEXCPT; + err_msg = "Exception occurs"; + goto err_private_sfp_set_soft_rs_1; + } + err_code = _common_set_uint8_attr(self, + address, + page, + offset, + update_val, + attr_p, + caller, + show_err); + if (err_code < 0) { + retval = err_code; + err_msg = "Write data via i2c fail!"; + goto err_private_sfp_set_soft_rs_1; + } + (*attr_p) = update_val; + return 0; + +err_private_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +static int +_sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + /* Check input value */ + if ((input_val != 0) && (input_val != 1)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + switch (err_code) { + case 0: + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "Not support this feature"; + break; + case ERR_TRANSVR_UNINIT: + retval = ERR_TRANSVR_UNINIT; + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + retval = ERR_TRANSVR_UNPLUGGED; + err_msg = "Transceiver unplugged!"; + break; + default: + retval = err_code; + err_msg = "Check Rate_ID fail!"; + break; + } + goto err_common_sfp_set_soft_rs_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + attr_update_func, + caller); + if ( (err_code < 0) || + ((*attr_p) == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Generate and update value */ + return __sfp_set_soft_rs(self, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + +err_common_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +sfp_set_soft_rs0(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(0)"] address + * A2h, offset: 110, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + bit_shift, + &_sfp_update_attr_soft_rs0, + &(self->soft_rs0), + "sfp_set_soft_rs0", + show_err); +} + + +int +sfp_set_soft_rs1(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(1)"] address + * A2h, offset: 118, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + bit_shift, + &_sfp_update_attr_soft_rs1, + &(self->soft_rs1), + "sfp_set_soft_rs1", + show_err); +} + + +int +__sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_tx_eq; + } + setv = (uint8_t)input; + if (self->tx_eq[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + setv, + &(self->tx_eq[0]), + "_sfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_tx_eq; + } + return 0; + +err_sfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; itx_eq[0]; + if (_sfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if (self->tx_eq[0] == tmp){ + return 0; + } + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +sfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_tx_eq(self, input, 1); +} + + +int +__sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_rx_em; + } + setv = (uint8_t)input; + if (self->rx_em[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + setv, + &(self->rx_em[0]), + "_sfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_rx_em; + } + return 0; + +err_sfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; irx_em[0]; + if (_sfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if (self->rx_em[0] == tmp){ + return 0; + } + } + return -1; +} + + +int +sfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_rx_em(self, input, 1); +} + + +int +sfp_set_1g_rj45_extphy_offset(struct transvr_obj_s *self, + int input) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xff)) { + return ERR_TRANSVR_BADINPUT; + } + self->extphy_offset = (uint8_t)input; + return 0; +} + + +int +sfp_set_1g_rj45_extphy_reg(struct transvr_obj_s *self, + int input) { + + int i = 0; + int retry = 3; + int delay = 200; + uint16_t tmp = 0; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xffff)) { + return ERR_TRANSVR_BADINPUT; + } + tmp = ((input & 0x00ff) << 8) | ((input & 0xff00) >> 8); + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; i<=retry; i++) { + if (i2c_smbus_write_word_data(self->i2c_client_p, + self->extphy_offset, + tmp) >= 0) { + return 0; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; +} + + +static int +__qsfp_set_cdr(struct transvr_obj_s *self, + int input_val, + int show_err) { + + uint8_t update_val; + int CDR_FEATURE_SUPPORTED = 0x3; + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_name = "__qsfp_set_cdr"; + + /* Check input value */ + if ((input_val < 0) || (input_val > 0xff)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_qsfp_set_cdr_1; + } + update_val = (uint8_t)input_val; + /* Check CDR supported by transceiver */ + err_code = qsfp_get_cdr_present(self); + if (err_code < 0) { + retval = err_code; + switch (err_code) { + case ERR_TRANSVR_UNINIT: + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + err_msg = "Transceiver unplugged!"; + break; + default: + err_msg = "Check CDR present fail!"; + break; + } + goto err_qsfp_set_cdr_1; + } + if (err_code != CDR_FEATURE_SUPPORTED) { + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "This transceiver not support CDR!"; + goto err_qsfp_set_cdr_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + func_name); + if ( (err_code < 0) || + (self->cdr == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_qsfp_set_cdr_1; + } + /* Write input value to transceiver */ + return _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + update_val, + &(self->cdr), + func_name, + show_err); + +err_qsfp_set_cdr_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +qsfp_set_cdr(struct transvr_obj_s *self, + int input_val) { + return __qsfp_set_cdr(self, input_val, 1); +} + + +int +qsfp_set_soft_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int show_err = 1; + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + int update_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_soft_tx_disable"); + if (retval < 0) { + snprintf(err_msg, 63, "Not ready. err:%d", retval); + goto err_qsfp_set_soft_tx_disable; + } + if ((input_val > in_max) || + (input_val < in_min) ){ + retval = ERR_TRANSVR_BADINPUT; + snprintf(err_msg, 63, "Input value:%d incorrect!", input_val); + goto err_qsfp_set_soft_tx_disable; + } + if ((self->tx_disable & 0x0f) == input_val) { + return 0; + } + update_val = ((self->tx_disable & 0xf0) & input_val); + retval = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + input_val, + &(self->tx_disable), + "qsfp_set_tx_disable", + show_err); + if (retval < 0) { + snprintf(err_msg, 63, "_common_set_uint8_attr:%d fail!", retval); + goto err_qsfp_set_soft_tx_disable; + } + return 0; + +err_qsfp_set_soft_tx_disable: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return retval; +} + + +int +_qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + uint8_t update) { + + uint8_t tx_enable = 0x0; + int show_e = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Handle timing issues */ + if (update != tx_enable) { + /* Note: + * Because there are some txvr has timing issues, + * therefore we need to execute reset cycle first. + * (enable -> other settings) + */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + tx_enable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set reset value fail"; + goto err_qsfp_set_auto_tx_disable; + } + mdelay(10); + } + /* Setup target value */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->auto_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set target value fail"; + goto err_qsfp_set_auto_tx_disable; + } + /* Check and update */ + err = _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C get value fail"; + goto err_qsfp_set_auto_tx_disable; + } + if (self->tx_disable != update) { + emsg = "data not become effective"; + goto err_qsfp_set_auto_tx_disable; + } + return 0; + +err_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s\n", + __func__, emsg, self->swp_name); + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Update settings*/ + if (input_val == VAL_TRANSVR_FUNCTION_DISABLE) { + emsg = "User disable auto tx_disable"; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + goto out_qsfp_set_auto_tx_disable; + } + if ((input_val > in_max) || (input_val < in_min) ){ + SWPS_INFO("%s: Input value:%d incorrect! :%s\n", + __func__, input_val, self->swp_name); + return ERR_TRANSVR_BADINPUT; + } + self->auto_tx_disable = input_val; + /* Check current soft tx_disable */ + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_auto_tx_disable"); + switch (retval) { + case 0: + break; + case ERR_TRANSVR_UNPLUGGED: + emsg = "Doesn't need to update"; + goto out_qsfp_set_auto_tx_disable; + default: + SWPS_INFO("%s: setup fail :%d :%s\n", + __func__, retval, self->swp_name); + return retval; + } + return _qsfp_set_auto_tx_disable(self, input_val); + +out_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s :%d\n :%d", + __func__, emsg, self->swp_name, input_val, retval); + return 0; +} + + +int +__qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_tx_eq; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->tx_eq[0] == setv[0]) && + (self->tx_eq[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + setv, + self->tx_eq, + "_qsfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_tx_eq; + } + return 0; + +err_qsfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; itx_eq[0]; + tmp[1] = self->tx_eq[1]; + if (_qsfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if ((self->tx_eq[0] == tmp[0]) && + (self->tx_eq[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_tx_eq(self, input, 1); +} + + +int +__qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_am; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_am[0] == setv[0]) && + (self->rx_am[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + setv, + self->rx_am, + "_qsfp_set_rx_am", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_am; + } + return 0; + +err_qsfp_set_rx_am: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_am[0]; + tmp[1] = self->rx_am[1]; + if (_qsfp_update_attr_rx_am(self, show_e) < 0){ + continue; + } + if ((self->rx_am[0] == tmp[0]) && + (self->rx_am[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_am(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_set_rx_am"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_am(self, input, 1); +} + + +int +__qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_em; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_em[0] == setv[0]) && + (self->rx_em[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + setv, + self->rx_em, + "_qsfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_em; + } + return 0; + +err_qsfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_em[0]; + tmp[1] = self->rx_em[1]; + if (_qsfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if ((self->rx_em[0] == tmp[0]) && + (self->rx_em[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_em(self, input, 1); +} + + +int +common_transvr_dump(struct transvr_obj_s* self){ + + char *type_name = "Undefined"; + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + switch (self->type) { + case TRANSVR_TYPE_SFP: + type_name = STR_TRANSVR_SFP; + break; + case TRANSVR_TYPE_QSFP: + type_name = STR_TRANSVR_QSFP; + break; + case TRANSVR_TYPE_QSFP_PLUS: + type_name = STR_TRANSVR_QSFP_PLUS; + break; + case TRANSVR_TYPE_QSFP_28: + type_name = STR_TRANSVR_QSFP28; + break; + case TRANSVR_TYPE_FAKE: + type_name = "FAKE"; + goto ok_common_transvr_dump; + case TRANSVR_TYPE_UNPLUGGED: + type_name = "UNPLUGGED"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_INCONSISTENT: + type_name = "INCONSISTENT"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_ERROR: + type_name = "ERROR"; + goto err_common_transvr_dump; + + default: + type_name = "UNEXPECTED"; + goto err_common_transvr_dump; + } + printk(KERN_INFO "[SWPS] Dump %s information:\n", self->swp_name); + printk(KERN_INFO " |- :%s\n", type_name); + printk(KERN_INFO " |- :%s\n", self->vendor_name); + printk(KERN_INFO " |- :%s\n", self->vendor_pn); + printk(KERN_INFO " |- :%s\n", self->vendor_rev); + printk(KERN_INFO " |- :%s\n", self->vendor_sn); + printk(KERN_INFO " |- :0x%02x\n", self->br); + printk(KERN_INFO " |- :0x%02x\n", self->comp_rev); + printk(KERN_INFO " |- :%d\n", self->len_om1); + printk(KERN_INFO " |- :%d\n", self->len_om2); + printk(KERN_INFO " |- :%d\n", self->len_om3); + printk(KERN_INFO " |- :%d\n", self->len_om4); + return 0; + +ok_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return 0; + +err_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return -1; +} + + +int +sfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_sm); + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :0x%02x\n", self->rate_id); + return 0; +} + + +int +qsfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :Class_%d\n", __qsfp_get_power_cls(self, 0)); + return 0; +} + + +int +fake_transvr_dump(struct transvr_obj_s* self) { + + printk(KERN_INFO "[SWPS] Dump transceiver information: %s\n", self->swp_name); + printk(KERN_INFO " |- :FAKE\n"); + printk(KERN_INFO " |- :FAKE_VENDER_NAME\n"); + printk(KERN_INFO " |- :FAKE_VENDER_PN\n"); + printk(KERN_INFO " |- :FAKE_VENDER_REV\n"); + printk(KERN_INFO " |- :FAKE_VENDER_SN\n"); + printk(KERN_INFO " |- :0x99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " '- :0x99\n"); + return 0; +} + + +/* ========== Object functions for fake type ========== + */ +int +fake_transvr_update(struct transvr_obj_s *self, + int show_err){ + self->state = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +fake_get_binary(struct transvr_obj_s *self){ + return 1; +} + +int +fake_get_int(struct transvr_obj_s *self){ + return 99; +} + + +int +fake_get_hex(struct transvr_obj_s *self){ + return 0x0f; +} + + +int +fake_get_str(struct transvr_obj_s *self, char *buf) { + return snprintf(buf, 16, "fake_get_str\n"); +} + + +int +fake_set_int(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: %d\n", __func__, input); + return 0; +} + + +int +fake_set_hex(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: 0x%02x\n", __func__, input); + return 0; +} + + +/* ========== Object functions for unsupported ========== + */ +int +unsupported_get_func(struct transvr_obj_s *self){ + return ERR_TRANSVR_NOTSUPPORT; +} + + +int +unsupported_get_func2(struct transvr_obj_s *self, + char *buf_p) { + int len = snprintf(buf_p, 8, "%d\n", ERR_TRANSVR_NOTSUPPORT); + return len; +} + + +int +unsupported_set_func(struct transvr_obj_s *self, + int input_val){ + return ERR_TRANSVR_NOTSUPPORT; +} + + + +/* ========== Object functions for long term task ========== + * + * [Note] + * SWPS transceiver worker is likely the green-thread (coroutine). + * Due to resource and performance considerations. SWPS run all + * features in one kthread at the same time, and handle by it self. + */ + +/* For Transceiver Task Handling + */ +static struct transvr_worker_s * +transvr_task_get(struct transvr_obj_s *self, + char *func_name) { + + struct transvr_worker_s *curr_p = self->worker_p; + + while(curr_p != NULL){ + if (strcmp((curr_p->func_name), func_name) == 0 ) { + return curr_p; + } + curr_p = curr_p->next_p; + } + return NULL; +} + + +static struct transvr_worker_s* +transvr_task_creat(struct transvr_obj_s *self, + int (*main_task)(struct transvr_worker_s *task), + int (*post_task)(struct transvr_worker_s *task), + char *caller) { + + struct transvr_worker_s *task_p = NULL; + struct transvr_worker_s *curr_p = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check task not exist */ + task_p = transvr_task_get(self, caller); + if (task_p) { + snprintf(err_msg, sizeof(err_msg), "Task already created!"); + goto err_transvr_task_creat; + } + /* Create task worker */ + task_p = kzalloc(sizeof(struct transvr_worker_s), GFP_KERNEL); + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_transvr_task_creat; + } + /* Setup task data */ + task_p->transvr_p = self; + task_p->next_p = NULL; + task_p->trigger_time = 0; + task_p->retry = 1; + task_p->state = STATE_T_TASK_INIT; + task_p->main_task = main_task; + task_p->post_task = post_task; + task_p->p_data = NULL; + snprintf(task_p->func_name, sizeof(task_p->func_name), "%s", caller); + /* Setup Link List */ + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p->next_p != NULL) { + curr_p = curr_p->next_p; + } + curr_p->next_p = task_p; + task_p->pre_p = curr_p; + } else { + self->worker_p = task_p; + task_p->pre_p = NULL; + } + return task_p; + +err_transvr_task_creat: + SWPS_ERR("%s: %s :%s :%s\n", + __func__, err_msg, caller, self->swp_name); + return NULL; +} + + +static void +transvr_task_free_one(struct transvr_worker_s *task_p){ + + struct transvr_worker_s *pre_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (task_p) { + pre_p = task_p->pre_p; + next_p = task_p->next_p; + + if ((pre_p) && (next_p)) { + pre_p->next_p = next_p; + next_p->pre_p = pre_p; + + } else if ((!pre_p) && (next_p)) { + next_p->pre_p = NULL; + + } else if ((pre_p) && (!next_p)) { + pre_p->next_p = NULL; + + } else if ((!pre_p) && (!next_p)) { + task_p->transvr_p->worker_p = NULL; + } else { + SWPS_ERR("%s: Unexcept case!\n :%s", + __func__, task_p->transvr_p->swp_name); + } + kfree(task_p->p_data); + kfree(task_p); + } +} + + +static void +transvr_task_free_all(struct transvr_obj_s *self) { + + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p) { + next_p = curr_p->next_p; + transvr_task_free_one(curr_p); + curr_p = next_p; + } + self->worker_p = NULL; + } +} + + +static void +transvr_cache_free_all(struct transvr_obj_s *self) { + + memset(self->vendor_name, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_rev, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_pn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_sn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + self->extphy_offset = 0; +} + +static int +_transvr_task_run_main(struct transvr_worker_s *task_p) { + + int retval = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "main_task is NULL!"); + goto main_transvr_task_err; + } + if ((task_p->trigger_time) == 0){ + goto main_transvr_task_run; + } + if (time_before(jiffies, task_p->trigger_time)){ + goto main_transvr_task_wait; + } + goto main_transvr_task_run; + +main_transvr_task_run: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + task_p->retry -= 1; + } + retval = task_p->main_task(task_p); + if (retval < 0) { + if (task_p->retry > 0) { + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + } + goto main_transvr_task_identify; + +main_transvr_task_identify: + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + + case EVENT_TRANSVR_TASK_DONE: + task_p->state = STATE_T_TASK_DONE; + return EVENT_TRANSVR_TASK_DONE; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + +main_transvr_task_wait: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + +main_transvr_task_err: + task_p->state = STATE_T_TASK_FAIL; + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, retval, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_transvr_task_run_post(struct transvr_worker_s *task_p) { + + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if ((task_p->post_task) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + switch (task_p->state) { + case STATE_T_TASK_WAIT: + case STATE_T_TASK_INIT: + goto post_transvr_task_wait; + + case STATE_T_TASK_DONE: + case STATE_T_TASK_FAIL: + goto post_transvr_task_run; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Unexcept task state"); + goto post_transvr_task_err; + +post_transvr_task_run: + task_p->post_task(task_p); + return EVENT_TRANSVR_TASK_DONE; + +post_transvr_task_wait: + return EVENT_TRANSVR_TASK_WAIT; + +post_transvr_task_err: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, task_p->state, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_one(struct transvr_worker_s *task_p) { + + int retval_main = DEBUG_TRANSVR_INT_VAL; + int retval_post = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval_main = _transvr_task_run_main(task_p); + if (retval_main < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute main_task fail!"); + goto err_transvr_task_run_one; + } + retval_post = _transvr_task_run_post(task_p); + if (retval_post < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute post_task fail!"); + goto err_transvr_task_run_one; + } + return retval_main; + +err_transvr_task_run_one: + SWPS_INFO("%s: %s
:%d :%d :%s :%s\n", + __func__, err_msg, retval_main, retval_post, + task_p->func_name, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_all(struct transvr_obj_s *self) { + + int haserr = 0; + int retval = DEBUG_TRANSVR_INT_VAL; + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if ((self->worker_p) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + curr_p = self->worker_p; + while (curr_p != NULL) { + next_p = curr_p->next_p; + retval = transvr_task_run_one(curr_p); + if (curr_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + curr_p = next_p; + continue; + } + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + break; + case EVENT_TRANSVR_TASK_DONE: + transvr_task_free_one(curr_p); + break; + case EVENT_TRANSVR_TASK_FAIL: + + default: + haserr = 1; + transvr_task_free_one(curr_p); + break; + } + curr_p = next_p; + } + if (haserr) { + return EVENT_TRANSVR_TASK_FAIL; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +static void +transvr_task_set_delay(struct transvr_worker_s *task_p, + unsigned long delay_msec) { + + task_p->trigger_time = (jiffies + (delay_msec * (HZ/1000))); +} + + +static void +transvr_task_set_retry(struct transvr_worker_s *task_p, + unsigned long retry_times) { + + task_p->retry = retry_times; +} + + +/* For Transceiver Post Task + */ +int +taskfunc_post_do_nothing(struct transvr_worker_s *task_p) { + + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_post_handle_task_state(struct transvr_worker_s *task_p) { + + struct transvr_obj_s* tp = task_p->transvr_p; + + switch (task_p->state) { + case STATE_T_TASK_INIT: + case STATE_T_TASK_WAIT: + return EVENT_TRANSVR_TASK_WAIT; + + case STATE_T_TASK_DONE: + tp->state = STATE_TRANSVR_CONNECTED; + tp->send_uevent(tp, KOBJ_ADD); + return EVENT_TRANSVR_TASK_DONE; + + case STATE_T_TASK_FAIL: + tp->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_TASK_FAIL; + + default: + break; + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +/* For Transceiver Main Task + */ +int +_taskfunc_sfp_setup_soft_rs(struct transvr_worker_s *task_p, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller) { + + int show_err = 0; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_soft_rs"; + + err_code = _sfp_update_attr_soft_rs0(task_p->transvr_p, 0); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + err_code = __sfp_set_soft_rs(task_p->transvr_p, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_setup_soft_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_code); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +__taskfunc_sfp_setup_hard_rs(struct transvr_worker_s *task_p, + int input_val, + int (*get_func)(struct ioexp_obj_s *self, int virt_offset), + int (*set_func)(struct ioexp_obj_s *self, int virt_offset, int input_val)) { + + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + + err_val = get_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset); + + if (err_val < 0) { + if (err_val == ERR_IOEXP_NOTSUPPORT) { + return EVENT_TRANSVR_TASK_DONE; + } + err_str = "Get current hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + if (err_val == input_val) { + return EVENT_TRANSVR_TASK_DONE; + } + err_val = set_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_p_taskfunc_sfp_setup_hard_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_hard_rs0(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs0, + task_p->transvr_p->ioexp_obj_p->set_hard_rs0); +} + + +int +_taskfunc_sfp_setup_hard_rs1(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs1, + task_p->transvr_p->ioexp_obj_p->set_hard_rs1); +} + + +int +_taskfunc_sfp_setup_rs0(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs0"; + + err_val = _taskfunc_sfp_setup_hard_rs0(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs0, + task_p->transvr_p->eeprom_map_p->page_soft_rs0, + task_p->transvr_p->eeprom_map_p->offset_soft_rs0, + bit_shift, + &(task_p->transvr_p->soft_rs0), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs0_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs0(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_rs1(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs1"; + + err_val = _taskfunc_sfp_setup_hard_rs1(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs1, + task_p->transvr_p->eeprom_map_p->page_soft_rs1, + task_p->transvr_p->eeprom_map_p->offset_soft_rs1, + bit_shift, + &(task_p->transvr_p->soft_rs1), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs1_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs1(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_sfp_setup_SFF8431_case1(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs0(task_p, update_val); +} + + + +int +taskfunc_sfp_setup_SFF8431_case2(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs1(task_p, update_val); +} + + +int +taskfunc_sfp_setup_SFF8431_case3(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + int update_rs0 = 1; + int update_rs1 = 1; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _taskfunc_sfp_setup_rs0(task_p, update_rs0); + if (err_code < 0) { + return err_code; + } + return _taskfunc_sfp_setup_rs1(task_p, update_rs1); +} + + +int +taskfunc_sfp_handle_1g_rj45(struct transvr_worker_s *task_p) { + + /* Not all of platform support 0x56 for transceiver + * external PHY, Support list as below: + * => 1. Magnolia-PVT (PS: EVT & DVT not ready) + */ + int ext_phy_addr = 0x56; + int ext_phy_page = -1; + int ext_phy_offs = 0x11; + int ext_phy_len = 1; + int lstate_mask = 0x04; /* 00000100 */ + int show_err = 0; + int fail_retry = 5; + int fail_delay = 1000; /* msec */ + int err_code = DEBUG_TRANSVR_INT_VAL; + uint8_t detect_val = DEBUG_TRANSVR_HEX_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + int *tmp_p = NULL; + char *func_name = "taskfunc_sfp_handle_1g_rj45"; + + if (task_p->transvr_p->state != STATE_TRANSVR_CONNECTED) { + return EVENT_TRANSVR_TASK_DONE; + } + if ( (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000) && + (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000_up) ) { + goto err_taskfunc_sfp_handle_1g_rj45_1; + } + err_code = _common_update_uint8_attr(task_p->transvr_p, + ext_phy_addr, + ext_phy_page, + ext_phy_offs, + ext_phy_len, + &detect_val, + func_name, + show_err); + if ( (err_code < 0) || + (detect_val == DEBUG_TRANSVR_HEX_VAL) ) { + snprintf(err_str, sizeof(err_str), "Detect external link status fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + if ((detect_val & lstate_mask) == lstate_mask) { + goto ok_taskfunc_sfp_handle_1g_rj45_link_up; + } + goto ok_taskfunc_sfp_handle_1g_rj45_link_down; + +ok_taskfunc_sfp_handle_1g_rj45_link_up: + /* Filter out noise */ + if (!(task_p->p_data)) { + tmp_p = kzalloc(sizeof(int), GFP_KERNEL); + if (!tmp_p) { + snprintf(err_str, sizeof(err_str), "kzalloc p_data fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + *tmp_p = TRANSVR_CLASS_BASE_T_1000_up; + task_p->p_data = tmp_p; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + } + if ((*(int *)(task_p->p_data)) != TRANSVR_CLASS_BASE_T_1000_up) { + kfree(task_p->p_data); + task_p->p_data = NULL; + snprintf(err_str, sizeof(err_str), "Internal error"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + kfree(task_p->p_data); + task_p->p_data = NULL; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_link_down: + if (task_p->p_data) { + kfree(task_p->p_data); + task_p->p_data = NULL; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_done: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_1: + snprintf(err_str, sizeof(err_str), "Detect transceiver:%d not Base-T, remove task.", + task_p->transvr_p->info); + SWPS_INFO("%s: %s :%s\n", __func__, err_str, task_p->transvr_p->swp_name); + transvr_task_set_retry(task_p, 0); + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_2: + if (task_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, fail_retry); + } + if ((task_p->retry) == 0) { + /* Error case: + * => In this case, SWPS will stop external Link state monitor features + * and keeps transvr_p->info on TRANSVR_CLASS_BASE_T_1000_up. + * Upper layer will see it always Linkup that because of these type of + * transceiver has external phy, BCM chip see it as Loopback transceiver. + */ + SWPS_WARN("%s can not access external PHY of Base-T SFP transceiver\n", + task_p->transvr_p->swp_name); + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + return EVENT_TRANSVR_TASK_DONE; + } else { + transvr_task_set_delay(task_p, fail_delay); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self, + int setup_val) { + + int curr_val = DEBUG_TRANSVR_INT_VAL; + int err_val = DEBUG_TRANSVR_INT_VAL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + if (io_no_init) { + + SWPS_INFO("%s no_io_init\n",__func__); + return EVENT_TRANSVR_TASK_DONE; + } + + curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset); + if (curr_val < 0){ + err_msg = "Get current value fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + if (curr_val == setup_val){ + return EVENT_TRANSVR_TASK_DONE; + } + err_val = self->ioexp_obj_p->set_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset, + setup_val); + if (err_val < 0){ + err_msg = "Setup power mode fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_qsfp_setup_power_mod_1: + SWPS_INFO("%s: %s :%d :%d :%d\n", + __func__, err_msg, err_val, curr_val, setup_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_qsfp_handle_tx_disable(struct transvr_worker_s *task_p) { + + int i = 0; + int retry = 5; + int delay_ms = 100; + + if (task_p->transvr_p->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return EVENT_TRANSVR_TASK_DONE; + } + if (!_qsfp_is_implement_tx_disable(task_p->transvr_p)) { + return EVENT_TRANSVR_TASK_DONE; + } + for (i=0; itransvr_p, + task_p->transvr_p->auto_tx_disable) + == EVENT_TRANSVR_TASK_DONE) { + goto ok_taskfunc_qsfp_handle_tx_disable; + } + mdelay(delay_ms); + } + SWPS_INFO("%s auto setup tx_disable:0x%02x fail.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_INIT_FAIL; + +ok_taskfunc_qsfp_handle_tx_disable: + SWPS_INFO("%s auto setup tx_disable:0x%02x ok.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_qsfp_set_hpmod(struct transvr_worker_s *task_p) { + + int err = DEBUG_TRANSVR_INT_VAL; + int HIGH_POWER_MODE = 0; + + /* Handle power mode */ + err = _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + HIGH_POWER_MODE); + if (err < 0) { + SWPS_INFO("%s: setup hpmod fail :%d :%s\n", + __func__, err, task_p->transvr_p->swp_name); + return err; + } + /* Handle auto tx_disable + * [Note] + * => Because there are some transceiver have timing issues or + * setup sequence issues, therefore we handle auto tx_disable + * after handle power mode. + */ + mdelay(100); + return taskfunc_qsfp_handle_tx_disable(task_p); +} + + +int +taskfunc_qsfp_set_lpmod(struct transvr_worker_s *task_p) { + + int LOW_POWER_MODE = 1; + return _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + LOW_POWER_MODE); +} + + +static int +initfunc_sfp_handle_multi_rate_mode(struct transvr_obj_s *self) { + + int task_retry = 3; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "sfp_handle_multi_rate_mode"; + struct transvr_worker_s *task_p = NULL; + + switch (self->rate_id) { + case 0x00: /* Unspecified */ + case 0x03: /* Unspecified */ + case 0x05: /* Unspecified */ + case 0x07: /* Unspecified */ + case 0x09: /* Unspecified */ + case 0x0B: /* Unspecified */ + case 0x0D: /* Unspecified */ + case 0x0F: /* Unspecified */ + goto sfp_handle_multi_rate_mode_4_unspecified; + + case 0x02: /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case1, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x04: /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case2, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x06: /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case3, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x01: /* SFF-8079 (4/2/1G Rate_Select & AS0/AS1) */ + err_str = "SFF-8079 (4/2/1G Rate_Select & AS0/AS1)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x08: /* FC-PI-5 (16/8/4G Rx Rate_select only) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Rx Rate_select only)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0A: /* FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0C: /* FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + */ + err_str = "FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0E: /* 10/8G Rx and Tx Rate_Select controlling the operation or + * locking modes of the internal signal conditioner, retimer + * or CDR, according to the logic table defined in Table 10-2, + * High Bit Rate (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = + * 8.5 Gb/s. In this mode, the default value of bit 110.3 (Soft + * Rate Select RS(0), Table 9-11) and of bit 118.3 (Soft Rate + * Select RS(1), Table 10-1) is 1. + */ + err_str = "cable type: 0x0E"; + goto sfp_handle_multi_rate_mode_4_not_support; + + default: + err_str = "cable type: UNKNOW"; + goto sfp_handle_multi_rate_mode_4_not_support; + } + +sfp_handle_multi_rate_mode_4_sff8431: + if (!task_p) { + err_str = "Create task fail!"; + goto sfp_handle_multi_rate_mode_4_fail_1; + } + transvr_task_set_retry(task_p, task_retry); + return EVENT_TRANSVR_TASK_WAIT; + +sfp_handle_multi_rate_mode_4_unspecified: + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_not_support: + SWPS_INFO("%s: Does not support %s :%s :0x%02x\n", + func_str, err_str, self->swp_name, self->rate_id); + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_fail_1: + SWPS_INFO("%s: %s :%s :0x%02x, :%d\n", + func_str, err_str, self->swp_name, self->rate_id, err_code); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +initfunc_sfp_handle_1g_rj45(struct transvr_obj_s *self) { + + struct transvr_worker_s *task_p = NULL; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_sfp_handle_1g_rj45"; + + + if (self->info == TRANSVR_CLASS_BASE_T_1000) { + task_p = transvr_task_creat(self, + taskfunc_sfp_handle_1g_rj45, + taskfunc_post_do_nothing, + func_str); + if (!task_p) { + snprintf(err_str, sizeof(err_str), "Create task fail"); + goto err_initfunc_sfp_handle_1g_rj45; + } + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_initfunc_sfp_handle_1g_rj45: + SWPS_INFO("%s: %s :%s :%d\n", + __func__, err_str, self->swp_name, detect_cls); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +initfunc_qsfp_handle_power_mode(struct transvr_obj_s *self) { + + int err_code = EVENT_TRANSVR_EXCEP_INIT; + int power_class = DEBUG_TRANSVR_INT_VAL; + int hpmod_retry = 3; + int lpower_config = 1; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + unsigned long hpmod_delay = 500; /* msec */ + struct transvr_worker_s *task_p = NULL; + + /* Handle power mode for IOEXP */ + power_class = __qsfp_get_power_cls(self, 0); + switch (power_class) { + case 1: /* Case: Low power mode (Class = 1) */ + err_code = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (err_code < 0){ + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + return EVENT_TRANSVR_TASK_DONE; + + case 2: /* Case: High power mode (Class > 1) */ + case 3: + case 4: + case 5: + case 6: + case 7: + task_p = transvr_task_creat(self, + taskfunc_qsfp_set_hpmod, + taskfunc_post_handle_task_state, + "transvr_init_qsfp"); + if (!task_p) { + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + transvr_task_set_retry(task_p, hpmod_retry); + transvr_task_set_delay(task_p, hpmod_delay); + return EVENT_TRANSVR_TASK_WAIT; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Exception case"); + goto err_initfunc_qsfp_handle_power_mode; + +err_initfunc_qsfp_handle_power_mode: + SWPS_INFO("%s: %s :%s \n", __func__, err_msg, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +initfunc_qsfp28_handle_cdr(struct transvr_obj_s *self) { + + uint8_t DEFAULT_VAL_CDR = 0xff; + int CDR_FUNC_EXISTED = 0x3; + int show_err = 1; + int err_val = EVENT_TRANSVR_TASK_FAIL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_qsfp28_handle_cdr"; + + err_val = __qsfp_get_cdr_present(self, 0); + if ( (err_val < 0) || + (err_val == DEBUG_TRANSVR_HEX_VAL) ) { + err_msg = "detect cdr_present fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + if (err_val == CDR_FUNC_EXISTED) { + err_val = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->offset_cdr, + DEFAULT_VAL_CDR, + &(self->cdr), + func_str, + show_err); + if (err_val < 0) { + err_msg = "set CDR fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_qsfp_handle_cdr_1: + SWPS_INFO("%s: %s :%d :%s\n", + func_str, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + +/* ========== Object functions for Final State Machine ========== + */ +int +is_plugged(struct transvr_obj_s *self){ + + int limit = 63; + int present = DEBUG_TRANSVR_INT_VAL; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p; + + if (!ioexp_p) { + snprintf(emsg, limit, "ioexp_p is null!"); + goto err_is_plugged_1; + } + present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset); + switch (present){ + case 0: + return 1; + case 1: + return 0; + case ERR_IOEXP_UNINIT: + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + default: + if (ioexp_p->state == STATE_IOEXP_INIT){ + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + } + break; + } + SWPS_INFO("%s: Exception case! :%d :%d\n", + __func__, present, ioexp_p->state); + return 0; + +err_is_plugged_1: + SWPS_DEBUG("%s: %s\n", __func__, emsg); + return 0; +} + + +static int +detect_transvr_type(struct transvr_obj_s* self){ + + int type = TRANSVR_TYPE_ERROR; + + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + type = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + + /* Case: 1. Wait transceiver I2C module. + * 2. Transceiver I2C module failure. + * Note: 1. SFF allow maximum transceiver initial time is 2 second. So, there + * are exist some case that we need to wait transceiver. + * For these case, we keeps status on "TRANSVR_TYPE_UNPLUGGED", than + * state machine will keep trace with it. + * 2. There exist some I2C failure case we need to handle. Such as user + * insert the failure transceiver, or any reason cause it abnormal. + */ + if (type < 0){ + switch (type) { + case -EIO: + SWPS_DEBUG("%s: %s smbus return:-5 (I/O error)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + case -ENXIO: + SWPS_DEBUG("%s: %s smbus return:-6 (No such device or address)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + default: + break; + } + SWPS_INFO("%s: %s unexpected smbus return:%d \n", + __func__, self->swp_name, type); + return TRANSVR_TYPE_ERROR; + } + /* Identify valid transceiver type */ + switch (type){ + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + break; + case TRANSVR_TYPE_UNKNOW_1: + case TRANSVR_TYPE_UNKNOW_2: + type = TRANSVR_TYPE_UNKNOW_2; + break; + default: + SWPS_DEBUG("%s: unknow type:0x%02x \n", __func__, type); + type = TRANSVR_TYPE_ERROR; + break; + } + return type; +} + + +static int +detect_transvr_state(struct transvr_obj_s *self, + int result[2]){ + /* [return] [result-0] [result-1] + * 0 STATE_TRANSVR_CONNECTED TRANSVR_TYPE_FAKE + * 0 STATE_TRANSVR_DISCONNECTED TRANSVR_TYPE_UNPLUGGED + * 0 STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * 0 STATE_TRANSVR_INIT / + * 0 STATE_TRANSVR_SWAPPED + * 0 STATE_TRANSVR_CONNECTED + * ERR_TRNASVR_BE_ISOLATED STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_I2C_CRASH STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_UNEXCPT STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_UNKNOW_1/2 + */ + result[0] = STATE_TRANSVR_UNEXCEPTED; /* For return state */ + result[1] = TRANSVR_TYPE_ERROR; /* For return type */ + + /* Case1: Fake type */ + if (self->type == TRANSVR_TYPE_FAKE){ + result[0] = STATE_TRANSVR_CONNECTED; + result[1] = TRANSVR_TYPE_FAKE; + return 0; + } + /* Case2: Transceiver unplugged */ + if (!is_plugged(self)){ + result[0] = STATE_TRANSVR_DISCONNECTED; + result[1] = TRANSVR_TYPE_UNPLUGGED; + return 0; + } + /* Case3: Transceiver be isolated */ + if (self->state == STATE_TRANSVR_ISOLATED){ + result[0] = STATE_TRANSVR_ISOLATED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case4: Transceiver plugged */ + result[1] = detect_transvr_type(self); + /* Case4.1: I2C topology crash + * Note : There are some I2C issues cause by transceiver/cables. + * We need to check topology status when user insert it. + * But in this step, we can't not ensure this is the issues + * port. So, it return the ERR_TRANSVR_I2C_CRASH, then upper + * layer will diagnostic I2C topology. + */ + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: %s detect I2C crash :%d\n", + __func__, self->swp_name, self->state); + result[0] = STATE_TRANSVR_UNEXCEPTED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_I2C_CRASH; + } + /* Case4.2: System initial not ready, + * Note : Sometime i2c channel or transceiver EEPROM will delay that will + * cause system in inconsistent state between EEPROM and IOEXP. + * In this case, SWP transceiver object keep state at LINK_DOWN + * to wait system ready. + * By the way, State Machine will handle these case. + */ + if (result[1] == TRANSVR_TYPE_UNPLUGGED){ + result[0] = STATE_TRANSVR_DISCONNECTED; + return 0; + } + /* Case4.3: Error transceiver type */ + if (result[1] == TRANSVR_TYPE_ERROR){ + result[0] = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s detect error type\n", __func__, self->swp_name); + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard!"); + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case3.3: Unknow transceiver type */ + if ((result[1] == TRANSVR_TYPE_UNKNOW_1) || + (result[1] == TRANSVR_TYPE_UNKNOW_2) ){ + result[0] = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + /* Case3.4: During initial process */ + if (self->state == STATE_TRANSVR_INIT){ + result[0] = STATE_TRANSVR_INIT; + return 0; + } + /* Case3.5: Transceiver be swapped */ + if (self->type != result[1]){ + result[0] = STATE_TRANSVR_SWAPPED; + return 0; + } + /* Case3.6: Link up state */ + result[0] = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +_sfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = _sfp_get_comp_extended(self); + + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_25G_AOC; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_25G_SR; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_25G_LR; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_25G_ER; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x0c: /* 25GBASE-CR CA-S */ + case 0x0d: /* 25GBASE-CR CA-N */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L1_25G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_10_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _sfp_get_comp_10g_eth_comp(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 10G Optical (x1) */ + if ((detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + } + if ((detect_val & 0x80) == 0x80) { /* 10000000 : 10GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_1g = 0x0b; + int upper_bound_1g = 0x1A; + int lower_bound_10g = 0x60; + int upper_bound_10g = 0x75; + int lower_bound_25g = 0xf0; + int upper_bound_25g = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 25G */ + if ((notmal_br >= lower_bound_25g) && + (notmal_br <= upper_bound_25g) ) { + return TRANSVR_CLASS_25G; + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + /* Check 1G */ + if ((notmal_br >= lower_bound_1g) && + (notmal_br <= upper_bound_1g) ) { + return TRANSVR_CLASS_1G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + int speed_br = DEBUG_TRANSVR_INT_VAL; + int speed_tmp = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + + speed_br = _sfp_detect_if_sp_by_br(self); + detect_val = _sfp_get_comp_1g_eth_comp(self); + + if (detect_val < 0) { + snprintf(err_str, sizeof(err_str), "Detect abnormal value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + } + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 1G (x1) */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 1000BASE-SX */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_SX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x02) == 0x02) { /* 00000010 : 1000BASE-LX *3 */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_LX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 1000BASE-CX */ + speed_tmp = TRANSVR_CLASS_COPPER_L1_1G; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + /* Case: 1000 Base-T (x1) */ + if ((detect_val & 0x08) == 0x08) { /* 00001000 : 1000BASE-T */ + return TRANSVR_CLASS_BASE_T_1000; + } + /* Case: 100 Base */ + if ( ((detect_val & 0x10) == 0x10) || /* 00010000 : 100BASE-LX/LX10 */ + ((detect_val & 0x20) == 0x20) || /* 00100000 : 100BASE-FX */ + ((detect_val & 0x40) == 0x40) || /* 01000000 : BASE-BX10 *3 */ + ((detect_val & 0x80) == 0x80) ){ /* 10000000 : BASE-PX *3 */ + return TRANSVR_CLASS_OPTICAL_100; + } + /* Case: ERROR */ + snprintf(err_str, sizeof(err_str), "Case:ERROR, value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + +ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g: + switch (speed_br) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_1G: + return speed_tmp; + case TRANSVR_CLASS_10G: + goto ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G; + } + +ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G: + switch (speed_tmp) { + case TRANSVR_CLASS_OPTICAL_1G_SX: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case TRANSVR_CLASS_OPTICAL_1G_LX: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case TRANSVR_CLASS_COPPER_L1_1G: + return TRANSVR_CLASS_COPPER_L1_10G; + default: + break; + } + snprintf(err_str, sizeof(err_str), "transfer_1to10 fail, speed:%d", speed_tmp); + goto err_p_sfp_detect_class_by_1g_ethernet; + +err_p_sfp_detect_class_by_1g_ethernet: + SWPS_INFO("%s: %s :%s", __func__, err_str, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int is_active = 0; + int conn_val = DEBUG_TRANSVR_INT_VAL; + int check_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _sfp_detect_if_sp_by_br(self); + conn_val = _sfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 */ + case 0x0d: /* MPO 2x16 */ + /* + * ToDo: Need verify Optical Pigtail + */ + goto ok_sfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + /* + * ToDo: Need check ACC use case + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x23: /* No separable connector */ + /* + * ToDo: Standard not clear, not all transceiver vendor + * have the same defined + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_check_active_passive: + check_val = _sfp_get_cable_tech(self); + switch(check_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_unknow; + case 0x04: /* Passive */ + goto ok_sfp_detect_class_by_feature_4_copper; + case 0x08: /* Active */ + is_active = 1; + goto ok_sfp_detect_class_by_feature_4_aoc; + default: + snprintf(err_msg, sizeof(err_msg), + "_sfp_get_cable_tech return Non define value:%d", + check_val); + break; + } + goto err_sfp_detect_class_by_feature_1; + +ok_sfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_25G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_25G_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_25G_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_25G_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_25G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + case TRANSVR_CLASS_1G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_1G_SX; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_1G_LX; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_1G_EX; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_1G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_sfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_OPTICAL_25G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_S_AOC; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_OPTICAL_1G_AOC; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_COPPER_L1_25G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L1_10G; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_COPPER_L1_1G; + default: + return TRANSVR_CLASS_COPPER; + } + +ok_sfp_detect_class_by_feature_4_unknow: + return TRANSVR_CLASS_UNSPECIFIED; + +err_sfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +sft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _sfp_detect_class_by_extend_comp(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 10G Compliance */ + detect_val = _sfp_detect_class_by_10_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 1G Compliance */ + detect_val = _sfp_detect_class_by_1g_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_BASE_T_1000: + case TRANSVR_CLASS_OPTICAL_100: + /* + * ToDo: Need Check 0.1G + */ + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_COPPER_L1_10G: + /* Transfer speed case + * => Example: Raycom 10G DAC + */ + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 1G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check by connector, br, wavelength */ + detect_val = _sfp_detect_class_by_feature(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_OPTICAL_1G: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_COPPER: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_COPPER_L1_10G: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined get_connector:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sft_detect_transceiver_class_1; + +err_sft_detect_transceiver_class_1: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_trident2_if_type_1; + +err_sfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SR); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_KR); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_tomahawk_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_tomahawk_if_type_1; + +err_sfp_set_tomahawk_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_bf_tofino_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to BF looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_sfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = sft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _sfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TRIDENT_3: + case BCM_CHIP_TYPE_TOMAHAWK: + return _sfp_set_tomahawk_if_type(self, detect_cls, result); + + case BF_CHIP_TYPE_TOFINO: + return _sfp_set_bf_tofino_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_sfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = sft_detect_transvr_class(self); + switch(detect_val) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_SP_100); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + detect_val); + goto err_sfp_detect_if_speed_1; + } + /* Check by BR */ + detect_val = _sfp_detect_if_sp_by_br(self); + switch (detect_val) { + case TRANSVR_CLASS_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + default: + break; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_detect_if_speed_1; + +err_sfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_extended(self); + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_100G_AOC; + + case 0x06: /* 100G CWDM4 */ + case 0x09: /* Obsolete (assigned before 100G CWDM4 MSA required FEC) */ + case 0x17: /* 100G CLR4 */ + case 0x1A: /* 100GE-DWDM2 */ + return TRANSVR_CLASS_OPTICAL_100G; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_100G_SR4; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_100G_LR4; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_100G_ER4; + + case 0x07: /* 100G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_100G_PSM4; + + case 0x12: /* 40G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_40G; + + case 0x11: /* 4 x 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + + case 0x10: /* 40GBASE-ER4 */ + return TRANSVR_CLASS_OPTICAL_40G_ER4; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L4_100G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_class_by_10_40_100_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_10_40_100_ethernet(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 40G Optical */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 40G Active Cable (XLPPI) */ + return TRANSVR_CLASS_OPTICAL_40G_AOC; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 40GBASE-SR4 */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + } + if ( (detect_val & 0x02) == 0x02) { /* 00000010 : 40GBASE-LR4 */ + return TRANSVR_CLASS_OPTICAL_40G_LR4; + } + if ( (detect_val & 0x08) == 0x08) { /* 00001000 : 40GBASE-CR4 */ + return TRANSVR_CLASS_COPPER_L4_40G; + } + /* Case: 10G Optical */ + if ( (detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + } + /* Case: Extend Compliance */ + if ( ((detect_val & 0x80) == 0x80) ){ /* 10000000 : Use Extend Compliance */ + return TRANSVR_CLASS_EXTEND_COMP; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_10g = 0x10; + int upper_bound_10g = 0x25; + int lower_bound_40g = 0x60; + int upper_bound_40g = 0x75; + int lower_bound_100g = 0x60; + int upper_bound_100g = 0x75; + int used_extend_br = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + int extend_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 40G */ + if ((notmal_br >= lower_bound_40g) && + (notmal_br <= upper_bound_40g) ) { + return TRANSVR_CLASS_40G; + } + /* Check 100G */ + if (notmal_br == used_extend_br) { + extend_br = (int)(self->extbr); /* updated by update_all() */ + if ((extend_br >= lower_bound_100g) && + (extend_br <= upper_bound_100g) ) { + return TRANSVR_CLASS_100G; + } + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_qsfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int conn_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _qsfp_detect_if_sp_by_br(self); + conn_val = _qsfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 (Multifiber Parallel Optic) */ + case 0x0d: /* MPO 2x16 */ + goto ok_qsfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + goto ok_qsfp_detect_class_by_feature_4_copper; + case 0x23: /* No separable connector */ + if ((_qsfp_get_comp_fc_link_length(self) > 0) || + (_qsfp_get_comp_fc_trans_tech(self) > 0) || + (_qsfp_get_comp_fc_trans_media(self) > 0) || + (_qsfp_get_comp_fc_speed(self) > 0) ) { + goto ok_qsfp_detect_class_by_feature_4_aoc; + } + goto ok_qsfp_detect_class_by_feature_4_copper; + default: + snprintf(err_msg, sizeof(err_msg), + "_qsfp_get_connector_type return Non define value:%d", + conn_val); + goto err_qsfp_detect_class_by_feature_1; + } + return TRANSVR_CLASS_UNSPECIFIED; + +ok_qsfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_100G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_100G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_100G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_100G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_100G; + + case TRANSVR_CLASS_40G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_40G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_40G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_40G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_40G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_Q_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_OPTICAL_100G_AOC; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_OPTICAL_40G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_Q_AOC; + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_COPPER_L4_100G; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_COPPER_L4_40G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L4_10G; + default: + return TRANSVR_CLASS_COPPER; + } + +err_qsfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", + __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +qsft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _qsfp_detect_class_by_extend_comp(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_COPPER_L4_100G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check 10/40G/100G Ethernet Compliance */ + detect_val = _qsfp_detect_class_by_10_40_100_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_COPPER_L4_40G: + return detect_val; + case TRANSVR_CLASS_EXTEND_COMP: + /* Format incorrect case (We already checked the Extend + * Compliance is 0 + */ + snprintf(err_msg, sizeof(err_msg), + "Transceiver format incorrect"); + goto err_qsft_detect_transvr_class_1; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10/40/100:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check by Connector type, BR and wavelength */ + detect_val = _qsfp_detect_class_by_feature(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_COPPER_L4_100G: + case TRANSVR_CLASS_COPPER_L4_40G: + case TRANSVR_CLASS_COPPER_L4_10G: + case TRANSVR_CLASS_COPPER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined connector:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), + "Can not identify!"); + goto err_qsft_detect_transvr_class_1; + +err_qsft_detect_transvr_class_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: LR4 or LR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: /* Need Check: ER4 or ER */ + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_KR4); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_bf_tofino_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to BF looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_qsfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = qsft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _qsfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TRIDENT_3: + case BCM_CHIP_TYPE_TOMAHAWK: + return _qsfp_set_tomahawk_if_type(self, detect_cls, result); + + case BF_CHIP_TYPE_TOFINO: + return _qsfp_set_bf_tofino_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 8; + char tmp_result[8] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = qsft_detect_transvr_class(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G Copper */ + case TRANSVR_CLASS_COPPER_L4_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + break; + /* Copper */ + case TRANSVR_CLASS_COPPER: + break; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined class case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Check br and extbr */ + detect_val = _qsfp_detect_if_sp_by_br(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + case TRANSVR_CLASS_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined BR case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_detect_if_speed_1; + +err_qsfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_common_set_lane_map_str(struct transvr_obj_s* self, + char *result) { + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + char err_msg[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_L_STR); + snprintf(result, LEN_TRANSVR_L_STR, "%s=", TRANSVR_UEVENT_KEY_LANE); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + if (tmp_val > 256) { + snprintf(err_msg, sizeof(err_msg), + "detect abnormal value:%d", tmp_val); + goto err_common_set_lane_map_str_1; + } + memset(tmp_str, 0, sizeof(tmp_str)); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_L_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_L_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_L_STR); + } + if (i == 0) { + goto err_common_set_lane_map_str_2; + } + return 0; + +err_common_set_lane_map_str_1: + SWPS_INFO("%s: %s", __func__, err_msg); +err_common_set_lane_map_str_2: + snprintf(result, LEN_TRANSVR_L_STR, "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_common_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action, + int (*detect_if_type)(struct transvr_obj_s *self, char *result), + int (*detect_if_speed)(struct transvr_obj_s *self, char *result), + int send_anyway) { + + char *uevent_envp[4]; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + char tmp_str[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_1[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_2[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_3[64] = DEBUG_TRANSVR_STR_VAL; + + if (TRANSVR_UEVENT_ENABLE != 1) { + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_get_if_lane(self, tmp_str) < 0) { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + } else { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, tmp_str); + } + switch (u_action) { + case KOBJ_ADD: + /* Detect type */ + if (detect_if_type(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface type fail!"); + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, tmp_str); + uevent_envp[0] = tmp_str_1; + /* Detect speed */ + if (detect_if_speed(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface speed fail!"); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, tmp_str); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + case KOBJ_REMOVE: + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + default: + snprintf(err_msg, sizeof(err_msg), "kobject_action:%d not support", u_action); + goto private_common_send_uevent_4_fail; + } + snprintf(err_msg, sizeof(err_msg), "%s", "Exception case"); + goto private_common_send_uevent_4_fail; + +private_common_send_uevent_4_fail: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + if (send_anyway) { + goto private_common_send_uevent_4_send; + } + return ERR_TRANSVR_UEVENT_FAIL; + +private_common_send_uevent_4_send: + return kobject_uevent_env(&(self->transvr_dev_p->kobj), + u_action, + uevent_envp); +} + +int +sfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_sfp_detect_if_type, + &_sfp_detect_if_speed, + send_anyway); +} + + +int +qsfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_qsfp_detect_if_type, + &_qsfp_detect_if_speed, + send_anyway); +} + + +int +fake_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + + int err; + int detect_result[2]; + int current_state = STATE_TRANSVR_UNEXCEPTED; + int current_type = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_NEW) { + if (_transvr_init_handler(self) < 0){ + return ERR_TRANSVR_INIT_FAIL; + } + } + err = detect_transvr_state(self, detect_result); + if (err < 0) { + return err; + } + /* In Direct mode, driver only detect transceiver when user call driver interface + * which on sysfs. So it only need consider the state of Transceiver. + */ + current_state = detect_result[0]; + current_type = detect_result[1]; + + switch (current_state){ + + case STATE_TRANSVR_DISCONNECTED: /* Transceiver is not plugged */ + self->state = current_state; + self->type = current_type; + return ERR_TRANSVR_UNPLUGGED; + + case STATE_TRANSVR_INIT: /* Transceiver is plugged, system not ready */ + return ERR_TRANSVR_UNINIT; + + case STATE_TRANSVR_ISOLATED: /* Transceiver is plugged, but has some issues */ + return ERR_TRNASVR_BE_ISOLATED; + + case STATE_TRANSVR_CONNECTED: /* Transceiver is plugged, system is ready */ + self->state = current_state; + self->type = current_type; + return 0; + + case STATE_TRANSVR_SWAPPED: /* Transceiver is plugged, system detect user changed */ + self->type = current_type; + if (reload_transvr_obj(self, current_type) < 0){ + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + self->state = current_state; + return 0; + + case STATE_TRANSVR_UNEXCEPTED: /* Transceiver type or state is unexpected case */ + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_UNEXCPT; + + default: + SWPS_INFO("%s: state:%d not in define.\n", __func__, current_state); + break; + } + return ERR_TRANSVR_UNEXCPT; +} + + +static int +_is_except_happened_4_pmode(struct transvr_obj_s* self, + int new_state) { + + int event_chk = 0; + + if (self->temp == 0){ + return 0; + } + switch (new_state) { + case STATE_TRANSVR_INIT: + event_chk = EVENT_TRANSVR_EXCEP_INIT; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_CONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_UP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_DISCONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_DOWN; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_SWAPPED: + event_chk = EVENT_TRANSVR_EXCEP_SWAP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_UNEXCEPTED: + event_chk = EVENT_TRANSVR_EXCEP_EXCEP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_ISOLATED: + event_chk = EVENT_TRANSVR_EXCEP_ISOLATED; + goto check_event_happened_4_pmode; + + default: + SWPS_INFO("%s: unexcepted case:%d\n", __func__, new_state); + break; + } + return 0; + +check_event_happened_4_pmode: + if (self->temp == event_chk){ + return 1; + } + return 0; +} + + +int +common_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + /* [Return Value]: + * ERR_TRANSVR_UNINIT : (1) Initial not ready + * ERR_TRANSVR_UNPLUGGED : (1) Any -> Down + * ERR_TRANSVR_TASK_BUSY : (1) Wait Initial task + * ERR_TRANSVR_UNEXCPT : (1) Initial fail + * (2) Task fail + * (3) Reload fail + * ERR_TRNASVR_BE_ISOLATED : (1) Already be isolated + * OK Case (return 0) : (1) action_4_connected + * (2) action_4_nothing (initial retry) + */ + int curr_state[2]; + int old_state = self->state; + int old_type = self->type; + int new_state = STATE_TRANSVR_UNEXCEPTED; + int new_type = TRANSVR_TYPE_ERROR; + int return_val = ERR_TRANSVR_UNEXCPT; + + /* Never initial */ + if (self->state == STATE_TRANSVR_NEW) { + goto comfsm_action_4_reinit_obj; + } + /* Detect current state */ + switch (detect_transvr_state(self, curr_state)) { + case 0: + new_state = curr_state[0]; + new_type = curr_state[1]; + break; + + case ERR_TRNASVR_BE_ISOLATED: + new_state = STATE_TRANSVR_ISOLATED; + new_type = old_type; + break; + + case ERR_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case ERR_TRANSVR_UNEXCPT: + default: + new_state = STATE_TRANSVR_UNEXCEPTED; + new_type = old_type; + } + /* State handling */ + switch (old_state) { + case STATE_TRANSVR_INIT: /* INIT -> */ + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 1-1: UP -> INIT */ + SWPS_INFO("Detect %s is present. :1-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 1-2: UP -> UP */ + return_val = 0; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 1-3: UP -> DOWN */ + SWPS_INFO("Detect %s is removed. :1-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 1-4: UP -> SWAP */ + SWPS_INFO("Detect %s is swapped. :1-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 1-5: UP -> UNEXPET */ + SWPS_INFO("Detect %s has error. :1-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 1-6: UP -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :1-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_DISCONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 2-1: DOWN -> INIT */ + SWPS_INFO("Detect %s is present. :2-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 2-2: DOWN -> UP */ + SWPS_INFO("Detect %s is present. :2-2\n",self->swp_name); + goto comfsm_action_4_reinit_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 2-3: DOWN -> DOWN */ + return_val = ERR_TRANSVR_UNPLUGGED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_SWAPPED: /* Case 2-4: DOWN -> SWAP */ + SWPS_INFO("Detect %s is swapped. :2-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 2-5: DOWN -> UNEXPET */ + SWPS_INFO("Detect %s has error. :2-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 2-6: DOWN -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :2-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_UNEXCEPTED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 3-1: UNEXPET -> INIT */ + SWPS_INFO("Detect %s is present. :3-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 3-2: UNEXPET -> UP */ + SWPS_INFO("Detect %s is present. :3-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 3-3: UNEXPET -> DOWN */ + SWPS_INFO("Detect %s is removed. :3-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 3-4: UNEXPET -> SWAP */ + SWPS_INFO("Detect %s is swapped. :3-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 3-5: UNEXPET -> UNEXPET */ + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRANSVR_UNEXCPT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 3-6: UNEXPET -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :3-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 4-1: ISOLATE -> INIT */ + SWPS_INFO("Detect %s internal error. :4-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 4-2: ISOLATE -> UP */ + SWPS_INFO("Detect %s internal error. :4-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 4-3: ISOLATE -> DOWN */ + SWPS_INFO("Detect %s is removed. :4-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 4-4: ISOLATE -> SWAP */ + SWPS_INFO("Detect %s internal error. :4-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 4-5: ISOLATE -> UNEXPET */ + SWPS_INFO("Detect %s internal error. :4-5\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 4-6: ISOLATE -> ISOLATE */ + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + default: + break; + } + goto comfsm_action_4_unexpected; + + default: + break; + } + goto comfsm_action_4_unexpected; + + +comfsm_action_4_keep_state: + return return_val; + +comfsm_action_4_reinit_obj: + SWPS_DEBUG("FSM action: %s re-initial.\n", self->swp_name); + return_val = _transvr_init_handler(self); + goto comfsm_action_4_identify_event; + +comfsm_action_4_reload_obj: + SWPS_DEBUG("FSM action: %s reload.\n", self->swp_name); + self->type = new_type; + return_val = reload_transvr_obj(self, new_type); + goto comfsm_action_4_identify_event; + +comfsm_action_4_identify_event: + switch (return_val) { + case EVENT_TRANSVR_INIT_UP: + case EVENT_TRANSVR_TASK_DONE: + goto comfsm_action_4_connected; + + case EVENT_TRANSVR_INIT_DOWN: + goto comfsm_action_4_disconnected; + + case EVENT_TRANSVR_INIT_REINIT: + goto comfsm_action_4_nothing; + + case EVENT_TRANSVR_TASK_WAIT: + self->state = STATE_TRANSVR_INIT; + return ERR_TRANSVR_TASK_BUSY; + + case EVENT_TRANSVR_TASK_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_TASK_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_INIT_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_INIT_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_RELOAD_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_RELOAD_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case EVENT_TRANSVR_EXCEP_ISOLATED: + goto comfsm_action_4_isolate_obj; + + default: + SWPS_INFO("%s detect undefined event:%d.\n", self->swp_name, return_val); + goto comfsm_action_4_unexpected; + } + +comfsm_action_4_nothing: + SWPS_DEBUG("FSM action: %s do nothing.\n", self->swp_name); + return 0; + +comfsm_action_4_connected: + SWPS_DEBUG("FSM action: %s Connected.\n", self->swp_name); + self->state = STATE_TRANSVR_CONNECTED; + self->type = new_type; + self->send_uevent(self, KOBJ_ADD); + _transvr_clean_retry(self); + return 0; + +comfsm_action_4_disconnected: + SWPS_DEBUG("FSM action: %s Disconnected. \n", self->swp_name); + self->state = STATE_TRANSVR_DISCONNECTED; + self->temp = EVENT_TRANSVR_TASK_DONE; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_retry(self); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNPLUGGED; + +comfsm_action_4_report_i2c_crash: + SWPS_DEBUG("FSM action: %s report I2C crash.\n", self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_I2C_CRASH; + +comfsm_action_4_isolate_obj: + SWPS_DEBUG("FSM action: %s isolate.\n", self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return ERR_TRNASVR_BE_ISOLATED; + +comfsm_action_4_unexpected: + SWPS_INFO("FSM action: %s unexpected.\n", self->swp_name); + SWPS_INFO("Dump: :%d :0x%02x :%d :0x%02x\n", + old_state, old_type, new_state, new_type); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNEXCPT; +} + + +int +fake_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +int +fake_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +/* ========== Object functions for Initial procedure ========== + */ +int +transvr_init_common(struct transvr_obj_s *self){ + /* Nothing to update */ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_fake(struct transvr_obj_s *self){ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_sfp(struct transvr_obj_s *self){ + + int tmp_val = DEBUG_TRANSVR_INT_VAL; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_msg = "ERR"; + + self->info = sft_detect_transvr_class(self); + /* Disable auto_config */ + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + /* Handle multi-rate */ + err_code = initfunc_sfp_handle_multi_rate_mode(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_multi_rate_mode fail!"; + goto err_transvr_init_sfp_1; + } + /* Handle 1G- RJ45 */ + tmp_val = err_code; + err_code = initfunc_sfp_handle_1g_rj45(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_1g_rj45 fail!"; + goto err_transvr_init_sfp_1; + } + tmp_val = (tmp_val > err_code ? tmp_val : err_code); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_sfp_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_code, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp(struct transvr_obj_s *self){ + + int err = EVENT_TRANSVR_EXCEP_EXCEP; + char *emsg = "ERR"; + + self->info = qsft_detect_transvr_class(self); + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + err = initfunc_qsfp_handle_power_mode(self); + if (err < 0){ + emsg = "initfunc_qsfp_handle_tx_disable fail!"; + goto err_transvr_init_qsfp; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, emsg, err, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp28(struct transvr_obj_s *self){ + + int tmp_val = EVENT_TRANSVR_EXCEP_EXCEP; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_msg = "ERR"; + + /* Handle QSFP common */ + err_val = transvr_init_qsfp(self); + if (err_val < 0){ + err_msg = "transvr_init_qsfp fail!"; + goto err_transvr_init_qsfp28_1; + } + /* Disable auto_config */ + if (!self->auto_config) { + return err_val; + } + /* Handle CDR */ + tmp_val = err_val; + err_val = initfunc_qsfp28_handle_cdr(self); + if (err_val < 0){ + err_msg = "Handle CDR fail!"; + goto err_transvr_init_qsfp28_1; + } + tmp_val = (tmp_val > err_val ? tmp_val : err_val); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp28_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== Object Initial handler ========== + */ +static int +_is_transvr_valid(struct transvr_obj_s *self, + int type, + int state) { + /* [Return] + * 0 : OK, inserted + * EVENT_TRANSVR_INIT_DOWN : OK, removed + * EVENT_TRANSVR_INIT_FAIL : Outside error, type doesn't supported + * EVENT_TRANSVR_EXCEP_INIT : Internal error, state undefined + */ + switch (type) { + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + break; + default: + SWPS_INFO("detect undefined type:0x%02x on %s\n", + type, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; + } + switch (state) { + case STATE_TRANSVR_DISCONNECTED: + return EVENT_TRANSVR_INIT_DOWN; + case STATE_TRANSVR_INIT: + case STATE_TRANSVR_CONNECTED: + case STATE_TRANSVR_SWAPPED: + break; + default: + SWPS_INFO("detect undefined state:%d on %s\n", + state, self->swp_name); + return EVENT_TRANSVR_EXCEP_INIT; + } + return 0; +} + + +static int +_is_transvr_hw_ready(struct transvr_obj_s *self, + int type){ + /* [Return] + * EVENT_TRANSVR_TASK_DONE : Ready + * EVENT_TRANSVR_TASK_WAIT : Not ready + * EVENT_TRANSVR_INIT_FAIL : Error + */ + int addr = DEBUG_TRANSVR_INT_VAL; + int page = DEBUG_TRANSVR_INT_VAL; + int offs = DEBUG_TRANSVR_INT_VAL; + int bit = DEBUG_TRANSVR_INT_VAL; + int ready = DEBUG_TRANSVR_INT_VAL; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t ab_val = DEBUG_TRANSVR_HEX_VAL; + + switch (type) { + case TRANSVR_TYPE_SFP: + addr = VAL_TRANSVR_8472_READY_ADDR; + page = VAL_TRANSVR_8472_READY_PAGE; + offs = VAL_TRANSVR_8472_READY_OFFSET; + bit = VAL_TRANSVR_8472_READY_BIT; + ready = VAL_TRANSVR_8472_READY_VALUE; + ab_val = VAL_TRANSVR_8472_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + addr = VAL_TRANSVR_8436_READY_ADDR; + page = VAL_TRANSVR_8436_READY_PAGE; + offs = VAL_TRANSVR_8436_READY_OFFSET; + bit = VAL_TRANSVR_8436_READY_BIT; + ready = VAL_TRANSVR_8436_READY_VALUE; + ab_val = VAL_TRANSVR_8436_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + return EVENT_TRANSVR_TASK_DONE; + + default: + emsg = "unexpected case"; + goto err_is_transvr_hw_ready; + } + /* Select target page */ + err = _common_setup_page(self, addr, page, offs, 1, 0); + if (err < 0) { + emsg = "setup page fail"; + goto err_is_transvr_hw_ready; + } + /* Check feature supported + * [Note] + * Some of transceiver/cables doesn't support "Status Indicators" + * (ex:DAC, RJ45 copper SFP ...etc). In these case, we bypass the + * step of checking Status Indicators, then state machine will take + * the following handle procedure. + */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (err < 0) { + emsg = "doesn't support Status Indicators"; + goto bypass_is_transvr_hw_ready; + } + /* Filter abnormal case */ + if (err == ab_val) { + emsg = "detect using unusual definition."; + goto bypass_is_transvr_hw_ready; + } + /* Get Status Indicators */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, offs); + if (err < 0) { + emsg = "detect current value fail"; + goto err_is_transvr_hw_ready; + } + if ((err & (1<:%d\n", __func__, emsg, type); + return EVENT_TRANSVR_TASK_DONE; + +err_is_transvr_hw_ready: + SWPS_DEBUG("%s: %s :%d\n", __func__, emsg, type); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_is_transvr_support_ctle(struct transvr_obj_s *self) { + + switch (self->info) { + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return 1; + default: + break; + } + return 0; +} + + +static int +_transvr_init_handler(struct transvr_obj_s *self){ + + int detect[2]; + int d_state = STATE_TRANSVR_UNEXCEPTED; + int d_type = TRANSVR_TYPE_ERROR; + int result = ERR_TRANSVR_UNINIT; + int retry = 6; /* (6+1) x 0.3 = 2.1s > spec:2.0s */ + int elimit = 63; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Clean and check callback */ + self->state = STATE_TRANSVR_INIT; + if (self->init == NULL) { + snprintf(emsg, elimit, "init() is null"); + goto initer_err_case_unexcept_0; + } + if (self->clean == NULL) { + snprintf(emsg, elimit, "clean() is null"); + goto initer_err_case_unexcept_0; + } + self->clean(self); + + /* Detect transceiver information */ + result = detect_transvr_state(self, detect); + if (result < 0) { + snprintf(emsg, elimit, "detect_transvr_state() fail"); + switch (result) { + case ERR_TRANSVR_I2C_CRASH: + goto initer_err_case_i2c_ceash; + case ERR_TRNASVR_BE_ISOLATED: + goto initer_err_case_be_isolated; + + case ERR_TRANSVR_UNEXCPT: + default: + break; + } + goto initer_err_case_retry_1; + } + d_state = detect[0]; + d_type = detect[1]; + + /* Verify transceiver type and state */ + switch (_is_transvr_valid(self, d_type, d_state)) { + case 0: + break; + case EVENT_TRANSVR_INIT_DOWN: + goto initer_ok_case_down;; + case EVENT_TRANSVR_INIT_FAIL: + snprintf(emsg, elimit, "transceiver type doesn't support"); + goto initer_err_case_alarm_to_user; + case EVENT_TRANSVR_EXCEP_INIT: + default: + goto initer_err_case_unexcept_1; + } + + /* Handle reload case */ + if (self->type != d_type){ + /* This is the protect mechanism. Normally, This case will not happen. + * When State machine detect swap event during initial, It will trigger + * reload function to ensure type correct. */ + if (_reload_transvr_obj(self, d_type) < 0){ + snprintf(emsg, elimit, "reload object fail"); + goto initer_err_case_unexcept_1; + } + } + + /* Check transceiver HW initial ready */ + switch (_is_transvr_hw_ready(self, d_type)) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_err_case_retry_1; + case EVENT_TRANSVR_INIT_FAIL: + default: + goto initer_err_case_unexcept_1; + } + + /* Try to update all and check */ + if (self->update_all(self, 1) < 0){ + /* For some transceiver, EEPROME has lag issues during initial stage. + * In this case, we set status back to STATE_TRANSVR_NEW, than it will + * be checked in next polling cycle. */ + goto initer_err_case_retry_1; + } + + /* Execute init() call back */ + result = self->init(self); + switch (result) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_ok_case_wait; + + default: + snprintf(emsg, elimit, "undefined init() return:%d\n", result); + goto initer_err_case_unexcept_1; + } + goto initer_ok_case_up; + + +initer_ok_case_wait: + self->dump_all(self); + return EVENT_TRANSVR_TASK_WAIT; + +initer_ok_case_up: + self->state = STATE_TRANSVR_CONNECTED; + self->temp = 0; + self->dump_all(self); + return EVENT_TRANSVR_INIT_UP; + +initer_ok_case_down: + self->temp = 0; + self->state = STATE_TRANSVR_DISCONNECTED; + return EVENT_TRANSVR_INIT_DOWN; + +initer_err_case_i2c_ceash: + SWPS_DEBUG("%s: %s :%s :I2C crash\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_I2C_CRASH; + +initer_err_case_be_isolated: + SWPS_DEBUG("%s: %s :%s :isolated\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return EVENT_TRANSVR_EXCEP_ISOLATED; + +initer_err_case_retry_1: + SWPS_DEBUG("%s: %s :%s :retry\n", + __func__, emsg, self->swp_name); + if (_transvr_handle_retry(self, retry) == 0) { + self->state = STATE_TRANSVR_NEW; + return EVENT_TRANSVR_INIT_REINIT; + } + goto initer_err_case_alarm_to_user; + +initer_err_case_unexcept_1: + self->clean(self); +initer_err_case_unexcept_0: + self->state = STATE_TRANSVR_UNEXCEPTED; + if (_is_except_happened_4_pmode(self, d_state) && + (self->mode == TRANSVR_MODE_POLLING) ){ + SWPS_INFO("%s: %s :%s\n", __func__, emsg, self->swp_name); + SWPS_INFO("Dump: :%d :%d :%d :%d\n", + self->state, self->type, d_state, d_type); + } + return EVENT_TRANSVR_INIT_FAIL; + +initer_err_case_alarm_to_user: + SWPS_DEBUG("%s: %s :%s :alarm_to_user\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard"); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== Object functions for Clean procedure ========== + */ +int +_transvr_clean_handler(struct transvr_obj_s *self){ + + int retval = DEBUG_TRANSVR_INT_VAL; + + if (!self->clean) { + SWPS_ERR("%s: %s clean() is NULL.\n", + __func__, self->swp_name); + return EVENT_TRANSVR_TASK_FAIL; + } + retval = self->clean(self); + if (retval != EVENT_TRANSVR_TASK_DONE){ + SWPS_ERR("%s: %s clean() fail. [ERR]:%d\n", + __func__, self->swp_name, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_transvr_clean(struct transvr_obj_s *self){ + + transvr_task_free_all(self); + transvr_cache_free_all(self); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +qsfp_transvr_clean(struct transvr_obj_s *self){ + + int retval; + int lpower_config = 1; + + retval = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (retval < 0){ + SWPS_ERR("%s: Set lpmod fail! :%d\n", + __func__, retval); + return retval; + } + retval = common_transvr_clean(self); + if (retval < 0){ + SWPS_ERR("%s: common_transvr_clean fail! :%d\n", + __func__, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +fake_transvr_clean(struct transvr_obj_s *self){ + + return EVENT_TRANSVR_TASK_DONE; +} + + +/* ========== Object functions for check and update ========== + */ +int +common_transvr_check(struct transvr_obj_s *self){ + + char fun_str[32] = "common_transvr_check"; + + if (self->mode != TRANSVR_MODE_POLLING) { + SWPS_ERR("%s: mode:%d is not TRANSVR_MODE_POLLING\n", + fun_str, self->mode); + return ERR_TRANSVR_UNEXCPT; + } + /* Trigger delay task */ + transvr_task_run_all(self); + /* Trigger state machine to check and update */ + return self->fsm_4_polling(self, fun_str); +} + + +int +fake_transvr_check(struct transvr_obj_s *self){ + return 0; +} + + +/* ========== Functions for Factory pattern ========== + */ +static int +setup_transvr_public_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = unsupported_get_func; + self->get_br = common_get_br; + self->get_len_sm = sfp_get_len_sm; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = sfp_get_comp_eth_1; + self->get_comp_eth_10 = sfp_get_comp_eth_10; + self->get_comp_eth_10_40 = unsupported_get_func; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = sfp_get_rate_id; + self->get_soft_rs0 = sfp_get_soft_rs0; + self->get_soft_rs1 = sfp_get_soft_rs1; + self->get_info = common_get_info; + self->get_if_type = sfp_get_if_type; + self->get_if_speed = sfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = sfp_get_transvr_temp; + self->get_curr_vol = sfp_get_transvr_voltage; + self->get_soft_rx_los = unsupported_get_func2; + self->get_soft_tx_disable = unsupported_get_func2; + self->get_soft_tx_fault = unsupported_get_func2; + self->get_auto_tx_disable = unsupported_get_func2; + self->get_tx_bias = sfp_get_transvr_tx_bias; + self->get_tx_power = sfp_get_transvr_tx_power; + self->get_rx_power = sfp_get_transvr_rx_power; + self->get_tx_eq = sfp_get_transvr_tx_eq; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = sfp_get_transvr_rx_em; + self->get_wavelength = sfp_get_wavelength; + self->get_extphy_offset = sfp_get_1g_rj45_extphy_offset; + self->get_extphy_reg = sfp_get_1g_rj45_extphy_reg; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = sfp_set_soft_rs0; + self->set_soft_rs1 = sfp_set_soft_rs1; + self->set_soft_tx_disable = unsupported_set_func; + self->set_auto_tx_disable = unsupported_set_func; + self->set_tx_eq = sfp_set_tx_eq; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = sfp_set_rx_em; + self->set_extphy_offset = sfp_set_1g_rj45_extphy_offset; + self->set_extphy_reg = sfp_set_1g_rj45_extphy_reg; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = unsupported_get_func2; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = unsupported_get_func2; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = unsupported_set_func; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = unsupported_set_func; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = qsfp_get_cdr; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = qsfp_get_transvr_tx_eq; + self->get_rx_am = qsfp_get_transvr_rx_am; + self->get_rx_em = qsfp_get_transvr_rx_em; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = qsfp_set_cdr; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = qsfp_set_tx_eq; + self->set_rx_am = qsfp_set_rx_am; + self->set_rx_em = qsfp_set_rx_em; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_FAKE: + self->get_id = fake_get_hex; + self->get_ext_id = fake_get_hex; + self->get_connector = fake_get_hex; + self->get_vendor_name = fake_get_str; + self->get_vendor_pn = fake_get_str; + self->get_vendor_rev = fake_get_str; + self->get_vendor_sn = fake_get_str; + self->get_power_cls = fake_get_int; + self->get_br = fake_get_hex; + self->get_len_sm = fake_get_int; + self->get_len_smf = fake_get_int; + self->get_len_om1 = fake_get_int; + self->get_len_om2 = fake_get_int; + self->get_len_om3 = fake_get_int; + self->get_len_om4 = fake_get_int; + self->get_comp_rev = fake_get_hex; + self->get_comp_eth_1 = fake_get_hex; + self->get_comp_eth_10 = fake_get_hex; + self->get_comp_eth_10_40 = fake_get_hex; + self->get_comp_extend = fake_get_hex; + self->get_cdr = fake_get_hex; + self->get_rate_id = fake_get_hex; + self->get_soft_rs0 = fake_get_binary; + self->get_soft_rs1 = fake_get_binary; + self->get_info = fake_get_int; + self->get_if_type = fake_get_str; + self->get_if_speed = fake_get_str; + self->get_if_lane = fake_get_str; + self->get_curr_temp = fake_get_str; + self->get_curr_vol = fake_get_str; + self->get_soft_rx_los = fake_get_str; + self->get_soft_tx_disable = fake_get_str; + self->get_soft_tx_fault = fake_get_str; + self->get_auto_tx_disable = fake_get_str; + self->get_tx_bias = fake_get_str; + self->get_tx_power = fake_get_str; + self->get_rx_power = fake_get_str; + self->get_tx_eq = fake_get_str; + self->get_rx_am = fake_get_str; + self->get_rx_em = fake_get_str; + self->get_wavelength = fake_get_str; + self->get_extphy_offset = fake_get_str; + self->get_extphy_reg = fake_get_str; + self->set_cdr = fake_set_hex; + self->set_soft_rs0 = fake_set_int; + self->set_soft_rs1 = fake_set_int; + self->set_soft_tx_disable = fake_set_int; + self->set_auto_tx_disable = fake_set_int; + self->set_tx_eq = fake_set_int; + self->set_rx_am = fake_set_int; + self->set_rx_em = fake_set_int; + self->set_extphy_offset = fake_set_hex; + self->set_extphy_reg = fake_set_hex; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_transvr_private_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->init = transvr_init_sfp; + self->clean = common_transvr_clean; + self->check = common_transvr_check; + self->update_all = _sfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = sfp_send_uevent; + self->dump_all = sfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->init = transvr_init_qsfp; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->init = transvr_init_qsfp28; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_FAKE: + self->init = transvr_init_fake; + self->clean = fake_transvr_clean; + self->check = fake_transvr_check; + self->update_all = fake_transvr_update; + self->fsm_4_direct = fake_fsm_4_direct_mode; + self->fsm_4_polling = fake_fsm_4_polling_mode; + self->send_uevent = fake_send_uevent; + self->dump_all = fake_transvr_dump; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static struct eeprom_map_s * +get_eeprom_map(int transvr_type){ + + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + return &eeprom_map_sfp; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + return &eeprom_map_qsfp; + case TRANSVR_TYPE_QSFP_28: + return &eeprom_map_qsfp28; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return NULL; +} + + +static int +setup_transvr_ssize_attr(char *swp_name, + struct transvr_obj_s *self, + struct eeprom_map_s *map_p, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int chan_id, + int run_mode){ + switch (run_mode){ + case TRANSVR_MODE_DIRECT: /* Direct access device mode */ + case TRANSVR_MODE_POLLING: /* Polling mode, read from cache */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = DEBUG_TRANSVR_INT_VAL; + return -1; + } + self->eeprom_map_p = map_p; + self->ioexp_obj_p = ioexp_obj_p; + self->ioexp_virt_offset = ioexp_virt_offset; + self->chan_id = chan_id; + self->layout = transvr_type; + self->type = transvr_type; + self->chipset_type = chipset_type; + self->state = STATE_TRANSVR_NEW; + self->info = STATE_TRANSVR_NEW; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + strncpy(self->swp_name, swp_name, 32); + mutex_init(&self->lock); + return 0; +} + + +static int +setup_transvr_dsize_attr(struct transvr_obj_s *self){ + + char *emsg = DEBUG_TRANSVR_STR_VAL; + + self->vendor_name = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_name){ + emsg = "vendor_name"; + goto err_setup_d_attr; + } + self->vendor_pn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_pn){ + emsg = "vendor_pn"; + goto err_setup_d_attr; + } + self->vendor_rev = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_rev){ + emsg = "vendor_rev"; + goto err_setup_d_attr; + } + self->vendor_sn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_sn){ + emsg = "vendor_sn"; + goto err_setup_d_attr; + } + self->worker_p = NULL; + return 0; + +err_setup_d_attr: + SWPS_ERR("%s: %s kzalloc fail!", __func__, emsg); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_i2c_client(struct transvr_obj_s *self){ + + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + adap = i2c_get_adapter(self->chan_id); + if(!adap){ + snprintf(err_msg, sizeof(err_msg), + "can not get adap:%d", self->chan_id); + goto err_setup_i2c_client; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + snprintf(err_msg, sizeof(err_msg), + "can not kzalloc client:%d", self->chan_id); + goto err_setup_i2c_client; + } + client->adapter = adap; + self->i2c_client_p = client; + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + return 0; + +err_setup_i2c_client: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return ERR_TRANSVR_UNEXCPT; +} + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode){ + + struct transvr_obj_s *result_p; + struct eeprom_map_s *map_p; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Allocate transceiver object */ + map_p = get_eeprom_map(transvr_type); + if (!map_p){ + snprintf(err_msg, sizeof(err_msg), + "Invalid transvr_type:%d", transvr_type); + goto err_create_transvr_fail; + } + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_create_transvr_fail; + } + /* Prepare static size attributes */ + if (setup_transvr_ssize_attr(swp_name, + result_p, + map_p, + ioexp_obj_p, + ioexp_virt_offset, + transvr_type, + chipset_type, + chan_id, + run_mode) < 0){ + goto err_create_transvr_sattr_fail; + } + /* Prepare dynamic size attributes */ + if (setup_transvr_dsize_attr(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_public_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_private_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare i2c client object */ + if (setup_i2c_client(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + return result_p; + +err_create_transvr_dattr_fail: + kfree(result_p->vendor_sn); + kfree(result_p->vendor_rev); + kfree(result_p->vendor_pn); + kfree(result_p->vendor_name); +err_create_transvr_sattr_fail: + kfree(result_p); +err_create_transvr_fail: + SWPS_ERR("%s: %s :%d :%d :%d\n", + __func__, err_msg, chan_id, ioexp_virt_offset, transvr_type); + return NULL; +} +EXPORT_SYMBOL(create_transvr_obj); + + +static int +_reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + struct eeprom_map_s *new_map_p; + struct eeprom_map_s *old_map_p = self->eeprom_map_p; + struct i2c_client *old_i2c_p = self->i2c_client_p; + int old_type = self->type; + + /* Change state to STATE_TRANSVR_INIT */ + self->state = STATE_TRANSVR_INIT; + self->type = new_type; + /* Replace EEPROME map */ + new_map_p = get_eeprom_map(new_type); + if (!new_map_p){ + goto err_private_reload_func_1; + } + self->eeprom_map_p = new_map_p; + /* Reload i2c client */ + if (setup_i2c_client(self) < 0){ + goto err_private_reload_func_2; + } + /* Replace call back functions */ + if (setup_transvr_public_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + if (setup_transvr_private_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + if(old_i2c_p){ + i2c_put_adapter(old_i2c_p->adapter); + } + kfree(old_i2c_p); + return 0; + +err_private_reload_func_3: + SWPS_INFO("%s: init() fail!\n", __func__); + if(old_i2c_p){ + i2c_put_adapter(old_i2c_p->adapter); + } + kfree(old_i2c_p); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return -2; + +err_private_reload_func_2: + self->eeprom_map_p = old_map_p; + self->i2c_client_p = old_i2c_p; +err_private_reload_func_1: + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = old_type; + SWPS_INFO("%s fail! :0x%02x\n", __func__, new_type); + return -1; +} + + +static int +reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + int result_val = ERR_TRANSVR_UNEXCPT; + + /* Reload phase */ + result_val = _reload_transvr_obj(self, new_type); + if (result_val < 0){ + SWPS_INFO("%s: reload phase fail! :%d\n", + __func__, result_val); + return EVENT_TRANSVR_RELOAD_FAIL; + } + /* Initial phase */ + result_val = _transvr_init_handler(self); + if (result_val < 0){ + SWPS_INFO("%s: initial phase fail! :%d\n", + __func__, result_val); + } + return result_val; +} + + +int +isolate_transvr_obj(struct transvr_obj_s *self) { + + self->state = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s be isolated\n", __func__, self->swp_name); + return 0; +} +EXPORT_SYMBOL(isolate_transvr_obj); + + +int +resync_channel_tier_2(struct transvr_obj_s *self) { + + int val = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_ISOLATED) { + return 0; + } + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + val = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (val < 0) { + return -1; + } + return 0; +} +EXPORT_SYMBOL(resync_channel_tier_2); + +/* For build single module using (Ex: ONL platform) */ +MODULE_LICENSE("GPL"); + + +/* ----------------------------------------- + * ToDo List + * ----------------------------------------- + * 1. _sfp_detect_class_by_feature() + * => Need check ACC use case. + * 2. _sfp_detect_class_by_1g_ethernet() + * => Need check 0.1G use case. + * 3. Loopback transceiver use case. + * => Less much data + * 4. _qsfp_detect_class_by_extend_comp() + * => Verify 100G CWDM4 + * => Verify Obsolete (assigned before 100G CWDM4 MSA required FEC) + * => Verify 100G CLR4 + * => Verify 100GE-DWDM2 + * => Verify 40G PSM4 Parallel SMF + * => Verify 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. + * => Verify 100G ACC or 25GAUI C2M ACC. + * => Verify 25GBASE-LR + * => Verify 40G Active Cable (XLPPI) + */ + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.h new file mode 100644 index 000000000000..0438a351271a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.h @@ -0,0 +1,809 @@ +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* advanced features control */ +#define TRANSVR_INFO_DUMP_ENABLE (1) +#define TRANSVR_INFO_CACHE_ENABLE (1) +#define TRANSVR_UEVENT_ENABLE (1) + +/* Transceiver type define */ +#define TRANSVR_TYPE_UNKNOW_1 (0x00) +#define TRANSVR_TYPE_UNKNOW_2 (0xff) +#define TRANSVR_TYPE_SFP (0x03) /* Define for SFP, SFP+, SFP28 */ +#define TRANSVR_TYPE_QSFP (0x0c) +#define TRANSVR_TYPE_QSFP_PLUS (0x0d) +#define TRANSVR_TYPE_QSFP_28 (0x11) +#define TRANSVR_TYPE_UNPLUGGED (0xfa) /* Define for ERROR handle */ +#define TRANSVR_TYPE_FAKE (0xfc) /* Define for ERROR handle */ +#define TRANSVR_TYPE_INCONSISTENT (0xfd) /* Define for ERROR handle */ +#define TRANSVR_TYPE_ERROR (0xfe) /* Define for ERROR handle */ + +/* Transceiver class for base info */ +#define TRANSVR_CLASS_UNSPECIFIED (0) +#define TRANSVR_CLASS_ERROR (-26001) +#define TRANSVR_CLASS_1G (26001) +#define TRANSVR_CLASS_10G (26011) +#define TRANSVR_CLASS_25G (26021) +#define TRANSVR_CLASS_40G (26041) +#define TRANSVR_CLASS_100G (26101) +#define TRANSVR_CLASS_NO_SPERARABLE (26901) +#define TRANSVR_CLASS_EXTEND_COMP (26902) +/* Transceiver class for Optical 1G */ +#define TRANSVR_CLASS_OPTICAL (27000) +#define TRANSVR_CLASS_OPTICAL_100 (27001) +#define TRANSVR_CLASS_OPTICAL_1G (27002) +#define TRANSVR_CLASS_OPTICAL_1G_AOC (27003) +#define TRANSVR_CLASS_OPTICAL_1G_SX (27004) +#define TRANSVR_CLASS_OPTICAL_1G_LX (27005) +#define TRANSVR_CLASS_OPTICAL_1G_EX (27006) +/* Transceiver class for Optical 10G */ +#define TRANSVR_CLASS_OPTICAL_10G (27010) +#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011) +#define TRANSVR_CLASS_OPTICAL_10G_S_SR (27012) +#define TRANSVR_CLASS_OPTICAL_10G_S_LR (27013) +#define TRANSVR_CLASS_OPTICAL_10G_S_ER (27014) +#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015) +#define TRANSVR_CLASS_OPTICAL_10G_Q_SR (27016) +#define TRANSVR_CLASS_OPTICAL_10G_Q_LR (27017) +#define TRANSVR_CLASS_OPTICAL_10G_Q_ER (27018) +/* Transceiver class for Optical 25G */ +#define TRANSVR_CLASS_OPTICAL_25G (27020) +#define TRANSVR_CLASS_OPTICAL_25G_AOC (27021) +#define TRANSVR_CLASS_OPTICAL_25G_SR (27022) +#define TRANSVR_CLASS_OPTICAL_25G_LR (27023) +#define TRANSVR_CLASS_OPTICAL_25G_ER (27024) +/* Transceiver class for Optical 40G */ +#define TRANSVR_CLASS_OPTICAL_40G (27040) +#define TRANSVR_CLASS_OPTICAL_40G_AOC (27041) +#define TRANSVR_CLASS_OPTICAL_40G_SR4 (27042) +#define TRANSVR_CLASS_OPTICAL_40G_LR4 (27043) +#define TRANSVR_CLASS_OPTICAL_40G_ER4 (27044) +/* Transceiver class for Optical 100G */ +#define TRANSVR_CLASS_OPTICAL_100G (27100) +#define TRANSVR_CLASS_OPTICAL_100G_AOC (27101) +#define TRANSVR_CLASS_OPTICAL_100G_SR4 (27102) +#define TRANSVR_CLASS_OPTICAL_100G_LR4 (27103) +#define TRANSVR_CLASS_OPTICAL_100G_ER4 (27104) +#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105) +/* Transceiver class for Copper */ +#define TRANSVR_CLASS_COPPER (28000) +#define TRANSVR_CLASS_COPPER_L1_1G (28001) +#define TRANSVR_CLASS_COPPER_L1_10G (28011) +#define TRANSVR_CLASS_COPPER_L4_10G (28012) +#define TRANSVR_CLASS_COPPER_L1_25G (28021) +#define TRANSVR_CLASS_COPPER_L4_40G (28041) +#define TRANSVR_CLASS_COPPER_L4_100G (28101) +/* Transceiver class for Base-T */ +#define TRANSVR_CLASS_BASE_T_1000 (29001) +#define TRANSVR_CLASS_BASE_T_1000_up (29002) +/* For uevent message */ +#define TRANSVR_UEVENT_KEY_IF "IF_TYPE" +#define TRANSVR_UEVENT_KEY_SP "IF_SPEED" +#define TRANSVR_UEVENT_KEY_LANE "IF_LANE" +#define TRANSVR_UEVENT_UNKNOW "UNKNOW" +#define TRANSVR_IF_KR "KR" +#define TRANSVR_IF_KR4 "KR4" +#define TRANSVR_IF_SR "SR" +#define TRANSVR_IF_SR4 "SR4" +#define TRANSVR_IF_SFI "SFI" +#define TRANSVR_IF_IF_GMII "GMII" +#define TRANSVR_IF_IF_XGMII "XGMII" +#define TRANSVR_IF_SP_100 "100" +#define TRANSVR_IF_SP_1G "1000" +#define TRANSVR_IF_SP_10G "10000" +#define TRANSVR_IF_SP_25G "25000" +#define TRANSVR_IF_SP_40G "40000" +#define TRANSVR_IF_SP_100G "100000" + +/* Transceiver mode define */ +#define TRANSVR_MODE_DIRECT (21000) +#define TRANSVR_MODE_POLLING (21001) + +/* Transceiver state define + * [Note] + * 1. State is used to represent the state of "Transceiver" and "Object". + * 2. State for different target has different means. The description as following: + */ +#define STATE_TRANSVR_CONNECTED (0) /* [Transvr]:Be plugged in. [Obj]:Link up, and work normally. */ +#define STATE_TRANSVR_NEW (-100) /* [Transvr]:(Not used) [Obj]:Create */ +#define STATE_TRANSVR_INIT (-101) /* [Transvr]:Be plugged in. [Obj]:Link up, and in initial process. */ +#define STATE_TRANSVR_ISOLATED (-102) /* [Transvr]:Be plugged in. [Obj]:Isolate, and not provide service. */ +#define STATE_TRANSVR_SWAPPED (-200) /* [Transvr]:Be plugged in. [Obj]:(Not used) */ +#define STATE_TRANSVR_DISCONNECTED (-300) /* [Transvr]:Un-plugged. [Obj]:Link down, and not provide service. */ +#define STATE_TRANSVR_UNEXCEPTED (-901) /* [Transvr]:Any [Obj]:Any, and not in expect case. */ + +/* Task state define */ +#define STATE_T_TASK_WAIT (110) +#define STATE_T_TASK_DONE (0) +#define STATE_T_TASK_INIT (-110) +#define STATE_T_TASK_FAIL (-410) + + +/* Event for task handling */ +#define EVENT_TRANSVR_TASK_WAIT (2101) +#define EVENT_TRANSVR_TASK_DONE (0) +#define EVENT_TRANSVR_TASK_FAIL (-2101) +/* Event for initial handling */ +#define EVENT_TRANSVR_INIT_UP (2201) +#define EVENT_TRANSVR_INIT_DOWN (1) +#define EVENT_TRANSVR_INIT_REINIT (-2201) +#define EVENT_TRANSVR_INIT_FAIL (-2202) +/* Event for others */ +#define EVENT_TRANSVR_RELOAD_FAIL (-2301) +#define EVENT_TRANSVR_EXCEP_INIT (-2401) +#define EVENT_TRANSVR_EXCEP_UP (-2402) +#define EVENT_TRANSVR_EXCEP_DOWN (-2403) +#define EVENT_TRANSVR_EXCEP_SWAP (-2404) +#define EVENT_TRANSVR_EXCEP_EXCEP (-2405) +#define EVENT_TRANSVR_EXCEP_ISOLATED (-2406) +#define EVENT_TRANSVR_I2C_CRASH (-2501) + +/* Transceiver error code define */ +#define ERR_TRANSVR_UNINIT (-201) +#define ERR_TRANSVR_UNPLUGGED (-202) +#define ERR_TRANSVR_ABNORMAL (-203) +#define ERR_TRANSVR_NOSTATE (-204) +#define ERR_TRANSVR_NOTSUPPORT (-205) +#define ERR_TRANSVR_BADINPUT (-206) +#define ERR_TRANSVR_UPDATE_FAIL (-207) +#define ERR_TRANSVR_RELOAD_FAIL (-208) +#define ERR_TRANSVR_INIT_FAIL (-209) +#define ERR_TRANSVR_UNDEFINED (-210) +#define ERR_TRANSVR_TASK_FAIL (-211) +#define ERR_TRANSVR_TASK_BUSY (-212) +#define ERR_TRANSVR_UEVENT_FAIL (-213) +#define ERR_TRANSVR_FUNC_DISABLE (-214) +#define ERR_TRANSVR_I2C_CRASH (-297) +#define ERR_TRNASVR_BE_ISOLATED (-298) +#define ERR_TRANSVR_UNEXCPT (-299) + +/* For debug */ +#define DEBUG_TRANSVR_INT_VAL (-99) +#define DEBUG_TRANSVR_HEX_VAL (0xfe) +#define DEBUG_TRANSVR_STR_VAL "ERROR" + +/* For system internal */ +#define VAL_TRANSVR_COMID_ARREESS (0x50) +#define VAL_TRANSVR_COMID_OFFSET (0x00) +#define VAL_TRANSVR_EXTPHY_ADDR_56 (0x56) +#define VAL_TRANSVR_8472_READY_ADDR (0x51) +#define VAL_TRANSVR_8472_READY_PAGE (-1) +#define VAL_TRANSVR_8472_READY_OFFSET (110) +#define VAL_TRANSVR_8472_READY_BIT (0) +#define VAL_TRANSVR_8472_READY_VALUE (0) +#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_READY_ADDR (0x50) +#define VAL_TRANSVR_8436_READY_PAGE (-1) +#define VAL_TRANSVR_8436_READY_OFFSET (2) +#define VAL_TRANSVR_8436_READY_BIT (0) +#define VAL_TRANSVR_8436_READY_VALUE (0) +#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_PWD_ADDR (0x50) +#define VAL_TRANSVR_8436_PWD_PAGE (-1) +#define VAL_TRANSVR_8436_PWD_OFFSET (123) +#define VAL_TRANSVR_PAGE_FREE (-99) +#define VAL_TRANSVR_PAGE_SELECT_OFFSET (127) +#define VAL_TRANSVR_PAGE_SELECT_DELAY (5) +#define VAL_TRANSVR_TASK_RETRY_FOREVER (-999) +#define VAL_TRANSVR_FUNCTION_DISABLE (-1) +#define STR_TRANSVR_SFP "SFP" +#define STR_TRANSVR_QSFP "QSFP" +#define STR_TRANSVR_QSFP_PLUS "QSFP+" +#define STR_TRANSVR_QSFP28 "QSFP28" + +/* For transvr buf len */ +#define LEN_TRANSVR_S_STR (16) +#define LEN_TRANSVR_M_STR (32) +#define LEN_TRANSVR_L_STR (64) + +/* Optical wavelength */ +#define VAL_OPTICAL_WAVELENGTH_SR (850) +#define VAL_OPTICAL_WAVELENGTH_LR (1310) +#define VAL_OPTICAL_WAVELENGTH_ER (1550) + +/* BCM chip type define */ +#define BCM_CHIP_TYPE_TRIDENT_2 (31001) /* Magnolia, Hudson32i, Spruce */ +#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress, Sequoia */ +#define BCM_CHIP_TYPE_TRIDENT_3 (31003) /* Maple */ + +#define BF_CHIP_TYPE_TOFINO (31011) /* Lavender */ + +/* Info from transceiver EEPROM */ +struct eeprom_map_s { + int addr_br; int page_br; int offset_br; int length_br; + int addr_cdr; int page_cdr; int offset_cdr; int length_cdr; + int addr_comp_rev; int page_comp_rev; int offset_comp_rev; int length_comp_rev; + int addr_connector; int page_connector; int offset_connector; int length_connector; + int addr_diag_type; int page_diag_type; int offset_diag_type; int length_diag_type; + int addr_extbr; int page_extbr; int offset_extbr; int length_extbr; + int addr_ext_id; int page_ext_id; int offset_ext_id; int length_ext_id; + int addr_id; int page_id; int offset_id; int length_id; + int addr_len_sm; int page_len_sm; int offset_len_sm; int length_len_sm; + int addr_len_smf; int page_len_smf; int offset_len_smf; int length_len_smf; + int addr_len_om1; int page_len_om1; int offset_len_om1; int length_len_om1; + int addr_len_om2; int page_len_om2; int offset_len_om2; int length_len_om2; + int addr_len_om3; int page_len_om3; int offset_len_om3; int length_len_om3; + int addr_len_om4; int page_len_om4; int offset_len_om4; int length_len_om4; + int addr_option; int page_option; int offset_option; int length_option; + int addr_rate_id; int page_rate_id; int offset_rate_id; int length_rate_id; + int addr_rx_am; int page_rx_am; int offset_rx_am; int length_rx_am; + int addr_rx_em; int page_rx_em; int offset_rx_em; int length_rx_em; + int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los; + int addr_rx_power; int page_rx_power; int offset_rx_power; int length_rx_power; + int addr_soft_rs0; int page_soft_rs0; int offset_soft_rs0; int length_soft_rs0; + int addr_soft_rs1; int page_soft_rs1; int offset_soft_rs1; int length_soft_rs1; + int addr_temp; int page_temp; int offset_temp; int length_temp; + int addr_trancomp; int page_trancomp; int offset_trancomp; int length_trancomp; + int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext; + int addr_tx_bias; int page_tx_bias; int offset_tx_bias; int length_tx_bias; + int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable; + int addr_tx_eq; int page_tx_eq; int offset_tx_eq; int length_tx_eq; + int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault; + int addr_tx_power; int page_tx_power; int offset_tx_power; int length_tx_power; + int addr_vendor_name; int page_vendor_name; int offset_vendor_name; int length_vendor_name; + int addr_vendor_pn; int page_vendor_pn; int offset_vendor_pn; int length_vendor_pn; + int addr_vendor_rev; int page_vendor_rev; int offset_vendor_rev; int length_vendor_rev; + int addr_vendor_sn; int page_vendor_sn; int offset_vendor_sn; int length_vendor_sn; + int addr_voltage; int page_voltage; int offset_voltage; int length_voltage; + int addr_wavelength; int page_wavelength; int offset_wavelength; int length_wavelength; +}; + + +struct transvr_worker_s; + +/* Class of transceiver object */ +struct transvr_obj_s { + + /* ========== Object private property ========== + * [Prop]: id + * [Desc]: Type of serial transceiver. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h + */ + uint8_t id; + + /* [Prop]: connector + * [Desc]: Connector type. + * [Note]: SFP : A0h / 2 + * QSFP: 00h / 130 + */ + uint8_t connector; + + /* [Prop]: transvr_comp + * [Desc]: Transceiver compliance code. + * [Note]: SFP: SFF-8472 + * - Normal : A0h / offset 3-10 + * - Extended: A0h / offset 36 + * QSFP: SFF-8436 & SFF-8636 + * - Normal : 00h / offset 131-138 + * - Extended: 00h / offset 192 + */ + uint8_t transvr_comp[8]; + uint8_t transvr_comp_ext; + + /* [Prop]: vendor_name + * [Desc]: SFP vendor name (ASCII 16 byte char). + * [Note]: ex:FINISAR CORP. + */ + char *vendor_name; + + /* [Prop]: vendor_pn + * [Desc]: Part number provided by SFP vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_pn; + + /* [Prop]: vendor_rev + * [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char). + * [Note]: + */ + char *vendor_rev; + + /* [Prop]: vendor_sn + * [Desc]: Serial number provided by vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_sn; + + /* [Prop]: Extended identifier + * [Desc]: SFP: + * => None + * + * QSFP: + * => This byte contained two information: + * (1) Power consumption class + * (2) CDR function present + * [Note]: Bit description as below: + * [SFP] + * None + * + * [QSFP] + * (1) Power consumption class: + * Class 1: 1.5W (Bit6-7 = 00:) + * Class 2: 2.0W (Bit6-7 = 01:) + * Class 3: 2.5W (Bit6-7 = 10:) + * Class 4: 3.5W (Bit6-7 = 11:) + * Class 5: 4.0W (Bit0-1 = 01:) + * Class 6: 4.5W (Bit0-1 = 10:) + * Class 7: 5.0W (Bit0-1 = 11:) + * (2) CDR function present: + * Bit2: 0 = No CDR in RX + * 1 = CDR present in RX + * Bit3: 0 = No CDR in TX + * 1 = CDR present in TX + */ + uint8_t ext_id; + + /* [Prop]: br + * [Desc]: Nominal bit rate, units of 100 MBits/sec. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh + * has val: 0x67 + * no val : + */ + uint8_t br; + + /* [Prop]: extbr + * [Desc]: Extended br (00h/222) + * [Desc]: Nominal bit rate per channel, units of 250 Mbps. + * Complements. Byte 140. See Table 32A. + */ + uint8_t extbr; + + /* [Prop]: len_sm + * [Desc]: Length (single mode)-(100's)m + * [Note]: This value specifies the link length that is supported by the transceiver + * while operating in compliance with the applicable standards using single mode + * fiber. The value is in units of 100 meters. A value of 255 means that the + * transceiver supports a link length greater than 25.4 km. A value of zero means + * that the transceiver does not support single mode fiber or that the length + * information must be determined from the transceiver technology. + */ + int len_sm; + + /* [Prop]: len_smf + * [Desc]: Length (single mode)-km + * [Note]: Addition to EEPROM data from original GBIC definition. This value specifies + * the link length that is supported by the transceiver while operating in + * compliance with the applicable standards using single mode fiber. The value + * is in units of kilometers. A value of 255 means that the transceiver supports + * a link length greater than 254 km. A value of zero means that the transceiver + * does not support single mode fiber or that the length information must be + * determined from the transceiver technology. + */ + int len_smf; + + /* [Prop]: len_om1 + * [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om1; + + /* [Prop]: len_om2 + * [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om2; + + /* [Prop]: len_om3 + * [Desc]: Length (50um, OM3) + * [Note]: This value specifies link length that is supported by the transceiver while + * operating in compliance with applicable standards using 50 micron multimode + * OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255 + * means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber + * or that the length information must be determined from the transceiver technology. + */ + int len_om3; + + /* [Prop]: len_om4 + * [Desc]: Length (50um, OM4) and Length (Active Cable or Copper) + * [Note]: For optical links, this value specifies link length that is supported by the + * transceiver while operating in compliance with applicable standards using 50 micron + * multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of + * 255 means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber or that + * the length information must be determined from the transceiver codes specified in Table 5-3. + * + * For copper links, this value specifies minimum link length supported by the transceiver + * while operating in compliance with applicable standards using copper cable. For active + * cable, this value represents actual length. The value is in units of 1 meter. A value of 255 + * means the transceiver supports a link length greater than 254 meters. A value of zero means + * the transceiver does not support copper or active cables or the length information must be + * determined from transceiver technology. Further information about cable design, equalization, + * and connectors is usually required to guarantee meeting a particular length requirement. + */ + int len_om4; + + /* [Prop]: comp_rev + * [Desc]: SFF spec revision compliance + * [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver + * complies with. (unsigned integer) + */ + uint8_t comp_rev; + + /* [Prop]: CDR + * [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal + * retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which + * directs traffic around the internal CDR. (Reference: SFF-8636) + * [Note]: value=0xff: ON. + * value=0x00: OFF. + */ + uint8_t cdr; + + /* [Prop]: rate_id + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Addr: A0h / Offset: 13 + * 2. Value description: + * 00h Unspecified + * 01h SFF-8079 (4/2/1G Rate_Select & AS0/AS1) + * 02h SFF-8431 (8/4/2G Rx Rate_Select only) + * 03h Unspecified * + * 04h SFF-8431 (8/4/2G Tx Rate_Select only) + * 05h Unspecified * + * 06h SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) + * 07h Unspecified * + * 08h FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G + * 09h Unspecified * + * 0Ah FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only, + * Low=8G/4G + * 0Bh Unspecified * + * 0Ch FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + * 0Dh Unspecified * + * 0Eh 10/8G Rx and Tx Rate_Select controlling the operation or locking + * modes of the internal signal conditioner, retimer or CDR, according + * to the logic table defined in Table 10-2, High Bit Rate + * (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode, + * the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11) + * and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1. + * 0Fh Unspecified * + * 10h-FFh Unallocated + */ + int rate_id; + + /* [Prop]: soft_rs0 + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Writing '1' selects full bandwidth operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 110 / Bit: 3 + */ + uint8_t soft_rs0; + + /* [Prop]: soft_rs1 + * [Desc]: Soft Rate Select 1(TX). + * [Note]: 1. Writing '1' selects full bandwidth TX operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 118 / Bit: 3 + */ + uint8_t soft_rs1; + + /* [Prop]: diag_type + * [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92) + * [Note]: Description in SFF-8472 as below: + * Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance + * with this document. + * Bit6: Digital diagnostic monitoring implemented (described in this document). + * Must be '1' for compliance with this document. + * Bit5 Internally calibrated + * Bit4 Externally calibrated + * Bit3 Received power measurement type.0 = OMA, 1 = average power + * Bit2 Address change required see section above, "addressing modes" + * Bit1-0 Unallocated + */ + uint8_t diag_type; + + /* [Prop]: curr_temp + * [Desc]: Transceiver Current Temperature (A2h/96-97) + * [Note]: 1. Dependent on diag_type. + * 2. 96: High byte + * 3. 97: Low byte + * 4. This feature only for SFP + */ + uint8_t curr_temp[2]; + + /* [Prop]: curr_vol + * [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23) + * [Note]: 1. Dependent on diag_type. + * 2. 98: High byte + * 3. 99: Low byte + * 4. This feature only for SFP + * 5. Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts + */ + uint8_t curr_voltage[2]; + + /* [Prop]: curr_tx_bias + * [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27) + * [Note]: 1. Dependent on diag_type. + * 2. 100: High byte + * 3. 101: Low byte + * 4. This feature only for SFP + * 5. Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + uint8_t curr_tx_bias[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + uint8_t curr_tx_power[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + uint8_t curr_rx_power[8]; + + /* [Prop]: wavelength + * [Desc]: Wavelength or Copper Cable Attenuation + * [Note]: (Following is info from SFF-8636) + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is a + * 16-bit hex value with Byte 186 as high order byte and Byte 187 as low + * order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. If the free side device is identified as + * copper cable these registers will be used to define the cable attenuation. + * An indication of 0 dB attenuation refers to the case where the attenuation + * is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + uint8_t wavelength[2]; + + /* [Prop]: Amplitude control + * [Desc]: Amplitude control + * [Note]: QSFP28 => SFF-8636 03H Byte-238/239 + */ + uint8_t rx_am[2]; + + /* [Prop]: Emphasis control + * [Desc]: Emphasis control + * [Note]: SFP+/28 => SFF-8472 A2H Byte-115 + * QSFP28 => SFF-8636 03H Byte-236/237 + */ + uint8_t rx_em[2]; + + /* [Prop]: Soft Rx LOS + * [Desc]: Soft Rx LOS which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 3: + * - Bit 0: L-Rx1 LOS + * - Bit 1: L-Rx2 LOS + * - Bit 2: L-Rx3 LOS + * - Bit 3: L-Rx4 LOS + */ + uint8_t rx_los; + + /* [Prop]: Soft Tx Disable + * [Desc]: Soft Tx Disable which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Disable + * - Bit 1: Tx2 Disable + * - Bit 2: Tx3 Disable + * - Bit 3: Tx4 Disable + */ + uint8_t tx_disable; + + /* [Prop]: Soft Tx Fault + * [Desc]: Soft Tx Fault which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Fault + * - Bit 1: Tx2 Fault + * - Bit 2: Tx3 Fault + * - Bit 3: Tx4 Fault + */ + uint8_t tx_fault; + + /* [Prop]: Transceiver EQUALIZATION + * [Desc]: Transceiver EQUALIZATION + * [Note]: SFP+/28 => SFF-8472 A2H Byte-114 + * QSFP28 => SFF-8636 03H Byte-234/235 + */ + uint8_t tx_eq[2]; + + /* [Prop]: OPTION VALUES + * [Desc]: The bits in the option field shall specify the options implemented in the transceiver. + * [Note]: SFP+/28 => SFF-8472 A0H Byte-64/65 + * QSFP+/28 => SFF-8636 00H Byte-193/195 + */ + uint8_t option[3]; + + /* [Prop]: External PHY offset + * [Desc]: It needs to be setup first if you want to access transceiver external phy. + * [Note]: This feature dependent on transceiver. + * Currently, only 1G-RJ45 transceiver supported it. + */ + uint8_t extphy_offset; + + /* ========== Object private property ========== + */ + struct device *transvr_dev_p; + struct eeprom_map_s *eeprom_map_p; + struct i2c_client *i2c_client_p; + struct ioexp_obj_s *ioexp_obj_p; + struct transvr_worker_s *worker_p; + struct mutex lock; + char swp_name[32]; + int auto_config; + int auto_tx_disable; + int chan_id; + int chipset_type; + int curr_page; + int info; + int ioexp_virt_offset; + int lane_id[8]; + int layout; + int mode; + int retry; + int state; + int temp; + int type; + + /* ========== Object public functions ========== + */ + int (*get_id)(struct transvr_obj_s *self); + int (*get_ext_id)(struct transvr_obj_s *self); + int (*get_connector)(struct transvr_obj_s *self); + int (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p); + int (*get_power_cls)(struct transvr_obj_s *self); + int (*get_br)(struct transvr_obj_s *self); + int (*get_len_sm)(struct transvr_obj_s *self); + int (*get_len_smf)(struct transvr_obj_s *self); + int (*get_len_om1)(struct transvr_obj_s *self); + int (*get_len_om2)(struct transvr_obj_s *self); + int (*get_len_om3)(struct transvr_obj_s *self); + int (*get_len_om4)(struct transvr_obj_s *self); + int (*get_comp_rev)(struct transvr_obj_s *self); + int (*get_comp_eth_1)(struct transvr_obj_s *self); + int (*get_comp_eth_10)(struct transvr_obj_s *self); + int (*get_comp_eth_10_40)(struct transvr_obj_s *self); + int (*get_comp_extend)(struct transvr_obj_s *self); + int (*get_cdr)(struct transvr_obj_s *self); + int (*get_rate_id)(struct transvr_obj_s *self); + int (*get_soft_rs0)(struct transvr_obj_s *self); + int (*get_soft_rs1)(struct transvr_obj_s *self); + int (*get_info)(struct transvr_obj_s *self); + int (*get_if_type)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_speed)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_lane)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p); + int (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_am)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_em)(struct transvr_obj_s *self, char *buf_p); + int (*get_wavelength)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_offset)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_reg)(struct transvr_obj_s *self, char *buf_p); + int (*set_cdr)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs0)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs1)(struct transvr_obj_s *self, int input_val); + int (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_tx_eq)(struct transvr_obj_s *self, int input_val); + int (*set_rx_am)(struct transvr_obj_s *self, int input_val); + int (*set_rx_em)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_offset)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_reg)(struct transvr_obj_s *self, int input_val); + + /* ========== Object private functions ========== + */ + int (*init)(struct transvr_obj_s *self); + int (*clean)(struct transvr_obj_s *self); + int (*check)(struct transvr_obj_s *self); + int (*update_all)(struct transvr_obj_s *self, int show_err); + int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name); + int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name); + int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action); + int (*dump_all)(struct transvr_obj_s* self); +}; + + +/* For AVL Mapping */ +struct transvr_avl_s { + char vendor_name[32]; + char vendor_pn[32]; + int (*init)(struct transvr_obj_s *self); +}; + + +/* Worker for long term task of transceiver */ +struct transvr_worker_s { + /* Task Parameter */ + struct transvr_obj_s *transvr_p; + struct transvr_worker_s *next_p; + struct transvr_worker_s *pre_p; + unsigned long trigger_time; + char func_name[64]; + int retry; + int state; + + /* Task private data */ + void *p_data; + + /* Call back function */ + int (*main_task)(struct transvr_worker_s *task); + int (*post_task)(struct transvr_worker_s *task); +}; + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode); + +void lock_transvr_obj(struct transvr_obj_s *self); +void unlock_transvr_obj(struct transvr_obj_s *self); +int isolate_transvr_obj(struct transvr_obj_s *self); + +int resync_channel_tier_2(struct transvr_obj_s *self); + +void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + +#endif /* TRANSCEIVER_H */ + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/ucd9000.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/ucd9000.c new file mode 100644 index 000000000000..5beba343b327 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/ucd9000.c @@ -0,0 +1,247 @@ +/* + * Hardware monitoring driver for UCD90xxx Sequencer and System Health + * Controller series + * + * Copyright (C) 2011 Ericsson AB. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "pmbus.h" + +enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 }; + +#define UCD9000_MONITOR_CONFIG 0xd5 +#define UCD9000_NUM_PAGES 0xd6 +#define UCD9000_FAN_CONFIG_INDEX 0xe7 +#define UCD9000_FAN_CONFIG 0xe8 +#define UCD9000_DEVICE_ID 0xfd + +#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07) +#define UCD9000_MON_PAGE(x) ((x) & 0x0f) + +#define UCD9000_MON_VOLTAGE 1 +#define UCD9000_MON_TEMPERATURE 2 +#define UCD9000_MON_CURRENT 3 +#define UCD9000_MON_VOLTAGE_HW 4 + +#define UCD9000_NUM_FAN 4 + +struct ucd9000_data { + u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX]; + struct pmbus_driver_info info; +}; +#define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info) + +static int ucd9000_get_fan_config(struct i2c_client *client, int fan) +{ + int fan_config = 0; + struct ucd9000_data *data + = to_ucd9000_data(pmbus_get_driver_info(client)); + + if (data->fan_data[fan][3] & 1) + fan_config |= PB_FAN_2_INSTALLED; /* Use lower bit position */ + + /* Pulses/revolution */ + fan_config |= (data->fan_data[fan][3] & 0x06) >> 1; + + return fan_config; +} + +static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg) +{ + int ret = 0; + int fan_config; + + switch (reg) { + case PMBUS_FAN_CONFIG_12: + if (page > 0) + return -ENXIO; + + ret = ucd9000_get_fan_config(client, 0); + if (ret < 0) + return ret; + fan_config = ret << 4; + ret = ucd9000_get_fan_config(client, 1); + if (ret < 0) + return ret; + fan_config |= ret; + ret = fan_config; + break; + case PMBUS_FAN_CONFIG_34: + if (page > 0) + return -ENXIO; + + ret = ucd9000_get_fan_config(client, 2); + if (ret < 0) + return ret; + fan_config = ret << 4; + ret = ucd9000_get_fan_config(client, 3); + if (ret < 0) + return ret; + fan_config |= ret; + ret = fan_config; + break; + default: + ret = -ENODATA; + break; + } + return ret; +} + +static const struct i2c_device_id ucd9000_id[] = { + {"ucd9000", ucd9000}, + {"ucd90120", ucd90120}, + {"ucd90124", ucd90124}, + {"ucd90160", ucd90160}, + {"ucd9090", ucd9090}, + {"ucd90910", ucd90910}, + {} +}; +MODULE_DEVICE_TABLE(i2c, ucd9000_id); + +static int ucd9000_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; + struct ucd9000_data *data; + struct pmbus_driver_info *info; + const struct i2c_device_id *mid; + int i, ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA)) + return -ENODEV; + + ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID, + block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read device ID\n"); + return ret; + } + block_buffer[ret] = '\0'; + dev_info(&client->dev, "Device ID %s\n", block_buffer); + + for (mid = ucd9000_id; mid->name[0]; mid++) { + if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) + break; + } + if (!mid->name[0]) { + dev_err(&client->dev, "Unsupported device\n"); + return -ENODEV; + } + + if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data) + dev_notice(&client->dev, + "Device mismatch: Configured %s, detected %s\n", + id->name, mid->name); + + data = devm_kzalloc(&client->dev, sizeof(struct ucd9000_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + info = &data->info; + + ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES); + if (ret < 0) { + dev_err(&client->dev, + "Failed to read number of active pages\n"); + return ret; + } + info->pages = ret; + if (!info->pages) { + dev_err(&client->dev, "No pages configured\n"); + return -ENODEV; + } + + /* The internal temperature sensor is always active */ + info->func[0] = PMBUS_HAVE_TEMP; + + /* Everything else is configurable */ + ret = i2c_smbus_read_block_data(client, UCD9000_MONITOR_CONFIG, + block_buffer); + if (ret <= 0) { + dev_err(&client->dev, "Failed to read configuration data\n"); + return -ENODEV; + } + for (i = 0; i < ret; i++) { + int page = UCD9000_MON_PAGE(block_buffer[i]); + + if (page >= info->pages) + continue; + + switch (UCD9000_MON_TYPE(block_buffer[i])) { + case UCD9000_MON_VOLTAGE: + case UCD9000_MON_VOLTAGE_HW: + info->func[page] |= PMBUS_HAVE_VOUT + | PMBUS_HAVE_STATUS_VOUT; + break; + case UCD9000_MON_TEMPERATURE: + info->func[page] |= PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_STATUS_TEMP; + break; + case UCD9000_MON_CURRENT: + info->func[page] |= PMBUS_HAVE_IOUT + | PMBUS_HAVE_STATUS_IOUT; + break; + default: + break; + } + } + + /* Fan configuration */ + if (mid->driver_data == ucd90124) { + for (i = 0; i < UCD9000_NUM_FAN; i++) { + i2c_smbus_write_byte_data(client, + UCD9000_FAN_CONFIG_INDEX, i); + ret = i2c_smbus_read_block_data(client, + UCD9000_FAN_CONFIG, + data->fan_data[i]); + if (ret < 0) + return ret; + } + i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0); + + info->read_byte_data = ucd9000_read_byte_data; + info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 + | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34; + } + + return pmbus_do_probe(client, mid, info); +} + +/* This is the driver that will be inserted */ +static struct i2c_driver ucd9000_driver = { + .driver = { + .name = "ucd9000", + }, + .probe = ucd9000_probe, + .remove = pmbus_do_remove, + .id_table = ucd9000_id, +}; + +module_i2c_driver(ucd9000_driver); + +MODULE_AUTHOR("Guenter Roeck"); +MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/setup.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/setup.py new file mode 100644 index 000000000000..8b45987a54ec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize Ivnetec D6356 platforms', + + packages=['sonic_platform'], +) + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/__init__.py new file mode 100644 index 000000000000..4bfefa0fb636 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/chassis.py new file mode 100644 index 000000000000..8f3520259038 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/chassis.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.eeprom import Eeprom + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu + from sonic_platform.sfp import Sfp + from sonic_platform.qsfp import QSfp + from sonic_platform.thermal import Thermal + from sonic_platform.transceiver_event import TransceiverEvent +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Chassis(ChassisBase): + + def __init__(self): + ChassisBase.__init__(self) + self.__num_of_fans = 8 + self.__num_of_psus = 2 + self.__num_of_sfps = 56 + self.__start_of_qsfp = 48 + self.__num_of_thermals = 5 + + # Initialize EEPROM + self._eeprom = Eeprom() + + # Initialize FAN + for index in range(1, self.__num_of_fans + 1): + fan = Fan(index, False, 0) + self._fan_list.append(fan) + + # Initialize PSU + for index in range(1, self.__num_of_psus + 1): + psu = Psu(index) + self._psu_list.append(psu) + + # Initialize SFP + for index in range(0, self.__num_of_sfps): + if index < self.__start_of_qsfp: + sfp = Sfp(index) + else: + sfp = QSfp(index) + self._sfp_list.append(sfp) + + # Initialize THERMAL + for index in range(0, self.__num_of_thermals): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + # Initialize TRANSCEIVER EVENT MONITOR + self.__xcvr_event = TransceiverEvent() + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + +############################################## +# Chassis methods +############################################## + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_address() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + raise NotImplementedError + +############################################## +# Other methods +############################################## + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + + rc, xcvr_event = self.__xcvr_event.get_transceiver_change_event(timeout) + + return rc, {'sfp': xcvr_event} + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/eeprom.py new file mode 100644 index 000000000000..ef0d6385534e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/eeprom.py @@ -0,0 +1,109 @@ +# +# Name: eeprom.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.__eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0055/eeprom" + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + self.__eeprom_tlv_dict = dict() + try: + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + ord(eeprom[tlv_index + 1])] + code = "0x%02X" % (ord(tlv[0])) + + if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT: + value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) | + (ord(tlv[4]) << 8) | ord(tlv[5])) + value += str(tlv[6:6 + ord(tlv[1])]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32: + break + + tlv_index += ord(eeprom[tlv_index+1]) + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2] + + def base_mac_address(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(eeprom_tlvinfo.TlvInfoDecoder, self).switchaddrstr(self.__eeprom_data) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2] + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2] + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2] + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.__eeprom_tlv_dict + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/fan.py new file mode 100644 index 000000000000..b9423e43dcb1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/fan.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +# +# Name: fan.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import math + import os + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Fan(FanBase): + + def __init__(self, index, is_psu_fan=False, psu_index=0): + self.__index = index + self.__is_psu_fan = is_psu_fan + + if self.__is_psu_fan: + self.__psu_index = psu_index + self.__presence_attr = "/sys/class/hwmon/hwmon{}/fan{}_input".format((self.__psu_index + 6), self.__index) + self.__speed_rpm_attr = "/sys/class/hwmon/hwmon{}/fan{}_input".format((self.__psu_index + 6), self.__index) + self.__pwm_attr = None + else: + self.__presence_attr = "/sys/class/hwmon/hwmon2/device/fan{}_input".format(self.__index) + self.__speed_rpm_attr = "/sys/class/hwmon/hwmon2/device/fan{}_input".format(self.__index) + self.__pwm_attr = "/sys/class/hwmon/hwmon2/device/pwm{}".format((self.__index + 1)/2) + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + if self.__is_psu_fan: + return "PSU{}-FAN{}".format(self.__psu_index, self.__index) + else: + return "FAN{}".format(self.__index) + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = self.__presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) != 0): + 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 + """ + return "N/A" + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + return "N/A" + + 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() + +############################################## +# FAN methods +############################################## + + def get_direction(self): + """ + Retrieves the direction of fan + + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + raise NotImplementedError + + 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) + """ + speed = 0 + + if self.__is_psu_fan: + attr_path = self.__speed_rpm_attr + else: + attr_path = self.__pwm_attr + + if self.get_presence() and None != attr_path: + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if self.__is_psu_fan: + fan_speed_rpm = int(attr_rv) + speed = math.ceil(float(fan_speed_rpm) * 100 / 11000) + else: + pwm = int(attr_rv) + speed = math.ceil(float(pwm * 100 / 255)) + + 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) + """ + raise NotImplementedError + + 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 + """ + raise NotImplementedError + + 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 + """ + raise NotImplementedError + + 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 + """ + raise NotImplementedError + + 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 + """ + if self.get_status() and self.get_speed() > 0: + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/platform.py new file mode 100644 index 000000000000..7d6bda4502de --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/platform.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/psu.py new file mode 100644 index 000000000000..3798ef9e5b80 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/psu.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python +# +# Name: psu.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Psu(PsuBase): + + def __init__(self, index): + self.__num_of_fans = 1 + self.__index = index + self.__psu_presence_attr = "/sys/class/hwmon/hwmon2/device/psu{}".format(self.__index) + self.__psu_power_in_attr = "/sys/class/hwmon/hwmon{}/power1_input".format(self.__index + 6) + self.__psu_power_out_attr = "/sys/class/hwmon/hwmon{}/power2_input".format(self.__index + 6) + self.__psu_voltage_out_attr = "/sys/class/hwmon/hwmon{}/in2_input".format(self.__index + 6) + self.__psu_current_out_attr = "/sys/class/hwmon/hwmon{}/curr2_input".format(self.__index + 6) + + # Overriding _fan_list class variable defined in PsuBase, to make it unique per Psu object + self._fan_list = [] + + # Initialize FAN + for x in range(1, self.__num_of_fans + 1): + fan = Fan(x, True, self.__index) + self._fan_list.append(fan) + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.__index) + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_normal = "1:normal" + attr_path = self.__psu_presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (attr_rv == attr_normal): + 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 + """ + return "N/A" + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + return "N/A" + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + status = False + attr_path = self.__psu_power_in_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) != 0): + status = True + + return status + +############################################## +# PSU methods +############################################## + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + voltage_out = 0.0 + attr_path = self.__psu_voltage_out_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + voltage_out = float(attr_rv) / 1000 + + return voltage_out + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + current_out = 0.0 + attr_path = self.__psu_current_out_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + current_out = float(attr_rv) / 1000 + + return current_out + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, e.g. 302.6 + """ + power_out = 0.0 + attr_path = self.__psu_power_out_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + power_out = float(attr_rv) / 1000000 + + return power_out + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + return self.get_status() + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + + Args: + color: A string representing the color with which to set the + PSU status LED + + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py new file mode 100644 index 000000000000..2cc4b6ca593a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py @@ -0,0 +1,925 @@ +#!/usr/bin/env python +# +# Name: qsfp.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import sys + import time + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +INFO_OFFSET = 128 +DOM_OFFSET = 0 + +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNEL_THRESHOLD_OFFSET = 176 +QSFP_CHANNEL_THRESHOLD_WIDTH = 16 + +class QSfp(SfpBase): + + def __init__(self, index): + self.__index = index + + self.__platform = "x86_64-inventec_d6356-r0" + self.__hwsku = "INVENTEC-D6356" + + self.__port_to_i2c_mapping = { + 0:22, 1:23, 2:24, 3:25, 4:26, 5:27, 6:28, 7:29, + 8:30, 9:31, 10:32, 11:33, 12:34, 13:35, 14:36, 15:37, + 16:38, 17:39, 18:40, 19:41, 20:42, 21:43, 22:44, 23:45, + 24:46, 25:47, 26:48, 27:49, 28:50, 29:51, 30:52, 31:53, + 32:54, 33:55, 34:56, 35:57, 36:58, 37:59, 38:60, 39:61, + 40:62, 41:63, 42:64, 43:65, 44:66, 45:67, 46:68, 47:69, + 48:14, 49:15, 50:16, 51:17, 52:18, 53:19, 54:20, 55:21 + } + self.__port_end = len(self.__port_to_i2c_mapping) - 1; + + self.__presence_attr = None + self.__eeprom_path = None + if self.__index in range(0, self.__port_end + 1): + self.__presence_attr = "/sys/class/swps/port{}/present".format(self.__index) + self.__lpmode_attr = "/sys/class/swps/port{}/lpmod".format(self.__index) + self.__reset_attr = "/sys/class/swps/port{}/reset".format(self.__index) + self.__eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom".format(self.__port_to_i2c_mapping[self.__index]) + + #print(self.__eeprom_path) + + SfpBase.__init__(self) + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def __is_host(self): + return os.system("docker > /dev/null 2>&1") == 0 + + def __get_path_to_port_config_file(self): + host_platform_root_path = '/usr/share/sonic/device' + docker_hwsku_path = '/usr/share/sonic/hwsku' + + host_platform_path = "/".join([host_platform_root_path, self.__platform]) + hwsku_path = "/".join([host_platform_path, self.__hwsku]) if self.__is_host() else docker_hwsku_path + + return "/".join([hwsku_path, "port_config.ini"]) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_eeprom_path = self.__eeprom_path + try: + sysfsfile_eeprom = open(sysfs_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + raw_len = len(raw) + for n in range(0, raw_len): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def __convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + name = None + + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings(self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.__index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = self.__presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 0): + 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 + """ + transceiver_info_dict = self.get_transceiver_info() + return transceiver_info_dict.get("model", "N/A") + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + transceiver_info_dict = self.get_transceiver_info() + return transceiver_info_dict.get("serial", "N/A") + + 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 not self.get_reset_status() + +############################################## +# SFP methods +############################################## + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + mominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + + transceiver_info_dict_keys = ['type', 'hardware_rev', + 'serial', 'manufacturer', + 'model', 'connector', + 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', + 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', + 'vendor_oui'] + + qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', 'Length Cable Assembly(m)') + + qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', 'Fibre Channel transmission media', + 'Fibre Channel Speed') + + sfpi_obj = sff8436InterfaceId() + if not self.get_presence() or not sfpi_obj: + return {} + + offset = INFO_OFFSET + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes((offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_QSFP) + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes((offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_QSFP) + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + + sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + + sfp_vendor_date_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + + transceiver_info_dict = dict.fromkeys(transceiver_info_dict_keys, 'N/A') + + if sfp_interface_bulk_data: + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' + + transceiver_info_dict['cable_type'] = "Unknown" + transceiver_info_dict['cable_length'] = "Unknown" + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + compliance_code_dict = dict() + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict_keys = ['rx_los', 'tx_fault', + 'reset_status', 'power_lpmode', + 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + + if not self.get_presence() or not sfpi_obj or not sfpd_obj: + return {} + + transceiver_dom_info_dict = dict.fromkeys(transceiver_dom_info_dict_keys, 'N/A') + offset = DOM_OFFSET + offset_xcvr = INFO_OFFSET + + # 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((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_dom_capability(qsfp_dom_capability_raw, 0) + else: + return None + + dom_temperature_raw = self.__read_eeprom_specific_bytes((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) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes((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) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes((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) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['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 = {} + dom_channel_monitor_raw = None + 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((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: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((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) + 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'] + + if dom_channel_monitor_raw: + 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'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self.__convert_string_to_num(transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['tx_disable'] = self.get_tx_disable() + transceiver_dom_info_dict['tx_disable_channel'] = self.get_tx_disable_channel() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + transceiver_dom_threshold_info_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + sfpd_obj = sff8436Dom() + if not self.get_presence() or not sfpd_obj: + return {} + + transceiver_dom_threshold_dict = dict.fromkeys(transceiver_dom_threshold_info_dict_keys, 'N/A') + offset = DOM_OFFSET + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw: + module_threshold_values = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + module_threshold_data = module_threshold_values.get('data') + if module_threshold_data: + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value'] + + dom_channel_thres_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNEL_THRESHOLD_OFFSET), QSFP_CHANNEL_THRESHOLD_WIDTH) + channel_threshold_values = sfpd_obj.parse_channel_threshold_values(dom_channel_thres_raw, 0) + channel_threshold_data = channel_threshold_values.get('data') + if channel_threshold_data: + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerhighwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value'] + + for key in transceiver_dom_threshold_dict: + transceiver_dom_threshold_dict[key] = self.__convert_string_to_num(transceiver_dom_threshold_dict[key]) + + return transceiver_dom_threshold_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + reset_status = False + attr_path = self.__reset_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 0): + reset_status = True + + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + rx_los = False + rx_los_list = [] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(QSFP_CHANNL_RX_LOS_STATUS_OFFSET, QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + rx_los = rx_los_list[0] and rx_los_list[1] and rx_los_list[2] and rx_los_list[3] + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + tx_fault = False + tx_fault_list = [] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(QSFP_CHANNL_TX_FAULT_STATUS_OFFSET, QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + tx_fault = tx_fault_list[0] and tx_fault_list[1] and tx_fault_list[2] and tx_fault_list[3] + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + tx_disable = False + tx_disable_list = [] + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return tx_disable + + dom_control_raw = self.__read_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + tx_disable_list.append('On' == dom_control_data['data']['TX1Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX2Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX3Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX4Disable']['value']) + tx_disable = tx_disable_list[0] and tx_disable_list[1] and tx_disable_list[2] and tx_disable_list[3] + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_channel = 0 + tx_disable_list = [] + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return tx_disable_channel + + dom_control_raw = self.__read_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + tx_disable_list.append('On' == dom_control_data['data']['TX1Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX2Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX3Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX4Disable']['value']) + + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disable_channel |= 1 << i + + return tx_disable_channel + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + lpmode = False + attr_path = self.__lpmode_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 1): + lpmode = True + + return lpmode + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + power_override = False + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return power_override + + dom_control_raw = self.__read_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + power_override = ('On' == dom_control_data['data']['PowerOverride']['value']) + + return power_override + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("temperature", "N/A") + + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("voltage", "N/A") + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A") + tx2_bs = transceiver_dom_info_dict.get("tx2bias", "N/A") + tx3_bs = transceiver_dom_info_dict.get("tx3bias", "N/A") + tx4_bs = transceiver_dom_info_dict.get("tx4bias", "N/A") + return [tx1_bs, tx2_bs, tx3_bs, tx4_bs] if transceiver_dom_info_dict else [] + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A") + rx2_pw = transceiver_dom_info_dict.get("rx2power", "N/A") + rx3_pw = transceiver_dom_info_dict.get("rx3power", "N/A") + rx4_pw = transceiver_dom_info_dict.get("rx4power", "N/A") + return [rx1_pw, rx2_pw, rx3_pw, rx4_pw] if transceiver_dom_info_dict else [] + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A") + tx2_pw = transceiver_dom_info_dict.get("tx2power", "N/A") + tx3_pw = transceiver_dom_info_dict.get("tx3power", "N/A") + tx4_pw = transceiver_dom_info_dict.get("tx4power", "N/A") + return [tx1_pw, tx2_pw, tx3_pw, tx4_pw] + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + + try: + reg_file = open(self.__reset_attr, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + try: + reg_file = open(self.__reset_attr, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + sysfs_eeprom_path = self.__eeprom_path + sysfsfile_eeprom = None + try: + tx_disable_ctl = 0xf if tx_disable else 0x0 + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open(sysfs_eeprom_path, "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + sysfs_eeprom_path = self.__eeprom_path + sysfsfile_eeprom = None + try: + channel_state = self.get_tx_disable_channel() + tx_enable_mask = [0xe, 0xd, 0xb, 0x7] + tx_disable_mask = [0x1, 0x3, 0x7, 0xf] + tx_disable_ctl = channel_state | tx_disable_mask[channel] if disable else channel_state & tx_enable_mask[channel] + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open(sysfs_eeprom_path, "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + try: + reg_file = open(self.__lpmode_attr, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + sysfs_eeprom_path = self.__eeprom_path + sysfsfile_eeprom = None + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfsfile_eeprom = open(sysfs_eeprom_path, "r+b") + sysfsfile_eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/sfp.py new file mode 100644 index 000000000000..8c432dc19764 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/sfp.py @@ -0,0 +1,739 @@ +#!/usr/bin/env python +# +# Name: sfp.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import sys + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sffbase + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +INFO_OFFSET = 0 +DOM_OFFSET = 256 + +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + +# Offset for values in SFP eeprom +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 40 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 1 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + +class Sfp(SfpBase): + + def __init__(self, index): + self.__index = index + + self.__platform = "x86_64-inventec_d6356-r0" + self.__hwsku = "INVENTEC-D6356" + + self.__port_to_i2c_mapping = { + 0:22, 1:23, 2:24, 3:25, 4:26, 5:27, 6:28, 7:29, + 8:30, 9:31, 10:32, 11:33, 12:34, 13:35, 14:36, 15:37, + 16:38, 17:39, 18:40, 19:41, 20:42, 21:43, 22:44, 23:45, + 24:46, 25:47, 26:48, 27:49, 28:50, 29:51, 30:52, 31:53, + 32:54, 33:55, 34:56, 35:57, 36:58, 37:59, 38:60, 39:61, + 40:62, 41:63, 42:64, 43:65, 44:66, 45:67, 46:68, 47:69, + 48:14, 49:15, 50:16, 51:17, 52:18, 53:19, 54:20, 55:21 + } + self.__port_end = len(self.__port_to_i2c_mapping) - 1; + + self.__presence_attr = None + self.__eeprom_path = None + if self.__index in range(0, self.__port_end + 1): + self.__presence_attr = "/sys/class/swps/port{}/present".format(self.__index) + self.__eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom".format(self.__port_to_i2c_mapping[self.__index]) + + SfpBase.__init__(self) + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def __is_host(self): + return os.system("docker > /dev/null 2>&1") == 0 + + def __get_path_to_port_config_file(self): + host_platform_root_path = '/usr/share/sonic/device' + docker_hwsku_path = '/usr/share/sonic/hwsku' + + host_platform_path = "/".join([host_platform_root_path, self.__platform]) + hwsku_path = "/".join([host_platform_path, self.__hwsku]) if self.__is_host() else docker_hwsku_path + + return "/".join([hwsku_path, "port_config.ini"]) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_eeprom_path = self.__eeprom_path + try: + sysfsfile_eeprom = open(sysfs_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + raw_len = len(raw) + for n in range(0, raw_len): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def __convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + name = None + + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings(self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.__index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = self.__presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 0): + 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 + """ + transceiver_info_dict = self.get_transceiver_info() + return transceiver_info_dict.get("model", "N/A") + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + transceiver_info_dict = self.get_transceiver_info() + return transceiver_info_dict.get("serial", "N/A") + + 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 not self.get_reset_status() + +############################################## +# SFP methods +############################################## + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + mominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + + transceiver_info_dict_keys = ['type', 'hardware_rev', + 'serial', 'manufacturer', + 'model', 'connector', + 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', + 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', + 'vendor_oui'] + + sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + + sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + + sfpi_obj = sff8472InterfaceId() + if not self.get_presence() or not sfpi_obj: + return {} + + offset = INFO_OFFSET + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes((offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_SFP) + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes((offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_SFP) + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + + sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + + sfp_vendor_date_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + + transceiver_info_dict = dict.fromkeys(transceiver_info_dict_keys, 'N/A') + + if sfp_interface_bulk_data: + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' + + transceiver_info_dict['cable_type'] = "Unknown" + transceiver_info_dict['cable_length'] = "Unknown" + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + compliance_code_dict = dict() + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict_keys = ['rx_los', 'tx_fault', + 'reset_status', 'power_lpmode', + 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + + sfpd_obj = sff8472Dom() + if not self.get_presence() or not sfpd_obj: + return {} + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = DOM_OFFSET + transceiver_dom_info_dict = dict.fromkeys(transceiver_dom_info_dict_keys, 'N/A') + + dom_temperature_raw = self.__read_eeprom_specific_bytes((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) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes((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) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_voltage_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_voltage_data['data']['TXPower']['value'] + transceiver_dom_info_dict['rx1power'] = dom_voltage_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_voltage_data['data']['TXBias']['value'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self.__convert_string_to_num(transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['tx_disable'] = self.get_tx_disable() + transceiver_dom_info_dict['tx_disable_channel'] = self.get_tx_disable_channel() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + transceiver_dom_threshold_info_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + sfpd_obj = sff8472Dom() + + if not self.get_presence() and not sfpd_obj: + return {} + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = DOM_OFFSET + transceiver_dom_threshold_info_dict = dict.fromkeys(transceiver_dom_threshold_info_dict_keys, 'N/A') + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((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) + + 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'] + + for key in transceiver_dom_threshold_info_dict: + transceiver_dom_threshold_info_dict[key] = self.__convert_string_to_num(transceiver_dom_threshold_info_dict[key]) + + return transceiver_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + rx_los = False + status_control_raw = self.__read_eeprom_specific_bytes(SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + rx_los = (sffbase().test_bit(data, 1) != 0) + + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + tx_fault = False + status_control_raw = self.__read_eeprom_specific_bytes(SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + tx_fault = (sffbase().test_bit(data, 2) != 0) + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + tx_disable = False + tx_fault = False + status_control_raw = self.__read_eeprom_specific_bytes(SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + tx_disable_hard = (sffbase().test_bit(data, SFP_TX_DISABLE_HARD_BIT) != 0) + tx_disable_soft = (sffbase().test_bit(data, SFP_TX_DISABLE_SOFT_BIT) != 0) + tx_disable = tx_disable_hard | tx_disable_soft + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + # SFP doesn't support this feature + return 0 + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("temperature", "N/A") + + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("voltage", "N/A") + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A") + return [tx1_bs, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A") + return [rx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A") + return [tx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + # SFP doesn't support this feature + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + sysfs_eeprom_path = self.__eeprom_path + status_control_raw = self.__read_eeprom_specific_bytes(SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw is not None: + # Set bit 6 for Soft TX Disable Select + # 01000000 = 64 and 10111111 = 191 + tx_disable_bit = 64 if tx_disable else 191 + status_control = int(status_control_raw[0], 16) + tx_disable_ctl = (status_control | tx_disable_bit) if tx_disable else (status_control & tx_disable_bit) + try: + sysfsfile_eeprom = open(sysfs_eeprom_path, mode="r+b", buffering=0) + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom.seek(SFP_STATUS_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except: + #print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + # SFP doesn't support this feature + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + # SFP doesn't support this feature + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + # SFP doesn't support this feature + return False + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/thermal.py new file mode 100644 index 000000000000..eba7ba728de9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/thermal.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python +# +# Name: thermal.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Thermal(ThermalBase): + + def __init__(self, index): + self.__index = index + + #thermal name list + self.__thermal_name_list = [ "PCH Temperature Sensor", + "CPU Board Temperature Sensor", + "FrontSide Temperature Sensor", + "NearASIC Temperature Sensor", + "RearSide Temperature Sensor" ] + + offset = 0 + if 0 != self.__index: + offset = 2 + self.__presence_attr = "/sys/class/hwmon/hwmon{}/temp1_input".format(self.__index + offset) + self.__temperature_attr = "/sys/class/hwmon/hwmon{}/temp1_input".format(self.__index + offset) + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return self.__thermal_name_list[self.__index] or "Unknown" + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = self.__presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) != 0): + 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 + """ + return "N/A" + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + return "N/A" + + 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() + +############################################## +# THERMAL methods +############################################## + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temperature = 0.0 + attr_path = self.__temperature_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + temperature = float(attr_rv) / 1000 + + return temperature + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + raise NotImplementedError + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + raise NotImplementedError + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/transceiver_event.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/transceiver_event.py new file mode 100644 index 000000000000..3eda411de3ba --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/transceiver_event.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# +# Name: transceiver_event.py, version: 1.0 +# + +try: + import time + import socket + import re + import os + from collections import OrderedDict +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class NetlinkEventMonitor(object): + __instance = None + + def __new__(cls, *args, **kwargs): + if not cls.__instance: + # print(cls) + cls.__instance = super(NetlinkEventMonitor, cls).__new__(cls) + cls.__instance.__recieved_events = OrderedDict() + return cls.__instance + + def __init__(self, timeout): + # print('__init__', self) + NETLINK_KOBJECT_UEVENT = 15 + self.__socket = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT) + self.__timeout = timeout + + def start(self): + # print('start', self.__timeout) + self.__socket.bind((os.getpid(), -1)) + if 0 == self.__timeout: + self.__socket.settimeout(None) + else: + self.__socket.settimeout(self.__timeout/1000.0) + + def stop(self): + self.__socket.close() + + def __enter__(self): + # print('__enter__', self) + self.start() + return self + + def __exit__(self, exc_type, exc_value, traceback): + # print('__exit__', self) + self.stop() + + def __iter__(self): + # print('__iter__', self) + while True: + for item in self.next_events(): + yield item + + def next_events(self): + try: + data = self.__socket.recv(16384) + event = {} + for item in data.split(b'\x00'): + if not item: + # check if we have an event and if we already received it + if event and 'SEQNUM' in event: + event_seqnum = event['SEQNUM'] + if event_seqnum in self.__recieved_events: + pass + else: + # print("=", event_seqnum) + self.__recieved_events[event_seqnum] = event + length = len(self.__recieved_events) + # print("=", length) + if (length > 100): + self.__recieved_events.popitem(last=False) + yield event + event = {} + else: + try: + k, v = item.split(b'=', 1) + event[k.decode('ascii')] = v.decode('ascii') + # print("=",k,v) + except ValueError: + pass + except Exception: + yield {} + +class TransceiverEvent(object): + + def __init__(self): + pass + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + with NetlinkEventMonitor(timeout) as netlink_monitor: + for event in netlink_monitor: + if event and 'SUBSYSTEM' in event: + if event['SUBSYSTEM'] == 'swps': + #print('SWPS event. From %s, ACTION %s, IF_TYPE %s, IF_LANE %s' % (event['DEVPATH'], event['ACTION'], event['IF_TYPE'], event['IF_LANE'])) + portname = event['DEVPATH'].split("/")[-1] + rc = re.match(r"port(?P\d+)",portname) + if rc is not None: + if event['ACTION'] == "remove": + remove_num = int(rc.group("num")) + port_dict[remove_num] = "0" + elif event['ACTION'] == "add": + add_num = int(rc.group("num")) + port_dict[add_num] = "1" + return True, port_dict + else: + return False, {} + else: + pass + else: + return True, {} + 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 new file mode 100755 index 000000000000..10fcb001b0c2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Inventec, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV: ', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[D6356]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +" with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + + +instantiate = [ +'echo inv_eeprom 0x55 > /sys/bus/i2c/devices/i2c-0/i2c-2/new_device' +#'echo inv_cpld 0x33 > /sys/bus/i2c/devices/i2c-0/i2c-2/new_device', +#'echo inv_cpld 0x77 > /sys/bus/i2c/devices/i2c-0/i2c-2/new_device' +] + + +drivers =[ +#kernel-dirvers +'lpc_ich', +'i2c-i801', +'i2c-mux', +'i2c-mux-pca954x', +'i2c-mux-pca9541', +'i2c-dev', +'ucd9000', +#inv-modules +'inv_eeprom', +'inv_cpld', +'inv_platform', +#'monitor', +'swps'] + + + +def system_install(): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("rmmod i2c_ismt ", 1) + status, output = exec_cmd("rmmod i2c-i801 ", 1) + status, output = exec_cmd("rmmod gpio_ich ", 1) + status, output = exec_cmd("rmmod lpc_ich ", 1) + + #insert extra module + 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)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #instantiate devices + for i in range(0,len(instantiate)): + #time.sleep(1) + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status +# +# INV_FIX-4037 +# It replaces the original sff8436 driver with the optoe driver +# + #optoe map to i2c-bus + for i in range(14,22): + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-6/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(22,30): + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-7/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(30,38): + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-8/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(38,46): + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-9/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(46,54): + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-10/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(54,62): + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-11/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(62,70): + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-12/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print "D6356 devices detected...." + return + +def uninstall(): + global FORCE + #uninstall drivers + exec_cmd("rmmod gpio_ich",1) + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0) + ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-5", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/Makefile new file mode 100644 index 000000000000..c13abd37e129 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/Makefile @@ -0,0 +1,6 @@ +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += inv_eeprom.o +obj-m += swps.o +obj-m += inv_pthread.o +swps-objs := inv_swps.o inv_mux.o io_expander.o transceiver.o diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_cpld.c new file mode 100644 index 000000000000..5ee4b26cdab9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_cpld.c @@ -0,0 +1,526 @@ +/* + * 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 "I2CHostCommunication.h" + +#define USE_SMBUS 1 + +/* definition */ +#define CPLD_INFO_OFFSET 0x00 +#define CPLD_PSU_OFFSET 0x08 +#define CPLD_LED_OFFSET 0x0E +#define CPLD_LED_STATU_OFFSET 0x0D +#define CPLD_CTL_OFFSET 0x0C +#define CPLD_BIOSCS_OFFSET 0x04 +#define CPLD_PSUFANLED_OFFSET 0x75 + +/* Each client has this additional data */ +struct cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +} + +static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t show_info(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[4]; + + memset(b, 0, 4); + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4); + mutex_unlock(&data->update_lock); + + if(status != 4) return sprintf(buf, "read cpld info fail\n"); + + status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/ + status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf); + status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf); + + return strlen(buf); +} + + +static ssize_t show_ctl(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[1]; + + mutex_lock(&data->update_lock); + + status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld ctl fail\n"); + + + status = sprintf (buf, "0x%X\n", b[0]); + + return strlen(buf); +} + +static ssize_t set_ctl(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1); + if(temp) byte |= (1<<0); + else byte &= ~(1<<0); + cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_bios_cs(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[1]; + + mutex_lock(&data->update_lock); + + status = cpld_i2c_read(client, b, CPLD_BIOSCS_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld BIOS_CS fail\n"); + + + status = sprintf (buf, "0x%X\n", b[0] & 0x01); + + return strlen(buf); +} + +static ssize_t set_bios_cs(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1); + if(temp) byte |= 0x01; + else byte &= ~(0x01); + cpld_i2c_write(client, &byte, CPLD_BIOSCS_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + + +static char* led_str[] = { + "OFF", //000 + "0.5 Hz", //001 + "1 Hz", //010 + "2 Hz", //011 + "4 Hz", //100 + "NA", //101 + "NA", //110 + "ON", //111 +}; + +static ssize_t show_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d: %s\n", byte, led_str[byte]); + + return strlen(buf); +} + +static ssize_t set_led(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 16); + u8 byte; + int shift = (attr->index == 0)?3:0; + + temp &= 0x7; + //validate temp value: 0,1,2,3,7, TBD + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + byte &= ~(0x7<update_lock); + + return count; +} + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu0 | psu1 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 1)?0:3; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + +static char* status_psufan_str[] = { + "OFF", //00 + "ON", //01 + "1 Hz", //10 + "2 Hz", //11 +}; + +static ssize_t show_psufan_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 red_status, grn_status, byte; + int shift = (attr->index == 0)?0:2; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_PSUFANLED_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte>>shift) & 0x33; + grn_status = byte >> 4; + red_status = byte & 0x03; + + return sprintf (buf, "0x%02x: Green %s , Red %s\n", byte, status_psufan_str[grn_status],status_psufan_str[red_status]); +} + +static ssize_t set_psufan_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int shift = (attr->index == 0)?0:2; + int mask = (attr->index == 0)?0xcc:0x33; + u8 temp = simple_strtol(buf, NULL, 16) & 0x33; + u8 byte = 0; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_PSUFANLED_OFFSET, 1); + byte &= mask; + byte |= (temp<update_lock); + + return count; +} + + +static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0); +static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0); + +static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0); +static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1); + +static SENSOR_DEVICE_ATTR(fan_led, S_IWUSR|S_IRUGO, show_psufan_led, set_psufan_led, 0); +static SENSOR_DEVICE_ATTR(psu_led, S_IWUSR|S_IRUGO, show_psufan_led, set_psufan_led, 1); + +static SENSOR_DEVICE_ATTR(bios_cs, S_IWUSR|S_IRUGO, show_bios_cs, set_bios_cs, 0); + +static struct attribute *cpld_attributes[] = { + //info + &sensor_dev_attr_info.dev_attr.attr, + &sensor_dev_attr_ctl.dev_attr.attr, + + &sensor_dev_attr_grn_led.dev_attr.attr, + &sensor_dev_attr_red_led.dev_attr.attr, + + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + &sensor_dev_attr_fan_led.dev_attr.attr, + &sensor_dev_attr_psu_led.dev_attr.attr, + + &sensor_dev_attr_bios_cs.dev_attr.attr, + + NULL +}; + +static const struct attribute_group cpld_group = { + .attrs = cpld_attributes, +}; + +static struct attribute *cpld2_attributes[] = { + //info + &sensor_dev_attr_info.dev_attr.attr, + + NULL +}; + +static const struct attribute_group cpld2_group = { + .attrs = cpld2_attributes, +}; + + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int +cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + +// printk("+%s \n", __func__); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + if(id->driver_data==1) // CPLD2 + status = sysfs_create_group(&client->dev.kobj, &cpld2_group); + else // default CPLD1 + status = sysfs_create_group(&client->dev.kobj, &cpld_group); + + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpld_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpld_group); + i2c_set_clientdata(client, NULL); + kfree(data); + return 0; +} + +static const struct i2c_device_id cpld_ids[] = { + { "inv_cpld" , 0, }, + { "inv_cpld2", 1, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, cpld_ids); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_cpld_init(void) +{ + return i2c_add_driver(&cpld_driver); +} + +static void __exit inv_cpld_exit(void) +{ + i2c_del_driver(&cpld_driver); +} + +MODULE_AUTHOR("eddie.lan "); +MODULE_DESCRIPTION("inv cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_cpld_init); +module_exit(inv_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_eeprom.c new file mode 100644 index 000000000000..7bb167d2e74e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_eeprom.c @@ -0,0 +1,181 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void inv_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } + +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + inv_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute inv_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = inv_eeprom_read, +}; + +static int inv_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int inv_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id inv_eeprom_id[] = { + { "inv_eeprom", 0 }, + { } +}; + +static struct i2c_driver inv_eeprom_driver = { + .driver = { + .name = "inv_eeprom", + }, + .probe = inv_eeprom_probe, + .remove = inv_eeprom_remove, + .id_table = inv_eeprom_id, +}; + +module_i2c_driver(inv_eeprom_driver); + +MODULE_AUTHOR("Inventec"); +MODULE_DESCRIPTION("Inventec D6556 Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.c new file mode 100644 index 000000000000..a303527bec46 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.c @@ -0,0 +1,281 @@ +/* + * 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 "io_expander.h" +#include "inv_mux.h" + +static struct mux_obj_s *mux_head_p = NULL; + + +/* ========== MUX object functions ========== + */ +int +_common_force_pull_gpio(int mem_addr, + int input, + int bit_offset){ + + unsigned int val = 0; + unsigned int targ = 0; + + /* Get current value */ + val = inl(mem_addr); + if (val == 0) { + SWPS_ERR("%s: inl:%d fail!\n", __func__, val); + return -1; + } + /* Count target value */ + switch (input) { + case 0: /* Pull Low */ + targ = (val & (~(1 << bit_offset))); + break; + case 1: /* Pull high */ + targ = (val | (1 << bit_offset)); + break; + default: + SWPS_ERR("%s: input state:%d incorrect!\n", + __func__, input); + return -1; + } + /* Setup gpio */ + outl(targ, mem_addr); + if (targ != inl(mem_addr)){ + SWPS_ERR("%s: outl:%d fail!\n", __func__, targ); + return -1; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + + +int +rangeley_force_pull_high(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +rangeley_force_pull_low(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +hedera_force_pull_high(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 1, 5); +} + + +int +hedera_force_pull_low(struct mux_obj_s *self){ + return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 0, 5); +} + + +int +normal_gpio_pull_high(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 1); +} + + +int +normal_gpio_pull_low(struct mux_obj_s *self){ + return gpio_direction_output(self->gpio_num, 0); +} + + +int +pca9548_reset_mux_all(struct mux_obj_s *self){ + /* [Note] Power-on reset (PCA9548A-NXP) + * When power is applied to VDD, an internal Power-On Reset (POR) + * holds the PCA9548A in a reset condition until VDD has reached + * VPOR. At this point, the reset condition is released and the + * PCA9548A register and I2C-bus state machine are initialized to + * their default states (all zeroes) causing all the channels to + * be deselected. Thereafter, VDD must be lowered below 0.2 V for + * at least 5 us in order to reset the device. + */ + if (self->_pull_low(self) < 0) { + SWPS_ERR("%s: _pull_low fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS); + if (self->_pull_high(self) < 0) { + SWPS_ERR("%s: _pull_high fail!\n", __func__); + return -1; + } + mdelay(MUX_RST_WAIT_MS); + return 0; +} + + +int +common_reset_mux_all(struct mux_obj_s *self){ + SWPS_ERR("%s: not ready!\n", __func__); + return -1; +} + + +int +init_gpio_4_force(struct mux_obj_s *self){ + return 0; +} + + +int +init_gpio_4_normal(struct mux_obj_s *self){ + + int err = 0; + + if (!gpio_is_valid(self->gpio_num)) { + SWPS_ERR("%s: GIPO:%d isn't valid\n", __func__, self->gpio_num); + return -1; + } + err = gpio_request(self->gpio_num, MUX_GPIO_LABEL); + if (err < 0) { + SWPS_ERR("%s: gpio_request fail :%d :%d\n", + __func__, err, self->gpio_num); + return -1; + } + SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num); + return 0; +} + + +static int +_setup_muxctl_cb(struct mux_obj_s *self, + unsigned gpio){ + + char mod_dsc[32] = "ERR"; + + switch (gpio) { + case MUX_RST_GPIO_FORCE_RANGELEY: + self->gpio_num = gpio; + self->_pull_low = rangeley_force_pull_low; + self->_pull_high = rangeley_force_pull_high; + self->_init = init_gpio_4_force; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Rangeley force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_FORCE_HEDERA: + self->gpio_num = gpio; + self->_pull_low = hedera_force_pull_low; + self->_pull_high = hedera_force_pull_high; + self->_init = init_gpio_4_force; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Hedera force mode"); + goto ok_setup_muxctl_cb; + + case MUX_RST_GPIO_48_PAC9548: + case MUX_RST_GPIO_69_PAC9548: + case MUX_RST_GPIO_249_PCA9548: + case MUX_RST_GPIO_500_PAC9548: + case MUX_RST_GPIO_505_PCA9548: + self->gpio_num = gpio; + self->_pull_low = normal_gpio_pull_low; + self->_pull_high = normal_gpio_pull_high; + self->_init = init_gpio_4_normal; + self->reset = pca9548_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "Normal mode :%d", (int)gpio); + goto ok_setup_muxctl_cb; + + default: + break; + } + SWPS_ERR("%s: Unexpected GPIO:%d\n", __func__, gpio); + return -1; + +ok_setup_muxctl_cb: + SWPS_INFO("muxctl: %s.\n", mod_dsc); + return 0; +} + + +/* ========== MUX public functions ========== + */ +void +clean_mux_gpio(void){ + + if (!mux_head_p) { + SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__); + return; + } + if (gpio_is_valid(mux_head_p->gpio_num)) { + gpio_free(mux_head_p->gpio_num); + } + kfree(mux_head_p); + mux_head_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} + + +int +reset_mux_gpio(void){ + + if (!mux_head_p) { + SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__); + return -1; + } + if (mux_head_p->reset(mux_head_p) < 0){ + SWPS_ERR("%s: reset fail!\n", __func__); + return -1; + } + return 0; +} + + +int +init_mux_gpio(unsigned gpio){ + + /* Create MUX control object */ + if (mux_head_p) { + SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__); + clean_mux_gpio(); + } + /* Currently, it is using single muxctl architecture. + * In the future, it may use the multi-muxctl if HW add new features. + * (Ex: Port power-status control) + */ + mux_head_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL); + if (!mux_head_p) { + SWPS_ERR("%s: kzalloc fail!\n", __func__); + return -1; + } + /* Initial MUX controller */ + if (_setup_muxctl_cb(mux_head_p, gpio) < 0){ + SWPS_ERR("%s: _setup_muxctl_cb fail!\n", __func__); + return -1; + } + if (mux_head_p->_init(mux_head_p) < 0) { + SWPS_ERR("%s: init() fail\n", __func__); + goto err_init_mux_gpio; + } + /* Setup default value */ + if (mux_head_p->_pull_high(mux_head_p) < 0) { + SWPS_ERR("%s: setup default fail!\n", __func__); + goto err_init_mux_gpio; + } + return 0; + +err_init_mux_gpio: + clean_mux_gpio(); + return -1; +} + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.h b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.h new file mode 100644 index 000000000000..f981a304644a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_mux.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef INV_MUX_H +#define INV_MUX_H + + +/* MUX basic information */ +#define MUX_GPIO_LABEL "SWPS_RST_MUX" + +/* MUX reset GPIO define */ +#define MUX_RST_GPIO_FORCE (30100) +#define MUX_RST_GPIO_FORCE_RANGELEY (30101) +#define MUX_RST_GPIO_FORCE_HEDERA (30102) +#define MUX_RST_GPIO_48_PAC9548 (48) +#define MUX_RST_GPIO_69_PAC9548 (69) +#define MUX_RST_GPIO_249_PCA9548 (249) +#define MUX_RST_GPIO_500_PAC9548 (500) +#define MUX_RST_GPIO_505_PCA9548 (505) + +/* MUX relate value define */ +#define MUX_RST_WAIT_MS (1) +#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD +#define MUX_RST_MEM_ADDR_HEDERA (0x548) + +struct mux_obj_s { + unsigned gpio_num; + int (*_pull_high)(struct mux_obj_s *self); + int (*_pull_low)(struct mux_obj_s *self); + int (*_init)(struct mux_obj_s *self); + int (*reset)(struct mux_obj_s *self); +}; + + +void clean_mux_gpio(void); +int reset_mux_gpio(void); +int init_mux_gpio(unsigned gpio); + + +#endif /* INV_MUX_H */ + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_platform.c new file mode 100644 index 000000000000..ba11c275ce81 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_platform.c @@ -0,0 +1,215 @@ +/* + * 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 + +struct inv_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +#define bus_id(id) (id) +static struct pca954x_platform_mode mux_modes_0[] = { + {.adap_id = bus_id(2),}, {.adap_id = bus_id(3),}, + {.adap_id = bus_id(4),}, {.adap_id = bus_id(5),}, + {.adap_id = bus_id(6),}, {.adap_id = bus_id(7),}, + {.adap_id = bus_id(8),}, {.adap_id = bus_id(9),}, +}; +static struct pca954x_platform_mode mux_modes_0_0[] = { + {.adap_id = bus_id(10),}, {.adap_id = bus_id(11),}, + {.adap_id = bus_id(12),}, {.adap_id = bus_id(13),}, + {.adap_id = bus_id(14),}, {.adap_id = bus_id(15),}, + {.adap_id = bus_id(16),}, {.adap_id = bus_id(17),}, +}; + +static struct pca954x_platform_mode mux_modes_0_1[] = { + {.adap_id = bus_id(18),}, {.adap_id = bus_id(19),}, + {.adap_id = bus_id(20),}, {.adap_id = bus_id(21),}, + {.adap_id = bus_id(22),}, {.adap_id = bus_id(23),}, + {.adap_id = bus_id(24),}, {.adap_id = bus_id(25),}, +}; + +static struct pca954x_platform_mode mux_modes_0_2[] = { + {.adap_id = bus_id(26),}, {.adap_id = bus_id(27),}, + {.adap_id = bus_id(28),}, {.adap_id = bus_id(29),}, + {.adap_id = bus_id(30),}, {.adap_id = bus_id(31),}, + {.adap_id = bus_id(32),}, {.adap_id = bus_id(33),}, +}; + +static struct pca954x_platform_mode mux_modes_0_3[] = { + {.adap_id = bus_id(34),}, {.adap_id = bus_id(35),}, + {.adap_id = bus_id(36),}, {.adap_id = bus_id(37),}, + {.adap_id = bus_id(38),}, {.adap_id = bus_id(39),}, + {.adap_id = bus_id(40),}, {.adap_id = bus_id(41),}, +}; + +static struct pca954x_platform_mode mux_modes_0_4[] = { + {.adap_id = bus_id(42),}, {.adap_id = bus_id(43),}, + {.adap_id = bus_id(44),}, {.adap_id = bus_id(45),}, + {.adap_id = bus_id(46),}, {.adap_id = bus_id(47),}, + {.adap_id = bus_id(48),}, {.adap_id = bus_id(49),}, +}; + +static struct pca954x_platform_mode mux_modes_0_5[] = { + {.adap_id = bus_id(50),}, {.adap_id = bus_id(51),}, + {.adap_id = bus_id(52),}, {.adap_id = bus_id(53),}, + {.adap_id = bus_id(54),}, {.adap_id = bus_id(55),}, + {.adap_id = bus_id(56),}, {.adap_id = bus_id(57),}, +}; + +static struct pca954x_platform_mode mux_modes_0_6[] = { + {.adap_id = bus_id(58),}, {.adap_id = bus_id(59),}, + {.adap_id = bus_id(60),}, {.adap_id = bus_id(61),}, + {.adap_id = bus_id(62),}, {.adap_id = bus_id(63),}, + {.adap_id = bus_id(64),}, {.adap_id = bus_id(65),}, +}; + +//no i2c device driver attach to mux 7 + + +static struct pca954x_platform_data mux_data_0 = { + .modes = mux_modes_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_0 = { + .modes = mux_modes_0_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_1 = { + .modes = mux_modes_0_1, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_2 = { + .modes = mux_modes_0_2, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_3 = { + .modes = mux_modes_0_3, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_4 = { + .modes = mux_modes_0_4, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_5 = { + .modes = mux_modes_0_5, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_6 = { + .modes = mux_modes_0_6, + .num_modes = 8, +}; + +static struct i2c_board_info i2c_device_info0[] __initdata = { + {"pca9548", 0, 0x70, &mux_data_0, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info2[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, +}; +static struct i2c_board_info i2c_device_info3[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, +}; +static struct i2c_board_info i2c_device_info4[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, +}; +static struct i2c_board_info i2c_device_info5[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, +}; +static struct i2c_board_info i2c_device_info6[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0}, +}; +static struct i2c_board_info i2c_device_info7[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0}, +}; +static struct i2c_board_info i2c_device_info8[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0}, +}; + + +static struct inv_i2c_board_info i2cdev_list[] = { + {bus_id(1), ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //mux root + + {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux 0 + {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux 1 + {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux 2 + {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux 3 + {bus_id(6), ARRAY_SIZE(i2c_device_info6), i2c_device_info6 }, //mux 4 + {bus_id(7), ARRAY_SIZE(i2c_device_info7), i2c_device_info7 }, //mux 5 + {bus_id(8), ARRAY_SIZE(i2c_device_info8), i2c_device_info8 }, //mux 6 +}; + +///////////////////////////////////////////////////////////////////////////////////////// +static struct i2c_gpio_platform_data i2c_gpio_platdata0 = { + .scl_pin = 238, + .sda_pin = 255, + + .udelay = 5, //5:100kHz + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, + .scl_is_output_only = 0 +}; + +static struct platform_device device_i2c_gpio0 = { + .name = "i2c-gpio", + .id = 1, // adapter number + .dev.platform_data = &i2c_gpio_platdata0, +}; + +static int __init inv_platform_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j,k; + + //use i2c-gpio + //register i2c gpio + //config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 gpio69=32*2+8*0+5 + outl( inl(0x533) | (1<<2), 0x533); + outl( inl(0x541) | (1<<3), 0x541); + outl( inl(0x540) | (1<<5), 0x540); //RST_I2C_MUX_N (GPIO69) + outl( inl(0x500) | (1<<7), 0x500); //SYS_RDY_N (GPIO7) + outl( inl(0x501) | (1<<7), 0x501); //BMC_HEART_BEAT (GPIO15) + outl( inl(0x503) | (1<<2)|(1<<3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27) + + + ret = platform_device_register(&device_i2c_gpio0); + if (ret) { + printk(KERN_ERR "i2c-gpio: device_i2c_gpio0 register fail %d\n", ret); + } + mdelay(500); //wait for device_i2c_gpio register successfully + + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define SWITCH_TEMPERATURE_SOCK "/proc/switch/temp" +#define PSOC_POLLING_PERIOD 1000 + +#include +#include +#include +#include + +#define IPMI_MAX_INTF (4) +#define NETFN_OEM 0x30 +#define CMD_GETDATA 0x31 +#define CMD_SETDATA 0x32 +#define FAN_NUM 4 +#define PSU_NUM 2 + +#define FAN_CLEI_SUPPORT 1 +#define PSU_CLEI_SUPPORT 0 + +#define PSU1 0x5800 +#define PSU2 0x5900 +#define BMC_PMBusNumber 3 +#define PMBus_Vendor 0x99 +#define PMBus_Serial 0x9E +#define PMBus_Temp2 0x8E +#define PMBus_Version 0x9B +#define MaxLeng_Result 0x40 + +#define BMC_FanCLEIBusNumber 9 +#define DEVICE_CLEI_ADDR 0x52,0x53,0x54,0x55,0x56,0x50,0x51 + +#define MAX_IPMI_RECV_LENGTH 0xff +static char CLEI_ADDR[]={DEVICE_CLEI_ADDR}; +struct task_struct *kthread_auto_update; +static long pmbus_reg2data_linear(int data, int linear16); +struct ipmi_result{ + char result[MAX_IPMI_RECV_LENGTH]; + int result_length; +}; + +DEFINE_MUTEX(ipmi_mutex); +DEFINE_MUTEX(ipmi2_mutex); +static struct ipmi_result ipmiresult; +static struct device *hwmon_dev; +static struct kobject *device_kobj; +static ipmi_user_t ipmi_mh_user = NULL; +static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data); +static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,}; + +static atomic_t dummy_count = ATOMIC_INIT(0); +static void dummy_smi_free(struct ipmi_smi_msg *msg) +{ + atomic_dec(&dummy_count); +} +static void dummy_recv_free(struct ipmi_recv_msg *msg) +{ + atomic_dec(&dummy_count); +} +static struct ipmi_smi_msg halt_smi_msg = { + .done = dummy_smi_free +}; +static struct ipmi_recv_msg halt_recv_msg = { + .done = dummy_recv_free +}; + +struct __attribute__ ((__packed__)) psoc_psu_layout { + u16 psu1_iin; + u16 psu2_iin; + u16 psu1_iout; + u16 psu2_iout; + + u16 psu1_pin; + u16 psu2_pin; + u16 psu1_pout; + u16 psu2_pout; + + u16 psu1_vin; + u16 psu2_vin; + u16 psu1_vout; + u16 psu2_vout; +}; + +struct __attribute__ ((__packed__)) clei { + u8 issue_number[3]; + u8 abbreviation_number[9]; + u8 fc_number[10]; + u8 clei_code[10]; + u8 product_year_and_month[5]; + u8 label_location_code[2]; + u8 serial_number[5]; + u8 pcb_revision[5]; + u8 vendor_name[10]; + u8 reserved[5]; +}; + +struct __attribute__ ((__packed__)) psoc_layout { + u8 ctl; //offset: 0 + u16 switch_temp; //offset: 1 + + // BYTE[03:20] - voltage + u16 voltage[15]; //offset: 0x03-0x20 + + // BYTE[21:27] - ExtFan + u8 led_ctl2; //offset: 21 + u8 ext_pwm; //offset: 22 + u16 ext_rpm[2]; //offset: 23 + u8 gpi_fan2; //offset: 27 + + //gpo + u8 led_ctl; //offset: 28 + + u8 gpio; //offset: 29 + + //pwm duty + u8 pwm[4]; //offset: 2a + u8 pwm_psu[2]; //offset: 2e + + //fan rpm + u16 fan[4*2]; //offset: 30 + + u8 reserve1[4]; //offset: 40 + + //gpi + u8 gpi_fan; //offset: 44 + + //psu state + u8 psu_state; //offset: 45 + + //temperature + u16 temp[5]; //offset: 46 + u16 temp_psu[2]; //offset: 50 + + //version + u8 version[2]; //offset: 54 + + u8 reserve2[4]; //offset: 56 + struct psoc_psu_layout psu_info; //offset: 5a +}; + +/* definition */ +#define PSOC_OFF(m) offsetof(struct psoc_layout, m) +#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m) + +#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp) +#define PWM_OFFSET PSOC_OFF(pwm) +#define THERMAL_OFFSET PSOC_OFF(temp) +#define RPM_OFFSET PSOC_OFF(fan) +#define DIAG_FLAG_OFFSET PSOC_OFF(ctl) +#define FAN_LED_OFFSET PSOC_OFF(led_ctl) +#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan) +#define PSOC_PSU_OFFSET PSOC_OFF(psu_state) +#define VERSION_OFFSET PSOC_OFF(version) +#define PSU_INFO_OFFSET PSOC_OFF(psu_info) + +#define PWM2_OFFSET PSOC_OFF(ext_pwm) +#define RPM2_OFFSET PSOC_OFF(ext_rpm) +#define FAN_LED2_OFFSET PSOC_OFF(led_ctl2) +#define FAN_GPI2_OFFSET PSOC_OFF(gpi_fan2) + +#define CLEI_OFF(m) offsetof(struct clei, m) +#define FAN1_CLEI_INDEX 0 +#define FAN2_CLEI_INDEX 1 +#define FAN3_CLEI_INDEX 2 +#define FAN4_CLEI_INDEX 3 +#define FAN5_CLEI_INDEX 4 +#define PSU1_CLEI_INDEX 5 +#define PSU2_CLEI_INDEX 6 + +static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data) +{ + struct ipmi_result *msg_result = recv_msg->user_msg_data; + + if(recv_msg->msg.data[0]==0 && recv_msg->msg.data_len>0) { + msg_result->result_length=recv_msg->msg.data_len-1; + memcpy(msg_result->result, &recv_msg->msg.data[1], recv_msg->msg.data_len-1); + } + ipmi_free_recv_msg(recv_msg); + mutex_unlock(&ipmi_mutex); + + return; +} + +int start_ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length) +{ + int rv=0,i; + int timeout; + + //wait previous command finish at least 50msec + timeout=50; + while((mutex_is_locked(&ipmi_mutex) == 1 || (mutex_is_locked(&ipmi2_mutex) == 1)) && (--timeout)>0) { usleep_range(1000,1010); } + if(timeout==0) { return -1; } + mutex_lock(&ipmi_mutex); + mutex_lock(&ipmi2_mutex); + + if(ipmi_mh_user == NULL) { + for (i=0,rv=1; i0) { usleep_range(1000,1100);} + if(timeout==0) { + mutex_unlock(&ipmi2_mutex); + return -1; + } + else { + *result_length=ipmiresult.result_length; + memcpy(result,ipmiresult.result,*result_length); + mutex_unlock(&ipmi2_mutex); + return 0; + } + } + return 0; +} +EXPORT_SYMBOL(start_ipmi_command); + +static ssize_t psoc_ipmi_read(u8 *buf, u8 offset, size_t count) +{ + uint8_t data[2]; + int result_len=0; + int rv; + + data[0] = offset; + data[1] = count; + + rv=start_ipmi_command(NETFN_OEM, CMD_GETDATA,data,2, buf, &result_len); + + return result_len; +} + +static ssize_t psoc_ipmi_write(char *buf, unsigned offset, size_t count) +{ + uint8_t data[count+1],result[1]; + int result_len; + + data[0] = offset; + memcpy(&data[1],buf,count); + + start_ipmi_command(NETFN_OEM, CMD_SETDATA,data,count+1, result, &result_len); + return count; +} + + +static u16 psoc_read16(u8 offset) +{ + u16 value = 0; + u8 buf[]={0,0}; + + if(psoc_ipmi_read(buf, offset, 2) == 2) + value = (buf[0]<<8 | buf[1]<<0); + + return value; +} + +static u8 psoc_read8(u8 offset) +{ + u8 value = 0; + u8 buf = 0; + + if(psoc_ipmi_read(&buf, offset, 1) == 1) + value = buf; + + return value; +} + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu1 | psu0 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu_st(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 byte=0; + int shift = (attr->index == 0)?3:0; + + status = psoc_ipmi_read(&byte, PSOC_PSU_OFFSET, 1); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + +static ssize_t show_ipmi_pmbus(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + uint8_t data[4],result[MaxLeng_Result]; + int result_len=0; + + data[0] = BMC_PMBusNumber; + data[1] = (attr->index & 0xFF00 ) >>7; + data[3] = attr->index & 0xff; + if(data[3]==PMBus_Temp2) + {data[2]=2;} + else + {data[2]=MaxLeng_Result;} + + if(start_ipmi_command(0x06, 0x52,data,4, result, &result_len)==0) + { + if(data[3]==PMBus_Temp2) + { + return sprintf(buf, "%ld \n", pmbus_reg2data_linear(result[0] | (result[1]<<8), 0 )); + } + result[result[0]+1]='\0'; + return sprintf(buf, "%s\n",&result[1] ); + } + else + { + return 0; + } +} + +static ssize_t show_clei(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 device_index = attr->index & 0xFF; + + uint8_t data[5],result[MaxLeng_Result]; + int result_len=0; + + data[0] = (device_index<=FAN5_CLEI_INDEX) ? BMC_FanCLEIBusNumber:BMC_PMBusNumber; + data[1] = CLEI_ADDR[device_index]<<1; + data[2] = sizeof(struct clei); + data[3] = (device_index<=FAN5_CLEI_INDEX) ? 0x00 : 0x01; //PSU CLEI will start from 0x0100 + data[4] = 0; + + if(start_ipmi_command(0x06, 0x52,data,5, result, &result_len)==0) + { + if(result_len < sizeof(struct clei)) memset(result, 0, sizeof(struct clei)); + sprintf (buf, "Issue Number: %.3s\n", &result[CLEI_OFF(issue_number)]); + sprintf (buf, "%sAbbreviation Number: %.9s\n", buf, &result[CLEI_OFF(abbreviation_number)]); + sprintf (buf, "%sFC Number: %.10s\n", buf, &result[CLEI_OFF(fc_number)]); + sprintf (buf, "%sCLEI Code: %.10s\n", buf, &result[CLEI_OFF(clei_code)]); + sprintf (buf, "%sProduct Year and Month: %.5s\n", buf, &result[CLEI_OFF(product_year_and_month)]); + sprintf (buf, "%s2D Label Location Code: %.2s\n", buf, &result[CLEI_OFF(label_location_code)]); + sprintf (buf, "%sSerial Number: %.5s\n", buf, &result[CLEI_OFF(serial_number)]); + sprintf (buf, "%sPCB Revision: %.5s\n", buf, &result[CLEI_OFF(pcb_revision)]); + sprintf (buf, "%sVendor Name: %.10s\n", buf, &result[CLEI_OFF(vendor_name)]); + return strlen(buf); + } + else + { + return sprintf(buf, "NONE\n"); + } +} + +static ssize_t show_thermal(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index * 2 + THERMAL_OFFSET; + + status = psoc_read16(offset); + + return sprintf(buf, "%d\n", + (s8)(status>>8) * 1000 ); +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index; + + status = psoc_read8(offset); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t set_pwm(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index; + u8 pwm = simple_strtol(buf, NULL, 10); + if(pwm > 255) pwm = 255; + psoc_ipmi_write(&pwm, offset, 1); + + return count; +} + + +static ssize_t show_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index; + status = psoc_read16(offset); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + u16 temp = 0; + + status = psoc_ipmi_read((u8*)&temp, SWITCH_TMP_OFFSET, 2); + + status = sprintf (buf, "%d\n", (s8)(temp>>8) * 1000 ); + + return strlen(buf); +} + +static ssize_t set_switch_tmp(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + long temp = simple_strtol(buf, NULL, 10); + u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ; + + psoc_ipmi_write((u8*)&temp2, SWITCH_TMP_OFFSET, 2); + + + return count; +} + +static ssize_t show_diag(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + u8 diag_flag = 0; + + status = psoc_ipmi_read((u8*)&diag_flag, DIAG_FLAG_OFFSET, 1); + + status = sprintf (buf, "%d\n", ((diag_flag & 0x80)?1:0)); + + return strlen(buf); +} + +static ssize_t set_diag(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + u8 value = 0; + u8 diag = simple_strtol(buf, NULL, 10); + + diag = diag?1:0; + + psoc_ipmi_read((u8*)&value, DIAG_FLAG_OFFSET, 1); + if(diag) value |= (1<<7); + else value &= ~(1<<7); + psoc_ipmi_write((u8*)&value, DIAG_FLAG_OFFSET, 1); + + return count; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + + status = psoc_read16(VERSION_OFFSET); + + return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) ); +} + + +static ssize_t show_fan_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 bit = attr->index; + + if(bit < 8) { status = psoc_read8(FAN_LED_OFFSET); } +#if FAN_NUM>4 + if(bit >= 8) { status = psoc_read8(FAN_LED2_OFFSET); bit-=8; } +#endif + + return sprintf(buf, "%d\n", + (status & (1<index; + u8 led_state = 0; + + u8 v = simple_strtol(buf, NULL, 10); + + if(attr->index < 8) { led_state = psoc_read8(FAN_LED_OFFSET ); } +#if FAN_NUM>4 + if(attr->index >= 8) { led_state = psoc_read8(FAN_LED2_OFFSET); bit-=8; } +#endif + if(v) led_state |= (1<index < 8) { psoc_ipmi_write(&led_state, FAN_LED_OFFSET, 1);} +#if FAN_NUM>4 + if(attr->index >= 8) { psoc_ipmi_write(&led_state, FAN_LED2_OFFSET,1);} +#endif + return count; +} + +static ssize_t show_value8(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index; + + status = psoc_read8(offset); + + return sprintf(buf, "0x%02X\n", status ); +} + +static long pmbus_reg2data_linear(int data, int linear16) +{ + s16 exponent; + s32 mantissa; + long val; + + if (linear16) { /* LINEAR16 */ + exponent = -9; + mantissa = (u16) data; + } else { /* LINEAR11 */ + exponent = ((s16)data) >> 11; + exponent = ((s16)( data & 0xF800) ) >> 11; + mantissa = ((s32)((data & 0x7ff) << 5)) >> 5; + } + + //printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa); + val = mantissa; + + /* scale result to micro-units for power sensors */ + val = val * 1000L; + + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index + PSU_INFO_OFFSET; + + status = psoc_read16(offset); + + if((strstr(attr->dev_attr.attr.name, "vout")!=NULL)|(strstr(attr->dev_attr.attr.name, "in3")!=NULL)|(strstr(attr->dev_attr.attr.name, "in4")!=NULL)) { + offset=1; + } + else { + offset=0; + } + + return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, offset )); +} + +static ssize_t show_name(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "inv_psoc\n"); +} + +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4); +static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5); +static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 6); +static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_thermal, 0, 5); +static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_thermal, 0, 6); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3 + PWM_OFFSET); +#if FAN_NUM > 4 +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0 + PWM2_OFFSET); +#endif +static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4 + PWM_OFFSET); +static SENSOR_DEVICE_ATTR(pwm7, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5 + PWM_OFFSET); + +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 0); +static SENSOR_DEVICE_ATTR(psu2, S_IRUGO, show_psu_st, 0, 1); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, show_rpm, 0, 8*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, show_rpm, 0, 9*2 + RPM_OFFSET); + +#if FAN_NUM > 4 +static SENSOR_DEVICE_ATTR(fan9_input , S_IRUGO, show_rpm, 0,0*2 + RPM2_OFFSET); +static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, show_rpm, 0,1*2 + RPM2_OFFSET); +#endif + +static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); +static SENSOR_DEVICE_ATTR(temp6_input, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); + +static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0); +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0); + +static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0); +static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1); +static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2); +static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3); +static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4); +static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5); +static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6); +static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7); + +#if FAN_NUM>4 +static SENSOR_DEVICE_ATTR(fan_led_grn5, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 8); +static SENSOR_DEVICE_ATTR(fan_led_red5, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 12); +static SENSOR_DEVICE_ATTR(fan_gpi2, S_IRUGO, show_value8, 0, FAN_GPI2_OFFSET); +#endif + +static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET); +static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout)); + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout)); +static SENSOR_DEVICE_ATTR(curr3_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout)); +static SENSOR_DEVICE_ATTR(power3_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout)); + +static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout)); + +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout)); +static SENSOR_DEVICE_ATTR(curr4_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout)); +static SENSOR_DEVICE_ATTR(power4_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout)); + +//IPMI +static SENSOR_DEVICE_ATTR(thermal2_psu1, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Temp2); + +static SENSOR_DEVICE_ATTR(psoc_psu1_vendor, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Vendor); +static SENSOR_DEVICE_ATTR(psoc_psu1_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Serial); +static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Version); + +static SENSOR_DEVICE_ATTR(thermal2_psu2, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(psoc_psu2_vendor, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Vendor); +static SENSOR_DEVICE_ATTR(psoc_psu2_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Serial); +static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Version); + +//CLEI +#if FAN_CLEI_SUPPORT +static SENSOR_DEVICE_ATTR(fan1_clei, S_IRUGO, show_clei, 0, FAN1_CLEI_INDEX ); +static SENSOR_DEVICE_ATTR(fan2_clei, S_IRUGO, show_clei, 0, FAN2_CLEI_INDEX ); +static SENSOR_DEVICE_ATTR(fan3_clei, S_IRUGO, show_clei, 0, FAN3_CLEI_INDEX ); +static SENSOR_DEVICE_ATTR(fan4_clei, S_IRUGO, show_clei, 0, FAN4_CLEI_INDEX ); +#if FAN_NUM > 4 +static SENSOR_DEVICE_ATTR(fan5_clei, S_IRUGO, show_clei, 0, FAN5_CLEI_INDEX ); +#endif +#endif + +#if PSU_CLEI_SUPPORT +static SENSOR_DEVICE_ATTR(psu1_clei, S_IRUGO, show_clei, 0, PSU1_CLEI_INDEX ); +static SENSOR_DEVICE_ATTR(psu2_clei, S_IRUGO, show_clei, 0, PSU2_CLEI_INDEX ); +#endif + +static struct attribute *psoc_attributes[] = { + //name + &dev_attr_name.attr, + //thermal + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + &sensor_dev_attr_thermal_psu1.dev_attr.attr, + &sensor_dev_attr_thermal_psu2.dev_attr.attr, + + &sensor_dev_attr_temp7_input.dev_attr.attr, + &sensor_dev_attr_temp8_input.dev_attr.attr, + + //pwm + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, +#if FAN_NUM > 4 + &sensor_dev_attr_pwm5.dev_attr.attr, +#endif + &sensor_dev_attr_pwm_psu1.dev_attr.attr, + &sensor_dev_attr_pwm_psu2.dev_attr.attr, + &sensor_dev_attr_pwm6.dev_attr.attr, + &sensor_dev_attr_pwm7.dev_attr.attr, + + //rpm + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, +#if FAN_NUM > 4 + &sensor_dev_attr_fan9_input.dev_attr.attr, + &sensor_dev_attr_fan10_input.dev_attr.attr, +#endif + &sensor_dev_attr_rpm_psu1.dev_attr.attr, + &sensor_dev_attr_rpm_psu2.dev_attr.attr, + &sensor_dev_attr_fan11_input.dev_attr.attr, + &sensor_dev_attr_fan12_input.dev_attr.attr, + //switch temperature + &sensor_dev_attr_switch_tmp.dev_attr.attr, + &sensor_dev_attr_temp6_input.dev_attr.attr, + + //diag flag + &sensor_dev_attr_diag.dev_attr.attr, + + //version + &sensor_dev_attr_version.dev_attr.attr, + + //fan led + &sensor_dev_attr_fan_led_grn1.dev_attr.attr, + &sensor_dev_attr_fan_led_grn2.dev_attr.attr, + &sensor_dev_attr_fan_led_grn3.dev_attr.attr, + &sensor_dev_attr_fan_led_grn4.dev_attr.attr, + &sensor_dev_attr_fan_led_red1.dev_attr.attr, + &sensor_dev_attr_fan_led_red2.dev_attr.attr, + &sensor_dev_attr_fan_led_red3.dev_attr.attr, + &sensor_dev_attr_fan_led_red4.dev_attr.attr, +#if FAN_NUM >4 + &sensor_dev_attr_fan_led_grn5.dev_attr.attr, + &sensor_dev_attr_fan_led_red5.dev_attr.attr, + &sensor_dev_attr_fan_gpi2.dev_attr.attr, +#endif + //fan GPI + &sensor_dev_attr_fan_gpi.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + &sensor_dev_attr_psu2.dev_attr.attr, + + + //psu_psoc + &sensor_dev_attr_psoc_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pout.dev_attr.attr, + + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_curr3_input.dev_attr.attr, + &sensor_dev_attr_power3_input.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_curr4_input.dev_attr.attr, + &sensor_dev_attr_power4_input.dev_attr.attr, + + //ipmi_i2c_command + &sensor_dev_attr_thermal2_psu1.dev_attr.attr, + &sensor_dev_attr_temp9_input.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_vendor.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_serial.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_version.dev_attr.attr, + + &sensor_dev_attr_thermal2_psu2.dev_attr.attr, + &sensor_dev_attr_temp10_input.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vendor.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_serial.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_version.dev_attr.attr, + + //clei +#if FAN_CLEI_SUPPORT + &sensor_dev_attr_fan1_clei.dev_attr.attr, + &sensor_dev_attr_fan2_clei.dev_attr.attr, + &sensor_dev_attr_fan3_clei.dev_attr.attr, + &sensor_dev_attr_fan4_clei.dev_attr.attr, +#if FAN_NUM > 4 + &sensor_dev_attr_fan5_clei.dev_attr.attr, +#endif +#endif + +#if PSU_CLEI_SUPPORT + &sensor_dev_attr_psu1_clei.dev_attr.attr, + &sensor_dev_attr_psu2_clei.dev_attr.attr, +#endif + NULL +}; + +static const struct attribute_group psoc_group = { + .attrs = psoc_attributes, +}; + +//================================= +static void check_switch_temp(void) +{ + static struct file *f; + mm_segment_t old_fs; + + set_fs(get_ds()); + f = filp_open(SWITCH_TEMPERATURE_SOCK,O_RDONLY,0644); + if(IS_ERR(f)) { + return; + } + else { + char temp_str[]={0,0,0,0,0,0,0}; + loff_t pos = 0; + u16 temp2 = 0; + old_fs = get_fs(); + set_fs(KERNEL_DS); + vfs_read(f, temp_str,6,&pos); + temp2 = ((simple_strtoul(temp_str,NULL,10)/1000) <<8 ) & 0xFF00 ; + psoc_ipmi_write((u8*)&temp2, SWITCH_TMP_OFFSET, 2); + } + filp_close(f,NULL); + set_fs(old_fs); +} + +static int psoc_polling_thread(void *p) +{ + while (!kthread_should_stop()) + { + check_switch_temp(); + set_current_state(TASK_INTERRUPTIBLE); + if(kthread_should_stop()) + break; + + schedule_timeout(msecs_to_jiffies(PSOC_POLLING_PERIOD)); + } + return 0; +} + +static int __init inv_psoc_init(void) +{ + int ret; + + hwmon_dev = hwmon_device_register(NULL); + if (IS_ERR(hwmon_dev)) { + goto fail_hwmon_device_register; + } + + device_kobj = kobject_create_and_add("device", &hwmon_dev->kobj); + if(!device_kobj) { + goto fail_hwmon_device_register; + } + + ret = sysfs_create_group(device_kobj, &psoc_group); + if (ret) { + goto fail_create_group_hwmon; + } + + ret = sysfs_create_group(&hwmon_dev->kobj, &psoc_group); + if (ret) { + goto fail_create_group_hwmon; + } + + kthread_auto_update = kthread_run(psoc_polling_thread,NULL,"BMC_DRIVER"); + if (IS_ERR(kthread_auto_update)) { + goto fail_create_group_hwmon; + } + return ret; + +fail_create_group_hwmon: + hwmon_device_unregister(hwmon_dev); +fail_hwmon_device_register: + return -ENOMEM; +} + +static void __exit inv_psoc_exit(void) +{ + kthread_stop(kthread_auto_update); + if(ipmi_mh_user!=NULL) {ipmi_destroy_user(ipmi_mh_user);} + if(hwmon_dev != NULL) hwmon_device_unregister(hwmon_dev); + sysfs_remove_group(device_kobj, &psoc_group); +} + +MODULE_AUTHOR("Ting.Jack "); +MODULE_DESCRIPTION("inv psoc driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_psoc_init); +module_exit(inv_psoc_exit); + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_pthread.c new file mode 100644 index 000000000000..e3b180cd5eab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_pthread.c @@ -0,0 +1,1459 @@ +/* + * 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. + */ + +/***************************** + Maple platform +******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SHOW_ATTR_WARNING ("N/A") +#define SHOW_ATTR_NOTPRINT ("Not Available") +#define SHOW_ATTR_NOTSUPPORT ("Not Support") + +#define INV_HWMID_MAX (10) +#define INV_HWMID_INIT (-1) + +/*access userspace data to kernel space*/ +#define ACC_R (0) +#define ACC_W (1) + +#define TINY_BUF_SIZE (8) +#define MAX_PATH_SIZE (64) +#define MIN_ACC_SIZE (32) +#define MAX_ACC_SIZE (256) + +/* + * LED definitions + */ +#define STATUS_LED_MODE_AUTO 0 +#define STATUS_LED_MODE_DIAG 1 +#define STATUS_LED_MODE_MANU 2 + +#define STATUS_LED_GRN0 10 // 0 - 000: off +#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz +#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz +#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz +#define STATUS_LED_GRN7 17 // 7 - 111: on +#define STATUS_LED_RED0 20 // 0 - 000: off +#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz +#define STATUS_LED_RED2 22 // 2 - 010: 1 hz +#define STATUS_LED_RED3 23 // 3 - 011: 2 hz +#define STATUS_LED_RED7 27 // 7 - 111: on +#define STATUS_LED_INVALID 0 // Invalid + +ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2); +ssize_t status_led_grn(const char *freq); +ssize_t status_led_red(const char *freq); +ssize_t status_led_diag_mode_enable(void); +ssize_t status_led_diag_mode_disable(void); +int status_led_check_color(void); +int status_led_check_diag_mode(void); + +int status_led_psu_control(void); +ssize_t status_fan_led(const char *freq); +ssize_t status_psu_led(const char *freq); + +#if 1 +/* For timestamps in SYSFS_LOG */ +#define SYSFS_LOG printk +#else +//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args) +#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args) +#endif + +#define INV_PTHREAD_KERNEL_MODULE (1) + +/* inventec_class *********************************/ +static struct kobject *status_kobj; +static struct kset *status_kset; + + +static struct mutex rw_lock; + +static int hwm_psoc = INV_HWMID_INIT; +static int hwm_cpld = INV_HWMID_INIT; + +int get_hwm_psoc(void) +{ + return hwm_psoc; +} + +int get_hwm_cpld(void) +{ + return hwm_cpld; +} + +static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + char *mark = NULL; + ssize_t vfs_ret = 0; + + if (mode == ACC_R) { + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_read(fp, buf, len, &pos); + + mark = strpbrk(buf, "\n"); + if (mark) + *mark = '\0'; + + filp_close(fp, NULL); + set_fs(fs); + } else if (mode == ACC_W) { + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_write(fp, buf, len, &pos); + filp_close(fp, NULL); + set_fs(fs); + } + + return vfs_ret; +} + +int inventec_strtol(const char *sbufp, char **endp, unsigned int base) +{ + char *endptr; + int value = simple_strtol(sbufp, &endptr, base); + if (value == 0 && sbufp == endptr) { + *endp = NULL; + return value; + } + *endp = (char*)1; + return value; +} + +int inventec_singlechar_to_int(const char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + else + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + else + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } + return -1; +} + +int inventec_store_input(char *inputp, int count) +{ + int i = 0; + while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) { + i++; + } + inputp[i] = '\0'; + return strlen(inputp); +} + +#if 0 +/* + * Time stamps for kernel log on yocto + */ +#include + +void SYSFS_LOG(char *fmt, ...) +{ + char buf[80], ts[32]; + va_list args; + int hlen; + + inventec_tmstmp(&ts[0]); + hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line + + va_start(args, fmt); + vsprintf(&buf[hlen-1], fmt, args); + va_end(args); + printk(KERN_WARNING "[p_thread] %s\n", buf); +} +#endif + +ssize_t +inventec_show_attr(char *buf_p, const char *invdevp) +{ + int inv_len = MAX_ACC_SIZE; /* INV driver return max length */ + char tmp_buf[MAX_ACC_SIZE]; + char *str_negative = "-", *mark = NULL; + + /* [Step2] Get data by uaccess */ + memset(tmp_buf, 0, sizeof(tmp_buf)); + mutex_lock(&rw_lock); + if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + mutex_unlock(&rw_lock); + + /* [Step3] Check return value + * - Ex: When transceiver not plugged + * => SWPS return error code "-202" + * => Pic8 need return "NA" (assume) + */ + if (strcspn(tmp_buf, str_negative) == 0) { + /* error case: "-202" */ + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + + /* OK case:*/ + mark = strpbrk(tmp_buf, "\n"); + if (mark) { *mark = '\0'; } + + return sprintf(buf_p, "%s\n", tmp_buf); +} + +ssize_t +inventec_store_attr(const char *buf_p, size_t count, const char *invdevp) +{ + ssize_t ret = 0; + + /* [Step2] Get data by uaccess */ + mutex_lock(&rw_lock); + if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return -EINVAL; + } + mutex_unlock(&rw_lock); + + /* OK case:*/ + return ret; +} + +int sysfs_detect_hwmon_index(void) +{ + char hwmon_buf[MAX_ACC_SIZE]; + char hwmon_path[MAX_PATH_SIZE]; + char hwmon_dev_path[MAX_PATH_SIZE]; + int hwid = 0; + + for (hwid = 0; + hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT); + hwid++) { + memset(hwmon_buf, 0, sizeof(hwmon_buf)); + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/name", hwid); + + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) { + hwm_psoc = hwid; + } + + sprintf(hwmon_dev_path, "/sys/class/hwmon/hwmon%d/device/name", hwid); + inventec_show_attr(hwmon_buf, hwmon_dev_path); + if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) { + hwm_cpld = hwid; + } + } + if (hwid >= INV_HWMID_MAX) { + printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return -1; + } + printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return 0; +} + +static int __init +inventec_class_init(void) +{ + mutex_init(&rw_lock); + +#ifdef INV_PTHREAD_KERNEL_MODULE + if (sysfs_detect_hwmon_index() < 0) { + return -1; + } +#endif + + printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__); + + return 0; +} + +static void __exit +inventec_class_exit(void) +{ + printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__); +} + +/* fan device *************************************/ +#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/device/fan_gpi" +#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/device/fan1_input" +#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/device/fan2_input" +#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/device/fan3_input" +#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/device/fan4_input" +#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/device/fan5_input" +#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/device/fan6_input" +#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/device/fan7_input" +#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/device/fan8_input" + +static char fan_dev_path_state[MAX_PATH_SIZE]; +static char fan_dev_path_fan1_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan2_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan3_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan4_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan5_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan6_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan7_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan8_input[MAX_PATH_SIZE]; + +void sysfs_fan_path_init(void) +{ + sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc()); + sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc()); +} + +#define FAN_STATE_NORMAL "normal" +#define FAN_STATE_FAULTY "faulty" +#define FAN_STATE_UNINSTALLED "uninstalled" +#define FAN_STATE_UNKNOW "unknown state" +#define FAN_STATE_INVALID "Invalid state value" +#define FAN_STATE_READ_ERROR "state read error" + +#define FAN_LOG_UNINSTALLED "removed" +#define FAN_LOG_NORMAL "inserted" + +//#define FAN_STATE_BIT_NORMAL 0 +#define FAN_STATE_BIT_FAULTY 0 +#define FAN_STATE_BIT_UNINSTALLED 1 +#define FAN_STATE_BIT_UNKNOW 2 +#define FAN_STATE_BIT_INVALID 3 +#define FAN_STATE_BIT_READ_ERROR 4 + +static struct fans_tbl_s { + char *fan_name; + char *fan_front; + char *fan_rear; + unsigned int fan_state; +} fans_tbl[] = { + {"fan1", fan_dev_path_fan1_input, + fan_dev_path_fan2_input, 0}, + {"fan2", fan_dev_path_fan3_input, + fan_dev_path_fan4_input, 0}, + {"fan3", fan_dev_path_fan5_input, + fan_dev_path_fan6_input, 0}, + {"fan4", fan_dev_path_fan7_input, + fan_dev_path_fan8_input, 0}, +}; +#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) ) + +#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0) + { + printk(KERN_ERR "[p_thread] All fans failed.\n"); + printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown); + } + cd_shutdown -= 1; + } + return ret; +} + +/* End of faninfo_device */ + +static int __init +fan_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_fan_path_init(); +#endif + return 0; +} + + +static void __exit +fan_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove fan module.\n"); +} + +/* psu device *************************************/ +static unsigned int psu_voltin = 0; +#define PSU_VOLTIN_ACDC (70000) + +/* + * normal/unpower/uninstall/fault are PSU states output from driver level + * checkpsu/error are defined by sysfs + */ +#define PSU_STATE_VAL_NORMAL (0) +#define PSU_STATE_VAL_UNPOWER (2) +#define PSU_STATE_VAL_FAULT (4) +#define PSU_STATE_VAL_UNINSTALL (7) +#define PSU_STATE_VAL_CHECKPSU (8) +#define PSU_STATE_VAL_ERROR (9) + +#define PSU_STATE_NORMAL ("0 : normal") +#define PSU_STATE_UNPOWER ("2 : unnormal") +#define PSU_STATE_FAULT ("4 : fault") +#define PSU_STATE_UNINSTALL ("7 : not installed") +#define PSU_STATE_CHECKPSU ("8 : check psu") +#define PSU_STATE_ERROR ("9 : state error") + +#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL)) +#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER)) +#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT)) +#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL)) +#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU)) + +typedef struct { + char *inv_dev_attrp; + char *inv_dev_pathp; +} psu_dev_t; + +typedef struct { + const char *psu_name; + int psu_major; + dev_t psu_devt; + struct device *psu_dev_p; + psu_dev_t *psu_dev_namep; + int psu_dev_total; + char *psu_inv_pathp; + void *psu_tracking; + char *psu_currentin; + char *psu_currentout; + char *psu_powerin; + char *psu_powerout; + char *psu_voltin; + char *psu_voltout; +} psu_dev_group_t; + +#define PSU_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s" + +static char psu_dev_path_state[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltin[MAX_PATH_SIZE]; + +static char psu_0_dev_path_state[MAX_PATH_SIZE]; +static char psu_1_dev_path_state[MAX_PATH_SIZE]; + +#if 0 +static char psu_dev_path_vendor[MAX_PATH_SIZE]; +static char psu_dev_path_version[MAX_PATH_SIZE]; +static char psu_dev_path_sn[MAX_PATH_SIZE]; +static char psu_dev_path_temperature[MAX_PATH_SIZE]; +static char psu_dev_path_fan_speed[MAX_PATH_SIZE]; +static char psu_dev_path_fan_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_fan_faulty[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_psu_rpm[MAX_PATH_SIZE]; +#endif + +void sysfs_psu_path_init(void) +{ + sprintf(&psu_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" ); + sprintf(&psu_dev_path_psu_voltin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + + sprintf(&psu_0_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "psu0" ); + sprintf(&psu_1_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "psu1" ); + +#if 0 + sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#endif +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +#if 0 + { "vendor", psu_dev_path_vendor }, + { "version", psu_dev_path_version }, + { "sn", psu_dev_path_sn }, + { "temperature", psu_dev_path_temperature }, + { "fan_speed", psu_dev_path_fan_speed }, + { "fan_pwm", psu_dev_path_fan_pwm }, + { "fan_faulty", psu_dev_path_fan_faulty }, + { "psu_currentin", psu_dev_path_psu_currentin }, + { "psu_currentout", psu_dev_path_psu_currentout }, + { "psu_powerin", psu_dev_path_psu_powerin }, + { "psu_powerout", psu_dev_path_psu_powerout }, + { "psu_voltout", psu_dev_path_psu_voltout }, + { "psu_pwm", psu_dev_path_psu_pwm }, + { "psu_rpm", psu_dev_path_psu_rpm }, +#endif +}; +#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) ) + +static psu_dev_group_t psu_dev_group[] = { + { + .psu_name = "psu1", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, + { + .psu_name = "psu2", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, +}; +#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) ) + +static char psu_state[4][MIN_ACC_SIZE]; + +static struct psu_wire_tbl_s { + char *psu_attr; + char *psu_name; + char *psu_wire; + char *psu_state; +} psu_wire_tbl[] = { + { "state", "psu1", "psu0", psu_state[0] }, // Using cpld + { "state", "psu2", "psu1", psu_state[1] }, + { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] }, + { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] }, +}; +#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) ) + +static char * +psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp) +{ + int i; + + for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) { + if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 && + strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) { + if (psu_statepp) { + *psu_statepp = psu_wire_tbl[i].psu_state; + } + return psu_wire_tbl[i].psu_wire; + } + } + return NULL; +} + +int psu_check_state_normal(char *statep) +{ + if (strstr(statep, "normal")) { + return 1; + } + return 0; +} + +#define PSU_ATTR_VOLTIN ("psu_voltin") +#define PSU_ATTR_VOLTIN_LEN (10) + +/* Get PSU voltin for determon AC(110v) or DC(48v) */ +void psu_get_voltin(void) +{ + char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE]; + psu_dev_t *devnamep; + unsigned int voltin; + char *invwirep; + int i, j; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + //psu_dev_group[i].psu_name; + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(volt, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + continue; + } + else { + voltin = simple_strtol(&volt[0], NULL, 10); + printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin); + if (voltin > psu_voltin) { + psu_voltin = voltin; + } + } + } + } + } + + SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin); +} + +#define PSU_ATTR_STATE ("state") +#define PSU_ATTR_STATE_LEN (5) + +/* psus_control() by inv_thread */ +int psus_control(int log_only) +{ + char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE]; + psu_dev_t *devnamep = NULL; + char *invwirep = NULL; + char *psu_statep = NULL; + int i, j, flag = 0; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(state, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) { + strcpy(psu_statep, PSU_STATE_ERROR); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR); + } + flag = 1; + } + else + if (strstr(state, "normal")) { + //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + } + else + if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */ + //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + flag = 1; + } + else { /* DC PSUS */ + if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) { + strcpy(psu_statep, PSU_STATE_CHECKPSU); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU); + } + flag = 1; + } + } + } + } + + if (log_only) { + return 0; + } + + //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag); + if (flag == 1) { + status_psu_led("0x20"); + return 1; + } + return 0; +} + +int status_led_psu_control(void) +{ + int retVal = 0; //no issue + + char buf[MAX_ACC_SIZE]; + + int normal_psu_cnt = 0; //normal + + int fault_psu_cnt = 0; + + //read fan status one by one + //read psu 0 status + if (inventec_show_attr(&buf[0], psu_0_dev_path_state) > 0) + { + if(buf[0] == '0') //normal + { + normal_psu_cnt = normal_psu_cnt + 1; + } + else if (buf[0] == '4') // psu fault + { + fault_psu_cnt = fault_psu_cnt + 1; + } + + //Check 2nd psu + if(inventec_show_attr(&buf[0], psu_1_dev_path_state) > 0) + { + if(buf[0] == '0') //normal + { + normal_psu_cnt = normal_psu_cnt + 1; + } + else if (buf[0] == '4') // psu fault + { + fault_psu_cnt = fault_psu_cnt + 1; + } + } + } + + if (normal_psu_cnt == 0) + { + status_psu_led("0"); + retVal = 1; + } + else + { + if( fault_psu_cnt > 0) + { + status_psu_led("0x01"); //Red lit + retVal = 1; + } + else if (normal_psu_cnt == 1) + { + status_psu_led("0x20"); // Green blink + retVal = 1; + } + else if (normal_psu_cnt == 2) + { + status_psu_led("0x10"); // Green Lit + retVal = 0; + } + } + + return retVal; +} + + +/* End of psuinfo_device */ + +static int __init +psu_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_psu_path_init(); +#endif + return 0; +} + + +static void __exit +psu_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove psu module.\n"); +} + +/* led device *************************************/ +#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led" +#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led" + +#define STATUS_LED_FAN_PATH "/sys/class/hwmon/hwmon%d/device/fan_led" +#define STATUS_LED_PSU_PATH "/sys/class/hwmon/hwmon%d/device/psu_led" + +#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1" +#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2" +#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3" +#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4" +#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1" +#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2" +#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3" +#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4" + +#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag" +#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl" + +static char status_led_grn_path[MAX_PATH_SIZE]; +static char status_led_red_path[MAX_PATH_SIZE]; +static char status_led_fan_path[MAX_PATH_SIZE]; +static char status_led_psu_path[MAX_PATH_SIZE]; + +static char fan_led_grn1_path[MAX_PATH_SIZE]; +static char fan_led_grn2_path[MAX_PATH_SIZE]; +static char fan_led_grn3_path[MAX_PATH_SIZE]; +static char fan_led_grn4_path[MAX_PATH_SIZE]; +static char fan_led_red1_path[MAX_PATH_SIZE]; +static char fan_led_red2_path[MAX_PATH_SIZE]; +static char fan_led_red3_path[MAX_PATH_SIZE]; +static char fan_led_red4_path[MAX_PATH_SIZE]; +static char hwmon_device_diag_path[MAX_PATH_SIZE]; +static char hwmon_device_ctrl_path[MAX_PATH_SIZE]; + +void sysfs_led_path_init(void) +{ + sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld()); + sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld()); + sprintf(&status_led_fan_path[0], STATUS_LED_FAN_PATH, get_hwm_cpld()); + sprintf(&status_led_psu_path[0], STATUS_LED_PSU_PATH, get_hwm_cpld()); + + sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc()); + sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc()); + sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc()); + sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc()); + sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld()); +} + +/* return 0/off 1/green 2/red */ +int +status_led_check_color(void) +{ + char tmpbuf[MIN_ACC_SIZE]; + int ret = STATUS_LED_INVALID; + + if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_GRN0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_GRN1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_GRN2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_GRN3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_GRN7; + } + return ret; + } + + if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_RED0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_RED1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_RED2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_RED3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_RED7; + } + return ret; + } + return ret; +} + +/* + * Store attr Section + */ +static DEFINE_MUTEX(diag_mutex); + +ssize_t status_led_diag_mode_enable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '0') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("1", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + mutex_unlock(&diag_mutex); + } + + return ret; +} + +ssize_t status_led_diag_mode_disable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '1') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("0", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + mutex_unlock(&diag_mutex); + } + return 1; +} + +ssize_t +status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2) +{ + ssize_t ret; + + ret = inventec_store_attr(tmp1, strlen(tmp1), path1); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(tmp2, strlen(tmp2), path2); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_red(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_grn_path[0]); + + if (ret < 0) { + return ret; + } + + ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]); + + if (ret < 0) { + return ret; + } + + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_grn(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +static int status_led_diag_mode = STATUS_LED_MODE_AUTO; + +int status_led_check_diag_mode(void) +{ + return status_led_diag_mode; +} + +//status led: FAN & PSU +ssize_t +status_fan_led(const char *freq) +{ + ssize_t ret; + ret = inventec_store_attr(freq, strlen(freq), &status_led_fan_path[0]); + if (ret < 0) { + return ret; + } + + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_psu_led(const char *freq) +{ + ssize_t ret; + ret = inventec_store_attr(freq, strlen(freq), &status_led_psu_path[0]); + if (ret < 0) { + return ret; + } + + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +/* End of ledinfo_device */ + +static int __init +led_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); +#endif + return 0; +} + + +static void __exit +led_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove led module.\n"); +} + +/* sensor device **********************************/ +#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp" + +static char sensor_dev_path_switch_temp[MAX_PATH_SIZE]; + +void sysfs_sensor_path_init(void) +{ + sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc()); +} + +void switch_temp_update(void) +{ + char buf[MIN_ACC_SIZE]; + ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp"); + if (count > 0) { + //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp); + inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp); + } +} + +/**************************************************/ +/* From system_device */ +static int inv_pthread_control = 1; + +int thread_control(void) +{ + return inv_pthread_control; +} + +void thread_control_set(int val) +{ + inv_pthread_control = val; +} +/* End system_device */ + +#define THREAD_SLEEP_MINS (3) +#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1) + +extern void psu_get_voltin(void); + +static struct task_struct *thread_st; +static int thread_data; + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO +void led_set_gpio_to_change_status_led(void) +{ + ssize_t ret = inventec_store_attr("253", 2, "/sys/class/gpio/export"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 253 to /sys/class/gpio/export failed\n"); + return; + } + + printk("[p_thread] Write 253 to /sys/class/gpio/export\n"); + + ret = inventec_store_attr("out", 3, "/sys/class/gpio/gpio253/direction"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio253/direction failed\n"); + return; + } + + //pull high and then low + ret = inventec_store_attr("1", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 1 to sys/class/gpio/gpio253/value failed\n"); + } + + //pull low + ret = inventec_store_attr("0", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 0 to sys/class/gpio/gpio253/value failed\n"); + } + + SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n"); +} +#endif + +// Function executed by kernel thread +static int thread_fn(void *unused) +{ + bool fan_issue = false; + bool psu_issue = false; + bool psu_number_issue = false; + + /* Delay for guarantee HW ready */ + ssleep(THREAD_DELAY_MINS); + +#ifndef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sysfs_fan_path_init(); + sysfs_psu_path_init(); +#endif + //sysfs_sensor_path_init(); + + /* Default status init */ + status_led_grn("7"); + + psu_get_voltin(); + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO + led_set_gpio_to_change_status_led(); +#endif + + while (1) + { + ssleep(THREAD_SLEEP_MINS); + + if (thread_control() == 0) { + printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__); + break; + } + + if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) { + /* status led in change color/freq mode, higher priority. Ignore fans sttaus */ + continue; + } + + //switch_temp_update(); + + if (fans_control() > 0) //has at least one failed fan + { + psus_control(0); //now we have separate led for FAN and PSU + fan_issue = true; + } + + if (psus_control(1) > 0) + { + psu_issue = true; + } + + if (status_led_psu_control() > 0) + { + psu_number_issue = true; + } + + if(fan_issue || psu_issue || psu_number_issue) + { + continue; + } + + if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */ + status_led_grn("7"); + } + } + +#ifndef INV_PTHREAD_KERNEL_MODULE +err_inv_pthread_fn_1: +#endif + do_exit(0); + printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__); + return 0; +} + + +static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int fan_absence; + size_t count; + + fan_absence = fans_control(); + count += sprintf(&buf[count], "%d\n", fan_absence); + return count; +} + +static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static struct attribute status_att = { + .name = "fan_absence", + .mode = 0777, +}; + +static const struct sysfs_ops status_ops = { + .show = s_show, + .store = s_store, +}; + +static struct kobj_type status_ktype = { + .sysfs_ops = &status_ops, +}; + + +static int __init inv_pthread_init(void) +{ + int retval; + + status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL); + if(!status_kobj) + return PTR_ERR(status_kobj); + + status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj); + if(!status_kset) + return -1; + + status_kobj->kset = status_kset; + + retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan"); + if(retval) + return retval; + + retval = sysfs_create_file(status_kobj, &status_att); + + + inventec_class_init(); + fan_device_init(); + psu_device_init(); + led_device_init(); + + thread_control_set(1); + + printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__); + //Create the kernel thread with name 'inv_pthread' + thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread"); + if (thread_st) + printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n"); + else + printk(KERN_ERR "[p_thread] inv_pthread creation failed\n"); + + return retval; +} + +static void __exit inv_pthread_exit(void) +{ + thread_control_set(0); + /* Delay for guarantee thread exit */ + ssleep(THREAD_DELAY_MINS); + + fan_device_exit(); + psu_device_exit(); + led_device_exit(); + inventec_class_exit(); + + sysfs_remove_file(status_kobj, &status_att); + kset_unregister(status_kset); + kobject_del(status_kobj); + + printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n"); +} + +module_init(inv_pthread_init); +module_exit(inv_pthread_exit); + +MODULE_AUTHOR("Robert "); +MODULE_DESCRIPTION("Inventec Platform Management Thread"); +MODULE_VERSION("version 1.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.c new file mode 100644 index 000000000000..cbb22fba2979 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.c @@ -0,0 +1,3049 @@ +/* + * 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 "inv_swps.h" + +static int ctl_major; +static int port_major; +static int ioexp_total; +static int port_total; +static int auto_config; +static int flag_i2c_reset; +static int flag_mod_state; +static unsigned gpio_rest_mux; +static struct class *swp_class_p = NULL; +static struct inv_platform_s *platform_p = NULL; +static struct inv_ioexp_layout_s *ioexp_layout = NULL; +static struct inv_port_layout_s *port_layout = NULL; + +static void swp_polling_worker(struct work_struct *work); +static DECLARE_DELAYED_WORK(swp_polling, swp_polling_worker); + +static int reset_i2c_topology(void); + + +static int +__swp_match(struct device *dev, +#ifdef SWPS_KERN_VER_AF_3_10 + + const void *data){ +#else + void *data){ +#endif + + char *name = (char *)data; + if (strcmp(dev_name(dev), name) == 0) + return 1; + return 0; +} + + +struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(swp_class_p, + NULL, + name, + __swp_match); + return dev; +} + + +static int +sscanf_2_int(const char *buf) { + + int result = -EBFONT; + char *hex_tag = "0x"; + + if (strcspn(buf, hex_tag) == 0) { + if (sscanf(buf,"%x",&result)) { + return result; + } + } else { + if (sscanf(buf,"%d",&result)) { + return result; + } + if(sscanf(buf,"-%d",&result)) { + return -result; + } + if (sscanf(buf,"%x",&result)) { + return result; + } + } + return -EBFONT; +} + + +static int +sscanf_2_binary(const char *buf) { + + int result = sscanf_2_int(buf); + + if (result < 0){ + return -EBFONT; + } + switch (result) { + case 0: + case 1: + return result; + default: + break; + } + return -EBFONT; +} + + +static int +_get_polling_period(void) { + + int retval = 0; + + if (SWP_POLLING_PERIOD == 0) { + return 0; + } + retval = ((SWP_POLLING_PERIOD * HZ) / 1000); + if (retval == 0) { + return 1; + } + return retval; +} + + +static struct transvr_obj_s * +_get_transvr_obj(char *dev_name) { + + struct device *dev_p = NULL; + struct transvr_obj_s *transvr_obj_p = NULL; + + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + return NULL; + } + transvr_obj_p = dev_get_drvdata(dev_p); + if (!transvr_obj_p){ + return NULL; + } + return transvr_obj_p; +} + + +static void +unlock_tobj_all(void) { + + struct transvr_obj_s *tobj_p; + char port_name[32]; + int port_id = 0; + int minor_curr = 0; + + for (minor_curr=0; minor_currauto_config = auto_config; + unlock_transvr_obj(tobj_p); + SWPS_DEBUG("%s: Set %s auto_config=%d\n", + __func__, tobj_p->swp_name, auto_config); + } + return retval; +} + + +/* ========== R/W Functions module control attribute ========== + */ +static ssize_t +show_attr_platform(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 32, "%s\n", platform_p->name); +} + + +static ssize_t +show_attr_version(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%s\n", SWP_VERSION); +} + + +static ssize_t +show_attr_status(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", flag_mod_state); +} + + +static ssize_t +show_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", auto_config); +} + + +static int +_check_reset_pwd(const char *buf_p, + size_t count) { + + int in_max = 64; + int in_len = (int)count; + char in_val[64] = "ERR"; + char *emsg = "ERR"; + + if (in_len >= in_max) { + emsg = "input too much"; + goto err_check_reset_pwd; + } + if (!sscanf(buf_p,"%s",in_val)) { + emsg = "format incorrect"; + goto err_check_reset_pwd; + } + if (strcmp(in_val, SWP_RESET_PWD) != 0) { + emsg = "password incorrect"; + goto err_check_reset_pwd; + } + return 0; + +err_check_reset_pwd: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + +static ssize_t +store_attr_reset_i2c(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + /* Polling mode */ + if (SWP_POLLING_ENABLE) { + SWPS_INFO("%s: reset I2C :polling\n", __func__); + flag_i2c_reset = 1; + return count; + } + /* Direct mode */ + SWPS_INFO("%s: reset I2C go. :direct\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset fail!\n", __func__); + return -EIO; + } + SWPS_INFO("%s: reset I2C ok. :direct\n", __func__); + return count; +} + + +static ssize_t +store_attr_reset_swps(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p; + char port_name[32] = "ERR"; + int port_id = 0; + int minor_curr = 0; + + if (_check_reset_pwd(buf_p, count) < 0) { + return -EBFONT; + } + for (minor_curr=0; minor_currstate = STATE_TRANSVR_DISCONNECTED; + unlock_transvr_obj(tobj_p); + SWPS_INFO("%s: reset:%s\n", __func__, tobj_p->swp_name); + } + return count; +} + + +static ssize_t +store_attr_auto_config(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if (input_val < 0){ + return -EBFONT; + } + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + auto_config = input_val; + _update_auto_config_2_trnasvr(); + return count; +} + + +/* ========== Show functions: For transceiver attribute ========== + */ +static ssize_t +_show_transvr_hex_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + int result; + + lock_transvr_obj(tobj_p); + result = get_func(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 8, "%d\n", result); + } else { + len = snprintf(buf_p, 8, "0x%02x\n", result); + } + return len; +} + + +static ssize_t +_show_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = snprintf(buf_p, 16, "%d\n", get_func(tobj_p)); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +_show_transvr_str_attr(struct transvr_obj_s* tobj_p, + int (*get_func)(struct transvr_obj_s* tobj_p, char* buf), + char *buf_p) { + size_t len; + + lock_transvr_obj(tobj_p); + len = get_func(tobj_p, buf_p); + unlock_transvr_obj(tobj_p); + return len; +} + + +static ssize_t +show_attr_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_id, + buf_p); +} + + +static ssize_t +show_attr_ext_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_ext_id, + buf_p); +} + + +static ssize_t +show_attr_connector(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_connector, + buf_p); +} + + +static ssize_t +show_attr_vendor_name(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_name, + buf_p); +} + + +static ssize_t +show_attr_vendor_pn(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_pn, + buf_p); +} + + +static ssize_t +show_attr_vendor_rev(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_rev, + buf_p); +} + + +static ssize_t +show_attr_vendor_sn(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_vendor_sn, + buf_p); +} + + +static ssize_t +show_attr_power_cls(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + size_t len; + int result; + struct transvr_obj_s *tobj_p; + + tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + lock_transvr_obj(tobj_p); + result = tobj_p->get_power_cls(tobj_p); + unlock_transvr_obj(tobj_p); + if (result < 0){ + len = snprintf(buf_p, 16, "%d\n", result); + } else { + len = snprintf(buf_p, 16, "Power Class %d\n", result); + } + return len; +} + + +static ssize_t +show_attr_br(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_br, + buf_p); +} + + +static ssize_t +show_attr_len_sm(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_sm, + buf_p); +} + + +static ssize_t +show_attr_len_smf(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_smf, + buf_p); +} + + +static ssize_t +show_attr_len_om1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om1, + buf_p); +} + + +static ssize_t +show_attr_len_om2(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om2, + buf_p); +} + + +static ssize_t +show_attr_len_om3(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om3, + buf_p); +} + + +static ssize_t +show_attr_len_om4(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_len_om4, + buf_p); +} + + +static ssize_t +show_attr_comp_rev(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_rev, + buf_p); +} + + +static ssize_t +show_attr_comp_eth(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_1, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10, + buf_p); +} + + +static ssize_t +show_attr_comp_eth_10_40(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_eth_10_40, + buf_p); +} + + +static ssize_t +show_attr_comp_extend(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_comp_extend, + buf_p); +} + + +static ssize_t +show_attr_rate_id(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_rate_id, + buf_p); +} + + +static ssize_t +show_attr_temperature(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_curr_temp, + buf_p); +} + + +static ssize_t +show_attr_voltage(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_curr_vol, + buf_p); +} + + +static ssize_t +show_attr_tx_bias(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_bias, + buf_p); +} + + +static ssize_t +show_attr_tx_power(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_power, + buf_p); +} + + +static ssize_t +show_attr_tx_eq(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_tx_eq, + buf_p); +} + + +static ssize_t +show_attr_rx_power(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_power, + buf_p); +} + + +static ssize_t +show_attr_rx_am(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_am, + buf_p); +} + + +static ssize_t +show_attr_rx_em(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_rx_em, + buf_p); +} + + +static ssize_t +show_attr_wavelength(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_wavelength, + buf_p); +} + + +static ssize_t +show_attr_extphy_offset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_extphy_offset, + buf_p); +} + + +static ssize_t +show_attr_extphy_reg(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_extphy_reg, + buf_p); +} + + +static ssize_t +show_attr_info(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_info, + buf_p); +} + + +static ssize_t +show_attr_if_type(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_type, + buf_p); +} + + +static ssize_t +show_attr_if_speed(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_speed, + buf_p); +} + + +static ssize_t +show_attr_if_lane(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_if_lane, + buf_p); +} + + +static ssize_t +show_attr_cdr(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_hex_attr(tobj_p, + tobj_p->get_cdr, + buf_p); +} + + +static ssize_t +show_attr_soft_rs0(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs0, + buf_p); +} + + +static ssize_t +show_attr_soft_rs1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_int_attr(tobj_p, + tobj_p->get_soft_rs1, + buf_p); +} + + +static ssize_t +show_attr_soft_rx_los(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_rx_los, + buf_p); +} + + +static ssize_t +show_attr_soft_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_disable, + buf_p); +} + + +static ssize_t +show_attr_soft_tx_fault(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_soft_tx_fault, + buf_p); +} + + +static ssize_t +show_attr_auto_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if(!tobj_p){ + return -ENODEV; + } + return _show_transvr_str_attr(tobj_p, + tobj_p->get_auto_tx_disable, + buf_p); +} + + +/* ========== Store functions: transceiver (R/W) attribute ========== + */ +static ssize_t +_store_transvr_int_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_byte_hex_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_int(buf_p); + if ((input < 0) || (input > 0xff)){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +_store_transvr_binary_attr(struct transvr_obj_s* tobj_p, + int (*set_func)(struct transvr_obj_s *tobj_p, int input_val), + const char *buf_p, + size_t count) { + int input, err; + + input = sscanf_2_binary(buf_p); + if (input < 0){ + return -EBFONT; + } + lock_transvr_obj(tobj_p); + err = set_func(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_cdr(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_byte_hex_attr(tobj_p, + tobj_p->set_cdr, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs0(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_rs1(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_binary_attr(tobj_p, + tobj_p->set_soft_rs1, + buf_p, + count); +} + + +static ssize_t +store_attr_soft_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int check = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((check < 0) || (check > 0xf)){ + return -EBFONT; + } + return _store_transvr_byte_hex_attr(tobj_p, + tobj_p->set_soft_tx_disable, + buf_p, + count); +} + + +static ssize_t +store_attr_auto_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count) { + + int err = -EPERM; + int input = sscanf_2_int(buf_p); + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + if ((input < 0) || (input > 0xf)){ + if (input != VAL_TRANSVR_FUNCTION_DISABLE) { + return -EBFONT; + } + } + lock_transvr_obj(tobj_p); + err = tobj_p->set_auto_tx_disable(tobj_p, input); + unlock_transvr_obj(tobj_p); + if (err < 0){ + return err; + } + return count; +} + + +static ssize_t +store_attr_tx_eq(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_tx_eq, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_am(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_rx_am, + buf_p, + count); +} + + +static ssize_t +store_attr_rx_em(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_rx_em, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_offset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_extphy_offset, + buf_p, + count); +} + + +static ssize_t +store_attr_extphy_reg(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _store_transvr_int_attr(tobj_p, + tobj_p->set_extphy_reg, + buf_p, + count); +} + +/* ========== Show functions: For I/O Expander attribute ========== + */ +static ssize_t +_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset), + char *buf_p) { + size_t len; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR(" %s: data corruption! :%s\n", __func__, tobj_p->swp_name); + return -ENODATA; + } + mutex_lock(&ioexp_p->lock); + len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset)); + mutex_unlock(&ioexp_p->lock); + return len; +} + + +static ssize_t +show_attr_present(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_present, + buf_p); +} + + +static ssize_t +show_attr_tx_fault(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_fault, + buf_p); +} + + +static ssize_t +show_attr_rxlos(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_rxlos, + buf_p); +} + + +static ssize_t +show_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_disable, + buf_p); +} + + +static ssize_t +show_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_reset, + buf_p); +} + + +static ssize_t +show_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_lpmod, + buf_p); +} + + +static ssize_t +show_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_modsel, + buf_p); +} + + +static ssize_t +show_attr_hard_rs0(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_hard_rs0, + buf_p); +} + + +static ssize_t +show_attr_hard_rs1(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_hard_rs1, + buf_p); +} + + +/* ========== Store functions: For I/O Expander (R/W) attribute ========== + */ +static ssize_t +_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*set_func)(struct ioexp_obj_s *ioexp_p, + int virt_offset, int input_val), + const char *buf_p, + size_t count) { + + int input, err; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR("%s: data corruption! :%s\n", + __func__, tobj_p->swp_name); + return -ENODATA; + } + input = sscanf_2_binary(buf_p); + if (input < 0) { + return -EBFONT; + } + mutex_lock(&ioexp_p->lock); + err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input); + mutex_unlock(&ioexp_p->lock); + if (err < 0){ + return err; + } + return count; +} + +static ssize_t +store_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_tx_disable, + buf_p, + count); +} + + +static ssize_t +store_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_reset, + buf_p, + count); +} + + +static ssize_t +store_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_lpmod, + buf_p, + count); +} + + +static ssize_t +store_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_modsel, + buf_p, + count); +} + + +static ssize_t +store_attr_hard_rs0(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_hard_rs0, + buf_p, + count); +} + + +static ssize_t +store_attr_hard_rs1(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_hard_rs1, + buf_p, + count); +} + + +/* ========== SWPS attribute: For module control ========== + */ +static DEVICE_ATTR(platform, S_IRUGO, show_attr_platform, NULL); +static DEVICE_ATTR(version, S_IRUGO, show_attr_version, NULL); +static DEVICE_ATTR(status, S_IRUGO, show_attr_status, NULL); +static DEVICE_ATTR(reset_i2c, S_IWUSR, NULL, store_attr_reset_i2c); +static DEVICE_ATTR(reset_swps, S_IWUSR, NULL, store_attr_reset_swps); +static DEVICE_ATTR(auto_config, S_IRUGO|S_IWUSR, show_attr_auto_config, store_attr_auto_config); + +/* ========== Transceiver attribute: from eeprom ========== + */ +static DEVICE_ATTR(id, S_IRUGO, show_attr_id, NULL); +static DEVICE_ATTR(ext_id, S_IRUGO, show_attr_ext_id, NULL); +static DEVICE_ATTR(connector, S_IRUGO, show_attr_connector, NULL); +static DEVICE_ATTR(vendor_name, S_IRUGO, show_attr_vendor_name, NULL); +static DEVICE_ATTR(vendor_pn, S_IRUGO, show_attr_vendor_pn, NULL); +static DEVICE_ATTR(vendor_rev, S_IRUGO, show_attr_vendor_rev, NULL); +static DEVICE_ATTR(vendor_sn, S_IRUGO, show_attr_vendor_sn, NULL); +static DEVICE_ATTR(power_cls, S_IRUGO, show_attr_power_cls, NULL); +static DEVICE_ATTR(br, S_IRUGO, show_attr_br, NULL); +static DEVICE_ATTR(len_sm, S_IRUGO, show_attr_len_sm, NULL); +static DEVICE_ATTR(len_smf, S_IRUGO, show_attr_len_smf, NULL); +static DEVICE_ATTR(len_om1, S_IRUGO, show_attr_len_om1, NULL); +static DEVICE_ATTR(len_om2, S_IRUGO, show_attr_len_om2, NULL); +static DEVICE_ATTR(len_om3, S_IRUGO, show_attr_len_om3, NULL); +static DEVICE_ATTR(len_om4, S_IRUGO, show_attr_len_om4, NULL); +static DEVICE_ATTR(comp_rev, S_IRUGO, show_attr_comp_rev, NULL); +static DEVICE_ATTR(comp_eth, S_IRUGO, show_attr_comp_eth, NULL); +static DEVICE_ATTR(comp_eth_10, S_IRUGO, show_attr_comp_eth_10, NULL); +static DEVICE_ATTR(comp_eth_10_40, S_IRUGO, show_attr_comp_eth_10_40, NULL); +static DEVICE_ATTR(comp_extend, S_IRUGO, show_attr_comp_extend, NULL); +static DEVICE_ATTR(rate_id, S_IRUGO, show_attr_rate_id, NULL); +static DEVICE_ATTR(temperature, S_IRUGO, show_attr_temperature, NULL); +static DEVICE_ATTR(voltage, S_IRUGO, show_attr_voltage, NULL); +static DEVICE_ATTR(tx_bias, S_IRUGO, show_attr_tx_bias, NULL); +static DEVICE_ATTR(tx_power, S_IRUGO, show_attr_tx_power, NULL); +static DEVICE_ATTR(rx_power, S_IRUGO, show_attr_rx_power, NULL); +static DEVICE_ATTR(info, S_IRUGO, show_attr_info, NULL); +static DEVICE_ATTR(if_type, S_IRUGO, show_attr_if_type, NULL); +static DEVICE_ATTR(if_speed, S_IRUGO, show_attr_if_speed, NULL); +static DEVICE_ATTR(if_lane, S_IRUGO, show_attr_if_lane, NULL); +static DEVICE_ATTR(soft_rx_los, S_IRUGO, show_attr_soft_rx_los, NULL); +static DEVICE_ATTR(soft_tx_fault, S_IRUGO, show_attr_soft_tx_fault, NULL); +static DEVICE_ATTR(wavelength, S_IRUGO, show_attr_wavelength, NULL); +static DEVICE_ATTR(tx_eq, S_IRUGO|S_IWUSR, show_attr_tx_eq, store_attr_tx_eq); +static DEVICE_ATTR(rx_am, S_IRUGO|S_IWUSR, show_attr_rx_am, store_attr_rx_am); +static DEVICE_ATTR(rx_em, S_IRUGO|S_IWUSR, show_attr_rx_em, store_attr_rx_em); +static DEVICE_ATTR(cdr, S_IRUGO|S_IWUSR, show_attr_cdr, store_attr_cdr); +static DEVICE_ATTR(soft_rs0, S_IRUGO|S_IWUSR, show_attr_soft_rs0, store_attr_soft_rs0); +static DEVICE_ATTR(soft_rs1, S_IRUGO|S_IWUSR, show_attr_soft_rs1, store_attr_soft_rs1); +static DEVICE_ATTR(soft_tx_disable, S_IRUGO|S_IWUSR, show_attr_soft_tx_disable, store_attr_soft_tx_disable); +static DEVICE_ATTR(auto_tx_disable, S_IRUGO|S_IWUSR, show_attr_auto_tx_disable, store_attr_auto_tx_disable); +static DEVICE_ATTR(extphy_offset, S_IRUGO|S_IWUSR, show_attr_extphy_offset, store_attr_extphy_offset); +static DEVICE_ATTR(extphy_reg, S_IRUGO|S_IWUSR, show_attr_extphy_reg, store_attr_extphy_reg); + +/* ========== IO Expander attribute: from expander ========== + */ +static DEVICE_ATTR(present, S_IRUGO, show_attr_present, NULL); +static DEVICE_ATTR(tx_fault, S_IRUGO, show_attr_tx_fault, NULL); +static DEVICE_ATTR(rxlos, S_IRUGO, show_attr_rxlos, NULL); +static DEVICE_ATTR(tx_disable, S_IRUGO|S_IWUSR, show_attr_tx_disable, store_attr_tx_disable); +static DEVICE_ATTR(reset, S_IRUGO|S_IWUSR, show_attr_reset, store_attr_reset); +static DEVICE_ATTR(lpmod, S_IRUGO|S_IWUSR, show_attr_lpmod, store_attr_lpmod); +static DEVICE_ATTR(modsel, S_IRUGO|S_IWUSR, show_attr_modsel, store_attr_modsel); +static DEVICE_ATTR(hard_rs0, S_IRUGO|S_IWUSR, show_attr_hard_rs0, store_attr_hard_rs0); +static DEVICE_ATTR(hard_rs1, S_IRUGO|S_IWUSR, show_attr_hard_rs1, store_attr_hard_rs1); + +/* ========== Functions for module handling ========== + */ +static void +clean_port_obj(void){ + + dev_t dev_num; + char dev_name[32]; + struct device *device_p; + struct transvr_obj_s *transvr_obj_p; + int minor_curr, port_id; + + for (minor_curr=0; minor_curri2c_client_p); + kfree(transvr_obj_p->vendor_name); + kfree(transvr_obj_p->vendor_pn); + kfree(transvr_obj_p->vendor_rev); + kfree(transvr_obj_p->vendor_sn); + kfree(transvr_obj_p->worker_p); + kfree(transvr_obj_p); + } + dev_num = MKDEV(port_major, minor_curr); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static void +clean_swps_common(void){ + + dev_t dev_num; + struct device *device_p; + + device_p = get_swpdev_by_name(SWP_DEV_MODCTL); + if (device_p){ + dev_num = MKDEV(ctl_major, 1); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + cancel_delayed_work_sync(&swp_polling); + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static int +get_platform_type(void){ + + int i; + int pf_total = ARRAY_SIZE(platform_map); + char log_msg[64] = "ERROR"; + + platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL); + if (!platform_p){ + snprintf(log_msg, sizeof(log_msg), "kzalloc fail"); + goto err_get_platform_type_1; + } + memset(platform_p->name, 0, sizeof(platform_p->name)); + + switch (PLATFORM_SETTINGS) { + case PLATFORM_TYPE_AUTO: + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", dmi_get_system_info(DMI_BOARD_NAME)); + for (i=0; iname, platform_map[i].name) == 0) { + platform_p->id = platform_map[i].id; + snprintf(log_msg, sizeof(log_msg), + "Auto detect platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Auto detect fail! detect platform: %s", + platform_p->name); + goto err_get_platform_type_2; + + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + case PLATFORM_TYPE_REDWOOD: + case PLATFORM_TYPE_REDWOOD_FSL: + case PLATFORM_TYPE_HUDSON32I_GA: + case PLATFORM_TYPE_SPRUCE: + case PLATFORM_TYPE_CYPRESS_GA1: + case PLATFORM_TYPE_CYPRESS_GA2: + case PLATFORM_TYPE_CYPRESS_BAI: + case PLATFORM_TYPE_TAHOE: + case PLATFORM_TYPE_SEQUOIA_GA: + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + case PLATFORM_TYPE_COTTONWOOD_RANGELEY: + case PLATFORM_TYPE_MAPLE: + platform_p->id = PLATFORM_SETTINGS; + for (i=0; iname, (sizeof(platform_p->name) - 1), + "%s", platform_map[i].name); + snprintf(log_msg, sizeof(log_msg), + "User setup platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Internal error, can not map id:%d", + PLATFORM_SETTINGS); + goto err_get_platform_type_2; + + default: + break; + } + snprintf(log_msg, sizeof(log_msg), + "PLATFORM_SETTINGS:%d undefined", PLATFORM_SETTINGS); + goto err_get_platform_type_2; + +ok_get_platform_type_1: + SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return 0; + +err_get_platform_type_2: + kfree(platform_p); +err_get_platform_type_1: + SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return -1; +} + + +static int +get_layout_info(void){ + + switch (platform_p->id) { +#ifdef SWPS_MAGNOLIA + case PLATFORM_TYPE_MAGNOLIA: + case PLATFORM_TYPE_MAGNOLIA_FNC: + gpio_rest_mux = magnolia_gpio_rest_mux; + ioexp_layout = magnolia_ioexp_layout; + port_layout = magnolia_port_layout; + ioexp_total = ARRAY_SIZE(magnolia_ioexp_layout); + port_total = ARRAY_SIZE(magnolia_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD + case PLATFORM_TYPE_REDWOOD: + gpio_rest_mux = redwood_gpio_rest_mux; + ioexp_layout = redwood_ioexp_layout; + port_layout = redwood_port_layout; + ioexp_total = ARRAY_SIZE(redwood_ioexp_layout); + port_total = ARRAY_SIZE(redwood_port_layout); + break; +#endif +#ifdef SWPS_HUDSON32I_GA + case PLATFORM_TYPE_HUDSON32I_GA: + gpio_rest_mux = hudsin32iga_gpio_rest_mux; + ioexp_layout = hudson32iga_ioexp_layout; + port_layout = hudson32iga_port_layout; + ioexp_total = ARRAY_SIZE(hudson32iga_ioexp_layout); + port_total = ARRAY_SIZE(hudson32iga_port_layout); + break; +#endif +#ifdef SWPS_SPRUCE + case PLATFORM_TYPE_SPRUCE: + gpio_rest_mux = spruce_gpio_rest_mux; + ioexp_layout = spruce_ioexp_layout; + port_layout = spruce_port_layout; + ioexp_total = ARRAY_SIZE(spruce_ioexp_layout); + port_total = ARRAY_SIZE(spruce_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA1 + case PLATFORM_TYPE_CYPRESS_GA1: + gpio_rest_mux = cypress_ga1_gpio_rest_mux; + ioexp_layout = cypress_ga1_ioexp_layout; + port_layout = cypress_ga1_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga1_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga1_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_GA2 + case PLATFORM_TYPE_CYPRESS_GA2: + gpio_rest_mux = cypress_ga2_gpio_rest_mux; + ioexp_layout = cypress_ga2_ioexp_layout; + port_layout = cypress_ga2_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga2_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga2_port_layout); + break; +#endif +#ifdef SWPS_CYPRESS_BAI + case PLATFORM_TYPE_CYPRESS_BAI: + gpio_rest_mux = cypress_b_gpio_rest_mux; + ioexp_layout = cypress_b_ioexp_layout; + port_layout = cypress_b_port_layout; + ioexp_total = ARRAY_SIZE(cypress_b_ioexp_layout); + port_total = ARRAY_SIZE(cypress_b_port_layout); + break; +#endif +#ifdef SWPS_REDWOOD_FSL + case PLATFORM_TYPE_REDWOOD_FSL: + gpio_rest_mux = redwood_fsl_gpio_rest_mux; + ioexp_layout = redwood_fsl_ioexp_layout; + port_layout = redwood_fsl_port_layout; + ioexp_total = ARRAY_SIZE(redwood_fsl_ioexp_layout); + port_total = ARRAY_SIZE(redwood_fsl_port_layout); + break; +#endif +#ifdef SWPS_TAHOE + case PLATFORM_TYPE_TAHOE: + gpio_rest_mux = tahoe_gpio_rest_mux; + ioexp_layout = tahoe_ioexp_layout; + port_layout = tahoe_port_layout; + ioexp_total = ARRAY_SIZE(tahoe_ioexp_layout); + port_total = ARRAY_SIZE(tahoe_port_layout); + break; +#endif +#ifdef SWPS_SEQUOIA + case PLATFORM_TYPE_SEQUOIA_GA: + gpio_rest_mux = sequoia_gpio_rest_mux; + ioexp_layout = sequoia_ioexp_layout; + port_layout = sequoia_port_layout; + ioexp_total = ARRAY_SIZE(sequoia_ioexp_layout); + port_total = ARRAY_SIZE(sequoia_port_layout); + break; +#endif +#ifdef SWPS_LAVENDER + case PLATFORM_TYPE_LAVENDER_GA: + case PLATFORM_TYPE_LAVENDER_ONL: + gpio_rest_mux = lavender_gpio_rest_mux; + ioexp_layout = lavender_ioexp_layout; + port_layout = lavender_port_layout; + ioexp_total = ARRAY_SIZE(lavender_ioexp_layout); + port_total = ARRAY_SIZE(lavender_port_layout); + break; +#endif +#ifdef SWPS_COTTONWOOD_RANGELEY + case PLATFORM_TYPE_COTTONWOOD_RANGELEY: + gpio_rest_mux = cottonwood_rangeley_gpio_rest_mux; + ioexp_layout = cottonwood_rangeley_ioexp_layout; + port_layout = cottonwood_rangeley_port_layout; + ioexp_total = ARRAY_SIZE(cottonwood_rangeley_ioexp_layout); + port_total = ARRAY_SIZE(cottonwood_rangeley_port_layout); + break; +#endif +#ifdef SWPS_MAPLE + case PLATFORM_TYPE_MAPLE: + gpio_rest_mux = maple_gpio_rest_mux; + ioexp_layout = maple_ioexp_layout; + port_layout = maple_port_layout; + ioexp_total = ARRAY_SIZE(maple_ioexp_layout); + port_total = ARRAY_SIZE(maple_port_layout); + break; +#endif + default: + SWPS_ERR(" Invalid platform: %d (%s)\n", + platform_p->id, platform_p->name); + return -1; + } + SWPS_INFO("Start to initial platform: %d (%s)\n", + platform_p->id, platform_p->name); + return 0; +} + + +/* ========== Functions for objects operations ========== + */ +static int +__detect_issues_port(int minor_num) { + + struct transvr_obj_s *tobj_p; + int port_id = port_layout[minor_num].port_id; + char port_name[32] = "ERR"; + char *i2c_emsg = "detected bad transceiver/cable"; + + memset(port_name, 0, sizeof(port_name)); + snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id); + tobj_p = _get_transvr_obj(port_name); + if (!tobj_p) { + SWPS_INFO("%s: tobj_p is NULL :%d\n", __func__, minor_num); + return -1; + } + if (resync_channel_tier_2(tobj_p) < 0) { + if (check_channel_tier_1() < 0) { + alarm_msg_2_user(tobj_p, i2c_emsg); + return -2;; + } + } + return 0; +} + + +static int +_detect_issues_port(void) { + /* OK : retrun -1; + * Fail: return fail at which minor number (0~N) + */ + char *emsg = "ERR"; + int minor = 0; + int minor_2st = 1; + + /* Force moving the initial channel pointer + * Filter out case of fail at minor-0 port + */ + while (minor_2st < port_total) { + minor = minor_2st; + if (__detect_issues_port(minor_2st) < 0) { + emsg = "detect minor_2st fail"; + goto err_p_detect_issues_port; + } + minor_2st += 8; + } + /* Scan all port */ + for (minor=0; minor:%d\n", __func__, emsg, minor_err); + return -1; +} + + +static int +check_transvr_obj_one(char *dev_name){ + /* [Return] + * 0 : Doesn't need to take care + * -1 : Single error + * -2 : Critical error (I2C topology die) + * -9 : Internal error + */ + struct transvr_obj_s *tobj_p = NULL; + int retval = -9; + + tobj_p = _get_transvr_obj(dev_name); + if (!tobj_p) { + SWPS_ERR("%s: %s _get_transvr_obj fail\n", + __func__, dev_name); + return -9; + } + /* Check transceiver current status */ + lock_transvr_obj(tobj_p); + retval = tobj_p->check(tobj_p); + unlock_transvr_obj(tobj_p); + switch (retval) { + case 0: + case ERR_TRANSVR_UNPLUGGED: + case ERR_TRNASVR_BE_ISOLATED: + case ERR_TRANSVR_TASK_BUSY: + return 0; + + case ERR_TRANSVR_I2C_CRASH: + default: + break; + } + /* Identify abnormal case */ + if (check_channel_tier_1() < 0) { + SWPS_DEBUG("%s: %s critical error :%d\n", + __func__, dev_name, retval); + return -2; + } + SWPS_DEBUG("%s: %s single error :%d\n", + __func__, dev_name, retval); + return -1; +} + + +static int +check_transvr_objs(void){ + + char dev_name[32]; + int port_id, err_code; + int minor_curr = 0; + + for (minor_curr=0; minor_curr:%d\n", + __func__, dev_name, err_code); + break; + } + } + return 0; + +err_check_transvr_objs: + SWPS_ERR("%s: %s reset_i2c_topology fail.\n", + __func__, dev_name); + return -1; +} + + +static void +swp_polling_worker(struct work_struct *work){ + + /* Reset I2C */ + if (flag_i2c_reset) { + goto polling_reset_i2c; + } + /* Check IOEXP */ + if (check_ioexp_objs() < 0) { + goto polling_reset_i2c; + } + /* Check transceiver */ + if (check_transvr_objs() < 0) { + SWPS_DEBUG("%s: check_transvr_objs fail.\n", __func__); + flag_i2c_reset = 1; + } + goto polling_schedule_round; + +polling_reset_i2c: + SWPS_DEBUG("%s: reset_i2c_topology start.\n", __func__); + if (reset_i2c_topology() < 0) { + SWPS_ERR("%s: reset i2c fail!\n", __func__); + flag_i2c_reset = 1; + } else { + SWPS_DEBUG("%s: reset_i2c_topology OK.\n", __func__); + flag_i2c_reset = 0; + } +polling_schedule_round: + schedule_delayed_work(&swp_polling, _get_polling_period()); +} + + +/* ========== Functions for register something ========== + */ +static int +register_transvr_common_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_id) < 0) { + err_attr = "dev_attr_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_ext_id) < 0) { + err_attr = "dev_attr_ext_id"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_connector) < 0) { + err_attr = "dev_attr_connector"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_name) < 0) { + err_attr = "dev_attr_vendor_name"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_pn) < 0) { + err_attr = "dev_attr_vendor_pn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_rev) < 0) { + err_attr = "dev_attr_vendor_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_vendor_sn) < 0) { + err_attr = "dev_attr_vendor_sn"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_br) < 0) { + err_attr = "dev_attr_br"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_smf) < 0) { + err_attr = "dev_attr_len_smf"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om1) < 0) { + err_attr = "dev_attr_len_om1"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om2) < 0) { + err_attr = "dev_attr_len_om2"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om3) < 0) { + err_attr = "dev_attr_len_om3"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_len_om4) < 0) { + err_attr = "dev_attr_len_om4"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_extend) < 0) { + err_attr = "dev_attr_comp_extend"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth) < 0) { + err_attr = "dev_attr_comp_eth"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_comp_rev) < 0) { + err_attr = "dev_attr_comp_rev"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_info) < 0) { + err_attr = "dev_attr_info"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_type) < 0) { + err_attr = "dev_attr_if_type"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_speed) < 0) { + err_attr = "dev_attr_if_speed"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_if_lane) < 0) { + err_attr = "dev_attr_if_lane"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_temperature) < 0) { + err_attr = "dev_attr_temperature"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_voltage) < 0) { + err_attr = "dev_attr_voltage"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_bias) < 0) { + err_attr = "dev_attr_tx_bias"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_power) < 0) { + err_attr = "dev_attr_tx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_power) < 0) { + err_attr = "dev_attr_rx_power"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_tx_eq) < 0) { + err_attr = "dev_attr_tx_eq"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_rx_em) < 0) { + err_attr = "dev_attr_rx_em"; + goto err_transvr_comm_attr; + } + if (device_create_file(device_p, &dev_attr_wavelength) < 0) { + err_attr = "dev_attr_wavelength"; + goto err_transvr_comm_attr; + } + return 0; + +err_transvr_comm_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + +static int +register_transvr_sfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10) < 0) { + err_attr = "dev_attr_comp_eth_10"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_len_sm) < 0) { + err_attr = "dev_attr_len_sm"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_rate_id) < 0) { + err_attr = "dev_attr_rate_id"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs0) < 0) { + err_attr = "dev_attr_soft_rs0"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rs1) < 0) { + err_attr = "dev_attr_soft_rs1"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_offset) < 0) { + err_attr = "dev_attr_extphy_offset"; + goto err_transvr_sfp_attr; + } + if (device_create_file(device_p, &dev_attr_extphy_reg) < 0) { + err_attr = "dev_attr_extphy_reg"; + goto err_transvr_sfp_attr; + } + return 0; + +err_transvr_sfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_common_attr(device_p) < 0) { + err_attr = "register_transvr_common_attr"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_comp_eth_10_40) < 0) { + err_attr = "dev_attr_comp_eth_10_40"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_power_cls) < 0) { + err_attr = "dev_attr_power_cls"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_rx_los) < 0) { + err_attr = "soft_rx_los"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_disable) < 0) { + err_attr = "soft_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_auto_tx_disable) < 0) { + err_attr = "auto_tx_disable"; + goto err_transvr_qsfp_attr; + } + if (device_create_file(device_p, &dev_attr_soft_tx_fault) < 0) { + err_attr = "soft_tx_fault"; + goto err_transvr_qsfp_attr; + } + return 0; + +err_transvr_qsfp_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_qsfp28_attr(struct device *device_p){ + + char *err_attr = NULL; + + if (register_transvr_qsfp_attr(device_p) < 0){ + err_attr = "register_transvr_qsfp_attr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_cdr) < 0) { + err_attr = "dev_attr_cdr"; + goto err_transvr_qsfp28_attr; + } + if (device_create_file(device_p, &dev_attr_rx_am) < 0) { + err_attr = "dev_attr_rx_am"; + goto err_transvr_qsfp28_attr; + } + return 0; + +err_transvr_qsfp28_attr: + SWPS_ERR("%s: %s\n", __func__, err_attr); + return -1; +} + + +static int +register_transvr_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + switch (transvr_obj->layout){ + case TRANSVR_TYPE_SFP: + if (register_transvr_sfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + if (register_transvr_qsfp_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + case TRANSVR_TYPE_QSFP_28: + if (register_transvr_qsfp28_attr(device_p) < 0){ + goto err_reg_tvr_attr; + } + break; + default: + goto err_reg_tvr_attr; + } + return 0; + +err_reg_tvr_attr: + SWPS_ERR("%s: fail! type=%d \n", __func__, transvr_obj->type); + return -1; +} + + +static int +register_ioexp_attr_sfp_1(struct device *device_p){ + /* Support machine type: + * - SFP : Magnolia + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_fault) < 0) { + err_attr = "dev_attr_tx_fault"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_rxlos) < 0) { + err_attr = "dev_attr_rxlos"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_disable) < 0) { + err_attr = "dev_attr_tx_disable"; + goto err_ioexp_sfp1_attr; + } + return 0; + +err_ioexp_sfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_ioexp_attr_sfp_2(struct device *device_p){ + /* Support machine type: + * - SFP28 : Cypress + */ + char *err_attr = NULL; + + if (register_ioexp_attr_sfp_1(device_p) < 0){ + goto err_ioexp_sfp2_attr; + } + if (device_create_file(device_p, &dev_attr_hard_rs0) < 0) { + err_attr = "dev_attr_hard_rs0"; + goto err_ioexp_sfp2_attr; + } + if (device_create_file(device_p, &dev_attr_hard_rs1) < 0) { + err_attr = "dev_attr_hard_rs1"; + goto err_ioexp_sfp2_attr; + } + return 0; + +err_ioexp_sfp2_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_ioexp_attr_qsfp_1(struct device *device_p){ + /* Support machine type: + * - QSFP : Magnolia, Redwood, Hudson32i + * - QSFP+ : Magnolia, Redwood, Hudson32i + * - QSFP28: Redwood + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_reset) < 0) { + err_attr = "dev_attr_reset"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_lpmod) < 0) { + err_attr = "dev_attr_lpmod"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_modsel) < 0) { + err_attr = "dev_attr_modsel"; + goto err_ioexp_qsfp1_attr; + } + return 0; + +err_ioexp_qsfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + + +static int +register_modctl_attr(struct device *device_p){ + + char *err_msg = NULL; + + if (device_create_file(device_p, &dev_attr_platform) < 0) { + err_msg = "dev_attr_platform"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_version) < 0) { + err_msg = "dev_attr_version"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_status) < 0) { + err_msg = "dev_attr_status"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_i2c) < 0) { + err_msg = "dev_attr_reset_i2c"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_reset_swps) < 0) { + err_msg = "dev_attr_reset_swps"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_auto_config) < 0) { + err_msg = "dev_attr_auto_config"; + goto err_reg_modctl_attr; + } + return 0; + +err_reg_modctl_attr: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int +register_ioexp_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + char *err_msg = "ERR"; + + switch (transvr_obj->ioexp_obj_p->ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case CPLD_TYPE_COTTONWOOD: + if (register_ioexp_attr_sfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_MAPLE_NABC: + if (register_ioexp_attr_sfp_2(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_2 fail"; + goto err_reg_ioexp_attr; + } + break; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case IOEXP_TYPE_MAPLE_0ABC: + if (register_ioexp_attr_qsfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_qsfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + + default: + err_msg = "Unknow type"; + goto err_reg_ioexp_attr; + } + return 0; + +err_reg_ioexp_attr: + SWPS_ERR("%s: %s :%d \n", + __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type); + return -1; +} + + +static int +register_modctl_device(void) { + + struct device *device_p = NULL; + int minor_comm = 0; /* Default minor number for common device */ + dev_t dev_num = MKDEV(ctl_major, minor_comm); + char *err_msg = "ERROR"; + + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + NULL, /* void *private_data */ + SWP_DEV_MODCTL); /* const char *fmt */ + if (IS_ERR(device_p)){ + err_msg = "device_create fail"; + goto err_register_modctl_device_1; + } + if (register_modctl_attr(device_p) < 0) { + err_msg = "register_modctl_attr fail"; + goto err_register_modctl_device_2; + } + return 0; + +err_register_modctl_device_2: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_register_modctl_device_1: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int +register_port_device(char *dev_name, + dev_t dev_num, + struct transvr_obj_s *transvr_obj){ + + struct device *device_p = NULL; + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + transvr_obj, /* void *private_data */ + dev_name); /* const char *fmt */ + if (IS_ERR(device_p)){ + goto err_regswp_create_dev; + } + if (register_transvr_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + if (register_ioexp_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + return 0; + +err_regswp_reg_attr: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_regswp_create_dev: + SWPS_ERR("%s fail! :%s\n", __func__, dev_name); + return -1; +} + + +static int +register_swp_module(void){ + + dev_t ctl_devt = 0; + dev_t port_devt = 0; + int dev_total = port_total + 1; /* char_dev for module control */ + + /* Register device number */ + if (alloc_chrdev_region(&ctl_devt, 0, 1, SWP_DEV_MODCTL) < 0){ + SWPS_WARN("Allocate CTL MAJOR failure! \n"); + goto err_register_swp_module_1; + } + if (alloc_chrdev_region(&port_devt, 0, dev_total, SWP_CLS_NAME) < 0){ + SWPS_WARN("Allocate PORT MAJOR failure! \n"); + goto err_register_swp_module_2; + } + ctl_major = MAJOR(ctl_devt); + port_major = MAJOR(port_devt); + + /* Create class object */ + swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME); + if (IS_ERR(swp_class_p)) { + SWPS_ERR("Create class failure! \n"); + goto err_register_swp_module_3; + } + return 0; + +err_register_swp_module_3: + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_register_swp_module_2: + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); +err_register_swp_module_1: + return -1; +} + + +/* ========== Module initial relate ========== + */ +static int +create_ioexp_objs(void) { + + int i, run_mod; + + /* Clean IOEXP object */ + clean_ioexp_objs(); + /* Get running mode */ + run_mod = IOEXP_MODE_DIRECT; + if (SWP_POLLING_ENABLE){ + run_mod = IOEXP_MODE_POLLING; + } + /* Create IOEXP object */ + for(i=0; i devlen_max) { + snprintf(err_msg, sizeof(err_msg), + "SWP_DEV_PORT too long!"); + goto err_initport_create_tranobj; + } + memset(dev_name, 0, sizeof(dev_name)); + snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id); + /* Create transceiver object */ + ioexp_obj_p = get_ioexp_obj(ioexp_id); + if (!ioexp_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "IOEXP object:%d not exist", ioexp_id); + goto err_initport_create_tranobj; + } + transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p, + ioexp_virt_offset, transvr_type, + chipset_type, run_mod); + if (!transvr_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "Create transceiver object fail :%s", dev_name); + goto err_initport_create_tranobj; + } + /* Setup Lane_ID mapping */ + i = ARRAY_SIZE(port_layout[minor_curr].lane_id); + j = ARRAY_SIZE(transvr_obj_p->lane_id); + if (i != j) { + snprintf(err_msg, sizeof(err_msg), + "Lane_id size inconsistent %d/%d", i, j); + goto err_initport_reg_device; + } + memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int)); + /* Create and register device object */ + if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){ + snprintf(err_msg, sizeof(err_msg), + "register_port_device fail"); + goto err_initport_reg_device; + } + /* Setup device_ptr of transvr_obj */ + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + snprintf(err_msg, sizeof(err_msg), + "get_swpdev_by_name fail"); + goto err_initport_reg_device; + } + transvr_obj_p->transvr_dev_p = dev_p; + /* Success */ + ok_count++; + } + SWPS_INFO("%s: initialed %d port-dev",__func__, ok_count); + return 0; + +err_initport_reg_device: + kfree(transvr_obj_p); +err_initport_create_tranobj: + clean_port_obj(); + SWPS_ERR("%s: %s", __func__, err_msg); + SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n", + port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod); + return -1; +} + + +static int +init_dev_topology(void){ + + int err; + char *emsg = "ERR"; + flag_mod_state = SWP_STATE_NORMAL; + + err = init_ioexp_objs(); + switch(err){ + case 0: /* Normal */ + SWPS_DEBUG("%s: normal case\n", __func__); + break; + + case -1: /* topology error */ + SWPS_DEBUG("%s: detect tier-1 topology initial failure :%d\n", + __func__, err); + /* Reset and isolate */ + err = reset_i2c_topology(); + if (err < 0) { + emsg = "reset i2c topology fail"; + goto err_init_dev_topology; + } + /* Re-initial again */ + err = init_ioexp_objs(); + if (err < 0) { + emsg = "re-init ioexp objects fail"; + goto err_init_dev_topology; + } + break; + + case -2: /* Internal error */ + SWPS_DEBUG("%s: internal error case\n", __func__); + err = -2; + emsg = "internal error"; + goto err_init_dev_topology; + + default: + SWPS_DEBUG("%s: undefined error case\n", __func__); + emsg = "undefined error case"; + goto err_init_dev_topology; + } + SWPS_DEBUG("%s: initial I2C topology success\n", __func__); + return 0; + +err_init_dev_topology: + SWPS_ERR("%s: %s :%d\n", __func__, emsg, err); + return -1; +} + + +static int +init_polling_task(void){ + + if (SWP_POLLING_ENABLE){ + schedule_delayed_work(&swp_polling, _get_polling_period()); + } + return 0; +} + + +static int +init_swps_common(void){ + + char *err_msg = "ERR"; + + auto_config = 0; + if ((SWP_AUTOCONFIG_ENABLE) && (SWP_POLLING_ENABLE)){ + auto_config = 1; + } + if (register_modctl_device() < 0) { + err_msg = "register_modctl_device fail"; + goto err_init_swps_common_1; + } + if (_update_auto_config_2_trnasvr() < 0) { + err_msg = "_update_auto_config_2_trnasvr fail"; + goto err_init_swps_common_1; + } + if (init_polling_task() < 0){ + err_msg = "init_polling_task fail"; + goto err_init_swps_common_1; + } + return 0; + +err_init_swps_common_1: + clean_swps_common(); + SWPS_ERR("%s: %s\n", __func__, err_msg); + return -1; +} + + +static int __init +swp_module_init(void){ + + if (get_platform_type() < 0){ + goto err_init_out; + } + if (get_layout_info() < 0){ + goto err_init_out; + } + if (register_swp_module() < 0){ + goto err_init_out; + } + if (create_ioexp_objs() < 0){ + goto err_init_ioexp; + } + if (create_port_objs() < 0){ + goto err_init_portobj; + } + if (init_mux_gpio(gpio_rest_mux) < 0){ + goto err_init_mux; + } + if (init_dev_topology() < 0){ + goto err_init_topology; + } + if (init_swps_common() < 0){ + goto err_init_topology; + } + SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION); + return 0; + + +err_init_topology: + clean_mux_gpio(); +err_init_mux: + clean_port_obj(); +err_init_portobj: + clean_ioexp_objs(); +err_init_ioexp: + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_init_out: + SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION); + return -1; +} + + +static void __exit +swp_module_exit(void){ + + clean_swps_common(); + clean_port_obj(); + clean_ioexp_objs(); + clean_mux_gpio(); + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(ctl_major, 0), 1); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); + SWPS_INFO("Remove Inventec switch-port module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(SWP_AUTHOR); +MODULE_DESCRIPTION(SWP_DESC); +MODULE_VERSION(SWP_VERSION); +MODULE_LICENSE(SWP_LICENSE); + +module_init(swp_module_init); +module_exit(swp_module_exit); + + + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.h new file mode 100644 index 000000000000..d28a0a3c968e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/inv_swps.h @@ -0,0 +1,1164 @@ +/* + * 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. + */ + +#ifndef INV_SWPS_H +#define INV_SWPS_H + +#include "transceiver.h" +#include "io_expander.h" +#include "inv_mux.h" + +/* Module settings */ +#define SWP_CLS_NAME "swps" +#define SWP_DEV_PORT "port" +#define SWP_DEV_MODCTL "module" +#define SWP_RESET_PWD "inventec" +#define SWP_POLLING_PERIOD (300) /* msec */ +#define SWP_POLLING_ENABLE (1) +#define SWP_AUTOCONFIG_ENABLE (1) + +/* Module information */ +#define SWP_AUTHOR "Neil " +#define SWP_DESC "Inventec port and transceiver driver" +#define SWP_VERSION "4.2.9" +#define SWP_LICENSE "GPL" + +/* Module status define */ +#define SWP_STATE_NORMAL (0) +#define SWP_STATE_I2C_DIE (-91) + +/* [Note]: + * Functions and mechanism for auto-detect platform type is ready, + * But HW and BIOS not ready! We need to wait them. + * So, please do not use PLATFORM_TYPE_AUTO until they are ready. + * (2016.06.13) + */ +#define PLATFORM_TYPE_AUTO (100) +#define PLATFORM_TYPE_MAGNOLIA (111) +#define PLATFORM_TYPE_MAGNOLIA_FNC (112) +#define PLATFORM_TYPE_REDWOOD (121) +#define PLATFORM_TYPE_REDWOOD_FSL (122) +#define PLATFORM_TYPE_HUDSON32I_GA (131) +#define PLATFORM_TYPE_SPRUCE (141) +#define PLATFORM_TYPE_CYPRESS_GA1 (151) /* Up -> Down */ +#define PLATFORM_TYPE_CYPRESS_GA2 (152) /* Down -> Up */ +#define PLATFORM_TYPE_CYPRESS_BAI (153) /* Down -> Up */ +#define PLATFORM_TYPE_TAHOE (161) +#define PLATFORM_TYPE_SEQUOIA_GA (171) +#define PLATFORM_TYPE_LAVENDER_GA (181) +#define PLATFORM_TYPE_LAVENDER_ONL (182) +#define PLATFORM_TYPE_COTTONWOOD_RANGELEY (191) +#define PLATFORM_TYPE_MAPLE (201) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_MAPLE + +/* Define platform flag and kernel version */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA_FNC) + #define SWPS_MAGNOLIA (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD) + #define SWPS_REDWOOD (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD_FSL) + #define SWPS_REDWOOD_FSL (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_HUDSON32I_GA) + #define SWPS_HUDSON32I_GA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SPRUCE) + #define SWPS_SPRUCE (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA1) + #define SWPS_CYPRESS_GA1 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA2) + #define SWPS_CYPRESS_GA2 (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_BAI) + #define SWPS_CYPRESS_BAI (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_TAHOE) + #define SWPS_TAHOE (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA) + #define SWPS_SEQUOIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) + #define SWPS_LAVENDER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_COTTONWOOD_RANGELEY) + #define SWPS_COTTONWOOD_RANGELEY (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE) + #define SWPS_MAPLE (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#endif + + +struct inv_platform_s { + int id; + char name[64]; +}; + +struct inv_ioexp_layout_s { + int ioexp_id; + int ioexp_type; + struct ioexp_addr_s addr[4]; +}; + +struct inv_port_layout_s { + int port_id; + int chan_id; + int ioexp_id; + int ioexp_offset; + int transvr_type; + int chipset_type; + int lane_id[8]; +}; + + +/* ========================================== + * Inventec Platform Settings + * ========================================== + */ +struct inv_platform_s platform_map[] = { + {PLATFORM_TYPE_AUTO, "Auto-Detect" }, + {PLATFORM_TYPE_MAGNOLIA, "Magnolia" }, + {PLATFORM_TYPE_MAGNOLIA_FNC, "Magnolia_FNC" }, + {PLATFORM_TYPE_REDWOOD, "Redwood" }, + {PLATFORM_TYPE_REDWOOD_FSL, "Redwood_FSL" }, + {PLATFORM_TYPE_HUDSON32I_GA, "Hudson32i" }, + {PLATFORM_TYPE_SPRUCE, "Spruce" }, + {PLATFORM_TYPE_CYPRESS_GA1, "Cypress_GA1" }, + {PLATFORM_TYPE_CYPRESS_GA2, "Cypress_GA2" }, + {PLATFORM_TYPE_CYPRESS_BAI, "Cypress_BAI" }, + {PLATFORM_TYPE_TAHOE, "Tahoe" }, + {PLATFORM_TYPE_SEQUOIA_GA, "Sequoia_GA" }, + {PLATFORM_TYPE_LAVENDER_GA, "Lavender_GA" }, + {PLATFORM_TYPE_LAVENDER_ONL, "Lavender_ONL" }, + {PLATFORM_TYPE_COTTONWOOD_RANGELEY, "Cottonwood_RANGELEY" }, + {PLATFORM_TYPE_MAPLE, "Maple" }, +}; + + +/* ========================================== + * Magnolia Layout configuration + * ========================================== + */ +#ifdef SWPS_MAGNOLIA +unsigned magnolia_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s magnolia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAGINOLIA_NAB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {1, IOEXP_TYPE_MAGINOLIA_NAB, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {2, IOEXP_TYPE_MAGINOLIA_NAB, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {3, IOEXP_TYPE_MAGINOLIA_4AB, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf0, 0xff}, {0xf0, 0xff}, }, }, /* addr[1] = I/O Expander 4 B */ + }, + {4, IOEXP_TYPE_MAGINOLIA_NAB, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {5, IOEXP_TYPE_MAGINOLIA_NAB, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */ + }, + {6, IOEXP_TYPE_MAGINOLIA_7AB, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[1] = I/O Expander 7 B */ + }, +}; + +struct inv_port_layout_s magnolia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 16} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 15} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 14} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 13} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 24} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 23} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 22} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 21} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 28} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 27} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 26} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 25} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 32} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 31} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 30} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 29} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 48} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 47} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 46} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 45} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 52} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 51} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 50} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 49} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 56} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 55} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 54} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 53} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 60} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 59} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 58} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 57} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 64} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 63} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 62} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 61} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 68} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 67} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 66} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 65} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 72} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 71} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 70} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 69} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 76} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 75} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 74} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 73} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD +unsigned redwood_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s redwood_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, +}; + +struct inv_port_layout_s redwood_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + { 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + { 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + { 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + { 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + {11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + {13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + {15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + {19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} }, + {29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} }, + {31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Hudson32i Layout configuration + * ========================================== + */ +#ifdef SWPS_HUDSON32I_GA +unsigned hudsin32iga_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s hudson32iga_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_HUDSON32IGA_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {1, IOEXP_TYPE_HUDSON32IGA_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */ + }, + {2, IOEXP_TYPE_HUDSON32IGA_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, + {3, IOEXP_TYPE_HUDSON32IGA_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */ + }, +}; + +struct inv_port_layout_s hudson32iga_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 1, 2, 3, 4} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 5, 6, 7, 8} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 9, 10, 11, 12} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 13, 14, 15, 16} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 17, 18, 19, 20} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 21, 22, 23, 24} }, + { 6, 12, 0, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 25, 26, 27, 28} }, + { 7, 13, 0, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 29, 30, 31, 32} }, + { 8, 14, 1, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 33, 34, 35, 36} }, + { 9, 15, 1, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 37, 38, 39, 40} }, + {10, 16, 1, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 41, 42, 43, 44} }, + {11, 17, 1, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 45, 46, 47, 48} }, + {12, 18, 1, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 49, 50, 51, 52} }, + {13, 19, 1, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 53, 54, 55, 56} }, + {14, 20, 1, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 57, 58, 59, 60} }, + {15, 21, 1, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 61, 62, 63, 64} }, + {16, 22, 2, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 65, 66, 67, 68} }, + {17, 23, 2, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 69, 70, 71, 72} }, + {18, 24, 2, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 73, 74, 75, 76} }, + {19, 25, 2, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + {20, 26, 2, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + {21, 27, 2, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 85, 86, 87, 88} }, + {22, 28, 2, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 89, 90, 91, 92} }, + {23, 29, 2, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 93, 94, 95, 96} }, + {24, 30, 3, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + {25, 31, 3, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + {26, 32, 3, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + {27, 33, 3, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, + {28, 34, 3, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {113,114,115,116} }, + {29, 35, 3, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {117,118,119,120} }, + {30, 36, 3, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {121,122,123,124} }, + {31, 37, 3, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Spruce Layout configuration + * ========================================== + */ +#ifdef SWPS_SPRUCE +unsigned spruce_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s spruce_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SPRUCE_7AB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[2] = I/O Expander 7B */ + }, +}; + +struct inv_port_layout_s spruce_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} }, + { 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} }, + { 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} }, + { 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} }, + { 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} }, + { 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Up->Down]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA1 +unsigned cypress_ga1_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; + +struct inv_ioexp_layout_s cypress_ga1_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_ga1_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (Inventec version [Down->Up]) + * ========================================== + */ +#ifdef SWPS_CYPRESS_GA2 +unsigned cypress_ga2_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +struct inv_ioexp_layout_s cypress_ga2_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_ga2_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 1, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 2, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 3, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 4, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 5, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 6, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 7, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 8, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + { 9, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + {10, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {11, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {12, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {13, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {14, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {15, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {16, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {17, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {18, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {19, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {20, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {21, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {22, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {23, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {24, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {25, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {26, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {27, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {28, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {29, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {30, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {31, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {32, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {33, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {34, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {35, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {36, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {37, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {38, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {39, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {40, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {41, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {42, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {43, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {44, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {45, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {46, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {47, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {48, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {49, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {50, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {51, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {52, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {53, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Cypress Layout configuration (BaiDu version) + * ========================================== + */ +#ifdef SWPS_CYPRESS_BAI +unsigned cypress_b_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; + +struct inv_ioexp_layout_s cypress_b_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_b_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 2, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 4, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 6, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 8, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + {10, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {12, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {14, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {16, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {18, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {20, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {22, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {24, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {26, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {28, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {30, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {32, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {34, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {36, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {38, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {40, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {42, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {44, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {46, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {48, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {50, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {52, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {54, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Redwood_fsl Layout configuration + * ========================================== + */ +#ifdef SWPS_REDWOOD_FSL +unsigned redwood_fsl_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; + +struct inv_ioexp_layout_s redwood_fsl_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, +}; + + +struct inv_port_layout_s redwood_fsl_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + { 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + { 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + { 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + { 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + {11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + {13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + {15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + {19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} }, + {29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} }, + {31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} }, +}; +#endif + + +/* ========================================== + * Tahoe Layout configuration + * ========================================== + */ +#ifdef SWPS_TAHOE +unsigned tahoe_gpio_rest_mux = MUX_RST_GPIO_249_PCA9548; + +struct inv_ioexp_layout_s tahoe_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_TAHOE_6ABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {1, IOEXP_TYPE_TAHOE_5A, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[0] = I/O Expander 5 A */ + }, +}; + + +struct inv_port_layout_s tahoe_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 12, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + { 1, 11, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + { 2, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + { 3, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + { 4, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + { 5, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + { 6, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + { 7, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + { 8, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + { 9, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, +}; +#endif + + +/* ========================================== + * Sequoia Layout configuration + * ========================================== + */ +#ifdef SWPS_SEQUOIA +unsigned sequoia_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; + +struct inv_ioexp_layout_s sequoia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { {1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + +struct inv_port_layout_s sequoia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 9, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 1, 10, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 2, 11, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 3, 12, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 4, 13, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + { 5, 14, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 6, 15, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + { 7, 16, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + { 8, 17, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + { 9, 18, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {10, 19, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {11, 20, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {12, 21, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + {13, 22, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + {14, 23, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121, 122, 123, 124} }, + {15, 24, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + {16, 25, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {137, 138, 139, 140} }, + {17, 26, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {129, 130, 131, 132} }, + {18, 27, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {153, 154, 155, 156} }, + {19, 28, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {145, 146, 147, 148} }, + {20, 29, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {169, 170, 171, 172} }, + {21, 30, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {161, 162, 163, 164} }, + {22, 31, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {185, 186, 187, 188} }, + {23, 32, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {177, 178, 179, 180} }, + {24, 33, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {201, 202, 203, 204} }, + {25, 34, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {193, 194, 195, 196} }, + {26, 35, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {217, 218, 219, 220} }, + {27, 36, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {209, 210, 211, 212} }, + {28, 37, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {233, 234, 235, 236} }, + {29, 38, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {225, 226, 227, 228} }, + {30, 39, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {249, 250, 251, 252} }, + {31, 40, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {241, 242, 243, 244} }, + {32, 44, 4, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + {33, 43, 4, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + {34, 42, 4, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + {35, 41, 4, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + {36, 48, 4, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {37, 47, 4, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {38, 46, 4, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {39, 45, 4, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {40, 52, 5, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {41, 51, 5, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {42, 50, 5, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {43, 49, 5, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {44, 56, 5, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, + {45, 55, 5, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + {46, 54, 5, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125, 126, 127, 128} }, + {47, 53, 5, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117, 118, 119, 120} }, + {48, 60, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {141, 142, 143, 144} }, + {49, 59, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {133, 134, 135, 136} }, + {50, 58, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {157, 158, 159, 160} }, + {51, 57, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {149, 150, 151, 152} }, + {52, 64, 6, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {173, 174, 175, 176} }, + {53, 63, 6, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {165, 166, 167, 168} }, + {54, 62, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {189, 190, 191, 192} }, + {55, 61, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {181, 182, 183, 184} }, + {56, 68, 7, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {205, 206, 207, 208} }, + {57, 67, 7, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {197, 198, 199, 200} }, + {58, 66, 7, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {221, 222, 223, 224} }, + {59, 65, 7, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {213, 214, 215, 216} }, + {60, 72, 7, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {237, 238, 239, 240} }, + {61, 71, 7, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {229, 230, 231, 232} }, + {62, 70, 7, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {253, 254, 255, 256} }, + {63, 69, 7, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {245, 246, 247, 248} }, +}; +#endif + + +/* ========================================== + * Lavender Layout configuration + * ========================================== + */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; +#endif + +#ifdef SWPS_LAVENDER +struct inv_ioexp_layout_s lavender_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { { 1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + { 1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { { 2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + { 2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + { 2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { { 3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + { 3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + { 3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { { 4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + { 4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + { 4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, + {8, IOEXP_TYPE_LAVENDER_P65, { { 5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xF6, 0xff}, {0xF8, 0xff}, }, }, /* addr[0] = I/O Expander CPU */ + }, +}; + + +struct inv_port_layout_s lavender_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {188, 189, 190, 191} }, + { 1, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {184, 185, 186, 187} }, + { 2, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {180, 181, 182, 183} }, + { 3, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {176, 177, 178, 179} }, + { 4, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {172, 173, 174, 175} }, + { 5, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {168, 169, 170, 171} }, + { 6, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {164, 165, 166, 167} }, + { 7, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {160, 161, 162, 163} }, + { 8, 25, 1, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {156, 157, 158, 159} }, + { 9, 26, 1, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {152, 153, 154, 155} }, + {10, 27, 1, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {148, 149, 150, 151} }, + {11, 28, 1, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {144, 145, 146, 147} }, + {12, 29, 1, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {140, 141, 142, 143} }, + {13, 30, 1, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {136, 137, 138, 139} }, + {14, 31, 1, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {132, 133, 134, 135} }, + {15, 32, 1, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {128, 129, 130, 131} }, + {16, 33, 2, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 0, 1, 2, 3} }, + {17, 34, 2, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 4, 5, 6, 7} }, + {18, 35, 2, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 8, 9, 10, 11} }, + {19, 36, 2, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 12, 13, 14, 15} }, + {20, 37, 2, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 16, 17, 18, 19} }, + {21, 38, 2, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 20, 21, 22, 23} }, + {22, 39, 2, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 24, 25, 26, 27} }, + {23, 40, 2, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 28, 29, 30, 31} }, + {24, 41, 3, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 32, 33, 34, 35} }, + {25, 42, 3, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 36, 37, 38, 39} }, + {26, 43, 3, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 40, 41, 42, 43} }, + {27, 44, 3, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 44, 45, 46, 47} }, + {28, 45, 3, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 48, 49, 50, 51} }, + {29, 46, 3, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 52, 53, 54, 55} }, + {30, 47, 3, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 56, 57, 58, 59} }, + {31, 48, 3, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 60, 61, 62, 63} }, + {32, 49, 4, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {256, 257, 258, 259} }, + {33, 50, 4, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {260, 261, 262, 263} }, + {34, 51, 4, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {264, 265, 266, 267} }, + {35, 52, 4, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {268, 269, 270, 271} }, + {36, 53, 4, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {272, 273, 274, 275} }, + {37, 54, 4, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {276, 277, 278, 279} }, + {38, 55, 4, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {280, 281, 282, 283} }, + {39, 56, 4, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {284, 285, 286, 287} }, + {40, 57, 5, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {288, 289, 290, 291} }, + {41, 58, 5, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {292, 293, 294, 295} }, + {42, 59, 5, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {296, 297, 298, 299} }, + {43, 60, 5, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {300, 301, 302, 303} }, + {44, 61, 5, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {304, 305, 306, 307} }, + {45, 62, 5, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {308, 309, 310, 311} }, + {46, 63, 5, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {312, 313, 314, 315} }, + {47, 64, 5, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {316, 317, 318, 319} }, + {48, 65, 6, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {444, 445, 446, 447} }, + {49, 66, 6, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {440, 441, 442, 443} }, + {50, 67, 6, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {436, 437, 438, 439} }, + {51, 68, 6, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {432, 433, 434, 435} }, + {52, 69, 6, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {428, 429, 430, 431} }, + {53, 70, 6, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {424, 425, 426, 427} }, + {54, 71, 6, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {420, 421, 422, 423} }, + {55, 72, 6, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {416, 417, 418, 419} }, + {56, 73, 7, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {412, 413, 414, 415} }, + {57, 74, 7, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {408, 409, 410, 411} }, + {58, 75, 7, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {404, 405, 406, 407} }, + {59, 76, 7, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {400, 401, 402, 403} }, + {60, 77, 7, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {396, 397, 398, 399} }, + {61, 78, 7, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {392, 393, 394, 395} }, + {62, 79, 7, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {388, 389, 390, 391} }, + {63, 80, 7, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {384, 385, 386, 387} }, + {64, 5, 8, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 64, 65, 66, 67} }, +}; +#endif + +/* =========================================================== + * Cottonwood Layout configuration Rangeley (Rangeley CPU board) + * =========================================================== + */ +#ifdef SWPS_COTTONWOOD_RANGELEY +unsigned cottonwood_rangeley_gpio_rest_mux = MUX_RST_GPIO_500_PAC9548; + +struct inv_ioexp_layout_s cottonwood_rangeley_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, CPLD_TYPE_COTTONWOOD,{ {1, 0x55, {22, 23, 24, 25}, {22, 23, 24, 25}, {-1, -1, -1, -1}, {0xee, 0xee, 0x99, 0x99}, {0x00, 0x00, 0x00, 0x00}, }, + }, + }, +}; + + +struct inv_port_layout_s cottonwood_rangeley_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHI_TYPE / LANE_ID */ + { 0, 2, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 75} }, + { 1, 3, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 77} }, + { 2, 4, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 79} }, + { 3, 5, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, +}; +#endif + +/* =========================================================== + * Maple Layout configuration + * =========================================================== + */ +#ifdef SWPS_MAPLE +unsigned maple_gpio_rest_mux = 249; + +struct inv_ioexp_layout_s maple_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAPLE_0ABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_MAPLE_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_MAPLE_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_MAPLE_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_MAPLE_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_MAPLE_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_MAPLE_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s maple_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 1} }, + { 1, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 2} }, + { 2, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 3} }, + { 3, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 4} }, + { 4, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 5} }, + { 5, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 6} }, + { 6, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 7} }, + { 7, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 8} }, + { 8, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 13} }, + { 9, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 14} }, + {10, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 15} }, + {11, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 16} }, + {12, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 21} }, + {13, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 22} }, + {14, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 23} }, + {15, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 24} }, + {16, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 29} }, + {17, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 30} }, + {18, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 31} }, + {19, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 32} }, + {20, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 33} }, + {21, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 34} }, + {22, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 35} }, + {23, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 36} }, + {24, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 41} }, + {25, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 42} }, + {26, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 43} }, + {27, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 44} }, + {28, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 49} }, + {29, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 50} }, + {30, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 51} }, + {31, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 52} }, + {32, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 57} }, + {33, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 58} }, + {34, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 59} }, + {35, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 60} }, + {36, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 61} }, + {37, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 62} }, + {38, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 63} }, + {39, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 64} }, + {40, 58, 6, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 65} }, + {41, 59, 6, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 66} }, + {42, 60, 6, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 67} }, + {43, 61, 6, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 68} }, + {44, 62, 6, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 69} }, + {45, 63, 6, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 70} }, + {46, 64, 6, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 71} }, + {47, 65, 6, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 72} }, + {48, 10, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 77, 78, 79, 80} }, + {49, 11, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 85, 86, 87, 88} }, + {50, 12, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 93, 94, 95, 96} }, + {51, 13, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 97, 98, 99,100} }, + {52, 14, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {105,106,107,108} }, + {53, 15, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {113,114,115,116} }, + {54, 16, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {121,122,123,124} }, + {55, 17, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {125,126,127,128} }, +}; +#endif + +#endif /* INV_SWPS_H */ + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.c new file mode 100644 index 000000000000..4564b5855fd8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.c @@ -0,0 +1,2046 @@ +#include +#include +#include "io_expander.h" + +static struct ioexp_obj_s *ioexp_head_p = NULL; +static struct ioexp_obj_s *ioexp_tail_p = NULL; + + +/* ========== Register IOEXP layout ========== + */ +struct ioexp_map_s ioexp_map_magnolia_nab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_magnolia_4ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_magnolia_7ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {1, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {1, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {1, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 2}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 3}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 0, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 0, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 0, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 0, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 0, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 0, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 0, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 1, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 1, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 1, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 1, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 1, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 1, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 1, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_cypress_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_cypress_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 1, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 1, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 1, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {0, 1, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {0, 1, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {1, 1, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {1, 1, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {1, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {1, 1, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_5a = { + + .chip_amount = 1, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_6abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 0}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 3}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 0}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + {2, 1, 5}, /* map_present[8] = MOD_ABS_PORT(X+8) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + {2, 1, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + {2, 1, 4}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+8) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + {2, 1, 2}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_sequoia_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_lavender_p65 = { + + .chip_amount = 1, + .data_width = 1, + + .map_present = { {0, 0, 4}, }, /* map_present[0] = MOD_ABS_PORT(X) */ + .map_reset = { {0, 0, 1}, }, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + .map_lpmod = { {0, 0, 2}, }, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + .map_modsel = { {0, 0, 0}, }, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ +}; + + +struct ioexp_map_s cpld_map_cottonwood = { + + .chip_amount = 1, + .data_width = 4, + + .map_present = { {0, 2, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 2, 4}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 3, 0}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 3, 4}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + }, + .map_tx_disable = { {0, 0, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 4}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 4}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + }, + .map_tx_fault = { {0, 2, 2}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 2, 6}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 3, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 3, 6}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + }, + .map_rxlos = { {0, 2, 1}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 2, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 3, 1}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 3, 5}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + }, + .map_hard_rs0 = { {0, 0, 2}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {0, 0, 6}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {0, 1, 2}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {0, 1, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + }, + .map_hard_rs1 = { {0, 0, 2}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {0, 0, 6}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {0, 1, 2}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {0, 1, 6}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + }, +}; + +struct ioexp_map_s ioexp_map_maple_0abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP_N_P(X+7) */ + }, +}; + +struct ioexp_map_s ioexp_map_maple_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + +/* ========== Private functions ========== + */ +int check_channel_tier_1(void); + +struct i2c_client * +_get_i2c_client(struct ioexp_obj_s *self, + int chip_id){ + + struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p; + + if (!(i2c_curr_p)){ + SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__); + return NULL; + } + while (i2c_curr_p){ + if ((i2c_curr_p->chip_id) == chip_id){ + return i2c_curr_p->i2c_client_p; + } + i2c_curr_p = i2c_curr_p->next; + } + SWPS_ERR("%s: not exist! :%d\n", __func__, chip_id); + return NULL; +} + + +static int +_common_ioexp_update_one(struct ioexp_obj_s *self, + struct ioexp_addr_s *ioexp_addr, + int chip_id, + int data_width, + int show_err, + char *caller_name) { + int buf = 0; + int err = 0; + int data_id = 0; + int r_offset = 0; + + for(data_id=0; data_idread_offset[data_id]; + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset); + /* Check error */ + if (buf < 0) { + err = 1; + if (show_err) { + SWPS_INFO("IOEXP-%d read fail! :%d \n", self->ioexp_id, buf); + SWPS_INFO("Dump: :%d :0x%02x :%d, :%s\n", + ioexp_addr->chan_id, ioexp_addr->chip_addr, + ioexp_addr->read_offset[data_id], caller_name); + } + continue; + } + /* Update IOEXP object */ + self->chip_data[chip_id].data[data_id] = (uint8_t)buf; + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +common_ioexp_update_all(struct ioexp_obj_s *self, + int show_err, + char *caller_name){ + + int err = 0; + int chip_id = 0; + int chip_amount = self->ioexp_map_p->chip_amount; + + for (chip_id=0; chip_idioexp_map_p->map_addr[chip_id]), + chip_id, + self->ioexp_map_p->data_width, + show_err, + caller_name) < 0) { + err = 1; + } + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +_common_check_by_mode(struct ioexp_obj_s *self){ + + switch (self->mode){ + case IOEXP_MODE_DIRECT: + return self->fsm_4_direct(self); + + case IOEXP_MODE_POLLING: + if (self->state >= 0){ + return 0; + } + switch (self->state){ + case STATE_IOEXP_INIT: + return ERR_IOEXP_UNINIT; + case STATE_IOEXP_ABNORMAL: + return ERR_IOEXP_ABNORMAL; + default: + return ERR_IOEXP_NOSTATE; + } + break; + + default: + break; + } + SWPS_ERR("%s: Exception occurs. :%d \n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +static int +_common_get_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + char *func_mane){ + uint8_t buf; + int err_code; + + /* Check and get address */ + err_code = _common_check_by_mode(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Get data form cache */ + buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + return (int)(buf >> bitmap_obj_p->bit_shift & 0x01); +} + + +static int +_common_set_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + int input_val, + char *func_mane){ + int err_code, target_offset; + uint8_t origin_byte; + uint8_t modify_byte; + + /* Check and get address */ + err_code = _common_check_by_mode(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Prepare write date */ + origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + switch (input_val) { + case 0: + modify_byte = origin_byte; + SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift); + break; + case 1: + modify_byte = origin_byte; + SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift); + break; + default: + SWPS_ERR("Input value incorrect! :%d :%d :%s\n", + input_val, self->ioexp_id, func_mane); + return ERR_IOEXP_BADINPUT; + } + /* Setup i2c client */ + target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset]; + /* Write byte to chip via I2C */ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id), + target_offset, + modify_byte); + /* Update or bollback object */ + if (err_code < 0){ + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte; + SWPS_ERR("I2C write fail! :%d :%d :%s :%d\n", + input_val, self->ioexp_id, func_mane, err_code); + return err_code; + } + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte; + return 0; +} + + +/* ========== Object public functions ========== + */ +int +common_get_present(struct ioexp_obj_s *self, + int virt_offset){ + + int UNPLUG = 1; + int retval = ERR_IOEXP_UNEXCPT; + + retval = _common_get_bit(self, + &(self->ioexp_map_p->map_present[virt_offset]), + "common_get_present"); + if (retval < 0) { + /* [Note] + * => Transceiver object does not need to handle IOEXP layer issues. + */ + return UNPLUG; + } + return retval; +} + + +int +common_get_tx_fault(struct ioexp_obj_s *self, + int virt_offset){ + /* [Transmit Fault (Tx_Fault)] + * A catastrophic laser fault will activate the transmitter signal, + * TX_FAULT, and disable the laser. This signal is an open collector + * output (pull-up required on the host board). A low signal indicates + * normal laser operation and a high signal indicates a fault. The + * TX_FAULT will be latched high when a laser fault occurs and is + * cleared by toggling the TX_DISABLE input or power cycling the + * transceiver. The transmitter fault condition can also be monitored + * via the two-wire serial interface. + * (address A2, byte 110, bit 2). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_fault[virt_offset]), + "common_get_tx_fault"); +} + + +int +common_get_rxlos(struct ioexp_obj_s *self, + int virt_offset){ + /* [Receiver Loss of Signal (Rx_LOS)] + * The post-amplification IC also includes transition detection circuitry + * which monitors the ac level of incoming optical signals and provides a + * TTL/CMOS compatible status signal to the host (pin 8). An adequate optical + * input results in a low Rx_LOS output while a high Rx_LOS output indicates + * an unusable optical input. The Rx_LOS thresholds are factory set so that + * a high output indicates a definite optical fault has occurred. Rx_LOS can + * also be monitored via the two-wire serial interface + * (address A2h, byte 110, bit 1). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_rxlos[virt_offset]), + "common_get_rxlos"); +} + + +int +common_get_tx_disable(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + "common_get_tx_disable"); +} + + +int +common_get_reset(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + "common_get_reset"); +} + + +int +common_get_lpmod(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + "common_get_lpmod"); +} + + +int +common_get_modsel(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + "common_get_modsel"); +} + + +int +common_get_hard_rs0(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + "common_get_hard_rs0"); +} + + +int +common_get_hard_rs1(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + "common_get_hard_rs1"); +} + + +int +common_set_tx_disable(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + input_val, + "common_set_tx_disable"); +} + + +int +common_set_reset(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + input_val, + "common_set_reset"); +} + + +int +common_set_lpmod(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + input_val, + "common_set_lpmod"); +} + + +int +common_set_modsel(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + input_val, + "common_set_modsel"); +} + + +int +common_set_hard_rs0(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + input_val, + "common_set_hard_rs0"); +} + + +int +common_set_hard_rs1(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + input_val, + "common_set_hard_rs1"); +} + + +int +ioexp_get_not_support(struct ioexp_obj_s *self, + int virt_offset){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +ioexp_set_not_support(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +fake_ioexp_init(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_ioexp_update(struct ioexp_obj_s *self){ + return 1; +} + + +int +fake_update_func(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_get_func(struct ioexp_obj_s *self, + int virt_offset){ + SWPS_WARN("Someone called fake_get_func\n"); + return -1; +} + +int +fake_set_func(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + SWPS_WARN("Someone called fake_set_func\n"); + return -1; +} + + +/* ========== Initial functions for IO Expander ========== + */ +int +common_ioexp_init(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + if (self->mode == IOEXP_MODE_DIRECT) { + goto update_common_ioexp_init; + } + /* Setup default value to each physical IO Expander */ + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + /* Get address mapping */ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("%s: IOEXP config incorrect! :%d \n", + __func__, chip_id); + return -1; + } + /* Setup default value */ + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + /* [Desc] Skip the setup default value behavior + [Note] Setup default value = -1 if you don't want to write the value to IOEXP or CPLD + */ + if(addr_p->write_offset[offset] < 0){ + SWPS_DEBUG("skip a write_offset <%d>\n", addr_p->conf_offset[offset]); + continue; + } + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->write_offset[offset], + addr_p->data_default[offset]); + if (err_code < 0){ + SWPS_ERR("%s: set default fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + } + } +update_common_ioexp_init: + /* Check and update info to object */ + err_code = self->update_all(self, 1, "common_ioexp_init"); + if (err_code < 0) { + SWPS_ERR("%s: update_all() fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +/* ========== Object functions for Final State Machine ========== + */ +int +_is_channel_ready(struct ioexp_obj_s *self){ + + int buf = 0; + int chip_id = 0; /* Use first chip which be registered */ + int data_id = 0; /* Use first byte which be registered */ + struct ioexp_addr_s *ioexp_addr = NULL; + + ioexp_addr = &(self->ioexp_map_p->map_addr[chip_id]); + if (!ioexp_addr){ + SWPS_ERR("%s: config incorrect!\n", __func__); + return ERR_IOEXP_UNEXCPT; + } + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), + ioexp_addr->read_offset[data_id]); + if (buf >= 0){ + return 1; + } + return 0; +} + +int +_ioexp_init_handler(struct ioexp_obj_s *self){ + + int return_val; + + switch (self->mode) { + case IOEXP_MODE_DIRECT: + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + + case IOEXP_MODE_POLLING: + /* Check system and channel is ready */ + if (self->state == STATE_IOEXP_INIT){ + if (!_is_channel_ready(self)){ + self->state = STATE_IOEXP_INIT; + SWPS_WARN("%s: IOEXP:%d channel not ready.\n", + __func__, self->ioexp_id); + return 0; + } + } + /* Execute initial callback */ + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + + default: + break; + } + SWPS_ERR("%s: exception occur :%d\n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){ + + int result_val; + int show_err = 1; + char *func_mane = "common_ioexp_fsm_4_direct"; + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, and return error */ + return ERR_IOEXP_UNINIT; + } + /* Case: Initial done */ + return 0; + + case STATE_IOEXP_NORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + SWPS_INFO("%s: NORMAL -> ABNORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + self->state = STATE_IOEXP_NORMAL; + return 0; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_DEBUG("%s: ABNORMAL -> NORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("%s: Exception occurs :%d\n", + __func__, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_polling(struct ioexp_obj_s *self){ + + int result_val, i, show_e; + int fail_retry = 3; + char *func_name = "common_ioexp_fsm_4_polling"; + +#ifdef DEBUG_SWPS + show_e = 1; +#else + show_e = 0; +#endif + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + /* Case: System (Channel) not ready */ + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, wait and retry */ + return 0; + } + /* Case: Initial done */ + SWPS_INFO("IOEXP-%d: initial done. :%d\n", + self->ioexp_id, self->ioexp_type); + return result_val; + + case STATE_IOEXP_NORMAL: + /* Retry mechanism for case of i2c topology not stable */ + for (i=0; iupdate_all(self, show_e, func_name); + if (result_val >= 0) { + self->state = STATE_IOEXP_NORMAL; + return 0; + } + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: detect I2C crash :%d\n", + __func__, self->ioexp_id); + break; + } + SWPS_DEBUG("IOEXP-%d: unstable :%d\n", + self->ioexp_id, result_val); + } + SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_e, func_name); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_INFO("IOEXP-%d: ABNORMAL -> NORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("IOEXP-%d: Exception occurs :%d\n", + self->ioexp_id, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +/* ========== Object private functions for check & update ========== + */ +int +common_ioexp_check(struct ioexp_obj_s *self){ + + int result; + + if (self->mode != IOEXP_MODE_POLLING){ + SWPS_ERR("%s: not polling mode :%d\n", + __func__, self->mode); + return ERR_IOEXP_NOTSUPPORT; + } + mutex_lock(&self->lock); + result = self->fsm_4_polling(self); + mutex_unlock(&self->lock); + return result; +} + + +/* ========== Functions for Factory pattern ========== + */ +static struct ioexp_map_s * +get_ioexp_map(int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + return &ioexp_map_magnolia_nab; + case IOEXP_TYPE_MAGINOLIA_4AB: + return &ioexp_map_magnolia_4ab; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + return &ioexp_map_magnolia_7ab; + case IOEXP_TYPE_REDWOOD_P01P08: + return &ioexp_map_redwood_p01p08_p17p24; + case IOEXP_TYPE_REDWOOD_P09P16: + return &ioexp_map_redwood_p09p16_p25p32; + case IOEXP_TYPE_HUDSON32IGA_P01P08: + return &ioexp_map_hudson32iga_p01p08_p17p24; + case IOEXP_TYPE_HUDSON32IGA_P09P16: + return &ioexp_map_hudson32iga_p09p16_p25p32; + case IOEXP_TYPE_CYPRESS_NABC: + return &ioexp_map_cypress_nabc; + case IOEXP_TYPE_CYPRESS_7ABC: + return &ioexp_map_cypress_7abc; + case IOEXP_TYPE_TAHOE_5A: + return &ioexp_map_tahoe_5a; + case IOEXP_TYPE_TAHOE_6ABC: + return &ioexp_map_tahoe_6abc; + case IOEXP_TYPE_SEQUOIA_NABC: + return &ioexp_map_sequoia_nabc; + case IOEXP_TYPE_LAVENDER_P65: + return &ioexp_map_lavender_p65; + case CPLD_TYPE_COTTONWOOD: + return &cpld_map_cottonwood; + case IOEXP_TYPE_MAPLE_0ABC: + return &ioexp_map_maple_0abc; + case IOEXP_TYPE_MAPLE_NABC: + return &ioexp_map_maple_nabc; + default: + return NULL; + } +} + + +int +setup_ioexp_ssize_attr(struct ioexp_obj_s *self, + struct ioexp_map_s *ioexp_map_p, + int ioexp_id, + int ioexp_type, + int run_mode){ + switch (run_mode){ + case IOEXP_MODE_POLLING: /* Direct access device mode */ + case IOEXP_MODE_DIRECT: /* Polling mode, read from cache */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = ERR_IOEXP_UNEXCPT; + return ERR_IOEXP_UNEXCPT; + } + /* Setup mapping structure */ + self->ioexp_map_p = kzalloc(sizeof(*ioexp_map_p), GFP_KERNEL); + if (!(self->ioexp_map_p)) { + SWPS_ERR("%s: kzalloc ioexp_map_p fail\n", __func__); + return -1; + } + memcpy(self->ioexp_map_p, ioexp_map_p, sizeof(*ioexp_map_p)); + /* Setup attributes */ + self->ioexp_id = ioexp_id; + self->ioexp_type = ioexp_type; + self->state = STATE_IOEXP_INIT; + mutex_init(&self->lock); + return 0; +} + + +static int +setup_addr_mapping(struct ioexp_obj_s *self, + struct ioexp_addr_s *addr_map_p, + int chip_amount){ + struct ioexp_addr_s *tmp_p; + if (!addr_map_p){ + SWPS_ERR("%s: map is null\n", __func__); + return -1; + } + tmp_p = kzalloc((sizeof(*addr_map_p) * chip_amount), GFP_KERNEL); + if (!tmp_p){ + SWPS_ERR("%s: kzalloc fail.\n", __func__); + return -1; + } + memcpy(tmp_p, addr_map_p, (sizeof(*addr_map_p) * chip_amount)); + self->ioexp_map_p->map_addr = tmp_p; + + return 0; +} + + +static int +setup_ioexp_public_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case CPLD_TYPE_COTTONWOOD: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_MAPLE_NABC: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->get_hard_rs0 = common_get_hard_rs0; + self->get_hard_rs1 = common_get_hard_rs1; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + self->set_hard_rs0 = common_set_hard_rs0; + self->set_hard_rs1 = common_set_hard_rs1; + return 0; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case IOEXP_TYPE_MAPLE_0ABC: + self->get_present = common_get_present; + self->get_tx_fault = ioexp_get_not_support; + self->get_rxlos = ioexp_get_not_support; + self->get_tx_disable = ioexp_get_not_support; + self->get_reset = common_get_reset; + self->get_lpmod = common_get_lpmod; + self->get_modsel = common_get_modsel; + self->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + self->set_tx_disable = ioexp_set_not_support; + self->set_reset = common_set_reset; + self->set_lpmod = common_set_lpmod; + self->set_modsel = common_set_modsel; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_ioexp_private_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_4AB: + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + case IOEXP_TYPE_LAVENDER_P65: + case CPLD_TYPE_COTTONWOOD: + case IOEXP_TYPE_MAPLE_NABC: + case IOEXP_TYPE_MAPLE_0ABC: + self->init = common_ioexp_init; + self->check = common_ioexp_check; + self->update_all = common_ioexp_update_all; + self->fsm_4_direct = common_ioexp_fsm_4_direct; + self->fsm_4_polling = common_ioexp_fsm_4_polling; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_i2c_client_one(struct ioexp_obj_s *self, + int chip_id){ + + char *err_msg = "ERROR"; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + struct ioexp_i2c_s *i2c_obj_p = NULL; + struct ioexp_i2c_s *i2c_curr_p = NULL; + + int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id; + adap = i2c_get_adapter(chan_id); + if(!adap){ + err_msg = "Can not get adap!"; + goto err_ioexp_setup_i2c_1; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + err_msg = "Can not kzalloc client!"; + goto err_ioexp_setup_i2c_1; + } + i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL); + if (!i2c_obj_p){ + err_msg = "Can not kzalloc i2c_obj_p!"; + goto err_ioexp_setup_i2c_2; + } + client->adapter = adap; + client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr; + i2c_obj_p->i2c_client_p = client; + i2c_obj_p->chip_id = chip_id; + i2c_obj_p->next = NULL; + if (!self->i2c_head_p){ + self->i2c_head_p = i2c_obj_p; + } else { + i2c_curr_p = self->i2c_head_p; + while (i2c_curr_p->next){ + i2c_curr_p = i2c_curr_p->next; + } + i2c_curr_p->next = i2c_obj_p; + } + return 0; + +err_ioexp_setup_i2c_2: + kfree(client); +err_ioexp_setup_i2c_1: + SWPS_ERR("%s: %s :%d\n", __func__, err_msg, chan_id); + return -1; +} + + +static int +setup_i2c_client(struct ioexp_obj_s* self){ + + int result; + int chip_id = 0; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + result = setup_i2c_client_one(self, chip_id); + if (result < 0){ + SWPS_ERR("%s fail! :%d\n", __func__, chip_id); + return -1; + } + } + return 0; +} + + +static int +setup_ioexp_config(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("IOEXP config incorrect! :%d \n",chip_id); + return -1; + } + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + /* [Desc] Skip the setup config value behavior + [Note] Setup config value = -1 if you don't want to write the value to IOEXP or CPLD + */ + if(addr_p->conf_offset[offset] < 0){ + SWPS_DEBUG("skip a config_offset <%d>\n", addr_p->conf_offset[offset]); + continue; + } + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->conf_offset[offset], + addr_p->conf_default[offset]); + + if (err_code < 0){ + SWPS_INFO("%s: set conf fail! :%d \n", __func__, err_code); + return -2; + } + } + } + return 0; +} + + +struct ioexp_obj_s * +_create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_map_s* ioexp_map_p; + struct ioexp_obj_s* result_p; + struct ioexp_i2c_s *i2c_curr_p; + struct ioexp_i2c_s *i2c_next_p; + + /* Get layout */ + ioexp_map_p = get_ioexp_map(ioexp_type); + if (!ioexp_map_p){ + SWPS_ERR("%s: Invalid ioexp_type\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare IOEXP object */ + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + SWPS_ERR("%s: kzalloc failure!\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare static size attributes */ + if (setup_ioexp_ssize_attr(result_p, + ioexp_map_p, + ioexp_id, + ioexp_type, + run_mode) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + /* Prepare address mapping */ + if (setup_addr_mapping(result_p, addr_map_p, ioexp_map_p->chip_amount) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + if (setup_i2c_client(result_p) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + /* Prepare call back functions of object */ + if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + return result_p; + +err_create_ioexp_setup_i2c_fail: + i2c_curr_p = result_p->i2c_head_p; + i2c_next_p = result_p->i2c_head_p; + while (i2c_curr_p){ + i2c_next_p = i2c_curr_p->next; + kfree(i2c_curr_p->i2c_client_p); + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } +err_create_ioexp_setup_attr_fail: + kfree(result_p); +err_create_ioexp_fail: + SWPS_ERR("%s: fail! :%d :%d \n", + __func__, ioexp_id, ioexp_type); + return NULL; +} + + +int +create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_obj_s *ioexp_p = NULL; + + ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type, + addr_map_p, run_mode); + if (!ioexp_p){ + return -1; + } + if (ioexp_head_p == NULL){ + ioexp_head_p = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; + } + ioexp_tail_p->next = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; +} + + +static int +_init_ioexp_obj(struct ioexp_obj_s* self) { + + char *err_msg = "ERR"; + char *func_name = "_init_ioexp_obj"; + + /* Setup IOEXP configure byte */ + if (setup_ioexp_config(self) < 0){ + err_msg = "setup_ioexp_config fail"; + goto err_init_ioexp_obj; + } + /* Setup default data */ + if (_ioexp_init_handler(self) < 0){ + err_msg = "_ioexp_init_handler fail"; + goto err_init_ioexp_obj; + } + /* Update all */ + if (self->state == STATE_IOEXP_NORMAL){ + if (self->update_all(self, 1, func_name) < 0){ + err_msg = "update_all() fail"; + goto err_init_ioexp_obj; + } + } + return 0; + +err_init_ioexp_obj: + SWPS_DEBUG("%s: %s\n", __func__, err_msg); + return -1; +} + + +int +init_ioexp_objs(void){ + /* Return value: + * 0: Success + * -1: Detect topology error + * -2: SWPS internal error + */ + + struct ioexp_obj_s *curr_p = ioexp_head_p; + + if (!curr_p) { + SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__); + return -2; + } + while (curr_p) { + if (_init_ioexp_obj(curr_p) < 0) { + SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__); + return -1; + } + curr_p = curr_p->next; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + + +void +clean_ioexp_objs(void){ + + struct ioexp_i2c_s *i2c_curr_p = NULL; + struct ioexp_i2c_s *i2c_next_p = NULL; + struct ioexp_obj_s *ioexp_next_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + if (ioexp_head_p == NULL){ + ioexp_tail_p = NULL; + return; + } + while(ioexp_curr_p){ + ioexp_next_p = ioexp_curr_p->next; + if (ioexp_curr_p->ioexp_map_p) { + if (ioexp_curr_p->ioexp_map_p->map_addr) { + kfree(ioexp_curr_p->ioexp_map_p->map_addr); + } + kfree(ioexp_curr_p->ioexp_map_p); + } + + i2c_curr_p = ioexp_curr_p->i2c_head_p; + while (i2c_curr_p) { + i2c_next_p = i2c_curr_p->next; + kfree(i2c_curr_p->i2c_client_p); + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } + kfree(ioexp_curr_p); + ioexp_curr_p = ioexp_next_p; + } + ioexp_tail_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} + + +int +check_ioexp_objs(void){ + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while (ioexp_curr_p){ + if ( (ioexp_curr_p->check(ioexp_curr_p)) < 0){ + SWPS_INFO("check IOEXP-%d fail! :%d\n", + ioexp_curr_p->ioexp_id, ioexp_curr_p->ioexp_type); + return -1; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +struct ioexp_obj_s * +get_ioexp_obj(int ioexp_id){ + + struct ioexp_obj_s *result_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + if (ioexp_curr_p->ioexp_id == ioexp_id){ + result_p = ioexp_curr_p; + break; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return result_p; +} + + +void +unlock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_unlock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } +} + + +int +lock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_lock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} + + +static int +_scan_channel_tier_1(int force, + int show_err) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + int ready = 0; + + if (!ioexp_curr_p) { + goto err_scan_tier_1_channel; + } + while(ioexp_curr_p) { + ready = _is_channel_ready(ioexp_curr_p); + if ((!ready) && (!force)) { + goto err_scan_tier_1_channel; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; + +err_scan_tier_1_channel: + if (show_err) { + if (ioexp_curr_p) { + SWPS_INFO("%s: IOEXP-%d fail\n", __func__, ioexp_curr_p->ioexp_id); + } else { + SWPS_INFO("%s: IOEXP is null.\n", __func__); + } + } + return -1; +} + + +static int +_scan_channel_tier_1_single(void) { + + int ret = 0; + int chan_id = 0; + int fake_cid = 0; + int fake_offs = 0; + int fake_addr = 0; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + + if (ioexp_head_p->ioexp_id != ioexp_tail_p->ioexp_id) { + return 0; + } + /* Setup i2c_client */ + chan_id = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chan_id; + fake_addr = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chip_addr; + adap = i2c_get_adapter((chan_id + 1)); + if(!adap){ + SWPS_INFO("%s: Can not get adap!\n", __func__); + return 0; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + SWPS_INFO("%s: Can not kzalloc client!\n", __func__); + return 0; + } + client->adapter = adap; + client->addr = fake_addr; + /* Fouce move ioexp ptr to next */ + ret = i2c_smbus_read_byte_data(client, fake_offs); + SWPS_DEBUG("%s: move ioexp_ptr done. :%d\n", __func__, ret); + kfree(client); + return 1; +} + + +int +resync_channel_tier_1(void) { + + char *emsg = "ERR"; + + if (!ioexp_head_p) { + emsg = "ioexp_head_p is NULL"; + goto err_resync_ioexp_status_1; + } + /* Run all */ + if (ioexp_head_p->ioexp_id == ioexp_tail_p->ioexp_id) { + _scan_channel_tier_1_single(); + } else { + _scan_channel_tier_1(1, 0); + } + /* Check all */ + if (_scan_channel_tier_1(0, 1) < 0) { + emsg = "resync tier-1 channel fail"; + goto err_resync_ioexp_status_1; + } + return 0; + +err_resync_ioexp_status_1: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.h new file mode 100644 index 000000000000..1af909e2466a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/io_expander.h @@ -0,0 +1,187 @@ +/* + * 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. + */ + +#ifndef IO_EXPANDER_H +#define IO_EXPANDER_H + +#include + + +/* IOEXP type define (SFP series) */ +#define IOEXP_TYPE_MAGINOLIA_NAB (10101) +#define IOEXP_TYPE_MAGINOLIA_4AB (10102) +#define IOEXP_TYPE_CYPRESS_NABC (10103) +#define IOEXP_TYPE_MAPLE_NABC (10104) + +/* IOEXP type define (QSFP series) */ +#define IOEXP_TYPE_MAGINOLIA_7AB (10201) +#define IOEXP_TYPE_REDWOOD_P01P08 (10202) +#define IOEXP_TYPE_REDWOOD_P09P16 (10203) +#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204) +#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205) +#define IOEXP_TYPE_SPRUCE_7AB (10206) +#define IOEXP_TYPE_CYPRESS_7ABC (10207) +#define IOEXP_TYPE_TAHOE_5A (10208) +#define IOEXP_TYPE_TAHOE_6ABC (10209) +#define IOEXP_TYPE_SEQUOIA_NABC (10210) +#define IOEXP_TYPE_LAVENDER_P65 (10211) +#define IOEXP_TYPE_MAPLE_0ABC (10212) + +/* CPLD type define */ +#define CPLD_TYPE_COTTONWOOD (10301) + +/* IOEXP mode define */ +#define IOEXP_MODE_POLLING (19000) +#define IOEXP_MODE_DIRECT (19001) + +/* IOEXP state define */ +#define STATE_IOEXP_NORMAL (0) +#define STATE_IOEXP_INIT (-1) +#define STATE_IOEXP_ABNORMAL (-2) + +/* IOEXP error code define */ +#define ERR_IOEXP_NOTSUPPORT (-100) +#define ERR_IOEXP_UNINIT (-101) +#define ERR_IOEXP_BADCONF (-102) +#define ERR_IOEXP_ABNORMAL (-103) +#define ERR_IOEXP_NOSTATE (-104) +#define ERR_IOEXP_BADINPUT (-105) +#define ERR_IOEXP_UNEXCPT (-199) + +#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args) +#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args) +#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args) + +#ifdef DEBUG_SWPS +# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args) +#else +# define SWPS_DEBUG(fmt, args...) +#endif + + +struct ioexp_addr_s { + int chan_id; + int chip_addr; + int read_offset[8]; + int write_offset[8]; + int conf_offset[8]; + uint8_t data_default[8]; + uint8_t conf_default[8]; +}; + +struct ioexp_i2c_s { + int chip_id; + struct i2c_client *i2c_client_p; + struct ioexp_i2c_s *next; +}; + + +struct ioexp_bitmap_s { + int chip_id; /* IOEXP chip id */ + int ioexp_voffset; /* IOEXP virtual offset */ + int bit_shift; +}; + +struct ioexp_map_s { + int chip_amount; /* Number of chips that IOEXP object content */ + int data_width; /* Number of (Read/Write/Config) bytes */ + struct ioexp_addr_s *map_addr; /* Chip address info */ + struct ioexp_bitmap_s map_present[10]; /* IOEXP for SFP / QSFP */ + struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[10]; /* IOEXP for QSFP */ +}; + +struct ioexp_data_s { + uint8_t data[8]; +}; + +struct ioexp_obj_s { + + /* ============================ + * Object public property + * ============================ + */ + int ioexp_id; + int ioexp_type; + + /* ============================ + * Object private property + * ============================ + */ + struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */ + struct ioexp_map_s *ioexp_map_p; + struct ioexp_obj_s *next; + struct ioexp_i2c_s *i2c_head_p; + struct mutex lock; + int mode; + int state; + + /* =========================================== + * Object public functions + * =========================================== + */ + int (*get_present)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset); + int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset); + int (*get_reset)(struct ioexp_obj_s *self, int virt_offset); + int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset); + int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs1)(struct ioexp_obj_s *self, int virt_offset); + int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val); + + /* =========================================== + * Object private functions + * =========================================== + */ + int (*init)(struct ioexp_obj_s *self); + int (*check)(struct ioexp_obj_s *self); + int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name); + int (*fsm_4_direct)(struct ioexp_obj_s* self); + int (*fsm_4_polling)(struct ioexp_obj_s* self); +}; + + +struct ioexp_obj_s* get_ioexp_obj(int ioexp_id); +int create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode); +int init_ioexp_objs(void); +int check_ioexp_objs(void); +void clean_ioexp_objs(void); + +void unlock_ioexp_all(void); +int lock_ioexp_all(void); + +int check_channel_tier_1(void); +int resync_channel_tier_1(void); + +/* Macro for bit control */ +#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift))) +#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift))) + + +#endif /* IO_EXPANDER_H */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.c new file mode 100644 index 000000000000..6fe8f599fb48 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.c @@ -0,0 +1,8389 @@ +/* + * 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 "io_expander.h" +#include "transceiver.h" + + +/* ========== Register EEPROM address mapping ========== + */ +struct eeprom_map_s eeprom_map_sfp = { + .addr_br =0x50, .page_br =-1, .offset_br =12, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =94, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =-1, .offset_connector =2, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =-1, .offset_diag_type =92 , .length_diag_type =1, + .addr_extbr =-1, .page_extbr =-1, .offset_extbr =-1, .length_extbr =-1, + .addr_ext_id =0x50, .page_ext_id =-1, .offset_ext_id =1, .length_ext_id =1, + .addr_id =0x50, .page_id =-1, .offset_id =0, .length_id =1, + .addr_len_sm =0x50, .page_len_sm =-1, .offset_len_sm =15, .length_len_sm =1, + .addr_len_smf =0x50, .page_len_smf =-1, .offset_len_smf =14, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =-1, .offset_len_om1 =17, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =-1, .offset_len_om2 =16, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =-1, .offset_len_om3 =19, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =-1, .offset_len_om4 =18, .length_len_om4 =1, + .addr_option =0x50, .page_option =-1, .offset_option =64, .length_option =2, + .addr_rate_id =0x50, .page_rate_id =-1, .offset_rate_id =13, .length_rate_id =1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =0x51, .page_rx_em =-1, .offset_rx_em =115, .length_rx_em =1, + .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1, + .addr_rx_power =0x51, .page_rx_power =-1, .offset_rx_power =104, .length_rx_power =2, + .addr_soft_rs0 =0x51, .page_soft_rs0 =-1, .offset_soft_rs0 =110, .length_soft_rs0 =1, + .addr_soft_rs1 =0x51, .page_soft_rs1 =-1, .offset_soft_rs1 =118, .length_soft_rs0 =1, + .addr_temp =0x51, .page_temp =-1, .offset_temp =96, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =-1, .offset_trancomp =3, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =-1, .offset_trancomp_ext =36, .length_trancomp_ext =1, + .addr_tx_bias =0x51, .page_tx_bias =-1, .offset_tx_bias =100, .length_tx_bias =2, + .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1, + .addr_tx_eq =0x51, .page_tx_eq =-1, .offset_tx_eq =114, .length_tx_eq =1, + .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1, + .addr_tx_power =0x51, .page_tx_power =-1, .offset_tx_power =102, .length_tx_power =2, + .addr_vendor_name =0x50, .page_vendor_name =-1, .offset_vendor_name =20, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =-1, .offset_vendor_pn =40, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =-1, .offset_vendor_rev =56, .length_vendor_rev =4, + .addr_vendor_sn =0x50, .page_vendor_sn =-1, .offset_vendor_sn =68, .length_vendor_sn =16, + .addr_voltage =0x51, .page_voltage =-1, .offset_voltage =98, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =-1, .offset_wavelength =60, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =-1, .page_rx_em =-1, .offset_rx_em =-1, .length_rx_em =-1, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =-1, .page_tx_eq =-1, .offset_tx_eq =-1, .length_tx_eq =-1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp28 = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =0x50, .page_cdr =-1, .offset_cdr =98, .length_cdr =1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =0x50, .page_rx_am =3, .offset_rx_am =238, .length_rx_am =2, + .addr_rx_em =0x50, .page_rx_em =3, .offset_rx_em =236, .length_rx_em =2, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =0x50, .page_tx_eq =3, .offset_tx_eq =234, .length_tx_eq =2, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + + +/* ========== Utility Functions ========== + */ +static int +get_bit(uint8_t origin_byte, int bit_shift) { + return (int)((origin_byte >> bit_shift) & 0x1); +} + +static int +transform_word_to_int(uint8_t hight_byte, + uint8_t low_byte) { + return ((((int)hight_byte) << 8) + (int)low_byte); +} + +void +alarm_msg_2_user(struct transvr_obj_s *self, + char *emsg) { + + SWPS_ERR("%s on %s.\n", emsg, self->swp_name); +} + + +/* ========== Private functions ========== + */ +static int +_reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +_is_transvr_support_ctle(struct transvr_obj_s *self); + +static int +_transvr_init_handler(struct transvr_obj_s *self); + +int +_transvr_clean_handler(struct transvr_obj_s *self); + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self); + + +void +lock_transvr_obj(struct transvr_obj_s *self) { + + mutex_lock(&self->lock); + self->curr_page = VAL_TRANSVR_PAGE_FREE; +} + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} + + +static int +_check_by_mode(struct transvr_obj_s *self, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + char *caller_name){ + + int return_val = ERR_TRANSVR_UNEXCPT; + + switch (self->mode){ + case TRANSVR_MODE_POLLING: + switch (self->state){ + case STATE_TRANSVR_CONNECTED: + goto ok_check_by_mode_1; + case STATE_TRANSVR_NEW: + case STATE_TRANSVR_INIT: + return ERR_TRANSVR_UNINIT; + case STATE_TRANSVR_DISCONNECTED: + return ERR_TRANSVR_UNPLUGGED; + case STATE_TRANSVR_UNEXCEPTED: + return ERR_TRANSVR_ABNORMAL; + case STATE_TRANSVR_ISOLATED: + return ERR_TRNASVR_BE_ISOLATED; + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + + case TRANSVR_MODE_DIRECT: + return_val = self->fsm_4_direct(self, caller_name); + if (return_val < 0){ + return return_val; + } + goto ok_check_by_mode_1; + + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + +ok_check_by_mode_1: + return attr_update_func(self, 0); + +err_check_by_mode_1: + SWPS_INFO("_check_by_mode: mode:%d state:%d\n", self->mode, self->state); + return ERR_TRANSVR_UNEXCPT; +} + + +static void +_transvr_clean_retry(struct transvr_obj_s *self) { + self->retry = 0; +} + + +static int +_transvr_handle_retry(struct transvr_obj_s *self, int retry) { + /* Return: 0: keep retry + * -1: stop retry + */ + if (self->retry == 0) { + self->retry = retry; + } + self->retry -= 1; + if (self->retry <= 0) { + _transvr_clean_retry(self); + return -1; + } + return 0; +} + + +static int +_common_setup_page(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int show_e) { + /* return: + * 0 : OK + * -1 : EEPROM settings incorrect + * -2 : I2C R/W failure + * -3 : Undefined case + */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Check */ + if ((addr < 0) || (offset < 0) || (len < 0)) { + emsg = "EEPROM settings incorrect"; + retval = -1; + goto err_common_setup_page; + } + /* Case1: continue access */ + if ((self->i2c_client_p->addr == addr) && + (self->curr_page == page)) { + return 0; + } + self->i2c_client_p->addr = addr; + /* Case2: select lower page */ + if (page == -1) { + self->curr_page = page; + return 0; + } + /* Case3: select upper page */ + if (page >= 0) { + goto upper_common_setup_page; + } + /* Unexpected case */ + show_e = 1; + emsg = "Unexpected case"; + retval = -3; + goto err_common_setup_page; + +upper_common_setup_page: + if (i2c_smbus_write_byte_data(self->i2c_client_p, + VAL_TRANSVR_PAGE_SELECT_OFFSET, + page) < 0) { + emsg = "I2C R/W failure"; + retval = -2; + goto err_common_setup_page; + } + self->curr_page = page; + mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY); + return 0; + +err_common_setup_page: + if (show_e) { + SWPS_INFO("%s: %s", __func__, emsg); + SWPS_INFO("%s: :0x%02x :%d :%d :%d\n", + __func__, addr, page, offset, len); + } + return retval; +} + +/* +static int +_common_setup_password(struct transvr_obj_s *self, + int addr, + int page, + int offs, + uint8_t pwd[4], + int show_e) { + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, 4, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_setup_password; + } + for (i=0; i<4; i++) { + err = i2c_smbus_write_byte_data(self->i2c_client_p, + (offs + i), + pwd[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_setup_password; + } + } + return 0; + +err_common_setup_password: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} +*/ + +static int +_common_update_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + uint8_t *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_uint8_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_uint8_attr; + } + buf[i] = err; + } + return 0; + +err_common_update_uint8_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_int_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_int_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_int_attr; + } + buf[i] = (int)err; + } + return 0; + +err_common_update_int_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_INT_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_string_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + char buf[], + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_string_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_string_attr; + } + buf[i] = (char)err; + } + return 0; + +err_common_update_string_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = 'e'; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + uint8_t update, + uint8_t *buf, + char *caller, + int show_e){ + int len = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + if ((*buf) == update){ + return 0; + } + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + err = i2c_smbus_write_byte_data(self->i2c_client_p, + offset, + update); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + (*buf) = update; + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_array(struct transvr_obj_s *self, + int addr, + int page, + int offs, + int len, + uint8_t update[], + uint8_t buf[], + char *caller, + int show_e){ + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + for (i=0; ii2c_client_p, + (offs + i), + update[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + buf[i] = update[i]; + } + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, emsg, caller, err, i); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_attr_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_id, + self->eeprom_map_p->page_id, + self->eeprom_map_p->offset_id, + self->eeprom_map_p->length_id, + &(self->id), + "_common_update_attr_id", + show_err); +} + + +static int +_common_update_attr_extended_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_ext_id, + self->eeprom_map_p->page_ext_id, + self->eeprom_map_p->offset_ext_id, + self->eeprom_map_p->length_ext_id, + &(self->ext_id), + "_common_update_attr_extended_id", + show_err); +} + + +static int +_common_update_attr_connector(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_connector, + self->eeprom_map_p->page_connector, + self->eeprom_map_p->offset_connector, + self->eeprom_map_p->length_connector, + &(self->connector), + "_common_update_attr_connector", + show_err); +} + + +static int +_common_update_attr_transvr_comp(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp, + self->eeprom_map_p->page_trancomp, + self->eeprom_map_p->offset_trancomp, + self->eeprom_map_p->length_trancomp, + self->transvr_comp, + "_common_update_attr_transvr_comp", + show_err); +} + + +static int +_common_update_attr_transvr_comp_ext(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp_ext, + self->eeprom_map_p->page_trancomp_ext, + self->eeprom_map_p->offset_trancomp_ext, + self->eeprom_map_p->length_trancomp_ext, + &(self->transvr_comp_ext), + "_common_update_attr_transvr_comp_ext", + show_err); +} + + +static int +_common_update_attr_vendor_name(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_name, + self->eeprom_map_p->page_vendor_name, + self->eeprom_map_p->offset_vendor_name, + self->eeprom_map_p->length_vendor_name, + self->vendor_name, + "_common_update_attr_vendor_name", + show_err); +} + + +static int +_common_update_attr_vendor_pn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_pn, + self->eeprom_map_p->page_vendor_pn, + self->eeprom_map_p->offset_vendor_pn, + self->eeprom_map_p->length_vendor_pn, + self->vendor_pn, + "_common_update_attr_vendor_pn", + show_err); +} + + +static int +_common_update_attr_vendor_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_rev, + self->eeprom_map_p->page_vendor_rev, + self->eeprom_map_p->offset_vendor_rev, + self->eeprom_map_p->length_vendor_rev, + self->vendor_rev, + "_common_update_attr_vendor_rev", + show_err); +} + + +static int +_common_update_attr_vendor_sn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_sn, + self->eeprom_map_p->page_vendor_sn, + self->eeprom_map_p->offset_vendor_sn, + self->eeprom_map_p->length_vendor_sn, + self->vendor_sn, + "_common_update_attr_vendor_sn", + show_err); +} + + +static int +_common_update_attr_br(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_br, + self->eeprom_map_p->page_br, + self->eeprom_map_p->offset_br, + self->eeprom_map_p->length_br, + &(self->br), + "_common_update_attr_br", + show_err); +} + + +static int +_common_update_attr_len_smf(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_smf, + self->eeprom_map_p->page_len_smf, + self->eeprom_map_p->offset_len_smf, + self->eeprom_map_p->length_len_smf, + &(self->len_smf), + "_common_update_attr_len_smf", + show_err); +} + + +static int +_common_update_attr_len_om1(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om1, + self->eeprom_map_p->page_len_om1, + self->eeprom_map_p->offset_len_om1, + self->eeprom_map_p->length_len_om1, + &(self->len_om1), + "_common_update_attr_len_om1", + show_err); +} + +static int +_common_update_attr_len_om2(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om2, + self->eeprom_map_p->page_len_om2, + self->eeprom_map_p->offset_len_om2, + self->eeprom_map_p->length_len_om2, + &(self->len_om2), + "_common_update_attr_len_om2", + show_err); +} + +static int +_common_update_attr_len_om3(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om3, + self->eeprom_map_p->page_len_om3, + self->eeprom_map_p->offset_len_om3, + self->eeprom_map_p->length_len_om3, + &(self->len_om3), + "_common_update_attr_len_om3", + show_err); +} + + +static int +_common_update_attr_len_om4(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om4, + self->eeprom_map_p->page_len_om4, + self->eeprom_map_p->offset_len_om4, + self->eeprom_map_p->length_len_om4, + &(self->len_om4), + "_common_update_attr_len_om4", + show_err); +} + + +static int +_common_update_attr_option(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_option, + self->eeprom_map_p->page_option, + self->eeprom_map_p->offset_option, + self->eeprom_map_p->length_option, + self->option, + "_common_update_attr_option", + show_err); +} + + +static int +_common_update_attr_comp_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_comp_rev, + self->eeprom_map_p->page_comp_rev, + self->eeprom_map_p->offset_comp_rev, + self->eeprom_map_p->length_comp_rev, + &(self->comp_rev), + "_common_update_attr_comp_rev", + show_err); +} + + +static int +_common_update_attr_diag_type(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_diag_type, + self->eeprom_map_p->page_diag_type, + self->eeprom_map_p->offset_diag_type, + self->eeprom_map_p->length_diag_type, + &(self->diag_type), + "_common_update_attr_diag_type", + show_err); +} + + +static int +_common_update_attr_wavelength(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_wavelength, + self->eeprom_map_p->page_wavelength, + self->eeprom_map_p->offset_wavelength, + self->eeprom_map_p->length_wavelength, + self->wavelength, + "_common_update_attr_wavelength", + show_err); +} + + +int +_common_get_option_value(struct transvr_obj_s *self, + int offset, + int bit_shift) { + /* SFP: + * - option[0] = A0h / 64 + * - option[1] = A0h / 65 + * QSFP: + * - option[0] = 00h / 193 + * - option[1] = 00h / 194 + * - option[2] = 00h / 195 + */ + return (self->option[offset] & (1 << bit_shift)); +} + + +static int +_sfp_update_attr_len_sm(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_sm, + self->eeprom_map_p->page_len_sm, + self->eeprom_map_p->offset_len_sm, + self->eeprom_map_p->length_len_sm, + &(self->len_sm), + "_common_update_attr_len_sm", + show_err); +} + + +static int +_sfp_update_attr_rate_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_rate_id, + self->eeprom_map_p->page_rate_id, + self->eeprom_map_p->offset_rate_id, + self->eeprom_map_p->length_rate_id, + &(self->rate_id), + "_sfp_update_attr_rate_id", + show_err); +} + + +static int +_sfp_update_attr_soft_rs0(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + self->eeprom_map_p->length_soft_rs0, + &(self->soft_rs0), + "_sfp_update_attr_soft_rs0", + show_err); +} + + +static int +_sfp_update_attr_soft_rs1(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + self->eeprom_map_p->length_soft_rs1, + &(self->soft_rs1), + "_sfp_update_attr_soft_rs1", + show_err); +} + + +int +_sfp_is_diag_support(struct transvr_obj_s *self){ + + uint8_t bit_mask = 0xC0; /* 1100 0000 */ + uint8_t en_val = 0x40; /* 0100 0000 */ + uint8_t checkval = (self->diag_type & bit_mask); + + if (checkval == en_val) { + return 1; + } + return 0; +} + + +static int +_sfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_sfp_update_attr_curr_temp", + show_err); +} + + +static int +_sfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_sfp_update_attr_curr_voltage", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_sfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_sfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_sfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_sfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_sfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_sfp_update_attr_rx_em", + show_err); +} + + +static int +_sfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_sfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_cdr(struct transvr_obj_s *self, + int show_err){ + if (self->type != TRANSVR_TYPE_QSFP_28){ + self->cdr = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + self->eeprom_map_p->length_cdr, + &(self->cdr), + "_common_update_attr_cdr", + show_err); +} + + +static int +_qsfg_update_attr_extbr(struct transvr_obj_s *self, + int show_err) { + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_extbr, + self->eeprom_map_p->page_extbr, + self->eeprom_map_p->offset_extbr, + self->eeprom_map_p->length_extbr, + &(self->extbr), + "_common_update_attr_extbr", + show_err); +} + + +static int +_qsfp_is_diag_support(struct transvr_obj_s *self, + int diag_type) { + /* Input Parm: diag_type + * => 1 : temperature + * => 2 : voltage + * => 3 : tx relate + * => 4 : rx relate + */ + uint8_t mask_b2 = 0x04; /* 0000 0100 */ + uint8_t mask_b3 = 0x08; /* 0000 1000 */ + + switch (diag_type) { + case 1: /* temperature */ + case 2: /* voltage */ + /* Direct access target, because of spec not defined */ + return 1; + case 3: + case 4: + /* [Note] + * Due to lot of transceiver vendor defined it not rigorously and + * consider of general support, we seem it as supported if there + * are bit-2 OR bit-3 defined by transceiver vendor. + */ + if ( ((self->diag_type & mask_b2) == mask_b2 ) || + ((self->diag_type & mask_b3) == mask_b3 ) ){ + return 1; + } + return 0; + default: + SWPS_INFO("%s: undefined diag_type:%d\n", + __func__, diag_type); + break; + } + return 0; +} + + +int +_qsfp_is_implement_tx_disable(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-4 + */ + int byte = 2; + int bit = 4; + return _common_get_option_value(self, byte, bit); +} + + +int +_qsfp_is_implement_tx_fault(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-3 + */ + int byte = 2; + int bit = 3; + return _common_get_option_value(self, byte, bit); +} + + +static int +_qsfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + int diag_type = 1; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_qsfp_update_attr_curr_temp", + show_err); +} + + +static int +_qsfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + int diag_type = 2; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_qsfp_update_attr_curr_voltage", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_qsfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_qsfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_qsfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 4; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_qsfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_qsfp_update_attr_soft_rx_los(struct transvr_obj_s *self, + int show_err){ + + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_los, + self->eeprom_map_p->page_rx_los, + self->eeprom_map_p->offset_rx_los, + self->eeprom_map_p->length_rx_los, + &(self->rx_los), + "_qsfp_update_attr_soft_rx_los", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_disable(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_disable(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_update_attr_soft_tx_disable", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_fault(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_fault(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_fault, + self->eeprom_map_p->page_tx_fault, + self->eeprom_map_p->offset_tx_fault, + self->eeprom_map_p->length_tx_fault, + &(self->tx_fault), + "_qsfp_update_attr_soft_tx_fault", + show_err); +} + + +static int +_qsfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_qsfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_rx_am(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + self->rx_am, + "_qsfp_update_attr_rx_am", + show_err); +} + + +static int +_qsfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_qsfp_update_attr_rx_em", + show_err); +} + + +int +_common_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = "err"; + + if (_common_update_attr_id(self, show_err) < 0) { + err_str = "_common_update_attr_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_extended_id(self, show_err) < 0) { + err_str = "_common_update_attr_extended_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_connector(self, show_err) < 0) { + err_str = "_common_update_attr_connector"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp_ext(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp_ext"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_name(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_name"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_pn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_pn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_rev(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_sn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_sn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_br(self, show_err) < 0) { + err_str = "_common_update_attr_br"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_smf(self, show_err) < 0) { + err_str = "_common_update_attr_len_smf"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om1(self, show_err) < 0) { + err_str = "_common_update_attr_len_om1"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om2(self, show_err) < 0) { + err_str = "_common_update_attr_len_om2"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om3(self, show_err) < 0) { + err_str = "_common_update_attr_len_om3"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om4(self, show_err) < 0) { + err_str = "_common_update_attr_len_om4"; + goto err_common_update_attr_all; + } + if (_common_update_attr_option(self, show_err) < 0) { + err_str = "_common_update_attr_option"; + goto err_common_update_attr_all; + } + if (_common_update_attr_comp_rev(self, show_err) < 0) { + err_str = "_common_update_attr_comp_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_diag_type(self, show_err) < 0) { + err_str = "_common_update_attr_diag_type"; + goto err_common_update_attr_all; + } + if (_common_update_attr_wavelength(self, show_err) < 0) { + err_str = "_common_update_attr_wavelength"; + goto err_common_update_attr_all; + } + return 0; + +err_common_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_sfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_len_sm(self, show_err) < 0) { + err_str = "_sfp_update_attr_len_sm"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_rate_id(self, show_err) < 0) { + err_str = "_sfp_update_attr_rate_id"; + goto err_sfp_update_attr_all; + } + if ((self->rate_id) > 0) { + if (_sfp_update_attr_soft_rs0(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs0"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_soft_rs1(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs1"; + goto err_sfp_update_attr_all; + } + } + return 0; + +err_sfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_qsfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_qsfp_update_attr_all; + } + if (_qsfg_update_attr_extbr(self, show_err) < 0) { + err_str = "_qsfg_update_attr_extbr"; + goto err_qsfp_update_attr_all; + } + if (self->type == TRANSVR_TYPE_QSFP_28) { + if (_qsfp_update_attr_cdr(self, 1) < 0) { + err_str = "_qsfp_update_attr_cdr"; + goto err_qsfp_update_attr_all; + } + } + return 0; + +err_qsfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +/* ========== Object functions for common type ========== + */ +int +_common_count_temp(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + int sign = 0; + int high = 0; + int low = 0; + int lmax = 8; + + /* Count high */ + sign = get_bit(high_byte,7); + SWP_BIT_CLEAR(high_byte, 7); + high = (int)high_byte; + if (sign == 1) { + high = 0 - high; + } + /* Count low */ + low = (get_bit(low_byte, 7) * 500); + low += (get_bit(low_byte, 6) * 250); + low += (get_bit(low_byte, 5) * 125); + low += (get_bit(low_byte, 4) * 62); + low = (low / 100); + /* Integrate High and Low */ + return snprintf(buf_p, lmax, "%d.%d\n", high, low); +} + + +int +_common_count_voltage(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note]: + * Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts. Practical + * considerations to be defined by transceiver manufacturer will + * tend to limit the actual bounds of the supply voltage measurement. + * Accuracy is vendor specific but must be better than 3% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. Note that in some transceivers, transmitter supply + * voltage and receiver supply voltage are isolated. In that case, + * only one supply is monitored. Refer to the device specification + * for more detail. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 100 uV (1mV=1000uV) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 Volt */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_tx_bias(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 2 uA (1mA=1000uA) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total*2) / 1000); + val_f = (((total*2) - (val_i*1000)) / 100); + /* Return Unit: 1 mA */ + return snprintf(buf_p, lmax, "%d.%01d\n", val_i, val_f); +} + + +int +_common_count_tx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_rx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_wavelength(struct transvr_obj_s *self, + uint8_t high_byte, + uint8_t low_byte) { + /* [Note] + * SFP : uint 1 um. + * QSFP: unit 0.05 um. + */ + int total = 0; + + total = transform_word_to_int(high_byte, low_byte); + switch (self->type) { + case TRANSVR_TYPE_SFP: + return total; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + return (total/20); + + default: + break; + } + return ERR_TRANSVR_UNDEFINED; +} + + +int +common_get_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_id, + "common_get_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->id; +} + + +int +common_get_ext_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "common_get_ext_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->ext_id; +} + + +int +common_get_connector(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_connector, + "common_get_connector"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->connector; +} + + +int +common_get_vendor_name(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_name, + "common_get_vendor_name"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); +} + + +int +common_get_vendor_pn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_pn, + "common_get_vendor_pn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); +} + + +int +common_get_vendor_rev(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_rev, + "common_get_vendor_rev"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); +} + + +int +common_get_vendor_sn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_sn, + "common_get_vendor_sn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); +} + + +int +common_get_br(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return (int)self->br; + } + err = _check_by_mode(self, + &_common_update_attr_br, + "common_get_br"); + if (err < 0){ + return err; + } + /* Transform to INT to show error case */ + return (int)self->br; +} + + +int +common_get_len_smf(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_smf; + } + err = _check_by_mode(self, + &_common_update_attr_len_smf, + "common_get_len_smf"); + if (err < 0){ + return err; + } + return self->len_smf; +} + + +int +common_get_len_om1(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om1; + } + err = _check_by_mode(self, + &_common_update_attr_len_om1, + "common_get_len_om1"); + if (err < 0){ + return err; + } + return self->len_om1; +} + + +int +common_get_len_om2(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om2; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om2, + "common_get_len_om2"); + if (err < 0){ + return err; + } + return self->len_om2; +} + + +int +common_get_len_om3(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om3; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om3, + "common_get_len_om3"); + if (err < 0){ + return err; + } + return self->len_om3; +} + + +int +common_get_len_om4(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om4; + } + err = _check_by_mode(self, + &_common_update_attr_len_om4, + "common_get_len_om4"); + if (err < 0){ + return err; + } + return self->len_om4; +} + + +int +common_get_comp_extended(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp_ext, + "common_get_comp_extended"); + if (err_code < 0){ + return err_code; + } + return self->transvr_comp_ext; +} + + +int +common_get_comp_rev(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_comp_rev, + "common_get_comp_rev"); + if (err_code < 0){ + return err_code; + } + return self->comp_rev; +} + + +int +common_get_info(struct transvr_obj_s *self){ + + if (self->state != STATE_TRANSVR_CONNECTED) { + return self->state; + } + return self->info; +} + + +int +_common_get_if_lane(struct transvr_obj_s *self, + char *result){ + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_M_STR); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + memset(tmp_str, 0, LEN_TRANSVR_M_STR); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_M_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_M_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_M_STR); + } + if (i == 0) { + return EVENT_TRANSVR_TASK_FAIL; + } + return 0; +} + + +int +common_get_if_lane(struct transvr_obj_s *self, + char *buf_p){ + + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + if (self->ioexp_obj_p->state != STATE_IOEXP_NORMAL) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n", ERR_TRANSVR_ABNORMAL); + } + if (_common_get_if_lane(self, tmp_str) < 0) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n" ,ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%s\n" ,tmp_str); +} + + +int +sfp_get_len_sm(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_len_sm, + "sfp_get_len_sm"); + if (err_code < 0){ + return err_code; + } + return self->len_sm; +} + + +int +sfp_get_rate_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_rate_id, + "sfp_get_rate_id"); + if (err_code < 0){ + return err_code; + } + return self->rate_id; +} + + +int +sfp_get_soft_rs0(struct transvr_obj_s *self){ + /* Note: + * SFP Soft Rate_Select Select [aka. "RS(0)"] address + * A2h, offset: 110, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs0, + "sfp_get_soft_rs0"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs0 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_soft_rs1(struct transvr_obj_s *self){ + /* Note: + * SFP Soft RS(1) Select address + * A2h, offset: 118, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs1, + "sfp_get_soft_rs1"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs1 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_temp, + "sfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +sfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_voltage, + "sfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +sfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_bias, + "sfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _common_count_tx_bias(self->curr_tx_bias[0], + self->curr_tx_bias[1], + buf_p); +} + + +int +sfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_power, + "sfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_tx_power(self->curr_tx_power[0], + self->curr_tx_power[1], + buf_p); +} + + +int +sfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_rx_power, + "sfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_rx_power(self->curr_rx_power[0], + self->curr_rx_power[0], + buf_p); +} + + +int +sfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->rx_em[0]); +} + + +int +sfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->tx_eq[0]); +} + + +int +_sfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: A0h / 36 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +__sfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* SFP Specification Compliance: A0h / 3-10 + * transvr_comp[0-7] = 3 - 10 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_get_comp_10g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[0] = address A0h / 3 + * + * 3 7: 10G Base-ER + * 3 6: 10GBASE-LRM + * 3 5: 10GBASE-LR + * 3 4: 10GBASE-SR + */ + int bitmask = 0xf0; /* 11110000 */ + return (__sfp_get_comp_attr(self, 0) & bitmask); +} + + +int +_sfp_get_comp_1g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[3] = address A0h / 6 + * + * 6 7: BASE-PX *3 + * 6 6: BASE-BX10 *3 + * 6 5: 100BASE-FX + * 6 4: 100BASE-LX/LX10 + * 6 3: 1000BASE-T + * 6 2: 1000BASE-CX + * 6 1: 1000BASE-LX *3 + * 6 0: 1000BASE-SX + */ + return __sfp_get_comp_attr(self, 3); +} + + +int +_sfp_get_cable_tech(struct transvr_obj_s *self) { + /* transvr_comp[5] = address A0h / 8 + * + * 8 3: Active Cable *8 + * 8 2: Passive Cable *8 + */ + int bitmask = 0x0c; /* 00001100 */ + return (__sfp_get_comp_attr(self, 5) & bitmask); +} + + +int +sfp_get_comp_eth_1(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_1"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_1g_eth_comp(self); +} + + +int +sfp_get_comp_eth_10(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_10"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_10g_eth_comp(self); +} + + +int +_sfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: A0h / 2 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Note] Optical and Cable Variants Specification Compliance (SFF-8472) + * [Addr] A0h, Bytes 60-61 + * [Note] For optical variants, as defined by having zero's in A0h Byte 8 + * bits 2 and 3, Bytes 60 and 61 denote nominal transmitter output + * wavelength at room temperature. 16 bit value with byte 60 as high + * order byte and byte 61 as low order byte. The laser wavelength is + * equal to the 16 bit integer value in nm. This field allows the user + * to read the laser wavelength directly, so it is not necessary to + * infer it from the Transceiver Codes A0h Bytes 3 to 10 (see Table + * 5-3). This also allows specification of wavelengths not covered + * in the Transceiver Codes, such as those used in coarse WDM systems. + * + * For passive and active cable variants, a value of 00h for both A0h + * Byte 60 and Byte 61 denotes laser wavelength or cable specification + * compliance is unspecified. + */ + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +int +sfp_get_1g_rj45_extphy_offset(struct transvr_obj_s *self, char *buf) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%02x\n", self->extphy_offset); +} + + +int +sfp_get_1g_rj45_extphy_reg(struct transvr_obj_s *self, char *buf) { + + int i = 0; + int ret = 0; + int retry = 3; + int delay = 200; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; ii2c_client_p, self->extphy_offset); + if (ret >=0) { + goto ok_sfp_get_1g_rj45_extphy_reg; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; + +ok_sfp_get_1g_rj45_extphy_reg: + ret = ((ret & 0x00ff) << 8) | ((ret & 0xff00) >> 8); + return snprintf(buf, LEN_TRANSVR_S_STR, "0x%04x\n", ret); +} + + +int +__qsfp_get_power_cls(struct transvr_obj_s *self, + int direct_access){ + + int err_code; + uint8_t detect_val; + + /* Detect and Update power class attribute */ + if (direct_access){ + err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_power_cls"); + } else { + err_code = self->ext_id; + } + if (err_code <0){ + return err_code; + } + if (err_code == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data */ + detect_val = self->ext_id; + SWP_BIT_CLEAR(detect_val, 2); /* Bit2: CDR RX present */ + SWP_BIT_CLEAR(detect_val, 3); /* Bit3: CDR TX present */ + SWP_BIT_CLEAR(detect_val, 4); /* Bit4: CLEI present */ + SWP_BIT_CLEAR(detect_val, 5); /* Bit5: reserved */ + /* Identify power class */ + switch (detect_val) { + case 0: /* Class_1: 00000000 */ + return 1; + case 64: /* Class_2: 01000000 */ + return 2; + case 128: /* Class_3: 10000000 */ + return 3; + case 192: /* Class_4: 11000000 */ + return 4; + case 1: /* Class_5: 00000001 */ + case 193: /* Class_5: 11000001 */ + return 5; + case 2: /* Class_6: 00000010 */ + case 194: /* Class_6: 11000010 */ + return 6; + case 3: /* Class_7: 00000011 */ + case 195: /* Class_7: 11000011 */ + return 7; + default: + break; + } + SWPS_INFO("%s: Detect undefined power class:%d\n", __func__, detect_val); + return ERR_TRANSVR_UNDEFINED; +} + + +int +qsfp_get_power_cls(struct transvr_obj_s *self) { + return __qsfp_get_power_cls(self, 1); +} + + +int +__qsfp_get_cdr_present(struct transvr_obj_s *self, + int direct_access){ + + int retval; + int BIT_SHIFT = 2; + int BIT_MASK = 0x3; + + /* Detect and Update power class attribute */ + if (direct_access) { + retval = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_cdr_present"); + if (retval < 0){ + return retval; + } + } + retval = self->ext_id; + if (retval == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data and return */ + return (int)(retval >> BIT_SHIFT & BIT_MASK); +} + + +int +qsfp_get_cdr_present(struct transvr_obj_s *self) { + return __qsfp_get_cdr_present(self, 1); +} + + +int +qsfp_get_cdr(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + "qsfp_get_cdr"); + if (err_code <0){ + return err_code; + } + + return self->cdr; +} + + +int +__qsfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* QSFP Specification Compliance: 00h / 131-138 + * transvr_comp[0-7] = 131 - 138 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_get_comp_10_40_100_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[0] = address 00h / 131 + * + * 131 7: Extended: See section 6.3.23. The Extended Specification Compliance + * Codes are maintained in the Transceiver Management section of SFF- + * 8024. + * 131 6: 10GBASE-LRM + * 131 5: 10GBASE-LR + * 131 4: 10GBASE-SR + * 131 3: 40GBASE-CR4 + * 131 2: 40GBASE-SR4 + * 131 1: 40GBASE-LR4 + * 131 0: 40G Active Cable (XLPPI) + */ + return __qsfp_get_comp_attr(self, 0); +} + + +int +_qsfp_get_comp_sonet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 132 7-3: Reserved + * 132 2: OC 48, long reach + * 132 1: OC 48, intermediate reach + * 132 0: OC 48 short reach + */ + return __qsfp_get_comp_attr(self, 1); +} + + +int +_qsfp_get_comp_sas_sata(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 133 7: SAS 24.0 Gb/s + * 133 6: SAS 12.0 Gb/s + * 133 5: SAS 6.0 Gb/s + * 133 4: SAS 3.0 Gb/s + * 133 3-0: Reserved + */ + return __qsfp_get_comp_attr(self, 2); +} + + +int +_qsfp_get_comp_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 134 7-4: Reserved + * 134 3: 1000BASE-T + * 134 2: 1000BASE-CX + * 134 1: 1000BASE-LX + * 134 0: 1000BASE-SX + */ + return __qsfp_get_comp_attr(self, 3); +} + + +int +_qsfp_get_comp_fc_link_length(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 7: Very long distance (V) + * 135 6: Short distance (S) + * 135 5: Intermediate distance (I) + * 135 4: Long distance (L) + * 135 3: Medium (M) + */ + int mask = 0xFC; /* 11111100 */ + return (__qsfp_get_comp_attr(self, 4) & mask); +} + + +int +_qsfp_get_comp_fc_trans_tech(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 2: Reserved + * 135 1: Longwave laser (LC) + * 135 0: Electrical inter-enclosure (EL) + * + * 136 7: Electrical intra-enclosure + * 136 6: Shortwave laser w/o OFC (SN) + * 136 5: Shortwave laser w OFC (SL) + * 136 4: Longwave Laser (LL) + * 136 3-0: Reserved + * + * return value = [bit 8-15:addr 135][bit 0-7:addr 136] + */ + int mask_135 = 7; /* 00000111 */ + int val_135 = (__qsfp_get_comp_attr(self, 4) & mask_135); + int val_136 = __qsfp_get_comp_attr(self, 5); + return ((val_135 << 7) + val_136); +} + + +int +_qsfp_get_comp_fc_trans_media(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 137 7: Twin Axial Pair (TW) + * 137 6: Shielded Twisted Pair (TP) + * 137 5: Miniature Coax (MI) + * 137 4: Video Coax (TV) + * 137 3: Multi-mode 62.5 m (M6) + * 137 2: Multi-mode 50 m (M5) + * 137 1: Multi-mode 50 um (OM3) + * 137 0: Single Mode (SM) + */ + return __qsfp_get_comp_attr(self, 6); +} + + +int +_qsfp_get_comp_fc_speed(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 138 7: 1200 MBps (per channel) + * 138 6: 800 MBps + * 138 5: 1600 MBps (per channel) + * 138 4: 400 MBps + * 138 3: 3200 MBps (per channel) + * 138 2: 200 MBps + * 138 1: Extended: See section 6.3.23. The Extended Specification + * Compliance Codes are maintained in the Transceiver Management + * section of SFF-8024. + * 138 0: 100 MBps + */ + return __qsfp_get_comp_attr(self, 7); +} + + +int +_qsfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: 00h / 192 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_comp_eth(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_eth"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_ethernet(self); +} + + +int +qsfp_get_comp_10_40(struct transvr_obj_s *self) { + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_10_40"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_10_40_100_ethernet(self); +} + + +int +_qsfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: 00h / 130 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_temp, + "qsfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +qsfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_voltage, + "qsfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +qsfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->tx_eq[0], self->tx_eq[1]); +} + + +int +qsfp_get_transvr_rx_am(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_get_transvr_rx_am"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_am[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_am[0], self->rx_am[1]); +} + + +int +qsfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_em[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_em[0], self->rx_em[1]); +} + + +int +_qsfp_get_channel_diag(uint8_t *data_array, + int (*count_func)(uint8_t high_byte, uint8_t low_byte, char *buf_p), + char *ch_name, + char *result_p) { + int i, high, low; + int len_max = 128; + char ch_buf[4][16] = { DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL }; + + for (i=0; i<4; i++) { + high = (i*2); + low = ((i*2) + 1); + count_func(data_array[high], data_array[low], ch_buf[i]); + } + return snprintf(result_p, len_max, + "%s-%d:%s%s-%d:%s%s-%d:%s%s-%d:%s", + ch_name, 1, ch_buf[0], + ch_name, 2, ch_buf[1], + ch_name, 3, ch_buf[2], + ch_name, 4, ch_buf[3]); +} + + +int +qsfp_get_soft_rx_los(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_rx_los, + "qsfp_get_soft_rx_los"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->rx_los & mask)); +} + + +int +qsfp_get_soft_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_get_soft_tx_disable"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_disable & mask)); +} + + +int +qsfp_get_soft_tx_fault(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_fault, + "qsfp_get_soft_tx_fault"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_fault & mask)); +} + + +int +qsfp_get_auto_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + if (self->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "%d\n", ERR_TRANSVR_FUNC_DISABLE); + } + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "0x%02x\n", self->auto_tx_disable); +} + + +int +qsfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_bias, + "qsfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _qsfp_get_channel_diag(self->curr_tx_bias, + _common_count_tx_bias, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_power, + "qsfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_tx_power, + _common_count_tx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "RX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_rx_power, + "qsfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_rx_power, + _common_count_rx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Desc] Wavelength or Copper Cable Attenuation (SFF-8636) + * [Addr] 00h 186-187 + * [Note] + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is + * a 16-bit hex value with Byte 186 as high order byte and Byte 187 as + * low order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. + * If the free side device is identified as copper cable these registers will + * be used to define the cable attenuation. An indication of 0 dB attenuation + * refers to the case where the attenuation is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +/* Public Function for Setup Features + */ +static int +__sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + uint8_t update_val = (*attr_p); + + switch (input_val) { + case 0: + SWP_BIT_CLEAR(update_val, bit_shift); + break; + case 1: + SWP_BIT_SET(update_val, bit_shift); + break; + default: + retval = ERR_TRANSVR_UNEXCPT; + err_code = ERR_TRANSVR_UNEXCPT; + err_msg = "Exception occurs"; + goto err_private_sfp_set_soft_rs_1; + } + err_code = _common_set_uint8_attr(self, + address, + page, + offset, + update_val, + attr_p, + caller, + show_err); + if (err_code < 0) { + retval = err_code; + err_msg = "Write data via i2c fail!"; + goto err_private_sfp_set_soft_rs_1; + } + (*attr_p) = update_val; + return 0; + +err_private_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +static int +_sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + /* Check input value */ + if ((input_val != 0) && (input_val != 1)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + switch (err_code) { + case 0: + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "Not support this feature"; + break; + case ERR_TRANSVR_UNINIT: + retval = ERR_TRANSVR_UNINIT; + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + retval = ERR_TRANSVR_UNPLUGGED; + err_msg = "Transceiver unplugged!"; + break; + default: + retval = err_code; + err_msg = "Check Rate_ID fail!"; + break; + } + goto err_common_sfp_set_soft_rs_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + attr_update_func, + caller); + if ( (err_code < 0) || + ((*attr_p) == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Generate and update value */ + return __sfp_set_soft_rs(self, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + +err_common_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +sfp_set_soft_rs0(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(0)"] address + * A2h, offset: 110, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + bit_shift, + &_sfp_update_attr_soft_rs0, + &(self->soft_rs0), + "sfp_set_soft_rs0", + show_err); +} + + +int +sfp_set_soft_rs1(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(1)"] address + * A2h, offset: 118, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + bit_shift, + &_sfp_update_attr_soft_rs1, + &(self->soft_rs1), + "sfp_set_soft_rs1", + show_err); +} + + +int +__sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_tx_eq; + } + setv = (uint8_t)input; + if (self->tx_eq[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + setv, + &(self->tx_eq[0]), + "_sfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_tx_eq; + } + return 0; + +err_sfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; itx_eq[0]; + if (_sfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if (self->tx_eq[0] == tmp){ + return 0; + } + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +sfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_tx_eq(self, input, 1); +} + + +int +__sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_rx_em; + } + setv = (uint8_t)input; + if (self->rx_em[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + setv, + &(self->rx_em[0]), + "_sfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_rx_em; + } + return 0; + +err_sfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; irx_em[0]; + if (_sfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if (self->rx_em[0] == tmp){ + return 0; + } + } + return -1; +} + + +int +sfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_rx_em(self, input, 1); +} + + +int +sfp_set_1g_rj45_extphy_offset(struct transvr_obj_s *self, + int input) { + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xff)) { + return ERR_TRANSVR_BADINPUT; + } + self->extphy_offset = (uint8_t)input; + return 0; +} + + +int +sfp_set_1g_rj45_extphy_reg(struct transvr_obj_s *self, + int input) { + + int i = 0; + int retry = 3; + int delay = 200; + uint16_t tmp = 0; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return ERR_TRANSVR_UNPLUGGED; + } + if ((self->info != TRANSVR_CLASS_BASE_T_1000) && + (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){ + return ERR_TRANSVR_NOTSUPPORT; + } + if ((input < 0) || (input > 0xffff)) { + return ERR_TRANSVR_BADINPUT; + } + tmp = ((input & 0x00ff) << 8) | ((input & 0xff00) >> 8); + if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56, + -1, self->extphy_offset, 1, 0) < 0) { + return -EIO; + } + for (i=0; i<=retry; i++) { + if (i2c_smbus_write_word_data(self->i2c_client_p, + self->extphy_offset, + tmp) >= 0) { + return 0; + } + msleep(delay); + } + SWPS_INFO("%s: retry:%d fail :%s :0x%02x\n", + __func__, retry, self->swp_name, self->extphy_offset); + return -EIO; +} + + +static int +__qsfp_set_cdr(struct transvr_obj_s *self, + int input_val, + int show_err) { + + uint8_t update_val; + int CDR_FEATURE_SUPPORTED = 0x3; + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_name = "__qsfp_set_cdr"; + + /* Check input value */ + if ((input_val < 0) || (input_val > 0xff)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_qsfp_set_cdr_1; + } + update_val = (uint8_t)input_val; + /* Check CDR supported by transceiver */ + err_code = qsfp_get_cdr_present(self); + if (err_code < 0) { + retval = err_code; + switch (err_code) { + case ERR_TRANSVR_UNINIT: + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + err_msg = "Transceiver unplugged!"; + break; + default: + err_msg = "Check CDR present fail!"; + break; + } + goto err_qsfp_set_cdr_1; + } + if (err_code != CDR_FEATURE_SUPPORTED) { + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "This transceiver not support CDR!"; + goto err_qsfp_set_cdr_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + func_name); + if ( (err_code < 0) || + (self->cdr == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_qsfp_set_cdr_1; + } + /* Write input value to transceiver */ + return _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + update_val, + &(self->cdr), + func_name, + show_err); + +err_qsfp_set_cdr_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +qsfp_set_cdr(struct transvr_obj_s *self, + int input_val) { + return __qsfp_set_cdr(self, input_val, 1); +} + + +int +qsfp_set_soft_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int show_err = 1; + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + int update_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_soft_tx_disable"); + if (retval < 0) { + snprintf(err_msg, 63, "Not ready. err:%d", retval); + goto err_qsfp_set_soft_tx_disable; + } + if ((input_val > in_max) || + (input_val < in_min) ){ + retval = ERR_TRANSVR_BADINPUT; + snprintf(err_msg, 63, "Input value:%d incorrect!", input_val); + goto err_qsfp_set_soft_tx_disable; + } + if ((self->tx_disable & 0x0f) == input_val) { + return 0; + } + update_val = ((self->tx_disable & 0xf0) & input_val); + retval = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + input_val, + &(self->tx_disable), + "qsfp_set_tx_disable", + show_err); + if (retval < 0) { + snprintf(err_msg, 63, "_common_set_uint8_attr:%d fail!", retval); + goto err_qsfp_set_soft_tx_disable; + } + return 0; + +err_qsfp_set_soft_tx_disable: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return retval; +} + + +int +_qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + uint8_t update) { + + uint8_t tx_enable = 0x0; + int show_e = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Handle timing issues */ + if (update != tx_enable) { + /* Note: + * Because there are some txvr has timing issues, + * therefore we need to execute reset cycle first. + * (enable -> other settings) + */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + tx_enable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set reset value fail"; + goto err_qsfp_set_auto_tx_disable; + } + mdelay(10); + } + /* Setup target value */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->auto_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set target value fail"; + goto err_qsfp_set_auto_tx_disable; + } + /* Check and update */ + err = _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C get value fail"; + goto err_qsfp_set_auto_tx_disable; + } + if (self->tx_disable != update) { + emsg = "data not become effective"; + goto err_qsfp_set_auto_tx_disable; + } + return 0; + +err_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s\n", + __func__, emsg, self->swp_name); + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Update settings*/ + if (input_val == VAL_TRANSVR_FUNCTION_DISABLE) { + emsg = "User disable auto tx_disable"; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + goto out_qsfp_set_auto_tx_disable; + } + if ((input_val > in_max) || (input_val < in_min) ){ + SWPS_INFO("%s: Input value:%d incorrect! :%s\n", + __func__, input_val, self->swp_name); + return ERR_TRANSVR_BADINPUT; + } + self->auto_tx_disable = input_val; + /* Check current soft tx_disable */ + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_auto_tx_disable"); + switch (retval) { + case 0: + break; + case ERR_TRANSVR_UNPLUGGED: + emsg = "Doesn't need to update"; + goto out_qsfp_set_auto_tx_disable; + default: + SWPS_INFO("%s: setup fail :%d :%s\n", + __func__, retval, self->swp_name); + return retval; + } + return _qsfp_set_auto_tx_disable(self, input_val); + +out_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s :%d\n :%d", + __func__, emsg, self->swp_name, input_val, retval); + return 0; +} + + +int +__qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_tx_eq; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->tx_eq[0] == setv[0]) && + (self->tx_eq[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + setv, + self->tx_eq, + "_qsfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_tx_eq; + } + return 0; + +err_qsfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; itx_eq[0]; + tmp[1] = self->tx_eq[1]; + if (_qsfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if ((self->tx_eq[0] == tmp[0]) && + (self->tx_eq[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_tx_eq(self, input, 1); +} + + +int +__qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_am; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_am[0] == setv[0]) && + (self->rx_am[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + setv, + self->rx_am, + "_qsfp_set_rx_am", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_am; + } + return 0; + +err_qsfp_set_rx_am: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_am[0]; + tmp[1] = self->rx_am[1]; + if (_qsfp_update_attr_rx_am(self, show_e) < 0){ + continue; + } + if ((self->rx_am[0] == tmp[0]) && + (self->rx_am[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_am(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_set_rx_am"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_am(self, input, 1); +} + + +int +__qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_em; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_em[0] == setv[0]) && + (self->rx_em[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + setv, + self->rx_em, + "_qsfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_em; + } + return 0; + +err_qsfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_em[0]; + tmp[1] = self->rx_em[1]; + if (_qsfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if ((self->rx_em[0] == tmp[0]) && + (self->rx_em[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_em(self, input, 1); +} + + +int +common_transvr_dump(struct transvr_obj_s* self){ + + char *type_name = "Undefined"; + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + switch (self->type) { + case TRANSVR_TYPE_SFP: + type_name = STR_TRANSVR_SFP; + break; + case TRANSVR_TYPE_QSFP: + type_name = STR_TRANSVR_QSFP; + break; + case TRANSVR_TYPE_QSFP_PLUS: + type_name = STR_TRANSVR_QSFP_PLUS; + break; + case TRANSVR_TYPE_QSFP_28: + type_name = STR_TRANSVR_QSFP28; + break; + case TRANSVR_TYPE_FAKE: + type_name = "FAKE"; + goto ok_common_transvr_dump; + case TRANSVR_TYPE_UNPLUGGED: + type_name = "UNPLUGGED"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_INCONSISTENT: + type_name = "INCONSISTENT"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_ERROR: + type_name = "ERROR"; + goto err_common_transvr_dump; + + default: + type_name = "UNEXPECTED"; + goto err_common_transvr_dump; + } + printk(KERN_INFO "[SWPS] Dump %s information:\n", self->swp_name); + printk(KERN_INFO " |- :%s\n", type_name); + printk(KERN_INFO " |- :%s\n", self->vendor_name); + printk(KERN_INFO " |- :%s\n", self->vendor_pn); + printk(KERN_INFO " |- :%s\n", self->vendor_rev); + printk(KERN_INFO " |- :%s\n", self->vendor_sn); + printk(KERN_INFO " |- :0x%02x\n", self->br); + printk(KERN_INFO " |- :0x%02x\n", self->comp_rev); + printk(KERN_INFO " |- :%d\n", self->len_om1); + printk(KERN_INFO " |- :%d\n", self->len_om2); + printk(KERN_INFO " |- :%d\n", self->len_om3); + printk(KERN_INFO " |- :%d\n", self->len_om4); + return 0; + +ok_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return 0; + +err_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return -1; +} + + +int +sfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_sm); + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :0x%02x\n", self->rate_id); + return 0; +} + + +int +qsfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :Class_%d\n", __qsfp_get_power_cls(self, 0)); + return 0; +} + + +int +fake_transvr_dump(struct transvr_obj_s* self) { + + printk(KERN_INFO "[SWPS] Dump transceiver information: %s\n", self->swp_name); + printk(KERN_INFO " |- :FAKE\n"); + printk(KERN_INFO " |- :FAKE_VENDER_NAME\n"); + printk(KERN_INFO " |- :FAKE_VENDER_PN\n"); + printk(KERN_INFO " |- :FAKE_VENDER_REV\n"); + printk(KERN_INFO " |- :FAKE_VENDER_SN\n"); + printk(KERN_INFO " |- :0x99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " '- :0x99\n"); + return 0; +} + + +/* ========== Object functions for fake type ========== + */ +int +fake_transvr_update(struct transvr_obj_s *self, + int show_err){ + self->state = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +fake_get_binary(struct transvr_obj_s *self){ + return 1; +} + +int +fake_get_int(struct transvr_obj_s *self){ + return 99; +} + + +int +fake_get_hex(struct transvr_obj_s *self){ + return 0x0f; +} + + +int +fake_get_str(struct transvr_obj_s *self, char *buf) { + return snprintf(buf, 16, "fake_get_str\n"); +} + + +int +fake_set_int(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: %d\n", __func__, input); + return 0; +} + + +int +fake_set_hex(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: 0x%02x\n", __func__, input); + return 0; +} + + +/* ========== Object functions for unsupported ========== + */ +int +unsupported_get_func(struct transvr_obj_s *self){ + return ERR_TRANSVR_NOTSUPPORT; +} + + +int +unsupported_get_func2(struct transvr_obj_s *self, + char *buf_p) { + int len = snprintf(buf_p, 8, "%d\n", ERR_TRANSVR_NOTSUPPORT); + return len; +} + + +int +unsupported_set_func(struct transvr_obj_s *self, + int input_val){ + return ERR_TRANSVR_NOTSUPPORT; +} + + + +/* ========== Object functions for long term task ========== + * + * [Note] + * SWPS transceiver worker is likely the green-thread (coroutine). + * Due to resource and performance considerations. SWPS run all + * features in one kthread at the same time, and handle by it self. + */ + +/* For Transceiver Task Handling + */ +static struct transvr_worker_s * +transvr_task_get(struct transvr_obj_s *self, + char *func_name) { + + struct transvr_worker_s *curr_p = self->worker_p; + + while(curr_p != NULL){ + if (strcmp((curr_p->func_name), func_name) == 0 ) { + return curr_p; + } + curr_p = curr_p->next_p; + } + return NULL; +} + + +static struct transvr_worker_s* +transvr_task_creat(struct transvr_obj_s *self, + int (*main_task)(struct transvr_worker_s *task), + int (*post_task)(struct transvr_worker_s *task), + char *caller) { + + struct transvr_worker_s *task_p = NULL; + struct transvr_worker_s *curr_p = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check task not exist */ + task_p = transvr_task_get(self, caller); + if (task_p) { + snprintf(err_msg, sizeof(err_msg), "Task already created!"); + goto err_transvr_task_creat; + } + /* Create task worker */ + task_p = kzalloc(sizeof(struct transvr_worker_s), GFP_KERNEL); + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_transvr_task_creat; + } + /* Setup task data */ + task_p->transvr_p = self; + task_p->next_p = NULL; + task_p->trigger_time = 0; + task_p->retry = 1; + task_p->state = STATE_T_TASK_INIT; + task_p->main_task = main_task; + task_p->post_task = post_task; + task_p->p_data = NULL; + snprintf(task_p->func_name, sizeof(task_p->func_name), "%s", caller); + /* Setup Link List */ + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p->next_p != NULL) { + curr_p = curr_p->next_p; + } + curr_p->next_p = task_p; + task_p->pre_p = curr_p; + } else { + self->worker_p = task_p; + task_p->pre_p = NULL; + } + return task_p; + +err_transvr_task_creat: + SWPS_ERR("%s: %s :%s :%s\n", + __func__, err_msg, caller, self->swp_name); + return NULL; +} + + +static void +transvr_task_free_one(struct transvr_worker_s *task_p){ + + struct transvr_worker_s *pre_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (task_p) { + pre_p = task_p->pre_p; + next_p = task_p->next_p; + + if ((pre_p) && (next_p)) { + pre_p->next_p = next_p; + next_p->pre_p = pre_p; + + } else if ((!pre_p) && (next_p)) { + next_p->pre_p = NULL; + + } else if ((pre_p) && (!next_p)) { + pre_p->next_p = NULL; + + } else if ((!pre_p) && (!next_p)) { + task_p->transvr_p->worker_p = NULL; + } else { + SWPS_ERR("%s: Unexcept case!\n :%s", + __func__, task_p->transvr_p->swp_name); + } + kfree(task_p->p_data); + kfree(task_p); + } +} + + +static void +transvr_task_free_all(struct transvr_obj_s *self) { + + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p) { + next_p = curr_p->next_p; + transvr_task_free_one(curr_p); + curr_p = next_p; + } + self->worker_p = NULL; + } +} + + +static void +transvr_cache_free_all(struct transvr_obj_s *self) { + + memset(self->vendor_name, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_rev, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_pn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + memset(self->vendor_sn, 0, (LEN_TRANSVR_M_STR * sizeof(char)) ); + self->extphy_offset = 0; +} + +static int +_transvr_task_run_main(struct transvr_worker_s *task_p) { + + int retval = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "main_task is NULL!"); + goto main_transvr_task_err; + } + if ((task_p->trigger_time) == 0){ + goto main_transvr_task_run; + } + if (time_before(jiffies, task_p->trigger_time)){ + goto main_transvr_task_wait; + } + goto main_transvr_task_run; + +main_transvr_task_run: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + task_p->retry -= 1; + } + retval = task_p->main_task(task_p); + if (retval < 0) { + if (task_p->retry > 0) { + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + } + goto main_transvr_task_identify; + +main_transvr_task_identify: + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + + case EVENT_TRANSVR_TASK_DONE: + task_p->state = STATE_T_TASK_DONE; + return EVENT_TRANSVR_TASK_DONE; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + +main_transvr_task_wait: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + +main_transvr_task_err: + task_p->state = STATE_T_TASK_FAIL; + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, retval, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_transvr_task_run_post(struct transvr_worker_s *task_p) { + + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if ((task_p->post_task) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + switch (task_p->state) { + case STATE_T_TASK_WAIT: + case STATE_T_TASK_INIT: + goto post_transvr_task_wait; + + case STATE_T_TASK_DONE: + case STATE_T_TASK_FAIL: + goto post_transvr_task_run; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Unexcept task state"); + goto post_transvr_task_err; + +post_transvr_task_run: + task_p->post_task(task_p); + return EVENT_TRANSVR_TASK_DONE; + +post_transvr_task_wait: + return EVENT_TRANSVR_TASK_WAIT; + +post_transvr_task_err: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, task_p->state, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_one(struct transvr_worker_s *task_p) { + + int retval_main = DEBUG_TRANSVR_INT_VAL; + int retval_post = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval_main = _transvr_task_run_main(task_p); + if (retval_main < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute main_task fail!"); + goto err_transvr_task_run_one; + } + retval_post = _transvr_task_run_post(task_p); + if (retval_post < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute post_task fail!"); + goto err_transvr_task_run_one; + } + return retval_main; + +err_transvr_task_run_one: + SWPS_INFO("%s: %s
:%d :%d :%s :%s\n", + __func__, err_msg, retval_main, retval_post, + task_p->func_name, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_all(struct transvr_obj_s *self) { + + int haserr = 0; + int retval = DEBUG_TRANSVR_INT_VAL; + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if ((self->worker_p) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + curr_p = self->worker_p; + while (curr_p != NULL) { + next_p = curr_p->next_p; + retval = transvr_task_run_one(curr_p); + if (curr_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + curr_p = next_p; + continue; + } + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + break; + case EVENT_TRANSVR_TASK_DONE: + transvr_task_free_one(curr_p); + break; + case EVENT_TRANSVR_TASK_FAIL: + + default: + haserr = 1; + transvr_task_free_one(curr_p); + break; + } + curr_p = next_p; + } + if (haserr) { + return EVENT_TRANSVR_TASK_FAIL; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +static void +transvr_task_set_delay(struct transvr_worker_s *task_p, + unsigned long delay_msec) { + + task_p->trigger_time = (jiffies + (delay_msec * (HZ/1000))); +} + + +static void +transvr_task_set_retry(struct transvr_worker_s *task_p, + unsigned long retry_times) { + + task_p->retry = retry_times; +} + + +/* For Transceiver Post Task + */ +int +taskfunc_post_do_nothing(struct transvr_worker_s *task_p) { + + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_post_handle_task_state(struct transvr_worker_s *task_p) { + + struct transvr_obj_s* tp = task_p->transvr_p; + + switch (task_p->state) { + case STATE_T_TASK_INIT: + case STATE_T_TASK_WAIT: + return EVENT_TRANSVR_TASK_WAIT; + + case STATE_T_TASK_DONE: + tp->state = STATE_TRANSVR_CONNECTED; + tp->send_uevent(tp, KOBJ_ADD); + return EVENT_TRANSVR_TASK_DONE; + + case STATE_T_TASK_FAIL: + tp->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_TASK_FAIL; + + default: + break; + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +/* For Transceiver Main Task + */ +int +_taskfunc_sfp_setup_soft_rs(struct transvr_worker_s *task_p, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller) { + + int show_err = 0; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_soft_rs"; + + err_code = _sfp_update_attr_soft_rs0(task_p->transvr_p, 0); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + err_code = __sfp_set_soft_rs(task_p->transvr_p, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_setup_soft_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_code); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +__taskfunc_sfp_setup_hard_rs(struct transvr_worker_s *task_p, + int input_val, + int (*get_func)(struct ioexp_obj_s *self, int virt_offset), + int (*set_func)(struct ioexp_obj_s *self, int virt_offset, int input_val)) { + + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + + err_val = get_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset); + + if (err_val < 0) { + if (err_val == ERR_IOEXP_NOTSUPPORT) { + return EVENT_TRANSVR_TASK_DONE; + } + err_str = "Get current hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + if (err_val == input_val) { + return EVENT_TRANSVR_TASK_DONE; + } + err_val = set_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_p_taskfunc_sfp_setup_hard_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_hard_rs0(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs0, + task_p->transvr_p->ioexp_obj_p->set_hard_rs0); +} + + +int +_taskfunc_sfp_setup_hard_rs1(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs1, + task_p->transvr_p->ioexp_obj_p->set_hard_rs1); +} + + +int +_taskfunc_sfp_setup_rs0(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs0"; + + err_val = _taskfunc_sfp_setup_hard_rs0(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs0, + task_p->transvr_p->eeprom_map_p->page_soft_rs0, + task_p->transvr_p->eeprom_map_p->offset_soft_rs0, + bit_shift, + &(task_p->transvr_p->soft_rs0), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs0_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs0(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_rs1(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs1"; + + err_val = _taskfunc_sfp_setup_hard_rs1(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs1, + task_p->transvr_p->eeprom_map_p->page_soft_rs1, + task_p->transvr_p->eeprom_map_p->offset_soft_rs1, + bit_shift, + &(task_p->transvr_p->soft_rs1), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs1_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs1(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_sfp_setup_SFF8431_case1(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs0(task_p, update_val); +} + + + +int +taskfunc_sfp_setup_SFF8431_case2(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs1(task_p, update_val); +} + + +int +taskfunc_sfp_setup_SFF8431_case3(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + int update_rs0 = 1; + int update_rs1 = 1; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _taskfunc_sfp_setup_rs0(task_p, update_rs0); + if (err_code < 0) { + return err_code; + } + return _taskfunc_sfp_setup_rs1(task_p, update_rs1); +} + + +int +taskfunc_sfp_handle_1g_rj45(struct transvr_worker_s *task_p) { + + /* Not all of platform support 0x56 for transceiver + * external PHY, Support list as below: + * => 1. Magnolia-PVT (PS: EVT & DVT not ready) + */ + int ext_phy_addr = 0x56; + int ext_phy_page = -1; + int ext_phy_offs = 0x11; + int ext_phy_len = 1; + int lstate_mask = 0x04; /* 00000100 */ + int show_err = 0; + int fail_retry = 5; + int fail_delay = 1000; /* msec */ + int err_code = DEBUG_TRANSVR_INT_VAL; + uint8_t detect_val = DEBUG_TRANSVR_HEX_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + int *tmp_p = NULL; + char *func_name = "taskfunc_sfp_handle_1g_rj45"; + + if (task_p->transvr_p->state != STATE_TRANSVR_CONNECTED) { + return EVENT_TRANSVR_TASK_DONE; + } + if ( (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000) && + (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000_up) ) { + goto err_taskfunc_sfp_handle_1g_rj45_1; + } + err_code = _common_update_uint8_attr(task_p->transvr_p, + ext_phy_addr, + ext_phy_page, + ext_phy_offs, + ext_phy_len, + &detect_val, + func_name, + show_err); + if ( (err_code < 0) || + (detect_val == DEBUG_TRANSVR_HEX_VAL) ) { + snprintf(err_str, sizeof(err_str), "Detect external link status fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + if ((detect_val & lstate_mask) == lstate_mask) { + goto ok_taskfunc_sfp_handle_1g_rj45_link_up; + } + goto ok_taskfunc_sfp_handle_1g_rj45_link_down; + +ok_taskfunc_sfp_handle_1g_rj45_link_up: + /* Filter out noise */ + if (!(task_p->p_data)) { + tmp_p = kzalloc(sizeof(int), GFP_KERNEL); + if (!tmp_p) { + snprintf(err_str, sizeof(err_str), "kzalloc p_data fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + *tmp_p = TRANSVR_CLASS_BASE_T_1000_up; + task_p->p_data = tmp_p; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + } + if ((*(int *)(task_p->p_data)) != TRANSVR_CLASS_BASE_T_1000_up) { + kfree(task_p->p_data); + task_p->p_data = NULL; + snprintf(err_str, sizeof(err_str), "Internal error"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + kfree(task_p->p_data); + task_p->p_data = NULL; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_link_down: + if (task_p->p_data) { + kfree(task_p->p_data); + task_p->p_data = NULL; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_done: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_1: + snprintf(err_str, sizeof(err_str), "Detect transceiver:%d not Base-T, remove task.", + task_p->transvr_p->info); + SWPS_INFO("%s: %s :%s\n", __func__, err_str, task_p->transvr_p->swp_name); + transvr_task_set_retry(task_p, 0); + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_2: + if (task_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, fail_retry); + } + if ((task_p->retry) == 0) { + /* Error case: + * => In this case, SWPS will stop external Link state monitor features + * and keeps transvr_p->info on TRANSVR_CLASS_BASE_T_1000_up. + * Upper layer will see it always Linkup that because of these type of + * transceiver has external phy, BCM chip see it as Loopback transceiver. + */ + SWPS_WARN("%s can not access external PHY of Base-T SFP transceiver\n", + task_p->transvr_p->swp_name); + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + return EVENT_TRANSVR_TASK_DONE; + } else { + transvr_task_set_delay(task_p, fail_delay); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self, + int setup_val) { + + int curr_val = DEBUG_TRANSVR_INT_VAL; + int err_val = DEBUG_TRANSVR_INT_VAL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset); + if (curr_val < 0){ + err_msg = "Get current value fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + if (curr_val == setup_val){ + return EVENT_TRANSVR_TASK_DONE; + } + err_val = self->ioexp_obj_p->set_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset, + setup_val); + if (err_val < 0){ + err_msg = "Setup power mode fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_qsfp_setup_power_mod_1: + SWPS_INFO("%s: %s :%d :%d :%d\n", + __func__, err_msg, err_val, curr_val, setup_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_qsfp_handle_tx_disable(struct transvr_worker_s *task_p) { + + int i = 0; + int retry = 5; + int delay_ms = 100; + + if (task_p->transvr_p->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return EVENT_TRANSVR_TASK_DONE; + } + if (!_qsfp_is_implement_tx_disable(task_p->transvr_p)) { + return EVENT_TRANSVR_TASK_DONE; + } + for (i=0; itransvr_p, + task_p->transvr_p->auto_tx_disable) + == EVENT_TRANSVR_TASK_DONE) { + goto ok_taskfunc_qsfp_handle_tx_disable; + } + mdelay(delay_ms); + } + SWPS_INFO("%s auto setup tx_disable:0x%02x fail.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_INIT_FAIL; + +ok_taskfunc_qsfp_handle_tx_disable: + SWPS_INFO("%s auto setup tx_disable:0x%02x ok.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_qsfp_set_hpmod(struct transvr_worker_s *task_p) { + + int err = DEBUG_TRANSVR_INT_VAL; + int HIGH_POWER_MODE = 0; + + /* Handle power mode */ + err = _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + HIGH_POWER_MODE); + if (err < 0) { + SWPS_INFO("%s: setup hpmod fail :%d :%s\n", + __func__, err, task_p->transvr_p->swp_name); + return err; + } + /* Handle auto tx_disable + * [Note] + * => Because there are some transceiver have timing issues or + * setup sequence issues, therefore we handle auto tx_disable + * after handle power mode. + */ + mdelay(100); + return taskfunc_qsfp_handle_tx_disable(task_p); +} + + +int +taskfunc_qsfp_set_lpmod(struct transvr_worker_s *task_p) { + + int LOW_POWER_MODE = 1; + return _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + LOW_POWER_MODE); +} + + +static int +initfunc_sfp_handle_multi_rate_mode(struct transvr_obj_s *self) { + + int task_retry = 3; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "sfp_handle_multi_rate_mode"; + struct transvr_worker_s *task_p = NULL; + + switch (self->rate_id) { + case 0x00: /* Unspecified */ + case 0x03: /* Unspecified */ + case 0x05: /* Unspecified */ + case 0x07: /* Unspecified */ + case 0x09: /* Unspecified */ + case 0x0B: /* Unspecified */ + case 0x0D: /* Unspecified */ + case 0x0F: /* Unspecified */ + goto sfp_handle_multi_rate_mode_4_unspecified; + + case 0x02: /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case1, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x04: /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case2, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x06: /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case3, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x01: /* SFF-8079 (4/2/1G Rate_Select & AS0/AS1) */ + err_str = "SFF-8079 (4/2/1G Rate_Select & AS0/AS1)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x08: /* FC-PI-5 (16/8/4G Rx Rate_select only) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Rx Rate_select only)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0A: /* FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0C: /* FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + */ + err_str = "FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0E: /* 10/8G Rx and Tx Rate_Select controlling the operation or + * locking modes of the internal signal conditioner, retimer + * or CDR, according to the logic table defined in Table 10-2, + * High Bit Rate (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = + * 8.5 Gb/s. In this mode, the default value of bit 110.3 (Soft + * Rate Select RS(0), Table 9-11) and of bit 118.3 (Soft Rate + * Select RS(1), Table 10-1) is 1. + */ + err_str = "cable type: 0x0E"; + goto sfp_handle_multi_rate_mode_4_not_support; + + default: + err_str = "cable type: UNKNOW"; + goto sfp_handle_multi_rate_mode_4_not_support; + } + +sfp_handle_multi_rate_mode_4_sff8431: + if (!task_p) { + err_str = "Create task fail!"; + goto sfp_handle_multi_rate_mode_4_fail_1; + } + transvr_task_set_retry(task_p, task_retry); + return EVENT_TRANSVR_TASK_WAIT; + +sfp_handle_multi_rate_mode_4_unspecified: + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_not_support: + SWPS_INFO("%s: Does not support %s :%s :0x%02x\n", + func_str, err_str, self->swp_name, self->rate_id); + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_fail_1: + SWPS_INFO("%s: %s :%s :0x%02x, :%d\n", + func_str, err_str, self->swp_name, self->rate_id, err_code); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +initfunc_sfp_handle_1g_rj45(struct transvr_obj_s *self) { + + struct transvr_worker_s *task_p = NULL; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_sfp_handle_1g_rj45"; + + + if (self->info == TRANSVR_CLASS_BASE_T_1000) { + task_p = transvr_task_creat(self, + taskfunc_sfp_handle_1g_rj45, + taskfunc_post_do_nothing, + func_str); + if (!task_p) { + snprintf(err_str, sizeof(err_str), "Create task fail"); + goto err_initfunc_sfp_handle_1g_rj45; + } + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_initfunc_sfp_handle_1g_rj45: + SWPS_INFO("%s: %s :%s :%d\n", + __func__, err_str, self->swp_name, detect_cls); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +initfunc_qsfp_handle_power_mode(struct transvr_obj_s *self) { + + int err_code = EVENT_TRANSVR_EXCEP_INIT; + int power_class = DEBUG_TRANSVR_INT_VAL; + int hpmod_retry = 3; + int lpower_config = 1; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + unsigned long hpmod_delay = 500; /* msec */ + struct transvr_worker_s *task_p = NULL; + + /* Handle power mode for IOEXP */ + power_class = __qsfp_get_power_cls(self, 0); + switch (power_class) { + case 1: /* Case: Low power mode (Class = 1) */ + err_code = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (err_code < 0){ + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + return EVENT_TRANSVR_TASK_DONE; + + case 2: /* Case: High power mode (Class > 1) */ + case 3: + case 4: + case 5: + case 6: + case 7: + task_p = transvr_task_creat(self, + taskfunc_qsfp_set_hpmod, + taskfunc_post_handle_task_state, + "transvr_init_qsfp"); + if (!task_p) { + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + transvr_task_set_retry(task_p, hpmod_retry); + transvr_task_set_delay(task_p, hpmod_delay); + return EVENT_TRANSVR_TASK_WAIT; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Exception case"); + goto err_initfunc_qsfp_handle_power_mode; + +err_initfunc_qsfp_handle_power_mode: + SWPS_INFO("%s: %s :%s \n", __func__, err_msg, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +initfunc_qsfp28_handle_cdr(struct transvr_obj_s *self) { + + uint8_t DEFAULT_VAL_CDR = 0xff; + int CDR_FUNC_EXISTED = 0x3; + int show_err = 1; + int err_val = EVENT_TRANSVR_TASK_FAIL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_qsfp28_handle_cdr"; + + err_val = __qsfp_get_cdr_present(self, 0); + if ( (err_val < 0) || + (err_val == DEBUG_TRANSVR_HEX_VAL) ) { + err_msg = "detect cdr_present fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + if (err_val == CDR_FUNC_EXISTED) { + err_val = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->offset_cdr, + DEFAULT_VAL_CDR, + &(self->cdr), + func_str, + show_err); + if (err_val < 0) { + err_msg = "set CDR fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_qsfp_handle_cdr_1: + SWPS_INFO("%s: %s :%d :%s\n", + func_str, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + +/* ========== Object functions for Final State Machine ========== + */ +int +is_plugged(struct transvr_obj_s *self){ + + int limit = 63; + int present = DEBUG_TRANSVR_INT_VAL; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p; + + if (!ioexp_p) { + snprintf(emsg, limit, "ioexp_p is null!"); + goto err_is_plugged_1; + } + present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset); + switch (present){ + case 0: + return 1; + case 1: + return 0; + case ERR_IOEXP_UNINIT: + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + default: + if (ioexp_p->state == STATE_IOEXP_INIT){ + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + } + break; + } + SWPS_INFO("%s: Exception case! :%d :%d\n", + __func__, present, ioexp_p->state); + return 0; + +err_is_plugged_1: + SWPS_DEBUG("%s: %s\n", __func__, emsg); + return 0; +} + + +static int +detect_transvr_type(struct transvr_obj_s* self){ + + int type = TRANSVR_TYPE_ERROR; + + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + type = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + + /* Case: 1. Wait transceiver I2C module. + * 2. Transceiver I2C module failure. + * Note: 1. SFF allow maximum transceiver initial time is 2 second. So, there + * are exist some case that we need to wait transceiver. + * For these case, we keeps status on "TRANSVR_TYPE_UNPLUGGED", than + * state machine will keep trace with it. + * 2. There exist some I2C failure case we need to handle. Such as user + * insert the failure transceiver, or any reason cause it abnormal. + */ + if (type < 0){ + switch (type) { + case -EIO: + SWPS_DEBUG("%s: %s smbus return:-5 (I/O error)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + case -ENXIO: + SWPS_DEBUG("%s: %s smbus return:-6 (No such device or address)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + default: + break; + } + SWPS_INFO("%s: %s unexpected smbus return:%d \n", + __func__, self->swp_name, type); + return TRANSVR_TYPE_ERROR; + } + /* Identify valid transceiver type */ + switch (type){ + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + break; + case TRANSVR_TYPE_UNKNOW_1: + case TRANSVR_TYPE_UNKNOW_2: + type = TRANSVR_TYPE_UNKNOW_2; + break; + default: + SWPS_DEBUG("%s: unknow type:0x%02x \n", __func__, type); + type = TRANSVR_TYPE_ERROR; + break; + } + return type; +} + + +static int +detect_transvr_state(struct transvr_obj_s *self, + int result[2]){ + /* [return] [result-0] [result-1] + * 0 STATE_TRANSVR_CONNECTED TRANSVR_TYPE_FAKE + * 0 STATE_TRANSVR_DISCONNECTED TRANSVR_TYPE_UNPLUGGED + * 0 STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * 0 STATE_TRANSVR_INIT / + * 0 STATE_TRANSVR_SWAPPED + * 0 STATE_TRANSVR_CONNECTED + * ERR_TRNASVR_BE_ISOLATED STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_I2C_CRASH STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_UNEXCPT STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_UNKNOW_1/2 + */ + result[0] = STATE_TRANSVR_UNEXCEPTED; /* For return state */ + result[1] = TRANSVR_TYPE_ERROR; /* For return type */ + + /* Case1: Fake type */ + if (self->type == TRANSVR_TYPE_FAKE){ + result[0] = STATE_TRANSVR_CONNECTED; + result[1] = TRANSVR_TYPE_FAKE; + return 0; + } + /* Case2: Transceiver unplugged */ + if (!is_plugged(self)){ + result[0] = STATE_TRANSVR_DISCONNECTED; + result[1] = TRANSVR_TYPE_UNPLUGGED; + return 0; + } + /* Case3: Transceiver be isolated */ + if (self->state == STATE_TRANSVR_ISOLATED){ + result[0] = STATE_TRANSVR_ISOLATED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case4: Transceiver plugged */ + result[1] = detect_transvr_type(self); + /* Case4.1: I2C topology crash + * Note : There are some I2C issues cause by transceiver/cables. + * We need to check topology status when user insert it. + * But in this step, we can't not ensure this is the issues + * port. So, it return the ERR_TRANSVR_I2C_CRASH, then upper + * layer will diagnostic I2C topology. + */ + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: %s detect I2C crash :%d\n", + __func__, self->swp_name, self->state); + result[0] = STATE_TRANSVR_UNEXCEPTED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_I2C_CRASH; + } + /* Case4.2: System initial not ready, + * Note : Sometime i2c channel or transceiver EEPROM will delay that will + * cause system in inconsistent state between EEPROM and IOEXP. + * In this case, SWP transceiver object keep state at LINK_DOWN + * to wait system ready. + * By the way, State Machine will handle these case. + */ + if (result[1] == TRANSVR_TYPE_UNPLUGGED){ + result[0] = STATE_TRANSVR_DISCONNECTED; + return 0; + } + /* Case4.3: Error transceiver type */ + if (result[1] == TRANSVR_TYPE_ERROR){ + result[0] = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s detect error type\n", __func__, self->swp_name); + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard!"); + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case3.3: Unknow transceiver type */ + if ((result[1] == TRANSVR_TYPE_UNKNOW_1) || + (result[1] == TRANSVR_TYPE_UNKNOW_2) ){ + result[0] = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + /* Case3.4: During initial process */ + if (self->state == STATE_TRANSVR_INIT){ + result[0] = STATE_TRANSVR_INIT; + return 0; + } + /* Case3.5: Transceiver be swapped */ + if (self->type != result[1]){ + result[0] = STATE_TRANSVR_SWAPPED; + return 0; + } + /* Case3.6: Link up state */ + result[0] = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +_sfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = _sfp_get_comp_extended(self); + + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_25G_AOC; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_25G_SR; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_25G_LR; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_25G_ER; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x0c: /* 25GBASE-CR CA-S */ + case 0x0d: /* 25GBASE-CR CA-N */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L1_25G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_10_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _sfp_get_comp_10g_eth_comp(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 10G Optical (x1) */ + if ((detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + } + if ((detect_val & 0x80) == 0x80) { /* 10000000 : 10GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_1g = 0x0b; + int upper_bound_1g = 0x1A; + int lower_bound_10g = 0x60; + int upper_bound_10g = 0x75; + int lower_bound_25g = 0xf0; + int upper_bound_25g = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 25G */ + if ((notmal_br >= lower_bound_25g) && + (notmal_br <= upper_bound_25g) ) { + return TRANSVR_CLASS_25G; + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + /* Check 1G */ + if ((notmal_br >= lower_bound_1g) && + (notmal_br <= upper_bound_1g) ) { + return TRANSVR_CLASS_1G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + int speed_br = DEBUG_TRANSVR_INT_VAL; + int speed_tmp = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + + speed_br = _sfp_detect_if_sp_by_br(self); + detect_val = _sfp_get_comp_1g_eth_comp(self); + + if (detect_val < 0) { + snprintf(err_str, sizeof(err_str), "Detect abnormal value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + } + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 1G (x1) */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 1000BASE-SX */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_SX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x02) == 0x02) { /* 00000010 : 1000BASE-LX *3 */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_LX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 1000BASE-CX */ + speed_tmp = TRANSVR_CLASS_COPPER_L1_1G; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + /* Case: 1000 Base-T (x1) */ + if ((detect_val & 0x08) == 0x08) { /* 00001000 : 1000BASE-T */ + return TRANSVR_CLASS_BASE_T_1000; + } + /* Case: 100 Base */ + if ( ((detect_val & 0x10) == 0x10) || /* 00010000 : 100BASE-LX/LX10 */ + ((detect_val & 0x20) == 0x20) || /* 00100000 : 100BASE-FX */ + ((detect_val & 0x40) == 0x40) || /* 01000000 : BASE-BX10 *3 */ + ((detect_val & 0x80) == 0x80) ){ /* 10000000 : BASE-PX *3 */ + return TRANSVR_CLASS_OPTICAL_100; + } + /* Case: ERROR */ + snprintf(err_str, sizeof(err_str), "Case:ERROR, value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + +ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g: + switch (speed_br) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_1G: + return speed_tmp; + case TRANSVR_CLASS_10G: + goto ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G; + } + +ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G: + switch (speed_tmp) { + case TRANSVR_CLASS_OPTICAL_1G_SX: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case TRANSVR_CLASS_OPTICAL_1G_LX: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case TRANSVR_CLASS_COPPER_L1_1G: + return TRANSVR_CLASS_COPPER_L1_10G; + default: + break; + } + snprintf(err_str, sizeof(err_str), "transfer_1to10 fail, speed:%d", speed_tmp); + goto err_p_sfp_detect_class_by_1g_ethernet; + +err_p_sfp_detect_class_by_1g_ethernet: + SWPS_INFO("%s: %s :%s", __func__, err_str, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int is_active = 0; + int conn_val = DEBUG_TRANSVR_INT_VAL; + int check_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _sfp_detect_if_sp_by_br(self); + conn_val = _sfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 */ + case 0x0d: /* MPO 2x16 */ + /* + * ToDo: Need verify Optical Pigtail + */ + goto ok_sfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + /* + * ToDo: Need check ACC use case + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x23: /* No separable connector */ + /* + * ToDo: Standard not clear, not all transceiver vendor + * have the same defined + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_check_active_passive: + check_val = _sfp_get_cable_tech(self); + switch(check_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_unknow; + case 0x04: /* Passive */ + goto ok_sfp_detect_class_by_feature_4_copper; + case 0x08: /* Active */ + is_active = 1; + goto ok_sfp_detect_class_by_feature_4_aoc; + default: + snprintf(err_msg, sizeof(err_msg), + "_sfp_get_cable_tech return Non define value:%d", + check_val); + break; + } + goto err_sfp_detect_class_by_feature_1; + +ok_sfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_25G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_25G_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_25G_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_25G_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_25G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + case TRANSVR_CLASS_1G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_1G_SX; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_1G_LX; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_1G_EX; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_1G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_sfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_OPTICAL_25G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_S_AOC; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_OPTICAL_1G_AOC; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_COPPER_L1_25G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L1_10G; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_COPPER_L1_1G; + default: + return TRANSVR_CLASS_COPPER; + } + +ok_sfp_detect_class_by_feature_4_unknow: + return TRANSVR_CLASS_UNSPECIFIED; + +err_sfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +sft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _sfp_detect_class_by_extend_comp(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 10G Compliance */ + detect_val = _sfp_detect_class_by_10_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 1G Compliance */ + detect_val = _sfp_detect_class_by_1g_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_BASE_T_1000: + case TRANSVR_CLASS_OPTICAL_100: + /* + * ToDo: Need Check 0.1G + */ + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_COPPER_L1_10G: + /* Transfer speed case + * => Example: Raycom 10G DAC + */ + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 1G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check by connector, br, wavelength */ + detect_val = _sfp_detect_class_by_feature(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_OPTICAL_1G: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_COPPER: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_COPPER_L1_10G: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined get_connector:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sft_detect_transceiver_class_1; + +err_sft_detect_transceiver_class_1: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_trident2_if_type_1; + +err_sfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SR); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_KR); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_tomahawk_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_tomahawk_if_type_1; + +err_sfp_set_tomahawk_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_bf_tofino_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to BF looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_sfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = sft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _sfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TRIDENT_3: + case BCM_CHIP_TYPE_TOMAHAWK: + return _sfp_set_tomahawk_if_type(self, detect_cls, result); + + case BF_CHIP_TYPE_TOFINO: + return _sfp_set_bf_tofino_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_sfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = sft_detect_transvr_class(self); + switch(detect_val) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_SP_100); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + detect_val); + goto err_sfp_detect_if_speed_1; + } + /* Check by BR */ + detect_val = _sfp_detect_if_sp_by_br(self); + switch (detect_val) { + case TRANSVR_CLASS_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + default: + break; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_detect_if_speed_1; + +err_sfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_extended(self); + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_100G_AOC; + + case 0x06: /* 100G CWDM4 */ + case 0x09: /* Obsolete (assigned before 100G CWDM4 MSA required FEC) */ + case 0x17: /* 100G CLR4 */ + case 0x1A: /* 100GE-DWDM2 */ + return TRANSVR_CLASS_OPTICAL_100G; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_100G_SR4; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_100G_LR4; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_100G_ER4; + + case 0x07: /* 100G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_100G_PSM4; + + case 0x12: /* 40G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_40G; + + case 0x11: /* 4 x 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + + case 0x10: /* 40GBASE-ER4 */ + return TRANSVR_CLASS_OPTICAL_40G_ER4; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L4_100G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_class_by_10_40_100_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_10_40_100_ethernet(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 40G Optical */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 40G Active Cable (XLPPI) */ + return TRANSVR_CLASS_OPTICAL_40G_AOC; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 40GBASE-SR4 */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + } + if ( (detect_val & 0x02) == 0x02) { /* 00000010 : 40GBASE-LR4 */ + return TRANSVR_CLASS_OPTICAL_40G_LR4; + } + if ( (detect_val & 0x08) == 0x08) { /* 00001000 : 40GBASE-CR4 */ + return TRANSVR_CLASS_COPPER_L4_40G; + } + /* Case: 10G Optical */ + if ( (detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + } + /* Case: Extend Compliance */ + if ( ((detect_val & 0x80) == 0x80) ){ /* 10000000 : Use Extend Compliance */ + return TRANSVR_CLASS_EXTEND_COMP; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_10g = 0x10; + int upper_bound_10g = 0x25; + int lower_bound_40g = 0x60; + int upper_bound_40g = 0x75; + int lower_bound_100g = 0x60; + int upper_bound_100g = 0x75; + int used_extend_br = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + int extend_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 40G */ + if ((notmal_br >= lower_bound_40g) && + (notmal_br <= upper_bound_40g) ) { + return TRANSVR_CLASS_40G; + } + /* Check 100G */ + if (notmal_br == used_extend_br) { + extend_br = (int)(self->extbr); /* updated by update_all() */ + if ((extend_br >= lower_bound_100g) && + (extend_br <= upper_bound_100g) ) { + return TRANSVR_CLASS_100G; + } + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_qsfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int conn_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _qsfp_detect_if_sp_by_br(self); + conn_val = _qsfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 (Multifiber Parallel Optic) */ + case 0x0d: /* MPO 2x16 */ + goto ok_qsfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + goto ok_qsfp_detect_class_by_feature_4_copper; + case 0x23: /* No separable connector */ + if ((_qsfp_get_comp_fc_link_length(self) > 0) || + (_qsfp_get_comp_fc_trans_tech(self) > 0) || + (_qsfp_get_comp_fc_trans_media(self) > 0) || + (_qsfp_get_comp_fc_speed(self) > 0) ) { + goto ok_qsfp_detect_class_by_feature_4_aoc; + } + goto ok_qsfp_detect_class_by_feature_4_copper; + default: + snprintf(err_msg, sizeof(err_msg), + "_qsfp_get_connector_type return Non define value:%d", + conn_val); + goto err_qsfp_detect_class_by_feature_1; + } + return TRANSVR_CLASS_UNSPECIFIED; + +ok_qsfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_100G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_100G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_100G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_100G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_100G; + + case TRANSVR_CLASS_40G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_40G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_40G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_40G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_40G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_Q_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_OPTICAL_100G_AOC; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_OPTICAL_40G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_Q_AOC; + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_COPPER_L4_100G; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_COPPER_L4_40G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L4_10G; + default: + return TRANSVR_CLASS_COPPER; + } + +err_qsfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", + __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +qsft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _qsfp_detect_class_by_extend_comp(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_COPPER_L4_100G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check 10/40G/100G Ethernet Compliance */ + detect_val = _qsfp_detect_class_by_10_40_100_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_COPPER_L4_40G: + return detect_val; + case TRANSVR_CLASS_EXTEND_COMP: + /* Format incorrect case (We already checked the Extend + * Compliance is 0 + */ + snprintf(err_msg, sizeof(err_msg), + "Transceiver format incorrect"); + goto err_qsft_detect_transvr_class_1; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10/40/100:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check by Connector type, BR and wavelength */ + detect_val = _qsfp_detect_class_by_feature(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_COPPER_L4_100G: + case TRANSVR_CLASS_COPPER_L4_40G: + case TRANSVR_CLASS_COPPER_L4_10G: + case TRANSVR_CLASS_COPPER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined connector:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), + "Can not identify!"); + goto err_qsft_detect_transvr_class_1; + +err_qsft_detect_transvr_class_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: LR4 or LR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: /* Need Check: ER4 or ER */ + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_KR4); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_bf_tofino_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + /* (TBD) + * Due to BF looks like doesn't have interface type. + * We bypass it currently. + */ + int lmax = 8; + return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); +} + + +int +_qsfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = qsft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _qsfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TRIDENT_3: + case BCM_CHIP_TYPE_TOMAHAWK: + return _qsfp_set_tomahawk_if_type(self, detect_cls, result); + + case BF_CHIP_TYPE_TOFINO: + return _qsfp_set_bf_tofino_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 8; + char tmp_result[8] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = qsft_detect_transvr_class(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G Copper */ + case TRANSVR_CLASS_COPPER_L4_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + break; + /* Copper */ + case TRANSVR_CLASS_COPPER: + break; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined class case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Check br and extbr */ + detect_val = _qsfp_detect_if_sp_by_br(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + case TRANSVR_CLASS_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined BR case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_detect_if_speed_1; + +err_qsfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_common_set_lane_map_str(struct transvr_obj_s* self, + char *result) { + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + char err_msg[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_L_STR); + snprintf(result, LEN_TRANSVR_L_STR, "%s=", TRANSVR_UEVENT_KEY_LANE); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + if (tmp_val > 256) { + snprintf(err_msg, sizeof(err_msg), + "detect abnormal value:%d", tmp_val); + goto err_common_set_lane_map_str_1; + } + memset(tmp_str, 0, sizeof(tmp_str)); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_L_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_L_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_L_STR); + } + if (i == 0) { + goto err_common_set_lane_map_str_2; + } + return 0; + +err_common_set_lane_map_str_1: + SWPS_INFO("%s: %s", __func__, err_msg); +err_common_set_lane_map_str_2: + snprintf(result, LEN_TRANSVR_L_STR, "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_common_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action, + int (*detect_if_type)(struct transvr_obj_s *self, char *result), + int (*detect_if_speed)(struct transvr_obj_s *self, char *result), + int send_anyway) { + + char *uevent_envp[4]; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + char tmp_str[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_1[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_2[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_3[64] = DEBUG_TRANSVR_STR_VAL; + + if (TRANSVR_UEVENT_ENABLE != 1) { + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_get_if_lane(self, tmp_str) < 0) { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + } else { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, tmp_str); + } + switch (u_action) { + case KOBJ_ADD: + /* Detect type */ + if (detect_if_type(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface type fail!"); + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, tmp_str); + uevent_envp[0] = tmp_str_1; + /* Detect speed */ + if (detect_if_speed(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface speed fail!"); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, tmp_str); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + case KOBJ_REMOVE: + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + default: + snprintf(err_msg, sizeof(err_msg), "kobject_action:%d not support", u_action); + goto private_common_send_uevent_4_fail; + } + snprintf(err_msg, sizeof(err_msg), "%s", "Exception case"); + goto private_common_send_uevent_4_fail; + +private_common_send_uevent_4_fail: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + if (send_anyway) { + goto private_common_send_uevent_4_send; + } + return ERR_TRANSVR_UEVENT_FAIL; + +private_common_send_uevent_4_send: + return kobject_uevent_env(&(self->transvr_dev_p->kobj), + u_action, + uevent_envp); +} + +int +sfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_sfp_detect_if_type, + &_sfp_detect_if_speed, + send_anyway); +} + + +int +qsfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_qsfp_detect_if_type, + &_qsfp_detect_if_speed, + send_anyway); +} + + +int +fake_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + + int err; + int detect_result[2]; + int current_state = STATE_TRANSVR_UNEXCEPTED; + int current_type = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_NEW) { + if (_transvr_init_handler(self) < 0){ + return ERR_TRANSVR_INIT_FAIL; + } + } + err = detect_transvr_state(self, detect_result); + if (err < 0) { + return err; + } + /* In Direct mode, driver only detect transceiver when user call driver interface + * which on sysfs. So it only need consider the state of Transceiver. + */ + current_state = detect_result[0]; + current_type = detect_result[1]; + + switch (current_state){ + + case STATE_TRANSVR_DISCONNECTED: /* Transceiver is not plugged */ + self->state = current_state; + self->type = current_type; + return ERR_TRANSVR_UNPLUGGED; + + case STATE_TRANSVR_INIT: /* Transceiver is plugged, system not ready */ + return ERR_TRANSVR_UNINIT; + + case STATE_TRANSVR_ISOLATED: /* Transceiver is plugged, but has some issues */ + return ERR_TRNASVR_BE_ISOLATED; + + case STATE_TRANSVR_CONNECTED: /* Transceiver is plugged, system is ready */ + self->state = current_state; + self->type = current_type; + return 0; + + case STATE_TRANSVR_SWAPPED: /* Transceiver is plugged, system detect user changed */ + self->type = current_type; + if (reload_transvr_obj(self, current_type) < 0){ + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + self->state = current_state; + return 0; + + case STATE_TRANSVR_UNEXCEPTED: /* Transceiver type or state is unexpected case */ + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_UNEXCPT; + + default: + SWPS_INFO("%s: state:%d not in define.\n", __func__, current_state); + break; + } + return ERR_TRANSVR_UNEXCPT; +} + + +static int +_is_except_happened_4_pmode(struct transvr_obj_s* self, + int new_state) { + + int event_chk = 0; + + if (self->temp == 0){ + return 0; + } + switch (new_state) { + case STATE_TRANSVR_INIT: + event_chk = EVENT_TRANSVR_EXCEP_INIT; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_CONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_UP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_DISCONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_DOWN; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_SWAPPED: + event_chk = EVENT_TRANSVR_EXCEP_SWAP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_UNEXCEPTED: + event_chk = EVENT_TRANSVR_EXCEP_EXCEP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_ISOLATED: + event_chk = EVENT_TRANSVR_EXCEP_ISOLATED; + goto check_event_happened_4_pmode; + + default: + SWPS_INFO("%s: unexcepted case:%d\n", __func__, new_state); + break; + } + return 0; + +check_event_happened_4_pmode: + if (self->temp == event_chk){ + return 1; + } + return 0; +} + + +int +common_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + /* [Return Value]: + * ERR_TRANSVR_UNINIT : (1) Initial not ready + * ERR_TRANSVR_UNPLUGGED : (1) Any -> Down + * ERR_TRANSVR_TASK_BUSY : (1) Wait Initial task + * ERR_TRANSVR_UNEXCPT : (1) Initial fail + * (2) Task fail + * (3) Reload fail + * ERR_TRNASVR_BE_ISOLATED : (1) Already be isolated + * OK Case (return 0) : (1) action_4_connected + * (2) action_4_nothing (initial retry) + */ + int curr_state[2]; + int old_state = self->state; + int old_type = self->type; + int new_state = STATE_TRANSVR_UNEXCEPTED; + int new_type = TRANSVR_TYPE_ERROR; + int return_val = ERR_TRANSVR_UNEXCPT; + + /* Never initial */ + if (self->state == STATE_TRANSVR_NEW) { + goto comfsm_action_4_reinit_obj; + } + /* Detect current state */ + switch (detect_transvr_state(self, curr_state)) { + case 0: + new_state = curr_state[0]; + new_type = curr_state[1]; + break; + + case ERR_TRNASVR_BE_ISOLATED: + new_state = STATE_TRANSVR_ISOLATED; + new_type = old_type; + break; + + case ERR_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case ERR_TRANSVR_UNEXCPT: + default: + new_state = STATE_TRANSVR_UNEXCEPTED; + new_type = old_type; + } + /* State handling */ + switch (old_state) { + case STATE_TRANSVR_INIT: /* INIT -> */ + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 1-1: UP -> INIT */ + SWPS_INFO("Detect %s is present. :1-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 1-2: UP -> UP */ + return_val = 0; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 1-3: UP -> DOWN */ + SWPS_INFO("Detect %s is removed. :1-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 1-4: UP -> SWAP */ + SWPS_INFO("Detect %s is swapped. :1-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 1-5: UP -> UNEXPET */ + SWPS_INFO("Detect %s has error. :1-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 1-6: UP -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :1-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_DISCONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 2-1: DOWN -> INIT */ + SWPS_INFO("Detect %s is present. :2-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 2-2: DOWN -> UP */ + SWPS_INFO("Detect %s is present. :2-2\n",self->swp_name); + goto comfsm_action_4_reinit_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 2-3: DOWN -> DOWN */ + return_val = ERR_TRANSVR_UNPLUGGED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_SWAPPED: /* Case 2-4: DOWN -> SWAP */ + SWPS_INFO("Detect %s is swapped. :2-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 2-5: DOWN -> UNEXPET */ + SWPS_INFO("Detect %s has error. :2-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 2-6: DOWN -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :2-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_UNEXCEPTED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 3-1: UNEXPET -> INIT */ + SWPS_INFO("Detect %s is present. :3-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 3-2: UNEXPET -> UP */ + SWPS_INFO("Detect %s is present. :3-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 3-3: UNEXPET -> DOWN */ + SWPS_INFO("Detect %s is removed. :3-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 3-4: UNEXPET -> SWAP */ + SWPS_INFO("Detect %s is swapped. :3-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 3-5: UNEXPET -> UNEXPET */ + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRANSVR_UNEXCPT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 3-6: UNEXPET -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :3-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 4-1: ISOLATE -> INIT */ + SWPS_INFO("Detect %s internal error. :4-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 4-2: ISOLATE -> UP */ + SWPS_INFO("Detect %s internal error. :4-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 4-3: ISOLATE -> DOWN */ + SWPS_INFO("Detect %s is removed. :4-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 4-4: ISOLATE -> SWAP */ + SWPS_INFO("Detect %s internal error. :4-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 4-5: ISOLATE -> UNEXPET */ + SWPS_INFO("Detect %s internal error. :4-5\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 4-6: ISOLATE -> ISOLATE */ + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + default: + break; + } + goto comfsm_action_4_unexpected; + + default: + break; + } + goto comfsm_action_4_unexpected; + + +comfsm_action_4_keep_state: + return return_val; + +comfsm_action_4_reinit_obj: + SWPS_DEBUG("FSM action: %s re-initial.\n", self->swp_name); + return_val = _transvr_init_handler(self); + goto comfsm_action_4_identify_event; + +comfsm_action_4_reload_obj: + SWPS_DEBUG("FSM action: %s reload.\n", self->swp_name); + self->type = new_type; + return_val = reload_transvr_obj(self, new_type); + goto comfsm_action_4_identify_event; + +comfsm_action_4_identify_event: + switch (return_val) { + case EVENT_TRANSVR_INIT_UP: + case EVENT_TRANSVR_TASK_DONE: + goto comfsm_action_4_connected; + + case EVENT_TRANSVR_INIT_DOWN: + goto comfsm_action_4_disconnected; + + case EVENT_TRANSVR_INIT_REINIT: + goto comfsm_action_4_nothing; + + case EVENT_TRANSVR_TASK_WAIT: + self->state = STATE_TRANSVR_INIT; + return ERR_TRANSVR_TASK_BUSY; + + case EVENT_TRANSVR_TASK_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_TASK_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_INIT_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_INIT_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_RELOAD_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_RELOAD_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case EVENT_TRANSVR_EXCEP_ISOLATED: + goto comfsm_action_4_isolate_obj; + + default: + SWPS_INFO("%s detect undefined event:%d.\n", self->swp_name, return_val); + goto comfsm_action_4_unexpected; + } + +comfsm_action_4_nothing: + SWPS_DEBUG("FSM action: %s do nothing.\n", self->swp_name); + return 0; + +comfsm_action_4_connected: + SWPS_DEBUG("FSM action: %s Connected.\n", self->swp_name); + self->state = STATE_TRANSVR_CONNECTED; + self->type = new_type; + self->send_uevent(self, KOBJ_ADD); + _transvr_clean_retry(self); + return 0; + +comfsm_action_4_disconnected: + SWPS_DEBUG("FSM action: %s Disconnected. \n", self->swp_name); + self->state = STATE_TRANSVR_DISCONNECTED; + self->temp = EVENT_TRANSVR_TASK_DONE; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_retry(self); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNPLUGGED; + +comfsm_action_4_report_i2c_crash: + SWPS_DEBUG("FSM action: %s report I2C crash.\n", self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_I2C_CRASH; + +comfsm_action_4_isolate_obj: + SWPS_DEBUG("FSM action: %s isolate.\n", self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return ERR_TRNASVR_BE_ISOLATED; + +comfsm_action_4_unexpected: + SWPS_INFO("FSM action: %s unexpected.\n", self->swp_name); + SWPS_INFO("Dump: :%d :0x%02x :%d :0x%02x\n", + old_state, old_type, new_state, new_type); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNEXCPT; +} + + +int +fake_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +int +fake_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +/* ========== Object functions for Initial procedure ========== + */ +int +transvr_init_common(struct transvr_obj_s *self){ + /* Nothing to update */ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_fake(struct transvr_obj_s *self){ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_sfp(struct transvr_obj_s *self){ + + int tmp_val = DEBUG_TRANSVR_INT_VAL; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_msg = "ERR"; + + self->info = sft_detect_transvr_class(self); + /* Disable auto_config */ + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + /* Handle multi-rate */ + err_code = initfunc_sfp_handle_multi_rate_mode(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_multi_rate_mode fail!"; + goto err_transvr_init_sfp_1; + } + /* Handle 1G- RJ45 */ + tmp_val = err_code; + err_code = initfunc_sfp_handle_1g_rj45(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_1g_rj45 fail!"; + goto err_transvr_init_sfp_1; + } + tmp_val = (tmp_val > err_code ? tmp_val : err_code); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_sfp_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_code, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp(struct transvr_obj_s *self){ + + int err = EVENT_TRANSVR_EXCEP_EXCEP; + char *emsg = "ERR"; + + self->info = qsft_detect_transvr_class(self); + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + err = initfunc_qsfp_handle_power_mode(self); + if (err < 0){ + emsg = "initfunc_qsfp_handle_tx_disable fail!"; + goto err_transvr_init_qsfp; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, emsg, err, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp28(struct transvr_obj_s *self){ + + int tmp_val = EVENT_TRANSVR_EXCEP_EXCEP; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_msg = "ERR"; + + /* Handle QSFP common */ + err_val = transvr_init_qsfp(self); + if (err_val < 0){ + err_msg = "transvr_init_qsfp fail!"; + goto err_transvr_init_qsfp28_1; + } + /* Disable auto_config */ + if (!self->auto_config) { + return err_val; + } + /* Handle CDR */ + tmp_val = err_val; + err_val = initfunc_qsfp28_handle_cdr(self); + if (err_val < 0){ + err_msg = "Handle CDR fail!"; + goto err_transvr_init_qsfp28_1; + } + tmp_val = (tmp_val > err_val ? tmp_val : err_val); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp28_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== Object Initial handler ========== + */ +static int +_is_transvr_valid(struct transvr_obj_s *self, + int type, + int state) { + /* [Return] + * 0 : OK, inserted + * EVENT_TRANSVR_INIT_DOWN : OK, removed + * EVENT_TRANSVR_INIT_FAIL : Outside error, type doesn't supported + * EVENT_TRANSVR_EXCEP_INIT : Internal error, state undefined + */ + switch (type) { + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + break; + default: + SWPS_INFO("detect undefined type:0x%02x on %s\n", + type, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; + } + switch (state) { + case STATE_TRANSVR_DISCONNECTED: + return EVENT_TRANSVR_INIT_DOWN; + case STATE_TRANSVR_INIT: + case STATE_TRANSVR_CONNECTED: + case STATE_TRANSVR_SWAPPED: + break; + default: + SWPS_INFO("detect undefined state:%d on %s\n", + state, self->swp_name); + return EVENT_TRANSVR_EXCEP_INIT; + } + return 0; +} + + +static int +_is_transvr_hw_ready(struct transvr_obj_s *self, + int type){ + /* [Return] + * EVENT_TRANSVR_TASK_DONE : Ready + * EVENT_TRANSVR_TASK_WAIT : Not ready + * EVENT_TRANSVR_INIT_FAIL : Error + */ + int addr = DEBUG_TRANSVR_INT_VAL; + int page = DEBUG_TRANSVR_INT_VAL; + int offs = DEBUG_TRANSVR_INT_VAL; + int bit = DEBUG_TRANSVR_INT_VAL; + int ready = DEBUG_TRANSVR_INT_VAL; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t ab_val = DEBUG_TRANSVR_HEX_VAL; + + switch (type) { + case TRANSVR_TYPE_SFP: + addr = VAL_TRANSVR_8472_READY_ADDR; + page = VAL_TRANSVR_8472_READY_PAGE; + offs = VAL_TRANSVR_8472_READY_OFFSET; + bit = VAL_TRANSVR_8472_READY_BIT; + ready = VAL_TRANSVR_8472_READY_VALUE; + ab_val = VAL_TRANSVR_8472_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + addr = VAL_TRANSVR_8436_READY_ADDR; + page = VAL_TRANSVR_8436_READY_PAGE; + offs = VAL_TRANSVR_8436_READY_OFFSET; + bit = VAL_TRANSVR_8436_READY_BIT; + ready = VAL_TRANSVR_8436_READY_VALUE; + ab_val = VAL_TRANSVR_8436_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + return EVENT_TRANSVR_TASK_DONE; + + default: + emsg = "unexpected case"; + goto err_is_transvr_hw_ready; + } + /* Select target page */ + err = _common_setup_page(self, addr, page, offs, 1, 0); + if (err < 0) { + emsg = "setup page fail"; + goto err_is_transvr_hw_ready; + } + /* Check feature supported + * [Note] + * Some of transceiver/cables doesn't support "Status Indicators" + * (ex:DAC, RJ45 copper SFP ...etc). In these case, we bypass the + * step of checking Status Indicators, then state machine will take + * the following handle procedure. + */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (err < 0) { + emsg = "doesn't support Status Indicators"; + goto bypass_is_transvr_hw_ready; + } + /* Filter abnormal case */ + if (err == ab_val) { + emsg = "detect using unusual definition."; + goto bypass_is_transvr_hw_ready; + } + /* Get Status Indicators */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, offs); + if (err < 0) { + emsg = "detect current value fail"; + goto err_is_transvr_hw_ready; + } + if ((err & (1<:%d\n", __func__, emsg, type); + return EVENT_TRANSVR_TASK_DONE; + +err_is_transvr_hw_ready: + SWPS_DEBUG("%s: %s :%d\n", __func__, emsg, type); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_is_transvr_support_ctle(struct transvr_obj_s *self) { + + switch (self->info) { + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return 1; + default: + break; + } + return 0; +} + + +static int +_transvr_init_handler(struct transvr_obj_s *self){ + + int detect[2]; + int d_state = STATE_TRANSVR_UNEXCEPTED; + int d_type = TRANSVR_TYPE_ERROR; + int result = ERR_TRANSVR_UNINIT; + int retry = 6; /* (6+1) x 0.3 = 2.1s > spec:2.0s */ + int elimit = 63; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Clean and check callback */ + self->state = STATE_TRANSVR_INIT; + if (self->init == NULL) { + snprintf(emsg, elimit, "init() is null"); + goto initer_err_case_unexcept_0; + } + if (self->clean == NULL) { + snprintf(emsg, elimit, "clean() is null"); + goto initer_err_case_unexcept_0; + } + self->clean(self); + + /* Detect transceiver information */ + result = detect_transvr_state(self, detect); + if (result < 0) { + snprintf(emsg, elimit, "detect_transvr_state() fail"); + switch (result) { + case ERR_TRANSVR_I2C_CRASH: + goto initer_err_case_i2c_ceash; + case ERR_TRNASVR_BE_ISOLATED: + goto initer_err_case_be_isolated; + + case ERR_TRANSVR_UNEXCPT: + default: + break; + } + goto initer_err_case_retry_1; + } + d_state = detect[0]; + d_type = detect[1]; + + /* Verify transceiver type and state */ + switch (_is_transvr_valid(self, d_type, d_state)) { + case 0: + break; + case EVENT_TRANSVR_INIT_DOWN: + goto initer_ok_case_down;; + case EVENT_TRANSVR_INIT_FAIL: + snprintf(emsg, elimit, "transceiver type doesn't support"); + goto initer_err_case_alarm_to_user; + case EVENT_TRANSVR_EXCEP_INIT: + default: + goto initer_err_case_unexcept_1; + } + + /* Handle reload case */ + if (self->type != d_type){ + /* This is the protect mechanism. Normally, This case will not happen. + * When State machine detect swap event during initial, It will trigger + * reload function to ensure type correct. */ + if (_reload_transvr_obj(self, d_type) < 0){ + snprintf(emsg, elimit, "reload object fail"); + goto initer_err_case_unexcept_1; + } + } + + /* Check transceiver HW initial ready */ + switch (_is_transvr_hw_ready(self, d_type)) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_err_case_retry_1; + case EVENT_TRANSVR_INIT_FAIL: + default: + goto initer_err_case_unexcept_1; + } + + /* Try to update all and check */ + if (self->update_all(self, 1) < 0){ + /* For some transceiver, EEPROME has lag issues during initial stage. + * In this case, we set status back to STATE_TRANSVR_NEW, than it will + * be checked in next polling cycle. */ + goto initer_err_case_retry_1; + } + + /* Execute init() call back */ + result = self->init(self); + switch (result) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_ok_case_wait; + + default: + snprintf(emsg, elimit, "undefined init() return:%d\n", result); + goto initer_err_case_unexcept_1; + } + goto initer_ok_case_up; + + +initer_ok_case_wait: + self->dump_all(self); + return EVENT_TRANSVR_TASK_WAIT; + +initer_ok_case_up: + self->state = STATE_TRANSVR_CONNECTED; + self->temp = 0; + self->dump_all(self); + return EVENT_TRANSVR_INIT_UP; + +initer_ok_case_down: + self->temp = 0; + self->state = STATE_TRANSVR_DISCONNECTED; + return EVENT_TRANSVR_INIT_DOWN; + +initer_err_case_i2c_ceash: + SWPS_DEBUG("%s: %s :%s :I2C crash\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_I2C_CRASH; + +initer_err_case_be_isolated: + SWPS_DEBUG("%s: %s :%s :isolated\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return EVENT_TRANSVR_EXCEP_ISOLATED; + +initer_err_case_retry_1: + SWPS_DEBUG("%s: %s :%s :retry\n", + __func__, emsg, self->swp_name); + if (_transvr_handle_retry(self, retry) == 0) { + self->state = STATE_TRANSVR_NEW; + return EVENT_TRANSVR_INIT_REINIT; + } + goto initer_err_case_alarm_to_user; + +initer_err_case_unexcept_1: + self->clean(self); +initer_err_case_unexcept_0: + self->state = STATE_TRANSVR_UNEXCEPTED; + if (_is_except_happened_4_pmode(self, d_state) && + (self->mode == TRANSVR_MODE_POLLING) ){ + SWPS_INFO("%s: %s :%s\n", __func__, emsg, self->swp_name); + SWPS_INFO("Dump: :%d :%d :%d :%d\n", + self->state, self->type, d_state, d_type); + } + return EVENT_TRANSVR_INIT_FAIL; + +initer_err_case_alarm_to_user: + SWPS_DEBUG("%s: %s :%s :alarm_to_user\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard"); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== Object functions for Clean procedure ========== + */ +int +_transvr_clean_handler(struct transvr_obj_s *self){ + + int retval = DEBUG_TRANSVR_INT_VAL; + + if (!self->clean) { + SWPS_ERR("%s: %s clean() is NULL.\n", + __func__, self->swp_name); + return EVENT_TRANSVR_TASK_FAIL; + } + retval = self->clean(self); + if (retval != EVENT_TRANSVR_TASK_DONE){ + SWPS_ERR("%s: %s clean() fail. [ERR]:%d\n", + __func__, self->swp_name, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_transvr_clean(struct transvr_obj_s *self){ + + transvr_task_free_all(self); + transvr_cache_free_all(self); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +qsfp_transvr_clean(struct transvr_obj_s *self){ + + int retval; + int lpower_config = 1; + + retval = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (retval < 0){ + SWPS_ERR("%s: Set lpmod fail! :%d\n", + __func__, retval); + return retval; + } + retval = common_transvr_clean(self); + if (retval < 0){ + SWPS_ERR("%s: common_transvr_clean fail! :%d\n", + __func__, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +fake_transvr_clean(struct transvr_obj_s *self){ + + return EVENT_TRANSVR_TASK_DONE; +} + + +/* ========== Object functions for check and update ========== + */ +int +common_transvr_check(struct transvr_obj_s *self){ + + char fun_str[32] = "common_transvr_check"; + + if (self->mode != TRANSVR_MODE_POLLING) { + SWPS_ERR("%s: mode:%d is not TRANSVR_MODE_POLLING\n", + fun_str, self->mode); + return ERR_TRANSVR_UNEXCPT; + } + /* Trigger delay task */ + transvr_task_run_all(self); + /* Trigger state machine to check and update */ + return self->fsm_4_polling(self, fun_str); +} + + +int +fake_transvr_check(struct transvr_obj_s *self){ + return 0; +} + + +/* ========== Functions for Factory pattern ========== + */ +static int +setup_transvr_public_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = unsupported_get_func; + self->get_br = common_get_br; + self->get_len_sm = sfp_get_len_sm; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = sfp_get_comp_eth_1; + self->get_comp_eth_10 = sfp_get_comp_eth_10; + self->get_comp_eth_10_40 = unsupported_get_func; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = sfp_get_rate_id; + self->get_soft_rs0 = sfp_get_soft_rs0; + self->get_soft_rs1 = sfp_get_soft_rs1; + self->get_info = common_get_info; + self->get_if_type = sfp_get_if_type; + self->get_if_speed = sfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = sfp_get_transvr_temp; + self->get_curr_vol = sfp_get_transvr_voltage; + self->get_soft_rx_los = unsupported_get_func2; + self->get_soft_tx_disable = unsupported_get_func2; + self->get_soft_tx_fault = unsupported_get_func2; + self->get_auto_tx_disable = unsupported_get_func2; + self->get_tx_bias = sfp_get_transvr_tx_bias; + self->get_tx_power = sfp_get_transvr_tx_power; + self->get_rx_power = sfp_get_transvr_rx_power; + self->get_tx_eq = sfp_get_transvr_tx_eq; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = sfp_get_transvr_rx_em; + self->get_wavelength = sfp_get_wavelength; + self->get_extphy_offset = sfp_get_1g_rj45_extphy_offset; + self->get_extphy_reg = sfp_get_1g_rj45_extphy_reg; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = sfp_set_soft_rs0; + self->set_soft_rs1 = sfp_set_soft_rs1; + self->set_soft_tx_disable = unsupported_set_func; + self->set_auto_tx_disable = unsupported_set_func; + self->set_tx_eq = sfp_set_tx_eq; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = sfp_set_rx_em; + self->set_extphy_offset = sfp_set_1g_rj45_extphy_offset; + self->set_extphy_reg = sfp_set_1g_rj45_extphy_reg; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = unsupported_get_func2; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = unsupported_get_func2; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = unsupported_set_func; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = unsupported_set_func; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = qsfp_get_cdr; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = qsfp_get_transvr_tx_eq; + self->get_rx_am = qsfp_get_transvr_rx_am; + self->get_rx_em = qsfp_get_transvr_rx_em; + self->get_wavelength = qsfp_get_wavelength; + self->get_extphy_offset = unsupported_get_func2; + self->get_extphy_reg = unsupported_get_func2; + self->set_cdr = qsfp_set_cdr; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = qsfp_set_tx_eq; + self->set_rx_am = qsfp_set_rx_am; + self->set_rx_em = qsfp_set_rx_em; + self->set_extphy_offset = unsupported_set_func; + self->set_extphy_reg = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_FAKE: + self->get_id = fake_get_hex; + self->get_ext_id = fake_get_hex; + self->get_connector = fake_get_hex; + self->get_vendor_name = fake_get_str; + self->get_vendor_pn = fake_get_str; + self->get_vendor_rev = fake_get_str; + self->get_vendor_sn = fake_get_str; + self->get_power_cls = fake_get_int; + self->get_br = fake_get_hex; + self->get_len_sm = fake_get_int; + self->get_len_smf = fake_get_int; + self->get_len_om1 = fake_get_int; + self->get_len_om2 = fake_get_int; + self->get_len_om3 = fake_get_int; + self->get_len_om4 = fake_get_int; + self->get_comp_rev = fake_get_hex; + self->get_comp_eth_1 = fake_get_hex; + self->get_comp_eth_10 = fake_get_hex; + self->get_comp_eth_10_40 = fake_get_hex; + self->get_comp_extend = fake_get_hex; + self->get_cdr = fake_get_hex; + self->get_rate_id = fake_get_hex; + self->get_soft_rs0 = fake_get_binary; + self->get_soft_rs1 = fake_get_binary; + self->get_info = fake_get_int; + self->get_if_type = fake_get_str; + self->get_if_speed = fake_get_str; + self->get_if_lane = fake_get_str; + self->get_curr_temp = fake_get_str; + self->get_curr_vol = fake_get_str; + self->get_soft_rx_los = fake_get_str; + self->get_soft_tx_disable = fake_get_str; + self->get_soft_tx_fault = fake_get_str; + self->get_auto_tx_disable = fake_get_str; + self->get_tx_bias = fake_get_str; + self->get_tx_power = fake_get_str; + self->get_rx_power = fake_get_str; + self->get_tx_eq = fake_get_str; + self->get_rx_am = fake_get_str; + self->get_rx_em = fake_get_str; + self->get_wavelength = fake_get_str; + self->get_extphy_offset = fake_get_str; + self->get_extphy_reg = fake_get_str; + self->set_cdr = fake_set_hex; + self->set_soft_rs0 = fake_set_int; + self->set_soft_rs1 = fake_set_int; + self->set_soft_tx_disable = fake_set_int; + self->set_auto_tx_disable = fake_set_int; + self->set_tx_eq = fake_set_int; + self->set_rx_am = fake_set_int; + self->set_rx_em = fake_set_int; + self->set_extphy_offset = fake_set_hex; + self->set_extphy_reg = fake_set_hex; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_transvr_private_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->init = transvr_init_sfp; + self->clean = common_transvr_clean; + self->check = common_transvr_check; + self->update_all = _sfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = sfp_send_uevent; + self->dump_all = sfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->init = transvr_init_qsfp; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->init = transvr_init_qsfp28; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_FAKE: + self->init = transvr_init_fake; + self->clean = fake_transvr_clean; + self->check = fake_transvr_check; + self->update_all = fake_transvr_update; + self->fsm_4_direct = fake_fsm_4_direct_mode; + self->fsm_4_polling = fake_fsm_4_polling_mode; + self->send_uevent = fake_send_uevent; + self->dump_all = fake_transvr_dump; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static struct eeprom_map_s * +get_eeprom_map(int transvr_type){ + + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + return &eeprom_map_sfp; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + return &eeprom_map_qsfp; + case TRANSVR_TYPE_QSFP_28: + return &eeprom_map_qsfp28; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return NULL; +} + + +static int +setup_transvr_ssize_attr(char *swp_name, + struct transvr_obj_s *self, + struct eeprom_map_s *map_p, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int chan_id, + int run_mode){ + switch (run_mode){ + case TRANSVR_MODE_DIRECT: /* Direct access device mode */ + case TRANSVR_MODE_POLLING: /* Polling mode, read from cache */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = DEBUG_TRANSVR_INT_VAL; + return -1; + } + self->eeprom_map_p = map_p; + self->ioexp_obj_p = ioexp_obj_p; + self->ioexp_virt_offset = ioexp_virt_offset; + self->chan_id = chan_id; + self->layout = transvr_type; + self->type = transvr_type; + self->chipset_type = chipset_type; + self->state = STATE_TRANSVR_NEW; + self->info = STATE_TRANSVR_NEW; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + strncpy(self->swp_name, swp_name, 32); + mutex_init(&self->lock); + return 0; +} + + +static int +setup_transvr_dsize_attr(struct transvr_obj_s *self){ + + char *emsg = DEBUG_TRANSVR_STR_VAL; + + self->vendor_name = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_name){ + emsg = "vendor_name"; + goto err_setup_d_attr; + } + self->vendor_pn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_pn){ + emsg = "vendor_pn"; + goto err_setup_d_attr; + } + self->vendor_rev = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_rev){ + emsg = "vendor_rev"; + goto err_setup_d_attr; + } + self->vendor_sn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_sn){ + emsg = "vendor_sn"; + goto err_setup_d_attr; + } + self->worker_p = NULL; + return 0; + +err_setup_d_attr: + SWPS_ERR("%s: %s kzalloc fail!", __func__, emsg); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_i2c_client(struct transvr_obj_s *self){ + + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + adap = i2c_get_adapter(self->chan_id); + if(!adap){ + snprintf(err_msg, sizeof(err_msg), + "can not get adap:%d", self->chan_id); + goto err_setup_i2c_client; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + snprintf(err_msg, sizeof(err_msg), + "can not kzalloc client:%d", self->chan_id); + goto err_setup_i2c_client; + } + client->adapter = adap; + self->i2c_client_p = client; + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + return 0; + +err_setup_i2c_client: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return ERR_TRANSVR_UNEXCPT; +} + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode){ + + struct transvr_obj_s *result_p; + struct eeprom_map_s *map_p; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Allocate transceiver object */ + map_p = get_eeprom_map(transvr_type); + if (!map_p){ + snprintf(err_msg, sizeof(err_msg), + "Invalid transvr_type:%d", transvr_type); + goto err_create_transvr_fail; + } + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_create_transvr_fail; + } + /* Prepare static size attributes */ + if (setup_transvr_ssize_attr(swp_name, + result_p, + map_p, + ioexp_obj_p, + ioexp_virt_offset, + transvr_type, + chipset_type, + chan_id, + run_mode) < 0){ + goto err_create_transvr_sattr_fail; + } + /* Prepare dynamic size attributes */ + if (setup_transvr_dsize_attr(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_public_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_private_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare i2c client object */ + if (setup_i2c_client(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + return result_p; + +err_create_transvr_dattr_fail: + kfree(result_p->vendor_sn); + kfree(result_p->vendor_rev); + kfree(result_p->vendor_pn); + kfree(result_p->vendor_name); +err_create_transvr_sattr_fail: + kfree(result_p); +err_create_transvr_fail: + SWPS_ERR("%s: %s :%d :%d :%d\n", + __func__, err_msg, chan_id, ioexp_virt_offset, transvr_type); + return NULL; +} + + +static int +_reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + struct eeprom_map_s *new_map_p; + struct eeprom_map_s *old_map_p = self->eeprom_map_p; + struct i2c_client *old_i2c_p = self->i2c_client_p; + int old_type = self->type; + + /* Change state to STATE_TRANSVR_INIT */ + self->state = STATE_TRANSVR_INIT; + self->type = new_type; + /* Replace EEPROME map */ + new_map_p = get_eeprom_map(new_type); + if (!new_map_p){ + goto err_private_reload_func_1; + } + self->eeprom_map_p = new_map_p; + /* Reload i2c client */ + if (setup_i2c_client(self) < 0){ + goto err_private_reload_func_2; + } + /* Replace call back functions */ + if (setup_transvr_public_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + if (setup_transvr_private_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + kfree(old_i2c_p); + return 0; + +err_private_reload_func_3: + SWPS_INFO("%s: init() fail!\n", __func__); + kfree(old_i2c_p); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return -2; + +err_private_reload_func_2: + self->eeprom_map_p = old_map_p; + self->i2c_client_p = old_i2c_p; +err_private_reload_func_1: + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = old_type; + SWPS_INFO("%s fail! :0x%02x\n", __func__, new_type); + return -1; +} + + +static int +reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + int result_val = ERR_TRANSVR_UNEXCPT; + + /* Reload phase */ + result_val = _reload_transvr_obj(self, new_type); + if (result_val < 0){ + SWPS_INFO("%s: reload phase fail! :%d\n", + __func__, result_val); + return EVENT_TRANSVR_RELOAD_FAIL; + } + /* Initial phase */ + result_val = _transvr_init_handler(self); + if (result_val < 0){ + SWPS_INFO("%s: initial phase fail! :%d\n", + __func__, result_val); + } + return result_val; +} + + +int +isolate_transvr_obj(struct transvr_obj_s *self) { + + self->state = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s be isolated\n", __func__, self->swp_name); + return 0; +} + + +int +resync_channel_tier_2(struct transvr_obj_s *self) { + + int val = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_ISOLATED) { + return 0; + } + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + val = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (val < 0) { + return -1; + } + return 0; +} + + +/* ----------------------------------------- + * ToDo List + * ----------------------------------------- + * 1. _sfp_detect_class_by_feature() + * => Need check ACC use case. + * 2. _sfp_detect_class_by_1g_ethernet() + * => Need check 0.1G use case. + * 3. Loopback transceiver use case. + * => Less much data + * 4. _qsfp_detect_class_by_extend_comp() + * => Verify 100G CWDM4 + * => Verify Obsolete (assigned before 100G CWDM4 MSA required FEC) + * => Verify 100G CLR4 + * => Verify 100GE-DWDM2 + * => Verify 40G PSM4 Parallel SMF + * => Verify 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. + * => Verify 100G ACC or 25GAUI C2M ACC. + * => Verify 25GBASE-LR + * => Verify 40G Active Cable (XLPPI) + */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.h new file mode 100644 index 000000000000..f17b7fde71b1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/modules/transceiver.h @@ -0,0 +1,815 @@ +/* + * 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. + */ + +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* advanced features control */ +#define TRANSVR_INFO_DUMP_ENABLE (1) +#define TRANSVR_INFO_CACHE_ENABLE (1) +#define TRANSVR_UEVENT_ENABLE (1) + +/* Transceiver type define */ +#define TRANSVR_TYPE_UNKNOW_1 (0x00) +#define TRANSVR_TYPE_UNKNOW_2 (0xff) +#define TRANSVR_TYPE_SFP (0x03) /* Define for SFP, SFP+, SFP28 */ +#define TRANSVR_TYPE_QSFP (0x0c) +#define TRANSVR_TYPE_QSFP_PLUS (0x0d) +#define TRANSVR_TYPE_QSFP_28 (0x11) +#define TRANSVR_TYPE_UNPLUGGED (0xfa) /* Define for ERROR handle */ +#define TRANSVR_TYPE_FAKE (0xfc) /* Define for ERROR handle */ +#define TRANSVR_TYPE_INCONSISTENT (0xfd) /* Define for ERROR handle */ +#define TRANSVR_TYPE_ERROR (0xfe) /* Define for ERROR handle */ + +/* Transceiver class for base info */ +#define TRANSVR_CLASS_UNSPECIFIED (0) +#define TRANSVR_CLASS_ERROR (-26001) +#define TRANSVR_CLASS_1G (26001) +#define TRANSVR_CLASS_10G (26011) +#define TRANSVR_CLASS_25G (26021) +#define TRANSVR_CLASS_40G (26041) +#define TRANSVR_CLASS_100G (26101) +#define TRANSVR_CLASS_NO_SPERARABLE (26901) +#define TRANSVR_CLASS_EXTEND_COMP (26902) +/* Transceiver class for Optical 1G */ +#define TRANSVR_CLASS_OPTICAL (27000) +#define TRANSVR_CLASS_OPTICAL_100 (27001) +#define TRANSVR_CLASS_OPTICAL_1G (27002) +#define TRANSVR_CLASS_OPTICAL_1G_AOC (27003) +#define TRANSVR_CLASS_OPTICAL_1G_SX (27004) +#define TRANSVR_CLASS_OPTICAL_1G_LX (27005) +#define TRANSVR_CLASS_OPTICAL_1G_EX (27006) +/* Transceiver class for Optical 10G */ +#define TRANSVR_CLASS_OPTICAL_10G (27010) +#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011) +#define TRANSVR_CLASS_OPTICAL_10G_S_SR (27012) +#define TRANSVR_CLASS_OPTICAL_10G_S_LR (27013) +#define TRANSVR_CLASS_OPTICAL_10G_S_ER (27014) +#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015) +#define TRANSVR_CLASS_OPTICAL_10G_Q_SR (27016) +#define TRANSVR_CLASS_OPTICAL_10G_Q_LR (27017) +#define TRANSVR_CLASS_OPTICAL_10G_Q_ER (27018) +/* Transceiver class for Optical 25G */ +#define TRANSVR_CLASS_OPTICAL_25G (27020) +#define TRANSVR_CLASS_OPTICAL_25G_AOC (27021) +#define TRANSVR_CLASS_OPTICAL_25G_SR (27022) +#define TRANSVR_CLASS_OPTICAL_25G_LR (27023) +#define TRANSVR_CLASS_OPTICAL_25G_ER (27024) +/* Transceiver class for Optical 40G */ +#define TRANSVR_CLASS_OPTICAL_40G (27040) +#define TRANSVR_CLASS_OPTICAL_40G_AOC (27041) +#define TRANSVR_CLASS_OPTICAL_40G_SR4 (27042) +#define TRANSVR_CLASS_OPTICAL_40G_LR4 (27043) +#define TRANSVR_CLASS_OPTICAL_40G_ER4 (27044) +/* Transceiver class for Optical 100G */ +#define TRANSVR_CLASS_OPTICAL_100G (27100) +#define TRANSVR_CLASS_OPTICAL_100G_AOC (27101) +#define TRANSVR_CLASS_OPTICAL_100G_SR4 (27102) +#define TRANSVR_CLASS_OPTICAL_100G_LR4 (27103) +#define TRANSVR_CLASS_OPTICAL_100G_ER4 (27104) +#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105) +/* Transceiver class for Copper */ +#define TRANSVR_CLASS_COPPER (28000) +#define TRANSVR_CLASS_COPPER_L1_1G (28001) +#define TRANSVR_CLASS_COPPER_L1_10G (28011) +#define TRANSVR_CLASS_COPPER_L4_10G (28012) +#define TRANSVR_CLASS_COPPER_L1_25G (28021) +#define TRANSVR_CLASS_COPPER_L4_40G (28041) +#define TRANSVR_CLASS_COPPER_L4_100G (28101) +/* Transceiver class for Base-T */ +#define TRANSVR_CLASS_BASE_T_1000 (29001) +#define TRANSVR_CLASS_BASE_T_1000_up (29002) +/* For uevent message */ +#define TRANSVR_UEVENT_KEY_IF "IF_TYPE" +#define TRANSVR_UEVENT_KEY_SP "IF_SPEED" +#define TRANSVR_UEVENT_KEY_LANE "IF_LANE" +#define TRANSVR_UEVENT_UNKNOW "UNKNOW" +#define TRANSVR_IF_KR "KR" +#define TRANSVR_IF_KR4 "KR4" +#define TRANSVR_IF_SR "SR" +#define TRANSVR_IF_SR4 "SR4" +#define TRANSVR_IF_SFI "SFI" +#define TRANSVR_IF_IF_GMII "GMII" +#define TRANSVR_IF_IF_XGMII "XGMII" +#define TRANSVR_IF_SP_100 "100" +#define TRANSVR_IF_SP_1G "1000" +#define TRANSVR_IF_SP_10G "10000" +#define TRANSVR_IF_SP_25G "25000" +#define TRANSVR_IF_SP_40G "40000" +#define TRANSVR_IF_SP_100G "100000" + +/* Transceiver mode define */ +#define TRANSVR_MODE_DIRECT (21000) +#define TRANSVR_MODE_POLLING (21001) + +/* Transceiver state define + * [Note] + * 1. State is used to represent the state of "Transceiver" and "Object". + * 2. State for different target has different means. The description as following: + */ +#define STATE_TRANSVR_CONNECTED (0) /* [Transvr]:Be plugged in. [Obj]:Link up, and work normally. */ +#define STATE_TRANSVR_NEW (-100) /* [Transvr]:(Not used) [Obj]:Create */ +#define STATE_TRANSVR_INIT (-101) /* [Transvr]:Be plugged in. [Obj]:Link up, and in initial process. */ +#define STATE_TRANSVR_ISOLATED (-102) /* [Transvr]:Be plugged in. [Obj]:Isolate, and not provide service. */ +#define STATE_TRANSVR_SWAPPED (-200) /* [Transvr]:Be plugged in. [Obj]:(Not used) */ +#define STATE_TRANSVR_DISCONNECTED (-300) /* [Transvr]:Un-plugged. [Obj]:Link down, and not provide service. */ +#define STATE_TRANSVR_UNEXCEPTED (-901) /* [Transvr]:Any [Obj]:Any, and not in expect case. */ + +/* Task state define */ +#define STATE_T_TASK_WAIT (110) +#define STATE_T_TASK_DONE (0) +#define STATE_T_TASK_INIT (-110) +#define STATE_T_TASK_FAIL (-410) + + +/* Event for task handling */ +#define EVENT_TRANSVR_TASK_WAIT (2101) +#define EVENT_TRANSVR_TASK_DONE (0) +#define EVENT_TRANSVR_TASK_FAIL (-2101) +/* Event for initial handling */ +#define EVENT_TRANSVR_INIT_UP (2201) +#define EVENT_TRANSVR_INIT_DOWN (1) +#define EVENT_TRANSVR_INIT_REINIT (-2201) +#define EVENT_TRANSVR_INIT_FAIL (-2202) +/* Event for others */ +#define EVENT_TRANSVR_RELOAD_FAIL (-2301) +#define EVENT_TRANSVR_EXCEP_INIT (-2401) +#define EVENT_TRANSVR_EXCEP_UP (-2402) +#define EVENT_TRANSVR_EXCEP_DOWN (-2403) +#define EVENT_TRANSVR_EXCEP_SWAP (-2404) +#define EVENT_TRANSVR_EXCEP_EXCEP (-2405) +#define EVENT_TRANSVR_EXCEP_ISOLATED (-2406) +#define EVENT_TRANSVR_I2C_CRASH (-2501) + +/* Transceiver error code define */ +#define ERR_TRANSVR_UNINIT (-201) +#define ERR_TRANSVR_UNPLUGGED (-202) +#define ERR_TRANSVR_ABNORMAL (-203) +#define ERR_TRANSVR_NOSTATE (-204) +#define ERR_TRANSVR_NOTSUPPORT (-205) +#define ERR_TRANSVR_BADINPUT (-206) +#define ERR_TRANSVR_UPDATE_FAIL (-207) +#define ERR_TRANSVR_RELOAD_FAIL (-208) +#define ERR_TRANSVR_INIT_FAIL (-209) +#define ERR_TRANSVR_UNDEFINED (-210) +#define ERR_TRANSVR_TASK_FAIL (-211) +#define ERR_TRANSVR_TASK_BUSY (-212) +#define ERR_TRANSVR_UEVENT_FAIL (-213) +#define ERR_TRANSVR_FUNC_DISABLE (-214) +#define ERR_TRANSVR_I2C_CRASH (-297) +#define ERR_TRNASVR_BE_ISOLATED (-298) +#define ERR_TRANSVR_UNEXCPT (-299) + +/* For debug */ +#define DEBUG_TRANSVR_INT_VAL (-99) +#define DEBUG_TRANSVR_HEX_VAL (0xfe) +#define DEBUG_TRANSVR_STR_VAL "ERROR" + +/* For system internal */ +#define VAL_TRANSVR_COMID_ARREESS (0x50) +#define VAL_TRANSVR_COMID_OFFSET (0x00) +#define VAL_TRANSVR_EXTPHY_ADDR_56 (0x56) +#define VAL_TRANSVR_8472_READY_ADDR (0x51) +#define VAL_TRANSVR_8472_READY_PAGE (-1) +#define VAL_TRANSVR_8472_READY_OFFSET (110) +#define VAL_TRANSVR_8472_READY_BIT (0) +#define VAL_TRANSVR_8472_READY_VALUE (0) +#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_READY_ADDR (0x50) +#define VAL_TRANSVR_8436_READY_PAGE (-1) +#define VAL_TRANSVR_8436_READY_OFFSET (2) +#define VAL_TRANSVR_8436_READY_BIT (0) +#define VAL_TRANSVR_8436_READY_VALUE (0) +#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_PWD_ADDR (0x50) +#define VAL_TRANSVR_8436_PWD_PAGE (-1) +#define VAL_TRANSVR_8436_PWD_OFFSET (123) +#define VAL_TRANSVR_PAGE_FREE (-99) +#define VAL_TRANSVR_PAGE_SELECT_OFFSET (127) +#define VAL_TRANSVR_PAGE_SELECT_DELAY (5) +#define VAL_TRANSVR_TASK_RETRY_FOREVER (-999) +#define VAL_TRANSVR_FUNCTION_DISABLE (-1) +#define STR_TRANSVR_SFP "SFP" +#define STR_TRANSVR_QSFP "QSFP" +#define STR_TRANSVR_QSFP_PLUS "QSFP+" +#define STR_TRANSVR_QSFP28 "QSFP28" + +/* For transvr buf len */ +#define LEN_TRANSVR_S_STR (16) +#define LEN_TRANSVR_M_STR (32) +#define LEN_TRANSVR_L_STR (64) + +/* Optical wavelength */ +#define VAL_OPTICAL_WAVELENGTH_SR (850) +#define VAL_OPTICAL_WAVELENGTH_LR (1310) +#define VAL_OPTICAL_WAVELENGTH_ER (1550) + +/* BCM chip type define */ +#define BCM_CHIP_TYPE_TRIDENT_2 (31001) /* Magnolia, Hudson32i, Spruce */ +#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress, Sequoia */ +#define BCM_CHIP_TYPE_TRIDENT_3 (31003) /* Maple */ + +#define BF_CHIP_TYPE_TOFINO (31011) /* Lavender */ + +/* Info from transceiver EEPROM */ +struct eeprom_map_s { + int addr_br; int page_br; int offset_br; int length_br; + int addr_cdr; int page_cdr; int offset_cdr; int length_cdr; + int addr_comp_rev; int page_comp_rev; int offset_comp_rev; int length_comp_rev; + int addr_connector; int page_connector; int offset_connector; int length_connector; + int addr_diag_type; int page_diag_type; int offset_diag_type; int length_diag_type; + int addr_extbr; int page_extbr; int offset_extbr; int length_extbr; + int addr_ext_id; int page_ext_id; int offset_ext_id; int length_ext_id; + int addr_id; int page_id; int offset_id; int length_id; + int addr_len_sm; int page_len_sm; int offset_len_sm; int length_len_sm; + int addr_len_smf; int page_len_smf; int offset_len_smf; int length_len_smf; + int addr_len_om1; int page_len_om1; int offset_len_om1; int length_len_om1; + int addr_len_om2; int page_len_om2; int offset_len_om2; int length_len_om2; + int addr_len_om3; int page_len_om3; int offset_len_om3; int length_len_om3; + int addr_len_om4; int page_len_om4; int offset_len_om4; int length_len_om4; + int addr_option; int page_option; int offset_option; int length_option; + int addr_rate_id; int page_rate_id; int offset_rate_id; int length_rate_id; + int addr_rx_am; int page_rx_am; int offset_rx_am; int length_rx_am; + int addr_rx_em; int page_rx_em; int offset_rx_em; int length_rx_em; + int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los; + int addr_rx_power; int page_rx_power; int offset_rx_power; int length_rx_power; + int addr_soft_rs0; int page_soft_rs0; int offset_soft_rs0; int length_soft_rs0; + int addr_soft_rs1; int page_soft_rs1; int offset_soft_rs1; int length_soft_rs1; + int addr_temp; int page_temp; int offset_temp; int length_temp; + int addr_trancomp; int page_trancomp; int offset_trancomp; int length_trancomp; + int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext; + int addr_tx_bias; int page_tx_bias; int offset_tx_bias; int length_tx_bias; + int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable; + int addr_tx_eq; int page_tx_eq; int offset_tx_eq; int length_tx_eq; + int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault; + int addr_tx_power; int page_tx_power; int offset_tx_power; int length_tx_power; + int addr_vendor_name; int page_vendor_name; int offset_vendor_name; int length_vendor_name; + int addr_vendor_pn; int page_vendor_pn; int offset_vendor_pn; int length_vendor_pn; + int addr_vendor_rev; int page_vendor_rev; int offset_vendor_rev; int length_vendor_rev; + int addr_vendor_sn; int page_vendor_sn; int offset_vendor_sn; int length_vendor_sn; + int addr_voltage; int page_voltage; int offset_voltage; int length_voltage; + int addr_wavelength; int page_wavelength; int offset_wavelength; int length_wavelength; +}; + + +struct transvr_worker_s; + +/* Class of transceiver object */ +struct transvr_obj_s { + + /* ========== Object private property ========== + * [Prop]: id + * [Desc]: Type of serial transceiver. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h + */ + uint8_t id; + + /* [Prop]: connector + * [Desc]: Connector type. + * [Note]: SFP : A0h / 2 + * QSFP: 00h / 130 + */ + uint8_t connector; + + /* [Prop]: transvr_comp + * [Desc]: Transceiver compliance code. + * [Note]: SFP: SFF-8472 + * - Normal : A0h / offset 3-10 + * - Extended: A0h / offset 36 + * QSFP: SFF-8436 & SFF-8636 + * - Normal : 00h / offset 131-138 + * - Extended: 00h / offset 192 + */ + uint8_t transvr_comp[8]; + uint8_t transvr_comp_ext; + + /* [Prop]: vendor_name + * [Desc]: SFP vendor name (ASCII 16 byte char). + * [Note]: ex:FINISAR CORP. + */ + char *vendor_name; + + /* [Prop]: vendor_pn + * [Desc]: Part number provided by SFP vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_pn; + + /* [Prop]: vendor_rev + * [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char). + * [Note]: + */ + char *vendor_rev; + + /* [Prop]: vendor_sn + * [Desc]: Serial number provided by vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_sn; + + /* [Prop]: Extended identifier + * [Desc]: SFP: + * => None + * + * QSFP: + * => This byte contained two information: + * (1) Power consumption class + * (2) CDR function present + * [Note]: Bit description as below: + * [SFP] + * None + * + * [QSFP] + * (1) Power consumption class: + * Class 1: 1.5W (Bit6-7 = 00:) + * Class 2: 2.0W (Bit6-7 = 01:) + * Class 3: 2.5W (Bit6-7 = 10:) + * Class 4: 3.5W (Bit6-7 = 11:) + * Class 5: 4.0W (Bit0-1 = 01:) + * Class 6: 4.5W (Bit0-1 = 10:) + * Class 7: 5.0W (Bit0-1 = 11:) + * (2) CDR function present: + * Bit2: 0 = No CDR in RX + * 1 = CDR present in RX + * Bit3: 0 = No CDR in TX + * 1 = CDR present in TX + */ + uint8_t ext_id; + + /* [Prop]: br + * [Desc]: Nominal bit rate, units of 100 MBits/sec. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh + * has val: 0x67 + * no val : + */ + uint8_t br; + + /* [Prop]: extbr + * [Desc]: Extended br (00h/222) + * [Desc]: Nominal bit rate per channel, units of 250 Mbps. + * Complements. Byte 140. See Table 32A. + */ + uint8_t extbr; + + /* [Prop]: len_sm + * [Desc]: Length (single mode)-(100's)m + * [Note]: This value specifies the link length that is supported by the transceiver + * while operating in compliance with the applicable standards using single mode + * fiber. The value is in units of 100 meters. A value of 255 means that the + * transceiver supports a link length greater than 25.4 km. A value of zero means + * that the transceiver does not support single mode fiber or that the length + * information must be determined from the transceiver technology. + */ + int len_sm; + + /* [Prop]: len_smf + * [Desc]: Length (single mode)-km + * [Note]: Addition to EEPROM data from original GBIC definition. This value specifies + * the link length that is supported by the transceiver while operating in + * compliance with the applicable standards using single mode fiber. The value + * is in units of kilometers. A value of 255 means that the transceiver supports + * a link length greater than 254 km. A value of zero means that the transceiver + * does not support single mode fiber or that the length information must be + * determined from the transceiver technology. + */ + int len_smf; + + /* [Prop]: len_om1 + * [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om1; + + /* [Prop]: len_om2 + * [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om2; + + /* [Prop]: len_om3 + * [Desc]: Length (50um, OM3) + * [Note]: This value specifies link length that is supported by the transceiver while + * operating in compliance with applicable standards using 50 micron multimode + * OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255 + * means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber + * or that the length information must be determined from the transceiver technology. + */ + int len_om3; + + /* [Prop]: len_om4 + * [Desc]: Length (50um, OM4) and Length (Active Cable or Copper) + * [Note]: For optical links, this value specifies link length that is supported by the + * transceiver while operating in compliance with applicable standards using 50 micron + * multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of + * 255 means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber or that + * the length information must be determined from the transceiver codes specified in Table 5-3. + * + * For copper links, this value specifies minimum link length supported by the transceiver + * while operating in compliance with applicable standards using copper cable. For active + * cable, this value represents actual length. The value is in units of 1 meter. A value of 255 + * means the transceiver supports a link length greater than 254 meters. A value of zero means + * the transceiver does not support copper or active cables or the length information must be + * determined from transceiver technology. Further information about cable design, equalization, + * and connectors is usually required to guarantee meeting a particular length requirement. + */ + int len_om4; + + /* [Prop]: comp_rev + * [Desc]: SFF spec revision compliance + * [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver + * complies with. (unsigned integer) + */ + uint8_t comp_rev; + + /* [Prop]: CDR + * [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal + * retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which + * directs traffic around the internal CDR. (Reference: SFF-8636) + * [Note]: value=0xff: ON. + * value=0x00: OFF. + */ + uint8_t cdr; + + /* [Prop]: rate_id + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Addr: A0h / Offset: 13 + * 2. Value description: + * 00h Unspecified + * 01h SFF-8079 (4/2/1G Rate_Select & AS0/AS1) + * 02h SFF-8431 (8/4/2G Rx Rate_Select only) + * 03h Unspecified * + * 04h SFF-8431 (8/4/2G Tx Rate_Select only) + * 05h Unspecified * + * 06h SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) + * 07h Unspecified * + * 08h FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G + * 09h Unspecified * + * 0Ah FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only, + * Low=8G/4G + * 0Bh Unspecified * + * 0Ch FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + * 0Dh Unspecified * + * 0Eh 10/8G Rx and Tx Rate_Select controlling the operation or locking + * modes of the internal signal conditioner, retimer or CDR, according + * to the logic table defined in Table 10-2, High Bit Rate + * (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode, + * the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11) + * and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1. + * 0Fh Unspecified * + * 10h-FFh Unallocated + */ + int rate_id; + + /* [Prop]: soft_rs0 + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Writing '1' selects full bandwidth operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 110 / Bit: 3 + */ + uint8_t soft_rs0; + + /* [Prop]: soft_rs1 + * [Desc]: Soft Rate Select 1(TX). + * [Note]: 1. Writing '1' selects full bandwidth TX operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 118 / Bit: 3 + */ + uint8_t soft_rs1; + + /* [Prop]: diag_type + * [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92) + * [Note]: Description in SFF-8472 as below: + * Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance + * with this document. + * Bit6: Digital diagnostic monitoring implemented (described in this document). + * Must be '1' for compliance with this document. + * Bit5 Internally calibrated + * Bit4 Externally calibrated + * Bit3 Received power measurement type.0 = OMA, 1 = average power + * Bit2 Address change required see section above, "addressing modes" + * Bit1-0 Unallocated + */ + uint8_t diag_type; + + /* [Prop]: curr_temp + * [Desc]: Transceiver Current Temperature (A2h/96-97) + * [Note]: 1. Dependent on diag_type. + * 2. 96: High byte + * 3. 97: Low byte + * 4. This feature only for SFP + */ + uint8_t curr_temp[2]; + + /* [Prop]: curr_vol + * [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23) + * [Note]: 1. Dependent on diag_type. + * 2. 98: High byte + * 3. 99: Low byte + * 4. This feature only for SFP + * 5. Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts + */ + uint8_t curr_voltage[2]; + + /* [Prop]: curr_tx_bias + * [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27) + * [Note]: 1. Dependent on diag_type. + * 2. 100: High byte + * 3. 101: Low byte + * 4. This feature only for SFP + * 5. Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + uint8_t curr_tx_bias[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + uint8_t curr_tx_power[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + uint8_t curr_rx_power[8]; + + /* [Prop]: wavelength + * [Desc]: Wavelength or Copper Cable Attenuation + * [Note]: (Following is info from SFF-8636) + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is a + * 16-bit hex value with Byte 186 as high order byte and Byte 187 as low + * order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. If the free side device is identified as + * copper cable these registers will be used to define the cable attenuation. + * An indication of 0 dB attenuation refers to the case where the attenuation + * is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + uint8_t wavelength[2]; + + /* [Prop]: Amplitude control + * [Desc]: Amplitude control + * [Note]: QSFP28 => SFF-8636 03H Byte-238/239 + */ + uint8_t rx_am[2]; + + /* [Prop]: Emphasis control + * [Desc]: Emphasis control + * [Note]: SFP+/28 => SFF-8472 A2H Byte-115 + * QSFP28 => SFF-8636 03H Byte-236/237 + */ + uint8_t rx_em[2]; + + /* [Prop]: Soft Rx LOS + * [Desc]: Soft Rx LOS which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 3: + * - Bit 0: L-Rx1 LOS + * - Bit 1: L-Rx2 LOS + * - Bit 2: L-Rx3 LOS + * - Bit 3: L-Rx4 LOS + */ + uint8_t rx_los; + + /* [Prop]: Soft Tx Disable + * [Desc]: Soft Tx Disable which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Disable + * - Bit 1: Tx2 Disable + * - Bit 2: Tx3 Disable + * - Bit 3: Tx4 Disable + */ + uint8_t tx_disable; + + /* [Prop]: Soft Tx Fault + * [Desc]: Soft Tx Fault which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Fault + * - Bit 1: Tx2 Fault + * - Bit 2: Tx3 Fault + * - Bit 3: Tx4 Fault + */ + uint8_t tx_fault; + + /* [Prop]: Transceiver EQUALIZATION + * [Desc]: Transceiver EQUALIZATION + * [Note]: SFP+/28 => SFF-8472 A2H Byte-114 + * QSFP28 => SFF-8636 03H Byte-234/235 + */ + uint8_t tx_eq[2]; + + /* [Prop]: OPTION VALUES + * [Desc]: The bits in the option field shall specify the options implemented in the transceiver. + * [Note]: SFP+/28 => SFF-8472 A0H Byte-64/65 + * QSFP+/28 => SFF-8636 00H Byte-193/195 + */ + uint8_t option[3]; + + /* [Prop]: External PHY offset + * [Desc]: It needs to be setup first if you want to access transceiver external phy. + * [Note]: This feature dependent on transceiver. + * Currently, only 1G-RJ45 transceiver supported it. + */ + uint8_t extphy_offset; + + /* ========== Object private property ========== + */ + struct device *transvr_dev_p; + struct eeprom_map_s *eeprom_map_p; + struct i2c_client *i2c_client_p; + struct ioexp_obj_s *ioexp_obj_p; + struct transvr_worker_s *worker_p; + struct mutex lock; + char swp_name[32]; + int auto_config; + int auto_tx_disable; + int chan_id; + int chipset_type; + int curr_page; + int info; + int ioexp_virt_offset; + int lane_id[8]; + int layout; + int mode; + int retry; + int state; + int temp; + int type; + + /* ========== Object public functions ========== + */ + int (*get_id)(struct transvr_obj_s *self); + int (*get_ext_id)(struct transvr_obj_s *self); + int (*get_connector)(struct transvr_obj_s *self); + int (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p); + int (*get_power_cls)(struct transvr_obj_s *self); + int (*get_br)(struct transvr_obj_s *self); + int (*get_len_sm)(struct transvr_obj_s *self); + int (*get_len_smf)(struct transvr_obj_s *self); + int (*get_len_om1)(struct transvr_obj_s *self); + int (*get_len_om2)(struct transvr_obj_s *self); + int (*get_len_om3)(struct transvr_obj_s *self); + int (*get_len_om4)(struct transvr_obj_s *self); + int (*get_comp_rev)(struct transvr_obj_s *self); + int (*get_comp_eth_1)(struct transvr_obj_s *self); + int (*get_comp_eth_10)(struct transvr_obj_s *self); + int (*get_comp_eth_10_40)(struct transvr_obj_s *self); + int (*get_comp_extend)(struct transvr_obj_s *self); + int (*get_cdr)(struct transvr_obj_s *self); + int (*get_rate_id)(struct transvr_obj_s *self); + int (*get_soft_rs0)(struct transvr_obj_s *self); + int (*get_soft_rs1)(struct transvr_obj_s *self); + int (*get_info)(struct transvr_obj_s *self); + int (*get_if_type)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_speed)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_lane)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p); + int (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_am)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_em)(struct transvr_obj_s *self, char *buf_p); + int (*get_wavelength)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_offset)(struct transvr_obj_s *self, char *buf_p); + int (*get_extphy_reg)(struct transvr_obj_s *self, char *buf_p); + int (*set_cdr)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs0)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs1)(struct transvr_obj_s *self, int input_val); + int (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_tx_eq)(struct transvr_obj_s *self, int input_val); + int (*set_rx_am)(struct transvr_obj_s *self, int input_val); + int (*set_rx_em)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_offset)(struct transvr_obj_s *self, int input_val); + int (*set_extphy_reg)(struct transvr_obj_s *self, int input_val); + + /* ========== Object private functions ========== + */ + int (*init)(struct transvr_obj_s *self); + int (*clean)(struct transvr_obj_s *self); + int (*check)(struct transvr_obj_s *self); + int (*update_all)(struct transvr_obj_s *self, int show_err); + int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name); + int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name); + int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action); + int (*dump_all)(struct transvr_obj_s* self); +}; + + +/* For AVL Mapping */ +struct transvr_avl_s { + char vendor_name[32]; + char vendor_pn[32]; + int (*init)(struct transvr_obj_s *self); +}; + + +/* Worker for long term task of transceiver */ +struct transvr_worker_s { + /* Task Parameter */ + struct transvr_obj_s *transvr_p; + struct transvr_worker_s *next_p; + struct transvr_worker_s *pre_p; + unsigned long trigger_time; + char func_name[64]; + int retry; + int state; + + /* Task private data */ + void *p_data; + + /* Call back function */ + int (*main_task)(struct transvr_worker_s *task); + int (*post_task)(struct transvr_worker_s *task); +}; + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode); + +void lock_transvr_obj(struct transvr_obj_s *self); +void unlock_transvr_obj(struct transvr_obj_s *self); +int isolate_transvr_obj(struct transvr_obj_s *self); + +int resync_channel_tier_2(struct transvr_obj_s *self); + +void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + +#endif /* TRANSCEIVER_H */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6556/utils/inventec_d6556_util.py b/platform/broadcom/sonic-platform-modules-inventec/d6556/utils/inventec_d6556_util.py new file mode 100644 index 000000000000..2ca077945f5a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6556/utils/inventec_d6556_util.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Inventec, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV: ', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[D6556]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +" with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + + +instantiate = [ +'echo inv_eeprom 0x53 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo inv_cpld 0x55 > /sys/bus/i2c/devices/i2c-0/new_device'] + + +drivers =[ +'gpio_ich', +'lpc_ich', +'i2c-i801', +'i2c-mux', +'i2c-mux-pca954x', +'i2c-dev', +'inv_eeprom', +'inv_platform', +'inv_psoc', +'inv_cpld', +'swps', +'inv_pthread'] + + + +def system_install(): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("rmmod i2c_ismt ", 1) + status, output = exec_cmd("rmmod i2c-i801 ", 1) + status, output = exec_cmd("rmmod gpio_ich ", 1) + status, output = exec_cmd("rmmod lpc_ich ", 1) + + + #install drivers + for i in range(0,len(drivers)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #instantiate devices + for i in range(0,len(instantiate)): + #time.sleep(1) + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + + + for i in range(10,18): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-2/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(18,26): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-3/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(26,34): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-4/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(34,42): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(42,50): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-6/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(50,58): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-7/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(58,66): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-8/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print "D6556 devices detected...." + return + +def uninstall(): + global FORCE + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0) + ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/Makefile new file mode 100755 index 000000000000..b596d1c4bc4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/Makefile @@ -0,0 +1,8 @@ +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += inv_eeprom.o +obj-m += swps.o +obj-m += inv_pthread.o +swps-objs := inv_swps.o io_expander.o transceiver.o + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_cpld.c new file mode 100644 index 000000000000..028e24b9eb86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_cpld.c @@ -0,0 +1,456 @@ +/* + * 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 "I2CHostCommunication.h" + +#define USE_SMBUS 1 + +/* definition */ +#define CPLD_INFO_OFFSET 0x00 +#define CPLD_RESET_OFFSET 0x08 +#define CPLD_PSU_OFFSET 0x09 +#define CPLD_LED_OFFSET 0x0E +#define CPLD_LED_STATU_OFFSET 0x0D +#define CPLD_CTL_OFFSET 0x0C + + + +/* Each client has this additional data */ +struct cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +} + +static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t show_info(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[4]; + + memset(b, 0, 4); + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4); + mutex_unlock(&data->update_lock); + + if(status != 4) return sprintf(buf, "read cpld info fail\n"); + + status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/ + status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf); + status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf); + + return strlen(buf); +} + +static ssize_t show_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[1]; + + mutex_lock(&data->update_lock); + + status = cpld_i2c_read(client, b, CPLD_RESET_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld reset fail\n"); + + + status = sprintf (buf, "The CPLD 1 cpld_reset = %d\n", b[0]); + + return strlen(buf); +} + +static ssize_t set_reset(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_write(client, &temp, CPLD_RESET_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_ctl(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[1]; + + mutex_lock(&data->update_lock); + + status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld ctl fail\n"); + + + status = sprintf (buf, "0x%X\n", b[0]); + + return strlen(buf); +} + +static ssize_t set_ctl(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1); + if(temp) byte |= (1<<0); + else byte &= ~(1<<0); + cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static char* led_str[] = { + "OFF", //000 + "0.5 Hz", //001 + "1 Hz", //010 + "2 Hz", //011 + "NA", //100 + "NA", //101 + "NA", //110 + "ON", //111 +}; + +static ssize_t show_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET); + + byte = (byte >> shift) & 0x7; + + /* + 0: off + 1: 0.5hz + 2: 1 hz + 3: 2 hz + 4~6: not define + 7: on + */ + + status = sprintf (buf, "%d: %s\n", byte, led_str[byte]); + + return strlen(buf); +} + +static ssize_t set_led(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 16); + u8 byte; + int shift = (attr->index == 0)?3:0; + + temp &= 0x7; + //validate temp value: 0,1,2,3,7, TBD + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + byte &= ~(0x7<update_lock); + + return count; +} + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu0 | psu1 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 1)?0:3; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + + +static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0); +static SENSOR_DEVICE_ATTR(reset, S_IWUSR|S_IRUGO, show_reset, set_reset, 0); +static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0); + +static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0); +static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1); + +static struct attribute *cpld_attributes[] = { + //info + &sensor_dev_attr_info.dev_attr.attr, + &sensor_dev_attr_reset.dev_attr.attr, + &sensor_dev_attr_ctl.dev_attr.attr, + + &sensor_dev_attr_grn_led.dev_attr.attr, + &sensor_dev_attr_red_led.dev_attr.attr, + + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + NULL +}; + +static const struct attribute_group cpld_group = { + .attrs = cpld_attributes, +}; + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int +cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + + printk("+%s\n", __func__); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld_group); + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpld_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpld_group); + i2c_set_clientdata(client, NULL); + kfree(data); + return 0; +} + +static const struct i2c_device_id cpld_ids[] = { + { "inv_cpld", 0, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, cpld_ids); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_cpld_init(void) +{ + return i2c_add_driver(&cpld_driver); +} + +static void __exit inv_cpld_exit(void) +{ + i2c_del_driver(&cpld_driver); +} + +MODULE_AUTHOR("eddie.lan "); +MODULE_DESCRIPTION("inv cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_cpld_init); +module_exit(inv_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_eeprom.c new file mode 100644 index 000000000000..b2dde612b610 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_eeprom.c @@ -0,0 +1,181 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void inv_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } + +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + inv_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute inv_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = inv_eeprom_read, +}; + +static int inv_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int inv_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id inv_eeprom_id[] = { + { "inv_eeprom", 0 }, + { } +}; + +static struct i2c_driver inv_eeprom_driver = { + .driver = { + .name = "inv_eeprom", + }, + .probe = inv_eeprom_probe, + .remove = inv_eeprom_remove, + .id_table = inv_eeprom_id, +}; + +module_i2c_driver(inv_eeprom_driver); + +MODULE_AUTHOR("Inventec"); +MODULE_DESCRIPTION("Inventec D7032 Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_platform.c new file mode 100644 index 000000000000..6a2c7353228d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_platform.c @@ -0,0 +1,198 @@ +#include +//#include +#include +#include +#include +#include +#include + +#include +#include +#include + +//#include +#define IO_EXPAND_BASE 64 +#define IO_EXPAND_NGPIO 16 + +struct inv_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +#define bus_id(id) (id) +static struct pca954x_platform_mode mux_modes_0[] = { + {.adap_id = bus_id(2),}, {.adap_id = bus_id(3),}, + {.adap_id = bus_id(4),}, {.adap_id = bus_id(5),}, +}; +static struct pca954x_platform_mode mux_modes_0_0[] = { + {.adap_id = bus_id(6),}, {.adap_id = bus_id(7),}, + {.adap_id = bus_id(8),}, {.adap_id = bus_id(9),}, + {.adap_id = bus_id(10),}, {.adap_id = bus_id(11),}, + {.adap_id = bus_id(12),}, {.adap_id = bus_id(13),}, +}; + +static struct pca954x_platform_mode mux_modes_0_1[] = { + {.adap_id = bus_id(14),}, {.adap_id = bus_id(15),}, + {.adap_id = bus_id(16),}, {.adap_id = bus_id(17),}, + {.adap_id = bus_id(18),}, {.adap_id = bus_id(19),}, + {.adap_id = bus_id(20),}, {.adap_id = bus_id(21),}, +}; + +static struct pca954x_platform_mode mux_modes_0_2[] = { + {.adap_id = bus_id(22),}, {.adap_id = bus_id(23),}, + {.adap_id = bus_id(24),}, {.adap_id = bus_id(25),}, + {.adap_id = bus_id(26),}, {.adap_id = bus_id(27),}, + {.adap_id = bus_id(28),}, {.adap_id = bus_id(29),}, +}; + +static struct pca954x_platform_mode mux_modes_0_3[] = { + {.adap_id = bus_id(30),}, {.adap_id = bus_id(31),}, + {.adap_id = bus_id(32),}, {.adap_id = bus_id(33),}, + {.adap_id = bus_id(34),}, {.adap_id = bus_id(35),}, + {.adap_id = bus_id(36),}, {.adap_id = bus_id(37),}, +}; + +static struct pca954x_platform_data mux_data_0 = { + .modes = mux_modes_0, + .num_modes = 4, +}; +static struct pca954x_platform_data mux_data_0_0 = { + .modes = mux_modes_0_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_1 = { + .modes = mux_modes_0_1, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_2 = { + .modes = mux_modes_0_2, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_3 = { + .modes = mux_modes_0_3, + .num_modes = 8, +}; + +static struct i2c_board_info i2c_device_info0[] __initdata = { + {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc + {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld + {"pca9545", 0, 0x70, &mux_data_0, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info1[] __initdata = { + {"pca9545", 0, 0x70, &mux_data_0, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info2[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info3[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info4[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info5[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, +}; + + +static struct inv_i2c_board_info i2cdev_list[] = { + {0, ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //smbus 0 + {1, ARRAY_SIZE(i2c_device_info1), i2c_device_info1 }, //smbus 1 or gpio11+12 + + {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux 0 + {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux 1 + {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux 2 + {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux 3 +}; + +///////////////////////////////////////////////////////////////////////////////////////// +static struct i2c_gpio_platform_data i2c_gpio_platdata0 = { + .scl_pin = 8, + .sda_pin = 9, + + .udelay = 5, //5:100kHz + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, + .scl_is_output_only = 0 +}; + +static struct i2c_gpio_platform_data i2c_gpio_platdata1 = { + .scl_pin = 12, + .sda_pin = 11, + + .udelay = 5, //5:100kHz + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, + .scl_is_output_only = 0 +}; + +static struct platform_device device_i2c_gpio0 = { + .name = "i2c-gpio", + .id = 0, // adapter number + .dev.platform_data = &i2c_gpio_platdata0, +}; + +static struct platform_device device_i2c_gpio1 = { + .name = "i2c-gpio", + .id = 1, // adapter number + .dev.platform_data = &i2c_gpio_platdata1, +}; + +static int __init plat_redwood_x86_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j; + + printk("el6661 plat_redwood_x86_init \n"); + +#if 0 //disable for ICOS + //use i2c-gpio + //register i2c gpio + //config gpio8,9 to gpio function + outl( inl(0x500) | (1<<8 | 1<<9), 0x500); + + ret = platform_device_register(&device_i2c_gpio0); + if (ret) { + printk(KERN_ERR "i2c-gpio: device_i2c_gpio0 register fail %d\n", ret); + } + + outl( inl(0x500) | (1<<11 | 1<<12), 0x500); + ret = platform_device_register(&device_i2c_gpio1); + if (ret) { + printk(KERN_ERR "i2c-gpio: device_i2c_gpio1 register fail %d\n", ret); + } +#endif + + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "I2CHostCommunication.h" + +#define USE_SMBUS 1 + +//#define offsetof(st, m) ((size_t)(&((st *)0)->m)) +#define FAN_NUM 5 +#define PSU_NUM 2 + +struct __attribute__ ((__packed__)) psoc_psu_layout { + u16 psu1_iin; + u16 psu2_iin; + u16 psu1_iout; + u16 psu2_iout; + + u16 psu1_pin; + u16 psu2_pin; + u16 psu1_pout; + u16 psu2_pout; + + u16 psu1_vin; + u16 psu2_vin; + u16 psu1_vout; + u16 psu2_vout; +}; + +struct __attribute__ ((__packed__)) psoc_layout { + u8 ctl; //offset: 0 + u16 switch_temp; //offset: 1 + u8 reserve1; //offset: 3 + + u8 fw_upgrade; //offset: 4 + + //i2c bridge + u8 i2c_st; //offset: 5 + u8 i2c_ctl; //offset: 6 + u8 i2c_addr; //offset: 7 + u8 i2c_data[0x20]; //offset: 8 + + //gpo + u8 led_grn; //offset: 28 + u8 led_red; //offset: 29 + + //pwm duty + u8 pwm[FAN_NUM]; //offset: 2a + u8 pwm_psu[PSU_NUM]; //offset: 2f + + //fan rpm + u16 fan[FAN_NUM*2]; //offset: 31 + //u16 fan_psu[PSU_NUM]; + + //gpi + u8 gpi_fan; //offset: 45 + + //psu state + u8 psu_state; //offset: 46 + + //temperature + u16 temp[5]; //offset: 47 + u16 temp_psu[PSU_NUM]; //offset: 51 + + //version + u8 version[2]; //offset: 55 + + u8 reserve2[3]; //offset: 57 + struct psoc_psu_layout psu_info; //offset: 5a +}; + + +/* definition */ +#define PSOC_OFF(m) offsetof(struct psoc_layout, m) +#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m) + +#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp) //0x01 +#define PWM_OFFSET PSOC_OFF(pwm) +#define PWM_PSU_OFFSET PSOC_OFF(pwm_psu) +#define THERMAL_OFFSET PSOC_OFF(temp) +#define RPM_OFFSET PSOC_OFF(fan) +//#define RPM_PSU_OFFSET PSOC_OFF(fan_psu) +#define DIAG_FLAG_OFFSET PSOC_OFF(ctl) +#define FAN_LED_OFFSET PSOC_OFF(led_grn) +#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan) +#define PSOC_PSU_OFFSET PSOC_OFF(psu_state) +#define VERSION_OFFSET PSOC_OFF(version) +#define PSU_INFO_OFFSET PSOC_OFF(psu_info) + + +/* Each client has this additional data */ +struct psoc_data { + struct device *hwmon_dev; + struct mutex update_lock; + u32 diag; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t psoc_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +} + +static ssize_t psoc_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +} + +static u32 psoc_read32(struct i2c_client *client, u8 offset) +{ + u32 value = 0; + u8 buf[4]; + + if( psoc_i2c_read(client, buf, offset, 4) == 4) + value = (buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]); + + return value; +} + +static u16 psoc_read16(struct i2c_client *client, u8 offset) +{ + u16 value = 0; + u8 buf[2]; + + if(psoc_i2c_read(client, buf, offset, 2) == 2) + value = (buf[0]<<8 | buf[1]<<0); + + return value; +} + +static u8 psoc_read8(struct i2c_client *client, u8 offset) +{ + u8 value = 0; + u8 buf = 0; + + if(psoc_i2c_read(client, &buf, offset, 1) == 1) + value = buf; + + return value; +} + +static int psoc_write_value(struct i2c_client *client, unsigned offset, u16 value) +{ + //TBD + return 0; +} + + +//PSOC i2c bridge regsters +#define PSOC_I2C_STATUS PSOC_OFF(i2c_st) +#define PSOC_I2C_CNTRL PSOC_OFF(i2c_ctl) +#define PSOC_I2C_ADDR PSOC_OFF(i2c_addr) +#define PSOC_I2C_DATA PSOC_OFF(i2c_data) + +//status bit definition +#define PSOC_I2C_START (1 << 0) +#define PSOC_PMB_SEL (1 << 7) + +//addr bits definition +#define PSOC_I2C_READ (1 << 0) + +//PMBUS registers definition +#define PMBUS_READ_VIN (0x88) +#define PMBUS_READ_IIN (0x89) +#define PMBUS_READ_VOUT (0x8B) +#define PMBUS_READ_IOUT (0x8C) +#define PMBUS_READ_POUT (0x96) +#define PMBUS_READ_PIN (0x97) + +#define PMBUS_MFR_ID (0x99) +#define PMBUS_MFR_MODEL (0x9A) +#define PMBUS_MFR_REVISION (0x9B) +#define PMBUS_MFR_DATE (0x9D) +#define PMBUS_MFR_SERIAL (0x9E) + +static int psoc_i2c_bridge_read(struct i2c_client *client, + unsigned char bus, + unsigned char chip, + char *addr, int alen, + unsigned char *data, int len ) +{ + unsigned char txdata[28], rxdata[28]; + int index, timeout; + + txdata[PSOC_I2C_STATUS] = 0; /* the status */ + txdata[PSOC_I2C_CNTRL] = ((alen & 3) << 5) | (len & 0x1f); /* the sizes */ + txdata[PSOC_I2C_ADDR] = (chip << 1) | PSOC_I2C_READ; /* read address */ + for(index = 0; index < alen; index++) + txdata[PSOC_I2C_DATA + index] = addr[index]; /* the chip address */ + for(; index < alen+len; index++) + txdata[PSOC_I2C_DATA + index] = 0; /* clear the chip data */ + + psoc_i2c_write(client, &txdata[PSOC_I2C_CNTRL], PSOC_I2C_CNTRL, 2 + alen + len); + + //delay a while ??? + //--------------------------------------------------------------------- + //start write + txdata[PSOC_I2C_STATUS] = PSOC_I2C_START; /* the start bit*/ + if(bus) + txdata[PSOC_I2C_STATUS] |= PSOC_PMB_SEL;/* bus id */ + psoc_i2c_write(client, &txdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1); + + //delay a while + timeout = 40; //40*20==>800 ms + do { + psoc_i2c_read(client, &rxdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1); + + //check rxdata[5] error bit(1) and complete bit(0) ,TBD + if((rxdata[PSOC_I2C_STATUS] & 0x2) == 0x2) { + //printk("i2c bridge fail!!!\n"); + timeout = 0; + break; + } + if((rxdata[PSOC_I2C_STATUS] & PSOC_I2C_START) == 0) { + /* comand complete */ + psoc_i2c_read(client, &rxdata[PSOC_I2C_DATA+alen], PSOC_I2C_DATA+alen, len); + break; + } + + //delay + msleep(20); + } while(timeout--); + + if(timeout <= 0) { + return -1; + } + + //--------------------------------------------------------------------- + + for(index=0; index < len; index++) { + data[index] = rxdata[PSOC_I2C_DATA + alen + index]; + } + + return 0; +} + + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu1 | psu0 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu_st(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, &byte, PSOC_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t show_thermal(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index * 2 + THERMAL_OFFSET; + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, offset); + status = __swab16(status); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + (s8)(status>>8) * 1000 ); +} + + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t set_pwm(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index; + + u8 pwm = simple_strtol(buf, NULL, 10); + if(pwm > 255) pwm = 255; + + if(data->diag) { + mutex_lock(&data->update_lock); + psoc_i2c_write(client, &pwm, offset, 1); + mutex_unlock(&data->update_lock); + } + + return count; +} + + +static ssize_t show_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index; + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, offset); + status = __swab16(status); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + status); +} +static ssize_t show_fan_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 index = attr->index; + int type = -1; + + mutex_lock(&data->update_lock); + status = psoc_read8(client, FAN_GPI_OFFSET); + mutex_unlock(&data->update_lock); + + if( (status & 1<update_lock); + status = psoc_i2c_read(client, (u8*)&temp, SWITCH_TMP_OFFSET, 2); + status = __swab16(status); + mutex_unlock(&data->update_lock); + + status = sprintf (buf, "%d\n", (s8)(temp>>8) * 1000 ); + + return strlen(buf); +} + +static ssize_t set_switch_tmp(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + long temp = simple_strtol(buf, NULL, 10); + u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ; + + //printk("set_switch_tmp temp=%d, temp2=0x%x (%x,%x)\n", temp, temp2, ( ( (temp/1000) <<8 ) & 0xFF00 ), (( (temp%1000) / 10 ) & 0xFF)); + + mutex_lock(&data->update_lock); + psoc_i2c_write(client, (u8*)&temp2, SWITCH_TMP_OFFSET, 2); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_diag(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 diag_flag = 0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, (u8*)&diag_flag, DIAG_FLAG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + data->diag = (diag_flag & 0x80)?1:0; + status = sprintf (buf, "%d\n", data->diag); + + return strlen(buf); +} + +static ssize_t set_diag(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 value = 0; + u8 diag = simple_strtol(buf, NULL, 10); + + diag = diag?1:0; + data->diag = diag; + + mutex_lock(&data->update_lock); + psoc_i2c_read(client, (u8*)&value, DIAG_FLAG_OFFSET, 1); + if(diag) value |= (1<<7); + else value &= ~(1<<7); + psoc_i2c_write(client, (u8*)&value, DIAG_FLAG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, VERSION_OFFSET); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) ); +} + + +static ssize_t show_fan_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 bit = attr->index; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, FAN_LED_OFFSET); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + (status & (1<index; + u8 led_state = 0; + + u8 v = simple_strtol(buf, NULL, 10); + + if(data->diag) { + mutex_lock(&data->update_lock); + led_state = psoc_read8(client, FAN_LED_OFFSET); + if(v) led_state |= (1<update_lock); + } + + return count; +} + +static ssize_t show_value8(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "0x%02X\n", status ); +} + +static long pmbus_reg2data_linear(int data, int linear16) +{ + s16 exponent; + s32 mantissa; + long val; + + if (linear16) { /* LINEAR16 */ + exponent = -9; + mantissa = (u16) data; + } else { /* LINEAR11 */ + exponent = ((s16)data) >> 11; + exponent = ((s16)( data & 0xF800) ) >> 11; + mantissa = ((s32)((data & 0x7ff) << 5)) >> 5; + } + + //printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa); + val = mantissa; + + /* scale result to micro-units for power sensors */ + val = val * 1000L; + + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 reg = attr->index & 0xFF; + u8 len = ((attr->index & 0xFF00) >> 8); + u8 chip = (attr->index >> 16)? 0x59:0x58; + u8 bus = 1; + unsigned char value[2] = {0,0};; + + if (len == 2) + { + mutex_lock(&data->update_lock); + psoc_i2c_bridge_read(client, bus, chip, ®, 1, value, 2); + mutex_unlock(&data->update_lock); + + status = value[1]<<8 | value[0]; + //status1 = value[1]<<8 | value[0]; + + return sprintf(buf, "%ld\n", pmbus_reg2data_linear(status, (reg==PMBUS_READ_VOUT)?1:0) ); + } + else + { //len is not defined. + u8 tmpbuf[32]; + mutex_lock(&data->update_lock); + //length of block read + psoc_i2c_bridge_read(client, bus, chip, ®, 1, &len, 1); + //data included length + psoc_i2c_bridge_read(client, bus, chip, ®, 1, tmpbuf, len+1); + mutex_unlock(&data->update_lock); + + memcpy(buf, tmpbuf+1, len); + buf[len]='\n'; + + return len+1; + } +} + +static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index + PSU_INFO_OFFSET; + + mutex_lock(&data->update_lock); + status = psoc_read16(client, offset); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, strstr(attr->dev_attr.attr.name, "vout")? 1:0 )); +} + + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4); +static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5); +static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 6); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_OFFSET+0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_OFFSET+1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_OFFSET+2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_OFFSET+3); +#if (FAN_NUM >= 5) +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_OFFSET+4); +#endif +static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_PSU_OFFSET+0); +static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, PWM_PSU_OFFSET+1); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu_st, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 1); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7*2 + RPM_OFFSET); +#if (FAN_NUM >= 5) +static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO, show_rpm, 0, 8*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, show_rpm, 0, 9*2 + RPM_OFFSET); +#endif +static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8*2 + RPM_OFFSET); +static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9*2 + RPM_OFFSET); + +static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); +static SENSOR_DEVICE_ATTR(temp6_input, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); + +static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0); +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0); + +static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0); +static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1); +static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2); +static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3); +static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4); +static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5); +static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6); +static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7); + +static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET); +static SENSOR_DEVICE_ATTR(fan1_type, S_IRUGO, show_fan_type, 0, 0); +static SENSOR_DEVICE_ATTR(fan2_type, S_IRUGO, show_fan_type, 0, 1); +static SENSOR_DEVICE_ATTR(fan3_type, S_IRUGO, show_fan_type, 0, 2); +static SENSOR_DEVICE_ATTR(fan4_type, S_IRUGO, show_fan_type, 0, 3); + +static SENSOR_DEVICE_ATTR(psu1_vin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VIN); +static SENSOR_DEVICE_ATTR(psu1_vout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VOUT); +static SENSOR_DEVICE_ATTR(psu1_iin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IIN); +static SENSOR_DEVICE_ATTR(psu1_iout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IOUT); +static SENSOR_DEVICE_ATTR(psu1_pin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_PIN); +static SENSOR_DEVICE_ATTR(psu1_pout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_POUT); + +static SENSOR_DEVICE_ATTR(psu1_vendor, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_ID); +static SENSOR_DEVICE_ATTR(psu1_model, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu1_version, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu1_date, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_DATE); +static SENSOR_DEVICE_ATTR(psu1_sn, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_SERIAL); + +static SENSOR_DEVICE_ATTR(psu2_vin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VIN); +static SENSOR_DEVICE_ATTR(psu2_vout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VOUT); +static SENSOR_DEVICE_ATTR(psu2_iin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IIN); +static SENSOR_DEVICE_ATTR(psu2_iout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IOUT); +static SENSOR_DEVICE_ATTR(psu2_pin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_PIN); +static SENSOR_DEVICE_ATTR(psu2_pout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_POUT); + +static SENSOR_DEVICE_ATTR(psu2_vendor, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_ID); +static SENSOR_DEVICE_ATTR(psu2_model, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu2_version, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu2_date, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_DATE); +static SENSOR_DEVICE_ATTR(psu2_sn, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_SERIAL); + +static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout)); + + +static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout)); + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); + + + +static struct attribute *psoc_attributes[] = { + //thermal + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + + &sensor_dev_attr_thermal_psu1.dev_attr.attr, + &sensor_dev_attr_thermal_psu2.dev_attr.attr, + + + //pwm + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, +#if (FAN_NUM >= 5) + //&sensor_dev_attr_pwm5.dev_attr.attr, +#endif + &sensor_dev_attr_pwm_psu1.dev_attr.attr, + &sensor_dev_attr_pwm_psu2.dev_attr.attr, + + //rpm + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, +#if (FAN_NUM >= 5) + //&sensor_dev_attr_fan9_input.dev_attr.attr, + //&sensor_dev_attr_fan10_input.dev_attr.attr, +#endif + + &sensor_dev_attr_rpm_psu1.dev_attr.attr, + &sensor_dev_attr_rpm_psu2.dev_attr.attr, + + //switch temperature + &sensor_dev_attr_switch_tmp.dev_attr.attr, + &sensor_dev_attr_temp6_input.dev_attr.attr, + + //diag flag + &sensor_dev_attr_diag.dev_attr.attr, + + //version + &sensor_dev_attr_version.dev_attr.attr, + + //fan led + &sensor_dev_attr_fan_led_grn1.dev_attr.attr, + &sensor_dev_attr_fan_led_grn2.dev_attr.attr, + &sensor_dev_attr_fan_led_grn3.dev_attr.attr, + &sensor_dev_attr_fan_led_grn4.dev_attr.attr, + &sensor_dev_attr_fan_led_red1.dev_attr.attr, + &sensor_dev_attr_fan_led_red2.dev_attr.attr, + &sensor_dev_attr_fan_led_red3.dev_attr.attr, + &sensor_dev_attr_fan_led_red4.dev_attr.attr, + + //fan GPI + &sensor_dev_attr_fan_gpi.dev_attr.attr, + + //fan type + &sensor_dev_attr_fan1_type.dev_attr.attr, + &sensor_dev_attr_fan2_type.dev_attr.attr, + &sensor_dev_attr_fan3_type.dev_attr.attr, + &sensor_dev_attr_fan4_type.dev_attr.attr, + + //psu + &sensor_dev_attr_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psu2_pout.dev_attr.attr, + + &sensor_dev_attr_psu1_vendor.dev_attr.attr, + &sensor_dev_attr_psu1_model.dev_attr.attr, + &sensor_dev_attr_psu1_version.dev_attr.attr, + &sensor_dev_attr_psu1_date.dev_attr.attr, + &sensor_dev_attr_psu1_sn.dev_attr.attr, + &sensor_dev_attr_psu2_vendor.dev_attr.attr, + &sensor_dev_attr_psu2_model.dev_attr.attr, + &sensor_dev_attr_psu2_version.dev_attr.attr, + &sensor_dev_attr_psu2_date.dev_attr.attr, + &sensor_dev_attr_psu2_sn.dev_attr.attr, + + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + //psu_psoc, new added on psoc 1.9 + &sensor_dev_attr_psoc_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pout.dev_attr.attr, + + // Add new fields which matching standard + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + + NULL +}; + +static const struct attribute_group psoc_group = { + .attrs = psoc_attributes, +}; + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int +psoc_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct psoc_data *data; + int status; + + printk("+%s\n", __func__); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct psoc_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->diag = 0; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &psoc_group); + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &psoc_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int psoc_remove(struct i2c_client *client) +{ + struct psoc_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &psoc_group); + i2c_set_clientdata(client, NULL); + kfree(data); + return 0; +} + +static const struct i2c_device_id psoc_ids[] = { + { "inv_psoc", 0, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, psoc_ids); + +static struct i2c_driver psoc_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_psoc", + }, + .probe = psoc_probe, + .remove = psoc_remove, + .id_table = psoc_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_psoc_init(void) +{ + return i2c_add_driver(&psoc_driver); +} + +static void __exit inv_psoc_exit(void) +{ + i2c_del_driver(&psoc_driver); +} + +MODULE_AUTHOR("eddie.lan "); +MODULE_DESCRIPTION("inv psoc driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_psoc_init); +module_exit(inv_psoc_exit); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_pthread.c new file mode 100644 index 000000000000..b0f905d6a7d9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_pthread.c @@ -0,0 +1,1305 @@ +/***************************** + Redwood platform +******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SHOW_ATTR_WARNING ("N/A") +#define SHOW_ATTR_NOTPRINT ("Not Available") +#define SHOW_ATTR_NOTSUPPORT ("Not Support") + +#define INV_HWMID_MAX (10) +#define INV_HWMID_INIT (-1) + +/*access userspace data to kernel space*/ +#define ACC_R (0) +#define ACC_W (1) + +#define TINY_BUF_SIZE (8) +#define MAX_PATH_SIZE (64) +#define MIN_ACC_SIZE (32) +#define MAX_ACC_SIZE (256) + +/* + * LED definitions + */ +#define STATUS_LED_MODE_AUTO 0 +#define STATUS_LED_MODE_DIAG 1 +#define STATUS_LED_MODE_MANU 2 + +#define STATUS_LED_GRN0 10 // 0 - 000: off +#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz +#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz +#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz +#define STATUS_LED_GRN7 17 // 7 - 111: on +#define STATUS_LED_RED0 20 // 0 - 000: off +#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz +#define STATUS_LED_RED2 22 // 2 - 010: 1 hz +#define STATUS_LED_RED3 23 // 3 - 011: 2 hz +#define STATUS_LED_RED7 27 // 7 - 111: on +#define STATUS_LED_INVALID 0 // Invalid + +ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2); +ssize_t status_led_grn(const char *freq); +ssize_t status_led_red(const char *freq); +ssize_t status_led_diag_mode_enable(void); +ssize_t status_led_diag_mode_disable(void); +int status_led_check_color(void); +int status_led_check_diag_mode(void); + +#if 1 +/* For timestamps in SYSFS_LOG */ +#define SYSFS_LOG printk +#else +//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args) +#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args) +#endif + +#define INV_PTHREAD_KERNEL_MODULE (1) +#define SWITCH_HEALTH_LED_CHANGE_VIA_GPIO (1) + +/* inventec_class *********************************/ +static struct kobject *status_kobj; +static struct kset *status_kset; + + +static struct mutex rw_lock; + +static int hwm_psoc = INV_HWMID_INIT; +static int hwm_cpld = INV_HWMID_INIT; + +int get_hwm_psoc(void) +{ + return hwm_psoc; +} + +int get_hwm_cpld(void) +{ + return hwm_cpld; +} + +static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + char *mark = NULL; + ssize_t vfs_ret = 0; + + if (mode == ACC_R) { + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_read(fp, buf, len, &pos); + + mark = strpbrk(buf, "\n"); + if (mark) + *mark = '\0'; + + filp_close(fp, NULL); + set_fs(fs); + } else if (mode == ACC_W) { + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_write(fp, buf, len, &pos); + filp_close(fp, NULL); + set_fs(fs); + } + + return vfs_ret; +} + +int inventec_strtol(const char *sbufp, char **endp, unsigned int base) +{ + char *endptr; + int value = simple_strtol(sbufp, &endptr, base); + if (value == 0 && sbufp == endptr) { + *endp = NULL; + return value; + } + *endp = (char*)1; + return value; +} + +int inventec_singlechar_to_int(const char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + else + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + else + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } + return -1; +} + +int inventec_store_input(char *inputp, int count) +{ + int i = 0; + while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) { + i++; + } + inputp[i] = '\0'; + return strlen(inputp); +} + +#if 0 +/* + * Time stamps for kernel log on yocto + */ +#include + +void SYSFS_LOG(char *fmt, ...) +{ + char buf[80], ts[32]; + va_list args; + int hlen; + + inventec_tmstmp(&ts[0]); + hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line + + va_start(args, fmt); + vsprintf(&buf[hlen-1], fmt, args); + va_end(args); + printk(KERN_WARNING "[p_thread] %s\n", buf); +} +#endif + +ssize_t +inventec_show_attr(char *buf_p, const char *invdevp) +{ + int inv_len = MAX_ACC_SIZE; /* INV driver return max length */ + char tmp_buf[MAX_ACC_SIZE]; + char *str_negative = "-", *mark = NULL; + + /* [Step2] Get data by uaccess */ + memset(tmp_buf, 0, sizeof(tmp_buf)); + mutex_lock(&rw_lock); + if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + mutex_unlock(&rw_lock); + + /* [Step3] Check return value + * - Ex: When transceiver not plugged + * => SWPS return error code "-202" + * => Pic8 need return "NA" (assume) + */ + if (strcspn(tmp_buf, str_negative) == 0) { + /* error case: "-202" */ + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + + /* OK case:*/ + mark = strpbrk(tmp_buf, "\n"); + if (mark) { *mark = '\0'; } + + return sprintf(buf_p, "%s\n", tmp_buf); +} + +ssize_t +inventec_store_attr(const char *buf_p, size_t count, const char *invdevp) +{ + ssize_t ret = 0; + + /* [Step2] Get data by uaccess */ + mutex_lock(&rw_lock); + if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return -EINVAL; + } + mutex_unlock(&rw_lock); + + /* OK case:*/ + return ret; +} + +int sysfs_detect_hwmon_index(void) +{ + char hwmon_buf[MAX_ACC_SIZE]; + char hwmon_path[MAX_PATH_SIZE]; + int hwid = 0; + + for (hwid = 0; + hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT); + hwid++) { + memset(hwmon_buf, 0, sizeof(hwmon_buf)); + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/device/name", hwid); + + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) { + hwm_cpld = hwid; + } + } + if (hwid >= INV_HWMID_MAX) { + printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return -1; + } + printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return 0; +} + +static int __init +inventec_class_init(void) +{ + mutex_init(&rw_lock); + +#ifdef INV_PTHREAD_KERNEL_MODULE + if (sysfs_detect_hwmon_index() < 0) { + return -1; + } +#endif + + printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__); + + return 0; +} + +static void __exit +inventec_class_exit(void) +{ + printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__); +} + +/* fan device *************************************/ +#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/device/fan_gpi" +#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/device/fan1_input" +#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/device/fan2_input" +#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/device/fan3_input" +#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/device/fan4_input" +#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/device/fan5_input" +#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/device/fan6_input" +#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/device/fan7_input" +#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/device/fan8_input" + +static char fan_dev_path_state[MAX_PATH_SIZE]; +static char fan_dev_path_fan1_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan2_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan3_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan4_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan5_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan6_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan7_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan8_input[MAX_PATH_SIZE]; + +void sysfs_fan_path_init(void) +{ + sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc()); + sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc()); +} + +#define FAN_STATE_NORMAL "normal" +#define FAN_STATE_FAULTY "faulty" +#define FAN_STATE_UNINSTALLED "uninstalled" +#define FAN_STATE_UNKNOW "unknown state" +#define FAN_STATE_INVALID "Invalid state value" +#define FAN_STATE_READ_ERROR "state read error" + +#define FAN_LOG_UNINSTALLED "removed" +#define FAN_LOG_NORMAL "inserted" + +//#define FAN_STATE_BIT_NORMAL 0 +#define FAN_STATE_BIT_FAULTY 0 +#define FAN_STATE_BIT_UNINSTALLED 1 +#define FAN_STATE_BIT_UNKNOW 2 +#define FAN_STATE_BIT_INVALID 3 +#define FAN_STATE_BIT_READ_ERROR 4 + +static struct fans_tbl_s { + char *fan_name; + char *fan_front; + char *fan_rear; + unsigned int fan_state; +} fans_tbl[] = { + {"fan1", fan_dev_path_fan1_input, + fan_dev_path_fan2_input, 0}, + {"fan2", fan_dev_path_fan3_input, + fan_dev_path_fan4_input, 0}, + {"fan3", fan_dev_path_fan5_input, + fan_dev_path_fan6_input, 0}, + {"fan4", fan_dev_path_fan7_input, + fan_dev_path_fan8_input, 0}, +}; +#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) ) + +#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0) + { + printk(KERN_ERR "[p_thread] All fans failed.\n"); + printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown); + } + cd_shutdown -= 1; + } + return ret; +} + +/* End of faninfo_device */ + +static int __init +fan_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_fan_path_init(); +#endif + return 0; +} + + +static void __exit +fan_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove fan module.\n"); +} + +/* psu device *************************************/ +static unsigned int psu_voltin = 0; +#define PSU_VOLTIN_ACDC (70000) + +/* + * normal/unpower/uninstall/fault are PSU states output from driver level + * checkpsu/error are defined by sysfs + */ +#define PSU_STATE_VAL_NORMAL (0) +#define PSU_STATE_VAL_UNPOWER (2) +#define PSU_STATE_VAL_FAULT (4) +#define PSU_STATE_VAL_UNINSTALL (7) +#define PSU_STATE_VAL_CHECKPSU (8) +#define PSU_STATE_VAL_ERROR (9) + +#define PSU_STATE_NORMAL ("0 : normal") +#define PSU_STATE_UNPOWER ("2 : unpowered") +#define PSU_STATE_FAULT ("4 : fault") +#define PSU_STATE_UNINSTALL ("7 : not installed") +#define PSU_STATE_CHECKPSU ("8 : check psu") +#define PSU_STATE_ERROR ("9 : state error") + +#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL)) +#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER)) +#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT)) +#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL)) +#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU)) + +typedef struct { + char *inv_dev_attrp; + char *inv_dev_pathp; +} psu_dev_t; + +typedef struct { + const char *psu_name; + int psu_major; + dev_t psu_devt; + struct device *psu_dev_p; + psu_dev_t *psu_dev_namep; + int psu_dev_total; + char *psu_inv_pathp; + void *psu_tracking; + char *psu_currentin; + char *psu_currentout; + char *psu_powerin; + char *psu_powerout; + char *psu_voltin; + char *psu_voltout; +} psu_dev_group_t; + +#define PSU_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s" + +static char psu_dev_path_state[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltin[MAX_PATH_SIZE]; +#if 0 +static char psu_dev_path_vendor[MAX_PATH_SIZE]; +static char psu_dev_path_version[MAX_PATH_SIZE]; +static char psu_dev_path_sn[MAX_PATH_SIZE]; +static char psu_dev_path_temperature[MAX_PATH_SIZE]; +static char psu_dev_path_fan_speed[MAX_PATH_SIZE]; +static char psu_dev_path_fan_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_fan_faulty[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_psu_rpm[MAX_PATH_SIZE]; +#endif + +void sysfs_psu_path_init(void) +{ + sprintf(&psu_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" ); + sprintf(&psu_dev_path_psu_voltin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#if 0 + sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#endif +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +#if 0 + { "vendor", psu_dev_path_vendor }, + { "version", psu_dev_path_version }, + { "sn", psu_dev_path_sn }, + { "temperature", psu_dev_path_temperature }, + { "fan_speed", psu_dev_path_fan_speed }, + { "fan_pwm", psu_dev_path_fan_pwm }, + { "fan_faulty", psu_dev_path_fan_faulty }, + { "psu_currentin", psu_dev_path_psu_currentin }, + { "psu_currentout", psu_dev_path_psu_currentout }, + { "psu_powerin", psu_dev_path_psu_powerin }, + { "psu_powerout", psu_dev_path_psu_powerout }, + { "psu_voltout", psu_dev_path_psu_voltout }, + { "psu_pwm", psu_dev_path_psu_pwm }, + { "psu_rpm", psu_dev_path_psu_rpm }, +#endif +}; +#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) ) + +static psu_dev_group_t psu_dev_group[] = { + { + .psu_name = "psu1", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, + { + .psu_name = "psu2", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, +}; +#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) ) + +static char psu_state[4][MIN_ACC_SIZE]; + +static struct psu_wire_tbl_s { + char *psu_attr; + char *psu_name; + char *psu_wire; + char *psu_state; +} psu_wire_tbl[] = { + { "state", "psu1", "psu0", psu_state[0] }, // Using cpld + { "state", "psu2", "psu1", psu_state[1] }, + { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] }, + { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] }, +}; +#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) ) + +static char * +psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp) +{ + int i; + + for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) { + if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 && + strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) { + if (psu_statepp) { + *psu_statepp = psu_wire_tbl[i].psu_state; + } + return psu_wire_tbl[i].psu_wire; + } + } + return NULL; +} + +int psu_check_state_normal(char *statep) +{ + if (strstr(statep, "normal")) { + return 1; + } + return 0; +} + +#define PSU_ATTR_VOLTIN ("psu_voltin") +#define PSU_ATTR_VOLTIN_LEN (10) + +/* Get PSU voltin for determon AC(110v) or DC(48v) */ +void psu_get_voltin(void) +{ + char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE]; + psu_dev_t *devnamep; + unsigned int voltin; + char *invwirep; + int i, j; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + //psu_dev_group[i].psu_name; + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(volt, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + continue; + } + else { + voltin = simple_strtol(&volt[0], NULL, 10); + printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin); + if (voltin > psu_voltin) { + psu_voltin = voltin; + } + } + } + } + } + + SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin); +} + +#define PSU_ATTR_STATE ("state") +#define PSU_ATTR_STATE_LEN (5) + +/* psus_control() by inv_thread */ +int psus_control(int log_only) +{ + char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE]; + psu_dev_t *devnamep = NULL; + char *invwirep = NULL; + char *psu_statep = NULL; + int i, j, flag = 0; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(state, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) { + strcpy(psu_statep, PSU_STATE_ERROR); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR); + } + flag = 1; + } + else + if (strstr(state, "normal")) { + //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + } + else + if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */ + //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + flag = 1; + } + else { /* DC PSUS */ + if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) { + strcpy(psu_statep, PSU_STATE_CHECKPSU); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU); + } + flag = 1; + } + } + } + } + + if (log_only) { + return 0; + } + + //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag); + if (flag == 1) { + status_led_grn("3"); + return 1; + } + return 0; +} + +/* End of psuinfo_device */ + +static int __init +psu_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_psu_path_init(); +#endif + return 0; +} + + +static void __exit +psu_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove psu module.\n"); +} + +/* led device *************************************/ +#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led" +#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led" + +#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1" +#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2" +#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3" +#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4" +#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1" +#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2" +#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3" +#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4" + +#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag" +#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl" + +static char status_led_grn_path[MAX_PATH_SIZE]; +static char status_led_red_path[MAX_PATH_SIZE]; +static char fan_led_grn1_path[MAX_PATH_SIZE]; +static char fan_led_grn2_path[MAX_PATH_SIZE]; +static char fan_led_grn3_path[MAX_PATH_SIZE]; +static char fan_led_grn4_path[MAX_PATH_SIZE]; +static char fan_led_red1_path[MAX_PATH_SIZE]; +static char fan_led_red2_path[MAX_PATH_SIZE]; +static char fan_led_red3_path[MAX_PATH_SIZE]; +static char fan_led_red4_path[MAX_PATH_SIZE]; +static char hwmon_device_diag_path[MAX_PATH_SIZE]; +static char hwmon_device_ctrl_path[MAX_PATH_SIZE]; + +void sysfs_led_path_init(void) +{ + sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld()); + sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld()); + sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc()); + sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc()); + sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc()); + sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc()); + sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld()); +} + +/* return 0/off 1/green 2/red */ +int +status_led_check_color(void) +{ + char tmpbuf[MIN_ACC_SIZE]; + int ret = STATUS_LED_INVALID; + + if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_GRN0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_GRN1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_GRN2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_GRN3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_GRN7; + } + return ret; + } + + if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_RED0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_RED1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_RED2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_RED3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_RED7; + } + return ret; + } + return ret; +} + +/* + * Store attr Section + */ +static DEFINE_MUTEX(diag_mutex); + +ssize_t status_led_diag_mode_enable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '0') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("1", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + mutex_unlock(&diag_mutex); + } + + return ret; +} + +ssize_t status_led_diag_mode_disable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '1') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("0", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + mutex_unlock(&diag_mutex); + } + return 1; +} + +ssize_t +status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2) +{ + ssize_t ret; + + ret = inventec_store_attr(tmp1, strlen(tmp1), path1); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(tmp2, strlen(tmp2), path2); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_red(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_grn_path[0]); + + if (ret < 0) { + return ret; + } + + ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]); + + if (ret < 0) { + return ret; + } + + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_grn(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +static int status_led_diag_mode = STATUS_LED_MODE_AUTO; + +int status_led_check_diag_mode(void) +{ + return status_led_diag_mode; +} + +/* End of ledinfo_device */ + +static int __init +led_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); +#endif + return 0; +} + + +static void __exit +led_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove led module.\n"); +} + +/* sensor device **********************************/ +#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp" + +static char sensor_dev_path_switch_temp[MAX_PATH_SIZE]; + +void sysfs_sensor_path_init(void) +{ + sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc()); +} + +void switch_temp_update(void) +{ + char buf[MIN_ACC_SIZE]; + ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp"); + if (count > 0) { + //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp); + inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp); + } +} + +/**************************************************/ +/* From system_device */ +static int inv_pthread_control = 1; + +int thread_control(void) +{ + return inv_pthread_control; +} + +void thread_control_set(int val) +{ + inv_pthread_control = val; +} +/* End system_device */ + +#define THREAD_SLEEP_MINS (3) +#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1) + +extern void psu_get_voltin(void); + +static struct task_struct *thread_st; +static int thread_data; + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO +void led_set_gpio_to_change_status_led(void) +{ + ssize_t ret = inventec_store_attr("253", 3, "/sys/class/gpio/export"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 253 to /sys/class/gpio/export failed\n"); + return; + } + + printk("[p_thread] Write 253 to /sys/class/gpio/export\n"); + + ret = inventec_store_attr("out", 3, "/sys/class/gpio/gpio253/direction"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio253/direction failed\n"); + return; + } + + //pull high and then low + ret = inventec_store_attr("1", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 1 to sys/class/gpio/gpio253/value failed\n"); + } + + //pull low + ret = inventec_store_attr("0", 1, "sys/class/gpio/gpio253/value"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 0 to sys/class/gpio/gpio253/value failed\n"); + } + + SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n"); +} +#endif + +// Function executed by kernel thread +static int thread_fn(void *unused) +{ + /* Delay for guarantee HW ready */ + ssleep(THREAD_DELAY_MINS); + +#ifndef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sysfs_fan_path_init(); + sysfs_psu_path_init(); +#endif + //sysfs_sensor_path_init(); + + /* Default status init */ + status_led_grn("7"); + + psu_get_voltin(); + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO + led_set_gpio_to_change_status_led(); +#endif + + while (1) + { + ssleep(THREAD_SLEEP_MINS); + + if (thread_control() == 0) { + printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__); + break; + } + + if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) { + /* status led in change color/freq mode, higher priority. Ignore fans sttaus */ + continue; + } + + // switch_temp_update(); + + if (fans_control() > 0) { + psus_control(1); + continue; + } + else + if (psus_control(0) > 0) { + continue; + } + + if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */ + status_led_grn("7"); + } + } + +#ifndef INV_PTHREAD_KERNEL_MODULE +err_inv_pthread_fn_1: +#endif + do_exit(0); + printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__); + return 0; +} + + +static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int fan_absence; + size_t count; + + fan_absence = fans_control(); + count += sprintf(&buf[count], "%d\n", fan_absence); + return count; +} + +static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static struct attribute status_att = { + .name = "fan_absence", + .mode = 0777, +}; + +static const struct sysfs_ops status_ops = { + .show = s_show, + .store = s_store, +}; + +static struct kobj_type status_ktype = { + .sysfs_ops = &status_ops, +}; + + +static int __init inv_pthread_init(void) +{ + int retval; + + status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL); + if(!status_kobj) + return PTR_ERR(status_kobj); + + status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj); + if(!status_kset) + return -1; + + status_kobj->kset = status_kset; + + retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan"); + if(retval) + return retval; + + retval = sysfs_create_file(status_kobj, &status_att); + + + inventec_class_init(); + fan_device_init(); + psu_device_init(); + led_device_init(); + + thread_control_set(1); + + printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__); + //Create the kernel thread with name 'inv_pthread' + thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread"); + if (thread_st) + printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n"); + else + printk(KERN_ERR "[p_thread] inv_pthread creation failed\n"); + + return retval; +} + +static void __exit inv_pthread_exit(void) +{ + thread_control_set(0); + /* Delay for guarantee thread exit */ + ssleep(THREAD_DELAY_MINS); + + fan_device_exit(); + psu_device_exit(); + led_device_exit(); + inventec_class_exit(); + + sysfs_remove_file(status_kobj, &status_att); + kset_unregister(status_kset); + kobject_del(status_kobj); + + printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n"); +} + +module_init(inv_pthread_init); +module_exit(inv_pthread_exit); + +MODULE_AUTHOR("Robert "); +MODULE_DESCRIPTION("Inventec Platform Management Thread"); +MODULE_VERSION("version 1.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.c new file mode 100644 index 000000000000..03ef85a0443c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.c @@ -0,0 +1,618 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_swps.h" + +static int port_major; +static int ioexp_total; +static int port_total; +static struct class *swp_class_p = NULL; +static struct inv_platform_s *platform_p = NULL; +static struct inv_ioexp_layout_s *ioexp_layout = NULL; +static struct inv_port_layout_s *port_layout = NULL; + +static int +__swp_match(struct device *dev, +#ifdef SWPS_KERN_VER_AF_3_10 + + const void *data){ +#else + void *data){ +#endif + + char *name = (char *)data; + if (strcmp(dev_name(dev), name) == 0) + return 1; + return 0; +} + + +struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(swp_class_p, + NULL, + name, + (const void *)__swp_match); + return dev; +} + + +static int +sscanf_2_int(const char *buf) { + + int result = -EBFONT; + char *hex_tag = "0x"; + + if (strcspn(buf, hex_tag) == 0) { + if (sscanf(buf,"%x",&result)) { + return result; + } + } else { + if (sscanf(buf,"%d",&result)) { + return result; + } + if(sscanf(buf,"-%d",&result)) { + return -result; + } + if (sscanf(buf,"%x",&result)) { + return result; + } + } + return -EBFONT; +} + + +static int +sscanf_2_binary(const char *buf) { + + int result = sscanf_2_int(buf); + + if (result < 0){ + return -EBFONT; + } + switch (result) { + case 0: + case 1: + return result; + default: + break; + } + return -EBFONT; +} + +/* ========== Show functions: For I/O Expander attribute ========== + */ +static ssize_t +_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset), + char *buf_p) { + size_t len; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR(" %s: data corruption! :%s\n", __func__, tobj_p->swp_name); + return -ENODATA; + } + mutex_lock(&ioexp_p->lock); + len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset)); + mutex_unlock(&ioexp_p->lock); + return len; +} + + +static ssize_t +show_attr_present(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_present, + buf_p); +} + +static ssize_t +show_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_reset, + buf_p); +} + +static ssize_t +show_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_lpmod, + buf_p); +} + + +static ssize_t +show_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_modsel, + buf_p); +} + +/* ========== Store functions: For I/O Expander (R/W) attribute ========== + */ +static ssize_t +_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*set_func)(struct ioexp_obj_s *ioexp_p, + int virt_offset, int input_val), + const char *buf_p, + size_t count) { + + int input, err; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR("%s: data corruption! :%s\n", + __func__, tobj_p->swp_name); + return -ENODATA; + } + input = sscanf_2_binary(buf_p); + if (input < 0) { + return -EBFONT; + } + mutex_lock(&ioexp_p->lock); + err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input); + mutex_unlock(&ioexp_p->lock); + if (err < 0){ + return err; + } + return count; +} + +static ssize_t +store_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_reset, + buf_p, + count); +} + + +static ssize_t +store_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_lpmod, + buf_p, + count); +} + + +static ssize_t +store_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_modsel, + buf_p, + count); +} + +/* ========== IO Expander attribute: from expander ========== + */ +static DEVICE_ATTR(present, S_IRUGO, show_attr_present, NULL); +static DEVICE_ATTR(reset, S_IRUGO|S_IWUSR, show_attr_reset, store_attr_reset); +static DEVICE_ATTR(lpmod, S_IRUGO|S_IWUSR, show_attr_lpmod, store_attr_lpmod); +static DEVICE_ATTR(modsel, S_IRUGO|S_IWUSR, show_attr_modsel, store_attr_modsel); + +/* ========== Functions for module handling ========== + */ +static void +clean_port_obj(void){ + + dev_t dev_num; + char dev_name[32]; + struct device *device_p; + struct transvr_obj_s *transvr_obj_p; + int minor_curr, port_id; + + for (minor_curr=0; minor_curri2c_client_p); + kfree(transvr_obj_p); + } + dev_num = MKDEV(port_major, minor_curr); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static int +get_platform_type(void){ + + char log_msg[64] = "ERROR"; + + platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL); + if (!platform_p){ + snprintf(log_msg, sizeof(log_msg), "kzalloc fail"); + goto err_get_platform_type_1; + } + platform_p->id = PLATFORM_SETTINGS; + memset(platform_p->name, 0, sizeof(platform_p->name)); + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", platform_map.name); + snprintf(log_msg, sizeof(log_msg), + "User setup platform: %d (%s)", + platform_p->id, platform_p->name); + SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return 0; + +err_get_platform_type_1: + SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return -1; +} + + +static int +get_layout_info(void){ + + ioexp_layout = redwood_ioexp_layout; + port_layout = redwood_port_layout; + ioexp_total = ARRAY_SIZE(redwood_ioexp_layout); + port_total = ARRAY_SIZE(redwood_port_layout); + + SWPS_INFO("Start to initial platform: %d (%s)\n", + platform_p->id, platform_p->name); + return 0; +} + +/* ========== Functions for register something ========== + */ + +static int +register_ioexp_attr_qsfp_1(struct device *device_p){ + /* Support machine type: + * - QSFP : Magnolia, Redwood, Hudson32i + * - QSFP+ : Magnolia, Redwood, Hudson32i + * - QSFP28: Redwood + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_reset) < 0) { + err_attr = "dev_attr_reset"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_lpmod) < 0) { + err_attr = "dev_attr_lpmod"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_modsel) < 0) { + err_attr = "dev_attr_modsel"; + goto err_ioexp_qsfp1_attr; + } + return 0; + +err_ioexp_qsfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + +static int +register_ioexp_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + char *err_msg = "ERR"; + + switch (transvr_obj->ioexp_obj_p->ioexp_type){ + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + if (register_ioexp_attr_qsfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_qsfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + + default: + err_msg = "Unknow type"; + goto err_reg_ioexp_attr; + } + return 0; + +err_reg_ioexp_attr: + SWPS_ERR("%s: %s :%d \n", + __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type); + return -1; +} + + +static int +register_port_device(char *dev_name, + dev_t dev_num, + struct transvr_obj_s *transvr_obj){ + + struct device *device_p = NULL; + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + transvr_obj, /* void *private_data */ + dev_name); /* const char *fmt */ + if (IS_ERR(device_p)){ + goto err_regswp_create_dev; + } + if (register_ioexp_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + return 0; + +err_regswp_reg_attr: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_regswp_create_dev: + SWPS_ERR("%s fail! :%s\n", __func__, dev_name); + return -1; +} + + +static int +register_swp_module(void){ + + dev_t port_devt = 0; + int dev_total = port_total + 1; /* char_dev for module control */ + + if (alloc_chrdev_region(&port_devt, 0, dev_total, SWP_CLS_NAME) < 0){ + SWPS_WARN("Allocate PORT MAJOR failure! \n"); + goto err_register_swp_module_3; + } + port_major = MAJOR(port_devt); + + /* Create class object */ + swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME); + if (IS_ERR(swp_class_p)) { + SWPS_ERR("Create class failure! \n"); + goto err_register_swp_module_3; + } + return 0; + +err_register_swp_module_3: + unregister_chrdev_region(MKDEV(port_major, 0), port_total); + return -1; +} + + +/* ========== Module initial relate ========== + */ +static int +create_ioexp_objs(void) { + + int i, run_mod; + + /* Clean IOEXP object */ + clean_ioexp_objs(); + /* Get running mode */ + run_mod = IOEXP_MODE_DIRECT; + /* Create IOEXP object */ + for(i=0; i devlen_max) { + snprintf(err_msg, sizeof(err_msg), + "SWP_DEV_PORT too long!"); + goto err_initport_create_tranobj; + } + memset(dev_name, 0, sizeof(dev_name)); + snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id); + /* Create transceiver object */ + ioexp_obj_p = get_ioexp_obj(ioexp_id); + if (!ioexp_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "IOEXP object:%d not exist", ioexp_id); + goto err_initport_create_tranobj; + } + transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p, + ioexp_virt_offset, transvr_type, + chipset_type, run_mod); + if (!transvr_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "Create transceiver object fail :%s", dev_name); + goto err_initport_create_tranobj; + } + /* Setup Lane_ID mapping */ + i = ARRAY_SIZE(port_layout[minor_curr].lane_id); + j = ARRAY_SIZE(transvr_obj_p->lane_id); + if (i != j) { + snprintf(err_msg, sizeof(err_msg), + "Lane_id size inconsistent %d/%d", i, j); + goto err_initport_reg_device; + } + memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int)); + /* Create and register device object */ + if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){ + snprintf(err_msg, sizeof(err_msg), + "register_port_device fail"); + goto err_initport_reg_device; + } + /* Setup device_ptr of transvr_obj */ + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + snprintf(err_msg, sizeof(err_msg), + "get_swpdev_by_name fail"); + goto err_initport_reg_device; + } + transvr_obj_p->transvr_dev_p = dev_p; + /* Success */ + ok_count++; + } + SWPS_INFO("%s: initialed %d port-dev",__func__, ok_count); + return 0; + +err_initport_reg_device: + kfree(transvr_obj_p); +err_initport_create_tranobj: + clean_port_obj(); + SWPS_ERR("%s: %s", __func__, err_msg); + SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n", + port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod); + return -1; +} + +static int __init +swp_module_init(void){ + + if (get_platform_type() < 0){ + goto err_init_out; + } + if (get_layout_info() < 0){ + goto err_init_out; + } + if (register_swp_module() < 0){ + goto err_init_out; + } + if (create_ioexp_objs() < 0){ + goto err_init_ioexp; + } + if (create_port_objs() < 0){ + goto err_init_portobj; + } + if (init_ioexp_objs() < 0){ + goto err_init_portobj; + } + SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION); + return 0; + + +err_init_portobj: + clean_ioexp_objs(); +err_init_ioexp: + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_init_out: + SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION); + return -1; +} + + +static void __exit +swp_module_exit(void){ + clean_port_obj(); + clean_ioexp_objs(); + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); + SWPS_INFO("Remove Inventec switch-port module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(SWP_AUTHOR); +MODULE_DESCRIPTION(SWP_DESC); +MODULE_VERSION(SWP_VERSION); +MODULE_LICENSE(SWP_LICENSE); + +module_init(swp_module_init); +module_exit(swp_module_exit); + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.h new file mode 100644 index 000000000000..b186c2202381 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/inv_swps.h @@ -0,0 +1,131 @@ +#ifndef INV_SWPS_H +#define INV_SWPS_H + +#include "transceiver.h" +#include "io_expander.h" + +/* Module settings */ +#define SWP_CLS_NAME "swps" +#define SWP_DEV_PORT "port" +#define SWP_AUTOCONFIG_ENABLE (1) + +/* Module information */ +#define SWP_AUTHOR "Neil " +#define SWP_DESC "Inventec port and transceiver driver" +#define SWP_VERSION "4.2.3" +#define SWP_LICENSE "GPL" + +/* Module status define */ +#define SWP_STATE_NORMAL (0) +#define SWP_STATE_I2C_DIE (-91) + +/* [Note]: + * Functions and mechanism for auto-detect platform type is ready, + * But HW and BIOS not ready! We need to wait them. + * So, please do not use PLATFORM_TYPE_AUTO until they are ready. + * (2016.06.13) + */ +#define PLATFORM_TYPE_REDWOOD (121) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_REDWOOD + +/* Define platform flag and kernel version */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD) + #define SWPS_KERN_VER_BF_3_8 (1) +#endif + +struct inv_platform_s { + int id; + char name[64]; +}; + +struct inv_ioexp_layout_s { + int ioexp_id; + int ioexp_type; + struct ioexp_addr_s addr[4]; +}; + +struct inv_port_layout_s { + int port_id; + int chan_id; + int ioexp_id; + int ioexp_offset; + int transvr_type; + int chipset_type; + int lane_id[8]; +}; + +/* ========================================== + * Inventec Platform Settings + * ========================================== + */ +struct inv_platform_s platform_map = {PLATFORM_TYPE_REDWOOD, "D7032Q28B" }; + +/* ========================================== + * Redwood Layout configuration + * ========================================== + */ +struct inv_ioexp_layout_s redwood_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, + {3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */ + {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */ + }, +}; + +struct inv_port_layout_s redwood_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + { 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + { 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + { 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + { 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + {11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + {13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + {15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + {19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, + {28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} }, + {29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} }, + {31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} }, +}; + +#endif /* INV_SWPS_H */ + + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.c new file mode 100644 index 000000000000..7c9f8a66aec7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.c @@ -0,0 +1,887 @@ +#include +#include +#include +#include "io_expander.h" + +static struct ioexp_obj_s *ioexp_head_p = NULL; +static struct ioexp_obj_s *ioexp_tail_p = NULL; + +struct ioexp_map_s ioexp_map_redwood_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + +/* ========== Private functions ========== + */ +int check_channel_tier_1(void); + +struct i2c_client * +_get_i2c_client(struct ioexp_obj_s *self, + int chip_id){ + + struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p; + + if (!(i2c_curr_p)){ + SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__); + return NULL; + } + while (i2c_curr_p){ + if ((i2c_curr_p->chip_id) == chip_id){ + return i2c_curr_p->i2c_client_p; + } + i2c_curr_p = i2c_curr_p->next; + } + SWPS_ERR("%s: not exist! :%d\n", __func__, chip_id); + return NULL; +} + + +static int +_common_ioexp_update_one(struct ioexp_obj_s *self, + struct ioexp_addr_s *ioexp_addr, + int chip_id, + int data_width, + int show_err, + char *caller_name) { + int buf = 0; + int err = 0; + int data_id = 0; + int r_offset = 0; + + for(data_id=0; data_idread_offset[data_id]; + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset); + /* Check error */ + if (buf < 0) { + err = 1; + if (show_err) { + SWPS_INFO("IOEXP-%d read fail! :%d \n", self->ioexp_id, buf); + SWPS_INFO("Dump: :%d :0x%02x :%d, :%s\n", + ioexp_addr->chan_id, ioexp_addr->chip_addr, + ioexp_addr->read_offset[data_id], caller_name); + } + continue; + } + /* Update IOEXP object */ + self->chip_data[chip_id].data[data_id] = (uint8_t)buf; + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +common_ioexp_update_all(struct ioexp_obj_s *self, + int show_err, + char *caller_name){ + + int err = 0; + int chip_id = 0; + int chip_amount = self->ioexp_map_p->chip_amount; + + for (chip_id=0; chip_idioexp_map_p->map_addr[chip_id]), + chip_id, + self->ioexp_map_p->data_width, + show_err, + caller_name) < 0) { + err = 1; + } + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + +static int +_common_get_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + char *func_mane){ + uint8_t buf; + int err_code; + + /* Get address */ + err_code = self->fsm_4_direct(self); + if (err_code < 0){ + return err_code; + } + + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Get data form cache */ + buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + return (int)(buf >> bitmap_obj_p->bit_shift & 0x01); +} + + +static int +_common_set_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + int input_val, + char *func_mane){ + int err_code, target_offset; + uint8_t origin_byte; + uint8_t modify_byte; + + /* Get address */ + err_code = self->fsm_4_direct(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Prepare write date */ + origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + switch (input_val) { + case 0: + modify_byte = origin_byte; + SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift); + break; + case 1: + modify_byte = origin_byte; + SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift); + break; + default: + SWPS_ERR("Input value incorrect! :%d :%d :%s\n", + input_val, self->ioexp_id, func_mane); + return ERR_IOEXP_BADINPUT; + } + /* Setup i2c client */ + target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset]; + /* Write byte to chip via I2C */ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id), + target_offset, + modify_byte); + /* Update or bollback object */ + if (err_code < 0){ + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte; + SWPS_ERR("I2C write fail! :%d :%d :%s :%d\n", + input_val, self->ioexp_id, func_mane, err_code); + return err_code; + } + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte; + return 0; +} + + +/* ========== Object public functions ========== + */ +int +common_get_present(struct ioexp_obj_s *self, + int virt_offset){ + + int UNPLUG = 1; + int retval = ERR_IOEXP_UNEXCPT; + + retval = _common_get_bit(self, + &(self->ioexp_map_p->map_present[virt_offset]), + "common_get_present"); + if (retval < 0) { + /* [Note] + * => Transceiver object does not need to handle IOEXP layer issues. + */ + return UNPLUG; + } + return retval; +} + + +int +common_get_reset(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + "common_get_reset"); +} + + +int +common_get_lpmod(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + "common_get_lpmod"); +} + + +int +common_get_modsel(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + "common_get_modsel"); +} + +int +common_set_reset(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + input_val, + "common_set_reset"); +} + + +int +common_set_lpmod(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + input_val, + "common_set_lpmod"); +} + + +int +common_set_modsel(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + input_val, + "common_set_modsel"); +} + +int +ioexp_get_not_support(struct ioexp_obj_s *self, + int virt_offset){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +ioexp_set_not_support(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + return ERR_IOEXP_NOTSUPPORT; +} + +/* ========== Initial functions for IO Expander ========== + */ +int +common_ioexp_init(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + if (self->mode == IOEXP_MODE_DIRECT) { ///important + goto update_common_ioexp_init; + } + /* Setup default value to each physical IO Expander */ + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + /* Get address mapping */ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("%s: IOEXP config incorrect! :%d \n", + __func__, chip_id); + return -1; + } + /* Setup default value */ + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->write_offset[offset], + addr_p->data_default[offset]); + if (err_code < 0){ + SWPS_ERR("%s: set default fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + } + } + +update_common_ioexp_init: + /* Check and update info to object */ + err_code = self->update_all(self, 1, "common_ioexp_init"); + if (err_code < 0) { + SWPS_ERR("%s: update_all() fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +/* ========== Object functions for Final State Machine ========== + */ +int +_is_channel_ready(struct ioexp_obj_s *self){ + + int buf = 0; + int chip_id = 0; /* Use first chip which be registered */ + int data_id = 0; /* Use first byte which be registered */ + struct ioexp_addr_s *ioexp_addr = NULL; + + ioexp_addr = &(self->ioexp_map_p->map_addr[chip_id]); + if (!ioexp_addr){ + SWPS_ERR("%s: config incorrect!\n", __func__); + return ERR_IOEXP_UNEXCPT; + } + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), + ioexp_addr->read_offset[data_id]); + if (buf >= 0){ + return 1; + } + return 0; +} + +int +_ioexp_init_handler(struct ioexp_obj_s *self){ + + int return_val; + + switch (self->mode) { + case IOEXP_MODE_DIRECT: + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + default: + break; + } + SWPS_ERR("%s: exception occur :%d\n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){ + + int result_val; + int show_err = 1; + char *func_mane = "common_ioexp_fsm_4_direct"; + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, and return error */ + return ERR_IOEXP_UNINIT; + } + /* Case: Initial done */ + return 0; + + case STATE_IOEXP_NORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + SWPS_INFO("%s: NORMAL -> ABNORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + self->state = STATE_IOEXP_NORMAL; + return 0; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_DEBUG("%s: ABNORMAL -> NORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("%s: Exception occurs :%d\n", + __func__, self->state); + return ERR_IOEXP_UNEXCPT; +} + +/* ========== Functions for Factory pattern ========== + */ +static struct ioexp_map_s * +get_ioexp_map(int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_REDWOOD_P01P08: + return &ioexp_map_redwood_p01p08_p17p24; + case IOEXP_TYPE_REDWOOD_P09P16: + return &ioexp_map_redwood_p09p16_p25p32; + default: + return NULL; + } +} + + +int +setup_ioexp_ssize_attr(struct ioexp_obj_s *self, + struct ioexp_map_s *ioexp_map_p, + int ioexp_id, + int ioexp_type, + int run_mode){ + switch (run_mode){ + case IOEXP_MODE_DIRECT: /* Direct access device mode */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = ERR_IOEXP_UNEXCPT; + return ERR_IOEXP_UNEXCPT; + } + self->ioexp_id = ioexp_id; + self->ioexp_type = ioexp_type; + self->ioexp_map_p = ioexp_map_p; + self->state = STATE_IOEXP_INIT; + mutex_init(&self->lock); + return 0; +} + + +static int +setup_addr_mapping(struct ioexp_obj_s *self, + struct ioexp_addr_s *addr_map_p){ + if (!addr_map_p){ + SWPS_ERR("%s: map is null\n", __func__); + return -1; + } + self->ioexp_map_p->map_addr = addr_map_p; + return 0; +} + + +static int +setup_ioexp_public_cb(struct ioexp_obj_s *self, + int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + self->get_present = common_get_present; + self->get_reset = common_get_reset; + self->get_lpmod = common_get_lpmod; + self->get_modsel = common_get_modsel; + self->set_reset = common_set_reset; + self->set_lpmod = common_set_lpmod; + self->set_modsel = common_set_modsel; + return 0; + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_ioexp_private_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + + self->init = common_ioexp_init; + self->update_all = common_ioexp_update_all; + self->fsm_4_direct = common_ioexp_fsm_4_direct; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_i2c_client_one(struct ioexp_obj_s *self, + int chip_id){ + + char *err_msg = "ERROR"; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + struct ioexp_i2c_s *i2c_obj_p = NULL; + struct ioexp_i2c_s *i2c_curr_p = NULL; + + int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id; + adap = i2c_get_adapter(chan_id); + if(!adap){ + err_msg = "Can not get adap!"; + goto err_ioexp_setup_i2c_1; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + err_msg = "Can not kzalloc client!"; + goto err_ioexp_setup_i2c_1; + } + i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL); + if (!i2c_obj_p){ + err_msg = "Can not kzalloc i2c_obj_p!"; + goto err_ioexp_setup_i2c_2; + } + client->adapter = adap; + client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr; + i2c_obj_p->i2c_client_p = client; + i2c_obj_p->chip_id = chip_id; + i2c_obj_p->next = NULL; + if (!self->i2c_head_p){ + self->i2c_head_p = i2c_obj_p; + } else { + i2c_curr_p = self->i2c_head_p; + while (i2c_curr_p->next){ + i2c_curr_p = i2c_curr_p->next; + } + i2c_curr_p->next = i2c_obj_p; + } + return 0; + +err_ioexp_setup_i2c_2: + kfree(client); +err_ioexp_setup_i2c_1: + SWPS_ERR("%s: %s :%d\n", __func__, err_msg, chan_id); + return -1; +} + + +static int +setup_i2c_client(struct ioexp_obj_s* self){ + + int result; + int chip_id = 0; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + result = setup_i2c_client_one(self, chip_id); + if (result < 0){ + SWPS_ERR("%s fail! :%d\n", __func__, chip_id); + return -1; + } + } + return 0; +} + +static int +setup_ioexp_config(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("IOEXP config incorrect! :%d \n",chip_id); + return -1; + } + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->conf_offset[offset], + addr_p->conf_default[offset]); + + if (err_code < 0){ + SWPS_INFO("%s: set conf fail! :%d \n", __func__, err_code); + return -2; + } + } + } + return 0; +} + +struct ioexp_obj_s * +_create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_map_s* ioexp_map_p; + struct ioexp_obj_s* result_p; + struct ioexp_i2c_s *i2c_curr_p; + struct ioexp_i2c_s *i2c_next_p; + + /* Get layout */ + ioexp_map_p = get_ioexp_map(ioexp_type); + if (!ioexp_map_p){ + SWPS_ERR("%s: Invalid ioexp_type\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare IOEXP object */ + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + SWPS_ERR("%s: kzalloc failure!\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare static size attributes */ + if (setup_ioexp_ssize_attr(result_p, + ioexp_map_p, + ioexp_id, + ioexp_type, + run_mode) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + /* Prepare address mapping */ + if (setup_addr_mapping(result_p, addr_map_p) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + if (setup_i2c_client(result_p) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + /* Prepare call back functions of object */ + if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + return result_p; + +err_create_ioexp_setup_i2c_fail: + i2c_curr_p = result_p->i2c_head_p; + i2c_next_p = result_p->i2c_head_p; + while (i2c_curr_p){ + i2c_next_p = i2c_curr_p->next; + kfree(i2c_curr_p->i2c_client_p); + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } +err_create_ioexp_setup_attr_fail: + kfree(result_p); +err_create_ioexp_fail: + SWPS_ERR("%s: fail! :%d :%d \n", + __func__, ioexp_id, ioexp_type); + return NULL; +} + + +int +create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_obj_s *ioexp_p = NULL; + + ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type, + addr_map_p, run_mode); + if (!ioexp_p){ + return -1; + } + if (ioexp_head_p == NULL){ + ioexp_head_p = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; + } + ioexp_tail_p->next = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; +} + +static int +_init_ioexp_obj(struct ioexp_obj_s* self) { + + char *err_msg = "ERR"; + char *func_name = "_init_ioexp_obj"; + + /* Setup IOEXP configure byte */ + if (setup_ioexp_config(self) < 0){ + err_msg = "setup_ioexp_config fail"; + goto err_init_ioexp_obj; + } + /* Setup default data */ + if (_ioexp_init_handler(self) < 0){ + err_msg = "_ioexp_init_handler fail"; + goto err_init_ioexp_obj; + } + /* Update all */ + if (self->state == STATE_IOEXP_NORMAL){ + if (self->update_all(self, 1, func_name) < 0){ + err_msg = "update_all() fail"; + goto err_init_ioexp_obj; + } + } + return 0; + +err_init_ioexp_obj: + SWPS_DEBUG("%s: %s\n", __func__, err_msg); + return -1; +} + +int +init_ioexp_objs(void){ + /* Return value: + * 0: Success + * -1: Detect topology error + * -2: SWPS internal error + */ + + struct ioexp_obj_s *curr_p = ioexp_head_p; + + if (!curr_p) { + SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__); + return -2; + } + while (curr_p) { + if (_init_ioexp_obj(curr_p) < 0) { + SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__); + return -1; + } + curr_p = curr_p->next; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + +void +clean_ioexp_objs(void){ + + struct ioexp_i2c_s *i2c_curr_p = NULL; + struct ioexp_i2c_s *i2c_next_p = NULL; + struct ioexp_obj_s *ioexp_next_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + if (ioexp_head_p == NULL){ + ioexp_tail_p = NULL; + return; + } + while(ioexp_curr_p){ + ioexp_next_p = ioexp_curr_p->next; + i2c_curr_p = ioexp_curr_p->i2c_head_p; + while (i2c_curr_p) { + i2c_next_p = i2c_curr_p->next; + kfree(i2c_curr_p->i2c_client_p); + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } + kfree(ioexp_curr_p); + ioexp_curr_p = ioexp_next_p; + } + ioexp_tail_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} + +struct ioexp_obj_s * +get_ioexp_obj(int ioexp_id){ + + struct ioexp_obj_s *result_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + if (ioexp_curr_p->ioexp_id == ioexp_id){ + result_p = ioexp_curr_p; + break; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return result_p; +} +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.h new file mode 100644 index 000000000000..8c51b4f6d94f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/io_expander.h @@ -0,0 +1,136 @@ +#ifndef IO_EXPANDER_H +#define IO_EXPANDER_H + +#include + +/* IOEXP type define (QSFP series) */ +#define IOEXP_TYPE_REDWOOD_P01P08 (10202) +#define IOEXP_TYPE_REDWOOD_P09P16 (10203) + +/* IOEXP mode define */ +#define IOEXP_MODE_DIRECT (19001) + +/* IOEXP state define */ +#define STATE_IOEXP_NORMAL (0) +#define STATE_IOEXP_INIT (-1) +#define STATE_IOEXP_ABNORMAL (-2) + +/* IOEXP error code define */ +#define ERR_IOEXP_NOTSUPPORT (-100) +#define ERR_IOEXP_UNINIT (-101) +#define ERR_IOEXP_BADCONF (-102) +#define ERR_IOEXP_BADINPUT (-105) +#define ERR_IOEXP_UNEXCPT (-199) + + +#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args) +#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args) +#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args) + +#ifdef DEBUG_SWPS +# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args) +#else +# define SWPS_DEBUG(fmt, args...) +#endif + + +struct ioexp_addr_s { + int chan_id; + int chip_addr; + int read_offset[8]; + int write_offset[8]; + int conf_offset[8]; + uint8_t data_default[8]; + uint8_t conf_default[8]; +}; + +struct ioexp_i2c_s { + int chip_id; + struct i2c_client *i2c_client_p; + struct ioexp_i2c_s *next; +}; + + +struct ioexp_bitmap_s { + int chip_id; /* IOEXP chip id */ + int ioexp_voffset; /* IOEXP virtual offset */ + int bit_shift; +}; + +struct ioexp_map_s { + int chip_amount; /* Number of chips that IOEXP object content */ + int data_width; /* Number of (Read/Write/Config) bytes */ + struct ioexp_addr_s *map_addr; /* Chip address info */ + struct ioexp_bitmap_s map_present[8]; /* IOEXP for SFP / QSFP */ + struct ioexp_bitmap_s map_reset[8]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_lpmod[8]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_modsel[8]; /* IOEXP for QSFP */ +}; + +struct ioexp_data_s { + uint8_t data[8]; +}; + +struct ioexp_obj_s { + + /* ============================ + * Object public property + * ============================ + */ + int ioexp_id; + int ioexp_type; + + /* ============================ + * Object private property + * ============================ + */ + struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */ + struct ioexp_map_s *ioexp_map_p; + struct ioexp_obj_s *next; + struct ioexp_i2c_s *i2c_head_p; + struct mutex lock; + int mode; + int state; + + /* =========================================== + * Object public functions + * =========================================== + */ + int (*get_present)(struct ioexp_obj_s *self, int virt_offset); + int (*get_reset)(struct ioexp_obj_s *self, int virt_offset); + int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset); + int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset); + int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val); + + /* =========================================== + * Object private functions + * =========================================== + */ + int (*init)(struct ioexp_obj_s *self); + int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name); + int (*fsm_4_direct)(struct ioexp_obj_s* self); +}; + + +struct ioexp_obj_s* get_ioexp_obj(int ioexp_id); +int create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode); +int init_ioexp_objs(void); +void clean_ioexp_objs(void); + +int check_channel_tier_1(void); + +/* Macro for bit control */ +#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift))) +#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift))) + + +#endif /* IO_EXPANDER_H */ + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.c new file mode 100644 index 000000000000..36ccc45a9216 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.c @@ -0,0 +1,898 @@ +#include +#include +#include +#include +#include "io_expander.h" +#include "transceiver.h" + + +/* ========== Register EEPROM address mapping ========== + */ +struct eeprom_map_s eeprom_map_qsfp = { + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, +}; + +struct eeprom_map_s eeprom_map_qsfp28 = { + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, +}; + + +/* ========== Utility Functions ========== + */ +void +alarm_msg_2_user(struct transvr_obj_s *self, + char *emsg) { + + SWPS_ERR("%s on %s.\n", emsg, self->swp_name); +} + + +/* ========== Private functions ========== + */ +static int +_reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +_transvr_init_handler(struct transvr_obj_s *self); + +static void +_transvr_clean_retry(struct transvr_obj_s *self) { + self->retry = 0; +} + + +static int +_transvr_handle_retry(struct transvr_obj_s *self, int retry) { + /* Return: 0: keep retry + * -1: stop retry + */ + if (self->retry == 0) { + self->retry = retry; + } + self->retry -= 1; + if (self->retry <= 0) { + _transvr_clean_retry(self); + return -1; + } + return 0; +} + +static int +_common_setup_page(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int show_e) { + /* return: + * 0 : OK + * -1 : EEPROM settings incorrect + * -2 : I2C R/W failure + * -3 : Undefined case + */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Check */ + if ((addr < 0) || (offset < 0) || (len < 0)) { + emsg = "EEPROM settings incorrect"; + retval = -1; + goto err_common_setup_page; + } + /* Case1: continue access */ + if ((self->i2c_client_p->addr == addr) && + (self->curr_page == page)) { + return 0; + } + self->i2c_client_p->addr = addr; + /* Case2: select lower page */ + if (page == -1) { + self->curr_page = page; + return 0; + } + /* Case3: select upper page */ + if (page >= 0) { + goto upper_common_setup_page; + } + /* Unexpected case */ + show_e = 1; + emsg = "Unexpected case"; + retval = -3; + goto err_common_setup_page; + +upper_common_setup_page: + if (i2c_smbus_write_byte_data(self->i2c_client_p, + VAL_TRANSVR_PAGE_SELECT_OFFSET, + page) < 0) { + emsg = "I2C R/W failure"; + retval = -2; + goto err_common_setup_page; + } + self->curr_page = page; + mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY); + return 0; + +err_common_setup_page: + if (show_e) { + SWPS_INFO("%s: %s", __func__, emsg); + SWPS_INFO("%s: :0x%02x :%d :%d :%d\n", + __func__, addr, page, offset, len); + } + return retval; +} + +/* ========== Object functions for Final State Machine ========== + */ +int +is_plugged(struct transvr_obj_s *self){ + + int limit = 63; + int present = DEBUG_TRANSVR_INT_VAL; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p; + + if (!ioexp_p) { + snprintf(emsg, limit, "ioexp_p is null!"); + goto err_is_plugged_1; + } + present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset); + switch (present){ + case 0: + return 1; + case 1: + return 0; + case ERR_IOEXP_UNINIT: + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + default: + if (ioexp_p->state == STATE_IOEXP_INIT){ + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + } + break; + } + SWPS_INFO("%s: Exception case! :%d :%d\n", + __func__, present, ioexp_p->state); + return 0; + +err_is_plugged_1: + SWPS_DEBUG("%s: %s\n", __func__, emsg); + return 0; +} + + +static int +detect_transvr_type(struct transvr_obj_s* self){ + + int type = TRANSVR_TYPE_ERROR; + + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + type = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + + /* Case: 1. Wait transceiver I2C module. + * 2. Transceiver I2C module failure. + * Note: 1. SFF allow maximum transceiver initial time is 2 second. So, there + * are exist some case that we need to wait transceiver. + * For these case, we keeps status on "TRANSVR_TYPE_UNPLUGGED", than + * state machine will keep trace with it. + * 2. There exist some I2C failure case we need to handle. Such as user + * insert the failure transceiver, or any reason cause it abnormal. + */ + if (type < 0){ + switch (type) { + case -EIO: + SWPS_DEBUG("%s: %s smbus return:-5 (I/O error)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + case -ENXIO: + SWPS_DEBUG("%s: %s smbus return:-6 (No such device or address)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + default: + break; + } + SWPS_INFO("%s: %s unexpected smbus return:%d \n", + __func__, self->swp_name, type); + return TRANSVR_TYPE_ERROR; + } + /* Identify valid transceiver type */ + switch (type){ + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + break; + case TRANSVR_TYPE_UNKNOW_1: + case TRANSVR_TYPE_UNKNOW_2: + type = TRANSVR_TYPE_UNKNOW_2; + break; + default: + SWPS_DEBUG("%s: unknow type:0x%02x \n", __func__, type); + type = TRANSVR_TYPE_ERROR; + break; + } + return type; +} + + +static int +detect_transvr_state(struct transvr_obj_s *self, + int result[2]){ + /* [return] [result-0] [result-1] + * 0 STATE_TRANSVR_CONNECTED TRANSVR_TYPE_FAKE + * 0 STATE_TRANSVR_DISCONNECTED TRANSVR_TYPE_UNPLUGGED + * 0 STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * 0 STATE_TRANSVR_INIT / + * 0 STATE_TRANSVR_SWAPPED + * 0 STATE_TRANSVR_CONNECTED + * ERR_TRNASVR_BE_ISOLATED STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_I2C_CRASH STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_UNEXCPT STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_UNKNOW_1/2 + */ + result[0] = STATE_TRANSVR_UNEXCEPTED; /* For return state */ + result[1] = TRANSVR_TYPE_ERROR; /* For return type */ + + /* Case1: Fake type */ + if (self->type == TRANSVR_TYPE_FAKE){ + result[0] = STATE_TRANSVR_CONNECTED; + result[1] = TRANSVR_TYPE_FAKE; + return 0; + } + /* Case2: Transceiver unplugged */ + if (!is_plugged(self)){ + result[0] = STATE_TRANSVR_DISCONNECTED; + result[1] = TRANSVR_TYPE_UNPLUGGED; + return 0; + } + /* Case3: Transceiver be isolated */ + if (self->state == STATE_TRANSVR_ISOLATED){ + result[0] = STATE_TRANSVR_ISOLATED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case4: Transceiver plugged */ + result[1] = detect_transvr_type(self); + /* Case4.1: I2C topology crash + * Note : There are some I2C issues cause by transceiver/cables. + * We need to check topology status when user insert it. + * But in this step, we can't not ensure this is the issues + * port. So, it return the ERR_TRANSVR_I2C_CRASH, then upper + * layer will diagnostic I2C topology. + */ + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: %s detect I2C crash :%d\n", + __func__, self->swp_name, self->state); + result[0] = STATE_TRANSVR_UNEXCEPTED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_I2C_CRASH; + } + /* Case4.2: System initial not ready, + * Note : Sometime i2c channel or transceiver EEPROM will delay that will + * cause system in inconsistent state between EEPROM and IOEXP. + * In this case, SWP transceiver object keep state at LINK_DOWN + * to wait system ready. + * By the way, State Machine will handle these case. + */ + if (result[1] == TRANSVR_TYPE_UNPLUGGED){ + result[0] = STATE_TRANSVR_DISCONNECTED; + return 0; + } + /* Case4.3: Error transceiver type */ + if (result[1] == TRANSVR_TYPE_ERROR){ + result[0] = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s detect error type\n", __func__, self->swp_name); + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard!"); + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case3.3: Unknow transceiver type */ + if ((result[1] == TRANSVR_TYPE_UNKNOW_1) || + (result[1] == TRANSVR_TYPE_UNKNOW_2) ){ + result[0] = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + /* Case3.4: During initial process */ + if (self->state == STATE_TRANSVR_INIT){ + result[0] = STATE_TRANSVR_INIT; + return 0; + } + /* Case3.5: Transceiver be swapped */ + if (self->type != result[1]){ + result[0] = STATE_TRANSVR_SWAPPED; + return 0; + } + /* Case3.6: Link up state */ + result[0] = STATE_TRANSVR_CONNECTED; + return 0; +} +int +common_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + + int err; + int detect_result[2]; + int current_state = STATE_TRANSVR_UNEXCEPTED; + int current_type = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_NEW) { + if (_transvr_init_handler(self) < 0){ + return ERR_TRANSVR_INIT_FAIL; + } + } + err = detect_transvr_state(self, detect_result); + if (err < 0) { + return err; + } + /* In Direct mode, driver only detect transceiver when user call driver interface + * which on sysfs. So it only need consider the state of Transceiver. + */ + current_state = detect_result[0]; + current_type = detect_result[1]; + + switch (current_state){ + + case STATE_TRANSVR_DISCONNECTED: /* Transceiver is not plugged */ + self->state = current_state; + self->type = current_type; + return ERR_TRANSVR_UNPLUGGED; + + case STATE_TRANSVR_INIT: /* Transceiver is plugged, system not ready */ + return ERR_TRANSVR_UNINIT; + + case STATE_TRANSVR_ISOLATED: /* Transceiver is plugged, but has some issues */ + return ERR_TRNASVR_BE_ISOLATED; + + case STATE_TRANSVR_CONNECTED: /* Transceiver is plugged, system is ready */ + self->state = current_state; + self->type = current_type; + return 0; + + case STATE_TRANSVR_SWAPPED: /* Transceiver is plugged, system detect user changed */ + self->type = current_type; + if (reload_transvr_obj(self, current_type) < 0){ + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + self->state = current_state; + return 0; + + case STATE_TRANSVR_UNEXCEPTED: /* Transceiver type or state is unexpected case */ + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_UNEXCPT; + + default: + SWPS_INFO("%s: state:%d not in define.\n", __func__, current_state); + break; + } + return ERR_TRANSVR_UNEXCPT; +} + +int +fake_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + +/* ========== Object Initial handler ========== + */ +static int +_is_transvr_valid(struct transvr_obj_s *self, + int type, + int state) { + /* [Return] + * 0 : OK, inserted + * EVENT_TRANSVR_INIT_DOWN : OK, removed + * EVENT_TRANSVR_INIT_FAIL : Outside error, type doesn't supported + * EVENT_TRANSVR_EXCEP_INIT : Internal error, state undefined + */ + switch (type) { + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + break; + default: + SWPS_INFO("detect undefined type:0x%02x on %s\n", + type, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; + } + switch (state) { + case STATE_TRANSVR_DISCONNECTED: + return EVENT_TRANSVR_INIT_DOWN; + case STATE_TRANSVR_INIT: + case STATE_TRANSVR_CONNECTED: + case STATE_TRANSVR_SWAPPED: + break; + default: + SWPS_INFO("detect undefined state:%d on %s\n", + state, self->swp_name); + return EVENT_TRANSVR_EXCEP_INIT; + } + return 0; +} + + +static int +_is_transvr_hw_ready(struct transvr_obj_s *self, + int type){ + /* [Return] + * EVENT_TRANSVR_TASK_DONE : Ready + * EVENT_TRANSVR_TASK_WAIT : Not ready + * EVENT_TRANSVR_INIT_FAIL : Error + */ + int addr = DEBUG_TRANSVR_INT_VAL; + int page = DEBUG_TRANSVR_INT_VAL; + int offs = DEBUG_TRANSVR_INT_VAL; + int bit = DEBUG_TRANSVR_INT_VAL; + int ready = DEBUG_TRANSVR_INT_VAL; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t ab_val = DEBUG_TRANSVR_HEX_VAL; + + switch (type) { + case TRANSVR_TYPE_SFP: + addr = VAL_TRANSVR_8472_READY_ADDR; + page = VAL_TRANSVR_8472_READY_PAGE; + offs = VAL_TRANSVR_8472_READY_OFFSET; + bit = VAL_TRANSVR_8472_READY_BIT; + ready = VAL_TRANSVR_8472_READY_VALUE; + ab_val = VAL_TRANSVR_8472_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + addr = VAL_TRANSVR_8436_READY_ADDR; + page = VAL_TRANSVR_8436_READY_PAGE; + offs = VAL_TRANSVR_8436_READY_OFFSET; + bit = VAL_TRANSVR_8436_READY_BIT; + ready = VAL_TRANSVR_8436_READY_VALUE; + ab_val = VAL_TRANSVR_8436_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + return EVENT_TRANSVR_TASK_DONE; + + default: + emsg = "unexpected case"; + goto err_is_transvr_hw_ready; + } + /* Select target page */ + err = _common_setup_page(self, addr, page, offs, 1, 0); + if (err < 0) { + emsg = "setup page fail"; + goto err_is_transvr_hw_ready; + } + /* Check feature supported + * [Note] + * Some of transceiver/cables doesn't support "Status Indicators" + * (ex:DAC, RJ45 copper SFP ...etc). In these case, we bypass the + * step of checking Status Indicators, then state machine will take + * the following handle procedure. + */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (err < 0) { + emsg = "doesn't support Status Indicators"; + goto bypass_is_transvr_hw_ready; + } + /* Filter abnormal case */ + if (err == ab_val) { + emsg = "detect using unusual definition."; + goto bypass_is_transvr_hw_ready; + } + /* Get Status Indicators */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, offs); + if (err < 0) { + emsg = "detect current value fail"; + goto err_is_transvr_hw_ready; + } + if ((err & (1<:%d\n", __func__, emsg, type); + return EVENT_TRANSVR_TASK_DONE; + +err_is_transvr_hw_ready: + SWPS_DEBUG("%s: %s :%d\n", __func__, emsg, type); + return EVENT_TRANSVR_INIT_FAIL; +} + +static int +_transvr_init_handler(struct transvr_obj_s *self){ + + int detect[2]; + int d_state = STATE_TRANSVR_UNEXCEPTED; + int d_type = TRANSVR_TYPE_ERROR; + int result = ERR_TRANSVR_UNINIT; + int retry = 6; /* (6+1) x 0.3 = 2.1s > spec:2.0s */ + int elimit = 63; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Clean and check callback */ + self->state = STATE_TRANSVR_INIT; + if (self->init == NULL) { + snprintf(emsg, elimit, "init() is null"); + goto initer_err_case_unexcept_0; + } + /* Detect transceiver information */ + result = detect_transvr_state(self, detect); + if (result < 0) { + snprintf(emsg, elimit, "detect_transvr_state() fail"); + switch (result) { + case ERR_TRANSVR_I2C_CRASH: + goto initer_err_case_i2c_ceash; + case ERR_TRNASVR_BE_ISOLATED: + goto initer_err_case_be_isolated; + + case ERR_TRANSVR_UNEXCPT: + default: + break; + } + goto initer_err_case_retry_1; + } + d_state = detect[0]; + d_type = detect[1]; + + /* Verify transceiver type and state */ + switch (_is_transvr_valid(self, d_type, d_state)) { + case 0: + break; + case EVENT_TRANSVR_INIT_DOWN: + goto initer_ok_case_down;; + case EVENT_TRANSVR_INIT_FAIL: + snprintf(emsg, elimit, "transceiver type doesn't support"); + goto initer_err_case_alarm_to_user; + case EVENT_TRANSVR_EXCEP_INIT: + default: + goto initer_err_case_unexcept_0; + } + + /* Handle reload case */ + if (self->type != d_type){ + /* This is the protect mechanism. Normally, This case will not happen. + * When State machine detect swap event during initial, It will trigger + * reload function to ensure type correct. */ + if (_reload_transvr_obj(self, d_type) < 0){ + snprintf(emsg, elimit, "reload object fail"); + goto initer_err_case_unexcept_0; + } + } + + /* Check transceiver HW initial ready */ + switch (_is_transvr_hw_ready(self, d_type)) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_err_case_retry_1; + case EVENT_TRANSVR_INIT_FAIL: + default: + goto initer_err_case_unexcept_0; + } + + /* Try to update all and check */ + if (self->update_all(self, 1) < 0){ + /* For some transceiver, EEPROME has lag issues during initial stage. + * In this case, we set status back to STATE_TRANSVR_NEW, than it will + * be checked in next polling cycle. */ + goto initer_err_case_retry_1; + } + + /* Execute init() call back */ + result = self->init(self); + switch (result) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_ok_case_wait; + + default: + snprintf(emsg, elimit, "undefined init() return:%d\n", result); + goto initer_err_case_unexcept_0; + } + goto initer_ok_case_up; + + +initer_ok_case_wait: + return EVENT_TRANSVR_TASK_WAIT; + +initer_ok_case_up: + self->state = STATE_TRANSVR_CONNECTED; + self->temp = 0; + return EVENT_TRANSVR_INIT_UP; + +initer_ok_case_down: + self->temp = 0; + self->state = STATE_TRANSVR_DISCONNECTED; + return EVENT_TRANSVR_INIT_DOWN; + +initer_err_case_i2c_ceash: + SWPS_DEBUG("%s: %s :%s :I2C crash\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_I2C_CRASH; + +initer_err_case_be_isolated: + SWPS_DEBUG("%s: %s :%s :isolated\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return EVENT_TRANSVR_EXCEP_ISOLATED; + +initer_err_case_retry_1: + SWPS_DEBUG("%s: %s :%s :retry\n", + __func__, emsg, self->swp_name); + if (_transvr_handle_retry(self, retry) == 0) { + self->state = STATE_TRANSVR_NEW; + return EVENT_TRANSVR_INIT_REINIT; + } + goto initer_err_case_alarm_to_user; + +initer_err_case_unexcept_0: + self->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_INIT_FAIL; + +initer_err_case_alarm_to_user: + SWPS_DEBUG("%s: %s :%s :alarm_to_user\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard"); + return EVENT_TRANSVR_INIT_FAIL; +} + +static int +setup_transvr_private_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->fsm_4_direct = common_fsm_4_direct_mode; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->fsm_4_direct = common_fsm_4_direct_mode; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->fsm_4_direct = common_fsm_4_direct_mode; + return 0; + + case TRANSVR_TYPE_FAKE: + self->fsm_4_direct = fake_fsm_4_direct_mode; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static struct eeprom_map_s * +get_eeprom_map(int transvr_type){ + + switch (transvr_type){ + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + return &eeprom_map_qsfp; + case TRANSVR_TYPE_QSFP_28: + return &eeprom_map_qsfp28; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return NULL; +} + + +static int +setup_transvr_ssize_attr(char *swp_name, + struct transvr_obj_s *self, + struct eeprom_map_s *map_p, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int chan_id, + int run_mode){ + switch (run_mode){ + case TRANSVR_MODE_DIRECT: /* Direct access device mode */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = DEBUG_TRANSVR_INT_VAL; + return -1; + } + self->eeprom_map_p = map_p; + self->ioexp_obj_p = ioexp_obj_p; + self->ioexp_virt_offset = ioexp_virt_offset; + self->chan_id = chan_id; + self->layout = transvr_type; + self->type = transvr_type; + self->chipset_type = chipset_type; + self->state = STATE_TRANSVR_NEW; + self->info = STATE_TRANSVR_NEW; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + strncpy(self->swp_name, swp_name, 32); + mutex_init(&self->lock); + return 0; +} + + + +static int +setup_i2c_client(struct transvr_obj_s *self){ + + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + adap = i2c_get_adapter(self->chan_id); + if(!adap){ + snprintf(err_msg, sizeof(err_msg), + "can not get adap:%d", self->chan_id); + goto err_setup_i2c_client; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + snprintf(err_msg, sizeof(err_msg), + "can not kzalloc client:%d", self->chan_id); + goto err_setup_i2c_client; + } + client->adapter = adap; + self->i2c_client_p = client; + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + return 0; + +err_setup_i2c_client: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return ERR_TRANSVR_UNEXCPT; +} + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode){ + + struct transvr_obj_s *result_p; + struct eeprom_map_s *map_p; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Allocate transceiver object */ + map_p = get_eeprom_map(transvr_type); + if (!map_p){ + snprintf(err_msg, sizeof(err_msg), + "Invalid transvr_type:%d", transvr_type); + goto err_create_transvr_fail; + } + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_create_transvr_fail; + } + /* Prepare static size attributes */ + if (setup_transvr_ssize_attr(swp_name, + result_p, + map_p, + ioexp_obj_p, + ioexp_virt_offset, + transvr_type, + chipset_type, + chan_id, + run_mode) < 0){ + goto err_create_transvr_sattr_fail; + } + + /* Prepare call back functions of object */ + if (setup_transvr_private_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_sattr_fail; + } + /* Prepare i2c client object */ + if (setup_i2c_client(result_p) < 0){ + goto err_create_transvr_sattr_fail; + } + return result_p; +err_create_transvr_sattr_fail: + kfree(result_p); +err_create_transvr_fail: + SWPS_ERR("%s: %s :%d :%d :%d\n", + __func__, err_msg, chan_id, ioexp_virt_offset, transvr_type); + return NULL; +} + + +static int +_reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + struct eeprom_map_s *new_map_p; + struct eeprom_map_s *old_map_p = self->eeprom_map_p; + struct i2c_client *old_i2c_p = self->i2c_client_p; + int old_type = self->type; + + /* Change state to STATE_TRANSVR_INIT */ + self->state = STATE_TRANSVR_INIT; + self->type = new_type; + /* Replace EEPROME map */ + new_map_p = get_eeprom_map(new_type); + if (!new_map_p){ + goto err_private_reload_func_1; + } + self->eeprom_map_p = new_map_p; + /* Reload i2c client */ + if (setup_i2c_client(self) < 0){ + goto err_private_reload_func_2; + } + if (setup_transvr_private_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + kfree(old_i2c_p); + return 0; + +err_private_reload_func_3: + SWPS_INFO("%s: init() fail!\n", __func__); + kfree(old_i2c_p); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return -2; + +err_private_reload_func_2: + self->eeprom_map_p = old_map_p; + self->i2c_client_p = old_i2c_p; +err_private_reload_func_1: + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = old_type; + SWPS_INFO("%s fail! :0x%02x\n", __func__, new_type); + return -1; +} + + +static int +reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + int result_val = ERR_TRANSVR_UNEXCPT; + + /* Reload phase */ + result_val = _reload_transvr_obj(self, new_type); + if (result_val < 0){ + SWPS_INFO("%s: reload phase fail! :%d\n", + __func__, result_val); + return EVENT_TRANSVR_RELOAD_FAIL; + } + /* Initial phase */ + result_val = _transvr_init_handler(self); + if (result_val < 0){ + SWPS_INFO("%s: initial phase fail! :%d\n", + __func__, result_val); + } + return result_val; +} + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.h new file mode 100644 index 000000000000..487fcdd76773 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/modules/transceiver.h @@ -0,0 +1,167 @@ +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* Transceiver type define */ +#define TRANSVR_TYPE_UNKNOW_1 (0x00) +#define TRANSVR_TYPE_UNKNOW_2 (0xff) +#define TRANSVR_TYPE_SFP (0x03) /* Define for SFP, SFP+, SFP28 */ +#define TRANSVR_TYPE_QSFP (0x0c) +#define TRANSVR_TYPE_QSFP_PLUS (0x0d) +#define TRANSVR_TYPE_QSFP_28 (0x11) +#define TRANSVR_TYPE_UNPLUGGED (0xfa) /* Define for ERROR handle */ +#define TRANSVR_TYPE_FAKE (0xfc) /* Define for ERROR handle */ +#define TRANSVR_TYPE_INCONSISTENT (0xfd) /* Define for ERROR handle */ +#define TRANSVR_TYPE_ERROR (0xfe) /* Define for ERROR handle */ + +/* Transceiver mode define */ +#define TRANSVR_MODE_DIRECT (21000) + +/* Transceiver state define + * [Note] + * 1. State is used to represent the state of "Transceiver" and "Object". + * 2. State for different target has different means. The description as following: + */ +#define STATE_TRANSVR_CONNECTED (0) /* [Transvr]:Be plugged in. [Obj]:Link up, and work normally. */ +#define STATE_TRANSVR_NEW (-100) /* [Transvr]:(Not used) [Obj]:Create */ +#define STATE_TRANSVR_INIT (-101) /* [Transvr]:Be plugged in. [Obj]:Link up, and in initial process. */ +#define STATE_TRANSVR_ISOLATED (-102) /* [Transvr]:Be plugged in. [Obj]:Isolate, and not provide service. */ +#define STATE_TRANSVR_SWAPPED (-200) /* [Transvr]:Be plugged in. [Obj]:(Not used) */ +#define STATE_TRANSVR_DISCONNECTED (-300) /* [Transvr]:Un-plugged. [Obj]:Link down, and not provide service. */ +#define STATE_TRANSVR_UNEXCEPTED (-901) /* [Transvr]:Any [Obj]:Any, and not in expect case. */ + +/* Event for task handling */ +#define EVENT_TRANSVR_TASK_WAIT (2101) +#define EVENT_TRANSVR_TASK_DONE (0) +#define EVENT_TRANSVR_TASK_FAIL (-2101) +/* Event for initial handling */ +#define EVENT_TRANSVR_INIT_UP (2201) +#define EVENT_TRANSVR_INIT_DOWN (1) +#define EVENT_TRANSVR_INIT_REINIT (-2201) +#define EVENT_TRANSVR_INIT_FAIL (-2202) +/* Event for others */ +#define EVENT_TRANSVR_RELOAD_FAIL (-2301) +#define EVENT_TRANSVR_EXCEP_INIT (-2401) +#define EVENT_TRANSVR_EXCEP_UP (-2402) +#define EVENT_TRANSVR_EXCEP_DOWN (-2403) +#define EVENT_TRANSVR_EXCEP_SWAP (-2404) +#define EVENT_TRANSVR_EXCEP_EXCEP (-2405) +#define EVENT_TRANSVR_EXCEP_ISOLATED (-2406) +#define EVENT_TRANSVR_I2C_CRASH (-2501) + +/* Transceiver error code define */ +#define ERR_TRANSVR_UNINIT (-201) +#define ERR_TRANSVR_UNPLUGGED (-202) +#define ERR_TRANSVR_ABNORMAL (-203) +#define ERR_TRANSVR_NOSTATE (-204) +#define ERR_TRANSVR_NOTSUPPORT (-205) +#define ERR_TRANSVR_BADINPUT (-206) +#define ERR_TRANSVR_UPDATE_FAIL (-207) +#define ERR_TRANSVR_RELOAD_FAIL (-208) +#define ERR_TRANSVR_INIT_FAIL (-209) +#define ERR_TRANSVR_UNDEFINED (-210) +#define ERR_TRANSVR_TASK_FAIL (-211) +#define ERR_TRANSVR_TASK_BUSY (-212) +#define ERR_TRANSVR_FUNC_DISABLE (-214) +#define ERR_TRANSVR_I2C_CRASH (-297) +#define ERR_TRNASVR_BE_ISOLATED (-298) +#define ERR_TRANSVR_UNEXCPT (-299) + +/* For debug */ +#define DEBUG_TRANSVR_INT_VAL (-99) +#define DEBUG_TRANSVR_HEX_VAL (0xfe) +#define DEBUG_TRANSVR_STR_VAL "ERROR" + +/* For system internal */ +#define VAL_TRANSVR_COMID_ARREESS (0x50) +#define VAL_TRANSVR_COMID_OFFSET (0x00) +#define VAL_TRANSVR_8472_READY_ADDR (0x51) +#define VAL_TRANSVR_8472_READY_PAGE (-1) +#define VAL_TRANSVR_8472_READY_OFFSET (110) +#define VAL_TRANSVR_8472_READY_BIT (0) +#define VAL_TRANSVR_8472_READY_VALUE (0) +#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_READY_ADDR (0x50) +#define VAL_TRANSVR_8436_READY_PAGE (-1) +#define VAL_TRANSVR_8436_READY_OFFSET (2) +#define VAL_TRANSVR_8436_READY_BIT (0) +#define VAL_TRANSVR_8436_READY_VALUE (0) +#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_PWD_ADDR (0x50) +#define VAL_TRANSVR_8436_PWD_PAGE (-1) +#define VAL_TRANSVR_8436_PWD_OFFSET (123) +#define VAL_TRANSVR_PAGE_FREE (-99) +#define VAL_TRANSVR_PAGE_SELECT_OFFSET (127) +#define VAL_TRANSVR_PAGE_SELECT_DELAY (5) +#define VAL_TRANSVR_TASK_RETRY_FOREVER (-999) +#define VAL_TRANSVR_FUNCTION_DISABLE (-1) +#define STR_TRANSVR_QSFP "QSFP" +#define STR_TRANSVR_QSFP_PLUS "QSFP+" +#define STR_TRANSVR_QSFP28 "QSFP28" + +/* BCM chip type define */ +#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress */ + +/* Info from transceiver EEPROM */ +struct eeprom_map_s { + int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los; + int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable; + int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault; +}; + +/* Class of transceiver object */ +struct transvr_obj_s { + /* ========== Object private property ========== + */ + struct device *transvr_dev_p; + struct eeprom_map_s *eeprom_map_p; + struct i2c_client *i2c_client_p; + struct ioexp_obj_s *ioexp_obj_p; + struct mutex lock; + char swp_name[32]; + int auto_tx_disable; + int chan_id; + int chipset_type; + int curr_page; + int info; + int ioexp_virt_offset; + int lane_id[8]; + int layout; + int mode; + int retry; + int state; + int temp; + int type; + + /* ========== Object private functions ========== + */ + int (*init)(struct transvr_obj_s *self); + int (*update_all)(struct transvr_obj_s *self, int show_err); + int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name); +}; + + +/* For AVL Mapping */ +struct transvr_avl_s { + char vendor_name[32]; + char vendor_pn[32]; + int (*init)(struct transvr_obj_s *self); +}; + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode); + +void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + +#endif /* TRANSCEIVER_H */ + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/utils/inventec_d7032_util.py b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/utils/inventec_d7032_util.py new file mode 100755 index 000000000000..6625efc00ed2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7032q28b/utils/inventec_d7032_util.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Inventec, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[D7032]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +"with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +instantiate =[ +#'echo pca9545 0x70> /sys/bus/i2c/devices/i2c-0/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-1/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-2/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-3/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-4/new_device', +#'echo inv_psoc 0x66> /sys/bus/i2c/devices/i2c-5/new_device', +#'echo inv_cpld 0x55> /sys/bus/i2c/devices/i2c-5/new_device', +'echo inv_eeprom 0x53> /sys/bus/i2c/devices/i2c-0/new_device'] + +drivers =[ +'lpc_ich', +'i2c-i801', +'i2c-mux', +'i2c-mux-pca954x', +'i2c-dev', +'inv_eeprom', +'inv_platform', +'inv_psoc', +'inv_cpld', +'swps', +'inv_pthread'] + + + +def system_install(): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("rmmod i2c_ismt ", 1) + status, output = exec_cmd("rmmod i2c-i801 ", 1) + status, output = exec_cmd("rmmod gpio_ich",1) + status, output = exec_cmd("insmod /lib/modules/3.16.0-5-amd64/extra/gpio-ich.ko gpiobase=0",1) + + #install drivers + for i in range(0,len(drivers)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #instantiate devices + for i in range(0,len(instantiate)): + time.sleep(1) + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(22,30): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-4/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(30,38): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-5/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(6,14): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-2/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(14,22): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-3/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print " D7032 devices detected...." + return + +def uninstall(): + global FORCE + exec_cmd("rmmod gpio_ich",1) + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0) + ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/Makefile new file mode 100755 index 000000000000..37cbc2f4e8be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/Makefile @@ -0,0 +1,7 @@ +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += inv_pthread.o +obj-m += inv_eeprom.o +obj-m += swps.o +swps-objs := inv_swps.o io_expander.o transceiver.o + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_cpld.c new file mode 100644 index 000000000000..683ffa0ff3ce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_cpld.c @@ -0,0 +1,415 @@ +/* + * 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 "I2CHostCommunication.h" + +#define USE_SMBUS 1 + +/* definition */ +#define CPLD_INFO_OFFSET 0x00 +#define CPLD_PSU_OFFSET 0x08 +#define CPLD_LED_OFFSET 0x0E +#define CPLD_LED_STATU_OFFSET 0x0D +#define CPLD_CTL_OFFSET 0x0C + + + +/* Each client has this additional data */ +struct cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +} + +static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t show_info(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[4]; + + memset(b, 0, 4); + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4); + mutex_unlock(&data->update_lock); + + if(status != 4) return sprintf(buf, "read cpld info fail\n"); + + status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/ + status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf); + status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf); + + return strlen(buf); +} + + +static ssize_t show_ctl(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[1]; + + mutex_lock(&data->update_lock); + + status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld ctl fail\n"); + + + status = sprintf (buf, "0x%X\n", b[0]); + + return strlen(buf); +} + +static ssize_t set_ctl(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1); + if(temp) byte |= (1<<0); + else byte &= ~(1<<0); + cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + + +static char* led_str[] = { + "OFF", //000 + "0.5 Hz", //001 + "1 Hz", //010 + "2 Hz", //011 + "NA", //100 + "NA", //101 + "NA", //110 + "ON", //111 +}; + +static ssize_t show_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET); + + byte = (byte >> shift) & 0x7; + + /* + 0: off + 1: 0.5hz + 2: 1 hz + 3: 2 hz + 4~6: not define + 7: on + */ + + status = sprintf (buf, "%d: %s\n", byte, led_str[byte]); + + return strlen(buf); +} + +static ssize_t set_led(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 16); + u8 byte; + int shift = (attr->index == 0)?3:0; + + temp &= 0x7; + //validate temp value: 0,1,2,3,7, TBD + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + byte &= ~(0x7<update_lock); + + return count; +} + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu0 | psu1 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 1)?0:3; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + + +static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0); +static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0); + +static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0); +static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1); + +static struct attribute *cpld_attributes[] = { + //info + &sensor_dev_attr_info.dev_attr.attr, + &sensor_dev_attr_ctl.dev_attr.attr, + + &sensor_dev_attr_grn_led.dev_attr.attr, + &sensor_dev_attr_red_led.dev_attr.attr, + + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + NULL +}; + +static const struct attribute_group cpld_group = { + .attrs = cpld_attributes, +}; + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int +cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + + printk("+%s\n", __func__); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld_group); + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpld_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpld_group); + i2c_set_clientdata(client, NULL); + kfree(data); + return 0; +} + +static const struct i2c_device_id cpld_ids[] = { + { "inv_cpld", 0, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, cpld_ids); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_cpld_init(void) +{ + return i2c_add_driver(&cpld_driver); +} + +static void __exit inv_cpld_exit(void) +{ + i2c_del_driver(&cpld_driver); +} + +MODULE_AUTHOR("eddie.lan "); +MODULE_DESCRIPTION("inv cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_cpld_init); +module_exit(inv_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_eeprom.c new file mode 100644 index 000000000000..3d13f3b04719 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_eeprom.c @@ -0,0 +1,181 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void inv_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } + +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + inv_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute inv_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = inv_eeprom_read, +}; + +static int inv_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int inv_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id inv_eeprom_id[] = { + { "inv_eeprom", 0 }, + { } +}; + +static struct i2c_driver inv_eeprom_driver = { + .driver = { + .name = "inv_eeprom", + }, + .probe = inv_eeprom_probe, + .remove = inv_eeprom_remove, + .id_table = inv_eeprom_id, +}; + +module_i2c_driver(inv_eeprom_driver); + +MODULE_AUTHOR("Inventec"); +MODULE_DESCRIPTION("Inventec D7054 Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_platform.c new file mode 100644 index 000000000000..5988bb55a434 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_platform.c @@ -0,0 +1,219 @@ +#include +//#include +#include +#include +#include +#include +#include + +#include +//#include +//#include + +//#include +//#define IO_EXPAND_BASE 64 +//#define IO_EXPAND_NGPIO 16 + +struct inv_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +#define bus_id(id) (id) +static struct pca954x_platform_mode mux_modes_0[] = { + {.adap_id = bus_id(2),}, {.adap_id = bus_id(3),}, + {.adap_id = bus_id(4),}, {.adap_id = bus_id(5),}, + {.adap_id = bus_id(6),}, {.adap_id = bus_id(7),}, + {.adap_id = bus_id(8),}, {.adap_id = bus_id(9),}, +}; +static struct pca954x_platform_mode mux_modes_0_0[] = { + {.adap_id = bus_id(10),}, {.adap_id = bus_id(11),}, + {.adap_id = bus_id(12),}, {.adap_id = bus_id(13),}, + {.adap_id = bus_id(14),}, {.adap_id = bus_id(15),}, + {.adap_id = bus_id(16),}, {.adap_id = bus_id(17),}, +}; + +static struct pca954x_platform_mode mux_modes_0_1[] = { + {.adap_id = bus_id(18),}, {.adap_id = bus_id(19),}, + {.adap_id = bus_id(20),}, {.adap_id = bus_id(21),}, + {.adap_id = bus_id(22),}, {.adap_id = bus_id(23),}, + {.adap_id = bus_id(24),}, {.adap_id = bus_id(25),}, +}; + +static struct pca954x_platform_mode mux_modes_0_2[] = { + {.adap_id = bus_id(26),}, {.adap_id = bus_id(27),}, + {.adap_id = bus_id(28),}, {.adap_id = bus_id(29),}, + {.adap_id = bus_id(30),}, {.adap_id = bus_id(31),}, + {.adap_id = bus_id(32),}, {.adap_id = bus_id(33),}, +}; + +static struct pca954x_platform_mode mux_modes_0_3[] = { + {.adap_id = bus_id(34),}, {.adap_id = bus_id(35),}, + {.adap_id = bus_id(36),}, {.adap_id = bus_id(37),}, + {.adap_id = bus_id(38),}, {.adap_id = bus_id(39),}, + {.adap_id = bus_id(40),}, {.adap_id = bus_id(41),}, +}; + +static struct pca954x_platform_mode mux_modes_0_4[] = { + {.adap_id = bus_id(42),}, {.adap_id = bus_id(43),}, + {.adap_id = bus_id(44),}, {.adap_id = bus_id(45),}, + {.adap_id = bus_id(46),}, {.adap_id = bus_id(47),}, + {.adap_id = bus_id(48),}, {.adap_id = bus_id(49),}, +}; + +static struct pca954x_platform_mode mux_modes_0_5[] = { + {.adap_id = bus_id(50),}, {.adap_id = bus_id(51),}, + {.adap_id = bus_id(52),}, {.adap_id = bus_id(53),}, + {.adap_id = bus_id(54),}, {.adap_id = bus_id(55),}, + {.adap_id = bus_id(56),}, {.adap_id = bus_id(57),}, +}; + +static struct pca954x_platform_mode mux_modes_0_6[] = { + {.adap_id = bus_id(58),}, {.adap_id = bus_id(59),}, + {.adap_id = bus_id(60),}, {.adap_id = bus_id(61),}, + {.adap_id = bus_id(62),}, {.adap_id = bus_id(63),}, + {.adap_id = bus_id(64),}, {.adap_id = bus_id(65),}, +}; + +//no i2c device driver attach to mux 7 + + +static struct pca954x_platform_data mux_data_0 = { + .modes = mux_modes_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_0 = { + .modes = mux_modes_0_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_1 = { + .modes = mux_modes_0_1, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_2 = { + .modes = mux_modes_0_2, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_3 = { + .modes = mux_modes_0_3, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_4 = { + .modes = mux_modes_0_4, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_5 = { + .modes = mux_modes_0_5, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_6 = { + .modes = mux_modes_0_6, + .num_modes = 8, +}; + +static struct i2c_board_info i2c_device_info0[] __initdata = { + {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc + {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld + {"pca9548", 0, 0x71, &mux_data_0, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info2[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, +}; +static struct i2c_board_info i2c_device_info3[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, +}; +static struct i2c_board_info i2c_device_info4[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, +}; +static struct i2c_board_info i2c_device_info5[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, +}; +static struct i2c_board_info i2c_device_info6[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0}, +}; +static struct i2c_board_info i2c_device_info7[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0}, +}; +static struct i2c_board_info i2c_device_info8[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0}, +}; + + +static struct inv_i2c_board_info i2cdev_list[] = { + {0, ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //smbus 0 + + {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux 0 + {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux 1 + {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux 2 + {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux 3 + {bus_id(6), ARRAY_SIZE(i2c_device_info6), i2c_device_info6 }, //mux 4 + {bus_id(7), ARRAY_SIZE(i2c_device_info7), i2c_device_info7 }, //mux 5 + {bus_id(8), ARRAY_SIZE(i2c_device_info8), i2c_device_info8 }, //mux 6 + +}; + +///////////////////////////////////////////////////////////////////////////////////////// +#if 0 +static struct i2c_gpio_platform_data i2c_gpio_platdata0 = { + .scl_pin = 58, + .sda_pin = 75, + + .udelay = 5, //5:100kHz + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, + .scl_is_output_only = 0 +}; + +static struct platform_device device_i2c_gpio0 = { + .name = "i2c-gpio", + .id = 0, // adapter number + .dev.platform_data = &i2c_gpio_platdata0, +}; +#endif +static int __init inv_platform_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j; + + printk("%s \n", __func__); + +#if 0 + //use i2c-gpio + //register i2c gpio + //config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 + outl( inl(0x533) | (1<<2), 0x533); + outl( inl(0x541) | (1<<3), 0x541); + + ret = platform_device_register(&device_i2c_gpio0); + if (ret) { + printk(KERN_ERR "i2c-gpio: device_i2c_gpio0 register fail %d\n", ret); + } + #endif + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "I2CHostCommunication.h" + +#define IMPLEMENT_IPMI_CODE 1 +int USE_IPMI=0; +//================================= +#if IMPLEMENT_IPMI_CODE +#include +#include +#include +#include + +#define IPMI_MAX_INTF (4) +#define NETFN_OEM 0x30 +#define CMD_GETDATA 0x31 +#define CMD_SETDATA 0x32 + +struct mutex ipmi_mutex; + +static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data); +static ipmi_user_t ipmi_mh_user = NULL; +static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,}; + +static atomic_t dummy_count = ATOMIC_INIT(0); +static void dummy_smi_free(struct ipmi_smi_msg *msg) +{ + atomic_dec(&dummy_count); +} +static void dummy_recv_free(struct ipmi_recv_msg *msg) +{ + atomic_dec(&dummy_count); +} +static struct ipmi_smi_msg halt_smi_msg = { + .done = dummy_smi_free +}; +static struct ipmi_recv_msg halt_recv_msg = { + .done = dummy_recv_free +}; +#endif +//================================= + +#define USE_SMBUS 1 + +#define FAN_NUM 4 +#define PSU_NUM 2 + +struct __attribute__ ((__packed__)) psoc_psu_layout { + u16 psu1_iin; + u16 psu2_iin; + u16 psu1_iout; + u16 psu2_iout; + + u16 psu1_pin; + u16 psu2_pin; + u16 psu1_pout; + u16 psu2_pout; + + u16 psu1_vin; + u16 psu2_vin; + u16 psu1_vout; + u16 psu2_vout; +}; + +struct __attribute__ ((__packed__)) psoc_layout { + u8 ctl; //offset: 0 + u16 switch_temp; //offset: 1 + u8 reserve0; //offset: 3 + + u8 fw_upgrade; //offset: 4 + + //i2c bridge + u8 i2c_st; //offset: 5 + u8 i2c_ctl; //offset: 6 + u8 i2c_addr; //offset: 7 + u8 i2c_data[0x20]; //offset: 8 + + //gpo + u8 led_ctl; //offset: 28 + + u8 gpio; //offset: 29 + + //pwm duty + u8 pwm[FAN_NUM]; //offset: 2a + u8 pwm_psu[PSU_NUM]; //offset: 2e + + //fan rpm + u16 fan[FAN_NUM*2]; //offset: 30 + + u8 reserve1[4]; //offset: 40 + + //gpi + u8 gpi_fan; //offset: 44 + + //psu state + u8 psu_state; //offset: 45 + + //temperature + u16 temp[5]; //offset: 46 + u16 temp_psu[PSU_NUM]; //offset: 50 + + //version + u8 version[2]; //offset: 54 + + u8 reserve2[4]; //offset: 56 + struct psoc_psu_layout psu_info; //offset: 5a +}; + +/* definition */ +/* definition */ +#define PSOC_OFF(m) offsetof(struct psoc_layout, m) +#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m) + +#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp) +#define PWM_OFFSET PSOC_OFF(pwm) +#define THERMAL_OFFSET PSOC_OFF(temp) +#define RPM_OFFSET PSOC_OFF(fan) +#define DIAG_FLAG_OFFSET PSOC_OFF(ctl) +#define FAN_LED_OFFSET PSOC_OFF(led_ctl) +#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan) +#define PSOC_PSU_OFFSET PSOC_OFF(psu_state) +#define VERSION_OFFSET PSOC_OFF(version) +#define PSU_INFO_OFFSET PSOC_OFF(psu_info) + +/* Each client has this additional data */ +struct psoc_data { + struct device *hwmon_dev; + struct mutex update_lock; + u32 diag; +}; + +/*-----------------------------------------------------------------------*/ +#if IMPLEMENT_IPMI_CODE +static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data) +{ + struct completion *comp = recv_msg->user_msg_data; + if (comp) + complete(comp); + else + ipmi_free_recv_msg(recv_msg); + return; +} + +int ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length) +{ + int rv=0,i; + struct ipmi_system_interface_addr addr; + uint8_t _data[data_length]; + struct kernel_ipmi_msg msg; + struct completion comp; + + if(!mutex_trylock(&ipmi_mutex)) return 0; + +// for (i=0,rv=1; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +} + +static ssize_t psoc_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if USE_SMBUS +if(USE_IPMI==0) +{ + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +} + +#if 0 +static u32 psoc_read32(struct i2c_client *client, u8 offset) +{ + u32 value = 0; + u8 buf[4]; + + if( psoc_i2c_read(client, buf, offset, 4) == 4) + value = (buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]); + + return value; +} +#endif + +static u16 psoc_read16(struct i2c_client *client, u8 offset) +{ + u16 value = 0; + u8 buf[2]; + + if(psoc_i2c_read(client, buf, offset, 2) == 2) + value = (buf[0]<<8 | buf[1]<<0); + + return value; +} + +static u8 psoc_read8(struct i2c_client *client, u8 offset) +{ + u8 value = 0; + u8 buf = 0; + + if(psoc_i2c_read(client, &buf, offset, 1) == 1) + value = buf; + + return value; +} + +//PSOC i2c bridge regsters +#define PSOC_I2C_STATUS 0x05 +#define PSOC_I2C_CNTRL 0x06 +#define PSOC_I2C_ADDR 0x07 +#define PSOC_I2C_DATA 0x08 + +//status bit definition +#define PSOC_I2C_START (1 << 0) +#define PSOC_PMB_SEL (1 << 7) + +//addr bits definition +#define PSOC_I2C_READ (1 << 0) + +//PMBUS registers definition +#define PMBUS_READ_VIN (0x88) +#define PMBUS_READ_IIN (0x89) +#define PMBUS_READ_VOUT (0x8B) +#define PMBUS_READ_IOUT (0x8C) +#define PMBUS_READ_POUT (0x96) +#define PMBUS_READ_PIN (0x97) + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu1 | psu0 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu_st(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, &byte, PSOC_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ +#define PSU1 0x5800 +#define PSU2 0x5900 +#define BMC_I2cBus 3 //BMC's I2C-1 +#define PMBus_Vender 0x99 +#define PMBus_Serial 0x9E +#define PMBus_Temp2 0x8E +#define PMBus_Version 0x9B +#define MaxLeng_Result 0x20 +#define MaxLog +static long pmbus_reg2data_linear(int data, int linear16); + + +static ssize_t show_ipmi_i2c(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + uint8_t data[4],result[MaxLeng_Result]; + int result_len; + + data[0] = BMC_I2cBus; + data[1] = (attr->index & 0xFF00 ) >>7; + data[3] = attr->index & 0xff; + if(data[3]==PMBus_Temp2) + data[2]=2; + else + data[2]=MaxLeng_Result; + + if(ipmi_command(0x06, 0x52,data,4, result, &result_len)==0) + { + if(data[3]==PMBus_Temp2) + { + return sprintf(buf, "%ld \n", pmbus_reg2data_linear(result[0] | (result[1]<<8), 0 )); + } + result[result[0]+1]='\0'; + + return sprintf(buf, "%s\n",&result[1] ); + } + else + return 0; +} + +static ssize_t show_ipmi_sollog(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + uint8_t data[5],result[256]; + int result_len; + uint32_t i; + + for(i=0;i<0xffffff;i+=255) + { + data[0] = attr->index; + data[1] = (i & 0x0000ff); + data[2] = (i & 0x00ff00)>>8; + data[3] = (i & 0xff0000)>>16; + data[4] = 0; + + result_len=0; + + if(ipmi_command(0x32, 0xFE, data, 5, result, &result_len)==0) + { + if(result_len==0) break; + result[result_len+1]='\0'; + printk("%s",result); + } + else break; + + if(result_len==0) break; + } + + return 0; +} + +static ssize_t show_thermal(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index * 2 + THERMAL_OFFSET; + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + (s8)(status>>8) * 1000 ); +} + + + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index + PWM_OFFSET; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t set_pwm(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index + PWM_OFFSET; + + u8 pwm = simple_strtol(buf, NULL, 10); + if(pwm > 255) pwm = 255; + + if(data->diag) { + mutex_lock(&data->update_lock); + psoc_i2c_write(client, &pwm, offset, 1); + mutex_unlock(&data->update_lock); + } + + return count; +} + + +static ssize_t show_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index*2 + RPM_OFFSET; + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u16 temp = 0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, (u8*)&temp, SWITCH_TMP_OFFSET, 2); + mutex_unlock(&data->update_lock); + + status = sprintf (buf, "%d\n", (s8)(temp>>8) * 1000 ); + + return strlen(buf); +} + +static ssize_t set_switch_tmp(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + + long temp = simple_strtol(buf, NULL, 10); + u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ; + + //printk("set_switch_tmp temp=%d, temp2=0x%x (%x,%x)\n", temp, temp2, ( ( (temp/1000) <<8 ) & 0xFF00 ), (( (temp%1000) / 10 ) & 0xFF)); + + mutex_lock(&data->update_lock); + psoc_i2c_write(client, (u8*)&temp2, SWITCH_TMP_OFFSET, 2); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_diag(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 diag_flag = 0; + + mutex_lock(&data->update_lock); + status = psoc_i2c_read(client, (u8*)&diag_flag, DIAG_FLAG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + data->diag = (diag_flag & 0x80)?1:0; + status = sprintf (buf, "%d\n", data->diag); + + return strlen(buf); +} + +static ssize_t set_diag(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 value = 0; + u8 diag = simple_strtol(buf, NULL, 10); + + diag = diag?1:0; + data->diag = diag; + + mutex_lock(&data->update_lock); + psoc_i2c_read(client, (u8*)&value, DIAG_FLAG_OFFSET, 1); + if(diag) value |= (1<<7); + else value &= ~(1<<7); + psoc_i2c_write(client, (u8*)&value, DIAG_FLAG_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + status = psoc_read16(client, VERSION_OFFSET); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) ); +} + + +static ssize_t show_fan_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 bit = attr->index; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, FAN_LED_OFFSET); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", + (status & (1<index; + u8 led_state = 0; + + u8 v = simple_strtol(buf, NULL, 10); + + if(data->diag) { + mutex_lock(&data->update_lock); + led_state = psoc_read8(client, FAN_LED_OFFSET); + if(v) led_state |= (1<update_lock); + } + + return count; +} + +static ssize_t show_value8(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index; + + mutex_lock(&data->update_lock); + + status = psoc_read8(client, offset); + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "0x%02X\n", status ); +} + +static long pmbus_reg2data_linear(int data, int linear16) +{ + s16 exponent; + s32 mantissa; + long val; + + if (linear16) { /* LINEAR16 */ + exponent = -9; + mantissa = (u16) data; + } else { /* LINEAR11 */ + exponent = ((s16)data) >> 11; + exponent = ((s16)( data & 0xF800) ) >> 11; + mantissa = ((s32)((data & 0x7ff) << 5)) >> 5; + } + + //printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa); + val = mantissa; + + /* scale result to micro-units for power sensors */ + val = val * 1000L; + + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psoc_data *data = i2c_get_clientdata(client); + u8 offset = attr->index + PSU_INFO_OFFSET; + + mutex_lock(&data->update_lock); + status = psoc_read16(client, offset); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, strstr(attr->dev_attr.attr.name, "vout")? 1:0 )); +} + + + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4); +static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5); +static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 6); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4); +static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu_st, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 1); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7); +static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8); +static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9); + +static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); +static SENSOR_DEVICE_ATTR(temp6_input, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); + +static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0); +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0); + +static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0); +static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1); +static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2); +static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3); +static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4); +static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5); +static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6); +static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7); + +static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET); +static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout)); + + +static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout)); + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); + + +//IPMI +static SENSOR_DEVICE_ATTR(thermal2_psu1, S_IRUGO, show_ipmi_i2c, 0, PSU1 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(psoc_psu1_vender, S_IRUGO, show_ipmi_i2c, 0, PSU1 | PMBus_Vender); +static SENSOR_DEVICE_ATTR(psoc_psu1_serial, S_IRUGO, show_ipmi_i2c, 0, PSU1 | PMBus_Serial); +static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_ipmi_i2c, 0, PSU1 | PMBus_Version); + +static SENSOR_DEVICE_ATTR(thermal2_psu2, S_IRUGO, show_ipmi_i2c, 0, PSU2 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(psoc_psu2_vender, S_IRUGO, show_ipmi_i2c, 0, PSU2 | PMBus_Vender); +static SENSOR_DEVICE_ATTR(psoc_psu2_serial, S_IRUGO, show_ipmi_i2c, 0, PSU2 | PMBus_Serial); +static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_ipmi_i2c, 0, PSU2 | PMBus_Version); + +static SENSOR_DEVICE_ATTR(sollog1, S_IRUGO, show_ipmi_sollog, 0, 1); +static SENSOR_DEVICE_ATTR(sollog2, S_IRUGO, show_ipmi_sollog, 0, 2); + +static struct attribute *psoc_attributes[] = { + //thermal + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + + &sensor_dev_attr_thermal_psu1.dev_attr.attr, + &sensor_dev_attr_thermal_psu2.dev_attr.attr, + + + //pwm + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm_psu1.dev_attr.attr, + &sensor_dev_attr_pwm_psu2.dev_attr.attr, + + //rpm + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, + + &sensor_dev_attr_rpm_psu1.dev_attr.attr, + &sensor_dev_attr_rpm_psu2.dev_attr.attr, + + //switch temperature + &sensor_dev_attr_switch_tmp.dev_attr.attr, + &sensor_dev_attr_temp6_input.dev_attr.attr, + + //diag flag + &sensor_dev_attr_diag.dev_attr.attr, + + //version + &sensor_dev_attr_version.dev_attr.attr, + + //fan led + &sensor_dev_attr_fan_led_grn1.dev_attr.attr, + &sensor_dev_attr_fan_led_grn2.dev_attr.attr, + &sensor_dev_attr_fan_led_grn3.dev_attr.attr, + &sensor_dev_attr_fan_led_grn4.dev_attr.attr, + &sensor_dev_attr_fan_led_red1.dev_attr.attr, + &sensor_dev_attr_fan_led_red2.dev_attr.attr, + &sensor_dev_attr_fan_led_red3.dev_attr.attr, + &sensor_dev_attr_fan_led_red4.dev_attr.attr, + + //fan GPI + &sensor_dev_attr_fan_gpi.dev_attr.attr, + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + + //psu_psoc, new added on psoc 1.9 + &sensor_dev_attr_psoc_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pout.dev_attr.attr, + + // Add new fields which matching standard + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + + //ipmi_command + &sensor_dev_attr_thermal2_psu1.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_vender.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_serial.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_version.dev_attr.attr, + + &sensor_dev_attr_thermal2_psu2.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vender.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_serial.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_version.dev_attr.attr, + + &sensor_dev_attr_sollog1.dev_attr.attr, + &sensor_dev_attr_sollog2.dev_attr.attr, + + NULL +}; + +static const struct attribute_group psoc_group = { + .attrs = psoc_attributes, +}; + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int +psoc_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct psoc_data *data; + int status,i,rv; + + printk("+%s\n", __func__); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct psoc_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->diag = 0; + +#if IMPLEMENT_IPMI_CODE + for (i=0,rv=1; idev.kobj, &psoc_group); + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &psoc_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int psoc_remove(struct i2c_client *client) +{ + struct psoc_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &psoc_group); + i2c_set_clientdata(client, NULL); + kfree(data); + return 0; +} + +static const struct i2c_device_id psoc_ids[] = { + { "inv_psoc", 0, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, psoc_ids); + +static struct i2c_driver psoc_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_psoc", + }, + .probe = psoc_probe, + .remove = psoc_remove, + .id_table = psoc_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_psoc_init(void) +{ + return i2c_add_driver(&psoc_driver); +} + +static void __exit inv_psoc_exit(void) +{ + i2c_del_driver(&psoc_driver); +} + +MODULE_AUTHOR("eddie.lan "); +MODULE_DESCRIPTION("inv psoc driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_psoc_init); +module_exit(inv_psoc_exit); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_pthread.c new file mode 100644 index 000000000000..4ca41e432be1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_pthread.c @@ -0,0 +1,1284 @@ +/***************************** + Cypress platform +******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INV_PTHREAD_KERNEL_MODULE + +#define SHOW_ATTR_WARNING ("N/A") +#define SHOW_ATTR_NOTPRINT ("Not Available") +#define SHOW_ATTR_NOTSUPPORT ("Not Support") + +#define INV_HWMID_MAX (10) +#define INV_HWMID_INIT (-1) + +/*access userspace data to kernel space*/ +#define ACC_R (0) +#define ACC_W (1) + +#define TINY_BUF_SIZE (8) +#define MAX_PATH_SIZE (64) +#define MIN_ACC_SIZE (32) +#define MAX_ACC_SIZE (256) + +/* + * LED definitions + */ +#define STATUS_LED_MODE_AUTO 0 +#define STATUS_LED_MODE_DIAG 1 +#define STATUS_LED_MODE_MANU 2 + +#define STATUS_LED_GRN0 10 // 0 - 000: off +#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz +#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz +#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz +#define STATUS_LED_GRN7 17 // 7 - 111: on +#define STATUS_LED_RED0 20 // 0 - 000: off +#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz +#define STATUS_LED_RED2 22 // 2 - 010: 1 hz +#define STATUS_LED_RED3 23 // 3 - 011: 2 hz +#define STATUS_LED_RED7 27 // 7 - 111: on +#define STATUS_LED_INVALID 0 // Invalid + +ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2); +ssize_t status_led_grn(const char *freq); +ssize_t status_led_red(const char *freq); +ssize_t status_led_diag_mode_enable(void); +ssize_t status_led_diag_mode_disable(void); +int status_led_check_color(void); +int status_led_check_diag_mode(void); + +#if 1 +/* For timestamps in SYSFS_LOG */ +#define SYSFS_LOG printk +#else +//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args) +#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args) +#endif + + +/* inventec_class *********************************/ +static struct kobject *status_kobj; +static struct kset *status_kset; + + +static struct mutex rw_lock; + +static int hwm_psoc = INV_HWMID_INIT; +static int hwm_cpld = INV_HWMID_INIT; + +int get_hwm_psoc(void) +{ + return hwm_psoc; +} + +int get_hwm_cpld(void) +{ + return hwm_cpld; +} + +static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + char *mark = NULL; + ssize_t vfs_ret = 0; + + if (mode == ACC_R) { + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_read(fp, buf, len, &pos); + + mark = strpbrk(buf, "\n"); + if (mark) + *mark = '\0'; + + filp_close(fp, NULL); + set_fs(fs); + } else if (mode == ACC_W) { + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_write(fp, buf, len, &pos); + filp_close(fp, NULL); + set_fs(fs); + } + + return vfs_ret; +} + +int inventec_strtol(const char *sbufp, char **endp, unsigned int base) +{ + char *endptr; + int value = simple_strtol(sbufp, &endptr, base); + if (value == 0 && sbufp == endptr) { + *endp = NULL; + return value; + } + *endp = (char*)1; + return value; +} + +int inventec_singlechar_to_int(const char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + else + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + else + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } + return -1; +} + +int inventec_store_input(char *inputp, int count) +{ + int i = 0; + while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) { + i++; + } + inputp[i] = '\0'; + return strlen(inputp); +} + +#if 0 +/* + * Time stamps for kernel log on yocto + */ +#include + +void SYSFS_LOG(char *fmt, ...) +{ + char buf[80], ts[32]; + va_list args; + int hlen; + + inventec_tmstmp(&ts[0]); + hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line + + va_start(args, fmt); + vsprintf(&buf[hlen-1], fmt, args); + va_end(args); + printk(KERN_WARNING "[p_thread] %s\n", buf); +} +#endif + +ssize_t +inventec_show_attr(char *buf_p, const char *invdevp) +{ + int inv_len = MAX_ACC_SIZE; /* INV driver return max length */ + char tmp_buf[MAX_ACC_SIZE]; + char *str_negative = "-", *mark = NULL; + + /* [Step2] Get data by uaccess */ + memset(tmp_buf, 0, sizeof(tmp_buf)); + mutex_lock(&rw_lock); + if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + mutex_unlock(&rw_lock); + + /* [Step3] Check return value + * - Ex: When transceiver not plugged + * => SWPS return error code "-202" + * => Pic8 need return "NA" (assume) + */ + if (strcspn(tmp_buf, str_negative) == 0) { + /* error case: "-202" */ + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + + /* OK case:*/ + mark = strpbrk(tmp_buf, "\n"); + if (mark) { *mark = '\0'; } + + return sprintf(buf_p, "%s\n", tmp_buf); +} + +ssize_t +inventec_store_attr(const char *buf_p, size_t count, const char *invdevp) +{ + ssize_t ret = 0; + + /* [Step2] Get data by uaccess */ + mutex_lock(&rw_lock); + if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return -EINVAL; + } + mutex_unlock(&rw_lock); + + /* OK case:*/ + return ret; +} + +int sysfs_detect_hwmon_index(void) +{ + char hwmon_buf[MAX_ACC_SIZE]; + char hwmon_path[MAX_PATH_SIZE]; + int hwid = 0; + + for (hwid = 0; + hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT); + hwid++) { + memset(hwmon_buf, 0, sizeof(hwmon_buf)); + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/device/name", hwid); + + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) { + hwm_cpld = hwid; + } + } + if (hwid >= INV_HWMID_MAX) { + printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return -1; + } + printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return 0; +} + +static int __init +inventec_class_init(void) +{ + mutex_init(&rw_lock); + +#ifdef INV_PTHREAD_KERNEL_MODULE + if (sysfs_detect_hwmon_index() < 0) { + return -1; + } +#endif + + printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__); + + return 0; +} + +static void __exit +inventec_class_exit(void) +{ + printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__); +} + +/* fan device *************************************/ +#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/device/fan_gpi" +#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/device/fan1_input" +#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/device/fan2_input" +#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/device/fan3_input" +#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/device/fan4_input" +#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/device/fan5_input" +#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/device/fan6_input" +#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/device/fan7_input" +#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/device/fan8_input" + +static char fan_dev_path_state[MAX_PATH_SIZE]; +static char fan_dev_path_fan1_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan2_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan3_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan4_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan5_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan6_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan7_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan8_input[MAX_PATH_SIZE]; + +void sysfs_fan_path_init(void) +{ + sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc()); + sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc()); +} + +#define FAN_STATE_NORMAL "normal" +#define FAN_STATE_FAULTY "faulty" +#define FAN_STATE_UNINSTALLED "uninstalled" +#define FAN_STATE_UNKNOW "unknown state" +#define FAN_STATE_INVALID "Invalid state value" +#define FAN_STATE_READ_ERROR "state read error" + +#define FAN_LOG_UNINSTALLED "removed" +#define FAN_LOG_NORMAL "inserted" + +//#define FAN_STATE_BIT_NORMAL 0 +#define FAN_STATE_BIT_FAULTY 0 +#define FAN_STATE_BIT_UNINSTALLED 1 +#define FAN_STATE_BIT_UNKNOW 2 +#define FAN_STATE_BIT_INVALID 3 +#define FAN_STATE_BIT_READ_ERROR 4 + +static struct fans_tbl_s { + char *fan_name; + char *fan_front; + char *fan_rear; + unsigned int fan_state; +} fans_tbl[] = { + {"fan1", fan_dev_path_fan1_input, + fan_dev_path_fan2_input, 0}, + {"fan2", fan_dev_path_fan3_input, + fan_dev_path_fan4_input, 0}, + {"fan3", fan_dev_path_fan5_input, + fan_dev_path_fan6_input, 0}, + {"fan4", fan_dev_path_fan7_input, + fan_dev_path_fan8_input, 0}, +}; +#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) ) + +#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0) + { + printk(KERN_ERR "[p_thread] All fans failed.\n"); + printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown); + } + cd_shutdown -= 1; + } + return ret; +} + +/* End of faninfo_device */ + +static int __init +fan_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_fan_path_init(); +#endif + return 0; +} + + +static void __exit +fan_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove fan module.\n"); +} + +/* psu device *************************************/ +static unsigned int psu_voltin = 0; +#define PSU_VOLTIN_ACDC (70000) + +/* + * normal/unpower/uninstall/fault are PSU states output from driver level + * checkpsu/error are defined by sysfs + */ +#define PSU_STATE_VAL_NORMAL (0) +#define PSU_STATE_VAL_UNPOWER (2) +#define PSU_STATE_VAL_FAULT (4) +#define PSU_STATE_VAL_UNINSTALL (7) +#define PSU_STATE_VAL_CHECKPSU (8) +#define PSU_STATE_VAL_ERROR (9) + +#define PSU_STATE_NORMAL ("0 : normal") +#define PSU_STATE_UNPOWER ("2 : unpowered") +#define PSU_STATE_FAULT ("4 : fault") +#define PSU_STATE_UNINSTALL ("7 : not installed") +#define PSU_STATE_CHECKPSU ("8 : check psu") +#define PSU_STATE_ERROR ("9 : state error") + +#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL)) +#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER)) +#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT)) +#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL)) +#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU)) + +typedef struct { + char *inv_dev_attrp; + char *inv_dev_pathp; +} psu_dev_t; + +typedef struct { + const char *psu_name; + int psu_major; + dev_t psu_devt; + struct device *psu_dev_p; + psu_dev_t *psu_dev_namep; + int psu_dev_total; + char *psu_inv_pathp; + void *psu_tracking; + char *psu_currentin; + char *psu_currentout; + char *psu_powerin; + char *psu_powerout; + char *psu_voltin; + char *psu_voltout; +} psu_dev_group_t; + +#define PSU_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s" + +static char psu_dev_path_state[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltin[MAX_PATH_SIZE]; +#if 0 +static char psu_dev_path_vendor[MAX_PATH_SIZE]; +static char psu_dev_path_version[MAX_PATH_SIZE]; +static char psu_dev_path_sn[MAX_PATH_SIZE]; +static char psu_dev_path_temperature[MAX_PATH_SIZE]; +static char psu_dev_path_fan_speed[MAX_PATH_SIZE]; +static char psu_dev_path_fan_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_fan_faulty[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_psu_rpm[MAX_PATH_SIZE]; +#endif + +void sysfs_psu_path_init(void) +{ + sprintf(&psu_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" ); + sprintf(&psu_dev_path_psu_voltin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#if 0 + sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#endif +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +#if 0 + { "vendor", psu_dev_path_vendor }, + { "version", psu_dev_path_version }, + { "sn", psu_dev_path_sn }, + { "temperature", psu_dev_path_temperature }, + { "fan_speed", psu_dev_path_fan_speed }, + { "fan_pwm", psu_dev_path_fan_pwm }, + { "fan_faulty", psu_dev_path_fan_faulty }, + { "psu_currentin", psu_dev_path_psu_currentin }, + { "psu_currentout", psu_dev_path_psu_currentout }, + { "psu_powerin", psu_dev_path_psu_powerin }, + { "psu_powerout", psu_dev_path_psu_powerout }, + { "psu_voltout", psu_dev_path_psu_voltout }, + { "psu_pwm", psu_dev_path_psu_pwm }, + { "psu_rpm", psu_dev_path_psu_rpm }, +#endif +}; +#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) ) + +static psu_dev_group_t psu_dev_group[] = { + { + .psu_name = "psu1", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, + { + .psu_name = "psu2", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, +}; +#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) ) + +static char psu_state[4][MIN_ACC_SIZE]; + +static struct psu_wire_tbl_s { + char *psu_attr; + char *psu_name; + char *psu_wire; + char *psu_state; +} psu_wire_tbl[] = { + { "state", "psu1", "psu0", psu_state[0] }, // Using cpld + { "state", "psu2", "psu1", psu_state[1] }, + { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] }, + { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] }, +}; +#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) ) + +static char * +psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp) +{ + int i; + + for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) { + if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 && + strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) { + if (psu_statepp) { + *psu_statepp = psu_wire_tbl[i].psu_state; + } + return psu_wire_tbl[i].psu_wire; + } + } + return NULL; +} + +int psu_check_state_normal(char *statep) +{ + if (strstr(statep, "normal")) { + return 1; + } + return 0; +} + +#define PSU_ATTR_VOLTIN ("psu_voltin") +#define PSU_ATTR_VOLTIN_LEN (10) + +/* Get PSU voltin for determon AC(110v) or DC(48v) */ +void psu_get_voltin(void) +{ + char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE]; + psu_dev_t *devnamep; + unsigned int voltin; + char *invwirep; + int i, j; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + //psu_dev_group[i].psu_name; + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(volt, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + continue; + } + else { + voltin = simple_strtol(&volt[0], NULL, 10); + printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin); + if (voltin > psu_voltin) { + psu_voltin = voltin; + } + } + } + } + } + + SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin); +} + +#define PSU_ATTR_STATE ("state") +#define PSU_ATTR_STATE_LEN (5) + +/* psus_control() by inv_thread */ +int psus_control(int log_only) +{ + char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE]; + psu_dev_t *devnamep = NULL; + char *invwirep = NULL; + char *psu_statep = NULL; + int i, j, flag = 0; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(state, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) { + strcpy(psu_statep, PSU_STATE_ERROR); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR); + } + flag = 1; + } + else + if (strstr(state, "normal")) { + //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + } + else + if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */ + //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + flag = 1; + } + else { /* DC PSUS */ + if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) { + strcpy(psu_statep, PSU_STATE_CHECKPSU); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU); + } + flag = 1; + } + } + } + } + + if (log_only) { + return 0; + } + + //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag); + if (flag == 1) { + status_led_grn("3"); + return 1; + } + return 0; +} + +/* End of psuinfo_device */ + +static int __init +psu_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_psu_path_init(); +#endif + return 0; +} + + +static void __exit +psu_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove psu module.\n"); +} + +/* led device *************************************/ +#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led" +#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led" + +#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1" +#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2" +#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3" +#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4" +#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1" +#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2" +#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3" +#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4" + +#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag" +#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl" + +static char status_led_grn_path[MAX_PATH_SIZE]; +static char status_led_red_path[MAX_PATH_SIZE]; +static char fan_led_grn1_path[MAX_PATH_SIZE]; +static char fan_led_grn2_path[MAX_PATH_SIZE]; +static char fan_led_grn3_path[MAX_PATH_SIZE]; +static char fan_led_grn4_path[MAX_PATH_SIZE]; +static char fan_led_red1_path[MAX_PATH_SIZE]; +static char fan_led_red2_path[MAX_PATH_SIZE]; +static char fan_led_red3_path[MAX_PATH_SIZE]; +static char fan_led_red4_path[MAX_PATH_SIZE]; +static char hwmon_device_diag_path[MAX_PATH_SIZE]; +static char hwmon_device_ctrl_path[MAX_PATH_SIZE]; + +void sysfs_led_path_init(void) +{ + sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld()); + sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld()); + sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc()); + sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc()); + sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc()); + sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc()); + sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld()); +} + +/* return 0/off 1/green 2/red */ +int +status_led_check_color(void) +{ + char tmpbuf[MIN_ACC_SIZE]; + int ret = STATUS_LED_INVALID; + + if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_GRN0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_GRN1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_GRN2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_GRN3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_GRN7; + } + return ret; + } + + if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_RED0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_RED1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_RED2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_RED3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_RED7; + } + return ret; + } + return ret; +} + +/* + * Store attr Section + */ +static DEFINE_MUTEX(diag_mutex); + +ssize_t status_led_diag_mode_enable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '0') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("1", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + mutex_unlock(&diag_mutex); + } + + return ret; +} + +ssize_t status_led_diag_mode_disable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '1') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("0", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + mutex_unlock(&diag_mutex); + } + return 1; +} + +ssize_t +status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2) +{ + ssize_t ret; + + ret = inventec_store_attr(tmp1, strlen(tmp1), path1); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(tmp2, strlen(tmp2), path2); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_red(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_grn(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +static int status_led_diag_mode = STATUS_LED_MODE_AUTO; + +int status_led_check_diag_mode(void) +{ + return status_led_diag_mode; +} + +/* End of ledinfo_device */ + +static int __init +led_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); +#endif + return 0; +} + + +static void __exit +led_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove led module.\n"); +} + +/* sensor device **********************************/ +#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp" + +static char sensor_dev_path_switch_temp[MAX_PATH_SIZE]; + +void sysfs_sensor_path_init(void) +{ + sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc()); +} + +void switch_temp_update(void) +{ + char buf[MIN_ACC_SIZE]; + ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp"); + if (count > 0) { + //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp); + inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp); + } +} + +/**************************************************/ +/* From system_device */ +static int inv_pthread_control = 1; + +int thread_control(void) +{ + return inv_pthread_control; +} + +void thread_control_set(int val) +{ + inv_pthread_control = val; +} +/* End system_device */ + +#define THREAD_SLEEP_MINS (3) +#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1) + +extern void psu_get_voltin(void); + +static struct task_struct *thread_st; +static int thread_data; + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO +void led_set_gpio_to_change_status_led(void) +{ + ssize_t ret = inventec_store_attr("57", 2, "/sys/class/gpio/export"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 57 to /sys/class/gpio/export failed\n"); + return; + } + ret = inventec_store_attr("low", 3, "/sys/class/gpio/gpio57/direction"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio57/direction failed\n"); + return; + } + SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n"); +} +#endif + +// Function executed by kernel thread +static int thread_fn(void *unused) +{ + /* Delay for guarantee HW ready */ + ssleep(THREAD_DELAY_MINS); + +#ifndef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sysfs_fan_path_init(); + sysfs_psu_path_init(); +#endif + //sysfs_sensor_path_init(); + + /* Default status init */ + status_led_grn("7"); + + psu_get_voltin(); + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO + led_set_gpio_to_change_status_led(); +#endif + + while (1) + { + ssleep(THREAD_SLEEP_MINS); + + if (thread_control() == 0) { + printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__); + break; + } + + if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) { + /* status led in change color/freq mode, higher priority. Ignore fans sttaus */ + continue; + } + + //switch_temp_update(); + + if (fans_control() > 0) { + psus_control(1); + continue; + } + else + if (psus_control(0) > 0) { + continue; + } + + if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */ + status_led_grn("7"); + } + } + +#ifndef INV_PTHREAD_KERNEL_MODULE +err_inv_pthread_fn_1: +#endif + do_exit(0); + printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__); + return 0; +} + + +static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int fan_absence; + size_t count; + + fan_absence = fans_control(); + count += sprintf(&buf[count], "%d\n", fan_absence); + return count; +} + +static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static struct attribute status_att = { + .name = "fan_absence", + .mode = 0777, +}; + +static const struct sysfs_ops status_ops = { + .show = s_show, + .store = s_store, +}; + +static struct kobj_type status_ktype = { + .sysfs_ops = &status_ops, +}; + + +static int __init inv_pthread_init(void) +{ + int retval; + + status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL); + if(!status_kobj) + return PTR_ERR(status_kobj); + + status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj); + if(!status_kset) + return -1; + + status_kobj->kset = status_kset; + + retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan"); + if(retval) + return retval; + + retval = sysfs_create_file(status_kobj, &status_att); + + + inventec_class_init(); + fan_device_init(); + psu_device_init(); + led_device_init(); + + thread_control_set(1); + + printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__); + //Create the kernel thread with name 'inv_pthread' + thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread"); + if (thread_st) + printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n"); + else + printk(KERN_ERR "[p_thread] inv_pthread creation failed\n"); + + return retval; +} + +static void __exit inv_pthread_exit(void) +{ + thread_control_set(0); + /* Delay for guarantee thread exit */ + ssleep(THREAD_DELAY_MINS); + + fan_device_exit(); + psu_device_exit(); + led_device_exit(); + inventec_class_exit(); + + sysfs_remove_file(status_kobj, &status_att); + kset_unregister(status_kset); + kobject_del(status_kobj); + + printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n"); +} + +module_init(inv_pthread_init); +module_exit(inv_pthread_exit); + +MODULE_AUTHOR("Robert "); +MODULE_DESCRIPTION("Inventec Platform Management Thread"); +MODULE_VERSION("version 1.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.c new file mode 100644 index 000000000000..08bd490e63b6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.c @@ -0,0 +1,730 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_swps.h" + +static int port_major; +static int ioexp_total; +static int port_total; +static struct class *swp_class_p = NULL; +static struct inv_platform_s *platform_p = NULL; +static struct inv_ioexp_layout_s *ioexp_layout = NULL; +static struct inv_port_layout_s *port_layout = NULL; + +static int +__swp_match(struct device *dev, +#ifdef SWPS_KERN_VER_AF_3_10 + + const void *data){ +#else + void *data){ +#endif + + char *name = (char *)data; + if (strcmp(dev_name(dev), name) == 0) + return 1; + return 0; +} + + +struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(swp_class_p, + NULL, + name, + (const void *)__swp_match); + return dev; +} + + +static int +sscanf_2_int(const char *buf) { + + int result = -EBFONT; + char *hex_tag = "0x"; + + if (strcspn(buf, hex_tag) == 0) { + if (sscanf(buf,"%x",&result)) { + return result; + } + } else { + if (sscanf(buf,"%d",&result)) { + return result; + } + if(sscanf(buf,"-%d",&result)) { + return -result; + } + if (sscanf(buf,"%x",&result)) { + return result; + } + } + return -EBFONT; +} + + +static int +sscanf_2_binary(const char *buf) { + + int result = sscanf_2_int(buf); + + if (result < 0){ + return -EBFONT; + } + switch (result) { + case 0: + case 1: + return result; + default: + break; + } + return -EBFONT; +} + +/* ========== Show functions: For I/O Expander attribute ========== + */ +static ssize_t +_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset), + char *buf_p) { + size_t len; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR(" %s: data corruption! :%s\n", __func__, tobj_p->swp_name); + return -ENODATA; + } + mutex_lock(&ioexp_p->lock); + len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset)); + mutex_unlock(&ioexp_p->lock); + return len; +} + + +static ssize_t +show_attr_present(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_present, + buf_p); +} + +static ssize_t +show_attr_tx_fault(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_fault, + buf_p); +} + +static ssize_t +show_attr_rxlos(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_rxlos, + buf_p); +} + +static ssize_t +show_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_disable, + buf_p); +} + +static ssize_t +show_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_reset, + buf_p); +} + +static ssize_t +show_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_lpmod, + buf_p); +} + + +static ssize_t +show_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_modsel, + buf_p); +} + +/* ========== Store functions: For I/O Expander (R/W) attribute ========== + */ +static ssize_t +_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*set_func)(struct ioexp_obj_s *ioexp_p, + int virt_offset, int input_val), + const char *buf_p, + size_t count) { + + int input, err; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR("%s: data corruption! :%s\n", + __func__, tobj_p->swp_name); + return -ENODATA; + } + input = sscanf_2_binary(buf_p); + if (input < 0) { + return -EBFONT; + } + mutex_lock(&ioexp_p->lock); + err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input); + mutex_unlock(&ioexp_p->lock); + if (err < 0){ + return err; + } + return count; +} + +static ssize_t +store_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_tx_disable, + buf_p, + count); +} + +static ssize_t +store_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_reset, + buf_p, + count); +} + + +static ssize_t +store_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_lpmod, + buf_p, + count); +} + + +static ssize_t +store_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_modsel, + buf_p, + count); +} + +/* ========== IO Expander attribute: from expander ========== + */ +static DEVICE_ATTR(present, S_IRUGO, show_attr_present, NULL); +static DEVICE_ATTR(tx_fault, S_IRUGO, show_attr_tx_fault, NULL); +static DEVICE_ATTR(rxlos, S_IRUGO, show_attr_rxlos, NULL); +static DEVICE_ATTR(tx_disable, S_IRUGO|S_IWUSR, show_attr_tx_disable, store_attr_tx_disable); +static DEVICE_ATTR(reset, S_IRUGO|S_IWUSR, show_attr_reset, store_attr_reset); +static DEVICE_ATTR(lpmod, S_IRUGO|S_IWUSR, show_attr_lpmod, store_attr_lpmod); +static DEVICE_ATTR(modsel, S_IRUGO|S_IWUSR, show_attr_modsel, store_attr_modsel); + +/* ========== Functions for module handling ========== + */ +static void +clean_port_obj(void){ + + dev_t dev_num; + char dev_name[32]; + struct device *device_p; + struct transvr_obj_s *transvr_obj_p; + int minor_curr, port_id; + + for (minor_curr=0; minor_curri2c_client_p); + kfree(transvr_obj_p); + } + dev_num = MKDEV(port_major, minor_curr); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static int +get_platform_type(void){ + + char log_msg[64] = "ERROR"; + + platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL); + if (!platform_p){ + snprintf(log_msg, sizeof(log_msg), "kzalloc fail"); + goto err_get_platform_type_1; + } + platform_p->id = PLATFORM_SETTINGS; + memset(platform_p->name, 0, sizeof(platform_p->name)); + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", platform_map.name); + snprintf(log_msg, sizeof(log_msg), + "User setup platform: %d (%s)", + platform_p->id, platform_p->name); + SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return 0; + +err_get_platform_type_1: + SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return -1; +} + + +static int +get_layout_info(void){ + ioexp_layout = cypress_ga2_ioexp_layout; + port_layout = cypress_ga2_port_layout; + ioexp_total = ARRAY_SIZE(cypress_ga2_ioexp_layout); + port_total = ARRAY_SIZE(cypress_ga2_port_layout); + + SWPS_INFO("Start to initial platform: %d (%s)\n", + platform_p->id, platform_p->name); + return 0; +} + +/* ========== Functions for register something ========== + */ + +static int +register_ioexp_attr_sfp_1(struct device *device_p){ + /* Support machine type: + * - SFP : Magnolia + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_fault) < 0) { + err_attr = "dev_attr_tx_fault"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_rxlos) < 0) { + err_attr = "dev_attr_rxlos"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_disable) < 0) { + err_attr = "dev_attr_tx_disable"; + goto err_ioexp_sfp1_attr; + } + return 0; + +err_ioexp_sfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + +static int +register_ioexp_attr_sfp_2(struct device *device_p){ + /* Support machine type: + * - SFP28 : Cypress + */ + char *err_attr = NULL; + + if (register_ioexp_attr_sfp_1(device_p) < 0){ + goto err_ioexp_sfp2_attr; + } + return 0; + +err_ioexp_sfp2_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + +static int +register_ioexp_attr_qsfp_1(struct device *device_p){ + /* Support machine type: + * - QSFP : Magnolia, Redwood, Hudson32i + * - QSFP+ : Magnolia, Redwood, Hudson32i + * - QSFP28: Redwood + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_reset) < 0) { + err_attr = "dev_attr_reset"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_lpmod) < 0) { + err_attr = "dev_attr_lpmod"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_modsel) < 0) { + err_attr = "dev_attr_modsel"; + goto err_ioexp_qsfp1_attr; + } + return 0; + +err_ioexp_qsfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + +static int +register_ioexp_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + char *err_msg = "ERR"; + + switch (transvr_obj->ioexp_obj_p->ioexp_type){ + case IOEXP_TYPE_CYPRESS_NABC: + if (register_ioexp_attr_sfp_2(device_p) < 0){ + err_msg = "register_ioexp_attr_sfp_2 fail"; + goto err_reg_ioexp_attr; + } + break; + case IOEXP_TYPE_CYPRESS_7ABC: + if (register_ioexp_attr_qsfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_qsfp_1 fail"; + goto err_reg_ioexp_attr; + } + break; + + default: + err_msg = "Unknow type"; + goto err_reg_ioexp_attr; + } + return 0; + +err_reg_ioexp_attr: + SWPS_ERR("%s: %s :%d \n", + __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type); + return -1; +} + + +static int +register_port_device(char *dev_name, + dev_t dev_num, + struct transvr_obj_s *transvr_obj){ + + struct device *device_p = NULL; + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + transvr_obj, /* void *private_data */ + dev_name); /* const char *fmt */ + if (IS_ERR(device_p)){ + goto err_regswp_create_dev; + } + if (register_ioexp_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + return 0; + +err_regswp_reg_attr: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_regswp_create_dev: + SWPS_ERR("%s fail! :%s\n", __func__, dev_name); + return -1; +} + + +static int +register_swp_module(void){ + + dev_t port_devt = 0; + int dev_total = port_total + 1; /* char_dev for module control */ + + if (alloc_chrdev_region(&port_devt, 0, dev_total, SWP_CLS_NAME) < 0){ + SWPS_WARN("Allocate PORT MAJOR failure! \n"); + goto err_register_swp_module_3; + } + port_major = MAJOR(port_devt); + + /* Create class object */ + swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME); + if (IS_ERR(swp_class_p)) { + SWPS_ERR("Create class failure! \n"); + goto err_register_swp_module_3; + } + return 0; + +err_register_swp_module_3: + unregister_chrdev_region(MKDEV(port_major, 0), port_total); + return -1; +} + + +/* ========== Module initial relate ========== + */ +static int +create_ioexp_objs(void) { + + int i, run_mod; + + /* Clean IOEXP object */ + clean_ioexp_objs(); + /* Get running mode */ + run_mod = IOEXP_MODE_DIRECT; + /* Create IOEXP object */ + for(i=0; i devlen_max) { + snprintf(err_msg, sizeof(err_msg), + "SWP_DEV_PORT too long!"); + goto err_initport_create_tranobj; + } + memset(dev_name, 0, sizeof(dev_name)); + snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id); + /* Create transceiver object */ + ioexp_obj_p = get_ioexp_obj(ioexp_id); + if (!ioexp_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "IOEXP object:%d not exist", ioexp_id); + goto err_initport_create_tranobj; + } + transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p, + ioexp_virt_offset, transvr_type, + chipset_type, run_mod); + if (!transvr_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "Create transceiver object fail :%s", dev_name); + goto err_initport_create_tranobj; + } + /* Setup Lane_ID mapping */ + i = ARRAY_SIZE(port_layout[minor_curr].lane_id); + j = ARRAY_SIZE(transvr_obj_p->lane_id); + if (i != j) { + snprintf(err_msg, sizeof(err_msg), + "Lane_id size inconsistent %d/%d", i, j); + goto err_initport_reg_device; + } + memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int)); + /* Create and register device object */ + if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){ + snprintf(err_msg, sizeof(err_msg), + "register_port_device fail"); + goto err_initport_reg_device; + } + /* Setup device_ptr of transvr_obj */ + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + snprintf(err_msg, sizeof(err_msg), + "get_swpdev_by_name fail"); + goto err_initport_reg_device; + } + transvr_obj_p->transvr_dev_p = dev_p; + /* Success */ + ok_count++; + } + SWPS_INFO("%s: initialed %d port-dev",__func__, ok_count); + return 0; + +err_initport_reg_device: + kfree(transvr_obj_p); +err_initport_create_tranobj: + clean_port_obj(); + SWPS_ERR("%s: %s", __func__, err_msg); + SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n", + port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod); + return -1; +} + +static int __init +swp_module_init(void){ + + if (get_platform_type() < 0){ + goto err_init_out; + } + if (get_layout_info() < 0){ + goto err_init_out; + } + if (register_swp_module() < 0){ + goto err_init_out; + } + if (create_ioexp_objs() < 0){ + goto err_init_ioexp; + } + if (create_port_objs() < 0){ + goto err_init_portobj; + } + if (init_ioexp_objs() < 0){ + goto err_init_portobj; + } + SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION); + return 0; + + +err_init_portobj: + clean_ioexp_objs(); +err_init_ioexp: + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_init_out: + SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION); + return -1; +} + + +static void __exit +swp_module_exit(void){ + clean_port_obj(); + clean_ioexp_objs(); + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); + SWPS_INFO("Remove Inventec switch-port module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(SWP_AUTHOR); +MODULE_DESCRIPTION(SWP_DESC); +MODULE_VERSION(SWP_VERSION); +MODULE_LICENSE(SWP_LICENSE); + +module_init(swp_module_init); +module_exit(swp_module_exit); + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.h new file mode 100644 index 000000000000..f37fd387e4a5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/inv_swps.h @@ -0,0 +1,170 @@ +#ifndef INV_SWPS_H +#define INV_SWPS_H + +#include "transceiver.h" +#include "io_expander.h" + +/* Module settings */ +#define SWP_CLS_NAME "swps" +#define SWP_DEV_PORT "port" +#define SWP_AUTOCONFIG_ENABLE (1) + +/* Module information */ +#define SWP_AUTHOR "Neil " +#define SWP_DESC "Inventec port and transceiver driver" +#define SWP_VERSION "4.2.3" +#define SWP_LICENSE "GPL" + +/* Module status define */ +#define SWP_STATE_NORMAL (0) +#define SWP_STATE_I2C_DIE (-91) + +/* [Note]: + * Functions and mechanism for auto-detect platform type is ready, + * But HW and BIOS not ready! We need to wait them. + * So, please do not use PLATFORM_TYPE_AUTO until they are ready. + * (2016.06.13) + */ +#define PLATFORM_TYPE_CYPRESS_GA2 (152) /* Down -> Up */ +#define PLATFORM_TYPE_CYPRESS_BAI (153) /* Down -> Up */ + +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_CYPRESS_GA2 + +/* Define platform flag and kernel version */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA2) + #define SWPS_KERN_VER_BF_3_8 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_BAI) + #define SWPS_KERN_VER_AF_3_10 (1) +#endif + + +struct inv_platform_s { + int id; + char name[64]; +}; + +struct inv_ioexp_layout_s { + int ioexp_id; + int ioexp_type; + struct ioexp_addr_s addr[4]; +}; + +struct inv_port_layout_s { + int port_id; + int chan_id; + int ioexp_id; + int ioexp_offset; + int transvr_type; + int chipset_type; + int lane_id[8]; +}; + +/* ========================================== + * Inventec Platform Settings + * ========================================== + */ +struct inv_platform_s platform_map = {PLATFORM_TYPE_CYPRESS_GA2, "D7054Q28B" }; + +/* ========================================== + * Cypress Layout configuration (Inventec version [Down->Up]) + * ========================================== + */ +struct inv_ioexp_layout_s cypress_ga2_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + +struct inv_port_layout_s cypress_ga2_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} }, + { 1, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} }, + { 2, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} }, + { 3, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} }, + { 4, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} }, + { 5, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} }, + { 6, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} }, + { 7, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} }, + { 8, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} }, + { 9, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} }, + {10, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} }, + {11, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} }, + {12, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} }, + {13, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} }, + {14, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} }, + {15, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} }, + {16, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} }, + {17, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} }, + {18, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} }, + {19, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} }, + {20, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} }, + {21, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} }, + {22, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} }, + {23, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} }, + {24, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} }, + {25, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} }, + {26, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} }, + {27, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} }, + {28, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} }, + {29, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} }, + {30, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} }, + {31, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} }, + {32, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} }, + {33, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} }, + {34, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} }, + {35, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} }, + {36, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} }, + {37, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} }, + {38, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} }, + {39, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} }, + {40, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} }, + {41, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} }, + {42, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} }, + {43, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} }, + {44, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} }, + {45, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} }, + {46, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} }, + {47, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} }, + {48, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {49, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} }, + {50, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} }, + {51, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} }, + {52, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} }, + {53, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} }, +}; + + +#endif /* SFP_DRIVER_H */ + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.c new file mode 100644 index 000000000000..057995e4551a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.c @@ -0,0 +1,944 @@ +#include +#include +#include "io_expander.h" + +static struct ioexp_obj_s *ioexp_head_p = NULL; +static struct ioexp_obj_s *ioexp_tail_p = NULL; + +struct ioexp_map_s ioexp_map_cypress_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, +}; + +struct ioexp_map_s ioexp_map_cypress_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 1, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 1, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 1, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {0, 1, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {0, 1, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {1, 1, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {1, 1, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {1, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {1, 1, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + + +/* ========== Private functions ========== + */ +int check_channel_tier_1(void); + +struct i2c_client * +_get_i2c_client(struct ioexp_obj_s *self, + int chip_id){ + + struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p; + + if (!(i2c_curr_p)){ + SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__); + return NULL; + } + while (i2c_curr_p){ + if ((i2c_curr_p->chip_id) == chip_id){ + return i2c_curr_p->i2c_client_p; + } + i2c_curr_p = i2c_curr_p->next; + } + SWPS_ERR("%s: not exist! :%d\n", __func__, chip_id); + return NULL; +} + + +static int +_common_ioexp_update_one(struct ioexp_obj_s *self, + struct ioexp_addr_s *ioexp_addr, + int chip_id, + int data_width, + int show_err, + char *caller_name) { + int buf = 0; + int err = 0; + int data_id = 0; + int r_offset = 0; + + for(data_id=0; data_idread_offset[data_id]; + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset); + /* Check error */ + if (buf < 0) { + err = 1; + if (show_err) { + SWPS_INFO("IOEXP-%d read fail! :%d \n", self->ioexp_id, buf); + SWPS_INFO("Dump: :%d :0x%02x :%d, :%s\n", + ioexp_addr->chan_id, ioexp_addr->chip_addr, + ioexp_addr->read_offset[data_id], caller_name); + } + continue; + } + /* Update IOEXP object */ + self->chip_data[chip_id].data[data_id] = (uint8_t)buf; + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +common_ioexp_update_all(struct ioexp_obj_s *self, + int show_err, + char *caller_name){ + + int err = 0; + int chip_id = 0; + int chip_amount = self->ioexp_map_p->chip_amount; + + for (chip_id=0; chip_idioexp_map_p->map_addr[chip_id]), + chip_id, + self->ioexp_map_p->data_width, + show_err, + caller_name) < 0) { + err = 1; + } + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + +static int +_common_get_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + char *func_mane){ + uint8_t buf; + int err_code; + + /* Get address */ + err_code = self->fsm_4_direct(self); + if (err_code < 0){ + return err_code; + } + + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Get data form cache */ + buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + return (int)(buf >> bitmap_obj_p->bit_shift & 0x01); +} + + +static int +_common_set_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + int input_val, + char *func_mane){ + int err_code, target_offset; + uint8_t origin_byte; + uint8_t modify_byte; + + /* Get address */ + err_code = self->fsm_4_direct(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Prepare write date */ + origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + switch (input_val) { + case 0: + modify_byte = origin_byte; + SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift); + break; + case 1: + modify_byte = origin_byte; + SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift); + break; + default: + SWPS_ERR("Input value incorrect! :%d :%d :%s\n", + input_val, self->ioexp_id, func_mane); + return ERR_IOEXP_BADINPUT; + } + /* Setup i2c client */ + target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset]; + /* Write byte to chip via I2C */ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id), + target_offset, + modify_byte); + /* Update or bollback object */ + if (err_code < 0){ + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte; + SWPS_ERR("I2C write fail! :%d :%d :%s :%d\n", + input_val, self->ioexp_id, func_mane, err_code); + return err_code; + } + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte; + return 0; +} + + +/* ========== Object public functions ========== + */ +int +common_get_present(struct ioexp_obj_s *self, + int virt_offset){ + + int UNPLUG = 1; + int retval = ERR_IOEXP_UNEXCPT; + + retval = _common_get_bit(self, + &(self->ioexp_map_p->map_present[virt_offset]), + "common_get_present"); + if (retval < 0) { + /* [Note] + * => Transceiver object does not need to handle IOEXP layer issues. + */ + return UNPLUG; + } + return retval; +} + +int +common_get_tx_fault(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_fault[virt_offset]), + "common_get_tx_fault"); +} + +int +common_get_rxlos(struct ioexp_obj_s *self, + int virt_offset){ + /* [Receiver Loss of Signal (Rx_LOS)] + * The post-amplification IC also includes transition detection circuitry + * which monitors the ac level of incoming optical signals and provides a + * TTL/CMOS compatible status signal to the host (pin 8). An adequate optical + * input results in a low Rx_LOS output while a high Rx_LOS output indicates + * an unusable optical input. The Rx_LOS thresholds are factory set so that + * a high output indicates a definite optical fault has occurred. Rx_LOS can + * also be monitored via the two-wire serial interface + * (address A2h, byte 110, bit 1). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_rxlos[virt_offset]), + "common_get_rxlos"); +} + + +int +common_get_tx_disable(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + "common_get_tx_disable"); +} + +int +common_get_reset(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + "common_get_reset"); +} + + +int +common_get_lpmod(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + "common_get_lpmod"); +} + + +int +common_get_modsel(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + "common_get_modsel"); +} + +int +common_set_tx_disable(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + input_val, + "common_set_tx_disable"); +} + +int +common_set_reset(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + input_val, + "common_set_reset"); +} + + +int +common_set_lpmod(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + input_val, + "common_set_lpmod"); +} + + +int +common_set_modsel(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + input_val, + "common_set_modsel"); +} + +int +ioexp_get_not_support(struct ioexp_obj_s *self, + int virt_offset){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +ioexp_set_not_support(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + return ERR_IOEXP_NOTSUPPORT; +} + +/* ========== Initial functions for IO Expander ========== + */ +int +common_ioexp_init(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + if (self->mode == IOEXP_MODE_DIRECT) { ///important + goto update_common_ioexp_init; + } + /* Setup default value to each physical IO Expander */ + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + /* Get address mapping */ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("%s: IOEXP config incorrect! :%d \n", + __func__, chip_id); + return -1; + } + /* Setup default value */ + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->write_offset[offset], + addr_p->data_default[offset]); + if (err_code < 0){ + SWPS_ERR("%s: set default fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + } + } + +update_common_ioexp_init: + /* Check and update info to object */ + err_code = self->update_all(self, 1, "common_ioexp_init"); + if (err_code < 0) { + SWPS_ERR("%s: update_all() fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +/* ========== Object functions for Final State Machine ========== + */ +int +_is_channel_ready(struct ioexp_obj_s *self){ + + int buf = 0; + int chip_id = 0; /* Use first chip which be registered */ + int data_id = 0; /* Use first byte which be registered */ + struct ioexp_addr_s *ioexp_addr = NULL; + + ioexp_addr = &(self->ioexp_map_p->map_addr[chip_id]); + if (!ioexp_addr){ + SWPS_ERR("%s: config incorrect!\n", __func__); + return ERR_IOEXP_UNEXCPT; + } + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), + ioexp_addr->read_offset[data_id]); + if (buf >= 0){ + return 1; + } + return 0; +} + +int +_ioexp_init_handler(struct ioexp_obj_s *self){ + + int return_val; + + switch (self->mode) { + case IOEXP_MODE_DIRECT: + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + default: + break; + } + SWPS_ERR("%s: exception occur :%d\n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){ + + int result_val; + int show_err = 1; + char *func_mane = "common_ioexp_fsm_4_direct"; + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, and return error */ + return ERR_IOEXP_UNINIT; + } + /* Case: Initial done */ + return 0; + + case STATE_IOEXP_NORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + SWPS_INFO("%s: NORMAL -> ABNORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + self->state = STATE_IOEXP_NORMAL; + return 0; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_DEBUG("%s: ABNORMAL -> NORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("%s: Exception occurs :%d\n", + __func__, self->state); + return ERR_IOEXP_UNEXCPT; +} + +/* ========== Functions for Factory pattern ========== + */ +static struct ioexp_map_s * +get_ioexp_map(int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_CYPRESS_NABC: + return &ioexp_map_cypress_nabc; + case IOEXP_TYPE_CYPRESS_7ABC: + return &ioexp_map_cypress_7abc; + default: + return NULL; + } +} + + +int +setup_ioexp_ssize_attr(struct ioexp_obj_s *self, + struct ioexp_map_s *ioexp_map_p, + int ioexp_id, + int ioexp_type, + int run_mode){ + switch (run_mode){ + case IOEXP_MODE_DIRECT: /* Direct access device mode */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = ERR_IOEXP_UNEXCPT; + return ERR_IOEXP_UNEXCPT; + } + self->ioexp_id = ioexp_id; + self->ioexp_type = ioexp_type; + self->ioexp_map_p = ioexp_map_p; + self->state = STATE_IOEXP_INIT; + mutex_init(&self->lock); + return 0; +} + + +static int +setup_addr_mapping(struct ioexp_obj_s *self, + struct ioexp_addr_s *addr_map_p){ + if (!addr_map_p){ + SWPS_ERR("%s: map is null\n", __func__); + return -1; + } + self->ioexp_map_p->map_addr = addr_map_p; + return 0; +} + + +static int +setup_ioexp_public_cb(struct ioexp_obj_s *self, + int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_CYPRESS_NABC: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + return 0; + case IOEXP_TYPE_CYPRESS_7ABC: + self->get_present = common_get_present; + self->get_tx_fault = ioexp_get_not_support; + self->get_rxlos = ioexp_get_not_support; + self->get_tx_disable = ioexp_get_not_support; + self->get_reset = common_get_reset; + self->get_lpmod = common_get_lpmod; + self->get_modsel = common_get_modsel; + self->set_tx_disable = ioexp_set_not_support; + self->set_reset = common_set_reset; + self->set_lpmod = common_set_lpmod; + self->set_modsel = common_set_modsel; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_ioexp_private_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_CYPRESS_7ABC: + self->init = common_ioexp_init; + self->update_all = common_ioexp_update_all; + self->fsm_4_direct = common_ioexp_fsm_4_direct; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_i2c_client_one(struct ioexp_obj_s *self, + int chip_id){ + + char *err_msg = "ERROR"; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + struct ioexp_i2c_s *i2c_obj_p = NULL; + struct ioexp_i2c_s *i2c_curr_p = NULL; + + int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id; + adap = i2c_get_adapter(chan_id); + if(!adap){ + err_msg = "Can not get adap!"; + goto err_ioexp_setup_i2c_1; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + err_msg = "Can not kzalloc client!"; + goto err_ioexp_setup_i2c_1; + } + i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL); + if (!i2c_obj_p){ + err_msg = "Can not kzalloc i2c_obj_p!"; + goto err_ioexp_setup_i2c_2; + } + client->adapter = adap; + client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr; + i2c_obj_p->i2c_client_p = client; + i2c_obj_p->chip_id = chip_id; + i2c_obj_p->next = NULL; + if (!self->i2c_head_p){ + self->i2c_head_p = i2c_obj_p; + } else { + i2c_curr_p = self->i2c_head_p; + while (i2c_curr_p->next){ + i2c_curr_p = i2c_curr_p->next; + } + i2c_curr_p->next = i2c_obj_p; + } + return 0; + +err_ioexp_setup_i2c_2: + kfree(client); +err_ioexp_setup_i2c_1: + SWPS_ERR("%s: %s :%d\n", __func__, err_msg, chan_id); + return -1; +} + + +static int +setup_i2c_client(struct ioexp_obj_s* self){ + + int result; + int chip_id = 0; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + result = setup_i2c_client_one(self, chip_id); + if (result < 0){ + SWPS_ERR("%s fail! :%d\n", __func__, chip_id); + return -1; + } + } + return 0; +} + +static int +setup_ioexp_config(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("IOEXP config incorrect! :%d \n",chip_id); + return -1; + } + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->conf_offset[offset], + addr_p->conf_default[offset]); + + if (err_code < 0){ + SWPS_INFO("%s: set conf fail! :%d \n", __func__, err_code); + return -2; + } + } + } + return 0; +} + +struct ioexp_obj_s * +_create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_map_s* ioexp_map_p; + struct ioexp_obj_s* result_p; + struct ioexp_i2c_s *i2c_curr_p; + struct ioexp_i2c_s *i2c_next_p; + + /* Get layout */ + ioexp_map_p = get_ioexp_map(ioexp_type); + if (!ioexp_map_p){ + SWPS_ERR("%s: Invalid ioexp_type\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare IOEXP object */ + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + SWPS_ERR("%s: kzalloc failure!\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare static size attributes */ + if (setup_ioexp_ssize_attr(result_p, + ioexp_map_p, + ioexp_id, + ioexp_type, + run_mode) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + /* Prepare address mapping */ + if (setup_addr_mapping(result_p, addr_map_p) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + if (setup_i2c_client(result_p) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + /* Prepare call back functions of object */ + if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + return result_p; + +err_create_ioexp_setup_i2c_fail: + i2c_curr_p = result_p->i2c_head_p; + i2c_next_p = result_p->i2c_head_p; + while (i2c_curr_p){ + i2c_next_p = i2c_curr_p->next; + kfree(i2c_curr_p->i2c_client_p); + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } +err_create_ioexp_setup_attr_fail: + kfree(result_p); +err_create_ioexp_fail: + SWPS_ERR("%s: fail! :%d :%d \n", + __func__, ioexp_id, ioexp_type); + return NULL; +} + + +int +create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_obj_s *ioexp_p = NULL; + + ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type, + addr_map_p, run_mode); + if (!ioexp_p){ + return -1; + } + if (ioexp_head_p == NULL){ + ioexp_head_p = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; + } + ioexp_tail_p->next = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; +} + +static int +_init_ioexp_obj(struct ioexp_obj_s* self) { + + char *err_msg = "ERR"; + char *func_name = "_init_ioexp_obj"; + + /* Setup IOEXP configure byte */ + if (setup_ioexp_config(self) < 0){ + err_msg = "setup_ioexp_config fail"; + goto err_init_ioexp_obj; + } + /* Setup default data */ + if (_ioexp_init_handler(self) < 0){ + err_msg = "_ioexp_init_handler fail"; + goto err_init_ioexp_obj; + } + /* Update all */ + if (self->state == STATE_IOEXP_NORMAL){ + if (self->update_all(self, 1, func_name) < 0){ + err_msg = "update_all() fail"; + goto err_init_ioexp_obj; + } + } + return 0; + +err_init_ioexp_obj: + SWPS_DEBUG("%s: %s\n", __func__, err_msg); + return -1; +} + +int +init_ioexp_objs(void){ + /* Return value: + * 0: Success + * -1: Detect topology error + * -2: SWPS internal error + */ + + struct ioexp_obj_s *curr_p = ioexp_head_p; + + if (!curr_p) { + SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__); + return -2; + } + while (curr_p) { + if (_init_ioexp_obj(curr_p) < 0) { + SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__); + return -1; + } + curr_p = curr_p->next; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + +void +clean_ioexp_objs(void){ + + struct ioexp_i2c_s *i2c_curr_p = NULL; + struct ioexp_i2c_s *i2c_next_p = NULL; + struct ioexp_obj_s *ioexp_next_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + if (ioexp_head_p == NULL){ + ioexp_tail_p = NULL; + return; + } + while(ioexp_curr_p){ + ioexp_next_p = ioexp_curr_p->next; + i2c_curr_p = ioexp_curr_p->i2c_head_p; + while (i2c_curr_p) { + i2c_next_p = i2c_curr_p->next; + kfree(i2c_curr_p->i2c_client_p); + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } + kfree(ioexp_curr_p); + ioexp_curr_p = ioexp_next_p; + } + ioexp_tail_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} + +struct ioexp_obj_s * +get_ioexp_obj(int ioexp_id){ + + struct ioexp_obj_s *result_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + if (ioexp_curr_p->ioexp_id == ioexp_id){ + result_p = ioexp_curr_p; + break; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return result_p; +} +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.h new file mode 100644 index 000000000000..a5541617dd05 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/io_expander.h @@ -0,0 +1,143 @@ +#ifndef IO_EXPANDER_H +#define IO_EXPANDER_H + +#include + +/* IOEXP type define (QSFP series) */ +#define IOEXP_TYPE_CYPRESS_NABC (10102) +#define IOEXP_TYPE_CYPRESS_7ABC (10207) + +/* IOEXP mode define */ +#define IOEXP_MODE_DIRECT (19001) + +/* IOEXP state define */ +#define STATE_IOEXP_NORMAL (0) +#define STATE_IOEXP_INIT (-1) +#define STATE_IOEXP_ABNORMAL (-2) + +/* IOEXP error code define */ +#define ERR_IOEXP_NOTSUPPORT (-100) +#define ERR_IOEXP_UNINIT (-101) +#define ERR_IOEXP_BADCONF (-102) +#define ERR_IOEXP_BADINPUT (-105) +#define ERR_IOEXP_UNEXCPT (-199) + + +#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args) +#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args) +#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args) + +#ifdef DEBUG_SWPS +# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args) +#else +# define SWPS_DEBUG(fmt, args...) +#endif + + +struct ioexp_addr_s { + int chan_id; + int chip_addr; + int read_offset[8]; + int write_offset[8]; + int conf_offset[8]; + uint8_t data_default[8]; + uint8_t conf_default[8]; +}; + +struct ioexp_i2c_s { + int chip_id; + struct i2c_client *i2c_client_p; + struct ioexp_i2c_s *next; +}; + + +struct ioexp_bitmap_s { + int chip_id; /* IOEXP chip id */ + int ioexp_voffset; /* IOEXP virtual offset */ + int bit_shift; +}; + +struct ioexp_map_s { + int chip_amount; /* Number of chips that IOEXP object content */ + int data_width; /* Number of (Read/Write/Config) bytes */ + struct ioexp_addr_s *map_addr; /* Chip address info */ + struct ioexp_bitmap_s map_present[8]; /* IOEXP for SFP / QSFP */ + struct ioexp_bitmap_s map_tx_disable[8]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_tx_fault[8]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_rxlos[8]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_reset[8]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_lpmod[8]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_modsel[8]; /* IOEXP for QSFP */ +}; + +struct ioexp_data_s { + uint8_t data[8]; +}; + +struct ioexp_obj_s { + + /* ============================ + * Object public property + * ============================ + */ + int ioexp_id; + int ioexp_type; + + /* ============================ + * Object private property + * ============================ + */ + struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */ + struct ioexp_map_s *ioexp_map_p; + struct ioexp_obj_s *next; + struct ioexp_i2c_s *i2c_head_p; + struct mutex lock; + int mode; + int state; + + /* =========================================== + * Object public functions + * =========================================== + */ + int (*get_present)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset); + int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset); + int (*get_reset)(struct ioexp_obj_s *self, int virt_offset); + int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset); + int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset); + int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val); + + /* =========================================== + * Object private functions + * =========================================== + */ + int (*init)(struct ioexp_obj_s *self); + int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name); + int (*fsm_4_direct)(struct ioexp_obj_s* self); +}; + + +struct ioexp_obj_s* get_ioexp_obj(int ioexp_id); +int create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode); +int init_ioexp_objs(void); +void clean_ioexp_objs(void); + +int check_channel_tier_1(void); + +/* Macro for bit control */ +#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift))) +#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift))) + + +#endif /* IO_EXPANDER_H */ + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.c new file mode 100644 index 000000000000..368e412b19e2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.c @@ -0,0 +1,906 @@ +#include +#include +#include +#include +#include "io_expander.h" +#include "transceiver.h" + + +/* ========== Register EEPROM address mapping ========== + */ +struct eeprom_map_s eeprom_map_sfp = { + .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1, + .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1, + .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1, +}; + +struct eeprom_map_s eeprom_map_qsfp = { + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, +}; + +struct eeprom_map_s eeprom_map_qsfp28 = { + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, +}; + + +/* ========== Utility Functions ========== + */ +void +alarm_msg_2_user(struct transvr_obj_s *self, + char *emsg) { + + SWPS_ERR("%s on %s.\n", emsg, self->swp_name); +} + + +/* ========== Private functions ========== + */ +static int +_reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +_transvr_init_handler(struct transvr_obj_s *self); + +static void +_transvr_clean_retry(struct transvr_obj_s *self) { + self->retry = 0; +} + + +static int +_transvr_handle_retry(struct transvr_obj_s *self, int retry) { + /* Return: 0: keep retry + * -1: stop retry + */ + if (self->retry == 0) { + self->retry = retry; + } + self->retry -= 1; + if (self->retry <= 0) { + _transvr_clean_retry(self); + return -1; + } + return 0; +} + +static int +_common_setup_page(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int show_e) { + /* return: + * 0 : OK + * -1 : EEPROM settings incorrect + * -2 : I2C R/W failure + * -3 : Undefined case + */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Check */ + if ((addr < 0) || (offset < 0) || (len < 0)) { + emsg = "EEPROM settings incorrect"; + retval = -1; + goto err_common_setup_page; + } + /* Case1: continue access */ + if ((self->i2c_client_p->addr == addr) && + (self->curr_page == page)) { + return 0; + } + self->i2c_client_p->addr = addr; + /* Case2: select lower page */ + if (page == -1) { + self->curr_page = page; + return 0; + } + /* Case3: select upper page */ + if (page >= 0) { + goto upper_common_setup_page; + } + /* Unexpected case */ + show_e = 1; + emsg = "Unexpected case"; + retval = -3; + goto err_common_setup_page; + +upper_common_setup_page: + if (i2c_smbus_write_byte_data(self->i2c_client_p, + VAL_TRANSVR_PAGE_SELECT_OFFSET, + page) < 0) { + emsg = "I2C R/W failure"; + retval = -2; + goto err_common_setup_page; + } + self->curr_page = page; + mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY); + return 0; + +err_common_setup_page: + if (show_e) { + SWPS_INFO("%s: %s", __func__, emsg); + SWPS_INFO("%s: :0x%02x :%d :%d :%d\n", + __func__, addr, page, offset, len); + } + return retval; +} + +/* ========== Object functions for Final State Machine ========== + */ +int +is_plugged(struct transvr_obj_s *self){ + + int limit = 63; + int present = DEBUG_TRANSVR_INT_VAL; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p; + + if (!ioexp_p) { + snprintf(emsg, limit, "ioexp_p is null!"); + goto err_is_plugged_1; + } + present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset); + switch (present){ + case 0: + return 1; + case 1: + return 0; + case ERR_IOEXP_UNINIT: + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + default: + if (ioexp_p->state == STATE_IOEXP_INIT){ + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + } + break; + } + SWPS_INFO("%s: Exception case! :%d :%d\n", + __func__, present, ioexp_p->state); + return 0; + +err_is_plugged_1: + SWPS_DEBUG("%s: %s\n", __func__, emsg); + return 0; +} + + +static int +detect_transvr_type(struct transvr_obj_s* self){ + + int type = TRANSVR_TYPE_ERROR; + + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + type = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + + /* Case: 1. Wait transceiver I2C module. + * 2. Transceiver I2C module failure. + * Note: 1. SFF allow maximum transceiver initial time is 2 second. So, there + * are exist some case that we need to wait transceiver. + * For these case, we keeps status on "TRANSVR_TYPE_UNPLUGGED", than + * state machine will keep trace with it. + * 2. There exist some I2C failure case we need to handle. Such as user + * insert the failure transceiver, or any reason cause it abnormal. + */ + if (type < 0){ + switch (type) { + case -EIO: + SWPS_DEBUG("%s: %s smbus return:-5 (I/O error)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + case -ENXIO: + SWPS_DEBUG("%s: %s smbus return:-6 (No such device or address)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + default: + break; + } + SWPS_INFO("%s: %s unexpected smbus return:%d \n", + __func__, self->swp_name, type); + return TRANSVR_TYPE_ERROR; + } + /* Identify valid transceiver type */ + switch (type){ + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + break; + case TRANSVR_TYPE_UNKNOW_1: + case TRANSVR_TYPE_UNKNOW_2: + type = TRANSVR_TYPE_UNKNOW_2; + break; + default: + SWPS_DEBUG("%s: unknow type:0x%02x \n", __func__, type); + type = TRANSVR_TYPE_ERROR; + break; + } + return type; +} + + +static int +detect_transvr_state(struct transvr_obj_s *self, + int result[2]){ + /* [return] [result-0] [result-1] + * 0 STATE_TRANSVR_CONNECTED TRANSVR_TYPE_FAKE + * 0 STATE_TRANSVR_DISCONNECTED TRANSVR_TYPE_UNPLUGGED + * 0 STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * 0 STATE_TRANSVR_INIT / + * 0 STATE_TRANSVR_SWAPPED + * 0 STATE_TRANSVR_CONNECTED + * ERR_TRNASVR_BE_ISOLATED STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_I2C_CRASH STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_UNEXCPT STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_UNKNOW_1/2 + */ + result[0] = STATE_TRANSVR_UNEXCEPTED; /* For return state */ + result[1] = TRANSVR_TYPE_ERROR; /* For return type */ + + /* Case1: Fake type */ + if (self->type == TRANSVR_TYPE_FAKE){ + result[0] = STATE_TRANSVR_CONNECTED; + result[1] = TRANSVR_TYPE_FAKE; + return 0; + } + /* Case2: Transceiver unplugged */ + if (!is_plugged(self)){ + result[0] = STATE_TRANSVR_DISCONNECTED; + result[1] = TRANSVR_TYPE_UNPLUGGED; + return 0; + } + /* Case3: Transceiver be isolated */ + if (self->state == STATE_TRANSVR_ISOLATED){ + result[0] = STATE_TRANSVR_ISOLATED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case4: Transceiver plugged */ + result[1] = detect_transvr_type(self); + /* Case4.1: I2C topology crash + * Note : There are some I2C issues cause by transceiver/cables. + * We need to check topology status when user insert it. + * But in this step, we can't not ensure this is the issues + * port. So, it return the ERR_TRANSVR_I2C_CRASH, then upper + * layer will diagnostic I2C topology. + */ + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: %s detect I2C crash :%d\n", + __func__, self->swp_name, self->state); + result[0] = STATE_TRANSVR_UNEXCEPTED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_I2C_CRASH; + } + /* Case4.2: System initial not ready, + * Note : Sometime i2c channel or transceiver EEPROM will delay that will + * cause system in inconsistent state between EEPROM and IOEXP. + * In this case, SWP transceiver object keep state at LINK_DOWN + * to wait system ready. + * By the way, State Machine will handle these case. + */ + if (result[1] == TRANSVR_TYPE_UNPLUGGED){ + result[0] = STATE_TRANSVR_DISCONNECTED; + return 0; + } + /* Case4.3: Error transceiver type */ + if (result[1] == TRANSVR_TYPE_ERROR){ + result[0] = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s detect error type\n", __func__, self->swp_name); + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard!"); + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case3.3: Unknow transceiver type */ + if ((result[1] == TRANSVR_TYPE_UNKNOW_1) || + (result[1] == TRANSVR_TYPE_UNKNOW_2) ){ + result[0] = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + /* Case3.4: During initial process */ + if (self->state == STATE_TRANSVR_INIT){ + result[0] = STATE_TRANSVR_INIT; + return 0; + } + /* Case3.5: Transceiver be swapped */ + if (self->type != result[1]){ + result[0] = STATE_TRANSVR_SWAPPED; + return 0; + } + /* Case3.6: Link up state */ + result[0] = STATE_TRANSVR_CONNECTED; + return 0; +} +int +common_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + + int err; + int detect_result[2]; + int current_state = STATE_TRANSVR_UNEXCEPTED; + int current_type = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_NEW) { + if (_transvr_init_handler(self) < 0){ + return ERR_TRANSVR_INIT_FAIL; + } + } + err = detect_transvr_state(self, detect_result); + if (err < 0) { + return err; + } + /* In Direct mode, driver only detect transceiver when user call driver interface + * which on sysfs. So it only need consider the state of Transceiver. + */ + current_state = detect_result[0]; + current_type = detect_result[1]; + + switch (current_state){ + + case STATE_TRANSVR_DISCONNECTED: /* Transceiver is not plugged */ + self->state = current_state; + self->type = current_type; + return ERR_TRANSVR_UNPLUGGED; + + case STATE_TRANSVR_INIT: /* Transceiver is plugged, system not ready */ + return ERR_TRANSVR_UNINIT; + + case STATE_TRANSVR_ISOLATED: /* Transceiver is plugged, but has some issues */ + return ERR_TRNASVR_BE_ISOLATED; + + case STATE_TRANSVR_CONNECTED: /* Transceiver is plugged, system is ready */ + self->state = current_state; + self->type = current_type; + return 0; + + case STATE_TRANSVR_SWAPPED: /* Transceiver is plugged, system detect user changed */ + self->type = current_type; + if (reload_transvr_obj(self, current_type) < 0){ + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + self->state = current_state; + return 0; + + case STATE_TRANSVR_UNEXCEPTED: /* Transceiver type or state is unexpected case */ + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_UNEXCPT; + + default: + SWPS_INFO("%s: state:%d not in define.\n", __func__, current_state); + break; + } + return ERR_TRANSVR_UNEXCPT; +} + +int +fake_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + +/* ========== Object Initial handler ========== + */ +static int +_is_transvr_valid(struct transvr_obj_s *self, + int type, + int state) { + /* [Return] + * 0 : OK, inserted + * EVENT_TRANSVR_INIT_DOWN : OK, removed + * EVENT_TRANSVR_INIT_FAIL : Outside error, type doesn't supported + * EVENT_TRANSVR_EXCEP_INIT : Internal error, state undefined + */ + switch (type) { + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + break; + default: + SWPS_INFO("detect undefined type:0x%02x on %s\n", + type, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; + } + switch (state) { + case STATE_TRANSVR_DISCONNECTED: + return EVENT_TRANSVR_INIT_DOWN; + case STATE_TRANSVR_INIT: + case STATE_TRANSVR_CONNECTED: + case STATE_TRANSVR_SWAPPED: + break; + default: + SWPS_INFO("detect undefined state:%d on %s\n", + state, self->swp_name); + return EVENT_TRANSVR_EXCEP_INIT; + } + return 0; +} + + +static int +_is_transvr_hw_ready(struct transvr_obj_s *self, + int type){ + /* [Return] + * EVENT_TRANSVR_TASK_DONE : Ready + * EVENT_TRANSVR_TASK_WAIT : Not ready + * EVENT_TRANSVR_INIT_FAIL : Error + */ + int addr = DEBUG_TRANSVR_INT_VAL; + int page = DEBUG_TRANSVR_INT_VAL; + int offs = DEBUG_TRANSVR_INT_VAL; + int bit = DEBUG_TRANSVR_INT_VAL; + int ready = DEBUG_TRANSVR_INT_VAL; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t ab_val = DEBUG_TRANSVR_HEX_VAL; + + switch (type) { + case TRANSVR_TYPE_SFP: + addr = VAL_TRANSVR_8472_READY_ADDR; + page = VAL_TRANSVR_8472_READY_PAGE; + offs = VAL_TRANSVR_8472_READY_OFFSET; + bit = VAL_TRANSVR_8472_READY_BIT; + ready = VAL_TRANSVR_8472_READY_VALUE; + ab_val = VAL_TRANSVR_8472_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + addr = VAL_TRANSVR_8436_READY_ADDR; + page = VAL_TRANSVR_8436_READY_PAGE; + offs = VAL_TRANSVR_8436_READY_OFFSET; + bit = VAL_TRANSVR_8436_READY_BIT; + ready = VAL_TRANSVR_8436_READY_VALUE; + ab_val = VAL_TRANSVR_8436_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + return EVENT_TRANSVR_TASK_DONE; + + default: + emsg = "unexpected case"; + goto err_is_transvr_hw_ready; + } + /* Select target page */ + err = _common_setup_page(self, addr, page, offs, 1, 0); + if (err < 0) { + emsg = "setup page fail"; + goto err_is_transvr_hw_ready; + } + /* Check feature supported + * [Note] + * Some of transceiver/cables doesn't support "Status Indicators" + * (ex:DAC, RJ45 copper SFP ...etc). In these case, we bypass the + * step of checking Status Indicators, then state machine will take + * the following handle procedure. + */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (err < 0) { + emsg = "doesn't support Status Indicators"; + goto bypass_is_transvr_hw_ready; + } + /* Filter abnormal case */ + if (err == ab_val) { + emsg = "detect using unusual definition."; + goto bypass_is_transvr_hw_ready; + } + /* Get Status Indicators */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, offs); + if (err < 0) { + emsg = "detect current value fail"; + goto err_is_transvr_hw_ready; + } + if ((err & (1<:%d\n", __func__, emsg, type); + return EVENT_TRANSVR_TASK_DONE; + +err_is_transvr_hw_ready: + SWPS_DEBUG("%s: %s :%d\n", __func__, emsg, type); + return EVENT_TRANSVR_INIT_FAIL; +} + +static int +_transvr_init_handler(struct transvr_obj_s *self){ + + int detect[2]; + int d_state = STATE_TRANSVR_UNEXCEPTED; + int d_type = TRANSVR_TYPE_ERROR; + int result = ERR_TRANSVR_UNINIT; + int retry = 6; /* (6+1) x 0.3 = 2.1s > spec:2.0s */ + int elimit = 63; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Clean and check callback */ + self->state = STATE_TRANSVR_INIT; + if (self->init == NULL) { + snprintf(emsg, elimit, "init() is null"); + goto initer_err_case_unexcept_0; + } + /* Detect transceiver information */ + result = detect_transvr_state(self, detect); + if (result < 0) { + snprintf(emsg, elimit, "detect_transvr_state() fail"); + switch (result) { + case ERR_TRANSVR_I2C_CRASH: + goto initer_err_case_i2c_ceash; + case ERR_TRNASVR_BE_ISOLATED: + goto initer_err_case_be_isolated; + + case ERR_TRANSVR_UNEXCPT: + default: + break; + } + goto initer_err_case_retry_1; + } + d_state = detect[0]; + d_type = detect[1]; + + /* Verify transceiver type and state */ + switch (_is_transvr_valid(self, d_type, d_state)) { + case 0: + break; + case EVENT_TRANSVR_INIT_DOWN: + goto initer_ok_case_down;; + case EVENT_TRANSVR_INIT_FAIL: + snprintf(emsg, elimit, "transceiver type doesn't support"); + goto initer_err_case_alarm_to_user; + case EVENT_TRANSVR_EXCEP_INIT: + default: + goto initer_err_case_unexcept_0; + } + + /* Handle reload case */ + if (self->type != d_type){ + /* This is the protect mechanism. Normally, This case will not happen. + * When State machine detect swap event during initial, It will trigger + * reload function to ensure type correct. */ + if (_reload_transvr_obj(self, d_type) < 0){ + snprintf(emsg, elimit, "reload object fail"); + goto initer_err_case_unexcept_0; + } + } + + /* Check transceiver HW initial ready */ + switch (_is_transvr_hw_ready(self, d_type)) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_err_case_retry_1; + case EVENT_TRANSVR_INIT_FAIL: + default: + goto initer_err_case_unexcept_0; + } + + /* Try to update all and check */ + if (self->update_all(self, 1) < 0){ + /* For some transceiver, EEPROME has lag issues during initial stage. + * In this case, we set status back to STATE_TRANSVR_NEW, than it will + * be checked in next polling cycle. */ + goto initer_err_case_retry_1; + } + + /* Execute init() call back */ + result = self->init(self); + switch (result) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_ok_case_wait; + + default: + snprintf(emsg, elimit, "undefined init() return:%d\n", result); + goto initer_err_case_unexcept_0; + } + goto initer_ok_case_up; + + +initer_ok_case_wait: + return EVENT_TRANSVR_TASK_WAIT; + +initer_ok_case_up: + self->state = STATE_TRANSVR_CONNECTED; + self->temp = 0; + return EVENT_TRANSVR_INIT_UP; + +initer_ok_case_down: + self->temp = 0; + self->state = STATE_TRANSVR_DISCONNECTED; + return EVENT_TRANSVR_INIT_DOWN; + +initer_err_case_i2c_ceash: + SWPS_DEBUG("%s: %s :%s :I2C crash\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_I2C_CRASH; + +initer_err_case_be_isolated: + SWPS_DEBUG("%s: %s :%s :isolated\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return EVENT_TRANSVR_EXCEP_ISOLATED; + +initer_err_case_retry_1: + SWPS_DEBUG("%s: %s :%s :retry\n", + __func__, emsg, self->swp_name); + if (_transvr_handle_retry(self, retry) == 0) { + self->state = STATE_TRANSVR_NEW; + return EVENT_TRANSVR_INIT_REINIT; + } + goto initer_err_case_alarm_to_user; + +initer_err_case_unexcept_0: + self->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_INIT_FAIL; + +initer_err_case_alarm_to_user: + SWPS_DEBUG("%s: %s :%s :alarm_to_user\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard"); + return EVENT_TRANSVR_INIT_FAIL; +} + +static int +setup_transvr_private_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->fsm_4_direct = common_fsm_4_direct_mode; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->fsm_4_direct = common_fsm_4_direct_mode; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->fsm_4_direct = common_fsm_4_direct_mode; + return 0; + + case TRANSVR_TYPE_FAKE: + self->fsm_4_direct = fake_fsm_4_direct_mode; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static struct eeprom_map_s * +get_eeprom_map(int transvr_type){ + + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + return &eeprom_map_sfp; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + return &eeprom_map_qsfp; + case TRANSVR_TYPE_QSFP_28: + return &eeprom_map_qsfp28; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return NULL; +} + + +static int +setup_transvr_ssize_attr(char *swp_name, + struct transvr_obj_s *self, + struct eeprom_map_s *map_p, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int chan_id, + int run_mode){ + switch (run_mode){ + case TRANSVR_MODE_DIRECT: /* Direct access device mode */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = DEBUG_TRANSVR_INT_VAL; + return -1; + } + self->eeprom_map_p = map_p; + self->ioexp_obj_p = ioexp_obj_p; + self->ioexp_virt_offset = ioexp_virt_offset; + self->chan_id = chan_id; + self->layout = transvr_type; + self->type = transvr_type; + self->chipset_type = chipset_type; + self->state = STATE_TRANSVR_NEW; + self->info = STATE_TRANSVR_NEW; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + strncpy(self->swp_name, swp_name, 32); + mutex_init(&self->lock); + return 0; +} + + + +static int +setup_i2c_client(struct transvr_obj_s *self){ + + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + adap = i2c_get_adapter(self->chan_id); + if(!adap){ + snprintf(err_msg, sizeof(err_msg), + "can not get adap:%d", self->chan_id); + goto err_setup_i2c_client; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + snprintf(err_msg, sizeof(err_msg), + "can not kzalloc client:%d", self->chan_id); + goto err_setup_i2c_client; + } + client->adapter = adap; + self->i2c_client_p = client; + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + return 0; + +err_setup_i2c_client: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return ERR_TRANSVR_UNEXCPT; +} + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode){ + + struct transvr_obj_s *result_p; + struct eeprom_map_s *map_p; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Allocate transceiver object */ + map_p = get_eeprom_map(transvr_type); + if (!map_p){ + snprintf(err_msg, sizeof(err_msg), + "Invalid transvr_type:%d", transvr_type); + goto err_create_transvr_fail; + } + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_create_transvr_fail; + } + /* Prepare static size attributes */ + if (setup_transvr_ssize_attr(swp_name, + result_p, + map_p, + ioexp_obj_p, + ioexp_virt_offset, + transvr_type, + chipset_type, + chan_id, + run_mode) < 0){ + goto err_create_transvr_sattr_fail; + } + + /* Prepare call back functions of object */ + if (setup_transvr_private_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_sattr_fail; + } + /* Prepare i2c client object */ + if (setup_i2c_client(result_p) < 0){ + goto err_create_transvr_sattr_fail; + } + return result_p; +err_create_transvr_sattr_fail: + kfree(result_p); +err_create_transvr_fail: + SWPS_ERR("%s: %s :%d :%d :%d\n", + __func__, err_msg, chan_id, ioexp_virt_offset, transvr_type); + return NULL; +} + + +static int +_reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + struct eeprom_map_s *new_map_p; + struct eeprom_map_s *old_map_p = self->eeprom_map_p; + struct i2c_client *old_i2c_p = self->i2c_client_p; + int old_type = self->type; + + /* Change state to STATE_TRANSVR_INIT */ + self->state = STATE_TRANSVR_INIT; + self->type = new_type; + /* Replace EEPROME map */ + new_map_p = get_eeprom_map(new_type); + if (!new_map_p){ + goto err_private_reload_func_1; + } + self->eeprom_map_p = new_map_p; + /* Reload i2c client */ + if (setup_i2c_client(self) < 0){ + goto err_private_reload_func_2; + } + if (setup_transvr_private_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + kfree(old_i2c_p); + return 0; + +err_private_reload_func_3: + SWPS_INFO("%s: init() fail!\n", __func__); + kfree(old_i2c_p); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return -2; + +err_private_reload_func_2: + self->eeprom_map_p = old_map_p; + self->i2c_client_p = old_i2c_p; +err_private_reload_func_1: + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = old_type; + SWPS_INFO("%s fail! :0x%02x\n", __func__, new_type); + return -1; +} + + +static int +reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + int result_val = ERR_TRANSVR_UNEXCPT; + + /* Reload phase */ + result_val = _reload_transvr_obj(self, new_type); + if (result_val < 0){ + SWPS_INFO("%s: reload phase fail! :%d\n", + __func__, result_val); + return EVENT_TRANSVR_RELOAD_FAIL; + } + /* Initial phase */ + result_val = _transvr_init_handler(self); + if (result_val < 0){ + SWPS_INFO("%s: initial phase fail! :%d\n", + __func__, result_val); + } + return result_val; +} + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.h new file mode 100644 index 000000000000..0e79f0b9027f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/modules/transceiver.h @@ -0,0 +1,168 @@ +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* Transceiver type define */ +#define TRANSVR_TYPE_UNKNOW_1 (0x00) +#define TRANSVR_TYPE_UNKNOW_2 (0xff) +#define TRANSVR_TYPE_SFP (0x03) /* Define for SFP, SFP+, SFP28 */ +#define TRANSVR_TYPE_QSFP (0x0c) +#define TRANSVR_TYPE_QSFP_PLUS (0x0d) +#define TRANSVR_TYPE_QSFP_28 (0x11) +#define TRANSVR_TYPE_UNPLUGGED (0xfa) /* Define for ERROR handle */ +#define TRANSVR_TYPE_FAKE (0xfc) /* Define for ERROR handle */ +#define TRANSVR_TYPE_INCONSISTENT (0xfd) /* Define for ERROR handle */ +#define TRANSVR_TYPE_ERROR (0xfe) /* Define for ERROR handle */ + +/* Transceiver mode define */ +#define TRANSVR_MODE_DIRECT (21000) + +/* Transceiver state define + * [Note] + * 1. State is used to represent the state of "Transceiver" and "Object". + * 2. State for different target has different means. The description as following: + */ +#define STATE_TRANSVR_CONNECTED (0) /* [Transvr]:Be plugged in. [Obj]:Link up, and work normally. */ +#define STATE_TRANSVR_NEW (-100) /* [Transvr]:(Not used) [Obj]:Create */ +#define STATE_TRANSVR_INIT (-101) /* [Transvr]:Be plugged in. [Obj]:Link up, and in initial process. */ +#define STATE_TRANSVR_ISOLATED (-102) /* [Transvr]:Be plugged in. [Obj]:Isolate, and not provide service. */ +#define STATE_TRANSVR_SWAPPED (-200) /* [Transvr]:Be plugged in. [Obj]:(Not used) */ +#define STATE_TRANSVR_DISCONNECTED (-300) /* [Transvr]:Un-plugged. [Obj]:Link down, and not provide service. */ +#define STATE_TRANSVR_UNEXCEPTED (-901) /* [Transvr]:Any [Obj]:Any, and not in expect case. */ + +/* Event for task handling */ +#define EVENT_TRANSVR_TASK_WAIT (2101) +#define EVENT_TRANSVR_TASK_DONE (0) +#define EVENT_TRANSVR_TASK_FAIL (-2101) +/* Event for initial handling */ +#define EVENT_TRANSVR_INIT_UP (2201) +#define EVENT_TRANSVR_INIT_DOWN (1) +#define EVENT_TRANSVR_INIT_REINIT (-2201) +#define EVENT_TRANSVR_INIT_FAIL (-2202) +/* Event for others */ +#define EVENT_TRANSVR_RELOAD_FAIL (-2301) +#define EVENT_TRANSVR_EXCEP_INIT (-2401) +#define EVENT_TRANSVR_EXCEP_UP (-2402) +#define EVENT_TRANSVR_EXCEP_DOWN (-2403) +#define EVENT_TRANSVR_EXCEP_SWAP (-2404) +#define EVENT_TRANSVR_EXCEP_EXCEP (-2405) +#define EVENT_TRANSVR_EXCEP_ISOLATED (-2406) +#define EVENT_TRANSVR_I2C_CRASH (-2501) + +/* Transceiver error code define */ +#define ERR_TRANSVR_UNINIT (-201) +#define ERR_TRANSVR_UNPLUGGED (-202) +#define ERR_TRANSVR_ABNORMAL (-203) +#define ERR_TRANSVR_NOSTATE (-204) +#define ERR_TRANSVR_NOTSUPPORT (-205) +#define ERR_TRANSVR_BADINPUT (-206) +#define ERR_TRANSVR_UPDATE_FAIL (-207) +#define ERR_TRANSVR_RELOAD_FAIL (-208) +#define ERR_TRANSVR_INIT_FAIL (-209) +#define ERR_TRANSVR_UNDEFINED (-210) +#define ERR_TRANSVR_TASK_FAIL (-211) +#define ERR_TRANSVR_TASK_BUSY (-212) +#define ERR_TRANSVR_FUNC_DISABLE (-214) +#define ERR_TRANSVR_I2C_CRASH (-297) +#define ERR_TRNASVR_BE_ISOLATED (-298) +#define ERR_TRANSVR_UNEXCPT (-299) + +/* For debug */ +#define DEBUG_TRANSVR_INT_VAL (-99) +#define DEBUG_TRANSVR_HEX_VAL (0xfe) +#define DEBUG_TRANSVR_STR_VAL "ERROR" + +/* For system internal */ +#define VAL_TRANSVR_COMID_ARREESS (0x50) +#define VAL_TRANSVR_COMID_OFFSET (0x00) +#define VAL_TRANSVR_8472_READY_ADDR (0x51) +#define VAL_TRANSVR_8472_READY_PAGE (-1) +#define VAL_TRANSVR_8472_READY_OFFSET (110) +#define VAL_TRANSVR_8472_READY_BIT (0) +#define VAL_TRANSVR_8472_READY_VALUE (0) +#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_READY_ADDR (0x50) +#define VAL_TRANSVR_8436_READY_PAGE (-1) +#define VAL_TRANSVR_8436_READY_OFFSET (2) +#define VAL_TRANSVR_8436_READY_BIT (0) +#define VAL_TRANSVR_8436_READY_VALUE (0) +#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_PWD_ADDR (0x50) +#define VAL_TRANSVR_8436_PWD_PAGE (-1) +#define VAL_TRANSVR_8436_PWD_OFFSET (123) +#define VAL_TRANSVR_PAGE_FREE (-99) +#define VAL_TRANSVR_PAGE_SELECT_OFFSET (127) +#define VAL_TRANSVR_PAGE_SELECT_DELAY (5) +#define VAL_TRANSVR_TASK_RETRY_FOREVER (-999) +#define VAL_TRANSVR_FUNCTION_DISABLE (-1) +#define STR_TRANSVR_SFP "SFP" +#define STR_TRANSVR_QSFP "QSFP" +#define STR_TRANSVR_QSFP_PLUS "QSFP+" +#define STR_TRANSVR_QSFP28 "QSFP28" + +/* BCM chip type define */ +#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress */ + +/* Info from transceiver EEPROM */ +struct eeprom_map_s { + int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los; + int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable; + int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault; +}; + +/* Class of transceiver object */ +struct transvr_obj_s { + /* ========== Object private property ========== + */ + struct device *transvr_dev_p; + struct eeprom_map_s *eeprom_map_p; + struct i2c_client *i2c_client_p; + struct ioexp_obj_s *ioexp_obj_p; + struct mutex lock; + char swp_name[32]; + int auto_tx_disable; + int chan_id; + int chipset_type; + int curr_page; + int info; + int ioexp_virt_offset; + int lane_id[8]; + int layout; + int mode; + int retry; + int state; + int temp; + int type; + + /* ========== Object private functions ========== + */ + int (*init)(struct transvr_obj_s *self); + int (*update_all)(struct transvr_obj_s *self, int show_err); + int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name); +}; + + +/* For AVL Mapping */ +struct transvr_avl_s { + char vendor_name[32]; + char vendor_pn[32]; + int (*init)(struct transvr_obj_s *self); +}; + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode); + +void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + +#endif /* TRANSCEIVER_H */ + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/setup.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/setup.py new file mode 100644 index 000000000000..3bd7b4825f43 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize Inventec D7054Q28B platforms', + + packages=['sonic_platform'], +) + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/__init__.py new file mode 100644 index 000000000000..4bfefa0fb636 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/chassis.py new file mode 100644 index 000000000000..0c83a22cd251 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/chassis.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.eeprom import Eeprom + from sonic_platform.psu import Psu + from sonic_platform.sfp import Sfp + from sonic_platform.fan import Fan + from sonic_platform.watchdog import Watchdog + from sonic_platform.thermal import Thermal + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Chassis(ChassisBase): + + def __init__(self): + ChassisBase.__init__(self) + self.__num_of_psus = 2 + self.__num_of_ports = 54 + self.__num_of_sfps = 48 + self.__num_of_fans = 4 + self.__num_of_thermals = 6 + + # Initialize EEPROM + self._eeprom = Eeprom() + + # Initialize watchdog + #self._watchdog = Watchdog() + + # Initialize FAN + for index in range(1, self.__num_of_fans + 1): + fan = Fan(index) + self._fan_list.append(fan) + + # Initialize thermal + for index in range(1, self.__num_of_thermals + 1): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + # Initialize PSU and PSU_FAN + for index in range(1, self.__num_of_psus + 1): + psu = Psu(index) + self._psu_list.append(psu) + fan = Fan(index, True) + self._fan_list.append(fan) + + # Initialize SFP + for index in range(0, self.__num_of_ports): + if index in range(0,self.__num_of_sfps): + sfp = Sfp(index, 'SFP') + else: + sfp = Sfp(index, 'QSFP') + + self._sfp_list.append(sfp) + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + +############################################## +# Chassis methods +############################################## + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/eeprom.py new file mode 100644 index 000000000000..70a4b0ecb437 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/eeprom.py @@ -0,0 +1,109 @@ +# +# Name: eeprom.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.__eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0053/eeprom" + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + self.__eeprom_tlv_dict = dict() + try: + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + ord(eeprom[tlv_index + 1])] + code = "0x%02X" % (ord(tlv[0])) + + if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT: + value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) | + (ord(tlv[4]) << 8) | ord(tlv[5])) + value += str(tlv[6:6 + ord(tlv[1])]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32: + break + + tlv_index += ord(eeprom[tlv_index+1]) + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2] + + def base_mac_addr(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2] + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2] + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2] + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.__eeprom_tlv_dict + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/fan.py new file mode 100644 index 000000000000..ecfbfe2d8763 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/fan.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python + +############################################################################# +# Inventec d7264 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the FAN information +# +############################################################################# + +try: + import os + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +############### +# Global +############### +FAN_DIR = "/sys/bus/i2c/devices/0-0066/" +MAX_PWM = 255 +class Fan(FanBase): + """Platform-specific Fan class""" + + def __init__(self, index, is_psu_fan=False): + self.is_psu_fan = is_psu_fan + + self.fan_gpi = "fan_gpi" + self.fan_index = index + if self.is_psu_fan: + self.fan_pwm = "pwm_psu{}".format(self.fan_index) + self.psu_fan_rpm = "rpm_psu{}".format(self.fan_index) + else: + self.fan_pwm = "pwm{}".format(self.fan_index) + self.fan_status_led_green_color = "fan_led_grn{}".format(self.fan_index) + self.fan_status_led_red_color = "fan_led_red{}".format(self.fan_index) + self.fan_front_rpm = "fan{}_input".format(self.fan_index * 2 - 1) + self.fan_rear_rpm = "fan{}_input".format(self.fan_index * 2) + + +####################### +# private function +####################### + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + + #################### + # Device base + #################### + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + if self.is_psu_fan: + return "PSU-{}_FAN".format(self.fan_index) + else: + return "FAN-{}".format(self.fan_index) + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + + Note: + fan_gpi define 8 bits + low byte means fan presense + high byte means fan direction + """ + presence = False + attr_path = FAN_DIR + self.fan_gpi + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + not_presence_bit = 1 << (self.fan_index - 1) + if not (int(attr_rv,16) and not_presence_bit): + presence = True + + return presence + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + if not self.is_psu_fan: + status = False + attr_grn_path = FAN_DIR + self.fan_status_led_green_color + + attr_grn_rv = self.__get_attr_value(attr_grn_path) + if (attr_grn_rv != 'ERR' and attr_grn_rv == '1'): + status = True + return status + + ################# + # fan base + ################# + + def get_direction(self): + """ + Retrieves the direction of fan + + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Note: + fan_gpi define 8 bits + low byte means fan presense + high byte means fan direction + """ + direction = self.FAN_DIRECTION_INTAKE + attr_path = FAN_DIR + self.fan_gpi + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + #attr_rv = attr_rv >> 4 + direction_bit = 1 << ((self.fan_index - 1)+4) + if not (int(attr_rv,16) and direction_bit): + direction = self.FAN_DIRECTION_EXHAUST + + return direction + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + speed = 0 + attr_path = FAN_DIR + self.fan_pwm + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + pwm = int(attr_rv,10)if attr_rv else 0 + speed = float(pwm*100/MAX_PWM) + + return int(speed) + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + speed = 0 + attr_path = FAN_DIR + self.fan_pwm + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + pwm = int(attr_rv,10)if attr_rv else 0 + speed = float(pwm*100/MAX_PWM) + + return int(speed) + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + return 20 + + 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 + """ + if self.is_psu_fan: + return self.STATUS_LED_COLOR_OFF + + attr_grn_path = FAN_DIR + self.fan_status_led_green_color + attr_red_path = FAN_DIR + self.fan_status_led_red_color + + attr_grn_rv = self.__get_attr_value(attr_grn_path) + attr_red_rv = self.__get_attr_value(attr_red_path) + if (attr_grn_rv != 'ERR' and attr_red_rv != 'ERR'): + if (attr_grn_rv == '1'): + return self.STATUS_LED_COLOR_GREEN + elif (attr_red_rv == '1'): + return self.STATUS_LED_COLOR_RED + else: + return self.STATUS_LED_COLOR_OFF diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/platform.py new file mode 100644 index 000000000000..ddad8c4c5788 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/platform.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/psu.py new file mode 100644 index 000000000000..52dd2b12fb20 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/psu.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python +# +# Name: psu.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + from sonic_platform_base.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PSU_DIR = "/sys/bus/i2c/devices/0-0066/" + +class Psu(PsuBase): + def __init__(self, index): + self.index = index + self.psu_presence_attr = "psu{}".format(self.index-1) + self.psu_status_attr = "psoc_psu{}_iout".format(self.index) + self.psu_power_in_attr = "power{}_input".format(self.index) + self.psu_power_out_attr = "power{}_input".format(self.index) + self.psu_voltage_out_attr = "psoc_psu{}_vin".format(self.index) + self.psu_current_out_attr = "psoc_psu{}_iout".format(self.index) + self.psu_serial_attr = "psoc_psu{}_serial".format(self.index) + self.psu_model_attr = "psoc_psu{}_vender".format(self.index) + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = PSU_DIR+self.psu_presence_attr + attr_normal = "0 : normal" + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (attr_rv == attr_normal): + 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 = "N/A" + attr_path = PSU_DIR+self.psu_model_attr + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + model = attr_rv + + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + serial = "N/A" + attr_path = PSU_DIR+self.psu_serial_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + serial = attr_rv + + 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 + """ + status = False + attr_path = PSU_DIR+self.psu_status_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) != 0): + status = True + + return status + +############################################## +# PSU methods +############################################## + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + voltage_out = 0.0 + attr_path = PSU_DIR+self.psu_voltage_out_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + voltage_out = float(attr_rv) / 1000 + + return voltage_out + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + current_out = 0.0 + attr_path = PSU_DIR+self.psu_current_out_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + current_out = float(attr_rv) / 1000 + + return current_out + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, e.g. 302.6 + """ + power_out = 0.0 + attr_path = PSU_DIR+self.psu_power_out_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + power_out = float(attr_rv) / 1000000 + + return power_out + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + return self.get_status() + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/sfp.py new file mode 100644 index 000000000000..a18d98d502f5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/sfp.py @@ -0,0 +1,1284 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Sfp contains an implementation of SONiC Platform Base API and +# provides the sfp device status which are available in the platform +# +############################################################################# + +import os +import time +import subprocess +from ctypes import create_string_buffer + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.inf8628 import inf8628InterfaceId + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +INFO_OFFSET = 128 +DOM_OFFSET = 0 + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 + +XCVR_INTERFACE_DATA_START = 0 +XCVR_INTERFACE_DATA_SIZE = 92 + +QSFP_DOM_BULK_DATA_START = 22 +QSFP_DOM_BULK_DATA_SIZE = 36 +SFP_DOM_BULK_DATA_START = 96 +SFP_DOM_BULK_DATA_SIZE = 10 + +# definitions of the offset for values in OSFP info eeprom +OSFP_TYPE_OFFSET = 0 +OSFP_VENDOR_NAME_OFFSET = 129 +OSFP_VENDOR_PN_OFFSET = 148 +OSFP_HW_REV_OFFSET = 164 +OSFP_VENDOR_SN_OFFSET = 166 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 1 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_MODULE_MONITOR_OFFSET = 0 +QSFP_MODULE_MONITOR_WIDTH = 9 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_POWEROVERRIDE_BIT = 0 +QSFP_POWERSET_BIT = 1 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_CHANNL_STATUS_OFFSET = 110 +SFP_CHANNL_STATUS_WIDTH = 1 + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes','FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia','FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" +OSFP_TYPE = "OSFP" + + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + + # Port number + PORT_START = 0 + PORT_END = 53 + + # Path to QSFP sysfs + PLATFORM_ROOT_PATH = "/usr/share/sonic/device" + PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" + HOST_CHK_CMD = "docker > /dev/null 2>&1" + + PLATFORM = "x86_64-inventec_d7054q28b-r0" + HWSKU = "INVENTEC-D7054Q28B-S48-Q6" + + def __init__(self, sfp_index, sfp_type): + # Init index + self.index = sfp_index + self.port_num = self.index + self.dom_supported = False + self.sfp_type = sfp_type + self.__sfp_presence_attr = "/sys/class/swps/port{}/present".format(self.index) + self.__sfp_lpmode_attr = "/sys/class/swps/port{}/lpmod".format(self.index) + self.__sfp_reset_attr = "/sys/class/swps/port{}/reset".format(self.index) + # Init eeprom path + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom' + self.port_to_eeprom_mapping = {} + self.port_to_i2c_mapping = { + 0: 10, + 1: 11, + 2: 12, + 3: 13, + 4: 14, + 5: 15, + 6: 16, + 7: 17, + 8: 18, + 9: 19, + 10: 20, + 11: 21, + 12: 22, + 13: 23, + 14: 24, + 15: 25, + 16: 26, + 17: 27, + 18: 28, + 19: 29, + 20: 30, + 21: 31, + 22: 32, + 23: 33, + 24: 34, + 25: 35, + 26: 36, + 27: 37, + 28: 38, + 29: 39, + 30: 40, + 31: 41, + 32: 42, + 33: 43, + 34: 44, + 35: 45, + 36: 46, + 37: 47, + 38: 48, + 39: 49, + 40: 50, + 41: 51, + 42: 52, + 43: 53, + 44: 54, + 45: 55, + 46: 56, + 47: 57, + 48: 58, + 49: 59, + 50: 60, + 51: 61, + 52: 62, + 53: 63 + } + + 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.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + SfpBase.__init__(self) + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def __read_txt_file(self, file_path): + try: + with open(file_path, 'r') as fd: + data = fd.read() + return data.strip() + except IOError: + pass + return "" + + def __is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) + hwsku_path = "/".join([platform_path, self.HWSKU] + ) if self.__is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + presence = False + attr_path = self.__sfp_presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 0): + presence = True + + return presence + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def _dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + return + + if self.sfp_type == "QSFP": + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # 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((offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self.__read_eeprom_specific_bytes(QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_OFFSET) + qsfp_version_compliance = int(qsfp_version_compliance_raw[0], 16) + qspf_dom_capability = int(qsfp_dom_capability_raw[0], 16) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = (qspf_dom_capability & 0x20 != 0) + self.dom_volt_supported = (qspf_dom_capability & 0x10 != 0) + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = (qspf_dom_capability & 0x04 != 0) + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = (qspf_dom_capability & 0x08 != 0) + self.dom_tx_power_supported = True + self.dom_supported = True + self.calibration = 1 + qsfp_option_value_raw = self.__read_eeprom_specific_bytes(QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH) + if qsfp_option_value_raw is not None: + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + self.optional_capability = sfpd_obj.parse_option_params(qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = self.optional_capability['data']['TxDisable']['value'] == 'On' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + elif self.sfp_type == "SFP": + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self.__read_eeprom_specific_bytes(XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = (int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + transceiver_info_dict = {} + compliance_code_dict = {} + + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + if self.sfp_type == OSFP_TYPE: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP + + sfpi_obj = inf8628InterfaceId() + if sfpi_obj is None: + return None + + sfp_type_raw = self.__read_eeprom_specific_bytes((offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes((offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes((offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes((offset + OSFP_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes((offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = 'N/A' + transceiver_info_dict['vendor_date'] = 'N/A' + transceiver_info_dict['connector'] = 'N/A' + transceiver_info_dict['encoding'] = 'N/A' + transceiver_info_dict['ext_identifier'] = 'N/A' + transceiver_info_dict['ext_rateselect_compliance'] = 'N/A' + transceiver_info_dict['cable_type'] = 'N/A' + transceiver_info_dict['cable_length'] = 'N/A' + transceiver_info_dict['specification_compliance'] = 'N/A' + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + + else: + if self.sfp_type == QSFP_TYPE: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + cable_length_width = XCVR_CABLE_LENGTH_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + sfp_type = 'QSFP' + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + cable_length_width = XCVR_CABLE_LENGTH_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + sfp_type = 'SFP' + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes(offset + XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE) + if sfp_interface_bulk_raw is None: + return None + + start = XCVR_INTFACE_BULK_OFFSET - XCVR_INTERFACE_DATA_START + end = start + interface_info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_NAME_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_NAME_WIDTH + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_PN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_PN_WIDTH + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_HW_REV_OFFSET - XCVR_INTERFACE_DATA_START + end = start + vendor_rev_width + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_SN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_SN_WIDTH + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_OUI_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_OUI_WIDTH + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_DATE_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_DATE_WIDTH + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_interface_bulk_raw[start : end], 0) + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + # check present status + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + + if not self.get_presence() or not sfpi_obj or not sfpd_obj: + return {} + + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + offset = DOM_OFFSET + offset_xcvr = INFO_OFFSET + + # 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( + (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_dom_capability( + qsfp_dom_capability_raw, 0) + else: + return None + + dom_temperature_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes( + (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) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes( + (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) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['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 = {} + dom_channel_monitor_raw = None + 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( + (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: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (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) + 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'] + + if dom_channel_monitor_raw: + 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'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self._convert_string_to_num( + transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + if not self.dom_supported: + return False + + if self.sfp_type == OSFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + dom_module_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_MODULE_MONITOR_OFFSET), QSFP_MODULE_MONITOR_WIDTH) + + if dom_module_monitor_raw is not None: + return True + else: + return False + elif self.sfp_type == SFP_TYPE: + offset = 0 + sfpd_obj = sff8472Dom() + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + + if dom_channel_monitor_raw is not None: + return True + else: + return False + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + if not self.dom_supported: + return None + + rx_los_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x02 != 0) + else: + return None + return rx_los_list + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + if not self.dom_supported: + return None + + tx_fault_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + else: + return None + return tx_fault_list + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + if not self.dom_supported: + return None + + tx_disable_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_CHANNL_DISABLE_STATUS_OFFSET), QSFP_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0x01 != 0) + tx_disable_list.append(tx_disable_data & 0x02 != 0) + tx_disable_list.append(tx_disable_data & 0x04 != 0) + tx_disable_list.append(tx_disable_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0xC0 != 0) + else: + return None + return tx_disable_list + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + lpmode = False + attr_path = self.__sfp_lpmode_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 0): + lpmode = True + + return lpmode + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + if self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self._read_eeprom_specific_bytes((offset + QSFP_CONTROL_OFFSET), QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + return ('On' == dom_control_data['data']['PowerOverride']) + else: + return NotImplementedError + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + if not self.dom_supported: + return None + if self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_temp_supported: + dom_temperature_raw = self._read_eeprom_specific_bytes((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) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + return temp + else: + return None + else: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + sfpd_obj._calibration_type = 1 + + dom_temperature_raw = self._read_eeprom_specific_bytes((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) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + return temp + else: + return None + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + Returns: + An integer number of supply voltage in mV + """ + if not self.dom_supported: + return None + if self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_volt_supported: + dom_voltage_raw = self._read_eeprom_specific_bytes((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) + voltage = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + return voltage + else: + return None + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + sfpd_obj._calibration_type = self.calibration + + dom_voltage_raw = self._read_eeprom_specific_bytes((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) + voltage = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + return voltage + else: + return None + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + tx_bias_list = [] + if self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((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) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Bias']['value'])) + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + sfpd_obj._calibration_type = self.calibration + + if self.dom_supported: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_MON_OFFSET), SFP_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) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXBias']['value'])) + else: + return None + else: + return None + + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + rx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((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) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value'])) + else: + return None + else: + return None + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_MON_OFFSET), SFP_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) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RXPower']['value'])) + else: + return None + else: + return None + + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + tx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_tx_power_supported: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((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) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value'])) + else: + return None + else: + return None + else: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_MON_OFFSET), SFP_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) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXPower']['value'])) + else: + return None + else: + return None + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + try: + reg_file = open(self.__sfp_reset_attr, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 seconds to allow it to settle + time.sleep(2) + + # Flip the value back write back to the register to take port out of reset + try: + reg_file = open(self.__sfp_reset_attr, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + if self.sfp_type == SFP_TYPE: + if self.dom_tx_disable_supported: + handle = self._open_sdk() + if handle is None: + return False + + tx_disable_mask = 1 << MCIA_ADDR_TX_DISABLE_BIT + if tx_disable: + tx_disable_bit = tx_disable_mask + else: + tx_disable_bit = 0 + + return self._write_i2c_via_mcia(2, 0x51, MCIA_ADDR_TX_DISABLE, tx_disable_bit, tx_disable_mask) + else: + return False + elif self.sfp_type == QSFP_TYPE: + if self.dom_tx_disable_supported: + channel_mask = 0x0f + if tx_disable: + disable_flag = channel_mask + else: + disable_flag = 0 + + return self._write_i2c_via_mcia(0, 0x50, MCIA_ADDR_TX_CHANNEL_DISABLE, disable_flag, channel_mask) + else: + return False + else: + return NotImplementedError + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + Returns: + A boolean, True if successful, False if not + """ + sysfsfile_eeprom = None + try: + channel_state = self.get_tx_disable_channel() + tx_enable_mask = [0xe, 0xd, 0xb, 0x7] + tx_disable_mask = [0x1, 0x3, 0x7, 0xf] + tx_disable_ctl = channel_state | tx_disable_mask[ + channel] if disable else channel_state & tx_enable_mask[channel] + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + return True + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfsfile_eeprom = open( + self.port_to_eeprom_mapping[self.port_num], "r+b") + sysfsfile_eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + #print "self.index{}".format(self.index) + name = sfputil_helper.logical[self.index] or "Unknown" + return name + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/thermal.py new file mode 100644 index 000000000000..039067428321 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/thermal.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python + +############################################################################# +# Inventec d7264 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermal information +# +############################################################################# + +import os + +try: + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +THERMAL_PATH = "/sys/bus/i2c/devices/0-0066/" + +thermal_name_tup = ( + "FrontSide Temperature", + "FanBoard Temperature", + "NearASIC Temperature", + "Center(U10) Temperature", + "CPU Board Temperature", + "ASIC Temperature" +) + +class Thermal(ThermalBase): + """Platform-specific Thermal class""" + + def __init__(self, thermal_index): + self.index = thermal_index-1 + self.thermal_tmp = "temp{}_input".format(self.index) + + + 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 ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return thermal_name_tup[self.index] + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + attr_path = THERMAL_PATH + self.thermal_tmp + return os.path.isfile(attr_path) + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + status = False + if (self.get_temperature() > 0): + status = True + + return status + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temperature = 0.0 + attr_path = THERMAL_PATH + self.thermal_tmp + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + temperature = float(attr_rv) / 1000 + + return temperature + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/utils/inventec_d7054_util.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/utils/inventec_d7054_util.py new file mode 100755 index 000000000000..246893ba05b7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/utils/inventec_d7054_util.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Inventec, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[D7032]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +"with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +instantiate =[ +#'echo pca9548 0x71> /sys/bus/i2c/devices/i2c-0/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-2/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-3/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-4/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-5/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-6/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-7/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-0/i2c-8/new_device', +'echo inv_eeprom 0x53 > /sys/bus/i2c/devices/i2c-0/new_device'] +#'echo inv_psoc 0x66> /sys/bus/i2c/devices/i2c-0/new_device', +#'echo inv_cpld 0x55> /sys/bus/i2c/devices/i2c-0/new_device'] + +drivers =[ +'lpc_ich', +'i2c-i801', +'i2c-mux', +'i2c-mux-pca954x', +'i2c-dev', +'inv_eeprom', +'inv_platform', +'inv_psoc', +'inv_cpld', +'inv_pthread', +'swps'] + + + +def system_install(): + global FORCE + + #install drivers + for i in range(0,len(drivers)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #instantiate devices + for i in range(0,len(instantiate)): + #time.sleep(1) + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(10,18): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-2/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(18,26): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-3/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(26,34): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-4/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(34,42): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-5/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(42,50): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-6/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(50,58): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-7/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(58,64): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-8/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print " D7054 devices detected...." + return + +def uninstall(): + global FORCE + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0) + ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/Makefile new file mode 100755 index 000000000000..37cbc2f4e8be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/Makefile @@ -0,0 +1,7 @@ +obj-m += inv_cpld.o inv_psoc.o +obj-m += inv_platform.o +obj-m += inv_pthread.o +obj-m += inv_eeprom.o +obj-m += swps.o +swps-objs := inv_swps.o io_expander.o transceiver.o + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_cpld.c new file mode 100644 index 000000000000..42401d626672 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_cpld.c @@ -0,0 +1,470 @@ +/* + * 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 "I2CHostCommunication.h" + +#define USE_SMBUS 1 + +/* definition */ +#define CPLD_INFO_OFFSET 0x00 +#define CPLD_PSU_OFFSET 0x08 +#define CPLD_LED_OFFSET 0x0E +#define CPLD_LED_STATU_OFFSET 0x0D +#define CPLD_CTL_OFFSET 0x0C +#define CPLD_BIOSCS_OFFSET 0x04 + + +/* Each client has this additional data */ +struct cpld_data { + struct device *hwmon_dev; + struct mutex update_lock; +}; + +/*-----------------------------------------------------------------------*/ + +static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg[0].buf = msgbuf; + msg[0].len = 1; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + status = i2c_transfer(client->adapter, msg, 2); + + if(status == 2) + status = count; + + return status; +#endif +} + +static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count) +{ +#if USE_SMBUS + int i; + + for(i=0; iaddr; + msg.flags = 0; + + /* msg.buf is u8 and casts will mask the values */ + msg.buf = writebuf; + + msg.buf[i++] = offset; + memcpy(&msg.buf[i], buf, count); + msg.len = i + count; + + status = i2c_transfer(client->adapter, &msg, 1); + if (status == 1) + status = count; + + return status; +#endif +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t show_info(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[4]; + + memset(b, 0, 4); + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4); + mutex_unlock(&data->update_lock); + + if(status != 4) return sprintf(buf, "read cpld info fail\n"); + + status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/ + status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf); + status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf); + + return strlen(buf); +} + + +static ssize_t show_ctl(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[1]; + + mutex_lock(&data->update_lock); + + status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld ctl fail\n"); + + + status = sprintf (buf, "0x%X\n", b[0]); + + return strlen(buf); +} + +static ssize_t set_ctl(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1); + if(temp) byte |= (1<<0); + else byte &= ~(1<<0); + cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_bios_cs(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + //struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 b[1]; + + mutex_lock(&data->update_lock); + + status = cpld_i2c_read(client, b, CPLD_BIOSCS_OFFSET, 1); + + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld BIOS_CS fail\n"); + + + status = sprintf (buf, "0x%X\n", b[0] & 0x01); + + return strlen(buf); +} + +static ssize_t set_bios_cs(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + + u8 temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1); + if(temp) byte |= 0x01; + else byte &= ~(0x01); + cpld_i2c_write(client, &byte, CPLD_BIOSCS_OFFSET, 1); + mutex_unlock(&data->update_lock); + + return count; +} + + +static char* led_str[] = { + "OFF", //000 + "0.5 Hz", //001 + "1 Hz", //010 + "2 Hz", //011 + "4 Hz", //100 + "NA", //101 + "NA", //110 + "ON", //111 +}; + +static ssize_t show_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + mutex_unlock(&data->update_lock); + + if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d: %s\n", byte, led_str[byte]); + + return strlen(buf); +} + +static ssize_t set_led(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 16); + u8 byte; + int shift = (attr->index == 0)?3:0; + + temp &= 0x7; + //validate temp value: 0,1,2,3,7, TBD + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1); + byte &= ~(0x7<update_lock); + + return count; +} + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu0 | psu1 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 1)?0:3; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + + +static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0); +static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0); + +static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0); +static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1); + +static SENSOR_DEVICE_ATTR(bios_cs, S_IWUSR|S_IRUGO, show_bios_cs, set_bios_cs, 0); + +static struct attribute *cpld_attributes[] = { + //info + &sensor_dev_attr_info.dev_attr.attr, + &sensor_dev_attr_ctl.dev_attr.attr, + + &sensor_dev_attr_grn_led.dev_attr.attr, + &sensor_dev_attr_red_led.dev_attr.attr, + + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + &sensor_dev_attr_bios_cs.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld_group = { + .attrs = cpld_attributes, +}; + +static struct attribute *cpld2_attributes[] = { + //info + &sensor_dev_attr_info.dev_attr.attr, + + NULL +}; + +static const struct attribute_group cpld2_group = { + .attrs = cpld2_attributes, +}; + + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int +cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + +// printk("+%s \n", __func__); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + if(id->driver_data==1) // CPLD2 + status = sysfs_create_group(&client->dev.kobj, &cpld2_group); + else // default CPLD1 + status = sysfs_create_group(&client->dev.kobj, &cpld_group); + + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &cpld_group); +exit_free: + i2c_set_clientdata(client, NULL); + kfree(data); + return status; +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cpld_group); + i2c_set_clientdata(client, NULL); + kfree(data); + return 0; +} + +static const struct i2c_device_id cpld_ids[] = { + { "inv_cpld" , 0, }, + { "inv_cpld2", 1, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, cpld_ids); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "inv_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_ids, +}; + +/*-----------------------------------------------------------------------*/ + +/* module glue */ + +static int __init inv_cpld_init(void) +{ + return i2c_add_driver(&cpld_driver); +} + +static void __exit inv_cpld_exit(void) +{ + i2c_del_driver(&cpld_driver); +} + +MODULE_AUTHOR("eddie.lan "); +MODULE_DESCRIPTION("inv cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_cpld_init); +module_exit(inv_cpld_exit); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_eeprom.c new file mode 100644 index 000000000000..3d13f3b04719 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_eeprom.c @@ -0,0 +1,181 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void inv_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } + +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + inv_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute inv_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = inv_eeprom_read, +}; + +static int inv_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int inv_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id inv_eeprom_id[] = { + { "inv_eeprom", 0 }, + { } +}; + +static struct i2c_driver inv_eeprom_driver = { + .driver = { + .name = "inv_eeprom", + }, + .probe = inv_eeprom_probe, + .remove = inv_eeprom_remove, + .id_table = inv_eeprom_id, +}; + +module_i2c_driver(inv_eeprom_driver); + +MODULE_AUTHOR("Inventec"); +MODULE_DESCRIPTION("Inventec D7054 Mother Board EEPROM driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_platform.c new file mode 100644 index 000000000000..753f8cd3407d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_platform.c @@ -0,0 +1,239 @@ +#include +//#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include + +//#include +//#define IO_EXPAND_BASE 64 +//#define IO_EXPAND_NGPIO 16 + +struct inv_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +#define bus_id(id) (id) +static struct pca954x_platform_mode mux_modes_0[] = { + {.adap_id = bus_id(2),}, {.adap_id = bus_id(3),}, + {.adap_id = bus_id(4),}, {.adap_id = bus_id(5),}, + {.adap_id = bus_id(6),}, {.adap_id = bus_id(7),}, + {.adap_id = bus_id(8),}, {.adap_id = bus_id(9),}, +}; +static struct pca954x_platform_mode mux_modes_0_0[] = { + {.adap_id = bus_id(10),}, {.adap_id = bus_id(11),}, + {.adap_id = bus_id(12),}, {.adap_id = bus_id(13),}, + {.adap_id = bus_id(14),}, {.adap_id = bus_id(15),}, + {.adap_id = bus_id(16),}, {.adap_id = bus_id(17),}, +}; + +static struct pca954x_platform_mode mux_modes_0_1[] = { + {.adap_id = bus_id(18),}, {.adap_id = bus_id(19),}, + {.adap_id = bus_id(20),}, {.adap_id = bus_id(21),}, + {.adap_id = bus_id(22),}, {.adap_id = bus_id(23),}, + {.adap_id = bus_id(24),}, {.adap_id = bus_id(25),}, +}; + +static struct pca954x_platform_mode mux_modes_0_2[] = { + {.adap_id = bus_id(26),}, {.adap_id = bus_id(27),}, + {.adap_id = bus_id(28),}, {.adap_id = bus_id(29),}, + {.adap_id = bus_id(30),}, {.adap_id = bus_id(31),}, + {.adap_id = bus_id(32),}, {.adap_id = bus_id(33),}, +}; + +static struct pca954x_platform_mode mux_modes_0_3[] = { + {.adap_id = bus_id(34),}, {.adap_id = bus_id(35),}, + {.adap_id = bus_id(36),}, {.adap_id = bus_id(37),}, + {.adap_id = bus_id(38),}, {.adap_id = bus_id(39),}, + {.adap_id = bus_id(40),}, {.adap_id = bus_id(41),}, +}; + +static struct pca954x_platform_mode mux_modes_0_4[] = { + {.adap_id = bus_id(42),}, {.adap_id = bus_id(43),}, + {.adap_id = bus_id(44),}, {.adap_id = bus_id(45),}, + {.adap_id = bus_id(46),}, {.adap_id = bus_id(47),}, + {.adap_id = bus_id(48),}, {.adap_id = bus_id(49),}, +}; + +static struct pca954x_platform_mode mux_modes_0_5[] = { + {.adap_id = bus_id(50),}, {.adap_id = bus_id(51),}, + {.adap_id = bus_id(52),}, {.adap_id = bus_id(53),}, + {.adap_id = bus_id(54),}, {.adap_id = bus_id(55),}, + {.adap_id = bus_id(56),}, {.adap_id = bus_id(57),}, +}; + +static struct pca954x_platform_mode mux_modes_0_6[] = { + {.adap_id = bus_id(58),}, {.adap_id = bus_id(59),}, + {.adap_id = bus_id(60),}, {.adap_id = bus_id(61),}, + {.adap_id = bus_id(62),}, {.adap_id = bus_id(63),}, + {.adap_id = bus_id(64),}, {.adap_id = bus_id(65),}, +}; + +static struct pca954x_platform_mode mux_modes_0_7[] = { + {.adap_id = bus_id(66),}, {.adap_id = bus_id(67),}, + {.adap_id = bus_id(68),}, {.adap_id = bus_id(69),}, + {.adap_id = bus_id(70),}, {.adap_id = bus_id(71),}, + {.adap_id = bus_id(72),}, {.adap_id = bus_id(73),}, +}; + +//no i2c device driver attach to mux 7 + + +static struct pca954x_platform_data mux_data_0 = { + .modes = mux_modes_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_0 = { + .modes = mux_modes_0_0, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_1 = { + .modes = mux_modes_0_1, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_2 = { + .modes = mux_modes_0_2, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_3 = { + .modes = mux_modes_0_3, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_4 = { + .modes = mux_modes_0_4, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_5 = { + .modes = mux_modes_0_5, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_6 = { + .modes = mux_modes_0_6, + .num_modes = 8, +}; +static struct pca954x_platform_data mux_data_0_7 = { + .modes = mux_modes_0_7, + .num_modes = 8, +}; + +static struct i2c_board_info i2c_device_info0[] __initdata = { +// {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc + {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld + {"inv_cpld2", 0, 0x77, 0, 0, 0},//cpld2 + {"pca9548", 0, 0x70, &mux_data_0, 0, 0}, +}; + +static struct i2c_board_info i2c_device_info2[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, +}; +static struct i2c_board_info i2c_device_info3[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, +}; +static struct i2c_board_info i2c_device_info4[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, +}; +static struct i2c_board_info i2c_device_info5[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, +}; +static struct i2c_board_info i2c_device_info6[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0}, +}; +static struct i2c_board_info i2c_device_info7[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0}, +}; +static struct i2c_board_info i2c_device_info8[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0}, +}; +static struct i2c_board_info i2c_device_info9[] __initdata = { + {"pca9548", 0, 0x72, &mux_data_0_7, 0, 0}, +}; + + +static struct inv_i2c_board_info i2cdev_list[] = { + {0, ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //smbus 0 + + {bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux 0 + {bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux 1 + {bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux 2 + {bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux 3 + {bus_id(6), ARRAY_SIZE(i2c_device_info6), i2c_device_info6 }, //mux 4 + {bus_id(7), ARRAY_SIZE(i2c_device_info7), i2c_device_info7 }, //mux 5 + {bus_id(8), ARRAY_SIZE(i2c_device_info8), i2c_device_info8 }, //mux 6 + {bus_id(9), ARRAY_SIZE(i2c_device_info9), i2c_device_info9 }, //mux 7 + +}; + +///////////////////////////////////////////////////////////////////////////////////////// +#if 0 +static struct i2c_gpio_platform_data i2c_gpio_platdata0 = { + .scl_pin = 58, + .sda_pin = 75, + + .udelay = 5, //5:100kHz + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, + .scl_is_output_only = 0 +}; + +static struct platform_device device_i2c_gpio0 = { + .name = "i2c-gpio", + .id = 1, // adapter number + .dev.platform_data = &i2c_gpio_platdata0, +}; +#endif +static int __init inv_platform_init(void) +{ + struct i2c_adapter *adap = NULL; + struct i2c_client *e = NULL; + int ret = 0; + int i,j,k; + + printk("%s \n", __func__); + +#if 0 + //use i2c-gpio + //register i2c gpio + //config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 gpio69=32*2+8*0+5 + outl( inl(0x533) | (1<<2), 0x533); + outl( inl(0x541) | (1<<3), 0x541); + outl( inl(0x540) | (1<<5), 0x540); //RST_I2C_MUX_N (GPIO69) + outl( inl(0x500) | (1<<7), 0x500); //SYS_RDY_N (GPIO7) + outl( inl(0x501) | (1<<7), 0x501); //BMC_HEART_BEAT (GPIO15) + outl( inl(0x503) | (1<<2)|(1<<3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27) + + ret = platform_device_register(&device_i2c_gpio0); + if (ret) { + printk(KERN_ERR "i2c-gpio: device_i2c_gpio0 register fail %d\n", ret); + } +#endif + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//================================= +#include +#include +#include +#include + +#define IPMI_MAX_INTF (4) +#define NETFN_OEM 0x30 +#define CMD_GETDATA 0x31 +#define CMD_SETDATA 0x32 +#define FAN_NUM 4 +#define PSU_NUM 2 + +#define PSU1 0x5800 +#define PSU2 0x5900 +#define BMC_PMBusNumber 3 +#define PMBus_Vender 0x99 +#define PMBus_Serial 0x9E +#define PMBus_Temp2 0x8E +#define PMBus_Version 0x9B +#define MaxLeng_Result 0x20 + +#define MAX_IPMI_RECV_LENGTH 0xff + +static long pmbus_reg2data_linear(int data, int linear16); +struct ipmi_result{ + char result[MAX_IPMI_RECV_LENGTH]; + int result_length; +}; + +DEFINE_MUTEX(ipmi_mutex); +DEFINE_MUTEX(ipmi2_mutex); +static struct ipmi_result ipmiresult; +static struct device *hwmon_dev; +static ipmi_user_t ipmi_mh_user = NULL; +static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data); +static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,}; + +static atomic_t dummy_count = ATOMIC_INIT(0); +static void dummy_smi_free(struct ipmi_smi_msg *msg) +{ + atomic_dec(&dummy_count); +} +static void dummy_recv_free(struct ipmi_recv_msg *msg) +{ + atomic_dec(&dummy_count); +} +static struct ipmi_smi_msg halt_smi_msg = { + .done = dummy_smi_free +}; +static struct ipmi_recv_msg halt_recv_msg = { + .done = dummy_recv_free +}; + +struct __attribute__ ((__packed__)) psoc_psu_layout { + u16 psu1_iin; + u16 psu2_iin; + u16 psu1_iout; + u16 psu2_iout; + + u16 psu1_pin; + u16 psu2_pin; + u16 psu1_pout; + u16 psu2_pout; + + u16 psu1_vin; + u16 psu2_vin; + u16 psu1_vout; + u16 psu2_vout; +}; + +struct __attribute__ ((__packed__)) psoc_layout { + u8 ctl; //offset: 0 + u16 switch_temp; //offset: 1 + u8 reserve0; //offset: 3 + + u8 fw_upgrade; //offset: 4 + + //i2c bridge + u8 i2c_st; //offset: 5 + u8 i2c_ctl; //offset: 6 + u8 i2c_addr; //offset: 7 + u8 i2c_data[0x20]; //offset: 8 + + //gpo + u8 led_ctl; //offset: 28 + + u8 gpio; //offset: 29 + + //pwm duty + u8 pwm[FAN_NUM]; //offset: 2a + u8 pwm_psu[PSU_NUM]; //offset: 2e + + //fan rpm + u16 fan[FAN_NUM*2]; //offset: 30 + + u8 reserve1[4]; //offset: 40 + + //gpi + u8 gpi_fan; //offset: 44 + + //psu state + u8 psu_state; //offset: 45 + + //temperature + u16 temp[5]; //offset: 46 + u16 temp_psu[PSU_NUM]; //offset: 50 + + //version + u8 version[2]; //offset: 54 + + u8 reserve2[4]; //offset: 56 + struct psoc_psu_layout psu_info; //offset: 5a +}; + +/* definition */ +/* definition */ +#define PSOC_OFF(m) offsetof(struct psoc_layout, m) +#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m) + +#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp) +#define PWM_OFFSET PSOC_OFF(pwm) +#define THERMAL_OFFSET PSOC_OFF(temp) +#define RPM_OFFSET PSOC_OFF(fan) +#define DIAG_FLAG_OFFSET PSOC_OFF(ctl) +#define FAN_LED_OFFSET PSOC_OFF(led_ctl) +#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan) +#define PSOC_PSU_OFFSET PSOC_OFF(psu_state) +#define VERSION_OFFSET PSOC_OFF(version) +#define PSU_INFO_OFFSET PSOC_OFF(psu_info) + + +static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data) +{ + struct ipmi_result *msg_result = recv_msg->user_msg_data; + + if(recv_msg->msg.data[0]==0 && recv_msg->msg.data_len>0) { + msg_result->result_length=recv_msg->msg.data_len-1; + memcpy(msg_result->result, &recv_msg->msg.data[1], recv_msg->msg.data_len-1); + } + ipmi_free_recv_msg(recv_msg); + mutex_unlock(&ipmi_mutex); + + return; +} + +int start_ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length) +{ + int rv=0,i; + int timeout; + + //wait previous command finish at least 50msec + timeout=50; + while((mutex_is_locked(&ipmi_mutex) == 1 || (mutex_is_locked(&ipmi2_mutex) == 1)) && (--timeout)>0) { usleep_range(1000,1010); } + if(timeout==0) { return -1; } + mutex_lock(&ipmi_mutex); + mutex_lock(&ipmi2_mutex); + + if(ipmi_mh_user == NULL) { + for (i=0,rv=1; i0) { usleep_range(1000,1100);} + if(timeout==0) { + mutex_unlock(&ipmi2_mutex); + return -1; + } + else { + *result_length=ipmiresult.result_length; + memcpy(result,ipmiresult.result,*result_length); + mutex_unlock(&ipmi2_mutex); + return 0; + } + } + return 0; +} +EXPORT_SYMBOL(start_ipmi_command); + +static ssize_t psoc_ipmi_read(u8 *buf, u8 offset, size_t count) +{ + uint8_t data[2]; + int result_len=0; + int rv; + + data[0] = offset; + data[1] = count; + + rv=start_ipmi_command(NETFN_OEM, CMD_GETDATA,data,2, buf, &result_len); + + return result_len; +} + +static ssize_t psoc_ipmi_write(char *buf, unsigned offset, size_t count) +{ + uint8_t data[count+1],result[1]; + int result_len; + + data[0] = offset; + memcpy(&data[1],buf,count); + + start_ipmi_command(NETFN_OEM, CMD_SETDATA,data,count+1, result, &result_len); + return count; +} + + +static u16 psoc_read16(u8 offset) +{ + u16 value = 0; + u8 buf[]={0,0}; + + if(psoc_ipmi_read(buf, offset, 2) == 2) + value = (buf[0]<<8 | buf[1]<<0); + + return value; +} + +static u8 psoc_read8(u8 offset) +{ + u8 value = 0; + u8 buf = 0; + + if(psoc_ipmi_read(&buf, offset, 1) == 1) + value = buf; + + return value; +} + +/* +CPLD report the PSU0 status +000 = PSU normal operation +100 = PSU fault +010 = PSU unpowered +111 = PSU not installed + +7 6 | 5 4 3 | 2 1 0 +---------------------- + | psu1 | psu0 +*/ +static char* psu_str[] = { + "normal", //000 + "NA", //001 + "unpowered", //010 + "NA", //011 + "fault", //100 + "NA", //101 + "NA", //110 + "not installed", //111 +}; + +static ssize_t show_psu_st(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 byte=0; + int shift = (attr->index == 0)?3:0; + + status = psoc_ipmi_read(&byte, PSOC_PSU_OFFSET, 1); + + byte = (byte >> shift) & 0x7; + + status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]); + + return strlen(buf); +} + +static ssize_t show_ipmi_pmbus(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + uint8_t data[4],result[MaxLeng_Result]; + int result_len=0; + + data[0] = BMC_PMBusNumber; + data[1] = (attr->index & 0xFF00 ) >>7; + data[3] = attr->index & 0xff; + if(data[3]==PMBus_Temp2) + {data[2]=2;} + else + {data[2]=MaxLeng_Result;} + + if(start_ipmi_command(0x06, 0x52,data,4, result, &result_len)==0) + { + if(data[3]==PMBus_Temp2) + { + return sprintf(buf, "%ld \n", pmbus_reg2data_linear(result[0] | (result[1]<<8), 0 )); + } + result[result[0]+1]='\0'; + return sprintf(buf, "%s\n",&result[1] ); + } + else + { + return 0; + } +} + +static ssize_t show_thermal(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index * 2 + THERMAL_OFFSET; + + status = psoc_read16(offset); + + return sprintf(buf, "%d\n", + (s8)(status>>8) * 1000 ); +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index + PWM_OFFSET; + + status = psoc_read8(offset); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t set_pwm(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index + PWM_OFFSET; + + u8 pwm = simple_strtol(buf, NULL, 10); + if(pwm > 255) pwm = 255; + + psoc_ipmi_write(&pwm, offset, 1); + + return count; +} + + +static ssize_t show_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index*2 + RPM_OFFSET; + + status = psoc_read16(offset); + + return sprintf(buf, "%d\n", + status); +} + +static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + u16 temp = 0; + + status = psoc_ipmi_read((u8*)&temp, SWITCH_TMP_OFFSET, 2); + + status = sprintf (buf, "%d\n", (s8)(temp>>8) * 1000 ); + + return strlen(buf); +} + +static ssize_t set_switch_tmp(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + long temp = simple_strtol(buf, NULL, 10); + u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ; + + //printk("set_switch_tmp temp=%d, temp2=0x%x (%x,%x)\n", temp, temp2, ( ( (temp/1000) <<8 ) & 0xFF00 ), (( (temp%1000) / 10 ) & 0xFF)); + psoc_ipmi_write((u8*)&temp2, SWITCH_TMP_OFFSET, 2); + + + return count; +} + +static ssize_t show_diag(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + u8 diag_flag = 0; + + status = psoc_ipmi_read((u8*)&diag_flag, DIAG_FLAG_OFFSET, 1); + + status = sprintf (buf, "%d\n", ((diag_flag & 0x80)?1:0)); + + return strlen(buf); +} + +static ssize_t set_diag(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + u8 value = 0; + u8 diag = simple_strtol(buf, NULL, 10); + + diag = diag?1:0; + + psoc_ipmi_read((u8*)&value, DIAG_FLAG_OFFSET, 1); + if(diag) value |= (1<<7); + else value &= ~(1<<7); + psoc_ipmi_write((u8*)&value, DIAG_FLAG_OFFSET, 1); + + return count; +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + + status = psoc_read16(VERSION_OFFSET); + + return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) ); +} + +static ssize_t show_name(struct device *dev, struct device_attribute *da, + char *buf) +{ + return sprintf (buf, "inv_psoc\n"); +} + + +static ssize_t show_fan_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 bit = attr->index; + + status = psoc_read8(FAN_LED_OFFSET); + + return sprintf(buf, "%d\n", + (status & (1<index; + u8 led_state = 0; + + u8 v = simple_strtol(buf, NULL, 10); + + led_state = psoc_read8(FAN_LED_OFFSET); + if(v) led_state |= (1<index; + + status = psoc_read8(offset); + + return sprintf(buf, "0x%02X\n", status ); +} + +static long pmbus_reg2data_linear(int data, int linear16) +{ + s16 exponent; + s32 mantissa; + long val; + + if (linear16) { /* LINEAR16 */ + exponent = -9; + mantissa = (u16) data; + } else { /* LINEAR11 */ + exponent = ((s16)data) >> 11; + exponent = ((s16)( data & 0xF800) ) >> 11; + mantissa = ((s32)((data & 0x7ff) << 5)) >> 5; + } + + //printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa); + val = mantissa; + + /* scale result to micro-units for power sensors */ + val = val * 1000L; + + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da, + char *buf) +{ + u16 status=0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 offset = attr->index + PSU_INFO_OFFSET; + + status = psoc_read16(offset); + + return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, strstr(attr->dev_attr.attr.name, "vout")? 1:0 )); +} + + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4); +static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5); +static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 6); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4); +static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5); + +static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu_st, 0, 0); +static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 1); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7); +static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8); +static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9); + +static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); +static SENSOR_DEVICE_ATTR(temp6_input, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0); + +static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0); +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0); +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); + +static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0); +static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1); +static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2); +static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3); +static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4); +static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5); +static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6); +static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7); + +static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET); +static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout)); + + +static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); +static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout)); + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin)); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin)); +static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin)); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin)); +static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin)); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin)); + +//IPMI +static SENSOR_DEVICE_ATTR(thermal2_psu1, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(psoc_psu1_vender, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Vender); +static SENSOR_DEVICE_ATTR(psoc_psu1_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Serial); +static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Version); + +static SENSOR_DEVICE_ATTR(thermal2_psu2, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Temp2); +static SENSOR_DEVICE_ATTR(psoc_psu2_vender, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Vender); +static SENSOR_DEVICE_ATTR(psoc_psu2_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Serial); +static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Version); + + +static struct attribute *psoc_attributes[] = { + //thermal + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + + &sensor_dev_attr_thermal_psu1.dev_attr.attr, + &sensor_dev_attr_thermal_psu2.dev_attr.attr, + + + //pwm + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm_psu1.dev_attr.attr, + &sensor_dev_attr_pwm_psu2.dev_attr.attr, + + //rpm + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, + + &sensor_dev_attr_rpm_psu1.dev_attr.attr, + &sensor_dev_attr_rpm_psu2.dev_attr.attr, + + //switch temperature + &sensor_dev_attr_switch_tmp.dev_attr.attr, + &sensor_dev_attr_temp6_input.dev_attr.attr, + //diag flag + &sensor_dev_attr_diag.dev_attr.attr, + + //version + &sensor_dev_attr_version.dev_attr.attr, + + //fan led + &sensor_dev_attr_fan_led_grn1.dev_attr.attr, + &sensor_dev_attr_fan_led_grn2.dev_attr.attr, + &sensor_dev_attr_fan_led_grn3.dev_attr.attr, + &sensor_dev_attr_fan_led_grn4.dev_attr.attr, + &sensor_dev_attr_fan_led_red1.dev_attr.attr, + &sensor_dev_attr_fan_led_red2.dev_attr.attr, + &sensor_dev_attr_fan_led_red3.dev_attr.attr, + &sensor_dev_attr_fan_led_red4.dev_attr.attr, + + //fan GPI + &sensor_dev_attr_fan_gpi.dev_attr.attr, + &sensor_dev_attr_psu0.dev_attr.attr, + &sensor_dev_attr_psu1.dev_attr.attr, + + + //psu_psoc + &sensor_dev_attr_psoc_psu1_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_pout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_iout.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pin.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_pout.dev_attr.attr, + + // Add new fields which matching standard + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_curr1_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_power1_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + + //ipmi_i2c_command + &sensor_dev_attr_thermal2_psu1.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_vender.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_serial.dev_attr.attr, + &sensor_dev_attr_psoc_psu1_version.dev_attr.attr, + + &sensor_dev_attr_thermal2_psu2.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_vender.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_serial.dev_attr.attr, + &sensor_dev_attr_psoc_psu2_version.dev_attr.attr, + + &sensor_dev_attr_name.dev_attr.attr, + + NULL +}; + +static const struct attribute_group psoc_group = { + .attrs = psoc_attributes, +}; + +static int __init inv_psoc_init(void) +{ + int ret; + + printk("+%s\n", __func__); + + hwmon_dev = hwmon_device_register(NULL); + if (IS_ERR(hwmon_dev)) { + goto fail_hwmon_device_register; + } + + ret = sysfs_create_group(&hwmon_dev->kobj, &psoc_group); + if (ret) { + goto fail_create_group_hwmon; + } + + printk(" Enable IPMI PSoC protocol.\n"); + return ret; + +fail_create_group_hwmon: + hwmon_device_unregister(hwmon_dev); +fail_hwmon_device_register: + return -ENOMEM; +} + +static void __exit inv_psoc_exit(void) +{ + sysfs_remove_group(&hwmon_dev->kobj, &psoc_group); + + if(ipmi_mh_user!=NULL) {ipmi_destroy_user(ipmi_mh_user);} + if(hwmon_dev != NULL) hwmon_device_unregister(hwmon_dev); +} + +MODULE_AUTHOR("Ting.Jack "); +MODULE_DESCRIPTION("inv psoc driver"); +MODULE_LICENSE("GPL"); + +module_init(inv_psoc_init); +module_exit(inv_psoc_exit); + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_pthread.c new file mode 100644 index 000000000000..a45db7423f25 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_pthread.c @@ -0,0 +1,1303 @@ +/***************************** + Sequoia platform +******************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INV_PTHREAD_KERNEL_MODULE + +#define SHOW_ATTR_WARNING ("N/A") +#define SHOW_ATTR_NOTPRINT ("Not Available") +#define SHOW_ATTR_NOTSUPPORT ("Not Support") + +#define INV_HWMID_MAX (10) +#define INV_HWMID_INIT (-1) + +/*access userspace data to kernel space*/ +#define ACC_R (0) +#define ACC_W (1) + +#define TINY_BUF_SIZE (8) +#define MAX_PATH_SIZE (64) +#define MIN_ACC_SIZE (32) +#define MAX_ACC_SIZE (256) + +/* + * LED definitions + */ +#define STATUS_LED_MODE_AUTO 0 +#define STATUS_LED_MODE_DIAG 1 +#define STATUS_LED_MODE_MANU 2 + +#define STATUS_LED_GRN0 10 // 0 - 000: off +#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz +#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz +#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz +#define STATUS_LED_GRN7 17 // 7 - 111: on +#define STATUS_LED_RED0 20 // 0 - 000: off +#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz +#define STATUS_LED_RED2 22 // 2 - 010: 1 hz +#define STATUS_LED_RED3 23 // 3 - 011: 2 hz +#define STATUS_LED_RED7 27 // 7 - 111: on +#define STATUS_LED_INVALID 0 // Invalid + +ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2); +ssize_t status_led_grn(const char *freq); +ssize_t status_led_red(const char *freq); +ssize_t status_led_diag_mode_enable(void); +ssize_t status_led_diag_mode_disable(void); +int status_led_check_color(void); +int status_led_check_diag_mode(void); + +#if 1 +/* For timestamps in SYSFS_LOG */ +#define SYSFS_LOG printk +#else +//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args) +#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args) +#endif + + +/* inventec_class *********************************/ +static struct kobject *status_kobj; +static struct kset *status_kset; + + +static struct mutex rw_lock; + +static int hwm_psoc = INV_HWMID_INIT; +static int hwm_cpld = INV_HWMID_INIT; +static int hwm_cpld2 = INV_HWMID_INIT; + +int get_hwm_psoc(void) +{ + return hwm_psoc; +} + +int get_hwm_cpld(void) +{ + return hwm_cpld; +} + +static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + char *mark = NULL; + ssize_t vfs_ret = 0; + + if (mode == ACC_R) { + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_read(fp, buf, len, &pos); + + mark = strpbrk(buf, "\n"); + if (mark) + *mark = '\0'; + + filp_close(fp, NULL); + set_fs(fs); + } else if (mode == ACC_W) { + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)) + return -ENODEV; + + fs = get_fs(); + set_fs(KERNEL_DS); + + vfs_ret = vfs_write(fp, buf, len, &pos); + filp_close(fp, NULL); + set_fs(fs); + } + + return vfs_ret; +} + +int inventec_strtol(const char *sbufp, char **endp, unsigned int base) +{ + char *endptr; + int value = simple_strtol(sbufp, &endptr, base); + if (value == 0 && sbufp == endptr) { + *endp = NULL; + return value; + } + *endp = (char*)1; + return value; +} + +int inventec_singlechar_to_int(const char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + else + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + else + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } + return -1; +} + +int inventec_store_input(char *inputp, int count) +{ + int i = 0; + while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) { + i++; + } + inputp[i] = '\0'; + return strlen(inputp); +} + +#if 0 +/* + * Time stamps for kernel log on yocto + */ +#include + +void SYSFS_LOG(char *fmt, ...) +{ + char buf[80], ts[32]; + va_list args; + int hlen; + + inventec_tmstmp(&ts[0]); + hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line + + va_start(args, fmt); + vsprintf(&buf[hlen-1], fmt, args); + va_end(args); + printk(KERN_WARNING "[p_thread] %s\n", buf); +} +#endif + +ssize_t +inventec_show_attr(char *buf_p, const char *invdevp) +{ + int inv_len = MAX_ACC_SIZE; /* INV driver return max length */ + char tmp_buf[MAX_ACC_SIZE]; + char *str_negative = "-", *mark = NULL; + + /* [Step2] Get data by uaccess */ + memset(tmp_buf, 0, sizeof(tmp_buf)); + mutex_lock(&rw_lock); + if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + mutex_unlock(&rw_lock); + + /* [Step3] Check return value + * - Ex: When transceiver not plugged + * => SWPS return error code "-202" + * => Pic8 need return "NA" (assume) + */ + if (strcspn(tmp_buf, str_negative) == 0) { + /* error case: "-202" */ + return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING); + } + + /* OK case:*/ + mark = strpbrk(tmp_buf, "\n"); + if (mark) { *mark = '\0'; } + + return sprintf(buf_p, "%s\n", tmp_buf); +} + +ssize_t +inventec_store_attr(const char *buf_p, size_t count, const char *invdevp) +{ + ssize_t ret = 0; + + /* [Step2] Get data by uaccess */ + mutex_lock(&rw_lock); + if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) { + /* u_access fail */ + mutex_unlock(&rw_lock); + return -EINVAL; + } + mutex_unlock(&rw_lock); + + /* OK case:*/ + return ret; +} + +int sysfs_detect_hwmon_index(void) +{ + char hwmon_buf[MAX_ACC_SIZE]; + char hwmon_path[MAX_PATH_SIZE]; + int hwid = 0; + + for (hwid = 0; + hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT); + hwid++) { + memset(hwmon_buf, 0, sizeof(hwmon_buf)); + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/name", hwid); + + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) { + hwm_psoc = hwid; + } + else + if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) { + hwm_psoc = hwid; + } + + sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/device/name", hwid); + inventec_show_attr(hwmon_buf, hwmon_path); + if (strncmp(hwmon_buf, "inv_cpld2", 9) == 0) { + hwm_cpld2 = hwid; + } + else + if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) { + hwm_cpld = hwid; + } + } + if (hwid >= INV_HWMID_MAX) { + printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return -1; + } + printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld); + return 0; +} + +static int __init +inventec_class_init(void) +{ + mutex_init(&rw_lock); + +#ifdef INV_PTHREAD_KERNEL_MODULE + if (sysfs_detect_hwmon_index() < 0) { + return -1; + } +#endif + + printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__); + + return 0; +} + +static void __exit +inventec_class_exit(void) +{ + printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__); +} + +/* fan device *************************************/ +#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/fan_gpi" +#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/fan1_input" +#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/fan2_input" +#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/fan3_input" +#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/fan4_input" +#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/fan5_input" +#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/fan6_input" +#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/fan7_input" +#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/fan8_input" + +static char fan_dev_path_state[MAX_PATH_SIZE]; +static char fan_dev_path_fan1_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan2_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan3_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan4_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan5_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan6_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan7_input[MAX_PATH_SIZE]; +static char fan_dev_path_fan8_input[MAX_PATH_SIZE]; + +void sysfs_fan_path_init(void) +{ + sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc()); + sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc()); + sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc()); +} + +#define FAN_STATE_NORMAL "normal" +#define FAN_STATE_FAULTY "faulty" +#define FAN_STATE_UNINSTALLED "uninstalled" +#define FAN_STATE_UNKNOW "unknown state" +#define FAN_STATE_INVALID "Invalid state value" +#define FAN_STATE_READ_ERROR "state read error" + +#define FAN_LOG_UNINSTALLED "removed" +#define FAN_LOG_NORMAL "inserted" + +//#define FAN_STATE_BIT_NORMAL 0 +#define FAN_STATE_BIT_FAULTY 0 +#define FAN_STATE_BIT_UNINSTALLED 1 +#define FAN_STATE_BIT_UNKNOW 2 +#define FAN_STATE_BIT_INVALID 3 +#define FAN_STATE_BIT_READ_ERROR 4 + +static struct fans_tbl_s { + char *fan_name; + char *fan_front; + char *fan_rear; + unsigned int fan_state; +} fans_tbl[] = { + {"fan1", fan_dev_path_fan1_input, + fan_dev_path_fan2_input, 0}, + {"fan2", fan_dev_path_fan3_input, + fan_dev_path_fan4_input, 0}, + {"fan3", fan_dev_path_fan5_input, + fan_dev_path_fan6_input, 0}, + {"fan4", fan_dev_path_fan7_input, + fan_dev_path_fan8_input, 0}, +}; +#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) ) + +#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0) + { + printk(KERN_ERR "[p_thread] All fans failed.\n"); + printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown); + } + cd_shutdown -= 1; + } + return ret; +} + +/* End of faninfo_device */ + +static int __init +fan_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_fan_path_init(); +#endif + return 0; +} + + +static void __exit +fan_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove fan module.\n"); +} + +/* psu device *************************************/ +static unsigned int psu_voltin = 0; +#define PSU_VOLTIN_ACDC (70000) + +/* + * normal/unpower/uninstall/fault are PSU states output from driver level + * checkpsu/error are defined by sysfs + */ +#define PSU_STATE_VAL_NORMAL (0) +#define PSU_STATE_VAL_UNPOWER (2) +#define PSU_STATE_VAL_FAULT (4) +#define PSU_STATE_VAL_UNINSTALL (7) +#define PSU_STATE_VAL_CHECKPSU (8) +#define PSU_STATE_VAL_ERROR (9) + +#define PSU_STATE_NORMAL ("0 : normal") +#define PSU_STATE_UNPOWER ("2 : unpowered") +#define PSU_STATE_FAULT ("4 : fault") +#define PSU_STATE_UNINSTALL ("7 : not installed") +#define PSU_STATE_CHECKPSU ("8 : check psu") +#define PSU_STATE_ERROR ("9 : state error") + +#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL)) +#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER)) +#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT)) +#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL)) +#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU)) + +typedef struct { + char *inv_dev_attrp; + char *inv_dev_pathp; +} psu_dev_t; + +typedef struct { + const char *psu_name; + int psu_major; + dev_t psu_devt; + struct device *psu_dev_p; + psu_dev_t *psu_dev_namep; + int psu_dev_total; + char *psu_inv_pathp; + void *psu_tracking; + char *psu_currentin; + char *psu_currentout; + char *psu_powerin; + char *psu_powerout; + char *psu_voltin; + char *psu_voltout; +} psu_dev_group_t; + +#define PSU_PSOC_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/%s" +#define PSU_CPLD_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s" + +static char psu_dev_path_state[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltin[MAX_PATH_SIZE]; +#if 0 +static char psu_dev_path_vendor[MAX_PATH_SIZE]; +static char psu_dev_path_version[MAX_PATH_SIZE]; +static char psu_dev_path_sn[MAX_PATH_SIZE]; +static char psu_dev_path_temperature[MAX_PATH_SIZE]; +static char psu_dev_path_fan_speed[MAX_PATH_SIZE]; +static char psu_dev_path_fan_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_fan_faulty[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_currentout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerin[MAX_PATH_SIZE]; +static char psu_dev_path_psu_powerout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_voltout[MAX_PATH_SIZE]; +static char psu_dev_path_psu_pwm[MAX_PATH_SIZE]; +static char psu_dev_path_psu_rpm[MAX_PATH_SIZE]; +#endif + +void sysfs_psu_path_init(void) +{ + sprintf(&psu_dev_path_state[0], PSU_CPLD_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" ); + sprintf(&psu_dev_path_psu_voltin[0], PSU_PSOC_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#if 0 + sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); + sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" ); +#endif +} + +static psu_dev_t psu_dev_name[] = { + { "state", psu_dev_path_state }, // Using cpld + { "psu_voltin", psu_dev_path_psu_voltin }, +#if 0 + { "vendor", psu_dev_path_vendor }, + { "version", psu_dev_path_version }, + { "sn", psu_dev_path_sn }, + { "temperature", psu_dev_path_temperature }, + { "fan_speed", psu_dev_path_fan_speed }, + { "fan_pwm", psu_dev_path_fan_pwm }, + { "fan_faulty", psu_dev_path_fan_faulty }, + { "psu_currentin", psu_dev_path_psu_currentin }, + { "psu_currentout", psu_dev_path_psu_currentout }, + { "psu_powerin", psu_dev_path_psu_powerin }, + { "psu_powerout", psu_dev_path_psu_powerout }, + { "psu_voltout", psu_dev_path_psu_voltout }, + { "psu_pwm", psu_dev_path_psu_pwm }, + { "psu_rpm", psu_dev_path_psu_rpm }, +#endif +}; +#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) ) + +static psu_dev_group_t psu_dev_group[] = { + { + .psu_name = "psu1", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, + { + .psu_name = "psu2", + .psu_dev_namep = &psu_dev_name[0], + .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t), + }, +}; +#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) ) + +static char psu_state[4][MIN_ACC_SIZE]; + +static struct psu_wire_tbl_s { + char *psu_attr; + char *psu_name; + char *psu_wire; + char *psu_state; +} psu_wire_tbl[] = { + { "state", "psu1", "psu0", psu_state[0] }, // Using cpld + { "state", "psu2", "psu1", psu_state[1] }, + { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] }, + { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] }, +}; +#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) ) + +static char * +psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp) +{ + int i; + + for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) { + if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 && + strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) { + if (psu_statepp) { + *psu_statepp = psu_wire_tbl[i].psu_state; + } + return psu_wire_tbl[i].psu_wire; + } + } + return NULL; +} + +int psu_check_state_normal(char *statep) +{ + if (strstr(statep, "normal")) { + return 1; + } + return 0; +} + +#define PSU_ATTR_VOLTIN ("psu_voltin") +#define PSU_ATTR_VOLTIN_LEN (10) + +/* Get PSU voltin for determon AC(110v) or DC(48v) */ +void psu_get_voltin(void) +{ + char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE]; + psu_dev_t *devnamep; + unsigned int voltin; + char *invwirep; + int i, j; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + //psu_dev_group[i].psu_name; + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(volt, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + continue; + } + else { + voltin = simple_strtol(&volt[0], NULL, 10); + printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin); + if (voltin > psu_voltin) { + psu_voltin = voltin; + } + } + } + } + } + + SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin); +} + +#define PSU_ATTR_STATE ("state") +#define PSU_ATTR_STATE_LEN (5) + +/* psus_control() by inv_thread */ +int psus_control(int log_only) +{ + char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE]; + psu_dev_t *devnamep = NULL; + char *invwirep = NULL; + char *psu_statep = NULL; + int i, j, flag = 0; + + for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) { + devnamep = psu_dev_group[i].psu_dev_namep; + for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) { + if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) { + invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep); + if (invwirep == NULL) { + printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name); + continue; + } + sprintf(acc_path, devnamep->inv_dev_pathp, invwirep); + //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path); + if (inventec_show_attr(state, acc_path) <= 0) { + printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path); + if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) { + strcpy(psu_statep, PSU_STATE_ERROR); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR); + } + flag = 1; + } + else + if (strstr(state, "normal")) { + //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + } + else + if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */ + //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state); + if (strncmp(psu_statep, state, strlen(state)) != 0) { + strcpy(psu_statep, state); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state); + } + flag = 1; + } + else { /* DC PSUS */ + if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) { + strcpy(psu_statep, PSU_STATE_CHECKPSU); + SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU); + } + flag = 1; + } + } + } + } + + if (log_only) { + return 0; + } + + //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag); + if (flag == 1) { + status_led_grn("3"); + return 1; + } + return 0; +} + +/* End of psuinfo_device */ + +static int __init +psu_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_psu_path_init(); +#endif + return 0; +} + + +static void __exit +psu_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove psu module.\n"); +} + +/* led device *************************************/ +#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led" +#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led" + +#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1" +#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2" +#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3" +#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4" +#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1" +#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2" +#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3" +#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4" + +#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag" +#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl" + +static char status_led_grn_path[MAX_PATH_SIZE]; +static char status_led_red_path[MAX_PATH_SIZE]; +static char fan_led_grn1_path[MAX_PATH_SIZE]; +static char fan_led_grn2_path[MAX_PATH_SIZE]; +static char fan_led_grn3_path[MAX_PATH_SIZE]; +static char fan_led_grn4_path[MAX_PATH_SIZE]; +static char fan_led_red1_path[MAX_PATH_SIZE]; +static char fan_led_red2_path[MAX_PATH_SIZE]; +static char fan_led_red3_path[MAX_PATH_SIZE]; +static char fan_led_red4_path[MAX_PATH_SIZE]; +static char hwmon_device_diag_path[MAX_PATH_SIZE]; +static char hwmon_device_ctrl_path[MAX_PATH_SIZE]; + +void sysfs_led_path_init(void) +{ + sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld()); + sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld()); + sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc()); + sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc()); + sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc()); + sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc()); + sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc()); + sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc()); + sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld()); +} + +/* return 0/off 1/green 2/red */ +int +status_led_check_color(void) +{ + char tmpbuf[MIN_ACC_SIZE]; + int ret = STATUS_LED_INVALID; + + if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_GRN0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_GRN1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_GRN2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_GRN3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_GRN7; + } + return ret; + } + + if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) { + if (tmpbuf[0] == '0') { + ret = STATUS_LED_RED0; + } + if (tmpbuf[0] == '1') { + ret = STATUS_LED_RED1; + } + if (tmpbuf[0] == '2') { + ret = STATUS_LED_RED2; + } + if (tmpbuf[0] == '3') { + ret = STATUS_LED_RED3; + } + if (tmpbuf[0] == '7') { + ret = STATUS_LED_RED7; + } + return ret; + } + return ret; +} + +/* + * Store attr Section + */ +static DEFINE_MUTEX(diag_mutex); + +ssize_t status_led_diag_mode_enable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '0') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("1", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return ret; + } + mutex_unlock(&diag_mutex); + } + + return ret; +} + +ssize_t status_led_diag_mode_disable(void) +{ + char tmp[MIN_ACC_SIZE]; + ssize_t ret; + + ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path); + if (ret <= 0) { + return ret; + } + + if (tmp[0] == '1') { + mutex_lock(&diag_mutex); + ret = inventec_store_attr("0", 1, hwmon_device_diag_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + mutex_unlock(&diag_mutex); + return 1; + } + mutex_unlock(&diag_mutex); + } + return 1; +} + +ssize_t +status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2) +{ + ssize_t ret; + + ret = inventec_store_attr(tmp1, strlen(tmp1), path1); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(tmp2, strlen(tmp2), path2); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_red(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +ssize_t +status_led_grn(const char *freq) +{ + ssize_t ret; + + ret = inventec_store_attr("0", 1, &status_led_red_path[0]); + if (ret < 0) { + return ret; + } + ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]); + if (ret < 0) { + return ret; + } + if ((ret = status_led_diag_mode_enable()) <= 0) { + return ret; + } + ssleep(1); + if ((ret = status_led_diag_mode_disable()) <= 0) { + return ret; + } + return ret; +} + +static int status_led_diag_mode = STATUS_LED_MODE_AUTO; + +int status_led_check_diag_mode(void) +{ + return status_led_diag_mode; +} + +void sys_ready(void) +{ + ssize_t ret; + ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path); + if (ret < 0) { + SYSFS_LOG("[p_thread] set ctl fail"); + } + SYSFS_LOG("[p_thread] set ctl successfully"); +} + +/* End of ledinfo_device */ + +static int __init +led_device_init(void) +{ +#ifdef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sys_ready(); +#endif + return 0; +} + + +static void __exit +led_device_exit(void) +{ + printk(KERN_INFO "[p_thread] Remove led module.\n"); +} + +/* sensor device **********************************/ +#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp" + +static char sensor_dev_path_switch_temp[MAX_PATH_SIZE]; + +void sysfs_sensor_path_init(void) +{ + sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc()); +} + +void switch_temp_update(void) +{ + char buf[MIN_ACC_SIZE]; + ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp"); + if (count > 0) { + //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp); + inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp); + } +} + +/**************************************************/ +/* From system_device */ +static int inv_pthread_control = 1; + +int thread_control(void) +{ + return inv_pthread_control; +} + +void thread_control_set(int val) +{ + inv_pthread_control = val; +} +/* End system_device */ + +#define THREAD_SLEEP_MINS (3) +#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1) + +extern void psu_get_voltin(void); + +static struct task_struct *thread_st; +static int thread_data; + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO +void led_set_gpio_to_change_status_led(void) +{ + ssize_t ret = inventec_store_attr("57", 2, "/sys/class/gpio/export"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write 57 to /sys/class/gpio/export failed\n"); + return; + } + ret = inventec_store_attr("low", 3, "/sys/class/gpio/gpio57/direction"); + if (ret < 0) { + SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio57/direction failed\n"); + return; + } + SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n"); +} +#endif + +// Function executed by kernel thread +static int thread_fn(void *unused) +{ + /* Delay for guarantee HW ready */ + ssleep(THREAD_DELAY_MINS); + +#ifndef INV_PTHREAD_KERNEL_MODULE + sysfs_led_path_init(); + sysfs_fan_path_init(); + sysfs_psu_path_init(); +#endif + //sysfs_sensor_path_init(); + + /* Default status init */ + status_led_grn("7"); + + psu_get_voltin(); + +#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO + led_set_gpio_to_change_status_led(); +#endif + + while (1) + { + ssleep(THREAD_SLEEP_MINS); + + if (thread_control() == 0) { + printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__); + break; + } + + if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) { + /* status led in change color/freq mode, higher priority. Ignore fans sttaus */ + continue; + } + + //switch_temp_update(); + + if (fans_control() > 0) { + psus_control(1); + continue; + } + else + if (psus_control(0) > 0) { + continue; + } + + if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */ + status_led_grn("7"); + } + } + +#ifndef INV_PTHREAD_KERNEL_MODULE +err_inv_pthread_fn_1: +#endif + do_exit(0); + printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__); + return 0; +} + + +static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int fan_absence; + size_t count; + + fan_absence = fans_control(); + count += sprintf(&buf[count], "%d\n", fan_absence); + return count; +} + +static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static struct attribute status_att = { + .name = "fan_absence", + .mode = 0777, +}; + +static const struct sysfs_ops status_ops = { + .show = s_show, + .store = s_store, +}; + +static struct kobj_type status_ktype = { + .sysfs_ops = &status_ops, +}; + + +static int __init inv_pthread_init(void) +{ + int retval; + + status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL); + if(!status_kobj) + return PTR_ERR(status_kobj); + + status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj); + if(!status_kset) + return -1; + + status_kobj->kset = status_kset; + + retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan"); + if(retval) + return retval; + + retval = sysfs_create_file(status_kobj, &status_att); + + + inventec_class_init(); + fan_device_init(); + psu_device_init(); + led_device_init(); + + thread_control_set(1); + + printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__); + //Create the kernel thread with name 'inv_pthread' + thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread"); + if (thread_st) + printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n"); + else + printk(KERN_ERR "[p_thread] inv_pthread creation failed\n"); + + return retval; +} + +static void __exit inv_pthread_exit(void) +{ + thread_control_set(0); + /* Delay for guarantee thread exit */ + ssleep(THREAD_DELAY_MINS); + + fan_device_exit(); + psu_device_exit(); + led_device_exit(); + inventec_class_exit(); + + sysfs_remove_file(status_kobj, &status_att); + kset_unregister(status_kset); + kobject_del(status_kobj); + + printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n"); +} + +module_init(inv_pthread_init); +module_exit(inv_pthread_exit); + +MODULE_AUTHOR("Robert "); +MODULE_DESCRIPTION("Inventec Platform Management Thread"); +MODULE_VERSION("version 1.0"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.c new file mode 100644 index 000000000000..58c1a0aeb048 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.c @@ -0,0 +1,719 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "inv_swps.h" + +static int port_major; +static int ioexp_total; +static int port_total; +static struct class *swp_class_p = NULL; +static struct inv_platform_s *platform_p = NULL; +static struct inv_ioexp_layout_s *ioexp_layout = NULL; +static struct inv_port_layout_s *port_layout = NULL; + +static int +__swp_match(struct device *dev,const void *data){ + + char *name = (char *)data; + if (strcmp(dev_name(dev), name) == 0) + return 1; + return 0; +} + + +struct device * +get_swpdev_by_name(char *name){ + struct device *dev = class_find_device(swp_class_p, + NULL, + name, + (const void *)__swp_match); + return dev; +} + + +static int +sscanf_2_int(const char *buf) { + + int result = -EBFONT; + char *hex_tag = "0x"; + + if (strcspn(buf, hex_tag) == 0) { + if (sscanf(buf,"%x",&result)) { + return result; + } + } else { + if (sscanf(buf,"%d",&result)) { + return result; + } + if(sscanf(buf,"-%d",&result)) { + return -result; + } + if (sscanf(buf,"%x",&result)) { + return result; + } + } + return -EBFONT; +} + + +static int +sscanf_2_binary(const char *buf) { + + int result = sscanf_2_int(buf); + + if (result < 0){ + return -EBFONT; + } + switch (result) { + case 0: + case 1: + return result; + default: + break; + } + return -EBFONT; +} + +/* ========== Show functions: For I/O Expander attribute ========== + */ +static ssize_t +_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset), + char *buf_p) { + size_t len; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR(" %s: data corruption! :%s\n", __func__, tobj_p->swp_name); + return -ENODATA; + } + mutex_lock(&ioexp_p->lock); + len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset)); + mutex_unlock(&ioexp_p->lock); + return len; +} + + +static ssize_t +show_attr_present(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_present, + buf_p); +} + +static ssize_t +show_attr_tx_fault(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_fault, + buf_p); +} + +static ssize_t +show_attr_rxlos(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_rxlos, + buf_p); +} + +static ssize_t +show_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_tx_disable, + buf_p); +} + +static ssize_t +show_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_reset, + buf_p); +} + +static ssize_t +show_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_lpmod, + buf_p); +} + + +static ssize_t +show_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p){ + return -ENODEV; + } + return _show_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->get_modsel, + buf_p); +} + +/* ========== Store functions: For I/O Expander (R/W) attribute ========== + */ +static ssize_t +_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p, + int (*set_func)(struct ioexp_obj_s *ioexp_p, + int virt_offset, int input_val), + const char *buf_p, + size_t count) { + + int input, err; + struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p; + + if (!ioexp_p) { + SWPS_ERR("%s: data corruption! :%s\n", + __func__, tobj_p->swp_name); + return -ENODATA; + } + input = sscanf_2_binary(buf_p); + if (input < 0) { + return -EBFONT; + } + mutex_lock(&ioexp_p->lock); + err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input); + mutex_unlock(&ioexp_p->lock); + if (err < 0){ + return err; + } + return count; +} + +static ssize_t +store_attr_tx_disable(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_tx_disable, + buf_p, + count); +} + +static ssize_t +store_attr_reset(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_reset, + buf_p, + count); +} + + +static ssize_t +store_attr_lpmod(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_lpmod, + buf_p, + count); +} + + +static ssize_t +store_attr_modsel(struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p); + if (!tobj_p) { + return -ENODEV; + } + return _store_ioexp_binary_attr(tobj_p, + tobj_p->ioexp_obj_p->set_modsel, + buf_p, + count); +} + +/* ========== IO Expander attribute: from expander ========== + */ +static DEVICE_ATTR(present, S_IRUGO, show_attr_present, NULL); +static DEVICE_ATTR(tx_fault, S_IRUGO, show_attr_tx_fault, NULL); +static DEVICE_ATTR(rxlos, S_IRUGO, show_attr_rxlos, NULL); +static DEVICE_ATTR(tx_disable, S_IRUGO|S_IWUSR, show_attr_tx_disable, store_attr_tx_disable); +static DEVICE_ATTR(reset, S_IRUGO|S_IWUSR, show_attr_reset, store_attr_reset); +static DEVICE_ATTR(lpmod, S_IRUGO|S_IWUSR, show_attr_lpmod, store_attr_lpmod); +static DEVICE_ATTR(modsel, S_IRUGO|S_IWUSR, show_attr_modsel, store_attr_modsel); + +/* ========== Functions for module handling ========== + */ +static void +clean_port_obj(void){ + + dev_t dev_num; + char dev_name[32]; + struct device *device_p; + struct transvr_obj_s *transvr_obj_p; + int minor_curr, port_id; + + for (minor_curr=0; minor_curri2c_client_p); + kfree(transvr_obj_p); + } + dev_num = MKDEV(port_major, minor_curr); + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); + } + SWPS_DEBUG("%s: done.\n", __func__); +} + + +static int +get_platform_type(void){ + + char log_msg[64] = "ERROR"; + + platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL); + if (!platform_p){ + snprintf(log_msg, sizeof(log_msg), "kzalloc fail"); + goto err_get_platform_type_1; + } + platform_p->id = PLATFORM_SETTINGS; + memset(platform_p->name, 0, sizeof(platform_p->name)); + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", platform_map.name); + snprintf(log_msg, sizeof(log_msg), + "User setup platform: %d (%s)", + platform_p->id, platform_p->name); + SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return 0; + +err_get_platform_type_1: + SWPS_ERR("%s: %s :%d\n", __func__, log_msg, PLATFORM_SETTINGS); + return -1; +} + + +static int +get_layout_info(void){ + ioexp_layout = secquoia_ioexp_layout; + port_layout = secquoia_port_layout; + ioexp_total = ARRAY_SIZE(secquoia_ioexp_layout); + port_total = ARRAY_SIZE(secquoia_port_layout); + + SWPS_INFO("Start to initial platform: %d (%s)\n", + platform_p->id, platform_p->name); + return 0; +} + +/* ========== Functions for register something ========== + */ + +static int +register_ioexp_attr_sfp_1(struct device *device_p){ + /* Support machine type: + * - SFP : Magnolia + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_fault) < 0) { + err_attr = "dev_attr_tx_fault"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_rxlos) < 0) { + err_attr = "dev_attr_rxlos"; + goto err_ioexp_sfp1_attr; + } + if (device_create_file(device_p, &dev_attr_tx_disable) < 0) { + err_attr = "dev_attr_tx_disable"; + goto err_ioexp_sfp1_attr; + } + return 0; + +err_ioexp_sfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + +static int +register_ioexp_attr_sfp_2(struct device *device_p){ + /* Support machine type: + * - SFP28 : Cypress + */ + char *err_attr = NULL; + + if (register_ioexp_attr_sfp_1(device_p) < 0){ + goto err_ioexp_sfp2_attr; + } + return 0; + +err_ioexp_sfp2_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + +static int +register_ioexp_attr_qsfp_1(struct device *device_p){ + /* Support machine type: + * - QSFP : Magnolia, Redwood, Hudson32i + * - QSFP+ : Magnolia, Redwood, Hudson32i + * - QSFP28: Redwood + */ + char *err_attr = NULL; + + if (device_create_file(device_p, &dev_attr_present) < 0) { + err_attr = "dev_attr_present"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_reset) < 0) { + err_attr = "dev_attr_reset"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_lpmod) < 0) { + err_attr = "dev_attr_lpmod"; + goto err_ioexp_qsfp1_attr; + } + if (device_create_file(device_p, &dev_attr_modsel) < 0) { + err_attr = "dev_attr_modsel"; + goto err_ioexp_qsfp1_attr; + } + return 0; + +err_ioexp_qsfp1_attr: + SWPS_ERR("Add device attribute:%s failure! \n",err_attr); + return -1; +} + +static int +register_ioexp_attr(struct device *device_p, + struct transvr_obj_s *transvr_obj){ + + char *err_msg = "ERR"; + + switch (transvr_obj->ioexp_obj_p->ioexp_type){ + case IOEXP_TYPE_SEQUOIA_NABC: + if (register_ioexp_attr_qsfp_1(device_p) < 0){ + err_msg = "register_ioexp_attr_qsfp_1 fail"; + goto err_reg_ioexp_attr; + } + + break; + + default: + err_msg = "Unknow type"; + goto err_reg_ioexp_attr; + } + return 0; + +err_reg_ioexp_attr: + SWPS_ERR("%s: %s :%d \n", + __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type); + return -1; +} + + +static int +register_port_device(char *dev_name, + dev_t dev_num, + struct transvr_obj_s *transvr_obj){ + + struct device *device_p = NULL; + device_p = device_create(swp_class_p, /* struct class *cls */ + NULL, /* struct device *parent */ + dev_num, /* dev_t devt */ + transvr_obj, /* void *private_data */ + dev_name); /* const char *fmt */ + if (IS_ERR(device_p)){ + goto err_regswp_create_dev; + } + if (register_ioexp_attr(device_p, transvr_obj) < 0){ + goto err_regswp_reg_attr; + } + return 0; + +err_regswp_reg_attr: + device_unregister(device_p); + device_destroy(swp_class_p, dev_num); +err_regswp_create_dev: + SWPS_ERR("%s fail! :%s\n", __func__, dev_name); + return -1; +} + + +static int +register_swp_module(void){ + + dev_t port_devt = 0; + int dev_total = port_total + 1; /* char_dev for module control */ + + if (alloc_chrdev_region(&port_devt, 0, dev_total, SWP_CLS_NAME) < 0){ + SWPS_WARN("Allocate PORT MAJOR failure! \n"); + goto err_register_swp_module_3; + } + port_major = MAJOR(port_devt); + + /* Create class object */ + swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME); + if (IS_ERR(swp_class_p)) { + SWPS_ERR("Create class failure! \n"); + goto err_register_swp_module_3; + } + return 0; + +err_register_swp_module_3: + unregister_chrdev_region(MKDEV(port_major, 0), port_total); + return -1; +} + + +/* ========== Module initial relate ========== + */ +static int +create_ioexp_objs(void) { + + int i, run_mod; + + /* Clean IOEXP object */ + clean_ioexp_objs(); + /* Get running mode */ + run_mod = IOEXP_MODE_DIRECT; + /* Create IOEXP object */ + for(i=0; i devlen_max) { + snprintf(err_msg, sizeof(err_msg), + "SWP_DEV_PORT too long!"); + goto err_initport_create_tranobj; + } + memset(dev_name, 0, sizeof(dev_name)); + snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id); + /* Create transceiver object */ + ioexp_obj_p = get_ioexp_obj(ioexp_id); + if (!ioexp_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "IOEXP object:%d not exist", ioexp_id); + goto err_initport_create_tranobj; + } + transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p, + ioexp_virt_offset, transvr_type, + chipset_type, run_mod); + if (!transvr_obj_p){ + snprintf(err_msg, sizeof(err_msg), + "Create transceiver object fail :%s", dev_name); + goto err_initport_create_tranobj; + } + /* Setup Lane_ID mapping */ + i = ARRAY_SIZE(port_layout[minor_curr].lane_id); + j = ARRAY_SIZE(transvr_obj_p->lane_id); + if (i != j) { + snprintf(err_msg, sizeof(err_msg), + "Lane_id size inconsistent %d/%d", i, j); + goto err_initport_reg_device; + } + memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int)); + /* Create and register device object */ + if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){ + snprintf(err_msg, sizeof(err_msg), + "register_port_device fail"); + goto err_initport_reg_device; + } + /* Setup device_ptr of transvr_obj */ + dev_p = get_swpdev_by_name(dev_name); + if (!dev_p){ + snprintf(err_msg, sizeof(err_msg), + "get_swpdev_by_name fail"); + goto err_initport_reg_device; + } + transvr_obj_p->transvr_dev_p = dev_p; + /* Success */ + ok_count++; + } + SWPS_INFO("%s: initialed %d port-dev",__func__, ok_count); + return 0; + +err_initport_reg_device: + kfree(transvr_obj_p); +err_initport_create_tranobj: + clean_port_obj(); + SWPS_ERR("%s: %s", __func__, err_msg); + SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n", + port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod); + return -1; +} + +static int __init +swp_module_init(void){ + + if (get_platform_type() < 0){ + goto err_init_out; + } + if (get_layout_info() < 0){ + goto err_init_out; + } + if (register_swp_module() < 0){ + goto err_init_out; + } + if (create_ioexp_objs() < 0){ + goto err_init_ioexp; + } + if (create_port_objs() < 0){ + goto err_init_portobj; + } + if (init_ioexp_objs() < 0){ + goto err_init_portobj; + } + SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION); + return 0; + + +err_init_portobj: + clean_ioexp_objs(); +err_init_ioexp: + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); +err_init_out: + SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION); + return -1; +} + + +static void __exit +swp_module_exit(void){ + clean_port_obj(); + clean_ioexp_objs(); + class_unregister(swp_class_p); + class_destroy(swp_class_p); + unregister_chrdev_region(MKDEV(port_major, 0), port_total); + SWPS_INFO("Remove Inventec switch-port module success.\n"); +} + + +/* Module information */ +MODULE_AUTHOR(SWP_AUTHOR); +MODULE_DESCRIPTION(SWP_DESC); +MODULE_VERSION(SWP_VERSION); +MODULE_LICENSE(SWP_LICENSE); + +module_init(swp_module_init); +module_exit(swp_module_exit); + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.h new file mode 100644 index 000000000000..3d462ed3c944 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/inv_swps.h @@ -0,0 +1,184 @@ +#ifndef INV_SWPS_H +#define INV_SWPS_H + +#include "transceiver.h" +#include "io_expander.h" + +/* Module settings */ +#define SWP_CLS_NAME "swps" +#define SWP_DEV_PORT "port" +#define SWP_DEV_MODCTL "module" +#define SWP_RESET_PWD "inventec" +#define SWP_POLLING_PERIOD (300) /* msec */ +#define SWP_POLLING_ENABLE (1) +#define SWP_AUTOCONFIG_ENABLE (1) + +/* Module information */ +#define SWP_AUTHOR "Neil " +#define SWP_DESC "Inventec port and transceiver driver" +#define SWP_VERSION "4.2.5" +#define SWP_LICENSE "GPL" + +/* Module status define */ +#define SWP_STATE_NORMAL (0) +#define SWP_STATE_I2C_DIE (-91) + +/* [Note]: + * Functions and mechanism for auto-detect platform type is ready, + * But HW and BIOS not ready! We need to wait them. + * So, please do not use PLATFORM_TYPE_AUTO until they are ready. + * (2016.06.13) + */ +#define PLATFORM_TYPE_SEQUOIA_GA (171) +/* Current running platfrom */ +#define PLATFORM_SETTINGS PLATFORM_TYPE_SEQUOIA_GA + +/* Define platform flag and kernel version */ +#if (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA) + #define SWPS_SEQUOIA (1) + #define SWPS_KERN_VER_BF_3_8 (1) +#endif + + +struct inv_platform_s { + int id; + char name[64]; +}; + +struct inv_ioexp_layout_s { + int ioexp_id; + int ioexp_type; + struct ioexp_addr_s addr[4]; +}; + +struct inv_port_layout_s { + int port_id; + int chan_id; + int ioexp_id; + int ioexp_offset; + int transvr_type; + int chipset_type; + int lane_id[8]; +}; + + +/* ========================================== + * Inventec Platform Settings + * ========================================== + */ +struct inv_platform_s platform_map = {PLATFORM_TYPE_SEQUOIA_GA, "Sequoia_GA" }; + +/* ========================================== + * Sequoia Layout configuration + * ========================================== + */ + +struct inv_ioexp_layout_s secquoia_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */ + }, + {2, IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */ + }, + {3, IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */ + }, + {4, IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */ + }, + {5, IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */ + }, + {6, IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */ + }, + {7, IOEXP_TYPE_SEQUOIA_NABC, { {9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */ + {9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + +struct inv_port_layout_s secquoia_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} }, + { 1, 11, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} }, + { 2, 12, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} }, + { 3, 13, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} }, + { 4, 14, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} }, + { 5, 15, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} }, + { 6, 16, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} }, + { 7, 17, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} }, + { 8, 18, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} }, + { 9, 19, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} }, + {10, 20, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} }, + {11, 21, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} }, + {12, 22, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} }, + {13, 23, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} }, + {14, 24, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121, 122, 123, 124} }, + {15, 25, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} }, + {16, 26, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {137, 138, 139, 140} }, + {17, 27, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {129, 130, 131, 132} }, + {18, 28, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {153, 154, 155, 156} }, + {19, 29, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {145, 146, 147, 148} }, + {20, 30, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {169, 170, 171, 172} }, + {21, 31, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {161, 162, 163, 164} }, + {22, 32, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {185, 186, 187, 188} }, + {23, 33, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {177, 178, 179, 180} }, + {24, 34, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {201, 202, 203, 204} }, + {25, 35, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {193, 194, 195, 196} }, + {26, 36, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {217, 218, 219, 220} }, + {27, 37, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {209, 210, 211, 212} }, + {28, 38, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {233, 234, 235, 236} }, + {29, 39, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {225, 226, 227, 228} }, + {30, 40, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {249, 250, 251, 252} }, + {31, 41, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {241, 242, 243, 244} }, + {32, 45, 4, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} }, + {33, 44, 4, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} }, + {34, 43, 4, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} }, + {35, 42, 4, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} }, + {36, 49, 4, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} }, + {37, 48, 4, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} }, + {38, 47, 4, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} }, + {39, 46, 4, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} }, + {40, 53, 5, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} }, + {41, 52, 5, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} }, + {42, 51, 5, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} }, + {43, 50, 5, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} }, + {44, 57, 5, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} }, + {45, 56, 5, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} }, + {46, 55, 5, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125, 126, 127, 128} }, + {47, 54, 5, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117, 118, 119, 120} }, + {48, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {141, 142, 143, 144} }, + {49, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {133, 134, 135, 136} }, + {50, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {157, 158, 159, 160} }, + {51, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {149, 150, 151, 152} }, + {52, 65, 6, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {173, 174, 175, 176} }, + {53, 64, 6, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {165, 166, 167, 168} }, + {54, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {189, 190, 191, 192} }, + {55, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {181, 182, 183, 184} }, + {56, 69, 7, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {205, 206, 207, 208} }, + {57, 68, 7, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {197, 198, 199, 200} }, + {58, 67, 7, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {221, 222, 223, 224} }, + {59, 66, 7, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {213, 214, 215, 216} }, + {60, 73, 7, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {237, 238, 239, 240} }, + {61, 72, 7, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {229, 230, 231, 232} }, + {62, 71, 7, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {253, 254, 255, 256} }, + {63, 70, 7, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {245, 246, 247, 248} }, +}; + + +#endif /* INV_SWPS_H */ + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.c new file mode 100644 index 000000000000..231884f3e442 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.c @@ -0,0 +1,1786 @@ +#include +#include +#include "io_expander.h" + +static struct ioexp_obj_s *ioexp_head_p = NULL; +static struct ioexp_obj_s *ioexp_tail_p = NULL; + + +/* ========== Register IOEXP layout ========== + */ +struct ioexp_map_s ioexp_map_magnolia_nab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_magnolia_7ab = { + + .chip_amount = 2, + .data_width = 2, + + .map_present = { {1, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {1, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {1, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 2}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 3}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_redwood_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p01p08_p17p24 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 0, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 0, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 0, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 0, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 0, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 0, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 0, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_hudson32iga_p09p16_p25p32 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MODABS_QSFP(X) */ + {2, 1, 1}, /* map_present[1] = MODABS_QSFP(X+1) */ + {2, 1, 2}, /* map_present[2] = MODABS_QSFP(X+2) */ + {2, 1, 3}, /* map_present[3] = MODABS_QSFP(X+3) */ + {2, 1, 4}, /* map_present[4] = MODABS_QSFP(X+4) */ + {2, 1, 5}, /* map_present[5] = MODABS_QSFP(X+5) */ + {2, 1, 6}, /* map_present[6] = MODABS_QSFP(X+6) */ + {2, 1, 7}, /* map_present[7] = MODABS_QSFP(X+7) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */ + {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */ + {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */ + {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */ + {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */ + }, + .map_lpmod = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X) */ + {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */ + {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */ + {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */ + }, + .map_modsel = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X) */ + {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */ + {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */ + {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */ + {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */ + {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_cypress_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_cypress_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {0, 1, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 1, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {0, 1, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {0, 1, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {0, 1, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {1, 1, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {1, 1, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {1, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {1, 1, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_5a = { + + .chip_amount = 1, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + }, +}; + + +struct ioexp_map_s ioexp_map_tahoe_6abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 0}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 3}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 0}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + {2, 1, 5}, /* map_present[8] = MOD_ABS_PORT(X+8) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + {2, 1, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + {2, 1, 4}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+8) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + {2, 1, 2}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_sequoia_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */ + {0, 1, 6}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */ + {0, 1, 7}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP28_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */ + {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */ + {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */ + {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */ + {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */ + }, +}; + + +/* ========== Private functions ========== + */ +int check_channel_tier_1(void); + +struct i2c_client * +_get_i2c_client(struct ioexp_obj_s *self, + int chip_id){ + + struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p; + + if (!(i2c_curr_p)){ + SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__); + return NULL; + } + while (i2c_curr_p){ + if ((i2c_curr_p->chip_id) == chip_id){ + return i2c_curr_p->i2c_client_p; + } + i2c_curr_p = i2c_curr_p->next; + } + SWPS_ERR("%s: not exist! :%d\n", __func__, chip_id); + return NULL; +} + + +static int +_common_ioexp_update_one(struct ioexp_obj_s *self, + struct ioexp_addr_s *ioexp_addr, + int chip_id, + int data_width, + int show_err, + char *caller_name) { + int buf = 0; + int err = 0; + int data_id = 0; + int r_offset = 0; + + for(data_id=0; data_idread_offset[data_id]; + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset); + /* Check error */ + if (buf < 0) { + err = 1; + if (show_err) { + SWPS_INFO("IOEXP-%d read fail! :%d \n", self->ioexp_id, buf); + SWPS_INFO("Dump: :%d :0x%02x :%d, :%s\n", + ioexp_addr->chan_id, ioexp_addr->chip_addr, + ioexp_addr->read_offset[data_id], caller_name); + } + continue; + } + /* Update IOEXP object */ + self->chip_data[chip_id].data[data_id] = (uint8_t)buf; + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +common_ioexp_update_all(struct ioexp_obj_s *self, + int show_err, + char *caller_name){ + + int err = 0; + int chip_id = 0; + int chip_amount = self->ioexp_map_p->chip_amount; + + for (chip_id=0; chip_idioexp_map_p->map_addr[chip_id]), + chip_id, + self->ioexp_map_p->data_width, + show_err, + caller_name) < 0) { + err = 1; + } + } + if (err) { + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +static int +_common_check_by_mode(struct ioexp_obj_s *self){ + + switch (self->mode){ + case IOEXP_MODE_DIRECT: + return self->fsm_4_direct(self); + + case IOEXP_MODE_POLLING: + if (self->state >= 0){ + return 0; + } + switch (self->state){ + case STATE_IOEXP_INIT: + return ERR_IOEXP_UNINIT; + case STATE_IOEXP_ABNORMAL: + return ERR_IOEXP_ABNORMAL; + default: + return ERR_IOEXP_NOSTATE; + } + break; + + default: + break; + } + SWPS_ERR("%s: Exception occurs. :%d \n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +static int +_common_get_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + char *func_mane){ + uint8_t buf; + int err_code; + + /* Check and get address */ + err_code = _common_check_by_mode(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Get data form cache */ + buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + return (int)(buf >> bitmap_obj_p->bit_shift & 0x01); +} + + +static int +_common_set_bit(struct ioexp_obj_s *self, + struct ioexp_bitmap_s *bitmap_obj_p, + int input_val, + char *func_mane){ + int err_code, target_offset; + uint8_t origin_byte; + uint8_t modify_byte; + + /* Check and get address */ + err_code = _common_check_by_mode(self); + if (err_code < 0){ + return err_code; + } + if (!bitmap_obj_p){ + SWPS_ERR("Layout config incorrect! :%d :%s\n", + self->ioexp_id, func_mane); + return ERR_IOEXP_BADCONF; + } + /* Prepare write date */ + origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset]; + switch (input_val) { + case 0: + modify_byte = origin_byte; + SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift); + break; + case 1: + modify_byte = origin_byte; + SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift); + break; + default: + SWPS_ERR("Input value incorrect! :%d :%d :%s\n", + input_val, self->ioexp_id, func_mane); + return ERR_IOEXP_BADINPUT; + } + /* Setup i2c client */ + target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset]; + /* Write byte to chip via I2C */ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id), + target_offset, + modify_byte); + /* Update or bollback object */ + if (err_code < 0){ + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte; + SWPS_ERR("I2C write fail! :%d :%d :%s :%d\n", + input_val, self->ioexp_id, func_mane, err_code); + return err_code; + } + self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte; + return 0; +} + + +/* ========== Object public functions ========== + */ +int +common_get_present(struct ioexp_obj_s *self, + int virt_offset){ + + int UNPLUG = 1; + int retval = ERR_IOEXP_UNEXCPT; + + retval = _common_get_bit(self, + &(self->ioexp_map_p->map_present[virt_offset]), + "common_get_present"); + if (retval < 0) { + /* [Note] + * => Transceiver object does not need to handle IOEXP layer issues. + */ + return UNPLUG; + } + return retval; +} + + +int +common_get_tx_fault(struct ioexp_obj_s *self, + int virt_offset){ + /* [Transmit Fault (Tx_Fault)] + * A catastrophic laser fault will activate the transmitter signal, + * TX_FAULT, and disable the laser. This signal is an open collector + * output (pull-up required on the host board). A low signal indicates + * normal laser operation and a high signal indicates a fault. The + * TX_FAULT will be latched high when a laser fault occurs and is + * cleared by toggling the TX_DISABLE input or power cycling the + * transceiver. The transmitter fault condition can also be monitored + * via the two-wire serial interface. + * (address A2, byte 110, bit 2). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_fault[virt_offset]), + "common_get_tx_fault"); +} + + +int +common_get_rxlos(struct ioexp_obj_s *self, + int virt_offset){ + /* [Receiver Loss of Signal (Rx_LOS)] + * The post-amplification IC also includes transition detection circuitry + * which monitors the ac level of incoming optical signals and provides a + * TTL/CMOS compatible status signal to the host (pin 8). An adequate optical + * input results in a low Rx_LOS output while a high Rx_LOS output indicates + * an unusable optical input. The Rx_LOS thresholds are factory set so that + * a high output indicates a definite optical fault has occurred. Rx_LOS can + * also be monitored via the two-wire serial interface + * (address A2h, byte 110, bit 1). + * + * 0: Normal + * 1: Abnormal + */ + return _common_get_bit(self, + &(self->ioexp_map_p->map_rxlos[virt_offset]), + "common_get_rxlos"); +} + + +int +common_get_tx_disable(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + "common_get_tx_disable"); +} + + +int +common_get_reset(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + "common_get_reset"); +} + + +int +common_get_lpmod(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + "common_get_lpmod"); +} + + +int +common_get_modsel(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + "common_get_modsel"); +} + + +int +common_get_hard_rs0(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + "common_get_hard_rs0"); +} + + +int +common_get_hard_rs1(struct ioexp_obj_s *self, + int virt_offset){ + + return _common_get_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + "common_get_hard_rs1"); +} + + +int +common_set_tx_disable(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_tx_disable[virt_offset]), + input_val, + "common_set_tx_disable"); +} + + +int +common_set_reset(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_reset[virt_offset]), + input_val, + "common_set_reset"); +} + + +int +common_set_lpmod(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_lpmod[virt_offset]), + input_val, + "common_set_lpmod"); +} + + +int +common_set_modsel(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_modsel[virt_offset]), + input_val, + "common_set_modsel"); +} + + +int +common_set_hard_rs0(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs0[virt_offset]), + input_val, + "common_set_hard_rs0"); +} + + +int +common_set_hard_rs1(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + + return _common_set_bit(self, + &(self->ioexp_map_p->map_hard_rs1[virt_offset]), + input_val, + "common_set_hard_rs1"); +} + + +int +ioexp_get_not_support(struct ioexp_obj_s *self, + int virt_offset){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +ioexp_set_not_support(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + return ERR_IOEXP_NOTSUPPORT; +} + + +int +fake_ioexp_init(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_ioexp_update(struct ioexp_obj_s *self){ + return 1; +} + + +int +fake_update_func(struct ioexp_obj_s *self){ + return 1; +} + +int +fake_get_func(struct ioexp_obj_s *self, + int virt_offset){ + SWPS_WARN("Someone called fake_get_func\n"); + return -1; +} + +int +fake_set_func(struct ioexp_obj_s *self, + int virt_offset, + int input_val){ + SWPS_WARN("Someone called fake_set_func\n"); + return -1; +} + + +/* ========== Initial functions for IO Expander ========== + */ +int +common_ioexp_init(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + /* Setup default value to each physical IO Expander */ + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + /* Get address mapping */ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("%s: IOEXP config incorrect! :%d \n", + __func__, chip_id); + return -1; + } + /* Setup default value */ + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->write_offset[offset], + addr_p->data_default[offset]); + if (err_code < 0){ + SWPS_ERR("%s: set default fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + } + } + /* Check and update info to object */ + err_code = self->update_all(self, 1, "common_ioexp_init"); + if (err_code < 0) { + SWPS_ERR("%s: update_all() fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } + return 0; +} + + +/* ========== Object functions for Final State Machine ========== + */ +int +_is_channel_ready(struct ioexp_obj_s *self){ + + int buf = 0; + int chip_id = 0; /* Use first chip which be registered */ + int data_id = 0; /* Use first byte which be registered */ + struct ioexp_addr_s *ioexp_addr = NULL; + + ioexp_addr = &(self->ioexp_map_p->map_addr[chip_id]); + if (!ioexp_addr){ + SWPS_ERR("%s: config incorrect!\n", __func__); + return ERR_IOEXP_UNEXCPT; + } + buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), + ioexp_addr->read_offset[data_id]); + if (buf >= 0){ + return 1; + } + return 0; +} + +int +_ioexp_init_handler(struct ioexp_obj_s *self){ + + int return_val; + + switch (self->mode) { + case IOEXP_MODE_DIRECT: + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + + case IOEXP_MODE_POLLING: + /* Check system and channel is ready */ + if (self->state == STATE_IOEXP_INIT){ + if (!_is_channel_ready(self)){ + self->state = STATE_IOEXP_INIT; + SWPS_WARN("%s: IOEXP:%d channel not ready.\n", + __func__, self->ioexp_id); + return 0; + } + } + /* Execute initial callback */ + return_val = self->init(self); + if (return_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + } else { + self->state = STATE_IOEXP_NORMAL; + } + return return_val; + + default: + break; + } + SWPS_ERR("%s: exception occur :%d\n", __func__, self->mode); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){ + + int result_val; + int show_err = 1; + char *func_mane = "common_ioexp_fsm_4_direct"; + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, and return error */ + return ERR_IOEXP_UNINIT; + } + /* Case: Initial done */ + return 0; + + case STATE_IOEXP_NORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + SWPS_INFO("%s: NORMAL -> ABNORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + self->state = STATE_IOEXP_NORMAL; + return 0; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_err, func_mane); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_DEBUG("%s: ABNORMAL -> NORMAL :%d\n", + __func__, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("%s: Exception occurs :%d\n", + __func__, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +int +common_ioexp_fsm_4_polling(struct ioexp_obj_s *self){ + + int result_val, i, show_e; + int fail_retry = 3; + char *func_name = "common_ioexp_fsm_4_polling"; + +#ifdef DEBUG_SWPS + show_e = 1; +#else + show_e = 0; +#endif + + switch (self->state){ + case STATE_IOEXP_INIT: + result_val = _ioexp_init_handler(self); + /* Exception case: terminate initial procedure */ + if(result_val < 0){ + /* Initial fail */ + return result_val; + } + /* Case: System (Channel) not ready */ + if(self->state == STATE_IOEXP_INIT){ + /* Keep in INIT state, wait and retry */ + return 0; + } + /* Case: Initial done */ + SWPS_INFO("IOEXP-%d: initial done. :%d\n", + self->ioexp_id, self->ioexp_type); + return result_val; + + case STATE_IOEXP_NORMAL: + /* Retry mechanism for case of i2c topology not stable */ + for (i=0; iupdate_all(self, show_e, func_name); + if (result_val >= 0) { + self->state = STATE_IOEXP_NORMAL; + return 0; + } + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: detect I2C crash :%d\n", + __func__, self->ioexp_id); + break; + } + SWPS_DEBUG("IOEXP-%d: unstable :%d\n", + self->ioexp_id, result_val); + } + SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + + case STATE_IOEXP_ABNORMAL: + result_val = self->update_all(self, show_e, func_name); + if (result_val < 0){ + self->state = STATE_IOEXP_ABNORMAL; + return result_val; + } + SWPS_INFO("IOEXP-%d: ABNORMAL -> NORMAL :%d\n", + self->ioexp_id, result_val); + self->state = STATE_IOEXP_NORMAL; + return 0; + + default: + break; + } + SWPS_ERR("IOEXP-%d: Exception occurs :%d\n", + self->ioexp_id, self->state); + return ERR_IOEXP_UNEXCPT; +} + + +/* ========== Object private functions for check & update ========== + */ +int +common_ioexp_check(struct ioexp_obj_s *self){ + + int result; + + if (self->mode != IOEXP_MODE_POLLING){ + SWPS_ERR("%s: not polling mode :%d\n", + __func__, self->mode); + return ERR_IOEXP_NOTSUPPORT; + } + mutex_lock(&self->lock); + result = self->fsm_4_polling(self); + mutex_unlock(&self->lock); + return result; +} + + +/* ========== Functions for Factory pattern ========== + */ +static struct ioexp_map_s * +get_ioexp_map(int ioexp_type){ + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + return &ioexp_map_magnolia_nab; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + return &ioexp_map_magnolia_7ab; + case IOEXP_TYPE_REDWOOD_P01P08: + return &ioexp_map_redwood_p01p08_p17p24; + case IOEXP_TYPE_REDWOOD_P09P16: + return &ioexp_map_redwood_p09p16_p25p32; + case IOEXP_TYPE_HUDSON32IGA_P01P08: + return &ioexp_map_hudson32iga_p01p08_p17p24; + case IOEXP_TYPE_HUDSON32IGA_P09P16: + return &ioexp_map_hudson32iga_p09p16_p25p32; + case IOEXP_TYPE_CYPRESS_NABC: + return &ioexp_map_cypress_nabc; + case IOEXP_TYPE_CYPRESS_7ABC: + return &ioexp_map_cypress_7abc; + case IOEXP_TYPE_TAHOE_5A: + return &ioexp_map_tahoe_5a; + case IOEXP_TYPE_TAHOE_6ABC: + return &ioexp_map_tahoe_6abc; + case IOEXP_TYPE_SEQUOIA_NABC: + return &ioexp_map_sequoia_nabc; + default: + return NULL; + } +} + + +int +setup_ioexp_ssize_attr(struct ioexp_obj_s *self, + struct ioexp_map_s *ioexp_map_p, + int ioexp_id, + int ioexp_type, + int run_mode){ + switch (run_mode){ + case IOEXP_MODE_POLLING: /* Direct access device mode */ + case IOEXP_MODE_DIRECT: /* Polling mode, read from cache */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = ERR_IOEXP_UNEXCPT; + return ERR_IOEXP_UNEXCPT; + } + self->ioexp_id = ioexp_id; + self->ioexp_type = ioexp_type; + self->ioexp_map_p = ioexp_map_p; + self->state = STATE_IOEXP_INIT; + mutex_init(&self->lock); + return 0; +} + + +static int +setup_addr_mapping(struct ioexp_obj_s *self, + struct ioexp_addr_s *addr_map_p){ + if (!addr_map_p){ + SWPS_ERR("%s: map is null\n", __func__); + return -1; + } + self->ioexp_map_p->map_addr = addr_map_p; + return 0; +} + + +static int +setup_ioexp_public_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + case IOEXP_TYPE_CYPRESS_NABC: + self->get_present = common_get_present; + self->get_tx_fault = common_get_tx_fault; + self->get_rxlos = common_get_rxlos; + self->get_tx_disable = common_get_tx_disable; + self->get_reset = ioexp_get_not_support; + self->get_lpmod = ioexp_get_not_support; + self->get_modsel = ioexp_get_not_support; + self->get_hard_rs0 = common_get_hard_rs0; + self->get_hard_rs1 = common_get_hard_rs1; + self->set_tx_disable = common_set_tx_disable; + self->set_reset = ioexp_set_not_support; + self->set_lpmod = ioexp_set_not_support; + self->set_modsel = ioexp_set_not_support; + self->set_hard_rs0 = common_set_hard_rs0; + self->set_hard_rs1 = common_set_hard_rs1; + return 0; + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + self->get_present = common_get_present; + self->get_tx_fault = ioexp_get_not_support; + self->get_rxlos = ioexp_get_not_support; + self->get_tx_disable = ioexp_get_not_support; + self->get_reset = common_get_reset; + self->get_lpmod = common_get_lpmod; + self->get_modsel = common_get_modsel; + self->get_hard_rs0 = ioexp_get_not_support; + self->get_hard_rs1 = ioexp_get_not_support; + self->set_tx_disable = ioexp_set_not_support; + self->set_reset = common_set_reset; + self->set_lpmod = common_set_lpmod; + self->set_modsel = common_set_modsel; + self->set_hard_rs0 = ioexp_set_not_support; + self->set_hard_rs1 = ioexp_set_not_support; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_ioexp_private_cb(struct ioexp_obj_s *self, + int ioexp_type){ + + switch (ioexp_type){ + case IOEXP_TYPE_MAGINOLIA_NAB: + case IOEXP_TYPE_MAGINOLIA_7AB: + case IOEXP_TYPE_SPRUCE_7AB: + case IOEXP_TYPE_REDWOOD_P01P08: + case IOEXP_TYPE_REDWOOD_P09P16: + case IOEXP_TYPE_HUDSON32IGA_P01P08: + case IOEXP_TYPE_HUDSON32IGA_P09P16: + case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_CYPRESS_7ABC: + case IOEXP_TYPE_TAHOE_5A: + case IOEXP_TYPE_TAHOE_6ABC: + case IOEXP_TYPE_SEQUOIA_NABC: + self->init = common_ioexp_init; + self->check = common_ioexp_check; + self->update_all = common_ioexp_update_all; + self->fsm_4_direct = common_ioexp_fsm_4_direct; + self->fsm_4_polling = common_ioexp_fsm_4_polling; + return 0; + + default: + SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type); + break; + } + return ERR_IOEXP_UNEXCPT; +} + + +static int +setup_i2c_client_one(struct ioexp_obj_s *self, + int chip_id){ + + char *err_msg = "ERROR"; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + struct ioexp_i2c_s *i2c_obj_p = NULL; + struct ioexp_i2c_s *i2c_curr_p = NULL; + + int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id; + adap = i2c_get_adapter(chan_id); + if(!adap){ + err_msg = "Can not get adap!"; + goto err_ioexp_setup_i2c_1; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + err_msg = "Can not kzalloc client!"; + goto err_ioexp_setup_i2c_1; + } + i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL); + if (!i2c_obj_p){ + err_msg = "Can not kzalloc i2c_obj_p!"; + goto err_ioexp_setup_i2c_2; + } + client->adapter = adap; + client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr; + i2c_obj_p->i2c_client_p = client; + i2c_obj_p->chip_id = chip_id; + i2c_obj_p->next = NULL; + if (!self->i2c_head_p){ + self->i2c_head_p = i2c_obj_p; + } else { + i2c_curr_p = self->i2c_head_p; + while (i2c_curr_p->next){ + i2c_curr_p = i2c_curr_p->next; + } + i2c_curr_p->next = i2c_obj_p; + } + return 0; + +err_ioexp_setup_i2c_2: + kfree(client); +err_ioexp_setup_i2c_1: + SWPS_ERR("%s: %s :%d\n", __func__, err_msg, chan_id); + return -1; +} + + +static int +setup_i2c_client(struct ioexp_obj_s* self){ + + int result; + int chip_id = 0; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + result = setup_i2c_client_one(self, chip_id); + if (result < 0){ + SWPS_ERR("%s fail! :%d\n", __func__, chip_id); + return -1; + } + } + return 0; +} + + +static int +setup_ioexp_config(struct ioexp_obj_s *self) { + + int chip_id, offset, err_code; + struct ioexp_addr_s *addr_p; + + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("IOEXP config incorrect! :%d \n",chip_id); + return -1; + } + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->conf_offset[offset], + addr_p->conf_default[offset]); + + if (err_code < 0){ + SWPS_INFO("%s: set conf fail! :%d \n", __func__, err_code); + return -2; + } + } + } + return 0; +} + + +struct ioexp_obj_s * +_create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_map_s* ioexp_map_p; + struct ioexp_obj_s* result_p; + struct ioexp_i2c_s *i2c_curr_p; + struct ioexp_i2c_s *i2c_next_p; + + /* Get layout */ + ioexp_map_p = get_ioexp_map(ioexp_type); + if (!ioexp_map_p){ + SWPS_ERR("%s: Invalid ioexp_type\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare IOEXP object */ + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + SWPS_ERR("%s: kzalloc failure!\n", __func__); + goto err_create_ioexp_fail; + } + /* Prepare static size attributes */ + if (setup_ioexp_ssize_attr(result_p, + ioexp_map_p, + ioexp_id, + ioexp_type, + run_mode) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + /* Prepare address mapping */ + if (setup_addr_mapping(result_p, addr_map_p) < 0){ + goto err_create_ioexp_setup_attr_fail; + } + if (setup_i2c_client(result_p) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + /* Prepare call back functions of object */ + if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){ + goto err_create_ioexp_setup_i2c_fail; + } + return result_p; + +err_create_ioexp_setup_i2c_fail: + i2c_curr_p = result_p->i2c_head_p; + i2c_next_p = result_p->i2c_head_p; + while (i2c_curr_p){ + i2c_next_p = i2c_curr_p->next; + kfree(i2c_curr_p->i2c_client_p); + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } +err_create_ioexp_setup_attr_fail: + kfree(result_p); +err_create_ioexp_fail: + SWPS_ERR("%s: fail! :%d :%d \n", + __func__, ioexp_id, ioexp_type); + return NULL; +} + + +int +create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode){ + + struct ioexp_obj_s *ioexp_p = NULL; + + ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type, + addr_map_p, run_mode); + if (!ioexp_p){ + return -1; + } + if (ioexp_head_p == NULL){ + ioexp_head_p = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; + } + ioexp_tail_p->next = ioexp_p; + ioexp_tail_p = ioexp_p; + return 0; +} + + +static int +_init_ioexp_obj(struct ioexp_obj_s* self) { + + char *err_msg = "ERR"; + char *func_name = "_init_ioexp_obj"; + + /* Setup IOEXP configure byte */ + if (setup_ioexp_config(self) < 0){ + err_msg = "setup_ioexp_config fail"; + goto err_init_ioexp_obj; + } + /* Setup default data */ + if (_ioexp_init_handler(self) < 0){ + err_msg = "_ioexp_init_handler fail"; + goto err_init_ioexp_obj; + } + /* Update all */ + if (self->state == STATE_IOEXP_NORMAL){ + if (self->update_all(self, 1, func_name) < 0){ + err_msg = "update_all() fail"; + goto err_init_ioexp_obj; + } + } + return 0; + +err_init_ioexp_obj: + SWPS_DEBUG("%s: %s\n", __func__, err_msg); + return -1; +} + + +int +init_ioexp_objs(void){ + /* Return value: + * 0: Success + * -1: Detect topology error + * -2: SWPS internal error + */ + + struct ioexp_obj_s *curr_p = ioexp_head_p; + + if (!curr_p) { + SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__); + return -2; + } + while (curr_p) { + if (_init_ioexp_obj(curr_p) < 0) { + SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__); + return -1; + } + curr_p = curr_p->next; + } + SWPS_DEBUG("%s: done.\n", __func__); + return 0; +} + + +void +clean_ioexp_objs(void){ + + struct ioexp_i2c_s *i2c_curr_p = NULL; + struct ioexp_i2c_s *i2c_next_p = NULL; + struct ioexp_obj_s *ioexp_next_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + if (ioexp_head_p == NULL){ + ioexp_tail_p = NULL; + return; + } + while(ioexp_curr_p){ + ioexp_next_p = ioexp_curr_p->next; + i2c_curr_p = ioexp_curr_p->i2c_head_p; + while (i2c_curr_p) { + i2c_next_p = i2c_curr_p->next; + kfree(i2c_curr_p->i2c_client_p); + kfree(i2c_curr_p); + i2c_curr_p = i2c_next_p; + } + kfree(ioexp_curr_p); + ioexp_curr_p = ioexp_next_p; + } + ioexp_tail_p = NULL; + SWPS_DEBUG("%s: done.\n", __func__); +} + + +int +check_ioexp_objs(void){ + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while (ioexp_curr_p){ + if ( (ioexp_curr_p->check(ioexp_curr_p)) < 0){ + SWPS_INFO("check IOEXP-%d fail! :%d\n", + ioexp_curr_p->ioexp_id, ioexp_curr_p->ioexp_type); + return -1; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +struct ioexp_obj_s * +get_ioexp_obj(int ioexp_id){ + + struct ioexp_obj_s *result_p = NULL; + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + if (ioexp_curr_p->ioexp_id == ioexp_id){ + result_p = ioexp_curr_p; + break; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return result_p; +} + + +void +unlock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_unlock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } +} + + +int +lock_ioexp_all(void) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + + while(ioexp_curr_p){ + mutex_lock(&ioexp_curr_p->lock); + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; +} + + +int +check_channel_tier_1(void) { + + if ( (!_is_channel_ready(ioexp_head_p)) && + (!_is_channel_ready(ioexp_tail_p)) ){ + return -1; + } + return 0; +} + + +static int +_scan_channel_tier_1(int force, + int show_err) { + + struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p; + int ready = 0; + + if (!ioexp_curr_p) { + goto err_scan_tier_1_channel; + } + while(ioexp_curr_p) { + ready = _is_channel_ready(ioexp_curr_p); + if ((!ready) && (!force)) { + goto err_scan_tier_1_channel; + } + ioexp_curr_p = ioexp_curr_p->next; + } + return 0; + +err_scan_tier_1_channel: + if (show_err) { + if (ioexp_curr_p) { + SWPS_INFO("%s: IOEXP-%d fail\n", __func__, ioexp_curr_p->ioexp_id); + } else { + SWPS_INFO("%s: IOEXP is null.\n", __func__); + } + } + return -1; +} + + +static int +_scan_channel_tier_1_single(void) { + + int ret = 0; + int chan_id = 0; + int fake_cid = 0; + int fake_offs = 0; + int fake_addr = 0; + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + + if (ioexp_head_p->ioexp_id != ioexp_tail_p->ioexp_id) { + return 0; + } + /* Setup i2c_client */ + chan_id = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chan_id; + fake_addr = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chip_addr; + adap = i2c_get_adapter((chan_id + 1)); + if(!adap){ + SWPS_INFO("%s: Can not get adap!\n", __func__); + return 0; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + SWPS_INFO("%s: Can not kzalloc client!\n", __func__); + return 0; + } + client->adapter = adap; + client->addr = fake_addr; + /* Fouce move ioexp ptr to next */ + ret = i2c_smbus_read_byte_data(client, fake_offs); + SWPS_DEBUG("%s: move ioexp_ptr done. :%d\n", __func__, ret); + kfree(client); + return 1; +} + + +int +resync_channel_tier_1(void) { + + char *emsg = "ERR"; + + if (!ioexp_head_p) { + emsg = "ioexp_head_p is NULL"; + goto err_resync_ioexp_status_1; + } + /* Run all */ + if (ioexp_head_p->ioexp_id == ioexp_tail_p->ioexp_id) { + _scan_channel_tier_1_single(); + } else { + _scan_channel_tier_1(1, 0); + } + /* Check all */ + if (_scan_channel_tier_1(0, 1) < 0) { + emsg = "resync tier-1 channel fail"; + goto err_resync_ioexp_status_1; + } + return 0; + +err_resync_ioexp_status_1: + SWPS_ERR("%s: %s\n", __func__, emsg); + return -1; +} + + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.h new file mode 100644 index 000000000000..4e39fcefa620 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/io_expander.h @@ -0,0 +1,173 @@ +#ifndef IO_EXPANDER_H +#define IO_EXPANDER_H + +#include + + +/* IOEXP type define (SFP series) */ +#define IOEXP_TYPE_MAGINOLIA_NAB (10101) +#define IOEXP_TYPE_CYPRESS_NABC (10102) + +/* IOEXP type define (QSFP series) */ +#define IOEXP_TYPE_MAGINOLIA_7AB (10201) +#define IOEXP_TYPE_REDWOOD_P01P08 (10202) +#define IOEXP_TYPE_REDWOOD_P09P16 (10203) +#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204) +#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205) +#define IOEXP_TYPE_SPRUCE_7AB (10206) +#define IOEXP_TYPE_CYPRESS_7ABC (10207) +#define IOEXP_TYPE_TAHOE_5A (10208) +#define IOEXP_TYPE_TAHOE_6ABC (10209) +#define IOEXP_TYPE_SEQUOIA_NABC (10210) + +/* IOEXP mode define */ +#define IOEXP_MODE_POLLING (19000) +#define IOEXP_MODE_DIRECT (19001) + +/* IOEXP state define */ +#define STATE_IOEXP_NORMAL (0) +#define STATE_IOEXP_INIT (-1) +#define STATE_IOEXP_ABNORMAL (-2) + +/* IOEXP error code define */ +#define ERR_IOEXP_NOTSUPPORT (-100) +#define ERR_IOEXP_UNINIT (-101) +#define ERR_IOEXP_BADCONF (-102) +#define ERR_IOEXP_ABNORMAL (-103) +#define ERR_IOEXP_NOSTATE (-104) +#define ERR_IOEXP_BADINPUT (-105) +#define ERR_IOEXP_UNEXCPT (-199) + + +#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args) +#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args) +#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args) + +#ifdef DEBUG_SWPS +# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args) +#else +# define SWPS_DEBUG(fmt, args...) +#endif + + +struct ioexp_addr_s { + int chan_id; + int chip_addr; + int read_offset[8]; + int write_offset[8]; + int conf_offset[8]; + uint8_t data_default[8]; + uint8_t conf_default[8]; +}; + +struct ioexp_i2c_s { + int chip_id; + struct i2c_client *i2c_client_p; + struct ioexp_i2c_s *next; +}; + + +struct ioexp_bitmap_s { + int chip_id; /* IOEXP chip id */ + int ioexp_voffset; /* IOEXP virtual offset */ + int bit_shift; +}; + +struct ioexp_map_s { + int chip_amount; /* Number of chips that IOEXP object content */ + int data_width; /* Number of (Read/Write/Config) bytes */ + struct ioexp_addr_s *map_addr; /* Chip address info */ + struct ioexp_bitmap_s map_present[10]; /* IOEXP for SFP / QSFP */ + struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */ + struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */ + struct ioexp_bitmap_s map_hard_rs1[10]; /* IOEXP for QSFP */ +}; + +struct ioexp_data_s { + uint8_t data[8]; +}; + +struct ioexp_obj_s { + + /* ============================ + * Object public property + * ============================ + */ + int ioexp_id; + int ioexp_type; + + /* ============================ + * Object private property + * ============================ + */ + struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */ + struct ioexp_map_s *ioexp_map_p; + struct ioexp_obj_s *next; + struct ioexp_i2c_s *i2c_head_p; + struct mutex lock; + int mode; + int state; + + /* =========================================== + * Object public functions + * =========================================== + */ + int (*get_present)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset); + int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset); + int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset); + int (*get_reset)(struct ioexp_obj_s *self, int virt_offset); + int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset); + int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset); + int (*get_hard_rs1)(struct ioexp_obj_s *self, int virt_offset); + int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val); + int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val); + + /* =========================================== + * Object private functions + * =========================================== + */ + int (*init)(struct ioexp_obj_s *self); + int (*check)(struct ioexp_obj_s *self); + int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name); + int (*fsm_4_direct)(struct ioexp_obj_s* self); + int (*fsm_4_polling)(struct ioexp_obj_s* self); +}; + + +struct ioexp_obj_s* get_ioexp_obj(int ioexp_id); +int create_ioexp_obj(int ioexp_id, + int ioexp_type, + struct ioexp_addr_s *addr_map_p, + int run_mode); +int init_ioexp_objs(void); +int check_ioexp_objs(void); +void clean_ioexp_objs(void); + +void unlock_ioexp_all(void); +int lock_ioexp_all(void); + +int check_channel_tier_1(void); +int resync_channel_tier_1(void); + +/* Macro for bit control */ +#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift))) +#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift))) + + +#endif /* IO_EXPANDER_H */ + + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.c new file mode 100644 index 000000000000..0bbd78935433 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.c @@ -0,0 +1,8212 @@ +#include +#include +#include +#include +#include "io_expander.h" +#include "transceiver.h" + + +/* ========== Register EEPROM address mapping ========== + */ +struct eeprom_map_s eeprom_map_sfp = { + .addr_br =0x50, .page_br =-1, .offset_br =12, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =94, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =-1, .offset_connector =2, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =-1, .offset_diag_type =92 , .length_diag_type =1, + .addr_extbr =-1, .page_extbr =-1, .offset_extbr =-1, .length_extbr =-1, + .addr_ext_id =0x50, .page_ext_id =-1, .offset_ext_id =1, .length_ext_id =1, + .addr_id =0x50, .page_id =-1, .offset_id =0, .length_id =1, + .addr_len_sm =0x50, .page_len_sm =-1, .offset_len_sm =15, .length_len_sm =1, + .addr_len_smf =0x50, .page_len_smf =-1, .offset_len_smf =14, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =-1, .offset_len_om1 =17, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =-1, .offset_len_om2 =16, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =-1, .offset_len_om3 =19, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =-1, .offset_len_om4 =18, .length_len_om4 =1, + .addr_option =0x50, .page_option =-1, .offset_option =64, .length_option =2, + .addr_rate_id =0x50, .page_rate_id =-1, .offset_rate_id =13, .length_rate_id =1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =0x51, .page_rx_em =-1, .offset_rx_em =115, .length_rx_em =1, + .addr_rx_los =-1, .page_rx_los =-1, .offset_rx_los =-1, .length_rx_los =-1, + .addr_rx_power =0x51, .page_rx_power =-1, .offset_rx_power =104, .length_rx_power =2, + .addr_soft_rs0 =0x51, .page_soft_rs0 =-1, .offset_soft_rs0 =110, .length_soft_rs0 =1, + .addr_soft_rs1 =0x51, .page_soft_rs1 =-1, .offset_soft_rs1 =118, .length_soft_rs0 =1, + .addr_temp =0x51, .page_temp =-1, .offset_temp =96, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =-1, .offset_trancomp =3, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =-1, .offset_trancomp_ext =36, .length_trancomp_ext =1, + .addr_tx_bias =0x51, .page_tx_bias =-1, .offset_tx_bias =100, .length_tx_bias =2, + .addr_tx_disable =-1, .page_tx_disable =-1, .offset_tx_disable =-1, .length_tx_disable =-1, + .addr_tx_eq =0x51, .page_tx_eq =-1, .offset_tx_eq =114, .length_tx_eq =1, + .addr_tx_fault =-1, .page_tx_fault =-1, .offset_tx_fault =-1, .length_tx_fault =-1, + .addr_tx_power =0x51, .page_tx_power =-1, .offset_tx_power =102, .length_tx_power =2, + .addr_vendor_name =0x50, .page_vendor_name =-1, .offset_vendor_name =20, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =-1, .offset_vendor_pn =40, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =-1, .offset_vendor_rev =56, .length_vendor_rev =4, + .addr_vendor_sn =0x50, .page_vendor_sn =-1, .offset_vendor_sn =68, .length_vendor_sn =16, + .addr_voltage =0x51, .page_voltage =-1, .offset_voltage =98, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =-1, .offset_wavelength =60, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =-1, .page_cdr =-1, .offset_cdr =-1, .length_cdr =-1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =-1, .page_rx_am =-1, .offset_rx_am =-1, .length_rx_am =-1, + .addr_rx_em =-1, .page_rx_em =-1, .offset_rx_em =-1, .length_rx_em =-1, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =-1, .page_tx_eq =-1, .offset_tx_eq =-1, .length_tx_eq =-1, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + +struct eeprom_map_s eeprom_map_qsfp28 = { + .addr_br =0x50, .page_br =0, .offset_br =140, .length_br =1, + .addr_cdr =0x50, .page_cdr =-1, .offset_cdr =98, .length_cdr =1, + .addr_comp_rev =0x50, .page_comp_rev =-1, .offset_comp_rev =1, .length_comp_rev =1, + .addr_connector =0x50, .page_connector =0, .offset_connector =130, .length_connector =1, + .addr_diag_type =0x50, .page_diag_type =0, .offset_diag_type =220, .length_diag_type =1, + .addr_extbr =0x50, .page_extbr =0, .offset_extbr =222, .length_extbr =1, + .addr_ext_id =0x50, .page_ext_id =0, .offset_ext_id =129, .length_ext_id =1, + .addr_id =0x50, .page_id =0, .offset_id =128, .length_id =1, + .addr_len_sm =-1, .page_len_sm =-1, .offset_len_sm =-1, .length_len_sm =-1, + .addr_len_smf =0x50, .page_len_smf =0, .offset_len_smf =142, .length_len_smf =1, + .addr_len_om1 =0x50, .page_len_om1 =0, .offset_len_om1 =145, .length_len_om1 =1, + .addr_len_om2 =0x50, .page_len_om2 =0, .offset_len_om2 =144, .length_len_om2 =1, + .addr_len_om3 =0x50, .page_len_om3 =0, .offset_len_om3 =143, .length_len_om3 =1, + .addr_len_om4 =0x50, .page_len_om4 =0, .offset_len_om4 =146, .length_len_om4 =1, + .addr_option =0x50, .page_option =0, .offset_option =193, .length_option =3, + .addr_rate_id =-1, .page_rate_id =-1, .offset_rate_id =-1, .length_rate_id =-1, + .addr_rx_am =0x50, .page_rx_am =3, .offset_rx_am =238, .length_rx_am =2, + .addr_rx_em =0x50, .page_rx_em =3, .offset_rx_em =236, .length_rx_em =2, + .addr_rx_los =0x50, .page_rx_los =-1, .offset_rx_los =3, .length_rx_los =1, + .addr_rx_power =0x50, .page_rx_power =-1, .offset_rx_power =34, .length_rx_power =8, + .addr_soft_rs0 =-1, .page_soft_rs0 =-1, .offset_soft_rs0 =-1, .length_soft_rs0 =-1, + .addr_soft_rs1 =-1, .page_soft_rs1 =-1, .offset_soft_rs1 =-1, .length_soft_rs0 =-1, + .addr_temp =0x50, .page_temp =-1, .offset_temp =22, .length_temp =2, + .addr_trancomp =0x50, .page_trancomp =0, .offset_trancomp =131, .length_trancomp =8, + .addr_trancomp_ext =0x50, .page_trancomp_ext =0, .offset_trancomp_ext =192, .length_trancomp_ext =1, + .addr_tx_bias =0x50, .page_tx_bias =-1, .offset_tx_bias =42, .length_tx_bias =8, + .addr_tx_disable =0x50, .page_tx_disable =-1, .offset_tx_disable =86, .length_tx_disable =1, + .addr_tx_eq =0x50, .page_tx_eq =3, .offset_tx_eq =234, .length_tx_eq =2, + .addr_tx_fault =0x50, .page_tx_fault =-1, .offset_tx_fault =4, .length_tx_fault =1, + .addr_tx_power =0x50, .page_tx_power =-1, .offset_tx_power =50, .length_tx_power =8, + .addr_vendor_name =0x50, .page_vendor_name =0, .offset_vendor_name =148, .length_vendor_name =16, + .addr_vendor_pn =0x50, .page_vendor_pn =0, .offset_vendor_pn =168, .length_vendor_pn =16, + .addr_vendor_rev =0x50, .page_vendor_rev =0, .offset_vendor_rev =184, .length_vendor_rev =2, + .addr_vendor_sn =0x50, .page_vendor_sn =0, .offset_vendor_sn =196, .length_vendor_sn =16, + .addr_voltage =0x50, .page_voltage =-1, .offset_voltage =26, .length_voltage =2, + .addr_wavelength =0x50, .page_wavelength =0, .offset_wavelength =186, .length_wavelength =2, +}; + + +/* ========== Utility Functions ========== + */ +static int +get_bit(uint8_t origin_byte, int bit_shift) { + return (int)((origin_byte >> bit_shift) & 0x1); +} + +static int +transform_word_to_int(uint8_t hight_byte, + uint8_t low_byte) { + return ((((int)hight_byte) << 8) + (int)low_byte); +} + +void +alarm_msg_2_user(struct transvr_obj_s *self, + char *emsg) { + + SWPS_ERR("%s on %s.\n", emsg, self->swp_name); +} + + +/* ========== Private functions ========== + */ +static int +_reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +reload_transvr_obj(struct transvr_obj_s *self,int new_type); + +static int +_is_transvr_support_ctle(struct transvr_obj_s *self); + +static int +_transvr_init_handler(struct transvr_obj_s *self); + +int +_transvr_clean_handler(struct transvr_obj_s *self); + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self); + + +void +lock_transvr_obj(struct transvr_obj_s *self) { + + mutex_lock(&self->lock); + self->curr_page = VAL_TRANSVR_PAGE_FREE; +} + + +void +unlock_transvr_obj(struct transvr_obj_s *self) { + + self->curr_page = VAL_TRANSVR_PAGE_FREE; + mutex_unlock(&self->lock); +} + + +static int +_check_by_mode(struct transvr_obj_s *self, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + char *caller_name){ + + int return_val = ERR_TRANSVR_UNEXCPT; + + switch (self->mode){ + case TRANSVR_MODE_POLLING: + switch (self->state){ + case STATE_TRANSVR_CONNECTED: + goto ok_check_by_mode_1; + case STATE_TRANSVR_NEW: + case STATE_TRANSVR_INIT: + return ERR_TRANSVR_UNINIT; + case STATE_TRANSVR_DISCONNECTED: + return ERR_TRANSVR_UNPLUGGED; + case STATE_TRANSVR_UNEXCEPTED: + return ERR_TRANSVR_ABNORMAL; + case STATE_TRANSVR_ISOLATED: + return ERR_TRNASVR_BE_ISOLATED; + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + + case TRANSVR_MODE_DIRECT: + return_val = self->fsm_4_direct(self, caller_name); + if (return_val < 0){ + return return_val; + } + goto ok_check_by_mode_1; + + default: + goto err_check_by_mode_1; + } + goto ok_check_by_mode_1; + +ok_check_by_mode_1: + return attr_update_func(self, 0); + +err_check_by_mode_1: + SWPS_INFO("_check_by_mode: mode:%d state:%d\n", self->mode, self->state); + return ERR_TRANSVR_UNEXCPT; +} + + +static void +_transvr_clean_retry(struct transvr_obj_s *self) { + self->retry = 0; +} + + +static int +_transvr_handle_retry(struct transvr_obj_s *self, int retry) { + /* Return: 0: keep retry + * -1: stop retry + */ + if (self->retry == 0) { + self->retry = retry; + } + self->retry -= 1; + if (self->retry <= 0) { + _transvr_clean_retry(self); + return -1; + } + return 0; +} + + +static int +_common_setup_page(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int show_e) { + /* return: + * 0 : OK + * -1 : EEPROM settings incorrect + * -2 : I2C R/W failure + * -3 : Undefined case + */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Check */ + if ((addr < 0) || (offset < 0) || (len < 0)) { + emsg = "EEPROM settings incorrect"; + retval = -1; + goto err_common_setup_page; + } + /* Case1: continue access */ + if ((self->i2c_client_p->addr == addr) && + (self->curr_page == page)) { + return 0; + } + self->i2c_client_p->addr = addr; + /* Case2: select lower page */ + if (page == -1) { + self->curr_page = page; + return 0; + } + /* Case3: select upper page */ + if (page >= 0) { + goto upper_common_setup_page; + } + /* Unexpected case */ + show_e = 1; + emsg = "Unexpected case"; + retval = -3; + goto err_common_setup_page; + +upper_common_setup_page: + if (i2c_smbus_write_byte_data(self->i2c_client_p, + VAL_TRANSVR_PAGE_SELECT_OFFSET, + page) < 0) { + emsg = "I2C R/W failure"; + retval = -2; + goto err_common_setup_page; + } + self->curr_page = page; + mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY); + return 0; + +err_common_setup_page: + if (show_e) { + SWPS_INFO("%s: %s", __func__, emsg); + SWPS_INFO("%s: :0x%02x :%d :%d :%d\n", + __func__, addr, page, offset, len); + } + return retval; +} + +/* +static int +_common_setup_password(struct transvr_obj_s *self, + int addr, + int page, + int offs, + uint8_t pwd[4], + int show_e) { + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, 4, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_setup_password; + } + for (i=0; i<4; i++) { + err = i2c_smbus_write_byte_data(self->i2c_client_p, + (offs + i), + pwd[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_setup_password; + } + } + return 0; + +err_common_setup_password: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} +*/ + +static int +_common_update_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + uint8_t *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_uint8_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_uint8_attr; + } + buf[i] = err; + } + return 0; + +err_common_update_uint8_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_int_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + int *buf, + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_int_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_int_attr; + } + buf[i] = (int)err; + } + return 0; + +err_common_update_int_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = DEBUG_TRANSVR_INT_VAL; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_string_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + int len, + char buf[], + char *caller, + int show_e){ + + int i; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_update_string_attr; + } + for (i=0; ii2c_client_p, (offset + i)); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_update_string_attr; + } + buf[i] = (char)err; + } + return 0; + +err_common_update_string_attr: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + buf[0] = 'e'; + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_attr(struct transvr_obj_s *self, + int addr, + int page, + int offset, + uint8_t update, + uint8_t *buf, + char *caller, + int show_e){ + int len = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + if ((*buf) == update){ + return 0; + } + err = _common_setup_page(self, addr, page, offset, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + err = i2c_smbus_write_byte_data(self->i2c_client_p, + offset, + update); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + (*buf) = update; + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d\n", + __func__, emsg, caller, err); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_set_uint8_array(struct transvr_obj_s *self, + int addr, + int page, + int offs, + int len, + uint8_t update[], + uint8_t buf[], + char *caller, + int show_e){ + int i = 0; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + err = _common_setup_page(self, addr, page, offs, len, show_e); + if (err < 0){ + emsg = "setup EEPROM page fail"; + goto err_common_set_uint8_attr_1; + } + for (i=0; ii2c_client_p, + (offs + i), + update[i]); + if (err < 0){ + emsg = "I2C R/W fail!"; + goto err_common_set_uint8_attr_1; + } + buf[i] = update[i]; + } + return 0; + +err_common_set_uint8_attr_1: + if (show_e) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, emsg, caller, err, i); + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +static int +_common_update_attr_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_id, + self->eeprom_map_p->page_id, + self->eeprom_map_p->offset_id, + self->eeprom_map_p->length_id, + &(self->id), + "_common_update_attr_id", + show_err); +} + + +static int +_common_update_attr_extended_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_ext_id, + self->eeprom_map_p->page_ext_id, + self->eeprom_map_p->offset_ext_id, + self->eeprom_map_p->length_ext_id, + &(self->ext_id), + "_common_update_attr_extended_id", + show_err); +} + + +static int +_common_update_attr_connector(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_connector, + self->eeprom_map_p->page_connector, + self->eeprom_map_p->offset_connector, + self->eeprom_map_p->length_connector, + &(self->connector), + "_common_update_attr_connector", + show_err); +} + + +static int +_common_update_attr_transvr_comp(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp, + self->eeprom_map_p->page_trancomp, + self->eeprom_map_p->offset_trancomp, + self->eeprom_map_p->length_trancomp, + self->transvr_comp, + "_common_update_attr_transvr_comp", + show_err); +} + + +static int +_common_update_attr_transvr_comp_ext(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_trancomp_ext, + self->eeprom_map_p->page_trancomp_ext, + self->eeprom_map_p->offset_trancomp_ext, + self->eeprom_map_p->length_trancomp_ext, + &(self->transvr_comp_ext), + "_common_update_attr_transvr_comp_ext", + show_err); +} + + +static int +_common_update_attr_vendor_name(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_name, + self->eeprom_map_p->page_vendor_name, + self->eeprom_map_p->offset_vendor_name, + self->eeprom_map_p->length_vendor_name, + self->vendor_name, + "_common_update_attr_vendor_name", + show_err); +} + + +static int +_common_update_attr_vendor_pn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_pn, + self->eeprom_map_p->page_vendor_pn, + self->eeprom_map_p->offset_vendor_pn, + self->eeprom_map_p->length_vendor_pn, + self->vendor_pn, + "_common_update_attr_vendor_pn", + show_err); +} + + +static int +_common_update_attr_vendor_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_rev, + self->eeprom_map_p->page_vendor_rev, + self->eeprom_map_p->offset_vendor_rev, + self->eeprom_map_p->length_vendor_rev, + self->vendor_rev, + "_common_update_attr_vendor_rev", + show_err); +} + + +static int +_common_update_attr_vendor_sn(struct transvr_obj_s *self, + int show_err){ + return _common_update_string_attr(self, + self->eeprom_map_p->addr_vendor_sn, + self->eeprom_map_p->page_vendor_sn, + self->eeprom_map_p->offset_vendor_sn, + self->eeprom_map_p->length_vendor_sn, + self->vendor_sn, + "_common_update_attr_vendor_sn", + show_err); +} + + +static int +_common_update_attr_br(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_br, + self->eeprom_map_p->page_br, + self->eeprom_map_p->offset_br, + self->eeprom_map_p->length_br, + &(self->br), + "_common_update_attr_br", + show_err); +} + + +static int +_common_update_attr_len_smf(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_smf, + self->eeprom_map_p->page_len_smf, + self->eeprom_map_p->offset_len_smf, + self->eeprom_map_p->length_len_smf, + &(self->len_smf), + "_common_update_attr_len_smf", + show_err); +} + + +static int +_common_update_attr_len_om1(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om1, + self->eeprom_map_p->page_len_om1, + self->eeprom_map_p->offset_len_om1, + self->eeprom_map_p->length_len_om1, + &(self->len_om1), + "_common_update_attr_len_om1", + show_err); +} + +static int +_common_update_attr_len_om2(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om2, + self->eeprom_map_p->page_len_om2, + self->eeprom_map_p->offset_len_om2, + self->eeprom_map_p->length_len_om2, + &(self->len_om2), + "_common_update_attr_len_om2", + show_err); +} + +static int +_common_update_attr_len_om3(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om3, + self->eeprom_map_p->page_len_om3, + self->eeprom_map_p->offset_len_om3, + self->eeprom_map_p->length_len_om3, + &(self->len_om3), + "_common_update_attr_len_om3", + show_err); +} + + +static int +_common_update_attr_len_om4(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_om4, + self->eeprom_map_p->page_len_om4, + self->eeprom_map_p->offset_len_om4, + self->eeprom_map_p->length_len_om4, + &(self->len_om4), + "_common_update_attr_len_om4", + show_err); +} + + +static int +_common_update_attr_option(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_option, + self->eeprom_map_p->page_option, + self->eeprom_map_p->offset_option, + self->eeprom_map_p->length_option, + self->option, + "_common_update_attr_option", + show_err); +} + + +static int +_common_update_attr_comp_rev(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_comp_rev, + self->eeprom_map_p->page_comp_rev, + self->eeprom_map_p->offset_comp_rev, + self->eeprom_map_p->length_comp_rev, + &(self->comp_rev), + "_common_update_attr_comp_rev", + show_err); +} + + +static int +_common_update_attr_diag_type(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_diag_type, + self->eeprom_map_p->page_diag_type, + self->eeprom_map_p->offset_diag_type, + self->eeprom_map_p->length_diag_type, + &(self->diag_type), + "_common_update_attr_diag_type", + show_err); +} + + +static int +_common_update_attr_wavelength(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_wavelength, + self->eeprom_map_p->page_wavelength, + self->eeprom_map_p->offset_wavelength, + self->eeprom_map_p->length_wavelength, + self->wavelength, + "_common_update_attr_wavelength", + show_err); +} + + +int +_common_get_option_value(struct transvr_obj_s *self, + int offset, + int bit_shift) { + /* SFP: + * - option[0] = A0h / 64 + * - option[1] = A0h / 65 + * QSFP: + * - option[0] = 00h / 193 + * - option[1] = 00h / 194 + * - option[2] = 00h / 195 + */ + return (self->option[offset] & (1 << bit_shift)); +} + + +static int +_sfp_update_attr_len_sm(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_len_sm, + self->eeprom_map_p->page_len_sm, + self->eeprom_map_p->offset_len_sm, + self->eeprom_map_p->length_len_sm, + &(self->len_sm), + "_common_update_attr_len_sm", + show_err); +} + + +static int +_sfp_update_attr_rate_id(struct transvr_obj_s *self, + int show_err){ + return _common_update_int_attr(self, + self->eeprom_map_p->addr_rate_id, + self->eeprom_map_p->page_rate_id, + self->eeprom_map_p->offset_rate_id, + self->eeprom_map_p->length_rate_id, + &(self->rate_id), + "_sfp_update_attr_rate_id", + show_err); +} + + +static int +_sfp_update_attr_soft_rs0(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + self->eeprom_map_p->length_soft_rs0, + &(self->soft_rs0), + "_sfp_update_attr_soft_rs0", + show_err); +} + + +static int +_sfp_update_attr_soft_rs1(struct transvr_obj_s *self, + int show_err){ + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + self->eeprom_map_p->length_soft_rs1, + &(self->soft_rs1), + "_sfp_update_attr_soft_rs1", + show_err); +} + + +int +_sfp_is_diag_support(struct transvr_obj_s *self){ + + uint8_t bit_mask = 0xC0; /* 1100 0000 */ + uint8_t en_val = 0x40; /* 0100 0000 */ + uint8_t checkval = (self->diag_type & bit_mask); + + if (checkval == en_val) { + return 1; + } + return 0; +} + + +static int +_sfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_sfp_update_attr_curr_temp", + show_err); +} + + +static int +_sfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_sfp_update_attr_curr_voltage", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_sfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_sfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_sfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_sfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + + if (!(_sfp_is_diag_support(self))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_sfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_sfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_sfp_update_attr_rx_em", + show_err); +} + + +static int +_sfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_sfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_cdr(struct transvr_obj_s *self, + int show_err){ + if (self->type != TRANSVR_TYPE_QSFP_28){ + self->cdr = DEBUG_TRANSVR_HEX_VAL; + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + self->eeprom_map_p->length_cdr, + &(self->cdr), + "_common_update_attr_cdr", + show_err); +} + + +static int +_qsfg_update_attr_extbr(struct transvr_obj_s *self, + int show_err) { + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_extbr, + self->eeprom_map_p->page_extbr, + self->eeprom_map_p->offset_extbr, + self->eeprom_map_p->length_extbr, + &(self->extbr), + "_common_update_attr_extbr", + show_err); +} + + +static int +_qsfp_is_diag_support(struct transvr_obj_s *self, + int diag_type) { + /* Input Parm: diag_type + * => 1 : temperature + * => 2 : voltage + * => 3 : tx relate + * => 4 : rx relate + */ + uint8_t mask_b2 = 0x04; /* 0000 0100 */ + uint8_t mask_b3 = 0x08; /* 0000 1000 */ + + switch (diag_type) { + case 1: /* temperature */ + case 2: /* voltage */ + /* Direct access target, because of spec not defined */ + return 1; + case 3: + case 4: + /* [Note] + * Due to lot of transceiver vendor defined it not rigorously and + * consider of general support, we seem it as supported if there + * are bit-2 OR bit-3 defined by transceiver vendor. + */ + if ( ((self->diag_type & mask_b2) == mask_b2 ) || + ((self->diag_type & mask_b3) == mask_b3 ) ){ + return 1; + } + return 0; + default: + SWPS_INFO("%s: undefined diag_type:%d\n", + __func__, diag_type); + break; + } + return 0; +} + + +int +_qsfp_is_implement_tx_disable(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-4 + */ + int byte = 2; + int bit = 4; + return _common_get_option_value(self, byte, bit); +} + + +int +_qsfp_is_implement_tx_fault(struct transvr_obj_s *self) { + /* + * 00h / Byte-195 / Bit-3 + */ + int byte = 2; + int bit = 3; + return _common_get_option_value(self, byte, bit); +} + + +static int +_qsfp_update_attr_curr_temp(struct transvr_obj_s *self, + int show_err){ + int diag_type = 1; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_temp, + self->eeprom_map_p->page_temp, + self->eeprom_map_p->offset_temp, + self->eeprom_map_p->length_temp, + self->curr_temp, + "_qsfp_update_attr_curr_temp", + show_err); +} + + +static int +_qsfp_update_attr_curr_voltage(struct transvr_obj_s *self, + int show_err){ + int diag_type = 2; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_voltage, + self->eeprom_map_p->page_voltage, + self->eeprom_map_p->offset_voltage, + self->eeprom_map_p->length_voltage, + self->curr_voltage, + "_qsfp_update_attr_curr_voltage", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_bias(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_bias, + self->eeprom_map_p->page_tx_bias, + self->eeprom_map_p->offset_tx_bias, + self->eeprom_map_p->length_tx_bias, + self->curr_tx_bias, + "_qsfp_update_attr_curr_tx_bias", + show_err); +} + + +static int +_qsfp_update_attr_curr_tx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 3; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_power, + self->eeprom_map_p->page_tx_power, + self->eeprom_map_p->offset_tx_power, + self->eeprom_map_p->length_tx_power, + self->curr_tx_power, + "_qsfp_update_attr_curr_tx_power", + show_err); +} + + +static int +_qsfp_update_attr_curr_rx_power(struct transvr_obj_s *self, + int show_err){ + int diag_type = 4; + + if (!(_qsfp_is_diag_support(self, diag_type))) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_power, + self->eeprom_map_p->page_rx_power, + self->eeprom_map_p->offset_rx_power, + self->eeprom_map_p->length_rx_power, + self->curr_rx_power, + "_qsfp_update_attr_curr_rx_power", + show_err); +} + + +static int +_qsfp_update_attr_soft_rx_los(struct transvr_obj_s *self, + int show_err){ + + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_los, + self->eeprom_map_p->page_rx_los, + self->eeprom_map_p->offset_rx_los, + self->eeprom_map_p->length_rx_los, + &(self->rx_los), + "_qsfp_update_attr_soft_rx_los", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_disable(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_disable(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_update_attr_soft_tx_disable", + show_err); +} + + +static int +_qsfp_update_attr_soft_tx_fault(struct transvr_obj_s *self, + int show_err){ + + if (!_qsfp_is_implement_tx_fault(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_fault, + self->eeprom_map_p->page_tx_fault, + self->eeprom_map_p->offset_tx_fault, + self->eeprom_map_p->length_tx_fault, + &(self->tx_fault), + "_qsfp_update_attr_soft_tx_fault", + show_err); +} + + +static int +_qsfp_update_attr_tx_eq(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + self->tx_eq, + "_qsfp_update_attr_tx_eq", + show_err); +} + + +static int +_qsfp_update_attr_rx_am(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + self->rx_am, + "_qsfp_update_attr_rx_am", + show_err); +} + + +static int +_qsfp_update_attr_rx_em(struct transvr_obj_s *self, + int show_err){ + + if (!_is_transvr_support_ctle(self)) { + return ERR_TRANSVR_NOTSUPPORT; + } + return _common_update_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + self->rx_em, + "_qsfp_update_attr_rx_em", + show_err); +} + + +int +_common_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = "err"; + + if (_common_update_attr_id(self, show_err) < 0) { + err_str = "_common_update_attr_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_extended_id(self, show_err) < 0) { + err_str = "_common_update_attr_extended_id"; + goto err_common_update_attr_all; + } + if (_common_update_attr_connector(self, show_err) < 0) { + err_str = "_common_update_attr_connector"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp"; + goto err_common_update_attr_all; + } + if (_common_update_attr_transvr_comp_ext(self, show_err) < 0) { + err_str = "_common_update_attr_transvr_comp_ext"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_name(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_name"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_pn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_pn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_rev(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_vendor_sn(self, show_err) < 0) { + err_str = "_common_update_attr_vendor_sn"; + goto err_common_update_attr_all; + } + if (_common_update_attr_br(self, show_err) < 0) { + err_str = "_common_update_attr_br"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_smf(self, show_err) < 0) { + err_str = "_common_update_attr_len_smf"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om1(self, show_err) < 0) { + err_str = "_common_update_attr_len_om1"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om2(self, show_err) < 0) { + err_str = "_common_update_attr_len_om2"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om3(self, show_err) < 0) { + err_str = "_common_update_attr_len_om3"; + goto err_common_update_attr_all; + } + if (_common_update_attr_len_om4(self, show_err) < 0) { + err_str = "_common_update_attr_len_om4"; + goto err_common_update_attr_all; + } + if (_common_update_attr_option(self, show_err) < 0) { + err_str = "_common_update_attr_option"; + goto err_common_update_attr_all; + } + if (_common_update_attr_comp_rev(self, show_err) < 0) { + err_str = "_common_update_attr_comp_rev"; + goto err_common_update_attr_all; + } + if (_common_update_attr_diag_type(self, show_err) < 0) { + err_str = "_common_update_attr_diag_type"; + goto err_common_update_attr_all; + } + if (_common_update_attr_wavelength(self, show_err) < 0) { + err_str = "_common_update_attr_wavelength"; + goto err_common_update_attr_all; + } + return 0; + +err_common_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_sfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_len_sm(self, show_err) < 0) { + err_str = "_sfp_update_attr_len_sm"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_rate_id(self, show_err) < 0) { + err_str = "_sfp_update_attr_rate_id"; + goto err_sfp_update_attr_all; + } + if ((self->rate_id) > 0) { + if (_sfp_update_attr_soft_rs0(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs0"; + goto err_sfp_update_attr_all; + } + if (_sfp_update_attr_soft_rs1(self, show_err) < 0) { + err_str = "_sfp_update_attr_soft_rs1"; + goto err_sfp_update_attr_all; + } + } + return 0; + +err_sfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +int +_qsfp_update_attr_all(struct transvr_obj_s *self, + int show_err){ + + char *err_str = DEBUG_TRANSVR_STR_VAL; + + if (_common_update_attr_all(self, show_err) < 0){ + err_str = "_common_update_attr_all"; + goto err_qsfp_update_attr_all; + } + if (_qsfg_update_attr_extbr(self, show_err) < 0) { + err_str = "_qsfg_update_attr_extbr"; + goto err_qsfp_update_attr_all; + } + if (self->type == TRANSVR_TYPE_QSFP_28) { + if (_qsfp_update_attr_cdr(self, 1) < 0) { + err_str = "_qsfp_update_attr_cdr"; + goto err_qsfp_update_attr_all; + } + } + return 0; + +err_qsfp_update_attr_all: + if (show_err){ + SWPS_INFO("%s: fail at:%s :%s\n", __func__, err_str, self->swp_name); + } + return -1; +} + + +/* ========== Object functions for common type ========== + */ +int +_common_count_temp(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + int sign = 0; + int high = 0; + int low = 0; + int lmax = 8; + + /* Count high */ + sign = get_bit(high_byte,7); + SWP_BIT_CLEAR(high_byte, 7); + high = (int)high_byte; + if (sign == 1) { + high = 0 - high; + } + /* Count low */ + low = (get_bit(low_byte, 7) * 500); + low += (get_bit(low_byte, 6) * 250); + low += (get_bit(low_byte, 5) * 125); + low += (get_bit(low_byte, 4) * 62); + low = (low / 100); + /* Integrate High and Low */ + return snprintf(buf_p, lmax, "%d.%d\n", high, low); +} + + +int +_common_count_voltage(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note]: + * Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts. Practical + * considerations to be defined by transceiver manufacturer will + * tend to limit the actual bounds of the supply voltage measurement. + * Accuracy is vendor specific but must be better than 3% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. Note that in some transceivers, transmitter supply + * voltage and receiver supply voltage are isolated. In that case, + * only one supply is monitored. Refer to the device specification + * for more detail. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 100 uV (1mV=1000uV) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 Volt */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_tx_bias(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 2 uA (1mA=1000uA) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total*2) / 1000); + val_f = (((total*2) - (val_i*1000)) / 100); + /* Return Unit: 1 mA */ + return snprintf(buf_p, lmax, "%d.%01d\n", val_i, val_f); +} + + +int +_common_count_tx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_rx_power(uint8_t high_byte, + uint8_t low_byte, + char *buf_p) { + /* [Note] + * Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + int total = 0; + int lmax = 8; + int val_i = 0; + int val_f = 0; + /* unit: 0.1 uW (1mW=1000uW) */ + total = transform_word_to_int(high_byte, low_byte); + val_i = ((total/10) / 1000); + val_f = ((total/10) - (val_i*1000)); + /* Return Unit: 1 mW */ + return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f); +} + + +int +_common_count_wavelength(struct transvr_obj_s *self, + uint8_t high_byte, + uint8_t low_byte) { + /* [Note] + * SFP : uint 1 um. + * QSFP: unit 0.05 um. + */ + int total = 0; + + total = transform_word_to_int(high_byte, low_byte); + switch (self->type) { + case TRANSVR_TYPE_SFP: + return total; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + return (total/20); + + default: + break; + } + return ERR_TRANSVR_UNDEFINED; +} + + +int +common_get_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_id, + "common_get_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->id; +} + + +int +common_get_ext_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "common_get_ext_id"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->ext_id; +} + + +int +common_get_connector(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_connector, + "common_get_connector"); + if (err_code < 0){ + return err_code; + } + /* Transform to INT to show error case */ + return (int)self->connector; +} + + +int +common_get_vendor_name(struct transvr_obj_s *self, char *buf){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_name, + "common_get_vendor_name"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name); +} + + +int +common_get_vendor_pn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_pn, + "common_get_vendor_pn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn); +} + + +int +common_get_vendor_rev(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_rev, + "common_get_vendor_rev"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev); +} + + +int +common_get_vendor_sn(struct transvr_obj_s *self, char *buf) { + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); + } + err = _check_by_mode(self, + &_common_update_attr_vendor_sn, + "common_get_vendor_sn"); + memset(buf, 0, LEN_TRANSVR_M_STR); + if (err < 0){ + return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err); + } + return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn); +} + + +int +common_get_br(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return (int)self->br; + } + err = _check_by_mode(self, + &_common_update_attr_br, + "common_get_br"); + if (err < 0){ + return err; + } + /* Transform to INT to show error case */ + return (int)self->br; +} + + +int +common_get_len_smf(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_smf; + } + err = _check_by_mode(self, + &_common_update_attr_len_smf, + "common_get_len_smf"); + if (err < 0){ + return err; + } + return self->len_smf; +} + + +int +common_get_len_om1(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om1; + } + err = _check_by_mode(self, + &_common_update_attr_len_om1, + "common_get_len_om1"); + if (err < 0){ + return err; + } + return self->len_om1; +} + + +int +common_get_len_om2(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om2; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om2, + "common_get_len_om2"); + if (err < 0){ + return err; + } + return self->len_om2; +} + + +int +common_get_len_om3(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om3; + } + + err = _check_by_mode(self, + &_common_update_attr_len_om3, + "common_get_len_om3"); + if (err < 0){ + return err; + } + return self->len_om3; +} + + +int +common_get_len_om4(struct transvr_obj_s *self){ + + int err = DEBUG_TRANSVR_INT_VAL; + + if (self->state == STATE_TRANSVR_CONNECTED && + self->mode == TRANSVR_MODE_POLLING && + TRANSVR_INFO_CACHE_ENABLE) { + return self->len_om4; + } + err = _check_by_mode(self, + &_common_update_attr_len_om4, + "common_get_len_om4"); + if (err < 0){ + return err; + } + return self->len_om4; +} + + +int +common_get_comp_extended(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp_ext, + "common_get_comp_extended"); + if (err_code < 0){ + return err_code; + } + return self->transvr_comp_ext; +} + + +int +common_get_comp_rev(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_comp_rev, + "common_get_comp_rev"); + if (err_code < 0){ + return err_code; + } + return self->comp_rev; +} + + +int +common_get_info(struct transvr_obj_s *self){ + + if (self->state != STATE_TRANSVR_CONNECTED) { + return self->state; + } + return self->info; +} + + +int +_common_get_if_lane(struct transvr_obj_s *self, + char *result){ + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_M_STR); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + memset(tmp_str, 0, LEN_TRANSVR_M_STR); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_M_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_M_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_M_STR); + } + if (i == 0) { + return EVENT_TRANSVR_TASK_FAIL; + } + return 0; +} + + +int +common_get_if_lane(struct transvr_obj_s *self, + char *buf_p){ + + char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL; + + if (self->ioexp_obj_p->state != STATE_IOEXP_NORMAL) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n", ERR_TRANSVR_ABNORMAL); + } + if (_common_get_if_lane(self, tmp_str) < 0) { + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n" ,ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, LEN_TRANSVR_M_STR, "%s\n" ,tmp_str); +} + + +int +sfp_get_len_sm(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_len_sm, + "sfp_get_len_sm"); + if (err_code < 0){ + return err_code; + } + return self->len_sm; +} + + +int +sfp_get_rate_id(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_sfp_update_attr_rate_id, + "sfp_get_rate_id"); + if (err_code < 0){ + return err_code; + } + return self->rate_id; +} + + +int +sfp_get_soft_rs0(struct transvr_obj_s *self){ + /* Note: + * SFP Soft Rate_Select Select [aka. "RS(0)"] address + * A2h, offset: 110, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs0, + "sfp_get_soft_rs0"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs0 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_soft_rs1(struct transvr_obj_s *self){ + /* Note: + * SFP Soft RS(1) Select address + * A2h, offset: 118, bit 3 (begin form 0) + */ + int err_code = DEBUG_TRANSVR_INT_VAL; + int bit_shift = 3; + uint8_t result = 0x00; + uint8_t bitmask = (1 << bit_shift); + + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + return ERR_TRANSVR_NOTSUPPORT; + } + /* Update and check */ + err_code = _check_by_mode(self, + &_sfp_update_attr_soft_rs1, + "sfp_get_soft_rs1"); + if (err_code <0){ + return err_code; + } + result = (self->soft_rs1 & bitmask); + if (result == bitmask) { + return 1; + } + if (result == 0) { + return 0; + } + return ERR_TRANSVR_UNEXCPT; +} + + +int +sfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_temp, + "sfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +sfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_voltage, + "sfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +sfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_bias, + "sfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _common_count_tx_bias(self->curr_tx_bias[0], + self->curr_tx_bias[1], + buf_p); +} + + +int +sfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_tx_power, + "sfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_tx_power(self->curr_tx_power[0], + self->curr_tx_power[1], + buf_p); +} + + +int +sfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_sfp_update_attr_curr_rx_power, + "sfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _common_count_rx_power(self->curr_rx_power[0], + self->curr_rx_power[0], + buf_p); +} + + +int +sfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->rx_em[0]); +} + + +int +sfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x\n", self->tx_eq[0]); +} + + +int +_sfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: A0h / 36 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +__sfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* SFP Specification Compliance: A0h / 3-10 + * transvr_comp[0-7] = 3 - 10 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_get_comp_10g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[0] = address A0h / 3 + * + * 3 7: 10G Base-ER + * 3 6: 10GBASE-LRM + * 3 5: 10GBASE-LR + * 3 4: 10GBASE-SR + */ + int bitmask = 0xf0; /* 11110000 */ + return (__sfp_get_comp_attr(self, 0) & bitmask); +} + + +int +_sfp_get_comp_1g_eth_comp(struct transvr_obj_s *self) { + /* transvr_comp[3] = address A0h / 6 + * + * 6 7: BASE-PX *3 + * 6 6: BASE-BX10 *3 + * 6 5: 100BASE-FX + * 6 4: 100BASE-LX/LX10 + * 6 3: 1000BASE-T + * 6 2: 1000BASE-CX + * 6 1: 1000BASE-LX *3 + * 6 0: 1000BASE-SX + */ + return __sfp_get_comp_attr(self, 3); +} + + +int +_sfp_get_cable_tech(struct transvr_obj_s *self) { + /* transvr_comp[5] = address A0h / 8 + * + * 8 3: Active Cable *8 + * 8 2: Passive Cable *8 + */ + int bitmask = 0x0c; /* 00001100 */ + return (__sfp_get_comp_attr(self, 5) & bitmask); +} + + +int +sfp_get_comp_eth_1(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_1"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_1g_eth_comp(self); +} + + +int +sfp_get_comp_eth_10(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "sfp_get_comp_eth_10"); + if (err_code < 0){ + return err_code; + } + return _sfp_get_comp_10g_eth_comp(self); +} + + +int +_sfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: A0h / 2 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Note] Optical and Cable Variants Specification Compliance (SFF-8472) + * [Addr] A0h, Bytes 60-61 + * [Note] For optical variants, as defined by having zero's in A0h Byte 8 + * bits 2 and 3, Bytes 60 and 61 denote nominal transmitter output + * wavelength at room temperature. 16 bit value with byte 60 as high + * order byte and byte 61 as low order byte. The laser wavelength is + * equal to the 16 bit integer value in nm. This field allows the user + * to read the laser wavelength directly, so it is not necessary to + * infer it from the Transceiver Codes A0h Bytes 3 to 10 (see Table + * 5-3). This also allows specification of wavelengths not covered + * in the Transceiver Codes, such as those used in coarse WDM systems. + * + * For passive and active cable variants, a value of 00h for both A0h + * Byte 60 and Byte 61 denotes laser wavelength or cable specification + * compliance is unspecified. + */ + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +int +__qsfp_get_power_cls(struct transvr_obj_s *self, + int direct_access){ + + int err_code; + uint8_t detect_val; + + /* Detect and Update power class attribute */ + if (direct_access){ + err_code = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_power_cls"); + } else { + err_code = self->ext_id; + } + if (err_code <0){ + return err_code; + } + if (err_code == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data */ + detect_val = self->ext_id; + SWP_BIT_CLEAR(detect_val, 2); /* Bit2: CDR RX present */ + SWP_BIT_CLEAR(detect_val, 3); /* Bit3: CDR TX present */ + SWP_BIT_CLEAR(detect_val, 4); /* Bit4: CLEI present */ + SWP_BIT_CLEAR(detect_val, 5); /* Bit5: reserved */ + /* Identify power class */ + switch (detect_val) { + case 0: /* Class_1: 00000000 */ + return 1; + case 64: /* Class_2: 01000000 */ + return 2; + case 128: /* Class_3: 10000000 */ + return 3; + case 192: /* Class_4: 11000000 */ + return 4; + case 1: /* Class_5: 00000001 */ + case 193: /* Class_5: 11000001 */ + return 5; + case 2: /* Class_6: 00000010 */ + case 194: /* Class_6: 11000010 */ + return 6; + case 3: /* Class_7: 00000011 */ + case 195: /* Class_7: 11000011 */ + return 7; + default: + break; + } + SWPS_INFO("%s: Detect undefined power class:%d\n", __func__, detect_val); + return ERR_TRANSVR_UNDEFINED; +} + + +int +qsfp_get_power_cls(struct transvr_obj_s *self) { + return __qsfp_get_power_cls(self, 1); +} + + +int +__qsfp_get_cdr_present(struct transvr_obj_s *self, + int direct_access){ + + int retval; + int BIT_SHIFT = 2; + int BIT_MASK = 0x3; + + /* Detect and Update power class attribute */ + if (direct_access) { + retval = _check_by_mode(self, + &_common_update_attr_extended_id, + "__qsfp_get_cdr_present"); + if (retval < 0){ + return retval; + } + } + retval = self->ext_id; + if (retval == DEBUG_TRANSVR_HEX_VAL){ + return ERR_TRANSVR_UPDATE_FAIL; + } + /* Clean data and return */ + return (int)(retval >> BIT_SHIFT & BIT_MASK); +} + + +int +qsfp_get_cdr_present(struct transvr_obj_s *self) { + return __qsfp_get_cdr_present(self, 1); +} + + +int +qsfp_get_cdr(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + "qsfp_get_cdr"); + if (err_code <0){ + return err_code; + } + + return self->cdr; +} + + +int +__qsfp_get_comp_attr(struct transvr_obj_s *self, + int array_offset) { + /* QSFP Specification Compliance: 00h / 131-138 + * transvr_comp[0-7] = 131 - 138 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp[array_offset]); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_get_comp_10_40_100_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[0] = address 00h / 131 + * + * 131 7: Extended: See section 6.3.23. The Extended Specification Compliance + * Codes are maintained in the Transceiver Management section of SFF- + * 8024. + * 131 6: 10GBASE-LRM + * 131 5: 10GBASE-LR + * 131 4: 10GBASE-SR + * 131 3: 40GBASE-CR4 + * 131 2: 40GBASE-SR4 + * 131 1: 40GBASE-LR4 + * 131 0: 40G Active Cable (XLPPI) + */ + return __qsfp_get_comp_attr(self, 0); +} + + +int +_qsfp_get_comp_sonet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 132 7-3: Reserved + * 132 2: OC 48, long reach + * 132 1: OC 48, intermediate reach + * 132 0: OC 48 short reach + */ + return __qsfp_get_comp_attr(self, 1); +} + + +int +_qsfp_get_comp_sas_sata(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 133 7: SAS 24.0 Gb/s + * 133 6: SAS 12.0 Gb/s + * 133 5: SAS 6.0 Gb/s + * 133 4: SAS 3.0 Gb/s + * 133 3-0: Reserved + */ + return __qsfp_get_comp_attr(self, 2); +} + + +int +_qsfp_get_comp_ethernet(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 134 7-4: Reserved + * 134 3: 1000BASE-T + * 134 2: 1000BASE-CX + * 134 1: 1000BASE-LX + * 134 0: 1000BASE-SX + */ + return __qsfp_get_comp_attr(self, 3); +} + + +int +_qsfp_get_comp_fc_link_length(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 7: Very long distance (V) + * 135 6: Short distance (S) + * 135 5: Intermediate distance (I) + * 135 4: Long distance (L) + * 135 3: Medium (M) + */ + int mask = 0xFC; /* 11111100 */ + return (__qsfp_get_comp_attr(self, 4) & mask); +} + + +int +_qsfp_get_comp_fc_trans_tech(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 135 2: Reserved + * 135 1: Longwave laser (LC) + * 135 0: Electrical inter-enclosure (EL) + * + * 136 7: Electrical intra-enclosure + * 136 6: Shortwave laser w/o OFC (SN) + * 136 5: Shortwave laser w OFC (SL) + * 136 4: Longwave Laser (LL) + * 136 3-0: Reserved + * + * return value = [bit 8-15:addr 135][bit 0-7:addr 136] + */ + int mask_135 = 7; /* 00000111 */ + int val_135 = (__qsfp_get_comp_attr(self, 4) & mask_135); + int val_136 = __qsfp_get_comp_attr(self, 5); + return ((val_135 << 7) + val_136); +} + + +int +_qsfp_get_comp_fc_trans_media(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 137 7: Twin Axial Pair (TW) + * 137 6: Shielded Twisted Pair (TP) + * 137 5: Miniature Coax (MI) + * 137 4: Video Coax (TV) + * 137 3: Multi-mode 62.5 m (M6) + * 137 2: Multi-mode 50 m (M5) + * 137 1: Multi-mode 50 um (OM3) + * 137 0: Single Mode (SM) + */ + return __qsfp_get_comp_attr(self, 6); +} + + +int +_qsfp_get_comp_fc_speed(struct transvr_obj_s *self) { + /* transvr_comp[1] = address 00h / 132 + * + * 138 7: 1200 MBps (per channel) + * 138 6: 800 MBps + * 138 5: 1600 MBps (per channel) + * 138 4: 400 MBps + * 138 3: 3200 MBps (per channel) + * 138 2: 200 MBps + * 138 1: Extended: See section 6.3.23. The Extended Specification + * Compliance Codes are maintained in the Transceiver Management + * section of SFF-8024. + * 138 0: 100 MBps + */ + return __qsfp_get_comp_attr(self, 7); +} + + +int +_qsfp_get_comp_extended(struct transvr_obj_s *self) { + /* Address: 00h / 192 + * Reference: SFF-8024 TABLE 4-4 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->transvr_comp_ext); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_comp_eth(struct transvr_obj_s *self){ + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_eth"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_ethernet(self); +} + + +int +qsfp_get_comp_10_40(struct transvr_obj_s *self) { + + int err_code = _check_by_mode(self, + &_common_update_attr_transvr_comp, + "qsfp_get_comp_10_40"); + if (err_code < 0){ + return err_code; + } + return _qsfp_get_comp_10_40_100_ethernet(self); +} + + +int +_qsfp_get_connector_type(struct transvr_obj_s *self) { + /* Address: 00h / 130 + * Reference: SFF-8024 TABLE 4-3 + */ + if ((self->state == STATE_TRANSVR_CONNECTED) || + (self->state == STATE_TRANSVR_INIT) ) { + return (int)(self->connector); + } + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_transvr_temp(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_temp, + "qsfp_get_transvr_temp"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return _common_count_temp(self->curr_temp[0], + self->curr_temp[1], + buf_p); +} + + +int +qsfp_get_transvr_voltage(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_voltage, + "qsfp_get_transvr_voltage"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 Volt */ + return _common_count_voltage(self->curr_voltage[0], + self->curr_voltage[1], + buf_p); +} + + +int +qsfp_get_transvr_tx_eq(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_get_transvr_tx_eq"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->tx_eq[0], self->tx_eq[1]); +} + + +int +qsfp_get_transvr_rx_am(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_get_transvr_rx_am"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_am[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_am[0], self->rx_am[1]); +} + + +int +qsfp_get_transvr_rx_em(struct transvr_obj_s *self, + char *buf_p) { + + int limt = 8; + int err = DEBUG_TRANSVR_INT_VAL; + + err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_get_transvr_rx_em"); + if (err < 0) { + return snprintf(buf_p, limt, "%d\n", err); + } + if ((self->rx_em[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + return snprintf(buf_p, limt, "0x%02x%02x\n", + self->rx_em[0], self->rx_em[1]); +} + + +int +_qsfp_get_channel_diag(uint8_t *data_array, + int (*count_func)(uint8_t high_byte, uint8_t low_byte, char *buf_p), + char *ch_name, + char *result_p) { + int i, high, low; + int len_max = 128; + char ch_buf[4][16] = { DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL, + DEBUG_TRANSVR_STR_VAL }; + + for (i=0; i<4; i++) { + high = (i*2); + low = ((i*2) + 1); + count_func(data_array[high], data_array[low], ch_buf[i]); + } + return snprintf(result_p, len_max, + "%s-%d:%s%s-%d:%s%s-%d:%s%s-%d:%s", + ch_name, 1, ch_buf[0], + ch_name, 2, ch_buf[1], + ch_name, 3, ch_buf[2], + ch_name, 4, ch_buf[3]); +} + + +int +qsfp_get_soft_rx_los(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_rx_los, + "qsfp_get_soft_rx_los"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->rx_los & mask)); +} + + +int +qsfp_get_soft_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_get_soft_tx_disable"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_disable & mask)); +} + + +int +qsfp_get_soft_tx_fault(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int mask = 0x0f; /* Bit 0 ~ Bit 3 */ + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_fault, + "qsfp_get_soft_tx_fault"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_fault & mask)); +} + + +int +qsfp_get_auto_tx_disable(struct transvr_obj_s *self, + char *buf_p) { + + if (self->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "%d\n", ERR_TRANSVR_FUNC_DISABLE); + } + return snprintf(buf_p, LEN_TRANSVR_S_STR, + "0x%02x\n", self->auto_tx_disable); +} + + +int +qsfp_get_transvr_tx_bias(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_bias, + "qsfp_get_transvr_tx_bias"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mA */ + return _qsfp_get_channel_diag(self->curr_tx_bias, + _common_count_tx_bias, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_tx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "TX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_tx_power, + "qsfp_get_transvr_tx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_tx_power, + _common_count_tx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_transvr_rx_power(struct transvr_obj_s *self, + char *buf_p) { + + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *ch_name = "RX"; + + err_code = _check_by_mode(self, + &_qsfp_update_attr_curr_rx_power, + "qsfp_get_transvr_rx_power"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* Return Unit: 1 mW */ + return _qsfp_get_channel_diag(self->curr_rx_power, + _common_count_rx_power, + ch_name, + buf_p); +} + + +int +qsfp_get_wavelength(struct transvr_obj_s *self, + char *buf_p) { + /* [Desc] Wavelength or Copper Cable Attenuation (SFF-8636) + * [Addr] 00h 186-187 + * [Note] + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is + * a 16-bit hex value with Byte 186 as high order byte and Byte 187 as + * low order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. + * If the free side device is identified as copper cable these registers will + * be used to define the cable attenuation. An indication of 0 dB attenuation + * refers to the case where the attenuation is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + int lmax = 8; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _check_by_mode(self, + &_common_update_attr_wavelength, + "common_get_wavelength"); + if (err_code < 0) { + return snprintf(buf_p, lmax, "%d\n", err_code); + } + if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL); + } + /* unit: 1 um */ + return snprintf(buf_p, lmax, "%d\n", + _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1])); +} + + +/* Public Function for Setup Features + */ +static int +__sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + uint8_t update_val = (*attr_p); + + switch (input_val) { + case 0: + SWP_BIT_CLEAR(update_val, bit_shift); + break; + case 1: + SWP_BIT_SET(update_val, bit_shift); + break; + default: + retval = ERR_TRANSVR_UNEXCPT; + err_code = ERR_TRANSVR_UNEXCPT; + err_msg = "Exception occurs"; + goto err_private_sfp_set_soft_rs_1; + } + err_code = _common_set_uint8_attr(self, + address, + page, + offset, + update_val, + attr_p, + caller, + show_err); + if (err_code < 0) { + retval = err_code; + err_msg = "Write data via i2c fail!"; + goto err_private_sfp_set_soft_rs_1; + } + (*attr_p) = update_val; + return 0; + +err_private_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +static int +_sfp_set_soft_rs(struct transvr_obj_s *self, + int input_val, + int address, + int page, + int offset, + int bit_shift, + int (*attr_update_func)(struct transvr_obj_s *self, int show_err), + uint8_t *attr_p, + char *caller, + int show_err) { + + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + /* Check input value */ + if ((input_val != 0) && (input_val != 1)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Check rate identifier is supported */ + err_code = self->get_rate_id(self); + if (err_code <= 0) { + switch (err_code) { + case 0: + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "Not support this feature"; + break; + case ERR_TRANSVR_UNINIT: + retval = ERR_TRANSVR_UNINIT; + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + retval = ERR_TRANSVR_UNPLUGGED; + err_msg = "Transceiver unplugged!"; + break; + default: + retval = err_code; + err_msg = "Check Rate_ID fail!"; + break; + } + goto err_common_sfp_set_soft_rs_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + attr_update_func, + caller); + if ( (err_code < 0) || + ((*attr_p) == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_common_sfp_set_soft_rs_1; + } + /* Generate and update value */ + return __sfp_set_soft_rs(self, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + +err_common_sfp_set_soft_rs_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +sfp_set_soft_rs0(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(0)"] address + * A2h, offset: 110, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs0, + self->eeprom_map_p->page_soft_rs0, + self->eeprom_map_p->offset_soft_rs0, + bit_shift, + &_sfp_update_attr_soft_rs0, + &(self->soft_rs0), + "sfp_set_soft_rs0", + show_err); +} + + +int +sfp_set_soft_rs1(struct transvr_obj_s *self, + int input_val) { + /* Note: + * SFP Soft Rate_Select Select RX ["RS(1)"] address + * A2h, offset: 118, bit 3 + */ + int bit_shift = 3; + int show_err = 1; + return _sfp_set_soft_rs(self, + input_val, + self->eeprom_map_p->addr_soft_rs1, + self->eeprom_map_p->page_soft_rs1, + self->eeprom_map_p->offset_soft_rs1, + bit_shift, + &_sfp_update_attr_soft_rs1, + &(self->soft_rs1), + "sfp_set_soft_rs1", + show_err); +} + + +int +__sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_tx_eq; + } + setv = (uint8_t)input; + if (self->tx_eq[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + setv, + &(self->tx_eq[0]), + "_sfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_tx_eq; + } + return 0; + +err_sfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; itx_eq[0]; + if (_sfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if (self->tx_eq[0] == tmp){ + return 0; + } + } + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +sfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_tx_eq, + "sfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_tx_eq(self, input, 1); +} + + +int +__sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv = DEBUG_TRANSVR_HEX_VAL; + + if ((input < 0) || (input > 0xFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_sfp_set_rx_em; + } + setv = (uint8_t)input; + if (self->rx_em[0] == setv) { + return 0; + } + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + setv, + &(self->rx_em[0]), + "_sfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_attr fail"; + goto err_sfp_set_rx_em; + } + return 0; + +err_sfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_sfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + uint8_t tmp; + int i = 0; + int retry = 3; + + for (i=0; irx_em[0]; + if (_sfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if (self->rx_em[0] == tmp){ + return 0; + } + } + return -1; +} + + +int +sfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_sfp_update_attr_rx_em, + "sfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _sfp_set_rx_em(self, input, 1); +} + + +static int +__qsfp_set_cdr(struct transvr_obj_s *self, + int input_val, + int show_err) { + + uint8_t update_val; + int CDR_FEATURE_SUPPORTED = 0x3; + int retval = ERR_TRANSVR_UNEXCPT; + int err_code = ERR_TRANSVR_UNEXCPT; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_name = "__qsfp_set_cdr"; + + /* Check input value */ + if ((input_val < 0) || (input_val > 0xff)){ + retval = ERR_TRANSVR_BADINPUT; + err_code = ERR_TRANSVR_BADINPUT; + err_msg = "Input range incorrect!"; + goto err_qsfp_set_cdr_1; + } + update_val = (uint8_t)input_val; + /* Check CDR supported by transceiver */ + err_code = qsfp_get_cdr_present(self); + if (err_code < 0) { + retval = err_code; + switch (err_code) { + case ERR_TRANSVR_UNINIT: + err_msg = "Check CDR present fail!"; + break; + case ERR_TRANSVR_UNPLUGGED: + err_msg = "Transceiver unplugged!"; + break; + default: + err_msg = "Check CDR present fail!"; + break; + } + goto err_qsfp_set_cdr_1; + } + if (err_code != CDR_FEATURE_SUPPORTED) { + retval = ERR_TRANSVR_NOTSUPPORT; + err_msg = "This transceiver not support CDR!"; + goto err_qsfp_set_cdr_1; + } + /* Check and update */ + err_code = _check_by_mode(self, + &_qsfp_update_attr_cdr, + func_name); + if ( (err_code < 0) || + (self->cdr == DEBUG_TRANSVR_HEX_VAL) ){ + retval = err_code; + err_msg = "Get current value fail!"; + goto err_qsfp_set_cdr_1; + } + /* Write input value to transceiver */ + return _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->page_cdr, + self->eeprom_map_p->offset_cdr, + update_val, + &(self->cdr), + func_name, + show_err); + +err_qsfp_set_cdr_1: + if (show_err) { + SWPS_INFO("%s: %s :%d :%s\n :%d\n", + __func__, err_msg, err_code, self->swp_name, input_val); + } + return retval; +} + + +int +qsfp_set_cdr(struct transvr_obj_s *self, + int input_val) { + return __qsfp_set_cdr(self, input_val, 1); +} + + +int +qsfp_set_soft_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int show_err = 1; + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + int update_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_soft_tx_disable"); + if (retval < 0) { + snprintf(err_msg, 63, "Not ready. err:%d", retval); + goto err_qsfp_set_soft_tx_disable; + } + if ((input_val > in_max) || + (input_val < in_min) ){ + retval = ERR_TRANSVR_BADINPUT; + snprintf(err_msg, 63, "Input value:%d incorrect!", input_val); + goto err_qsfp_set_soft_tx_disable; + } + if ((self->tx_disable & 0x0f) == input_val) { + return 0; + } + update_val = ((self->tx_disable & 0xf0) & input_val); + retval = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + input_val, + &(self->tx_disable), + "qsfp_set_tx_disable", + show_err); + if (retval < 0) { + snprintf(err_msg, 63, "_common_set_uint8_attr:%d fail!", retval); + goto err_qsfp_set_soft_tx_disable; + } + return 0; + +err_qsfp_set_soft_tx_disable: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return retval; +} + + +int +_qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + uint8_t update) { + + uint8_t tx_enable = 0x0; + int show_e = 1; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Handle timing issues */ + if (update != tx_enable) { + /* Note: + * Because there are some txvr has timing issues, + * therefore we need to execute reset cycle first. + * (enable -> other settings) + */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + tx_enable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set reset value fail"; + goto err_qsfp_set_auto_tx_disable; + } + mdelay(10); + } + /* Setup target value */ + err = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->auto_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C set target value fail"; + goto err_qsfp_set_auto_tx_disable; + } + /* Check and update */ + err = _common_update_uint8_attr(self, + self->eeprom_map_p->addr_tx_disable, + self->eeprom_map_p->page_tx_disable, + self->eeprom_map_p->offset_tx_disable, + self->eeprom_map_p->length_tx_disable, + &(self->tx_disable), + "_qsfp_set_auto_tx_disable", + show_e); + if (err < 0) { + emsg = "I2C get value fail"; + goto err_qsfp_set_auto_tx_disable; + } + if (self->tx_disable != update) { + emsg = "data not become effective"; + goto err_qsfp_set_auto_tx_disable; + } + return 0; + +err_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s\n", + __func__, emsg, self->swp_name); + return ERR_TRANSVR_UPDATE_FAIL; +} + + +int +qsfp_set_auto_tx_disable(struct transvr_obj_s *self, + int input_val) { + + int in_max = 0xf; /* 1111 */ + int in_min = 0x0; /* 0000 */ + int retval = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + + /* Update settings*/ + if (input_val == VAL_TRANSVR_FUNCTION_DISABLE) { + emsg = "User disable auto tx_disable"; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + goto out_qsfp_set_auto_tx_disable; + } + if ((input_val > in_max) || (input_val < in_min) ){ + SWPS_INFO("%s: Input value:%d incorrect! :%s\n", + __func__, input_val, self->swp_name); + return ERR_TRANSVR_BADINPUT; + } + self->auto_tx_disable = input_val; + /* Check current soft tx_disable */ + retval = _check_by_mode(self, + &_qsfp_update_attr_soft_tx_disable, + "qsfp_set_auto_tx_disable"); + switch (retval) { + case 0: + break; + case ERR_TRANSVR_UNPLUGGED: + emsg = "Doesn't need to update"; + goto out_qsfp_set_auto_tx_disable; + default: + SWPS_INFO("%s: setup fail :%d :%s\n", + __func__, retval, self->swp_name); + return retval; + } + return _qsfp_set_auto_tx_disable(self, input_val); + +out_qsfp_set_auto_tx_disable: + SWPS_DEBUG("%s: %s :%s :%d\n :%d", + __func__, emsg, self->swp_name, input_val, retval); + return 0; +} + + +int +__qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_tx_eq; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->tx_eq[0] == setv[0]) && + (self->tx_eq[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_tx_eq, + self->eeprom_map_p->page_tx_eq, + self->eeprom_map_p->offset_tx_eq, + self->eeprom_map_p->length_tx_eq, + setv, + self->tx_eq, + "_qsfp_set_tx_eq", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_tx_eq; + } + return 0; + +err_qsfp_set_tx_eq: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_tx_eq(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; itx_eq[0]; + tmp[1] = self->tx_eq[1]; + if (_qsfp_update_attr_tx_eq(self, show_e) < 0){ + continue; + } + if ((self->tx_eq[0] == tmp[0]) && + (self->tx_eq[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_tx_eq(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_tx_eq, + "qsfp_set_tx_eq"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_tx_eq(self, input, 1); +} + + +int +__qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_am; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_am[0] == setv[0]) && + (self->rx_am[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_am, + self->eeprom_map_p->page_rx_am, + self->eeprom_map_p->offset_rx_am, + self->eeprom_map_p->length_rx_am, + setv, + self->rx_am, + "_qsfp_set_rx_am", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_am; + } + return 0; + +err_qsfp_set_rx_am: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_am(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_am[0]; + tmp[1] = self->rx_am[1]; + if (_qsfp_update_attr_rx_am(self, show_e) < 0){ + continue; + } + if ((self->rx_am[0] == tmp[0]) && + (self->rx_am[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_am(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_am, + "qsfp_set_rx_am"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_am(self, input, 1); +} + + +int +__qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + /* [Note] + * 0x + */ + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t setv[2] = {0x00, 0x00}; + + if ((input < 0) || (input > 0xFFFF)) { + emsg = "input incorrect"; + err = ERR_TRANSVR_BADINPUT; + goto err_qsfp_set_rx_em; + } + setv[0] = (uint8_t)((input & 0xFF00) >> 8); + setv[1] = (uint8_t)(input & 0xFF); + if ((self->rx_em[0] == setv[0]) && + (self->rx_em[1] == setv[1]) ) { + return 0; + } + err = _common_set_uint8_array(self, + self->eeprom_map_p->addr_rx_em, + self->eeprom_map_p->page_rx_em, + self->eeprom_map_p->offset_rx_em, + self->eeprom_map_p->length_rx_em, + setv, + self->rx_em, + "_qsfp_set_rx_em", + show_e); + if (err < 0) { + emsg = "set_uint8_array fail"; + goto err_qsfp_set_rx_em; + } + return 0; + +err_qsfp_set_rx_em: + if (show_e) { + SWPS_INFO("%s: %s :%d\n", __func__, emsg, input); + } + return err; +} + + +int +_qsfp_set_rx_em(struct transvr_obj_s *self, + int input, + int show_e) { + + int i = 0; + int retry = 3; + uint8_t tmp[2]; + + for (i=0; irx_em[0]; + tmp[1] = self->rx_em[1]; + if (_qsfp_update_attr_rx_em(self, show_e) < 0){ + continue; + } + if ((self->rx_em[0] == tmp[0]) && + (self->rx_em[1] == tmp[1]) ){ + return 0; + } + } + return -1; +} + + +int +qsfp_set_rx_em(struct transvr_obj_s *self, + int input) { + + int err = _check_by_mode(self, + &_qsfp_update_attr_rx_em, + "qsfp_set_rx_em"); + if (err < 0) { + SWPS_DEBUG("%s: check fail :%d\n", __func__, err); + return err; + } + return _qsfp_set_rx_em(self, input, 1); +} + + +int +common_transvr_dump(struct transvr_obj_s* self){ + + char *type_name = "Undefined"; + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + switch (self->type) { + case TRANSVR_TYPE_SFP: + type_name = STR_TRANSVR_SFP; + break; + case TRANSVR_TYPE_QSFP: + type_name = STR_TRANSVR_QSFP; + break; + case TRANSVR_TYPE_QSFP_PLUS: + type_name = STR_TRANSVR_QSFP_PLUS; + break; + case TRANSVR_TYPE_QSFP_28: + type_name = STR_TRANSVR_QSFP28; + break; + case TRANSVR_TYPE_FAKE: + type_name = "FAKE"; + goto ok_common_transvr_dump; + case TRANSVR_TYPE_UNPLUGGED: + type_name = "UNPLUGGED"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_INCONSISTENT: + type_name = "INCONSISTENT"; + goto err_common_transvr_dump; + case TRANSVR_TYPE_ERROR: + type_name = "ERROR"; + goto err_common_transvr_dump; + + default: + type_name = "UNEXPECTED"; + goto err_common_transvr_dump; + } + printk(KERN_INFO "[SWPS] Dump %s information:\n", self->swp_name); + printk(KERN_INFO " |- :%s\n", type_name); + printk(KERN_INFO " |- :%s\n", self->vendor_name); + printk(KERN_INFO " |- :%s\n", self->vendor_pn); + printk(KERN_INFO " |- :%s\n", self->vendor_rev); + printk(KERN_INFO " |- :%s\n", self->vendor_sn); + printk(KERN_INFO " |- :0x%02x\n", self->br); + printk(KERN_INFO " |- :0x%02x\n", self->comp_rev); + printk(KERN_INFO " |- :%d\n", self->len_om1); + printk(KERN_INFO " |- :%d\n", self->len_om2); + printk(KERN_INFO " |- :%d\n", self->len_om3); + printk(KERN_INFO " |- :%d\n", self->len_om4); + return 0; + +ok_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return 0; + +err_common_transvr_dump: + SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name); + return -1; +} + + +int +sfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_sm); + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :0x%02x\n", self->rate_id); + return 0; +} + + +int +qsfp_transvr_dump(struct transvr_obj_s* self) { + + if (TRANSVR_INFO_DUMP_ENABLE != 1) { + return 0; + } + if (common_transvr_dump(self) < 0) { + return -1; + } + printk(KERN_INFO " |- :%d\n", self->len_smf); + printk(KERN_INFO " '- :Class_%d\n", __qsfp_get_power_cls(self, 0)); + return 0; +} + + +int +fake_transvr_dump(struct transvr_obj_s* self) { + + printk(KERN_INFO "[SWPS] Dump transceiver information: %s\n", self->swp_name); + printk(KERN_INFO " |- :FAKE\n"); + printk(KERN_INFO " |- :FAKE_VENDER_NAME\n"); + printk(KERN_INFO " |- :FAKE_VENDER_PN\n"); + printk(KERN_INFO " |- :FAKE_VENDER_REV\n"); + printk(KERN_INFO " |- :FAKE_VENDER_SN\n"); + printk(KERN_INFO " |- :0x99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " |- :99\n"); + printk(KERN_INFO " '- :0x99\n"); + return 0; +} + + +/* ========== Object functions for fake type ========== + */ +int +fake_transvr_update(struct transvr_obj_s *self, + int show_err){ + self->state = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +fake_get_binary(struct transvr_obj_s *self){ + return 1; +} + +int +fake_get_int(struct transvr_obj_s *self){ + return 99; +} + + +int +fake_get_hex(struct transvr_obj_s *self){ + return 0x0f; +} + + +int +fake_get_str(struct transvr_obj_s *self, char *buf) { + return snprintf(buf, 16, "fake_get_str\n"); +} + + +int +fake_set_int(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: %d\n", __func__, input); + return 0; +} + + +int +fake_set_hex(struct transvr_obj_s *self, int input){ + SWPS_INFO("%s: 0x%02x\n", __func__, input); + return 0; +} + + +/* ========== Object functions for unsupported ========== + */ +int +unsupported_get_func(struct transvr_obj_s *self){ + return ERR_TRANSVR_NOTSUPPORT; +} + + +int +unsupported_get_func2(struct transvr_obj_s *self, + char *buf_p) { + int len = snprintf(buf_p, 8, "%d\n", ERR_TRANSVR_NOTSUPPORT); + return len; +} + + +int +unsupported_set_func(struct transvr_obj_s *self, + int input_val){ + return ERR_TRANSVR_NOTSUPPORT; +} + + + +/* ========== Object functions for long term task ========== + * + * [Note] + * SWPS transceiver worker is likely the green-thread (coroutine). + * Due to resource and performance considerations. SWPS run all + * features in one kthread at the same time, and handle by it self. + */ + +/* For Transceiver Task Handling + */ +static struct transvr_worker_s * +transvr_task_get(struct transvr_obj_s *self, + char *func_name) { + + struct transvr_worker_s *curr_p = self->worker_p; + + while(curr_p != NULL){ + if (strcmp((curr_p->func_name), func_name) == 0 ) { + return curr_p; + } + curr_p = curr_p->next_p; + } + return NULL; +} + + +static struct transvr_worker_s* +transvr_task_creat(struct transvr_obj_s *self, + int (*main_task)(struct transvr_worker_s *task), + int (*post_task)(struct transvr_worker_s *task), + char *caller) { + + struct transvr_worker_s *task_p = NULL; + struct transvr_worker_s *curr_p = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check task not exist */ + task_p = transvr_task_get(self, caller); + if (task_p) { + snprintf(err_msg, sizeof(err_msg), "Task already created!"); + goto err_transvr_task_creat; + } + /* Create task worker */ + task_p = kzalloc(sizeof(struct transvr_worker_s), GFP_KERNEL); + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_transvr_task_creat; + } + /* Setup task data */ + task_p->transvr_p = self; + task_p->next_p = NULL; + task_p->trigger_time = 0; + task_p->retry = 1; + task_p->state = STATE_T_TASK_INIT; + task_p->main_task = main_task; + task_p->post_task = post_task; + task_p->p_data = NULL; + snprintf(task_p->func_name, sizeof(task_p->func_name), "%s", caller); + /* Setup Link List */ + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p->next_p != NULL) { + curr_p = curr_p->next_p; + } + curr_p->next_p = task_p; + task_p->pre_p = curr_p; + } else { + self->worker_p = task_p; + task_p->pre_p = NULL; + } + return task_p; + +err_transvr_task_creat: + SWPS_ERR("%s: %s :%s :%s\n", + __func__, err_msg, caller, self->swp_name); + return NULL; +} + + +static void +transvr_task_free_one(struct transvr_worker_s *task_p){ + + struct transvr_worker_s *pre_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (task_p) { + pre_p = task_p->pre_p; + next_p = task_p->next_p; + + if ((pre_p) && (next_p)) { + pre_p->next_p = next_p; + next_p->pre_p = pre_p; + + } else if ((!pre_p) && (next_p)) { + next_p->pre_p = NULL; + + } else if ((pre_p) && (!next_p)) { + pre_p->next_p = NULL; + + } else if ((!pre_p) && (!next_p)) { + task_p->transvr_p->worker_p = NULL; + } else { + SWPS_ERR("%s: Unexcept case!\n :%s", + __func__, task_p->transvr_p->swp_name); + } + kfree(task_p->p_data); + kfree(task_p); + } +} + + +static void +transvr_task_free_all(struct transvr_obj_s *self) { + + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if (self->worker_p) { + curr_p = self->worker_p; + while(curr_p) { + next_p = curr_p->next_p; + transvr_task_free_one(curr_p); + curr_p = next_p; + } + self->worker_p = NULL; + } +} + + +static int +_transvr_task_run_main(struct transvr_worker_s *task_p) { + + int retval = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if (!task_p){ + snprintf(err_msg, sizeof(err_msg), "main_task is NULL!"); + goto main_transvr_task_err; + } + if ((task_p->trigger_time) == 0){ + goto main_transvr_task_run; + } + if (time_before(jiffies, task_p->trigger_time)){ + goto main_transvr_task_wait; + } + goto main_transvr_task_run; + +main_transvr_task_run: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + task_p->retry -= 1; + } + retval = task_p->main_task(task_p); + if (retval < 0) { + if (task_p->retry > 0) { + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + } + goto main_transvr_task_identify; + +main_transvr_task_identify: + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + + case EVENT_TRANSVR_TASK_DONE: + task_p->state = STATE_T_TASK_DONE; + return EVENT_TRANSVR_TASK_DONE; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Run main_task fail!"); + goto main_transvr_task_err; + +main_transvr_task_wait: + task_p->state = STATE_T_TASK_WAIT; + return EVENT_TRANSVR_TASK_WAIT; + +main_transvr_task_err: + task_p->state = STATE_T_TASK_FAIL; + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, retval, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_transvr_task_run_post(struct transvr_worker_s *task_p) { + + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + if ((task_p->post_task) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + switch (task_p->state) { + case STATE_T_TASK_WAIT: + case STATE_T_TASK_INIT: + goto post_transvr_task_wait; + + case STATE_T_TASK_DONE: + case STATE_T_TASK_FAIL: + goto post_transvr_task_run; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Unexcept task state"); + goto post_transvr_task_err; + +post_transvr_task_run: + task_p->post_task(task_p); + return EVENT_TRANSVR_TASK_DONE; + +post_transvr_task_wait: + return EVENT_TRANSVR_TASK_WAIT; + +post_transvr_task_err: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, task_p->state, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_one(struct transvr_worker_s *task_p) { + + int retval_main = DEBUG_TRANSVR_INT_VAL; + int retval_post = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + retval_main = _transvr_task_run_main(task_p); + if (retval_main < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute main_task fail!"); + goto err_transvr_task_run_one; + } + retval_post = _transvr_task_run_post(task_p); + if (retval_post < 0) { + snprintf(err_msg, sizeof(err_msg), "Execute post_task fail!"); + goto err_transvr_task_run_one; + } + return retval_main; + +err_transvr_task_run_one: + SWPS_INFO("%s: %s
:%d :%d :%s :%s\n", + __func__, err_msg, retval_main, retval_post, + task_p->func_name, task_p->transvr_p->swp_name); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +transvr_task_run_all(struct transvr_obj_s *self) { + + int haserr = 0; + int retval = DEBUG_TRANSVR_INT_VAL; + struct transvr_worker_s *curr_p = NULL; + struct transvr_worker_s *next_p = NULL; + + if ((self->worker_p) == NULL) { + return EVENT_TRANSVR_TASK_DONE; + } + curr_p = self->worker_p; + while (curr_p != NULL) { + next_p = curr_p->next_p; + retval = transvr_task_run_one(curr_p); + if (curr_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + curr_p = next_p; + continue; + } + switch (retval) { + case EVENT_TRANSVR_TASK_WAIT: + break; + case EVENT_TRANSVR_TASK_DONE: + transvr_task_free_one(curr_p); + break; + case EVENT_TRANSVR_TASK_FAIL: + + default: + haserr = 1; + transvr_task_free_one(curr_p); + break; + } + curr_p = next_p; + } + if (haserr) { + return EVENT_TRANSVR_TASK_FAIL; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +static void +transvr_task_set_delay(struct transvr_worker_s *task_p, + unsigned long delay_msec) { + + task_p->trigger_time = (jiffies + (delay_msec * (HZ/1000))); +} + + +static void +transvr_task_set_retry(struct transvr_worker_s *task_p, + unsigned long retry_times) { + + task_p->retry = retry_times; +} + + +/* For Transceiver Post Task + */ +int +taskfunc_post_do_nothing(struct transvr_worker_s *task_p) { + + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_post_handle_task_state(struct transvr_worker_s *task_p) { + + struct transvr_obj_s* tp = task_p->transvr_p; + + switch (task_p->state) { + case STATE_T_TASK_INIT: + case STATE_T_TASK_WAIT: + return EVENT_TRANSVR_TASK_WAIT; + + case STATE_T_TASK_DONE: + tp->state = STATE_TRANSVR_CONNECTED; + tp->send_uevent(tp, KOBJ_ADD); + return EVENT_TRANSVR_TASK_DONE; + + case STATE_T_TASK_FAIL: + tp->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_TASK_FAIL; + + default: + break; + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +/* For Transceiver Main Task + */ +int +_taskfunc_sfp_setup_soft_rs(struct transvr_worker_s *task_p, + int input_val, + int address, + int page, + int offset, + int bit_shift, + uint8_t *attr_p, + char *caller) { + + int show_err = 0; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_soft_rs"; + + err_code = _sfp_update_attr_soft_rs0(task_p->transvr_p, 0); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + err_code = __sfp_set_soft_rs(task_p->transvr_p, + input_val, + address, + page, + offset, + bit_shift, + attr_p, + caller, + show_err); + if (err_code < 0) { + err_str = "Get current soft_rs0 fail!"; + goto err_taskfunc_sfp_setup_soft_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_setup_soft_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_code); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +__taskfunc_sfp_setup_hard_rs(struct transvr_worker_s *task_p, + int input_val, + int (*get_func)(struct ioexp_obj_s *self, int virt_offset), + int (*set_func)(struct ioexp_obj_s *self, int virt_offset, int input_val)) { + + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + + err_val = get_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset); + + if (err_val < 0) { + if (err_val == ERR_IOEXP_NOTSUPPORT) { + return EVENT_TRANSVR_TASK_DONE; + } + err_str = "Get current hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + if (err_val == input_val) { + return EVENT_TRANSVR_TASK_DONE; + } + err_val = set_func(task_p->transvr_p->ioexp_obj_p, + task_p->transvr_p->ioexp_virt_offset, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs fail!"; + goto err_p_taskfunc_sfp_setup_hard_rs_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_p_taskfunc_sfp_setup_hard_rs_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + __func__, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_hard_rs0(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs0, + task_p->transvr_p->ioexp_obj_p->set_hard_rs0); +} + + +int +_taskfunc_sfp_setup_hard_rs1(struct transvr_worker_s *task_p, + int input_val) { + + return __taskfunc_sfp_setup_hard_rs(task_p, + input_val, + task_p->transvr_p->ioexp_obj_p->get_hard_rs1, + task_p->transvr_p->ioexp_obj_p->set_hard_rs1); +} + + +int +_taskfunc_sfp_setup_rs0(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs0"; + + err_val = _taskfunc_sfp_setup_hard_rs0(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs0, + task_p->transvr_p->eeprom_map_p->page_soft_rs0, + task_p->transvr_p->eeprom_map_p->offset_soft_rs0, + bit_shift, + &(task_p->transvr_p->soft_rs0), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs0 fail!"; + goto err_private_taskfunc_sfp_setup_rs0_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs0_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs0(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_sfp_setup_rs1(struct transvr_worker_s *task_p, + int input_val) { + + int bit_shift = 3; + int old_val = DEBUG_TRANSVR_INT_VAL; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "_taskfunc_sfp_setup_rs1"; + + err_val = _taskfunc_sfp_setup_hard_rs1(task_p, + input_val); + if (err_val < 0) { + err_str = "Setup hard_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + old_val = err_val; + err_val = _taskfunc_sfp_setup_soft_rs(task_p, + input_val, + task_p->transvr_p->eeprom_map_p->addr_soft_rs1, + task_p->transvr_p->eeprom_map_p->page_soft_rs1, + task_p->transvr_p->eeprom_map_p->offset_soft_rs1, + bit_shift, + &(task_p->transvr_p->soft_rs1), + func_str); + if (err_val < 0) { + err_str = "Setup soft_rs1 fail!"; + goto err_private_taskfunc_sfp_setup_rs1_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_sfp_setup_rs1_1: + if ((task_p->retry) == 0) { + SWPS_INFO("%s: %s :%s :%d :%d\n", + func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val); + } + _taskfunc_sfp_setup_hard_rs1(task_p, old_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_sfp_setup_SFF8431_case1(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs0(task_p, update_val); +} + + + +int +taskfunc_sfp_setup_SFF8431_case2(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + int update_val = 1; + + return _taskfunc_sfp_setup_rs1(task_p, update_val); +} + + +int +taskfunc_sfp_setup_SFF8431_case3(struct transvr_worker_s *task_p) { + /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + int update_rs0 = 1; + int update_rs1 = 1; + int err_code = DEBUG_TRANSVR_INT_VAL; + + err_code = _taskfunc_sfp_setup_rs0(task_p, update_rs0); + if (err_code < 0) { + return err_code; + } + return _taskfunc_sfp_setup_rs1(task_p, update_rs1); +} + + +int +taskfunc_sfp_handle_1g_rj45(struct transvr_worker_s *task_p) { + + /* Not all of platform support 0x56 for transceiver + * external PHY, Support list as below: + * => 1. Magnolia-PVT (PS: EVT & DVT not ready) + */ + int ext_phy_addr = 0x56; + int ext_phy_page = -1; + int ext_phy_offs = 0x11; + int ext_phy_len = 1; + int lstate_mask = 0x04; /* 00000100 */ + int show_err = 0; + int fail_retry = 5; + int fail_delay = 1000; /* msec */ + int err_code = DEBUG_TRANSVR_INT_VAL; + uint8_t detect_val = DEBUG_TRANSVR_HEX_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + int *tmp_p = NULL; + char *func_name = "taskfunc_sfp_handle_1g_rj45"; + + if (task_p->transvr_p->state != STATE_TRANSVR_CONNECTED) { + return EVENT_TRANSVR_TASK_DONE; + } + if ( (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000) && + (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000_up) ) { + goto err_taskfunc_sfp_handle_1g_rj45_1; + } + err_code = _common_update_uint8_attr(task_p->transvr_p, + ext_phy_addr, + ext_phy_page, + ext_phy_offs, + ext_phy_len, + &detect_val, + func_name, + show_err); + if ( (err_code < 0) || + (detect_val == DEBUG_TRANSVR_HEX_VAL) ) { + snprintf(err_str, sizeof(err_str), "Detect external link status fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + if ((detect_val & lstate_mask) == lstate_mask) { + goto ok_taskfunc_sfp_handle_1g_rj45_link_up; + } + goto ok_taskfunc_sfp_handle_1g_rj45_link_down; + +ok_taskfunc_sfp_handle_1g_rj45_link_up: + /* Filter out noise */ + if (!(task_p->p_data)) { + tmp_p = kzalloc(sizeof(int), GFP_KERNEL); + if (!tmp_p) { + snprintf(err_str, sizeof(err_str), "kzalloc p_data fail"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + *tmp_p = TRANSVR_CLASS_BASE_T_1000_up; + task_p->p_data = tmp_p; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + } + if ((*(int *)(task_p->p_data)) != TRANSVR_CLASS_BASE_T_1000_up) { + kfree(task_p->p_data); + task_p->p_data = NULL; + snprintf(err_str, sizeof(err_str), "Internal error"); + goto err_taskfunc_sfp_handle_1g_rj45_2; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + kfree(task_p->p_data); + task_p->p_data = NULL; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_link_down: + if (task_p->p_data) { + kfree(task_p->p_data); + task_p->p_data = NULL; + } + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000; + goto ok_taskfunc_sfp_handle_1g_rj45_done; + +ok_taskfunc_sfp_handle_1g_rj45_done: + if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_1: + snprintf(err_str, sizeof(err_str), "Detect transceiver:%d not Base-T, remove task.", + task_p->transvr_p->info); + SWPS_INFO("%s: %s :%s\n", __func__, err_str, task_p->transvr_p->swp_name); + transvr_task_set_retry(task_p, 0); + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_sfp_handle_1g_rj45_2: + if (task_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) { + transvr_task_set_retry(task_p, fail_retry); + } + if ((task_p->retry) == 0) { + /* Error case: + * => In this case, SWPS will stop external Link state monitor features + * and keeps transvr_p->info on TRANSVR_CLASS_BASE_T_1000_up. + * Upper layer will see it always Linkup that because of these type of + * transceiver has external phy, BCM chip see it as Loopback transceiver. + */ + SWPS_WARN("%s can not access external PHY of Base-T SFP transceiver\n", + task_p->transvr_p->swp_name); + task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up; + return EVENT_TRANSVR_TASK_DONE; + } else { + transvr_task_set_delay(task_p, fail_delay); + } + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self, + int setup_val) { + + int curr_val = DEBUG_TRANSVR_INT_VAL; + int err_val = DEBUG_TRANSVR_INT_VAL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + + curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset); + if (curr_val < 0){ + err_msg = "Get current value fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + if (curr_val == setup_val){ + return EVENT_TRANSVR_TASK_DONE; + } + err_val = self->ioexp_obj_p->set_lpmod(self->ioexp_obj_p, + self->ioexp_virt_offset, + setup_val); + if (err_val < 0){ + err_msg = "Setup power mode fail!"; + goto err_private_taskfunc_qsfp_setup_power_mod_1; + } + return EVENT_TRANSVR_TASK_DONE; + +err_private_taskfunc_qsfp_setup_power_mod_1: + SWPS_INFO("%s: %s :%d :%d :%d\n", + __func__, err_msg, err_val, curr_val, setup_val); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +taskfunc_qsfp_handle_tx_disable(struct transvr_worker_s *task_p) { + + int i = 0; + int retry = 5; + int delay_ms = 100; + + if (task_p->transvr_p->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) { + return EVENT_TRANSVR_TASK_DONE; + } + if (!_qsfp_is_implement_tx_disable(task_p->transvr_p)) { + return EVENT_TRANSVR_TASK_DONE; + } + for (i=0; itransvr_p, + task_p->transvr_p->auto_tx_disable) + == EVENT_TRANSVR_TASK_DONE) { + goto ok_taskfunc_qsfp_handle_tx_disable; + } + mdelay(delay_ms); + } + SWPS_INFO("%s auto setup tx_disable:0x%02x fail.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_INIT_FAIL; + +ok_taskfunc_qsfp_handle_tx_disable: + SWPS_INFO("%s auto setup tx_disable:0x%02x ok.\n", + task_p->transvr_p->swp_name, + task_p->transvr_p->auto_tx_disable); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +taskfunc_qsfp_set_hpmod(struct transvr_worker_s *task_p) { + + int err = DEBUG_TRANSVR_INT_VAL; + int HIGH_POWER_MODE = 0; + + /* Handle power mode */ + err = _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + HIGH_POWER_MODE); + if (err < 0) { + SWPS_INFO("%s: setup hpmod fail :%d :%s\n", + __func__, err, task_p->transvr_p->swp_name); + return err; + } + /* Handle auto tx_disable + * [Note] + * => Because there are some transceiver have timing issues or + * setup sequence issues, therefore we handle auto tx_disable + * after handle power mode. + */ + mdelay(100); + return taskfunc_qsfp_handle_tx_disable(task_p); +} + + +int +taskfunc_qsfp_set_lpmod(struct transvr_worker_s *task_p) { + + int LOW_POWER_MODE = 1; + return _taskfunc_qsfp_setup_power_mod(task_p->transvr_p, + LOW_POWER_MODE); +} + + +static int +initfunc_sfp_handle_multi_rate_mode(struct transvr_obj_s *self) { + + int task_retry = 3; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_str = DEBUG_TRANSVR_STR_VAL; + char *func_str = "sfp_handle_multi_rate_mode"; + struct transvr_worker_s *task_p = NULL; + + switch (self->rate_id) { + case 0x00: /* Unspecified */ + case 0x03: /* Unspecified */ + case 0x05: /* Unspecified */ + case 0x07: /* Unspecified */ + case 0x09: /* Unspecified */ + case 0x0B: /* Unspecified */ + case 0x0D: /* Unspecified */ + case 0x0F: /* Unspecified */ + goto sfp_handle_multi_rate_mode_4_unspecified; + + case 0x02: /* SFF-8431 (8/4/2G Rx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case1, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x04: /* SFF-8431 (8/4/2G Tx Rate_Select only) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case2, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x06: /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */ + task_p = transvr_task_creat(self, + taskfunc_sfp_setup_SFF8431_case3, + taskfunc_post_handle_task_state, + func_str); + goto sfp_handle_multi_rate_mode_4_sff8431; + + case 0x01: /* SFF-8079 (4/2/1G Rate_Select & AS0/AS1) */ + err_str = "SFF-8079 (4/2/1G Rate_Select & AS0/AS1)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x08: /* FC-PI-5 (16/8/4G Rx Rate_select only) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Rx Rate_select only)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0A: /* FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) + * High=16G only, Low=8G/4G + */ + err_str = "FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0C: /* FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + */ + err_str = "FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)"; + goto sfp_handle_multi_rate_mode_4_not_support; + + case 0x0E: /* 10/8G Rx and Tx Rate_Select controlling the operation or + * locking modes of the internal signal conditioner, retimer + * or CDR, according to the logic table defined in Table 10-2, + * High Bit Rate (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = + * 8.5 Gb/s. In this mode, the default value of bit 110.3 (Soft + * Rate Select RS(0), Table 9-11) and of bit 118.3 (Soft Rate + * Select RS(1), Table 10-1) is 1. + */ + err_str = "cable type: 0x0E"; + goto sfp_handle_multi_rate_mode_4_not_support; + + default: + err_str = "cable type: UNKNOW"; + goto sfp_handle_multi_rate_mode_4_not_support; + } + +sfp_handle_multi_rate_mode_4_sff8431: + if (!task_p) { + err_str = "Create task fail!"; + goto sfp_handle_multi_rate_mode_4_fail_1; + } + transvr_task_set_retry(task_p, task_retry); + return EVENT_TRANSVR_TASK_WAIT; + +sfp_handle_multi_rate_mode_4_unspecified: + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_not_support: + SWPS_INFO("%s: Does not support %s :%s :0x%02x\n", + func_str, err_str, self->swp_name, self->rate_id); + return EVENT_TRANSVR_TASK_DONE; + +sfp_handle_multi_rate_mode_4_fail_1: + SWPS_INFO("%s: %s :%s :0x%02x, :%d\n", + func_str, err_str, self->swp_name, self->rate_id, err_code); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +initfunc_sfp_handle_1g_rj45(struct transvr_obj_s *self) { + + struct transvr_worker_s *task_p = NULL; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_sfp_handle_1g_rj45"; + + + if (self->info == TRANSVR_CLASS_BASE_T_1000) { + task_p = transvr_task_creat(self, + taskfunc_sfp_handle_1g_rj45, + taskfunc_post_do_nothing, + func_str); + if (!task_p) { + snprintf(err_str, sizeof(err_str), "Create task fail"); + goto err_initfunc_sfp_handle_1g_rj45; + } + transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER); + } + return EVENT_TRANSVR_TASK_DONE; + +err_initfunc_sfp_handle_1g_rj45: + SWPS_INFO("%s: %s :%s :%d\n", + __func__, err_str, self->swp_name, detect_cls); + return EVENT_TRANSVR_TASK_FAIL; +} + + +static int +initfunc_qsfp_handle_power_mode(struct transvr_obj_s *self) { + + int err_code = EVENT_TRANSVR_EXCEP_INIT; + int power_class = DEBUG_TRANSVR_INT_VAL; + int hpmod_retry = 3; + int lpower_config = 1; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + unsigned long hpmod_delay = 500; /* msec */ + struct transvr_worker_s *task_p = NULL; + + /* Handle power mode for IOEXP */ + power_class = __qsfp_get_power_cls(self, 0); + switch (power_class) { + case 1: /* Case: Low power mode (Class = 1) */ + err_code = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (err_code < 0){ + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + return EVENT_TRANSVR_TASK_DONE; + + case 2: /* Case: High power mode (Class > 1) */ + case 3: + case 4: + case 5: + case 6: + case 7: + task_p = transvr_task_creat(self, + taskfunc_qsfp_set_hpmod, + taskfunc_post_handle_task_state, + "transvr_init_qsfp"); + if (!task_p) { + snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail :%d", err_code); + goto err_initfunc_qsfp_handle_power_mode; + } + transvr_task_set_retry(task_p, hpmod_retry); + transvr_task_set_delay(task_p, hpmod_delay); + return EVENT_TRANSVR_TASK_WAIT; + + default: + break; + } + snprintf(err_msg, sizeof(err_msg), "Exception case"); + goto err_initfunc_qsfp_handle_power_mode; + +err_initfunc_qsfp_handle_power_mode: + SWPS_INFO("%s: %s :%s \n", __func__, err_msg, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +initfunc_qsfp28_handle_cdr(struct transvr_obj_s *self) { + + uint8_t DEFAULT_VAL_CDR = 0xff; + int CDR_FUNC_EXISTED = 0x3; + int show_err = 1; + int err_val = EVENT_TRANSVR_TASK_FAIL; + char *err_msg = DEBUG_TRANSVR_STR_VAL; + char *func_str = "initfunc_qsfp28_handle_cdr"; + + err_val = __qsfp_get_cdr_present(self, 0); + if ( (err_val < 0) || + (err_val == DEBUG_TRANSVR_HEX_VAL) ) { + err_msg = "detect cdr_present fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + if (err_val == CDR_FUNC_EXISTED) { + err_val = _common_set_uint8_attr(self, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->addr_cdr, + self->eeprom_map_p->offset_cdr, + DEFAULT_VAL_CDR, + &(self->cdr), + func_str, + show_err); + if (err_val < 0) { + err_msg = "set CDR fail!"; + goto err_taskfunc_qsfp_handle_cdr_1; + } + } + return EVENT_TRANSVR_TASK_DONE; + +err_taskfunc_qsfp_handle_cdr_1: + SWPS_INFO("%s: %s :%d :%s\n", + func_str, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + +/* ========== Object functions for Final State Machine ========== + */ +int +is_plugged(struct transvr_obj_s *self){ + + int limit = 63; + int present = DEBUG_TRANSVR_INT_VAL; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p; + + if (!ioexp_p) { + snprintf(emsg, limit, "ioexp_p is null!"); + goto err_is_plugged_1; + } + present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset); + switch (present){ + case 0: + return 1; + case 1: + return 0; + case ERR_IOEXP_UNINIT: + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + default: + if (ioexp_p->state == STATE_IOEXP_INIT){ + snprintf(emsg, limit, "ioexp_p not ready!"); + goto err_is_plugged_1; + } + break; + } + SWPS_INFO("%s: Exception case! :%d :%d\n", + __func__, present, ioexp_p->state); + return 0; + +err_is_plugged_1: + SWPS_DEBUG("%s: %s\n", __func__, emsg); + return 0; +} + + +static int +detect_transvr_type(struct transvr_obj_s* self){ + + int type = TRANSVR_TYPE_ERROR; + + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + type = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + + /* Case: 1. Wait transceiver I2C module. + * 2. Transceiver I2C module failure. + * Note: 1. SFF allow maximum transceiver initial time is 2 second. So, there + * are exist some case that we need to wait transceiver. + * For these case, we keeps status on "TRANSVR_TYPE_UNPLUGGED", than + * state machine will keep trace with it. + * 2. There exist some I2C failure case we need to handle. Such as user + * insert the failure transceiver, or any reason cause it abnormal. + */ + if (type < 0){ + switch (type) { + case -EIO: + SWPS_DEBUG("%s: %s smbus return:-5 (I/O error)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + case -ENXIO: + SWPS_DEBUG("%s: %s smbus return:-6 (No such device or address)\n", + __func__, self->swp_name); + return TRANSVR_TYPE_UNPLUGGED; + default: + break; + } + SWPS_INFO("%s: %s unexpected smbus return:%d \n", + __func__, self->swp_name, type); + return TRANSVR_TYPE_ERROR; + } + /* Identify valid transceiver type */ + switch (type){ + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + break; + case TRANSVR_TYPE_UNKNOW_1: + case TRANSVR_TYPE_UNKNOW_2: + type = TRANSVR_TYPE_UNKNOW_2; + break; + default: + SWPS_DEBUG("%s: unknow type:0x%02x \n", __func__, type); + type = TRANSVR_TYPE_ERROR; + break; + } + return type; +} + + +static int +detect_transvr_state(struct transvr_obj_s *self, + int result[2]){ + /* [return] [result-0] [result-1] + * 0 STATE_TRANSVR_CONNECTED TRANSVR_TYPE_FAKE + * 0 STATE_TRANSVR_DISCONNECTED TRANSVR_TYPE_UNPLUGGED + * 0 STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * 0 STATE_TRANSVR_INIT / + * 0 STATE_TRANSVR_SWAPPED + * 0 STATE_TRANSVR_CONNECTED + * ERR_TRNASVR_BE_ISOLATED STATE_TRANSVR_ISOLATED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_I2C_CRASH STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_ERROR + * ERR_TRANSVR_UNEXCPT STATE_TRANSVR_UNEXCEPTED TRANSVR_TYPE_UNKNOW_1/2 + */ + result[0] = STATE_TRANSVR_UNEXCEPTED; /* For return state */ + result[1] = TRANSVR_TYPE_ERROR; /* For return type */ + + /* Case1: Fake type */ + if (self->type == TRANSVR_TYPE_FAKE){ + result[0] = STATE_TRANSVR_CONNECTED; + result[1] = TRANSVR_TYPE_FAKE; + return 0; + } + /* Case2: Transceiver unplugged */ + if (!is_plugged(self)){ + result[0] = STATE_TRANSVR_DISCONNECTED; + result[1] = TRANSVR_TYPE_UNPLUGGED; + return 0; + } + /* Case3: Transceiver be isolated */ + if (self->state == STATE_TRANSVR_ISOLATED){ + result[0] = STATE_TRANSVR_ISOLATED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case4: Transceiver plugged */ + result[1] = detect_transvr_type(self); + /* Case4.1: I2C topology crash + * Note : There are some I2C issues cause by transceiver/cables. + * We need to check topology status when user insert it. + * But in this step, we can't not ensure this is the issues + * port. So, it return the ERR_TRANSVR_I2C_CRASH, then upper + * layer will diagnostic I2C topology. + */ + if (check_channel_tier_1() < 0) { + SWPS_INFO("%s: %s detect I2C crash :%d\n", + __func__, self->swp_name, self->state); + result[0] = STATE_TRANSVR_UNEXCEPTED; + result[1] = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_I2C_CRASH; + } + /* Case4.2: System initial not ready, + * Note : Sometime i2c channel or transceiver EEPROM will delay that will + * cause system in inconsistent state between EEPROM and IOEXP. + * In this case, SWP transceiver object keep state at LINK_DOWN + * to wait system ready. + * By the way, State Machine will handle these case. + */ + if (result[1] == TRANSVR_TYPE_UNPLUGGED){ + result[0] = STATE_TRANSVR_DISCONNECTED; + return 0; + } + /* Case4.3: Error transceiver type */ + if (result[1] == TRANSVR_TYPE_ERROR){ + result[0] = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s detect error type\n", __func__, self->swp_name); + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard!"); + return ERR_TRNASVR_BE_ISOLATED; + } + /* Case3.3: Unknow transceiver type */ + if ((result[1] == TRANSVR_TYPE_UNKNOW_1) || + (result[1] == TRANSVR_TYPE_UNKNOW_2) ){ + result[0] = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + /* Case3.4: During initial process */ + if (self->state == STATE_TRANSVR_INIT){ + result[0] = STATE_TRANSVR_INIT; + return 0; + } + /* Case3.5: Transceiver be swapped */ + if (self->type != result[1]){ + result[0] = STATE_TRANSVR_SWAPPED; + return 0; + } + /* Case3.6: Link up state */ + result[0] = STATE_TRANSVR_CONNECTED; + return 0; +} + + +int +_sfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = _sfp_get_comp_extended(self); + + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_25G_AOC; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_25G_SR; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_25G_LR; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_25G_ER; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x0c: /* 25GBASE-CR CA-S */ + case 0x0d: /* 25GBASE-CR CA-N */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L1_25G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_10_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _sfp_get_comp_10g_eth_comp(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 10G Optical (x1) */ + if ((detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + } + if ((detect_val & 0x80) == 0x80) { /* 10000000 : 10GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_1g = 0x0b; + int upper_bound_1g = 0x1A; + int lower_bound_10g = 0x60; + int upper_bound_10g = 0x75; + int lower_bound_25g = 0xf0; + int upper_bound_25g = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 25G */ + if ((notmal_br >= lower_bound_25g) && + (notmal_br <= upper_bound_25g) ) { + return TRANSVR_CLASS_25G; + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + /* Check 1G */ + if ((notmal_br >= lower_bound_1g) && + (notmal_br <= upper_bound_1g) ) { + return TRANSVR_CLASS_1G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + int speed_br = DEBUG_TRANSVR_INT_VAL; + int speed_tmp = DEBUG_TRANSVR_INT_VAL; + char err_str[64] = DEBUG_TRANSVR_STR_VAL; + + speed_br = _sfp_detect_if_sp_by_br(self); + detect_val = _sfp_get_comp_1g_eth_comp(self); + + if (detect_val < 0) { + snprintf(err_str, sizeof(err_str), "Detect abnormal value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + } + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 1G (x1) */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 1000BASE-SX */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_SX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x02) == 0x02) { /* 00000010 : 1000BASE-LX *3 */ + speed_tmp = TRANSVR_CLASS_OPTICAL_1G_LX; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 1000BASE-CX */ + speed_tmp = TRANSVR_CLASS_COPPER_L1_1G; + goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g; + } + /* Case: 1000 Base-T (x1) */ + if ((detect_val & 0x08) == 0x08) { /* 00001000 : 1000BASE-T */ + return TRANSVR_CLASS_BASE_T_1000; + } + /* Case: 100 Base */ + if ( ((detect_val & 0x10) == 0x10) || /* 00010000 : 100BASE-LX/LX10 */ + ((detect_val & 0x20) == 0x20) || /* 00100000 : 100BASE-FX */ + ((detect_val & 0x40) == 0x40) || /* 01000000 : BASE-BX10 *3 */ + ((detect_val & 0x80) == 0x80) ){ /* 10000000 : BASE-PX *3 */ + return TRANSVR_CLASS_OPTICAL_100; + } + /* Case: ERROR */ + snprintf(err_str, sizeof(err_str), "Case:ERROR, value:%d", detect_val); + goto err_p_sfp_detect_class_by_1g_ethernet; + +ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g: + switch (speed_br) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_1G: + return speed_tmp; + case TRANSVR_CLASS_10G: + goto ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G; + } + +ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G: + switch (speed_tmp) { + case TRANSVR_CLASS_OPTICAL_1G_SX: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case TRANSVR_CLASS_OPTICAL_1G_LX: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case TRANSVR_CLASS_COPPER_L1_1G: + return TRANSVR_CLASS_COPPER_L1_10G; + default: + break; + } + snprintf(err_str, sizeof(err_str), "transfer_1to10 fail, speed:%d", speed_tmp); + goto err_p_sfp_detect_class_by_1g_ethernet; + +err_p_sfp_detect_class_by_1g_ethernet: + SWPS_INFO("%s: %s :%s", __func__, err_str, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int is_active = 0; + int conn_val = DEBUG_TRANSVR_INT_VAL; + int check_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _sfp_detect_if_sp_by_br(self); + conn_val = _sfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 */ + case 0x0d: /* MPO 2x16 */ + /* + * ToDo: Need verify Optical Pigtail + */ + goto ok_sfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + /* + * ToDo: Need check ACC use case + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + case 0x23: /* No separable connector */ + /* + * ToDo: Standard not clear, not all transceiver vendor + * have the same defined + */ + goto ok_sfp_detect_class_by_feature_4_check_active_passive; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_check_active_passive: + check_val = _sfp_get_cable_tech(self); + switch(check_val) { + case 0x00: /* Unspecified */ + goto ok_sfp_detect_class_by_feature_4_unknow; + case 0x04: /* Passive */ + goto ok_sfp_detect_class_by_feature_4_copper; + case 0x08: /* Active */ + is_active = 1; + goto ok_sfp_detect_class_by_feature_4_aoc; + default: + snprintf(err_msg, sizeof(err_msg), + "_sfp_get_cable_tech return Non define value:%d", + check_val); + break; + } + goto err_sfp_detect_class_by_feature_1; + +ok_sfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_25G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_25G_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_25G_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_25G_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_25G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_S_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_S_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_S_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + case TRANSVR_CLASS_1G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_1G_SX; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_1G_LX; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_1G_EX; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_1G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_sfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_OPTICAL_25G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_S_AOC; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_OPTICAL_1G_AOC; + default: + break; + } + goto ok_sfp_detect_class_by_feature_4_unknow; + +ok_sfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_25G: + return TRANSVR_CLASS_COPPER_L1_25G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L1_10G; + case TRANSVR_CLASS_1G: + return TRANSVR_CLASS_COPPER_L1_1G; + default: + return TRANSVR_CLASS_COPPER; + } + +ok_sfp_detect_class_by_feature_4_unknow: + return TRANSVR_CLASS_UNSPECIFIED; + +err_sfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +sft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _sfp_detect_class_by_extend_comp(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 10G Compliance */ + detect_val = _sfp_detect_class_by_10_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check 1G Compliance */ + detect_val = _sfp_detect_class_by_1g_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_BASE_T_1000: + case TRANSVR_CLASS_OPTICAL_100: + /* + * ToDo: Need Check 0.1G + */ + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_COPPER_L1_10G: + /* Transfer speed case + * => Example: Raycom 10G DAC + */ + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 1G_eth:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Check by connector, br, wavelength */ + detect_val = _sfp_detect_class_by_feature(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_OPTICAL_1G: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_COPPER: + case TRANSVR_CLASS_COPPER_L1_1G: + case TRANSVR_CLASS_COPPER_L1_10G: + case TRANSVR_CLASS_COPPER_L1_25G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined get_connector:%d", + detect_val); + goto err_sft_detect_transceiver_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sft_detect_transceiver_class_1; + +err_sft_detect_transceiver_class_1: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_sfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_trident2_if_type_1; + +err_sfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result) { + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch(transvr_cls) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SR); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_KR); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SFI); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_IF_GMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_sfp_set_tomahawk_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_set_tomahawk_if_type_1; + +err_sfp_set_tomahawk_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_sfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = sft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _sfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TOMAHAWK: + return _sfp_set_tomahawk_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_sfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = sft_detect_transvr_class(self); + switch(detect_val) { + case TRANSVR_CLASS_ERROR: + case TRANSVR_CLASS_UNSPECIFIED: + break; + /* 25G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 25G COPPER */ + case TRANSVR_CLASS_COPPER_L1_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + /* 10G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_10G_S_AOC: + case TRANSVR_CLASS_OPTICAL_10G_S_SR: + case TRANSVR_CLASS_OPTICAL_10G_S_LR: + case TRANSVR_CLASS_OPTICAL_10G_S_ER: + case TRANSVR_CLASS_OPTICAL_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G COPPER */ + case TRANSVR_CLASS_COPPER_L1_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 1G OPTICAL */ + case TRANSVR_CLASS_OPTICAL_1G_AOC: + case TRANSVR_CLASS_OPTICAL_1G_SX: + case TRANSVR_CLASS_OPTICAL_1G_LX: + case TRANSVR_CLASS_OPTICAL_1G_EX: + case TRANSVR_CLASS_OPTICAL_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G COPPER */ + case TRANSVR_CLASS_COPPER_L1_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 1G BASE_T */ + case TRANSVR_CLASS_BASE_T_1000: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + /* 100 Base */ + case TRANSVR_CLASS_OPTICAL_100: + return snprintf(result, lmax, TRANSVR_IF_SP_100); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + detect_val); + goto err_sfp_detect_if_speed_1; + } + /* Check by BR */ + detect_val = _sfp_detect_if_sp_by_br(self); + switch (detect_val) { + case TRANSVR_CLASS_25G: + return snprintf(result, lmax, TRANSVR_IF_SP_25G); + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_1G: + return snprintf(result, lmax, TRANSVR_IF_SP_1G); + default: + break; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_sfp_detect_if_speed_1; + +err_sfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +sfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_sfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_class_by_extend_comp(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_extended(self); + switch(detect_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + + case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */ + case 0x18: /* 100G AOC or 25GAUI C2M AOC. */ + return TRANSVR_CLASS_OPTICAL_100G_AOC; + + case 0x06: /* 100G CWDM4 */ + case 0x09: /* Obsolete (assigned before 100G CWDM4 MSA required FEC) */ + case 0x17: /* 100G CLR4 */ + case 0x1A: /* 100GE-DWDM2 */ + return TRANSVR_CLASS_OPTICAL_100G; + + case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_100G_SR4; + + case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */ + return TRANSVR_CLASS_OPTICAL_100G_LR4; + + case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */ + return TRANSVR_CLASS_OPTICAL_100G_ER4; + + case 0x07: /* 100G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_100G_PSM4; + + case 0x12: /* 40G PSM4 Parallel SMF */ + return TRANSVR_CLASS_OPTICAL_40G; + + case 0x11: /* 4 x 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + + case 0x10: /* 40GBASE-ER4 */ + return TRANSVR_CLASS_OPTICAL_40G_ER4; + + case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */ + case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */ + case 0x19: /* 100G ACC or 25GAUI C2M ACC. */ + return TRANSVR_CLASS_COPPER_L4_100G; + + default: + break; + } + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_class_by_10_40_100_ethernet(struct transvr_obj_s* self) { + /* Reference: SFF-8472 (v12.2) + */ + int detect_val = DEBUG_TRANSVR_INT_VAL; + + detect_val = _qsfp_get_comp_10_40_100_ethernet(self); + /* Case: Unspecified */ + if (detect_val == 0x00) { + return TRANSVR_CLASS_UNSPECIFIED; + } + /* Case: 40G Optical */ + if ((detect_val & 0x01) == 0x01) { /* 00000001 : 40G Active Cable (XLPPI) */ + return TRANSVR_CLASS_OPTICAL_40G_AOC; + } + if ((detect_val & 0x04) == 0x04) { /* 00000100 : 40GBASE-SR4 */ + return TRANSVR_CLASS_OPTICAL_40G_SR4; + } + if ( (detect_val & 0x02) == 0x02) { /* 00000010 : 40GBASE-LR4 */ + return TRANSVR_CLASS_OPTICAL_40G_LR4; + } + if ( (detect_val & 0x08) == 0x08) { /* 00001000 : 40GBASE-CR4 */ + return TRANSVR_CLASS_COPPER_L4_40G; + } + /* Case: 10G Optical */ + if ( (detect_val & 0x10) == 0x10) { /* 00010000 : 10GBASE-SR */ + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + } + if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR */ + ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */ + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + } + /* Case: Extend Compliance */ + if ( ((detect_val & 0x80) == 0x80) ){ /* 10000000 : Use Extend Compliance */ + return TRANSVR_CLASS_EXTEND_COMP; + } + /* Case: ERROR */ + SWPS_INFO("%s: Unexcept value:0x%02x\n :%s", + __func__, detect_val, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_detect_if_sp_by_br(struct transvr_obj_s* self) { + + int lower_bound_10g = 0x10; + int upper_bound_10g = 0x25; + int lower_bound_40g = 0x60; + int upper_bound_40g = 0x75; + int lower_bound_100g = 0x60; + int upper_bound_100g = 0x75; + int used_extend_br = 0xff; + int notmal_br = DEBUG_TRANSVR_INT_VAL; + int extend_br = DEBUG_TRANSVR_INT_VAL; + + notmal_br = (int)(self->br); /* updated by update_all() */ + /* Check 40G */ + if ((notmal_br >= lower_bound_40g) && + (notmal_br <= upper_bound_40g) ) { + return TRANSVR_CLASS_40G; + } + /* Check 100G */ + if (notmal_br == used_extend_br) { + extend_br = (int)(self->extbr); /* updated by update_all() */ + if ((extend_br >= lower_bound_100g) && + (extend_br <= upper_bound_100g) ) { + return TRANSVR_CLASS_100G; + } + } + /* Check 10G */ + if ((notmal_br >= lower_bound_10g) && + (notmal_br <= upper_bound_10g) ) { + return TRANSVR_CLASS_10G; + } + return TRANSVR_CLASS_UNSPECIFIED; +} + + +int +_qsfp_detect_class_by_feature(struct transvr_obj_s* self) { + /* Reference: SFF-8024 (v3.8) + */ + int conn_val = DEBUG_TRANSVR_INT_VAL; + int wave_len = DEBUG_TRANSVR_INT_VAL; + int speed_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + speed_val = _qsfp_detect_if_sp_by_br(self); + conn_val = _qsfp_get_connector_type(self); + + switch(conn_val) { + case 0x00: /* Unspecified */ + return TRANSVR_CLASS_UNSPECIFIED; + case 0x07: /* LC (Lucent Connector) */ + case 0x0b: /* Optical Pigtail */ + case 0x0c: /* MPO 1x12 (Multifiber Parallel Optic) */ + case 0x0d: /* MPO 2x16 */ + goto ok_qsfp_detect_class_by_feature_4_optiocal; + case 0x21: /* Copper pigtail */ + goto ok_qsfp_detect_class_by_feature_4_copper; + case 0x23: /* No separable connector */ + if ((_qsfp_get_comp_fc_link_length(self) > 0) || + (_qsfp_get_comp_fc_trans_tech(self) > 0) || + (_qsfp_get_comp_fc_trans_media(self) > 0) || + (_qsfp_get_comp_fc_speed(self) > 0) ) { + goto ok_qsfp_detect_class_by_feature_4_aoc; + } + goto ok_qsfp_detect_class_by_feature_4_copper; + default: + snprintf(err_msg, sizeof(err_msg), + "_qsfp_get_connector_type return Non define value:%d", + conn_val); + goto err_qsfp_detect_class_by_feature_1; + } + return TRANSVR_CLASS_UNSPECIFIED; + +ok_qsfp_detect_class_by_feature_4_optiocal: + wave_len = _common_count_wavelength(self, + self->wavelength[0], + self->wavelength[1]); + switch(speed_val) { + case TRANSVR_CLASS_100G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_100G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_100G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_100G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_100G; + + case TRANSVR_CLASS_40G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_40G_SR4; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_40G_LR4; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_40G_ER4; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_40G; + + case TRANSVR_CLASS_10G: + switch (wave_len) { + case VAL_OPTICAL_WAVELENGTH_SR: + return TRANSVR_CLASS_OPTICAL_10G_Q_SR; + case VAL_OPTICAL_WAVELENGTH_LR: + return TRANSVR_CLASS_OPTICAL_10G_Q_LR; + case VAL_OPTICAL_WAVELENGTH_ER: + return TRANSVR_CLASS_OPTICAL_10G_Q_ER; + default: + break; + } + return TRANSVR_CLASS_OPTICAL_10G; + + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_aoc: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_OPTICAL_100G_AOC; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_OPTICAL_40G_AOC; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_OPTICAL_10G_Q_AOC; + default: + return TRANSVR_CLASS_OPTICAL; + } + +ok_qsfp_detect_class_by_feature_4_copper: + switch(speed_val) { + case TRANSVR_CLASS_100G: + return TRANSVR_CLASS_COPPER_L4_100G; + case TRANSVR_CLASS_40G: + return TRANSVR_CLASS_COPPER_L4_40G; + case TRANSVR_CLASS_10G: + return TRANSVR_CLASS_COPPER_L4_10G; + default: + return TRANSVR_CLASS_COPPER; + } + +err_qsfp_detect_class_by_feature_1: + SWPS_INFO("%s: %s\n :%s", + __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +qsft_detect_transvr_class(struct transvr_obj_s* self) { + + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Check Extended Compliance */ + detect_val = _qsfp_detect_class_by_extend_comp(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_COPPER_L4_100G: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined extend_comp:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check 10/40G/100G Ethernet Compliance */ + detect_val = _qsfp_detect_class_by_10_40_100_ethernet(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_COPPER_L4_40G: + return detect_val; + case TRANSVR_CLASS_EXTEND_COMP: + /* Format incorrect case (We already checked the Extend + * Compliance is 0 + */ + snprintf(err_msg, sizeof(err_msg), + "Transceiver format incorrect"); + goto err_qsft_detect_transvr_class_1; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined 10/40/100:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Check by Connector type, BR and wavelength */ + detect_val = _qsfp_detect_class_by_feature(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL: + case TRANSVR_CLASS_COPPER_L4_100G: + case TRANSVR_CLASS_COPPER_L4_40G: + case TRANSVR_CLASS_COPPER_L4_10G: + case TRANSVR_CLASS_COPPER: + return detect_val; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined connector:%d", + detect_val); + goto err_qsft_detect_transvr_class_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), + "Can not identify!"); + goto err_qsft_detect_transvr_class_1; + +err_qsft_detect_transvr_class_1: + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return TRANSVR_CLASS_ERROR; +} + + +int +_qsfp_set_trident2_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: LR4 or LR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: /* Need Check: ER4 or ER */ + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_IF_XGMII); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_set_tomahawk_if_type(struct transvr_obj_s* self, + int transvr_cls, + char *result){ + + int lmax = 8; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + switch (transvr_cls) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_KR4); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + return snprintf(result, lmax, TRANSVR_IF_SR4); + /* Copper */ + case TRANSVR_CLASS_COPPER: + return snprintf(result, lmax, TRANSVR_IF_KR4); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined value:%d", + transvr_cls); + goto err_qsfp_set_trident2_if_type_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_set_trident2_if_type_1; + +err_qsfp_set_trident2_if_type_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s\n :%s", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +_qsfp_detect_if_type(struct transvr_obj_s* self, + char *result){ + + int lmax = 8; + int detect_cls = DEBUG_TRANSVR_INT_VAL; + + detect_cls = qsft_detect_transvr_class(self); + switch (self->chipset_type) { + case BCM_CHIP_TYPE_TRIDENT_2: + return _qsfp_set_trident2_if_type(self, detect_cls, result); + + case BCM_CHIP_TYPE_TOMAHAWK: + return _qsfp_set_tomahawk_if_type(self, detect_cls, result); + + default: + SWPS_INFO("%s: non-defined chipset_type:%d :%s\n", + __func__, self->chipset_type, self->swp_name); + break; + } + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_type(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 8; + char tmp_result[8] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_type(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_qsfp_detect_if_speed(struct transvr_obj_s* self, + char *result){ + int lmax = 16; + int detect_val = DEBUG_TRANSVR_INT_VAL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + detect_val = qsft_detect_transvr_class(self); + switch (detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + case TRANSVR_CLASS_ERROR: + break; + /* 100G Optical */ + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 100G Copper */ + case TRANSVR_CLASS_COPPER_L4_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + /* 40G Optical */ + case TRANSVR_CLASS_OPTICAL_40G: + case TRANSVR_CLASS_OPTICAL_40G_AOC: + case TRANSVR_CLASS_OPTICAL_40G_SR4: + case TRANSVR_CLASS_OPTICAL_40G_LR4: + case TRANSVR_CLASS_OPTICAL_40G_ER4: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 40G Copper */ + case TRANSVR_CLASS_COPPER_L4_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + /* 10G Optical */ + case TRANSVR_CLASS_OPTICAL_10G: + case TRANSVR_CLASS_OPTICAL_10G_Q_AOC: + case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */ + case TRANSVR_CLASS_OPTICAL_10G_Q_ER: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* 10G Copper */ + case TRANSVR_CLASS_COPPER_L4_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + /* Optical */ + case TRANSVR_CLASS_OPTICAL: + break; + /* Copper */ + case TRANSVR_CLASS_COPPER: + break; + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined class case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Check br and extbr */ + detect_val = _qsfp_detect_if_sp_by_br(self); + switch(detect_val) { + case TRANSVR_CLASS_UNSPECIFIED: + break; + case TRANSVR_CLASS_10G: + return snprintf(result, lmax, TRANSVR_IF_SP_10G); + case TRANSVR_CLASS_40G: + return snprintf(result, lmax, TRANSVR_IF_SP_40G); + case TRANSVR_CLASS_100G: + return snprintf(result, lmax, TRANSVR_IF_SP_100G); + default: + snprintf(err_msg, sizeof(err_msg), + "Detect undefined BR case:%d", + detect_val); + goto err_qsfp_detect_if_speed_1; + } + /* Exception case: Can't verify */ + snprintf(err_msg, sizeof(err_msg), "Can not identify!"); + goto err_qsfp_detect_if_speed_1; + +err_qsfp_detect_if_speed_1: + snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW); + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + return ERR_TRANSVR_ABNORMAL; +} + + +int +qsfp_get_if_speed(struct transvr_obj_s *self, + char *buf_p){ + + int lmax = 16; + char tmp_result[16] = DEBUG_TRANSVR_STR_VAL; + + if (self->state != STATE_TRANSVR_CONNECTED) { + return snprintf(buf_p, lmax, "%d\n", self->state); + } + if (_qsfp_detect_if_speed(self, tmp_result) < 0) { + return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL); + } + return snprintf(buf_p, lmax, "%s\n", tmp_result); +} + + +int +_common_set_lane_map_str(struct transvr_obj_s* self, + char *result) { + int i = 0; + int tmp_val = 0; + char tmp_str[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + char err_msg[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL; + + memset(result, 0, LEN_TRANSVR_L_STR); + snprintf(result, LEN_TRANSVR_L_STR, "%s=", TRANSVR_UEVENT_KEY_LANE); + + for (i=0; ilane_id); i++) { + tmp_val = self->lane_id[i]; + if (tmp_val < 1) { + break; + } + if (tmp_val > 256) { + snprintf(err_msg, sizeof(err_msg), + "detect abnormal value:%d", tmp_val); + goto err_common_set_lane_map_str_1; + } + memset(tmp_str, 0, sizeof(tmp_str)); + if (i == 0) { + snprintf(tmp_str, LEN_TRANSVR_L_STR, "%d", tmp_val); + } else { + snprintf(tmp_str, LEN_TRANSVR_L_STR, ",%d", tmp_val); + } + strncat(result, tmp_str, LEN_TRANSVR_L_STR); + } + if (i == 0) { + goto err_common_set_lane_map_str_2; + } + return 0; + +err_common_set_lane_map_str_1: + SWPS_INFO("%s: %s", __func__, err_msg); +err_common_set_lane_map_str_2: + snprintf(result, LEN_TRANSVR_L_STR, "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + return EVENT_TRANSVR_TASK_FAIL; +} + + +int +_common_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action, + int (*detect_if_type)(struct transvr_obj_s *self, char *result), + int (*detect_if_speed)(struct transvr_obj_s *self, char *result), + int send_anyway) { + + char *uevent_envp[4]; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + char tmp_str[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_1[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_2[32] = DEBUG_TRANSVR_STR_VAL; + char tmp_str_3[64] = DEBUG_TRANSVR_STR_VAL; + + if (TRANSVR_UEVENT_ENABLE != 1) { + return ERR_TRANSVR_NOTSUPPORT; + } + if (_common_get_if_lane(self, tmp_str) < 0) { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW); + } else { + snprintf(tmp_str_3, sizeof(tmp_str_3), + "%s=%s", TRANSVR_UEVENT_KEY_LANE, tmp_str); + } + switch (u_action) { + case KOBJ_ADD: + /* Detect type */ + if (detect_if_type(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface type fail!"); + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, tmp_str); + uevent_envp[0] = tmp_str_1; + /* Detect speed */ + if (detect_if_speed(self, tmp_str) < 0) { + snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface speed fail!"); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_fail; + } + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, tmp_str); + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + case KOBJ_REMOVE: + snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW); + snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW); + uevent_envp[0] = tmp_str_1; + uevent_envp[1] = tmp_str_2; + uevent_envp[2] = tmp_str_3; + uevent_envp[3] = NULL; + goto private_common_send_uevent_4_send; + + default: + snprintf(err_msg, sizeof(err_msg), "kobject_action:%d not support", u_action); + goto private_common_send_uevent_4_fail; + } + snprintf(err_msg, sizeof(err_msg), "%s", "Exception case"); + goto private_common_send_uevent_4_fail; + +private_common_send_uevent_4_fail: + SWPS_INFO("%s: %s :%s\n", __func__, err_msg, self->swp_name); + if (send_anyway) { + goto private_common_send_uevent_4_send; + } + return ERR_TRANSVR_UEVENT_FAIL; + +private_common_send_uevent_4_send: + return kobject_uevent_env(&(self->transvr_dev_p->kobj), + u_action, + uevent_envp); +} + +int +sfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_sfp_detect_if_type, + &_sfp_detect_if_speed, + send_anyway); +} + + +int +qsfp_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + int send_anyway = 1; + return _common_send_uevent(self, + u_action, + &_qsfp_detect_if_type, + &_qsfp_detect_if_speed, + send_anyway); +} + + +int +fake_send_uevent(struct transvr_obj_s* self, + enum kobject_action u_action) { + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + + int err; + int detect_result[2]; + int current_state = STATE_TRANSVR_UNEXCEPTED; + int current_type = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_NEW) { + if (_transvr_init_handler(self) < 0){ + return ERR_TRANSVR_INIT_FAIL; + } + } + err = detect_transvr_state(self, detect_result); + if (err < 0) { + return err; + } + /* In Direct mode, driver only detect transceiver when user call driver interface + * which on sysfs. So it only need consider the state of Transceiver. + */ + current_state = detect_result[0]; + current_type = detect_result[1]; + + switch (current_state){ + + case STATE_TRANSVR_DISCONNECTED: /* Transceiver is not plugged */ + self->state = current_state; + self->type = current_type; + return ERR_TRANSVR_UNPLUGGED; + + case STATE_TRANSVR_INIT: /* Transceiver is plugged, system not ready */ + return ERR_TRANSVR_UNINIT; + + case STATE_TRANSVR_ISOLATED: /* Transceiver is plugged, but has some issues */ + return ERR_TRNASVR_BE_ISOLATED; + + case STATE_TRANSVR_CONNECTED: /* Transceiver is plugged, system is ready */ + self->state = current_state; + self->type = current_type; + return 0; + + case STATE_TRANSVR_SWAPPED: /* Transceiver is plugged, system detect user changed */ + self->type = current_type; + if (reload_transvr_obj(self, current_type) < 0){ + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_UNEXCPT; + } + self->state = current_state; + return 0; + + case STATE_TRANSVR_UNEXCEPTED: /* Transceiver type or state is unexpected case */ + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return ERR_TRANSVR_UNEXCPT; + + default: + SWPS_INFO("%s: state:%d not in define.\n", __func__, current_state); + break; + } + return ERR_TRANSVR_UNEXCPT; +} + + +static int +_is_except_happened_4_pmode(struct transvr_obj_s* self, + int new_state) { + + int event_chk = 0; + + if (self->temp == 0){ + return 0; + } + switch (new_state) { + case STATE_TRANSVR_INIT: + event_chk = EVENT_TRANSVR_EXCEP_INIT; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_CONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_UP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_DISCONNECTED: + event_chk = EVENT_TRANSVR_EXCEP_DOWN; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_SWAPPED: + event_chk = EVENT_TRANSVR_EXCEP_SWAP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_UNEXCEPTED: + event_chk = EVENT_TRANSVR_EXCEP_EXCEP; + goto check_event_happened_4_pmode; + + case STATE_TRANSVR_ISOLATED: + event_chk = EVENT_TRANSVR_EXCEP_ISOLATED; + goto check_event_happened_4_pmode; + + default: + SWPS_INFO("%s: unexcepted case:%d\n", __func__, new_state); + break; + } + return 0; + +check_event_happened_4_pmode: + if (self->temp == event_chk){ + return 1; + } + return 0; +} + + +int +common_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + /* [Return Value]: + * ERR_TRANSVR_UNINIT : (1) Initial not ready + * ERR_TRANSVR_UNPLUGGED : (1) Any -> Down + * ERR_TRANSVR_TASK_BUSY : (1) Wait Initial task + * ERR_TRANSVR_UNEXCPT : (1) Initial fail + * (2) Task fail + * (3) Reload fail + * ERR_TRNASVR_BE_ISOLATED : (1) Already be isolated + * OK Case (return 0) : (1) action_4_connected + * (2) action_4_nothing (initial retry) + */ + int curr_state[2]; + int old_state = self->state; + int old_type = self->type; + int new_state = STATE_TRANSVR_UNEXCEPTED; + int new_type = TRANSVR_TYPE_ERROR; + int return_val = ERR_TRANSVR_UNEXCPT; + + /* Never initial */ + if (self->state == STATE_TRANSVR_NEW) { + goto comfsm_action_4_reinit_obj; + } + /* Detect current state */ + switch (detect_transvr_state(self, curr_state)) { + case 0: + new_state = curr_state[0]; + new_type = curr_state[1]; + break; + + case ERR_TRNASVR_BE_ISOLATED: + new_state = STATE_TRANSVR_ISOLATED; + new_type = old_type; + break; + + case ERR_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case ERR_TRANSVR_UNEXCPT: + default: + new_state = STATE_TRANSVR_UNEXCEPTED; + new_type = old_type; + } + /* State handling */ + switch (old_state) { + case STATE_TRANSVR_INIT: /* INIT -> */ + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 1-1: UP -> INIT */ + SWPS_INFO("Detect %s is present. :1-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 1-2: UP -> UP */ + return_val = 0; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 1-3: UP -> DOWN */ + SWPS_INFO("Detect %s is removed. :1-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 1-4: UP -> SWAP */ + SWPS_INFO("Detect %s is swapped. :1-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 1-5: UP -> UNEXPET */ + SWPS_INFO("Detect %s has error. :1-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 1-6: UP -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :1-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_DISCONNECTED: + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 2-1: DOWN -> INIT */ + SWPS_INFO("Detect %s is present. :2-1\n",self->swp_name); + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 2-2: DOWN -> UP */ + SWPS_INFO("Detect %s is present. :2-2\n",self->swp_name); + goto comfsm_action_4_reinit_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 2-3: DOWN -> DOWN */ + return_val = ERR_TRANSVR_UNPLUGGED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_SWAPPED: /* Case 2-4: DOWN -> SWAP */ + SWPS_INFO("Detect %s is swapped. :2-4\n",self->swp_name); + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 2-5: DOWN -> UNEXPET */ + SWPS_INFO("Detect %s has error. :2-5\n",self->swp_name); + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: /* Case 2-6: DOWN -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :2-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_UNEXCEPTED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 3-1: UNEXPET -> INIT */ + SWPS_INFO("Detect %s is present. :3-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRANSVR_UNINIT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 3-2: UNEXPET -> UP */ + SWPS_INFO("Detect %s is present. :3-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_DISCONNECTED: /* Case 3-3: UNEXPET -> DOWN */ + SWPS_INFO("Detect %s is removed. :3-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 3-4: UNEXPET -> SWAP */ + SWPS_INFO("Detect %s is swapped. :3-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + goto comfsm_action_4_reload_obj; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 3-5: UNEXPET -> UNEXPET */ + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRANSVR_UNEXCPT; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 3-6: UNEXPET -> ISOLATE */ + SWPS_INFO("Detect %s be isolated. :3-6\n",self->swp_name); + goto comfsm_action_4_isolate_obj; + + default: + break; + } + goto comfsm_action_4_unexpected; + + case STATE_TRANSVR_ISOLATED: + /* Filter out re-action */ + if (_is_except_happened_4_pmode(self, new_state)) { + goto comfsm_action_4_keep_state; + } + /* First action */ + switch (new_state) { + case STATE_TRANSVR_INIT: /* Case 4-1: ISOLATE -> INIT */ + SWPS_INFO("Detect %s internal error. :4-1\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_INIT; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_CONNECTED: /* Case 4-2: ISOLATE -> UP */ + SWPS_INFO("Detect %s internal error. :4-2\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_UP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_DISCONNECTED: /* Case 4-3: ISOLATE -> DOWN */ + SWPS_INFO("Detect %s is removed. :4-3\n",self->swp_name); + goto comfsm_action_4_disconnected; + + case STATE_TRANSVR_SWAPPED: /* Case 4-4: ISOLATE -> SWAP */ + SWPS_INFO("Detect %s internal error. :4-4\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_SWAP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_UNEXCEPTED: /* Case 4-5: ISOLATE -> UNEXPET */ + SWPS_INFO("Detect %s internal error. :4-5\n",self->swp_name); + self->temp = EVENT_TRANSVR_EXCEP_EXCEP; + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + case STATE_TRANSVR_ISOLATED: /* Case 4-6: ISOLATE -> ISOLATE */ + return_val = ERR_TRNASVR_BE_ISOLATED; + goto comfsm_action_4_keep_state; + + default: + break; + } + goto comfsm_action_4_unexpected; + + default: + break; + } + goto comfsm_action_4_unexpected; + + +comfsm_action_4_keep_state: + return return_val; + +comfsm_action_4_reinit_obj: + SWPS_DEBUG("FSM action: %s re-initial.\n", self->swp_name); + return_val = _transvr_init_handler(self); + goto comfsm_action_4_identify_event; + +comfsm_action_4_reload_obj: + SWPS_DEBUG("FSM action: %s reload.\n", self->swp_name); + self->type = new_type; + return_val = reload_transvr_obj(self, new_type); + goto comfsm_action_4_identify_event; + +comfsm_action_4_identify_event: + switch (return_val) { + case EVENT_TRANSVR_INIT_UP: + case EVENT_TRANSVR_TASK_DONE: + goto comfsm_action_4_connected; + + case EVENT_TRANSVR_INIT_DOWN: + goto comfsm_action_4_disconnected; + + case EVENT_TRANSVR_INIT_REINIT: + goto comfsm_action_4_nothing; + + case EVENT_TRANSVR_TASK_WAIT: + self->state = STATE_TRANSVR_INIT; + return ERR_TRANSVR_TASK_BUSY; + + case EVENT_TRANSVR_TASK_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_TASK_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_INIT_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_INIT_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_RELOAD_FAIL: + SWPS_INFO("%s detect EVENT_TRANSVR_RELOAD_FAIL.\n", self->swp_name); + goto comfsm_action_4_unexpected; + + case EVENT_TRANSVR_I2C_CRASH: + goto comfsm_action_4_report_i2c_crash; + + case EVENT_TRANSVR_EXCEP_ISOLATED: + goto comfsm_action_4_isolate_obj; + + default: + SWPS_INFO("%s detect undefined event:%d.\n", self->swp_name, return_val); + goto comfsm_action_4_unexpected; + } + +comfsm_action_4_nothing: + SWPS_DEBUG("FSM action: %s do nothing.\n", self->swp_name); + return 0; + +comfsm_action_4_connected: + SWPS_DEBUG("FSM action: %s Connected.\n", self->swp_name); + self->state = STATE_TRANSVR_CONNECTED; + self->type = new_type; + self->send_uevent(self, KOBJ_ADD); + _transvr_clean_retry(self); + return 0; + +comfsm_action_4_disconnected: + SWPS_DEBUG("FSM action: %s Disconnected. \n", self->swp_name); + self->state = STATE_TRANSVR_DISCONNECTED; + self->temp = EVENT_TRANSVR_TASK_DONE; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_retry(self); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNPLUGGED; + +comfsm_action_4_report_i2c_crash: + SWPS_DEBUG("FSM action: %s report I2C crash.\n", self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return ERR_TRANSVR_I2C_CRASH; + +comfsm_action_4_isolate_obj: + SWPS_DEBUG("FSM action: %s isolate.\n", self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return ERR_TRNASVR_BE_ISOLATED; + +comfsm_action_4_unexpected: + SWPS_INFO("FSM action: %s unexpected.\n", self->swp_name); + SWPS_INFO("Dump: :%d :0x%02x :%d :0x%02x\n", + old_state, old_type, new_state, new_type); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->send_uevent(self, KOBJ_REMOVE); + _transvr_clean_handler(self); + return ERR_TRANSVR_UNEXCPT; +} + + +int +fake_fsm_4_direct_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +int +fake_fsm_4_polling_mode(struct transvr_obj_s* self, + char *caller_name){ + self->state = STATE_TRANSVR_CONNECTED; + self->type = TRANSVR_TYPE_FAKE; + return 0; +} + + +/* ========== Object functions for Initial procedure ========== + */ +int +transvr_init_common(struct transvr_obj_s *self){ + /* Nothing to update */ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_fake(struct transvr_obj_s *self){ + return EVENT_TRANSVR_TASK_DONE; +} + + +int +transvr_init_sfp(struct transvr_obj_s *self){ + + int tmp_val = DEBUG_TRANSVR_INT_VAL; + int err_code = DEBUG_TRANSVR_INT_VAL; + char *err_msg = "ERR"; + + self->info = sft_detect_transvr_class(self); + /* Disable auto_config */ + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + /* Handle multi-rate */ + err_code = initfunc_sfp_handle_multi_rate_mode(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_multi_rate_mode fail!"; + goto err_transvr_init_sfp_1; + } + /* Handle 1G- RJ45 */ + tmp_val = err_code; + err_code = initfunc_sfp_handle_1g_rj45(self); + if (err_code < 0) { + err_msg = "initfunc_sfp_handle_1g_rj45 fail!"; + goto err_transvr_init_sfp_1; + } + tmp_val = (tmp_val > err_code ? tmp_val : err_code); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_sfp_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_code, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp(struct transvr_obj_s *self){ + + int err = EVENT_TRANSVR_EXCEP_EXCEP; + char *emsg = "ERR"; + + self->info = qsft_detect_transvr_class(self); + if (!self->auto_config) { + return EVENT_TRANSVR_TASK_DONE; + } + err = initfunc_qsfp_handle_power_mode(self); + if (err < 0){ + emsg = "initfunc_qsfp_handle_tx_disable fail!"; + goto err_transvr_init_qsfp; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, emsg, err, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +int +transvr_init_qsfp28(struct transvr_obj_s *self){ + + int tmp_val = EVENT_TRANSVR_EXCEP_EXCEP; + int err_val = EVENT_TRANSVR_EXCEP_EXCEP; + char *err_msg = "ERR"; + + /* Handle QSFP common */ + err_val = transvr_init_qsfp(self); + if (err_val < 0){ + err_msg = "transvr_init_qsfp fail!"; + goto err_transvr_init_qsfp28_1; + } + /* Disable auto_config */ + if (!self->auto_config) { + return err_val; + } + /* Handle CDR */ + tmp_val = err_val; + err_val = initfunc_qsfp28_handle_cdr(self); + if (err_val < 0){ + err_msg = "Handle CDR fail!"; + goto err_transvr_init_qsfp28_1; + } + tmp_val = (tmp_val > err_val ? tmp_val : err_val); + if (tmp_val > EVENT_TRANSVR_TASK_DONE) { + return tmp_val; + } + return EVENT_TRANSVR_TASK_DONE; + +err_transvr_init_qsfp28_1: + SWPS_INFO("%s: %s :%d :%s\n", + __func__, err_msg, err_val, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== Object Initial handler ========== + */ +static int +_is_transvr_valid(struct transvr_obj_s *self, + int type, + int state) { + /* [Return] + * 0 : OK, inserted + * EVENT_TRANSVR_INIT_DOWN : OK, removed + * EVENT_TRANSVR_INIT_FAIL : Outside error, type doesn't supported + * EVENT_TRANSVR_EXCEP_INIT : Internal error, state undefined + */ + switch (type) { + case TRANSVR_TYPE_SFP: + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + break; + default: + SWPS_INFO("detect undefined type:0x%02x on %s\n", + type, self->swp_name); + return EVENT_TRANSVR_INIT_FAIL; + } + switch (state) { + case STATE_TRANSVR_DISCONNECTED: + return EVENT_TRANSVR_INIT_DOWN; + case STATE_TRANSVR_INIT: + case STATE_TRANSVR_CONNECTED: + case STATE_TRANSVR_SWAPPED: + break; + default: + SWPS_INFO("detect undefined state:%d on %s\n", + state, self->swp_name); + return EVENT_TRANSVR_EXCEP_INIT; + } + return 0; +} + + +static int +_is_transvr_hw_ready(struct transvr_obj_s *self, + int type){ + /* [Return] + * EVENT_TRANSVR_TASK_DONE : Ready + * EVENT_TRANSVR_TASK_WAIT : Not ready + * EVENT_TRANSVR_INIT_FAIL : Error + */ + int addr = DEBUG_TRANSVR_INT_VAL; + int page = DEBUG_TRANSVR_INT_VAL; + int offs = DEBUG_TRANSVR_INT_VAL; + int bit = DEBUG_TRANSVR_INT_VAL; + int ready = DEBUG_TRANSVR_INT_VAL; + int err = DEBUG_TRANSVR_INT_VAL; + char *emsg = DEBUG_TRANSVR_STR_VAL; + uint8_t ab_val = DEBUG_TRANSVR_HEX_VAL; + + switch (type) { + case TRANSVR_TYPE_SFP: + addr = VAL_TRANSVR_8472_READY_ADDR; + page = VAL_TRANSVR_8472_READY_PAGE; + offs = VAL_TRANSVR_8472_READY_OFFSET; + bit = VAL_TRANSVR_8472_READY_BIT; + ready = VAL_TRANSVR_8472_READY_VALUE; + ab_val = VAL_TRANSVR_8472_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + case TRANSVR_TYPE_QSFP_28: + addr = VAL_TRANSVR_8436_READY_ADDR; + page = VAL_TRANSVR_8436_READY_PAGE; + offs = VAL_TRANSVR_8436_READY_OFFSET; + bit = VAL_TRANSVR_8436_READY_BIT; + ready = VAL_TRANSVR_8436_READY_VALUE; + ab_val = VAL_TRANSVR_8436_READY_ABNORMAL; + break; + + case TRANSVR_TYPE_UNPLUGGED: + case TRANSVR_TYPE_FAKE: + return EVENT_TRANSVR_TASK_DONE; + + default: + emsg = "unexpected case"; + goto err_is_transvr_hw_ready; + } + /* Select target page */ + err = _common_setup_page(self, addr, page, offs, 1, 0); + if (err < 0) { + emsg = "setup page fail"; + goto err_is_transvr_hw_ready; + } + /* Check feature supported + * [Note] + * Some of transceiver/cables doesn't support "Status Indicators" + * (ex:DAC, RJ45 copper SFP ...etc). In these case, we bypass the + * step of checking Status Indicators, then state machine will take + * the following handle procedure. + */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (err < 0) { + emsg = "doesn't support Status Indicators"; + goto bypass_is_transvr_hw_ready; + } + /* Filter abnormal case */ + if (err == ab_val) { + emsg = "detect using unusual definition."; + goto bypass_is_transvr_hw_ready; + } + /* Get Status Indicators */ + err = i2c_smbus_read_byte_data(self->i2c_client_p, offs); + if (err < 0) { + emsg = "detect current value fail"; + goto err_is_transvr_hw_ready; + } + if ((err & (1<:%d\n", __func__, emsg, type); + return EVENT_TRANSVR_TASK_DONE; + +err_is_transvr_hw_ready: + SWPS_DEBUG("%s: %s :%d\n", __func__, emsg, type); + return EVENT_TRANSVR_INIT_FAIL; +} + + +static int +_is_transvr_support_ctle(struct transvr_obj_s *self) { + + switch (self->info) { + case TRANSVR_CLASS_OPTICAL_25G: + case TRANSVR_CLASS_OPTICAL_25G_AOC: + case TRANSVR_CLASS_OPTICAL_25G_SR: + case TRANSVR_CLASS_OPTICAL_25G_LR: + case TRANSVR_CLASS_OPTICAL_25G_ER: + case TRANSVR_CLASS_OPTICAL_100G: + case TRANSVR_CLASS_OPTICAL_100G_AOC: + case TRANSVR_CLASS_OPTICAL_100G_SR4: + case TRANSVR_CLASS_OPTICAL_100G_LR4: + case TRANSVR_CLASS_OPTICAL_100G_ER4: + case TRANSVR_CLASS_OPTICAL_100G_PSM4: + return 1; + default: + break; + } + return 0; +} + + +static int +_transvr_init_handler(struct transvr_obj_s *self){ + + int detect[2]; + int d_state = STATE_TRANSVR_UNEXCEPTED; + int d_type = TRANSVR_TYPE_ERROR; + int result = ERR_TRANSVR_UNINIT; + int retry = 6; /* (6+1) x 0.3 = 2.1s > spec:2.0s */ + int elimit = 63; + char emsg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Clean and check callback */ + self->state = STATE_TRANSVR_INIT; + if (self->init == NULL) { + snprintf(emsg, elimit, "init() is null"); + goto initer_err_case_unexcept_0; + } + if (self->clean == NULL) { + snprintf(emsg, elimit, "clean() is null"); + goto initer_err_case_unexcept_0; + } + self->clean(self); + + /* Detect transceiver information */ + result = detect_transvr_state(self, detect); + if (result < 0) { + snprintf(emsg, elimit, "detect_transvr_state() fail"); + switch (result) { + case ERR_TRANSVR_I2C_CRASH: + goto initer_err_case_i2c_ceash; + case ERR_TRNASVR_BE_ISOLATED: + goto initer_err_case_be_isolated; + + case ERR_TRANSVR_UNEXCPT: + default: + break; + } + goto initer_err_case_retry_1; + } + d_state = detect[0]; + d_type = detect[1]; + + /* Verify transceiver type and state */ + switch (_is_transvr_valid(self, d_type, d_state)) { + case 0: + break; + case EVENT_TRANSVR_INIT_DOWN: + goto initer_ok_case_down;; + case EVENT_TRANSVR_INIT_FAIL: + snprintf(emsg, elimit, "transceiver type doesn't support"); + goto initer_err_case_alarm_to_user; + case EVENT_TRANSVR_EXCEP_INIT: + default: + goto initer_err_case_unexcept_1; + } + + /* Handle reload case */ + if (self->type != d_type){ + /* This is the protect mechanism. Normally, This case will not happen. + * When State machine detect swap event during initial, It will trigger + * reload function to ensure type correct. */ + if (_reload_transvr_obj(self, d_type) < 0){ + snprintf(emsg, elimit, "reload object fail"); + goto initer_err_case_unexcept_1; + } + } + + /* Check transceiver HW initial ready */ + switch (_is_transvr_hw_ready(self, d_type)) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_err_case_retry_1; + case EVENT_TRANSVR_INIT_FAIL: + default: + goto initer_err_case_unexcept_1; + } + + /* Try to update all and check */ + if (self->update_all(self, 1) < 0){ + /* For some transceiver, EEPROME has lag issues during initial stage. + * In this case, we set status back to STATE_TRANSVR_NEW, than it will + * be checked in next polling cycle. */ + goto initer_err_case_retry_1; + } + + /* Execute init() call back */ + result = self->init(self); + switch (result) { + case EVENT_TRANSVR_TASK_DONE: + break; + case EVENT_TRANSVR_TASK_WAIT: + goto initer_ok_case_wait; + + default: + snprintf(emsg, elimit, "undefined init() return:%d\n", result); + goto initer_err_case_unexcept_1; + } + goto initer_ok_case_up; + + +initer_ok_case_wait: + self->dump_all(self); + return EVENT_TRANSVR_TASK_WAIT; + +initer_ok_case_up: + self->state = STATE_TRANSVR_CONNECTED; + self->temp = 0; + self->dump_all(self); + return EVENT_TRANSVR_INIT_UP; + +initer_ok_case_down: + self->temp = 0; + self->state = STATE_TRANSVR_DISCONNECTED; + return EVENT_TRANSVR_INIT_DOWN; + +initer_err_case_i2c_ceash: + SWPS_DEBUG("%s: %s :%s :I2C crash\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + return EVENT_TRANSVR_I2C_CRASH; + +initer_err_case_be_isolated: + SWPS_DEBUG("%s: %s :%s :isolated\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_ISOLATED; + return EVENT_TRANSVR_EXCEP_ISOLATED; + +initer_err_case_retry_1: + SWPS_DEBUG("%s: %s :%s :retry\n", + __func__, emsg, self->swp_name); + if (_transvr_handle_retry(self, retry) == 0) { + self->state = STATE_TRANSVR_NEW; + return EVENT_TRANSVR_INIT_REINIT; + } + goto initer_err_case_alarm_to_user; + +initer_err_case_unexcept_1: + self->clean(self); +initer_err_case_unexcept_0: + self->state = STATE_TRANSVR_UNEXCEPTED; + if (_is_except_happened_4_pmode(self, d_state) && + (self->mode == TRANSVR_MODE_POLLING) ){ + SWPS_INFO("%s: %s :%s\n", __func__, emsg, self->swp_name); + SWPS_INFO("Dump: :%d :%d :%d :%d\n", + self->state, self->type, d_state, d_type); + } + return EVENT_TRANSVR_INIT_FAIL; + +initer_err_case_alarm_to_user: + SWPS_DEBUG("%s: %s :%s :alarm_to_user\n", + __func__, emsg, self->swp_name); + self->state = STATE_TRANSVR_UNEXCEPTED; + alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard"); + return EVENT_TRANSVR_INIT_FAIL; +} + + +/* ========== Object functions for Clean procedure ========== + */ +int +_transvr_clean_handler(struct transvr_obj_s *self){ + + int retval = DEBUG_TRANSVR_INT_VAL; + + if (!self->clean) { + SWPS_ERR("%s: %s clean() is NULL.\n", + __func__, self->swp_name); + return EVENT_TRANSVR_TASK_FAIL; + } + retval = self->clean(self); + if (retval != EVENT_TRANSVR_TASK_DONE){ + SWPS_ERR("%s: %s clean() fail. [ERR]:%d\n", + __func__, self->swp_name, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +common_transvr_clean(struct transvr_obj_s *self){ + + transvr_task_free_all(self); + return EVENT_TRANSVR_TASK_DONE; +} + + +int +qsfp_transvr_clean(struct transvr_obj_s *self){ + + int retval; + int lpower_config = 1; + + retval = _taskfunc_qsfp_setup_power_mod(self, lpower_config); + if (retval < 0){ + SWPS_ERR("%s: Set lpmod fail! :%d\n", + __func__, retval); + return retval; + } + retval = common_transvr_clean(self); + if (retval < 0){ + SWPS_ERR("%s: common_transvr_clean fail! :%d\n", + __func__, retval); + return retval; + } + return EVENT_TRANSVR_TASK_DONE; +} + + +int +fake_transvr_clean(struct transvr_obj_s *self){ + + return EVENT_TRANSVR_TASK_DONE; +} + + +/* ========== Object functions for check and update ========== + */ +int +common_transvr_check(struct transvr_obj_s *self){ + + char fun_str[32] = "common_transvr_check"; + + if (self->mode != TRANSVR_MODE_POLLING) { + SWPS_ERR("%s: mode:%d is not TRANSVR_MODE_POLLING\n", + fun_str, self->mode); + return ERR_TRANSVR_UNEXCPT; + } + /* Trigger delay task */ + transvr_task_run_all(self); + /* Trigger state machine to check and update */ + return self->fsm_4_polling(self, fun_str); +} + + +int +fake_transvr_check(struct transvr_obj_s *self){ + return 0; +} + + +/* ========== Functions for Factory pattern ========== + */ +static int +setup_transvr_public_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = unsupported_get_func; + self->get_br = common_get_br; + self->get_len_sm = sfp_get_len_sm; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = sfp_get_comp_eth_1; + self->get_comp_eth_10 = sfp_get_comp_eth_10; + self->get_comp_eth_10_40 = unsupported_get_func; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = sfp_get_rate_id; + self->get_soft_rs0 = sfp_get_soft_rs0; + self->get_soft_rs1 = sfp_get_soft_rs1; + self->get_info = common_get_info; + self->get_if_type = sfp_get_if_type; + self->get_if_speed = sfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = sfp_get_transvr_temp; + self->get_curr_vol = sfp_get_transvr_voltage; + self->get_soft_rx_los = unsupported_get_func2; + self->get_soft_tx_disable = unsupported_get_func2; + self->get_soft_tx_fault = unsupported_get_func2; + self->get_auto_tx_disable = unsupported_get_func2; + self->get_tx_bias = sfp_get_transvr_tx_bias; + self->get_tx_power = sfp_get_transvr_tx_power; + self->get_rx_power = sfp_get_transvr_rx_power; + self->get_tx_eq = sfp_get_transvr_tx_eq; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = sfp_get_transvr_rx_em; + self->get_wavelength = sfp_get_wavelength; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = sfp_set_soft_rs0; + self->set_soft_rs1 = sfp_set_soft_rs1; + self->set_soft_tx_disable = unsupported_set_func; + self->set_auto_tx_disable = unsupported_set_func; + self->set_tx_eq = sfp_set_tx_eq; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = sfp_set_rx_em; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = unsupported_get_func; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = unsupported_get_func2; + self->get_rx_am = unsupported_get_func2; + self->get_rx_em = unsupported_get_func2; + self->get_wavelength = qsfp_get_wavelength; + self->set_cdr = unsupported_set_func; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = unsupported_set_func; + self->set_rx_am = unsupported_set_func; + self->set_rx_em = unsupported_set_func; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->get_id = common_get_id; + self->get_ext_id = common_get_ext_id; + self->get_connector = common_get_connector; + self->get_vendor_name = common_get_vendor_name; + self->get_vendor_pn = common_get_vendor_pn; + self->get_vendor_rev = common_get_vendor_rev; + self->get_vendor_sn = common_get_vendor_sn; + self->get_power_cls = qsfp_get_power_cls; + self->get_br = common_get_br; + self->get_len_sm = unsupported_get_func; + self->get_len_smf = common_get_len_smf; + self->get_len_om1 = common_get_len_om1; + self->get_len_om2 = common_get_len_om2; + self->get_len_om3 = common_get_len_om3; + self->get_len_om4 = common_get_len_om4; + self->get_comp_rev = common_get_comp_rev; + self->get_comp_eth_1 = qsfp_get_comp_eth; + self->get_comp_eth_10 = unsupported_get_func; + self->get_comp_eth_10_40 = qsfp_get_comp_10_40; + self->get_comp_extend = common_get_comp_extended; + self->get_cdr = qsfp_get_cdr; + self->get_rate_id = unsupported_get_func; + self->get_soft_rs0 = unsupported_get_func; /* TBD */ + self->get_soft_rs1 = unsupported_get_func; /* TBD */ + self->get_info = common_get_info; + self->get_if_type = qsfp_get_if_type; + self->get_if_speed = qsfp_get_if_speed; + self->get_if_lane = common_get_if_lane; + self->get_curr_temp = qsfp_get_transvr_temp; + self->get_curr_vol = qsfp_get_transvr_voltage; + self->get_soft_rx_los = qsfp_get_soft_rx_los; + self->get_soft_tx_disable = qsfp_get_soft_tx_disable; + self->get_soft_tx_fault = qsfp_get_soft_tx_fault; + self->get_auto_tx_disable = qsfp_get_auto_tx_disable; + self->get_tx_bias = qsfp_get_transvr_tx_bias; + self->get_tx_power = qsfp_get_transvr_tx_power; + self->get_rx_power = qsfp_get_transvr_rx_power; + self->get_tx_eq = qsfp_get_transvr_tx_eq; + self->get_rx_am = qsfp_get_transvr_rx_am; + self->get_rx_em = qsfp_get_transvr_rx_em; + self->get_wavelength = qsfp_get_wavelength; + self->set_cdr = qsfp_set_cdr; + self->set_soft_rs0 = unsupported_set_func; /* TBD */ + self->set_soft_rs1 = unsupported_set_func; /* TBD */ + self->set_soft_tx_disable = qsfp_set_soft_tx_disable; + self->set_auto_tx_disable = qsfp_set_auto_tx_disable; + self->set_tx_eq = qsfp_set_tx_eq; + self->set_rx_am = qsfp_set_rx_am; + self->set_rx_em = qsfp_set_rx_em; + return 0; + + case TRANSVR_TYPE_FAKE: + self->get_id = fake_get_hex; + self->get_ext_id = fake_get_hex; + self->get_connector = fake_get_hex; + self->get_vendor_name = fake_get_str; + self->get_vendor_pn = fake_get_str; + self->get_vendor_rev = fake_get_str; + self->get_vendor_sn = fake_get_str; + self->get_power_cls = fake_get_int; + self->get_br = fake_get_hex; + self->get_len_sm = fake_get_int; + self->get_len_smf = fake_get_int; + self->get_len_om1 = fake_get_int; + self->get_len_om2 = fake_get_int; + self->get_len_om3 = fake_get_int; + self->get_len_om4 = fake_get_int; + self->get_comp_rev = fake_get_hex; + self->get_comp_eth_1 = fake_get_hex; + self->get_comp_eth_10 = fake_get_hex; + self->get_comp_eth_10_40 = fake_get_hex; + self->get_comp_extend = fake_get_hex; + self->get_cdr = fake_get_hex; + self->get_rate_id = fake_get_hex; + self->get_soft_rs0 = fake_get_binary; + self->get_soft_rs1 = fake_get_binary; + self->get_info = fake_get_int; + self->get_if_type = fake_get_str; + self->get_if_speed = fake_get_str; + self->get_if_lane = fake_get_str; + self->get_curr_temp = fake_get_str; + self->get_curr_vol = fake_get_str; + self->get_soft_rx_los = fake_get_str; + self->get_soft_tx_disable = fake_get_str; + self->get_soft_tx_fault = fake_get_str; + self->get_auto_tx_disable = fake_get_str; + self->get_tx_bias = fake_get_str; + self->get_tx_power = fake_get_str; + self->get_rx_power = fake_get_str; + self->get_tx_eq = fake_get_str; + self->get_rx_am = fake_get_str; + self->get_rx_em = fake_get_str; + self->get_wavelength = fake_get_str; + self->set_cdr = fake_set_hex; + self->set_soft_rs0 = fake_set_int; + self->set_soft_rs1 = fake_set_int; + self->set_soft_tx_disable = fake_set_int; + self->set_auto_tx_disable = fake_set_int; + self->set_tx_eq = fake_set_int; + self->set_rx_am = fake_set_int; + self->set_rx_em = fake_set_int; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_transvr_private_cb(struct transvr_obj_s *self, + int transvr_type){ + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + self->init = transvr_init_sfp; + self->clean = common_transvr_clean; + self->check = common_transvr_check; + self->update_all = _sfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = sfp_send_uevent; + self->dump_all = sfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + self->init = transvr_init_qsfp; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_QSFP_28: + self->init = transvr_init_qsfp28; + self->clean = qsfp_transvr_clean; + self->check = common_transvr_check; + self->update_all = _qsfp_update_attr_all; + self->fsm_4_direct = common_fsm_4_direct_mode; + self->fsm_4_polling = common_fsm_4_polling_mode; + self->send_uevent = qsfp_send_uevent; + self->dump_all = qsfp_transvr_dump; + return 0; + + case TRANSVR_TYPE_FAKE: + self->init = transvr_init_fake; + self->clean = fake_transvr_clean; + self->check = fake_transvr_check; + self->update_all = fake_transvr_update; + self->fsm_4_direct = fake_fsm_4_direct_mode; + self->fsm_4_polling = fake_fsm_4_polling_mode; + self->send_uevent = fake_send_uevent; + self->dump_all = fake_transvr_dump; + return 0; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return ERR_TRANSVR_UNEXCPT; +} + + +static struct eeprom_map_s * +get_eeprom_map(int transvr_type){ + + switch (transvr_type){ + case TRANSVR_TYPE_SFP: + return &eeprom_map_sfp; + case TRANSVR_TYPE_QSFP: + case TRANSVR_TYPE_QSFP_PLUS: + return &eeprom_map_qsfp; + case TRANSVR_TYPE_QSFP_28: + return &eeprom_map_qsfp28; + + default: + break; + } + SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type); + return NULL; +} + + +static int +setup_transvr_ssize_attr(char *swp_name, + struct transvr_obj_s *self, + struct eeprom_map_s *map_p, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int chan_id, + int run_mode){ + switch (run_mode){ + case TRANSVR_MODE_DIRECT: /* Direct access device mode */ + case TRANSVR_MODE_POLLING: /* Polling mode, read from cache */ + self->mode = run_mode; + break; + default: + SWPS_ERR("%s: non-defined run_mode:%d\n", + __func__, run_mode); + self->mode = DEBUG_TRANSVR_INT_VAL; + return -1; + } + self->eeprom_map_p = map_p; + self->ioexp_obj_p = ioexp_obj_p; + self->ioexp_virt_offset = ioexp_virt_offset; + self->chan_id = chan_id; + self->layout = transvr_type; + self->type = transvr_type; + self->chipset_type = chipset_type; + self->state = STATE_TRANSVR_NEW; + self->info = STATE_TRANSVR_NEW; + self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE; + strncpy(self->swp_name, swp_name, 32); + mutex_init(&self->lock); + return 0; +} + + +static int +setup_transvr_dsize_attr(struct transvr_obj_s *self){ + + char *emsg = DEBUG_TRANSVR_STR_VAL; + + self->vendor_name = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_name){ + emsg = "vendor_name"; + goto err_setup_d_attr; + } + self->vendor_pn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_pn){ + emsg = "vendor_pn"; + goto err_setup_d_attr; + } + self->vendor_rev = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_rev){ + emsg = "vendor_rev"; + goto err_setup_d_attr; + } + self->vendor_sn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL); + if (!self->vendor_sn){ + emsg = "vendor_sn"; + goto err_setup_d_attr; + } + self->worker_p = NULL; + return 0; + +err_setup_d_attr: + SWPS_ERR("%s: %s kzalloc fail!", __func__, emsg); + return ERR_TRANSVR_UNEXCPT; +} + + +static int +setup_i2c_client(struct transvr_obj_s *self){ + + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + adap = i2c_get_adapter(self->chan_id); + if(!adap){ + snprintf(err_msg, sizeof(err_msg), + "can not get adap:%d", self->chan_id); + goto err_setup_i2c_client; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client){ + snprintf(err_msg, sizeof(err_msg), + "can not kzalloc client:%d", self->chan_id); + goto err_setup_i2c_client; + } + client->adapter = adap; + self->i2c_client_p = client; + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + return 0; + +err_setup_i2c_client: + SWPS_ERR("%s: %s\n", __func__, err_msg); + return ERR_TRANSVR_UNEXCPT; +} + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode){ + + struct transvr_obj_s *result_p; + struct eeprom_map_s *map_p; + char err_msg[64] = DEBUG_TRANSVR_STR_VAL; + + /* Allocate transceiver object */ + map_p = get_eeprom_map(transvr_type); + if (!map_p){ + snprintf(err_msg, sizeof(err_msg), + "Invalid transvr_type:%d", transvr_type); + goto err_create_transvr_fail; + } + result_p = kzalloc(sizeof(*result_p), GFP_KERNEL); + if (!result_p){ + snprintf(err_msg, sizeof(err_msg), "kzalloc fail"); + goto err_create_transvr_fail; + } + /* Prepare static size attributes */ + if (setup_transvr_ssize_attr(swp_name, + result_p, + map_p, + ioexp_obj_p, + ioexp_virt_offset, + transvr_type, + chipset_type, + chan_id, + run_mode) < 0){ + goto err_create_transvr_sattr_fail; + } + /* Prepare dynamic size attributes */ + if (setup_transvr_dsize_attr(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_public_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare call back functions of object */ + if (setup_transvr_private_cb(result_p, transvr_type) < 0){ + goto err_create_transvr_dattr_fail; + } + /* Prepare i2c client object */ + if (setup_i2c_client(result_p) < 0){ + goto err_create_transvr_dattr_fail; + } + return result_p; + +err_create_transvr_dattr_fail: + kfree(result_p->vendor_sn); + kfree(result_p->vendor_rev); + kfree(result_p->vendor_pn); + kfree(result_p->vendor_name); +err_create_transvr_sattr_fail: + kfree(result_p); +err_create_transvr_fail: + SWPS_ERR("%s: %s :%d :%d :%d\n", + __func__, err_msg, chan_id, ioexp_virt_offset, transvr_type); + return NULL; +} + + +static int +_reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + struct eeprom_map_s *new_map_p; + struct eeprom_map_s *old_map_p = self->eeprom_map_p; + struct i2c_client *old_i2c_p = self->i2c_client_p; + int old_type = self->type; + + /* Change state to STATE_TRANSVR_INIT */ + self->state = STATE_TRANSVR_INIT; + self->type = new_type; + /* Replace EEPROME map */ + new_map_p = get_eeprom_map(new_type); + if (!new_map_p){ + goto err_private_reload_func_1; + } + self->eeprom_map_p = new_map_p; + /* Reload i2c client */ + if (setup_i2c_client(self) < 0){ + goto err_private_reload_func_2; + } + /* Replace call back functions */ + if (setup_transvr_public_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + if (setup_transvr_private_cb(self, new_type) < 0){ + goto err_private_reload_func_3; + } + kfree(old_i2c_p); + return 0; + +err_private_reload_func_3: + SWPS_INFO("%s: init() fail!\n", __func__); + kfree(old_i2c_p); + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = TRANSVR_TYPE_ERROR; + return -2; + +err_private_reload_func_2: + self->eeprom_map_p = old_map_p; + self->i2c_client_p = old_i2c_p; +err_private_reload_func_1: + self->state = STATE_TRANSVR_UNEXCEPTED; + self->type = old_type; + SWPS_INFO("%s fail! :0x%02x\n", __func__, new_type); + return -1; +} + + +static int +reload_transvr_obj(struct transvr_obj_s *self, + int new_type){ + + int result_val = ERR_TRANSVR_UNEXCPT; + + /* Reload phase */ + result_val = _reload_transvr_obj(self, new_type); + if (result_val < 0){ + SWPS_INFO("%s: reload phase fail! :%d\n", + __func__, result_val); + return EVENT_TRANSVR_RELOAD_FAIL; + } + /* Initial phase */ + result_val = _transvr_init_handler(self); + if (result_val < 0){ + SWPS_INFO("%s: initial phase fail! :%d\n", + __func__, result_val); + } + return result_val; +} + + +int +isolate_transvr_obj(struct transvr_obj_s *self) { + + self->state = STATE_TRANSVR_ISOLATED; + SWPS_INFO("%s: %s be isolated\n", __func__, self->swp_name); + return 0; +} + + +int +resync_channel_tier_2(struct transvr_obj_s *self) { + + int val = TRANSVR_TYPE_ERROR; + + if (self->state == STATE_TRANSVR_ISOLATED) { + return 0; + } + self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS; + val = i2c_smbus_read_byte_data(self->i2c_client_p, + VAL_TRANSVR_COMID_OFFSET); + if (val < 0) { + return -1; + } + return 0; +} + + +/* ----------------------------------------- + * ToDo List + * ----------------------------------------- + * 1. _sfp_detect_class_by_feature() + * => Need check ACC use case. + * 2. _sfp_detect_class_by_1g_ethernet() + * => Need check 0.1G use case. + * 3. Loopback transceiver use case. + * => Less much data + * 4. _qsfp_detect_class_by_extend_comp() + * => Verify 100G CWDM4 + * => Verify Obsolete (assigned before 100G CWDM4 MSA required FEC) + * => Verify 100G CLR4 + * => Verify 100GE-DWDM2 + * => Verify 40G PSM4 Parallel SMF + * => Verify 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. + * => Verify 100G ACC or 25GAUI C2M ACC. + * => Verify 25GBASE-LR + * => Verify 40G Active Cable (XLPPI) + */ + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.h new file mode 100644 index 000000000000..ddd22c38caf0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/modules/transceiver.h @@ -0,0 +1,792 @@ +#ifndef TRANSCEIVER_H +#define TRANSCEIVER_H + +#include + +/* advanced features control */ +#define TRANSVR_INFO_DUMP_ENABLE (1) +#define TRANSVR_INFO_CACHE_ENABLE (1) +#define TRANSVR_UEVENT_ENABLE (1) + +/* Transceiver type define */ +#define TRANSVR_TYPE_UNKNOW_1 (0x00) +#define TRANSVR_TYPE_UNKNOW_2 (0xff) +#define TRANSVR_TYPE_SFP (0x03) /* Define for SFP, SFP+, SFP28 */ +#define TRANSVR_TYPE_QSFP (0x0c) +#define TRANSVR_TYPE_QSFP_PLUS (0x0d) +#define TRANSVR_TYPE_QSFP_28 (0x11) +#define TRANSVR_TYPE_UNPLUGGED (0xfa) /* Define for ERROR handle */ +#define TRANSVR_TYPE_FAKE (0xfc) /* Define for ERROR handle */ +#define TRANSVR_TYPE_INCONSISTENT (0xfd) /* Define for ERROR handle */ +#define TRANSVR_TYPE_ERROR (0xfe) /* Define for ERROR handle */ + +/* Transceiver class for base info */ +#define TRANSVR_CLASS_UNSPECIFIED (0) +#define TRANSVR_CLASS_ERROR (-26001) +#define TRANSVR_CLASS_1G (26001) +#define TRANSVR_CLASS_10G (26011) +#define TRANSVR_CLASS_25G (26021) +#define TRANSVR_CLASS_40G (26041) +#define TRANSVR_CLASS_100G (26101) +#define TRANSVR_CLASS_NO_SPERARABLE (26901) +#define TRANSVR_CLASS_EXTEND_COMP (26902) +/* Transceiver class for Optical 1G */ +#define TRANSVR_CLASS_OPTICAL (27000) +#define TRANSVR_CLASS_OPTICAL_100 (27001) +#define TRANSVR_CLASS_OPTICAL_1G (27002) +#define TRANSVR_CLASS_OPTICAL_1G_AOC (27003) +#define TRANSVR_CLASS_OPTICAL_1G_SX (27004) +#define TRANSVR_CLASS_OPTICAL_1G_LX (27005) +#define TRANSVR_CLASS_OPTICAL_1G_EX (27006) +/* Transceiver class for Optical 10G */ +#define TRANSVR_CLASS_OPTICAL_10G (27010) +#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011) +#define TRANSVR_CLASS_OPTICAL_10G_S_SR (27012) +#define TRANSVR_CLASS_OPTICAL_10G_S_LR (27013) +#define TRANSVR_CLASS_OPTICAL_10G_S_ER (27014) +#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015) +#define TRANSVR_CLASS_OPTICAL_10G_Q_SR (27016) +#define TRANSVR_CLASS_OPTICAL_10G_Q_LR (27017) +#define TRANSVR_CLASS_OPTICAL_10G_Q_ER (27018) +/* Transceiver class for Optical 25G */ +#define TRANSVR_CLASS_OPTICAL_25G (27020) +#define TRANSVR_CLASS_OPTICAL_25G_AOC (27021) +#define TRANSVR_CLASS_OPTICAL_25G_SR (27022) +#define TRANSVR_CLASS_OPTICAL_25G_LR (27023) +#define TRANSVR_CLASS_OPTICAL_25G_ER (27024) +/* Transceiver class for Optical 40G */ +#define TRANSVR_CLASS_OPTICAL_40G (27040) +#define TRANSVR_CLASS_OPTICAL_40G_AOC (27041) +#define TRANSVR_CLASS_OPTICAL_40G_SR4 (27042) +#define TRANSVR_CLASS_OPTICAL_40G_LR4 (27043) +#define TRANSVR_CLASS_OPTICAL_40G_ER4 (27044) +/* Transceiver class for Optical 100G */ +#define TRANSVR_CLASS_OPTICAL_100G (27100) +#define TRANSVR_CLASS_OPTICAL_100G_AOC (27101) +#define TRANSVR_CLASS_OPTICAL_100G_SR4 (27102) +#define TRANSVR_CLASS_OPTICAL_100G_LR4 (27103) +#define TRANSVR_CLASS_OPTICAL_100G_ER4 (27104) +#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105) +/* Transceiver class for Copper */ +#define TRANSVR_CLASS_COPPER (28000) +#define TRANSVR_CLASS_COPPER_L1_1G (28001) +#define TRANSVR_CLASS_COPPER_L1_10G (28011) +#define TRANSVR_CLASS_COPPER_L4_10G (28012) +#define TRANSVR_CLASS_COPPER_L1_25G (28021) +#define TRANSVR_CLASS_COPPER_L4_40G (28041) +#define TRANSVR_CLASS_COPPER_L4_100G (28101) +/* Transceiver class for Base-T */ +#define TRANSVR_CLASS_BASE_T_1000 (29001) +#define TRANSVR_CLASS_BASE_T_1000_up (29002) +/* For uevent message */ +#define TRANSVR_UEVENT_KEY_IF "IF_TYPE" +#define TRANSVR_UEVENT_KEY_SP "IF_SPEED" +#define TRANSVR_UEVENT_KEY_LANE "IF_LANE" +#define TRANSVR_UEVENT_UNKNOW "UNKNOW" +#define TRANSVR_IF_KR "KR" +#define TRANSVR_IF_KR4 "KR4" +#define TRANSVR_IF_SR "SR" +#define TRANSVR_IF_SR4 "SR4" +#define TRANSVR_IF_SFI "SFI" +#define TRANSVR_IF_IF_GMII "GMII" +#define TRANSVR_IF_IF_XGMII "XGMII" +#define TRANSVR_IF_SP_100 "100" +#define TRANSVR_IF_SP_1G "1000" +#define TRANSVR_IF_SP_10G "10000" +#define TRANSVR_IF_SP_25G "25000" +#define TRANSVR_IF_SP_40G "40000" +#define TRANSVR_IF_SP_100G "100000" + +/* Transceiver mode define */ +#define TRANSVR_MODE_DIRECT (21000) +#define TRANSVR_MODE_POLLING (21001) + +/* Transceiver state define + * [Note] + * 1. State is used to represent the state of "Transceiver" and "Object". + * 2. State for different target has different means. The description as following: + */ +#define STATE_TRANSVR_CONNECTED (0) /* [Transvr]:Be plugged in. [Obj]:Link up, and work normally. */ +#define STATE_TRANSVR_NEW (-100) /* [Transvr]:(Not used) [Obj]:Create */ +#define STATE_TRANSVR_INIT (-101) /* [Transvr]:Be plugged in. [Obj]:Link up, and in initial process. */ +#define STATE_TRANSVR_ISOLATED (-102) /* [Transvr]:Be plugged in. [Obj]:Isolate, and not provide service. */ +#define STATE_TRANSVR_SWAPPED (-200) /* [Transvr]:Be plugged in. [Obj]:(Not used) */ +#define STATE_TRANSVR_DISCONNECTED (-300) /* [Transvr]:Un-plugged. [Obj]:Link down, and not provide service. */ +#define STATE_TRANSVR_UNEXCEPTED (-901) /* [Transvr]:Any [Obj]:Any, and not in expect case. */ + +/* Task state define */ +#define STATE_T_TASK_WAIT (110) +#define STATE_T_TASK_DONE (0) +#define STATE_T_TASK_INIT (-110) +#define STATE_T_TASK_FAIL (-410) + + +/* Event for task handling */ +#define EVENT_TRANSVR_TASK_WAIT (2101) +#define EVENT_TRANSVR_TASK_DONE (0) +#define EVENT_TRANSVR_TASK_FAIL (-2101) +/* Event for initial handling */ +#define EVENT_TRANSVR_INIT_UP (2201) +#define EVENT_TRANSVR_INIT_DOWN (1) +#define EVENT_TRANSVR_INIT_REINIT (-2201) +#define EVENT_TRANSVR_INIT_FAIL (-2202) +/* Event for others */ +#define EVENT_TRANSVR_RELOAD_FAIL (-2301) +#define EVENT_TRANSVR_EXCEP_INIT (-2401) +#define EVENT_TRANSVR_EXCEP_UP (-2402) +#define EVENT_TRANSVR_EXCEP_DOWN (-2403) +#define EVENT_TRANSVR_EXCEP_SWAP (-2404) +#define EVENT_TRANSVR_EXCEP_EXCEP (-2405) +#define EVENT_TRANSVR_EXCEP_ISOLATED (-2406) +#define EVENT_TRANSVR_I2C_CRASH (-2501) + +/* Transceiver error code define */ +#define ERR_TRANSVR_UNINIT (-201) +#define ERR_TRANSVR_UNPLUGGED (-202) +#define ERR_TRANSVR_ABNORMAL (-203) +#define ERR_TRANSVR_NOSTATE (-204) +#define ERR_TRANSVR_NOTSUPPORT (-205) +#define ERR_TRANSVR_BADINPUT (-206) +#define ERR_TRANSVR_UPDATE_FAIL (-207) +#define ERR_TRANSVR_RELOAD_FAIL (-208) +#define ERR_TRANSVR_INIT_FAIL (-209) +#define ERR_TRANSVR_UNDEFINED (-210) +#define ERR_TRANSVR_TASK_FAIL (-211) +#define ERR_TRANSVR_TASK_BUSY (-212) +#define ERR_TRANSVR_UEVENT_FAIL (-213) +#define ERR_TRANSVR_FUNC_DISABLE (-214) +#define ERR_TRANSVR_I2C_CRASH (-297) +#define ERR_TRNASVR_BE_ISOLATED (-298) +#define ERR_TRANSVR_UNEXCPT (-299) + +/* For debug */ +#define DEBUG_TRANSVR_INT_VAL (-99) +#define DEBUG_TRANSVR_HEX_VAL (0xfe) +#define DEBUG_TRANSVR_STR_VAL "ERROR" + +/* For system internal */ +#define VAL_TRANSVR_COMID_ARREESS (0x50) +#define VAL_TRANSVR_COMID_OFFSET (0x00) +#define VAL_TRANSVR_8472_READY_ADDR (0x51) +#define VAL_TRANSVR_8472_READY_PAGE (-1) +#define VAL_TRANSVR_8472_READY_OFFSET (110) +#define VAL_TRANSVR_8472_READY_BIT (0) +#define VAL_TRANSVR_8472_READY_VALUE (0) +#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_READY_ADDR (0x50) +#define VAL_TRANSVR_8436_READY_PAGE (-1) +#define VAL_TRANSVR_8436_READY_OFFSET (2) +#define VAL_TRANSVR_8436_READY_BIT (0) +#define VAL_TRANSVR_8436_READY_VALUE (0) +#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff) +#define VAL_TRANSVR_8436_PWD_ADDR (0x50) +#define VAL_TRANSVR_8436_PWD_PAGE (-1) +#define VAL_TRANSVR_8436_PWD_OFFSET (123) +#define VAL_TRANSVR_PAGE_FREE (-99) +#define VAL_TRANSVR_PAGE_SELECT_OFFSET (127) +#define VAL_TRANSVR_PAGE_SELECT_DELAY (5) +#define VAL_TRANSVR_TASK_RETRY_FOREVER (-999) +#define VAL_TRANSVR_FUNCTION_DISABLE (-1) +#define STR_TRANSVR_SFP "SFP" +#define STR_TRANSVR_QSFP "QSFP" +#define STR_TRANSVR_QSFP_PLUS "QSFP+" +#define STR_TRANSVR_QSFP28 "QSFP28" + +/* For transvr buf len */ +#define LEN_TRANSVR_S_STR (16) +#define LEN_TRANSVR_M_STR (32) +#define LEN_TRANSVR_L_STR (64) + +/* Optical wavelength */ +#define VAL_OPTICAL_WAVELENGTH_SR (850) +#define VAL_OPTICAL_WAVELENGTH_LR (1310) +#define VAL_OPTICAL_WAVELENGTH_ER (1550) + +/* BCM chip type define */ +#define BCM_CHIP_TYPE_TRIDENT_2 (31001) /* Magnolia, Hudson32i, Spruce */ +#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress */ + +/* Info from transceiver EEPROM */ +struct eeprom_map_s { + int addr_br; int page_br; int offset_br; int length_br; + int addr_cdr; int page_cdr; int offset_cdr; int length_cdr; + int addr_comp_rev; int page_comp_rev; int offset_comp_rev; int length_comp_rev; + int addr_connector; int page_connector; int offset_connector; int length_connector; + int addr_diag_type; int page_diag_type; int offset_diag_type; int length_diag_type; + int addr_extbr; int page_extbr; int offset_extbr; int length_extbr; + int addr_ext_id; int page_ext_id; int offset_ext_id; int length_ext_id; + int addr_id; int page_id; int offset_id; int length_id; + int addr_len_sm; int page_len_sm; int offset_len_sm; int length_len_sm; + int addr_len_smf; int page_len_smf; int offset_len_smf; int length_len_smf; + int addr_len_om1; int page_len_om1; int offset_len_om1; int length_len_om1; + int addr_len_om2; int page_len_om2; int offset_len_om2; int length_len_om2; + int addr_len_om3; int page_len_om3; int offset_len_om3; int length_len_om3; + int addr_len_om4; int page_len_om4; int offset_len_om4; int length_len_om4; + int addr_option; int page_option; int offset_option; int length_option; + int addr_rate_id; int page_rate_id; int offset_rate_id; int length_rate_id; + int addr_rx_am; int page_rx_am; int offset_rx_am; int length_rx_am; + int addr_rx_em; int page_rx_em; int offset_rx_em; int length_rx_em; + int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los; + int addr_rx_power; int page_rx_power; int offset_rx_power; int length_rx_power; + int addr_soft_rs0; int page_soft_rs0; int offset_soft_rs0; int length_soft_rs0; + int addr_soft_rs1; int page_soft_rs1; int offset_soft_rs1; int length_soft_rs1; + int addr_temp; int page_temp; int offset_temp; int length_temp; + int addr_trancomp; int page_trancomp; int offset_trancomp; int length_trancomp; + int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext; + int addr_tx_bias; int page_tx_bias; int offset_tx_bias; int length_tx_bias; + int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable; + int addr_tx_eq; int page_tx_eq; int offset_tx_eq; int length_tx_eq; + int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault; + int addr_tx_power; int page_tx_power; int offset_tx_power; int length_tx_power; + int addr_vendor_name; int page_vendor_name; int offset_vendor_name; int length_vendor_name; + int addr_vendor_pn; int page_vendor_pn; int offset_vendor_pn; int length_vendor_pn; + int addr_vendor_rev; int page_vendor_rev; int offset_vendor_rev; int length_vendor_rev; + int addr_vendor_sn; int page_vendor_sn; int offset_vendor_sn; int length_vendor_sn; + int addr_voltage; int page_voltage; int offset_voltage; int length_voltage; + int addr_wavelength; int page_wavelength; int offset_wavelength; int length_wavelength; +}; + + +struct transvr_worker_s; + +/* Class of transceiver object */ +struct transvr_obj_s { + + /* ========== Object private property ========== + * [Prop]: id + * [Desc]: Type of serial transceiver. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h + */ + uint8_t id; + + /* [Prop]: connector + * [Desc]: Connector type. + * [Note]: SFP : A0h / 2 + * QSFP: 00h / 130 + */ + uint8_t connector; + + /* [Prop]: transvr_comp + * [Desc]: Transceiver compliance code. + * [Note]: SFP: SFF-8472 + * - Normal : A0h / offset 3-10 + * - Extended: A0h / offset 36 + * QSFP: SFF-8436 & SFF-8636 + * - Normal : 00h / offset 131-138 + * - Extended: 00h / offset 192 + */ + uint8_t transvr_comp[8]; + uint8_t transvr_comp_ext; + + /* [Prop]: vendor_name + * [Desc]: SFP vendor name (ASCII 16 byte char). + * [Note]: ex:FINISAR CORP. + */ + char *vendor_name; + + /* [Prop]: vendor_pn + * [Desc]: Part number provided by SFP vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_pn; + + /* [Prop]: vendor_rev + * [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char). + * [Note]: + */ + char *vendor_rev; + + /* [Prop]: vendor_sn + * [Desc]: Serial number provided by vendor (ASCII 16 byte char). + * [Note]: + */ + char *vendor_sn; + + /* [Prop]: Extended identifier + * [Desc]: SFP: + * => None + * + * QSFP: + * => This byte contained two information: + * (1) Power consumption class + * (2) CDR function present + * [Note]: Bit description as below: + * [SFP] + * None + * + * [QSFP] + * (1) Power consumption class: + * Class 1: 1.5W (Bit6-7 = 00:) + * Class 2: 2.0W (Bit6-7 = 01:) + * Class 3: 2.5W (Bit6-7 = 10:) + * Class 4: 3.5W (Bit6-7 = 11:) + * Class 5: 4.0W (Bit0-1 = 01:) + * Class 6: 4.5W (Bit0-1 = 10:) + * Class 7: 5.0W (Bit0-1 = 11:) + * (2) CDR function present: + * Bit2: 0 = No CDR in RX + * 1 = CDR present in RX + * Bit3: 0 = No CDR in TX + * 1 = CDR present in TX + */ + uint8_t ext_id; + + /* [Prop]: br + * [Desc]: Nominal bit rate, units of 100 MBits/sec. + * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh + * has val: 0x67 + * no val : + */ + uint8_t br; + + /* [Prop]: extbr + * [Desc]: Extended br (00h/222) + * [Desc]: Nominal bit rate per channel, units of 250 Mbps. + * Complements. Byte 140. See Table 32A. + */ + uint8_t extbr; + + /* [Prop]: len_sm + * [Desc]: Length (single mode)-(100's)m + * [Note]: This value specifies the link length that is supported by the transceiver + * while operating in compliance with the applicable standards using single mode + * fiber. The value is in units of 100 meters. A value of 255 means that the + * transceiver supports a link length greater than 25.4 km. A value of zero means + * that the transceiver does not support single mode fiber or that the length + * information must be determined from the transceiver technology. + */ + int len_sm; + + /* [Prop]: len_smf + * [Desc]: Length (single mode)-km + * [Note]: Addition to EEPROM data from original GBIC definition. This value specifies + * the link length that is supported by the transceiver while operating in + * compliance with the applicable standards using single mode fiber. The value + * is in units of kilometers. A value of 255 means that the transceiver supports + * a link length greater than 254 km. A value of zero means that the transceiver + * does not support single mode fiber or that the length information must be + * determined from the transceiver technology. + */ + int len_smf; + + /* [Prop]: len_om1 + * [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om1; + + /* [Prop]: len_om2 + * [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m + * [Note]: The value is in units of 10 meters. A value of 255 means that the + * transceiver supports a link length greater than 2.54 km. A value of + * zero means that the transceiver does not support 50 micron multi-mode + * fiber or that the length information must be determined from the transceiver + * technology. + */ + int len_om2; + + /* [Prop]: len_om3 + * [Desc]: Length (50um, OM3) + * [Note]: This value specifies link length that is supported by the transceiver while + * operating in compliance with applicable standards using 50 micron multimode + * OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255 + * means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber + * or that the length information must be determined from the transceiver technology. + */ + int len_om3; + + /* [Prop]: len_om4 + * [Desc]: Length (50um, OM4) and Length (Active Cable or Copper) + * [Note]: For optical links, this value specifies link length that is supported by the + * transceiver while operating in compliance with applicable standards using 50 micron + * multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of + * 255 means that the transceiver supports a link length greater than 2.54 km. A value + * of zero means that the transceiver does not support 50 micron multimode fiber or that + * the length information must be determined from the transceiver codes specified in Table 5-3. + * + * For copper links, this value specifies minimum link length supported by the transceiver + * while operating in compliance with applicable standards using copper cable. For active + * cable, this value represents actual length. The value is in units of 1 meter. A value of 255 + * means the transceiver supports a link length greater than 254 meters. A value of zero means + * the transceiver does not support copper or active cables or the length information must be + * determined from transceiver technology. Further information about cable design, equalization, + * and connectors is usually required to guarantee meeting a particular length requirement. + */ + int len_om4; + + /* [Prop]: comp_rev + * [Desc]: SFF spec revision compliance + * [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver + * complies with. (unsigned integer) + */ + uint8_t comp_rev; + + /* [Prop]: CDR + * [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal + * retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which + * directs traffic around the internal CDR. (Reference: SFF-8636) + * [Note]: value=0xff: ON. + * value=0x00: OFF. + */ + uint8_t cdr; + + /* [Prop]: rate_id + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Addr: A0h / Offset: 13 + * 2. Value description: + * 00h Unspecified + * 01h SFF-8079 (4/2/1G Rate_Select & AS0/AS1) + * 02h SFF-8431 (8/4/2G Rx Rate_Select only) + * 03h Unspecified * + * 04h SFF-8431 (8/4/2G Tx Rate_Select only) + * 05h Unspecified * + * 06h SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) + * 07h Unspecified * + * 08h FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G + * 09h Unspecified * + * 0Ah FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only, + * Low=8G/4G + * 0Bh Unspecified * + * 0Ch FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select) + * High=32G only, Low = 16G/8G + * 0Dh Unspecified * + * 0Eh 10/8G Rx and Tx Rate_Select controlling the operation or locking + * modes of the internal signal conditioner, retimer or CDR, according + * to the logic table defined in Table 10-2, High Bit Rate + * (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode, + * the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11) + * and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1. + * 0Fh Unspecified * + * 10h-FFh Unallocated + */ + int rate_id; + + /* [Prop]: soft_rs0 + * [Desc]: Soft Rate Select 0(RX). + * [Note]: 1. Writing '1' selects full bandwidth operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 110 / Bit: 3 + */ + uint8_t soft_rs0; + + /* [Prop]: soft_rs1 + * [Desc]: Soft Rate Select 1(TX). + * [Note]: 1. Writing '1' selects full bandwidth TX operation. + * 2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value. + * 3. Default at power up is logic zero/low + * 4. Addr: A2h / Offset: 118 / Bit: 3 + */ + uint8_t soft_rs1; + + /* [Prop]: diag_type + * [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92) + * [Note]: Description in SFF-8472 as below: + * Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance + * with this document. + * Bit6: Digital diagnostic monitoring implemented (described in this document). + * Must be '1' for compliance with this document. + * Bit5 Internally calibrated + * Bit4 Externally calibrated + * Bit3 Received power measurement type.0 = OMA, 1 = average power + * Bit2 Address change required see section above, "addressing modes" + * Bit1-0 Unallocated + */ + uint8_t diag_type; + + /* [Prop]: curr_temp + * [Desc]: Transceiver Current Temperature (A2h/96-97) + * [Note]: 1. Dependent on diag_type. + * 2. 96: High byte + * 3. 97: Low byte + * 4. This feature only for SFP + */ + uint8_t curr_temp[2]; + + /* [Prop]: curr_vol + * [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23) + * [Note]: 1. Dependent on diag_type. + * 2. 98: High byte + * 3. 99: Low byte + * 4. This feature only for SFP + * 5. Internally measured transceiver supply voltage. Represented + * as a 16 bit unsigned integer with the voltage defined as the + * full 16 bit value (0-65535) with LSB equal to 100 uVolt, + * yielding a total range of 0 to +6.55 Volts + */ + uint8_t curr_voltage[2]; + + /* [Prop]: curr_tx_bias + * [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27) + * [Note]: 1. Dependent on diag_type. + * 2. 100: High byte + * 3. 101: Low byte + * 4. This feature only for SFP + * 5. Measured TX bias current in uA. Represented as a 16 bit unsigned + * integer with the current defined as the full 16 bit value (0-65535) + * with LSB equal to 2 uA, yielding a total range of 0 to 131 mA. + * Accuracy is vendor specific but must be better than 10% of the + * manufacturer's nominal value over specified operating temperature + * and voltage. + */ + uint8_t curr_tx_bias[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured TX output power in mW. Represented as a 16 bit unsigned + * integer with the power defined as the full 16 bit value (0-65535) + * with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW + * (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of + * laser monitor photodiode current. It is factory calibrated to absolute + * units using the most representative fiber output type. Accuracy is + * vendor specific but must be better than 3dB over specified temperature + * and voltage. Data is not valid when the transmitter is disabled. + */ + uint8_t curr_tx_power[8]; + + /* [Prop]: curr_tx_power + * [Desc]: Transceiver TX Output Power (A2h/102-103) + * [Note]: 1. Dependent on diag_type. + * 2. 102: High byte + * 3. 103: Low byte + * 4. This feature only for SFP + * 5. Measured RX received optical power in mW. Value can represent either + * average received power or OMA depending upon how bit 3 of byte 92 (A0h) + * is set. Represented as a 16 bit unsigned integer with the power defined + * as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a + * total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is + * dependent upon the exact optical wavelength. For the vendor specified + * wavelength, accuracy shall be better than 3dB over specified temperature + * and voltage. + */ + uint8_t curr_rx_power[8]; + + /* [Prop]: wavelength + * [Desc]: Wavelength or Copper Cable Attenuation + * [Note]: (Following is info from SFF-8636) + * For optical free side devices, this parameter identifies the nominal + * transmitter output wavelength at room temperature. This parameter is a + * 16-bit hex value with Byte 186 as high order byte and Byte 187 as low + * order byte. The laser wavelength is equal to the 16-bit integer value + * divided by 20 in nm (units of 0.05 nm). This resolution should be adequate + * to cover all relevant wavelengths yet provide enough resolution for all + * expected DWDM applications. For accurate representation of controlled + * wavelength applications, this value should represent the center of the + * guaranteed wavelength range. If the free side device is identified as + * copper cable these registers will be used to define the cable attenuation. + * An indication of 0 dB attenuation refers to the case where the attenuation + * is not known or is unavailable. + * Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB. + * Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB. + */ + uint8_t wavelength[2]; + + /* [Prop]: Amplitude control + * [Desc]: Amplitude control + * [Note]: QSFP28 => SFF-8636 03H Byte-238/239 + */ + uint8_t rx_am[2]; + + /* [Prop]: Emphasis control + * [Desc]: Emphasis control + * [Note]: SFP+/28 => SFF-8472 A2H Byte-115 + * QSFP28 => SFF-8636 03H Byte-236/237 + */ + uint8_t rx_em[2]; + + /* [Prop]: Soft Rx LOS + * [Desc]: Soft Rx LOS which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 3: + * - Bit 0: L-Rx1 LOS + * - Bit 1: L-Rx2 LOS + * - Bit 2: L-Rx3 LOS + * - Bit 3: L-Rx4 LOS + */ + uint8_t rx_los; + + /* [Prop]: Soft Tx Disable + * [Desc]: Soft Tx Disable which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Disable + * - Bit 1: Tx2 Disable + * - Bit 2: Tx3 Disable + * - Bit 3: Tx4 Disable + */ + uint8_t tx_disable; + + /* [Prop]: Soft Tx Fault + * [Desc]: Soft Tx Fault which provide by transceiver + * [Note]: (Following is info from SFF-8636) + * Byte 86: + * - Bit 0: Tx1 Fault + * - Bit 1: Tx2 Fault + * - Bit 2: Tx3 Fault + * - Bit 3: Tx4 Fault + */ + uint8_t tx_fault; + + /* [Prop]: Transceiver EQUALIZATION + * [Desc]: Transceiver EQUALIZATION + * [Note]: SFP+/28 => SFF-8472 A2H Byte-114 + * QSFP28 => SFF-8636 03H Byte-234/235 + */ + uint8_t tx_eq[2]; + + /* [Prop]: OPTION VALUES + * [Desc]: The bits in the option field shall specify the options implemented in the transceiver. + * [Note]: SFP+/28 => SFF-8472 A0H Byte-64/65 + * QSFP+/28 => SFF-8636 00H Byte-193/195 + */ + uint8_t option[3]; + + + /* ========== Object private property ========== + */ + struct device *transvr_dev_p; + struct eeprom_map_s *eeprom_map_p; + struct i2c_client *i2c_client_p; + struct ioexp_obj_s *ioexp_obj_p; + struct transvr_worker_s *worker_p; + struct mutex lock; + char swp_name[32]; + int auto_config; + int auto_tx_disable; + int chan_id; + int chipset_type; + int curr_page; + int info; + int ioexp_virt_offset; + int lane_id[8]; + int layout; + int mode; + int retry; + int state; + int temp; + int type; + + /* ========== Object public functions ========== + */ + int (*get_id)(struct transvr_obj_s *self); + int (*get_ext_id)(struct transvr_obj_s *self); + int (*get_connector)(struct transvr_obj_s *self); + int (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p); + int (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p); + int (*get_power_cls)(struct transvr_obj_s *self); + int (*get_br)(struct transvr_obj_s *self); + int (*get_len_sm)(struct transvr_obj_s *self); + int (*get_len_smf)(struct transvr_obj_s *self); + int (*get_len_om1)(struct transvr_obj_s *self); + int (*get_len_om2)(struct transvr_obj_s *self); + int (*get_len_om3)(struct transvr_obj_s *self); + int (*get_len_om4)(struct transvr_obj_s *self); + int (*get_comp_rev)(struct transvr_obj_s *self); + int (*get_comp_eth_1)(struct transvr_obj_s *self); + int (*get_comp_eth_10)(struct transvr_obj_s *self); + int (*get_comp_eth_10_40)(struct transvr_obj_s *self); + int (*get_comp_extend)(struct transvr_obj_s *self); + int (*get_cdr)(struct transvr_obj_s *self); + int (*get_rate_id)(struct transvr_obj_s *self); + int (*get_soft_rs0)(struct transvr_obj_s *self); + int (*get_soft_rs1)(struct transvr_obj_s *self); + int (*get_info)(struct transvr_obj_s *self); + int (*get_if_type)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_speed)(struct transvr_obj_s *self, char *buf_p); + int (*get_if_lane)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p); + int (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p); + int (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_power)(struct transvr_obj_s *self, char *buf_p); + int (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_am)(struct transvr_obj_s *self, char *buf_p); + int (*get_rx_em)(struct transvr_obj_s *self, char *buf_p); + int (*get_wavelength)(struct transvr_obj_s *self, char *buf_p); + int (*set_cdr)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs0)(struct transvr_obj_s *self, int input_val); + int (*set_soft_rs1)(struct transvr_obj_s *self, int input_val); + int (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val); + int (*set_tx_eq)(struct transvr_obj_s *self, int input_val); + int (*set_rx_am)(struct transvr_obj_s *self, int input_val); + int (*set_rx_em)(struct transvr_obj_s *self, int input_val); + + /* ========== Object private functions ========== + */ + int (*init)(struct transvr_obj_s *self); + int (*clean)(struct transvr_obj_s *self); + int (*check)(struct transvr_obj_s *self); + int (*update_all)(struct transvr_obj_s *self, int show_err); + int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name); + int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name); + int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action); + int (*dump_all)(struct transvr_obj_s* self); +}; + + +/* For AVL Mapping */ +struct transvr_avl_s { + char vendor_name[32]; + char vendor_pn[32]; + int (*init)(struct transvr_obj_s *self); +}; + + +/* Worker for long term task of transceiver */ +struct transvr_worker_s { + /* Task Parameter */ + struct transvr_obj_s *transvr_p; + struct transvr_worker_s *next_p; + struct transvr_worker_s *pre_p; + unsigned long trigger_time; + char func_name[64]; + int retry; + int state; + + /* Task private data */ + void *p_data; + + /* Call back function */ + int (*main_task)(struct transvr_worker_s *task); + int (*post_task)(struct transvr_worker_s *task); +}; + + +struct transvr_obj_s * +create_transvr_obj(char *swp_name, + int chan_id, + struct ioexp_obj_s *ioexp_obj_p, + int ioexp_virt_offset, + int transvr_type, + int chipset_type, + int run_mode); + +void lock_transvr_obj(struct transvr_obj_s *self); +void unlock_transvr_obj(struct transvr_obj_s *self); +int isolate_transvr_obj(struct transvr_obj_s *self); + +int resync_channel_tier_2(struct transvr_obj_s *self); + +void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + +#endif /* TRANSCEIVER_H */ + + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/utils/inventec_d7264_util.py b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/utils/inventec_d7264_util.py new file mode 100755 index 000000000000..fea26decf2a5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d7264q28b/utils/inventec_d7264_util.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Inventec, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[D7264]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +"with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +instantiate =[ +#'echo pca9545 0x70> /sys/bus/i2c/devices/i2c-0/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-1/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-2/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-3/new_device', +#'echo pca9548 0x72> /sys/bus/i2c/devices/i2c-4/new_device', +#'echo inv_psoc 0x66> /sys/bus/i2c/devices/i2c-5/new_device', +#'echo inv_cpld 0x55> /sys/bus/i2c/devices/i2c-5/new_device', +'echo inv_eeprom 0x53> /sys/bus/i2c/devices/i2c-0/new_device'] + +drivers =[ +'gpio-ich', +'lpc_ich', +'i2c-i801', +'i2c-mux', +'i2c-mux-pca954x', +'i2c-dev', +'inv_eeprom', +'inv_platform', +'inv_psoc', +'inv_cpld', +'inv_pthread', +'swps'] + + +def system_install(): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("rmmod i2c_ismt ", 1) + status, output = exec_cmd("rmmod i2c-i801 ", 1) + #install drivers + for i in range(0,len(drivers)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #instantiate devices + for i in range(0,len(instantiate)): + time.sleep(1) + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(10,17): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-2/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(18,25): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-3/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(26,33): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-4/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(34,41): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-5/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(42,49): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-6/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(50,57): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-7/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(58,65): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-8/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + for i in range(66,73): + status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-9/i2c-"+str(i)+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + return + + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print " D7264 devices detected...." + return + +def uninstall(): + global FORCE + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0) + ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() + + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/changelog b/platform/broadcom/sonic-platform-modules-inventec/debian/changelog new file mode 100644 index 000000000000..46aebb02ec8e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/changelog @@ -0,0 +1,25 @@ +sonic-inventec-platform-modules (1.1.0) unstable; urgency=low + * Add support for Inventec d7264 + + -- alvin lin Thu, 12 Jul 2018 16:00:00 +0800 + +sonic-inventec-platform-modules (1.1.0) unstable; urgency=low + * Add support for Inventec d6556 + + -- alvin lin Thu, 12 Jul 2018 16:00:00 +0800 + +sonic-inventec-platform-modules (1.1.0) unstable; urgency=low + * Add support for Inventec d6254 + + -- alvin lin Wed, 09 May 2018 16:00:00 +0800 + +sonic-inventec-platform-modules (1.1.0) unstable; urgency=low + * Add support for Inventec d7054 + + -- developer Tue, 18 Jul 2017 16:30:45 +0800 + +sonic-inventec-platform-modules (1.0.0) unstable; urgency=low + + * Add support for Inventec d7032 + + -- developer Wed, 05 Oct 2016 16:30:45 +0800 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/compat b/platform/broadcom/sonic-platform-modules-inventec/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/control b/platform/broadcom/sonic-platform-modules-inventec/debian/control new file mode 100644 index 000000000000..7a435d9b6e60 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/control @@ -0,0 +1,41 @@ +Source: sonic-inventec-platform-modules +Section: main +Priority: extra +Maintainer: Inventec +Build-Depends: debhelper (>= 8.0.0), bzip2, dh-python +Standards-Version: 3.9.3 + +Package: platform-modules-d7032q28b +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led + +Package: platform-modules-d7054q28b +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led + +Package: platform-modules-d6254qs +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led + +Package: platform-modules-d6556 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led + +Package: platform-modules-d6356 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led + +Package: platform-modules-d7264q28b +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led + +Package: platform-modules-d6332 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.init new file mode 100644 index 000000000000..92405e28fd26 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.init @@ -0,0 +1,73 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d6254qs board. +### END INIT INFO + +DIR=/usr/share/sonic/device/x86_64-inventec_d6254qs-r0/plugins +MONITOR_DAEMON=$DIR/transceiver_monitor.py +MONITOR_DAEMON_NAME=transceiver_monitor +LED_DAEMON=$DIR/led_proc.py +LED_DAEMON_NAME=led_proc +ASIC_DAEMON=$DIR/asic_monitor.py +ASIC_DAEMON_NAME=asic_monitor +ASIC_DAEMON_NAM=asic_monitor +PLATFORM_STATUS_DAEMON=$DIR/platform_status.py +PLATFORM_STATUS_DAEMON_NAME=platform_status + +# The process ID of the script when it runs is stored here: +MONITOR_PIDFILE=/var/run/$MONITOR_DAEMON_NAME.pid +LED_PIDFILE=/var/run/$LED_DAEMON_NAME.pid +ASIC_PIDFILE=/var/run/$ASIC_DAEMON_NAME.pid +PLATFORM_STATUS_PIDFILE=/var/run/$PLATFORM_STATUS_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $LED_PIDFILE --make-pidfile --startas $LED_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $MONITOR_PIDFILE --make-pidfile --startas $MONITOR_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $ASIC_PIDFILE --make-pidfile --startas $ASIC_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_STATUS_PIDFILE --make-pidfile --startas $PLATFORM_STATUS_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $MONITOR_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $LED_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $ASIC_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_STATUS_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + /usr/local/bin/inventec_d6254_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + + /usr/local/bin/inventec_d6254_util.py -f clean + do_monitor_${1} + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d6254qs.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.install new file mode 100644 index 000000000000..c4c32c02b299 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6254qs.install @@ -0,0 +1,6 @@ +d6254qs/utils/inventec_d6254_util.py usr/local/bin +common/utils/transceiver_monitor.py usr/share/sonic/device/x86_64-inventec_d6254qs-r0/plugins +common/utils/led_proc.py usr/share/sonic/device/x86_64-inventec_d6254qs-r0/plugins +common/utils/asic_monitor.py usr/share/sonic/device/x86_64-inventec_d6254qs-r0/plugins +common/utils/platform_status.py usr/share/sonic/device/x86_64-inventec_d6254qs-r0/plugins +systemd/platform-modules-d6254qs.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6332.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6332.init new file mode 100644 index 000000000000..9b14421a1324 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6332.init @@ -0,0 +1,74 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d6356j board. +### END INIT INFO + +PLATFORM_DIR=/usr/share/sonic/device/x86_64-inventec_d6332-r0/plugins +PLUGIN_DIR=/usr/lib/python2.7/dist-packages/inventec_plugin + +PLATFORM_DAEMON=$PLATFORM_DIR/platfmgr.py +PLATFORM_DAEMON_NAME=platfmgr +INVSYNCD_DAEMON=$PLUGIN_DIR/invSyncd.py +INVSYNCD_DAEMON_NAME=invSyncd + +# The process ID of the script when it runs is stored here: +PLATFORM_PIDFILE=/var/run/$PLATFORM_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_PIDFILE --make-pidfile --startas $PLATFORM_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $INVSYNCD_PIDFILE --make-pidfile --startas $INVSYNCD_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $INVSYNCD_PIDFILE --retry 10 +} + +# Check Fast-Reboot cause +FAST_REBOOT='no' +case "$(cat /proc/cmdline)" in + *fast-reboot*|*warm*) + FAST_REBOOT='yes' + ;; + *) + FAST_REBOOT='no' + ;; +esac + +case "$1" in +start) + echo -n "Setting up board... " + if [ "$FAST_REBOOT" = "yes" ] ; then + /usr/local/bin/inventec_d6332_util.py -f fast-reboot-install + else + /usr/local/bin/inventec_d6332_util.py -f install + fi + do_monitor_${1} + echo "done." + ;; + +stop) + /usr/local/bin/inventec_d6332_util.py -f clean + do_monitor_${1} + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d6332.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6332.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6332.install new file mode 100644 index 000000000000..d21e85a86e1e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6332.install @@ -0,0 +1,4 @@ +d6332/utils/inventec_d6332_util.py /usr/local/bin +systemd/platform-modules-d6332.service /lib/systemd/system +d6332/utils/sonic_platform-1.0-py2-none-any.whl /usr/share/sonic/device/x86_64-inventec_d6332-r0 +d6332/utils/sonic_platform-1.0-py3-none-any.whl /usr/share/sonic/device/x86_64-inventec_d6332-r0 \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6332.postinst b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6332.postinst new file mode 100644 index 000000000000..dff0ecc8522e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6332.postinst @@ -0,0 +1,25 @@ +#!/bin/sh +# Automatically added by dh_systemd_enable +# This will only remove masks created by d-s-h on package removal. +deb-systemd-helper unmask platform-modules-d6356j.service >/dev/null || true + +# was-enabled defaults to true, so new installations run enable. +if deb-systemd-helper --quiet was-enabled platform-modules-d6332.service; then + # Enables the unit on first installation, creates new + # symlinks on upgrades if the unit file has changed. + deb-systemd-helper enable platform-modules-d6332.service >/dev/null || true +else + # Update the statefile to add new symlinks (if any), which need to be + # cleaned up on purge. Also remove old symlinks. + deb-systemd-helper update-state platform-modules-d6332.service >/dev/null || true +fi +# End automatically added section +depmod -a +# Automatically added by dh_installinit +if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then + if [ -x "/etc/init.d/platform-modules-d6332" ]; then + update-rc.d platform-modules-d6332 defaults >/dev/null + invoke-rc.d platform-modules-d6332 start || exit $? + fi +fi +# End automatically added section diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.init new file mode 100644 index 000000000000..6d0f785fcd14 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.init @@ -0,0 +1,54 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d6356 board. +### END INIT INFO + +PLATFORM_DIR=/usr/share/sonic/device/x86_64-inventec_d6356-r0/plugins + +PLATFORM_DAEMON=$PLATFORM_DIR/platfmgr.py +PLATFORM_DAEMON_NAME=platfmgr + +# The process ID of the script when it runs is stored here: +PLATFORM_PIDFILE=/var/run/$PLATFORM_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_PIDFILE --make-pidfile --startas $PLATFORM_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + /usr/local/bin/inventec_d6356_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + /usr/local/bin/inventec_d6356_util.py -f clean + do_monitor_${1} + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d6356.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.install new file mode 100644 index 000000000000..6f03ede72e05 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.install @@ -0,0 +1,3 @@ +d6356/utils/inventec_d6356_util.py usr/local/bin +d6356/utils/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-inventec_d6356-r0 +systemd/platform-modules-d6356.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.init new file mode 100644 index 000000000000..fc6ba5a261bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.init @@ -0,0 +1,72 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d6556 board. +### END INIT INFO + +DIR=/usr/share/sonic/device/x86_64-inventec_d6556-r0/plugins +MONITOR_DAEMON=$DIR/transceiver_monitor.py +MONITOR_DAEMON_NAME=transceiver_monitor +LED_DAEMON=$DIR/led_proc.py +LED_DAEMON_NAME=led_proc +ASIC_DAEMON=$DIR/asic_monitor.py +ASIC_DAEMON_NAME=asic_monitor +PLATFORM_STATUS_DAEMON=$DIR/platform_status.py +PLATFORM_STATUS_DAEMON_NAME=platform_status + +# The process ID of the script when it runs is stored here: +MONITOR_PIDFILE=/var/run/$MONITOR_DAEMON_NAME.pid +LED_PIDFILE=/var/run/$LED_DAEMON_NAME.pid +ASIC_PIDFILE=/var/run/$ASIC_DAEMON_NAME.pid +PLATFORM_STATUS_PIDFILE=/var/run/$PLATFORM_STATUS_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $LED_PIDFILE --make-pidfile --startas $LED_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $MONITOR_PIDFILE --make-pidfile --startas $MONITOR_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $ASIC_PIDFILE --make-pidfile --startas $ASIC_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_STATUS_PIDFILE --make-pidfile --startas $PLATFORM_STATUS_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $MONITOR_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $LED_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $ASIC_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_STATUS_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + /usr/local/bin/inventec_d6556_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + + /usr/local/bin/inventec_d6556_util.py -f clean + do_monitor_${1} + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d6556.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.install new file mode 100644 index 000000000000..f9e9de9a8b10 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6556.install @@ -0,0 +1,6 @@ +d6556/utils/inventec_d6556_util.py usr/local/bin +common/utils/transceiver_monitor.py usr/share/sonic/device/x86_64-inventec_d6556-r0/plugins +common/utils/led_proc.py usr/share/sonic/device/x86_64-inventec_d6556-r0/plugins +common/utils/asic_monitor.py usr/share/sonic/device/x86_64-inventec_d6556-r0/plugins +common/utils/platform_status.py usr/share/sonic/device/x86_64-inventec_d6556-r0/plugins +systemd/platform-modules-d6556.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.init new file mode 100644 index 000000000000..bcc9610abedb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.init @@ -0,0 +1,72 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d7032q28b board. +### END INIT INFO + +DIR=/usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/plugins +MONITOR_DAEMON=$DIR/transceiver_monitor.py +MONITOR_DAEMON_NAME=transceiver_monitor +LED_DAEMON=$DIR/led_proc.py +LED_DAEMON_NAME=led_proc +ASIC_DAEMON=$DIR/asic_monitor.py +ASIC_DAEMON_NAME=asic_monitor +PLATFORM_STATUS_DAEMON=$DIR/platform_status.py +PLATFORM_STATUS_DAEMON_NAME=platform_status + +# The process ID of the script when it runs is stored here: +MONITOR_PIDFILE=/var/run/$MONITOR_DAEMON_NAME.pid +LED_PIDFILE=/var/run/$LED_DAEMON_NAME.pid +ASIC_PIDFILE=/var/run/$ASIC_DAEMON_NAME.pid +PLATFORM_STATUS_PIDFILE=/var/run/$PLATFORM_STATUS_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $LED_PIDFILE --make-pidfile --startas $LED_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $MONITOR_PIDFILE --make-pidfile --startas $MONITOR_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $ASIC_PIDFILE --make-pidfile --startas $ASIC_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_STATUS_PIDFILE --make-pidfile --startas $PLATFORM_STATUS_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $MONITOR_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $LED_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $ASIC_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_STATUS_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + /usr/local/bin/inventec_d7032_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + + /usr/local/bin/inventec_d7032_util.py -f clean + do_monitor_${1} + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d7032q28b.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.install new file mode 100644 index 000000000000..49ef07def38a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7032q28b.install @@ -0,0 +1,6 @@ +d7032q28b/utils/inventec_d7032_util.py usr/local/bin +common/utils/transceiver_monitor.py usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/plugins +common/utils/led_proc.py usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/plugins +common/utils/asic_monitor.py usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/plugins +common/utils/platform_status.py usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/plugins +systemd/platform-modules-d7032q28b.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.init new file mode 100644 index 000000000000..809ad6255556 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.init @@ -0,0 +1,72 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d7054q28b board. +### END INIT INFO + +DIR=/usr/share/sonic/device/x86_64-inventec_d7054q28b-r0/plugins +MONITOR_DAEMON=$DIR/transceiver_monitor.py +MONITOR_DAEMON_NAME=transceiver_monitor +LED_DAEMON=$DIR/led_proc.py +LED_DAEMON_NAME=led_proc +ASIC_DAEMON=$DIR/asic_monitor.py +ASIC_DAEMON_NAME=asic_monitor +PLATFORM_STATUS_DAEMON=$DIR/platform_status.py +PLATFORM_STATUS_DAEMON_NAME=platform_status + +# The process ID of the script when it runs is stored here: +MONITOR_PIDFILE=/var/run/$MONITOR_DAEMON_NAME.pid +LED_PIDFILE=/var/run/$LED_DAEMON_NAME.pid +ASIC_PIDFILE=/var/run/$ASIC_DAEMON_NAME.pid +PLATFORM_STATUS_PIDFILE=/var/run/$PLATFORM_STATUS_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $LED_PIDFILE --make-pidfile --startas $LED_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $MONITOR_PIDFILE --make-pidfile --startas $MONITOR_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $ASIC_PIDFILE --make-pidfile --startas $ASIC_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_STATUS_PIDFILE --make-pidfile --startas $PLATFORM_STATUS_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $MONITOR_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $LED_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $ASIC_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_STATUS_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + /usr/local/bin/inventec_d7054_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + + /usr/local/bin/inventec_d7054_util.py -f clean + do_monitor_${1} + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d7054q28b.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.install new file mode 100644 index 000000000000..a83009858d6d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7054q28b.install @@ -0,0 +1,7 @@ +d7054q28b/utils/inventec_d7054_util.py usr/local/bin +d7054q28b/utils/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-inventec_d7054q28b-r0 +common/utils/transceiver_monitor.py usr/share/sonic/device/x86_64-inventec_d7054q28b-r0/plugins +common/utils/led_proc.py usr/share/sonic/device/x86_64-inventec_d7054q28b-r0/plugins +common/utils/asic_monitor.py usr/share/sonic/device/x86_64-inventec_d7054q28b-r0/plugins +common/utils/platform_status.py usr/share/sonic/device/x86_64-inventec_d7054q28b-r0/plugins +systemd/platform-modules-d7054q28b.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.init new file mode 100644 index 000000000000..606c7a7cdd09 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.init @@ -0,0 +1,67 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup Inventec d7264q28b board. +### END INIT INFO + +DIR=/usr/share/sonic/device/x86_64-inventec_d7264q28b-r0/plugins +MONITOR_DAEMON=$DIR/transceiver_monitor.py +MONITOR_DAEMON_NAME=transceiver_monitor +ASIC_DAEMON=$DIR/asic_monitor.py +ASIC_DAEMON_NAME=asic_monitor +PLATFORM_STATUS_DAEMON=$DIR/platform_status.py +PLATFORM_STATUS_DAEMON_NAME=platform_status + +# The process ID of the script when it runs is stored here: +MONITOR_PIDFILE=/var/run/$MONITOR_DAEMON_NAME.pid +ASIC_PIDFILE=/var/run/$ASIC_DAEMON_NAME.pid +PLATFORM_STATUS_PIDFILE=/var/run/$PLATFORM_STATUS_DAEMON_NAME.pid + +do_monitor_start() { + /sbin/start-stop-daemon --quiet --oknodo --pidfile $MONITOR_PIDFILE --make-pidfile --startas $MONITOR_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $ASIC_PIDFILE --make-pidfile --startas $ASIC_DAEMON --start --background -- $DAEMON_OPTS + /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_STATUS_PIDFILE --make-pidfile --startas $PLATFORM_STATUS_DAEMON --start --background -- $DAEMON_OPTS +} + +do_monitor_stop() { + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $MONITOR_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $ASIC_PIDFILE --retry 10 + /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_STATUS_PIDFILE --retry 10 +} + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + /usr/local/bin/inventec_d7264_util.py -f install + do_monitor_${1} + echo "done." + ;; + +stop) + + /usr/local/bin/inventec_d7264_util.py -f clean + do_monitor_${1} + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-d7264q28b.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.install new file mode 100644 index 000000000000..66e77e1ddf89 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d7264q28b.install @@ -0,0 +1,5 @@ +d7264q28b/utils/inventec_d7264_util.py usr/local/bin +common/utils/transceiver_monitor.py usr/share/sonic/device/x86_64-inventec_d7264q28b-r0/plugins +common/utils/asic_monitor.py usr/share/sonic/device/x86_64-inventec_d7264q28b-r0/plugins +common/utils/platform_status.py usr/share/sonic/device/x86_64-inventec_d7264q28b-r0/plugins +systemd/platform-modules-d7264q28b.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/rules b/platform/broadcom/sonic-platform-modules-inventec/debian/rules new file mode 100755 index 000000000000..0044efbba491 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/rules @@ -0,0 +1,66 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= d7032q28b d7054q28b d6254qs d6556 d6356 d7264q28b d6332 + +%: + dh $@ --with python2,systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + if [ $$mod = "d7054q28b" ] || [ $$mod = "d6356" ] || [ $$mod = "d6332" ]; then \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2 setup.py build; \ + python2 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/utils; \ + cd $(MOD_SRC_DIR); \ + fi; \ + if [ $$mod = "d6332" ]; then \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python3 setup.py build; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/utils; \ + cd $(MOD_SRC_DIR); \ + fi \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + if [ $$mod = "d7054q28b" ] || [ $$mod = "d6356" ] || [ $$mod = "d6332" ]; then \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2 setup.py install --root=$(MOD_SRC_DIR)/debian/platform-modules-$${mod} --install-layout=deb; \ + cd $(MOD_SRC_DIR); \ + fi; \ + if [ $$mod = "d6332" ]; then \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python3 setup.py install --root=$(MOD_SRC_DIR)/debian/platform-modules-$${mod} --install-layout=deb; \ + cd $(MOD_SRC_DIR); \ + fi \ + done) + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6254qs.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6254qs.service new file mode 100644 index 000000000000..b7aa6dc0e1e7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6254qs.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d6254qs Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d6254qs start +ExecStop=-/etc/init.d/platform-modules-d6254qs stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6332.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6332.service new file mode 100644 index 000000000000..1cbe712da280 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6332.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d6332 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d6332 start +ExecStop=-/etc/init.d/platform-modules-d6332 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6356.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6356.service new file mode 100644 index 000000000000..85fa47a72611 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6356.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d6356 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d6356 start +ExecStop=-/etc/init.d/platform-modules-d6356 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6556.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6556.service new file mode 100644 index 000000000000..6fbd6711ede8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6556.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d7032q28b Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d6556 start +ExecStop=-/etc/init.d/platform-modules-d6556 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7032q28b.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7032q28b.service new file mode 100644 index 000000000000..b96374b343f4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7032q28b.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d7032q28b Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d7032q28b start +ExecStop=-/etc/init.d/platform-modules-d7032q28b stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7054q28b.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7054q28b.service new file mode 100644 index 000000000000..0c2d463598ad --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7054q28b.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d7054q28b Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d7054q28b start +ExecStop=-/etc/init.d/platform-modules-d7054q28b stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7264q28b.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7264q28b.service new file mode 100644 index 000000000000..a4cda3934357 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d7264q28b.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d7032q28b Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d7264q28b start +ExecStop=-/etc/init.d/platform-modules-d7264q28b stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-juniper/.gitignore b/platform/broadcom/sonic-platform-modules-juniper/.gitignore new file mode 100644 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-juniper/LICENSE b/platform/broadcom/sonic-platform-modules-juniper/LICENSE new file mode 100644 index 000000000000..c819eacfeb94 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2019 Juniper Networks + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-juniper/README.md b/platform/broadcom/sonic-platform-modules-juniper/README.md new file mode 100644 index 000000000000..3a661cef8eeb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/README.md @@ -0,0 +1,290 @@ +Juniper Networks Platform Support for SONiC +=========================================== + +This readme provides information on how to install and upgrade ONIE and SONiC images on the Juniper Networks switches. + +Note: Switches ship with ONIE and SONiC images preinstalled. + +## Supported platforms + +The following Juniper Networks platforms are supported for the SONiC operating system: + + - QFX5210-64C-S + - QFX5200-32C-S + + +## Building and Installing ONIE + +ONIE is the bootloader used and it's a prerequisite to install ONIE on the switches before installing SONiC. + +1. Cross compile ONIE + +To compile ONIE, you need to change the directories to "build-config" and then based on the platform issue the following commands + +a) For QFX5210-64C-S platform, invoke "make MACHINEROOT=../machine/juniper MACHINE=juniper_qfx5210 all". + +For example: + +``` + $ cd build-config + $ make -j4 MACHINEROOT=../machine/juniper MACHINE=juniper_qfx5210 all +``` + +b) For QFX5200-32C-S platform, invoke "make MACHINEROOT=../machine/juniper MACHINE=juniper_qfx5200 all". + +ONIE binaries are located at the directory /build/images. The following command shows how to navigate the directory to view the ONIE binaries: + +``` +stack@controller:~/ONIE_J/onie/build/images$ ls -rlt + +total 40740 + +-rw-rw-r-- 1 stack stack 3710240 Aug 3 12:32 juniper_x86-r0.vmlinuz -- ONIE kernel image +-rw-rw-r-- 1 stack stack 6038416 Aug 3 12:32 juniper_x86-r0.initrd -- ONIE initramfs (filesystem) +-rw-rw-r-- 1 stack stack 9811831 Aug 3 12:32 onie-updater-x86_64-juniper_x86-r0 -- ONIE self-update image for installing ONIE. +-rw-rw-r-- 1 stack stack 22151168 Aug 3 12:33 onie-recovery-x86_64-juniper_x86-r0.iso -- Recovery ISO image to create a bootable USB memory device for installing/recovery ONIE. +-rw-rw-r-- 1 stack stack 31465984 Aug 3 12:33 onie-recovery-x86_64-juniper_qfx5210-r0.efi64.pxe -- Recovery PXE image used for installing ONIE using PXE Network install. +``` + + +Note: Use the following command to build a demo target: + +For example: + +``` + $ make -j4 MACHINEROOT=../machine/juniper MACHINE=juniper_qfx5210 all demo +``` + +In addition to the above list of binary files, the following two binary files are also created: + +``` +-rw-rw---- 1 build build 12576008 Aug 19 16:30 demo-installer-x86_64-juniper_qfx5210-r0.bin +-rw-rw---- 1 build build 12576008 Aug 19 16:30 demo-diag-installer-x86_64-juniper_qfx5210-r0.bin +``` + +You can install these binary files by using the 'onie-nos-install' command to test the install / boot workflow. + +Use the following command for make clean: + +For example: + +``` + $ make machine-clean MACHINEROOT=../machine/juniper MACHINE=juniper_qfx5210 +``` + + +## Installing ONIE + +To install ONIE on a new switch, you can use one of the following ONIE recovery images: + +1) ..iso -- Hybrid ISO image. +2) ..efi64.pxe -- PXE image for UEFI64 machines. + +Note: Second method is not applicable for QFX5200-32C-S + + +## Creating an ISO Recovery Image + +You can use the recovery ISO (.iso) image to create a bootable USB memory device. + +To create a bootable USB memory device, use the "dd" command on a Linux workstation as follows: + +``` + $ dd if=.iso of=/dev/sdX bs=10M +``` + +For example: + +``` + $ dd if=onie-recovery-x86_64-juniper_qfx5210-r0.iso of=/dev/sdb bs=10M +``` + +You can find the correct "/dev/sdX" by validating the "dmesg" output after inserting an USB device into the Linux workstation. + + +1) Booting from a USB Memory Device + +To boot from an external USB memory device connected to the switch, you need to: + +a. Insert the USB memory device to the USB port of the switch. + +b. Power on the switch and enter the BIOS configuration by pressing the Esc key, as displayed in the console screen. + +c. Set the hard drive boot order as follows: + + When you see the "Boot Option #1" displayed on the console screen, select the USB memory device: + + Boot-->Boot Option Priorities-->Boot Option #1 + + If the USB memory device name is not listed in "Boot Option #1", check the priorities in the hard drive boot order: + + Boot-->Hard Drive BBS Priorities-->Boot Option #1 + + + For example, consider "JetFlashTranscend 8GB 8.07" as the USB memory device, the boot order will display as follows: + +``` + Boot Option Priorities + + Boot Option #1 [JetFlashTranscend 8...] + + Boot Option #2 [ATP ATP IG eUSB 1100] + + Boot Option #3 [IBA GE Slot 00A0 v1543] + + Boot Option #4 [UEFI: Built-in EFI ...] +``` + +d. Go to "Save & Exit" in the BIOS screen and from the Boot Override option select the USB memory device (For example, JetFlashTranscend 8GB 8.07). + +e. After a few seconds, the switch would restart and boot from the USB memory device and then you will see the following on the console screen: + +``` + GNU GRUB version 2.02~beta2+e4a1fe391 + + +----------------------------------------------------------------------------+ + |*ONIE: Rescue | + | ONIE: Embed ONIE | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------------------------------------------------------------------+ + + Use the ^ and v keys to select which entry is highlighted. + Press enter to boot the selected OS, `e' to edit the commands before booting or `c' for a command-line. +``` + +f. Select "ONIE: Embed ONIE" to create a fresh partition to install ONIE automatically. + + Warning: All the data on the hard disk drive will be erased. + +g. Select "ONIE: Rescue" to enter the ONIE recovery command-line shell (Optional). + + + +2) Recovering ONIE using PXE-UEFI64 Recovery Image + +Note: This section is only applicable for QFX5210-64C-S platform. + +You can use the onie-recovery-x86_64-juniper_qfx5210-r0.efi64.pxe image to recover the ONIE image through UEFI PXE. + + The onie-recovery-x86_64-juniper_qfx5210-r0.efi64.pxe is made for the QFX5210-64C-S switch that has a PXE client which is based on UEFI64. + The onie-recovery-x86_64-juniper_qfx5210-r0.efi64.pxe is a combination of grub-efi-64 and the .iso recovery image, that looks like an UEFI application. The UEFI PXE client on the QFX5210-64C-S can then boot it. + + For more information on UEFI PXE Netboot, see https://wiki.ubuntu.com/UEFI/PXE-netboot-install. + + Note: To install the PXE-UEFI64 recovery image over the network, you need to configure your DHCP server so that DHCP clients receives the onie-recovery-x86_64-juniper_qfx5210-r0.efi64.pxe image as the bootfile. + + To enable IPv4 PXE boot on the QFX5210-64C-S switch: + + 1) Enter the BIOS configuration. + 2) Click "Save & Exit" menu on the "Boot Override" option. + 3) Select "UEFI: IP4 Broadcom NetXtreme Gigabit Ethernet" + +## Related Documentation for ONIE: + +The following links provide more information about ONIE: + + 1. ONIE documentation: https://opencomputeproject.github.io/onie/. + 2. How to build and install ONIE on QFX5210-64C-S switch, see https://github.com/opencomputeproject/onie/blob/master/machine/juniper/juniper_qfx5210/INSTALL. + +## SONiC Build Process: + +The instruction on how to build an ONIE compatible network operating system (NOS) installer image for Juniper Networks switches, and how to build docker images running inside the NOS is available at https://github.com/Azure/sonic-buildimage#usage. + + +## Install SONiC on the Juniper Networks switch:es + +You need to copy the SONiC image 'sonic-broadcom.bin' to the switch. You can copy the sonic-broadcom.bin to an USB memory device and insert it to the USB port of the switch. You can also use the 'scp' command to copy the sonic-broadcom.bin image to the switch over the network. + +Note: Unmount the USB memory device after copying the sonic-broadcom.bin. For example, umount /dev/sdX, where X is the name of the drive of the USB memory device. + +Run the following command to install SONIC: + +``` +For example, +ONIE:/var/tmp # onie-nos-install /var/tmp/sonic-broadcom.bin +``` + +## Booting SONiC + +The switch restarts automatically after the SONiC image has been successfully installed. + +1) Select SONiC from the GRUB boot manager. + +``` + GNU GRUB version 2.02 + + +----------------------------------------------------------------------------+ + |*SONiC-OS-master.0-dirty-20190913.060138 | + | ONIE | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------------------------------------------------------------------+ + + Use the ^ and v keys to select which entry is highlighted. + Press enter to boot the selected OS, `e' to edit the commands + before booting or `c' for a command-line. +``` + +2. At the SONiC login prompt, enter the username as admin and password as YourPaSsWoRd. + +You can now start configuring the Juniper Networks switch running SONiC as its operating system. + + +## Upgrading SONiC image + +To upgrade the SONiC operating system to a latest version, you need to: + + 1. Copy the latest image of the SONiC image to the switch. + 2. Run the following command from the directory where the latest SONiC image has been copied. + +``` +$ sudo ./sonic-braodcom.bin +``` + +or + +``` +$ sudo sonic-installer ./sonic-broadcom.bin -y +``` + + +## Uninstalling SONiC image + +To unintall SONiC operating system from the switch, you need to: + + 1. Reboot the switch. + 2. Go to the ONIE GRUB menu and then select ONIE: Uninstall OS option to uninstall SONiC. + +For more details on drivers and platform scripts see the following links: + +1) QFX5210-64C-S: https://github.com/Azure/sonic-buildimage/blob/master/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/README + +2) QFX5200-32C-S: https://github.com/Azure/sonic-buildimage/blob/master/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/README + +## Related Documentation for SONiC: + +The following links provide more information about SONiC: + 1. SONiC documentation: https://github.com/azure/sonic/wiki. + +## Viewing the Device Revision of the FRU Model from IDEEPROM + +You can view the device revisions of the FRU model from IDEEPROM by using the show platform syseeprom CLI command. + +Note: The Device version shown is the HEX ASCII equivalent of the FRU model. For example, if the device version shows 41, then the HEX ASCII equivalent is character A. diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/gpio-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/common/modules/gpio-tmc.c new file mode 100644 index 000000000000..7b02e8a5bc74 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/common/modules/gpio-tmc.c @@ -0,0 +1,661 @@ +/* + * Juniper Networks TMC GPIO driver + * + * Copyright (C) 2020 Juniper Networks + * Author: Ashish Bhensdadia + * + * This driver implement the GPIO set/get functionality + * + * 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; 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jnx-tmc.h" + +#define TMC_GPIO_MAX_BITS_PER_REG 16 +#define TMC_GPIO_SFP_MAX_BITS_PER_REG 2 +#define TMC_GPIO_PTPCFG_MAX_BITS_PER_REG 8 + +#define TMC_GPIO_FIND_GROUP(gpio) \ + ((gpio) / TMC_GPIO_MAX_BITS_PER_REG) +#define TMC_GPIO_FIND_GPIO(gpio) \ + ((gpio) % TMC_GPIO_MAX_BITS_PER_REG) + +#define TMC_GPIO_SFP_FIND_GROUP(gpio) \ + ((gpio) / TMC_GPIO_SFP_MAX_BITS_PER_REG) +#define TMC_GPIO_SFP_FIND_GPIO(gpio) \ + ((gpio) % TMC_GPIO_SFP_MAX_BITS_PER_REG) + +#define TMC_GPIO_PTPCFG_FIND_GPIO(gpio) \ + ((gpio) % TMC_GPIO_PTPCFG_MAX_BITS_PER_REG) + +#define TMC_GPIO_MAX_NGPIO_PER_GROUP 320 + +#define TMC_PFE_QSFP_RESET_OFFSET 0x4 +#define TMC_PFE_QSFP_PRESENT_OFFSET 0x8 +#define TMC_PFE_QSFP_PHY_RESET_OFFSET 0x10 +#define TMC_PFE_QSFP_LPMOD_OFFSET 0x78 +#define TMC_PFE_QSFP_LED_CTRL_OFFSET 0x20 + +#define TMC_PFE_LANES_GREEN_LED_VALUE 0x3 +#define TMC_PFE_LANE0_GREEN_LED_BIT_POSITION 0 +#define TMC_PFE_LANE1_GREEN_LED_BIT_POSITION 2 +#define TMC_PFE_LANE2_GREEN_LED_BIT_POSITION 4 +#define TMC_PFE_LANE3_GREEN_LED_BIT_POSITION 6 + +#define TMC_PFE_LANES_BEACON_LED_VALUE 0x2 +#define TMC_PFE_LANE0_BEACON_LED_BIT_POSITION 0 +#define TMC_PFE_LANE1_BEACON_LED_BIT_POSITION 2 +#define TMC_PFE_LANE2_BEACON_LED_BIT_POSITION 4 +#define TMC_PFE_LANE3_BEACON_LED_BIT_POSITION 6 + +#define TMC_PFE_LANES_FAULT_LED_VALUE 0x1 +#define TMC_PFE_LANE0_FAULT_LED_BIT_POSITION 0 +#define TMC_PFE_LANE1_FAULT_LED_BIT_POSITION 2 +#define TMC_PFE_LANE2_FAULT_LED_BIT_POSITION 4 +#define TMC_PFE_LANE3_FAULT_LED_BIT_POSITION 6 + +#define TMC_PFE_SFPSB0_TX_DISABLE_OFFSET 0x0 +#define TMC_PFE_SFPSB0_LED_CTRL_OFFSET 0xC +#define TMC_PFE_SFPSB0_LED_ACTIVITY_OFFSET 0x14 +#define TMC_PFE_SFPSB0_PRESENT_OFFSET 0x18 +#define TMC_PFE_SFPSB0_LOSS_OFFSET 0x1C +#define TMC_PFE_SFPSB0_TX_FAULT_OFFSET 0x20 + +#define TMC_PFE_SFPSB1_TX_DISABLE_OFFSET 0x0 +#define TMC_PFE_SFPSB1_LED_CTRL_OFFSET 0x8 +#define TMC_PFE_SFPSB1_LED_ACTIVITY_OFFSET 0x10 +#define TMC_PFE_SFPSB1_PRESENT_OFFSET 0x14 +#define TMC_PFE_SFPSB1_LOSS_OFFSET 0x18 +#define TMC_PFE_SFPSB1_TX_FAULT_OFFSET 0x1C + +/* + * Index 4 to 15 is used for QSFP starting with + * QSFP_LED_LANE0_GREEN. To keep multibit set/get common + * starting SFP_LED_LANE0_GREEN with 16 which will avoid + * conflict with QSFP enums. + */ +#define SFP_LED_OP_START_INDEX 16 + +/* + * Used for off-setting SFP led op index + */ +#define SFP_LED_OP_OFFSET 0xB + +/* + * SFP slave blocks + */ +#define SFP_SLAVE0_BLOCK 0x1 +#define SFP_SLAVE1_BLOCK 0x2 + +/* + * each group represent the 16 gpios. + * QSFP_RST - QSFP_LPMODE + * each bit represent the one gpio + * exemple: bits[0:15] - bit0 - gpio0 + * QSFP_LED_LANE0_GREEN - QSFP_LED_LANE3_FAULT + * here, number represent the one gpio + * exemple: bits[0:1] + * 00 - gpio off, 01 - gpio on [ gpio0] + * 00 - gpio off, 10 - gpio on [ gpio1] + * 00 - gpio off, 11 - gpio on [ gpio2] + * + */ +enum { + QSFP_RST, + QSFP_PRESENT, + QSFP_PHY_RST, + QSFP_LPMOD, + QSFP_LED_LANE0_GREEN, + QSFP_LED_LANE1_GREEN, + QSFP_LED_LANE2_GREEN, + QSFP_LED_LANE3_GREEN, + QSFP_LED_LANE0_BEACON, + QSFP_LED_LANE1_BEACON, + QSFP_LED_LANE2_BEACON, + QSFP_LED_LANE3_BEACON, + QSFP_LED_LANE0_FAULT, + QSFP_LED_LANE1_FAULT, + QSFP_LED_LANE2_FAULT, + QSFP_LED_LANE3_FAULT, + TMC_PFE_GPIO_GROUP_MAX +}; + +enum sfp_op { + SFP_TX_DISABLE, + SFP_LED_ACTIVITY, + SFP_PRESENT, + SFP_SFP_LOS, + SFP_TX_FAULT, + SFP_LED_LANE0_GREEN = SFP_LED_OP_START_INDEX, + SFP_LED_LANE1_GREEN, + SFP_LED_LANE2_GREEN, + SFP_LED_LANE3_GREEN, + SFP_LED_LANE0_BEACON, + SFP_LED_LANE1_BEACON, + SFP_LED_LANE2_BEACON, + SFP_LED_LANE3_BEACON, + SFP_LED_LANE0_FAULT, + SFP_LED_LANE1_FAULT, + SFP_LED_LANE2_FAULT, + SFP_LED_LANE3_FAULT, + TMC_PFE_SFP_GPIO_GROUP_MAX +}; + +static const u32 group_offset[TMC_PFE_GPIO_GROUP_MAX] = { + TMC_PFE_QSFP_RESET_OFFSET, + TMC_PFE_QSFP_PRESENT_OFFSET, + TMC_PFE_QSFP_PHY_RESET_OFFSET, + TMC_PFE_QSFP_LPMOD_OFFSET, + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 GREEN */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 GREEN */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 GREEN */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 GREEN */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 BEACON */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 BEACON */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 BEACON */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 BEACON */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 FAULT */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 FAULT */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 FAULT */ + TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 FAULT */ +}; + +static const u32 sfp_slaveb0_group_offset[TMC_PFE_SFP_GPIO_GROUP_MAX] = { + TMC_PFE_SFPSB0_TX_DISABLE_OFFSET, + TMC_PFE_SFPSB0_LED_ACTIVITY_OFFSET, + TMC_PFE_SFPSB0_PRESENT_OFFSET, + TMC_PFE_SFPSB0_LOSS_OFFSET, + TMC_PFE_SFPSB0_TX_FAULT_OFFSET, + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 GREEN */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 GREEN */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 GREEN */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 GREEN */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 BEACON */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 BEACON */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 BEACON */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 BEACON */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 FAULT */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 FAULT */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 FAULT */ + TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 FAULT */ +}; + +static const u32 sfp_slaveb1_group_offset[TMC_PFE_SFP_GPIO_GROUP_MAX] = { + TMC_PFE_SFPSB1_TX_DISABLE_OFFSET, + TMC_PFE_SFPSB1_LED_ACTIVITY_OFFSET, + TMC_PFE_SFPSB1_PRESENT_OFFSET, + TMC_PFE_SFPSB1_LOSS_OFFSET, + TMC_PFE_SFPSB1_TX_FAULT_OFFSET, + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 GREEN */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 GREEN */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 GREEN */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 GREEN */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 BEACON */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 BEACON */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 BEACON */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 BEACON */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 FAULT */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 FAULT */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 FAULT */ + TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 FAULT */ +}; + +struct tmc_gpio_info { + int (*get)(struct gpio_chip *, unsigned int); + void (*set)(struct gpio_chip *, unsigned int, int); + int (*dirin)(struct gpio_chip *, unsigned int); + int (*dirout)(struct gpio_chip *, unsigned int, int); +}; + +struct tmc_gpio_chip { + const struct tmc_gpio_info *info; + void __iomem *base; + struct device *dev; + struct gpio_chip gpio; + int ngpio; + spinlock_t gpio_lock; /* gpio lock */ + int sfp_slave_block; +}; + +/* slave gpio max */ +static int gpio_max = 320; +module_param(gpio_max, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(gpio_max, "Maximum number of gpio for SLAVE TMC GPIO"); + +/* + * generic bit operation functions + */ +static u32 tmc_gpio_reset_bits(u32 state, u32 val, u32 shift) +{ + state &= ~(val << shift); + return state; +}; + +static u32 tmc_gpio_set_bits(u32 state, u32 val, u32 shift) +{ + state |= (val << shift); + return state; +}; + +static u32 tmc_gpio_find_bits_val(u32 state, u32 shift, u32 mask) +{ + return ((state >> shift)) & mask; +}; + +#define to_tmc_chip(chip) \ + container_of((chip), struct tmc_gpio_chip, gpio) + +/* + * tmc_gpio_multiple_bitsop - Generic TMC GPIO multiple bits operation + */ +static void tmc_gpio_multiple_bitsop(struct tmc_gpio_chip *chip, + unsigned int gpiono, u32 group, u32 offset, bool set) +{ + u32 gpio_state, led_val, bit_shift; + unsigned long flags; + void __iomem *iobase; + + iobase = chip->base + offset; + + dev_dbg(chip->dev, "TMC GPIO multiple bitop group=%u, " + "gpiono=%u, offet:=%u, set=%u\n", group, gpiono, offset, set); + + spin_lock_irqsave(&chip->gpio_lock, flags); + + switch (group) { + case QSFP_LED_LANE0_GREEN: + case SFP_LED_LANE0_GREEN: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_GREEN_LED_VALUE; + bit_shift = TMC_PFE_LANE0_GREEN_LED_BIT_POSITION; + break; + case QSFP_LED_LANE1_GREEN: + case SFP_LED_LANE1_GREEN: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_GREEN_LED_VALUE; + bit_shift = TMC_PFE_LANE1_GREEN_LED_BIT_POSITION; + break; + case QSFP_LED_LANE2_GREEN: + case SFP_LED_LANE2_GREEN: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_GREEN_LED_VALUE; + bit_shift = TMC_PFE_LANE2_GREEN_LED_BIT_POSITION; + break; + case QSFP_LED_LANE3_GREEN: + case SFP_LED_LANE3_GREEN: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_GREEN_LED_VALUE; + bit_shift = TMC_PFE_LANE3_GREEN_LED_BIT_POSITION; + break; + case QSFP_LED_LANE0_BEACON: + case SFP_LED_LANE0_BEACON: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_BEACON_LED_VALUE; + bit_shift = TMC_PFE_LANE0_BEACON_LED_BIT_POSITION; + break; + case QSFP_LED_LANE1_BEACON: + case SFP_LED_LANE1_BEACON: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_BEACON_LED_VALUE; + bit_shift = TMC_PFE_LANE1_BEACON_LED_BIT_POSITION; + break; + case QSFP_LED_LANE2_BEACON: + case SFP_LED_LANE2_BEACON: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_BEACON_LED_VALUE; + bit_shift = TMC_PFE_LANE2_BEACON_LED_BIT_POSITION; + break; + case QSFP_LED_LANE3_BEACON: + case SFP_LED_LANE3_BEACON: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_BEACON_LED_VALUE; + bit_shift = TMC_PFE_LANE3_BEACON_LED_BIT_POSITION; + break; + case QSFP_LED_LANE0_FAULT: + case SFP_LED_LANE0_FAULT: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_FAULT_LED_VALUE; + bit_shift = TMC_PFE_LANE0_FAULT_LED_BIT_POSITION; + break; + case QSFP_LED_LANE1_FAULT: + case SFP_LED_LANE1_FAULT: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_FAULT_LED_VALUE; + bit_shift = TMC_PFE_LANE1_FAULT_LED_BIT_POSITION; + break; + case QSFP_LED_LANE2_FAULT: + case SFP_LED_LANE2_FAULT: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_FAULT_LED_VALUE; + bit_shift = TMC_PFE_LANE2_FAULT_LED_BIT_POSITION; + break; + case QSFP_LED_LANE3_FAULT: + case SFP_LED_LANE3_FAULT: + gpio_state = ioread32(iobase+(0x004*gpiono)); + led_val = TMC_PFE_LANES_FAULT_LED_VALUE; + bit_shift = TMC_PFE_LANE3_FAULT_LED_BIT_POSITION; + break; + + default: + spin_unlock_irqrestore(&chip->gpio_lock, flags); + return; + } + + if (set) { + gpio_state = tmc_gpio_reset_bits(gpio_state, 0x3, bit_shift); + gpio_state = tmc_gpio_set_bits(gpio_state, led_val, bit_shift); + } else { + gpio_state = tmc_gpio_reset_bits(gpio_state, 0x3, bit_shift); + } + + iowrite32(gpio_state, (iobase+(0x004*gpiono))); + + spin_unlock_irqrestore(&chip->gpio_lock, flags); + + return; +}; + +/* + * tmc_gpio_one_bitop - Generic TMC GPIO single bit operation + */ +static void tmc_gpio_one_bitop(struct tmc_gpio_chip *chip, + unsigned int bit, u32 offset, bool set) +{ + u32 gpio_state; + unsigned long flags; + void __iomem *iobase; + + iobase = chip->base + offset; + + dev_dbg(chip->dev, "TMC GPIO one bitop bit=%u, offset=%x, " + "set=%u\n", bit, offset, set); + + spin_lock_irqsave(&chip->gpio_lock, flags); + + gpio_state = ioread32(iobase); + if (set) + gpio_state |= BIT(bit); + else + gpio_state &= ~BIT(bit); + + iowrite32(gpio_state, iobase); + + spin_unlock_irqrestore(&chip->gpio_lock, flags); + + return; +} + +/* + * tmc_gpio_get_multiple_bitsop - Generic TMC get GPIO multiple bits operation + */ +static int tmc_gpio_get_multiple_bitsop(struct tmc_gpio_chip *chip, + unsigned int gpiono, u32 group, u32 offset) +{ + u32 gpio_state; + void __iomem *iobase; + + iobase = chip->base + offset; + + dev_dbg(chip->dev, "TMC GPIO get multiple bitsop group=%u, " + "gpiono=%u, offset=%u\n", group, gpiono, offset); + + switch (group) { + case QSFP_LED_LANE0_GREEN: + case SFP_LED_LANE0_GREEN: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_GREEN_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE0_GREEN_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE1_GREEN: + case SFP_LED_LANE1_GREEN: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_GREEN_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE1_GREEN_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE2_GREEN: + case SFP_LED_LANE2_GREEN: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_GREEN_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE2_GREEN_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE3_GREEN: + case SFP_LED_LANE3_GREEN: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_GREEN_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE3_GREEN_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE0_BEACON: + case SFP_LED_LANE0_BEACON: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_BEACON_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE0_BEACON_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE1_BEACON: + case SFP_LED_LANE1_BEACON: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_BEACON_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE1_BEACON_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE2_BEACON: + case SFP_LED_LANE2_BEACON: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_BEACON_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE2_BEACON_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE3_BEACON: + case SFP_LED_LANE3_BEACON: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_BEACON_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE3_BEACON_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE0_FAULT: + case SFP_LED_LANE0_FAULT: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_FAULT_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE0_FAULT_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE1_FAULT: + case SFP_LED_LANE1_FAULT: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_FAULT_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE1_FAULT_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE2_FAULT: + case SFP_LED_LANE2_FAULT: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_FAULT_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE2_FAULT_LED_BIT_POSITION, 0x3)); + case QSFP_LED_LANE3_FAULT: + case SFP_LED_LANE3_FAULT: + gpio_state = ioread32(iobase+(0x004*gpiono)); + return (TMC_PFE_LANES_FAULT_LED_VALUE == + tmc_gpio_find_bits_val(gpio_state, + TMC_PFE_LANE3_FAULT_LED_BIT_POSITION, 0x3)); + default: + return 0; + } +}; + +/* + * tmc_gpio_get - Read the specified signal of the GPIO device. + */ +static int tmc_gpio_get(struct gpio_chip *gc, unsigned int gpio) +{ + struct tmc_gpio_chip *chip = to_tmc_chip(gc); + unsigned int group = TMC_GPIO_FIND_GROUP(gpio); + unsigned int bit = TMC_GPIO_FIND_GPIO(gpio); + + if (group >= TMC_PFE_GPIO_GROUP_MAX) + return 0; + + switch (group) { + case QSFP_RST: + case QSFP_PRESENT: + case QSFP_PHY_RST: + case QSFP_LPMOD: + dev_dbg(chip->dev, "TMC GPIO get one bitop group=%u, gpio=%u, " + "bit=%u\n", group, gpio, bit); + return !!(ioread32(chip->base + group_offset[group]) + & BIT(bit)); + default: + return tmc_gpio_get_multiple_bitsop(chip, bit, group, group_offset[group]); + } +} + +/* + * tmc_gpio_set - Write the specified signal of the GPIO device. + */ +static void tmc_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ + struct tmc_gpio_chip *chip = to_tmc_chip(gc); + unsigned int group = TMC_GPIO_FIND_GROUP(gpio); + unsigned int bit = TMC_GPIO_FIND_GPIO(gpio); + + if (group >= TMC_PFE_GPIO_GROUP_MAX) + return; + + switch (group) { + case QSFP_RST: + case QSFP_PRESENT: + case QSFP_PHY_RST: + case QSFP_LPMOD: + dev_dbg(chip->dev, "TMC GPIO one bitop group=%d\n", group); + tmc_gpio_one_bitop(chip, bit, group_offset[group], val); + break; + default: + tmc_gpio_multiple_bitsop(chip, bit, group, group_offset[group], val); + break; + } +} + +static struct tmc_gpio_info tmc_gpios[] = { + { + .get = tmc_gpio_get, + .set = tmc_gpio_set, + }, +}; + +static void tmc_gpio_setup(struct tmc_gpio_chip *sgc, int id) +{ + struct gpio_chip *chip = &sgc->gpio; + const struct tmc_gpio_info *info = sgc->info; + + chip->get = info->get; + chip->set = info->set; + chip->direction_input = info->dirin; + chip->direction_output = info->dirout; + chip->dbg_show = NULL; + chip->can_sleep = 0; + + if (id == 0) { + chip->base = 0; + } else if (id == 1) { + chip->base = (gpio_max * id); + } else { + chip->base = -1; + } + + chip->ngpio = sgc->ngpio; + chip->label = dev_name(sgc->dev); + chip->parent = sgc->dev; + chip->owner = THIS_MODULE; +} + +static int tmc_gpio_of_init(struct device *dev, + struct tmc_gpio_chip *chip) +{ + chip->info = &tmc_gpios[0]; + chip->ngpio = gpio_max; + + return 0; +} + +static int tmc_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tmc_gpio_chip *chip; + struct resource *res; + int ret; + + const struct mfd_cell *cell = mfd_get_cell(pdev); + + dev_dbg(dev, "TMC GPIO probe\n"); + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + dev_info(dev, "TMC GPIO resource 0x%llx, %llu\n", + res->start, resource_size(res)); + + chip->base = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (!chip->base) + return -ENOMEM; + + ret = tmc_gpio_of_init(dev, chip); + if (ret) + return ret; + + chip->dev = dev; + spin_lock_init(&chip->gpio_lock); + + tmc_gpio_setup(chip, cell->id); + + ret = gpiochip_add(&chip->gpio); + if (ret) { + dev_err(dev, + "Failed to register TMC gpiochip : %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, chip); + dev_info(dev, "TMC GPIO registered at 0x%lx, gpiobase: %d\n", + (long unsigned)chip->base, chip->gpio.base); + + return 0; +} + +static int tmc_gpio_remove(struct platform_device *pdev) +{ + struct tmc_gpio_chip *chip = platform_get_drvdata(pdev); + + gpiochip_remove(&chip->gpio); + + return 0; +} + +static struct platform_driver tmc_gpio_driver = { + .driver = { + .name = "gpioslave-tmc", + .owner = THIS_MODULE, + }, + .probe = tmc_gpio_probe, + .remove = tmc_gpio_remove, +}; + +module_platform_driver(tmc_gpio_driver); + +MODULE_DESCRIPTION("Juniper Networks TMC FPGA GPIO driver"); +MODULE_AUTHOR("Ashish Bhensdadia "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/i2c-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/common/modules/i2c-tmc.c new file mode 100644 index 000000000000..afd0311dc130 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/common/modules/i2c-tmc.c @@ -0,0 +1,1107 @@ +/* + * Juniper Networks TMC I2C Accelerator driver + * + * Copyright (C) 2020 Juniper Networks + * Author: Ashish Bhensdadia + * + * This driver implement the I2C functionality + * + * 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; 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jnx-tmc.h" + + +#define TMC_I2C_MASTER_I2C_SCAN_RESET_BIT BIT(31) + +#define TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET 0x0 +#define TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET 0x10 + +#define TMC_I2C_MSTR_AUTOMATION_I2C(adap, offset) \ + ((adap)->membase + offset) + +#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0 0x0 +#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8 0x8 +#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4 0x4 +#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C 0xC +#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10 0x10 +#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14 0x14 +#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18 0x18 +#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C 0x1C +#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_20 0x20 +#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_24 0x24 + +#define TMC_I2C_MSTR_I2C_DPMEM(adap, offset) \ + ((adap)->dpmbase + offset) + +#define TMC_I2C_TRANS_LEN 2 +#define tmc_iowrite(val, addr) iowrite32((val), (addr)) + +#define TMC_I2C_CTRL_GROUP(g) (((g) & 0xFF) << 8) +#define TMC_I2C_CTRL_WRCNT(w) (((w) & 0x3F) << 16) +#define TMC_I2C_CTRL_RDCNT(r) (((r) & 0x3F) << 16) +#define TMC_I2C_CTRL_DEVADDR(d) (((d) & 0xFF) << 8) +#define TMC_I2C_CTRL_OFFSET(o) ((o) & 0xFF) + + +#define TMC_I2C_MEM_CTRL_VLD BIT(31) + +#define TMC_I2C_CTRL_ERR(s) ((s) & 0x0F000000) +#define TMC_I2C_CTRL_DONE_BIT(s) ((s) & BIT(31)) +#define TMC_I2C_CTRL_STATUS_OK(s) (TMC_I2C_CTRL_DONE_BIT(s) & \ + TMC_I2C_CTRL_ERR(s)) +#define TMC_I2C_CTRL_DONE(s) (TMC_I2C_CTRL_DONE_BIT(s) == BIT(31)) + +#define TMC_I2C_STAT_INC(adap, s) (((adap)->stat.s)++) +#define TMC_I2C_STAT_INCN(adap, s, n) (((adap)->stat.s) += (n)) +#define TMC_I2C_GET_MASTER(tadap) ((tadap)->tctrl) + +#define TMC_I2C_READ 0x1 +#define TMC_I2C_WRITE 0x2 + +#define TMC_I2C_MASTER_LOCK(s, flags) \ +do { \ + spin_lock_irqsave(&(s)->lock, flags); \ +} while (0) + +#define TMC_I2C_MASTER_UNLOCK(s, flags) \ +do { \ + spin_unlock_irqrestore(&(s)->lock, flags); \ +} while (0) + +#define tmc_i2c_dbg(dev, fmt, args...) \ +do { \ + if (tmc_i2c_debug >= 1) \ + dev_err(dev, fmt, ## args); \ +} while (0) + + +/* pfe TMC i2c channel */ +static int pfe_channel = 32; +module_param(pfe_channel, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(pfe_channel, "Maximum number of channel for PFE TMC"); + +/* chassid TMC i2c channel */ +static int chd_channel = 11; +module_param(chd_channel, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(chd_channel, "Maximum number of channel for CHASSID TMC"); + +static u32 wr_index_to_oper[] = {0x01000000, 0x02000000, + 0x84000000, 0x85000000, 0x83000000}; +static u32 rd_index_to_oper[] = {0x08000000, 0x09000000, 0x0A000000, + 0x8B000000, 0x8C000000, 0x8D000000, 0x83000000}; + +struct tmc_i2c_adapter_stats { + u32 abort; + u32 go; + u32 mstr_rdy; + u32 mstr_busy; + u32 trans_compl; + u32 msg_cnt; + u32 rd_cnt; + u32 wr_cnt; + u32 byte_cnt; + u32 slave_timeo; + u32 scl_bus_loss; + u32 sda_bus_loss; + u32 ack_ptimeo; + u32 rd_cnt_0; + u32 rd_cnt_gt32; + u32 rst_tgt; + u32 rst_mstr; +}; + +struct tmc_i2c_adapter { + void __iomem *membase; + void __iomem *dpmbase; + struct i2c_adapter adap; + struct i2c_mux_core *muxc; + struct tmc_i2c_ctrl *tctrl; + int mux_channels; + int mux_select; + u32 i2c_delay; + int entries; + int master; + u32 control; + u32 speed; + bool done; + bool polling; + bool use_block; + wait_queue_head_t wait; + struct tmc_i2c_adapter_stats stat; +}; + +struct tmc_i2c_ctrl { + void __iomem *membase; + void __iomem *dpmbase; + struct i2c_adapter **adap; + struct device *dev; + int num_masters; + int mux_channels; + u32 i2c_delay; + u32 master_mask; + spinlock_t lock; /* master lock */ +}; + +/* + * Reset the Tmc I2C master + */ +static void tmc_i2c_reset_master(struct i2c_adapter *adap) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + struct tmc_i2c_ctrl *tmc = TMC_I2C_GET_MASTER(tadap); + u32 val, master = tadap->master; + unsigned long flags; + void __iomem *addr; + + dev_warn(&adap->dev, "Re-setting i2c master: %d\n", master); + + TMC_I2C_MASTER_LOCK(tmc, flags); + + addr = tmc->membase + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET; + val = ioread32(addr); + tmc_iowrite(val | (TMC_I2C_MASTER_I2C_SCAN_RESET_BIT), addr); + tmc_iowrite(val & ~(TMC_I2C_MASTER_I2C_SCAN_RESET_BIT), addr); + TMC_I2C_STAT_INC(tadap, rst_mstr); + + TMC_I2C_MASTER_UNLOCK(tmc, flags); +} + +/* + * check if the Tmc I2C master is ready + */ +static int tmc_i2c_mstr_wait_rdy(struct i2c_adapter *adap, u8 rw, u32 delay) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + unsigned long timeout; + u32 val; + + val = ioread32(TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + if (val) { + tmc_iowrite(0x80000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + mdelay(5); + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + val = ioread32(TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + } else { + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + } + + if ((rw == TMC_I2C_READ) && (delay)) { + tmc_iowrite(0x80000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + return 0; + } + + timeout = jiffies + adap->timeout; + do { + val = ioread32(TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + if (!val) + return 0; + + if (tadap->polling) { + usleep_range(50, 100); + } else { + tadap->done = false; + wait_event_timeout(tadap->wait, tadap->done, + adap->timeout); + } + } while (time_before(jiffies, timeout)); + + TMC_I2C_STAT_INC(tadap, mstr_busy); + + return -EBUSY; +} + +/* + * Wait for master completion + */ +static u32 tmc_i2c_mstr_wait_completion(struct i2c_adapter *adap, + u32 dp_entry_offset) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + u32 val; + + if (tadap->polling) { + /* Poll for the results */ + unsigned long timeout = jiffies + adap->timeout; + + do { + usleep_range(1000, 1200); + val = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap, + dp_entry_offset)); + if (TMC_I2C_CTRL_DONE(val)) + break; + } while (time_before(jiffies, timeout)); + } else { + wait_event_timeout(tadap->wait, tadap->done, adap->timeout); + val = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap, + dp_entry_offset)); + } + + return TMC_I2C_CTRL_STATUS_OK(val); +} + +/* + * TMC I2C delay read/write operation + */ +static int tmc_i2c_delay_rw_op(struct i2c_adapter *adap, u8 rw, u32 mux, + u32 addr, u32 offset, u32 len, u32 delay, u8 *buf) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + struct device *dev = &adap->dev; + int err, n; + u32 control = 0, data = 0; + u32 val; + + err = tmc_i2c_mstr_wait_rdy(adap, rw, 0); + if (err < 0) { + tmc_i2c_reset_master(adap); + return err; + } + + TMC_I2C_STAT_INC(tadap, mstr_rdy); + + /* initialize the start address and mux */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET)); + + tmc_iowrite(mux, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0)); + tmc_iowrite(0x84400000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4)); + + /* populate delay */ + if (delay) { + if (delay > 1000) { + delay = delay/1000; + delay |= (1 << 16); + } + } + tmc_iowrite(delay, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8)); + tmc_iowrite(0x86000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C)); + + /* prepare control command */ + control |= TMC_I2C_CTRL_DEVADDR(addr); + control |= TMC_I2C_CTRL_OFFSET(offset); + + if (rw == TMC_I2C_WRITE) { + for (n = 0; n < len; n++) + data |= (buf[n] << ((len - 1 - n) * 8)); + tmc_iowrite(data, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10)); + control |= TMC_I2C_CTRL_WRCNT(len); + control |= wr_index_to_oper[len-1]; + dev_dbg(dev, "WR Data: [%#04x, %#04x, %#04x, %#04x]\n", + ((data >> 24) & 0xff), ((data >> 16) & 0xff), + ((data >> 8) & 0xff), (data & 0xff)); + + } else { + /* read */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10)); + control |= TMC_I2C_CTRL_RDCNT(len); + control |= rd_index_to_oper[len-1]; + } + + /* + * valid this transaction as well + */ + control |= TMC_I2C_MEM_CTRL_VLD; + + tadap->control = control; + + /* + * operation control command + */ + tmc_iowrite(control, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14)); + + /* + * End commands + */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18)); + tmc_iowrite(0x8E000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C)); + tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_20)); + tmc_iowrite(0x8F000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_24)); + + dev_dbg(dev, "Control (%#x): RD_WR_TYPE:%#02x, RD_WR_LEN:%d," + "Addr:%#01x, Offset:%#02x\n", control, + ((control >> 24) & 0x3F), ((control >> 16) & 0x3F), + ((control >> 8) & 0xff), ((control) & 0xff)); + + tadap->done = false; + + /* fire the transaction */ + tmc_iowrite(0x00000001, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + + TMC_I2C_STAT_INC(tadap, go); + + val = tmc_i2c_mstr_wait_completion(adap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10); + if (val) { + dev_err(&adap->dev, + "i2c transaction error (0x%08x)\n", val); + + /* stop the transaction */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + return -EIO; + } + + /* + * read a word of data + */ + if (rw == TMC_I2C_READ) { + data = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10)); + for (n = 0; n < len; n++) + buf[n] = (data >> (n * 8)) & 0xff; + + dev_dbg(dev, "RD Data: [%#04x, %#04x, %#04x, %#04x]\n", + ((data >> 24) & 0xff), ((data >> 16) & 0xff), + ((data >> 8) & 0xff), (data & 0xff)); + + TMC_I2C_STAT_INC(tadap, rd_cnt); + } else { + /* write */ + TMC_I2C_STAT_INC(tadap, wr_cnt); + } + + /* stop the transaction */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + + return 0; + +} + +/* + *TMC I2C none delay Read/write opertion + */ +static int tmc_i2c_none_delay_rw_op(struct i2c_adapter *adap, u8 rw, u32 mux, + u32 addr, u32 offset, u32 len, u8 *buf) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + struct device *dev = &adap->dev; + int err, n; + u32 control = 0, data = 0; + u32 val; + + err = tmc_i2c_mstr_wait_rdy(adap, rw, 0); + if (err < 0) { + tmc_i2c_reset_master(adap); + return err; + } + + TMC_I2C_STAT_INC(tadap, mstr_rdy); + + /* initialize the start address and mux */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET)); + + tmc_iowrite(mux, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0)); + tmc_iowrite(0x84400000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4)); + + + /* prepare control command */ + control |= TMC_I2C_CTRL_DEVADDR(addr); + control |= TMC_I2C_CTRL_OFFSET(offset); + + if (rw == TMC_I2C_WRITE) { + for (n = 0; n < len; n++) + data |= (buf[n] << (n * 8)); + tmc_iowrite(data, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8)); + control |= wr_index_to_oper[len-1]; + dev_dbg(dev, "WR Data: [%#04x, %#04x, %#04x, %#04x]\n", + ((data >> 24) & 0xff), ((data >> 16) & 0xff), + ((data >> 8) & 0xff), (data & 0xff)); + + } else { + /* read */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8)); + control |= rd_index_to_oper[len-1]; + } + + /* + * valid this transaction as well + */ + control |= TMC_I2C_MEM_CTRL_VLD; + + tadap->control = control; + + /* + * operation control command + */ + tmc_iowrite(control, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C)); + + /* + * End commands + */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10)); + tmc_iowrite(0x8E000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14)); + tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18)); + tmc_iowrite(0x8F000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C)); + + dev_dbg(dev, "Control (%#x): RD_WR_TYPE:%#02x, RD_WR_LEN:%d," + "Addr:%#01x, Offset:%#02x\n", control, + ((control >> 24) & 0x3F), ((control >> 16) & 0x3F), + ((control >> 8) & 0xff), ((control) & 0xff)); + + tadap->done = false; + + /* fire the transaction */ + tmc_iowrite(0x00000001, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + + TMC_I2C_STAT_INC(tadap, go); + + /* wait till transaction complete */ + val = tmc_i2c_mstr_wait_completion(adap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8); + if (val) { + dev_err(&adap->dev, + "i2c transaction error (0x%08x)\n", val); + + /* stop the transaction */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + return -EIO; + } + + /* + * read a word of data + */ + if (rw == TMC_I2C_READ) { + data = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8)); + for (n = 0; n < len; n++) + buf[n] = (data >> (n * 8)) & 0xff; + + dev_dbg(dev, "RD Data: [%#04x, %#04x, %#04x, %#04x]\n", + ((data >> 24) & 0xff), ((data >> 16) & 0xff), + ((data >> 8) & 0xff), (data & 0xff)); + TMC_I2C_STAT_INC(tadap, rd_cnt); + } else { + /* write */ + TMC_I2C_STAT_INC(tadap, wr_cnt); + } + + /* stop the transaction */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + + return 0; +} + +/* + * TMC I2C read/write operation + */ +static int tmc_i2c_rw_op(struct i2c_adapter *adap, u8 rw, u32 mux, + u32 addr, u32 offset, u32 len, u8 *buf) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + u32 i2c_delay = tadap->i2c_delay; + + if (i2c_delay) { + return tmc_i2c_delay_rw_op(adap, rw, mux, addr, offset, + len, i2c_delay, buf); + } else { + return tmc_i2c_none_delay_rw_op(adap, rw, mux, addr, offset, + len, buf); + } +} + +static int tmc_i2c_calc_entries(int msglen) +{ + int entries = msglen / TMC_I2C_TRANS_LEN; + + return (entries += (msglen % TMC_I2C_TRANS_LEN) ? 1 : 0); +} + +static int tmc_i2c_block_read(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + struct device *dev = &adap->dev; + int curmsg, entries, len; + int offset = 0; + struct i2c_msg *msg; + int err, n = 0; + u8 rwbuf[4] = {0}; + + dev_dbg(dev, "Read i2c Block\n"); + + for (curmsg = 0, offset = 0; curmsg < num; curmsg++) { + msg = &msgs[curmsg]; + len = msg->len; + + if (msg->flags & I2C_M_RECV_LEN) + len = (I2C_SMBUS_BLOCK_MAX + 1); + + entries = tmc_i2c_calc_entries(len); + + if (msg->flags & I2C_M_RD) { + if (curmsg == 1 && ((msg->flags & I2C_M_RECV_LEN && + !(msgs[0].flags & I2C_M_RD)) || + (msg->len > TMC_I2C_TRANS_LEN))) { + offset = msgs[0].buf[0]; + } + + while (entries) { + err = tmc_i2c_rw_op(adap, TMC_I2C_READ, + tadap->mux_select, + msgs[0].addr, offset, + TMC_I2C_TRANS_LEN, rwbuf); + if (err < 0) + return err; + msg = &msgs[num - 1]; + msg->buf[n] = rwbuf[0]; + msg->buf[n+1] = rwbuf[1]; + n = n + TMC_I2C_TRANS_LEN; + offset = offset + TMC_I2C_TRANS_LEN; + entries--; + } + } + } + + return 0; +} + +/* + *TMC I2C SMB Read opertion + */ +static int tmc_i2c_smb_block_read_op(struct i2c_adapter *adap, u8 rw, u32 mux, + u32 addr, u32 offset, u32 len, u8 *buf) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + int err, i = 0; + u32 control = 0, data = 0; + u32 start_add; + + err = tmc_i2c_mstr_wait_rdy(adap, rw, 0); + if (err < 0) { + tmc_i2c_reset_master(adap); + return err; + } + + TMC_I2C_STAT_INC(tadap, mstr_rdy); + + /* initialize the start address and mux */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET)); + + tmc_iowrite(mux, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0)); + tmc_iowrite(0x84400000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4)); + + + /* prepare control command */ + control |= TMC_I2C_CTRL_DEVADDR(addr); + control |= TMC_I2C_CTRL_OFFSET(offset); + + /* read */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8)); + control |= TMC_I2C_CTRL_RDCNT(len);; + control |= rd_index_to_oper[6]; + + tadap->control = control; + + /* + * operation control command + */ + tmc_iowrite(control, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C)); + + /* + * End commands + */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10)); + tmc_iowrite(0x8E000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14)); + tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18)); + tmc_iowrite(0x8F000000, TMC_I2C_MSTR_I2C_DPMEM(tadap, + TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C)); + + tadap->done = false; + + /* fire the transaction */ + tmc_iowrite(0x00000001, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + + TMC_I2C_STAT_INC(tadap, go); + + /* + * read a block of data + */ + start_add = TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8; + while (len > 0) { + usleep_range(10000, 12000); + data = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap, start_add)); + buf[i] = data & 0xff; + buf[i + 1] = (data >> 8) & 0xff; + start_add = start_add + 8; + i = i + 2; + len = len - 2; + + TMC_I2C_STAT_INC(tadap, rd_cnt); + } + + /* stop the transaction */ + tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap, + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET)); + + return 0; +} + +static int tmc_i2c_smb_block_read(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + int curmsg, len; + int offset = 0; + struct i2c_msg *msg; + int err, i = 0; + u8 rwbuf[32] = {0}; + + for (curmsg = 0, offset = 0; curmsg < num; curmsg++) { + msg = &msgs[curmsg]; + len = msg->len; + + if (msg->flags & I2C_M_RECV_LEN) + len = (I2C_SMBUS_BLOCK_MAX + 1); + + if (msg->flags & I2C_M_RD) { + if ((curmsg == 1) && (msg->flags & I2C_M_RECV_LEN) && + !(msgs[0].flags & I2C_M_RD)) { + offset = msgs[0].buf[0]; + } + + err = tmc_i2c_smb_block_read_op(adap, TMC_I2C_READ, + tadap->mux_select, + msgs[0].addr, offset, + 32, rwbuf); + if (err < 0) { + return err; + } + msg = &msgs[num - 1]; + for (i = 0; i < len - 1; i++) { + msg->buf[i] = rwbuf[i]; + } + } + } + + return 0; +} + +static int tmc_i2c_mstr_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + struct device *dev = &adap->dev; + int n, curmsg, len = 0; + int err = 0; + struct i2c_msg *msg; + bool read; + u8 rwbuf[4] = {0}; + + dev_dbg(dev, "Num messages -> %d\n", num); + + /* + * Initialize all vars + */ + tadap->entries = 0; + tadap->use_block = false; + + for (curmsg = 0; curmsg < num; curmsg++) { + msg = &msgs[curmsg]; + dev_dbg(dev, "[%02d] %d bytes, flag %#02x buf %#02x\n", + curmsg, msg->len, msg->flags, msg->buf[0]); + if ((msg->len > TMC_I2C_TRANS_LEN) || + ((msg->flags & I2C_M_RD) && + (msg->flags & I2C_M_RECV_LEN))) { + /* If PEC is enabled len will come as 3 for a word read. + * We don't want to use block read for this case. + */ + if ((msg->flags & I2C_CLIENT_PEC) && + (msg->len == TMC_I2C_TRANS_LEN+1)) { + tadap->use_block = false; + } else { + tadap->use_block = true; + } + break; + } + } + + if (tadap->use_block) { + /* Read Block */ + if ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN)) { + err = tmc_i2c_smb_block_read(adap, msgs, num); + } else { + err = tmc_i2c_block_read(adap, msgs, num); + } + if (err < 0) + return err; + } else { + read = msgs[num - 1].flags & I2C_M_RD; + for (curmsg = 0; curmsg < num; curmsg++) { + msg = &msgs[curmsg]; + len = msg->len; + + dev_dbg(dev, " [%02d] %s %d bytes addr %#02x, " + "flag %#02x, buf[0] %#02x\n", curmsg, + read ? "RD" : "WR", len, msg->addr, + msg->flags, msg->buf[0]); + + /* SMBus quick read/write command */ + if (len == 0 && curmsg == 0 && num == 1) { + if (read) { + len = 1; + } + break; + } + + if (curmsg == 0) { + if (!read) { + for (n = 1; n < len; n++) + rwbuf[n-1] = (msg->buf[n]); + len--; + } else { + /* read operation */ + continue; + } + } + } + + if (!read) { + /* write */ + err = tmc_i2c_rw_op(adap, TMC_I2C_WRITE, + tadap->mux_select, msgs[0].addr, + msgs[0].buf[0], len, rwbuf); + } else { + /* read */ + /* + * If PEC is enabled read only 2 bytes as expected in + * case of a word read instead of 3 to make it compatible + * with word write implementation. + */ + if (msg->flags & I2C_CLIENT_PEC && (len == TMC_I2C_TRANS_LEN + 1)) { + len--; + } + + err = tmc_i2c_rw_op(adap, TMC_I2C_READ, + tadap->mux_select, + msgs[0].addr, msgs[0].buf[0], + len, rwbuf); + msg = &msgs[num - 1]; + len = msg->len; + /* + * To avoid failure in PEC enabled case clear flag. + */ + if (len == TMC_I2C_TRANS_LEN + 1) { + msgs[num - 1].flags &= ~I2C_M_RD; + } + for (n = 0; n < len; n++) + msg->buf[n] = rwbuf[n]; + } + if (err < 0) + return err; + } + + TMC_I2C_STAT_INCN(tadap, msg_cnt, num); + + return num; +} + +static u32 tmc_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL + | I2C_FUNC_SMBUS_READ_BLOCK_DATA; +} + +static const struct i2c_algorithm tmc_i2c_algo = { + .master_xfer = tmc_i2c_mstr_xfer, + .functionality = tmc_i2c_func, +}; + +static int tmc_i2c_mux_group_sel(struct i2c_mux_core *muxc, u32 chan) +{ + struct tmc_i2c_adapter *tadap = i2c_mux_priv(muxc); + + dev_dbg(muxc->dev, "chan = %d\n", chan); + + if (!tadap || chan > TMC_I2C_MSTR_MAX_GROUPS) + return -ENODEV; + tadap->mux_select = chan; + + return 0; +} + +static int tmc_i2c_mux_init(struct i2c_adapter *adap) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + int chan, ret; + + tadap->muxc = i2c_mux_alloc(adap, &adap->dev, tadap->mux_channels, + 0, 0, tmc_i2c_mux_group_sel, NULL); + + if (!tadap->muxc) + return -ENOMEM; + + tadap->muxc->priv = tadap; + for (chan = 0; chan < tadap->mux_channels; chan++) { + ret = i2c_mux_add_adapter(tadap->muxc, 0, chan, 0); + if (ret) { + dev_err(&adap->dev, "Failed to add adapter %d\n", chan); + i2c_mux_del_adapters(tadap->muxc); + return ret; + } + } + + return 0; +} + +static struct i2c_adapter * +tmc_i2c_init_one(struct tmc_i2c_ctrl *tmc, + int master, int id) +{ + struct tmc_i2c_adapter *adapter; + struct device *dev = tmc->dev; + int err; + + adapter = devm_kzalloc(dev, sizeof(*adapter), GFP_KERNEL); + if (!adapter) + return ERR_PTR(-ENOMEM); + + init_waitqueue_head(&adapter->wait); + adapter->adap.owner = THIS_MODULE; + adapter->adap.algo = &tmc_i2c_algo; + adapter->adap.nr = -1; + adapter->adap.timeout = HZ / 5; + adapter->master = master; + adapter->mux_channels = tmc->mux_channels; + adapter->i2c_delay = tmc->i2c_delay; + adapter->membase = tmc->membase; + adapter->dpmbase = tmc->dpmbase; + adapter->polling = 1; + adapter->tctrl = tmc; + + i2c_set_adapdata(&adapter->adap, adapter); + snprintf(adapter->adap.name, sizeof(adapter->adap.name), + "%s:%d", dev_name(dev), master); + + adapter->adap.dev.parent = dev; + err = i2c_add_numbered_adapter(&adapter->adap); + if (err) + goto error; + + err = tmc_i2c_mux_init(&adapter->adap); + if (err) + goto err_remove; + + dev_dbg(dev, "Adapter[%02d-%02d]: " + "dpmbase: 0x%lx\n", id, master, + (unsigned long)adapter->dpmbase); + return &adapter->adap; + +err_remove: + i2c_del_adapter(&adapter->adap); +error: + return ERR_PTR(err); +} + +static void tmc_i2c_cleanup_one(struct i2c_adapter *adap) +{ + struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap); + + i2c_mux_del_adapters(tadap->muxc); + i2c_del_adapter(adap); + +} + + +static int tmc_i2c_of_init(struct device *dev, + struct tmc_i2c_ctrl *tmc, int id) +{ + u32 mux_channels, master, num_masters = 0, master_mask = 0; + u32 i2c_delay = 0; + + if (!(master_mask & BIT(master))) + num_masters++; + master_mask |= BIT(master); + + if (id == 0) { + /* chassisd */ + mux_channels = chd_channel; + num_masters = 1; + i2c_delay = 0; + } else if (id == 1) { + /* pfe */ + mux_channels = pfe_channel; + num_masters = 1; + i2c_delay = 20; + } else { + return -EINVAL; + } + + tmc->adap = devm_kcalloc(dev, num_masters, + sizeof(struct i2c_adapter *), + GFP_KERNEL); + if (!tmc->adap) + return -ENOMEM; + + tmc->num_masters = num_masters; + tmc->master_mask = master_mask; + tmc->mux_channels = mux_channels; + tmc->i2c_delay = i2c_delay; + + return 0; +} + +static int tmc_i2c_probe(struct platform_device *pdev) +{ + int i, n, err; + struct resource *res; + struct i2c_adapter *adap; + struct device *dev = &pdev->dev; + struct tmc_i2c_ctrl *tmc; + + const struct mfd_cell *cell = mfd_get_cell(pdev); + + /* + * Allocate memory for the Tmc FPGA + */ + tmc = devm_kzalloc(dev, sizeof(*tmc), GFP_KERNEL); + if (!tmc) + return -ENOMEM; + + platform_set_drvdata(pdev, tmc); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + dev_info(dev, "Tmc I2C Accel resource 0x%llx, %llu\n", + res->start, resource_size(res)); + + tmc->membase = devm_ioremap_nocache(dev, res->start, + resource_size(res)); + if (!tmc->membase) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) + return -ENODEV; + + dev_info(dev, "Tmc I2C Mem resource 0x%llx, %llu\n", + res->start, resource_size(res)); + + tmc->dpmbase = devm_ioremap_nocache(dev, res->start, + resource_size(res)); + if (!tmc->dpmbase) + return -ENOMEM; + + tmc->dev = dev; + spin_lock_init(&tmc->lock); + + err = tmc_i2c_of_init(dev, tmc, cell->id); + if (err) + return err; + + dev_info(dev, "Tmc I2C Masters: %d\n", tmc->num_masters); + dev_info(dev, "Tmc I2C Delay: %d\n", tmc->i2c_delay); + + for (n = 0, i = 0; i < TMC_I2C_MASTER_NR_MSTRS; i++) { + if (tmc->master_mask & BIT(i)) { + adap = tmc_i2c_init_one(tmc, i, n); + if (IS_ERR(adap)) { + err = PTR_ERR(adap); + dev_err(dev, "Failed to initialize master " + "adapter %d: %d\n", i, err); + goto err_remove; + } + tmc->adap[n++] = adap; + } + } + + return 0; + +err_remove: + for (n--; n >= 0; n--) + tmc_i2c_cleanup_one(tmc->adap[n]); + return err; +} + +static int tmc_i2c_remove(struct platform_device *pdev) +{ + struct tmc_i2c_ctrl *tmc = platform_get_drvdata(pdev); + int i; + + /* Disable all masters */ + tmc_iowrite(0, tmc->membase + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET); + + for (i = 0; i < tmc->num_masters; i++) + tmc_i2c_cleanup_one(tmc->adap[i]); + + return 0; +} + +static struct platform_driver tmc_i2c_driver = { + .driver = { + .name = "i2c-tmc", + .owner = THIS_MODULE, + }, + .probe = tmc_i2c_probe, + .remove = tmc_i2c_remove, +}; + +module_platform_driver(tmc_i2c_driver); + +MODULE_DESCRIPTION("Juniper Networks TMC FPGA I2C Accelerator driver"); +MODULE_AUTHOR("Ashish Bhensdadia "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-refpga-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-refpga-tmc.c new file mode 100644 index 000000000000..ef36bca72e9d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-refpga-tmc.c @@ -0,0 +1,603 @@ +/* + * Juniper Networks RE-FPGA qfx platform specific driver + * + * Copyright (C) 2020 Juniper Networks + * Author: Ciju Rajan K + * + * This driver implements various features such as + * - ALARM led driver + * - Fan full speed reset control + * - FAN precense detection + * - FAN type detection + * - Any new QFX specific features which uses RE-FPGA + * + * 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 + +#define NUM_LEDS 7 /* Max number of Alarm + FAN LEDs */ + +#define ALARM_MINOR_LED 0 +#define ALARM_MAJOR_LED 1 + +#define REFPGA_PCIE_RESET_CTRL 0x13 +#define REFPGA_PCIE_ALARM 0x33 +#define REFPGA_FAN0_CTRL_STAT 0x28 + +#define REFPGA_RESET_FAN_SPEED BIT(3) +#define REFPGA_OPER_TYPE BIT(0) +#define REFPGA_OPER_START BIT(1) +#define REFPGA_OPER_DONE BIT(2) + +#define TMC_REFPGA_ADDR_REG 0x0 /* TMC offset: 0x228 */ +#define TMC_REFPGA_DATA_REG 0x4 /* TMC offset: 0x22C */ +#define TMC_REFPGA_CTRL_REG 0x8 /* TMC offset: 0x230 */ + +#define TMC_REFPGA_READ_CMD 0x3 +#define TMC_REFPGA_WRITE_CMD 0x2 + +#define REFPGA_INTR_NR_GROUPS 1 +#define REFPGA_INTR_MAX_IRQS_PG 32 + +#define MAX_FANS 5 + +#define REFPGA_IRQ_MAX_BITS_PER_REG 32 + +#define POLL_INTERVAL 5000 + +#define AFI_MASK (0x01) +#define AFO_MASK (0x02) +#define AFI_AFO_MASK (0x03) +/* + * LED specific data structures + */ +struct refpga_led { + struct led_classdev lc; + struct work_struct work; + int blink; + int on; + int bit; + void __iomem *addr; +}; + +struct refpga_led_data { + int num_leds; + struct refpga_led *leds; +}; + +static DEFINE_MUTEX(alarm_led_lock); + +/* + * Common routines + */ +struct refpga_chip { + struct refpga_led_data *led; +}; + +static struct refpga_chip *refpga; + +static DEFINE_MUTEX(refpga_lock); + +static void __iomem *tmc_membase; + +static void wait_for_refpga_oper(void __iomem *base_addr) +{ + volatile u32 done = ~(-1); + unsigned long int timeout; + void __iomem *addr; + + addr = base_addr + (TMC_REFPGA_CTRL_REG); + /* + * Wait till the transaction is complete + */ + timeout = jiffies + msecs_to_jiffies(100); + + do { + usleep_range(50, 100); + done = ioread32(addr); + if (done & (REFPGA_OPER_DONE)) + break; + } while(time_before(jiffies, timeout)); +} +static u32 refpga_read(void __iomem *base_addr, u32 refpga_offset) +{ + u32 value; + + mutex_lock(&refpga_lock); + iowrite32(refpga_offset, base_addr + (TMC_REFPGA_ADDR_REG)); + iowrite32(TMC_REFPGA_READ_CMD, base_addr + (TMC_REFPGA_CTRL_REG)); + wait_for_refpga_oper(base_addr); + value = ioread32(base_addr + (TMC_REFPGA_DATA_REG)); + mutex_unlock(&refpga_lock); + + return value; +} + +static void refpga_write(void __iomem *base_addr, u32 refpga_offset, u32 val) +{ + mutex_lock(&refpga_lock); + iowrite32(refpga_offset, base_addr + (TMC_REFPGA_ADDR_REG)); + iowrite32(val, base_addr + (TMC_REFPGA_DATA_REG)); + iowrite32(TMC_REFPGA_WRITE_CMD, base_addr + (TMC_REFPGA_CTRL_REG)); + wait_for_refpga_oper(base_addr); + mutex_unlock(&refpga_lock); +} + +static bool get_fan_presense(u8 idx) +{ + u8 value = 0x00; + u8 offset = REFPGA_FAN0_CTRL_STAT; + bool ret = 0; + + value = refpga_read(tmc_membase, (offset + (idx * 2))); + /* + * Get the last two bits of REFPGA_FANx_CTRL_STAT. + * REFPGA_FANx_CTRL_STAT register of REFPGA gives the fan airflow + * status. There are 5 fans in QFX5200. Last two bits give the AFI + * & AFO status. If any of these bits are set, fan is present. + */ + value = (value & BIT(0)) | (value & BIT(1)); + if (value) + ret = 1; + + return ret; +} + +static int get_fan_type(u8 idx) +{ + u8 value = 0x00; + u8 offset = REFPGA_FAN0_CTRL_STAT; + int ret = -1; + + value = refpga_read(tmc_membase, (offset + (idx * 2))); + /* + * Get the last two bits of REFPGA_FANx_CTRL_STAT. + * REFPGA_FANx_CTRL_STAT register of REFPGA gives the fan airflow + * status. There are 5 fans in QFX5200. Last two bits give the AFI + * & AFO status. If bit1 is set, it's AFO and if bit 0 is set, + * it's AFI. + * + * This function will return '1' for AFO, '0' for AFI, and '-1' + * if there is no fan or if both AFI & AFO bits are set. + */ + value &= AFI_AFO_MASK; + + switch(value) { + case AFI_MASK: + ret = 0; + break; + case AFO_MASK: + ret = 1; + break; + default: + ret = -1; + break; + }; + + return ret; +} + +enum sysfs_fan_attributes { + FAN0_PRESENT, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, +}; + +enum sysfs_fan_type_attributes { + FAN0_TYPE, + FAN1_TYPE, + FAN2_TYPE, + FAN3_TYPE, + FAN4_TYPE, +}; + +/* + * The sysfs files will be present in this path + * /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan*_present + * /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan*_type + */ + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, refpga_fan_presense_show, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_type, S_IRUGO, refpga_fan_type_show, NULL, FAN##index##_TYPE) +#define DECLARE_FAN_TYPE_ATTR(index) &sensor_dev_attr_fan##index##_type.dev_attr.attr + +static ssize_t refpga_fan_presense_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr); + + return sprintf(buf, "%d\n", get_fan_presense(s_attr->index)); + +} + +static ssize_t refpga_fan_type_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr); + + return sprintf(buf, "%d\n", get_fan_type(s_attr->index)); + +} + +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(0); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); + +DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(0); +DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(1); +DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(2); +DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(3); +DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(4); + +static struct attribute *refpga_fan_attrs[] = { + DECLARE_FAN_PRESENT_ATTR(0), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_TYPE_ATTR(0), + DECLARE_FAN_TYPE_ATTR(1), + DECLARE_FAN_TYPE_ATTR(2), + DECLARE_FAN_TYPE_ATTR(3), + DECLARE_FAN_TYPE_ATTR(4), + NULL +}; + +static struct attribute_group refpga_fan_attr_group = { + .attrs = refpga_fan_attrs, +}; + +/* + * There is only a single ALARM led in QFX5200 and that + * is used for both Major & Minor alarm indicator. + * These are represented by two different bits in RE-FPGA + * PCIE_ALARM register. Only one of the bit (either Red or + * Yellow) should be set a time. If both the bits are set, + * it's an undefined behaviour. + * + * The following table describes how the conditions are + * handled in the driver as there can be both Major & Minor + * alarms can be triggered from userspace. + * + * Major Minor Colour + * + * 0 0 Nil + * 0 1 Yellow + * 1 1 Red + * 1 0 Red + * + */ +static void manage_alarm_led(void __iomem *addr, int led_type, int value) +{ + static int alarm_major = 0, alarm_minor = 0; + u32 reg = 0x0; + + mutex_lock(&alarm_led_lock); + reg = refpga_read(addr, REFPGA_PCIE_ALARM); + + (led_type == ALARM_MAJOR_LED) ? + ((value == 1) ? (alarm_major = 1) : (alarm_major = 0)) : + ((value == 1) ? (alarm_minor = 1) : (alarm_minor = 0)); + if (alarm_major) { + reg &= ~BIT(ALARM_MINOR_LED); + reg |= BIT(ALARM_MAJOR_LED); + } else { + if (alarm_minor) { + reg &= ~BIT(ALARM_MAJOR_LED); + reg |= BIT(ALARM_MINOR_LED); + } else { + reg &= ~BIT(ALARM_MINOR_LED); + reg &= ~BIT(ALARM_MAJOR_LED); + } + } + refpga_write(addr, REFPGA_PCIE_ALARM, reg); + mutex_unlock(&alarm_led_lock); +} + +static void manage_fan_led(void __iomem *addr, int fan_slot, int value) +{ + u8 offset = REFPGA_FAN0_CTRL_STAT + (fan_slot * 2); + u32 reg = 0x0; + + reg = refpga_read(addr, offset); + if(value) { + /* Turn on s/w control */ + reg = reg | BIT(4); + /* Turn off green led */ + reg &= ~BIT(5); + /* Turn on yellow led & make it blink */ + reg |= (BIT(6) | BIT(7)); + } else { + /* Clear yellow led & stop blink */ + reg &= ~(BIT(6) | BIT(7)); + /* Stop s/w control */ + reg &= ~BIT(4); + } + refpga_write(addr, offset, reg); +} + +static void refpga_led_work(struct work_struct *work) +{ + struct refpga_led *led = container_of(work, struct refpga_led, work); + void __iomem *addr; + + addr = led->addr; + + if(strstr(led->lc.name, "fan")) + manage_fan_led(addr, led->bit, led->on); + else + manage_alarm_led(addr, led->bit, led->on); +} + +static void refpga_led_brightness_set(struct led_classdev *lc, + enum led_brightness brightness) +{ + struct refpga_led *led = container_of(lc, struct refpga_led, lc); + + led->on = (brightness != LED_OFF); + led->blink = 0; /* always turn off hw blink on brightness_set() */ + schedule_work(&led->work); +} + +struct led_table +{ + const char *name; + int reg; +}; + +static struct led_table qfx5200_led_data[] = { + { + .name = "alarm-minor", + .reg = 0, + }, + { + .name = "alarm-major", + .reg = 1, + }, + { + .name = "fan0-fault", + .reg = 0, + }, + { + .name = "fan1-fault", + .reg = 1, + }, + { + .name = "fan2-fault", + .reg = 2, + }, + { + .name = "fan3-fault", + .reg = 3, + }, + { + .name = "fan4-fault", + .reg = 4, + } +}; + +static int refpga_led_init_one(struct device *dev, + struct refpga_led_data *ild, + int num) +{ + struct refpga_led *led; + int ret = 0; + + led = &ild->leds[num]; + led->addr = tmc_membase; + + led->lc.name = qfx5200_led_data[num].name; + led->bit = qfx5200_led_data[num].reg; + led->lc.brightness = LED_OFF; + led->lc.brightness_set = refpga_led_brightness_set; + + ret = devm_led_classdev_register(dev, &led->lc); + if (ret) { + dev_err(dev, "devm_led_classdev_register failed\n"); + return ret; + } + + INIT_WORK(&led->work, refpga_led_work); + + return 0; +} + +static int refpga_led_qfx5200_init(struct device *dev, struct refpga_led_data *ild) +{ + int ret = 0, idx = 0; + + + if (!dev->parent) { + dev_err(dev, "dev->parent is null\n"); + return -ENODEV; + } + + ild->num_leds = NUM_LEDS; + ild->leds = devm_kzalloc(dev, sizeof(struct refpga_led) * NUM_LEDS, + GFP_KERNEL); + if (!ild->leds) { + dev_err(dev, "LED allocation failed\n"); + return -ENOMEM; + } + + for(idx=0; idxdev; + struct refpga_led_data *ild; + int ret; + + ild = devm_kzalloc(dev, sizeof(*ild), GFP_KERNEL); + if (!ild) { + dev_err(dev, "ild allocation failed\n"); + return -ENOMEM; + } + + ret = refpga_led_qfx5200_init(dev, ild); + if (ret < 0) + return ret; + + refpga->led = ild; + + return 0; +} + +static int jnx_refpga_led_remove(struct platform_device *pdev) +{ + struct refpga_chip *drv_data = platform_get_drvdata(pdev); + struct refpga_led_data *ild = drv_data->led; + int i; + + for (i = 0; i < ild->num_leds; i++) { + devm_led_classdev_unregister(&pdev->dev, &ild->leds[i].lc); + cancel_work_sync(&ild->leds[i].work); + } + if (ild) { + if (ild->leds) + devm_kfree(&pdev->dev, ild->leds); + devm_kfree(&pdev->dev, ild); + } + return 0; +} + +static void reset_fan_full_speed(struct device *dev) +{ + u32 val = ~(-1), tmp = ~(-1); + + /* + * Reading the REFPGA_PCIE_RESET_CTRL register + */ + val = refpga_read(tmc_membase, REFPGA_PCIE_RESET_CTRL); + /* + * Clearing the fan full_speed bit + */ + val &= ~(REFPGA_RESET_FAN_SPEED); + /* + * Writing the REFPGA_PCIE_RESET_CTRL register + */ + refpga_write(tmc_membase, REFPGA_PCIE_RESET_CTRL, val); + /* + * Reading the REFPGA_PCIE_RESET_CTRL register + */ + tmp = refpga_read(tmc_membase, REFPGA_PCIE_RESET_CTRL); + dev_info(dev, "After resetting fan full speed control: %X\n", tmp); +} + +static int jnx_refpga_tmc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + int ret = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "resource allocation failed\n"); + return -ENODEV; + } + + tmc_membase = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (!tmc_membase) { + dev_err(dev, "ioremap failed\n"); + return -ENOMEM; + } + + refpga = devm_kzalloc(dev, sizeof(*refpga), GFP_KERNEL); + if (!refpga) { + dev_err(dev, "refpga memory allocation failed\n"); + return -ENOMEM; + } + + reset_fan_full_speed(dev); + + ret = jnx_refpga_led_probe(pdev); + if (ret != 0) { + dev_err(dev, "Refpga LED probe failed\n"); + return ret; + } + + dev_info(dev, "Refpga LED probe successful: TMC memoy base: %p\n", + tmc_membase); + + ret = sysfs_create_group(&dev->kobj, &refpga_fan_attr_group); + if (ret != 0) { + dev_err(dev, "sysfs_create_group failed: %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, refpga); + + return 0; +} + +static int jnx_refpga_tmc_remove(struct platform_device *pdev) +{ + jnx_refpga_led_remove(pdev); + sysfs_remove_group(&pdev->dev.kobj, &refpga_fan_attr_group); + + return 0; +} + +static struct platform_driver jnx_refpga_tmc_driver = { + .driver = { + .name = "refpga-tmc", + .owner = THIS_MODULE, + }, + .probe = jnx_refpga_tmc_probe, + .remove = jnx_refpga_tmc_remove, +}; + +static int __init jnx_refpga_tmc_driver_init(void) +{ + int ret = -1; + + ret = platform_driver_register(&jnx_refpga_tmc_driver); + + return ret; + +} + +static void __exit jnx_refpga_tmc_driver_exit(void) +{ + platform_driver_unregister(&jnx_refpga_tmc_driver); +} + +module_init(jnx_refpga_tmc_driver_init); +module_exit(jnx_refpga_tmc_driver_exit); + +MODULE_DESCRIPTION("Juniper Networks REFPGA / TMC driver"); +MODULE_AUTHOR("Ciju Rajan K "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc-core.c b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc-core.c new file mode 100644 index 000000000000..833164bfed63 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc-core.c @@ -0,0 +1,477 @@ +/* + * Juniper Networks TMC-FPGA MFD Core driver for qfx platform + * + * Copyright (c) 2020, Juniper Networks + * Author: Ashish Bhensdadia + * + * This driver implement the resource publish for below devices + * - I2C + * - GPIO + * - RE FPGA + * - PSU + * + * 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 +#include +#include +#include +#include +#include +#include +#include "jnx-tmc.h" + +#define TMC_DO_SCRATCH_TEST 1 + +/* + * TMC FPGA Device IDs + */ +#define PCI_VENDOR_ID_JUNIPER 0x1304 + +#define PCI_DEVICE_ID_JNX_TMC_CHD 0x007B +#define PCI_DEVICE_ID_JNX_TMC_PFE 0x007C + +/* + * TMC resources + */ +static struct resource tmc_resource_i2c[] = { + /* I2C AUTOMATION Block */ + { + .name = "i2c-tmc", + .start = TMC_I2C_AUTOMATION_I2C_CONTROL_START, + .end = TMC_I2C_AUTOMATION_I2C_CONTROL_END, + .flags = IORESOURCE_MEM, + }, + + /* I2C DPMEM */ + { + .name = "i2c-tmc-mem", + .start = TMC_I2C_DPMEM_ENTRY_START, + .end = TMC_I2C_DPMEM_ENTRY_END, + .flags = IORESOURCE_MEM, + }, +}; + +#define TMC_RES_I2C_NR ARRAY_SIZE(tmc_resource_i2c) + +/* + * LED resources + */ +static struct resource tmc_resource_leds[] = { + { + .name = "leds-tmc", + .start = TMC_LED_CONTROL_START, + .end = TMC_LED_CONTROL_END, + .flags = IORESOURCE_MEM, + }, +}; + +#define TMC_RES_LEDS_NR ARRAY_SIZE(tmc_resource_leds) + +/* + * TMC RE-FPGA devices + */ +static struct resource tmc_resource_refpga[] = { + { + .name = "refpga-tmc", + .start = TMC_REFPGA_ACCESS_START, + .end = TMC_REFPGA_ACCESS_END, + .flags = IORESOURCE_MEM, + }, +}; + +#define TMC_RES_REFPGA_NR ARRAY_SIZE(tmc_resource_refpga) + +static struct resource tmc_resource_gpioslave0[] = { + /* SLAVE0 Block */ + { + .name = "gpioslave-tmc", + .start = TMC_GPIO_SLAVE0_START, + .end = TMC_GPIO_SLAVE0_END, + .flags = IORESOURCE_MEM, + } +}; + +#define TMC_RES_GPIOSLAVE0_NR ARRAY_SIZE(tmc_resource_gpioslave0) + +static struct resource tmc_resource_gpioslave1[] = { + /* SLAVE1 Block */ + { + .name = "gpioslave-tmc", + .start = TMC_GPIO_SLAVE1_START, + .end = TMC_GPIO_SLAVE1_END, + .flags = IORESOURCE_MEM, + } +}; + +#define TMC_RES_GPIOSLAVE1_NR ARRAY_SIZE(tmc_resource_gpioslave1) + +static struct resource tmc_resource_psu[] = { + /* PSU Block */ + { + .name = "psu-tmc", + .start = TMC_PSU_START, + .end = TMC_PSU_END, + .flags = IORESOURCE_MEM, + } +}; + +#define TMC_RES_PSU_NR ARRAY_SIZE(tmc_resource_psu) + +/* + * CHASSISD TMC MFD devices + */ +static struct mfd_cell chassisd_tmc_mfd_devs[] = { + { + .name = "i2c-tmc", + .num_resources = ARRAY_SIZE(tmc_resource_i2c), + .resources = &tmc_resource_i2c[0], + .of_compatible = "jnx,i2c-tmc", + .id = 0, + }, + { + .name = "leds-tmc", + .num_resources = ARRAY_SIZE(tmc_resource_leds), + .resources = &tmc_resource_leds[0], + .of_compatible = "jnx,leds-tmc", + .id = 0, + }, + { + .name = "refpga-tmc", + .num_resources = ARRAY_SIZE(tmc_resource_refpga), + .resources = &tmc_resource_refpga[0], + .of_compatible = "jnx,refpga-tmc", + .id = 0, + }, + { + .name = "psu-tmc", + .num_resources = ARRAY_SIZE(tmc_resource_psu), + .resources = &tmc_resource_psu[0], + .of_compatible = "jnx,psu-tmc", + .id = 0, + }, +}; + +/* + * PFE TMC MFD devices + */ +static struct mfd_cell pfe_tmc_mfd_devs[] = { + { + .name = "i2c-tmc", + .num_resources = ARRAY_SIZE(tmc_resource_i2c), + .resources = &tmc_resource_i2c[0], + .of_compatible = "jnx,i2c-tmc", + .id = 1, + }, + { + .name = "gpioslave-tmc", + .num_resources = ARRAY_SIZE(tmc_resource_gpioslave0), + .resources = &tmc_resource_gpioslave0[0], + .of_compatible = "jnx,gpioslave-tmc", + .id = 0, + }, + { + .name = "gpioslave-tmc", + .num_resources = ARRAY_SIZE(tmc_resource_gpioslave1), + .resources = &tmc_resource_gpioslave1[0], + .of_compatible = "jnx,gpioslave-tmc", + .id = 1, + }, +}; + + +struct tmc_fpga_data { + void __iomem *membase; + struct pci_dev *pdev; + + u32 major; /* Device id & Major version*/ + u32 minor; /* Minor version */ + + u32 optic_cpld_major; /* optic cpld major version */ + u32 optic_cpld_minor; /* optic cpld minor version */ + u32 optic_cpld_devid; /* optic cpld device id */ +}; + +/* sysfs entries */ +static ssize_t major_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tmc_fpga_data *tmc = dev_get_drvdata(dev); + + return sprintf(buf, "0x%02X_%06X\n", + (tmc->major >> 24) & 0xff, + tmc->major & 0xffffff); +} + +static ssize_t minor_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tmc_fpga_data *tmc = dev_get_drvdata(dev); + + return sprintf(buf, "%02X\n", (tmc->minor) & 0xff); +} + +static ssize_t optic_cpld_major_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tmc_fpga_data *tmc = dev_get_drvdata(dev); + + return sprintf(buf, "%01X\n", tmc->optic_cpld_major & 0xf); +} + +static ssize_t optic_cpld_devid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tmc_fpga_data *tmc = dev_get_drvdata(dev); + + return sprintf(buf, "%01X\n", + (tmc->optic_cpld_major >> 4) & 0xf); +} + +static ssize_t optic_cpld_minor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct tmc_fpga_data *tmc = dev_get_drvdata(dev); + + return sprintf(buf, "%02X\n", tmc->optic_cpld_minor & 0xff); +} + +static ssize_t set_sys_shutdown(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t len) +{ + + struct tmc_fpga_data *tmc = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) + return ret; + + if (val != 1) + return -EINVAL; + + /* Unlock the shutdown register */ + iowrite32(0x12345678, tmc->membase + TMC_SYS_SHUTDOWN_LOCK); + iowrite32(0x1, tmc->membase + TMC_SYS_SHUTDOWN); + + return len; +} + + +static DEVICE_ATTR(major, S_IRUGO, major_show, NULL); +static DEVICE_ATTR(minor, S_IRUGO, minor_show, NULL); +static DEVICE_ATTR(optic_cpld_major, S_IRUGO, optic_cpld_major_show, NULL); +static DEVICE_ATTR(optic_cpld_devid, S_IRUGO, optic_cpld_devid_show, NULL); +static DEVICE_ATTR(optic_cpld_minor, S_IRUGO, optic_cpld_minor_show, NULL); +static DEVICE_ATTR(shutdown, S_IWUSR, NULL, set_sys_shutdown); + +static struct attribute *tmc_attrs[] = { + &dev_attr_major.attr, + &dev_attr_minor.attr, + &dev_attr_optic_cpld_major.attr, + &dev_attr_optic_cpld_devid.attr, + &dev_attr_optic_cpld_minor.attr, + &dev_attr_shutdown.attr, + NULL, +}; + +static struct attribute_group tmc_attr_group = { + .attrs = tmc_attrs, +}; + +#if defined TMC_DO_SCRATCH_TEST +/* Do a quick scratch access test */ +static int tmc_do_test_scratch(struct tmc_fpga_data *tmc) +{ + struct pci_dev *pdev = tmc->pdev; + struct device *dev = &pdev->dev; + int offset = TMC_SCRATCH; + u32 acc, val = 0xdeadbeaf; + + /* + * Check rw register access -> use the scratch reg. + */ + iowrite32(val, tmc->membase + offset); + acc = ioread32(tmc->membase + offset); + if (acc != val) { + dev_err(dev, "Tmc scratch(0x%x) failed: %08x.%08x!\n", + offset, val, acc); + return -EIO; + } + + for (val = 0; val < 0xf0000000; val += 0x01010101) { + iowrite32(val, tmc->membase + offset); + acc = ioread32(tmc->membase + offset); + if (acc != val) { + dev_err(dev, "Tmc scratch(0x%x) failed: %08x.%08x!\n", + offset, val, acc); + return -EIO; + } + } + + /* + * Write a sig before leaving.. + */ + val = 0xcafebabe; + iowrite32(val, tmc->membase + offset); + dev_dbg(dev, "Tmc scratch result: 0x%08x\n", + ioread32(tmc->membase + offset)); + + return 0; +} +#endif /* TMC_DO_SCRATCH_TEST */ + +static int tmc_fpga_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int err; + struct tmc_fpga_data *tmc; + struct device *dev = &pdev->dev; + + dev_dbg(dev, "Tmc FPGA Probe called\n"); + + tmc = devm_kzalloc(dev, sizeof(*tmc), GFP_KERNEL); + if (!tmc) + return -ENOMEM; + + err = pcim_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, "Failed to enable device %d\n", err); + return err; + } + + err = pcim_iomap_regions(pdev, 1 << 0, "tmc-core"); + if (err) { + dev_err(&pdev->dev, "Failed to iomap regions %d\n", err); + goto err_disable; + } + + tmc->membase = pcim_iomap_table(pdev)[0]; + if (IS_ERR(tmc->membase)) { + dev_err(dev, "pci_ioremap_bar() failed\n"); + err = -ENOMEM; + goto err_release; + } + + tmc->pdev = pdev; + pci_set_drvdata(pdev, tmc); + + /* All Tmc uses MSI interrupts - enable bus mastering */ + pci_set_master(pdev); + +#if defined TMC_DO_SCRATCH_TEST + /* Check IO before proceeding */ + dev_dbg(dev, "Tmc FPGA starting scratch test\n"); + err = tmc_do_test_scratch(tmc); + if (err) + goto err_unmap; + + dev_dbg(dev, "Tmc FPGA scratch test passed !!!\n"); +#endif /* TMC_DO_SCRATCH_TEST */ + + switch (id->device) { + case PCI_DEVICE_ID_JNX_TMC_CHD: + err = mfd_add_devices(dev, pdev->bus->number, + &chassisd_tmc_mfd_devs[0], + ARRAY_SIZE(chassisd_tmc_mfd_devs), + &pdev->resource[0], + 0, NULL /* tmc->irq_domain */); + break; + case PCI_DEVICE_ID_JNX_TMC_PFE: + err = mfd_add_devices(dev, pdev->bus->number, + &pfe_tmc_mfd_devs[0], + ARRAY_SIZE(pfe_tmc_mfd_devs), + &pdev->resource[0], + 0, NULL /* tmc->irq_domain */); + break; + default: + dev_err(&pdev->dev, "Invalid PCI Device ID id:%d\n", + id->device); + goto err_unmap; + } + + if (err < 0) { + dev_err(&pdev->dev, "Failed to add mfd devices %d\n", err); + goto err_unmap; + } + + err = sysfs_create_group(&pdev->dev.kobj, &tmc_attr_group); + if (err) { + sysfs_remove_group(&pdev->dev.kobj, &tmc_attr_group); + dev_err(&pdev->dev, "Failed to create attr group\n"); + goto err_remove_mfd; + } + + tmc->major = ioread32(tmc->membase + TMC_REVISION); + tmc->minor = ioread32(tmc->membase + TMC_MINOR); + + tmc->optic_cpld_major = ioread32(tmc->membase + TMC_OPTIC_CPLD_MAJOR); + tmc->optic_cpld_minor = ioread32(tmc->membase + TMC_OPTIC_CPLD_MINOR); + + dev_info(dev, "Tmc FPGA Revision: 0x%02X_%06X, Minor: %02X\n", + (tmc->major >> 24) & 0xff, + tmc->major & 0xffffff, + (tmc->minor) & 0xff); + dev_info(dev, "Tmc FPGA optic cpld Major: 0x%01X, Minor: 0x%02X " + "Devid: 0x%01X\n", (tmc->optic_cpld_major) & 0xf, + (tmc->optic_cpld_minor) & 0xff, + (tmc->optic_cpld_major >> 4) & 0xf); + dev_info(dev, "Tmc FPGA mem:0x%lx\n", + (unsigned long)tmc->membase); + + return 0; + +err_remove_mfd: + mfd_remove_devices(dev); +err_unmap: + pci_iounmap(pdev, tmc->membase); +err_release: + pci_release_regions(pdev); +err_disable: + pci_disable_device(pdev); + + return err; +} + +static void tmc_fpga_remove(struct pci_dev *pdev) +{ + struct tmc_fpga_data *tmc = dev_get_drvdata(&pdev->dev); + + sysfs_remove_group(&pdev->dev.kobj, &tmc_attr_group); + mfd_remove_devices(&pdev->dev); +} + +static const struct pci_device_id tmc_fpga_id_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TMC_CHD) }, + { PCI_DEVICE(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TMC_PFE) }, + { } +}; +MODULE_DEVICE_TABLE(pci, tmc_fpga_id_tbl); + +static struct pci_driver tmc_fpga_driver = { + .name = "tmc-core", + .id_table = tmc_fpga_id_tbl, + .probe = tmc_fpga_probe, + .remove = tmc_fpga_remove, +}; + +module_pci_driver(tmc_fpga_driver); + +MODULE_DESCRIPTION("Juniper Networks TMC FPGA MFD core driver"); +MODULE_AUTHOR("Ashish Bhensdadia "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc.h b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc.h new file mode 100644 index 000000000000..dce7d7be3311 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc.h @@ -0,0 +1,93 @@ +/* + * Juniper Tmc FPGA register definitions + * + * Copyright (C) 2018 Juniper Networks + * Author: Ashish Bhensdadia + * + * 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. + */ + +#ifndef __JNX_TMC_H__ +#define __JNX_TMC_H__ + + +#define TMC_REVISION 0x00064 +#define TMC_MINOR 0x00068 +#define TMC_SCRATCH 0x00098 + +#define TMC_OPTIC_CPLD_MAJOR 0x00104 +#define TMC_OPTIC_CPLD_MINOR 0x00108 + +/* + * I2C Master Block + */ +#define TMC_I2C_AUTOMATION_I2C_CONTROL_START 0x07000 +#define TMC_I2C_AUTOMATION_I2C_CONTROL_END 0x07500 + +#define TMC_I2C_DPMEM_ENTRY_START 0x10000 +#define TMC_I2C_DPMEM_ENTRY_END 0x13FFC + +#define TMC_LED_CONTROL_START 0x58 +#define TMC_LED_CONTROL_END 0x5B + +/* + * RE-FPGA block + */ +#define TMC_REFPGA_ACCESS_START 0x228 +#define TMC_REFPGA_ACCESS_END 0x233 + +#define TMC_I2C_MASTER_NR_MSTRS 16 +#define TMC_I2C_MSTR_MAX_GROUPS 66 + + +/* + * TMC GPIO SLAVE Block + */ +#define TMC_GPIO_PTP_RESET_START 0x94 +#define TMC_GPIO_PTP_RESET_END 0x97 + +#define TMC_GPIO_PTP_CFG_START 0xa4 +#define TMC_GPIO_PTP_CFG_END 0xa7 + +#define TMC_GPIO_PTP_DATA_START 0xa8 +#define TMC_GPIO_PTP_DATA_END 0xab + +#define TMC_GPIO_SLAVE0_START 0xf0 +#define TMC_GPIO_SLAVE0_END 0x16b + +#define TMC_GPIO_SLAVE1_START 0x170 +#define TMC_GPIO_SLAVE1_END 0x1eb + +#define TMC_GPIO_SLAVE2_START 0x1f0 +#define TMC_GPIO_SLAVE2_END 0x213 + +#define TMC_GPIO_SLAVE3_START 0x280 +#define TMC_GPIO_SLAVE3_END 0x2eb + +#define TMC_GPIO_SFP_SLAVE0_START 0x308 +#define TMC_GPIO_SFP_SLAVE0_END 0x32b + +#define TMC_GPIO_SFP_SLAVE1_START 0x32c +#define TMC_GPIO_SFP_SLAVE1_END 0x34b + +/* + * TMC PSU Block + */ +#define TMC_PSU_START 0x240 +#define TMC_PSU_END 0x243 + +/* + * TMC SHUTDOWN REG + */ +#define TMC_SYS_SHUTDOWN_LOCK 0x254 +#define TMC_SYS_SHUTDOWN 0x250 + +/* + * TMC DS100 MUX Block + */ +#define TMC_GPIO_MUX_SLAVE_START 0x26c +#define TMC_GPIO_MUX_SLAVE_END 0x26f + +#endif /* __JNX_TMC_H__ */ diff --git a/platform/broadcom/sonic-platform-modules-juniper/debian/changelog b/platform/broadcom/sonic-platform-modules-juniper/debian/changelog new file mode 100755 index 000000000000..bc640fa563af --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/debian/changelog @@ -0,0 +1,6 @@ +sonic-juniper-platform-modules (1.1) unstable; urgency=low + + * Initial release: Add support for QFX5210. + -- Juniper Networks + Ciju Rajan K Tue, 30 July 2019 + diff --git a/platform/broadcom/sonic-platform-modules-juniper/debian/compat b/platform/broadcom/sonic-platform-modules-juniper/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-juniper/debian/control b/platform/broadcom/sonic-platform-modules-juniper/debian/control new file mode 100755 index 000000000000..9c3d12685a47 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/debian/control @@ -0,0 +1,14 @@ +Source: sonic-juniper-platform-modules +Section: main +Priority: extra +Maintainer: Juniper Networks +Build-Depends: debhelper (>= 9), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-juniper-qfx5210 +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-juniper-qfx5200 +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-juniper/debian/rules b/platform/broadcom/sonic-platform-modules-juniper/debian/rules new file mode 100755 index 000000000000..1a781912a544 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/debian/rules @@ -0,0 +1,85 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-juniper +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= qfx5210 qfx5200 +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules || exit 1; \ + $(PYTHON) setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} /$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} /usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} /lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5200.install b/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5200.install new file mode 100644 index 000000000000..a726447549d9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5200.install @@ -0,0 +1,8 @@ +qfx5200/utils/juniper_qfx5200_util.py usr/local/bin +qfx5200/utils/juniper_qfx5200_monitor.py usr/local/bin +qfx5200/utils/show_thresholds usr/local/bin +qfx5200/utils/temperature_thresholds_AFI.txt usr/local/bin +qfx5200/utils/temperature_thresholds_AFO.txt usr/local/bin +qfx5200/service/qfx5200-platform-init.service etc/systemd/system +qfx5200/utils/wrapper-warm-reboot usr/local/bin +qfx5200/utils/wrapper-fast-reboot usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5200.postinst b/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5200.postinst new file mode 100644 index 000000000000..bdcf70e2beaf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5200.postinst @@ -0,0 +1,37 @@ +#!/bin/bash + +systemctl enable qfx5200-platform-init.service +systemctl start qfx5200-platform-init.service + +# There are primary and secondary bios in qfx5200 platform. +# There is a problem with bios which prevents the OS booting from the +# secondary bios when the OS was installed using primary bios. +# Secondary bios fails to detect the UEFI partition. Right now +# the workaround is to have a folder structure /EFI/BOOT/BOOT64x.efi + +SONIC_VERSION=$(sonic-cfggen -y /etc/sonic/sonic_version.yml -v build_version) +FIRST_BOOT_FILE="/host/image-${SONIC_VERSION}/platform/firsttime" + +if [ -f $FIRST_BOOT_FILE ]; then + mkdir /tmp/sda1 + mount /dev/sda1 /tmp/sda1 + cd /tmp/sda1/EFI + mkdir BOOT > /dev/null 2>&1 + cp SONiC-OS/grubx64.efi BOOT/BOOTX64.EFI + cd /tmp + umount sda1 + # This code block ensures that no additional entries + # are added. This is applicable during SONiC image + # upgrades. + entries=`efibootmgr -v | grep "BOOTX64"` + if [ -z "$entries" ]; then + # Creating the UEFI entry for the first time. + efibootmgr -c -L "SONiC" -l "\EFI\BOOT\BOOTX64.EFI" > /var/tmp/efi_log 2>&1 + fi + mkdir /usr/bin/qfx5200-warm-reboot + mkdir /usr/bin/qfx5200-fast-reboot + cp /usr/bin/warm-reboot /usr/bin/qfx5200-warm-reboot + cp /usr/bin/fast-reboot /usr/bin/qfx5200-fast-reboot + cp /usr/local/bin/wrapper-warm-reboot /usr/bin/warm-reboot + cp /usr/local/bin/wrapper-fast-reboot /usr/bin/fast-reboot +fi diff --git a/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5210.install b/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5210.install new file mode 100644 index 000000000000..9444aae8b7c2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5210.install @@ -0,0 +1,6 @@ +qfx5210/utils/juniper_qfx5210_util.py usr/local/bin +qfx5210/utils/juniper_qfx5210_monitor.py usr/local/bin +qfx5210/utils/platform_poweroff usr/local/bin +qfx5210/service/qfx5210-platform-init.service etc/systemd/system +qfx5210/utils/wrapper-warm-reboot usr/local/bin +qfx5210/utils/wrapper-fast-reboot usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5210.postinst b/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5210.postinst new file mode 100644 index 000000000000..e4a9d353ef5d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5210.postinst @@ -0,0 +1,37 @@ +#!/bin/bash + +systemctl enable qfx5210-platform-init.service +systemctl start qfx5210-platform-init.service + +# There are primary and secondary bios in qfx5210 platform. +# There is a problem with bios which prevents the OS booting from the +# secondary bios when the OS was installed using primary bios. +# Secondary bios fails to detect the UEFI partition. Right now +# the workaround is to have a folder structure /EFI/BOOT/BOOT64x.efi + +SONIC_VERSION=$(sonic-cfggen -y /etc/sonic/sonic_version.yml -v build_version) +FIRST_BOOT_FILE="/host/image-${SONIC_VERSION}/platform/firsttime" + +if [ -f $FIRST_BOOT_FILE ]; then + mkdir /tmp/sda1 + mount /dev/sda1 /tmp/sda1 + cd /tmp/sda1/EFI + mkdir BOOT > /dev/null 2>&1 + cp SONiC-OS/grubx64.efi BOOT/BOOTX64.EFI + cd /tmp + umount sda1 + # This code block ensures that no additional entries + # are added. This is applicable during SONiC image + # upgrades. + entries=`efibootmgr -v | grep "BOOTX64"` + if [ -z "$entries" ]; then + # Creating the UEFI entry for the first time. + efibootmgr -c -L "SONiC" -l "\EFI\BOOT\BOOTX64.EFI" > /var/tmp/efi_log 2>&1 + fi + mkdir /usr/bin/qfx5210-warm-reboot + mkdir /usr/bin/qfx5210-fast-reboot + cp /usr/bin/warm-reboot /usr/bin/qfx5210-warm-reboot + cp /usr/bin/fast-reboot /usr/bin/qfx5210-fast-reboot + cp /usr/local/bin/wrapper-warm-reboot /usr/bin/warm-reboot + cp /usr/local/bin/wrapper-fast-reboot /usr/bin/fast-reboot +fi diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/Makefile b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/Makefile new file mode 100644 index 000000000000..2b9cc2c22f71 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/Makefile @@ -0,0 +1 @@ +obj-m:=jnx-tmc-core.o i2c-tmc.o jnx-refpga-tmc.o leds-jnx-tmc.o gpio-tmc.o jnx-tmc-psu.o jnx-psu-monitor.o jnx-refpga-lpcm.o diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/gpio-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/gpio-tmc.c new file mode 120000 index 000000000000..257a13181ee9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/gpio-tmc.c @@ -0,0 +1 @@ +../../common/modules/gpio-tmc.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/i2c-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/i2c-tmc.c new file mode 120000 index 000000000000..6fc8e5f3b47b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/i2c-tmc.c @@ -0,0 +1 @@ +../../common/modules/i2c-tmc.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-psu-monitor.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-psu-monitor.c new file mode 100644 index 000000000000..e1604d3d0d51 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-psu-monitor.c @@ -0,0 +1,325 @@ +/* + * A hwmon PSU monitoring driver for Juniper QFX5200 platform + * + * Copyright (C) 2020 Juniper Networks. + * Ciju Rajan K + * + * Based on ym2651.c by Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TEMP_INT_MASK (0xFFC0) +#define V_IN_INT_MASK (0xFFE0) +#define V_OUT_INT_MASK (0xFF00) +#define INVALID_READING (0xFFFF) +#define TEMP_FR_LEN 6 +#define V_IN_FR_LEN 5 +#define V_OUT_FR_LEN 8 + +static const unsigned short normal_i2c[] = { 0x58, 0x58, I2C_CLIENT_END }; + +struct psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u16 v_out; + u16 i_out; + u16 v_in; + u16 i_in; + u16 temp1_input; + u16 temp2_input; + u16 temp3_input; + u16 temp4_input; + u16 fan1_input; + u16 fan2_input; +}; + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); + +static struct psu_data *psu_update_device(struct device *dev); + +enum psu_sysfs_attributes { + PSU_V_OUT, + PSU_I_OUT, + PSU_V_IN, + PSU_I_IN, + PSU_TEMP1_INPUT, + PSU_TEMP2_INPUT, + PSU_TEMP3_INPUT, + PSU_TEMP4_INPUT, + PSU_FAN1_RPM, + PSU_FAN2_RPM, +}; + +/* + * sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_word, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_word, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_word, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_word, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_word, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_word, NULL, PSU_TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_word, NULL, PSU_TEMP3_INPUT); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_word, NULL, PSU_TEMP4_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_word, NULL, PSU_FAN1_RPM); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_word, NULL, PSU_FAN2_RPM); + +static struct attribute *psu_attributes[] = { + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + NULL +}; + +static short convert_to_decimal(u16 value, + u16 data_mask, + u8 fr_len) +{ + return (((short)value >= 0) ? ((value & data_mask) >> fr_len) : + (-((((~(value & data_mask)) >> fr_len) + 1)))); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct psu_data *data = psu_update_device(dev); + u32 value = 0x0000; + + switch (attr->index) { + case PSU_V_OUT: + value = 1000 * convert_to_decimal(data->v_out, + V_OUT_INT_MASK, + V_OUT_FR_LEN); + break; + case PSU_V_IN: + value = convert_to_decimal(data->v_in, + V_IN_INT_MASK, + V_IN_FR_LEN); + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = 1000 * data->i_out / 64; + break; + case PSU_FAN1_RPM: + value = data->fan1_input; + break; + case PSU_FAN2_RPM: + value = data->fan2_input; + break; + case PSU_TEMP1_INPUT: + value = 1000 * convert_to_decimal(data->temp1_input, + TEMP_INT_MASK, + TEMP_FR_LEN); + break; + case PSU_TEMP2_INPUT: + value = 1000 * convert_to_decimal(data->temp2_input, + TEMP_INT_MASK, + TEMP_FR_LEN); + break; + case PSU_TEMP3_INPUT: + value = 1000 * convert_to_decimal(data->temp3_input, + TEMP_INT_MASK, + TEMP_FR_LEN); + break; + case PSU_TEMP4_INPUT: + value = 1000 * convert_to_decimal(data->temp4_input, + TEMP_INT_MASK, + TEMP_FR_LEN); + break; + } + + return sprintf(buf, "%d\n", (int)value); +} + +static const struct attribute_group jnx_psu_group = { + .attrs = psu_attributes, +}; + +static int jnx_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + dev_dbg(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &jnx_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &jnx_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int jnx_psu_remove(struct i2c_client *client) +{ + struct psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &jnx_psu_group); + kfree(data); + + return 0; +} + +enum { + JPSU, +}; + +static const struct i2c_device_id psu_id[] = { + { "jpsu", JPSU }, + {} +}; +MODULE_DEVICE_TABLE(i2c, psu_id); + + +static struct i2c_driver jnx_psu_monitor_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "jnx-psu-monitor", + }, + .probe = jnx_psu_probe, + .remove = jnx_psu_remove, + .id_table = psu_id, + .address_list = normal_i2c, +}; + + +static int psu_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct psu_data *psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + struct reg_data_word regs_word[] = { + {0x00, &data->temp1_input}, + {0x01, &data->temp2_input}, + {0x02, &data->temp3_input}, + {0x03, &data->temp4_input}, + {0x28, &data->v_out}, + {0x32, &data->v_in}, + {0x33, &data->i_out}, + {0x3D, &data->i_in}, + {0x20, &data->fan1_input}, + {0x21, &data->fan2_input} + }; + + dev_dbg(dev, "Starting psu monitoring update\n"); + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = psu_read_word(client, regs_word[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + } + else { + u16 value = (u16)status; + (INVALID_READING != value) ? (*(regs_word[i].value) = status) : + (*(regs_word[i].value) = 0); + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(jnx_psu_monitor_driver); + +MODULE_AUTHOR("Ciju Rajan K "); +MODULE_DESCRIPTION("Juniper PSU monitoring driver for QFX5200"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-lpcm.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-lpcm.c new file mode 100644 index 000000000000..e305b1c3219c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-lpcm.c @@ -0,0 +1,118 @@ +/* + * Juniper Networks Re-Fpga lpc module + * + * Copyright (C) 2020 Juniper Networks + * Author: Ciju Rajan K + * + * This module implements: + * - Registering Reboot handler to reset cpu + * - Reset management port + * + * 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 + +#define REFPGA_LPC_BASE_ADDRESS 0xFED50000 +#define REFPGA_LPC_WINDOW_SIZE 0x00000400 + +#define REFPGA_MRE_LPCM_RST_CTL_REG (0x3) +#define REFPGA_MAJOR_VERSION (0x0) +#define REFPGA_MINOR_VERSION (0x1) + +#define REFPGA_CPU_RESET BIT(0) +#define REFPGA_MGMT1_PHY_RESET BIT(1) + +static void __iomem *fpga = NULL; + +static int qfx5200_cpu_reset(struct notifier_block *nb, + unsigned long action, + void *data) +{ + int ret = 0; + + switch (action) { + case SYS_POWER_OFF: + case SYS_HALT: + printk(KERN_CRIT "System halt/power_off\n"); + break; + case SYS_RESTART: + printk(KERN_CRIT "System restart: qfx5200_cpu_reset\n"); + iowrite8(REFPGA_CPU_RESET, (u8 *)fpga + REFPGA_MRE_LPCM_RST_CTL_REG); + msleep(100); + break; + default: + /* Do Nothing */ + break; + } + return NOTIFY_DONE; +} + +static struct notifier_block qfx5200_nb = { + .notifier_call = qfx5200_cpu_reset, +}; + +static int __init refpga_lpcm_init(void) +{ + u8 major_version = 0x00; + u8 minor_version = 0x00; + + if (!request_mem_region(REFPGA_LPC_BASE_ADDRESS, REFPGA_LPC_WINDOW_SIZE, "refpga-lpc")) { + printk(KERN_ERR "Cannot allocate Re-fpga memory region\n"); + return -ENODEV; + } + + if ((fpga = ioremap(REFPGA_LPC_BASE_ADDRESS, REFPGA_LPC_WINDOW_SIZE)) == NULL) { + release_mem_region(REFPGA_LPC_BASE_ADDRESS, REFPGA_LPC_WINDOW_SIZE); + printk(KERN_ERR "Re-Fpga address mapping failed\n"); + return -1; + } + + major_version = ioread8((u8 *)fpga + REFPGA_MAJOR_VERSION); + minor_version = ioread8((u8 *)fpga + REFPGA_MINOR_VERSION); + printk(KERN_INFO "Re-Fpga major version: %x minor version: %x\n", major_version, minor_version); + + /* + * Register the cpld soft reset handler + */ + if(register_reboot_notifier(&qfx5200_nb)) { + printk(KERN_ALERT "Restart handler registration failed\n"); + } + + iowrite8(REFPGA_MGMT1_PHY_RESET, (u8 *)fpga + REFPGA_MRE_LPCM_RST_CTL_REG); + + return 0; + +} + +static void __exit refpga_lpcm_exit(void) +{ + /* + * Unregister the fpga soft reset handler + */ + if (unregister_reboot_notifier(&qfx5200_nb)) { + printk(KERN_CRIT "Failed to uregister reboot notifier\n"); + return; + } + iounmap(fpga); + release_mem_region(REFPGA_LPC_BASE_ADDRESS, REFPGA_LPC_WINDOW_SIZE); + printk(KERN_INFO "Re-Fpga lpcm module removed\n"); +} + +module_init(refpga_lpcm_init); +module_exit(refpga_lpcm_exit); + +MODULE_DESCRIPTION("Juniper Networks RE-FPGA lpc module"); +MODULE_AUTHOR("Ciju Rajan K "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-tmc.c new file mode 120000 index 000000000000..355eda2afdf7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-tmc.c @@ -0,0 +1 @@ +../../common/modules/jnx-refpga-tmc.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-core.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-core.c new file mode 120000 index 000000000000..623e7a0188c6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-core.c @@ -0,0 +1 @@ +../../common/modules/jnx-tmc-core.c \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-psu.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-psu.c new file mode 100644 index 000000000000..86eeb6f88e45 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-psu.c @@ -0,0 +1,173 @@ +/* + * Juniper Networks TMC fpga PSU driver + * + * This driver is for detecting if the PSU is present or not + * + * Copyright (C) 2020 Juniper Networks + * Author: Ciju Rajan K + * + * 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 + +/* Max PSUs supported by this driver */ +#define NUM_PSU 2 + +struct tmc_psu_data { + int num_psu; + void __iomem *tmc_membase; +}; + +enum sysfs_psu_attributes { + PSU0_PRESENT, + PSU1_PRESENT, +}; + +static bool get_psu_presense(void *addr, u8 idx) +{ + bool ret = 0; + u32 value = ~(-1); + + value = ioread32(addr); + /* + * BIT(6) is for PSU 0 + * BIT(7) is for PSU 1 + * idx will be either 0 (PSU0) or 1 (PSU1) + */ + value &= BIT(idx+6); + + if (value) + ret = 1; + + return ret; +} + +/* + * Sysfs files are present in this path + * /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/psu-tmc.15/psu*_present + */ + +#define DECLARE_PSU_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(psu##index##_present, S_IRUGO, tmc_psu_presense_show, NULL, PSU##index##_PRESENT) +#define DECLARE_PSU_PRESENT_ATTR(index) &sensor_dev_attr_psu##index##_present.dev_attr.attr + +static ssize_t tmc_psu_presense_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr); + struct platform_device *pdev = to_platform_device(dev); + struct tmc_psu_data *psu = platform_get_drvdata(pdev); + + return sprintf(buf, "%d\n", get_psu_presense(psu->tmc_membase, s_attr->index)); + +} + +DECLARE_PSU_PRESENT_SENSOR_DEV_ATTR(0); +DECLARE_PSU_PRESENT_SENSOR_DEV_ATTR(1); + +static struct attribute *tmc_psu_attrs[] = { + DECLARE_PSU_PRESENT_ATTR(0), + DECLARE_PSU_PRESENT_ATTR(1), + NULL +}; + +static struct attribute_group tmc_psu_attr_group = { + .attrs = tmc_psu_attrs, +}; + +static int tmc_psu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tmc_psu_data *psu; + int ret; + struct resource *res; + void __iomem *addr; + + psu = devm_kzalloc(dev, sizeof(*psu), GFP_KERNEL); + if (!psu) { + dev_err(dev, "psu structure allocation failed\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "res allocation failed\n"); + return -ENODEV; + } + + addr = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (!addr) { + dev_err(dev, "ioremap failed\n"); + return -ENOMEM; + } + + psu->tmc_membase = addr; + psu->num_psu = NUM_PSU; + + platform_set_drvdata(pdev, psu); + + ret = sysfs_create_group(&dev->kobj, &tmc_psu_attr_group); + if (ret != 0) { + dev_err(dev, "jnx-tmc-psu: sysfs_create_group failed: %d\n", ret); + return ret; + } + + return 0; +} + +static int tmc_psu_remove(struct platform_device *pdev) +{ + struct tmc_psu_data *psu = platform_get_drvdata(pdev); + + if (psu) { + devm_kfree(&pdev->dev, psu); + } + sysfs_remove_group(&pdev->dev.kobj, &tmc_psu_attr_group); + + return 0; +} + +static struct platform_driver jnx_tmc_psu_driver = { + .driver = { + .name = "psu-tmc", + .owner = THIS_MODULE, + }, + .probe = tmc_psu_probe, + .remove = tmc_psu_remove, +}; + +static int __init jnx_tmc_psu_driver_init(void) +{ + int ret = -1; + + ret = platform_driver_register(&jnx_tmc_psu_driver); + + return ret; + +} + +static void __exit jnx_tmc_psu_driver_exit(void) +{ + platform_driver_unregister(&jnx_tmc_psu_driver); +} + +module_init(jnx_tmc_psu_driver_init); +module_exit(jnx_tmc_psu_driver_exit); + +MODULE_DESCRIPTION("Juniper Networks TMC PSU driver"); +MODULE_AUTHOR("Ciju Rajan K "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc.h b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc.h new file mode 120000 index 000000000000..bfacb7ae018d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc.h @@ -0,0 +1 @@ +../../common/modules/jnx-tmc.h \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/leds-jnx-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/leds-jnx-tmc.c new file mode 100644 index 000000000000..134faefd70a3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/leds-jnx-tmc.c @@ -0,0 +1,223 @@ +/* + * Juniper Networks TMC fpga LEDs driver + * + * Copyright (C) 2018 Juniper Networks + * Author: Ciju Rajan K + * + * This driver is based on I2CS fpga LEDs driver by Georgi Vlaev + * + * 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 + +/* Max LEDs supported by this driver (2bits of control per LED in 32bit reg) */ +#define NUM_LEDS 3 + +struct tmc_led { + struct led_classdev lc; + struct work_struct work; + int on; + int bit; + void __iomem *addr; +}; + +struct tmc_led_data { + int num_leds; + struct tmc_led *leds; +}; + +struct led_table +{ + const char *name; + int reg; +}; + +static struct led_table qfx5200_tmc_led_data[] = { + { + .name = "system", + .reg = 0, + }, + { + .name = "beacon", + .reg = 3, + }, + { + .name = "master", + .reg = 5, + } +}; + +static void jnx_tmc_leds_work(struct work_struct *work) +{ + struct tmc_led *led = container_of(work, struct tmc_led, work); + u32 value = ~(-1); + + value = ioread32(led->addr); + + if (led->on) { + if (!strncmp(led->lc.name, "beacon", 6)) { + value &= ~BIT(led->bit + 1); + value |= BIT(led->bit); + } else { + value |= BIT(led->bit) | BIT(led->bit + 1); + } + } else { + value &= ~(BIT(led->bit) | BIT(led->bit + 1)); + } + + iowrite32(value, led->addr); +} + +static void jnx_tmc_leds_brightness_set(struct led_classdev *lc, + enum led_brightness brightness) +{ + struct tmc_led *led = container_of(lc, struct tmc_led, lc); + + led->on = (brightness != LED_OFF); + schedule_work(&led->work); +} + +static int jnx_tmc_leds_init_one(struct device *dev, + struct tmc_led_data *ild, + int num, void __iomem *addr) +{ + struct tmc_led *led; + int ret; + + led = &ild->leds[num]; + + led->addr = addr; + + led->lc.name = qfx5200_tmc_led_data[num].name; + led->bit = qfx5200_tmc_led_data[num].reg; + led->lc.brightness_set = jnx_tmc_leds_brightness_set; + + + ret = devm_led_classdev_register(dev, &led->lc); + if (ret) + return ret; + + INIT_WORK(&led->work, jnx_tmc_leds_work); + + return 0; +} + +static int jnx_tmc_leds_init(struct device *dev, struct tmc_led_data *ild, + struct resource *res) +{ + int ret, idx = 0; + void __iomem *addr; + + if (!dev->parent) { + dev_err(dev, "dev->parent is null\n"); + return -ENODEV; + } + + addr = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (!addr) { + dev_err(dev, "ioremap failed\n"); + return -ENOMEM; + } + + ild->num_leds = NUM_LEDS; + ild->leds = devm_kzalloc(dev, sizeof(struct tmc_led) * NUM_LEDS, + GFP_KERNEL); + if (!ild->leds) { + dev_err(dev, "LED allocation failed\n"); + return -ENOMEM; + } + + for (idx=0; idxdev; + struct tmc_led_data *ild; + int ret; + struct resource *res; + + ild = devm_kzalloc(dev, sizeof(*ild), GFP_KERNEL); + if (!ild) { + dev_err(dev, "ild allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(pdev, ild); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "res allocation failed\n"); + return -ENODEV; + } + + ret = jnx_tmc_leds_init(dev, ild, res); + if (ret < 0) + return ret; + + return 0; +} + +static int tmc_leds_remove(struct platform_device *pdev) +{ + struct tmc_led_data *ild = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < ild->num_leds; i++) { + devm_led_classdev_unregister(&pdev->dev, &ild->leds[i].lc); + cancel_work_sync(&ild->leds[i].work); + } + + if (ild) { + if (ild->leds) + devm_kfree(&pdev->dev, ild->leds); + devm_kfree(&pdev->dev, ild); + } + + return 0; +} + +static struct platform_driver jnx_tmc_leds_driver = { + .driver = { + .name = "leds-tmc", + .owner = THIS_MODULE, + }, + .probe = tmc_leds_probe, + .remove = tmc_leds_remove, +}; + +static int __init jnx_tmc_leds_driver_init(void) +{ + int ret = -1; + + ret = platform_driver_register(&jnx_tmc_leds_driver); + + return ret; + +} + +static void __exit jnx_tmc_leds_driver_exit(void) +{ + platform_driver_unregister(&jnx_tmc_leds_driver); +} + +module_init(jnx_tmc_leds_driver_init); +module_exit(jnx_tmc_leds_driver_exit); + +MODULE_DESCRIPTION("Juniper Networks TMC leds driver"); +MODULE_AUTHOR("Ciju Rajan K "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/service/qfx5200-platform-init.service b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/service/qfx5200-platform-init.service new file mode 100644 index 000000000000..550a9eda3464 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/service/qfx5200-platform-init.service @@ -0,0 +1,15 @@ +[Unit] +Description=Juniper QFX5200 initialization service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/juniper_qfx5200_util.py install +ExecStart=/usr/local/bin/juniper_qfx5200_monitor.py +RemainAfterExit=yes +StandardOutput=syslog+console +StandardError=syslog+console + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/README b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/README new file mode 100755 index 000000000000..558410def831 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/README @@ -0,0 +1,152 @@ + +Copyright (c) 2020, Juniper Networks, Inc. +All rights reserved. + +Front panel LEDs +================ +There are 4 system LEDs in the front panel. Master, System, Alarm, & Beacon. +LED controls can be found under /sys/class/leds. The sysfs interface & +colour mappings are as follows: + +For master LED: /sys/class/leds/master/brightness + 0 => off + 1 => green + +For system LED: /sys/class/leds/system/brightness + 0 => off + 1 => green + +For alarm LED: /sys/class/leds/alarm/brightness + 0 => off + 1 => amber + 2 => red + +For beacon LED: /sys/class/leds/beacon/brightness + 0 => off + 1 => blue + +For any of the above LEDs, max_brightness file can tell the maximum value +accepted. + +System FANs +=========== +There are 5 fans and each of the fan has 2 fan modules. Overall there are +10 fans in the system. These fans are controlled by ADT7470 driver. + +Fan controls can be found in + /sys/bus/i2c/devices/7-002c + /sys/bus/i2c/devices/7-002e + /sys/bus/i2c/devices/7-002f + +For example, the complete path to driver control files will be + /sys/bus/i2c/devices/7-002c/hwmon/hwmon12 + +Fan duty cycle can be controlled through 'pwm1', 'pwm2', 'pwm3', 'pwm4' sysfs files. + +For example, these are the absolute paths to the control files + + /sys/bus/i2c/devices/7-002c/hwmon/hwmon*/pwm1 7-002c controls 2 fan modules + /sys/bus/i2c/devices/7-002c/hwmon/hwmon*/pwm2 + /sys/bus/i2c/devices/7-002c/hwmon/hwmon*/pwm3 + /sys/bus/i2c/devices/7-002c/hwmon/hwmon*/pwm4 + + /sys/bus/i2c/devices/7-002e/hwmon/hwmon*/pwm1 7-002e controls 2 fan modules + /sys/bus/i2c/devices/7-002e/hwmon/hwmon*/pwm2 + /sys/bus/i2c/devices/7-002e/hwmon/hwmon*/pwm3 + /sys/bus/i2c/devices/7-002e/hwmon/hwmon*/pwm4 + + /sys/bus/i2c/devices/7-002f/hwmon/hwmon*/pwm1 7-002c controls only 1 fan module + /sys/bus/i2c/devices/7-002f/hwmon/hwmon*/pwm2 + +For convenience, it will be represented as +/sys/bus/i2c/devices/7-002[c/e/f]/hwmon/hwmon*/pwm[1-4] + +Fan speed is given by +/sys/bus/i2c/devices/7-002[c/e/f]/hwmon/hwmon*/fan[1-4]_input + +Fan module presence is given by +/sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan[0-4]_present +file. A value of '1' indicate that fan is present & a value of '0' otherwise. + +Fan rotation direction is given by +/sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan[0-4]_type +A value of '1' indicate the direction is AFO (Front to back airflow) or Airflow +out. A value of '0' indicate that direction is AFI (Back to front airflow) or +Airflow in. + + +Temperature sensors +=================== +There are 10 temperature sensors. Kernel driver tmp401 is used for +reading temeperature sensors. + +The readings are available in + +/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input +/sys/bus/i2c/devices/5-0049/hwmon/hwmon*/temp1_input +/sys/bus/i2c/devices/5-004a/hwmon/hwmon*/temp1_input +/sys/bus/i2c/devices/5-004b/hwmon/hwmon*/temp1_input + +/sys/bus/i2c/devices/6-0048/hwmon/hwmon*/temp1_input +/sys/bus/i2c/devices/6-0049/hwmon/hwmon*/temp1_input +/sys/bus/i2c/devices/6-004a/hwmon/hwmon*/temp1_input +/sys/bus/i2c/devices/6-004b/hwmon/hwmon*/temp1_input + +/sys/bus/i2c/devices/7-0048/hwmon/hwmon*/temp1_input +/sys/bus/i2c/devices/7-0049/hwmon/hwmon*/temp1_input + +System PSUs +=========== +There are two independent PSUs. These are controlled by TMC fpga. + +PSU presence is given by jnx-tmc-psu dirver and is available at +/sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/psu-tmc.15/psu*_present +A value of '1' indicate PSU is present and a value of '0' otherwise. + +PSU monitoring data is provided by jnx-psu-monitor driver and is available at +/sys/bus/i2c/devices/3-0058 +/sys/bus/i2c/devices/4-0058 + +SFPs +==== +There are 32 QSFP+ modules supported in qfx5200 platform. EEPORMs will be +mapped under /sys/bus/i2c/devices/[14-45]-0050/ sysfs directory. + +FEC should be turned on for 100G SR4 & PSM4 optics and should +be turned off for 100G LR4 optics. If the FEC mode is not set +as per the optic type the port may not link up or work properly. +In some cases while interoperating between other NOSs & traffic +generators, FEC need to be enabled even for 100G DAC cables. + +As an example, see this configuration for FEC for 100G SR4 optics in +/etc/sonic/config_db.json + +"Ethernet4": { + "admin_status": "up", + "alias": "Ethernet4", + "fec": "rs", + "index": "1", + "lanes": "65,66,67,68", + "mtu": "9100", + "speed": "100000" + } + +Sensor details +============== +LM75 supported sensor modules will be available under 'sensors' command. + +Platform reboot +================= +Platform reboot sequences are in place for system reboot. The following +messages are displayed in the console when the system is rebooted: + + [ 6053.163363] System restart: qfx5200_cpu_reset + +Platform monitoring daemon +========================== +“juniper_qfx5200_monitor.py” is the platform monitoring script. +It implements the qfx5200 EM policy. This script will run as system service +and monitor the temperature sensors in every 20 seconds. Based on the EM +policy thresholds, it controls the fan rpm, manage alarm leds, and +shutdown the box in case of any over heating. + diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/juniper_qfx5200_monitor.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/juniper_qfx5200_monitor.py new file mode 100755 index 000000000000..dc47f1049322 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/juniper_qfx5200_monitor.py @@ -0,0 +1,913 @@ +#!/usr/bin/env python +# +# Name: juniper_qfx5200_monitor.py version: 1.0 +# +# Description: This file contains the EM implementation for QFX5200 platform +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. + +try: + import os + import commands + import subprocess + import logging + import logging.config + import logging.handlers + import time + import glob + import re +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/var/log/juniper_qfx5200_monitor' +verbose = False +DEBUG = False + +log_file = '%s.log' % FUNCTION_NAME +log_level = logging.DEBUG + + +isPlatformAFI = False +PrevASICValue = 0 + +temp_policy_AFI = { + 0: [[35, 0, 30000], [35, 30000, 39000], [55, 39000, 0], [55, 39000, 48000], [75, 48000, 0], [75, 48000, 56000], [90, 56000, 0], [90, 56000, 66000],[100, 66000, 0], + ['Yellow Alarm', 64000, 70000], ['Red Alarm', 70000, 73000], ['Fire Shut Alarm', 73000, 0]], + + 1: [[35, 0, 30000], [35, 30000, 39000], [55, 39000, 0], [55, 39000, 48000], [75, 48000, 0], [75, 48000, 56000], [90, 56000, 0], [90, 56000, 66000],[100, 66000, 0], + ['Yellow Alarm', 64000, 70000], ['Red Alarm', 70000, 73000], ['Fire Shut Alarm', 73000, 0]], + + 2: [[35, 0, 40000], [35, 40000, 47000], [55, 47000, 0], [55, 47000, 55000], [75, 55000, 0], [75, 55000, 62000], [90, 62000, 0], [90, 62000, 70000],[100, 70000, 0], + ['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]], + + 3: [[35, 0, 36000], [35, 36000, 44000], [55, 44000, 0], [55, 44000, 52000], [75, 52000, 0], [75, 52000, 60000], [90, 60000, 0], [90, 60000, 69000],[100, 69000, 0], + ['Yellow Alarm', 67000, 73000], ['Red Alarm', 73000, 76000], ['Fire Shut Alarm', 76000, 0]], + + 4: [[35, 0, 52000], [35, 52000, 57000], [55, 57000, 0], [55, 57000, 63000], [75, 63000, 0], [75, 63000, 68000], [90, 68000, 0], [90, 68000, 74000],[100, 74000, 0], + ['Yellow Alarm', 72000, 78000], ['Red Alarm', 78000, 81000], ['Fire Shut Alarm', 81000, 0]], + + 5: [[35, 0, 37000], [35, 37000, 45000], [55, 45000, 0], [55, 45000, 53000], [75, 53000, 0], [75, 53000, 61000], [90, 61000, 0], [90, 61000, 70000],[100, 70000, 0], + ['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]], + + 6: [[35, 0, 37000], [35, 37000, 45000], [55, 45000, 0], [55, 45000, 53000], [75, 53000, 0], [75, 53000, 60000], [90, 60000, 0], [90, 60000, 69000],[100, 69000, 0], + ['Yellow Alarm', 67000, 73000], ['Red Alarm', 73000, 76000], ['Fire Shut Alarm', 76000, 0]], + + 7: [[35, 0, 52000], [35, 52000, 57000], [55, 57000, 0], [55, 57000, 63000], [75, 63000, 0], [75, 63000, 68000], [90, 68000, 0], [90, 68000, 74000],[100, 74000, 0], + ['Yellow Alarm', 72000, 78000], ['Red Alarm', 78000, 81000], ['Fire Shut Alarm', 81000, 0]], + + 8: [[35, 0, 41000], [35, 41000, 48000], [55, 48000, 0], [55, 48000, 55000], [75, 55000, 0], [75, 55000, 62000], [90, 62000, 0], [90, 62000, 70000],[100, 70000, 0], + ['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]], + + 9: [[35, 0, 42000], [35, 42000, 49000], [55, 49000, 0], [55, 49000, 57000], [75, 57000, 0], [75, 57000, 64000], [90, 64000, 0], [90, 64000, 72000],[100, 72000, 0], + ['Yellow Alarm', 70000, 76000], ['Red Alarm', 76000, 79000], ['Fire Shut Alarm', 79000, 0]], + + 10: [[35, 0, 42000], [35, 42000, 50000], [55, 50000, 0], [55, 50000, 58000], [75, 58000, 0], [75, 58000, 66000], [90, 66000, 0], [90, 66000, 75000],[100, 75000, 0], + ['Yellow Alarm', 86000, 92000], ['Red Alarm', 92000, 95000], ['Fire Shut Alarm', 95000, 0]], + + 11: [[35, 0, 68000], [35, 68000, 74000], [55, 74000, 0], [55, 74000, 80000], [75, 80000, 0], [75, 80000, 85000], [90, 85000, 0], [90, 85000, 92000],[100, 92000, 0], + ['Yellow Alarm', 99000, 102000], ['Red Alarm', 102000, 105000], ['Fire Shut Alarm', 105000, 0]], + } + +temp_policy_AFO = { + 0: [[35, 0, 42000], [35, 42000, 49000], [55, 49000, 0], [55, 49000, 55000], [75, 55000, 0], [75, 55000, 62000], [90, 62000, 0], [90, 62000, 69000],[100, 69000, 0], + ['Yellow Alarm', 67000, 73000], ['Red Alarm', 73000, 76000], ['Fire Shut Alarm', 76000, 0]], + + 1: [[35, 0, 41000], [35, 41000, 48000], [55, 48000, 0], [55, 48000, 55000], [75, 55000, 0], [75, 55000, 61000], [90, 61000, 0], [90, 61000, 69000],[100, 69000, 0], + ['Yellow Alarm', 67000, 73000], ['Red Alarm', 73000, 76000], ['Fire Shut Alarm', 76000, 0]], + + 2: [[35, 0, 44000], [35, 44000, 50000], [55, 50000, 0], [55, 50000, 56000], [75, 56000, 0], [75, 56000, 63000], [90, 63000, 0], [90, 63000, 70000],[100, 70000, 0], + ['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]], + + 3: [[35, 0, 36000], [35, 36000, 43000], [55, 43000, 0], [55, 43000, 50000], [75, 50000, 0], [75, 50000, 57000], [90, 57000, 0], [90, 57000, 65000],[100, 65000, 0], + ['Yellow Alarm', 63000, 69000], ['Red Alarm', 69000, 72000], ['Fire Shut Alarm', 72000, 0]], + + 4: [[35, 0, 49000], [35, 49000, 54000], [55, 54000, 0], [55, 54000, 60000], [75, 60000, 0], [75, 60000, 65000], [90, 65000, 0], [90, 65000, 71000],[100, 71000, 0], + ['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]], + + 5: [[35, 0, 46000], [35, 46000, 52000], [55, 52000, 0], [55, 52000, 58000], [75, 58000, 0], [75, 58000, 63000], [90, 63000, 0], [90, 63000, 70000],[100, 70000, 0], + ['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]], + + 6: [[35, 0, 50000], [35, 50000, 55000], [55, 55000, 0], [55, 55000, 60000], [75, 60000, 0], [75, 60000, 65000], [90, 65000, 0], [90, 65000, 71000],[100, 71000, 0], + ['Yellow Alarm', 65000, 71000], ['Red Alarm', 71000, 78000], ['Fire Shut Alarm', 78000, 0]], + + 7: [[35, 0, 49000], [35, 49000, 55000], [55, 55000, 0], [55, 55000, 60000], [75, 60000, 0], [75, 60000, 66000], [90, 66000, 0], [90, 66000, 72000],[100, 72000, 0], + ['Yellow Alarm', 70000, 76000], ['Red Alarm', 76000, 79000], ['Fire Shut Alarm', 79000, 0]], + + 8: [[35, 0, 41000], [35, 41000, 47000], [55, 47000, 0], [55, 47000, 54000], [75, 54000, 0], [75, 54000, 60000], [90, 60000, 0], [90, 60000, 67000],[100, 67000, 0], + ['Yellow Alarm', 65000, 71000], ['Red Alarm', 71000, 74000], ['Fire Shut Alarm', 74000, 0]], + + 9: [[35, 0, 57000], [35, 57000, 61000], [55, 61000, 0], [55, 61000, 66000], [75, 66000, 0], [75, 66000, 70000], [90, 70000, 0], [90, 70000, 75000],[100, 75000, 0], + ['Yellow Alarm', 73000, 79000], ['Red Alarm', 79000, 82000], ['Fire Shut Alarm', 82000, 0]], + + 10: [[35, 0, 51000], [35, 51000, 58000], [55, 58000, 0], [55, 58000, 64000], [75, 64000, 0], [75, 64000, 70000], [90, 70000, 0], [90, 70000, 78000],[100, 78000, 0], + ['Yellow Alarm', 86000, 92000], ['Red Alarm', 92000, 95000], ['Fire Shut Alarm', 95000, 0]], + + 11: [[35, 0, 76000], [35, 76000, 79000], [55, 79000, 0], [55, 79000, 83000], [75, 83000, 0], [75, 83000, 86000], [90, 86000, 0], [90, 86000, 90000],[100, 90000, 0], + ['Yellow Alarm', 99000, 102000], ['Red Alarm', 102000, 105000], ['Fire Shut Alarm', 105000, 0]], + } + +class QFX5200_FanUtil(object): + """QFX5200 Platform FanUtil class""" + + PWMINPUT_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/{1}/pwm{2}' + HWMONINPUT_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/' + PWMINPUT_NUM_IDX = 0 + PWMINPUT_NUM = 10 + _pwm_input_path_mapping = {} + _hwmon_input_path_mapping = {} + + # PWM NUMBERS + _pwm_input_node_mapping = ['1','2','3','4','1','2','3','4','1','2'] + + # I2C NUMBERS + _hwmon_input_node_mapping = ['2c','2c','2c','2c','2e','2e','2e','2e','2f','2f'] + def __init__(self): + hwmoninput_path = self.HWMONINPUT_PATH + pwminput_path = self.PWMINPUT_PATH + for x in range(self.PWMINPUT_NUM): + self._hwmon_input_path_mapping[x] = hwmoninput_path.format( + self._hwmon_input_node_mapping[x]) + + hwmon_path = os.listdir(self._hwmon_input_path_mapping[x]) + hwmon_dir = '' + for hwmon_name in hwmon_path: + hwmon_dir = hwmon_name + + self._pwm_input_path_mapping[x] = pwminput_path.format( + self._hwmon_input_node_mapping[x], + hwmon_dir, + self._pwm_input_node_mapping[x]) + def get_fan_dutycycle(self): + fan_speed = {86: 35, 139: 55, 192: 75, 230: 90,255: 100} + ret_value = 0 + for x in range(self.PWMINPUT_NUM): + pwm_value = 0 + pwm_value1 = 0 + device_path = self._pwm_input_path_mapping[x] + cmd = ("sudo cat %s" %(device_path)) + status, pwm_value = commands.getstatusoutput(cmd) + pwm_value1 = int(pwm_value) + time.sleep(0.25) + if int(pwm_value1) > 0: + ret_value = fan_speed.get(int(pwm_value)) + break + + return int(ret_value) + + def set_fan_dutycycle(self, val): + fan_speed = {35: 86, 55: 139, 75: 192, 90: 230,100: 255} + for x in range(self.PWMINPUT_NUM): + device_path = self._pwm_input_path_mapping[x] + pwm_value = fan_speed.get(val) + pwm_value1 = str(pwm_value) + cmd = ("sudo echo %s > %s" %(pwm_value1,device_path)) + os.system(cmd) + time.sleep(0.25) + logging.debug('Setting PWM value: %s to all fans', pwm_value1) + return True + + def get_check_fan_dutycycle(self): + pwm_str = '' + for x in range(self.PWMINPUT_NUM): + device_path = self._pwm_input_path_mapping[x] + cmd = ("sudo cat %s" %(device_path)) + status, pwm_value = commands.getstatusoutput(cmd) + pwm_str += pwm_value + if (x != self.PWMINPUT_NUM -1): + pwm_str += ', ' + time.sleep(0.25) + logging.debug('Current PWM values set in all fans: %s', pwm_str) + + +class QFX5200_ThermalUtil(object): + """QFX5200 Platform ThermalUtil class""" + + SENSOR_NUM_ON_MAIN_BOARD = 10 + CORETEMP_INDEX_ON_MAIN_BOARD = 10 + SENSOR_CORETEMP_NUM_ON_MAIN_BOARD = 12 + CORETEMP_NUM_ON_MAIN_BOARD = 5 + THERMAL_NUM_RANGE = 10 + SENSOR_NUM_0_IDX = 0 + SENSORS_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + CORETEMP_PATH = '/sys/bus/platform/devices/coretemp.0/hwmon/hwmon*/temp{0}_input' + MAJORALARM_LED_PATH = '/sys/class/leds/alarm-major/brightness' + MINORALARM_LED_PATH = '/sys/class/leds/alarm-minor/brightness' + MONITORLOG_PATH = '/var/log/juniper_qfx5200_monitor.log' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _sensor_to_device_path_mapping = {} + + _sensor_to_device_node_mapping = [ + ['7', '48'], + ['7', '49'], + ['5', '48'], + ['5', '49'], + ['5', '4a'], + ['5', '4b'], + ['6', '48'], + ['6', '49'], + ['6', '4a'], + ['6', '4b'], + ] + + _coretemp_to_device_path_mapping = {} + + _coretemp_to_device_node_mapping = [1, 2, 3, 4, 5] + + def __init__(self): + sensor_path = self.SENSORS_PATH + coretemp_path = self.CORETEMP_PATH + for x in range(self.SENSOR_NUM_ON_MAIN_BOARD): + self._sensor_to_device_path_mapping[x] = sensor_path.format( + self._sensor_to_device_node_mapping[x][0], + self._sensor_to_device_node_mapping[x][1]) + + for x in range(self.CORETEMP_NUM_ON_MAIN_BOARD): + self._coretemp_to_device_path_mapping[x] = coretemp_path.format( + self._coretemp_to_device_node_mapping[x]) + + + """ Function reads the 5 temp inputs in CORETEMP_PATH + and returns the average of these 5 temp readings """ + def get_coretempValue(self): + sum = 0 + for x in range(self.CORETEMP_NUM_ON_MAIN_BOARD): + sum += self._get_coretemp_node_val(x) + avg = sum/self.CORETEMP_NUM_ON_MAIN_BOARD + return int(avg) + + + """ Function takes the Sensor number as input, constructs the device path, + opens sensor file, reads the temp content from the file and returns the value """ + def _get_sensor_node_val(self, thermal_num): + if thermal_num < self.SENSOR_NUM_0_IDX or thermal_num >= self.SENSOR_NUM_ON_MAIN_BOARD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('get_sensor_node_val: unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('get_sensor_node_val: content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except IOError as e: + logging.error('get_sensor_node_val: unable to close file. device_path:%s', str(e)) + return None + + return int(content) + + + """ Function takes the coretemp number as input, constructs the device path, + opens sensor file, reads the temp content from the file and returns the value """ + def _get_coretemp_node_val(self, thermal_num): + + device_path = self.get_coretemp_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('get_coretemp_node_val: unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('get_coretemp_node_val: content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except IOError as e: + logging.error('_get_coretemp_node_val: unable to close file. device_path:%s', str(e)) + return None + + return int(content) + + + def get_thermal_to_device_path(self, thermal_num): + return self._sensor_to_device_path_mapping[thermal_num] + + + def get_coretemp_to_device_path(self, thermal_num): + return self._coretemp_to_device_path_mapping[thermal_num] + + + def get_alarm_led_brightness(self): + try: + val_file = open(self.MAJORALARM_LED_PATH) + except IOError as e: + logging.error('get_alarm_led_brightness: unable to open file: %s', str(e)) + return False + majoralarm_value = val_file.readline().rstrip() + val_file.close() + + try: + val_file = open(self.MINORALARM_LED_PATH) + except IOError as e: + logging.error('get_alarm_led_brightness: unable to open file: %s', str(e)) + return False + minoralarm_value = val_file.readline().rstrip() + val_file.close() + + if (majoralarm_value == str(1)) and (minoralarm_value == str(0)): + content = 2 + elif (majoralarm_value == str(0)) and (minoralarm_value == str(1)): + content = 1 + elif (majoralarm_value == str(0)) and (minoralarm_value == str(0)): + content = 0 + else: + pass + + return int(content) + + def set_alarm_led_brightness(self, val): + + """ Major Alarm set""" + if val == 2: + major_alarm_val = 1 + minor_alarm_val = 0 + + try: + val_file = open(self.MAJORALARM_LED_PATH, 'r+') + except IOError as e: + logging.error('set_alarm_led_brightness: unable to open file: %s', str(e)) + return False + + val_file.write(str(major_alarm_val)) + val_file.close() + + try: + val_file = open(self.MINORALARM_LED_PATH, 'r+') + except IOError as e: + logging.error('set_alarm_led_brightness: unable to open file: %s', str(e)) + return False + + val_file.write(str(minor_alarm_val)) + val_file.close() + + elif val == 1: + major_alarm_val = 0 + minor_alarm_val = 1 + + try: + val_file = open(self.MAJORALARM_LED_PATH, 'r+') + except IOError as e: + logging.error('set_alarm_led_brightness: unable to open file: %s', str(e)) + return False + + val_file.write(str(major_alarm_val)) + val_file.close() + + try: + val_file = open(self.MINORALARM_LED_PATH, 'r+') + except IOError as e: + logging.error('set_alarm_led_brightness: unable to open file: %s', str(e)) + return False + val_file.write(str(minor_alarm_val)) + val_file.close() + + else: + major_alarm_val = 0 + minor_alarm_val = 0 + + try: + val_file = open(self.MAJORALARM_LED_PATH, 'r+') + except IOError as e: + logging.error('set_alarm_led_brightness: unable to open file: %s', str(e)) + return False + + val_file.write(str(major_alarm_val)) + val_file.close() + + try: + val_file = open(self.MINORALARM_LED_PATH, 'r+') + except IOError as e: + logging.error('set_alarm_led_brightness: unable to open file: %s', str(e)) + return False + val_file.write(str(minor_alarm_val)) + val_file.close() + + """ Function is called periodically every 20 secs. It reads the 10 Temp sensors, 1 core Temp sensor and ASIC temp sets + Sensor flags accordingly. Also reads the Fan duty cycle and depending on the FAN duty cycle reading and temp sensor reading, + set the different parameters + + Below is the Sensor Mapping(Refer AFI/AFO EM Policy Specification) to the I2C devices + + /sys/bus/i2c/devices/7-0048/hwmon/hwmon* --> Sensor# 2 + /sys/bus/i2c/devices/7-0049/hwmon/hwmon* --> Sensor# 3 + /sys/bus/i2c/devices/5-0048/hwmon/hwmon* --> Sensor# 5 + /sys/bus/i2c/devices/5-0049/hwmon/hwmon* --> Sensor# 6 + /sys/bus/i2c/devices/5-004a/hwmon/hwmon* --> Sensor# 7 + /sys/bus/i2c/devices/5-004b/hwmon/hwmon* --> Sensor# 8 + /sys/bus/i2c/devices/6-0048/hwmon/hwmon* --> Sensor# 9 + /sys/bus/i2c/devices/6-0049/hwmon/hwmon* --> Sensor# 10 + /sys/bus/i2c/devices/6-004a/hwmon/hwmon* --> Sensor# 11 + /sys/bus/i2c/devices/6-004b/hwmon/hwmon* --> Sensor# 12 + """ + + def getSensorTemp(self): + global isPlatformAFI + global PrevASICValue + + sensor_str = '' + + #AFI + if (isPlatformAFI == True): + temp_policy = temp_policy_AFI + else: + #AFO + temp_policy = temp_policy_AFO + + """ Dictionary where + key = thermal id index starting from 0. 0 is the sensor 1 ... + value = Different temp ranges """ + SensorFlag = { + 0: [0,0,0,0,0,0,0,0,0,0,0,0], + 1: [0,0,0,0,0,0,0,0,0,0,0,0], + 2: [0,0,0,0,0,0,0,0,0,0,0,0], + 3: [0,0,0,0,0,0,0,0,0,0,0,0], + 4: [0,0,0,0,0,0,0,0,0,0,0,0], + 5: [0,0,0,0,0,0,0,0,0,0,0,0], + 6: [0,0,0,0,0,0,0,0,0,0,0,0], + 7: [0,0,0,0,0,0,0,0,0,0,0,0], + 8: [0,0,0,0,0,0,0,0,0,0,0,0], + 9: [0,0,0,0,0,0,0,0,0,0,0,0], + 10: [0,0,0,0,0,0,0,0,0,0,0,0], + 11: [0,0,0,0,0,0,0,0,0,0,0,0], + } + + for x in range(self.SENSOR_CORETEMP_NUM_ON_MAIN_BOARD): + SEN_str = 'SEN' + + if x < self.SENSOR_NUM_ON_MAIN_BOARD: + value = self._get_sensor_node_val(x) + if ( x < 2): + SEN_str += `x + 2` + else: + SEN_str += `x + 3` + + sensor_str += SEN_str + ':' + str(value) + ', ' + + elif x == self.CORETEMP_INDEX_ON_MAIN_BOARD: + value = self.get_coretempValue() + sensor_str += 'CPU:' + str(value) + ', ' + + else: + proc = subprocess.Popen("bcmcmd \"show temp\" | grep \"maximum peak temperature\" | awk '{ print $5 }' > /var/log/asic_value 2>&1 & ",shell=True) + time.sleep(2) + cmd = "kill -9 %s"%(proc.pid) + commands.getstatusoutput(cmd) + + if os.stat("/var/log/asic_value").st_size == 0: + value = PrevASICValue + else: + with open('/var/log/asic_value', 'r') as f: + value1 = f.readline() + value2 = float(value1) + value1 = value2 * 1000 + value = int(value1) + PrevASICValue = value + + sensor_str += 'BRCM TH:' + str(value) + + # 35% Duty Cycle + if value > temp_policy[x][0][1] and value <= temp_policy[x][0][2]: + SensorFlag[x][0] = True + + # 35% Prev Duty Cycle + elif value > temp_policy[x][1][1] and value < temp_policy[x][1][2]: + SensorFlag[x][1] = True + + # 55% Duty Cycle + elif value == temp_policy[x][2][1]: + SensorFlag[x][2] = True + + # 55% Prev Duty Cycle + elif value > temp_policy[x][3][1] and value < temp_policy[x][3][2]: + SensorFlag[x][3] = True + + # 75% Duty Cycle + elif value == temp_policy[x][4][1]: + SensorFlag[x][4] = True + + # 75% Prev Duty Cycle + elif value > temp_policy[x][5][1] and value < temp_policy[x][5][2]: + SensorFlag[x][5] = True + + # 90% Duty Cycle + elif value == temp_policy[x][6][1]: + SensorFlag[x][6] = True + + # 90% Prev Duty Cycle + elif value > temp_policy[x][7][1] and value < temp_policy[x][7][2]: + SensorFlag[x][7] = True + + #100% Duty Cycle + elif value >= temp_policy[x][8][1]: + SensorFlag[x][8] = True + + else: + pass + + # Yellow Alarm + if value >= temp_policy[x][9][1] and value < temp_policy[x][9][2]: + SensorFlag[x][9] = True + + # Red Alarm + elif value >= temp_policy[x][10][1] and value < temp_policy[x][10][2]: + SensorFlag[x][10] = True + + # Fire Shut down + elif value >= temp_policy[x][11][1]: + SensorFlag[x][11] = True + + logging.debug('Sensor values : %s', sensor_str) + fan = QFX5200_FanUtil() + # CHECK IF ANY TEMPERATURE SENSORS is running at Soft shutdown temperature + if (SensorFlag[0][11] or SensorFlag[1][11] or SensorFlag[2][11] or SensorFlag[3][11] or SensorFlag[4][11] or SensorFlag[5][11] or SensorFlag[6][11] or SensorFlag[7][11] + or SensorFlag[8][11] or SensorFlag[9][11] or SensorFlag[10][11] or SensorFlag[11][11]): + + logging.debug('Fire Threshold reached: System is going to shutdown now') + os.system("echo 'CRITICAL: Fire Threshold reached: System is going to shutdown now' > /dev/console") + + + logging.debug('Executing poweroff command') + + time.sleep(1) + + try: + monitorlog_file = open(self.MONITORLOG_PATH) + except IOError as e: + logging.error('get_Sensor_temp: unable to open file: %s', str(e)) + return False + + monitorlog_file.close() + + cmd = "poweroff" + os.system(cmd) + + # CHECK IF ANY TEMPERATURE SENSORS is running at RED warning , IF YES, SET THE ALARM LED TO 'RED' + elif (SensorFlag[0][10] or SensorFlag[1][10] or SensorFlag[2][10] or SensorFlag[3][10] or SensorFlag[4][10] or SensorFlag[5][10] or SensorFlag[6][10] or SensorFlag[7][10] + or SensorFlag[8][10] or SensorFlag[9][10] or SensorFlag[10][10] or SensorFlag[11][10]): + + self.set_alarm_led_brightness(2) + + logging.debug('Setting Red Alarm') + + # CHECK IF ANY TEMPERATURE SENSORS is running at Yellow warning, IF YES, SET THE ALARM LED TO 'YELLOW' + elif (SensorFlag[0][9] or SensorFlag[1][9] or SensorFlag[2][9] or SensorFlag[3][9] or SensorFlag[4][9] or SensorFlag[5][9] or SensorFlag[6][9] or SensorFlag[7][9] + or SensorFlag[8][9] or SensorFlag[9][9] or SensorFlag[10][9] or SensorFlag[11][9]): + + self.set_alarm_led_brightness(1) + + logging.debug('Setting Yellow Alarm') + + else: + value = self.get_alarm_led_brightness() + if ( value == 2): + logging.debug('Clearing Red Alarm') + elif ( value == 1): + logging.debug('Clearing Yellow Alarm') + + self.set_alarm_led_brightness(0) + + #CHECK IF ANY TEMPERATURE SENSORS HAS SET 100% DUTY CYCLE FLAG + if (SensorFlag[0][8] or SensorFlag[1][8] or SensorFlag[2][8] or SensorFlag[3][8] or SensorFlag[4][8] or SensorFlag[5][8] or SensorFlag[6][8] or SensorFlag[7][8] + or SensorFlag[8][8] or SensorFlag[9][8] or SensorFlag[10][8] or SensorFlag[11][8]): + + fan.get_check_fan_dutycycle() + if (fan.get_fan_dutycycle() < 100): + time.sleep(0.50) + fan.set_fan_dutycycle(100) + + logging.debug('Fan set to 100% dutycycle') + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 90% PREV DUTY CYCLE FLAG + elif (SensorFlag[0][7] or SensorFlag[1][7] or SensorFlag[2][7] or SensorFlag[3][7] or SensorFlag[4][7] or SensorFlag[5][7] or SensorFlag[6][7] or SensorFlag[7][7] + or SensorFlag[8][7] or SensorFlag[9][7] or SensorFlag[10][7] or SensorFlag[11][7]): + + fan.get_check_fan_dutycycle() + + if (fan.get_fan_dutycycle() == 100): + logging.debug('Fan set to 100% dutycycle') + elif (fan.get_fan_dutycycle() != 90): + time.sleep(0.25) + fan.set_fan_dutycycle(90) + logging.debug('Fan set to 90% dutycycle') + else: + logging.debug('Fan set to 90% dutycycle') + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 90% DUTY CYCLE FLAG + elif (SensorFlag[0][6] or SensorFlag[1][6] or SensorFlag[2][6] or SensorFlag[3][6] or SensorFlag[4][6] or SensorFlag[5][6] or SensorFlag[6][6] or SensorFlag[7][6] + or SensorFlag[8][6] or SensorFlag[9][6] or SensorFlag[10][6] or SensorFlag[11][6]): + + fan.get_check_fan_dutycycle() + + if (fan.get_fan_dutycycle() < 90): + time.sleep(0.25) + fan.set_fan_dutycycle(90) + logging.debug('Fan set to 90% dutycycle') + elif (fan.get_fan_dutycycle() == 90): + logging.debug('Fan set to 90% dutycycle') + else: + time.sleep(0.25) + fan.set_fan_dutycycle(90) + logging.debug('Fan set to 90% dutycycle') + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 75% PREV DUTY CYCLE FLAG + elif (SensorFlag[0][5] or SensorFlag[1][5] or SensorFlag[2][5] or SensorFlag[3][5] or SensorFlag[4][5] or SensorFlag[5][5] or SensorFlag[6][5] or SensorFlag[7][5] + or SensorFlag[8][5] or SensorFlag[9][5] or SensorFlag[10][5] or SensorFlag[11][5]): + + fan.get_check_fan_dutycycle() + + if (fan.get_fan_dutycycle() > 75): + if (fan.get_fan_dutycycle() == 100): + time.sleep(0.25) + fan.set_fan_dutycycle(90) + logging.debug('Fan set to 90% dutycycle') + else: + logging.debug('Fan set to 90% dutycycle') + elif (fan.get_fan_dutycycle() != 75): + time.sleep(0.25) + fan.set_fan_dutycycle(75) + logging.debug('Fan set to 75% dutycycle') + else: + logging.debug('Fan set to 75% dutycycle') + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 75% DUTY CYCLE FLAG + elif (SensorFlag[0][4] or SensorFlag[1][4] or SensorFlag[2][4] or SensorFlag[3][4] or SensorFlag[4][4] or SensorFlag[5][4] or SensorFlag[6][4] or SensorFlag[7][4] + or SensorFlag[8][4] or SensorFlag[9][4] or SensorFlag[10][4] or SensorFlag[11][4]): + + fan.get_check_fan_dutycycle() + if (fan.get_fan_dutycycle() < 75): + time.sleep(0.25) + fan.set_fan_dutycycle(75) + logging.debug('Fan set to 75% dutycycle') + + elif (fan.get_fan_dutycycle() == 75): + logging.debug('Fan set to 75% dutycycle') + + else: + time.sleep(0.25) + fan.set_fan_dutycycle(75) + logging.debug('Fan set to 75% dutycycle') + + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 55% DUTY CYCLE PREV FLAG + elif (SensorFlag[0][3] or SensorFlag[1][3] or SensorFlag[2][3] or SensorFlag[3][3] or SensorFlag[4][3] or SensorFlag[5][3] or SensorFlag[6][3] or SensorFlag[7][3] + or SensorFlag[8][3] or SensorFlag[9][3] or SensorFlag[10][3] or SensorFlag[11][3]): + + fan.get_check_fan_dutycycle() + + if (fan.get_fan_dutycycle() > 55): + if (fan.get_fan_dutycycle() == 100): + time.sleep(0.25) + fan.set_fan_dutycycle(90) + logging.debug('Fan set to 90% dutycycle') + elif (fan.get_fan_dutycycle() == 90): + time.sleep(0.25) + fan.set_fan_dutycycle(75) + logging.debug('Fan set to 75% dutycycle') + else: + logging.debug('Fan set to 75% dutycycle') + elif (fan.get_fan_dutycycle() != 55): + time.sleep(0.25) + fan.set_fan_dutycycle(55) + logging.debug('Fan set to 55% dutycycle') + else: + logging.debug('Fan set to 55% dutycycle') + + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 55% DUTY CYCLE FLAG + elif (SensorFlag[0][2] or SensorFlag[1][2] or SensorFlag[2][2] or SensorFlag[3][2] or SensorFlag[4][2] or SensorFlag[5][2] or SensorFlag[6][2] or SensorFlag[7][2] + or SensorFlag[8][2] or SensorFlag[9][2] or SensorFlag[10][2] or SensorFlag[11][2]): + + fan.get_check_fan_dutycycle() + + if (fan.get_fan_dutycycle() < 55): + time.sleep(0.25) + fan.set_fan_dutycycle(55) + logging.debug('Fan set to 55% dutycycle') + elif (fan.get_fan_dutycycle() == 55): + logging.debug('Fan set to 55% dutycycle') + else: + time.sleep(0.25) + fan.set_fan_dutycycle(55) + logging.debug('Fan set to 55% dutycycle') + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 35% PREV DUTY CYCLE FLAG + elif (SensorFlag[0][1] or SensorFlag[1][1] or SensorFlag[2][1] or SensorFlag[3][1] or SensorFlag[4][1] or SensorFlag[5][1] or SensorFlag[6][1] or SensorFlag[7][1] + or SensorFlag[8][1] or SensorFlag[9][1] or SensorFlag[10][1] or SensorFlag[11][1]): + + fan.get_check_fan_dutycycle() + + if (fan.get_fan_dutycycle() > 35): + if (fan.get_fan_dutycycle() == 100): + time.sleep(0.25) + fan.set_fan_dutycycle(90) + logging.debug('Fan set to 90% dutycycle') + elif (fan.get_fan_dutycycle() == 90): + time.sleep(0.25) + fan.set_fan_dutycycle(75) + logging.debug('Fan set to 75% dutycycle') + elif (fan.get_fan_dutycycle() == 75): + time.sleep(0.25) + fan.set_fan_dutycycle(55) + logging.debug('Fan set to 55% dutycycle') + else: + logging.debug('Fan set to 55% dutycycle') + elif (fan.get_fan_dutycycle() == 35): + logging.debug('Fan set to 35% dutycycle') + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 35% DUTY CYCLE FLAG + elif (SensorFlag[0][0] or SensorFlag[1][0] or SensorFlag[2][0] or SensorFlag[3][0] or SensorFlag[4][0] or SensorFlag[5][0] or SensorFlag[6][0] or SensorFlag[7][0] + or SensorFlag[8][0] or SensorFlag[9][0] or SensorFlag[10][0] or SensorFlag[11][0]): + + fan.get_check_fan_dutycycle() + + if (fan.get_fan_dutycycle() > 35): + time.sleep(0.25) + fan.set_fan_dutycycle(35) + + logging.debug('Fan set to 35% dutycycle') + + else: + pass + + + # RESET ALL THE SENSOR FLAGS + for x in range(self.SENSOR_CORETEMP_NUM_ON_MAIN_BOARD): + for y in range(self.SENSOR_CORETEMP_NUM_ON_MAIN_BOARD): + SensorFlag[x][y] = 0 + +class device_monitor(object): + + MASTER_LED_PATH = '/sys/class/leds/master/brightness' + SYSTEM_LED_PATH = '/sys/class/leds/system/brightness' + + PWMINPUT_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/{1}/pwm{2}' + HWMONINPUT_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/' + + PWMINPUT_NUM = 10 + _pwm_input_path_mapping = {} + _hwmon_input_path_mapping = {} + + # PWM NUMBERS + _pwm_input_node_mapping = ['1','2','3','4','1','2','3','4','1','2'] + + # I2C NUMBERS + _hwmon_input_node_mapping = ['2c','2c','2c','2c','2e','2e','2e','2e','2f','2f'] + + def __init__(self, log_file, log_level): + global DEBUG + global isPlatformAFI + + hwmoninput_path = self.HWMONINPUT_PATH + pwminput_path = self.PWMINPUT_PATH + for x in range(self.PWMINPUT_NUM): + self._hwmon_input_path_mapping[x] = hwmoninput_path.format( + self._hwmon_input_node_mapping[x]) + + hwmon_path = os.listdir(self._hwmon_input_path_mapping[x]) + hwmon_dir = '' + for hwmon_name in hwmon_path: + hwmon_dir = hwmon_name + + self._pwm_input_path_mapping[x] = pwminput_path.format( + self._hwmon_input_node_mapping[x], + hwmon_dir, + self._pwm_input_node_mapping[x]) + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s' + ) + + if DEBUG == True: + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + filename = "/var/run/eeprom" + AFO_str = "AFO" + pattern = re.compile(r"Fan Type", re.IGNORECASE) + with open(filename, "rt") as myfile: + for line in myfile: + if pattern.search(line) != None: + fan_type = str(line) + if "=" in fan_type: + user=fan_type[fan_type.find("=")+1:].split()[0] + if user == AFO_str: + isPlatformAFI = False + else: + isPlatformAFI = True + + master_led_value = 1 + + try: + masterLED_file = open(self.MASTER_LED_PATH, 'r+') + except IOError as e: + logging.error('device_monitor: unable to open Master LED file: %s', str(e)) + + masterLED_file.write(str(master_led_value)) + masterLED_file.close() + + system_led_value = 1 + + try: + systemLED_file = open(self.SYSTEM_LED_PATH, 'r+') + except IOError as e: + logging.error('device_monitor: unable to open System LED file: %s', str(e)) + + systemLED_file.write(str(system_led_value)) + systemLED_file.close() + self.get_Initial_fan_dutycycle() + self.set_Default_fan_dutycycle(35) + + + def set_Default_fan_dutycycle(self, val): + fan_speed = {35: 86, 55: 139, 75: 192, 90: 230,100: 255} + for x in range(self.PWMINPUT_NUM): + device_path = self._pwm_input_path_mapping[x] + pwm_value = fan_speed.get(val) + pwm_value1 = str(pwm_value) + time.sleep(0.25) + cmd = ("sudo echo %s > %s" %(pwm_value1,device_path)) + os.system(cmd) + + logging.debug('Setting Default PWM value: 86 to all fans') + return True + + def get_Initial_fan_dutycycle(self): + pwm_str = '' + for x in range(self.PWMINPUT_NUM): + device_path = self._pwm_input_path_mapping[x] + cmd = ("sudo cat %s" %(device_path)) + status, pwm_value = commands.getstatusoutput(cmd) + pwm_str += pwm_value + if (x != self.PWMINPUT_NUM -1): + pwm_str += ', ' + time.sleep(0.25) + logging.debug('Initial PWM values read: %s', pwm_str) + return True + + def manage_device(self): + thermal = QFX5200_ThermalUtil() + thermal.getSensorTemp() + +def main(): + #Introducing sleep of 150 seconds to wait for all the docker containers to start before starting the EM policy. + time.sleep(150) + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_device() + time.sleep(20) + +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/juniper_qfx5200_util.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/juniper_qfx5200_util.py new file mode 100755 index 000000000000..2e6171d99180 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/juniper_qfx5200_util.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python +# +# Description: This file contains the Juniper QFX5200 Platform Initialization routines +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import commands +import sys +import logging +import time + +PROJECT_NAME = 'QFX5200-32C' +verbose = False +DEBUG = False +FORCE = 0 + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + +i2c_prefix = '/sys/bus/i2c/devices/' + +kos = [ +'modprobe i2c-mux', +'modprobe mfd-core', +'modprobe tmp401', +'modprobe jnx-tmc-core', +'modprobe leds-jnx-tmc', +'modprobe jnx-refpga-tmc', +'modprobe i2c-tmc', +'modprobe gpio-tmc', +'modprobe jnx-tmc-psu', +'modprobe jnx-psu-monitor', +'modprobe jnx-refpga-lpcm', +'modprobe adt7470' +] + +mknod =[ +'echo tmp435 0x48 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo tmp435 0x49 > /sys/bus/i2c/devices/i2c-5/new_device', +'echo tmp435 0x4A > /sys/bus/i2c/devices/i2c-5/new_device', +'echo tmp435 0x4B > /sys/bus/i2c/devices/i2c-5/new_device', +'echo tmp435 0x48 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo tmp435 0x49 > /sys/bus/i2c/devices/i2c-6/new_device', +'echo tmp435 0x4A > /sys/bus/i2c/devices/i2c-6/new_device', +'echo tmp435 0x4B > /sys/bus/i2c/devices/i2c-6/new_device', +'echo tmp435 0x48 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo tmp435 0x49 > /sys/bus/i2c/devices/i2c-7/new_device', +'echo adt7470 0x2C > /sys/bus/i2c/devices/i2c-7/new_device', +'echo adt7470 0x2E > /sys/bus/i2c/devices/i2c-7/new_device', +'echo adt7470 0x2F > /sys/bus/i2c/devices/i2c-7/new_device', +'echo jpsu 0x58 > /sys/bus/i2c/devices/i2c-3/new_device', +'echo jpsu 0x58 > /sys/bus/i2c/devices/i2c-4/new_device', +] + +def my_log(txt): + if DEBUG == True: + print txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_install(): + global FORCE + log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + time.sleep(2) + if status: + if FORCE == 0: + return status + return 0 + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"5-0049", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"7-002c", 0) + + return not(ret1 or ret2) + +def device_install(): + global FORCE + for i in range(0,len(mknod)): + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + +def do_install(): + status = driver_install() + if status: + if FORCE == 0: + return status + + if not device_exist(): + logging.info('No device, installing....') + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def main(): + + hwmon_input_node_mapping = ['2c','2e','2f'] + PWM1FREQ_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/{1}/pwm1_freq' + NUMSENSORS_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/{1}/num_temp_sensors' + HWMONINPUT_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/' + PWMINPUT_NUM = 3 + hwmon_input_path_mapping = {} + pwm_input_path_mapping = {} + numsensors_input_path_mapping = {} + + + # Enabling REFPGA + EnableREFFGACmd = 'busybox devmem 0xFED50011 8 0x53' + try: + os.system(EnableREFFGACmd) + except OSError: + print 'Error: Execution of "%s" failed', EnableREFFGACmd + return False + + time.sleep(2) + + # Create CPU Board EEPROM device + CreateEEPROMdeviceCmd = 'sudo echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-0/new_device' + try: + os.system(CreateEEPROMdeviceCmd) + except OSError: + print 'Error: Execution of "%s" failed', CreateEEPROMdeviceCmd + return False + + time.sleep(1) + + #Retrieve the Base MAC Address from EEPROM + status, macAddress = commands.getstatusoutput("decode-syseeprom -m 0x24") + if status: + print 'Error: Could not retrieve BASE MAC Address from EEPROM' + return False + + #Make eth0 interface down + status, eth0Down = commands.getstatusoutput("ifconfig eth0 down") + if status: + print 'Error: Could not make eth0 interface down' + return False + + #Assign BASE MAC ADDRESS retieved from CPU board EEPROM to eth0 interface + mac_address_prog = "ifconfig eth0 hw ether " + str(macAddress) + + status, MACAddressProg = commands.getstatusoutput(mac_address_prog) + if status: + print 'Error: Could not set up "macAddress" for eth0 interface' + return False + + #Make eth0 interface up + status, eth0UP = commands.getstatusoutput("ifconfig eth0 up") + if status: + print 'Error: Could not make eth0 interface up' + return False + + # Juniper QFX5200 platform drivers install + do_install() + time.sleep(2) + + # Juniper SFP Intialization + JuniperSFPInitCmd = 'python /usr/share/sonic/device/x86_64-juniper_qfx5200-r0/plugins/qfx5200_sfp_init.py' + try: + os.system(JuniperSFPInitCmd) + except OSError: + print 'Error: Execution of "%s" failed', JuniperSFPInitCmd + return False + + time.sleep(1) + # Invoking the script which retrieves the data from CPU Board and Main Board EEPROM and storing in file + EEPROMDataCmd = 'python /usr/share/sonic/device/x86_64-juniper_qfx5200-r0/plugins/qfx5200_eeprom_data.py' + try: + os.system(EEPROMDataCmd) + except OSError: + print 'Error: Execution of "%s" failed', EEPROMDataCmd + return False + + for x in range(PWMINPUT_NUM): + hwmon_input_path_mapping[x] = HWMONINPUT_PATH.format(hwmon_input_node_mapping[x]) + + hwmon_path = os.listdir(hwmon_input_path_mapping[x]) + hwmon_dir = '' + for hwmon_name in hwmon_path: + hwmon_dir = hwmon_name + + pwm_input_path_mapping[x] = PWM1FREQ_PATH.format( + hwmon_input_node_mapping[x], + hwmon_dir) + device_path = pwm_input_path_mapping[x] + time.sleep(1) + cmd = ("sudo echo 22500 > %s" %device_path) + os.system(cmd) + + numsensors_input_path_mapping[x] = NUMSENSORS_PATH.format( + hwmon_input_node_mapping[x], + hwmon_dir) + numsensors_path = numsensors_input_path_mapping[x] + time.sleep(1) + cmd = ("sudo echo 0 > %s" %numsensors_path) + os.system(cmd) + + return True + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/show_thresholds b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/show_thresholds new file mode 100755 index 000000000000..29d584e7f328 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/show_thresholds @@ -0,0 +1,43 @@ +#!/usr/bin/env python +import os +import commands + +def fantype_detect(): + + refpgaTMC_path = "/sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15" + + AFO = "1" + AFI = "0" + + #default fan type is AFI + default_fantype = 0 + + for filename in os.listdir(refpgaTMC_path): + if filename.endswith('_type'): + fantype_path = os.path.join(refpgaTMC_path, filename) + cat_string = "cat " + fantype_string = cat_string + fantype_path + status,fan_type=commands.getstatusoutput(fantype_string) + if ((fan_type == AFO) or (fan_type == AFI)): + return fan_type + else: + pass + + return default_fantype + +def main(): + AFO_value = "1" + + fan_type = fantype_detect() + + if fan_type == AFO_value: + temp_thres_file = open("/usr/local/bin/temperature_thresholds_AFO.txt", "r+") + print temp_thres_file.read() + else: + temp_thres_file = open("/usr/local/bin/temperature_thresholds_AFI.txt", "r+") + print temp_thres_file.read() + + temp_thres_file.close() + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/temperature_thresholds_AFI.txt b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/temperature_thresholds_AFI.txt new file mode 100755 index 000000000000..055bd850906a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/temperature_thresholds_AFI.txt @@ -0,0 +1,27 @@ +Sensor # 35% 55% 75% 90% 100% Yellow Red Fire + Duty cycle Duty cycle Duty cycle Duty cycle Duty cycle Alarm Alarm Shutdown +================== ================================================================================================== +1 CPU <50 >=50 & <58 >=58 & 66 >=66 & <75 >=75 >86 >92 >95 + +2 (tmp435-i2c-7-48) <39 >=39 & <48 >=48 & <56 >=56 & <66 >=66 >64 >70 >73 + +3 (tmp435-i2c-7-49) <39 >=39 & <48 >=48 & <56 >=56 & <66 >=66 >64 >70 >73 + +4 BRCM TH1 ASIC <74 >=74 & <80 >=80 & <85 >=85 & <92 >=92 >99 >102 >105 + +5 (tmp435-i2c-5-48) <47 >=47 & <55 >=55 & <62 >=62 & <70 >=70 >68 >74 >77 + +6 (tmp435-i2c-5-49) <44 >=44 & <52 >=52 & <60 >=60 & <69 >=69 >67 >73 >76 + +7 (tmp435-i2c-5-4a) <57 >=57 & <63 >=63 & <68 >=68 & <74 >=74 >72 >78 >81 + +8 (tmp435-i2c-5-4b) <45 >=45 & <53 >=53 & <61 >=61 & <70 >=70 >68 >74 >77 + +9 (tmp435-i2c-6-48) <45 >=45 & <53 >=53 & <60 >=60 & <69 >=69 >67 >73 >76 + +10 (tmp435-i2c-6-49) <57 >=57 & <63 >=63 & <68 >=68 & <74 >=74 >72 >78 >81 + +11 (tmp435-i2c-6-4A) <48 >=48 & <55 >=55 & <62 >=62 & <70 >=70 >68 >74 >77 + +12 (tmp435-i2c-6-4B) <49 >=49 & <57 >=57 & <64 >=64 & <72 >=72 >70 >76 >79 + diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/temperature_thresholds_AFO.txt b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/temperature_thresholds_AFO.txt new file mode 100755 index 000000000000..b7f489b5565a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/temperature_thresholds_AFO.txt @@ -0,0 +1,27 @@ +Sensor # 35% 55% 75% 90% 100% Yellow Red Fire + Duty cycle Duty cycle Duty cycle Duty cycle Duty cycle Alarm Alarm Shutdown +================== ================================================================================================== +1 CPU <58 >=58 & <64 >=64 & <70 >=70 & <78 >=78 >86 >92 >95 + +2 (tmp435-i2c-7-48) <49 >=49 & <55 >=55 & <62 >=62 & <69 >=69 >67 >73 >76 + +3 (tmp435-i2c-7-49) <48 >=48 & <55 >=55 & <61 >=61 & <69 >=69 >67 >73 >76 + +4 BRCM TH1 ASIC <79 >=79 & <83 >=83 & <86 >=86 & <90 >=90 >99 >102 >105 + +5 (tmp435-i2c-5-48) <50 >=50 & <56 >=56 & <63 >=63 & <70 >=70 >68 >74 >77 + +6 (tmp435-i2c-5-49) <43 >=43 & <50 >=50 & <57 >=57 & <65 >=65 >63 >69 >72 + +7 (tmp435-i2c-5-4a) <54 >=54 & <60 >=60 & <65 >=65 & <71 >=71 >68 >74 >77 + +8 (tmp435-i2c-5-4b) <52 >=52 & <58 >=58 & <63 >=63 & <70 >=70 >68 >74 >77 + +9 (tmp435-i2c-6-48) <55 >=55 & <60 >=60 & <65 >=65 & <71 >=71 >65 >71 >78 + +10 (tmp435-i2c-6-49) <55 >=55 & <60 >=60 & <66 >=66 & <72 >=72 >70 >76 >79 + +11 (tmp435-i2c-6-4A) <47 >=47 & <54 >=54 & <60 >=60 & <67 >=67 >65 >71 >74 + +12 (tmp435-i2c-6-4B) <61 >=61 & <66 >=66 & <70 >=70 & <75 >=75 >73 >79 >82 + diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/wrapper-fast-reboot b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/wrapper-fast-reboot new file mode 100755 index 000000000000..08ac3be0d688 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/wrapper-fast-reboot @@ -0,0 +1,17 @@ +#!/bin/bash + +# Disable exit on non zero +set +e + +# Unloading this module as it contains the reboot +# notifier hook. When the kexec is invoked with platform +# reset handlers, it results in a cold reboot. Removing +# the reset handlers ensures that kernel does a kexec +# based fast reboot +rmmod jnx-refpga-lpcm > /dev/null 2>&1 + +/usr/bin/qfx5200-fast-reboot/fast-reboot $@ + +# Re-load the module if the fast-reboot script returns +# here. +modprobe jnx-refpga-lpcm > /dev/null 2>&1 diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/wrapper-warm-reboot b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/wrapper-warm-reboot new file mode 100755 index 000000000000..e34db6629588 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/utils/wrapper-warm-reboot @@ -0,0 +1,17 @@ +#!/bin/bash + +# Disable exit on non zero +set +e + +# Unloading this module as it contains the reboot +# notifier hook. When the kexec is invoked with platform +# reset handlers, it results in a cold reboot. Removing +# the reset handlers ensures that kernel does a kexec +# based fast reboot +rmmod jnx-refpga-lpcm > /dev/null 2>&1 + +/usr/bin/qfx5200-warm-reboot/warm-reboot $@ + +# Re-load the module if the warm-reboot script returns +# here. +modprobe jnx-refpga-lpcm > /dev/null 2>&1 diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/Makefile b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/Makefile new file mode 100644 index 000000000000..2218af494da7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/Makefile @@ -0,0 +1,2 @@ +obj-m:=x86-64-juniper-qfx5210-64x-fan.o x86-64-juniper-qfx5210-64x-leds.o \ + x86-64-juniper-qfx5210-64x-psu.o juniper_i2c_cpld.o ym2651y.o diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/juniper_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/juniper_i2c_cpld.c new file mode 100644 index 000000000000..25860a6ac1f9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/juniper_i2c_cpld.c @@ -0,0 +1,892 @@ +/* + * A hwmon driver for the juniper_i2c_cpld + * + * Tested and validated on Juniper QFX5210 + * Ciju Rajan K + * + * Copyright (C) 2013 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define MAX_PORT_NUM 64 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define I2C_ADDR_CPLD1 0x60 +#define I2C_ADDR_CPLD2 0x62 +#define I2C_ADDR_CPLD3 0x64 +#define CPLD_ADDRS {I2C_ADDR_CPLD1, I2C_ADDR_CPLD2, I2C_ADDR_CPLD3} + + +/* + * Number of additional attribute pointers to allocate + * with each call to krealloc + */ +#define ATTR_ALLOC_SIZE 1 /*For last attribute which is NUll.*/ + +#define NAME_SIZE 24 +#define MAX_RESP_LENGTH 48 + +typedef ssize_t (*show_func)( struct device *dev, + struct device_attribute *attr, + char *buf); +typedef ssize_t (*store_func)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); + +enum models { + AS7712_32X, + AS7716_32X, + qfx5210_64X, + AS7312_54X, + PLAIN_CPLD, /*No attribute but add i2c addr to the list.*/ + NUM_MODEL +}; + +enum sfp_func { + HAS_SFP = 1<<0 , + HAS_QSFP = 1<<1 , +}; + +enum common_attrs { + CMN_VERSION, + CMN_ACCESS, + CMN_PRESENT_ALL, + NUM_COMMON_ATTR +}; + +enum sfp_attrs { + SFP_PRESENT, + SFP_RESET, + SFP_LP_MODE, + NUM_SFP_ATTR +}; + +struct cpld_sensor { + struct cpld_sensor *next; + char name[NAME_SIZE+1]; /* sysfs sensor name */ + struct device_attribute attribute; + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. Negative if there was a read error */ + + u8 reg; /* register */ + u8 mask; /* bit mask */ + bool invert; /* inverted value*/ + +}; + +#define to_cpld_sensor(_attr) \ + container_of(_attr, struct cpld_sensor, attribute) + +struct cpld_data { + struct device *dev; + struct device *hwmon_dev; + + int num_attributes; + struct attribute_group group; + + enum models model; + struct cpld_sensor *sensors; + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + int attr_index; + u16 sfp_num; + u8 sfp_types; + struct model_attrs *cmn_attr; +}; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + + +struct base_attrs { + const char *name; + umode_t mode; + show_func get; + store_func set; +}; + +struct attrs { + int reg; + bool invert; + struct base_attrs *base; +}; + +struct model_attrs { + struct attrs **cmn; + struct attrs **portly; +}; + + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t show_presnet_all(struct device *dev, + struct device_attribute *devattr, char *buf); +static ssize_t set_1bit(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_byte(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +int juniper_i2c_cpld_read(u8 cpld_addr, u8 reg); +int juniper_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + + +struct base_attrs common_attrs[NUM_COMMON_ATTR] = +{ + [CMN_VERSION] = {"version", S_IRUGO, show_bit, NULL}, + [CMN_ACCESS] = {"access", S_IWUSR, NULL, set_byte}, + [CMN_PRESENT_ALL] = {"module_present_all", S_IRUGO, show_presnet_all, NULL}, +}; + +struct attrs as7712_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {0x30, false, &common_attrs[CMN_PRESENT_ALL]}, +}; +struct attrs qfx5210_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {0x30, false, &common_attrs[CMN_PRESENT_ALL]}, +}; +struct attrs as7312_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, + [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]}, + [CMN_PRESENT_ALL] = {-1, false, &common_attrs[CMN_PRESENT_ALL]}, +}; +struct attrs plain_common[] = { + [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]}, +}; + +struct base_attrs portly_attrs[] = +{ + [SFP_PRESENT] = {"module_present", S_IRUGO, show_bit, NULL}, + // Only root user will have the privilege to write to sysfs + // [SFP_RESET] = {"module_reset", S_IRUGO|S_IWUGO, show_bit, set_1bit}, + [SFP_RESET] = {"module_reset", S_IRUGO|S_IWUSR, show_bit, set_1bit}, +}; + +struct attrs as7712_port[] = { + {0x30, true, &portly_attrs[SFP_PRESENT]}, + {0x04, true, &portly_attrs[SFP_RESET]}, +}; + +struct attrs qfx5210_port[] = { + {0x70, true, &portly_attrs[SFP_PRESENT]}, + {0x40, true, &portly_attrs[SFP_RESET]}, +}; + +struct attrs *as7712_cmn_list[] = { + &as7712_common[CMN_VERSION], + &as7712_common[CMN_ACCESS], + &as7712_common[CMN_PRESENT_ALL], + NULL +}; + +struct attrs *qfx5210_cmn_list[] = { + &qfx5210_common[CMN_VERSION], + &qfx5210_common[CMN_ACCESS], + &qfx5210_common[CMN_PRESENT_ALL], + NULL +}; + +struct attrs *as7312_cmn_list[] = { + &as7312_common[CMN_VERSION], + &as7312_common[CMN_ACCESS], + &as7312_common[CMN_PRESENT_ALL], + NULL +}; + +struct attrs *plain_cmn_list[] = { + &plain_common[CMN_VERSION], + NULL +}; + +struct attrs *as7712_port_list[] = { + &as7712_port[SFP_PRESENT], + &as7712_port[SFP_RESET], + NULL +}; +struct attrs *qfx5210_port_list[] = { + &qfx5210_port[SFP_PRESENT], + &qfx5210_port[SFP_RESET], + NULL +}; + +struct model_attrs models_attr[NUM_MODEL] = { + {.cmn = as7712_cmn_list, .portly=as7712_port_list}, + {.cmn = as7712_cmn_list, .portly=as7712_port_list}, /*7716's as 7712*/ + {.cmn = qfx5210_cmn_list, .portly=qfx5210_port_list}, + {.cmn = as7312_cmn_list, .portly=qfx5210_port_list}, + {.cmn = plain_cmn_list, .portly=NULL}, +}; + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; +/* Addresses scanned for juniper_i2c_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static int get_sfp_spec(int model, u16 *num, u8 *types) +{ + switch (model) { + case AS7712_32X: + case AS7716_32X: + *num = 32; + *types = HAS_QSFP; + break; + case qfx5210_64X: + *num = 64; + *types = HAS_QSFP; + break; + case AS7312_54X: + *num = 54; + *types = HAS_QSFP|HAS_SFP; + default: + *types = 0; + *num = 0; + break; + } + + return 0; +} + +static int get_present_reg(int model, u8 port, u8 *cpld_addr, u8 *reg, u8 *num) +{ + u8 cpld_address[] = CPLD_ADDRS; + + switch (model) { + case AS7312_54X: + if (port < 48) { + *cpld_addr = cpld_address[1 + port/24]; + *reg = 0x09 + (port%24)/8; + *num = 8; + } + else + { + *reg = 0x18; + *num = 4; + *cpld_addr = ( port < 52)? cpld_address[1]: cpld_address[2]; + } + break; + default: + return -EINVAL; + } +} + + +/*Assume the bits for ports are listed in-a-row.*/ +static int get_reg_bit(u8 reg_start, int port, + u8 *reg ,u8 *mask) +{ + *reg = reg_start + ((port)/8); + *mask = 1 << ((port)%8); + + return 0; +} + +static int cpld_write_internal( + struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + + +/*Turn a numberic array into string with " " between each element. + * e.g., {0x11, 0x33, 0xff, 0xf1} => "11 33 ff f1" + */ +static ssize_t array_stringify(char *buf, u8 *input, size_t size) { + + int i; + char t[MAX_RESP_LENGTH+1]; + + buf[0] = '\0'; + for (i = 0; i < size; i++) { + snprintf(t, MAX_RESP_LENGTH, "%x ", input[i]); + strncat(buf, t, MAX_RESP_LENGTH); + } + + if (strlen(buf) > 0) + buf[strlen(buf)-1] = '\0'; /*Remove tailing blank*/ + + return snprintf(buf, MAX_RESP_LENGTH, "%s\n", buf); +} + +static ssize_t show_presnet_all_distinct(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 i, value, reg; + u8 cpld_addr, num; + u8 _value[8]; + u64 *values = (u64 *)_value; + + values = 0; + mutex_lock(&data->update_lock); + while(i < data->sfp_num) + { + get_present_reg(data->model, i, &cpld_addr, ®, &num); + if(cpld_addr == client->addr) + value = cpld_read_internal(client, reg); + else + value = juniper_i2c_cpld_read(cpld_addr, reg); + + if (unlikely(value < 0)) { + goto exit; + } + + *values |= (value&((1<<(num))-1)) << i; + i += num; + } + mutex_unlock(&data->update_lock); + + *values = cpu_to_le64(*values); + return array_stringify(buf, _value, i); +exit: + mutex_unlock(&data->update_lock); + return value; +} + +static ssize_t show_presnet_all(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + u8 i, values[MAX_RESP_LENGTH/8]; + + if (sensor->reg < 0) { + return show_presnet_all_distinct(dev, devattr, buf); + } + + mutex_lock(&data->update_lock); + for (i = 0; i < ((data->sfp_num+7)/8); i++) { + values[i] = cpld_read_internal(client, sensor->reg + i); + if (unlikely(values[i] < 0)) { + goto exit; + } + } + mutex_unlock(&data->update_lock); + return array_stringify(buf, values, i); + +exit: + mutex_unlock(&data->update_lock); + return values[i]; +} + +static ssize_t show_bit(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int value; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, sensor->reg); + value = value & sensor->mask; + if (sensor->invert) + value = !value; + mutex_unlock(&data->update_lock); + + return snprintf(buf, PAGE_SIZE, "%x\n", value); +} + +static ssize_t set_1bit(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + long is_reset; + int value, status; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + struct cpld_sensor *sensor = to_cpld_sensor(devattr); + u8 cpld_bit, reg; + + status = kstrtol(buf, 10, &is_reset); + if (status) { + return status; + } + reg = sensor->reg; + cpld_bit = sensor->mask; + mutex_lock(&data->update_lock); + value = cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + if (sensor->invert) + is_reset = !is_reset; + + if (is_reset) { + value |= cpld_bit; + } + else { + value &= ~cpld_bit; + } + + status = cpld_write_internal(client, reg, value); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_byte(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + return access(dev, da, buf, count); +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void juniper_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = + kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", + client->addr); + return; + } + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void juniper_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int cpld_add_attribute(struct cpld_data *data, struct attribute *attr) +{ + int new_max_attrs = ++data->num_attributes + ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + + + data->group.attrs[data->num_attributes-1] = attr; + data->group.attrs[data->num_attributes] = NULL; + + return 0; +} + +static void cpld_dev_attr_init(struct device_attribute *dev_attr, + const char *name, umode_t mode, + show_func show, store_func store) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static struct cpld_sensor * add_sensor(struct cpld_data *data, + const char *name, + u8 reg, u8 mask, bool invert, + bool update, umode_t mode, + show_func get, store_func set) +{ + struct cpld_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), name); + sensor->reg = reg; + sensor->mask = mask; + sensor->update = update; + sensor->invert = invert; + cpld_dev_attr_init(a, sensor->name, + mode, + get, set); + + if (cpld_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int add_attributes_cmn(struct cpld_data *data, struct attrs **cmn) +{ + u8 reg, i ; + bool invert; + struct attrs *a; + struct base_attrs *b; + + if (NULL == cmn) + return -1; + + for (i = 0; cmn[i]; i++) + { + a = cmn[i]; + + reg = a->reg; + invert = a->invert; + + b = a->base; + if (NULL == b) + break; + + if (add_sensor(data, b->name, + reg, 0xff, invert, + true, b->mode, + b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + return 0; +} + +static int add_attributes_portly(struct cpld_data *data, struct attrs **pa) +{ + char name[NAME_SIZE+1]; + int i, j; + u8 reg, mask, invert; + struct attrs *a; + struct base_attrs *b; + + if (NULL == pa) + return -1; + + + for (i = 0; pa[i]; i++) { + a = pa[i]; + + invert = a->invert; + b = a->base; + if (b == NULL) + break; + + for (j = 0; j < data->sfp_num; j++) + { + snprintf(name, NAME_SIZE, "%s_%d", b->name, j+1); + get_reg_bit(a->reg, j, ®, &mask); + + if (add_sensor(data, name, reg, mask, invert, + true, b->mode, b->get, b->set) == NULL) + { + return -ENOMEM; + } + } + } + return 0; +} + +static int add_attributes(struct i2c_client *client, + struct cpld_data *data) +{ + struct model_attrs *m = data->cmn_attr; + + if (m == NULL) + return -EINVAL; + + /* Common attributes.*/ + add_attributes_cmn(data, m->cmn); + + /* Port-wise attributes.*/ + add_attributes_portly(data, m->portly); + + return 0; +} + +static int juniper_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + struct device *dev = &client->dev; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + return -EIO; + } + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->model = dev_id->driver_data; + data->cmn_attr = &models_attr[data->model]; + get_sfp_spec(data->model, &data->sfp_num, &data->sfp_types); + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->dev = dev; + dev_info(dev, "chip found\n"); + + status = add_attributes(client, data); + if (status) + goto out_kfree; + + /* + * If there are no attributes, something is wrong. + * Bail out instead of trying to register nothing. + */ + if (!data->num_attributes) { + dev_err(dev, "No attributes found\n"); + status = -ENODEV; + goto out_kfree; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->group); + if (status) { + goto out_kfree; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + juniper_i2c_cpld_add_client(client); + dev_info(dev, "%s: cpld '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->group); +out_kfree: + kfree(data->group.attrs); + return status; + +} + +static int juniper_i2c_cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->group); + kfree(data->group.attrs); + juniper_i2c_cpld_remove_client(client); + return 0; +} + +int juniper_i2c_cpld_read(u8 cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(juniper_i2c_cpld_read); + +int juniper_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(juniper_i2c_cpld_write); + + +static const struct i2c_device_id juniper_i2c_cpld_id[] = { + { "cpld_as7712", AS7712_32X}, + { "cpld_as7716", AS7716_32X}, + { "cpld_qfx5210", qfx5210_64X}, + { "cpld_as7312", AS7312_54X}, + { "cpld_plain", PLAIN_CPLD}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, juniper_i2c_cpld_id); + +static struct i2c_driver juniper_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "juniper_i2c_cpld", + }, + .probe = juniper_i2c_cpld_probe, + .remove = juniper_i2c_cpld_remove, + .id_table = juniper_i2c_cpld_id, + .address_list = normal_i2c, +}; + + +static int __init juniper_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&juniper_i2c_cpld_driver); +} + +static void __exit juniper_i2c_cpld_exit(void) +{ + i2c_del_driver(&juniper_i2c_cpld_driver); +} + +module_init(juniper_i2c_cpld_init); +module_exit(juniper_i2c_cpld_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("juniper_i2c_cpld driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-fan.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-fan.c new file mode 100644 index 000000000000..3e9b67a5da63 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-fan.c @@ -0,0 +1,470 @@ +/* + * A hwmon driver for the juniper qfx5210-64x fan + * + * Modified and tested to work on Juniper QFX5210 + * Ciju Rajan K + * + * Copyright (C) 2014 juniper Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "qfx5210_64x_fan" + +static struct qfx5210_64x_fan_data *qfx5210_64x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x80, /* fan 1-4 present status */ + 0x81, /* fan 1-4 direction(0:F2B 1:B2F) */ + 0x87, /* fan PWM(for all fan) */ + 0x90, /* front fan 1 speed(rpm) */ + 0x91, /* front fan 2 speed(rpm) */ + 0x92, /* front fan 3 speed(rpm) */ + 0x93, /* front fan 4 speed(rpm) */ + 0x98, /* rear fan 1 speed(rpm) */ + 0x99, /* rear fan 2 speed(rpm) */ + 0x9A, /* rear fan 3 speed(rpm) */ + 0x9B, /* rear fan 4 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct qfx5210_64x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE);\ + static SENSOR_DEVICE_ATTR(pwm##index, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN_DUTY_CYCLE_PERCENTAGE) + +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan_duty_cycle_percentage.dev_attr.attr, \ + &sensor_dev_attr_pwm##index.dev_attr.attr + + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##index2##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4,14); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1,11); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2,12); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3,13); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4,14); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); + +static struct attribute *qfx5210_64x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1,11), + DECLARE_FAN_FAULT_ATTR(2,12), + DECLARE_FAN_FAULT_ATTR(3,13), + DECLARE_FAN_FAULT_ATTR(4,14), + DECLARE_FAN_SPEED_RPM_ATTR(1,11), + DECLARE_FAN_SPEED_RPM_ATTR(2,12), + DECLARE_FAN_SPEED_RPM_ATTR(3,13), + DECLARE_FAN_SPEED_RPM_ATTR(4,14), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0xF +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +static int qfx5210_64x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int qfx5210_64x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + + if (!reg_val) { + return 0; + } + + if (reg_val == 0xF) { + return FAN_MAX_DUTY_CYCLE; + } + + return (reg_val * 6) + 10; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle < 16) { + return 0; + } + + if (duty_cycle >= 100) { + return 0xF; + } + + return (duty_cycle - 10) / 6; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + return !!(reg_val & mask); +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + return !(reg_val & mask); +} + +static u8 is_fan_fault(struct qfx5210_64x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + if (value > FAN_MAX_DUTY_CYCLE) + value = FAN_MAX_DUTY_CYCLE; + if (value < 0) + return -EINVAL; + + qfx5210_64x_fan_write_value(client, 0x28, 0); /* Disable fan speed watch dog */ + qfx5210_64x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct qfx5210_64x_fan_data *data = qfx5210_64x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + { + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + } + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group qfx5210_64x_fan_group = { + .attrs = qfx5210_64x_fan_attributes, +}; + +static struct qfx5210_64x_fan_data *qfx5210_64x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct qfx5210_64x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting qfx5210_64x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = qfx5210_64x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int qfx5210_64x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct qfx5210_64x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct qfx5210_64x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qfx5210_64x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qfx5210_64x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int qfx5210_64x_fan_remove(struct i2c_client *client) +{ + struct qfx5210_64x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &qfx5210_64x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static const struct i2c_device_id qfx5210_64x_fan_id[] = { + { "qfx5210_64x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, qfx5210_64x_fan_id); + +static struct i2c_driver qfx5210_64x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = qfx5210_64x_fan_probe, + .remove = qfx5210_64x_fan_remove, + .id_table = qfx5210_64x_fan_id, + .address_list = normal_i2c, +}; + +static int __init qfx5210_64x_fan_init(void) +{ + return i2c_add_driver(&qfx5210_64x_fan_driver); +} + +static void __exit qfx5210_64x_fan_exit(void) +{ + i2c_del_driver(&qfx5210_64x_fan_driver); +} + +module_init(qfx5210_64x_fan_init); +module_exit(qfx5210_64x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("qfx5210_64x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-leds.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-leds.c new file mode 100644 index 000000000000..51ce772c5e80 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-leds.c @@ -0,0 +1,449 @@ +/* + * LED driver for the qfx5210 + * + * Modified and tested to work on Juniper QFX5210 + * Ciju Rajan K + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int juniper_i2c_cpld_read (u8 cpld_addr, u8 reg); +extern int juniper_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "qfx5210_64x_led" + +struct qfx5210_64x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* only 1 register*/ +}; + +static struct qfx5210_64x_led_data *ledctl = NULL; + +/* + * LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) /* CPLD1 i2c address */ + +#define LED_TYPE_ALARM_REG_MASK (0x03) +#define LED_MODE_ALARM_RED_VALUE (0x01) +#define LED_MODE_ALARM_AMBER_VALUE (0x02) +#define LED_MODE_ALARM_OFF_VALUE (0x00) + +#define LED_TYPE_SYSTEM_REG_MASK (0x0C) +#define LED_MODE_SYSTEM_GREEN_VALUE (0x04) +#define LED_MODE_SYSTEM_GREEN_BLINKING_VALUE (0x08) +#define LED_MODE_SYSTEM_OFF_VALUE (0x00) + +#define LED_TYPE_MASTER_REG_MASK (0x30) +#define LED_MODE_MASTER_GREEN_VALUE (0x10) +#define LED_MODE_MASTER_GREEN_BLINKING_VALUE (0x20) +#define LED_MODE_MASTER_OFF_VALUE (0x00) + +#define LED_TYPE_BEACON_REG_MASK (0xC0) +#define LED_MODE_BEACON_VALUE (0x40) +#define LED_MODE_BEACON_OFF_VALUE (0x00) + +enum led_type { + LED_TYPE_ALARM, + LED_TYPE_SYSTEM, + LED_TYPE_MASTER, + LED_TYPE_BEACON +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + {(1 << LED_TYPE_ALARM) | (1 << LED_TYPE_SYSTEM) | (1 << LED_TYPE_MASTER) | (1 << LED_TYPE_BEACON), 0x30}, +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_RED = 1, + LED_MODE_AMBER = 2, + LED_MODE_GREEN = 1, + LED_MODE_GREEN_BLINKING = 2, + LED_MODE_BLUE_BLINKING = 1 +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int reg_bit_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { + {LED_TYPE_ALARM, LED_MODE_RED, LED_TYPE_ALARM_REG_MASK, LED_MODE_ALARM_RED_VALUE}, + {LED_TYPE_ALARM, LED_MODE_AMBER, LED_TYPE_ALARM_REG_MASK, LED_MODE_ALARM_AMBER_VALUE}, + {LED_TYPE_ALARM, LED_MODE_OFF, LED_TYPE_ALARM_REG_MASK, LED_MODE_ALARM_OFF_VALUE}, + + {LED_TYPE_SYSTEM, LED_MODE_GREEN, LED_TYPE_SYSTEM_REG_MASK, LED_MODE_SYSTEM_GREEN_VALUE}, + {LED_TYPE_SYSTEM, LED_MODE_GREEN_BLINKING, LED_TYPE_SYSTEM_REG_MASK, LED_MODE_SYSTEM_GREEN_BLINKING_VALUE}, + {LED_TYPE_SYSTEM, LED_MODE_OFF, LED_TYPE_SYSTEM_REG_MASK, LED_MODE_SYSTEM_OFF_VALUE}, + + {LED_TYPE_MASTER, LED_MODE_GREEN, LED_TYPE_MASTER_REG_MASK, LED_MODE_MASTER_GREEN_VALUE}, + {LED_TYPE_MASTER, LED_MODE_GREEN_BLINKING, LED_TYPE_MASTER_REG_MASK, LED_MODE_MASTER_GREEN_BLINKING_VALUE}, + {LED_TYPE_MASTER, LED_MODE_OFF, LED_TYPE_MASTER_REG_MASK, LED_MODE_MASTER_OFF_VALUE}, + + {LED_TYPE_BEACON, LED_MODE_BLUE_BLINKING, LED_TYPE_BEACON_REG_MASK, LED_MODE_BEACON_VALUE}, + {LED_TYPE_BEACON, LED_MODE_OFF, LED_TYPE_BEACON_REG_MASK, LED_MODE_BEACON_OFF_VALUE} +}; + +static int get_led_reg(enum led_type type, u8 *reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(led_reg_map); i++) { + if(led_reg_map[i].types & (1 << type)) { + *reg = led_reg_map[i].reg_addr; + return 0; + } + } + + return 1; +} + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].reg_bit_mask & reg_val) == + led_type_mode_data[i].mode_value) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_value | + (reg_val & (~led_type_mode_data[i].reg_bit_mask)); + break; + } + + return reg_val; +} + +static int qfx5210_64x_led_read_value(u8 reg) +{ + return juniper_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int qfx5210_64x_led_write_value(u8 reg, u8 value) +{ + return juniper_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void qfx5210_64x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting qfx5210_64x_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = qfx5210_64x_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void qfx5210_64x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !get_led_reg(type, ®)) { + dev_dbg(&ledctl->pdev->dev, "Not match register for %d.\n", type); + } + + reg_val = qfx5210_64x_led_read_value(reg); + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + qfx5210_64x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void qfx5210_64x_led_system_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + qfx5210_64x_led_set(led_cdev, led_light_mode, LED_TYPE_SYSTEM); +} + +static enum led_brightness qfx5210_64x_led_system_get(struct led_classdev *cdev) +{ + qfx5210_64x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_SYSTEM, ledctl->reg_val[0]); +} + +static void qfx5210_64x_led_master_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + qfx5210_64x_led_set(led_cdev, led_light_mode, LED_TYPE_MASTER); +} + +static enum led_brightness qfx5210_64x_led_master_get(struct led_classdev *cdev) +{ + qfx5210_64x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_MASTER, ledctl->reg_val[0]); +} + +static void qfx5210_64x_led_alarm_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + qfx5210_64x_led_set(led_cdev, led_light_mode, LED_TYPE_ALARM); +} + +static enum led_brightness qfx5210_64x_led_alarm_get(struct led_classdev *cdev) +{ + qfx5210_64x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_ALARM, ledctl->reg_val[0]); +} + +static void qfx5210_64x_led_beacon_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + qfx5210_64x_led_set(led_cdev, led_light_mode, LED_TYPE_BEACON); +} + +static enum led_brightness qfx5210_64x_led_beacon_get(struct led_classdev *cdev) +{ + qfx5210_64x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_BEACON, ledctl->reg_val[0]); +} + +static struct led_classdev qfx5210_64x_leds[] = { + [LED_TYPE_ALARM] = { + .name = "alarm", + .default_trigger = "unused", + .brightness_set = qfx5210_64x_led_alarm_set, + .brightness_get = qfx5210_64x_led_alarm_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_SYSTEM] = { + .name = "system", + .default_trigger = "unused", + .brightness_set = qfx5210_64x_led_system_set, + .brightness_get = qfx5210_64x_led_system_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN_BLINKING, + }, + [LED_TYPE_MASTER] = { + .name = "master", + .default_trigger = "unused", + .brightness_set = qfx5210_64x_led_master_set, + .brightness_get = qfx5210_64x_led_master_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_GREEN_BLINKING, + }, + [LED_TYPE_BEACON] = { + .name = "beacon", + .default_trigger = "unused", + .brightness_set = qfx5210_64x_led_beacon_set, + .brightness_get = qfx5210_64x_led_beacon_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_BLUE_BLINKING, + }, +}; + +static int qfx5210_64x_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(qfx5210_64x_leds); i++) { + led_classdev_suspend(&qfx5210_64x_leds[i]); + } + + return 0; +} + +static int qfx5210_64x_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(qfx5210_64x_leds); i++) { + led_classdev_resume(&qfx5210_64x_leds[i]); + } + + return 0; +} + +static int qfx5210_64x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(qfx5210_64x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &qfx5210_64x_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(qfx5210_64x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&qfx5210_64x_leds[i]); + } + } + + return ret; +} + +static int qfx5210_64x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(qfx5210_64x_leds); i++) { + led_classdev_unregister(&qfx5210_64x_leds[i]); + } + + return 0; +} + +static struct platform_driver qfx5210_64x_led_driver = { + .probe = qfx5210_64x_led_probe, + .remove = qfx5210_64x_led_remove, + .suspend = qfx5210_64x_led_suspend, + .resume = qfx5210_64x_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init qfx5210_64x_led_init(void) +{ + int ret; + + ret = platform_driver_register(&qfx5210_64x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct qfx5210_64x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&qfx5210_64x_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&qfx5210_64x_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; +} + +static void __exit qfx5210_64x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&qfx5210_64x_led_driver); + kfree(ledctl); +} + +module_init(qfx5210_64x_led_init); +module_exit(qfx5210_64x_led_exit); + +MODULE_AUTHOR("Ciju Rajan K "); +MODULE_DESCRIPTION("qfx5210_64x_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-psu.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-psu.c new file mode 100644 index 000000000000..49a0cbbcebdd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-psu.c @@ -0,0 +1,322 @@ +/* + * An hwmon driver for juniper qfx5210_64x Power Module + * + * Modified and tested on Juniper QFX5210 + * Ciju Rajan K + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x03 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(2+id))) +#define IS_PRESENT(id, value) (!(value & BIT(id))) + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static struct qfx5210_64x_psu_data *qfx5210_64x_psu_update_device(struct device *dev); +extern int juniper_i2c_cpld_read (u8 cpld_addr, u8 reg); +/* + * This function is defined in juniper_i2c_cpld.c + */ +extern int juniper_i2c_cpld_write(unsigned short, u8, u8); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct qfx5210_64x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ +}; + +enum qfx5210_64x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_POWER_GOOD +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *qfx5210_64x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static int qfx5210_cpld_soft_reset(struct notifier_block *nb, + unsigned long action, + void *data) +{ + int ret = 0; + + switch (action) { + case SYS_POWER_OFF: + case SYS_HALT: + printk(KERN_CRIT "System halt/power_off\n"); + break; + case SYS_RESTART: + printk(KERN_CRIT "System restart: qfx5210_cpld_soft_reset\n"); + ret = juniper_i2c_cpld_write(0x65, 0x04, 0x01); + if (ret) { + printk(KERN_CRIT "qfx5210_cpld_soft_reset failed\n"); + } + msleep(100); + break; + default: + /* Do Nothing */ + break; + } + return NOTIFY_DONE; +} + +static struct notifier_block qfx5210_nb = { + .notifier_call = qfx5210_cpld_soft_reset, +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct qfx5210_64x_psu_data *data = qfx5210_64x_psu_update_device(dev); + u8 status = 0; + + if (!data->valid) { + return -EIO; + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static const struct attribute_group qfx5210_64x_psu_group = { + .attrs = qfx5210_64x_psu_attributes, +}; + +/* + * QFX5210 power off sequence + */ +static void qfx5210_cpld_power_off(void) +{ + printk(KERN_ALERT "pm_power_off: qfx5210_cpld_power_off\n"); + (void) juniper_i2c_cpld_write(0x65, 0x14, 0x00); + msleep(100); + (void) juniper_i2c_cpld_write(0x77, 0x00, 0x01); + msleep(100); + (void) juniper_i2c_cpld_write(0x76, 0x00, 0x04); +} + +/* + * Default platform pm_power_off handler + */ +static void (*default_pm_power_off)(void); + +static int qfx5210_64x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct qfx5210_64x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct qfx5210_64x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qfx5210_64x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qfx5210_64x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int qfx5210_64x_psu_remove(struct i2c_client *client) +{ + struct qfx5210_64x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &qfx5210_64x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + qfx5210_64x_psu1, + qfx5210_64x_psu2 +}; + +static const struct i2c_device_id qfx5210_64x_psu_id[] = { + { "qfx5210_64x_psu1", qfx5210_64x_psu1 }, + { "qfx5210_64x_psu2", qfx5210_64x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, qfx5210_64x_psu_id); + +static struct i2c_driver qfx5210_64x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qfx5210_64x_psu", + }, + .probe = qfx5210_64x_psu_probe, + .remove = qfx5210_64x_psu_remove, + .id_table = qfx5210_64x_psu_id, + .address_list = normal_i2c, +}; + +static struct qfx5210_64x_psu_data *qfx5210_64x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct qfx5210_64x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + + data->valid = 0; + dev_dbg(&client->dev, "Starting qfx5210_64x update\n"); + + /* Read psu status */ + status = juniper_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init qfx5210_64x_psu_init(void) +{ + /* + * Store the default poweroff handler for later usage + */ + default_pm_power_off = pm_power_off; + /* + * Register the cpld poweroff handler + */ + pm_power_off = qfx5210_cpld_power_off; + /* + * Register the cpld soft reset handler + */ + if(register_reboot_notifier(&qfx5210_nb)) { + printk(KERN_ALERT "Restart handler registration failed\n"); + } + + return i2c_add_driver(&qfx5210_64x_psu_driver); +} + +static void __exit qfx5210_64x_psu_exit(void) +{ + /* + * Restore the poweroff handler + */ + pm_power_off = default_pm_power_off; + /* + * Unregister the cpld soft reset handler + */ + if (unregister_reboot_notifier(&qfx5210_nb)) { + printk(KERN_CRIT "Failed to uregister restart handler\n"); + } + + i2c_del_driver(&qfx5210_64x_psu_driver); +} + +module_init(qfx5210_64x_psu_init); +module_exit(qfx5210_64x_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("qfx5210_64x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/ym2651y.c new file mode 100644 index 000000000000..3ade5684107a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/ym2651y.c @@ -0,0 +1,622 @@ +/* + * An hwmon driver for the 3Y Power YM-2651Y Power Module + * + * Tested and validated on Juniper QFX5210 + * Ciju Rajan K + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END }; + +enum chips { + YM2651, + YM2401, + YM2851, +}; + +/* Each client has this additional data + */ +struct ym2651y_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 capability; /* Register value */ + u16 status_word; /* Register value */ + u8 fan_fault; /* Register value */ + u8 over_temp; /* Register value */ + u16 v_out; /* Register value */ + u16 i_out; /* Register value */ + u16 p_out; /* Register value */ + u16 temp; /* Register value */ + u16 fan_speed; /* Register value */ + u16 fan_duty_cycle[2]; /* Register value */ + u8 fan_dir[4]; /* Register value */ + u8 pmbus_revision; /* Register value */ + u8 mfr_id[10]; /* Register value */ + u8 mfr_model[10]; /* Register value */ + u8 mfr_revsion[3]; /* Register value */ + u16 mfr_vin_min; /* Register value */ + u16 mfr_vin_max; /* Register value */ + u16 mfr_iin_max; /* Register value */ + u16 mfr_iout_max; /* Register value */ + u16 mfr_pin_max; /* Register value */ + u16 mfr_pout_max; /* Register value */ + u16 mfr_vout_min; /* Register value */ + u16 mfr_vout_max; /* Register value */ +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct ym2651y_data *ym2651y_update_device(struct device *dev); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum ym2651y_sysfs_attributes { + PSU_POWER_ON = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD, + PSU_FAN1_FAULT, + PSU_FAN_DIRECTION, + PSU_OVER_TEMP, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, + PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/ + PSU_TEMP1_INPUT, + PSU_FAN1_SPEED, + PSU_FAN1_DUTY_CYCLE, + PSU_PMBUS_REVISION, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_REVISION, + PSU_MFR_VIN_MIN, + PSU_MFR_VIN_MAX, + PSU_MFR_VOUT_MIN, + PSU_MFR_VOUT_MAX, + PSU_MFR_IIN_MAX, + PSU_MFR_IOUT_MAX, + PSU_MFR_PIN_MAX, + PSU_MFR_POUT_MAX +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); +static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); +static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); +static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); + +/*Duplicate nodes for lm-sensors.*/ +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_linear, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); + +static struct attribute *ym2651y_attributes[] = { + &sensor_dev_attr_psu_power_on.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_over_temp.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, + &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, + &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, + /*Duplicate nodes for lm-sensors.*/ + &sensor_dev_attr_curr2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_power2_input.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + NULL +}; + +static ssize_t show_byte(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : + sprintf(buf, "0\n"); +} + +static ssize_t show_word(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u16 status = 0; + + switch (attr->index) { + case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ + status = (data->status_word & 0x40) ? 0 : 1; + break; + case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ + status = (data->status_word & 0x4) >> 2; + break; + case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ + status = (data->status_word & 0x800) ? 0 : 1; + break; + } + + return sprintf(buf, "%d\n", status); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_OUT: + value = data->v_out; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_OUT_UV: + multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/ + /*Passing through*/ + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + case PSU_FAN1_DUTY_CYCLE: + value = data->fan_duty_cycle[0]; + multiplier = 1; + break; + case PSU_MFR_VIN_MIN: + value = data->mfr_vin_min; + break; + case PSU_MFR_VIN_MAX: + value = data->mfr_vin_max; + break; + case PSU_MFR_VOUT_MIN: + value = data->mfr_vout_min; + break; + case PSU_MFR_VOUT_MAX: + value = data->mfr_vout_max; + break; + case PSU_MFR_PIN_MAX: + value = data->mfr_pin_max; + break; + case PSU_MFR_POUT_MAX: + value = data->mfr_pout_max; + break; + case PSU_MFR_IOUT_MAX: + value = data->mfr_iout_max; + break; + case PSU_MFR_IIN_MAX: + value = data->mfr_iin_max; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct ym2651y_data *data = ym2651y_update_device(dev); + + return sprintf(buf, "%d\n", data->over_temp >> 7); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ym2651y_data *data = ym2651y_update_device(dev); + u8 *ptr = NULL; + + switch (attr->index) { + case PSU_FAN_DIRECTION: /* psu_fan_dir */ + ptr = data->fan_dir; + break; + case PSU_MFR_ID: /* psu_mfr_id */ + ptr = data->mfr_id; + break; + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model; + break; + case PSU_MFR_REVISION: /* psu_mfr_revision */ + ptr = data->mfr_revsion; + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group ym2651y_group = { + .attrs = ym2651y_attributes, +}; + +static int ym2651y_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct ym2651y_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int ym2651y_remove(struct i2c_client *client) +{ + struct ym2651y_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &ym2651y_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id ym2651y_id[] = { + { "ym2651", YM2651 }, + { "ym2401", YM2401 }, + { "ym2851", YM2851 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ym2651y_id); + +static struct i2c_driver ym2651y_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ym2651", + }, + .probe = ym2651y_probe, + .remove = ym2651y_remove, + .id_table = ym2651y_id, + .address_list = normal_i2c, +}; + +static int ym2651y_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int ym2651y_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + return i2c_smbus_write_word_data(client, reg, value); +} + +static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; + +abort: + return result; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct ym2651y_data *ym2651y_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ym2651y_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + u8 command; + u8 fan_dir[5] = {0}; + struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, + {0x7d, &data->over_temp}, + {0x81, &data->fan_fault}, + {0x98, &data->pmbus_revision} + }; + struct reg_data_word regs_word[] = { {0x79, &data->status_word}, + {0x8b, &data->v_out}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x8d, &data->temp}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x3c, &(data->fan_duty_cycle[1])}, + {0x90, &data->fan_speed}, + {0xa0, &data->mfr_vin_min}, + {0xa1, &data->mfr_vin_max}, + {0xa2, &data->mfr_iin_max}, + {0xa3, &data->mfr_pin_max}, + {0xa4, &data->mfr_vout_min}, + {0xa5, &data->mfr_vout_max}, + {0xa6, &data->mfr_iout_max}, + {0xa7, &data->mfr_pout_max} + }; + + dev_dbg(&client->dev, "Starting ym2651 update\n"); + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = ym2651y_read_byte(client, regs_byte[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = ym2651y_read_word(client, regs_word[i].reg); + + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read fan_direction */ + command = 0xC3; + status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + } + + strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1); + data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; + + /* Read mfr_id */ + command = 0x99; + status = ym2651y_read_block(client, command, data->mfr_id, + ARRAY_SIZE(data->mfr_id)-1); + data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_model */ + command = 0x9a; + status = ym2651y_read_block(client, command, data->mfr_model, + ARRAY_SIZE(data->mfr_model)-1); + data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + /* Read mfr_revsion */ + command = 0x9b; + status = ym2651y_read_block(client, command, data->mfr_revsion, + ARRAY_SIZE(data->mfr_revsion)-1); + data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; + + if (status < 0) + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +module_i2c_driver(ym2651y_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); +MODULE_LICENSE("GPL"); + + diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/service/qfx5210-platform-init.service b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/service/qfx5210-platform-init.service new file mode 100644 index 000000000000..46377aa9fdc8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/service/qfx5210-platform-init.service @@ -0,0 +1,15 @@ +[Unit] +Description=Juniper QFX5210 initialization service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/local/bin/juniper_qfx5210_util.py install +ExecStart=/usr/local/bin/juniper_qfx5210_monitor.py +RemainAfterExit=yes +StandardOutput=syslog+console +StandardError=syslog+console + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/README b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/README new file mode 100755 index 000000000000..ec9ebe97f0ee --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/README @@ -0,0 +1,117 @@ + +Copyright (c) 2019, Juniper Networks, Inc. +All rights reserved. + +Front panel LEDs +================ +There are 4 system LEDs in the front panel. Master, System, Alarm, & Beacon. +LED controls can be found under /sys/class/leds. The sysfs interface & +colour mappings are as follows: + +For master LED: /sys/class/leds/master/brightness + 0 => off + 1 => green + +For system LED: /sys/class/leds/system/brightness + 0 => off + 1 => green + +For alarm LED: /sys/class/leds/alarm/brightness + 0 => off + 1 => amber + 2 => red + +For beacon LED: /sys/class/leds/beacon/brightness + 0 => off + 1 => blue + +For any of the above LEDs, max_brightness file can tell the maximum value +accepted. + +System FANs +=========== +There are 4 fans and each of the fan has 2 fan modules. Overall there are +8 fans in the system. + +Fan controls can be found in /sys/bus/i2c/devices/17-0068. All the fans +are controlled by one duty cycle value, ranges from 0 to 100 + +Fan duty cycle can be controlled through /sys/bus/i2c/devices/17-0068/pwm1 + +Fan module presence is given by /sys/bus/i2c/devices/17-0068/fan[1-4]_present +file. A value of '1' indicate that fan is present & a value of '0' otherwise. + +Fan rotation direction is given by /sys/bus/i2c/devices/17-0068/fan[1-4]_direction. +A value of '0' indicate the direction is AFO (Front to back airflow) or Airflow +out. A value of '1' indicate that direction is AFI (Back to front airflow) or +Airflow in. + +Fan speed is given by fan[1-4]_input + +Temperature sensors +=================== +There are 6 temperature sensors. The readings are available in +/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input + +System PSUs +=========== +There are two independent PSUs. These are controlled by a dedicated CPLD. +The status registers are mapped under /sys/bus/i2c/devices/9-0050 and +/sys/bus/i2c/devices/10-0053. + +SFPs +==== +There are 64 QSFP+ modules supported in qfx5210 platform. EEPORMs will be +mapped under /sys/bus/i2c/devices/[25-88]-0050/ sysfs directory. + +FEC should be turned on for 100G SR optics and should be turned off for +100G LR optics. If the optic is changed, please update the entry and +reload the configuration. If the FEC mode is not set as per the optic +type the port may not link up or work properly. + +As an example, see this configuration for FEC for 100G SR4 optics in +/etc/sonic/config_db.json + +"Ethernet4": { + "admin_status": "up", + "alias": "Ethernet4", + "fec": "rs", + "index": "1", + "lanes": "65,66,67,68", + "mtu": "9100", + "speed": "100000" + } + +Sensor details +============== +LM75 supported sensor modules will be available under 'sensors' command. +If you want to get all the sensor data including the SFPs & LEDs, you can +invoke 'sudo juniper_qfx5210_util.py show' + +Platform poweroff +================= +Linux poweroff commands such as 'poweroff', 'shutdown', 'halt', etc. will not +power off qfx5210 platform as there are custom CPLDs control the power off +sequences. So acpi poweroff hooks are added for powering off the qfx5210. The +following messages are displayed in the console towards end of poweroff +sequence: + + [ 52.500807] System halt/power_off + [ 52.866331] reboot: Power down + [ 52.903257] pm_power_off: qfx5210_cpld_power_off + +Once the above messages are seen, you can safely remove the power to the system. + +Similarly platform reboot sequences are in place for system reboot. The following +messages are displayed in the console when the system is rebooted: + + [ 6053.163363] System restart: qfx5210_cpld_soft_reset + +Platform monitoring daemon +========================== +“juniper_qfx5210_monitor.py” is the platform monitoring script. +It implements the qfx5210 EM policy. This script will run as system service +and monitor the temperature sensors in every 20 seconds. Based on the EM +policy thresholds, it controls the fan rpm, manage alarm leds, and +shutdown the box. + 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 new file mode 100755 index 000000000000..77eac5234257 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_monitor.py @@ -0,0 +1,601 @@ +#!/usr/bin/env python +# +# Name: juniper_qfx5210_monitor.py version: 1.0 +# +# Description: This file contains the EM implementation for qfx5210 platform +# +# Copyright (c) 2019, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. + +try: + import os + import commands + import subprocess + import logging + import logging.config + import logging.handlers + import time + import glob +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = '/var/log/juniper_qfx5210_monitor' +verbose = False +DEBUG = False + +log_file = '%s.log' % FUNCTION_NAME +log_level = logging.DEBUG + +isPlatformAFI = False +is80PerFlag = True +is60PerFlag = True +isFireThresholdReached = False +isFireThresholdPrint = True +PrevASICValue = 0 +FireThresholdSecsRemaining = 120 + +temp_policy_AFI = { + 0: [[70, 0, 48000], [70, 48000, 53000], [80, 53000, 0], [80, 53000, 58000], [100, 58000, 0], ['Yellow Alarm', 64000, 70000], ['Red Alarm', 70000, 75000], ['Fire Shut Alarm', 75000, 0]], + 1: [[70, 0, 41000], [70, 41000, 47000], [80, 47000, 0], [80, 47000, 52000], [100, 52000, 0], ['Yellow Alarm', 58000, 64000], ['Red Alarm', 64000, 69000], ['Fire Shut Alarm', 69000, 0]], + 2: [[70, 0, 33000], [70, 33000, 39000], [80, 39000, 0], [80, 39000, 45000], [100, 45000, 0], ['Yellow Alarm', 53000, 59000], ['Red Alarm', 59000, 64000], ['Fire Shut Alarm', 64000, 0]], + 3: [[70, 0, 31000], [70, 31000, 36000], [80, 36000, 0], [80, 36000, 42000], [100, 42000, 0], ['Yellow Alarm', 48000, 55000], ['Red Alarm', 55000, 60000], ['Fire Shut Alarm', 60000, 0]], + 4: [[70, 0, 31000], [70, 31000, 36000], [80, 36000, 0], [80, 36000, 42000], [100, 42000, 0], ['Yellow Alarm', 48000, 55000], ['Red Alarm', 55000, 60000], ['Fire Shut Alarm', 60000, 0]], + 5: [[70, 0, 31000], [70, 31000, 36000], [80, 36000, 0], [80, 36000, 43000], [100, 43000, 0], ['Yellow Alarm', 49000, 56000], ['Red Alarm', 56000, 61000], ['Fire Shut Alarm', 61000, 0]], + 6: [[70, 0, 70000], [70, 70000, 78000], [80, 78000, 0], [80, 78000, 86000], [100, 86000, 0], ['Yellow Alarm', 91000, 96000], ['Red Alarm', 96000, 102000], ['Fire Shut Alarm', 102000, 0]], + 7: [[70, 0, 84000], [70, 84000, 91000], [80, 91000, 0], [80, 91000, 98000], [100, 98000, 0], ['Yellow Alarm', 103000, 108000], ['Red Alarm', 108000, 120000], ['Fire Shut Alarm', 120000, 0]], + } + +temp_policy_AFO = { + 0: [[60, 0, 49000], [60, 49000, 55000], [80, 55000, 0], [80, 55000, 62000], [100, 62000, 0], ['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 78000], ['Fire Shut Alarm', 78000, 0]], + 1: [[60, 0, 55000], [60, 55000, 60000], [80, 60000, 0], [80, 60000, 65000], [100, 65000, 0], ['Yellow Alarm', 70000, 76000], ['Red Alarm', 76000, 80000], ['Fire Shut Alarm', 80000, 0]], + 2: [[60, 0, 34000], [60, 34000, 40000], [80, 40000, 0], [80, 40000, 47000], [100, 47000, 0], ['Yellow Alarm', 54000, 60000], ['Red Alarm', 60000, 64000], ['Fire Shut Alarm', 64000, 0]], + 3: [[60, 0, 36000], [60, 36000, 41000], [80, 41000, 0], [80, 41000, 47000], [100, 47000, 0], ['Yellow Alarm', 54000, 60000], ['Red Alarm', 60000, 64000], ['Fire Shut Alarm', 64000, 0]], + 4: [[60, 0, 39000], [60, 39000, 45000], [80, 45000, 0], [80, 45000, 52000], [100, 52000, 0], ['Yellow Alarm', 59000, 65000], ['Red Alarm', 65000, 69000], ['Fire Shut Alarm', 69000, 0]], + 5: [[60, 0, 37000], [60, 37000, 43000], [80, 43000, 0], [80, 43000, 50000], [100, 50000, 0], ['Yellow Alarm', 57000, 63000], ['Red Alarm', 63000, 67000], ['Fire Shut Alarm', 67000, 0]], + 6: [[60, 0, 70000], [60, 70000, 78000], [80, 78000, 0], [80, 78000, 86000], [100, 86000, 0], ['Yellow Alarm', 91000, 96000], ['Red Alarm', 96000, 102000], ['Fire Shut Alarm', 102000, 0]], + 7: [[60, 0, 84000], [60, 84000, 91000], [80, 91000, 0], [80, 91000, 98000], [100, 98000, 0], ['Yellow Alarm', 103000, 108000], ['Red Alarm', 108000, 120000], ['Fire Shut Alarm', 120000, 0]], + } + +class QFX5210_FanUtil(object): + """QFX5210 Platform FanUtil class""" + + FANBASE_VAL_PATH = '/sys/bus/i2c/devices/17-0068/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/17-0068/fan_duty_cycle_percentage' + + def __init__(self): + fan_path = self.FANBASE_VAL_PATH + + def get_fan_duty_cycle(self): + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + logging.error('get_fan_duty_cycle: unable to open file: %s', str(e)) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + logging.error('set_fan_duty_cycle: unable to open file: %s', str(e)) + return False + fan_file.write(str(val)) + fan_file.close() + return True + +class QFX5210_ThermalUtil(object): + """QFX5210 Platform ThermalUtil class""" + + SENSOR_NUM_ON_MAIN_BOARD = 6 + CORETEMP_INDEX_ON_MAIN_BOARD = 6 + SENSOR_CORETEMP_NUM_ON_MAIN_BOARD = 8 + CORETEMP_NUM_ON_MAIN_BOARD = 5 + THERMAL_NUM_RANGE = 8 + SENSOR_NUM_1_IDX = 1 + SENSORS_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + CORETEMP_PATH = '/sys/bus/platform/devices/coretemp.0/hwmon/hwmon1/temp{0}_input' + ALARM_LED_PATH = '/sys/class/leds/alarm/brightness' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _sensor_to_device_path_mapping = {} + + _sensor_to_device_node_mapping = [ + ['18', '48'], + ['18', '49'], + ['18', '4a'], + ['18', '4b'], + ['17', '4d'], + ['17', '4e'], + ] + + _coretemp_to_device_path_mapping = {} + + _coretemp_to_device_node_mapping = [1, 2, 3, 4, 5] + + def __init__(self): + sensor_path = self.SENSORS_PATH + coretemp_path = self.CORETEMP_PATH + for x in range(self.SENSOR_NUM_ON_MAIN_BOARD): + self._sensor_to_device_path_mapping[x+1] = sensor_path.format( + self._sensor_to_device_node_mapping[x][0], + self._sensor_to_device_node_mapping[x][1]) + + for x in range(self.CORETEMP_NUM_ON_MAIN_BOARD): + self._coretemp_to_device_path_mapping[x] = coretemp_path.format( + self._coretemp_to_device_node_mapping[x]) + + + """ Function reads the 5 temp inputs in CORETEMP_PATH + and returns the average of these 5 temp readings """ + def get_coretempValue(self): + sum = 0 + for x in range(self.CORETEMP_NUM_ON_MAIN_BOARD): + sum += self._get_coretemp_node_val(x) + avg = sum/self.CORETEMP_NUM_ON_MAIN_BOARD + return int(avg) + + + """ Function takes the Sensor number as input, constructs the device path, + opens sensor file, reads the temp content from the file and returns the value """ + def _get_sensor_node_val(self, thermal_num): + if thermal_num < self.SENSOR_NUM_1_IDX or thermal_num > self.SENSOR_NUM_ON_MAIN_BOARD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('get_sensor_node_val: unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('get_sensor_node_val: content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except IOError as e: + logging.debug('get_sensor_node_val: unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + """ Function takes the coretemp number as input, constructs the device path, + opens sensor file, reads the temp content from the file and returns the value """ + def _get_coretemp_node_val(self, thermal_num): + + device_path = self.get_coretemp_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('get_coretemp_node_val: unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('get_coretemp_node_val: content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except IOError as e: + logging.debug('get_coretemp_node_val: unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_thermal_to_device_path(self, thermal_num): + return self._sensor_to_device_path_mapping[thermal_num] + + + def get_coretemp_to_device_path(self, thermal_num): + return self._coretemp_to_device_path_mapping[thermal_num] + + + """ Function opens the alarm LED file, reads the content from the file + and returns the value.This value indicates the Brigthness level. + The value of 1 = YELLOW ALARM + The value of 2 = RED ALARM + The value of 0 = NO ALARM """ + def get_alarm_led_brightness(self): + try: + val_file = open(self.ALARM_LED_PATH) + except IOError as e: + logging.error('get_alarm_led_brightness: unable to open file: %s', str(e)) + return False + + content = val_file.readline().rstrip() + val_file.close() + return int(content) + + + """ Function takes the value to set in the alarm LED file as input. + Reads the content from the file and sets the value.This value indicates the Brigthness level. + The value of 1 = YELLOW ALARM + The value of 2 = RED ALARM + The value of 0 = NO ALARM """ + def set_alarm_led_brightness(self, val): + try: + val_file = open(self.ALARM_LED_PATH, 'r+') + except IOError as e: + logging.error('set_alarm_led_brightness: unable to open file: %s', str(e)) + return False + val_file.write(str(val)) + val_file.close() + return True + + + + """ Function is called periodically every 20 secs. It reads the 6 Temp sensors and 1 core Temp sensor and sets + Sensor flags accordingly. Also reads the Fan duty cycle and depending on the FAN duty cycle reading and temp sensor reading, + set the different parameters """ + def getSensorTemp(self): + sum = 0 + global isPlatformAFI + global is80PerFlag + global is60PerFlag + global isFireThresholdReached + global FireThresholdSecsRemaining + global isFireThresholdPrint + global PrevASICValue + #AFI + if (isPlatformAFI == True): + temp_policy = temp_policy_AFI + else: + #AFO + temp_policy = temp_policy_AFO + + """ Dictionary where + key = thermal id index starting from 0. 0 is the sensor 1 ... + value = Different temp ranges """ + SensorFlag = { + 0: [0,0,0,0,0,0,0,0], + 1: [0,0,0,0,0,0,0,0], + 2: [0,0,0,0,0,0,0,0], + 3: [0,0,0,0,0,0,0,0], + 4: [0,0,0,0,0,0,0,0], + 5: [0,0,0,0,0,0,0,0], + 6: [0,0,0,0,0,0,0,0], + 7: [0,0,0,0,0,0,0,0], + } + # if the Firethreshold Flag is set and 120 seconds have elapsed, invoking the "poweroff" to shutdown the box + if (isFireThresholdReached == True): + firethr = FireThresholdSecsRemaining - 20 + if firethr == 0: + logging.critical('CRITICAL: Fire Threshold reached: System is going to shutdown now') + os.system("echo 'CRITICAL: Fire Threshold reached: System is going to shutdown now' > /dev/console") + else: + logging.critical('CRITICAL: Fire Threshold reached: System is going to shutdown in %s seconds', firethr) + os.system("echo 'CRITICAL: Fire Threshold reached: System is going to shutdown in %s seconds' > /dev/console" % firethr) + + FireThresholdSecsRemaining = FireThresholdSecsRemaining - 20 + logging.critical('CRITICAL: Value of FireThresholdSecsRemaining %s seconds', FireThresholdSecsRemaining) + + if (FireThresholdSecsRemaining == 0): + isFireThresholdReached == False + time.sleep(20) + cmd = "poweroff" + os.system(cmd) + + for x in range(self.SENSOR_CORETEMP_NUM_ON_MAIN_BOARD): + if x < self.SENSOR_NUM_ON_MAIN_BOARD: + value = self._get_sensor_node_val(x+1) + logging.debug('Sensor value %d : %s', x, value) + elif x == self.CORETEMP_INDEX_ON_MAIN_BOARD: + value = self.get_coretempValue() + logging.debug('Main Board CORE temp: %s', value) + else: + logging.debug('Reading ASIC Temp value using bcmcmd') + proc = subprocess.Popen("bcmcmd \"show temp\" | grep \"maximum peak temperature\" | awk '{ print $5 }' > /var/log/asic_value 2>&1 & ",shell=True) + time.sleep(2) + cmd = "kill -9 %s"%(proc.pid) + commands.getstatusoutput(cmd) + + if os.stat("/var/log/asic_value").st_size == 0: + value = PrevASICValue + logging.debug('No ASIC Temp file, Prev ASIC Temp Value: %s', PrevASICValue) + else: + with open('/var/log/asic_value', 'r') as f: + value1 = f.readline() + value2 = float(value1) + value1 = value2 * 1000 + value = int(value1) + PrevASICValue = value + logging.debug('Reading from ASIC Temp file: %s', value) + logging.debug('Reading from Prev ASIC Temp Value: %s', PrevASICValue) + + os.system('rm /var/log/asic_value') + + # 60% Duty Cycle for AFO and 70% Duty Cycle for AFI + if value > temp_policy[x][0][1] and value <= temp_policy[x][0][2]: + SensorFlag[x][0] = True + + # 60% Prev Duty Cycle for AFO and 70% Prev Duty Cycle for AFI + elif value > temp_policy[x][1][1] and value < temp_policy[x][1][2]: + SensorFlag[x][1] = True + + # 80% Duty Cycle + elif value == temp_policy[x][2][1]: + SensorFlag[x][2] = True + + #80% Prev Duty Cycle + elif value > temp_policy[x][3][1] and value < temp_policy[x][3][2]: + SensorFlag[x][3] = True + + #100% Duty Cycle + elif value >= temp_policy[x][4][1]: + SensorFlag[x][4] = True + + else: + pass + + # Yellow Alarm + if value >= temp_policy[x][5][1] and value < temp_policy[x][5][2]: + SensorFlag[x][5] = True + + # Red Alarm + elif value >= temp_policy[x][6][1] and value < temp_policy[x][6][2]: + SensorFlag[x][6] = True + + # Fire Shut down + elif value >= temp_policy[x][7][1]: + SensorFlag[x][7] = True + + fan = QFX5210_FanUtil() + # CHECK IF ANY TEMPERATURE SENSORS HAS SET FIRE SHUTDOWN FLAG + if SensorFlag[0][7] or SensorFlag[1][7] or SensorFlag[2][7] or SensorFlag[3][7] or SensorFlag[4][7] or SensorFlag[5][7] or SensorFlag[6][7] or SensorFlag[7][7]: + isFireThresholdReached = True + if (isFireThresholdPrint == True): + logging.critical('CRITICAL: Fire Threshold reached: System is going to shutdown in 120 seconds') + os.system("echo 'CRITICAL: Fire Threshold reached: System is going to shutdown in 120 seconds' > /dev/console") + isFireThresholdPrint = False + + logging.debug('Temp Sensor is set to FIRE SHUTDOWN Flag') + fan.set_fan_duty_cycle(100) + self.set_alarm_led_brightness(2) + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 'RED' ALARM FLAG, IF YES, SET THE ALARM LED TO 'RED' + elif SensorFlag[0][6] or SensorFlag[1][6] or SensorFlag[2][6] or SensorFlag[3][6] or SensorFlag[4][6] or SensorFlag[5][6] or SensorFlag[6][6] or SensorFlag[7][6]: + fan.set_fan_duty_cycle(100) + self.set_alarm_led_brightness(2) + logging.debug('Temp Sensor is set to Red Alarm Flag') + if (isFireThresholdReached == True): + logging.critical('CRITICAL: System Stabilized, not shutting down') + os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console") + FireThresholdSecsRemaining = 120 + isFireThresholdReached = False + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 'YELLOW' ALARM FLAG, IF YES, SET THE ALARM LED TO 'YELLOW' + elif SensorFlag[0][5] or SensorFlag[1][5] or SensorFlag[2][5] or SensorFlag[3][5] or SensorFlag[4][5] or SensorFlag[5][5] or SensorFlag[6][5] or SensorFlag[7][5]: + fan.set_fan_duty_cycle(100) + self.set_alarm_led_brightness(1) + logging.debug('Temp Sensor is set to Yellow Alarm Flag') + if (isFireThresholdReached == True): + logging.critical('CRITICAL: System Stabilized, not shutting down') + os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console") + FireThresholdSecsRemaining = 120 + isFireThresholdReached = False + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 100% DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 100% + elif SensorFlag[0][4] or SensorFlag[1][4] or SensorFlag[2][4] or SensorFlag[3][4] or SensorFlag[4][4] or SensorFlag[5][4] or SensorFlag[6][4] or SensorFlag[7][4]: + fan.set_fan_duty_cycle(100) + value = self.get_alarm_led_brightness() + if ( value > 0): + self.set_alarm_led_brightness(0) + is80PerFlag = False + is60PerFlag = False + logging.debug('Temp Sensor is set to 100% Duty Cycle Flag') + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 80% DUTY CYCLE PREV FLAG, IF YES, SET THE FAN DUTY CYCLE TO 80% + elif SensorFlag[0][3] or SensorFlag[1][3] or SensorFlag[2][3] or SensorFlag[3][3] or SensorFlag[4][3] or SensorFlag[5][3] or SensorFlag[6][3] or SensorFlag[7][3]: + if (is80PerFlag == True): + fan.set_fan_duty_cycle(80) + is80PerFlag = False + else: + pass + + value = self.get_alarm_led_brightness() + if ( value > 0): + self.set_alarm_led_brightness(0) + + if (isFireThresholdReached == True): + logging.critical('CRITICAL: System Stabilized, not shutting down') + os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console") + FireThresholdSecsRemaining = 120 + isFireThresholdReached = False + logging.debug('Temp Sensor is set to 80% Prev Duty Cycle Flag') + + # CHECK IF ANY TEMPERATURE SENSORS HAS SET 80% DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 80% + elif SensorFlag[0][2] or SensorFlag[1][2] or SensorFlag[2][2] or SensorFlag[3][2] or SensorFlag[4][2] or SensorFlag[5][2] or SensorFlag[6][2] or SensorFlag[7][2]: + fan.set_fan_duty_cycle(80) + value = self.get_alarm_led_brightness() + if ( value > 0): + self.set_alarm_led_brightness(0) + is80PerFlag = True + + if (isFireThresholdReached == True): + logging.critical('CRITICAL: System Stabilized, not shutting down') + os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console") + FireThresholdSecsRemaining = 120 + isFireThresholdReached = False + + logging.debug('Temp Sensor is set to 80% Duty Cycle Flag') + + # FOR "AFO" Platform CHECK IF ANY TEMPERATURE SENSORS HAS SET 60% DUTY CYCLE PREV FLAG, IF YES, SET THE FAN DUTY CYCLE TO 60% + # FOR "AFI" Platform CHECK IF ANY TEMPERATURE SENSORS HAS SET 70% DUTY CYCLE PREV FLAG, IF YES, SET THE FAN DUTY CYCLE TO 70% + elif SensorFlag[0][1] or SensorFlag[1][1] or SensorFlag[2][1] or SensorFlag[3][1] or SensorFlag[4][1] or SensorFlag[5][1] or SensorFlag[6][1] or SensorFlag[7][1]: + if (is60PerFlag == True): + if (isPlatformAFI == True): + fan.set_fan_duty_cycle(70) + else: + fan.set_fan_duty_cycle(60) + + is60PerFlag = False + is80PerFlag = True + else: + pass + + value = self.get_alarm_led_brightness() + if ( value > 0): + self.set_alarm_led_brightness(0) + + if (isFireThresholdReached == True): + logging.critical('CRITICAL: System Stabilized, not shutting down') + os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console") + FireThresholdSecsRemaining = 120 + isFireThresholdReached = False + + logging.debug('Temp Sensor is set to 60% Prev Duty Cycle Flag') + + # FOR "AFO" Platform CHECK IF ANY TEMPERATURE SENSORS HAS SET 60% DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 60% + # FOR "AFI" Platform CHECK IF ANY TEMPERATURE SENSORS HAS SET 70% DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 70% + elif SensorFlag[0][0] or SensorFlag[1][0] or SensorFlag[2][0] or SensorFlag[3][0] or SensorFlag[4][0] or SensorFlag[5][0] or SensorFlag[6][0] or SensorFlag[7][0]: + if (isPlatformAFI == True): + fan.set_fan_duty_cycle(70) + else: + fan.set_fan_duty_cycle(60) + value = self.get_alarm_led_brightness() + if ( value > 0): + self.set_alarm_led_brightness(0) + is60PerFlag = True + is80PerFlag = True + + if (isFireThresholdReached == True): + logging.critical('CRITICAL: System Stabilized, not shutting down') + os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console") + FireThresholdSecsRemaining = 120 + isFireThresholdReached = False + logging.debug('Temp Sensor is set to 60% Duty Cycle Flag') + + else: + pass + + + # RESET ALL THE SENSOR FLAGS + for x in range(self.SENSOR_CORETEMP_NUM_ON_MAIN_BOARD): + for y in range(self.THERMAL_NUM_RANGE): + SensorFlag[x][y] = 0 + +class device_monitor(object): + + def __init__(self, log_file, log_level): + global DEBUG + MASTER_LED_PATH = '/sys/class/leds/master/brightness' + SYSTEM_LED_PATH = '/sys/class/leds/system/brightness' + FANTYPE_PATH = '/sys/bus/i2c/devices/17-0068/fan1_direction' + + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + if DEBUG == True: + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + try: + fan_type_file = open(FANTYPE_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + fan_type = -1 + else: + fan_type = fan_type_file.read() + fan_type_file.close() + + + # the return value of get_fan_type is AFO = 0, AFI = 1 and for error condition it is -1 + # In the error condition also, we are making default platform as AFO, to continue with Energy Monitoring + if (int(fan_type) == -1 or int(fan_type) == 0): + logging.debug('FANTYPE_PATH. fan_type %d', int(fan_type)) + if (int(fan_type) == -1): + logging.error('device_monitor: unable to open sys file for fan handling, defaulting it to AFO') + isPlatformAFI = False + else: + isPlatformAFI = True + + master_led_value = 1 + try: + masterLED_file = open(MASTER_LED_PATH, 'r+') + except IOError as e: + logging.error('device_monitor: unable to open Master LED file: %s', str(e)) + return + masterLED_file.write(str(master_led_value)) + masterLED_file.close() + + system_led_value = 1 + try: + systemLED_file = open(SYSTEM_LED_PATH, 'r+') + except IOError as e: + logging.error('device_monitor: unable to open System LED file: %s', str(e)) + return + systemLED_file.write(str(system_led_value)) + systemLED_file.close() + + def manage_device(self): + thermal = QFX5210_ThermalUtil() + thermal.getSensorTemp() + +def main(): + + #Introducing sleep of 150 seconds to wait for all the docker containers to start before starting the EM policy. + time.sleep(150) + monitor = device_monitor(log_file, log_level) + while True: + monitor.manage_device() + time.sleep(20) + +if __name__ == '__main__': + main() + diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py new file mode 100755 index 000000000000..5479c0e04126 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py @@ -0,0 +1,562 @@ +#!/usr/bin/env python +# +# Modified to work on Juniper QFX5210 +# +# Based on accton_as7816_util.py +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import binascii +import logging +import time + + + + +PROJECT_NAME = 'qfx5210_64x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':4, 'fan':4,'thermal':6, 'psu':2, 'sfp':64} +FORCE = 0 +FUNCTION_NAME = '/var/log/juniper_qfx5210_util' + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.DEBUG + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S') + + if DEBUG == True: + print options + print args + print len(sys.argv) + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + DisableWatchDogCmd = '/usr/sbin/i2cset -f -y 0 0x65 0x3 0x04' + # Disable watchdog + try: + os.system(DisableWatchDogCmd) + except OSError: + print 'Error: Execution of "%s" failed', DisableWatchDogCmd + return False + + time.sleep(1) + # Invoking the script which retrieves the data from Board EEPROM and storing in file + EEPROMDataCmd = 'python /usr/share/sonic/device/x86_64-juniper_qfx5210-r0/plugins/qfx5210_eeprom_data.py' + try: + os.system(EEPROMDataCmd) + except OSError: + print 'Error: Execution of "%s" failed', EEPROMDataCmd + return False + + return True + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-32 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-32 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep juniper", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ +'modprobe i2c_dev', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe optoe', +'modprobe juniper_i2c_cpld' , +'modprobe ym2651y' , +'modprobe x86-64-juniper-qfx5210-64x-fan' , +'modprobe x86-64-juniper-qfx5210-64x-leds' , +'modprobe x86-64-juniper-qfx5210-64x-psu' ] + +def driver_install(): + global FORCE + status, output = log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/' +hwmon_types = {'led': ['alarm','system','master','beacon']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['17-0068'] , + 'thermal': ['18-0048','18-0049', '18-004a' , '18-004b', '17-004d', '17-004e'] , + 'psu': ['10-0053','9-0050'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'module_present']} + +sfp_map = [37,38,39,40,42,41,44,43,33,34,35,36,45,46,47,48,49,50,51,52, + 61,62,63,64,53,54,55,56,57,58,59,60,69,70,71,72,77,78,79,80,65, + 66,67,68,73,74,75,76,85,86,87,88,31,32,29,30,81,82,83,84,25,26, + 27,28] + +mknod =[ +'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-1/new_device', +'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-2/new_device', +'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device', +'echo qfx5210_64x_psu1 0x53 > /sys/bus/i2c/devices/i2c-10/new_device', +'echo ym2851 0x5b > /sys/bus/i2c/devices/i2c-10/new_device', +'echo qfx5210_64x_psu2 0x50 > /sys/bus/i2c/devices/i2c-9/new_device', +'echo ym2851 0x58 > /sys/bus/i2c/devices/i2c-9/new_device', +'echo qfx5210_64x_fan 0x68 > /sys/bus/i2c/devices/i2c-17/new_device', +'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device', +'echo lm75 0x4d > /sys/bus/i2c/devices/i2c-17/new_device', +'echo lm75 0x4e > /sys/bus/i2c/devices/i2c-17/new_device', +'echo cpld_qfx5210 0x60 > /sys/bus/i2c/devices/i2c-19/new_device', +'echo cpld_plain 0x62 > /sys/bus/i2c/devices/i2c-20/new_device', +'echo cpld_plain 0x64 > /sys/bus/i2c/devices/i2c-21/new_device', +'echo cpld_plain 0x66 > /sys/bus/i2c/devices/i2c-22/new_device', +'echo cpld_plain 0x65 > /sys/bus/i2c/devices/i2c-0/new_device 2>/dev/null' +] + +def i2c_order_check(): + return 0 + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + path = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device" + status, output =log_os_system("echo optoe1 0x50 > " + path, 1) + if status: + print output + if FORCE == 0: + return status + status, output =log_os_system("echo Port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0076", 0) + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + logging.info('Checking system....') + + status = driver_install() + if status: + if FORCE == 0: + return status + + if not device_exist(): + logging.info('No device, installing....') + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + + return + +def do_uninstall(): + logging.info('Checking system....') + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + logging.info('Removing device....') + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + logging.info('Removing installed driver....') + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + fmt = i2c_prefix+"19-0060/{0}_{1}" + path = fmt.format(nodes[j], k+1) + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + i = int(index)-1 + node = i2c_prefix+ str(sfp_map[i])+ i2c_bus['sfp'][0]+"/"+ 'eeprom' + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system(hex_cmd +" -C "+node, 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0076", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/platform_poweroff b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/platform_poweroff new file mode 100755 index 000000000000..27b23cff93ab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/platform_poweroff @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +# +# Name: platform_poweroff version: 1.0 +# +# Description: This file contains the implementation of qfx5210 poweroff +# sequences +# +# Copyright (c) 2019, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 2 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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. +# +# 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. + +LOGFILE="/var/log/poweroff_log" +TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"` + +retry() +{ + local ret_value=0 + + if [ $# -ne 3 ]; then + echo 'usage: retry ""' + exit 1 + fi + retries=$1 + wait_retry=$2 + command=$3 + for i in `seq 1 $retries`; do + echo "$TIMESTAMP $command" >> $LOGFILE + $command + ret_value=$? + [ $ret_value -eq 0 ] && break + echo "$TIMESTAMP Error: Command Execution failed with $ret_value, waiting to retry..." >> $LOGFILE + sleep $wait_retry + done + return $ret_value +} + + +if [ -f /usr/sbin/i2cset ] && [ -f /usr/sbin/i2cget ]; then + #Check if the CPU CPLD address is present on the bus or not + #0x65 - Azurite CPU CPLD I2C Addr + retry 128 1 "i2cget -y 0 0x65 0x0" + ret_val=$? + if [ $ret_val -ne 0 ]; then + echo "$TIMESTAMP CPU CPLD I2C Addr is not accessible...Terminating the halt.." >> $LOGFILE + return $ret_value + fi + #Initing Halt condition + retry 128 1 "/usr/sbin/i2cset -f -y 0 0x65 0x14 0x00" + ret_val=$? + if [ $ret_val -ne 0 ]; then + echo "$TIMESTAMP Halt Init Failed..." >> $LOGFILE + return $ret_value + fi + #Enable 0x77 MUX's First channel to access 0x76 MUX + retry 128 1 "/usr/sbin/i2cset -f -y 0 0x77 0 0x01" + ret_val=$? + if [ $ret_val -ne 0 ]; then + echo "$TIMESTAMP Mux Level1 enabling failed..." >> $LOGFILE + return $ret_value + fi + #Enable 0x76 MUX's Third channel to access Main Board CPLD @0x60 + retry 128 1 "/usr/sbin/i2cset -f -y 0 0x76 0 0x04" + ret_val=$? + if [ $ret_val -ne 0 ]; then + echo "$TIMESTAMP Mux Level2 enabling failed..." >> $LOGFILE + return $ret_value + fi + + sync + + echo "$TIMESTAMP System is going to Halt now ........" | tee $LOGFILE + #Sleeping for sometime, so that Print can reach to logger + sleep 1 + #Asserting the Halt on Azurite + retry 128 1 "/usr/sbin/i2cset -f -y 0 0x60 0x24 0x00" + ret_val=$? + if [ $ret_val -ne 0 ]; then + echo "$TIMESTAMP Halt command execution failed...Terminating the halt.." | tee $LOGFILE + return $ret_value + fi +fi diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/wrapper-fast-reboot b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/wrapper-fast-reboot new file mode 100755 index 000000000000..e1a32a52472f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/wrapper-fast-reboot @@ -0,0 +1,17 @@ +#!/bin/bash + +# Disable exit on non zero +set +e + +# Unloading this module as it contains the reboot +# notifier hook. When the kexec is invoked with platform +# reset handlers, it results in a cold reboot. Removing +# the reset handlers ensures that kernel does a kexec +# based fast reboot +rmmod x86-64-juniper-qfx5210-64x-psu > /dev/null 2>&1 + +/usr/bin/qfx5210-fast-reboot/fast-reboot $@ + +# Re-load the module if the fast-reboot script returns +# here +modprobe x86-64-juniper-qfx5210-64x-psu > /dev/null 2>&1 diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/wrapper-warm-reboot b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/wrapper-warm-reboot new file mode 100755 index 000000000000..8815efe0acae --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/wrapper-warm-reboot @@ -0,0 +1,17 @@ +#!/bin/bash + +# Disable exit on non zero +set +e + +# Unloading this module as it contains the reboot +# notifier hook. When the kexec is invoked with platform +# reset handlers, it results in a cold reboot. Removing +# the reset handlers ensures that kernel does a kexec +# based fast reboot +rmmod x86-64-juniper-qfx5210-64x-psu > /dev/null 2>&1 + +/usr/bin/qfx5210-warm-reboot/warm-reboot $@ + +# Re-load the module if the warm-reboot script returns +# here +modprobe x86-64-juniper-qfx5210-64x-psu > /dev/null 2>&1 diff --git a/platform/broadcom/sonic-platform-modules-juniper/setup.py b/platform/broadcom/sonic-platform-modules-juniper/setup.py new file mode 100755 index 000000000000..283c00d3860f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize Juniper platforms', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/__init__.py new file mode 100755 index 000000000000..9e1b2e56b1c4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/__init__.py @@ -0,0 +1 @@ +import platform diff --git a/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/chassis.py new file mode 100755 index 000000000000..4f673ab086ba --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/chassis.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# which provide the chassis specific details +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. +# + +try: + import os + import commands + import sys + import time + import syslog + from sonic_platform_base.chassis_base import ChassisBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +SYSLOG_IDENTIFIER = "Juniper-Chassis" + +def log_info(msg): + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_INFO, msg) + syslog.closelog() + +class Chassis(ChassisBase): + + def __init__(self): + ChassisBase.__init__(self) + + def get_parameter_value(self,parameter_name): + try: + with open("/var/run/eeprom", "r") as file: + for item in file: + content = item.split('=') + if content[0] == parameter_name: + return content[1:] + return "False" + except IOError: + print "Error: File not found" + return "False" + + def get_product_name(self): + product_name_list = self.get_parameter_value('Product Name') + if product_name_list: + product_name = ''.join(product_name_list) + return product_name + else: + return False + + + def get_part_number(self): + part_number_list = self.get_parameter_value('Part Number') + if part_number_list: + part_number = ''.join(part_number_list) + return part_number + else: + return False + + + def get_serial(self): + serial_number_list = self.get_parameter_value('Serial Number') + if serial_number_list: + serial_number = ''.join(serial_number_list) + return serial_number + else: + return False + + + def get_base_mac(self): + mac_list = self.get_parameter_value('MAC') + if mac_list: + mac = ''.join(mac_list) + return mac + else: + return False + + + def get_mfg_date(self): + mfgdate_list = self.get_parameter_value('Manufacture Date') + if mfgdate_list: + mfgdate = ''.join(mfgdate_list) + return mfgdate + else: + return False + + def get_deviceversion_name(self): + device_version_list = self.get_parameter_value('Device Version') + if device_version_list: + deviceversion_name = ''.join(device_version_list) + return deviceversion_name + else: + return False + + def get_platform_name(self): + platform_name_list = self.get_parameter_value('Platform Name') + if platform_name_list: + platform_name = ''.join(platform_name_list) + return platform_name + else: + return False + + def get_MACnumber_name(self): + MACnumber_name_list = self.get_parameter_value('Number of MAC Addresses') + if MACnumber_name_list: + MACnumber_name = ''.join(MACnumber_name_list) + return MACnumber_name + else: + return False + + def get_vendor_name(self): + vendor_name_list = self.get_parameter_value('Vendor Name') + if vendor_name_list: + vendor_name = ''.join(vendor_name_list) + return vendor_name + else: + return False + + def get_mfg_name(self): + mfg_name_list = self.get_parameter_value('Manufacture Name') + if mfg_name_list: + mfg_name = ''.join(mfg_name_list) + return mfg_name + else: + return False + + def get_vendorext_name(self): + vendorext_list = self.get_parameter_value('Vendor Extension') + if vendorext_list: + vendorext = ''.join(vendorext_list) + return vendorext + else: + return False + + def get_vendorextIANA_name(self): + vendorext_list = self.get_parameter_value('IANA') + if vendorext_list: + vendorext = ''.join(vendorext_list) + return vendorext + else: + return False + + def get_vendorextASMREV_name(self): + vendorext_list = self.get_parameter_value('Assembly Part Number Rev') + if vendorext_list: + vendorext = ''.join(vendorext_list) + return vendorext + else: + return False + + def get_vendorextASMPartNum_name(self): + vendorext_list = self.get_parameter_value('Assembly Part Number') + if vendorext_list: + vendorext = ''.join(vendorext_list) + return vendorext + else: + return False + + def get_vendorextASMID_name(self): + vendorext_list = self.get_parameter_value('Assembly ID') + if vendorext_list: + vendorext = ''.join(vendorext_list) + return vendorext + else: + return False + + def get_vendorextASMMajNum_name(self): + vendorext_list = self.get_parameter_value('Assembly Major Revision') + if vendorext_list: + vendorext = ''.join(vendorext_list) + return vendorext + else: + return False + + def get_vendorextASMMinNum_name(self): + vendorext_list = self.get_parameter_value('Assembly Minor Revision') + if vendorext_list: + vendorext = ''.join(vendorext_list) + return vendorext + else: + return False + + def get_vendorextCLEI_name(self): + vendorext_list = self.get_parameter_value('CLEI code') + if vendorext_list: + vendorext = ''.join(vendorext_list) + return vendorext + else: + return False + + def get_onieversion_name(self): + onieversion_name_list = self.get_parameter_value('ONIE Version') + if onieversion_name_list: + onieversion_name = ''.join(onieversion_name_list) + return onieversion_name + else: + return False + + def get_crc_name(self): + crc_list = self.get_parameter_value('CRC') + if crc_list: + crc_name = ''.join(crc_list) + return crc_name + else: + return False + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + """ + platform_name = self.get_platform_name() + platform_name = platform_name.replace("\r","") + platform_name = platform_name.replace("\n","") + log_info("Juniper Platform name: {} and {}".format(self.get_platform_name(), platform_name)) + if str(platform_name) == "x86_64-juniper_networks_qfx5210-r0": + log_info("Juniper Platform QFX5210 ") + status, last_reboot_reason = commands.getstatusoutput("i2cget -f -y 0 0x65 0x24") + if (status == 0): + if last_reboot_reason == "0x80": + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) + elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08": + return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None) + elif last_reboot_reason == "0x20": + return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None) + elif last_reboot_reason == "0x10": + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset") + else: + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason") + else: + time.sleep(3) + status, last_reboot_reason = commands.getstatusoutput("i2cget -f -y 0 0x65 0x24") + if last_reboot_reason == "0x80": + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) + elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08": + return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None) + elif last_reboot_reason == "0x20": + return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None) + elif last_reboot_reason == "0x10": + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset") + else: + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason") + + elif str(platform_name) == "x86_64-juniper_networks_qfx5200-r0" : + log_info("Juniper Platform QFX5200 ") + status, major_version = commands.getstatusoutput("busybox devmem 0xFED50000 8") + status, minor_version = commands.getstatusoutput("busybox devmem 0xFED50001 8") + status, last_reboot_reason = commands.getstatusoutput("busybox devmem 0xFED50004 8") + if (status == 0): + if (major_version == "0x31") and (minor_version == "0x03") and (last_reboot_reason == "0x80"): + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) + elif (major_version == "0x31") and (minor_version == "0x05") and (last_reboot_reason == "0x02"): + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) + elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08": + return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None) + elif last_reboot_reason == "0x20": + return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None) + elif last_reboot_reason == "0x10": + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset") + else: + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason") + else: + time.sleep(3) + status, major_version = commands.getstatusoutput("busybox devmem 0xFED50000 8") + status, minor_version = commands.getstatusoutput("busybox devmem 0xFED50001 8") + status, last_reboot_reason = commands.getstatusoutput("busybox devmem 0xFED50004 8") + if (status == 0): + if (major_version == "0x31") and (minor_version == "0x03") and (last_reboot_reason == "0x80"): + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) + elif (major_version == "0x31") and (minor_version == "0x05") and (last_reboot_reason == "0x02"): + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) + elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08": + return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None) + elif last_reboot_reason == "0x20": + return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None) + elif last_reboot_reason == "0x10": + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset") + else: + return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason") + else: + log_info("Error while reading Re-Fpga") + else: + log_info("Unsupported platform") diff --git a/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/platform.py new file mode 100755 index 000000000000..c3a596111d38 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/platform.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definition of SONiC platform API +# which provide the platform specific details +# +# Copyright (c) 2020, Juniper Networks, Inc. +# All rights reserved. +# +# Notice and Disclaimer: This code is licensed to you under the GNU General +# Public License as published by the Free Software Foundation, version 3 or +# any later version. This code is not an official Juniper product. You can +# obtain a copy of the License at +# +# OSS License: +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Third-Party Code: This code may depend on other components under separate +# copyright notice and license terms. Your use of the source code for those +# components is subject to the terms and conditions of the respective license +# as noted in the Third-Party source code file. +# + + +import sys + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +class Platform(PlatformBase): + """ + Juniper Platform-specific class + """ + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-mitac/.gitignore b/platform/broadcom/sonic-platform-modules-mitac/.gitignore new file mode 100644 index 000000000000..38e72f05332d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/.gitignore @@ -0,0 +1,17 @@ +# Build file +ly1200-32x/modules/*.mod.c +ly1200-32x/modules/*.mod.o +ly1200-32x/modules/*.o +ly1200-32x/modules/*.ko +ly1200-32x/modules/*.cmd +ly1200-32x/modules/Module.symvers +ly1200-32x/modules/modules.order +ly1200-32x/modules/.tmp_versions + +debian/sonic-platform-mitac-ly1200-32x/ +debian/sonic-platform-mitac-ly1200-32x.debhelper.log +debian/sonic-platform-mitac-ly1200-32x.postinst.debhelper +debian/sonic-platform-mitac-ly1200-32x.postrm.debhelper +debian/sonic-platform-mitac-ly1200-32x.prerm.debhelper +debian/sonic-platform-mitac-ly1200-32x.substvars +debian/files diff --git a/platform/broadcom/sonic-platform-modules-mitac/LICENSE b/platform/broadcom/sonic-platform-modules-mitac/LICENSE new file mode 100644 index 000000000000..c07c63913aeb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 MiTAC Technology Corporation + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-mitac/README.md b/platform/broadcom/sonic-platform-modules-mitac/README.md new file mode 100644 index 000000000000..d7d47a58debf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/README.md @@ -0,0 +1 @@ +platform drivers of MiTAC products for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/changelog b/platform/broadcom/sonic-platform-modules-mitac/debian/changelog new file mode 100644 index 000000000000..592bb3a71134 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/changelog @@ -0,0 +1,5 @@ +sonic-mitac-platform-modules (1.0) unstable; urgency=low + + * Initial release + + -- MiTAC Network Thu, 01 Sep 2017 11:26:38 +0800 diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/compat b/platform/broadcom/sonic-platform-modules-mitac/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/control b/platform/broadcom/sonic-platform-modules-mitac/debian/control new file mode 100644 index 000000000000..f909c6af9489 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/control @@ -0,0 +1,12 @@ +Source: sonic-mitac-platform-modules +Section: main +Priority: extra +Maintainer: MiTAC network +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-mitac-ly1200-32x +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/rules b/platform/broadcom/sonic-platform-modules-mitac/debian/rules new file mode 100755 index 000000000000..7f9f99827d21 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/rules @@ -0,0 +1,41 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_PRE_NAME := sonic-platform-mitac +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= ly1200-32x + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}\ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin;\ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + mkdir -p debian/$(PACKAGE_PRE_NAME)-$${mod}/opt; \ + cp -rfL $(MOD_SRC_DIR)/$${mod}/opt/* \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/opt; \ + mkdir -p debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/init.d; \ + cp -rfL $(MOD_SRC_DIR)/$${mod}/etc/* \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/etc; \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init new file mode 100644 index 000000000000..d2f7dbf610ab --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init @@ -0,0 +1,51 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ly1200-32x board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + echo 0 > /proc/sys/kernel/perf_cpu_time_max_percent + + /etc/init.d/gpe start + /etc/init.d/i2c_init start + /etc/init.d/sys_polld start + /opt/script/start_watchdog.sh & + /opt/script/start_service.sh & + echo "done." + ;; + +stop) + echo -n "cleaning... " + + /etc/init.d/gpe stop + /etc/init.d/i2c_init stop + /etc/init.d/xcvr_servd stop + /etc/init.d/sys_servd stop + /etc/init.d/sys_polld stop + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-mitac-ly1200-32x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.upstart b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.upstart new file mode 100644 index 000000000000..39533b8226af --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.upstart @@ -0,0 +1,5 @@ +description "SONiC platform service" + +respawn + +exec /etc/init.d/sonic-platform-mitac-ly1200-32x start diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld new file mode 100755 index 000000000000..936f01e8b640 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld @@ -0,0 +1,35 @@ +#!/bin/bash +### BEGIN INIT INFO +# Provides: fan-ctrld +# Required-Start: +# Required-Stop: +# Default-Start: rc.local +# Default-Stop: +# Short-Description: Daemon fan-ctrld +### END INIT INFO + +N=/etc/init.d/fan-ctrld +D_PATH=/opt/fan-ctrl/fan-ctrl + +set -e + +stop_fan_ctrld () { + pkill -f $D_PATH +} + +case "$1" in + start) + $D_PATH & + ;; + stop) + stop_fan_ctrld + ;; + reload|restart|force-reload) + ;; + *) + echo "Usage: $N {start}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe new file mode 100755 index 000000000000..c326442db047 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe @@ -0,0 +1,39 @@ +#! /bin/bash +### BEGIN INIT INFO +# Provides: gpe +# Required-Start: +# Required-Stop: +# Default-Start: rc.local +# Default-Stop: +# Short-Description: Daemon gpe +### END INIT INFO + +# Load kernel modules +load_module () { + if [ `lsmod | grep -c "gpe "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_gpe.ko + fi +} + +remove_module () { + rmmod mitac-ly1200-32x_gpe +} + +case "$1" in + start) + load_module + ;; + stop) + remove_module + ;; + reload|restart|force-reload) + remove_module + load_module + ;; + *) + echo "Usage: $N {start|stop|reload|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init new file mode 100755 index 000000000000..caddfce3325d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init @@ -0,0 +1,214 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup ly1200-32x board. +### END INIT INFO + +I2C_I801_RM_PRINT=0 +I2C_ISMT_RM_PRINT=0 +I2C_I801_INS_PRINT=0 +I2C_ISMT_INS_PRINT=0 +I2C_I801_RM_RETRY=0 +I2C_ISMT_RM_RETRY=0 +I2C_I801_INS_RETRY=0 +I2C_ISMT_INS_RETRY=0 +RETRY=3 + +# process name/id +DAEMON_NAME=`basename $0` +DAEMON_PID="$$" + +# default log file +DEF_LOG_FILE="/var/log/syslog" + +#/* +#* FEATURE: +#* log_msg +#* PURPOSE: +#* log message +#* PARAMETERS: +#* msg (IN) message +#* RETURNS: +#* +#*/ +function log_msg() { + local msg=$1 + + echo -e "`date +"%b %_d %T"` `hostname` $DAEMON_NAME[$DAEMON_PID]: ${msg}" >> ${DEF_LOG_FILE} +} + + +# Load kernel modules +load_modules () { + #----------remove i801 start--------------------- + if [ `lsmod | grep -c "i2c_i801 "` -eq 1 ]; then + rmmod i2c_i801 + while [ `lsmod | grep -c "i2c_i801 "` -eq 1 ] + do + if [ $I2C_I801_RM_PRINT -eq 0 ]; then + I2C_I801_RM_PRINT=1 + log_msg "Wait for i2c_i801 remove." + fi + if [ $I2C_I801_RM_RETRY -lt $RETRY ];then + I2C_I801_RM_RETRY=$((I2C_I801_RM_RETRY + 1)) + else + break + fi + sleep 1 + done + if [ $I2C_I801_RM_PRINT -eq 1 ]; then + log_msg "i2c_i801 remove success." + fi + fi + #----------remove i801 end------------------------ + + + #----------remove ismt start---------------------- + if [ `lsmod | grep -c "i2c_ismt "` -eq 1 ]; then + rmmod i2c_ismt + while [ `lsmod | grep -c "i2c_ismt "` -eq 1 ] + do + if [ $I2C_ISMT_RM_PRINT -eq 0 ]; then + I2C_ISMT_RM_PRINT=1 + log_msg "Wait for i2c_ismt remove." + fi + if [ $I2C_ISMT_RM_RETRY -lt $RETRY ];then + I2C_ISMT_RM_RETRY=$((I2C_ISMT_RM_RETRY + 1)) + else + break + fi + sleep 1 + done + if [ $I2C_ISMT_RM_PRINT -eq 1 ]; then + log_msg "i2c_ismt remove success." + fi + fi + #----------remove ismt end------------------------ + + #----------insert i801 start---------------------- + insmod /lib/modules/`uname -r`/kernel/drivers/i2c/busses/i2c-i801.ko + while [ `lsmod | grep -c "i2c_i801 "` -eq 0 ] + do + if [ $I2C_I801_INS_PRINT -eq 0 ]; then + I2C_I801_INS_PRINT=1 + log_msg "Wait for i2c_i801 insert." + fi + if [ $I2C_I801_INS_RETRY -lt $RETRY ];then + I2C_I801_INS_RETRY=$((I2C_I801_INS_RETRY + 1)) + else + break + fi + sleep 1 + done + if [ $I2C_I801_INS_PRINT -eq 1 ]; then + log_msg "i2c_i801 insert success." + fi + #----------insert i801 end------------------------ + + #----------insert ismt start---------------------- + insmod /lib/modules/`uname -r`/kernel/drivers/i2c/busses/i2c-ismt.ko + while [ `lsmod | grep -c "i2c_ismt "` -eq 0 ] + do + if [ $I2C_ISMT_INS_PRINT -eq 0 ]; then + I2C_ISMT_INS_PRINT=1 + log_msg "Wait for i2c_ismt insert." + fi + if [ $I2C_ISMT_INS_RETRY -lt $RETRY ];then + I2C_ISMT_INS_RETRY=$((I2C_ISMT_INS_RETRY + 1)) + else + break + fi + sleep 1 + done + if [ $I2C_ISMT_INS_PRINT -eq 1 ]; then + log_msg "i2c_ismt insert success." + fi + #----------insert ismt start------------------------ + if [ `lsmod | grep -c "at24 "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/misc/eeprom/at24.ko + fi + if [ `lsmod | grep -c "i2c_mux "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/i2c/i2c-mux.ko + fi + if [ `lsmod | grep -c "i2c_mux_pca954x "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/i2c/muxes/i2c-mux-pca954x.ko + fi + if [ `lsmod | grep -c "lm75 "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/hwmon/lm75.ko + fi + if [ `lsmod | grep -c "max31790 "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/hwmon/max31790.ko + fi + if [ `lsmod | grep -c "sff_8436_eeprom "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/kernel/drivers/misc/eeprom/sff_8436_eeprom.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_fse000 "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_fse000.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_system_cpld "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_system_cpld.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_master_cpld "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_master_cpld.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_slave_cpld "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_slave_cpld.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_cb_i2c "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_cb_i2c.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_sb_i2c "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_sb_i2c.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_pb_i2c "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_pb_i2c.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_fb_i2c "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_fb_i2c.ko + fi + if [ `lsmod | grep -c "mitac_ly1200_32x_fb_module_i2c "` -eq 0 ]; then + insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_fb_module_i2c.ko + fi +} + +# Load i2c_dev modules +load_i2c_dev_modules () { + if [ `lsmod | grep -c "i2c_dev "` -eq 0 ]; then + modprobe i2c_dev + fi +} + +case "$1" in +start) + echo -n "Setting up board... " + load_i2c_dev_modules + load_modules + echo "done." + ;; + +stop) + echo -n "cleaning... " + + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/i2c_init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld new file mode 100755 index 000000000000..1df43346f257 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld @@ -0,0 +1,48 @@ +#!/bin/bash +### BEGIN INIT INFO +# Provides: sys-polld +# Required-Start: +# Required-Stop: +# Default-Start: rc.local +# Default-Stop: +# Short-Description: Daemon sys-polld +### END INIT INFO + +N=/etc/init.d/sys-polld +D_PATH=/opt/system-check/system-check.sh + +set -e + +stop_syspolld () { + local GCOUNT=`ps aux | grep -c "$D_PATH"` + local KILL_COUNT=0 + + while [ $GCOUNT -gt 1 ] + do + local ID=`ps aux | grep "$D_PATH" | head -n 1 | awk -F' ' '{print $2}'` + kill -15 $ID + GCOUNT=`ps aux | grep -c "$D_PATH"` + KILL_COUNT=`expr $KILL_COUNT + 1` + if [ $KILL_COUNT -eq 100 ]; then + echo "Error: kill sys-polld $KILL_COUNT times. stop kill process." + GCOUNT=0 + fi + done +} + +case "$1" in + start) + $D_PATH & + ;; + stop) + stop_syspolld + ;; + reload|restart|force-reload) + ;; + *) + echo "Usage: $N {start}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd new file mode 100755 index 000000000000..09ee087d5db0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd @@ -0,0 +1,28 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: sys-servd +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: rc.local +# Default-Stop: 0 1 6 +# Short-Description: Daemon sys-servd +### END INIT INFO + +# Author: Eddy Weng + +DESC="Service script for /opt/sys-serv/sys-servd" +DAEMON=/opt/sys-serv/sys-servd + +case "$1" in + start) + start-stop-daemon --start --exec $DAEMON + ;; + stop) + start-stop-daemon --stop --name sys-servd + ;; + *) + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd new file mode 100755 index 000000000000..1558614fd43c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd @@ -0,0 +1,28 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: xcvr-servd +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: rc.local +# Default-Stop: 0 1 6 +# Short-Description: Daemon xcvr-servd +### END INIT INFO + +# Author: Yencheng Lin + +DESC="Service script for /opt/xcvr-serv/xcvr-servd" +DAEMON=/opt/xcvr-serv/xcvr-servd + +case "$1" in + start) + start-stop-daemon --start --exec $DAEMON + ;; + stop) + start-stop-daemon --stop --name xcvr-servd + ;; + *) + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd new file mode 120000 index 000000000000..d71f756d3deb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd @@ -0,0 +1 @@ +../init.d/xcvr_servd \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd new file mode 120000 index 000000000000..d71f756d3deb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd @@ -0,0 +1 @@ +../init.d/xcvr_servd \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd new file mode 120000 index 000000000000..d71f756d3deb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd @@ -0,0 +1 @@ +../init.d/xcvr_servd \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/Makefile new file mode 100644 index 000000000000..fc3f88de8eb3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/Makefile @@ -0,0 +1,5 @@ +obj-m:=mitac_ly1200_32x_fb_i2c.o mitac_ly1200_32x_fse000.o \ +mitac_ly1200_32x_master_cpld.o mitac_ly1200_32x_sb_i2c.o \ +mitac_ly1200_32x_system_cpld.o mitac_ly1200_32x_cb_i2c.o \ +mitac_ly1200_32x_fb_module_i2c.o mitac_ly1200_32x_gpe.o \ +mitac_ly1200_32x_pb_i2c.o mitac_ly1200_32x_slave_cpld.o diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/bms_i2c.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/bms_i2c.h new file mode 100644 index 000000000000..dd63607f39c7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/bms_i2c.h @@ -0,0 +1,26 @@ +#ifndef _BMS_I2C_H_ +#define _BMS_I2C_H_ + +const char *bms_i2c_adapter_names[] = { + "SMBus I801 adapter", + "SMBus iSMT adapter", +}; + +enum i2c_adapter_type { + I2C_ADAPTER_I801 = 0, + I2C_ADAPTER_ISMT, +}; + +enum bms_module_switch_bus { + I2C_STAGE1_MUX_CHAN0 = 0, + I2C_STAGE1_MUX_CHAN1, + I2C_STAGE1_MUX_CHAN2, + I2C_STAGE1_MUX_CHAN3, + I2C_STAGE1_MUX_CHAN4, + I2C_STAGE1_MUX_CHAN5, + I2C_STAGE1_MUX_CHAN6, + I2C_STAGE1_MUX_CHAN7, +}; + +#endif /* _BMS_I2C_H_ */ + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_reg.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_reg.h new file mode 100644 index 000000000000..dfdc89dbe57d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_reg.h @@ -0,0 +1,275 @@ +#ifndef __MASTER_CPLD_REG +#define __MASTER_CPLD_REG + +static int master_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); +static int master_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); + +/* generic CPLD read function */ +#define FLD_RAW_RD_FUNC(_reg, _fld, _wdh) static ssize_t \ +master_cpld_##_fld##_raw_read(struct device *dev, struct device_attribute *attr, char *buf) { \ + return master_cpld_raw_read(dev, attr, buf, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* generic CPLD write function */ +#define FLD_RAW_WR_FUNC(_reg, _fld, _wdh) static ssize_t \ +master_cpld_##_fld##_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { \ + return master_cpld_raw_write(dev, attr, buf, count, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* CPLD register definition macros */ +#define REG_DEF(_reg, _off, _wdh) \ +static unsigned int _reg##_offset = (unsigned int)(_off); \ +static unsigned int _reg##_width = (unsigned int)(_wdh); + +/* CPLD register field definition macros, with generic read/write function */ +#define FLD_RAW_RO_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) + +#define FLD_RAW_RW_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) FLD_RAW_WR_FUNC(_reg, _fld, _wdh) + +/* declare master CPLD registers */ +/* register name offset width */ +/* --------------------------------------- ------- ----- */ +REG_DEF( mstr_cpld_rev, 0x00, 8) +REG_DEF( mstr_cpld_gpr, 0x01, 8) +REG_DEF( mb_brd_rev_type, 0x02, 8) +REG_DEF( mstr_srr, 0x03, 8) +REG_DEF( eeprom_wp, 0x04, 8) +REG_DEF( mstr_irq, 0x05, 8) +REG_DEF( system_led, 0x06, 8) +REG_DEF( fan_tray_3_1_led, 0x07, 8) +REG_DEF( fan_tray_6_4_led, 0x08, 8) +REG_DEF( fan_tray_status, 0x09, 8) +REG_DEF( fan_type_status, 0x0A, 8) +REG_DEF( psu_en_status, 0x0B, 8) +REG_DEF( mb_pwr_en_status, 0x0C, 8) +REG_DEF( mb_pwr_status, 0x0D, 8) + +REG_DEF( zqsfp28_present_8_1_status, 0x10, 8) +REG_DEF( zqsfp28_present_16_9_status, 0x11, 8) +REG_DEF( zqsfp28_rst_8_1, 0x12, 8) +REG_DEF( zqsfp28_rst_16_9, 0x13, 8) +REG_DEF( zqsfp28_modsel_8_1, 0x14, 8) +REG_DEF( zqsfp28_modsel_16_9, 0x15, 8) +REG_DEF( zqsfp28_lpmode_8_1, 0x16, 8) +REG_DEF( zqsfp28_lpmode_16_9, 0x17, 8) +REG_DEF( zqsfp28_irq_8_1_status, 0x18, 8) +REG_DEF( zqsfp28_irq_16_9_status, 0x19, 8) +REG_DEF( zqsfp28_irq_msk_8_1_status, 0x1A, 8) +REG_DEF( zqsfp28_irq_msk_16_9_status, 0x1B, 8) + + +/* declare master CPLD register's fields */ +/* register name field name shift width */ +/* ---------------------- ---------------- ------ ----- */ +FLD_RAW_RO_DEF( mstr_cpld_rev, mjr_rev, 4, 4) +FLD_RAW_RO_DEF( mstr_cpld_rev, mnr_rev, 0, 4) + +FLD_RAW_RW_DEF( mstr_cpld_gpr, scrtch_reg, 0, 8) + +FLD_RAW_RO_DEF( mb_brd_rev_type, brd_rev, 4, 4) +FLD_RAW_RO_DEF( mb_brd_rev_type, brd_type, 0, 4) + +FLD_RAW_RW_DEF( mstr_srr, mb_rst, 2, 1) +FLD_RAW_RW_DEF( mstr_srr, npu_rst, 1, 1) +FLD_RAW_RW_DEF( mstr_srr, mgmt_phy_rst, 0, 1) + +FLD_RAW_RW_DEF( eeprom_wp, mb_eeprom_wp, 2, 1) +FLD_RAW_RW_DEF( eeprom_wp, cpld_spi_wp, 1, 1) +FLD_RAW_RW_DEF( eeprom_wp, fan_eeprom_wp, 0, 1) + +FLD_RAW_RW_DEF( mstr_irq, ps2_int_msk, 7, 1) +FLD_RAW_RW_DEF( mstr_irq, ps1_int_msk, 6, 1) +FLD_RAW_RW_DEF( mstr_irq, usb_fault_msk, 5, 1) +FLD_RAW_RW_DEF( mstr_irq, pcie_int_msk, 4, 1) +FLD_RAW_RW_DEF( mstr_irq, fan_alert_int_msk, 3, 1) +FLD_RAW_RO_DEF( mstr_irq, usb_fault, 2, 1) +FLD_RAW_RO_DEF( mstr_irq, pcie_int, 1, 1) +FLD_RAW_RO_DEF( mstr_irq, fan_alert_int, 0, 1) + +FLD_RAW_RW_DEF( system_led, system_led_fld, 6, 2) +FLD_RAW_RW_DEF( system_led, power_led, 4, 2) +FLD_RAW_RW_DEF( system_led, fan_led, 2, 2) +FLD_RAW_RW_DEF( system_led, locate_led, 1, 1) + +FLD_RAW_RW_DEF( fan_tray_3_1_led, led_test, 6, 2) +FLD_RAW_RW_DEF( fan_tray_3_1_led, fan_tray3_led, 4, 2) +FLD_RAW_RW_DEF( fan_tray_3_1_led, fan_tray2_led, 2, 2) +FLD_RAW_RW_DEF( fan_tray_3_1_led, fan_tray1_led, 0, 2) + +FLD_RAW_RW_DEF( fan_tray_6_4_led, fan_tray6_led, 4, 2) +FLD_RAW_RW_DEF( fan_tray_6_4_led, fan_tray5_led, 2, 2) +FLD_RAW_RW_DEF( fan_tray_6_4_led, fan_tray4_led, 0, 2) + +FLD_RAW_RO_DEF( fan_tray_status, fan_tray6_present, 5, 1) +FLD_RAW_RO_DEF( fan_tray_status, fan_tray5_present, 4, 1) +FLD_RAW_RO_DEF( fan_tray_status, fan_tray4_present, 3, 1) +FLD_RAW_RO_DEF( fan_tray_status, fan_tray3_present, 2, 1) +FLD_RAW_RO_DEF( fan_tray_status, fan_tray2_present, 1, 1) +FLD_RAW_RO_DEF( fan_tray_status, fan_tray1_present, 0, 1) + +FLD_RAW_RO_DEF( fan_type_status, fan_type6, 5, 1) +FLD_RAW_RO_DEF( fan_type_status, fan_type5, 4, 1) +FLD_RAW_RO_DEF( fan_type_status, fan_type4, 3, 1) +FLD_RAW_RO_DEF( fan_type_status, fan_type3, 2, 1) +FLD_RAW_RO_DEF( fan_type_status, fan_type2, 1, 1) +FLD_RAW_RO_DEF( fan_type_status, fan_type1, 0, 1) + +FLD_RAW_RO_DEF( psu_en_status, ps1_ps, 7, 1) +FLD_RAW_RO_DEF( psu_en_status, ps1_pg, 6, 1) +FLD_RAW_RO_DEF( psu_en_status, ps1_int, 5, 1) +FLD_RAW_RW_DEF( psu_en_status, ps1_on, 4, 1) +FLD_RAW_RO_DEF( psu_en_status, ps2_ps, 3, 1) +FLD_RAW_RO_DEF( psu_en_status, ps2_pg, 2, 1) +FLD_RAW_RO_DEF( psu_en_status, ps2_int, 1, 1) +FLD_RAW_RW_DEF( psu_en_status, ps2_on, 0, 1) + +FLD_RAW_RW_DEF( mb_pwr_en_status, usb1_vbus_en, 7, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, v5p0_en, 5, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, v3p3_en, 4, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, vcc_1v8_en, 3, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, mac_avs1v_en, 2, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, mac1v_en, 1, 1) +FLD_RAW_RO_DEF( mb_pwr_en_status, vcc_1v25_en, 0, 1) + +FLD_RAW_RO_DEF( mb_pwr_status, vcc_3p3_cpld, 6, 1) +FLD_RAW_RO_DEF( mb_pwr_status, vcc5v_pg, 5, 1) +FLD_RAW_RO_DEF( mb_pwr_status, vcc3v3_pg, 4, 1) +FLD_RAW_RO_DEF( mb_pwr_status, vcc_1v8_pg, 3, 1) +FLD_RAW_RO_DEF( mb_pwr_status, mac_avs1v_pg, 2, 1) +FLD_RAW_RO_DEF( mb_pwr_status, mac1v_pg, 1, 1) +FLD_RAW_RO_DEF( mb_pwr_status, vcc_1v25_pg, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port8_present, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port7_present, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port6_present, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port5_present, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port4_present, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port3_present, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port2_present, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port1_present, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port16_present, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port15_present, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port14_present, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port13_present, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port12_present, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port11_present, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port10_present, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port9_present, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port8_rst, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port7_rst, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port6_rst, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port5_rst, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port4_rst, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port3_rst, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port2_rst, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port1_rst, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port16_rst, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port15_rst, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port14_rst, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port13_rst, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port12_rst, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port11_rst, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port10_rst, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port9_rst, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port8_modsel, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port7_modsel, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port6_modsel, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port5_modsel, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port4_modsel, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port3_modsel, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port2_modsel, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port1_modsel, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port16_modsel, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port15_modsel, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port14_modsel, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port13_modsel, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port12_modsel, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port11_modsel, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port10_modsel, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port9_modsel, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port8_lpmode, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port7_lpmode, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port6_lpmode, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port5_lpmode, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port4_lpmode, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port3_lpmode, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port2_lpmode, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port1_lpmode, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port16_lpmode, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port15_lpmode, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port14_lpmode, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port13_lpmode, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port12_lpmode, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port11_lpmode, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port10_lpmode, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port9_lpmode, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port8_irq_status, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port7_irq_status, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port6_irq_status, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port5_irq_status, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port4_irq_status, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port3_irq_status, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port2_irq_status, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port1_irq_status, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port16_irq_status, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port15_irq_status, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port14_irq_status, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port13_irq_status, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port12_irq_status, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port11_irq_status, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port10_irq_status, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port9_irq_status, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port8_irq_msk, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port7_irq_msk, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port6_irq_msk, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port5_irq_msk, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port4_irq_msk, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port3_irq_msk, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port2_irq_msk, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port1_irq_msk, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port16_irq_msk, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port15_irq_msk, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port14_irq_msk, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port13_irq_msk, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port12_irq_msk, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port11_irq_msk, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port10_irq_msk, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port9_irq_msk, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_present_8_1_status, port_1_8_present, 0, 8) +FLD_RAW_RO_DEF( zqsfp28_present_16_9_status,port_9_16_present, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_rst_8_1, port_1_8_rst, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_rst_16_9, port_9_16_rst, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_modsel_8_1, port_1_8_modsel, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_modsel_16_9, port_9_16_modsel, 0, 8) +FLD_RAW_RO_DEF( zqsfp28_irq_8_1_status, port_1_8_irq_status, 0, 8) +FLD_RAW_RO_DEF( zqsfp28_irq_16_9_status, port_9_16_irq_status,0, 8) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_8_1_status, port_1_8_irq_msk, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_16_9_status,port_9_16_irq_msk, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_lpmode_8_1, port_1_8_lpmode, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_lpmode_16_9, port_9_16_lpmode, 0, 8) + +FLD_RAW_RO_DEF( fan_tray_status, fan_tray1_6_present, 0, 8) +FLD_RAW_RO_DEF( psu_en_status, psu_en_status_fld, 0, 8) +#endif /* __MASTER_CPLD_REG */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h new file mode 100644 index 000000000000..e851ca5fb487 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h @@ -0,0 +1,226 @@ +#ifndef __MASTER_CPLD_SYSFS +#define __MASTER_CPLD_SYSFS + +/* generic CPLD sysfs file definition macros */ +#define SYSFS_RAW_RO_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, master_cpld_##field##_raw_read, NULL); + +#define SYSFS_RAW_RW_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, master_cpld_##field##_raw_read, master_cpld_##field##_raw_write); + +#define SYSFS_MISC_RO_ATTR_DEF(field, _read) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, _read, NULL); + +#define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write); + +#define SYSFS_ATTR_PTR(field) \ +&field.attr + +/* declare master CPLD file system */ +SYSFS_RAW_RO_ATTR_DEF(mjr_rev) +SYSFS_RAW_RO_ATTR_DEF(mnr_rev) + +SYSFS_RAW_RW_ATTR_DEF(scrtch_reg) + +SYSFS_RAW_RO_ATTR_DEF(brd_rev) +SYSFS_RAW_RO_ATTR_DEF(brd_type) + +SYSFS_RAW_RW_ATTR_DEF(mb_rst) +SYSFS_RAW_RW_ATTR_DEF(npu_rst) +SYSFS_RAW_RW_ATTR_DEF(mgmt_phy_rst) + +SYSFS_RAW_RW_ATTR_DEF(mb_eeprom_wp) +SYSFS_RAW_RW_ATTR_DEF(cpld_spi_wp) +SYSFS_RAW_RW_ATTR_DEF(fan_eeprom_wp) + +SYSFS_RAW_RW_ATTR_DEF(ps2_int_msk) +SYSFS_RAW_RW_ATTR_DEF(ps1_int_msk) +SYSFS_RAW_RW_ATTR_DEF(usb_fault_msk) +SYSFS_RAW_RW_ATTR_DEF(pcie_int_msk) +SYSFS_RAW_RW_ATTR_DEF(fan_alert_int_msk) +SYSFS_RAW_RO_ATTR_DEF(usb_fault) +SYSFS_RAW_RO_ATTR_DEF(pcie_int) +SYSFS_RAW_RO_ATTR_DEF(fan_alert_int) + +SYSFS_RAW_RW_ATTR_DEF(system_led_fld) +SYSFS_RAW_RW_ATTR_DEF(power_led) +SYSFS_RAW_RW_ATTR_DEF(fan_led) +SYSFS_RAW_RW_ATTR_DEF(locate_led) + +SYSFS_RAW_RW_ATTR_DEF(led_test) +SYSFS_RAW_RW_ATTR_DEF(fan_tray3_led) +SYSFS_RAW_RW_ATTR_DEF(fan_tray2_led) +SYSFS_RAW_RW_ATTR_DEF(fan_tray1_led) + +SYSFS_RAW_RW_ATTR_DEF(fan_tray6_led) +SYSFS_RAW_RW_ATTR_DEF(fan_tray5_led) +SYSFS_RAW_RW_ATTR_DEF(fan_tray4_led) + +SYSFS_RAW_RO_ATTR_DEF(fan_tray6_present) +SYSFS_RAW_RO_ATTR_DEF(fan_tray5_present) +SYSFS_RAW_RO_ATTR_DEF(fan_tray4_present) +SYSFS_RAW_RO_ATTR_DEF(fan_tray3_present) +SYSFS_RAW_RO_ATTR_DEF(fan_tray2_present) +SYSFS_RAW_RO_ATTR_DEF(fan_tray1_present) + +SYSFS_RAW_RO_ATTR_DEF(fan_type6) +SYSFS_RAW_RO_ATTR_DEF(fan_type5) +SYSFS_RAW_RO_ATTR_DEF(fan_type4) +SYSFS_RAW_RO_ATTR_DEF(fan_type3) +SYSFS_RAW_RO_ATTR_DEF(fan_type2) +SYSFS_RAW_RO_ATTR_DEF(fan_type1) + +SYSFS_RAW_RO_ATTR_DEF(ps1_ps) +SYSFS_RAW_RO_ATTR_DEF(ps1_pg) +SYSFS_RAW_RO_ATTR_DEF(ps1_int) +SYSFS_RAW_RW_ATTR_DEF(ps1_on) +SYSFS_RAW_RO_ATTR_DEF(ps2_ps) +SYSFS_RAW_RO_ATTR_DEF(ps2_pg) +SYSFS_RAW_RO_ATTR_DEF(ps2_int) +SYSFS_RAW_RW_ATTR_DEF(ps2_on) + +SYSFS_RAW_RW_ATTR_DEF(usb1_vbus_en) +SYSFS_RAW_RO_ATTR_DEF(v5p0_en) +SYSFS_RAW_RO_ATTR_DEF(v3p3_en) +SYSFS_RAW_RO_ATTR_DEF(vcc_1v8_en) +SYSFS_RAW_RO_ATTR_DEF(mac_avs1v_en) +SYSFS_RAW_RO_ATTR_DEF(mac1v_en) +SYSFS_RAW_RO_ATTR_DEF(vcc_1v25_en) + +SYSFS_RAW_RO_ATTR_DEF(vcc_3p3_cpld) +SYSFS_RAW_RO_ATTR_DEF(vcc5v_pg) +SYSFS_RAW_RO_ATTR_DEF(vcc3v3_pg) +SYSFS_RAW_RO_ATTR_DEF(vcc_1v8_pg) +SYSFS_RAW_RO_ATTR_DEF(mac_avs1v_pg) +SYSFS_RAW_RO_ATTR_DEF(mac1v_pg) +SYSFS_RAW_RO_ATTR_DEF(vcc_1v25_pg) + +SYSFS_RAW_RO_ATTR_DEF(port8_present) +SYSFS_RAW_RO_ATTR_DEF(port7_present) +SYSFS_RAW_RO_ATTR_DEF(port6_present) +SYSFS_RAW_RO_ATTR_DEF(port5_present) +SYSFS_RAW_RO_ATTR_DEF(port4_present) +SYSFS_RAW_RO_ATTR_DEF(port3_present) +SYSFS_RAW_RO_ATTR_DEF(port2_present) +SYSFS_RAW_RO_ATTR_DEF(port1_present) + +SYSFS_RAW_RO_ATTR_DEF(port16_present) +SYSFS_RAW_RO_ATTR_DEF(port15_present) +SYSFS_RAW_RO_ATTR_DEF(port14_present) +SYSFS_RAW_RO_ATTR_DEF(port13_present) +SYSFS_RAW_RO_ATTR_DEF(port12_present) +SYSFS_RAW_RO_ATTR_DEF(port11_present) +SYSFS_RAW_RO_ATTR_DEF(port10_present) +SYSFS_RAW_RO_ATTR_DEF(port9_present) + +SYSFS_RAW_RW_ATTR_DEF(port8_rst) +SYSFS_RAW_RW_ATTR_DEF(port7_rst) +SYSFS_RAW_RW_ATTR_DEF(port6_rst) +SYSFS_RAW_RW_ATTR_DEF(port5_rst) +SYSFS_RAW_RW_ATTR_DEF(port4_rst) +SYSFS_RAW_RW_ATTR_DEF(port3_rst) +SYSFS_RAW_RW_ATTR_DEF(port2_rst) +SYSFS_RAW_RW_ATTR_DEF(port1_rst) + +SYSFS_RAW_RW_ATTR_DEF(port16_rst) +SYSFS_RAW_RW_ATTR_DEF(port15_rst) +SYSFS_RAW_RW_ATTR_DEF(port14_rst) +SYSFS_RAW_RW_ATTR_DEF(port13_rst) +SYSFS_RAW_RW_ATTR_DEF(port12_rst) +SYSFS_RAW_RW_ATTR_DEF(port11_rst) +SYSFS_RAW_RW_ATTR_DEF(port10_rst) +SYSFS_RAW_RW_ATTR_DEF(port9_rst) + +SYSFS_RAW_RW_ATTR_DEF(port8_modsel) +SYSFS_RAW_RW_ATTR_DEF(port7_modsel) +SYSFS_RAW_RW_ATTR_DEF(port6_modsel) +SYSFS_RAW_RW_ATTR_DEF(port5_modsel) +SYSFS_RAW_RW_ATTR_DEF(port4_modsel) +SYSFS_RAW_RW_ATTR_DEF(port3_modsel) +SYSFS_RAW_RW_ATTR_DEF(port2_modsel) +SYSFS_RAW_RW_ATTR_DEF(port1_modsel) + +SYSFS_RAW_RW_ATTR_DEF(port16_modsel) +SYSFS_RAW_RW_ATTR_DEF(port15_modsel) +SYSFS_RAW_RW_ATTR_DEF(port14_modsel) +SYSFS_RAW_RW_ATTR_DEF(port13_modsel) +SYSFS_RAW_RW_ATTR_DEF(port12_modsel) +SYSFS_RAW_RW_ATTR_DEF(port11_modsel) +SYSFS_RAW_RW_ATTR_DEF(port10_modsel) +SYSFS_RAW_RW_ATTR_DEF(port9_modsel) + +SYSFS_RAW_RW_ATTR_DEF(port8_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port7_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port6_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port5_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port4_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port3_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port2_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port1_lpmode) + +SYSFS_RAW_RW_ATTR_DEF(port16_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port15_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port14_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port13_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port12_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port11_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port10_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port9_lpmode) + +SYSFS_RAW_RO_ATTR_DEF(port8_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port7_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port6_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port5_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port4_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port3_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port2_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port1_irq_status) + +SYSFS_RAW_RO_ATTR_DEF(port16_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port15_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port14_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port13_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port12_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port11_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port10_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port9_irq_status) + +SYSFS_RAW_RW_ATTR_DEF(port8_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port7_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port6_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port5_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port4_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port3_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port2_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port1_irq_msk) + +SYSFS_RAW_RW_ATTR_DEF(port16_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port15_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port14_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port13_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port12_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port11_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port10_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port9_irq_msk) + +SYSFS_RAW_RO_ATTR_DEF(port_1_8_present) +SYSFS_RAW_RO_ATTR_DEF(port_9_16_present) +SYSFS_RAW_RW_ATTR_DEF(port_1_8_rst) +SYSFS_RAW_RW_ATTR_DEF(port_9_16_rst) +SYSFS_RAW_RW_ATTR_DEF(port_1_8_modsel) +SYSFS_RAW_RW_ATTR_DEF(port_9_16_modsel) +SYSFS_RAW_RO_ATTR_DEF(port_1_8_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port_9_16_irq_status) +SYSFS_RAW_RW_ATTR_DEF(port_1_8_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port_9_16_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port_1_8_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port_9_16_lpmode) + +SYSFS_RAW_RO_ATTR_DEF(fan_tray1_6_present) +SYSFS_RAW_RO_ATTR_DEF(psu_en_status_fld) +#endif /* __MASTER_CPLD_SYSFS */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_cb_i2c.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_cb_i2c.c new file mode 100644 index 000000000000..11fffe251785 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_cb_i2c.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include "bms_i2c.h" + +#define BMS_CB_I2C_CLIENT_NUM 5 +#define BMS_CB_ADAPTER_BASE 0 + +static struct i2c_client *bms_cb_clients[BMS_CB_I2C_CLIENT_NUM] = {NULL}; +static int bms_cb_client_index = 0; + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + { + return 0; + } + adapter = to_i2c_adapter(dev); + + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = bms_i2c_adapter_names[type]; + + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + + +static __init struct i2c_client *bms_cb_setup_spd( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("spd", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + + +static __init struct i2c_client *bms_cb_setup_eeprom_24c02( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("24c02", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static __init struct i2c_client *bms_cb_setup_tmp75( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("tmp75", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static __init struct i2c_client *bms_cb_setup_system_cpld(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("system_cpld", 0x31), + }; + + return i2c_new_device(adap, &info); +} + +static int __init bms_cb_setup_devices_i801(void) +{ + struct i2c_adapter *adap; + int adap_num = find_i2c_adapter_num(I2C_ADAPTER_I801); + + if (adap_num < 0) + return adap_num; + + adap = i2c_get_adapter(adap_num); + if (!adap) { + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + goto exit; + } + + bms_cb_clients[bms_cb_client_index++] = bms_cb_setup_spd(adap, 0x50); + bms_cb_clients[bms_cb_client_index++] = bms_cb_setup_spd(adap, 0x52); + bms_cb_clients[bms_cb_client_index++] = bms_cb_setup_tmp75(adap, 0x4e); + +exit: + return 0; +} + +static int __init bms_cb_setup_devices_ismt(void) +{ + struct i2c_adapter *adap; + int adap_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + + if (adap_num < 0) + return adap_num; + + adap = i2c_get_adapter(adap_num); + if (!adap) { + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + return 0; + } + + bms_cb_clients[bms_cb_client_index++] = bms_cb_setup_system_cpld(adap); + bms_cb_clients[bms_cb_client_index++] = bms_cb_setup_eeprom_24c02(adap, 0x56); + return 0; +} + +static int __init bms_cb_i2c_init(void) +{ + /* Initial bms_cb_slients array. */ + memset(bms_cb_clients, 0x0, BMS_CB_I2C_CLIENT_NUM); + + bms_cb_setup_devices_i801(); + mdelay(200); + bms_cb_setup_devices_ismt(); + + return 0; +} + + +static void __exit bms_cb_i2c_exit(void){ + int i; + + for (i=(bms_cb_client_index-1); i>=0; i--) { + if (bms_cb_clients[i]) { + i2c_unregister_device(bms_cb_clients[i]); + bms_cb_clients[i] = NULL; + } + } + + bms_cb_client_index = 0; + +} + + +module_init(bms_cb_i2c_init); +module_exit(bms_cb_i2c_exit); + + +MODULE_DESCRIPTION("mitac_ly1200_32x_cb_i2c driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_i2c.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_i2c.c new file mode 100644 index 000000000000..d228bc481279 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_i2c.c @@ -0,0 +1,153 @@ +#include +#include +#include "bms_i2c.h" + +#define BMS_FB_I2C_CLIENT_NUM 3 + + +static struct i2c_client *bms_fb_clients[BMS_FB_I2C_CLIENT_NUM] = {NULL}; +static int bms_fb_client_index = 0; + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + { + return 0; + } + adapter = to_i2c_adapter(dev); + + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = bms_i2c_adapter_names[type]; + + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static int __init find_i2c_mux_adapter_num(int parent_num, int num) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + char name[48]; + + snprintf(name, sizeof(name), "i2c-%d-mux (chan_id %d)", + parent_num, num); + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static __init struct i2c_client *bms_fb_setup_tmp75( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("tmp75", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static __init struct i2c_client *bms_fb_setup_max31790( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("max31790", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static int __init bms_fb_setup_devices(void) +{ + struct i2c_adapter *adap; + int adap_num; + int parent_num; + + parent_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + if (parent_num < 0) + return parent_num; + + /* Mux chan1 steup */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN1); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_fb_clients[bms_fb_client_index++] = bms_fb_setup_max31790(adap, 0x20); + bms_fb_clients[bms_fb_client_index++] = bms_fb_setup_max31790(adap, 0x23); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN1); + } + + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN2); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_fb_clients[bms_fb_client_index++] = bms_fb_setup_tmp75(adap, 0x4d); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN2); + } + + return 0; +} + +static int __init bms_fb_i2c_init(void) +{ + bms_fb_setup_devices(); + + return 0; +} + +static void __exit bms_fb_i2c_exit(void){ + int i; + + for (i=(bms_fb_client_index-1); i>=0; i--) { + if (bms_fb_clients[i]) { + i2c_unregister_device(bms_fb_clients[i]); + bms_fb_clients[i] = NULL; + } + } + + bms_fb_client_index = 0; + +} + +module_init(bms_fb_i2c_init); +module_exit(bms_fb_i2c_exit); + + +MODULE_DESCRIPTION("mitac_ly1200_32x_fb_i2c driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_module_i2c.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_module_i2c.c new file mode 100644 index 000000000000..174dba197217 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fb_module_i2c.c @@ -0,0 +1,138 @@ +#include +#include +#include "bms_i2c.h" + +#define BMS_FB_MODULE_I2C_CLIENT_NUM 6 + +static struct i2c_client *bms_fb_module_clients[BMS_FB_MODULE_I2C_CLIENT_NUM] = {NULL}; +static int bms_fb_module_client_index = 0; + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + { + return 0; + } + adapter = to_i2c_adapter(dev); + + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = bms_i2c_adapter_names[type]; + + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static int __init find_i2c_mux_adapter_num(int parent_num, int num) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + char name[48]; + + snprintf(name, sizeof(name), "i2c-%d-mux (chan_id %d)", + parent_num, num); + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + + +static __init struct i2c_client *bms_fb_module_setup_eeprom_24c02( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("24c02", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static int __init bms_fb_module_setup_devices(void) +{ + struct i2c_adapter *adap; + int adap_num; + int parent_num; + + parent_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + if (parent_num < 0) + return parent_num; + + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN1); + if (adap_num < 0) + return adap_num; + + adap = i2c_get_adapter(adap_num); + if (!adap) { + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + goto exit; + } + + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x50); + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x51); + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x52); + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x53); + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x54); + bms_fb_module_clients[bms_fb_module_client_index++] = bms_fb_module_setup_eeprom_24c02(adap, 0x55); + +exit: + return 0; +} + +static int __init bms_fb_module_i2c_init(void) +{ + /* Initial bms_sb_slients array. */ + memset(bms_fb_module_clients, 0x0, BMS_FB_MODULE_I2C_CLIENT_NUM); + + bms_fb_module_setup_devices(); + + return 0; +} + +static void __exit bms_fb_module_i2c_exit(void){ + int i; + + for (i=(bms_fb_module_client_index-1); i>=0; i--) { + if (bms_fb_module_clients[i]) { + i2c_unregister_device(bms_fb_module_clients[i]); + bms_fb_module_clients[i] = NULL; + } + } + + bms_fb_module_client_index = 0; + +} + +module_init(bms_fb_module_i2c_init); +module_exit(bms_fb_module_i2c_exit); + + +MODULE_DESCRIPTION("mitac_ly1200_32x_fb_module_i2c driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fse000.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fse000.c new file mode 100644 index 000000000000..69d8c53cd0a9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_fse000.c @@ -0,0 +1,1787 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pmbus.h" +#include + +/* + * Number of additional attribute pointers to allocate + * with each call to krealloc + */ +#define PMBUS_ATTR_ALLOC_SIZE 32 + +/* + * Index into status register array, per status register group + */ +#define PB_STATUS_BASE 0 +#define PB_STATUS_VOUT_BASE (PB_STATUS_BASE + PMBUS_PAGES) +#define PB_STATUS_IOUT_BASE (PB_STATUS_VOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN_BASE (PB_STATUS_IOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN34_BASE (PB_STATUS_FAN_BASE + PMBUS_PAGES) +#define PB_STATUS_TEMP_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES) +#define PB_STATUS_INPUT_BASE (PB_STATUS_TEMP_BASE + PMBUS_PAGES) +#define PB_STATUS_VMON_BASE (PB_STATUS_INPUT_BASE + 1) + +#define PB_NUM_STATUS_REG (PB_STATUS_VMON_BASE + 1) + +#define PMBUS_NAME_SIZE 24 +#define PMBUS_BLOCK_READ_SIZE 32 + +struct pmbus_sensor { + struct pmbus_sensor *next; + char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */ + struct device_attribute attribute; + u8 page; /* page number */ + u16 reg; /* register */ + enum pmbus_sensor_classes class; /* sensor class */ + bool update; /* runtime sensor update needed */ + int data; /* Sensor data. + Negative if there was a read error */ +}; +#define to_pmbus_sensor(_attr) \ + container_of(_attr, struct pmbus_sensor, attribute) + +struct pmbus_st { + char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ + struct sensor_device_attribute attribute; + u16 base; +}; +#define to_pmbus_status(_attr) \ + container_of(_attr, struct pmbus_st, attribute) + +struct pmbus_mfr { + struct pmbus_mfr *next; + char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */ + struct device_attribute attribute; + u8 page; /* page number */ + u16 reg; /* register */ + int data; /* Sensor data. + Negative if there was a read error */ + char data_buf[PMBUS_BLOCK_READ_SIZE]; +}; +#define to_pmbus_mfr(_attr) \ + container_of(_attr, struct pmbus_mfr, attribute) + +struct pmbus_boolean { + char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ + struct sensor_device_attribute attribute; + struct pmbus_sensor *s1; + struct pmbus_sensor *s2; +}; +#define to_pmbus_boolean(_attr) \ + container_of(_attr, struct pmbus_boolean, attribute) + +struct pmbus_label { + char name[PMBUS_NAME_SIZE]; /* sysfs label name */ + struct device_attribute attribute; + char label[PMBUS_NAME_SIZE]; /* label */ +}; +#define to_pmbus_label(_attr) \ + container_of(_attr, struct pmbus_label, attribute) + +struct pmbus_data { + struct device *dev; + struct device *hwmon_dev; + + u32 flags; /* from platform data */ + + int exponent[PMBUS_PAGES]; + /* linear mode: exponent for output voltages */ + + const struct pmbus_driver_info *info; + + int max_attributes; + int num_attributes; + struct attribute_group group; + const struct attribute_group *groups[2]; + + struct pmbus_sensor *sensors; + struct pmbus_mfr *mfr; + + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + /* + * A single status register covers multiple attributes, + * so we keep them all together. + */ + u8 status[PB_NUM_STATUS_REG]; + u8 status_register; + + u8 currpage; +}; + +void pmbus_clear_cache(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + + data->valid = false; +} + +int pmbus_set_page(struct i2c_client *client, u8 page) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int rv = 0; + int newpage; + + if (page != data->currpage) { + rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); + newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); + if (newpage != page) + rv = -EIO; + else + data->currpage = page; + } + return rv; +} + +int pmbus_write_byte(struct i2c_client *client, int page, u8 value) +{ + int rv; + + if (page >= 0) { + rv = pmbus_set_page(client, page); + if (rv < 0) + return rv; + } + + return i2c_smbus_write_byte(client, value); +} + +/* + * _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->write_byte) { + status = info->write_byte(client, page, value); + if (status != -ENODATA) + return status; + } + return pmbus_write_byte(client, page, value); +} + +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word) +{ + int rv; + + rv = pmbus_set_page(client, page); + if (rv < 0) + return rv; + + return i2c_smbus_write_word_data(client, reg, word); +} + +/* + * _pmbus_write_word_data() is similar to pmbus_write_word_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg, + u16 word) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->write_word_data) { + status = info->write_word_data(client, page, reg, word); + if (status != -ENODATA) + return status; + } + if (reg >= PMBUS_VIRT_BASE) + return -ENXIO; + return pmbus_write_word_data(client, page, reg, word); +} + +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg) +{ + int rv; + + rv = pmbus_set_page(client, page); + if (rv < 0) + return rv; + + return i2c_smbus_read_word_data(client, reg); +} + +int pmbus_read_block_data(struct i2c_client *client, u8 reg, u8* value) +{ + return i2c_smbus_read_block_data(client, reg, value); +} + +static int _pmbus_read_block_data(struct i2c_client *client, int page, int reg, u8* value) +{ + int rv; + + rv = pmbus_set_page(client, page); + if (rv < 0) + return rv; + return pmbus_read_block_data(client, reg, value); +} + +/* + * _pmbus_read_word_data() is similar to pmbus_read_word_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->read_word_data) { + status = info->read_word_data(client, page, reg); + if (status != -ENODATA) + return status; + } + if (reg >= PMBUS_VIRT_BASE) + return -ENXIO; + return pmbus_read_word_data(client, page, reg); +} + +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg) +{ + int rv; + + if (page >= 0) { + rv = pmbus_set_page(client, page); + if (rv < 0) + return rv; + } + + return i2c_smbus_read_byte_data(client, reg); +} + +/* + * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if + * a device specific mapping function exists and calls it if necessary. + */ +static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + int status; + + if (info->read_byte_data) { + status = info->read_byte_data(client, page, reg); + if (status != -ENODATA) + return status; + } + return pmbus_read_byte_data(client, page, reg); +} + +static void pmbus_clear_fault_page(struct i2c_client *client, int page) +{ + _pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); +} + +void pmbus_clear_faults(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int i; + + for (i = 0; i < data->info->pages; i++) + pmbus_clear_fault_page(client, i); +} + +static int pmbus_check_status_cml(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int status, status2; + + status = _pmbus_read_byte_data(client, -1, data->status_register); + if (status < 0 || (status & PB_STATUS_CML)) { + status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML); + if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND)) + return -EIO; + } + return 0; +} + +static bool pmbus_check_register(struct i2c_client *client, + int (*func)(struct i2c_client *client, + int page, int reg), + int page, int reg) +{ + int rv; + struct pmbus_data *data = i2c_get_clientdata(client); + + rv = func(client, page, reg); + if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) + rv = pmbus_check_status_cml(client); + pmbus_clear_fault_page(client, -1); + return rv >= 0; +} + +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg) +{ + return pmbus_check_register(client, _pmbus_read_byte_data, page, reg); +} + +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg) +{ + return pmbus_check_register(client, _pmbus_read_word_data, page, reg); +} + +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + + return data->info; +} + +static struct _pmbus_status { + u32 func; + u16 base; + u16 reg; +} pmbus_status[] = { + { PMBUS_HAVE_STATUS_VOUT, PB_STATUS_VOUT_BASE, PMBUS_STATUS_VOUT }, + { PMBUS_HAVE_STATUS_IOUT, PB_STATUS_IOUT_BASE, PMBUS_STATUS_IOUT }, + { PMBUS_HAVE_STATUS_TEMP, PB_STATUS_TEMP_BASE, + PMBUS_STATUS_TEMPERATURE }, + { PMBUS_HAVE_STATUS_FAN12, PB_STATUS_FAN_BASE, PMBUS_STATUS_FAN_12 }, + { PMBUS_HAVE_STATUS_FAN34, PB_STATUS_FAN34_BASE, PMBUS_STATUS_FAN_34 }, +}; + +static struct _pmbus_status_reg { + char name[PMBUS_NAME_SIZE]; + u16 base; + u8 offset; +} pmbus_status_reg[] = { + { "vout_ov_fault", PB_STATUS_VOUT_BASE, PB_VOLTAGE_UV_FAULT}, + { "vout_uv_fault", PB_STATUS_VOUT_BASE, PB_VOLTAGE_OV_FAULT}, + { "ot_fault", PB_STATUS_TEMP_BASE, PB_TEMP_OT_FAULT}, + { "ot_warning", PB_STATUS_TEMP_BASE, PB_TEMP_OT_WARNING}, + { "vin_uv_warning", PB_STATUS_INPUT_BASE, PB_VOLTAGE_UV_WARNING}, + { "vin_uv_fault", PB_STATUS_INPUT_BASE, PB_VOLTAGE_UV_FAULT}, +}; + +static struct _pmbus_mfr_reg { + char name[PMBUS_NAME_SIZE]; + u16 reg; +} pmbus_mfr_reg[] = { + { "mfr_id", PMBUS_MFR_ID}, + { "mfr_model", PMBUS_MFR_MODEL}, + { "mfr_revision", PMBUS_MFR_REVISION}, + { "mfr_location", PMBUS_MFR_LOCATION}, + { "mfr_date", PMBUS_MFR_DATE}, + { "mfr_serial", PMBUS_MFR_SERIAL}, +}; + +static struct pmbus_data *pmbus_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev->parent); + struct pmbus_data *data = i2c_get_clientdata(client); + const struct pmbus_driver_info *info = data->info; + struct pmbus_sensor *sensor; + struct pmbus_mfr *mfr; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + int i, j; + + for (i = 0; i < info->pages; i++) { + data->status[PB_STATUS_BASE + i] + = _pmbus_read_byte_data(client, i, + data->status_register); + for (j = 0; j < ARRAY_SIZE(pmbus_status); j++) { + struct _pmbus_status *s = &pmbus_status[j]; + + if (!(info->func[i] & s->func)) + continue; + data->status[s->base + i] + = _pmbus_read_byte_data(client, i, + s->reg); + } + } + + if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) + data->status[PB_STATUS_INPUT_BASE] + = _pmbus_read_byte_data(client, 0, + PMBUS_STATUS_INPUT); + + if (info->func[0] & PMBUS_HAVE_STATUS_VMON) + data->status[PB_STATUS_VMON_BASE] + = _pmbus_read_byte_data(client, 0, + PMBUS_VIRT_STATUS_VMON); + + for (sensor = data->sensors; sensor; sensor = sensor->next) { + if (!data->valid || sensor->update) + sensor->data + = _pmbus_read_word_data(client, + sensor->page, + sensor->reg); + } + + /* read mfg data */ + for (mfr = data->mfr; mfr; mfr = mfr->next) { + mfr->data = _pmbus_read_block_data(client, mfr->page, mfr->reg, mfr->data_buf); + } + + pmbus_clear_faults(client); + data->last_updated = jiffies; + data->valid = 1; + } + mutex_unlock(&data->update_lock); + return data; +} + +/* + * Convert linear sensor values to milli- or micro-units + * depending on sensor type. + */ +static long pmbus_reg2data_linear(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + s16 exponent; + s32 mantissa; + long val; + + if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ + exponent = data->exponent[sensor->page]; + mantissa = (u16) sensor->data; + } else { /* LINEAR11 */ + exponent = ((s16)sensor->data) >> 11; + mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5; + } + + val = mantissa; + + /* scale result to milli-units for all sensors except fans */ + if (sensor->class != PSC_FAN) + val = val * 1000L; + + /* scale result to micro-units for power sensors */ + if (sensor->class == PSC_POWER) + val = val * 1000L; + + if (exponent >= 0) + val <<= exponent; + else + val >>= -exponent; + + return val; +} + +/* + * Convert direct sensor values to milli- or micro-units + * depending on sensor type. + */ +static long pmbus_reg2data_direct(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + long val = (s16) sensor->data; + long m, b, R; + + m = data->info->m[sensor->class]; + b = data->info->b[sensor->class]; + R = data->info->R[sensor->class]; + + if (m == 0) + return 0; + + /* X = 1/m * (Y * 10^-R - b) */ + R = -R; + /* scale result to milli-units for everything but fans */ + if (sensor->class != PSC_FAN) { + R += 3; + b *= 1000; + } + + /* scale result to micro-units for power sensors */ + if (sensor->class == PSC_POWER) { + R += 3; + b *= 1000; + } + + while (R > 0) { + val *= 10; + R--; + } + while (R < 0) { + val = DIV_ROUND_CLOSEST(val, 10); + R++; + } + + return (val - b) / m; +} + +/* + * Convert VID sensor values to milli- or micro-units + * depending on sensor type. + * We currently only support VR11. + */ +static long pmbus_reg2data_vid(struct pmbus_data *data, + struct pmbus_sensor *sensor) +{ + long val = sensor->data; + + if (val < 0x02 || val > 0xb2) + return 0; + return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100); +} + +static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) +{ + long val; + + switch (data->info->format[sensor->class]) { + case direct: + val = pmbus_reg2data_direct(data, sensor); + break; + case vid: + val = pmbus_reg2data_vid(data, sensor); + break; + case linear: + default: + val = pmbus_reg2data_linear(data, sensor); + break; + } + return val; +} + +#define MAX_MANTISSA (1023 * 1000) +#define MIN_MANTISSA (511 * 1000) + +static u16 pmbus_data2reg_linear(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + s16 exponent = 0, mantissa; + bool negative = false; + + /* simple case */ + if (val == 0) + return 0; + + if (sensor->class == PSC_VOLTAGE_OUT) { + /* LINEAR16 does not support negative voltages */ + if (val < 0) + return 0; + + /* + * For a static exponents, we don't have a choice + * but to adjust the value to it. + */ + if (data->exponent[sensor->page] < 0) + val <<= -data->exponent[sensor->page]; + else + val >>= data->exponent[sensor->page]; + val = DIV_ROUND_CLOSEST(val, 1000); + return val & 0xffff; + } + + if (val < 0) { + negative = true; + val = -val; + } + + /* Power is in uW. Convert to mW before converting. */ + if (sensor->class == PSC_POWER) + val = DIV_ROUND_CLOSEST(val, 1000L); + + /* + * For simplicity, convert fan data to milli-units + * before calculating the exponent. + */ + if (sensor->class == PSC_FAN) + val = val * 1000; + + /* Reduce large mantissa until it fits into 10 bit */ + while (val >= MAX_MANTISSA && exponent < 15) { + exponent++; + val >>= 1; + } + /* Increase small mantissa to improve precision */ + while (val < MIN_MANTISSA && exponent > -15) { + exponent--; + val <<= 1; + } + + /* Convert mantissa from milli-units to units */ + mantissa = DIV_ROUND_CLOSEST(val, 1000); + + /* Ensure that resulting number is within range */ + if (mantissa > 0x3ff) + mantissa = 0x3ff; + + /* restore sign */ + if (negative) + mantissa = -mantissa; + + /* Convert to 5 bit exponent, 11 bit mantissa */ + return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800); +} + +static u16 pmbus_data2reg_direct(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + long m, b, R; + + m = data->info->m[sensor->class]; + b = data->info->b[sensor->class]; + R = data->info->R[sensor->class]; + + /* Power is in uW. Adjust R and b. */ + if (sensor->class == PSC_POWER) { + R -= 3; + b *= 1000; + } + + /* Calculate Y = (m * X + b) * 10^R */ + if (sensor->class != PSC_FAN) { + R -= 3; /* Adjust R and b for data in milli-units */ + b *= 1000; + } + val = val * m + b; + + while (R > 0) { + val *= 10; + R--; + } + while (R < 0) { + val = DIV_ROUND_CLOSEST(val, 10); + R++; + } + + return val; +} + +static u16 pmbus_data2reg_vid(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + val = clamp_val(val, 500, 1600); + + return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625); +} + +static u16 pmbus_data2reg(struct pmbus_data *data, + struct pmbus_sensor *sensor, long val) +{ + u16 regval; + + switch (data->info->format[sensor->class]) { + case direct: + regval = pmbus_data2reg_direct(data, sensor, val); + break; + case vid: + regval = pmbus_data2reg_vid(data, sensor, val); + break; + case linear: + default: + regval = pmbus_data2reg_linear(data, sensor, val); + break; + } + return regval; +} + +/* + * Return boolean calculated from converted data. + * defines a status register index and mask. + * The mask is in the lower 8 bits, the register index is in bits 8..23. + * + * The associated pmbus_boolean structure contains optional pointers to two + * sensor attributes. If specified, those attributes are compared against each + * other to determine if a limit has been exceeded. + * + * If the sensor attribute pointers are NULL, the function returns true if + * (status[reg] & mask) is true. + * + * If sensor attribute pointers are provided, a comparison against a specified + * limit has to be performed to determine the boolean result. + * In this case, the function returns true if v1 >= v2 (where v1 and v2 are + * sensor values referenced by sensor attribute pointers s1 and s2). + * + * To determine if an object exceeds upper limits, specify = . + * To determine if an object exceeds lower limits, specify = . + * + * If a negative value is stored in any of the referenced registers, this value + * reflects an error code which will be returned. + */ +static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b, + int index) +{ + struct pmbus_sensor *s1 = b->s1; + struct pmbus_sensor *s2 = b->s2; + u16 reg = (index >> 8) & 0xffff; + u8 mask = index & 0xff; + int ret, status; + u8 regval; + + status = data->status[reg]; + if (status < 0) + return status; + + regval = status & mask; + if (!s1 && !s2) { + ret = !!regval; + } else if (!s1 || !s2) { + WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2); + return 0; + } else { + long v1, v2; + + if (s1->data < 0) + return s1->data; + if (s2->data < 0) + return s2->data; + + v1 = pmbus_reg2data(data, s1); + v2 = pmbus_reg2data(data, s2); + ret = !!(regval && v1 >= v2); + } + return ret; +} + +static ssize_t pmbus_show_boolean(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct pmbus_boolean *boolean = to_pmbus_boolean(attr); + struct pmbus_data *data = pmbus_update_device(dev); + int val; + + val = pmbus_get_boolean(data, boolean, attr->index); + if (val < 0) + return val; + return snprintf(buf, PAGE_SIZE, "%d\n", val); +} + +static ssize_t pmbus_show_sensor(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct pmbus_data *data = pmbus_update_device(dev); + struct pmbus_sensor *sensor = to_pmbus_sensor(devattr); + + if (sensor->data < 0) + return sensor->data; + + return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor)); +} + +static ssize_t pmbus_show_status(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct pmbus_st *status = to_pmbus_status(attr); + struct pmbus_data *data = pmbus_update_device(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", !!(data->status[status->base] & attr->index)); +} + +static ssize_t pmbus_show_mfr(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct pmbus_mfr *mfr; + + pmbus_update_device(dev); + mfr = to_pmbus_mfr(devattr); + + if (mfr->data < 0) + return mfr->data; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,16,49) + /* mfr->data[0] is data length, we don't want show data length when show command */ + return snprintf(buf, PAGE_SIZE, "%s\n", &mfr->data_buf[1]); +#else + return snprintf(buf, PAGE_SIZE, "%s\n", &mfr->data_buf); +#endif +} + +static ssize_t pmbus_set_sensor(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev->parent); + struct pmbus_data *data = i2c_get_clientdata(client); + struct pmbus_sensor *sensor = to_pmbus_sensor(devattr); + ssize_t rv = count; + long val = 0; + int ret; + u16 regval; + + if (kstrtol(buf, 10, &val) < 0) + return -EINVAL; + + mutex_lock(&data->update_lock); + regval = pmbus_data2reg(data, sensor, val); + ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval); + if (ret < 0) + rv = ret; + else + sensor->data = regval; + mutex_unlock(&data->update_lock); + return rv; +} + +static ssize_t pmbus_show_label(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct pmbus_label *label = to_pmbus_label(da); + + return snprintf(buf, PAGE_SIZE, "%s\n", label->label); +} + +static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr) +{ + if (data->num_attributes >= data->max_attributes - 1) { + int new_max_attrs = data->max_attributes + PMBUS_ATTR_ALLOC_SIZE; + void *new_attrs = krealloc(data->group.attrs, + new_max_attrs * sizeof(void *), + GFP_KERNEL); + if (!new_attrs) + return -ENOMEM; + data->group.attrs = new_attrs; + data->max_attributes = new_max_attrs; + } + + data->group.attrs[data->num_attributes++] = attr; + data->group.attrs[data->num_attributes] = NULL; + return 0; +} + +static void pmbus_dev_attr_init(struct device_attribute *dev_attr, + const char *name, + umode_t mode, + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*store)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count)) +{ + sysfs_attr_init(&dev_attr->attr); + dev_attr->attr.name = name; + dev_attr->attr.mode = mode; + dev_attr->show = show; + dev_attr->store = store; +} + +static void pmbus_attr_init(struct sensor_device_attribute *a, + const char *name, + umode_t mode, + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf), + ssize_t (*store)(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count), + int idx) +{ + pmbus_dev_attr_init(&a->dev_attr, name, mode, show, store); + a->index = idx; +} + +static int pmbus_add_boolean(struct pmbus_data *data, + const char *name, const char *type, int seq, + struct pmbus_sensor *s1, + struct pmbus_sensor *s2, + u16 reg, u8 mask) +{ + struct pmbus_boolean *boolean; + struct sensor_device_attribute *a; + + boolean = devm_kzalloc(data->dev, sizeof(*boolean), GFP_KERNEL); + if (!boolean) + return -ENOMEM; + + a = &boolean->attribute; + + snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s", + name, seq, type); + boolean->s1 = s1; + boolean->s2 = s2; + pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL, + (reg << 8) | mask); + + return pmbus_add_attribute(data, &a->dev_attr.attr); +} + +static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data, + const char *name, const char *type, + int seq, int page, int reg, + enum pmbus_sensor_classes class, + bool update, bool readonly) +{ + struct pmbus_sensor *sensor; + struct device_attribute *a; + + sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return NULL; + a = &sensor->attribute; + + snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s", + name, seq, type); + sensor->page = page; + sensor->reg = reg; + sensor->class = class; + sensor->update = update; + pmbus_dev_attr_init(a, sensor->name, + readonly ? S_IRUGO : S_IRUGO | S_IWUSR, + pmbus_show_sensor, pmbus_set_sensor); + + if (pmbus_add_attribute(data, &a->attr)) + return NULL; + + sensor->next = data->sensors; + data->sensors = sensor; + + return sensor; +} + +static int pmbus_add_status(struct pmbus_data *data, + const char *name, u16 base, + u8 offset) +{ + struct pmbus_st *status; + struct sensor_device_attribute *a; + + status = devm_kzalloc(data->dev, sizeof(*status), GFP_KERNEL); + if (!status) + return -ENOMEM; + + a = &status->attribute; + + snprintf(status->name, sizeof(status->name), "%s", name); + + status->base = base; + + pmbus_attr_init(a, status->name, S_IRUGO, + pmbus_show_status, NULL, offset); + + return pmbus_add_attribute(data, &a->dev_attr.attr); +} + +static struct pmbus_mfr *pmbus_add_mfr(struct pmbus_data *data, + const char *name, + int page, int reg) +{ + struct pmbus_mfr *mfr; + struct device_attribute *a; + + mfr = devm_kzalloc(data->dev, sizeof(*mfr), GFP_KERNEL); + if (!mfr) + return NULL; + a = &mfr->attribute; + + snprintf(mfr->name, sizeof(mfr->name), "%s", name); + mfr->page = page; + mfr->reg = reg; + pmbus_dev_attr_init(a, mfr->name, S_IRUGO, + pmbus_show_mfr, NULL); + + if (pmbus_add_attribute(data, &a->attr)) + return NULL; + + mfr->next = data->mfr; + data->mfr = mfr; + + return mfr; +} + +static int pmbus_add_label(struct pmbus_data *data, + const char *name, int seq, + const char *lstring, int index) +{ + struct pmbus_label *label; + struct device_attribute *a; + + label = devm_kzalloc(data->dev, sizeof(*label), GFP_KERNEL); + if (!label) + return -ENOMEM; + + a = &label->attribute; + + snprintf(label->name, sizeof(label->name), "%s%d_label", name, seq); + if (!index) + strncpy(label->label, lstring, sizeof(label->label) - 1); + else + snprintf(label->label, sizeof(label->label), "%s%d", lstring, + index); + + pmbus_dev_attr_init(a, label->name, S_IRUGO, pmbus_show_label, NULL); + return pmbus_add_attribute(data, &a->attr); +} + +/* + * Search for attributes. Allocate sensors, booleans, and labels as needed. + */ + +/* + * The pmbus_limit_attr structure describes a single limit attribute + * and its associated alarm attribute. + */ +struct pmbus_limit_attr { + u16 reg; /* Limit register */ + u16 sbit; /* Alarm attribute status bit */ + bool update; /* True if register needs updates */ + bool low; /* True if low limit; for limits with compare + functions only */ + const char *attr; /* Attribute name */ + const char *alarm; /* Alarm attribute name */ +}; + +/* + * The pmbus_sensor_attr structure describes one sensor attribute. This + * description includes a reference to the associated limit attributes. + */ +struct pmbus_sensor_attr { + u16 reg; /* sensor register */ + u8 gbit; /* generic status bit */ + u8 nlimit; /* # of limit registers */ + enum pmbus_sensor_classes class;/* sensor class */ + const char *label; /* sensor label */ + bool paged; /* true if paged sensor */ + bool update; /* true if update needed */ + bool compare; /* true if compare function needed */ + u32 func; /* sensor mask */ + u32 sfunc; /* sensor status mask */ + int sbase; /* status base register */ + const struct pmbus_limit_attr *limit;/* limit registers */ +}; + +/* + * Add a set of limit attributes and, if supported, the associated + * alarm attributes. + * returns 0 if no alarm register found, 1 if an alarm register was found, + * < 0 on errors. + */ +static int pmbus_add_limit_attrs(struct i2c_client *client, + struct pmbus_data *data, + const struct pmbus_driver_info *info, + const char *name, int index, int page, + struct pmbus_sensor *base, + const struct pmbus_sensor_attr *attr) +{ + const struct pmbus_limit_attr *l = attr->limit; + int nlimit = attr->nlimit; + int have_alarm = 0; + int i, ret; + struct pmbus_sensor *curr; + + for (i = 0; i < nlimit; i++) { + if (pmbus_check_word_register(client, page, l->reg)) { + curr = pmbus_add_sensor(data, name, l->attr, index, + page, l->reg, attr->class, + attr->update || l->update, + false); + if (!curr) + return -ENOMEM; + if (l->sbit && (info->func[page] & attr->sfunc)) { + ret = pmbus_add_boolean(data, name, + l->alarm, index, + attr->compare ? l->low ? curr : base + : NULL, + attr->compare ? l->low ? base : curr + : NULL, + attr->sbase + page, l->sbit); + if (ret) + return ret; + have_alarm = 1; + } + } + l++; + } + return have_alarm; +} + +static int pmbus_add_sensor_attrs_one(struct i2c_client *client, + struct pmbus_data *data, + const struct pmbus_driver_info *info, + const char *name, + int index, int page, + const struct pmbus_sensor_attr *attr) +{ + struct pmbus_sensor *base; + int ret; + + if (attr->label) { + ret = pmbus_add_label(data, name, index, attr->label, + attr->paged ? page + 1 : 0); + if (ret) + return ret; + } + base = pmbus_add_sensor(data, name, "input", index, page, attr->reg, + attr->class, true, true); + if (!base) + return -ENOMEM; + if (attr->sfunc) { + ret = pmbus_add_limit_attrs(client, data, info, name, + index, page, base, attr); + if (ret < 0) + return ret; + /* + * Add generic alarm attribute only if there are no individual + * alarm attributes, if there is a global alarm bit, and if + * the generic status register for this page is accessible. + */ + if (!ret && attr->gbit && + pmbus_check_byte_register(client, page, + data->status_register)) { + ret = pmbus_add_boolean(data, name, "alarm", index, + NULL, NULL, + PB_STATUS_BASE + page, + attr->gbit); + if (ret) + return ret; + } + } + return 0; +} + +static int pmbus_add_sensor_attrs(struct i2c_client *client, + struct pmbus_data *data, + const char *name, + const struct pmbus_sensor_attr *attrs, + int nattrs) +{ + const struct pmbus_driver_info *info = data->info; + int index, i; + int ret; + + index = 1; + for (i = 0; i < nattrs; i++) { + int page, pages; + + pages = attrs->paged ? info->pages : 1; + for (page = 0; page < pages; page++) { + if (!(info->func[page] & attrs->func)) + continue; + ret = pmbus_add_sensor_attrs_one(client, data, info, + name, index, page, + attrs); + if (ret) + return ret; + index++; + } + attrs++; + } + return 0; +} + +static const struct pmbus_sensor_attr voltage_attributes[] = { + { + .reg = PMBUS_READ_VOUT, + .class = PSC_VOLTAGE_OUT, + .label = "vout", + .paged = true, + .func = PMBUS_HAVE_VOUT, + .sfunc = PMBUS_HAVE_STATUS_VOUT, + .sbase = PB_STATUS_VOUT_BASE, + .gbit = PB_STATUS_VOUT_OV, + } +}; + +static const struct pmbus_limit_attr iout_limit_attrs[] = { + { + .reg = PMBUS_IOUT_OC_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_IOUT_OC_WARNING, + }, { + .reg = PMBUS_IOUT_OC_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_IOUT_OC_FAULT, + } +}; + +static const struct pmbus_sensor_attr current_attributes[] = { + { + .reg = PMBUS_READ_IIN, + .class = PSC_CURRENT_IN, + .label = "iin", + .func = PMBUS_HAVE_IIN, + .sfunc = PMBUS_HAVE_STATUS_INPUT, + .sbase = PB_STATUS_INPUT_BASE, + }, { + .reg = PMBUS_READ_IOUT, + .class = PSC_CURRENT_OUT, + .label = "iout", + .paged = true, + .func = PMBUS_HAVE_IOUT, + .sfunc = PMBUS_HAVE_STATUS_IOUT, + .sbase = PB_STATUS_IOUT_BASE, + .gbit = PB_STATUS_IOUT_OC, + .limit = iout_limit_attrs, + .nlimit = ARRAY_SIZE(iout_limit_attrs), + } +}; + +/* Temperature atributes */ +static const struct pmbus_limit_attr temp_limit_attrs[] = { + { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + } +}; + +static const struct pmbus_limit_attr temp_limit_attrs2[] = { + { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + } +}; + +static const struct pmbus_limit_attr temp_limit_attrs3[] = { + { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + } +}; + +static const struct pmbus_sensor_attr temp_attributes[] = { + { + .reg = PMBUS_READ_TEMPERATURE_1, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs, + .nlimit = ARRAY_SIZE(temp_limit_attrs), + }, { + .reg = PMBUS_READ_TEMPERATURE_2, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP2, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs2, + .nlimit = ARRAY_SIZE(temp_limit_attrs2), + }, { + .reg = PMBUS_READ_TEMPERATURE_3, + .class = PSC_TEMPERATURE, + .paged = true, + .update = true, + .compare = true, + .func = PMBUS_HAVE_TEMP3, + .sfunc = PMBUS_HAVE_STATUS_TEMP, + .sbase = PB_STATUS_TEMP_BASE, + .gbit = PB_STATUS_TEMPERATURE, + .limit = temp_limit_attrs3, + .nlimit = ARRAY_SIZE(temp_limit_attrs3), + } +}; + +static const int pmbus_fan_registers[] = { + PMBUS_READ_FAN_SPEED_1, +}; + +static const int pmbus_fan_config_registers[] = { + PMBUS_FAN_CONFIG_12, +}; + +static const int pmbus_fan_status_registers[] = { + PMBUS_STATUS_FAN_12, +}; + +static const u32 pmbus_fan_flags[] = { + PMBUS_HAVE_FAN12, +}; + +static const u32 pmbus_fan_status_flags[] = { + PMBUS_HAVE_STATUS_FAN12, +}; + +/* Fans */ +static int pmbus_add_fan_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + const struct pmbus_driver_info *info = data->info; + int index = 1; + int page; + int ret; + + for (page = 0; page < info->pages; page++) { + int f; + + for (f = 0; f < ARRAY_SIZE(pmbus_fan_registers); f++) { + int regval; + + if (!(info->func[page] & pmbus_fan_flags[f])) + break; + + if (!pmbus_check_word_register(client, page, + pmbus_fan_registers[f])) + break; + + /* + * Skip fan if not installed. + * Each fan configuration register covers multiple fans, + * so we have to do some magic. + */ + regval = _pmbus_read_byte_data(client, page, + pmbus_fan_config_registers[f]); + if (regval < 0 || + (!(regval & (PB_FAN_1_INSTALLED >> ((f & 1) * 4))))) + continue; + + if (pmbus_add_sensor(data, "fan", "input", index, + page, pmbus_fan_registers[f], + PSC_FAN, true, true) == NULL) + return -ENOMEM; + + /* + * Each fan status register covers multiple fans, + * so we have to do some magic. + */ + if ((info->func[page] & pmbus_fan_status_flags[f]) && + pmbus_check_byte_register(client, + page, pmbus_fan_status_registers[f])) { + int base; + + if (f > 1) /* fan 3, 4 */ + base = PB_STATUS_FAN34_BASE + page; + else + base = PB_STATUS_FAN_BASE + page; + ret = pmbus_add_boolean(data, "fan", + "alarm", index, NULL, NULL, base, + PB_FAN_FAN1_WARNING >> (f & 1)); + if (ret) + return ret; + ret = pmbus_add_boolean(data, "fan", + "fault", index, NULL, NULL, base, + PB_FAN_FAN1_FAULT >> (f & 1)); + if (ret) + return ret; + } + index++; + } + } + return 0; +} + +/* mfr items */ +static int pmbus_add_mfr_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + int page = 0; + int i; + + for(i = 0; i < ARRAY_SIZE(pmbus_mfr_reg);i++){ + + if (pmbus_add_mfr(data, pmbus_mfr_reg[i].name, page, pmbus_mfr_reg[i].reg) == NULL){ + return -ENOMEM; + } + } + + return 0; +} + +/* status items */ +static int pmbus_add_status_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(pmbus_status_reg);i++){ + if (pmbus_add_status(data, pmbus_status_reg[i].name, pmbus_status_reg[i].base, pmbus_status_reg[i].offset)){ + return -ENOMEM; + } + } + + return 0; +} + +static int pmbus_find_attributes(struct i2c_client *client, + struct pmbus_data *data) +{ + int ret; + + /* Voltage sensors */ + ret = pmbus_add_sensor_attrs(client, data, "in", voltage_attributes, + ARRAY_SIZE(voltage_attributes)); + if (ret) + return ret; + + /* Current sensors */ + ret = pmbus_add_sensor_attrs(client, data, "curr", current_attributes, + ARRAY_SIZE(current_attributes)); + if (ret) + return ret; + + /* Temperature sensors */ + ret = pmbus_add_sensor_attrs(client, data, "temp", temp_attributes, + ARRAY_SIZE(temp_attributes)); + if (ret) + return ret; + + /* Fans */ + ret = pmbus_add_fan_attributes(client, data); + if (ret) + return ret; + + /* mfr data */ + ret = pmbus_add_mfr_attributes(client, data); + if (ret) + return ret; + + /* status data */ + ret = pmbus_add_status_attributes(client, data); + return ret; +} + +/* + * Identify chip parameters. + * This function is called for all chips. + */ +static int pmbus_identify_common(struct i2c_client *client, + struct pmbus_data *data, int page) +{ + int vout_mode = -1; + + if (pmbus_check_byte_register(client, page, PMBUS_VOUT_MODE)) + vout_mode = _pmbus_read_byte_data(client, page, + PMBUS_VOUT_MODE); + if (vout_mode >= 0 && vout_mode != 0xff) { + /* + * Not all chips support the VOUT_MODE command, + * so a failure to read it is not an error. + */ + switch (vout_mode >> 5) { + case 0: /* linear mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != linear) + return -ENODEV; + + data->exponent[page] = ((s8)(vout_mode << 3)) >> 3; + break; + case 1: /* VID mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != vid) + return -ENODEV; + break; + case 2: /* direct mode */ + if (data->info->format[PSC_VOLTAGE_OUT] != direct) + return -ENODEV; + break; + default: + return -ENODEV; + } + } + + pmbus_clear_fault_page(client, page); + return 0; +} + +static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, + struct pmbus_driver_info *info) +{ + struct device *dev = &client->dev; + int page, ret; + + /* + * Some PMBus chips don't support PMBUS_STATUS_BYTE, so try + * to use PMBUS_STATUS_WORD instead if that is the case. + * Bail out if both registers are not supported. + */ + data->status_register = PMBUS_STATUS_BYTE; + ret = i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE); + if (ret < 0 || ret == 0xff) { + data->status_register = PMBUS_STATUS_WORD; + ret = i2c_smbus_read_word_data(client, PMBUS_STATUS_WORD); + if (ret < 0 || ret == 0xffff) { + dev_err(dev, "PMBus status register not found\n"); + return -ENODEV; + } + } + + pmbus_clear_faults(client); + + if (info->identify) { + ret = (*info->identify)(client, info); + if (ret < 0) { + dev_err(dev, "Chip identification failed\n"); + return ret; + } + } + + if (info->pages <= 0 || info->pages > PMBUS_PAGES) { + dev_err(dev, "Bad number of PMBus pages: %d\n", info->pages); + return -ENODEV; + } + + /* Current only using page 1 in BMS project */ + info->pages = 1; + + for (page = 0; page < info->pages; page++) { + ret = pmbus_identify_common(client, data, page); + if (ret < 0) { + dev_err(dev, "Failed to identify chip capabilities\n"); + return ret; + } + } + return 0; +} + +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info) +{ + struct device *dev = &client->dev; + const struct pmbus_platform_data *pdata = dev_get_platdata(dev); + struct pmbus_data *data; + int ret; + + if (!info) + return -ENODEV; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE + | I2C_FUNC_SMBUS_BYTE_DATA + | I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->dev = dev; + + if (pdata) + data->flags = pdata->flags; + data->info = info; + + ret = pmbus_init_common(client, data, info); + if (ret < 0) + return ret; + + ret = pmbus_find_attributes(client, data); + if (ret) + goto out_kfree; + + /* + * If there are no attributes, something is wrong. + * Bail out instead of trying to register nothing. + */ + if (!data->num_attributes) { + dev_err(dev, "No attributes found\n"); + ret = -ENODEV; + goto out_kfree; + } + + data->groups[0] = &data->group; + data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + if (IS_ERR(data->hwmon_dev)) { + ret = PTR_ERR(data->hwmon_dev); + dev_err(dev, "Failed to register hwmon device\n"); + goto out_kfree; + } + return 0; + +out_kfree: + kfree(data->group.attrs); + return ret; +} + +int pmbus_do_remove(struct i2c_client *client) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + kfree(data->group.attrs); + return 0; +} + + +/* + * Find sensor groups and status registers on each page. + */ +static void pmbus_find_sensor_groups(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int page; + + /* Sensors detected on page 0 only */ + if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) + info->func[0] |= PMBUS_HAVE_VIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_VCAP)) + info->func[0] |= PMBUS_HAVE_VCAP; + if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN)) + info->func[0] |= PMBUS_HAVE_IIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN)) + info->func[0] |= PMBUS_HAVE_PIN; + if (info->func[0] + && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) + info->func[0] |= PMBUS_HAVE_STATUS_INPUT; + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { + info->func[0] |= PMBUS_HAVE_FAN12; + if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN12; + } + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) { + info->func[0] |= PMBUS_HAVE_FAN34; + if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN34; + } + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) + info->func[0] |= PMBUS_HAVE_TEMP; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) + info->func[0] |= PMBUS_HAVE_TEMP2; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) + info->func[0] |= PMBUS_HAVE_TEMP3; + if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_TEMP3) + && pmbus_check_byte_register(client, 0, + PMBUS_STATUS_TEMPERATURE)) + info->func[0] |= PMBUS_HAVE_STATUS_TEMP; + + /* Sensors detected on all pages */ + for (page = 0; page < info->pages; page++) { + if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) { + info->func[page] |= PMBUS_HAVE_VOUT; + if (pmbus_check_byte_register(client, page, + PMBUS_STATUS_VOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_VOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) { + info->func[page] |= PMBUS_HAVE_IOUT; + if (pmbus_check_byte_register(client, 0, + PMBUS_STATUS_IOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_IOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_POUT)) + info->func[page] |= PMBUS_HAVE_POUT; + } +} + +/* + * Identify chip parameters. + */ +static int pmbus_identify(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int ret = 0; + + if (!info->pages) { + /* + * Check if the PAGE command is supported. If it is, + * keep setting the page number until it fails or until the + * maximum number of pages has been reached. Assume that + * this is the number of pages supported by the chip. + */ + if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { + int page; + + for (page = 1; page < PMBUS_PAGES; page++) { + if (pmbus_set_page(client, page) < 0) + break; + } + pmbus_set_page(client, 0); + info->pages = page; + } else { + info->pages = 1; + } + } + + if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { + int vout_mode; + + vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); + if (vout_mode >= 0 && vout_mode != 0xff) { + switch (vout_mode >> 5) { + case 0: + break; + case 1: + info->format[PSC_VOLTAGE_OUT] = vid; + break; + case 2: + info->format[PSC_VOLTAGE_OUT] = direct; + break; + default: + ret = -ENODEV; + goto abort; + } + } + } + + /* + * We should check if the COEFFICIENTS register is supported. + * If it is, and the chip is configured for direct mode, we can read + * the coefficients from the chip, one set per group of sensor + * registers. + * + * To do this, we will need access to a chip which actually supports the + * COEFFICIENTS command, since the command is too complex to implement + * without testing it. Until then, abort if a chip configured for direct + * mode was detected. + */ + if (info->format[PSC_VOLTAGE_OUT] == direct) { + ret = -ENODEV; + goto abort; + } + + /* Try to find sensor groups */ + pmbus_find_sensor_groups(client, info); +abort: + return ret; +} + +static int pmbus_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pmbus_driver_info *info; + + info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), + GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->pages = id->driver_data; + info->identify = pmbus_identify; + + return pmbus_do_probe(client, id, info); +} + +/* + * Use driver_data to set the number of pages supported by the chip. + */ +static const struct i2c_device_id pmbus_id[] = { + {"fse000", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, pmbus_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver pmbus_driver = { + .driver = { + .name = "fse000", + }, + .probe = pmbus_probe, + .remove = pmbus_do_remove, + .id_table = pmbus_id, +}; + +module_i2c_driver(pmbus_driver); + +MODULE_DESCRIPTION("mitac_ly1200_32x_fse000 driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_gpe.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_gpe.c new file mode 100644 index 000000000000..3ced2b0a399b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_gpe.c @@ -0,0 +1,93 @@ +#include +#include + +#define BMS_GPE_CLASS "bms_acpi" +#define BMS_GPE_DRIVER_NAME "bms_gpe" +#define BMS_GPE_DEVICE_NAME "bms_acpi_gpe" + +static int bms_gpe[] = {0x01, 0x02, 0x47}; +static int bms_gpe_num = sizeof(bms_gpe) / sizeof(bms_gpe[0]); + +static u32 bms_gpe_handler(acpi_handle handle, u32 gpe_num, void *context) +{ + struct acpi_device *device = context; + + acpi_bus_generate_netlink_event(device->pnp.device_class,dev_name(&device->dev), + gpe_num, 0); + return ACPI_INTERRUPT_HANDLED; /* GPE will be disable afterward */ +} + +static int bms_gpe_add(struct acpi_device *device) +{ + acpi_status status; + int i = 0; + char info_str[60] = { 0 }; + char temp[6] = { 0 }; + + if (!device) { + printk("No device of BMS GPE\n"); + return -EINVAL; + } + + strcpy(acpi_device_name(device), BMS_GPE_DEVICE_NAME); + strcpy(acpi_device_class(device), BMS_GPE_CLASS); + + strncat(info_str, "Initialized GPE list = ", 23); + for (i = 0; i < bms_gpe_num; i++) { + status = acpi_install_gpe_handler(NULL, bms_gpe[i], + ACPI_GPE_LEVEL_TRIGGERED, + &bms_gpe_handler, device); + if (status != AE_OK) { + printk("Fail to claim BMS GPE%X (code:0x%X)\n",bms_gpe[i],status); + return -EINVAL; + } + snprintf(temp, sizeof(temp), "0x%.2X ", bms_gpe[i]); + strncat(info_str, temp, 6); + } + + dev_info(&device->dev, "%s.\n", info_str); + + return 0; +} + +static int bms_gpe_remove(struct acpi_device *device) +{ + int i = 0; + for (i = 0; i < bms_gpe_num; i++) { + acpi_remove_gpe_handler(NULL, bms_gpe[i], &bms_gpe_handler); + } + return 0; +} + +static const struct acpi_device_id bms_acpi_device_ids[] = { + { "PNP0C01", 0 }, + { /* END OF LIST */ } +}; + +static struct acpi_driver bms_gpe_driver = { + .name = BMS_GPE_DRIVER_NAME, + .class = BMS_GPE_CLASS, + .ids = bms_acpi_device_ids, + .ops = { + .add = bms_gpe_add, + .remove = bms_gpe_remove, + }, +}; + +static int __init bms_gpe_init(void) +{ + printk(KERN_INFO "%s: init.\n", __FUNCTION__); + return acpi_bus_register_driver(&bms_gpe_driver); +} + +static void __exit bms_gpe_exit(void) +{ + printk(KERN_INFO "%s: exit.\n", __FUNCTION__); + acpi_bus_unregister_driver(&bms_gpe_driver); +} + +module_init(bms_gpe_init); +module_exit(bms_gpe_exit); +MODULE_AUTHOR("Yencheng Lin "); +MODULE_DESCRIPTION("mitac_ly1200_32x_gpe driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_master_cpld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_master_cpld.c new file mode 100644 index 000000000000..921a2ea424a3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_master_cpld.c @@ -0,0 +1,503 @@ +#include +#include + +#include "master_cpld_reg.h" +#include "master_cpld_sysfs.h" + +static int debug_flag = 0; + +struct master_cpld_data { + struct mutex lock; + + struct i2c_client *client; + struct device_attribute bin; +}; + + +static const struct i2c_device_id master_cpld_ids[] = { + { "master_cpld", 0 }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, master_cpld_ids); + +static int master_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + unsigned int reg_val = 0, fld_val; + static int debug_flag; + struct master_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int err; + + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + mutex_lock(&data->lock); + if ((err = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, err); + return err; + } + reg_val = err; + if (debug_flag) { + printk("%s: reg_offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + if (fld_width == reg_width) {fld_val = reg_val & fld_mask;} + else {fld_val = (reg_val >> fld_shift) & fld_mask;} + return sprintf(buf, "0x%x\n", fld_val); +} + +static int master_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + int ret_code; + unsigned int reg_val, fld_val; + unsigned long val; + static int debug_flag; + struct master_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + /* Parse buf and store to fld_val */ + if ((ret_code = kstrtoul(buf, 16, &val))){ + printk("%s: Conversion value = %s failed, errno = %d.\n", reg_name, buf, ret_code); + return ret_code; + } + fld_val = (unsigned int)val; + mutex_lock(&data->lock); + if ((ret_code = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* Handle CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + reg_val = ret_code; + if (debug_flag) { + printk("%s: offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + if (fld_width == reg_width) {reg_val = fld_val & fld_mask;} + else {reg_val = (reg_val & ~(fld_mask << fld_shift)) | + ((fld_val & (fld_mask)) << fld_shift);} + if ((ret_code = i2c_smbus_write_byte_data(client, (u8)reg_offset, (u8)reg_val)) != 0) { + /* Handle CPLD write error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c write failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + else if (debug_flag) { + printk("%s: offset = %d, width = %d, new value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + return count; +} + +/*--------------------special file for debug---------------------- */ +static ssize_t master_cpld_debug_read(struct device *dev, struct device_attribute *attr, + char *buf){ + + return sprintf(buf, "%d\n", debug_flag); +} + + +static ssize_t master_cpld_debug_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int temp; + int error; + + error = kstrtoint(buf, 10, &temp); + if (error){ + printk(KERN_INFO "%s: Conversion value = %s failed.\n", __FUNCTION__, buf); + return count; + } + debug_flag = temp; + + if(debug_flag) + printk("%s, debug_flag = %d\n", __FUNCTION__, debug_flag); + + return count; +} +SYSFS_MISC_RW_ATTR_DEF(debug, master_cpld_debug_read, master_cpld_debug_write) + + + + +/* ----------------define port group---------------------------- */ +static struct attribute *port1_attributes[] = { + SYSFS_ATTR_PTR(port1_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port1_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port1_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port1_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port1_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port1_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + + +static struct attribute *port2_attributes[] = { + SYSFS_ATTR_PTR(port2_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port2_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port2_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port2_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port2_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port2_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + + +static struct attribute *port3_attributes[] = { + SYSFS_ATTR_PTR(port3_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port3_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port3_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port3_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port3_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port3_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port4_attributes[] = { + SYSFS_ATTR_PTR(port4_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port4_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port4_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port4_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port4_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port4_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port5_attributes[] = { + SYSFS_ATTR_PTR(port5_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port5_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port5_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port5_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port5_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port5_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port6_attributes[] = { + SYSFS_ATTR_PTR(port6_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port6_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port6_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port6_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port6_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port6_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port7_attributes[] = { + SYSFS_ATTR_PTR(port7_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port7_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port7_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port7_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port7_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port7_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port8_attributes[] = { + SYSFS_ATTR_PTR(port8_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port8_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port8_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port8_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port8_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port8_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + NULL +}; + +static struct attribute *port9_attributes[] = { + SYSFS_ATTR_PTR(port9_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port9_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port9_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port9_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port9_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port9_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port10_attributes[] = { + SYSFS_ATTR_PTR(port10_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port10_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port10_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port10_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port10_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port10_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port11_attributes[] = { + SYSFS_ATTR_PTR(port11_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port11_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port11_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port11_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port11_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port11_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port12_attributes[] = { + SYSFS_ATTR_PTR(port12_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port12_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port12_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port12_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port12_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port12_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port13_attributes[] = { + SYSFS_ATTR_PTR(port13_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port13_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port13_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port13_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port13_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port13_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port14_attributes[] = { + SYSFS_ATTR_PTR(port14_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port14_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port14_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port14_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port14_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port14_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port15_attributes[] = { + SYSFS_ATTR_PTR(port15_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port15_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port15_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port15_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port15_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port15_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + +static struct attribute *port16_attributes[] = { + SYSFS_ATTR_PTR(port16_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port16_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port16_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port16_lpmode), /* register: zqsfp28_lpmode_16_9 */ + SYSFS_ATTR_PTR(port16_irq_status), /* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port16_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + NULL +}; + + +static const struct attribute_group master_cpld_port_group[] = { + {.attrs = port1_attributes, + .name = "port1",}, + {.attrs = port2_attributes, + .name = "port2",}, + {.attrs = port3_attributes, + .name = "port3",}, + {.attrs = port4_attributes, + .name = "port4",}, + {.attrs = port5_attributes, + .name = "port5",}, + {.attrs = port6_attributes, + .name = "port6",}, + {.attrs = port7_attributes, + .name = "port7",}, + {.attrs = port8_attributes, + .name = "port8",}, + {.attrs = port9_attributes, + .name = "port9",}, + {.attrs = port10_attributes, + .name = "port10",}, + {.attrs = port11_attributes, + .name = "port11",}, + {.attrs = port12_attributes, + .name = "port12",}, + {.attrs = port13_attributes, + .name = "port13",}, + {.attrs = port14_attributes, + .name = "port14",}, + {.attrs = port15_attributes, + .name = "port15",}, + {.attrs = port16_attributes, + .name = "port16",} +}; + +/* ----------------define misc group---------------------------- */ +static struct attribute *misc_attributes[] = { + SYSFS_ATTR_PTR(mjr_rev), /* register: mstr_cpld_rev */ + SYSFS_ATTR_PTR(mnr_rev), /* register: mstr_cpld_rev */ + + SYSFS_ATTR_PTR(scrtch_reg), /* register: mstr_cpld_gpr */ + + SYSFS_ATTR_PTR(brd_rev), /* register: mb_brd_rev_type */ + SYSFS_ATTR_PTR(brd_type), /* register: mb_brd_rev_type */ + + SYSFS_ATTR_PTR(mb_rst), /* register: mstr_srr */ + SYSFS_ATTR_PTR(npu_rst), /* register: mstr_srr */ + SYSFS_ATTR_PTR(mgmt_phy_rst), /* register: mstr_srr */ + + SYSFS_ATTR_PTR(mb_eeprom_wp), /* register: eeprom_wp */ + SYSFS_ATTR_PTR(cpld_spi_wp), /* register: eeprom_wp */ + SYSFS_ATTR_PTR(fan_eeprom_wp), /* register: eeprom_wp */ + + SYSFS_ATTR_PTR(ps2_int_msk), /* register: mstr_irq */ + SYSFS_ATTR_PTR(ps1_int_msk), /* register: mstr_irq */ + SYSFS_ATTR_PTR(usb_fault_msk), /* register: mstr_irq */ + SYSFS_ATTR_PTR(pcie_int_msk), /* register: mstr_irq */ + SYSFS_ATTR_PTR(fan_alert_int_msk), /* register: mstr_irq */ + SYSFS_ATTR_PTR(usb_fault), /* register: mstr_irq */ + SYSFS_ATTR_PTR(pcie_int), /* register: mstr_irq */ + SYSFS_ATTR_PTR(fan_alert_int), /* register: mstr_irq */ + SYSFS_ATTR_PTR(system_led_fld), /* register: mstr_irq */ + SYSFS_ATTR_PTR(power_led), /* register: mstr_irq */ + SYSFS_ATTR_PTR(fan_led), /* register: mstr_irq */ + SYSFS_ATTR_PTR(locate_led), /* register: mstr_irq */ + + SYSFS_ATTR_PTR(led_test), /* register: fan_tray_3_1_led */ + SYSFS_ATTR_PTR(fan_tray3_led), /* register: fan_tray_3_1_led */ + SYSFS_ATTR_PTR(fan_tray2_led), /* register: fan_tray_3_1_led */ + SYSFS_ATTR_PTR(fan_tray1_led), /* register: fan_tray_3_1_led */ + SYSFS_ATTR_PTR(fan_tray6_led), /* register: fan_tray_6_4_led */ + SYSFS_ATTR_PTR(fan_tray5_led), /* register: fan_tray_6_4_led */ + SYSFS_ATTR_PTR(fan_tray4_led), /* register: fan_tray_6_4_led */ + + SYSFS_ATTR_PTR(fan_tray6_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(fan_tray5_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(fan_tray4_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(fan_tray3_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(fan_tray2_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(fan_tray1_present), /* register: fan_tray_status */ + + SYSFS_ATTR_PTR(fan_type6), /* register: fan_type_status */ + SYSFS_ATTR_PTR(fan_type5), /* register: fan_type_status */ + SYSFS_ATTR_PTR(fan_type4), /* register: fan_type_status */ + SYSFS_ATTR_PTR(fan_type3), /* register: fan_type_status */ + SYSFS_ATTR_PTR(fan_type2), /* register: fan_type_status */ + SYSFS_ATTR_PTR(fan_type1), /* register: fan_type_status */ + + SYSFS_ATTR_PTR(ps1_ps), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps1_pg), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps1_int), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps1_on), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps2_ps), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps2_pg), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps2_int), /* register: psu_en_status */ + SYSFS_ATTR_PTR(ps2_on), /* register: psu_en_status */ + + SYSFS_ATTR_PTR(usb1_vbus_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(v5p0_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(v3p3_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(vcc_1v8_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(mac_avs1v_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(mac1v_en), /* register: mb_pwr_en_status */ + SYSFS_ATTR_PTR(vcc_1v25_en), /* register: mb_pwr_en_status */ + + SYSFS_ATTR_PTR(vcc_3p3_cpld), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(vcc5v_pg), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(vcc3v3_pg), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(vcc_1v8_pg), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(mac_avs1v_pg), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(mac1v_pg), /* register: mb_pwr_status */ + SYSFS_ATTR_PTR(vcc_1v25_pg), /* register: mb_pwr_status */ + + SYSFS_ATTR_PTR(port_1_8_present), /* register: zqsfp28_present_8_1_status */ + SYSFS_ATTR_PTR(port_9_16_present), /* register: zqsfp28_present_16_9_status */ + SYSFS_ATTR_PTR(port_1_8_rst), /* register: zqsfp28_rst_8_1 */ + SYSFS_ATTR_PTR(port_9_16_rst), /* register: zqsfp28_rst_16_9 */ + SYSFS_ATTR_PTR(port_1_8_modsel), /* register: zqsfp28_modsel_8_1 */ + SYSFS_ATTR_PTR(port_9_16_modsel), /* register: zqsfp28_modsel_16_9 */ + SYSFS_ATTR_PTR(port_1_8_irq_status), /* register: zqsfp28_irq_8_1_status */ + SYSFS_ATTR_PTR(port_9_16_irq_status),/* register: zqsfp28_irq_16_9_status */ + SYSFS_ATTR_PTR(port_1_8_irq_msk), /* register: zqsfp28_irq_msk_8_1_status */ + SYSFS_ATTR_PTR(port_9_16_irq_msk), /* register: zqsfp28_irq_msk_16_9_status */ + SYSFS_ATTR_PTR(port_1_8_lpmode), /* register: zqsfp28_lpmode_8_1 */ + SYSFS_ATTR_PTR(port_9_16_lpmode), /* register: zqsfp28_lpmode_16_9 */ + + SYSFS_ATTR_PTR(fan_tray1_6_present), /* register: fan_tray_status */ + SYSFS_ATTR_PTR(psu_en_status_fld), /* register: psu_en_status*/ + + SYSFS_ATTR_PTR(debug), /* debug flag for print more messages */ + NULL +}; +static const struct attribute_group master_cpld_group_misc = { + .attrs = misc_attributes, +}; + +static int master_cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct master_cpld_data *master_cpld; + int err, i; + int grp_number = (int)( sizeof(master_cpld_port_group) / sizeof(master_cpld_port_group[0])); + + /* allocate memory to master_cpld */ + master_cpld = devm_kzalloc(&client->dev, sizeof(struct master_cpld_data) , GFP_KERNEL); + + if (!master_cpld) + return -ENOMEM; + + mutex_init(&master_cpld->lock); + + for(i = 0 ; i < grp_number ; i++){ + err = sysfs_create_group(&client->dev.kobj, &master_cpld_port_group[i]); + if (err){ + printk("%s: Error creeat port group %d.\n", __FUNCTION__, i+1); + } + } + err = sysfs_create_group(&client->dev.kobj, &master_cpld_group_misc); + if (err){ + printk("%s: Error creeat misc group.\n", __FUNCTION__); + } + + master_cpld->client = client; + i2c_set_clientdata(client, master_cpld); + + printk(KERN_INFO "%s: Master CPLD LCMXO3LF created.\n", __FUNCTION__); + + return 0; + +} + +static int master_cpld_remove(struct i2c_client *client) +{ + int i; + int grp_number = (int)( sizeof(master_cpld_port_group) / sizeof(master_cpld_port_group[0])); + + for(i = 0 ; i < grp_number ; i++){ + sysfs_remove_group(&client->dev.kobj, &master_cpld_port_group[i]); + } + sysfs_remove_group(&client->dev.kobj, &master_cpld_group_misc); + + printk(KERN_INFO "%s: Master CPLD removed.\n", __FUNCTION__); + return 0; +} + +static struct i2c_driver master_cpld_driver = { + .driver = { + .name = "master_cpld", + .owner = THIS_MODULE, + }, + .probe = master_cpld_probe, + .remove = master_cpld_remove, + .id_table = master_cpld_ids, +}; + +static int __init master_cpld_init(void) +{ + printk(KERN_INFO "%s: init.\n", __FUNCTION__); + return i2c_add_driver(&master_cpld_driver); +} +module_init(master_cpld_init); + +static void __exit master_cpld_exit(void) +{ + printk(KERN_INFO "%s: exit.\n", __FUNCTION__); + i2c_del_driver(&master_cpld_driver); +} +module_exit(master_cpld_exit); + +MODULE_DESCRIPTION("mitac_ly1200_32x_master_cpld driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_pb_i2c.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_pb_i2c.c new file mode 100644 index 000000000000..bad9260ab4ca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_pb_i2c.c @@ -0,0 +1,137 @@ +#include +#include +#include "bms_i2c.h" + +#define BMS_PB_I2C_CLIENT_NUM 6 + +static struct i2c_client *bms_pb_clients[BMS_PB_I2C_CLIENT_NUM] = {NULL}; +static int bms_pb_client_index = 0; + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + { + return 0; + } + adapter = to_i2c_adapter(dev); + + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = bms_i2c_adapter_names[type]; + + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + + +static int __init find_i2c_mux_adapter_num(int parent_num, int num) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + char name[48]; + + snprintf(name, sizeof(name), "i2c-%d-mux (chan_id %d)", + parent_num, num); + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static __init struct i2c_client *bms_pb_setup_eeprom_24c01( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("24c01", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + + +static int __init bms_pb_setup_devices(void) +{ + struct i2c_adapter *adap; + int adap_num; + int parent_num; + + parent_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + if (parent_num < 0) + return parent_num; + + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN3); + if (adap_num < 0) + return adap_num; + + adap = i2c_get_adapter(adap_num); + if (!adap) { + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + goto exit; + } + + bms_pb_clients[bms_pb_client_index++] = bms_pb_setup_eeprom_24c01(adap, 0x50); + bms_pb_clients[bms_pb_client_index++] = bms_pb_setup_eeprom_24c01(adap, 0x51); + +exit: + return 0; +} + +static int __init bms_pb_i2c_init(void) +{ + /* Initial bms_sb_slients array. */ + memset(bms_pb_clients, 0x0, BMS_PB_I2C_CLIENT_NUM); + + bms_pb_setup_devices(); + return 0; +} + + +static void __exit bms_pb_i2c_exit(void){ + int i; + + for (i=(bms_pb_client_index-1); i>=0; i--) { + if (bms_pb_clients[i]) { + i2c_unregister_device(bms_pb_clients[i]); + bms_pb_clients[i] = NULL; + } + } + + bms_pb_client_index = 0; + + +} + + +module_init(bms_pb_i2c_init); +module_exit(bms_pb_i2c_exit); + + +MODULE_DESCRIPTION("mitac_ly1200_32x_pb_i2c driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_sb_i2c.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_sb_i2c.c new file mode 100644 index 000000000000..6389229581bc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_sb_i2c.c @@ -0,0 +1,514 @@ +#include +#include +#include +#include +#include +#include +#include "bms_i2c.h" + +/* Don't include MAC_AVS_1V */ +#define BMS_SB_I2C_CLIENT_NUM 35 +#define BMS_SB_ADAPTER_BASE 2 +#define BMS_SB_STAGE2_MUX_BUS_BASE 6 + + +static struct i2c_client *bms_sb_clients[BMS_SB_I2C_CLIENT_NUM] = {NULL}; +static int bms_sb_client_index = 0; + +enum bms_sb_switch_stage2_mux0_bus { + I2C_STAGE2_MUX0_CHAN0 = 0, + I2C_STAGE2_MUX0_CHAN1, + I2C_STAGE2_MUX0_CHAN2, + I2C_STAGE2_MUX0_CHAN3, + I2C_STAGE2_MUX0_CHAN4, + I2C_STAGE2_MUX0_CHAN5, + I2C_STAGE2_MUX0_CHAN6, + I2C_STAGE2_MUX0_CHAN7, +}; + +enum bms_sb_switch_stage2_mux1_bus { + I2C_STAGE2_MUX1_CHAN8 = 0, + I2C_STAGE2_MUX1_CHAN9, + I2C_STAGE2_MUX1_CHAN10, + I2C_STAGE2_MUX1_CHAN11, + I2C_STAGE2_MUX1_CHAN12, + I2C_STAGE2_MUX1_CHAN13, + I2C_STAGE2_MUX1_CHAN14, + I2C_STAGE2_MUX1_CHAN15, +}; + +enum bms_sb_switch_stage2_mux2_bus { + I2C_STAGE2_MUX2_CHAN16 = 0, + I2C_STAGE2_MUX2_CHAN17, + I2C_STAGE2_MUX2_CHAN18, + I2C_STAGE2_MUX2_CHAN19, + I2C_STAGE2_MUX2_CHAN20, + I2C_STAGE2_MUX2_CHAN21, + I2C_STAGE2_MUX2_CHAN22, + I2C_STAGE2_MUX2_CHAN23, +}; + +enum bms_sb_switch_stage2_mux3_bus { + I2C_STAGE2_MUX3_CHAN24 = 0, + I2C_STAGE2_MUX3_CHAN25, + I2C_STAGE2_MUX3_CHAN26, + I2C_STAGE2_MUX3_CHAN27, + I2C_STAGE2_MUX3_CHAN28, + I2C_STAGE2_MUX3_CHAN29, + I2C_STAGE2_MUX3_CHAN30, + I2C_STAGE2_MUX3_CHAN31, +}; + +static struct pca954x_platform_mode pmode_pca9548_mux[] = { + { .adap_id = BMS_SB_ADAPTER_BASE + 0, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 1, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 2, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 3, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 4, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 5, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 6, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 7, }, +}; + +static struct pca954x_platform_data platdata_pca9548_mux = { + .modes = pmode_pca9548_mux, + .num_modes = ARRAY_SIZE(pmode_pca9548_mux), +}; + +static struct pca954x_platform_mode pmode_stage1_pca9548_mux0[] = { + { .adap_id = BMS_SB_ADAPTER_BASE + 8, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 9, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 10, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 11, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 12, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 13, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 14, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 15, }, +}; + +static struct pca954x_platform_data platdata_stage1_pca9548_mux0 = { + .modes = pmode_stage1_pca9548_mux0, + .num_modes = ARRAY_SIZE(pmode_stage1_pca9548_mux0), +}; + +static struct pca954x_platform_mode pmode_stage1_pca9548_mux1[] = { + { .adap_id = BMS_SB_ADAPTER_BASE + 16, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 17, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 18, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 19, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 20, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 21, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 22, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 23, }, +}; + +static struct pca954x_platform_data platdata_stage1_pca9548_mux1 = { + .modes = pmode_stage1_pca9548_mux1, + .num_modes = ARRAY_SIZE(pmode_stage1_pca9548_mux1), +}; + +static struct pca954x_platform_mode pmode_stage1_pca9548_mux2[] = { + { .adap_id = BMS_SB_ADAPTER_BASE + 24, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 25, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 26, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 27, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 28, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 29, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 30, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 31, }, +}; + +static struct pca954x_platform_data platdata_stage1_pca9548_mux2 = { + .modes = pmode_stage1_pca9548_mux2, + .num_modes = ARRAY_SIZE(pmode_stage1_pca9548_mux2), +}; + +static struct pca954x_platform_mode pmode_stage1_pca9548_mux3[] = { + { .adap_id = BMS_SB_ADAPTER_BASE + 32, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 33, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 34, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 35, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 36, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 37, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 38, }, + { .adap_id = BMS_SB_ADAPTER_BASE + 39, }, +}; + +static struct pca954x_platform_data platdata_stage1_pca9548_mux3 = { + .modes = pmode_stage1_pca9548_mux3, + .num_modes = ARRAY_SIZE(pmode_stage1_pca9548_mux3), +}; + +static int __init __find_i2c_adap(struct device *dev, void *data) +{ + const char *name = data; + static const char *prefix = "i2c-"; + struct i2c_adapter *adapter; + + if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) + { + return 0; + } + adapter = to_i2c_adapter(dev); + + return (strncmp(adapter->name, name, strlen(name)) == 0); +} + +static int __init find_i2c_adapter_num(enum i2c_adapter_type type) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + const char *name = bms_i2c_adapter_names[type]; + + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static int __init find_i2c_mux_adapter_num(int parent_num, int num) +{ + struct device *dev = NULL; + struct i2c_adapter *adapter; + char name[48]; + + snprintf(name, sizeof(name), "i2c-%d-mux (chan_id %d)", + parent_num, num); + /* find the adapter by name */ + dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, + __find_i2c_adap); + if (!dev) { + pr_err("%s: i2c adapter %s not found on system.\n", + __func__, name); + return -ENODEV; + } + adapter = to_i2c_adapter(dev); + + return adapter->nr; +} + +static __init struct i2c_client *bms_sb_setup_eeprom_24c04( + struct i2c_adapter *adap) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("24c04", 0x50), + }; + + return i2c_new_device(adap, &info_spd); +} + +static __init struct i2c_client *bms_sb_setup_tmp75( + struct i2c_adapter *adap, int addr) +{ + struct i2c_board_info info_spd = { + I2C_BOARD_INFO("tmp75", addr), + }; + + return i2c_new_device(adap, &info_spd); +} + +static __init struct i2c_client *bms_sb_setup_switch(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &platdata_pca9548_mux, + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_stage1_mux0(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("pca9548", 0x71), + .platform_data = &platdata_stage1_pca9548_mux0, + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_stage1_mux1(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("pca9548", 0x72), + .platform_data = &platdata_stage1_pca9548_mux1, + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_stage1_mux2(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &platdata_stage1_pca9548_mux2, + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_stage1_mux3(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("pca9548", 0x74), + .platform_data = &platdata_stage1_pca9548_mux3, + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_slave_cpld(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("slave_cpld", 0x33), + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_master_cpld(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("master_cpld", 0x32), + }; + + return i2c_new_device(adap, &info); +} + +static __init struct i2c_client *bms_sb_setup_sff8436(struct i2c_adapter *adap) +{ + struct i2c_board_info info = { + I2C_BOARD_INFO("sff8436", 0x50), + }; + + return i2c_new_device(adap, &info); +} + +static int __init bms_sb_setup_devices_ismt(void) +{ + struct i2c_adapter *adap; + int adap_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + + if (adap_num < 0) + return adap_num; + + adap = i2c_get_adapter(adap_num); + if (!adap) { + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + return 0; + } + + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_switch(adap); + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_master_cpld(adap); + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_slave_cpld(adap); + + return 0; +} + +static int __init bms_sb_setup_devices_stage1(void) +{ + struct i2c_adapter *adap; + int adap_num; + int parent_num; + + parent_num = find_i2c_adapter_num(I2C_ADAPTER_ISMT); + if (parent_num < 0) + return parent_num; + + /* Mux chan0 steup */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN0); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_eeprom_24c04(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN0); + } + + /* Mux chan1 connect to fan board */ + + /* Mux chan2 steup */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN2); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_tmp75(adap, 0x4a); + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_tmp75(adap, 0x4b); + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_tmp75(adap, 0x4c); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN2); + } + + /* Mux chan3 connect to power board */ + + /* Mux chan4 setup for i2c mux0 */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN4); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_stage1_mux0(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN4); + } + + /* Mux chan5 setup for i2c mux1 */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN5); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_stage1_mux1(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN5); + } + + /* Mux chan6 setup for i2c mux2 */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN6); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_stage1_mux2(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN6); + } + + /* Mux chan7 setup for i2c mux3 */ + adap_num = find_i2c_mux_adapter_num(parent_num, I2C_STAGE1_MUX_CHAN7); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_stage1_mux3(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN7); + } + + return 0; +} + +static int __init bms_sb_setup_devices_stage2(void) +{ + struct i2c_adapter *adap; + int adap_num; + int i2c_base = sizeof(bms_i2c_adapter_names) / sizeof(bms_i2c_adapter_names[0]); + int i; + + /* stage2 mux0 chan0~7 install sff8436 */ + for(i = I2C_STAGE2_MUX0_CHAN0; i <= I2C_STAGE2_MUX0_CHAN7; i++){ + adap_num = find_i2c_mux_adapter_num(I2C_STAGE1_MUX_CHAN4 + i2c_base, I2C_STAGE2_MUX0_CHAN0 + i); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_sff8436(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN4 + i2c_base); + } + } + + /* stage2 mux1 chan0~7 install sff8436 */ + for(i = I2C_STAGE2_MUX1_CHAN8; i <= I2C_STAGE2_MUX1_CHAN15; i++){ + adap_num = find_i2c_mux_adapter_num(I2C_STAGE1_MUX_CHAN5 + i2c_base, I2C_STAGE2_MUX1_CHAN8 + i); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_sff8436(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN5 + i2c_base); + } + } + + /* stage2 mux2 chan0~7 install sff8436 */ + for(i = I2C_STAGE2_MUX2_CHAN16; i <= I2C_STAGE2_MUX2_CHAN23; i++){ + adap_num = find_i2c_mux_adapter_num(I2C_STAGE1_MUX_CHAN6 + i2c_base, I2C_STAGE2_MUX2_CHAN16 + i); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_sff8436(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN6 + i2c_base); + } + } + + /* stage2 mux3 chan0~7 install sff8436 */ + for(i = I2C_STAGE2_MUX3_CHAN24; i <= I2C_STAGE2_MUX3_CHAN31; i++){ + adap_num = find_i2c_mux_adapter_num(I2C_STAGE1_MUX_CHAN7 + i2c_base, I2C_STAGE2_MUX3_CHAN24 + i); + if (adap_num >= 0){ + adap = i2c_get_adapter(adap_num); + if(adap) { + bms_sb_clients[bms_sb_client_index++] = bms_sb_setup_sff8436(adap); + }else{ + pr_err("%s failed to get i2c adap %d.\n", __func__, adap_num); + } + }else{ + pr_err("%s failed to find i2c mux adap number %d.\n", __func__, I2C_STAGE1_MUX_CHAN7 + i2c_base); + } + } +} + +static int __init bms_sb_i2c_init(void) +{ + /* Initial bms_sb_slients array. */ + memset(bms_sb_clients, 0x0, BMS_SB_I2C_CLIENT_NUM); + + bms_sb_setup_devices_ismt(); + mdelay(200); + bms_sb_setup_devices_stage1(); + mdelay(200); + bms_sb_setup_devices_stage2(); + + return 0; +} + +static void __exit bms_sb_i2c_exit(void){ + int i; + + for (i=(bms_sb_client_index-1); i>=0; i--) { + if (bms_sb_clients[i]) { + i2c_unregister_device(bms_sb_clients[i]); + bms_sb_clients[i] = NULL; + } + } + + bms_sb_client_index = 0; + +} + +module_init(bms_sb_i2c_init); +module_exit(bms_sb_i2c_exit); + +MODULE_DESCRIPTION("mitac_ly1200_32x_sb_i2c driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_slave_cpld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_slave_cpld.c new file mode 100644 index 000000000000..8809573fa4ad --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_slave_cpld.c @@ -0,0 +1,427 @@ +#include +#include + +#include "slave_cpld_reg.h" +#include "slave_cpld_sysfs.h" + +static int debug_flag = 0; + +struct slave_cpld_data { + struct mutex lock; + + struct i2c_client *client; + struct device_attribute bin; +}; + + +static const struct i2c_device_id slave_cpld_ids[] = { + { "slave_cpld", 0 }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, slave_cpld_ids); + +static int slave_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + unsigned int reg_val = 0, fld_val; + static int debug_flag; + struct slave_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int err; + + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + mutex_lock(&data->lock); + if ((err = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, err); + return err; + } + reg_val = err; + if (debug_flag) { + printk("%s: reg_offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + if (fld_width == reg_width) {fld_val = reg_val & fld_mask;} + else {fld_val = (reg_val >> fld_shift) & fld_mask;} + return sprintf(buf, "0x%x\n", fld_val); +} + +static int slave_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + int ret_code; + unsigned int reg_val, fld_val; + unsigned long val; + static int debug_flag; + struct slave_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + /* Parse buf and store to fld_val */ + if ((ret_code = kstrtoul(buf, 16, &val))){ + printk("%s: Conversion value = %s failed, errno = %d.\n", reg_name, buf, ret_code); + return ret_code; + } + fld_val = (unsigned int)val; + mutex_lock(&data->lock); + if ((ret_code = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* Handle CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + reg_val = ret_code; + if (debug_flag) { + printk("%s: offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + if (fld_width == reg_width) {reg_val = fld_val & fld_mask;} + else {reg_val = (reg_val & ~(fld_mask << fld_shift)) | + ((fld_val & (fld_mask)) << fld_shift);} + if ((ret_code = i2c_smbus_write_byte_data(client, (u8)reg_offset, (u8)reg_val)) != 0) { + /* Handle CPLD write error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c write failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + else if (debug_flag) { + printk("%s: offset = %d, width = %d, new value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + return count; +} + +/*--------------------special file for debug---------------------- */ +static ssize_t slave_cpld_debug_read(struct device *dev, struct device_attribute *attr, + char *buf){ + + return sprintf(buf, "%d\n", debug_flag); +} + + +static ssize_t slave_cpld_debug_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int temp; + int error; + + error = kstrtoint(buf, 10, &temp); + if (error){ + printk(KERN_INFO "%s: Conversion value = %s failed.\n", __FUNCTION__, buf); + return count; + } + debug_flag = temp; + + if(debug_flag) + printk("%s, debug_flag = %d\n", __FUNCTION__, debug_flag); + + return count; +} +SYSFS_MISC_RW_ATTR_DEF(debug, slave_cpld_debug_read, slave_cpld_debug_write) + + + + +/* ----------------define port group---------------------------- */ +static struct attribute *port17_attributes[] = { + SYSFS_ATTR_PTR(port17_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port17_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port17_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port17_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port17_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port17_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port18_attributes[] = { + SYSFS_ATTR_PTR(port18_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port18_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port18_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port18_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port18_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port18_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port19_attributes[] = { + SYSFS_ATTR_PTR(port19_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port19_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port19_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port19_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port19_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port19_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port20_attributes[] = { + SYSFS_ATTR_PTR(port20_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port20_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port20_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port20_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port20_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port20_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port21_attributes[] = { + SYSFS_ATTR_PTR(port21_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port21_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port21_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port21_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port21_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port21_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port22_attributes[] = { + SYSFS_ATTR_PTR(port22_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port22_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port22_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port22_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port22_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port22_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port23_attributes[] = { + SYSFS_ATTR_PTR(port23_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port23_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port23_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port23_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port23_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port23_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port24_attributes[] = { + SYSFS_ATTR_PTR(port24_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port24_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port24_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port24_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port24_irq_status), /* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port24_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + NULL +}; + +static struct attribute *port25_attributes[] = { + SYSFS_ATTR_PTR(port25_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port25_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port25_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port25_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port25_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port25_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port26_attributes[] = { + SYSFS_ATTR_PTR(port26_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port26_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port26_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port26_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port26_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port26_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port27_attributes[] = { + SYSFS_ATTR_PTR(port27_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port27_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port27_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port27_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port27_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port27_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port28_attributes[] = { + SYSFS_ATTR_PTR(port28_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port28_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port28_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port28_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port28_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port28_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port29_attributes[] = { + SYSFS_ATTR_PTR(port29_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port29_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port29_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port29_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port29_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port29_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port30_attributes[] = { + SYSFS_ATTR_PTR(port30_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port30_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port30_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port30_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port30_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port30_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port31_attributes[] = { + SYSFS_ATTR_PTR(port31_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port31_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port31_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port31_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port31_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port31_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static struct attribute *port32_attributes[] = { + SYSFS_ATTR_PTR(port32_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port32_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port32_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port32_lpmode), /* register: zqsfp28_lpmode_32_25 */ + SYSFS_ATTR_PTR(port32_irq_status), /* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port32_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + NULL +}; + +static const struct attribute_group slave_cpld_port_group[] = { + {.attrs = port17_attributes, + .name = "port17",}, + {.attrs = port18_attributes, + .name = "port18",}, + {.attrs = port19_attributes, + .name = "port19",}, + {.attrs = port20_attributes, + .name = "port20",}, + {.attrs = port21_attributes, + .name = "port21",}, + {.attrs = port22_attributes, + .name = "port22",}, + {.attrs = port23_attributes, + .name = "port23",}, + {.attrs = port24_attributes, + .name = "port24",}, + {.attrs = port25_attributes, + .name = "port25",}, + {.attrs = port26_attributes, + .name = "port26",}, + {.attrs = port27_attributes, + .name = "port27",}, + {.attrs = port28_attributes, + .name = "port28",}, + {.attrs = port29_attributes, + .name = "port29",}, + {.attrs = port30_attributes, + .name = "port30",}, + {.attrs = port31_attributes, + .name = "port31",}, + {.attrs = port32_attributes, + .name = "port32",} +}; + +/* ----------------define misc group---------------------------- */ +static struct attribute *misc_attributes[] = { + SYSFS_ATTR_PTR(mjr_rev), /* register: slv_cpld_rev */ + SYSFS_ATTR_PTR(mnr_rev), /* register: slv_cpld_rev */ + SYSFS_ATTR_PTR(scrtch_reg), /* register: slv_cpld_gpr */ + SYSFS_ATTR_PTR(brd_rev), /* register: mb_brd_rev_type */ + SYSFS_ATTR_PTR(brd_type), /* register: mb_brd_rev_type */ + + SYSFS_ATTR_PTR(port_17_24_present), /* register: zqsfp28_present_24_17_status */ + SYSFS_ATTR_PTR(port_25_32_present), /* register: zqsfp28_present_32_25_status */ + SYSFS_ATTR_PTR(port_17_24_rst), /* register: zqsfp28_rst_24_17 */ + SYSFS_ATTR_PTR(port_25_32_rst), /* register: zqsfp28_rst_32_25 */ + SYSFS_ATTR_PTR(port_17_24_modsel), /* register: zqsfp28_modsel_24_17 */ + SYSFS_ATTR_PTR(port_25_32_modsel), /* register: zqsfp28_modsel_32_25 */ + SYSFS_ATTR_PTR(port_17_24_irq_status),/* register: zqsfp28_irq_24_17_status */ + SYSFS_ATTR_PTR(port_25_32_irq_status),/* register: zqsfp28_irq_32_25_status */ + SYSFS_ATTR_PTR(port_17_24_irq_msk), /* register: zqsfp28_irq_msk_24_17_status */ + SYSFS_ATTR_PTR(port_25_32_irq_msk), /* register: zqsfp28_irq_msk_32_25_status */ + SYSFS_ATTR_PTR(port_17_24_lpmode), /* register: zqsfp28_lpmode_24_17 */ + SYSFS_ATTR_PTR(port_25_32_lpmode), /* register: zqsfp28_lpmode_32_25 */ + + SYSFS_ATTR_PTR(debug), /* debug flag for print more messages */ + NULL +}; +static const struct attribute_group slave_cpld_group_misc = { + .attrs = misc_attributes, +}; + +static int slave_cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct slave_cpld_data *slave_cpld; + int err, i; + int grp_number = (int)( sizeof(slave_cpld_port_group) / sizeof(slave_cpld_port_group[0])); + + /* allocate memory to slave_cpld */ + slave_cpld = devm_kzalloc(&client->dev, sizeof(struct slave_cpld_data) , GFP_KERNEL); + + if (!slave_cpld) + return -ENOMEM; + + mutex_init(&slave_cpld->lock); + + for(i = 0 ; i < grp_number ; i++){ + err = sysfs_create_group(&client->dev.kobj, &slave_cpld_port_group[i]); + if (err){ + printk("%s: Error creeat port group %d.\n", __FUNCTION__, i+1); + } + } + err = sysfs_create_group(&client->dev.kobj, &slave_cpld_group_misc); + if (err){ + printk("%s: Error creeat misc group.\n", __FUNCTION__); + } + + slave_cpld->client = client; + i2c_set_clientdata(client, slave_cpld); + + printk(KERN_INFO "%s: Slave CPLD LCMXO3LF created.\n", __FUNCTION__); + + return 0; + +} + +static int slave_cpld_remove(struct i2c_client *client) +{ + int i; + int grp_number = (int)( sizeof(slave_cpld_port_group) / sizeof(slave_cpld_port_group[0])); + + for(i = 0 ; i < grp_number ; i++){ + sysfs_remove_group(&client->dev.kobj, &slave_cpld_port_group[i]); + } + sysfs_remove_group(&client->dev.kobj, &slave_cpld_group_misc); + + printk(KERN_INFO "%s: Slave CPLD removed.\n", __FUNCTION__); + return 0; +} + +static struct i2c_driver slave_cpld_driver = { + .driver = { + .name = "slave_cpld", + .owner = THIS_MODULE, + }, + .probe = slave_cpld_probe, + .remove = slave_cpld_remove, + .id_table = slave_cpld_ids, +}; + +static int __init slave_cpld_init(void) +{ + printk(KERN_INFO "%s: init.\n", __FUNCTION__); + return i2c_add_driver(&slave_cpld_driver); +} +module_init(slave_cpld_init); + +static void __exit slave_cpld_exit(void) +{ + printk(KERN_INFO "%s: exit.\n", __FUNCTION__); + i2c_del_driver(&slave_cpld_driver); +} +module_exit(slave_cpld_exit); + +MODULE_DESCRIPTION("mitac_ly1200_32x_slave_cpld driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c new file mode 100644 index 000000000000..e5af8b70bf9a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c @@ -0,0 +1,541 @@ +#define CONFIG_DRV_SYSCPLD_WDT 1 + +#include +#include + +#include "system_cpld_reg.h" +#include "system_cpld_sysfs.h" +#ifdef CONFIG_DRV_SYSCPLD_WDT +#include +#include +#include +#include +#include +#include +#endif + +static int debug_flag = 0; + +struct system_cpld_data { + struct mutex lock; + + struct i2c_client *client; + struct device_attribute bin; +}; +struct system_cpld_data *system_cpld; + +static const struct i2c_device_id system_cpld_ids[] = { + { "system_cpld", 0 }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, system_cpld_ids); + +static int system_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + unsigned int reg_val = 0, fld_val; + static int debug_flag; + struct system_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int err; + + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + mutex_lock(&data->lock); + if ((err = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, err); + return err; + } + reg_val = err; + if (debug_flag) { + printk("%s: reg_offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + if (fld_width == reg_width) {fld_val = reg_val & fld_mask;} + else {fld_val = (reg_val >> fld_shift) & fld_mask;} + return sprintf(buf, "0x%x\n", fld_val); +} + +static int system_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ + int ret_code; + unsigned int reg_val, fld_val; + unsigned long val; + static int debug_flag; + struct system_cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + if (reg_width != 8){ + printk("%s: Register table width setting failed.\n", reg_name); + return -EINVAL; + } + /* Parse buf and store to fld_val */ + if ((ret_code = kstrtoul(buf, 16, &val))){ + printk("%s: Conversion value = %s failed, errno = %d.\n", reg_name, buf, ret_code); + return ret_code; + } + fld_val = (unsigned int)val; + mutex_lock(&data->lock); + if ((ret_code = i2c_smbus_read_byte_data(client, (u8)reg_offset)) < 0) { + /* Handle CPLD read error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c read failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + reg_val = ret_code; + if (debug_flag) { + printk("%s: offset = %d, width = %d, cur value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + if (fld_width == reg_width) {reg_val = fld_val & fld_mask;} + else {reg_val = (reg_val & ~(fld_mask << fld_shift)) | + ((fld_val & (fld_mask)) << fld_shift);} + if ((ret_code = i2c_smbus_write_byte_data(client, (u8)reg_offset, (u8)reg_val)) != 0) { + /* Handle CPLD write error condition */; + mutex_unlock(&data->lock); + printk("%s: i2c write failed, error code = %d.\n", reg_name, ret_code); + return ret_code; + } + else if (debug_flag) { + printk("%s: offset = %d, width = %d, new value = 0x%x.\n", reg_name, reg_offset, reg_width, reg_val); + } + mutex_unlock(&data->lock); + return count; +} + +/*--------------------special file for debug---------------------- */ +static ssize_t system_cpld_debug_read(struct device *dev, struct device_attribute *attr, + char *buf){ + + return sprintf(buf, "%d\n", debug_flag); +} + + +static ssize_t system_cpld_debug_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int temp; + int error; + + error = kstrtoint(buf, 10, &temp); + if (error){ + printk(KERN_INFO "%s: Conversion value = %s failed.\n", __FUNCTION__, buf); + return count; + } + debug_flag = temp; + + if(debug_flag) + printk("%s, debug_flag = %d\n", __FUNCTION__, debug_flag); + + return count; +} +SYSFS_MISC_RW_ATTR_DEF(debug, system_cpld_debug_read, system_cpld_debug_write) + + +/* ----------------define misc group---------------------------- */ +static struct attribute *misc_attributes[] = { + SYSFS_ATTR_PTR(mjr_rev), /* register: sys_cpld_rev */ + SYSFS_ATTR_PTR(mnr_rev), /* register: sys_cpld_rev */ + + SYSFS_ATTR_PTR(scrtch_reg), /* register: sys_cpld_gpr */ + + SYSFS_ATTR_PTR(brd_rev), /* register: cpu_brd_rev_type */ + SYSFS_ATTR_PTR(brd_type), /* register: cpu_brd_rev_type */ + + SYSFS_ATTR_PTR(ssd_present), /* register: sys_srr */ + SYSFS_ATTR_PTR(spi_cs_sel), /* register: sys_srr */ + SYSFS_ATTR_PTR(rst_bios_switch), /* register: sys_srr */ + SYSFS_ATTR_PTR(cpld_upgrade_rst), /* register: sys_srr */ + + SYSFS_ATTR_PTR(cpld_spi_wp), /* register: sys_eeprom_wp */ + SYSFS_ATTR_PTR(system_id_eeprom_wp), /* register: sys_eeprom_wp */ + SYSFS_ATTR_PTR(spi_me_wp), /* register: sys_eeprom_wp */ + SYSFS_ATTR_PTR(spi_bios_wp), /* register: sys_eeprom_wp */ + SYSFS_ATTR_PTR(spi_bak_bios_wp), /* register: sys_eeprom_wp */ + + SYSFS_ATTR_PTR(vrhot_irq_en), /* register: sys_irq */ + SYSFS_ATTR_PTR(cpu_thermtrip_irq_en), /* register: sys_irq */ + SYSFS_ATTR_PTR(temp_alert_irq_en), /* register: sys_irq */ + SYSFS_ATTR_PTR(vrhot_irq), /* register: sys_irq */ + SYSFS_ATTR_PTR(cpu_thermtrip_irq), /* register: sys_irq */ + SYSFS_ATTR_PTR(temp_alert_irq), /* register: sys_irq */ + + SYSFS_ATTR_PTR(wd_timer), /* register: sys_wd */ + SYSFS_ATTR_PTR(wd_en), /* register: sys_wd */ + SYSFS_ATTR_PTR(wd_punch), /* register: sys_wd */ + + SYSFS_ATTR_PTR(mb_rst_en), /* register: sys_mb_rst_en */ + + SYSFS_ATTR_PTR(pwr_v3p3_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_vcc_vnn_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_vccsram_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_vddq_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_vcc_ref_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_v1p05_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_v1p8_en), /* register: cpu_pwr_en_status */ + SYSFS_ATTR_PTR(pwr_v2p5_en), /* register: cpu_pwr_en_status */ + + SYSFS_ATTR_PTR(pg_v3p3), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_vcc_vnn), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_vccsram), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_vddq), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_vcc_ref), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_v1p05), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_v1p8), /* register: cpu_pwr_status */ + SYSFS_ATTR_PTR(pg_v2p5), /* register: cpu_pwr_status */ + + SYSFS_ATTR_PTR(debug), /* debug flag for print more messages */ + NULL +}; +static const struct attribute_group system_cpld_group_misc = { + .attrs = misc_attributes, +}; + +#ifdef CONFIG_DRV_SYSCPLD_WDT +/* + ***************************************************************************** + * + * Watchdog Driver + * + ***************************************************************************** + */ +/* wdt_timeout[] are defined by CPLD spec , -1 means researved + 300 sec is not supported */ +int wdt_timeout[]={15,30,60,90,120,180,240,300,-1,-1,-1,-1,-1,-1,-1,-1}; +#define WD_TIMO_MAX_NUM 16 +/* Default margin */ +#define WD_TIMO 30 + +static int wdt_margin = WD_TIMO; +module_param(wdt_margin, int, 0); +MODULE_PARM_DESC(wdt_margin, "Watchdog timeout in seconds (default " + __MODULE_STRING(WD_TIMO) "s)"); + +static unsigned long wdt_is_open; +static int boot_flag; + +/** + * wdt_ping: + * + * Reload counter one with the watchdog timeout. We don't bother reloading + * the cascade counter. + */ +static void wdt_ping(void) +{ + struct device *dev = &system_cpld->client->dev; + struct device_attribute *fake_attr=NULL; + char *buf="0";/* 0: punch is defined by CPLD spec */ + int err; + err = system_cpld_wd_punch_raw_write(dev, fake_attr, buf, (size_t)0); + if(err < 0){ + system_cpld_wd_punch_raw_write(dev, fake_attr, buf, (size_t)0); + } +} + +/** + * wdt_disable: + * + * disables watchdog. + */ +static void wdt_disable(void) +{ + struct device *dev = &system_cpld->client->dev; + struct device_attribute *fake_attr=NULL; + char *buf="0";/* 0: disable is defined by CPLD spec */ + int err; + err = system_cpld_wd_en_raw_write(dev, fake_attr, buf, (size_t)0); + if(err < 0){ + system_cpld_wd_en_raw_write(dev, fake_attr, buf, (size_t)0); + } +} + +/** + * wdt_enable: + * + * enables watchdog. + */ +static void wdt_enable(void) +{ + struct device *dev = &system_cpld->client->dev; + struct device_attribute *fake_attr=NULL; + char *buf="1";/* 1: enable is defined by CPLD spec */ + int err; + err = system_cpld_wd_en_raw_write(dev, fake_attr, buf, (size_t)0); + if(err < 0){ + system_cpld_wd_en_raw_write(dev, fake_attr, buf, (size_t)0); + } +} + +/** + * wdt_set_timeout: + * + * set watchdog timeout. + */ +static void wdt_set_timeout(int index) +{ + struct device *dev = &system_cpld->client->dev; + struct device_attribute *fake_attr=NULL; + char buf[1]; + if ( WD_TIMO_MAX_NUM == 16 ) { + sprintf(buf,"%x",index); + system_cpld_wd_timer_raw_write(dev, fake_attr, buf, (size_t)0); + } + else + printk(KERN_INFO "%s: It is out of spec.\n", __FUNCTION__); +} + +/** + * wdt_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ +static ssize_t wdt_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + wdt_ping(); + return 1; + } + return 0; +} + +/** + * wdt_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. We only actually usefully support + * querying capabilities and current status. + */ +static int wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int new_margin, rv, i; + static struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, + .firmware_version = 1, + .identity = "SYS_CPLD WTD" + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info __user *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(boot_flag, (int __user *)arg); + case WDIOC_KEEPALIVE: + wdt_ping(); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_margin, (int __user *)arg)) + return -EFAULT; + /* Arbitrary, can't find the card's limits */ + if (new_margin <= 1) + return -EINVAL; + for( i=0; i= WD_TIMO_MAX_NUM || i < 0 ) + return -EINVAL; + wdt_set_timeout(i); + case WDIOC_GETTIMEOUT: + return put_user(wdt_margin, (int __user *)arg); + + case WDIOC_SETOPTIONS: + if (copy_from_user(&rv, (int __user *)arg, sizeof(int))) + return -EFAULT; + + if (rv & WDIOS_DISABLECARD) { + pr_info("System CPLD: disable watchdog\n"); + wdt_disable(); + } + + if (rv & WDIOS_ENABLECARD) { + pr_info("System CPLD: enable watchdog\n"); + wdt_enable(); + } + return -EINVAL; + } + return -ENOTTY; +} + +static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret; + + ret = wdt_ioctl(file, cmd, arg); + + return ret; +} + +/** + * wdt_open: + * @inode: inode of device + * @file: file handle to device + * + */ +static int wdt_open(struct inode *inode, struct file *file) +{ + if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { + if (test_and_set_bit(0, &wdt_is_open)) { + return -EBUSY; + } + /* + * Activate + */ + + wdt_enable(); + return nonseekable_open(inode, file); + } + return -ENODEV; +} + +/** + * wdt_close: + * @inode: inode to board + * @file: file handle to board + * + */ +static int wdt_release(struct inode *inode, struct file *file) +{ + if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) + clear_bit(0, &wdt_is_open); + return 0; +} + +/** + * notify_sys: + * @this: our notifier block + * @code: the event being reported + * @unused: unused + * + * Our notifier is called on system shutdowns. We want to turn the card + * off at reboot otherwise the machine will reboot again during memory + * test or worse yet during the following fsck. This would suck, in fact + * trust me - if it happens it does suck. + */ +static int wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + /* Disable Watchdog */ + wdt_disable(); + return NOTIFY_DONE; +} + +static const struct file_operations wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = wdt_write, + .unlocked_ioctl = wdt_unlocked_ioctl, + .open = wdt_open, + .release = wdt_release, +}; + +static struct miscdevice wdt_dev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &wdt_fops, +}; + +/* + * The WDT card needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ +static struct notifier_block wdt_notifier = { + .notifier_call = wdt_notify_sys, +}; +#endif /* CONFIG_DRV_SYSCPLD_WDT */ + +static int system_cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int err; + + /* allocate memory to system_cpld */ + system_cpld = devm_kzalloc(&client->dev, sizeof(struct system_cpld_data) , GFP_KERNEL); + + if (!system_cpld) + return -ENOMEM; + + mutex_init(&system_cpld->lock); + + err = sysfs_create_group(&client->dev.kobj, &system_cpld_group_misc); + if (err){ + printk("%s: Error creeat misc group.\n", __FUNCTION__); + } + + system_cpld->client = client; + i2c_set_clientdata(client, system_cpld); + + printk(KERN_INFO "%s: System CPLD LCMXO3LF created.\n", __FUNCTION__); + +#ifdef CONFIG_DRV_SYSCPLD_WDT + err = misc_register(&wdt_dev); + if (err) + return err; + err = register_reboot_notifier(&wdt_notifier); + if (err) { + misc_deregister(&wdt_dev); + return err; + } + printk(KERN_INFO "%s: System CPLD watchdog created.\n", __FUNCTION__); +#endif + + return 0; + +} + +static int system_cpld_remove(struct i2c_client *client) +{ +#ifdef CONFIG_DRV_SYSCPLD_WDT + misc_deregister(&wdt_dev); + unregister_reboot_notifier(&wdt_notifier); +#endif + sysfs_remove_group(&client->dev.kobj, &system_cpld_group_misc); + + printk(KERN_INFO "%s: System CPLD removed.\n", __FUNCTION__); + return 0; +} + +static struct i2c_driver system_cpld_driver = { + .driver = { + .name = "system_cpld", + .owner = THIS_MODULE, + }, + .probe = system_cpld_probe, + .remove = system_cpld_remove, + .id_table = system_cpld_ids, +}; + +static int __init system_cpld_init(void) +{ + printk(KERN_INFO "%s: init.\n", __FUNCTION__); + return i2c_add_driver(&system_cpld_driver); +} +module_init(system_cpld_init); + +static void __exit system_cpld_exit(void) +{ + printk(KERN_INFO "%s: exit.\n", __FUNCTION__); + i2c_del_driver(&system_cpld_driver); +} +module_exit(system_cpld_exit); + +MODULE_DESCRIPTION("mitac_ly1200_32x_system_cpld driver"); +MODULE_AUTHOR("Eddy Weng "); +MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/pmbus.h new file mode 100644 index 000000000000..55cb8663e6e9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/pmbus.h @@ -0,0 +1,366 @@ +#ifndef PMBUS_H +#define PMBUS_H + +/* + * Registers + */ +#define PMBUS_PAGE 0x00 +#define PMBUS_OPERATION 0x01 +#define PMBUS_ON_OFF_CONFIG 0x02 +#define PMBUS_CLEAR_FAULTS 0x03 +#define PMBUS_PHASE 0x04 + +#define PMBUS_CAPABILITY 0x19 +#define PMBUS_QUERY 0x1A + +#define PMBUS_VOUT_MODE 0x20 +#define PMBUS_VOUT_COMMAND 0x21 +#define PMBUS_VOUT_TRIM 0x22 +#define PMBUS_VOUT_CAL_OFFSET 0x23 +#define PMBUS_VOUT_MAX 0x24 +#define PMBUS_VOUT_MARGIN_HIGH 0x25 +#define PMBUS_VOUT_MARGIN_LOW 0x26 +#define PMBUS_VOUT_TRANSITION_RATE 0x27 +#define PMBUS_VOUT_DROOP 0x28 +#define PMBUS_VOUT_SCALE_LOOP 0x29 +#define PMBUS_VOUT_SCALE_MONITOR 0x2A + +#define PMBUS_COEFFICIENTS 0x30 +#define PMBUS_POUT_MAX 0x31 + +#define PMBUS_FAN_CONFIG_12 0x3A +#define PMBUS_FAN_COMMAND_1 0x3B +#define PMBUS_FAN_COMMAND_2 0x3C +#define PMBUS_FAN_CONFIG_34 0x3D +#define PMBUS_FAN_COMMAND_3 0x3E +#define PMBUS_FAN_COMMAND_4 0x3F + +#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40 +#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41 +#define PMBUS_VOUT_OV_WARN_LIMIT 0x42 +#define PMBUS_VOUT_UV_WARN_LIMIT 0x43 +#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44 +#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45 +#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46 +#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47 +#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48 +#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49 +#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A +#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B +#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C + +#define PMBUS_OT_FAULT_LIMIT 0x4F +#define PMBUS_OT_FAULT_RESPONSE 0x50 +#define PMBUS_OT_WARN_LIMIT 0x51 +#define PMBUS_UT_WARN_LIMIT 0x52 +#define PMBUS_UT_FAULT_LIMIT 0x53 +#define PMBUS_UT_FAULT_RESPONSE 0x54 +#define PMBUS_VIN_OV_FAULT_LIMIT 0x55 +#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56 +#define PMBUS_VIN_OV_WARN_LIMIT 0x57 +#define PMBUS_VIN_UV_WARN_LIMIT 0x58 +#define PMBUS_VIN_UV_FAULT_LIMIT 0x59 + +#define PMBUS_IIN_OC_FAULT_LIMIT 0x5B +#define PMBUS_IIN_OC_WARN_LIMIT 0x5D + +#define PMBUS_POUT_OP_FAULT_LIMIT 0x68 +#define PMBUS_POUT_OP_WARN_LIMIT 0x6A +#define PMBUS_PIN_OP_WARN_LIMIT 0x6B + +#define PMBUS_STATUS_BYTE 0x78 +#define PMBUS_STATUS_WORD 0x79 +#define PMBUS_STATUS_VOUT 0x7A +#define PMBUS_STATUS_IOUT 0x7B +#define PMBUS_STATUS_INPUT 0x7C +#define PMBUS_STATUS_TEMPERATURE 0x7D +#define PMBUS_STATUS_CML 0x7E +#define PMBUS_STATUS_OTHER 0x7F +#define PMBUS_STATUS_MFR_SPECIFIC 0x80 +#define PMBUS_STATUS_FAN_12 0x81 +#define PMBUS_STATUS_FAN_34 0x82 + +#define PMBUS_READ_VIN 0x88 +#define PMBUS_READ_IIN 0x89 +#define PMBUS_READ_VCAP 0x8A +#define PMBUS_READ_VOUT 0x8B +#define PMBUS_READ_IOUT 0x8C +#define PMBUS_READ_TEMPERATURE_1 0x8D +#define PMBUS_READ_TEMPERATURE_2 0x8E +#define PMBUS_READ_TEMPERATURE_3 0x8F +#define PMBUS_READ_FAN_SPEED_1 0x90 +#define PMBUS_READ_FAN_SPEED_2 0x91 +#define PMBUS_READ_FAN_SPEED_3 0x92 +#define PMBUS_READ_FAN_SPEED_4 0x93 +#define PMBUS_READ_DUTY_CYCLE 0x94 +#define PMBUS_READ_FREQUENCY 0x95 +#define PMBUS_READ_POUT 0x96 +#define PMBUS_READ_PIN 0x97 + +#define PMBUS_REVISION 0x98 +#define PMBUS_MFR_ID 0x99 +#define PMBUS_MFR_MODEL 0x9A +#define PMBUS_MFR_REVISION 0x9B +#define PMBUS_MFR_LOCATION 0x9C +#define PMBUS_MFR_DATE 0x9D +#define PMBUS_MFR_SERIAL 0x9E + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ +#define PMBUS_VIRT_BASE 0x100 +#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0) +#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1) +#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2) +#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3) +#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4) +#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5) +#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6) +#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7) +#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8) +#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9) +#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10) +#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11) +#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12) +#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13) +#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14) +#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15) +#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16) +#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17) +#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18) +#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19) +#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20) +#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21) +#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22) +#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23) +#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24) +#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25) +#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26) +#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27) +#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28) +#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29) + +#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30) +#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31) +#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32) +#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33) +#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34) +#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT (1<<4) +#define PB_CAPABILITY_ERROR_CHECK (1<<7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1)) +#define PB_FAN_2_RPM (1 << 2) +#define PB_FAN_2_INSTALLED (1 << 3) +#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5)) +#define PB_FAN_1_RPM (1 << 6) +#define PB_FAN_1_INSTALLED (1 << 7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE (1<<0) +#define PB_STATUS_CML (1<<1) +#define PB_STATUS_TEMPERATURE (1<<2) +#define PB_STATUS_VIN_UV (1<<3) +#define PB_STATUS_IOUT_OC (1<<4) +#define PB_STATUS_VOUT_OV (1<<5) +#define PB_STATUS_OFF (1<<6) +#define PB_STATUS_BUSY (1<<7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN (1<<8) +#define PB_STATUS_OTHER (1<<9) +#define PB_STATUS_FANS (1<<10) +#define PB_STATUS_POWER_GOOD_N (1<<11) +#define PB_STATUS_WORD_MFR (1<<12) +#define PB_STATUS_INPUT (1<<13) +#define PB_STATUS_IOUT_POUT (1<<14) +#define PB_STATUS_VOUT (1<<15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING (1<<0) +#define PB_POUT_OP_FAULT (1<<1) +#define PB_POWER_LIMITING (1<<2) +#define PB_CURRENT_SHARE_FAULT (1<<3) +#define PB_IOUT_UC_FAULT (1<<4) +#define PB_IOUT_OC_WARNING (1<<5) +#define PB_IOUT_OC_LV_FAULT (1<<6) +#define PB_IOUT_OC_FAULT (1<<7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT (1<<4) +#define PB_VOLTAGE_UV_WARNING (1<<5) +#define PB_VOLTAGE_OV_WARNING (1<<6) +#define PB_VOLTAGE_OV_FAULT (1<<7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING (1<<0) +#define PB_IIN_OC_WARNING (1<<1) +#define PB_IIN_OC_FAULT (1<<2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT (1<<4) +#define PB_TEMP_UT_WARNING (1<<5) +#define PB_TEMP_OT_WARNING (1<<6) +#define PB_TEMP_OT_FAULT (1<<7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING (1<<0) +#define PB_FAN_AIRFLOW_FAULT (1<<1) +#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2) +#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3) +#define PB_FAN_FAN2_WARNING (1<<4) +#define PB_FAN_FAN1_WARNING (1<<5) +#define PB_FAN_FAN2_FAULT (1<<6) +#define PB_FAN_FAN1_FAULT (1<<7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0) +#define PB_CML_FAULT_OTHER_COMM (1<<1) +#define PB_CML_FAULT_PROCESSOR (1<<3) +#define PB_CML_FAULT_MEMORY (1<<4) +#define PB_CML_FAULT_PACKET_ERROR (1<<5) +#define PB_CML_FAULT_INVALID_DATA (1<<6) +#define PB_CML_FAULT_INVALID_COMMAND (1<<7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN (1 << 0) +#define PMBUS_HAVE_VCAP (1 << 1) +#define PMBUS_HAVE_VOUT (1 << 2) +#define PMBUS_HAVE_IIN (1 << 3) +#define PMBUS_HAVE_IOUT (1 << 4) +#define PMBUS_HAVE_PIN (1 << 5) +#define PMBUS_HAVE_POUT (1 << 6) +#define PMBUS_HAVE_FAN12 (1 << 7) +#define PMBUS_HAVE_FAN34 (1 << 8) +#define PMBUS_HAVE_TEMP (1 << 9) +#define PMBUS_HAVE_TEMP2 (1 << 10) +#define PMBUS_HAVE_TEMP3 (1 << 11) +#define PMBUS_HAVE_STATUS_VOUT (1 << 12) +#define PMBUS_HAVE_STATUS_IOUT (1 << 13) +#define PMBUS_HAVE_STATUS_INPUT (1 << 14) +#define PMBUS_HAVE_STATUS_TEMP (1 << 15) +#define PMBUS_HAVE_STATUS_FAN12 (1 << 16) +#define PMBUS_HAVE_STATUS_FAN34 (1 << 17) +#define PMBUS_HAVE_VMON (1 << 18) +#define PMBUS_HAVE_STATUS_VMON (1 << 19) + +enum pmbus_data_format { linear = 0, direct, vid }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); +}; + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +void pmbus_clear_faults(struct i2c_client *client); +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); + +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_reg.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_reg.h new file mode 100644 index 000000000000..a8169bdb88ee --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_reg.h @@ -0,0 +1,192 @@ +#ifndef __SLAVE_CPLD_REG +#define __SLAVE_CPLD_REG + +static int slave_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); +static int slave_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); + +/* generic CPLD read function */ +#define FLD_RAW_RD_FUNC(_reg, _fld, _wdh) static ssize_t \ +slave_cpld_##_fld##_raw_read(struct device *dev, struct device_attribute *attr, char *buf) { \ + return slave_cpld_raw_read(dev, attr, buf, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* generic CPLD write function */ +#define FLD_RAW_WR_FUNC(_reg, _fld, _wdh) static ssize_t \ +slave_cpld_##_fld##_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { \ + return slave_cpld_raw_write(dev, attr, buf, count, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* CPLD register definition macros */ +#define REG_DEF(_reg, _off, _wdh) \ +static unsigned int _reg##_offset = (unsigned int)(_off); \ +static unsigned int _reg##_width = (unsigned int)(_wdh); + +/* CPLD register field definition macros, with generic read/write function */ +#define FLD_RAW_RO_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) + +#define FLD_RAW_RW_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) FLD_RAW_WR_FUNC(_reg, _fld, _wdh) + +/* declare slave CPLD registers */ +/* register name offset width */ +/* --------------------------------------- ------- ----- */ +REG_DEF( slv_cpld_rev, 0x00, 8) +REG_DEF( slv_cpld_gpr, 0x01, 8) +REG_DEF( mb_brd_rev_type, 0x02, 8) + +REG_DEF( zqsfp28_present_24_17_status, 0x10, 8) +REG_DEF( zqsfp28_present_32_25_status, 0x11, 8) +REG_DEF( zqsfp28_rst_24_17, 0x12, 8) +REG_DEF( zqsfp28_rst_32_25, 0x13, 8) +REG_DEF( zqsfp28_modsel_24_17, 0x14, 8) +REG_DEF( zqsfp28_modsel_32_25, 0x15, 8) +REG_DEF( zqsfp28_lpmode_24_17, 0x16, 8) +REG_DEF( zqsfp28_lpmode_32_25, 0x17, 8) +REG_DEF( zqsfp28_irq_24_17_status, 0x18, 8) +REG_DEF( zqsfp28_irq_32_25_status, 0x19, 8) +REG_DEF( zqsfp28_irq_msk_24_17_status, 0x1A, 8) +REG_DEF( zqsfp28_irq_msk_32_25_status, 0x1B, 8) + + +/* declare slave CPLD register's fields */ +/* register name field name shift width */ +/* ---------------------- ---------------- ------ ----- */ +FLD_RAW_RO_DEF( slv_cpld_rev, mjr_rev, 4, 4) +FLD_RAW_RO_DEF( slv_cpld_rev, mnr_rev, 0, 4) + +FLD_RAW_RW_DEF( slv_cpld_gpr, scrtch_reg, 0, 8) + +FLD_RAW_RO_DEF( mb_brd_rev_type, brd_rev, 4, 4) +FLD_RAW_RO_DEF( mb_brd_rev_type, brd_type, 0, 4) + +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port24_present, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port23_present, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port22_present, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port21_present, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port20_present, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port19_present, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port18_present, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port17_present, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port32_present, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port31_present, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port30_present, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port29_present, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port28_present, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port27_present, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port26_present, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port25_present, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port24_rst, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port23_rst, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port22_rst, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port21_rst, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port20_rst, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port19_rst, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port18_rst, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port17_rst, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port32_rst, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port31_rst, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port30_rst, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port29_rst, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port28_rst, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port27_rst, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port26_rst, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port25_rst, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port24_modsel, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port23_modsel, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port22_modsel, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port21_modsel, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port20_modsel, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port19_modsel, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port18_modsel, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port17_modsel, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port32_modsel, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port31_modsel, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port30_modsel, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port29_modsel, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port28_modsel, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port27_modsel, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port26_modsel, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port25_modsel, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port24_lpmode, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port23_lpmode, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port22_lpmode, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port21_lpmode, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port20_lpmode, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port19_lpmode, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port18_lpmode, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port17_lpmode, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port32_lpmode, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port31_lpmode, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port30_lpmode, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port29_lpmode, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port28_lpmode, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port27_lpmode, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port26_lpmode, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port25_lpmode, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port24_irq_status, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port23_irq_status, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port22_irq_status, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port21_irq_status, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port20_irq_status, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port19_irq_status, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port18_irq_status, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port17_irq_status, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port32_irq_status, 7, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port31_irq_status, 6, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port30_irq_status, 5, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port29_irq_status, 4, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port28_irq_status, 3, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port27_irq_status, 2, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port26_irq_status, 1, 1) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port25_irq_status, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port24_irq_msk, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port23_irq_msk, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port22_irq_msk, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port21_irq_msk, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port20_irq_msk, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port19_irq_msk, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port18_irq_msk, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port17_irq_msk, 0, 1) + +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port32_irq_msk, 7, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port31_irq_msk, 6, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port30_irq_msk, 5, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port29_irq_msk, 4, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port28_irq_msk, 3, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port27_irq_msk, 2, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port26_irq_msk, 1, 1) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port25_irq_msk, 0, 1) + +FLD_RAW_RO_DEF( zqsfp28_present_24_17_status, port_17_24_present, 0, 8) +FLD_RAW_RO_DEF( zqsfp28_present_32_25_status, port_25_32_present, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_rst_24_17, port_17_24_rst, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_rst_32_25, port_25_32_rst, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_modsel_24_17, port_17_24_modsel, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_modsel_32_25, port_25_32_modsel, 0, 8) +FLD_RAW_RO_DEF( zqsfp28_irq_24_17_status, port_17_24_irq_status,0, 8) +FLD_RAW_RO_DEF( zqsfp28_irq_32_25_status, port_25_32_irq_status,0, 8) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_24_17_status, port_17_24_irq_msk, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_irq_msk_32_25_status, port_25_32_irq_msk, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_lpmode_24_17, port_17_24_lpmode, 0, 8) +FLD_RAW_RW_DEF( zqsfp28_lpmode_32_25, port_25_32_lpmode, 0, 8) + +#endif /* __SLAVE_CPLD_REG */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h new file mode 100644 index 000000000000..92d00d29d493 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h @@ -0,0 +1,155 @@ +#ifndef __SLAVE_CPLD_SYSFS +#define __SLAVE_CPLD_SYSFS + +/* generic CPLD sysfs file definition macros */ +#define SYSFS_RAW_RO_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, slave_cpld_##field##_raw_read, NULL); + +#define SYSFS_RAW_RW_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, slave_cpld_##field##_raw_read, slave_cpld_##field##_raw_write); + +#define SYSFS_MISC_RO_ATTR_DEF(field, _read) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, _read, NULL); + +#define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write); + +#define SYSFS_ATTR_PTR(field) \ +&field.attr + + +/* declare slave CPLD file system */ +SYSFS_RAW_RO_ATTR_DEF(mjr_rev) +SYSFS_RAW_RO_ATTR_DEF(mnr_rev) + +SYSFS_RAW_RW_ATTR_DEF(scrtch_reg) + +SYSFS_RAW_RO_ATTR_DEF(brd_rev) +SYSFS_RAW_RO_ATTR_DEF(brd_type) + +SYSFS_RAW_RO_ATTR_DEF(port24_present) +SYSFS_RAW_RO_ATTR_DEF(port23_present) +SYSFS_RAW_RO_ATTR_DEF(port22_present) +SYSFS_RAW_RO_ATTR_DEF(port21_present) +SYSFS_RAW_RO_ATTR_DEF(port20_present) +SYSFS_RAW_RO_ATTR_DEF(port19_present) +SYSFS_RAW_RO_ATTR_DEF(port18_present) +SYSFS_RAW_RO_ATTR_DEF(port17_present) + +SYSFS_RAW_RO_ATTR_DEF(port32_present) +SYSFS_RAW_RO_ATTR_DEF(port31_present) +SYSFS_RAW_RO_ATTR_DEF(port30_present) +SYSFS_RAW_RO_ATTR_DEF(port29_present) +SYSFS_RAW_RO_ATTR_DEF(port28_present) +SYSFS_RAW_RO_ATTR_DEF(port27_present) +SYSFS_RAW_RO_ATTR_DEF(port26_present) +SYSFS_RAW_RO_ATTR_DEF(port25_present) + +SYSFS_RAW_RW_ATTR_DEF(port24_rst) +SYSFS_RAW_RW_ATTR_DEF(port23_rst) +SYSFS_RAW_RW_ATTR_DEF(port22_rst) +SYSFS_RAW_RW_ATTR_DEF(port21_rst) +SYSFS_RAW_RW_ATTR_DEF(port20_rst) +SYSFS_RAW_RW_ATTR_DEF(port19_rst) +SYSFS_RAW_RW_ATTR_DEF(port18_rst) +SYSFS_RAW_RW_ATTR_DEF(port17_rst) + +SYSFS_RAW_RW_ATTR_DEF(port32_rst) +SYSFS_RAW_RW_ATTR_DEF(port31_rst) +SYSFS_RAW_RW_ATTR_DEF(port30_rst) +SYSFS_RAW_RW_ATTR_DEF(port29_rst) +SYSFS_RAW_RW_ATTR_DEF(port28_rst) +SYSFS_RAW_RW_ATTR_DEF(port27_rst) +SYSFS_RAW_RW_ATTR_DEF(port26_rst) +SYSFS_RAW_RW_ATTR_DEF(port25_rst) + +SYSFS_RAW_RW_ATTR_DEF(port24_modsel) +SYSFS_RAW_RW_ATTR_DEF(port23_modsel) +SYSFS_RAW_RW_ATTR_DEF(port22_modsel) +SYSFS_RAW_RW_ATTR_DEF(port21_modsel) +SYSFS_RAW_RW_ATTR_DEF(port20_modsel) +SYSFS_RAW_RW_ATTR_DEF(port19_modsel) +SYSFS_RAW_RW_ATTR_DEF(port18_modsel) +SYSFS_RAW_RW_ATTR_DEF(port17_modsel) + +SYSFS_RAW_RW_ATTR_DEF(port32_modsel) +SYSFS_RAW_RW_ATTR_DEF(port31_modsel) +SYSFS_RAW_RW_ATTR_DEF(port30_modsel) +SYSFS_RAW_RW_ATTR_DEF(port29_modsel) +SYSFS_RAW_RW_ATTR_DEF(port28_modsel) +SYSFS_RAW_RW_ATTR_DEF(port27_modsel) +SYSFS_RAW_RW_ATTR_DEF(port26_modsel) +SYSFS_RAW_RW_ATTR_DEF(port25_modsel) + +SYSFS_RAW_RW_ATTR_DEF(port24_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port23_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port22_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port21_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port20_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port19_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port18_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port17_lpmode) + +SYSFS_RAW_RW_ATTR_DEF(port32_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port31_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port30_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port29_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port28_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port27_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port26_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port25_lpmode) + +SYSFS_RAW_RO_ATTR_DEF(port24_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port23_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port22_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port21_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port20_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port19_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port18_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port17_irq_status) + +SYSFS_RAW_RO_ATTR_DEF(port32_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port31_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port30_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port29_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port28_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port27_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port26_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port25_irq_status) + +SYSFS_RAW_RW_ATTR_DEF(port24_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port23_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port22_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port21_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port20_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port19_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port18_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port17_irq_msk) + +SYSFS_RAW_RW_ATTR_DEF(port32_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port31_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port30_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port29_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port28_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port27_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port26_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port25_irq_msk) + +SYSFS_RAW_RO_ATTR_DEF(port_17_24_present) +SYSFS_RAW_RO_ATTR_DEF(port_25_32_present) +SYSFS_RAW_RW_ATTR_DEF(port_17_24_rst) +SYSFS_RAW_RW_ATTR_DEF(port_25_32_rst) +SYSFS_RAW_RW_ATTR_DEF(port_17_24_modsel) +SYSFS_RAW_RW_ATTR_DEF(port_25_32_modsel) +SYSFS_RAW_RO_ATTR_DEF(port_17_24_irq_status) +SYSFS_RAW_RO_ATTR_DEF(port_25_32_irq_status) +SYSFS_RAW_RW_ATTR_DEF(port_17_24_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port_25_32_irq_msk) +SYSFS_RAW_RW_ATTR_DEF(port_17_24_lpmode) +SYSFS_RAW_RW_ATTR_DEF(port_25_32_lpmode) + +#endif /* __SLAVE_CPLD_SYSFS */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_reg.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_reg.h new file mode 100644 index 000000000000..ba66519efe8a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_reg.h @@ -0,0 +1,107 @@ +#ifndef __SYSTEM_CPLD_REG +#define __SYSTEM_CPLD_REG + +static int system_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); +static int system_cpld_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count, + int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name); + +/* generic CPLD read function */ +#define FLD_RAW_RD_FUNC(_reg, _fld, _wdh) static ssize_t \ +system_cpld_##_fld##_raw_read(struct device *dev, struct device_attribute *attr, char *buf) { \ + return system_cpld_raw_read(dev, attr, buf, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* generic CPLD write function */ +#define FLD_RAW_WR_FUNC(_reg, _fld, _wdh) static ssize_t \ +system_cpld_##_fld##_raw_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { \ + return system_cpld_raw_write(dev, attr, buf, count, _reg##_offset, _reg##_width, _fld##_shift, _fld##_width, _fld##_mask, #_reg); \ +} + +/* CPLD register definition macros */ +#define REG_DEF(_reg, _off, _wdh) \ +static unsigned int _reg##_offset = (unsigned int)(_off); \ +static unsigned int _reg##_width = (unsigned int)(_wdh); + +/* CPLD register field definition macros, with generic read/write function */ +#define FLD_RAW_RO_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) + +#define FLD_RAW_RW_DEF(_reg, _fld, _sft, _wdh) \ +static unsigned int _fld##_shift = (unsigned int)(_sft); \ +static unsigned int _fld##_width = (unsigned int)(_wdh); \ +static unsigned int _fld##_mask = ((((unsigned int)1) << (_wdh)) - 1); \ +FLD_RAW_RD_FUNC(_reg, _fld, _wdh) FLD_RAW_WR_FUNC(_reg, _fld, _wdh) + +/* declare system CPLD registers */ +/* register name offset width */ +/* --------------------------------------- ------- ----- */ +REG_DEF( sys_cpld_rev, 0x00, 8) +REG_DEF( sys_cpld_gpr, 0x01, 8) +REG_DEF( cpu_brd_rev_type, 0x02, 8) +REG_DEF( sys_srr, 0x03, 8) +REG_DEF( sys_eeprom_wp, 0x04, 8) +REG_DEF( sys_irq, 0x05, 8) +REG_DEF( sys_wd, 0x06, 8) +REG_DEF( sys_mb_rst_en, 0x07, 8) +REG_DEF( cpu_pwr_en_status, 0x08, 8) +REG_DEF( cpu_pwr_status, 0x09, 8) + + +/* declare system CPLD register's fields */ +/* register name field name shift width */ +/* ---------------------- ---------------- ------ ----- */ +FLD_RAW_RO_DEF( sys_cpld_rev, mjr_rev, 4, 4) +FLD_RAW_RO_DEF( sys_cpld_rev, mnr_rev, 0, 4) + +FLD_RAW_RW_DEF( sys_cpld_gpr, scrtch_reg, 0, 8) + +FLD_RAW_RO_DEF( cpu_brd_rev_type, brd_rev, 4, 4) +FLD_RAW_RO_DEF( cpu_brd_rev_type, brd_type, 0, 4) + +FLD_RAW_RO_DEF( sys_srr, ssd_present, 3, 1) +FLD_RAW_RW_DEF( sys_srr, spi_cs_sel, 2, 1) +FLD_RAW_RW_DEF( sys_srr, rst_bios_switch, 1, 1) +FLD_RAW_RW_DEF( sys_srr, cpld_upgrade_rst, 0, 1) + +FLD_RAW_RW_DEF( sys_eeprom_wp, cpld_spi_wp, 4, 1) +FLD_RAW_RW_DEF( sys_eeprom_wp, system_id_eeprom_wp, 3, 1) +FLD_RAW_RW_DEF( sys_eeprom_wp, spi_me_wp, 2, 1) +FLD_RAW_RW_DEF( sys_eeprom_wp, spi_bios_wp, 1, 1) +FLD_RAW_RW_DEF( sys_eeprom_wp, spi_bak_bios_wp, 0, 1) + +FLD_RAW_RW_DEF( sys_irq, vrhot_irq_en, 6, 1) +FLD_RAW_RW_DEF( sys_irq, cpu_thermtrip_irq_en,5, 1) +FLD_RAW_RW_DEF( sys_irq, temp_alert_irq_en, 4, 1) +FLD_RAW_RO_DEF( sys_irq, vrhot_irq, 2, 1) +FLD_RAW_RO_DEF( sys_irq, cpu_thermtrip_irq, 1, 1) +FLD_RAW_RO_DEF( sys_irq, temp_alert_irq, 0, 1) + +FLD_RAW_RW_DEF( sys_wd, wd_timer, 4, 4) +FLD_RAW_RW_DEF( sys_wd, wd_en, 1, 1) +FLD_RAW_RW_DEF( sys_wd, wd_punch, 0, 1) + +FLD_RAW_RW_DEF( sys_mb_rst_en, mb_rst_en, 0, 1) + +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_v3p3_en, 7, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_vcc_vnn_en, 6, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_vccsram_en, 5, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_vddq_en, 4, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_vcc_ref_en, 3, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_v1p05_en, 2, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_v1p8_en, 1, 1) +FLD_RAW_RO_DEF( cpu_pwr_en_status, pwr_v2p5_en, 0, 1) + +FLD_RAW_RO_DEF( cpu_pwr_status, pg_v3p3, 7, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_vcc_vnn, 6, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_vccsram, 5, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_vddq, 4, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_vcc_ref, 3, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_v1p05, 2, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_v1p8, 1, 1) +FLD_RAW_RO_DEF( cpu_pwr_status, pg_v2p5, 0, 1) + +#endif /* __SYSTEM_CPLD_REG */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h new file mode 100644 index 000000000000..e6b03bd1bd0d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h @@ -0,0 +1,76 @@ +#ifndef __SYSTEM_CPLD_SYSFS +#define __SYSTEM_CPLD_SYSFS + +/* generic CPLD sysfs file definition macros */ +#define SYSFS_RAW_RO_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, system_cpld_##field##_raw_read, NULL); + +#define SYSFS_RAW_RW_ATTR_DEF(field) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, system_cpld_##field##_raw_read, system_cpld_##field##_raw_write); + +#define SYSFS_MISC_RO_ATTR_DEF(field, _read) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO, _read, NULL); + +#define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \ +struct device_attribute field \ + = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write); + +#define SYSFS_ATTR_PTR(field) \ +&field.attr + + +/* declare system CPLD file system */ +SYSFS_RAW_RO_ATTR_DEF(mjr_rev) +SYSFS_RAW_RO_ATTR_DEF(mnr_rev) + +SYSFS_RAW_RW_ATTR_DEF(scrtch_reg) + +SYSFS_RAW_RO_ATTR_DEF(brd_rev) +SYSFS_RAW_RO_ATTR_DEF(brd_type) + +SYSFS_RAW_RO_ATTR_DEF(ssd_present) +SYSFS_RAW_RW_ATTR_DEF(spi_cs_sel) +SYSFS_RAW_RW_ATTR_DEF(rst_bios_switch) +SYSFS_RAW_RW_ATTR_DEF(cpld_upgrade_rst) + +SYSFS_RAW_RW_ATTR_DEF(cpld_spi_wp) +SYSFS_RAW_RW_ATTR_DEF(system_id_eeprom_wp) +SYSFS_RAW_RW_ATTR_DEF(spi_me_wp) +SYSFS_RAW_RW_ATTR_DEF(spi_bios_wp) +SYSFS_RAW_RW_ATTR_DEF(spi_bak_bios_wp) + +SYSFS_RAW_RW_ATTR_DEF(vrhot_irq_en) +SYSFS_RAW_RW_ATTR_DEF(cpu_thermtrip_irq_en) +SYSFS_RAW_RW_ATTR_DEF(temp_alert_irq_en) +SYSFS_RAW_RO_ATTR_DEF(vrhot_irq) +SYSFS_RAW_RO_ATTR_DEF(cpu_thermtrip_irq) +SYSFS_RAW_RO_ATTR_DEF(temp_alert_irq) + +SYSFS_RAW_RW_ATTR_DEF(wd_timer) +SYSFS_RAW_RW_ATTR_DEF(wd_en) +SYSFS_RAW_RW_ATTR_DEF(wd_punch) + +SYSFS_RAW_RW_ATTR_DEF(mb_rst_en) + +SYSFS_RAW_RO_ATTR_DEF(pwr_v3p3_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_vcc_vnn_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_vccsram_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_vddq_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_vcc_ref_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_v1p05_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_v1p8_en) +SYSFS_RAW_RO_ATTR_DEF(pwr_v2p5_en) + +SYSFS_RAW_RO_ATTR_DEF(pg_v3p3) +SYSFS_RAW_RO_ATTR_DEF(pg_vcc_vnn) +SYSFS_RAW_RO_ATTR_DEF(pg_vccsram) +SYSFS_RAW_RO_ATTR_DEF(pg_vddq) +SYSFS_RAW_RO_ATTR_DEF(pg_vcc_ref) +SYSFS_RAW_RO_ATTR_DEF(pg_v1p05) +SYSFS_RAW_RO_ATTR_DEF(pg_v1p8) +SYSFS_RAW_RO_ATTR_DEF(pg_v2p5) + +#endif /* __SYSTEM_CPLD_SYSFS */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-ctrl b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-ctrl new file mode 100755 index 000000000000..73ff759b6f45 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-ctrl @@ -0,0 +1,679 @@ +#!/bin/bash +#/* +#********************************************************************** +#* +#* @filename fan-ctrl +#* +#* @purpose system daemon for controlling system fan pwm +#* +#* @create 2017/06/21 +#* +#* @author nixon.chu +#* +#* @history 2017/06/21: init version +#* +#********************************************************************** +#*/ + +DIR=$(dirname $0) + +# include files +source ${DIR}/funcs.sh + +#/* +#********************************************************************** +#* +#* CONSTANT VARIABLES +#* +#********************************************************************** +#*/ + +# process name/id +DAEMON_NAME=`basename $0` +DAEMON_PID="$$" + +# define symbol for fan/temperature type sensor +SYMBOL_TEMP="TEMP_" +SYMBOL_FAN="FAN_" + +# describe the structure of temperature sensor by id +STRUCT_TEMP_NAME=0 +STRUCT_TEMP_CMD=1 +STRUCT_TEMP_MAX=2 +STRUCT_TEMP_SIZE=$(( ${STRUCT_TEMP_MAX} + 1 )) + +# describe the structure of fan sensor by id +STRUCT_FAN_CMD=0 +STRUCT_FAN_SIZE=$(( ${STRUCT_FAN_CMD} + 1 )) + +# default fan zone configuration file +DEF_ZONE_CONF="${DIR}/fan-zone.conf" + +# default fan zone thermal configuration file +DEF_TEMP_CONF="${DIR}/fan-zone-thermal.conf" + +# default interval (sec) +DEF_INTERVAL=10 + +# default hysteresis (deg C) +DEF_HYSIS=3 + +# default debug mode (0: OFF, 1: ON) +DEF_DEBUG_MODE=0 + +# default log file +DEF_LOG_FILE="/var/log/syslog" + +# default fan level +DEF_FAN_LEVEL=0 + +# default minimum pwm (38.25=255x15%) +DEF_MIN_PWM=39 + +# default zone id +DEF_ZONE_ID=0 + +# error codes +E_STATUS_GOOD=0 +E_STATUS_FAULT=1 +E_INVALID_ARGS=11 +E_INVALID_CONF=12 + +# message levels +MSG_EMERG=0 +MSG_ALERT=1 +MSG_CRIT=2 +MSG_ERR=3 +MSG_WARNING=4 +MSG_NOTICE=5 +MSG_INFO=6 +MSG_DEBUG=7 + +# default message level +DEF_MSG_LEVEL=$MSG_WARNING + +#/* +#********************************************************************** +#* +#* GLOBAL VARIABLES +#* +#********************************************************************** +#*/ + +# temperature sensor group +GBL_TEMP_GRP=() +GBL_TEMP_NUM=${#GBL_TEMP_GRP[@]} + +# fan sensor group +GBL_FAN_GRP=() +GBL_FAN_NUM=${#GBL_FAN_GRP[@]} + +# fan level table +GBL_FAN_LEVEL=() +GBL_LEVEL_NUM=${#GBL_FAN_LEVEL[@]} + +# load defaults +GBL_ZONE_CONF=$DEF_ZONE_CONF +GBL_TEMP_CONF=$DEF_TEMP_CONF +GBL_INTERVAL=$DEF_INTERVAL +GBL_HYSIS=$DEF_HYSIS +GBL_DEBUG_MODE=$DEF_DEBUG_MODE +GBL_LOG_FILE=$DEF_LOG_FILE +GBL_CUR_LEVEL=$DEF_FAN_LEVEL +GBL_MIN_PWM=$DEF_MIN_PWM +GBL_ZONE_ID=$DEF_ZONE_ID +GBL_MSG_LEVEL=$DEF_MSG_LEVEL + +# temperature sensors' readings/statuses/properties (properties list have to be converted with fan level table) +GBL_TEMP_READINGS=() +GBL_TEMP_STATUSES=() +GBL_TEMP_PROPERTY=() + +#/* +#********************************************************************** +#* +#* FUNCTIONS +#* +#********************************************************************** +#*/ + +#/* +#* FEATURE: +#* usage +#* PURPOSE: +#* show the usage of this daemon +#* PARAMETERS: +#* +#* RETURNS: +#* success, this function returns @E_INVALID_ARGS. +#*/ +function usage() { + local dbg_mode + + [ $GBL_DEBUG_MODE -eq 0 ] && dbg_mode="off" || dbg_mode="on" + + echo -e "Usage: $0 [-z zone_file] [-t thermal_file] [-o log_file] [-d]" >&2 + echo -e "" >&2 + echo -e "Arguments:" >&2 + echo -e " -z, --zone-config Fan zone configuration file (default: $DEF_ZONE_CONF)" >&2 + echo -e " -t, --temp-config Fan zone thermal configuration file (default: $DEF_TEMP_CONF)" >&2 + echo -e " -o, --log-file Log file (default: $DEF_LOG_FILE)" >&2 + echo -e " -d, --debug Debug mode (default: $dbg_mode)" >&2 + exit ${E_INVALID_ARGS} +} + +#/* +#* FEATURE: +#* print_msg +#* PURPOSE: +#* print message by message level +#* PARAMETERS: +#* msg_lvl (IN) message level +#* msg (IN) message +#* RETURNS: +#* +#*/ +function print_msg() { + local msg_lvl=$1 + local msg=$2 + + [ $msg_lvl -le $GBL_MSG_LEVEL ] && echo "${msg}" >&2 +} + +#/* +#* FEATURE: +#* err_msg +#* PURPOSE: +#* log error message +#* PARAMETERS: +#* msg (IN) message +#* err_no (IN) error code +#* RETURNS: +#* success, this function returns non-zero error code. +#*/ +function err_msg() { + local msg=$1 + local err_no=$2 + + log_msg $MSG_ERROR "${msg}" + exit ${err_no} +} + +#/* +#* FEATURE: +#* log_msg +#* PURPOSE: +#* log message +#* PARAMETERS: +#* msg_lvl (IN) message level +#* msg (IN) message +#* RETURNS: +#* +#*/ +function log_msg() { + local msg_lvl=$1 + local msg=$2 + + if [ $GBL_LOG_FILE == $DEF_LOG_FILE ]; then + `logger -t $DAEMON_NAME -p $msg_lvl $msg` + else + echo -e "`date +"%b %_d %T"` `hostname` $DAEMON_NAME[$DAEMON_PID]: ${msg}" >> ${GBL_LOG_FILE} + fi + + print_msg $msg_lvl "${msg}" +} + +#/* +#* FEATURE: +#* debug_temp_grp +#* PURPOSE: +#* debug function for showing the temperature sensor group configs +#* @GBL_TEMP_GRP[]: store sensor group configs (sensor name, command, and max_temp) +#* PARAMETERS: +#* +#* RETURNS: +#* +#*/ +function debug_temp_grp() { + if [ $GBL_DEBUG_MODE -ne 0 ]; then + echo "********* Sensor Group *********" + for ((i=0; i<$GBL_TEMP_NUM; i++)) + do + echo -en "`fetch_temp_struct $i $STRUCT_TEMP_NAME`\t" + echo -en "`fetch_temp_struct $i $STRUCT_TEMP_CMD`\t" + echo "`fetch_temp_struct $i $STRUCT_TEMP_MAX`" + done + fi +} + +#/* +#* FEATURE: +#* debug_temp_readings +#* PURPOSE: +#* debug function for showing the temperature sensors' readings +#* @GBL_TEMP_READINGS[]: store current reading for temperature sensors +#* PARAMETERS: +#* +#* RETURNS: +#* +#*/ +function debug_temp_readings() { + if [ $GBL_DEBUG_MODE -ne 0 ]; then + echo "********* Sensor Reading *********" + for ((i=0; i<$GBL_TEMP_NUM; i++)) + do + echo -e "`fetch_temp_struct $i $STRUCT_TEMP_NAME`\t${GBL_TEMP_READINGS[$i]}" + done + fi +} + +#/* +#* FEATURE: +#* debug_temp_property +#* PURPOSE: +#* debug function for showing the temperature sensors' properties +#* @GBL_TEMP_PROPERTY[]: store temperature sensors' properties (asserted temperature for each fan levels) +#* PARAMETERS: +#* +#* RETURNS: +#* +#*/ +function debug_temp_property() { + local size base start_idx level + if [ $GBL_DEBUG_MODE -ne 0 ]; then + echo "********* Sensor Table *********" + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + # show array @GBL_TEMP_PROPERTY[]: format name(1) + fan levels(2-?) + size=$(( ${GBL_LEVEL_NUM}+1 )) + base=$i*${size} + start_idx=$(( $base+1 )) + level=${GBL_LEVEL_NUM} + echo -e "${GBL_TEMP_PROPERTY[$base]}\t\t${GBL_TEMP_PROPERTY[@]:$start_idx:$level}" + done + fi +} + +#/* +#* FEATURE: +#* fetch_temp_struct +#* PURPOSE: +#* fetch the member value of specific temperature sensor +#* PARAMETERS: +#* id (IN) sensor id +#* member_id (IN) member id +#* RETURNS: +#* success, returns member value +#*/ +function fetch_temp_struct() { + local id member_id index_base data + + id=$1 + member_id=$2 + + index_base=$(( $id * $STRUCT_TEMP_SIZE )) + data=${GBL_TEMP_GRP[$(($index_base+$member_id))]} + # remove unuseful characters, such as double quotes('"') and the start/end space(' ') of a string. + data=`echo $data | sed 's/^ *\| *$//g' | sed 's/^"\|\"$//g'` + echo $data +} + +#/* +#* FEATURE: +#* fetch_temp_property +#* PURPOSE: +#* fetch the properties of specific temperature sensor +#* PARAMETERS: +#* name (IN) sensor name +#* RETURNS: +#* success, returns an asserted temperature list +#*/ +function fetch_temp_property() { + local name size base start_idx length + + name=$1 + + size=$(( $GBL_LEVEL_NUM+1 )) + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + base=$i*${size} + # find sensor by name + if [ ${GBL_TEMP_PROPERTY[${base}]} == "${name}" ]; then + start_idx=$(( $base+1 )) + length=$GBL_LEVEL_NUM + echo ${GBL_TEMP_PROPERTY[@]:$start_idx:$length} + break + fi + done +} + +#/* +#* FEATURE: +#* debug_fan_speed +#* PURPOSE: +#* debug function for showing system current fan level and PWM +#* @GBL_CUR_LEVEL: system current/output fan level +#* PARAMETERS: +#* +#* RETURNS: +#* +#*/ +function debug_fan_speed() { + if [ $GBL_DEBUG_MODE -ne 0 ]; then + # For human readable, the representation of fan level will start from 1. + echo "Current Level: $(( $GBL_CUR_LEVEL+1 )), PWM: ${GBL_FAN_LEVEL[$GBL_CUR_LEVEL]}" + fi +} + +#/* +#* FEATURE: +#* arg_parse +#* PURPOSE: +#* parser for input arguments +#* PARAMETERS: +#* arg_lists[] (IN) argument list +#* RETURNS: +#* +#*/ +function arg_parse() { + while [[ $# -ge 1 ]] + do + key="$1" + case $key in + -z|--zone-config) + [ $# -lt 2 ] && usage + GBL_ZONE_CONF=$2 + [ ! -e $GBL_ZONE_CONF ] && usage + shift # past argument + ;; + -t|--temp-config) + [ $# -lt 2 ] && usage + GBL_TEMP_CONF=$2 + [ ! -e $GBL_TEMP_CONF ] && usage + shift # past argument + ;; + -o|--log-file) + [ $# -lt 2 ] && usage + GBL_LOG_FILE=$2 + shift # past argument + ;; + -d|--debug) + GBL_DEBUG_MODE=1 + ;; + *) + usage # unknown option + ;; + esac + shift # past argument or value + done +} + +#/* +#* FEATURE: +#* valid_conf +#* PURPOSE: +#* check if configuration files are valid +#* PARAMETERS: +#* +#* RETURNS: +#* success, this function returns nothing +#* fail, returns @E_INVALID_CONF +#*/ +function valid_conf() { + local list_1 list_2 match_num + + list_1=("${!1}") + list_2=("${!2}") + + # validate zone config + [ ${GBL_TEMP_NUM} -eq 0 ] && err_msg "config: status=invalid. reason=no TEMPERATURE SENSORS defined." "${E_INVALID_CONF}" + [ ${GBL_FAN_NUM} -eq 0 ] && err_msg "config: status=invalid. reason=no FAN defined." "${E_INVALID_CONF}" + + # validate thermal config + [ ${GBL_LEVEL_NUM} -eq 0 ] && err_msg "config: status=invalid. reason=no FAN LEVELS defined." "${E_INVALID_CONF}" + [ ${#list_2[@]} -ne ${GBL_TEMP_NUM} ] && err_msg "config: status=invalid. reason=the number of temperature sensors is inconsistent." "${E_INVALID_CONF}" + + # compare temperature sensor name between configuration files + match_num=0 + for i in ${!list_1[@]} + do + for j in ${!list_2[@]} + do + [ "${list_1[$i]}" == "${list_2[$j]}" ] && match_num=$(( $match_num+1 )) + done + done + [ $match_num -ne ${GBL_TEMP_NUM} ] && err_msg "config: status=invalid. reason=the name of temperature sensors is inconsistent." "${E_INVALID_CONF}" + + # validate pwm values + for pwm in ${GBL_FAN_LEVEL[@]} + do + expr $pwm + $GBL_MIN_PWM >/dev/null 2>&1 + [ $? -ne 0 ] && err_msg "config: status=invalid. reason=the value of pwm is not integer." "$E_INVALID_CONF" + [ $pwm -lt $GBL_MIN_PWM ] && err_msg "config: status=invalid. reason=the value of fan level is less than MIN_PWM($GBL_MIN_PWM)." "$E_INVALID_CONF" + done +} + +#/* +#* FEATURE: +#* initialize +#* PURPOSE: +#* load zone config and thermal config +#* PARAMETERS: +#* +#* RETURNS: +#* +#*/ +function initialize() { + local data conf_interval conf_hysis conf_min_pwm conf_zone_id conf_msg_level temp_list_1 temp_list_2 + + log_msg $MSG_INFO "Initializing fan control service..." + + # fetch temperature sensor name from configuration files + temp_list_1=(`cat ${GBL_ZONE_CONF} | grep "^${SYMBOL_TEMP}" | awk -F "," {'print $1'}`) + temp_list_2=(`cat ${GBL_TEMP_CONF} | grep "^${SYMBOL_TEMP}" | awk {'print $1'}`) + + # calculate the number of temperature/fan sensors + GBL_TEMP_NUM=${#temp_list_1[@]} + GBL_FAN_NUM=(`cat ${GBL_ZONE_CONF} | grep "^${SYMBOL_FAN}" | awk {'print $2'} | wc -l`) + + # calculate the number of fan levels + GBL_FAN_LEVEL=(`cat ${GBL_TEMP_CONF} | grep "^PWM" | awk -F "PWM" {'print $2'}`) + GBL_LEVEL_NUM=${#GBL_FAN_LEVEL[@]} + + # check if the interval/hyteresis should be updated. + conf_interval=`cat ${GBL_ZONE_CONF} | grep "^INTERVAL=" | awk -F "=" {'print $2'} | tail` + [ ! -z ${conf_interval} ] && GBL_INTERVAL=${conf_interval} + conf_hysis=`cat ${GBL_ZONE_CONF} | grep "^HYTERESIS=" | awk -F "=" {'print $2'} | tail` + [ ! -z ${conf_hysis} ] && GBL_HYSIS=${conf_hysis} + conf_min_pwm=`cat ${GBL_ZONE_CONF} | grep "^MIN_PWM=" | awk -F "=" {'print $2'} | tail` + [ ! -z ${conf_min_pwm} ] && GBL_MIN_PWM=${conf_min_pwm} + conf_zone_id=`cat ${GBL_ZONE_CONF} | grep "^ZONE_ID=" | awk -F "=" {'print $2'} | tail` + [ ! -z ${conf_zone_id} ] && GBL_ZONE_ID=${conf_zone_id} + conf_msg_level=`cat ${GBL_ZONE_CONF} | grep "^MSG_LEVEL=" | awk -F "=" {'print $2'} | tail` + [ ! -z ${conf_msg_level} ] && GBL_MSG_LEVEL=${conf_msg_level} + + # load zone config + for ((i=1; i<=${GBL_TEMP_NUM}; i++)) + do + GBL_TEMP_STATUSES+=($E_STATUS_GOOD) + data=`cat ${GBL_ZONE_CONF} | grep "^${SYMBOL_TEMP}" | awk NR==$i` + # FIXME + GBL_TEMP_GRP+=("`echo $data | awk -F ", " {'print $1'}`") + GBL_TEMP_GRP+=("`echo $data | awk -F ", " {'print $2'}`") + GBL_TEMP_GRP+=("`echo $data | awk -F ", " {'print $3'}`") + done + debug_temp_grp + + for ((i=1; i<=${GBL_FAN_NUM}; i++)) + do + data=`cat ${GBL_ZONE_CONF} | grep "^${SYMBOL_FAN}" | awk NR==$i{'print $2'}` + GBL_FAN_GRP+=("`echo $data`") + done + + # load thermal config + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + index=$(( $i * ${STRUCT_TEMP_SIZE} + ${STRUCT_TEMP_NAME} )) + sensor_name=${GBL_TEMP_GRP[$index]} + GBL_TEMP_PROPERTY+=(`cat ${GBL_TEMP_CONF} | grep "^${sensor_name}" | tail`) + done + debug_temp_property + + # check if the config files is valid + valid_conf temp_list_1[@] temp_list_2[@] +} + +#/* +#* FEATURE: +#* temperature_collection +#* PURPOSE: +#* collect all temperature sensor readlings +#* PARAMETERS: +#* +#* RETURNS: +#* success, returns a series of reading @GBL_TEMP_READINGS[] +#*/ +function temperature_collection() { + local name cmd max_temp reading status pre_status + + GBL_TEMP_READINGS=() + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + # read temperature sensor value & record sensor status + name=`fetch_temp_struct $i ${STRUCT_TEMP_NAME}` + cmd=`fetch_temp_struct $i ${STRUCT_TEMP_CMD}` + max_temp=`fetch_temp_struct $i ${STRUCT_TEMP_MAX}` + reading=`eval ${cmd} 2>/dev/null` + if [ $? -eq 0 ]; then + GBL_TEMP_READINGS+=($reading) + status=$E_STATUS_GOOD + else + GBL_TEMP_READINGS+=($max_temp) + status=$E_STATUS_FAULT + fi + + # Compare previous status of temperature sensor, then update it. + pre_status=${GBL_TEMP_STATUSES[$i]} + if [ $pre_status -eq $E_STATUS_GOOD ] && [ $status -eq $E_STATUS_FAULT ]; then + # Good -> Fault + log_msg $MSG_WARN "[ZONE_${GBL_ZONE_ID}] Sensor $name: status=ERROR. reason=read sensor failed." + elif [ $pre_status -eq $E_STATUS_FAULT ] && [ $status -eq $E_STATUS_GOOD ]; then + # Fault -> Good + log_msg $MSG_WARN "[ZONE_${GBL_ZONE_ID}] Sensor $name: status=RECOVER. reason=reading is $reading deg C" + fi + GBL_TEMP_STATUSES[$i]=$status + done + debug_temp_readings +} + +#/* +#* FEATURE: +#* fan_level_selection +#* PURPOSE: +#* select proper fan level by temperature sensor reading +#* PARAMETERS: +#* reading_list (IN) sensor reading list +#* RETURNS: +#* success, returns a fan level value +#*/ +function fan_level_selection() { + local reading_list name reading temp_list highest_level pre_level next_level hysis_temp res res1 + + reading_list=("${!1}") + highest_level=0 + pre_level=${GBL_CUR_LEVEL} + next_level=0 + + # search fan table by each temperature sensor reading + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + name=`fetch_temp_struct $i $STRUCT_TEMP_NAME` + reading=${reading_list[$i]} + temp_list=(`fetch_temp_property ${name}`) + for j in ${!temp_list[@]} + do + res=`echo $reading \<= ${temp_list[$j]} | bc -l` + if [ $res -eq 1 ] || [ $j -eq $((${#temp_list[@]}-1)) ]; then + if [ $j -gt $highest_level ]; then + highest_level=$j + fi + break + fi + done + done + + if [ $highest_level -lt $pre_level ]; then + # Determine if require decreasing current fan level @assert_level + local pass_num + pass_num=0 + for ((i=0; i<${GBL_TEMP_NUM}; i++)) + do + name=`fetch_temp_struct $i $STRUCT_TEMP_NAME` + reading=${reading_list[$i]} + temp_list=(`fetch_temp_property ${name}`) + assert_level=$(( $pre_level-1 )) + hysis_temp=`echo ${temp_list[$assert_level]} - $GBL_HYSIS | bc` + res=`echo $reading \<= $hysis_temp | bc -l` + if [ $res -eq 1 ]; then + pass_num=$(( $pass_num+1 )) + else + break + fi + done + if [ $pass_num -eq ${GBL_TEMP_NUM} ]; then + # Decrease fan pwm: All sensor reading should less than its own hysteresis temperature + next_level=${highest_level} + else + # Keep current fan pwm + next_level=${pre_level} + fi + else + # Increase fan pwm + next_level=${highest_level} + fi + GBL_CUR_LEVEL=${next_level} +} + +#/* +#* FEATURE: +#* apply_fan_level +#* PURPOSE: +#* convert given fan level to PWM, then output to fans +#* PARAMETERS: +#* fan_list (IN) fan devices list +#* fan_level (IN) fan level +#* RETURNS: +#* success, returns a pwm value +#*/ +function apply_fan_level() { + local fan_level fan_list + + fan_list=("${!1}") + fan_level=$2 + + for fan in ${fan_list[@]} + do + echo ${GBL_FAN_LEVEL[$fan_level]} > $fan + done + debug_fan_speed +} + +#/* +#********************************************************************** +#* +#* MAIN +#* +#********************************************************************** +#*/ +Platform_init +arg_parse $@ +initialize +log_msg $MSG_INFO "Starting fan control service..." +while [ true ]; do + temperature_collection + fan_level_selection GBL_TEMP_READINGS[@] + apply_fan_level GBL_FAN_GRP[@] ${GBL_CUR_LEVEL} + sleep $GBL_INTERVAL +done + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf new file mode 100644 index 000000000000..56409f5c3e30 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf @@ -0,0 +1,12 @@ +##### Temperature vs Fan table ##### +## FORMAT: "PWM" fan speed(range from 0 to 255) +# Duty Cycle 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85% 90% 95% 100% +PWM 64 77 89 102 115 128 140 153 166 179 191 204 217 230 242 255 +## FORMAT: sensor name(TEMP_XXX) with asserted temperature by each levels +TEMP_CPU 52 55 58 61 64 67 70 73 76 79 82 85 88 91 94 97 +TEMP_SWITCH 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 +#TEMP_HDD 25 +#TEMP_TMP75_CPU 25 +#TEMP_TMP75_CENTER 25 +#TEMP_TMP75_RIGHT 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 +TEMP_TMP75_FAN 26.5 31.5 36.5 41.5 46.5 51.5 56.5 61.5 66.5 71.5 76.5 81.5 86.5 91.5 96.5 101.5 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf new file mode 100644 index 000000000000..6c459d874feb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf @@ -0,0 +1,12 @@ +##### Temperature vs Fan table ##### +## FORMAT: "PWM" fan speed(range from 0 to 255) +# Duty Cycle 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85% 90% 95% 100% +PWM 64 77 89 102 115 128 140 153 166 179 191 204 217 230 242 255 +## FORMAT: sensor name(TEMP_XXX) with asserted temperature by each levels +TEMP_CPU 60 65 70 73 76 79 82 85 88 91 94 97 100 103 106 109 +TEMP_SWITCH 73 76 79 82 85 88 91 94 97 100 103 106 109 112 115 118 +#TEMP_HDD 25 +#TEMP_TMP75_CPU 25 +#TEMP_TMP75_CENTER 25 +TEMP_TMP75_RIGHT 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 +#TEMP_TMP75_FAN 25 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_B2F.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_B2F.conf new file mode 100644 index 000000000000..b51f3b7aa67d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_B2F.conf @@ -0,0 +1,38 @@ +##### ZONE ID ##### +ZONE_ID=0 + +##### SENSOR GROUP START ##### +## FORMAT: name(TEMP_XXX), command, max_temp(deg C) +TEMP_CPU, "data=`sensors | grep coretemp -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $4'} | sed 's/^+\|°C//g'", 110 +TEMP_SWITCH, "[ `file /var/run/docker-syncd/sswsyncd.socket | grep -c " socket"` -ne 1 ] && exit 1; [ `ss -a | grep "/var/run/sswsyncd/sswsyncd.socket" |grep -c "LISTEN"` -ne 1 ] && exit 1; data=`bcmcmd -c "show temp" | grep "temperature monitor"`; [ $? -ne 0 ] && exit 1; switch_temps=(`echo "$data" | awk {'print $5'} | sed 's/,//g'`); high_temp=0; for reading in ${switch_temps[@]}; do res=`echo "$reading > $high_temp" | bc -l`; [ $res -eq 1 ] && high_temp=$reading; done; echo $high_temp", 120 +#TEMP_HDD, "data=`hddtemp /dev/sdb | grep -v "not available"`; [ $? -ne 0 ] && exit 1; echo "$data" | awk -F ": " {'print $3'} | sed 's/°C//g'", 85 +#TEMP_TMP75_CPU, "data=`sensors | grep tmp75-i2c-0-4e -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +#TEMP_TMP75_CENTER, "data=`sensors | grep tmp75-i2c-4-4a -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +#TEMP_TMP75_RIGHT, "data=`sensors | grep tmp75-i2c-4-4c -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +TEMP_TMP75_FAN, "data=`sensors | grep tmp75-i2c-4-4d -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +##### SENSOR GROUP END ##### + +##### FAN GROUP START ##### +## FORMAT: name(FAN_YYY) input_files +FAN_1 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm1 +FAN_2 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm2 +FAN_3 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm3 +FAN_4 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm4 +FAN_5 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm5 +FAN_6 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm6 +FAN_7 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm1 +FAN_8 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm2 +FAN_9 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm3 +FAN_10 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm4 +FAN_11 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm5 +FAN_12 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm6 +##### FAN GROUP END ##### + +##### INTERVAL (sec) ##### +INTERVAL=10 + +##### HYTERESIS (deg C) ##### +HYTERESIS=2 + +##### MINIMUM PWM (38.25=255x15%) ##### +MIN_PWM=39 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_F2B.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_F2B.conf new file mode 100644 index 000000000000..2d5987c5c66b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone_F2B.conf @@ -0,0 +1,38 @@ +##### ZONE ID ##### +ZONE_ID=0 + +##### SENSOR GROUP START ##### +## FORMAT: name(TEMP_XXX), command, max_temp(deg C) +TEMP_CPU, "data=`sensors | grep coretemp -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $4'} | sed 's/^+\|°C//g'", 110 +TEMP_SWITCH, "[ `file /var/run/docker-syncd/sswsyncd.socket | grep -c " socket"` -ne 1 ] && exit 1; [ `ss -a | grep "/var/run/sswsyncd/sswsyncd.socket" |grep -c "LISTEN"` -ne 1 ] && exit 1; data=`bcmcmd -c "show temp" | grep "temperature monitor"`; [ $? -ne 0 ] && exit 1; switch_temps=(`echo "$data" | awk {'print $5'} | sed 's/,//g'`); high_temp=0; for reading in ${switch_temps[@]}; do res=`echo "$reading > $high_temp" | bc -l`; [ $res -eq 1 ] && high_temp=$reading; done; echo $high_temp", 120 +#TEMP_HDD, "data=`hddtemp /dev/sdb | grep -v "not available"`; [ $? -ne 0 ] && exit 1; echo "$data" | awk -F ": " {'print $3'} | sed 's/°C//g'", 85 +#TEMP_TMP75_CPU, "data=`sensors | grep tmp75-i2c-0-4e -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +#TEMP_TMP75_CENTER, "data=`sensors | grep tmp75-i2c-4-4a -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +TEMP_TMP75_RIGHT, "data=`sensors | grep tmp75-i2c-4-4c -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +#TEMP_TMP75_FAN, "data=`sensors | grep tmp75-i2c-4-4d -A2`; [ $? -ne 0 ] && exit 1; echo "$data" | tail -n1 | awk {'print $2'} | sed 's/^+\|°C//g'", 125 +##### SENSOR GROUP END ##### + +##### FAN GROUP START ##### +## FORMAT: name(FAN_YYY) input_files +FAN_1 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm1 +FAN_2 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm2 +FAN_3 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm3 +FAN_4 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm4 +FAN_5 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm5 +FAN_6 /sys/bus/i2c/devices/3-0020/hwmon/hwmon*/pwm6 +FAN_7 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm1 +FAN_8 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm2 +FAN_9 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm3 +FAN_10 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm4 +FAN_11 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm5 +FAN_12 /sys/bus/i2c/devices/3-0023/hwmon/hwmon*/pwm6 +##### FAN GROUP END ##### + +##### INTERVAL (sec) ##### +INTERVAL=10 + +##### HYTERESIS (deg C) ##### +HYTERESIS=2 + +##### MINIMUM PWM (38.25=255x15%) ##### +MIN_PWM=39 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/funcs.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/funcs.sh new file mode 100755 index 000000000000..3e417f699543 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/funcs.sh @@ -0,0 +1,22 @@ +#!/bin/bash +#/* +#********************************************************************** +#* +#* @filename funcs.sh +#* +#* @purpose api functions script for fan-ctrl +#* +#* @create 2017/08/09 +#* +#* @author nixon.chu +#* +#* @history 2017/08/09: init version +#* +#********************************************************************** +#*/ + +DIR=$(dirname $0) + +function Platform_init() { + ${DIR}/init.sh +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/init.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/init.sh new file mode 100755 index 000000000000..06df071fa147 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/init.sh @@ -0,0 +1,26 @@ +#!/bin/bash +DIR=$(dirname $0) + +# board type +BOARD_TYPE=`cat /sys/bus/i2c/devices/1-0032/brd_type` + +# fan tables +FORWARD_SENSOR_CONF=${DIR}/fan-zone_F2B.conf +FORWARD_PWM_CONF=${DIR}/fan-zone-thermal_F2B.conf +REVERSE_SENSOR_CONF=${DIR}/fan-zone_B2F.conf +REVERSE_PWM_CONF=${DIR}/fan-zone-thermal_B2F.conf + +# Nixon: Please refer to "BMS CPLD Design Spec." +# board type : BRD_TYPE[3:0] +# 0x0 (0000b): BMS_AC_PSU_NORMAL_FAN, 0x2 (0010b): BMS_DC_PSU_NORMAL_FAN +# 0x1 (0001b): BMS_AC_PSU_REVERSE_FAN, 0x3 (0011b): BMS_DC_PSU_REVERSE_FAN +case $BOARD_TYPE in + 0x0|0x2) + ln -sf $FORWARD_SENSOR_CONF ${DIR}/fan-zone.conf + ln -sf $FORWARD_PWM_CONF ${DIR}/fan-zone-thermal.conf + ;; + 0x1|0x3) + ln -sf $REVERSE_SENSOR_CONF ${DIR}/fan-zone.conf + ln -sf $REVERSE_PWM_CONF ${DIR}/fan-zone-thermal.conf + ;; +esac diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh new file mode 100755 index 000000000000..4b0c4c35471f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh @@ -0,0 +1,23 @@ +#/bin/bash + +# process name/id +DAEMON_NAME=`basename $0` +DAEMON_PID="$$" + +DEF_SEVERITY="INFO" + +#/* +#* FEATURE: +#* log_msg +#* PURPOSE: +#* log message +#* PARAMETERS: +#* msg (IN) message +#* RETURNS: +#* +#*/ +function log_msg() { + local msg=$1 + + `logger -t $DAEMON_NAME -p $DEF_SEVERITY $msg` +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh new file mode 100755 index 000000000000..2bc9589738d0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh @@ -0,0 +1,99 @@ +#/bin/bash + +DIR=$(dirname $0) + +# include files +source ${DIR}/funcs.sh + +ACPI_INSTALL_PRINT=0 +ACPID_INSTALL_PRINT=0 +BC_INSTALL_PRINT=0 +ACPID_SOCKET_PRINT=0 +ACPI_PRINT=0 + + +while [ 1 ] +do + if [ `dpkg -l |grep -c "acpi "` -eq "0" ]; then + dpkg -i /opt/debs/acpi_1.7-1_amd64.deb + if [ "$?" -ne "0" ]; then + if [ $ACPI_INSTALL_PRINT -eq 0 ]; then + ACPI_INSTALL_PRINT=1 + log_msg "Wait for acpi package install." + fi + sleep 1 + continue + else + log_msg "Install acpi package success." + fi + fi + break +done + +while [ 1 ] +do + if [ `dpkg -l |grep -c "acpid "` -eq "0" ]; then + dpkg -i /opt/debs/acpid_2.0.23-2_amd64.deb + if [ "$?" -ne "0" ]; then + if [ $ACPID_INSTALL_PRINT -eq 0 ]; then + ACPID_INSTALL_PRINT=1 + log_msg "Wait for acpid package install." + fi + sleep 1 + continue + else + log_msg "Install acpid package success." + fi + fi + break +done + +while [ 1 ] +do + if [ `dpkg -l |grep -c " bc "` -eq "0" ]; then + dpkg -i /opt/debs/bc_1.06.95-9_amd64.deb + if [ "$?" -ne "0" ]; then + if [ $BC_INSTALL_PRINT -eq 0 ]; then + BC_INSTALL_PRINT=1 + log_msg "Wait for bc package install." + fi + sleep 1 + continue + else + log_msg "Install bc package success." + fi + fi + break +done + +while [ 1 ] +do + if [ ! -e "/sys/firmware/acpi/interrupts/gpe01" ]; then + if [ $ACPI_PRINT -eq 0 ]; then + ACPI_PRINT=1 + log_msg "Wait for acpi daemon start." + fi + sleep 1 + continue + fi + log_msg "The acpi daemon start." + break +done + +while [ 1 ] +do + if [ ! -e "/var/run/acpid.socket" ]; then + if [ $ACPID_SOCKET_PRINT -eq 0 ]; then + ACPID_SOCKET_PRINT=1 + log_msg "Wait for acipd daemon start." + fi + sleep 1 + continue + fi + log_msg "The acpid daemon start." + break +done + +/etc/init.d/xcvr_servd start +/etc/init.d/sys_servd start +exit 0; diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh new file mode 100755 index 000000000000..2268e5e0d16e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh @@ -0,0 +1,32 @@ +#/bin/bash + +DIR=$(dirname $0) + +# include files +source ${DIR}/funcs.sh + +WATCHDOG_PRINT=0 + +while [ 1 ] +do + if [ `dpkg -l |grep -c "watchdog "` -eq "0" ]; then + dpkg -i /opt/debs/watchdog_5.14-3_amd64.deb + if [ "$?" -ne "0" ]; then + if [ $WATCHDOG_PRINT -eq 0 ]; then + WATCHDOG_PRINT=1 + log_msg "Wait for watchdog package install." + fi + sleep 1 + continue + else + log_msg "Install watchdog package success." + fi + fi + break +done + +ln -sf /opt/watchdog/watchdog.conf /etc/watchdog.conf + +/usr/sbin/watchdog -c /etc/watchdog.conf + +exit 0; diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd new file mode 100755 index 000000000000..a1b4f177897c Binary files /dev/null and b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd differ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/system-check/system-check.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/system-check/system-check.sh new file mode 100755 index 000000000000..f44ed046330d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/system-check/system-check.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +SW_READY_STAMP='/tmp/.BcmSdkReady' +SYSTEM_INIT=0 +CURRENTR_LED=0 + +# 0 was not ready, 1 was ready +SYSTEM_READY=1 + +function check_sdk_ready() { + if [ `file /var/run/docker-syncd/sswsyncd.socket | grep -c " socket"` -ne 1 ]; then + SYSTEM_READY=0 + return 1 + else + if [ `ss -a | grep "/var/run/sswsyncd/sswsyncd.socket" |grep -c "LISTEN"` -ne 1 ]; then + SYSTEM_READY=0 + return 1 + fi + fi + return 0 +} + +while [ true ] +do + SYSTEM_READY=1 + #-----check start------------ + check_sdk_ready + #-----cech end--------------- + + if [ "$SYSTEM_INIT" -eq "0" ]; then + if [ $SYSTEM_READY -eq 1 ]; then + SYSTEM_INIT=1 + # set SYSTEM LED to Green + echo 0x01 > /sys/bus/i2c/devices/1-0032/system_led_fld + CURRENTR_LED=1 + fi + else + if [ $SYSTEM_READY -eq 0 ]; then + # set SYSTEM LED to Amber + if [ "$CURRENTR_LED" -ne "2" ]; then + echo 0x02 > /sys/bus/i2c/devices/1-0032/system_led_fld + CURRENTR_LED=2 + fi + else + # set SYS LED to Green + if [ "$CURRENTR_LED" -ne "1" ]; then + echo 0x01 > /sys/bus/i2c/devices/1-0032/system_led_fld + CURRENTR_LED=1 + fi + fi + fi + sleep 10 +done + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf new file mode 100644 index 000000000000..81f0b7b819bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf @@ -0,0 +1,45 @@ +#ping = 172.31.14.1 +#ping = 172.26.1.255 +#interface = eth0 +#file = /var/log/messages +#change = 1407 + +# Uncomment to enable test. Setting one of these values to '0' disables it. +# These values will hopefully never reboot your machine during normal use +# (if your machine is really hung, the loadavg will go much higher than 25) +#max-load-1 = 24 +#max-load-5 = 18 +#max-load-15 = 12 + +# Note that this is the number of pages! +# To get the real size, check how large the pagesize is on your machine. +#min-memory = 1 +#allocatable-memory = 1 + +#repair-binary = /usr/sbin/repair +#repair-timeout = +#test-binary = +#test-timeout = + +watchdog-device = /dev/watchdog + +# Defaults compiled into the binary +#temperature-device = +#max-temperature = 120 + +# Defaults compiled into the binary +#admin = root +#interval = 1 +#logtick = 1 +#log-dir = /var/log/watchdog + +# This greatly decreases the chance that watchdog won't be scheduled before +# your machine is really loaded +realtime = yes +priority = 99 + +# Check if rsyslogd is still running by enabling the following line +#pidfile = /var/run/rsyslogd.pid + +# timeout : 15 , 30 , 60 , 90 , 120 , 180 , 240 sec +watchdog-timeout = 120 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd new file mode 100755 index 000000000000..c882ff8e335a Binary files /dev/null and b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd differ diff --git a/platform/broadcom/sonic-platform-modules-quanta/.gitignore b/platform/broadcom/sonic-platform-modules-quanta/.gitignore new file mode 100755 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/broadcom/sonic-platform-modules-quanta/LICENSE b/platform/broadcom/sonic-platform-modules-quanta/LICENSE new file mode 100755 index 000000000000..609b3082d11c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 Quanta Computer Inc. + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-quanta/README.md b/platform/broadcom/sonic-platform-modules-quanta/README.md new file mode 100644 index 000000000000..bcc06271904a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-quanta +SONiC platform folder which contain drivers for Quanta Switch diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/changelog b/platform/broadcom/sonic-platform-modules-quanta/debian/changelog new file mode 100644 index 000000000000..fe1cfa45490b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/changelog @@ -0,0 +1,34 @@ +sonic-quanta-platform-modules (1.0) unstable; urgency=low + + * Add support for Quanta IX1B-32X + * Initial release + + -- Chih-Pei Chang Jonathan Tsai Wed, 20 Dec 2017 09:26:01 +0800 + +sonic-quanta-platform-modules (1.0) unstable; urgency=low + + * Add support for Quanta IX7-32X + * Initial release + + -- Chih-Pei Chang Jonathan Tsai Tue, 17 Apr 2018 14:40:01 +0800 + +sonic-quanta-platform-modules (1.0) unstable; urgency=low + + * Add support for Quanta IX8-56X + * Initial release + + -- Chih-Pei Chang Jonathan Tsai Thu, 3 May 2018 16:40:01 +0800 + +sonic-quanta-platform-modules (1.0) unstable; urgency=low + + * Add support for Quanta IX8C-56X + * Initial release + + -- Chih-Pei Chang Jonathan Tsai Thu, 4 Jan 2018 13:50:01 +0800 + +sonic-quanta-platform-modules (1.0) unstable; urgency=low + + * Add support for Quanta IX9-32X + * Initial release + + -- Jonathan Tsai Thu, 31 Jan 2019 13:09:01 +0800 diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/compat b/platform/broadcom/sonic-platform-modules-quanta/debian/compat new file mode 100755 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/control b/platform/broadcom/sonic-platform-modules-quanta/debian/control new file mode 100644 index 000000000000..f25b0d8e3c5b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/control @@ -0,0 +1,26 @@ +Source: sonic-quanta-platform-modules +Section: main +Priority: extra +Maintainer: Chih-Pei Chang , Jonathan Tsai +Build-Depends: debhelper (>= 9), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-quanta-ix1b-32x +Architecture: amd64 +Description: kernel modules for platform devices such as psu, led, sfp + +Package: sonic-platform-quanta-ix7-32x +Architecture: amd64 +Description: kernel modules for platform devices such as psu, led, sfp + +Package: sonic-platform-quanta-ix8-56x +Architecture: amd64 +Description: kernel modules for platform devices such as psu, led, sfp + +Package: sonic-platform-quanta-ix8c-56x +Architecture: amd64 +Description: kernel modules for platform devices such as psu, led, sfp + +Package: sonic-platform-quanta-ix9-32x +Architecture: amd64 +Description: kernel modules for platform devices such as psu, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-quanta/debian/rules b/platform/broadcom/sonic-platform-modules-quanta/debian/rules new file mode 100755 index 000000000000..46b9607135a8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/debian/rules @@ -0,0 +1,86 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-quanta +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= ix1b-32x ix7-32x ix8-56x ix8c-56x ix9-32x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/Makefile new file mode 100755 index 000000000000..48683c54a7bc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/Makefile @@ -0,0 +1 @@ +obj-m:=qci_pmbus.o qci_cpld_qsfp28.o qci_platform_ix1b.o qci_hwmon_ix1b.o diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_cpld_qsfp28.c b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_cpld_qsfp28.c new file mode 100755 index 000000000000..15c5369fd219 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_cpld_qsfp28.c @@ -0,0 +1,409 @@ +/* + * A CPLD driver for monitor QSFP28 module I/O + * + * The CPLD is customize by Quanta for controlling QSFP28 module signals, + * they are RESET , INTERREPT , Module_Present, LPMODE + * Each CPLD control 16 modules, each module use 4 bits in register. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_ida); + +enum platform_type { + QSFP28 = 0, + NONE +}; + +static struct class *cpld_class = NULL; + +struct sfp_data { + struct i2c_client *cpld_client; + char name[8]; + u8 port_id; + u8 cpld_port; +}; + +struct cpld_data { + struct mutex lock; + struct device *port_dev[16]; + struct sfp_data *port_data[16]; +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_id[] = { + { "CPLD-QSFP28", QSFP28 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_qsfp28", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +// .address_list = normal_i2c, +}; + +#define CPLD_ID_PREFIX "port-" +#define CPLD_ID_FORMAT CPLD_ID_PREFIX "%d" + +#define RESET_MASK 0x08 +#define INTERRUPT_MASK 0x04 +#define MODULE_PRESENT_MASK 0x02 +#define LPMODE_MASK 0x01 + +static inline u8 get_group_cmd(u8 group) +{ + //FIXME: if group cmd change + return (group + 1); +} + +static inline u8 port_remapping(u8 phy_port) +{ + /* FIXME: implement by hardware design */ + /* The CPLD register port mapping is weird : + * MSB -------- LSB (word data) + * P3 P4 P1 P2 (per port 4 bits) + * For easy coding bit shift, we treat it as hw port swap + */ + return (phy_port % 2) ? (phy_port - 1) : (phy_port + 1); +} + +static ssize_t get_reset(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= RESET_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_interrupt(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= INTERRUPT_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_module_present(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= MODULE_PRESENT_MASK; + + //FIXME: if present is not low active + return sprintf(buf, "%d\n", value ? 0 : 1); +} + +static ssize_t get_lpmode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= LPMODE_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t set_reset(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(RESET_MASK << (group_port * 4)); + if (disable) + value |= (RESET_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_lpmode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(LPMODE_MASK << (group_port * 4)); + if (disable) + value |= (LPMODE_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(reset, S_IWUSR | S_IRUGO, get_reset, set_reset); +static DEVICE_ATTR(lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode); +static DEVICE_ATTR(module_present, S_IRUGO, get_module_present, NULL); +static DEVICE_ATTR(interrupt, S_IRUGO, get_interrupt, NULL); + +static const struct attribute *sfp_attrs[] = { + &dev_attr_reset.attr, + &dev_attr_lpmode.attr, + &dev_attr_module_present.attr, + &dev_attr_interrupt.attr, + NULL, +}; + +static const struct attribute_group sfp_attr_group = { + .attrs = (struct attribute **) sfp_attrs, +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_data *data; + struct sfp_data *port_data; + struct device *port_dev; + int port_nr, i, err; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, "cpld-qsfp28"); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* register sfp port data to sysfs */ + for (i = 0; i < 16; i++) + { + port_nr = ida_simple_get(&cpld_ida, 1, 99, GFP_KERNEL); + if (port_nr < 0) + return ERR_PTR(port_nr); + + port_data = kzalloc(sizeof(struct sfp_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), port_data, CPLD_ID_FORMAT, port_nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + // printk("err_status\n"); + } + + data->port_dev[i] = port_dev; + data->port_data[i] = port_data; + + dev_info(&client->dev, "Register qsfp28 port-%d\n", port_nr); + + /* FIXME: implement Logical/Physical port remapping */ + //port_data->cpld_port = i; + port_data->cpld_port = port_remapping(i); + sprintf(port_data->name, "port-%d", port_nr); + port_data->port_id = port_nr; + dev_set_drvdata(port_dev, port_data); + port_dev->init_name = port_data->name; + port_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &sfp_attr_group); + // if (status) printk("err status\n"); + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +//FIXME: implement error check +exit_remove: +// sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + int i, id; + + for (i = 15; i >= 0; i--) + { + dev_info(data->port_dev[i], "Remove qsfp28 port-%d\n", data->port_data[i]->port_id); + device_unregister(data->port_dev[i]); + ida_simple_remove(&cpld_ida, data->port_data[i]->port_id); + kfree(data->port_data[i]); + } + + if (cpld_idr_is_empty(&cpld_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_DESCRIPTION("Quanta Switch SFP CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_hwmon_ix1b.c b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_hwmon_ix1b.c new file mode 100644 index 000000000000..eb730cb28d0e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_hwmon_ix1b.c @@ -0,0 +1,425 @@ +/* + * A hwmon driver for Cypress PSoC fan controller and thermal sensor + * + * This PSoC is a specific customize design only for Quanta Switch + * This driver is also monitoring pca9555 which is related to + * RPSU detection and LED controll in front panel. Instead a standalone + * driver, it should be combined with gpio lib to work correctly. + * + * Copyright (C) 2014 Quanta Inc. + * + * Author: Luffy Cheng + * + * Based on: + * adt7470.c from Darrick J. Wong + * Copyright (C) 2007 IBM + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define QUANTA_IX1_PSU_GPIO_PSU1_PRSNT_N 16 +#define QUANTA_IX1_PSU_GPIO_PSU1_PWRGD 17 +#define QUANTA_IX1_PSU_GPIO_PSU2_PRSNT_N 19 +#define QUANTA_IX1_PSU_GPIO_PSU2_PWRGD 20 + +#define QUANTA_IX1_FAN_GPIO_FAN1_PRSNT_N 36 +#define QUANTA_IX1_FAN_GPIO_FAN2_PRSNT_N 37 +#define QUANTA_IX1_FAN_GPIO_FAN3_PRSNT_N 38 +#define QUANTA_IX1_FAN_GPIO_FAN4_PRSNT_N 39 + +#define AUTO_UPDATE_INTERVAL 10000 + +enum psu_nr { + PSU1 = 0, + PSU2 +}; + +enum fan_nr { + FAN1 = 0, + FAN2, + FAN3, + FAN4, +}; + +enum led_color { + LED_RED = 1, + LED_GREEN, + LED_COLOR_OFF +}; + +int hwmon_enable = 1; + +struct qci_hwmon_data { + struct device *hwmon_dev; + struct task_struct *auto_update; + struct completion auto_update_stop; + unsigned int auto_update_interval; + struct attribute_group attrs; + +}; + +static void simple_atoi(const char *buf, int *output_val) +{ + int negative = 0; + + if (buf[0] == '-') + { + negative = 1; + buf++; + } + + while (*buf >= '0' && *buf <= '9') { + *output_val = *output_val * 10 + *buf - '0'; + buf++; + } + + if (negative) + *output_val = 0 - *output_val; +} + +int read_gpio_file(int gpio) +{ + struct file *fp; + char buffer[512], file_path[255]; + int offset = 0; + int ret; + + /*open the file in read mode*/ + sprintf(file_path, "/sys/class/gpio/gpio%d/value", gpio); + fp = filp_open(file_path, O_RDONLY, 0); + if (IS_ERR(fp)) { + printk("Cannot open the file %ld\n", PTR_ERR(fp)); + return -1; + } + + /*Read the data to the end of the file*/ + while (1) { + ret = kernel_read(fp, offset, buffer, 512); + if (ret > 0) { + offset += ret; + } + else { + break; + } + } + + filp_close(fp, NULL); + + simple_atoi(buffer, &ret); + + return ret; +} + +static ssize_t get_hwmon_status(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "%d\n", hwmon_enable); +} + +static ssize_t set_hwmon_status(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + long enable; + + if (kstrtol(buf, 0, &enable)) + return -EINVAL; + + if ((enable != 1) && (enable != 0)) + return -EINVAL; + + hwmon_enable = enable; + + return count; +} + +static u8 read_fan_present(u8 fan_nr) +{ + u8 value = 0; + + if (fan_nr == PSU1) + value = read_gpio_file(QUANTA_IX1_FAN_GPIO_FAN1_PRSNT_N); + else if (fan_nr == FAN2) + value = read_gpio_file(QUANTA_IX1_FAN_GPIO_FAN2_PRSNT_N); + else if (fan_nr == FAN3) + value = read_gpio_file(QUANTA_IX1_FAN_GPIO_FAN3_PRSNT_N); + else if (fan_nr == FAN4) + value = read_gpio_file(QUANTA_IX1_FAN_GPIO_FAN4_PRSNT_N); + else + return -1; + + return value; +} + +static u8 read_psu_present(u8 psu_nr) +{ + u8 value = 0; + + if (psu_nr == PSU1) + value = read_gpio_file(QUANTA_IX1_PSU_GPIO_PSU1_PRSNT_N); + else if (psu_nr == PSU2) + value = read_gpio_file(QUANTA_IX1_PSU_GPIO_PSU2_PRSNT_N); + else + return -1; + + return value; +} + +static u8 read_psu_AC_good(u8 psu_nr) +{ + u8 value = 0; + + if (psu_nr == PSU1) + value = read_gpio_file(QUANTA_IX1_PSU_GPIO_PSU1_PWRGD); + else if (psu_nr == PSU2) + value = read_gpio_file(QUANTA_IX1_PSU_GPIO_PSU2_PWRGD); + else + return -1; + + return value; +} + +static u8 front_led_set(char *name, char *value) +{ + struct file *fp; + char file_path[255]; + int ret; + mm_segment_t oldfs; + + sprintf(file_path, "/sys/class/leds/%s/brightness", name); + fp = filp_open(file_path, O_RDWR | O_CREAT, 0644); + + if (IS_ERR(fp)) { + printk("Cannot open the file %ld\n", PTR_ERR(fp)); + return -1; + } + + oldfs = get_fs(); + set_fs(get_ds()); + + ret = vfs_write(fp, value, sizeof(value), &fp->f_pos); + + set_fs(oldfs); + + filp_close(fp, NULL); + + return 0; +} + +static u8 update_led(u8 *fan_status, u8 *psu_status) +{ + u8 i = 0, fan_color = LED_GREEN; + + // Update FAN front LED + for (i = 0; i < 4; i++) + { + if (fan_status[i] == 1) + { + fan_color = LED_RED; + front_led_set("front_led_fan_red", "1"); + front_led_set("front_led_fan_green", "0"); + break; + } + } + + if (fan_color == LED_GREEN) + { + front_led_set("front_led_fan_red", "0"); + front_led_set("front_led_fan_green", "1"); + } + + // Update PSU1 front LED + if ((psu_status[0] == 0) && (psu_status[2] == 1)) + { + front_led_set("front_led_psu1_green", "1"); + front_led_set("front_led_psu1_red", "0"); + } + else if (psu_status[0] == 1) + { + front_led_set("front_led_psu1_green", "0"); + front_led_set("front_led_psu1_red", "0"); + } + else + { + front_led_set("front_led_psu1_green", "0"); + front_led_set("front_led_psu1_red", "1"); + } + + // Update PSU2 front LED + if ((psu_status[1] == 0) && (psu_status[3] == 1)) + { + front_led_set("front_led_psu2_green", "1"); + front_led_set("front_led_psu2_red", "0"); + } + else if (psu_status[1] == 1) + { + front_led_set("front_led_psu2_green", "0"); + front_led_set("front_led_psu2_red", "0"); + } + else + { + front_led_set("front_led_psu2_green", "0"); + front_led_set("front_led_psu2_red", "1"); + } + + return 0; +} + +static int led_update_thread(void *p) +{ + struct platform_device *pdev = p; + struct qci_hwmon_data *data = platform_get_drvdata(pdev); + + u8 i = 0; + u8 psu_status[4] = {0}; // {PSU1-2 present, PSU1-2 AC good} + u8 fan_status[4] = {0}; // {FAN1-4 present} + + while (!kthread_should_stop()) { + + if (hwmon_enable) + { + for (i = 0; i < 4; i++) + { + fan_status[i] = read_fan_present(i); + } + + for (i = 0; i < 2; i++) + { + psu_status[i] = read_psu_present(i); + psu_status[i+2] = read_psu_AC_good(i); + } + + update_led(fan_status, psu_status); + } + + if (kthread_should_stop()) + break; + msleep_interruptible(data->auto_update_interval); + } + + complete_all(&data->auto_update_stop); + return 0; +} + +static DEVICE_ATTR(hwmon_status, S_IWUSR | S_IRUGO, get_hwmon_status, set_hwmon_status); + +static struct attribute *qci_hwmon_attr[] = { + + &dev_attr_hwmon_status.attr, + + NULL +}; + +static int qci_hwmon_probe(struct platform_device *pdev) +{ + struct qci_hwmon_data *data; + int err; + + data = devm_kzalloc(&pdev->dev, sizeof(struct qci_hwmon_data), + GFP_KERNEL); + if (!data) + { + return -ENOMEM; + } + + data->auto_update_interval = AUTO_UPDATE_INTERVAL; + data->attrs.attrs = qci_hwmon_attr; + + platform_set_drvdata(pdev, data); + + dev_info(&pdev->dev, "%s device found\n", pdev->name); + + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + } + + err = sysfs_create_group(&pdev->dev.kobj, &data->attrs); + if (err) + return err; + + init_completion(&data->auto_update_stop); + data->auto_update = kthread_run(led_update_thread, pdev, + dev_name(data->hwmon_dev)); + if (IS_ERR(data->auto_update)) { + err = PTR_ERR(data->auto_update); + goto exit_unregister; + } + + return 0; + +exit_unregister: + hwmon_device_unregister(data->hwmon_dev); + return err; +} + +static int qci_hwmon_remove(struct platform_device *pdev) +{ + struct qci_hwmon_data *data = platform_get_drvdata(pdev); + + kthread_stop(data->auto_update); + wait_for_completion(&data->auto_update_stop); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &data->attrs); + return 0; +} + +static struct platform_driver qci_hwmon_driver = { + .probe = qci_hwmon_probe, + .remove = qci_hwmon_remove, + .driver = { + .name = "qci-hwmon", + .owner = THIS_MODULE, + }, +}; + +static int __init qci_hwmon_init(void) +{ + platform_driver_register(&qci_hwmon_driver); + + return 0; +} + +static void __exit qci_hwmon_exit(void) +{ + platform_driver_unregister(&qci_hwmon_driver); +} + +module_init(qci_hwmon_init); +module_exit(qci_hwmon_exit); + +MODULE_AUTHOR("Quanta Computer Inc."); +MODULE_DESCRIPTION("Quanta Switch Hardware Monitor driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform.h b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform.h new file mode 100755 index 000000000000..0737c8ce8170 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform.h @@ -0,0 +1,64 @@ +/* + * Driver model definations for Quanta Platform drivers + * + * Copyright (C) 2015-2016 Quanta QCT + * + * 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. + * + */ +#ifndef __QCI_PLATFORM_H_INCLUDED +#define __QCI_PLATFORM_H_INCLUDED + +#define MUX_INFO(bus, deselect) \ + {.adap_id = bus, .deselect_on_exit = deselect} + +#define GPIO_INFO(id, gpio_nr) \ + {.gpio_id = id, .system_gpio_nr = gpio_nr} + +struct platform_gpio { + int gpio_id; + int system_gpio_nr; +}; + +/* FIXME: Please add important GPIO which need to be request */ +enum PLATFORM_GPIO_ID { + GPIO_PSU1_PRSNT, + GPIO_PSU1_PWRGD, + GPIO_PSU2_PRSNT, + GPIO_PSU2_PWRGD, +}; + +#define LED_ON LED_FULL + +#define LED_INFO(id) \ + {.led_id = id, .cdev = NULL} + +struct platform_led { + int led_id; + struct led_classdev *cdev; +}; + +enum PLATFORM_LED_ID { + SYSLED_AMBER, + SYSLED_GREEN, + FRONT_PSU1_GREEN, + FRONT_PSU1_RED, + FRONT_PSU2_GREEN, + FRONT_PSU2_RED, + FRONT_FAN_GREEN, + FRONT_FAN_RED, + REAR_FAN1_RED, + REAR_FAN2_RED, + REAR_FAN3_RED, + REAR_FAN4_RED, + REAR_FAN5_RED, + REAR_FAN6_RED, + TOTAL_LED_NR +}; + +extern int qci_platform_get_gpio(int platform_gpio); +extern int qci_platform_set_led(int led_id, bool led_on); + +#endif /* __QCI_PLATFORM_H_INCLUDED */ diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform_ix1b.c b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform_ix1b.c new file mode 100644 index 000000000000..b3e955217a01 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_platform_ix1b.c @@ -0,0 +1,501 @@ +/* + * Quanta IX1B platform driver + * + * + * Copyright (C) 2014 Quanta Computer inc. + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,12,0) +#include +#else +#include +#endif +#include "qci_platform.h" + +#define QUANTA_CPU_RGL + +static struct pca954x_platform_mode pca9548sfp1_modes[] = { + MUX_INFO(0x20, 1), + MUX_INFO(0x21, 1), + MUX_INFO(0x22, 1), + MUX_INFO(0x23, 1), + MUX_INFO(0x24, 1), + MUX_INFO(0x25, 1), + MUX_INFO(0x26, 1), + MUX_INFO(0x27, 1), +}; + +static struct pca954x_platform_data pca9548sfp1_data = { + .modes = pca9548sfp1_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp2_modes[] = { + MUX_INFO(0x28, 1), + MUX_INFO(0x29, 1), + MUX_INFO(0x2a, 1), + MUX_INFO(0x2b, 1), + MUX_INFO(0x2c, 1), + MUX_INFO(0x2d, 1), + MUX_INFO(0x2e, 1), + MUX_INFO(0x2f, 1), +}; + +static struct pca954x_platform_data pca9548sfp2_data = { + .modes = pca9548sfp2_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp3_modes[] = { + MUX_INFO(0x30, 1), + MUX_INFO(0x31, 1), + MUX_INFO(0x32, 1), + MUX_INFO(0x33, 1), + MUX_INFO(0x34, 1), + MUX_INFO(0x35, 1), + MUX_INFO(0x36, 1), + MUX_INFO(0x37, 1), +}; + +static struct pca954x_platform_data pca9548sfp3_data = { + .modes = pca9548sfp3_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp4_modes[] = { + MUX_INFO(0x38, 1), + MUX_INFO(0x39, 1), + MUX_INFO(0x3a, 1), + MUX_INFO(0x3b, 1), + MUX_INFO(0x3c, 1), + MUX_INFO(0x3d, 1), + MUX_INFO(0x3e, 1), + MUX_INFO(0x3f, 1), +}; + +static struct pca954x_platform_data pca9548sfp4_data = { + .modes = pca9548sfp4_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9546_1_modes[] = { + MUX_INFO(0x10, 1), + MUX_INFO(0x11, 1), + MUX_INFO(0x12, 1), + MUX_INFO(0x13, 1), +}; + +static struct pca954x_platform_data pca9546_1_data = { + .modes = pca9546_1_modes, + .num_modes = 4, +}; + +static struct pca954x_platform_mode pca9546_2_modes[] = { + MUX_INFO(0x14, 1), + MUX_INFO(0x15, 1), + MUX_INFO(0x16, 1), + MUX_INFO(0x17, 1), +}; + +static struct pca954x_platform_data pca9546_2_data = { + .modes = pca9546_2_modes, + .num_modes = 4, +}; + +/* CPU gpio base defined in devicetree + * default is ARCH_NR_GPIOS - 32, (256-32=224) + * It must match devicetree default gpio base + * */ +#define PCA9555_PSU_GPIO_BASE 0x10 +#define PCA9555_FAN_GPIO_BASE 0x20 +#define PCA9555_ID_GPIO_BASE 0x30 + +#if defined(QUANTA_CPU_RGL) +#define PCA9555_CPU_LED_GPIO_BASE 0x80 + +static struct pca954x_platform_mode pca9546_cpu1_modes[] = { + MUX_INFO(0x18, 1), + MUX_INFO(0x19, 1), + MUX_INFO(0x1a, 1), + MUX_INFO(0x1b, 1), +}; + +static struct pca954x_platform_data pca9546_cpu1_data = { + .modes = pca9546_cpu1_modes, + .num_modes = 4, +}; + +static struct pca953x_platform_data pca9555_cpuled_data = { + .gpio_base = PCA9555_CPU_LED_GPIO_BASE, +}; +#endif + +static struct pca953x_platform_data pca9555psu1_data = { + .gpio_base = PCA9555_PSU_GPIO_BASE, +}; + +static struct pca953x_platform_data pca9555fan_data = { + .gpio_base = PCA9555_FAN_GPIO_BASE, +}; + +static struct pca953x_platform_data pca9555ID_data = { + .gpio_base = PCA9555_ID_GPIO_BASE, +}; + +static struct i2c_board_info ix1b_i2c_devices[] = { + { + I2C_BOARD_INFO("pca9546", 0x77), // 0 + .platform_data = &pca9546_1_data, + }, + { + I2C_BOARD_INFO("pca9546", 0x72), // 1 + .platform_data = &pca9546_2_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x26), // 2 + .platform_data = &pca9555psu1_data, + }, + { + I2C_BOARD_INFO("24c02", 0x54), // 3 + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 4 + .platform_data = &pca9548sfp1_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x74), // 5 + .platform_data = &pca9548sfp2_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x75), // 6 + .platform_data = &pca9548sfp3_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x76), // 7 + .platform_data = &pca9548sfp4_data, + }, + { + I2C_BOARD_INFO("CPLD-QSFP28", 0x38), // 8 + }, + { + I2C_BOARD_INFO("CPLD-QSFP28", 0x39), // 9 + }, + { + I2C_BOARD_INFO("pca9555", 0x23), // 10 + .platform_data = &pca9555ID_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x25), // 11 + .platform_data = &pca9555fan_data, + }, + { + I2C_BOARD_INFO("qci_pmbus_ix1b", 0x5f), // 12 + }, + { + I2C_BOARD_INFO("qci_pmbus_ix1b", 0x59), // 13 + }, +#if defined(QUANTA_CPU_RGL) + { + I2C_BOARD_INFO("pca9546", 0x71), // 14 + .platform_data = &pca9546_cpu1_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x20), // 15 + .platform_data = &pca9555_cpuled_data, + }, + { + I2C_BOARD_INFO("optoe1", 0x50), // 16 + }, +#endif +}; + +static struct platform_driver ix1b_platform_driver = { + .driver = { + .name = "qci-ix1b", + .owner = THIS_MODULE, + }, +}; + +static struct platform_led ix1b_leds[] = { +#if defined(QUANTA_CPU_RGL) + LED_INFO(SYSLED_AMBER), + LED_INFO(SYSLED_GREEN), +#endif + LED_INFO(FRONT_PSU1_GREEN), + LED_INFO(FRONT_PSU1_RED), + LED_INFO(FRONT_PSU2_GREEN), + LED_INFO(FRONT_PSU2_RED), + LED_INFO(FRONT_FAN_GREEN), + LED_INFO(FRONT_FAN_RED), + LED_INFO(REAR_FAN1_RED), + LED_INFO(REAR_FAN2_RED), + LED_INFO(REAR_FAN3_RED), + LED_INFO(REAR_FAN4_RED), +}; + +static struct gpio_led system_led[] = { +#if defined(QUANTA_CPU_RGL) + { + .name = "sysled_amber", + .default_trigger = "timer", + .gpio = (PCA9555_CPU_LED_GPIO_BASE + 10), + .active_low = 0, + }, + { + .name = "sysled_green", + .gpio = (PCA9555_CPU_LED_GPIO_BASE + 11), + .active_low = 0, + }, +#endif + { + .name = "front_led_psu1_green", + .gpio = (PCA9555_PSU_GPIO_BASE + 10), + .active_low = 0, + }, + { + .name = "front_led_psu1_red", + .gpio = (PCA9555_PSU_GPIO_BASE + 11), + .active_low = 0, + }, + { + .name = "front_led_psu2_green", + .gpio = (PCA9555_PSU_GPIO_BASE + 12), + .active_low = 0, + }, + { + .name = "front_led_psu2_red", + .gpio = (PCA9555_PSU_GPIO_BASE + 13), + .active_low = 0, + }, + { + .name = "front_led_fan_green", + .gpio = (PCA9555_PSU_GPIO_BASE + 14), + .active_low = 0, + }, + { + .name = "front_led_fan_red", + .gpio = (PCA9555_PSU_GPIO_BASE + 15), + .active_low = 0, + }, + { + .name = "rear_led_fan1_red", + .gpio = (PCA9555_FAN_GPIO_BASE + 12), + .active_low = 0, + }, + { + .name = "rear_led_fan2_red", + .gpio = (PCA9555_FAN_GPIO_BASE + 13), + .active_low = 0, + }, + { + .name = "rear_led_fan3_red", + .gpio = (PCA9555_FAN_GPIO_BASE + 14), + .active_low = 0, + }, + { + .name = "rear_led_fan4_red", + .gpio = (PCA9555_FAN_GPIO_BASE + 15), + .active_low = 0, + }, +}; + +static struct gpio_led_platform_data system_led_data = { + .num_leds = ARRAY_SIZE(system_led), + .leds = system_led +}; + +static struct platform_device system_led_dev = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &system_led_data, + }, +}; + +static struct platform_device qci_hwmon_device = { + .name = "qci-hwmon", + .id = 0, + .dev = { + }, +}; + +static struct platform_device *ix1b_device; + +struct gpio_led_data { + struct led_classdev cdev; + unsigned gpio; + struct work_struct work; + u8 new_level; + u8 can_sleep; + u8 active_low; + u8 blinking; + int (*platform_gpio_blink_set)(unsigned gpio, int state, + unsigned long *delay_on, unsigned long *delay_off); +}; + +struct gpio_leds_priv { + int num_leds; + struct gpio_led_data leds[]; +}; + +static int __init ix1b_platform_init(void) +{ + struct i2c_client *client; + struct i2c_adapter *adapter; + struct gpio_leds_priv *priv; + int i; + int ret; + + ret = platform_driver_register(&ix1b_platform_driver); + if (ret < 0) + return ret; + + /* Register platform stuff */ + ix1b_device = platform_device_alloc("qci-ix1b", -1); + if (!ix1b_device) { + ret = -ENOMEM; + goto fail_platform_driver; + } + + ret = platform_device_add(ix1b_device); + if (ret) + goto fail_platform_device; + + adapter = i2c_get_adapter(0); + client = i2c_new_device(adapter, &ix1b_i2c_devices[0]); // pca9546_1 - Address: 0x77 + printk("[CC] NEW device pca9546_1\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[1]); // pca9546_2 - Address: 0x72 + printk("[CC] NEW device pca9546_2\n"); +#if defined(QUANTA_CPU_RGL) + client = i2c_new_device(adapter, &ix1b_i2c_devices[14]); // cpu pca9546_1 - Address: 0x71 + printk("[CC] NEW device cpu pca9546_1\n"); +#endif + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x14); + client = i2c_new_device(adapter, &ix1b_i2c_devices[12]); // pmbus_psu1 - Address: 0x5f + printk("[CC] NEW device pmbus_psu1\n"); + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x15); + client = i2c_new_device(adapter, &ix1b_i2c_devices[13]); // pmbus_psu2 - Address: 0x59 + printk("[CC] NEW device pmbus_psu2\n"); + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x16); + client = i2c_new_device(adapter, &ix1b_i2c_devices[2]); // pca9555-PSU1 - Address: 0x26 + printk("[CC] NEW device pca9555-PSU1\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[3]); // MB_BOARDINFO_EEPROM - Address: 0x54 + printk("[CC] NEW device MB_BOARDINFO_EEPROM\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[10]); // pca9555-ID - Address: 0x23 + printk("[CC] NEW device pca9555-ID\n"); + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x17); + client = i2c_new_device(adapter, &ix1b_i2c_devices[11]); // pca9555-fan - Address: 0x25 + printk("[CC] NEW device pca9555-fan\n"); + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x10); + client = i2c_new_device(adapter, &ix1b_i2c_devices[4]); // pca9548_1 SFP - Address: 0x73 + printk("[CC] NEW device pca9548_1 SFP\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[5]); // pca9548_2 SFP - Address: 0x74 + printk("[CC] NEW device pca9548_2 SFP\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[6]); // pca9548_3 SFP - Address: 0x75 + printk("[CC] NEW device pca9548_3 SFP\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[8]); // CPLD2 - Address: 0x38 + printk("[CC] NEW device CPLD2\n"); + client = i2c_new_device(adapter, &ix1b_i2c_devices[9]); // CPLD3 - Address: 0x39 + printk("[CC] NEW device CPLD3\n"); + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x11); + client = i2c_new_device(adapter, &ix1b_i2c_devices[7]); // pca9548_4 SFP - Address: 0x76 + printk("[CC] NEW device pca9548_4 SFP\n"); + i2c_put_adapter(adapter); + +#if defined(QUANTA_CPU_RGL) + adapter = i2c_get_adapter(0x18); + client = i2c_new_device(adapter, &ix1b_i2c_devices[15]); // cpu pca9555_1 - Address: 0x20 + printk("[CC] NEW device cpu pca9555_1\n"); + i2c_put_adapter(adapter); + + for(i = 0x20; i < 0x40; i++) + { + adapter = i2c_get_adapter(i); + client = i2c_new_device(adapter, &ix1b_i2c_devices[16]); // eeprom for loopback module - Address: 0x50 + i2c_put_adapter(adapter); + } + printk("[CC] NEW device eeprom\n"); +#endif + + /* Register LED devices */ + platform_device_register(&system_led_dev); + priv = platform_get_drvdata(&system_led_dev); + for (i = 0; i < priv->num_leds; i++) { + printk("leds-gpio gpio-%d: Register led %s\n", priv->leds[i].gpio, priv->leds[i].cdev.name); + ix1b_leds[i].cdev = &(priv->leds[i].cdev); + } + printk("[CC] NEW device led\n"); + + platform_device_register(&qci_hwmon_device); + printk("[CC] NEW device hwmon\n"); + + return 0; + +fail_platform_device: + platform_device_put(ix1b_device); + +fail_platform_driver: + platform_driver_unregister(&ix1b_platform_driver); + return ret; +} + +static void __exit ix1b_platform_exit(void) +{ + platform_device_unregister(ix1b_device); + platform_driver_unregister(&ix1b_platform_driver); +} + +module_init(ix1b_platform_init); +module_exit(ix1b_platform_exit); + + +MODULE_AUTHOR("Quanta Computer Inc."); +MODULE_DESCRIPTION("Quanta IX1B Platform Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_pmbus.c b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_pmbus.c new file mode 100755 index 000000000000..0fac27b59b6c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/modules/qci_pmbus.c @@ -0,0 +1,741 @@ +/* + * QUANTA Generic PMBUS driver + * + * + * Based on generic pmbus driver and ltc2978 driver + * + * Author: Chih-Pei Chang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +enum projects { ly8, ix1, ix2, ix1b }; + +#define DELAY_TIME 1000 /* uS */ + +/* Pmbus reg defines are copied from drivers/hwmon/pmbus/pmbus.h*/ +/* + * Registers + */ +enum pmbus_regs { + PMBUS_PAGE = 0x00, + PMBUS_OPERATION = 0x01, + PMBUS_ON_OFF_CONFIG = 0x02, + PMBUS_CLEAR_FAULTS = 0x03, + PMBUS_PHASE = 0x04, + + PMBUS_CAPABILITY = 0x19, + PMBUS_QUERY = 0x1A, + + PMBUS_VOUT_MODE = 0x20, + PMBUS_VOUT_COMMAND = 0x21, + PMBUS_VOUT_TRIM = 0x22, + PMBUS_VOUT_CAL_OFFSET = 0x23, + PMBUS_VOUT_MAX = 0x24, + PMBUS_VOUT_MARGIN_HIGH = 0x25, + PMBUS_VOUT_MARGIN_LOW = 0x26, + PMBUS_VOUT_TRANSITION_RATE = 0x27, + PMBUS_VOUT_DROOP = 0x28, + PMBUS_VOUT_SCALE_LOOP = 0x29, + PMBUS_VOUT_SCALE_MONITOR = 0x2A, + + PMBUS_COEFFICIENTS = 0x30, + PMBUS_POUT_MAX = 0x31, + + PMBUS_FAN_CONFIG_12 = 0x3A, + PMBUS_FAN_COMMAND_1 = 0x3B, + PMBUS_FAN_COMMAND_2 = 0x3C, + PMBUS_FAN_CONFIG_34 = 0x3D, + PMBUS_FAN_COMMAND_3 = 0x3E, + PMBUS_FAN_COMMAND_4 = 0x3F, + + PMBUS_VOUT_OV_FAULT_LIMIT = 0x40, + PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41, + PMBUS_VOUT_OV_WARN_LIMIT = 0x42, + PMBUS_VOUT_UV_WARN_LIMIT = 0x43, + PMBUS_VOUT_UV_FAULT_LIMIT = 0x44, + PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45, + PMBUS_IOUT_OC_FAULT_LIMIT = 0x46, + PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47, + PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48, + PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49, + PMBUS_IOUT_OC_WARN_LIMIT = 0x4A, + PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B, + PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C, + + PMBUS_OT_FAULT_LIMIT = 0x4F, + PMBUS_OT_FAULT_RESPONSE = 0x50, + PMBUS_OT_WARN_LIMIT = 0x51, + PMBUS_UT_WARN_LIMIT = 0x52, + PMBUS_UT_FAULT_LIMIT = 0x53, + PMBUS_UT_FAULT_RESPONSE = 0x54, + PMBUS_VIN_OV_FAULT_LIMIT = 0x55, + PMBUS_VIN_OV_FAULT_RESPONSE = 0x56, + PMBUS_VIN_OV_WARN_LIMIT = 0x57, + PMBUS_VIN_UV_WARN_LIMIT = 0x58, + PMBUS_VIN_UV_FAULT_LIMIT = 0x59, + + PMBUS_IIN_OC_FAULT_LIMIT = 0x5B, + PMBUS_IIN_OC_WARN_LIMIT = 0x5D, + + PMBUS_POUT_OP_FAULT_LIMIT = 0x68, + PMBUS_POUT_OP_WARN_LIMIT = 0x6A, + PMBUS_PIN_OP_WARN_LIMIT = 0x6B, + + PMBUS_STATUS_BYTE = 0x78, + PMBUS_STATUS_WORD = 0x79, + PMBUS_STATUS_VOUT = 0x7A, + PMBUS_STATUS_IOUT = 0x7B, + PMBUS_STATUS_INPUT = 0x7C, + PMBUS_STATUS_TEMPERATURE = 0x7D, + PMBUS_STATUS_CML = 0x7E, + PMBUS_STATUS_OTHER = 0x7F, + PMBUS_STATUS_MFR_SPECIFIC = 0x80, + PMBUS_STATUS_FAN_12 = 0x81, + PMBUS_STATUS_FAN_34 = 0x82, + + PMBUS_READ_VIN = 0x88, + PMBUS_READ_IIN = 0x89, + PMBUS_READ_VCAP = 0x8A, + PMBUS_READ_VOUT = 0x8B, + PMBUS_READ_IOUT = 0x8C, + PMBUS_READ_TEMPERATURE_1 = 0x8D, + PMBUS_READ_TEMPERATURE_2 = 0x8E, + PMBUS_READ_TEMPERATURE_3 = 0x8F, + PMBUS_READ_FAN_SPEED_1 = 0x90, + PMBUS_READ_FAN_SPEED_2 = 0x91, + PMBUS_READ_FAN_SPEED_3 = 0x92, + PMBUS_READ_FAN_SPEED_4 = 0x93, + PMBUS_READ_DUTY_CYCLE = 0x94, + PMBUS_READ_FREQUENCY = 0x95, + PMBUS_READ_POUT = 0x96, + PMBUS_READ_PIN = 0x97, + + PMBUS_REVISION = 0x98, + PMBUS_MFR_ID = 0x99, + PMBUS_MFR_MODEL = 0x9A, + PMBUS_MFR_REVISION = 0x9B, + PMBUS_MFR_LOCATION = 0x9C, + PMBUS_MFR_DATE = 0x9D, + PMBUS_MFR_SERIAL = 0x9E, + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ + PMBUS_VIRT_BASE = 0x100, + PMBUS_VIRT_READ_TEMP_AVG, + PMBUS_VIRT_READ_TEMP_MIN, + PMBUS_VIRT_READ_TEMP_MAX, + PMBUS_VIRT_RESET_TEMP_HISTORY, + PMBUS_VIRT_READ_VIN_AVG, + PMBUS_VIRT_READ_VIN_MIN, + PMBUS_VIRT_READ_VIN_MAX, + PMBUS_VIRT_RESET_VIN_HISTORY, + PMBUS_VIRT_READ_IIN_AVG, + PMBUS_VIRT_READ_IIN_MIN, + PMBUS_VIRT_READ_IIN_MAX, + PMBUS_VIRT_RESET_IIN_HISTORY, + PMBUS_VIRT_READ_PIN_AVG, + PMBUS_VIRT_READ_PIN_MIN, + PMBUS_VIRT_READ_PIN_MAX, + PMBUS_VIRT_RESET_PIN_HISTORY, + PMBUS_VIRT_READ_POUT_AVG, + PMBUS_VIRT_READ_POUT_MIN, + PMBUS_VIRT_READ_POUT_MAX, + PMBUS_VIRT_RESET_POUT_HISTORY, + PMBUS_VIRT_READ_VOUT_AVG, + PMBUS_VIRT_READ_VOUT_MIN, + PMBUS_VIRT_READ_VOUT_MAX, + PMBUS_VIRT_RESET_VOUT_HISTORY, + PMBUS_VIRT_READ_IOUT_AVG, + PMBUS_VIRT_READ_IOUT_MIN, + PMBUS_VIRT_READ_IOUT_MAX, + PMBUS_VIRT_RESET_IOUT_HISTORY, + PMBUS_VIRT_READ_TEMP2_AVG, + PMBUS_VIRT_READ_TEMP2_MIN, + PMBUS_VIRT_READ_TEMP2_MAX, + PMBUS_VIRT_RESET_TEMP2_HISTORY, + + PMBUS_VIRT_READ_VMON, + PMBUS_VIRT_VMON_UV_WARN_LIMIT, + PMBUS_VIRT_VMON_OV_WARN_LIMIT, + PMBUS_VIRT_VMON_UV_FAULT_LIMIT, + PMBUS_VIRT_VMON_OV_FAULT_LIMIT, + PMBUS_VIRT_STATUS_VMON, +}; + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN BIT(0) +#define PMBUS_HAVE_VCAP BIT(1) +#define PMBUS_HAVE_VOUT BIT(2) +#define PMBUS_HAVE_IIN BIT(3) +#define PMBUS_HAVE_IOUT BIT(4) +#define PMBUS_HAVE_PIN BIT(5) +#define PMBUS_HAVE_POUT BIT(6) +#define PMBUS_HAVE_FAN12 BIT(7) +#define PMBUS_HAVE_FAN34 BIT(8) +#define PMBUS_HAVE_TEMP BIT(9) +#define PMBUS_HAVE_TEMP2 BIT(10) +#define PMBUS_HAVE_TEMP3 BIT(11) +#define PMBUS_HAVE_STATUS_VOUT BIT(12) +#define PMBUS_HAVE_STATUS_IOUT BIT(13) +#define PMBUS_HAVE_STATUS_INPUT BIT(14) +#define PMBUS_HAVE_STATUS_TEMP BIT(15) +#define PMBUS_HAVE_STATUS_FAN12 BIT(16) +#define PMBUS_HAVE_STATUS_FAN34 BIT(17) +#define PMBUS_HAVE_VMON BIT(18) +#define PMBUS_HAVE_STATUS_VMON BIT(19) + +enum pmbus_data_format { linear = 0, direct, vid }; +enum vrm_version { vr11 = 0, vr12, vr13 }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + enum vrm_version vrm_version; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); + + /* Regulator functionality, if supported by this chip driver. */ + int num_regulators; + const struct regulator_desc *reg_desc; +}; + +extern int pmbus_set_page(struct i2c_client *client, u8 page); +extern int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +extern bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +extern bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); +extern int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +extern int pmbus_do_remove(struct i2c_client *client); + +/* Needed to access the mutex. Copied from pmbus_core.c */ +#define PB_STATUS_BASE 0 +#define PB_STATUS_VOUT_BASE (PB_STATUS_BASE + PMBUS_PAGES) +#define PB_STATUS_IOUT_BASE (PB_STATUS_VOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN_BASE (PB_STATUS_IOUT_BASE + PMBUS_PAGES) +#define PB_STATUS_FAN34_BASE (PB_STATUS_FAN_BASE + PMBUS_PAGES) +#define PB_STATUS_TEMP_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES) +#define PB_STATUS_INPUT_BASE (PB_STATUS_TEMP_BASE + PMBUS_PAGES) +#define PB_STATUS_VMON_BASE (PB_STATUS_INPUT_BASE + 1) +#define PB_NUM_STATUS_REG (PB_STATUS_VMON_BASE + 1) +struct pmbus_data { + struct device *dev; + struct device *hwmon_dev; + + u32 flags; /* from platform data */ + + int exponent[PMBUS_PAGES]; + /* linear mode: exponent for output voltages */ + + const struct pmbus_driver_info *info; + + int max_attributes; + int num_attributes; + struct attribute_group group; + const struct attribute_group *groups[2]; + + struct pmbus_sensor *sensors; + + struct mutex update_lock; + bool valid; + unsigned long last_updated; /* in jiffies */ + + /* + * A single status register covers multiple attributes, + * so we keep them all together. + */ + u8 status[PB_NUM_STATUS_REG]; + u8 status_register; + + u8 currpage; +}; + +static int qci_pmbus_read_block(struct i2c_client *client, u8 command, int data_len, u8 *data) +{ + int result = 0; + int retry_count = 3; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (result < 0) { + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static ssize_t qci_pmbus_show_mfr_id(struct device *dev, + struct device_attribute *da, char *buf) +{ + int ret, len; + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1], *str; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + ret = qci_pmbus_read_block(client, PMBUS_MFR_ID, I2C_SMBUS_BLOCK_MAX, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer ID\n"); + return ret; + } + len = block_buffer[0]; + block_buffer[(len+1)] = '\0'; + str = &(block_buffer[1]); + + return snprintf(buf, PAGE_SIZE, "%s\n", str); +} + +static ssize_t qci_pmbus_show_mfr_model(struct device *dev, + struct device_attribute *da, char *buf) +{ + int ret, len; + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1], *str; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + ret = qci_pmbus_read_block(client, PMBUS_MFR_MODEL, I2C_SMBUS_BLOCK_MAX, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer Model\n"); + return ret; + } + len = block_buffer[0]; + block_buffer[(len+1)] = '\0'; + str = &(block_buffer[1]); + + return snprintf(buf, PAGE_SIZE, "%s\n", str); +} + +static ssize_t qci_pmbus_show_mfr_revision(struct device *dev, + struct device_attribute *da, char *buf) +{ + int ret, len; + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1], *str; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + ret = qci_pmbus_read_block(client, PMBUS_MFR_REVISION, I2C_SMBUS_BLOCK_MAX, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer Revision\n"); + return ret; + } + len = block_buffer[0]; + block_buffer[(len+1)] = '\0'; + str = &(block_buffer[1]); + + return snprintf(buf, PAGE_SIZE, "%s\n", str); +} + +static ssize_t qci_pmbus_show_mfr_location(struct device *dev, + struct device_attribute *da, char *buf) +{ + int ret, len; + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1], *str; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + ret = qci_pmbus_read_block(client, PMBUS_MFR_LOCATION, I2C_SMBUS_BLOCK_MAX, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacture Location\n"); + return ret; + } + len = block_buffer[0]; + block_buffer[(len+1)] = '\0'; + str = &(block_buffer[1]); + + return snprintf(buf, PAGE_SIZE, "%s\n", str); +} + +static ssize_t qci_pmbus_show_mfr_serial(struct device *dev, + struct device_attribute *da, char *buf) +{ + int ret, len; + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1], *str; + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + + ret = qci_pmbus_read_block(client, PMBUS_MFR_SERIAL, I2C_SMBUS_BLOCK_MAX, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer Serial\n"); + return ret; + } + len = block_buffer[0]; + block_buffer[(len+1)] = '\0'; + str = &(block_buffer[1]); + + return snprintf(buf, PAGE_SIZE, "%s\n", str); +} + + +static DEVICE_ATTR(mfr_id, S_IRUGO, qci_pmbus_show_mfr_id, NULL); +static DEVICE_ATTR(mfr_model, S_IRUGO, qci_pmbus_show_mfr_model, NULL); +static DEVICE_ATTR(mfr_revision, S_IRUGO, qci_pmbus_show_mfr_revision, NULL); +static DEVICE_ATTR(mfr_location, S_IRUGO, qci_pmbus_show_mfr_location, NULL); +static DEVICE_ATTR(mfr_serial, S_IRUGO, qci_pmbus_show_mfr_serial, NULL); + + +static struct attribute *qci_pmbus_inventory_attrs[] = { + &dev_attr_mfr_id.attr, + &dev_attr_mfr_model.attr, + &dev_attr_mfr_revision.attr, + &dev_attr_mfr_location.attr, + &dev_attr_mfr_serial.attr, + NULL +}; + +static struct attribute_group qci_pmbus_inventory_attr_grp = { + .attrs = qci_pmbus_inventory_attrs +}; + +/* FIXME: add project specific id here */ +static const struct i2c_device_id qci_pmbus_id[] = { + {"qci_pmbus_ly8", ly8}, + {"qci_pmbus_ix1", ix1}, + {"qci_pmbus_ix2", ix2}, + {"qci_pmbus_ix1b", ix1b}, + {} +}; +MODULE_DEVICE_TABLE(i2c, qci_pmbus_id); + +/* + * Find sensor groups and status registers on each page. + */ +static void qci_pmbus_find_sensor_groups(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int page; + + /* Sensors detected on page 0 only */ + if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) + info->func[0] |= PMBUS_HAVE_VIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_VCAP)) + info->func[0] |= PMBUS_HAVE_VCAP; + if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN)) + info->func[0] |= PMBUS_HAVE_IIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN)) + info->func[0] |= PMBUS_HAVE_PIN; + if (info->func[0] + && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) + info->func[0] |= PMBUS_HAVE_STATUS_INPUT; + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { + info->func[0] |= PMBUS_HAVE_FAN12; + if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN12; + } + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) { + info->func[0] |= PMBUS_HAVE_FAN34; + if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN34; + } + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) + info->func[0] |= PMBUS_HAVE_TEMP; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) + info->func[0] |= PMBUS_HAVE_TEMP2; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) + info->func[0] |= PMBUS_HAVE_TEMP3; + if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_TEMP3) + && pmbus_check_byte_register(client, 0, + PMBUS_STATUS_TEMPERATURE)) + info->func[0] |= PMBUS_HAVE_STATUS_TEMP; + + /* Sensors detected on all pages */ + for (page = 0; page < info->pages; page++) { + if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) { + info->func[page] |= PMBUS_HAVE_VOUT; + if (pmbus_check_byte_register(client, page, + PMBUS_STATUS_VOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_VOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) { + info->func[page] |= PMBUS_HAVE_IOUT; + if (pmbus_check_byte_register(client, 0, + PMBUS_STATUS_IOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_IOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_POUT)) + info->func[page] |= PMBUS_HAVE_POUT; + } +} + +/* + * Identify chip parameters. + */ +static int qci_pmbus_identify(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int ret = 0; + + if (!info->pages) { + /* + * Check if the PAGE command is supported. If it is, + * keep setting the page number until it fails or until the + * maximum number of pages has been reached. Assume that + * this is the number of pages supported by the chip. + */ + if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { + int page; + + for (page = 1; page < PMBUS_PAGES; page++) { + if (pmbus_set_page(client, page) < 0) + break; + } + pmbus_set_page(client, 0); + info->pages = page; + } else { + info->pages = 1; + } + } + + if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { + int vout_mode; + + vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); + if (vout_mode >= 0 && vout_mode != 0xff) { + switch (vout_mode >> 5) { + case 0: + break; + case 1: + info->format[PSC_VOLTAGE_OUT] = vid; + info->vrm_version = vr11; + break; + case 2: + info->format[PSC_VOLTAGE_OUT] = direct; + break; + default: + ret = -ENODEV; + goto abort; + } + } + } + + /* + * We should check if the COEFFICIENTS register is supported. + * If it is, and the chip is configured for direct mode, we can read + * the coefficients from the chip, one set per group of sensor + * registers. + * + * To do this, we will need access to a chip which actually supports the + * COEFFICIENTS command, since the command is too complex to implement + * without testing it. Until then, abort if a chip configured for direct + * mode was detected. + */ + if (info->format[PSC_VOLTAGE_OUT] == direct) { + ret = -ENODEV; + goto abort; + } + + /* if no function pre-defined, try to find sensor groups */ + if (info->func[0] == 0) qci_pmbus_find_sensor_groups(client, info); +abort: + return ret; +} + +int qci_pmbus_set_page(struct i2c_client *client, u8 page) +{ + struct pmbus_data *data = i2c_get_clientdata(client); + int rv = 0; + int newpage; + + if (page != data->currpage) { + rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); + udelay(DELAY_TIME); + newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); + if (newpage != page) + rv = -EIO; + else + data->currpage = page; + } + return rv; +} + +int qci_write_byte(struct i2c_client *client, int page, u8 value) +{ + int rv; + + if (page >= 0) { + rv = qci_pmbus_set_page(client, page); + if (rv < 0) + return rv; + } + + rv = i2c_smbus_write_byte(client, value); + udelay(DELAY_TIME); + return rv; +} + +int qci_write_word_data(struct i2c_client *client, int page, int reg, u16 word) +{ + int rv; + + rv = qci_pmbus_set_page(client, page); + if (rv < 0) + return rv; + + rv = i2c_smbus_write_word_data(client, reg, word); + udelay(DELAY_TIME); + return rv; +} + +static int qci_pmbus_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct pmbus_driver_info *info; + int ret; + + dev_info(dev, "qci_pmbus_probe\n"); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_WORD_DATA)) + return -ENODEV; + + info = devm_kzalloc(dev, sizeof(struct pmbus_driver_info), GFP_KERNEL); + + if (!info) + return -ENOMEM; + + info->func[0] = 0; + + /* FIXME: add project specific function table here */ + switch (id->driver_data) { + case ly8: + info->pages = 1; + info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT + | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 + | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT + | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT + ; + break; + case ix1: + case ix2: + case ix1b: + info->pages = 1; + info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN + | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT + | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 + | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP + | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT + | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT + | PMBUS_HAVE_POUT + ; + break; + default: + break; + } + info->write_word_data = qci_write_word_data; + info->write_byte = qci_write_byte; + info->identify = qci_pmbus_identify; /* FIXME: reserve for future use */ + + /* Register sysfs hooks */ + ret = sysfs_create_group(&dev->kobj, &qci_pmbus_inventory_attr_grp); + if (ret) { + dev_err(dev, "Failed to create sysfs entries\n"); + return -1; + } + + return pmbus_do_probe(client, id, info); +} + +/* This is the driver that will be inserted */ +static struct i2c_driver qci_pmbus_driver = { + .driver = { + .name = "qci-pmbus", + }, + .probe = qci_pmbus_probe, + .remove = pmbus_do_remove, + .id_table = qci_pmbus_id, +}; + +module_i2c_driver(qci_pmbus_driver); + + +MODULE_AUTHOR("Quanta Computer Inc."); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("QUANTA generic PMBus driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/service/ix1b-platform-init.service b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/service/ix1b-platform-init.service new file mode 100755 index 000000000000..a51c0cca6914 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/service/ix1b-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Quanta IX1B-32X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/quanta_ix1b_util.py install +ExecStop=/usr/local/bin/quanta_ix1b_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/setup.py b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/setup.py new file mode 100755 index 000000000000..e37687db7eca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='ix1b_32x', + version='1.0', + description='Module to initialize Quanta IX1B-32X platforms', + + packages=['ix1b_32x'], + package_dir={'ix1b_32x': 'ix1b-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/utils/quanta_ix1b_util.py b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/utils/quanta_ix1b_util.py new file mode 100755 index 000000000000..2135932938eb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix1b-32x/utils/quanta_ix1b_util.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Quanta Computer Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv) < 2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level = logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[IX1B-32X]" + txt + + return + +def exec_cmd(cmd, show): + logging.info('Run :' + cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd + "with result:" + str(status)) + show_log (" output:" + output) + if status: + logging.info('Failed :' + cmd) + if show: + print('Failed :' + cmd) + + return status, output + +instantiate = [ +#turn on module power +'echo 53 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio53/direction', +'echo 1 > /sys/class/gpio/gpio53/value', +#PSU1 present +'echo 16 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio16/direction', +#PSU1 power good signal +'echo 17 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio17/direction', +#PSU2 present +'echo 19 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio19/direction', +#PSU2 power good signal +'echo 20 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio20/direction', +#FAN 1-4 present +'echo 36 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio36/direction', +'echo 37 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio37/direction', +'echo 38 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio38/direction', +'echo 39 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio39/direction', +#turn on 100G led by default +'i2cset -y 0x13 0x38 0x00 0xff', +'i2cset -y 0x13 0x38 0x01 0xff', +'i2cset -y 0x13 0x39 0x00 0xff', +'i2cset -y 0x13 0x39 0x01 0xff' +] + +drivers =[ +'lpc_ich', +'i2c-i801', +'i2c-dev', +'i2c-mux-pca954x', +'gpio-pca953x', +'qci_pmbus', +'leds-gpio', +'optoe', +'qci_cpld_qsfp28', +'qci_platform_ix1b' +] + +def system_install(): + global FORCE + + time.sleep(3) + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("rmmod i2c_ismt ", 1) + status, output = exec_cmd("rmmod i2c-i801 ", 1) + #setup driver dependency + status, output = exec_cmd("depmod -a ", 1) + + #install drivers + for i in range(0, len(drivers)): + status, output = exec_cmd("modprobe " + drivers[i], 1) + + if status: + print output + if FORCE == 0: + return status + + #instantiate devices + for i in range(0, len(instantiate)): + status, output = exec_cmd(instantiate[i], 1) + + if status: + print output + if FORCE == 0: + return status + + #Mount Quanta hardware monitor driver + status, output = exec_cmd("modprobe qci_hwmon_ix1b", 1) + + #QSFP for 1~32 port + for port_number in range(1, 33): + bus_number = port_number + 31 + os.system("echo %d >/sys/bus/i2c/devices/%d-0050/port_name" % (port_number, bus_number)) + + #Set system LED to green + status, output = exec_cmd("echo 1 > /sys/class/leds/sysled_green/brightness", 1) + + return + +def system_ready(): + if not device_found(): + return False + + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + + if status: + if FORCE == 0: + return status + else: + print " ix1b driver already installed...." + + return + +def uninstall(): + global FORCE + + #uninstall drivers + for i in range(len(drivers) - 1, -1, -1): + status, output = exec_cmd("rmmod " + drivers[i], 1) + + if status: + print output + if FORCE == 0: + return status + + return + +def device_found(): + ret1, log = exec_cmd("ls " + i2c_prefix + "i2c-0", 0) + + return ret1 + +if __name__ == "__main__": + main() + + + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/Makefile new file mode 100644 index 000000000000..405c9153c091 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m:=qci_cpld.o qci_cpld_led.o quanta_platform_ix7.o + + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/qci_cpld.c b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/qci_cpld.c new file mode 100644 index 000000000000..e8556bc72d46 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/qci_cpld.c @@ -0,0 +1,451 @@ +/* + * A CPLD driver for monitor QSFP28 module I/O + * + * The CPLD is customize by Quanta for controlling QSFP28 module signals, + * they are RESET , INTERREPT , Module_Present, LPMODE + * Each CPLD control 16 modules, each module use 4 bits in register. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_ida); + +enum platform_type { + SFP = 0, + QSFP, + QSFP28, + NONE +}; + +static struct class *cpld_class = NULL; + +struct sfp_data { + struct i2c_client *cpld_client; + char name[8]; + char type[8]; + u8 port_id; + u8 cpld_port; +}; + +struct cpld_data { + struct mutex lock; + struct device *port_dev[16]; + struct sfp_data *port_data[16]; +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_id[] = { + { "CPLD-SFP", SFP }, + { "CPLD-QSFP", QSFP }, + { "CPLD-QSFP28", QSFP28 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +// .address_list = normal_i2c, +}; + +#define CPLD_ID_PREFIX "port-" +#define CPLD_ID_FORMAT CPLD_ID_PREFIX "%d" + +#define RESET_MASK 0x08 +#define INTERRUPT_MASK 0x04 +#define MODULE_PRESENT_MASK 0x02 +#define LPMODE_MASK 0x01 +//#define I2C_MONITOR_MASK 0x01 + +static inline u8 get_group_cmd(u8 group) +{ + //FIXME: if group cmd change + return (group + 1); +} + +static inline u8 port_remapping(u8 phy_port) +{ + /* FIXME: implement by hardware design */ + /* The CPLD register port mapping is weird : + * MSB -------- LSB (word data) + * P3 P4 P1 P2 (per port 4 bits) + * For easy coding bit shift, we treat it as hw port swap + */ + return (phy_port % 2) ? (phy_port - 1) : (phy_port + 1); +} + +static ssize_t get_reset(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= RESET_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_interrupt(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= INTERRUPT_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_module_present(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= MODULE_PRESENT_MASK; + + //FIXME: if present is not low active + return sprintf(buf, "%d\n", value ? 0 : 1); +} + +static ssize_t get_lpmode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= LPMODE_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t set_reset(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(RESET_MASK << (group_port * 4)); + if (disable) + value |= (RESET_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_lpmode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(LPMODE_MASK << (group_port * 4)); + if (disable) + value |= (LPMODE_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(reset, S_IWUSR | S_IRUGO, get_reset, set_reset); +static DEVICE_ATTR(lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode); +static DEVICE_ATTR(module_present, S_IRUGO, get_module_present, NULL); +static DEVICE_ATTR(interrupt, S_IRUGO, get_interrupt, NULL); +//static DEVICE_ATTR(led_enable, S_IWUSR | S_IRUGO, get_led_enable, set_led_enable); +//static DEVICE_ATTR(monitor_enable, S_IWUSR | S_IRUGO, get_monitor_enable, set_monitor_enable); + +static const struct attribute *sfp_attrs[] = { + &dev_attr_reset.attr, + &dev_attr_lpmode.attr, + &dev_attr_module_present.attr, + &dev_attr_interrupt.attr, +// &dev_attr_led_enable.attr, + NULL, +}; + +static const struct attribute_group sfp_attr_group = { + .attrs = (struct attribute **) sfp_attrs, +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_data *data; + struct sfp_data *port_data; +// struct i2c_monitor_data *monitor_data; + struct device *port_dev; +// struct device *i2c_dev; + int port_nr, i=0, err, max_port_num; + char name[I2C_NAME_SIZE], type[I2C_NAME_SIZE]; + + printk("cpld cpld_probe\n"); + + while(id->name[i]) + { + name[i]=tolower(id->name[i]); + i++; + } + name[i]='\0'; + strncpy(type,name+5,strlen(name)-5); + type[strlen(name)-5]='\0'; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, name); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + if(!strcmp(client->name, "CPLD-QSFP28")){ + max_port_num = 16; + } + else{ + max_port_num = 4; + } + + /* register sfp port data to sysfs */ + for (i = 0; i < max_port_num; i++) + { + port_nr = ida_simple_get(&cpld_ida, 1, 99, GFP_KERNEL); + if (port_nr < 0) + goto err_out; + + port_data = kzalloc(sizeof(struct sfp_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), port_data, CPLD_ID_FORMAT, port_nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + printk("err_status\n"); + } + + data->port_dev[i] = port_dev; + data->port_data[i] = port_data; + + strcpy(port_data->type, type); + + dev_info(&client->dev, "Register %s port-%d\n", port_data->type , port_nr); + + /* FIXME: implement Logical/Physical port remapping */ + //port_data->cpld_port = i; + port_data->cpld_port = port_remapping(i); + sprintf(port_data->name, "port-%d", port_nr); + port_data->port_id = port_nr; + dev_set_drvdata(port_dev, port_data); + port_dev->init_name = port_data->name; + port_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &sfp_attr_group); + // if (status) printk("err status\n"); + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +err_out: + return port_nr; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +#if 1 +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} +#endif + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + int i, max_port_num; +// int id; + + if(!strcmp(client->name, "CPLD-QSFP28")){ + max_port_num = 16; + } + else{ + max_port_num = 4; + } + + for (i = (max_port_num - 1); i >= 0; i--) + { + dev_info(data->port_dev[i], "Remove %s port-%d\n", data->port_data[i]->type , data->port_data[i]->port_id); + device_unregister(data->port_dev[i]); + ida_simple_remove(&cpld_ida, data->port_data[i]->port_id); + kfree(data->port_data[i]); + } + + if (cpld_idr_is_empty(&cpld_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_DESCRIPTION("Quanta Switch QSFP28 CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/qci_cpld_led.c b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/qci_cpld_led.c new file mode 100644 index 000000000000..37fc2e07246e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/qci_cpld_led.c @@ -0,0 +1,275 @@ +/* + * A LED CPLD driver for Quanta Switch Platform + * + * The CPLD is customize by Quanta for decode led bit stream, + * This driver modify from Quanta CPLD I/O driver. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * Author: Roger Chang + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_led_ida); + +enum platform_type { + IX7 = 0, + IX8, + NONE +}; + +static struct class *cpld_class = NULL; + +struct cpld_data { + struct i2c_client *cpld_client; + char name[8]; + u8 cpld_id; +}; + +struct cpld_led_data { + struct mutex lock; + struct device *port_dev; + struct cpld_data *cpld_data; +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_led_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_led_id[] = { + { "CPLDLED_IX7", IX7 }, + { "CPLDLED_IX8", IX8 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_led_id); + +static struct i2c_driver cpld_led_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_led", + }, + .probe = cpld_led_probe, + .remove = cpld_led_remove, + .id_table = cpld_led_id, +// .address_list = normal_i2c, +}; + +#define CPLD_LED_ID_PREFIX "CPLDLED-" +#define CPLD_LED_ID_FORMAT CPLD_LED_ID_PREFIX "%d" + +#define CPLD_DECODER_OFFSET 0x4 +#define CPLD_DECODER_MASK 0x1 +#define CPLD_USERCODE_START_OFFSET 0x0 + +static ssize_t get_led_decode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 offset = (u8)(CPLD_DECODER_OFFSET); + s32 value; + + value = i2c_smbus_read_byte_data(client, offset); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value &= CPLD_DECODER_MASK; + + return sprintf(buf, "%d\n", (value == 0) ? 1 : 0); +} + +static ssize_t get_usercode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 i = 0; + s32 value = 0, reading = 0; + + for (i = 0; i < 4; i++) + { + reading = i2c_smbus_read_byte_data(client, CPLD_USERCODE_START_OFFSET + i); + if (reading < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led usercode reg %d value= %x\n", i, reading); + + value |= reading << (24 - 8 * i); + } + + return sprintf(buf, "%X\n", value); +} + +static ssize_t set_led_decode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + s32 value; + long enable; + + if (kstrtol(buf, 0, &enable)) + return -EINVAL; + + if ((enable != 1) && (enable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_byte_data(client, CPLD_DECODER_OFFSET); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value |= CPLD_DECODER_MASK; + if (enable) + value &= ~CPLD_DECODER_MASK; + + dev_dbg(&client->dev, "write led decode value= %x\n", value); + + i2c_smbus_write_byte_data(client, CPLD_DECODER_OFFSET, (u8)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(led_decode, S_IWUSR | S_IRUGO, get_led_decode, set_led_decode); +static DEVICE_ATTR(usercode, S_IRUGO, get_usercode, NULL); + +static const struct attribute *led_attrs[] = { + &dev_attr_usercode.attr, + &dev_attr_led_decode.attr, + NULL, +}; + +static const struct attribute_group led_attr_group = { + .attrs = (struct attribute **) led_attrs, +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_led_data *data; + struct cpld_data *led_data; + struct device *port_dev; + int nr, err; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, "cpld-led"); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_led_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* Test */ + nr = ida_simple_get(&cpld_led_ida, 1, 99, GFP_KERNEL); + if (nr < 0) + goto err_out; + + led_data = kzalloc(sizeof(struct cpld_led_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), led_data, CPLD_LED_ID_FORMAT, nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + // printk("err_status\n"); + } + + data->port_dev = port_dev; + data->cpld_data = led_data; + + dev_info(&client->dev, "Register CPLDLED %d\n", nr); + + sprintf(led_data->name, "LED%d-data", nr); + led_data->cpld_id = nr; + dev_set_drvdata(port_dev, led_data); + port_dev->init_name = led_data->name; + led_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &led_attr_group); + // if (status) printk("err status\n"); + /* end */ + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +err_out: + return nr; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} + +static int cpld_led_remove(struct i2c_client *client) +{ + struct cpld_led_data *data = i2c_get_clientdata(client); + + dev_info(data->port_dev, "Remove CPLDLED-%d\n", data->cpld_data->cpld_id); + device_unregister(data->port_dev); + ida_simple_remove(&cpld_led_ida, data->cpld_data->cpld_id); + kfree(data->cpld_data); + + if (cpld_idr_is_empty(&cpld_led_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_led_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_AUTHOR("Roger Chang "); +MODULE_DESCRIPTION("Quanta Switch LED CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/quanta_platform_ix7.c b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/quanta_platform_ix7.c new file mode 100644 index 000000000000..a6e5733199ac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/modules/quanta_platform_ix7.c @@ -0,0 +1,323 @@ +/* + * Quanta IX7 platform driver + * + * + * Copyright (C) 2014 Quanta Computer inc. + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)) +#include +#else +#include +#endif + +#define MUX_INFO(bus, deselect) \ + {.adap_id = bus, .deselect_on_exit = deselect} + +static struct pca954x_platform_mode pca9548sfp1_modes[] = { + MUX_INFO(0x20, 1), + MUX_INFO(0x21, 1), + MUX_INFO(0x22, 1), + MUX_INFO(0x23, 1), + MUX_INFO(0x24, 1), + MUX_INFO(0x25, 1), + MUX_INFO(0x26, 1), + MUX_INFO(0x27, 1), +}; + +static struct pca954x_platform_data pca9548sfp1_data = { + .modes = pca9548sfp1_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp2_modes[] = { + MUX_INFO(0x28, 1), + MUX_INFO(0x29, 1), + MUX_INFO(0x2a, 1), + MUX_INFO(0x2b, 1), + MUX_INFO(0x2c, 1), + MUX_INFO(0x2d, 1), + MUX_INFO(0x2e, 1), + MUX_INFO(0x2f, 1), +}; + +static struct pca954x_platform_data pca9548sfp2_data = { + .modes = pca9548sfp2_modes, + .num_modes = 8, +}; +static struct pca954x_platform_mode pca9548sfp3_modes[] = { + MUX_INFO(0x30, 1), + MUX_INFO(0x31, 1), + MUX_INFO(0x32, 1), + MUX_INFO(0x33, 1), + MUX_INFO(0x34, 1), + MUX_INFO(0x35, 1), + MUX_INFO(0x36, 1), + MUX_INFO(0x37, 1), +}; + +static struct pca954x_platform_data pca9548sfp3_data = { + .modes = pca9548sfp3_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp4_modes[] = { + MUX_INFO(0x38, 1), + MUX_INFO(0x39, 1), + MUX_INFO(0x3a, 1), + MUX_INFO(0x3b, 1), + MUX_INFO(0x3c, 1), + MUX_INFO(0x3d, 1), + MUX_INFO(0x3e, 1), + MUX_INFO(0x3f, 1), +}; + +static struct pca954x_platform_data pca9548sfp4_data = { + .modes = pca9548sfp4_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9546_modes[] = { + MUX_INFO(0x10, 1), + MUX_INFO(0x11, 1), + MUX_INFO(0x12, 1), + MUX_INFO(0x13, 1), +}; + +static struct pca954x_platform_data pca9546_data = { + .modes = pca9546_modes, + .num_modes = 4, +}; + +static struct pca954x_platform_mode pca9548_modes[] = { + MUX_INFO(0x14, 1), + MUX_INFO(0x15, 1), + MUX_INFO(0x16, 1), + MUX_INFO(0x17, 1), + MUX_INFO(0x18, 1), + MUX_INFO(0x19, 1), + MUX_INFO(0x1a, 1), + MUX_INFO(0x1b, 1), +}; + +static struct pca954x_platform_data pca9548_data = { + .modes = pca9548_modes, + .num_modes = 8, +}; + +/* CPU Board i2c device */ +static struct pca954x_platform_mode pca9546_cpu_modes[] = { + MUX_INFO(0x02, 1), + MUX_INFO(0x03, 1), + MUX_INFO(0x04, 1), + MUX_INFO(0x05, 1), +}; + +static struct pca954x_platform_data pca9546_cpu_data = { + .modes = pca9546_cpu_modes, + .num_modes = 4, +}; +//MB Board Data +static struct pca953x_platform_data pca9555_1_data = { + .gpio_base = 0x10, +}; +//CPU Board pca9555 +static struct pca953x_platform_data pca9555_CPU_data = { + .gpio_base = 0x20, +}; + +static struct i2c_board_info ix7_i2c_devices[] = { + { + I2C_BOARD_INFO("pca9546", 0x72), // 0 + .platform_data = &pca9546_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x77), // 1 + .platform_data = &pca9548_data, + }, + { + I2C_BOARD_INFO("24c02", 0x54), // 2 0x72 ch2 eeprom + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 3 0x77 ch0 + .platform_data = &pca9548sfp1_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 4 0x77 ch1 + .platform_data = &pca9548sfp2_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 5 0x77 ch2 + .platform_data = &pca9548sfp3_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 6 0x77 ch3 + .platform_data = &pca9548sfp4_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x23), // 7 0x72 ch3 pca9555 MB Board Data + .platform_data = &pca9555_1_data, + }, + { + I2C_BOARD_INFO("CPLD-QSFP28", 0x38), // 8 0x72 ch0 + }, + { + I2C_BOARD_INFO("CPLD-QSFP28", 0x38), // 9 0x72 ch1 + }, + { + I2C_BOARD_INFO("pca9546", 0x71), // 10 CPU Board i2c device + .platform_data = &pca9546_cpu_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x20), // 11 0x71 ch0 CPU Board Data + .platform_data = &pca9555_CPU_data, + }, + { + I2C_BOARD_INFO("optoe1", 0x50), // 12 0x50 QSFP EEPROM + }, + { + I2C_BOARD_INFO("CPLDLED_IX7", 0x39), // 13 0x72 ch0 CPLD_led_1 + }, + { + I2C_BOARD_INFO("CPLDLED_IX7", 0x39), // 14 0x72 ch1 CPLD_led_1 + }, +}; + +static struct platform_driver ix7_platform_driver = { + .driver = { + .name = "qci-ix7", + .owner = THIS_MODULE, + }, +}; + +static struct platform_device *ix7_device; + +static int __init ix7_platform_init(void) +{ + struct i2c_client *client; + struct i2c_adapter *adapter; + int ret, i; + + ret = platform_driver_register(&ix7_platform_driver); + if (ret < 0) + return ret; + + /* Register platform stuff */ + ix7_device = platform_device_alloc("qci-ix7", -1); + if (!ix7_device) { + ret = -ENOMEM; + goto fail_platform_driver; + } + + ret = platform_device_add(ix7_device); + if (ret) + goto fail_platform_device; + + adapter = i2c_get_adapter(0); + client = i2c_new_device(adapter, &ix7_i2c_devices[0]); // pca9546 + client = i2c_new_device(adapter, &ix7_i2c_devices[1]); // pca9548 + client = i2c_new_device(adapter, &ix7_i2c_devices[10]); // pca9546 in CPU board + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x02); + client = i2c_new_device(adapter, &ix7_i2c_devices[11]); // CPU Board Data + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x10); + client = i2c_new_device(adapter, &ix7_i2c_devices[8]); // CPLD2 + client = i2c_new_device(adapter, &ix7_i2c_devices[13]); // CPLD_led_1 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x11); + client = i2c_new_device(adapter, &ix7_i2c_devices[9]); // CPLD3 + client = i2c_new_device(adapter, &ix7_i2c_devices[14]); // CPLD_led_2 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x12); + client = i2c_new_device(adapter, &ix7_i2c_devices[2]); // MB_BOARDINFO_EEPROM + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x13); + client = i2c_new_device(adapter, &ix7_i2c_devices[7]); // pca9555 MB Board Data + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x14); + client = i2c_new_device(adapter, &ix7_i2c_devices[3]); // pca9548_1 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x15); + client = i2c_new_device(adapter, &ix7_i2c_devices[4]); // pca9548_2 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x16); + client = i2c_new_device(adapter, &ix7_i2c_devices[5]); // pca9548_3 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x17); + client = i2c_new_device(adapter, &ix7_i2c_devices[6]); // pca9548_4 SFP + i2c_put_adapter(adapter); + for(i = 32; i < 64; i ++){ // QSFP 1~32 EEPROM + adapter = i2c_get_adapter(i); + client = i2c_new_device(adapter, &ix7_i2c_devices[12]); + i2c_put_adapter(adapter); + } + + return 0; + +fail_platform_device: + platform_device_put(ix7_device); + +fail_platform_driver: + platform_driver_unregister(&ix7_platform_driver); + return ret; +} + +static void __exit ix7_platform_exit(void) +{ + platform_device_unregister(ix7_device); + platform_driver_unregister(&ix7_platform_driver); +} + +module_init(ix7_platform_init); +module_exit(ix7_platform_exit); + + +MODULE_AUTHOR("Jonathan Tsai "); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("Quanta IX7 Platform Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/service/ix7-platform-init.service b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/service/ix7-platform-init.service new file mode 100755 index 000000000000..fa46136d17ff --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/service/ix7-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Quanta IX7-32X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/quanta_ix7_util.py install +ExecStop=/usr/local/bin/quanta_ix7_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/setup.py b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/setup.py new file mode 100644 index 000000000000..a2f84b31a56a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='ix7_32x', + version='1.0', + description='Module to initialize Quanta IX7-32X platforms', + + packages=['ix7_32x'], + package_dir={'ix7_32x': 'ix7-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/utils/quanta_ix7_util.py b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/utils/quanta_ix7_util.py new file mode 100644 index 000000000000..e583d2374a99 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix7-32x/utils/quanta_ix7_util.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Quanta Computer Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[IX7-32X]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +"with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +instantiate =[ +#turn on module power +'echo 21 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio21/direction', +'echo 1 >/sys/class/gpio/gpio21/value', +#Reset fron-ports LED CPLD +'echo 73 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio73/direction', +'echo 0 >/sys/class/gpio/gpio73/value', +'echo 1 >/sys/class/gpio/gpio73/value', +#Enable front-ports LED decoding +'echo 1 > /sys/class/cpld-led/CPLDLED-1/led_decode', +'echo 1 > /sys/class/cpld-led/CPLDLED-2/led_decode', +#Update System LED +'echo 42 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio42/direction', +'echo 0 > /sys/class/gpio/gpio42/value', +'echo 43 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio43/direction', +'echo 1 > /sys/class/gpio/gpio43/value', +] + +drivers =[ +'lpc_ich', +'i2c-i801', +'i2c-dev', +'i2c-mux-pca954x', +'gpio-pca953x', +'optoe', +'qci_cpld', +'qci_cpld_led', +'quanta_platform_ix7', +'ipmi_devintf' +] + + + +def system_install(): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("echo 'blacklist i2c-ismt' > /etc/modprobe.d/blacklist.conf", 1) + time.sleep(1) + status, output = exec_cmd("modprobe -r i2c-ismt ", 1) + status, output = exec_cmd("modprobe -r i2c-i801 ", 1) + #setup driver dependency + status, output = exec_cmd("depmod -a ", 1) + #install drivers + for i in range(0,len(drivers)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #instantiate devices + for i in range(0,len(instantiate)): + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + + #QSFP for 1~32 port + for port_number in range(1,33): + bus_number = port_number + 31 + os.system("echo %d >/sys/bus/i2c/devices/%d-0050/port_name" % (port_number, bus_number)) + return + + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print " ix7 driver already installed...." + return + +def uninstall(): + global FORCE + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"i2c-0", 0) + return ret1 + +if __name__ == "__main__": + main() + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/Makefile b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/Makefile new file mode 100755 index 000000000000..011cd52d673d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m:=qci_cpld_sfp28.o qci_cpld_led.o qci_platform_ix8.o + + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/qci_cpld_led.c b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/qci_cpld_led.c new file mode 100755 index 000000000000..37fc2e07246e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/qci_cpld_led.c @@ -0,0 +1,275 @@ +/* + * A LED CPLD driver for Quanta Switch Platform + * + * The CPLD is customize by Quanta for decode led bit stream, + * This driver modify from Quanta CPLD I/O driver. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * Author: Roger Chang + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_led_ida); + +enum platform_type { + IX7 = 0, + IX8, + NONE +}; + +static struct class *cpld_class = NULL; + +struct cpld_data { + struct i2c_client *cpld_client; + char name[8]; + u8 cpld_id; +}; + +struct cpld_led_data { + struct mutex lock; + struct device *port_dev; + struct cpld_data *cpld_data; +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_led_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_led_id[] = { + { "CPLDLED_IX7", IX7 }, + { "CPLDLED_IX8", IX8 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_led_id); + +static struct i2c_driver cpld_led_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_led", + }, + .probe = cpld_led_probe, + .remove = cpld_led_remove, + .id_table = cpld_led_id, +// .address_list = normal_i2c, +}; + +#define CPLD_LED_ID_PREFIX "CPLDLED-" +#define CPLD_LED_ID_FORMAT CPLD_LED_ID_PREFIX "%d" + +#define CPLD_DECODER_OFFSET 0x4 +#define CPLD_DECODER_MASK 0x1 +#define CPLD_USERCODE_START_OFFSET 0x0 + +static ssize_t get_led_decode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 offset = (u8)(CPLD_DECODER_OFFSET); + s32 value; + + value = i2c_smbus_read_byte_data(client, offset); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value &= CPLD_DECODER_MASK; + + return sprintf(buf, "%d\n", (value == 0) ? 1 : 0); +} + +static ssize_t get_usercode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 i = 0; + s32 value = 0, reading = 0; + + for (i = 0; i < 4; i++) + { + reading = i2c_smbus_read_byte_data(client, CPLD_USERCODE_START_OFFSET + i); + if (reading < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led usercode reg %d value= %x\n", i, reading); + + value |= reading << (24 - 8 * i); + } + + return sprintf(buf, "%X\n", value); +} + +static ssize_t set_led_decode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + s32 value; + long enable; + + if (kstrtol(buf, 0, &enable)) + return -EINVAL; + + if ((enable != 1) && (enable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_byte_data(client, CPLD_DECODER_OFFSET); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value |= CPLD_DECODER_MASK; + if (enable) + value &= ~CPLD_DECODER_MASK; + + dev_dbg(&client->dev, "write led decode value= %x\n", value); + + i2c_smbus_write_byte_data(client, CPLD_DECODER_OFFSET, (u8)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(led_decode, S_IWUSR | S_IRUGO, get_led_decode, set_led_decode); +static DEVICE_ATTR(usercode, S_IRUGO, get_usercode, NULL); + +static const struct attribute *led_attrs[] = { + &dev_attr_usercode.attr, + &dev_attr_led_decode.attr, + NULL, +}; + +static const struct attribute_group led_attr_group = { + .attrs = (struct attribute **) led_attrs, +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_led_data *data; + struct cpld_data *led_data; + struct device *port_dev; + int nr, err; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, "cpld-led"); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_led_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* Test */ + nr = ida_simple_get(&cpld_led_ida, 1, 99, GFP_KERNEL); + if (nr < 0) + goto err_out; + + led_data = kzalloc(sizeof(struct cpld_led_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), led_data, CPLD_LED_ID_FORMAT, nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + // printk("err_status\n"); + } + + data->port_dev = port_dev; + data->cpld_data = led_data; + + dev_info(&client->dev, "Register CPLDLED %d\n", nr); + + sprintf(led_data->name, "LED%d-data", nr); + led_data->cpld_id = nr; + dev_set_drvdata(port_dev, led_data); + port_dev->init_name = led_data->name; + led_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &led_attr_group); + // if (status) printk("err status\n"); + /* end */ + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +err_out: + return nr; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} + +static int cpld_led_remove(struct i2c_client *client) +{ + struct cpld_led_data *data = i2c_get_clientdata(client); + + dev_info(data->port_dev, "Remove CPLDLED-%d\n", data->cpld_data->cpld_id); + device_unregister(data->port_dev); + ida_simple_remove(&cpld_led_ida, data->cpld_data->cpld_id); + kfree(data->cpld_data); + + if (cpld_idr_is_empty(&cpld_led_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_led_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_AUTHOR("Roger Chang "); +MODULE_DESCRIPTION("Quanta Switch LED CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/qci_cpld_sfp28.c b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/qci_cpld_sfp28.c new file mode 100755 index 000000000000..dac76667c6ca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/qci_cpld_sfp28.c @@ -0,0 +1,398 @@ +/* + * A CPLD driver for monitor SFP28 module I/O + * + * The CPLD is customize by Quanta for controlling SFP28 module signals, + * they are TX_FAULT , TX_DIS , PRE_N , RX_LOS + * Each CPLD control 16 modules, each module use 4 bits in register. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_ida); + +enum platform_type { + SFP = 0, + SFP28, + NONE +}; + +static struct class *cpld_class = NULL; + +struct sfp_data { + struct i2c_client *cpld_client; + char name[8]; + char type[8]; + u8 port_id; + u8 cpld_port; +}; + +struct cpld_data { + struct mutex lock; + struct device *port_dev[16]; + struct sfp_data *port_data[16]; +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_id[] = { + { "CPLD-SFP", SFP }, + { "CPLD-SFP28", SFP28 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_sfp28", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +// .address_list = normal_i2c, +}; + +#define CPLD_ID_PREFIX "port-" +#define CPLD_ID_FORMAT CPLD_ID_PREFIX "%d" + +//SFP28 +#define TX_FAULT_MASK 0x08 +#define TX_DIS_MASK 0x04 +#define PRE_N_MASK 0x02 +#define RX_LOS_MASK 0x01 + +static inline u8 get_group_cmd(u8 group) +{ + //FIXME: if group cmd change + return (group + 1); +} + +static inline u8 port_remapping(u8 phy_port) +{ + /* FIXME: implement by hardware design */ + /* The CPLD register port mapping is weird : + * MSB -------- LSB (word data) + * P3 P4 P1 P2 (per port 4 bits) + * For easy coding bit shift, we treat it as hw port swap + */ + return (phy_port % 2) ? (phy_port - 1) : (phy_port + 1); +} + +//SFP +static ssize_t get_tx_fault(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= TX_FAULT_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_tx_dis(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= TX_DIS_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_pre_n(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= PRE_N_MASK; + + //FIXME: if present is not low active + return sprintf(buf, "%d\n", value ? 0 : 1); +} + +static ssize_t get_rx_los(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= RX_LOS_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} +static ssize_t set_tx_dis(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(TX_DIS_MASK << (group_port * 4)); + if (disable) + value |= (TX_DIS_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} +//SFP + +//static DEVICE_ATTR(led_enable, S_IWUSR | S_IRUGO, get_led_enable, set_led_enable); +//static DEVICE_ATTR(monitor_enable, S_IWUSR | S_IRUGO, get_monitor_enable, set_monitor_enable); +//SFP +static DEVICE_ATTR(tx_fault, S_IRUGO, get_tx_fault, NULL); +static DEVICE_ATTR(tx_dis, S_IWUSR | S_IRUGO, get_tx_dis, set_tx_dis); +static DEVICE_ATTR(pre_n, S_IRUGO, get_pre_n, NULL); +static DEVICE_ATTR(rx_los, S_IRUGO, get_rx_los, NULL); + +static const struct attribute *sfp_attrs[] = { +// &dev_attr_led_enable.attr, + &dev_attr_tx_fault.attr, + &dev_attr_tx_dis.attr, + &dev_attr_pre_n.attr, + &dev_attr_rx_los.attr, + NULL, +}; + +static const struct attribute_group sfp_attr_group = { + .attrs = (struct attribute **) sfp_attrs, +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_data *data; + struct sfp_data *port_data; +// struct i2c_monitor_data *monitor_data; + struct device *port_dev; +// struct device *i2c_dev; + int port_nr, i=0, err; + char name[I2C_NAME_SIZE], type[I2C_NAME_SIZE]; + + printk("cpld cpld_probe\n"); + + while(id->name[i]) + { + name[i]=tolower(id->name[i]); + i++; + } + name[i]='\0'; + strncpy(type,name+5,strlen(name)-5); + type[strlen(name)-5]='\0'; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, name); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* register sfp port data to sysfs */ + for (i = 0; i < 16; i++) + { + port_nr = ida_simple_get(&cpld_ida, 1, 99, GFP_KERNEL); + if (port_nr < 0) + goto err_out; + + port_data = kzalloc(sizeof(struct sfp_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), port_data, CPLD_ID_FORMAT, port_nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + printk("err_status\n"); + } + + data->port_dev[i] = port_dev; + data->port_data[i] = port_data; + + strcpy(port_data->type, type); + + dev_info(&client->dev, "Register %s port-%d\n", port_data->type , port_nr); + + /* FIXME: implement Logical/Physical port remapping */ + //port_data->cpld_port = i; + port_data->cpld_port = port_remapping(i); + sprintf(port_data->name, "port-%d", port_nr); + port_data->port_id = port_nr; + dev_set_drvdata(port_dev, port_data); + port_dev->init_name = port_data->name; + port_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &sfp_attr_group); + // if (status) printk("err status\n"); + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +err_out: + return port_nr; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +#if 1 +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} +#endif + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + int i; +// int id; + + for (i = 15; i >= 0; i--) + { + dev_info(data->port_dev[i], "Remove %s port-%d\n", data->port_data[i]->type , data->port_data[i]->port_id); + device_unregister(data->port_dev[i]); + ida_simple_remove(&cpld_ida, data->port_data[i]->port_id); + kfree(data->port_data[i]); + } + + if (cpld_idr_is_empty(&cpld_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("Jonathan Tsai "); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("Quanta Switch SFP28 CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/qci_platform_ix8.c b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/qci_platform_ix8.c new file mode 100755 index 000000000000..d35a56641e38 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/modules/qci_platform_ix8.c @@ -0,0 +1,420 @@ +/* + * Quanta IX8 platform driver + * + * + * Copyright (C) 2017 Quanta Computer inc. + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)) +#include +#else +#include +#endif + +#define MUX_INFO(bus, deselect) \ + {.adap_id = bus, .deselect_on_exit = deselect} + +static struct pca954x_platform_mode pca9548sfp1_modes[] = { + MUX_INFO(0x20, 1), + MUX_INFO(0x21, 1), + MUX_INFO(0x22, 1), + MUX_INFO(0x23, 1), + MUX_INFO(0x24, 1), + MUX_INFO(0x25, 1), + MUX_INFO(0x26, 1), + MUX_INFO(0x27, 1), +}; + +static struct pca954x_platform_data pca9548sfp1_data = { + .modes = pca9548sfp1_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp2_modes[] = { + MUX_INFO(0x28, 1), + MUX_INFO(0x29, 1), + MUX_INFO(0x2a, 1), + MUX_INFO(0x2b, 1), + MUX_INFO(0x2c, 1), + MUX_INFO(0x2d, 1), + MUX_INFO(0x2e, 1), + MUX_INFO(0x2f, 1), +}; + +static struct pca954x_platform_data pca9548sfp2_data = { + .modes = pca9548sfp2_modes, + .num_modes = 8, +}; +static struct pca954x_platform_mode pca9548sfp3_modes[] = { + MUX_INFO(0x30, 1), + MUX_INFO(0x31, 1), + MUX_INFO(0x32, 1), + MUX_INFO(0x33, 1), + MUX_INFO(0x34, 1), + MUX_INFO(0x35, 1), + MUX_INFO(0x36, 1), + MUX_INFO(0x37, 1), +}; + +static struct pca954x_platform_data pca9548sfp3_data = { + .modes = pca9548sfp3_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp4_modes[] = { + MUX_INFO(0x38, 1), + MUX_INFO(0x39, 1), + MUX_INFO(0x3a, 1), + MUX_INFO(0x3b, 1), + MUX_INFO(0x3c, 1), + MUX_INFO(0x3d, 1), + MUX_INFO(0x3e, 1), + MUX_INFO(0x3f, 1), +}; + +static struct pca954x_platform_data pca9548sfp4_data = { + .modes = pca9548sfp4_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp5_modes[] = { + MUX_INFO(0x40, 1), + MUX_INFO(0x41, 1), + MUX_INFO(0x42, 1), + MUX_INFO(0x43, 1), + MUX_INFO(0x44, 1), + MUX_INFO(0x45, 1), + MUX_INFO(0x46, 1), + MUX_INFO(0x47, 1), +}; + +static struct pca954x_platform_data pca9548sfp5_data = { + .modes = pca9548sfp5_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp6_modes[] = { + MUX_INFO(0x48, 1), + MUX_INFO(0x49, 1), + MUX_INFO(0x4a, 1), + MUX_INFO(0x4b, 1), + MUX_INFO(0x4c, 1), + MUX_INFO(0x4d, 1), + MUX_INFO(0x4e, 1), + MUX_INFO(0x4f, 1), +}; + +static struct pca954x_platform_data pca9548sfp6_data = { + .modes = pca9548sfp6_modes, + .num_modes = 8, +}; + +//ZQSFP +static struct pca954x_platform_mode pca9548sfp7_modes[] = { + MUX_INFO(0x50, 1), + MUX_INFO(0x51, 1), + MUX_INFO(0x52, 1), + MUX_INFO(0x53, 1), + MUX_INFO(0x54, 1), + MUX_INFO(0x55, 1), + MUX_INFO(0x56, 1), + MUX_INFO(0x57, 1), +}; + +static struct pca954x_platform_data pca9548sfp7_data = { + .modes = pca9548sfp7_modes, + .num_modes = 8, +}; + +// end port + +static struct pca954x_platform_mode pca9546_modes[] = { + MUX_INFO(0x10, 1), + MUX_INFO(0x11, 1), + MUX_INFO(0x12, 1), + MUX_INFO(0x13, 1), +}; + +static struct pca954x_platform_data pca9546_data = { + .modes = pca9546_modes, + .num_modes = 4, +}; + +static struct pca954x_platform_mode pca9548_modes[] = { + MUX_INFO(0x14, 1), + MUX_INFO(0x15, 1), + MUX_INFO(0x16, 1), + MUX_INFO(0x17, 1), + MUX_INFO(0x18, 1), + MUX_INFO(0x19, 1), + MUX_INFO(0x1a, 1), + MUX_INFO(0x1b, 1), +}; + +static struct pca954x_platform_data pca9548_data = { + .modes = pca9548_modes, + .num_modes = 8, +}; + +/* CPU Board i2c device */ +static struct pca954x_platform_mode pca9546_cpu_modes[] = { + MUX_INFO(0x02, 1), + MUX_INFO(0x03, 1), + MUX_INFO(0x04, 1), + MUX_INFO(0x05, 1), +}; + +static struct pca954x_platform_data pca9546_cpu_data = { + .modes = pca9546_cpu_modes, + .num_modes = 4, +}; +//MB Board Data +static struct pca953x_platform_data pca9555_1_data = { + .gpio_base = 0x10, +}; +//QSFP28 49-56 IO Expander +static struct pca953x_platform_data pca9698_2_data = { + .gpio_base = 0x20, +}; +//CPU Board pca9555 +static struct pca953x_platform_data pca9555_CPU_data = { + .gpio_base = 0x48, +}; +static struct i2c_board_info ix8_i2c_devices[] = { + { + I2C_BOARD_INFO("pca9546", 0x72), // 0 + .platform_data = &pca9546_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x77), // 1 + .platform_data = &pca9548_data, + }, + { + I2C_BOARD_INFO("24c02", 0x54), // 2 eeprom + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 3 0x77 ch0 + .platform_data = &pca9548sfp1_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 4 0x77 ch1 + .platform_data = &pca9548sfp2_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 5 0x77 ch2 + .platform_data = &pca9548sfp3_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 6 0x77 ch3 + .platform_data = &pca9548sfp4_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 7 0x77 ch4 + .platform_data = &pca9548sfp5_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 8 0x77 ch5 + .platform_data = &pca9548sfp6_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 9 0x77 ch6 + .platform_data = &pca9548sfp7_data, + }, + { + I2C_BOARD_INFO("CPLD-SFP28", 0x38), // 10 0x72 ch0 CPLD1_:SFP28 1~16 + }, + { + I2C_BOARD_INFO("CPLD-SFP28", 0x38), // 11 0x72 ch1 CPLD2_:SFP28 17~32 + }, + { + I2C_BOARD_INFO("CPLD-SFP28", 0x38), // 12 0x72 ch2 CPLD_3:SFP28 33~48 + }, + { + I2C_BOARD_INFO("pca9555", 0x23), // 13 0x72 ch3 MB Board Data + .platform_data = &pca9555_1_data, + }, + { + I2C_BOARD_INFO("pca9698", 0x21), // 14 0x72 ch3 QSFP:49~52 + .platform_data = &pca9698_2_data, + }, + { + I2C_BOARD_INFO("optoe1", 0x50), // 15 0x50 QSFP EEPROM + }, + { + I2C_BOARD_INFO("pca9546", 0x71), // 16 + .platform_data = &pca9546_cpu_data, + }, + { + I2C_BOARD_INFO("pca9555", 0x20), // 17 0x71 ch0 CPU Board Data + .platform_data = &pca9555_CPU_data, + }, + { + I2C_BOARD_INFO("CPLDLED_IX8", 0x3a), // 18 0x72 ch0 CPLD4 LED function of SFP28 & QSFP28 (Port27~56) + }, + { + I2C_BOARD_INFO("CPLDLED_IX8", 0x39), // 19 0x72 ch0 CPLD6 LED function of SFP28 & QSFP28 (Port1~26) + }, + { + I2C_BOARD_INFO("optoe2", 0x50), // 20 0x50 SFP28 EEPROM + }, +}; + +static struct platform_driver ix8_platform_driver = { + .driver = { + .name = "qci-ix8", + .owner = THIS_MODULE, + }, +}; + +static struct platform_device *ix8_device; + +static int __init ix8_platform_init(void) +{ + struct i2c_client *client; + struct i2c_adapter *adapter; + int ret, i; + + ret = platform_driver_register(&ix8_platform_driver); + if (ret < 0) + return ret; + + /* Register platform stuff */ + ix8_device = platform_device_alloc("qci-ix8", -1); + if (!ix8_device) { + ret = -ENOMEM; + goto fail_platform_driver; + } + + ret = platform_device_add(ix8_device); + if (ret) + goto fail_platform_device; + + adapter = i2c_get_adapter(0); + client = i2c_new_device(adapter, &ix8_i2c_devices[0]); // pca9546 + client = i2c_new_device(adapter, &ix8_i2c_devices[1]); // pca9548 + client = i2c_new_device(adapter, &ix8_i2c_devices[16]); // pca9546cpu + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x02); + client = i2c_new_device(adapter, &ix8_i2c_devices[17]); // CPU Board Data + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x10); + client = i2c_new_device(adapter, &ix8_i2c_devices[10]); // CPLD_1 + client = i2c_new_device(adapter, &ix8_i2c_devices[18]); // CPLD_4 + client = i2c_new_device(adapter, &ix8_i2c_devices[19]); // CPLD_6 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x11); + client = i2c_new_device(adapter, &ix8_i2c_devices[11]); // CPLD_2 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x12); + client = i2c_new_device(adapter, &ix8_i2c_devices[12]); // CPLD_3 + client = i2c_new_device(adapter, &ix8_i2c_devices[2]); // MB_BOARDINFO_EEPROM + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x13); + client = i2c_new_device(adapter, &ix8_i2c_devices[13]); // MB Board Data + client = i2c_new_device(adapter, &ix8_i2c_devices[14]); // QSFP:49~52 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x14); + client = i2c_new_device(adapter, &ix8_i2c_devices[3]); // pca9548_1 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x15); + client = i2c_new_device(adapter, &ix8_i2c_devices[4]); // pca9548_2 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x16); + client = i2c_new_device(adapter, &ix8_i2c_devices[5]); // pca9548_3 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x17); + client = i2c_new_device(adapter, &ix8_i2c_devices[6]); // pca9548_4 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x18); + client = i2c_new_device(adapter, &ix8_i2c_devices[7]); // pca9548_5 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x19); + client = i2c_new_device(adapter, &ix8_i2c_devices[8]); // pca9548_6 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x1a); + client = i2c_new_device(adapter, &ix8_i2c_devices[9]); // pca9548_7 QSFP + i2c_put_adapter(adapter); + + for(i = 80; i < 88; i ++){ // QSFP 49~56 EEPROM + adapter = i2c_get_adapter(i); + client = i2c_new_device(adapter, &ix8_i2c_devices[15]); + i2c_put_adapter(adapter); + } + + for(i = 32; i < 80; i ++){ // SFP28 1~48 EEPROM + adapter = i2c_get_adapter(i); + client = i2c_new_device(adapter, &ix8_i2c_devices[20]); + i2c_put_adapter(adapter); + } + + return 0; + +fail_platform_device: + platform_device_put(ix8_device); + +fail_platform_driver: + platform_driver_unregister(&ix8_platform_driver); + return ret; +} + +static void __exit ix8_platform_exit(void) +{ + platform_device_unregister(ix8_device); + platform_driver_unregister(&ix8_platform_driver); +} + +module_init(ix8_platform_init); +module_exit(ix8_platform_exit); + + +MODULE_AUTHOR("Jonathan Tsai "); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("Quanta IX8 Platform Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/service/ix8-platform-init.service b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/service/ix8-platform-init.service new file mode 100755 index 000000000000..d4eb6bfcc3e1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/service/ix8-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Quanta IX8-56X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/quanta_ix8_util.py install +ExecStop=/usr/local/bin/quanta_ix8_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/setup.py b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/setup.py new file mode 100755 index 000000000000..76c5eacbee4c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='ix8_56x', + version='1.0', + description='Module to initialize Quanta IX8-56X platforms', + + packages=['ix8_56x'], + package_dir={'ix8_56x': 'ix8-56x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/utils/quanta_ix8_util.py b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/utils/quanta_ix8_util.py new file mode 100755 index 000000000000..fe93611b114c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8-56x/utils/quanta_ix8_util.py @@ -0,0 +1,329 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Quanta Computer Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[IX8-56X]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +"with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +instantiate =[ +#turn on module power +'echo 21 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio21/direction', +'echo 1 >/sys/class/gpio/gpio21/value', +#export pca9698 for qsfp present +'echo 34 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio34/direction', +'echo 38 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio38/direction', +'echo 42 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio42/direction', +'echo 46 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio46/direction', +'echo 50 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio50/direction', +'echo 54 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio54/direction', +'echo 58 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio58/direction', +'echo 62 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio62/direction', +#export pca9698 for qsfp reset +'echo 32 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio32/direction', +'echo 1 >/sys/class/gpio/gpio32/value', +'echo 36 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio36/direction', +'echo 1 >/sys/class/gpio/gpio36/value', +'echo 40 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio40/direction', +'echo 1 >/sys/class/gpio/gpio40/value', +'echo 44 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio44/direction', +'echo 1 >/sys/class/gpio/gpio44/value', +'echo 48 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio48/direction', +'echo 1 >/sys/class/gpio/gpio48/value', +'echo 52 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio52/direction', +'echo 1 >/sys/class/gpio/gpio52/value', +'echo 56 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio56/direction', +'echo 1 >/sys/class/gpio/gpio56/value', +'echo 60 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio60/direction', +'echo 1 >/sys/class/gpio/gpio60/value', +#export pca9698 for qsfp lpmode +'echo 35 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio35/direction', +'echo 0 >/sys/class/gpio/gpio35/value', +'echo 39 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio39/direction', +'echo 0 >/sys/class/gpio/gpio39/value', +'echo 43 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio43/direction', +'echo 0 >/sys/class/gpio/gpio43/value', +'echo 47 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio47/direction', +'echo 0 >/sys/class/gpio/gpio47/value', +'echo 51 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio51/direction', +'echo 0 >/sys/class/gpio/gpio51/value', +'echo 55 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio55/direction', +'echo 0 >/sys/class/gpio/gpio55/value', +'echo 59 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio59/direction', +'echo 0 >/sys/class/gpio/gpio59/value', +'echo 63 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio63/direction', +'echo 0 >/sys/class/gpio/gpio63/value', +#Reset fron-ports LED CPLD +'echo 73 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio73/direction', +'echo 0 >/sys/class/gpio/gpio73/value', +'echo 1 >/sys/class/gpio/gpio73/value', +#Enable front-ports LED decoding +'echo 1 > /sys/class/cpld-led/CPLDLED-1/led_decode', +'echo 1 > /sys/class/cpld-led/CPLDLED-2/led_decode', +#SFP28 Module TxEnable +'echo 0 > /sys/class/cpld-sfp28/port-1/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-2/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-3/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-4/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-5/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-6/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-7/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-8/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-9/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-10/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-11/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-12/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-13/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-14/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-15/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-16/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-17/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-18/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-19/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-20/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-21/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-22/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-23/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-24/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-25/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-26/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-27/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-28/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-29/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-30/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-31/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-32/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-33/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-34/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-35/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-36/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-37/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-38/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-39/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-40/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-41/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-42/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-43/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-44/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-45/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-46/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-47/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-48/tx_dis', +#Update System LED +'echo 82 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio82/direction', +'echo 0 > /sys/class/gpio/gpio82/value', +'echo 83 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio83/direction', +'echo 1 > /sys/class/gpio/gpio83/value', +] + +drivers =[ +'lpc_ich', +'i2c-i801', +'i2c-dev', +'i2c-mux-pca954x', +'gpio-pca953x', +'optoe', +'qci_cpld_sfp28', +'qci_cpld_led', +'qci_platform_ix8', +'ipmi_devintf' +] + + + +def system_install(): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("echo 'blacklist i2c-ismt' > /etc/modprobe.d/blacklist.conf", 1) + time.sleep(1) + status, output = exec_cmd("modprobe -r i2c-ismt ", 1) + status, output = exec_cmd("modprobe -r i2c-i801 ", 1) + #setup driver dependency + status, output = exec_cmd("depmod -a ", 1) + #install drivers + for i in range(0,len(drivers)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #instantiate devices + for i in range(0,len(instantiate)): + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + + #QSFP for 1~56 port + for port_number in range(1,57): + bus_number = port_number + 31 + os.system("echo %d >/sys/bus/i2c/devices/%d-0050/port_name" % (port_number, bus_number)) + + return + + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print " ix8 driver already installed...." + return + +def uninstall(): + global FORCE + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"i2c-0", 0) + return ret1 + +if __name__ == "__main__": + main() + + + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/Makefile b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/Makefile new file mode 100644 index 000000000000..bfb8ec0c458f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m:=qci_cpld_sfp28.o qci_cpld_led.o qci_platform_ix8c.o + + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/qci_cpld_led.c b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/qci_cpld_led.c new file mode 100644 index 000000000000..229195249b5f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/qci_cpld_led.c @@ -0,0 +1,275 @@ +/* + * A LED CPLD driver for Quanta Switch Platform + * + * The CPLD is customize by Quanta for decode led bit stream, + * This driver modify from Quanta CPLD I/O driver. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * Author: Roger Chang + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_led_ida); + +enum platform_type { + IX7 = 0, + IX8C, + NONE +}; + +static struct class *cpld_class = NULL; + +struct cpld_data { + struct i2c_client *cpld_client; + char name[8]; + u8 cpld_id; +}; + +struct cpld_led_data { + struct mutex lock; + struct device *port_dev; + struct cpld_data *cpld_data; +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_led_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_led_id[] = { + { "CPLDLED_IX7", IX7 }, + { "CPLDLED_IX8C", IX8C }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_led_id); + +static struct i2c_driver cpld_led_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_led", + }, + .probe = cpld_led_probe, + .remove = cpld_led_remove, + .id_table = cpld_led_id, +// .address_list = normal_i2c, +}; + +#define CPLD_LED_ID_PREFIX "CPLDLED-" +#define CPLD_LED_ID_FORMAT CPLD_LED_ID_PREFIX "%d" + +#define CPLD_DECODER_OFFSET 0x4 +#define CPLD_DECODER_MASK 0x1 +#define CPLD_USERCODE_START_OFFSET 0x0 + +static ssize_t get_led_decode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 offset = (u8)(CPLD_DECODER_OFFSET); + s32 value; + + value = i2c_smbus_read_byte_data(client, offset); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value &= CPLD_DECODER_MASK; + + return sprintf(buf, "%d\n", (value == 0) ? 1 : 0); +} + +static ssize_t get_usercode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 i = 0; + s32 value = 0, reading = 0; + + for (i = 0; i < 4; i++) + { + reading = i2c_smbus_read_byte_data(client, CPLD_USERCODE_START_OFFSET + i); + if (reading < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led usercode reg %d value= %x\n", i, reading); + + value |= reading << (24 - 8 * i); + } + + return sprintf(buf, "%X\n", value); +} + +static ssize_t set_led_decode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + s32 value; + long enable; + + if (kstrtol(buf, 0, &enable)) + return -EINVAL; + + if ((enable != 1) && (enable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_byte_data(client, CPLD_DECODER_OFFSET); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value |= CPLD_DECODER_MASK; + if (enable) + value &= ~CPLD_DECODER_MASK; + + dev_dbg(&client->dev, "write led decode value= %x\n", value); + + i2c_smbus_write_byte_data(client, CPLD_DECODER_OFFSET, (u8)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(led_decode, S_IWUSR | S_IRUGO, get_led_decode, set_led_decode); +static DEVICE_ATTR(usercode, S_IRUGO, get_usercode, NULL); + +static const struct attribute *led_attrs[] = { + &dev_attr_usercode.attr, + &dev_attr_led_decode.attr, + NULL, +}; + +static const struct attribute_group led_attr_group = { + .attrs = (struct attribute **) led_attrs, +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_led_data *data; + struct cpld_data *led_data; + struct device *port_dev; + int nr, err; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, "cpld-led"); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_led_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* Test */ + nr = ida_simple_get(&cpld_led_ida, 1, 99, GFP_KERNEL); + if (nr < 0) + goto err_out; + + led_data = kzalloc(sizeof(struct cpld_led_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), led_data, CPLD_LED_ID_FORMAT, nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + // printk("err_status\n"); + } + + data->port_dev = port_dev; + data->cpld_data = led_data; + + dev_info(&client->dev, "Register CPLDLED %d\n", nr); + + sprintf(led_data->name, "LED%d-data", nr); + led_data->cpld_id = nr; + dev_set_drvdata(port_dev, led_data); + port_dev->init_name = led_data->name; + led_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &led_attr_group); + // if (status) printk("err status\n"); + /* end */ + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +err_out: + return nr; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} + +static int cpld_led_remove(struct i2c_client *client) +{ + struct cpld_led_data *data = i2c_get_clientdata(client); + + dev_info(data->port_dev, "Remove CPLDLED-%d\n", data->cpld_data->cpld_id); + device_unregister(data->port_dev); + ida_simple_remove(&cpld_led_ida, data->cpld_data->cpld_id); + kfree(data->cpld_data); + + if (cpld_idr_is_empty(&cpld_led_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_led_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_AUTHOR("Roger Chang "); +MODULE_DESCRIPTION("Quanta Switch LED CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/qci_cpld_sfp28.c b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/qci_cpld_sfp28.c new file mode 100644 index 000000000000..dac76667c6ca --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/qci_cpld_sfp28.c @@ -0,0 +1,398 @@ +/* + * A CPLD driver for monitor SFP28 module I/O + * + * The CPLD is customize by Quanta for controlling SFP28 module signals, + * they are TX_FAULT , TX_DIS , PRE_N , RX_LOS + * Each CPLD control 16 modules, each module use 4 bits in register. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_ida); + +enum platform_type { + SFP = 0, + SFP28, + NONE +}; + +static struct class *cpld_class = NULL; + +struct sfp_data { + struct i2c_client *cpld_client; + char name[8]; + char type[8]; + u8 port_id; + u8 cpld_port; +}; + +struct cpld_data { + struct mutex lock; + struct device *port_dev[16]; + struct sfp_data *port_data[16]; +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_id[] = { + { "CPLD-SFP", SFP }, + { "CPLD-SFP28", SFP28 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_sfp28", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +// .address_list = normal_i2c, +}; + +#define CPLD_ID_PREFIX "port-" +#define CPLD_ID_FORMAT CPLD_ID_PREFIX "%d" + +//SFP28 +#define TX_FAULT_MASK 0x08 +#define TX_DIS_MASK 0x04 +#define PRE_N_MASK 0x02 +#define RX_LOS_MASK 0x01 + +static inline u8 get_group_cmd(u8 group) +{ + //FIXME: if group cmd change + return (group + 1); +} + +static inline u8 port_remapping(u8 phy_port) +{ + /* FIXME: implement by hardware design */ + /* The CPLD register port mapping is weird : + * MSB -------- LSB (word data) + * P3 P4 P1 P2 (per port 4 bits) + * For easy coding bit shift, we treat it as hw port swap + */ + return (phy_port % 2) ? (phy_port - 1) : (phy_port + 1); +} + +//SFP +static ssize_t get_tx_fault(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= TX_FAULT_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_tx_dis(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= TX_DIS_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_pre_n(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= PRE_N_MASK; + + //FIXME: if present is not low active + return sprintf(buf, "%d\n", value ? 0 : 1); +} + +static ssize_t get_rx_los(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= RX_LOS_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} +static ssize_t set_tx_dis(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(TX_DIS_MASK << (group_port * 4)); + if (disable) + value |= (TX_DIS_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} +//SFP + +//static DEVICE_ATTR(led_enable, S_IWUSR | S_IRUGO, get_led_enable, set_led_enable); +//static DEVICE_ATTR(monitor_enable, S_IWUSR | S_IRUGO, get_monitor_enable, set_monitor_enable); +//SFP +static DEVICE_ATTR(tx_fault, S_IRUGO, get_tx_fault, NULL); +static DEVICE_ATTR(tx_dis, S_IWUSR | S_IRUGO, get_tx_dis, set_tx_dis); +static DEVICE_ATTR(pre_n, S_IRUGO, get_pre_n, NULL); +static DEVICE_ATTR(rx_los, S_IRUGO, get_rx_los, NULL); + +static const struct attribute *sfp_attrs[] = { +// &dev_attr_led_enable.attr, + &dev_attr_tx_fault.attr, + &dev_attr_tx_dis.attr, + &dev_attr_pre_n.attr, + &dev_attr_rx_los.attr, + NULL, +}; + +static const struct attribute_group sfp_attr_group = { + .attrs = (struct attribute **) sfp_attrs, +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_data *data; + struct sfp_data *port_data; +// struct i2c_monitor_data *monitor_data; + struct device *port_dev; +// struct device *i2c_dev; + int port_nr, i=0, err; + char name[I2C_NAME_SIZE], type[I2C_NAME_SIZE]; + + printk("cpld cpld_probe\n"); + + while(id->name[i]) + { + name[i]=tolower(id->name[i]); + i++; + } + name[i]='\0'; + strncpy(type,name+5,strlen(name)-5); + type[strlen(name)-5]='\0'; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, name); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* register sfp port data to sysfs */ + for (i = 0; i < 16; i++) + { + port_nr = ida_simple_get(&cpld_ida, 1, 99, GFP_KERNEL); + if (port_nr < 0) + goto err_out; + + port_data = kzalloc(sizeof(struct sfp_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), port_data, CPLD_ID_FORMAT, port_nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + printk("err_status\n"); + } + + data->port_dev[i] = port_dev; + data->port_data[i] = port_data; + + strcpy(port_data->type, type); + + dev_info(&client->dev, "Register %s port-%d\n", port_data->type , port_nr); + + /* FIXME: implement Logical/Physical port remapping */ + //port_data->cpld_port = i; + port_data->cpld_port = port_remapping(i); + sprintf(port_data->name, "port-%d", port_nr); + port_data->port_id = port_nr; + dev_set_drvdata(port_dev, port_data); + port_dev->init_name = port_data->name; + port_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &sfp_attr_group); + // if (status) printk("err status\n"); + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +err_out: + return port_nr; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +#if 1 +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} +#endif + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + int i; +// int id; + + for (i = 15; i >= 0; i--) + { + dev_info(data->port_dev[i], "Remove %s port-%d\n", data->port_data[i]->type , data->port_data[i]->port_id); + device_unregister(data->port_dev[i]); + ida_simple_remove(&cpld_ida, data->port_data[i]->port_id); + kfree(data->port_data[i]); + } + + if (cpld_idr_is_empty(&cpld_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("Jonathan Tsai "); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("Quanta Switch SFP28 CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/qci_platform_ix8c.c b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/qci_platform_ix8c.c new file mode 100644 index 000000000000..f389304a2fbd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/modules/qci_platform_ix8c.c @@ -0,0 +1,400 @@ +/* + * Quanta IX8C platform driver + * + * + * Copyright (C) 2017 Quanta Computer inc. + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)) +#include +#else +#include +#endif + +#define MUX_INFO(bus, deselect) \ + {.adap_id = bus, .deselect_on_exit = deselect} + +static struct pca954x_platform_mode pca9548sfp1_modes[] = { + MUX_INFO(0x20, 1), + MUX_INFO(0x21, 1), + MUX_INFO(0x22, 1), + MUX_INFO(0x23, 1), + MUX_INFO(0x24, 1), + MUX_INFO(0x25, 1), + MUX_INFO(0x26, 1), + MUX_INFO(0x27, 1), +}; + +static struct pca954x_platform_data pca9548sfp1_data = { + .modes = pca9548sfp1_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp2_modes[] = { + MUX_INFO(0x28, 1), + MUX_INFO(0x29, 1), + MUX_INFO(0x2a, 1), + MUX_INFO(0x2b, 1), + MUX_INFO(0x2c, 1), + MUX_INFO(0x2d, 1), + MUX_INFO(0x2e, 1), + MUX_INFO(0x2f, 1), +}; + +static struct pca954x_platform_data pca9548sfp2_data = { + .modes = pca9548sfp2_modes, + .num_modes = 8, +}; +static struct pca954x_platform_mode pca9548sfp3_modes[] = { + MUX_INFO(0x30, 1), + MUX_INFO(0x31, 1), + MUX_INFO(0x32, 1), + MUX_INFO(0x33, 1), + MUX_INFO(0x34, 1), + MUX_INFO(0x35, 1), + MUX_INFO(0x36, 1), + MUX_INFO(0x37, 1), +}; + +static struct pca954x_platform_data pca9548sfp3_data = { + .modes = pca9548sfp3_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp4_modes[] = { + MUX_INFO(0x38, 1), + MUX_INFO(0x39, 1), + MUX_INFO(0x3a, 1), + MUX_INFO(0x3b, 1), + MUX_INFO(0x3c, 1), + MUX_INFO(0x3d, 1), + MUX_INFO(0x3e, 1), + MUX_INFO(0x3f, 1), +}; + +static struct pca954x_platform_data pca9548sfp4_data = { + .modes = pca9548sfp4_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp5_modes[] = { + MUX_INFO(0x40, 1), + MUX_INFO(0x41, 1), + MUX_INFO(0x42, 1), + MUX_INFO(0x43, 1), + MUX_INFO(0x44, 1), + MUX_INFO(0x45, 1), + MUX_INFO(0x46, 1), + MUX_INFO(0x47, 1), +}; + +static struct pca954x_platform_data pca9548sfp5_data = { + .modes = pca9548sfp5_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp6_modes[] = { + MUX_INFO(0x48, 1), + MUX_INFO(0x49, 1), + MUX_INFO(0x4a, 1), + MUX_INFO(0x4b, 1), + MUX_INFO(0x4c, 1), + MUX_INFO(0x4d, 1), + MUX_INFO(0x4e, 1), + MUX_INFO(0x4f, 1), +}; + +static struct pca954x_platform_data pca9548sfp6_data = { + .modes = pca9548sfp6_modes, + .num_modes = 8, +}; + +//ZQSFP +static struct pca954x_platform_mode pca9548sfp7_modes[] = { + MUX_INFO(0x50, 1), + MUX_INFO(0x51, 1), + MUX_INFO(0x52, 1), + MUX_INFO(0x53, 1), + MUX_INFO(0x54, 1), + MUX_INFO(0x55, 1), + MUX_INFO(0x56, 1), + MUX_INFO(0x57, 1), +}; + +static struct pca954x_platform_data pca9548sfp7_data = { + .modes = pca9548sfp7_modes, + .num_modes = 8, +}; + +// end port + +static struct pca954x_platform_mode pca9546_modes[] = { + MUX_INFO(0x10, 1), + MUX_INFO(0x11, 1), + MUX_INFO(0x12, 1), + MUX_INFO(0x13, 1), +}; + +static struct pca954x_platform_data pca9546_data = { + .modes = pca9546_modes, + .num_modes = 4, +}; + +static struct pca954x_platform_mode pca9548_modes[] = { + MUX_INFO(0x14, 1), + MUX_INFO(0x15, 1), + MUX_INFO(0x16, 1), + MUX_INFO(0x17, 1), + MUX_INFO(0x18, 1), + MUX_INFO(0x19, 1), + MUX_INFO(0x1a, 1), + MUX_INFO(0x1b, 1), +}; + +static struct pca954x_platform_data pca9548_data = { + .modes = pca9548_modes, + .num_modes = 8, +}; + +//MB Board Data +static struct pca953x_platform_data pca9555_1_data = { + .gpio_base = 0x10, +}; +//QSFP28 49-56 IO Expander +static struct pca953x_platform_data pca9698_2_data = { + .gpio_base = 0x20, +}; +//CPU Linking Board at CPU's I2C Bus +static struct pca953x_platform_data pca9555_CPU_data = { + .gpio_base = 0x48, +}; +static struct i2c_board_info ix8c_i2c_devices[] = { + { + I2C_BOARD_INFO("pca9546", 0x72), // 0 + .platform_data = &pca9546_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x77), // 1 + .platform_data = &pca9548_data, + }, + { + I2C_BOARD_INFO("24c02", 0x54), // 2 eeprom + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 3 0x77 ch0 + .platform_data = &pca9548sfp1_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 4 0x77 ch1 + .platform_data = &pca9548sfp2_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 5 0x77 ch2 + .platform_data = &pca9548sfp3_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 6 0x77 ch3 + .platform_data = &pca9548sfp4_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 7 0x77 ch4 + .platform_data = &pca9548sfp5_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 8 0x77 ch5 + .platform_data = &pca9548sfp6_data, + }, + { + I2C_BOARD_INFO("pca9548", 0x73), // 9 0x77 ch6 + .platform_data = &pca9548sfp7_data, + }, + { + I2C_BOARD_INFO("CPLD-SFP28", 0x38), // 10 0x72 ch0 CPLD1_:SFP28 1~16 + }, + { + I2C_BOARD_INFO("CPLD-SFP28", 0x38), // 11 0x72 ch1 CPLD2_:SFP28 17~32 + }, + { + I2C_BOARD_INFO("CPLD-SFP28", 0x38), // 12 0x72 ch2 CPLD_3:SFP28 33~48 + }, + { + I2C_BOARD_INFO("pca9555", 0x23), // 13 0x72 ch3 MB Board Data + .platform_data = &pca9555_1_data, + }, + { + I2C_BOARD_INFO("pca9698", 0x21), // 14 0x72 ch3 QSFP:49~52 + .platform_data = &pca9698_2_data, + }, + { + I2C_BOARD_INFO("optoe1", 0x50), // 15 0x50 QSFP EEPROM + }, + { + I2C_BOARD_INFO("pca9555", 0x22), // 16 CPU Linking Board at CPU's I2C Bus + .platform_data = &pca9555_CPU_data, + }, + { + I2C_BOARD_INFO("CPLDLED_IX8C", 0x3a), // 17 0x72 ch0 CPLD4 LED function of SFP28 & QSFP28 (Port27~56) + }, + { + I2C_BOARD_INFO("CPLDLED_IX8C", 0x39), // 18 0x72 ch0 CPLD6 LED function of SFP28 & QSFP28 (Port1~26) + }, + { + I2C_BOARD_INFO("optoe2", 0x50), // 19 0x50 SFP28 EEPROM + }, +}; + +static struct platform_driver ix8c_platform_driver = { + .driver = { + .name = "qci-ix8c", + .owner = THIS_MODULE, + }, +}; + +static struct platform_device *ix8c_device; + +static int __init ix8c_platform_init(void) +{ + struct i2c_client *client; + struct i2c_adapter *adapter; + int ret, i; + + ret = platform_driver_register(&ix8c_platform_driver); + if (ret < 0) + return ret; + + /* Register platform stuff */ + ix8c_device = platform_device_alloc("qci-ix8c", -1); + if (!ix8c_device) { + ret = -ENOMEM; + goto fail_platform_driver; + } + + ret = platform_device_add(ix8c_device); + if (ret) + goto fail_platform_device; + + adapter = i2c_get_adapter(0); + client = i2c_new_device(adapter, &ix8c_i2c_devices[0]); // pca9546 + client = i2c_new_device(adapter, &ix8c_i2c_devices[1]); // pca9548 + client = i2c_new_device(adapter, &ix8c_i2c_devices[16]); // CPU Linking Board at CPU's I2C Bus + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x10); + client = i2c_new_device(adapter, &ix8c_i2c_devices[10]); // CPLD_1 + client = i2c_new_device(adapter, &ix8c_i2c_devices[17]); // CPLD_4 + client = i2c_new_device(adapter, &ix8c_i2c_devices[18]); // CPLD_6 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x11); + client = i2c_new_device(adapter, &ix8c_i2c_devices[11]); // CPLD_2 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x12); + client = i2c_new_device(adapter, &ix8c_i2c_devices[12]); // CPLD_3 + client = i2c_new_device(adapter, &ix8c_i2c_devices[2]); // MB_BOARDINFO_EEPROM + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x13); + client = i2c_new_device(adapter, &ix8c_i2c_devices[13]); // MB Board Data + client = i2c_new_device(adapter, &ix8c_i2c_devices[14]); // QSFP:49~52 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x14); + client = i2c_new_device(adapter, &ix8c_i2c_devices[3]); // pca9548_1 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x15); + client = i2c_new_device(adapter, &ix8c_i2c_devices[4]); // pca9548_2 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x16); + client = i2c_new_device(adapter, &ix8c_i2c_devices[5]); // pca9548_3 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x17); + client = i2c_new_device(adapter, &ix8c_i2c_devices[6]); // pca9548_4 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x18); + client = i2c_new_device(adapter, &ix8c_i2c_devices[7]); // pca9548_5 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x19); + client = i2c_new_device(adapter, &ix8c_i2c_devices[8]); // pca9548_6 SFP + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x1a); + client = i2c_new_device(adapter, &ix8c_i2c_devices[9]); // pca9548_7 QSFP + i2c_put_adapter(adapter); + + for(i = 80; i < 88; i ++){ // QSFP 49~56 EEPROM + adapter = i2c_get_adapter(i); + client = i2c_new_device(adapter, &ix8c_i2c_devices[15]); + i2c_put_adapter(adapter); + } + + for(i = 32; i < 80; i ++){ // SFP28 1~48 EEPROM + adapter = i2c_get_adapter(i); + client = i2c_new_device(adapter, &ix8c_i2c_devices[19]); + i2c_put_adapter(adapter); + } + + return 0; + +fail_platform_device: + platform_device_put(ix8c_device); + +fail_platform_driver: + platform_driver_unregister(&ix8c_platform_driver); + return ret; +} + +static void __exit ix8c_platform_exit(void) +{ + platform_device_unregister(ix8c_device); + platform_driver_unregister(&ix8c_platform_driver); +} + +module_init(ix8c_platform_init); +module_exit(ix8c_platform_exit); + + +MODULE_AUTHOR("Jonathan Tsai "); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("Quanta IX8C Platform Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/service/ix8c-platform-init.service b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/service/ix8c-platform-init.service new file mode 100755 index 000000000000..d9c80a55771f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/service/ix8c-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Quanta IX8C-56X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/quanta_ix8c_util.py install +ExecStop=/usr/local/bin/quanta_ix8c_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/setup.py b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/setup.py new file mode 100644 index 000000000000..26a3101bf7a2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='ix8c_56x', + version='1.0', + description='Module to initialize Quanta IX8C-56X platforms', + + packages=['ix8c_56x'], + package_dir={'ix8c_56x': 'ix8c-56x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/utils/quanta_ix8c_util.py b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/utils/quanta_ix8c_util.py new file mode 100755 index 000000000000..c495533638e8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix8c-56x/utils/quanta_ix8c_util.py @@ -0,0 +1,329 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Quanta Computer Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[IX8C-56X]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +"with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +instantiate =[ +#turn on module power +'echo 21 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio21/direction', +'echo 1 >/sys/class/gpio/gpio21/value', +#export pca9698 for qsfp present +'echo 34 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio34/direction', +'echo 38 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio38/direction', +'echo 42 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio42/direction', +'echo 46 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio46/direction', +'echo 50 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio50/direction', +'echo 54 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio54/direction', +'echo 58 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio58/direction', +'echo 62 > /sys/class/gpio/export', +'echo in > /sys/class/gpio/gpio62/direction', +#export pca9698 for qsfp reset +'echo 32 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio32/direction', +'echo 1 >/sys/class/gpio/gpio32/value', +'echo 36 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio36/direction', +'echo 1 >/sys/class/gpio/gpio36/value', +'echo 40 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio40/direction', +'echo 1 >/sys/class/gpio/gpio40/value', +'echo 44 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio44/direction', +'echo 1 >/sys/class/gpio/gpio44/value', +'echo 48 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio48/direction', +'echo 1 >/sys/class/gpio/gpio48/value', +'echo 52 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio52/direction', +'echo 1 >/sys/class/gpio/gpio52/value', +'echo 56 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio56/direction', +'echo 1 >/sys/class/gpio/gpio56/value', +'echo 60 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio60/direction', +'echo 1 >/sys/class/gpio/gpio60/value', +#export pca9698 for qsfp lpmode +'echo 35 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio35/direction', +'echo 0 >/sys/class/gpio/gpio35/value', +'echo 39 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio39/direction', +'echo 0 >/sys/class/gpio/gpio39/value', +'echo 43 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio43/direction', +'echo 0 >/sys/class/gpio/gpio43/value', +'echo 47 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio47/direction', +'echo 0 >/sys/class/gpio/gpio47/value', +'echo 51 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio51/direction', +'echo 0 >/sys/class/gpio/gpio51/value', +'echo 55 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio55/direction', +'echo 0 >/sys/class/gpio/gpio55/value', +'echo 59 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio59/direction', +'echo 0 >/sys/class/gpio/gpio59/value', +'echo 63 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio63/direction', +'echo 0 >/sys/class/gpio/gpio63/value', +#Reset fron-ports LED CPLD +'echo 73 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio73/direction', +'echo 0 >/sys/class/gpio/gpio73/value', +'echo 1 >/sys/class/gpio/gpio73/value', +#Enable front-ports LED decoding +'echo 1 > /sys/class/cpld-led/CPLDLED-1/led_decode', +'echo 1 > /sys/class/cpld-led/CPLDLED-2/led_decode', +#SFP28 Module TxEnable +'echo 0 > /sys/class/cpld-sfp28/port-1/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-2/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-3/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-4/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-5/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-6/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-7/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-8/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-9/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-10/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-11/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-12/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-13/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-14/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-15/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-16/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-17/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-18/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-19/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-20/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-21/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-22/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-23/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-24/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-25/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-26/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-27/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-28/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-29/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-30/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-31/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-32/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-33/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-34/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-35/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-36/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-37/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-38/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-39/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-40/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-41/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-42/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-43/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-44/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-45/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-46/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-47/tx_dis', +'echo 0 > /sys/class/cpld-sfp28/port-48/tx_dis' +] + +drivers =[ +'lpc_ich', +'i2c-i801', +'i2c-dev', +'i2c-mux-pca954x', +'gpio-pca953x', +'optoe', +'qci_cpld_sfp28', +'qci_cpld_led', +'qci_platform_ix8c', +'ipmi_devintf' +] + + + +def system_install(): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("rmmod i2c_ismt ", 1) + status, output = exec_cmd("rmmod i2c-i801 ", 1) + #setup driver dependency + status, output = exec_cmd("depmod -a ", 1) + #install drivers + for i in range(0,len(drivers)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #remove net rules for generating new net rules + status, output = exec_cmd("systemctl stop systemd-udevd.service ", 1) + status, output = exec_cmd("rm /etc/udev/rules.d/70-persistent-net.rules ", 1) + status, output = exec_cmd("rmmod ixgbe ", 1) + status, output = exec_cmd("rmmod igb ", 1) + status, output = exec_cmd("modprobe igb ", 1) + status, output = exec_cmd("modprobe ixgbe ", 1) + status, output = exec_cmd("systemctl start systemd-udevd.service ", 1) + + #instantiate devices + for i in range(0,len(instantiate)): + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + + #QSFP for 1~56 port + for port_number in range(1,57): + bus_number = port_number + 31 + os.system("echo %d >/sys/bus/i2c/devices/%d-0050/port_name" % (port_number, bus_number)) + + return + + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print " ix8c driver already installed...." + return + +def uninstall(): + global FORCE + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"i2c-0", 0) + return ret1 + +if __name__ == "__main__": + main() + + + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/classes/__init__.py b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/classes/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/Makefile b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/Makefile new file mode 100644 index 000000000000..929782931a47 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m:=qci_cpld_qsfpdd.o qci_cpld_led.o qci_platform_ix9.o + + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_led.c b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_led.c new file mode 100644 index 000000000000..d8f89240a851 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_led.c @@ -0,0 +1,277 @@ +/* + * A LED CPLD driver for Quanta Switch Platform + * + * The CPLD is customize by Quanta for decode led bit stream, + * This driver modify from Quanta CPLD I/O driver. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * Author: Roger Chang + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_led_ida); + +enum platform_type { + IX7 = 0, + IX8C, + IX9, + NONE +}; + +static struct class *cpld_class = NULL; + +struct cpld_data { + struct i2c_client *cpld_client; + char name[8]; + u8 cpld_id; +}; + +struct cpld_led_data { + struct mutex lock; + struct device *port_dev; + struct cpld_data *cpld_data; +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_led_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_led_id[] = { + { "CPLDLED_IX7", IX7 }, + { "CPLDLED_IX8C", IX8C }, + { "CPLDLED_IX9", IX9 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_led_id); + +static struct i2c_driver cpld_led_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_led", + }, + .probe = cpld_led_probe, + .remove = cpld_led_remove, + .id_table = cpld_led_id, +// .address_list = normal_i2c, +}; + +#define CPLD_LED_ID_PREFIX "CPLDLED-" +#define CPLD_LED_ID_FORMAT CPLD_LED_ID_PREFIX "%d" + +#define CPLD_DECODER_OFFSET 0x4 +#define CPLD_DECODER_MASK 0x1 +#define CPLD_USERCODE_START_OFFSET 0x0 + +static ssize_t get_led_decode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 offset = (u8)(CPLD_DECODER_OFFSET); + s32 value; + + value = i2c_smbus_read_byte_data(client, offset); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value &= CPLD_DECODER_MASK; + + return sprintf(buf, "%d\n", (value == 0) ? 1 : 0); +} + +static ssize_t get_usercode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 i = 0; + s32 value = 0, reading = 0; + + for (i = 0; i < 4; i++) + { + reading = i2c_smbus_read_byte_data(client, CPLD_USERCODE_START_OFFSET + i); + if (reading < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led usercode reg %d value= %x\n", i, reading); + + value |= reading << (24 - 8 * i); + } + + return sprintf(buf, "%X\n", value); +} + +static ssize_t set_led_decode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + s32 value; + long enable; + + if (kstrtol(buf, 0, &enable)) + return -EINVAL; + + if ((enable != 1) && (enable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_byte_data(client, CPLD_DECODER_OFFSET); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read led decode value= %x\n", value); + + value |= CPLD_DECODER_MASK; + if (enable) + value &= ~CPLD_DECODER_MASK; + + dev_dbg(&client->dev, "write led decode value= %x\n", value); + + i2c_smbus_write_byte_data(client, CPLD_DECODER_OFFSET, (u8)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(led_decode, S_IWUSR | S_IRUGO, get_led_decode, set_led_decode); +static DEVICE_ATTR(usercode, S_IRUGO, get_usercode, NULL); + +static const struct attribute *led_attrs[] = { + &dev_attr_usercode.attr, + &dev_attr_led_decode.attr, + NULL, +}; + +static const struct attribute_group led_attr_group = { + .attrs = (struct attribute **) led_attrs, +}; + +static int cpld_led_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_led_data *data; + struct cpld_data *led_data; + struct device *port_dev; + int nr, err; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, "cpld-led"); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_led_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* Test */ + nr = ida_simple_get(&cpld_led_ida, 1, 99, GFP_KERNEL); + if (nr < 0) + goto err_out; + + led_data = kzalloc(sizeof(struct cpld_led_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), led_data, CPLD_LED_ID_FORMAT, nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + // printk("err_status\n"); + } + + data->port_dev = port_dev; + data->cpld_data = led_data; + + dev_info(&client->dev, "Register CPLDLED %d\n", nr); + + sprintf(led_data->name, "LED%d-data", nr); + led_data->cpld_id = nr; + dev_set_drvdata(port_dev, led_data); + port_dev->init_name = led_data->name; + led_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &led_attr_group); + // if (status) printk("err status\n"); + /* end */ + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +err_out: + return nr; +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} + +static int cpld_led_remove(struct i2c_client *client) +{ + struct cpld_led_data *data = i2c_get_clientdata(client); + + dev_info(data->port_dev, "Remove CPLDLED-%d\n", data->cpld_data->cpld_id); + device_unregister(data->port_dev); + ida_simple_remove(&cpld_led_ida, data->cpld_data->cpld_id); + kfree(data->cpld_data); + + if (cpld_idr_is_empty(&cpld_led_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_led_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_AUTHOR("Roger Chang "); +MODULE_DESCRIPTION("Quanta Switch LED CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_qsfpdd.c b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_qsfpdd.c new file mode 100644 index 000000000000..d616f887dbbf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_cpld_qsfpdd.c @@ -0,0 +1,411 @@ +/* + * A CPLD driver for monitor QSFPDD module I/O + * + * The CPLD is customize by Quanta for controlling QSFPDD module signals, + * they are RESET , INTERREPT , Module_Present, LPMODE + * Each CPLD control 16 modules, each module use 4 bits in register. + * + * Copyright (C) 2015 Quanta Inc. + * + * Author: Luffy Cheng + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_IDA(cpld_ida); + +enum platform_type { + QSFPDD = 0, + NONE +}; + +static struct class *cpld_class = NULL; + +struct sfp_data { + struct i2c_client *cpld_client; + char name[8]; + u8 port_id; + u8 cpld_port; +}; + +struct cpld_data { + struct mutex lock; + struct device *port_dev[16]; + struct sfp_data *port_data[16]; +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int cpld_remove(struct i2c_client *client); + +static const struct i2c_device_id cpld_id[] = { + { "CPLD-QSFPDD", QSFPDD }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "qci_cpld_qsfpdd", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +// .address_list = normal_i2c, +}; + +#define CPLD_ID_PREFIX "port-" +#define CPLD_ID_FORMAT CPLD_ID_PREFIX "%d" + +#define RESET_MASK 0x08 +#define INTERRUPT_MASK 0x04 +#define MODULE_PRESENT_MASK 0x02 +#define LPMODE_MASK 0x01 + +static inline u8 get_group_cmd(u8 group) +{ + //FIXME: if group cmd change + return (group + 1); +} + +static inline u8 port_remapping(u8 phy_port) +{ + /* FIXME: implement by hardware design */ + /* The CPLD register port mapping is weird : + * MSB -------- LSB (word data) + * P3 P4 P1 P2 (per port 4 bits) + * For easy coding bit shift, we treat it as hw port swap + */ + return (phy_port % 2) ? (phy_port - 1) : (phy_port + 1); +} + +static ssize_t get_reset(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= RESET_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_interrupt(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= INTERRUPT_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t get_module_present(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= MODULE_PRESENT_MASK; + + //FIXME: if present is not low active + return sprintf(buf, "%d\n", value ? 0 : 1); +} + +static ssize_t get_lpmode(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value >>= (group_port * 4); + value &= LPMODE_MASK; + + return sprintf(buf, "%d\n", value ? 1 : 0); +} + +static ssize_t set_reset(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(RESET_MASK << (group_port * 4)); + if (disable) + value |= (RESET_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_lpmode(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sfp_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->cpld_client; + u8 group = (u8)(data->cpld_port / 4); + u8 group_port = data->cpld_port % 4; + s32 value; + long disable; + + dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id, + data->cpld_port + 1, group + 1, group_port + 1); + + if (kstrtol(buf, 0, &disable)) + return -EINVAL; + + if ((disable != 1) && (disable != 0)) + return -EINVAL; + +// mutex_lock(&data->lock); + value = i2c_smbus_read_word_data(client, get_group_cmd(group)); + if (value < 0) + return -ENODEV; + + dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value); + + value &= ~(LPMODE_MASK << (group_port * 4)); + if (disable) + value |= (LPMODE_MASK << (group_port * 4)); + + dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value); + + i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value); +// mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(reset, S_IWUSR | S_IRUGO, get_reset, set_reset); +static DEVICE_ATTR(lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode); +static DEVICE_ATTR(module_present, S_IRUGO, get_module_present, NULL); +static DEVICE_ATTR(interrupt, S_IRUGO, get_interrupt, NULL); + +static const struct attribute *sfp_attrs[] = { + &dev_attr_reset.attr, + &dev_attr_lpmode.attr, + &dev_attr_module_present.attr, + &dev_attr_interrupt.attr, + NULL, +}; + +static const struct attribute_group sfp_attr_group = { + .attrs = (struct attribute **) sfp_attrs, +}; + +static int cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cpld_data *data; + struct sfp_data *port_data; + struct device *port_dev; + int port_nr, i, err; + + if (!cpld_class) + { + cpld_class = class_create(THIS_MODULE, "cpld-qsfpdd"); + if (IS_ERR(cpld_class)) { + pr_err("couldn't create sysfs class\n"); + return PTR_ERR(cpld_class); + } + } + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* register sfp port data to sysfs */ + for (i = 0; i < 16; i++) + { + port_nr = ida_simple_get(&cpld_ida, 1, 99, GFP_KERNEL); + if (port_nr < 0) + return port_nr; + + port_data = kzalloc(sizeof(struct sfp_data), GFP_KERNEL); + + port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), port_data, CPLD_ID_FORMAT, port_nr); + if (IS_ERR(port_dev)) { + err = PTR_ERR(port_dev); + // printk("err_status\n"); + } + + data->port_dev[i] = port_dev; + data->port_data[i] = port_data; + + dev_info(&client->dev, "Register qsfpdd port-%d\n", port_nr); + + /* FIXME: implement Logical/Physical port remapping */ + //port_data->cpld_port = i; + port_data->cpld_port = port_remapping(i); + sprintf(port_data->name, "port-%d", port_nr); + port_data->port_id = port_nr; + dev_set_drvdata(port_dev, port_data); + port_dev->init_name = port_data->name; + port_data->cpld_client = client; + + err = sysfs_create_group(&port_dev->kobj, &sfp_attr_group); + // if (status) printk("err status\n"); + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s device found\n", client->name); + + + return 0; + +#if 0 +//FIXME: implement error check +exit_remove: +// sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +#endif +} + +/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */ +static int idr_has_entry(int id, void *p, void *data) +{ + return 1; +} + +static bool cpld_idr_is_empty(struct idr *idp) +{ + return !idr_for_each(idp, idr_has_entry, NULL); +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + int i; + + for (i = 15; i >= 0; i--) + { + dev_info(data->port_dev[i], "Remove qsfpdd port-%d\n", data->port_data[i]->port_id); + device_unregister(data->port_dev[i]); + ida_simple_remove(&cpld_ida, data->port_data[i]->port_id); + kfree(data->port_data[i]); + } + + if (cpld_idr_is_empty(&cpld_ida.idr)) + class_destroy(cpld_class); + + return 0; +} + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("Luffy Cheng "); +MODULE_DESCRIPTION("Quanta Switch SFP CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_platform_ix9.c b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_platform_ix9.c new file mode 100644 index 000000000000..1b98c4a2f31f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/modules/qci_platform_ix9.c @@ -0,0 +1,293 @@ +/* + * Quanta IX9 platform driver + * + * + * Copyright (C) 2019 Quanta Computer inc. + * + * 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. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,12,0) +#include +#else +#include +#endif +#define MUX_INFO(bus, deselect) \ + {.adap_id = bus, .deselect_on_exit = deselect} + +static struct pca954x_platform_mode pca9546_1_modes[] = { + MUX_INFO(0x10, 1), + MUX_INFO(0x11, 1), + MUX_INFO(0x12, 1), + MUX_INFO(0x13, 1), +}; + +static struct pca954x_platform_data pca9546_1_data = { + .modes = pca9546_1_modes, + .num_modes = 4, +}; + +static struct pca954x_platform_mode pca9548_1_modes[] = { + MUX_INFO(0x14, 1), + MUX_INFO(0x15, 1), + MUX_INFO(0x16, 1), + MUX_INFO(0x17, 1), +}; + +static struct pca954x_platform_data pca9548_1_data = { + .modes = pca9548_1_modes, + .num_modes = 4, +}; + +static struct pca954x_platform_mode pca9548sfp1_modes[] = { + MUX_INFO(0x20, 1), + MUX_INFO(0x21, 1), + MUX_INFO(0x22, 1), + MUX_INFO(0x23, 1), + MUX_INFO(0x24, 1), + MUX_INFO(0x25, 1), + MUX_INFO(0x26, 1), + MUX_INFO(0x27, 1), +}; + +static struct pca954x_platform_data pca9548sfp1_data = { + .modes = pca9548sfp1_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp2_modes[] = { + MUX_INFO(0x28, 1), + MUX_INFO(0x29, 1), + MUX_INFO(0x2a, 1), + MUX_INFO(0x2b, 1), + MUX_INFO(0x2c, 1), + MUX_INFO(0x2d, 1), + MUX_INFO(0x2e, 1), + MUX_INFO(0x2f, 1), +}; + +static struct pca954x_platform_data pca9548sfp2_data = { + .modes = pca9548sfp2_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp3_modes[] = { + MUX_INFO(0x30, 1), + MUX_INFO(0x31, 1), + MUX_INFO(0x32, 1), + MUX_INFO(0x33, 1), + MUX_INFO(0x34, 1), + MUX_INFO(0x35, 1), + MUX_INFO(0x36, 1), + MUX_INFO(0x37, 1), +}; + +static struct pca954x_platform_data pca9548sfp3_data = { + .modes = pca9548sfp3_modes, + .num_modes = 8, +}; + +static struct pca954x_platform_mode pca9548sfp4_modes[] = { + MUX_INFO(0x38, 1), + MUX_INFO(0x39, 1), + MUX_INFO(0x3a, 1), + MUX_INFO(0x3b, 1), + MUX_INFO(0x3c, 1), + MUX_INFO(0x3d, 1), + MUX_INFO(0x3e, 1), + MUX_INFO(0x3f, 1), +}; + +static struct pca954x_platform_data pca9548sfp4_data = { + .modes = pca9548sfp4_modes, + .num_modes = 8, +}; + +static struct pca953x_platform_data tca9539_1_data = { + .gpio_base = 0x10, +}; +//CPU Linking Board at CPU's I2C Bus +static struct pca953x_platform_data pca9555_CPU_data = { + .gpio_base = 0x20, +}; + +static struct i2c_board_info ix9_i2c_devices[] = { + { + I2C_BOARD_INFO("pca9546", 0x72), + .platform_data = &pca9546_1_data, // 0 pca9546_1 + }, + { + I2C_BOARD_INFO("pca9548", 0x77), + .platform_data = &pca9548_1_data, // 1 pca9548_1 + }, + { + I2C_BOARD_INFO("tca9539", 0x74), + .platform_data = &tca9539_1_data, // 2 Board ID and QSFP-DD PW EN/PG + }, + { + I2C_BOARD_INFO("24c02", 0x54), // 3 MB_BOARDINFO_EEPROM + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca9548sfp1_data, // 4 0x77 ch0 pca9548 #1 + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca9548sfp2_data, // 5 0x77 ch1 pca9548 #2 + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca9548sfp3_data, // 6 0x77 ch2 pca9548 #3 + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca9548sfp4_data, // 7 0x77 ch3 pca9548 #4 + }, + { + I2C_BOARD_INFO("CPLD-QSFPDD", 0x38), // 8 0x72 ch0 CPLD-IO #2, #3 + }, + { + I2C_BOARD_INFO("CPLDLED_IX9", 0x39), // 9 0x72 ch1 CPLD-LED #4, #5 + }, + { + I2C_BOARD_INFO("optoe1", 0x50), // 10 eeprom for loopback module + }, + { + I2C_BOARD_INFO("pca9555", 0x22), // 11 CPU Linking Board at CPU's I2C Bus + .platform_data = &pca9555_CPU_data, + }, +}; + +static struct platform_driver ix9_platform_driver = { + .driver = { + .name = "qci-ix9", + .owner = THIS_MODULE, + }, +}; + +static struct platform_device *ix9_device; + +static int __init ix9_platform_init(void) +{ + struct i2c_client *client; + struct i2c_adapter *adapter; + int ret, i; + + ret = platform_driver_register(&ix9_platform_driver); + if (ret < 0) + return ret; + + /* Register platform stuff */ + ix9_device = platform_device_alloc("qci-ix9", -1); + if (!ix9_device) { + ret = -ENOMEM; + goto fail_platform_driver; + } + + ret = platform_device_add(ix9_device); + if (ret) + goto fail_platform_device; + + adapter = i2c_get_adapter(0); + client = i2c_new_device(adapter, &ix9_i2c_devices[0]); // pca9546_1 - Address: 0x72 + client = i2c_new_device(adapter, &ix9_i2c_devices[1]); // pca9548_1 - Address: 0x77 + client = i2c_new_device(adapter, &ix9_i2c_devices[11]); // CPU Linking Board at CPU's I2C Bus - Address: 0x22 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x10); + client = i2c_new_device(adapter, &ix9_i2c_devices[8]); // CPLD-IO #2 - Address: 0x38 + client = i2c_new_device(adapter, &ix9_i2c_devices[9]); // CPLD-LED #4 - Address: 0x39 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x11); + client = i2c_new_device(adapter, &ix9_i2c_devices[8]); // CPLD-IO #3 - Address: 0x38 + client = i2c_new_device(adapter, &ix9_i2c_devices[9]); // CPLD-LED #5 - Address: 0x39 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x12); + client = i2c_new_device(adapter, &ix9_i2c_devices[3]); // MB_BOARDINFO_EEPROM - Address: 0x54 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x13); + client = i2c_new_device(adapter, &ix9_i2c_devices[2]); // tca9539_1 Board ID and QSFP-DD PW EN/PG - Address: 0x74 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x14); + client = i2c_new_device(adapter, &ix9_i2c_devices[4]); // pca9548 #1 QSFPDD - Address: 0x73 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x15); + client = i2c_new_device(adapter, &ix9_i2c_devices[5]); // pca9548 #2 QSFPDD - Address: 0x73 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x16); + client = i2c_new_device(adapter, &ix9_i2c_devices[6]); // pca9548 #3 QSFPDD - Address: 0x73 + i2c_put_adapter(adapter); + + adapter = i2c_get_adapter(0x17); + client = i2c_new_device(adapter, &ix9_i2c_devices[7]); // pca9548 #4 QSFPDD - Address: 0x73 + i2c_put_adapter(adapter); + + for(i = 0x20; i < 0x40; i++) + { + adapter = i2c_get_adapter(i); + client = i2c_new_device(adapter, &ix9_i2c_devices[10]); // eeprom for loopback module - Address: 0x50 + i2c_put_adapter(adapter); + } + + return 0; + +fail_platform_device: + platform_device_put(ix9_device); + +fail_platform_driver: + platform_driver_unregister(&ix9_platform_driver); + return ret; +} + +static void __exit ix9_platform_exit(void) +{ + platform_device_unregister(ix9_device); + platform_driver_unregister(&ix9_platform_driver); +} + +module_init(ix9_platform_init); +module_exit(ix9_platform_exit); + +MODULE_AUTHOR("Jonathan Tsai "); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("Quanta IX9 Platform Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/service/ix9-platform-init.service b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/service/ix9-platform-init.service new file mode 100755 index 000000000000..1f33cc170118 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/service/ix9-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Quanta IX9-32X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/quanta_ix9_util.py install +ExecStop=/usr/local/bin/quanta_ix9_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/setup.py b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/setup.py new file mode 100644 index 000000000000..b2f1b39fcd73 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='ix9_32x', + version='1.0', + description='Module to initialize Quanta IX9-32X platforms', + + packages=['ix9_32x'], + package_dir={'ix9_32x': 'ix9-32x/classes'}, +) + diff --git a/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/utils/quanta_ix9_util.py b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/utils/quanta_ix9_util.py new file mode 100755 index 000000000000..4c31aa8584b8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-quanta/ix9-32x/utils/quanta_ix9_util.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Quanta Computer Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + +DEBUG = False +args = [] +FORCE = 0 +i2c_prefix = '/sys/bus/i2c/devices/' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + install() + elif arg == 'clean': + uninstall() + else: + show_help() + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_log(txt): + if DEBUG == True: + print "[IX9-32X]"+txt + return + +def exec_cmd(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + show_log (cmd +"with result:" + str(status)) + show_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +instantiate =[ +#turn on module power +'echo 21 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio21/direction', +'echo 1 >/sys/class/gpio/gpio21/value', +#Reset fron-ports LED CPLD +'echo 33 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio33/direction', +'echo 0 >/sys/class/gpio/gpio33/value', +'echo 1 >/sys/class/gpio/gpio33/value', +#Enable front-ports LED decoding +'echo 1 > /sys/class/cpld-led/CPLDLED-1/led_decode', +'echo 1 > /sys/class/cpld-led/CPLDLED-2/led_decode', +#Update System LED +'echo 39 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio39/direction', +'echo 0 > /sys/class/gpio/gpio39/value', +'echo 40 > /sys/class/gpio/export', +'echo out > /sys/class/gpio/gpio40/direction', +'echo 1 > /sys/class/gpio/gpio40/value', +] + +drivers =[ +'lpc_ich', +'i2c-i801', +'i2c-dev', +'i2c-mux-pca954x', +'gpio-pca953x', +'qci_cpld_qsfpdd', +'qci_cpld_led', +'qci_platform_ix9', +'ipmi_devintf' +] + + + +def system_install(): + global FORCE + + #remove default drivers to avoid modprobe order conflicts + status, output = exec_cmd("rmmod i2c_ismt ", 1) + status, output = exec_cmd("rmmod i2c-i801 ", 1) + #setup driver dependency + status, output = exec_cmd("depmod -a ", 1) + #install drivers + for i in range(0,len(drivers)): + status, output = exec_cmd("modprobe "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + + #remove net rules for generating new net rules + status, output = exec_cmd("systemctl stop systemd-udevd.service ", 1) + status, output = exec_cmd("rm /etc/udev/rules.d/70-persistent-net.rules ", 1) + status, output = exec_cmd("rmmod ixgbe ", 1) + status, output = exec_cmd("rmmod igb ", 1) + status, output = exec_cmd("modprobe igb ", 1) + status, output = exec_cmd("modprobe ixgbe ", 1) + status, output = exec_cmd("systemctl start systemd-udevd.service ", 1) + + #instantiate devices + for i in range(0,len(instantiate)): + status, output = exec_cmd(instantiate[i], 1) + if status: + print output + if FORCE == 0: + return status + + #QSFPDD for 1~32 port + for port_number in range(1,33): + bus_number = port_number + 31 + os.system("echo %d >/sys/bus/i2c/devices/%d-0050/port_name" % (port_number, bus_number)) + + return + +def system_ready(): + if not device_found(): + return False + return True + +def install(): + if not device_found(): + print "No device, installing...." + status = system_install() + if status: + if FORCE == 0: + return status + else: + print " ix9 driver already installed...." + return + +def uninstall(): + global FORCE + #uninstall drivers + for i in range(len(drivers)-1,-1,-1): + status, output = exec_cmd("rmmod "+drivers[i], 1) + if status: + print output + if FORCE == 0: + return status + return + +def device_found(): + ret1, log = exec_cmd("ls "+i2c_prefix+"i2c-0", 0) + return ret1 + +if __name__ == "__main__": + main() + + + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/LICENSE b/platform/broadcom/sonic-platform-modules-ruijie/LICENSE new file mode 100755 index 000000000000..68463127d0bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 Ruijie Network Corporation +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/LICENSE b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/LICENSE new file mode 100755 index 000000000000..68463127d0bf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 Ruijie Network Corporation +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/MAINTAINERS b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/MAINTAINERS new file mode 100755 index 000000000000..7b2f22c0328a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/MAINTAINERS @@ -0,0 +1,6 @@ +# This file describes the maintainers for sonic-platform-modules-ruijie +# See the SONiC project governance document for more information + +Name = "sonic_rd" +Email = "sonic_rd@ruijie.com.cn" +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/Makefile b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/Makefile new file mode 100755 index 000000000000..1b09fe02bf6e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/Makefile @@ -0,0 +1,22 @@ +PWD = $(shell pwd) +DIR_KERNEL_SRC = $(PWD)/modules/driver +EXTRA_CFLAGS:= -I$(M)/include +EXTRA_CFLAGS+= -Wall +SUB_BUILD_DIR = $(PWD)/build +INSTALL_DIR = $(SUB_BUILD_DIR)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) +INSTALL_SCRIPT_DIR = $(SUB_BUILD_DIR)/usr/local/bin + +KBUILD_EXTRA_SYMBOLS += $(DIR_KERNEL_SRC)/Module.symvers +export KBUILD_EXTRA_SYMBOLS + +all: + $(MAKE) -C $(KBUILD_OUTPUT) M=$(DIR_KERNEL_SRC) modules + @if [ ! -d ${INSTALL_DIR} ]; then mkdir -p ${INSTALL_DIR} ;fi + cp -r $(DIR_KERNEL_SRC)/*.ko $(INSTALL_DIR) + @if [ ! -d ${INSTALL_SCRIPT_DIR} ]; then mkdir -p ${INSTALL_SCRIPT_DIR} ;fi + cp -r $(PWD)/config/* $(INSTALL_SCRIPT_DIR) +clean: + rm -f ${DIR_KERNEL_SRC}/*.o ${DIR_KERNEL_SRC}/*.ko ${DIR_KERNEL_SRC}/*.mod.c ${DIR_KERNEL_SRC}/.*.cmd + rm -f ${DIR_KERNEL_SRC}/Module.markers ${DIR_KERNEL_SRC}/Module.symvers ${DIR_KERNEL_SRC}/modules.order + rm -rf ${DIR_KERNEL_SRC}/.tmp_versions + rm -rf $(SUB_BUILD_DIR) diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/README.md b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/README.md new file mode 100755 index 000000000000..b4dbacd5e466 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-ruijie +Device drivers for support of ruijie platform for the SONiC project diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/config/x86_64_ruijie_b6510_48vs8cq_r0_config.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/config/x86_64_ruijie_b6510_48vs8cq_r0_config.py new file mode 100755 index 000000000000..23684230f6d7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/config/x86_64_ruijie_b6510_48vs8cq_r0_config.py @@ -0,0 +1,787 @@ +#!/usr/bin/python3 +# -*- coding: UTF-8 -*- + +fancontrol_loc = "/usr/local/bin" +fancontrol_config_loc = "/usr/local/bin" + +GLOBALCONFIG = "GLOBALCONFIG" +MONITOR_CONST = "MONITOR_CONST" + +RUIJIE_PART_NUMBER = "RJ000001" +RUIJIE_LABEL_REVISION = "R01" +RUIJIE_ONIE_VERSION = "2018.02" +RUIJIE_MAC_SIZE = 3 +RUIJIE_MANUF_NAME = "Ruijie" +RUIJIE_MANUF_COUNTRY = "CHN" +RUIJIE_VENDOR_NAME = "Ruijie" +RUIJIE_DIAG_VERSION = "0.1.0.15" +RUIJIE_SERVICE_TAG = "www.ruijie.com.cn" + +DEV_LEDS = {} +MEM_SLOTS = [] + +LOCAL_LED_CONTROL = { + "CLOSE":{}, + "OPEN":{} +} + +FIRMWARE_TOOLS = {} + +################################################################################################### +##### fan board ID reference +################################################################################################### +FANS_DEF = { + 0x8100:"M6500-FAN-F", + 0x8101:"M6510-FAN-F", + 0x8102:"M6520-FAN-F", + 0x8103:"M6510-FAN-R" +} + +factest_module = { + "sysinfo_showfanmsg":1, + "sysinfo_showPsumsg":1, + "sysinfo_showrestfanmsg":0, + "sysinfo_showrestpsumsg":0 +} + +MONITOR_MAC_SOURCE_SYSFS = 0 #1 get mac temperature from sysfs ,0 get mac temperature from bcmcmd +MONITOR_MAC_SOURCE_PATH = None #sysfs path + +################################################################### + +SLOT_MONITOR_PARAM = {} + +FAN_PROTECT = {"bus":0, "devno":0x32, "addr":0x19, "open":0x00, "close":0x0f} +rg_eeprom = "2-0057/eeprom" +E2_LOC = {"bus":2, "devno":0x57} +E2_PROTECT ={"bus":2, "devno":0x33, "addr":0xb0, "open":0, "close":1} +MAC_LED_RESET = {"pcibus": 8, "slot": 0, "fn": 0, "bar": 0, "offset": 64, "reset": 0x98} + +PCA9548START = -1 +PCA9548BUSEND = -2 + + +RUIJIE_CARDID = 0x00004040 +RUIJIE_PRODUCTNAME = "B6510-48VS8CQ" + +STARTMODULE = { + "fancontrol":1, + "avscontrol":1, + "dev_monitor":1 +} + +i2ccheck_params = {"busend":"i2c-66","retrytime":6} + +DEV_MONITOR_PARAM = { + "polling_time": 10, + "psus": [ + { + "name": "psu1", + "present": { + "gettype": "i2c", + "bus": 2, + "loc": 0x37, + "offset": 0x51, + "presentbit": 0, + "okval": 0, + }, + "device": [ + { + "id": "psu1pmbus", + "name": "dps550", + "bus": 7, + "loc": 0x58, + "attr": "hwmon", + }, + ], + }, + { + "name": "psu2", + "present": { + "gettype": "i2c", + "bus": 2, + "loc": 0x37, + "offset": 0x51, + "presentbit": 4, + "okval": 0, + }, + "device": [ + { + "id": "psu2pmbus", + "name": "dps550", + "bus": 8, + "loc": 0x5B, + "attr": "hwmon", + }, + ], + }, + ], +} + +fanlevel = { + "tips":["low","medium","high"], + "level":[51,150,255], + "low_speed":[500,7500,17000], + "high_speed":[11000,22500,28500] +} + +fanloc =[ {"name":"FAN1/FAN2/FAN3/FAN4", "location":"0-0032/fan_speed_set", + "childfans":[{"name":"FAN1", "location":"2-0037/hwmon/hwmon4/fan1_input"}, + {"name":"FAN2", "location":"2-0037/hwmon/hwmon4/fan2_input"}, + {"name":"FAN3", "location":"2-0037/hwmon/hwmon4/fan3_input"}, + {"name":"FAN4", "location":"2-0037/hwmon/hwmon4/fan4_input"} ]}, + ] + + +#################FAN-Speed-Adjustment-Parameters############################## +MONITOR_TEMP_MIN = 38 # temperature before speed-adjsutment +MONITOR_K = 11 # speed-adjustment algorithm +MONITOR_MAC_IN = 35 # temperature difference between mac and chip +MONITOR_DEFAULT_SPEED = 0x60 # default speed +MONITOR_MAX_SPEED = 0xFF # maximum speed +MONITOR_MIN_SPEED = 0x33 # minimum speed +MONITOR_MAC_ERROR_SPEED = 0XBB # MAC abnormal speed +MONITOR_FAN_TOTAL_NUM = 4 # 3+1 redundancy design, report to syslog if there exists a error +MONITOR_MAC_UP_TEMP = 50 # MAC compared with temperature inlet up +MONITOR_MAC_LOWER_TEMP = -50 # MAC compared with temperature outlet down +MONITOR_MAC_MAX_TEMP = 100 # + +MONITOR_FALL_TEMP = 4 # speed-adjustment reduced temperature +MONITOR_MAC_WARNING_THRESHOLD = 100 #100 +MONITOR_OUTTEMP_WARNING_THRESHOLD = 85 +MONITOR_BOARDTEMP_WARNING_THRESHOLD = 85 +MONITOR_CPUTEMP_WARNING_THRESHOLD = 85 +MONITOR_INTEMP_WARNING_THRESHOLD = 70 #70 + +MONITOR_MAC_CRITICAL_THRESHOLD = 105 #105 +MONITOR_OUTTEMP_CRITICAL_THRESHOLD = 90 #90 +MONITOR_BOARDTEMP_CRITICAL_THRESHOLD = 90 #90 +MONITOR_CPUTEMP_CRITICAL_THRESHOLD = 100 #100 +MONITOR_INTEMP_CRITICAL_THRESHOLD = 80 # 80 +MONITOR_CRITICAL_NUM = 3 #retry times +MONITOR_SHAKE_TIME = 20 #anti-shake intervals +MONITOR_INTERVAL = 60 + +MONITOR_SYS_LED = [ + {"bus":2,"devno":0x33, "addr":0xb2, "yellow":0x03, "red":0x02,"green":0x01}, + {"bus":2,"devno":0x37, "addr":0xb2, "yellow":0x03, "red":0x02,"green":0x01}] + +MONITOR_SYS_FAN_LED =[ + {"bus":2,"devno":0x33, "addr":0xb4, "yellow":0x06, "red":0x02,"green":0x04}, + ] +MONITOR_FANS_LED = [ + {"bus":2,"devno":0x32, "addr":0x23, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x24, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x25, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x26, "green":0x09, "red":0x0a}] + + +CPLDVERSIONS = [ + {"bus":2, "devno":0x33, "name":"MAC board CPLD-A"}, + {"bus":2, "devno":0x35, "name":"MAC board CPLD-B"}, + {"bus":2, "devno":0x37, "name":"CONNECT board CPLD-A"}, + {"bus":0, "devno":0x0d, "name":"CPU board CPLD"}, +] + +MONITOR_SYS_PSU_LED =[ + {"bus":2,"devno":0x33, "addr":0xb3, "yellow":0x06, "red":0x02,"green":0x04}, + ] + +MONITOR_FAN_STATUS = [ + {'status':'green', 'minOkNum':4,'maxOkNum':4}, + {'status':'yellow', 'minOkNum':3,'maxOkNum':3}, + {'status':'red' , 'minOkNum':0,'maxOkNum':2}, + ] + +MONITOR_PSU_STATUS = [ + {'status':'green', 'minOkNum':2,'maxOkNum':2}, + {'status':'yellow', 'minOkNum':1,'maxOkNum':1}, + {'status':'red' , 'minOkNum':0,'maxOkNum':0}, + ] + + +MONITOR_DEV_STATUS = { + "temperature": [ + {"name":"lm75in", "location":"/sys/bus/i2c/devices/2-0048/hwmon/*/temp1_input"}, + {"name":"lm75out", "location":"/sys/bus/i2c/devices/2-0049/hwmon/*/temp1_input"}, + {"name":"lm75hot", "location":"/sys/bus/i2c/devices/2-004a/hwmon/*/temp1_input"}, + {"name":"cpu", "location":"/sys/class/hwmon/hwmon0"}, + ], + "fans": [ + { + "name":"fan1", + "presentstatus":{"bus":2, "loc":0x37, "offset":0x30, 'bit':0}, + "rollstatus": [ + {"name":"motor1","bus":2, "loc":0x37, "offset":0x31, 'bit':0}, + ] + }, + { + "name":"fan2", + "presentstatus":{"bus":2, "loc":0x37, "offset":0x30, 'bit':1}, + "rollstatus":[ + {"name":"motor1","bus":2, "loc":0x37, "offset":0x31, 'bit':1}, + ] + }, + { + "name":"fan3", + "presentstatus":{"bus":2, "loc":0x37, "offset":0x30, 'bit':2}, + "rollstatus":[ + {"name":"motor1","bus":2, "loc":0x37, "offset":0x31, 'bit':2}, + ] + }, + { + "name":"fan4", + "presentstatus":{"bus":2, "loc":0x37, "offset":0x30, 'bit':3}, + "rollstatus":[ + {"name":"motor1","bus":2, "loc":0x37, "offset":0x31, 'bit':3}, + ] + }, + ], + "psus": [ + {"name":"psu1", "bus":2, "loc":0x37, "offset":0x51, "gettype":"i2c", 'presentbit': 0, 'statusbit':1,'alertbit':2}, + {"name":"psu2", "bus":2, "loc":0x37, "offset":0x51, "gettype":"i2c", 'presentbit': 4, 'statusbit':5,'alertbit':6}, + ], + "mac_temp" : { + "flag" : {"bus":2, "loc":0x33, "offset":0xd4, "gettype":"i2c", 'okbit': 0, 'okval':1}, + "loc" : [ + "2-0035/mac_temp_input", + ], + "try_bcmcmd" : 0, + }, +} + +MONITOR_DEV_STATUS_DECODE = { + 'fanpresent': {0:'PRESENT', 1:'ABSENT', 'okval':0}, + 'fanroll' : {0:'STALL' , 1:'ROLL', 'okval':1}, + 'psupresent': {0:'PRESENT', 1:'ABSENT', 'okval':0}, + 'psuoutput' : {0:'FAULT' , 1:'NORMAL', 'okval':1}, + 'psualert' : {0:'FAULT' , 1:'NORMAL', 'okval':1}, +} +################################################################### + + +#####################MAC-Voltage-Adjustment-Parameters(B6510)#################################### +MAC_AVS_PARAM ={ + 0x72:0x0384, + 0x73:0x037e, + 0x74:0x0378, + 0x75:0x0372, + 0x76:0x036b, + 0x77:0x0365, + 0x78:0x035f, + 0x79:0x0359, + 0x7a:0x0352, + 0x7b:0x034c, + 0x7c:0x0346, + 0x7d:0x0340, + 0x7e:0x0339, + 0x7f:0x0333, + 0x80:0x032d, + 0x81:0x0327, + 0x82:0x0320, + 0x83:0x031a, + 0x84:0x0314, + 0x85:0x030e, + 0x86:0x0307, + 0x87:0x0301, + 0x88:0x02fb, + 0x89:0x02f5, + 0x8A:0x02ee +} +# 6510 Default Configuration +MAC_DEFAULT_PARAM = { + "type": 1, # type 1 represents default if out of range / 0 represents no voltage-adjustment if out of range + "default":0x74, # should be used with type + "loopaddr":0x00, # AVS loop address + "loop":0x00, # AVS loop value + "open":0x00, # diasble write-protection value + "close":0x40, # enable write-protection value + "bus":2, # AVSI2C bus address + "devno":0x60, # AVS address + "addr":0x21, # AVS voltage-adjustment address + "protectaddr":0x10, # AVS write-protection address + "sdkreg":"TOP_AVS_SEL_REG", # SDK register name + "sdktype": 0, # type 0 represents no shift operation / 1 represents shift operation + "macregloc":24, # shift operation + "mask": 0xff # mask after shift +} +#####################MAC-Voltage-Adjustment-Parameters#################################### + +## Drivers List +## +DRIVERLISTS = [ + {"name":"i2c_dev", "delay":0}, + {"name":"i2c_gpio", "delay":0}, + {"name":"i2c_algo_bit","delay":0}, + {"name":"i2c_mux_pca9641", "delay":0}, + {"name":"i2c_mux_pca954x force_create_bus=1", "delay":0},# force_deselect_on_exit=1 + {"name":"i2c_mux", "delay":0}, + {"name":"lm75", "delay":0}, + {"name":"optoe", "delay":0}, + {"name":"at24", "delay":0}, + {"name":"ruijie_platform", "delay":0}, + {"name":"rg_cpld", "delay":0}, + {"name":"rg_fan", "delay":0}, + {"name":"rg_psu", "delay":0}, + {"name":"pmbus_core", "delay":0}, + {"name":"csu550", "delay":0}, + {"name":"rg_gpio_xeon", "delay":0}, + {"name":"ipmi_devintf", "delay":0}, + {"name":"ipmi_si", "delay":0}, + {"name":"ipmi_msghandler", "delay":0}, +] + +DEVICE = [ + {"name":"pca9541","bus":0,"loc":0x10 }, + {"name":"pca9548","bus":2,"loc":0x70 }, + {"name":"lm75","bus": 2, "loc":0x48 }, + {"name":"lm75","bus": 2, "loc":0x49 }, + {"name":"lm75","bus": 2, "loc":0x4a }, + {"name":"24c02","bus":2, "loc":0x57 }, + {"name":"rg_cpld","bus":0,"loc":0x32 }, + {"name":"rg_cpld","bus":1,"loc":0x34 }, + {"name":"rg_cpld","bus":1,"loc":0x36 }, + {"name":"rg_cpld","bus":2,"loc":0x33 }, + {"name":"rg_cpld","bus":2,"loc":0x35 }, + {"name":"rg_cpld","bus":2,"loc":0x37 }, + {"name":"pca9548","bus":1,"loc":0x70 }, + {"name":"pca9548","bus":1,"loc":0x71 }, + {"name":"pca9548","bus":1,"loc":0x72 }, + {"name":"pca9548","bus":1,"loc":0x73 }, + {"name":"pca9548","bus":1,"loc":0x74 }, + {"name":"pca9548","bus":1,"loc":0x75 }, + {"name":"pca9548","bus":1,"loc":0x76 }, + {"name":"rg_fan","bus":3,"loc":0x53 }, + {"name":"rg_fan","bus":4,"loc":0x53 }, + {"name":"rg_fan","bus":5,"loc":0x53 }, + {"name":"rg_fan","bus":6,"loc":0x53 }, + {"name":"rg_psu","bus":7,"loc":0x50 }, + {"name":"dps550","bus":7,"loc":0x58 }, + {"name":"rg_psu","bus":8,"loc":0x53 }, + {"name":"dps550","bus":8,"loc":0x5b }, +] + +INIT_PARAM = [ + {"loc":"1-0034/sfp_enable","value": "01"}, + {"loc":"2-0035/sfp_enable2","value":"ff"}, + {"loc":"2-0033/mac_led", "value":"ff"}, + {"loc":"1-0034/sfp_txdis1","value":"00"}, + {"loc":"1-0034/sfp_txdis2","value":"00"}, + {"loc":"1-0034/sfp_txdis3","value":"00"}, + {"loc":"1-0036/sfp_txdis4","value":"00"}, + {"loc":"1-0036/sfp_txdis5","value":"00"}, + {"loc":"1-0036/sfp_txdis6","value":"00"}, + {"loc":fanloc[0]["location"], "value":"80"}, + {"loc":"2-0033/sfp_led1_yellow","value":"ad"}, + {"loc":"2-0035/sfp_led2_yellow","value":"ad"}, +] + +INIT_COMMAND = [ +] + +## Driver List +## + +#####################FRU-Info-Adaption################################# +E2TYPE = {"1": "tlveeprom", + "2": "x86cpueeprom", + "3": "bmceeprom", + "4": "cpueeprom", + "5": "maceeprom", + "6": "sloteeprom", + "7": "fanconnecteeprom", + "8": "M1HFANI-F", + "9": "M1HFANI-R", + "A": "M2HFANI-F", + "B": "M2HFANI-R", + "C": "psu"} +FRULISTS = [] +################################Manufacturing-Test-Adaption-Area####################################################### +# need to export interface +fanlevel_6510 = { + "level":[51,150,255], + "low_speed":[500,7500,17000], + "high_speed":[11000,22500,28500] +} + +fanlevel_6520 = { + "level":[75,150,255], + "low_speed":[750,4250,6750], + "high_speed":[4500,7500,10000] +} + +TEMPIDCHANGE = { + "lm75in":"inlet", + "lm75out":"outlet", + "lm75hot":"hot-point", + "inlet":"lm75in", + "outlet":"lm75out", + "hot-point":"lm75hot", +} + +# Manufacturing-Test module +FACTESTMODULE = { } + +##################################Manufacturing-Test-Menu +item1 = {"name":"Single Test", "deal" :"test_signal", "childid":1} +test_sys_reload_item = {"name":"reset-system", "deal" :"test_sys_reload"} + +test_sys_item = { "name":"Product information test", "deal" :"test_sysinfo"} +test_temp_item = { "name":"temperature test", "deal" :"test_tempinfo"} +test_mem_item = { "name":"Memory test", "deal" :"test_cpumemoryinfo"} +test_hd_item = { "name":"Hard disk test", "deal" :"test_hard"} +test_rtc_item = { "name":"RTC test ", "deal" :"test_rtc"} +test_i2c_item = { "name":"I2c test ", "deal" :"test_i2c"} +test_cpld_item = { "name":"CPLD test", "deal" :"test_cpld"} +test_portframe_item = { "name":"Port transmit-receive frame test", "deal" :"test_portframe"} +test_sysled_item = { "name":"System led test", "deal" :"test_led"} +test_fan_item = { "name":"Fan status test", "deal" :"test_fan"} +test_power_item = { "name":"PSU status test", "deal" :"test_power"} +test_usb_item = { "name":"USB test", "deal" :"test_usb"} +test_prbs_item = { "name":"PRBS test", "deal" :"test_prbs"} +test_portbroadcast_item = { "name":"Port broadcast", "deal" :"test_portbroadcast"} + +test_debug_level = {"name":"Change debug level", "deal" :"test_setdebug"} +test_log_level = {"name":"Log output level", "deal" :"test_loginfolevel"} +test_setmac = {"name":"setmac", "deal" :"test_setmac"} +test_setrtc = {"name":"Set RTC", "deal" :"test_set_rtc"} + +log_level_critical = {"name":"CRITICAL", "deal" :"test_log_critical"} +log_level_debug = {"name":"DEBUG", "deal" :"test_log_debug"} +log_level_error = {"name":"ERROR", "deal" :"test_log_error"} +log_level_info = {"name":"INFO", "deal" :"test_log_info"} +log_level_notset = {"name":"NOTSET", "deal" :"test_log_notset"} +log_level_warning = {"name":"WARNING", "deal" :"test_log_warning"} + + +test_e2_setmac_item = {"name":"E2SETMAC", "deal" :"test_e2_setmac"} +test_bmc_setmac_item = {"name":"BMCSETMAC", "deal" :"test_bmc_setmac"} +test_fan_setmac_item = {"name":"fan SETMAC", "deal" :"test_fan_setmac"} + +alltest = [ + test_sys_item, + test_temp_item, + test_mem_item, + test_hd_item, + test_rtc_item, + test_i2c_item, + test_cpld_item, + test_portframe_item, + test_sysled_item, + test_fan_item, + test_power_item, + test_usb_item, + test_prbs_item, + test_portbroadcast_item + ] + +looptest = [ + test_sys_item, + test_temp_item, + test_mem_item, + test_hd_item, + test_rtc_item, + test_i2c_item, + test_cpld_item, + test_portframe_item, + test_fan_item, + test_power_item, + test_usb_item, + test_prbs_item, + test_portbroadcast_item , +] + +diagtestall = [ +] + +menuList =[ + { + "menuid":0, "value":[ + {"name":"Single test", "deal" :"test_signal", "childid":1}, + {"name":"All test", "deal" :"test_all"}, + {"name":"Loop test", "deal" :"test_loop"}, + #{"name":"Check loop-test result", "deal" :"test_loop_read"}, + #{"name":"Delete loop-test result", "deal" :"test_loop_delete"}, +# {"name":"Load configuration", "deal" :"test_config"}, + test_sys_reload_item, + {"name":"System Configuration", "deal" :"test_sysconfig","childid":2}, + ] + }, + { + "menuid":1, "parentid":0, "value":[ + test_sys_item , + test_temp_item , + test_mem_item , + test_hd_item , + test_rtc_item , + test_i2c_item , + test_cpld_item , + test_portframe_item , + test_sysled_item , + test_fan_item , + test_power_item , + test_usb_item , + test_prbs_item , + test_portbroadcast_item , + ]}, + { + "menuid":2, "parentid":0, "value":[ + test_debug_level, + test_log_level , + test_setmac , + test_setrtc , + ]}, + { + "menuid":3, "parentid":2, "value":[ + log_level_critical , + log_level_debug , + log_level_error , + log_level_info , + log_level_notset , + log_level_warning , + ]}, + { + "menuid":4, "parentid":2, "value":[ + test_e2_setmac_item , + test_bmc_setmac_item, + test_fan_setmac_item, + ]}, +] + + +TESTCASE={ + "CPLD":[ + {"name":"CONNECT BOARD CPLD-A" ,"cases":[ + {"name":"cpld32", "cmd":"grtd_test.py cpld_check 0 0x32 0xAA"}, + {"name":"cpld37", "cmd":"grtd_test.py cpld_check 2 0x37 0xAC"}, + ] + }, + {"name":"MAC BOARD CPLD-A" ,"cases":[ + {"name":"cpld33", "cmd":"grtd_test.py cpld_check 2 0x33 0xAB"}, + {"name":"cpld34", "cmd":"grtd_test.py cpld_check 1 0x34 0xAA"}, + ] + }, + {"name":"MAC BOARD CPLD-B" ,"cases":[ + {"name":"cpld36", "cmd":"grtd_test.py cpld_check 1 0x36 0xAA"}, + {"name":"cpld35", "cmd":"grtd_test.py cpld_check 2 0x35 0xAB"}, + ] + }, + ], + "TEMPERATURE":[ + { + "name":"-->temperature test" , "cases":[ + {"name":"inlet","cmd":"grtd_test.py temp 2-0048/hwmon/hwmon1/temp1_input"}, + {"name":"outlet","cmd":"grtd_test.py temp 2-0049/hwmon/hwmon2/temp1_input"}, + {"name":"hot-point","cmd":"grtd_test.py temp 2-004a/hwmon/hwmon3/temp1_input"}, + ] + } + ], + "MEMTORY":{ + "cases":[ + {"name":"->memory test 1M","cmd":"memtester 1M 1"}, + {"name":"->memory test 2M","cmd":"memtester 2M 1"}, + {"name":"->memory test 8M","cmd":"memtester 8M 1"}, +# {"name":"->memory test 16M","cmd":"memtester 16M 1"}, +# {"name":"->memory test 256M","cmd":"memtester 256M 1"}, + ] + }, + "SMARTCTLCMDS":{ + "cases":[ + {"name":"->Check Hard Disk Info", "cmd":"smartctl -i /dev/sda"}, + {"name":"->Check Hard Disk Monitor Status", "cmd":"smartctl -H /dev/sda"}, + ] + }, + "LED":[ + {"name":"Light Port Led test","cases":[ + {"name":"-> Red Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + {"name":"-> Red Led On", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff"}, + {"name":"-> Recovery Red Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + + {"name":"-> Yellow Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + {"name":"-> Yellow Led On", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff"}, + {"name":"-> Recovery Yellow Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + ] + }, + {"name":"fan 1 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x09"}, + ] + }, + {"name":"fan 2 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x09"}, + ] + }, + {"name":"fan 3 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x09"}, + ] + }, + {"name":"Front panel CPU Led", "cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x00"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x02"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x03"}, + {"name":"-> Green Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x11"}, + {"name":"-> Green Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x21"}, + {"name":"-> Green Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x41"}, + {"name":"-> Green Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x81"}, + {"name":"-> Red Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x12"}, + {"name":"-> Red Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x22"}, + {"name":"-> Red Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x42"}, + {"name":"-> Red Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x82"}, + {"name":"-> Yellow Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x13"}, + {"name":"-> Yellow Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x23"}, + {"name":"-> Yellow Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x43"}, + {"name":"-> Yellow Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x83"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x01"}, + ] + }, + {"name":"Front panel BMC Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x04"}, + ] + }, + {"name":"Front panel location Led" , "cases":[ + {"name":"-> LedOff","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xff"}, + {"name":"-> LedOn","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xfe"}, + {"name":"->Recovery LedOff","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xff"}, + ] + }, + + {"name":"Front panel pwr Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x04"}, + ] + }, + {"name":"Front panel fan Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x04"}, + ] + }, + + ], + "I2C":[ + ####type 1 represents value obtained compated with value + ####type 2 represents return True or False + {"name":"I2C device test" ,"cases":[ + {"name":" PCA9641 test", "cmd":"grtd_test.py dev_rd 0 10 0","deal_type":2}, + {"name":" cpld32 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld33 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld34 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld35 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld36 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld37 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" inlet LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" outlet LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" hot-point LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" EEPROM", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" Port 1", "cmd":"grtd_test.py dev_rd 11 0050 0","deal_type":2}, + {"name":" Port 2", "cmd":"grtd_test.py dev_rd 12 0050 0","deal_type":2}, + {"name":" Port 3", "cmd":"grtd_test.py dev_rd 13 0050 0","deal_type":2}, + {"name":" Port 4", "cmd":"grtd_test.py dev_rd 14 0050 0","deal_type":2}, + {"name":" Port 5", "cmd":"grtd_test.py dev_rd 15 0050 0","deal_type":2}, + {"name":" Port 6", "cmd":"grtd_test.py dev_rd 16 0050 0","deal_type":2}, + {"name":" Port 7", "cmd":"grtd_test.py dev_rd 17 0050 0","deal_type":2}, + {"name":" Port 8", "cmd":"grtd_test.py dev_rd 18 0050 0","deal_type":2}, + {"name":" Port 9", "cmd":"grtd_test.py dev_rd 19 0050 0","deal_type":2}, + {"name":" Port 10", "cmd":"grtd_test.py dev_rd 20 0050 0","deal_type":2}, + {"name":" Port 11", "cmd":"grtd_test.py dev_rd 21 0050 0","deal_type":2}, + {"name":" Port 12", "cmd":"grtd_test.py dev_rd 22 0050 0","deal_type":2}, + {"name":" Port 13", "cmd":"grtd_test.py dev_rd 23 0050 0","deal_type":2}, + {"name":" Port 14", "cmd":"grtd_test.py dev_rd 24 0050 0","deal_type":2}, + {"name":" Port 15", "cmd":"grtd_test.py dev_rd 25 0050 0","deal_type":2}, + {"name":" Port 16", "cmd":"grtd_test.py dev_rd 26 0050 0","deal_type":2}, + {"name":" Port 17", "cmd":"grtd_test.py dev_rd 27 0050 0","deal_type":2}, + {"name":" Port 18", "cmd":"grtd_test.py dev_rd 28 0050 0","deal_type":2}, + {"name":" Port 19", "cmd":"grtd_test.py dev_rd 29 0050 0","deal_type":2}, + {"name":" Port 20", "cmd":"grtd_test.py dev_rd 30 0050 0","deal_type":2}, + {"name":" Port 21", "cmd":"grtd_test.py dev_rd 31 0050 0","deal_type":2}, + {"name":" Port 22", "cmd":"grtd_test.py dev_rd 32 0050 0","deal_type":2}, + {"name":" Port 23", "cmd":"grtd_test.py dev_rd 33 0050 0","deal_type":2}, + {"name":" Port 24", "cmd":"grtd_test.py dev_rd 34 0050 0","deal_type":2}, + {"name":" Port 25", "cmd":"grtd_test.py dev_rd 35 0050 0","deal_type":2}, + {"name":" Port 26", "cmd":"grtd_test.py dev_rd 36 0050 0","deal_type":2}, + {"name":" Port 27", "cmd":"grtd_test.py dev_rd 37 0050 0","deal_type":2}, + {"name":" Port 28", "cmd":"grtd_test.py dev_rd 38 0050 0","deal_type":2}, + {"name":" Port 29", "cmd":"grtd_test.py dev_rd 39 0050 0","deal_type":2}, + {"name":" Port 30", "cmd":"grtd_test.py dev_rd 40 0050 0","deal_type":2}, + {"name":" Port 31", "cmd":"grtd_test.py dev_rd 41 0050 0","deal_type":2}, + {"name":" Port 32", "cmd":"grtd_test.py dev_rd 42 0050 0","deal_type":2}, + {"name":" Port 33", "cmd":"grtd_test.py dev_rd 43 0050 0","deal_type":2}, + {"name":" Port 34", "cmd":"grtd_test.py dev_rd 44 0050 0","deal_type":2}, + {"name":" Port 35", "cmd":"grtd_test.py dev_rd 45 0050 0","deal_type":2}, + {"name":" Port 36", "cmd":"grtd_test.py dev_rd 46 0050 0","deal_type":2}, + {"name":" Port 37", "cmd":"grtd_test.py dev_rd 47 0050 0","deal_type":2}, + {"name":" Port 38", "cmd":"grtd_test.py dev_rd 48 0050 0","deal_type":2}, + {"name":" Port 39", "cmd":"grtd_test.py dev_rd 49 0050 0","deal_type":2}, + {"name":" Port 40", "cmd":"grtd_test.py dev_rd 50 0050 0","deal_type":2}, + {"name":" Port 41", "cmd":"grtd_test.py dev_rd 51 0050 0","deal_type":2}, + {"name":" Port 42", "cmd":"grtd_test.py dev_rd 52 0050 0","deal_type":2}, + {"name":" Port 43", "cmd":"grtd_test.py dev_rd 53 0050 0","deal_type":2}, + {"name":" Port 44", "cmd":"grtd_test.py dev_rd 54 0050 0","deal_type":2}, + {"name":" Port 45", "cmd":"grtd_test.py dev_rd 55 0050 0","deal_type":2}, + {"name":" Port 46", "cmd":"grtd_test.py dev_rd 56 0050 0","deal_type":2}, + {"name":" Port 47", "cmd":"grtd_test.py dev_rd 57 0050 0","deal_type":2}, + {"name":" Port 48", "cmd":"grtd_test.py dev_rd 58 0050 0","deal_type":2}, + {"name":" Port 49", "cmd":"grtd_test.py dev_rd 59 0050 0","deal_type":2}, + {"name":" Port 50", "cmd":"grtd_test.py dev_rd 60 0050 0","deal_type":2}, + {"name":" Port 51", "cmd":"grtd_test.py dev_rd 61 0050 0","deal_type":2}, + {"name":" Port 52", "cmd":"grtd_test.py dev_rd 62 0050 0","deal_type":2}, + {"name":" Port 53", "cmd":"grtd_test.py dev_rd 63 0050 0","deal_type":2}, + {"name":" Port 54", "cmd":"grtd_test.py dev_rd 64 0050 0","deal_type":2}, + {"name":" Port 55", "cmd":"grtd_test.py dev_rd 65 0050 0","deal_type":2}, + {"name":" Port 56", "cmd":"grtd_test.py dev_rd 66 0050 0","deal_type":2}, + {"name":" Port 57", "cmd":"grtd_test.py dev_rd 67 0050 0","deal_type":2}, + {"name":" Port 58", "cmd":"grtd_test.py dev_rd 68 0050 0","deal_type":2}, + {"name":" Port 59", "cmd":"grtd_test.py dev_rd 69 0050 0","deal_type":2}, + {"name":" Port 60", "cmd":"grtd_test.py dev_rd 70 0050 0","deal_type":2}, + {"name":" Port 61", "cmd":"grtd_test.py dev_rd 71 0050 0","deal_type":2}, + {"name":" Port 62", "cmd":"grtd_test.py dev_rd 72 0050 0","deal_type":2}, + {"name":" Port 63", "cmd":"grtd_test.py dev_rd 73 0050 0","deal_type":2}, + {"name":" Port 64", "cmd":"grtd_test.py dev_rd 74 0050 0","deal_type":2}, + ] + }, + ], +} + +PCIe_DEV_LIST = [] +PCIe_SPEED_ITEM = [] + +################################Manufacturing-Test-Adaption-Area####################################################### diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/Makefile b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/Makefile new file mode 100755 index 000000000000..f10216ec4d5a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/Makefile @@ -0,0 +1 @@ +obj-m := rg_cpld.o diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/rg_cpld.c b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/rg_cpld.c new file mode 100755 index 000000000000..0d890d5ba23b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/modules/driver/rg_cpld.c @@ -0,0 +1,602 @@ +/* + * rg_cpld.c - A driver for cpld + * + * Copyright (c) 2019 + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* debug level */ +typedef enum { + DBG_START, + DBG_VERBOSE, + DBG_KEY, + DBG_WARN, + DBG_ERROR, + DBG_END, +} dbg_level_t; + +static int debuglevel = 0; +module_param(debuglevel, int, S_IRUGO); + +#define DBG_DEBUG(fmt, arg...) do { \ + if ( debuglevel > DBG_START && debuglevel < DBG_ERROR) { \ + printk(KERN_INFO "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } else if ( debuglevel >= DBG_ERROR ) { \ + printk(KERN_ERR "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } else { } \ +} while (0) + +#define DBG_ERROR(fmt, arg...) do { \ + if ( debuglevel > DBG_START) { \ + printk(KERN_ERR "[ERROR]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \ + } \ +} while (0) + +static const unsigned short rg_i2c_cpld[] = { 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, I2C_CLIENT_END }; + +#define CPLD_SIZE 256 +#define CPLD_I2C_RETRY_TIMES 3 +#define READ_TEMP_FAIL 1000000 + +struct cpld_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[CPLD_SIZE]; /* Register value */ +}; + +static s32 cpld_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < CPLD_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_byte_data(client, command) ) >= 0 ) + break; + } + return ret; +} + +static s32 cpld_i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < CPLD_I2C_RETRY_TIMES; try++) { + if ((ret = i2c_smbus_read_i2c_block_data(client, command, length, values) ) >= 0 ) + break; + } + return ret; +} + +static ssize_t show_fan_rpm_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int index = to_sensor_dev_attr_2(da)->index; + uint8_t size; + s32 status; + s32 ret_t; + + ret_t = 0; + status = -1; + size = 0; + mutex_lock(&data->update_lock); + status = cpld_i2c_smbus_read_byte_data(client, index); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + data->data[0] = status; + status = cpld_i2c_smbus_read_byte_data(client, index + 1); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + data->data[1] = status; + DBG_DEBUG("cpld reg pos:0x%x value:0x%x\n", index, data->data[0]); + DBG_DEBUG("cpld reg pos:0x%x value:0x%x\n", index + 1, data->data[1]); + ret_t = (data->data[1] << 8) + data->data[0] ; + if (ret_t == 0 ) { + size = snprintf(buf, CPLD_SIZE, "%d\n", ret_t); + } else if (ret_t == 0xffff) { + size = snprintf(buf, CPLD_SIZE, "%d\n", 0); + } else { + size = snprintf(buf, CPLD_SIZE, "%d\n", 15000000 / ret_t); + } + mutex_unlock(&data->update_lock); + return size; +} + +static ssize_t set_cpld_sysfs_value(struct device *dev, struct device_attribute *da, const char *buf, size_t +count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + unsigned long val; + int err; + + err = kstrtoul(buf, 16, &val); + if (err) + return err; + if ((val < 0) || (val > 0xff)) { + DBG_ERROR("please enter 0x00 ~ 0xff\n"); + return -1; + } + mutex_lock(&data->update_lock); + data->data[0] = (u8)val; + DBG_DEBUG("pos: 0x%02x count = %ld, data = 0x%02x\n", attr->index, count, data->data[0]); + i2c_smbus_write_byte_data(client, attr->index, data->data[0]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + s32 status; + + status = -1; + mutex_lock(&data->update_lock); + status = cpld_i2c_smbus_read_i2c_block_data(client, 0, 4, data->data); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%02x %02x %02x %02x \n", data->data[0], data->data[1], data->data[2], + data->data[3]); +} + +static ssize_t show_cpld_sysfs_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + s32 status; + + status = -1; + mutex_lock(&data->update_lock); + status = cpld_i2c_smbus_read_byte_data(client, attr->index); + if (status < 0) { + mutex_unlock(&data->update_lock); + return 0; + } + data->data[0] = status; + DBG_DEBUG("cpld reg pos:0x%x value:0x%02x\n", attr->index, data->data[0]); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%02x\n", data->data[0]); +} + +static ssize_t show_mac_temp_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int index = to_sensor_dev_attr_2(da)->index; + int tmp_value, value; + s32 status; + + status = -1; + mutex_lock(&data->update_lock); + + status = cpld_i2c_smbus_read_byte_data(client, index); + if (status < 0) { + mutex_unlock(&data->update_lock); + return snprintf(buf, CPLD_SIZE, "%d\n", -READ_TEMP_FAIL); + } + data->data[0] = status; + status = cpld_i2c_smbus_read_byte_data(client, index + 1); + if (status < 0) { + mutex_unlock(&data->update_lock); + return snprintf(buf, CPLD_SIZE, "%d\n", -READ_TEMP_FAIL); + } + data->data[1] = status; + DBG_DEBUG("cpld reg pos:0x%x value:0x%x\n", index, data->data[0]); + DBG_DEBUG("cpld reg pos:0x%x value:0x%x\n", index + 1, data->data[1]); + mutex_unlock(&data->update_lock); + + tmp_value = (data->data[1] << 8) + data->data[0]; + if (tmp_value == 0) { + DBG_ERROR("invalid cpld value : %d.\n", tmp_value); + return snprintf(buf, CPLD_SIZE, "%d\n", -READ_TEMP_FAIL); + } + + DBG_DEBUG("tmp_value = 0x%x\n", tmp_value); + value = 434100 - (12500000 / (tmp_value * 100 - 1) *535); + if ((value / 1000 < -70) || (value / 1000 > 200)) { + return snprintf(buf, CPLD_SIZE, "%d\n", -READ_TEMP_FAIL); + } + + return snprintf(buf, CPLD_SIZE, "%d\n", value); + +} + +/* common */ +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO | S_IWUSR, show_cpld_version, NULL, 0); + +/*0x37 hwmon*/ +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO | S_IWUSR ,show_fan_rpm_value, NULL, 0x1B); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO | S_IWUSR ,show_fan_rpm_value, NULL, 0x1D); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO | S_IWUSR ,show_fan_rpm_value, NULL, 0x1F); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO | S_IWUSR ,show_fan_rpm_value, NULL, 0x21); + +/* 0x32 */ +static SENSOR_DEVICE_ATTR(fan_speed_set, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x15); +static SENSOR_DEVICE_ATTR(fan0_led, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x23); +static SENSOR_DEVICE_ATTR(fan1_led, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x24); +static SENSOR_DEVICE_ATTR(fan2_led, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x25); +static SENSOR_DEVICE_ATTR(fan3_led, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x26); + +/* 0x37 */ +static SENSOR_DEVICE_ATTR(fan_present, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, NULL, 0x30); +static SENSOR_DEVICE_ATTR(fan_status, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, NULL, 0x31); +static SENSOR_DEVICE_ATTR(psu_status, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, NULL, 0x51); +static SENSOR_DEVICE_ATTR(broad_back_lct, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x2a); +static SENSOR_DEVICE_ATTR(broad_back_sys, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xb2); + +/* 0x33 */ +static SENSOR_DEVICE_ATTR(mac_led, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa0); +static SENSOR_DEVICE_ATTR(broad_front_lct, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x2a); +static SENSOR_DEVICE_ATTR(broad_front_bmc, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xb1); +static SENSOR_DEVICE_ATTR(broad_front_cpu, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xb2); +static SENSOR_DEVICE_ATTR(broad_front_pwr, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xb3); +static SENSOR_DEVICE_ATTR(broad_front_fan, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xb4); +static SENSOR_DEVICE_ATTR(sfp_led1_yellow, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xad); +static SENSOR_DEVICE_ATTR(mac_temp_flag, S_IRUGO, show_cpld_sysfs_value, NULL, 0xd4); + +/* 0x34 */ +static SENSOR_DEVICE_ATTR(sfp_presence1, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, NULL, 0x30); +static SENSOR_DEVICE_ATTR(sfp_presence2, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, NULL, 0x31); +static SENSOR_DEVICE_ATTR(sfp_presence3, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, NULL, 0x32); + +static SENSOR_DEVICE_ATTR(sfp_enable, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa1); +static SENSOR_DEVICE_ATTR(sfp_led1, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa2); +static SENSOR_DEVICE_ATTR(sfp_led2, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa3); +static SENSOR_DEVICE_ATTR(sfp_led3, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa4); +static SENSOR_DEVICE_ATTR(sfp_led_flash1, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa5); +static SENSOR_DEVICE_ATTR(sfp_led_flash2, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa6); +static SENSOR_DEVICE_ATTR(sfp_led_flash3, S_IRUGO | S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa7); +static SENSOR_DEVICE_ATTR(sfp_txdis1, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x60); +static SENSOR_DEVICE_ATTR(sfp_txdis2, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x61); +static SENSOR_DEVICE_ATTR(sfp_txdis3, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0x62); + +static SENSOR_DEVICE_ATTR(port_speed1, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc0); +static SENSOR_DEVICE_ATTR(port_speed2, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc1); +static SENSOR_DEVICE_ATTR(port_speed3, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc2); +static SENSOR_DEVICE_ATTR(port_speed4, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc3); +static SENSOR_DEVICE_ATTR(port_speed5, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc4); +static SENSOR_DEVICE_ATTR(port_speed6, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc5); + +/* 0x35 */ +static SENSOR_DEVICE_ATTR(sfp_enable2, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa0); +static SENSOR_DEVICE_ATTR(sfp_led2_yellow, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xad); +static SENSOR_DEVICE_ATTR(mac_temp_input, S_IRUGO, show_mac_temp_value, NULL, 0xca); + +/* 0x36 */ +static SENSOR_DEVICE_ATTR(sfp_presence4, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, NULL, 0x30); +static SENSOR_DEVICE_ATTR(sfp_presence5, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, NULL, 0x31); +static SENSOR_DEVICE_ATTR(sfp_presence6, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, NULL, 0x32); +static SENSOR_DEVICE_ATTR(sfp_presence7, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, NULL, 0x33); +static SENSOR_DEVICE_ATTR(sfp_led4, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa2); +static SENSOR_DEVICE_ATTR(sfp_led5, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa3); +static SENSOR_DEVICE_ATTR(sfp_led6, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa4); +static SENSOR_DEVICE_ATTR(sfp_led7, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa5); +static SENSOR_DEVICE_ATTR(sfp_led_flash4, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa6); +static SENSOR_DEVICE_ATTR(sfp_led_flash5, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa7); +static SENSOR_DEVICE_ATTR(sfp_led_flash6, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa8); +static SENSOR_DEVICE_ATTR(sfp_led_flash7, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0xa9); + +static SENSOR_DEVICE_ATTR(sfp_txdis4, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0x60); +static SENSOR_DEVICE_ATTR(sfp_txdis5, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0x61); +static SENSOR_DEVICE_ATTR(sfp_txdis6, S_IRUGO | S_IWUSR ,show_cpld_sysfs_value, set_cpld_sysfs_value, 0x62); + +static SENSOR_DEVICE_ATTR(port_speed7, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc0); +static SENSOR_DEVICE_ATTR(port_speed8, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc1); +static SENSOR_DEVICE_ATTR(port_speed9, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc2); +static SENSOR_DEVICE_ATTR(port_speed10, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc3); +static SENSOR_DEVICE_ATTR(port_speed11, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc4); +static SENSOR_DEVICE_ATTR(port_speed12, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc5); +static SENSOR_DEVICE_ATTR(port_speed13, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc6); +static SENSOR_DEVICE_ATTR(port_speed14, S_IRUGO| S_IWUSR, show_cpld_sysfs_value, set_cpld_sysfs_value, 0xc7); + +static struct attribute *cpld32_sysfs_attrs[] = { + &sensor_dev_attr_fan_speed_set.dev_attr.attr, + &sensor_dev_attr_fan0_led.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &sensor_dev_attr_fan3_led.dev_attr.attr, + NULL +}; + +static struct attribute *cpld37_sysfs_attrs[] = { + &sensor_dev_attr_fan_present.dev_attr.attr, + &sensor_dev_attr_fan_status.dev_attr.attr, + &sensor_dev_attr_psu_status.dev_attr.attr, + &sensor_dev_attr_broad_back_lct.dev_attr.attr, + &sensor_dev_attr_broad_back_sys.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + NULL +}; + +static struct attribute *cpld33_sysfs_attrs[] = { + &sensor_dev_attr_mac_led.dev_attr.attr, + &sensor_dev_attr_broad_front_lct.dev_attr.attr, + &sensor_dev_attr_broad_front_bmc.dev_attr.attr, + &sensor_dev_attr_broad_front_cpu.dev_attr.attr, + &sensor_dev_attr_broad_front_pwr.dev_attr.attr, + &sensor_dev_attr_broad_front_fan.dev_attr.attr, + &sensor_dev_attr_sfp_led1_yellow.dev_attr.attr, + &sensor_dev_attr_mac_temp_flag.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + NULL +}; + +static struct attribute *cpld34_sysfs_attrs[] = { + &sensor_dev_attr_sfp_presence1.dev_attr.attr, + &sensor_dev_attr_sfp_presence2.dev_attr.attr, + &sensor_dev_attr_sfp_presence3.dev_attr.attr, + &sensor_dev_attr_sfp_enable.dev_attr.attr, + &sensor_dev_attr_sfp_led1.dev_attr.attr, + &sensor_dev_attr_sfp_led2.dev_attr.attr, + &sensor_dev_attr_sfp_led3.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash1.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash2.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash3.dev_attr.attr, + &sensor_dev_attr_sfp_txdis1.dev_attr.attr, + &sensor_dev_attr_sfp_txdis2.dev_attr.attr, + &sensor_dev_attr_sfp_txdis3.dev_attr.attr, + &sensor_dev_attr_port_speed1.dev_attr.attr, + &sensor_dev_attr_port_speed2.dev_attr.attr, + &sensor_dev_attr_port_speed3.dev_attr.attr, + &sensor_dev_attr_port_speed4.dev_attr.attr, + &sensor_dev_attr_port_speed5.dev_attr.attr, + &sensor_dev_attr_port_speed6.dev_attr.attr, + NULL +}; + +static struct attribute *cpld36_sysfs_attrs[] = { + &sensor_dev_attr_sfp_presence4.dev_attr.attr, + &sensor_dev_attr_sfp_presence5.dev_attr.attr, + &sensor_dev_attr_sfp_presence6.dev_attr.attr, + &sensor_dev_attr_sfp_presence7.dev_attr.attr, + &sensor_dev_attr_sfp_led4.dev_attr.attr, + &sensor_dev_attr_sfp_led5.dev_attr.attr, + &sensor_dev_attr_sfp_led6.dev_attr.attr, + &sensor_dev_attr_sfp_led7.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash4.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash5.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash6.dev_attr.attr, + &sensor_dev_attr_sfp_led_flash7.dev_attr.attr, + &sensor_dev_attr_sfp_txdis4.dev_attr.attr, + &sensor_dev_attr_sfp_txdis5.dev_attr.attr, + &sensor_dev_attr_sfp_txdis6.dev_attr.attr, + &sensor_dev_attr_port_speed7.dev_attr.attr, + &sensor_dev_attr_port_speed8.dev_attr.attr, + &sensor_dev_attr_port_speed9.dev_attr.attr, + &sensor_dev_attr_port_speed10.dev_attr.attr, + &sensor_dev_attr_port_speed11.dev_attr.attr, + &sensor_dev_attr_port_speed12.dev_attr.attr, + &sensor_dev_attr_port_speed13.dev_attr.attr, + &sensor_dev_attr_port_speed14.dev_attr.attr, + NULL +}; + +static struct attribute *cpld35_sysfs_attrs[] = { + &sensor_dev_attr_sfp_enable2.dev_attr.attr, + &sensor_dev_attr_broad_front_lct.dev_attr.attr, + &sensor_dev_attr_broad_front_bmc.dev_attr.attr, + &sensor_dev_attr_broad_front_cpu.dev_attr.attr, + &sensor_dev_attr_broad_front_pwr.dev_attr.attr, + &sensor_dev_attr_broad_front_fan.dev_attr.attr, + &sensor_dev_attr_sfp_led2_yellow.dev_attr.attr, + &sensor_dev_attr_mac_temp_input.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld32_sysfs_group = { + .attrs = cpld32_sysfs_attrs, +}; + +static const struct attribute_group cpld37_sysfs_group = { + .attrs = cpld37_sysfs_attrs, +}; + +static const struct attribute_group cpld33_sysfs_group = { + .attrs = cpld33_sysfs_attrs, +}; + +static const struct attribute_group cpld34_sysfs_group = { + .attrs = cpld34_sysfs_attrs, +}; + +static const struct attribute_group cpld36_sysfs_group = { + .attrs = cpld36_sysfs_attrs, +}; + +static const struct attribute_group cpld35_sysfs_group = { + .attrs = cpld35_sysfs_attrs, +}; + +static struct attribute *cpld_hwmon_attrs[] = { + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + NULL +}; +ATTRIBUTE_GROUPS(cpld_hwmon); + +struct cpld_attr_match_group { + int bus_nr; /* I2C BUS */ + unsigned short addr; /* slave addr*/ + const struct attribute_group *attr_group_ptr; + const struct attribute_group *attr_hwmon_ptr; +}; + +static struct cpld_attr_match_group g_cpld_attr_match[] = { + {0, 0x32, &cpld32_sysfs_group, NULL}, + {2, 0x37, &cpld37_sysfs_group, (struct attribute_group *)cpld_hwmon_groups}, + {2, 0x33, &cpld33_sysfs_group, NULL}, + {1, 0x34, &cpld34_sysfs_group, NULL}, + {1, 0x36, &cpld36_sysfs_group, NULL}, + {2, 0x35, &cpld35_sysfs_group, NULL}, +}; + +static const struct attribute_group *cpld_get_attr_group(struct i2c_client *client, int is_hwmon) +{ + int i; + struct cpld_attr_match_group *group; + + for (i = 0; i < ARRAY_SIZE(g_cpld_attr_match); i++) { + group = &g_cpld_attr_match[i]; + DBG_DEBUG("is_hwmon %d i %d client(nr:%d,addr:0x%x), group(nr:%d,addr:0x0%x).\n", is_hwmon, + i, client->adapter->nr, client->addr, group->bus_nr, group->addr); + if ((client->addr == group->addr) && (client->adapter->nr == group->bus_nr)) { + DBG_DEBUG("is_hwmon %d i %d nr %d addr %d .\n", is_hwmon, i, client->adapter->nr, client->addr); + return (is_hwmon) ? (group->attr_hwmon_ptr) : (group->attr_group_ptr); + } + } + + DBG_DEBUG("is_hwmon %d nr %d addr %d dismatch, return NULL.\n", is_hwmon, client->adapter->nr, client->addr); + return NULL; +} + +static int cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + const struct attribute_group *sysfs_group, *hwmon_group; + + status = -1; + DBG_DEBUG("=========cpld_probe(addr:0x%x, nr:%d)===========\n", client->addr, client->adapter->nr); + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + sysfs_group = NULL; + sysfs_group = cpld_get_attr_group(client, 0); + if (sysfs_group) { + status = sysfs_create_group(&client->dev.kobj, sysfs_group); + DBG_DEBUG("=========(addr:0x%x, nr:%d) sysfs_create_group status %d===========\n", client->addr, client->adapter->nr, status); + if (status != 0) { + DBG_ERROR("sysfs_create_group status %d.\n", status); + goto error; + } + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no sysfs_create_group \n", client->addr, client->adapter->nr); + } + + hwmon_group = NULL; + hwmon_group = cpld_get_attr_group(client, 1); + if (hwmon_group) { + data->hwmon_dev = hwmon_device_register_with_groups(&client->dev, client->name, data, (const struct attribute_group **)hwmon_group); + if (IS_ERR(data->hwmon_dev)) { + sysfs_remove_group(&client->dev.kobj, (const struct attribute_group *)sysfs_group); + DBG_ERROR("hwmon_device_register_with_groups failed ret %ld.\n", PTR_ERR(data->hwmon_dev)); + return PTR_ERR(data->hwmon_dev); + } + DBG_DEBUG("=========(addr:0x%x, nr:%d) hwmon_device_register_with_groups success===========\n", client->addr, client->adapter->nr); + if (status != 0) { + DBG_ERROR("sysfs_create_group status %d.\n", status); + goto error; + } + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no hwmon_device_register_with_groups \n", client->addr, client->adapter->nr); + } + +error: + return status; + +} + +static int cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *sysfs_group, *hwmon_group; + + DBG_DEBUG("=========cpld_remove(addr:0x%x, nr:%d)===========\n", client->addr, client->adapter->nr); + + sysfs_group = NULL; + sysfs_group = cpld_get_attr_group(client, 0); + if (sysfs_group) { + DBG_DEBUG("=========(addr:0x%x, nr:%d) do sysfs_remove_group \n", client->addr, client->adapter->nr); + sysfs_remove_group(&client->dev.kobj, (const struct attribute_group *)sysfs_group); + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no sysfs_remove_group \n", client->addr, client->adapter->nr); + } + + hwmon_group = NULL; + hwmon_group = cpld_get_attr_group(client, 1); + if (hwmon_group) { + DBG_DEBUG("=========(addr:0x%x, nr:%d) do hwmon_device_unregister \n", client->addr, client->adapter->nr); + hwmon_device_unregister(data->hwmon_dev); + } else { + DBG_DEBUG("=========(addr:0x%x, nr:%d) no hwmon_device_unregister \n", client->addr, client->adapter->nr); + } + + return 0; +} + + +static const struct i2c_device_id cpld_id[] = { + { "rg_cpld", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver rg_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "rg_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, +}; + +module_i2c_driver(rg_cpld_driver); + +MODULE_AUTHOR("sonic_rd "); +MODULE_DESCRIPTION("ruijie CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/scripts/b6510-48vs8cq_platform.sh b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/scripts/b6510-48vs8cq_platform.sh new file mode 100755 index 000000000000..c7833deeae19 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/scripts/b6510-48vs8cq_platform.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +#platform init script for B6510-48VS8CQ + +install_python_api_package() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + rv=$(pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl) +} + +remove_python_api_package() { + rv=$(pip show sonic-platform > /dev/null 2>/dev/null) + if [ $? -eq 0 ]; then + rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null) + fi +} + +if [[ "$1" == "init" ]]; then + echo "b6510 init" + install_python_api_package + +elif [[ "$1" == "deinit" ]]; then + remove_python_api_package +else + echo "B6510-48VS8CQ_PLATFORM : Invalid option !" +fi diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/setup.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/setup.py new file mode 100644 index 000000000000..2dfacd39b78a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/setup.py @@ -0,0 +1,34 @@ +from setuptools import setup + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on RUIJIE B6510 Platforms', + license='Apache 2.0', + author='SONiC Team', + author_email='sonic_rd@ruijie.com.cn', + url='', + maintainer='RUIJIE B6510', + maintainer_email='', + packages=[ + 'sonic_platform', + 'plat_hal', + 'rjutil', + 'eepromutil', + 'sonic_pcie' + ], + 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 :: 3.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/__init__.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/__init__.py new file mode 100644 index 000000000000..73e2a89c8d74 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/__init__.py @@ -0,0 +1 @@ +__all__ = ["pcie_common"] \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/pcie_common.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/pcie_common.py new file mode 100644 index 000000000000..56e9d8664a23 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_pcie/pcie_common.py @@ -0,0 +1,107 @@ +# pcie_common.py +# Common PCIE check interfaces for SONIC +# + +import os +import yaml +import subprocess +import re +import sys +from copy import deepcopy +try: + from .pcie import PcieBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PcieUtil(PcieBase): + """Platform-specific PCIEutil class""" + # got the config file path + def __init__(self, path): + self.config_path = path + + # load the config file + def load_config_file(self): + config_file = self.config_path + "/" + "pcie.yaml" + try: + with open(config_file) as conf_file: + self.confInfo = yaml.load(conf_file) + except IOError as e: + print("Error: {}".format(str(e))) + print("Not found config file, please add a config file manually, or generate it by running [pcieutil pcie_generate]") + sys.exit() + + # load current PCIe device + def get_pcie_device(self): + pciDict = {} + pciList = [] + p1 = "^(\w+):(\w+)\.(\w)\s(.*)\s*\(*.*\)*" + p2 = "^.*:.*:.*:(\w+)\s*\(*.*\)*" + command1 = "sudo lspci" + command2 = "sudo lspci -n" + # run command 1 + proc1 = subprocess.Popen(command1, shell=True, universal_newlines=True, stdout=subprocess.PIPE) + output1 = proc1.stdout.readlines() + proc1.communicate() + # run command 2 + proc2 = subprocess.Popen(command2, shell=True, universal_newlines=True, stdout=subprocess.PIPE) + output2 = proc2.stdout.readlines() + proc2.communicate() + + if proc1.returncode > 0: + for line1 in output1: + print(line1.strip()) + return + elif proc2.returncode > 0: + for line2 in output2: + print(line2.strip()) + return + else: + for (line1, line2) in zip(output1, output2): + pciDict.clear() + match1 = re.search(p1, line1.strip()) + match2 = re.search(p2, line2.strip()) + if match1 and match2: + Bus = match1.group(1) + Dev = match1.group(2) + Fn = match1.group(3) + Name = match1.group(4) + Id = match2.group(1) + pciDict["name"] = Name + pciDict["bus"] = Bus + pciDict["dev"] = Dev + pciDict["fn"] = Fn + pciDict["id"] = Id + pciList.append(pciDict) + pciDict = deepcopy(pciDict) + else: + print("CAN NOT MATCH PCIe DEVICE") + return pciList + + # check the sysfs tree for each PCIe device + def check_pcie_sysfs(self, domain=0, bus=0, device=0, func=0): + dev_path = os.path.join('/sys/bus/pci/devices', '%04x:%02x:%02x.%d' % (domain, bus, device, func)) + if os.path.exists(dev_path): + return True + return False + + # check the current PCIe device with config file and return the result + def get_pcie_check(self): + self.load_config_file() + for item_conf in self.confInfo: + bus_conf = item_conf["bus"] + dev_conf = item_conf["dev"] + fn_conf = item_conf["fn"] + if self.check_pcie_sysfs(bus=int(bus_conf, base=16), device=int(dev_conf, base=16), func=int(fn_conf, base=16)): + item_conf["result"] = "Passed" + else: + item_conf["result"] = "Failed" + return self.confInfo + + # generate the config file with current pci device + def dump_conf_yaml(self): + curInfo = self.get_pcie_device() + with open(self.config_path + "/" + "pcie.yaml", "w") as conf_file: + yaml.dump(curInfo, conf_file, default_flow_style=False) + return + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/__init__.py new file mode 100644 index 000000000000..f6c1757b8374 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/__init__.py @@ -0,0 +1 @@ +__all__ = ["platform", "chassis", "fan", "psu", "sfp", "thermal", "common"] diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/chassis.py new file mode 100644 index 000000000000..ea4048e19f6e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/chassis.py @@ -0,0 +1,448 @@ +# -*- coding: utf-8 -*- + +############################################################################# +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import time + import subprocess + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.common import Common + from sonic_platform.sfp import Sfp + from sonic_platform.sfp import PORT_START + from sonic_platform.sfp import PORTS_IN_BLOCK + from sonic_platform.logger import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Chassis(ChassisBase): + """ + Ruijie B6510-48VS8CQ Platform-specific Chassis class + """ + def __init__(self): + ChassisBase.__init__(self) + self.CHASSIS_CONFIG = 'chassis.json' + self.THERMAL_CONFIG = 'thermal.json' + self.SFP_CONFIG = 'sfp.json' + self.PSU_CONFIG = 'psu.json' + self.FAN_CONFIG = 'fan.json' + self.COMPONENT_CONFIG = 'component.json' + + self.SFP_STATUS_INSERTED = "1" + self.SFP_STATUS_REMOVED = "0" + self.port_dict = {} + self.enable_read= "i2cset -f -y 2 0x35 0x2a 0x01" + self.disable_read = "i2cset -f -y 2 0x35 0x2a 0x00" + self.enable_write = "i2cset -f -y 2 0x35 0x2b 0x00" + self.disable_write = "i2cset -f -y 2 0x35 0x2b 0x01" + self.enable_erase = "i2cset -f -y 2 0x35 0x2c 0x01" + self.disable_erase = "i2cset -f -y 2 0x35 0x2c 0x00" + self.read_value = "i2cget -f -y 2 0x35 0x25" + self.write_value = "i2cset -f -y 2 0x35 0x21 0x0a" + self.set_sys_led_cmd = "i2cset -f -y 2 0x33 0xb2 " + self.get_sys_led_cmd = "i2cget -f -y 2 0x33 0xb2" + self.led_status = "red" + # Initialize SFP list + # sfp.py will read eeprom contents and retrive the eeprom data. + # It will also provide support sfp controls like reset and setting + # low power mode. + # We pass the eeprom path and sfp control path from chassis.py + # So that sfp.py implementation can be generic to all platforms + for index in range(PORT_START, PORTS_IN_BLOCK): + sfp_node = Sfp(index) + self._sfp_list.append(sfp_node) + if sfp_node.get_presence(): + self.port_dict[index] = self.SFP_STATUS_INSERTED + else: + self.port_dict[index] = self.SFP_STATUS_REMOVED + + self._api_common = Common() + config_path = self._api_common.get_config_path(self.CHASSIS_CONFIG) + self._config = self._api_common.load_json_file(config_path) + self.__initialize_eeprom() + + if self._api_common.is_host(): + self.__initialize_fan() + self.__initialize_psu() + self.__initialize_thermals() + else: + self.__initialize_components() + + def __initialize_fan(self): + from sonic_platform.fan import Fan + from sonic_platform.fan_drawer import FanDrawer + + fan_config_path = self._api_common.get_config_path(self.FAN_CONFIG) + self.fan_config = self._api_common.load_json_file(fan_config_path)["fans"] + + if self.fan_config: + drawer_fan_list = [] + for index in range(0, len(self.fan_config)): + fan = Fan(index, config=self.fan_config[index]) + self._fan_list.append(fan) + drawer_fan_list.append(fan) + fan_drawer = FanDrawer(0, fan_list=drawer_fan_list) + self._fan_drawer_list.append(fan_drawer) + + def __initialize_psu(self): + from sonic_platform.psu import Psu + + psu_config_path = self._api_common.get_config_path(self.PSU_CONFIG) + self.psu_config = self._api_common.load_json_file(psu_config_path)["psus"] + + if self.psu_config: + for index in range(0, len(self.psu_config)): + psu = Psu(index, config=self.psu_config[index]) + self._psu_list.append(psu) + + def __initialize_thermals(self): + from sonic_platform.thermal import Thermal + + thermal_config_path = self._api_common.get_config_path(self.THERMAL_CONFIG) + self.thermal_config = self._api_common.load_json_file(thermal_config_path)['thermals'] + + if self.thermal_config: + for index in range(0, len(self.thermal_config)): + thermal = Thermal(index, config=self.thermal_config[index]) + self._thermal_list.append(thermal) + + def __initialize_eeprom(self): + from sonic_platform.eeprom import Eeprom + self._eeprom = Eeprom(config=self._config["eeprom"]) + + + def __initialize_components(self): + from sonic_platform.component import Component + + component_config_path = self._api_common.get_config_path(self.COMPONENT_CONFIG) + self.component_config = self._api_common.load_json_file(component_config_path)['components'] + + if self.component_config: + for index in range(0, len(self.component_config)): + component = Component(index, config=self.component_config[index]) + self._component_list.append(component) + + def _init_standard_config(self, conflist, class_name, objlist): + for conf in conflist: + obj = globals()[class_name](conf.get("name"), config=conf) + objlist.append(obj) + + def _init_by_hal(self, hal_interface): + self.hal_interface = hal_interface + self.hal_interface.get_fans() + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + try: + is_power_loss = False + # enable read + subprocess.getstatusoutput(self.disable_write) + subprocess.getstatusoutput(self.enable_read) + ret , log = subprocess.getstatusoutput(self.read_value) + if ret == 0 and "0x0a" in log: + is_power_loss = True + + # erase i2c and e2 + subprocess.getstatusoutput(self.enable_erase) + time.sleep(1) + subprocess.getstatusoutput(self.disable_erase) + # clear data + subprocess.getstatusoutput(self.enable_write) + subprocess.getstatusoutput(self.disable_read) + subprocess.getstatusoutput(self.disable_write) + subprocess.getstatusoutput(self.enable_read) + # enable write and set data + subprocess.getstatusoutput(self.enable_write) + subprocess.getstatusoutput(self.disable_read) + subprocess.getstatusoutput(self.write_value) + if is_power_loss: + return(self.REBOOT_CAUSE_POWER_LOSS, None) + except Exception as e: + logger.error(str(e)) + + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + Specifically for SFP event, besides SFP plug in and plug out, + there are some other error event could be raised from SFP, when + these error happened, SFP eeprom will not be avalaible, XCVRD shall + stop to read eeprom before SFP recovered from error status. + status='2' I2C bus stuck, + status='3' Bad eeprom, + status='4' Unsupported cable, + status='5' High Temperature, + status='6' Bad cable. + """ + change_event_dict = {"fan": {}, "sfp": {}} + sfp_status, sfp_change_dict = self.get_transceiver_change_event(timeout) + change_event_dict["sfp"] = sfp_change_dict + if sfp_status is True: + return True, change_event_dict + + return False, {} + + def get_transceiver_change_event(self, timeout=0): + + start_time = time.time() + currernt_port_dict = {} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print("get_transceiver_change_event:Invalid timeout value", timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print( + "get_transceiver_change_event:" "time wrap / invalid timeout value", + timeout, + ) + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + # Check for OIR events and return updated port_dict + for index in range(PORT_START, PORTS_IN_BLOCK): + if self._sfp_list[index].get_presence(): + currernt_port_dict[index] = self.SFP_STATUS_INSERTED + else: + currernt_port_dict[index] = self.SFP_STATUS_REMOVED + if currernt_port_dict == self.port_dict: + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + else: + # Update reg value + self.port_dict = currernt_port_dict + print(self.port_dict) + return True, self.port_dict + print("get_transceiver_change_event: Should not reach here.") + return False, {} + + def get_all_components(self): + return self._component_list + + def get_all_fans(self): + return self._fan_list + + def get_all_psus(self): + return self._psu_list + + def get_all_thermals(self): + return self._thermal_list + + def get_supervisor_slot(self): + """ + Retrieves the physical-slot of the supervisor-module in the modular + chassis. On the supervisor or line-card modules, it will return the + physical-slot of the supervisor-module. + On the fixed-platforms, the API can be ignored. + Users of the API can catch the exception and return a default + ModuleBase.MODULE_INVALID_SLOT and bypass code for fixed-platforms. + Returns: + An integer, the vendor specific physical slot identifier of the + supervisor module in the modular-chassis. + """ + return 0 + + def get_my_slot(self): + """ + Retrieves the physical-slot of this module in the modular chassis. + On the supervisor, it will return the physical-slot of the supervisor + module. On the linecard, it will return the physical-slot of the + linecard module where this instance of SONiC is running. + On the fixed-platforms, the API can be ignored. + Users of the API can catch the exception and return a default + ModuleBase.MODULE_INVALID_SLOT and bypass code for fixed-platforms. + Returns: + An integer, the vendor specific physical slot identifier of this + module in the modular-chassis. + """ + return 0 + + def is_modular_chassis(self): + """ + Retrieves whether the sonic instance is part of modular chassis + Returns: + A bool value, should return False by default or for fixed-platforms. + Should return True for supervisor-cards, line-cards etc running as part + of modular-chassis. + """ + return True + + def init_midplane_switch(self): + """ + Initializes the midplane functionality of the modular chassis. For + example, any validation of midplane, populating any lookup tables etc + can be done here. The expectation is that the required kernel modules, + ip-address assignment etc are done before the pmon, database dockers + are up. + Returns: + A bool value, should return True if the midplane initialized + successfully. + """ + return True + + def get_module_index(self, module_name): + """ + Retrieves module index from the module name + Args: + module_name: A string, prefixed by SUPERVISOR, LINE-CARD or FABRIC-CARD + Ex. SUPERVISOR0, LINE-CARD1, FABRIC-CARD5 + Returns: + An integer, the index of the ModuleBase object in the module_list + """ + return 0 + + def set_status_led(self, color): + """ + Sets the state of the system LED + Args: + color: A string representing the color with which to set the + system LED + Returns: + bool: True if system LED state is set successfully, False if not + """ + colors = { + "amber" : "0x00", + "red" : "0x02", + "green" : "0x04" + } + regval = colors.get(color, None) + if regval is None: + print("Invaild color input.") + return False + ret , log = subprocess.getstatusoutput(self.set_sys_led_cmd + regval) + if ret != 0: + print("Cannot execute %s" % self.set_sys_led_cmd + regval) + return False + self.led_status = color + return True + + def get_status_led(self): + """ + Gets the state of the system LED + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + ret , log = subprocess.getstatusoutput(self.get_sys_led_cmd) + if ret != 0: + print("Cannot execute %s" % self.get_sys_led_cmd) + return False + colors = { + "0x00" : "amber", + "0x02" : "red", + "0x04" : "green" + } + color = colors.get(log, None) + if color is None: + return "Unknown color status" + self.led_status = color + return self.led_status + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/common.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/common.py new file mode 100644 index 000000000000..c1a85f618609 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/common.py @@ -0,0 +1,44 @@ +import os +import yaml + +from sonic_py_common import device_info + + +class Common: + + DEVICE_PATH = '/usr/share/sonic/device/' + PMON_PLATFORM_PATH = '/usr/share/sonic/platform/' + CONFIG_DIR = 'sonic_platform_config' + + HOST_CHK_CMD = "docker > /dev/null 2>&1" + + def __init__(self): + (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() + + def is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def load_json_file(self, path): + """ + Retrieves the json object from json file path + + Returns: + A json object + """ + with open(path, 'r') as f: + json_data = yaml.safe_load(f) + + return json_data + + def get_config_path(self, config_name): + """ + Retrieves the path to platform api config directory + + Args: + config_name: A string containing the name of config file. + + Returns: + A string containing the path to json file + """ + return os.path.join(self.DEVICE_PATH, self.platform, self.CONFIG_DIR, config_name) if self.is_host() else os.path.join(self.PMON_PLATFORM_PATH, self.CONFIG_DIR, config_name) + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/component.py new file mode 100644 index 000000000000..33ff6ef8b35d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/component.py @@ -0,0 +1,85 @@ +######################################################################## +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import subprocess + from sonic_platform_base.component_base import ComponentBase + from sonic_platform.regutil import Reg + from sonic_platform.logger import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Component(ComponentBase): + """Ruijie Platform-specific Component class""" + + def __init__(self, index, config=None): + self.index = index + self.name = config.get("name") + self._reg_fm_ver = Reg(config.get("firmware_version")) + self.description = config.get("desc") + self.slot = config.get("slot") + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + try: + return self._reg_fm_ver.decode() + except Exception as e: + logger.error(str(e)) + + return "" + + 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 + """ + try: + successtips = "CPLD Upgrade succeeded!" + status, output = subprocess.getstatusoutput("which firmware_upgrade") + if status or len(output) <= 0: + logger.error("no upgrade tool.") + return False + cmdstr = "%s %s cpld %d cpld"%(output,image_path,self.slot) + ret, log = subprocess.getstatusoutput(cmdstr) + if ret == 0 and successtips in log: + return True + logger.error("upgrade failed. ret:%d, log:\n%s" % (ret, log)) + except Exception as e: + logger.error(str(e)) + return False + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/config.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/config.py new file mode 100644 index 000000000000..162f01680ad0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/config.py @@ -0,0 +1,558 @@ +# -*- coding: utf-8 -*- + +PSU_FAN_AIRFLOW = { + "CSU550AP-3-300": "F2B", + "AS-40FAN-01-F-RJ": "F2B", + "CSU550AP-3-500": "F2B", + "DPS-550AB-39 A": "F2B", + "DPS-1300AB-6 S": "F2B", + "FSP1200-20ERM": "F2B", + "CSU800AP-3-300": "F2B", + "CSU550AP-3-501": "B2F", + "DPS-550AB-40 A": "B2F", +} + +FAN_AIRFLOW = { + "AS-80FAN-01-F-RJ": "F2B", + "AS-40FAN-01-F-RJ": "F2B", + "AS-80FAN-01-R-RJ": "B2F", + "AS-40FAN-01-R-RJ": "B2F", +} + +psutypedecode = { + 0x00: "N/A", + 0x01: "AC", + 0x02: "DC", +} + + +class Unit: + Temperature = "C" + Voltage = "V" + Current = "A" + Power = "W" + Speed = "RPM" + + +class Threshold: + PSU_TEMP_MIN = -10 * 1000 + PSU_TEMP_MAX = 60 * 1000 + + PSU_FAN_SPEED_MIN = 2000 + PSU_FAN_SPEED_MAX = 28000 + + PSU_OUTPUT_VOLTAGE_MIN = 11 * 1000 + PSU_OUTPUT_VOLTAGE_MAX = 14 * 1000 + + PSU_AC_INPUT_VOLTAGE_MIN = 200 * 1000 + PSU_AC_INPUT_VOLTAGE_MAX = 240 * 1000 + + PSU_DC_INPUT_VOLTAGE_MIN = 190 * 1000 + PSU_DC_INPUT_VOLTAGE_MAX = 290 * 1000 + + ERR_VALUE = -9999999 + + PSU_OUTPUT_POWER_MIN = 10 * 1000 + PSU_OUTPUT_POWER_MAX = 1300 * 1000 + + PSU_INPUT_POWER_MIN = 10 * 1000 + PSU_INPUT_POWER_MAX = 1444 * 1000 + + PSU_OUTPUT_CURRENT_MIN = 2 * 1000 + PSU_OUTPUT_CURRENT_MAX = 107 * 1000 + + PSU_INPUT_CURRENT_MIN = 0.2 * 1000 + PSU_INPUT_CURRENT_MAX = 7 * 1000 + + FAN_SPEED_MAX = 23000 + FAN_SPEED_MIN = 500 + + +class DecodeFormat: + TEXT = 0 + DECIMAL = 1 + ONE_BIT_HEX = 2 + HUNDREDTH = 3 + THOUSANDTH = 4 + MILLIONTH = 5 + AND = 6 + JOIN = 7 + + +class DecodeMethod: + SYSFS = 0 + I2C = 1 + I2C_WORD = 2 + DEVMEM = 3 + SDK = 4 + + +class Description: + CPLD = "Used for managing IO modules, SFP+ modules and system LEDs" + BIOS = "Performs initialization of hardware components during booting" + FPGA = "Platform management controller for on-board temperature monitoring, in-chassis power, Fan and LED control" + + +FAN_LED_COLORS = { + "green": 0b1001, + "red": 0b1010, + "amber": 0b0011, +} + + +DEVICE_CONF = { + "eeprom": {"bus": 2, "loc": "0057"}, + "components": [ + { + "name": "CPLD1 (MAC Board A)", + "firmware_version": { + "bus": 2, + "addr": 0x33, + "offset": 0, + "size": 4, + "way": DecodeMethod.I2C, + "format": DecodeFormat.JOIN, + "sep": "/", + }, + "desc": Description.CPLD, + "slot": 0, + }, + { + "name": "CPLD2 (MAC Board B)", + "firmware_version": { + "bus": 2, + "addr": 0x35, + "offset": 0, + "size": 4, + "way": DecodeMethod.I2C, + "format": DecodeFormat.JOIN, + "sep": "/", + }, + "desc": Description.CPLD, + "slot": 0, + }, + { + "name": "CPLD3 (CONNECT Board A)", + "firmware_version": { + "bus": 2, + "addr": 0x37, + "offset": 0, + "size": 4, + "way": DecodeMethod.I2C, + "format": DecodeFormat.JOIN, + "sep": "/", + }, + "desc": Description.CPLD, + "slot": 0, + }, + { + "name": "CPLD4 (CPU Board)", + "firmware_version": { + "bus": 0, + "addr": 0x0D, + "offset": 0, + "size": 4, + "way": DecodeMethod.I2C, + "format": DecodeFormat.JOIN, + "sep": "/", + }, + "desc": Description.CPLD, + "slot": 1, + }, + ], + "thermals": [ + { + "name": "INLET TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-0048/hwmon/*/temp1_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": None, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-0048/hwmon/*/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "OUTLET TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-0049/hwmon/*/temp1_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": None, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-0049/hwmon/*/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "BOARD TEMP", + "high": { + "loc": "/sys/bus/i2c/devices/2-004a/hwmon/*/temp1_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": None, + "temperature": { + "loc": "/sys/bus/i2c/devices/2-004a/hwmon/*/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "PHYSICAL ID 0", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp1_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp1_crit", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "CPU CORE 0", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp2_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp2_crit", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp2_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "CPU CORE 1", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp3_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp3_crit", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp3_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "CPU CORE 2", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp4_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp4_crit", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp4_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + { + "name": "CPU CORE 3", + "high": { + "loc": "/sys/class/hwmon/hwmon0/temp5_max", + "format": DecodeFormat.THOUSANDTH, + }, + "low": None, + "crit_low": None, + "crit_high": { + "loc": "/sys/class/hwmon/hwmon0/temp5_crit", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/class/hwmon/hwmon0/temp5_input", + "format": DecodeFormat.THOUSANDTH, + }, + }, + ], + "fans": [ + { + "name": "fan1", + "e2loc": {"bus": 3, "addr": 0x53, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 0, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 0, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/3-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/3-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan0_led", + "format": DecodeFormat.AND, + "mask": 0b1011, + }, + "led_colors": FAN_LED_COLORS, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan1_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": Threshold.FAN_SPEED_MAX, + } + ], + }, + { + "name": "fan2", + "e2loc": {"bus": 4, "addr": 0x53, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 1, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 1, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/4-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/4-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan1_led", + "format": DecodeFormat.AND, + "mask": 0b1011, + }, + "led_colors": FAN_LED_COLORS, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan2_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": Threshold.FAN_SPEED_MAX, + } + ], + }, + { + "name": "fan3", + "e2loc": {"bus": 3, "addr": 0x53, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 2, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 2, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/5-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/5-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan2_led", + "format": DecodeFormat.AND, + "mask": 0b1011, + }, + "led_colors": FAN_LED_COLORS, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan3_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": Threshold.FAN_SPEED_MAX, + } + ], + }, + { + "name": "fan4", + "e2loc": {"bus": 3, "addr": 0x53, "way": "i2c", "size": "256"}, + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_present", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 3, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/fan_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 3, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/6-0053/fan_hw_version"}, + "sn": {"loc": "/sys/bus/i2c/devices/6-0053/fan_sn"}, + "led": { + "loc": "/sys/bus/i2c/devices/0-0032/fan3_led", + "format": DecodeFormat.AND, + "mask": 0b1011, + }, + "led_colors": FAN_LED_COLORS, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/2-0037/hwmon/*/fan4_input" + }, + "speed_setter": { + "loc": "/sys/bus/i2c/devices/0-0032/fan_speed_set" + }, + "speed_max": Threshold.FAN_SPEED_MAX, + } + ], + }, + ], + "psus": [ + { + "name": "psu1", + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 0, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 1, + }, + "sn": {"loc": "/sys/bus/i2c/devices/7-0050/psu_sn"}, + "in_current": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/curr1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "in_voltage": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/in1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "out_voltage": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/in2_input", + "format": DecodeFormat.THOUSANDTH, + }, + "out_current": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/curr2_input", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/7-0050/psu_hw"}, + "psu_type": {"loc": "/sys/bus/i2c/devices/7-0050/psu_type"}, + "fans": [ + { + "name": "psu_fan1", + "present": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/fan1_fault", + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 1, + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/fan1_input" + }, + "speed_max": Threshold.PSU_FAN_SPEED_MAX, + } + ], + } + ], + "in_power": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/power1_input", + "format": DecodeFormat.MILLIONTH, + }, + "out_power": { + "loc": "/sys/bus/i2c/devices/7-0058/hwmon/*/power2_input", + "format": DecodeFormat.MILLIONTH, + }, + }, + { + "name": "psu2", + "present": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 4, + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 5, + }, + "sn": {"loc": "/sys/bus/i2c/devices/8-0053/psu_sn"}, + "in_current": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/curr1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "in_voltage": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/in1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "out_voltage": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/in2_input", + "format": DecodeFormat.THOUSANDTH, + }, + "out_current": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/curr2_input", + "format": DecodeFormat.THOUSANDTH, + }, + "temperature": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/temp1_input", + "format": DecodeFormat.THOUSANDTH, + }, + "hw_version": {"loc": "/sys/bus/i2c/devices/8-0053/psu_hw"}, + "psu_type": {"loc": "/sys/bus/i2c/devices/8-0053/psu_type"}, + "fans": [ + { + "name": "psu_fan1", + "present": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/fan1_fault", + }, + "status": { + "loc": "/sys/bus/i2c/devices/2-0037/psu_status", + "format": DecodeFormat.ONE_BIT_HEX, + "bit": 5, + }, + "rotors": [ + { + "speed_getter": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/fan1_input" + }, + "speed_max": Threshold.PSU_FAN_SPEED_MAX, + } + ], + } + ], + "in_power": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/power1_input", + "format": DecodeFormat.MILLIONTH, + }, + "out_power": { + "loc": "/sys/bus/i2c/devices/8-005b/hwmon/*/power2_input", + "format": DecodeFormat.MILLIONTH, + }, + }, + ], +} diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/eeprom.py new file mode 100644 index 000000000000..5fe0561f6c46 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/eeprom.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- + +######################################################################## +# Ruijie B6510-48VS8CQ +# +# Module contains platform specific implementation of SONiC Platform +# Base API and provides the EEPROMs' information. +# +# The different EEPROMs available are as follows: +# - System EEPROM : Contains Serial number, Service tag, Base MA +# address, etc. in ONIE TlvInfo EEPROM format. +# - PSU EEPROM : Contains Serial number, Part number, Service Tag, +# PSU type, Revision. +# - Fan EEPROM : Contains Serial number, Part number, Service Tag, +# Fan type, Number of Fans in Fantray, Revision. +######################################################################## + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + def __init__(self, bus=2, loc="0057", config=None, iom_eeprom=False): + self.is_module = iom_eeprom + + if config: + bus = config.get("bus") + loc = config.get("loc") + + if bus and loc: + self.eeprom_path = "/sys/bus/i2c/devices/{}-{}/eeprom".format(bus, loc) + else: + raise ValueError( + "Eeprom location error, bus: {}, loc: {}, config: {}".format( + bus, loc, config + ) + ) + + super(Eeprom, self).__init__(self.eeprom_path, 0, "", True) + self.eeprom_tlv_dict = dict() + + try: + if self.is_module: + # TODO + pass + # self.write_eeprom("\x00\x00") + # self.eeprom_data = self.read_eeprom_bytes(256) + else: + self.eeprom_data = self.read_eeprom() + except Exception: + self.eeprom_data = "N/A" + if not self.is_module: + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index : tlv_index + 2 + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + if tlv[0] == self._TLV_CODE_VENDOR_EXT: + value = str( + (tlv[2] << 24) + | (tlv[3] << 16) + | (tlv[4] << 8) + | tlv[5] + ) + value += str(tlv[6 : 6 + tlv[1]]) + else: + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index + 1] + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER + ) + if not is_valid: + return "N/A" + + return results[2] + + def base_mac_addr(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_MAC_BASE + ) + if not is_valid or results[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join([hex(T) for T in results[2]]) + + def modelstr(self): + 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" + + return results[2] + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PART_NUMBER + ) + if not is_valid: + return "N/A" + + return results[2] + + def serial_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERVICE_TAG + ) + if not is_valid: + return "N/A" + + return results[2] + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_DEVICE_VERSION + ) + if not is_valid: + return "N/A" + + return results[2] + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan.py new file mode 100644 index 000000000000..173c0529443a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan.py @@ -0,0 +1,289 @@ +# -*- coding: utf-8 -*- + +######################################################################## +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fans' information which are available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_base import FanBase + from sonic_platform.regutil import Reg + from sonic_platform.rotor import Rotor + from sonic_platform.logger import logger + from math import ceil +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Fan(FanBase): + """Ruijie Platform-specific Fan class""" + + MAX_SPEED_CODE = 255 + + def __init__(self, index, config=None, hal_fan=None, is_psu_fan=False): + self.index = index + self.is_psu_fan = is_psu_fan + if config: + if self.is_psu_fan: + self.name = "Psu{}-{}".format(self.index, config.get("name")) + else: + self.name = config.get("name") + self.__reg_sn = Reg(config.get("sn")) + self.__reg_present = Reg(config.get("present")) + self.__reg_status = Reg(config.get("status")) + self.__reg_led = Reg(config.get("led")) + self.__reg_pn = Reg(config.get("pn")) + self.__led_colors = config.get("led_colors") + + # rotors + rotors = config.get("rotors") + if isinstance(rotors, list): + self.__rotors = [] + for rotor in rotors: + self.__rotors.append(Rotor(rotor)) + + self._hal_fan = hal_fan + + def _reg_setter(self, target, val): + if isinstance(val, dict): + target = Reg(val) + elif isinstance(val, Reg): + target = val + else: + raise ValueError + return target + + @property + def reg_sn(self): + return self.__reg_sn + + @reg_sn.setter + def reg_sn(self, val): + self._reg_setter(self.__reg_sn, val) + + @property + def reg_present(self): + return self.__reg_present + + @reg_present.setter + def reg_present(self, val): + self._reg_setter(self.__reg_present, val) + + @property + def reg_status(self): + return self.__reg_status + + @reg_status.setter + def reg_status(self, val): + self._reg_setter(self.__reg_status, val) + + @property + def reg_led(self): + return self.__reg_led + + @reg_led.setter + def reg_led(self, val): + self._reg_setter(self.__reg_led, val) + + def get_name(self): + """ + Retrieves the fan name + Returns: + string: The name of the device + """ + return self.name + + def get_model(self): + """ + Retrieves the part number of the FAN + Returns: + string: Part number of FAN + """ + if self._hal_fan: + return self._hal_fan.pn() + + try: + if isinstance(self.__reg_pn, Reg): + return self.__reg_pn.decode() + except Exception as e: + logger.error(str(e)) + + return "NA" + + def get_serial(self): + """ + Retrieves the serial number of the FAN + Returns: + string: Serial number of FAN + """ + if self._hal_fan: + return self._hal_fan.sn() + + try: + if isinstance(self.__reg_sn, Reg): + return self.__reg_sn.decode() + except Exception as e: + logger.error(str(e)) + + return "NA" + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if fan is present, False if not + """ + + # print self.fan_presence_reg.decode() + # return True if self.fan_presence_reg.decode() == 0 else False + if self._hal_fan: + return self._hal_fan.get_presence() + + try: + if isinstance(self.__reg_present, Reg): + present = self.__reg_present.decode() + if present == 0 or present == "0": + return True + except Exception as e: + logger.error(str(e)) + + return False + + def get_status(self): + """ + Retrieves the operational status of the FAN + Returns: + bool: True if FAN is operating properly, False if not + """ + + # return True if self.fan_status_reg.decode() == 1 else False + if self._hal_fan: + return self._hal_fan.get_status() + + try: + if isinstance(self.__reg_status, Reg): + status = self.__reg_status.decode() + if status == 1 or status == "1": + return True + except Exception as e: + pass + + return False + + def get_direction(self): + """ + Retrieves the fan airflow direction + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + - Forward/Exhaust : Air flows from Port side to Fan side. + - Reverse/Intake : Air flows from Fan side to Port side. + """ + + # TODO + return self.FAN_DIRECTION_EXHAUST + + def get_speed(self): + """ + Retrieves the speed of fan + Returns: + int: percentage of the max fan speed + """ + if self.get_presence(): + maxspeed = 0 + for r in self.__rotors: + speed = r.get_speed_percentage() + if speed > maxspeed: + maxspeed = speed + return maxspeed + else: + return 0 + + 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 + """ + # TODO + return 0 + + def set_speed(self, speed): + """ + Set fan speed to expected value + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + Returns: + bool: True if set success, False if fail. + """ + if self.__rotors: + speed_code = hex(int(ceil(float(self.MAX_SPEED_CODE) / 100 * speed))) + return self.__rotors[0].set_speed(speed_code) + + return False + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if set success, False if fail. + """ + # TODO + if self.is_psu_fan: + # No LED available for PSU Fan + return False + try: + if color not in self.__led_colors: + logger.error("color:%s not defined." % color) + return False + val = hex(self.__led_colors[color]) + if isinstance(self.__reg_led, Reg): + return self.__reg_led.encode(val) + return ret + except Exception as e: + logger.error(str(e)) + return False + + + def get_status_led(self): + """ + Gets the state of the Fan status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + # TODO + if self.is_psu_fan: + # No LED available for PSU Fan + return None + else: + try: + if isinstance(self.__reg_led, Reg) : + led_color = self.__reg_led.decode() + for color, code in self.__led_colors.items(): + if code ^ led_color == 0: + return color + except Exception as e: + logger.error(str(e)) + + return None + + 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) + """ + # TODO + return 0 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..692819a04339 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/fan_drawer.py @@ -0,0 +1,71 @@ +# +# fan_drawer_base.py +# +# Abstract base class for implementing a platform-specific class with which +# to interact with a fan drawer module in SONiC +# + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanDrawer(FanDrawerBase): + """ + Abstract base class for interfacing with a fan drawer + """ + # Device type definition. Note, this is a constant. + DEVICE_TYPE = "fan_drawer" + + def __init__(self, index, fan_list): + FanDrawerBase.__init__(self) + + self._fan_list = fan_list + self._index = index + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + + return "fan {}".format(self._index) + + def get_num_fans(self): + """ + Retrieves the number of fans available on this fan drawer + Returns: + An integer, the number of fan modules available on this fan drawer + """ + return len(self._fan_list) + + def get_all_fans(self): + """ + Retrieves all fan modules available on this fan drawer + Returns: + A list of objects derived from FanBase representing all fan + modules available on this fan drawer + """ + return self._fan_list + + def set_status_led(self, color): + """ + Sets the state of the fan drawer status LED + Args: + color: A string representing the color with which to set the + fan drawer status LED + Returns: + bool: True if status LED state is set successfully, False if not + """ + return self._fan_list[self._index].set_status_led(color) + + def get_status_led(self, color): + """ + Gets the state of the fan drawer LED + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + return self._fan_list[self._index].get_status_led(color) + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/logger.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/logger.py new file mode 100644 index 000000000000..5969781bf9a9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/logger.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +import logging + + +def _init_logger(): + formatter = logging.Formatter( + "%(asctime)s %(levelname)s %(filename)s[%(funcName)s][%(lineno)s]: %(message)s" + ) + handler = logging.FileHandler("/var/log/syslog") + handler.setFormatter(formatter) + + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + logger.addHandler(handler) + return logger + + +logger = _init_logger() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/pcie.py new file mode 100644 index 000000000000..5a66997d33d0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/pcie.py @@ -0,0 +1,43 @@ +# +# pcie_base.py +# +# Abstract base class for implementing platform-specific +# PCIE functionality for SONiC +# + +try: + import abc + from sonic_pcie import PcieUtil +except ImportError as e: + raise ImportError (str(e) + " - required module not found") + +class PcieBase(object): + def __init__(self, path): + """ + Constructor + Args: + pcieutil file and config file path + """ + self.pcie_util = PcieUtil(path) + + + @abc.abstractmethod + def get_pcie_device(self): + """ + get current device pcie info + + Returns: + A list including pcie device info + """ + return self.pcie_util.get_pcie_device() + + + @abc.abstractmethod + def get_pcie_check(self): + """ + Check Pcie device with config file + Returns: + A list including pcie device and test result info + """ + return self.pcie_util.get_pcie_check() + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/platform.py new file mode 100644 index 000000000000..3aa7fe3f2605 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/platform.py @@ -0,0 +1,22 @@ +############################################################################# +# +# 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): + """ + Ruijie Platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/psu.py new file mode 100644 index 000000000000..65e27bc1cf76 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/psu.py @@ -0,0 +1,413 @@ +# -*- coding: utf-8 -*- + +######################################################################## +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan + from sonic_platform.regutil import Reg + from sonic_platform.logger import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Psu(PsuBase): + """Ruijie Platform-specific PSU class""" + + # HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + # HWMON_NODE = os.listdir(HWMON_DIR)[0] + # MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + def __init__(self, index, config=None, hal_psu=None): + """ + "psus": [ + { + "name": "psu1", + "present": {"loc": "2-0037/psu_status", "format": DecodeFormat.ONE_BIT_HEX, "bit": 0}, + "status": {"loc": "2-0037/psu_status", "format": DecodeFormat.ONE_BIT_HEX, "bit": 1}, + "sn": {"loc": "7-0050/psu_sn"}, + "in_current": {"loc": "7-0058/hwmon/*/curr1_input", "format": DecodeFormat.THOUSANDTH}, + "in_voltage": {"loc": "7-0058/hwmon/*/in1_input", "format": DecodeFormat.THOUSANDTH}, + "out_voltage": {"loc": "7-0058/hwmon/*/in2_input", "format": DecodeFormat.THOUSANDTH}, + "out_current": {"loc": "7-0058/hwmon/*/curr2_input", "format": DecodeFormat.THOUSANDTH}, + "temperature": {"loc": "7-0058/hwmon/*/temp1_input", "format": DecodeFormat.THOUSANDTH}, + "hw_version": {"loc": "7-0050/psu_hw"}, + "psu_type": {"loc": "7-0050/psu_type"}, + "fans": [ + { + "rotor": { + "speed": {"loc": "7-0058/hwmon/*/fan1_input"}, + "speed_max": xx + } + } + ], + "in_power": {"loc": "7-0058/hwmon/*/power1_input", "format": DecodeFormat.MILLIONTH}, + "out_power": {"loc": "7-0058/hwmon/*/power2_input", "format": DecodeFormat.MILLIONTH}, + } + ] + """ + self._fan_list = [] + self.PSU_TEMP_MAX = 60 * 1000 + self.PSU_OUTPUT_POWER_MAX = 1300 * 1000 + self.PSU_OUTPUT_VOLTAGE_MIN = 11 * 1000 + self.PSU_OUTPUT_VOLTAGE_MAX = 14 * 1000 + self.index = index + if config is not None: + self.name = config.get("name") + self.__reg_sn = Reg(config.get("sn")) + self.__reg_present = Reg(config.get("present")) + self.__reg_status = Reg(config.get("status")) + self.__reg_out_vol = Reg(config.get("out_voltage")) + self.__reg_out_cur = Reg(config.get("out_current")) + self.__reg_out_pow = Reg(config.get("out_power")) + self.__reg_pn = Reg(config.get("pn")) + self.__reg_temperature = Reg(config.get("temperature")) + self._fan_list = config.get("fans") + self._psu_fan_parser(config.get("fans")) + + self._hal_psu = hal_psu + + def _psu_fan_parser(self, fans): + if not isinstance(fans, list): + raise TypeError("fan type error fans: {}".format(fans)) + for index in range(0,len(fans)): + if not isinstance(fans[index], dict): + raise TypeError("fan type must be a dict") + self._fan_list.append(Fan(index, config=fans[index], is_psu_fan=True)) + + def _reg_setter(self, target, val): + if isinstance(val, dict): + target = Reg(val) + elif isinstance(val, Reg): + target = val + else: + raise ValueError + return target + + @property + def reg_sn(self): + return self.__reg_sn + + @reg_sn.setter + def reg_sn(self, val): + self._reg_setter(self.__reg_sn, val) + + @property + def reg_present(self): + return self.__reg_present + + @reg_present.setter + def reg_present(self, val): + self._reg_setter(self.__reg_present, val) + + @property + def reg_status(self): + return self.__reg_status + + @reg_status.setter + def reg_status(self, val): + self._reg_setter(self.__reg_status, val) + + @property + def reg_out_vol(self): + return self.__reg_out_vol + + @reg_out_vol.setter + def reg_out_vol(self, val): + self._reg_setter(self.__reg_out_vol, val) + + @property + def reg_out_cur(self): + return self.__reg_out_cur + + @reg_out_cur.setter + def reg_out_cur(self, val): + self._reg_setter(self.__reg_out_cur, val) + + @property + def reg_out_pow(self): + return self.__reg_out_pow + + @reg_out_pow.setter + def reg_out_pow(self, val): + self._reg_setter(self.__reg_out_pow, val) + + def get_all_fans(self): + return self._fan_list + + def get_num_fans(self): + return len(self._fan_list) + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return self.name + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + if self._hal_psu: + pass + + try: + if isinstance(self.__reg_present, Reg): + psu_presence = self.__reg_present.decode() + if psu_presence == 0 or psu_presence == "0": + return True + except Exception as e: + logger.error(str(e)) + + return False + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + + if self._hal_psu: + return self._hal_psu.pn() + + try: + if isinstance(self.__reg_pn, Reg): + return self.__reg_pn.decode() + except Exception as e: + logger.error(str(e)) + + return "NA" + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + if self._hal_psu: + return self._hal_psu.sn() + + try: + if isinstance(self.__reg_sn, Reg): + return self.__reg_sn.decode() + except Exception as e: + logger.error(str(e)) + + return "NA" + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + # status = False + # psu_status = self._get_pmc_register(self.psu_presence_reg) + # if (psu_status != 'ERR'): + # psu_status = int(psu_status, 16) + # # Checking whether both bit 3 and bit 2 are not set + # if (~psu_status & 0b1000) and (~psu_status & 0b0100): + # status = True + + if self._hal_psu: + return self._hal_psu.get_status() + + try: + if isinstance(self.reg_status, Reg): + psu_status = self.reg_status.decode() + if psu_status == 1 or psu_status == "1": + return True + elif psu_status == 0 or psu_status == "0": + return False + except Exception as e: + logger.error(str(e)) + + return False + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + # psu_voltage = self._get_pmc_register(self.psu_voltage_reg) + # if (psu_voltage != 'ERR') and self.get_presence(): + # # Converting the value returned by driver which is in + # # millivolts to volts + # psu_voltage = float(psu_voltage) / 1000 + # else: + # psu_voltage = 0.0 + + if self._hal_psu: + pass + + try: + if isinstance(self.__reg_out_vol, Reg): + return self.__reg_out_vol.decode() + except Exception as e: + logger.error(str(e)) + + return 0.0 + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + # psu_current = self._get_pmc_register(self.psu_current_reg) + # if (psu_current != 'ERR') and self.get_presence(): + # # Converting the value returned by driver which is in + # # milliamperes to amperes + # psu_current = float(psu_current) / 1000 + # else: + # psu_current = 0.0 + + if self._hal_psu: + pass + + try: + if isinstance(self.__reg_out_cur, Reg): + return self.__reg_out_cur.decode() + except Exception as e: + logger.error(str(e)) + + return 0.0 + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + + if self._hal_psu: + pass + + try: + if isinstance(self.__reg_out_pow, Reg): + return self.__reg_out_pow.decode() + except Exception as e: + logger.error(str(e)) + + return 0.0 + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + if self._hal_psu: + pass + else: + if self.get_status() and self.get_presence(): + return True + + return False + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + # TODO + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_RED + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if + not + """ + # not supported + return False + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self._hal_psu: + pass + + try: + if isinstance(self.__reg_temperature, Reg): + return self.__reg_temperature.decode() + except Exception as e: + logger.error(str(e)) + + return 0.0 + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + return float(self.PSU_TEMP_MAX/1000) + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return float(self.PSU_OUTPUT_VOLTAGE_MAX/1000) + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return float(self.PSU_OUTPUT_VOLTAGE_MIN/1000) + + def get_maximum_supplied_power(self): + """ + Retrieves the maximum supplied power by PSU + Returns: + A float number, the maximum power output in Watts. + e.g. 1200.1 + """ + return float(self.PSU_OUTPUT_POWER_MAX/1000) + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/regutil.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/regutil.py new file mode 100644 index 000000000000..d216da9307b1 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/regutil.py @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- +from glob import glob +from plat_hal.osutil import osutil + +try: + from sonic_platform.config import DecodeFormat, DecodeMethod + + DECODE_FORMAT = DecodeFormat + DECODE_METHOD = DecodeMethod +except ImportError: + raise ImportError(str(e) + "- required module not found") + +ERR_CODE = "ERR" + + +class Reg(object): + """ + "e2loc": {"bus": 3, "addr": 0x53, "way": "i2c"} + "value": { + "loc": "/sys/bus/i2c/devices/2-0048/hwmon/hwmon*/temp1_input", + "way": "sysfs", + + "InputsStatus": { + "bus": 8, + "addr": 0x5B, + "offset": 0x79, + "way": "i2cword", + "mask": 0x0200, + }, + """ + + def __new__(cls, *args): + if args[0] is None or not isinstance(args[0], dict): + return None + return super(Reg, cls).__new__(cls) + + def __init__(self, data): + + self.loc = None + self.way = DECODE_METHOD.SYSFS + self.addr = None + self.bus = None + self.offset = None + self.size = 1 + self.bit = None + self.mask = None + self.digit = None + self.sdk_type = None + self.sep = None + self.format = DECODE_FORMAT.TEXT + self.__dict__.update(data) + + def _read_reg_val(self): + ret = None + try: + if self.way == DECODE_METHOD.SYSFS: + ret = self.get_sysfs() + elif self.way == DECODE_METHOD.I2C: + ret = self.get_i2c() + elif self.way == DECODE_METHOD.I2C_WORD: + ret = self.get_i2cword() + elif self.way == DECODE_METHOD.DEVMEM: + ret = self.get_devmem() + elif self.way == DECODE_METHOD.SDK: + # TODO + pass + else: + pass + except Exception as e: + raise e + + return ret + + def _write_reg_val(self, val): + try: + if self.way == DECODE_METHOD.SYSFS: + return self._write_sysfs(val) + except Exception as e: + raise e + + return False + + def _write_sysfs(self, val): + try: + with open(glob(self.loc)[0], "w") as f: + f.write(val) + f.flush() + return True + except Exception as e: + raise e + + def _format_val(self, val): + try: + if isinstance(val, str): + val = val.strip() + if self.format == DECODE_FORMAT.THOUSANDTH: + return float("%.1f" % (float(val) / 1000)) + elif self.format == DECODE_FORMAT.HUNDREDTH: + return float("%.1f" % (float(val) / 100)) + elif self.format == DECODE_FORMAT.ONE_BIT_HEX: + return (int(val, 16) & (1 << self.bit)) >> self.bit + elif self.format == DECODE_FORMAT.DECIMAL: + return int(val, 10) + elif self.format == DECODE_FORMAT.MILLIONTH: + return float("%.1f" % (float(val) / 1000 / 1000)) + elif self.format == DECODE_FORMAT.AND: + return (int(val, 16)) & self.mask + elif isinstance(val, list): + if self.format == DECODE_FORMAT.JOIN: + return self.sep.join(val) + except Exception as e: + raise e + else: + return val + + def decode(self): + """ + get value by config way + way i2c/sysfs/lpc + """ + if self.way is None: + raise ValueError("cannot found way to deal") + + ret = self._read_reg_val() + + ret = self._format_val(ret) + return ret + + def encode(self, val): + if self.way is None: + raise ValueError("cannot found way to deal") + + return self._write_reg_val(val) + + def get_sdk(self): + # TODO + pass + + def get_sysfs(self): + if self.loc is None: + raise ValueError("Not Enough Attr: loc: {}".format(self.loc)) + + ret, val = osutil.readsysfs(self.loc) + + if not ret: + raise IOError(val) + + return val + + def get_devmem(self): + if self.addr is None or self.digit is None or self.mask is None: + raise ValueError( + "Not Enough Attr: addr: {}, digit: {}, mask: {}".format( + self.addr, self.digit, self.mask + ) + ) + + ret, val = osutil.getdevmem(self.addr, self.digit, self.mask) + + if not ret: + raise IOError(val) + + return val + + def get_i2cword(self): + if self.bus is None or self.addr is None or self.offset is None: + raise ValueError( + "Not Enough Attr: bus: {}, addr: {}, offset: {}".format( + self.bus, self.addr, self.offset + ) + ) + + ret, val = osutil.geti2cword(self.bus, self.addr, self.offset) + + if not ret: + raise IOError(val) + + return val + + def get_i2c(self): + if ( + self.bus is None + or self.addr is None + or self.offset is None + or self.size is None + ): + raise ValueError( + "Not Enough Attr: bus: {}, addr: {}, offset: {}".format( + self.bus, self.addr, self.offset + ) + ) + + value = [] + for i in range(self.size): + ofs = self.offset + i + ret, val = osutil.rji2cget(self.bus, self.addr, ofs) + + if not ret: + raise IOError(val) + else: + value.append(repr(chr(val)).translate(None, r"\\x").replace("'", "")) + + return value + + def set_i2cword(self, bus, addr, offset, byte): + return self.seti2cword(bus, addr, offset, byte) + + def seti2cword(self, bus, addr, offset, byte): + return osutil.seti2cword(bus, addr, offset, byte) + + def set_i2c(self, bus, addr, offset, byte): + return self.seti2c(bus, addr, offset, byte) + + def seti2c(self, bus, addr, offset, byte): + ret, val = osutil.rji2cset(bus, addr, offset, byte) + return ret, val + + def getbcmtemp(self): + try: + sta, ret = osutil.getmactemp() + if sta == True: + mac_aver = float(ret.get("average", self.__error_ret)) + #mac_max = float(ret.get("maximum", self.__error_ret)) + mac_aver = mac_aver * 1000 + #mac_max = mac_max * 1000 + else: + return False, ret + except AttributeError as e: + return False, str(e) + return True, mac_aver + + def getbcmreg(self, reg): + ret, val = osutil.getsdkreg(reg) + return ret, val + + def logger_debug(self, msg): + baseutil.logger_debug(msg) + + def command(self, cmd): + ret, output = osutil.command(cmd) + return ret, output + + def set_val(self, val): + # TODO + pass diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/rotor.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/rotor.py new file mode 100644 index 000000000000..3e5bcc5b9b9a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/rotor.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- + +try: + from sonic_platform.regutil import Reg + from sonic_platform.logger import logger +except ImportError: + raise ImportError(str(e) + "- required module not found") + +class Rotor: + def __init__(self, config): + if config is not None and isinstance(config, dict): + self.__reg_speed_getter = Reg(config.get("speed_getter")) + self.__reg_speed_setter = Reg(config.get("speed_setter")) + self.__speed_max = config.get("speed_max") + else: + raise ValueError("init rotor Error: {}".format(config)) + + def get_speed(self): + try: + return int(self.__reg_speed_getter.decode()) + except Exception as e: + logger.error(str(e)) + + return 0 + + def set_speed(self, speed): + try: + return self.__reg_speed_setter.encode(speed) + except Exception as e: + logger.error(str(e)) + + return False + + def get_speed_percentage(self): + try: + speed = self.get_speed() + return (100 * speed) / self.__speed_max + except Exception as e: + logger.error(str(e)) + + return 0 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/sfp.py new file mode 100644 index 000000000000..41c2b63c05d8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/sfp.py @@ -0,0 +1,1566 @@ +# -*- coding: utf-8 -* + +############################################################################# +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import time + from ctypes import create_string_buffer + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +############################################################################# +# Ruijie B6510-48VS8CQ +PORT_START = 0 +PORT_END = 55 +PORTS_IN_BLOCK = 56 + +PORT_QSFP_START = 48 +PORT_QSFP_END = 56 + +EEPROM_OFFSET = 11 +############################################################################# + +IDENTITY_EEPROM_ADDR = 0x50 + +INFO_OFFSET = 128 +DOM_OFFSET = 0 +DOM_OFFSET1 = 384 + +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" +OSFP_TYPE = "OSFP" + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 + +XCVR_INTERFACE_DATA_START = 0 +XCVR_INTERFACE_DATA_SIZE = 92 + +QSFP_DOM_BULK_DATA_START = 22 +QSFP_DOM_BULK_DATA_SIZE = 36 +SFP_DOM_BULK_DATA_START = 96 +SFP_DOM_BULK_DATA_SIZE = 10 + +# definitions of the offset for values in OSFP info eeprom +OSFP_TYPE_OFFSET = 0 +OSFP_VENDOR_NAME_OFFSET = 129 +OSFP_VENDOR_PN_OFFSET = 148 +OSFP_HW_REV_OFFSET = 164 +OSFP_VENDOR_SN_OFFSET = 166 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_MODULE_MONITOR_OFFSET = 0 +QSFP_MODULE_MONITOR_WIDTH = 9 +QSFP_POWERMODE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_POWERSET_BIT = 1 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 +QSFP_MODULE_UPPER_PAGE3_START = 384 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_CHANNL_THRESHOLD_OFFSET = 176 +QSFP_CHANNL_THRESHOLD_WIDTH = 24 + +SFP_MODULE_ADDRA2_OFFSET = 256 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_CHANNL_STATUS_OFFSET = 110 +SFP_CHANNL_STATUS_WIDTH = 1 + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +class Sfp(SfpBase): + """ + DELLEMC Platform-specific Sfp class + """ + + SFP_DEVICE_TYPE = "optoe2" + QSFP_DEVICE_TYPE = "optoe1" + port_to_i2cbus_mapping = {} + def __init__(self, index): + self.index = index + self.port_num = self.index + PORT_START + self.sfp_type = self.__get_sfp_info() + self.dom_supported = False + for x in range(PORT_START, PORTS_IN_BLOCK): + self.port_to_i2cbus_mapping[x] = (x + EEPROM_OFFSET) + + self.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'lp_mode', 'tx_disable', 'tx_disabled_channel', 'temperature', 'voltage', + 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + self.__dom_capability_detect() + + @property + def qsfp_ports(self): + return range(PORT_QSFP_START, PORT_QSFP_END) + + def get_presence(self): + # Check for invalid self.port_num + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + + if self.port_num <= 7: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence1" + elif self.port_num >= 8 and self.port_num <= 15: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence2" + elif self.port_num >= 16 and self.port_num <= 23: + presence_path = "/sys/bus/i2c/devices/1-0034/sfp_presence3" + elif self.port_num >= 24 and self.port_num <= 31: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence4" + elif self.port_num >= 32 and self.port_num <= 39: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence5" + elif self.port_num >= 40 and self.port_num <= 47: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence6" + elif self.port_num >= 48 and self.port_num <= 55: + presence_path = "/sys/bus/i2c/devices/1-0036/sfp_presence7" + else: + return False + + try: + data = open(presence_path, "rb") + except IOError: + return False + + presence_data = data.read(2) + if presence_data == "": + return False + result = int(presence_data, 16) + data.close() + + # ModPrsL is active low + if result & (1 << (self.port_num % 8)) == 0: + return True + + return False + + def __get_sfp_info(self): + if PORT_START <= self.port_num <= PORT_END: + if self.port_num in self.qsfp_ports: + sfp_type = QSFP_TYPE + else: + sfp_type = SFP_TYPE + else: + return "port range error" + return sfp_type + + def __dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.qsfp_page3_available = False + self.calibration = 0 + return + + if self.sfp_type == "QSFP": + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # 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( + (offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self.__read_eeprom_specific_bytes( + QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH) + qsfp_version_compliance = int( + qsfp_version_compliance_raw[0], 16) + dom_capability = sfpi_obj.parse_qsfp_dom_capability( + qsfp_dom_capability_raw, 0) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = dom_capability['data']['Temp_support']['value'] == 'On' + self.dom_volt_supported = dom_capability['data']['Voltage_support']['value'] == 'On' + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = dom_capability['data']['Tx_power_support']['value'] == 'On' + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = True + + self.dom_supported = True + self.calibration = 1 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + qsfp_option_value_raw = self.__read_eeprom_specific_bytes( + QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH) + if qsfp_option_value_raw is not None: + optional_capability = sfpd_obj.parse_option_params( + qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = optional_capability[ + 'data']['TxDisable']['value'] == 'On' + dom_status_indicator = sfpd_obj.parse_dom_status_indicator( + qsfp_version_compliance_raw, 1) + self.qsfp_page3_available = dom_status_indicator['data']['FlatMem']['value'] == 'Off' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.qsfp_page3_available = False + + elif self.sfp_type == "SFP": + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = ( + int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def __add_new_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr, devtype): + try: + sysfs_nd_path = "%s/new_device" % sysfs_sfp_i2c_adapter_path + + # Write device address to new_device file + nd_file = open(sysfs_nd_path, "w") + nd_str = "%s %s" % (devtype, hex(devaddr)) + nd_file.write(nd_str) + nd_file.close() + + except Exception as err: + print("Error writing to new device file: %s" % str(err)) + return 1 + else: + return 0 + + def __get_port_eeprom_path(self, port_num, devid): + if self.get_presence() is False: + print("port %d Not present" % port_num) + return None + + eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050' + i2c_path = '/sys/bus/i2c/devices/i2c-{0}' + sysfs_sfp_i2c_client_path = eeprom_path.format(self.port_to_i2cbus_mapping[port_num]) + sysfs_sfp_i2c_adapter_path= i2c_path.format(self.port_to_i2cbus_mapping[port_num]) + # If sfp device is not present on bus, Add it + if not os.path.exists(sysfs_sfp_i2c_client_path): + if port_num in self.qsfp_ports: + ret = self.__add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.QSFP_DEVICE_TYPE) + else: + ret = self.__add_new_sfp_device( + sysfs_sfp_i2c_adapter_path, devid, self.SFP_DEVICE_TYPE) + if ret != 0: + print("Error adding sfp device") + return None + + sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path + + return sysfs_sfp_i2c_client_eeprom_path + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.__get_port_eeprom_path(self.port_num, IDENTITY_EEPROM_ADDR) + if sysfs_sfp_i2c_client_eeprom_path is None: + return eeprom_raw + try: + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + except IOError: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def __convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + ''' + if not self.get_presence(): + return transceiver_info_dict + ''' + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + #port_eeprom_path = self.sfputilbase.__get_port_eeprom_path(self.port_num, IDENTITY_EEPROM_ADDR) + if self.sfp_type == QSFP_TYPE: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + offset + XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE) + if sfp_interface_bulk_raw is None: + return None + + start = XCVR_INTFACE_BULK_OFFSET - XCVR_INTERFACE_DATA_START + end = start + interface_info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_NAME_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_NAME_WIDTH + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_PN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_PN_WIDTH + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_HW_REV_OFFSET - XCVR_INTERFACE_DATA_START + end = start + vendor_rev_width + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_SN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_SN_WIDTH + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_OUI_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_OUI_WIDTH + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_DATE_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_DATE_WIDTH + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_interface_bulk_raw[start: end], 0) + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + self.__dom_capability_detect() + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + + if self.sfp_type == QSFP_TYPE: + offset = 128 + qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + self.dom_supported = True + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_DOM_BULK_DATA_START), QSFP_DOM_BULK_DATA_SIZE) + if dom_data_raw is None: + return transceiver_dom_info_dict + + if self.dom_temp_supported: + start = QSFP_TEMPE_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + temp = self.__convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + if temp is not None: + transceiver_dom_info_dict['temperature'] = temp + + if self.dom_volt_supported: + start = QSFP_VOLT_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + volt = self.__convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + if volt is not None: + transceiver_dom_info_dict['voltage'] = volt + + start = QSFP_CHANNL_MON_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power( + dom_data_raw[start: end], 0) + + if self.dom_tx_power_supported: + transceiver_dom_info_dict['tx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX1Power']['value']) + transceiver_dom_info_dict['tx2power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX2Power']['value']) + transceiver_dom_info_dict['tx3power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX3Power']['value']) + transceiver_dom_info_dict['tx4power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX4Power']['value']) + + if self.dom_rx_power_supported: + transceiver_dom_info_dict['rx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX1Power']['value']) + transceiver_dom_info_dict['rx2power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX2Power']['value']) + transceiver_dom_info_dict['rx3power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX3Power']['value']) + transceiver_dom_info_dict['rx4power'] = self.__convert_string_to_num( + 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: + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + if sfpd_obj._calibration_type == 1: + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_DOM_BULK_DATA_START), SFP_DOM_BULK_DATA_SIZE) + start = SFP_TEMPE_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + + start = SFP_VOLT_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + + start = SFP_CHANNL_MON_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_CHANNL_MON_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_data_raw[start: end], 0) + else: + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset), offset + 256) + dom_temperature_data = sfpd_obj.parse_temperature(dom_data_raw, 0) + + dom_voltage_data = sfpd_obj.parse_voltage(dom_data_raw, 0) + + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_data_raw, 0) + + transceiver_dom_info_dict['temperature'] = self.__convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + transceiver_dom_info_dict['voltage'] = self.__convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + transceiver_dom_info_dict['rx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RXPower']['value']) + transceiver_dom_info_dict['tx1bias'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXBias']['value']) + transceiver_dom_info_dict['tx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXPower']['value']) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['tx_disable'] = self.get_tx_disable() + transceiver_dom_info_dict['tx_disabled_channel'] = self.get_tx_disable_channel() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + self.__dom_capability_detect() + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + transceiver_dom_threshold_info_dict = dict.fromkeys( + self.threshold_dict_keys, 'N/A') + + if self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + if not self.dom_supported or not self.qsfp_page3_available: + return transceiver_dom_threshold_info_dict + + # Dom Threshold data starts from offset 384 + # Revert offset back to 0 once data is retrieved + offset = QSFP_MODULE_UPPER_PAGE3_START + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values( + dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNL_THRESHOLD_OFFSET), + QSFP_CHANNL_THRESHOLD_WIDTH) + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values( + dom_channel_threshold_raw, 0) + + # 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'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + + else: + offset = SFP_MODULE_ADDRA2_OFFSET + + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = sff8472Dom(None, self.calibration) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + sfpd_obj._calibration_type = self.calibration + + if sfpd_obj._calibration_type == 1: + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + SFP_MODULE_THRESHOLD_OFFSET), + SFP_MODULE_THRESHOLD_WIDTH) + else: + dom_module_threshold_raw = self.__read_eeprom_specific_bytes( + (offset), offset + 256) + 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 + + # 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 + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + transceiver_bulk_status = self.get_transceiver_bulk_status() + if transceiver_bulk_status is not None: + return transceiver_bulk_status.get("temperature", "N/A") + else: + return None + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + transceiver_bulk_status = self.get_transceiver_bulk_status() + if transceiver_bulk_status is not None: + return transceiver_bulk_status.get("voltage", "N/A") + else: + return None + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + tx_bias_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (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) + tx_bias_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX4Bias']['value'])) + else: + return None + else: + return None + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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) + tx_bias_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXBias']['value'])) + else: + return None + else: + return None + + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + rx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (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) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RX4Power']['value'])) + else: + return None + else: + return None + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RXPower']['value'])) + else: + return None + else: + return None + + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + tx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_tx_power_supported: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (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) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TX4Power']['value'])) + else: + return None + else: + return None + else: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXPower']['value'])) + else: + return None + else: + return None + + return tx_power_list + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + if not self.dom_supported: + return None + + rx_los_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x02 != 0) + else: + return None + + return rx_los_list + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + if not self.dom_supported: + return None + tx_fault_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + else: + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + else: + return None + + return tx_fault_list + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + # Check for invalid self.port_num + if self.port_num < PORT_START or self.port_num > PORT_END: + return None + if not self.dom_supported: + return None + + tx_disable_list = [] + + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + QSFP_CHANNL_DISABLE_STATUS_OFFSET), QSFP_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0x01 != 0) + tx_disable_list.append(tx_disable_data & 0x02 != 0) + tx_disable_list.append(tx_disable_data & 0x04 != 0) + tx_disable_list.append(tx_disable_data & 0x08 != 0) + else: + if self.port_num <= 7: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis1" + elif self.port_num >= 8 and self.port_num <= 15: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis2" + elif self.port_num >= 16 and self.port_num <= 23: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis3" + elif self.port_num >= 24 and self.port_num <= 31: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis4" + elif self.port_num >= 32 and self.port_num <= 39: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis5" + elif self.port_num >= 40 and self.port_num <= 47: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis6" + else: + return None + try: + data = open(txdis_path, "rb") + except IOError: + return None + + txdis_data = data.read(2) + if txdis_data == "": + return None + result = int(txdis_data, 16) + data.close() + + # ModPrsL is active low + tx_disable_list.append(result & (1 << (self.port_num % 8)) != 0) + + return tx_disable_list + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + ''' + Not support LPMode pin to control lpmde. + This function is affected by the Power_over-ride and Power_set software control bits (byte 93 bits 0,1) + ''' + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + offset + QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + lpmode = ('On' == dom_control_data['data']['PowerSet']['value']) + power_override = ('On' == dom_control_data['data']['PowerOverride']['value']) + if lpmode == power_override == True: + return True + elif self.sfp_type == SFP_TYPE: + # SFP doesn't support this feature + return False + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + offset + QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + power_override = ('On' == dom_control_data['data']['PowerOverride']['value']) + return power_override + elif self.sfp_type == SFP_TYPE: + # SFP doesn't support this feature + return False + return False + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + if self.port_num >= 48 and self.port_num <= 55: + reset_path = "/sys/bus/i2c/devices/1-0036/qsfp_reset" + else: + return False + try: + data = open(reset_path, "rb") + except IOError: + return None + + reset_data = data.read(2) + if reset_data == "": + return None + result = int(reset_data, 16) + data.close() + reset_status = result & (1 << (self.port_num % 8)) == 0 + return reset_status + + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + offset = 0 + sysfsfile_eeprom = None + try: + tx_disable_ctl = 0xf if tx_disable else 0x0 + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self.__get_port_eeprom_path(self.port_num, IDENTITY_EEPROM_ADDR) + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(offset + QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + elif self.sfp_type == SFP_TYPE: + if self.port_num <= 7: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis1" + elif self.port_num >= 8 and self.port_num <= 15: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis2" + elif self.port_num >= 16 and self.port_num <= 23: + txdis_path = "/sys/bus/i2c/devices/1-0034/sfp_txdis3" + elif self.port_num >= 24 and self.port_num <= 31: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis4" + elif self.port_num >= 32 and self.port_num <= 39: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis5" + elif self.port_num >= 40 and self.port_num <= 47: + txdis_path = "/sys/bus/i2c/devices/1-0036/sfp_txdis6" + else: + return False + try: + data = open(txdis_path, "r+") + txdis_data = data.read(2) + if txdis_data == "": + return False + result = int(txdis_data, 16) + if tx_disable: + result = result | (1 << (self.port_num % 8)) + else: + result = result & (~(1 << (self.port_num % 8))) + data.seek(0) + sres = hex(result)[2:] + data.write(sres) + data.close() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + return True + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + offset = 0 + if 0 <= channel <= 15: + try: + channel_state = self.get_tx_disable_channel() + if disable: + tx_disable_ctl = channel_state | channel + else: + tx_disable_ctl = channel_state & (~channel) + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self.__get_port_eeprom_path(self.port_num, IDENTITY_EEPROM_ADDR) + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(offset + QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + elif self.sfp_type == SFP_TYPE: + # SFP doesn't support this feature + return False + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + ''' + Not support LPMode pin to control lpmde. + This function is affected by the Power_over-ride and Power_set software control bits (byte 93 bits 0,1) + ''' + if lpmode: + return self.set_power_override(True, lpmode) + else: + return self.set_power_override(False, lpmode) + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + offset = 0 + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfs_sfp_i2c_client_eeprom_path = self.__get_port_eeprom_path(self.port_num, IDENTITY_EEPROM_ADDR) + sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, "r+b") + sysfsfile_eeprom.seek(offset + QSFP_POWERMODE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + elif self.sfp_type == SFP_TYPE: + # SFP doesn't support this feature + return False + return False + + def reset(self, reset): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + if self.port_num < PORT_START or self.port_num > PORT_END: + return False + if self.sfp_type == QSFP_TYPE: + if self.port_num >= 48 and self.port_num <= 55: + reset_path = "/sys/bus/i2c/devices/1-0036/qsfp_reset" + else: + return False + try: + data = open(reset_path, "r+") + reset_data = data.read(2) + if reset_data == "": + return False + result = int(reset_data, 16) + if reset: + result = result & (~(1 << (self.port_num % 8))) + else: + result = result | (1 << (self.port_num % 8)) + data.seek(0) + sres = hex(result)[2:] + data.write(sres) + data.close() + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + + return True + elif self.sfp_type == SFP_TYPE: + # SFP doesn't support this feature + return False + return False + + def read_eeprom(self, offset, num_bytes): + """ + read eeprom specfic bytes beginning from a random offset with size as num_bytes + Args: + offset : + Integer, the offset from which the read transaction will start + num_bytes: + Integer, the number of bytes to be read + Returns: + bytearray, if raw sequence of bytes are read correctly from the offset of size num_bytes + None, if the read_eeprom fails + """ + raise NotImplementedError + + def write_eeprom(self, offset, num_bytes, write_buffer): + """ + write eeprom specfic bytes beginning from a random offset with size as num_bytes + and write_buffer as the required bytes + Args: + offset : + Integer, the offset from which the read transaction will start + num_bytes: + Integer, the number of bytes to be written + write_buffer: + bytearray, raw bytes buffer which is to be written beginning at the offset + Returns: + a Boolean, true if the write succeeded and false if it did not succeed. + """ + raise NotImplementedError + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/thermal.py new file mode 100644 index 000000000000..49beb8e16339 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/thermal.py @@ -0,0 +1,217 @@ +######################################################################## +# Ruijie B6510-48VS8CQ +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + from sonic_platform_base.thermal_base import ThermalBase + from sonic_platform.regutil import Reg + from sonic_platform.logger import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + def __init__(self, index, config=None, hal_thermal=None): + self.index = index + if config: + self.name = config.get("name") + self.__reg_low_threshold = Reg(config.get("low")) + self.__reg_high_thresnold = Reg(config.get("high")) + self.__reg_crit_low_threshold = Reg(config.get("crit_low")) + self.__reg_crit_high_thresnold = Reg(config.get("crit_high")) + self.__reg_temperature = Reg(config.get("temperature")) + self.minimum_thermal = self.get_temperature() + self.maximum_thermal = self.get_temperature() + + def get_name(self): + """ + Retrieves the name of the thermal + + Returns: + string: The name of the thermal + """ + return self.name + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return "NA" + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return "NA" + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + if self.get_temperature() == 0.0: + return False + + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + try: + if isinstance(self.__reg_temperature, Reg): + return self.__reg_temperature.decode() + except Exception as e: + logger.error(str(e)) + + return None + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + try: + if isinstance(self.__reg_high_thresnold, Reg): + return float(self.__reg_high_thresnold.decode()) + except Exception as e: + logger.error(str(e)) + + return None + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + try: + if isinstance(self.__reg_low_threshold, Reg): + return float(self.__reg_low_threshold.decode()) + except Exception as e: + logger.error(str(e)) + + return None + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + try: + if isinstance(self.__reg_high_thresnold, Reg): + temp_val = str(int(temperature * 1000)) + return self.__reg_high_thresnold.encode(temp_val) + except Exception as e: + logger.error(str(e)) + + return False + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + # not supported + return False + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + try: + if isinstance(self.__reg_crit_high_thresnold, Reg): + return float(self.__reg_crit_high_thresnold.decode()) + except Exception as e: + logger.error(str(e)) + + return None + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature of thermal + + Returns: + A float number, the low critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + try: + if isinstance(self.__reg_crit_low_threshold, Reg): + return float(self.__reg_crit_low_threshold.decode()) + except Exception as e: + logger.error(str(e)) + + return None + + def get_minimum_recorded(self): + """ + Retrieves the minimum recorded temperature of thermal + Returns: + A float number, the minimum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + tmp = self.get_temperature() + if tmp < self.minimum_thermal: + self.minimum_thermal = tmp + raise self.minimum_thermal + + def get_maximum_recorded(self): + """ + Retrieves the maximum recorded temperature of thermal + Returns: + A float number, the maximum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + tmp = self.get_temperature() + if tmp > self.maximum_thermal: + self.maximum_thermal = tmp + raise self.maximum_thermal + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/watchdog.py new file mode 100644 index 000000000000..6c3939c5a1ee --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/sonic_platform/watchdog.py @@ -0,0 +1,70 @@ +######################################################################## +# +# Ruijie B6510-48VS8CQ +# +# Abstract base class for implementing a platform-specific class with +# which to interact with a hardware watchdog module in SONiC +# +######################################################################## + +try: + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Watchdog(WatchdogBase): + """ + Abstract base class for interfacing with a hardware watchdog module + """ + + def __init__(self): + print("INFO: Watchdog __init__") + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* available + value. + + Returns: + An integer specifying the *actual* number of seconds the watchdog + was armed with. On failure returns -1. + """ + print("ERROR: Platform did not implement arm()") + raise NotImplementedError + + def disarm(self): + """ + Disarm the hardware watchdog + + Returns: + A boolean, True if watchdog is disarmed successfully, False if not + """ + print("ERROR: Platform did not implement disarm()") + raise NotImplementedError + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + + Returns: + A boolean, True if watchdog is armed, False if not + """ + print("ERROR: Platform did not implement is_armed()") + raise NotImplementedError + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds remaining on + the watchdog timer + + Returns: + An integer specifying the number of seconds remaining on thei + watchdog timer. If the watchdog is not armed, returns -1. + """ + print("ERROR: Platform did not implement get_remaining_time()") + raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/systemd/platform-modules-b6510-48vs8cq.service b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/systemd/platform-modules-b6510-48vs8cq.service new file mode 100644 index 000000000000..3b0e8a0005e8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/b6510-48vs8cq/systemd/platform-modules-b6510-48vs8cq.service @@ -0,0 +1,13 @@ +[Unit] +Description=b6510-48vs8cq platform modules +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/b6510-48vs8cq_platform.sh init +ExecStop=/usr/local/bin/b6510-48vs8cq_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/Makefile b/platform/broadcom/sonic-platform-modules-ruijie/common/Makefile new file mode 100755 index 000000000000..205a32578e2a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/Makefile @@ -0,0 +1,37 @@ +PWD = $(shell pwd) +CC ?=gcc +INSTALL_MOD_DIR ?=extra +KVERSION ?= $(shell uname -r) +KERNEL_SRC ?= /lib/modules/$(KVERSION) +EXTRA_CFLAGS:= -I$(M)/include +EXTRA_CFLAGS+= -Wall +SUB_BUILD_DIR = $(PWD)/build +DIR_KERNEL_SRC = $(PWD)/modules +SCRIPT_DIR = $(PWD)/script +SERVICE_DIR = $(PWD)/service + +KBUILD_EXTRA_SYMBOLS += $(DIR_KERNEL_SRC)/Module.symvers +export KBUILD_EXTRA_SYMBOLS + +INSTALL_MODULE_DIR = $(SUB_BUILD_DIR)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) +INSTALL_SCRIPT_DIR = $(SUB_BUILD_DIR)/usr/local/bin +INSTALL_SERVICE_DIR = $(SUB_BUILD_DIR)/lib/systemd/system +INSTALL_LIB_DIR = $(SUB_BUILD_DIR)/usr/lib/python3.7/dist-packages + +all: + $(MAKE) -C $(KERNEL_SRC)/build M=$(DIR_KERNEL_SRC) modules + @if [ ! -d ${INSTALL_MODULE_DIR} ]; then mkdir -p ${INSTALL_MODULE_DIR} ;fi + @if [ ! -d ${INSTALL_SCRIPT_DIR} ]; then mkdir -p ${INSTALL_SCRIPT_DIR} ;fi + @if [ ! -d ${INSTALL_SERVICE_DIR} ]; then mkdir -p ${INSTALL_SERVICE_DIR} ;fi + @if [ ! -d ${INSTALL_LIB_DIR} ]; then mkdir -p ${INSTALL_LIB_DIR} ;fi + @if [ -d $(PWD)/lib/ ]; then cp -r $(PWD)/lib/* ${INSTALL_LIB_DIR} ;fi + @if [ -d $(PWD)/lib/ ]; then cp -r $(PWD)/lib/* ${INSTALL_LIB_DIR2} ;fi + cp -r $(DIR_KERNEL_SRC)/*.ko $(INSTALL_MODULE_DIR) + cp -r $(SCRIPT_DIR)/* $(INSTALL_SCRIPT_DIR) + cp -r $(SERVICE_DIR)/* $(INSTALL_SERVICE_DIR) + @if [ -d $(INSTALL_SCRIPT_DIR) ]; then chmod +x $(INSTALL_SCRIPT_DIR)/* ;fi +clean: + rm -f ${DIR_KERNEL_SRC}/*.o ${DIR_KERNEL_SRC}/*.ko ${DIR_KERNEL_SRC}/*.mod.c ${DIR_KERNEL_SRC}/.*.cmd + rm -f ${DIR_KERNEL_SRC}/Module.markers ${DIR_KERNEL_SRC}/Module.symvers ${DIR_KERNEL_SRC}/modules.order + rm -rf ${DIR_KERNEL_SRC}/.tmp_versions + rm -rf $(SUB_BUILD_DIR) diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/__init__.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fantlv.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fantlv.py new file mode 100644 index 000000000000..2d434d1ad2a6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fantlv.py @@ -0,0 +1,212 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +class FantlvException(Exception): + def __init__(self, message='fantlverror', code=-100): + err = 'errcode: {0} message:{1}'.format(code, message) + Exception.__init__(self, err) + self.code = code + self.message = message + +class fan_tlv(object): + HEAD_INFO = "\x01\x7e\x01\xf1" + VERSION = 0x01 # E2PROM file init version is 0x01 + FLAG = 0x7E #new version E2PROM mark as 0x7E + HW_VER = 0X01 # consists of master version and revised version + TYPE = 0xf1 # hardware type define + TLV_LEN = 00 # vaild data length(16bit) + _FAN_TLV_HDR_LEN = 6 + _FAN_TLV_CRC_LEN = 2 + + _FAN_TLV_TYPE_NAME = 0x02 + _FAN_TLV_TYPE_SN = 0x03 + _FAN_TLV_TYPE_HW_INFO = 0x05 + _FAN_TLV_TYPE_DEV_TYPE = 0x06 + + _fandecodetime = 0 + + @property + def dstatus(self): + return self._dstatus + + @property + def typename(self): + return self._typename + + @property + def typesn(self): + return self._typesn + + @property + def typehwinfo(self): + return self._typehwinfo + + @property + def typedevtype(self): + return self._typedevtype + + @property + def fanbus(self): + return self._fanbus + + @property + def fanloc(self): + return self._fanloc + + @property + def fandecodetime(self): + return self._fandecodetime + + def __init__(self): + self._typename = "" + self._typesn = "" + self._typehwinfo = "" + self._typedevtype = "" + self._dstatus = 0 + + def strtoarr(self, str): + s = [] + if str is not None: + for index in range(len(str)): + s.append(str[index]) + return s + + def str_to_hex(self,rest_v): + value = 0 + for index in range(len(rest_v)): + value |= ord(rest_v[index]) << ((len(rest_v) - index - 1) * 8) + return value + + def hex_to_str(self,s): + len_t = len(s) + if len_t % 2 != 0: + return 0 + ret = "" + for t in range(0, int(len_t / 2)): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + return ret + + def generate_fan_value(self): + bin_buffer = [chr(0xff)] * 256 + bin_buffer[0] = chr(self.VERSION) + bin_buffer[1] = chr(self.FLAG) + bin_buffer[2] = chr(self.HW_VER) + bin_buffer[3] = chr(self.TYPE) + + temp_t = "%08x" % self.typedevtype # handle devtype first + typedevtype_t = self.hex_to_str(temp_t) + total_len = len(self.typename) + len(self.typesn) + \ + len(self.typehwinfo) + len(typedevtype_t) + 8 + + bin_buffer[4] = chr(total_len >> 8) + bin_buffer[5] = chr(total_len & 0x00FF) + + index_start = 6 + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_NAME) + bin_buffer[index_start + 1] = chr(len(self.typename)) + bin_buffer[index_start + 2: index_start + 2 + + len(self.typename)] = self.strtoarr(self.typename) + index_start = index_start + 2 + len(self.typename) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_SN) + bin_buffer[index_start + 1] = chr(len(self.typesn)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typesn)] = self.strtoarr(self.typesn) + index_start = index_start + 2 + len(self.typesn) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_HW_INFO) + bin_buffer[index_start + 1] = chr(len(self.typehwinfo)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typehwinfo)] = self.strtoarr(self.typehwinfo) + index_start = index_start + 2 + len(self.typehwinfo) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_DEV_TYPE) + bin_buffer[index_start + 1] = chr(len(typedevtype_t)) + bin_buffer[index_start + 2:index_start + 2 + + len(typedevtype_t)] = self.strtoarr(typedevtype_t) + index_start = index_start + 2 + len(typedevtype_t) + + crcs = fan_tlv.fancrc(''.join(bin_buffer[0:index_start])) # 2bytes checking + bin_buffer[index_start] = chr(crcs >> 8) + bin_buffer[index_start + 1] = chr(crcs & 0x00ff) + # printvalue(bin_buffer) + return bin_buffer + + def decode(self, e2): + if e2[0:4] != self.HEAD_INFO: + raise FantlvException("Fan tlv head info error,not fan tlv type", -10) + ret = [] + self.VERSION = ord(e2[0]) + self.FLAG = ord(e2[1]) + self.HW_VER = ord(e2[2]) + self.TYPE = ord(e2[3]) + self.TLV_LEN = (ord(e2[4]) << 8) | ord(e2[5]) + + tlv_index = self._FAN_TLV_HDR_LEN + tlv_end = self._FAN_TLV_HDR_LEN + self.TLV_LEN + + # check sum + if len(e2) < self._FAN_TLV_HDR_LEN + self.TLV_LEN + 2: + raise FantlvException("Fan tlv eeprom len error!", -2) + sumcrc = fan_tlv.fancrc(e2[0:self._FAN_TLV_HDR_LEN + self.TLV_LEN]) + readcrc = ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN] + ) << 8 | ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN + 1]) + if sumcrc != readcrc: + raise FantlvException("Fan tlv eeprom checksum error!", -1) + else: + self._dstatus = 0 + while (tlv_index + 2) < len(e2) and tlv_index < tlv_end: + s = self.decoder( + e2[tlv_index:tlv_index + 2 + ord(e2[tlv_index + 1])]) + tlv_index += ord(e2[tlv_index + 1]) + 2 + ret.append(s) + + return ret + + @staticmethod + def fancrc(t): + sum = 0 + for index in range(len(t)): + sum += ord(t[index]) + return sum + + def decoder(self, t): + try: + name = "" + value = "" + if ord(t[0]) == self._FAN_TLV_TYPE_NAME: + name = "Product Name" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._typename = value + elif ord(t[0]) == self._FAN_TLV_TYPE_SN: + name = "serial Number" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._typesn = value + elif ord(t[0]) == self._FAN_TLV_TYPE_HW_INFO: + name = "hardware info" + _len = ord(t[1]) + value = t[2:2 + ord(t[1])] + self._typehwinfo = value + elif ord(t[0]) == self._FAN_TLV_TYPE_DEV_TYPE: + name = "dev type" + _len = ord(t[1]) + value = "0x" + for c in t[2:2 + ord(t[1])]: + value += "%02X" % (ord(c),) + self._typedevtype = int(value,16) + except Exception as e: + print(e) + return {"name": name, "code": ord(t[0]), "value": value,"lens": _len} + + def __str__(self): + formatstr = "VERSION : 0x%02x \n" \ + " FLAG : 0x%02x \n" \ + " HW_VER : 0x%02x \n" \ + " TYPE : 0x%02x \n" \ + "typename : %s \n" \ + "typesn : %s \n" \ + "typehwinfo : %s \n" + return formatstr % (self.VERSION, self.FLAG, self.HW_VER, self.TYPE, self.typename, self.typesn, self.typehwinfo) + + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fru.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fru.py new file mode 100644 index 000000000000..892d0619468b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/eepromutil/fru.py @@ -0,0 +1,954 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +import collections +from bitarray import bitarray +from datetime import datetime, timedelta +import sys + +__all__ = ["FruException", "FruUtil", "BaseArea", "BoardInfoArea", "ProductInfoArea", + "MultiRecordArea", "Field", "ipmifru"] + +__DEBUG__ = "N" + + +class FruException(Exception): + def __init__(self, message='fruerror', code=-100): + err = 'errcode: {0} message:{1}'.format(code, message) + Exception.__init__(self, err) + self.code = code + self.message = message + + +def e_print(err): + print("ERROR: " + err) + + +def d_print(debug_info): + if(__DEBUG__ == "Y"): + print(debug_info) + + +class FruUtil(): + @staticmethod + def decodeLength(value): + a = bitarray(8) + a.setall(True) + a[0:1] = 0 + a[1:2] = 0 + x = ord(a.tobytes()) + return x & ord(value) + + @staticmethod + def minToData(): + starttime = datetime(1996, 1, 1, 0, 0, 0) + endtime = datetime.now() + seconds = (endtime - starttime).total_seconds() + mins = seconds / 60 + m = int(round(mins)) + return m + + @staticmethod + def getTimeFormat(): + return datetime.now().strftime('%Y-%m-%d') + + @staticmethod + def getTypeLength(value): + if value is None: + return 0 + a = bitarray(8) + a.setall(False) + a[0:1] = 1 + a[1:2] = 1 + x = ord(a.tobytes()) + return x | len(value) + + @staticmethod + def checksum(b): + result = 0 + for i in range(len(b)): + result += ord(b[i]) + return (0x100 - (result & 0xff)) & 0xff + + +class BaseArea(object): + SUGGESTED_SIZE_COMMON_HEADER = 8 + SUGGESTED_SIZE_INTERNAL_USE_AREA = 72 + SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32 + SUGGESTED_SIZE_BOARD_INFO_AREA = 80 + SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80 + + INITVALUE = b'\x00' + resultvalue = INITVALUE * 256 + COMMON_HEAD_VERSION = b'\x01' + __childList = None + + def __init__(self, name="", size=0, offset=0): + self.__childList = [] + self._offset = offset + self.name = name + self._size = size + self._isPresent = False + self._data = b'\x00' * size + self.__dataoffset = 0 + + @property + def childList(self): + return self.__childList + + @childList.setter + def childList(self, value): + self.__childList = value + + @property + def offset(self): + return self._offset + + @offset.setter + def offset(self, value): + self._offset = value + + @property + def size(self): + return self._size + + @size.setter + def size(self, value): + self._size = value + + @property + def data(self): + return self._data + + @data.setter + def data(self, value): + self._data = value + + @property + def isPresent(self): + return self._isPresent + + @isPresent.setter + def isPresent(self, value): + self._isPresent = value + + +class InternalUseArea(BaseArea): + pass + + +class ChassisInfoArea(BaseArea): + pass + + +class BoardInfoArea(BaseArea): + _boardTime = None + _fields = None + _mfg_date = None + + def __str__(self): + formatstr = "version : %x\n" \ + "length : %d \n" \ + "language : %x \n" \ + "mfg_date : %s \n" \ + "boardManufacturer : %s \n" \ + "boardProductName : %s \n" \ + "boardSerialNumber : %s \n" \ + "boardPartNumber : %s \n" \ + "fruFileId : %s \n" + + tmpstr = formatstr % (ord(self.boardversion), self.size, + self.language, self.getMfgRealData(), + self.boardManufacturer, self.boardProductName, + self.boardSerialNumber, self.boardPartNumber, + self.fruFileId) + for i in range(1, 11): + valtmp = "boardextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + tmpstr += "boardextra%d : %s \n" % (i, valtmpval) + else: + break + + return tmpstr + + def todict(self): + dic = collections.OrderedDict() + dic["boardversion"] = ord(self.boardversion) + dic["boardlength"] = self.size + dic["boardlanguage"] = self.language + dic["boardmfg_date"] = self.getMfgRealData() + dic["boardManufacturer"] = self.boardManufacturer + dic["boardProductName"] = self.boardProductName + dic["boardSerialNumber"] = self.boardSerialNumber + dic["boardPartNumber"] = self.boardPartNumber + dic["boardfruFileId"] = self.fruFileId + for i in range(1, 11): + valtmp = "boardextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + dic[valtmp] = valtmpval + else: + break + return dic + + def decodedata(self): + index = 0 + self.areaversion = self.data[index] + index += 1 + d_print("decode length :%d class size:%d" % + ((ord(self.data[index]) * 8), self.size)) + index += 2 + + timetmp = self.data[index: index + 3] + self.mfg_date = ord(timetmp[0]) | ( + ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16) + d_print("decode getMfgRealData :%s" % self.getMfgRealData()) + index += 3 + + templen = FruUtil.decodeLength(self.data[index]) + self.boardManufacturer = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardManufacturer:%s" % self.boardManufacturer) + + templen = FruUtil.decodeLength(self.data[index]) + self.boardProductName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardProductName:%s" % self.boardProductName) + + templen = FruUtil.decodeLength(self.data[index]) + self.boardSerialNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardSerialNumber:%s" % self.boardSerialNumber) + + templen = FruUtil.decodeLength(self.data[index]) + self.boardPartNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode boardPartNumber:%s" % self.boardPartNumber) + + templen = FruUtil.decodeLength(self.data[index]) + self.fruFileId = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode fruFileId:%s" % self.fruFileId) + + + for i in range(1, 11): + valtmp = "boardextra%d" % i + if self.data[index] != chr(0xc1): + templen = FruUtil.decodeLength(self.data[index]) + tmpval = self.data[index + 1: index + templen + 1] + setattr(self, valtmp, tmpval) + index += templen + 1 + d_print("decode boardextra%d:%s" % (i, tmpval)) + else: + break + + def recalcute(self): + d_print("boardInfoArea version:%x" % ord(self.boardversion)) + d_print("boardInfoArea length:%d" % self.size) + d_print("boardInfoArea language:%x" % self.language) + self.mfg_date = FruUtil.minToData() + d_print("boardInfoArea mfg_date:%x" % self.mfg_date) + + self.data = chr(ord(self.boardversion)) + \ + chr(self.size / 8) + chr(self.language) + + self.data += chr(self.mfg_date & 0xFF) + self.data += chr((self.mfg_date >> 8) & 0xFF) + self.data += chr((self.mfg_date >> 16) & 0xFF) + + d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer) + typelength = FruUtil.getTypeLength(self.boardManufacturer) + self.data += chr(typelength) + self.data += self.boardManufacturer + + d_print("boardInfoArea boardProductName:%s" % self.boardProductName) + self.data += chr(FruUtil.getTypeLength(self.boardProductName)) + self.data += self.boardProductName + + d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber) + self.data += chr(FruUtil.getTypeLength(self.boardSerialNumber)) + self.data += self.boardSerialNumber + + d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber) + self.data += chr(FruUtil.getTypeLength(self.boardPartNumber)) + self.data += self.boardPartNumber + + d_print("boardInfoArea fruFileId:%s" % self.fruFileId) + self.data += chr(FruUtil.getTypeLength(self.fruFileId)) + self.data += self.fruFileId + + for i in range(1, 11): + valtmp = "boardextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + d_print("boardInfoArea boardextra%d:%s" % (i, valtmpval)) + self.data += chr(FruUtil.getTypeLength(valtmpval)) + if valtmpval is None: + pass + else: + self.data += valtmpval + else: + break + + self.data += chr(0xc1) + + if len(self.data) > (self.size - 1): + incr = (len(self.data) - self.size) / 8 + 1 + self.size += incr * 8 + + self.data = self.data[0:1] + chr(self.size / 8) + self.data[2:] + d_print("self data:%d" % len(self.data)) + d_print("self size:%d" % self.size) + d_print("adjust size:%d" % (self.size - len(self.data) - 1)) + self.data = self.data.ljust((self.size - 1), self.INITVALUE) + + # checksum + checksum = FruUtil.checksum(self.data) + d_print("board info checksum:%x" % checksum) + self.data += chr(checksum) + + def getMfgRealData(self): + starttime = datetime(1996, 1, 1, 0, 0, 0) + mactime = starttime + timedelta(minutes=self.mfg_date) + return mactime + + @property + def language(self): + self._language = 25 + return self._language + + @property + def mfg_date(self): + return self._mfg_date + + @mfg_date.setter + def mfg_date(self, val): + self._mfg_date = val + + @property + def boardversion(self): + self._boardversion = self.COMMON_HEAD_VERSION + return self._boardversion + + @property + def fruFileId(self): + return self._FRUFileID + + @fruFileId.setter + def fruFileId(self, val): + self._FRUFileID = val + + @property + def boardPartNumber(self): + return self._boardPartNumber + + @boardPartNumber.setter + def boardPartNumber(self, val): + self._boardPartNumber = val + + @property + def boardSerialNumber(self): + return self._boardSerialNumber + + @boardSerialNumber.setter + def boardSerialNumber(self, val): + self._boardSerialNumber = val + + @property + def boardProductName(self): + return self._boradProductName + + @boardProductName.setter + def boardProductName(self, val): + self._boradProductName = val + + @property + def boardManufacturer(self): + return self._boardManufacturer + + @boardManufacturer.setter + def boardManufacturer(self, val): + self._boardManufacturer = val + + @property + def boardTime(self): + return self._boardTime + + @boardTime.setter + def boardTime(self, val): + self._boardTime = val + + @property + def fields(self): + return self._fields + + @fields.setter + def fields(self, val): + self._fields = val + + +class ProductInfoArea(BaseArea): + _productManufacturer = None + _productAssetTag = None + _FRUFileID = None + + def __str__(self): + formatstr = "version : %x\n" \ + "length : %d \n" \ + "language : %x \n" \ + "productManufacturer : %s \n" \ + "productName : %s \n" \ + "productPartModelName: %s \n" \ + "productVersion : %s \n" \ + "productSerialNumber : %s \n" \ + "productAssetTag : %s \n" \ + "fruFileId : %s \n" + + tmpstr = formatstr % (ord(self.areaversion), self.size, + self.language, self.productManufacturer, + self.productName, self.productPartModelName, + self.productVersion, self.productSerialNumber, + self.productAssetTag, self.fruFileId) + + for i in range(1, 11): + valtmp = "productextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + tmpstr += "productextra%d : %s \n" % (i, valtmpval) + else: + break + + return tmpstr + + def todict(self): + dic = collections.OrderedDict() + dic["productversion"] = ord(self.areaversion) + dic["productlength"] = self.size + dic["productlanguage"] = self.language + dic["productManufacturer"] = self.productManufacturer + dic["productName"] = self.productName + dic["productPartModelName"] = self.productPartModelName + dic["productVersion"] = int(self.productVersion, 16) + dic["productSerialNumber"] = self.productSerialNumber + dic["productAssetTag"] = self.productAssetTag + dic["productfruFileId"] = self.fruFileId + for i in range(1, 11): + valtmp = "productextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + dic[valtmp] = valtmpval + else: + break + return dic + + def decodedata(self): + index = 0 + self.areaversion = self.data[index] # 0 + index += 1 + d_print("decode length %d" % (ord(self.data[index]) * 8)) + d_print("class size %d" % self.size) + index += 2 + + templen = FruUtil.decodeLength(self.data[index]) + self.productManufacturer = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productManufacturer:%s" % self.productManufacturer) + + templen = FruUtil.decodeLength(self.data[index]) + self.productName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productName:%s" % self.productName) + + templen = FruUtil.decodeLength(self.data[index]) + self.productPartModelName = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productPartModelName:%s" % self.productPartModelName) + + templen = FruUtil.decodeLength(self.data[index]) + self.productVersion = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productVersion:%s" % self.productVersion) + + templen = FruUtil.decodeLength(self.data[index]) + self.productSerialNumber = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productSerialNumber:%s" % self.productSerialNumber) + + templen = FruUtil.decodeLength(self.data[index]) + self.productAssetTag = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode productAssetTag:%s" % self.productAssetTag) + + templen = FruUtil.decodeLength(self.data[index]) + self.fruFileId = self.data[index + 1: index + templen + 1] + index += templen + 1 + d_print("decode fruFileId:%s" % self.fruFileId) + + for i in range(1, 11): + valtmp = "productextra%d" % i + if self.data[index] != chr(0xc1) and index < self.size - 1: + templen = FruUtil.decodeLength(self.data[index]) + if templen == 0: + break + tmpval = self.data[index + 1: index + templen + 1] + d_print("decode boardextra%d:%s" % (i, tmpval)) + setattr(self, valtmp, tmpval) + index += templen + 1 + else: + break + + @property + def productVersion(self): + return self._productVersion + + @productVersion.setter + def productVersion(self, name): + self._productVersion = name + + @property + def areaversion(self): + self._areaversion = self.COMMON_HEAD_VERSION + return self._areaversion + + @areaversion.setter + def areaversion(self, name): + self._areaversion = name + + @property + def language(self): + self._language = 25 + return self._language + + @property + def productManufacturer(self): + return self._productManufacturer + + @productManufacturer.setter + def productManufacturer(self, name): + self._productManufacturer = name + + @property + def productName(self): + return self._productName + + @productName.setter + def productName(self, name): + self._productName = name + + @property + def productPartModelName(self): + return self._productPartModelName + + @productPartModelName.setter + def productPartModelName(self, name): + self._productPartModelName = name + + @property + def productSerialNumber(self): + return self._productSerialNumber + + @productSerialNumber.setter + def productSerialNumber(self, name): + self._productSerialNumber = name + + @property + def productAssetTag(self): + return self._productAssetTag + + @productAssetTag.setter + def productAssetTag(self, name): + self._productAssetTag = name + + @property + def fruFileId(self): + return self._FRUFileID + + @fruFileId.setter + def fruFileId(self, name): + self._FRUFileID = name + + def recalcute(self): + d_print("product version:%x" % ord(self.areaversion)) + d_print("product length:%d" % self.size) + d_print("product language:%x" % self.language) + self.data = chr(ord(self.areaversion)) + \ + chr(self.size / 8) + chr(self.language) + + typelength = FruUtil.getTypeLength(self.productManufacturer) + self.data += chr(typelength) + self.data += self.productManufacturer + + self.data += chr(FruUtil.getTypeLength(self.productName)) + self.data += self.productName + + self.data += chr(FruUtil.getTypeLength(self.productPartModelName)) + self.data += self.productPartModelName + + self.data += chr(FruUtil.getTypeLength(self.productVersion)) + self.data += self.productVersion + + self.data += chr(FruUtil.getTypeLength(self.productSerialNumber)) + self.data += self.productSerialNumber + + self.data += chr(FruUtil.getTypeLength(self.productAssetTag)) + if self.productAssetTag is not None: + self.data += self.productAssetTag + + self.data += chr(FruUtil.getTypeLength(self.fruFileId)) + self.data += self.fruFileId + + # 判断拓展字段是否存在, 拓展字段必须按顺序来 + for i in range(1, 11): + valtmp = "productextra%d" % i + if hasattr(self, valtmp): + valtmpval = getattr(self, valtmp) + d_print("boardInfoArea productextra%d:%s" % (i, valtmpval)) + self.data += chr(FruUtil.getTypeLength(valtmpval)) + if valtmpval is None: + pass + else: + self.data += valtmpval + else: + break + + self.data += chr(0xc1) + if len(self.data) > (self.size - 1): + incr = (len(self.data) - self.size) / 8 + 1 + self.size += incr * 8 + d_print("self.data:%d" % len(self.data)) + d_print("self.size:%d" % self.size) + + self.data = self.data[0:1] + chr(self.size / 8) + self.data[2:] + self.data = self.data.ljust((self.size - 1), self.INITVALUE) + checksum = FruUtil.checksum(self.data) + d_print("board info checksum:%x" % checksum) + self.data += chr(checksum) + + +class MultiRecordArea(BaseArea): + pass + + +class Field(object): + + def __init__(self, fieldType="ASCII", fieldData=""): + self.fieldData = fieldData + self.fieldType = fieldType + + @property + def data(self): + return self._data + + @property + def fieldType(self): + return self._fieldType + + @property + def fieldData(self): + return self._fieldData + + +class ipmifru(BaseArea): + _BoardInfoArea = None + _ProductInfoArea = None + _InternalUseArea = None + _ChassisInfoArea = None + _multiRecordArea = None + _productinfoAreaOffset = BaseArea.INITVALUE + _boardInfoAreaOffset = BaseArea.INITVALUE + _internalUserAreaOffset = BaseArea.INITVALUE + _chassicInfoAreaOffset = BaseArea.INITVALUE + _multiRecordAreaOffset = BaseArea.INITVALUE + _bindata = None + _bodybin = None + _version = BaseArea.COMMON_HEAD_VERSION + _zeroCheckSum = None + + def __str__(self): + tmpstr = "" + if self.boardInfoArea.isPresent: + tmpstr += "\nboardinfoarea: \n" + tmpstr += self.boardInfoArea.__str__() + if self.productInfoArea.isPresent: + tmpstr += "\nproductinfoarea: \n" + tmpstr += self.productInfoArea.__str__() + return tmpstr + + def decodeBin(self, eeprom): + commonHead = eeprom[0:8] + d_print("decode version %x" % ord(commonHead[0])) + if self.COMMON_HEAD_VERSION != commonHead[0]: + raise FruException("HEAD VERSION error,not Fru format!", -10) + if FruUtil.checksum(commonHead[0:7]) != ord(commonHead[7]): + strtemp = "check header checksum error [cal:%02x data:%02x]" % ( + FruUtil.checksum(commonHead[0:7]), ord(commonHead[7])) + raise FruException(strtemp, -3) + if commonHead[1] != self.INITVALUE: + d_print("Internal Use Area is present") + self.internalUseArea = InternalUseArea( + name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA) + self.internalUseArea.isPresent = True + self.internalUserAreaOffset = ord(commonHead[1]) + self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: ( + self.internalUserAreaOffset * 8 + self.internalUseArea.size)] + if commonHead[2] != self.INITVALUE: + d_print("Chassis Info Area is present") + self.chassisInfoArea = ChassisInfoArea( + name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA) + self.chassisInfoArea.isPresent = True + self.chassicInfoAreaOffset = ord(commonHead[2]) + self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: ( + self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)] + if commonHead[3] != self.INITVALUE: + self.boardInfoArea = BoardInfoArea( + name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA) + self.boardInfoArea.isPresent = True + self.boardInfoAreaOffset = ord(commonHead[3]) + self.boardInfoArea.size = ord( + eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8 + d_print("Board Info Area is present size:%d" % + (self.boardInfoArea.size)) + self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: ( + self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)] + if FruUtil.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]): + print("check boardInfoArea checksum error[cal:%02x data:%02x]" % \ + (FruUtil.checksum( + self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:]))) + sys.exit(-1) + self.boardInfoArea.decodedata() + if commonHead[4] != self.INITVALUE: + d_print("Product Info Area is present") + self.productInfoArea = ProductInfoArea( + name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA) + self.productInfoArea.isPresent = True + self.productinfoAreaOffset = ord(commonHead[4]) + d_print("length offset value: %02x" % + ord(eeprom[self.productinfoAreaOffset * 8 + 1])) + self.productInfoArea.size = ord( + eeprom[self.productinfoAreaOffset * 8 + 1]) * 8 + d_print("Product Info Area is present size:%d" % + (self.productInfoArea.size)) + + self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: ( + self.productinfoAreaOffset * 8 + self.productInfoArea.size)] + if FruUtil.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]): + strtmp = "check productInfoArea checksum error [cal:%02x data:%02x]" % ( + FruUtil.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:])) + raise FruException(strtmp, -3) + self.productInfoArea.decodedata() + if commonHead[5] != self.INITVALUE: + self.multiRecordArea = MultiRecordArea( + name="MultiRecord record Area ") + d_print("MultiRecord record present") + self.multiRecordArea.isPresent = True + self.multiRecordAreaOffset = ord(commonHead[5]) + self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: ( + self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)] + + def initDefault(self): + self.version = self.COMMON_HEAD_VERSION + self.internalUserAreaOffset = self.INITVALUE + self.chassicInfoAreaOffset = self.INITVALUE + self.boardInfoAreaOffset = self.INITVALUE + self.productinfoAreaOffset = self.INITVALUE + self.multiRecordAreaOffset = self.INITVALUE + self.PAD = self.INITVALUE + self.zeroCheckSum = self.INITVALUE + self.offset = self.SUGGESTED_SIZE_COMMON_HEADER + self.productInfoArea = None + self.internalUseArea = None + self.boardInfoArea = None + self.chassisInfoArea = None + self.multiRecordArea = None + # self.recalcute() + + @property + def version(self): + return self._version + + @version.setter + def version(self, name): + self._version = name + + @property + def internalUserAreaOffset(self): + return self._internalUserAreaOffset + + @internalUserAreaOffset.setter + def internalUserAreaOffset(self, obj): + self._internalUserAreaOffset = obj + + @property + def chassicInfoAreaOffset(self): + return self._chassicInfoAreaOffset + + @chassicInfoAreaOffset.setter + def chassicInfoAreaOffset(self, obj): + self._chassicInfoAreaOffset = obj + + @property + def productinfoAreaOffset(self): + return self._productinfoAreaOffset + + @productinfoAreaOffset.setter + def productinfoAreaOffset(self, obj): + self._productinfoAreaOffset = obj + + @property + def boardInfoAreaOffset(self): + return self._boardInfoAreaOffset + + @boardInfoAreaOffset.setter + def boardInfoAreaOffset(self, obj): + self._boardInfoAreaOffset = obj + + @property + def multiRecordAreaOffset(self): + return self._multiRecordAreaOffset + + @multiRecordAreaOffset.setter + def multiRecordAreaOffset(self, obj): + self._multiRecordAreaOffset = obj + + @property + def zeroCheckSum(self): + return self._zeroCheckSum + + @zeroCheckSum.setter + def zeroCheckSum(self, obj): + self._zeroCheckSum = obj + + @property + def productInfoArea(self): + return self._ProductInfoArea + + @productInfoArea.setter + def productInfoArea(self, obj): + self._ProductInfoArea = obj + + @property + def internalUseArea(self): + return self._InternalUseArea + + @internalUseArea.setter + def internalUseArea(self, obj): + self.internalUseArea = obj + + @property + def boardInfoArea(self): + return self._BoardInfoArea + + @boardInfoArea.setter + def boardInfoArea(self, obj): + self._BoardInfoArea = obj + + @property + def chassisInfoArea(self): + return self._ChassisInfoArea + + @chassisInfoArea.setter + def chassisInfoArea(self, obj): + self._ChassisInfoArea = obj + + @property + def multiRecordArea(self): + return self._multiRecordArea + + @multiRecordArea.setter + def multiRecordArea(self, obj): + self._multiRecordArea = obj + + @property + def bindata(self): + return self._bindata + + @bindata.setter + def bindata(self, obj): + self._bindata = obj + + @property + def bodybin(self): + return self._bodybin + + @bodybin.setter + def bodybin(self, obj): + self._bodybin = obj + + def recalcuteCommonHead(self): + self.bindata = "" + self.offset = self.SUGGESTED_SIZE_COMMON_HEADER + d_print("common Header %d" % self.offset) + if self.internalUseArea is not None and self.internalUseArea.isPresent: + self.internalUserAreaOffset = self.offset / 8 + self.offset += self.internalUseArea.size + d_print("internalUseArea is present offset:%d" % self.offset) + + if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: + self.chassicInfoAreaOffset = self.offset / 8 + self.offset += self.chassisInfoArea.size + d_print("chassisInfoArea is present offset:%d" % self.offset) + + if self.boardInfoArea is not None and self.boardInfoArea.isPresent: + self.boardInfoAreaOffset = self.offset / 8 + self.offset += self.boardInfoArea.size + d_print("boardInfoArea is present offset:%d" % self.offset) + d_print("boardInfoArea is present size:%d" % + self.boardInfoArea.size) + + if self.productInfoArea is not None and self.productInfoArea.isPresent: + self.productinfoAreaOffset = self.offset / 8 + self.offset += self.productInfoArea.size + d_print("productInfoArea is present offset:%d" % self.offset) + + if self.multiRecordArea is not None and self.multiRecordArea.isPresent: + self.multiRecordAreaOffset = self.offset / 8 + d_print("multiRecordArea is present offset:%d" % self.offset) + + if self.internalUserAreaOffset == self.INITVALUE: + self.internalUserAreaOffset = 0 + if self.productinfoAreaOffset == self.INITVALUE: + self.productinfoAreaOffset = 0 + if self.chassicInfoAreaOffset == self.INITVALUE: + self.chassicInfoAreaOffset = 0 + if self.boardInfoAreaOffset == self.INITVALUE: + self.boardInfoAreaOffset = 0 + if self.multiRecordAreaOffset == self.INITVALUE: + self.multiRecordAreaOffset = 0 + + self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset + - self.boardInfoAreaOffset - self.multiRecordAreaOffset) & 0xff + d_print("zerochecksum:%x" % self.zeroCheckSum) + self.data = self.version + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr( + self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + self.INITVALUE + chr(self.zeroCheckSum) + + self.bindata = self.data + self.bodybin + totallen = len(self.bindata) + d_print("totallen %d" % totallen) + if (totallen < 256): + self.bindata = self.bindata.ljust(256, self.INITVALUE) + else: + raise FruException('bin data more than 256', -2) + + def recalcutebin(self): + self.bodybin = "" + if self.internalUseArea is not None and self.internalUseArea.isPresent: + d_print("internalUseArea present") + self.bodybin += self.internalUseArea.data + if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: + d_print("chassisInfoArea present") + self.bodybin += self.chassisInfoArea.data + if self.boardInfoArea is not None and self.boardInfoArea.isPresent: + d_print("boardInfoArea present") + self.boardInfoArea.recalcute() + self.bodybin += self.boardInfoArea.data + if self.productInfoArea is not None and self.productInfoArea.isPresent: + d_print("productInfoAreapresent") + self.productInfoArea.recalcute() + self.bodybin += self.productInfoArea.data + if self.multiRecordArea is not None and self.multiRecordArea.isPresent: + d_print("multiRecordArea present") + self.bodybin += self.productInfoArea.data + + def recalcute(self): + self.recalcutebin() + self.recalcuteCommonHead() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/__init__.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/__init__.py new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/__init__.py @@ -0,0 +1 @@ + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/osutil.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/osutil.py new file mode 100644 index 000000000000..46f3089bbdbf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/plat_hal/osutil.py @@ -0,0 +1,222 @@ +####################################################### +# +# osutil.py +# Python implementation of the Class osutil +# Original author: sonic_rd@ruijie.com.cn +# +####################################################### + +import subprocess +import time +import glob +import re +#import chardet +from rjutil.smbus import SMBus +import time +from functools import wraps + + +def retry(maxretry =6, delay = 0.01): + ''' + maxretry: max retry times + delay : interval after last retry + ''' + def decorator(f): + @wraps(f) + def wrapper(*args, **kwargs): + time_retry = maxretry + time_delay = delay + result_msg = "" + while time_retry: + try: + val , result_msg = f(*args, **kwargs) + if val is False: + time_retry -=1 + time.sleep(time_delay) + continue + else: + return val, result_msg + except Exception as e: + time_retry -= 1 + result_msg = str(e) + time.sleep(time_delay) + return False, "max time retry last errmsg is {}".format(result_msg) + return wrapper + return decorator + +class osutil(object): + """ + osutil + """ + + @staticmethod + @retry(maxretry = 6) + def rji2cget_python(bus, addr, reg): + with SMBus(bus) as y: + val , ind = y.read_byte_data(addr, reg, True) + return val , ind + + + @staticmethod + @retry(maxretry = 6) + def rji2cset_python(bus, addr, reg, value): + with SMBus(bus) as y: + val , ind = y.write_byte_data(addr, reg, value, True) + return val , ind + + @staticmethod + @retry(maxretry = 6) + def rji2cgetword_python(bus, addr, reg): + with SMBus(bus) as y: + val , ind = y.read_word_data(addr, reg, True) + return val , ind + + @staticmethod + @retry(maxretry = 6) + def rji2csetword_python(bus, addr, reg, value): + with SMBus(bus) as y: + val , ind = y.write_word_data(addr, reg, value, True) + return val , ind + + @staticmethod + def command(cmdstr): + retcode, output = subprocess.getstatusoutput(cmdstr) + return retcode, output + + + @staticmethod + def geti2cword_i2ctool(bus, addr, offset): + command_line = "i2cget -f -y %d 0x%02x 0x%02x wp" % (bus, addr, offset) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, int(ret_t, 16) + time.sleep(0.1) + return False, ret_t + + + @staticmethod + def seti2cword_i2ctool(bus, addr, offset, val): + command_line = "i2cset -f -y %d 0x%02x 0x%0x 0x%04x wp" % (bus, addr, offset, val) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, ret_t + time.sleep(0.1) + return False, ret_t + + @staticmethod + def rji2cget_i2ctool(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, int(ret_t, 16) + time.sleep(0.1) + return False, ret_t + + @staticmethod + def rji2cset_i2ctool(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % ( + bus, devno, address, byte) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + + @staticmethod + def geti2cword(bus, addr, offset): + return osutil.rji2cgetword_python(bus, addr, offset) + @staticmethod + def seti2cword(bus, addr, offset, val): + return osutil.rji2csetword_python(bus, addr, offset, val) + @staticmethod + def rji2cget(bus, devno, address): + return osutil.rji2cget_python(bus, devno, address) + @staticmethod + def rji2cset(bus, devno, address, byte): + return osutil.rji2cset_python(bus, devno, address, byte) + + @staticmethod + def byteTostr(val): + strtmp = '' + for i in range(len(val)): + strtmp += chr(val[i]) + return strtmp + + @staticmethod + def readsysfs(location): + try: + locations = glob.glob(location) + with open(locations[0], 'rb') as fd1: + retval = fd1.read() + retval = retval.strip() + except Exception as e: + return False, (str(e)+" location[%s]" % location) + return True, retval.decode("utf-8", "ignore") + + @staticmethod + def getdevmem(addr, digit, mask): + command_line = "devmem 0x%02x %d" %(addr, digit) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = osutil.command(command_line) + if ret == 0: + if mask != None: + ret_t = str(int(ret_t, 16) & mask) + return True, ret_t + return False, ret_t + + @staticmethod + def rj_os_system(cmd): + status, output = subprocess.getstatusoutput(cmd) + return status, output + + @staticmethod + def getsdkreg(reg): + try: + cmd = "bcmcmd -t 1 'getr %s ' < /dev/null" % reg + ret, result = osutil.rj_os_system(cmd) + result_t = result.strip().replace("\r", "").replace("\n", "") + if ret != 0 or "Error:" in result_t: + return False, result + patt = r"%s.(.*):(.*)>drivshell" % reg + rt = re.findall(patt, result_t, re.S) + test = re.findall("=(.*)", rt[0][0])[0] + except Exception as e: + return False, 'get sdk register error' + return True, test + + @staticmethod + def getmactemp(): + try: + result = {} + #waitForDocker() + #need to exec twice + osutil.rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + ret, log = osutil.rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + if ret: + return False, result + else: + logs = log.splitlines() + for line in logs: + if "average" in line: + b = re.findall(r'\d+.\d+', line) + result["average"] = b[0] + elif "maximum" in line: + b = re.findall(r'\d+.\d+', line) + result["maximum"] = b[0] + except Exception as e: + return False, str(e) + return True, result + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/__init__.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/baseutil.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/baseutil.py new file mode 100644 index 000000000000..1cf74d32d22f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/baseutil.py @@ -0,0 +1,23 @@ +# -*- coding: UTF-8 -*- +import os + +def get_machine_info(): + if not os.path.isfile('/host/machine.conf'): + return None + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars + +def get_platform_info(machine_info): + if machine_info != None: + if 'onie_platform' in machine_info: + return machine_info['onie_platform'] + elif 'aboot_platform' in machine_info: + return machine_info['aboot_platform'] + return None + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/smbus.py b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/smbus.py new file mode 100644 index 000000000000..f3651fe59a4a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/lib/rjutil/smbus.py @@ -0,0 +1,705 @@ +"""smbus2 - A drop-in replacement for smbus-cffi/smbus-python""" +# The MIT License (MIT) +# Copyright (c) 2017 Karl-Petter Lindegaard +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import os +import sys +from fcntl import ioctl +from ctypes import c_uint32, c_uint8, c_uint16, c_char, POINTER, Structure, Array, Union, create_string_buffer, string_at + + +# Commands from uapi/linux/i2c-dev.h +I2C_SLAVE = 0x0703 # Use this slave address +I2C_SLAVE_FORCE = 0x0706 # Use this slave address, even if it is already in use by a driver! +I2C_FUNCS = 0x0705 # Get the adapter functionality mask +I2C_RDWR = 0x0707 # Combined R/W transfer (one STOP only) +I2C_SMBUS = 0x0720 # SMBus transfer. Takes pointer to i2c_smbus_ioctl_data + +# SMBus transfer read or write markers from uapi/linux/i2c.h +I2C_SMBUS_WRITE = 0 +I2C_SMBUS_READ = 1 + +# Size identifiers uapi/linux/i2c.h +I2C_SMBUS_QUICK = 0 +I2C_SMBUS_BYTE = 1 +I2C_SMBUS_BYTE_DATA = 2 +I2C_SMBUS_WORD_DATA = 3 +I2C_SMBUS_PROC_CALL = 4 +I2C_SMBUS_BLOCK_DATA = 5 # This isn't supported by Pure-I2C drivers with SMBUS emulation, like those in RaspberryPi, OrangePi, etc :( +I2C_SMBUS_BLOCK_PROC_CALL = 7 # Like I2C_SMBUS_BLOCK_DATA, it isn't supported by Pure-I2C drivers either. +I2C_SMBUS_I2C_BLOCK_DATA = 8 +I2C_SMBUS_BLOCK_MAX = 32 + +# To determine what functionality is present (uapi/linux/i2c.h) +try: + from enum import IntFlag +except ImportError: + IntFlag = int + + +class I2cFunc(IntFlag): + """ + These flags identify the operations supported by an I2C/SMBus device. + + You can test these flags on your `smbus.funcs` + + On newer python versions, I2cFunc is an IntFlag enum, but it + falls back to class with a bunch of int constants on older releases. + """ + I2C = 0x00000001 + ADDR_10BIT = 0x00000002 + PROTOCOL_MANGLING = 0x00000004 # I2C_M_IGNORE_NAK etc. + SMBUS_PEC = 0x00000008 + NOSTART = 0x00000010 # I2C_M_NOSTART + SLAVE = 0x00000020 + SMBUS_BLOCK_PROC_CALL = 0x00008000 # SMBus 2.0 + SMBUS_QUICK = 0x00010000 + SMBUS_READ_BYTE = 0x00020000 + SMBUS_WRITE_BYTE = 0x00040000 + SMBUS_READ_BYTE_DATA = 0x00080000 + SMBUS_WRITE_BYTE_DATA = 0x00100000 + SMBUS_READ_WORD_DATA = 0x00200000 + SMBUS_WRITE_WORD_DATA = 0x00400000 + SMBUS_PROC_CALL = 0x00800000 + SMBUS_READ_BLOCK_DATA = 0x01000000 + SMBUS_WRITE_BLOCK_DATA = 0x02000000 + SMBUS_READ_I2C_BLOCK = 0x04000000 # I2C-like block xfer + SMBUS_WRITE_I2C_BLOCK = 0x08000000 # w/ 1-byte reg. addr. + SMBUS_HOST_NOTIFY = 0x10000000 + + SMBUS_BYTE = 0x00060000 + SMBUS_BYTE_DATA = 0x00180000 + SMBUS_WORD_DATA = 0x00600000 + SMBUS_BLOCK_DATA = 0x03000000 + SMBUS_I2C_BLOCK = 0x0c000000 + SMBUS_EMUL = 0x0eff0008 + + +# i2c_msg flags from uapi/linux/i2c.h +I2C_M_RD = 0x0001 + +# Pointer definitions +LP_c_uint8 = POINTER(c_uint8) +LP_c_uint16 = POINTER(c_uint16) +LP_c_uint32 = POINTER(c_uint32) + + +############################################################# +# Type definitions as in i2c.h + + +class i2c_smbus_data(Array): + """ + Adaptation of the i2c_smbus_data union in ``i2c.h``. + + Data for SMBus messages. + """ + _length_ = I2C_SMBUS_BLOCK_MAX + 2 + _type_ = c_uint8 + + +class union_i2c_smbus_data(Union): + _fields_ = [ + ("byte", c_uint8), + ("word", c_uint16), + ("block", i2c_smbus_data) + ] + + +union_pointer_type = POINTER(union_i2c_smbus_data) + + +class i2c_smbus_ioctl_data(Structure): + """ + As defined in ``i2c-dev.h``. + """ + _fields_ = [ + ('read_write', c_uint8), + ('command', c_uint8), + ('size', c_uint32), + ('data', union_pointer_type)] + __slots__ = [name for name, type in _fields_] + + @staticmethod + def create(read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE_DATA): + u = union_i2c_smbus_data() + return i2c_smbus_ioctl_data( + read_write=read_write, command=command, size=size, + data=union_pointer_type(u)) + + +############################################################# +# Type definitions for i2c_rdwr combined transactions + + +class i2c_msg(Structure): + """ + As defined in ``i2c.h``. + """ + _fields_ = [ + ('addr', c_uint16), + ('flags', c_uint16), + ('len', c_uint16), + ('buf', POINTER(c_char))] + + def __iter__(self): + """ Iterator / Generator + + :return: iterates over :py:attr:`buf` + :rtype: :py:class:`generator` which returns int values + """ + idx = 0 + while idx < self.len: + yield ord(self.buf[idx]) + idx += 1 + + def __len__(self): + return self.len + + def __bytes__(self): + return string_at(self.buf, self.len) + + def __repr__(self): + return 'i2c_msg(%d,%d,%r)' % (self.addr, self.flags, self.__bytes__()) + + def __str__(self): + s = self.__bytes__() + if sys.version_info.major >= 3: + s = ''.join(map(chr, s)) + return s + + @staticmethod + def read(address, length): + """ + Prepares an i2c read transaction. + + :param address: Slave address. + :type: address: int + :param length: Number of bytes to read. + :type: length: int + :return: New :py:class:`i2c_msg` instance for read operation. + :rtype: :py:class:`i2c_msg` + """ + arr = create_string_buffer(length) + return i2c_msg( + addr=address, flags=I2C_M_RD, len=length, + buf=arr) + + @staticmethod + def write(address, buf): + """ + Prepares an i2c write transaction. + + :param address: Slave address. + :type address: int + :param buf: Bytes to write. Either list of values or str. + :type buf: list + :return: New :py:class:`i2c_msg` instance for write operation. + :rtype: :py:class:`i2c_msg` + """ + if sys.version_info.major >= 3: + if type(buf) is str: + buf = bytes(map(ord, buf)) + else: + buf = bytes(buf) + else: + if type(buf) is not str: + buf = ''.join([chr(x) for x in buf]) + arr = create_string_buffer(buf, len(buf)) + return i2c_msg( + addr=address, flags=0, len=len(arr), + buf=arr) + + +class i2c_rdwr_ioctl_data(Structure): + """ + As defined in ``i2c-dev.h``. + """ + _fields_ = [ + ('msgs', POINTER(i2c_msg)), + ('nmsgs', c_uint32) + ] + __slots__ = [name for name, type in _fields_] + + @staticmethod + def create(*i2c_msg_instances): + """ + Factory method for creating a i2c_rdwr_ioctl_data struct that can + be called with ``ioctl(fd, I2C_RDWR, data)``. + + :param i2c_msg_instances: Up to 42 i2c_msg instances + :rtype: i2c_rdwr_ioctl_data + """ + n_msg = len(i2c_msg_instances) + msg_array = (i2c_msg * n_msg)(*i2c_msg_instances) + return i2c_rdwr_ioctl_data( + msgs=msg_array, + nmsgs=n_msg + ) + + +############################################################# + + +class SMBus(object): + + def __init__(self, bus=None, force=False): + """ + Initialize and (optionally) open an i2c bus connection. + + :param bus: i2c bus number (e.g. 0 or 1) + or an absolute file path (e.g. `/dev/i2c-42`). + If not given, a subsequent call to ``open()`` is required. + :type bus: int or str + :param force: force using the slave address even when driver is + already using it. + :type force: boolean + """ + self.fd = None + self.funcs = I2cFunc(0) + if bus is not None: + self.open(bus) + self.address = None + self.force = force + self._force_last = None + + def __enter__(self): + """Enter handler.""" + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """Exit handler.""" + self.close() + + def open(self, bus): + """ + Open a given i2c bus. + + :param bus: i2c bus number (e.g. 0 or 1) + or an absolute file path (e.g. '/dev/i2c-42'). + :type bus: int or str + :raise TypeError: if type(bus) is not in (int, str) + """ + if isinstance(bus, int): + filepath = "/dev/i2c-{}".format(bus) + elif isinstance(bus, str): + filepath = bus + else: + raise TypeError("Unexpected type(bus)={}".format(type(bus))) + + self.fd = os.open(filepath, os.O_RDWR) + self.funcs = self._get_funcs() + + def close(self): + """ + Close the i2c connection. + """ + if self.fd: + os.close(self.fd) + self.fd = None + + def _set_address(self, address, force=None): + """ + Set i2c slave address to use for subsequent calls. + + :param address: + :type address: int + :param force: + :type force: Boolean + """ + force = force if force is not None else self.force + if self.address != address or self._force_last != force: + if force is True: + ioctl(self.fd, I2C_SLAVE_FORCE, address) + else: + ioctl(self.fd, I2C_SLAVE, address) + self.address = address + self._force_last = force + + def _get_funcs(self): + """ + Returns a 32-bit value stating supported I2C functions. + + :rtype: int + """ + f = c_uint32() + ioctl(self.fd, I2C_FUNCS, f) + return f.value + + def write_quick(self, i2c_addr, force=None): + """ + Perform quick transaction. Throws IOError if unsuccessful. + :param i2c_addr: i2c address + :type i2c_addr: int + :param force: + :type force: Boolean + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=0, size=I2C_SMBUS_QUICK) + ioctl(self.fd, I2C_SMBUS, msg) + + def read_byte(self, i2c_addr, force=None): + """ + Read a single byte from a device. + + :rtype: int + :param i2c_addr: i2c address + :type i2c_addr: int + :param force: + :type force: Boolean + :return: Read byte value + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE + ) + ioctl(self.fd, I2C_SMBUS, msg) + return msg.data.contents.byte + + def write_byte(self, i2c_addr, value, force=None): + """ + Write a single byte to a device. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param value: value to write + :type value: int + :param force: + :type force: Boolean + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=value, size=I2C_SMBUS_BYTE + ) + ioctl(self.fd, I2C_SMBUS, msg) + + def read_byte_data(self, i2c_addr, register, force=None): + """ + Read a single byte from a designated register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read + :type register: int + :param force: + :type force: Boolean + :return: Read byte value + :rtype: int + """ + val_t = -1 + returnmsg="" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BYTE_DATA + ) + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + self.close() + returnmsg = str(e) + if val_t < 0: + return False, returnmsg + else: + return True, msg.data.contents.byte + + def write_byte_data(self, i2c_addr, register, value, force=None): + """ + Write a byte to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to write to + :type register: int + :param value: Byte value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: None + """ + val_t = -1 + returnmsg = "" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BYTE_DATA + ) + msg.data.contents.byte = value + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, "" + + def read_word_data(self, i2c_addr, register, force=None): + """ + Read a single word (2 bytes) from a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read + :type register: int + :param force: + :type force: Boolean + :return: 2-byte word + :rtype: int + """ + val_t = -1 + returnmsg = "" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_WORD_DATA + ) + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, msg.data.contents.word + + def write_word_data(self, i2c_addr, register, value, force=None): + """ + Write a byte to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to write to + :type register: int + :param value: Word value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: None + """ + val_t = -1 + returnmsg = "" + try: + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_WORD_DATA + ) + msg.data.contents.word = value + val_t = ioctl(self.fd, I2C_SMBUS, msg) + except Exception as e: + returnmsg = str(e) + self.close() + if val_t < 0: + return False, returnmsg or "" + else: + return True, "" + + def process_call(self, i2c_addr, register, value, force=None): + """ + Executes a SMBus Process Call, sending a 16-bit value and receiving a 16-bit response + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read/write to + :type register: int + :param value: Word value to transmit + :type value: int + :param force: + :type force: Boolean + :rtype: int + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_PROC_CALL + ) + msg.data.contents.word = value + ioctl(self.fd, I2C_SMBUS, msg) + return msg.data.contents.word + + def read_block_data(self, i2c_addr, register, force=None): + """ + Read a block of up to 32-bytes from a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param force: + :type force: Boolean + :return: List of bytes + :rtype: list + """ + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BLOCK_DATA + ) + ioctl(self.fd, I2C_SMBUS, msg) + length = msg.data.contents.block[0] + return msg.data.contents.block[1:length + 1] + + def write_block_data(self, i2c_addr, register, data, force=None): + """ + Write a block of byte data to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param data: List of bytes + :type data: list + :param force: + :type force: Boolean + :rtype: None + """ + length = len(data) + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_DATA + ) + msg.data.contents.block[0] = length + msg.data.contents.block[1:length + 1] = data + ioctl(self.fd, I2C_SMBUS, msg) + + def block_process_call(self, i2c_addr, register, data, force=None): + """ + Executes a SMBus Block Process Call, sending a variable-size data + block and receiving another variable-size response + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Register to read/write to + :type register: int + :param data: List of bytes + :type data: list + :param force: + :type force: Boolean + :return: List of bytes + :rtype: list + """ + length = len(data) + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_PROC_CALL + ) + msg.data.contents.block[0] = length + msg.data.contents.block[1:length + 1] = data + ioctl(self.fd, I2C_SMBUS, msg) + length = msg.data.contents.block[0] + return msg.data.contents.block[1:length + 1] + + def read_i2c_block_data(self, i2c_addr, register, length, force=None): + """ + Read a block of byte data from a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param length: Desired block length + :type length: int + :param force: + :type force: Boolean + :return: List of bytes + :rtype: list + """ + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Desired block length over %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA + ) + msg.data.contents.byte = length + ioctl(self.fd, I2C_SMBUS, msg) + return msg.data.contents.block[1:length + 1] + + def write_i2c_block_data(self, i2c_addr, register, data, force=None): + """ + Write a block of byte data to a given register. + + :param i2c_addr: i2c address + :type i2c_addr: int + :param register: Start register + :type register: int + :param data: List of bytes + :type data: list + :param force: + :type force: Boolean + :rtype: None + """ + length = len(data) + if length > I2C_SMBUS_BLOCK_MAX: + raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX) + self._set_address(i2c_addr, force=force) + msg = i2c_smbus_ioctl_data.create( + read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA + ) + msg.data.contents.block[0] = length + msg.data.contents.block[1:length + 1] = data + ioctl(self.fd, I2C_SMBUS, msg) + + def i2c_rdwr(self, *i2c_msgs): + """ + Combine a series of i2c read and write operations in a single + transaction (with repeated start bits but no stop bits in between). + + This method takes i2c_msg instances as input, which must be created + first with :py:meth:`i2c_msg.read` or :py:meth:`i2c_msg.write`. + + :param i2c_msgs: One or more i2c_msg class instances. + :type i2c_msgs: i2c_msg + :rtype: None + """ + ioctl_data = i2c_rdwr_ioctl_data.create(*i2c_msgs) + ioctl(self.fd, I2C_RDWR, ioctl_data) + + +class SMBusWrapper: + """ + Wrapper class around the SMBus. + Deprecated as of version 0.3.0. Please replace with :py:class:`SMBus`. + + Enables the user to wrap access to the :py:class:`SMBus` class in a + "with" statement. If auto_cleanup is True (default), the + :py:class:`SMBus` handle will be automatically closed + upon exit of the ``with`` block. + """ + def __init__(self, bus_number=0, auto_cleanup=True, force=False): + """ + :param auto_cleanup: Close bus when leaving scope. + :type auto_cleanup: Boolean + :param force: Force using the slave address even when driver is already using it. + :type force: Boolean + """ + self.bus_number = bus_number + self.auto_cleanup = auto_cleanup + self.force = force + + def __enter__(self): + self.bus = SMBus(bus=self.bus_number, force=self.force) + return self.bus + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.auto_cleanup: + self.bus.close() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/Makefile b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/Makefile new file mode 100755 index 000000000000..373027a26e00 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/Makefile @@ -0,0 +1,7 @@ +obj-m := rg-gpio-xeon.o +obj-m += rg_fan.o +obj-m += rg_psu.o +obj-m += ruijie_platform.o +obj-m += i2c-mux-pca9641.o +obj-m += i2c-mux-pca954x.o +obj-m += csu550.o diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/csu550.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/csu550.c new file mode 100755 index 000000000000..bb6a1588991e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/csu550.c @@ -0,0 +1,209 @@ +/* + * csu550.c - A driver for pmbus + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2019 + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pmbus.h" + + +/* + * Find sensor groups and status registers on each page. + */ +static void pmbus_find_sensor_groups(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int page; + + /* Sensors detected on page 0 only */ + if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) + info->func[0] |= PMBUS_HAVE_VIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN)) + info->func[0] |= PMBUS_HAVE_IIN; + if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN)) + info->func[0] |= PMBUS_HAVE_PIN; + if (info->func[0] && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) + info->func[0] |= PMBUS_HAVE_STATUS_INPUT; + if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && + pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { + info->func[0] |= PMBUS_HAVE_FAN12; + if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) + info->func[0] |= PMBUS_HAVE_STATUS_FAN12; + } + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) + info->func[0] |= PMBUS_HAVE_TEMP; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) + info->func[0] |= PMBUS_HAVE_TEMP2; + if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) + info->func[0] |= PMBUS_HAVE_TEMP3; + if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3) + && pmbus_check_byte_register(client, 0, PMBUS_STATUS_TEMPERATURE)) + info->func[0] |= PMBUS_HAVE_STATUS_TEMP; + + /* Sensors detected on all pages */ + for (page = 0; page < info->pages; page++) { + if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) { + info->func[page] |= PMBUS_HAVE_VOUT; + if (pmbus_check_byte_register(client, page, + PMBUS_STATUS_VOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_VOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) { + info->func[page] |= PMBUS_HAVE_IOUT; + if (pmbus_check_byte_register(client, 0, + PMBUS_STATUS_IOUT)) + info->func[page] |= PMBUS_HAVE_STATUS_IOUT; + } + if (pmbus_check_word_register(client, page, PMBUS_READ_POUT)) + info->func[page] |= PMBUS_HAVE_POUT; + } +} + +/* + * Identify chip parameters. + */ +static int pmbus_identify(struct i2c_client *client, + struct pmbus_driver_info *info) +{ + int ret = 0; + + if (!info->pages) { + /* + * Check if the PAGE command is supported. If it is, + * keep setting the page number until it fails or until the + * maximum number of pages has been reached. Assume that + * this is the number of pages supported by the chip. + */ + if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { + int page; + + for (page = 1; page < PMBUS_PAGES; page++) { + if (pmbus_set_page(client, page) < 0) + break; + } + pmbus_set_page(client, 0); + info->pages = page; + } else { + info->pages = 1; + } + } + + if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { + int vout_mode; + + vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); + if (vout_mode >= 0 && vout_mode != 0xff) { + switch (vout_mode >> 5) { + case 0: + break; + case 1: + info->format[PSC_VOLTAGE_OUT] = vid; + break; + case 2: + info->format[PSC_VOLTAGE_OUT] = direct; + break; + default: + ret = -ENODEV; + goto abort; + } + } + } + + /* + * We should check if the COEFFICIENTS register is supported. + * If it is, and the chip is configured for direct mode, we can read + * the coefficients from the chip, one set per group of sensor + * registers. + * + * To do this, we will need access to a chip which actually supports the + * COEFFICIENTS command, since the command is too complex to implement + * without testing it. Until then, abort if a chip configured for direct + * mode was detected. + */ + if (info->format[PSC_VOLTAGE_OUT] == direct) { + ret = -ENODEV; + goto abort; + } + + /* Try to find sensor groups */ + pmbus_find_sensor_groups(client, info); +abort: + return ret; +} + +static int pmbus_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct pmbus_driver_info *info; + struct pmbus_platform_data *pdata = NULL; + struct device *dev = &client->dev; + + info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + if (!strncmp(id->name, "dps460", sizeof("dps460")) || + !strncmp(id->name, "fsp1200", sizeof("fsp1200")) || !strncmp(id->name, "dps550", sizeof("dps550"))) { + pdata = kzalloc(sizeof(struct pmbus_platform_data), GFP_KERNEL); + if (!pdata) { + kfree(info); + return -ENOMEM; + } + pdata->flags = PMBUS_SKIP_STATUS_CHECK; + } + + info->pages = id->driver_data; + info->identify = pmbus_identify; + dev->platform_data = pdata; + + return pmbus_do_probe(client, id, info); +} + +static const struct i2c_device_id pmbus_id[] = { + {"csu550", 0}, + {"csu800", 1}, + {"fsp1200", 1}, + {"dps550", 1}, + {} +}; +MODULE_DEVICE_TABLE(i2c, pmbus_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver pmbus_driver = { + .probe = pmbus_probe, + .remove = pmbus_do_remove, + .id_table = pmbus_id, + .driver = { + .name = "pmbus", + }, +}; + +module_i2c_driver(pmbus_driver); + +MODULE_AUTHOR("sonic_rd "); +MODULE_DESCRIPTION("ruijie psupmbus driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca954x.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca954x.c new file mode 100755 index 000000000000..cc2d12c8b263 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca954x.c @@ -0,0 +1,1763 @@ +/* + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * Copyright (c) 2019 + * + * I2C multiplexer + * + * This module supports the PCA954x series of I2C multiplexer/switch chips + * made by Philips Semiconductors. + * This includes the: + * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547 + * and PCA9548. + * + * These chips are all controlled via the I2C bus itself, and all have a + * single 8-bit register. The upstream "parent" bus fans out to two, + * four, or eight downstream busses or channels; which of these + * are selected is determined by the chip type and register contents. A + * mux can select only one sub-bus at a time; a switch can select any + * combination simultaneously. + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PCA954X_MAX_NCHANS 8 + +#define PCA954X_IRQ_OFFSET 4 + +extern int pca9641_setmuxflag(int nr, int flag); + +int force_create_bus = 0; +module_param(force_create_bus, int, S_IRUGO | S_IWUSR); + +enum pca_type { + pca_9540, + pca_9542, + pca_9543, + pca_9544, + pca_9545, + pca_9546, + pca_9547, + pca_9548, +}; + +struct chip_desc { + u8 nchans; + u8 enable; /* used for muxes only */ + u8 has_irq; + enum muxtype { + pca954x_ismux = 0, + pca954x_isswi + } muxtype; +}; + + + + +struct pca954x { + const struct chip_desc *chip; + + u8 last_chan; /* last register value */ + u8 deselect; + struct i2c_client *client; + + struct irq_domain *irq; + unsigned int irq_mask; + raw_spinlock_t lock; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [pca_9540] = { + .nchans = 2, + .enable = 0x4, + .muxtype = pca954x_ismux, + }, + [pca_9542] = { + .nchans = 2, + .enable = 0x4, + .has_irq = 1, + .muxtype = pca954x_ismux, + }, + [pca_9543] = { + .nchans = 2, + .has_irq = 1, + .muxtype = pca954x_isswi, + }, + [pca_9544] = { + .nchans = 4, + .enable = 0x4, + .has_irq = 1, + .muxtype = pca954x_ismux, + }, + [pca_9545] = { + .nchans = 4, + .has_irq = 1, + .muxtype = pca954x_isswi, + }, + [pca_9546] = { + .nchans = 4, + .muxtype = pca954x_isswi, + }, + [pca_9547] = { + .nchans = 8, + .enable = 0x8, + .muxtype = pca954x_ismux, + }, + [pca_9548] = { + .nchans = 8, + .muxtype = pca954x_isswi, + }, +}; + +static const struct i2c_device_id pca954x_id[] = { + { "pca9540", pca_9540 }, + { "pca9542", pca_9542 }, + { "pca9543", pca_9543 }, + { "pca9544", pca_9544 }, + { "pca9545", pca_9545 }, + { "pca9546", pca_9546 }, + { "pca9547", pca_9547 }, + { "pca9548", pca_9548 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pca954x_id); + +#ifdef CONFIG_OF +static const struct of_device_id pca954x_of_match[] = { + { .compatible = "nxp,pca9540", .data = &chips[pca_9540] }, + { .compatible = "nxp,pca9542", .data = &chips[pca_9542] }, + { .compatible = "nxp,pca9543", .data = &chips[pca_9543] }, + { .compatible = "nxp,pca9544", .data = &chips[pca_9544] }, + { .compatible = "nxp,pca9545", .data = &chips[pca_9545] }, + { .compatible = "nxp,pca9546", .data = &chips[pca_9546] }, + { .compatible = "nxp,pca9547", .data = &chips[pca_9547] }, + { .compatible = "nxp,pca9548", .data = &chips[pca_9548] }, + {} +}; +MODULE_DEVICE_TABLE(of, pca954x_of_match); +#endif + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int pca954x_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + int ret = -ENODEV; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[1]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 1; + buf[0] = val; + msg.buf = buf; + ret = __i2c_transfer(adap, &msg, 1); + + if (ret >= 0 && ret != 1) + ret = -EREMOTEIO; + } else { + union i2c_smbus_data data; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + val, I2C_SMBUS_BYTE, &data); + } + + return ret; +} + + static int pca954x_setmuxflag(struct i2c_client *client, int flag) + { + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + pca9641_setmuxflag(adap->nr, flag); + return 0; + } + +static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + const struct chip_desc *chip = data->chip; + u8 regval; + int ret = 0; + + /* we make switches look like muxes, not sure how to be smarter */ + if (chip->muxtype == pca954x_ismux) + regval = chan | chip->enable; + else + regval = 1 << chan; + + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + pca954x_setmuxflag(client, 0); + ret = pca954x_reg_write(muxc->parent, client, regval); + data->last_chan = ret < 0 ? 0 : regval; + } + + return ret; +} + + +typedef void (*pca954x_hw_do_reset_func_t)(int busid, int addr); +pca954x_hw_do_reset_func_t g_notify_to_do_reset = NULL; + +void pca954x_hw_do_reset_func_register(void* func) +{ + if (func == NULL) { + return ; + } + g_notify_to_do_reset = func; + return; +} +EXPORT_SYMBOL(pca954x_hw_do_reset_func_register); + +static int pca954x_hw_do_reset(int busid, int addr) +{ + if (g_notify_to_do_reset != NULL) { + (*g_notify_to_do_reset)(busid, addr); + return 0; + } + + return 0; +} +/***************************************9548 reset*****************************************/ +#define DEV_TYPE 0x4040 /* BT2575 */ +#define PCA9548_MAX_CPLD_NUM (32) /* PCA9548 max number */ +#define PCA9548_MAX_CPLD_LAYER (8) /* PCA9548 max layer */ +#define DFD_PID_BUF_LEN (32) +#define DFD_PRODUCT_ID_LENGTH (8) +#define CPLD_PCA9548_RESET 0x023500b0 /* bus:2, addr:0x35, offset:0xb0 */ +#define B6510_32CQ_CPLD_PCA9548_RESET 0x060d0060 /* bus:6, addr:0x0d, offset:0x60 */ + +#define DFD_PUB_CARDTYPE_FILE "/sys/module/ruijie_common/parameters/dfd_my_type" +#define DFD_MAX_PRODUCT_NUM (32) + + +#define I2C_RETRY_TIMES 5 +#define I2C_RETRY_WAIT_TIMES 10 /*delay 10ms*/ + +#define PCA9548_I2C_GET_BUS(addr) (((addr) >> 24) & 0x00ff) +#define PCA9548_I2C_GET_CLIENT(addr) (((addr) >> 16) & 0x00ff) +#define PCA9548_I2C_GET_OFFSET(addr) (addr & 0xffff) + +typedef enum pca9548_reset_type { + PCA9548_RESET_FUNC = 0, + PCA9548_RESET_GPIO = 1, +} pca9548_reset_type_t; + +typedef void (*pca954x_hw_do_reset_func_t_new)(int io_port, u8 value); +typedef u8 (*pca954x_get_umask_func_t)(int io_port); + +void pca954x_hw_do_reset_by_i2c(int addr, u8 value); +u8 pca954x_get_umask_by_i2c(int addr); +void pca954x_hw_do_reset_by_lpc(int io_port, u8 value); +u8 pca954x_get_umask_by_lpc(int io_port); + + +typedef struct func_attr_s { + int cfg_offset[PCA9548_MAX_CPLD_LAYER]; + int umask[PCA9548_MAX_CPLD_LAYER]; + pca954x_hw_do_reset_func_t_new reset_func; /* 9548 reset function */ + pca954x_get_umask_func_t get_umask_func; /* get reset mask */ +} func_attr_t; + +typedef struct gpio_attr_s { + int gpio; + int gpio_init; + u8 reset_on; + u8 reset_off; +} gpio_attr_t; + +typedef struct pca9548_cfg_info_s { + int pca9548_reset_type; + int pca9548_bus; + int pca9548_addr; + int rst_delay_b; /* delay time before reset(us) */ + int rst_delay; /* reset time(us) */ + int rst_delay_a; /* delay time after reset(us) */ + union { + func_attr_t func_attr; + gpio_attr_t gpio_attr; + } attr; +} pca9548_cfg_info_t; + +typedef struct fpga_pcie_card_info_s { + int dev_type[DFD_MAX_PRODUCT_NUM]; /* dev type */ + pca9548_cfg_info_t pca9548_cfg_info[PCA9548_MAX_CPLD_NUM]; +} pca9548_card_info_t; + +static pca9548_card_info_t g_pca9548_card_info[] = { + { + .dev_type = {0x4040,0x4061,0x4071}, /*B6510,BT2575,TCS81*/ + .pca9548_cfg_info = { + /* psu fan */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 2, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 7, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 1, + .gpio_attr.reset_off = 0, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* sff5 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* sff6 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x75, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* sff7 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(6), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4041}, /*B6520*/ + .pca9548_cfg_info = { + /* psu fan */ + { + .pca9548_reset_type = PCA9548_RESET_GPIO, + .pca9548_bus = 2, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .gpio_attr.gpio = 7, + .gpio_attr.gpio_init = 0, + .gpio_attr.reset_on = 1, + .gpio_attr.reset_off = 0, + }, + }, + /* sff1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* sff2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* sff3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* sff4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* sff5 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x74, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* sff6 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x75, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* sff7 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(6), -1}, + }, + }, + /* sff8 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 1, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_i2c, + .func_attr.get_umask_func = pca954x_get_umask_by_i2c, + .func_attr.cfg_offset = {CPLD_PCA9548_RESET, -1}, + .func_attr.umask = {BIT(7), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4044,0x4072,0x4048}, /*B6920,TCS83,BS100R0*/ + .pca9548_cfg_info = { + /* һ��9548 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 2, + .pca9548_addr = 0x76, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x936, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* �װ� */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 8, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(4), -1}, + }, + }, + /* �ӿ�1 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 9, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* �ӿ�2 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 12, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* �ӿ�3 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 11, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* �ӿ�4 */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 7, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x917, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + /* ����A */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 14, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb10, -1}, + .func_attr.umask = {BIT(5), -1}, + }, + }, + /* ����B */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 13, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb10, -1}, + .func_attr.umask = {BIT(7), -1}, + }, + }, + /* �ӿ�1 ��ģ�� */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 3, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* �ӿ�2 ��ģ�� */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + /* �ӿ�3 ��ģ�� */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 5, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(2), -1}, + }, + }, + /* �ӿ�4 ��ģ�� */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x70, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x71, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x72, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 6, + .pca9548_addr = 0x73, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0xb17, -1}, + .func_attr.umask = {BIT(3), -1}, + }, + }, + }, + }, + { + .dev_type = {0x4058,0x4073}, /* B6510-32CQ, TCS82 */ + .pca9548_cfg_info = { + /* psu */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 4, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x960, -1}, + .func_attr.umask = {BIT(0), -1}, + }, + }, + /* fan */ + { + .pca9548_reset_type = PCA9548_RESET_FUNC, + .pca9548_bus = 2, + .pca9548_addr = 0x77, + .rst_delay_b = 0, + .rst_delay = 1000, + .rst_delay_a = 1000, + .attr = { + .func_attr.reset_func = pca954x_hw_do_reset_by_lpc, + .func_attr.get_umask_func = pca954x_get_umask_by_lpc, + .func_attr.cfg_offset = {0x960, -1}, + .func_attr.umask = {BIT(1), -1}, + }, + }, + }, + }, +}; +int g_pca954x_debug = 0; +module_param(g_pca954x_debug, int, S_IRUGO | S_IWUSR); + +#define PCA954X_DEBUG(fmt, args...) do { \ + if (g_pca954x_debug) { \ + printk(KERN_ERR "[PCA95x][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +/* x86�豸��ȡ�忨���ͷ��� */ +static int dfd_get_my_dev_type_by_file(void) +{ + struct file *fp; + /* mm_segment_t fs;*/ + loff_t pos; + static int card_type; + char buf[DFD_PID_BUF_LEN]; + + if (card_type != 0) { + return card_type; + } + + fp= filp_open(DFD_PUB_CARDTYPE_FILE, O_RDONLY, 0); + if (IS_ERR(fp)) { + PCA954X_DEBUG("open file fail!\r\n"); + return -1; + } + /* fs = get_fs(); */ + /* set_fs(KERNEL_DS); */ + memset(buf, 0, DFD_PID_BUF_LEN); + pos = 0; + kernel_read(fp, pos, buf, DFD_PRODUCT_ID_LENGTH + 1 ); + if (pos < 0) { + PCA954X_DEBUG("read file fail!\r\n"); + goto exit; + } + + card_type = simple_strtoul(buf, NULL, 10); + PCA954X_DEBUG("card_type 0x%x.\n", card_type); + +exit: + /* set_fs(fs); */ + filp_close(fp, NULL); + return card_type; +} + +static int drv_get_my_dev_type(void) +{ + static int type = -1; + + if (type > 0) { + return type; + } + type = dfd_get_my_dev_type_by_file(); + PCA954X_DEBUG("ko board type %d\r\n", type); + + return type; +} + +pca9548_card_info_t* pca9548_get_card_info(int dev_type) +{ + int i, j; + int size; + + size = ARRAY_SIZE(g_pca9548_card_info); + + PCA954X_DEBUG("Enter dev_type 0x%x size %d.\n", dev_type, size); + for (i = 0; i < size; i++) { + for(j = 0; j < DFD_MAX_PRODUCT_NUM; j++) { + if (g_pca9548_card_info[i].dev_type[j] == dev_type) { + PCA954X_DEBUG("match dev_type 0x%x.\n", dev_type); + return &g_pca9548_card_info[i]; + } + } + } + + PCA954X_DEBUG("dismatch dev_type 0x%x.\n", dev_type); + return NULL; +} + +pca9548_cfg_info_t* get_pca9548_cfg_info(int bus, int addr) +{ + int dev_type; + pca9548_card_info_t *info; + pca9548_cfg_info_t *pca9548_cfg_info; + int i; + int size; + + dev_type = drv_get_my_dev_type(); + if (dev_type < 0) { + PCA954X_DEBUG("drv_get_my_dev_type failed ret %d.\n", dev_type); + return NULL; + } + + info = pca9548_get_card_info(dev_type); + if (info == NULL) { + PCA954X_DEBUG("fpga_pcie_get_card_info dev_type %d failed.\n", dev_type); + return NULL; + } + + size = PCA9548_MAX_CPLD_NUM; + for (i = 0; i < size; i++) { + pca9548_cfg_info = &(info->pca9548_cfg_info[i]); + if ((pca9548_cfg_info->pca9548_bus == bus) && (pca9548_cfg_info->pca9548_addr == addr)) { + PCA954X_DEBUG("match dev_type 0x%x bus %d addr 0x%x.\n", dev_type, bus, addr); + return pca9548_cfg_info; + } + } + + PCA954X_DEBUG("dismatch dev_type 0x%x bus %d addr 0x%x.\n", dev_type, bus, addr); + return NULL; +} + +static void pca9548_gpio_init(gpio_attr_t *gpio_attr) +{ + if (gpio_attr->gpio_init == 0) { + PCA954X_DEBUG("gpio%d init.\n", gpio_attr->gpio); + gpio_request(gpio_attr->gpio, "pca9548_reset"); + gpio_direction_output(gpio_attr->gpio, gpio_attr->reset_off); + gpio_attr->gpio_init = 1; + } +} + +static void pca9548_gpio_free(gpio_attr_t *gpio_attr) +{ + if (gpio_attr == NULL) { + PCA954X_DEBUG("pca9548_gpio_free,params error\n"); + return ; + } + if (gpio_attr->gpio_init == 1) { + PCA954X_DEBUG("gpio%d release.\n", gpio_attr->gpio); + gpio_free(gpio_attr->gpio); + gpio_attr->gpio_init = 0; + } +} + +static int pca954x_do_gpio_reset(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + struct pca954x *data = i2c_get_clientdata(client); + int ret = -1; + gpio_attr_t *tmp_gpio_attr; + int timeout; + int val; + struct i2c_adapter *adapter; + int adapter_timeout; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_GPIO) { + tmp_gpio_attr = &(cfg_info->attr.gpio_attr); + timeout = cfg_info->rst_delay_a; + + pca9548_gpio_init(tmp_gpio_attr); + udelay(cfg_info->rst_delay_b); + /* reset on */ + PCA954X_DEBUG("set gpio%d %d.\n", tmp_gpio_attr->gpio, tmp_gpio_attr->reset_on); + __gpio_set_value(tmp_gpio_attr->gpio, tmp_gpio_attr->reset_on); + udelay(cfg_info->rst_delay); + /* reset off */ + PCA954X_DEBUG("set gpio%d %d.\n", tmp_gpio_attr->gpio, tmp_gpio_attr->reset_off); + __gpio_set_value(tmp_gpio_attr->gpio, tmp_gpio_attr->reset_off); + + while (timeout > 0) { + udelay(1); + val = __gpio_get_value(tmp_gpio_attr->gpio); + if (val == tmp_gpio_attr->reset_off) { + adapter = adap; + /* get bus info */ + while(i2c_parent_is_i2c_adapter(adapter)){ + adapter = to_i2c_adapter(adapter->dev.parent); + } + + adapter_timeout = adapter->timeout; + adapter->timeout = msecs_to_jiffies(50); + pca954x_reg_write(adap, client, data->last_chan); + adapter->timeout = adapter_timeout; + ret = 0; + PCA954X_DEBUG("pca954x_do_gpio_reset success.\n"); + break; + } + + if (timeout >= 1000 && (timeout % 1000 == 0)) { + /* 1MS schedule*/ + schedule(); + } + timeout--; + } + + if (ret) { + PCA954X_DEBUG("pca954x_do_gpio_reset failed.\n"); + } + pca9548_gpio_free(&(cfg_info->attr.gpio_attr)); + } else { + PCA954X_DEBUG("pca9548_reset_type invalid, pca954x_do_gpio_reset failed.\n"); + } + + return ret; +} + +static int pca954x_do_func_reset(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + struct pca954x *data = i2c_get_clientdata(client); + int ret = -1; + func_attr_t *tmp_func_attr; + int timeout; + int val; + struct i2c_adapter *adapter; + int adapter_timeout; + int i; + u8 old_value; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_FUNC) { + tmp_func_attr = &(cfg_info->attr.func_attr); + timeout = cfg_info->rst_delay_a; + + if ((tmp_func_attr->reset_func == NULL) || (tmp_func_attr->get_umask_func == NULL)) { + PCA954X_DEBUG("pca954x hw do reset func or get umask func is null.\n"); + return ret; + } + + for(i = 0; (i < PCA9548_MAX_CPLD_LAYER) && (tmp_func_attr->cfg_offset[i] != -1) + && (tmp_func_attr->umask[i] != -1); i++) { + old_value = (*tmp_func_attr->get_umask_func)(tmp_func_attr->cfg_offset[i]); + PCA954X_DEBUG("cfg info: offset:0x%x umask:0x%x, old_value:0x%x\n", + tmp_func_attr->cfg_offset[i], tmp_func_attr->umask[i],old_value); + (*tmp_func_attr->reset_func)(tmp_func_attr->cfg_offset[i], old_value & ~tmp_func_attr->umask[i]); + udelay(cfg_info->rst_delay); + (*tmp_func_attr->reset_func)(tmp_func_attr->cfg_offset[i], old_value | tmp_func_attr->umask[i]); + } + + while (timeout > 0) { + udelay(1); + val = (*tmp_func_attr->get_umask_func)(tmp_func_attr->cfg_offset[i - 1]); + val &= (tmp_func_attr->umask[i - 1]); + if (val == tmp_func_attr->umask[i - 1]) { + adapter = adap; + /* get bus info */ + while(i2c_parent_is_i2c_adapter(adapter)){ + adapter = to_i2c_adapter(adapter->dev.parent); + } + + adapter_timeout = adapter->timeout; + adapter->timeout = msecs_to_jiffies(50); + pca954x_reg_write(adap, client, data->last_chan); + adapter->timeout = adapter_timeout; + ret = 0; + PCA954X_DEBUG("pca954x_do_func_reset success.\n"); + break; + } + + if (timeout >= 1000 && (timeout % 1000 == 0)) { + /* 1MS schedule*/ + schedule(); + } + timeout--; + } + + if (ret) { + PCA954X_DEBUG("pca954x_do_func_reset failed.\n"); + } + } else { + PCA954X_DEBUG("pca9548_reset_type invalid, pca954x_do_func_reset failed.\n"); + } + + return ret; +} + +static int pca9548_reset_ctrl(pca9548_cfg_info_t *cfg_info, struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + int ret = -1; + + if (cfg_info == NULL) { + PCA954X_DEBUG("pca9548 cfg info is null.\n"); + return ret; + } + + if (cfg_info->pca9548_reset_type == PCA9548_RESET_FUNC) { + ret = pca954x_do_func_reset(cfg_info, adap, client, chan); + } else if (cfg_info->pca9548_reset_type == PCA9548_RESET_GPIO) { + ret = pca954x_do_gpio_reset(cfg_info, adap, client, chan); + } + + if (ret < 0) { + PCA954X_DEBUG("pca9548_reset_ctrl failed.\n"); + } + return ret; +} + +static int pca954x_reset_i2c_read(uint32_t bus, uint32_t addr, uint32_t offset_addr, + unsigned char *buf, uint32_t size) +{ + struct file *fp; + /* mm_segment_t fs; */ + struct i2c_client client; + char i2c_path[32]; + int i ,j ; + int rv; + + rv = 0; + memset(i2c_path, 0, 32); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus); + fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR); + if (IS_ERR(fp)) { + PCA954X_DEBUG("i2c open fail.\n"); + return -1; + } + memcpy(&client, fp->private_data, sizeof(struct i2c_client)); + client.addr = addr; + /* fs = get_fs(); */ + /* set_fs(KERNEL_DS); */ + for (j = 0 ;j < size ;j++){ + for (i = 0; i < I2C_RETRY_TIMES; i++) { + rv = i2c_smbus_read_byte_data(&client, (offset_addr + j)); + if (rv < 0) { + PCA954X_DEBUG("i2c read failed, try again.\n"); + msleep(I2C_RETRY_WAIT_TIMES); + if (i >= (I2C_RETRY_TIMES - 1)) { + goto out; + } + continue; + } + *(buf + j) = (unsigned char)rv; + break; + } + } +out: + filp_close(fp, NULL); + /* set_fs(fs); */ + return rv; +} + +static int pca954x_reset_i2c_write(uint32_t bus, uint32_t dev_addr, uint32_t offset_addr, + uint8_t write_buf) +{ + struct file *fp; + /* mm_segment_t fs; */ + struct i2c_client client; + char i2c_path[32]; + int i; + int rv; + + rv = 0; + memset(i2c_path, 0, 32); + snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus); + fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR); + if (IS_ERR(fp)) { + PCA954X_DEBUG("i2c open fail.\n"); + return -1; + } + memcpy(&client, fp->private_data, sizeof(struct i2c_client)); + client.addr = dev_addr; + /* fs = get_fs(); */ + /* set_fs(KERNEL_DS); */ + for (i = 0; i < I2C_RETRY_TIMES; i++) { + rv = i2c_smbus_write_byte_data(&client, offset_addr, write_buf); + if (rv < 0) { + PCA954X_DEBUG("i2c write failed, try again.\n"); + msleep(I2C_RETRY_WAIT_TIMES); + if (i >= (I2C_RETRY_TIMES - 1)) { + goto out; + } + continue; + } + break; + } +out: + filp_close(fp, NULL); + /* set_fs(fs); */ + return rv; +} + +int pca954x_reset_reg_i2c_read_byte(int addr, u8 *value) +{ + int bus; + int client_addr; + int offset; + int ret; + + bus = PCA9548_I2C_GET_BUS(addr); + client_addr = PCA9548_I2C_GET_CLIENT(addr); + offset = PCA9548_I2C_GET_OFFSET(addr); + + ret = pca954x_reset_i2c_read(bus, client_addr, offset, value, 1); + if (ret < 0) { + PCA954X_DEBUG(" 0x%x read fail\r\n", addr); + goto end; + } +end: + return ret; +} + +int pca954x_reset_reg_i2c_write_byte(int addr, u8 value) +{ + int bus; + int client_addr; + int offset; + int ret; + + bus = PCA9548_I2C_GET_BUS(addr); + client_addr = PCA9548_I2C_GET_CLIENT(addr); + offset = PCA9548_I2C_GET_OFFSET(addr); + + ret = pca954x_reset_i2c_write(bus, client_addr, offset, value); + if (ret < 0) { + PCA954X_DEBUG(" 0x%x write fail\r\n", addr); + goto end; + } +end: + return ret; +} + +void pca954x_hw_do_reset_by_i2c(int addr, u8 value) +{ + int ret; + + PCA954X_DEBUG("write i2c cpld[0x%x], value[%d]\n", addr, value); + ret = pca954x_reset_reg_i2c_write_byte(addr, value); + if (ret < 0) { + PCA954X_DEBUG("write cpld pca9548 reset reg failed, ret = %d \n", ret); + } +} + +u8 pca954x_get_umask_by_i2c(int addr) +{ + u8 value = 0xFF; + int ret; + + ret = pca954x_reset_reg_i2c_read_byte(addr, &value); + PCA954X_DEBUG("read i2c cpld[0x%x], value[%d], ret = %d\n", addr, value, ret); + + return value; +} + +void pca954x_hw_do_reset_by_lpc(int io_port, u8 value) +{ + PCA954X_DEBUG("write lpc offset[0x%x], value[%d]\n", (u16)io_port, value); + outb(value, (u16)io_port); +} + +u8 pca954x_get_umask_by_lpc(int io_port) +{ + u8 value; + + value = inb(io_port); + PCA954X_DEBUG("read lpc offset[0x%x], value[%d]\n", (u16)io_port, value); + + return value; +} + +int pca954x_hw_do_reset_new(struct i2c_adapter *adap, + struct i2c_client *client, u32 chan) +{ + pca9548_cfg_info_t *cfg_info; + int ret = -1; + + cfg_info = get_pca9548_cfg_info(adap->nr, client->addr); + if (cfg_info == NULL && g_notify_to_do_reset == NULL) { + PCA954X_DEBUG("fpga_do_pca954x_reset_func do nothing.\n"); + return ret; + } + if(cfg_info != NULL) { + ret = pca9548_reset_ctrl(cfg_info, adap, client, chan); + } else { + ret = pca954x_hw_do_reset(adap->nr, client->addr); + } + if (ret < 0) { + PCA954X_DEBUG("pca954x_hw_do_reset failed.\n"); + } + return ret; +} +/******************************end 9548 reset***********************************/ + +static int pca954x_do_reset(struct i2c_adapter *adap, + void *client, u32 chan) +{ + struct i2c_client *new_client; + int ret = -1; + + PCA954X_DEBUG("do pca954x reset x86\n"); + new_client =(struct i2c_client *) client; + ret = pca954x_hw_do_reset_new(adap, new_client, chan); + if (ret < 0) { + PCA954X_DEBUG("pca954x_do_reset failed.\n"); + return ret; + } + + PCA954X_DEBUG("pca954x_do_reset success.\n"); + ret = 0; + return ret; +} +static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret, rv; + struct i2c_client * new_client; + + /* Deselect active channel */ + data->last_chan = 0; + + ret = pca954x_reg_write(muxc->parent, client, data->last_chan); + if (ret < 0) { + /* ʹ��i2c��ʽ�ر�ͨ��ʧ�ܣ�����ʹ��reset��ʽ */ + new_client =(struct i2c_client *) client; + dev_warn(&new_client->dev, "pca954x close chn failed, do reset.\n"); + rv = pca954x_do_reset(client->adapter, client, chan); + if (rv == 0) { + ret = 0; + } + + } + /*9641Ȩ����Ҫ��9548��λ֮���ͷţ����¹�һ��ͨ��ȷ��9641Ȩ�������ͷ�*/ + pca954x_setmuxflag(client, 1); + (void)pca954x_reg_write(muxc->parent, client, data->last_chan); + + return ret; + +} + +static irqreturn_t pca954x_irq_handler(int irq, void *dev_id) +{ + struct pca954x *data = dev_id; + unsigned int child_irq; + int ret, i, handled = 0; + + ret = i2c_smbus_read_byte(data->client); + if (ret < 0) + return IRQ_NONE; + + for (i = 0; i < data->chip->nchans; i++) { + if (ret & BIT(PCA954X_IRQ_OFFSET + i)) { + child_irq = irq_linear_revmap(data->irq, i); + handle_nested_irq(child_irq); + handled++; + } + } + return handled ? IRQ_HANDLED : IRQ_NONE; +} + +static void pca954x_irq_mask(struct irq_data *idata) +{ + struct pca954x *data = irq_data_get_irq_chip_data(idata); + unsigned int pos = idata->hwirq; + unsigned long flags; + + raw_spin_lock_irqsave(&data->lock, flags); + + data->irq_mask &= ~BIT(pos); + if (!data->irq_mask) + disable_irq(data->client->irq); + + raw_spin_unlock_irqrestore(&data->lock, flags); +} + +static void pca954x_irq_unmask(struct irq_data *idata) +{ + struct pca954x *data = irq_data_get_irq_chip_data(idata); + unsigned int pos = idata->hwirq; + unsigned long flags; + + raw_spin_lock_irqsave(&data->lock, flags); + + if (!data->irq_mask) + enable_irq(data->client->irq); + data->irq_mask |= BIT(pos); + + raw_spin_unlock_irqrestore(&data->lock, flags); +} + +static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type) +{ + if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW) + return -EINVAL; + return 0; +} + +static struct irq_chip pca954x_irq_chip = { + .name = "i2c-mux-pca954x", + .irq_mask = pca954x_irq_mask, + .irq_unmask = pca954x_irq_unmask, + .irq_set_type = pca954x_irq_set_type, +}; + +static int pca954x_irq_setup(struct i2c_mux_core *muxc) +{ + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int c, err, irq; + + if (!data->chip->has_irq || client->irq <= 0) + return 0; + + raw_spin_lock_init(&data->lock); + + data->irq = irq_domain_add_linear(client->dev.of_node, + data->chip->nchans, + &irq_domain_simple_ops, data); + if (!data->irq) + return -ENODEV; + + for (c = 0; c < data->chip->nchans; c++) { + irq = irq_create_mapping(data->irq, c); + irq_set_chip_data(irq, data); + irq_set_chip_and_handler(irq, &pca954x_irq_chip, + handle_simple_irq); + } + + err = devm_request_threaded_irq(&client->dev, data->client->irq, NULL, + pca954x_irq_handler, + IRQF_ONESHOT | IRQF_SHARED, + "pca954x", data); + if (err) + goto err_req_irq; + + disable_irq(data->client->irq); + + return 0; +err_req_irq: + for (c = 0; c < data->chip->nchans; c++) { + irq = irq_find_mapping(data->irq, c); + irq_dispose_mapping(irq); + } + irq_domain_remove(data->irq); + + return err; +} + +/* + * I2C init/probing/exit functions + */ +static int pca954x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct device_node *of_node = client->dev.of_node; + bool idle_disconnect_dt; + struct gpio_desc *gpio; + int num, force, class; + struct i2c_mux_core *muxc; + struct pca954x *data; + const struct of_device_id *match; + int ret; + + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + muxc = i2c_mux_alloc(adap, &client->dev, + PCA954X_MAX_NCHANS, sizeof(*data), 0, + pca954x_select_chan, pca954x_deselect_mux); + if (!muxc) + return -ENOMEM; + data = i2c_mux_priv(muxc); + + i2c_set_clientdata(client, muxc); + data->client = client; + + /* Get the mux out of reset if a reset GPIO is specified. */ + gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + + /* Write the mux register at addr to verify + * that the mux is in fact present. This also + * initializes the mux to disconnected state. + */ + if ((i2c_smbus_write_byte(client, 0) < 0) && (force_create_bus == 0)) { + dev_warn(&client->dev, "probe failed\n"); + return -ENODEV; + } + + match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev); + if (match) + data->chip = of_device_get_match_data(&client->dev); + else + data->chip = &chips[id->driver_data]; + + data->last_chan = 0; /* force the first selection */ + + idle_disconnect_dt = of_node && + of_property_read_bool(of_node, "i2c-mux-idle-disconnect"); + + ret = pca954x_irq_setup(muxc); + if (ret) + goto fail_del_adapters; + + /* Now create an adapter for each channel */ + for (num = 0; num < data->chip->nchans; num++) { + bool idle_disconnect_pd = false; + + force = 0; /* dynamic adap number */ + class = 0; /* no class by default */ + if (pdata) { + if (num < pdata->num_modes) { + /* force static number */ + force = pdata->modes[num].adap_id; + class = pdata->modes[num].class; + } else + /* discard unconfigured channels */ + break; + idle_disconnect_pd = pdata->modes[num].deselect_on_exit; + } + data->deselect |= (idle_disconnect_pd || + idle_disconnect_dt) << num; + + ret = i2c_mux_add_adapter(muxc, force, num, class); + if (ret) + goto fail_del_adapters; + } + + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s %s\n", + num, data->chip->muxtype == pca954x_ismux + ? "mux" : "switch", client->name); + + return 0; + +fail_del_adapters: + i2c_mux_del_adapters(muxc); + return ret; +} + +static int pca954x_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + int c, irq; + + if (data->irq) { + for (c = 0; c < data->chip->nchans; c++) { + irq = irq_find_mapping(data->irq, c); + irq_dispose_mapping(irq); + } + irq_domain_remove(data->irq); + } + + i2c_mux_del_adapters(muxc); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int pca954x_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca954x *data = i2c_mux_priv(muxc); + + data->last_chan = 0; + return i2c_smbus_write_byte(client, 0); +} +#endif + +static SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume); + +static struct i2c_driver pca954x_driver = { + .driver = { + .name = "pca954x", + .pm = &pca954x_pm, + .of_match_table = of_match_ptr(pca954x_of_match), + }, + .probe = pca954x_probe, + .remove = pca954x_remove, + .id_table = pca954x_id, +}; + +module_i2c_driver(pca954x_driver); + +MODULE_AUTHOR("sonic_rd sonic_rd@ruijie.com.cn"); +MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca9641.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca9641.c new file mode 100755 index 000000000000..bb2af837df31 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/i2c-mux-pca9641.c @@ -0,0 +1,645 @@ +/* + * I2C multiplexer driver for PCA9541 bus master selector + * + * Copyright (c) 2010 Ericsson AB. + * Copyright (c) 2019 + * Author: Guenter Roeck + * + * Derived from: + * pca954x.c + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The PCA9541 is a bus master selector. It supports two I2C masters connected + * to a single slave bus. + * + * Before each bus transaction, a master has to acquire bus ownership. After the + * transaction is complete, bus ownership has to be released. This fits well + * into the I2C multiplexer framework, which provides select and release + * functions for this purpose. For this reason, this driver is modeled as + * single-channel I2C bus multiplexer. + * + * This driver assumes that the two bus masters are controlled by two different + * hosts. If a single host controls both masters, platform code has to ensure + * that only one of the masters is instantiated at any given time. + */ + +#define PCA9541_CONTROL 0x01 +#define PCA9541_ISTAT 0x02 + +#define PCA9541_CTL_MYBUS (1 << 0) +#define PCA9541_CTL_NMYBUS (1 << 1) +#define PCA9541_CTL_BUSON (1 << 2) +#define PCA9541_CTL_NBUSON (1 << 3) +#define PCA9541_CTL_BUSINIT (1 << 4) +#define PCA9541_CTL_TESTON (1 << 6) +#define PCA9541_CTL_NTESTON (1 << 7) +#define PCA9541_ISTAT_INTIN (1 << 0) +#define PCA9541_ISTAT_BUSINIT (1 << 1) +#define PCA9541_ISTAT_BUSOK (1 << 2) +#define PCA9541_ISTAT_BUSLOST (1 << 3) +#define PCA9541_ISTAT_MYTEST (1 << 6) +#define PCA9541_ISTAT_NMYTEST (1 << 7) +#define PCA9641_ID 0x00 +#define PCA9641_ID_MAGIC 0x38 +#define PCA9641_CONTROL 0x01 +#define PCA9641_STATUS 0x02 +#define PCA9641_TIME 0x03 +#define PCA9641_CTL_LOCK_REQ BIT(0) +#define PCA9641_CTL_LOCK_GRANT BIT(1) +#define PCA9641_CTL_BUS_CONNECT BIT(2) +#define PCA9641_CTL_BUS_INIT BIT(3) +#define PCA9641_CTL_SMBUS_SWRST BIT(4) +#define PCA9641_CTL_IDLE_TIMER_DIS BIT(5) +#define PCA9641_CTL_SMBUS_DIS BIT(6) +#define PCA9641_CTL_PRIORITY BIT(7) +#define PCA9641_STS_OTHER_LOCK BIT(0) +#define PCA9641_STS_BUS_INIT_FAIL BIT(1) +#define PCA9641_STS_BUS_HUNG BIT(2) +#define PCA9641_STS_MBOX_EMPTY BIT(3) +#define PCA9641_STS_MBOX_FULL BIT(4) +#define PCA9641_STS_TEST_INT BIT(5) +#define PCA9641_STS_SCL_IO BIT(6) +#define PCA9641_STS_SDA_IO BIT(7) +#define PCA9641_RES_TIME 0x03 +#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) +#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) +#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) +#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) +#define BUSOFF(x, y) (!((x) & PCA9641_CTL_LOCK_GRANT) && \ + !((y) & PCA9641_STS_OTHER_LOCK)) +#define other_lock(x) ((x) & PCA9641_STS_OTHER_LOCK) +#define lock_grant(x) ((x) & PCA9641_CTL_LOCK_GRANT) + +#define PCA9641_RETRY_TIME 8 + +typedef struct i2c_muxs_struct_flag +{ + int nr; + char name[48]; + struct mutex update_lock; + int flag; +}i2c_mux_flag; + +i2c_mux_flag pca_flag = { + .flag = -1, +}; + +int pca9641_setmuxflag(int nr, int flag) +{ + if (pca_flag.nr == nr) { + pca_flag.flag = flag; + } + return 0; +} +EXPORT_SYMBOL(pca9641_setmuxflag); + +int g_debug = 0; +module_param(g_debug, int, S_IRUGO | S_IWUSR); + +#define PCA_DEBUG(fmt, args...) do { \ + if (g_debug) { \ + printk(KERN_ERR "[pca9641][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + + +/* arbitration timeouts, in jiffies */ +#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ +#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ + +/* arbitration retry delays, in us */ +#define SELECT_DELAY_SHORT 50 +#define SELECT_DELAY_LONG 1000 + +struct pca9541 { + struct i2c_client *client; + unsigned long select_timeout; + unsigned long arb_timeout; +}; + +static const struct i2c_device_id pca9541_id[] = { + {"pca9541", 0}, + {"pca9641", 1}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, pca9541_id); + +#ifdef CONFIG_OF +static const struct of_device_id pca9541_of_match[] = { + { .compatible = "nxp,pca9541" }, + { .compatible = "nxp,pca9641" }, + {} +}; +MODULE_DEVICE_TABLE(of, pca9541_of_match); +#endif + + +/* + * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock the adapter a second time. + */ +static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[2]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + buf[0] = command; + buf[1] = val; + msg.buf = buf; + ret = __i2c_transfer(adap, &msg, 1); + } else { + union i2c_smbus_data data; + + data.byte = val; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + command, + I2C_SMBUS_BYTE_DATA, &data); + } + + return ret; +} + +/* + * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock adapter a second time. + */ +static int pca9541_reg_read(struct i2c_client *client, u8 command) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + u8 val; + + if (adap->algo->master_xfer) { + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &command + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = &val + } + }; + ret = __i2c_transfer(adap, msg, 2); + if (ret == 2) + ret = val; + else if (ret >= 0) + ret = -EIO; + } else { + union i2c_smbus_data data; + + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_READ, + command, + I2C_SMBUS_BYTE_DATA, &data); + if (!ret) + ret = data.byte; + } + return ret; +} + +/* + * Arbitration management functions + */ + +/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ +static void pca9541_release_bus(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg >= 0 && !busoff(reg) && mybus(reg)) + pca9541_reg_write(client, PCA9541_CONTROL, + (reg & PCA9541_CTL_NBUSON) >> 1); +} + +/* + * Arbitration is defined as a two-step process. A bus master can only activate + * the slave bus if it owns it; otherwise it has to request ownership first. + * This multi-step process ensures that access contention is resolved + * gracefully. + * + * Bus Ownership Other master Action + * state requested access + * ---------------------------------------------------- + * off - yes wait for arbitration timeout or + * for other master to drop request + * off no no take ownership + * off yes no turn on bus + * on yes - done + * on no - wait for arbitration timeout or + * for other master to release bus + * + * The main contention point occurs if the slave bus is off and both masters + * request ownership at the same time. In this case, one master will turn on + * the slave bus, believing that it owns it. The other master will request + * bus ownership. Result is that the bus is turned on, and master which did + * _not_ own the slave bus before ends up owning it. + */ + +/* Control commands per PCA9541 datasheet */ +static const u8 pca9541_control[16] = { + 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 +}; + +/* + * Channel arbitration + * + * Return values: + * <0: error + * 0 : bus not acquired + * 1 : bus acquired + */ +static int pca9541_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg < 0) + return reg; + + if (busoff(reg)) { + int istat; + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + istat = pca9541_reg_read(client, PCA9541_ISTAT); + if (!(istat & PCA9541_ISTAT_NMYTEST) + || time_is_before_eq_jiffies(data->arb_timeout)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_NTESTON); + data->select_timeout = SELECT_DELAY_SHORT; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (mybus(reg)) { + /* + * Bus is on, and we own it. We are done with acquisition. + * Reset NTESTON and BUSINIT, then return success. + */ + if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg & ~(PCA9541_CTL_NTESTON + | PCA9541_CTL_BUSINIT)); + return 1; + } else { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + if (time_is_before_eq_jiffies(data->arb_timeout)) { + /* Time is up, take the bus and reset it. */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_BUSINIT + | PCA9541_CTL_NTESTON); + } else { + /* Request bus ownership if needed */ + if (!(reg & PCA9541_CTL_NTESTON)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg | PCA9541_CTL_NTESTON); + } + } + return 0; +} + +static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + + do { + ret = pca9541_arbitrate(client); + if (ret) + return ret < 0 ? ret : 0; + + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + pca9541_release_bus(client); + return 0; +} + +/* +* Arbitration management functions +*/ +static void pca9641_release_bus(struct i2c_client *client) +{ + pca9541_reg_write(client, PCA9641_CONTROL, 0x80); //master 0x80 +} + +/* +* Channel arbitration +* +* Return values: +* <0: error +* 0 : bus not acquired +* 1 : bus acquired +*/ +static int pca9641_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg_ctl, reg_sts; + + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); + if (reg_ctl < 0) + return reg_ctl; + reg_sts = pca9541_reg_read(client, PCA9641_STATUS); + + if (BUSOFF(reg_ctl, reg_sts)) { + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + reg_ctl |= PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); + + if (lock_grant(reg_ctl)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + reg_ctl |= PCA9641_CTL_BUS_CONNECT + | PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + data->select_timeout = SELECT_DELAY_SHORT; + + return 1; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (lock_grant(reg_ctl)) { + /* + * Bus is on, and we own it. We are done with acquisition. + */ + reg_ctl |= PCA9641_CTL_BUS_CONNECT | PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + + return 1; + } else if (other_lock(reg_sts)) { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + reg_ctl |= PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + } + return 0; +} + + +int pca9641_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + int result; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + for (result = 0 ; result < PCA9641_RETRY_TIME ; result ++) { + do { + ret = pca9641_arbitrate(client); + if (ret == 1) { + return 0; + } + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + timeout = jiffies + ARB2_TIMEOUT; + } + return -ETIMEDOUT; +} +EXPORT_SYMBOL(pca9641_select_chan); + +static int pca9641_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + if (pca_flag.flag) { + pca9641_release_bus(client); + } + return 0; +} + +static int pca9641_detect_id(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9641_ID); + if (reg == PCA9641_ID_MAGIC) + return 1; + else + return 0; +} + +/** + ** �޶�: 20180827 ֧��һ��PCA9641 + **/ +static int pca9641_recordflag(struct i2c_adapter *adap) { + if (pca_flag.flag != -1) { + pr_err(" %s %d has init already!!!", __func__, __LINE__); + return -1 ; + } + pca_flag.nr = adap->nr; + PCA_DEBUG(" adap->nr:%d\n", adap->nr); + snprintf(pca_flag.name, sizeof(pca_flag.name),adap->name); + return 0; +} + +static void i2c_lock_adapter(struct i2c_adapter *adapter){ + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + if (parent) + i2c_lock_adapter(parent); + else + rt_mutex_lock(&adapter->bus_lock); +} + +void i2c_unlock_adapter(struct i2c_adapter *adapter) +{ + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + + if (parent) + i2c_unlock_adapter(parent); + else + rt_mutex_unlock(&adapter->bus_lock); +} +/* + * I2C init/probing/exit functions + */ +static int pca9541_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = client->adapter; + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct i2c_mux_core *muxc; + struct pca9541 *data; + int force; + int ret = -ENODEV; + int detect_id; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + detect_id = pca9641_detect_id(client); + + /* + * I2C accesses are unprotected here. + * We have to lock the adapter before releasing the bus. + */ + if (detect_id == 0) { + i2c_lock_adapter(adap); + pca9541_release_bus(client); + i2c_unlock_adapter(adap); + } else { + i2c_lock_adapter(adap); + pca9641_release_bus(client); + i2c_unlock_adapter(adap); + } + + /* Create mux adapter */ + + force = 0; + if (pdata) + force = pdata->modes[0].adap_id; + + if (detect_id == 0) { + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9541_select_chan, pca9541_release_chan); + if (!muxc) + return -ENOMEM; + + data = i2c_mux_priv(muxc); + data->client = client; + + i2c_set_clientdata(client, muxc); + + ret = i2c_mux_add_adapter(muxc, force, 0, 0); + if (ret) + return ret; + } else { + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9641_select_chan, pca9641_release_chan); + if (!muxc) + return -ENOMEM; + + data = i2c_mux_priv(muxc); + data->client = client; + + i2c_set_clientdata(client, muxc); + + ret = i2c_mux_add_adapter(muxc, force, 0, 0); + if (ret) + return ret; + } + pca9641_recordflag(muxc->adapter[0]); + + dev_info(&client->dev, "registered master selector for I2C %s\n", + client->name); + + return 0; + +} + +static int pca9541_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + + i2c_mux_del_adapters(muxc); + return 0; +} + +static struct i2c_driver pca9641_driver = { + .driver = { + .name = "pca9641", + .of_match_table = of_match_ptr(pca9541_of_match), + }, + .probe = pca9541_probe, + .remove = pca9541_remove, + .id_table = pca9541_id, +}; + +module_i2c_driver(pca9641_driver); + +MODULE_AUTHOR("sonic_rd sonic_rd@ruijie.com.cn"); +MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/pmbus.h new file mode 100755 index 000000000000..869a8d1558a4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/pmbus.h @@ -0,0 +1,424 @@ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PMBUS_H +#define PMBUS_H + +#include +#include + +/* + * Registers + */ +enum pmbus_regs { + PMBUS_PAGE = 0x00, + PMBUS_OPERATION = 0x01, + PMBUS_ON_OFF_CONFIG = 0x02, + PMBUS_CLEAR_FAULTS = 0x03, + PMBUS_PHASE = 0x04, + + PMBUS_CAPABILITY = 0x19, + PMBUS_QUERY = 0x1A, + + PMBUS_VOUT_MODE = 0x20, + PMBUS_VOUT_COMMAND = 0x21, + PMBUS_VOUT_TRIM = 0x22, + PMBUS_VOUT_CAL_OFFSET = 0x23, + PMBUS_VOUT_MAX = 0x24, + PMBUS_VOUT_MARGIN_HIGH = 0x25, + PMBUS_VOUT_MARGIN_LOW = 0x26, + PMBUS_VOUT_TRANSITION_RATE = 0x27, + PMBUS_VOUT_DROOP = 0x28, + PMBUS_VOUT_SCALE_LOOP = 0x29, + PMBUS_VOUT_SCALE_MONITOR = 0x2A, + + PMBUS_COEFFICIENTS = 0x30, + PMBUS_POUT_MAX = 0x31, + + PMBUS_FAN_CONFIG_12 = 0x3A, + PMBUS_FAN_COMMAND_1 = 0x3B, + PMBUS_FAN_COMMAND_2 = 0x3C, + PMBUS_FAN_CONFIG_34 = 0x3D, + PMBUS_FAN_COMMAND_3 = 0x3E, + PMBUS_FAN_COMMAND_4 = 0x3F, + + PMBUS_VOUT_OV_FAULT_LIMIT = 0x40, + PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41, + PMBUS_VOUT_OV_WARN_LIMIT = 0x42, + PMBUS_VOUT_UV_WARN_LIMIT = 0x43, + PMBUS_VOUT_UV_FAULT_LIMIT = 0x44, + PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45, + PMBUS_IOUT_OC_FAULT_LIMIT = 0x46, + PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47, + PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48, + PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49, + PMBUS_IOUT_OC_WARN_LIMIT = 0x4A, + PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B, + PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C, + + PMBUS_OT_FAULT_LIMIT = 0x4F, + PMBUS_OT_FAULT_RESPONSE = 0x50, + PMBUS_OT_WARN_LIMIT = 0x51, + PMBUS_UT_WARN_LIMIT = 0x52, + PMBUS_UT_FAULT_LIMIT = 0x53, + PMBUS_UT_FAULT_RESPONSE = 0x54, + PMBUS_VIN_OV_FAULT_LIMIT = 0x55, + PMBUS_VIN_OV_FAULT_RESPONSE = 0x56, + PMBUS_VIN_OV_WARN_LIMIT = 0x57, + PMBUS_VIN_UV_WARN_LIMIT = 0x58, + PMBUS_VIN_UV_FAULT_LIMIT = 0x59, + + PMBUS_IIN_OC_FAULT_LIMIT = 0x5B, + PMBUS_IIN_OC_WARN_LIMIT = 0x5D, + + PMBUS_POUT_OP_FAULT_LIMIT = 0x68, + PMBUS_POUT_OP_WARN_LIMIT = 0x6A, + PMBUS_PIN_OP_WARN_LIMIT = 0x6B, + + PMBUS_STATUS_BYTE = 0x78, + PMBUS_STATUS_WORD = 0x79, + PMBUS_STATUS_VOUT = 0x7A, + PMBUS_STATUS_IOUT = 0x7B, + PMBUS_STATUS_INPUT = 0x7C, + PMBUS_STATUS_TEMPERATURE = 0x7D, + PMBUS_STATUS_CML = 0x7E, + PMBUS_STATUS_OTHER = 0x7F, + PMBUS_STATUS_MFR_SPECIFIC = 0x80, + PMBUS_STATUS_FAN_12 = 0x81, + PMBUS_STATUS_FAN_34 = 0x82, + + PMBUS_READ_VIN = 0x88, + PMBUS_READ_IIN = 0x89, + PMBUS_READ_VCAP = 0x8A, + PMBUS_READ_VOUT = 0x8B, + PMBUS_READ_IOUT = 0x8C, + PMBUS_READ_TEMPERATURE_1 = 0x8D, + PMBUS_READ_TEMPERATURE_2 = 0x8E, + PMBUS_READ_TEMPERATURE_3 = 0x8F, + PMBUS_READ_FAN_SPEED_1 = 0x90, + PMBUS_READ_FAN_SPEED_2 = 0x91, + PMBUS_READ_FAN_SPEED_3 = 0x92, + PMBUS_READ_FAN_SPEED_4 = 0x93, + PMBUS_READ_DUTY_CYCLE = 0x94, + PMBUS_READ_FREQUENCY = 0x95, + PMBUS_READ_POUT = 0x96, + PMBUS_READ_PIN = 0x97, + + PMBUS_REVISION = 0x98, + PMBUS_MFR_ID = 0x99, + PMBUS_MFR_MODEL = 0x9A, + PMBUS_MFR_REVISION = 0x9B, + PMBUS_MFR_LOCATION = 0x9C, + PMBUS_MFR_DATE = 0x9D, + PMBUS_MFR_SERIAL = 0x9E, + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ + PMBUS_VIRT_BASE = 0x100, + PMBUS_VIRT_READ_TEMP_AVG, + PMBUS_VIRT_READ_TEMP_MIN, + PMBUS_VIRT_READ_TEMP_MAX, + PMBUS_VIRT_RESET_TEMP_HISTORY, + PMBUS_VIRT_READ_VIN_AVG, + PMBUS_VIRT_READ_VIN_MIN, + PMBUS_VIRT_READ_VIN_MAX, + PMBUS_VIRT_RESET_VIN_HISTORY, + PMBUS_VIRT_READ_IIN_AVG, + PMBUS_VIRT_READ_IIN_MIN, + PMBUS_VIRT_READ_IIN_MAX, + PMBUS_VIRT_RESET_IIN_HISTORY, + PMBUS_VIRT_READ_PIN_AVG, + PMBUS_VIRT_READ_PIN_MIN, + PMBUS_VIRT_READ_PIN_MAX, + PMBUS_VIRT_RESET_PIN_HISTORY, + PMBUS_VIRT_READ_POUT_AVG, + PMBUS_VIRT_READ_POUT_MIN, + PMBUS_VIRT_READ_POUT_MAX, + PMBUS_VIRT_RESET_POUT_HISTORY, + PMBUS_VIRT_READ_VOUT_AVG, + PMBUS_VIRT_READ_VOUT_MIN, + PMBUS_VIRT_READ_VOUT_MAX, + PMBUS_VIRT_RESET_VOUT_HISTORY, + PMBUS_VIRT_READ_IOUT_AVG, + PMBUS_VIRT_READ_IOUT_MIN, + PMBUS_VIRT_READ_IOUT_MAX, + PMBUS_VIRT_RESET_IOUT_HISTORY, + PMBUS_VIRT_READ_TEMP2_AVG, + PMBUS_VIRT_READ_TEMP2_MIN, + PMBUS_VIRT_READ_TEMP2_MAX, + PMBUS_VIRT_RESET_TEMP2_HISTORY, + + PMBUS_VIRT_READ_VMON, + PMBUS_VIRT_VMON_UV_WARN_LIMIT, + PMBUS_VIRT_VMON_OV_WARN_LIMIT, + PMBUS_VIRT_VMON_UV_FAULT_LIMIT, + PMBUS_VIRT_VMON_OV_FAULT_LIMIT, + PMBUS_VIRT_STATUS_VMON, +}; + +/* + * OPERATION + */ +#define PB_OPERATION_CONTROL_ON BIT(7) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT BIT(4) +#define PB_CAPABILITY_ERROR_CHECK BIT(7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1)) +#define PB_FAN_2_RPM BIT(2) +#define PB_FAN_2_INSTALLED BIT(3) +#define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5)) +#define PB_FAN_1_RPM BIT(6) +#define PB_FAN_1_INSTALLED BIT(7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE BIT(0) +#define PB_STATUS_CML BIT(1) +#define PB_STATUS_TEMPERATURE BIT(2) +#define PB_STATUS_VIN_UV BIT(3) +#define PB_STATUS_IOUT_OC BIT(4) +#define PB_STATUS_VOUT_OV BIT(5) +#define PB_STATUS_OFF BIT(6) +#define PB_STATUS_BUSY BIT(7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN BIT(8) +#define PB_STATUS_OTHER BIT(9) +#define PB_STATUS_FANS BIT(10) +#define PB_STATUS_POWER_GOOD_N BIT(11) +#define PB_STATUS_WORD_MFR BIT(12) +#define PB_STATUS_INPUT BIT(13) +#define PB_STATUS_IOUT_POUT BIT(14) +#define PB_STATUS_VOUT BIT(15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING BIT(0) +#define PB_POUT_OP_FAULT BIT(1) +#define PB_POWER_LIMITING BIT(2) +#define PB_CURRENT_SHARE_FAULT BIT(3) +#define PB_IOUT_UC_FAULT BIT(4) +#define PB_IOUT_OC_WARNING BIT(5) +#define PB_IOUT_OC_LV_FAULT BIT(6) +#define PB_IOUT_OC_FAULT BIT(7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT BIT(4) +#define PB_VOLTAGE_UV_WARNING BIT(5) +#define PB_VOLTAGE_OV_WARNING BIT(6) +#define PB_VOLTAGE_OV_FAULT BIT(7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING BIT(0) +#define PB_IIN_OC_WARNING BIT(1) +#define PB_IIN_OC_FAULT BIT(2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT BIT(4) +#define PB_TEMP_UT_WARNING BIT(5) +#define PB_TEMP_OT_WARNING BIT(6) +#define PB_TEMP_OT_FAULT BIT(7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING BIT(0) +#define PB_FAN_AIRFLOW_FAULT BIT(1) +#define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2) +#define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3) +#define PB_FAN_FAN2_WARNING BIT(4) +#define PB_FAN_FAN1_WARNING BIT(5) +#define PB_FAN_FAN2_FAULT BIT(6) +#define PB_FAN_FAN1_FAULT BIT(7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0) +#define PB_CML_FAULT_OTHER_COMM BIT(1) +#define PB_CML_FAULT_PROCESSOR BIT(3) +#define PB_CML_FAULT_MEMORY BIT(4) +#define PB_CML_FAULT_PACKET_ERROR BIT(5) +#define PB_CML_FAULT_INVALID_DATA BIT(6) +#define PB_CML_FAULT_INVALID_COMMAND BIT(7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN BIT(0) +#define PMBUS_HAVE_VCAP BIT(1) +#define PMBUS_HAVE_VOUT BIT(2) +#define PMBUS_HAVE_IIN BIT(3) +#define PMBUS_HAVE_IOUT BIT(4) +#define PMBUS_HAVE_PIN BIT(5) +#define PMBUS_HAVE_POUT BIT(6) +#define PMBUS_HAVE_FAN12 BIT(7) +#define PMBUS_HAVE_FAN34 BIT(8) +#define PMBUS_HAVE_TEMP BIT(9) +#define PMBUS_HAVE_TEMP2 BIT(10) +#define PMBUS_HAVE_TEMP3 BIT(11) +#define PMBUS_HAVE_STATUS_VOUT BIT(12) +#define PMBUS_HAVE_STATUS_IOUT BIT(13) +#define PMBUS_HAVE_STATUS_INPUT BIT(14) +#define PMBUS_HAVE_STATUS_TEMP BIT(15) +#define PMBUS_HAVE_STATUS_FAN12 BIT(16) +#define PMBUS_HAVE_STATUS_FAN34 BIT(17) +#define PMBUS_HAVE_VMON BIT(18) +#define PMBUS_HAVE_STATUS_VMON BIT(19) + +enum pmbus_data_format { linear = 0, direct, vid }; +enum vrm_version { vr11 = 0, vr12, vr13 }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + enum vrm_version vrm_version[PMBUS_PAGES]; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); + + /* Regulator functionality, if supported by this chip driver. */ + int num_regulators; + const struct regulator_desc *reg_desc; +}; + +/* Regulator ops */ + +extern const struct regulator_ops pmbus_regulator_ops; + +/* Macro for filling in array of struct regulator_desc */ +#define PMBUS_REGULATOR(_name, _id) \ + [_id] = { \ + .name = (_name # _id), \ + .id = (_id), \ + .of_match = of_match_ptr(_name # _id), \ + .regulators_node = of_match_ptr("regulators"), \ + .ops = &pmbus_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, + u8 value); +int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg, + u8 mask, u8 value); +void pmbus_clear_faults(struct i2c_client *client); +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg-gpio-xeon.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg-gpio-xeon.c new file mode 100644 index 000000000000..89043f377888 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg-gpio-xeon.c @@ -0,0 +1,357 @@ +/* + * GPIO interface for XEON Super I/O chip + * + * Author: sonic_rd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GPIO_NAME "xeon-gpio" +#define GPIO_IOSIZE 7 +#define GPIO_BASE 0x500 + +#define GPIO_USE_SEL GPIO_BASE +#define GP_IO_SEL (GPIO_BASE+0x4) +#define GP_LVL (GPIO_BASE+0xC) + +#define GPIO_USE_SEL2 (GPIO_BASE+0x30) +#define GP_IO_SEL2 (GPIO_BASE+0x34) +#define GP_LVL2 (GPIO_BASE+0x38) + +#define GPIO_USE_SEL3 (GPIO_BASE+0x40) +#define GP_IO_SEL3 (GPIO_BASE+0x44) +#define GP_LVL3 (GPIO_BASE+0x48) + + +#define GPIO_BASE_ID 0 +#define BANKSIZE 32 + +#define GPIO_SDA 17 +#define GPIO_SCL 1 + +#define GPIO_XEON_SPIN_LOCK(lock, flags) spin_lock_irqsave(&(lock), (flags)) +#define GPIO_XEON_SPIN_UNLOCK(lock, flags) spin_unlock_irqrestore(&(lock), (flags)) +static DEFINE_SPINLOCK(sio_lock); + +/****************** i2c adapter with gpio ***********************/ + +static struct i2c_gpio_platform_data i2c_pdata = { + .timeout = 200, + .udelay = 10, + .scl_is_output_only = 0, + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, +}; + +static struct gpiod_lookup_table rg_gpio_lookup_table = { + .dev_id = "i2c-gpio", + .table = { + GPIO_LOOKUP(GPIO_NAME, GPIO_SDA, "sda", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP(GPIO_NAME, GPIO_SCL, "scl", + GPIO_ACTIVE_HIGH), + }, +}; + +static void i2c_gpio_release(struct device *dev) +{ + return; +} + +static struct platform_device i2c_gpio = { + .name = "i2c-gpio", + .num_resources = 0, + .id = -1, + + .dev = { + .platform_data = &i2c_pdata, + .release = i2c_gpio_release, + } +}; + +static int xeon_gpio_get(struct gpio_chip *gc, unsigned gpio_num) +{ + unsigned int data; + unsigned int bank, offset; + unsigned long flags; + + data = 0; + bank = gpio_num / BANKSIZE; + offset = gpio_num % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GP_LVL) & (1 << offset); + if (data) { + data = 1; + } + } else if (bank == 1) { + data = inl(GP_LVL2) & (1 << offset); + if (data) { + data = 1; + } + } else if (bank == 2) { + data = inl(GP_LVL3) & (1 << offset); + if (data) { + data = 1; + } + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); + + return data; +} + +static int xeon_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) +{ + unsigned int data; + unsigned int bank, offset; + unsigned long flags; + + bank = gpio_num / BANKSIZE; + offset = gpio_num % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GP_IO_SEL); + data = data | (1 << offset); + outl(data, GP_IO_SEL); + } else if (bank == 1) { + data = inl(GP_IO_SEL2); + data = data | (1 << offset); + outl(data, GP_IO_SEL2); + } else if (bank == 2) { + data = inl(GP_IO_SEL3); + data = data | (1 << offset); + outl(data, GP_IO_SEL3); + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); + + return 0; +} + +static void xeon_gpio_set(struct gpio_chip *gc, + unsigned gpio_num, int val) +{ + unsigned int data; + unsigned int bank, offset; + unsigned long flags; + + bank = gpio_num / BANKSIZE; + offset = gpio_num % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GP_LVL); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL); + } else if (bank == 1) { + data = inl(GP_LVL2); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL2); + } else if (bank == 2) { + data = inl(GP_LVL3); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL3); + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); +} + +static int xeon_gpio_direction_out(struct gpio_chip *gc, + unsigned gpio_num, int val) +{ + unsigned int data; + unsigned int bank, offset; + unsigned long flags; + + bank = gpio_num / BANKSIZE; + offset = gpio_num % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GP_IO_SEL); + data = data & ~(1 << offset); + outl(data, GP_IO_SEL); + + data = inl(GP_LVL); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL); + } else if (bank == 1) { + data = inl(GP_IO_SEL2); + data = data & ~(1 << offset); + outl(data, GP_IO_SEL2); + + data = inl(GP_LVL2); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL2); + } else if (bank == 2) { + data = inl(GP_IO_SEL3); + data = data & ~(1 << offset); + outl(data, GP_IO_SEL3); + + data = inl(GP_LVL3); + if (val) { + data = data | (1 << offset); + } else { + data = data & ~(1 << offset); + } + outl(data, GP_LVL3); + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); + + return 0; +} + +static int xeon_gpio_request(struct gpio_chip *chip, unsigned int offset) +{ + unsigned int data; + unsigned int bank, tmp_offset; + unsigned long flags; + + bank = offset / BANKSIZE; + tmp_offset = offset % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GPIO_USE_SEL); + data = data | (1 << tmp_offset); + outl(data, GPIO_USE_SEL); + } else if (bank == 1) { + data = inl(GPIO_USE_SEL2); + data = data | (1 << tmp_offset); + outl(data, GPIO_USE_SEL2); + } else if (bank == 2) { + data = inl(GPIO_USE_SEL3); + data = data | (1 << tmp_offset); + outl(data, GPIO_USE_SEL3); + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); + return 0; +} + +static void xeon_gpio_free(struct gpio_chip *chip, unsigned int offset) +{ + unsigned int data; + unsigned int bank, tmp_offset; + unsigned long flags; + + bank = offset / BANKSIZE; + tmp_offset = offset % BANKSIZE; + + GPIO_XEON_SPIN_LOCK(sio_lock, flags); + if (bank == 0) { + data = inl(GPIO_USE_SEL); + data = data & ~(1 << tmp_offset); + outl(data, GPIO_USE_SEL); + } else if (bank == 1) { + data = inl(GPIO_USE_SEL2); + data = data & ~(1 << tmp_offset); + outl(data, GPIO_USE_SEL2); + } else if (bank == 2) { + data = inl(GPIO_USE_SEL3); + data = data & ~(1 << tmp_offset); + outl(data, GPIO_USE_SEL3); + } + GPIO_XEON_SPIN_UNLOCK(sio_lock, flags); +} + +static struct gpio_chip xeon_gpio_chip = { + .label = GPIO_NAME, + .owner = THIS_MODULE, + .get = xeon_gpio_get, + .direction_input = xeon_gpio_direction_in, + .set = xeon_gpio_set, + .direction_output = xeon_gpio_direction_out, + .request = xeon_gpio_request, + .free = xeon_gpio_free, +}; + +static int __init xeon_gpio_init(void) +{ + int err; + if (!request_region(GPIO_BASE, GPIO_IOSIZE, GPIO_NAME)) + return -EBUSY; + + xeon_gpio_chip.base = GPIO_BASE_ID; + xeon_gpio_chip.ngpio = 96; + + err = gpiochip_add_data(&xeon_gpio_chip, NULL); + if (err < 0) + goto gpiochip_add_err; + gpiod_add_lookup_table(&rg_gpio_lookup_table); + err = platform_device_register(&i2c_gpio); + if (err < 0) { + goto i2c_get_adapter_err; + } + return 0; + +i2c_get_adapter_err: + gpiod_remove_lookup_table(&rg_gpio_lookup_table); + platform_device_unregister(&i2c_gpio); + gpiochip_remove(&xeon_gpio_chip); + +gpiochip_add_err: + release_region(GPIO_BASE, GPIO_IOSIZE); + return -1; +} + +static void __exit xeon_gpio_exit(void) +{ + gpiod_remove_lookup_table(&rg_gpio_lookup_table); + platform_device_unregister(&i2c_gpio); + mdelay(100); + gpiochip_remove(&xeon_gpio_chip); + release_region(GPIO_BASE, GPIO_IOSIZE); +} + +module_init(xeon_gpio_init); +module_exit(xeon_gpio_exit); + +MODULE_AUTHOR("sonic_rd "); +MODULE_DESCRIPTION("GPIO interface for XEON Super I/O chip"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_fan.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_fan.c new file mode 100755 index 000000000000..45c9e4ab4c3b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_fan.c @@ -0,0 +1,266 @@ +/* + * rg_fan.c - A driver for control rg_fan base on rg_fan.c + * + * Copyright (c) 1998, 1999 Frodo Looijaard + * Copyright (c) 2019 + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FAN_SIZE (256) +#define SYS_FAN_BUF_LEN (64) + +typedef enum { + DBG_START, + DBG_VERBOSE, + DBG_KEY, + DBG_WARN, + DBG_ERROR, + DBG_END, +} dbg_level_t; + +static int debuglevel = 0; + +#define DBG_DEBUG(fmt, arg...) \ + do { \ + if (debuglevel > DBG_START && debuglevel < DBG_ERROR) { \ + printk(KERN_INFO "[DEBUG]:<%s, %d>:" fmt, \ + __FUNCTION__, __LINE__, ##arg); \ + } else if (debuglevel >= DBG_ERROR) { \ + printk(KERN_ERR "[DEBUG]:<%s, %d>:" fmt, __FUNCTION__, \ + __LINE__, ##arg); \ + } else { \ + } \ + } while (0) + +#define DBG_ERROR(fmt, arg...) \ + do { \ + if (debuglevel > DBG_START) { \ + printk(KERN_ERR "[ERROR]:<%s, %d>:" fmt, __FUNCTION__, \ + __LINE__, ##arg); \ + } \ + } while (0) + +extern s32 platform_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command); +extern s32 platform_i2c_smbus_read_i2c_block_data( + const struct i2c_client *client, u8 command, u8 length, u8 *values); +extern s32 platform_i2c_smbus_read_word_data(const struct i2c_client *client, u8 command); + +typedef enum dfd_dev_info_type_e { + DFD_DEV_INFO_TYPE_MAC = 1, + DFD_DEV_INFO_TYPE_NAME = 2, + DFD_DEV_INFO_TYPE_SN = 3, + DFD_DEV_INFO_TYPE_PWR_CONS = 4, + DFD_DEV_INFO_TYPE_HW_INFO = 5, + DFD_DEV_INFO_TYPE_DEV_TYPE = 6, +} dfd_dev_tlv_type_t; + +typedef struct dfd_dev_head_info_s { + uint8_t ver; /* define E2PROM version,default is 0x01 */ + uint8_t flag; /* flag is 0x7E in new version E2PROM */ + uint8_t hw_ver; /* consists of main version and revise version */ + uint8_t type; /* HW type */ + int16_t tlv_len; /* 16 bits */ +} dfd_dev_head_info_t; + +typedef struct dfd_dev_tlv_info_s { + uint8_t type; + uint8_t len; + uint8_t data[0]; +} dfd_dev_tlv_info_t; + +struct fan_data { + struct i2c_client *client; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated[8]; /* In jiffies */ + u8 data[FAN_SIZE]; /* Register value */ +}; + +static ssize_t show_fan_sysfs_tlv_value(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct fan_data *data = i2c_get_clientdata(client); + + dfd_dev_head_info_t info; + uint8_t tmp_tlv_len[sizeof(uint16_t)]; + uint8_t *tlv_data; + dfd_dev_tlv_info_t *tlv; + int type; + int buf_len = SYS_FAN_BUF_LEN - 1; + u8 sysfs_buf[SYS_FAN_BUF_LEN]; + int i; + int ret = 0; + + mutex_lock(&data->update_lock); + memset(sysfs_buf, 0, SYS_FAN_BUF_LEN); + ret = platform_i2c_smbus_read_i2c_block_data( + client, 0, sizeof(dfd_dev_head_info_t), (uint8_t *)&info); + if (ret != sizeof(dfd_dev_head_info_t)) { + DBG_ERROR("fan maybe not set mac or not present0"); + goto exit; + } + + /* transform TLV_LEN */ + memcpy(tmp_tlv_len, (uint8_t *)&info.tlv_len, sizeof(int16_t)); + info.tlv_len = (tmp_tlv_len[0] << 8) + tmp_tlv_len[1]; + + if ((info.tlv_len <= 0) || (info.tlv_len > 0xFF)) { + DBG_ERROR("fan maybe not set mac or not present1"); + goto exit; + } + + type = attr->index; + tlv_data = (uint8_t *)kmalloc(info.tlv_len, GFP_KERNEL); + memset(tlv_data, 0, info.tlv_len); + + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + for (i = 0; i < info.tlv_len; i += 32) + if (platform_i2c_smbus_read_i2c_block_data(client, + sizeof(dfd_dev_head_info_t) + i, + 32, tlv_data + i) != 32) + break; + } + + DBG_DEBUG("TLV Len:%d\n", (int)sizeof(dfd_dev_tlv_info_t)); + for (tlv = (dfd_dev_tlv_info_t *)tlv_data; + (ulong)tlv < (ulong)tlv_data + info.tlv_len;) { + DBG_DEBUG( + "tlv: %p, tlv->type: 0x%x, tlv->len: 0x%x info->tlv_len: 0x%x\n", + tlv, tlv->type, tlv->len, info.tlv_len); + if (tlv->type == type && buf_len >= tlv->len) { + memcpy((uint8_t *)sysfs_buf, (uint8_t *)tlv->data, + tlv->len); + buf_len = (uint32_t)tlv->len; + break; + } + tlv = (dfd_dev_tlv_info_t *)((uint8_t *)tlv + + sizeof(dfd_dev_tlv_info_t) + + tlv->len); + } + + kfree(tlv_data); + DBG_DEBUG("value: %s \n", sysfs_buf); +exit: + mutex_unlock(&data->update_lock); + return sprintf(buf, "%s\n", sysfs_buf); +} + +static ssize_t show_fan_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct fan_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i; + + mutex_lock(&data->update_lock); + + if (i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + for (i = 0; i < FAN_SIZE; i += 32) { + if (platform_i2c_smbus_read_i2c_block_data( + client, i, 32, data->data + i) != 32) + goto exit; + } + } else { + for (i = 0; i < FAN_SIZE; i += 2) { + int word = platform_i2c_smbus_read_word_data(client, i); + if (word < 0) + goto exit; + data->data[i] = word & 0xff; + data->data[i + 1] = word >> 8; + } + } + memcpy(buf, &data->data[0], FAN_SIZE); +exit: + mutex_unlock(&data->update_lock); + return FAN_SIZE; +} + +static SENSOR_DEVICE_ATTR(fan_hw_version, S_IRUGO, show_fan_sysfs_tlv_value, NULL, DFD_DEV_INFO_TYPE_HW_INFO); +static SENSOR_DEVICE_ATTR(fan_sn, S_IRUGO, show_fan_sysfs_tlv_value, NULL, DFD_DEV_INFO_TYPE_SN); +static SENSOR_DEVICE_ATTR(fan_type, S_IRUGO, show_fan_sysfs_tlv_value, NULL, DFD_DEV_INFO_TYPE_NAME); +static SENSOR_DEVICE_ATTR(fan, S_IRUGO, show_fan_value, NULL, 0); + +static struct attribute *fan_sysfs_attrs[] = { + &sensor_dev_attr_fan_hw_version.dev_attr.attr, + &sensor_dev_attr_fan_sn.dev_attr.attr, + &sensor_dev_attr_fan_type.dev_attr.attr, + &sensor_dev_attr_fan.dev_attr.attr, + NULL +}; + +static const struct attribute_group fan_sysfs_group = { + .attrs = fan_sysfs_attrs, +}; + +static int fan_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct fan_data *data; + int status; + + status = -1; + DBG_DEBUG("fan_probe(0x%02x)\n", client->addr); + data = devm_kzalloc(&client->dev, sizeof(struct fan_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + status = sysfs_create_group(&client->dev.kobj, &fan_sysfs_group); + if (status != 0) { + DBG_ERROR(" sysfs_create_group err\n"); + return status; + } + return 0; +} + +static int fan_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &fan_sysfs_group); + return 0; +} + +static const struct i2c_device_id fan_id[] = { { "rg_fan", 0 }, {} }; +MODULE_DEVICE_TABLE(i2c, fan_id); + +static struct i2c_driver rg_fan_driver = { + .driver = { + .name = "rg_fan", + }, + .probe = fan_probe, + .remove = fan_remove, + .id_table = fan_id, +}; + +module_i2c_driver(rg_fan_driver); +MODULE_AUTHOR("sonic_rd "); +MODULE_DESCRIPTION("ruijie fan driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_psu.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_psu.c new file mode 100755 index 000000000000..4b58a5102f24 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/rg_psu.c @@ -0,0 +1,340 @@ +/* + * rg_cpld.c - A driver for pmbus psu + * + * Copyright (c) 2019 + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAGIC_PSU_RATE (0xA7) +#define MAGIC_PSU_OUT_CURRENT (0x8C) +#define MAGIC_PSU_OUT_VOLTAGE (0x8B) +#define MAGIC_PSU_IN_VOLTAGE (0x88) +#define MAGIC_PSU_IN_CURRENT (0x89) +#define MAGIC_PSU_TEMP (0x8D) +#define MAGIC_PSU_TYPE (0x25) +#define MAGIC_PSU_SN (0x38) +#define MAGIC_PSU_HW (0x35) +#define PSU_SIZE (256) + +typedef enum { + DBG_START, + DBG_VERBOSE, + DBG_KEY, + DBG_WARN, + DBG_ERROR, + DBG_END, +} dbg_level_t; + +static int debuglevel = 0; + +#define DBG_DEBUG(fmt, arg...) \ + do { \ + if (debuglevel > DBG_START && debuglevel < DBG_ERROR) { \ + printk(KERN_INFO "[DEBUG]:<%s, %d>:" fmt, \ + __FUNCTION__, __LINE__, ##arg); \ + } else if (debuglevel >= DBG_ERROR) { \ + printk(KERN_ERR "[DEBUG]:<%s, %d>:" fmt, __FUNCTION__, \ + __LINE__, ##arg); \ + } else { \ + } \ + } while (0) + +#define DBG_INFO(fmt, arg...) \ + do { \ + if (debuglevel > DBG_KEY) { \ + printk(KERN_INFO "[INFO]:<%s, %d>:" fmt, __FUNCTION__, \ + __LINE__, ##arg); \ + } \ + } while (0) + +#define DBG_ERROR(fmt, arg...) \ + do { \ + if (debuglevel > DBG_START) { \ + printk(KERN_ERR "[ERROR]:<%s, %d>:" fmt, __FUNCTION__, \ + __LINE__, ##arg); \ + } \ + } while (0) + +static const unsigned short rg_i2c_psu[] = { 0x50, 0x53, 0x58, 0x5b, I2C_CLIENT_END }; + +extern s32 platform_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command); +extern s32 platform_i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values); + +struct psu_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[PSU_SIZE]; /* Register value */ +}; + +static ssize_t show_psu_sysfs_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_sysfs_15_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_psu_value(struct device *dev, struct device_attribute *da, char *buf); + +static SENSOR_DEVICE_ATTR(psu_rate, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_RATE); +static SENSOR_DEVICE_ATTR(psu_out_current, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_OUT_CURRENT); +static SENSOR_DEVICE_ATTR(psu_out_voltage, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_OUT_VOLTAGE); +static SENSOR_DEVICE_ATTR(psu_in_voltage, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_IN_VOLTAGE); +static SENSOR_DEVICE_ATTR(psu_in_current, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_IN_CURRENT); +static SENSOR_DEVICE_ATTR(psu_temp, S_IRUGO, show_psu_sysfs_value, NULL, MAGIC_PSU_TEMP); +static SENSOR_DEVICE_ATTR(psu_type, S_IRUGO, show_sysfs_15_value, NULL, MAGIC_PSU_TYPE); +static SENSOR_DEVICE_ATTR(psu_sn, S_IRUGO, show_sysfs_15_value, NULL, MAGIC_PSU_SN); +static SENSOR_DEVICE_ATTR(psu_hw, S_IRUGO, show_psu_value, NULL, MAGIC_PSU_HW); + +static struct attribute *psu_pmbus_sysfs_attrs[] = { + &sensor_dev_attr_psu_rate.dev_attr.attr, + &sensor_dev_attr_psu_out_current.dev_attr.attr, + &sensor_dev_attr_psu_out_voltage.dev_attr.attr, + &sensor_dev_attr_psu_in_voltage.dev_attr.attr, + &sensor_dev_attr_psu_in_current.dev_attr.attr, + &sensor_dev_attr_psu_temp.dev_attr.attr, + NULL +}; + +static struct attribute *psu_fru_sysfs_attrs[] = { + &sensor_dev_attr_psu_type.dev_attr.attr, + &sensor_dev_attr_psu_sn.dev_attr.attr, + &sensor_dev_attr_psu_hw.dev_attr.attr, + NULL +}; + +static const struct attribute_group psu_pmbus_sysfs_attrs_group = { + .attrs = psu_pmbus_sysfs_attrs, +}; + +static const struct attribute_group psu_fru_sysfs_attrs_group = { + .attrs = psu_fru_sysfs_attrs, +}; + +static ssize_t show_psu_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + int ret; + char psu_buf[PSU_SIZE]; + memset(psu_buf, 0, PSU_SIZE); + mutex_lock(&data->update_lock); + ret = platform_i2c_smbus_read_i2c_block_data(client, attr->index, 2, psu_buf); + if (ret < 0) { + DBG_ERROR("Failed to read psu\n"); + } + DBG_DEBUG("cpld reg pos:0x%x value:0x%02x\n", attr->index, data->data[0]); + mutex_unlock(&data->update_lock); + return snprintf(buf, 3, "%s\n", psu_buf); +} + +static int linear_to_value(short reg, bool v_out) +{ + short exponent; + int mantissa; + long val; + + if (v_out) { + exponent = -9; + mantissa = reg; + } else { + exponent = reg >> 11; + mantissa = (((reg & 0x7ff) << 5)) >> 5; + } + val = mantissa; + val = val * 1000L; + if (exponent >= 0) { + val <<= exponent; + } else { + val >>= -exponent; + } + + return val; +} + +static ssize_t show_psu_sysfs_value(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + int ret; + u8 smbud_buf[PSU_SIZE]; + uint16_t value; + int result; + + ret = -1; + memset(smbud_buf, 0, PSU_SIZE); + mutex_lock(&data->update_lock); + DBG_DEBUG("ret:%d", ret); + ret = platform_i2c_smbus_read_i2c_block_data(client, attr->index, 2, smbud_buf); + if (ret < 0) { + DBG_ERROR("Failed to read psu \n"); + } + value = smbud_buf[1]; + value = value << 8; + value |= smbud_buf[0]; + + if (attr->index == 0x8b) { + result = linear_to_value(value, true); + } else { + result = linear_to_value(value, false); + } + mutex_unlock(&data->update_lock); + return snprintf(buf, PSU_SIZE, "%d\n", result); +} + +static ssize_t show_sysfs_15_value(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + int ret; + u8 smbud_buf[PSU_SIZE]; + + memset(smbud_buf, 0, PSU_SIZE); + mutex_lock(&data->update_lock); + ret = platform_i2c_smbus_read_i2c_block_data(client, attr->index, 15, smbud_buf); + if (ret < 0) { + DBG_ERROR("Failed to read psu\n"); + } + mutex_unlock(&data->update_lock); + return snprintf(buf, PSU_SIZE, "%s\n", smbud_buf); +} + +static ssize_t show_sysfs_13_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + int ret; + u8 smbud_buf[PSU_SIZE]; + + memset(smbud_buf, 0, PSU_SIZE); + mutex_lock(&data->update_lock); + ret = platform_i2c_smbus_read_i2c_block_data(client, attr->index, 13, smbud_buf); + if (ret < 0) { + DBG_ERROR("Failed to read psu \n"); + } + mutex_unlock(&data->update_lock); + return snprintf(buf, PSU_SIZE, "%s\n", smbud_buf); +} + +static int psu_detect(struct i2c_client *new_client, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int conf; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + conf = platform_i2c_smbus_read_byte_data(new_client, 0); + if (!conf) + return -ENODEV; + + return 0; +} + +static int psu_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct psu_data *data; + int status; + + status = -1; + data = devm_kzalloc(&client->dev, sizeof(struct psu_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + switch (client->addr) { + case 0x50: + case 0x53: + status = sysfs_create_group(&client->dev.kobj, + &psu_fru_sysfs_attrs_group); + if (status != 0) { + DBG_ERROR("%s %d sysfs_create_group err\n", __func__, __LINE__); + } + break; + case 0x58: + case 0x5b: + status = sysfs_create_group(&client->dev.kobj, + &psu_pmbus_sysfs_attrs_group); + if (status != 0) { + DBG_ERROR("%s %d sysfs_create_group err\n", __func__, __LINE__); + break; + } + break; + default: + break; + } + + return status; +} + +static int psu_remove(struct i2c_client *client) +{ + switch (client->addr) { + case 0x50: + case 0x53: + sysfs_remove_group(&client->dev.kobj, &psu_fru_sysfs_attrs_group); + break; + case 0x58: + case 0x5b: + sysfs_remove_group(&client->dev.kobj, &psu_pmbus_sysfs_attrs_group); + break; + default: + break; + } + return 0; +} + +static const struct i2c_device_id psu_id[] = { + { "rg_psu", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, psu_id); + +static struct i2c_driver rg_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "rg_psu", + }, + .probe = psu_probe, + .remove = psu_remove, + .id_table = psu_id, + .detect = psu_detect, + .address_list = rg_i2c_psu, +}; + +module_i2c_driver(rg_psu_driver); + +MODULE_AUTHOR("sonic_rd "); +MODULE_DESCRIPTION("ruijie pmbus psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/modules/ruijie_platform.c b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/ruijie_platform.c new file mode 100755 index 000000000000..105e6f1d26cf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/modules/ruijie_platform.c @@ -0,0 +1,97 @@ +/* + * ruijie_platform.c - A driver for ruijie platform module + * + * Copyright (c) 2019 + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PLATFORM_I2C_RETRY_TIMES (3) + +s32 platform_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try ++) { + if ((ret = i2c_smbus_read_byte_data(client, command)) >= 0) + break; + } + return ret; +} +EXPORT_SYMBOL(platform_i2c_smbus_read_byte_data); + +s32 platform_i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values) +{ + int try ; + s32 ret; + + ret = -1; + for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try ++) { + if ((ret = i2c_smbus_read_i2c_block_data(client, command, length, values)) >= 0) + break; + } + return ret; +} +EXPORT_SYMBOL(platform_i2c_smbus_read_i2c_block_data); + +s32 platform_i2c_smbus_read_word_data(const struct i2c_client *client, u8 command) +{ + int try; + s32 ret; + + ret = -1; + for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try ++) { + if ((ret = i2c_smbus_read_word_data(client, command)) >= 0) + break; + } + return ret; +} +EXPORT_SYMBOL(platform_i2c_smbus_read_word_data); + +static int __init ruijie_platform_init(void) +{ + return 0; +} + +static void __exit ruijie_platform_exit(void) +{ + return; +} + +module_init(ruijie_platform_init); +module_exit(ruijie_platform_exit); + +MODULE_DESCRIPTION("ruijie Platform Support"); +MODULE_AUTHOR("sonic_rd "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/avscontrol.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/avscontrol.py new file mode 100755 index 000000000000..c3461d7fcf67 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/avscontrol.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +import click +import time +import syslog +import traceback +from ruijieutil import waitForDocker, STARTMODULE, AVSUTIL +try: + from rest.rest import BMCMessage +except ImportError: + pass + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def avswarninglog(s): + s = s.decode('utf-8').encode('gb2312') + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_WARNING,s) + +def avscriticallog(s): + s = s.decode('utf-8').encode('gb2312') + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_CRIT,s) + +def avserror(s): + s = s.decode('utf-8').encode('gb2312') + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR,s) + +def avsinfo(s): + syslog.openlog("AVSCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_INFO,s) + +def doAvsCtrol(): + index = 0 + url = "/xyz/openbmc_project/hostchannel/attr/MacRov" + while True: + if "avscontrol_restful" in STARTMODULE and STARTMODULE['avscontrol_restful'] == 1: + try: + #for alibmc rest.py has define get_macrov_value function + get_macrov_value = getattr(BMCMessage(), "get_macrov_value", None) + if callable(get_macrov_value): + macrov_value = int(get_macrov_value()) + else: + macrov_value = int(BMCMessage().getBmcValue(url)) + if macrov_value >= 0: + break + except Exception as e: + time.sleep(2) + continue + else: + if AVSUTIL.mac_adj(): + break + + index += 1 + if index >= 10: + avserror("%%DEV_MONITOR-AVS: MAC Voltage adjust failed.") + exit(-1) + avsinfo("%%AVSCONTROL success") + exit(0) + +def run(interval): + while True: + try: + if waitForDocker(timeout = 0) == True: + time.sleep(10) # w10s + doAvsCtrol() + time.sleep(interval) + except Exception as e: + traceback.print_exc() + print(e) + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + +@main.command() +def start(): + '''start AVS control''' + avsinfo("%%AVSCONTROL start") + interval = 5 + run(interval) + +##device_i2c operation +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/device_i2c.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/device_i2c.py new file mode 100755 index 000000000000..35bca09c0206 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/device_i2c.py @@ -0,0 +1,336 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- + +import click +import os +import subprocess +import time +from ruijieconfig import GLOBALCONFIG, GLOBALINITPARAM, GLOBALINITCOMMAND, MAC_LED_RESET, STARTMODULE, i2ccheck_params + +from ruijieutil import rjpciwr + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def log_os_system(cmd): + u'''execute shell command''' + status, output = subprocess.getstatusoutput(cmd) + if status: + print(output) + return status, output + +def write_sysfs_value(reg_name, value): + u'''write sysfs file''' + mb_reg_file = "/sys/bus/i2c/devices/" + reg_name + if (not os.path.isfile(mb_reg_file)): + print(mb_reg_file, 'not found !') + return False + try: + with open(mb_reg_file, 'w') as fd: + fd.write(value) + except Exception as error: + return False + return True + +def check_driver(): + u'''whether there is driver start with rg''' + status, output = log_os_system("lsmod | grep rg | wc -l") + #System execution error + if status: + return False + if output.isdigit() and int(output) > 0: + return True + else: + return False + +def i2c_getPid(name): + ret = [] + for dirname in os.listdir('/proc'): + if dirname == 'curproc': + continue + try: + with open('/proc/{}/cmdline'.format(dirname), mode='r') as fd: + content = fd.read() + except Exception: + continue + if name in content: + ret.append(dirname) + return ret + +def startAvscontrol(): + cmd = "nohup avscontrol.py start >/dev/null 2>&1 &" + rets = i2c_getPid("avscontrol.py") + if len(rets) == 0: + os.system(cmd) + +def startFanctrol(): + if STARTMODULE['fancontrol'] == 1: + cmd = "nohup fancontrol.py start >/dev/null 2>&1 &" + rets = i2c_getPid("fancontrol.py") + if len(rets) == 0: + os.system(cmd) + +def starthal_fanctrl(): + if STARTMODULE.get('hal_fanctrl',0) == 1: + cmd = "nohup hal_fanctrl.py start >/dev/null 2>&1 &" + rets = i2c_getPid("hal_fanctrl.py") + if len(rets) == 0: + os.system(cmd) + +def starthal_ledctrl(): + if STARTMODULE.get('hal_ledctrl',0) == 1: + cmd = "nohup hal_ledctrl.py start >/dev/null 2>&1 &" + rets = i2c_getPid("hal_ledctrl.py") + if len(rets) == 0: + os.system(cmd) + +def startDevmonitor(): + if STARTMODULE.get('dev_monitor',0) == 1: + cmd = "nohup dev_monitor.py start >/dev/null 2>&1 &" + rets = i2c_getPid("dev_monitor.py") + if len(rets) == 0: + os.system(cmd) + +def startSlotmonitor(): + if STARTMODULE.get('slot_monitor',0) == 1: + cmd = "nohup slot_monitor.py start >/dev/null 2>&1 &" + rets = i2c_getPid("slot_monitor.py") + if len(rets) == 0: + os.system(cmd) + +def stopFanctrol(): + u'''disable fan timer service''' + if STARTMODULE['fancontrol'] == 1: + rets = i2c_getPid("fancontrol.py") # + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + +def stophal_ledctrl(): + if STARTMODULE.get('hal_ledctrl',0) == 1: + rets = i2c_getPid("hal_ledctrl.py") + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + + +def stopDevmonitor(): + u'''disable the fan timer service''' + if STARTMODULE.get('dev_monitor',0) == 1: + rets = i2c_getPid("dev_monitor.py") # + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + +def stopSlotmonitor(): + u'''disable slot timer service''' + if STARTMODULE.get('slot_monitor',0) == 1: + rets = i2c_getPid("slot_monitor.py") # + for ret in rets: + cmd = "kill "+ ret + os.system(cmd) + return True + +def removeDev(bus, loc): + cmd = "echo 0x%02x > /sys/bus/i2c/devices/i2c-%d/delete_device" % (loc, bus) + devpath = "/sys/bus/i2c/devices/%d-%04x"%(bus, loc) + if os.path.exists(devpath): + log_os_system(cmd) + +def addDev(name, bus, loc): + if name == "lm75": + time.sleep(0.1) + pdevpath = "/sys/bus/i2c/devices/i2c-%d/" % (bus) + for i in range(1, 100):#wait for mother-bus generation,maximum wait time is 10s + if os.path.exists(pdevpath) == True: + break + time.sleep(0.1) + if i % 10 == 0: + click.echo("%%DEVICE_I2C-INIT: %s not found, wait 0.1 second ! i %d " % (pdevpath,i)) + + cmd = "echo %s 0x%02x > /sys/bus/i2c/devices/i2c-%d/new_device" % (name, loc, bus) + devpath = "/sys/bus/i2c/devices/%d-%04x"%(bus, loc) + if os.path.exists(devpath) == False: + os.system(cmd) + +def removedevs(): + devs = GLOBALCONFIG["DEVS"] + for index in range(len(devs)-1, -1, -1 ): + removeDev(devs[index]["bus"] , devs[index]["loc"]) + +def adddevs(): + devs = GLOBALCONFIG["DEVS"] + for dev in range(0, devs.__len__()): + addDev(devs[dev]["name"], devs[dev]["bus"] , devs[dev]["loc"]) + +def checksignaldriver(name): + modisexistcmd = "lsmod | grep %s | wc -l" % name + status, output = log_os_system(modisexistcmd) + #System execution error + if status: + return False + if output.isdigit() and int(output) > 0: + return True + else: + return False + +def adddriver(name, delay): + cmd = "modprobe %s" % name + if delay != 0: + time.sleep(delay) + if checksignaldriver(name) != True: + log_os_system(cmd) + +def removedriver(name, delay): + realname = name.lstrip().split(" ")[0]; + cmd = "rmmod -f %s" % realname + if checksignaldriver(realname): + log_os_system(cmd) + +def removedrivers(): + u'''remove all drivers''' + if GLOBALCONFIG is None: + click.echo("%%DEVICE_I2C-INIT: load global config failed.") + return + drivers = GLOBALCONFIG.get("DRIVERLISTS", None) + if drivers is None: + click.echo("%%DEVICE_I2C-INIT: load driver list failed.") + return + for index in range(len(drivers)-1, -1, -1 ): + delay = 0 + name = "" + if type(drivers[index]) == dict and "delay" in drivers[index]: + name = drivers[index].get("name") + delay = drivers[index]["delay"] + else: + name = drivers[index] + removedriver(name, delay) + +def adddrivers(): + u'''add drivers''' + if GLOBALCONFIG is None: + click.echo("%%DEVICE_I2C-INIT: load global config failed.") + return + drivers = GLOBALCONFIG.get("DRIVERLISTS", None) + if drivers is None: + click.echo("%%DEVICE_I2C-INIT: load driver list failed.") + return + for index in range(0 ,len(drivers)): + delay = 0 + name = "" + if type(drivers[index]) == dict and "delay" in drivers[index]: + name = drivers[index].get("name") + delay = drivers[index]["delay"] + else: + name = drivers[index] + adddriver(name, delay) + +def otherinit(): + for index in GLOBALINITPARAM: + write_sysfs_value(index["loc"], index["value"]) + + for index in GLOBALINITCOMMAND: + log_os_system(index) + +def unload_driver(): + u'''remove devices and drivers''' + stopDevmonitor() # disable removable device driver monitors + stopFanctrol() # disable fan-control service + removedevs() # remove other devices + removedrivers() # remove drivers + +def reload_driver(): + u'''reload devices and drivers''' + removedevs() # remove other devices + removedrivers() # remove drivers + time.sleep(1) + adddrivers() + adddevs() + + +def i2c_check(bus,retrytime = 6): + try: + i2cpath = "/sys/bus/i2c/devices/" + bus + while retrytime and not os.path.exists(i2cpath): + click.echo("%%DEVICE_I2C-HA: i2c bus abnormal, last bus %s is not exist." % i2cpath) + reload_driver() + retrytime -= 1 + time.sleep(1) + except Exception as e: + click.echo("%%DEVICE_I2C-HA: %s" % str(e)) + return + +def MacLedSet(data): + '''write pci register''' + pcibus = MAC_LED_RESET.get("pcibus") + slot = MAC_LED_RESET.get("slot") + fn = MAC_LED_RESET.get("fn") + bar = MAC_LED_RESET.get("bar") + offset = MAC_LED_RESET.get("offset") + val = MAC_LED_RESET.get(data, None) + if val is None: + click.echo("%%DEVICE_I2C-INIT: MacLedSet wrong input") + return + rjpciwr(pcibus, slot, fn, bar, offset, val) + +def load_driver(): + u'''load devices and drivers''' + adddrivers() + adddevs() + if STARTMODULE.get("i2ccheck",0) == 1: #i2c HA + busend = i2ccheck_params.get("busend") + retrytime = i2ccheck_params.get("retrytime") + i2c_check(busend,retrytime) + startFanctrol() # enable fan + starthal_fanctrl() # enable fan control + starthal_ledctrl() # enable LED control + if STARTMODULE['avscontrol'] == 1: + startAvscontrol() # avs voltage-adjustment + startDevmonitor() # enable removable device driver monitors + startSlotmonitor() # slot insertion and removal initialization monitor + otherinit(); # other initialization, QSFP initialization + if STARTMODULE.get("macledreset",0) == 1: + MacLedSet("reset") + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + + +@main.command() +def start(): + '''load device ''' + if check_driver(): + unload_driver() + load_driver() + +@main.command() +def stop(): + '''stop device ''' + unload_driver() + +@main.command() +def restart(): + '''restart device''' + unload_driver() + load_driver() + +if __name__ == '__main__': + u'''device_i2c operation''' + main() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/fancontrol.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/fancontrol.py new file mode 100755 index 000000000000..87fb01e5f6ac --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/fancontrol.py @@ -0,0 +1,838 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +import click +import os +import time +import syslog +from ruijieconfig import MONITOR_CONST, FANCTROLDEBUG, MONITOR_FANS_LED, DEV_LEDS, MONITOR_PSU_STATUS, \ + MONITOR_SYS_PSU_LED, MONITOR_DEV_STATUS, MONITOR_FAN_STATUS, MONITOR_DEV_STATUS_DECODE, \ + MONITOR_SYS_FAN_LED, MONITOR_SYS_LED, fanloc + +from ruijieutil import rji2cget, getMacTemp_sysfs, write_sysfs_value, get_sysfs_value, strtoint, \ + rji2cset + +import traceback +import glob + + +CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) + +DEBUG_COMMON = 0x01 +DEBUG_LEDCONTROL = 0x02 +DEBUG_FANCONTROL = 0x04 + + +class AliasedGroup(click.Group): + def get_command(self, ctx, cmd_name): + rv = click.Group.get_command(self, ctx, cmd_name) + if rv is not None: + return rv + matches = [x for x in self.list_commands(ctx) + if x.startswith(cmd_name)] + if not matches: + return None + elif len(matches) == 1: + return click.Group.get_command(self, ctx, matches[0]) + ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + +def fanwarninglog(s): + #s = s.decode('utf-8').encode('gb2312') + syslog.openlog("FANCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_WARNING,s) + +def fancriticallog(s): + #s = s.decode('utf-8').encode('gb2312') + syslog.openlog("FANCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_CRIT,s) + +def fanerror(s): + #s = s.decode('utf-8').encode('gb2312') + syslog.openlog("FANCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_ERR,s) + +def fanwarningdebuglog(debuglevel,s): + #s = s.decode('utf-8').encode('gb2312') + if FANCTROLDEBUG & debuglevel: + syslog.openlog("FANCONTROL",syslog.LOG_PID) + syslog.syslog(syslog.LOG_DEBUG,s) + + +class FanControl(object): + critnum = 0 + def __init__(self): + self._fanOKNum = 0 + self._psuOKNum = 0 + self._intemp = -100.0 + self._mac_aver = -100.0 + self._mac_max = -100.0 + self._preIntemp = -1000 # previous temperature + self._outtemp = -100 + self._boardtemp = -100 + self._cputemp = -1000 + + @property + def fanOKNum(self): + return self._fanOKNum; + + @property + def psuOKNum(self): + return self._psuOKNum; + + @property + def cputemp(self): + return self._cputemp; + + @property + def intemp(self): + return self._intemp; + + @property + def outtemp(self): + return self._outtemp; + + @property + def boardtemp(self): + return self._boardtemp; + + @property + def mac_aver(self): + return self._mac_aver; + + @property + def preIntemp(self): + return self._preIntemp; + + @property + def mac_max(self): + return self._mac_max; + + def sortCallback(self, element): + return element['id'] + + def gettemp(self,ret): + u'''get inlet, outlet, hot-point and cpu temperature''' + temp_conf = MONITOR_DEV_STATUS.get('temperature', None) + + if temp_conf is None: + fanerror("gettemp: config error") + return False + for item_temp in temp_conf: + try: + retval = "" + rval = None + name = item_temp.get('name') + location = item_temp.get('location') + if name == "cpu": + L=[] + for dirpath, dirnames, filenames in os.walk(location): + for file in filenames : + if file.endswith("input"): + L.append(os.path.join(dirpath, file)) + L =sorted(L,reverse=False) + for i in range(len(L)): + nameloc = "%s/temp%d_label"%(location,i+1) + valloc = "%s/temp%d_input"%(location,i+1) + with open(nameloc, 'r') as fd1: + retval2 = fd1.read() + with open(valloc, 'r') as fd2: + retval3 = fd2.read() + ret_t ={} + ret_t["name"] = retval2.strip() + ret_t["value"] = float(retval3)/1000 + ret.append(ret_t) + fanwarningdebuglog(DEBUG_COMMON,"gettemp %s : %f" % (ret_t["name"],ret_t["value"])) + else: + locations = glob.glob(location) + with open(locations[0], 'r') as fd1: + retval = fd1.read() + rval = float(retval)/1000 + ret_t ={} + ret_t["name"] = name + ret_t["value"] = rval + ret.append(ret_t) + fanwarningdebuglog(DEBUG_COMMON,"gettemp %s : %f" % (ret_t["name"],ret_t["value"])) + except Exception as e: + fanerror("gettemp error:name:%s" % name) + fanerror(str(e)) + return True + + def checkslot(self,ret): + u'''get slot present status''' + slots_conf = MONITOR_DEV_STATUS.get('slots', None) + slotpresent = MONITOR_DEV_STATUS_DECODE.get('slotpresent',None) + + if slots_conf is None or slotpresent is None: + return False + for item_slot in slots_conf: + totalerr = 0 + try: + ret_t = {} + ret_t["id"] = item_slot.get('name') + ret_t["status"] = "" + gettype = item_slot.get('gettype') + presentbit = item_slot.get('presentbit') + if gettype == "io": + io_addr = item_slot.get('io_addr') + val = io_rd(io_addr) + if val is not None: + retval = val + else: + totalerr -= 1 + fanerror(" %s %s" % (item_slot.get('name'), "lpc read failed")) + else: + bus = item_slot.get('bus') + loc = item_slot.get('loc') + offset = item_slot.get('offset') + ind, val = rji2cget(bus, loc,offset) + if ind == True: + retval = val + else: + totalerr -= 1 + fanerror(" %s %s" % (item_slot.get('name'), "i2c read failed")) + if totalerr < 0 : + ret_t["status"] = "NOT OK" + ret.append(ret_t) + continue + val_t = (int(retval,16) & (1<< presentbit)) >> presentbit + fanwarningdebuglog(DEBUG_COMMON,"%s present:%s" % (item_slot.get('name'),slotpresent.get(val_t))) + if val_t != slotpresent.get('okval'): + ret_t["status"] = "ABSENT" + else: + ret_t["status"] = "PRESENT" + except Exception as e: + ret_t["status"] = "NOT OK" + totalerr -= 1 + fanerror("checkslot error") + fanerror(str(e)) + ret.append(ret_t) + return True + + def checkpsu(self,ret): + u'''get psu status present, output and warning''' + psus_conf = MONITOR_DEV_STATUS.get('psus', None) + psupresent = MONITOR_DEV_STATUS_DECODE.get('psupresent',None) + psuoutput = MONITOR_DEV_STATUS_DECODE.get('psuoutput',None) + psualert = MONITOR_DEV_STATUS_DECODE.get('psualert',None) + + if psus_conf is None or psupresent is None or psuoutput is None: + fanerror("checkpsu: config error") + return False + for item_psu in psus_conf: + totalerr = 0 + try: + ret_t = {} + ret_t["id"] = item_psu.get('name') + ret_t["status"] = "" + gettype = item_psu.get('gettype') + presentbit = item_psu.get('presentbit') + statusbit = item_psu.get('statusbit') + alertbit = item_psu.get('alertbit') + if gettype == "io": + io_addr = item_psu.get('io_addr') + val = io_rd(io_addr) + if val is not None: + retval = val + else: + totalerr -= 1 + fanerror(" %s %s" % (item_psu.get('name'), "lpc read failed")) + else: + bus = item_psu.get('bus') + loc = item_psu.get('loc') + offset = item_psu.get('offset') + ind, val = rji2cget(bus, loc,offset) + if ind == True: + retval = val + else: + totalerr -= 1 + fanerror(" %s %s" % (item_psu.get('name'), "i2c read failed")) + if totalerr < 0 : + ret_t["status"] = "NOT OK" + ret.append(ret_t) + continue + val_t = (int(retval,16) & (1<< presentbit)) >> presentbit + val_status = (int(retval,16) & (1<< statusbit)) >> statusbit + val_alert = (int(retval,16) & (1<< alertbit)) >> alertbit + fanwarningdebuglog(DEBUG_COMMON,"%s present:%s output:%s alert:%s" % (item_psu.get('name'),psupresent.get(val_t),psuoutput.get(val_status),psualert.get(val_alert))) + if val_t != psupresent.get('okval') or val_status != psuoutput.get('okval') or val_alert != psualert.get('okval'): + totalerr -=1 + except Exception as e: + totalerr -= 1 + fanerror("checkpsu error") + fanerror(str(e)) + if totalerr < 0: + ret_t["status"] = "NOT OK" + else: + ret_t["status"] = "OK" + ret.append(ret_t) + return True + + def checkfan(self,ret): + u'''get fan status present and roll''' + fans_conf = MONITOR_DEV_STATUS.get('fans', None) + fanpresent = MONITOR_DEV_STATUS_DECODE.get('fanpresent',None) + fanroll = MONITOR_DEV_STATUS_DECODE.get('fanroll',None) + + if fans_conf is None or fanpresent is None or fanroll is None: + fanerror("checkfan: config error") + return False + for item_fan in fans_conf: + totalerr = 0 + try: + ret_t = {} + ret_t["id"] = item_fan.get('name') + ret_t["status"] = "" + presentstatus = item_fan.get('presentstatus') + presentbus = presentstatus.get('bus') + presentloc = presentstatus.get('loc') + presentaddr = presentstatus.get('offset') + presentbit = presentstatus.get('bit') + ind, val = rji2cget(presentbus, presentloc,presentaddr) + if ind == True: + val_t = (int(val,16) & (1<< presentbit)) >> presentbit + fanwarningdebuglog(DEBUG_COMMON,"checkfan:%s present status:%s" % (item_fan.get('name'),fanpresent.get(val_t))) + if val_t != fanpresent.get('okval'): + ret_t["status"] = "ABSENT" + ret.append(ret_t) + continue + else: + fanerror("checkfan: %s get present status error." % item_fan.get('name')) + motors = item_fan.get("rollstatus") + for motor in motors: + statusbus = motor.get('bus', None) + statusloc = motor.get('loc', None) + statusaddr = motor.get('offset', None) + statusbit = motor.get('bit', None) + ind, val = rji2cget(statusbus, statusloc, statusaddr) + if ind == True: + val_t = (int(val,16) & (1<< statusbit)) >> statusbit + fanwarningdebuglog(DEBUG_COMMON,"checkfan:%s roll status:%s" % (motor.get('name'),fanroll.get(val_t))) + if val_t != fanroll.get('okval'): + totalerr -= 1 + else: + totalerr -= 1 + fanerror("checkfan: %s " % item_fan.get('name')) + fanerror("get %s status error." % motor["name"]) + except Exception as e: + totalerr -= 1 + fanerror("checkfan error") + fanerror(str(e)) + if totalerr < 0: + ret_t["status"] = "NOT OK" + else: + ret_t["status"] = "OK" + ret.append(ret_t) + return True + + def getCurrentSpeed(self): + try: + loc = fanloc[0].get("location","") + sped = get_sysfs_value(loc) + value = strtoint(sped) + return value + except Exception as e: + fanerror("%%policy: get current speedlevel error") + fanerror(str(e)) + return None + + # guarantee the speed is lowest when speed lower than lowest value after speed-adjustment + def checkCurrentSpeedSet(self): + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy: guarantee the lowest speed after speed-adjustment") + value = self.getCurrentSpeed() + if value is None or value == 0: + raise Exception("%%policy: getCurrentSpeed None") + elif value < MONITOR_CONST.MIN_SPEED: + self.fanSpeedSet(MONITOR_CONST.MIN_SPEED) + + + def fanSpeedSet(self, level): + if level >= MONITOR_CONST.MAX_SPEED: + level = MONITOR_CONST.MAX_SPEED + for item in fanloc: + try: + loc = item.get("location","") + write_sysfs_value(loc, "0x%02x"% level ) + except Exception as e: + fanerror(str(e)) + fanerror("%%policy: config fan runlevel error") + self.checkCurrentSpeedSet() # guaranteed minimum + + def fanSpeedSetMax(self): + try: + self.fanSpeedSet(MONITOR_CONST.MAX_SPEED) + except Exception as e: + fanerror("%%policy:fanSpeedSetMax failed") + fanerror(str(e)) + + def fanStatusCheck(self): # fan status check , max speed if fan error + if self.fanOKNum < MONITOR_CONST.FAN_TOTAL_NUM: + fanwarninglog("%%DEV_MONITOR-FAN: Normal fan number: %d" % (self.fanOKNum)) + self.fanSpeedSetMax() + return False + return True + + def setFanAttr(self,val): + u'''set status of each fan''' + for item in val: + fanid = item.get("id") + fanattr = fanid + "status" + fanstatus = item.get("status") + setattr(FanControl,fanattr,fanstatus) + fanwarningdebuglog(DEBUG_COMMON,"fanattr:%s,fanstatus:%s"% (fanattr,fanstatus)) + + def getFanPresentNum(self,curFanStatus): + fanoknum = 0; + for item in curFanStatus: + if item["status"] == "OK": + fanoknum += 1 + self._fanOKNum = fanoknum + fanwarningdebuglog(DEBUG_COMMON,"fanOKNum = %d"% self._fanOKNum) + + def getFanStatus(self): + try: + curFanStatus = [] + ret = self.checkfan(curFanStatus) + if ret == True: + self.setFanAttr(curFanStatus) + self.getFanPresentNum(curFanStatus) + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getFanStatus success" ) + return 0 + except AttributeError as e: + fanerror(str(e)) + except Exception as e: + fanerror(str(e)) + return -1 + + def getPsuOkNum(self,curPsuStatus): + psuoknum = 0; + for item in curPsuStatus: + if item.get("status") == "OK": + psuoknum += 1 + self._psuOKNum = psuoknum + fanwarningdebuglog(DEBUG_COMMON,"psuOKNum = %d"% self._psuOKNum) + + def getPsuStatus(self): + try: + curPsuStatus = [] + ret = self.checkpsu(curPsuStatus) + if ret == True: + self.getPsuOkNum(curPsuStatus) + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getPsuStatus success" ) + return 0 + except AttributeError as e: + fanerror(str(e)) + except Exception as e: + fanerror(str(e)) + return -1 + + def getMonitorTemp(self, temp): + for item in temp: + if item.get('name') == "lm75in": + self._intemp = item.get('value',self._intemp) + if item.get('name') == "lm75out": + self._outtemp = item.get('value',self._outtemp) + if item.get('name') == "lm75hot": + self._boardtemp = item.get('value',self._boardtemp) + if item.get('name') == "Physical id 0": + self._cputemp = item.get('value',self._cputemp) + fanwarningdebuglog(DEBUG_COMMON,"intemp:%f, outtemp:%f, boadrtemp:%f, cputemp:%f"% (self._intemp,self._outtemp,self._boardtemp,self._cputemp)) + + def getTempStatus(self): + try: + monitortemp =[] + ret = self.gettemp(monitortemp) + if ret == True: + self.getMonitorTemp(monitortemp) + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getTempStatus success" ) + return 0 + except AttributeError as e: + fanerror(str(e)) + except Exception as e: + fanerror(str(e)) + return -1 + + def getMacStatus_bcmcmd(self): + try: + if waitForDocker(timeout = 0) == True : + sta, ret = getMacTemp() + if sta == True: + self._mac_aver = float(ret.get("average",self._mac_aver)) + self._mac_max = float(ret.get("maximum",self._mac_max)) + fanwarningdebuglog(DEBUG_COMMON,"mac_aver:%f, mac_max:%f" % (self.mac_aver,self._mac_max)) + else: + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getMacStatus_bcmcmd failed" ) + else: + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getMacStatus_bcmcmd SDK not OK" ) + return 0 + except AttributeError as e: + fanerror(str(e)) + return -1 + + def getMacStatus_sysfs(self,conf): + try: + sta, ret = getMacTemp_sysfs(conf) + if sta == True: + self._mac_aver = float(ret) / 1000 + self._mac_max = float(ret) / 1000 + fanwarningdebuglog(DEBUG_COMMON,"mac_aver:%f, mac_max:%f" % (self.mac_aver,self._mac_max)) + elif conf.get("try_bcmcmd", 0) == 1: + fanwarningdebuglog(DEBUG_COMMON,"get sysfs mac temp failed.try to use bcmcmd") + self.getMacStatus_bcmcmd() + else: + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getMacStatus_sysfs failed" ) + return 0 + except AttributeError as e: + fanerror(str(e)) + return -1 + + def getMacStatus(self): + try: + mactempconf = MONITOR_DEV_STATUS.get('mac_temp', None) + if mactempconf is not None: + self.getMacStatus_sysfs(mactempconf) + else: + self.getMacStatus_bcmcmd() + return 0 + except AttributeError as e: + fanerror(str(e)) + return -1 + + def settSlotAttr(self,val): + u'''set each slot present status attribute''' + for item in val: + slotid = item.get("id") + slotattr = slotid + "status" + slotstatus = item.get("status") + setattr(FanControl,slotattr,slotstatus) + fanwarningdebuglog(DEBUG_COMMON,"slotattr:%s,slotstatus:%s"% (slotattr,slotstatus)) + + def getSlotStatus(self): + try: + curSlotStatus = [] + ret = self.checkslot(curSlotStatus) + if ret == True: + self.settSlotAttr(curSlotStatus) + fanwarningdebuglog(DEBUG_COMMON,"%%policy:getSlotStatus success" ) + except AttributeError as e: + fanerror(str(e)) + return 0 + + def fanctrol(self): #fan speed-adjustment + try: + if self.preIntemp <= -1000: + self.preIntemp = self.intemp + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:previous temperature[%.2f] , current temperature[%.2f]" % (self.preIntemp,self.intemp)) + if self.intemp < MONITOR_CONST.TEMP_MIN: + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:inlet %.2f minimum temperature: %.2f" %(self.intemp,MONITOR_CONST.TEMP_MIN)) + self.fanSpeedSet(MONITOR_CONST.DEFAULT_SPEED) # default level + elif self.intemp >= MONITOR_CONST.TEMP_MIN and self.intemp > self.preIntemp: + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:increase temperature") + self.policySpeed(self.intemp) + elif self.intemp >= MONITOR_CONST.TEMP_MIN and (self.preIntemp - self.intemp) > MONITOR_CONST.MONITOR_FALL_TEMP: + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:temperature reduce over %d degree" % MONITOR_CONST.MONITOR_FALL_TEMP) + self.policySpeed(self.intemp) + else: + speed = self.getCurrentSpeed()# set according to current speed, prevent fan watch-dog + if speed is not None: + self.fanSpeedSet(speed) + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:change nothing") + except Exception as e: + fanerror("%%policy: fancontrol error") + + # start speed-adjustment + def startFanCtrol(self): + self.checkCrit() + if self.critnum == 0 and self.checkWarning() == False and self.fanStatusCheck() ==True: + self.fanctrol() + self.checkDevError() + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy: speed after speed-adjustment is %0x" % (self.getCurrentSpeed())) + + def policySpeed(self, temp): # fan speed-adjustment algorithm + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:fan speed-adjustment algorithm") + sped_level = MONITOR_CONST.DEFAULT_SPEED + MONITOR_CONST.K * (temp - MONITOR_CONST.TEMP_MIN) + self.fanSpeedSet(sped_level) + self.preIntemp = self.intemp + + def getBoardMonitorMsg(self,ledcontrol = False): + ret_t = 0 + try: + ret_t += self.getFanStatus() # get fan status, get number of fan which status is OK + ret_t += self.getTempStatus() # get inlet, outlet, hot-point temperature, CPU temperature + ret_t += self.getMacStatus() # get MAC highest and average temperature + if ledcontrol == True: + ret_t += self.getSlotStatus() # get slot present status + ret_t += self.getPsuStatus() # get psu status + if ret_t == 0: + return True + except Exception as e: + fanerror(str(e)) + return False + + # device error algorithm Tmac-Tin≥50℃, or Tmac-Tin≤-50℃ + def checkDevError(self): + try: + if (self.mac_aver - self.intemp) >= MONITOR_CONST.MAC_UP_TEMP or (self.mac_aver - self.intemp) <= MONITOR_CONST.MAC_LOWER_TEMP: + fanwarningdebuglog(DEBUG_FANCONTROL,"%%DEV_MONITOR-TEMP: MAC temp get failed.") + value = self.getCurrentSpeed() + if MONITOR_CONST.MAC_ERROR_SPEED >= value: + self.fanSpeedSet(MONITOR_CONST.MAC_ERROR_SPEED) + else: + self.fanSpeedSetMax() + else: + pass + except Exception as e: + fanerror("%%policy:checkDevError failed") + fanerror(str(e)) + + def checkTempWarning(self): + u'''check whether temperature above the normal alarm value''' + try: + if self._mac_aver >= MONITOR_CONST.MAC_WARNING_THRESHOLD \ + or self._outtemp >= MONITOR_CONST.OUTTEMP_WARNING_THRESHOLD \ + or self._boardtemp >= MONITOR_CONST.BOARDTEMP_WARNING_THRESHOLD \ + or self._cputemp>=MONITOR_CONST.CPUTEMP_WARNING_THRESHOLD \ + or self._intemp >=MONITOR_CONST.INTEMP_WARNING_THRESHOLD: + fanwarningdebuglog(DEBUG_COMMON,"check whether temperature above the normal alarm value") + return True + except Exception as e: + fanerror("%%policy: checkTempWarning failed") + fanerror(str(e)) + return False + + def checkTempCrit(self): + u'''check whether temperature above the critical alarm value''' + try: + if self._mac_aver >= MONITOR_CONST.MAC_CRITICAL_THRESHOLD \ + or ( self._outtemp >= MONITOR_CONST.OUTTEMP_CRITICAL_THRESHOLD \ + and self._boardtemp >= MONITOR_CONST.BOARDTEMP_CRITICAL_THRESHOLD \ + and self._cputemp>= MONITOR_CONST.CPUTEMP_CRITICAL_THRESHOLD \ + and self._intemp >= MONITOR_CONST.INTEMP_CRITICAL_THRESHOLD): + fanwarningdebuglog(DEBUG_COMMON,"temperature above the critical alarm value") + return True + except Exception as e: + fanerror("%%policy: checkTempCrit failed") + fanerror(str(e)) + return False + + def checkFanStatus(self): + u'''check fan status''' + for item in MONITOR_FAN_STATUS: + maxoknum = item.get('maxOkNum') + minoknum = item.get('minOkNum') + status = item.get('status') + if self.fanOKNum >= minoknum and self.fanOKNum <= maxoknum : + fanwarningdebuglog(DEBUG_COMMON,"checkFanStatus:fanOKNum:%d,status:%s" % (self.fanOKNum,status)) + return status + fanwarningdebuglog(DEBUG_COMMON,"checkFanStatus Error:fanOKNum:%d" % (self.fanOKNum)) + return None + + def checkPsuStatus(self): + u'''check psu status''' + for item in MONITOR_PSU_STATUS: + maxoknum = item.get('maxOkNum') + minoknum = item.get('minOkNum') + status = item.get('status') + if self.psuOKNum >= minoknum and self.psuOKNum <= maxoknum : + fanwarningdebuglog(DEBUG_COMMON,"checkPsuStatus:psuOKNum:%d,status:%s" % (self.psuOKNum,status)) + return status + fanwarningdebuglog(DEBUG_COMMON,"checkPsuStatus Error:psuOKNum:%d" % (self.psuOKNum)) + return None + + def dealSysLedStatus(self): + u'''set up SYSLED according to temperature, fan and psu status''' + try: + fanstatus = self.checkFanStatus() + psustatus = self.checkPsuStatus() + if self.checkTempCrit() == True or fanstatus == "red" or psustatus == "red": + status = "red" + elif self.checkTempWarning() == True or fanstatus == "yellow" or psustatus == "yellow": + status = "yellow" + else: + status = "green" + self.setSysLed(status) + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:dealSysLedStatus success, status:%s," % status) + except Exception as e: + fanerror(str(e)) + + def dealSysFanLedStatus(self): + u'''light panel fan led according to status''' + try: + status = self.checkFanStatus() + if status is not None: + self.setSysFanLed(status) + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:dealSysFanLedStatus success, status:%s," % status) + except Exception as e: + fanerror("%%ledcontrol:dealSysLedStatus error") + fanerror(str(e)) + + def dealPsuLedStatus(self): + u'''set up PSU-LED according to psu status''' + try: + status = self.checkPsuStatus() + if status is not None: + self.setSysPsuLed(status) + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:dealPsuLedStatus success, status:%s," % status) + except Exception as e: + fanerror("%%ledcontrol:dealPsuLedStatus error") + fanerror(str(e)) + + def dealLocFanLedStatus(self): + u'''light fan led according to fan status''' + for item in MONITOR_FANS_LED: + try: + index = MONITOR_FANS_LED.index(item) + 1 + fanattr = "fan%dstatus" % index + val_t = getattr(FanControl,fanattr,None) + if val_t == "NOT OK": + rji2cset(item["bus"],item["devno"],item["addr"], item["red"]) + elif val_t == "OK": + rji2cset(item["bus"],item["devno"],item["addr"], item["green"]) + else: + pass + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:dealLocFanLed success.fanattr:%s, status:%s"% (fanattr,val_t)) + except Exception as e: + fanerror("%%ledcontrol:dealLocFanLedStatus error") + fanerror(str(e)) + + def dealSlotLedStatus(self): + u'''light slot status led according to slot present status''' + slotLedList = DEV_LEDS.get("SLOTLED",[]) + for item in slotLedList: + try: + index = slotLedList.index(item) + 1 + slotattr = "slot%dstatus" % index + val_t = getattr(FanControl,slotattr,None) + if val_t == "PRESENT": + rji2cset(item["bus"],item["devno"],item["addr"], item["green"]) + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:dealSlotLedStatus success.slotattr:%s, status:%s"% (slotattr,val_t)) + except Exception as e: + fanerror("%%ledcontrol:dealSlotLedStatus error") + fanerror(str(e)) + + def dealBmcLedstatus(self,val): + pass + + def dealLctLedstatus(self,val): + pass + + def setled(self, item, color): + if item.get('type', 'i2c') == 'sysfs': + rjsysset(item["cmdstr"], item.get(color)) + else : + mask = item.get('mask', 0xff) + ind, val = rji2cget(item["bus"], item["devno"], item["addr"]) + if ind == True: + setval = (int(val,16) & ~mask) | item.get(color) + rji2cset(item["bus"], item["devno"], item["addr"], setval) + else: + fanerror("led %s" % "i2c read failed") + + def setSysLed(self,color): + for item in MONITOR_SYS_LED: + self.setled(item, color) + + def setSysFanLed(self,color): + for item in MONITOR_SYS_FAN_LED: + self.setled(item, color) + + def setSysPsuLed(self,color): + for item in MONITOR_SYS_PSU_LED: + self.setled(item, color) + + def checkWarning(self): + try: + if self.checkTempWarning() == True: + fanwarningdebuglog(DEBUG_FANCONTROL,"anti-shake start") + time.sleep(MONITOR_CONST.SHAKE_TIME) + fanwarningdebuglog(DEBUG_FANCONTROL,"anti-shake end") + self.getBoardMonitorMsg()# re-read + if self.checkTempWarning() == True: + fanwarninglog("%%DEV_MONITOR-TEMP:The temperature of device is over warning value.") + self.fanSpeedSetMax() # fan full speed + return True + except Exception as e: + fanerror("%%policy: checkWarning failed") + fanerror(str(e)) + return False + + def checkCrit(self): + try: + if self.checkTempCrit() == True: + fanwarningdebuglog(DEBUG_FANCONTROL,"anti-shake start") + time.sleep(MONITOR_CONST.SHAKE_TIME) + fanwarningdebuglog(DEBUG_FANCONTROL,"anti-shake end") + self.getBoardMonitorMsg()# re-read + if self.checkTempCrit() == True: + fancriticallog("%%DEV_MONITOR-TEMP:The temperature of device is over critical value.") + self.fanSpeedSetMax() # fan full speed + self.critnum += 1 # anti-shake + if self.critnum >= MONITOR_CONST.CRITICAL_NUM: + os.system("reboot") + fanwarningdebuglog(DEBUG_FANCONTROL,"crit次数:%d" % self.critnum) + else: + self.critnum = 0 + else: + self.critnum = 0 + except Exception as e: + fanerror("%%policy: checkCrit failed") + fanerror(str(e)) + + +def callback(): + pass + +def doFanCtrol(fanCtrol): + ret = fanCtrol.getBoardMonitorMsg() + if ret==True: + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:startFanCtrol") + fanCtrol.startFanCtrol() + else: + fanCtrol.fanSpeedSetMax() + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:getBoardMonitorMsg error") + +def doLedCtrol(fanCtrol): + fanCtrol.getBoardMonitorMsg(ledcontrol = True) # get status + fanCtrol.dealSysLedStatus() # light system led + fanCtrol.dealSysFanLedStatus() # light panel fan led + fanCtrol.dealLocFanLedStatus() # light fan led + fanCtrol.dealPsuLedStatus() # light psu led + fanCtrol.dealSlotLedStatus() # light slot status led + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:doLedCtrol success") + +def run(interval, fanCtrol): + loop = 0 + # waitForDocker() + while True: + try: + if loop % MONITOR_CONST.MONITOR_INTERVAL ==0: # fan speed-adjustment + fanwarningdebuglog(DEBUG_FANCONTROL,"%%policy:fanCtrol") + doFanCtrol(fanCtrol) + else: + fanwarningdebuglog(DEBUG_LEDCONTROL,"%%ledcontrol:start ledctrol")# LED control + doLedCtrol(fanCtrol) + time.sleep(interval) + loop += interval + except Exception as e: + traceback.print_exc() + fanerror(str(e)) + +@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS) +def main(): + '''device operator''' + pass + +@main.command() +def start(): + '''start fan control''' + fanwarninglog("FANCTROL start") + fanCtrol = FanControl() + interval = MONITOR_CONST.MONITOR_INTERVAL /30 + run(interval, fanCtrol) + +@main.command() +def stop(): + '''stop fan control ''' + fanwarninglog("stop") + +##device_i2c operation +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijiecommon.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijiecommon.py new file mode 100755 index 000000000000..53eac5ce1ce4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijiecommon.py @@ -0,0 +1,717 @@ +# -*- coding: UTF-8 -*- +#------------------------------------------------------------------------------- +# Name: Ruijie python common module +# Purpose: called by other modules +# +# Author: rd +# +# Created: 02/07/2018 +# Copyright: (c) rd 2018 +#------------------------------------------------------------------------------- + +################################driver-load-adaption####################################################### +# need to export interface +################################################################################################### + +__all__ = ["fancontrol_loc", "fancontrol_config_loc", "GLOBALCONFIG", "MONITOR_CONST", + "RUIJIE_PART_NUMBER", "RUIJIE_LABEL_REVISION", "RUIJIE_ONIE_VERSION", "RUIJIE_MAC_SIZE", + "RUIJIE_MANUF_NAME", "RUIJIE_MANUF_COUNTRY", "RUIJIE_VENDOR_NAME", "RUIJIE_DIAG_VERSION", + "RUIJIE_SERVICE_TAG", "DEV_LEDS", "MEM_SLOTS", "LOCAL_LED_CONTROL", "FIRMWARE_TOOLS", + "STARTMODULE", "i2ccheck_params", "FANS_DEF", "factest_module", "MONITOR_TEMP_MIN", + "MONITOR_K", "MONITOR_MAC_IN", "MONITOR_DEFAULT_SPEED", "MONITOR_MAX_SPEED", + "MONITOR_MIN_SPEED", "MONITOR_MAC_ERROR_SPEED","MONITOR_FAN_TOTAL_NUM", + "MONITOR_MAC_UP_TEMP", "MONITOR_MAC_LOWER_TEMP","MONITOR_MAC_MAX_TEMP", + "MONITOR_FALL_TEMP","MONITOR_MAC_WARNING_THRESHOLD", "MONITOR_OUTTEMP_WARNING_THRESHOLD", + "MONITOR_BOARDTEMP_WARNING_THRESHOLD", "MONITOR_CPUTEMP_WARNING_THRESHOLD", + "MONITOR_INTEMP_WARNING_THRESHOLD", "MONITOR_MAC_CRITICAL_THRESHOLD", + "MONITOR_OUTTEMP_CRITICAL_THRESHOLD", "MONITOR_BOARDTEMP_CRITICAL_THRESHOLD", + "MONITOR_CPUTEMP_CRITICAL_THRESHOLD", "MONITOR_INTEMP_CRITICAL_THRESHOLD", + "MONITOR_CRITICAL_NUM", "MONITOR_SHAKE_TIME", "MONITOR_INTERVAL", + "MONITOR_MAC_SOURCE_SYSFS", "MONITOR_MAC_SOURCE_PATH", "MAC_AVS_PARAM", + "MAC_DEFAULT_PARAM", "MONITOR_SYS_LED", "MONITOR_SYS_FAN_LED", "MONITOR_FANS_LED", + "MONITOR_SYS_PSU_LED", "MONITOR_FAN_STATUS", "MONITOR_PSU_STATUS", "MONITOR_DEV_STATUS", + "MONITOR_DEV_STATUS_DECODE", "DEV_MONITOR_PARAM", "SLOT_MONITOR_PARAM", "fanloc", + "PCA9548START", "PCA9548BUSEND", "RUIJIE_CARDID", "RUIJIE_PRODUCTNAME", "FAN_PROTECT", + "rg_eeprom", "E2_LOC", "E2_PROTECT", "MAC_LED_RESET", "INIT_PARAM", "INIT_COMMAND", + "CPLDVERSIONS", "DRIVERLISTS", "DEVICE", "E2TYPE", "FRULISTS", "fanlevel_6510", + "fanlevel_6520", "fanlevel", "TEMPIDCHANGE", "FACTESTMODULE", "item1", + "test_sys_reload_item", "test_sys_item", "test_temp_item", "test_mem_item", + "test_hd_item", "test_rtc_item", "test_i2c_item", "test_cpld_item", + "test_portframe_item", "test_sysled_item", "test_fan_item", "test_power_item", + "test_usb_item", "test_prbs_item", "test_portbroadcast_item", "test_debug_level", + "test_log_level", "test_setmac", "test_setrtc", "log_level_critical", "log_level_debug", + "log_level_error", "log_level_info", "log_level_notset", "log_level_warning", + "test_e2_setmac_item", "test_bmc_setmac_item", "test_fan_setmac_item", "alltest", + "looptest", "diagtestall", "menuList", "TESTCASE", "PCIe_DEV_LIST", "PCIe_SPEED_ITEM"] + +fancontrol_loc = "/usr/local/bin" +fancontrol_config_loc = "/usr/local/bin" + +GLOBALCONFIG = "GLOBALCONFIG" +MONITOR_CONST = "MONITOR_CONST" + +RUIJIE_PART_NUMBER = "RJ000001" +RUIJIE_LABEL_REVISION = "R01" +RUIJIE_ONIE_VERSION = "2018.02" +RUIJIE_MAC_SIZE = 3 +RUIJIE_MANUF_NAME = "Ruijie" +RUIJIE_MANUF_COUNTRY = "CHN" +RUIJIE_VENDOR_NAME = "Ruijie" +RUIJIE_DIAG_VERSION = "0.1.0.15" +RUIJIE_SERVICE_TAG = "www.ruijie.com.cn" + +DEV_LEDS = {} +MEM_SLOTS = [] + +LOCAL_LED_CONTROL = { + "CLOSE":{}, + "OPEN":{} +} + +FIRMWARE_TOOLS = {} +#start-up module +STARTMODULE = { + "fancontrol":1, + "avscontrol":1 + } + +i2ccheck_params = {"busend":"i2c-66","retrytime":6} + +################################################################################################### +##### fan board ID reference +################################################################################################### +FANS_DEF = { + 0x8100:"M6500-FAN-F", + 0x8101:"M6510-FAN-F", + 0x8102:"M6520-FAN-F", + 0x8103:"M6510-FAN-R" +} + +factest_module = { + "sysinfo_showfanmsg":1, + "sysinfo_showPsumsg":1, + "sysinfo_showrestfanmsg":0, + "sysinfo_showrestpsumsg":0 +} + +#################fan adjustment parameters ############################## +MONITOR_TEMP_MIN = 38 # temperature before speed-adjustment +MONITOR_K = 11 # adjustment algorithm +MONITOR_MAC_IN = 35 # temperature difference between mac and chip(backup) +MONITOR_DEFAULT_SPEED = 0x60 # default speed +MONITOR_MAX_SPEED = 0xFF # maximum speed +MONITOR_MIN_SPEED = 0x33 # minimum speed +MONITOR_MAC_ERROR_SPEED = 0XBB # MAC abnormal speed +MONITOR_FAN_TOTAL_NUM = 4 # 3+1 redundancy design, report to syslog if there is a error +MONITOR_MAC_UP_TEMP = 50 # MAC compared with inlet up +MONITOR_MAC_LOWER_TEMP = -50 # MAC compared with outlet down +MONITOR_MAC_MAX_TEMP = 100 # + +MONITOR_FALL_TEMP = 4 # adjustment reduced temperature +MONITOR_MAC_WARNING_THRESHOLD = 100 #100 +MONITOR_OUTTEMP_WARNING_THRESHOLD = 85 +MONITOR_BOARDTEMP_WARNING_THRESHOLD = 85 +MONITOR_CPUTEMP_WARNING_THRESHOLD = 85 +MONITOR_INTEMP_WARNING_THRESHOLD = 70 #70 + +MONITOR_MAC_CRITICAL_THRESHOLD = 105 #105 +MONITOR_OUTTEMP_CRITICAL_THRESHOLD = 90 #90 +MONITOR_BOARDTEMP_CRITICAL_THRESHOLD = 90 #90 +MONITOR_CPUTEMP_CRITICAL_THRESHOLD = 100 #100 +MONITOR_INTEMP_CRITICAL_THRESHOLD = 80 # 80 +MONITOR_CRITICAL_NUM = 3 #retry times +MONITOR_SHAKE_TIME = 20 #anti-shake times +MONITOR_INTERVAL = 60 + +MONITOR_MAC_SOURCE_SYSFS = 0 #1 get mac temperature from sysfs ,0 get mac temperature from bcmcmd +MONITOR_MAC_SOURCE_PATH = None #sysfs path + +################################################################### + + +#####################MAC调压parameters (B6510)#################################### +MAC_AVS_PARAM ={ + 0x72:0x0384 , + 0x73:0x037e , + 0x74:0x0378 , + 0x75:0x0372 , + 0x76:0x036b , + 0x77:0x0365 , + 0x78:0x035f , + 0x79:0x0359 , + 0x7a:0x0352 , + 0x7b:0x034c , + 0x7c:0x0346 , + 0x7d:0x0340 , + 0x7e:0x0339 , + 0x7f:0x0333 , + 0x80:0x032d , + 0x81:0x0327 , + 0x82:0x0320 , + 0x83:0x031a , + 0x84:0x0314 , + 0x85:0x030e , + 0x86:0x0307 , + 0x87:0x0301 , + 0x88:0x02fb , + 0x89:0x02f5 , + 0x8A:0x02ee +} + +# default 6520 configuration +MAC_DEFAULT_PARAM = { + "type": 1, # type 1 represents default if out of range / 0 represents no voltage-adjustment if out of range + "default":0x74, # should be used with type + "loopaddr":0x00, # AVS loop address + "loop":0x00, # AVS loop value + "open":0x00, # diasble write-protection value + "close":0x40, # enable write-protection value + "bus":2, # AVSI2C bus address + "devno":0x60, # AVS address + "addr":0x21, # AVS voltage-adjustment address + "protectaddr":0x10, # AVS write-protection address + "sdkreg":"DMU_PCU_OTP_CONFIG_8", # SDK register name + "sdktype": 1, # type 0 represents no shift operation / 1 represents shift operation + "macregloc":24 , # shift operation + "mask": 0xff # mask after shift +} + +MONITOR_SYS_LED = [ + {"bus":2,"devno":0x33, "addr":0xb2, "yellow":0x06, "red":0x02,"green":0x04}, + {"bus":2,"devno":0x32, "addr":0x72, "yellow":0x06, "red":0x02,"green":0x04}] + +MONITOR_SYS_FAN_LED =[ + {"bus":2,"devno":0x33, "addr":0xb4, "yellow":0x06, "red":0x02,"green":0x04}, + ] + +MONITOR_FANS_LED = [ + {"bus":2,"devno":0x32, "addr":0x23, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x24, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x25, "green":0x09, "red":0x0a}, + {"bus":2,"devno":0x32, "addr":0x26, "green":0x09, "red":0x0a}] + + +MONITOR_SYS_PSU_LED =[ + {"bus":2,"devno":0x33, "addr":0xb3, "yellow":0x06, "red":0x02,"green":0x04}, + ] + +MONITOR_FAN_STATUS = [ + {'status':'green' , 'minOkNum':4,'maxOkNum':4}, + {'status':'yellow', 'minOkNum':3,'maxOkNum':3}, + {'status':'red' , 'minOkNum':0,'maxOkNum':2}, + ] + +MONITOR_PSU_STATUS = [ + {'status':'green' , 'minOkNum':2,'maxOkNum':2}, + {'status':'yellow', 'minOkNum':1,'maxOkNum':1}, + {'status':'red' , 'minOkNum':0,'maxOkNum':0}, + ] + +MONITOR_DEV_STATUS = {} +MONITOR_DEV_STATUS_DECODE = {} +DEV_MONITOR_PARAM = {} +SLOT_MONITOR_PARAM = {} + + +fanloc = {"name":"fanset","location":"0-0032/fan_speed_set"} +#####################MAC-Voltage-Adjustment-Parameters#################################### + + +####================================Adaption-Area================================ +#### RUIJIE_COMMON common configuration head +#### “platform” specific configuration head +#### +PCA9548START = 11 +PCA9548BUSEND = 74 + +RUIJIE_CARDID = 0x00004040 +RUIJIE_PRODUCTNAME = "ruijie_b6510" + +FAN_PROTECT = {"bus":0, "devno":0x32, "addr":0x19, "open":0x00, "close":0x0f} +rg_eeprom = "2-0057/eeprom" +E2_LOC = {"bus":2, "devno":0x57} +E2_PROTECT ={"bus":2, "devno":0x33, "addr":0xb0, "open":0, "close":1} +MAC_LED_RESET = {"pcibus":8, "slot":0, "fn":0, "bar":0, "offset":64, "reset":0x98} + +INIT_PARAM = [ + {"loc":"1-0034/sfp_enable","value": "01"}, + {"loc":"2-0035/sfp_enable2","value":"ff"}, + {"loc":"2-0033/mac_led", "value":"ff"}, + {"loc":"1-0034/sfp_txdis1","value":"00"}, + {"loc":"1-0034/sfp_txdis2","value":"00"}, + {"loc":"1-0034/sfp_txdis3","value":"00"}, + {"loc":"1-0036/sfp_txdis4","value":"00"}, + {"loc":"1-0036/sfp_txdis5","value":"00"}, + {"loc":"1-0036/sfp_txdis6","value":"00"}, + {"loc":fanloc["location"], "value":"80"} +] + +INIT_COMMAND = [ +] + +CPLDVERSIONS = [ + {"loc":"2-0033/cpld_version","des":"MAC Board 上CPLDA"}, + {"loc":"2-0035/cpld_version","des":"MAC Board 上CPLDB"}, + {"loc":"2-0037/cpld_version","des":"CPU Board 上cpld"} +] + +## Driver List +## +DRIVERLISTS = [ + "i2c_dev", + "i2c_algo_bit", + "i2c_gpio", + "i2c_mux", + "i2c_mux_pca9641", + "i2c_mux_pca954x", # force_deselect_on_exit=1 + "eeprom", + "at24", + "ruijie_platform", + "rg_cpld", + "rg_fan", + "rg_psu", + "csu550", + "rg_gpio_xeon", + #IPMIdriver + "ipmi_msghandler", + "ipmi_devintf", + "ipmi_si", +] + +DEVICE = [ + {"name":"pca9641","bus":0 ,"loc":0x10 }, + {"name":"pca9548","bus":2 ,"loc":0x70 }, + {"name":"lm75","bus": 2, "loc":0x48 }, + {"name":"lm75","bus": 2, "loc":0x49 }, + {"name":"lm75","bus": 2, "loc":0x4a }, + {"name":"24c02","bus":2 , "loc":0x57 }, + {"name":"rg_cpld","bus":2 ,"loc":0x33 }, + {"name":"rg_cpld","bus":2 ,"loc":0x35 }, + {"name":"rg_cpld","bus":2 ,"loc":0x37 }, + {"name":"pca9548","bus":1,"loc":0x70 }, + {"name":"pca9548","bus":1,"loc":0x71 }, + {"name":"pca9548","bus":1,"loc":0x72 }, + {"name":"pca9548","bus":1,"loc":0x73 }, + {"name":"pca9548","bus":1,"loc":0x74 }, + {"name":"pca9548","bus":1,"loc":0x75 }, + {"name":"pca9548","bus":1,"loc":0x76 }, + {"name":"pca9548","bus":1,"loc":0x77 }, + {"name":"rg_fan","bus":3,"loc":0x53 }, + {"name":"rg_fan","bus":4,"loc":0x53 }, + {"name":"rg_fan","bus":5,"loc":0x53 }, + #{"name":"rg_fan","bus":6,"loc":0x53 }, #specific fan + {"name":"rg_psu","bus":7 ,"loc":0x50 }, + {"name":"csu550","bus":7 ,"loc":0x58 }, + {"name":"rg_psu","bus":8 ,"loc":0x53 }, + {"name":"csu550","bus":8 ,"loc":0x5b }, +] + +#####################FRU-Info-Adaption################################# +E2TYPE = {"1": "tlveeprom", + "2": "x86cpueeprom", + "3": "bmceeprom", + "4": "cpueeprom", + "5": "maceeprom", + "6": "sloteeprom", + "7": "fanconnecteeprom", + "8": "M1HFANI-F", + "9": "M1HFANI-R", + "A": "M2HFANI-F", + "B": "M2HFANI-R", + "C": "psu"} +FRULISTS = [] +################################Manufacturing-Test-Adaption-Area####################################################### +# need to export interface +fanlevel_6510 = { + "level":[51,150,255], + "low_speed":[500,7500,17000], + "high_speed":[11000,22500,28500] +} + +fanlevel_6520 = { + "level":[75,150,255], + "low_speed":[750,4250,6750], + "high_speed":[4500,7500,10000] +} + +fanlevel = fanlevel_6520 + +TEMPIDCHANGE = { + "lm75in":"inlet", + "lm75out":"outlet", + "lm75hot":"hot-point", + "inlet":"lm75in", + "outlet":"lm75out", + "hot-point":"lm75hot", +} + +# Manufacturing-Test module +FACTESTMODULE = { } + +##################################Manufacturing-Test-Menu +item1 = {"name":"Single Test", "deal" :"test_signal", "childid":1} +test_sys_reload_item = {"name":"reset-system", "deal" :"test_sys_reload"} + +test_sys_item = { "name":"Product information test", "deal" :"test_sysinfo"} +test_temp_item = { "name":"temperature test", "deal" :"test_tempinfo"} +test_mem_item = { "name":"Memory test", "deal" :"test_cpumemoryinfo"} +test_hd_item = { "name":"Hard disk test", "deal" :"test_hard"} +test_rtc_item = { "name":"RTC test ", "deal" :"test_rtc"} +test_i2c_item = { "name":"I2c test ", "deal" :"test_i2c"} +test_cpld_item = { "name":"CPLD test", "deal" :"test_cpld"} +test_portframe_item = { "name":"Port transmit-receive frame test", "deal" :"test_portframe"} +test_sysled_item = { "name":"System led test", "deal" :"test_led"} +test_fan_item = { "name":"Fan status test", "deal" :"test_fan"} +test_power_item = { "name":"PSU status test", "deal" :"test_power"} +test_usb_item = { "name":"USB test", "deal" :"test_usb"} +test_prbs_item = { "name":"PRBS test", "deal" :"test_prbs"} +test_portbroadcast_item = { "name":"Port broadcast", "deal" :"test_portbroadcast"} + +test_debug_level = {"name":"Change debug level", "deal" :"test_setdebug"} +test_log_level = {"name":"Log output level", "deal" :"test_loginfolevel"} +test_setmac = {"name":"setmac", "deal" :"test_setmac"} +test_setrtc = {"name":"Set RTC", "deal" :"test_set_rtc"} + +log_level_critical = {"name":"CRITICAL", "deal" :"test_log_critical"} +log_level_debug = {"name":"DEBUG", "deal" :"test_log_debug"} +log_level_error = {"name":"ERROR", "deal" :"test_log_error"} +log_level_info = {"name":"INFO", "deal" :"test_log_info"} +log_level_notset = {"name":"NOTSET", "deal" :"test_log_notset"} +log_level_warning = {"name":"WARNING", "deal" :"test_log_warning"} + + +test_e2_setmac_item = {"name":"E2SETMAC", "deal" :"test_e2_setmac"} +test_bmc_setmac_item = {"name":"BMCSETMAC", "deal" :"test_bmc_setmac"} +test_fan_setmac_item = {"name":"fan SETMAC", "deal" :"test_fan_setmac"} + +alltest = [ + test_sys_item, + test_temp_item, + test_mem_item, + test_hd_item, + test_rtc_item, + test_i2c_item, + test_cpld_item, + test_portframe_item, + test_sysled_item, + test_fan_item, + test_power_item, + test_usb_item, + test_prbs_item, + test_portbroadcast_item + ] + +looptest = [ + test_sys_item, + test_temp_item, + test_mem_item, + test_hd_item, + test_rtc_item, + test_i2c_item, + test_cpld_item, + test_portframe_item, + test_fan_item, + test_power_item, + test_usb_item, + test_prbs_item, + test_portbroadcast_item , +] + +diagtestall = [ +] + +menuList =[ + { + "menuid":0, "value":[ + {"name":"Single test", "deal" :"test_signal", "childid":1}, + {"name":"All test", "deal" :"test_all"}, + {"name":"Loop test", "deal" :"test_loop"}, + #{"name":"Check loop-test result", "deal" :"test_loop_read"}, + #{"name":"Delete loop-test result", "deal" :"test_loop_delete"}, +# {"name":"Load configuration", "deal" :"test_config"}, + test_sys_reload_item, + {"name":"System Configuration", "deal" :"test_sysconfig","childid":2}, + ] + }, + { + "menuid":1, "parentid":0, "value":[ + test_sys_item , + test_temp_item , + test_mem_item , + test_hd_item , + test_rtc_item , + test_i2c_item , + test_cpld_item , + test_portframe_item , + test_sysled_item , + test_fan_item , + test_power_item , + test_usb_item , + test_prbs_item , + test_portbroadcast_item , + ]}, + { + "menuid":2, "parentid":0, "value":[ + test_debug_level, + test_log_level , + test_setmac , + test_setrtc , + ]}, + { + "menuid":3, "parentid":2, "value":[ + log_level_critical , + log_level_debug , + log_level_error , + log_level_info , + log_level_notset , + log_level_warning , + ]}, + { + "menuid":4, "parentid":2, "value":[ + test_e2_setmac_item , + test_bmc_setmac_item, + test_fan_setmac_item, + ]}, +] + + +TESTCASE={ + "CPLD":[ + {"name":"CONNECT BOARD CPLD-A" ,"cases":[ + {"name":"cpld32", "cmd":"grtd_test.py cpld_check 0 0x32 0xAA"}, + {"name":"cpld37", "cmd":"grtd_test.py cpld_check 2 0x37 0xAC"}, + ] + }, + {"name":"MAC BOARD CPLD-A" ,"cases":[ + {"name":"cpld33", "cmd":"grtd_test.py cpld_check 2 0x33 0xAB"}, + {"name":"cpld34", "cmd":"grtd_test.py cpld_check 1 0x34 0xAA"}, + ] + }, + {"name":"MAC BOARD CPLD-B" ,"cases":[ + {"name":"cpld36", "cmd":"grtd_test.py cpld_check 1 0x36 0xAA"}, + {"name":"cpld35", "cmd":"grtd_test.py cpld_check 2 0x35 0xAB"}, + ] + }, + ], + "TEMPERATURE":[ + { + "name":"-->temperature test" , "cases":[ + {"name":"inlet","cmd":"grtd_test.py temp 2-0048/hwmon/hwmon1/temp1_input"}, + {"name":"outlet","cmd":"grtd_test.py temp 2-0049/hwmon/hwmon2/temp1_input"}, + {"name":"hot-point","cmd":"grtd_test.py temp 2-004a/hwmon/hwmon3/temp1_input"}, + ] + } + ], + "MEMTORY":{ + "cases":[ + {"name":"->memory test 1M","cmd":"memtester 1M 1"}, + {"name":"->memory test 2M","cmd":"memtester 2M 1"}, + {"name":"->memory test 8M","cmd":"memtester 8M 1"}, +# {"name":"->memory test 16M","cmd":"memtester 16M 1"}, +# {"name":"->memory test 256M","cmd":"memtester 256M 1"}, + ] + }, + "SMARTCTLCMDS":{ + "cases":[ + {"name":"->Check Hard Disk Info", "cmd":"smartctl -i /dev/sda"}, + {"name":"->Check Hard Disk Monitor Status", "cmd":"smartctl -H /dev/sda"}, + ] + }, + "LED":[ + {"name":"Light Port Led test","cases":[ + {"name":"-> Red Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + {"name":"-> Red Led On", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff"}, + {"name":"-> Recovery Red Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_red,1-0034/sfp_led2_red,1-0034/sfp_led3_red,1-0034/sfp_led8_red,1-0036/sfp_led4_red,1-0036/sfp_led5_red,1-0036/sfp_led6_red,1-0036/sfp_led7_red 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + + {"name":"-> Yellow Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + {"name":"-> Yellow Led On", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff"}, + {"name":"-> Recovery Yellow Led Off", "cmd":"grtd_test.py led loc 1-0034/sfp_led1_yellow,1-0034/sfp_led2_yellow,1-0034/sfp_led3_yellow,1-0034/sfp_led8_yellow,1-0036/sfp_led4_yellow,1-0036/sfp_led5_yellow,1-0036/sfp_led6_yellow,1-0036/sfp_led7_yellow 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"}, + ] + }, + {"name":"fan 1 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan0_led 0x09"}, + ] + }, + {"name":"fan 2 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan1_led 0x09"}, + ] + }, + {"name":"fan 3 Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0b"}, + {"name":"-> Red Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0a"}, + {"name":"-> Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x09"}, + {"name":"-> Yellow Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x08"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0e"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0d"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x0c"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 0-0032/fan2_led 0x09"}, + ] + }, + {"name":"Front panel CPU Led", "cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x00"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x02"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x03"}, + {"name":"-> Green Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x11"}, + {"name":"-> Green Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x21"}, + {"name":"-> Green Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x41"}, + {"name":"-> Green Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x81"}, + {"name":"-> Red Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x12"}, + {"name":"-> Red Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x22"}, + {"name":"-> Red Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x42"}, + {"name":"-> Red Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x82"}, + {"name":"-> Yellow Led 1/4sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x13"}, + {"name":"-> Yellow Led 1/2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x23"}, + {"name":"-> Yellow Led 1sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x43"}, + {"name":"-> Yellow Led 2sFlashing ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x83"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_cpu 0x01"}, + ] + }, + {"name":"Front panel BMC Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_bmc 0x04"}, + ] + }, + {"name":"Front panel location Led" , "cases":[ + {"name":"-> LedOff","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xff"}, + {"name":"-> LedOn","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xfe"}, + {"name":"->Recovery LedOff","cmd":"grtd_test.py led loc 2-0035/broad_front_lct 0xff"}, + ] + }, + + {"name":"Front panel pwr Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_pwr 0x04"}, + ] + }, + {"name":"Front panel fan Led" ,"cases":[ + {"name":"-> LedOff", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x00"}, + {"name":"-> Red Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x01"}, + {"name":"-> Red Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x02"}, + {"name":"-> Green Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x03"}, + {"name":"-> Green Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x04"}, + {"name":"-> Yellow Led Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x05"}, + {"name":"-> Yellow Led not Flashing", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x06"}, + {"name":"-> Recovery Green Led ", "cmd":"grtd_test.py led loc 2-0035/broad_front_fan 0x04"}, + ] + }, + + ], + "I2C":[ + ####type 1 represents value obtained compated with value + ####type 2 represents return True or False + {"name":"I2C device test" ,"cases":[ + {"name":" PCA9641 test", "cmd":"grtd_test.py dev_rd 0 10 0","deal_type":2}, + {"name":" cpld32 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld33 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld34 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld35 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld36 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" cpld37 test", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" inlet LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" outlet LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" hot-point LM75", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" EEPROM", "cmd":"grtd_test.py dev_rd 0 32 0","deal_type":2}, + {"name":" Port 1", "cmd":"grtd_test.py dev_rd 11 0050 0","deal_type":2}, + {"name":" Port 2", "cmd":"grtd_test.py dev_rd 12 0050 0","deal_type":2}, + {"name":" Port 3", "cmd":"grtd_test.py dev_rd 13 0050 0","deal_type":2}, + {"name":" Port 4", "cmd":"grtd_test.py dev_rd 14 0050 0","deal_type":2}, + {"name":" Port 5", "cmd":"grtd_test.py dev_rd 15 0050 0","deal_type":2}, + {"name":" Port 6", "cmd":"grtd_test.py dev_rd 16 0050 0","deal_type":2}, + {"name":" Port 7", "cmd":"grtd_test.py dev_rd 17 0050 0","deal_type":2}, + {"name":" Port 8", "cmd":"grtd_test.py dev_rd 18 0050 0","deal_type":2}, + {"name":" Port 9", "cmd":"grtd_test.py dev_rd 19 0050 0","deal_type":2}, + {"name":" Port 10", "cmd":"grtd_test.py dev_rd 20 0050 0","deal_type":2}, + {"name":" Port 11", "cmd":"grtd_test.py dev_rd 21 0050 0","deal_type":2}, + {"name":" Port 12", "cmd":"grtd_test.py dev_rd 22 0050 0","deal_type":2}, + {"name":" Port 13", "cmd":"grtd_test.py dev_rd 23 0050 0","deal_type":2}, + {"name":" Port 14", "cmd":"grtd_test.py dev_rd 24 0050 0","deal_type":2}, + {"name":" Port 15", "cmd":"grtd_test.py dev_rd 25 0050 0","deal_type":2}, + {"name":" Port 16", "cmd":"grtd_test.py dev_rd 26 0050 0","deal_type":2}, + {"name":" Port 17", "cmd":"grtd_test.py dev_rd 27 0050 0","deal_type":2}, + {"name":" Port 18", "cmd":"grtd_test.py dev_rd 28 0050 0","deal_type":2}, + {"name":" Port 19", "cmd":"grtd_test.py dev_rd 29 0050 0","deal_type":2}, + {"name":" Port 20", "cmd":"grtd_test.py dev_rd 30 0050 0","deal_type":2}, + {"name":" Port 21", "cmd":"grtd_test.py dev_rd 31 0050 0","deal_type":2}, + {"name":" Port 22", "cmd":"grtd_test.py dev_rd 32 0050 0","deal_type":2}, + {"name":" Port 23", "cmd":"grtd_test.py dev_rd 33 0050 0","deal_type":2}, + {"name":" Port 24", "cmd":"grtd_test.py dev_rd 34 0050 0","deal_type":2}, + {"name":" Port 25", "cmd":"grtd_test.py dev_rd 35 0050 0","deal_type":2}, + {"name":" Port 26", "cmd":"grtd_test.py dev_rd 36 0050 0","deal_type":2}, + {"name":" Port 27", "cmd":"grtd_test.py dev_rd 37 0050 0","deal_type":2}, + {"name":" Port 28", "cmd":"grtd_test.py dev_rd 38 0050 0","deal_type":2}, + {"name":" Port 29", "cmd":"grtd_test.py dev_rd 39 0050 0","deal_type":2}, + {"name":" Port 30", "cmd":"grtd_test.py dev_rd 40 0050 0","deal_type":2}, + {"name":" Port 31", "cmd":"grtd_test.py dev_rd 41 0050 0","deal_type":2}, + {"name":" Port 32", "cmd":"grtd_test.py dev_rd 42 0050 0","deal_type":2}, + {"name":" Port 33", "cmd":"grtd_test.py dev_rd 43 0050 0","deal_type":2}, + {"name":" Port 34", "cmd":"grtd_test.py dev_rd 44 0050 0","deal_type":2}, + {"name":" Port 35", "cmd":"grtd_test.py dev_rd 45 0050 0","deal_type":2}, + {"name":" Port 36", "cmd":"grtd_test.py dev_rd 46 0050 0","deal_type":2}, + {"name":" Port 37", "cmd":"grtd_test.py dev_rd 47 0050 0","deal_type":2}, + {"name":" Port 38", "cmd":"grtd_test.py dev_rd 48 0050 0","deal_type":2}, + {"name":" Port 39", "cmd":"grtd_test.py dev_rd 49 0050 0","deal_type":2}, + {"name":" Port 40", "cmd":"grtd_test.py dev_rd 50 0050 0","deal_type":2}, + {"name":" Port 41", "cmd":"grtd_test.py dev_rd 51 0050 0","deal_type":2}, + {"name":" Port 42", "cmd":"grtd_test.py dev_rd 52 0050 0","deal_type":2}, + {"name":" Port 43", "cmd":"grtd_test.py dev_rd 53 0050 0","deal_type":2}, + {"name":" Port 44", "cmd":"grtd_test.py dev_rd 54 0050 0","deal_type":2}, + {"name":" Port 45", "cmd":"grtd_test.py dev_rd 55 0050 0","deal_type":2}, + {"name":" Port 46", "cmd":"grtd_test.py dev_rd 56 0050 0","deal_type":2}, + {"name":" Port 47", "cmd":"grtd_test.py dev_rd 57 0050 0","deal_type":2}, + {"name":" Port 48", "cmd":"grtd_test.py dev_rd 58 0050 0","deal_type":2}, + {"name":" Port 49", "cmd":"grtd_test.py dev_rd 59 0050 0","deal_type":2}, + {"name":" Port 50", "cmd":"grtd_test.py dev_rd 60 0050 0","deal_type":2}, + {"name":" Port 51", "cmd":"grtd_test.py dev_rd 61 0050 0","deal_type":2}, + {"name":" Port 52", "cmd":"grtd_test.py dev_rd 62 0050 0","deal_type":2}, + {"name":" Port 53", "cmd":"grtd_test.py dev_rd 63 0050 0","deal_type":2}, + {"name":" Port 54", "cmd":"grtd_test.py dev_rd 64 0050 0","deal_type":2}, + {"name":" Port 55", "cmd":"grtd_test.py dev_rd 65 0050 0","deal_type":2}, + {"name":" Port 56", "cmd":"grtd_test.py dev_rd 66 0050 0","deal_type":2}, + {"name":" Port 57", "cmd":"grtd_test.py dev_rd 67 0050 0","deal_type":2}, + {"name":" Port 58", "cmd":"grtd_test.py dev_rd 68 0050 0","deal_type":2}, + {"name":" Port 59", "cmd":"grtd_test.py dev_rd 69 0050 0","deal_type":2}, + {"name":" Port 60", "cmd":"grtd_test.py dev_rd 70 0050 0","deal_type":2}, + {"name":" Port 61", "cmd":"grtd_test.py dev_rd 71 0050 0","deal_type":2}, + {"name":" Port 62", "cmd":"grtd_test.py dev_rd 72 0050 0","deal_type":2}, + {"name":" Port 63", "cmd":"grtd_test.py dev_rd 73 0050 0","deal_type":2}, + {"name":" Port 64", "cmd":"grtd_test.py dev_rd 74 0050 0","deal_type":2}, + ] + }, + ], +} + +PCIe_DEV_LIST = [] +PCIe_SPEED_ITEM = [] + +################################Manufacturing-Test-Adaption-Area####################################################### + + + + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieconfig.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieconfig.py new file mode 100755 index 000000000000..297e5af6db21 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieconfig.py @@ -0,0 +1,186 @@ +#!/usr/bin/python3 +# -*- coding: UTF-8 -*- +#------------------------------------------------------------------------------- +# Name: ruijieconfig.py +# Purpose: block the difference between various product/onie version for other module +# +# Author: rd +# +# Created: 02/07/2018 +# Copyright: (c) rd 2018 +#------------------------------------------------------------------------------- +import sys +import os +from rjutil.baseutil import get_machine_info +from rjutil.baseutil import get_platform_info + +__all__ = ["getdeviceplatform", "get_rjconfig_info", "MONITOR_CONST", "MAILBOX_DIR", "DEVICE", + "GLOBALCONFIG", "GLOBALINITPARAM", "GLOBALINITCOMMAND", "MAC_LED_RESET", "STARTMODULE", + "fanloc", "RUIJIE_CARDID", "RUIJIE_PRODUCTNAME", "RUIJIE_PART_NUMBER", + "RUIJIE_LABEL_REVISION", "RUIJIE_MAC_SIZE", "RUIJIE_MANUF_NAME", "RUIJIE_MANUF_COUNTRY", + "RUIJIE_VENDOR_NAME", "RUIJIE_DIAG_VERSION", "RUIJIE_SERVICE_TAG", "E2_PROTECT", + "E2_LOC", "FAN_PROTECT", "FANS_DEF", "MONITOR_FANS_LED", "MONITOR_SYS_FAN_LED", + "MONITOR_SYS_PSU_LED", "MONITOR_FAN_STATUS", "MONITOR_PSU_STATUS", "MONITOR_DEV_STATUS", + "MONITOR_DEV_STATUS_DECODE", "DEV_LEDS", "MAC_AVS_PARAM", "MAC_DEFAULT_PARAM", + "FRULISTS", "rg_eeprom", "i2ccheck_params", "FANCTROLDEBUG", "DEVMONITORDEBUG"] + +def getdeviceplatform(): + x = get_platform_info(get_machine_info()) + if x != None: + filepath = "/usr/share/sonic/device/" + x + return filepath + + +platform = get_platform_info(get_machine_info()) # platform get platform info x86_64-ruijie_b6520-64cq-r0 +platformpath = getdeviceplatform() # platformpath get mappable docker contents /usr/share/sonic/device/x86_64-ruijie_b6520-64cq-r0 +MAILBOX_DIR = "/sys/bus/i2c/devices/" # sysfs top contents +grtd_productfile = (platform + "_config").replace("-","_") +common_productfile = "ruijiecommon" +configfile_pre = "/usr/local/bin/" # py's contents, use /usr/local/bin temporarily + +sys.path.append(platformpath) +sys.path.append(configfile_pre) + +def get_rjconfig_info(attr_key): + rjconf_filename = platformpath + "/plugins" + "/rj.conf" + if not os.path.isfile(rjconf_filename): + return None + with open(rjconf_filename) as rjconf_file: + for line in rjconf_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + if tokens[0] == attr_key: + return tokens[1].strip() + return None + +#####BMC-Password### +OPENBMC_PASSWORD = get_rjconfig_info("OPENBMC_PASSWORD") +OPENBMC_PASSWORD = OPENBMC_PASSWORD if(OPENBMC_PASSWORD != None) else "0penBmc" + +############################################################################################ +## if there is no specific file, use common file +module_product = None +if os.path.exists(configfile_pre + grtd_productfile + ".py"): + module_product = __import__(grtd_productfile, globals(), locals(), [], 0) +elif os.path.exists(configfile_pre + common_productfile + ".py"): + module_product = __import__(common_productfile, globals(), locals(), [], 0) +else: + print("No Configuration existed, quit") + exit(-1) +############################################################################################ + +DEVICE = module_product.DEVICE + +##########Driver loading needs parameters +#get different product configuration +RUIJIE_GLOBALCONFIG ={ + "DRIVERLISTS":module_product.DRIVERLISTS, + "QSFP": {"startbus":module_product.PCA9548START, "endbus":module_product.PCA9548BUSEND}, + "DEVS": DEVICE +} +GLOBALCONFIG = RUIJIE_GLOBALCONFIG +GLOBALINITPARAM = module_product.INIT_PARAM +GLOBALINITCOMMAND = module_product.INIT_COMMAND + +fancontrol_loc = module_product.fancontrol_loc +fancontrol_config_loc = module_product.fancontrol_config_loc +MAC_LED_RESET = module_product.MAC_LED_RESET +###########Stat-up module parameters +STARTMODULE = module_product.STARTMODULE +FIRMWARE_TOOLS = module_product.FIRMWARE_TOOLS + + +##########Manufacturing-Test need parameters +FACTESTMODULE = module_product.FACTESTMODULE +TESTCASE = module_product.TESTCASE +menuList = module_product.menuList +alltest = module_product.alltest +diagtestall = module_product.diagtestall +looptest = module_product.looptest +fanloc = module_product.fanloc +fanlevel = module_product.fanlevel # fan adjustment level +TEMPIDCHANGE = module_product.TEMPIDCHANGE +CPLDVERSIONS = module_product.CPLDVERSIONS +RUIJIE_CARDID = module_product.RUIJIE_CARDID +RUIJIE_PRODUCTNAME = module_product.RUIJIE_PRODUCTNAME + +RUIJIE_PART_NUMBER = module_product.RUIJIE_PART_NUMBER +RUIJIE_LABEL_REVISION = module_product.RUIJIE_LABEL_REVISION +RUIJIE_ONIE_VERSION = module_product.RUIJIE_ONIE_VERSION +RUIJIE_MAC_SIZE = module_product.RUIJIE_MAC_SIZE +RUIJIE_MANUF_NAME = module_product.RUIJIE_MANUF_NAME +RUIJIE_MANUF_COUNTRY = module_product.RUIJIE_MANUF_COUNTRY +RUIJIE_VENDOR_NAME = module_product.RUIJIE_VENDOR_NAME +RUIJIE_DIAG_VERSION = module_product.RUIJIE_DIAG_VERSION +RUIJIE_SERVICE_TAG = module_product.RUIJIE_SERVICE_TAG + +E2_PROTECT = module_product.E2_PROTECT +E2_LOC = module_product.E2_LOC +FAN_PROTECT = module_product.FAN_PROTECT + +FANS_DEF = module_product.FANS_DEF +MONITOR_SYS_LED = module_product.MONITOR_SYS_LED +MONITOR_FANS_LED = module_product.MONITOR_FANS_LED +MONITOR_SYS_FAN_LED = module_product.MONITOR_SYS_FAN_LED +MONITOR_SYS_PSU_LED = module_product.MONITOR_SYS_PSU_LED +MONITOR_FAN_STATUS = module_product.MONITOR_FAN_STATUS +MONITOR_PSU_STATUS = module_product.MONITOR_PSU_STATUS +MONITOR_DEV_STATUS = module_product.MONITOR_DEV_STATUS +MONITOR_DEV_STATUS_DECODE = module_product.MONITOR_DEV_STATUS_DECODE +DEV_MONITOR_PARAM = module_product.DEV_MONITOR_PARAM +SLOT_MONITOR_PARAM = module_product.SLOT_MONITOR_PARAM + + +DEV_LEDS = module_product.DEV_LEDS +MEM_SLOTS = module_product.MEM_SLOTS + +MAC_AVS_PARAM = module_product.MAC_AVS_PARAM +MAC_DEFAULT_PARAM = module_product.MAC_DEFAULT_PARAM +E2TYPE = module_product.E2TYPE +FRULISTS = module_product.FRULISTS +rg_eeprom = "%d-%04x/eeprom" % (E2_LOC["bus"], E2_LOC["devno"]) +factest_module = module_product.factest_module + +LOCAL_LED_CONTROL = module_product.LOCAL_LED_CONTROL + +PCIe_DEV_LIST = module_product.PCIe_DEV_LIST +PCIe_SPEED_ITEM = module_product.PCIe_SPEED_ITEM +i2ccheck_params = module_product.i2ccheck_params + + +class MONITOR_CONST: + TEMP_MIN = module_product.MONITOR_TEMP_MIN + K =module_product.MONITOR_K + MAC_IN =module_product.MONITOR_MAC_IN + DEFAULT_SPEED =module_product.MONITOR_DEFAULT_SPEED + MAX_SPEED =module_product.MONITOR_MAX_SPEED + MIN_SPEED =module_product.MONITOR_MIN_SPEED + MAC_ERROR_SPEED =module_product.MONITOR_MAC_ERROR_SPEED + FAN_TOTAL_NUM =module_product.MONITOR_FAN_TOTAL_NUM + MAC_UP_TEMP =module_product.MONITOR_MAC_UP_TEMP + MAC_LOWER_TEMP =module_product.MONITOR_MAC_LOWER_TEMP + MAC_MAX_TEMP = module_product.MONITOR_MAC_MAX_TEMP + + MAC_WARNING_THRESHOLD = module_product.MONITOR_MAC_WARNING_THRESHOLD + OUTTEMP_WARNING_THRESHOLD = module_product.MONITOR_OUTTEMP_WARNING_THRESHOLD + BOARDTEMP_WARNING_THRESHOLD = module_product.MONITOR_BOARDTEMP_WARNING_THRESHOLD + CPUTEMP_WARNING_THRESHOLD = module_product.MONITOR_CPUTEMP_WARNING_THRESHOLD + INTEMP_WARNING_THRESHOLD = module_product.MONITOR_INTEMP_WARNING_THRESHOLD + + MAC_CRITICAL_THRESHOLD = module_product.MONITOR_MAC_CRITICAL_THRESHOLD + OUTTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_OUTTEMP_CRITICAL_THRESHOLD + BOARDTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_BOARDTEMP_CRITICAL_THRESHOLD + CPUTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_CPUTEMP_CRITICAL_THRESHOLD + INTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_INTEMP_CRITICAL_THRESHOLD + CRITICAL_NUM = module_product.MONITOR_CRITICAL_NUM + SHAKE_TIME = module_product.MONITOR_SHAKE_TIME + MONITOR_INTERVAL= module_product.MONITOR_INTERVAL + MONITOR_FALL_TEMP = module_product.MONITOR_FALL_TEMP + + MONITOR_MAC_SOURCE_SYSFS = module_product.MONITOR_MAC_SOURCE_SYSFS + MONITOR_MAC_SOURCE_PATH = module_product.MONITOR_MAC_SOURCE_PATH + +FANCTROLDEBUG = 0 # 1 means enable +DEVMONITORDEBUG = 0 # 1 means enable + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieutil.py b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieutil.py new file mode 100755 index 000000000000..ff594b72e342 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/script/ruijieutil.py @@ -0,0 +1,1828 @@ +# -*- coding: UTF-8 -*- +#------------------------------------------------------------------------- +# Name: ruijieutil +# Purpose: common configuration and api +# +# Author: rd +# +# Created: 02/07/2018 +# Copyright: (c) rd 2018 +#------------------------------------------------------------------------- +import sys +import os +import re +import subprocess +import syslog +import time +import binascii +import tty +import termios +import threading +import click +import mmap +from ruijieconfig import rg_eeprom, FRULISTS, MAC_DEFAULT_PARAM, MAC_AVS_PARAM, FANS_DEF, \ + FAN_PROTECT, E2_LOC, E2_PROTECT, RUIJIE_SERVICE_TAG, RUIJIE_DIAG_VERSION, \ + STARTMODULE, RUIJIE_CARDID, RUIJIE_PRODUCTNAME, RUIJIE_PART_NUMBER, \ + RUIJIE_LABEL_REVISION, RUIJIE_MAC_SIZE, RUIJIE_MANUF_NAME, RUIJIE_MANUF_COUNTRY, \ + RUIJIE_VENDOR_NAME, MAILBOX_DIR + +try: + from eepromutil.fru import ipmifru + +except Exception or SystemExit: + pass + +import logging.handlers +import shutil +import gzip +import glob + +__all__ = ["MENUID", "MENUPARENT", "MENUVALUE", "CHILDID", "MENUITEMNAME", "MENUITEMDEAL", + "GOBACK", "GOQUIT", "file_name", "CRITICAL", "FATAL", "ERROR", "WARNING", "WARN", + "INFO", "DEBUG", "NOTSET", "levelNames", "TLV_INFO_ID_STRING", "TLV_INFO_VERSION", + "TLV_INFO_LENGTH", "TLV_INFO_LENGTH_VALUE", "TLV_CODE_PRODUCT_NAME", + "TLV_CODE_PART_NUMBER", "TLV_CODE_SERIAL_NUMBER", "TLV_CODE_MAC_BASE", + "TLV_CODE_MANUF_DATE", "TLV_CODE_DEVICE_VERSION", "TLV_CODE_LABEL_REVISION", + "TLV_CODE_PLATFORM_NAME", "TLV_CODE_ONIE_VERSION", "TLV_CODE_MAC_SIZE", + "TLV_CODE_MANUF_NAME", "TLV_CODE_MANUF_COUNTRY", "TLV_CODE_VENDOR_NAME", + "TLV_CODE_DIAG_VERSION", "TLV_CODE_SERVICE_TAG", "TLV_CODE_VENDOR_EXT", + "TLV_CODE_CRC_32", "_TLV_DISPLAY_VENDOR_EXT", "TLV_CODE_RJ_CARID", + "_TLV_INFO_HDR_LEN", "SYSLOG_IDENTIFIER", "log_info", "log_debug", "log_warning", + "log_error", "CompressedRotatingFileHandler", "SETMACException", "checkinput", + "checkinputproduct", "getInputSetmac", "fan_tlv", "AVSUTIL", "I2CUTIL", "BMC", + "getSdkReg", "getfilevalue", "get_sysfs_value", "write_sysfs_value", + "RJPRINTERR", "strtoint", "inttostr", "str_to_hex", "hex_to_str", "str_to_bin", + "bin_to_str", "getMacTemp", "getMacTemp_sysfs", "restartDockerService", + "waitForDhcp", "waitForSdk", "waitForDocker", "getTLV_BODY", "_crc32", + "printvalue", "generate_value", "getsyseeprombyId", "fac_init_cardidcheck", + "isValidMac", "util_setmac", "getInputCheck", "getrawch", "upper_input", + "changeTypeValue", "astrcmp", "generate_ext", "rji2cget", "rji2cset", "rjpcird", + "rjpciwr", "rjsysset", "rji2cgetWord", "rji2csetWord", "fan_setmac", "checkfansninput", + "checkfanhwinput", "util_show_fanse2", "get_fane2_sysfs", "util_show_fane2", "getPid", + "fac_fans_setmac_tlv", "fac_fan_setmac_fru", "fac_fans_setmac", "fac_fan_setmac", + "writeToEEprom", "get_local_eth0_mac", "getonieversion", "createbmcMac", + "fac_board_setmac", "ipmi_set_mac", "getInputValue", "bmc_setmac", "closeProtocol", + "checkSdkMem", "getch", "get_raw_input", "getsysvalue", "get_pmc_register", "decoder", + "decode_eeprom", "get_sys_eeprom", "getCardId", "getsysmeminfo", "getsysmeminfo_detail", + "getDmiSysByType", "gethwsys", "getsysbios", "searchDirByName", "getUsbLocation", + "getusbinfo", "get_cpu_info", "get_version_config_info", "io_rd", "io_wr"] + +MENUID = "menuid" +MENUPARENT = "parentid" +MENUVALUE = "value" +CHILDID = "childid" +MENUITEMNAME = "name" +MENUITEMDEAL = "deal" +GOBACK = "goBack" +GOQUIT = "quit" + +file_name = "/etc/init.d/opennsl-modules-3.16.0-5-amd64" +########################################################################## +# ERROR LOG LEVEL +########################################################################## +CRITICAL = 50 +FATAL = CRITICAL +ERROR = 40 +WARNING = 30 +WARN = WARNING +INFO = 20 +DEBUG = 10 +NOTSET = 0 + +levelNames = { + CRITICAL: 'CRITICAL', + ERROR: 'ERROR', + WARNING: 'WARNING', + INFO: 'INFO', + DEBUG: 'DEBUG', + NOTSET: 'NOTSET', + 'CRITICAL': CRITICAL, + 'ERROR': ERROR, + 'WARN': WARNING, + 'WARNING': WARNING, + 'INFO': INFO, + 'DEBUG': DEBUG, + 'NOTSET': NOTSET, +} + +TLV_INFO_ID_STRING = "TlvInfo\x00" +TLV_INFO_VERSION = 0x01 +TLV_INFO_LENGTH = 0x00 +TLV_INFO_LENGTH_VALUE = 0xba + +########################################################################## +# eeprom info +########################################################################## +TLV_CODE_PRODUCT_NAME = 0x21 +TLV_CODE_PART_NUMBER = 0x22 +TLV_CODE_SERIAL_NUMBER = 0x23 +TLV_CODE_MAC_BASE = 0x24 +TLV_CODE_MANUF_DATE = 0x25 +TLV_CODE_DEVICE_VERSION = 0x26 +TLV_CODE_LABEL_REVISION = 0x27 +TLV_CODE_PLATFORM_NAME = 0x28 +TLV_CODE_ONIE_VERSION = 0x29 +TLV_CODE_MAC_SIZE = 0x2A +TLV_CODE_MANUF_NAME = 0x2B +TLV_CODE_MANUF_COUNTRY = 0x2C +TLV_CODE_VENDOR_NAME = 0x2D +TLV_CODE_DIAG_VERSION = 0x2E +TLV_CODE_SERVICE_TAG = 0x2F +TLV_CODE_VENDOR_EXT = 0xFD +TLV_CODE_CRC_32 = 0xFE +_TLV_DISPLAY_VENDOR_EXT = 1 +TLV_CODE_RJ_CARID = 0x01 +_TLV_INFO_HDR_LEN = 11 + + +SYSLOG_IDENTIFIER = "UTILTOOL" + +# ========================== 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_debug(msg, also_print_to_console=False): + try: + syslog.openlog(SYSLOG_IDENTIFIER) + syslog.syslog(syslog.LOG_DEBUG, msg) + syslog.closelog() + + if also_print_to_console: + click.echo(msg) + except Exception as e: + pass + + +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) + +class CompressedRotatingFileHandler(logging.handlers.RotatingFileHandler): + def doRollover(self): + """ + Do a rollover, as described in __init__(). + """ + if self.stream: + self.stream.close() + self.stream = None + if self.backupCount > 0: + for i in range(self.backupCount - 1, 0, -1): + sfn = "%s.%d.gz" % (self.baseFilename, i) + dfn = "%s.%d.gz" % (self.baseFilename, i + 1) + if os.path.exists(sfn): + if os.path.exists(dfn): + os.remove(dfn) + os.rename(sfn, dfn) + dfn = self.baseFilename + ".1.gz" + if os.path.exists(dfn): + os.remove(dfn) + # These two lines below are the only new lines. I commented out the os.rename(self.baseFilename, dfn) and + # replaced it with these two lines. + with open(self.baseFilename, 'rb') as f_in, gzip.open(dfn, 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) + self.mode = 'w' + self.stream = self._open() + + +class SETMACException(Exception): + def __init__(self, param='ERROR', errno="-1"): + err = "Setmac fail[%s]: %s" % (errno, param) + Exception.__init__(self, err) + self.param = param + self.errno = errno + +def checkinput(b): + if b.isdigit() == False: + raise Exception("Ivalid Number") + if int(b) > 0xff or int(b) < 0: + raise Exception("Out of area") + +def checkinputproduct(b): + if b.isalnum() ==False: + raise Exception("Invalid string") + +def getInputSetmac(val): + bia = val.boardInfoArea + pia = val.productInfoArea + if bia != None: + a = raw_input("[Board Card]Product Serial Number:") + if len(a) != 13: + raise Exception("Invalid Serial Number length") + checkinputproduct(a) + bia.boardSerialNumber = a + b = raw_input("[Board Card]Product Version:(from 1-255)") + checkinput(b) + b = "%0x" % int(b) + bia.boardextra1 = b.upper() + if pia != None: + a = raw_input("[Product Area]Product Serial Number:") + if len(a) != 13: + raise Exception("Invalid Serial Number") + checkinputproduct(a) + pia.productSerialNumber = a + b = raw_input("[Product Area]Product Version:(from 1-255)") + checkinput(b) + b = "%0x" % int(b) + pia.productVersion = b.upper() + return val + +class fan_tlv(object): + VERSION = 0x01 # E2PROM Version,start from 0x01 + FLAG = 0x7E # New E2PROM version flag is 0x7E + HW_VER = 0X01 # compose by master version and fixed version + TYPE = 0xf1 # hw type defination + TLV_LEN = 00 # data length (16bit) + _FAN_TLV_HDR_LEN = 6 + _FAN_TLV_CRC_LEN = 2 + + _FAN_TLV_TYPE_NAME = 0x02 + _FAN_TLV_TYPE_SN = 0x03 + _FAN_TLV_TYPE_HW_INFO = 0x05 + _FAN_TLV_TYPE_DEV_TYPE = 0x06 + + _fandecodetime = 0 + + @property + def dstatus(self): + return self._dstatus + + @property + def typename(self): + return self._typename + + @property + def typesn(self): + return self._typesn + + @property + def typehwinfo(self): + return self._typehwinfo + + @property + def typedevtype(self): + return self._typedevtype + + @property + def fanbus(self): + return self._fanbus + + @property + def fanloc(self): + return self._fanloc + + @property + def fandecodetime(self): + return self._fandecodetime + + def __init__(self): + self._typename = "" + self._typesn = "" + self._typehwinfo = "" + self._typedevtype = "" + self._dstatus = 0 + + def strtoarr(self, str): + s = [] + if str is not None: + for index in range(len(str)): + s.append(str[index]) + return s + + def generate_fan_value(self): + bin_buffer = [chr(0xff)] * 256 + bin_buffer[0] = chr(self.VERSION) + bin_buffer[1] = chr(self.FLAG) + bin_buffer[2] = chr(self.HW_VER) + bin_buffer[3] = chr(self.TYPE) + + temp_t = "%08x" % self.typedevtype # handle devtype first + typedevtype_t = hex_to_str(temp_t) + total_len = len(self.typename) + len(self.typesn) + \ + len(self.typehwinfo) + len(typedevtype_t) + 8 + + bin_buffer[4] = chr(total_len >> 8) + bin_buffer[5] = chr(total_len & 0x00FF) + + index_start = 6 + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_NAME) + bin_buffer[index_start + 1] = chr(len(self.typename)) + bin_buffer[index_start + 2: index_start + 2 + + len(self.typename)] = self.strtoarr(self.typename) + index_start = index_start + 2 + len(self.typename) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_SN) + bin_buffer[index_start + 1] = chr(len(self.typesn)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typesn)] = self.strtoarr(self.typesn) + index_start = index_start + 2 + len(self.typesn) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_HW_INFO) + bin_buffer[index_start + 1] = chr(len(self.typehwinfo)) + bin_buffer[index_start + 2:index_start + 2 + + len(self.typehwinfo)] = self.strtoarr(self.typehwinfo) + index_start = index_start + 2 + len(self.typehwinfo) + + bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_DEV_TYPE) + bin_buffer[index_start + 1] = chr(len(typedevtype_t)) + bin_buffer[index_start + 2:index_start + 2 + + len(typedevtype_t)] = self.strtoarr(typedevtype_t) + index_start = index_start + 2 + len(typedevtype_t) + + crcs = fan_tlv.fancrc(''.join(bin_buffer[0:index_start])) # check 2bytes + bin_buffer[index_start] = chr(crcs >> 8) + bin_buffer[index_start + 1] = chr(crcs & 0x00ff) + return bin_buffer + + def decode(self, e2): + ret = [] + self.VERSION = ord(e2[0]) + self.FLAG = ord(e2[1]) + self.HW_VER = ord(e2[2]) + self.TYPE = ord(e2[3]) + self.TLV_LEN = (ord(e2[4]) << 8) | ord(e2[5]) + + tlv_index = self._FAN_TLV_HDR_LEN + tlv_end = self._FAN_TLV_HDR_LEN + self.TLV_LEN + + # check checksum + if len(e2) < self._FAN_TLV_HDR_LEN + self.TLV_LEN + 2: + self._dstatus = -2 + return ret + sumcrc = fan_tlv.fancrc(e2[0:self._FAN_TLV_HDR_LEN + self.TLV_LEN]) + readcrc = ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN] + ) << 8 | ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN + 1]) + if sumcrc != readcrc: + self._dstatus = -1 + return ret + else: + self._dstatus = 0 + while (tlv_index + 2) < len(e2) and tlv_index < tlv_end: + s = self.decoder( + e2[tlv_index:tlv_index + 2 + ord(e2[tlv_index + 1])]) + tlv_index += ord(e2[tlv_index + 1]) + 2 + ret.append(s) + + return ret + + @staticmethod + def fancrc(t): + sum = 0 + for index in range(len(t)): + sum += ord(t[index]) + return sum + + def decoder(self, t): + try: + name = "" + value = "" + if ord(t[0]) == self._FAN_TLV_TYPE_NAME: + name = "Product Name" + value = str(t[2:2 + ord(t[1])]) + self._typename = value + elif ord(t[0]) == self._FAN_TLV_TYPE_SN: + name = "serial Number" + value = str(t[2:2 + ord(t[1])]) + self._typesn = value + elif ord(t[0]) == self._FAN_TLV_TYPE_HW_INFO: + name = "hardware info" + value = str(t[2:2 + ord(t[1])]) + self._typehwinfo = value + elif ord(t[0]) == self._FAN_TLV_TYPE_DEV_TYPE: + name = "dev type" + value = str(t[2:2 + ord(t[1])]) + value = str_to_hex(value) + self._typedevtype = value + value = "0x08%x" % value + except Exception as e: + print(e) + return {"name": name, "code": ord(t[0]), "value": value} + + def __str__(self): + formatstr = "VERSION : 0x%02x \n" \ + " FLAG : 0x%02x \n" \ + " HW_VER : 0x%02x \n" \ + " TYPE : 0x%02x \n" \ + "typename : %s \n" \ + "typesn : %s \n" \ + "typehwinfo : %s \n" + return formatstr % (self.VERSION, self.FLAG, self.HW_VER, self.TYPE, self.typename, self.typesn, self.typehwinfo) + + +class AVSUTIL(): + @staticmethod + def mac_avs_chip(bus, devno, loc, open, close, loop, protectaddr, level, loopaddr): + # disable protection + rji2cset(bus, devno, protectaddr, open) + rji2cset(bus, devno, loopaddr, loop) + rji2csetWord(bus, devno, loc, level) + ret, value = rji2cgetWord(bus, devno, loc) + if strtoint(value) == level: + ret = 0 + # enable protection + rji2cset(bus, devno, protectaddr, close) + if ret == 0: + return True + return False + + @staticmethod + def macPressure_adj(macavs, avs_param, mac_def_param): + # check whether it within range + max_adj = max(avs_param.keys()) + min_adj = min(avs_param.keys()) + type = mac_def_param["type"] + level = 0 + if type == 0: + if macavs not in range(min_adj, max_adj + 1): + return False + else: + level = macavs + else: + if macavs not in range(min_adj, max_adj + 1): + level = mac_def_param["default"] + else: + level = macavs + ret = AVSUTIL.mac_avs_chip(mac_def_param["bus"], mac_def_param["devno"], mac_def_param["addr"], mac_def_param["open"], + mac_def_param["close"], mac_def_param["loop"], mac_def_param["protectaddr"], avs_param[level], mac_def_param["loopaddr"]) + return ret + + @staticmethod + def mac_adj(): + macavs = 0 + name = MAC_DEFAULT_PARAM["sdkreg"] + ret, status = getSdkReg(name) + if ret == False: + return False + status = strtoint(status) + # shift operation + if MAC_DEFAULT_PARAM["sdktype"] != 0: + status = ( + status >> MAC_DEFAULT_PARAM["macregloc"]) & MAC_DEFAULT_PARAM["mask"] + macavs = status + ret = AVSUTIL.macPressure_adj(macavs, MAC_AVS_PARAM, MAC_DEFAULT_PARAM) + return ret + + +class I2CUTIL(): + @staticmethod + def getvaluefromdevice(name): + ret = [] + for item in DEVICE: + if item["name"] == name: + ret.append(item) + return ret + + @staticmethod + def openFanE2Protect(): + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["open"]) + + @staticmethod + def closeFanE2Protect(): + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["close"]) + + @staticmethod + def writeToFanE2(bus, loc, rst_arr): + index = 0 + for item in rst_arr: + rji2cset(bus, loc, index, ord(item)) + index += 1 + + @staticmethod + def writeToE2(bus, loc, rst_arr): + index = 0 + for item in rst_arr: + rji2cset(bus, loc, index, ord(item)) + index += 1 + + @staticmethod + def getE2File(bus, loc): + return "/sys/bus/i2c/devices/%d-00%02x/eeprom" % (bus, loc) + + +class BMC(): + _instance_lock = threading.Lock() + + def __init__(self): + pass + + def __new__(cls, *args, **kwargs): + if not hasattr(Singleton, "_instance"): + with Singleton._instance_lock: + if not hasattr(Singleton, "_instance"): + Singleton._instance = object.__new__(cls) + return Singleton._instance + +# Internal interface + + +def getSdkReg(reg): + try: + cmd = "bcmcmd -t 1 'getr %s ' < /dev/null" % reg + ret, result = rj_os_system(cmd) + result_t = result.strip().replace("\r", "").replace("\n", "") + if ret != 0 or "Error:" in result_t: + return False, result + patt = r"%s.(.*):(.*)>drivshell" % reg + rt = re.findall(patt, result_t, re.S) + test = re.findall("=(.*)", rt[0][0])[0] + except Exception as e: + return False, 'getsdk register error' + return True, test + + +def getfilevalue(location): + try: + with open(location, 'r') as fd: + value = fd.read() + return True, value.strip() + except Exception as e: + return False, "error" + + +def get_sysfs_value(location): + pos_t = str(location) + name = get_pmc_register(pos_t) + return name + + +def write_sysfs_value(reg_name, value): + fileLoc = MAILBOX_DIR + reg_name + try: + if not os.path.isfile(fileLoc): + print(fileLoc, 'not found !') + return False + with open(fileLoc, 'w') as fd: + fd.write(value) + except Exception as error: + log_error("Unable to open " + fileLoc + "file !") + return False + return True + + +def RJPRINTERR(str): + print("\033[0;31m%s\033[0m" % str) + + +def strtoint(str): # convert Hex string to int such as "4040"/"0x4040"/"0X4040" = 16448 + value = 0 + rest_v = str.replace("0X", "").replace("0x", "") + for index in range(len(rest_v)): + print(rest_v[index]) + value |= int(rest_v[index], 16) << ((len(rest_v) - index - 1) * 4) + return value + +def inttostr(vl,len): # convert int to string such as 0x3030 = 00 + if type(vl) != int: + raise Exception(" type error") + index = 0 + ret_t = "" + while index < len: + ret = 0xff & (vl >> index * 8) + ret_t += chr(ret) + index += 1; + return ret_t + +def str_to_hex(rest_v): + value = 0 + for index in range(len(rest_v)): + value |= ord(rest_v[index]) << ((len(rest_v) - index - 1) * 8) + return value + + +def hex_to_str(s): + len_t = len(s) + if len_t % 2 != 0: + return 0 + ret = "" + for t in range(0, int(len_t / 2)): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + return ret + + +def str_to_bin(s): + return ' '.join([bin(ord(c)).replace('0b', '') for c in s]) + + +def bin_to_str(s): + return ''.join([chr(i) for i in [int(b, 2) for b in s.split(' ')]]) + + +def getMacTemp(): + result = {} + #waitForDocker() + # exec twice, get the second result + rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + ret, log = rj_os_system("bcmcmd -t 1 \"show temp\" < /dev/null") + if ret: + return False, result + else: + # decode obtained info + logs = log.splitlines() + for line in logs: + if "average" in line: + b = re.findall(r'\d+.\d+', line) + result["average"] = b[0] + elif "maximum" in line: + b = re.findall(r'\d+.\d+', line) + result["maximum"] = b[0] + return True, result + +def getMacTemp_sysfs(mactempconf): + try: + temp = -1000000 + temp_list = [] + mac_temp_loc = mactempconf.get("loc", []) + mac_temp_flag = mactempconf.get("flag",None) + if mac_temp_flag is not None: # check mac temperature vaild flag + gettype = mac_temp_flag.get('gettype') + okbit = mac_temp_flag.get('okbit') + okval = mac_temp_flag.get('okval') + if gettype == "io": + io_addr = mac_temp_flag.get('io_addr') + val = io_rd(io_addr) + if val is None: + raise Exception("get mac_flag by io failed.") + else: + bus = mac_temp_flag.get('bus') + loc = mac_temp_flag.get('loc') + offset = mac_temp_flag.get('offset') + ind, val = rji2cget(bus, loc, offset) + if ind is not True: + raise Exception("get mac_flag by i2c failed.") + val_t = (int(val,16) & (1<< okbit)) >> okbit + if val_t != okval: + raise Exception("mac_flag invalid, val_t:%d." % val_t) + for loc in mac_temp_loc: + temp_s = get_sysfs_value(loc) + if isinstance(temp_s, str) and temp_s.startswith("ERR"): + raise Exception("get mac temp error. loc:%s" % loc) + temp_t = int(temp_s) + if temp_t == -1000000: + raise Exception("mac temp invalid.loc:%s" % loc) + temp_list.append(temp_t) + temp_list.sort(reverse=True) + temp = temp_list[0] + except Exception as e: + return False, temp + return True, temp + +def restartDockerService(force=False): + container_name = ["database","snmp","syncd","swss","dhcp_relay","radv","teamd","pmon"] + ret, status = rj_os_system("docker ps") + if ret == 0 : + for tmpname in container_name: + if (tmpname not in status): + if (force == True): + rj_os_system("docker restart %s"%tmpname) + else: + rj_os_system("systemctl restart %s"%tmpname) + + +def waitForDhcp(timeout): + time_cnt = 0 + while True: + try: + ret, status = rj_os_system("systemctl status dhcp_relay.service") + if (ret == 0 and "running" in status) or "SUCCESS" in status: + break + else: + sys.stdout.write(".") + sys.stdout.flush() + time_cnt = time_cnt + 1 + if time_cnt > timeout: + raise Exception("waitForDhcp timeout") + time.sleep(1) + except Exception as e: + return False + return True + +def waitForSdk(sdk_fpath ,timeout): + time_cnt = 0 + while True: + try: + if os.path.exists(sdk_fpath): + break + else: + sys.stdout.write(".") + sys.stdout.flush() + time_cnt = time_cnt + 1 + if time_cnt > timeout: + raise Exception("waitForSdk timeout") + time.sleep(1) + except Exception as e: + return False + return True + +def waitForDocker(need_restart=False,timeout=180): + sdkcheck_params = STARTMODULE.get("sdkcheck",{}) + if sdkcheck_params.get("checktype") == "file": # pass file check + sdk_fpath = sdkcheck_params.get("sdk_fpath") + return waitForSdk(sdk_fpath,timeout) + return waitForDhcp(timeout) + + +def getTLV_BODY(type, productname): + x = [] + temp_t = "" + if type == TLV_CODE_MAC_BASE: + arr = productname.split(':') + for tt in arr: + temp_t += chr(int(tt, 16)) + elif type == TLV_CODE_DEVICE_VERSION: + temp_t = chr(productname) + elif type == TLV_CODE_MAC_SIZE: + temp_t = chr(productname >> 8) + chr(productname & 0x00ff) + else: + temp_t = productname + x.append(chr(type)) + x.append(chr(len(temp_t))) + for i in temp_t: + x.append(i) + return x + + +def _crc32(v): + return '0x%08x' % (binascii.crc32(v) & 0xffffffff) # get 8 bytes of crc32 %x return hex + + +def printvalue(b): + index = 0 + for i in range(0, len(b)): + if index % 16 == 0: + print(" ") + print("%02x " % ord(b[i])) + index += 1 + print("\n") + + +def generate_value(_t): + ret = [] + for i in TLV_INFO_ID_STRING: + ret.append(i) + ret.append(chr(TLV_INFO_VERSION)) + ret.append(chr(TLV_INFO_LENGTH)) + ret.append(chr(TLV_INFO_LENGTH_VALUE)) + + total_len = 0 + for key in _t: + x = getTLV_BODY(key, _t[key]) + ret += x + total_len += len(x) + ret[10] = chr(total_len + 6) + + ret.append(chr(0xFE)) + ret.append(chr(0x04)) + s = _crc32(''.join(ret)) + for t in range(0, 4): + ret.append(chr(int(s[2 * t + 2:2 * t + 4], 16))) + totallen = len(ret) + if (totallen < 256): + for left_t in range(0, 256 - totallen): + ret.append(chr(0x00)) + return (ret, True) + + +def getsyseeprombyId(id): + ret = get_sys_eeprom() + for item in ret: + if item["code"] == id: + return item + return None + + +def fac_init_cardidcheck(): + rest = getsyseeprombyId(TLV_CODE_RJ_CARID) # check cardId same or not + if rest is None: + print("need to program write bin file") + return False + else: + rest_v = rest['value'] + value = strtoint(rest_v) + if value == RUIJIE_CARDID: + log_debug("check card ID pass") + else: + log_debug("check card ID error") + return False + return True + + +def isValidMac(mac): + if re.match(r"^\s*([0-9a-fA-F]{2,2}:){5,5}[0-9a-fA-F]{2,2}\s*$", mac): + return True + return False + +# Internet cardsetmac + + +def util_setmac(eth, mac): + rulefile = "/etc/udev/rules.d/70-persistent-net.rules" + if isValidMac(mac) == False: + return False, "MAC invaild" + cmd = "ethtool -e %s | grep 0x0010 | awk '{print \"0x\"$13$12$15$14}'" % eth + ret, log = rj_os_system(cmd) + log_debug(log) + magic = "" + if ret == 0 and len(log): + magic = log + macs = mac.upper().split(":") + + # chage ETH0 to value after setmac + ifconfigcmd = "ifconfig eth0 hw ether %s" % mac + log_debug(ifconfigcmd) + ret, status = rj_os_system(ifconfigcmd) + if ret: + raise SETMACException("software set Internet cardMAC error") + index = 0 + for item in macs: + cmd = "ethtool -E %s magic %s offset %d value 0x%s" % ( + eth, magic, index, item) + log_debug(cmd) + index += 1 + ret, log = rj_os_system(cmd) + if ret != 0: + raise SETMACException(" set hardware Internet card MAC error") + # get value after setting + cmd_t = "ethtool -e eth0 offset 0 length 6" + ret, log = rj_os_system(cmd_t) + m = re.split(':', log)[-1].strip().upper() + mac_result = m.upper().split(" ") + + for ind, s in enumerate(macs): + if s != mac_result[ind]: + RJPRINTERR("MAC comparison error") + if os.path.exists(rulefile): + os.remove(rulefile) + print("MGMT MAC[%s]" % mac) + return True + + +def getInputCheck(tips): + str = raw_input(tips) + if astrcmp(str, "y") or astrcmp(str, "ye") or astrcmp(str, "yes") or astrcmp(str, ""): + return True + else: + return False + +def getrawch(): + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + ch = sys.stdin.read(1) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + return ch + +def upper_input(tips): + sys.stdout.write(tips) + sys.stdout.flush() + passwd = [] + while True: + ch = getrawch().upper() + if ch == "\r" or ch == "\n": + return "".join(passwd) + elif ch == '\b' or ord(ch) == 127: + if passwd: + del passwd[-1] + sys.stdout.write('\b \b') + else: + sys.stdout.write(ch) + passwd.append(ch) + +def changeTypeValue(_value, type1, tips, example): + if type1 == TLV_CODE_PRODUCT_NAME: + while True: + print("please check (1)air from forward to backward/(2)air from backward to forward:") + option = raw_input() + if option == "1": + _value[type1] = example + "-F-RJ" + print("check Product is air from forward to backward device,Product Name:%s"%_value[type1]) + break + elif option == "2": + _value[type1] = example + "-R-RJ" + print("check Product is air from backward to forward device,Product Name:%s"%_value[type1]) + break + else: + print("input incorrect, check please") + return True + print("Please input[%s]such as(%s):" % (tips, example)) + name = upper_input("") + if type1 == TLV_CODE_MAC_BASE: + if len(name) != 12: + raise SETMACException("MAC address length incorrect, check please") + release_mac = "" + for i in range(int(len(name) / 2)): + if i == 0: + release_mac += name[i * 2:i * 2 + 2] + else: + release_mac += ":" + name[i * 2:i * 2 + 2] + if isValidMac(release_mac) == True: + _value[type1] = release_mac + else: + raise SETMACException("MAC address invaild, check please") + elif type1 == TLV_CODE_DEVICE_VERSION: + if name.isdigit(): + _value[type1] = int(name) + else: + raise SETMACException("Version is not number, check please") + elif type1 == TLV_CODE_MAC_SIZE: + if name.isdigit(): + _value[type1] = int(name, 16) + else: + raise SETMACException("Version is not number, check please") + elif type1 == TLV_CODE_SERIAL_NUMBER: + if name.isalnum() == False: + raise SETMACException("Serial Number invaild string, check please") + elif len(name) != 13: + raise SETMACException("Serial Number length incorrect, check please") + else: + _value[type1] = name + elif type1 == TLV_CODE_VENDOR_EXT: + _value[type1] = name + else: + _value[type1] = name + return True + + +def astrcmp(str1, str2): + return str1.lower() == str2.lower() + + +def generate_ext(cardid): + s = "%08x" % cardid + ret = "" + for t in range(0, 4): + ret += chr(int(s[2 * t:2 * t + 2], 16)) + ret = chr(0x01) + chr(len(ret)) + ret + return ret + + +def rji2cget(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + time.sleep(0.1) + return False, ret_t + + +def rji2cset(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % ( + bus, devno, address, byte) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + +def rjpcird(pcibus , slot , fn, bar, offset): + '''read pci register''' + if offset % 4 != 0: + return + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + file = open(filename, "r+") + size = os.path.getsize(filename) + data = mmap.mmap(file.fileno(), size) + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + return "0x%08x" % val + + +def rjpciwr(pcibus , slot ,fn, bar, offset, data): + '''write pci register''' + ret = inttostr(data, 4) + filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar)) + file = open(filename, "r+") + size = os.path.getsize(filename) + data = mmap.mmap(file.fileno(), size) + data[offset: offset + 4] = ret + result = data[offset: offset + 4] + s = result[::-1] + val = 0 + for i in range(0, len(s)): + val = val << 8 | ord(s[i]) + data.close() + +def rjsysset(location, value): + command_line = "echo 0x%02x > %s" % (value, location) + retrytime = 6 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + + +def rji2cgetWord(bus, devno, address): + command_line = "i2cget -f -y %d 0x%02x 0x%02x w" % (bus, devno, address) + retrytime = 3 + ret_t = "" + for i in range(retrytime): + ret, ret_t = rj_os_system(command_line) + if ret == 0: + return True, ret_t + return False, ret_t + + +def rji2csetWord(bus, devno, address, byte): + command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%x w" % ( + bus, devno, address, byte) + rj_os_system(command_line) + + +def fan_setmac(): + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["open"]) + rji2cset(FAN_PROTECT["bus"], FAN_PROTECT["devno"], + FAN_PROTECT["addr"], FAN_PROTECT["close"]) + + +def checkfansninput(fan_sn, fansntemp): + if fan_sn in fansntemp: + RJPRINTERR("exist same Serial Number,please input again") + return False + if(len(fan_sn) != 13): + RJPRINTERR("Serial Number length incorrect,please input again") + return False + return True + +# check 输入的hardware version + + +def checkfanhwinput(hw): + if len(hw) != 4: + RJPRINTERR("hardware version length incorrect, please input again") + return False + if hw.find(".") != 1: + RJPRINTERR("hardware version incorrect, please input again") + return False + return True + + +def util_show_fanse2(fans): + formatstr = "%-8s %-20s %-20s %-20s %-20s" + print(formatstr % ("id", "Name", "hardware version", "Serial Number", "Time")) + print(formatstr % ("------", "---------------", "---------------", "---------------", "----")) + for fan in fans: + # print fan.dstatus + if fan.dstatus < 0: + print("%-8s" % ("FAN%d" % (fans.index(fan) + 1))) + RJPRINTERR(" decode e2 error") + else: + print(formatstr % ("FAN%d" % (fans.index(fan) + 1), fan.typename.replace(chr(0x00), ""), + fan.typehwinfo.replace(chr(0x00), ""), fan.typesn.replace(chr(0x00), ""), fan.fandecodetime)) + + +def get_fane2_sysfs(bus, loc): + rg_fan_e2 = "%d-%04x/fan" % (bus, loc) + eeprom = get_sysfs_value(rg_fan_e2) + return eeprom + + +def util_show_fane2(): + ret = sorted(I2CUTIL.getvaluefromdevice("rg_fan")) + if len(ret) <=0: + return None + fans = [] + for index in range(len(ret)): + t1 = (int(round(time.time() * 1000))) + eeprom = get_fane2_sysfs(ret[index]["bus"], ret[index]["loc"]) + t2 = (int(round(time.time() * 1000))) + fane2 = fan_tlv() + fane2.fandecodetime = t2 - t1 + fane2.decode(eeprom) + fans.append(fane2) + util_show_fanse2(fans) + + +def getPid(name): + ret = [] + for dirname in os.listdir('/proc'): + if dirname == 'curproc': + continue + try: + with open('/proc/{}/cmdline'.format(dirname), mode='rb') as fd: + content = fd.read() + except Exception: + continue + if name in content: + ret.append(dirname) + return ret + +def fac_fans_setmac_tlv(ret): + if len(ret) <=0: + return None + fans = [] + fansntemp = [] + for index in range(len(ret)): + item = ret[index] + log_debug(item) + eeprom = get_fane2_sysfs(item["bus"], item["loc"]) + fane2 = fan_tlv() + fane2.decode(eeprom) + fane2.fanbus = item["bus"] + fane2.fanloc = item["loc"] + log_debug("decode eeprom success") + + print("Fan[%d]-[%s]setmac" % ((index + 1), FANS_DEF[fane2.typedevtype])) + while True: + print("Please input[%s]:" % "Serial Number") + fan_sn = raw_input() + if checkfansninput(fan_sn, fansntemp) == False: + continue + fansntemp.append(fan_sn) + fan_sn = fan_sn + chr(0x00) + fane2.typesn = fan_sn + chr(0x00) + break + while True: + print("Please input[%s]:" % "hardware version") + hwinfo = raw_input() + if checkfanhwinput(hwinfo) == False: + continue + fan_hwinfo = hwinfo + chr(0x00) + fane2.typehwinfo = fan_hwinfo + chr(0x00) + break + log_debug(fane2.typedevtype) + fane2.typename = FANS_DEF[fane2.typedevtype] + chr(0x00) + fans.append(fane2) + print("\n") + print("\n*******************************\n") + + util_show_fanse2(fans) + if getInputCheck("check input correctly or not(Yes/No):") == True: + for fan in fans: + log_debug("ouput fan") + fac_fan_setmac(fan) + else: + print("setmac quit") + return False + + +def fac_fan_setmac_fru(ret): + fans = FRULISTS.get('fans') + + fanfrus = {} + newfrus = {} + + #getmsg + try: + for fan in fans: + print("===============%s ================getmessage" % fan.get('name')) + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + fru = ipmifru() + fru.decodeBin(eeprom) + fanfrus[fan.get('name')] = fru + except Exception as e: + print(str(e)) + return False + + #setmsg + for fan in fans: + print("===============%s ================setmac" % fan.get('name')) + fruold = fanfrus.get(fan.get('name')) + newfru = getInputSetmac(fruold) + newfru.recalcute() + newfrus[fan.get('name')] = newfru + #writemsg + for fan in fans: + print("===============%s ================writeToE2" % fan.get('name')) + ret_t = newfrus.get(fan.get('name')) + I2CUTIL.openFanE2Protect() + I2CUTIL.writeToFanE2(fan.get('bus'), fan.get('loc'), ret_t.bindata) + I2CUTIL.closeFanE2Protect() + #check + try: + for fan in fans: + print("===============%s ================getmessage" % fan.get('name')) + eeprom = getsysvalue(I2CUTIL.getE2File(fan.get('bus'), fan.get('loc'))) + fru = ipmifru() + fru.decodeBin(eeprom) + except Exception as e: + print(str(e)) + return False + return True + +def fac_fans_setmac(): + ret = I2CUTIL.getvaluefromdevice("rg_fan") + if ret is not None and len(ret) > 0: + return fac_fans_setmac_tlv(ret) + fans = FRULISTS.get('fans', None) + if fans is not None and len(fans)>0: + return fac_fan_setmac_fru(ret) + return False + +def fac_fan_setmac(item): + I2CUTIL.openFanE2Protect() + I2CUTIL.writeToFanE2(item.fanbus, item.fanloc, item.generate_fan_value()) + I2CUTIL.closeFanE2Protect() + +def writeToEEprom(rst_arr): + dealtype = E2_PROTECT.get('gettype',None) + if dealtype is None: + rji2cset(E2_PROTECT["bus"], E2_PROTECT["devno"], + E2_PROTECT["addr"], E2_PROTECT["open"]) + elif dealtype == "io": + io_wr(E2_PROTECT["io_addr"], E2_PROTECT["open"]) + index = 0 + for item in rst_arr: + rji2cset(E2_LOC["bus"], E2_LOC["devno"], index, ord(item)) + index += 1 + + if dealtype is None: + rji2cset(E2_PROTECT["bus"], E2_PROTECT["devno"], + E2_PROTECT["addr"], E2_PROTECT["close"]) + elif dealtype == "io": + io_wr(E2_PROTECT["io_addr"], E2_PROTECT["close"]) + # deal last drivers + os.system("rmmod at24 ") + os.system("modprobe at24 ") + os.system("rm -f /var/cache/sonic/decode-syseeprom/syseeprom_cache") + + +def get_local_eth0_mac(): + cmd = "ifconfig eth0 |grep HWaddr" + print(rj_os_system(cmd)) + +def getonieversion(): + if not os.path.isfile('/host/machine.conf'): + return "" + machine_vars = {} + with open('/host/machine.conf') as machine_file: + for line in machine_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + machine_vars[tokens[0]] = tokens[1].strip() + return machine_vars.get("onie_version") + +def createbmcMac(cpumac , num = 2): + bcmvalue = strtoint(cpumac[cpumac.rindex(":")+ 1:len(cpumac)]) + num + # bmcmac = + t = cpumac.split(":") + t[5] = "%02x" % bcmvalue + bmcmac = ":".join(t) + return bmcmac.upper() + + +def fac_board_setmac(): + _value = {} + # default value + _value[TLV_CODE_VENDOR_EXT] = generate_ext(RUIJIE_CARDID) # generate id + _value[TLV_CODE_PRODUCT_NAME] = RUIJIE_PRODUCTNAME + _value[TLV_CODE_PART_NUMBER] = RUIJIE_PART_NUMBER + _value[TLV_CODE_LABEL_REVISION] = RUIJIE_LABEL_REVISION + _value[TLV_CODE_PLATFORM_NAME] = platform + _value[TLV_CODE_ONIE_VERSION] = getonieversion() + _value[TLV_CODE_MAC_SIZE] = RUIJIE_MAC_SIZE + _value[TLV_CODE_MANUF_NAME] = RUIJIE_MANUF_NAME + _value[TLV_CODE_MANUF_COUNTRY] = RUIJIE_MANUF_COUNTRY + _value[TLV_CODE_VENDOR_NAME] = RUIJIE_VENDOR_NAME + _value[TLV_CODE_DIAG_VERSION] = RUIJIE_DIAG_VERSION + _value[TLV_CODE_SERVICE_TAG] = RUIJIE_SERVICE_TAG + try: + if 0x00004052 == RUIJIE_CARDID: + _value[TLV_CODE_PRODUCT_NAME] = RUIJIE_PRODUCTNAME + "-RJ" + elif 0x00004051 == RUIJIE_CARDID or 0x00004050 == RUIJIE_CARDID: + changeTypeValue(_value, TLV_CODE_PRODUCT_NAME, + "Product name",RUIJIE_PRODUCTNAME) + + changeTypeValue(_value, TLV_CODE_SERIAL_NUMBER, + "SN", "0000000000000") # add serial number + changeTypeValue(_value, TLV_CODE_DEVICE_VERSION, + "hardware version", "101") # hardware version + changeTypeValue(_value, TLV_CODE_MAC_BASE, + "MAC address", "58696cfb2108") # MAC address + _value[TLV_CODE_MANUF_DATE] = time.strftime( + '%m/%d/%Y %H:%M:%S', time.localtime()) # add setmac time + rst, ret = generate_value(_value) + if util_setmac("eth0", _value[TLV_CODE_MAC_BASE]) == True: # set Internet cardIP + writeToEEprom(rst) # write to e2 + # set BMC MAC + if "bmcsetmac" in FACTESTMODULE and FACTESTMODULE['bmcsetmac'] == 1: + bmcmac = createbmcMac(_value[TLV_CODE_MAC_BASE]) + if ipmi_set_mac(bmcmac) == True: + print("BMC MAC[%s]"%bmcmac) + else: + print("SET BMC MAC FAILED") + return False + else: + return False + except SETMACException as e: + #print(e) + RJPRINTERR("\n\n%s\n\n" % e) + return False + except ValueError as e: + return False + return True + + +def ipmi_set_mac(mac): + macs = mac.split(":") + cmdinit = "ipmitool raw 0x0c 0x01 0x01 0xc2 0x00" + cmdset = "ipmitool raw 0x0c 0x01 0x01 0x05" + for ind in range(len(macs)): + cmdset += " 0x%02x" % int(macs[ind], 16) + rj_os_system(cmdinit) + ret, status = rj_os_system(cmdset) + if ret: + RJPRINTERR("\n\n%s\n\n" % status) + return False + return True + + +def getInputValue(title, tips): + print("Please input[%s]such as(%s):" % (title, tips)) + name = raw_input() + + return name + + +def bmc_setmac(): + tips = "BMC MAC" + print("Please input value you want to change[%s]:" % tips) + name = raw_input() + if len(name) != 12: + RJPRINTERR("\nMAC address invaild, try again\n") + return False + release_mac = "" + for i in range(int(len(name) / 2)): + if i == 0: + release_mac += name[i * 2:i * 2 + 2] + else: + release_mac += ":" + name[i * 2:i * 2 + 2] + if isValidMac(release_mac) == True: + if ipmi_set_mac(release_mac) == True: + return True + else: + RJPRINTERR("\nMAC address invaild, try again\n") + return False + + +def closeProtocol(): + # disable LLDP + log_info("disable LLDP") + sys.stdout.write(".") + sys.stdout.flush() + rj_os_system("systemctl stop lldp.service") + log_info("disable lldp service") + sys.stdout.write(".") + sys.stdout.flush() + rj_os_system("systemctl stop bgp.service") + log_info("disable bgp service") + sys.stdout.write(".") + sys.stdout.flush() + #ret, status = rj_os_system('bcmcmd "port ce,xe stp=disable"') + +# check SDK memory must be 256M + + +def checkSdkMem(): + ind = 0 + file_data = "" + with open(file_name, "r") as f: + for line in f: + if "dmasize=16M" in line: + line = line.replace("dmasize=16M", "dmasize=256M") + ind = -1 + file_data += line + if ind == 0: + return + with open(file_name, "w") as f: + f.write(file_data) + print("change SDK memory to 256, reboot required") + rj_os_system("sync") + rj_os_system("reboot") + +########################################################################## +# receives a character setting +########################################################################## + + +def getch(msg): + ret = "" + fd = sys.stdin.fileno() + old_ttyinfo = termios.tcgetattr(fd) + new_ttyinfo = old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + sys.stdout.write(msg) + sys.stdout.flush() + try: + termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo) + ret = os.read(fd, 1) + finally: + # print "try to setting" + termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo) + return ret + +def get_raw_input(): + ret="" + fd=sys.stdin.fileno() + old_ttyinfo=termios.tcgetattr(fd) + new_ttyinfo=old_ttyinfo[:] + new_ttyinfo[3] &= ~termios.ICANON + new_ttyinfo[3] &= ~termios.ECHO + try: + termios.tcsetattr(fd,termios.TCSANOW,new_ttyinfo) + ret=raw_input("") + except Exception as e: + print(e) + finally: + termios.tcsetattr(fd,termios.TCSANOW,old_ttyinfo) + return ret + + +def getsysvalue(location): + retval = None + mb_reg_file = location + if (not os.path.isfile(mb_reg_file)): + print(mb_reg_file, 'not found !') + return retval + try: + if (not os.path.isfile(mb_reg_file)): + print(mb_reg_file, 'not found !') + return retval + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + log_error("Unable to open " + mb_reg_file + "file !") + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + #log_debug(retval) + return retval + +# get file value + + +def get_pmc_register(reg_name): + retval = 'ERR' + mb_reg_file = MAILBOX_DIR + reg_name + filepath = glob.glob(mb_reg_file) + if(len(filepath) == 0): + return "%s %s notfound"% (retval , mb_reg_file) + mb_reg_file = filepath[0] + if (not os.path.isfile(mb_reg_file)): + return "%s %s notfound"% (retval , mb_reg_file) + try: + with open(mb_reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + pass + retval = retval.rstrip('\r\n') + retval = retval.lstrip(" ") + return retval + +# decode EEPROM + + +def decoder(s, t): + if ord(t[0]) == TLV_CODE_PRODUCT_NAME: + name = "Product Name" + value = str(t[2:2 + ord(t[1])]) + elif ord(t[0]) == TLV_CODE_PART_NUMBER: + name = "Part Number" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_SERIAL_NUMBER: + name = "Serial Number" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MAC_BASE: + name = "Base MAC Address" + value = ":".join([binascii.b2a_hex(T) for T in t[2:8]]).upper() + elif ord(t[0]) == TLV_CODE_MANUF_DATE: + name = "Manufacture Date" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_DEVICE_VERSION: + name = "Device Version" + value = str(ord(t[2])) + elif ord(t[0]) == TLV_CODE_LABEL_REVISION: + name = "Label Revision" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_PLATFORM_NAME: + name = "Platform Name" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_ONIE_VERSION: + name = "ONIE Version" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MAC_SIZE: + name = "MAC Addresses" + value = str((ord(t[2]) << 8) | ord(t[3])) + elif ord(t[0]) == TLV_CODE_MANUF_NAME: + name = "Manufacturer" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_MANUF_COUNTRY: + name = "Manufacture Country" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_VENDOR_NAME: + name = "Vendor Name" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_DIAG_VERSION: + name = "Diag Version" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_SERVICE_TAG: + name = "Service Tag" + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_VENDOR_EXT: + name = "Vendor Extension" + value = "" + if _TLV_DISPLAY_VENDOR_EXT: + value = t[2:2 + ord(t[1])] + elif ord(t[0]) == TLV_CODE_CRC_32 and len(t) == 6: + name = "CRC-32" + value = "0x%08X" % (((ord(t[2]) << 24) | ( + ord(t[3]) << 16) | (ord(t[4]) << 8) | ord(t[5])),) + elif ord(t[0]) == TLV_CODE_RJ_CARID: + name = "rj_cardid" + value = "" + for c in t[2:2 + ord(t[1])]: + value += "%02X" % (ord(c),) + else: + name = "Unknown" + value = "" + for c in t[2:2 + ord(t[1])]: + value += "0x%02X " % (ord(c),) + return {"name": name, "code": ord(t[0]), "value": value} + + +def decode_eeprom(e): + total_len = (ord(e[9]) << 8) | ord(e[10]) + tlv_index = _TLV_INFO_HDR_LEN + tlv_end = _TLV_INFO_HDR_LEN + total_len + ret = [] + while (tlv_index + 2) < len(e) and tlv_index < tlv_end: + rt = decoder(None, e[tlv_index:tlv_index + 2 + ord(e[tlv_index + 1])]) + ret.append(rt) + if ord(e[tlv_index]) == TLV_CODE_CRC_32: + break + tlv_index += ord(e[tlv_index + 1]) + 2 + for item in ret: + if item['code'] == TLV_CODE_VENDOR_EXT: + rt = decoder(None, item["value"] + [0: 0 + 2 + ord(item["value"][0 + 1])]) + ret.append(rt) + return ret + + +def get_sys_eeprom(): + eeprom = get_sysfs_value(rg_eeprom) + return decode_eeprom(eeprom) + +# get card ID +def getCardId(): + ret = get_sys_eeprom() + for item in ret: + if item['code'] == TLV_CODE_RJ_CARID: + return item.get('value',None) + return None + +# ==================================== +# execute shell command +# ==================================== +def rj_os_system(cmd): + status, output = subprocess.getstatusoutput(cmd) + return status, output + +########################################### +# get memory slot and number via DMI command +########################################### +def getsysmeminfo(): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + "|grep -P -A5 \"Memory\s+Device\"|grep Size|grep -v Range" + # get total number first + result = [] + ret1, log1 = rj_os_system(cmd) + if ret1 == 0 and len(log1): + log1 = log1.lstrip() + arr = log1.split("\n") + #total = len(arr) # total slot number + for i in range(len(arr)): + val = re.sub("\D", "", arr[i]) + if val == "": + val = arr[i].lstrip() + val = re.sub('Size:', '', val).lstrip() + # print val + result.append({"slot": i + 1, "size": val}) + return True, result + return False, "error" + +########################################### +# get memory slot and number via DMI command +# return various arrays +########################################### +def getsysmeminfo_detail(): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + " -t 17 | grep -A21 \"Memory Device\"" # 17 + # get total number + ret1, log1 = rj_os_system(cmd) + if ret1 != 0 or len(log1) <= 0: + return False, "command execution error[%s]" % cmd + result_t = log1.split("--") + mem_rets = [] + for item in result_t: + its = item.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + mem_rets.append(ret) + return True, mem_rets + + +########################################### +# get BIOS info via DMI command +########################################### +def getDmiSysByType(type_t): + ret, log = rj_os_system("which dmidecode ") + if ret != 0 or len(log) <= 0: + error = "cmd find dmidecode" + return False, error + cmd = log + " -t %s" % type_t + # get total number + ret1, log1 = rj_os_system(cmd) + if ret1 != 0 or len(log1) <= 0: + return False, "command execution error[%s]" % cmd + its = log1.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + return True, ret + + +def gethwsys(): + return getDmiSysByType(1) + +########################################### +# get BIOS info via DMI command + + +def getsysbios(): + return getDmiSysByType(0) + + +def searchDirByName(name, dir): + result = [] + try: + files = os.listdir(dir) + for file in files: + if name in file: + result.append(os.path.join(dir, file)) + except Exception as e: + pass + return result + + +def getUsbLocation(): + dir = "/sys/block/" + spect = "sd" + usbpath = "" + result = searchDirByName(spect, dir) + if len(result) <= 0: + return False + for item in result: + with open(os.path.join(item, "removable"), 'r') as fd: + value = fd.read() + if value.strip() == "1": # U-Disk found + usbpath = item + break + if usbpath == "": # no U-Disk found + log_debug("no usb found") + return False, usbpath + return True, usbpath + +# judge USB file +def getusbinfo(): + ret, path = getUsbLocation() + if ret == False: + return False, "not usb exists" + str = os.path.join(path, "size") + ret, value = getfilevalue(str) + if ret == True: + return True, {"id": os.path.basename(path), "size": float(value) * 512 / 1024 / 1024 / 1024} + else: + return False, "Err" + +def get_cpu_info(): + cmd = "cat /proc/cpuinfo |grep processor -A18" # 17 + + ret, log1 = rj_os_system(cmd) + if ret != 0 or len(log1) <= 0: + return False, "command execution error[%s]" % cmd + result_t = log1.split("--") + mem_rets = [] + for item in result_t: + its = item.replace("\t", "").strip().split("\n") + ret = {} + for it in its: + if ":" in it: + key = it.split(":")[0].lstrip() + value = it.split(":")[1].lstrip() + ret[key] = value + mem_rets.append(ret) + return True, mem_rets +# read file +def get_version_config_info(attr_key, file_name=None): + if file_name is None: + version_conf_filename = "/root/version.json" + else: + version_conf_filename = file_name + if not os.path.isfile(version_conf_filename): + return None + with open(version_conf_filename) as rjconf_file: + for line in rjconf_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + if tokens[0] == attr_key: + return tokens[1].strip() + return None + + +def io_rd(reg_addr, len =1): + u'''io read''' + try: + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + str = os.read(fd, len) + return "".join(["%02x"% ord(item) for item in str]) + except ValueError: + return None + except Exception as e: + print(e) + return None + finally: + os.close(fd) + + +def io_wr(reg_addr, reg_data): + u'''io write''' + try: + regdata = 0 + regaddr = 0 + if type(reg_addr) == int: + regaddr = reg_addr + else: + regaddr = int(reg_addr, 16) + if type(reg_data) == int: + regdata = reg_data + else: + regdata = int(reg_data, 16) + devfile = "/dev/port" + fd = os.open(devfile, os.O_RDWR|os.O_CREAT) + os.lseek(fd, regaddr, os.SEEK_SET) + os.write(fd, chr(regdata)) + return True + except ValueError as e: + print(e) + return False + except Exception as e: + print(e) + return False + finally: + os.close(fd) + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/common/service/device_i2c.service b/platform/broadcom/sonic-platform-modules-ruijie/common/service/device_i2c.service new file mode 100755 index 000000000000..8777a46b7504 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/common/service/device_i2c.service @@ -0,0 +1,15 @@ +[Unit] +Description= Ruijie Global Initialize I2c drivers. +After=local-fs.target +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/device_i2c.py start +ExecStop=/usr/local/bin/device_i2c.py stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/changelog b/platform/broadcom/sonic-platform-modules-ruijie/debian/changelog new file mode 100755 index 000000000000..c987c3560017 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/changelog @@ -0,0 +1,5 @@ +sonic-ruijie-platform-modules (1.0) unstable; urgency=low + + * Initial release + + -- sonic_rd Fri, 21 APR 2017 11:11:11 -0800 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/compat b/platform/broadcom/sonic-platform-modules-ruijie/debian/compat new file mode 100755 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/control b/platform/broadcom/sonic-platform-modules-ruijie/debian/control new file mode 100755 index 000000000000..369ad546e8cc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/control @@ -0,0 +1,10 @@ +Source: sonic-ruijie-platform-modules +Section: main +Priority: extra +Maintainer: Ruijie Network +Standards-Version: 3.9.3 + +Package: platform-modules-ruijie-b6510-48vs8cq +Architecture: amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/copyright b/platform/broadcom/sonic-platform-modules-ruijie/debian/copyright new file mode 100755 index 000000000000..c00a47507890 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/copyright @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 Ruijie Network Corporation + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.init b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.init new file mode 100644 index 000000000000..a2ff25881623 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.init @@ -0,0 +1,39 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup B6510-48VS8CQ board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + /usr/local/bin/b6510-48vs8cq_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/b6510-48vs8cq_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-b6510-48vs8cq.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.install b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.install new file mode 100644 index 000000000000..436896926310 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.install @@ -0,0 +1,3 @@ +b6510-48vs8cq/modules/sonic_platform-1.0-py3-none-any.whl /usr/share/sonic/device/x86_64-ruijie_b6510-48vs8cq-r0 +b6510-48vs8cq/scripts/b6510-48vs8cq_platform.sh /usr/local/bin +b6510-48vs8cq/systemd/platform-modules-b6510-48vs8cq.service /usr/lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.postinst b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.postinst new file mode 100755 index 000000000000..5edc53b1cac5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/platform-modules-ruijie-b6510-48vs8cq.postinst @@ -0,0 +1,15 @@ +#!/bin/sh +# postinst + +kernel_version=$(uname -r) + +if [ -e /boot/System.map-${kernel_version} ]; then + depmod -a -F /boot/System.map-${kernel_version} ${kernel_version} || true +fi + +# Enable Ruijie-B6510-48VS8CQ-platform-service +depmod -a +systemctl enable platform-modules-b6510-48vs8cq.service +systemctl start platform-modules-b6510-48vs8cq.service + +#DEBHELPER# diff --git a/platform/broadcom/sonic-platform-modules-ruijie/debian/rules b/platform/broadcom/sonic-platform-modules-ruijie/debian/rules new file mode 100755 index 000000000000..a2b71bb5c229 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-ruijie/debian/rules @@ -0,0 +1,93 @@ +#!/usr/bin/make -f +CC=gcc +INSTALL_MOD_DIR:=extra +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +KBUILD_OUTPUT=$(KERNEL_SRC)/build + +LIB_DIR = usr/lib/python3.7/dist-packages +CUSTOM_RULES_DIR := $(shell pwd)/debian + +export INSTALL_MOD_DIR top_srcdir KVERSION KERNEL_SRC CC KBUILD_OUTPUT + +currentdir = $(shell pwd) +MODULE_DIRS := b6510-48vs8cq +export CUSTOMS_DIRS MODULE_DIRS + +#all product need common +COMPILE_DIRS = $(MODULE_DIRS) + +clean_dirs = $(MODULE_DIRS) +clean_dirs += common + +custom_clean_dirs := $(addprefix _clean_,$(clean_dirs) ) + + +%: + dh $@ +build: $(COMPILE_DIRS) + @echo "build success" + +$(custom_clean_dirs): + $(MAKE) -C $(patsubst _clean_%,%,$@) clean + +common_build : + $(MAKE) -C $(MOD_SRC_DIR)/common + +$(COMPILE_DIRS): common_build + $(MAKE) -C $(MOD_SRC_DIR)/$@ + dh_testdir + dh_installdirs + if [ $@ = "b6510-48vs8cq" ]; then \ + dh_installdirs -pplatform-modules-ruijie-$@ \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + fi; \ + cp -r $(MOD_SRC_DIR)/common/build/* debian/platform-modules-ruijie-$@/ + cp -r $(MOD_SRC_DIR)/$@/build/* debian/platform-modules-ruijie-$@/ + + @(for mod in $(MODULE_DIRS); do \ + cp -r $@/build/* $(MOD_SRC_DIR)/debian/platform-modules-ruijie-$${mod}/; \ + if [ $$mod = "b6510-48vs8cq" ]; then \ + cd $(MOD_SRC_DIR)/$${mod}; \ + cp -r $(MOD_SRC_DIR)/common/lib/plat_hal $(MOD_SRC_DIR)/$${mod}/; \ + cp -r $(MOD_SRC_DIR)/common/lib/rjutil $(MOD_SRC_DIR)/$${mod}/; \ + cp -r $(MOD_SRC_DIR)/common/lib/eepromutil $(MOD_SRC_DIR)/$${mod}/; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/plat_hal; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/rjutil; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/eepromutil; \ + cd $(MOD_SRC_DIR); \ + fi; \ + done) + +binary: binary-indep + @echo "=======================================================" + +binary-indep: + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +override_dh_usrlocal: + +override_dh_pysupport: + +clean: $(custom_clean_dirs) + dh_testdir + dh_testroot + dh_clean + +.PHONY: build $(COMPILE_DIRS) binary binary-arch binary-indep clean diff --git a/platform/cavium/cavm-platform-modules.mk b/platform/cavium/cavm-platform-modules.mk new file mode 100644 index 000000000000..4ac72a4c4aab --- /dev/null +++ b/platform/cavium/cavm-platform-modules.mk @@ -0,0 +1,3 @@ +CAVM_PLATFORM_DEB = cavm_platform_modules.deb +$(CAVM_PLATFORM_DEB)_SRC_PATH = $(PLATFORM_PATH)/cavm_platform_modules +SONIC_MAKE_DEBS += $(CAVM_PLATFORM_DEB) diff --git a/platform/cavium/cavm-sai.mk b/platform/cavium/cavm-sai.mk new file mode 100644 index 000000000000..0008135729c5 --- /dev/null +++ b/platform/cavium/cavm-sai.mk @@ -0,0 +1,13 @@ +# Cavium SAI + +CAVM_SAI_GITHUB = https://github.com/XPliant/OpenXPS/raw/13a7eaf10f523e7887964ca235f19095fcc88537/SAI/cavm-sai/ + +CAVM_LIBSAI = libsai.deb +CAVM_SAI = sai.deb +XP_TOOLS = xp-tools.deb + +$(CAVM_LIBSAI)_URL = $(CAVM_SAI_GITHUB)/$(CAVM_LIBSAI) +$(CAVM_SAI)_URL = $(CAVM_SAI_GITHUB)/$(CAVM_SAI) +$(XP_TOOLS)_URL = $(CAVM_SAI_GITHUB)/$(XP_TOOLS) + +SONIC_ONLINE_DEBS += $(CAVM_LIBSAI) $(CAVM_SAI) $(XP_TOOLS) diff --git a/platform/cavium/cavm-xpnet.mk b/platform/cavium/cavm-xpnet.mk new file mode 100644 index 000000000000..ed86558a36ae --- /dev/null +++ b/platform/cavium/cavm-xpnet.mk @@ -0,0 +1,6 @@ +CAVM_SAI_URL = https://github.com/XPliant/OpenXPS/raw/c26aea6a7098936ab3692e148238d73fa8962585/SAI + +CAVM_XPNET_DEB = xp80-Pcie-Endpoint.deb +$(CAVM_XPNET_DEB)_URL = $(CAVM_SAI_URL)/netdev/$(CAVM_XPNET_DEB) + +SONIC_ONLINE_DEBS += $(CAVM_XPNET_DEB) diff --git a/platform/cavium/cavm_platform_modules/DEBIAN/changelog b/platform/cavium/cavm_platform_modules/DEBIAN/changelog new file mode 100644 index 000000000000..b138dba26289 --- /dev/null +++ b/platform/cavium/cavm_platform_modules/DEBIAN/changelog @@ -0,0 +1,6 @@ + +cavm-platform-modules (1.0) unstable; urgency=low + + * Initial release + +-- Nadiya.Stetskovych@cavium.com Thu, 12 Jan 2017 19:24:41 +0200 diff --git a/platform/cavium/cavm_platform_modules/DEBIAN/control b/platform/cavium/cavm_platform_modules/DEBIAN/control new file mode 100755 index 000000000000..6a665e88c718 --- /dev/null +++ b/platform/cavium/cavm_platform_modules/DEBIAN/control @@ -0,0 +1,6 @@ +Package: cavm-platform-modules +Version: 1.0 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Maintainer: Nadiya.Stetskovych@cavium.com +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/cavium/cavm_platform_modules/Makefile b/platform/cavium/cavm_platform_modules/Makefile new file mode 100644 index 000000000000..aeb274aa5a42 --- /dev/null +++ b/platform/cavium/cavm_platform_modules/Makefile @@ -0,0 +1,33 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = cavm_platform_modules.deb +DEB_BUILD_DIR = cavm-platform-modules-deb +SCRIPT_SRC = $(DEB_BUILD_DIR)/ +SYSTEMD_DIR = /etc/systemd/system + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf SONiC + git clone https://github.com/edge-core/SONiC.git + + # build + pushd SONiC/AS7512-32X/module/ + + KERNEL_SRC=/lib/modules/$(KVERSION)/build make + popd + mkdir -p $(DEB_BUILD_DIR)/lib/modules/$(KVERSION) + mkdir -p $(DEB_BUILD_DIR)/usr/bin + mkdir -p $(DEB_BUILD_DIR)$(SYSTEMD_DIR)/multi-user.target.wants/ + + cp SONiC/AS7512-32X/module/*.ko $(DEB_BUILD_DIR)/lib/modules/$(KVERSION) + cp SONiC/AS7512-32X/accton_as7512_util.py $(DEB_BUILD_DIR)/usr/bin + chmod +x $(DEB_BUILD_DIR)/usr/bin/accton_as7512_util.py + cp as7512-platform-init.service $(DEB_BUILD_DIR)$(SYSTEMD_DIR) + ln -s $(SYSTEMD_DIR)/as7512-platform-init.service $(DEB_BUILD_DIR)$(SYSTEMD_DIR)/multi-user.target.wants/as7512-platform-init.service + cp -r DEBIAN $(DEB_BUILD_DIR) + dpkg-deb -b $(DEB_BUILD_DIR) $(MAIN_TARGET) + + mv $(MAIN_TARGET) $(DEST)/ + rm -rf $(DEB_BUILD_DIR) diff --git a/platform/cavium/cavm_platform_modules/as7512-platform-init.service b/platform/cavium/cavm_platform_modules/as7512-platform-init.service new file mode 100644 index 000000000000..69f03c0b2e45 --- /dev/null +++ b/platform/cavium/cavm_platform_modules/as7512-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Accton AS7512-32X Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/bin/accton_as7512_util.py install +ExecStop=/usr/bin/accton_as7512_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/cavium/cavm_sdk/filelist.txt b/platform/cavium/cavm_sdk/filelist.txt new file mode 100644 index 000000000000..bc40295dfbdc --- /dev/null +++ b/platform/cavium/cavm_sdk/filelist.txt @@ -0,0 +1,7 @@ +## Get vendor SAI SDK +## https://github.com/Azure/sonic-buildimage/blob/master/README.md#3-get-vendor-sai-sdk + +libsai.deb +sai.deb +xp-tools.deb +xpshell.deb diff --git a/platform/cavium/docker-saiserver-cavm/Dockerfile b/platform/cavium/docker-saiserver-cavm/Dockerfile new file mode 100644 index 000000000000..d15b16cbfd43 --- /dev/null +++ b/platform/cavium/docker-saiserver-cavm/Dockerfile @@ -0,0 +1,30 @@ +FROM docker-base + +RUN apt-get update \ + && apt-get install -y libsensors4-dev \ + python \ + python-dev + +COPY deps /root/deps + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; \ + dpkg_apt /root/deps/xp-tools.deb \ + && dpkg_apt /root/deps/libsai.deb \ + && dpkg_apt /root/deps/sai.deb \ + && dpkg_apt /root/deps/libthrift-0.9.3_*.deb \ + && dpkg_apt /root/deps/libnl-3-200_*.deb \ + && dpkg_apt /root/deps/libnl-genl-3-200_*.deb \ + && dpkg_apt /root/deps/libnl-route-3-200_*.deb + + +COPY ["deps/saiserver", "start.sh", "/usr/bin/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +COPY ["portmap.ini", "profile.ini", "/etc/sai/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf deps + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/cavium/docker-saiserver-cavm/portmap.ini b/platform/cavium/docker-saiserver-cavm/portmap.ini new file mode 100644 index 000000000000..c35776dcfcc5 --- /dev/null +++ b/platform/cavium/docker-saiserver-cavm/portmap.ini @@ -0,0 +1,33 @@ +# alias lanes +Ethernet0 16,17,18,19 +Ethernet4 20,21,22,23 +Ethernet8 24,25,26,27 +Ethernet12 28,29,30,31 +Ethernet16 32,33,34,35 +Ethernet20 36,37,38,39 +Ethernet24 40,41,42,43 +Ethernet28 44,45,46,47 +Ethernet32 0,1,2,3 +Ethernet36 4,5,6,7 +Ethernet40 8,9,10,11 +Ethernet44 12,13,14,15 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 127,126,125,124 +Ethernet68 123,122,121,120 +Ethernet72 115,114,113,112 +Ethernet76 119,118,117,116 +Ethernet80 79,78,77,76 +Ethernet84 75,74,73,72 +Ethernet88 64,65,66,67 +Ethernet92 71,70,68,69 +Ethernet96 111,110,109,108 +Ethernet100 107,106,105,104 +Ethernet104 103,102,101,100 +Ethernet108 99,98,97,96 +Ethernet112 95,94,93,92 +Ethernet116 91,90,89,88 +Ethernet120 87,86,85,84 +Ethernet124 83,82,81,80 diff --git a/platform/cavium/docker-saiserver-cavm/profile.ini b/platform/cavium/docker-saiserver-cavm/profile.ini new file mode 100644 index 000000000000..2b85ae77ebef --- /dev/null +++ b/platform/cavium/docker-saiserver-cavm/profile.ini @@ -0,0 +1,4 @@ +#SKU_128X10 +mode=0 + +hwId=as7512 diff --git a/platform/cavium/docker-saiserver-cavm/start.sh b/platform/cavium/docker-saiserver-cavm/start.sh new file mode 100755 index 000000000000..09cc0ddb5416 --- /dev/null +++ b/platform/cavium/docker-saiserver-cavm/start.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start saiserver diff --git a/platform/cavium/docker-saiserver-cavm/supervisord.conf b/platform/cavium/docker-saiserver-cavm/supervisord.conf new file mode 100644 index 000000000000..cb67a0fc9a47 --- /dev/null +++ b/platform/cavium/docker-saiserver-cavm/supervisord.conf @@ -0,0 +1,28 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[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=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:saiserver] +command=/usr/bin/saiserver -p /etc/sai/profile.ini -f /etc/sai/portmap.ini +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/cavium/docker-syncd-cavm-rpc.mk b/platform/cavium/docker-syncd-cavm-rpc.mk new file mode 100644 index 000000000000..a19124609bb0 --- /dev/null +++ b/platform/cavium/docker-syncd-cavm-rpc.mk @@ -0,0 +1,22 @@ +# docker image for cavium syncd with rpc + +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) $(PTF) +$(DOCKER_SYNCD_CAVM_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_CAVM_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_CAVM_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_CAVM) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_CAVM_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_CAVM_RPC) +endif + +$(DOCKER_SYNCD_CAVM_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_CAVM_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_CAVM_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_CAVM_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/cavium/docker-syncd-cavm-rpc/Dockerfile.j2 b/platform/cavium/docker-syncd-cavm-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..e9e9facef5ee --- /dev/null +++ b/platform/cavium/docker-syncd-cavm-rpc/Dockerfile.j2 @@ -0,0 +1,55 @@ +FROM docker-syncd-cavm + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_cavm_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get purge -y syncd + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_cavm_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/cavium/docker-syncd-cavm-rpc/ptf_nn_agent.conf b/platform/cavium/docker-syncd-cavm-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/cavium/docker-syncd-cavm-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/cavium/docker-syncd-cavm.mk b/platform/cavium/docker-syncd-cavm.mk new file mode 100644 index 000000000000..059d2c71ebb4 --- /dev/null +++ b/platform/cavium/docker-syncd-cavm.mk @@ -0,0 +1,23 @@ +# docker image for cavium syncd + +DOCKER_SYNCD_CAVM = docker-syncd-cavm.gz +$(DOCKER_SYNCD_CAVM)_PATH = $(PLATFORM_PATH)/docker-syncd-cavm +$(DOCKER_SYNCD_CAVM)_DEPENDS += $(SYNCD) $(CAVM_LIBSAI) $(XP_TOOLS) +$(DOCKER_SYNCD_CAVM)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_CAVM)_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_CAVM)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_CAVM) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_CAVM) +endif + +$(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/Dockerfile.j2 b/platform/cavium/docker-syncd-cavm/Dockerfile.j2 new file mode 100755 index 000000000000..fcf82276ad1a --- /dev/null +++ b/platform/cavium/docker-syncd-cavm/Dockerfile.j2 @@ -0,0 +1,35 @@ +FROM docker-config-engine + +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 + +COPY \ +{% for deb in docker_syncd_cavm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get -y install libpcap-dev libxml2-dev python-dev swig libsensors4-dev libatomic1 libjemalloc1 liblua5.1-0 lua-bitop lua-cjson + +RUN dpkg -i \ +{% for deb in docker_syncd_cavm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor/"] + +COPY ["profile.ini", "/etc/ssw/AS7512/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] 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..61e290e3189e --- /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 program syncd|syncd with path "/usr/bin/process_checker syncd /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/platform/cavium/docker-syncd-cavm/critical_processes b/platform/cavium/docker-syncd-cavm/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/cavium/docker-syncd-cavm/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/platform/cavium/docker-syncd-cavm/profile.ini b/platform/cavium/docker-syncd-cavm/profile.ini new file mode 100644 index 000000000000..017996f7d7cc --- /dev/null +++ b/platform/cavium/docker-syncd-cavm/profile.ini @@ -0,0 +1,2 @@ +mode=1 +hwId=as7512 diff --git a/platform/cavium/docker-syncd-cavm/start.sh b/platform/cavium/docker-syncd-cavm/start.sh new file mode 100755 index 000000000000..623316050475 --- /dev/null +++ b/platform/cavium/docker-syncd-cavm/start.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start syncd diff --git a/platform/cavium/docker-syncd-cavm/supervisord.conf b/platform/cavium/docker-syncd-cavm/supervisord.conf new file mode 100644 index 000000000000..91b94a258033 --- /dev/null +++ b/platform/cavium/docker-syncd-cavm/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 syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +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:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/cavium/libsaithrift-dev.mk b/platform/cavium/libsaithrift-dev.mk new file mode 100644 index 000000000000..7883a307d969 --- /dev/null +++ b/platform/cavium/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_amd64.deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(CAVM_LIBSAI) $(CAVM_SAI) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(CAVM_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_amd64.deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_amd64.deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(CAVM_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_amd64.deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/cavium/one-image.mk b/platform/cavium/one-image.mk new file mode 100644 index 000000000000..d81763430c05 --- /dev/null +++ b/platform/cavium/one-image.mk @@ -0,0 +1,15 @@ +# sonic cavium one image installer + +SONIC_ONE_IMAGE = sonic-cavium.bin +$(SONIC_ONE_IMAGE)_MACHINE = cavium +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(CAVM_PLATFORM_DEB) +$(SONIC_ONE_IMAGE)_INSTALLS += $(CAVM_XPNET_DEB) +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/cavium/platform.conf b/platform/cavium/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/cavium/rules.mk b/platform/cavium/rules.mk new file mode 100644 index 000000000000..a526774d2951 --- /dev/null +++ b/platform/cavium/rules.mk @@ -0,0 +1,23 @@ +include $(PLATFORM_PATH)/cavm-sai.mk +include $(PLATFORM_PATH)/docker-syncd-cavm.mk +include $(PLATFORM_PATH)/docker-syncd-cavm-rpc.mk +include $(PLATFORM_PATH)/cavm-platform-modules.mk +include $(PLATFORM_PATH)/cavm-xpnet.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_FPM) \ + $(DOCKER_PTF_CAVM) \ + $(DOCKER_SYNCD_CAVM_RPC) + +# Inject cavium sai into syncd +$(SYNCD)_DEPENDS += $(CAVM_SAI) $(CAVM_LIBSAI) +$(SYNCD)_UNINSTALLS += $(CAVM_LIBSAI) + +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV_CAVM) +endif + +# Runtime dependency on cavium sai is set only for syncd +$(SYNCD)_RDEPENDS += $(CAVM_SAI) diff --git a/platform/centec-arm64/docker-saiserver-centec.mk b/platform/centec-arm64/docker-saiserver-centec.mk new file mode 100755 index 000000000000..8d1b11bf005e --- /dev/null +++ b/platform/centec-arm64/docker-saiserver-centec.mk @@ -0,0 +1,15 @@ +# docker image for centec saiserver + +DOCKER_SAISERVER_CENTEC = docker-saiserver-centec.gz +$(DOCKER_SAISERVER_CENTEC)_PATH = $(PLATFORM_PATH)/docker-saiserver-centec +$(DOCKER_SAISERVER_CENTEC)_DEPENDS += $(SAISERVER) +$(DOCKER_SAISERVER_CENTEC)_FILES += $(DSSERVE) $(BCMCMD) +$(DOCKER_SAISERVER_CENTEC)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) +SONIC_DOCKER_IMAGES += $(DOCKER_SAISERVER_CENTEC) + +$(DOCKER_SAISERVER_CENTEC)_CONTAINER_NAME = saiserver +$(DOCKER_SAISERVER_CENTEC)_RUN_OPT += --privileged -t +$(DOCKER_SAISERVER_CENTEC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SAISERVER_CENTEC)_RUN_OPT += -v /var/run/docker-saiserver:/var/run/sswsyncd +$(DOCKER_SAISERVER_CENTEC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SAISERVER_CENTEC)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/centec-arm64/docker-syncd-centec-rpc.mk b/platform/centec-arm64/docker-syncd-centec-rpc.mk new file mode 100755 index 000000000000..2c441e4fc410 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec-rpc.mk @@ -0,0 +1,23 @@ +# docker image for centec syncd with rpc + +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)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_CENTEC_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_CENTEC_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_CENTEC_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_CENTEC_RPC) +endif + +$(DOCKER_SYNCD_CENTEC_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += --privileged -t +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/centec-arm64/docker-syncd-centec-rpc/Dockerfile.j2 b/platform/centec-arm64/docker-syncd-centec-rpc/Dockerfile.j2 new file mode 100755 index 000000000000..bec9c7f4426b --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec-rpc/Dockerfile.j2 @@ -0,0 +1,57 @@ +FROM docker-syncd-centec + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_centec_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get purge -y syncd + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + python-setuptools \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_centec_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip2 install cffi==1.7.0 \ + && pip2 install --upgrade cffi==1.7.0 \ + && pip2 install wheel \ + && pip2 install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/centec-arm64/docker-syncd-centec-rpc/ptf_nn_agent.conf b/platform/centec-arm64/docker-syncd-centec-rpc/ptf_nn_agent.conf new file mode 100755 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/centec-arm64/docker-syncd-centec.mk b/platform/centec-arm64/docker-syncd-centec.mk new file mode 100755 index 000000000000..9c3d1b1aff75 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec.mk @@ -0,0 +1,17 @@ +# docker image for centec syncd + +DOCKER_SYNCD_PLATFORM_CODE = centec +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) $(PYTHON_SDK_API) +$(DOCKER_SYNCD_CENTEC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) + +$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot +$(DOCKER_SYNCD_CENTEC)_RUN_OPT += --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 diff --git a/platform/centec-arm64/docker-syncd-centec/Dockerfile.j2 b/platform/centec-arm64/docker-syncd-centec/Dockerfile.j2 new file mode 100755 index 000000000000..b97bfe3d3e18 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec/Dockerfile.j2 @@ -0,0 +1,37 @@ +FROM docker-config-engine-buster + +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 + +COPY \ +{% for deb in docker_syncd_centec_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + iputils-ping + +RUN apt-get -y install libpcap-dev libxml2-dev python-dev swig libsensors4-dev nfs-common + +RUN dpkg -i \ +{% for deb in docker_syncd_centec_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin/"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/centec-arm64/docker-syncd-centec/critical_processes b/platform/centec-arm64/docker-syncd-centec/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/platform/centec-arm64/docker-syncd-centec/supervisord.conf b/platform/centec-arm64/docker-syncd-centec/supervisord.conf new file mode 100755 index 000000000000..10f406129d9c --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec/supervisord.conf @@ -0,0 +1,38 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python2 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running diff --git a/platform/centec-arm64/docker-syncd-centec/syncd.sh b/platform/centec-arm64/docker-syncd-centec/syncd.sh new file mode 100755 index 000000000000..993cf100f2f0 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec/syncd.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +function clean_up { + service syncd stop + exit +} + +trap clean_up SIGTERM SIGKILL + +service syncd start + +read diff --git a/platform/centec-arm64/libsaithrift-dev.mk b/platform/centec-arm64/libsaithrift-dev.mk new file mode 100755 index 000000000000..5b63dbbf7a29 --- /dev/null +++ b/platform/centec-arm64/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(CENTEC_SAI) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(CENTEC_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(CENTEC_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/centec-arm64/modules b/platform/centec-arm64/modules new file mode 100644 index 000000000000..30cdc339d8de --- /dev/null +++ b/platform/centec-arm64/modules @@ -0,0 +1,22 @@ +pinctrl-ctc +mtdblock +ofpart +spi-ctc-qspi +spi-nor +m25p80 +i2c-ctc +i2c-dev +rtc-sd2405 +ctc5236_switch +ctc5236_mdio +ctcmac +ctcmac_test +ctc5236-mc +ctc_wdt +ehci-ctc +sdhci-ctc5236 +gpio-ctc +pwm-ctc +ext4 +overlay +squashfs diff --git a/platform/centec-arm64/one-image.mk b/platform/centec-arm64/one-image.mk new file mode 100755 index 000000000000..e8f0cf3690e5 --- /dev/null +++ b/platform/centec-arm64/one-image.mk @@ -0,0 +1,18 @@ +# sonic centec one image installer + +SONIC_ONE_IMAGE = sonic-centec-arm64.bin +$(SONIC_ONE_IMAGE)_MACHINE = centec-arm64 +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie + +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_IMAGE)_INSTALLS += $(TSINGMA_BSP_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2C_PLATFORM_MODULE) + +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/centec-arm64/platform-modules-centec-e530.mk b/platform/centec-arm64/platform-modules-centec-e530.mk new file mode 100644 index 000000000000..3058e77a57e3 --- /dev/null +++ b/platform/centec-arm64/platform-modules-centec-e530.mk @@ -0,0 +1,18 @@ +# Centec E530-48T4X-P Platform modules + + +CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION =1.1 +CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION =1.1 + +export CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION + +CENTEC_E530_48T4X_P_PLATFORM_MODULE = platform-modules-e530-48t4x-p_$(CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION)_arm64.deb + +$(CENTEC_E530_48T4X_P_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-e530 +$(CENTEC_E530_48T4X_P_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_48t4x_p-r0 +$(CENTEC_E530_48T4X_P_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_DPKG_DEBS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE) + +CENTEC_E530_24X2C_PLATFORM_MODULE = platform-modules-e530-24x2c_$(CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION)_arm64.deb +$(CENTEC_E530_24X2C_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_24x2c-r0 +$(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_24X2C_PLATFORM_MODULE))) diff --git a/platform/centec-arm64/platform.conf b/platform/centec-arm64/platform.conf new file mode 100755 index 000000000000..8b29d0ded3a9 --- /dev/null +++ b/platform/centec-arm64/platform.conf @@ -0,0 +1,46 @@ +# Copyright (C) Centec Inc + +# over ride default behaviour + +echo "Preparing for installation ... " + +demo_mnt=/mnt + +hw_load() { + echo "ext4load mmc 0:2 \$loadaddr onie_uimage" +} + +create_partition() { + echo y | mkfs.ext4 -L CTC-SYSTEM /dev/mmcblk0p1 +} + +mount_partition() { + echo "mount flash" + mount -t ext4 /dev/mmcblk0p1 $demo_mnt +} + +bootloader_menu_config() { + mkdir -p $demo_mnt/boot + mount -t ext4 /dev/mmcblk0p2 $demo_mnt/boot + + rm $demo_mnt/boot/centec-e530.itb -rf + cp $demo_mnt/$image_dir/boot/sonic_arm64.fit $demo_mnt/boot/centec-e530.itb + cd $demo_mnt/boot + rm onie_uimage -rf + ln -s centec-e530.itb onie_uimage + cd - + sync + umount -l $demo_mnt/boot + + hw_load_str="$(hw_load)" + + (cat < /tmp/env.txt + + fw_setenv -f -s /tmp/env.txt + fw_setenv -f image_dir $image_dir +} diff --git a/platform/centec-arm64/rules.mk b/platform/centec-arm64/rules.mk new file mode 100755 index 000000000000..1982f86b757c --- /dev/null +++ b/platform/centec-arm64/rules.mk @@ -0,0 +1,22 @@ +include $(PLATFORM_PATH)/sai.mk +include $(PLATFORM_PATH)/docker-syncd-centec.mk +include $(PLATFORM_PATH)/docker-syncd-centec-rpc.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/tsingma-bsp.mk +include $(PLATFORM_PATH)/platform-modules-centec-e530.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_FPM) +# $(DOCKER_SYNCD_CENTEC_RPC) + +# Inject centec sai into syncd +$(SYNCD)_DEPENDS += $(CENTEC_SAI) +$(SYNCD)_UNINSTALLS += $(CENTEC_SAI) + +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV) +endif + +# Runtime dependency on centec sai is set only for syncd +$(SYNCD)_RDEPENDS += $(CENTEC_SAI) diff --git a/platform/centec-arm64/sai.mk b/platform/centec-arm64/sai.mk new file mode 100755 index 000000000000..2b902b49403a --- /dev/null +++ b/platform/centec-arm64/sai.mk @@ -0,0 +1,9 @@ +# Centec SAI + +export CENTEC_SAI_VERSION = 1.6.3-1 +export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb + +$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI) +$(eval $(call add_conflict_package,$(CENTEC_SAI),$(LIBSAIVS_DEV))) +SONIC_ONLINE_DEBS += $(CENTEC_SAI) + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/classes/__init__.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/Makefile b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/Makefile new file mode 100644 index 000000000000..c1beeaa15c68 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/Makefile @@ -0,0 +1 @@ +obj-m := centec_e530_24x2c_platform.o diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/centec_e530_24x2c_platform.c b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/centec_e530_24x2c_platform.c new file mode 100644 index 000000000000..8c2437a2d071 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/centec_e530_24x2c_platform.c @@ -0,0 +1,1111 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define SFP_NUM 24 +#define QSFP_NUM 2 +#define PORT_NUM (SFP_NUM + QSFP_NUM) +#endif + +#if SEP("i2c:smbus") +static int e530_24x2c_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + } + else + { + *value = 0; + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} + +static int e530_24x2c_smbus_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_write_byte_data(client, reg, value); + if (ret != 0) + { + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} +#endif + +#if SEP("i2c:master") +static struct i2c_adapter *i2c_adp_master = NULL; /* i2c-1-cpu */ + +static int e530_24x2c_init_i2c_master(void) +{ + /* find i2c-core master */ + i2c_adp_master = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e530_24x2c_init_i2c_master can't find i2c-core bus\n"); + return -1; + } + + return 0; +} + +static int e530_24x2c_exit_i2c_master(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_adp_master)) { + i2c_put_adapter(i2c_adp_master); + i2c_adp_master = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:gpio") +static struct i2c_adapter *i2c_adp_gpio0 = NULL; /* gpio0 */ +static struct i2c_adapter *i2c_adp_gpio1 = NULL; /* gpio1 */ +static struct i2c_adapter *i2c_adp_gpio2 = NULL; /* gpio2 */ +static struct i2c_board_info i2c_dev_gpio0 = { + I2C_BOARD_INFO("i2c-gpio0", 0x21), +}; +static struct i2c_board_info i2c_dev_gpio1 = { + I2C_BOARD_INFO("i2c-gpio1", 0x22), +}; +static struct i2c_board_info i2c_dev_gpio2 = { + I2C_BOARD_INFO("i2c-gpio2", 0x23), +}; +static struct i2c_client *i2c_client_gpio0 = NULL; +static struct i2c_client *i2c_client_gpio1 = NULL; +static struct i2c_client *i2c_client_gpio2 = NULL; + +static int e530_24x2c_init_i2c_gpio(void) +{ + int ret = 0; + + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e530_24x2c_init_i2c_gpio can't find i2c-core bus\n"); + return -1; + } + + i2c_adp_gpio0 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio0)) + { + i2c_adp_gpio0 = NULL; + printk(KERN_CRIT "get e530_24x2c gpio0 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio0 = i2c_new_device(i2c_adp_gpio0, &i2c_dev_gpio0); + if(IS_INVALID_PTR(i2c_client_gpio0)) + { + i2c_client_gpio0 = NULL; + printk(KERN_CRIT "create e530_24x2c board i2c client gpio0 failed\n"); + return -1; + } + + i2c_adp_gpio1 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio1)) + { + i2c_adp_gpio1 = NULL; + printk(KERN_CRIT "get e530_24x2c gpio1 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio1 = i2c_new_device(i2c_adp_gpio1, &i2c_dev_gpio1); + if(IS_INVALID_PTR(i2c_client_gpio1)) + { + i2c_client_gpio1 = NULL; + printk(KERN_CRIT "create e530_24x2c board i2c client gpio1 failed\n"); + return -1; + } + + i2c_adp_gpio2 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio2)) + { + i2c_adp_gpio2 = NULL; + printk(KERN_CRIT "get e530_24x2c gpio2 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio2 = i2c_new_device(i2c_adp_gpio2, &i2c_dev_gpio2); + if(IS_INVALID_PTR(i2c_client_gpio2)) + { + i2c_client_gpio2 = NULL; + printk(KERN_CRIT "create e530_24x2c board i2c client gpio2 failed\n"); + return -1; + } + + /* gpio0 */ + ret = e530_24x2c_smbus_write_reg(i2c_client_gpio0, 0x02, 0x00); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio0, 0x03, 0x00); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio0, 0x06, 0x00); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio0, 0x07, 0x00); + /* gpio1 */ + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio1, 0x02, 0xbf); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio1, 0x03, 0xff); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio1, 0x06, 0x0c); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio1, 0x07, 0xff); + /* gpio2 */ + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio2, 0x02, 0x00); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio2, 0x03, 0xff); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio2, 0x06, 0x00); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio2, 0x07, 0xff); + + if (ret) + { + printk(KERN_CRIT "init e530_24x2c board i2c gpio config failed\n"); + return -1; + } + + return 0; +} + +static int e530_24x2c_exit_i2c_gpio(void) +{ + if(IS_VALID_PTR(i2c_client_gpio0)) { + i2c_unregister_device(i2c_client_gpio0); + i2c_client_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio0)) + { + i2c_put_adapter(i2c_adp_gpio0); + i2c_adp_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio1)) { + i2c_unregister_device(i2c_client_gpio1); + i2c_client_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio1)) + { + i2c_put_adapter(i2c_adp_gpio1); + i2c_adp_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio2)) { + i2c_unregister_device(i2c_client_gpio2); + i2c_client_gpio2 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio2)) + { + i2c_put_adapter(i2c_adp_gpio2); + i2c_adp_gpio2 = NULL; + } + + return 0; +} +#endif + + +#if SEP("drivers:psu") +static struct class* psu_class = NULL; +static struct device* psu_dev_psu1 = NULL; +static struct device* psu_dev_psu2 = NULL; + +static ssize_t e530_24x2c_psu_read_presence(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char present_no = 0; + unsigned char present = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio1; + present_no = 9; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio1; + present_no = 13; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_24x2c_smbus_read_reg(i2c_psu_client, present_no/8, &present); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((present & (1<<(present_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_24x2c_psu_read_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char workstate_no = 0; + unsigned char workstate = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio1; + workstate_no = 11; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio1; + workstate_no = 15; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_24x2c_smbus_read_reg(i2c_psu_client, workstate_no/8, &workstate); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((workstate & (1<<(workstate_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static DEVICE_ATTR(psu_presence, S_IRUGO, e530_24x2c_psu_read_presence, NULL); +static DEVICE_ATTR(psu_status, S_IRUGO, e530_24x2c_psu_read_status, NULL); + +static int e530_24x2c_init_psu(void) +{ + int ret = 0; + + psu_class = class_create(THIS_MODULE, "psu"); + if (IS_INVALID_PTR(psu_class)) + { + psu_class = NULL; + printk(KERN_CRIT "create e530_24x2c class psu failed\n"); + return -1; + } + + psu_dev_psu1 = device_create(psu_class, NULL, MKDEV(222,0), NULL, "psu1"); + if (IS_INVALID_PTR(psu_dev_psu1)) + { + psu_dev_psu1 = NULL; + printk(KERN_CRIT "create e530_24x2c psu1 device failed\n"); + return -1; + } + + psu_dev_psu2 = device_create(psu_class, NULL, MKDEV(222,1), NULL, "psu2"); + if (IS_INVALID_PTR(psu_dev_psu2)) + { + psu_dev_psu2 = NULL; + printk(KERN_CRIT "create e530_24x2c psu2 device failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c psu1 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c psu1 device attr:status failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c psu2 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c psu2 device attr:status failed\n"); + return -1; + } + + return 0; +} + +static int e530_24x2c_exit_psu(void) +{ + if (IS_VALID_PTR(psu_dev_psu1)) + { + device_remove_file(psu_dev_psu1, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu1, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,0)); + } + + if (IS_VALID_PTR(psu_dev_psu2)) + { + device_remove_file(psu_dev_psu2, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu2, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,1)); + } + + if (IS_VALID_PTR(psu_class)) + { + class_destroy(psu_class); + psu_class = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:leds") +extern void e530_24x2c_led_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_24x2c_led_get(struct led_classdev *led_cdev); +extern void e530_24x2c_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_24x2c_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_system = { + .name = "system", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_idn = { + .name = "idn", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_fan1 = { + .name = "fan1", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_fan2 = { + .name = "fan2", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_fan3 = { + .name = "fan3", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_fan4 = { + .name = "fan4", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_psu1 = { + .name = "psu1", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_psu2 = { + .name = "psu2", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port1", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port2", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port3", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port4", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port5", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port6", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port7", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port8", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port9", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port10", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port11", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port12", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port13", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port14", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port15", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port16", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port17", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port18", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port19", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port20", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port21", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port22", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port23", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port24", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port25", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port26", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void e530_24x2c_led_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_gpio1; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x60; + shift = 5; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x10; + shift = 4; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_24x2c_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return; + } + + led_value = ((led_value & (~mask)) | ((set_value << shift) & (mask))); + + ret = e530_24x2c_smbus_write_reg(i2c_led_client, reg, led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s led attr failed\n", led_cdev->name); + return; + } + + return; + +not_support: + + printk(KERN_INFO "Error: led not support device:%s\n", led_cdev->name); + return; +} + +enum led_brightness e530_24x2c_led_get(struct led_classdev *led_cdev) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_gpio0; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x60; + shift = 5; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x10; + shift = 4; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_24x2c_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return 0; + } + + led_value = ((led_value & mask) >> shift); + + return led_value; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return 0; +} + +void e530_24x2c_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum-1] = set_value; + + return; +} + +enum led_brightness e530_24x2c_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum-1]; +} + +static int e530_24x2c_init_led(void) +{ + int ret = 0; + int i = 0; + + ret = led_classdev_register(NULL, &led_dev_system); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_system device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_idn); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_idn device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_fan1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_fan2 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan3); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_fan3 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan4); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_fan4 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_psu1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_psu2 device failed\n"); + return -1; + } + + for (i=0; i SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + presence = sfp_info[portNum].presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + return sprintf(buf, "%d\n", presence); +} + +static ssize_t e530_24x2c_sfp_write_presence(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + int presence = simple_strtol(buf, NULL, 10); + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + sfp_info[portNum].presence = presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_24x2c_sfp_read_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char value = 0; + unsigned char reg_no = 0; + unsigned char input_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + value = 0; + } + + if (portNum <= SFP_NUM) + { + if (portNum >= 1 && portNum <= 16) + { + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_gpio0; + } + else if (portNum > 16 && portNum <= 24) + { + reg_no = portNum - 17; + i2c_sfp_client = i2c_client_gpio2; + } + + input_bank = (reg_no/8) + 0x2; + ret = e530_24x2c_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp enable: %s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 ); + } + else + { + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + value = sfp_info[portNum].enable; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_24x2c_sfp_write_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned char value = 0; + unsigned char set_value = simple_strtol(buf, NULL, 10); + unsigned char reg_no = 0; + unsigned char input_bank = 0; + unsigned char output_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + return size; + } + + if (portNum <= SFP_NUM) + { + if (portNum >= 1 && portNum <= 16) + { + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_gpio0; + } + else if (portNum > 16 && portNum <= 24) + { + reg_no = portNum - 17; + i2c_sfp_client = i2c_client_gpio2; + } + + set_value = ((set_value > 0) ? 0 : 1); + + input_bank = (reg_no/8) + 0x2; + ret = e530_24x2c_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s enable failed\n", name); + return size; + } + + if (set_value) + { + value = (value | (1<<(reg_no % 8))); + } + else + { + value = (value & (~(1<<(reg_no % 8)))); + } + + output_bank = (reg_no/8) + 0x2; + ret = e530_24x2c_smbus_write_reg(i2c_sfp_client, output_bank, value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s enable failed\n", name); + return size; + } + } + else + { + set_value = ((set_value > 0) ? 1 : 0); + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + sfp_info[portNum].enable = set_value; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + } + + return size; +} + +static ssize_t e530_24x2c_sfp_read_eeprom(struct device *dev, struct device_attribute *attr, char *buf) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + size_t size = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read eeprom, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(buf, sfp_info[portNum].eeprom[0], sfp_info[portNum].data_len[0]); + size = sfp_info[portNum].data_len[0]; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_24x2c_sfp_write_eeprom(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp write eeprom, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(sfp_info[portNum].eeprom[0], buf, size); + sfp_info[portNum].data_len[0] = size; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static DEVICE_ATTR(sfp_presence, S_IRUGO|S_IWUSR, e530_24x2c_sfp_read_presence, e530_24x2c_sfp_write_presence); +static DEVICE_ATTR(sfp_enable, S_IRUGO|S_IWUSR, e530_24x2c_sfp_read_enable, e530_24x2c_sfp_write_enable); +static DEVICE_ATTR(sfp_eeprom, S_IRUGO|S_IWUSR, e530_24x2c_sfp_read_eeprom, e530_24x2c_sfp_write_eeprom); + +static int e530_24x2c_init_sfp(void) +{ + int ret = 0; + int i = 0; + + sfp_class = class_create(THIS_MODULE, "sfp"); + if (IS_INVALID_PTR(sfp_class)) + { + sfp_class = NULL; + printk(KERN_CRIT "create e530_24x2c class sfp failed\n"); + return -1; + } + + for (i=1; i<=SFP_NUM+QSFP_NUM; i++) + { + memset(&(sfp_info[i].eeprom), 0, sizeof(sfp_info[i].eeprom)); + memset(&(sfp_info[i].data_len), 0, sizeof(sfp_info[i].data_len)); + spin_lock_init(&(sfp_info[i].lock)); + + sfp_dev[i] = device_create(sfp_class, NULL, MKDEV(223,i), NULL, "sfp%d", i); + if (IS_INVALID_PTR(sfp_dev[i])) + { + sfp_dev[i] = NULL; + printk(KERN_CRIT "create e530_24x2c sfp[%d] device failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c sfp[%d] device attr:presence failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_enable); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c sfp[%d] device attr:enable failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_eeprom); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c sfp[%d] device attr:eeprom failed\n", i); + continue; + } + } + + return ret; +} + +static int e530_24x2c_exit_sfp(void) +{ + int i = 0; + + for (i=1; i<=SFP_NUM+QSFP_NUM; i++) + { + if (IS_VALID_PTR(sfp_dev[i])) + { + device_remove_file(sfp_dev[i], &dev_attr_sfp_presence); + device_remove_file(sfp_dev[i], &dev_attr_sfp_enable); + device_remove_file(sfp_dev[i], &dev_attr_sfp_eeprom); + device_destroy(sfp_class, MKDEV(223,i)); + sfp_dev[i] = NULL; + } + } + + if (IS_VALID_PTR(sfp_class)) + { + class_destroy(sfp_class); + sfp_class = NULL; + } + + return 0; +} +#endif + +static int e530_24x2c_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "install e530_24x2c board dirver...\n"); + + ret = e530_24x2c_init_i2c_master(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2c_init_i2c_gpio(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2c_init_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2c_init_led(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2c_init_sfp(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "install e530_24x2c board driver failed\n"); + else + printk(KERN_ALERT "install e530_24x2c board dirver...ok\n"); + + return 0; +} + +static void e530_24x2c_exit(void) +{ + printk(KERN_INFO "uninstall e530_24x2c board dirver...\n"); + + e530_24x2c_exit_sfp(); + e530_24x2c_exit_led(); + e530_24x2c_exit_psu(); + e530_24x2c_exit_i2c_gpio(); + e530_24x2c_exit_i2c_master(); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("shil centecNetworks, Inc"); +MODULE_DESCRIPTION("e530-24x2c board driver"); +module_init(e530_24x2c_init); +module_exit(e530_24x2c_exit); diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/service/24x2c_platform.service b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/service/24x2c_platform.service new file mode 100644 index 000000000000..50e35ad601cb --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/service/24x2c_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-e530-24x2c start +ExecStop=-/etc/init.d/platform-modules-e530-24x2c stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/setup.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/setup.py new file mode 100755 index 000000000000..17f8b8f01b55 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='24x2c', + version='1.1', + description='Module to initialize centec e530-24x2c platforms', + + packages=['24x2c'], + package_dir={'24x2c': '24x2c/classes'}, +) + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/classes/__init__.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/Makefile b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/Makefile new file mode 100644 index 000000000000..47327a1a0037 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/Makefile @@ -0,0 +1 @@ +obj-m := centec_e530_48t4x_p_platform.o diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/centec_e530_48t4x_p_platform.c b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/centec_e530_48t4x_p_platform.c new file mode 100644 index 000000000000..aedbe6601a07 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/centec_e530_48t4x_p_platform.c @@ -0,0 +1,1023 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define SFP_NUM 4 +#define PORT_NUM (48+SFP_NUM) +#endif + +#if SEP("i2c:smbus") +static int e530_48t4x_p_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + } + else + { + *value = 0; + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} + +static int e530_48t4x_p_smbus_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_write_byte_data(client, reg, value); + if (ret != 0) + { + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} +#endif + +#if SEP("i2c:master") +static struct i2c_adapter *i2c_adp_master = NULL; /* i2c-1-cpu */ + +static int e530_48t4x_p_init_i2c_master(void) +{ + /* find i2c-core master */ + i2c_adp_master = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e530_48t4x_p_init_i2c_master can't find i2c-core bus\n"); + return -1; + } + + return 0; +} + +static int e530_48t4x_p_exit_i2c_master(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_adp_master)) { + i2c_put_adapter(i2c_adp_master); + i2c_adp_master = NULL; + } + + return 0; +} +#endif + +//TODO!!! +#if SEP("i2c:gpio") +static struct i2c_adapter *i2c_adp_gpio0 = NULL; /* gpio0 */ +static struct i2c_board_info i2c_dev_gpio0 = { + I2C_BOARD_INFO("i2c-gpio0", 0x22), +}; +static struct i2c_client *i2c_client_gpio0 = NULL; + +static int e530_48t4x_p_init_i2c_gpio(void) +{ + int ret = 0; + + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e530_48t4x_p_init_i2c_gpio can't find i2c-core bus\n"); + return -1; + } + + i2c_adp_gpio0 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio0)) + { + i2c_adp_gpio0 = NULL; + printk(KERN_CRIT "get e530_48t4x_p gpio0 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio0 = i2c_new_device(i2c_adp_gpio0, &i2c_dev_gpio0); + if(IS_INVALID_PTR(i2c_client_gpio0)) + { + i2c_client_gpio0 = NULL; + printk(KERN_CRIT "create e530_48t4x_p board i2c client gpio0 failed\n"); + return -1; + } + + /* gpio0 */ + /* tx enable and release mac led and close indicate led */ + ret = e530_48t4x_p_smbus_write_reg(i2c_client_gpio0, 0x02, 0xf0); + /* bank 0 : output bank 1 : input */ + ret += e530_48t4x_p_smbus_write_reg(i2c_client_gpio0, 0x06, 0x00); + ret += e530_48t4x_p_smbus_write_reg(i2c_client_gpio0, 0x07, 0xff); + + if (ret) + { + printk(KERN_CRIT "init e530_48t4x_p board i2c gpio config failed\n"); + return -1; + } + + return 0; +} + +static int e530_48t4x_p_exit_i2c_gpio(void) +{ + if(IS_VALID_PTR(i2c_client_gpio0)) { + i2c_unregister_device(i2c_client_gpio0); + i2c_client_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio0)) + { + i2c_put_adapter(i2c_adp_gpio0); + i2c_adp_gpio0 = NULL; + } + + return 0; +} +#endif + + +#if SEP("drivers:psu") +static struct class* psu_class = NULL; +static struct device* psu_dev_psu1 = NULL; +static struct device* psu_dev_psu2 = NULL; + +static ssize_t e530_48t4x_p_psu_read_presence(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char present_no = 0; + unsigned char present = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio0; + present_no = 9; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio0; + present_no = 13; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_48t4x_p_smbus_read_reg(i2c_psu_client, present_no/8, &present); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((present & (1<<(present_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_48t4x_p_psu_read_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char workstate_no = 0; + unsigned char workstate = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio0; + workstate_no = 11; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio0; + workstate_no = 15; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_48t4x_p_smbus_read_reg(i2c_psu_client, workstate_no/8, &workstate); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((workstate & (1<<(workstate_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static DEVICE_ATTR(psu_presence, S_IRUGO, e530_48t4x_p_psu_read_presence, NULL); +static DEVICE_ATTR(psu_status, S_IRUGO, e530_48t4x_p_psu_read_status, NULL); + +static int e530_48t4x_p_init_psu(void) +{ + int ret = 0; + + psu_class = class_create(THIS_MODULE, "psu"); + if (IS_INVALID_PTR(psu_class)) + { + psu_class = NULL; + printk(KERN_CRIT "create e530_48t4x_p class psu failed\n"); + return -1; + } + + psu_dev_psu1 = device_create(psu_class, NULL, MKDEV(222,0), NULL, "psu1"); + if (IS_INVALID_PTR(psu_dev_psu1)) + { + psu_dev_psu1 = NULL; + printk(KERN_CRIT "create e530_48t4x_p psu1 device failed\n"); + return -1; + } + + psu_dev_psu2 = device_create(psu_class, NULL, MKDEV(222,1), NULL, "psu2"); + if (IS_INVALID_PTR(psu_dev_psu2)) + { + psu_dev_psu2 = NULL; + printk(KERN_CRIT "create e530_48t4x_p psu2 device failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p psu1 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p psu1 device attr:status failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p psu2 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p psu2 device attr:status failed\n"); + return -1; + } + + return 0; +} + +static int e530_48t4x_p_exit_psu(void) +{ + if (IS_VALID_PTR(psu_dev_psu1)) + { + device_remove_file(psu_dev_psu1, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu1, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,0)); + } + + if (IS_VALID_PTR(psu_dev_psu2)) + { + device_remove_file(psu_dev_psu2, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu2, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,1)); + } + + if (IS_VALID_PTR(psu_class)) + { + class_destroy(psu_class); + psu_class = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:leds") +extern void e530_48t4x_p_led_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_48t4x_p_led_get(struct led_classdev *led_cdev); +extern void e530_48t4x_p_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_48t4x_p_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_system = { + .name = "system", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_idn = { + .name = "idn", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_fan1 = { + .name = "fan1", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_fan2 = { + .name = "fan2", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_fan3 = { + .name = "fan3", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_fan4 = { + .name = "fan4", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_psu1 = { + .name = "psu1", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_psu2 = { + .name = "psu2", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port1", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port2", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port3", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port4", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port5", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port6", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port7", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port8", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port9", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port10", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port11", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port12", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port13", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port14", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port15", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port16", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port17", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port18", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port19", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port20", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port21", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port22", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port23", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port24", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port25", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port26", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port27", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port28", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port29", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port30", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port31", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port32", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port33", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port34", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port35", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port36", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port37", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port38", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port39", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port40", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port41", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port42", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port43", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port44", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port45", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port46", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port47", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port48", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port49", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port50", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port51", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port52", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void e530_48t4x_p_led_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_gpio0; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x60; + shift = 5; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x10; + shift = 4; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_48t4x_p_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return; + } + + led_value = ((led_value & (~mask)) | ((set_value << shift) & (mask))); + + ret = e530_48t4x_p_smbus_write_reg(i2c_led_client, reg, led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s led attr failed\n", led_cdev->name); + return; + } + + return; + +not_support: + + printk(KERN_INFO "Error: led not support device:%s\n", led_cdev->name); + return; +} + +enum led_brightness e530_48t4x_p_led_get(struct led_classdev *led_cdev) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_gpio0; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x60; + shift = 5; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x10; + shift = 4; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_48t4x_p_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return 0; + } + + led_value = ((led_value & mask) >> shift); + + return led_value; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return 0; +} + +void e530_48t4x_p_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum-1] = set_value; + + return; +} + +enum led_brightness e530_48t4x_p_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum-1]; +} + +static int e530_48t4x_p_init_led(void) +{ + int ret = 0; + int i = 0; + + ret = led_classdev_register(NULL, &led_dev_system); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_system device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_idn); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_idn device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_fan1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_fan2 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan3); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_fan3 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan4); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_fan4 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_psu1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_psu2 device failed\n"); + return -1; + } + + for (i=0; i SFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + presence = sfp_info[portNum].presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + return sprintf(buf, "%d\n", presence); +} + +static ssize_t e530_48t4x_p_sfp_write_presence(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + int presence = simple_strtol(buf, NULL, 10); + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + sfp_info[portNum].presence = presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_48t4x_p_sfp_read_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char value = 0; + unsigned char reg_no = 0; + unsigned char input_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + value = 0; + } + + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_gpio0; + + input_bank = (reg_no/8) + 0x2; + ret = e530_48t4x_p_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp enable: %s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_48t4x_p_sfp_write_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned char value = 0; + unsigned char set_value = simple_strtol(buf, NULL, 10); + unsigned char reg_no = 0; + unsigned char input_bank = 0; + unsigned char output_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + return size; + } + + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_gpio0; + + set_value = ((set_value > 0) ? 0 : 1); + + input_bank = (reg_no/8) + 0x2; + ret = e530_48t4x_p_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s enable failed\n", name); + return size; + } + + if (set_value) + { + value = (value | (1<<(reg_no % 8))); + } + else + { + value = (value & (~(1<<(reg_no % 8)))); + } + + output_bank = (reg_no/8) + 0x2; + ret = e530_48t4x_p_smbus_write_reg(i2c_sfp_client, output_bank, value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s enable failed\n", name); + return size; + } + + return size; +} + +static ssize_t e530_48t4x_p_sfp_read_eeprom(struct device *dev, struct device_attribute *attr, char *buf) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + size_t size = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read eeprom, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(buf, sfp_info[portNum].data, sfp_info[portNum].data_len); + size = sfp_info[portNum].data_len; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_48t4x_p_sfp_write_eeprom(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp write eeprom, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(sfp_info[portNum].data, buf, size); + sfp_info[portNum].data_len = size; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static DEVICE_ATTR(sfp_presence, S_IRUGO|S_IWUSR, e530_48t4x_p_sfp_read_presence, e530_48t4x_p_sfp_write_presence); +static DEVICE_ATTR(sfp_enable, S_IRUGO|S_IWUSR, e530_48t4x_p_sfp_read_enable, e530_48t4x_p_sfp_write_enable); +static DEVICE_ATTR(sfp_eeprom, S_IRUGO|S_IWUSR, e530_48t4x_p_sfp_read_eeprom, e530_48t4x_p_sfp_write_eeprom); +static int e530_48t4x_p_init_sfp(void) +{ + int ret = 0; + int i = 0; + + sfp_class = class_create(THIS_MODULE, "sfp"); + if (IS_INVALID_PTR(sfp_class)) + { + sfp_class = NULL; + printk(KERN_CRIT "create e530_48t4x_p class sfp failed\n"); + return -1; + } + + for (i=1; i<=SFP_NUM; i++) + { + memset(&(sfp_info[i].data), 0, MAX_SFP_EEPROM_DATA_LEN+1); + sfp_info[i].data_len = 0; + spin_lock_init(&(sfp_info[i].lock)); + + sfp_dev[i] = device_create(sfp_class, NULL, MKDEV(223,i), NULL, "sfp%d", i); + if (IS_INVALID_PTR(sfp_dev[i])) + { + sfp_dev[i] = NULL; + printk(KERN_CRIT "create e530_48t4x_p sfp[%d] device failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p sfp[%d] device attr:presence failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_enable); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p sfp[%d] device attr:enable failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_eeprom); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p sfp[%d] device attr:eeprom failed\n", i); + continue; + } + } + + return ret; +} + +static int e530_48t4x_p_exit_sfp(void) +{ + int i = 0; + + for (i=1; i<=SFP_NUM; i++) + { + if (IS_VALID_PTR(sfp_dev[i])) + { + device_remove_file(sfp_dev[i], &dev_attr_sfp_presence); + device_remove_file(sfp_dev[i], &dev_attr_sfp_enable); + device_remove_file(sfp_dev[i], &dev_attr_sfp_eeprom); + device_destroy(sfp_class, MKDEV(223,i)); + sfp_dev[i] = NULL; + } + } + + if (IS_VALID_PTR(sfp_class)) + { + class_destroy(sfp_class); + sfp_class = NULL; + } + + return 0; +} +#endif + +static int e530_48t4x_p_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "install e530_48t4x_p board dirver...\n"); + + ret = e530_48t4x_p_init_i2c_master(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48t4x_p_init_i2c_gpio(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48t4x_p_init_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48t4x_p_init_led(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48t4x_p_init_sfp(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "install e530_48t4x_p board driver failed\n"); + else + printk(KERN_ALERT "install e530_48t4x_p board dirver...ok\n"); + + return 0; +} + +static void e530_48t4x_p_exit(void) +{ + printk(KERN_INFO "uninstall e530_48t4x_p board dirver...\n"); + + e530_48t4x_p_exit_sfp(); + e530_48t4x_p_exit_led(); + e530_48t4x_p_exit_psu(); + e530_48t4x_p_exit_i2c_gpio(); + e530_48t4x_p_exit_i2c_master(); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("shil centecNetworks, Inc"); +MODULE_DESCRIPTION("e530-48t4x-p board driver"); +module_init(e530_48t4x_p_init); +module_exit(e530_48t4x_p_exit); diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/service/48t4x_p_platform.service b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/service/48t4x_p_platform.service new file mode 100644 index 000000000000..957f232259ad --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/service/48t4x_p_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-e530-48t4x-p start +ExecStop=-/etc/init.d/platform-modules-e530-48t4x-p stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/setup.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/setup.py new file mode 100755 index 000000000000..eee1cd2a841c --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='48t4x_p', + version='1.1', + description='Module to initialize centec e530-48t4x-p platforms', + + packages=['48t4x_p'], + package_dir={'48t4x_p': '48t4x_p/classes'}, +) + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/LICENSE b/platform/centec-arm64/sonic-platform-modules-e530/LICENSE new file mode 100644 index 000000000000..2d14d2b7785f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2019 Centec, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/centec-arm64/sonic-platform-modules-e530/README.md b/platform/centec-arm64/sonic-platform-modules-e530/README.md new file mode 100644 index 000000000000..6b907de17378 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/README.md @@ -0,0 +1 @@ +platform drivers for Centec E530 for the SONiC project diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/changelog b/platform/centec-arm64/sonic-platform-modules-e530/debian/changelog new file mode 100644 index 000000000000..6ac3ca4827b9 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/changelog @@ -0,0 +1,11 @@ +sonic-centec-platform-modules (1.1) unstable; urgency=low + + * Add support for centec e530-48t4x-p and e530-24x2c + + -- shil Fri, 15 Nov 2019 13:36:54 +0800 + +sonic-centec-platform-modules (1.0) unstable; urgency=low + + * Initial release + + -- shil Fri, 15 Nov 2019 13:35:06 +0800 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/compat b/platform/centec-arm64/sonic-platform-modules-e530/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/control b/platform/centec-arm64/sonic-platform-modules-e530/debian/control new file mode 100644 index 000000000000..2a1bc972a8b2 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/control @@ -0,0 +1,16 @@ +Source: sonic-centec-platform-modules +Section: main +Priority: extra +Maintainer: shil +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-e530-48t4x-p +Architecture: arm64 +Depends: linux-image-4.19.0-12-2-arm64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-e530-24x2c +Architecture: arm64 +Depends: linux-image-4.19.0-12-2-arm64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.init b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.init new file mode 100755 index 000000000000..e0349914b58d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.init @@ -0,0 +1,61 @@ +#!/bin/bash +# This script load/unload centec kernel modules + +### BEGIN INIT INFO +# Provides: platform-modules-e530-24x2c +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load Centec kernel modules +### END INIT INFO + + +function load_kernel_modules() +{ + depmod -a + modprobe centec_e530_24x2c_platform + modprobe dal + modprobe tun + modprobe tap +} + +function remove_kernel_modules() +{ + modprobe -r tap + modprobe -r tun + modprobe -r dal + modprobe -r centec_e530_24x2c_platform +} + +case "$1" in +start) + echo -n "Load Centec kernel modules... " + + load_kernel_modules + + echo "done." + ;; + +stop) + echo -n "Unload Centec kernel modules... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-e530-24x2c {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install new file mode 100644 index 000000000000..b74a968fe976 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install @@ -0,0 +1,3 @@ +../../centec/centec-dal/dal.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +24x2c/modules/centec_e530_24x2c_platform.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +24x2c/service/24x2c_platform.service /lib/systemd/system diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.postinst b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.postinst new file mode 100644 index 000000000000..8bc216369078 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.postinst @@ -0,0 +1,2 @@ +systemctl enable 24x2c_platform.service +systemctl start 24x2c_platform.service diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.init b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.init new file mode 100755 index 000000000000..b9a6d555b024 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.init @@ -0,0 +1,61 @@ +#!/bin/bash +# This script load/unload centec kernel modules + +### BEGIN INIT INFO +# Provides: platform-modules-e530-48t4x-p +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load Centec kernel modules +### END INIT INFO + + +function load_kernel_modules() +{ + depmod -a + modprobe centec_e530_48t4x_p_platform + modprobe dal + modprobe tun + modprobe tap +} + +function remove_kernel_modules() +{ + modprobe -r tap + modprobe -r tun + modprobe -r dal + modprobe -r centec_e530_48t4x_p_platform +} + +case "$1" in +start) + echo -n "Load Centec kernel modules... " + + load_kernel_modules + + echo "done." + ;; + +stop) + echo -n "Unload Centec kernel modules... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-e530-48t4x-p {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install new file mode 100644 index 000000000000..7d1c00eebeae --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install @@ -0,0 +1,3 @@ +../../centec/centec-dal/dal.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +48t4x_p/modules/centec_e530_48t4x_p_platform.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +48t4x_p/service/48t4x_p_platform.service /lib/systemd/system diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.postinst b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.postinst new file mode 100644 index 000000000000..12ef719aad8f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.postinst @@ -0,0 +1,2 @@ +systemctl enable 48t4x_p_platform.service +systemctl start 48t4x_p_platform.service diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/rules b/platform/centec-arm64/sonic-platform-modules-e530/debian/rules new file mode 100755 index 000000000000..69ab667c063d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/rules @@ -0,0 +1,91 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-modules-e530 +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= 48t4x_p 24x2c +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf +KDAL_DIR := ../../centec/centec-dal/ + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(KDAL_DIR); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/; \ + done) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$(KDAL_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/centec-arm64/sonic_fit.its b/platform/centec-arm64/sonic_fit.its new file mode 100644 index 000000000000..7ee89e6c812f --- /dev/null +++ b/platform/centec-arm64/sonic_fit.its @@ -0,0 +1,62 @@ +/* + *Copyright 2018 CENTEC + * + */ + +/dts-v1/; + +/ { + description = "arm64 kernel, initramfs and FDT blob"; + #address-cells = <1>; + + images { + kernel_ctc { + description = "ARM64 Kernel"; + data = /incbin/("./vmlinuz-4.19.0-12-2-arm64"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x80080000>; + entry = <0x80080000>; + hash { + algo = "crc32"; + }; + }; + initramfs { + description = "initramfs"; + data = /incbin/("./initrd.img-4.19.0-12-2-arm64"); + type = "ramdisk"; + arch = "arm64"; + os = "linux"; + compression = "gzip"; + load = <0x85000000>; + entry = <0x85000000>; + hash { + algo = "crc32"; + }; + }; + ctc_fdt { + description = "dtb for tm_ctc5236"; + data = /incbin/("./e530-ctc5236.dtb"); + type = "flat_dt"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x88000000>; + hash { + algo = "crc32"; + }; + }; + }; + configurations { + default = "e530-ctc5236"; + + e530-ctc5236 { + description = "config for tm_ctc5236"; + kernel = "kernel_ctc"; + ramdisk = "initramfs"; + fdt = "ctc_fdt"; + }; + }; +}; diff --git a/platform/centec-arm64/tsingma-bsp.mk b/platform/centec-arm64/tsingma-bsp.mk new file mode 100644 index 000000000000..3b2095ef1d79 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp.mk @@ -0,0 +1,12 @@ +# Centec TsingMa BSP Platform modules + + +TSINGMA_BSP_MODULE_VERSION = 1.0 + +export TSINGMA_BSP_MODULE_VERSION + +TSINGMA_BSP_MODULE = tsingma-bsp_$(TSINGMA_BSP_MODULE_VERSION)_$(PLATFORM_ARCH).deb + +$(TSINGMA_BSP_MODULE)_SRC_PATH = $(PLATFORM_PATH)/tsingma-bsp +$(TSINGMA_BSP_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_DPKG_DEBS += $(TSINGMA_BSP_MODULE) diff --git a/platform/centec-arm64/tsingma-bsp/LICENSE b/platform/centec-arm64/tsingma-bsp/LICENSE new file mode 100644 index 000000000000..2d14d2b7785f --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2019 Centec, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/centec-arm64/tsingma-bsp/README.md b/platform/centec-arm64/tsingma-bsp/README.md new file mode 100644 index 000000000000..41684740dc9b --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/README.md @@ -0,0 +1 @@ +platform drivers for Centec TsingMa soc diff --git a/platform/centec-arm64/tsingma-bsp/debian/changelog b/platform/centec-arm64/tsingma-bsp/debian/changelog new file mode 100644 index 000000000000..df95b50b9117 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/debian/changelog @@ -0,0 +1,5 @@ +tsingma-bsp (1.0) unstable; urgency=low + + * Initial release + + -- shil Wed, 24 Jun 2020 14:20:58 +0800 diff --git a/platform/centec-arm64/tsingma-bsp/debian/compat b/platform/centec-arm64/tsingma-bsp/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/centec-arm64/tsingma-bsp/debian/control b/platform/centec-arm64/tsingma-bsp/debian/control new file mode 100644 index 000000000000..fc6d0b8def4f --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/debian/control @@ -0,0 +1,11 @@ +Source: tsingma-bsp +Section: main +Priority: extra +Maintainer: shil +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: tsingma-bsp +Architecture: arm64 +Depends: linux-image-4.19.0-12-2-arm64-unsigned +Description: kernel modules for tsingma bsp diff --git a/platform/centec-arm64/tsingma-bsp/debian/rules b/platform/centec-arm64/tsingma-bsp/debian/rules new file mode 100644 index 000000000000..17788b62411a --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/debian/rules @@ -0,0 +1,66 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +PACKAGE_PRE_NAME := tsingma-bsp +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= ctc5236-mc ctc5236_switch ctcmac ctc_wdt ehci-ctc gpio-ctc i2c-ctc pinctrl-ctc pwm-ctc rtc-sd2405 sdhci-ctc5236 spi-ctc-qspi +DTS_DIR := ctc-dts +MODULE_DIR := src +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$(MODULE_DIR)/$${mod}; \ + done) + make -C $(MOD_SRC_DIR)/$(MODULE_DIR)/$(DTS_DIR) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +binary-indep: + dh_testdir + dh_installdirs + + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.init b/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.init new file mode 100644 index 000000000000..dedbebb3be08 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.init @@ -0,0 +1,49 @@ +#!/bin/bash +# This script config centec tsingma soc + +### BEGIN INIT INFO +# Provides: tsingma-bsp +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Config Centec TsingMa SOC +### END INIT INFO + + +function config_tsingma_soc() +{ + hwaddr=`fw_printenv ethaddr | awk -F = '{print $2}'` + if [ "$hwaddr" != "" ]; then + ifconfig eth0 hw ether $hwaddr + fi + modprobe tun + modprobe tap +} + +case "$1" in +start) + echo -n "Config Centec TsingMa SOC... " + + config_tsingma_soc + + echo "done." + ;; + +stop) + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/tsingma-bsp {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install b/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install new file mode 100644 index 000000000000..e2fb35af1b6c --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install @@ -0,0 +1,17 @@ +src/ctc5236-mc/ctc5236-mc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/pwm-ctc/pwm-ctc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctc5236_switch/ctc5236_switch.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/pinctrl-ctc/pinctrl-ctc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctc_wdt/ctc_wdt.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctcmac/ctcmac.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctcmac/ctcmac_test.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctcmac/ctc5236_mdio.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/i2c-ctc/i2c-ctc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/gpio-ctc/gpio-ctc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ehci-ctc/ehci-ctc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/rtc-sd2405/rtc-sd2405.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/sdhci-ctc5236/sdhci-ctc5236.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/spi-ctc-qspi/spi-ctc-qspi.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctc-dts/e530-ctc5236.dtb /boot/ +src/config/fw_env.config /etc/ +src/config/tsingma-bsp.service /lib/systemd/system diff --git a/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.postinst b/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.postinst new file mode 100644 index 000000000000..2aaf59573a74 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.postinst @@ -0,0 +1,2 @@ +systemctl enable tsingma-bsp.service +systemctl start tsingma-bsp.service diff --git a/platform/centec-arm64/tsingma-bsp/src/config/fw_env.config b/platform/centec-arm64/tsingma-bsp/src/config/fw_env.config new file mode 100644 index 000000000000..6ef503c1cdb3 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/config/fw_env.config @@ -0,0 +1,2 @@ +# MTD device name Device offset Env. size Flash sector size +/dev/mtd1 0x00000000 0x00010000 0x00001000 diff --git a/platform/centec-arm64/tsingma-bsp/src/config/tsingma-bsp.service b/platform/centec-arm64/tsingma-bsp/src/config/tsingma-bsp.service new file mode 100644 index 000000000000..b384b4896e8b --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/config/tsingma-bsp.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec tsingma bsp init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/tsingma-bsp start +ExecStop=-/etc/init.d/tsingma-bsp stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc-dts/Makefile b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/Makefile new file mode 100644 index 000000000000..146a62ce37a7 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/Makefile @@ -0,0 +1,4 @@ +e530-ctc5236.dtb: e530-ctc5236.dts ctc5236.dtsi ctc5236-clock.dtsi + cpp -nostdinc -I. -undef -x assembler-with-cpp e530-ctc5236.dts > tmp.dts + dtc -O dtb -o e530-ctc5236.dtb tmp.dts + rm tmp.dts -rf diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc-dts/arm-gic.h b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/arm-gic.h new file mode 100644 index 000000000000..8c75d237d4b7 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/arm-gic.h @@ -0,0 +1,22 @@ +/* + * This header provides constants for the ARM GIC. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H + +#include "irq.h" + +/* interrupt specifier cell 0 */ + +#define GIC_SPI 0 +#define GIC_PPI 1 + +/* + * Interrupt specifier cell 2. + * The flags in irq.h are valid, plus those below. + */ +#define GIC_CPU_MASK_RAW(x) ((x) << 8) +#define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1) + +#endif diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc-dts/ctc5236-clks.h b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/ctc5236-clks.h new file mode 100644 index 000000000000..56d91da3130a --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/ctc5236-clks.h @@ -0,0 +1,25 @@ +/* + * ctc5236 clock tree IDs + * + * (C) Copyright 2004-2017 Centec Networks (suzhou) Co., LTD. + * + * Jay Cao + * + * 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 version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __CTC5236_CLKS_H +#define __CTC5236_CLKs_H + +#define CLKID_UNUSED 0 +#define CLKID_PLL_FIXED 1 +#define CLKID_UART0 2 + +#endif /* __CTC5236_CLKS_H */ diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc-dts/ctc5236-clock.dtsi b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/ctc5236-clock.dtsi new file mode 100644 index 000000000000..ae6b00c00ba2 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/ctc5236-clock.dtsi @@ -0,0 +1,63 @@ +/* + * dts file for Centec CTC5236(TsingMa) SoC + * + * (C) Copyright 2004-2017 Centec Networks (suzhou) Co., LTD. + * + * Jay Cao + * + * 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. + */ + + osc: oscillator { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <50000000>; + }; + + sup_clk: sup_clk_12m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <1200000000>; + clock-output-names = "sup_clk"; + }; + + uart_clk: uart_clk_20m { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <20000000>; + clock-output-names = "uart_clk"; + }; + + i2c_clk: clkm { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <50000000>; + clock-output-names = "i2c_clk"; + }; + wdog_clk:wdog_clk{ + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <1000000>; + clock-output-names = "wdog_clk"; + }; + timer_clk:timer_clk{ + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <500000000>; + clock-output-names = "timer_clk"; + }; + mmc_clk:mmc_clk{ + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + clock-output-names = "mmc_clk"; + }; + spi_clk:spi_clk{ + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + clock-output-names = "spi_clk"; + }; diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc-dts/ctc5236.dtsi b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/ctc5236.dtsi new file mode 100644 index 000000000000..d92000612c29 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/ctc5236.dtsi @@ -0,0 +1,376 @@ +/* + * dts file for Centec CTC5236(TsingMa) SoC + * + * (C) Copyright 2004-2017 Centec Networks (suzhou) Co., LTD. + * + * Jay Cao + * + * 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 "arm-gic.h" +#include "ctc5236-clks.h" +#include "../pinctrl-ctc/pinctrl-ctc.h" + +/ { + compatible = "centec,ctc5236"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&gic>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + }; + }; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0 0x000>; + enable-method = "spin-table"; + cpu-release-addr = <0 0x0010fff0>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0 0x001>; + enable-method = "spin-table"; + cpu-release-addr = <0 0x0010fff0>; + }; + }; + + gic: interrupt-controller@31201000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x0 0x31201000 0 0x1000>, + <0x0 0x31202000 0 0x2000>, + <0x0 0x31204000 0 0x2000>, + <0x0 0x31206000 0 0x2000>; + interrupts = ; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + }; + + soc: soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + #include "ctc5236-clock.dtsi" + ocram: sram@00100000 { + compatible = "mmio-sram"; + reg = <0x0 0x00100000 0x0 0x10000>; + }; + + memory-controller@30600000 { + compatible = "ctc,ctc5236-ddr-ctrl"; + reg = <0x0 0x30600000 0x0 0x100000>; + interrupts = ; + }; + + sysctrl: sysctrl@33200000 { + compatible = "ctc,ctc5236-sysctrl", "syscon"; + reg = <0x0 0x33200000 0x0 0x100000>; + little-endian; + }; + + serial0: serial@33000000 { + compatible = "arm,pl011","arm,primecell"; + reg = <0x0 0x33000000 0x0 0x1000>; + interrupts = ; + clocks = <&uart_clk>, <&sup_clk>; + clock-names = "uart_clk", "apb_pclk"; + status="disabled"; + }; + serial1: serial@33001000 { + compatible = "arm,pl011","arm,primecell"; + reg = <0x0 0x33001000 0x0 0x1000>; + interrupts = ; + clocks = <&uart_clk>, <&sup_clk>; + clock-names = "uart_clk", "apb_pclk"; + status="disabled"; + }; + serial2: serial@33002000 { + compatible = "arm,pl011","arm,primecell"; + reg = <0x0 0x33002000 0x0 0x1000>; + interrupts = ; + clocks = <&uart_clk>, <&sup_clk>; + clock-names = "uart_clk", "apb_pclk"; + status="disabled"; + }; + mdio: mdio@33620000 { + compatible = "ctc,mdio"; + reg = <0x0 0x33620000 0x0 0x10000>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + enet0: ethernet@33410000 { + compatible = "ctc,mac"; + device_type = "network"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&gic>; + status = "disabled"; + index = <0x00>; + reg = <0x0 0x33410000 0x0 0x10000>, + <0x0 0x33400000 0x0 0x10000>; + interrupts = , + , + ; + ctc,sysctrl = <&sysctrl>; + }; + + enet1: ethernet@33420000 { + compatible = "ctc,mac"; + device_type = "network"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&gic>; + status = "disabled"; + index = <0x01>; + reg = <0x0 0x33420000 0x0 0x10000>, + <0x0 0x33400000 0x0 0x10000>; + interrupts = , + , + ; + ctc,sysctrl = <&sysctrl>; + }; + + ehci0: usb@30500000 { + compatible = "ctc-ehci"; + reg = <0x0 0x30500000 0x0 0x1000>; + interrupts = ; + status = "disabled"; + }; + + ohci0: usb@30580000 { + compatible = "generic-ohci"; + reg = <0x0 0x30580000 0x0 0x1000>; + interrupts = ; + status = "disabled"; + }; + + spi: spi@33100000 { + compatible = "arm,pl022","arm,primecell"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x33100000 0x0 0x100000>; + clocks = <&spi_clk>, <&sup_clk>; + clock-names = "spi_clk", "apb_pclk"; + num-cs = <4>; + interrupts = ; + ctc,sysctrl = <&sysctrl>; + status ="disabled"; + }; + + qspi: qspi@10000000 { + compatible = "ctc, igdaxi001a-qspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x10000000 0x0 0x10000>; + pclk = <500000000>; + num-cs = <2>; + idle-cycle = <2>; + post-cycle = <1>; + pre-cycle = <2>; + interrupts = ; + status = "disabled"; + }; + switch: switch@31100000 { + compatible = "centec,dal-localbus"; + reg = <0x0 0x31100000 0x0 0x1000>, + <0x0 0x33290000 0x0 0x10000>; + interrupts = , + , + , + , + , + , + , + ; + status ="disabled"; + }; + switch1: switch1@31101000 { + compatible = "centec,switch"; + reg = <0x0 0x31101000 0x0 0x1000>; + status ="disabled"; + }; + + i2c0: i2c0@33700000{ + compatible = "ctc,i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x33700000 0x0 0x1000>; + interrupts = ; + clocks = <&i2c_clk>; + status ="disabled"; + }; + + i2c1: i2c1@33701000{ + compatible = "ctc,i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x33701000 0x0 0x1000>; + interrupts = ; + clocks = <&i2c_clk>; + status ="disabled"; + }; + + pcie: pcie@20000000 { + compatible = "centec,ctc5236-pcie"; + reg = <0x0 0x20000000 0x0 0x10000000 + 0x0 0x30000000 0x0 0x1000>; + reg-names = "cfg", "ctrl"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + interrupt-parent = <&gic>; + interrupts = , + , + ; + interrupt-names = "msi","aer","pme"; + msi-parent = <&pcie>; + bus-range = <0 0xff>; + ranges = <0x43000000 0 0x00000000 0 0x40000000 0 0x40000000>; + num-lanes = <1>; + ctc,sysctrl = <&sysctrl>; + status ="disabled"; + }; + + wtd0: wtd0@33500000{ + compatible = "arm,sp805-wdt", "arm,primecell"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x33500000 0x0 0x1000>; + clocks = <&wdog_clk>, <&sup_clk>; + clock-names = "wdog_clk", "apb_pclk"; + ctc,sysctrl = <&sysctrl>; + interrupts = ; + status="disabled"; + }; + wtd1: wtd1@33501000{ + compatible = "arm,sp805-wdt", "arm,primecell"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x33501000 0x0 0x1000>; + clocks = <&wdog_clk>, <&sup_clk>; + clock-names = "wdog_clk", "apb_pclk"; + ctc,sysctrl = <&sysctrl>; + interrupts = ; + status="disabled"; + }; + + sdhci: sdhci@30400000 { + compatible = "centec,ctc5236-sdhci"; + status = "disabled"; + interrupt-parent = <&gic>; + interrupts = ; + clocks = <&mmc_clk>; + clock-names = "mmc_clk"; + ctc,sysctrl = <&sysctrl>; + reg = <0x0 0x30400000 0x0 0x1000>; + }; + + timer0: timer0@33600000{ + compatible = "snps,dw-apb-timer"; + reg = <0x0 0x33600000 0x0 0x20>; + clocks = <&timer_clk>; + clock-names = "timer"; + interrupts = ; + DivNum = <0x3c>; + status="disabled"; + }; + timer1: timer1@33600020{ + compatible = "snps,dw-apb-timer"; + reg = <0x0 0x33600020 0x0 0x20>; + clocks = <&timer_clk>; + clock-names = "timer"; + interrupts = ; + DivNum = <0x3c>; + status="disabled"; + }; + + pwm: pwm@33200240{ + compatible = "centec-pwm"; + ctc,sysctrl = <&sysctrl>; + #pwm-cells = <2>; + + status="disabled"; + }; + + fan: fan-ctc5236 { + compatible = "fan-ctc5236"; + pwms = <&pwm 0 1000000>, + <&pwm 1 1000000>, + <&pwm 2 1000000>, + <&pwm 3 1000000>; + pwm-names = "pwm1","pwm2","pwm3","pwm4"; + }; + + gpio0: gpio@33610000 { + compatible = "ctc,apb-gpio"; + reg = <0x0 0x33610000 0x0 0x10000>; + #address-cells = <1>; + #size-cells = <0>; + + porta: gpio-port@0 { + compatible = "ctc,apb-gpio-porta"; + gpio-controller; + #gpio-cells = <2>; + ctc,nr-gpios = <16>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + }; + portb: gpio-port@1 { + compatible = "ctc,apb-gpio-portb"; + gpio-controller; + #gpio-cells = <2>; + ctc,nr-gpios = <18>; + reg = <1>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + }; + }; + + pinctrl: pinctrl { + compatible = "ctc,ctc5236-pinctrl"; + #address-cells = <0x2>; + #size-cells = <0x2>; + ctc,pinctrl-bank0 = <16>; + ctc,pinctrl-bank1 = <8>; + ctc,sysctrl = <&sysctrl>; + status = "okay"; + }; + }; + +}; + diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc-dts/e530-ctc5236.dts b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/e530-ctc5236.dts new file mode 100644 index 000000000000..d8544666e2ce --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/e530-ctc5236.dts @@ -0,0 +1,212 @@ +/* + * dts file for Centec CTC5236(TsingMa) SoC E530-24X2C Board + * + * (C) Copyright 2004-2018 Centec Networks (suzhou) Co., LTD. + * + * liuht + * + * 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. + */ + +/dts-v1/; +#include "ctc5236.dtsi" + + +/ { + model = " CTC5236(TsingMa) E530 Board"; + compatible = "ctc5236,e530-ctc5236"; + + memory { + device_type = "memory"; + reg = <0 0x80000000 0x0 0x40000000>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + serial0 = &serial0; + serial1 = &serial1; + ethernet0 = &enet0; + ethernet1 = &enet1; + }; + +}; + +&serial0 { + status = "okay"; +}; + +&serial1 { + status = "okay"; +}; + +&mdio { + status = "okay"; + phy0: ethernet-phy@0 { + index = <0x00>; + reg = <0x00>; + }; +}; + +&enet0 { + status = "okay"; + phy-handle = <&phy0>; + auto-nego-mode= "sgmii-mac"; +}; + +&qspi { + status = "okay"; + + qspiflash: mx25u3235f@0 { + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-cpha; + spi-cpol; + spi-max-frequency = <25000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x300000>; + }; + partition@300000 { + label = "uboot-env"; + reg = <0x300000 0x10000>; + }; + partition@310000 { + label = "system"; + reg = <0x310000 0x10000>; + }; + partition@320000 { + label = "hw-info"; + reg = <0x320000 0x10000>; + }; + }; + }; +}; + +&spi { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&spi_pin>; + + clock0: ad9559@1 { + compatible = "analog,ad9559"; + reg = <1>; + spi-max-frequency = <25000000>; + }; +}; + +&switch { + status = "okay"; +}; + +&switch1 { + status = "okay"; +}; + +&i2c0{ + status = "okay"; + clock-frequency = <400000>; + + eeprom_0:eeprom_0@57 { + compatible = "atmel,24c64"; + reg = <0x57>; + pagesize = <32>; + }; + + rtc_0:rtc_0@32{ + compatible = "sd2405"; + reg = <0x32>; + }; +}; + +&i2c1{ + status = "okay"; + clock-frequency = <400000>; +}; + +&ehci0 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&wtd0{ + status = "okay"; +}; + +&wtd1{ + status = "disabled"; +}; + +&sdhci { + bus-width = <8>; + max-frequency = <100000000>; + non-removable; + no-sd; + no-sdio; + voltage-ranges = <3300 3300>; + status = "okay"; +}; + +&timer0 { + status = "okay"; +}; + +&soc { + ctc-irq@0 { + compatible = "centec,ctc-irq"; + device_type = "ctc-irq"; + interrupt-parent=<&porta>; + interrupts = < 0 IRQ_TYPE_LEVEL_LOW>, + < 1 IRQ_TYPE_LEVEL_LOW>, + <15 IRQ_TYPE_LEVEL_LOW>, + < 6 IRQ_TYPE_LEVEL_HIGH>, + < 7 IRQ_TYPE_LEVEL_HIGH>; + + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pin>; + status = "okay"; +}; + + +&pinctrl { + spi { + spi_pin: spi_pin { + status = "disabled"; + ctc,pins = <0 0 PIN_FUNC_SPI>, + <0 2 PIN_FUNC_SPI>, + <0 3 PIN_FUNC_SPI>, + <0 5 PIN_FUNC_SPI>; + }; + }; + + pwm0 { + pwm0_pin: pwm0_pin { + ctc,pins = <0 8 PIN_FUNC_PWM>, + <0 9 PIN_FUNC_PWM>, + <0 10 PIN_FUNC_PWM>, + <0 11 PIN_FUNC_PWM>, + <0 12 PIN_FUNC_PWM>, + <0 13 PIN_FUNC_PWM>, + <0 14 PIN_FUNC_PWM>, + <0 15 PIN_FUNC_PWM>; + }; + }; +}; diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc-dts/irq.h b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/irq.h new file mode 100644 index 000000000000..33a1003c55aa --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc-dts/irq.h @@ -0,0 +1,19 @@ +/* + * This header provides constants for most IRQ bindings. + * + * Most IRQ bindings include a flags cell as part of the IRQ specifier. + * In most cases, the format of the flags cell uses the standard values + * defined in this header. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H + +#define IRQ_TYPE_NONE 0 +#define IRQ_TYPE_EDGE_RISING 1 +#define IRQ_TYPE_EDGE_FALLING 2 +#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) +#define IRQ_TYPE_LEVEL_HIGH 4 +#define IRQ_TYPE_LEVEL_LOW 8 + +#endif diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc5236-mc/Makefile b/platform/centec-arm64/tsingma-bsp/src/ctc5236-mc/Makefile new file mode 100644 index 000000000000..b31896d1ef26 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc5236-mc/Makefile @@ -0,0 +1 @@ +obj-m = ctc5236-mc.o diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc5236-mc/ctc5236-mc.c b/platform/centec-arm64/tsingma-bsp/src/ctc5236-mc/ctc5236-mc.c new file mode 100644 index 000000000000..55c86b3a5626 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc5236-mc/ctc5236-mc.c @@ -0,0 +1,279 @@ +/* Centec TsingMa Memory Controller Driver + * + * Author: lius + * + * Copyright 2002-2019, Centec Networks (Suzhou) Co., Ltd. + * + * + * 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 + +struct ctc5236_mc { + struct device *dev; + void __iomem *base; + int irq; + +}; + +/* DDR interrupt enable register */ +#define DDR_ERR_INT_EN 0xF0 + +/* DDR interrupt status register */ +#define DDR_ERR_INT_STATUS 0xF4 + +/* over top-bound info register*/ +#define DDR_ERR_INT_OVER_TOPBOUND_L 0xF8 +#define DDR_ERR_INT_OVER_TOPBOUND_H 0xFC + +#define DDR_PORT0_ERR_INT_STATUS 0x1 +#define DDR_PORT1_ERR_INT_STATUS 0x2 +#define DDR_PORT2_ERR_INT_STATUS 0x3 +#define DDR_PORT3_ERR_INT_STATUS 0x4 +#define DDR_ERR_ECC_INT_STATUS 0x10000 +#define DDR_ERR_WR_PORT_REC_UNDERFLOW 0x20000 +#define DDR_ERR_WR_PORT_REC_OVERFLOW 0x40000 +#define DDR_ERR_RD_PORT_REC_UNDERFLOW 0x80000 +#define DDR_ERR_RD_PORT_REC_OVERFLOW 0x100000 + +#define DDR_PORT0_STATUS 0xB0 +#define DDR_PORT1_STATUS 0xB4 +#define DDR_PORT2_STATUS 0xB8 +#define DDR_PORT3_STATUS 0xBC + +#define DDR_ERR_OVER_TOPBOUND 0x20000 +#define DDR_ERR_WCMDQ_OVER 0x40000 +#define DDR_ERR_WCMDQ_UNDER 0x80000 +#define DDR_ERR_WDATAQ_OVER 0x100000 +#define DDR_ERR_WDATAQ_UNDER 0x200000 +#define DDR_ERR_WESPQ_OVER 0x400000 +#define DDR_ERR_WESPQ_UNDER 0x800000 +#define DDR_ERR_WINFOQ_OVER 0x1000000 +#define DDR_ERR_WINFOQ_UNDER 0x2000000 +#define DDR_ERR_RCMDQ_OVER 0x4000000 +#define DDR_ERR_RCMDQ_UNDER 0x8000000 +#define DDR_ERR_RDATAQ_OVER 0x10000000 +#define DDR_ERR_RDATAQ_UNDER 0x20000000 +#define DDR_ERR_RESPQ_OVER 0x40000000 +#define DDR_ERR_RESPQ_UNDER 0x80000000 + +#define DDR_PORT0_BASE 0xB0 +#define DDR_PORT1_BASE 0xB4 +#define DDR_PORT2_BASE 0xB8 +#define DDR_PORT3_BASE 0xBc + +#define DDR_PORT0 0 +#define DDR_PORT1 1 +#define DDR_PORT2 2 +#define DDR_PORT3 3 + +static int port_err_status(int status, int port, void *dev_id) +{ + int id = port; + unsigned long temp = 0; + unsigned int addr_h = 0; + unsigned int addr_l = 0; + struct ctc5236_mc *mci = dev_id; + + /*the reason of port interrupt */ + if (status & DDR_ERR_OVER_TOPBOUND) { + /* get low 32-bit address */ + addr_l = readl(mci->base + DDR_ERR_INT_OVER_TOPBOUND_L); + /* get high 2-bit address */ + addr_h = readl(mci->base + DDR_ERR_INT_OVER_TOPBOUND_H); + temp = (addr_l | (((unsigned long)((addr_h >> 12) & 0x3)) << 32) + ); + + pr_emerg("ERROR:port%d is out of top-bound range!\n" + "The error address is 0x%p\n", + id, (void *)temp); + } + + if (status & DDR_ERR_WCMDQ_OVER) + pr_err("ERROR:port%d write command queue is overflow!\n", id); + + if (status & DDR_ERR_WCMDQ_UNDER) + pr_err("ERROR:port%d write command queue is underflow!\n", id); + + if (status & DDR_ERR_WDATAQ_OVER) + pr_err("ERROR:port%d write data queue is overflow!\n", id); + + if (status & DDR_ERR_WDATAQ_UNDER) + pr_err("ERROR:port%d write data queue is underflow!\n", id); + + if (status & DDR_ERR_WESPQ_OVER) + pr_err("ERROR:port%d write response queue is overflow!\n", id); + + if (status & DDR_ERR_WESPQ_UNDER) + pr_err("ERROR:port%d write response queue is underflow!\n", id); + + if (status & DDR_ERR_WINFOQ_OVER) + pr_err("ERROR:port%d write info queue is overflow!\n", id); + + if (status & DDR_ERR_WINFOQ_UNDER) + pr_err("ERROR:port%d write info queue is underflow!\n", id); + + if (status & DDR_ERR_RCMDQ_OVER) + pr_err("ERROR:port%d read command queue is overflow!\n", id); + + if (status & DDR_ERR_RCMDQ_UNDER) + pr_err("ERROR:port%d read command queue is underflow!\n", id); + + if (status & DDR_ERR_RDATAQ_OVER) + pr_err("ERROR:port%d read data queue is overflow!\n", id); + + if (status & DDR_ERR_RDATAQ_UNDER) + pr_err("ERROR:port%d read data queue is underflow!\n", id); + + if (status & DDR_ERR_RESPQ_OVER) + pr_err("ERROR:port%d read response queue is overflow!\n", id); + + if (status & DDR_ERR_RESPQ_UNDER) + pr_err("ERROR:port%d read response queue is underflow!\n", id); + + return 1; +} + +static irqreturn_t ctc_mc_err_handler(int irq, void *dev_id) +{ + struct ctc5236_mc *mci = dev_id; + unsigned int status; + unsigned int ret = 0; + + /* get interrupt status */ + status = readl(mci->base + DDR_ERR_INT_STATUS); + + if (status & DDR_PORT0_ERR_INT_STATUS) { + ret = readl(mci->base + DDR_PORT0_BASE); + port_err_status(ret, DDR_PORT0, mci); + } + + if (status & DDR_PORT1_ERR_INT_STATUS) { + ret = readl(mci->base + DDR_PORT1_BASE); + port_err_status(ret, DDR_PORT1, mci); + } + + if (status & DDR_PORT2_ERR_INT_STATUS) { + ret = readl(mci->base + DDR_PORT2_BASE); + port_err_status(ret, DDR_PORT2, mci); + } + + if (status & DDR_PORT3_ERR_INT_STATUS) { + ret = readl(mci->base + DDR_PORT3_BASE); + port_err_status(ret, DDR_PORT3, mci); + } + + if (status & DDR_ERR_ECC_INT_STATUS) + pr_err("ERROR:The ecc more than 1-bit error !\n"); + + if (status & DDR_ERR_WR_PORT_REC_UNDERFLOW) + pr_err("ERROR:MPARB wr_port_rec FIFO is underflow!\n"); + + if (status & DDR_ERR_WR_PORT_REC_OVERFLOW) + pr_err("ERROR:MPARB wr_port_rec FIFO is overflow!\n"); + + if (status & DDR_ERR_RD_PORT_REC_UNDERFLOW) + pr_err("ERROR:MPARB rd_port_rec FIFO is underflow!\n"); + + if (status & DDR_ERR_RD_PORT_REC_OVERFLOW) + pr_err("ERROR:MPARB rd_port_rec FIFO is underflow!\n"); + + /* disable DDR interrupt */ + writel(0x0, mci->base + DDR_ERR_INT_EN); + + return IRQ_HANDLED; +} + +static const struct of_device_id ctc5236_ddr_ctrl_of_match[] = { + { + .compatible = "ctc,ctc5236-ddr-ctrl", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, ctc5236_ddr_ctrl_of_match); + +static int ctc5236_mc_probe(struct platform_device *pdev) +{ + const struct of_device_id *id; + struct ctc5236_mc *mci; + int ret; + + id = of_match_device(ctc5236_ddr_ctrl_of_match, &pdev->dev); + if (!id) + return -ENODEV; + + mci = kzalloc(sizeof(*mci), GFP_KERNEL); + if (!mci) + return -ENODEV; + + mci->base = devm_ioremap_resource(&pdev->dev, pdev->resource); + if (IS_ERR(mci->base)) + return PTR_ERR(mci->base); + + mci->irq = platform_get_irq(pdev, 0); + ret = + devm_request_irq(&pdev->dev, mci->irq, ctc_mc_err_handler, 0, + dev_name(&pdev->dev), mci); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to request irq %d\n", mci->irq); + goto err; + } + + return 0; + +err: + dev_err(&pdev->dev, "Probe Failed!\n"); + return ret; +} + +static int ctc5236_mc_remove(struct platform_device *pdev) +{ + struct ctc5236_mc *mci = platform_get_drvdata(pdev); + + devm_iounmap(&pdev->dev, mci->base); + devm_free_irq(&pdev->dev, mci->irq, mci); + + kfree(mci); + return 0; +} + +static struct platform_driver ctc5236_mc_driver = { + .probe = ctc5236_mc_probe, + .remove = ctc5236_mc_remove, + .driver = { + .name = "ctc5236_mc", + .of_match_table = ctc5236_ddr_ctrl_of_match, + }, +}; + +static int __init ctc5236_mc_init(void) +{ + return platform_driver_register(&ctc5236_mc_driver); +} + +static void __exit ctc5236_mc_exit(void) +{ + platform_driver_unregister(&ctc5236_mc_driver); +} + +module_init(ctc5236_mc_init); +module_exit(ctc5236_mc_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Centec Network"); +MODULE_DESCRIPTION("Centec TsingMa memory controller driver"); diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc5236_switch/Makefile b/platform/centec-arm64/tsingma-bsp/src/ctc5236_switch/Makefile new file mode 100644 index 000000000000..cb2b8a5e2381 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc5236_switch/Makefile @@ -0,0 +1 @@ +obj-m = ctc5236_switch.o diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc5236_switch/ctc5236_switch.c b/platform/centec-arm64/tsingma-bsp/src/ctc5236_switch/ctc5236_switch.c new file mode 100644 index 000000000000..1cc86667d9b9 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc5236_switch/ctc5236_switch.c @@ -0,0 +1,324 @@ +/* (C) Copyright 2004-2017 Centec Networks (suzhou) Co., LTD. + * Wangyb + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include +#include <../include/ctc5236_switch.h> + +struct ctc_access_t *access; + +#define SWITCH_DTS_OFFSET 0x1000 + +int ctc5236_switch_read(u32 offset, u32 len, u32 *p_value) +{ + union ctc_switch_cmd_status_u_t cmd_status_u; + u32 timeout = 0x6400; + u32 cmd_len = 0; + u8 index = 0; + + if (!p_value) { + pr_err("switch read:value buffer is NULL!\n"); + return -1; + } + + /* switch only have 16 databuf, len must not exceed 16 */ + if (len > 16 || len == 0) { + pr_err("switch read: length error! len = %d\n", len); + return -1; + } + /* cmdDataLen must be power of 2 */ + if ((len & (len - 1)) == 0) { + cmd_len = len; + } else { + cmd_len = len; + do { + cmd_len++; + } while ((cmd_len <= 16) && (cmd_len & (cmd_len - 1))); + } + + /* 1. write CmdStatusReg */ + memset(&cmd_status_u, 0, sizeof(union ctc_switch_cmd_status_u_t)); + cmd_status_u.cmd_status.cmdReadType = 1; + /* normal operate only support 1 entry */ + cmd_status_u.cmd_status.cmdEntryWords = (len == 16) ? 0 : len; + cmd_status_u.cmd_status.cmdDataLen = len; + writel(cmd_status_u.val, &access->cmd_status); + /* 2. write AddrReg */ + writel(offset, &access->addr); + /* 3. polling status and check */ + cmd_status_u.val = readl(&access->cmd_status); + while (!(cmd_status_u.cmd_status.reqProcDone) && (--timeout)) + cmd_status_u.val = readl(&access->cmd_status); + /* 4. check cmd done */ + if (!(cmd_status_u.cmd_status.reqProcDone)) { + pr_err("switch read error! cmd_status = %x\n", + cmd_status_u.val); + return -1; + } + /* 5. check pcie read status */ + if (cmd_status_u.cmd_status.reqProcError != 0) { + pr_err("pci read error! cmd_status = %x, offset = 0x%x\n", + cmd_status_u.val, offset); + return -1; + } + + /* 6. read data from buffer */ + for (index = 0; index < len; index++) + p_value[index] = readl(&access->data[index]); + + return 0; +} + +int ctc5236_switch_write(u32 offset, u32 len, u32 *p_value) +{ + union ctc_switch_cmd_status_u_t cmd_status_u; + u32 timeout = 0x6400; /* need to be confirmed */ + u32 cmd_len = 0; + u8 index = 0; + + if (!p_value) { + pr_err("switch write:value buffer is NULL!\n"); + return -1; + } + + /* switch only have 16 databuf, len must not exceed 16 */ + if (len > 16 || len == 0) { + pr_err("switch write length error! len = %d\n", len); + return -1; + } + + /* cmdDataLen must be power of 2 */ + if ((len & (len - 1)) == 0) { + cmd_len = len; + } else { + cmd_len = len; + do { + cmd_len++; + } while ((cmd_len <= 16) && (cmd_len & (cmd_len - 1))); + } + + /* 1. write CmdStatusReg */ + memset(&cmd_status_u, 0, sizeof(struct ctc_switch_cmd_status_t)); + cmd_status_u.cmd_status.cmdReadType = 0; + cmd_status_u.cmd_status.cmdEntryWords = (len == 16) ? 0 : len; + /* Notice: for 1 entry op, cmdDatalen eq cmdEntryWords, + * but for mutil entry, len = cmd_len + */ + cmd_status_u.cmd_status.cmdDataLen = len; + writel(cmd_status_u.val, &access->cmd_status); + /* 2. write AddrReg */ + writel(offset, &access->addr); + /* 3. write data into databuffer */ + for (index = 0; index < len; index++) + writel(p_value[index], &access->data[index]); + + /* 4. polling status and check */ + cmd_status_u.val = readl(&access->cmd_status); + while (!(cmd_status_u.cmd_status.reqProcDone) && (--timeout)) + cmd_status_u.val = readl(&access->cmd_status); + + /* 5. check cmd done */ + if (!(cmd_status_u.cmd_status.reqProcDone)) { + pr_err("switch write error! cmd_status = %x\n", + cmd_status_u.val); + return -1; + } + + /* 6. check switch read status */ + if (cmd_status_u.cmd_status.reqProcError != 0) { + pr_err("switch write error! cmd_status = %x, offset=0x%x\n", + cmd_status_u.val, offset); + return -1; + } + + return 0; +} + +static int +_sys_tsingma_peri_get_temp_with_code(u8 lchip, u32 temp_code, u32 *p_temp_val) +{ + u16 temp_mapping_tbl[SYS_TSINGMA_TEMP_TABLE_NUM + 1] = { + 804, 801, 798, 795, 792, 790, 787, 784, 781, 778, + 775, 772, 769, 766, 763, 761, 758, 755, 752, 749, + 746, 743, 740, 737, 734, 731, 728, 725, 722, 719, + 717, 714, 711, 708, 705, 702, 699, 696, 693, 690, + 687, 684, 681, 678, 675, 672, 669, 666, 663, 660, + 658, 655, 652, 649, 646, 643, 640, 637, 634, 631, + 628, 625, 622, 619, 616, 613, 610, 607, 604, 601, + 599, 596, 593, 590, 587, 584, 581, 578, 575, 572, + 569, 566, 563, 560, 557, 554, 551, 548, 545, 542, + 540, 537, 534, 531, 528, 525, 522, 519, 516, 513, + 510, 507, 504, 501, 498, 495, 492, 489, 486, 483, + 481, 478, 475, 472, 469, 466, 463, 460, 457, 454, + 451, 448, 445, 442, 439, 436, 433, 430, 427, 424, + 421, 418, 415, 412, 409, 406, 403, 400, 397, 394, + 391, 388, 385, 382, 379, 376, 373, 370, 367, 364, + 361, 358, 355, 352, 349, 346, 343, 340, 337, 334, + 331, 328, 325, 322, 319, 316, 0 + }; + u8 index = 0; + + for (index = 0; index < SYS_TSINGMA_TEMP_TABLE_NUM; index++) { + if ((temp_code <= temp_mapping_tbl[index]) + && (temp_code > temp_mapping_tbl[index + 1])) { + break; + } + } + + if (index < 39) + *p_temp_val = 40 - index + (1 << 31); + else + *p_temp_val = index - 40; + + return 0; +} + +int get_switch_temperature(void) +{ + int temperature; + u32 value, offset, p_value = 0; + u32 timeout = SYS_TSINGMA_SENSOR_TIMEOUT; + + value = 0x310c7; + offset = 0xf * 4; + ctc5236_switch_write(OMCMEM_BASE + offset, 1, &value); + + /*config RTHMC_RST=1 */ + /*mask_write tbl-reg OmcMem 0x10 offset 0x0 0x00000010 0x00000010 */ + offset = 0x10 * 4; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + value |= BIT(4); + ctc5236_switch_write(OMCMEM_BASE + offset, 1, &value); + + /*wait RTHMC_RST=1 */ + /*read tbl-reg OmcMem 0x10 offset 0x0 */ + timeout = SYS_TSINGMA_SENSOR_TIMEOUT; + offset = 0x10 * 4; + while (timeout) { + timeout--; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + if ((BIT(4) & value) == 0) + break; + msleep(1); + } + if (timeout == 0) + return 0xffff; + + /*config ENBIAS=1ENVR=1ENAD=1 */ + /*mask_write tbl-reg OmcMem 0x11 offset 0x0 0x02000007 0x03000007 */ + offset = 0x11 * 4; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + value |= BIT(0) | BIT(1) | BIT(2) | BIT(25); + value &= ~BIT(24); + ctc5236_switch_write(OMCMEM_BASE + offset, 1, &value); + + msleep(1); + + /*set RTHM_MODE=1,RSAMPLE_DONE_INTEN=1,RDUMMY_THMRD=1,RV_SAMPLE_EN=1 */ + /*mask_write tbl-reg OmcMem 0x10 offset 0x0 0x00000203 0x00000003 */ + /*mask_write tbl-reg OmcMem 0x8 offset 0x0 0x00000004 0x00000004 */ + /*mask_write tbl-reg OmcMem 0x12 offset 0x0 0x00000001 0x00000001 */ + offset = 0x10 * 4; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + value |= BIT(0) | BIT(1) | BIT(9); + ctc5236_switch_write(OMCMEM_BASE + offset, 1, &value); + offset = 0x8 * 4; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + value |= BIT(2); + ctc5236_switch_write(OMCMEM_BASE + offset, 1, &value); + offset = 0x12 * 4; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + value |= BIT(0); + ctc5236_switch_write(OMCMEM_BASE + offset, 1, &value); + + /*mask_write tbl-reg OmcMem 0x10 offset 0x0 0x00000001 0x00000001 */ + offset = 0x10 * 4; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + value |= BIT(0); + ctc5236_switch_write(OMCMEM_BASE + offset, 1, &value); + + msleep(1); + + /*mask_write tbl-reg OmcMem 0x12 offset 0x0 0x00000001 0x00000001 */ + offset = 0x12 * 4; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + value |= BIT(0); + ctc5236_switch_write(OMCMEM_BASE + offset, 1, &value); + + /*Wait((mask_read tbl-reg OmcMem 0xa offset 0x0 0x00000004) =1) */ + timeout = SYS_TSINGMA_SENSOR_TIMEOUT; + offset = 0xa * 4; + while (timeout) { + timeout--; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + if (value & BIT(2)) + break; + + msleep(1); + } + if (timeout == 0) + return 0xffff; + + /*mask_write tbl-reg OmcMem 0x11 offset 0x0 0x00000006 0x00000006 */ + offset = 0x11 * 4; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + value |= BIT(1) | BIT(2); + ctc5236_switch_write(OMCMEM_BASE + offset, 1, &value); + + msleep(10); + + /*read-reg OmcMem 0xd offset 0x0 */ + offset = 0xd * 4; + ctc5236_switch_read(OMCMEM_BASE + offset, 1, &value); + _sys_tsingma_peri_get_temp_with_code(0, value, &p_value); + temperature = p_value & ~BIT(31); + if ((p_value & BIT(31)) == 0) + return temperature; + else + return -temperature; + +} +EXPORT_SYMBOL_GPL(get_switch_temperature); + +static int ctc_switch_probe(struct platform_device *pdev) +{ + struct resource *iomem; + void __iomem *ioaddr; + resource_size_t start; + + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + start = iomem->start - 0x1000; + ioaddr = devm_ioremap(&pdev->dev, start, resource_size(iomem)); + if (IS_ERR(ioaddr)) + return -1; + access = (struct ctc_access_t *) ioaddr; + + return 0; +} + +static const struct of_device_id ctc_switch_of_match[] = { + {.compatible = "centec,switch"}, + {} +}; + +MODULE_DEVICE_TABLE(of, ctc_switch_of_match); + +static struct platform_driver ctc_switch_driver = { + .driver = { + .name = "ctc-switch", + .of_match_table = ctc_switch_of_match, + }, + .probe = ctc_switch_probe, +}; + +module_platform_driver(ctc_switch_driver); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:switch"); diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc_wdt/Makefile b/platform/centec-arm64/tsingma-bsp/src/ctc_wdt/Makefile new file mode 100644 index 000000000000..f13d35509ba4 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc_wdt/Makefile @@ -0,0 +1 @@ +obj-m = ctc_wdt.o diff --git a/platform/centec-arm64/tsingma-bsp/src/ctc_wdt/ctc_wdt.c b/platform/centec-arm64/tsingma-bsp/src/ctc_wdt/ctc_wdt.c new file mode 100644 index 000000000000..2beecbb99e70 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctc_wdt/ctc_wdt.c @@ -0,0 +1,398 @@ +/* drivers/char/watchdog/ctc-wdt.c + * + * Watchdog driver for CTC TSINGMA, based on ARM SP805 watchdog module + * + * Copyright (C) 2010 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2 or later. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/sysctl.h" +#include +#include + +/* default timeout in seconds */ +#define DEFAULT_TIMEOUT 60 + +#define MODULE_NAME "ctc-wdt" + +/* watchdog register offsets and masks */ +#define WDTLOAD 0x000 +#define LOAD_MIN 0x00000001 +#define LOAD_MAX 0xFFFFFFFF +#define WDTVALUE 0x004 +#define WDTCONTROL 0x008 + /* control register masks */ +#define INT_ENABLE (1 << 0) +#define RESET_ENABLE (1 << 1) +#define WDTINTCLR 0x00C +#define WDTRIS 0x010 +#define WDTMIS 0x014 +#define INT_MASK (1 << 0) +#define WDTLOCK 0xC00 +#define UNLOCK 0x1ACCE551 +#define LOCK 0x00000001 + +/* TsingMa SoC */ +#define WDTCLK_MAX 500000000UL + +/** + * struct ctc_wdt: ctc wdt device structure + * @wdd: instance of struct watchdog_device + * @lock: spin lock protecting dev structure and io access + * @base: base address of wdt + * @clk: clock structure of wdt + * @adev: amba device structure of wdt + * @status: current status of wdt + * @load_val: load value to be set for current timeout + */ +struct ctc_wdt { + struct watchdog_device wdd; + spinlock_t lock; + void __iomem *base; + struct clk *clk; + struct amba_device *adev; + unsigned int load_val; + struct regmap *regmap_base; +}; + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, + "Set to 1 to keep watchdog running after device release"); + +/* This routine finds load value that will reset system in required timeout */ +static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout) +{ + struct ctc_wdt *wdt = watchdog_get_drvdata(wdd); + u64 load, rate; + + rate = clk_get_rate(wdt->clk); + + /* + * ctc wdt runs counter with given value twice, after the end of first + * counter it gives an interrupt and then starts counter again. If + * interrupt already occurred then it resets the system. This is why + * load is half of what should be required. + */ + load = div_u64(rate, 2) * timeout - 1; + + load = (load > LOAD_MAX) ? LOAD_MAX : load; + load = (load < LOAD_MIN) ? LOAD_MIN : load; + + spin_lock(&wdt->lock); + wdt->load_val = load; + /* roundup timeout to closest positive integer value */ + wdd->timeout = div_u64((load + 1) * 2 + (rate / 2), rate); + spin_unlock(&wdt->lock); + + return 0; +} + +/* returns number of seconds left for reset to occur */ +static unsigned int wdt_timeleft(struct watchdog_device *wdd) +{ + struct ctc_wdt *wdt = watchdog_get_drvdata(wdd); + u64 load, rate; + + rate = clk_get_rate(wdt->clk); + + spin_lock(&wdt->lock); + load = readl_relaxed(wdt->base + WDTVALUE); + + /*If the interrupt is inactive then time left is WDTValue + WDTLoad. */ + if (!(readl_relaxed(wdt->base + WDTRIS) & INT_MASK)) + load += wdt->load_val + 1; + spin_unlock(&wdt->lock); + + return div_u64(load, rate); +} + +static int wdt_config(struct watchdog_device *wdd, bool ping) +{ + struct ctc_wdt *wdt = watchdog_get_drvdata(wdd); + int ret; + + if (!ping) { + + ret = clk_prepare_enable(wdt->clk); + if (ret) { + dev_err(&wdt->adev->dev, "clock enable fail"); + return ret; + } + } + + spin_lock(&wdt->lock); + + writel_relaxed(UNLOCK, wdt->base + WDTLOCK); + writel_relaxed(wdt->load_val, wdt->base + WDTLOAD); + writel_relaxed(INT_MASK, wdt->base + WDTINTCLR); + + if (!ping) + writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + + WDTCONTROL); + + writel_relaxed(LOCK, wdt->base + WDTLOCK); + + /* Flush posted writes. */ + readl_relaxed(wdt->base + WDTLOCK); + spin_unlock(&wdt->lock); + + return 0; +} + +static int wdt_ping(struct watchdog_device *wdd) +{ + return wdt_config(wdd, true); +} + +/* enables watchdog timers reset */ +static int wdt_enable(struct watchdog_device *wdd) +{ + return wdt_config(wdd, false); +} + +/* disables watchdog timers reset */ +static int wdt_disable(struct watchdog_device *wdd) +{ + struct ctc_wdt *wdt = watchdog_get_drvdata(wdd); + + spin_lock(&wdt->lock); + + writel_relaxed(UNLOCK, wdt->base + WDTLOCK); + writel_relaxed(0, wdt->base + WDTCONTROL); + writel_relaxed(LOCK, wdt->base + WDTLOCK); + + /* Flush posted writes. */ + readl_relaxed(wdt->base + WDTLOCK); + spin_unlock(&wdt->lock); + + clk_disable_unprepare(wdt->clk); + + return 0; +} + +static int wdt_restart(struct watchdog_device *wdd, unsigned long action, + void *cmd) +{ + struct ctc_wdt *wdt = watchdog_get_drvdata(wdd); + + spin_lock(&wdt->lock); + + writel_relaxed(UNLOCK, wdt->base + WDTLOCK); + writel_relaxed(0, wdt->base + WDTCONTROL); + writel_relaxed(1, wdt->base + WDTLOAD); + writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL); + writel_relaxed(LOCK, wdt->base + WDTLOCK); + + spin_unlock(&wdt->lock); + + mdelay(100); + + return 0; +} + +static int wdt_set_pretimeout(struct watchdog_device *wdd, + unsigned int new_pretimeout) +{ + struct ctc_wdt *wdt = watchdog_get_drvdata(wdd); + u64 load, rate; + + rate = clk_get_rate(wdt->clk); + + load = rate * new_pretimeout - 1; + load = (load > LOAD_MAX) ? LOAD_MAX : load; + load = (load < LOAD_MIN) ? LOAD_MIN : load; + + spin_lock(&wdt->lock); + wdt->load_val = load; + /* roundup timeout to closest positive integer value */ + wdd->pretimeout = div_u64((load + 1) + (rate / 2), rate); + + spin_unlock(&wdt->lock); + + return 0; +} + +static irqreturn_t ctc_wdt_irq(int irq, void *dev_id) +{ + struct ctc_wdt *wdt = dev_id; + + watchdog_notify_pretimeout(&wdt->wdd); + + return IRQ_HANDLED; +} + +static const struct watchdog_info wdt_info = { + .options = + WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | + WDIOF_PRETIMEOUT, + .identity = MODULE_NAME, +}; + +static const struct watchdog_ops wdt_ops = { + .owner = THIS_MODULE, + .start = wdt_enable, + .stop = wdt_disable, + .ping = wdt_ping, + .set_timeout = wdt_setload, + .get_timeleft = wdt_timeleft, + .restart = wdt_restart, + .set_pretimeout = wdt_set_pretimeout, +}; + +static int ctc_wdt_probe(struct amba_device *adev, const struct amba_id *id) +{ + struct ctc_wdt *wdt; + int ret = 0; + u64 rate; + unsigned int fdc; + + wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL); + if (!wdt) { + ret = -ENOMEM; + goto err; + } + + wdt->base = devm_ioremap_resource(&adev->dev, &adev->res); + if (IS_ERR(wdt->base)) + return PTR_ERR(wdt->base); + + wdt->clk = devm_clk_get(&adev->dev, NULL); + if (IS_ERR(wdt->clk)) { + dev_warn(&adev->dev, "Clock not found\n"); + ret = PTR_ERR(wdt->clk); + goto err; + } + wdt->regmap_base = syscon_regmap_lookup_by_phandle(adev->dev.of_node, + "ctc,sysctrl"); + if (IS_ERR(wdt->regmap_base)) + return PTR_ERR(wdt->regmap_base); + + /* + * TsingMa SoC wdt reference clock is obtained by clockSub frequency + * division,which is 500Mhz.So we need to set the frequency division + * register according to the configured clock. + */ + + rate = clk_get_rate(wdt->clk); + if (rate < 0 || rate > WDTCLK_MAX) { + dev_err(&adev->dev, "Clock out of range\n"); + goto err; + } + + fdc = div_u64(WDTCLK_MAX, rate); + regmap_write(wdt->regmap_base, offsetof(struct SysCtl_regs, SysWdt0Cnt), + fdc); + regmap_write(wdt->regmap_base, offsetof(struct SysCtl_regs, SysWdt1Cnt), + fdc); + wdt->adev = adev; + wdt->wdd.info = &wdt_info; + wdt->wdd.ops = &wdt_ops; + wdt->wdd.parent = &adev->dev; + + spin_lock_init(&wdt->lock); + watchdog_set_nowayout(&wdt->wdd, nowayout); + watchdog_set_drvdata(&wdt->wdd, wdt); + wdt_setload(&wdt->wdd, DEFAULT_TIMEOUT); + ret = devm_request_irq(&adev->dev, adev->irq[0], ctc_wdt_irq, + 0, "ctc-wdt", wdt); + if (ret < 0) { + dev_err(&adev->dev, "devm_request_irq() failed: %d\n", ret); + goto err; + } + ret = watchdog_register_device(&wdt->wdd); + if (ret) { + dev_err(&adev->dev, "watchdog_register_device() failed: %d\n", + ret); + goto err; + } + amba_set_drvdata(adev, wdt); + + dev_info(&adev->dev, "registration successful\n"); + return 0; + +err: + dev_err(&adev->dev, "Probe Failed!!!\n"); + return ret; +} + +static int ctc_wdt_remove(struct amba_device *adev) +{ + struct ctc_wdt *wdt = amba_get_drvdata(adev); + + watchdog_unregister_device(&wdt->wdd); + watchdog_set_drvdata(&wdt->wdd, NULL); + + return 0; +} + +static int __maybe_unused ctc_wdt_suspend(struct device *dev) +{ + struct ctc_wdt *wdt = dev_get_drvdata(dev); + + if (watchdog_active(&wdt->wdd)) + return wdt_disable(&wdt->wdd); + + return 0; +} + +static int __maybe_unused ctc_wdt_resume(struct device *dev) +{ + struct ctc_wdt *wdt = dev_get_drvdata(dev); + + if (watchdog_active(&wdt->wdd)) + return wdt_enable(&wdt->wdd); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(ctc_wdt_dev_pm_ops, ctc_wdt_suspend, ctc_wdt_resume); + +static struct amba_id ctc_wdt_ids[] = { + /* Centec TsingMa SoC WDT ID */ + { + .id = 0x001bb824, + .mask = 0x00ffffff, + }, + {0, 0}, +}; + +MODULE_DEVICE_TABLE(amba, ctc_wdt_ids); + +static struct amba_driver ctc_wdt_driver = { + .drv = { + .name = MODULE_NAME, + .pm = &ctc_wdt_dev_pm_ops, + }, + .id_table = ctc_wdt_ids, + .probe = ctc_wdt_probe, + .remove = ctc_wdt_remove, +}; + +module_amba_driver(ctc_wdt_driver); + +MODULE_AUTHOR("lius "); +MODULE_DESCRIPTION("ARM CTC Watchdog Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/tsingma-bsp/src/ctcmac/Makefile b/platform/centec-arm64/tsingma-bsp/src/ctcmac/Makefile new file mode 100644 index 000000000000..f29ac076955d --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctcmac/Makefile @@ -0,0 +1,3 @@ +KBUILD_EXTRA_SYMBOLS = /sonic/platform/centec-arm64/tsingma-bsp/src/ctc5236_switch/Module.symvers + +obj-m = ctcmac.o ctcmac_test.o ctc5236_mdio.o diff --git a/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctc5236_mdio.c b/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctc5236_mdio.c new file mode 100644 index 000000000000..c176e0cfbc86 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctc5236_mdio.c @@ -0,0 +1,195 @@ +/* Centec cpu_mac Ethernet Driver -- cpu_mac controller implementation + * Provides Bus interface for MIIM regs + * + * Author: liuht + * + * Copyright 2002-2018, Centec Networks (Suzhou) Co., Ltd. + * + * + * 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 +#include +#include +#include +#include +#include + +#include + +#include "ctcmac.h" +#include "ctcmac_reg.h" + +struct ctc_mdio_priv { + void __iomem *map; + struct mdio_soc_regs *mdio_reg; +}; + +static int ctc_mdio_write(struct mii_bus *bus, int mii_id, int reg, u16 value) +{ + int ret = 0; + u32 cmd = 0; + u32 tmp = 0; + struct ctc_mdio_priv *priv = (struct ctc_mdio_priv *)bus->priv; + + cmd = CTCMAC_MDIO_CMD_REGAD(reg) | CTCMAC_MDIO_CMD_PHYAD(mii_id) + | CTCMAC_MDIO_CMD_OPCODE(1) | CTCMAC_MDIO_CMD_DATA(value); + + writel(cmd, &priv->mdio_reg->mdio_soc_cmd_0[0]); + writel(1, &priv->mdio_reg->mdio_soc_cmd_0[1]); + + ret = readl_poll_timeout(&priv->mdio_reg->mdio_soc_status_0, + tmp, tmp & CTCMAC_MDIO_STAT(1), 1000, 10000); + + if (ret < 0) + return -1; + + return 0; +} + +static int ctc_mdio_read(struct mii_bus *bus, int mii_id, int reg) +{ + int ret = 0; + u32 cmd = 0; + u32 status; + int value = 0; + struct ctc_mdio_priv *priv = (struct ctc_mdio_priv *)bus->priv; + + cmd = CTCMAC_MDIO_CMD_REGAD(reg) | CTCMAC_MDIO_CMD_PHYAD(mii_id) + | CTCMAC_MDIO_CMD_OPCODE(2); + + writel(cmd, &priv->mdio_reg->mdio_soc_cmd_0[0]); + writel(1, &priv->mdio_reg->mdio_soc_cmd_0[1]); + + ret = readl_poll_timeout(&priv->mdio_reg->mdio_soc_status_0, + status, status & CTCMAC_MDIO_STAT(1), 1000, + 10000); + if (ret < 0) { + pr_err("ctc_mdio_read1\n"); + return -1; + } + + value = (readl(&priv->mdio_reg->mdio_soc_status_0) & 0xffff); + + return value; +} + +static int ctc_mdio_reset(struct mii_bus *bus) +{ + struct ctc_mdio_priv *priv = (struct ctc_mdio_priv *)bus->priv; + + writel(0x91f, &priv->mdio_reg->mdio_soc_cfg_0); + + return 0; +} + +static const struct of_device_id ctc_mdio_match[] = { + { + .compatible = "ctc,mdio", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, ctc_mdio_match); + +static int ctc_mdio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct resource res; + struct ctc_mdio_priv *priv; + struct mii_bus *new_bus; + int err; + + new_bus = mdiobus_alloc_size(sizeof(*priv)); + if (!new_bus) + return -ENOMEM; + + priv = new_bus->priv; + new_bus->name = "CTC MII Bus", new_bus->read = &ctc_mdio_read; + new_bus->write = &ctc_mdio_write; + new_bus->reset = &ctc_mdio_reset; + + err = of_address_to_resource(np, 0, &res); + if (err < 0) { + pr_err("Of address to resource fail %d!\n", err); + goto error; + } + + snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s@%llx", np->name, + (unsigned long long)res.start); + + priv->map = of_iomap(np, 0); + if (!priv->map) { + err = -ENOMEM; + pr_err("of iomap fail %d!\n", err); + goto error; + } + priv->mdio_reg = (struct mdio_soc_regs *)priv->map; + new_bus->parent = &pdev->dev; + platform_set_drvdata(pdev, new_bus); + + err = of_mdiobus_register(new_bus, np); + if (err) { + pr_err("register mdio bus fail %d!\n", err); + goto error; + } + + return 0; + +error: + if (priv->map) + iounmap(priv->map); + + kfree(new_bus); + + return err; +} + +static int ctc_mdio_remove(struct platform_device *pdev) +{ + struct device *device = &pdev->dev; + struct mii_bus *bus = dev_get_drvdata(device); + struct ctc_mdio_priv *priv = bus->priv; + + mdiobus_unregister(bus); + + iounmap(priv->map); + mdiobus_free(bus); + + return 0; +} + +static struct platform_driver ctc_mdio_driver = { + .driver = { + .name = "ctc_mdio", + .of_match_table = ctc_mdio_match, + }, + .probe = ctc_mdio_probe, + .remove = ctc_mdio_remove, +}; + +module_platform_driver(ctc_mdio_driver); + +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac.c b/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac.c new file mode 100644 index 000000000000..6e267ed8fb42 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac.c @@ -0,0 +1,2697 @@ +/* Centec cpu_mac Ethernet Driver -- cpu_mac controller implementation + * Provides Bus interface for MIIM regs + * + * Author: liuht + * + * Copyright 2002-2018, Centec Networks (Suzhou) Co., Ltd. + * + * + * 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 +#include +#include +#include + +#include +#include "../pinctrl-ctc/pinctrl-ctc.h" +#include "../include/sysctl.h" +#include +#include +#include +#include "../include/ctc5236_switch.h" +#include +#include "ctcmac.h" +#include "ctcmac_reg.h" + +static int ctcmac_alloc_skb_resources(struct net_device *ndev); +static int ctcmac_free_skb_resources(struct ctcmac_private *priv); +static void cpumac_start(struct ctcmac_private *priv); +static void cpumac_halt(struct ctcmac_private *priv); +static void ctcmac_hw_init(struct ctcmac_private *priv); +static spinlock_t global_reglock __aligned(SMP_CACHE_BYTES); +static int g_reglock_init_done; +static int g_mac_unit_init_done; +static struct regmap *regmap_base; +static struct ctcmac_pkt_stats g_pkt_stats[2]; + +static const char ctc_stat_gstrings[][ETH_GSTRING_LEN] = { + "RX-bytes-good-ucast", + "RX-frame-good-ucast", + "RX-bytes-good-mcast", + "RX-frame-good-mcast", + "RX-bytes-good-bcast", + "RX-frame-good-bcast", + "RX-bytes-good-pause", + "RX-frame-good-pause", + "RX-bytes-good-pfc", + "RX-frame-good-pfc", + "RX-bytes-good-control", + "RX-frame-good-control", + "RX-bytes-fcs-error", + "RX-frame-fcs-error", + "RX-bytes-mac-overrun", + "RX-frame-mac-overrun", + "RX-bytes-good-63B", + "RX-frame-good-63B", + "RX-bytes-bad-63B", + "RX-frame-bad-63B", + "RX-bytes", + "RX-frame", + "RX-bytes-bad", + "RX-frame-bad", + "RX-bytes-good-jumbo", + "RX-frame-good-jumbo", + "RX-bytes-bad-jumbo", + "RX-frame-bad-jumbo", + "RX-bytes-64B", + "RX-frame-64B", + "RX-bytes-127B", + "RX-frame-127B", + "RX-bytes-255B", + "RX-frame-255B", + "RX-bytes-511B", + "RX-frame-511B", + "RX-bytes-1023B", + "RX-frame-1023B", + "RX-bytes", + "RX-frame", + "TX-bytes-ucast", + "TX-frame-ucast", + "TX-bytes-mcast", + "TX-frame-mcast", + "TX-bytes-bcast", + "TX-frame-bcast", + "TX-bytes-pause", + "TX-frame-pause", + "TX-bytes-control", + "TX-frame-control", + "TX-bytes-fcs-error", + "TX-frame-fcs-error", + "TX-bytes-underrun", + "TX-frame-underrun", + "TX-bytes-63B", + "TX-frame-63B", + "TX-bytes-64B", + "TX-frame-64B", + "TX-bytes-127B", + "TX-frame-127B", + "TX-bytes-255B", + "TX-frame-255B", + "TX-bytes-511B", + "TX-frame-511B", + "TX-bytes-1023B", + "TX-frame-1023B", + "TX-bytes-mtu1", + "TX-frame-mtu1", + "TX-bytes-mtu2", + "TX-frame-mtu2", + "TX-bytes-jumbo", + "TX-frame-jumbo", + "mtu1", + "mtu2", +}; + +static void clrsetbits(unsigned __iomem *addr, u32 clr, u32 set) +{ + writel((readl(addr) & ~(clr)) | (set), addr); +} + +static inline u32 ctcmac_regr(unsigned __iomem *addr) +{ + u32 val; + + val = readl(addr); + return val; +} + +static inline void ctcmac_regw(unsigned __iomem *addr, u32 val) +{ + writel(val, addr); +} + +static inline int ctcmac_rxbd_unused(struct ctcmac_priv_rx_q *rxq) +{ + /* left one rx desc unused */ + if (rxq->next_to_clean > rxq->next_to_use) + return rxq->next_to_clean - rxq->next_to_use - 1; + + return rxq->rx_ring_size + rxq->next_to_clean - rxq->next_to_use - 1; +} + +static int ctcmac_alloc_tx_queues(struct ctcmac_private *priv) +{ + int i; + + for (i = 0; i < priv->num_tx_queues; i++) { + priv->tx_queue[i] = kzalloc(sizeof(*priv->tx_queue[i]), + GFP_KERNEL); + if (!priv->tx_queue[i]) + return -ENOMEM; + + priv->tx_queue[i]->tx_skbuff = NULL; + priv->tx_queue[i]->qindex = i; + priv->tx_queue[i]->dev = priv->ndev; + spin_lock_init(&priv->tx_queue[i]->txlock); + } + return 0; +} + +static int ctcmac_alloc_rx_queues(struct ctcmac_private *priv) +{ + int i; + + for (i = 0; i < priv->num_rx_queues; i++) { + priv->rx_queue[i] = kzalloc(sizeof(*priv->rx_queue[i]), + GFP_KERNEL); + if (!priv->rx_queue[i]) + return -ENOMEM; + + priv->rx_queue[i]->qindex = i; + priv->rx_queue[i]->ndev = priv->ndev; + } + return 0; +} + +static void ctcmac_unmap_io_space(struct ctcmac_private *priv) +{ + if (priv->iobase) + iounmap(priv->iobase); +} + +static void ctcmac_free_tx_queues(struct ctcmac_private *priv) +{ + int i; + + for (i = 0; i < priv->num_tx_queues; i++) + kfree(priv->tx_queue[i]); +} + +static void ctcmac_free_rx_queues(struct ctcmac_private *priv) +{ + int i; + + for (i = 0; i < priv->num_rx_queues; i++) + kfree(priv->rx_queue[i]); +} + +static void ctcmac_free_dev(struct ctcmac_private *priv) +{ + if (priv->ndev) + free_netdev(priv->ndev); +} + +static int ctcmac_fixed_phy_link_update(struct net_device *dev, + struct fixed_phy_status *status) +{ + u32 mon = 0; + struct ctcmac_private *priv; + + if (!dev) + return 0; + + priv = netdev_priv(dev); + + if (priv->interface != PHY_INTERFACE_MODE_SGMII) + return 0; + + mon = readl(&priv->cpumac_reg->cpu_mac_sgmii_mon[0]); + if (priv->autoneg_mode == CTCMAC_AUTONEG_DISABLE) { + if ((mon & 0x100) == 0x100) + status->link = 1; + else + status->link = 0; + + } else { + if ((mon & CSM_ANST_MASK) == 6) + status->link = 1; + else + status->link = 0; + } + + return 0; +} + +static int ctcmac_of_init(struct platform_device *ofdev, + struct net_device **pdev) +{ + int err = 0, index; + const char *ctype, *automode, *dfe; + struct net_device *dev = NULL; + struct ctcmac_private *priv = NULL; + unsigned int num_tx_qs, num_rx_qs; + struct device_node *np = ofdev->dev.of_node; + + num_tx_qs = CTCMAC_TX_QUEUE_MAX; + num_rx_qs = CTCMAC_RX_QUEUE_MAX; + + *pdev = alloc_etherdev_mq(sizeof(*priv), num_tx_qs); + dev = *pdev; + if (!dev) + return -ENOMEM; + + priv = netdev_priv(dev); + priv->ndev = dev; + priv->ofdev = ofdev; + priv->dev = &ofdev->dev; + priv->dev->coherent_dma_mask = DMA_BIT_MASK(64); + priv->num_tx_queues = num_tx_qs; + netif_set_real_num_rx_queues(dev, num_rx_qs); + priv->num_rx_queues = num_rx_qs; + + if (ctcmac_alloc_tx_queues(priv)) + goto fail; + + if (ctcmac_alloc_rx_queues(priv)) + goto fail; + + /* init cpumac_reg/cpumac_mem/cpumac_unit address */ + priv->iobase = of_iomap(np, 0); + priv->cpumac_reg = priv->iobase + CPUMAC_REG_BASE; + priv->cpumac_mem = priv->iobase + CPUMAC_MEM_BASE; + priv->cpumacu_reg = of_iomap(np, 1) + CPUMACUNIT_REG_BASE; + + /* Get cpu_mac index */ + err = of_property_read_u32(np, "index", &index); + if (err == 0) + priv->index = index; + else + priv->index = 0; + + /* Get interface type, CTC5236 only support PHY_INTERFACE_MODE_SGMII */ + err = of_property_read_string(np, "phy-connection-type", &ctype); + if (err == 0 && !strncmp(ctype, "mii", 3)) { + priv->interface = PHY_INTERFACE_MODE_MII; + priv->supported = SUPPORTED_10baseT_Full; + } else { + priv->interface = PHY_INTERFACE_MODE_SGMII; + priv->supported = CTCMAC_SUPPORTED; + } + + err = of_property_read_string(np, "auto-nego-mode", &automode); + if (err == 0 && !strncmp(automode, "disable", 7)) + priv->autoneg_mode = CTCMAC_AUTONEG_DISABLE; + else if (err == 0 && !strncmp(automode, "sgmii-mac", 9)) + priv->autoneg_mode = CTCMAC_AUTONEG_MAC_M; + else if (err == 0 && !strncmp(automode, "sgmii-phy", 9)) + priv->autoneg_mode = CTCMAC_AUTONEG_PHY_M; + else if (err == 0 && !strncmp(automode, "1000base-x", 10)) + priv->autoneg_mode = CTCMAC_AUTONEG_1000BASEX_M; + else + priv->autoneg_mode = CTCMAC_AUTONEG_MAC_M; + + err = of_property_read_string(np, "dfe", &dfe); + if (err == 0 && !strncmp(dfe, "enable", 6)) + priv->dfe_enable = 1; + else + priv->dfe_enable = 0; + + priv->phy_node = of_parse_phandle(np, "phy-handle", 0); + /* In the case of a fixed PHY, the DT node associated + * to the PHY is the Ethernet MAC DT node. + */ + if (!priv->phy_node && of_phy_is_fixed_link(np)) { + err = of_phy_register_fixed_link(np); + if (err) + return -1; + + priv->phy_node = of_node_get(np); + } + /* mapping from hw irq to sw irq */ + priv->irqinfo[CTCMAC_NORMAL].irq = irq_of_parse_and_map(np, 0); + priv->irqinfo[CTCMAC_FUNC].irq = irq_of_parse_and_map(np, 1); + + return 0; + +fail: + ctcmac_unmap_io_space(priv); + ctcmac_free_tx_queues(priv); + ctcmac_free_rx_queues(priv); + ctcmac_free_dev(priv); + + return -1; +} + +int startup_ctcmac(struct net_device *ndev) +{ + struct ctcmac_private *priv = netdev_priv(ndev); + int err; + + ctcmac_hw_init(priv); + + err = ctcmac_alloc_skb_resources(ndev); + if (err) + return err; + + /* barrier */ + smp_mb__before_atomic(); + clear_bit(CTCMAC_DOWN, &priv->state); + /* barrier */ + smp_mb__after_atomic(); + + cpumac_start(priv); + /* force link state update after mac reset */ + priv->oldlink = 0; + priv->oldspeed = 0; + priv->oldduplex = -1; + + phy_start(ndev->phydev); + + napi_enable(&priv->napi_rx); + napi_enable(&priv->napi_tx); + + netif_tx_wake_all_queues(ndev); + + return 0; +} + +void stop_ctcmac(struct net_device *ndev) +{ + struct ctcmac_private *priv = netdev_priv(ndev); + + /* disable ints and gracefully shut down Rx/Tx DMA */ + cpumac_halt(priv); + + netif_tx_stop_all_queues(ndev); + + /* barrier */ + smp_mb__before_atomic(); + set_bit(CTCMAC_DOWN, &priv->state); + /* barrier */ + smp_mb__after_atomic(); + napi_disable(&priv->napi_rx); + napi_disable(&priv->napi_tx); + phy_stop(ndev->phydev); + ctcmac_free_skb_resources(priv); +} + +static void ctcmac_reset(struct net_device *ndev) +{ + struct ctcmac_private *priv = netdev_priv(ndev); + + while (test_and_set_bit_lock(CTCMAC_RESETTING, &priv->state)) + cpu_relax(); + + stop_ctcmac(ndev); + startup_ctcmac(ndev); + clear_bit_unlock(CTCMAC_RESETTING, &priv->state); +} + +/* ctcmac_reset_task gets scheduled when a packet has not been + * transmitted after a set amount of time. + * For now, assume that clearing out all the structures, and + * starting over will fix the problem. + */ +static void ctcmac_reset_task(struct work_struct *work) +{ + struct ctcmac_private *priv = container_of(work, struct ctcmac_private, + reset_task); + ctcmac_reset(priv->ndev); +} + +/* get the rxdesc number that was used by cpu_mac but has not been + * handled by CPU + */ +static int ctcmac_rxbd_recycle(struct ctcmac_private *priv, int qidx) +{ + u32 count; + + if (qidx) { + count = readl(&priv->cpumac_reg->cpu_mac_desc_mon[2]); + return count & 0xffff; + } + + count = readl(&priv->cpumac_reg->cpu_mac_desc_mon[1]); + + return (count >> 16) & 0xffff; +} + +static int ctcmac_rxbd_usable(struct ctcmac_private *priv, int qidx) +{ + return (readl(&priv->cpumac_reg->cpu_mac_desc_mon[0]) >> (qidx * 16)) & + 0xffff; +} + +/* get the txdesc number that was used by cpu_mac + * but has not been handled by CPU + */ +static int ctcmac_txbd_used_untreated(struct ctcmac_private *priv) +{ + u32 count; + + count = readl(&priv->cpumac_reg->cpu_mac_desc_mon[2]); + + return (count >> 16) & 0xffff; +} + +/* Add rx buffer data to skb fragment */ +static bool ctcmac_add_rx_frag(struct ctcmac_rx_buff *rxb, u32 lstatus, + struct sk_buff *skb, bool first) +{ + struct page *page = rxb->page; + unsigned int size = + (lstatus & CPU_MAC_DESC_INTF_W1_DESC_SIZE_MASK) >> 8; + int data_size; + + /* Remove the CRC from the packet length */ + if (lstatus & CPU_MAC_DESC_INTF_W1_DESC_EOP) + data_size = size - 4; + else + data_size = size; + + if (likely(first)) { + skb_put(skb, data_size); + } else { + if (data_size > 0) + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, + rxb->page_offset, data_size, + CTCMAC_RXB_TRUESIZE); + + if (data_size < 0) + pskb_trim(skb, skb->len + data_size); + } + + /* try reuse page */ + if (unlikely(page_count(page) != 1)) + return false; + + /* change offset to the other half */ + rxb->page_offset ^= CTCMAC_RXB_TRUESIZE; + + if (data_size > 0) + page_ref_inc(page); + + return true; +} + +/* Reused page that has been release by CPU */ +static void ctcmac_reuse_rx_page(struct ctcmac_priv_rx_q *rxq, + struct ctcmac_rx_buff *old_rxb) +{ + struct ctcmac_rx_buff *new_rxb; + u16 nta = rxq->next_to_alloc; + + new_rxb = &rxq->rx_buff[nta]; + + /* find next buf that can reuse a page */ + nta++; + rxq->next_to_alloc = (nta < rxq->rx_ring_size) ? nta : 0; + + /* copy page reference */ + *new_rxb = *old_rxb; + + /* sync for use by the device */ + dma_sync_single_range_for_device(rxq->dev, old_rxb->dma, + old_rxb->page_offset, + CTCMAC_RXB_TRUESIZE, DMA_FROM_DEVICE); +} + +/* Handle the rx buffer that has been used by cpu_mac */ +static struct sk_buff *ctcmac_get_next_rxbuff(struct ctcmac_priv_rx_q *rx_queue, + u32 lstatus, struct sk_buff *skb) +{ + struct ctcmac_rx_buff *rxb = + &rx_queue->rx_buff[rx_queue->next_to_clean]; + struct page *page = rxb->page; + bool first = false; + + if (likely(!skb)) { + void *buff_addr = page_address(page) + rxb->page_offset; + + skb = build_skb(buff_addr, CTCMAC_SKBFRAG_SIZE); + if (unlikely(!skb)) + return NULL; + first = true; + } + + dma_sync_single_range_for_cpu(rx_queue->dev, rxb->dma, rxb->page_offset, + CTCMAC_RXB_TRUESIZE, DMA_FROM_DEVICE); + + if (ctcmac_add_rx_frag(rxb, lstatus, skb, first)) { + /* reuse the free half of the page */ + ctcmac_reuse_rx_page(rx_queue, rxb); + } else { + /* page cannot be reused, unmap it */ + dma_unmap_page(rx_queue->dev, rxb->dma, + PAGE_SIZE, DMA_FROM_DEVICE); + } + + /* clear rxb content */ + rxb->page = NULL; + + return skb; +} + +static void ctcmac_process_frame(struct net_device *ndev, struct sk_buff *skb) +{ + skb->protocol = eth_type_trans(skb, ndev); +} + +int ctc_mac_hss_write(struct ctcmac_private *priv, u8 addr, u8 data, + u8 serdes_id) +{ + u8 accid; + int timeout = 2000; + u32 val = 0, mon = 0; + + if (serdes_id == 0) + accid = 3; + else if (serdes_id == 1) + accid = 4; + else + accid = 0; + val = addr | (data << 8) | (accid << 24) | (1 << 31); + writel(val, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + + while (timeout--) { + mon = + readl(&priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_result); + if (mon & CPU_MAC_UNIT_HSS_REG_ACC_RESULT_W0_HSS_ACC_ACK_MASK) + break; + mdelay(1); + } + if (!(mon & CPU_MAC_UNIT_HSS_REG_ACC_RESULT_W0_HSS_ACC_ACK_MASK)) { + dev_err(&priv->ndev->dev, + "wait for write ack cpu_mac_unit_hss_reg_acc_result:0x%x addr 0x%x data 0x%x serdes %d fail!\n", + readl(&priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_result), + addr, data, serdes_id); + return -1; + } + + return 0; +} + +int ctc_mac_hss_read(struct ctcmac_private *priv, u8 addr, u8 *data, + u8 serdes_id) +{ + u8 accid; + u32 val = 0; + u32 mon = 0; + int timeout = 2000; + + if (serdes_id == 0) + accid = 3; + else if (serdes_id == 1) + accid = 4; + else + accid = 0; + val = addr | (1 << 16) | (accid << 24) | (1 << 31); + + writel(val, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + + while (timeout--) { + mon = + readl(&priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_result); + if (mon & CPU_MAC_UNIT_HSS_REG_ACC_RESULT_W0_HSS_ACC_ACK_MASK) + break; + mdelay(1); + } + if (!(mon & CPU_MAC_UNIT_HSS_REG_ACC_RESULT_W0_HSS_ACC_ACK_MASK)) { + dev_err(&priv->ndev->dev, + "wait for read ack cpu_mac_unit_hss_reg_acc_result:0x%x fail!\n", + readl(&priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_result)); + *data = 0x0; + return -1; + } + + val = readl(&priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_result); + *data = val & 0xff; + + return 0; +} + +static int ctcmac_maximize_margin_of_cmu_tempearture_ramp(struct ctcmac_private + *priv) +{ + u8 val, ctune, delta, ctune_cal; + int tmpr = 0; + + tmpr = get_switch_temperature(); + if (tmpr == 0xffff) { + pr_err("get temperature fail!\n"); + return -1; + } + + ctc_mac_hss_read(priv, 0x1c, &val, 2); + val &= 0xf8; + val |= 0x4; + ctc_mac_hss_write(priv, 0x1c, val, 2); + + /*r_pll_dlol_en 0x30[0] write 1 enable pll lol status output */ + ctc_mac_hss_read(priv, 0x30, &val, 2); + val |= BIT(0); + ctc_mac_hss_write(priv, 0x30, val, 2); + + if (tmpr <= -20) + delta = 2; + else if (tmpr <= 60) + delta = 1; + else + delta = 0; + + /*read_vco_ctune 0xe0[3:0] read ctune raw value */ + ctc_mac_hss_read(priv, 0xe0, &val, 2); + ctune = val & 0xf; + ctune_cal = ctune - delta; + /*cfg_vco_byp_ctune 0x07[3:0] write (ctune - delta) */ + ctc_mac_hss_read(priv, 0x7, &val, 2); + val &= 0xf0; + val |= ctune_cal; + ctc_mac_hss_write(priv, 0x7, val, 2); + + /*cfg_vco_cal_byp 0x06[7] write 1 */ + ctc_mac_hss_read(priv, 0x6, &val, 2); + val |= BIT(7); + ctc_mac_hss_write(priv, 0x6, val, 2); + + /*for temperature -40~-20C, try (ctune-1) if (ctune-2) causes lol */ + mdelay(10); + /*pll_lol_udl 0xe0[4] read 0 */ + val = ctc_mac_hss_read(priv, 0xe0, &val, 2); + if ((0 != (val & BIT(4))) && delta == 2) { + /*cfg_vco_byp_ctune 0x07[3:0] write (ctune - 1) */ + ctune_cal = ctune - 1; + ctc_mac_hss_read(priv, 0x7, &val, 2); + val &= 0xf0; + val |= ctune_cal; + ctc_mac_hss_write(priv, 0x7, val, 2); + } + /*check pll lol */ + mdelay(10); + /*pll_lol_udl 0xe0[4] read 0 */ + val = ctc_mac_hss_read(priv, 0xe0, &val, 2); + if (0 != (val & BIT(4))) { + pr_err("maximize margin of cmu tempearture ramp fail!\n"); + return -1; + } + + return 0; +} + +/* serdes init flow */ +static int ctc_mac_serdes_init(struct ctcmac_private *priv) +{ + int ret = 0; + u32 status; + int delay_ms = 10; + + if (priv->dfe_enable) { + /* reset serdes */ + writel(0x4610b003, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[5]); + writel(0x4610b003, + &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[11]); + writel(0x83806000, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[0]); + writel(0x28061800, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[2]); + writel(0x0066c03a, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[6]); + writel(0x28061810, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[8]); + writel(0x0066c03a, + &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[12]); + } else { + /* reset serdes */ + writel(0x4610a805, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[5]); + writel(0x4610a805, + &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[11]); + writel(0x83806000, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[0]); + writel(0x28061800, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[2]); + writel(0x0026c02a, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[6]); + writel(0x28061810, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[8]); + writel(0x0026c02a, + &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[12]); + } + + /* offset0 bit1 BlkRstN */ + writel(0x83806002, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[0]); + mdelay(delay_ms); + + writel(0x80002309, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x80000842, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8000ea45, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + + /* serdes 0 init */ + writel(0x83000a05, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83002008, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300640f, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83000214, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83008015, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83000116, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83001817, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83003018, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83000e24, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83008226, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83001f27, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83002028, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83002829, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300302a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83002038, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300223a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300523b, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83002040, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300f141, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300014a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300e693, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + + /* serdes 1 init */ + writel(0x84000a05, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84002008, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400640f, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84000214, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84008015, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84000116, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84001817, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84003018, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84000e24, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84008226, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84001f27, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84002028, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84002829, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400302a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84002038, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400223a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400523b, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84002040, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400f141, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400014a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400e693, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + + ctc_mac_hss_write(priv, 0x0c, 0x21, 0); + ctc_mac_hss_write(priv, 0x0f, 0x64, 0); + ctc_mac_hss_write(priv, 0x1a, 0x06, 0); + ctc_mac_hss_write(priv, 0x91, 0x30, 0); + ctc_mac_hss_write(priv, 0x48, 0x20, 0); + ctc_mac_hss_write(priv, 0x90, 0x30, 0); + //ctc_mac_hss_write(priv, 0x9e, 0x36, 0); + //ctc_mac_hss_write(priv, 0x93, 0x76, 0); + ctc_mac_hss_write(priv, 0x14, 0x01, 0); + ctc_mac_hss_write(priv, 0x26, 0x81, 0); + + ctc_mac_hss_write(priv, 0x0c, 0x21, 1); + ctc_mac_hss_write(priv, 0x0f, 0x64, 1); + ctc_mac_hss_write(priv, 0x1a, 0x06, 1); + ctc_mac_hss_write(priv, 0x91, 0x30, 1); + ctc_mac_hss_write(priv, 0x48, 0x20, 1); + ctc_mac_hss_write(priv, 0x90, 0x30, 1); + //ctc_mac_hss_write(priv, 0x9e, 0x36, 1); + //ctc_mac_hss_write(priv, 0x93, 0x76, 1); + ctc_mac_hss_write(priv, 0x14, 0x01, 1); + ctc_mac_hss_write(priv, 0x26, 0x81, 1); + + /* serdes post release */ + writel(0x83806003, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[0]); + writel(0x83826003, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[0]); + + writel(0x28061801, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[2]); + writel(0x28061c01, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[2]); + writel(0x28071c01, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[2]); + + writel(0x28061811, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[8]); + writel(0x28061c11, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[8]); + writel(0x28071c11, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[8]); + + ret = + readl_poll_timeout(&priv->cpumacu_reg->cpu_mac_unit_hss_mon[1], + status, + status & + CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_DFE_RST_DONE, + 1000, 2000000); + if (ret) { + netdev_dbg(priv->ndev, + "%s:wait for hss reset done fail with cpu_mac_unit_hss_mon[1]:0x%x\n", + priv->ndev->name, + readl(&priv->cpumacu_reg->cpu_mac_unit_hss_mon[1])); + } + mdelay(delay_ms); + + ctcmac_maximize_margin_of_cmu_tempearture_ramp(priv); + + return 0; +} + +/* Hardware init flow */ +static void ctcmac_hw_init(struct ctcmac_private *priv) +{ + int i; + u32 val; + int use_extram = 0; + + /* two cpumac access the same cpumac unit register */ + spin_lock_irq(&global_reglock); + if (priv->index == 0) { + /* release cpu_mac_0 */ + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_reset_ctl, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_BASE, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC0); + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_reset_ctl, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC0, 0); + } else { + /* release cpu_mac_0 */ + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_reset_ctl, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_BASE, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC1); + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_reset_ctl, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC1, 0); + } + + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_ts_cfg, + 0, CPU_MAC_UNIT_TS_CFG_W0_CFG_FORCE_S_AND_NS_EN); + + spin_unlock_irq(&global_reglock); + mdelay(10); + + /* init cpu_mac */ + clrsetbits(&priv->cpumac_reg->cpu_mac_init, 0, + CPU_MAC_INIT_DONE_W0_INIT_DONE); + udelay(1); + + if (priv->interface == PHY_INTERFACE_MODE_SGMII) { + /* switch to sgmii and enable auto nego */ + val = readl(&priv->cpumac_reg->cpu_mac_sgmii_auto_neg_cfg); + val &= ~(CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_ENABLE_MASK + | CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_MODE_MASK); + val |= (CSA_SGMII_MD_MASK | CSA_EN); + writel(val, &priv->cpumac_reg->cpu_mac_sgmii_auto_neg_cfg); + } + + if (priv->autoneg_mode == CTCMAC_AUTONEG_DISABLE) { + clrsetbits(&priv->cpumac_reg->cpu_mac_sgmii_auto_neg_cfg, + CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_ENABLE, 0); + + } else { + val = readl(&priv->cpumac_reg->cpu_mac_sgmii_auto_neg_cfg); + val &= ~CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_MODE_MASK; + val |= + (priv->autoneg_mode << 2 | + CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_ENABLE); + writel(val, &priv->cpumac_reg->cpu_mac_sgmii_auto_neg_cfg); + } + /* disable rx link filter */ + clrsetbits(&priv->cpumac_reg->cpu_mac_sgmii_cfg[0], + CPU_MAC_SGMII_CFG_W0_CFG_MII_RX_LINK_FILTER_EN, 0); + /* ignore tx event */ + clrsetbits(&priv->cpumac_reg->cpu_mac_sgmii_cfg[0], + 0, CPU_MAC_SGMII_CFG_W0_CFG_TX_EVEN_IGNORE); + + clrsetbits(&priv->cpumac_reg->cpu_mac_axi_cfg, + 0, CPU_MAC_AXI_CFG_W0_CFG_AXI_RD_D_WORD_SWAP_EN); + clrsetbits(&priv->cpumac_reg->cpu_mac_axi_cfg, + 0, CPU_MAC_AXI_CFG_W0_CFG_AXI_WR_D_WORD_SWAP_EN); + + /* drop over size packet */ + clrsetbits(&priv->cpumac_reg->cpu_mac_gmac_cfg[0], + 0, CPU_MAC_GMAC_CFG_W0_CFG_RX_OVERRUN_DROP_EN + | CPU_MAC_GMAC_CFG_W0_CFG_RX_OVERSIZE_DROP_EN); + + /* not strip 4B crc when send packet */ + clrsetbits(&priv->cpumac_reg->cpu_mac_gmac_cfg[2], + CPU_MAC_GMAC_CFG_W2_CFG_TX_STRIP_CRC_EN, 0); + + /* enable cut-through mode */ + clrsetbits(&priv->cpumac_reg->cpu_mac_gmac_cfg[2], + 0, CPU_MAC_GMAC_CFG_W2_CFG_TX_CUT_THROUGH_EN); + + for (i = 0; i < priv->num_tx_queues; i++) { + if (priv->tx_queue[i]->tx_ring_size > + CTCMAC_INTERNAL_RING_SIZE) { + use_extram = 1; + break; + } + } + + for (i = 0; i < priv->num_rx_queues; i++) { + if (priv->rx_queue[i]->rx_ring_size > + CTCMAC_INTERNAL_RING_SIZE) { + use_extram = 1; + break; + } + } + + if (use_extram) { + spin_lock_irq(&global_reglock); + /* enable external SRAM to store rx/tx desc, + * support max 1023*3 desc + */ + regmap_read(regmap_base, + offsetof(struct SysCtl_regs, SysMemCtl), &val); + val |= SYS_MEM_CTL_W0_CFG_RAM_MUX_EN; + regmap_write(regmap_base, + offsetof(struct SysCtl_regs, SysMemCtl), val); + spin_unlock_irq(&global_reglock); + + if (priv->index == 0) { + ctcmac_regw(&priv->cpumac_reg->cpu_mac_ext_ram_cfg[1], + CTCMAC0_EXSRAM_BASE); + } else { + ctcmac_regw(&priv->cpumac_reg->cpu_mac_ext_ram_cfg[1], + CTCMAC1_EXSRAM_BASE); + } + ctcmac_regw(&priv->cpumac_reg->cpu_mac_ext_ram_cfg[0], + CTCMAC_TX_RING_SIZE); + clrsetbits(&priv->cpumac_reg->cpu_mac_ext_ram_cfg[0], 0, + CPU_MAC_EXT_RAM_CFG_W0_CFG_EXT_RAM_EN); + } else { + /* disable external SRAM to store rx/tx desc, + * support max 64*3 desc + */ + clrsetbits(&priv->cpumac_reg->cpu_mac_ext_ram_cfg[0], + CPU_MAC_EXT_RAM_CFG_W0_CFG_EXT_RAM_EN, 0); + spin_lock_irq(&global_reglock); + + regmap_read(regmap_base, + offsetof(struct SysCtl_regs, SysMemCtl), &val); + val &= ~SYS_MEM_CTL_W0_CFG_RAM_MUX_EN; + regmap_write(regmap_base, + offsetof(struct SysCtl_regs, SysMemCtl), val); + spin_unlock_irq(&global_reglock); + } + + if (priv->int_type == CTCMAC_INT_DESC) { + val = CPU_MAC_DESC_CFG_W0_CFG_TX_DESC_ACK_EN + | (CTCMAC_DESC_INT_NUM << 16) + | (CTCMAC_DESC_INT_NUM << 8) + | (CTCMAC_DESC_INT_NUM << 0); + ctcmac_regw(&priv->cpumac_reg->cpu_mac_desc_cfg[0], val); + } else { + val = CPU_MAC_DESC_CFG_W0_CFG_TX_DESC_DONE_INTR_EOP_EN + | CPU_MAC_DESC_CFG_W0_CFG_RX_DESC_DONE_INTR_EOP_EN + | CPU_MAC_DESC_CFG_W0_CFG_TX_DESC_ACK_EN; + ctcmac_regw(&priv->cpumac_reg->cpu_mac_desc_cfg[0], val); + } + + /* clear all interrupt */ + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_func[1], 0xffffffff); + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_normal[1], 0xffffffff); + /* mask all interrupt */ + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_func[2], 0xffffffff); + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_normal[2], 0xffffffff); +} + +static int ctcmac_wait_for_linkup(struct ctcmac_private *priv) +{ + int timeout = 3000; + u32 mon = 0; + + if (priv->autoneg_mode == CTCMAC_AUTONEG_DISABLE) { + /* wait for linkup */ + while (timeout--) { + mon = readl(&priv->cpumac_reg->cpu_mac_sgmii_mon[0]); + if ((mon & 0x100) == 0x100) + break; + + mdelay(1); + } + if ((mon & 0x100) != 0x100) { + pr_err("Error! when phy link up, link status %d is not right.\n", + mon); + return -1; + } + + } else { + /* wait for sgmii auto nego complete */ + while (timeout--) { + mon = readl(&priv->cpumac_reg->cpu_mac_sgmii_mon[0]); + if ((mon & CSM_ANST_MASK) == 6) + break; + + mdelay(1); + } + + if ((mon & CSM_ANST_MASK) != 6) { + pr_err("Error! when phy link up, auto-neg status %d is not right.\n", + mon); + return -1; + } + } + + return 0; +} + +/* update cpumac speed when phy linkup speed changed */ +static noinline void ctcmac_update_link_state(struct ctcmac_private *priv, + struct phy_device *phydev) +{ + u32 cfg_rep, cfg_smp; + int speed = phydev->speed; + + if (priv->interface != PHY_INTERFACE_MODE_SGMII) + return; + + if (netif_msg_link(priv)) + netdev_dbg(priv->ndev, "link up speed is %d\n", speed); + + if (phydev->link) { + cfg_rep = readl(&priv->cpumac_reg->cpu_mac_sgmii_cfg[0]); + cfg_smp = readl(&priv->cpumac_reg->cpu_mac_sgmii_cfg[1]); + cfg_rep &= ~CSC_REP_MASK; + cfg_smp &= ~CSC_SMP_MASK; + if (speed == 1000) { + cfg_rep |= CSC_1000M; + cfg_smp |= CSC_1000M; + } else if (speed == 100) { + cfg_rep |= CSC_100M; + cfg_smp |= CSC_100M; + } else if (speed == 10) { + cfg_rep |= CSC_10M; + cfg_smp |= CSC_10M; + } else { + return; + } + writel(cfg_rep, &priv->cpumac_reg->cpu_mac_sgmii_cfg[0]); + writel(cfg_smp, &priv->cpumac_reg->cpu_mac_sgmii_cfg[1]); + + ctcmac_wait_for_linkup(priv); + + if (!priv->oldlink) + priv->oldlink = 1; + + } else { + priv->oldlink = 0; + priv->oldspeed = 0; + priv->oldduplex = -1; + } +} + +static void adjust_link(struct net_device *dev) +{ + struct ctcmac_private *priv = netdev_priv(dev); + struct phy_device *phydev = dev->phydev; + + if (unlikely(phydev->link != priv->oldlink || + (phydev->link && (phydev->duplex != priv->oldduplex || + phydev->speed != priv->oldspeed)))) + ctcmac_update_link_state(priv, phydev); +} + +/* Initializes driver's PHY state, and attaches to the PHY. + * Returns 0 on success. + */ +static int ctcmac_init_phy(struct net_device *dev) +{ + int err; + struct ctcmac_private *priv = netdev_priv(dev); + phy_interface_t interface; + struct phy_device *phydev; + + priv->oldlink = 0; + priv->oldspeed = 0; + priv->oldduplex = -1; + + interface = priv->interface; + + phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, 0, + interface); + if (!phydev) { + dev_err(&dev->dev, "could not attach to PHY\n"); + return -ENODEV; + } + if (of_phy_is_fixed_link(priv->phy_node)) { + err = fixed_phy_set_link_update(dev->phydev, + ctcmac_fixed_phy_link_update); + if (err) + dev_err(&priv->ndev->dev, "Set link update fail!\n"); + } + + /* Remove any features not supported by the controller */ + phydev->supported &= priv->supported; + phydev->advertising = phydev->supported; + + return 0; +} + +static irqreturn_t ctcmac_receive(int irq, struct ctcmac_private *priv) +{ + unsigned long flags; + + if (likely(napi_schedule_prep(&priv->napi_rx))) { + /* disable interrupt */ + spin_lock_irqsave(&priv->reglock, flags); + writel(CTCMAC_NOR_RX0_D | CTCMAC_NOR_RX1_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[2]); + spin_unlock_irqrestore(&priv->reglock, flags); + __napi_schedule(&priv->napi_rx); + } else { + /* clear interrupt */ + writel(CTCMAC_NOR_RX0_D | CTCMAC_NOR_RX1_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[1]); + } + + return IRQ_HANDLED; +} + +static irqreturn_t ctcmac_transmit(int irq, struct ctcmac_private *priv) +{ + unsigned long flags; + + if (likely(napi_schedule_prep(&priv->napi_tx))) { + /* disable interrupt */ + spin_lock_irqsave(&priv->reglock, flags); + writel(CTCMAC_NOR_TX_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[2]); + spin_unlock_irqrestore(&priv->reglock, flags); + __napi_schedule(&priv->napi_tx); + + } else { + /* clear interrupt */ + writel(CTCMAC_NOR_TX_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[1]); + } + + return IRQ_HANDLED; +} + +static irqreturn_t ctcmac_func(int irq, void *data) +{ + u32 event, stat, mask; + struct ctcmac_private *priv = (struct ctcmac_private *)data; + + stat = ctcmac_regr(&priv->cpumac_reg->cpu_mac_interrupt_func[0]); + mask = ctcmac_regr(&priv->cpumac_reg->cpu_mac_interrupt_func[2]); + event = stat & ~mask; + + if (netif_msg_intr(priv)) { + netdev_dbg(priv->ndev, + "function interrupt stat 0x%x mask 0x%x\n", stat, + mask); + } + if ((event & CTCMAC_NOR_RX0_D) || (event & CTCMAC_NOR_RX1_D)) + ctcmac_receive(irq, priv); + + if (event & CTCMAC_NOR_TX_D) + ctcmac_transmit(irq, priv); + + return IRQ_HANDLED; +} + +/* not used */ +static irqreturn_t ctcmac_normal(int irq, void *data) //TODO by liuht +{ + u32 stat, mask; + struct ctcmac_private *priv = (struct ctcmac_private *)data; + + stat = ctcmac_regr(&priv->cpumac_reg->cpu_mac_interrupt_func[0]); + mask = ctcmac_regr(&priv->cpumac_reg->cpu_mac_interrupt_func[2]); + + if (netif_msg_intr(priv)) { + netdev_dbg(priv->ndev, "normal interrupt stat 0x%x mask 0x%x\n", + stat, mask); + } + + return IRQ_HANDLED; +} + +static int ctcmac_request_irq(struct ctcmac_private *priv) +{ + int err = 0; + + err = request_irq(priv->irqinfo[CTCMAC_NORMAL].irq, ctcmac_normal, 0, + priv->irqinfo[CTCMAC_NORMAL].name, priv); + if (err < 0) + free_irq(priv->irqinfo[CTCMAC_NORMAL].irq, priv); + enable_irq_wake(priv->irqinfo[CTCMAC_NORMAL].irq); + + err = request_irq(priv->irqinfo[CTCMAC_FUNC].irq, ctcmac_func, 0, + priv->irqinfo[CTCMAC_FUNC].name, priv); + if (err < 0) + free_irq(priv->irqinfo[CTCMAC_FUNC].irq, priv); + enable_irq_wake(priv->irqinfo[CTCMAC_FUNC].irq); + + return err; +} + +static void ctcmac_free_irq(struct ctcmac_private *priv) +{ + free_irq(priv->irqinfo[CTCMAC_NORMAL].irq, priv); + free_irq(priv->irqinfo[CTCMAC_FUNC].irq, priv); +} + +static bool ctcmac_new_page(struct ctcmac_priv_rx_q *rxq, + struct ctcmac_rx_buff *rxb) +{ + struct page *page; + dma_addr_t addr; + + page = dev_alloc_page(); + if (unlikely(!page)) + return false; + + addr = dma_map_page(rxq->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(rxq->dev, addr))) { + __free_page(page); + + return false; + } + + rxb->dma = addr; + rxb->page = page; + rxb->page_offset = 0; + + return true; +} + +static void ctcmac_fill_rxbd(struct ctcmac_private *priv, + struct ctcmac_rx_buff *rxb, int qidx) +{ + u32 desc_cfg_low, desc_cfg_high; + dma_addr_t bufaddr = rxb->dma + rxb->page_offset; + + /* DDR base address is 0 for cpu_mac, but is 0x80000000 for CPU */ + desc_cfg_low = + (bufaddr - CTC_DDR_BASE) & CPU_MAC_DESC_INTF_W0_DESC_ADDR_31_0_MASK; + /* CPU_MAC_DESC_INTF_W1_DESC_SIZE:bit(8) */ + desc_cfg_high = (CTCMAC_RXB_SIZE << 8) | + (((bufaddr - + CTC_DDR_BASE) >> 32) & + CPU_MAC_DESC_INTF_W1_DESC_ADDR_39_32_MASK); + + spin_lock_irq(&priv->reglock); + if (qidx) { + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_1[0], + desc_cfg_low); + /* barrier */ + smp_mb__before_atomic(); + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_1[1], + desc_cfg_high); + + } else { + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_0[0], + desc_cfg_low); + /* barrier */ + smp_mb__before_atomic(); + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_0[1], + desc_cfg_high); + } + + spin_unlock_irq(&priv->reglock); +} + +static void ctcmac_fill_txbd(struct ctcmac_private *priv, + struct ctcmac_desc_cfg *txdesc) +{ + u32 desc_cfg_low, desc_cfg_high; + + desc_cfg_low = txdesc->addr_low; + /* CPU_MAC_DESC_INTF_W1_DESC_SIZE:bit(8) */ + /* CPU_MAC_DESC_INTF_W1_DESC_SOP:bit(22) */ + /* CPU_MAC_DESC_INTF_W1_DESC_EOP:bit(23) */ + desc_cfg_high = txdesc->addr_high | + (txdesc->size << 8) | (txdesc->sop << 22) | (txdesc->eop << 23); + + spin_lock_irq(&priv->reglock); + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_2[0], desc_cfg_low); + /* barrier */ + smp_mb__before_atomic(); + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_2[1], desc_cfg_high); + + spin_unlock_irq(&priv->reglock); +} + +/* reclaim tx desc */ +static void ctcmac_get_txbd(struct ctcmac_private *priv) +{ + u32 lstatus; + + spin_lock_irq(&priv->reglock); + lstatus = ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_2[0]); + /* barrier */ + smp_mb__before_atomic(); + lstatus = ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_2[1]); + spin_unlock_irq(&priv->reglock); +} + +/* reclaim rx desc */ +static void ctcmac_get_rxbd(struct ctcmac_private *priv, u32 *lstatus, + int qidx) +{ + spin_lock_irq(&priv->reglock); + if (qidx) { + ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_1[0]); + *lstatus = + ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_1[1]); + } else { + ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_0[0]); + *lstatus = + ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_0[1]); + } + /* barrier */ + smp_mb__before_atomic(); + + spin_unlock_irq(&priv->reglock); +} + +/* alloc rx buffer for rx desc */ +static void ctcmac_alloc_rx_buffs(struct ctcmac_priv_rx_q *rx_queue, + int alloc_cnt) +{ + int i, j; + int qidx = rx_queue->qindex; + struct ctcmac_rx_buff *rxb; + struct net_device *ndev = rx_queue->ndev; + struct ctcmac_private *priv = netdev_priv(ndev); + + i = rx_queue->next_to_use; + j = rx_queue->next_to_alloc; + rxb = &rx_queue->rx_buff[i]; + + while (alloc_cnt--) { + /* if rx buffer is unmapped, alloc new pages */ + if (unlikely(!rxb->page)) { + if (unlikely(!ctcmac_new_page(rx_queue, rxb))) + break; + if (unlikely(++j == rx_queue->rx_ring_size)) + j = 0; + } + + /* fill rx desc */ + ctcmac_fill_rxbd(priv, rxb, qidx); + rxb++; + + if (unlikely(++i == rx_queue->rx_ring_size)) { + i = 0; + rxb = rx_queue->rx_buff; + } + } + + rx_queue->next_to_use = i; + rx_queue->next_to_alloc = j; +} + +static void ctcmac_alloc_one_rx_buffs(struct ctcmac_priv_rx_q *rx_queue) +{ + int i, j; + int qidx = rx_queue->qindex; + struct ctcmac_rx_buff *rxb; + struct net_device *ndev = rx_queue->ndev; + struct ctcmac_private *priv = netdev_priv(ndev); + + i = rx_queue->next_to_use; + j = rx_queue->next_to_alloc; + rxb = &rx_queue->rx_buff[i]; + + if (unlikely(!rxb->page)) { + if (unlikely(!ctcmac_new_page(rx_queue, rxb))) + return; + if (unlikely(++j == rx_queue->rx_ring_size)) + j = 0; + } + + if (unlikely(++i == rx_queue->rx_ring_size)) + i = 0; + + rx_queue->next_to_use = i; + rx_queue->next_to_alloc = j; + + /* fill rx desc */ + ctcmac_fill_rxbd(priv, rxb, qidx); +} + +static noinline int ctcmac_clean_rx_ring(struct ctcmac_priv_rx_q *rx_queue, + int rx_work_limit) +{ + struct net_device *ndev = rx_queue->ndev; + struct ctcmac_private *priv = netdev_priv(ndev); + int i, howmany = 0; + struct sk_buff *skb = rx_queue->skb; + int cleaned_cnt = ctcmac_rxbd_unused(rx_queue); + unsigned int total_bytes = 0, total_pkts = 0; + int qidx = rx_queue->qindex; + u32 alloc_new; + int budget = rx_work_limit; + + /* Get the first full descriptor */ + i = rx_queue->next_to_clean; + + while (rx_work_limit--) { + u32 lstatus; + + if (!rx_queue->pps_limit) { + if (cleaned_cnt >= CTCMAC_RX_BUFF_ALLOC) { + ctcmac_alloc_rx_buffs(rx_queue, cleaned_cnt); + cleaned_cnt = 0; + } + } else { + alloc_new = rx_queue->token / CTCMAC_TOKEN_PER_PKT; + if (cleaned_cnt >= CTCMAC_RX_BUFF_ALLOC && alloc_new) { + alloc_new = min_t(int, cleaned_cnt, + (int)alloc_new); + ctcmac_alloc_rx_buffs(rx_queue, alloc_new); + rx_queue->token -= + CTCMAC_TOKEN_PER_PKT * alloc_new; + cleaned_cnt -= alloc_new; + } + } + + if (ctcmac_rxbd_recycle(priv, qidx) <= 0) + break; + + ctcmac_get_rxbd(priv, &lstatus, qidx); + + /* fetch next to clean buffer from the ring */ + skb = ctcmac_get_next_rxbuff(rx_queue, lstatus, skb); + if (unlikely(!skb)) + break; + + cleaned_cnt++; + howmany++; + + if (unlikely(++i == rx_queue->rx_ring_size)) + i = 0; + + rx_queue->next_to_clean = i; + + if (netif_msg_rx_status(priv)) { + netdev_dbg(priv->ndev, + "%s rxbuf allocted %d used %d clean %d\n", + ndev->name, rx_queue->next_to_alloc, + rx_queue->next_to_use, + rx_queue->next_to_clean); + } + + /* fetch next buffer if not the last in frame */ + if (!(lstatus & CPU_MAC_DESC_INTF_W1_DESC_EOP)) { + if (rx_queue->pps_limit) + rx_queue->token += CTCMAC_TOKEN_PER_PKT; + continue; + } + + if (unlikely(lstatus & CPU_MAC_DESC_INTF_W1_DESC_ERR)) { + /* discard faulty buffer */ + dev_kfree_skb(skb); + skb = NULL; + rx_queue->stats.rx_dropped++; + if (netif_msg_rx_err(priv)) { + netdev_dbg(priv->ndev, + "%s: Error with rx desc status 0x%x\n", + ndev->name, lstatus); + } + continue; + } + + skb_record_rx_queue(skb, rx_queue->qindex); + ctcmac_process_frame(ndev, skb); + if (!(ndev->flags & IFF_PROMISC) && + skb->pkt_type == PACKET_OTHERHOST) { + /* discard */ + dev_kfree_skb(skb); + skb = NULL; + rx_queue->stats.rx_dropped++; + continue; + } + /* Increment the number of packets */ + total_pkts++; + total_bytes += skb->len + ETH_HLEN; + /* Send the packet up the stack */ + napi_gro_receive(&priv->napi_rx, skb); + + skb = NULL; + } + + /* Store incomplete frames for completion */ + rx_queue->skb = skb; + + rx_queue->stats.rx_packets += total_pkts; + rx_queue->stats.rx_bytes += total_bytes; + + if (!rx_queue->pps_limit && cleaned_cnt) + ctcmac_alloc_rx_buffs(rx_queue, cleaned_cnt); + + if (rx_queue->pps_limit && rx_queue->skb) + return budget; + + return howmany; +} + +static void ctcmac_clean_tx_ring(struct ctcmac_priv_tx_q *tx_queue) +{ + u16 next_to_clean; + int tqi = tx_queue->qindex; + struct sk_buff *skb; + struct netdev_queue *txq; + struct ctcmac_tx_buff *tx_buff; + struct net_device *dev = tx_queue->dev; + struct ctcmac_private *priv = netdev_priv(dev); + + txq = netdev_get_tx_queue(dev, tqi); + next_to_clean = tx_queue->next_to_clean; + while (ctcmac_txbd_used_untreated(priv)) { + ctcmac_get_txbd(priv); + skb = tx_queue->tx_skbuff[next_to_clean]; + dev_kfree_skb_any(skb); + tx_queue->tx_skbuff[next_to_clean] = NULL; + tx_buff = &tx_queue->tx_buff[next_to_clean]; + dma_unmap_single(priv->dev, tx_buff->dma, + tx_buff->len, DMA_TO_DEVICE); + if (tx_buff->alloc) + kfree(tx_buff->vaddr); + if (netif_msg_tx_queued(priv)) { + netdev_dbg(priv->ndev, "%s: clean skbuff id %d\n", + priv->ndev->name, tx_queue->next_to_clean); + } + if ((next_to_clean + 1) >= tx_queue->tx_ring_size) + next_to_clean = 0; + else + next_to_clean++; + + spin_lock(&tx_queue->txlock); + tx_queue->num_txbdfree++; + spin_unlock(&tx_queue->txlock); + } + + /* If we freed a buffer, we can restart transmission, if necessary */ + if (tx_queue->num_txbdfree && + netif_tx_queue_stopped(txq) && + !(test_bit(CTCMAC_DOWN, &priv->state))) { + netif_wake_subqueue(priv->ndev, tqi); + } + + tx_queue->next_to_clean = next_to_clean; +} + +static int ctcmac_poll_rx_sq(struct napi_struct *napi, int budget) +{ + int work_done = 0; + int rx_work_limit; + struct ctcmac_private *priv = + container_of(napi, struct ctcmac_private, napi_rx); + struct ctcmac_priv_rx_q *rxq0 = NULL, *rxq1 = NULL; + + /* clear interrupt */ + writel(CTCMAC_NOR_RX0_D | CTCMAC_NOR_RX1_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[1]); + + rx_work_limit = budget; + rxq0 = priv->rx_queue[0]; + rxq1 = priv->rx_queue[1]; + + work_done += ctcmac_clean_rx_ring(rxq1, rx_work_limit); + rx_work_limit -= work_done; + work_done += ctcmac_clean_rx_ring(rxq0, rx_work_limit); + rx_work_limit -= work_done; + + rxq0->rx_trigger = 0; + rxq1->rx_trigger = 0; + if (work_done < budget) { + napi_complete(napi); + if (!ctcmac_rxbd_usable(priv, 0) && + !ctcmac_rxbd_recycle(priv, 0)) + rxq0->rx_trigger = 1; + + if (!ctcmac_rxbd_usable(priv, 1) && + !ctcmac_rxbd_recycle(priv, 1)) + rxq1->rx_trigger = 1; + + spin_lock_irq(&priv->reglock); + /* enable interrupt */ + writel(CTCMAC_NOR_RX0_D | CTCMAC_NOR_RX1_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[3]); + spin_unlock_irq(&priv->reglock); + } + + return work_done; +} + +static int ctcmac_poll_tx_sq(struct napi_struct *napi, int budget) +{ + struct ctcmac_private *priv = + container_of(napi, struct ctcmac_private, napi_tx); + struct ctcmac_priv_tx_q *tx_queue = priv->tx_queue[0]; + + /* clear interrupt */ + writel(CTCMAC_NOR_TX_D, &priv->cpumac_reg->cpu_mac_interrupt_func[1]); + + ctcmac_clean_tx_ring(tx_queue); + + napi_complete(napi); + /* enable interrupt */ + spin_lock_irq(&priv->reglock); + writel(CTCMAC_NOR_TX_D, &priv->cpumac_reg->cpu_mac_interrupt_func[3]); + spin_unlock_irq(&priv->reglock); + + return 0; +} + +static void ctcmac_free_rx_resources(struct ctcmac_private *priv) +{ + int i, j; + struct ctcmac_priv_rx_q *rx_queue = NULL; + + for (i = 0; i < priv->num_rx_queues; i++) { + rx_queue = priv->rx_queue[i]; + if (rx_queue->skb) + dev_kfree_skb(rx_queue->skb); + + for (j = 0; j < rx_queue->rx_ring_size; j++) { + struct ctcmac_rx_buff *rxb = &rx_queue->rx_buff[j]; + + if (!rxb->page) + continue; + dma_unmap_single(rx_queue->dev, rxb->dma, + PAGE_SIZE, DMA_TO_DEVICE); + __free_page(rxb->page); + } + kfree(rx_queue->rx_buff); + rx_queue->rx_buff = NULL; + } +} + +static int ctcmac_init_rx_resources(struct net_device *ndev) +{ + int i; + struct ctcmac_private *priv = netdev_priv(ndev); + struct device *dev = priv->dev; + struct ctcmac_priv_rx_q *rx_queue = NULL; + + for (i = 0; i < priv->num_rx_queues; i++) { + rx_queue = priv->rx_queue[i]; + rx_queue->ndev = ndev; + rx_queue->dev = dev; + rx_queue->next_to_clean = 0; + rx_queue->next_to_use = 0; + rx_queue->next_to_alloc = 0; + rx_queue->skb = NULL; + rx_queue->rx_trigger = 0; + rx_queue->rx_buff = kcalloc(rx_queue->rx_ring_size, + sizeof(*rx_queue->rx_buff), + GFP_KERNEL); + if (!rx_queue->rx_buff) + goto cleanup; + + ctcmac_alloc_rx_buffs(rx_queue, ctcmac_rxbd_unused(rx_queue)); + } + + return 0; + +cleanup: + ctcmac_free_rx_resources(priv); + + return -1; +} + +static void ctcmac_free_tx_resources(struct ctcmac_private *priv) +{ + int i; + struct ctcmac_priv_tx_q *tx_queue = NULL; + + for (i = 0; i < priv->num_tx_queues; i++) { + struct netdev_queue *txq; + + tx_queue = priv->tx_queue[i]; + txq = netdev_get_tx_queue(tx_queue->dev, tx_queue->qindex); + + kfree(tx_queue->tx_skbuff); + tx_queue->tx_skbuff = NULL; + } +} + +static int ctcmac_init_tx_resources(struct net_device *ndev) +{ + int i; + struct ctcmac_private *priv = netdev_priv(ndev); + struct ctcmac_priv_tx_q *tx_queue = NULL; + + for (i = 0; i < priv->num_tx_queues; i++) { + tx_queue = priv->tx_queue[i]; + tx_queue->num_txbdfree = tx_queue->tx_ring_size; + tx_queue->next_to_clean = 0; + tx_queue->next_to_alloc = 0; + tx_queue->dev = ndev; + tx_queue->tx_skbuff = + kmalloc_array(tx_queue->tx_ring_size, + sizeof(*tx_queue->tx_skbuff), GFP_KERNEL); + + if (!tx_queue->tx_skbuff) + goto cleanup; + } + + return 0; + +cleanup: + ctcmac_free_tx_resources(priv); + + return -1; +} + +static int ctcmac_alloc_skb_resources(struct net_device *ndev) +{ + if (ctcmac_init_rx_resources(ndev)) + return -1; + if (ctcmac_init_tx_resources(ndev)) + return -1; + + return 0; +} + +static int ctcmac_free_skb_resources(struct ctcmac_private *priv) +{ + ctcmac_free_rx_resources(priv); + ctcmac_free_tx_resources(priv); + + return 0; +} + +static void cpumac_start(struct ctcmac_private *priv) +{ + /* 1. enable rx/tx interrupt */ + writel(CTCMAC_NOR_TX_D | CTCMAC_NOR_RX0_D | CTCMAC_NOR_RX1_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[3]); + /* 2. enable rx/tx */ + clrsetbits(&priv->cpumac_reg->cpu_mac_reset, + CPU_MAC_RESET_W0_SOFT_RST_TX, + 0); + clrsetbits(&priv->cpumac_reg->cpu_mac_reset, + CPU_MAC_RESET_W0_SOFT_RST_RX, + 0); + + netif_trans_update(priv->ndev); /* prevent tx timeout */ +} + +static void cpumac_halt(struct ctcmac_private *priv) +{ + /* 1. disable rx/tx interrupt */ + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_func[2], 0xffffffff); + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_normal[2], 0xffffffff); + /* 2. disable rx/tx */ + clrsetbits(&priv->cpumac_reg->cpu_mac_reset, 0, + CPU_MAC_RESET_W0_SOFT_RST_TX); + clrsetbits(&priv->cpumac_reg->cpu_mac_reset, 0, + CPU_MAC_RESET_W0_SOFT_RST_RX); +} + +static void ctcmac_token_timer(struct timer_list *t) +{ + struct ctcmac_private *priv = from_timer(priv, t, token_timer); + struct ctcmac_priv_rx_q *rxq0, *rxq1; + + mod_timer(&priv->token_timer, jiffies + HZ / 10 - 1); + rxq0 = priv->rx_queue[0]; + rxq1 = priv->rx_queue[1]; + rxq0->token = min(rxq0->token + rxq0->pps_limit, rxq0->token_max); + rxq1->token = min(rxq1->token + rxq1->pps_limit, rxq1->token_max); + + if (rxq0->rx_trigger == 1 && (rxq0->token / CTCMAC_TOKEN_PER_PKT)) { + rxq0->rx_trigger = 0; + rxq0->token -= CTCMAC_TOKEN_PER_PKT; + ctcmac_alloc_one_rx_buffs(rxq0); + } + + if (rxq1->rx_trigger == 1 && (rxq1->token / CTCMAC_TOKEN_PER_PKT)) { + rxq1->rx_trigger = 0; + rxq1->token -= CTCMAC_TOKEN_PER_PKT; + ctcmac_alloc_one_rx_buffs(rxq1); + } +} + +static ssize_t rxq0_pps_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ctcmac_private *priv = + (struct ctcmac_private *)dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", priv->rx_queue[0]->pps_limit); +} + +static ssize_t rxq0_pps_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + u32 rq0_pps; + struct ctcmac_private *priv = + (struct ctcmac_private *)dev_get_drvdata(dev); + + if (kstrtou32(buf, 0, &rq0_pps)) { + dev_err(&priv->ndev->dev, "Invalid rx queue0 pps!\n"); + return -1; + } + priv->rx_queue[0]->pps_limit = rq0_pps; + + return count; +} + +static ssize_t rxq1_pps_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ctcmac_private *priv = + (struct ctcmac_private *)dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", priv->rx_queue[1]->pps_limit); +} + +static ssize_t rxq1_pps_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + u32 rq1_pps; + struct ctcmac_private *priv = + (struct ctcmac_private *)dev_get_drvdata(dev); + + if (kstrtou32(buf, 0, &rq1_pps)) { + dev_err(&priv->ndev->dev, "Invalid rx queue0 pps!\n"); + return -1; + } + priv->rx_queue[1]->pps_limit = rq1_pps; + + return count; +} + +static DEVICE_ATTR(rxq0_pps, S_IRUGO | S_IWUSR, rxq0_pps_show, rxq0_pps_store); +static DEVICE_ATTR(rxq1_pps, S_IRUGO | S_IWUSR, rxq1_pps_show, rxq1_pps_store); + +static void ctcmac_pps_init(struct ctcmac_private *priv) +{ + struct ctcmac_priv_rx_q *rxq0, *rxq1; + + rxq0 = priv->rx_queue[0]; + rxq1 = priv->rx_queue[1]; + + if (device_create_file(&priv->ndev->dev, &dev_attr_rxq0_pps) < 0) { + dev_err(&priv->ndev->dev, "create pps limit node fail\n"); + return; + } + if (device_create_file(&priv->ndev->dev, &dev_attr_rxq1_pps) < 0) { + dev_err(&priv->ndev->dev, "create pps limit node fail\n"); + return; + } + + rxq0->pps_limit = 0; + rxq1->pps_limit = 0; +} + +static void ctcmac_pps_disable(struct ctcmac_private *priv) +{ + priv->rx_queue[0]->pps_limit = 0; + priv->rx_queue[1]->pps_limit = 0; + del_timer(&priv->token_timer); +} + +static void ctcmac_pps_cfg(struct ctcmac_private *priv) +{ + struct ctcmac_priv_rx_q *rxq0, *rxq1; + + rxq0 = priv->rx_queue[0]; + rxq1 = priv->rx_queue[1]; + + rxq0->token = 0; + rxq0->token_max = rxq0->pps_limit * CTCMAC_TOKEN_PER_PKT; + rxq0->rx_trigger = 0; + rxq1->token = 0; + rxq1->token_max = rxq1->pps_limit * CTCMAC_TOKEN_PER_PKT; + rxq1->rx_trigger = 0; + if (rxq0->pps_limit || rxq1->pps_limit) { + timer_setup(&priv->token_timer, ctcmac_token_timer, 0); + priv->token_timer.expires = jiffies + HZ / 10; + add_timer(&priv->token_timer); + /* when enable pps ratelimit, must use desc done interrupt */ + priv->int_type = CTCMAC_INT_DESC; + } else { + priv->int_type = CTCMAC_INT_PACKET; + } +} + +static int ctcmac_enet_open(struct net_device *dev) +{ + struct ctcmac_private *priv = netdev_priv(dev); + int err; + + ctcmac_pps_cfg(priv); + + err = ctcmac_init_phy(dev); + if (err) + return err; + + err = ctcmac_request_irq(priv); + if (err) + return err; + + err = startup_ctcmac(dev); + if (err) + return err; + + return 0; +} + +static struct ctcmac_tx_buff *skb_to_txbuff(struct ctcmac_private *priv, + struct sk_buff *skb) +{ + u64 addr, offset; + int frag_index, nr_frags, rq; + skb_frag_t *frag; + struct ctcmac_tx_buff *tx_buff; + struct ctcmac_priv_tx_q *tx_queue = NULL; + + nr_frags = skb_shinfo(skb)->nr_frags; + rq = skb->queue_mapping; + tx_queue = priv->tx_queue[rq]; + + tx_buff = &tx_queue->tx_buff[tx_queue->next_to_alloc]; + addr = (u64)skb->data; + if (!nr_frags && + ((addr & PAGE_MASK) == ((addr + skb_headlen(skb)) & PAGE_MASK))) { + tx_buff->alloc = 0; + tx_buff->vaddr = skb->data; + tx_buff->len = skb_headlen(skb); + tx_buff->dma = + dma_map_single(priv->dev, skb->data, skb_headlen(skb), + DMA_TO_DEVICE); + tx_buff->offset = 0; + + } else { + int alloc_size; + + alloc_size = ALIGN(skb->len, BUF_ALIGNMENT); + tx_buff->alloc = 1; + tx_buff->len = skb->len; + tx_buff->vaddr = kmalloc(alloc_size, GFP_KERNEL); + offset = + (BUF_ALIGNMENT - + (((u64)tx_buff->vaddr) & (BUF_ALIGNMENT - 1))); + if (offset == BUF_ALIGNMENT) + offset = 0; + tx_buff->offset = offset; + memcpy(tx_buff->vaddr + offset, skb->data, skb_headlen(skb)); + offset += skb_headlen(skb); + for (frag_index = 0; frag_index < nr_frags; frag_index++) { + frag = &skb_shinfo(skb)->frags[frag_index]; + memcpy(tx_buff->vaddr + offset, frag, + skb_frag_size(frag)); + offset += skb_frag_size(frag); + } + + tx_buff->dma = + dma_map_single(priv->dev, tx_buff->vaddr, tx_buff->len, + DMA_TO_DEVICE); + } + return tx_buff; +} + +static int ctcmac_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int rq = 0; + unsigned int bytes_sent; + struct netdev_queue *txq; + struct ctcmac_desc_cfg tx_desc; + struct ctcmac_tx_buff *tx_buff; + struct ctcmac_priv_tx_q *tx_queue = NULL; + struct ctcmac_private *priv = netdev_priv(dev); + + rq = skb->queue_mapping; + tx_queue = priv->tx_queue[rq]; + txq = netdev_get_tx_queue(dev, rq); + + /* check if there is space to queue this packet */ + if (tx_queue->num_txbdfree <= 0) { + if (netif_msg_tx_err(priv)) { + netdev_dbg(priv->ndev, + "%s: no space left before send pkt!\n", + priv->ndev->name); + } + /* no space, stop the queue */ + netif_tx_stop_queue(txq); + dev->stats.tx_fifo_errors++; + return NETDEV_TX_BUSY; + } + + /* Update transmit stats */ + bytes_sent = skb->len; + tx_queue->stats.tx_bytes += bytes_sent; + tx_queue->stats.tx_packets++; + + tx_buff = skb_to_txbuff(priv, skb); + tx_queue->tx_skbuff[tx_queue->next_to_alloc] = skb; + tx_desc.sop = 1; + tx_desc.eop = 1; + tx_desc.size = tx_buff->len; + tx_desc.addr_low = (tx_buff->dma + tx_buff->offset - CTC_DDR_BASE) + & CPU_MAC_DESC_INTF_W0_DESC_ADDR_31_0_MASK; + tx_desc.addr_high = + ((tx_buff->dma + tx_buff->offset - CTC_DDR_BASE) >> 32) + & CPU_MAC_DESC_INTF_W1_DESC_ADDR_39_32_MASK; + ctcmac_fill_txbd(priv, &tx_desc); + + if (netif_msg_tx_queued(priv)) { + netdev_dbg(priv->ndev, "%s: alloc skbuff id %d\n", + priv->ndev->name, tx_queue->next_to_alloc); + } + + if (tx_queue->next_to_alloc >= tx_queue->tx_ring_size - 1) + tx_queue->next_to_alloc = 0; + else + tx_queue->next_to_alloc++; + + /* We can work in parallel with 872(), except + * when modifying num_txbdfree. Note that we didn't grab the lock + * when we were reading the num_txbdfree and checking for available + * space, that's because outside of this function it can only grow. + */ + spin_lock_bh(&tx_queue->txlock); + /* reduce TxBD free count */ + tx_queue->num_txbdfree--; + spin_unlock_bh(&tx_queue->txlock); + + /* If the next BD still needs to be cleaned up, then the bds + * are full. We need to tell the kernel to stop sending us stuff. + */ + if (!tx_queue->num_txbdfree) { + netif_tx_stop_queue(txq); + if (netif_msg_tx_err(priv)) { + netdev_dbg(dev, "%s: no space left before send pkt!\n", + priv->ndev->name); + } + dev->stats.tx_fifo_errors++; + } + + return NETDEV_TX_OK; +} + +static int ctcmac_change_mtu(struct net_device *dev, int new_mtu) +{ + struct ctcmac_private *priv = netdev_priv(dev); + int frame_size = new_mtu + ETH_HLEN; + + if (frame_size < 64 || frame_size > CTCMAC_JUMBO_FRAME_SIZE) + return -EINVAL; + + while (test_and_set_bit_lock(CTCMAC_RESETTING, &priv->state)) + cpu_relax(); + + if (dev->flags & IFF_UP) + stop_ctcmac(dev); + + dev->mtu = new_mtu; + + if (dev->flags & IFF_UP) + startup_ctcmac(dev); + + clear_bit_unlock(CTCMAC_RESETTING, &priv->state); + + return 0; +} + +static int ctcmac_set_features(struct net_device *dev, + netdev_features_t features) +{ + return 0; +} + +/* Stops the kernel queue, and halts the controller */ +static int ctcmac_close(struct net_device *dev) +{ + struct ctcmac_private *priv = netdev_priv(dev); + + ctcmac_pps_disable(priv); + cancel_work_sync(&priv->reset_task); + stop_ctcmac(dev); + + /* Disconnect from the PHY */ + phy_disconnect(dev->phydev); + + ctcmac_free_irq(priv); + + return 0; +} + +static void ctcmac_set_multi(struct net_device *dev) +{ +} + +static void ctcmac_timeout(struct net_device *dev) +{ + struct ctcmac_private *priv = netdev_priv(dev); + + dev->stats.tx_errors++; + schedule_work(&priv->reset_task); +} + +static int ctcmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct phy_device *phydev = dev->phydev; + + if (!netif_running(dev)) + return -EINVAL; + + if (!phydev) + return -ENODEV; + + return phy_mii_ioctl(phydev, rq, cmd); +} + +static struct net_device_stats *ctcmac_get_stats(struct net_device *dev) +{ + int qidx; + unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0; + unsigned long tx_packets = 0, tx_bytes = 0; + struct ctcmac_private *priv = netdev_priv(dev); + + for (qidx = 0; qidx < priv->num_rx_queues; qidx++) { + if (!priv->rx_queue[qidx]) + return &dev->stats; + rx_packets += priv->rx_queue[qidx]->stats.rx_packets; + rx_bytes += priv->rx_queue[qidx]->stats.rx_bytes; + rx_dropped += priv->rx_queue[qidx]->stats.rx_dropped; + } + + if (!priv->tx_queue[0]) + return &dev->stats; + + tx_packets = priv->tx_queue[0]->stats.tx_packets; + tx_bytes = priv->tx_queue[0]->stats.tx_bytes; + + dev->stats.rx_packets = rx_packets; + dev->stats.rx_bytes = rx_bytes; + dev->stats.rx_dropped = rx_dropped; + dev->stats.tx_bytes = tx_bytes; + dev->stats.tx_packets = tx_packets; + + return &dev->stats; +} + +static int ctcmac_set_mac_addr(struct net_device *dev, void *p) +{ + eth_mac_addr(dev, p); + return 0; +} + +static void ctcmac_gdrvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + strlcpy(drvinfo->driver, "ctcmac", sizeof(drvinfo->driver)); + strlcpy(drvinfo->version, "v1.0", sizeof(drvinfo->version)); + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info)); +} + +/* Return the length of the register structure */ +static int ctcmac_reglen(struct net_device *dev) +{ + return sizeof(struct cpu_mac_regs); +} + +/* Return a dump of the GFAR register space */ +static void ctcmac_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *regbuf) +{ + int i; + struct ctcmac_private *priv = netdev_priv(dev); + u32 __iomem *theregs = (u32 __iomem *)priv->cpumac_reg; + u32 *buf = (u32 *)regbuf; + + for (i = 0; i < sizeof(struct cpu_mac_regs) / sizeof(u32); i++) + buf[i] = ctcmac_regr(&theregs[i]); +} + +/* Fills in rvals with the current ring parameters. Currently, + * rx, rx_mini, and rx_jumbo rings are the same size, as mini and + * jumbo are ignored by the driver + */ +static void ctcmac_gringparam(struct net_device *dev, + struct ethtool_ringparam *rvals) +{ + struct ctcmac_private *priv = netdev_priv(dev); + struct ctcmac_priv_tx_q *tx_queue = NULL; + struct ctcmac_priv_rx_q *rx_queue = NULL; + + tx_queue = priv->tx_queue[0]; + rx_queue = priv->rx_queue[0]; + + rvals->rx_max_pending = CTCMAC_MAX_RING_SIZE; + rvals->rx_mini_max_pending = CTCMAC_MAX_RING_SIZE; + rvals->rx_jumbo_max_pending = CTCMAC_MAX_RING_SIZE; + rvals->tx_max_pending = CTCMAC_MAX_RING_SIZE; + + /* Values changeable by the user. The valid values are + * in the range 1 to the "*_max_pending" counterpart above. + */ + rvals->rx_pending = rx_queue->rx_ring_size; + rvals->rx_mini_pending = rx_queue->rx_ring_size; + rvals->rx_jumbo_pending = rx_queue->rx_ring_size; + rvals->tx_pending = tx_queue->tx_ring_size; +} + +/* Change the current ring parameters, stopping the controller if + * necessary so that we don't mess things up while we're in motion. + */ +static int ctcmac_sringparam(struct net_device *dev, + struct ethtool_ringparam *rvals) +{ + struct ctcmac_private *priv = netdev_priv(dev); + int err = 0, i; + + if (rvals->rx_pending > CTCMAC_MAX_RING_SIZE) + return -EINVAL; + + if (rvals->tx_pending > CTCMAC_MAX_RING_SIZE) + return -EINVAL; + + while (test_and_set_bit_lock(CTCMAC_RESETTING, &priv->state)) + cpu_relax(); + + if (dev->flags & IFF_UP) + stop_ctcmac(dev); + + /* Change the sizes */ + for (i = 0; i < priv->num_rx_queues; i++) + priv->rx_queue[i]->rx_ring_size = rvals->rx_pending; + + for (i = 0; i < priv->num_tx_queues; i++) + priv->tx_queue[i]->tx_ring_size = rvals->tx_pending; + + /* Rebuild the rings with the new size */ + if (dev->flags & IFF_UP) + err = startup_ctcmac(dev); + + clear_bit_unlock(CTCMAC_RESETTING, &priv->state); + + return err; +} + +static void ctcmac_gpauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) +{ +} + +static int ctcmac_spauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) +{ + return 0; +} + +static void ctcmac_gstrings(struct net_device *dev, u32 stringset, u8 *buf) +{ + memcpy(buf, ctc_stat_gstrings, CTCMAC_STATS_LEN * ETH_GSTRING_LEN); +} + +static int ctcmac_sset_count(struct net_device *dev, int sset) +{ + return CTCMAC_STATS_LEN; +} + +static void ctcmac_fill_stats(struct net_device *netdev, + struct ethtool_stats *dummy, u64 *buf) +{ + u32 mtu; + unsigned long flags; + struct ctcmac_pkt_stats *stats; + struct ctcmac_private *priv = netdev_priv(netdev); + + spin_lock_irqsave(&priv->reglock, flags); + stats = &g_pkt_stats[priv->index]; + stats->rx_good_ucast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_0[0]); + stats->rx_good_ucast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_0[2]); + stats->rx_good_mcast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_1[0]); + stats->rx_good_mcast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_1[2]); + stats->rx_good_bcast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_2[0]); + stats->rx_good_bcast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_2[2]); + stats->rx_good_pause_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_3[0]); + stats->rx_good_pause_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_3[2]); + stats->rx_good_pfc_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_4[0]); + stats->rx_good_pfc_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_4[2]); + stats->rx_good_control_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_5[0]); + stats->rx_good_control_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_5[2]); + stats->rx_fcs_error_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_6[0]); + stats->rx_fcs_error_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_6[2]); + stats->rx_mac_overrun_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_7[0]); + stats->rx_mac_overrun_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_7[2]); + stats->rx_good_63B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_8[0]); + stats->rx_good_63B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_8[2]); + stats->rx_bad_63B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_9[0]); + stats->rx_bad_63B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_9[2]); + stats->rx_good_mtu2B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_10[0]); + stats->rx_good_mtu2B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_10[2]); + stats->rx_bad_mtu2B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_11[0]); + stats->rx_bad_mtu2B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_11[2]); + stats->rx_good_jumbo_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_12[0]); + stats->rx_good_jumbo_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_12[2]); + stats->rx_bad_jumbo_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_13[0]); + stats->rx_bad_jumbo_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_13[2]); + stats->rx_64B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_14[0]); + stats->rx_64B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_14[2]); + stats->rx_127B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_15[0]); + stats->rx_127B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_15[2]); + stats->rx_255B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_16[0]); + stats->rx_255B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_16[2]); + stats->rx_511B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_17[0]); + stats->rx_511B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_17[2]); + stats->rx_1023B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_18[0]); + stats->rx_1023B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_18[2]); + stats->rx_mtu1B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_19[0]); + stats->rx_mtu1B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_19[2]); + stats->tx_ucast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_20[0]); + stats->tx_ucast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_20[2]); + stats->tx_mcast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_21[0]); + stats->tx_mcast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_21[2]); + stats->tx_bcast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_22[0]); + stats->tx_bcast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_22[2]); + stats->tx_pause_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_23[0]); + stats->tx_pause_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_23[2]); + stats->tx_control_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_24[0]); + stats->tx_control_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_24[2]); + stats->tx_fcs_error_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_25[0]); + stats->tx_fcs_error_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_25[2]); + stats->tx_underrun_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_26[0]); + stats->tx_underrun_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_26[2]); + stats->tx_63B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_27[0]); + stats->tx_63B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_27[2]); + stats->tx_64B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_28[0]); + stats->tx_64B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_28[2]); + stats->tx_127B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_29[0]); + stats->tx_127B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_29[2]); + stats->tx_255B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_30[0]); + stats->tx_255B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_30[2]); + stats->tx_511B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_31[0]); + stats->tx_511B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_31[2]); + stats->tx_1023B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_32[0]); + stats->tx_1023B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_32[2]); + stats->tx_mtu1_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_33[0]); + stats->tx_mtu1_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_33[2]); + stats->tx_mtu2_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_34[0]); + stats->tx_mtu2_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_34[2]); + stats->tx_jumbo_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_35[0]); + stats->tx_jumbo_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_35[2]); + mtu = readl(&priv->cpumac_reg->cpu_mac_stats_cfg[1]); + stats->mtu1 = mtu & 0x3fff; + stats->mtu2 = (mtu >> 16) & 0x3fff; + spin_unlock_irqrestore(&priv->reglock, flags); + + memcpy(buf, (void *)stats, sizeof(struct ctcmac_pkt_stats)); +} + +static uint32_t ctcmac_get_msglevel(struct net_device *dev) +{ + struct ctcmac_private *priv = netdev_priv(dev); + + return priv->msg_enable; +} + +static void ctcmac_set_msglevel(struct net_device *dev, uint32_t data) +{ + struct ctcmac_private *priv = netdev_priv(dev); + + priv->msg_enable = data; +} + +static int ctcmac_get_ts_info(struct net_device *dev, + struct ethtool_ts_info *info) +{ + return 0; +} + +const struct ethtool_ops ctcmac_ethtool_ops = { + .get_drvinfo = ctcmac_gdrvinfo, + .get_regs_len = ctcmac_reglen, + .get_regs = ctcmac_get_regs, + .get_link = ethtool_op_get_link, + .get_ringparam = ctcmac_gringparam, + .set_ringparam = ctcmac_sringparam, + .get_pauseparam = ctcmac_gpauseparam, + .set_pauseparam = ctcmac_spauseparam, + .get_strings = ctcmac_gstrings, + .get_sset_count = ctcmac_sset_count, + .get_ethtool_stats = ctcmac_fill_stats, + .get_msglevel = ctcmac_get_msglevel, + .set_msglevel = ctcmac_set_msglevel, + .get_link_ksettings = phy_ethtool_get_link_ksettings, + .set_link_ksettings = phy_ethtool_set_link_ksettings, + .get_ts_info = ctcmac_get_ts_info, +}; + +static const struct net_device_ops ctcmac_netdev_ops = { + .ndo_open = ctcmac_enet_open, + .ndo_start_xmit = ctcmac_start_xmit, + .ndo_stop = ctcmac_close, + .ndo_change_mtu = ctcmac_change_mtu, + .ndo_set_features = ctcmac_set_features, + .ndo_set_rx_mode = ctcmac_set_multi, + .ndo_tx_timeout = ctcmac_timeout, + .ndo_do_ioctl = ctcmac_ioctl, + .ndo_get_stats = ctcmac_get_stats, + .ndo_set_mac_address = ctcmac_set_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + +static int ctcmac_probe(struct platform_device *ofdev) +{ + struct net_device *dev = NULL; + struct ctcmac_private *priv = NULL; + int err = 0, i; + + regmap_base = + syscon_regmap_lookup_by_phandle(ofdev->dev.of_node, "ctc,sysctrl"); + if (IS_ERR(regmap_base)) + return PTR_ERR(regmap_base); + + err = ctcmac_of_init(ofdev, &dev); + if (err) + return err; + + priv = netdev_priv(dev); + SET_NETDEV_DEV(dev, &ofdev->dev); + INIT_WORK(&priv->reset_task, ctcmac_reset_task); + platform_set_drvdata(ofdev, priv); + dev_set_drvdata(&dev->dev, priv); + + dev->base_addr = (unsigned long)priv->iobase; + dev->watchdog_timeo = TX_TIMEOUT; + dev->mtu = CTCMAC_DEFAULT_MTU; + dev->netdev_ops = &ctcmac_netdev_ops; + dev->ethtool_ops = &ctcmac_ethtool_ops; + + netif_napi_add(dev, &priv->napi_rx, ctcmac_poll_rx_sq, + CTCMAC_NAIP_RX_WEIGHT); + netif_napi_add(dev, &priv->napi_tx, ctcmac_poll_tx_sq, + CTCMAC_NAIP_TX_WEIGHT); + + /* Initializing some of the rx/tx queue level parameters */ + for (i = 0; i < priv->num_tx_queues; i++) { + priv->tx_queue[i]->tx_ring_size = CTCMAC_TX_RING_SIZE; + priv->tx_queue[i]->num_txbdfree = CTCMAC_TX_RING_SIZE; + } + + for (i = 0; i < priv->num_rx_queues; i++) + priv->rx_queue[i]->rx_ring_size = CTCMAC_RX_RING_SIZE; + + set_bit(CTCMAC_DOWN, &priv->state); + + if (!g_reglock_init_done) + spin_lock_init(&global_reglock); + + g_reglock_init_done = 1; + + spin_lock_init(&priv->reglock); + /* Carrier starts down, phylib will bring it up */ + netif_carrier_off(dev); + err = register_netdev(dev); + if (err) + goto register_fail; + + if (!g_mac_unit_init_done) { + writel(0x07, &priv->cpumacu_reg->cpu_mac_unit_reset_ctl); + writel(0x00, &priv->cpumacu_reg->cpu_mac_unit_reset_ctl); + + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_ts_cfg, + 0, CPU_MAC_UNIT_TS_CFG_W0_CFG_FORCE_S_AND_NS_EN); + if (priv->interface == PHY_INTERFACE_MODE_SGMII) { + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_ref_pulse_cfg[1], + CPU_MAC_UNIT_REF_PULSE_CFG_W1_REF_LINK_PULSE_RST, + 0); + + ctc_mac_serdes_init(priv); + } + g_mac_unit_init_done = 1; + } + + ctcmac_pps_init(priv); + + mdelay(10); + + sprintf(priv->irqinfo[CTCMAC_NORMAL].name, "%s%s", + dev->name, "_normal"); + sprintf(priv->irqinfo[CTCMAC_FUNC].name, "%s%s", dev->name, "_func"); + + return 0; + +register_fail: + ctcmac_unmap_io_space(priv); + ctcmac_free_rx_queues(priv); + ctcmac_free_tx_queues(priv); + of_node_put(priv->phy_node); + ctcmac_free_dev(priv); + + return err; +} + +static int ctcmac_remove(struct platform_device *ofdev) +{ + struct ctcmac_private *priv = platform_get_drvdata(ofdev); + + device_remove_file(&priv->ndev->dev, &dev_attr_rxq0_pps); + device_remove_file(&priv->ndev->dev, &dev_attr_rxq1_pps); + + of_node_put(priv->phy_node); + + unregister_netdev(priv->ndev); + + ctcmac_unmap_io_space(priv); + ctcmac_free_rx_queues(priv); + ctcmac_free_tx_queues(priv); + ctcmac_free_dev(priv); + + return 0; +} + +static const struct of_device_id ctcmac_match[] = { + { + .type = "network", + .compatible = "ctc,mac", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, ctcmac_match); + +/* Structure for a device driver */ +static struct platform_driver ctcmac_driver = { + .driver = { + .name = "ctc-cpumac", + .of_match_table = ctcmac_match, + }, + .probe = ctcmac_probe, + .remove = ctcmac_remove, +}; + +module_platform_driver(ctcmac_driver); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac.h b/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac.h new file mode 100644 index 000000000000..4378c2c802e9 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac.h @@ -0,0 +1,307 @@ +/* + * Centec cpu_mac Ethernet Driver -- cpu_mac controller implementation + * Provides Bus interface for MIIM regs + * + * Author: liuht + * + * Copyright 2002-2017, Centec Networks (Suzhou) Co., Ltd. + * + * + * 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. + * + */ + +#ifndef __CTCMAC_H +#define __CTCMAC_H + +#define TX_TIMEOUT (5 * HZ) + +#define CTCMAC_DEFAULT_MTU 1500 +#define CTCMAC_MIN_PKT_LEN 64 + +#define CTCMAC_TX_QUEUE_MAX 1 +#define CTCMAC_RX_QUEUE_MAX 2 + +#define CTCMAC0_EXSRAM_BASE 0x0 +#define CTCMAC1_EXSRAM_BASE 0x1800 +#define CTCMAC_MAX_RING_SIZE 1023 +#define CTCMAC_TX_RING_SIZE 1023 +#define CTCMAC_RX_RING_SIZE 1023 +#define CTCMAC_RX_BUFF_ALLOC 16 +#define CTCMAC_INTERNAL_RING_SIZE 64 + +/* The maximum number of packets to be handled in one call of gfar_poll */ +#define CTCMAC_NAIP_RX_WEIGHT 16 +#define CTCMAC_NAIP_TX_WEIGHT 16 + +#define CTCMAC_RXB_SIZE 1024 +#define CTCMAC_SKBFRAG_SIZE (CTCMAC_RXB_SIZE \ + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) +#define CTCMAC_RXB_TRUESIZE 2048 +#define BUF_ALIGNMENT 256 +#define CTCMAC_JUMBO_FRAME_SIZE 9600 + +#define CTCMAC_TOKEN_PER_PKT 10 +#define CTCMAC_TIMER_COMPENSATE 1 + +#define CTCMAC_NOR_RX1_R BIT(7) +#define CTCMAC_NOR_RX0_R BIT(6) +#define CTCMAC_NOR_RX1_D BIT(5) +#define CTCMAC_NOR_RX0_D BIT(4) +#define CTCMAC_NOR_TX_D BIT(3) +#define CTCMAC_NOR_AN_D BIT(2) +#define CTCMAC_NOR_LINK_DOWN BIT(1) +#define CTCMAC_NOR_LINK_UP BIT(0) + +#define CTC_DDR_BASE 0x80000000 + +#define CSA_SGMII_MD_MASK 0x00000008 +#define CSA_EN 0x00000001 + +/*Mask*/ +/*CTCMAC_SGMII_CFG*/ +#define CSC_REP_MASK 0x1fc00000 +#define CSC_SMP_MASK 0x1fc00000 +/*CTCMAC_SGMII_MON*/ +#define CSM_ANST_MASK 0x00000007 + +#define CSC_1000M 0x00000000 +#define CSC_100M 0x02400000 +#define CSC_10M 0x18c00000 + +#define CTCMAC_DESC_INT_NUM 1 + +#define CTCMAC_SUPPORTED (SUPPORTED_10baseT_Full \ + | SUPPORTED_100baseT_Full \ + | SUPPORTED_1000baseT_Full \ + | SUPPORTED_Autoneg) + +#define CTCMAC_STATS_LEN (sizeof(struct ctcmac_pkt_stats) / sizeof(u64)) + +struct ctcmac_skb_cb { + unsigned int bytes_sent; /* bytes-on-wire (i.e. no FCB) */ +}; + +#define CTCMAC_CB(skb) ((struct ctcmac_skb_cb *)((skb)->cb)) + +enum ctcmac_irqinfo_id { + CTCMAC_NORMAL = 0, + CTCMAC_FUNC, + CTCMAC_UNIT, + CTCMAC_NUM_IRQS +}; + +enum ctcmac_dev_state { + CTCMAC_DOWN = 1, + CTCMAC_RESETTING +}; + +enum ctcmac_int_type { + CTCMAC_INT_PACKET = 1, + CTCMAC_INT_DESC, + CTCMAC_INT_MAX +}; + +enum ctcmac_autoneg { + CTCMAC_AUTONEG_1000BASEX_M, + CTCMAC_AUTONEG_PHY_M, + CTCMAC_AUTONEG_MAC_M, + CTCMAC_AUTONEG_DISABLE, + CTCMAC_AUTONEG_MAX +}; + +/* Per TX queue stats */ +struct txq_stats { + unsigned long tx_packets; + unsigned long tx_bytes; +}; + +struct ctcmac_tx_buff { + void *vaddr; + dma_addr_t dma; + u32 len; + u32 offset; + u8 alloc; +}; + +struct ctcmac_priv_tx_q { + spinlock_t txlock __aligned(SMP_CACHE_BYTES); + struct ctcmac_tx_buff tx_buff[CTCMAC_MAX_RING_SIZE + 1]; + unsigned int num_txbdfree; + u16 tx_ring_size; + u16 qindex; + u16 next_to_alloc; + u16 next_to_clean; + struct txq_stats stats; + struct net_device *dev; + struct sk_buff **tx_skbuff; +}; + +/*Per RX queue stats */ +struct rxq_stats { + unsigned long rx_packets; + unsigned long rx_bytes; + unsigned long rx_dropped; +}; + +struct ctcmac_rx_buff { + dma_addr_t dma; + struct page *page; + unsigned int page_offset; +}; + +struct ctcmac_priv_rx_q { + struct ctcmac_rx_buff *rx_buff __aligned(SMP_CACHE_BYTES); + struct net_device *ndev; + struct device *dev; + u16 rx_ring_size; + u16 qindex; + u16 next_to_clean; + u16 next_to_use; + u16 next_to_alloc; + struct sk_buff *skb; + struct rxq_stats stats; + u32 pps_limit; + u32 token, token_max; + u32 rx_trigger; +}; + +struct ctcmac_irqinfo { + unsigned int irq; + char name[32]; +}; + +struct ctcmac_desc_cfg { + u8 err_type; /*used when err == 1 */ + u8 err; + u8 eop; + u8 sop; + u32 size; + u32 addr_high; + u32 addr_low; +}; + +struct ctcmac_private { + spinlock_t reglock __aligned(SMP_CACHE_BYTES); + struct device *dev; + struct net_device *ndev; + void __iomem *iobase; + struct cpu_mac_regs __iomem *cpumac_reg; + struct cpu_mac_mems __iomem *cpumac_mem; + struct cpu_mac_unit_regs *cpumacu_reg; + u32 device_flags; + int irq_num; + int index; + + struct ctcmac_priv_tx_q *tx_queue[CTCMAC_TX_QUEUE_MAX]; + struct ctcmac_priv_rx_q *rx_queue[CTCMAC_RX_QUEUE_MAX]; + + unsigned long state; + unsigned int num_tx_queues; + unsigned int num_rx_queues; + + /* PHY stuff */ + phy_interface_t interface; + struct device_node *phy_node; + struct mii_bus *mii_bus; + int oldspeed; + int oldlink; + int oldduplex; + + struct work_struct reset_task; + struct platform_device *ofdev; + struct napi_struct napi_rx; + struct napi_struct napi_tx; + struct ctcmac_irqinfo irqinfo[CTCMAC_NUM_IRQS]; + + int hwts_rx_en; + int hwts_tx_en; + u32 autoneg_mode; + u32 supported; + u32 msg_enable; + u32 int_type; + u8 dfe_enable; + struct timer_list token_timer; +}; + +struct ctcmac_pkt_stats { + u64 rx_good_ucast_bytes; + u64 rx_good_ucast_pkt; + u64 rx_good_mcast_bytes; + u64 rx_good_mcast_pkt; + u64 rx_good_bcast_bytes; + u64 rx_good_bcast_pkt; + u64 rx_good_pause_bytes; + u64 rx_good_pause_pkt; + u64 rx_good_pfc_bytes; + u64 rx_good_pfc_pkt; + u64 rx_good_control_bytes; + u64 rx_good_control_pkt; + u64 rx_fcs_error_bytes; + u64 rx_fcs_error_pkt; + u64 rx_mac_overrun_bytes; + u64 rx_mac_overrun_pkt; + u64 rx_good_63B_bytes; + u64 rx_good_63B_pkt; + u64 rx_bad_63B_bytes; + u64 rx_bad_63B_pkt; + u64 rx_good_mtu2B_bytes; + u64 rx_good_mtu2B_pkt; + u64 rx_bad_mtu2B_bytes; + u64 rx_bad_mtu2B_pkt; + u64 rx_good_jumbo_bytes; + u64 rx_good_jumbo_pkt; + u64 rx_bad_jumbo_bytes; + u64 rx_bad_jumbo_pkt; + u64 rx_64B_bytes; + u64 rx_64B_pkt; + u64 rx_127B_bytes; + u64 rx_127B_pkt; + u64 rx_255B_bytes; + u64 rx_255B_pkt; + u64 rx_511B_bytes; + u64 rx_511B_pkt; + u64 rx_1023B_bytes; + u64 rx_1023B_pkt; + u64 rx_mtu1B_bytes; + u64 rx_mtu1B_pkt; + u64 tx_ucast_bytes; + u64 tx_ucast_pkt; + u64 tx_mcast_bytes; + u64 tx_mcast_pkt; + u64 tx_bcast_bytes; + u64 tx_bcast_pkt; + u64 tx_pause_bytes; + u64 tx_pause_pkt; + u64 tx_control_bytes; + u64 tx_control_pkt; + u64 tx_fcs_error_bytes; + u64 tx_fcs_error_pkt; + u64 tx_underrun_bytes; + u64 tx_underrun_pkt; + u64 tx_63B_bytes; + u64 tx_63B_pkt; + u64 tx_64B_bytes; + u64 tx_64B_pkt; + u64 tx_127B_bytes; + u64 tx_127B_pkt; + u64 tx_255B_bytes; + u64 tx_255B_pkt; + u64 tx_511B_bytes; + u64 tx_511B_pkt; + u64 tx_1023B_bytes; + u64 tx_1023B_pkt; + u64 tx_mtu1_bytes; + u64 tx_mtu1_pkt; + u64 tx_mtu2_bytes; + u64 tx_mtu2_pkt; + u64 tx_jumbo_bytes; + u64 tx_jumbo_pkt; + u64 mtu1; + u64 mtu2; +}; + +#endif diff --git a/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac_reg.h b/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac_reg.h new file mode 100644 index 000000000000..2778f0bb4553 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac_reg.h @@ -0,0 +1,5288 @@ +#ifndef __CTCMAC_H__ +#define __CTCMAC_H__ + +#define CPUMAC_MEM_BASE 0x00004000 +#define CPUMAC_REG_BASE 0x00000000 + +struct cpu_mac_regs { + u32 cpu_mac_axi_cfg; /* 0x00000000 */ + u32 cpu_mac_axi_mon; /* 0x00000004 */ + u32 cpu_mac_desc_cfg[2]; /* 0x00000008 */ + u32 cpu_mac_buffer_cfg[3]; /* 0x00000010 */ + u32 rsv7; + u32 cpu_mac_debug_stats[3]; /* 0x00000020 */ + u32 rsv11; + u32 cpu_mac_desc_mon[3]; /* 0x00000030 */ + u32 rsv15; + u32 cpu_mac_dma_weight_cfg; /* 0x00000040 */ + u32 cpu_mac_init; /* 0x00000044 */ + u32 cpu_mac_init_done; /* 0x00000048 */ + u32 cpu_mac_parity_ctl; /* 0x0000004c */ + u32 cpu_mac_ext_ram_cfg[2]; /* 0x00000050 */ + u32 rsv22; + u32 rsv23; + u32 cpu_mac_fifo_ctl[4]; /* 0x00000060 */ + u32 cpu_mac_gmac_cfg[4]; /* 0x00000070 */ + u32 cpu_mac_ram_chk_rec; /* 0x00000080 */ + u32 cpu_mac_reset; /* 0x00000084 */ + u32 cpu_mac_sgmii_auto_neg_cfg; /* 0x00000088 */ + u32 cpu_mac_reserved; /* 0x0000008c */ + u32 cpu_mac_gmac_mon[2]; /* 0x00000090 */ + u32 cpu_mac_credit_ctl; /* 0x00000098 */ + u32 cpu_mac_credit_status; /* 0x0000009c */ + u32 cpu_mac_pause_cfg[4]; /* 0x000000a0 */ + u32 cpu_mac_pause_mon[3]; /* 0x000000b0 */ + u32 rsv47; + u32 cpu_mac_sgmii_cfg[2]; /* 0x000000c0 */ + u32 cpu_mac_sgmii_mon[2]; /* 0x000000c8 */ + u32 cpu_mac_stats_cfg[2]; /* 0x000000d0 */ + u32 rsv54; + u32 rsv55; + u32 cpu_mac_interrupt_func[4]; /* 0x000000e0 */ + u32 cpu_mac_interrupt_normal[4]; /* 0x000000f0 */ + u32 cpu_mac_fifo_status[3]; /* 0x00000100 */ +}; + +/* cpu_mac_axi_cfg Definition */ +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_WR_BURST_LEN BIT(0) +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_WR_WORD_SWAP_EN BIT(18) +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_WR_D_WORD_SWAP_EN BIT(19) +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_RD_D_WORD_SWAP_EN BIT(17) +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_RD_ADDR_ALIGN_EN BIT(20) +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_RD_BURST_LEN BIT(8) +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_RD_WORD_SWAP_EN BIT(16) + +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_WR_BURST_LEN_MASK 0x000000ff +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_WR_WORD_SWAP_EN_MASK 0x00040000 +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_WR_D_WORD_SWAP_EN_MASK 0x00080000 +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_RD_D_WORD_SWAP_EN_MASK 0x00020000 +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_RD_ADDR_ALIGN_EN_MASK 0x00100000 +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_RD_BURST_LEN_MASK 0x0000ff00 +#define CPU_MAC_AXI_CFG_W0_CFG_AXI_RD_WORD_SWAP_EN_MASK 0x00010000 + +/* cpu_mac_axi_mon Definition */ +#define CPU_MAC_AXI_MON_W0_MON_AXI_WR_RESP BIT(4) +#define CPU_MAC_AXI_MON_W0_MON_AXI_RD_RESP BIT(0) + +#define CPU_MAC_AXI_MON_W0_MON_AXI_WR_RESP_MASK 0x00000070 +#define CPU_MAC_AXI_MON_W0_MON_AXI_RD_RESP_MASK 0x00000007 + +/* cpu_mac_desc_cfg Definition */ +#define CPU_MAC_DESC_CFG_W0_CFG_TX_DESC_DONE_INTR_EOP_EN BIT(30) +#define CPU_MAC_DESC_CFG_W0_CFG_RX_DESC_DONE_INTR_EOP_EN BIT(29) +#define CPU_MAC_DESC_CFG_W0_CFG_RX_DESC0_DONE_INTR_THRD BIT(8) +#define CPU_MAC_DESC_CFG_W0_CFG_TX_DESC_DONE_INTR_THRD BIT(0) +#define CPU_MAC_DESC_CFG_W0_CFG_RX_DESC1_DONE_INTR_THRD BIT(16) +#define CPU_MAC_DESC_CFG_W0_CFG_TX_DESC_ACK_EN BIT(31) +#define CPU_MAC_DESC_CFG_W1_CFG_RX_DESC0_REQ_INTR_THRD BIT(0) +#define CPU_MAC_DESC_CFG_W1_CFG_RX_DESC1_REQ_INTR_THRD BIT(8) + +#define CPU_MAC_DESC_CFG_W0_CFG_TX_DESC_DONE_INTR_EOP_EN_MASK 0x40000000 +#define CPU_MAC_DESC_CFG_W0_CFG_RX_DESC_DONE_INTR_EOP_EN_MASK 0x20000000 +#define CPU_MAC_DESC_CFG_W0_CFG_RX_DESC0_DONE_INTR_THRD_MASK 0x0000ff00 +#define CPU_MAC_DESC_CFG_W0_CFG_TX_DESC_DONE_INTR_THRD_MASK 0x000000ff +#define CPU_MAC_DESC_CFG_W0_CFG_RX_DESC1_DONE_INTR_THRD_MASK 0x00ff0000 +#define CPU_MAC_DESC_CFG_W0_CFG_TX_DESC_ACK_EN_MASK 0x80000000 +#define CPU_MAC_DESC_CFG_W1_CFG_RX_DESC0_REQ_INTR_THRD_MASK 0x000000ff +#define CPU_MAC_DESC_CFG_W1_CFG_RX_DESC1_REQ_INTR_THRD_MASK 0x0000ff00 + +/* cpu_mac_buffer_cfg Definition */ +#define CPU_MAC_BUFFER_CFG_W0_CFG_RX_X_OFF_THRD BIT(16) +#define CPU_MAC_BUFFER_CFG_W0_CFG_RX_X_ON_THRD BIT(0) +#define CPU_MAC_BUFFER_CFG_W1_CFG_RX_RSV_THRD BIT(0) +#define CPU_MAC_BUFFER_CFG_W1_CFG_RX_FLUSH_THRD BIT(16) +#define CPU_MAC_BUFFER_CFG_W2_CFG_RX_FLUSH_EN BIT(0) + +#define CPU_MAC_BUFFER_CFG_W0_CFG_RX_X_OFF_THRD_MASK 0x3fff0000 +#define CPU_MAC_BUFFER_CFG_W0_CFG_RX_X_ON_THRD_MASK 0x00003fff +#define CPU_MAC_BUFFER_CFG_W1_CFG_RX_RSV_THRD_MASK 0x00003fff +#define CPU_MAC_BUFFER_CFG_W1_CFG_RX_FLUSH_THRD_MASK 0x3fff0000 +#define CPU_MAC_BUFFER_CFG_W2_CFG_RX_FLUSH_EN_MASK 0x00000001 + +/* cpu_mac_debug_stats Definition */ +#define CPU_MAC_DEBUG_STATS_W0_DMA_RX_ERROR_CNT BIT(20) +#define CPU_MAC_DEBUG_STATS_W0_GMAC_TX_SOP_CNT BIT(24) +#define CPU_MAC_DEBUG_STATS_W0_GMAC_RX_SOP_CNT BIT(0) +#define CPU_MAC_DEBUG_STATS_W0_GMAC_RX_EOP_CNT BIT(4) +#define CPU_MAC_DEBUG_STATS_W0_GMAC_TX_EOP_CNT BIT(28) +#define CPU_MAC_DEBUG_STATS_W0_DMA_RX_EOP_CNT BIT(16) +#define CPU_MAC_DEBUG_STATS_W0_GMAC_RX_ERROR_CNT BIT(8) +#define CPU_MAC_DEBUG_STATS_W0_DMA_RX_SOP_CNT BIT(12) +#define CPU_MAC_DEBUG_STATS_W1_DMA_TX_EOP_CNT BIT(8) +#define CPU_MAC_DEBUG_STATS_W1_GMAC_TX_PTP_ERR_CNT BIT(16) +#define CPU_MAC_DEBUG_STATS_W1_DMA_TX_SOP_CNT BIT(4) +#define CPU_MAC_DEBUG_STATS_W1_DMA_TX_ERROR_CNT BIT(12) +#define CPU_MAC_DEBUG_STATS_W1_GMAC_TX_ERROR_CNT BIT(0) +#define CPU_MAC_DEBUG_STATS_W2_AXI_RD_BURST_CNT BIT(8) +#define CPU_MAC_DEBUG_STATS_W2_EXT_RAM_SBE_CNT BIT(16) +#define CPU_MAC_DEBUG_STATS_W2_AXI_RD_BURST_ERR_CNT BIT(12) +#define CPU_MAC_DEBUG_STATS_W2_AXI_WR_BURST_CNT BIT(0) +#define CPU_MAC_DEBUG_STATS_W2_AXI_WR_BURST_ERR_CNT BIT(4) + +#define CPU_MAC_DEBUG_STATS_W0_DMA_RX_ERROR_CNT_MASK 0x00f00000 +#define CPU_MAC_DEBUG_STATS_W0_GMAC_TX_SOP_CNT_MASK 0x0f000000 +#define CPU_MAC_DEBUG_STATS_W0_GMAC_RX_SOP_CNT_MASK 0x0000000f +#define CPU_MAC_DEBUG_STATS_W0_GMAC_RX_EOP_CNT_MASK 0x000000f0 +#define CPU_MAC_DEBUG_STATS_W0_GMAC_TX_EOP_CNT_MASK 0xf0000000 +#define CPU_MAC_DEBUG_STATS_W0_DMA_RX_EOP_CNT_MASK 0x000f0000 +#define CPU_MAC_DEBUG_STATS_W0_GMAC_RX_ERROR_CNT_MASK 0x00000f00 +#define CPU_MAC_DEBUG_STATS_W0_DMA_RX_SOP_CNT_MASK 0x0000f000 +#define CPU_MAC_DEBUG_STATS_W1_DMA_TX_EOP_CNT_MASK 0x00000f00 +#define CPU_MAC_DEBUG_STATS_W1_GMAC_TX_PTP_ERR_CNT_MASK 0x000f0000 +#define CPU_MAC_DEBUG_STATS_W1_DMA_TX_SOP_CNT_MASK 0x000000f0 +#define CPU_MAC_DEBUG_STATS_W1_DMA_TX_ERROR_CNT_MASK 0x0000f000 +#define CPU_MAC_DEBUG_STATS_W1_GMAC_TX_ERROR_CNT_MASK 0x0000000f +#define CPU_MAC_DEBUG_STATS_W2_AXI_RD_BURST_CNT_MASK 0x00000f00 +#define CPU_MAC_DEBUG_STATS_W2_EXT_RAM_SBE_CNT_MASK 0x000f0000 +#define CPU_MAC_DEBUG_STATS_W2_AXI_RD_BURST_ERR_CNT_MASK 0x0000f000 +#define CPU_MAC_DEBUG_STATS_W2_AXI_WR_BURST_CNT_MASK 0x0000000f +#define CPU_MAC_DEBUG_STATS_W2_AXI_WR_BURST_ERR_CNT_MASK 0x000000f0 + +/* cpu_mac_desc_mon Definition */ +#define CPU_MAC_DESC_MON_W0_MON_DESC_AVAIL_NUM0 BIT(0) +#define CPU_MAC_DESC_MON_W0_MON_DESC_AVAIL_NUM1 BIT(16) +#define CPU_MAC_DESC_MON_W1_MON_DESC_AVAIL_NUM2 BIT(0) +#define CPU_MAC_DESC_MON_W1_MON_DESC_DONE_NUM0 BIT(16) +#define CPU_MAC_DESC_MON_W2_MON_DESC_DONE_NUM1 BIT(0) +#define CPU_MAC_DESC_MON_W2_MON_DESC_DONE_NUM2 BIT(16) + +#define CPU_MAC_DESC_MON_W0_MON_DESC_AVAIL_NUM0_MASK 0x0000ffff +#define CPU_MAC_DESC_MON_W0_MON_DESC_AVAIL_NUM1_MASK 0xffff0000 +#define CPU_MAC_DESC_MON_W1_MON_DESC_AVAIL_NUM2_MASK 0x0000ffff +#define CPU_MAC_DESC_MON_W1_MON_DESC_DONE_NUM0_MASK 0xffff0000 +#define CPU_MAC_DESC_MON_W2_MON_DESC_DONE_NUM1_MASK 0x0000ffff +#define CPU_MAC_DESC_MON_W2_MON_DESC_DONE_NUM2_MASK 0xffff0000 + +/* cpu_mac_dma_weight_cfg Definition */ +#define CPU_MAC_DMA_WEIGHT_CFG_W0_CFG_DMA_RX_WEIGHT1 BIT(8) +#define CPU_MAC_DMA_WEIGHT_CFG_W0_CFG_DMA_RX_WEIGHT0 BIT(0) + +#define CPU_MAC_DMA_WEIGHT_CFG_W0_CFG_DMA_RX_WEIGHT1_MASK 0x00000f00 +#define CPU_MAC_DMA_WEIGHT_CFG_W0_CFG_DMA_RX_WEIGHT0_MASK 0x0000000f + +/* cpu_mac_init Definition */ +#define CPU_MAC_INIT_W0_INIT BIT(0) + +#define CPU_MAC_INIT_W0_INIT_MASK 0x00000001 + +/* cpu_mac_init_done Definition */ +#define CPU_MAC_INIT_DONE_W0_INIT_DONE BIT(0) + +#define CPU_MAC_INIT_DONE_W0_INIT_DONE_MASK 0x00000001 + +/* cpu_mac_parity_ctl Definition */ +#define CPU_MAC_PARITY_CTL_W0_RX_PKT_MSG_FIFO_PARITY_EN BIT(2) +#define CPU_MAC_PARITY_CTL_W0_TX_PKT_FIFO_PARITY_EN BIT(4) +#define CPU_MAC_PARITY_CTL_W0_EXT_RAM_ECC_DETECT_DIS BIT(8) +#define CPU_MAC_PARITY_CTL_W0_CPU_MAC_STATS_RAM_PARITY_EN BIT(0) +#define CPU_MAC_PARITY_CTL_W0_RX_DESC0_CFG_FIFO_PARITY_EN BIT(5) +#define CPU_MAC_PARITY_CTL_W0_RX_PKT_DATA_FIFO_PARITY_EN BIT(1) +#define CPU_MAC_PARITY_CTL_W0_TX_DESC_CFG_FIFO_PARITY_EN BIT(7) +#define CPU_MAC_PARITY_CTL_W0_RX_DESC1_CFG_FIFO_PARITY_EN BIT(6) +#define CPU_MAC_PARITY_CTL_W0_EXT_RAM_ECC_CORRECT_DIS BIT(9) + +#define CPU_MAC_PARITY_CTL_W0_RX_PKT_MSG_FIFO_PARITY_EN_MASK 0x00000004 +#define CPU_MAC_PARITY_CTL_W0_TX_PKT_FIFO_PARITY_EN_MASK 0x00000010 +#define CPU_MAC_PARITY_CTL_W0_EXT_RAM_ECC_DETECT_DIS_MASK 0x00000100 +#define CPU_MAC_PARITY_CTL_W0_CPU_MAC_STATS_RAM_PARITY_EN_MASK 0x00000001 +#define CPU_MAC_PARITY_CTL_W0_RX_DESC0_CFG_FIFO_PARITY_EN_MASK 0x00000020 +#define CPU_MAC_PARITY_CTL_W0_RX_PKT_DATA_FIFO_PARITY_EN_MASK 0x00000002 +#define CPU_MAC_PARITY_CTL_W0_TX_DESC_CFG_FIFO_PARITY_EN_MASK 0x00000080 +#define CPU_MAC_PARITY_CTL_W0_RX_DESC1_CFG_FIFO_PARITY_EN_MASK 0x00000040 +#define CPU_MAC_PARITY_CTL_W0_EXT_RAM_ECC_CORRECT_DIS_MASK 0x00000200 + +/* cpu_mac_ext_ram_cfg Definition */ +#define CPU_MAC_EXT_RAM_CFG_W0_CFG_EXT_RAM_EN BIT(31) +#define CPU_MAC_EXT_RAM_CFG_W0_CFG_EXT_RAM_BASE_SIZE BIT(0) +#define CPU_MAC_EXT_RAM_CFG_W1_CFG_EXT_RAM_BASE_ADDR BIT(0) + +#define CPU_MAC_EXT_RAM_CFG_W0_CFG_EXT_RAM_EN_MASK 0x80000000 +#define CPU_MAC_EXT_RAM_CFG_W0_CFG_EXT_RAM_BASE_SIZE_MASK 0x000003ff +#define CPU_MAC_EXT_RAM_CFG_W1_CFG_EXT_RAM_BASE_ADDR_MASK 0x000fffff + +/* cpu_mac_fifo_ctl Definition */ +#define CPU_MAC_FIFO_CTL_W0_RX_PKT_DATA_FIFO_A_FULL_THRD BIT(0) +#define CPU_MAC_FIFO_CTL_W1_RX_PKT_MSG_FIFO_A_FULL_THRD BIT(0) +#define CPU_MAC_FIFO_CTL_W2_TX_PKT_FIFO_A_FULL_THRD BIT(0) +#define CPU_MAC_FIFO_CTL_W3_RX_PKT_FIFO_A_FULL_THRD BIT(0) + +#define CPU_MAC_FIFO_CTL_W0_RX_PKT_DATA_FIFO_A_FULL_THRD_MASK 0x00001fff +#define CPU_MAC_FIFO_CTL_W1_RX_PKT_MSG_FIFO_A_FULL_THRD_MASK 0x000003ff +#define CPU_MAC_FIFO_CTL_W2_TX_PKT_FIFO_A_FULL_THRD_MASK 0x000007ff +#define CPU_MAC_FIFO_CTL_W3_RX_PKT_FIFO_A_FULL_THRD_MASK 0x000003ff + +/* cpu_mac_gmac_cfg Definition */ +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_CUT_THROUGH_EN BIT(4) +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_UNDERSIZE_DROP_EN BIT(3) +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_ERROR_DROP_EN BIT(5) +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_TS_EN BIT(0) +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_OVERSIZE_DROP_EN BIT(2) +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_PAUSE_DROP_EN BIT(6) +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_OVERRUN_DROP_EN BIT(1) +#define CPU_MAC_GMAC_CFG_W1_CFG_RX_MAX_PKT_LEN_CHK_EN BIT(0) +#define CPU_MAC_GMAC_CFG_W1_CFG_RX_MIN_PKT_LEN BIT(17) +#define CPU_MAC_GMAC_CFG_W1_CFG_RX_MIN_PKT_LEN_CHK_EN BIT(16) +#define CPU_MAC_GMAC_CFG_W1_CFG_RX_MAX_PKT_LEN BIT(1) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_START_THRD BIT(16) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_ERR_MASK_OFF BIT(1) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_PTP_ERR_EN BIT(6) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_KEEP_TS_EN BIT(12) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_PAUSE_STALL_EN BIT(4) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_CUT_THROUGH_EN BIT(10) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_STRIP_CRC_EN BIT(8) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_PKT_EN BIT(5) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_PAD_EN BIT(3) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_WAIT_CAPTURE_TS BIT(9) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_HDR_INFO_EN BIT(11) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_LPI_EN BIT(2) +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_APPEND_CRC_EN BIT(0) +#define CPU_MAC_GMAC_CFG_W3_CFG_TX_SLEEP_TIMER BIT(0) +#define CPU_MAC_GMAC_CFG_W3_CFG_TX_WAKEUP_TIMER BIT(16) + +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_CUT_THROUGH_EN_MASK 0x00000010 +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_UNDERSIZE_DROP_EN_MASK 0x00000008 +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_ERROR_DROP_EN_MASK 0x00000020 +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_TS_EN_MASK 0x00000001 +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_OVERSIZE_DROP_EN_MASK 0x00000004 +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_PAUSE_DROP_EN_MASK 0x00000040 +#define CPU_MAC_GMAC_CFG_W0_CFG_RX_OVERRUN_DROP_EN_MASK 0x00000002 +#define CPU_MAC_GMAC_CFG_W1_CFG_RX_MAX_PKT_LEN_CHK_EN_MASK 0x00000001 +#define CPU_MAC_GMAC_CFG_W1_CFG_RX_MIN_PKT_LEN_MASK 0x00fe0000 +#define CPU_MAC_GMAC_CFG_W1_CFG_RX_MIN_PKT_LEN_CHK_EN_MASK 0x00010000 +#define CPU_MAC_GMAC_CFG_W1_CFG_RX_MAX_PKT_LEN_MASK 0x0000fffe +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_START_THRD_MASK 0x07ff0000 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_ERR_MASK_OFF_MASK 0x00000002 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_PTP_ERR_EN_MASK 0x00000040 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_KEEP_TS_EN_MASK 0x00001000 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_PAUSE_STALL_EN_MASK 0x00000010 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_CUT_THROUGH_EN_MASK 0x00000400 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_STRIP_CRC_EN_MASK 0x00000100 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_PKT_EN_MASK 0x00000020 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_PAD_EN_MASK 0x00000008 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_WAIT_CAPTURE_TS_MASK 0x00000200 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_HDR_INFO_EN_MASK 0x00000800 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_LPI_EN_MASK 0x00000004 +#define CPU_MAC_GMAC_CFG_W2_CFG_TX_APPEND_CRC_EN_MASK 0x00000001 +#define CPU_MAC_GMAC_CFG_W3_CFG_TX_SLEEP_TIMER_MASK 0x0000ffff +#define CPU_MAC_GMAC_CFG_W3_CFG_TX_WAKEUP_TIMER_MASK 0xffff0000 + +/* cpu_mac_ram_chk_rec Definition */ +#define CPU_MAC_RAM_CHK_REC_W0_CPU_MAC_STATS_RAM_PARITY_FAIL BIT(31) +#define CPU_MAC_RAM_CHK_REC_W0_CPU_MAC_STATS_RAM_PARITY_FAIL_ADDR BIT(0) + +#define CPU_MAC_RAM_CHK_REC_W0_CPU_MAC_STATS_RAM_PARITY_FAIL_MASK 0x80000000 +#define CPU_MAC_RAM_CHK_REC_W0_CPU_MAC_STATS_RAM_PARITY_FAIL_ADDR_MASK 0x0000003f + +/* cpu_mac_reset Definition */ +#define CPU_MAC_RESET_W0_SOFT_RST_TX BIT(1) +#define CPU_MAC_RESET_W0_SOFT_RST_RX BIT(0) + +#define CPU_MAC_RESET_W0_SOFT_RST_TX_MASK 0x00000002 +#define CPU_MAC_RESET_W0_SOFT_RST_RX_MASK 0x00000001 + +/* cpu_mac_sgmii_auto_neg_cfg Definition */ +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_RESTART BIT(1) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LOCAL_SPEED_MODE BIT(7) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LINK_TIMER_CNT BIT(16) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_MODE BIT(2) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_REMOTE_LINKUP_EN BIT(25) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_IGNORE_LINK_FAILURE BIT(5) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_PARALLEL_DETECT_EN BIT(24) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_TX_XMIT_LOAD_USE_ASYNC_FIFO BIT(14) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LOCAL_EEE_ABILITY BIT(9) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_ENABLE BIT(0) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LOCAL_OFFLINE BIT(6) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_IGNORE_ANEG_ERR BIT(4) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_TX_CONFIG_REG_BIT14 BIT(13) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LOCAL_EEE_CLK_STOP BIT(10) +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LOCAL_PAUSE_ABILITY BIT(11) + +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_RESTART_MASK 0x00000002 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LOCAL_SPEED_MODE_MASK 0x00000180 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LINK_TIMER_CNT_MASK 0x00ff0000 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_MODE_MASK 0x0000000c +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_REMOTE_LINKUP_EN_MASK 0x02000000 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_IGNORE_LINK_FAILURE_MASK 0x00000020 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_PARALLEL_DETECT_EN_MASK 0x01000000 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_TX_XMIT_LOAD_USE_ASYNC_FIFO_MASK 0x00004000 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LOCAL_EEE_ABILITY_MASK 0x00000200 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_ENABLE_MASK 0x00000001 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LOCAL_OFFLINE_MASK 0x00000040 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_IGNORE_ANEG_ERR_MASK 0x00000010 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_TX_CONFIG_REG_BIT14_MASK 0x00002000 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LOCAL_EEE_CLK_STOP_MASK 0x00000400 +#define CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_LOCAL_PAUSE_ABILITY_MASK 0x00001800 + +/* cpu_mac_reserved Definition */ +#define CPU_MAC_RESERVED_W0_RESERVED BIT(0) + +#define CPU_MAC_RESERVED_W0_RESERVED_MASK 0xffffffff + +/* cpu_mac_gmac_mon Definition */ +#define CPU_MAC_GMAC_MON_W0_MON_TX_LPI_STATE BIT(6) +#define CPU_MAC_GMAC_MON_W0_MON_RX_METER_TOKEN BIT(8) +#define CPU_MAC_GMAC_MON_W0_MON_RX_PKT_STATE BIT(0) +#define CPU_MAC_GMAC_MON_W1_GMAC_RX_BUF_FULL_DROP_CNT BIT(20) +#define CPU_MAC_GMAC_MON_W1_GMAC_RX_FILTER_DROP_CNT BIT(24) +#define CPU_MAC_GMAC_MON_W1_MON_TX_LPI_STATUS BIT(0) +#define CPU_MAC_GMAC_MON_W1_MON_RX_BUF_RD_STATE BIT(2) +#define CPU_MAC_GMAC_MON_W1_MON_TX_POP_STATE BIT(5) +#define CPU_MAC_GMAC_MON_W1_GMAC_RX_RUNT_DROP_CNT BIT(16) +#define CPU_MAC_GMAC_MON_W1_MON_TX_STATS_UNDERRUN BIT(1) +#define CPU_MAC_GMAC_MON_W1_MON_RX_PKT_LEN BIT(8) +#define CPU_MAC_GMAC_MON_W1_GMAC_RX_PAUSE_DROP_CNT BIT(28) + +#define CPU_MAC_GMAC_MON_W0_MON_TX_LPI_STATE_MASK 0x000000c0 +#define CPU_MAC_GMAC_MON_W0_MON_RX_METER_TOKEN_MASK 0xffffff00 +#define CPU_MAC_GMAC_MON_W0_MON_RX_PKT_STATE_MASK 0x0000000f +#define CPU_MAC_GMAC_MON_W1_GMAC_RX_BUF_FULL_DROP_CNT_MASK 0x00f00000 +#define CPU_MAC_GMAC_MON_W1_GMAC_RX_FILTER_DROP_CNT_MASK 0x0f000000 +#define CPU_MAC_GMAC_MON_W1_MON_TX_LPI_STATUS_MASK 0x00000001 +#define CPU_MAC_GMAC_MON_W1_MON_RX_BUF_RD_STATE_MASK 0x0000001c +#define CPU_MAC_GMAC_MON_W1_MON_TX_POP_STATE_MASK 0x000000e0 +#define CPU_MAC_GMAC_MON_W1_GMAC_RX_RUNT_DROP_CNT_MASK 0x000f0000 +#define CPU_MAC_GMAC_MON_W1_MON_TX_STATS_UNDERRUN_MASK 0x00000002 +#define CPU_MAC_GMAC_MON_W1_MON_RX_PKT_LEN_MASK 0x0000ff00 +#define CPU_MAC_GMAC_MON_W1_GMAC_RX_PAUSE_DROP_CNT_MASK 0xf0000000 + +/* cpu_mac_credit_ctl Definition */ +#define CPU_MAC_CREDIT_CTL_W0_CPU_MAC_CPU_RAM_CREDIT_THRD BIT(0) + +#define CPU_MAC_CREDIT_CTL_W0_CPU_MAC_CPU_RAM_CREDIT_THRD_MASK 0x000000ff + +/* cpu_mac_credit_status Definition */ +#define CPU_MAC_CREDIT_STATUS_W0_CPU_MAC_CPU_RAM_CREDIT_USED BIT(0) + +#define CPU_MAC_CREDIT_STATUS_W0_CPU_MAC_CPU_RAM_CREDIT_USED_MASK 0x000000ff + +/* cpu_mac_pause_cfg Definition */ +#define CPU_MAC_PAUSE_CFG_W0_CFG_RX_PAUSE_TIMER_ADJ_VALUE BIT(1) +#define CPU_MAC_PAUSE_CFG_W0_CFG_RX_NORM_PAUSE_EN BIT(0) +#define CPU_MAC_PAUSE_CFG_W0_CFG_RX_PAUSE_TIMER_DEC_VALUE BIT(11) +#define CPU_MAC_PAUSE_CFG_W1_CFG_TX_PAUSE_TIMER_ADJ_VALUE BIT(1) +#define CPU_MAC_PAUSE_CFG_W1_CFG_TX_PAUSE_TIMER_DEC_VALUE BIT(18) +#define CPU_MAC_PAUSE_CFG_W1_CFG_TX_PAUSE_EN BIT(0) +#define CPU_MAC_PAUSE_CFG_W2_CFG_TX_PAUSE_MAC_SA_31_0 BIT(0) +#define CPU_MAC_PAUSE_CFG_W3_CFG_TX_PAUSE_MAC_SA_47_32 BIT(0) +#define CPU_MAC_PAUSE_CFG_W3_CFG_TX_PAUSE_QUANTA BIT(16) + +#define CPU_MAC_PAUSE_CFG_W0_CFG_RX_PAUSE_TIMER_ADJ_VALUE_MASK 0x000007fe +#define CPU_MAC_PAUSE_CFG_W0_CFG_RX_NORM_PAUSE_EN_MASK 0x00000001 +#define CPU_MAC_PAUSE_CFG_W0_CFG_RX_PAUSE_TIMER_DEC_VALUE_MASK 0x0007f800 +#define CPU_MAC_PAUSE_CFG_W1_CFG_TX_PAUSE_TIMER_ADJ_VALUE_MASK 0x0003fffe +#define CPU_MAC_PAUSE_CFG_W1_CFG_TX_PAUSE_TIMER_DEC_VALUE_MASK 0x03fc0000 +#define CPU_MAC_PAUSE_CFG_W1_CFG_TX_PAUSE_EN_MASK 0x00000001 +#define CPU_MAC_PAUSE_CFG_W2_CFG_TX_PAUSE_MAC_SA_31_0_MASK 0x00000001 +#define CPU_MAC_PAUSE_CFG_W3_CFG_TX_PAUSE_MAC_SA_47_32_MASK 0x00000001 +#define CPU_MAC_PAUSE_CFG_W3_CFG_TX_PAUSE_QUANTA_MASK 0xffff0000 + +/* cpu_mac_pause_mon Definition */ +#define CPU_MAC_PAUSE_MON_W0_MON_TX_PAUSE_TIMER BIT(0) +#define CPU_MAC_PAUSE_MON_W1_MON_RX_PAUSE_TIMER BIT(0) +#define CPU_MAC_PAUSE_MON_W2_MON_TX_PAUSE_CUR_STATUS BIT(0) +#define CPU_MAC_PAUSE_MON_W2_MON_TX_PAUSE_LOG_STATUS BIT(1) + +#define CPU_MAC_PAUSE_MON_W0_MON_TX_PAUSE_TIMER_MASK 0x0001ffff +#define CPU_MAC_PAUSE_MON_W1_MON_RX_PAUSE_TIMER_MASK 0x0000ffff +#define CPU_MAC_PAUSE_MON_W2_MON_TX_PAUSE_CUR_STATUS_MASK 0x00000001 +#define CPU_MAC_PAUSE_MON_W2_MON_TX_PAUSE_LOG_STATUS_MASK 0x00000002 + +/* cpu_mac_sgmii_cfg Definition */ +#define CPU_MAC_SGMII_CFG_W0_CFG_TX_EVEN_IGNORE BIT(3) +#define CPU_MAC_SGMII_CFG_W0_CFG_TX_IPG_LEN BIT(14) +#define CPU_MAC_SGMII_CFG_W0_CFG_TX_PREAMBLE_LEN BIT(18) +#define CPU_MAC_SGMII_CFG_W0_CFG_UNIDIRECTION_EN BIT(4) +#define CPU_MAC_SGMII_CFG_W0_CFG_MII_RX_CHK_LINK_FOR_SOP BIT(31) +#define CPU_MAC_SGMII_CFG_W0_CFG_FORCE_RELOCK BIT(0) +#define CPU_MAC_SGMII_CFG_W0_CFG_FORCE_SIGNAL_DETECT BIT(1) +#define CPU_MAC_SGMII_CFG_W0_CFG_TX_REPLICATE_CNT BIT(22) +#define CPU_MAC_SGMII_CFG_W0_CFG_MII_RX_LINK_FILTER_TIMER BIT(6) +#define CPU_MAC_SGMII_CFG_W0_CFG_SIG_DET_ACTIVE_VALUE BIT(2) +#define CPU_MAC_SGMII_CFG_W0_CFG_MII_RX_LINK_FILTER_EN BIT(5) +#define CPU_MAC_SGMII_CFG_W1_CFG_MII_RX_SAMPLE_CNT BIT(22) +#define CPU_MAC_SGMII_CFG_W1_CFG_TX_THRESHOLD BIT(0) +#define CPU_MAC_SGMII_CFG_W1_CFG_MII_TX_A_FULL_THRD BIT(5) + +#define CPU_MAC_SGMII_CFG_W0_CFG_TX_EVEN_IGNORE_MASK 0x00000008 +#define CPU_MAC_SGMII_CFG_W0_CFG_TX_IPG_LEN_MASK 0x0003c000 +#define CPU_MAC_SGMII_CFG_W0_CFG_TX_PREAMBLE_LEN_MASK 0x003c0000 +#define CPU_MAC_SGMII_CFG_W0_CFG_UNIDIRECTION_EN_MASK 0x00000010 +#define CPU_MAC_SGMII_CFG_W0_CFG_MII_RX_CHK_LINK_FOR_SOP_MASK 0x80000000 +#define CPU_MAC_SGMII_CFG_W0_CFG_FORCE_RELOCK_MASK 0x00000001 +#define CPU_MAC_SGMII_CFG_W0_CFG_FORCE_SIGNAL_DETECT_MASK 0x00000002 +#define CPU_MAC_SGMII_CFG_W0_CFG_TX_REPLICATE_CNT_MASK 0x1fc00000 +#define CPU_MAC_SGMII_CFG_W0_CFG_MII_RX_LINK_FILTER_TIMER_MASK 0x00003fc0 +#define CPU_MAC_SGMII_CFG_W0_CFG_SIG_DET_ACTIVE_VALUE_MASK 0x00000004 +#define CPU_MAC_SGMII_CFG_W0_CFG_MII_RX_LINK_FILTER_EN_MASK 0x00000020 +#define CPU_MAC_SGMII_CFG_W1_CFG_MII_RX_SAMPLE_CNT_MASK 0x1fc00000 +#define CPU_MAC_SGMII_CFG_W1_CFG_TX_THRESHOLD_MASK 0x0000001f +#define CPU_MAC_SGMII_CFG_W1_CFG_MII_TX_A_FULL_THRD_MASK 0x000003e0 + +/* cpu_mac_sgmii_mon Definition */ +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_TX_CODE_STATE BIT(23) +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_TX_SOP_FLAG BIT(18) +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_TX_EOP_FLAG BIT(19) +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_RX_EOP_FLAG BIT(9) +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_RX_SFD_FLAG BIT(11) +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_TX_LPI_STATE BIT(20) +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_RX_LPI_STATE BIT(12) +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_RX_PKT_STATE BIT(15) +#define CPU_MAC_SGMII_MON_W0_MON_ANEG_STATE BIT(0) +#define CPU_MAC_SGMII_MON_W0_MON_CODE_ERR_CNT BIT(4) +#define CPU_MAC_SGMII_MON_W0_MON_LINK_STATUS BIT(8) +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_RX_SOP_FLAG BIT(10) +#define CPU_MAC_SGMII_MON_W1_MON_AN_RX_REMOTE_CFG BIT(0) + +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_TX_CODE_STATE_MASK 0x03800000 +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_TX_SOP_FLAG_MASK 0x00040000 +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_TX_EOP_FLAG_MASK 0x00080000 +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_RX_EOP_FLAG_MASK 0x00000200 +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_RX_SFD_FLAG_MASK 0x00000800 +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_TX_LPI_STATE_MASK 0x00700000 +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_RX_LPI_STATE_MASK 0x00007000 +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_RX_PKT_STATE_MASK 0x00038000 +#define CPU_MAC_SGMII_MON_W0_MON_ANEG_STATE_MASK 0x00000007 +#define CPU_MAC_SGMII_MON_W0_MON_CODE_ERR_CNT_MASK 0x000000f0 +#define CPU_MAC_SGMII_MON_W0_MON_LINK_STATUS_MASK 0x00000100 +#define CPU_MAC_SGMII_MON_W0_MON_SGMII_RX_SOP_FLAG_MASK 0x00000400 +#define CPU_MAC_SGMII_MON_W1_MON_AN_RX_REMOTE_CFG_MASK 0x0000ffff + +/* cpu_mac_stats_cfg Definition */ +#define CPU_MAC_STATS_CFG_W0_CFG_GMAC_STATS64_B_PKT_HI_PRI BIT(4) +#define CPU_MAC_STATS_CFG_W0_CFG_GMAC_STATS_INCR_SATURATE BIT(1) +#define CPU_MAC_STATS_CFG_W0_CFG_GMAC_STATS_INCR_HOLD BIT(2) +#define CPU_MAC_STATS_CFG_W0_CFG_GMAC_STATS_CLEAR_ON_READ BIT(0) +#define CPU_MAC_STATS_CFG_W0_CFG_GMAC_STATS_OVER_WRITE_EN BIT(3) +#define CPU_MAC_STATS_CFG_W1_CFG_GMAC_STATS_MTU1 BIT(0) +#define CPU_MAC_STATS_CFG_W1_CFG_GMAC_STATS_MTU2 BIT(16) + +#define CPU_MAC_STATS_CFG_W0_CFG_GMAC_STATS64_B_PKT_HI_PRI_MASK 0x00000010 +#define CPU_MAC_STATS_CFG_W0_CFG_GMAC_STATS_INCR_SATURATE_MASK 0x00000002 +#define CPU_MAC_STATS_CFG_W0_CFG_GMAC_STATS_INCR_HOLD_MASK 0x00000004 +#define CPU_MAC_STATS_CFG_W0_CFG_GMAC_STATS_CLEAR_ON_READ_MASK 0x00000001 +#define CPU_MAC_STATS_CFG_W0_CFG_GMAC_STATS_OVER_WRITE_EN_MASK 0x00000008 +#define CPU_MAC_STATS_CFG_W1_CFG_GMAC_STATS_MTU1_MASK 0x00003fff +#define CPU_MAC_STATS_CFG_W1_CFG_GMAC_STATS_MTU2_MASK 0x3fff0000 + +/* cpu_mac_interrupt_func Definition */ +#define CPU_MAC_INTERRUPT_FUNC_W0_VALUE_SET0_CPU_MAC_INTERRUPT_FUNC BIT(0) +#define CPU_MAC_INTERRUPT_FUNC_W1_VALUE_RESET0_CPU_MAC_INTERRUPT_FUNC BIT(0) +#define CPU_MAC_INTERRUPT_FUNC_W2_MASK_SET0_CPU_MAC_INTERRUPT_FUNC BIT(0) +#define CPU_MAC_INTERRUPT_FUNC_W3_MASK_RESET0_CPU_MAC_INTERRUPT_FUNC BIT(0) + +#define CPU_MAC_INTERRUPT_FUNC_W0_VALUE_SET0_CPU_MAC_INTERRUPT_FUNC_MASK 0x000000ff +#define CPU_MAC_INTERRUPT_FUNC_W1_VALUE_RESET0_CPU_MAC_INTERRUPT_FUNC_MASK 0x000000ff +#define CPU_MAC_INTERRUPT_FUNC_W2_MASK_SET0_CPU_MAC_INTERRUPT_FUNC_MASK 0x000000ff +#define CPU_MAC_INTERRUPT_FUNC_W3_MASK_RESET0_CPU_MAC_INTERRUPT_FUNC_MASK 0x000000ff + +/* cpu_mac_interrupt_normal Definition */ +#define CPU_MAC_INTERRUPT_NORMAL_W0_VALUE_SET0_CPU_MAC_INTERRUPT_NORMAL BIT(0) +#define CPU_MAC_INTERRUPT_NORMAL_W1_VALUE_RESET0_CPU_MAC_INTERRUPT_NORMAL BIT(0) +#define CPU_MAC_INTERRUPT_NORMAL_W2_MASK_SET0_CPU_MAC_INTERRUPT_NORMAL BIT(0) +#define CPU_MAC_INTERRUPT_NORMAL_W3_MASK_RESET0_CPU_MAC_INTERRUPT_NORMAL BIT(0) + +#define CPU_MAC_INTERRUPT_NORMAL_W0_VALUE_SET0_CPU_MAC_INTERRUPT_NORMAL_MASK 0xffffffff +#define CPU_MAC_INTERRUPT_NORMAL_W1_VALUE_RESET0_CPU_MAC_INTERRUPT_NORMAL_MASK 0xffffffff +#define CPU_MAC_INTERRUPT_NORMAL_W2_MASK_SET0_CPU_MAC_INTERRUPT_NORMAL_MASK 0xffffffff +#define CPU_MAC_INTERRUPT_NORMAL_W3_MASK_RESET0_CPU_MAC_INTERRUPT_NORMAL_MASK 0xffffffff + +/* cpu_mac_fifo_status Definition */ +#define CPU_MAC_FIFO_STATUS_W0_RX_PKT_MSG_FIFO_FIFO_DEPTH BIT(0) +#define CPU_MAC_FIFO_STATUS_W0_RX_PKT_DATA_FIFO_FIFO_DEPTH BIT(20) +#define CPU_MAC_FIFO_STATUS_W0_TX_DESC_ACK_FIFO_FIFO_DEPTH BIT(10) +#define CPU_MAC_FIFO_STATUS_W0_EXT_RAM_RD_TRACK_FIFO_FIFO_DEPTH BIT(16) +#define CPU_MAC_FIFO_STATUS_W1_RX_DESC0_ACK_FIFO_FIFO_DEPTH BIT(12) +#define CPU_MAC_FIFO_STATUS_W1_RX_DESC1_CFG_FIFO_FIFO_DEPTH BIT(18) +#define CPU_MAC_FIFO_STATUS_W1_RX_DESC0_CFG_FIFO_FIFO_DEPTH BIT(6) +#define CPU_MAC_FIFO_STATUS_W1_RX_DESC1_ACK_FIFO_FIFO_DEPTH BIT(24) +#define CPU_MAC_FIFO_STATUS_W1_TX_DESC_CFG_FIFO_FIFO_DEPTH BIT(0) +#define CPU_MAC_FIFO_STATUS_W2_TX_PKT_FIFO_FIFO_DEPTH BIT(16) +#define CPU_MAC_FIFO_STATUS_W2_RX_PKT_FIFO_FIFO_DEPTH BIT(0) + +#define CPU_MAC_FIFO_STATUS_W0_RX_PKT_MSG_FIFO_FIFO_DEPTH_MASK 0x000003ff +#define CPU_MAC_FIFO_STATUS_W0_RX_PKT_DATA_FIFO_FIFO_DEPTH_MASK 0xfff00000 +#define CPU_MAC_FIFO_STATUS_W0_TX_DESC_ACK_FIFO_FIFO_DEPTH_MASK 0x0000fc00 +#define CPU_MAC_FIFO_STATUS_W0_EXT_RAM_RD_TRACK_FIFO_FIFO_DEPTH_MASK 0x000f0000 +#define CPU_MAC_FIFO_STATUS_W1_RX_DESC0_ACK_FIFO_FIFO_DEPTH_MASK 0x0003f000 +#define CPU_MAC_FIFO_STATUS_W1_RX_DESC1_CFG_FIFO_FIFO_DEPTH_MASK 0x00fc0000 +#define CPU_MAC_FIFO_STATUS_W1_RX_DESC0_CFG_FIFO_FIFO_DEPTH_MASK 0x00000fc0 +#define CPU_MAC_FIFO_STATUS_W1_RX_DESC1_ACK_FIFO_FIFO_DEPTH_MASK 0x3f000000 +#define CPU_MAC_FIFO_STATUS_W1_TX_DESC_CFG_FIFO_FIFO_DEPTH_MASK 0x0000003f +#define CPU_MAC_FIFO_STATUS_W2_TX_PKT_FIFO_FIFO_DEPTH_MASK 0x03ff0000 +#define CPU_MAC_FIFO_STATUS_W2_RX_PKT_FIFO_FIFO_DEPTH_MASK 0x000003ff + +struct cpu_mac_mems { + u32 tx_pkt_fifo_0[3]; /* 0x00004000 */ + u32 tx_pkt_fifo_0_rsv3; + u32 tx_pkt_fifo_1[3]; /* 0x00004010 */ + u32 tx_pkt_fifo_1_rsv3; + u32 tx_pkt_fifo_2[3]; /* 0x00004020 */ + u32 tx_pkt_fifo_2_rsv3; + u32 tx_pkt_fifo_3[3]; /* 0x00004030 */ + u32 tx_pkt_fifo_3_rsv3; + u32 tx_pkt_fifo_4[3]; /* 0x00004040 */ + u32 tx_pkt_fifo_4_rsv3; + u32 tx_pkt_fifo_5[3]; /* 0x00004050 */ + u32 tx_pkt_fifo_5_rsv3; + u32 tx_pkt_fifo_6[3]; /* 0x00004060 */ + u32 tx_pkt_fifo_6_rsv3; + u32 tx_pkt_fifo_7[3]; /* 0x00004070 */ + u32 tx_pkt_fifo_7_rsv3; + u32 tx_pkt_fifo_8[3]; /* 0x00004080 */ + u32 tx_pkt_fifo_8_rsv3; + u32 tx_pkt_fifo_9[3]; /* 0x00004090 */ + u32 tx_pkt_fifo_9_rsv3; + u32 tx_pkt_fifo_10[3]; /* 0x000040a0 */ + u32 tx_pkt_fifo_10_rsv3; + u32 tx_pkt_fifo_11[3]; /* 0x000040b0 */ + u32 tx_pkt_fifo_11_rsv3; + u32 tx_pkt_fifo_12[3]; /* 0x000040c0 */ + u32 tx_pkt_fifo_12_rsv3; + u32 tx_pkt_fifo_13[3]; /* 0x000040d0 */ + u32 tx_pkt_fifo_13_rsv3; + u32 tx_pkt_fifo_14[3]; /* 0x000040e0 */ + u32 tx_pkt_fifo_14_rsv3; + u32 tx_pkt_fifo_15[3]; /* 0x000040f0 */ + u32 tx_pkt_fifo_15_rsv3; + u32 tx_pkt_fifo_16[3]; /* 0x00004100 */ + u32 tx_pkt_fifo_16_rsv3; + u32 tx_pkt_fifo_17[3]; /* 0x00004110 */ + u32 tx_pkt_fifo_17_rsv3; + u32 tx_pkt_fifo_18[3]; /* 0x00004120 */ + u32 tx_pkt_fifo_18_rsv3; + u32 tx_pkt_fifo_19[3]; /* 0x00004130 */ + u32 tx_pkt_fifo_19_rsv3; + u32 tx_pkt_fifo_20[3]; /* 0x00004140 */ + u32 tx_pkt_fifo_20_rsv3; + u32 tx_pkt_fifo_21[3]; /* 0x00004150 */ + u32 tx_pkt_fifo_21_rsv3; + u32 tx_pkt_fifo_22[3]; /* 0x00004160 */ + u32 tx_pkt_fifo_22_rsv3; + u32 tx_pkt_fifo_23[3]; /* 0x00004170 */ + u32 tx_pkt_fifo_23_rsv3; + u32 tx_pkt_fifo_24[3]; /* 0x00004180 */ + u32 tx_pkt_fifo_24_rsv3; + u32 tx_pkt_fifo_25[3]; /* 0x00004190 */ + u32 tx_pkt_fifo_25_rsv3; + u32 tx_pkt_fifo_26[3]; /* 0x000041a0 */ + u32 tx_pkt_fifo_26_rsv3; + u32 tx_pkt_fifo_27[3]; /* 0x000041b0 */ + u32 tx_pkt_fifo_27_rsv3; + u32 tx_pkt_fifo_28[3]; /* 0x000041c0 */ + u32 tx_pkt_fifo_28_rsv3; + u32 tx_pkt_fifo_29[3]; /* 0x000041d0 */ + u32 tx_pkt_fifo_29_rsv3; + u32 tx_pkt_fifo_30[3]; /* 0x000041e0 */ + u32 tx_pkt_fifo_30_rsv3; + u32 tx_pkt_fifo_31[3]; /* 0x000041f0 */ + u32 tx_pkt_fifo_31_rsv3; + u32 tx_pkt_fifo_32[3]; /* 0x00004200 */ + u32 tx_pkt_fifo_32_rsv3; + u32 tx_pkt_fifo_33[3]; /* 0x00004210 */ + u32 tx_pkt_fifo_33_rsv3; + u32 tx_pkt_fifo_34[3]; /* 0x00004220 */ + u32 tx_pkt_fifo_34_rsv3; + u32 tx_pkt_fifo_35[3]; /* 0x00004230 */ + u32 tx_pkt_fifo_35_rsv3; + u32 tx_pkt_fifo_36[3]; /* 0x00004240 */ + u32 tx_pkt_fifo_36_rsv3; + u32 tx_pkt_fifo_37[3]; /* 0x00004250 */ + u32 tx_pkt_fifo_37_rsv3; + u32 tx_pkt_fifo_38[3]; /* 0x00004260 */ + u32 tx_pkt_fifo_38_rsv3; + u32 tx_pkt_fifo_39[3]; /* 0x00004270 */ + u32 tx_pkt_fifo_39_rsv3; + u32 tx_pkt_fifo_40[3]; /* 0x00004280 */ + u32 tx_pkt_fifo_40_rsv3; + u32 tx_pkt_fifo_41[3]; /* 0x00004290 */ + u32 tx_pkt_fifo_41_rsv3; + u32 tx_pkt_fifo_42[3]; /* 0x000042a0 */ + u32 tx_pkt_fifo_42_rsv3; + u32 tx_pkt_fifo_43[3]; /* 0x000042b0 */ + u32 tx_pkt_fifo_43_rsv3; + u32 tx_pkt_fifo_44[3]; /* 0x000042c0 */ + u32 tx_pkt_fifo_44_rsv3; + u32 tx_pkt_fifo_45[3]; /* 0x000042d0 */ + u32 tx_pkt_fifo_45_rsv3; + u32 tx_pkt_fifo_46[3]; /* 0x000042e0 */ + u32 tx_pkt_fifo_46_rsv3; + u32 tx_pkt_fifo_47[3]; /* 0x000042f0 */ + u32 tx_pkt_fifo_47_rsv3; + u32 tx_pkt_fifo_48[3]; /* 0x00004300 */ + u32 tx_pkt_fifo_48_rsv3; + u32 tx_pkt_fifo_49[3]; /* 0x00004310 */ + u32 tx_pkt_fifo_49_rsv3; + u32 tx_pkt_fifo_50[3]; /* 0x00004320 */ + u32 tx_pkt_fifo_50_rsv3; + u32 tx_pkt_fifo_51[3]; /* 0x00004330 */ + u32 tx_pkt_fifo_51_rsv3; + u32 tx_pkt_fifo_52[3]; /* 0x00004340 */ + u32 tx_pkt_fifo_52_rsv3; + u32 tx_pkt_fifo_53[3]; /* 0x00004350 */ + u32 tx_pkt_fifo_53_rsv3; + u32 tx_pkt_fifo_54[3]; /* 0x00004360 */ + u32 tx_pkt_fifo_54_rsv3; + u32 tx_pkt_fifo_55[3]; /* 0x00004370 */ + u32 tx_pkt_fifo_55_rsv3; + u32 tx_pkt_fifo_56[3]; /* 0x00004380 */ + u32 tx_pkt_fifo_56_rsv3; + u32 tx_pkt_fifo_57[3]; /* 0x00004390 */ + u32 tx_pkt_fifo_57_rsv3; + u32 tx_pkt_fifo_58[3]; /* 0x000043a0 */ + u32 tx_pkt_fifo_58_rsv3; + u32 tx_pkt_fifo_59[3]; /* 0x000043b0 */ + u32 tx_pkt_fifo_59_rsv3; + u32 tx_pkt_fifo_60[3]; /* 0x000043c0 */ + u32 tx_pkt_fifo_60_rsv3; + u32 tx_pkt_fifo_61[3]; /* 0x000043d0 */ + u32 tx_pkt_fifo_61_rsv3; + u32 tx_pkt_fifo_62[3]; /* 0x000043e0 */ + u32 tx_pkt_fifo_62_rsv3; + u32 tx_pkt_fifo_63[3]; /* 0x000043f0 */ + u32 tx_pkt_fifo_63_rsv3; + u32 tx_pkt_fifo_64[3]; /* 0x00004400 */ + u32 tx_pkt_fifo_64_rsv3; + u32 tx_pkt_fifo_65[3]; /* 0x00004410 */ + u32 tx_pkt_fifo_65_rsv3; + u32 tx_pkt_fifo_66[3]; /* 0x00004420 */ + u32 tx_pkt_fifo_66_rsv3; + u32 tx_pkt_fifo_67[3]; /* 0x00004430 */ + u32 tx_pkt_fifo_67_rsv3; + u32 tx_pkt_fifo_68[3]; /* 0x00004440 */ + u32 tx_pkt_fifo_68_rsv3; + u32 tx_pkt_fifo_69[3]; /* 0x00004450 */ + u32 tx_pkt_fifo_69_rsv3; + u32 tx_pkt_fifo_70[3]; /* 0x00004460 */ + u32 tx_pkt_fifo_70_rsv3; + u32 tx_pkt_fifo_71[3]; /* 0x00004470 */ + u32 tx_pkt_fifo_71_rsv3; + u32 tx_pkt_fifo_72[3]; /* 0x00004480 */ + u32 tx_pkt_fifo_72_rsv3; + u32 tx_pkt_fifo_73[3]; /* 0x00004490 */ + u32 tx_pkt_fifo_73_rsv3; + u32 tx_pkt_fifo_74[3]; /* 0x000044a0 */ + u32 tx_pkt_fifo_74_rsv3; + u32 tx_pkt_fifo_75[3]; /* 0x000044b0 */ + u32 tx_pkt_fifo_75_rsv3; + u32 tx_pkt_fifo_76[3]; /* 0x000044c0 */ + u32 tx_pkt_fifo_76_rsv3; + u32 tx_pkt_fifo_77[3]; /* 0x000044d0 */ + u32 tx_pkt_fifo_77_rsv3; + u32 tx_pkt_fifo_78[3]; /* 0x000044e0 */ + u32 tx_pkt_fifo_78_rsv3; + u32 tx_pkt_fifo_79[3]; /* 0x000044f0 */ + u32 tx_pkt_fifo_79_rsv3; + u32 tx_pkt_fifo_80[3]; /* 0x00004500 */ + u32 tx_pkt_fifo_80_rsv3; + u32 tx_pkt_fifo_81[3]; /* 0x00004510 */ + u32 tx_pkt_fifo_81_rsv3; + u32 tx_pkt_fifo_82[3]; /* 0x00004520 */ + u32 tx_pkt_fifo_82_rsv3; + u32 tx_pkt_fifo_83[3]; /* 0x00004530 */ + u32 tx_pkt_fifo_83_rsv3; + u32 tx_pkt_fifo_84[3]; /* 0x00004540 */ + u32 tx_pkt_fifo_84_rsv3; + u32 tx_pkt_fifo_85[3]; /* 0x00004550 */ + u32 tx_pkt_fifo_85_rsv3; + u32 tx_pkt_fifo_86[3]; /* 0x00004560 */ + u32 tx_pkt_fifo_86_rsv3; + u32 tx_pkt_fifo_87[3]; /* 0x00004570 */ + u32 tx_pkt_fifo_87_rsv3; + u32 tx_pkt_fifo_88[3]; /* 0x00004580 */ + u32 tx_pkt_fifo_88_rsv3; + u32 tx_pkt_fifo_89[3]; /* 0x00004590 */ + u32 tx_pkt_fifo_89_rsv3; + u32 tx_pkt_fifo_90[3]; /* 0x000045a0 */ + u32 tx_pkt_fifo_90_rsv3; + u32 tx_pkt_fifo_91[3]; /* 0x000045b0 */ + u32 tx_pkt_fifo_91_rsv3; + u32 tx_pkt_fifo_92[3]; /* 0x000045c0 */ + u32 tx_pkt_fifo_92_rsv3; + u32 tx_pkt_fifo_93[3]; /* 0x000045d0 */ + u32 tx_pkt_fifo_93_rsv3; + u32 tx_pkt_fifo_94[3]; /* 0x000045e0 */ + u32 tx_pkt_fifo_94_rsv3; + u32 tx_pkt_fifo_95[3]; /* 0x000045f0 */ + u32 tx_pkt_fifo_95_rsv3; + u32 tx_pkt_fifo_96[3]; /* 0x00004600 */ + u32 tx_pkt_fifo_96_rsv3; + u32 tx_pkt_fifo_97[3]; /* 0x00004610 */ + u32 tx_pkt_fifo_97_rsv3; + u32 tx_pkt_fifo_98[3]; /* 0x00004620 */ + u32 tx_pkt_fifo_98_rsv3; + u32 tx_pkt_fifo_99[3]; /* 0x00004630 */ + u32 tx_pkt_fifo_99_rsv3; + u32 tx_pkt_fifo_100[3]; /* 0x00004640 */ + u32 tx_pkt_fifo_100_rsv3; + u32 tx_pkt_fifo_101[3]; /* 0x00004650 */ + u32 tx_pkt_fifo_101_rsv3; + u32 tx_pkt_fifo_102[3]; /* 0x00004660 */ + u32 tx_pkt_fifo_102_rsv3; + u32 tx_pkt_fifo_103[3]; /* 0x00004670 */ + u32 tx_pkt_fifo_103_rsv3; + u32 tx_pkt_fifo_104[3]; /* 0x00004680 */ + u32 tx_pkt_fifo_104_rsv3; + u32 tx_pkt_fifo_105[3]; /* 0x00004690 */ + u32 tx_pkt_fifo_105_rsv3; + u32 tx_pkt_fifo_106[3]; /* 0x000046a0 */ + u32 tx_pkt_fifo_106_rsv3; + u32 tx_pkt_fifo_107[3]; /* 0x000046b0 */ + u32 tx_pkt_fifo_107_rsv3; + u32 tx_pkt_fifo_108[3]; /* 0x000046c0 */ + u32 tx_pkt_fifo_108_rsv3; + u32 tx_pkt_fifo_109[3]; /* 0x000046d0 */ + u32 tx_pkt_fifo_109_rsv3; + u32 tx_pkt_fifo_110[3]; /* 0x000046e0 */ + u32 tx_pkt_fifo_110_rsv3; + u32 tx_pkt_fifo_111[3]; /* 0x000046f0 */ + u32 tx_pkt_fifo_111_rsv3; + u32 tx_pkt_fifo_112[3]; /* 0x00004700 */ + u32 tx_pkt_fifo_112_rsv3; + u32 tx_pkt_fifo_113[3]; /* 0x00004710 */ + u32 tx_pkt_fifo_113_rsv3; + u32 tx_pkt_fifo_114[3]; /* 0x00004720 */ + u32 tx_pkt_fifo_114_rsv3; + u32 tx_pkt_fifo_115[3]; /* 0x00004730 */ + u32 tx_pkt_fifo_115_rsv3; + u32 tx_pkt_fifo_116[3]; /* 0x00004740 */ + u32 tx_pkt_fifo_116_rsv3; + u32 tx_pkt_fifo_117[3]; /* 0x00004750 */ + u32 tx_pkt_fifo_117_rsv3; + u32 tx_pkt_fifo_118[3]; /* 0x00004760 */ + u32 tx_pkt_fifo_118_rsv3; + u32 tx_pkt_fifo_119[3]; /* 0x00004770 */ + u32 tx_pkt_fifo_119_rsv3; + u32 tx_pkt_fifo_120[3]; /* 0x00004780 */ + u32 tx_pkt_fifo_120_rsv3; + u32 tx_pkt_fifo_121[3]; /* 0x00004790 */ + u32 tx_pkt_fifo_121_rsv3; + u32 tx_pkt_fifo_122[3]; /* 0x000047a0 */ + u32 tx_pkt_fifo_122_rsv3; + u32 tx_pkt_fifo_123[3]; /* 0x000047b0 */ + u32 tx_pkt_fifo_123_rsv3; + u32 tx_pkt_fifo_124[3]; /* 0x000047c0 */ + u32 tx_pkt_fifo_124_rsv3; + u32 tx_pkt_fifo_125[3]; /* 0x000047d0 */ + u32 tx_pkt_fifo_125_rsv3; + u32 tx_pkt_fifo_126[3]; /* 0x000047e0 */ + u32 tx_pkt_fifo_126_rsv3; + u32 tx_pkt_fifo_127[3]; /* 0x000047f0 */ + u32 tx_pkt_fifo_127_rsv3; + u32 tx_pkt_fifo_128[3]; /* 0x00004800 */ + u32 tx_pkt_fifo_128_rsv3; + u32 tx_pkt_fifo_129[3]; /* 0x00004810 */ + u32 tx_pkt_fifo_129_rsv3; + u32 tx_pkt_fifo_130[3]; /* 0x00004820 */ + u32 tx_pkt_fifo_130_rsv3; + u32 tx_pkt_fifo_131[3]; /* 0x00004830 */ + u32 tx_pkt_fifo_131_rsv3; + u32 tx_pkt_fifo_132[3]; /* 0x00004840 */ + u32 tx_pkt_fifo_132_rsv3; + u32 tx_pkt_fifo_133[3]; /* 0x00004850 */ + u32 tx_pkt_fifo_133_rsv3; + u32 tx_pkt_fifo_134[3]; /* 0x00004860 */ + u32 tx_pkt_fifo_134_rsv3; + u32 tx_pkt_fifo_135[3]; /* 0x00004870 */ + u32 tx_pkt_fifo_135_rsv3; + u32 tx_pkt_fifo_136[3]; /* 0x00004880 */ + u32 tx_pkt_fifo_136_rsv3; + u32 tx_pkt_fifo_137[3]; /* 0x00004890 */ + u32 tx_pkt_fifo_137_rsv3; + u32 tx_pkt_fifo_138[3]; /* 0x000048a0 */ + u32 tx_pkt_fifo_138_rsv3; + u32 tx_pkt_fifo_139[3]; /* 0x000048b0 */ + u32 tx_pkt_fifo_139_rsv3; + u32 tx_pkt_fifo_140[3]; /* 0x000048c0 */ + u32 tx_pkt_fifo_140_rsv3; + u32 tx_pkt_fifo_141[3]; /* 0x000048d0 */ + u32 tx_pkt_fifo_141_rsv3; + u32 tx_pkt_fifo_142[3]; /* 0x000048e0 */ + u32 tx_pkt_fifo_142_rsv3; + u32 tx_pkt_fifo_143[3]; /* 0x000048f0 */ + u32 tx_pkt_fifo_143_rsv3; + u32 tx_pkt_fifo_144[3]; /* 0x00004900 */ + u32 tx_pkt_fifo_144_rsv3; + u32 tx_pkt_fifo_145[3]; /* 0x00004910 */ + u32 tx_pkt_fifo_145_rsv3; + u32 tx_pkt_fifo_146[3]; /* 0x00004920 */ + u32 tx_pkt_fifo_146_rsv3; + u32 tx_pkt_fifo_147[3]; /* 0x00004930 */ + u32 tx_pkt_fifo_147_rsv3; + u32 tx_pkt_fifo_148[3]; /* 0x00004940 */ + u32 tx_pkt_fifo_148_rsv3; + u32 tx_pkt_fifo_149[3]; /* 0x00004950 */ + u32 tx_pkt_fifo_149_rsv3; + u32 tx_pkt_fifo_150[3]; /* 0x00004960 */ + u32 tx_pkt_fifo_150_rsv3; + u32 tx_pkt_fifo_151[3]; /* 0x00004970 */ + u32 tx_pkt_fifo_151_rsv3; + u32 tx_pkt_fifo_152[3]; /* 0x00004980 */ + u32 tx_pkt_fifo_152_rsv3; + u32 tx_pkt_fifo_153[3]; /* 0x00004990 */ + u32 tx_pkt_fifo_153_rsv3; + u32 tx_pkt_fifo_154[3]; /* 0x000049a0 */ + u32 tx_pkt_fifo_154_rsv3; + u32 tx_pkt_fifo_155[3]; /* 0x000049b0 */ + u32 tx_pkt_fifo_155_rsv3; + u32 tx_pkt_fifo_156[3]; /* 0x000049c0 */ + u32 tx_pkt_fifo_156_rsv3; + u32 tx_pkt_fifo_157[3]; /* 0x000049d0 */ + u32 tx_pkt_fifo_157_rsv3; + u32 tx_pkt_fifo_158[3]; /* 0x000049e0 */ + u32 tx_pkt_fifo_158_rsv3; + u32 tx_pkt_fifo_159[3]; /* 0x000049f0 */ + u32 tx_pkt_fifo_159_rsv3; + u32 tx_pkt_fifo_160[3]; /* 0x00004a00 */ + u32 tx_pkt_fifo_160_rsv3; + u32 tx_pkt_fifo_161[3]; /* 0x00004a10 */ + u32 tx_pkt_fifo_161_rsv3; + u32 tx_pkt_fifo_162[3]; /* 0x00004a20 */ + u32 tx_pkt_fifo_162_rsv3; + u32 tx_pkt_fifo_163[3]; /* 0x00004a30 */ + u32 tx_pkt_fifo_163_rsv3; + u32 tx_pkt_fifo_164[3]; /* 0x00004a40 */ + u32 tx_pkt_fifo_164_rsv3; + u32 tx_pkt_fifo_165[3]; /* 0x00004a50 */ + u32 tx_pkt_fifo_165_rsv3; + u32 tx_pkt_fifo_166[3]; /* 0x00004a60 */ + u32 tx_pkt_fifo_166_rsv3; + u32 tx_pkt_fifo_167[3]; /* 0x00004a70 */ + u32 tx_pkt_fifo_167_rsv3; + u32 tx_pkt_fifo_168[3]; /* 0x00004a80 */ + u32 tx_pkt_fifo_168_rsv3; + u32 tx_pkt_fifo_169[3]; /* 0x00004a90 */ + u32 tx_pkt_fifo_169_rsv3; + u32 tx_pkt_fifo_170[3]; /* 0x00004aa0 */ + u32 tx_pkt_fifo_170_rsv3; + u32 tx_pkt_fifo_171[3]; /* 0x00004ab0 */ + u32 tx_pkt_fifo_171_rsv3; + u32 tx_pkt_fifo_172[3]; /* 0x00004ac0 */ + u32 tx_pkt_fifo_172_rsv3; + u32 tx_pkt_fifo_173[3]; /* 0x00004ad0 */ + u32 tx_pkt_fifo_173_rsv3; + u32 tx_pkt_fifo_174[3]; /* 0x00004ae0 */ + u32 tx_pkt_fifo_174_rsv3; + u32 tx_pkt_fifo_175[3]; /* 0x00004af0 */ + u32 tx_pkt_fifo_175_rsv3; + u32 tx_pkt_fifo_176[3]; /* 0x00004b00 */ + u32 tx_pkt_fifo_176_rsv3; + u32 tx_pkt_fifo_177[3]; /* 0x00004b10 */ + u32 tx_pkt_fifo_177_rsv3; + u32 tx_pkt_fifo_178[3]; /* 0x00004b20 */ + u32 tx_pkt_fifo_178_rsv3; + u32 tx_pkt_fifo_179[3]; /* 0x00004b30 */ + u32 tx_pkt_fifo_179_rsv3; + u32 tx_pkt_fifo_180[3]; /* 0x00004b40 */ + u32 tx_pkt_fifo_180_rsv3; + u32 tx_pkt_fifo_181[3]; /* 0x00004b50 */ + u32 tx_pkt_fifo_181_rsv3; + u32 tx_pkt_fifo_182[3]; /* 0x00004b60 */ + u32 tx_pkt_fifo_182_rsv3; + u32 tx_pkt_fifo_183[3]; /* 0x00004b70 */ + u32 tx_pkt_fifo_183_rsv3; + u32 tx_pkt_fifo_184[3]; /* 0x00004b80 */ + u32 tx_pkt_fifo_184_rsv3; + u32 tx_pkt_fifo_185[3]; /* 0x00004b90 */ + u32 tx_pkt_fifo_185_rsv3; + u32 tx_pkt_fifo_186[3]; /* 0x00004ba0 */ + u32 tx_pkt_fifo_186_rsv3; + u32 tx_pkt_fifo_187[3]; /* 0x00004bb0 */ + u32 tx_pkt_fifo_187_rsv3; + u32 tx_pkt_fifo_188[3]; /* 0x00004bc0 */ + u32 tx_pkt_fifo_188_rsv3; + u32 tx_pkt_fifo_189[3]; /* 0x00004bd0 */ + u32 tx_pkt_fifo_189_rsv3; + u32 tx_pkt_fifo_190[3]; /* 0x00004be0 */ + u32 tx_pkt_fifo_190_rsv3; + u32 tx_pkt_fifo_191[3]; /* 0x00004bf0 */ + u32 tx_pkt_fifo_191_rsv3; + u32 tx_pkt_fifo_192[3]; /* 0x00004c00 */ + u32 tx_pkt_fifo_192_rsv3; + u32 tx_pkt_fifo_193[3]; /* 0x00004c10 */ + u32 tx_pkt_fifo_193_rsv3; + u32 tx_pkt_fifo_194[3]; /* 0x00004c20 */ + u32 tx_pkt_fifo_194_rsv3; + u32 tx_pkt_fifo_195[3]; /* 0x00004c30 */ + u32 tx_pkt_fifo_195_rsv3; + u32 tx_pkt_fifo_196[3]; /* 0x00004c40 */ + u32 tx_pkt_fifo_196_rsv3; + u32 tx_pkt_fifo_197[3]; /* 0x00004c50 */ + u32 tx_pkt_fifo_197_rsv3; + u32 tx_pkt_fifo_198[3]; /* 0x00004c60 */ + u32 tx_pkt_fifo_198_rsv3; + u32 tx_pkt_fifo_199[3]; /* 0x00004c70 */ + u32 tx_pkt_fifo_199_rsv3; + u32 tx_pkt_fifo_200[3]; /* 0x00004c80 */ + u32 tx_pkt_fifo_200_rsv3; + u32 tx_pkt_fifo_201[3]; /* 0x00004c90 */ + u32 tx_pkt_fifo_201_rsv3; + u32 tx_pkt_fifo_202[3]; /* 0x00004ca0 */ + u32 tx_pkt_fifo_202_rsv3; + u32 tx_pkt_fifo_203[3]; /* 0x00004cb0 */ + u32 tx_pkt_fifo_203_rsv3; + u32 tx_pkt_fifo_204[3]; /* 0x00004cc0 */ + u32 tx_pkt_fifo_204_rsv3; + u32 tx_pkt_fifo_205[3]; /* 0x00004cd0 */ + u32 tx_pkt_fifo_205_rsv3; + u32 tx_pkt_fifo_206[3]; /* 0x00004ce0 */ + u32 tx_pkt_fifo_206_rsv3; + u32 tx_pkt_fifo_207[3]; /* 0x00004cf0 */ + u32 tx_pkt_fifo_207_rsv3; + u32 tx_pkt_fifo_208[3]; /* 0x00004d00 */ + u32 tx_pkt_fifo_208_rsv3; + u32 tx_pkt_fifo_209[3]; /* 0x00004d10 */ + u32 tx_pkt_fifo_209_rsv3; + u32 tx_pkt_fifo_210[3]; /* 0x00004d20 */ + u32 tx_pkt_fifo_210_rsv3; + u32 tx_pkt_fifo_211[3]; /* 0x00004d30 */ + u32 tx_pkt_fifo_211_rsv3; + u32 tx_pkt_fifo_212[3]; /* 0x00004d40 */ + u32 tx_pkt_fifo_212_rsv3; + u32 tx_pkt_fifo_213[3]; /* 0x00004d50 */ + u32 tx_pkt_fifo_213_rsv3; + u32 tx_pkt_fifo_214[3]; /* 0x00004d60 */ + u32 tx_pkt_fifo_214_rsv3; + u32 tx_pkt_fifo_215[3]; /* 0x00004d70 */ + u32 tx_pkt_fifo_215_rsv3; + u32 tx_pkt_fifo_216[3]; /* 0x00004d80 */ + u32 tx_pkt_fifo_216_rsv3; + u32 tx_pkt_fifo_217[3]; /* 0x00004d90 */ + u32 tx_pkt_fifo_217_rsv3; + u32 tx_pkt_fifo_218[3]; /* 0x00004da0 */ + u32 tx_pkt_fifo_218_rsv3; + u32 tx_pkt_fifo_219[3]; /* 0x00004db0 */ + u32 tx_pkt_fifo_219_rsv3; + u32 tx_pkt_fifo_220[3]; /* 0x00004dc0 */ + u32 tx_pkt_fifo_220_rsv3; + u32 tx_pkt_fifo_221[3]; /* 0x00004dd0 */ + u32 tx_pkt_fifo_221_rsv3; + u32 tx_pkt_fifo_222[3]; /* 0x00004de0 */ + u32 tx_pkt_fifo_222_rsv3; + u32 tx_pkt_fifo_223[3]; /* 0x00004df0 */ + u32 tx_pkt_fifo_223_rsv3; + u32 tx_pkt_fifo_224[3]; /* 0x00004e00 */ + u32 tx_pkt_fifo_224_rsv3; + u32 tx_pkt_fifo_225[3]; /* 0x00004e10 */ + u32 tx_pkt_fifo_225_rsv3; + u32 tx_pkt_fifo_226[3]; /* 0x00004e20 */ + u32 tx_pkt_fifo_226_rsv3; + u32 tx_pkt_fifo_227[3]; /* 0x00004e30 */ + u32 tx_pkt_fifo_227_rsv3; + u32 tx_pkt_fifo_228[3]; /* 0x00004e40 */ + u32 tx_pkt_fifo_228_rsv3; + u32 tx_pkt_fifo_229[3]; /* 0x00004e50 */ + u32 tx_pkt_fifo_229_rsv3; + u32 tx_pkt_fifo_230[3]; /* 0x00004e60 */ + u32 tx_pkt_fifo_230_rsv3; + u32 tx_pkt_fifo_231[3]; /* 0x00004e70 */ + u32 tx_pkt_fifo_231_rsv3; + u32 tx_pkt_fifo_232[3]; /* 0x00004e80 */ + u32 tx_pkt_fifo_232_rsv3; + u32 tx_pkt_fifo_233[3]; /* 0x00004e90 */ + u32 tx_pkt_fifo_233_rsv3; + u32 tx_pkt_fifo_234[3]; /* 0x00004ea0 */ + u32 tx_pkt_fifo_234_rsv3; + u32 tx_pkt_fifo_235[3]; /* 0x00004eb0 */ + u32 tx_pkt_fifo_235_rsv3; + u32 tx_pkt_fifo_236[3]; /* 0x00004ec0 */ + u32 tx_pkt_fifo_236_rsv3; + u32 tx_pkt_fifo_237[3]; /* 0x00004ed0 */ + u32 tx_pkt_fifo_237_rsv3; + u32 tx_pkt_fifo_238[3]; /* 0x00004ee0 */ + u32 tx_pkt_fifo_238_rsv3; + u32 tx_pkt_fifo_239[3]; /* 0x00004ef0 */ + u32 tx_pkt_fifo_239_rsv3; + u32 tx_pkt_fifo_240[3]; /* 0x00004f00 */ + u32 tx_pkt_fifo_240_rsv3; + u32 tx_pkt_fifo_241[3]; /* 0x00004f10 */ + u32 tx_pkt_fifo_241_rsv3; + u32 tx_pkt_fifo_242[3]; /* 0x00004f20 */ + u32 tx_pkt_fifo_242_rsv3; + u32 tx_pkt_fifo_243[3]; /* 0x00004f30 */ + u32 tx_pkt_fifo_243_rsv3; + u32 tx_pkt_fifo_244[3]; /* 0x00004f40 */ + u32 tx_pkt_fifo_244_rsv3; + u32 tx_pkt_fifo_245[3]; /* 0x00004f50 */ + u32 tx_pkt_fifo_245_rsv3; + u32 tx_pkt_fifo_246[3]; /* 0x00004f60 */ + u32 tx_pkt_fifo_246_rsv3; + u32 tx_pkt_fifo_247[3]; /* 0x00004f70 */ + u32 tx_pkt_fifo_247_rsv3; + u32 tx_pkt_fifo_248[3]; /* 0x00004f80 */ + u32 tx_pkt_fifo_248_rsv3; + u32 tx_pkt_fifo_249[3]; /* 0x00004f90 */ + u32 tx_pkt_fifo_249_rsv3; + u32 tx_pkt_fifo_250[3]; /* 0x00004fa0 */ + u32 tx_pkt_fifo_250_rsv3; + u32 tx_pkt_fifo_251[3]; /* 0x00004fb0 */ + u32 tx_pkt_fifo_251_rsv3; + u32 tx_pkt_fifo_252[3]; /* 0x00004fc0 */ + u32 tx_pkt_fifo_252_rsv3; + u32 tx_pkt_fifo_253[3]; /* 0x00004fd0 */ + u32 tx_pkt_fifo_253_rsv3; + u32 tx_pkt_fifo_254[3]; /* 0x00004fe0 */ + u32 tx_pkt_fifo_254_rsv3; + u32 tx_pkt_fifo_255[3]; /* 0x00004ff0 */ + u32 tx_pkt_fifo_255_rsv3; + u32 tx_pkt_fifo_256[3]; /* 0x00005000 */ + u32 tx_pkt_fifo_256_rsv3; + u32 tx_pkt_fifo_257[3]; /* 0x00005010 */ + u32 tx_pkt_fifo_257_rsv3; + u32 tx_pkt_fifo_258[3]; /* 0x00005020 */ + u32 tx_pkt_fifo_258_rsv3; + u32 tx_pkt_fifo_259[3]; /* 0x00005030 */ + u32 tx_pkt_fifo_259_rsv3; + u32 tx_pkt_fifo_260[3]; /* 0x00005040 */ + u32 tx_pkt_fifo_260_rsv3; + u32 tx_pkt_fifo_261[3]; /* 0x00005050 */ + u32 tx_pkt_fifo_261_rsv3; + u32 tx_pkt_fifo_262[3]; /* 0x00005060 */ + u32 tx_pkt_fifo_262_rsv3; + u32 tx_pkt_fifo_263[3]; /* 0x00005070 */ + u32 tx_pkt_fifo_263_rsv3; + u32 tx_pkt_fifo_264[3]; /* 0x00005080 */ + u32 tx_pkt_fifo_264_rsv3; + u32 tx_pkt_fifo_265[3]; /* 0x00005090 */ + u32 tx_pkt_fifo_265_rsv3; + u32 tx_pkt_fifo_266[3]; /* 0x000050a0 */ + u32 tx_pkt_fifo_266_rsv3; + u32 tx_pkt_fifo_267[3]; /* 0x000050b0 */ + u32 tx_pkt_fifo_267_rsv3; + u32 tx_pkt_fifo_268[3]; /* 0x000050c0 */ + u32 tx_pkt_fifo_268_rsv3; + u32 tx_pkt_fifo_269[3]; /* 0x000050d0 */ + u32 tx_pkt_fifo_269_rsv3; + u32 tx_pkt_fifo_270[3]; /* 0x000050e0 */ + u32 tx_pkt_fifo_270_rsv3; + u32 tx_pkt_fifo_271[3]; /* 0x000050f0 */ + u32 tx_pkt_fifo_271_rsv3; + u32 tx_pkt_fifo_272[3]; /* 0x00005100 */ + u32 tx_pkt_fifo_272_rsv3; + u32 tx_pkt_fifo_273[3]; /* 0x00005110 */ + u32 tx_pkt_fifo_273_rsv3; + u32 tx_pkt_fifo_274[3]; /* 0x00005120 */ + u32 tx_pkt_fifo_274_rsv3; + u32 tx_pkt_fifo_275[3]; /* 0x00005130 */ + u32 tx_pkt_fifo_275_rsv3; + u32 tx_pkt_fifo_276[3]; /* 0x00005140 */ + u32 tx_pkt_fifo_276_rsv3; + u32 tx_pkt_fifo_277[3]; /* 0x00005150 */ + u32 tx_pkt_fifo_277_rsv3; + u32 tx_pkt_fifo_278[3]; /* 0x00005160 */ + u32 tx_pkt_fifo_278_rsv3; + u32 tx_pkt_fifo_279[3]; /* 0x00005170 */ + u32 tx_pkt_fifo_279_rsv3; + u32 tx_pkt_fifo_280[3]; /* 0x00005180 */ + u32 tx_pkt_fifo_280_rsv3; + u32 tx_pkt_fifo_281[3]; /* 0x00005190 */ + u32 tx_pkt_fifo_281_rsv3; + u32 tx_pkt_fifo_282[3]; /* 0x000051a0 */ + u32 tx_pkt_fifo_282_rsv3; + u32 tx_pkt_fifo_283[3]; /* 0x000051b0 */ + u32 tx_pkt_fifo_283_rsv3; + u32 tx_pkt_fifo_284[3]; /* 0x000051c0 */ + u32 tx_pkt_fifo_284_rsv3; + u32 tx_pkt_fifo_285[3]; /* 0x000051d0 */ + u32 tx_pkt_fifo_285_rsv3; + u32 tx_pkt_fifo_286[3]; /* 0x000051e0 */ + u32 tx_pkt_fifo_286_rsv3; + u32 tx_pkt_fifo_287[3]; /* 0x000051f0 */ + u32 tx_pkt_fifo_287_rsv3; + u32 tx_pkt_fifo_288[3]; /* 0x00005200 */ + u32 tx_pkt_fifo_288_rsv3; + u32 tx_pkt_fifo_289[3]; /* 0x00005210 */ + u32 tx_pkt_fifo_289_rsv3; + u32 tx_pkt_fifo_290[3]; /* 0x00005220 */ + u32 tx_pkt_fifo_290_rsv3; + u32 tx_pkt_fifo_291[3]; /* 0x00005230 */ + u32 tx_pkt_fifo_291_rsv3; + u32 tx_pkt_fifo_292[3]; /* 0x00005240 */ + u32 tx_pkt_fifo_292_rsv3; + u32 tx_pkt_fifo_293[3]; /* 0x00005250 */ + u32 tx_pkt_fifo_293_rsv3; + u32 tx_pkt_fifo_294[3]; /* 0x00005260 */ + u32 tx_pkt_fifo_294_rsv3; + u32 tx_pkt_fifo_295[3]; /* 0x00005270 */ + u32 tx_pkt_fifo_295_rsv3; + u32 tx_pkt_fifo_296[3]; /* 0x00005280 */ + u32 tx_pkt_fifo_296_rsv3; + u32 tx_pkt_fifo_297[3]; /* 0x00005290 */ + u32 tx_pkt_fifo_297_rsv3; + u32 tx_pkt_fifo_298[3]; /* 0x000052a0 */ + u32 tx_pkt_fifo_298_rsv3; + u32 tx_pkt_fifo_299[3]; /* 0x000052b0 */ + u32 tx_pkt_fifo_299_rsv3; + u32 tx_pkt_fifo_300[3]; /* 0x000052c0 */ + u32 tx_pkt_fifo_300_rsv3; + u32 tx_pkt_fifo_301[3]; /* 0x000052d0 */ + u32 tx_pkt_fifo_301_rsv3; + u32 tx_pkt_fifo_302[3]; /* 0x000052e0 */ + u32 tx_pkt_fifo_302_rsv3; + u32 tx_pkt_fifo_303[3]; /* 0x000052f0 */ + u32 tx_pkt_fifo_303_rsv3; + u32 tx_pkt_fifo_304[3]; /* 0x00005300 */ + u32 tx_pkt_fifo_304_rsv3; + u32 tx_pkt_fifo_305[3]; /* 0x00005310 */ + u32 tx_pkt_fifo_305_rsv3; + u32 tx_pkt_fifo_306[3]; /* 0x00005320 */ + u32 tx_pkt_fifo_306_rsv3; + u32 tx_pkt_fifo_307[3]; /* 0x00005330 */ + u32 tx_pkt_fifo_307_rsv3; + u32 tx_pkt_fifo_308[3]; /* 0x00005340 */ + u32 tx_pkt_fifo_308_rsv3; + u32 tx_pkt_fifo_309[3]; /* 0x00005350 */ + u32 tx_pkt_fifo_309_rsv3; + u32 tx_pkt_fifo_310[3]; /* 0x00005360 */ + u32 tx_pkt_fifo_310_rsv3; + u32 tx_pkt_fifo_311[3]; /* 0x00005370 */ + u32 tx_pkt_fifo_311_rsv3; + u32 tx_pkt_fifo_312[3]; /* 0x00005380 */ + u32 tx_pkt_fifo_312_rsv3; + u32 tx_pkt_fifo_313[3]; /* 0x00005390 */ + u32 tx_pkt_fifo_313_rsv3; + u32 tx_pkt_fifo_314[3]; /* 0x000053a0 */ + u32 tx_pkt_fifo_314_rsv3; + u32 tx_pkt_fifo_315[3]; /* 0x000053b0 */ + u32 tx_pkt_fifo_315_rsv3; + u32 tx_pkt_fifo_316[3]; /* 0x000053c0 */ + u32 tx_pkt_fifo_316_rsv3; + u32 tx_pkt_fifo_317[3]; /* 0x000053d0 */ + u32 tx_pkt_fifo_317_rsv3; + u32 tx_pkt_fifo_318[3]; /* 0x000053e0 */ + u32 tx_pkt_fifo_318_rsv3; + u32 tx_pkt_fifo_319[3]; /* 0x000053f0 */ + u32 tx_pkt_fifo_319_rsv3; + u32 tx_pkt_fifo_320[3]; /* 0x00005400 */ + u32 tx_pkt_fifo_320_rsv3; + u32 tx_pkt_fifo_321[3]; /* 0x00005410 */ + u32 tx_pkt_fifo_321_rsv3; + u32 tx_pkt_fifo_322[3]; /* 0x00005420 */ + u32 tx_pkt_fifo_322_rsv3; + u32 tx_pkt_fifo_323[3]; /* 0x00005430 */ + u32 tx_pkt_fifo_323_rsv3; + u32 tx_pkt_fifo_324[3]; /* 0x00005440 */ + u32 tx_pkt_fifo_324_rsv3; + u32 tx_pkt_fifo_325[3]; /* 0x00005450 */ + u32 tx_pkt_fifo_325_rsv3; + u32 tx_pkt_fifo_326[3]; /* 0x00005460 */ + u32 tx_pkt_fifo_326_rsv3; + u32 tx_pkt_fifo_327[3]; /* 0x00005470 */ + u32 tx_pkt_fifo_327_rsv3; + u32 tx_pkt_fifo_328[3]; /* 0x00005480 */ + u32 tx_pkt_fifo_328_rsv3; + u32 tx_pkt_fifo_329[3]; /* 0x00005490 */ + u32 tx_pkt_fifo_329_rsv3; + u32 tx_pkt_fifo_330[3]; /* 0x000054a0 */ + u32 tx_pkt_fifo_330_rsv3; + u32 tx_pkt_fifo_331[3]; /* 0x000054b0 */ + u32 tx_pkt_fifo_331_rsv3; + u32 tx_pkt_fifo_332[3]; /* 0x000054c0 */ + u32 tx_pkt_fifo_332_rsv3; + u32 tx_pkt_fifo_333[3]; /* 0x000054d0 */ + u32 tx_pkt_fifo_333_rsv3; + u32 tx_pkt_fifo_334[3]; /* 0x000054e0 */ + u32 tx_pkt_fifo_334_rsv3; + u32 tx_pkt_fifo_335[3]; /* 0x000054f0 */ + u32 tx_pkt_fifo_335_rsv3; + u32 tx_pkt_fifo_336[3]; /* 0x00005500 */ + u32 tx_pkt_fifo_336_rsv3; + u32 tx_pkt_fifo_337[3]; /* 0x00005510 */ + u32 tx_pkt_fifo_337_rsv3; + u32 tx_pkt_fifo_338[3]; /* 0x00005520 */ + u32 tx_pkt_fifo_338_rsv3; + u32 tx_pkt_fifo_339[3]; /* 0x00005530 */ + u32 tx_pkt_fifo_339_rsv3; + u32 tx_pkt_fifo_340[3]; /* 0x00005540 */ + u32 tx_pkt_fifo_340_rsv3; + u32 tx_pkt_fifo_341[3]; /* 0x00005550 */ + u32 tx_pkt_fifo_341_rsv3; + u32 tx_pkt_fifo_342[3]; /* 0x00005560 */ + u32 tx_pkt_fifo_342_rsv3; + u32 tx_pkt_fifo_343[3]; /* 0x00005570 */ + u32 tx_pkt_fifo_343_rsv3; + u32 tx_pkt_fifo_344[3]; /* 0x00005580 */ + u32 tx_pkt_fifo_344_rsv3; + u32 tx_pkt_fifo_345[3]; /* 0x00005590 */ + u32 tx_pkt_fifo_345_rsv3; + u32 tx_pkt_fifo_346[3]; /* 0x000055a0 */ + u32 tx_pkt_fifo_346_rsv3; + u32 tx_pkt_fifo_347[3]; /* 0x000055b0 */ + u32 tx_pkt_fifo_347_rsv3; + u32 tx_pkt_fifo_348[3]; /* 0x000055c0 */ + u32 tx_pkt_fifo_348_rsv3; + u32 tx_pkt_fifo_349[3]; /* 0x000055d0 */ + u32 tx_pkt_fifo_349_rsv3; + u32 tx_pkt_fifo_350[3]; /* 0x000055e0 */ + u32 tx_pkt_fifo_350_rsv3; + u32 tx_pkt_fifo_351[3]; /* 0x000055f0 */ + u32 tx_pkt_fifo_351_rsv3; + u32 tx_pkt_fifo_352[3]; /* 0x00005600 */ + u32 tx_pkt_fifo_352_rsv3; + u32 tx_pkt_fifo_353[3]; /* 0x00005610 */ + u32 tx_pkt_fifo_353_rsv3; + u32 tx_pkt_fifo_354[3]; /* 0x00005620 */ + u32 tx_pkt_fifo_354_rsv3; + u32 tx_pkt_fifo_355[3]; /* 0x00005630 */ + u32 tx_pkt_fifo_355_rsv3; + u32 tx_pkt_fifo_356[3]; /* 0x00005640 */ + u32 tx_pkt_fifo_356_rsv3; + u32 tx_pkt_fifo_357[3]; /* 0x00005650 */ + u32 tx_pkt_fifo_357_rsv3; + u32 tx_pkt_fifo_358[3]; /* 0x00005660 */ + u32 tx_pkt_fifo_358_rsv3; + u32 tx_pkt_fifo_359[3]; /* 0x00005670 */ + u32 tx_pkt_fifo_359_rsv3; + u32 tx_pkt_fifo_360[3]; /* 0x00005680 */ + u32 tx_pkt_fifo_360_rsv3; + u32 tx_pkt_fifo_361[3]; /* 0x00005690 */ + u32 tx_pkt_fifo_361_rsv3; + u32 tx_pkt_fifo_362[3]; /* 0x000056a0 */ + u32 tx_pkt_fifo_362_rsv3; + u32 tx_pkt_fifo_363[3]; /* 0x000056b0 */ + u32 tx_pkt_fifo_363_rsv3; + u32 tx_pkt_fifo_364[3]; /* 0x000056c0 */ + u32 tx_pkt_fifo_364_rsv3; + u32 tx_pkt_fifo_365[3]; /* 0x000056d0 */ + u32 tx_pkt_fifo_365_rsv3; + u32 tx_pkt_fifo_366[3]; /* 0x000056e0 */ + u32 tx_pkt_fifo_366_rsv3; + u32 tx_pkt_fifo_367[3]; /* 0x000056f0 */ + u32 tx_pkt_fifo_367_rsv3; + u32 tx_pkt_fifo_368[3]; /* 0x00005700 */ + u32 tx_pkt_fifo_368_rsv3; + u32 tx_pkt_fifo_369[3]; /* 0x00005710 */ + u32 tx_pkt_fifo_369_rsv3; + u32 tx_pkt_fifo_370[3]; /* 0x00005720 */ + u32 tx_pkt_fifo_370_rsv3; + u32 tx_pkt_fifo_371[3]; /* 0x00005730 */ + u32 tx_pkt_fifo_371_rsv3; + u32 tx_pkt_fifo_372[3]; /* 0x00005740 */ + u32 tx_pkt_fifo_372_rsv3; + u32 tx_pkt_fifo_373[3]; /* 0x00005750 */ + u32 tx_pkt_fifo_373_rsv3; + u32 tx_pkt_fifo_374[3]; /* 0x00005760 */ + u32 tx_pkt_fifo_374_rsv3; + u32 tx_pkt_fifo_375[3]; /* 0x00005770 */ + u32 tx_pkt_fifo_375_rsv3; + u32 tx_pkt_fifo_376[3]; /* 0x00005780 */ + u32 tx_pkt_fifo_376_rsv3; + u32 tx_pkt_fifo_377[3]; /* 0x00005790 */ + u32 tx_pkt_fifo_377_rsv3; + u32 tx_pkt_fifo_378[3]; /* 0x000057a0 */ + u32 tx_pkt_fifo_378_rsv3; + u32 tx_pkt_fifo_379[3]; /* 0x000057b0 */ + u32 tx_pkt_fifo_379_rsv3; + u32 tx_pkt_fifo_380[3]; /* 0x000057c0 */ + u32 tx_pkt_fifo_380_rsv3; + u32 tx_pkt_fifo_381[3]; /* 0x000057d0 */ + u32 tx_pkt_fifo_381_rsv3; + u32 tx_pkt_fifo_382[3]; /* 0x000057e0 */ + u32 tx_pkt_fifo_382_rsv3; + u32 tx_pkt_fifo_383[3]; /* 0x000057f0 */ + u32 tx_pkt_fifo_383_rsv3; + u32 tx_pkt_fifo_384[3]; /* 0x00005800 */ + u32 tx_pkt_fifo_384_rsv3; + u32 tx_pkt_fifo_385[3]; /* 0x00005810 */ + u32 tx_pkt_fifo_385_rsv3; + u32 tx_pkt_fifo_386[3]; /* 0x00005820 */ + u32 tx_pkt_fifo_386_rsv3; + u32 tx_pkt_fifo_387[3]; /* 0x00005830 */ + u32 tx_pkt_fifo_387_rsv3; + u32 tx_pkt_fifo_388[3]; /* 0x00005840 */ + u32 tx_pkt_fifo_388_rsv3; + u32 tx_pkt_fifo_389[3]; /* 0x00005850 */ + u32 tx_pkt_fifo_389_rsv3; + u32 tx_pkt_fifo_390[3]; /* 0x00005860 */ + u32 tx_pkt_fifo_390_rsv3; + u32 tx_pkt_fifo_391[3]; /* 0x00005870 */ + u32 tx_pkt_fifo_391_rsv3; + u32 tx_pkt_fifo_392[3]; /* 0x00005880 */ + u32 tx_pkt_fifo_392_rsv3; + u32 tx_pkt_fifo_393[3]; /* 0x00005890 */ + u32 tx_pkt_fifo_393_rsv3; + u32 tx_pkt_fifo_394[3]; /* 0x000058a0 */ + u32 tx_pkt_fifo_394_rsv3; + u32 tx_pkt_fifo_395[3]; /* 0x000058b0 */ + u32 tx_pkt_fifo_395_rsv3; + u32 tx_pkt_fifo_396[3]; /* 0x000058c0 */ + u32 tx_pkt_fifo_396_rsv3; + u32 tx_pkt_fifo_397[3]; /* 0x000058d0 */ + u32 tx_pkt_fifo_397_rsv3; + u32 tx_pkt_fifo_398[3]; /* 0x000058e0 */ + u32 tx_pkt_fifo_398_rsv3; + u32 tx_pkt_fifo_399[3]; /* 0x000058f0 */ + u32 tx_pkt_fifo_399_rsv3; + u32 tx_pkt_fifo_400[3]; /* 0x00005900 */ + u32 tx_pkt_fifo_400_rsv3; + u32 tx_pkt_fifo_401[3]; /* 0x00005910 */ + u32 tx_pkt_fifo_401_rsv3; + u32 tx_pkt_fifo_402[3]; /* 0x00005920 */ + u32 tx_pkt_fifo_402_rsv3; + u32 tx_pkt_fifo_403[3]; /* 0x00005930 */ + u32 tx_pkt_fifo_403_rsv3; + u32 tx_pkt_fifo_404[3]; /* 0x00005940 */ + u32 tx_pkt_fifo_404_rsv3; + u32 tx_pkt_fifo_405[3]; /* 0x00005950 */ + u32 tx_pkt_fifo_405_rsv3; + u32 tx_pkt_fifo_406[3]; /* 0x00005960 */ + u32 tx_pkt_fifo_406_rsv3; + u32 tx_pkt_fifo_407[3]; /* 0x00005970 */ + u32 tx_pkt_fifo_407_rsv3; + u32 tx_pkt_fifo_408[3]; /* 0x00005980 */ + u32 tx_pkt_fifo_408_rsv3; + u32 tx_pkt_fifo_409[3]; /* 0x00005990 */ + u32 tx_pkt_fifo_409_rsv3; + u32 tx_pkt_fifo_410[3]; /* 0x000059a0 */ + u32 tx_pkt_fifo_410_rsv3; + u32 tx_pkt_fifo_411[3]; /* 0x000059b0 */ + u32 tx_pkt_fifo_411_rsv3; + u32 tx_pkt_fifo_412[3]; /* 0x000059c0 */ + u32 tx_pkt_fifo_412_rsv3; + u32 tx_pkt_fifo_413[3]; /* 0x000059d0 */ + u32 tx_pkt_fifo_413_rsv3; + u32 tx_pkt_fifo_414[3]; /* 0x000059e0 */ + u32 tx_pkt_fifo_414_rsv3; + u32 tx_pkt_fifo_415[3]; /* 0x000059f0 */ + u32 tx_pkt_fifo_415_rsv3; + u32 tx_pkt_fifo_416[3]; /* 0x00005a00 */ + u32 tx_pkt_fifo_416_rsv3; + u32 tx_pkt_fifo_417[3]; /* 0x00005a10 */ + u32 tx_pkt_fifo_417_rsv3; + u32 tx_pkt_fifo_418[3]; /* 0x00005a20 */ + u32 tx_pkt_fifo_418_rsv3; + u32 tx_pkt_fifo_419[3]; /* 0x00005a30 */ + u32 tx_pkt_fifo_419_rsv3; + u32 tx_pkt_fifo_420[3]; /* 0x00005a40 */ + u32 tx_pkt_fifo_420_rsv3; + u32 tx_pkt_fifo_421[3]; /* 0x00005a50 */ + u32 tx_pkt_fifo_421_rsv3; + u32 tx_pkt_fifo_422[3]; /* 0x00005a60 */ + u32 tx_pkt_fifo_422_rsv3; + u32 tx_pkt_fifo_423[3]; /* 0x00005a70 */ + u32 tx_pkt_fifo_423_rsv3; + u32 tx_pkt_fifo_424[3]; /* 0x00005a80 */ + u32 tx_pkt_fifo_424_rsv3; + u32 tx_pkt_fifo_425[3]; /* 0x00005a90 */ + u32 tx_pkt_fifo_425_rsv3; + u32 tx_pkt_fifo_426[3]; /* 0x00005aa0 */ + u32 tx_pkt_fifo_426_rsv3; + u32 tx_pkt_fifo_427[3]; /* 0x00005ab0 */ + u32 tx_pkt_fifo_427_rsv3; + u32 tx_pkt_fifo_428[3]; /* 0x00005ac0 */ + u32 tx_pkt_fifo_428_rsv3; + u32 tx_pkt_fifo_429[3]; /* 0x00005ad0 */ + u32 tx_pkt_fifo_429_rsv3; + u32 tx_pkt_fifo_430[3]; /* 0x00005ae0 */ + u32 tx_pkt_fifo_430_rsv3; + u32 tx_pkt_fifo_431[3]; /* 0x00005af0 */ + u32 tx_pkt_fifo_431_rsv3; + u32 tx_pkt_fifo_432[3]; /* 0x00005b00 */ + u32 tx_pkt_fifo_432_rsv3; + u32 tx_pkt_fifo_433[3]; /* 0x00005b10 */ + u32 tx_pkt_fifo_433_rsv3; + u32 tx_pkt_fifo_434[3]; /* 0x00005b20 */ + u32 tx_pkt_fifo_434_rsv3; + u32 tx_pkt_fifo_435[3]; /* 0x00005b30 */ + u32 tx_pkt_fifo_435_rsv3; + u32 tx_pkt_fifo_436[3]; /* 0x00005b40 */ + u32 tx_pkt_fifo_436_rsv3; + u32 tx_pkt_fifo_437[3]; /* 0x00005b50 */ + u32 tx_pkt_fifo_437_rsv3; + u32 tx_pkt_fifo_438[3]; /* 0x00005b60 */ + u32 tx_pkt_fifo_438_rsv3; + u32 tx_pkt_fifo_439[3]; /* 0x00005b70 */ + u32 tx_pkt_fifo_439_rsv3; + u32 tx_pkt_fifo_440[3]; /* 0x00005b80 */ + u32 tx_pkt_fifo_440_rsv3; + u32 tx_pkt_fifo_441[3]; /* 0x00005b90 */ + u32 tx_pkt_fifo_441_rsv3; + u32 tx_pkt_fifo_442[3]; /* 0x00005ba0 */ + u32 tx_pkt_fifo_442_rsv3; + u32 tx_pkt_fifo_443[3]; /* 0x00005bb0 */ + u32 tx_pkt_fifo_443_rsv3; + u32 tx_pkt_fifo_444[3]; /* 0x00005bc0 */ + u32 tx_pkt_fifo_444_rsv3; + u32 tx_pkt_fifo_445[3]; /* 0x00005bd0 */ + u32 tx_pkt_fifo_445_rsv3; + u32 tx_pkt_fifo_446[3]; /* 0x00005be0 */ + u32 tx_pkt_fifo_446_rsv3; + u32 tx_pkt_fifo_447[3]; /* 0x00005bf0 */ + u32 tx_pkt_fifo_447_rsv3; + u32 tx_pkt_fifo_448[3]; /* 0x00005c00 */ + u32 tx_pkt_fifo_448_rsv3; + u32 tx_pkt_fifo_449[3]; /* 0x00005c10 */ + u32 tx_pkt_fifo_449_rsv3; + u32 tx_pkt_fifo_450[3]; /* 0x00005c20 */ + u32 tx_pkt_fifo_450_rsv3; + u32 tx_pkt_fifo_451[3]; /* 0x00005c30 */ + u32 tx_pkt_fifo_451_rsv3; + u32 tx_pkt_fifo_452[3]; /* 0x00005c40 */ + u32 tx_pkt_fifo_452_rsv3; + u32 tx_pkt_fifo_453[3]; /* 0x00005c50 */ + u32 tx_pkt_fifo_453_rsv3; + u32 tx_pkt_fifo_454[3]; /* 0x00005c60 */ + u32 tx_pkt_fifo_454_rsv3; + u32 tx_pkt_fifo_455[3]; /* 0x00005c70 */ + u32 tx_pkt_fifo_455_rsv3; + u32 tx_pkt_fifo_456[3]; /* 0x00005c80 */ + u32 tx_pkt_fifo_456_rsv3; + u32 tx_pkt_fifo_457[3]; /* 0x00005c90 */ + u32 tx_pkt_fifo_457_rsv3; + u32 tx_pkt_fifo_458[3]; /* 0x00005ca0 */ + u32 tx_pkt_fifo_458_rsv3; + u32 tx_pkt_fifo_459[3]; /* 0x00005cb0 */ + u32 tx_pkt_fifo_459_rsv3; + u32 tx_pkt_fifo_460[3]; /* 0x00005cc0 */ + u32 tx_pkt_fifo_460_rsv3; + u32 tx_pkt_fifo_461[3]; /* 0x00005cd0 */ + u32 tx_pkt_fifo_461_rsv3; + u32 tx_pkt_fifo_462[3]; /* 0x00005ce0 */ + u32 tx_pkt_fifo_462_rsv3; + u32 tx_pkt_fifo_463[3]; /* 0x00005cf0 */ + u32 tx_pkt_fifo_463_rsv3; + u32 tx_pkt_fifo_464[3]; /* 0x00005d00 */ + u32 tx_pkt_fifo_464_rsv3; + u32 tx_pkt_fifo_465[3]; /* 0x00005d10 */ + u32 tx_pkt_fifo_465_rsv3; + u32 tx_pkt_fifo_466[3]; /* 0x00005d20 */ + u32 tx_pkt_fifo_466_rsv3; + u32 tx_pkt_fifo_467[3]; /* 0x00005d30 */ + u32 tx_pkt_fifo_467_rsv3; + u32 tx_pkt_fifo_468[3]; /* 0x00005d40 */ + u32 tx_pkt_fifo_468_rsv3; + u32 tx_pkt_fifo_469[3]; /* 0x00005d50 */ + u32 tx_pkt_fifo_469_rsv3; + u32 tx_pkt_fifo_470[3]; /* 0x00005d60 */ + u32 tx_pkt_fifo_470_rsv3; + u32 tx_pkt_fifo_471[3]; /* 0x00005d70 */ + u32 tx_pkt_fifo_471_rsv3; + u32 tx_pkt_fifo_472[3]; /* 0x00005d80 */ + u32 tx_pkt_fifo_472_rsv3; + u32 tx_pkt_fifo_473[3]; /* 0x00005d90 */ + u32 tx_pkt_fifo_473_rsv3; + u32 tx_pkt_fifo_474[3]; /* 0x00005da0 */ + u32 tx_pkt_fifo_474_rsv3; + u32 tx_pkt_fifo_475[3]; /* 0x00005db0 */ + u32 tx_pkt_fifo_475_rsv3; + u32 tx_pkt_fifo_476[3]; /* 0x00005dc0 */ + u32 tx_pkt_fifo_476_rsv3; + u32 tx_pkt_fifo_477[3]; /* 0x00005dd0 */ + u32 tx_pkt_fifo_477_rsv3; + u32 tx_pkt_fifo_478[3]; /* 0x00005de0 */ + u32 tx_pkt_fifo_478_rsv3; + u32 tx_pkt_fifo_479[3]; /* 0x00005df0 */ + u32 tx_pkt_fifo_479_rsv3; + u32 tx_pkt_fifo_480[3]; /* 0x00005e00 */ + u32 tx_pkt_fifo_480_rsv3; + u32 tx_pkt_fifo_481[3]; /* 0x00005e10 */ + u32 tx_pkt_fifo_481_rsv3; + u32 tx_pkt_fifo_482[3]; /* 0x00005e20 */ + u32 tx_pkt_fifo_482_rsv3; + u32 tx_pkt_fifo_483[3]; /* 0x00005e30 */ + u32 tx_pkt_fifo_483_rsv3; + u32 tx_pkt_fifo_484[3]; /* 0x00005e40 */ + u32 tx_pkt_fifo_484_rsv3; + u32 tx_pkt_fifo_485[3]; /* 0x00005e50 */ + u32 tx_pkt_fifo_485_rsv3; + u32 tx_pkt_fifo_486[3]; /* 0x00005e60 */ + u32 tx_pkt_fifo_486_rsv3; + u32 tx_pkt_fifo_487[3]; /* 0x00005e70 */ + u32 tx_pkt_fifo_487_rsv3; + u32 tx_pkt_fifo_488[3]; /* 0x00005e80 */ + u32 tx_pkt_fifo_488_rsv3; + u32 tx_pkt_fifo_489[3]; /* 0x00005e90 */ + u32 tx_pkt_fifo_489_rsv3; + u32 tx_pkt_fifo_490[3]; /* 0x00005ea0 */ + u32 tx_pkt_fifo_490_rsv3; + u32 tx_pkt_fifo_491[3]; /* 0x00005eb0 */ + u32 tx_pkt_fifo_491_rsv3; + u32 tx_pkt_fifo_492[3]; /* 0x00005ec0 */ + u32 tx_pkt_fifo_492_rsv3; + u32 tx_pkt_fifo_493[3]; /* 0x00005ed0 */ + u32 tx_pkt_fifo_493_rsv3; + u32 tx_pkt_fifo_494[3]; /* 0x00005ee0 */ + u32 tx_pkt_fifo_494_rsv3; + u32 tx_pkt_fifo_495[3]; /* 0x00005ef0 */ + u32 tx_pkt_fifo_495_rsv3; + u32 tx_pkt_fifo_496[3]; /* 0x00005f00 */ + u32 tx_pkt_fifo_496_rsv3; + u32 tx_pkt_fifo_497[3]; /* 0x00005f10 */ + u32 tx_pkt_fifo_497_rsv3; + u32 tx_pkt_fifo_498[3]; /* 0x00005f20 */ + u32 tx_pkt_fifo_498_rsv3; + u32 tx_pkt_fifo_499[3]; /* 0x00005f30 */ + u32 tx_pkt_fifo_499_rsv3; + u32 tx_pkt_fifo_500[3]; /* 0x00005f40 */ + u32 tx_pkt_fifo_500_rsv3; + u32 tx_pkt_fifo_501[3]; /* 0x00005f50 */ + u32 tx_pkt_fifo_501_rsv3; + u32 tx_pkt_fifo_502[3]; /* 0x00005f60 */ + u32 tx_pkt_fifo_502_rsv3; + u32 tx_pkt_fifo_503[3]; /* 0x00005f70 */ + u32 tx_pkt_fifo_503_rsv3; + u32 tx_pkt_fifo_504[3]; /* 0x00005f80 */ + u32 tx_pkt_fifo_504_rsv3; + u32 tx_pkt_fifo_505[3]; /* 0x00005f90 */ + u32 tx_pkt_fifo_505_rsv3; + u32 tx_pkt_fifo_506[3]; /* 0x00005fa0 */ + u32 tx_pkt_fifo_506_rsv3; + u32 tx_pkt_fifo_507[3]; /* 0x00005fb0 */ + u32 tx_pkt_fifo_507_rsv3; + u32 tx_pkt_fifo_508[3]; /* 0x00005fc0 */ + u32 tx_pkt_fifo_508_rsv3; + u32 tx_pkt_fifo_509[3]; /* 0x00005fd0 */ + u32 tx_pkt_fifo_509_rsv3; + u32 tx_pkt_fifo_510[3]; /* 0x00005fe0 */ + u32 tx_pkt_fifo_510_rsv3; + u32 tx_pkt_fifo_511[3]; /* 0x00005ff0 */ + u32 tx_pkt_fifo_511_rsv3; + u32 tx_pkt_fifo_512[3]; /* 0x00006000 */ + u32 tx_pkt_fifo_512_rsv3; + u32 tx_pkt_fifo_513[3]; /* 0x00006010 */ + u32 tx_pkt_fifo_513_rsv3; + u32 tx_pkt_fifo_514[3]; /* 0x00006020 */ + u32 tx_pkt_fifo_514_rsv3; + u32 tx_pkt_fifo_515[3]; /* 0x00006030 */ + u32 tx_pkt_fifo_515_rsv3; + u32 tx_pkt_fifo_516[3]; /* 0x00006040 */ + u32 tx_pkt_fifo_516_rsv3; + u32 tx_pkt_fifo_517[3]; /* 0x00006050 */ + u32 tx_pkt_fifo_517_rsv3; + u32 tx_pkt_fifo_518[3]; /* 0x00006060 */ + u32 tx_pkt_fifo_518_rsv3; + u32 tx_pkt_fifo_519[3]; /* 0x00006070 */ + u32 tx_pkt_fifo_519_rsv3; + u32 tx_pkt_fifo_520[3]; /* 0x00006080 */ + u32 tx_pkt_fifo_520_rsv3; + u32 tx_pkt_fifo_521[3]; /* 0x00006090 */ + u32 tx_pkt_fifo_521_rsv3; + u32 tx_pkt_fifo_522[3]; /* 0x000060a0 */ + u32 tx_pkt_fifo_522_rsv3; + u32 tx_pkt_fifo_523[3]; /* 0x000060b0 */ + u32 tx_pkt_fifo_523_rsv3; + u32 tx_pkt_fifo_524[3]; /* 0x000060c0 */ + u32 tx_pkt_fifo_524_rsv3; + u32 tx_pkt_fifo_525[3]; /* 0x000060d0 */ + u32 tx_pkt_fifo_525_rsv3; + u32 tx_pkt_fifo_526[3]; /* 0x000060e0 */ + u32 tx_pkt_fifo_526_rsv3; + u32 tx_pkt_fifo_527[3]; /* 0x000060f0 */ + u32 tx_pkt_fifo_527_rsv3; + u32 tx_pkt_fifo_528[3]; /* 0x00006100 */ + u32 tx_pkt_fifo_528_rsv3; + u32 tx_pkt_fifo_529[3]; /* 0x00006110 */ + u32 tx_pkt_fifo_529_rsv3; + u32 tx_pkt_fifo_530[3]; /* 0x00006120 */ + u32 tx_pkt_fifo_530_rsv3; + u32 tx_pkt_fifo_531[3]; /* 0x00006130 */ + u32 tx_pkt_fifo_531_rsv3; + u32 tx_pkt_fifo_532[3]; /* 0x00006140 */ + u32 tx_pkt_fifo_532_rsv3; + u32 tx_pkt_fifo_533[3]; /* 0x00006150 */ + u32 tx_pkt_fifo_533_rsv3; + u32 tx_pkt_fifo_534[3]; /* 0x00006160 */ + u32 tx_pkt_fifo_534_rsv3; + u32 tx_pkt_fifo_535[3]; /* 0x00006170 */ + u32 tx_pkt_fifo_535_rsv3; + u32 tx_pkt_fifo_536[3]; /* 0x00006180 */ + u32 tx_pkt_fifo_536_rsv3; + u32 tx_pkt_fifo_537[3]; /* 0x00006190 */ + u32 tx_pkt_fifo_537_rsv3; + u32 tx_pkt_fifo_538[3]; /* 0x000061a0 */ + u32 tx_pkt_fifo_538_rsv3; + u32 tx_pkt_fifo_539[3]; /* 0x000061b0 */ + u32 tx_pkt_fifo_539_rsv3; + u32 tx_pkt_fifo_540[3]; /* 0x000061c0 */ + u32 tx_pkt_fifo_540_rsv3; + u32 tx_pkt_fifo_541[3]; /* 0x000061d0 */ + u32 tx_pkt_fifo_541_rsv3; + u32 tx_pkt_fifo_542[3]; /* 0x000061e0 */ + u32 tx_pkt_fifo_542_rsv3; + u32 tx_pkt_fifo_543[3]; /* 0x000061f0 */ + u32 tx_pkt_fifo_543_rsv3; + u32 tx_pkt_fifo_544[3]; /* 0x00006200 */ + u32 tx_pkt_fifo_544_rsv3; + u32 tx_pkt_fifo_545[3]; /* 0x00006210 */ + u32 tx_pkt_fifo_545_rsv3; + u32 tx_pkt_fifo_546[3]; /* 0x00006220 */ + u32 tx_pkt_fifo_546_rsv3; + u32 tx_pkt_fifo_547[3]; /* 0x00006230 */ + u32 tx_pkt_fifo_547_rsv3; + u32 tx_pkt_fifo_548[3]; /* 0x00006240 */ + u32 tx_pkt_fifo_548_rsv3; + u32 tx_pkt_fifo_549[3]; /* 0x00006250 */ + u32 tx_pkt_fifo_549_rsv3; + u32 tx_pkt_fifo_550[3]; /* 0x00006260 */ + u32 tx_pkt_fifo_550_rsv3; + u32 tx_pkt_fifo_551[3]; /* 0x00006270 */ + u32 tx_pkt_fifo_551_rsv3; + u32 tx_pkt_fifo_552[3]; /* 0x00006280 */ + u32 tx_pkt_fifo_552_rsv3; + u32 tx_pkt_fifo_553[3]; /* 0x00006290 */ + u32 tx_pkt_fifo_553_rsv3; + u32 tx_pkt_fifo_554[3]; /* 0x000062a0 */ + u32 tx_pkt_fifo_554_rsv3; + u32 tx_pkt_fifo_555[3]; /* 0x000062b0 */ + u32 tx_pkt_fifo_555_rsv3; + u32 tx_pkt_fifo_556[3]; /* 0x000062c0 */ + u32 tx_pkt_fifo_556_rsv3; + u32 tx_pkt_fifo_557[3]; /* 0x000062d0 */ + u32 tx_pkt_fifo_557_rsv3; + u32 tx_pkt_fifo_558[3]; /* 0x000062e0 */ + u32 tx_pkt_fifo_558_rsv3; + u32 tx_pkt_fifo_559[3]; /* 0x000062f0 */ + u32 tx_pkt_fifo_559_rsv3; + u32 tx_pkt_fifo_560[3]; /* 0x00006300 */ + u32 tx_pkt_fifo_560_rsv3; + u32 tx_pkt_fifo_561[3]; /* 0x00006310 */ + u32 tx_pkt_fifo_561_rsv3; + u32 tx_pkt_fifo_562[3]; /* 0x00006320 */ + u32 tx_pkt_fifo_562_rsv3; + u32 tx_pkt_fifo_563[3]; /* 0x00006330 */ + u32 tx_pkt_fifo_563_rsv3; + u32 tx_pkt_fifo_564[3]; /* 0x00006340 */ + u32 tx_pkt_fifo_564_rsv3; + u32 tx_pkt_fifo_565[3]; /* 0x00006350 */ + u32 tx_pkt_fifo_565_rsv3; + u32 tx_pkt_fifo_566[3]; /* 0x00006360 */ + u32 tx_pkt_fifo_566_rsv3; + u32 tx_pkt_fifo_567[3]; /* 0x00006370 */ + u32 tx_pkt_fifo_567_rsv3; + u32 tx_pkt_fifo_568[3]; /* 0x00006380 */ + u32 tx_pkt_fifo_568_rsv3; + u32 tx_pkt_fifo_569[3]; /* 0x00006390 */ + u32 tx_pkt_fifo_569_rsv3; + u32 tx_pkt_fifo_570[3]; /* 0x000063a0 */ + u32 tx_pkt_fifo_570_rsv3; + u32 tx_pkt_fifo_571[3]; /* 0x000063b0 */ + u32 tx_pkt_fifo_571_rsv3; + u32 tx_pkt_fifo_572[3]; /* 0x000063c0 */ + u32 tx_pkt_fifo_572_rsv3; + u32 tx_pkt_fifo_573[3]; /* 0x000063d0 */ + u32 tx_pkt_fifo_573_rsv3; + u32 tx_pkt_fifo_574[3]; /* 0x000063e0 */ + u32 tx_pkt_fifo_574_rsv3; + u32 tx_pkt_fifo_575[3]; /* 0x000063f0 */ + u32 tx_pkt_fifo_575_rsv3; + u32 tx_pkt_fifo_576[3]; /* 0x00006400 */ + u32 tx_pkt_fifo_576_rsv3; + u32 tx_pkt_fifo_577[3]; /* 0x00006410 */ + u32 tx_pkt_fifo_577_rsv3; + u32 tx_pkt_fifo_578[3]; /* 0x00006420 */ + u32 tx_pkt_fifo_578_rsv3; + u32 tx_pkt_fifo_579[3]; /* 0x00006430 */ + u32 tx_pkt_fifo_579_rsv3; + u32 tx_pkt_fifo_580[3]; /* 0x00006440 */ + u32 tx_pkt_fifo_580_rsv3; + u32 tx_pkt_fifo_581[3]; /* 0x00006450 */ + u32 tx_pkt_fifo_581_rsv3; + u32 tx_pkt_fifo_582[3]; /* 0x00006460 */ + u32 tx_pkt_fifo_582_rsv3; + u32 tx_pkt_fifo_583[3]; /* 0x00006470 */ + u32 tx_pkt_fifo_583_rsv3; + u32 tx_pkt_fifo_584[3]; /* 0x00006480 */ + u32 tx_pkt_fifo_584_rsv3; + u32 tx_pkt_fifo_585[3]; /* 0x00006490 */ + u32 tx_pkt_fifo_585_rsv3; + u32 tx_pkt_fifo_586[3]; /* 0x000064a0 */ + u32 tx_pkt_fifo_586_rsv3; + u32 tx_pkt_fifo_587[3]; /* 0x000064b0 */ + u32 tx_pkt_fifo_587_rsv3; + u32 tx_pkt_fifo_588[3]; /* 0x000064c0 */ + u32 tx_pkt_fifo_588_rsv3; + u32 tx_pkt_fifo_589[3]; /* 0x000064d0 */ + u32 tx_pkt_fifo_589_rsv3; + u32 tx_pkt_fifo_590[3]; /* 0x000064e0 */ + u32 tx_pkt_fifo_590_rsv3; + u32 tx_pkt_fifo_591[3]; /* 0x000064f0 */ + u32 tx_pkt_fifo_591_rsv3; + u32 tx_pkt_fifo_592[3]; /* 0x00006500 */ + u32 tx_pkt_fifo_592_rsv3; + u32 tx_pkt_fifo_593[3]; /* 0x00006510 */ + u32 tx_pkt_fifo_593_rsv3; + u32 tx_pkt_fifo_594[3]; /* 0x00006520 */ + u32 tx_pkt_fifo_594_rsv3; + u32 tx_pkt_fifo_595[3]; /* 0x00006530 */ + u32 tx_pkt_fifo_595_rsv3; + u32 tx_pkt_fifo_596[3]; /* 0x00006540 */ + u32 tx_pkt_fifo_596_rsv3; + u32 tx_pkt_fifo_597[3]; /* 0x00006550 */ + u32 tx_pkt_fifo_597_rsv3; + u32 tx_pkt_fifo_598[3]; /* 0x00006560 */ + u32 tx_pkt_fifo_598_rsv3; + u32 tx_pkt_fifo_599[3]; /* 0x00006570 */ + u32 tx_pkt_fifo_599_rsv3; + u32 tx_pkt_fifo_600[3]; /* 0x00006580 */ + u32 tx_pkt_fifo_600_rsv3; + u32 tx_pkt_fifo_601[3]; /* 0x00006590 */ + u32 tx_pkt_fifo_601_rsv3; + u32 tx_pkt_fifo_602[3]; /* 0x000065a0 */ + u32 tx_pkt_fifo_602_rsv3; + u32 tx_pkt_fifo_603[3]; /* 0x000065b0 */ + u32 tx_pkt_fifo_603_rsv3; + u32 tx_pkt_fifo_604[3]; /* 0x000065c0 */ + u32 tx_pkt_fifo_604_rsv3; + u32 tx_pkt_fifo_605[3]; /* 0x000065d0 */ + u32 tx_pkt_fifo_605_rsv3; + u32 tx_pkt_fifo_606[3]; /* 0x000065e0 */ + u32 tx_pkt_fifo_606_rsv3; + u32 tx_pkt_fifo_607[3]; /* 0x000065f0 */ + u32 tx_pkt_fifo_607_rsv3; + u32 tx_pkt_fifo_608[3]; /* 0x00006600 */ + u32 tx_pkt_fifo_608_rsv3; + u32 tx_pkt_fifo_609[3]; /* 0x00006610 */ + u32 tx_pkt_fifo_609_rsv3; + u32 tx_pkt_fifo_610[3]; /* 0x00006620 */ + u32 tx_pkt_fifo_610_rsv3; + u32 tx_pkt_fifo_611[3]; /* 0x00006630 */ + u32 tx_pkt_fifo_611_rsv3; + u32 tx_pkt_fifo_612[3]; /* 0x00006640 */ + u32 tx_pkt_fifo_612_rsv3; + u32 tx_pkt_fifo_613[3]; /* 0x00006650 */ + u32 tx_pkt_fifo_613_rsv3; + u32 tx_pkt_fifo_614[3]; /* 0x00006660 */ + u32 tx_pkt_fifo_614_rsv3; + u32 tx_pkt_fifo_615[3]; /* 0x00006670 */ + u32 tx_pkt_fifo_615_rsv3; + u32 tx_pkt_fifo_616[3]; /* 0x00006680 */ + u32 tx_pkt_fifo_616_rsv3; + u32 tx_pkt_fifo_617[3]; /* 0x00006690 */ + u32 tx_pkt_fifo_617_rsv3; + u32 tx_pkt_fifo_618[3]; /* 0x000066a0 */ + u32 tx_pkt_fifo_618_rsv3; + u32 tx_pkt_fifo_619[3]; /* 0x000066b0 */ + u32 tx_pkt_fifo_619_rsv3; + u32 tx_pkt_fifo_620[3]; /* 0x000066c0 */ + u32 tx_pkt_fifo_620_rsv3; + u32 tx_pkt_fifo_621[3]; /* 0x000066d0 */ + u32 tx_pkt_fifo_621_rsv3; + u32 tx_pkt_fifo_622[3]; /* 0x000066e0 */ + u32 tx_pkt_fifo_622_rsv3; + u32 tx_pkt_fifo_623[3]; /* 0x000066f0 */ + u32 tx_pkt_fifo_623_rsv3; + u32 tx_pkt_fifo_624[3]; /* 0x00006700 */ + u32 tx_pkt_fifo_624_rsv3; + u32 tx_pkt_fifo_625[3]; /* 0x00006710 */ + u32 tx_pkt_fifo_625_rsv3; + u32 tx_pkt_fifo_626[3]; /* 0x00006720 */ + u32 tx_pkt_fifo_626_rsv3; + u32 tx_pkt_fifo_627[3]; /* 0x00006730 */ + u32 tx_pkt_fifo_627_rsv3; + u32 tx_pkt_fifo_628[3]; /* 0x00006740 */ + u32 tx_pkt_fifo_628_rsv3; + u32 tx_pkt_fifo_629[3]; /* 0x00006750 */ + u32 tx_pkt_fifo_629_rsv3; + u32 tx_pkt_fifo_630[3]; /* 0x00006760 */ + u32 tx_pkt_fifo_630_rsv3; + u32 tx_pkt_fifo_631[3]; /* 0x00006770 */ + u32 tx_pkt_fifo_631_rsv3; + u32 tx_pkt_fifo_632[3]; /* 0x00006780 */ + u32 tx_pkt_fifo_632_rsv3; + u32 tx_pkt_fifo_633[3]; /* 0x00006790 */ + u32 tx_pkt_fifo_633_rsv3; + u32 tx_pkt_fifo_634[3]; /* 0x000067a0 */ + u32 tx_pkt_fifo_634_rsv3; + u32 tx_pkt_fifo_635[3]; /* 0x000067b0 */ + u32 tx_pkt_fifo_635_rsv3; + u32 tx_pkt_fifo_636[3]; /* 0x000067c0 */ + u32 tx_pkt_fifo_636_rsv3; + u32 tx_pkt_fifo_637[3]; /* 0x000067d0 */ + u32 tx_pkt_fifo_637_rsv3; + u32 tx_pkt_fifo_638[3]; /* 0x000067e0 */ + u32 tx_pkt_fifo_638_rsv3; + u32 tx_pkt_fifo_639[3]; /* 0x000067f0 */ + u32 tx_pkt_fifo_639_rsv3; + u32 rsv6656; + u32 rsv6657; + u32 rsv6658; + u32 rsv6659; + u32 rsv6660; + u32 rsv6661; + u32 rsv6662; + u32 rsv6663; + u32 rsv6664; + u32 rsv6665; + u32 rsv6666; + u32 rsv6667; + u32 rsv6668; + u32 rsv6669; + u32 rsv6670; + u32 rsv6671; + u32 rsv6672; + u32 rsv6673; + u32 rsv6674; + u32 rsv6675; + u32 rsv6676; + u32 rsv6677; + u32 rsv6678; + u32 rsv6679; + u32 rsv6680; + u32 rsv6681; + u32 rsv6682; + u32 rsv6683; + u32 rsv6684; + u32 rsv6685; + u32 rsv6686; + u32 rsv6687; + u32 rsv6688; + u32 rsv6689; + u32 rsv6690; + u32 rsv6691; + u32 rsv6692; + u32 rsv6693; + u32 rsv6694; + u32 rsv6695; + u32 rsv6696; + u32 rsv6697; + u32 rsv6698; + u32 rsv6699; + u32 rsv6700; + u32 rsv6701; + u32 rsv6702; + u32 rsv6703; + u32 rsv6704; + u32 rsv6705; + u32 rsv6706; + u32 rsv6707; + u32 rsv6708; + u32 rsv6709; + u32 rsv6710; + u32 rsv6711; + u32 rsv6712; + u32 rsv6713; + u32 rsv6714; + u32 rsv6715; + u32 rsv6716; + u32 rsv6717; + u32 rsv6718; + u32 rsv6719; + u32 rsv6720; + u32 rsv6721; + u32 rsv6722; + u32 rsv6723; + u32 rsv6724; + u32 rsv6725; + u32 rsv6726; + u32 rsv6727; + u32 rsv6728; + u32 rsv6729; + u32 rsv6730; + u32 rsv6731; + u32 rsv6732; + u32 rsv6733; + u32 rsv6734; + u32 rsv6735; + u32 rsv6736; + u32 rsv6737; + u32 rsv6738; + u32 rsv6739; + u32 rsv6740; + u32 rsv6741; + u32 rsv6742; + u32 rsv6743; + u32 rsv6744; + u32 rsv6745; + u32 rsv6746; + u32 rsv6747; + u32 rsv6748; + u32 rsv6749; + u32 rsv6750; + u32 rsv6751; + u32 rsv6752; + u32 rsv6753; + u32 rsv6754; + u32 rsv6755; + u32 rsv6756; + u32 rsv6757; + u32 rsv6758; + u32 rsv6759; + u32 rsv6760; + u32 rsv6761; + u32 rsv6762; + u32 rsv6763; + u32 rsv6764; + u32 rsv6765; + u32 rsv6766; + u32 rsv6767; + u32 rsv6768; + u32 rsv6769; + u32 rsv6770; + u32 rsv6771; + u32 rsv6772; + u32 rsv6773; + u32 rsv6774; + u32 rsv6775; + u32 rsv6776; + u32 rsv6777; + u32 rsv6778; + u32 rsv6779; + u32 rsv6780; + u32 rsv6781; + u32 rsv6782; + u32 rsv6783; + u32 rsv6784; + u32 rsv6785; + u32 rsv6786; + u32 rsv6787; + u32 rsv6788; + u32 rsv6789; + u32 rsv6790; + u32 rsv6791; + u32 rsv6792; + u32 rsv6793; + u32 rsv6794; + u32 rsv6795; + u32 rsv6796; + u32 rsv6797; + u32 rsv6798; + u32 rsv6799; + u32 rsv6800; + u32 rsv6801; + u32 rsv6802; + u32 rsv6803; + u32 rsv6804; + u32 rsv6805; + u32 rsv6806; + u32 rsv6807; + u32 rsv6808; + u32 rsv6809; + u32 rsv6810; + u32 rsv6811; + u32 rsv6812; + u32 rsv6813; + u32 rsv6814; + u32 rsv6815; + u32 rsv6816; + u32 rsv6817; + u32 rsv6818; + u32 rsv6819; + u32 rsv6820; + u32 rsv6821; + u32 rsv6822; + u32 rsv6823; + u32 rsv6824; + u32 rsv6825; + u32 rsv6826; + u32 rsv6827; + u32 rsv6828; + u32 rsv6829; + u32 rsv6830; + u32 rsv6831; + u32 rsv6832; + u32 rsv6833; + u32 rsv6834; + u32 rsv6835; + u32 rsv6836; + u32 rsv6837; + u32 rsv6838; + u32 rsv6839; + u32 rsv6840; + u32 rsv6841; + u32 rsv6842; + u32 rsv6843; + u32 rsv6844; + u32 rsv6845; + u32 rsv6846; + u32 rsv6847; + u32 rsv6848; + u32 rsv6849; + u32 rsv6850; + u32 rsv6851; + u32 rsv6852; + u32 rsv6853; + u32 rsv6854; + u32 rsv6855; + u32 rsv6856; + u32 rsv6857; + u32 rsv6858; + u32 rsv6859; + u32 rsv6860; + u32 rsv6861; + u32 rsv6862; + u32 rsv6863; + u32 rsv6864; + u32 rsv6865; + u32 rsv6866; + u32 rsv6867; + u32 rsv6868; + u32 rsv6869; + u32 rsv6870; + u32 rsv6871; + u32 rsv6872; + u32 rsv6873; + u32 rsv6874; + u32 rsv6875; + u32 rsv6876; + u32 rsv6877; + u32 rsv6878; + u32 rsv6879; + u32 rsv6880; + u32 rsv6881; + u32 rsv6882; + u32 rsv6883; + u32 rsv6884; + u32 rsv6885; + u32 rsv6886; + u32 rsv6887; + u32 rsv6888; + u32 rsv6889; + u32 rsv6890; + u32 rsv6891; + u32 rsv6892; + u32 rsv6893; + u32 rsv6894; + u32 rsv6895; + u32 rsv6896; + u32 rsv6897; + u32 rsv6898; + u32 rsv6899; + u32 rsv6900; + u32 rsv6901; + u32 rsv6902; + u32 rsv6903; + u32 rsv6904; + u32 rsv6905; + u32 rsv6906; + u32 rsv6907; + u32 rsv6908; + u32 rsv6909; + u32 rsv6910; + u32 rsv6911; + u32 rsv6912; + u32 rsv6913; + u32 rsv6914; + u32 rsv6915; + u32 rsv6916; + u32 rsv6917; + u32 rsv6918; + u32 rsv6919; + u32 rsv6920; + u32 rsv6921; + u32 rsv6922; + u32 rsv6923; + u32 rsv6924; + u32 rsv6925; + u32 rsv6926; + u32 rsv6927; + u32 rsv6928; + u32 rsv6929; + u32 rsv6930; + u32 rsv6931; + u32 rsv6932; + u32 rsv6933; + u32 rsv6934; + u32 rsv6935; + u32 rsv6936; + u32 rsv6937; + u32 rsv6938; + u32 rsv6939; + u32 rsv6940; + u32 rsv6941; + u32 rsv6942; + u32 rsv6943; + u32 rsv6944; + u32 rsv6945; + u32 rsv6946; + u32 rsv6947; + u32 rsv6948; + u32 rsv6949; + u32 rsv6950; + u32 rsv6951; + u32 rsv6952; + u32 rsv6953; + u32 rsv6954; + u32 rsv6955; + u32 rsv6956; + u32 rsv6957; + u32 rsv6958; + u32 rsv6959; + u32 rsv6960; + u32 rsv6961; + u32 rsv6962; + u32 rsv6963; + u32 rsv6964; + u32 rsv6965; + u32 rsv6966; + u32 rsv6967; + u32 rsv6968; + u32 rsv6969; + u32 rsv6970; + u32 rsv6971; + u32 rsv6972; + u32 rsv6973; + u32 rsv6974; + u32 rsv6975; + u32 rsv6976; + u32 rsv6977; + u32 rsv6978; + u32 rsv6979; + u32 rsv6980; + u32 rsv6981; + u32 rsv6982; + u32 rsv6983; + u32 rsv6984; + u32 rsv6985; + u32 rsv6986; + u32 rsv6987; + u32 rsv6988; + u32 rsv6989; + u32 rsv6990; + u32 rsv6991; + u32 rsv6992; + u32 rsv6993; + u32 rsv6994; + u32 rsv6995; + u32 rsv6996; + u32 rsv6997; + u32 rsv6998; + u32 rsv6999; + u32 rsv7000; + u32 rsv7001; + u32 rsv7002; + u32 rsv7003; + u32 rsv7004; + u32 rsv7005; + u32 rsv7006; + u32 rsv7007; + u32 rsv7008; + u32 rsv7009; + u32 rsv7010; + u32 rsv7011; + u32 rsv7012; + u32 rsv7013; + u32 rsv7014; + u32 rsv7015; + u32 rsv7016; + u32 rsv7017; + u32 rsv7018; + u32 rsv7019; + u32 rsv7020; + u32 rsv7021; + u32 rsv7022; + u32 rsv7023; + u32 rsv7024; + u32 rsv7025; + u32 rsv7026; + u32 rsv7027; + u32 rsv7028; + u32 rsv7029; + u32 rsv7030; + u32 rsv7031; + u32 rsv7032; + u32 rsv7033; + u32 rsv7034; + u32 rsv7035; + u32 rsv7036; + u32 rsv7037; + u32 rsv7038; + u32 rsv7039; + u32 rsv7040; + u32 rsv7041; + u32 rsv7042; + u32 rsv7043; + u32 rsv7044; + u32 rsv7045; + u32 rsv7046; + u32 rsv7047; + u32 rsv7048; + u32 rsv7049; + u32 rsv7050; + u32 rsv7051; + u32 rsv7052; + u32 rsv7053; + u32 rsv7054; + u32 rsv7055; + u32 rsv7056; + u32 rsv7057; + u32 rsv7058; + u32 rsv7059; + u32 rsv7060; + u32 rsv7061; + u32 rsv7062; + u32 rsv7063; + u32 rsv7064; + u32 rsv7065; + u32 rsv7066; + u32 rsv7067; + u32 rsv7068; + u32 rsv7069; + u32 rsv7070; + u32 rsv7071; + u32 rsv7072; + u32 rsv7073; + u32 rsv7074; + u32 rsv7075; + u32 rsv7076; + u32 rsv7077; + u32 rsv7078; + u32 rsv7079; + u32 rsv7080; + u32 rsv7081; + u32 rsv7082; + u32 rsv7083; + u32 rsv7084; + u32 rsv7085; + u32 rsv7086; + u32 rsv7087; + u32 rsv7088; + u32 rsv7089; + u32 rsv7090; + u32 rsv7091; + u32 rsv7092; + u32 rsv7093; + u32 rsv7094; + u32 rsv7095; + u32 rsv7096; + u32 rsv7097; + u32 rsv7098; + u32 rsv7099; + u32 rsv7100; + u32 rsv7101; + u32 rsv7102; + u32 rsv7103; + u32 rsv7104; + u32 rsv7105; + u32 rsv7106; + u32 rsv7107; + u32 rsv7108; + u32 rsv7109; + u32 rsv7110; + u32 rsv7111; + u32 rsv7112; + u32 rsv7113; + u32 rsv7114; + u32 rsv7115; + u32 rsv7116; + u32 rsv7117; + u32 rsv7118; + u32 rsv7119; + u32 rsv7120; + u32 rsv7121; + u32 rsv7122; + u32 rsv7123; + u32 rsv7124; + u32 rsv7125; + u32 rsv7126; + u32 rsv7127; + u32 rsv7128; + u32 rsv7129; + u32 rsv7130; + u32 rsv7131; + u32 rsv7132; + u32 rsv7133; + u32 rsv7134; + u32 rsv7135; + u32 rsv7136; + u32 rsv7137; + u32 rsv7138; + u32 rsv7139; + u32 rsv7140; + u32 rsv7141; + u32 rsv7142; + u32 rsv7143; + u32 rsv7144; + u32 rsv7145; + u32 rsv7146; + u32 rsv7147; + u32 rsv7148; + u32 rsv7149; + u32 rsv7150; + u32 rsv7151; + u32 rsv7152; + u32 rsv7153; + u32 rsv7154; + u32 rsv7155; + u32 rsv7156; + u32 rsv7157; + u32 rsv7158; + u32 rsv7159; + u32 rsv7160; + u32 rsv7161; + u32 rsv7162; + u32 rsv7163; + u32 rsv7164; + u32 rsv7165; + u32 rsv7166; + u32 rsv7167; + u32 rsv7168; + u32 rsv7169; + u32 rsv7170; + u32 rsv7171; + u32 rsv7172; + u32 rsv7173; + u32 rsv7174; + u32 rsv7175; + u32 rsv7176; + u32 rsv7177; + u32 rsv7178; + u32 rsv7179; + u32 rsv7180; + u32 rsv7181; + u32 rsv7182; + u32 rsv7183; + u32 rsv7184; + u32 rsv7185; + u32 rsv7186; + u32 rsv7187; + u32 rsv7188; + u32 rsv7189; + u32 rsv7190; + u32 rsv7191; + u32 rsv7192; + u32 rsv7193; + u32 rsv7194; + u32 rsv7195; + u32 rsv7196; + u32 rsv7197; + u32 rsv7198; + u32 rsv7199; + u32 rsv7200; + u32 rsv7201; + u32 rsv7202; + u32 rsv7203; + u32 rsv7204; + u32 rsv7205; + u32 rsv7206; + u32 rsv7207; + u32 rsv7208; + u32 rsv7209; + u32 rsv7210; + u32 rsv7211; + u32 rsv7212; + u32 rsv7213; + u32 rsv7214; + u32 rsv7215; + u32 rsv7216; + u32 rsv7217; + u32 rsv7218; + u32 rsv7219; + u32 rsv7220; + u32 rsv7221; + u32 rsv7222; + u32 rsv7223; + u32 rsv7224; + u32 rsv7225; + u32 rsv7226; + u32 rsv7227; + u32 rsv7228; + u32 rsv7229; + u32 rsv7230; + u32 rsv7231; + u32 rsv7232; + u32 rsv7233; + u32 rsv7234; + u32 rsv7235; + u32 rsv7236; + u32 rsv7237; + u32 rsv7238; + u32 rsv7239; + u32 rsv7240; + u32 rsv7241; + u32 rsv7242; + u32 rsv7243; + u32 rsv7244; + u32 rsv7245; + u32 rsv7246; + u32 rsv7247; + u32 rsv7248; + u32 rsv7249; + u32 rsv7250; + u32 rsv7251; + u32 rsv7252; + u32 rsv7253; + u32 rsv7254; + u32 rsv7255; + u32 rsv7256; + u32 rsv7257; + u32 rsv7258; + u32 rsv7259; + u32 rsv7260; + u32 rsv7261; + u32 rsv7262; + u32 rsv7263; + u32 rsv7264; + u32 rsv7265; + u32 rsv7266; + u32 rsv7267; + u32 rsv7268; + u32 rsv7269; + u32 rsv7270; + u32 rsv7271; + u32 rsv7272; + u32 rsv7273; + u32 rsv7274; + u32 rsv7275; + u32 rsv7276; + u32 rsv7277; + u32 rsv7278; + u32 rsv7279; + u32 rsv7280; + u32 rsv7281; + u32 rsv7282; + u32 rsv7283; + u32 rsv7284; + u32 rsv7285; + u32 rsv7286; + u32 rsv7287; + u32 rsv7288; + u32 rsv7289; + u32 rsv7290; + u32 rsv7291; + u32 rsv7292; + u32 rsv7293; + u32 rsv7294; + u32 rsv7295; + u32 rsv7296; + u32 rsv7297; + u32 rsv7298; + u32 rsv7299; + u32 rsv7300; + u32 rsv7301; + u32 rsv7302; + u32 rsv7303; + u32 rsv7304; + u32 rsv7305; + u32 rsv7306; + u32 rsv7307; + u32 rsv7308; + u32 rsv7309; + u32 rsv7310; + u32 rsv7311; + u32 rsv7312; + u32 rsv7313; + u32 rsv7314; + u32 rsv7315; + u32 rsv7316; + u32 rsv7317; + u32 rsv7318; + u32 rsv7319; + u32 rsv7320; + u32 rsv7321; + u32 rsv7322; + u32 rsv7323; + u32 rsv7324; + u32 rsv7325; + u32 rsv7326; + u32 rsv7327; + u32 rsv7328; + u32 rsv7329; + u32 rsv7330; + u32 rsv7331; + u32 rsv7332; + u32 rsv7333; + u32 rsv7334; + u32 rsv7335; + u32 rsv7336; + u32 rsv7337; + u32 rsv7338; + u32 rsv7339; + u32 rsv7340; + u32 rsv7341; + u32 rsv7342; + u32 rsv7343; + u32 rsv7344; + u32 rsv7345; + u32 rsv7346; + u32 rsv7347; + u32 rsv7348; + u32 rsv7349; + u32 rsv7350; + u32 rsv7351; + u32 rsv7352; + u32 rsv7353; + u32 rsv7354; + u32 rsv7355; + u32 rsv7356; + u32 rsv7357; + u32 rsv7358; + u32 rsv7359; + u32 rsv7360; + u32 rsv7361; + u32 rsv7362; + u32 rsv7363; + u32 rsv7364; + u32 rsv7365; + u32 rsv7366; + u32 rsv7367; + u32 rsv7368; + u32 rsv7369; + u32 rsv7370; + u32 rsv7371; + u32 rsv7372; + u32 rsv7373; + u32 rsv7374; + u32 rsv7375; + u32 rsv7376; + u32 rsv7377; + u32 rsv7378; + u32 rsv7379; + u32 rsv7380; + u32 rsv7381; + u32 rsv7382; + u32 rsv7383; + u32 rsv7384; + u32 rsv7385; + u32 rsv7386; + u32 rsv7387; + u32 rsv7388; + u32 rsv7389; + u32 rsv7390; + u32 rsv7391; + u32 rsv7392; + u32 rsv7393; + u32 rsv7394; + u32 rsv7395; + u32 rsv7396; + u32 rsv7397; + u32 rsv7398; + u32 rsv7399; + u32 rsv7400; + u32 rsv7401; + u32 rsv7402; + u32 rsv7403; + u32 rsv7404; + u32 rsv7405; + u32 rsv7406; + u32 rsv7407; + u32 rsv7408; + u32 rsv7409; + u32 rsv7410; + u32 rsv7411; + u32 rsv7412; + u32 rsv7413; + u32 rsv7414; + u32 rsv7415; + u32 rsv7416; + u32 rsv7417; + u32 rsv7418; + u32 rsv7419; + u32 rsv7420; + u32 rsv7421; + u32 rsv7422; + u32 rsv7423; + u32 rsv7424; + u32 rsv7425; + u32 rsv7426; + u32 rsv7427; + u32 rsv7428; + u32 rsv7429; + u32 rsv7430; + u32 rsv7431; + u32 rsv7432; + u32 rsv7433; + u32 rsv7434; + u32 rsv7435; + u32 rsv7436; + u32 rsv7437; + u32 rsv7438; + u32 rsv7439; + u32 rsv7440; + u32 rsv7441; + u32 rsv7442; + u32 rsv7443; + u32 rsv7444; + u32 rsv7445; + u32 rsv7446; + u32 rsv7447; + u32 rsv7448; + u32 rsv7449; + u32 rsv7450; + u32 rsv7451; + u32 rsv7452; + u32 rsv7453; + u32 rsv7454; + u32 rsv7455; + u32 rsv7456; + u32 rsv7457; + u32 rsv7458; + u32 rsv7459; + u32 rsv7460; + u32 rsv7461; + u32 rsv7462; + u32 rsv7463; + u32 rsv7464; + u32 rsv7465; + u32 rsv7466; + u32 rsv7467; + u32 rsv7468; + u32 rsv7469; + u32 rsv7470; + u32 rsv7471; + u32 rsv7472; + u32 rsv7473; + u32 rsv7474; + u32 rsv7475; + u32 rsv7476; + u32 rsv7477; + u32 rsv7478; + u32 rsv7479; + u32 rsv7480; + u32 rsv7481; + u32 rsv7482; + u32 rsv7483; + u32 rsv7484; + u32 rsv7485; + u32 rsv7486; + u32 rsv7487; + u32 rsv7488; + u32 rsv7489; + u32 rsv7490; + u32 rsv7491; + u32 rsv7492; + u32 rsv7493; + u32 rsv7494; + u32 rsv7495; + u32 rsv7496; + u32 rsv7497; + u32 rsv7498; + u32 rsv7499; + u32 rsv7500; + u32 rsv7501; + u32 rsv7502; + u32 rsv7503; + u32 rsv7504; + u32 rsv7505; + u32 rsv7506; + u32 rsv7507; + u32 rsv7508; + u32 rsv7509; + u32 rsv7510; + u32 rsv7511; + u32 rsv7512; + u32 rsv7513; + u32 rsv7514; + u32 rsv7515; + u32 rsv7516; + u32 rsv7517; + u32 rsv7518; + u32 rsv7519; + u32 rsv7520; + u32 rsv7521; + u32 rsv7522; + u32 rsv7523; + u32 rsv7524; + u32 rsv7525; + u32 rsv7526; + u32 rsv7527; + u32 rsv7528; + u32 rsv7529; + u32 rsv7530; + u32 rsv7531; + u32 rsv7532; + u32 rsv7533; + u32 rsv7534; + u32 rsv7535; + u32 rsv7536; + u32 rsv7537; + u32 rsv7538; + u32 rsv7539; + u32 rsv7540; + u32 rsv7541; + u32 rsv7542; + u32 rsv7543; + u32 rsv7544; + u32 rsv7545; + u32 rsv7546; + u32 rsv7547; + u32 rsv7548; + u32 rsv7549; + u32 rsv7550; + u32 rsv7551; + u32 rsv7552; + u32 rsv7553; + u32 rsv7554; + u32 rsv7555; + u32 rsv7556; + u32 rsv7557; + u32 rsv7558; + u32 rsv7559; + u32 rsv7560; + u32 rsv7561; + u32 rsv7562; + u32 rsv7563; + u32 rsv7564; + u32 rsv7565; + u32 rsv7566; + u32 rsv7567; + u32 rsv7568; + u32 rsv7569; + u32 rsv7570; + u32 rsv7571; + u32 rsv7572; + u32 rsv7573; + u32 rsv7574; + u32 rsv7575; + u32 rsv7576; + u32 rsv7577; + u32 rsv7578; + u32 rsv7579; + u32 rsv7580; + u32 rsv7581; + u32 rsv7582; + u32 rsv7583; + u32 rsv7584; + u32 rsv7585; + u32 rsv7586; + u32 rsv7587; + u32 rsv7588; + u32 rsv7589; + u32 rsv7590; + u32 rsv7591; + u32 rsv7592; + u32 rsv7593; + u32 rsv7594; + u32 rsv7595; + u32 rsv7596; + u32 rsv7597; + u32 rsv7598; + u32 rsv7599; + u32 rsv7600; + u32 rsv7601; + u32 rsv7602; + u32 rsv7603; + u32 rsv7604; + u32 rsv7605; + u32 rsv7606; + u32 rsv7607; + u32 rsv7608; + u32 rsv7609; + u32 rsv7610; + u32 rsv7611; + u32 rsv7612; + u32 rsv7613; + u32 rsv7614; + u32 rsv7615; + u32 rsv7616; + u32 rsv7617; + u32 rsv7618; + u32 rsv7619; + u32 rsv7620; + u32 rsv7621; + u32 rsv7622; + u32 rsv7623; + u32 rsv7624; + u32 rsv7625; + u32 rsv7626; + u32 rsv7627; + u32 rsv7628; + u32 rsv7629; + u32 rsv7630; + u32 rsv7631; + u32 rsv7632; + u32 rsv7633; + u32 rsv7634; + u32 rsv7635; + u32 rsv7636; + u32 rsv7637; + u32 rsv7638; + u32 rsv7639; + u32 rsv7640; + u32 rsv7641; + u32 rsv7642; + u32 rsv7643; + u32 rsv7644; + u32 rsv7645; + u32 rsv7646; + u32 rsv7647; + u32 rsv7648; + u32 rsv7649; + u32 rsv7650; + u32 rsv7651; + u32 rsv7652; + u32 rsv7653; + u32 rsv7654; + u32 rsv7655; + u32 rsv7656; + u32 rsv7657; + u32 rsv7658; + u32 rsv7659; + u32 rsv7660; + u32 rsv7661; + u32 rsv7662; + u32 rsv7663; + u32 rsv7664; + u32 rsv7665; + u32 rsv7666; + u32 rsv7667; + u32 rsv7668; + u32 rsv7669; + u32 rsv7670; + u32 rsv7671; + u32 rsv7672; + u32 rsv7673; + u32 rsv7674; + u32 rsv7675; + u32 rsv7676; + u32 rsv7677; + u32 rsv7678; + u32 rsv7679; + u32 rsv7680; + u32 rsv7681; + u32 rsv7682; + u32 rsv7683; + u32 rsv7684; + u32 rsv7685; + u32 rsv7686; + u32 rsv7687; + u32 rsv7688; + u32 rsv7689; + u32 rsv7690; + u32 rsv7691; + u32 rsv7692; + u32 rsv7693; + u32 rsv7694; + u32 rsv7695; + u32 rsv7696; + u32 rsv7697; + u32 rsv7698; + u32 rsv7699; + u32 rsv7700; + u32 rsv7701; + u32 rsv7702; + u32 rsv7703; + u32 rsv7704; + u32 rsv7705; + u32 rsv7706; + u32 rsv7707; + u32 rsv7708; + u32 rsv7709; + u32 rsv7710; + u32 rsv7711; + u32 rsv7712; + u32 rsv7713; + u32 rsv7714; + u32 rsv7715; + u32 rsv7716; + u32 rsv7717; + u32 rsv7718; + u32 rsv7719; + u32 rsv7720; + u32 rsv7721; + u32 rsv7722; + u32 rsv7723; + u32 rsv7724; + u32 rsv7725; + u32 rsv7726; + u32 rsv7727; + u32 rsv7728; + u32 rsv7729; + u32 rsv7730; + u32 rsv7731; + u32 rsv7732; + u32 rsv7733; + u32 rsv7734; + u32 rsv7735; + u32 rsv7736; + u32 rsv7737; + u32 rsv7738; + u32 rsv7739; + u32 rsv7740; + u32 rsv7741; + u32 rsv7742; + u32 rsv7743; + u32 rsv7744; + u32 rsv7745; + u32 rsv7746; + u32 rsv7747; + u32 rsv7748; + u32 rsv7749; + u32 rsv7750; + u32 rsv7751; + u32 rsv7752; + u32 rsv7753; + u32 rsv7754; + u32 rsv7755; + u32 rsv7756; + u32 rsv7757; + u32 rsv7758; + u32 rsv7759; + u32 rsv7760; + u32 rsv7761; + u32 rsv7762; + u32 rsv7763; + u32 rsv7764; + u32 rsv7765; + u32 rsv7766; + u32 rsv7767; + u32 rsv7768; + u32 rsv7769; + u32 rsv7770; + u32 rsv7771; + u32 rsv7772; + u32 rsv7773; + u32 rsv7774; + u32 rsv7775; + u32 rsv7776; + u32 rsv7777; + u32 rsv7778; + u32 rsv7779; + u32 rsv7780; + u32 rsv7781; + u32 rsv7782; + u32 rsv7783; + u32 rsv7784; + u32 rsv7785; + u32 rsv7786; + u32 rsv7787; + u32 rsv7788; + u32 rsv7789; + u32 rsv7790; + u32 rsv7791; + u32 rsv7792; + u32 rsv7793; + u32 rsv7794; + u32 rsv7795; + u32 rsv7796; + u32 rsv7797; + u32 rsv7798; + u32 rsv7799; + u32 rsv7800; + u32 rsv7801; + u32 rsv7802; + u32 rsv7803; + u32 rsv7804; + u32 rsv7805; + u32 rsv7806; + u32 rsv7807; + u32 rsv7808; + u32 rsv7809; + u32 rsv7810; + u32 rsv7811; + u32 rsv7812; + u32 rsv7813; + u32 rsv7814; + u32 rsv7815; + u32 rsv7816; + u32 rsv7817; + u32 rsv7818; + u32 rsv7819; + u32 rsv7820; + u32 rsv7821; + u32 rsv7822; + u32 rsv7823; + u32 rsv7824; + u32 rsv7825; + u32 rsv7826; + u32 rsv7827; + u32 rsv7828; + u32 rsv7829; + u32 rsv7830; + u32 rsv7831; + u32 rsv7832; + u32 rsv7833; + u32 rsv7834; + u32 rsv7835; + u32 rsv7836; + u32 rsv7837; + u32 rsv7838; + u32 rsv7839; + u32 rsv7840; + u32 rsv7841; + u32 rsv7842; + u32 rsv7843; + u32 rsv7844; + u32 rsv7845; + u32 rsv7846; + u32 rsv7847; + u32 rsv7848; + u32 rsv7849; + u32 rsv7850; + u32 rsv7851; + u32 rsv7852; + u32 rsv7853; + u32 rsv7854; + u32 rsv7855; + u32 rsv7856; + u32 rsv7857; + u32 rsv7858; + u32 rsv7859; + u32 rsv7860; + u32 rsv7861; + u32 rsv7862; + u32 rsv7863; + u32 rsv7864; + u32 rsv7865; + u32 rsv7866; + u32 rsv7867; + u32 rsv7868; + u32 rsv7869; + u32 rsv7870; + u32 rsv7871; + u32 rsv7872; + u32 rsv7873; + u32 rsv7874; + u32 rsv7875; + u32 rsv7876; + u32 rsv7877; + u32 rsv7878; + u32 rsv7879; + u32 rsv7880; + u32 rsv7881; + u32 rsv7882; + u32 rsv7883; + u32 rsv7884; + u32 rsv7885; + u32 rsv7886; + u32 rsv7887; + u32 rsv7888; + u32 rsv7889; + u32 rsv7890; + u32 rsv7891; + u32 rsv7892; + u32 rsv7893; + u32 rsv7894; + u32 rsv7895; + u32 rsv7896; + u32 rsv7897; + u32 rsv7898; + u32 rsv7899; + u32 rsv7900; + u32 rsv7901; + u32 rsv7902; + u32 rsv7903; + u32 rsv7904; + u32 rsv7905; + u32 rsv7906; + u32 rsv7907; + u32 rsv7908; + u32 rsv7909; + u32 rsv7910; + u32 rsv7911; + u32 rsv7912; + u32 rsv7913; + u32 rsv7914; + u32 rsv7915; + u32 rsv7916; + u32 rsv7917; + u32 rsv7918; + u32 rsv7919; + u32 rsv7920; + u32 rsv7921; + u32 rsv7922; + u32 rsv7923; + u32 rsv7924; + u32 rsv7925; + u32 rsv7926; + u32 rsv7927; + u32 rsv7928; + u32 rsv7929; + u32 rsv7930; + u32 rsv7931; + u32 rsv7932; + u32 rsv7933; + u32 rsv7934; + u32 rsv7935; + u32 rsv7936; + u32 rsv7937; + u32 rsv7938; + u32 rsv7939; + u32 rsv7940; + u32 rsv7941; + u32 rsv7942; + u32 rsv7943; + u32 rsv7944; + u32 rsv7945; + u32 rsv7946; + u32 rsv7947; + u32 rsv7948; + u32 rsv7949; + u32 rsv7950; + u32 rsv7951; + u32 rsv7952; + u32 rsv7953; + u32 rsv7954; + u32 rsv7955; + u32 rsv7956; + u32 rsv7957; + u32 rsv7958; + u32 rsv7959; + u32 rsv7960; + u32 rsv7961; + u32 rsv7962; + u32 rsv7963; + u32 rsv7964; + u32 rsv7965; + u32 rsv7966; + u32 rsv7967; + u32 rsv7968; + u32 rsv7969; + u32 rsv7970; + u32 rsv7971; + u32 rsv7972; + u32 rsv7973; + u32 rsv7974; + u32 rsv7975; + u32 rsv7976; + u32 rsv7977; + u32 rsv7978; + u32 rsv7979; + u32 rsv7980; + u32 rsv7981; + u32 rsv7982; + u32 rsv7983; + u32 rsv7984; + u32 rsv7985; + u32 rsv7986; + u32 rsv7987; + u32 rsv7988; + u32 rsv7989; + u32 rsv7990; + u32 rsv7991; + u32 rsv7992; + u32 rsv7993; + u32 rsv7994; + u32 rsv7995; + u32 rsv7996; + u32 rsv7997; + u32 rsv7998; + u32 rsv7999; + u32 rsv8000; + u32 rsv8001; + u32 rsv8002; + u32 rsv8003; + u32 rsv8004; + u32 rsv8005; + u32 rsv8006; + u32 rsv8007; + u32 rsv8008; + u32 rsv8009; + u32 rsv8010; + u32 rsv8011; + u32 rsv8012; + u32 rsv8013; + u32 rsv8014; + u32 rsv8015; + u32 rsv8016; + u32 rsv8017; + u32 rsv8018; + u32 rsv8019; + u32 rsv8020; + u32 rsv8021; + u32 rsv8022; + u32 rsv8023; + u32 rsv8024; + u32 rsv8025; + u32 rsv8026; + u32 rsv8027; + u32 rsv8028; + u32 rsv8029; + u32 rsv8030; + u32 rsv8031; + u32 rsv8032; + u32 rsv8033; + u32 rsv8034; + u32 rsv8035; + u32 rsv8036; + u32 rsv8037; + u32 rsv8038; + u32 rsv8039; + u32 rsv8040; + u32 rsv8041; + u32 rsv8042; + u32 rsv8043; + u32 rsv8044; + u32 rsv8045; + u32 rsv8046; + u32 rsv8047; + u32 rsv8048; + u32 rsv8049; + u32 rsv8050; + u32 rsv8051; + u32 rsv8052; + u32 rsv8053; + u32 rsv8054; + u32 rsv8055; + u32 rsv8056; + u32 rsv8057; + u32 rsv8058; + u32 rsv8059; + u32 rsv8060; + u32 rsv8061; + u32 rsv8062; + u32 rsv8063; + u32 rsv8064; + u32 rsv8065; + u32 rsv8066; + u32 rsv8067; + u32 rsv8068; + u32 rsv8069; + u32 rsv8070; + u32 rsv8071; + u32 rsv8072; + u32 rsv8073; + u32 rsv8074; + u32 rsv8075; + u32 rsv8076; + u32 rsv8077; + u32 rsv8078; + u32 rsv8079; + u32 rsv8080; + u32 rsv8081; + u32 rsv8082; + u32 rsv8083; + u32 rsv8084; + u32 rsv8085; + u32 rsv8086; + u32 rsv8087; + u32 rsv8088; + u32 rsv8089; + u32 rsv8090; + u32 rsv8091; + u32 rsv8092; + u32 rsv8093; + u32 rsv8094; + u32 rsv8095; + u32 rsv8096; + u32 rsv8097; + u32 rsv8098; + u32 rsv8099; + u32 rsv8100; + u32 rsv8101; + u32 rsv8102; + u32 rsv8103; + u32 rsv8104; + u32 rsv8105; + u32 rsv8106; + u32 rsv8107; + u32 rsv8108; + u32 rsv8109; + u32 rsv8110; + u32 rsv8111; + u32 rsv8112; + u32 rsv8113; + u32 rsv8114; + u32 rsv8115; + u32 rsv8116; + u32 rsv8117; + u32 rsv8118; + u32 rsv8119; + u32 rsv8120; + u32 rsv8121; + u32 rsv8122; + u32 rsv8123; + u32 rsv8124; + u32 rsv8125; + u32 rsv8126; + u32 rsv8127; + u32 rsv8128; + u32 rsv8129; + u32 rsv8130; + u32 rsv8131; + u32 rsv8132; + u32 rsv8133; + u32 rsv8134; + u32 rsv8135; + u32 rsv8136; + u32 rsv8137; + u32 rsv8138; + u32 rsv8139; + u32 rsv8140; + u32 rsv8141; + u32 rsv8142; + u32 rsv8143; + u32 rsv8144; + u32 rsv8145; + u32 rsv8146; + u32 rsv8147; + u32 rsv8148; + u32 rsv8149; + u32 rsv8150; + u32 rsv8151; + u32 rsv8152; + u32 rsv8153; + u32 rsv8154; + u32 rsv8155; + u32 rsv8156; + u32 rsv8157; + u32 rsv8158; + u32 rsv8159; + u32 rsv8160; + u32 rsv8161; + u32 rsv8162; + u32 rsv8163; + u32 rsv8164; + u32 rsv8165; + u32 rsv8166; + u32 rsv8167; + u32 rsv8168; + u32 rsv8169; + u32 rsv8170; + u32 rsv8171; + u32 rsv8172; + u32 rsv8173; + u32 rsv8174; + u32 rsv8175; + u32 rsv8176; + u32 rsv8177; + u32 rsv8178; + u32 rsv8179; + u32 rsv8180; + u32 rsv8181; + u32 rsv8182; + u32 rsv8183; + u32 rsv8184; + u32 rsv8185; + u32 rsv8186; + u32 rsv8187; + u32 rsv8188; + u32 rsv8189; + u32 rsv8190; + u32 rsv8191; + u32 rx_pkt_msg_fifo_0[1]; /* 0x00008000 */ + u32 rx_pkt_msg_fifo_1[1]; /* 0x00008004 */ + u32 rx_pkt_msg_fifo_2[1]; /* 0x00008008 */ + u32 rx_pkt_msg_fifo_3[1]; /* 0x0000800c */ + u32 rx_pkt_msg_fifo_4[1]; /* 0x00008010 */ + u32 rx_pkt_msg_fifo_5[1]; /* 0x00008014 */ + u32 rx_pkt_msg_fifo_6[1]; /* 0x00008018 */ + u32 rx_pkt_msg_fifo_7[1]; /* 0x0000801c */ + u32 rx_pkt_msg_fifo_8[1]; /* 0x00008020 */ + u32 rx_pkt_msg_fifo_9[1]; /* 0x00008024 */ + u32 rx_pkt_msg_fifo_10[1]; /* 0x00008028 */ + u32 rx_pkt_msg_fifo_11[1]; /* 0x0000802c */ + u32 rx_pkt_msg_fifo_12[1]; /* 0x00008030 */ + u32 rx_pkt_msg_fifo_13[1]; /* 0x00008034 */ + u32 rx_pkt_msg_fifo_14[1]; /* 0x00008038 */ + u32 rx_pkt_msg_fifo_15[1]; /* 0x0000803c */ + u32 rx_pkt_msg_fifo_16[1]; /* 0x00008040 */ + u32 rx_pkt_msg_fifo_17[1]; /* 0x00008044 */ + u32 rx_pkt_msg_fifo_18[1]; /* 0x00008048 */ + u32 rx_pkt_msg_fifo_19[1]; /* 0x0000804c */ + u32 rx_pkt_msg_fifo_20[1]; /* 0x00008050 */ + u32 rx_pkt_msg_fifo_21[1]; /* 0x00008054 */ + u32 rx_pkt_msg_fifo_22[1]; /* 0x00008058 */ + u32 rx_pkt_msg_fifo_23[1]; /* 0x0000805c */ + u32 rx_pkt_msg_fifo_24[1]; /* 0x00008060 */ + u32 rx_pkt_msg_fifo_25[1]; /* 0x00008064 */ + u32 rx_pkt_msg_fifo_26[1]; /* 0x00008068 */ + u32 rx_pkt_msg_fifo_27[1]; /* 0x0000806c */ + u32 rx_pkt_msg_fifo_28[1]; /* 0x00008070 */ + u32 rx_pkt_msg_fifo_29[1]; /* 0x00008074 */ + u32 rx_pkt_msg_fifo_30[1]; /* 0x00008078 */ + u32 rx_pkt_msg_fifo_31[1]; /* 0x0000807c */ + u32 rx_pkt_msg_fifo_32[1]; /* 0x00008080 */ + u32 rx_pkt_msg_fifo_33[1]; /* 0x00008084 */ + u32 rx_pkt_msg_fifo_34[1]; /* 0x00008088 */ + u32 rx_pkt_msg_fifo_35[1]; /* 0x0000808c */ + u32 rx_pkt_msg_fifo_36[1]; /* 0x00008090 */ + u32 rx_pkt_msg_fifo_37[1]; /* 0x00008094 */ + u32 rx_pkt_msg_fifo_38[1]; /* 0x00008098 */ + u32 rx_pkt_msg_fifo_39[1]; /* 0x0000809c */ + u32 rx_pkt_msg_fifo_40[1]; /* 0x000080a0 */ + u32 rx_pkt_msg_fifo_41[1]; /* 0x000080a4 */ + u32 rx_pkt_msg_fifo_42[1]; /* 0x000080a8 */ + u32 rx_pkt_msg_fifo_43[1]; /* 0x000080ac */ + u32 rx_pkt_msg_fifo_44[1]; /* 0x000080b0 */ + u32 rx_pkt_msg_fifo_45[1]; /* 0x000080b4 */ + u32 rx_pkt_msg_fifo_46[1]; /* 0x000080b8 */ + u32 rx_pkt_msg_fifo_47[1]; /* 0x000080bc */ + u32 rx_pkt_msg_fifo_48[1]; /* 0x000080c0 */ + u32 rx_pkt_msg_fifo_49[1]; /* 0x000080c4 */ + u32 rx_pkt_msg_fifo_50[1]; /* 0x000080c8 */ + u32 rx_pkt_msg_fifo_51[1]; /* 0x000080cc */ + u32 rx_pkt_msg_fifo_52[1]; /* 0x000080d0 */ + u32 rx_pkt_msg_fifo_53[1]; /* 0x000080d4 */ + u32 rx_pkt_msg_fifo_54[1]; /* 0x000080d8 */ + u32 rx_pkt_msg_fifo_55[1]; /* 0x000080dc */ + u32 rx_pkt_msg_fifo_56[1]; /* 0x000080e0 */ + u32 rx_pkt_msg_fifo_57[1]; /* 0x000080e4 */ + u32 rx_pkt_msg_fifo_58[1]; /* 0x000080e8 */ + u32 rx_pkt_msg_fifo_59[1]; /* 0x000080ec */ + u32 rx_pkt_msg_fifo_60[1]; /* 0x000080f0 */ + u32 rx_pkt_msg_fifo_61[1]; /* 0x000080f4 */ + u32 rx_pkt_msg_fifo_62[1]; /* 0x000080f8 */ + u32 rx_pkt_msg_fifo_63[1]; /* 0x000080fc */ + u32 rx_pkt_msg_fifo_64[1]; /* 0x00008100 */ + u32 rx_pkt_msg_fifo_65[1]; /* 0x00008104 */ + u32 rx_pkt_msg_fifo_66[1]; /* 0x00008108 */ + u32 rx_pkt_msg_fifo_67[1]; /* 0x0000810c */ + u32 rx_pkt_msg_fifo_68[1]; /* 0x00008110 */ + u32 rx_pkt_msg_fifo_69[1]; /* 0x00008114 */ + u32 rx_pkt_msg_fifo_70[1]; /* 0x00008118 */ + u32 rx_pkt_msg_fifo_71[1]; /* 0x0000811c */ + u32 rx_pkt_msg_fifo_72[1]; /* 0x00008120 */ + u32 rx_pkt_msg_fifo_73[1]; /* 0x00008124 */ + u32 rx_pkt_msg_fifo_74[1]; /* 0x00008128 */ + u32 rx_pkt_msg_fifo_75[1]; /* 0x0000812c */ + u32 rx_pkt_msg_fifo_76[1]; /* 0x00008130 */ + u32 rx_pkt_msg_fifo_77[1]; /* 0x00008134 */ + u32 rx_pkt_msg_fifo_78[1]; /* 0x00008138 */ + u32 rx_pkt_msg_fifo_79[1]; /* 0x0000813c */ + u32 rx_pkt_msg_fifo_80[1]; /* 0x00008140 */ + u32 rx_pkt_msg_fifo_81[1]; /* 0x00008144 */ + u32 rx_pkt_msg_fifo_82[1]; /* 0x00008148 */ + u32 rx_pkt_msg_fifo_83[1]; /* 0x0000814c */ + u32 rx_pkt_msg_fifo_84[1]; /* 0x00008150 */ + u32 rx_pkt_msg_fifo_85[1]; /* 0x00008154 */ + u32 rx_pkt_msg_fifo_86[1]; /* 0x00008158 */ + u32 rx_pkt_msg_fifo_87[1]; /* 0x0000815c */ + u32 rx_pkt_msg_fifo_88[1]; /* 0x00008160 */ + u32 rx_pkt_msg_fifo_89[1]; /* 0x00008164 */ + u32 rx_pkt_msg_fifo_90[1]; /* 0x00008168 */ + u32 rx_pkt_msg_fifo_91[1]; /* 0x0000816c */ + u32 rx_pkt_msg_fifo_92[1]; /* 0x00008170 */ + u32 rx_pkt_msg_fifo_93[1]; /* 0x00008174 */ + u32 rx_pkt_msg_fifo_94[1]; /* 0x00008178 */ + u32 rx_pkt_msg_fifo_95[1]; /* 0x0000817c */ + u32 rx_pkt_msg_fifo_96[1]; /* 0x00008180 */ + u32 rx_pkt_msg_fifo_97[1]; /* 0x00008184 */ + u32 rx_pkt_msg_fifo_98[1]; /* 0x00008188 */ + u32 rx_pkt_msg_fifo_99[1]; /* 0x0000818c */ + u32 rx_pkt_msg_fifo_100[1]; /* 0x00008190 */ + u32 rx_pkt_msg_fifo_101[1]; /* 0x00008194 */ + u32 rx_pkt_msg_fifo_102[1]; /* 0x00008198 */ + u32 rx_pkt_msg_fifo_103[1]; /* 0x0000819c */ + u32 rx_pkt_msg_fifo_104[1]; /* 0x000081a0 */ + u32 rx_pkt_msg_fifo_105[1]; /* 0x000081a4 */ + u32 rx_pkt_msg_fifo_106[1]; /* 0x000081a8 */ + u32 rx_pkt_msg_fifo_107[1]; /* 0x000081ac */ + u32 rx_pkt_msg_fifo_108[1]; /* 0x000081b0 */ + u32 rx_pkt_msg_fifo_109[1]; /* 0x000081b4 */ + u32 rx_pkt_msg_fifo_110[1]; /* 0x000081b8 */ + u32 rx_pkt_msg_fifo_111[1]; /* 0x000081bc */ + u32 rx_pkt_msg_fifo_112[1]; /* 0x000081c0 */ + u32 rx_pkt_msg_fifo_113[1]; /* 0x000081c4 */ + u32 rx_pkt_msg_fifo_114[1]; /* 0x000081c8 */ + u32 rx_pkt_msg_fifo_115[1]; /* 0x000081cc */ + u32 rx_pkt_msg_fifo_116[1]; /* 0x000081d0 */ + u32 rx_pkt_msg_fifo_117[1]; /* 0x000081d4 */ + u32 rx_pkt_msg_fifo_118[1]; /* 0x000081d8 */ + u32 rx_pkt_msg_fifo_119[1]; /* 0x000081dc */ + u32 rx_pkt_msg_fifo_120[1]; /* 0x000081e0 */ + u32 rx_pkt_msg_fifo_121[1]; /* 0x000081e4 */ + u32 rx_pkt_msg_fifo_122[1]; /* 0x000081e8 */ + u32 rx_pkt_msg_fifo_123[1]; /* 0x000081ec */ + u32 rx_pkt_msg_fifo_124[1]; /* 0x000081f0 */ + u32 rx_pkt_msg_fifo_125[1]; /* 0x000081f4 */ + u32 rx_pkt_msg_fifo_126[1]; /* 0x000081f8 */ + u32 rx_pkt_msg_fifo_127[1]; /* 0x000081fc */ + u32 rx_pkt_msg_fifo_128[1]; /* 0x00008200 */ + u32 rx_pkt_msg_fifo_129[1]; /* 0x00008204 */ + u32 rx_pkt_msg_fifo_130[1]; /* 0x00008208 */ + u32 rx_pkt_msg_fifo_131[1]; /* 0x0000820c */ + u32 rx_pkt_msg_fifo_132[1]; /* 0x00008210 */ + u32 rx_pkt_msg_fifo_133[1]; /* 0x00008214 */ + u32 rx_pkt_msg_fifo_134[1]; /* 0x00008218 */ + u32 rx_pkt_msg_fifo_135[1]; /* 0x0000821c */ + u32 rx_pkt_msg_fifo_136[1]; /* 0x00008220 */ + u32 rx_pkt_msg_fifo_137[1]; /* 0x00008224 */ + u32 rx_pkt_msg_fifo_138[1]; /* 0x00008228 */ + u32 rx_pkt_msg_fifo_139[1]; /* 0x0000822c */ + u32 rx_pkt_msg_fifo_140[1]; /* 0x00008230 */ + u32 rx_pkt_msg_fifo_141[1]; /* 0x00008234 */ + u32 rx_pkt_msg_fifo_142[1]; /* 0x00008238 */ + u32 rx_pkt_msg_fifo_143[1]; /* 0x0000823c */ + u32 rx_pkt_msg_fifo_144[1]; /* 0x00008240 */ + u32 rx_pkt_msg_fifo_145[1]; /* 0x00008244 */ + u32 rx_pkt_msg_fifo_146[1]; /* 0x00008248 */ + u32 rx_pkt_msg_fifo_147[1]; /* 0x0000824c */ + u32 rx_pkt_msg_fifo_148[1]; /* 0x00008250 */ + u32 rx_pkt_msg_fifo_149[1]; /* 0x00008254 */ + u32 rx_pkt_msg_fifo_150[1]; /* 0x00008258 */ + u32 rx_pkt_msg_fifo_151[1]; /* 0x0000825c */ + u32 rx_pkt_msg_fifo_152[1]; /* 0x00008260 */ + u32 rx_pkt_msg_fifo_153[1]; /* 0x00008264 */ + u32 rx_pkt_msg_fifo_154[1]; /* 0x00008268 */ + u32 rx_pkt_msg_fifo_155[1]; /* 0x0000826c */ + u32 rx_pkt_msg_fifo_156[1]; /* 0x00008270 */ + u32 rx_pkt_msg_fifo_157[1]; /* 0x00008274 */ + u32 rx_pkt_msg_fifo_158[1]; /* 0x00008278 */ + u32 rx_pkt_msg_fifo_159[1]; /* 0x0000827c */ + u32 rx_pkt_msg_fifo_160[1]; /* 0x00008280 */ + u32 rx_pkt_msg_fifo_161[1]; /* 0x00008284 */ + u32 rx_pkt_msg_fifo_162[1]; /* 0x00008288 */ + u32 rx_pkt_msg_fifo_163[1]; /* 0x0000828c */ + u32 rx_pkt_msg_fifo_164[1]; /* 0x00008290 */ + u32 rx_pkt_msg_fifo_165[1]; /* 0x00008294 */ + u32 rx_pkt_msg_fifo_166[1]; /* 0x00008298 */ + u32 rx_pkt_msg_fifo_167[1]; /* 0x0000829c */ + u32 rx_pkt_msg_fifo_168[1]; /* 0x000082a0 */ + u32 rx_pkt_msg_fifo_169[1]; /* 0x000082a4 */ + u32 rx_pkt_msg_fifo_170[1]; /* 0x000082a8 */ + u32 rx_pkt_msg_fifo_171[1]; /* 0x000082ac */ + u32 rx_pkt_msg_fifo_172[1]; /* 0x000082b0 */ + u32 rx_pkt_msg_fifo_173[1]; /* 0x000082b4 */ + u32 rx_pkt_msg_fifo_174[1]; /* 0x000082b8 */ + u32 rx_pkt_msg_fifo_175[1]; /* 0x000082bc */ + u32 rx_pkt_msg_fifo_176[1]; /* 0x000082c0 */ + u32 rx_pkt_msg_fifo_177[1]; /* 0x000082c4 */ + u32 rx_pkt_msg_fifo_178[1]; /* 0x000082c8 */ + u32 rx_pkt_msg_fifo_179[1]; /* 0x000082cc */ + u32 rx_pkt_msg_fifo_180[1]; /* 0x000082d0 */ + u32 rx_pkt_msg_fifo_181[1]; /* 0x000082d4 */ + u32 rx_pkt_msg_fifo_182[1]; /* 0x000082d8 */ + u32 rx_pkt_msg_fifo_183[1]; /* 0x000082dc */ + u32 rx_pkt_msg_fifo_184[1]; /* 0x000082e0 */ + u32 rx_pkt_msg_fifo_185[1]; /* 0x000082e4 */ + u32 rx_pkt_msg_fifo_186[1]; /* 0x000082e8 */ + u32 rx_pkt_msg_fifo_187[1]; /* 0x000082ec */ + u32 rx_pkt_msg_fifo_188[1]; /* 0x000082f0 */ + u32 rx_pkt_msg_fifo_189[1]; /* 0x000082f4 */ + u32 rx_pkt_msg_fifo_190[1]; /* 0x000082f8 */ + u32 rx_pkt_msg_fifo_191[1]; /* 0x000082fc */ + u32 rx_pkt_msg_fifo_192[1]; /* 0x00008300 */ + u32 rx_pkt_msg_fifo_193[1]; /* 0x00008304 */ + u32 rx_pkt_msg_fifo_194[1]; /* 0x00008308 */ + u32 rx_pkt_msg_fifo_195[1]; /* 0x0000830c */ + u32 rx_pkt_msg_fifo_196[1]; /* 0x00008310 */ + u32 rx_pkt_msg_fifo_197[1]; /* 0x00008314 */ + u32 rx_pkt_msg_fifo_198[1]; /* 0x00008318 */ + u32 rx_pkt_msg_fifo_199[1]; /* 0x0000831c */ + u32 rx_pkt_msg_fifo_200[1]; /* 0x00008320 */ + u32 rx_pkt_msg_fifo_201[1]; /* 0x00008324 */ + u32 rx_pkt_msg_fifo_202[1]; /* 0x00008328 */ + u32 rx_pkt_msg_fifo_203[1]; /* 0x0000832c */ + u32 rx_pkt_msg_fifo_204[1]; /* 0x00008330 */ + u32 rx_pkt_msg_fifo_205[1]; /* 0x00008334 */ + u32 rx_pkt_msg_fifo_206[1]; /* 0x00008338 */ + u32 rx_pkt_msg_fifo_207[1]; /* 0x0000833c */ + u32 rx_pkt_msg_fifo_208[1]; /* 0x00008340 */ + u32 rx_pkt_msg_fifo_209[1]; /* 0x00008344 */ + u32 rx_pkt_msg_fifo_210[1]; /* 0x00008348 */ + u32 rx_pkt_msg_fifo_211[1]; /* 0x0000834c */ + u32 rx_pkt_msg_fifo_212[1]; /* 0x00008350 */ + u32 rx_pkt_msg_fifo_213[1]; /* 0x00008354 */ + u32 rx_pkt_msg_fifo_214[1]; /* 0x00008358 */ + u32 rx_pkt_msg_fifo_215[1]; /* 0x0000835c */ + u32 rx_pkt_msg_fifo_216[1]; /* 0x00008360 */ + u32 rx_pkt_msg_fifo_217[1]; /* 0x00008364 */ + u32 rx_pkt_msg_fifo_218[1]; /* 0x00008368 */ + u32 rx_pkt_msg_fifo_219[1]; /* 0x0000836c */ + u32 rx_pkt_msg_fifo_220[1]; /* 0x00008370 */ + u32 rx_pkt_msg_fifo_221[1]; /* 0x00008374 */ + u32 rx_pkt_msg_fifo_222[1]; /* 0x00008378 */ + u32 rx_pkt_msg_fifo_223[1]; /* 0x0000837c */ + u32 rx_pkt_msg_fifo_224[1]; /* 0x00008380 */ + u32 rx_pkt_msg_fifo_225[1]; /* 0x00008384 */ + u32 rx_pkt_msg_fifo_226[1]; /* 0x00008388 */ + u32 rx_pkt_msg_fifo_227[1]; /* 0x0000838c */ + u32 rx_pkt_msg_fifo_228[1]; /* 0x00008390 */ + u32 rx_pkt_msg_fifo_229[1]; /* 0x00008394 */ + u32 rx_pkt_msg_fifo_230[1]; /* 0x00008398 */ + u32 rx_pkt_msg_fifo_231[1]; /* 0x0000839c */ + u32 rx_pkt_msg_fifo_232[1]; /* 0x000083a0 */ + u32 rx_pkt_msg_fifo_233[1]; /* 0x000083a4 */ + u32 rx_pkt_msg_fifo_234[1]; /* 0x000083a8 */ + u32 rx_pkt_msg_fifo_235[1]; /* 0x000083ac */ + u32 rx_pkt_msg_fifo_236[1]; /* 0x000083b0 */ + u32 rx_pkt_msg_fifo_237[1]; /* 0x000083b4 */ + u32 rx_pkt_msg_fifo_238[1]; /* 0x000083b8 */ + u32 rx_pkt_msg_fifo_239[1]; /* 0x000083bc */ + u32 rx_pkt_msg_fifo_240[1]; /* 0x000083c0 */ + u32 rx_pkt_msg_fifo_241[1]; /* 0x000083c4 */ + u32 rx_pkt_msg_fifo_242[1]; /* 0x000083c8 */ + u32 rx_pkt_msg_fifo_243[1]; /* 0x000083cc */ + u32 rx_pkt_msg_fifo_244[1]; /* 0x000083d0 */ + u32 rx_pkt_msg_fifo_245[1]; /* 0x000083d4 */ + u32 rx_pkt_msg_fifo_246[1]; /* 0x000083d8 */ + u32 rx_pkt_msg_fifo_247[1]; /* 0x000083dc */ + u32 rx_pkt_msg_fifo_248[1]; /* 0x000083e0 */ + u32 rx_pkt_msg_fifo_249[1]; /* 0x000083e4 */ + u32 rx_pkt_msg_fifo_250[1]; /* 0x000083e8 */ + u32 rx_pkt_msg_fifo_251[1]; /* 0x000083ec */ + u32 rx_pkt_msg_fifo_252[1]; /* 0x000083f0 */ + u32 rx_pkt_msg_fifo_253[1]; /* 0x000083f4 */ + u32 rx_pkt_msg_fifo_254[1]; /* 0x000083f8 */ + u32 rx_pkt_msg_fifo_255[1]; /* 0x000083fc */ + u32 rx_pkt_msg_fifo_256[1]; /* 0x00008400 */ + u32 rx_pkt_msg_fifo_257[1]; /* 0x00008404 */ + u32 rx_pkt_msg_fifo_258[1]; /* 0x00008408 */ + u32 rx_pkt_msg_fifo_259[1]; /* 0x0000840c */ + u32 rx_pkt_msg_fifo_260[1]; /* 0x00008410 */ + u32 rx_pkt_msg_fifo_261[1]; /* 0x00008414 */ + u32 rx_pkt_msg_fifo_262[1]; /* 0x00008418 */ + u32 rx_pkt_msg_fifo_263[1]; /* 0x0000841c */ + u32 rx_pkt_msg_fifo_264[1]; /* 0x00008420 */ + u32 rx_pkt_msg_fifo_265[1]; /* 0x00008424 */ + u32 rx_pkt_msg_fifo_266[1]; /* 0x00008428 */ + u32 rx_pkt_msg_fifo_267[1]; /* 0x0000842c */ + u32 rx_pkt_msg_fifo_268[1]; /* 0x00008430 */ + u32 rx_pkt_msg_fifo_269[1]; /* 0x00008434 */ + u32 rx_pkt_msg_fifo_270[1]; /* 0x00008438 */ + u32 rx_pkt_msg_fifo_271[1]; /* 0x0000843c */ + u32 rx_pkt_msg_fifo_272[1]; /* 0x00008440 */ + u32 rx_pkt_msg_fifo_273[1]; /* 0x00008444 */ + u32 rx_pkt_msg_fifo_274[1]; /* 0x00008448 */ + u32 rx_pkt_msg_fifo_275[1]; /* 0x0000844c */ + u32 rx_pkt_msg_fifo_276[1]; /* 0x00008450 */ + u32 rx_pkt_msg_fifo_277[1]; /* 0x00008454 */ + u32 rx_pkt_msg_fifo_278[1]; /* 0x00008458 */ + u32 rx_pkt_msg_fifo_279[1]; /* 0x0000845c */ + u32 rx_pkt_msg_fifo_280[1]; /* 0x00008460 */ + u32 rx_pkt_msg_fifo_281[1]; /* 0x00008464 */ + u32 rx_pkt_msg_fifo_282[1]; /* 0x00008468 */ + u32 rx_pkt_msg_fifo_283[1]; /* 0x0000846c */ + u32 rx_pkt_msg_fifo_284[1]; /* 0x00008470 */ + u32 rx_pkt_msg_fifo_285[1]; /* 0x00008474 */ + u32 rx_pkt_msg_fifo_286[1]; /* 0x00008478 */ + u32 rx_pkt_msg_fifo_287[1]; /* 0x0000847c */ + u32 rx_pkt_msg_fifo_288[1]; /* 0x00008480 */ + u32 rx_pkt_msg_fifo_289[1]; /* 0x00008484 */ + u32 rx_pkt_msg_fifo_290[1]; /* 0x00008488 */ + u32 rx_pkt_msg_fifo_291[1]; /* 0x0000848c */ + u32 rx_pkt_msg_fifo_292[1]; /* 0x00008490 */ + u32 rx_pkt_msg_fifo_293[1]; /* 0x00008494 */ + u32 rx_pkt_msg_fifo_294[1]; /* 0x00008498 */ + u32 rx_pkt_msg_fifo_295[1]; /* 0x0000849c */ + u32 rx_pkt_msg_fifo_296[1]; /* 0x000084a0 */ + u32 rx_pkt_msg_fifo_297[1]; /* 0x000084a4 */ + u32 rx_pkt_msg_fifo_298[1]; /* 0x000084a8 */ + u32 rx_pkt_msg_fifo_299[1]; /* 0x000084ac */ + u32 rx_pkt_msg_fifo_300[1]; /* 0x000084b0 */ + u32 rx_pkt_msg_fifo_301[1]; /* 0x000084b4 */ + u32 rx_pkt_msg_fifo_302[1]; /* 0x000084b8 */ + u32 rx_pkt_msg_fifo_303[1]; /* 0x000084bc */ + u32 rx_pkt_msg_fifo_304[1]; /* 0x000084c0 */ + u32 rx_pkt_msg_fifo_305[1]; /* 0x000084c4 */ + u32 rx_pkt_msg_fifo_306[1]; /* 0x000084c8 */ + u32 rx_pkt_msg_fifo_307[1]; /* 0x000084cc */ + u32 rx_pkt_msg_fifo_308[1]; /* 0x000084d0 */ + u32 rx_pkt_msg_fifo_309[1]; /* 0x000084d4 */ + u32 rx_pkt_msg_fifo_310[1]; /* 0x000084d8 */ + u32 rx_pkt_msg_fifo_311[1]; /* 0x000084dc */ + u32 rx_pkt_msg_fifo_312[1]; /* 0x000084e0 */ + u32 rx_pkt_msg_fifo_313[1]; /* 0x000084e4 */ + u32 rx_pkt_msg_fifo_314[1]; /* 0x000084e8 */ + u32 rx_pkt_msg_fifo_315[1]; /* 0x000084ec */ + u32 rx_pkt_msg_fifo_316[1]; /* 0x000084f0 */ + u32 rx_pkt_msg_fifo_317[1]; /* 0x000084f4 */ + u32 rx_pkt_msg_fifo_318[1]; /* 0x000084f8 */ + u32 rx_pkt_msg_fifo_319[1]; /* 0x000084fc */ + u32 rx_pkt_msg_fifo_320[1]; /* 0x00008500 */ + u32 rx_pkt_msg_fifo_321[1]; /* 0x00008504 */ + u32 rx_pkt_msg_fifo_322[1]; /* 0x00008508 */ + u32 rx_pkt_msg_fifo_323[1]; /* 0x0000850c */ + u32 rx_pkt_msg_fifo_324[1]; /* 0x00008510 */ + u32 rsv8517; + u32 rsv8518; + u32 rsv8519; + u32 rsv8520; + u32 rsv8521; + u32 rsv8522; + u32 rsv8523; + u32 rsv8524; + u32 rsv8525; + u32 rsv8526; + u32 rsv8527; + u32 rsv8528; + u32 rsv8529; + u32 rsv8530; + u32 rsv8531; + u32 rsv8532; + u32 rsv8533; + u32 rsv8534; + u32 rsv8535; + u32 rsv8536; + u32 rsv8537; + u32 rsv8538; + u32 rsv8539; + u32 rsv8540; + u32 rsv8541; + u32 rsv8542; + u32 rsv8543; + u32 rsv8544; + u32 rsv8545; + u32 rsv8546; + u32 rsv8547; + u32 rsv8548; + u32 rsv8549; + u32 rsv8550; + u32 rsv8551; + u32 rsv8552; + u32 rsv8553; + u32 rsv8554; + u32 rsv8555; + u32 rsv8556; + u32 rsv8557; + u32 rsv8558; + u32 rsv8559; + u32 rsv8560; + u32 rsv8561; + u32 rsv8562; + u32 rsv8563; + u32 rsv8564; + u32 rsv8565; + u32 rsv8566; + u32 rsv8567; + u32 rsv8568; + u32 rsv8569; + u32 rsv8570; + u32 rsv8571; + u32 rsv8572; + u32 rsv8573; + u32 rsv8574; + u32 rsv8575; + u32 rsv8576; + u32 rsv8577; + u32 rsv8578; + u32 rsv8579; + u32 rsv8580; + u32 rsv8581; + u32 rsv8582; + u32 rsv8583; + u32 rsv8584; + u32 rsv8585; + u32 rsv8586; + u32 rsv8587; + u32 rsv8588; + u32 rsv8589; + u32 rsv8590; + u32 rsv8591; + u32 rsv8592; + u32 rsv8593; + u32 rsv8594; + u32 rsv8595; + u32 rsv8596; + u32 rsv8597; + u32 rsv8598; + u32 rsv8599; + u32 rsv8600; + u32 rsv8601; + u32 rsv8602; + u32 rsv8603; + u32 rsv8604; + u32 rsv8605; + u32 rsv8606; + u32 rsv8607; + u32 rsv8608; + u32 rsv8609; + u32 rsv8610; + u32 rsv8611; + u32 rsv8612; + u32 rsv8613; + u32 rsv8614; + u32 rsv8615; + u32 rsv8616; + u32 rsv8617; + u32 rsv8618; + u32 rsv8619; + u32 rsv8620; + u32 rsv8621; + u32 rsv8622; + u32 rsv8623; + u32 rsv8624; + u32 rsv8625; + u32 rsv8626; + u32 rsv8627; + u32 rsv8628; + u32 rsv8629; + u32 rsv8630; + u32 rsv8631; + u32 rsv8632; + u32 rsv8633; + u32 rsv8634; + u32 rsv8635; + u32 rsv8636; + u32 rsv8637; + u32 rsv8638; + u32 rsv8639; + u32 rsv8640; + u32 rsv8641; + u32 rsv8642; + u32 rsv8643; + u32 rsv8644; + u32 rsv8645; + u32 rsv8646; + u32 rsv8647; + u32 rsv8648; + u32 rsv8649; + u32 rsv8650; + u32 rsv8651; + u32 rsv8652; + u32 rsv8653; + u32 rsv8654; + u32 rsv8655; + u32 rsv8656; + u32 rsv8657; + u32 rsv8658; + u32 rsv8659; + u32 rsv8660; + u32 rsv8661; + u32 rsv8662; + u32 rsv8663; + u32 rsv8664; + u32 rsv8665; + u32 rsv8666; + u32 rsv8667; + u32 rsv8668; + u32 rsv8669; + u32 rsv8670; + u32 rsv8671; + u32 rsv8672; + u32 rsv8673; + u32 rsv8674; + u32 rsv8675; + u32 rsv8676; + u32 rsv8677; + u32 rsv8678; + u32 rsv8679; + u32 rsv8680; + u32 rsv8681; + u32 rsv8682; + u32 rsv8683; + u32 rsv8684; + u32 rsv8685; + u32 rsv8686; + u32 rsv8687; + u32 rsv8688; + u32 rsv8689; + u32 rsv8690; + u32 rsv8691; + u32 rsv8692; + u32 rsv8693; + u32 rsv8694; + u32 rsv8695; + u32 rsv8696; + u32 rsv8697; + u32 rsv8698; + u32 rsv8699; + u32 rsv8700; + u32 rsv8701; + u32 rsv8702; + u32 rsv8703; + u32 cpu_mac_stats_ram_0[4]; /* 0x00008800 */ + u32 cpu_mac_stats_ram_1[4]; /* 0x00008810 */ + u32 cpu_mac_stats_ram_2[4]; /* 0x00008820 */ + u32 cpu_mac_stats_ram_3[4]; /* 0x00008830 */ + u32 cpu_mac_stats_ram_4[4]; /* 0x00008840 */ + u32 cpu_mac_stats_ram_5[4]; /* 0x00008850 */ + u32 cpu_mac_stats_ram_6[4]; /* 0x00008860 */ + u32 cpu_mac_stats_ram_7[4]; /* 0x00008870 */ + u32 cpu_mac_stats_ram_8[4]; /* 0x00008880 */ + u32 cpu_mac_stats_ram_9[4]; /* 0x00008890 */ + u32 cpu_mac_stats_ram_10[4]; /* 0x000088a0 */ + u32 cpu_mac_stats_ram_11[4]; /* 0x000088b0 */ + u32 cpu_mac_stats_ram_12[4]; /* 0x000088c0 */ + u32 cpu_mac_stats_ram_13[4]; /* 0x000088d0 */ + u32 cpu_mac_stats_ram_14[4]; /* 0x000088e0 */ + u32 cpu_mac_stats_ram_15[4]; /* 0x000088f0 */ + u32 cpu_mac_stats_ram_16[4]; /* 0x00008900 */ + u32 cpu_mac_stats_ram_17[4]; /* 0x00008910 */ + u32 cpu_mac_stats_ram_18[4]; /* 0x00008920 */ + u32 cpu_mac_stats_ram_19[4]; /* 0x00008930 */ + u32 cpu_mac_stats_ram_20[4]; /* 0x00008940 */ + u32 cpu_mac_stats_ram_21[4]; /* 0x00008950 */ + u32 cpu_mac_stats_ram_22[4]; /* 0x00008960 */ + u32 cpu_mac_stats_ram_23[4]; /* 0x00008970 */ + u32 cpu_mac_stats_ram_24[4]; /* 0x00008980 */ + u32 cpu_mac_stats_ram_25[4]; /* 0x00008990 */ + u32 cpu_mac_stats_ram_26[4]; /* 0x000089a0 */ + u32 cpu_mac_stats_ram_27[4]; /* 0x000089b0 */ + u32 cpu_mac_stats_ram_28[4]; /* 0x000089c0 */ + u32 cpu_mac_stats_ram_29[4]; /* 0x000089d0 */ + u32 cpu_mac_stats_ram_30[4]; /* 0x000089e0 */ + u32 cpu_mac_stats_ram_31[4]; /* 0x000089f0 */ + u32 cpu_mac_stats_ram_32[4]; /* 0x00008a00 */ + u32 cpu_mac_stats_ram_33[4]; /* 0x00008a10 */ + u32 cpu_mac_stats_ram_34[4]; /* 0x00008a20 */ + u32 cpu_mac_stats_ram_35[4]; /* 0x00008a30 */ + u32 cpu_mac_stats_ram_36[4]; /* 0x00008a40 */ + u32 cpu_mac_stats_ram_37[4]; /* 0x00008a50 */ + u32 cpu_mac_stats_ram_38[4]; /* 0x00008a60 */ + u32 cpu_mac_stats_ram_39[4]; /* 0x00008a70 */ + u32 rsv8864; + u32 rsv8865; + u32 rsv8866; + u32 rsv8867; + u32 rsv8868; + u32 rsv8869; + u32 rsv8870; + u32 rsv8871; + u32 rsv8872; + u32 rsv8873; + u32 rsv8874; + u32 rsv8875; + u32 rsv8876; + u32 rsv8877; + u32 rsv8878; + u32 rsv8879; + u32 rsv8880; + u32 rsv8881; + u32 rsv8882; + u32 rsv8883; + u32 rsv8884; + u32 rsv8885; + u32 rsv8886; + u32 rsv8887; + u32 rsv8888; + u32 rsv8889; + u32 rsv8890; + u32 rsv8891; + u32 rsv8892; + u32 rsv8893; + u32 rsv8894; + u32 rsv8895; + u32 rsv8896; + u32 rsv8897; + u32 rsv8898; + u32 rsv8899; + u32 rsv8900; + u32 rsv8901; + u32 rsv8902; + u32 rsv8903; + u32 rsv8904; + u32 rsv8905; + u32 rsv8906; + u32 rsv8907; + u32 rsv8908; + u32 rsv8909; + u32 rsv8910; + u32 rsv8911; + u32 rsv8912; + u32 rsv8913; + u32 rsv8914; + u32 rsv8915; + u32 rsv8916; + u32 rsv8917; + u32 rsv8918; + u32 rsv8919; + u32 rsv8920; + u32 rsv8921; + u32 rsv8922; + u32 rsv8923; + u32 rsv8924; + u32 rsv8925; + u32 rsv8926; + u32 rsv8927; + u32 rsv8928; + u32 rsv8929; + u32 rsv8930; + u32 rsv8931; + u32 rsv8932; + u32 rsv8933; + u32 rsv8934; + u32 rsv8935; + u32 rsv8936; + u32 rsv8937; + u32 rsv8938; + u32 rsv8939; + u32 rsv8940; + u32 rsv8941; + u32 rsv8942; + u32 rsv8943; + u32 rsv8944; + u32 rsv8945; + u32 rsv8946; + u32 rsv8947; + u32 rsv8948; + u32 rsv8949; + u32 rsv8950; + u32 rsv8951; + u32 rsv8952; + u32 rsv8953; + u32 rsv8954; + u32 rsv8955; + u32 rsv8956; + u32 rsv8957; + u32 rsv8958; + u32 rsv8959; + u32 tx_desc_cfg_fifo_0[2]; /* 0x00008c00 */ + u32 tx_desc_cfg_fifo_1[2]; /* 0x00008c08 */ + u32 tx_desc_cfg_fifo_2[2]; /* 0x00008c10 */ + u32 tx_desc_cfg_fifo_3[2]; /* 0x00008c18 */ + u32 tx_desc_cfg_fifo_4[2]; /* 0x00008c20 */ + u32 tx_desc_cfg_fifo_5[2]; /* 0x00008c28 */ + u32 tx_desc_cfg_fifo_6[2]; /* 0x00008c30 */ + u32 tx_desc_cfg_fifo_7[2]; /* 0x00008c38 */ + u32 tx_desc_cfg_fifo_8[2]; /* 0x00008c40 */ + u32 tx_desc_cfg_fifo_9[2]; /* 0x00008c48 */ + u32 tx_desc_cfg_fifo_10[2]; /* 0x00008c50 */ + u32 tx_desc_cfg_fifo_11[2]; /* 0x00008c58 */ + u32 tx_desc_cfg_fifo_12[2]; /* 0x00008c60 */ + u32 tx_desc_cfg_fifo_13[2]; /* 0x00008c68 */ + u32 tx_desc_cfg_fifo_14[2]; /* 0x00008c70 */ + u32 tx_desc_cfg_fifo_15[2]; /* 0x00008c78 */ + u32 tx_desc_cfg_fifo_16[2]; /* 0x00008c80 */ + u32 tx_desc_cfg_fifo_17[2]; /* 0x00008c88 */ + u32 tx_desc_cfg_fifo_18[2]; /* 0x00008c90 */ + u32 tx_desc_cfg_fifo_19[2]; /* 0x00008c98 */ + u32 tx_desc_cfg_fifo_20[2]; /* 0x00008ca0 */ + u32 tx_desc_cfg_fifo_21[2]; /* 0x00008ca8 */ + u32 tx_desc_cfg_fifo_22[2]; /* 0x00008cb0 */ + u32 tx_desc_cfg_fifo_23[2]; /* 0x00008cb8 */ + u32 tx_desc_cfg_fifo_24[2]; /* 0x00008cc0 */ + u32 tx_desc_cfg_fifo_25[2]; /* 0x00008cc8 */ + u32 tx_desc_cfg_fifo_26[2]; /* 0x00008cd0 */ + u32 tx_desc_cfg_fifo_27[2]; /* 0x00008cd8 */ + u32 tx_desc_cfg_fifo_28[2]; /* 0x00008ce0 */ + u32 tx_desc_cfg_fifo_29[2]; /* 0x00008ce8 */ + u32 tx_desc_cfg_fifo_30[2]; /* 0x00008cf0 */ + u32 tx_desc_cfg_fifo_31[2]; /* 0x00008cf8 */ + u32 tx_desc_cfg_fifo_32[2]; /* 0x00008d00 */ + u32 tx_desc_cfg_fifo_33[2]; /* 0x00008d08 */ + u32 tx_desc_cfg_fifo_34[2]; /* 0x00008d10 */ + u32 tx_desc_cfg_fifo_35[2]; /* 0x00008d18 */ + u32 tx_desc_cfg_fifo_36[2]; /* 0x00008d20 */ + u32 tx_desc_cfg_fifo_37[2]; /* 0x00008d28 */ + u32 tx_desc_cfg_fifo_38[2]; /* 0x00008d30 */ + u32 tx_desc_cfg_fifo_39[2]; /* 0x00008d38 */ + u32 tx_desc_cfg_fifo_40[2]; /* 0x00008d40 */ + u32 tx_desc_cfg_fifo_41[2]; /* 0x00008d48 */ + u32 tx_desc_cfg_fifo_42[2]; /* 0x00008d50 */ + u32 tx_desc_cfg_fifo_43[2]; /* 0x00008d58 */ + u32 tx_desc_cfg_fifo_44[2]; /* 0x00008d60 */ + u32 tx_desc_cfg_fifo_45[2]; /* 0x00008d68 */ + u32 tx_desc_cfg_fifo_46[2]; /* 0x00008d70 */ + u32 tx_desc_cfg_fifo_47[2]; /* 0x00008d78 */ + u32 tx_desc_cfg_fifo_48[2]; /* 0x00008d80 */ + u32 tx_desc_cfg_fifo_49[2]; /* 0x00008d88 */ + u32 tx_desc_cfg_fifo_50[2]; /* 0x00008d90 */ + u32 tx_desc_cfg_fifo_51[2]; /* 0x00008d98 */ + u32 tx_desc_cfg_fifo_52[2]; /* 0x00008da0 */ + u32 tx_desc_cfg_fifo_53[2]; /* 0x00008da8 */ + u32 tx_desc_cfg_fifo_54[2]; /* 0x00008db0 */ + u32 tx_desc_cfg_fifo_55[2]; /* 0x00008db8 */ + u32 tx_desc_cfg_fifo_56[2]; /* 0x00008dc0 */ + u32 tx_desc_cfg_fifo_57[2]; /* 0x00008dc8 */ + u32 tx_desc_cfg_fifo_58[2]; /* 0x00008dd0 */ + u32 tx_desc_cfg_fifo_59[2]; /* 0x00008dd8 */ + u32 tx_desc_cfg_fifo_60[2]; /* 0x00008de0 */ + u32 tx_desc_cfg_fifo_61[2]; /* 0x00008de8 */ + u32 tx_desc_cfg_fifo_62[2]; /* 0x00008df0 */ + u32 tx_desc_cfg_fifo_63[2]; /* 0x00008df8 */ + u32 rx_desc_0_cfg_fifo_0[2]; /* 0x00008e00 */ + u32 rx_desc_0_cfg_fifo_1[2]; /* 0x00008e08 */ + u32 rx_desc_0_cfg_fifo_2[2]; /* 0x00008e10 */ + u32 rx_desc_0_cfg_fifo_3[2]; /* 0x00008e18 */ + u32 rx_desc_0_cfg_fifo_4[2]; /* 0x00008e20 */ + u32 rx_desc_0_cfg_fifo_5[2]; /* 0x00008e28 */ + u32 rx_desc_0_cfg_fifo_6[2]; /* 0x00008e30 */ + u32 rx_desc_0_cfg_fifo_7[2]; /* 0x00008e38 */ + u32 rx_desc_0_cfg_fifo_8[2]; /* 0x00008e40 */ + u32 rx_desc_0_cfg_fifo_9[2]; /* 0x00008e48 */ + u32 rx_desc_0_cfg_fifo_10[2]; /* 0x00008e50 */ + u32 rx_desc_0_cfg_fifo_11[2]; /* 0x00008e58 */ + u32 rx_desc_0_cfg_fifo_12[2]; /* 0x00008e60 */ + u32 rx_desc_0_cfg_fifo_13[2]; /* 0x00008e68 */ + u32 rx_desc_0_cfg_fifo_14[2]; /* 0x00008e70 */ + u32 rx_desc_0_cfg_fifo_15[2]; /* 0x00008e78 */ + u32 rx_desc_0_cfg_fifo_16[2]; /* 0x00008e80 */ + u32 rx_desc_0_cfg_fifo_17[2]; /* 0x00008e88 */ + u32 rx_desc_0_cfg_fifo_18[2]; /* 0x00008e90 */ + u32 rx_desc_0_cfg_fifo_19[2]; /* 0x00008e98 */ + u32 rx_desc_0_cfg_fifo_20[2]; /* 0x00008ea0 */ + u32 rx_desc_0_cfg_fifo_21[2]; /* 0x00008ea8 */ + u32 rx_desc_0_cfg_fifo_22[2]; /* 0x00008eb0 */ + u32 rx_desc_0_cfg_fifo_23[2]; /* 0x00008eb8 */ + u32 rx_desc_0_cfg_fifo_24[2]; /* 0x00008ec0 */ + u32 rx_desc_0_cfg_fifo_25[2]; /* 0x00008ec8 */ + u32 rx_desc_0_cfg_fifo_26[2]; /* 0x00008ed0 */ + u32 rx_desc_0_cfg_fifo_27[2]; /* 0x00008ed8 */ + u32 rx_desc_0_cfg_fifo_28[2]; /* 0x00008ee0 */ + u32 rx_desc_0_cfg_fifo_29[2]; /* 0x00008ee8 */ + u32 rx_desc_0_cfg_fifo_30[2]; /* 0x00008ef0 */ + u32 rx_desc_0_cfg_fifo_31[2]; /* 0x00008ef8 */ + u32 rx_desc_0_cfg_fifo_32[2]; /* 0x00008f00 */ + u32 rx_desc_0_cfg_fifo_33[2]; /* 0x00008f08 */ + u32 rx_desc_0_cfg_fifo_34[2]; /* 0x00008f10 */ + u32 rx_desc_0_cfg_fifo_35[2]; /* 0x00008f18 */ + u32 rx_desc_0_cfg_fifo_36[2]; /* 0x00008f20 */ + u32 rx_desc_0_cfg_fifo_37[2]; /* 0x00008f28 */ + u32 rx_desc_0_cfg_fifo_38[2]; /* 0x00008f30 */ + u32 rx_desc_0_cfg_fifo_39[2]; /* 0x00008f38 */ + u32 rx_desc_0_cfg_fifo_40[2]; /* 0x00008f40 */ + u32 rx_desc_0_cfg_fifo_41[2]; /* 0x00008f48 */ + u32 rx_desc_0_cfg_fifo_42[2]; /* 0x00008f50 */ + u32 rx_desc_0_cfg_fifo_43[2]; /* 0x00008f58 */ + u32 rx_desc_0_cfg_fifo_44[2]; /* 0x00008f60 */ + u32 rx_desc_0_cfg_fifo_45[2]; /* 0x00008f68 */ + u32 rx_desc_0_cfg_fifo_46[2]; /* 0x00008f70 */ + u32 rx_desc_0_cfg_fifo_47[2]; /* 0x00008f78 */ + u32 rx_desc_0_cfg_fifo_48[2]; /* 0x00008f80 */ + u32 rx_desc_0_cfg_fifo_49[2]; /* 0x00008f88 */ + u32 rx_desc_0_cfg_fifo_50[2]; /* 0x00008f90 */ + u32 rx_desc_0_cfg_fifo_51[2]; /* 0x00008f98 */ + u32 rx_desc_0_cfg_fifo_52[2]; /* 0x00008fa0 */ + u32 rx_desc_0_cfg_fifo_53[2]; /* 0x00008fa8 */ + u32 rx_desc_0_cfg_fifo_54[2]; /* 0x00008fb0 */ + u32 rx_desc_0_cfg_fifo_55[2]; /* 0x00008fb8 */ + u32 rx_desc_0_cfg_fifo_56[2]; /* 0x00008fc0 */ + u32 rx_desc_0_cfg_fifo_57[2]; /* 0x00008fc8 */ + u32 rx_desc_0_cfg_fifo_58[2]; /* 0x00008fd0 */ + u32 rx_desc_0_cfg_fifo_59[2]; /* 0x00008fd8 */ + u32 rx_desc_0_cfg_fifo_60[2]; /* 0x00008fe0 */ + u32 rx_desc_0_cfg_fifo_61[2]; /* 0x00008fe8 */ + u32 rx_desc_0_cfg_fifo_62[2]; /* 0x00008ff0 */ + u32 rx_desc_0_cfg_fifo_63[2]; /* 0x00008ff8 */ + u32 rx_desc_1_cfg_fifo_0[2]; /* 0x00009000 */ + u32 rx_desc_1_cfg_fifo_1[2]; /* 0x00009008 */ + u32 rx_desc_1_cfg_fifo_2[2]; /* 0x00009010 */ + u32 rx_desc_1_cfg_fifo_3[2]; /* 0x00009018 */ + u32 rx_desc_1_cfg_fifo_4[2]; /* 0x00009020 */ + u32 rx_desc_1_cfg_fifo_5[2]; /* 0x00009028 */ + u32 rx_desc_1_cfg_fifo_6[2]; /* 0x00009030 */ + u32 rx_desc_1_cfg_fifo_7[2]; /* 0x00009038 */ + u32 rx_desc_1_cfg_fifo_8[2]; /* 0x00009040 */ + u32 rx_desc_1_cfg_fifo_9[2]; /* 0x00009048 */ + u32 rx_desc_1_cfg_fifo_10[2]; /* 0x00009050 */ + u32 rx_desc_1_cfg_fifo_11[2]; /* 0x00009058 */ + u32 rx_desc_1_cfg_fifo_12[2]; /* 0x00009060 */ + u32 rx_desc_1_cfg_fifo_13[2]; /* 0x00009068 */ + u32 rx_desc_1_cfg_fifo_14[2]; /* 0x00009070 */ + u32 rx_desc_1_cfg_fifo_15[2]; /* 0x00009078 */ + u32 rx_desc_1_cfg_fifo_16[2]; /* 0x00009080 */ + u32 rx_desc_1_cfg_fifo_17[2]; /* 0x00009088 */ + u32 rx_desc_1_cfg_fifo_18[2]; /* 0x00009090 */ + u32 rx_desc_1_cfg_fifo_19[2]; /* 0x00009098 */ + u32 rx_desc_1_cfg_fifo_20[2]; /* 0x000090a0 */ + u32 rx_desc_1_cfg_fifo_21[2]; /* 0x000090a8 */ + u32 rx_desc_1_cfg_fifo_22[2]; /* 0x000090b0 */ + u32 rx_desc_1_cfg_fifo_23[2]; /* 0x000090b8 */ + u32 rx_desc_1_cfg_fifo_24[2]; /* 0x000090c0 */ + u32 rx_desc_1_cfg_fifo_25[2]; /* 0x000090c8 */ + u32 rx_desc_1_cfg_fifo_26[2]; /* 0x000090d0 */ + u32 rx_desc_1_cfg_fifo_27[2]; /* 0x000090d8 */ + u32 rx_desc_1_cfg_fifo_28[2]; /* 0x000090e0 */ + u32 rx_desc_1_cfg_fifo_29[2]; /* 0x000090e8 */ + u32 rx_desc_1_cfg_fifo_30[2]; /* 0x000090f0 */ + u32 rx_desc_1_cfg_fifo_31[2]; /* 0x000090f8 */ + u32 rx_desc_1_cfg_fifo_32[2]; /* 0x00009100 */ + u32 rx_desc_1_cfg_fifo_33[2]; /* 0x00009108 */ + u32 rx_desc_1_cfg_fifo_34[2]; /* 0x00009110 */ + u32 rx_desc_1_cfg_fifo_35[2]; /* 0x00009118 */ + u32 rx_desc_1_cfg_fifo_36[2]; /* 0x00009120 */ + u32 rx_desc_1_cfg_fifo_37[2]; /* 0x00009128 */ + u32 rx_desc_1_cfg_fifo_38[2]; /* 0x00009130 */ + u32 rx_desc_1_cfg_fifo_39[2]; /* 0x00009138 */ + u32 rx_desc_1_cfg_fifo_40[2]; /* 0x00009140 */ + u32 rx_desc_1_cfg_fifo_41[2]; /* 0x00009148 */ + u32 rx_desc_1_cfg_fifo_42[2]; /* 0x00009150 */ + u32 rx_desc_1_cfg_fifo_43[2]; /* 0x00009158 */ + u32 rx_desc_1_cfg_fifo_44[2]; /* 0x00009160 */ + u32 rx_desc_1_cfg_fifo_45[2]; /* 0x00009168 */ + u32 rx_desc_1_cfg_fifo_46[2]; /* 0x00009170 */ + u32 rx_desc_1_cfg_fifo_47[2]; /* 0x00009178 */ + u32 rx_desc_1_cfg_fifo_48[2]; /* 0x00009180 */ + u32 rx_desc_1_cfg_fifo_49[2]; /* 0x00009188 */ + u32 rx_desc_1_cfg_fifo_50[2]; /* 0x00009190 */ + u32 rx_desc_1_cfg_fifo_51[2]; /* 0x00009198 */ + u32 rx_desc_1_cfg_fifo_52[2]; /* 0x000091a0 */ + u32 rx_desc_1_cfg_fifo_53[2]; /* 0x000091a8 */ + u32 rx_desc_1_cfg_fifo_54[2]; /* 0x000091b0 */ + u32 rx_desc_1_cfg_fifo_55[2]; /* 0x000091b8 */ + u32 rx_desc_1_cfg_fifo_56[2]; /* 0x000091c0 */ + u32 rx_desc_1_cfg_fifo_57[2]; /* 0x000091c8 */ + u32 rx_desc_1_cfg_fifo_58[2]; /* 0x000091d0 */ + u32 rx_desc_1_cfg_fifo_59[2]; /* 0x000091d8 */ + u32 rx_desc_1_cfg_fifo_60[2]; /* 0x000091e0 */ + u32 rx_desc_1_cfg_fifo_61[2]; /* 0x000091e8 */ + u32 rx_desc_1_cfg_fifo_62[2]; /* 0x000091f0 */ + u32 rx_desc_1_cfg_fifo_63[2]; /* 0x000091f8 */ + u32 rx_desc_0_ack_fifo_0[1]; /* 0x00009200 */ + u32 rx_desc_0_ack_fifo_1[1]; /* 0x00009204 */ + u32 rx_desc_0_ack_fifo_2[1]; /* 0x00009208 */ + u32 rx_desc_0_ack_fifo_3[1]; /* 0x0000920c */ + u32 rx_desc_0_ack_fifo_4[1]; /* 0x00009210 */ + u32 rx_desc_0_ack_fifo_5[1]; /* 0x00009214 */ + u32 rx_desc_0_ack_fifo_6[1]; /* 0x00009218 */ + u32 rx_desc_0_ack_fifo_7[1]; /* 0x0000921c */ + u32 rx_desc_0_ack_fifo_8[1]; /* 0x00009220 */ + u32 rx_desc_0_ack_fifo_9[1]; /* 0x00009224 */ + u32 rx_desc_0_ack_fifo_10[1]; /* 0x00009228 */ + u32 rx_desc_0_ack_fifo_11[1]; /* 0x0000922c */ + u32 rx_desc_0_ack_fifo_12[1]; /* 0x00009230 */ + u32 rx_desc_0_ack_fifo_13[1]; /* 0x00009234 */ + u32 rx_desc_0_ack_fifo_14[1]; /* 0x00009238 */ + u32 rx_desc_0_ack_fifo_15[1]; /* 0x0000923c */ + u32 rx_desc_0_ack_fifo_16[1]; /* 0x00009240 */ + u32 rx_desc_0_ack_fifo_17[1]; /* 0x00009244 */ + u32 rx_desc_0_ack_fifo_18[1]; /* 0x00009248 */ + u32 rx_desc_0_ack_fifo_19[1]; /* 0x0000924c */ + u32 rx_desc_0_ack_fifo_20[1]; /* 0x00009250 */ + u32 rx_desc_0_ack_fifo_21[1]; /* 0x00009254 */ + u32 rx_desc_0_ack_fifo_22[1]; /* 0x00009258 */ + u32 rx_desc_0_ack_fifo_23[1]; /* 0x0000925c */ + u32 rx_desc_0_ack_fifo_24[1]; /* 0x00009260 */ + u32 rx_desc_0_ack_fifo_25[1]; /* 0x00009264 */ + u32 rx_desc_0_ack_fifo_26[1]; /* 0x00009268 */ + u32 rx_desc_0_ack_fifo_27[1]; /* 0x0000926c */ + u32 rx_desc_0_ack_fifo_28[1]; /* 0x00009270 */ + u32 rx_desc_0_ack_fifo_29[1]; /* 0x00009274 */ + u32 rx_desc_0_ack_fifo_30[1]; /* 0x00009278 */ + u32 rx_desc_0_ack_fifo_31[1]; /* 0x0000927c */ + u32 rx_desc_0_ack_fifo_32[1]; /* 0x00009280 */ + u32 rx_desc_0_ack_fifo_33[1]; /* 0x00009284 */ + u32 rx_desc_0_ack_fifo_34[1]; /* 0x00009288 */ + u32 rx_desc_0_ack_fifo_35[1]; /* 0x0000928c */ + u32 rx_desc_0_ack_fifo_36[1]; /* 0x00009290 */ + u32 rx_desc_0_ack_fifo_37[1]; /* 0x00009294 */ + u32 rx_desc_0_ack_fifo_38[1]; /* 0x00009298 */ + u32 rx_desc_0_ack_fifo_39[1]; /* 0x0000929c */ + u32 rx_desc_0_ack_fifo_40[1]; /* 0x000092a0 */ + u32 rx_desc_0_ack_fifo_41[1]; /* 0x000092a4 */ + u32 rx_desc_0_ack_fifo_42[1]; /* 0x000092a8 */ + u32 rx_desc_0_ack_fifo_43[1]; /* 0x000092ac */ + u32 rx_desc_0_ack_fifo_44[1]; /* 0x000092b0 */ + u32 rx_desc_0_ack_fifo_45[1]; /* 0x000092b4 */ + u32 rx_desc_0_ack_fifo_46[1]; /* 0x000092b8 */ + u32 rx_desc_0_ack_fifo_47[1]; /* 0x000092bc */ + u32 rx_desc_0_ack_fifo_48[1]; /* 0x000092c0 */ + u32 rx_desc_0_ack_fifo_49[1]; /* 0x000092c4 */ + u32 rx_desc_0_ack_fifo_50[1]; /* 0x000092c8 */ + u32 rx_desc_0_ack_fifo_51[1]; /* 0x000092cc */ + u32 rx_desc_0_ack_fifo_52[1]; /* 0x000092d0 */ + u32 rx_desc_0_ack_fifo_53[1]; /* 0x000092d4 */ + u32 rx_desc_0_ack_fifo_54[1]; /* 0x000092d8 */ + u32 rx_desc_0_ack_fifo_55[1]; /* 0x000092dc */ + u32 rx_desc_0_ack_fifo_56[1]; /* 0x000092e0 */ + u32 rx_desc_0_ack_fifo_57[1]; /* 0x000092e4 */ + u32 rx_desc_0_ack_fifo_58[1]; /* 0x000092e8 */ + u32 rx_desc_0_ack_fifo_59[1]; /* 0x000092ec */ + u32 rx_desc_0_ack_fifo_60[1]; /* 0x000092f0 */ + u32 rx_desc_0_ack_fifo_61[1]; /* 0x000092f4 */ + u32 rx_desc_0_ack_fifo_62[1]; /* 0x000092f8 */ + u32 rx_desc_0_ack_fifo_63[1]; /* 0x000092fc */ + u32 rx_desc_1_ack_fifo_0[1]; /* 0x00009300 */ + u32 rx_desc_1_ack_fifo_1[1]; /* 0x00009304 */ + u32 rx_desc_1_ack_fifo_2[1]; /* 0x00009308 */ + u32 rx_desc_1_ack_fifo_3[1]; /* 0x0000930c */ + u32 rx_desc_1_ack_fifo_4[1]; /* 0x00009310 */ + u32 rx_desc_1_ack_fifo_5[1]; /* 0x00009314 */ + u32 rx_desc_1_ack_fifo_6[1]; /* 0x00009318 */ + u32 rx_desc_1_ack_fifo_7[1]; /* 0x0000931c */ + u32 rx_desc_1_ack_fifo_8[1]; /* 0x00009320 */ + u32 rx_desc_1_ack_fifo_9[1]; /* 0x00009324 */ + u32 rx_desc_1_ack_fifo_10[1]; /* 0x00009328 */ + u32 rx_desc_1_ack_fifo_11[1]; /* 0x0000932c */ + u32 rx_desc_1_ack_fifo_12[1]; /* 0x00009330 */ + u32 rx_desc_1_ack_fifo_13[1]; /* 0x00009334 */ + u32 rx_desc_1_ack_fifo_14[1]; /* 0x00009338 */ + u32 rx_desc_1_ack_fifo_15[1]; /* 0x0000933c */ + u32 rx_desc_1_ack_fifo_16[1]; /* 0x00009340 */ + u32 rx_desc_1_ack_fifo_17[1]; /* 0x00009344 */ + u32 rx_desc_1_ack_fifo_18[1]; /* 0x00009348 */ + u32 rx_desc_1_ack_fifo_19[1]; /* 0x0000934c */ + u32 rx_desc_1_ack_fifo_20[1]; /* 0x00009350 */ + u32 rx_desc_1_ack_fifo_21[1]; /* 0x00009354 */ + u32 rx_desc_1_ack_fifo_22[1]; /* 0x00009358 */ + u32 rx_desc_1_ack_fifo_23[1]; /* 0x0000935c */ + u32 rx_desc_1_ack_fifo_24[1]; /* 0x00009360 */ + u32 rx_desc_1_ack_fifo_25[1]; /* 0x00009364 */ + u32 rx_desc_1_ack_fifo_26[1]; /* 0x00009368 */ + u32 rx_desc_1_ack_fifo_27[1]; /* 0x0000936c */ + u32 rx_desc_1_ack_fifo_28[1]; /* 0x00009370 */ + u32 rx_desc_1_ack_fifo_29[1]; /* 0x00009374 */ + u32 rx_desc_1_ack_fifo_30[1]; /* 0x00009378 */ + u32 rx_desc_1_ack_fifo_31[1]; /* 0x0000937c */ + u32 rx_desc_1_ack_fifo_32[1]; /* 0x00009380 */ + u32 rx_desc_1_ack_fifo_33[1]; /* 0x00009384 */ + u32 rx_desc_1_ack_fifo_34[1]; /* 0x00009388 */ + u32 rx_desc_1_ack_fifo_35[1]; /* 0x0000938c */ + u32 rx_desc_1_ack_fifo_36[1]; /* 0x00009390 */ + u32 rx_desc_1_ack_fifo_37[1]; /* 0x00009394 */ + u32 rx_desc_1_ack_fifo_38[1]; /* 0x00009398 */ + u32 rx_desc_1_ack_fifo_39[1]; /* 0x0000939c */ + u32 rx_desc_1_ack_fifo_40[1]; /* 0x000093a0 */ + u32 rx_desc_1_ack_fifo_41[1]; /* 0x000093a4 */ + u32 rx_desc_1_ack_fifo_42[1]; /* 0x000093a8 */ + u32 rx_desc_1_ack_fifo_43[1]; /* 0x000093ac */ + u32 rx_desc_1_ack_fifo_44[1]; /* 0x000093b0 */ + u32 rx_desc_1_ack_fifo_45[1]; /* 0x000093b4 */ + u32 rx_desc_1_ack_fifo_46[1]; /* 0x000093b8 */ + u32 rx_desc_1_ack_fifo_47[1]; /* 0x000093bc */ + u32 rx_desc_1_ack_fifo_48[1]; /* 0x000093c0 */ + u32 rx_desc_1_ack_fifo_49[1]; /* 0x000093c4 */ + u32 rx_desc_1_ack_fifo_50[1]; /* 0x000093c8 */ + u32 rx_desc_1_ack_fifo_51[1]; /* 0x000093cc */ + u32 rx_desc_1_ack_fifo_52[1]; /* 0x000093d0 */ + u32 rx_desc_1_ack_fifo_53[1]; /* 0x000093d4 */ + u32 rx_desc_1_ack_fifo_54[1]; /* 0x000093d8 */ + u32 rx_desc_1_ack_fifo_55[1]; /* 0x000093dc */ + u32 rx_desc_1_ack_fifo_56[1]; /* 0x000093e0 */ + u32 rx_desc_1_ack_fifo_57[1]; /* 0x000093e4 */ + u32 rx_desc_1_ack_fifo_58[1]; /* 0x000093e8 */ + u32 rx_desc_1_ack_fifo_59[1]; /* 0x000093ec */ + u32 rx_desc_1_ack_fifo_60[1]; /* 0x000093f0 */ + u32 rx_desc_1_ack_fifo_61[1]; /* 0x000093f4 */ + u32 rx_desc_1_ack_fifo_62[1]; /* 0x000093f8 */ + u32 rx_desc_1_ack_fifo_63[1]; /* 0x000093fc */ + u32 tx_desc_ack_fifo_0[1]; /* 0x00009400 */ + u32 tx_desc_ack_fifo_1[1]; /* 0x00009404 */ + u32 tx_desc_ack_fifo_2[1]; /* 0x00009408 */ + u32 tx_desc_ack_fifo_3[1]; /* 0x0000940c */ + u32 tx_desc_ack_fifo_4[1]; /* 0x00009410 */ + u32 tx_desc_ack_fifo_5[1]; /* 0x00009414 */ + u32 tx_desc_ack_fifo_6[1]; /* 0x00009418 */ + u32 tx_desc_ack_fifo_7[1]; /* 0x0000941c */ + u32 tx_desc_ack_fifo_8[1]; /* 0x00009420 */ + u32 tx_desc_ack_fifo_9[1]; /* 0x00009424 */ + u32 tx_desc_ack_fifo_10[1]; /* 0x00009428 */ + u32 tx_desc_ack_fifo_11[1]; /* 0x0000942c */ + u32 tx_desc_ack_fifo_12[1]; /* 0x00009430 */ + u32 tx_desc_ack_fifo_13[1]; /* 0x00009434 */ + u32 tx_desc_ack_fifo_14[1]; /* 0x00009438 */ + u32 tx_desc_ack_fifo_15[1]; /* 0x0000943c */ + u32 tx_desc_ack_fifo_16[1]; /* 0x00009440 */ + u32 tx_desc_ack_fifo_17[1]; /* 0x00009444 */ + u32 tx_desc_ack_fifo_18[1]; /* 0x00009448 */ + u32 tx_desc_ack_fifo_19[1]; /* 0x0000944c */ + u32 tx_desc_ack_fifo_20[1]; /* 0x00009450 */ + u32 tx_desc_ack_fifo_21[1]; /* 0x00009454 */ + u32 tx_desc_ack_fifo_22[1]; /* 0x00009458 */ + u32 tx_desc_ack_fifo_23[1]; /* 0x0000945c */ + u32 tx_desc_ack_fifo_24[1]; /* 0x00009460 */ + u32 tx_desc_ack_fifo_25[1]; /* 0x00009464 */ + u32 tx_desc_ack_fifo_26[1]; /* 0x00009468 */ + u32 tx_desc_ack_fifo_27[1]; /* 0x0000946c */ + u32 tx_desc_ack_fifo_28[1]; /* 0x00009470 */ + u32 tx_desc_ack_fifo_29[1]; /* 0x00009474 */ + u32 tx_desc_ack_fifo_30[1]; /* 0x00009478 */ + u32 tx_desc_ack_fifo_31[1]; /* 0x0000947c */ + u32 tx_desc_ack_fifo_32[1]; /* 0x00009480 */ + u32 tx_desc_ack_fifo_33[1]; /* 0x00009484 */ + u32 tx_desc_ack_fifo_34[1]; /* 0x00009488 */ + u32 tx_desc_ack_fifo_35[1]; /* 0x0000948c */ + u32 tx_desc_ack_fifo_36[1]; /* 0x00009490 */ + u32 tx_desc_ack_fifo_37[1]; /* 0x00009494 */ + u32 tx_desc_ack_fifo_38[1]; /* 0x00009498 */ + u32 tx_desc_ack_fifo_39[1]; /* 0x0000949c */ + u32 tx_desc_ack_fifo_40[1]; /* 0x000094a0 */ + u32 tx_desc_ack_fifo_41[1]; /* 0x000094a4 */ + u32 tx_desc_ack_fifo_42[1]; /* 0x000094a8 */ + u32 tx_desc_ack_fifo_43[1]; /* 0x000094ac */ + u32 tx_desc_ack_fifo_44[1]; /* 0x000094b0 */ + u32 tx_desc_ack_fifo_45[1]; /* 0x000094b4 */ + u32 tx_desc_ack_fifo_46[1]; /* 0x000094b8 */ + u32 tx_desc_ack_fifo_47[1]; /* 0x000094bc */ + u32 tx_desc_ack_fifo_48[1]; /* 0x000094c0 */ + u32 tx_desc_ack_fifo_49[1]; /* 0x000094c4 */ + u32 tx_desc_ack_fifo_50[1]; /* 0x000094c8 */ + u32 tx_desc_ack_fifo_51[1]; /* 0x000094cc */ + u32 tx_desc_ack_fifo_52[1]; /* 0x000094d0 */ + u32 tx_desc_ack_fifo_53[1]; /* 0x000094d4 */ + u32 tx_desc_ack_fifo_54[1]; /* 0x000094d8 */ + u32 tx_desc_ack_fifo_55[1]; /* 0x000094dc */ + u32 tx_desc_ack_fifo_56[1]; /* 0x000094e0 */ + u32 tx_desc_ack_fifo_57[1]; /* 0x000094e4 */ + u32 tx_desc_ack_fifo_58[1]; /* 0x000094e8 */ + u32 tx_desc_ack_fifo_59[1]; /* 0x000094ec */ + u32 tx_desc_ack_fifo_60[1]; /* 0x000094f0 */ + u32 tx_desc_ack_fifo_61[1]; /* 0x000094f4 */ + u32 tx_desc_ack_fifo_62[1]; /* 0x000094f8 */ + u32 tx_desc_ack_fifo_63[1]; /* 0x000094fc */ + u32 cpu_mac_desc_intf_0[2]; /* 0x00009500 */ + u32 cpu_mac_desc_intf_1[2]; /* 0x00009508 */ + u32 cpu_mac_desc_intf_2[2]; /* 0x00009510 */ +}; + +/* tx_pkt_fifo Definition */ +#define TX_PKT_FIFO_W0_TX_PKT_FIFO_FIELD0 BIT(0) +#define TX_PKT_FIFO_W1_TX_PKT_FIFO_FIELD1 BIT(0) +#define TX_PKT_FIFO_W2_TX_PKT_FIFO_FIELD2 BIT(0) + +#define TX_PKT_FIFO_W0_TX_PKT_FIFO_FIELD0_MASK 0xffffffff +#define TX_PKT_FIFO_W1_TX_PKT_FIFO_FIELD1_MASK 0xffffffff +#define TX_PKT_FIFO_W2_TX_PKT_FIFO_FIELD2_MASK 0x0000000f + +/* rx_pkt_msg_fifo Definition */ +#define RX_PKT_MSG_FIFO_W0_RX_PKT_MSG_FIFO_FIELD BIT(0) + +#define RX_PKT_MSG_FIFO_W0_RX_PKT_MSG_FIFO_FIELD_MASK 0x0000ffff + +/* cpu_mac_stats_ram Definition */ +#define CPU_MAC_STATS_RAM_W0_BYTE_CNT_31_0 BIT(0) +#define CPU_MAC_STATS_RAM_W1_BYTE_CNT_39_32 BIT(0) +#define CPU_MAC_STATS_RAM_W2_FRAME_CNT_31_0 BIT(0) +#define CPU_MAC_STATS_RAM_W3_FRAME_CNT_33_32 BIT(0) + +#define CPU_MAC_STATS_RAM_W0_BYTE_CNT_31_0_MASK 0xffffffff +#define CPU_MAC_STATS_RAM_W1_BYTE_CNT_39_32_MASK 0x000000ff +#define CPU_MAC_STATS_RAM_W2_FRAME_CNT_31_0_MASK 0xffffffff +#define CPU_MAC_STATS_RAM_W3_FRAME_CNT_33_32_MASK 0x00000003 + +/* tx_desc_cfg_fifo Definition */ +#define TX_DESC_CFG_FIFO_W0_TX_DESC_CFG_FIFO_FIELD0 BIT(0) +#define TX_DESC_CFG_FIFO_W1_TX_DESC_CFG_FIFO_FIELD1 BIT(0) + +#define TX_DESC_CFG_FIFO_W0_TX_DESC_CFG_FIFO_FIELD0_MASK 0xffffffff +#define TX_DESC_CFG_FIFO_W1_TX_DESC_CFG_FIFO_FIELD1_MASK 0x01ffffff + +/* rx_desc_0_cfg_fifo Definition */ +#define RX_DESC0_CFG_FIFO_W0_RX_DESC0_CFG_FIFO_FIELD0 BIT(0) +#define RX_DESC0_CFG_FIFO_W1_RX_DESC0_CFG_FIFO_FIELD1 BIT(0) + +#define RX_DESC0_CFG_FIFO_W0_RX_DESC0_CFG_FIFO_FIELD0_MASK 0xffffffff +#define RX_DESC0_CFG_FIFO_W1_RX_DESC0_CFG_FIFO_FIELD1_MASK 0x01ffffff + +/* rx_desc_1_cfg_fifo Definition */ +#define RX_DESC1_CFG_FIFO_W0_RX_DESC1_CFG_FIFO_FIELD0 BIT(0) +#define RX_DESC1_CFG_FIFO_W1_RX_DESC1_CFG_FIFO_FIELD1 BIT(0) + +#define RX_DESC1_CFG_FIFO_W0_RX_DESC1_CFG_FIFO_FIELD0_MASK 0xffffffff +#define RX_DESC1_CFG_FIFO_W1_RX_DESC1_CFG_FIFO_FIELD1_MASK 0x01ffffff + +/* rx_desc_0_ack_fifo Definition */ +#define RX_DESC0_ACK_FIFO_W0_RX_DESC0_ACK_FIFO_FIELD BIT(0) + +#define RX_DESC0_ACK_FIFO_W0_RX_DESC0_ACK_FIFO_FIELD_MASK 0x0007ffff + +/* rx_desc_1_ack_fifo Definition */ +#define RX_DESC1_ACK_FIFO_W0_RX_DESC1_ACK_FIFO_FIELD BIT(0) + +#define RX_DESC1_ACK_FIFO_W0_RX_DESC1_ACK_FIFO_FIELD_MASK 0x0007ffff + +/* tx_desc_ack_fifo Definition */ +#define TX_DESC_ACK_FIFO_W0_TX_DESC_ACK_FIFO_FIELD BIT(0) + +#define TX_DESC_ACK_FIFO_W0_TX_DESC_ACK_FIFO_FIELD_MASK 0x00000001 + +/* cpu_mac_desc_intf Definition */ +#define CPU_MAC_DESC_INTF_W0_DESC_ADDR_31_0 BIT(0) +#define CPU_MAC_DESC_INTF_W1_DESC_ADDR_39_32 BIT(0) +#define CPU_MAC_DESC_INTF_W1_DESC_SIZE BIT(8) +#define CPU_MAC_DESC_INTF_W1_DESC_SOP BIT(22) +#define CPU_MAC_DESC_INTF_W1_DESC_ERR_TYPE BIT(25) +#define CPU_MAC_DESC_INTF_W1_DESC_EOP BIT(23) +#define CPU_MAC_DESC_INTF_W1_DESC_ERR BIT(24) + +#define CPU_MAC_DESC_INTF_W0_DESC_ADDR_31_0_MASK 0xffffffff +#define CPU_MAC_DESC_INTF_W1_DESC_ADDR_39_32_MASK 0x000000ff +#define CPU_MAC_DESC_INTF_W1_DESC_SIZE_MASK 0x003fff00 +#define CPU_MAC_DESC_INTF_W1_DESC_SOP_MASK 0x00400000 +#define CPU_MAC_DESC_INTF_W1_DESC_ERR_TYPE_MASK 0x0e000000 +#define CPU_MAC_DESC_INTF_W1_DESC_EOP_MASK 0x00800000 +#define CPU_MAC_DESC_INTF_W1_DESC_ERR_MASK 0x01000000 + +/* defing MDIOSOC_REG_BASE 0x00000000 */ + +struct mdio_soc_regs { + u32 mdio_soc_cmd_0[2]; /* 0x00000000 */ + u32 mdio_soc_cmd_1[2]; /* 0x00000008 */ + u32 mdio_soc_status_1; /* 0x00000010 */ + u32 mdio_soc_status_0; /* 0x00000014 */ + u32 mdio_soc_reserved; /* 0x00000018 */ + u32 mdio_soc_cfg_0; /* 0x0000001c */ + u32 mdio_soc_cfg_1; /* 0x00000020 */ +}; + +/* mdio_soc_cmd_0 Definition */ +#define MDIO_SOC_CMD0_W0_OP_CODE_CMD_LANE0 BIT(26) +#define MDIO_SOC_CMD0_W0_REG_ADD_CMD_LANE0 BIT(16) +#define MDIO_SOC_CMD0_W0_DATA_CMD_LANE0 BIT(0) +#define MDIO_SOC_CMD0_W0_PHY_ADD_CMD_LANE0 BIT(21) +#define MDIO_SOC_CMD0_W1_START_CMD_LANE0 BIT(0) + +#define MDIO_SOC_CMD0_W0_OP_CODE_CMD_LANE0_MASK 0x0c000000 +#define MDIO_SOC_CMD0_W0_REG_ADD_CMD_LANE0_MASK 0x001f0000 +#define MDIO_SOC_CMD0_W0_DATA_CMD_LANE0_MASK 0x0000ffff +#define MDIO_SOC_CMD0_W0_PHY_ADD_CMD_LANE0_MASK 0x03e00000 +#define MDIO_SOC_CMD0_W1_START_CMD_LANE0_MASK 0x00000003 + +/* mdio_soc_cmd_1 Definition */ +#define MDIO_SOC_CMD1_W0_PHY_ADD_CMD_LANE1 BIT(21) +#define MDIO_SOC_CMD1_W0_OP_CODE_CMD_LANE1 BIT(26) +#define MDIO_SOC_CMD1_W0_DATA_CMD_LANE1 BIT(0) +#define MDIO_SOC_CMD1_W0_REG_ADD_CMD_LANE1 BIT(16) +#define MDIO_SOC_CMD1_W1_START_CMD_LANE1 BIT(0) + +#define MDIO_SOC_CMD1_W0_PHY_ADD_CMD_LANE1_MASK 0x03e00000 +#define MDIO_SOC_CMD1_W0_OP_CODE_CMD_LANE1_MASK 0x0c000000 +#define MDIO_SOC_CMD1_W0_DATA_CMD_LANE1_MASK 0x0000ffff +#define MDIO_SOC_CMD1_W0_REG_ADD_CMD_LANE1_MASK 0x001f0000 +#define MDIO_SOC_CMD1_W1_START_CMD_LANE1_MASK 0x00000003 + +/* mdio_soc_status_1 Definition */ +#define MDIO_SOC_STATUS1_W0_MDIO_CMD_DONE_LANE1 BIT(16) +#define MDIO_SOC_STATUS1_W0_MDIO_READ_DATA_LANE1 BIT(0) + +#define MDIO_SOC_STATUS1_W0_MDIO_CMD_DONE_LANE1_MASK 0x00010000 +#define MDIO_SOC_STATUS1_W0_MDIO_READ_DATA_LANE1_MASK 0x0000ffff + +/* mdio_soc_status_0 Definition */ +#define MDIO_SOC_STATUS0_W0_MDIO_CMD_DONE_LANE0 BIT(16) +#define MDIO_SOC_STATUS0_W0_MDIO_READ_DATA_LANE0 BIT(0) + +#define MDIO_SOC_STATUS0_W0_MDIO_CMD_DONE_LANE0_MASK 0x00010000 +#define MDIO_SOC_STATUS0_W0_MDIO_READ_DATA_LANE0_MASK 0x0000ffff + +/* mdio_soc_reserved Definition */ +#define MDIO_SOC_RESERVED_W0_RESERVED BIT(0) + +#define MDIO_SOC_RESERVED_W0_RESERVED_MASK 0x0000ffff + +/* mdio_soc_cfg_0 Definition */ +#define MDIO_SOC_CFG0_W0_MDIO_MAC_PRE_LANE0 BIT(0) +#define MDIO_SOC_CFG0_W0_MDIO_IN_DLY_LANE0 BIT(8) + +#define MDIO_SOC_CFG0_W0_MDIO_MAC_PRE_LANE0_MASK 0x0000003f +#define MDIO_SOC_CFG0_W0_MDIO_IN_DLY_LANE0_MASK 0x00000f00 + +/* mdio_soc_cfg_1 Definition */ +#define MDIO_SOC_CFG1_W0_MDIO_IN_DLY_LANE1 BIT(8) +#define MDIO_SOC_CFG1_W0_MDIO_MAC_PRE_LANE1 BIT(0) + +#define MDIO_SOC_CFG1_W0_MDIO_IN_DLY_LANE1_MASK 0x00000f00 +#define MDIO_SOC_CFG1_W0_MDIO_MAC_PRE_LANE1_MASK 0x0000003f + +#define CPUMACUNIT_MEM_BASE 0x00000400 +#define CPUMACUNIT_REG_BASE 0x00000040 + +struct cpu_mac_unit_regs { + u32 cpu_mac_unit_hss_mon[7]; /* 0x00000040 */ + u32 rsv23; + u32 cpu_mac_hss_reg_acc_timing_cfg[2]; /* 0x00000060 */ + u32 cpu_mac_unit_reset_ctl; /* 0x00000068 */ + u32 cpu_mac_unit_hss_reg_acc_ctl; /* 0x0000006c */ + u32 cpu_mac_unit_hss_reg_acc_result; /* 0x00000070 */ + u32 cpu_mac_unit_axi_cfg; /* 0x00000074 */ + u32 cpu_mac_unit_ts_cfg; /* 0x00000078 */ + u32 cpu_mac_unit_fifo_status; /* 0x0000007c */ + u32 cpu_mac_unit_ts_mon[3]; /* 0x00000080 */ + u32 rsv35; + u32 cpu_mac_unit_ref_pulse_cfg[4]; /* 0x00000090 */ + u32 cpu_mac_unit_interrupt_func[4]; /* 0x000000a0 */ + u32 rsv44; + u32 rsv45; + u32 rsv46; + u32 rsv47; + u32 cpu_mac_unit_hss_cfg[12]; /* 0x000000c0 */ + u32 rsv60; + u32 rsv61; + u32 rsv62; + u32 rsv63; + u32 cpu_mac_unit_ip_cam_cfg[32]; /* 0x00000100 */ + u32 cpu_mac_unit_mac_cam_cfg[32]; /* 0x00000180 */ + u32 cpu_mac_unit_filter_cfg[6]; /* 0x00000200 */ +}; + +/* cpu_mac_unit_hss_mon Definition */ +#define CPU_MAC_UNIT_HSS_MON_W0_MON_HSS_CMU0_DBG_OBS BIT(0) +#define CPU_MAC_UNIT_HSS_MON_W0_MON_HSS_CMU0_LOL BIT(16) +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_PMA2_PCS_TX_DET_RX_N BIT(22) +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_PMA2_PCS_TX_DET_RX_P BIT(23) +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_LOL_UDL BIT(20) +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_RX_EI BIT(18) +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_DBG_OBS BIT(0) +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_PMA_RST_DONE BIT(17) +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_I_SCAN_DONE BIT(21) +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_RX_EI_FILTERED BIT(24) +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_LOL BIT(19) +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_DFE_RST_DONE BIT(16) +#define CPU_MAC_UNIT_HSS_MON_W2_MON_HSS_L0_I_SCAN_RESULTS_31_0 BIT(0) +#define CPU_MAC_UNIT_HSS_MON_W3_MON_HSS_L0_I_SCAN_RESULTS_63_32 BIT(0) +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_PMA2_PCS_TX_DET_RX_P BIT(23) +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_RX_EI_FILTERED BIT(24) +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_I_SCAN_DONE BIT(21) +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_PMA2_PCS_TX_DET_RX_N BIT(22) +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_LOL BIT(19) +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_DFE_RST_DONE BIT(16) +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_LOL_UDL BIT(20) +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_PMA_RST_DONE BIT(17) +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_RX_EI BIT(18) +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_DBG_OBS BIT(0) +#define CPU_MAC_UNIT_HSS_MON_W5_MON_HSS_L1_I_SCAN_RESULTS_31_0 BIT(0) +#define CPU_MAC_UNIT_HSS_MON_W6_MON_HSS_L1_I_SCAN_RESULTS_63_32 BIT(0) + +#define CPU_MAC_UNIT_HSS_MON_W0_MON_HSS_CMU0_DBG_OBS_MASK 0x0000ffff +#define CPU_MAC_UNIT_HSS_MON_W0_MON_HSS_CMU0_LOL_MASK 0x00010000 +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_PMA2_PCS_TX_DET_RX_N_MASK 0x00400000 +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_PMA2_PCS_TX_DET_RX_P_MASK 0x00800000 +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_LOL_UDL_MASK 0x00100000 +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_RX_EI_MASK 0x00040000 +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_DBG_OBS_MASK 0x0000ffff +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_PMA_RST_DONE_MASK 0x00020000 +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_I_SCAN_DONE_MASK 0x00200000 +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_RX_EI_FILTERED_MASK 0x01000000 +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_LOL_MASK 0x00080000 +#define CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_DFE_RST_DONE_MASK 0x00010000 +#define CPU_MAC_UNIT_HSS_MON_W2_MON_HSS_L0_I_SCAN_RESULTS_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_HSS_MON_W3_MON_HSS_L0_I_SCAN_RESULTS_63_32_MASK 0x00000001 +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_PMA2_PCS_TX_DET_RX_P_MASK 0x00800000 +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_RX_EI_FILTERED_MASK 0x01000000 +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_I_SCAN_DONE_MASK 0x00200000 +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_PMA2_PCS_TX_DET_RX_N_MASK 0x00400000 +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_LOL_MASK 0x00080000 +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_DFE_RST_DONE_MASK 0x00010000 +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_LOL_UDL_MASK 0x00100000 +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_PMA_RST_DONE_MASK 0x00020000 +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_RX_EI_MASK 0x00040000 +#define CPU_MAC_UNIT_HSS_MON_W4_MON_HSS_L1_DBG_OBS_MASK 0x0000ffff +#define CPU_MAC_UNIT_HSS_MON_W5_MON_HSS_L1_I_SCAN_RESULTS_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_HSS_MON_W6_MON_HSS_L1_I_SCAN_RESULTS_63_32_MASK 0x00000001 + +/* cpu_mac_hss_reg_acc_timing_cfg Definition */ +#define CPU_MAC_HSS_REG_ACC_TIMING_CFG_W0_CFG_ACTIVE_CYCLES BIT(0) +#define CPU_MAC_HSS_REG_ACC_TIMING_CFG_W0_CFG_HOLD_CYCLES BIT(8) +#define CPU_MAC_HSS_REG_ACC_TIMING_CFG_W1_CFG_RD_OUT_VALID_CYCLES BIT(8) +#define CPU_MAC_HSS_REG_ACC_TIMING_CFG_W1_CFG_SETUP_CYCLES BIT(0) + +#define CPU_MAC_HSS_REG_ACC_TIMING_CFG_W0_CFG_ACTIVE_CYCLES_MASK 0x000000ff +#define CPU_MAC_HSS_REG_ACC_TIMING_CFG_W0_CFG_HOLD_CYCLES_MASK 0x0000ff00 +#define CPU_MAC_HSS_REG_ACC_TIMING_CFG_W1_CFG_RD_OUT_VALID_CYCLES_MASK 0x0000ff00 +#define CPU_MAC_HSS_REG_ACC_TIMING_CFG_W1_CFG_SETUP_CYCLES_MASK 0x000000ff + +/* cpu_mac_unit_reset_ctl Definition */ +#define CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC1 BIT(1) +#define CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC0 BIT(2) +#define CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_BASE BIT(0) + +#define CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC1_MASK 0x00000002 +#define CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC0_MASK 0x00000004 +#define CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_BASE_MASK 0x00000001 + +/* cpu_mac_unit_hss_reg_acc_ctl Definition */ +#define CPU_MAC_UNIT_HSS_REG_ACC_CTL_W0_HSS_ACC_WDATA BIT(8) +#define CPU_MAC_UNIT_HSS_REG_ACC_CTL_W0_HSS_ACC_VALID BIT(31) +#define CPU_MAC_UNIT_HSS_REG_ACC_CTL_W0_HSS_ACC_ADDR BIT(0) +#define CPU_MAC_UNIT_HSS_REG_ACC_CTL_W0_HSS_ACC_IS_READ BIT(16) +#define CPU_MAC_UNIT_HSS_REG_ACC_CTL_W0_HSS_ACC_ID BIT(24) + +#define CPU_MAC_UNIT_HSS_REG_ACC_CTL_W0_HSS_ACC_WDATA_MASK 0x0000ff00 +#define CPU_MAC_UNIT_HSS_REG_ACC_CTL_W0_HSS_ACC_VALID_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_REG_ACC_CTL_W0_HSS_ACC_ADDR_MASK 0x000000ff +#define CPU_MAC_UNIT_HSS_REG_ACC_CTL_W0_HSS_ACC_IS_READ_MASK 0x00010000 +#define CPU_MAC_UNIT_HSS_REG_ACC_CTL_W0_HSS_ACC_ID_MASK 0x0f000000 + +/* cpu_mac_unit_hss_reg_acc_result Definition */ +#define CPU_MAC_UNIT_HSS_REG_ACC_RESULT_W0_HSS_ACC_ACK BIT(31) +#define CPU_MAC_UNIT_HSS_REG_ACC_RESULT_W0_HSS_ACC_ACK_DATA BIT(0) + +#define CPU_MAC_UNIT_HSS_REG_ACC_RESULT_W0_HSS_ACC_ACK_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_REG_ACC_RESULT_W0_HSS_ACC_ACK_DATA_MASK 0x000000ff + +/* cpu_mac_unit_axi_cfg Definition */ +#define CPU_MAC_UNIT_AXI_CFG_W0_CFG_AXI0_ID BIT(0) +#define CPU_MAC_UNIT_AXI_CFG_W0_CFG_AXI1_ID BIT(4) + +#define CPU_MAC_UNIT_AXI_CFG_W0_CFG_AXI0_ID_MASK 0x0000000f +#define CPU_MAC_UNIT_AXI_CFG_W0_CFG_AXI1_ID_MASK 0x000000f0 + +/* cpu_mac_unit_ts_cfg Definition */ +#define CPU_MAC_UNIT_TS_CFG_W0_CFG_TX_CAPTURE_FIFO_INTR_THRD BIT(0) +#define CPU_MAC_UNIT_TS_CFG_W0_CFG_FORCE_S_AND_NS_EN BIT(31) + +#define CPU_MAC_UNIT_TS_CFG_W0_CFG_TX_CAPTURE_FIFO_INTR_THRD_MASK 0x0000000f +#define CPU_MAC_UNIT_TS_CFG_W0_CFG_FORCE_S_AND_NS_EN_MASK 0x80000000 + +/* cpu_mac_unit_fifo_status Definition */ +#define CPU_MAC_UNIT_FIFO_STATUS_W0_CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_FIFO_DEPTH BIT(0) + +#define CPU_MAC_UNIT_FIFO_STATUS_W0_CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_FIFO_DEPTH_MASK 0x0000000f + +/* cpu_mac_unit_ts_mon Definition */ +#define CPU_MAC_UNIT_TS_MON_W0_MON_ADJ_NS BIT(0) +#define CPU_MAC_UNIT_TS_MON_W1_MON_ADJ_SECOND BIT(0) +#define CPU_MAC_UNIT_TS_MON_W2_MON_TX_CAPTURE_FIFO_DROP_CNT BIT(0) + +#define CPU_MAC_UNIT_TS_MON_W0_MON_ADJ_NS_MASK 0x3fffffff +#define CPU_MAC_UNIT_TS_MON_W1_MON_ADJ_SECOND_MASK 0xffffffff +#define CPU_MAC_UNIT_TS_MON_W2_MON_TX_CAPTURE_FIFO_DROP_CNT_MASK 0x0000000f + +/* cpu_mac_unit_ref_pulse_cfg Definition */ +#define CPU_MAC_UNIT_REF_PULSE_CFG_W0_REF_PAUSE_TIMER_PULSE_DIV BIT(0) +#define CPU_MAC_UNIT_REF_PULSE_CFG_W0_REF_PAUSE_TIMER_PULSE_RST BIT(31) +#define CPU_MAC_UNIT_REF_PULSE_CFG_W1_REF_LINK_PULSE_DIV BIT(0) +#define CPU_MAC_UNIT_REF_PULSE_CFG_W1_REF_LINK_PULSE_RST BIT(31) +#define CPU_MAC_UNIT_REF_PULSE_CFG_W2_REF_LINK_FILTER_PULSE_RST BIT(31) +#define CPU_MAC_UNIT_REF_PULSE_CFG_W2_REF_LINK_FILTER_PULSE_DIV BIT(0) +#define CPU_MAC_UNIT_REF_PULSE_CFG_W3_REF_EEE_PULSE_DIV BIT(0) +#define CPU_MAC_UNIT_REF_PULSE_CFG_W3_REF_EEE_PULSE_RST BIT(31) + +#define CPU_MAC_UNIT_REF_PULSE_CFG_W0_REF_PAUSE_TIMER_PULSE_DIV_MASK 0x7fffffff +#define CPU_MAC_UNIT_REF_PULSE_CFG_W0_REF_PAUSE_TIMER_PULSE_RST_MASK 0x80000000 +#define CPU_MAC_UNIT_REF_PULSE_CFG_W1_REF_LINK_PULSE_DIV_MASK 0x7fffffff +#define CPU_MAC_UNIT_REF_PULSE_CFG_W1_REF_LINK_PULSE_RST_MASK 0x80000000 +#define CPU_MAC_UNIT_REF_PULSE_CFG_W2_REF_LINK_FILTER_PULSE_RST_MASK 0x80000000 +#define CPU_MAC_UNIT_REF_PULSE_CFG_W2_REF_LINK_FILTER_PULSE_DIV_MASK 0x7fffffff +#define CPU_MAC_UNIT_REF_PULSE_CFG_W3_REF_EEE_PULSE_DIV_MASK 0x7fffffff +#define CPU_MAC_UNIT_REF_PULSE_CFG_W3_REF_EEE_PULSE_RST_MASK 0x80000000 + +/* cpu_mac_unit_interrupt_func Definition */ +#define CPU_MAC_UNIT_INTERRUPT_FUNC_W0_VALUE_SET0_CPU_MAC_UNIT_INTERRUPT_FUNC BIT(0) +#define CPU_MAC_UNIT_INTERRUPT_FUNC_W1_VALUE_RESET0_CPU_MAC_UNIT_INTERRUPT_FUNC BIT(0) +#define CPU_MAC_UNIT_INTERRUPT_FUNC_W2_MASK_SET0_CPU_MAC_UNIT_INTERRUPT_FUNC BIT(0) +#define CPU_MAC_UNIT_INTERRUPT_FUNC_W3_MASK_RESET0_CPU_MAC_UNIT_INTERRUPT_FUNC BIT(0) + +#define CPU_MAC_UNIT_INTERRUPT_FUNC_W0_VALUE_SET0_CPU_MAC_UNIT_INTERRUPT_FUNC_MASK 0x00000001 +#define CPU_MAC_UNIT_INTERRUPT_FUNC_W1_VALUE_RESET0_CPU_MAC_UNIT_INTERRUPT_FUNC_MASK 0x00000001 +#define CPU_MAC_UNIT_INTERRUPT_FUNC_W2_MASK_SET0_CPU_MAC_UNIT_INTERRUPT_FUNC_MASK 0x00000001 +#define CPU_MAC_UNIT_INTERRUPT_FUNC_W3_MASK_RESET0_CPU_MAC_UNIT_INTERRUPT_FUNC_MASK 0x00000001 + +/* cpu_mac_unit_hss_cfg Definition */ +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_BCLK_RST_N_BIT 1 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_BIAS_DN_EN_BIT 13 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_BIAS_UP_EN_BIT 14 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_CFG_DIV_SEL_BIT 5 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_CK_TREE_PD_BIT 29 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_EN_TX_CK_DN_BIT 24 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_EN_TX_CK_UP_BIT 23 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_IBIAS_PD_BIT 26 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_LINK_BUF_EN_BIT 16 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_MULTI_LANE_MODE_BIT 12 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_PMA_TX_CK_PD_BIT 31 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_REFCK_PD_BIT 30 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_REFCK_TERM_EN_BIT 25 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_RST_TREE_PD_MA_BIT 27 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_VCO_DIV_SEL_BIT 2 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_VCO_PD_BIT 28 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_PCLK_GATING_BIT 15 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_PCS2_PMA_PHY_MODE_BIT 18 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_REXT10_K_BIT 11 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_RST_N_BIT 17 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_GLB_RST_N_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_CTRL_LOGIC_PD_BIT 28 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_EN_DUMMY_BIT 29 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_PD_DIV64_BIT 26 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_PD_DIV66_BIT 27 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_CENTER_SPREAD_BIT 25 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_MCNT_MAX_VAL_BIT 9 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_NCN_MAX_VAL_BIT 14 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_RES_EN_BIT 2 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_SRC_SEL_BIT 3 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_SSC_PI_BW_BIT 6 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_SSC_PI_STEP_BIT 4 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_SSC_RESET_N_BIT 1 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_SSC_RTL_CLK_SEL_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_AUX_RX_CK_SEL_BIT 2 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_AUX_TX_CK_SEL_BIT 1 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_DATA_WIDTH_SEL_BIT 7 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_HWT_MULTI_LANE_MODE_BIT 3 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_LANE_ID_BIT 4 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_PCS2_PMA_PHY_MODE_BIT 22 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_PCS2_PMA_TX_SWING_BIT 31 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_PCS2_PMA_VGA_CTRL_BIT 27 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_PMA_RX_DIV_SEL_BIT 19 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_PMA_TX_CK_SEL_BIT 13 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_RST_N_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_RX_RATE_SEL_BIT 17 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_RX_RST_N_BIT 16 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_TX_RATE_SEL_BIT 11 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_TX_RST_N_BIT 10 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_HWT_FOM_SEL_BIT 19 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS2_PMA_PI_EXT_DAC_BIT20_TO14_BIT 20 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS2_PMA_PI_EXT_DAC_BIT23_TO21_BIT 27 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS2_PMA_TX_EI_BIT 18 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_EN_ADV_BIT 9 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_EN_DLY_BIT 8 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_EN_MAIN_BIT 7 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_I_SCAN_EN_BIT 6 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_TAP_ADV_BIT 1 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_TAP_DLY_BIT 10 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_TAP_MAIN_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_ITX_PREEMP_BASE_BIT 30 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_MCNT_MAX_VAL_BIT 25 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_PI_FLOOP_STEPS_BIT 23 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_RX_SSC_LH_BIT 22 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_SSC_EN_BIT 21 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_SSC_PI_BW_BIT 17 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_SSC_PI_STEP_BIT 15 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_SSC_RESETB_BIT 14 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_SSC_RTL_CLK_SEL_BIT 13 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_TX_DET_RX_EN_BIT 12 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_TX_DET_RX_STR_BIT 11 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMANCNT_MAX_VAL_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W5_CFG_HSS_L0_PCS2_PMA_EN_PRE_EMPH_BIT 31 +#define CPU_MAC_UNIT_HSS_CFG_W5_CFG_HSS_L0_PCS2_PMA_EQC_FORCE_BIT 27 +#define CPU_MAC_UNIT_HSS_CFG_W5_CFG_HSS_L0_PCS2_PMA_EQR_BYP_BIT 26 +#define CPU_MAC_UNIT_HSS_CFG_W5_CFG_HSS_L0_PCS2_PMA_ISCAN_EXT_DAC_BIT7_BIT 25 +#define CPU_MAC_UNIT_HSS_CFG_W5_CFG_HSS_L0_PCS2_PMA_POWER_CTRL_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_FORCE_SIGNAL_DETECT_BIT 31 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCLK_GATING_BIT 7 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_CENTER_SPREADING_BIT 6 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_CTLE_RSTN_BIT 17 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_DIS2ND_ORDER_BIT 5 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_EID_LP_BIT 18 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_EN_DFE_DIG_BIT 4 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_EQ_RES_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_HOLD_DFE_BIT 22 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_ISCAN_SEL_BIT 19 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_PI_HOLD_BIT 20 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_R50_EN_BIT 21 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_TX_MARGIN_BIT 8 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_DLEV_BIT 23 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_DLEV_BYP_BIT 31 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H1_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H2_BIT 6 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H3_BIT 11 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H4_BIT 15 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H5_BIT 19 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H_BYP_BIT 30 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_AUX_RX_CK_SEL_BIT 2 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_AUX_TX_CK_SEL_BIT 1 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_DATA_WIDTH_SEL_BIT 7 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_HWT_MULTI_LANE_MODE_BIT 3 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_LANE_ID_BIT 4 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_PCS2_PMA_PHY_MODE_BIT 22 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_PCS2_PMA_TX_SWING_BIT 31 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_PCS2_PMA_VGA_CTRL_BIT 27 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_PMA_RX_DIV_SEL_BIT 19 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_PMA_TX_CK_SEL_BIT 13 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_RST_N_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_RX_RATE_SEL_BIT 17 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_RX_RST_N_BIT 16 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_TX_RATE_SEL_BIT 11 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_TX_RST_N_BIT 10 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_HWT_FOM_SEL_BIT 19 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS2_PMA_PI_EXT_DAC_BIT20_TO14_BIT 20 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS2_PMA_PI_EXT_DAC_BIT23_TO21_BIT 27 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS2_PMA_TX_EI_BIT 18 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_EN_ADV_BIT 9 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_EN_DLY_BIT 8 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_EN_MAIN_BIT 7 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_I_SCAN_EN_BIT 6 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_TAP_ADV_BIT 1 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_TAP_DLY_BIT 10 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_TAP_MAIN_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_ITX_PREEMP_BASE_BIT 30 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_MCNT_MAX_VAL_BIT 25 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_PI_FLOOP_STEPS_BIT 23 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_RX_SSC_LH_BIT 22 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_SSC_EN_BIT 21 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_SSC_PI_BW_BIT 17 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_SSC_PI_STEP_BIT 15 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_SSC_RESETB_BIT 14 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_SSC_RTL_CLK_SEL_BIT 13 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_TX_DET_RX_EN_BIT 12 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_TX_DET_RX_STR_BIT 11 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMANCNT_MAX_VAL_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W11_CFG_HSS_L1_PCS2_PMA_EN_PRE_EMPH_BIT 31 +#define CPU_MAC_UNIT_HSS_CFG_W11_CFG_HSS_L1_PCS2_PMA_EQC_FORCE_BIT 27 +#define CPU_MAC_UNIT_HSS_CFG_W11_CFG_HSS_L1_PCS2_PMA_EQR_BYP_BIT 26 +#define CPU_MAC_UNIT_HSS_CFG_W11_CFG_HSS_L1_PCS2_PMA_ISCAN_EXT_DAC_BIT7_BIT 25 +#define CPU_MAC_UNIT_HSS_CFG_W11_CFG_HSS_L1_PCS2_PMA_POWER_CTRL_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_FORCE_SIGNAL_DETECT_BIT 31 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCLK_GATING_BIT 7 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_CENTER_SPREADING_BIT 6 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_CTLE_RSTN_BIT 17 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_DIS2ND_ORDER_BIT 5 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_EID_LP_BIT 18 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_EN_DFE_DIG_BIT 4 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_EQ_RES_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_HOLD_DFE_BIT 22 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_ISCAN_SEL_BIT 19 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_PI_HOLD_BIT 20 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_R50_EN_BIT 21 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_TX_MARGIN_BIT 8 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_DLEV_BIT 23 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_DLEV_BYP_BIT 31 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H1_BIT 0 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H2_BIT 6 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H3_BIT 11 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H4_BIT 15 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H5_BIT 19 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H_BYP_BIT 30 + +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_BCLK_RST_N_MASK 0x00000002 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_BIAS_DN_EN_MASK 0x00002000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_BIAS_UP_EN_MASK 0x00004000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_CFG_DIV_SEL_MASK 0x000007e0 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_CK_TREE_PD_MASK 0x20000000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_EN_TX_CK_DN_MASK 0x01000000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_EN_TX_CK_UP_MASK 0x00800000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_IBIAS_PD_MASK 0x04000000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_LINK_BUF_EN_MASK 0x00010000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_MULTI_LANE_MODE_MASK 0x00001000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_PMA_TX_CK_PD_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_REFCK_PD_MASK 0x40000000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_REFCK_TERM_EN_MASK 0x02000000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_RST_TREE_PD_MA_MASK 0x08000000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_VCO_DIV_SEL_MASK 0x0000001c +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_HWT_VCO_PD_MASK 0x10000000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_PCLK_GATING_MASK 0x00008000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_PCS2_PMA_PHY_MODE_MASK 0x007c0000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_REXT10_K_MASK 0x00000800 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_CMU0_RST_N_MASK 0x00020000 +#define CPU_MAC_UNIT_HSS_CFG_W0_CFG_HSS_GLB_RST_N_MASK 0x00000001 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_CTRL_LOGIC_PD_MASK 0x10000000 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_EN_DUMMY_MASK 0x20000000 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_PD_DIV64_MASK 0x04000000 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_PD_DIV66_MASK 0x08000000 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_CENTER_SPREAD_MASK 0x02000000 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_MCNT_MAX_VAL_MASK 0x00003e00 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_NCN_MAX_VAL_MASK 0x01ffc000 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_RES_EN_MASK 0x00000004 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_SRC_SEL_MASK 0x00000008 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_SSC_PI_BW_MASK 0x000001c0 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_SSC_PI_STEP_MASK 0x00000030 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_SSC_RESET_N_MASK 0x00000002 +#define CPU_MAC_UNIT_HSS_CFG_W1_CFG_HSS_CMU0_HWT_REF_CK_SSC_RTL_CLK_SEL_MASK 0x00000001 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_AUX_RX_CK_SEL_MASK 0x00000004 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_AUX_TX_CK_SEL_MASK 0x00000002 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_DATA_WIDTH_SEL_MASK 0x00000380 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_HWT_MULTI_LANE_MODE_MASK 0x00000008 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_LANE_ID_MASK 0x00000070 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_PCS2_PMA_PHY_MODE_MASK 0x07c00000 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_PCS2_PMA_TX_SWING_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_PCS2_PMA_VGA_CTRL_MASK 0x78000000 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_PMA_RX_DIV_SEL_MASK 0x00380000 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_PMA_TX_CK_SEL_MASK 0x0000e000 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_RST_N_MASK 0x00000001 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_RX_RATE_SEL_MASK 0x00060000 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_RX_RST_N_MASK 0x00010000 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_TX_RATE_SEL_MASK 0x00001800 +#define CPU_MAC_UNIT_HSS_CFG_W2_CFG_HSS_L0_TX_RST_N_MASK 0x00000400 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_HWT_FOM_SEL_MASK 0x00080000 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS2_PMA_PI_EXT_DAC_BIT20_TO14_MASK 0x07f00000 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS2_PMA_PI_EXT_DAC_BIT23_TO21_MASK 0x38000000 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS2_PMA_TX_EI_MASK 0x00040000 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_EN_ADV_MASK 0x00000200 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_EN_DLY_MASK 0x00000100 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_EN_MAIN_MASK 0x00000080 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_I_SCAN_EN_MASK 0x00000040 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_TAP_ADV_MASK 0x0000003e +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_TAP_DLY_MASK 0x00007c00 +#define CPU_MAC_UNIT_HSS_CFG_W3_CFG_HSS_L0_PCS_TAP_MAIN_MASK 0x00000001 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_ITX_PREEMP_BASE_MASK 0xc0000000 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_MCNT_MAX_VAL_MASK 0x3e000000 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_PI_FLOOP_STEPS_MASK 0x01800000 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_RX_SSC_LH_MASK 0x00400000 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_SSC_EN_MASK 0x00200000 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_SSC_PI_BW_MASK 0x001e0000 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_SSC_PI_STEP_MASK 0x00018000 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_SSC_RESETB_MASK 0x00004000 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_SSC_RTL_CLK_SEL_MASK 0x00002000 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_TX_DET_RX_EN_MASK 0x00001000 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMA_TX_DET_RX_STR_MASK 0x00000800 +#define CPU_MAC_UNIT_HSS_CFG_W4_CFG_HSS_L0_PCS2_PMANCNT_MAX_VAL_MASK 0x000007ff +#define CPU_MAC_UNIT_HSS_CFG_W5_CFG_HSS_L0_PCS2_PMA_EN_PRE_EMPH_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_CFG_W5_CFG_HSS_L0_PCS2_PMA_EQC_FORCE_MASK 0x78000000 +#define CPU_MAC_UNIT_HSS_CFG_W5_CFG_HSS_L0_PCS2_PMA_EQR_BYP_MASK 0x04000000 +#define CPU_MAC_UNIT_HSS_CFG_W5_CFG_HSS_L0_PCS2_PMA_ISCAN_EXT_DAC_BIT7_MASK 0x02000000 +#define CPU_MAC_UNIT_HSS_CFG_W5_CFG_HSS_L0_PCS2_PMA_POWER_CTRL_MASK 0x01ffffff +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_FORCE_SIGNAL_DETECT_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCLK_GATING_MASK 0x00000080 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_CENTER_SPREADING_MASK 0x00000040 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_CTLE_RSTN_MASK 0x00020000 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_DIS2ND_ORDER_MASK 0x00000020 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_EID_LP_MASK 0x00040000 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_EN_DFE_DIG_MASK 0x00000010 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_EQ_RES_MASK 0x0000000f +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_HOLD_DFE_MASK 0x00400000 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_ISCAN_SEL_MASK 0x00080000 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_PI_HOLD_MASK 0x00100000 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_R50_EN_MASK 0x00200000 +#define CPU_MAC_UNIT_HSS_CFG_W6_CFG_HSS_L0_PCS2_PMA_TX_MARGIN_MASK 0x0001ff00 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_DLEV_MASK 0x3f800000 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_DLEV_BYP_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H1_MASK 0x0000003f +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H2_MASK 0x000007c0 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H3_MASK 0x00007800 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H4_MASK 0x00078000 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H5_MASK 0x00780000 +#define CPU_MAC_UNIT_HSS_CFG_W7_CFG_HSS_L0_PCS2_PMA_H_BYP_MASK 0x40000000 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_AUX_RX_CK_SEL_MASK 0x00000004 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_AUX_TX_CK_SEL_MASK 0x00000002 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_DATA_WIDTH_SEL_MASK 0x00000380 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_HWT_MULTI_LANE_MODE_MASK 0x00000008 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_LANE_ID_MASK 0x00000070 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_PCS2_PMA_PHY_MODE_MASK 0x07c00000 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_PCS2_PMA_TX_SWING_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_PCS2_PMA_VGA_CTRL_MASK 0x78000000 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_PMA_RX_DIV_SEL_MASK 0x00380000 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_PMA_TX_CK_SEL_MASK 0x0000e000 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_RST_N_MASK 0x00000001 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_RX_RATE_SEL_MASK 0x00060000 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_RX_RST_N_MASK 0x00010000 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_TX_RATE_SEL_MASK 0x00001800 +#define CPU_MAC_UNIT_HSS_CFG_W8_CFG_HSS_L1_TX_RST_N_MASK 0x00000400 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_HWT_FOM_SEL_MASK 0x00080000 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS2_PMA_PI_EXT_DAC_BIT20_TO14_MASK 0x07f00000 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS2_PMA_PI_EXT_DAC_BIT23_TO21_MASK 0x38000000 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS2_PMA_TX_EI_MASK 0x00040000 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_EN_ADV_MASK 0x00000200 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_EN_DLY_MASK 0x00000100 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_EN_MAIN_MASK 0x00000080 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_I_SCAN_EN_MASK 0x00000040 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_TAP_ADV_MASK 0x0000003e +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_TAP_DLY_MASK 0x00007c00 +#define CPU_MAC_UNIT_HSS_CFG_W9_CFG_HSS_L1_PCS_TAP_MAIN_MASK 0x00000001 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_ITX_PREEMP_BASE_MASK 0xc0000000 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_MCNT_MAX_VAL_MASK 0x3e000000 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_PI_FLOOP_STEPS_MASK 0x01800000 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_RX_SSC_LH_MASK 0x00400000 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_SSC_EN_MASK 0x00200000 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_SSC_PI_BW_MASK 0x001e0000 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_SSC_PI_STEP_MASK 0x00018000 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_SSC_RESETB_MASK 0x00004000 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_SSC_RTL_CLK_SEL_MASK 0x00002000 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_TX_DET_RX_EN_MASK 0x00001000 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMA_TX_DET_RX_STR_MASK 0x00000800 +#define CPU_MAC_UNIT_HSS_CFG_W10_CFG_HSS_L1_PCS2_PMANCNT_MAX_VAL_MASK 0x000007ff +#define CPU_MAC_UNIT_HSS_CFG_W11_CFG_HSS_L1_PCS2_PMA_EN_PRE_EMPH_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_CFG_W11_CFG_HSS_L1_PCS2_PMA_EQC_FORCE_MASK 0x78000000 +#define CPU_MAC_UNIT_HSS_CFG_W11_CFG_HSS_L1_PCS2_PMA_EQR_BYP_MASK 0x04000000 +#define CPU_MAC_UNIT_HSS_CFG_W11_CFG_HSS_L1_PCS2_PMA_ISCAN_EXT_DAC_BIT7_MASK 0x02000000 +#define CPU_MAC_UNIT_HSS_CFG_W11_CFG_HSS_L1_PCS2_PMA_POWER_CTRL_MASK 0x01ffffff +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_FORCE_SIGNAL_DETECT_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCLK_GATING_MASK 0x00000080 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_CENTER_SPREADING_MASK 0x00000040 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_CTLE_RSTN_MASK 0x00020000 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_DIS2ND_ORDER_MASK 0x00000020 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_EID_LP_MASK 0x00040000 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_EN_DFE_DIG_MASK 0x00000010 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_EQ_RES_MASK 0x0000000f +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_HOLD_DFE_MASK 0x00400000 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_ISCAN_SEL_MASK 0x00080000 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_PI_HOLD_MASK 0x00100000 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_R50_EN_MASK 0x00200000 +#define CPU_MAC_UNIT_HSS_CFG_W12_CFG_HSS_L1_PCS2_PMA_TX_MARGIN_MASK 0x0001ff00 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_DLEV_MASK 0x3f800000 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_DLEV_BYP_MASK 0x80000000 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H1_MASK 0x0000003f +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H2_MASK 0x000007c0 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H3_MASK 0x00007800 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H4_MASK 0x00078000 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H5_MASK 0x00780000 +#define CPU_MAC_UNIT_HSS_CFG_W13_CFG_HSS_L1_PCS2_PMA_H_BYP_MASK 0x40000000 +/* cpu_mac_unit_ip_cam_cfg Definition */ +#define CPU_MAC_UNIT_IP_CAM_CFG_W0_CFG_IP_CAM_VALUE0_31_0 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W1_CFG_IP_CAM_VALUE0_63_32 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W2_CFG_IP_CAM_VALUE0_95_64 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W3_CFG_IP_CAM_VALUE0_127_96 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W4_CFG_IP_CAM_VALUE1_31_0 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W5_CFG_IP_CAM_VALUE1_63_32 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W6_CFG_IP_CAM_VALUE1_95_64 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W7_CFG_IP_CAM_VALUE1_127_96 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W8_CFG_IP_CAM_VALUE2_31_0 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W9_CFG_IP_CAM_VALUE2_63_32 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W10_CFG_IP_CAM_VALUE2_95_64 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W11_CFG_IP_CAM_VALUE2_127_96 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W12_CFG_IP_CAM_VALUE3_31_0 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W13_CFG_IP_CAM_VALUE3_63_32 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W14_CFG_IP_CAM_VALUE3_95_64 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W15_CFG_IP_CAM_VALUE3_127_96 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W16_CFG_IP_CAM_MASK0_31_0 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W17_CFG_IP_CAM_MASK0_63_32 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W18_CFG_IP_CAM_MASK0_95_64 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W19_CFG_IP_CAM_MASK0_127_96 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W20_CFG_IP_CAM_MASK1_31_0 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W21_CFG_IP_CAM_MASK1_63_32 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W22_CFG_IP_CAM_MASK1_95_64 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W23_CFG_IP_CAM_MASK1_127_96 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W24_CFG_IP_CAM_MASK2_31_0 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W25_CFG_IP_CAM_MASK2_63_32 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W26_CFG_IP_CAM_MASK2_95_64 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W27_CFG_IP_CAM_MASK2_127_96 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W28_CFG_IP_CAM_MASK3_31_0 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W29_CFG_IP_CAM_MASK3_63_32 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W30_CFG_IP_CAM_MASK3_95_64 BIT(0) +#define CPU_MAC_UNIT_IP_CAM_CFG_W31_CFG_IP_CAM_MASK3_127_96 BIT(0) + +#define CPU_MAC_UNIT_IP_CAM_CFG_W0_CFG_IP_CAM_VALUE0_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W1_CFG_IP_CAM_VALUE0_63_32_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W2_CFG_IP_CAM_VALUE0_95_64_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W3_CFG_IP_CAM_VALUE0_127_96_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W4_CFG_IP_CAM_VALUE1_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W5_CFG_IP_CAM_VALUE1_63_32_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W6_CFG_IP_CAM_VALUE1_95_64_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W7_CFG_IP_CAM_VALUE1_127_96_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W8_CFG_IP_CAM_VALUE2_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W9_CFG_IP_CAM_VALUE2_63_32_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W10_CFG_IP_CAM_VALUE2_95_64_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W11_CFG_IP_CAM_VALUE2_127_96_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W12_CFG_IP_CAM_VALUE3_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W13_CFG_IP_CAM_VALUE3_63_32_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W14_CFG_IP_CAM_VALUE3_95_64_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W15_CFG_IP_CAM_VALUE3_127_96_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W16_CFG_IP_CAM_MASK0_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W17_CFG_IP_CAM_MASK0_63_32_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W18_CFG_IP_CAM_MASK0_95_64_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W19_CFG_IP_CAM_MASK0_127_96_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W20_CFG_IP_CAM_MASK1_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W21_CFG_IP_CAM_MASK1_63_32_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W22_CFG_IP_CAM_MASK1_95_64_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W23_CFG_IP_CAM_MASK1_127_96_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W24_CFG_IP_CAM_MASK2_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W25_CFG_IP_CAM_MASK2_63_32_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W26_CFG_IP_CAM_MASK2_95_64_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W27_CFG_IP_CAM_MASK2_127_96_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W28_CFG_IP_CAM_MASK3_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W29_CFG_IP_CAM_MASK3_63_32_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W30_CFG_IP_CAM_MASK3_95_64_MASK 0x00000001 +#define CPU_MAC_UNIT_IP_CAM_CFG_W31_CFG_IP_CAM_MASK3_127_96_MASK 0x00000001 + +/* cpu_mac_unit_mac_cam_cfg Definition */ +#define CPU_MAC_UNIT_MAC_CAM_CFG_W0_CFG_MAC_CAM_VALUE0_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W1_CFG_MAC_CAM_VALUE0_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W2_CFG_MAC_CAM_VALUE1_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W3_CFG_MAC_CAM_VALUE1_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W4_CFG_MAC_CAM_VALUE2_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W5_CFG_MAC_CAM_VALUE2_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W6_CFG_MAC_CAM_VALUE3_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W7_CFG_MAC_CAM_VALUE3_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W8_CFG_MAC_CAM_VALUE4_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W9_CFG_MAC_CAM_VALUE4_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W10_CFG_MAC_CAM_VALUE5_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W11_CFG_MAC_CAM_VALUE5_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W12_CFG_MAC_CAM_VALUE6_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W13_CFG_MAC_CAM_VALUE6_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W14_CFG_MAC_CAM_VALUE7_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W15_CFG_MAC_CAM_VALUE7_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W16_CFG_MAC_CAM_MASK0_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W17_CFG_MAC_CAM_MASK0_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W18_CFG_MAC_CAM_MASK1_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W19_CFG_MAC_CAM_MASK1_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W20_CFG_MAC_CAM_MASK2_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W21_CFG_MAC_CAM_MASK2_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W22_CFG_MAC_CAM_MASK3_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W23_CFG_MAC_CAM_MASK3_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W24_CFG_MAC_CAM_MASK4_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W25_CFG_MAC_CAM_MASK4_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W26_CFG_MAC_CAM_MASK5_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W27_CFG_MAC_CAM_MASK5_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W28_CFG_MAC_CAM_MASK6_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W29_CFG_MAC_CAM_MASK6_47_32 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W30_CFG_MAC_CAM_MASK7_31_0 BIT(0) +#define CPU_MAC_UNIT_MAC_CAM_CFG_W31_CFG_MAC_CAM_MASK7_47_32 BIT(0) + +#define CPU_MAC_UNIT_MAC_CAM_CFG_W0_CFG_MAC_CAM_VALUE0_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W1_CFG_MAC_CAM_VALUE0_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W2_CFG_MAC_CAM_VALUE1_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W3_CFG_MAC_CAM_VALUE1_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W4_CFG_MAC_CAM_VALUE2_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W5_CFG_MAC_CAM_VALUE2_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W6_CFG_MAC_CAM_VALUE3_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W7_CFG_MAC_CAM_VALUE3_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W8_CFG_MAC_CAM_VALUE4_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W9_CFG_MAC_CAM_VALUE4_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W10_CFG_MAC_CAM_VALUE5_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W11_CFG_MAC_CAM_VALUE5_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W12_CFG_MAC_CAM_VALUE6_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W13_CFG_MAC_CAM_VALUE6_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W14_CFG_MAC_CAM_VALUE7_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W15_CFG_MAC_CAM_VALUE7_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W16_CFG_MAC_CAM_MASK0_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W17_CFG_MAC_CAM_MASK0_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W18_CFG_MAC_CAM_MASK1_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W19_CFG_MAC_CAM_MASK1_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W20_CFG_MAC_CAM_MASK2_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W21_CFG_MAC_CAM_MASK2_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W22_CFG_MAC_CAM_MASK3_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W23_CFG_MAC_CAM_MASK3_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W24_CFG_MAC_CAM_MASK4_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W25_CFG_MAC_CAM_MASK4_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W26_CFG_MAC_CAM_MASK5_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W27_CFG_MAC_CAM_MASK5_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W28_CFG_MAC_CAM_MASK6_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W29_CFG_MAC_CAM_MASK6_47_32_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W30_CFG_MAC_CAM_MASK7_31_0_MASK 0x00000001 +#define CPU_MAC_UNIT_MAC_CAM_CFG_W31_CFG_MAC_CAM_MASK7_47_32_MASK 0x00000001 + +/* cpu_mac_unit_filter_cfg Definition */ +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_ADDR_IS_SA0 BIT(17) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA0 BIT(9) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_ADDR_IS_SA3 BIT(20) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA6 BIT(15) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_ADDR_IS_SA1 BIT(18) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_FILTER_IS_LOOSE BIT(5) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA7 BIT(16) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_ADDR_FILTER_EN BIT(2) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_BLOCK_SUPPRESSION_TRAFFIC BIT(6) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_ADDR_IS_SA2 BIT(19) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_CAM3_IS_V6 BIT(24) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA5 BIT(14) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA2 BIT(11) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA4 BIT(13) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_CAM_IS_BLACK_LIST BIT(4) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_CAM_IS_BLACK_LIST BIT(3) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_FILTER_EN BIT(0) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_CAM2_IS_V6 BIT(23) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_CAM1_IS_V6 BIT(22) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_ETHER_TYPE_FILTER_EN BIT(1) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA1 BIT(10) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA3 BIT(12) +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_CAM0_IS_V6 BIT(21) +#define CPU_MAC_UNIT_FILTER_CFG_W1_CFG_SUPPRESSION_ETHER_TYPE0 BIT(16) +#define CPU_MAC_UNIT_FILTER_CFG_W1_CFG_VLAN_TPID BIT(0) +#define CPU_MAC_UNIT_FILTER_CFG_W2_CFG_SUPPRESSION_ETHER_TYPE1 BIT(0) +#define CPU_MAC_UNIT_FILTER_CFG_W2_CFG_SUPPRESSION_ETHER_TYPE2 BIT(16) +#define CPU_MAC_UNIT_FILTER_CFG_W3_CFG_CONFIRM_ETHER_TYPE0 BIT(0) +#define CPU_MAC_UNIT_FILTER_CFG_W3_CFG_CONFIRM_ETHER_TYPE1 BIT(16) +#define CPU_MAC_UNIT_FILTER_CFG_W4_CFG_CONFIRM_ETHER_TYPE2 BIT(0) +#define CPU_MAC_UNIT_FILTER_CFG_W5_CFG_METER_TOKEN_UPD_INTERVAL BIT(0) +#define CPU_MAC_UNIT_FILTER_CFG_W5_CFG_METER_TOKEN_UPD_VALUE BIT(16) + +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_ADDR_IS_SA0_MASK 0x00020000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA0_MASK 0x00000200 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_ADDR_IS_SA3_MASK 0x00100000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA6_MASK 0x00008000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_ADDR_IS_SA1_MASK 0x00040000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_FILTER_IS_LOOSE_MASK 0x00000020 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA7_MASK 0x00010000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_ADDR_FILTER_EN_MASK 0x00000004 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_BLOCK_SUPPRESSION_TRAFFIC_MASK 0x000001c0 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_ADDR_IS_SA2_MASK 0x00080000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_CAM3_IS_V6_MASK 0x01000000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA5_MASK 0x00004000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA2_MASK 0x00000800 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA4_MASK 0x00002000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_CAM_IS_BLACK_LIST_MASK 0x00000010 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_CAM_IS_BLACK_LIST_MASK 0x00000008 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_FILTER_EN_MASK 0x00000001 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_CAM2_IS_V6_MASK 0x00800000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_CAM1_IS_V6_MASK 0x00400000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_ETHER_TYPE_FILTER_EN_MASK 0x00000002 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA1_MASK 0x00000400 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_MAC_ADDR_IS_SA3_MASK 0x00001000 +#define CPU_MAC_UNIT_FILTER_CFG_W0_CFG_IP_CAM0_IS_V6_MASK 0x00200000 +#define CPU_MAC_UNIT_FILTER_CFG_W1_CFG_SUPPRESSION_ETHER_TYPE0_MASK 0xffff0000 +#define CPU_MAC_UNIT_FILTER_CFG_W1_CFG_VLAN_TPID_MASK 0x0000ffff +#define CPU_MAC_UNIT_FILTER_CFG_W2_CFG_SUPPRESSION_ETHER_TYPE1_MASK 0x0000ffff +#define CPU_MAC_UNIT_FILTER_CFG_W2_CFG_SUPPRESSION_ETHER_TYPE2_MASK 0xffff0000 +#define CPU_MAC_UNIT_FILTER_CFG_W3_CFG_CONFIRM_ETHER_TYPE0_MASK 0x0000ffff +#define CPU_MAC_UNIT_FILTER_CFG_W3_CFG_CONFIRM_ETHER_TYPE1_MASK 0xffff0000 +#define CPU_MAC_UNIT_FILTER_CFG_W4_CFG_CONFIRM_ETHER_TYPE2_MASK 0x0000ffff +#define CPU_MAC_UNIT_FILTER_CFG_W5_CFG_METER_TOKEN_UPD_INTERVAL_MASK 0x0000ffff +#define CPU_MAC_UNIT_FILTER_CFG_W5_CFG_METER_TOKEN_UPD_VALUE_MASK 0xffff0000 + +struct cpu_mac_unit_mems { + u32 cpu_mac_unit_tx_ts_capture_fifo_0[3]; /* 0x00000400 */ + u32 cpu_mac_unit_tx_ts_capture_fifo_0_rsv3; + u32 cpu_mac_unit_tx_ts_capture_fifo_1[3]; /* 0x00000410 */ + u32 cpu_mac_unit_tx_ts_capture_fifo_1_rsv3; + u32 cpu_mac_unit_tx_ts_capture_fifo_2[3]; /* 0x00000420 */ + u32 cpu_mac_unit_tx_ts_capture_fifo_2_rsv3; + u32 cpu_mac_unit_tx_ts_capture_fifo_3[3]; /* 0x00000430 */ + u32 cpu_mac_unit_tx_ts_capture_fifo_3_rsv3; + u32 cpu_mac_unit_tx_ts_capture_fifo_4[3]; /* 0x00000440 */ + u32 cpu_mac_unit_tx_ts_capture_fifo_4_rsv3; + u32 cpu_mac_unit_tx_ts_capture_fifo_5[3]; /* 0x00000450 */ + u32 cpu_mac_unit_tx_ts_capture_fifo_5_rsv3; + u32 cpu_mac_unit_tx_ts_capture_fifo_6[3]; /* 0x00000460 */ + u32 cpu_mac_unit_tx_ts_capture_fifo_6_rsv3; + u32 cpu_mac_unit_tx_ts_capture_fifo_7[3]; /* 0x00000470 */ + u32 cpu_mac_unit_tx_ts_capture_fifo_7_rsv3; + u32 cpu_mac_unit_tx_capture_ts_0[3]; /* 0x00000480 */ + u32 cpu_mac_unit_tx_capture_ts_0_rsv3; +}; + +/* cpu_mac_unit_tx_ts_capture_fifo Definition */ +#define CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_W0_CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_FIELD0 BIT(0) +#define CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_W1_CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_FIELD1 BIT(0) +#define CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_W2_CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_FIELD2 BIT(0) + +#define CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_W0_CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_FIELD0_MASK 0xffffffff +#define CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_W1_CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_FIELD1_MASK 0xffffffff +#define CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_W2_CPU_MAC_UNIT_TX_TS_CAPTURE_FIFO_FIELD2_MASK 0x0000000f + +/* cpu_mac_unit_tx_capture_ts Definition */ +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W0_CPU_MAC1_TX_SEQ_ID BIT(5) +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W0_CPU_MAC1_TX_SFD BIT(4) +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W0_CPU_MAC0_TX_SEQ_ID BIT(1) +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W0_CPU_MAC0_TX_SFD BIT(0) +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W1_ADJ_RC_SECOND BIT(0) +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W2_ADJ_RC_NS BIT(0) + +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W0_CPU_MAC1_TX_SEQ_ID_MASK 0x00000060 +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W0_CPU_MAC1_TX_SFD_MASK 0x00000010 +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W0_CPU_MAC0_TX_SEQ_ID_MASK 0x00000006 +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W0_CPU_MAC0_TX_SFD_MASK 0x00000001 +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W1_ADJ_RC_SECOND_MASK 0xffffffff +#define CPU_MAC_UNIT_TX_CAPTURE_TS_W2_ADJ_RC_NS_MASK 0x3fffffff + +#define CTCMAC_NUM 2 +#define TX_BUF_CNT 2 + +#define CTCMAC_MDIO_BASE 0x33620000 +#define CTCMAC_0_BASE 0x33410000 +#define CTCMAC_1_BASE 0x33420000 + +#define CTCMAC_MDIO_CMD_STCODE(V) (V << 0) +#define CTCMAC_MDIO_CMD_OPCODE(V) (V << 26) +#define CTCMAC_MDIO_CMD_PHYAD(V) (V << 21) +#define CTCMAC_MDIO_CMD_REGAD(V) (V << 16) +#define CTCMAC_MDIO_CMD_DATA(V) (V << 0) + +#define CTCMAC_MDIO_STAT(V) (V << 16) + +#endif diff --git a/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac_test.c b/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac_test.c new file mode 100644 index 000000000000..72bbf7599ebb --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ctcmac/ctcmac_test.c @@ -0,0 +1,2116 @@ +/* + * Centec cpu_mac Ethernet Driver For Test -- cpu_mac controller implementation + * Provides Bus interface for MIIM regs + * + * Author: liuht + * + * Copyright 2002-2018, Centec Networks (Suzhou) Co., Ltd. + * + * + * 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 +#include +#include +#include + +#include +#include "../pinctrl-ctc/pinctrl-ctc.h" +#include "../include/sysctl.h" +#include +#include +#include + +#include "ctcmac.h" +#include "ctcmac_reg.h" + +enum ctcmac_test_field { + CTCMAC_RING_SIZE = 0, + CTCMAC_PAYLOAD_SIZE = 1, + CTCMAC_RXTS_EN = 2, + CTCMAC_RXTS_DUMP = 3, + CTCMAC_TXTS_EN = 4, + CTCMAC_TXTS_DUMP = 5, + CTCMAC_TXINFO_VAL1 = 6, + CTCMAC_TXINFO_VAL2 = 7, + CTCMAC_TXINFO_VAL3 = 8, + CTCMAC_TXINFO_VAL4 = 9, +}; + +struct ctcmac_ptp_info { + u32 val1; + u32 val2; + u32 val3; + u32 val4; +}; + +struct ctcmac_test_param { + u32 ring_size; + u32 payload_size; + u32 rxts_en; + u32 rxts_dump; + u32 txts_en; + u32 txts_dump; + struct ctcmac_ptp_info ptp_info; +}; + +static int ctcmac_alloc_skb_resources(struct net_device *ndev); +static int ctcmac_free_skb_resources(struct ctcmac_private *priv); +static void cpumac_start(struct ctcmac_private *priv); +static void cpumac_halt(struct ctcmac_private *priv); +static void ctcmac_hw_init(struct ctcmac_private *priv); +static spinlock_t global_reglock __aligned(SMP_CACHE_BYTES); +static int g_reglock_init_done; +static int g_mac_unit_init_done; +static struct ctcmac_test_param test_param[2]; +static struct ctcmac_pkt_stats pkt_stats[2]; +static int cpumac_unit_irq_installed; +static struct regmap *regmap_base; +struct cpu_mac_unit_regs *g_cpumacu_reg; +/* get cpumac register : just for test */ +static int ctcmac_ethtool_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *ee, u8 *data) +{ + u8 *iobase; + u32 val; + unsigned long flags; + struct ctcmac_private *priv = netdev_priv(netdev); + + if (ee->offset >= 0x00010000) { + iobase = (u8 *)priv->cpumacu_reg; + ee->offset -= (0x00010000 + CPUMACUNIT_REG_BASE); + } else if (ee->offset >= 0x00004000) { + iobase = (u8 *)priv->cpumac_mem; + ee->offset -= 0x00004000; + } else { + iobase = (u8 *)priv->cpumac_reg; + } + + spin_lock_irqsave(&priv->reglock, flags); + val = readl((unsigned __iomem *)(iobase + ee->offset)); + pr_err("0x%llx : 0x%x\n", (u64)(iobase + ee->offset), val); + memcpy(data, (u8 *)&val, 4); + + spin_unlock_irqrestore(&priv->reglock, flags); + + return 0; +} + +static int ctcmac_fill_test_param(u32 index, u32 field, u32 val) +{ + if (field == CTCMAC_RING_SIZE) + test_param[index].ring_size = val; + else if (field == CTCMAC_PAYLOAD_SIZE) + test_param[index].payload_size = val; + else if (field == CTCMAC_RXTS_EN) + test_param[index].rxts_en = val; + else if (field == CTCMAC_RXTS_DUMP) + test_param[index].rxts_dump = val; + else if (field == CTCMAC_TXTS_EN) + test_param[index].txts_en = val; + else if (field == CTCMAC_TXTS_DUMP) + test_param[index].txts_dump = val; + else if (field == CTCMAC_TXINFO_VAL1) + test_param[index].ptp_info.val1 = val; + else if (field == CTCMAC_TXINFO_VAL2) + test_param[index].ptp_info.val2 = val; + else if (field == CTCMAC_TXINFO_VAL3) + test_param[index].ptp_info.val3 = val; + else if (field == CTCMAC_TXINFO_VAL4) + test_param[index].ptp_info.val4 = val; + + pr_err("test param:\n"); + pr_err("ring size : %d\n", test_param[index].ring_size); + pr_err("payload size : %d\n", test_param[index].payload_size); + pr_err("rxts en : %d\n", test_param[index].rxts_en); + pr_err("rxts dump : %d\n", test_param[index].rxts_dump); + pr_err("txts en : %d\n", test_param[index].txts_en); + pr_err("txts dump : %d\n", test_param[index].txts_dump); + pr_err("ptp info : 0x%x 0x%x 0x%x 0x%x\n", + test_param[index].ptp_info.val1, + test_param[index].ptp_info.val2, + test_param[index].ptp_info.val3, + test_param[index].ptp_info.val4); + + return 0; +} + +/* set cpumac register : just for test */ +static int ctcmac_ethtool_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *ee, u8 *data) +{ + u8 *iobase; + u32 val = 0; + unsigned long flags; + struct ctcmac_private *priv = netdev_priv(netdev); + + if (ee->offset >= 0x00030000) { + memset(&pkt_stats[priv->index], 0, + sizeof(struct ctcmac_pkt_stats)); + return 0; + } else if (ee->offset >= 0x00020000) { + val = + data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << + 24); + ctcmac_fill_test_param(priv->index, ee->offset - 0x00020000, + val); + return 0; + } else if (ee->offset >= 0x00010000) { + iobase = (u8 *)priv->cpumacu_reg; + ee->offset -= (0x00010000 + CPUMACUNIT_REG_BASE); + } else if (ee->offset >= 0x00004000) { + iobase = (u8 *)priv->cpumac_mem; + ee->offset -= 0x00004000; + } else { + iobase = (u8 *)priv->cpumac_reg; + } + + val = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); + pr_err("0x%llx : 0x%x\n", (u64)(iobase + ee->offset), val); + spin_lock_irqsave(&priv->reglock, flags); + writel(val, (unsigned __iomem *)(iobase + ee->offset)); + spin_unlock_irqrestore(&priv->reglock, flags); + + return 0; +} + +static void ctcmac_ethtool_get_stats(struct net_device *netdev, + struct ethtool_regs *regs, void *regbuf) +{ + u32 mtu; + unsigned long flags; + struct ctcmac_pkt_stats *stats; + struct ctcmac_private *priv = netdev_priv(netdev); + + spin_lock_irqsave(&priv->reglock, flags); + stats = &pkt_stats[priv->index]; + stats->rx_good_ucast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_0[0]); + stats->rx_good_ucast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_0[2]); + stats->rx_good_mcast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_1[0]); + stats->rx_good_mcast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_1[2]); + stats->rx_good_bcast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_2[0]); + stats->rx_good_bcast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_2[2]); + stats->rx_good_pause_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_3[0]); + stats->rx_good_pause_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_3[2]); + stats->rx_good_pfc_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_4[0]); + stats->rx_good_pfc_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_4[2]); + stats->rx_good_control_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_5[0]); + stats->rx_good_control_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_5[2]); + stats->rx_fcs_error_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_6[0]); + stats->rx_fcs_error_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_6[2]); + stats->rx_mac_overrun_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_7[0]); + stats->rx_mac_overrun_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_7[2]); + stats->rx_good_63B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_8[0]); + stats->rx_good_63B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_8[2]); + stats->rx_bad_63B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_9[0]); + stats->rx_bad_63B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_9[2]); + stats->rx_good_mtu2B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_10[0]); + stats->rx_good_mtu2B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_10[2]); + stats->rx_bad_mtu2B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_11[0]); + stats->rx_bad_mtu2B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_11[2]); + stats->rx_good_jumbo_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_12[0]); + stats->rx_good_jumbo_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_12[2]); + stats->rx_bad_jumbo_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_13[0]); + stats->rx_bad_jumbo_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_13[2]); + stats->rx_64B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_14[0]); + stats->rx_64B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_14[2]); + stats->rx_127B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_15[0]); + stats->rx_127B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_15[2]); + stats->rx_255B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_16[0]); + stats->rx_255B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_16[2]); + stats->rx_511B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_17[0]); + stats->rx_511B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_17[2]); + stats->rx_1023B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_18[0]); + stats->rx_1023B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_18[2]); + stats->rx_mtu1B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_19[0]); + stats->rx_mtu1B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_19[2]); + stats->tx_ucast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_20[0]); + stats->tx_ucast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_20[2]); + stats->tx_mcast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_21[0]); + stats->tx_mcast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_21[2]); + stats->tx_bcast_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_22[0]); + stats->tx_bcast_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_22[2]); + stats->tx_pause_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_23[0]); + stats->tx_pause_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_23[2]); + stats->tx_control_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_24[0]); + stats->tx_control_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_24[2]); + stats->tx_fcs_error_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_25[0]); + stats->tx_fcs_error_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_25[2]); + stats->tx_underrun_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_26[0]); + stats->tx_underrun_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_26[2]); + stats->tx_63B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_27[0]); + stats->tx_63B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_27[2]); + stats->tx_64B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_28[0]); + stats->tx_64B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_28[2]); + stats->tx_127B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_29[0]); + stats->tx_127B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_29[2]); + stats->tx_255B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_30[0]); + stats->tx_255B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_30[2]); + stats->tx_511B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_31[0]); + stats->tx_511B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_31[2]); + stats->tx_1023B_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_32[0]); + stats->tx_1023B_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_32[2]); + stats->tx_mtu1_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_33[0]); + stats->tx_mtu1_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_33[2]); + stats->tx_mtu2_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_34[0]); + stats->tx_mtu2_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_34[2]); + stats->tx_jumbo_bytes += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_35[0]); + stats->tx_jumbo_pkt += + readq(&priv->cpumac_mem->cpu_mac_stats_ram_35[2]); + mtu = readl(&priv->cpumac_reg->cpu_mac_stats_cfg[1]); + stats->mtu1 = mtu & 0x3fff; + stats->mtu2 = (mtu >> 16) & 0x3fff; + spin_unlock_irqrestore(&priv->reglock, flags); + + memcpy(regbuf, (void *)stats, sizeof(struct ctcmac_pkt_stats)); +} + +static int ctcmac_ethtool_get_eeprom_len(struct net_device *netdev) +{ + return 0x40000; +} + +static int ctcmac_ethtool_get_regs_len(struct net_device *netdev) +{ + return sizeof(struct ctcmac_pkt_stats); +} + +const struct ethtool_ops ctcmac_ethtool_test_ops = { + .get_eeprom = ctcmac_ethtool_get_eeprom, + .set_eeprom = ctcmac_ethtool_set_eeprom, + .get_eeprom_len = ctcmac_ethtool_get_eeprom_len, + .get_regs = ctcmac_ethtool_get_stats, + .get_regs_len = ctcmac_ethtool_get_regs_len, +}; + +static void clrsetbits(unsigned __iomem *addr, u32 clr, u32 set) +{ + writel((readl(addr) & ~(clr)) | (set), addr); +} + +static u32 ctcmac_regr(unsigned __iomem *addr) +{ + u32 val; + + val = readl(addr); + return val; +} + +static void ctcmac_regw(unsigned __iomem *addr, u32 val) +{ + writel(val, addr); +} + +static inline int ctcmac_rxbd_unused(struct ctcmac_priv_rx_q *rxq) +{ + if (rxq->next_to_clean > rxq->next_to_use) + return rxq->next_to_clean - rxq->next_to_use - 1; + + return rxq->rx_ring_size + rxq->next_to_clean - rxq->next_to_use - 1; +} + +static int ctcmac_alloc_tx_queues(struct ctcmac_private *priv) +{ + int i; + + for (i = 0; i < priv->num_tx_queues; i++) { + priv->tx_queue[i] = kzalloc(sizeof(*priv->tx_queue[i]), + GFP_KERNEL); + if (!priv->tx_queue[i]) + return -ENOMEM; + + priv->tx_queue[i]->tx_skbuff = NULL; + priv->tx_queue[i]->qindex = i; + priv->tx_queue[i]->dev = priv->ndev; + spin_lock_init(&priv->tx_queue[i]->txlock); + } + return 0; +} + +static int ctcmac_alloc_rx_queues(struct ctcmac_private *priv) +{ + int i; + + for (i = 0; i < priv->num_rx_queues; i++) { + priv->rx_queue[i] = kzalloc(sizeof(*priv->rx_queue[i]), + GFP_KERNEL); + if (!priv->rx_queue[i]) + return -ENOMEM; + + priv->rx_queue[i]->qindex = i; + priv->rx_queue[i]->ndev = priv->ndev; + } + return 0; +} + +static void ctcmac_unmap_io_space(struct ctcmac_private *priv) +{ + if (priv->iobase) + iounmap(priv->iobase); +} + +static void ctcmac_free_tx_queues(struct ctcmac_private *priv) +{ + int i; + + for (i = 0; i < priv->num_tx_queues; i++) + kfree(priv->tx_queue[i]); +} + +static void ctcmac_free_rx_queues(struct ctcmac_private *priv) +{ + int i; + + for (i = 0; i < priv->num_rx_queues; i++) + kfree(priv->rx_queue[i]); +} + +static void ctcmac_free_dev(struct ctcmac_private *priv) +{ + if (priv->ndev) + free_netdev(priv->ndev); +} + +static int ctcmac_of_init(struct platform_device *ofdev, + struct net_device **pdev) +{ + int err = 0, index; + const char *ctype; + struct net_device *dev = NULL; + struct ctcmac_private *priv = NULL; + unsigned int num_tx_qs, num_rx_qs; + struct device_node *np = ofdev->dev.of_node; + + num_tx_qs = CTCMAC_TX_QUEUE_MAX; + num_rx_qs = CTCMAC_RX_QUEUE_MAX; + + *pdev = alloc_etherdev_mq(sizeof(*priv), num_tx_qs); + dev = *pdev; + if (!dev) + return -ENOMEM; + + priv = netdev_priv(dev); + priv->ndev = dev; + priv->ofdev = ofdev; + priv->dev = &ofdev->dev; + priv->dev->coherent_dma_mask = DMA_BIT_MASK(64); + priv->num_tx_queues = num_tx_qs; + netif_set_real_num_rx_queues(dev, num_rx_qs); + priv->num_rx_queues = num_rx_qs; + + priv->iobase = of_iomap(np, 0); + priv->cpumac_reg = priv->iobase + CPUMAC_REG_BASE; + priv->cpumac_mem = priv->iobase + CPUMAC_MEM_BASE; + priv->cpumacu_reg = of_iomap(np, 1) + CPUMACUNIT_REG_BASE; + g_cpumacu_reg = priv->cpumacu_reg; + + err = of_property_read_u32(np, "index", &index); + if (err == 0) + priv->index = index; + else + priv->index = 0; + + err = of_property_read_string(np, "phy-connection-type", &ctype); + if (err == 0 && !strncmp(ctype, "sgmii", 5)) + priv->interface = PHY_INTERFACE_MODE_SGMII; + else + priv->interface = PHY_INTERFACE_MODE_MII; + + priv->supported = SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half; + err = of_property_read_string(np, "capability-100M", &ctype); + if (err == 0 && !strncmp(ctype, "support", 7)) + priv->supported |= + SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half; + + err = of_property_read_string(np, "capability-1000M", &ctype); + if (err == 0 && !strncmp(ctype, "support", 7)) + priv->supported |= SUPPORTED_1000baseT_Full; + + priv->phy_node = of_parse_phandle(np, "phy-handle", 0); + + priv->irqinfo[CTCMAC_NORMAL].irq = irq_of_parse_and_map(np, 0); + priv->irqinfo[CTCMAC_FUNC].irq = irq_of_parse_and_map(np, 1); + priv->irqinfo[CTCMAC_UNIT].irq = irq_of_parse_and_map(np, 2); + + return 0; +} + +static int startup_ctcmac(struct net_device *ndev) +{ + int i; + int err; + struct ctcmac_private *priv = netdev_priv(ndev); + + if (ctcmac_alloc_tx_queues(priv)) + return -1; + + if (ctcmac_alloc_rx_queues(priv)) + return -1; + + /* Initializing some of the rx/tx queue level parameters */ + for (i = 0; i < priv->num_tx_queues; i++) { + priv->tx_queue[i]->tx_ring_size = + test_param[priv->index].ring_size; + priv->tx_queue[i]->num_txbdfree = + test_param[priv->index].ring_size; + } + + for (i = 0; i < priv->num_rx_queues; i++) { + priv->rx_queue[i]->rx_ring_size = + test_param[priv->index].ring_size; + } + + ctcmac_hw_init(priv); + + err = ctcmac_alloc_skb_resources(ndev); + if (err) + return err; + + /* barrier */ + smp_mb__before_atomic(); + clear_bit(CTCMAC_DOWN, &priv->state); + /* barrier */ + smp_mb__after_atomic(); + + cpumac_start(priv); + /* force link state update after mac reset */ + priv->oldlink = 0; + priv->oldspeed = 0; + priv->oldduplex = -1; + + phy_start(ndev->phydev); + + napi_enable(&priv->napi_rx); + napi_enable(&priv->napi_tx); + + netif_tx_wake_all_queues(ndev); + + return 0; +} + +static void stop_ctcmac(struct net_device *ndev) +{ + struct ctcmac_private *priv = netdev_priv(ndev); + + /* disable ints and gracefully shut down Rx/Tx DMA */ + cpumac_halt(priv); + + netif_tx_stop_all_queues(ndev); + + /* barrier */ + smp_mb__before_atomic(); + set_bit(CTCMAC_DOWN, &priv->state); + /* barrier */ + smp_mb__after_atomic(); + napi_disable(&priv->napi_rx); + napi_disable(&priv->napi_tx); + phy_stop(ndev->phydev); + ctcmac_free_skb_resources(priv); +} + +static void ctcmac_reset(struct net_device *ndev) +{ + struct ctcmac_private *priv = netdev_priv(ndev); + + while (test_and_set_bit_lock(CTCMAC_RESETTING, &priv->state)) + cpu_relax(); + + stop_ctcmac(ndev); + startup_ctcmac(ndev); + clear_bit_unlock(CTCMAC_RESETTING, &priv->state); +} + +/* ctcmac_reset_task gets scheduled when a packet has not been + * transmitted after a set amount of time. + * For now, assume that clearing out all the structures, and + * starting over will fix the problem. + */ +static void ctcmac_reset_task(struct work_struct *work) +{ + struct ctcmac_private *priv = container_of(work, struct ctcmac_private, + reset_task); + + ctcmac_reset(priv->ndev); +} + +static int ctcmac_rxbd_used_untreated(struct ctcmac_private *priv, int qidx) +{ + u32 count; + + if (qidx) { + count = readl(&priv->cpumac_reg->cpu_mac_desc_mon[2]); + return count & 0xffff; + } + + count = readl(&priv->cpumac_reg->cpu_mac_desc_mon[1]); + + return (count >> 16) & 0xffff; +} + +static int ctcmac_txbd_used_untreated(struct ctcmac_private *priv) +{ + u32 count; + + count = readl(&priv->cpumac_reg->cpu_mac_desc_mon[2]); + + return (count >> 16) & 0xffff; +} + +static bool ctcmac_add_rx_frag(struct ctcmac_rx_buff *rxb, u32 lstatus, + struct sk_buff *skb, bool first) +{ + struct page *page = rxb->page; + unsigned int size = + (lstatus & CPU_MAC_DESC_INTF_W1_DESC_SIZE_MASK) >> 8; + + if (likely(first)) { + skb_put(skb, size); + } else { + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, + rxb->page_offset, size, CTCMAC_RXB_TRUESIZE); + } + + /* try reuse page */ + if (unlikely(page_count(page) != 1)) + return false; + + /* change offset to the other half */ + rxb->page_offset ^= CTCMAC_RXB_TRUESIZE; + + page_ref_inc(page); + + return true; +} + +static void ctcmac_reuse_rx_page(struct ctcmac_priv_rx_q *rxq, + struct ctcmac_rx_buff *old_rxb) +{ + struct ctcmac_rx_buff *new_rxb; + u16 nta = rxq->next_to_alloc; + + new_rxb = &rxq->rx_buff[nta]; + + /* find next buf that can reuse a page */ + nta++; + rxq->next_to_alloc = (nta < rxq->rx_ring_size) ? nta : 0; + + /* copy page reference */ + *new_rxb = *old_rxb; + + /* sync for use by the device */ + dma_sync_single_range_for_device(rxq->dev, old_rxb->dma, + old_rxb->page_offset, + CTCMAC_RXB_TRUESIZE, DMA_FROM_DEVICE); +} + +static struct sk_buff *ctcmac_get_next_rxbuff(struct ctcmac_priv_rx_q *rx_queue, + u32 lstatus, struct sk_buff *skb) +{ + struct ctcmac_rx_buff *rxb = + &rx_queue->rx_buff[rx_queue->next_to_clean]; + struct page *page = rxb->page; + bool first = false; + + if (likely(!skb)) { + void *buff_addr = page_address(page) + rxb->page_offset; + + skb = build_skb(buff_addr, CTCMAC_SKBFRAG_SIZE); + if (unlikely(!skb)) + return NULL; + first = true; + } + + dma_sync_single_range_for_cpu(rx_queue->dev, rxb->dma, rxb->page_offset, + CTCMAC_RXB_TRUESIZE, DMA_FROM_DEVICE); + + if (ctcmac_add_rx_frag(rxb, lstatus, skb, first)) { + /* reuse the free half of the page */ + ctcmac_reuse_rx_page(rx_queue, rxb); + } else { + /* page cannot be reused, unmap it */ + dma_unmap_page(rx_queue->dev, rxb->dma, + PAGE_SIZE, DMA_FROM_DEVICE); + } + + /* clear rxb content */ + rxb->page = NULL; + + return skb; +} + +static void ctcmac_process_frame(struct net_device *ndev, struct sk_buff *skb) +{ + struct ctcmac_private *priv = netdev_priv(ndev); + + if (test_param[priv->index].rxts_en) { + struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); + u64 *ns = (u64 *)(skb->data + skb->len - 8); + + if (test_param[priv->index].rxts_dump) + pr_err("receive frame time stamp 0x%llx\n", *ns); + + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); + shhwtstamps->hwtstamp = ns_to_ktime(be64_to_cpu(*ns)); + skb_pull(skb, 8); + if (test_param[priv->index].rxts_dump) { + pr_err("receive frame time stamp %lld\n", + shhwtstamps->hwtstamp); + } + } + + skb->protocol = eth_type_trans(skb, ndev); +} + +static int ctc_mac_serdes_init(struct ctcmac_private *priv) +{ + int ret = 0; + u32 status; + int delay_ms = 10; + + /* reset serdes */ + writel(0x83806000, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[0]); + writel(0x28061800, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[2]); + writel(0x0026c03a, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[6]); + writel(0x28061810, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[8]); + writel(0x0026c03a, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[12]); + + /* offset0 bit1 BlkRstN */ + writel(0x83806002, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[0]); + mdelay(delay_ms); + + writel(0x80002309, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x80000842, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8000ea45, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + + /* serdes 0 init */ + writel(0x83000a05, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83002008, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300640f, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83000214, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83008015, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83000116, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83001817, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83003018, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83000e24, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83008226, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83001f27, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83002028, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83002829, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300302a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83002038, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300223a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300523b, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x83002040, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300f141, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300014a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8300e693, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + + /* serdes 1 init */ + writel(0x84000a05, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84002008, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400640f, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84000214, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84008015, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84000116, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84001817, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84003018, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84000e24, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84008226, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84001f27, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84002028, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84002829, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400302a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84002038, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400223a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400523b, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x84002040, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400f141, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400014a, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + mdelay(delay_ms); + writel(0x8400e693, &priv->cpumacu_reg->cpu_mac_unit_hss_reg_acc_ctl); + + /* serdes post release */ + writel(0x83806003, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[0]); + writel(0x83826003, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[0]); + + writel(0x28061801, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[2]); + writel(0x28061c01, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[2]); + writel(0x28071c01, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[2]); + + writel(0x28061811, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[8]); + writel(0x28061c11, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[8]); + writel(0x28071c11, &priv->cpumacu_reg->cpu_mac_unit_hss_cfg[8]); + + ret = + readl_poll_timeout(&priv->cpumacu_reg->cpu_mac_unit_hss_mon[1], + status, + status & + CPU_MAC_UNIT_HSS_MON_W1_MON_HSS_L0_DFE_RST_DONE, + 1000, 2000000); + if (ret) { + netdev_dbg(priv->ndev, + "%s:wait for hss reset done fail with cpu_mac_unit_hss_mon[1]:0x%x\n", + priv->ndev->name, + readl(&priv->cpumacu_reg->cpu_mac_unit_hss_mon[1])); + } + mdelay(delay_ms); + + return 0; +} + +static void ctcmac_hw_init(struct ctcmac_private *priv) +{ + int i; + u32 val; + int use_extram = 0; + + /* two cpumac access the same cpumac unit register */ + spin_lock_irq(&global_reglock); + if (priv->index == 0) { + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_reset_ctl, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_BASE, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC0); + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_reset_ctl, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC0, 0); + } else { + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_reset_ctl, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_BASE, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC1); + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_reset_ctl, + CPU_MAC_UNIT_RESET_CTL_W0_RESET_CORE_CPU_MAC1, 0); + } + + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_ts_cfg, + 0, CPU_MAC_UNIT_TS_CFG_W0_CFG_FORCE_S_AND_NS_EN); + + spin_unlock_irq(&global_reglock); + mdelay(10); + + clrsetbits(&priv->cpumac_reg->cpu_mac_init, 0, + CPU_MAC_INIT_DONE_W0_INIT_DONE); + udelay(1); + + if (priv->interface == PHY_INTERFACE_MODE_SGMII) { + /* switch to sgmii and enable auto nego */ + val = readl(&priv->cpumac_reg->cpu_mac_sgmii_auto_neg_cfg); + val &= ~(CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_ENABLE_MASK + | CPU_MAC_SGMII_AUTO_NEG_CFG_W0_CFG_AN_MODE_MASK); + val |= (CSA_SGMII_MD_MASK | CSA_EN); + writel(val, &priv->cpumac_reg->cpu_mac_sgmii_auto_neg_cfg); + } + + clrsetbits(&priv->cpumac_reg->cpu_mac_sgmii_cfg[0], + CPU_MAC_SGMII_CFG_W0_CFG_MII_RX_LINK_FILTER_EN, 0); + clrsetbits(&priv->cpumac_reg->cpu_mac_sgmii_cfg[0], + 0, CPU_MAC_SGMII_CFG_W0_CFG_TX_EVEN_IGNORE); + + clrsetbits(&priv->cpumac_reg->cpu_mac_axi_cfg, + 0, CPU_MAC_AXI_CFG_W0_CFG_AXI_RD_D_WORD_SWAP_EN); + clrsetbits(&priv->cpumac_reg->cpu_mac_axi_cfg, + 0, CPU_MAC_AXI_CFG_W0_CFG_AXI_WR_D_WORD_SWAP_EN); + + clrsetbits(&priv->cpumac_reg->cpu_mac_gmac_cfg[0], + 0, CPU_MAC_GMAC_CFG_W0_CFG_RX_OVERRUN_DROP_EN + | CPU_MAC_GMAC_CFG_W0_CFG_RX_OVERSIZE_DROP_EN); + + clrsetbits(&priv->cpumac_reg->cpu_mac_gmac_cfg[2], + CPU_MAC_GMAC_CFG_W2_CFG_TX_STRIP_CRC_EN, 0); + + clrsetbits(&priv->cpumac_reg->cpu_mac_gmac_cfg[2], + 0, CPU_MAC_GMAC_CFG_W2_CFG_TX_CUT_THROUGH_EN); + + for (i = 0; i < priv->num_tx_queues; i++) { + if (priv->tx_queue[i]->tx_ring_size > + CTCMAC_INTERNAL_RING_SIZE) { + use_extram = 1; + break; + } + } + + for (i = 0; i < priv->num_rx_queues; i++) { + if (priv->rx_queue[i]->rx_ring_size > + CTCMAC_INTERNAL_RING_SIZE) { + use_extram = 1; + break; + } + } + + if (use_extram) { + spin_lock_irq(&global_reglock); + regmap_read(regmap_base, + offsetof(struct SysCtl_regs, SysMemCtl), &val); + val |= SYS_MEM_CTL_W0_CFG_RAM_MUX_EN; + regmap_write(regmap_base, + offsetof(struct SysCtl_regs, SysMemCtl), val); + spin_unlock_irq(&global_reglock); + if (priv->index == 0) { + ctcmac_regw(&priv->cpumac_reg->cpu_mac_ext_ram_cfg[1], + CTCMAC0_EXSRAM_BASE); + } else { + ctcmac_regw(&priv->cpumac_reg->cpu_mac_ext_ram_cfg[1], + CTCMAC1_EXSRAM_BASE); + } + ctcmac_regw(&priv->cpumac_reg->cpu_mac_ext_ram_cfg[0], + test_param[priv->index].ring_size); + clrsetbits(&priv->cpumac_reg->cpu_mac_ext_ram_cfg[0], 0, + CPU_MAC_EXT_RAM_CFG_W0_CFG_EXT_RAM_EN); + + } else { + clrsetbits(&priv->cpumac_reg->cpu_mac_ext_ram_cfg[0], + CPU_MAC_EXT_RAM_CFG_W0_CFG_EXT_RAM_EN, 0); + spin_lock_irq(&global_reglock); + regmap_read(regmap_base, + offsetof(struct SysCtl_regs, SysMemCtl), &val); + val &= ~SYS_MEM_CTL_W0_CFG_RAM_MUX_EN; + regmap_write(regmap_base, + offsetof(struct SysCtl_regs, SysMemCtl), val); + spin_unlock_irq(&global_reglock); + } + + if (test_param[priv->index].rxts_en) { + clrsetbits(&priv->cpumac_reg->cpu_mac_gmac_cfg[0], + 0, CPU_MAC_GMAC_CFG_W0_CFG_RX_TS_EN); + } + + if (test_param[priv->index].txts_en) { + clrsetbits(&priv->cpumac_reg->cpu_mac_gmac_cfg[2], + CPU_MAC_GMAC_CFG_W2_CFG_TX_WAIT_CAPTURE_TS, + CPU_MAC_GMAC_CFG_W2_CFG_TX_HDR_INFO_EN); + } + + /* clear all interrupt */ + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_func[1], 0xffffffff); + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_normal[1], 0xffffffff); + /* mask all interrupt */ + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_func[2], 0xffffffff); + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_normal[2], 0xffffffff); + + pr_err("%s ctcmac_hw_init 0x%x\n", __func__, priv->ndev->flags); +} + +/* update cpumac speed when phy linkup speed changed */ +static noinline void ctcmac_update_link_state(struct ctcmac_private *priv, + struct phy_device *phydev) +{ + int timeout = 2000; + u32 mon, cfg_rep, cfg_smp; + int speed = phydev->speed; + + if (priv->interface != PHY_INTERFACE_MODE_SGMII) + return; + + if (netif_msg_link(priv)) + netdev_dbg(priv->ndev, "link up speed is %d\n", speed); + + if (phydev->link) { + cfg_rep = readl(&priv->cpumac_reg->cpu_mac_sgmii_cfg[0]); + cfg_smp = readl(&priv->cpumac_reg->cpu_mac_sgmii_cfg[1]); + cfg_rep &= ~CSC_REP_MASK; + cfg_smp &= ~CSC_SMP_MASK; + if (speed == 1000) { + cfg_rep |= CSC_1000M; + cfg_smp |= CSC_1000M; + } else if (speed == 100) { + cfg_rep |= CSC_100M; + cfg_smp |= CSC_100M; + } else if (speed == 10) { + cfg_rep |= CSC_10M; + cfg_smp |= CSC_10M; + } else { + return; + } + writel(cfg_rep, &priv->cpumac_reg->cpu_mac_sgmii_cfg[0]); + writel(cfg_smp, &priv->cpumac_reg->cpu_mac_sgmii_cfg[1]); + + while (timeout--) { + mon = readl(&priv->cpumac_reg->cpu_mac_sgmii_mon[0]); + if ((mon & CSM_ANST_MASK) == 6) + break; + + mdelay(1); + } + + if ((mon & CSM_ANST_MASK) != 6) { + pr_err("Error! when phy link up, auto-neg status %d is not right.\n", + mon); + } + if (!priv->oldlink) + priv->oldlink = 1; + + } else { + priv->oldlink = 0; + priv->oldspeed = 0; + priv->oldduplex = -1; + } +} + +static void adjust_link(struct net_device *dev) +{ + struct ctcmac_private *priv = netdev_priv(dev); + struct phy_device *phydev = dev->phydev; + + if (unlikely(phydev->link != priv->oldlink || + (phydev->link && (phydev->duplex != priv->oldduplex || + phydev->speed != priv->oldspeed)))) + ctcmac_update_link_state(priv, phydev); +} + +/* Initializes driver's PHY state, and attaches to the PHY. + * Returns 0 on success. + */ +static int ctcmac_init_phy(struct net_device *dev) +{ + struct ctcmac_private *priv = netdev_priv(dev); + phy_interface_t interface; + struct phy_device *phydev; + + priv->oldlink = 0; + priv->oldspeed = 0; + priv->oldduplex = -1; + + interface = priv->interface; + + phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, 0, + interface); + if (!phydev) { + dev_err(&dev->dev, "could not attach to PHY\n"); + return -ENODEV; + } + + /* Remove any features not supported by the controller */ + phydev->supported = priv->supported; + phydev->advertising = phydev->supported; + + return 0; +} + +static irqreturn_t ctcmac_receive(int irq, struct ctcmac_private *priv) +{ + unsigned long flags; + + if (likely(napi_schedule_prep(&priv->napi_rx))) { + /* disable interrupt */ + spin_lock_irqsave(&priv->reglock, flags); + writel(CTCMAC_NOR_RX0_D | CTCMAC_NOR_RX1_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[2]); + spin_unlock_irqrestore(&priv->reglock, flags); + __napi_schedule(&priv->napi_rx); + } else { + /* clear interrupt */ + writel(CTCMAC_NOR_RX0_D | CTCMAC_NOR_RX1_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[1]); + } + + return IRQ_HANDLED; +} + +static irqreturn_t ctcmac_transmit(int irq, struct ctcmac_private *priv) +{ + unsigned long flags; + + if (likely(napi_schedule_prep(&priv->napi_tx))) { + /* disable interrupt */ + spin_lock_irqsave(&priv->reglock, flags); + writel(CTCMAC_NOR_TX_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[2]); + spin_unlock_irqrestore(&priv->reglock, flags); + __napi_schedule(&priv->napi_tx); + + } else { + /* clear interrupt */ + writel(CTCMAC_NOR_TX_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[1]); + } + + return IRQ_HANDLED; +} + +static irqreturn_t ctcmac_func(int irq, void *data) +{ + u32 event, stat, mask; + struct ctcmac_private *priv = (struct ctcmac_private *)data; + + stat = ctcmac_regr(&priv->cpumac_reg->cpu_mac_interrupt_func[0]); + mask = ctcmac_regr(&priv->cpumac_reg->cpu_mac_interrupt_func[2]); + event = stat & ~mask; + + if ((event & CTCMAC_NOR_RX0_D) || (event & CTCMAC_NOR_RX1_D)) + ctcmac_receive(irq, priv); + + if (event & CTCMAC_NOR_TX_D) + ctcmac_transmit(irq, priv); + + return IRQ_HANDLED; +} + +static irqreturn_t ctcmac_unit(int irq, void *data) +{ + struct cpu_mac_unit_mems *mems = + (struct cpu_mac_unit_mems *)(g_cpumacu_reg + 0x400 - + CPUMACUNIT_REG_BASE); + + ctcmac_regw(&g_cpumacu_reg->cpu_mac_unit_interrupt_func[2], 1); + ctcmac_regw(&g_cpumacu_reg->cpu_mac_unit_interrupt_func[1], 1); + + while (ctcmac_regr(&g_cpumacu_reg->cpu_mac_unit_fifo_status)) { + pr_err("Tx Capture time stamp in fifo 0x%x 0x%x 0x%x\n", + ctcmac_regr(&mems->cpu_mac_unit_tx_capture_ts_0[0]), + ctcmac_regr(&mems->cpu_mac_unit_tx_capture_ts_0[1]), + ctcmac_regr(&mems->cpu_mac_unit_tx_capture_ts_0[2])); + } + ctcmac_regw(&g_cpumacu_reg->cpu_mac_unit_interrupt_func[3], 1); + + return IRQ_HANDLED; +} + +static irqreturn_t ctcmac_normal(int irq, void *grp_id) //TODO by liuht +{ + return IRQ_HANDLED; +} + +static int ctcmac_request_irq(struct ctcmac_private *priv) +{ + int err = 0; + + err = request_irq(priv->irqinfo[CTCMAC_NORMAL].irq, ctcmac_normal, 0, + priv->irqinfo[CTCMAC_NORMAL].name, priv); + if (err < 0) + free_irq(priv->irqinfo[CTCMAC_NORMAL].irq, priv); + enable_irq_wake(priv->irqinfo[CTCMAC_NORMAL].irq); + + err = request_irq(priv->irqinfo[CTCMAC_FUNC].irq, ctcmac_func, 0, + priv->irqinfo[CTCMAC_FUNC].name, priv); + if (err < 0) + free_irq(priv->irqinfo[CTCMAC_FUNC].irq, priv); + enable_irq_wake(priv->irqinfo[CTCMAC_FUNC].irq); + + spin_lock_irq(&global_reglock); + if (priv->irqinfo[CTCMAC_UNIT].irq && !cpumac_unit_irq_installed) { + err = + request_irq(priv->irqinfo[CTCMAC_UNIT].irq, ctcmac_unit, 0, + "cpumac_unit", NULL); + if (err < 0) { + free_irq(priv->irqinfo[CTCMAC_UNIT].irq, NULL); + return err; + } + enable_irq_wake(priv->irqinfo[CTCMAC_UNIT].irq); + cpumac_unit_irq_installed = 1; + } + spin_unlock_irq(&global_reglock); + + return err; +} + +static void ctcmac_free_irq(struct ctcmac_private *priv) +{ + free_irq(priv->irqinfo[CTCMAC_NORMAL].irq, priv); + free_irq(priv->irqinfo[CTCMAC_FUNC].irq, priv); + + spin_lock_irq(&global_reglock); + if (cpumac_unit_irq_installed == 1) { + free_irq(priv->irqinfo[CTCMAC_UNIT].irq, NULL); + cpumac_unit_irq_installed = 0; + } + spin_unlock_irq(&global_reglock); +} + +static bool ctcmac_new_page(struct ctcmac_priv_rx_q *rxq, + struct ctcmac_rx_buff *rxb) +{ + struct page *page; + dma_addr_t addr; + + page = dev_alloc_page(); + if (unlikely(!page)) + return false; + + addr = dma_map_page(rxq->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(rxq->dev, addr))) { + __free_page(page); + + return false; + } + + rxb->dma = addr; + rxb->page = page; + rxb->page_offset = 0; + + return true; +} + +static void ctcmac_fill_rxbd(struct ctcmac_private *priv, + struct ctcmac_rx_buff *rxb, int qidx) +{ + u32 desc_cfg_low, desc_cfg_high; + dma_addr_t bufaddr = rxb->dma + rxb->page_offset; + + desc_cfg_low = + (bufaddr - CTC_DDR_BASE) & CPU_MAC_DESC_INTF_W0_DESC_ADDR_31_0_MASK; + /* CPU_MAC_DESC_INTF_W1_DESC_SIZE:bit(8) */ + desc_cfg_high = (test_param[priv->index].payload_size << 8) | + (((bufaddr - + CTC_DDR_BASE) >> 32) & + CPU_MAC_DESC_INTF_W1_DESC_ADDR_39_32_MASK); + + spin_lock_irq(&priv->reglock); + if (qidx) { + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_1[0], + desc_cfg_low); + /* barrier */ + smp_mb__before_atomic(); + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_1[1], + desc_cfg_high); + + } else { + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_0[0], + desc_cfg_low); + /* barrier */ + smp_mb__before_atomic(); + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_0[1], + desc_cfg_high); + } + + spin_unlock_irq(&priv->reglock); +} + +static void ctcmac_fill_txbd(struct ctcmac_private *priv, + struct ctcmac_desc_cfg *txdesc) +{ + u32 desc_cfg_low, desc_cfg_high; + + desc_cfg_low = txdesc->addr_low; + /* CPU_MAC_DESC_INTF_W1_DESC_SIZE:bit(8) */ + /* CPU_MAC_DESC_INTF_W1_DESC_SOP:bit(22) */ + /* CPU_MAC_DESC_INTF_W1_DESC_EOP:bit(23) */ + desc_cfg_high = txdesc->addr_high | + (txdesc->size << 8) | (txdesc->sop << 22) | (txdesc->eop << 23); + + spin_lock_irq(&priv->reglock); + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_2[0], desc_cfg_low); + /* barrier */ + smp_mb__before_atomic(); + ctcmac_regw(&priv->cpumac_mem->cpu_mac_desc_intf_2[1], desc_cfg_high); + spin_unlock_irq(&priv->reglock); +} + +static void ctcmac_get_txbd(struct ctcmac_private *priv) +{ + u32 lstatus; + + spin_lock_irq(&priv->reglock); + lstatus = ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_2[0]); + /* barrier */ + smp_mb__before_atomic(); + lstatus = ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_2[1]); + + spin_unlock_irq(&priv->reglock); +} + +static void ctcmac_get_rxbd(struct ctcmac_private *priv, u32 *lstatus, + int qidx) +{ + spin_lock_irq(&priv->reglock); + if (qidx) { + ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_1[0]); + *lstatus = + ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_1[1]); + } else { + ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_0[0]); + *lstatus = + ctcmac_regr(&priv->cpumac_mem->cpu_mac_desc_intf_0[1]); + } + /* barrier */ + smp_mb__before_atomic(); + + spin_unlock_irq(&priv->reglock); +} + +static void ctcmac_alloc_rx_buffs(struct ctcmac_priv_rx_q *rx_queue, + int alloc_cnt) +{ + int i; + int qidx = rx_queue->qindex; + struct ctcmac_rx_buff *rxb; + struct net_device *ndev = rx_queue->ndev; + struct ctcmac_private *priv = netdev_priv(ndev); + + i = rx_queue->next_to_use; + rxb = &rx_queue->rx_buff[i]; + + while (alloc_cnt--) { + /* try reuse page */ + if (unlikely(!rxb->page)) { + if (unlikely(!ctcmac_new_page(rx_queue, rxb))) + break; + } + + ctcmac_fill_rxbd(priv, rxb, qidx); + rxb++; + + if (unlikely(++i == rx_queue->rx_ring_size)) { + i = 0; + rxb = rx_queue->rx_buff; + } + } + + rx_queue->next_to_use = i; + rx_queue->next_to_alloc = i; +} + +static int ctcmac_clean_rx_ring(struct ctcmac_priv_rx_q *rx_queue, + int rx_work_limit) +{ + struct net_device *ndev = rx_queue->ndev; + struct ctcmac_private *priv = netdev_priv(ndev); + int i, howmany = 0; + struct sk_buff *skb = rx_queue->skb; + int cleaned_cnt = ctcmac_rxbd_unused(rx_queue); + unsigned int total_bytes = 0, total_pkts = 0; + int qidx = rx_queue->qindex; + + /* Get the first full descriptor */ + i = rx_queue->next_to_clean; + + while (rx_work_limit--) { + u32 lstatus; + + if (cleaned_cnt >= test_param[priv->index].ring_size / 2) { + ctcmac_alloc_rx_buffs(rx_queue, cleaned_cnt); + cleaned_cnt = 0; + } + + if (ctcmac_rxbd_used_untreated(priv, qidx) <= 0) + break; + + if (qidx != 0) + pr_err("rx queue %d rx packet!\n", qidx); + ctcmac_get_rxbd(priv, &lstatus, qidx); + + /* fetch next to clean buffer from the ring */ + skb = ctcmac_get_next_rxbuff(rx_queue, lstatus, skb); + if (unlikely(!skb)) + break; + + cleaned_cnt++; + howmany++; + + if (unlikely(++i == rx_queue->rx_ring_size)) + i = 0; + + rx_queue->next_to_clean = i; + + /* fetch next buffer if not the last in frame */ + if (!(lstatus & CPU_MAC_DESC_INTF_W1_DESC_EOP)) + continue; + + if (unlikely(lstatus & CPU_MAC_DESC_INTF_W1_DESC_ERR)) { + if (!test_param[priv->index].rxts_en) { + /* discard faulty buffer */ + dev_kfree_skb(skb); + skb = NULL; + rx_queue->stats.rx_dropped++; + pr_err("%s: Error with rx desc status 0x%x\n", + ndev->name, lstatus); + continue; + } else { + pr_err("%s: Error with rx desc status 0x%x\n", + ndev->name, lstatus); + } + } + + /* Increment the number of packets */ + total_pkts++; + total_bytes += skb->len; + + skb_record_rx_queue(skb, rx_queue->qindex); + ctcmac_process_frame(ndev, skb); + /* Send the packet up the stack */ + napi_gro_receive(&priv->napi_rx, skb); + + skb = NULL; + } + + /* Store incomplete frames for completion */ + rx_queue->skb = skb; + + rx_queue->stats.rx_packets += total_pkts; + rx_queue->stats.rx_bytes += total_bytes; + + if (cleaned_cnt) + ctcmac_alloc_rx_buffs(rx_queue, cleaned_cnt); + + return howmany; +} + +static void ctcmac_clean_tx_ring(struct ctcmac_priv_tx_q *tx_queue) +{ + u16 next_to_clean; + int tqi = tx_queue->qindex; + struct sk_buff *skb; + struct netdev_queue *txq; + struct ctcmac_tx_buff *tx_buff; + struct net_device *dev = tx_queue->dev; + struct ctcmac_private *priv = netdev_priv(dev); + + txq = netdev_get_tx_queue(dev, tqi); + next_to_clean = tx_queue->next_to_clean; + while (ctcmac_txbd_used_untreated(priv)) { + ctcmac_get_txbd(priv); + + tx_buff = &tx_queue->tx_buff[next_to_clean]; + skb = tx_queue->tx_skbuff[next_to_clean]; + dev_kfree_skb_any(skb); + tx_queue->tx_skbuff[next_to_clean] = NULL; + + dma_unmap_single(priv->dev, tx_buff->dma, + tx_buff->len, DMA_TO_DEVICE); + if (tx_buff->alloc) + kfree(tx_buff->vaddr); + + if ((next_to_clean + 1) >= tx_queue->tx_ring_size) + next_to_clean = 0; + else + next_to_clean++; + + spin_lock(&tx_queue->txlock); + tx_queue->num_txbdfree++; + spin_unlock(&tx_queue->txlock); + } + + /* If we freed a buffer, we can restart transmission, if necessary */ + if (tx_queue->num_txbdfree && + netif_tx_queue_stopped(txq) && + !(test_bit(CTCMAC_DOWN, &priv->state))) { + netif_wake_subqueue(priv->ndev, tqi); + } + + tx_queue->next_to_clean = next_to_clean; +} + +static int ctcmac_poll_rx_sq(struct napi_struct *napi, int budget) +{ + int qidx; + int work_done = 0; + int rx_work_limit; + struct ctcmac_private *priv = + container_of(napi, struct ctcmac_private, napi_rx); + struct ctcmac_priv_rx_q *rx_queue = NULL; + + /* clear interrupt */ + writel(CTCMAC_NOR_RX0_D | CTCMAC_NOR_RX1_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[1]); + + rx_work_limit = budget; + for (qidx = priv->num_rx_queues - 1; qidx >= 0; qidx--) { + rx_queue = priv->rx_queue[qidx]; + work_done += ctcmac_clean_rx_ring(rx_queue, rx_work_limit); + rx_work_limit -= work_done; + } + + if (work_done < budget) { + napi_complete(napi); + /* enable interrupt */ + spin_lock_irq(&priv->reglock); + writel(CTCMAC_NOR_RX0_D | CTCMAC_NOR_RX1_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[3]); + spin_unlock_irq(&priv->reglock); + } + + return work_done; +} + +static int ctcmac_poll_tx_sq(struct napi_struct *napi, int budget) +{ + struct ctcmac_private *priv = + container_of(napi, struct ctcmac_private, napi_tx); + struct ctcmac_priv_tx_q *tx_queue = priv->tx_queue[0]; + + /* clear interrupt */ + writel(CTCMAC_NOR_TX_D, &priv->cpumac_reg->cpu_mac_interrupt_func[1]); + + ctcmac_clean_tx_ring(tx_queue); + + napi_complete(napi); + /* enable interrupt */ + spin_lock_irq(&priv->reglock); + writel(CTCMAC_NOR_TX_D, &priv->cpumac_reg->cpu_mac_interrupt_func[3]); + spin_unlock_irq(&priv->reglock); + + return 0; +} + +static void ctcmac_free_rx_resources(struct ctcmac_private *priv) +{ + int i, j; + struct ctcmac_priv_rx_q *rx_queue = NULL; + + for (i = 0; i < priv->num_rx_queues; i++) { + rx_queue = priv->rx_queue[i]; + if (rx_queue->skb) + dev_kfree_skb(rx_queue->skb); + + for (j = 0; j < rx_queue->rx_ring_size; j++) { + struct ctcmac_rx_buff *rxb = &rx_queue->rx_buff[j]; + + if (!rxb->page) + continue; + dma_unmap_single(rx_queue->dev, rxb->dma, + PAGE_SIZE, DMA_TO_DEVICE); + __free_page(rxb->page); + } + kfree(rx_queue->rx_buff); + rx_queue->rx_buff = NULL; + } +} + +static int ctcmac_init_rx_resources(struct net_device *ndev) +{ + int i; + struct ctcmac_private *priv = netdev_priv(ndev); + struct device *dev = priv->dev; + struct ctcmac_priv_rx_q *rx_queue = NULL; + + for (i = 0; i < priv->num_rx_queues; i++) { + rx_queue = priv->rx_queue[i]; + rx_queue->ndev = ndev; + rx_queue->dev = dev; + rx_queue->next_to_clean = 0; + rx_queue->next_to_use = 0; + rx_queue->next_to_alloc = 0; + rx_queue->skb = NULL; + rx_queue->rx_buff = kcalloc(rx_queue->rx_ring_size, + sizeof(*rx_queue->rx_buff), + GFP_KERNEL); + if (!rx_queue->rx_buff) + goto cleanup; + + ctcmac_alloc_rx_buffs(rx_queue, ctcmac_rxbd_unused(rx_queue)); + } + + return 0; + +cleanup: + ctcmac_free_rx_resources(priv); + + return -1; +} + +static void ctcmac_free_tx_resources(struct ctcmac_private *priv) +{ + int i; + struct ctcmac_priv_tx_q *tx_queue = NULL; + + for (i = 0; i < priv->num_tx_queues; i++) { + struct netdev_queue *txq; + + tx_queue = priv->tx_queue[i]; + txq = netdev_get_tx_queue(tx_queue->dev, tx_queue->qindex); + + kfree(tx_queue->tx_skbuff); + tx_queue->tx_skbuff = NULL; + } +} + +static int ctcmac_init_tx_resources(struct net_device *ndev) +{ + int i; + struct ctcmac_private *priv = netdev_priv(ndev); + struct ctcmac_priv_tx_q *tx_queue = NULL; + + for (i = 0; i < priv->num_tx_queues; i++) { + tx_queue = priv->tx_queue[i]; + tx_queue->num_txbdfree = tx_queue->tx_ring_size; + tx_queue->next_to_clean = 0; + tx_queue->next_to_alloc = 0; + tx_queue->dev = ndev; + tx_queue->tx_skbuff = + kmalloc_array(tx_queue->tx_ring_size, + sizeof(*tx_queue->tx_skbuff), GFP_KERNEL); + + if (!tx_queue->tx_skbuff) + goto cleanup; + } + + return 0; + +cleanup: + ctcmac_free_tx_resources(priv); + + return -1; +} + +static int ctcmac_alloc_skb_resources(struct net_device *ndev) +{ + if (ctcmac_init_rx_resources(ndev)) + return -1; + if (ctcmac_init_tx_resources(ndev)) + return -1; + + return 0; +} + +static int ctcmac_free_skb_resources(struct ctcmac_private *priv) +{ + ctcmac_free_rx_resources(priv); + ctcmac_free_tx_resources(priv); + ctcmac_free_tx_queues(priv); + ctcmac_free_rx_queues(priv); + + return 0; +} + +static void cpumac_start(struct ctcmac_private *priv) +{ + /* 1. enable rx/tx interrupt */ + writel(CTCMAC_NOR_TX_D | CTCMAC_NOR_RX0_D | CTCMAC_NOR_RX1_D, + &priv->cpumac_reg->cpu_mac_interrupt_func[3]); + /* 2. enable rx/tx */ + clrsetbits(&priv->cpumac_reg->cpu_mac_reset, + CPU_MAC_RESET_W0_SOFT_RST_TX, + 0); + clrsetbits(&priv->cpumac_reg->cpu_mac_reset, + CPU_MAC_RESET_W0_SOFT_RST_RX, + 0); + + netif_trans_update(priv->ndev); /* prevent tx timeout */ +} + +static void cpumac_halt(struct ctcmac_private *priv) +{ + /* 1. disable rx/tx interrupt */ + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_func[2], 0xffffffff); + ctcmac_regw(&priv->cpumac_reg->cpu_mac_interrupt_normal[2], 0xffffffff); + /* 2. disable rx/tx */ + clrsetbits(&priv->cpumac_reg->cpu_mac_reset, 0, + CPU_MAC_RESET_W0_SOFT_RST_TX); + clrsetbits(&priv->cpumac_reg->cpu_mac_reset, 0, + CPU_MAC_RESET_W0_SOFT_RST_RX); +} + +static int ctcmac_enet_open(struct net_device *dev) +{ + struct ctcmac_private *priv = netdev_priv(dev); + int err; + + err = ctcmac_init_phy(dev); + if (err) + return err; + err = ctcmac_request_irq(priv); + if (err) + return err; + err = startup_ctcmac(dev); + if (err) + return err; + return 0; +} + +static struct ctcmac_tx_buff *skb_to_txbuff(struct ctcmac_private *priv, + struct sk_buff *skb) +{ + u64 addr, offset; + int frag_index, nr_frags, rq; + skb_frag_t *frag; + struct ctcmac_tx_buff *tx_buff; + struct ctcmac_priv_tx_q *tx_queue = NULL; + + nr_frags = skb_shinfo(skb)->nr_frags; + rq = skb->queue_mapping; + tx_queue = priv->tx_queue[rq]; + + tx_buff = &tx_queue->tx_buff[tx_queue->next_to_alloc]; + addr = (u64)skb->data; + if (!test_param[priv->index].txts_en && !nr_frags && + ((addr & PAGE_MASK) == ((addr + skb_headlen(skb)) & PAGE_MASK))) { + tx_buff->alloc = 0; + tx_buff->vaddr = skb->data; + tx_buff->len = skb_headlen(skb); + tx_buff->dma = + dma_map_single(priv->dev, skb->data, skb_headlen(skb), + DMA_TO_DEVICE); + tx_buff->offset = 0; + + } else { + int alloc_size; + + if (test_param[priv->index].txts_en) { + alloc_size = ALIGN(skb->len + 16, BUF_ALIGNMENT); + tx_buff->len = skb->len + 16; + } else { + alloc_size = ALIGN(skb->len, BUF_ALIGNMENT); + tx_buff->len = skb->len; + } + tx_buff->alloc = 1; + tx_buff->vaddr = kmalloc(alloc_size, GFP_KERNEL); + offset = + (BUF_ALIGNMENT - + (((u64)tx_buff->vaddr) & (BUF_ALIGNMENT - 1))); + if (offset == BUF_ALIGNMENT) + offset = 0; + + tx_buff->offset = offset; + if (test_param[priv->index].txts_en) { + memcpy(tx_buff->vaddr + offset, + &test_param[priv->index].ptp_info, 16); + } + + offset += 16; + memcpy(tx_buff->vaddr + offset, skb->data, skb_headlen(skb)); + offset += skb_headlen(skb); + for (frag_index = 0; frag_index < nr_frags; frag_index++) { + frag = &skb_shinfo(skb)->frags[frag_index]; + memcpy(tx_buff->vaddr + offset, frag, + skb_frag_size(frag)); + offset += skb_frag_size(frag); + } + + tx_buff->dma = + dma_map_single(priv->dev, tx_buff->vaddr, tx_buff->len, + DMA_TO_DEVICE); + } + return tx_buff; +} + +static int ctcmac_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int rq = 0; + unsigned int bytes_sent; + struct netdev_queue *txq; + struct ctcmac_desc_cfg tx_desc; + struct ctcmac_tx_buff *tx_buff; + struct ctcmac_priv_tx_q *tx_queue = NULL; + struct ctcmac_private *priv = netdev_priv(dev); + + rq = skb->queue_mapping; + tx_queue = priv->tx_queue[rq]; + txq = netdev_get_tx_queue(dev, rq); + + /* check if there is space to queue this packet */ + if (tx_queue->num_txbdfree <= 0) { + pr_err("%s: no space left before send pkt!\n", + priv->ndev->name); + /* no space, stop the queue */ + netif_tx_stop_queue(txq); + dev->stats.tx_fifo_errors++; + return NETDEV_TX_BUSY; + } + + /* Update transmit stats */ + bytes_sent = skb->len; + tx_queue->stats.tx_bytes += bytes_sent; + tx_queue->stats.tx_packets++; + + tx_buff = skb_to_txbuff(priv, skb); + tx_desc.sop = 1; + tx_desc.eop = 1; + tx_desc.size = tx_buff->len; + tx_desc.addr_low = (tx_buff->dma + tx_buff->offset - CTC_DDR_BASE) + & CPU_MAC_DESC_INTF_W0_DESC_ADDR_31_0_MASK; + tx_desc.addr_high = + ((tx_buff->dma + tx_buff->offset - CTC_DDR_BASE) >> 32) + & CPU_MAC_DESC_INTF_W1_DESC_ADDR_39_32_MASK; + ctcmac_fill_txbd(priv, &tx_desc); + tx_queue->tx_skbuff[tx_queue->next_to_alloc] = skb; + + if (tx_queue->next_to_alloc >= tx_queue->tx_ring_size - 1) + tx_queue->next_to_alloc = 0; + else + tx_queue->next_to_alloc++; + + /* We can work in parallel with 872(), except + * when modifying num_txbdfree. Note that we didn't grab the lock + * when we were reading the num_txbdfree and checking for available + * space, that's because outside of this function it can only grow. + */ + spin_lock_bh(&tx_queue->txlock); + /* reduce TxBD free count */ + tx_queue->num_txbdfree--; + spin_unlock_bh(&tx_queue->txlock); + + /* If the next BD still needs to be cleaned up, then the bds + * are full. We need to tell the kernel to stop sending us stuff. + */ + if (!tx_queue->num_txbdfree) { + netif_tx_stop_queue(txq); + pr_err("%s: no space left after send pkt!\n", priv->ndev->name); + dev->stats.tx_fifo_errors++; + } + + return NETDEV_TX_OK; +} + +static int ctcmac_change_mtu(struct net_device *dev, int new_mtu) +{ + struct ctcmac_private *priv = netdev_priv(dev); + int frame_size = new_mtu + ETH_HLEN; + + if (frame_size < 64 || frame_size > CTCMAC_JUMBO_FRAME_SIZE) + return -EINVAL; + + while (test_and_set_bit_lock(CTCMAC_RESETTING, &priv->state)) + cpu_relax(); + + if (dev->flags & IFF_UP) + stop_ctcmac(dev); + + dev->mtu = new_mtu; + + if (dev->flags & IFF_UP) + startup_ctcmac(dev); + + clear_bit_unlock(CTCMAC_RESETTING, &priv->state); + + return 0; +} + +static int ctcmac_set_features(struct net_device *dev, + netdev_features_t features) +{ + return 0; +} + +/* Stops the kernel queue, and halts the controller */ +static int ctcmac_close(struct net_device *dev) +{ + struct ctcmac_private *priv = netdev_priv(dev); + + cancel_work_sync(&priv->reset_task); + stop_ctcmac(dev); + + /* Disconnect from the PHY */ + phy_disconnect(dev->phydev); + ctcmac_free_irq(priv); + return 0; +} + +static void ctcmac_set_multi(struct net_device *dev) +{ +} + +static void ctcmac_timeout(struct net_device *dev) +{ + struct ctcmac_private *priv = netdev_priv(dev); + + dev->stats.tx_errors++; + schedule_work(&priv->reset_task); +} + +static int ctcmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct phy_device *phydev = dev->phydev; + + if (!netif_running(dev)) + return -EINVAL; + + if (!phydev) + return -ENODEV; + + return phy_mii_ioctl(phydev, rq, cmd); +} + +static struct net_device_stats *ctcmac_get_stats(struct net_device *dev) +{ + int qidx; + unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0; + unsigned long tx_packets = 0, tx_bytes = 0; + struct ctcmac_private *priv = netdev_priv(dev); + + for (qidx = 0; qidx < priv->num_rx_queues; qidx++) { + if (!priv->rx_queue[qidx]) + return &dev->stats; + rx_packets += priv->rx_queue[qidx]->stats.rx_packets; + rx_bytes += priv->rx_queue[qidx]->stats.rx_bytes; + rx_dropped += priv->rx_queue[qidx]->stats.rx_dropped; + } + + if (!priv->tx_queue[0]) + return &dev->stats; + + tx_packets = priv->tx_queue[0]->stats.tx_packets; + tx_bytes = priv->tx_queue[0]->stats.tx_bytes; + + dev->stats.rx_packets = rx_packets; + dev->stats.rx_bytes = rx_bytes; + dev->stats.rx_dropped = rx_dropped; + dev->stats.tx_bytes = tx_bytes; + dev->stats.tx_packets = tx_packets; + + return &dev->stats; +} + +static int ctcmac_set_mac_addr(struct net_device *dev, void *p) +{ + eth_mac_addr(dev, p); + + return 0; +} + +static const struct net_device_ops ctcmac_netdev_ops = { + .ndo_open = ctcmac_enet_open, + .ndo_start_xmit = ctcmac_start_xmit, + .ndo_stop = ctcmac_close, + .ndo_change_mtu = ctcmac_change_mtu, + .ndo_set_features = ctcmac_set_features, + .ndo_set_rx_mode = ctcmac_set_multi, + .ndo_tx_timeout = ctcmac_timeout, + .ndo_do_ioctl = ctcmac_ioctl, + .ndo_get_stats = ctcmac_get_stats, + .ndo_set_mac_address = ctcmac_set_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + +static int ctcmac_probe(struct platform_device *ofdev) +{ + struct net_device *dev = NULL; + struct ctcmac_private *priv = NULL; + int err = 0; + + regmap_base = + syscon_regmap_lookup_by_phandle(ofdev->dev.of_node, "ctc,sysctrl"); + if (IS_ERR(regmap_base)) + return PTR_ERR(regmap_base); + + err = ctcmac_of_init(ofdev, &dev); + if (err) + return err; + + priv = netdev_priv(dev); + SET_NETDEV_DEV(dev, &ofdev->dev); + INIT_WORK(&priv->reset_task, ctcmac_reset_task); + platform_set_drvdata(ofdev, priv); + + dev->base_addr = (unsigned long)priv->iobase; + dev->watchdog_timeo = TX_TIMEOUT; + dev->mtu = CTCMAC_DEFAULT_MTU; + dev->netdev_ops = &ctcmac_netdev_ops; + dev->ethtool_ops = &ctcmac_ethtool_test_ops; + + netif_napi_add(dev, &priv->napi_rx, ctcmac_poll_rx_sq, + CTCMAC_NAIP_RX_WEIGHT); + netif_napi_add(dev, &priv->napi_tx, ctcmac_poll_tx_sq, + CTCMAC_NAIP_TX_WEIGHT); + + set_bit(CTCMAC_DOWN, &priv->state); + + if (!g_reglock_init_done) + spin_lock_init(&global_reglock); + + g_reglock_init_done = 1; + + spin_lock_init(&priv->reglock); + /* Carrier starts down, phylib will bring it up */ + netif_carrier_off(dev); + err = register_netdev(dev); + if (err) + goto register_fail; + + if (!g_mac_unit_init_done) { + writel(0x07, &priv->cpumacu_reg->cpu_mac_unit_reset_ctl); + writel(0x00, &priv->cpumacu_reg->cpu_mac_unit_reset_ctl); + + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_ts_cfg, + 0, CPU_MAC_UNIT_TS_CFG_W0_CFG_FORCE_S_AND_NS_EN); + if (priv->interface == PHY_INTERFACE_MODE_SGMII) { + clrsetbits(&priv->cpumacu_reg->cpu_mac_unit_ref_pulse_cfg[1], + CPU_MAC_UNIT_REF_PULSE_CFG_W1_REF_LINK_PULSE_RST, + 0); + + ctc_mac_serdes_init(priv); + } + g_mac_unit_init_done = 1; + } + + mdelay(10); + + sprintf(priv->irqinfo[CTCMAC_NORMAL].name, "%s%s", + dev->name, "_normal"); + sprintf(priv->irqinfo[CTCMAC_FUNC].name, "%s%s", dev->name, "_func"); + sprintf(priv->irqinfo[CTCMAC_UNIT].name, "%s%s", dev->name, "_unit"); + test_param[priv->index].ring_size = 64; + test_param[priv->index].payload_size = 256; + + return 0; + +register_fail: + ctcmac_unmap_io_space(priv); + ctcmac_free_rx_queues(priv); + ctcmac_free_tx_queues(priv); + of_node_put(priv->phy_node); + ctcmac_free_dev(priv); + + return err; +} + +static int ctcmac_remove(struct platform_device *ofdev) +{ + struct ctcmac_private *priv = platform_get_drvdata(ofdev); + + of_node_put(priv->phy_node); + + unregister_netdev(priv->ndev); + + ctcmac_unmap_io_space(priv); + ctcmac_free_rx_queues(priv); + ctcmac_free_tx_queues(priv); + ctcmac_free_dev(priv); + + return 0; +} + +static const struct of_device_id ctcmac_match[] = { + { + .type = "network", + .compatible = "ctc,mac-test", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, ctcmac_match); + +/* Structure for a device driver */ +static struct platform_driver ctcmac_driver = { + .driver = { + .name = "ctc-cpumac-test", + .of_match_table = ctcmac_match, + }, + .probe = ctcmac_probe, + .remove = ctcmac_remove, +}; + +module_platform_driver(ctcmac_driver); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/tsingma-bsp/src/ehci-ctc/Makefile b/platform/centec-arm64/tsingma-bsp/src/ehci-ctc/Makefile new file mode 100644 index 000000000000..121d3a0eada7 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ehci-ctc/Makefile @@ -0,0 +1 @@ +obj-m = ehci-ctc.o diff --git a/platform/centec-arm64/tsingma-bsp/src/ehci-ctc/ehci-ctc.c b/platform/centec-arm64/tsingma-bsp/src/ehci-ctc/ehci-ctc.c new file mode 100644 index 000000000000..458ef18dc3ff --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ehci-ctc/ehci-ctc.c @@ -0,0 +1,423 @@ +/* + * Centec platform ehci driver + * + * Copyright 2018 Liuht + * + * Licensed under the GNU/GPL. See COPYING for details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ehci.h" + +#define DRIVER_DESC "Centec EHCI platform driver" +#define EHCI_MAX_CLKS 4 +#define EHCI_MAX_RSTS 4 +#define hcd_to_ehci_priv(h) ((struct ehci_ctc_priv *)hcd_to_ehci(h)->priv) + +struct ehci_ctc_priv { + struct clk *clks[EHCI_MAX_CLKS]; + struct reset_control *rsts[EHCI_MAX_RSTS]; + struct phy **phys; + int num_phys; + bool reset_on_resume; +}; + +static const char hcd_name[] = "ehci-ctc"; + +static int ehci_ctc_reset(struct usb_hcd *hcd) +{ + struct platform_device *pdev = to_platform_device(hcd->self.controller); + struct usb_ehci_pdata *pdata = dev_get_platdata(&pdev->dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int retval; + + ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug; + + if (pdata->pre_setup) { + retval = pdata->pre_setup(hcd); + if (retval < 0) + return retval; + } + + ehci->caps = hcd->regs + pdata->caps_offset; + retval = ehci_setup(hcd); + if (retval) + return retval; + + if (pdata->no_io_watchdog) + ehci->need_io_watchdog = 0; + return 0; +} + +static int ehci_ctc_power_on(struct platform_device *dev) +{ + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct ehci_ctc_priv *priv = hcd_to_ehci_priv(hcd); + int clk, ret, phy_num; + + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) { + ret = clk_prepare_enable(priv->clks[clk]); + if (ret) + goto err_disable_clks; + } + + for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { + ret = phy_init(priv->phys[phy_num]); + if (ret) + goto err_exit_phy; + ret = phy_power_on(priv->phys[phy_num]); + if (ret) { + phy_exit(priv->phys[phy_num]); + goto err_exit_phy; + } + } + + return 0; + +err_exit_phy: + while (--phy_num >= 0) { + phy_power_off(priv->phys[phy_num]); + phy_exit(priv->phys[phy_num]); + } +err_disable_clks: + while (--clk >= 0) + clk_disable_unprepare(priv->clks[clk]); + + return ret; +} + +static void ehci_ctc_power_off(struct platform_device *dev) +{ + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct ehci_ctc_priv *priv = hcd_to_ehci_priv(hcd); + int clk, phy_num; + + for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { + phy_power_off(priv->phys[phy_num]); + phy_exit(priv->phys[phy_num]); + } + + for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--) + if (priv->clks[clk]) + clk_disable_unprepare(priv->clks[clk]); +} + +static struct hc_driver __read_mostly ehci_ctc_hc_driver; + +static const struct ehci_driver_overrides platform_overrides __initconst = { + .reset = ehci_ctc_reset, + .extra_priv_size = sizeof(struct ehci_ctc_priv), +}; + +static struct usb_ehci_pdata ehci_ctc_defaults = { + .caps_offset = 0x100, + .dma_mask_64 = 1, + .power_on = ehci_ctc_power_on, + .power_suspend = ehci_ctc_power_off, + .power_off = ehci_ctc_power_off, +}; + +#define KERN_CTC KERN_ERR +static int ehci_ctc_probe(struct platform_device *dev) +{ + struct usb_hcd *hcd; + struct resource *res_mem; + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); + struct ehci_ctc_priv *priv; + struct ehci_hcd *ehci; + int err, irq, phy_num, clk = 0, rst; + + if (usb_disabled()) + return -ENODEV; + + /* + * Use reasonable defaults so platforms don't have to provide these + * with DT probing on ARM. + */ + if (!pdata) + pdata = &ehci_ctc_defaults; + + err = dma_coerce_mask_and_coherent(&dev->dev, + pdata->dma_mask_64 ? + DMA_BIT_MASK(64) : DMA_BIT_MASK(32)); + if (err) { + dev_err(&dev->dev, "Error: DMA mask configuration failed\n"); + return err; + } + + irq = platform_get_irq(dev, 0); + if (irq < 0) { + dev_err(&dev->dev, "no irq provided"); + return irq; + } + + hcd = usb_create_hcd(&ehci_ctc_hc_driver, &dev->dev, + dev_name(&dev->dev)); + if (!hcd) + return -ENOMEM; + + platform_set_drvdata(dev, hcd); + dev->dev.platform_data = pdata; + priv = hcd_to_ehci_priv(hcd); + ehci = hcd_to_ehci(hcd); + if (pdata == &ehci_ctc_defaults && dev->dev.of_node) { + if (of_property_read_bool(dev->dev.of_node, "big-endian-regs")) + ehci->big_endian_mmio = 1; + + if (of_property_read_bool(dev->dev.of_node, "big-endian-desc")) + ehci->big_endian_desc = 1; + + if (of_property_read_bool(dev->dev.of_node, "big-endian")) + ehci->big_endian_mmio = ehci->big_endian_desc = 1; + + if (of_property_read_bool(dev->dev.of_node, + "needs-reset-on-resume")) + priv->reset_on_resume = true; + + if (of_property_read_bool(dev->dev.of_node, + "has-transaction-translator")) + hcd->has_tt = 1; + + priv->num_phys = of_count_phandle_with_args(dev->dev.of_node, + "phys", + "#phy-cells"); + + if (priv->num_phys > 0) { + priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, + sizeof(struct phy *), + GFP_KERNEL); + if (!priv->phys) + return -ENOMEM; + } else + priv->num_phys = 0; + + for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { + priv->phys[phy_num] = + devm_of_phy_get_by_index(&dev->dev, + dev->dev.of_node, phy_num); + if (IS_ERR(priv->phys[phy_num])) { + err = PTR_ERR(priv->phys[phy_num]); + goto err_put_hcd; + } + } + + for (clk = 0; clk < EHCI_MAX_CLKS; clk++) { + priv->clks[clk] = of_clk_get(dev->dev.of_node, clk); + if (IS_ERR(priv->clks[clk])) { + err = PTR_ERR(priv->clks[clk]); + if (err == -EPROBE_DEFER) + goto err_put_clks; + priv->clks[clk] = NULL; + break; + } + } + } + for (rst = 0; rst < EHCI_MAX_RSTS; rst++) { + priv->rsts[rst] = + devm_reset_control_get_shared_by_index(&dev->dev, rst); + if (IS_ERR(priv->rsts[rst])) { + err = PTR_ERR(priv->rsts[rst]); + if (err == -EPROBE_DEFER) + goto err_reset; + priv->rsts[rst] = NULL; + break; + } + + err = reset_control_deassert(priv->rsts[rst]); + if (err) + goto err_reset; + } + if (pdata->big_endian_desc) + ehci->big_endian_desc = 1; + if (pdata->big_endian_mmio) + ehci->big_endian_mmio = 1; + if (pdata->has_tt) + hcd->has_tt = 1; + if (pdata->reset_on_resume) + priv->reset_on_resume = true; + +#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO + if (ehci->big_endian_mmio) { + dev_err(&dev->dev, + "Error: CONFIG_USB_EHCI_BIG_ENDIAN_MMIO not set\n"); + err = -EINVAL; + goto err_reset; + } +#endif +#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC + if (ehci->big_endian_desc) { + dev_err(&dev->dev, + "Error: CONFIG_USB_EHCI_BIG_ENDIAN_DESC not set\n"); + err = -EINVAL; + goto err_reset; + } +#endif + + if (pdata->power_on) { + err = pdata->power_on(dev); + if (err < 0) + goto err_reset; + } + res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); + hcd->regs = devm_ioremap_resource(&dev->dev, res_mem); + if (IS_ERR(hcd->regs)) { + err = PTR_ERR(hcd->regs); + goto err_power; + } + hcd->rsrc_start = res_mem->start; + hcd->rsrc_len = resource_size(res_mem); + err = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (err) + goto err_power; + device_wakeup_enable(hcd->self.controller); + platform_set_drvdata(dev, hcd); + return err; + +err_power: + if (pdata->power_off) + pdata->power_off(dev); +err_reset: + while (--rst >= 0) + reset_control_assert(priv->rsts[rst]); +err_put_clks: + while (--clk >= 0) + clk_put(priv->clks[clk]); +err_put_hcd: + if (pdata == &ehci_ctc_defaults) + dev->dev.platform_data = NULL; + + usb_put_hcd(hcd); + + return err; +} + +static int ehci_ctc_remove(struct platform_device *dev) +{ + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); + struct ehci_ctc_priv *priv = hcd_to_ehci_priv(hcd); + int clk, rst; + + usb_remove_hcd(hcd); + + if (pdata->power_off) + pdata->power_off(dev); + + for (rst = 0; rst < EHCI_MAX_RSTS && priv->rsts[rst]; rst++) + reset_control_assert(priv->rsts[rst]); + + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) + clk_put(priv->clks[clk]); + + usb_put_hcd(hcd); + + if (pdata == &ehci_ctc_defaults) + dev->dev.platform_data = NULL; + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int ehci_ctc_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev_get_platdata(dev); + struct platform_device *pdev = to_platform_device(dev); + bool do_wakeup = device_may_wakeup(dev); + int ret; + + ret = ehci_suspend(hcd, do_wakeup); + if (ret) + return ret; + + if (pdata->power_suspend) + pdata->power_suspend(pdev); + + return ret; +} + +static int ehci_ctc_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev_get_platdata(dev); + struct platform_device *pdev = to_platform_device(dev); + struct ehci_ctc_priv *priv = hcd_to_ehci_priv(hcd); + + if (pdata->power_on) { + int err = pdata->power_on(pdev); + + if (err < 0) + return err; + } + + ehci_resume(hcd, priv->reset_on_resume); + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct of_device_id ctc_ehci_ids[] = { + {.compatible = "ctc-ehci",}, + {} +}; + +MODULE_DEVICE_TABLE(of, ctc_ehci_ids); + +static const struct platform_device_id ehci_ctc_table[] = { + {"ehci-ctc", 0}, + {} +}; + +MODULE_DEVICE_TABLE(platform, ehci_ctc_table); + +static SIMPLE_DEV_PM_OPS(ehci_ctc_pm_ops, ehci_ctc_suspend, ehci_ctc_resume); + +static struct platform_driver ehci_ctc_driver = { + .id_table = ehci_ctc_table, + .probe = ehci_ctc_probe, + .remove = ehci_ctc_remove, + .shutdown = usb_hcd_platform_shutdown, + .driver = { + .name = "ehci-ctc", + .pm = &ehci_ctc_pm_ops, + .of_match_table = ctc_ehci_ids, + } +}; + +static int __init ehci_ctc_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ehci_init_driver(&ehci_ctc_hc_driver, &platform_overrides); + return platform_driver_register(&ehci_ctc_driver); +} + +module_init(ehci_ctc_init); + +static void __exit ehci_ctc_cleanup(void) +{ + platform_driver_unregister(&ehci_ctc_driver); +} + +module_exit(ehci_ctc_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Hauke Mehrtens"); +MODULE_AUTHOR("Alan Stern"); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/tsingma-bsp/src/ehci-ctc/ehci.h b/platform/centec-arm64/tsingma-bsp/src/ehci-ctc/ehci.h new file mode 100644 index 000000000000..c8e9a48e1d51 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/ehci-ctc/ehci.h @@ -0,0 +1,894 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2001-2002 by David Brownell + */ + +#ifndef __LINUX_EHCI_HCD_H +#define __LINUX_EHCI_HCD_H + +/* definitions used for the EHCI driver */ + +/* + * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to + * __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN_DESC), depending on + * the host controller implementation. + * + * To facilitate the strongest possible byte-order checking from "sparse" + * and so on, we use __leXX unless that's not practical. + */ +#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC +typedef __u32 __bitwise __hc32; +typedef __u16 __bitwise __hc16; +#else +#define __hc32 __le32 +#define __hc16 __le16 +#endif + +/* statistics can be kept for tuning/monitoring */ +#ifdef CONFIG_DYNAMIC_DEBUG +#define EHCI_STATS +#endif + +struct ehci_stats { + /* irq usage */ + unsigned long normal; + unsigned long error; + unsigned long iaa; + unsigned long lost_iaa; + + /* termination of urbs from core */ + unsigned long complete; + unsigned long unlink; +}; + +/* + * Scheduling and budgeting information for periodic transfers, for both + * high-speed devices and full/low-speed devices lying behind a TT. + */ +struct ehci_per_sched { + struct usb_device *udev; /* access to the TT */ + struct usb_host_endpoint *ep; + struct list_head ps_list; /* node on ehci_tt's ps_list */ + u16 tt_usecs; /* time on the FS/LS bus */ + u16 cs_mask; /* C-mask and S-mask bytes */ + u16 period; /* actual period in frames */ + u16 phase; /* actual phase, frame part */ + u8 bw_phase; /* same, for bandwidth + reservation */ + u8 phase_uf; /* uframe part of the phase */ + u8 usecs, c_usecs; /* times on the HS bus */ + u8 bw_uperiod; /* period in microframes, for + bandwidth reservation */ + u8 bw_period; /* same, in frames */ +}; +#define NO_FRAME 29999 /* frame not assigned yet */ + +/* ehci_hcd->lock guards shared data against other CPUs: + * ehci_hcd: async, unlink, periodic (and shadow), ... + * usb_host_endpoint: hcpriv + * ehci_qh: qh_next, qtd_list + * ehci_qtd: qtd_list + * + * Also, hold this lock when talking to HC registers or + * when updating hw_* fields in shared qh/qtd/... structures. + */ + +#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ + +/* + * ehci_rh_state values of EHCI_RH_RUNNING or above mean that the + * controller may be doing DMA. Lower values mean there's no DMA. + */ +enum ehci_rh_state { + EHCI_RH_HALTED, + EHCI_RH_SUSPENDED, + EHCI_RH_RUNNING, + EHCI_RH_STOPPING +}; + +/* + * Timer events, ordered by increasing delay length. + * Always update event_delays_ns[] and event_handlers[] (defined in + * ehci-timer.c) in parallel with this list. + */ +enum ehci_hrtimer_event { + EHCI_HRTIMER_POLL_ASS, /* Poll for async schedule off */ + EHCI_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */ + EHCI_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */ + EHCI_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ + EHCI_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */ + EHCI_HRTIMER_ACTIVE_UNLINK, /* Wait while unlinking an active QH */ + EHCI_HRTIMER_START_UNLINK_INTR, /* Unlink empty interrupt QHs */ + EHCI_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */ + EHCI_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */ + EHCI_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */ + EHCI_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */ + EHCI_HRTIMER_IO_WATCHDOG, /* Check for missing IRQs */ + EHCI_HRTIMER_NUM_EVENTS /* Must come last */ +}; +#define EHCI_HRTIMER_NO_EVENT 99 + +struct ehci_hcd { /* one per controller */ + /* timing support */ + enum ehci_hrtimer_event next_hrtimer_event; + unsigned enabled_hrtimer_events; + ktime_t hr_timeouts[EHCI_HRTIMER_NUM_EVENTS]; + struct hrtimer hrtimer; + + int PSS_poll_count; + int ASS_poll_count; + int died_poll_count; + + /* glue to PCI and HCD framework */ + struct ehci_caps __iomem *caps; + struct ehci_regs __iomem *regs; + struct ehci_dbg_port __iomem *debug; + + __u32 hcs_params; /* cached register copy */ + spinlock_t lock; + enum ehci_rh_state rh_state; + + /* general schedule support */ + bool scanning:1; + bool need_rescan:1; + bool intr_unlinking:1; + bool iaa_in_progress:1; + bool async_unlinking:1; + bool shutdown:1; + struct ehci_qh *qh_scan_next; + + /* async schedule support */ + struct ehci_qh *async; + struct ehci_qh *dummy; /* For AMD quirk use */ + struct list_head async_unlink; + struct list_head async_idle; + unsigned async_unlink_cycle; + unsigned async_count; /* async activity count */ + __hc32 old_current; /* Test for QH becoming */ + __hc32 old_token; /* inactive during unlink */ + + /* periodic schedule support */ +#define DEFAULT_I_TDPS 1024 /* some HCs can do less */ + unsigned periodic_size; + __hc32 *periodic; /* hw periodic table */ + dma_addr_t periodic_dma; + struct list_head intr_qh_list; + unsigned i_thresh; /* uframes HC might cache */ + + union ehci_shadow *pshadow; /* mirror hw periodic table */ + struct list_head intr_unlink_wait; + struct list_head intr_unlink; + unsigned intr_unlink_wait_cycle; + unsigned intr_unlink_cycle; + unsigned now_frame; /* frame from HC hardware */ + unsigned last_iso_frame; /* last frame scanned for iso */ + unsigned intr_count; /* intr activity count */ + unsigned isoc_count; /* isoc activity count */ + unsigned periodic_count; /* periodic activity count */ + unsigned uframe_periodic_max; /* max periodic time per uframe */ + + + /* list of itds & sitds completed while now_frame was still active */ + struct list_head cached_itd_list; + struct ehci_itd *last_itd_to_free; + struct list_head cached_sitd_list; + struct ehci_sitd *last_sitd_to_free; + + /* per root hub port */ + unsigned long reset_done[EHCI_MAX_ROOT_PORTS]; + + /* bit vectors (one bit per port) */ + unsigned long bus_suspended; /* which ports were + already suspended at the start of a bus suspend */ + unsigned long companion_ports; /* which ports are + dedicated to the companion controller */ + unsigned long owned_ports; /* which ports are + owned by the companion during a bus suspend */ + unsigned long port_c_suspend; /* which ports have + the change-suspend feature turned on */ + unsigned long suspended_ports; /* which ports are + suspended */ + unsigned long resuming_ports; /* which ports have + started to resume */ + + /* per-HC memory pools (could be per-bus, but ...) */ + struct dma_pool *qh_pool; /* qh per active urb */ + struct dma_pool *qtd_pool; /* one or more per qh */ + struct dma_pool *itd_pool; /* itd per iso urb */ + struct dma_pool *sitd_pool; /* sitd per split iso urb */ + + unsigned random_frame; + unsigned long next_statechange; + ktime_t last_periodic_enable; + u32 command; + + /* SILICON QUIRKS */ + unsigned no_selective_suspend:1; + unsigned has_fsl_port_bug:1; /* FreeScale */ + unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */ + unsigned has_fsl_susp_errata:1; /* NXP SUSP quirk */ + unsigned big_endian_mmio:1; + unsigned big_endian_desc:1; + unsigned big_endian_capbase:1; + unsigned has_amcc_usb23:1; + unsigned need_io_watchdog:1; + unsigned amd_pll_fix:1; + unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ + unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ + unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ + unsigned need_oc_pp_cycle:1; /* MPC834X port power */ + unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ + + /* required for usb32 quirk */ + #define OHCI_CTRL_HCFS (3 << 6) + #define OHCI_USB_OPER (2 << 6) + #define OHCI_USB_SUSPEND (3 << 6) + + #define OHCI_HCCTRL_OFFSET 0x4 + #define OHCI_HCCTRL_LEN 0x4 + __hc32 *ohci_hcctrl_reg; + unsigned has_hostpc:1; + unsigned has_tdi_phy_lpm:1; + unsigned has_ppcd:1; /* support per-port change bits */ + u8 sbrn; /* packed release number */ + + /* irq statistics */ +#ifdef EHCI_STATS + struct ehci_stats stats; +# define COUNT(x) ((x)++) +#else +# define COUNT(x) +#endif + + /* debug files */ +#ifdef CONFIG_DYNAMIC_DEBUG + struct dentry *debug_dir; +#endif + + /* bandwidth usage */ +#define EHCI_BANDWIDTH_SIZE 64 +#define EHCI_BANDWIDTH_FRAMES (EHCI_BANDWIDTH_SIZE >> 3) + u8 bandwidth[EHCI_BANDWIDTH_SIZE]; + /* us allocated per uframe */ + u8 tt_budget[EHCI_BANDWIDTH_SIZE]; + /* us budgeted per uframe */ + struct list_head tt_list; + + /* platform-specific data -- must come last */ + unsigned long priv[0] __aligned(sizeof(s64)); +}; + +/* convert between an HCD pointer and the corresponding EHCI_HCD */ +static inline struct ehci_hcd *hcd_to_ehci(struct usb_hcd *hcd) +{ + return (struct ehci_hcd *) (hcd->hcd_priv); +} +static inline struct usb_hcd *ehci_to_hcd(struct ehci_hcd *ehci) +{ + return container_of((void *) ehci, struct usb_hcd, hcd_priv); +} + +/*-------------------------------------------------------------------------*/ + +#include + +/*-------------------------------------------------------------------------*/ + +#define QTD_NEXT(ehci, dma) cpu_to_hc32(ehci, (u32)dma) + +/* + * EHCI Specification 0.95 Section 3.5 + * QTD: describe data transfer components (buffer, direction, ...) + * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". + * + * These are associated only with "QH" (Queue Head) structures, + * used with control, bulk, and interrupt transfers. + */ +struct ehci_qtd { + /* first part defined by EHCI spec */ + __hc32 hw_next; /* see EHCI 3.5.1 */ + __hc32 hw_alt_next; /* see EHCI 3.5.2 */ + __hc32 hw_token; /* see EHCI 3.5.3 */ +#define QTD_TOGGLE (1 << 31) /* data toggle */ +#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) +#define QTD_IOC (1 << 15) /* interrupt on complete */ +#define QTD_CERR(tok) (((tok)>>10) & 0x3) +#define QTD_PID(tok) (((tok)>>8) & 0x3) +#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ +#define QTD_STS_HALT (1 << 6) /* halted on error */ +#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ +#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ +#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ +#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ +#define QTD_STS_STS (1 << 1) /* split transaction state */ +#define QTD_STS_PING (1 << 0) /* issue PING? */ + +#define ACTIVE_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_ACTIVE) +#define HALT_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_HALT) +#define STATUS_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_STS) + + __hc32 hw_buf[5]; /* see EHCI 3.5.4 */ + __hc32 hw_buf_hi[5]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t qtd_dma; /* qtd address */ + struct list_head qtd_list; /* sw qtd list */ + struct urb *urb; /* qtd's urb */ + size_t length; /* length of buffer */ +} __aligned(32); + +/* mask NakCnt+T in qh->hw_alt_next */ +#define QTD_MASK(ehci) cpu_to_hc32(ehci, ~0x1f) + +#define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) + +/*-------------------------------------------------------------------------*/ + +/* type tag from {qh,itd,sitd,fstn}->hw_next */ +#define Q_NEXT_TYPE(ehci, dma) ((dma) & cpu_to_hc32(ehci, 3 << 1)) + +/* + * Now the following defines are not converted using the + * cpu_to_le32() macro anymore, since we have to support + * "dynamic" switching between be and le support, so that the driver + * can be used on one system with SoC EHCI controller using big-endian + * descriptors as well as a normal little-endian PCI EHCI controller. + */ +/* values for that type tag */ +#define Q_TYPE_ITD (0 << 1) +#define Q_TYPE_QH (1 << 1) +#define Q_TYPE_SITD (2 << 1) +#define Q_TYPE_FSTN (3 << 1) + +/* next async queue entry, or pointer to interrupt/periodic QH */ +#define QH_NEXT(ehci, dma) \ + (cpu_to_hc32(ehci, (((u32) dma) & ~0x01f) | Q_TYPE_QH)) + +/* for periodic/async schedules and qtd lists, mark end of list */ +#define EHCI_LIST_END(ehci) cpu_to_hc32(ehci, 1) /* "null pointer" to hw */ + +/* + * Entries in periodic shadow table are pointers to one of four kinds + * of data structure. That's dictated by the hardware; a type tag is + * encoded in the low bits of the hardware's periodic schedule. Use + * Q_NEXT_TYPE to get the tag. + * + * For entries in the async schedule, the type tag always says "qh". + */ +union ehci_shadow { + struct ehci_qh *qh; /* Q_TYPE_QH */ + struct ehci_itd *itd; /* Q_TYPE_ITD */ + struct ehci_sitd *sitd; /* Q_TYPE_SITD */ + struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ + __hc32 *hw_next; /* (all types) */ + void *ptr; +}; + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.95 Section 3.6 + * QH: describes control/bulk/interrupt endpoints + * See Fig 3-7 "Queue Head Structure Layout". + * + * These appear in both the async and (for interrupt) periodic schedules. + */ + +/* first part defined by EHCI spec */ +struct ehci_qh_hw { + __hc32 hw_next; /* see EHCI 3.6.1 */ + __hc32 hw_info1; /* see EHCI 3.6.2 */ +#define QH_CONTROL_EP (1 << 27) /* FS/LS control endpoint */ +#define QH_HEAD (1 << 15) /* Head of async reclamation list */ +#define QH_TOGGLE_CTL (1 << 14) /* Data toggle control */ +#define QH_HIGH_SPEED (2 << 12) /* Endpoint speed */ +#define QH_LOW_SPEED (1 << 12) +#define QH_FULL_SPEED (0 << 12) +#define QH_INACTIVATE (1 << 7) /* Inactivate on next transaction */ + __hc32 hw_info2; /* see EHCI 3.6.2 */ +#define QH_SMASK 0x000000ff +#define QH_CMASK 0x0000ff00 +#define QH_HUBADDR 0x007f0000 +#define QH_HUBPORT 0x3f800000 +#define QH_MULT 0xc0000000 + __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */ + + /* qtd overlay (hardware parts of a struct ehci_qtd) */ + __hc32 hw_qtd_next; + __hc32 hw_alt_next; + __hc32 hw_token; + __hc32 hw_buf[5]; + __hc32 hw_buf_hi[5]; +} __aligned(32); + +struct ehci_qh { + struct ehci_qh_hw *hw; /* Must come first */ + /* the rest is HCD-private */ + dma_addr_t qh_dma; /* address of qh */ + union ehci_shadow qh_next; /* ptr to qh; or periodic */ + struct list_head qtd_list; /* sw qtd list */ + struct list_head intr_node; /* list of intr QHs */ + struct ehci_qtd *dummy; + struct list_head unlink_node; + struct ehci_per_sched ps; /* scheduling info */ + + unsigned unlink_cycle; + + u8 qh_state; +#define QH_STATE_LINKED 1 /* HC sees this */ +#define QH_STATE_UNLINK 2 /* HC may still see this */ +#define QH_STATE_IDLE 3 /* HC doesn't see this */ +#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on unlink q */ +#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ + + u8 xacterrs; /* XactErr retry counter */ +#define QH_XACTERR_MAX 32 /* XactErr retry limit */ + + u8 unlink_reason; +#define QH_UNLINK_HALTED 0x01 /* Halt flag is set */ +#define QH_UNLINK_SHORT_READ 0x02 /* Recover from a short read */ +#define QH_UNLINK_DUMMY_OVERLAY 0x04 /* QH overlayed the dummy TD */ +#define QH_UNLINK_SHUTDOWN 0x08 /* The HC isn't running */ +#define QH_UNLINK_QUEUE_EMPTY 0x10 /* Reached end of the queue */ +#define QH_UNLINK_REQUESTED 0x20 /* Disable, reset, or dequeue */ + + u8 gap_uf; /* uframes split/csplit gap */ + + unsigned is_out:1; /* bulk or intr OUT */ + unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ + unsigned dequeue_during_giveback:1; + unsigned should_be_inactive:1; +}; + +/*-------------------------------------------------------------------------*/ + +/* description of one iso transaction (up to 3 KB data if highspeed) */ +struct ehci_iso_packet { + /* These will be copied to iTD when scheduling */ + u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ + __hc32 transaction; /* itd->hw_transaction[i] |= */ + u8 cross; /* buf crosses pages */ + /* for full speed OUT splits */ + u32 buf1; +}; + +/* temporary schedule data for packets from iso urbs (both speeds) + * each packet is one logical usb transaction to the device (not TT), + * beginning at stream->next_uframe + */ +struct ehci_iso_sched { + struct list_head td_list; + unsigned span; + unsigned first_packet; + struct ehci_iso_packet packet[0]; +}; + +/* + * ehci_iso_stream - groups all (s)itds for this endpoint. + * acts like a qh would, if EHCI had them for ISO. + */ +struct ehci_iso_stream { + /* first field matches ehci_hq, but is NULL */ + struct ehci_qh_hw *hw; + + u8 bEndpointAddress; + u8 highspeed; + struct list_head td_list; /* queued itds/sitds */ + struct list_head free_list; /* list of unused itds/sitds */ + + /* output of (re)scheduling */ + struct ehci_per_sched ps; /* scheduling info */ + unsigned next_uframe; + __hc32 splits; + + /* the rest is derived from the endpoint descriptor, + * including the extra info for hw_bufp[0..2] + */ + u16 uperiod; /* period in uframes */ + u16 maxp; + unsigned bandwidth; + + /* This is used to initialize iTD's hw_bufp fields */ + __hc32 buf0; + __hc32 buf1; + __hc32 buf2; + + /* this is used to initialize sITD's tt info */ + __hc32 address; +}; + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.95 Section 3.3 + * Fig 3-4 "Isochronous Transaction Descriptor (iTD)" + * + * Schedule records for high speed iso xfers + */ +struct ehci_itd { + /* first part defined by EHCI spec */ + __hc32 hw_next; /* see EHCI 3.3.1 */ + __hc32 hw_transaction[8]; /* see EHCI 3.3.2 */ +#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ +#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ +#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ +#define EHCI_ISOC_XACTERR (1<<28) /* XactErr - transaction error */ +#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff) +#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */ + +#define ITD_ACTIVE(ehci) cpu_to_hc32(ehci, EHCI_ISOC_ACTIVE) + + __hc32 hw_bufp[7]; /* see EHCI 3.3.3 */ + __hc32 hw_bufp_hi[7]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t itd_dma; /* for this itd */ + union ehci_shadow itd_next; /* ptr to periodic q entry */ + + struct urb *urb; + struct ehci_iso_stream *stream; /* endpoint's queue */ + struct list_head itd_list; /* list of stream's itds */ + + /* any/all hw_transactions here may be used by that urb */ + unsigned frame; /* where scheduled */ + unsigned pg; + unsigned index[8]; /* in urb->iso_frame_desc */ +} __aligned(32); + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.95 Section 3.4 + * siTD, aka split-transaction isochronous Transfer Descriptor + * ... describe full speed iso xfers through TT in hubs + * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD) + */ +struct ehci_sitd { + /* first part defined by EHCI spec */ + __hc32 hw_next; +/* uses bit field macros above - see EHCI 0.95 Table 3-8 */ + __hc32 hw_fullspeed_ep; /* EHCI table 3-9 */ + __hc32 hw_uframe; /* EHCI table 3-10 */ + __hc32 hw_results; /* EHCI table 3-11 */ +#define SITD_IOC (1 << 31) /* interrupt on completion */ +#define SITD_PAGE (1 << 30) /* buffer 0/1 */ +#define SITD_LENGTH(x) (((x) >> 16) & 0x3ff) +#define SITD_STS_ACTIVE (1 << 7) /* HC may execute this */ +#define SITD_STS_ERR (1 << 6) /* error from TT */ +#define SITD_STS_DBE (1 << 5) /* data buffer error (in HC) */ +#define SITD_STS_BABBLE (1 << 4) /* device was babbling */ +#define SITD_STS_XACT (1 << 3) /* illegal IN response */ +#define SITD_STS_MMF (1 << 2) /* incomplete split transaction */ +#define SITD_STS_STS (1 << 1) /* split transaction state */ + +#define SITD_ACTIVE(ehci) cpu_to_hc32(ehci, SITD_STS_ACTIVE) + + __hc32 hw_buf[2]; /* EHCI table 3-12 */ + __hc32 hw_backpointer; /* EHCI table 3-13 */ + __hc32 hw_buf_hi[2]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t sitd_dma; + union ehci_shadow sitd_next; /* ptr to periodic q entry */ + + struct urb *urb; + struct ehci_iso_stream *stream; /* endpoint's queue */ + struct list_head sitd_list; /* list of stream's sitds */ + unsigned frame; + unsigned index; +} __aligned(32); + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.96 Section 3.7 + * Periodic Frame Span Traversal Node (FSTN) + * + * Manages split interrupt transactions (using TT) that span frame boundaries + * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN + * makes the HC jump (back) to a QH to scan for fs/ls QH completions until + * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. + */ +struct ehci_fstn { + __hc32 hw_next; /* any periodic q entry */ + __hc32 hw_prev; /* qh or EHCI_LIST_END */ + + /* the rest is HCD-private */ + dma_addr_t fstn_dma; + union ehci_shadow fstn_next; /* ptr to periodic q entry */ +} __aligned(32); + +/*-------------------------------------------------------------------------*/ + +/* + * USB-2.0 Specification Sections 11.14 and 11.18 + * Scheduling and budgeting split transactions using TTs + * + * A hub can have a single TT for all its ports, or multiple TTs (one for each + * port). The bandwidth and budgeting information for the full/low-speed bus + * below each TT is self-contained and independent of the other TTs or the + * high-speed bus. + * + * "Bandwidth" refers to the number of microseconds on the FS/LS bus allocated + * to an interrupt or isochronous endpoint for each frame. "Budget" refers to + * the best-case estimate of the number of full-speed bytes allocated to an + * endpoint for each microframe within an allocated frame. + * + * Removal of an endpoint invalidates a TT's budget. Instead of trying to + * keep an up-to-date record, we recompute the budget when it is needed. + */ + +struct ehci_tt { + u16 bandwidth[EHCI_BANDWIDTH_FRAMES]; + + struct list_head tt_list; /* List of all ehci_tt's */ + struct list_head ps_list; /* Items using this TT */ + struct usb_tt *usb_tt; + int tt_port; /* TT port number */ +}; + +/*-------------------------------------------------------------------------*/ + +/* Prepare the PORTSC wakeup flags during controller suspend/resume */ + +#define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup) \ + ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup) + +#define ehci_prepare_ports_for_controller_resume(ehci) \ + ehci_adjust_port_wakeup_flags(ehci, false, false) + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT + +/* + * Some EHCI controllers have a Transaction Translator built into the + * root hub. This is a non-standard feature. Each controller will need + * to add code to the following inline functions, and call them as + * needed (mostly in root hub code). + */ + +#define ehci_is_TDI(e) (ehci_to_hcd(e)->has_tt) + +/* Returns the speed of a device attached to a port on the root hub. */ +static inline unsigned int +ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) +{ + if (ehci_is_TDI(ehci)) { + switch ((portsc >> (ehci->has_hostpc ? 25 : 26)) & 3) { + case 0: + return 0; + case 1: + return USB_PORT_STAT_LOW_SPEED; + case 2: + default: + return USB_PORT_STAT_HIGH_SPEED; + } + } + return USB_PORT_STAT_HIGH_SPEED; +} + +#else + +#define ehci_is_TDI(e) (0) + +#define ehci_port_speed(ehci, portsc) USB_PORT_STAT_HIGH_SPEED +#endif + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_PPC_83xx +/* Some Freescale processors have an erratum in which the TT + * port number in the queue head was 0..N-1 instead of 1..N. + */ +#define ehci_has_fsl_portno_bug(e) ((e)->has_fsl_port_bug) +#else +#define ehci_has_fsl_portno_bug(e) (0) +#endif + +#define PORTSC_FSL_PFSC 24 /* Port Force Full-Speed Connect */ + +#if defined(CONFIG_PPC_85xx) +/* Some Freescale processors have an erratum (USB A-005275) in which + * incoming packets get corrupted in HS mode + */ +#define ehci_has_fsl_hs_errata(e) ((e)->has_fsl_hs_errata) +#else +#define ehci_has_fsl_hs_errata(e) (0) +#endif + +/* + * Some Freescale/NXP processors have an erratum (USB A-005697) + * in which we need to wait for 10ms for bus to enter suspend mode + * after setting SUSP bit. + */ +#define ehci_has_fsl_susp_errata(e) ((e)->has_fsl_susp_errata) + +/* + * While most USB host controllers implement their registers in + * little-endian format, a minority (celleb companion chip) implement + * them in big endian format. + * + * This attempts to support either format at compile time without a + * runtime penalty, or both formats with the additional overhead + * of checking a flag bit. + * + * ehci_big_endian_capbase is a special quirk for controllers that + * implement the HC capability registers as separate registers and not + * as fields of a 32-bit register. + */ + +#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO +#define ehci_big_endian_mmio(e) ((e)->big_endian_mmio) +#define ehci_big_endian_capbase(e) ((e)->big_endian_capbase) +#else +#define ehci_big_endian_mmio(e) 0 +#define ehci_big_endian_capbase(e) 0 +#endif + +/* + * Big-endian read/write functions are arch-specific. + * Other arches can be added if/when they're needed. + */ +#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_IXP4XX) +#define readl_be(addr) __raw_readl((__force unsigned *)addr) +#define writel_be(val, addr) __raw_writel(val, (__force unsigned *)addr) +#endif + +static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, + __u32 __iomem *regs) +{ +#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO + return ehci_big_endian_mmio(ehci) ? + readl_be(regs) : + readl(regs); +#else + return readl(regs); +#endif +} + +#ifdef CONFIG_SOC_IMX28 +static inline void imx28_ehci_writel(const unsigned int val, + volatile __u32 __iomem *addr) +{ + __asm__ ("swp %0, %0, [%1]" : : "r"(val), "r"(addr)); +} +#else +static inline void imx28_ehci_writel(const unsigned int val, + volatile __u32 __iomem *addr) +{ +} +#endif +static inline void ehci_writel(const struct ehci_hcd *ehci, + const unsigned int val, __u32 __iomem *regs) +{ +#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO + ehci_big_endian_mmio(ehci) ? + writel_be(val, regs) : + writel(val, regs); +#else + if (ehci->imx28_write_fix) + imx28_ehci_writel(val, regs); + else + writel(val, regs); +#endif +} + +/* + * On certain ppc-44x SoC there is a HW issue, that could only worked around with + * explicit suspend/operate of OHCI. This function hereby makes sense only on that arch. + * Other common bits are dependent on has_amcc_usb23 quirk flag. + */ +#ifdef CONFIG_44x +static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) +{ + u32 hc_control; + + hc_control = (readl_be(ehci->ohci_hcctrl_reg) & ~OHCI_CTRL_HCFS); + if (operational) + hc_control |= OHCI_USB_OPER; + else + hc_control |= OHCI_USB_SUSPEND; + + writel_be(hc_control, ehci->ohci_hcctrl_reg); + (void) readl_be(ehci->ohci_hcctrl_reg); +} +#else +static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) +{ } +#endif + +/*-------------------------------------------------------------------------*/ + +/* + * The AMCC 440EPx not only implements its EHCI registers in big-endian + * format, but also its DMA data structures (descriptors). + * + * EHCI controllers accessed through PCI work normally (little-endian + * everywhere), so we won't bother supporting a BE-only mode for now. + */ +#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC +#define ehci_big_endian_desc(e) ((e)->big_endian_desc) + +/* cpu to ehci */ +static inline __hc32 cpu_to_hc32(const struct ehci_hcd *ehci, const u32 x) +{ + return ehci_big_endian_desc(ehci) + ? (__force __hc32)cpu_to_be32(x) + : (__force __hc32)cpu_to_le32(x); +} + +/* ehci to cpu */ +static inline u32 hc32_to_cpu(const struct ehci_hcd *ehci, const __hc32 x) +{ + return ehci_big_endian_desc(ehci) + ? be32_to_cpu((__force __be32)x) + : le32_to_cpu((__force __le32)x); +} + +static inline u32 hc32_to_cpup(const struct ehci_hcd *ehci, const __hc32 *x) +{ + return ehci_big_endian_desc(ehci) + ? be32_to_cpup((__force __be32 *)x) + : le32_to_cpup((__force __le32 *)x); +} + +#else + +/* cpu to ehci */ +static inline __hc32 cpu_to_hc32(const struct ehci_hcd *ehci, const u32 x) +{ + return cpu_to_le32(x); +} + +/* ehci to cpu */ +static inline u32 hc32_to_cpu(const struct ehci_hcd *ehci, const __hc32 x) +{ + return le32_to_cpu(x); +} + +static inline u32 hc32_to_cpup(const struct ehci_hcd *ehci, const __hc32 *x) +{ + return le32_to_cpup(x); +} + +#endif + +/*-------------------------------------------------------------------------*/ + +#define ehci_dbg(ehci, fmt, args...) \ + dev_dbg(ehci_to_hcd(ehci)->self.controller, fmt, ## args) +#define ehci_err(ehci, fmt, args...) \ + dev_err(ehci_to_hcd(ehci)->self.controller, fmt, ## args) +#define ehci_info(ehci, fmt, args...) \ + dev_info(ehci_to_hcd(ehci)->self.controller, fmt, ## args) +#define ehci_warn(ehci, fmt, args...) \ + dev_warn(ehci_to_hcd(ehci)->self.controller, fmt, ## args) + +/*-------------------------------------------------------------------------*/ + +/* Declarations of things exported for use by ehci platform drivers */ + +struct ehci_driver_overrides { + size_t extra_priv_size; + int (*reset)(struct usb_hcd *hcd); + int (*port_power)(struct usb_hcd *hcd, + int portnum, bool enable); +}; + +extern void ehci_init_driver(struct hc_driver *drv, + const struct ehci_driver_overrides *over); +extern int ehci_setup(struct usb_hcd *hcd); +extern int ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr, + u32 mask, u32 done, int usec); +extern int ehci_reset(struct ehci_hcd *ehci); + +extern int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup); +extern int ehci_resume(struct usb_hcd *hcd, bool force_reset); +extern void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, + bool suspending, bool do_wakeup); + +extern int ehci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + u16 wIndex, char *buf, u16 wLength); + +#endif /* __LINUX_EHCI_HCD_H */ diff --git a/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/Makefile b/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/Makefile new file mode 100644 index 000000000000..52d73b89e5a6 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/Makefile @@ -0,0 +1 @@ +obj-m = gpio-ctc.o diff --git a/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/gpio-ctc.c b/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/gpio-ctc.c new file mode 100644 index 000000000000..de310e02d210 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/gpio-ctc.c @@ -0,0 +1,558 @@ +/* + * Copyright (c) 2018 Liuht + * + * 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. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gpio-ctcapb.h" +#include +#include "gpiolib.h" + +#define DWAPB_MAX_PORTS 2 + +struct ctcapb_gpio; + +struct ctcapb_gpio_port { + bool is_registered; + unsigned int idx; + struct gpio_chip gc; + struct ctcapb_gpio *gpio; + struct GpioSoc_port_regs *regs; + struct irq_domain *domain; +}; + +struct ctcapb_gpio { + struct device *dev; + unsigned int nr_ports; + struct GpioSoc_regs *regs; + struct ctcapb_gpio_port *ports; +}; + +static void clrsetbits(unsigned __iomem *addr, u32 clr, u32 set) +{ + writel((readl(addr) & ~(clr)) | (set), addr); +} + +static int ctcapb_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) +{ + struct ctcapb_gpio_port *port = gpiochip_get_data(gc); + + return irq_find_mapping(port->domain, offset); +} + +static void ctcapb_toggle_trigger(struct ctcapb_gpio_port *port, + unsigned int offs) +{ + u32 v = readl(&port->regs->GpioIntrPolarity); + + if (gpio_get_value(port->gc.base + offs)) + v &= ~BIT(offs); + else + v |= BIT(offs); + + writel(v, &port->regs->GpioIntrPolarity); +} + +static u32 ctcapb_do_irq(struct ctcapb_gpio_port *port) +{ + u32 irq_status = readl_relaxed(&port->regs->GpioIntrStatus); + u32 ret = irq_status; + + while (irq_status) { + int hwirq = fls(irq_status) - 1; + int gpio_irq = irq_find_mapping(port->domain, hwirq); + + generic_handle_irq(gpio_irq); + irq_status &= ~BIT(hwirq); + + if ((irq_get_trigger_type(gpio_irq) & IRQ_TYPE_SENSE_MASK) + == IRQ_TYPE_EDGE_BOTH) + ctcapb_toggle_trigger(port, hwirq); + } + + return ret; +} + +static void ctcapb_irq_handler(struct irq_desc *desc) +{ + struct ctcapb_gpio_port *port = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + + ctcapb_do_irq(port); + + if (chip->irq_eoi) + chip->irq_eoi(irq_desc_get_irq_data(desc)); +} + +static void ctcapb_irq_enable(struct irq_data *d) +{ + struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); + struct ctcapb_gpio_port *port = igc->private; + struct gpio_chip *gc = &port->gc; + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + clrsetbits(&port->regs->GpioIntrEn, 0, BIT(d->hwirq)); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +extern void irq_gc_mask_clr_bit(struct irq_data *d); + +static void ctcapb_irq_unmask(struct irq_data *d) +{ + irq_gc_mask_clr_bit(d); + ctcapb_irq_enable(d); +} + +static int ctcapb_irq_reqres(struct irq_data *d) +{ + struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); + struct ctcapb_gpio_port *port = igc->private; + struct gpio_chip *gc = &port->gc; + + if (gpiochip_lock_as_irq(gc, irqd_to_hwirq(d))) { + dev_err(port->gpio->dev, "unable to lock HW IRQ %lu for IRQ\n", + irqd_to_hwirq(d)); + return -EINVAL; + } + return 0; +} + +static void ctcapb_irq_relres(struct irq_data *d) +{ + struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); + struct ctcapb_gpio_port *port = igc->private; + struct gpio_chip *gc = &port->gc; + + gpiochip_unlock_as_irq(gc, irqd_to_hwirq(d)); +} + +static int ctcapb_irq_set_type(struct irq_data *d, u32 type) +{ + struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); + struct ctcapb_gpio_port *port = igc->private; + struct gpio_chip *gc = &port->gc; + int bit = d->hwirq; + unsigned long level, polarity, flags; + + if (type & ~(IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | + IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) + return -EINVAL; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + level = readl(&port->regs->GpioIntrLevel); + polarity = readl(&port->regs->GpioIntrPolarity); + + switch (type) { + case IRQ_TYPE_EDGE_BOTH: + level &= ~BIT(bit); + ctcapb_toggle_trigger(port, bit); + break; + case IRQ_TYPE_EDGE_RISING: + level &= ~BIT(bit); + polarity |= BIT(bit); + break; + case IRQ_TYPE_EDGE_FALLING: + level &= ~BIT(bit); + polarity &= ~BIT(bit); + break; + case IRQ_TYPE_LEVEL_HIGH: + level |= BIT(bit); + polarity |= BIT(bit); + break; + case IRQ_TYPE_LEVEL_LOW: + level |= BIT(bit); + polarity &= ~BIT(bit); + break; + } + + irq_setup_alt_chip(d, type); + + writel(level, &port->regs->GpioIntrLevel); + writel(polarity, &port->regs->GpioIntrPolarity); + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; +} + +static int ctcapb_gpio_set_debounce(struct gpio_chip *gc, + unsigned int offset, unsigned int debounce) +{ + struct ctcapb_gpio_port *port = gpiochip_get_data(gc); + unsigned long flags, val_deb; + unsigned long mask = BIT(offset); + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + val_deb = readl(&port->regs->GpioDebCtl); + if (debounce) + writel(val_deb | mask, &port->regs->GpioDebCtl); + else + writel(val_deb & ~mask, &port->regs->GpioDebCtl); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; +} + +static int ctc_gpio_set_config(struct gpio_chip *gc, unsigned int offset, + unsigned long config) +{ + u32 debounce; + + if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE) + return -ENOTSUPP; + + debounce = pinconf_to_config_argument(config); + return ctcapb_gpio_set_debounce(gc, offset, debounce); +} + +static irqreturn_t ctcapb_irq_handler_mfd(int irq, void *dev_id) +{ + u32 worked; + struct ctcapb_gpio_port *port = dev_id; + + worked = ctcapb_do_irq(port); + + return worked ? IRQ_HANDLED : IRQ_NONE; +} + +static void ctcapb_configure_irqs(struct ctcapb_gpio_port *port, + struct ctcapb_port_property *pp) +{ + struct gpio_chip *gc = &port->gc; + struct fwnode_handle *fwnode = pp->fwnode; + struct irq_chip_generic *irq_gc = NULL; + unsigned int hwirq, ngpio = gc->ngpio; + struct irq_chip_type *ct; + int err, i; + + port->domain = irq_domain_create_linear(fwnode, ngpio, + &irq_generic_chip_ops, port); + if (!port->domain) + return; + + err = irq_alloc_domain_generic_chips(port->domain, ngpio, 2, + "gpio-ctcapb", handle_level_irq, + IRQ_NOREQUEST, 0, + IRQ_GC_INIT_NESTED_LOCK); + if (err) { + dev_info(port->gpio->dev, + "irq_alloc_domain_generic_chips failed\n"); + irq_domain_remove(port->domain); + port->domain = NULL; + return; + } + + irq_gc = irq_get_domain_generic_chip(port->domain, 0); + if (!irq_gc) { + irq_domain_remove(port->domain); + port->domain = NULL; + return; + } + + irq_gc->reg_base = port->regs; + irq_gc->private = port; + + for (i = 0; i < 2; i++) { + ct = &irq_gc->chip_types[i]; + ct->chip.irq_ack = irq_gc_ack_set_bit; + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = ctcapb_irq_unmask; + ct->chip.irq_set_type = ctcapb_irq_set_type; + //ct->chip.irq_enable = ctcapb_irq_enable; + //ct->chip.irq_disable = ctcapb_irq_disable; + ct->chip.irq_request_resources = ctcapb_irq_reqres; + ct->chip.irq_release_resources = ctcapb_irq_relres; + ct->regs.ack = + (&port->regs->GpioEoiCtl - &port->regs->GpioDataCtl) * 4; + ct->regs.mask = + (&port->regs->GpioIntrMask - &port->regs->GpioDataCtl) * 4; + ct->type = IRQ_TYPE_LEVEL_MASK; + } + + irq_gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK; + irq_gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH; + irq_gc->chip_types[1].handler = handle_edge_irq; + + if (!pp->irq_shared) { + irq_set_chained_handler_and_data(pp->irq, ctcapb_irq_handler, + port); + } else { + /* + * Request a shared IRQ since where MFD would have devices + * using the same irq pin + */ + err = devm_request_irq(port->gpio->dev, pp->irq, + ctcapb_irq_handler_mfd, + IRQF_SHARED, "gpio-ctcapb-mfd", port); + if (err) { + dev_err(port->gpio->dev, "error requesting IRQ\n"); + irq_domain_remove(port->domain); + port->domain = NULL; + return; + } + } + + for (hwirq = 0; hwirq < ngpio; hwirq++) + irq_create_mapping(port->domain, hwirq); + + port->gc.to_irq = ctcapb_gpio_to_irq; +} + +static void ctcapb_irq_teardown(struct ctcapb_gpio_port *port) +{ + struct gpio_chip *gc = &port->gc; + unsigned int ngpio = gc->ngpio; + irq_hw_number_t hwirq; + + if (!port->domain) + return; + + for (hwirq = 0; hwirq < ngpio; hwirq++) + irq_dispose_mapping(irq_find_mapping(port->domain, hwirq)); + + irq_domain_remove(port->domain); + port->domain = NULL; +} + +static int ctcapb_gpio_add_port(struct ctcapb_gpio *gpio, + struct ctcapb_port_property *pp, + unsigned int offs) +{ + struct ctcapb_gpio_port *port; + void __iomem *dat, *set, *dirout; + int err; + + port = &gpio->ports[offs]; + port->gpio = gpio; + port->idx = pp->idx; + + if (port->idx == 0) { + dat = &gpio->regs->GpioReadData; + set = &gpio->regs->GpioDataCtl; + dirout = &gpio->regs->GpioOutCtl; + port->regs = + (struct GpioSoc_port_regs *)&gpio->regs->GpioDataCtl; + } else { + dat = &gpio->regs->GpioHsReadData; + set = &gpio->regs->GpioHsDataCtl; + dirout = &gpio->regs->GpioHsOutCtl; + port->regs = + (struct GpioSoc_port_regs *)&gpio->regs->GpioHsDataCtl; + } + + err = bgpio_init(&port->gc, gpio->dev, 4, dat, set, NULL, dirout, + NULL, false); + if (err) { + dev_err(gpio->dev, "failed to init gpio chip for port%d\n", + port->idx); + return err; + } +#ifdef CONFIG_OF_GPIO + port->gc.of_node = to_of_node(pp->fwnode); +#endif + port->gc.ngpio = pp->ngpio; + port->gc.base = pp->gpio_base; + port->gc.set_config = ctc_gpio_set_config; + + if (pp->irq) + ctcapb_configure_irqs(port, pp); + + err = gpiochip_add_data(&port->gc, port); + if (err) + dev_err(gpio->dev, "failed to register gpiochip for port%d\n", + port->idx); + else + port->is_registered = true; + + /* Add GPIO-signaled ACPI event support */ + if (pp->irq) + acpi_gpiochip_request_interrupts(&port->gc); + + return err; +} + +static void ctcapb_gpio_unregister(struct ctcapb_gpio *gpio) +{ + unsigned int m; + + for (m = 0; m < gpio->nr_ports; ++m) + if (gpio->ports[m].is_registered) + gpiochip_remove(&gpio->ports[m].gc); +} + +static struct ctcapb_platform_data *ctcapb_gpio_get_pdata(struct device *dev) +{ + struct fwnode_handle *fwnode; + struct ctcapb_platform_data *pdata; + struct ctcapb_port_property *pp; + int nports; + int i; + + nports = device_get_child_node_count(dev); + if (nports == 0) + return ERR_PTR(-ENODEV); + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + pdata->properties = devm_kcalloc(dev, nports, sizeof(*pp), GFP_KERNEL); + if (!pdata->properties) + return ERR_PTR(-ENOMEM); + + pdata->nports = nports; + + i = 0; + device_for_each_child_node(dev, fwnode) { + pp = &pdata->properties[i++]; + pp->fwnode = fwnode; + + if (fwnode_property_read_u32(fwnode, "reg", &pp->idx) || + pp->idx >= DWAPB_MAX_PORTS) { + dev_err(dev, + "missing/invalid port index for port%d\n", i); + fwnode_handle_put(fwnode); + return ERR_PTR(-EINVAL); + } + + if (fwnode_property_read_u32(fwnode, "ctc,nr-gpios", + &pp->ngpio)) { + dev_info(dev, + "failed to get number of gpios for port%d\n", + i); + pp->ngpio = 32; + } + + if (dev->of_node && fwnode_property_read_bool(fwnode, + "interrupt-controller")) { + pp->irq = irq_of_parse_and_map(to_of_node(fwnode), 0); + if (!pp->irq) + dev_warn(dev, "no irq for port%d\n", pp->idx); + } + + if (has_acpi_companion(dev) && pp->idx == 0) + pp->irq = platform_get_irq(to_platform_device(dev), 0); + + pp->irq_shared = false; + pp->gpio_base = -1; + } + + return pdata; +} + +static int ctcapb_gpio_probe(struct platform_device *pdev) +{ + unsigned int i; + struct resource *res; + struct ctcapb_gpio *gpio; + int err; + struct device *dev = &pdev->dev; + struct ctcapb_platform_data *pdata = dev_get_platdata(dev); + + if (!pdata) { + pdata = ctcapb_gpio_get_pdata(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + } + + if (!pdata->nports) + return -ENODEV; + + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) + return -ENOMEM; + + gpio->dev = &pdev->dev; + gpio->nr_ports = pdata->nports; + + gpio->ports = devm_kcalloc(&pdev->dev, gpio->nr_ports, + sizeof(*gpio->ports), GFP_KERNEL); + if (!gpio->ports) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + gpio->regs = + (struct GpioSoc_regs *)devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(gpio->regs)) + return PTR_ERR(gpio->regs); + + for (i = 0; i < gpio->nr_ports; i++) { + err = ctcapb_gpio_add_port(gpio, &pdata->properties[i], i); + if (err) + goto out_unregister; + } + platform_set_drvdata(pdev, gpio); + + return 0; + +out_unregister: + ctcapb_gpio_unregister(gpio); + for (i = 0; i < gpio->nr_ports; i++) + ctcapb_irq_teardown(&gpio->ports[i]); + + return err; +} + +static int ctcapb_gpio_remove(struct platform_device *pdev) +{ + int i; + struct ctcapb_gpio *gpio = platform_get_drvdata(pdev); + + ctcapb_gpio_unregister(gpio); + for (i = 0; i < gpio->nr_ports; i++) + ctcapb_irq_teardown(&gpio->ports[i]); + + return 0; +} + +static const struct of_device_id ctcapb_of_match[] = { + {.compatible = "ctc,apb-gpio"}, + { /* Sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, ctcapb_of_match); + +static const struct acpi_device_id ctcapb_acpi_match[] = { + {"HISI0181", 0}, + {"APMC0D07", 0}, + {} +}; + +MODULE_DEVICE_TABLE(acpi, ctcapb_acpi_match); + +static struct platform_driver ctcapb_gpio_driver = { + .driver = { + .name = "gpio-ctcapb", + .of_match_table = of_match_ptr(ctcapb_of_match), + .acpi_match_table = ACPI_PTR(ctcapb_acpi_match), + }, + .probe = ctcapb_gpio_probe, + .remove = ctcapb_gpio_remove, +}; + +module_platform_driver(ctcapb_gpio_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Liuht"); +MODULE_DESCRIPTION("Centec APB GPIO driver"); diff --git a/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/gpio-ctcapb.h b/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/gpio-ctcapb.h new file mode 100644 index 000000000000..7be811afa48c --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/gpio-ctcapb.h @@ -0,0 +1,75 @@ +/* + * Copyright(c) 2014 Intel Corporation. + * + * 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. + */ + +#ifndef GPIO_CTC_APB_H +#define GPIO_CTC_APB_H + +struct ctcapb_port_property { + struct fwnode_handle *fwnode; + unsigned int idx; + unsigned int ngpio; + unsigned int gpio_base; + unsigned int irq; + bool irq_shared; +}; + +struct ctcapb_platform_data { + struct ctcapb_port_property *properties; + unsigned int nports; +}; + +struct GpioSoc_regs { + u32 GpioDataCtl; /* 0x00000000 */ + u32 GpioOutCtl; /* 0x00000004 */ + u32 GpioDebCtl; /* 0x00000008 */ + u32 GpioReadData; /* 0x0000000c */ + u32 GpioIntrEn; /* 0x00000010 */ + u32 GpioIntrMask; /* 0x00000014 */ + u32 GpioIntrLevel; /* 0x00000018 */ + u32 GpioIntrPolarity; /* 0x0000001c */ + u32 GpioIntrStatus; /* 0x00000020 */ + u32 GpioIntrRaw; /* 0x00000024 */ + u32 GpioEoiCtl; /* 0x00000028 */ + u32 rsv11; + u32 GpioDebCnt; /* 0x00000030 */ + u32 GpioVerId; /* 0x00000034 */ + u32 rsv14; + u32 rsv15; + u32 GpioHsDataCtl; /* 0x00000040 */ + u32 GpioHsOutCtl; /* 0x00000044 */ + u32 GpioHsDebCtl; /* 0x00000048 */ + u32 GpioHsReadData; /* 0x0000004c */ + u32 GpioHsIntrEn; /* 0x00000050 */ + u32 GpioHsIntrMask; /* 0x00000054 */ + u32 GpioHsIntrLevel; /* 0x00000058 */ + u32 GpioHsIntrPolarity; /* 0x0000005c */ + u32 GpioHsIntrStatus; /* 0x00000060 */ + u32 GpioHsIntrRaw; /* 0x00000064 */ + u32 GpioHsEoiCtl; /* 0x00000068 */ +}; + +struct GpioSoc_port_regs { + u32 GpioDataCtl; + u32 GpioOutCtl; + u32 GpioDebCtl; + u32 GpioReadData; + u32 GpioIntrEn; + u32 GpioIntrMask; + u32 GpioIntrLevel; + u32 GpioIntrPolarity; + u32 GpioIntrStatus; + u32 GpioIntrRaw; + u32 GpioEoiCtl; +}; + +#endif diff --git a/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/gpiolib.h b/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/gpiolib.h new file mode 100644 index 000000000000..a7e49fef73d4 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/gpio-ctc/gpiolib.h @@ -0,0 +1,298 @@ +/* + * Internal GPIO functions. + * + * Copyright (C) 2013, Intel Corporation + * Author: Mika Westerberg + * + * 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. + */ + +#ifndef GPIOLIB_H +#define GPIOLIB_H + +#include +#include /* for enum gpiod_flags */ +#include +#include +#include +#include + +enum of_gpio_flags; +enum gpio_lookup_flags; +struct acpi_device; + +/** + * struct gpio_device - internal state container for GPIO devices + * @id: numerical ID number for the GPIO chip + * @dev: the GPIO device struct + * @chrdev: character device for the GPIO device + * @mockdev: class device used by the deprecated sysfs interface (may be + * NULL) + * @owner: helps prevent removal of modules exporting active GPIOs + * @chip: pointer to the corresponding gpiochip, holding static + * data for this device + * @descs: array of ngpio descriptors. + * @ngpio: the number of GPIO lines on this GPIO device, equal to the size + * of the @descs array. + * @base: GPIO base in the DEPRECATED global Linux GPIO numberspace, assigned + * at device creation time. + * @label: a descriptive name for the GPIO device, such as the part number + * or name of the IP component in a System on Chip. + * @data: per-instance data assigned by the driver + * @list: links gpio_device:s together for traversal + * + * This state container holds most of the runtime variable data + * for a GPIO device and can hold references and live on after the + * GPIO chip has been removed, if it is still being used from + * userspace. + */ +struct gpio_device { + int id; + struct device dev; + struct cdev chrdev; + struct device *mockdev; + struct module *owner; + struct gpio_chip *chip; + struct gpio_desc *descs; + int base; + u16 ngpio; + const char *label; + void *data; + struct list_head list; + +#ifdef CONFIG_PINCTRL + /* + * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally + * describe the actual pin range which they serve in an SoC. This + * information would be used by pinctrl subsystem to configure + * corresponding pins for gpio usage. + */ + struct list_head pin_ranges; +#endif +}; + +/** + * struct acpi_gpio_info - ACPI GPIO specific information + * @adev: reference to ACPI device which consumes GPIO resource + * @flags: GPIO initialization flags + * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo + * @polarity: interrupt polarity as provided by ACPI + * @triggering: triggering type as provided by ACPI + * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping + */ +struct acpi_gpio_info { + struct acpi_device *adev; + enum gpiod_flags flags; + bool gpioint; + int polarity; + int triggering; + unsigned int quirks; +}; + +/* gpio suffixes used for ACPI and device tree lookup */ +static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; + +#ifdef CONFIG_OF_GPIO +struct gpio_desc *of_find_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + enum gpio_lookup_flags *flags); +struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, + const char *list_name, int index, enum of_gpio_flags *flags); +int of_gpiochip_add(struct gpio_chip *gc); +void of_gpiochip_remove(struct gpio_chip *gc); +#else +static inline struct gpio_desc *of_find_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + enum gpio_lookup_flags *flags) +{ + return ERR_PTR(-ENOENT); +} +static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, + const char *list_name, int index, enum of_gpio_flags *flags) +{ + return ERR_PTR(-ENOENT); +} +static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; } +static inline void of_gpiochip_remove(struct gpio_chip *gc) { } +#endif /* CONFIG_OF_GPIO */ + +#ifdef CONFIG_ACPI +void acpi_gpiochip_add(struct gpio_chip *chip); +void acpi_gpiochip_remove(struct gpio_chip *chip); + +void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); +void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); + +int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, + struct acpi_gpio_info *info); + +struct gpio_desc *acpi_find_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + enum gpiod_flags *dflags, + enum gpio_lookup_flags *lookupflags); +struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, + const char *propname, int index, + struct acpi_gpio_info *info); + +int acpi_gpio_count(struct device *dev, const char *con_id); + +bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id); +#else +static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } +static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } + +static inline void +acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { } + +static inline void +acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } + +static inline int +acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info) +{ + return 0; +} + +static inline struct gpio_desc * +acpi_find_gpio(struct device *dev, const char *con_id, + unsigned int idx, enum gpiod_flags *dflags, + enum gpio_lookup_flags *lookupflags) +{ + return ERR_PTR(-ENOENT); +} +static inline struct gpio_desc * +acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, + int index, struct acpi_gpio_info *info) +{ + return ERR_PTR(-ENXIO); +} +static inline int acpi_gpio_count(struct device *dev, const char *con_id) +{ + return -ENODEV; +} + +static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev, + const char *con_id) +{ + return false; +} +#endif + +struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum); +int gpiod_get_array_value_complex(bool raw, bool can_sleep, + unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array); +int gpiod_set_array_value_complex(bool raw, bool can_sleep, + unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array); + +/* This is just passed between gpiolib and devres */ +struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label); + +extern struct spinlock gpio_lock; +extern struct list_head gpio_devices; + +struct gpio_desc { + struct gpio_device *gdev; + unsigned long flags; +/* flag symbols are bit numbers */ +#define FLAG_REQUESTED 0 +#define FLAG_IS_OUT 1 +#define FLAG_EXPORT 2 /* protected by sysfs_lock */ +#define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */ +#define FLAG_ACTIVE_LOW 6 /* value has active low */ +#define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */ +#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */ +#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */ +#define FLAG_IS_HOGGED 11 /* GPIO is hogged */ +#define FLAG_TRANSITORY 12 /* GPIO may lose value in sleep or reset */ + + /* Connection label */ + const char *label; + /* Name of the GPIO */ + const char *name; +}; + +int gpiod_request(struct gpio_desc *desc, const char *label); +void gpiod_free(struct gpio_desc *desc); +int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, + unsigned long lflags, enum gpiod_flags dflags); +int gpiod_hog(struct gpio_desc *desc, const char *name, + unsigned long lflags, enum gpiod_flags dflags); + +/* + * Return the GPIO number of the passed descriptor relative to its chip + */ +static inline int gpio_chip_hwgpio(const struct gpio_desc *desc) +{ + return desc - &desc->gdev->descs[0]; +} + +void devprop_gpiochip_set_names(struct gpio_chip *chip, + const struct fwnode_handle *fwnode); + +/* With descriptor prefix */ + +#define gpiod_emerg(desc, fmt, ...) \ + pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ + ##__VA_ARGS__) +#define gpiod_crit(desc, fmt, ...) \ + pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ + ##__VA_ARGS__) +#define gpiod_err(desc, fmt, ...) \ + pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ + ##__VA_ARGS__) +#define gpiod_warn(desc, fmt, ...) \ + pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ + ##__VA_ARGS__) +#define gpiod_info(desc, fmt, ...) \ + pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ + ##__VA_ARGS__) +#define gpiod_dbg(desc, fmt, ...) \ + pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ + ##__VA_ARGS__) + +/* With chip prefix */ + +#define chip_emerg(chip, fmt, ...) \ + dev_emerg(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) +#define chip_crit(chip, fmt, ...) \ + dev_crit(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) +#define chip_err(chip, fmt, ...) \ + dev_err(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) +#define chip_warn(chip, fmt, ...) \ + dev_warn(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) +#define chip_info(chip, fmt, ...) \ + dev_info(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) +#define chip_dbg(chip, fmt, ...) \ + dev_dbg(&chip->gpiodev->dev, "(%s): " fmt, chip->label, ##__VA_ARGS__) + +#ifdef CONFIG_GPIO_SYSFS + +int gpiochip_sysfs_register(struct gpio_device *gdev); +void gpiochip_sysfs_unregister(struct gpio_device *gdev); + +#else + +static inline int gpiochip_sysfs_register(struct gpio_device *gdev) +{ + return 0; +} + +static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev) +{ +} + +#endif /* CONFIG_GPIO_SYSFS */ + +#endif /* GPIOLIB_H */ diff --git a/platform/centec-arm64/tsingma-bsp/src/i2c-ctc/Makefile b/platform/centec-arm64/tsingma-bsp/src/i2c-ctc/Makefile new file mode 100644 index 000000000000..3821209dfe92 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/i2c-ctc/Makefile @@ -0,0 +1 @@ +obj-m = i2c-ctc.o diff --git a/platform/centec-arm64/tsingma-bsp/src/i2c-ctc/i2c-ctc.c b/platform/centec-arm64/tsingma-bsp/src/i2c-ctc/i2c-ctc.c new file mode 100644 index 000000000000..bcae26040d06 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/i2c-ctc/i2c-ctc.c @@ -0,0 +1,822 @@ +/* Centec I2C controller driver + * + * Author: Wangyb + * + * Copyright 2005-2018, Centec Networks (Suzhou) Co., Ltd. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-ctc.h" + +#define IC_ICK_NS(f) (1000000000 / f) + +static char *abort_sources[] = { + [ABRT_7B_ADDR_NOACK] = "slave address not acknowledged (7bit mode)", + [ABRT_10ADDR1_NOACK] = + "first address byte not acknowledged (10bit mode)", + [ABRT_10ADDR2_NOACK] = + "second address byte not acknowledged (10bit mode)", + [ABRT_TXDATA_NOACK] = "data not acknowledged", + [ABRT_GCALL_NOACK] = "no acknowledgment for a general call", + [ABRT_GCALL_READ] = "read after general call", + [ABRT_SBYTE_ACKDET] = "start byte acknowledged", + [ABRT_SBYTE_NORSTRT] = + "trying to send start byte when restart is disabled", + [ABRT_10B_RD_NORSTRT] = + "trying to read when restart is disabled (10bit mode)", + [ABRT_MASTER_DIS] = "trying to use disabled adapter", + [ARB_LOST] = "lost arbitration", +}; + +static u32 ctc_readl(struct ctc_i2c_dev *dev, int offset) +{ + u32 value; + + value = readl_relaxed(dev->base + offset); + return value; +} + +static void ctc_writel(struct ctc_i2c_dev *dev, u32 b, int offset) +{ + writel_relaxed(b, dev->base + offset); +} + +static void __i2c_ctc_enable(struct ctc_i2c_dev *dev, bool enable) +{ + int timeout = 100; + + do { + ctc_writel(dev, enable, CTC_IC_ENABLE); + if ((ctc_readl(dev, CTC_IC_ENABLE_STATUS) & 1) == enable) + return; + usleep_range(25, 250); + } while (timeout--); + + dev_warn(dev->dev, "timeout in %sabling adapter\n", + enable ? "en" : "dis"); +} + +/* Conditional expression: + * SCL high level time = (high level cnt + (14 + 4)cnt) * 20ns + * SCL low level time = (low level cnt + (1 + 2)cnt) * 20ns + */ +static u32 __ctc_calc_ss_cnt(u32 clk_freq) +{ + return CTC_SCL_Timing(clk_freq) / 2 / 20; +} + +static u32 __ctc_calc_fs_cnt(u32 clk_freq) +{ + return CTC_SCL_Timing(clk_freq) / 2 / 20 + 1; +} + +int i2c_ctc_init(struct ctc_i2c_dev *dev) +{ + u32 hcnt, lcnt; + u32 reg, comp_param1; + + reg = ctc_readl(dev, CTC_IC_COMP_TYPE); + if (reg != CTC_IC_COMP_TYPE_VALUE) { + dev_err(dev->dev, "Unknown Centec component type: 0x%08x\n", + reg); + return -ENODEV; + } + + /* Disable the adapter */ + __i2c_ctc_enable(dev, false); + + /* Set SCL timing parameters */ + if ((dev->master_cfg & CTC_IC_CON_SPEED_MASK) + == CTC_IC_CON_SPEED_FAST) { + hcnt = __ctc_calc_fs_cnt(dev->clk_freq) - 14 - 4; + lcnt = __ctc_calc_fs_cnt(dev->clk_freq) - 1 - 2; + + ctc_writel(dev, hcnt, CTC_IC_FS_SCL_HCNT); + ctc_writel(dev, lcnt, CTC_IC_FS_SCL_LCNT); + dev_info(dev->dev, + "Fast-mode HCNT:LCNT = %d:%d, clk_freq = %d\n", hcnt, + lcnt, dev->clk_freq); + + } else { + hcnt = __ctc_calc_ss_cnt(dev->clk_freq) - 14 - 2; + lcnt = __ctc_calc_ss_cnt(dev->clk_freq) - 1; + + ctc_writel(dev, hcnt, CTC_IC_SS_SCL_HCNT); + ctc_writel(dev, lcnt, CTC_IC_SS_SCL_LCNT); + dev_info(dev->dev, + "Standard-mode HCNT:LCNT = %d:%d, clk_freq = %d\n", + hcnt, lcnt, dev->clk_freq); + } + + /* Configure SDA Hold Time if required */ + if (dev->sda_hold_time) + ctc_writel(dev, dev->sda_hold_time, CTC_IC_SDA_HOLD); + + /* Configure Tx/Rx FIFO threshold levels */ + comp_param1 = ctc_readl(dev, CTC_IC_COMP_PARAM_1); + dev->tx_fifo_depth = ((comp_param1 >> 16) & 0xff) + 1; + dev->rx_fifo_depth = ((comp_param1 >> 8) & 0xff) + 1; + + ctc_writel(dev, dev->tx_fifo_depth / 2, CTC_IC_TX_TL); + ctc_writel(dev, 0, CTC_IC_RX_TL); + + /* Configure the i2c master */ + ctc_writel(dev, dev->master_cfg, CTC_IC_CON); + + return 0; +} + +static int i2c_ctc_wait_bus_not_busy(struct ctc_i2c_dev *dev) +{ + int timeout = 20; + + while (ctc_readl(dev, CTC_IC_STATUS) & CTC_IC_STATUS_ACTIVITY) { + if (timeout <= 0) { + dev_warn(dev->dev, "timeout waiting for bus ready\n"); + return -ETIMEDOUT; + } + timeout--; + usleep_range(1000, 1100); + } + return 0; +} + +void i2c_ctc_disable_intr(struct ctc_i2c_dev *dev) +{ + ctc_writel(dev, 0, CTC_IC_INTR_MASK); +} + +static void i2c_ctc_xfer_init(struct ctc_i2c_dev *dev) +{ + struct i2c_msg *msgs = dev->msgs; + u32 ic_con, ic_tar = 0; + + /* Disable the adapter */ + __i2c_ctc_enable(dev, false); + + /* if the slave address is ten bit address, enable 10BITADDR */ + ic_con = ctc_readl(dev, CTC_IC_CON); + if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) { + ic_con |= CTC_IC_CON_10BITADDR_MASTER; + ic_tar = CTC_IC_TAR_10BITADDR_MASTER; + } else { + ic_con &= ~CTC_IC_CON_10BITADDR_MASTER; + } + + ctc_writel(dev, ic_con, CTC_IC_CON); + + /* Set the slave (target) address */ + ctc_writel(dev, msgs[dev->msg_write_idx].addr | ic_tar, CTC_IC_TAR); + + /* Enforce disabled interrupts (due to HW issues) */ + i2c_ctc_disable_intr(dev); + + /* Enable the adapter */ + __i2c_ctc_enable(dev, true); + + /* Clear and enable interrupts */ + ctc_readl(dev, CTC_IC_CLR_INTR); + ctc_writel(dev, CTC_IC_INTR_DEFAULT_MASK, CTC_IC_INTR_MASK); +} + +static int i2c_ctc_handle_tx_abort(struct ctc_i2c_dev *dev) +{ + unsigned long abort_source = dev->abort_source; + int i; + + if (abort_source & CTC_IC_TX_ABRT_NOACK) { + for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) + dev_dbg(dev->dev, "%s: %s\n", __func__, + abort_sources[i]); + return -EREMOTEIO; + } + + for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) + dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); + + if (abort_source & CTC_IC_TX_ARB_LOST) + return -EAGAIN; + else if (abort_source & CTC_IC_TX_ABRT_GCALL_READ) + return -EINVAL; + else + return -EIO; +} + +static int i2c_ctc_interrupt_transfer(struct ctc_i2c_dev *dev) +{ + int ret; + + mutex_lock(&dev->lock); + + reinit_completion(&dev->cmd_complete); + + dev->cmd_err = 0; + dev->msg_write_idx = 0; + dev->msg_read_idx = 0; + dev->msg_err = 0; + dev->status = STATUS_IDLE; + dev->abort_source = 0; + dev->rx_outstanding = 0; + + ret = i2c_ctc_wait_bus_not_busy(dev); + if (ret < 0) + goto done; + + /* start the transfers */ + i2c_ctc_xfer_init(dev); + + /* wait for tx to complete */ + if (!wait_for_completion_timeout(&dev->cmd_complete, HZ)) { + dev_err(dev->dev, "controller timed out\n"); + i2c_ctc_init(dev); + ret = -ETIMEDOUT; + goto done; + } + + __i2c_ctc_enable(dev, false); + + if (dev->msg_err) { + ret = dev->msg_err; + goto done; + } + + /* no error */ + if (likely(!dev->cmd_err)) { + ret = dev->msgs_num; + goto done; + } + + /* We have an error */ + if (dev->cmd_err == CTC_IC_ERR_TX_ABRT) { + ret = i2c_ctc_handle_tx_abort(dev); + goto done; + } + ret = -EIO; + +done: + mutex_unlock(&dev->lock); + return ret; +} + +static void ctc_i2c_flush_rxfifo(struct ctc_i2c_dev *dev) +{ + while (ctc_readl(dev, CTC_IC_STATUS) & CTC_IC_STATUS_RFNE) + ctc_readl(dev, CTC_IC_DATA_CMD); +} + +static int ctc_i2c_xfer_finish(struct ctc_i2c_dev *dev) +{ + int ret; + ulong start_stop_det = jiffies; + + while (1) { + if ((ctc_readl(dev, CTC_IC_RAW_INTR_STAT) & + CTC_IC_INTR_STOP_DET)) { + ctc_readl(dev, CTC_IC_CLR_STOP_DET); + break; + } else if (time_after(jiffies, start_stop_det + + I2C_STOPDET_TO)) { + break; + } + } + + ret = i2c_ctc_wait_bus_not_busy(dev); + if (ret < 0) + return -1; + + ctc_i2c_flush_rxfifo(dev); + + return 0; +} + +static int __ctc_i2c_read(struct ctc_i2c_dev *dev, __u16 chip_addr, u8 *offset, + __u16 olen, u8 *data, __u16 dlen) +{ + unsigned int active = 0; + unsigned int flag = 0; + int ret; + unsigned long start_time_rx; + + ret = i2c_ctc_wait_bus_not_busy(dev); + if (ret < 0) + return -1; + + /* Disable the adapter */ + __i2c_ctc_enable(dev, false); + + /* Set the slave (target) address */ + ctc_writel(dev, chip_addr, CTC_IC_TAR); + + /* Enable the adapter */ + __i2c_ctc_enable(dev, true); + + if (olen > 0) { + ctc_writel(dev, *offset | CTC_RESTART, CTC_IC_DATA_CMD); + olen--; + while (olen) { + offset++; + olen--; + ctc_writel(dev, *offset, CTC_IC_DATA_CMD); + } + } + + start_time_rx = jiffies; + while (dlen) { + if (!active) { + if (flag == 0) { + if (dlen == 1) { + ctc_writel(dev, + CTC_CMD_READ | CTC_STOP | + CTC_RESTART, + CTC_IC_DATA_CMD); + } else { + ctc_writel(dev, + CTC_CMD_READ | CTC_RESTART, + CTC_IC_DATA_CMD); + } + flag = 1; + } else if (dlen != 1) { + ctc_writel(dev, CTC_CMD_READ, CTC_IC_DATA_CMD); + } else { + ctc_writel(dev, CTC_CMD_READ | CTC_STOP, + CTC_IC_DATA_CMD); + } + active = 1; + } + if (ctc_readl(dev, CTC_IC_STATUS) & CTC_IC_STATUS_RFNE) { + *data++ = + (unsigned char)ctc_readl(dev, CTC_IC_DATA_CMD); + dlen--; + start_time_rx = jiffies; + active = 0; + } else if (time_after(jiffies, start_time_rx + I2C_BYTE_TO)) { + return -ETIMEDOUT; + } + } + + return ctc_i2c_xfer_finish(dev); +} + +static int __ctc_i2c_write(struct ctc_i2c_dev *dev, __u16 chip_addr, + u8 *offset, __u16 olen, u8 *data, __u16 dlen) +{ + int ret; + unsigned long start_time_tx; + int nb = dlen; + + ret = i2c_ctc_wait_bus_not_busy(dev); + if (ret < 0) + return -1; + + /* Disable the adapter */ + __i2c_ctc_enable(dev, false); + + /* Set the slave (target) address */ + ctc_writel(dev, chip_addr, CTC_IC_TAR); + + /* Enable the adapter */ + __i2c_ctc_enable(dev, true); + + start_time_tx = jiffies; + while (dlen) { + if (ctc_readl(dev, CTC_IC_STATUS) & CTC_IC_STATUS_TFNF) { + if (--dlen == 0) { + ctc_writel(dev, *data | CTC_STOP, + CTC_IC_DATA_CMD); + } else { + ctc_writel(dev, *data, CTC_IC_DATA_CMD); + } + data++; + start_time_tx = jiffies; + } else if (time_after(jiffies, start_time_tx + + (nb * I2C_BYTE_TO))) { + dev_err(dev->dev, "Timed out. i2c write Failed\n"); + return -ETIMEDOUT; + } + } + return ctc_i2c_xfer_finish(dev); +} + +static int i2c_ctc_polling_transfer(struct ctc_i2c_dev *dev) +{ + struct i2c_msg *dmsg, *omsg, dummy; + int ret; + + memset(&dummy, 0, sizeof(struct i2c_msg)); + + /* We expect either two messages (one with an offset and one with the + * actucal data) or one message (just data) + */ + if (dev->msgs_num > 2 || dev->msgs_num == 0) { + dev_err(dev->dev, "%s: Only one or two messages are supported.", + __func__); + return -1; + } + + omsg = dev->msgs_num == 1 ? &dummy : dev->msgs; + dmsg = dev->msgs_num == 1 ? dev->msgs : (dev->msgs + 1); + + if (dmsg->flags & I2C_M_RD) { + ret = __ctc_i2c_read(dev, dmsg->addr, omsg->buf, omsg->len, + dmsg->buf, dmsg->len); + } else + ret = __ctc_i2c_write(dev, dmsg->addr, omsg->buf, omsg->len, + dmsg->buf, dmsg->len); + if (!ret) + return dev->msgs_num; + else + return -EIO; +} + +static int i2c_ctc_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + int num) +{ + struct ctc_i2c_dev *dev = i2c_get_adapdata(adap); + int ret; + + dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); + dev->msgs = msgs; + dev->msgs_num = num; + + if (dev->xfer_type == CTC_IC_INTERRUPT_TRANSFER) + ret = i2c_ctc_interrupt_transfer(dev); + else + ret = i2c_ctc_polling_transfer(dev); + + return ret; +} + +static void i2c_ctc_xfer_msg(struct ctc_i2c_dev *dev) +{ + struct i2c_msg *msgs = dev->msgs; + u32 intr_mask; + int tx_limit, rx_limit; + u32 addr = msgs[dev->msg_write_idx].addr; + u32 buf_len = dev->tx_buf_len; + u8 *buf = dev->tx_buf; + bool need_restart = false; + + intr_mask = CTC_IC_INTR_DEFAULT_MASK; + + /* msg_write_idx */ + for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) { + + if (msgs[dev->msg_write_idx].addr != addr) { + dev_err(dev->dev, "%s: invalid target address\n", + __func__); + dev->msg_err = -EINVAL; + break; + } + + if (msgs[dev->msg_write_idx].len == 0) { + dev_err(dev->dev, "%s: invalid message length\n", + __func__); + dev->msg_err = -EINVAL; + break; + } + + if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { + /* new i2c_msg */ + buf = msgs[dev->msg_write_idx].buf; + buf_len = msgs[dev->msg_write_idx].len; + + if ((dev->master_cfg & CTC_IC_CON_RESTART_EN) + && (dev->msg_write_idx > 0)) + need_restart = true; + } + + tx_limit = dev->tx_fifo_depth - ctc_readl(dev, CTC_IC_TXFLR); + rx_limit = dev->rx_fifo_depth - ctc_readl(dev, CTC_IC_RXFLR); + + while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { + u32 cmd = 0; + + /* set the stop bit */ + if (dev->msg_write_idx == dev->msgs_num - 1 + && buf_len == 1) + cmd |= BIT(9); + + /* set the restart bit */ + if (need_restart) { + cmd |= BIT(10); + need_restart = false; + } + + if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { + if (rx_limit - dev->rx_outstanding <= 0) + break; + + /* 1 = Read */ + ctc_writel(dev, cmd | CTC_CMD_READ, + CTC_IC_DATA_CMD); + rx_limit--; + dev->rx_outstanding++; + } else + /* 0 = Write */ + ctc_writel(dev, cmd | *buf++, CTC_IC_DATA_CMD); + tx_limit--; + buf_len--; + } + + dev->tx_buf = buf; + dev->tx_buf_len = buf_len; + + if (buf_len > 0) { + /* more bytes to be written */ + dev->status |= STATUS_WRITE_IN_PROGRESS; + break; + } + dev->status &= ~STATUS_WRITE_IN_PROGRESS; + } + + if (dev->msg_write_idx == dev->msgs_num) + intr_mask &= ~CTC_IC_INTR_TX_EMPTY; + + if (dev->msg_err) + intr_mask = 0; + + ctc_writel(dev, intr_mask, CTC_IC_INTR_MASK); +} + +static void i2c_ctc_read(struct ctc_i2c_dev *dev) +{ + struct i2c_msg *msgs = dev->msgs; + int rx_valid; + u32 len; + u8 *buf; + + /* msg_read_idx */ + for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) { + + if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD)) + continue; + + if (!(dev->status & STATUS_READ_IN_PROGRESS)) { + len = msgs[dev->msg_read_idx].len; + buf = msgs[dev->msg_read_idx].buf; + } else { + len = dev->rx_buf_len; + buf = dev->rx_buf; + } + + rx_valid = ctc_readl(dev, CTC_IC_RXFLR); + + for (; len > 0 && rx_valid > 0; len--, rx_valid--) { + *buf++ = ctc_readl(dev, CTC_IC_DATA_CMD); + dev->rx_outstanding--; + } + + if (len > 0) { + dev->status |= STATUS_READ_IN_PROGRESS; + dev->rx_buf_len = len; + dev->rx_buf = buf; + return; + } + dev->status &= ~STATUS_READ_IN_PROGRESS; + } +} + +static u32 i2c_ctc_read_clear_intrbits(struct ctc_i2c_dev *dev) +{ + u32 stat; + + stat = ctc_readl(dev, CTC_IC_INTR_STAT); + if (stat & CTC_IC_INTR_RX_UNDER) + ctc_readl(dev, CTC_IC_CLR_RX_UNDER); + if (stat & CTC_IC_INTR_RX_OVER) + ctc_readl(dev, CTC_IC_CLR_RX_OVER); + if (stat & CTC_IC_INTR_TX_OVER) + ctc_readl(dev, CTC_IC_CLR_TX_OVER); + if (stat & CTC_IC_INTR_RD_REQ) + ctc_readl(dev, CTC_IC_CLR_RD_REQ); + if (stat & CTC_IC_INTR_TX_ABRT) { + dev->abort_source = ctc_readl(dev, CTC_IC_TX_ABRT_SOURCE); + ctc_readl(dev, CTC_IC_CLR_TX_ABRT); + } + if (stat & CTC_IC_INTR_RX_DONE) + ctc_readl(dev, CTC_IC_CLR_RX_DONE); + if (stat & CTC_IC_INTR_ACTIVITY) + ctc_readl(dev, CTC_IC_CLR_ACTIVITY); + if (stat & CTC_IC_INTR_STOP_DET) + ctc_readl(dev, CTC_IC_CLR_STOP_DET); + if (stat & CTC_IC_INTR_START_DET) + ctc_readl(dev, CTC_IC_CLR_START_DET); + if (stat & CTC_IC_INTR_GEN_CALL) + ctc_readl(dev, CTC_IC_CLR_GEN_CALL); + + return stat; +} + +static irqreturn_t i2c_ctc_isr(int this_irq, void *dev_id) +{ + struct ctc_i2c_dev *dev = dev_id; + u32 stat, enabled; + + enabled = ctc_readl(dev, CTC_IC_ENABLE); + stat = ctc_readl(dev, CTC_IC_RAW_INTR_STAT); + dev_dbg(dev->dev, "%s: enabled=%#x stat=%#x\n", __func__, enabled, + stat); + if (!enabled || !(stat & ~CTC_IC_INTR_ACTIVITY)) + return IRQ_NONE; + + stat = i2c_ctc_read_clear_intrbits(dev); + + if (stat & CTC_IC_INTR_TX_ABRT) { + dev->cmd_err |= CTC_IC_ERR_TX_ABRT; + dev->status = STATUS_IDLE; + + ctc_writel(dev, 0, CTC_IC_INTR_MASK); + goto tx_aborted; + } + + if (stat & CTC_IC_INTR_RX_FULL) + i2c_ctc_read(dev); + + if (stat & CTC_IC_INTR_TX_EMPTY) + i2c_ctc_xfer_msg(dev); + +tx_aborted: + if ((stat & (CTC_IC_INTR_TX_ABRT | CTC_IC_INTR_STOP_DET)) + || dev->msg_err) + complete(&dev->cmd_complete); + return IRQ_HANDLED; +} + +static u32 i2c_ctc_func(struct i2c_adapter *adap) +{ + struct ctc_i2c_dev *dev = i2c_get_adapdata(adap); + + return dev->functionality; +} + +static struct i2c_algorithm i2c_ctc_algo = { + .master_xfer = i2c_ctc_xfer, + .functionality = i2c_ctc_func, +}; + +int i2c_ctc_probe(struct ctc_i2c_dev *dev) +{ + struct i2c_adapter *adap = &dev->adapter; + int ret; + + init_completion(&dev->cmd_complete); + mutex_init(&dev->lock); + + i2c_ctc_init(dev); + + snprintf(adap->name, sizeof(adap->name), + "Centec TsingMa SoC's I2C adapter"); + adap->algo = &i2c_ctc_algo; + adap->dev.parent = dev->dev; + i2c_set_adapdata(adap, dev); + + i2c_ctc_disable_intr(dev); + if (dev->xfer_type == CTC_IC_INTERRUPT_TRANSFER) { + ret = devm_request_irq(dev->dev, dev->irq, i2c_ctc_isr, + IRQF_SHARED | IRQF_COND_SUSPEND, + dev_name(dev->dev), dev); + if (ret) { + dev_err(dev->dev, "failure requesting irq %i: %d\n", + dev->irq, ret); + return ret; + } + } + ret = i2c_add_numbered_adapter(adap); + if (ret) + dev_err(dev->dev, "failure adding adapter: %d\n", ret); + + return ret; +} + +static int ctc_i2c_plat_probe(struct platform_device *pdev) +{ + struct ctc_i2c_dev *dev; + struct i2c_adapter *adap; + struct resource *mem; + int irq, ret; + u32 clk_freq, ht; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + dev = devm_kzalloc(&pdev->dev, sizeof(struct ctc_i2c_dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dev->base = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(dev->base)) + return PTR_ERR(dev->base); + + dev->dev = &pdev->dev; + dev->irq = irq; + platform_set_drvdata(pdev, dev); + + of_property_read_u32(pdev->dev.of_node, "clock-frequency", &clk_freq); + + dev->clk_freq = clk_freq; + if (dev->clk_freq <= 100000) + dev->master_cfg |= CTC_IC_CON_SPEED_STD; + else if (dev->clk_freq <= 400000) + dev->master_cfg |= CTC_IC_CON_SPEED_FAST; + else { + dev_err(&pdev->dev, "Unsupported this frequency\n"); + return -EINVAL; + } + + dev->master_cfg |= + CTC_IC_CON_MASTER | CTC_IC_CON_SLAVE_DISABLE | + CTC_IC_CON_RESTART_EN; + + dev->functionality = + I2C_FUNC_I2C | + I2C_FUNC_10BIT_ADDR | + I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK; + + dev->clk = devm_clk_get(&pdev->dev, NULL); + clk_prepare_enable(dev->clk); + + if (!of_property_read_u32 + (pdev->dev.of_node, "i2c-sda-hold-time-ns", &ht)) { + dev->sda_hold_time = ht / IC_ICK_NS(clk_get_rate(dev->clk)); + } + + if (of_property_read_bool(pdev->dev.of_node, "i2c-polling-xfer")) + dev->xfer_type = CTC_IC_POLLING_TRANSFER; + else + dev->xfer_type = CTC_IC_INTERRUPT_TRANSFER; + + dev->adapter.nr = pdev->id; + adap = &dev->adapter; + adap->owner = THIS_MODULE; + adap->class = I2C_CLASS_DEPRECATED; + adap->dev.of_node = pdev->dev.of_node; + + ret = i2c_ctc_probe(dev); + return ret; +} + +static int ctc_i2c_plat_remove(struct platform_device *pdev) +{ + struct ctc_i2c_dev *dev = platform_get_drvdata(pdev); + + i2c_del_adapter(&dev->adapter); + + /* Disable controller */ + __i2c_ctc_enable(dev, false); + + /* Disable all interupts */ + ctc_writel(dev, 0, CTC_IC_INTR_MASK); + ctc_readl(dev, CTC_IC_CLR_INTR); + + return 0; +} + +static const struct of_device_id ctc_i2c_of_match[] = { + {.compatible = "ctc,i2c",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, ctc_i2c_of_match); + +static struct platform_driver ctc_i2c_driver = { + .probe = ctc_i2c_plat_probe, + .remove = ctc_i2c_plat_remove, + .driver = { + .name = "i2c_centec", + .of_match_table = of_match_ptr(ctc_i2c_of_match), + }, +}; + +static int __init ctc_i2c_init_driver(void) +{ + return platform_driver_register(&ctc_i2c_driver); +} + +subsys_initcall(ctc_i2c_init_driver); + +static void __exit ctc_i2c_exit_driver(void) +{ + platform_driver_unregister(&ctc_i2c_driver); +} + +module_exit(ctc_i2c_exit_driver); + +MODULE_AUTHOR("Centec, Inc."); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/tsingma-bsp/src/i2c-ctc/i2c-ctc.h b/platform/centec-arm64/tsingma-bsp/src/i2c-ctc/i2c-ctc.h new file mode 100644 index 000000000000..c27079646a30 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/i2c-ctc/i2c-ctc.h @@ -0,0 +1,162 @@ +/* Author: Wangyb + * + * Copyright 2005-2018, Centec Networks (Suzhou) Co., Ltd. + * + */ + +#define CTC_IC_CON_MASTER 0x1 +#define CTC_IC_CON_SPEED_STD 0x2 +#define CTC_IC_CON_SPEED_FAST 0x4 +#define CTC_IC_CON_SPEED_MASK 0x6 +#define CTC_IC_CON_10BITADDR_MASTER 0x10 +#define CTC_IC_CON_RESTART_EN 0x20 +#define CTC_IC_CON_SLAVE_DISABLE 0x40 + +#define CTC_SCL_Timing(T) (1000000000 / T) /* in nanoseconds */ + +/* + * Registers offset + */ +#define CTC_IC_CON 0x0 +#define CTC_IC_TAR 0x4 +#define CTC_IC_DATA_CMD 0x10 +#define CTC_IC_SS_SCL_HCNT 0x14 +#define CTC_IC_SS_SCL_LCNT 0x18 +#define CTC_IC_FS_SCL_HCNT 0x1c +#define CTC_IC_FS_SCL_LCNT 0x20 +#define CTC_IC_INTR_STAT 0x2c +#define CTC_IC_INTR_MASK 0x30 +#define CTC_IC_RAW_INTR_STAT 0x34 +#define CTC_IC_RX_TL 0x38 +#define CTC_IC_TX_TL 0x3c +#define CTC_IC_CLR_INTR 0x40 +#define CTC_IC_CLR_RX_UNDER 0x44 +#define CTC_IC_CLR_RX_OVER 0x48 +#define CTC_IC_CLR_TX_OVER 0x4c +#define CTC_IC_CLR_RD_REQ 0x50 +#define CTC_IC_CLR_TX_ABRT 0x54 +#define CTC_IC_CLR_RX_DONE 0x58 +#define CTC_IC_CLR_ACTIVITY 0x5c +#define CTC_IC_CLR_STOP_DET 0x60 +#define CTC_IC_CLR_START_DET 0x64 +#define CTC_IC_CLR_GEN_CALL 0x68 +#define CTC_IC_ENABLE 0x6c +#define CTC_IC_STATUS 0x70 +#define CTC_IC_TXFLR 0x74 +#define CTC_IC_RXFLR 0x78 +#define CTC_IC_SDA_HOLD 0x7c +#define CTC_IC_TX_ABRT_SOURCE 0x80 +#define CTC_IC_ENABLE_STATUS 0x9c +#define CTC_IC_COMP_PARAM_1 0xf4 +#define CTC_IC_COMP_VERSION 0xf8 +#define CTC_IC_SDA_HOLD_MIN_VERS 0x3131312A +#define CTC_IC_COMP_TYPE 0xfc +#define CTC_IC_COMP_TYPE_VALUE 0x44570140 + +#define CTC_IC_STATUS_ACTIVITY 0x1 +#define CTC_IC_TAR_10BITADDR_MASTER BIT(12) +#define CTC_IC_ERR_TX_ABRT 0x1 + +#define CTC_IC_INTR_RX_UNDER 0x001 +#define CTC_IC_INTR_RX_OVER 0x002 +#define CTC_IC_INTR_RX_FULL 0x004 +#define CTC_IC_INTR_TX_OVER 0x008 +#define CTC_IC_INTR_TX_EMPTY 0x010 +#define CTC_IC_INTR_RD_REQ 0x020 +#define CTC_IC_INTR_TX_ABRT 0x040 +#define CTC_IC_INTR_RX_DONE 0x080 +#define CTC_IC_INTR_ACTIVITY 0x100 +#define CTC_IC_INTR_STOP_DET 0x200 +#define CTC_IC_INTR_START_DET 0x400 +#define CTC_IC_INTR_GEN_CALL 0x800 + +#define CTC_IC_INTR_DEFAULT_MASK (CTC_IC_INTR_RX_FULL | \ + CTC_IC_INTR_TX_EMPTY | \ + CTC_IC_INTR_TX_ABRT | \ + CTC_IC_INTR_STOP_DET) + +/* + * status codes + */ +#define STATUS_IDLE 0x0 +#define STATUS_WRITE_IN_PROGRESS 0x1 +#define STATUS_READ_IN_PROGRESS 0x2 + +#define ABRT_7B_ADDR_NOACK 0 +#define ABRT_10ADDR1_NOACK 1 +#define ABRT_10ADDR2_NOACK 2 +#define ABRT_TXDATA_NOACK 3 +#define ABRT_GCALL_NOACK 4 +#define ABRT_GCALL_READ 5 +#define ABRT_SBYTE_ACKDET 7 +#define ABRT_SBYTE_NORSTRT 9 +#define ABRT_10B_RD_NORSTRT 10 +#define ABRT_MASTER_DIS 11 +#define ARB_LOST 12 + +#define CTC_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK) +#define CTC_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK) +#define CTC_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK) +#define CTC_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK) +#define CTC_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK) +#define CTC_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ) +#define CTC_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET) +#define CTC_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT) +#define CTC_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT) +#define CTC_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS) +#define CTC_IC_TX_ARB_LOST (1UL << ARB_LOST) + +#define CTC_IC_TX_ABRT_NOACK (CTC_IC_TX_ABRT_7B_ADDR_NOACK | \ + CTC_IC_TX_ABRT_10ADDR1_NOACK | \ + CTC_IC_TX_ABRT_10ADDR2_NOACK | \ + CTC_IC_TX_ABRT_TXDATA_NOACK | \ + CTC_IC_TX_ABRT_GCALL_NOACK) + +#define CTC_CMD_READ 0x0100 +#define CTC_STOP 0x0200 +#define CTC_RESTART 0x0400 + +#define CTC_IC_STATUS_RFNE 0x0008 +#define CTC_IC_STATUS_TFNF 0x0002 + +#define I2C_BYTE_TO 1 /* means 1 jiffies = 4ms */ +#define I2C_STOPDET_TO 1 /* means 1 jiffies = 4ms */ + +#define CTC_IC_STATUS_MA 0x0020 +#define CTC_IC_STATUS_TFE 0x0004 + +enum xfer_type_e { + CTC_IC_INTERRUPT_TRANSFER, + CTC_IC_POLLING_TRANSFER +}; + +struct ctc_i2c_dev { + struct device *dev; + void __iomem *base; + struct completion cmd_complete; + struct clk *clk; + struct mutex lock; + u32 master_cfg; + int irq; + unsigned int rx_fifo_depth; + unsigned int tx_fifo_depth; + struct i2c_adapter adapter; + struct i2c_msg *msgs; + int msgs_num; + int msg_err; + int cmd_err; + unsigned int status; + u32 abort_source; + int msg_read_idx; + int rx_outstanding; + int msg_write_idx; + u32 tx_buf_len; + u8 *tx_buf; + u32 rx_buf_len; + u8 *rx_buf; + u32 accessor_flags; + u32 functionality; + u32 clk_freq; + u32 sda_hold_time; + u32 xfer_type; +}; diff --git a/platform/centec-arm64/tsingma-bsp/src/include/ctc5236_switch.h b/platform/centec-arm64/tsingma-bsp/src/include/ctc5236_switch.h new file mode 100644 index 000000000000..aba77b10be32 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/include/ctc5236_switch.h @@ -0,0 +1,43 @@ +#ifndef __CTC5236_SWITCH_H +#define __CTC5236_SWITCH_H + +#define OMCMEM_BASE 0x00041000 +#define SYS_TSINGMA_MDIO_CTLR_NUM 2 +#define SYS_TSINGMA_TEMP_TABLE_NUM 166 +#define SYS_TSINGMA_SENSOR_TIMEOUT 1000 + +struct ctc_switch_cmd_status_t { + u32 cmdReadType:1; + u32 pcieReqCmdChk:3; + u32 cmdEntryWords:4; + u32 cmdDataLen:5; + u32 reserved:1; + u32 pcieReqError:1; + u32 pcieDataError:1; + u32 reqProcDone:1; + u32 reqProcError:1; + u32 reqProcTimeout:1; + u32 reqProcAckError:1; + u32 reqProcAckCnt:5; + u32 regProcBusy:1; + u32 cmdStatusWaitReq:1; + u32 pciePoisoned:1; + u32 regProcState:3; + u32 pcieReqOverlap:1; +}; + +union ctc_switch_cmd_status_u_t { + struct ctc_switch_cmd_status_t cmd_status; + u32 val; +}; + +struct ctc_access_t { + u32 cmd_status; + u32 addr; + u32 data[16]; +}; + +extern int ctc5236_switch_read(u32 offset, u32 len, u32 *p_value); +extern int ctc5236_switch_write(u32 offset, u32 len, u32 *p_value); +extern int get_switch_temperature(void); +#endif diff --git a/platform/centec-arm64/tsingma-bsp/src/include/sysctl.h b/platform/centec-arm64/tsingma-bsp/src/include/sysctl.h new file mode 100644 index 000000000000..2201db88558f --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/include/sysctl.h @@ -0,0 +1,2714 @@ +/* + * (C) Copyright 2004-2017 Centec Networks (suzhou) Co., LTD. + * Jay Cao + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef __CTC5236_SYSCTL_H__ +#define __CTC5236_SYSCTL_H__ + +#ifndef __ASSEMBLY__ + +/* define SYSCTL_MEM_BASE 0x0000fe00 */ +/* defing SYSCTL_REG_BASE 0x00000000 */ + +struct SysCtl_regs { + u32 SysResetCtl; /* 0x00000000 */ + u32 SysResetAutoEn; /* 0x00000004 */ + u32 SysGicResetCtl; /* 0x00000008 */ + u32 rsv3; + u32 SysWdtResetCtl; /* 0x00000010 */ + u32 SysDmaResetCtl; /* 0x00000014 */ + u32 SysDdrResetCtl; /* 0x00000018 */ + u32 SysPcieResetCtl; /* 0x0000001c */ + u32 SysMacResetCtl; /* 0x00000020 */ + u32 SysMshResetCtl; /* 0x00000024 */ + u32 SysUsbResetCtl; /* 0x00000028 */ + u32 SysSpiResetCtl; /* 0x0000002c */ + u32 SysQspiResetCtl; /* 0x00000030 */ + u32 SysAxiSupResetCtl; /* 0x00000034 */ + u32 SysGpioResetCtl; /* 0x00000038 */ + u32 SysI2CResetCtl; /* 0x0000003c */ + u32 SysMdioSocResetCtl; /* 0x00000040 */ + u32 SysTimerResetCtl; /* 0x00000044 */ + u32 SysUartResetCtl; /* 0x00000048 */ + u32 SysTraceResetCtl; /* 0x0000004c */ + u32 SysDbg0ResetEnCtl; /* 0x00000050 */ + u32 SysDbg1ResetEnCtl; /* 0x00000054 */ + u32 SysWarm0ResetEnCtl; /* 0x00000058 */ + u32 SysWarm1ResetEnCtl; /* 0x0000005c */ + u32 SysWdt0ResetEnCtl; /* 0x00000060 */ + u32 SysWdt1ResetEnCtl; /* 0x00000064 */ + u32 SysCtlReserved; /* 0x00000068 */ + u32 SysEnClkCfg; /* 0x0000006c */ + u32 SysPllSocCfg0; /* 0x00000070 */ + u32 SysPllSocCfg1; /* 0x00000074 */ + u32 SysPllDdrCfg0; /* 0x00000078 */ + u32 SysPllDdrCfg1; /* 0x0000007c */ + u32 SysClkSelCfg; /* 0x00000080 */ + u32 SysClkDivCfg; /* 0x00000084 */ + u32 SysClkPeriCfg[2]; /* 0x00000088 */ + u32 SysDbgCreditCtl; /* 0x00000090 */ + u32 rsv37; + u32 SysI2CMultiCtl; /* 0x00000098 */ + u32 BootStrapPin; /* 0x0000009c */ + u32 SysCntValue[2]; /* 0x000000a0 */ + u32 SysCntLog; /* 0x000000a8 */ + u32 rsv43; + u32 rsv44; + u32 rsv45; + u32 SysCoreGicAddrBase; /* 0x000000b8 */ + u32 rsv47; + u32 SysCorePmCfg; /* 0x000000c0 */ + u32 SysCoreStatus; /* 0x000000c4 */ + u32 SysCorePmuEvent0; /* 0x000000c8 */ + u32 SysCorePmuEvent1; /* 0x000000cc */ + u32 SysRstVecBar0[2]; /* 0x000000d0 */ + u32 SysRstVecBar1[2]; /* 0x000000d8 */ + u32 SysGicCfg; /* 0x000000e0 */ + u32 SysGicStatus; /* 0x000000e4 */ + u32 rsv58; + u32 SysMemCtl; /* 0x000000ec */ + u32 SysDmaMapCfg; /* 0x000000f0 */ + u32 SysDmaAbortCfg; /* 0x000000f4 */ + u32 rsv62; + u32 rsv63; + u32 SysCstCfg; /* 0x00000100 */ + u32 SysCstTargetIdCfg; /* 0x00000104 */ + u32 SysCstMemMapIdCfg; /* 0x00000108 */ + u32 rsv67; + u32 SysQspiBootCfg0; /* 0x00000110 */ + u32 SysQspiBootCfg1; /* 0x00000114 */ + u32 SysQspiBootCfg2; /* 0x00000118 */ + u32 SysQspiBootCfg3; /* 0x0000011c */ + u32 SysDdrCfg; /* 0x00000120 */ + u32 rsv73; + u32 SysSpiSelCfg; /* 0x00000128 */ + u32 SysMdioSocCfg; /* 0x0000012c */ + u32 SysWdt0Cnt; /* 0x00000130 */ + u32 SysWdt0Rev; /* 0x00000134 */ + u32 SysWdt1Cnt; /* 0x00000138 */ + u32 SysWdt1Rev; /* 0x0000013c */ + u32 SysMshCfg; /* 0x00000140 */ + u32 SysMshStatus; /* 0x00000144 */ + u32 SysUsbCfg0; /* 0x00000148 */ + u32 SysUsbCfg1; /* 0x0000014c */ + u32 SysUsbCfg2; /* 0x00000150 */ + u32 SysUsbStatus; /* 0x00000154 */ + u32 rsv86; + u32 rsv87; + u32 rsv88; + u32 rsv89; + u32 rsv90; + u32 rsv91; + u32 rsv92; + u32 rsv93; + u32 SysPcieBaseCfg; /* 0x00000178 */ + u32 SysRegCfg; /* 0x0000017c */ + u32 SysInitCtl[2]; /* 0x00000180 */ + u32 SysPllSupCfg0; /* 0x00000188 */ + u32 SysPllSupCfg1; /* 0x0000018c */ + u32 SysApbProcTimer; /* 0x00000190 */ + u32 rsv101; + u32 SysUsbTest[2]; /* 0x00000198 */ + u32 SysGpioMultiCtl; /* 0x000001a0 */ + u32 rsv105; + u32 SysGpioHsMultiCtl[2]; /* 0x000001a8 */ + u32 rsv108; + u32 rsv109; + u32 SysPcieStatus[2]; /* 0x000001b8 */ + u32 SysMsixStatus[8]; /* 0x000001c0 */ + u32 SysMsixMask[8]; /* 0x000001e0 */ + u32 SysMsixAddr; /* 0x00000200 */ + u32 SysMsixVecCtl; /* 0x00000204 */ + u32 SysMsixAddrEn; /* 0x00000208 */ + u32 SysMsixIntrLog; /* 0x0000020c */ + u32 SysDebugCtl; /* 0x00000210 */ + u32 rsv133; + u32 rsv134; + u32 rsv135; + u32 SysMsixPending[8]; /* 0x00000220 */ + u32 SysPwmCtl[8]; /* 0x00000240 */ + u32 SysTachLog[8]; /* 0x00000260 */ + u32 MonAxiCpuCurInfo[14]; /* 0x00000280 */ + u32 rsv174; + u32 rsv175; + u32 MonAxiCpuLogInfo[14]; /* 0x000002c0 */ + u32 rsv190; + u32 rsv191; + u32 MonAxiDdr0CurInfo[14]; /* 0x00000300 */ + u32 rsv206; + u32 rsv207; + u32 MonAxiDdr0LogInfo[14]; /* 0x00000340 */ + u32 rsv222; + u32 rsv223; + u32 MonAxiDdr1CurInfo[10]; /* 0x00000380 */ + u32 rsv234; + u32 rsv235; + u32 rsv236; + u32 rsv237; + u32 rsv238; + u32 rsv239; + u32 MonAxiDdr1LogInfo[10]; /* 0x000003c0 */ + u32 rsv250; + u32 rsv251; + u32 rsv252; + u32 rsv253; + u32 rsv254; + u32 rsv255; + u32 MonAxiMemCurInfo[10]; /* 0x00000400 */ + u32 rsv266; + u32 rsv267; + u32 rsv268; + u32 rsv269; + u32 rsv270; + u32 rsv271; + u32 MonAxiMemLogInfo[10]; /* 0x00000440 */ + u32 rsv282; + u32 rsv283; + u32 rsv284; + u32 rsv285; + u32 rsv286; + u32 rsv287; + u32 MonAxiMshCurInfo[9]; /* 0x00000480 */ + u32 rsv297; + u32 rsv298; + u32 rsv299; + u32 rsv300; + u32 rsv301; + u32 rsv302; + u32 rsv303; + u32 MonAxiMshLogInfo[9]; /* 0x000004c0 */ + u32 rsv313; + u32 rsv314; + u32 rsv315; + u32 rsv316; + u32 rsv317; + u32 rsv318; + u32 rsv319; + u32 MonAxiPcieCurInfo[10]; /* 0x00000500 */ + u32 rsv330; + u32 rsv331; + u32 rsv332; + u32 rsv333; + u32 rsv334; + u32 rsv335; + u32 MonAxiPcieLogInfo[10]; /* 0x00000540 */ + u32 rsv346; + u32 rsv347; + u32 rsv348; + u32 rsv349; + u32 rsv350; + u32 rsv351; + u32 MonAxiQspiCurInfo[7]; /* 0x00000580 */ + u32 rsv359; + u32 MonAxiQspiLogInfo[8]; /* 0x000005a0 */ + u32 MonAxiSupCurInfo[8]; /* 0x000005c0 */ + u32 MonAxiSupLogInfo[8]; /* 0x000005e0 */ + u32 MonSysApbCurInfo[4]; /* 0x00000600 */ + u32 MonSysApbLogInfo[4]; /* 0x00000610 */ + u32 MonSecApbCurInfo[4]; /* 0x00000620 */ + u32 MonSecApbLogInfo[4]; /* 0x00000630 */ + u32 DebugCpuCnt[2]; /* 0x00000640 */ + u32 DebugMemCnt[2]; /* 0x00000648 */ + u32 DebugDdrCnt[4]; /* 0x00000650 */ + u32 DebugMshCnt[2]; /* 0x00000660 */ + u32 DebugPcieCnt[2]; /* 0x00000668 */ + u32 DebugQspiCnt[2]; /* 0x00000670 */ + u32 DebugSupCnt[2]; /* 0x00000678 */ + u32 SysSpiVecLog[5]; /* 0x00000680 */ + u32 rsv421; + u32 rsv422; + u32 rsv423; + u32 DebugAhbRespCnt; /* 0x000006a0 */ + u32 DebugGicRespCnt; /* 0x000006a4 */ + u32 DebugMemPtrCfg; /* 0x000006a8 */ + u32 rsv427; + u32 rsv428; + u32 rsv429; + u32 rsv430; + u32 rsv431; + u32 rsv432; + u32 rsv433; + u32 rsv434; + u32 rsv435; + u32 rsv436; + u32 rsv437; + u32 rsv438; + u32 rsv439; + u32 rsv440; + u32 rsv441; + u32 rsv442; + u32 rsv443; + u32 rsv444; + u32 rsv445; + u32 rsv446; + u32 rsv447; + u32 Grant0IntMask; /* 0x00000700 */ + u32 Grant0IntCtl; /* 0x00000704 */ + u32 Grant1IntMask; /* 0x00000708 */ + u32 Grant1IntCtl; /* 0x0000070c */ + u32 Grant2IntMask; /* 0x00000710 */ + u32 Grant2IntCtl; /* 0x00000714 */ + u32 Grant3IntMask; /* 0x00000718 */ + u32 Grant3IntCtl; /* 0x0000071c */ + u32 SysIntrIntCtl[2]; /* 0x00000720 */ + u32 SupIntrIntCtl[2]; /* 0x00000728 */ + u32 SysMiscInfo0; /* 0x00000730 */ + u32 SysMiscInfo1; /* 0x00000734 */ + u32 SysMiscInfo2; /* 0x00000738 */ + u32 SysMiscInfo3; /* 0x0000073c */ + u32 CommonInfo0; /* 0x00000740 */ + u32 CommonInfo1; /* 0x00000744 */ + u32 CommonInfo2; /* 0x00000748 */ + u32 CommonInfo3; /* 0x0000074c */ + u32 rsv468; + u32 rsv469; + u32 rsv470; + u32 rsv471; + u32 rsv472; + u32 rsv473; + u32 rsv474; + u32 rsv475; + u32 rsv476; + u32 rsv477; + u32 rsv478; + u32 rsv479; + u32 Grant0ExtMask; /* 0x00000780 */ + u32 Grant0ExtCtl; /* 0x00000784 */ + u32 Grant1ExtMask; /* 0x00000788 */ + u32 Grant1ExtCtl; /* 0x0000078c */ + u32 Grant2ExtMask; /* 0x00000790 */ + u32 Grant2ExtCtl; /* 0x00000794 */ + u32 Grant3ExtMask; /* 0x00000798 */ + u32 Grant3ExtCtl; /* 0x0000079c */ + u32 SysIntrExtCtl[2]; /* 0x000007a0 */ + u32 SupIntrExtCtl[2]; /* 0x000007a8 */ + u32 SupMiscInfo0; /* 0x000007b0 */ + u32 SupMiscInfo1; /* 0x000007b4 */ + u32 SupMiscInfo2; /* 0x000007b8 */ + u32 SupMiscInfo3; /* 0x000007bc */ +}; + +/* ############################################################################ + * # SysResetCtl Definition + */ +#define SYS_RESET_CTL_W0_CFG_NIC_RESET BIT(9) +#define SYS_RESET_CTL_W0_LOG_CST_RESET BIT(23) +#define SYS_RESET_CTL_W0_CFG_SYS_APB_RESET BIT(12) +#define SYS_RESET_CTL_W0_LOG_NIC_RESET BIT(25) +#define SYS_RESET_CTL_W0_LOG_CPU0_COLD_RESET BIT(16) +#define SYS_RESET_CTL_W0_CFG_CPU_APB_RESET BIT(5) +#define SYS_RESET_CTL_W0_CFG_CPU1_COLD_RESET BIT(1) +#define SYS_RESET_CTL_W0_CFG_CPU1_CORE_RESET BIT(3) +#define SYS_RESET_CTL_W0_LOG_CPU_APB_RESET BIT(21) +#define SYS_RESET_CTL_W0_CFG_SEC_APB_RESET BIT(11) +#define SYS_RESET_CTL_W0_CFG_CPU0_CORE_RESET BIT(2) +#define SYS_RESET_CTL_W0_LOG_SEC_APB_RESET BIT(27) +#define SYS_RESET_CTL_W0_CFG_CPU0_COLD_RESET BIT(0) +#define SYS_RESET_CTL_W0_CFG_CST_RESET BIT(7) +#define SYS_RESET_CTL_W0_LOG_JTAG_POT_RESET BIT(22) +#define SYS_RESET_CTL_W0_LOG_CPU1_CORE_RESET BIT(19) +#define SYS_RESET_CTL_W0_LOG_SYS_APB_RESET BIT(28) +#define SYS_RESET_CTL_W0_LOG_CPU0_CORE_RESET BIT(18) +#define SYS_RESET_CTL_W0_LOG_CPU1_COLD_RESET BIT(17) +#define SYS_RESET_CTL_W0_LOG_CPU_L2_RESET BIT(20) +#define SYS_RESET_CTL_W0_LOG_GPV_RESET BIT(26) +#define SYS_RESET_CTL_W0_CFG_CPU_L2_RESET BIT(4) +#define SYS_RESET_CTL_W0_CFG_GPV_RESET BIT(10) +#define SYS_RESET_CTL_W0_CFG_JTAG_POT_RESET BIT(6) +#define SYS_RESET_CTL_W0_CFG_CPU_MEM_RESET BIT(8) +#define SYS_RESET_CTL_W0_LOG_CPU_MEM_RESET BIT(24) + +#define SYS_RESET_CTL_W0_CFG_NIC_RESET_MASK 0x00000200 +#define SYS_RESET_CTL_W0_LOG_CST_RESET_MASK 0x00800000 +#define SYS_RESET_CTL_W0_CFG_SYS_APB_RESET_MASK 0x00001000 +#define SYS_RESET_CTL_W0_LOG_NIC_RESET_MASK 0x02000000 +#define SYS_RESET_CTL_W0_LOG_CPU0_COLD_RESET_MASK 0x00010000 +#define SYS_RESET_CTL_W0_CFG_CPU_APB_RESET_MASK 0x00000020 +#define SYS_RESET_CTL_W0_CFG_CPU1_COLD_RESET_MASK 0x00000002 +#define SYS_RESET_CTL_W0_CFG_CPU1_CORE_RESET_MASK 0x00000008 +#define SYS_RESET_CTL_W0_LOG_CPU_APB_RESET_MASK 0x00200000 +#define SYS_RESET_CTL_W0_CFG_SEC_APB_RESET_MASK 0x00000800 +#define SYS_RESET_CTL_W0_CFG_CPU0_CORE_RESET_MASK 0x00000004 +#define SYS_RESET_CTL_W0_LOG_SEC_APB_RESET_MASK 0x08000000 +#define SYS_RESET_CTL_W0_CFG_CPU0_COLD_RESET_MASK 0x00000001 +#define SYS_RESET_CTL_W0_CFG_CST_RESET_MASK 0x00000080 +#define SYS_RESET_CTL_W0_LOG_JTAG_POT_RESET_MASK 0x00400000 +#define SYS_RESET_CTL_W0_LOG_CPU1_CORE_RESET_MASK 0x00080000 +#define SYS_RESET_CTL_W0_LOG_SYS_APB_RESET_MASK 0x10000000 +#define SYS_RESET_CTL_W0_LOG_CPU0_CORE_RESET_MASK 0x00040000 +#define SYS_RESET_CTL_W0_LOG_CPU1_COLD_RESET_MASK 0x00020000 +#define SYS_RESET_CTL_W0_LOG_CPU_L2_RESET_MASK 0x00100000 +#define SYS_RESET_CTL_W0_LOG_GPV_RESET_MASK 0x04000000 +#define SYS_RESET_CTL_W0_CFG_CPU_L2_RESET_MASK 0x00000010 +#define SYS_RESET_CTL_W0_CFG_GPV_RESET_MASK 0x00000400 +#define SYS_RESET_CTL_W0_CFG_JTAG_POT_RESET_MASK 0x00000040 +#define SYS_RESET_CTL_W0_CFG_CPU_MEM_RESET_MASK 0x00000100 +#define SYS_RESET_CTL_W0_LOG_CPU_MEM_RESET_MASK 0x01000000 + +/* ############################################################################ + * # SysResetAutoEn Definition + */ +#define SYS_RESET_AUTO_EN_W0_CFG_CPU1_CORE_RESET_AUTO_EN BIT(3) +#define SYS_RESET_AUTO_EN_W0_CFG_NIC_RESET_AUTO_EN BIT(9) +#define SYS_RESET_AUTO_EN_W0_CFG_CST_RESET_AUTO_EN BIT(7) +#define SYS_RESET_AUTO_EN_W0_CFG_WDT1_RESET_AUTO_EN BIT(14) +#define SYS_RESET_AUTO_EN_W0_CFG_CPU0_COLD_RESET_AUTO_EN BIT(0) +#define SYS_RESET_AUTO_EN_W0_CFG_GPV_RESET_AUTO_EN BIT(10) +#define SYS_RESET_AUTO_EN_W0_CFG_WDT0_RESET_AUTO_EN BIT(13) +#define SYS_RESET_AUTO_EN_W0_CFG_JTAG_POT_RESET_AUTO_EN BIT(6) +#define SYS_RESET_AUTO_EN_W0_CFG_SEC_APB_RESET_AUTO_EN BIT(11) +#define SYS_RESET_AUTO_EN_W0_CFG_CPU_MEM_RESET_AUTO_EN BIT(8) +#define SYS_RESET_AUTO_EN_W0_CFG_SYS_APB_RESET_AUTO_EN BIT(12) +#define SYS_RESET_AUTO_EN_W0_CFG_CPU_L2_RESET_AUTO_EN BIT(4) +#define SYS_RESET_AUTO_EN_W0_CFG_CPU_APB_RESET_AUTO_EN BIT(5) +#define SYS_RESET_AUTO_EN_W0_CFG_CPU1_COLD_RESET_AUTO_EN BIT(1) +#define SYS_RESET_AUTO_EN_W0_CFG_CPU0_CORE_RESET_AUTO_EN BIT(2) + +#define SYS_RESET_AUTO_EN_W0_CFG_CPU1_CORE_RESET_AUTO_EN_MASK 0x00000008 +#define SYS_RESET_AUTO_EN_W0_CFG_NIC_RESET_AUTO_EN_MASK 0x00000200 +#define SYS_RESET_AUTO_EN_W0_CFG_CST_RESET_AUTO_EN_MASK 0x00000080 +#define SYS_RESET_AUTO_EN_W0_CFG_WDT1_RESET_AUTO_EN_MASK 0x00004000 +#define SYS_RESET_AUTO_EN_W0_CFG_CPU0_COLD_RESET_AUTO_EN_MASK 0x00000001 +#define SYS_RESET_AUTO_EN_W0_CFG_GPV_RESET_AUTO_EN_MASK 0x00000400 +#define SYS_RESET_AUTO_EN_W0_CFG_WDT0_RESET_AUTO_EN_MASK 0x00002000 +#define SYS_RESET_AUTO_EN_W0_CFG_JTAG_POT_RESET_AUTO_EN_MASK 0x00000040 +#define SYS_RESET_AUTO_EN_W0_CFG_SEC_APB_RESET_AUTO_EN_MASK 0x00000800 +#define SYS_RESET_AUTO_EN_W0_CFG_CPU_MEM_RESET_AUTO_EN_MASK 0x00000100 +#define SYS_RESET_AUTO_EN_W0_CFG_SYS_APB_RESET_AUTO_EN_MASK 0x00001000 +#define SYS_RESET_AUTO_EN_W0_CFG_CPU_L2_RESET_AUTO_EN_MASK 0x00000010 +#define SYS_RESET_AUTO_EN_W0_CFG_CPU_APB_RESET_AUTO_EN_MASK 0x00000020 +#define SYS_RESET_AUTO_EN_W0_CFG_CPU1_COLD_RESET_AUTO_EN_MASK 0x00000002 +#define SYS_RESET_AUTO_EN_W0_CFG_CPU0_CORE_RESET_AUTO_EN_MASK 0x00000004 + +/* ############################################################################ + * # SysGicResetCtl Definition + */ +#define SYS_GIC_RESET_CTL_W0_CFG_GIC_RESET BIT(0) + +#define SYS_GIC_RESET_CTL_W0_CFG_GIC_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysWdtResetCtl Definition + */ +#define SYS_WDT_RESET_CTL_W0_LOG_WDT1_RESET BIT(5) +#define SYS_WDT_RESET_CTL_W0_CFG_WDT0_RESET BIT(0) +#define SYS_WDT_RESET_CTL_W0_LOG_WDT0_RESET BIT(4) +#define SYS_WDT_RESET_CTL_W0_CFG_WDT1_RESET BIT(1) + +#define SYS_WDT_RESET_CTL_W0_LOG_WDT1_RESET_MASK 0x00000020 +#define SYS_WDT_RESET_CTL_W0_CFG_WDT0_RESET_MASK 0x00000001 +#define SYS_WDT_RESET_CTL_W0_LOG_WDT0_RESET_MASK 0x00000010 +#define SYS_WDT_RESET_CTL_W0_CFG_WDT1_RESET_MASK 0x00000002 + +/* ############################################################################ + * # SysDmaResetCtl Definition + */ +#define SYS_DMA_RESET_CTL_W0_CFG_CPU_DMA_RESET BIT(0) + +#define SYS_DMA_RESET_CTL_W0_CFG_CPU_DMA_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysDdrResetCtl Definition + */ +#define SYS_DDR_RESET_CTL_W0_CFG_DDR_MC_RESET BIT(2) +#define SYS_DDR_RESET_CTL_W0_CFG_DDR_CFG_RESET BIT(0) +#define SYS_DDR_RESET_CTL_W0_CFG_DDR_AXI_RESET BIT(1) + +#define SYS_DDR_RESET_CTL_W0_CFG_DDR_MC_RESET_MASK 0x00000004 +#define SYS_DDR_RESET_CTL_W0_CFG_DDR_CFG_RESET_MASK 0x00000001 +#define SYS_DDR_RESET_CTL_W0_CFG_DDR_AXI_RESET_MASK 0x00000002 + +/* ############################################################################ + * # SysPcieResetCtl Definition + */ +#define SYS_PCIE_RESET_CTL_W0_CFG_PIPE_RESET BIT(1) +#define SYS_PCIE_RESET_CTL_W0_CFG_PHY_REG_RESET BIT(3) +#define SYS_PCIE_RESET_CTL_W0_CFG_PCIE_RESET BIT(0) +#define SYS_PCIE_RESET_CTL_W0_CFG_PCIE_POR BIT(2) + +#define SYS_PCIE_RESET_CTL_W0_CFG_PIPE_RESET_MASK 0x00000002 +#define SYS_PCIE_RESET_CTL_W0_CFG_PHY_REG_RESET_MASK 0x00000008 +#define SYS_PCIE_RESET_CTL_W0_CFG_PCIE_RESET_MASK 0x00000001 +#define SYS_PCIE_RESET_CTL_W0_CFG_PCIE_POR_MASK 0x00000004 + +/* ############################################################################ + * # SysMacResetCtl Definition + */ +#define SYS_MAC_RESET_CTL_W0_CFG_CPU_MAC_RESET BIT(0) + +#define SYS_MAC_RESET_CTL_W0_CFG_CPU_MAC_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysMshResetCtl Definition + */ +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_C_TX_RESET BIT(3) +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_C_RX_DLL_RESET BIT(6) +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_CFG_RESET BIT(1) +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_REF_C_RESET BIT(4) +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_C_RX_RESET BIT(2) +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_AXI_RESET BIT(0) +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_TM_RESET BIT(5) + +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_C_TX_RESET_MASK 0x00000008 +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_C_RX_DLL_RESET_MASK 0x00000040 +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_CFG_RESET_MASK 0x00000002 +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_REF_C_RESET_MASK 0x00000010 +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_C_RX_RESET_MASK 0x00000004 +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_AXI_RESET_MASK 0x00000001 +#define SYS_MSH_RESET_CTL_W0_CFG_MSH_TM_RESET_MASK 0x00000020 + +/* ############################################################################ + * # SysUsbResetCtl Definition + */ +#define SYS_USB_RESET_CTL_W0_CFG_USB_INTF_RESET BIT(0) +#define SYS_USB_RESET_CTL_W0_CFG_USB_PHY_RESET BIT(2) +#define SYS_USB_RESET_CTL_W0_CFG_USB_PHY_ATE_RESET BIT(6) +#define SYS_USB_RESET_CTL_W0_CFG_USB_PHY_PORT_RESET BIT(5) +#define SYS_USB_RESET_CTL_W0_CFG_USB_UTMI_RESET BIT(3) +#define SYS_USB_RESET_CTL_W0_CFG_USB_AUX_RESET BIT(1) +#define SYS_USB_RESET_CTL_W0_CFG_USB_PHY_PWR_ON_RESET BIT(4) + +#define SYS_USB_RESET_CTL_W0_CFG_USB_INTF_RESET_MASK 0x00000001 +#define SYS_USB_RESET_CTL_W0_CFG_USB_PHY_RESET_MASK 0x00000004 +#define SYS_USB_RESET_CTL_W0_CFG_USB_PHY_ATE_RESET_MASK 0x00000040 +#define SYS_USB_RESET_CTL_W0_CFG_USB_PHY_PORT_RESET_MASK 0x00000020 +#define SYS_USB_RESET_CTL_W0_CFG_USB_UTMI_RESET_MASK 0x00000008 +#define SYS_USB_RESET_CTL_W0_CFG_USB_AUX_RESET_MASK 0x00000002 +#define SYS_USB_RESET_CTL_W0_CFG_USB_PHY_PWR_ON_RESET_MASK 0x00000010 + +/* ############################################################################ + * # SysSpiResetCtl Definition + */ +#define SYS_SPI_RESET_CTL_W0_CFG_SPI_RESET BIT(0) + +#define SYS_SPI_RESET_CTL_W0_CFG_SPI_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysQspiResetCtl Definition + */ +#define SYS_QSPI_RESET_CTL_W0_CFG_QSPI_RESET BIT(0) + +#define SYS_QSPI_RESET_CTL_W0_CFG_QSPI_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysAxiSupResetCtl Definition + */ +#define SYS_AXI_SUP_RESET_CTL_W0_CFG_SWITCH_CORE_RESET BIT(1) +#define SYS_AXI_SUP_RESET_CTL_W0_CFG_SWITCH_SUP_RESET BIT(2) +#define SYS_AXI_SUP_RESET_CTL_W0_CFG_AXI_SUP_RESET BIT(0) + +#define SYS_AXI_SUP_RESET_CTL_W0_CFG_SWITCH_CORE_RESET_MASK 0x00000002 +#define SYS_AXI_SUP_RESET_CTL_W0_CFG_SWITCH_SUP_RESET_MASK 0x00000004 +#define SYS_AXI_SUP_RESET_CTL_W0_CFG_AXI_SUP_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysGpioResetCtl Definition + */ +#define SYS_GPIO_RESET_CTL_W0_CFG_GPIO_RESET BIT(0) + +#define SYS_GPIO_RESET_CTL_W0_CFG_GPIO_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysI2CResetCtl Definition + */ +#define SYS_I2_C_RESET_CTL_W0_CFG_I2_C0_RESET BIT(0) +#define SYS_I2_C_RESET_CTL_W0_CFG_I2_C1_RESET BIT(1) + +#define SYS_I2_C_RESET_CTL_W0_CFG_I2_C0_RESET_MASK 0x00000001 +#define SYS_I2_C_RESET_CTL_W0_CFG_I2_C1_RESET_MASK 0x00000002 + +/* ############################################################################ + * # SysMdioSocResetCtl Definition + */ +#define SYS_MDIO_SOC_RESET_CTL_W0_CFG_MDIO_SOC_RESET BIT(0) + +#define SYS_MDIO_SOC_RESET_CTL_W0_CFG_MDIO_SOC_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysTimerResetCtl Definition + */ +#define SYS_TIMER_RESET_CTL_W0_CFG_TIMER_RESET BIT(0) + +#define SYS_TIMER_RESET_CTL_W0_CFG_TIMER_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysUartResetCtl Definition + */ +#define SYS_UART_RESET_CTL_W0_CFG_UART1_RESET BIT(1) +#define SYS_UART_RESET_CTL_W0_CFG_UART2_RESET BIT(2) +#define SYS_UART_RESET_CTL_W0_CFG_UART0_RESET BIT(0) + +#define SYS_UART_RESET_CTL_W0_CFG_UART1_RESET_MASK 0x00000002 +#define SYS_UART_RESET_CTL_W0_CFG_UART2_RESET_MASK 0x00000004 +#define SYS_UART_RESET_CTL_W0_CFG_UART0_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysTraceResetCtl Definition + */ +#define SYS_TRACE_RESET_CTL_W0_CFG_TRACE_RESET BIT(0) + +#define SYS_TRACE_RESET_CTL_W0_CFG_TRACE_RESET_MASK 0x00000001 + +/* ############################################################################ + * # SysDbg0ResetEnCtl Definition + */ +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU_L2 BIT(4) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU1_CORE BIT(3) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CST BIT(7) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU0_COLD BIT(0) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_WDT0 BIT(9) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_WDT1 BIT(10) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU1_COLD BIT(1) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU0_CORE BIT(2) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU_MEM BIT(8) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_NIC BIT(11) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_JTAG_POT BIT(6) +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU_APB BIT(5) + +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU_L2_MASK 0x00000010 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU1_CORE_MASK 0x00000008 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CST_MASK 0x00000080 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU0_COLD_MASK 0x00000001 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_WDT0_MASK 0x00000200 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_WDT1_MASK 0x00000400 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU1_COLD_MASK 0x00000002 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU0_CORE_MASK 0x00000004 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU_MEM_MASK 0x00000100 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_NIC_MASK 0x00000800 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_JTAG_POT_MASK 0x00000040 +#define SYS_DBG0_RESET_EN_CTL_W0_DBG0_RST_EN_CPU_APB_MASK 0x00000020 + +/* ############################################################################ + * # SysDbg1ResetEnCtl Definition + */ +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU1_CORE BIT(3) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU_APB BIT(5) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_JTAG_POT BIT(6) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU0_COLD BIT(0) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU_MEM BIT(8) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU1_COLD BIT(1) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU0_CORE BIT(2) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CST BIT(7) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_WDT0 BIT(9) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU_L2 BIT(4) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_WDT1 BIT(10) +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_NIC BIT(11) + +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU1_CORE_MASK 0x00000008 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU_APB_MASK 0x00000020 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_JTAG_POT_MASK 0x00000040 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU0_COLD_MASK 0x00000001 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU_MEM_MASK 0x00000100 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU1_COLD_MASK 0x00000002 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU0_CORE_MASK 0x00000004 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CST_MASK 0x00000080 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_WDT0_MASK 0x00000200 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_CPU_L2_MASK 0x00000010 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_WDT1_MASK 0x00000400 +#define SYS_DBG1_RESET_EN_CTL_W0_DBG1_RST_EN_NIC_MASK 0x00000800 + +/* ############################################################################ + * # SysWarm0ResetEnCtl Definition + */ +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU1_COLD BIT(1) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_WDT0 BIT(9) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU0_COLD BIT(0) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU_L2 BIT(4) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_JTAG_POT BIT(6) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CST BIT(7) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU_APB BIT(5) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU0_CORE BIT(2) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU_MEM BIT(8) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_WDT1 BIT(10) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_NIC BIT(11) +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU1_CORE BIT(3) + +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU1_COLD_MASK 0x00000002 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_WDT0_MASK 0x00000200 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU0_COLD_MASK 0x00000001 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU_L2_MASK 0x00000010 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_JTAG_POT_MASK 0x00000040 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CST_MASK 0x00000080 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU_APB_MASK 0x00000020 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU0_CORE_MASK 0x00000004 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU_MEM_MASK 0x00000100 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_WDT1_MASK 0x00000400 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_NIC_MASK 0x00000800 +#define SYS_WARM0_RESET_EN_CTL_W0_WARM0_RST_EN_CPU1_CORE_MASK 0x00000008 + +/* ############################################################################ + * # SysWarm1ResetEnCtl Definition + */ +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU_MEM BIT(8) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU1_COLD BIT(1) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_WDT1 BIT(10) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU_APB BIT(5) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CST BIT(7) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_NIC BIT(11) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU0_COLD BIT(0) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU1_CORE BIT(3) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU_L2 BIT(4) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_WDT0 BIT(9) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_JTAG_POT BIT(6) +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU0_CORE BIT(2) + +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU_MEM_MASK 0x00000100 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU1_COLD_MASK 0x00000002 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_WDT1_MASK 0x00000400 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU_APB_MASK 0x00000020 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CST_MASK 0x00000080 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_NIC_MASK 0x00000800 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU0_COLD_MASK 0x00000001 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU1_CORE_MASK 0x00000008 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU_L2_MASK 0x00000010 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_WDT0_MASK 0x00000200 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_JTAG_POT_MASK 0x00000040 +#define SYS_WARM1_RESET_EN_CTL_W0_WARM1_RST_EN_CPU0_CORE_MASK 0x00000004 + +/* ############################################################################ + * # SysWdt0ResetEnCtl Definition + */ +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU_L2 BIT(4) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU1_COLD BIT(1) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU_APB BIT(5) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_WDT1 BIT(10) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CST BIT(7) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU0_CORE BIT(2) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_WDT0 BIT(9) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU_MEM BIT(8) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_JTAG_POT BIT(6) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU1_CORE BIT(3) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU0_COLD BIT(0) +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_NIC BIT(11) + +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU_L2_MASK 0x00000010 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU1_COLD_MASK 0x00000002 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU_APB_MASK 0x00000020 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_WDT1_MASK 0x00000400 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CST_MASK 0x00000080 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU0_CORE_MASK 0x00000004 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_WDT0_MASK 0x00000200 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU_MEM_MASK 0x00000100 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_JTAG_POT_MASK 0x00000040 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU1_CORE_MASK 0x00000008 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_CPU0_COLD_MASK 0x00000001 +#define SYS_WDT0_RESET_EN_CTL_W0_WDT0_RST_EN_NIC_MASK 0x00000800 + +/* ############################################################################ + * # SysWdt1ResetEnCtl Definition + */ +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU_L2 BIT(4) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_WDT0 BIT(9) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_WDT1 BIT(10) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU1_CORE BIT(3) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU_APB BIT(5) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CST BIT(7) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU0_COLD BIT(0) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU_MEM BIT(8) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU1_COLD BIT(1) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_JTAG_POT BIT(6) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU0_CORE BIT(2) +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_NIC BIT(11) + +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU_L2_MASK 0x00000010 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_WDT0_MASK 0x00000200 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_WDT1_MASK 0x00000400 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU1_CORE_MASK 0x00000008 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU_APB_MASK 0x00000020 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CST_MASK 0x00000080 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU0_COLD_MASK 0x00000001 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU_MEM_MASK 0x00000100 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU1_COLD_MASK 0x00000002 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_JTAG_POT_MASK 0x00000040 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_CPU0_CORE_MASK 0x00000004 +#define SYS_WDT1_RESET_EN_CTL_W0_WDT1_RST_EN_NIC_MASK 0x00000800 + +/* ############################################################################ + * # SysCtlReserved Definition + */ +#define SYS_CTL_RESERVED_W0_RESERVED BIT(0) + +#define SYS_CTL_RESERVED_W0_RESERVED_MASK 0xffffffff + +/* ############################################################################ + * # SysEnClkCfg Definition + */ +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_MSH BIT(2) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_CPU_DMA BIT(5) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_CPU_MEM BIT(8) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_CPU_MAC BIT(7) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_CST BIT(4) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_TZC BIT(3) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_MISC BIT(12) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_DDR BIT(0) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_SSP BIT(10) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_GIC BIT(6) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_USB BIT(1) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_AXI_SUP BIT(9) +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_QSPI BIT(11) + +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_MSH_MASK 0x00000004 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_CPU_DMA_MASK 0x00000020 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_CPU_MEM_MASK 0x00000100 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_CPU_MAC_MASK 0x00000080 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_CST_MASK 0x00000010 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_TZC_MASK 0x00000008 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_MISC_MASK 0x00001000 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_DDR_MASK 0x00000001 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_SSP_MASK 0x00000400 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_GIC_MASK 0x00000040 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_USB_MASK 0x00000002 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_AXI_SUP_MASK 0x00000200 +#define SYS_EN_CLK_CFG_W0_CFG_EN_CLK_QSPI_MASK 0x00000800 + +/* ############################################################################ + * # SysPllSocCfg0 Definition + */ +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_POST_DIV BIT(12) +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_MULT_INT BIT(20) +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_INT_FBK BIT(2) +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_DCO_BYPASS BIT(1) +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_PRE_DIV BIT(4) +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_RESET BIT(0) +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_PLL_PWD BIT(3) + +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_POST_DIV_MASK 0x0003f000 +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_MULT_INT_MASK 0x0ff00000 +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_INT_FBK_MASK 0x00000004 +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_DCO_BYPASS_MASK 0x00000002 +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_PRE_DIV_MASK 0x000001f0 +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_RESET_MASK 0x00000001 +#define SYS_PLL_SOC_CFG0_W0_PLL_SOC_PLL_PWD_MASK 0x00000008 + +/* ############################################################################ + * # SysPllSocCfg1 Definition + */ +#define SYS_PLL_SOC_CFG1_W0_PLL_SOC_BYPASS BIT(24) +#define SYS_PLL_SOC_CFG1_W0_PLL_SOC_SLOCK BIT(16) +#define SYS_PLL_SOC_CFG1_W0_PLL_SOC_SGAIN BIT(20) +#define SYS_PLL_SOC_CFG1_W0_PLL_SOC_SIP BIT(0) +#define SYS_PLL_SOC_CFG1_W0_MON_PLL_SOC_LOCK BIT(28) +#define SYS_PLL_SOC_CFG1_W0_PLL_SOC_SIC BIT(8) + +#define SYS_PLL_SOC_CFG1_W0_PLL_SOC_BYPASS_MASK 0x01000000 +#define SYS_PLL_SOC_CFG1_W0_PLL_SOC_SLOCK_MASK 0x00010000 +#define SYS_PLL_SOC_CFG1_W0_PLL_SOC_SGAIN_MASK 0x00700000 +#define SYS_PLL_SOC_CFG1_W0_PLL_SOC_SIP_MASK 0x0000001f +#define SYS_PLL_SOC_CFG1_W0_MON_PLL_SOC_LOCK_MASK 0x10000000 +#define SYS_PLL_SOC_CFG1_W0_PLL_SOC_SIC_MASK 0x00001f00 + +/* ############################################################################ + * # SysPllDdrCfg0 Definition + */ +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_DCO_BYPASS BIT(1) +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_PRE_DIV BIT(4) +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_RESET BIT(0) +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_INT_FBK BIT(2) +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_PLL_PWD BIT(3) +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_MULT_INT BIT(20) +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_POST_DIV BIT(12) + +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_DCO_BYPASS_MASK 0x00000002 +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_PRE_DIV_MASK 0x000001f0 +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_RESET_MASK 0x00000001 +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_INT_FBK_MASK 0x00000004 +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_PLL_PWD_MASK 0x00000008 +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_MULT_INT_MASK 0x0ff00000 +#define SYS_PLL_DDR_CFG0_W0_PLL_DDR_POST_DIV_MASK 0x0003f000 + +/* ############################################################################ + * # SysPllDdrCfg1 Definition + */ +#define SYS_PLL_DDR_CFG1_W0_PLL_DDR_SLOCK BIT(16) +#define SYS_PLL_DDR_CFG1_W0_PLL_DDR_BYPASS BIT(24) +#define SYS_PLL_DDR_CFG1_W0_MON_PLL_DDR_LOCK BIT(28) +#define SYS_PLL_DDR_CFG1_W0_PLL_DDR_SIC BIT(8) +#define SYS_PLL_DDR_CFG1_W0_PLL_DDR_SIP BIT(0) +#define SYS_PLL_DDR_CFG1_W0_PLL_DDR_SGAIN BIT(20) + +#define SYS_PLL_DDR_CFG1_W0_PLL_DDR_SLOCK_MASK 0x00010000 +#define SYS_PLL_DDR_CFG1_W0_PLL_DDR_BYPASS_MASK 0x01000000 +#define SYS_PLL_DDR_CFG1_W0_MON_PLL_DDR_LOCK_MASK 0x10000000 +#define SYS_PLL_DDR_CFG1_W0_PLL_DDR_SIC_MASK 0x00001f00 +#define SYS_PLL_DDR_CFG1_W0_PLL_DDR_SIP_MASK 0x0000001f +#define SYS_PLL_DDR_CFG1_W0_PLL_DDR_SGAIN_MASK 0x00700000 + +/* ############################################################################ + * # SysClkSelCfg Definition + */ +#define SYS_CLK_SEL_CFG_W0_RELEASE_DIV_CLK BIT(1) +#define SYS_CLK_SEL_CFG_W0_SUP_CLOCK_SEL BIT(0) + +#define SYS_CLK_SEL_CFG_W0_RELEASE_DIV_CLK_MASK 0x00000002 +#define SYS_CLK_SEL_CFG_W0_SUP_CLOCK_SEL_MASK 0x00000001 + +/* ############################################################################ + * # SysClkDivCfg Definition + */ +#define SYS_CLK_DIV_CFG_W0_CFG_DIV_AHB_CNT BIT(8) +#define SYS_CLK_DIV_CFG_W0_CFG_DIV_TRACE_CNT BIT(16) +#define SYS_CLK_DIV_CFG_W0_CFG_DIV_CST_CNT BIT(0) +#define SYS_CLK_DIV_CFG_W0_CFG_DIV_MSH_CNT BIT(24) + +#define SYS_CLK_DIV_CFG_W0_CFG_DIV_AHB_CNT_MASK 0x0000ff00 +#define SYS_CLK_DIV_CFG_W0_CFG_DIV_TRACE_CNT_MASK 0x00ff0000 +#define SYS_CLK_DIV_CFG_W0_CFG_DIV_CST_CNT_MASK 0x000000ff +#define SYS_CLK_DIV_CFG_W0_CFG_DIV_MSH_CNT_MASK 0xff000000 + +/* ############################################################################ + * # SysClkPeriCfg Definition + */ +#define SYS_CLK_PERI_CFG_W0_CFG_DIV_USB_PHY_CNT BIT(16) +#define SYS_CLK_PERI_CFG_W0_CFG_DIV_SSP_CNT BIT(8) +#define SYS_CLK_PERI_CFG_W0_CFG_DIV_MSH_REF_CNT BIT(0) +#define SYS_CLK_PERI_CFG_W0_CFG_DIV_UART_CNT BIT(24) +#define SYS_CLK_PERI_CFG_W1_CFG_DIV_UART_CHG_EN BIT(15) +#define SYS_CLK_PERI_CFG_W1_CFG_DIV_MSH_TM_CNT BIT(0) +#define SYS_CLK_PERI_CFG_W1_CFG_DIV_MDIO_SOC_CNT BIT(16) + +#define SYS_CLK_PERI_CFG_W0_CFG_DIV_USB_PHY_CNT_MASK 0x00ff0000 +#define SYS_CLK_PERI_CFG_W0_CFG_DIV_SSP_CNT_MASK 0x0000ff00 +#define SYS_CLK_PERI_CFG_W0_CFG_DIV_MSH_REF_CNT_MASK 0x000000ff +#define SYS_CLK_PERI_CFG_W0_CFG_DIV_UART_CNT_MASK 0xff000000 +#define SYS_CLK_PERI_CFG_W1_CFG_DIV_UART_CHG_EN_MASK 0x00008000 +#define SYS_CLK_PERI_CFG_W1_CFG_DIV_MSH_TM_CNT_MASK 0x000007ff +#define SYS_CLK_PERI_CFG_W1_CFG_DIV_MDIO_SOC_CNT_MASK 0x07ff0000 + +/* ############################################################################ + * # SysDbgCreditCtl Definition + */ +#define SYS_DBG_CREDIT_CTL_W0_DBG_CREDIT_CNT BIT(8) +#define SYS_DBG_CREDIT_CTL_W0_CFG_DBG_CREDIT_CNT BIT(0) +#define SYS_DBG_CREDIT_CTL_W0_DBG_CREDIT_OK BIT(12) +#define SYS_DBG_CREDIT_CTL_W0_CFG_DBG_CREDIT_THRD BIT(4) + +#define SYS_DBG_CREDIT_CTL_W0_DBG_CREDIT_CNT_MASK 0x00000700 +#define SYS_DBG_CREDIT_CTL_W0_CFG_DBG_CREDIT_CNT_MASK 0x00000007 +#define SYS_DBG_CREDIT_CTL_W0_DBG_CREDIT_OK_MASK 0x00001000 +#define SYS_DBG_CREDIT_CTL_W0_CFG_DBG_CREDIT_THRD_MASK 0x00000070 + +/* ############################################################################ + * # SysI2CMultiCtl Definition + */ +#define SYS_I2_C_MULTI_CTL_W0_CFG_I2_C_SLAVE_EN BIT(0) + +#define SYS_I2_C_MULTI_CTL_W0_CFG_I2_C_SLAVE_EN_MASK 0x00000001 + +/* ############################################################################ + * # BootStrapPin Definition + */ +#define BOOT_STRAP_PIN_W0_BOOT_STRAP_LOG BIT(0) +#define BOOT_STRAP_PIN_W0_CPU_SPEED_LOG BIT(4) + +#define BOOT_STRAP_PIN_W0_BOOT_STRAP_LOG_MASK 0x00000007 +#define BOOT_STRAP_PIN_W0_CPU_SPEED_LOG_MASK 0x00000010 + +/* ############################################################################ + * # SysCntValue Definition + */ +#define SYS_CNT_VALUE_W0_SYS_CNT_VALUE_READ_31_0 BIT(0) +#define SYS_CNT_VALUE_W1_SYS_CNT_VALUE_READ_63_32 BIT(0) + +#define SYS_CNT_VALUE_W0_SYS_CNT_VALUE_READ_31_0_MASK 0x00000001 +#define SYS_CNT_VALUE_W1_SYS_CNT_VALUE_READ_63_32_MASK 0x00000001 + +/* ############################################################################ + * # SysCntLog Definition + */ +#define SYS_CNT_LOG_W0_SYS_CNT_HALT_READ BIT(1) +#define SYS_CNT_LOG_W0_SYS_CNT_OVER_READ BIT(2) +#define SYS_CNT_LOG_W0_SYS_CNT_DIV_READ BIT(16) +#define SYS_CNT_LOG_W0_SYS_CNT_EN_READ BIT(0) + +#define SYS_CNT_LOG_W0_SYS_CNT_HALT_READ_MASK 0x00000002 +#define SYS_CNT_LOG_W0_SYS_CNT_OVER_READ_MASK 0x00000004 +#define SYS_CNT_LOG_W0_SYS_CNT_DIV_READ_MASK 0x03ff0000 +#define SYS_CNT_LOG_W0_SYS_CNT_EN_READ_MASK 0x00000001 + +/* ############################################################################ + * # SysCoreGicAddrBase Definition + */ +#define SYS_CORE_GIC_ADDR_BASE_W0_CFG_GIC_REG_BASE BIT(0) + +#define SYS_CORE_GIC_ADDR_BASE_W0_CFG_GIC_REG_BASE_MASK 0x00ffffff + +/* ############################################################################ + * # SysCorePmCfg Definition + */ +#define SYS_CORE_PM_CFG_W0_LOG_L2_Q_ACCEPTN BIT(1) +#define SYS_CORE_PM_CFG_W0_LOG_DBG_NO_PWR_DWN BIT(4) +#define SYS_CORE_PM_CFG_W0_LOG_L2_Q_DENY BIT(2) +#define SYS_CORE_PM_CFG_W0_CFG_L2_Q_REQN BIT(8) +#define SYS_CORE_PM_CFG_W0_LOG_L2_Q_ACTIVE BIT(0) + +#define SYS_CORE_PM_CFG_W0_LOG_L2_Q_ACCEPTN_MASK 0x00000002 +#define SYS_CORE_PM_CFG_W0_LOG_DBG_NO_PWR_DWN_MASK 0x00000030 +#define SYS_CORE_PM_CFG_W0_LOG_L2_Q_DENY_MASK 0x00000004 +#define SYS_CORE_PM_CFG_W0_CFG_L2_Q_REQN_MASK 0x00000100 +#define SYS_CORE_PM_CFG_W0_LOG_L2_Q_ACTIVE_MASK 0x00000001 + +/* ############################################################################ + * # SysCoreStatus Definition + */ +#define SYS_CORE_STATUS_W0_CORE_STANDBY_WFI_L2 BIT(7) +#define SYS_CORE_STATUS_W0_JTAG_NSW_LOG BIT(8) +#define SYS_CORE_STATUS_W0_CFG_CORE1_EVENT_CLR BIT(17) +#define SYS_CORE_STATUS_W0_CORE_SMP_EN BIT(4) +#define SYS_CORE_STATUS_W0_JTAG_TOP_LOG BIT(9) +#define SYS_CORE_STATUS_W0_CORE_STANDBY_WFE BIT(2) +#define SYS_CORE_STATUS_W0_CORE_L2_FLUSH_DONE BIT(6) +#define SYS_CORE_STATUS_W0_CORE_STANDBY_WFI BIT(0) +#define SYS_CORE_STATUS_W0_CFG_CORE0_EVENT_CLR BIT(16) +#define SYS_CORE_STATUS_W0_CFG_CORE0_EVENT_RAW BIT(18) +#define SYS_CORE_STATUS_W0_CFG_CORE1_EVENT_RAW BIT(19) + +#define SYS_CORE_STATUS_W0_CORE_STANDBY_WFI_L2_MASK 0x00000080 +#define SYS_CORE_STATUS_W0_JTAG_NSW_LOG_MASK 0x00000100 +#define SYS_CORE_STATUS_W0_CFG_CORE1_EVENT_CLR_MASK 0x00020000 +#define SYS_CORE_STATUS_W0_CORE_SMP_EN_MASK 0x00000030 +#define SYS_CORE_STATUS_W0_JTAG_TOP_LOG_MASK 0x00000200 +#define SYS_CORE_STATUS_W0_CORE_STANDBY_WFE_MASK 0x0000000c +#define SYS_CORE_STATUS_W0_CORE_L2_FLUSH_DONE_MASK 0x00000040 +#define SYS_CORE_STATUS_W0_CORE_STANDBY_WFI_MASK 0x00000003 +#define SYS_CORE_STATUS_W0_CFG_CORE0_EVENT_CLR_MASK 0x00010000 +#define SYS_CORE_STATUS_W0_CFG_CORE0_EVENT_RAW_MASK 0x00040000 +#define SYS_CORE_STATUS_W0_CFG_CORE1_EVENT_RAW_MASK 0x00080000 + +/* ############################################################################ + * # SysCorePmuEvent0 Definition + */ +#define SYS_CORE_PMU_EVENT0_W0_CORE0_PMU_EVENT BIT(0) + +#define SYS_CORE_PMU_EVENT0_W0_CORE0_PMU_EVENT_MASK 0x3fffffff + +/* ############################################################################ + * # SysCorePmuEvent1 Definition + */ +#define SYS_CORE_PMU_EVENT1_W0_CORE1_PMU_EVENT BIT(0) + +#define SYS_CORE_PMU_EVENT1_W0_CORE1_PMU_EVENT_MASK 0x3fffffff + +/* ############################################################################ + * # SysRstVecBar0 Definition + */ +#define SYS_RST_VEC_BAR0_W0_CFG_RV_BAR_ADDR0_31_0 BIT(0) +#define SYS_RST_VEC_BAR0_W1_CFG_RV_BAR_ADDR0_39_32 BIT(0) + +#define SYS_RST_VEC_BAR0_W0_CFG_RV_BAR_ADDR0_31_0_MASK 0x00000001 +#define SYS_RST_VEC_BAR0_W1_CFG_RV_BAR_ADDR0_39_32_MASK 0x00000001 + +/* ############################################################################ + * # SysRstVecBar1 Definition + */ +#define SYS_RST_VEC_BAR1_W0_CFG_RV_BAR_ADDR1_31_0 BIT(0) +#define SYS_RST_VEC_BAR1_W1_CFG_RV_BAR_ADDR1_39_32 BIT(0) + +#define SYS_RST_VEC_BAR1_W0_CFG_RV_BAR_ADDR1_31_0_MASK 0x00000001 +#define SYS_RST_VEC_BAR1_W1_CFG_RV_BAR_ADDR1_39_32_MASK 0x00000001 + +/* ############################################################################ + * # SysGicCfg Definition + */ +#define SYS_GIC_CFG_W0_CFG_GIC_LEGACY_IRQ_BAR BIT(4) +#define SYS_GIC_CFG_W0_CFG_GIC_WA_USER BIT(9) +#define SYS_GIC_CFG_W0_CFG_GIC_LEGACY_FIQ_BAR BIT(0) +#define SYS_GIC_CFG_W0_CFG_GIC_RA_USER BIT(8) + +#define SYS_GIC_CFG_W0_CFG_GIC_LEGACY_IRQ_BAR_MASK 0x00000030 +#define SYS_GIC_CFG_W0_CFG_GIC_WA_USER_MASK 0x00000200 +#define SYS_GIC_CFG_W0_CFG_GIC_LEGACY_FIQ_BAR_MASK 0x00000003 +#define SYS_GIC_CFG_W0_CFG_GIC_RA_USER_MASK 0x00000100 + +/* ############################################################################ + * # SysGicStatus Definition + */ +#define SYS_GIC_STATUS_W0_GIC_FIQ_OUT_LOG BIT(0) +#define SYS_GIC_STATUS_W0_GIC_IRQ_OUT_LOG BIT(2) + +#define SYS_GIC_STATUS_W0_GIC_FIQ_OUT_LOG_MASK 0x00000003 +#define SYS_GIC_STATUS_W0_GIC_IRQ_OUT_LOG_MASK 0x0000000c + +/* ############################################################################ + * # SysMemCtl Definition + */ +#define SYS_MEM_CTL_W0_CFG_RAM_MUX_EN BIT(0) +#define SYS_MEM_CTL_W0_CFG_SYS_REMAP_EN BIT(2) +#define SYS_MEM_CTL_W0_CFG_SYS_DBG_EN BIT(4) +#define SYS_MEM_CTL_W0_CFG_RAM_REMAP BIT(1) + +#define SYS_MEM_CTL_W0_CFG_RAM_MUX_EN_MASK 0x00000001 +#define SYS_MEM_CTL_W0_CFG_SYS_REMAP_EN_MASK 0x00000004 +#define SYS_MEM_CTL_W0_CFG_SYS_DBG_EN_MASK 0x00000010 +#define SYS_MEM_CTL_W0_CFG_RAM_REMAP_MASK 0x00000002 + +/* ############################################################################ + * # SysDmaMapCfg Definition + */ +#define SYS_DMA_MAP_CFG_W0_CFG_CPU_DMA_WR_MAP_LOW BIT(0) +#define SYS_DMA_MAP_CFG_W0_CFG_CPU_DMA_WR_MAP_HIGH BIT(16) +#define SYS_DMA_MAP_CFG_W0_CFG_CPU_DMA_RD_MAP_HIGH BIT(24) +#define SYS_DMA_MAP_CFG_W0_CFG_CPU_DMA_RD_MAP_LOW BIT(8) + +#define SYS_DMA_MAP_CFG_W0_CFG_CPU_DMA_WR_MAP_LOW_MASK 0x0000000f +#define SYS_DMA_MAP_CFG_W0_CFG_CPU_DMA_WR_MAP_HIGH_MASK 0x000f0000 +#define SYS_DMA_MAP_CFG_W0_CFG_CPU_DMA_RD_MAP_HIGH_MASK 0x0f000000 +#define SYS_DMA_MAP_CFG_W0_CFG_CPU_DMA_RD_MAP_LOW_MASK 0x00000f00 + +/* ############################################################################ + * # SysDmaAbortCfg Definition + */ +#define SYS_DMA_ABORT_CFG_W0_DMA_ABORT_LEVEL_EN BIT(4) +#define SYS_DMA_ABORT_CFG_W0_DMA_ABORT_STATUS BIT(0) + +#define SYS_DMA_ABORT_CFG_W0_DMA_ABORT_LEVEL_EN_MASK 0x00000010 +#define SYS_DMA_ABORT_CFG_W0_DMA_ABORT_STATUS_MASK 0x00000001 + +/* ############################################################################ + * # SysCstCfg Definition + */ +#define SYS_CST_CFG_W0_CFG_CST_PIU_TP_CTL BIT(4) +#define SYS_CST_CFG_W0_CFG_CST_PIU_TP_MAX_DATA_SIZE BIT(8) +#define SYS_CST_CFG_W0_CFG_CST_INSTANCE_ID BIT(0) +#define SYS_CST_CFG_W0_CFG_CST_DEVICE_EN BIT(5) + +#define SYS_CST_CFG_W0_CFG_CST_PIU_TP_CTL_MASK 0x00000010 +#define SYS_CST_CFG_W0_CFG_CST_PIU_TP_MAX_DATA_SIZE_MASK 0x00001f00 +#define SYS_CST_CFG_W0_CFG_CST_INSTANCE_ID_MASK 0x0000000f +#define SYS_CST_CFG_W0_CFG_CST_DEVICE_EN_MASK 0x00000020 + +/* ############################################################################ + * # SysCstTargetIdCfg Definition + */ +#define SYS_CST_TARGET_ID_CFG_W0_CFG_CST_TARGET_ID BIT(0) + +#define SYS_CST_TARGET_ID_CFG_W0_CFG_CST_TARGET_ID_MASK 0xffffffff + +/* ############################################################################ + * # SysCstMemMapIdCfg Definition + */ +#define SYS_CST_MEM_MAP_ID_CFG_W0_CFG_CST_MEM_MAP_TARGET_ID BIT(0) + +#define SYS_CST_MEM_MAP_ID_CFG_W0_CFG_CST_MEM_MAP_TARGET_ID_MASK 0xffffffff + +/* ############################################################################ + * # SysQspiBootCfg0 Definition + */ +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_EN_CPHA BIT(4) +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_HOLD BIT(6) +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_WP BIT(7) +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_CHIP_SEL BIT(8) +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_RX_CODE BIT(12) +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_EN BIT(0) +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_XIP_EN BIT(1) +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_EN_CPOL BIT(5) +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_CLK_DIV BIT(16) + +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_EN_CPHA_MASK 0x00000010 +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_HOLD_MASK 0x00000040 +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_WP_MASK 0x00000080 +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_CHIP_SEL_MASK 0x00000700 +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_RX_CODE_MASK 0x00007000 +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_EN_MASK 0x00000001 +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_XIP_EN_MASK 0x00000002 +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_EN_CPOL_MASK 0x00000020 +#define SYS_QSPI_BOOT_CFG0_W0_QSPI_BOOT_CLK_DIV_MASK 0x00ff0000 + +/* ############################################################################ + * # SysQspiBootCfg1 Definition + */ +#define SYS_QSPI_BOOT_CFG1_W0_QSPI_BOOT_CMD_CODE BIT(24) +#define SYS_QSPI_BOOT_CFG1_W0_QSPI_BOOT_CMD_MODE BIT(12) +#define SYS_QSPI_BOOT_CFG1_W0_QSPI_BOOT_CMD_CYCLE BIT(16) +#define SYS_QSPI_BOOT_CFG1_W0_QSPI_BOOT_ADDR_MODE BIT(8) +#define SYS_QSPI_BOOT_CFG1_W0_QSPI_BOOT_ADDR_CYCLE BIT(0) + +#define SYS_QSPI_BOOT_CFG1_W0_QSPI_BOOT_CMD_CODE_MASK 0xff000000 +#define SYS_QSPI_BOOT_CFG1_W0_QSPI_BOOT_CMD_MODE_MASK 0x00007000 +#define SYS_QSPI_BOOT_CFG1_W0_QSPI_BOOT_CMD_CYCLE_MASK 0x001f0000 +#define SYS_QSPI_BOOT_CFG1_W0_QSPI_BOOT_ADDR_MODE_MASK 0x00000700 +#define SYS_QSPI_BOOT_CFG1_W0_QSPI_BOOT_ADDR_CYCLE_MASK 0x0000003f + +/* ############################################################################ + * # SysQspiBootCfg2 Definition + */ +#define SYS_QSPI_BOOT_CFG2_W0_QSPI_BOOT_DUMMY_MODE BIT(8) +#define SYS_QSPI_BOOT_CFG2_W0_QSPI_BOOT_DUMMY_CYCLE BIT(0) + +#define SYS_QSPI_BOOT_CFG2_W0_QSPI_BOOT_DUMMY_MODE_MASK 0x00000700 +#define SYS_QSPI_BOOT_CFG2_W0_QSPI_BOOT_DUMMY_CYCLE_MASK 0x0000003f + +/* ############################################################################ + * # SysQspiBootCfg3 Definition + */ +#define SYS_QSPI_BOOT_CFG3_W0_QSPI_BOOT_DUMMY_CODE BIT(0) + +#define SYS_QSPI_BOOT_CFG3_W0_QSPI_BOOT_DUMMY_CODE_MASK 0xffffffff + +/* ############################################################################ + * # SysDdrCfg Definition + */ +#define SYS_DDR_CFG_W0_DDR_RESET_CK_E_LATCH_BAR BIT(0) +#define SYS_DDR_CFG_W0_DDR_FORCE_STA_CK_STP1 BIT(3) +#define SYS_DDR_CFG_W0_DDR_PHY_IDDQ BIT(4) +#define SYS_DDR_CFG_W0_DDR_VDD_ON BIT(2) +#define SYS_DDR_CFG_W0_DDR_PWR_OFF_PHY BIT(1) + +#define SYS_DDR_CFG_W0_DDR_RESET_CK_E_LATCH_BAR_MASK 0x00000001 +#define SYS_DDR_CFG_W0_DDR_FORCE_STA_CK_STP1_MASK 0x00000008 +#define SYS_DDR_CFG_W0_DDR_PHY_IDDQ_MASK 0x00000010 +#define SYS_DDR_CFG_W0_DDR_VDD_ON_MASK 0x00000004 +#define SYS_DDR_CFG_W0_DDR_PWR_OFF_PHY_MASK 0x00000002 + +/* ############################################################################ + * # SysSpiSelCfg Definition + */ +#define SYS_SPI_SEL_CFG_W0_SSP_SLAVE_SEL BIT(0) +#define SYS_SPI_SEL_CFG_W0_SSP_CS_CFG_CTL BIT(4) + +#define SYS_SPI_SEL_CFG_W0_SSP_SLAVE_SEL_MASK 0x00000003 +#define SYS_SPI_SEL_CFG_W0_SSP_CS_CFG_CTL_MASK 0x000000f0 + +/* ############################################################################ + * # SysMdioSocCfg Definition + */ +#define SYS_MDIO_SOC_CFG_W0_CFG_EN_CLK_MDIO_SOC BIT(4) +#define SYS_MDIO_SOC_CFG_W0_CFG_INV_MDIO_SOC BIT(0) +#define SYS_MDIO_SOC_CFG_W0_CFG_EN_CLK_MDIO_SOC_REG BIT(5) + +#define SYS_MDIO_SOC_CFG_W0_CFG_EN_CLK_MDIO_SOC_MASK 0x00000010 +#define SYS_MDIO_SOC_CFG_W0_CFG_INV_MDIO_SOC_MASK 0x00000001 +#define SYS_MDIO_SOC_CFG_W0_CFG_EN_CLK_MDIO_SOC_REG_MASK 0x00000020 + +/* ############################################################################ + * # SysWdt0Cnt Definition + */ +#define SYS_WDT0_CNT_W0_CFG_WDT0_DIV_CNT BIT(0) + +#define SYS_WDT0_CNT_W0_CFG_WDT0_DIV_CNT_MASK 0xffffffff + +/* ############################################################################ + * # SysWdt0Rev Definition + */ +#define SYS_WDT0_REV_W0_CFG_WDT0_ECO_REV BIT(0) + +#define SYS_WDT0_REV_W0_CFG_WDT0_ECO_REV_MASK 0x0000000f + +/* ############################################################################ + * # SysWdt1Cnt Definition + */ +#define SYS_WDT1_CNT_W0_CFG_WDT1_DIV_CNT BIT(0) + +#define SYS_WDT1_CNT_W0_CFG_WDT1_DIV_CNT_MASK 0xffffffff + +/* ############################################################################ + * # SysWdt1Rev Definition + */ +#define SYS_WDT1_REV_W0_CFG_WDT1_ECO_REV BIT(0) + +#define SYS_WDT1_REV_W0_CFG_WDT1_ECO_REV_MASK 0x0000000f + +/* ############################################################################ + * # SysMshCfg Definition + */ +#define SYS_MSH_CFG_W0_CFG_MSH_CARD_DETECT_IN_EN BIT(4) +#define SYS_MSH_CFG_W0_CFG_MSH_CARD_DETECT BIT(5) +#define SYS_MSH_CFG_W0_MSH_INTF_C_CLK_TX_DELAY BIT(16) +#define SYS_MSH_CFG_W0_MSH_INTF_C_CLK_TX_PHASE_SEL BIT(24) +#define SYS_MSH_CFG_W0_CFG_MSH_CARD_WRITE_PROT BIT(7) +#define SYS_MSH_CFG_W0_CFG_RESET_BAR_MSH_SEL BIT(12) +#define SYS_MSH_CFG_W0_MSH_INTF_TX_DLL_MASTER_BYPASS BIT(2) +#define SYS_MSH_CFG_W0_MSH_INTF_RX_DLL_MASTER_BYPASS BIT(1) +#define SYS_MSH_CFG_W0_MSH_INTF_C_CLK_TX_SEL BIT(25) +#define SYS_MSH_CFG_W0_MSH_INTF_AT_DLL_MASTER_BYPASS BIT(0) +#define SYS_MSH_CFG_W0_CFG_MSH_CARD_WRITE_PROT_IN_EN BIT(6) + +#define SYS_MSH_CFG_W0_CFG_MSH_CARD_DETECT_IN_EN_MASK 0x00000010 +#define SYS_MSH_CFG_W0_CFG_MSH_CARD_DETECT_MASK 0x00000020 +#define SYS_MSH_CFG_W0_MSH_INTF_C_CLK_TX_DELAY_MASK 0x00ff0000 +#define SYS_MSH_CFG_W0_MSH_INTF_C_CLK_TX_PHASE_SEL_MASK 0x01000000 +#define SYS_MSH_CFG_W0_CFG_MSH_CARD_WRITE_PROT_MASK 0x00000080 +#define SYS_MSH_CFG_W0_CFG_RESET_BAR_MSH_SEL_MASK 0x00001000 +#define SYS_MSH_CFG_W0_MSH_INTF_TX_DLL_MASTER_BYPASS_MASK 0x00000004 +#define SYS_MSH_CFG_W0_MSH_INTF_RX_DLL_MASTER_BYPASS_MASK 0x00000002 +#define SYS_MSH_CFG_W0_MSH_INTF_C_CLK_TX_SEL_MASK 0x02000000 +#define SYS_MSH_CFG_W0_MSH_INTF_AT_DLL_MASTER_BYPASS_MASK 0x00000001 +#define SYS_MSH_CFG_W0_CFG_MSH_CARD_WRITE_PROT_IN_EN_MASK 0x00000040 + +/* ############################################################################ + * # SysMshStatus Definition + */ +#define SYS_MSH_STATUS_W0_MON_MSH_C_RESET_DONE BIT(2) +#define SYS_MSH_STATUS_W0_MON_MSH_SD_CLK_LOCK BIT(6) +#define SYS_MSH_STATUS_W0_MON_MSH_SD_DATXFER_WIDTH BIT(0) +#define SYS_MSH_STATUS_W0_MON_MSH_AT_DLL_LOCK BIT(4) +#define SYS_MSH_STATUS_W0_MON_MSH_RX_DLL_LOCK BIT(5) + +#define SYS_MSH_STATUS_W0_MON_MSH_C_RESET_DONE_MASK 0x00000004 +#define SYS_MSH_STATUS_W0_MON_MSH_SD_CLK_LOCK_MASK 0x00000040 +#define SYS_MSH_STATUS_W0_MON_MSH_SD_DATXFER_WIDTH_MASK 0x00000003 +#define SYS_MSH_STATUS_W0_MON_MSH_AT_DLL_LOCK_MASK 0x00000010 +#define SYS_MSH_STATUS_W0_MON_MSH_RX_DLL_LOCK_MASK 0x00000020 + +/* ############################################################################ + * # SysUsbCfg0 Definition + */ +#define SYS_USB_CFG0_W0_USB_PHY_TX_PRE_EMP_AMP_TUNE BIT(2) +#define SYS_USB_CFG0_W0_USB_PHY_FSEL BIT(8) +#define SYS_USB_CFG0_W0_USB_PHY_COMMON_ONN BIT(0) +#define SYS_USB_CFG0_W0_USB_PHY_PLL_B_TUNE BIT(1) +#define SYS_USB_CFG0_W0_USB_PHY_COMP_DIS_TUNE BIT(4) +#define SYS_USB_CFG0_W0_USB_PHY_TX_RISE_TUNE BIT(20) +#define SYS_USB_CFG0_W0_USB_PHY_TX_HSXV_TUNE BIT(28) +#define SYS_USB_CFG0_W0_USB_PHY_VA_TEST_EN_B BIT(22) +#define SYS_USB_CFG0_W0_USB_PHY_TX_VREF_TUNE BIT(24) +#define SYS_USB_CFG0_W0_USB_PHY_TX_RES_TUNE BIT(30) +#define SYS_USB_CFG0_W0_USB_PHY_TX_FS_LS_TUNE BIT(16) +#define SYS_USB_CFG0_W0_USB_PHY_VREG_BYPASS BIT(11) +#define SYS_USB_CFG0_W0_USB_PHY_TX_PRE_EMP_PULSE_TUNE BIT(7) +#define SYS_USB_CFG0_W0_USB_PHY_SQ_RX_TUNE BIT(12) + +#define SYS_USB_CFG0_W0_USB_PHY_TX_PRE_EMP_AMP_TUNE_MASK 0x0000000c +#define SYS_USB_CFG0_W0_USB_PHY_FSEL_MASK 0x00000700 +#define SYS_USB_CFG0_W0_USB_PHY_COMMON_ONN_MASK 0x00000001 +#define SYS_USB_CFG0_W0_USB_PHY_PLL_B_TUNE_MASK 0x00000002 +#define SYS_USB_CFG0_W0_USB_PHY_COMP_DIS_TUNE_MASK 0x00000070 +#define SYS_USB_CFG0_W0_USB_PHY_TX_RISE_TUNE_MASK 0x00300000 +#define SYS_USB_CFG0_W0_USB_PHY_TX_HSXV_TUNE_MASK 0x30000000 +#define SYS_USB_CFG0_W0_USB_PHY_VA_TEST_EN_B_MASK 0x00c00000 +#define SYS_USB_CFG0_W0_USB_PHY_TX_VREF_TUNE_MASK 0x0f000000 +#define SYS_USB_CFG0_W0_USB_PHY_TX_RES_TUNE_MASK 0xc0000000 +#define SYS_USB_CFG0_W0_USB_PHY_TX_FS_LS_TUNE_MASK 0x000f0000 +#define SYS_USB_CFG0_W0_USB_PHY_VREG_BYPASS_MASK 0x00000800 +#define SYS_USB_CFG0_W0_USB_PHY_TX_PRE_EMP_PULSE_TUNE_MASK 0x00000080 +#define SYS_USB_CFG0_W0_USB_PHY_SQ_RX_TUNE_MASK 0x00007000 + +/* ############################################################################ + * # SysUsbCfg1 Definition + */ +#define SYS_USB_CFG1_W0_USB_INTF_AUTOPPD_ON_OVERCUR_EN BIT(1) +#define SYS_USB_CFG1_W0_USB_INTF_FL_ADJ_VAL_HOST BIT(4) +#define SYS_USB_CFG1_W0_USB_INTF_WORD_IF BIT(16) +#define SYS_USB_CFG1_W0_USB_INTF_OHCI_CNT_SEL BIT(13) +#define SYS_USB_CFG1_W0_USB_INTF_OHCI_SUSP_LGCY BIT(14) +#define SYS_USB_CFG1_W0_USB_INTF_OHCI_CLKCKTRST_BAR BIT(12) +#define SYS_USB_CFG1_W0_USB_INTF_APP_START_CLK BIT(0) +#define SYS_USB_CFG1_W0_USB_PHY_LOOPBACK_EN BIT(17) +#define SYS_USB_CFG1_W0_USB_INTF_SIM_MODE BIT(15) +#define SYS_USB_CFG1_W0_USB_INTF_HUBSETUP_MIN BIT(2) + +#define SYS_USB_CFG1_W0_USB_INTF_AUTOPPD_ON_OVERCUR_EN_MASK 0x00000002 +#define SYS_USB_CFG1_W0_USB_INTF_FL_ADJ_VAL_HOST_MASK 0x000003f0 +#define SYS_USB_CFG1_W0_USB_INTF_WORD_IF_MASK 0x00010000 +#define SYS_USB_CFG1_W0_USB_INTF_OHCI_CNT_SEL_MASK 0x00002000 +#define SYS_USB_CFG1_W0_USB_INTF_OHCI_SUSP_LGCY_MASK 0x00004000 +#define SYS_USB_CFG1_W0_USB_INTF_OHCI_CLKCKTRST_BAR_MASK 0x00001000 +#define SYS_USB_CFG1_W0_USB_INTF_APP_START_CLK_MASK 0x00000001 +#define SYS_USB_CFG1_W0_USB_PHY_LOOPBACK_EN_MASK 0x00020000 +#define SYS_USB_CFG1_W0_USB_INTF_SIM_MODE_MASK 0x00008000 +#define SYS_USB_CFG1_W0_USB_INTF_HUBSETUP_MIN_MASK 0x00000004 + +/* ############################################################################ + * # SysUsbCfg2 Definition + */ +#define SYS_USB_CFG2_W0_USB_PHY_PLL_P_TUNE BIT(8) +#define SYS_USB_CFG2_W0_USB_PHY_PLL_I_TUNE BIT(4) +#define SYS_USB_CFG2_W0_USB_PHY_TX_BIT_STUFF_EN0 BIT(16) +#define SYS_USB_CFG2_W0_USB_PHY_TX_BIT_STUFF_EN_H0 BIT(17) +#define SYS_USB_CFG2_W0_USB_PHY_OTG_TUNE BIT(0) +#define SYS_USB_CFG2_W0_USB_PHY_VDAT_REF_TUNE BIT(12) + +#define SYS_USB_CFG2_W0_USB_PHY_PLL_P_TUNE_MASK 0x00000f00 +#define SYS_USB_CFG2_W0_USB_PHY_PLL_I_TUNE_MASK 0x00000030 +#define SYS_USB_CFG2_W0_USB_PHY_TX_BIT_STUFF_EN0_MASK 0x00010000 +#define SYS_USB_CFG2_W0_USB_PHY_TX_BIT_STUFF_EN_H0_MASK 0x00020000 +#define SYS_USB_CFG2_W0_USB_PHY_OTG_TUNE_MASK 0x00000007 +#define SYS_USB_CFG2_W0_USB_PHY_VDAT_REF_TUNE_MASK 0x00003000 + +/* ############################################################################ + * # SysUsbStatus Definition + */ +#define SYS_USB_STATUS_W0_USB_INTF_EHCI_LPSMC_STATE BIT(0) +#define SYS_USB_STATUS_W0_USB_INTF_EHCI_XFER_CNT BIT(4) +#define SYS_USB_STATUS_W0_USB_INTF_OHCI_ISOC_OUT_MEM_READ BIT(18) +#define SYS_USB_STATUS_W0_USB_INTF_OHCI_CCS BIT(16) +#define SYS_USB_STATUS_W0_USB_INTF_EHCI_XFER_PRDC BIT(15) +#define SYS_USB_STATUS_W0_USB_INTF_OHCI_GLOBALSUSPEND BIT(17) +#define SYS_USB_STATUS_W0_USB_INTF_OHCI_RMTWKP BIT(19) + +#define SYS_USB_STATUS_W0_USB_INTF_EHCI_LPSMC_STATE_MASK 0x0000000f +#define SYS_USB_STATUS_W0_USB_INTF_EHCI_XFER_CNT_MASK 0x00007ff0 +#define SYS_USB_STATUS_W0_USB_INTF_OHCI_ISOC_OUT_MEM_READ_MASK 0x00040000 +#define SYS_USB_STATUS_W0_USB_INTF_OHCI_CCS_MASK 0x00010000 +#define SYS_USB_STATUS_W0_USB_INTF_EHCI_XFER_PRDC_MASK 0x00008000 +#define SYS_USB_STATUS_W0_USB_INTF_OHCI_GLOBALSUSPEND_MASK 0x00020000 +#define SYS_USB_STATUS_W0_USB_INTF_OHCI_RMTWKP_MASK 0x00080000 + +/* ############################################################################ + * # SysPcieBaseCfg Definition + */ +#define SYS_PCIE_BASE_CFG_W0_PCIE_BASE_CFG BIT(0) + +#define SYS_PCIE_BASE_CFG_W0_PCIE_BASE_CFG_MASK 0x000fffff + +/* ############################################################################ + * # SysRegCfg Definition + */ +#define SYS_REG_CFG_W0_EN_CLK_GLOBAL_SYS BIT(0) +#define SYS_REG_CFG_W0_CFG_SOC_ACC_DIR_EN BIT(1) + +#define SYS_REG_CFG_W0_EN_CLK_GLOBAL_SYS_MASK 0x00000001 +#define SYS_REG_CFG_W0_CFG_SOC_ACC_DIR_EN_MASK 0x00000002 + +/* ############################################################################ + * # SysInitCtl Definition + */ +#define SYS_INIT_CTL_W0_CPU_MEM_INIT_DONE BIT(1) +#define SYS_INIT_CTL_W0_CFG_INIT_EN BIT(0) +#define SYS_INIT_CTL_W1_CFG_INIT_START_PTR BIT(0) +#define SYS_INIT_CTL_W1_CFG_INIT_END_PTR BIT(16) + +#define SYS_INIT_CTL_W0_CPU_MEM_INIT_DONE_MASK 0x00000002 +#define SYS_INIT_CTL_W0_CFG_INIT_EN_MASK 0x00000001 +#define SYS_INIT_CTL_W1_CFG_INIT_START_PTR_MASK 0x00007fff +#define SYS_INIT_CTL_W1_CFG_INIT_END_PTR_MASK 0x7fff0000 + +/* ############################################################################ + * # SysPllSupCfg0 Definition + */ +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_PLL_PWD BIT(3) +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_MULT_INT BIT(20) +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_RESET BIT(0) +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_INT_FBK BIT(2) +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_PRE_DIV BIT(4) +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_DCO_BYPASS BIT(1) +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_POST_DIV BIT(12) + +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_PLL_PWD_MASK 0x00000008 +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_MULT_INT_MASK 0x0ff00000 +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_RESET_MASK 0x00000001 +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_INT_FBK_MASK 0x00000004 +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_PRE_DIV_MASK 0x000001f0 +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_DCO_BYPASS_MASK 0x00000002 +#define SYS_PLL_SUP_CFG0_W0_PLL_SUP_POST_DIV_MASK 0x0003f000 + +/* ############################################################################ + * # SysPllSupCfg1 Definition + */ +#define SYS_PLL_SUP_CFG1_W0_MON_PLL_SUP_LOCK BIT(28) +#define SYS_PLL_SUP_CFG1_W0_PLL_SUP_SGAIN BIT(20) +#define SYS_PLL_SUP_CFG1_W0_PLL_SUP_SIP BIT(0) +#define SYS_PLL_SUP_CFG1_W0_PLL_SUP_SIC BIT(8) +#define SYS_PLL_SUP_CFG1_W0_PLL_SUP_SLOCK BIT(16) +#define SYS_PLL_SUP_CFG1_W0_PLL_SUP_BYPASS BIT(24) + +#define SYS_PLL_SUP_CFG1_W0_MON_PLL_SUP_LOCK_MASK 0x10000000 +#define SYS_PLL_SUP_CFG1_W0_PLL_SUP_SGAIN_MASK 0x00700000 +#define SYS_PLL_SUP_CFG1_W0_PLL_SUP_SIP_MASK 0x0000001f +#define SYS_PLL_SUP_CFG1_W0_PLL_SUP_SIC_MASK 0x00001f00 +#define SYS_PLL_SUP_CFG1_W0_PLL_SUP_SLOCK_MASK 0x00010000 +#define SYS_PLL_SUP_CFG1_W0_PLL_SUP_BYPASS_MASK 0x01000000 + +/* ############################################################################ + * # SysApbProcTimer Definition + */ +#define SYS_APB_PROC_TIMER_W0_CFG_APB_PROC_TIMER BIT(0) + +#define SYS_APB_PROC_TIMER_W0_CFG_APB_PROC_TIMER_MASK 0x0000ffff + +/* ############################################################################ + * # SysUsbTest Definition + */ +#define SYS_USB_TEST_W0_USB_PHY_TEST_DATA_IN BIT(8) +#define SYS_USB_TEST_W0_USB_PHY_TEST_DATA_OUT_SEL BIT(16) +#define SYS_USB_TEST_W0_USB_PHY_TEST_ADDR BIT(0) +#define SYS_USB_TEST_W1_USB_PHY_TEST_CLK BIT(16) +#define SYS_USB_TEST_W1_USB_PHY_TEST_DATA_OUT BIT(0) + +#define SYS_USB_TEST_W0_USB_PHY_TEST_DATA_IN_MASK 0x0000ff00 +#define SYS_USB_TEST_W0_USB_PHY_TEST_DATA_OUT_SEL_MASK 0x00010000 +#define SYS_USB_TEST_W0_USB_PHY_TEST_ADDR_MASK 0x0000000f +#define SYS_USB_TEST_W1_USB_PHY_TEST_CLK_MASK 0x00010000 +#define SYS_USB_TEST_W1_USB_PHY_TEST_DATA_OUT_MASK 0x0000000f + +/* ############################################################################ + * # SysGpioMultiCtl Definition + */ +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO14_SEL BIT(28) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO5_SEL BIT(10) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO15_SEL BIT(30) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO7_SEL BIT(14) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO9_SEL BIT(18) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO13_SEL BIT(26) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO0_SEL BIT(0) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO1_SEL BIT(2) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO6_SEL BIT(12) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO11_SEL BIT(22) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO3_SEL BIT(6) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO10_SEL BIT(20) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO2_SEL BIT(4) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO8_SEL BIT(16) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO12_SEL BIT(24) +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO4_SEL BIT(8) + +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO14_SEL_MASK 0x30000000 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO5_SEL_MASK 0x00000c00 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO15_SEL_MASK 0xc0000000 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO7_SEL_MASK 0x0000c000 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO9_SEL_MASK 0x000c0000 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO13_SEL_MASK 0x0c000000 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO0_SEL_MASK 0x00000003 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO1_SEL_MASK 0x0000000c +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO6_SEL_MASK 0x00003000 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO11_SEL_MASK 0x00c00000 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO3_SEL_MASK 0x000000c0 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO10_SEL_MASK 0x00300000 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO2_SEL_MASK 0x00000030 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO8_SEL_MASK 0x00030000 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO12_SEL_MASK 0x03000000 +#define SYS_GPIO_MULTI_CTL_W0_CFG_GPIO4_SEL_MASK 0x00000300 + +/* ############################################################################ + * # SysGpioHsMultiCtl Definition + */ +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS13_SEL BIT(26) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS7_SEL BIT(14) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS9_SEL BIT(18) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS14_SEL BIT(28) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS11_SEL BIT(22) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS15_SEL BIT(30) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS5_SEL BIT(10) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS4_SEL BIT(8) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS10_SEL BIT(20) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS8_SEL BIT(16) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS12_SEL BIT(24) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS6_SEL BIT(12) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS3_SEL BIT(6) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS2_SEL BIT(4) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS0_SEL BIT(0) +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS1_SEL BIT(2) +#define SYS_GPIO_HS_MULTI_CTL_W1_CFG_GPIO_HS17_SEL BIT(2) +#define SYS_GPIO_HS_MULTI_CTL_W1_CFG_GPIO_HS16_SEL BIT(0) + +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS13_SEL_MASK 0x0c000000 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS7_SEL_MASK 0x0000c000 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS9_SEL_MASK 0x000c0000 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS14_SEL_MASK 0x30000000 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS11_SEL_MASK 0x00c00000 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS15_SEL_MASK 0xc0000000 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS5_SEL_MASK 0x00000c00 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS4_SEL_MASK 0x00000300 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS10_SEL_MASK 0x00300000 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS8_SEL_MASK 0x00030000 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS12_SEL_MASK 0x03000000 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS6_SEL_MASK 0x00003000 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS3_SEL_MASK 0x000000c0 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS2_SEL_MASK 0x00000030 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS0_SEL_MASK 0x00000003 +#define SYS_GPIO_HS_MULTI_CTL_W0_CFG_GPIO_HS1_SEL_MASK 0x0000000c +#define SYS_GPIO_HS_MULTI_CTL_W1_CFG_GPIO_HS17_SEL_MASK 0x0000000c +#define SYS_GPIO_HS_MULTI_CTL_W1_CFG_GPIO_HS16_SEL_MASK 0x00000003 + +/* ############################################################################ + * # SysPcieStatus Definition + */ +#define SYS_PCIE_STATUS_W0_PCIE_LTSSM_LOG_31_0 BIT(0) +#define SYS_PCIE_STATUS_W1_PCIE_LTSSM_LOG_63_32 BIT(0) + +#define SYS_PCIE_STATUS_W0_PCIE_LTSSM_LOG_31_0_MASK 0x00000001 +#define SYS_PCIE_STATUS_W1_PCIE_LTSSM_LOG_63_32_MASK 0x00000001 + +/* ############################################################################ + * # SysMsixStatus Definition + */ +#define SYS_MSIX_STATUS_W0_MSIX_STATUS0 BIT(0) +#define SYS_MSIX_STATUS_W1_MSIX_STATUS1 BIT(0) +#define SYS_MSIX_STATUS_W2_MSIX_STATUS2 BIT(0) +#define SYS_MSIX_STATUS_W3_MSIX_STATUS3 BIT(0) +#define SYS_MSIX_STATUS_W4_MSIX_STATUS4 BIT(0) +#define SYS_MSIX_STATUS_W5_MSIX_STATUS5 BIT(0) +#define SYS_MSIX_STATUS_W6_MSIX_STATUS6 BIT(0) +#define SYS_MSIX_STATUS_W7_MSIX_STATUS7 BIT(0) + +#define SYS_MSIX_STATUS_W0_MSIX_STATUS0_MASK 0xffffffff +#define SYS_MSIX_STATUS_W1_MSIX_STATUS1_MASK 0xffffffff +#define SYS_MSIX_STATUS_W2_MSIX_STATUS2_MASK 0xffffffff +#define SYS_MSIX_STATUS_W3_MSIX_STATUS3_MASK 0xffffffff +#define SYS_MSIX_STATUS_W4_MSIX_STATUS4_MASK 0xffffffff +#define SYS_MSIX_STATUS_W5_MSIX_STATUS5_MASK 0xffffffff +#define SYS_MSIX_STATUS_W6_MSIX_STATUS6_MASK 0xffffffff +#define SYS_MSIX_STATUS_W7_MSIX_STATUS7_MASK 0xffffffff + +/* ############################################################################ + * # SysMsixMask Definition + */ +#define SYS_MSIX_MASK_W0_MSIX_MASK0 BIT(0) +#define SYS_MSIX_MASK_W1_MSIX_MASK1 BIT(0) +#define SYS_MSIX_MASK_W2_MSIX_MASK2 BIT(0) +#define SYS_MSIX_MASK_W3_MSIX_MASK3 BIT(0) +#define SYS_MSIX_MASK_W4_MSIX_MASK4 BIT(0) +#define SYS_MSIX_MASK_W5_MSIX_MASK5 BIT(0) +#define SYS_MSIX_MASK_W6_MSIX_MASK6 BIT(0) +#define SYS_MSIX_MASK_W7_MSIX_MASK7 BIT(0) + +#define SYS_MSIX_MASK_W0_MSIX_MASK0_MASK 0xffffffff +#define SYS_MSIX_MASK_W1_MSIX_MASK1_MASK 0xffffffff +#define SYS_MSIX_MASK_W2_MSIX_MASK2_MASK 0xffffffff +#define SYS_MSIX_MASK_W3_MSIX_MASK3_MASK 0xffffffff +#define SYS_MSIX_MASK_W4_MSIX_MASK4_MASK 0xffffffff +#define SYS_MSIX_MASK_W5_MSIX_MASK5_MASK 0xffffffff +#define SYS_MSIX_MASK_W6_MSIX_MASK6_MASK 0xffffffff +#define SYS_MSIX_MASK_W7_MSIX_MASK7_MASK 0xffffffff + +/* ############################################################################ + * # SysMsixAddr Definition + */ +#define SYS_MSIX_ADDR_W0_MSIX_ADDR BIT(0) + +#define SYS_MSIX_ADDR_W0_MSIX_ADDR_MASK 0xffffffff + +/* ############################################################################ + * # SysMsixVecCtl Definition + */ +#define SYS_MSIX_VEC_CTL_W0_MSIX_VEC_EN BIT(0) + +#define SYS_MSIX_VEC_CTL_W0_MSIX_VEC_EN_MASK 0x000000ff + +/* ############################################################################ + * # SysMsixAddrEn Definition + */ +#define SYS_MSIX_ADDR_EN_W0_MSIX_ADDR_EN BIT(0) + +#define SYS_MSIX_ADDR_EN_W0_MSIX_ADDR_EN_MASK 0x00000001 + +/* ############################################################################ + * # SysMsixIntrLog Definition + */ +#define SYS_MSIX_INTR_LOG_W0_MSIX_INTR_LOG BIT(0) + +#define SYS_MSIX_INTR_LOG_W0_MSIX_INTR_LOG_MASK 0x000000ff + +/* ############################################################################ + * # SysDebugCtl Definition + */ +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_PCIE BIT(4) +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_SYS_APB BIT(8) +#define SYS_DEBUG_CTL_W0_DEBUG_EN_SYS_APB BIT(9) +#define SYS_DEBUG_CTL_W0_DEBUG_EN_SEC_APB BIT(13) +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_MSH BIT(7) +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_DDR1 BIT(3) +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_CPU BIT(0) +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_DDR0 BIT(2) +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_SEC_APB BIT(12) +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_MEM BIT(1) +#define SYS_DEBUG_CTL_W0_DEBUG_ONCE_SEC_APB BIT(14) +#define SYS_DEBUG_CTL_W0_DEBUG_ONCE_SYS_APB BIT(10) +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_SUP BIT(6) +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_QSPI BIT(5) + +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_PCIE_MASK 0x00000010 +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_SYS_APB_MASK 0x00000100 +#define SYS_DEBUG_CTL_W0_DEBUG_EN_SYS_APB_MASK 0x00000200 +#define SYS_DEBUG_CTL_W0_DEBUG_EN_SEC_APB_MASK 0x00002000 +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_MSH_MASK 0x00000080 +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_DDR1_MASK 0x00000008 +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_CPU_MASK 0x00000001 +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_DDR0_MASK 0x00000004 +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_SEC_APB_MASK 0x00001000 +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_MEM_MASK 0x00000002 +#define SYS_DEBUG_CTL_W0_DEBUG_ONCE_SEC_APB_MASK 0x00004000 +#define SYS_DEBUG_CTL_W0_DEBUG_ONCE_SYS_APB_MASK 0x00000400 +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_SUP_MASK 0x00000040 +#define SYS_DEBUG_CTL_W0_DEBUG_INIT_QSPI_MASK 0x00000020 + +/* ############################################################################ + * # SysMsixPending Definition + */ +#define SYS_MSIX_PENDING_W0_MSIX_PENDING0 BIT(0) +#define SYS_MSIX_PENDING_W1_MSIX_PENDING1 BIT(0) +#define SYS_MSIX_PENDING_W2_MSIX_PENDING2 BIT(0) +#define SYS_MSIX_PENDING_W3_MSIX_PENDING3 BIT(0) +#define SYS_MSIX_PENDING_W4_MSIX_PENDING4 BIT(0) +#define SYS_MSIX_PENDING_W5_MSIX_PENDING5 BIT(0) +#define SYS_MSIX_PENDING_W6_MSIX_PENDING6 BIT(0) +#define SYS_MSIX_PENDING_W7_MSIX_PENDING7 BIT(0) + +#define SYS_MSIX_PENDING_W0_MSIX_PENDING0_MASK 0xffffffff +#define SYS_MSIX_PENDING_W1_MSIX_PENDING1_MASK 0xffffffff +#define SYS_MSIX_PENDING_W2_MSIX_PENDING2_MASK 0xffffffff +#define SYS_MSIX_PENDING_W3_MSIX_PENDING3_MASK 0xffffffff +#define SYS_MSIX_PENDING_W4_MSIX_PENDING4_MASK 0xffffffff +#define SYS_MSIX_PENDING_W5_MSIX_PENDING5_MASK 0xffffffff +#define SYS_MSIX_PENDING_W6_MSIX_PENDING6_MASK 0xffffffff +#define SYS_MSIX_PENDING_W7_MSIX_PENDING7_MASK 0xffffffff + +/* ############################################################################ + * # SysPwmCtl Definition + */ +#define SYS_PWM_CTL_W0_CFG_PWM0_EN BIT(31) +#define SYS_PWM_CTL_W0_CFG_PWM0_PERIOD_CYCLE BIT(0) +#define SYS_PWM_CTL_W1_CFG_PWM0_DUTY_CYCLE BIT(0) +#define SYS_PWM_CTL_W2_CFG_PWM1_EN BIT(31) +#define SYS_PWM_CTL_W2_CFG_PWM1_PERIOD_CYCLE BIT(0) +#define SYS_PWM_CTL_W3_CFG_PWM1_DUTY_CYCLE BIT(0) +#define SYS_PWM_CTL_W4_CFG_PWM2_EN BIT(31) +#define SYS_PWM_CTL_W4_CFG_PWM2_PERIOD_CYCLE BIT(0) +#define SYS_PWM_CTL_W5_CFG_PWM2_DUTY_CYCLE BIT(0) +#define SYS_PWM_CTL_W6_CFG_PWM3_EN BIT(31) +#define SYS_PWM_CTL_W6_CFG_PWM3_PERIOD_CYCLE BIT(0) +#define SYS_PWM_CTL_W7_CFG_PWM3_DUTY_CYCLE BIT(0) + +#define SYS_PWM_CTL_W0_CFG_PWM0_EN_MASK 0x80000000 +#define SYS_PWM_CTL_W0_CFG_PWM0_PERIOD_CYCLE_MASK 0x00ffffff +#define SYS_PWM_CTL_W1_CFG_PWM0_DUTY_CYCLE_MASK 0x00ffffff +#define SYS_PWM_CTL_W2_CFG_PWM1_EN_MASK 0x80000000 +#define SYS_PWM_CTL_W2_CFG_PWM1_PERIOD_CYCLE_MASK 0x00ffffff +#define SYS_PWM_CTL_W3_CFG_PWM1_DUTY_CYCLE_MASK 0x00ffffff +#define SYS_PWM_CTL_W4_CFG_PWM2_EN_MASK 0x80000000 +#define SYS_PWM_CTL_W4_CFG_PWM2_PERIOD_CYCLE_MASK 0x00ffffff +#define SYS_PWM_CTL_W5_CFG_PWM2_DUTY_CYCLE_MASK 0x00ffffff +#define SYS_PWM_CTL_W6_CFG_PWM3_EN_MASK 0x80000000 +#define SYS_PWM_CTL_W6_CFG_PWM3_PERIOD_CYCLE_MASK 0x00ffffff +#define SYS_PWM_CTL_W7_CFG_PWM3_DUTY_CYCLE_MASK 0x00ffffff + +/* ############################################################################ + * # SysTachLog Definition + */ +#define SYS_TACH_LOG_W0_TACH0_PERIOD_CYCLE BIT(0) +#define SYS_TACH_LOG_W1_TACH0_DUTY_CYCLE BIT(0) +#define SYS_TACH_LOG_W2_TACH1_PERIOD_CYCLE BIT(0) +#define SYS_TACH_LOG_W3_TACH1_DUTY_CYCLE BIT(0) +#define SYS_TACH_LOG_W4_TACH2_PERIOD_CYCLE BIT(0) +#define SYS_TACH_LOG_W5_TACH2_DUTY_CYCLE BIT(0) +#define SYS_TACH_LOG_W6_TACH3_PERIOD_CYCLE BIT(0) +#define SYS_TACH_LOG_W7_TACH3_DUTY_CYCLE BIT(0) + +#define SYS_TACH_LOG_W0_TACH0_PERIOD_CYCLE_MASK 0x00ffffff +#define SYS_TACH_LOG_W1_TACH0_DUTY_CYCLE_MASK 0x00ffffff +#define SYS_TACH_LOG_W2_TACH1_PERIOD_CYCLE_MASK 0x00ffffff +#define SYS_TACH_LOG_W3_TACH1_DUTY_CYCLE_MASK 0x00ffffff +#define SYS_TACH_LOG_W4_TACH2_PERIOD_CYCLE_MASK 0x00ffffff +#define SYS_TACH_LOG_W5_TACH2_DUTY_CYCLE_MASK 0x00ffffff +#define SYS_TACH_LOG_W6_TACH3_PERIOD_CYCLE_MASK 0x00ffffff +#define SYS_TACH_LOG_W7_TACH3_DUTY_CYCLE_MASK 0x00ffffff + +/* ############################################################################ + * # MonAxiCpuCurInfo Definition + */ +#define MON_AXI_CPU_CUR_INFO_W0_MON_AXI_CPU_CUR_INFO_31_0 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W1_MON_AXI_CPU_CUR_INFO_63_32 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W2_MON_AXI_CPU_CUR_INFO_95_64 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W3_MON_AXI_CPU_CUR_INFO_127_96 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W4_MON_AXI_CPU_CUR_INFO_159_128 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W5_MON_AXI_CPU_CUR_INFO_191_160 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W6_MON_AXI_CPU_CUR_INFO_223_192 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W7_MON_AXI_CPU_CUR_INFO_255_224 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W8_MON_AXI_CPU_CUR_INFO_287_256 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W9_MON_AXI_CPU_CUR_INFO_319_288 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W10_MON_AXI_CPU_CUR_INFO_351_320 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W11_MON_AXI_CPU_CUR_INFO_383_352 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W12_MON_AXI_CPU_CUR_INFO_415_384 BIT(0) +#define MON_AXI_CPU_CUR_INFO_W13_MON_AXI_CPU_CUR_INFO_427_416 BIT(0) + +#define MON_AXI_CPU_CUR_INFO_W0_MON_AXI_CPU_CUR_INFO_31_0_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W1_MON_AXI_CPU_CUR_INFO_63_32_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W2_MON_AXI_CPU_CUR_INFO_95_64_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W3_MON_AXI_CPU_CUR_INFO_127_96_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W4_MON_AXI_CPU_CUR_INFO_159_128_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W5_MON_AXI_CPU_CUR_INFO_191_160_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W6_MON_AXI_CPU_CUR_INFO_223_192_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W7_MON_AXI_CPU_CUR_INFO_255_224_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W8_MON_AXI_CPU_CUR_INFO_287_256_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W9_MON_AXI_CPU_CUR_INFO_319_288_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W10_MON_AXI_CPU_CUR_INFO_351_320_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W11_MON_AXI_CPU_CUR_INFO_383_352_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W12_MON_AXI_CPU_CUR_INFO_415_384_MASK 0x00000001 +#define MON_AXI_CPU_CUR_INFO_W13_MON_AXI_CPU_CUR_INFO_427_416_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiCpuLogInfo Definition + */ +#define MON_AXI_CPU_LOG_INFO_W0_MON_AXI_CPU_LOG_INFO_31_0 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W1_MON_AXI_CPU_LOG_INFO_63_32 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W2_MON_AXI_CPU_LOG_INFO_95_64 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W3_MON_AXI_CPU_LOG_INFO_127_96 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W4_MON_AXI_CPU_LOG_INFO_159_128 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W5_MON_AXI_CPU_LOG_INFO_191_160 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W6_MON_AXI_CPU_LOG_INFO_223_192 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W7_MON_AXI_CPU_LOG_INFO_255_224 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W8_MON_AXI_CPU_LOG_INFO_287_256 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W9_MON_AXI_CPU_LOG_INFO_319_288 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W10_MON_AXI_CPU_LOG_INFO_351_320 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W11_MON_AXI_CPU_LOG_INFO_383_352 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W12_MON_AXI_CPU_LOG_INFO_415_384 BIT(0) +#define MON_AXI_CPU_LOG_INFO_W13_MON_AXI_CPU_LOG_INFO_427_416 BIT(0) + +#define MON_AXI_CPU_LOG_INFO_W0_MON_AXI_CPU_LOG_INFO_31_0_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W1_MON_AXI_CPU_LOG_INFO_63_32_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W2_MON_AXI_CPU_LOG_INFO_95_64_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W3_MON_AXI_CPU_LOG_INFO_127_96_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W4_MON_AXI_CPU_LOG_INFO_159_128_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W5_MON_AXI_CPU_LOG_INFO_191_160_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W6_MON_AXI_CPU_LOG_INFO_223_192_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W7_MON_AXI_CPU_LOG_INFO_255_224_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W8_MON_AXI_CPU_LOG_INFO_287_256_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W9_MON_AXI_CPU_LOG_INFO_319_288_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W10_MON_AXI_CPU_LOG_INFO_351_320_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W11_MON_AXI_CPU_LOG_INFO_383_352_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W12_MON_AXI_CPU_LOG_INFO_415_384_MASK 0x00000001 +#define MON_AXI_CPU_LOG_INFO_W13_MON_AXI_CPU_LOG_INFO_427_416_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiDdr0CurInfo Definition + */ +#define MON_AXI_DDR0_CUR_INFO_W0_MON_AXI_DDR0_CUR_INFO_31_0 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W1_MON_AXI_DDR0_CUR_INFO_63_32 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W2_MON_AXI_DDR0_CUR_INFO_95_64 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W3_MON_AXI_DDR0_CUR_INFO_127_96 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W4_MON_AXI_DDR0_CUR_INFO_159_128 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W5_MON_AXI_DDR0_CUR_INFO_191_160 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W6_MON_AXI_DDR0_CUR_INFO_223_192 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W7_MON_AXI_DDR0_CUR_INFO_255_224 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W8_MON_AXI_DDR0_CUR_INFO_287_256 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W9_MON_AXI_DDR0_CUR_INFO_319_288 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W10_MON_AXI_DDR0_CUR_INFO_351_320 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W11_MON_AXI_DDR0_CUR_INFO_383_352 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W12_MON_AXI_DDR0_CUR_INFO_415_384 BIT(0) +#define MON_AXI_DDR0_CUR_INFO_W13_MON_AXI_DDR0_CUR_INFO_427_416 BIT(0) + +#define MON_AXI_DDR0_CUR_INFO_W0_MON_AXI_DDR0_CUR_INFO_31_0_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W1_MON_AXI_DDR0_CUR_INFO_63_32_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W2_MON_AXI_DDR0_CUR_INFO_95_64_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W3_MON_AXI_DDR0_CUR_INFO_127_96_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W4_MON_AXI_DDR0_CUR_INFO_159_128_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W5_MON_AXI_DDR0_CUR_INFO_191_160_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W6_MON_AXI_DDR0_CUR_INFO_223_192_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W7_MON_AXI_DDR0_CUR_INFO_255_224_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W8_MON_AXI_DDR0_CUR_INFO_287_256_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W9_MON_AXI_DDR0_CUR_INFO_319_288_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W10_MON_AXI_DDR0_CUR_INFO_351_320_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W11_MON_AXI_DDR0_CUR_INFO_383_352_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W12_MON_AXI_DDR0_CUR_INFO_415_384_MASK 0x00000001 +#define MON_AXI_DDR0_CUR_INFO_W13_MON_AXI_DDR0_CUR_INFO_427_416_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiDdr0LogInfo Definition + */ +#define MON_AXI_DDR0_LOG_INFO_W0_MON_AXI_DDR0_LOG_INFO_31_0 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W1_MON_AXI_DDR0_LOG_INFO_63_32 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W2_MON_AXI_DDR0_LOG_INFO_95_64 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W3_MON_AXI_DDR0_LOG_INFO_127_96 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W4_MON_AXI_DDR0_LOG_INFO_159_128 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W5_MON_AXI_DDR0_LOG_INFO_191_160 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W6_MON_AXI_DDR0_LOG_INFO_223_192 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W7_MON_AXI_DDR0_LOG_INFO_255_224 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W8_MON_AXI_DDR0_LOG_INFO_287_256 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W9_MON_AXI_DDR0_LOG_INFO_319_288 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W10_MON_AXI_DDR0_LOG_INFO_351_320 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W11_MON_AXI_DDR0_LOG_INFO_383_352 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W12_MON_AXI_DDR0_LOG_INFO_415_384 BIT(0) +#define MON_AXI_DDR0_LOG_INFO_W13_MON_AXI_DDR0_LOG_INFO_427_416 BIT(0) + +#define MON_AXI_DDR0_LOG_INFO_W0_MON_AXI_DDR0_LOG_INFO_31_0_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W1_MON_AXI_DDR0_LOG_INFO_63_32_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W2_MON_AXI_DDR0_LOG_INFO_95_64_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W3_MON_AXI_DDR0_LOG_INFO_127_96_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W4_MON_AXI_DDR0_LOG_INFO_159_128_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W5_MON_AXI_DDR0_LOG_INFO_191_160_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W6_MON_AXI_DDR0_LOG_INFO_223_192_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W7_MON_AXI_DDR0_LOG_INFO_255_224_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W8_MON_AXI_DDR0_LOG_INFO_287_256_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W9_MON_AXI_DDR0_LOG_INFO_319_288_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W10_MON_AXI_DDR0_LOG_INFO_351_320_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W11_MON_AXI_DDR0_LOG_INFO_383_352_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W12_MON_AXI_DDR0_LOG_INFO_415_384_MASK 0x00000001 +#define MON_AXI_DDR0_LOG_INFO_W13_MON_AXI_DDR0_LOG_INFO_427_416_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiDdr1CurInfo Definition + */ +#define MON_AXI_DDR1_CUR_INFO_W0_MON_AXI_DDR1_CUR_INFO_31_0 BIT(0) +#define MON_AXI_DDR1_CUR_INFO_W1_MON_AXI_DDR1_CUR_INFO_63_32 BIT(0) +#define MON_AXI_DDR1_CUR_INFO_W2_MON_AXI_DDR1_CUR_INFO_95_64 BIT(0) +#define MON_AXI_DDR1_CUR_INFO_W3_MON_AXI_DDR1_CUR_INFO_127_96 BIT(0) +#define MON_AXI_DDR1_CUR_INFO_W4_MON_AXI_DDR1_CUR_INFO_159_128 BIT(0) +#define MON_AXI_DDR1_CUR_INFO_W5_MON_AXI_DDR1_CUR_INFO_191_160 BIT(0) +#define MON_AXI_DDR1_CUR_INFO_W6_MON_AXI_DDR1_CUR_INFO_223_192 BIT(0) +#define MON_AXI_DDR1_CUR_INFO_W7_MON_AXI_DDR1_CUR_INFO_255_224 BIT(0) +#define MON_AXI_DDR1_CUR_INFO_W8_MON_AXI_DDR1_CUR_INFO_287_256 BIT(0) +#define MON_AXI_DDR1_CUR_INFO_W9_MON_AXI_DDR1_CUR_INFO_299_288 BIT(0) + +#define MON_AXI_DDR1_CUR_INFO_W0_MON_AXI_DDR1_CUR_INFO_31_0_MASK 0x00000001 +#define MON_AXI_DDR1_CUR_INFO_W1_MON_AXI_DDR1_CUR_INFO_63_32_MASK 0x00000001 +#define MON_AXI_DDR1_CUR_INFO_W2_MON_AXI_DDR1_CUR_INFO_95_64_MASK 0x00000001 +#define MON_AXI_DDR1_CUR_INFO_W3_MON_AXI_DDR1_CUR_INFO_127_96_MASK 0x00000001 +#define MON_AXI_DDR1_CUR_INFO_W4_MON_AXI_DDR1_CUR_INFO_159_128_MASK 0x00000001 +#define MON_AXI_DDR1_CUR_INFO_W5_MON_AXI_DDR1_CUR_INFO_191_160_MASK 0x00000001 +#define MON_AXI_DDR1_CUR_INFO_W6_MON_AXI_DDR1_CUR_INFO_223_192_MASK 0x00000001 +#define MON_AXI_DDR1_CUR_INFO_W7_MON_AXI_DDR1_CUR_INFO_255_224_MASK 0x00000001 +#define MON_AXI_DDR1_CUR_INFO_W8_MON_AXI_DDR1_CUR_INFO_287_256_MASK 0x00000001 +#define MON_AXI_DDR1_CUR_INFO_W9_MON_AXI_DDR1_CUR_INFO_299_288_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiDdr1LogInfo Definition + */ +#define MON_AXI_DDR1_LOG_INFO_W0_MON_AXI_DDR1_LOG_INFO_31_0 BIT(0) +#define MON_AXI_DDR1_LOG_INFO_W1_MON_AXI_DDR1_LOG_INFO_63_32 BIT(0) +#define MON_AXI_DDR1_LOG_INFO_W2_MON_AXI_DDR1_LOG_INFO_95_64 BIT(0) +#define MON_AXI_DDR1_LOG_INFO_W3_MON_AXI_DDR1_LOG_INFO_127_96 BIT(0) +#define MON_AXI_DDR1_LOG_INFO_W4_MON_AXI_DDR1_LOG_INFO_159_128 BIT(0) +#define MON_AXI_DDR1_LOG_INFO_W5_MON_AXI_DDR1_LOG_INFO_191_160 BIT(0) +#define MON_AXI_DDR1_LOG_INFO_W6_MON_AXI_DDR1_LOG_INFO_223_192 BIT(0) +#define MON_AXI_DDR1_LOG_INFO_W7_MON_AXI_DDR1_LOG_INFO_255_224 BIT(0) +#define MON_AXI_DDR1_LOG_INFO_W8_MON_AXI_DDR1_LOG_INFO_287_256 BIT(0) +#define MON_AXI_DDR1_LOG_INFO_W9_MON_AXI_DDR1_LOG_INFO_299_288 BIT(0) + +#define MON_AXI_DDR1_LOG_INFO_W0_MON_AXI_DDR1_LOG_INFO_31_0_MASK 0x00000001 +#define MON_AXI_DDR1_LOG_INFO_W1_MON_AXI_DDR1_LOG_INFO_63_32_MASK 0x00000001 +#define MON_AXI_DDR1_LOG_INFO_W2_MON_AXI_DDR1_LOG_INFO_95_64_MASK 0x00000001 +#define MON_AXI_DDR1_LOG_INFO_W3_MON_AXI_DDR1_LOG_INFO_127_96_MASK 0x00000001 +#define MON_AXI_DDR1_LOG_INFO_W4_MON_AXI_DDR1_LOG_INFO_159_128_MASK 0x00000001 +#define MON_AXI_DDR1_LOG_INFO_W5_MON_AXI_DDR1_LOG_INFO_191_160_MASK 0x00000001 +#define MON_AXI_DDR1_LOG_INFO_W6_MON_AXI_DDR1_LOG_INFO_223_192_MASK 0x00000001 +#define MON_AXI_DDR1_LOG_INFO_W7_MON_AXI_DDR1_LOG_INFO_255_224_MASK 0x00000001 +#define MON_AXI_DDR1_LOG_INFO_W8_MON_AXI_DDR1_LOG_INFO_287_256_MASK 0x00000001 +#define MON_AXI_DDR1_LOG_INFO_W9_MON_AXI_DDR1_LOG_INFO_299_288_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiMemCurInfo Definition + */ +#define MON_AXI_MEM_CUR_INFO_W0_MON_AXI_MEM_CUR_INFO_31_0 BIT(0) +#define MON_AXI_MEM_CUR_INFO_W1_MON_AXI_MEM_CUR_INFO_63_32 BIT(0) +#define MON_AXI_MEM_CUR_INFO_W2_MON_AXI_MEM_CUR_INFO_95_64 BIT(0) +#define MON_AXI_MEM_CUR_INFO_W3_MON_AXI_MEM_CUR_INFO_127_96 BIT(0) +#define MON_AXI_MEM_CUR_INFO_W4_MON_AXI_MEM_CUR_INFO_159_128 BIT(0) +#define MON_AXI_MEM_CUR_INFO_W5_MON_AXI_MEM_CUR_INFO_191_160 BIT(0) +#define MON_AXI_MEM_CUR_INFO_W6_MON_AXI_MEM_CUR_INFO_223_192 BIT(0) +#define MON_AXI_MEM_CUR_INFO_W7_MON_AXI_MEM_CUR_INFO_255_224 BIT(0) +#define MON_AXI_MEM_CUR_INFO_W8_MON_AXI_MEM_CUR_INFO_287_256 BIT(0) +#define MON_AXI_MEM_CUR_INFO_W9_MON_AXI_MEM_CUR_INFO_303_288 BIT(0) + +#define MON_AXI_MEM_CUR_INFO_W0_MON_AXI_MEM_CUR_INFO_31_0_MASK 0x00000001 +#define MON_AXI_MEM_CUR_INFO_W1_MON_AXI_MEM_CUR_INFO_63_32_MASK 0x00000001 +#define MON_AXI_MEM_CUR_INFO_W2_MON_AXI_MEM_CUR_INFO_95_64_MASK 0x00000001 +#define MON_AXI_MEM_CUR_INFO_W3_MON_AXI_MEM_CUR_INFO_127_96_MASK 0x00000001 +#define MON_AXI_MEM_CUR_INFO_W4_MON_AXI_MEM_CUR_INFO_159_128_MASK 0x00000001 +#define MON_AXI_MEM_CUR_INFO_W5_MON_AXI_MEM_CUR_INFO_191_160_MASK 0x00000001 +#define MON_AXI_MEM_CUR_INFO_W6_MON_AXI_MEM_CUR_INFO_223_192_MASK 0x00000001 +#define MON_AXI_MEM_CUR_INFO_W7_MON_AXI_MEM_CUR_INFO_255_224_MASK 0x00000001 +#define MON_AXI_MEM_CUR_INFO_W8_MON_AXI_MEM_CUR_INFO_287_256_MASK 0x00000001 +#define MON_AXI_MEM_CUR_INFO_W9_MON_AXI_MEM_CUR_INFO_303_288_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiMemLogInfo Definition + */ +#define MON_AXI_MEM_LOG_INFO_W0_MON_AXI_MEM_LOG_INFO_31_0 BIT(0) +#define MON_AXI_MEM_LOG_INFO_W1_MON_AXI_MEM_LOG_INFO_63_32 BIT(0) +#define MON_AXI_MEM_LOG_INFO_W2_MON_AXI_MEM_LOG_INFO_95_64 BIT(0) +#define MON_AXI_MEM_LOG_INFO_W3_MON_AXI_MEM_LOG_INFO_127_96 BIT(0) +#define MON_AXI_MEM_LOG_INFO_W4_MON_AXI_MEM_LOG_INFO_159_128 BIT(0) +#define MON_AXI_MEM_LOG_INFO_W5_MON_AXI_MEM_LOG_INFO_191_160 BIT(0) +#define MON_AXI_MEM_LOG_INFO_W6_MON_AXI_MEM_LOG_INFO_223_192 BIT(0) +#define MON_AXI_MEM_LOG_INFO_W7_MON_AXI_MEM_LOG_INFO_255_224 BIT(0) +#define MON_AXI_MEM_LOG_INFO_W8_MON_AXI_MEM_LOG_INFO_287_256 BIT(0) +#define MON_AXI_MEM_LOG_INFO_W9_MON_AXI_MEM_LOG_INFO_303_288 BIT(0) + +#define MON_AXI_MEM_LOG_INFO_W0_MON_AXI_MEM_LOG_INFO_31_0_MASK 0x00000001 +#define MON_AXI_MEM_LOG_INFO_W1_MON_AXI_MEM_LOG_INFO_63_32_MASK 0x00000001 +#define MON_AXI_MEM_LOG_INFO_W2_MON_AXI_MEM_LOG_INFO_95_64_MASK 0x00000001 +#define MON_AXI_MEM_LOG_INFO_W3_MON_AXI_MEM_LOG_INFO_127_96_MASK 0x00000001 +#define MON_AXI_MEM_LOG_INFO_W4_MON_AXI_MEM_LOG_INFO_159_128_MASK 0x00000001 +#define MON_AXI_MEM_LOG_INFO_W5_MON_AXI_MEM_LOG_INFO_191_160_MASK 0x00000001 +#define MON_AXI_MEM_LOG_INFO_W6_MON_AXI_MEM_LOG_INFO_223_192_MASK 0x00000001 +#define MON_AXI_MEM_LOG_INFO_W7_MON_AXI_MEM_LOG_INFO_255_224_MASK 0x00000001 +#define MON_AXI_MEM_LOG_INFO_W8_MON_AXI_MEM_LOG_INFO_287_256_MASK 0x00000001 +#define MON_AXI_MEM_LOG_INFO_W9_MON_AXI_MEM_LOG_INFO_303_288_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiMshCurInfo Definition + */ +#define MON_AXI_MSH_CUR_INFO_W0_MON_AXI_MSH_CUR_INFO_31_0 BIT(0) +#define MON_AXI_MSH_CUR_INFO_W1_MON_AXI_MSH_CUR_INFO_63_32 BIT(0) +#define MON_AXI_MSH_CUR_INFO_W2_MON_AXI_MSH_CUR_INFO_95_64 BIT(0) +#define MON_AXI_MSH_CUR_INFO_W3_MON_AXI_MSH_CUR_INFO_127_96 BIT(0) +#define MON_AXI_MSH_CUR_INFO_W4_MON_AXI_MSH_CUR_INFO_159_128 BIT(0) +#define MON_AXI_MSH_CUR_INFO_W5_MON_AXI_MSH_CUR_INFO_191_160 BIT(0) +#define MON_AXI_MSH_CUR_INFO_W6_MON_AXI_MSH_CUR_INFO_223_192 BIT(0) +#define MON_AXI_MSH_CUR_INFO_W7_MON_AXI_MSH_CUR_INFO_255_224 BIT(0) +#define MON_AXI_MSH_CUR_INFO_W8_MON_AXI_MSH_CUR_INFO_275_256 BIT(0) + +#define MON_AXI_MSH_CUR_INFO_W0_MON_AXI_MSH_CUR_INFO_31_0_MASK 0x00000001 +#define MON_AXI_MSH_CUR_INFO_W1_MON_AXI_MSH_CUR_INFO_63_32_MASK 0x00000001 +#define MON_AXI_MSH_CUR_INFO_W2_MON_AXI_MSH_CUR_INFO_95_64_MASK 0x00000001 +#define MON_AXI_MSH_CUR_INFO_W3_MON_AXI_MSH_CUR_INFO_127_96_MASK 0x00000001 +#define MON_AXI_MSH_CUR_INFO_W4_MON_AXI_MSH_CUR_INFO_159_128_MASK 0x00000001 +#define MON_AXI_MSH_CUR_INFO_W5_MON_AXI_MSH_CUR_INFO_191_160_MASK 0x00000001 +#define MON_AXI_MSH_CUR_INFO_W6_MON_AXI_MSH_CUR_INFO_223_192_MASK 0x00000001 +#define MON_AXI_MSH_CUR_INFO_W7_MON_AXI_MSH_CUR_INFO_255_224_MASK 0x00000001 +#define MON_AXI_MSH_CUR_INFO_W8_MON_AXI_MSH_CUR_INFO_275_256_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiMshLogInfo Definition + */ +#define MON_AXI_MSH_LOG_INFO_W0_MON_AXI_MSH_LOG_INFO_31_0 BIT(0) +#define MON_AXI_MSH_LOG_INFO_W1_MON_AXI_MSH_LOG_INFO_63_32 BIT(0) +#define MON_AXI_MSH_LOG_INFO_W2_MON_AXI_MSH_LOG_INFO_95_64 BIT(0) +#define MON_AXI_MSH_LOG_INFO_W3_MON_AXI_MSH_LOG_INFO_127_96 BIT(0) +#define MON_AXI_MSH_LOG_INFO_W4_MON_AXI_MSH_LOG_INFO_159_128 BIT(0) +#define MON_AXI_MSH_LOG_INFO_W5_MON_AXI_MSH_LOG_INFO_191_160 BIT(0) +#define MON_AXI_MSH_LOG_INFO_W6_MON_AXI_MSH_LOG_INFO_223_192 BIT(0) +#define MON_AXI_MSH_LOG_INFO_W7_MON_AXI_MSH_LOG_INFO_255_224 BIT(0) +#define MON_AXI_MSH_LOG_INFO_W8_MON_AXI_MSH_LOG_INFO_275_256 BIT(0) +#define MON_AXI_MSH_LOG_INFO_W8_MON_AXI_MSH_LOG_WD_ID BIT(24) + +#define MON_AXI_MSH_LOG_INFO_W0_MON_AXI_MSH_LOG_INFO_31_0_MASK 0x00000001 +#define MON_AXI_MSH_LOG_INFO_W1_MON_AXI_MSH_LOG_INFO_63_32_MASK 0x00000001 +#define MON_AXI_MSH_LOG_INFO_W2_MON_AXI_MSH_LOG_INFO_95_64_MASK 0x00000001 +#define MON_AXI_MSH_LOG_INFO_W3_MON_AXI_MSH_LOG_INFO_127_96_MASK 0x00000001 +#define MON_AXI_MSH_LOG_INFO_W4_MON_AXI_MSH_LOG_INFO_159_128_MASK 0x00000001 +#define MON_AXI_MSH_LOG_INFO_W5_MON_AXI_MSH_LOG_INFO_191_160_MASK 0x00000001 +#define MON_AXI_MSH_LOG_INFO_W6_MON_AXI_MSH_LOG_INFO_223_192_MASK 0x00000001 +#define MON_AXI_MSH_LOG_INFO_W7_MON_AXI_MSH_LOG_INFO_255_224_MASK 0x00000001 +#define MON_AXI_MSH_LOG_INFO_W8_MON_AXI_MSH_LOG_INFO_275_256_MASK 0x00000001 +#define MON_AXI_MSH_LOG_INFO_W8_MON_AXI_MSH_LOG_WD_ID_MASK 0x0f000000 + +/* ############################################################################ + * # MonAxiPcieCurInfo Definition + */ +#define MON_AXI_PCIE_CUR_INFO_W0_MON_AXI_PCIE_CUR_INFO_31_0 BIT(0) +#define MON_AXI_PCIE_CUR_INFO_W1_MON_AXI_PCIE_CUR_INFO_63_32 BIT(0) +#define MON_AXI_PCIE_CUR_INFO_W2_MON_AXI_PCIE_CUR_INFO_95_64 BIT(0) +#define MON_AXI_PCIE_CUR_INFO_W3_MON_AXI_PCIE_CUR_INFO_127_96 BIT(0) +#define MON_AXI_PCIE_CUR_INFO_W4_MON_AXI_PCIE_CUR_INFO_159_128 BIT(0) +#define MON_AXI_PCIE_CUR_INFO_W5_MON_AXI_PCIE_CUR_INFO_191_160 BIT(0) +#define MON_AXI_PCIE_CUR_INFO_W6_MON_AXI_PCIE_CUR_INFO_223_192 BIT(0) +#define MON_AXI_PCIE_CUR_INFO_W7_MON_AXI_PCIE_CUR_INFO_255_224 BIT(0) +#define MON_AXI_PCIE_CUR_INFO_W8_MON_AXI_PCIE_CUR_INFO_287_256 BIT(0) +#define MON_AXI_PCIE_CUR_INFO_W9_MON_AXI_PCIE_CUR_INFO_291_288 BIT(0) + +#define MON_AXI_PCIE_CUR_INFO_W0_MON_AXI_PCIE_CUR_INFO_31_0_MASK 0x00000001 +#define MON_AXI_PCIE_CUR_INFO_W1_MON_AXI_PCIE_CUR_INFO_63_32_MASK 0x00000001 +#define MON_AXI_PCIE_CUR_INFO_W2_MON_AXI_PCIE_CUR_INFO_95_64_MASK 0x00000001 +#define MON_AXI_PCIE_CUR_INFO_W3_MON_AXI_PCIE_CUR_INFO_127_96_MASK 0x00000001 +#define MON_AXI_PCIE_CUR_INFO_W4_MON_AXI_PCIE_CUR_INFO_159_128_MASK 0x00000001 +#define MON_AXI_PCIE_CUR_INFO_W5_MON_AXI_PCIE_CUR_INFO_191_160_MASK 0x00000001 +#define MON_AXI_PCIE_CUR_INFO_W6_MON_AXI_PCIE_CUR_INFO_223_192_MASK 0x00000001 +#define MON_AXI_PCIE_CUR_INFO_W7_MON_AXI_PCIE_CUR_INFO_255_224_MASK 0x00000001 +#define MON_AXI_PCIE_CUR_INFO_W8_MON_AXI_PCIE_CUR_INFO_287_256_MASK 0x00000001 +#define MON_AXI_PCIE_CUR_INFO_W9_MON_AXI_PCIE_CUR_INFO_291_288_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiPcieLogInfo Definition + */ +#define MON_AXI_PCIE_LOG_INFO_W0_MON_AXI_PCIE_LOG_INFO_31_0 BIT(0) +#define MON_AXI_PCIE_LOG_INFO_W1_MON_AXI_PCIE_LOG_INFO_63_32 BIT(0) +#define MON_AXI_PCIE_LOG_INFO_W2_MON_AXI_PCIE_LOG_INFO_95_64 BIT(0) +#define MON_AXI_PCIE_LOG_INFO_W3_MON_AXI_PCIE_LOG_INFO_127_96 BIT(0) +#define MON_AXI_PCIE_LOG_INFO_W4_MON_AXI_PCIE_LOG_INFO_159_128 BIT(0) +#define MON_AXI_PCIE_LOG_INFO_W5_MON_AXI_PCIE_LOG_INFO_191_160 BIT(0) +#define MON_AXI_PCIE_LOG_INFO_W6_MON_AXI_PCIE_LOG_INFO_223_192 BIT(0) +#define MON_AXI_PCIE_LOG_INFO_W7_MON_AXI_PCIE_LOG_INFO_255_224 BIT(0) +#define MON_AXI_PCIE_LOG_INFO_W8_MON_AXI_PCIE_LOG_INFO_287_256 BIT(0) +#define MON_AXI_PCIE_LOG_INFO_W9_MON_AXI_PCIE_LOG_INFO_291_288 BIT(0) + +#define MON_AXI_PCIE_LOG_INFO_W0_MON_AXI_PCIE_LOG_INFO_31_0_MASK 0x00000001 +#define MON_AXI_PCIE_LOG_INFO_W1_MON_AXI_PCIE_LOG_INFO_63_32_MASK 0x00000001 +#define MON_AXI_PCIE_LOG_INFO_W2_MON_AXI_PCIE_LOG_INFO_95_64_MASK 0x00000001 +#define MON_AXI_PCIE_LOG_INFO_W3_MON_AXI_PCIE_LOG_INFO_127_96_MASK 0x00000001 +#define MON_AXI_PCIE_LOG_INFO_W4_MON_AXI_PCIE_LOG_INFO_159_128_MASK 0x00000001 +#define MON_AXI_PCIE_LOG_INFO_W5_MON_AXI_PCIE_LOG_INFO_191_160_MASK 0x00000001 +#define MON_AXI_PCIE_LOG_INFO_W6_MON_AXI_PCIE_LOG_INFO_223_192_MASK 0x00000001 +#define MON_AXI_PCIE_LOG_INFO_W7_MON_AXI_PCIE_LOG_INFO_255_224_MASK 0x00000001 +#define MON_AXI_PCIE_LOG_INFO_W8_MON_AXI_PCIE_LOG_INFO_287_256_MASK 0x00000001 +#define MON_AXI_PCIE_LOG_INFO_W9_MON_AXI_PCIE_LOG_INFO_291_288_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiQspiCurInfo Definition + */ +#define MON_AXI_QSPI_CUR_INFO_W0_MON_AXI_QSPI_CUR_INFO_31_0 BIT(0) +#define MON_AXI_QSPI_CUR_INFO_W1_MON_AXI_QSPI_CUR_INFO_63_32 BIT(0) +#define MON_AXI_QSPI_CUR_INFO_W2_MON_AXI_QSPI_CUR_INFO_95_64 BIT(0) +#define MON_AXI_QSPI_CUR_INFO_W3_MON_AXI_QSPI_CUR_INFO_127_96 BIT(0) +#define MON_AXI_QSPI_CUR_INFO_W4_MON_AXI_QSPI_CUR_INFO_159_128 BIT(0) +#define MON_AXI_QSPI_CUR_INFO_W5_MON_AXI_QSPI_CUR_INFO_191_160 BIT(0) +#define MON_AXI_QSPI_CUR_INFO_W6_MON_AXI_QSPI_CUR_INFO_223_192 BIT(0) + +#define MON_AXI_QSPI_CUR_INFO_W0_MON_AXI_QSPI_CUR_INFO_31_0_MASK 0x00000001 +#define MON_AXI_QSPI_CUR_INFO_W1_MON_AXI_QSPI_CUR_INFO_63_32_MASK 0x00000001 +#define MON_AXI_QSPI_CUR_INFO_W2_MON_AXI_QSPI_CUR_INFO_95_64_MASK 0x00000001 +#define MON_AXI_QSPI_CUR_INFO_W3_MON_AXI_QSPI_CUR_INFO_127_96_MASK 0x00000001 +#define MON_AXI_QSPI_CUR_INFO_W4_MON_AXI_QSPI_CUR_INFO_159_128_MASK 0x00000001 +#define MON_AXI_QSPI_CUR_INFO_W5_MON_AXI_QSPI_CUR_INFO_191_160_MASK 0x00000001 +#define MON_AXI_QSPI_CUR_INFO_W6_MON_AXI_QSPI_CUR_INFO_223_192_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiQspiLogInfo Definition + */ +#define MON_AXI_QSPI_LOG_INFO_W0_MON_AXI_QSPI_LOG_INFO_31_0 BIT(0) +#define MON_AXI_QSPI_LOG_INFO_W1_MON_AXI_QSPI_LOG_INFO_63_32 BIT(0) +#define MON_AXI_QSPI_LOG_INFO_W2_MON_AXI_QSPI_LOG_INFO_95_64 BIT(0) +#define MON_AXI_QSPI_LOG_INFO_W3_MON_AXI_QSPI_LOG_INFO_127_96 BIT(0) +#define MON_AXI_QSPI_LOG_INFO_W4_MON_AXI_QSPI_LOG_INFO_159_128 BIT(0) +#define MON_AXI_QSPI_LOG_INFO_W5_MON_AXI_QSPI_LOG_INFO_191_160 BIT(0) +#define MON_AXI_QSPI_LOG_INFO_W6_MON_AXI_QSPI_LOG_INFO_223_192 BIT(0) +#define MON_AXI_QSPI_LOG_INFO_W7_MON_AXI_QSPI_LOG_WD_ID BIT(0) + +#define MON_AXI_QSPI_LOG_INFO_W0_MON_AXI_QSPI_LOG_INFO_31_0_MASK 0x00000001 +#define MON_AXI_QSPI_LOG_INFO_W1_MON_AXI_QSPI_LOG_INFO_63_32_MASK 0x00000001 +#define MON_AXI_QSPI_LOG_INFO_W2_MON_AXI_QSPI_LOG_INFO_95_64_MASK 0x00000001 +#define MON_AXI_QSPI_LOG_INFO_W3_MON_AXI_QSPI_LOG_INFO_127_96_MASK 0x00000001 +#define MON_AXI_QSPI_LOG_INFO_W4_MON_AXI_QSPI_LOG_INFO_159_128_MASK 0x00000001 +#define MON_AXI_QSPI_LOG_INFO_W5_MON_AXI_QSPI_LOG_INFO_191_160_MASK 0x00000001 +#define MON_AXI_QSPI_LOG_INFO_W6_MON_AXI_QSPI_LOG_INFO_223_192_MASK 0x00000001 +#define MON_AXI_QSPI_LOG_INFO_W7_MON_AXI_QSPI_LOG_WD_ID_MASK 0x000003ff + +/* ############################################################################ + * # MonAxiSupCurInfo Definition + */ +#define MON_AXI_SUP_CUR_INFO_W0_MON_AXI_SUP_CUR_INFO_31_0 BIT(0) +#define MON_AXI_SUP_CUR_INFO_W1_MON_AXI_SUP_CUR_INFO_63_32 BIT(0) +#define MON_AXI_SUP_CUR_INFO_W2_MON_AXI_SUP_CUR_INFO_95_64 BIT(0) +#define MON_AXI_SUP_CUR_INFO_W3_MON_AXI_SUP_CUR_INFO_127_96 BIT(0) +#define MON_AXI_SUP_CUR_INFO_W4_MON_AXI_SUP_CUR_INFO_159_128 BIT(0) +#define MON_AXI_SUP_CUR_INFO_W5_MON_AXI_SUP_CUR_INFO_191_160 BIT(0) +#define MON_AXI_SUP_CUR_INFO_W6_MON_AXI_SUP_CUR_INFO_223_192 BIT(0) +#define MON_AXI_SUP_CUR_INFO_W7_MON_AXI_SUP_CUR_INFO_231_224 BIT(0) + +#define MON_AXI_SUP_CUR_INFO_W0_MON_AXI_SUP_CUR_INFO_31_0_MASK 0x00000001 +#define MON_AXI_SUP_CUR_INFO_W1_MON_AXI_SUP_CUR_INFO_63_32_MASK 0x00000001 +#define MON_AXI_SUP_CUR_INFO_W2_MON_AXI_SUP_CUR_INFO_95_64_MASK 0x00000001 +#define MON_AXI_SUP_CUR_INFO_W3_MON_AXI_SUP_CUR_INFO_127_96_MASK 0x00000001 +#define MON_AXI_SUP_CUR_INFO_W4_MON_AXI_SUP_CUR_INFO_159_128_MASK 0x00000001 +#define MON_AXI_SUP_CUR_INFO_W5_MON_AXI_SUP_CUR_INFO_191_160_MASK 0x00000001 +#define MON_AXI_SUP_CUR_INFO_W6_MON_AXI_SUP_CUR_INFO_223_192_MASK 0x00000001 +#define MON_AXI_SUP_CUR_INFO_W7_MON_AXI_SUP_CUR_INFO_231_224_MASK 0x00000001 + +/* ############################################################################ + * # MonAxiSupLogInfo Definition + */ +#define MON_AXI_SUP_LOG_INFO_W0_MON_AXI_SUP_LOG_INFO_31_0 BIT(0) +#define MON_AXI_SUP_LOG_INFO_W1_MON_AXI_SUP_LOG_INFO_63_32 BIT(0) +#define MON_AXI_SUP_LOG_INFO_W2_MON_AXI_SUP_LOG_INFO_95_64 BIT(0) +#define MON_AXI_SUP_LOG_INFO_W3_MON_AXI_SUP_LOG_INFO_127_96 BIT(0) +#define MON_AXI_SUP_LOG_INFO_W4_MON_AXI_SUP_LOG_INFO_159_128 BIT(0) +#define MON_AXI_SUP_LOG_INFO_W5_MON_AXI_SUP_LOG_INFO_191_160 BIT(0) +#define MON_AXI_SUP_LOG_INFO_W6_MON_AXI_SUP_LOG_INFO_223_192 BIT(0) +#define MON_AXI_SUP_LOG_INFO_W7_MON_AXI_SUP_LOG_INFO_231_224 BIT(0) + +#define MON_AXI_SUP_LOG_INFO_W0_MON_AXI_SUP_LOG_INFO_31_0_MASK 0x00000001 +#define MON_AXI_SUP_LOG_INFO_W1_MON_AXI_SUP_LOG_INFO_63_32_MASK 0x00000001 +#define MON_AXI_SUP_LOG_INFO_W2_MON_AXI_SUP_LOG_INFO_95_64_MASK 0x00000001 +#define MON_AXI_SUP_LOG_INFO_W3_MON_AXI_SUP_LOG_INFO_127_96_MASK 0x00000001 +#define MON_AXI_SUP_LOG_INFO_W4_MON_AXI_SUP_LOG_INFO_159_128_MASK 0x00000001 +#define MON_AXI_SUP_LOG_INFO_W5_MON_AXI_SUP_LOG_INFO_191_160_MASK 0x00000001 +#define MON_AXI_SUP_LOG_INFO_W6_MON_AXI_SUP_LOG_INFO_223_192_MASK 0x00000001 +#define MON_AXI_SUP_LOG_INFO_W7_MON_AXI_SUP_LOG_INFO_231_224_MASK 0x00000001 + +/* ############################################################################ + * # MonSysApbCurInfo Definition + */ +#define MON_SYS_APB_CUR_INFO_W0_MON_SYS_APB_CUR_ADDR BIT(0) +#define MON_SYS_APB_CUR_INFO_W1_MON_SYS_APB_CUR_WR_DATA BIT(0) +#define MON_SYS_APB_CUR_INFO_W2_MON_SYS_APB_CUR_RD_DATA BIT(0) +#define MON_SYS_APB_CUR_INFO_W3_MON_SYS_APB_CUR_ENABLE BIT(3) +#define MON_SYS_APB_CUR_INFO_W3_MON_SYS_APB_CUR_WRITE BIT(2) +#define MON_SYS_APB_CUR_INFO_W3_MON_SYS_APB_CUR_READY BIT(1) +#define MON_SYS_APB_CUR_INFO_W3_MON_SYS_APB_CUR_SEL BIT(4) +#define MON_SYS_APB_CUR_INFO_W3_MON_SYS_APB_CUR_SLV_ERR BIT(0) + +#define MON_SYS_APB_CUR_INFO_W0_MON_SYS_APB_CUR_ADDR_MASK 0xffffffff +#define MON_SYS_APB_CUR_INFO_W1_MON_SYS_APB_CUR_WR_DATA_MASK 0xffffffff +#define MON_SYS_APB_CUR_INFO_W2_MON_SYS_APB_CUR_RD_DATA_MASK 0xffffffff +#define MON_SYS_APB_CUR_INFO_W3_MON_SYS_APB_CUR_ENABLE_MASK 0x00000008 +#define MON_SYS_APB_CUR_INFO_W3_MON_SYS_APB_CUR_WRITE_MASK 0x00000004 +#define MON_SYS_APB_CUR_INFO_W3_MON_SYS_APB_CUR_READY_MASK 0x00000002 +#define MON_SYS_APB_CUR_INFO_W3_MON_SYS_APB_CUR_SEL_MASK 0x00000010 +#define MON_SYS_APB_CUR_INFO_W3_MON_SYS_APB_CUR_SLV_ERR_MASK 0x00000001 + +/* ############################################################################ + * # MonSysApbLogInfo Definition + */ +#define MON_SYS_APB_LOG_INFO_W0_MON_SYS_APB_LOG_ADDR BIT(0) +#define MON_SYS_APB_LOG_INFO_W1_MON_SYS_APB_LOG_WR_DATA BIT(0) +#define MON_SYS_APB_LOG_INFO_W2_MON_SYS_APB_LOG_RD_DATA BIT(0) +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_LOG_SEL BIT(4) +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_LOG_ENABLE BIT(3) +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_LOG_READY BIT(1) +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_ERR_CNT BIT(8) +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_LOG_SLV_ERR BIT(0) +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_LOG_WRITE BIT(2) + +#define MON_SYS_APB_LOG_INFO_W0_MON_SYS_APB_LOG_ADDR_MASK 0xffffffff +#define MON_SYS_APB_LOG_INFO_W1_MON_SYS_APB_LOG_WR_DATA_MASK 0xffffffff +#define MON_SYS_APB_LOG_INFO_W2_MON_SYS_APB_LOG_RD_DATA_MASK 0xffffffff +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_LOG_SEL_MASK 0x00000010 +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_LOG_ENABLE_MASK 0x00000008 +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_LOG_READY_MASK 0x00000002 +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_ERR_CNT_MASK 0x0000ff00 +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_LOG_SLV_ERR_MASK 0x00000001 +#define MON_SYS_APB_LOG_INFO_W3_MON_SYS_APB_LOG_WRITE_MASK 0x00000004 + +/* ############################################################################ + * # MonSecApbCurInfo Definition + */ +#define MON_SEC_APB_CUR_INFO_W0_MON_SEC_APB_CUR_ADDR BIT(0) +#define MON_SEC_APB_CUR_INFO_W1_MON_SEC_APB_CUR_WR_DATA BIT(0) +#define MON_SEC_APB_CUR_INFO_W2_MON_SEC_APB_CUR_RD_DATA BIT(0) +#define MON_SEC_APB_CUR_INFO_W3_MON_SEC_APB_CUR_WRITE BIT(2) +#define MON_SEC_APB_CUR_INFO_W3_MON_SEC_APB_CUR_READY BIT(1) +#define MON_SEC_APB_CUR_INFO_W3_MON_SEC_APB_CUR_SLV_ERR BIT(0) +#define MON_SEC_APB_CUR_INFO_W3_MON_SEC_APB_CUR_ENABLE BIT(3) +#define MON_SEC_APB_CUR_INFO_W3_MON_SEC_APB_CUR_SEL BIT(4) + +#define MON_SEC_APB_CUR_INFO_W0_MON_SEC_APB_CUR_ADDR_MASK 0xffffffff +#define MON_SEC_APB_CUR_INFO_W1_MON_SEC_APB_CUR_WR_DATA_MASK 0xffffffff +#define MON_SEC_APB_CUR_INFO_W2_MON_SEC_APB_CUR_RD_DATA_MASK 0xffffffff +#define MON_SEC_APB_CUR_INFO_W3_MON_SEC_APB_CUR_WRITE_MASK 0x00000004 +#define MON_SEC_APB_CUR_INFO_W3_MON_SEC_APB_CUR_READY_MASK 0x00000002 +#define MON_SEC_APB_CUR_INFO_W3_MON_SEC_APB_CUR_SLV_ERR_MASK 0x00000001 +#define MON_SEC_APB_CUR_INFO_W3_MON_SEC_APB_CUR_ENABLE_MASK 0x00000008 +#define MON_SEC_APB_CUR_INFO_W3_MON_SEC_APB_CUR_SEL_MASK 0x00000010 + +/* ############################################################################ + * # MonSecApbLogInfo Definition + */ +#define MON_SEC_APB_LOG_INFO_W0_MON_SEC_APB_LOG_ADDR BIT(0) +#define MON_SEC_APB_LOG_INFO_W1_MON_SEC_APB_LOG_WR_DATA BIT(0) +#define MON_SEC_APB_LOG_INFO_W2_MON_SEC_APB_LOG_RD_DATA BIT(0) +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_LOG_SLV_ERR BIT(0) +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_LOG_WRITE BIT(2) +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_LOG_READY BIT(1) +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_LOG_ENABLE BIT(3) +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_LOG_SEL BIT(4) +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_ERR_CNT BIT(8) + +#define MON_SEC_APB_LOG_INFO_W0_MON_SEC_APB_LOG_ADDR_MASK 0xffffffff +#define MON_SEC_APB_LOG_INFO_W1_MON_SEC_APB_LOG_WR_DATA_MASK 0xffffffff +#define MON_SEC_APB_LOG_INFO_W2_MON_SEC_APB_LOG_RD_DATA_MASK 0xffffffff +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_LOG_SLV_ERR_MASK 0x00000001 +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_LOG_WRITE_MASK 0x00000004 +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_LOG_READY_MASK 0x00000002 +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_LOG_ENABLE_MASK 0x00000008 +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_LOG_SEL_MASK 0x00000010 +#define MON_SEC_APB_LOG_INFO_W3_MON_SEC_APB_ERR_CNT_MASK 0x0000ff00 + +/* ############################################################################ + * # DebugCpuCnt Definition + */ +#define DEBUG_CPU_CNT_W0_MON_CPU_WA_LOG_CNT BIT(8) +#define DEBUG_CPU_CNT_W0_MON_CPU_RA_LOG_CNT BIT(0) +#define DEBUG_CPU_CNT_W0_MON_CPU_WD_LOG_CNT BIT(16) +#define DEBUG_CPU_CNT_W1_MON_CPU_WR_OUT_CNT BIT(8) +#define DEBUG_CPU_CNT_W1_MON_CPU_RD_OUT_CNT BIT(0) +#define DEBUG_CPU_CNT_W1_MON_CPU_WR_RESP_ERROR_CNT BIT(24) +#define DEBUG_CPU_CNT_W1_MON_CPU_RD_RESP_ERROR_CNT BIT(16) + +#define DEBUG_CPU_CNT_W0_MON_CPU_WA_LOG_CNT_MASK 0x0000ff00 +#define DEBUG_CPU_CNT_W0_MON_CPU_RA_LOG_CNT_MASK 0x000000ff +#define DEBUG_CPU_CNT_W0_MON_CPU_WD_LOG_CNT_MASK 0x00ff0000 +#define DEBUG_CPU_CNT_W1_MON_CPU_WR_OUT_CNT_MASK 0x00001f00 +#define DEBUG_CPU_CNT_W1_MON_CPU_RD_OUT_CNT_MASK 0x0000001f +#define DEBUG_CPU_CNT_W1_MON_CPU_WR_RESP_ERROR_CNT_MASK 0xff000000 +#define DEBUG_CPU_CNT_W1_MON_CPU_RD_RESP_ERROR_CNT_MASK 0x00ff0000 + +/* ############################################################################ + * # DebugMemCnt Definition + */ +#define DEBUG_MEM_CNT_W0_MON_MEM_WA_LOG_CNT BIT(8) +#define DEBUG_MEM_CNT_W0_MON_MEM_RA_LOG_CNT BIT(0) +#define DEBUG_MEM_CNT_W0_MON_MEM_WD_LOG_CNT BIT(16) +#define DEBUG_MEM_CNT_W1_MON_MEM_WR_OUT_CNT BIT(8) +#define DEBUG_MEM_CNT_W1_MON_MEM_RD_OUT_CNT BIT(0) + +#define DEBUG_MEM_CNT_W0_MON_MEM_WA_LOG_CNT_MASK 0x0000ff00 +#define DEBUG_MEM_CNT_W0_MON_MEM_RA_LOG_CNT_MASK 0x000000ff +#define DEBUG_MEM_CNT_W0_MON_MEM_WD_LOG_CNT_MASK 0x00ff0000 +#define DEBUG_MEM_CNT_W1_MON_MEM_WR_OUT_CNT_MASK 0x00001f00 +#define DEBUG_MEM_CNT_W1_MON_MEM_RD_OUT_CNT_MASK 0x0000001f + +/* ############################################################################ + * # DebugDdrCnt Definition + */ +#define DEBUG_DDR_CNT_W0_MON_DDR0_WA_LOG_CNT BIT(8) +#define DEBUG_DDR_CNT_W0_MON_DDR0_RA_LOG_CNT BIT(0) +#define DEBUG_DDR_CNT_W0_MON_DDR0_WD_LOG_CNT BIT(16) +#define DEBUG_DDR_CNT_W1_MON_DDR0_RD_OUT_CNT BIT(0) +#define DEBUG_DDR_CNT_W1_MON_DDR0_WR_RESP_ERROR_CNT BIT(24) +#define DEBUG_DDR_CNT_W1_MON_DDR0_RD_RESP_ERROR_CNT BIT(16) +#define DEBUG_DDR_CNT_W1_MON_DDR0_WR_OUT_CNT BIT(8) +#define DEBUG_DDR_CNT_W2_MON_DDR1_RA_LOG_CNT BIT(0) +#define DEBUG_DDR_CNT_W2_MON_DDR1_WD_LOG_CNT BIT(16) +#define DEBUG_DDR_CNT_W2_MON_DDR1_WA_LOG_CNT BIT(8) +#define DEBUG_DDR_CNT_W3_MON_DDR1_WR_OUT_CNT BIT(8) +#define DEBUG_DDR_CNT_W3_MON_DDR1_RD_RESP_ERROR_CNT BIT(16) +#define DEBUG_DDR_CNT_W3_MON_DDR1_RD_OUT_CNT BIT(0) +#define DEBUG_DDR_CNT_W3_MON_DDR1_WR_RESP_ERROR_CNT BIT(24) + +#define DEBUG_DDR_CNT_W0_MON_DDR0_WA_LOG_CNT_MASK 0x0000ff00 +#define DEBUG_DDR_CNT_W0_MON_DDR0_RA_LOG_CNT_MASK 0x000000ff +#define DEBUG_DDR_CNT_W0_MON_DDR0_WD_LOG_CNT_MASK 0x00ff0000 +#define DEBUG_DDR_CNT_W1_MON_DDR0_RD_OUT_CNT_MASK 0x0000001f +#define DEBUG_DDR_CNT_W1_MON_DDR0_WR_RESP_ERROR_CNT_MASK 0xff000000 +#define DEBUG_DDR_CNT_W1_MON_DDR0_RD_RESP_ERROR_CNT_MASK 0x00ff0000 +#define DEBUG_DDR_CNT_W1_MON_DDR0_WR_OUT_CNT_MASK 0x00001f00 +#define DEBUG_DDR_CNT_W2_MON_DDR1_RA_LOG_CNT_MASK 0x000000ff +#define DEBUG_DDR_CNT_W2_MON_DDR1_WD_LOG_CNT_MASK 0x00ff0000 +#define DEBUG_DDR_CNT_W2_MON_DDR1_WA_LOG_CNT_MASK 0x0000ff00 +#define DEBUG_DDR_CNT_W3_MON_DDR1_WR_OUT_CNT_MASK 0x00001f00 +#define DEBUG_DDR_CNT_W3_MON_DDR1_RD_RESP_ERROR_CNT_MASK 0x00ff0000 +#define DEBUG_DDR_CNT_W3_MON_DDR1_RD_OUT_CNT_MASK 0x0000001f +#define DEBUG_DDR_CNT_W3_MON_DDR1_WR_RESP_ERROR_CNT_MASK 0xff000000 + +/* ############################################################################ + * # DebugMshCnt Definition + */ +#define DEBUG_MSH_CNT_W0_MON_MSH_WD_LOG_CNT BIT(16) +#define DEBUG_MSH_CNT_W0_MON_MSH_RA_LOG_CNT BIT(0) +#define DEBUG_MSH_CNT_W0_MON_MSH_WA_LOG_CNT BIT(8) +#define DEBUG_MSH_CNT_W1_MON_MSH_RD_OUT_CNT BIT(0) +#define DEBUG_MSH_CNT_W1_MON_MSH_WR_OUT_CNT BIT(8) + +#define DEBUG_MSH_CNT_W0_MON_MSH_WD_LOG_CNT_MASK 0x00ff0000 +#define DEBUG_MSH_CNT_W0_MON_MSH_RA_LOG_CNT_MASK 0x000000ff +#define DEBUG_MSH_CNT_W0_MON_MSH_WA_LOG_CNT_MASK 0x0000ff00 +#define DEBUG_MSH_CNT_W1_MON_MSH_RD_OUT_CNT_MASK 0x0000001f +#define DEBUG_MSH_CNT_W1_MON_MSH_WR_OUT_CNT_MASK 0x00001f00 + +/* ############################################################################ + * # DebugPcieCnt Definition + */ +#define DEBUG_PCIE_CNT_W0_MON_PCIE_WD_LOG_CNT BIT(16) +#define DEBUG_PCIE_CNT_W0_MON_PCIE_RA_LOG_CNT BIT(0) +#define DEBUG_PCIE_CNT_W0_MON_PCIE_WA_LOG_CNT BIT(8) +#define DEBUG_PCIE_CNT_W1_MON_PCIE_WR_OUT_CNT BIT(8) +#define DEBUG_PCIE_CNT_W1_MON_PCIE_RD_OUT_CNT BIT(0) +#define DEBUG_PCIE_CNT_W1_MON_PCIE_WR_RESP_ERROR_CNT BIT(24) +#define DEBUG_PCIE_CNT_W1_MON_PCIE_RD_RESP_ERROR_CNT BIT(16) + +#define DEBUG_PCIE_CNT_W0_MON_PCIE_WD_LOG_CNT_MASK 0x00ff0000 +#define DEBUG_PCIE_CNT_W0_MON_PCIE_RA_LOG_CNT_MASK 0x000000ff +#define DEBUG_PCIE_CNT_W0_MON_PCIE_WA_LOG_CNT_MASK 0x0000ff00 +#define DEBUG_PCIE_CNT_W1_MON_PCIE_WR_OUT_CNT_MASK 0x00001f00 +#define DEBUG_PCIE_CNT_W1_MON_PCIE_RD_OUT_CNT_MASK 0x0000001f +#define DEBUG_PCIE_CNT_W1_MON_PCIE_WR_RESP_ERROR_CNT_MASK 0xff000000 +#define DEBUG_PCIE_CNT_W1_MON_PCIE_RD_RESP_ERROR_CNT_MASK 0x00ff0000 + +/* ############################################################################ + * # DebugQspiCnt Definition + */ +#define DEBUG_QSPI_CNT_W0_MON_QSPI_WD_LOG_CNT BIT(16) +#define DEBUG_QSPI_CNT_W0_MON_QSPI_RA_LOG_CNT BIT(0) +#define DEBUG_QSPI_CNT_W0_MON_QSPI_WA_LOG_CNT BIT(8) +#define DEBUG_QSPI_CNT_W1_MON_QSPI_RD_OUT_CNT BIT(0) +#define DEBUG_QSPI_CNT_W1_MON_QSPI_WR_OUT_CNT BIT(8) + +#define DEBUG_QSPI_CNT_W0_MON_QSPI_WD_LOG_CNT_MASK 0x00ff0000 +#define DEBUG_QSPI_CNT_W0_MON_QSPI_RA_LOG_CNT_MASK 0x000000ff +#define DEBUG_QSPI_CNT_W0_MON_QSPI_WA_LOG_CNT_MASK 0x0000ff00 +#define DEBUG_QSPI_CNT_W1_MON_QSPI_RD_OUT_CNT_MASK 0x0000001f +#define DEBUG_QSPI_CNT_W1_MON_QSPI_WR_OUT_CNT_MASK 0x00001f00 + +/* ############################################################################ + * # DebugSupCnt Definition + */ +#define DEBUG_SUP_CNT_W0_MON_SUP_WD_LOG_CNT BIT(16) +#define DEBUG_SUP_CNT_W0_MON_SUP_RA_LOG_CNT BIT(0) +#define DEBUG_SUP_CNT_W0_MON_SUP_WA_LOG_CNT BIT(8) +#define DEBUG_SUP_CNT_W1_MON_SUP_WR_OUT_CNT BIT(8) +#define DEBUG_SUP_CNT_W1_MON_SUP_RD_RESP_ERROR_CNT BIT(16) +#define DEBUG_SUP_CNT_W1_MON_SUP_WR_RESP_ERROR_CNT BIT(24) +#define DEBUG_SUP_CNT_W1_MON_SUP_RD_OUT_CNT BIT(0) + +#define DEBUG_SUP_CNT_W0_MON_SUP_WD_LOG_CNT_MASK 0x00ff0000 +#define DEBUG_SUP_CNT_W0_MON_SUP_RA_LOG_CNT_MASK 0x000000ff +#define DEBUG_SUP_CNT_W0_MON_SUP_WA_LOG_CNT_MASK 0x0000ff00 +#define DEBUG_SUP_CNT_W1_MON_SUP_WR_OUT_CNT_MASK 0x00001f00 +#define DEBUG_SUP_CNT_W1_MON_SUP_RD_RESP_ERROR_CNT_MASK 0x00ff0000 +#define DEBUG_SUP_CNT_W1_MON_SUP_WR_RESP_ERROR_CNT_MASK 0xff000000 +#define DEBUG_SUP_CNT_W1_MON_SUP_RD_OUT_CNT_MASK 0x0000001f + +/* ############################################################################ + * # SysSpiVecLog Definition + */ +#define SYS_SPI_VEC_LOG_W0_SPI_VEC_LOG_31_0 BIT(0) +#define SYS_SPI_VEC_LOG_W1_SPI_VEC_LOG_63_32 BIT(0) +#define SYS_SPI_VEC_LOG_W2_SPI_VEC_LOG_95_64 BIT(0) +#define SYS_SPI_VEC_LOG_W3_SPI_VEC_LOG_127_96 BIT(0) +#define SYS_SPI_VEC_LOG_W4_SPI_VEC_LOG_159_128 BIT(0) + +#define SYS_SPI_VEC_LOG_W0_SPI_VEC_LOG_31_0_MASK 0x00000001 +#define SYS_SPI_VEC_LOG_W1_SPI_VEC_LOG_63_32_MASK 0x00000001 +#define SYS_SPI_VEC_LOG_W2_SPI_VEC_LOG_95_64_MASK 0x00000001 +#define SYS_SPI_VEC_LOG_W3_SPI_VEC_LOG_127_96_MASK 0x00000001 +#define SYS_SPI_VEC_LOG_W4_SPI_VEC_LOG_159_128_MASK 0x00000001 + +/* ############################################################################ + * # DebugAhbRespCnt Definition + */ +#define DEBUG_AHB_RESP_CNT_W0_MON_MSH_CFG_RESP_ERROR_CNT BIT(8) +#define DEBUG_AHB_RESP_CNT_W0_MON_DDR_CFG_RESP_ERROR_CNT BIT(0) +#define DEBUG_AHB_RESP_CNT_W0_MON_USB_CFG_RESP_ERROR_CNT BIT(16) + +#define DEBUG_AHB_RESP_CNT_W0_MON_MSH_CFG_RESP_ERROR_CNT_MASK 0x0000ff00 +#define DEBUG_AHB_RESP_CNT_W0_MON_DDR_CFG_RESP_ERROR_CNT_MASK 0x000000ff +#define DEBUG_AHB_RESP_CNT_W0_MON_USB_CFG_RESP_ERROR_CNT_MASK 0x00ff0000 + +/* ############################################################################ + * # DebugGicRespCnt Definition + */ +#define DEBUG_GIC_RESP_CNT_W0_MON_GIC_RD_RESP_ERROR_CNT BIT(0) +#define DEBUG_GIC_RESP_CNT_W0_MON_GIC_WR_RESP_ERROR_CNT BIT(8) + +#define DEBUG_GIC_RESP_CNT_W0_MON_GIC_RD_RESP_ERROR_CNT_MASK 0x000000ff +#define DEBUG_GIC_RESP_CNT_W0_MON_GIC_WR_RESP_ERROR_CNT_MASK 0x0000ff00 + +/* ############################################################################ + * # DebugMemPtrCfg Definition + */ +#define DEBUG_MEM_PTR_CFG_W0_CFG_DBG_START_PTR BIT(0) +#define DEBUG_MEM_PTR_CFG_W0_CFG_DBG_END_PTR BIT(16) + +#define DEBUG_MEM_PTR_CFG_W0_CFG_DBG_START_PTR_MASK 0x00003fff +#define DEBUG_MEM_PTR_CFG_W0_CFG_DBG_END_PTR_MASK 0x3fff0000 + +/* ############################################################################ + * # Grant0IntMask Definition + */ +#define GRANT0_INT_MASK_W0_GRANT0_INT_MASK BIT(0) + +#define GRANT0_INT_MASK_W0_GRANT0_INT_MASK_MASK 0xffffffff + +/* ############################################################################ + * # Grant0IntCtl Definition + */ +#define GRANT0_INT_CTL_W0_GRANT0_INT_CTL BIT(0) + +#define GRANT0_INT_CTL_W0_GRANT0_INT_CTL_MASK 0xffffffff + +/* ############################################################################ + * # Grant1IntMask Definition + */ +#define GRANT1_INT_MASK_W0_GRANT1_INT_MASK BIT(0) + +#define GRANT1_INT_MASK_W0_GRANT1_INT_MASK_MASK 0xffffffff + +/* ############################################################################ + * # Grant1IntCtl Definition + */ +#define GRANT1_INT_CTL_W0_GRANT1_INT_CTL BIT(0) + +#define GRANT1_INT_CTL_W0_GRANT1_INT_CTL_MASK 0xffffffff + +/* ############################################################################ + * # Grant2IntMask Definition + */ +#define GRANT2_INT_MASK_W0_GRANT2_INT_MASK BIT(0) + +#define GRANT2_INT_MASK_W0_GRANT2_INT_MASK_MASK 0xffffffff + +/* ############################################################################ + * # Grant2IntCtl Definition + */ +#define GRANT2_INT_CTL_W0_GRANT2_INT_CTL BIT(0) + +#define GRANT2_INT_CTL_W0_GRANT2_INT_CTL_MASK 0xffffffff + +/* ############################################################################ + * # Grant3IntMask Definition + */ +#define GRANT3_INT_MASK_W0_GRANT3_INT_MASK BIT(0) + +#define GRANT3_INT_MASK_W0_GRANT3_INT_MASK_MASK 0xffffffff + +/* ############################################################################ + * # Grant3IntCtl Definition + */ +#define GRANT3_INT_CTL_W0_GRANT3_INT_CTL BIT(0) + +#define GRANT3_INT_CTL_W0_GRANT3_INT_CTL_MASK 0xffffffff + +/* ############################################################################ + * # SysIntrIntCtl Definition + */ +#define SYS_INTR_INT_CTL_W0_SYS_INTR_INT_CTL_31_0 BIT(0) +#define SYS_INTR_INT_CTL_W1_SYS_INTR_INT_CTL_63_32 BIT(0) + +#define SYS_INTR_INT_CTL_W0_SYS_INTR_INT_CTL_31_0_MASK 0x00000001 +#define SYS_INTR_INT_CTL_W1_SYS_INTR_INT_CTL_63_32_MASK 0x00000001 + +/* ############################################################################ + * # SupIntrIntCtl Definition + */ +#define SUP_INTR_INT_CTL_W0_SUP_INTR_INT_CTL_31_0 BIT(0) +#define SUP_INTR_INT_CTL_W1_SUP_INTR_INT_CTL_63_32 BIT(0) + +#define SUP_INTR_INT_CTL_W0_SUP_INTR_INT_CTL_31_0_MASK 0x00000001 +#define SUP_INTR_INT_CTL_W1_SUP_INTR_INT_CTL_63_32_MASK 0x00000001 + +/* ############################################################################ + * # SysMiscInfo0 Definition + */ +#define SYS_MISC_INFO0_W0_SYS_MISC_INFO0 BIT(0) + +#define SYS_MISC_INFO0_W0_SYS_MISC_INFO0_MASK 0xffffffff + +/* ############################################################################ + * # SysMiscInfo1 Definition + */ +#define SYS_MISC_INFO1_W0_SYS_MISC_INFO1 BIT(0) + +#define SYS_MISC_INFO1_W0_SYS_MISC_INFO1_MASK 0xffffffff + +/* ############################################################################ + * # SysMiscInfo2 Definition + */ +#define SYS_MISC_INFO2_W0_SYS_MISC_INFO2 BIT(0) + +#define SYS_MISC_INFO2_W0_SYS_MISC_INFO2_MASK 0xffffffff + +/* ############################################################################ + * # SysMiscInfo3 Definition + */ +#define SYS_MISC_INFO3_W0_SYS_MISC_INFO3 BIT(0) + +#define SYS_MISC_INFO3_W0_SYS_MISC_INFO3_MASK 0xffffffff + +/* ############################################################################ + * # CommonInfo0 Definition + */ +#define COMMON_INFO0_W0_COMMON_INFO0 BIT(0) + +#define COMMON_INFO0_W0_COMMON_INFO0_MASK 0xffffffff + +/* ############################################################################ + * # CommonInfo1 Definition + */ +#define COMMON_INFO1_W0_COMMON_INFO1 BIT(0) + +#define COMMON_INFO1_W0_COMMON_INFO1_MASK 0xffffffff + +/* ############################################################################ + * # CommonInfo2 Definition + */ +#define COMMON_INFO2_W0_COMMON_INFO2 BIT(0) + +#define COMMON_INFO2_W0_COMMON_INFO2_MASK 0xffffffff + +/* ############################################################################ + * # CommonInfo3 Definition + */ +#define COMMON_INFO3_W0_COMMON_INFO3 BIT(0) + +#define COMMON_INFO3_W0_COMMON_INFO3_MASK 0xffffffff + +/* ############################################################################ + * # Grant0ExtMask Definition + */ +#define GRANT0_EXT_MASK_W0_GRANT0_EXT_MASK BIT(0) + +#define GRANT0_EXT_MASK_W0_GRANT0_EXT_MASK_MASK 0xffffffff + +/* ############################################################################ + * # Grant0ExtCtl Definition + */ +#define GRANT0_EXT_CTL_W0_GRANT0_EXT_CTL BIT(0) + +#define GRANT0_EXT_CTL_W0_GRANT0_EXT_CTL_MASK 0xffffffff + +/* ############################################################################ + * # Grant1ExtMask Definition + */ +#define GRANT1_EXT_MASK_W0_GRANT1_EXT_MASK BIT(0) + +#define GRANT1_EXT_MASK_W0_GRANT1_EXT_MASK_MASK 0xffffffff + +/* ############################################################################ + * # Grant1ExtCtl Definition + */ +#define GRANT1_EXT_CTL_W0_GRANT1_EXT_CTL BIT(0) + +#define GRANT1_EXT_CTL_W0_GRANT1_EXT_CTL_MASK 0xffffffff + +/* ############################################################################ + * # Grant2ExtMask Definition + */ +#define GRANT2_EXT_MASK_W0_GRANT2_EXT_MASK BIT(0) + +#define GRANT2_EXT_MASK_W0_GRANT2_EXT_MASK_MASK 0xffffffff + +/* ############################################################################ + * # Grant2ExtCtl Definition + */ +#define GRANT2_EXT_CTL_W0_GRANT2_EXT_CTL BIT(0) + +#define GRANT2_EXT_CTL_W0_GRANT2_EXT_CTL_MASK 0xffffffff + +/* ############################################################################ + * # Grant3ExtMask Definition + */ +#define GRANT3_EXT_MASK_W0_GRANT3_EXT_MASK BIT(0) + +#define GRANT3_EXT_MASK_W0_GRANT3_EXT_MASK_MASK 0xffffffff + +/* ############################################################################ + * # Grant3ExtCtl Definition + */ +#define GRANT3_EXT_CTL_W0_GRANT3_EXT_CTL BIT(0) + +#define GRANT3_EXT_CTL_W0_GRANT3_EXT_CTL_MASK 0xffffffff + +/* ############################################################################ + * # SysIntrExtCtl Definition + */ +#define SYS_INTR_EXT_CTL_W0_SYS_INTR_EXT_CTL_31_0 BIT(0) +#define SYS_INTR_EXT_CTL_W1_SYS_INTR_EXT_CTL_63_32 BIT(0) + +#define SYS_INTR_EXT_CTL_W0_SYS_INTR_EXT_CTL_31_0_MASK 0x00000001 +#define SYS_INTR_EXT_CTL_W1_SYS_INTR_EXT_CTL_63_32_MASK 0x00000001 + +/* ############################################################################ + * # SupIntrExtCtl Definition + */ +#define SUP_INTR_EXT_CTL_W0_SUP_INTR_EXT_CTL_31_0 BIT(0) +#define SUP_INTR_EXT_CTL_W1_SUP_INTR_EXT_CTL_63_32 BIT(0) + +#define SUP_INTR_EXT_CTL_W0_SUP_INTR_EXT_CTL_31_0_MASK 0x00000001 +#define SUP_INTR_EXT_CTL_W1_SUP_INTR_EXT_CTL_63_32_MASK 0x00000001 + +/* ############################################################################ + * # SupMiscInfo0 Definition + */ +#define SUP_MISC_INFO0_W0_SUP_MISC_INFO0 BIT(0) + +#define SUP_MISC_INFO0_W0_SUP_MISC_INFO0_MASK 0xffffffff + +/* ############################################################################ + * # SupMiscInfo1 Definition + */ +#define SUP_MISC_INFO1_W0_SUP_MISC_INFO1 BIT(0) + +#define SUP_MISC_INFO1_W0_SUP_MISC_INFO1_MASK 0xffffffff + +/* ############################################################################ + * # SupMiscInfo2 Definition + */ +#define SUP_MISC_INFO2_W0_SUP_MISC_INFO2 BIT(0) + +#define SUP_MISC_INFO2_W0_SUP_MISC_INFO2_MASK 0xffffffff + +/* ############################################################################ + * # SupMiscInfo3 Definition + */ +#define SUP_MISC_INFO3_W0_SUP_MISC_INFO3 BIT(0) + +#define SUP_MISC_INFO3_W0_SUP_MISC_INFO3_MASK 0xffffffff + +struct SysCtl_mems { + u32 SysApbMem0[3]; /* 0x0000fe00 */ + u32 SysApbMem0_rsv3; + u32 SysApbMem1[3]; /* 0x0000fe10 */ + u32 SysApbMem1_rsv3; + u32 SysApbMem2[3]; /* 0x0000fe20 */ + u32 SysApbMem2_rsv3; + u32 SysApbMem3[3]; /* 0x0000fe30 */ + u32 SysApbMem3_rsv3; + u32 SysApbMem4[3]; /* 0x0000fe40 */ + u32 SysApbMem4_rsv3; + u32 SysApbMem5[3]; /* 0x0000fe50 */ + u32 SysApbMem5_rsv3; + u32 SysApbMem6[3]; /* 0x0000fe60 */ + u32 SysApbMem6_rsv3; + u32 SysApbMem7[3]; /* 0x0000fe70 */ + u32 SysApbMem7_rsv3; + u32 SysApbMem8[3]; /* 0x0000fe80 */ + u32 SysApbMem8_rsv3; + u32 SysApbMem9[3]; /* 0x0000fe90 */ + u32 SysApbMem9_rsv3; + u32 SysApbMem10[3]; /* 0x0000fea0 */ + u32 SysApbMem10_rsv3; + u32 SysApbMem11[3]; /* 0x0000feb0 */ + u32 SysApbMem11_rsv3; + u32 SysApbMem12[3]; /* 0x0000fec0 */ + u32 SysApbMem12_rsv3; + u32 SysApbMem13[3]; /* 0x0000fed0 */ + u32 SysApbMem13_rsv3; + u32 SysApbMem14[3]; /* 0x0000fee0 */ + u32 SysApbMem14_rsv3; + u32 SysApbMem15[3]; /* 0x0000fef0 */ + u32 SysApbMem15_rsv3; + u32 SecApbMem0[3]; /* 0x0000ff00 */ + u32 SecApbMem0_rsv3; + u32 SecApbMem1[3]; /* 0x0000ff10 */ + u32 SecApbMem1_rsv3; + u32 SecApbMem2[3]; /* 0x0000ff20 */ + u32 SecApbMem2_rsv3; + u32 SecApbMem3[3]; /* 0x0000ff30 */ + u32 SecApbMem3_rsv3; + u32 SecApbMem4[3]; /* 0x0000ff40 */ + u32 SecApbMem4_rsv3; + u32 SecApbMem5[3]; /* 0x0000ff50 */ + u32 SecApbMem5_rsv3; + u32 SecApbMem6[3]; /* 0x0000ff60 */ + u32 SecApbMem6_rsv3; + u32 SecApbMem7[3]; /* 0x0000ff70 */ + u32 SecApbMem7_rsv3; + u32 SecApbMem8[3]; /* 0x0000ff80 */ + u32 SecApbMem8_rsv3; + u32 SecApbMem9[3]; /* 0x0000ff90 */ + u32 SecApbMem9_rsv3; + u32 SecApbMem10[3]; /* 0x0000ffa0 */ + u32 SecApbMem10_rsv3; + u32 SecApbMem11[3]; /* 0x0000ffb0 */ + u32 SecApbMem11_rsv3; + u32 SecApbMem12[3]; /* 0x0000ffc0 */ + u32 SecApbMem12_rsv3; + u32 SecApbMem13[3]; /* 0x0000ffd0 */ + u32 SecApbMem13_rsv3; + u32 SecApbMem14[3]; /* 0x0000ffe0 */ + u32 SecApbMem14_rsv3; + u32 SecApbMem15[3]; /* 0x0000fff0 */ + u32 SecApbMem15_rsv3; +}; + +/* ############################################################################ + * # SysApbMem Definition + */ +#define SYS_APB_MEM_W0_ADDR BIT(0) +#define SYS_APB_MEM_W1_DATA BIT(0) +#define SYS_APB_MEM_W2_WR_EN BIT(0) +#define SYS_APB_MEM_W2_SLV_ERR BIT(1) + +#define SYS_APB_MEM_W0_ADDR_MASK 0xffffffff +#define SYS_APB_MEM_W1_DATA_MASK 0xffffffff +#define SYS_APB_MEM_W2_WR_EN_MASK 0x00000001 +#define SYS_APB_MEM_W2_SLV_ERR_MASK 0x00000002 + +/* ############################################################################ + * # SecApbMem Definition + */ +#define SEC_APB_MEM_W0_ADDR BIT(0) +#define SEC_APB_MEM_W1_DATA BIT(0) +#define SEC_APB_MEM_W2_WR_EN BIT(0) +#define SEC_APB_MEM_W2_SLV_ERR BIT(1) + +#define SEC_APB_MEM_W0_ADDR_MASK 0xffffffff +#define SEC_APB_MEM_W1_DATA_MASK 0xffffffff +#define SEC_APB_MEM_W2_WR_EN_MASK 0x00000001 +#define SEC_APB_MEM_W2_SLV_ERR_MASK 0x00000002 + +/* Bootmode setting values */ +#define ROM_QSPI_MODE 0x00000000 +#define ROM_EMMC_MODE 0x00000001 +#define ROM_SD_MODE 0x00000002 +#define ROM_UART_MODE 0x00000003 +#define NON_ROM_MODE 0x00000004 +#define JTAG_MODE 0x00000005 +#define ROM_QSPI_DEBUG_MODE 0x00000007 + +#define BOOT_MODES_MASK 0x00000007 + +#define sysctl_base ((struct SysCtl_regs *)CONFIG_SYS_CTC5236_SYSCTL_BASE) +#endif + +#endif /*__CTC5236_SYSCTL_H__*/ diff --git a/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/Makefile b/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/Makefile new file mode 100644 index 000000000000..b6d77c0e6cac --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/Makefile @@ -0,0 +1 @@ +obj-m = pinctrl-ctc.o diff --git a/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/core.h b/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/core.h new file mode 100644 index 000000000000..4a0526e567df --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/core.h @@ -0,0 +1,254 @@ +/* + * Core private header for the pin control subsystem + * + * Copyright (C) 2011 ST-Ericsson SA + * Written on behalf of Linaro for ST-Ericsson + * + * Author: Linus Walleij + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include + +struct pinctrl_gpio_range; + +/** + * struct pinctrl_dev - pin control class device + * @node: node to include this pin controller in the global pin controller list + * @desc: the pin controller descriptor supplied when initializing this pin + * controller + * @pin_desc_tree: each pin descriptor for this pin controller is stored in + * this radix tree + * @pin_group_tree: optionally each pin group can be stored in this radix tree + * @num_groups: optionally number of groups can be kept here + * @pin_function_tree: optionally each function can be stored in this radix tree + * @num_functions: optionally number of functions can be kept here + * @gpio_ranges: a list of GPIO ranges that is handled by this pin controller, + * ranges are added to this list at runtime + * @dev: the device entry for this pin controller + * @owner: module providing the pin controller, used for refcounting + * @driver_data: driver data for drivers registering to the pin controller + * subsystem + * @p: result of pinctrl_get() for this device + * @hog_default: default state for pins hogged by this device + * @hog_sleep: sleep state for pins hogged by this device + * @mutex: mutex taken on each pin controller specific action + * @device_root: debugfs root for this device + */ +struct pinctrl_dev { + struct list_head node; + struct pinctrl_desc *desc; + struct radix_tree_root pin_desc_tree; +#ifdef CONFIG_GENERIC_PINCTRL_GROUPS + struct radix_tree_root pin_group_tree; + unsigned int num_groups; +#endif +#ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS + struct radix_tree_root pin_function_tree; + unsigned int num_functions; +#endif + struct list_head gpio_ranges; + struct device *dev; + struct module *owner; + void *driver_data; + struct pinctrl *p; + struct pinctrl_state *hog_default; + struct pinctrl_state *hog_sleep; + struct mutex mutex; +#ifdef CONFIG_DEBUG_FS + struct dentry *device_root; +#endif +}; + +/** + * struct pinctrl - per-device pin control state holder + * @node: global list node + * @dev: the device using this pin control handle + * @states: a list of states for this device + * @state: the current state + * @dt_maps: the mapping table chunks dynamically parsed from device tree for + * this device, if any + * @users: reference count + */ +struct pinctrl { + struct list_head node; + struct device *dev; + struct list_head states; + struct pinctrl_state *state; + struct list_head dt_maps; + struct kref users; +}; + +/** + * struct pinctrl_state - a pinctrl state for a device + * @node: list node for struct pinctrl's @states field + * @name: the name of this state + * @settings: a list of settings for this state + */ +struct pinctrl_state { + struct list_head node; + const char *name; + struct list_head settings; +}; + +/** + * struct pinctrl_setting_mux - setting data for MAP_TYPE_MUX_GROUP + * @group: the group selector to program + * @func: the function selector to program + */ +struct pinctrl_setting_mux { + unsigned group; + unsigned func; +}; + +/** + * struct pinctrl_setting_configs - setting data for MAP_TYPE_CONFIGS_* + * @group_or_pin: the group selector or pin ID to program + * @configs: a pointer to an array of config parameters/values to program into + * hardware. Each individual pin controller defines the format and meaning + * of config parameters. + * @num_configs: the number of entries in array @configs + */ +struct pinctrl_setting_configs { + unsigned group_or_pin; + unsigned long *configs; + unsigned num_configs; +}; + +/** + * struct pinctrl_setting - an individual mux or config setting + * @node: list node for struct pinctrl_settings's @settings field + * @type: the type of setting + * @pctldev: pin control device handling to be programmed. Not used for + * PIN_MAP_TYPE_DUMMY_STATE. + * @dev_name: the name of the device using this state + * @data: Data specific to the setting type + */ +struct pinctrl_setting { + struct list_head node; + enum pinctrl_map_type type; + struct pinctrl_dev *pctldev; + const char *dev_name; + union { + struct pinctrl_setting_mux mux; + struct pinctrl_setting_configs configs; + } data; +}; + +/** + * struct pin_desc - pin descriptor for each physical pin in the arch + * @pctldev: corresponding pin control device + * @name: a name for the pin, e.g. the name of the pin/pad/finger on a + * datasheet or such + * @dynamic_name: if the name of this pin was dynamically allocated + * @drv_data: driver-defined per-pin data. pinctrl core does not touch this + * @mux_usecount: If zero, the pin is not claimed, and @owner should be NULL. + * If non-zero, this pin is claimed by @owner. This field is an integer + * rather than a boolean, since pinctrl_get() might process multiple + * mapping table entries that refer to, and hence claim, the same group + * or pin, and each of these will increment the @usecount. + * @mux_owner: The name of device that called pinctrl_get(). + * @mux_setting: The most recent selected mux setting for this pin, if any. + * @gpio_owner: If pinctrl_gpio_request() was called for this pin, this is + * the name of the GPIO that "owns" this pin. + */ +struct pin_desc { + struct pinctrl_dev *pctldev; + const char *name; + bool dynamic_name; + void *drv_data; + /* These fields only added when supporting pinmux drivers */ +#ifdef CONFIG_PINMUX + unsigned mux_usecount; + const char *mux_owner; + const struct pinctrl_setting_mux *mux_setting; + const char *gpio_owner; +#endif +}; + +/** + * struct pinctrl_maps - a list item containing part of the mapping table + * @node: mapping table list node + * @maps: array of mapping table entries + * @num_maps: the number of entries in @maps + */ +struct pinctrl_maps { + struct list_head node; + const struct pinctrl_map *maps; + unsigned num_maps; +}; + +#ifdef CONFIG_GENERIC_PINCTRL_GROUPS + +/** + * struct group_desc - generic pin group descriptor + * @name: name of the pin group + * @pins: array of pins that belong to the group + * @num_pins: number of pins in the group + * @data: pin controller driver specific data + */ +struct group_desc { + const char *name; + int *pins; + int num_pins; + void *data; +}; + +int pinctrl_generic_get_group_count(struct pinctrl_dev *pctldev); + +const char *pinctrl_generic_get_group_name(struct pinctrl_dev *pctldev, + unsigned int group_selector); + +int pinctrl_generic_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int group_selector, + const unsigned int **pins, + unsigned int *npins); + +struct group_desc *pinctrl_generic_get_group(struct pinctrl_dev *pctldev, + unsigned int group_selector); + +int pinctrl_generic_add_group(struct pinctrl_dev *pctldev, const char *name, + int *gpins, int ngpins, void *data); + +int pinctrl_generic_remove_group(struct pinctrl_dev *pctldev, + unsigned int group_selector); + +#endif /* CONFIG_GENERIC_PINCTRL_GROUPS */ + +struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name); +struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np); +int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name); +const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin); +int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, + const char *pin_group); + +static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, + unsigned int pin) +{ + return radix_tree_lookup(&pctldev->pin_desc_tree, pin); +} + +extern struct pinctrl_gpio_range * +pinctrl_find_gpio_range_from_pin_nolock(struct pinctrl_dev *pctldev, + unsigned int pin); + +int pinctrl_register_map(const struct pinctrl_map *maps, unsigned num_maps, + bool dup); +void pinctrl_unregister_map(const struct pinctrl_map *map); + +extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev); +extern int pinctrl_force_default(struct pinctrl_dev *pctldev); + +extern struct mutex pinctrl_maps_mutex; +extern struct list_head pinctrl_maps; + +#define for_each_maps(_maps_node_, _i_, _map_) \ + list_for_each_entry(_maps_node_, &pinctrl_maps, node) \ + for (_i_ = 0, _map_ = &_maps_node_->maps[_i_]; \ + _i_ < _maps_node_->num_maps; \ + _i_++, _map_ = &_maps_node_->maps[_i_]) diff --git a/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/pinconf.h b/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/pinconf.h new file mode 100644 index 000000000000..6c722505f893 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/pinconf.h @@ -0,0 +1,132 @@ +/* + * Internal interface between the core pin control system and the + * pin config portions + * + * Copyright (C) 2011 ST-Ericsson SA + * Written on behalf of Linaro for ST-Ericsson + * Based on bits of regulator core, gpio core and clk core + * + * Author: Linus Walleij + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifdef CONFIG_PINCONF + +int pinconf_check_ops(struct pinctrl_dev *pctldev); +int pinconf_validate_map(const struct pinctrl_map *map, int i); +int pinconf_map_to_setting(const struct pinctrl_map *map, + struct pinctrl_setting *setting); +void pinconf_free_setting(const struct pinctrl_setting *setting); +int pinconf_apply_setting(const struct pinctrl_setting *setting); + +int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *configs, size_t nconfigs); + +/* + * You will only be interested in these if you're using PINCONF + * so don't supply any stubs for these. + */ +int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *config); +int pin_config_group_get(const char *dev_name, const char *pin_group, + unsigned long *config); + +#else + +static inline int pinconf_check_ops(struct pinctrl_dev *pctldev) +{ + return 0; +} + +static inline int pinconf_validate_map(const struct pinctrl_map *map, int i) +{ + return 0; +} + +static inline int pinconf_map_to_setting(const struct pinctrl_map *map, + struct pinctrl_setting *setting) +{ + return 0; +} + +static inline void pinconf_free_setting(const struct pinctrl_setting *setting) +{ +} + +static inline int pinconf_apply_setting(const struct pinctrl_setting *setting) +{ + return 0; +} + +static inline int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *configs, size_t nconfigs) +{ + return -ENOTSUPP; +} + +#endif + +#if defined(CONFIG_PINCONF) && defined(CONFIG_DEBUG_FS) + +void pinconf_show_map(struct seq_file *s, const struct pinctrl_map *map); +void pinconf_show_setting(struct seq_file *s, + const struct pinctrl_setting *setting); +void pinconf_init_device_debugfs(struct dentry *devroot, + struct pinctrl_dev *pctldev); + +#else + +static inline void pinconf_show_map(struct seq_file *s, + const struct pinctrl_map *map) +{ +} + +static inline void pinconf_show_setting(struct seq_file *s, + const struct pinctrl_setting *setting) +{ +} + +static inline void pinconf_init_device_debugfs(struct dentry *devroot, + struct pinctrl_dev *pctldev) +{ +} + +#endif + +/* + * The following functions are available if the driver uses the generic + * pin config. + */ + +#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_DEBUG_FS) + +void pinconf_generic_dump_pins(struct pinctrl_dev *pctldev, + struct seq_file *s, const char *gname, + unsigned pin); + +void pinconf_generic_dump_config(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned long config); +#else + +static inline void pinconf_generic_dump_pins(struct pinctrl_dev *pctldev, + struct seq_file *s, + const char *gname, unsigned pin) +{ + return; +} + +static inline void pinconf_generic_dump_config(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned long config) +{ + return; +} +#endif + +#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_OF) +int pinconf_generic_parse_dt_config(struct device_node *np, + struct pinctrl_dev *pctldev, + unsigned long **configs, + unsigned int *nconfigs); +#endif diff --git a/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/pinctrl-ctc.c b/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/pinctrl-ctc.c new file mode 100644 index 000000000000..50c65dbfd786 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/pinctrl-ctc.c @@ -0,0 +1,537 @@ +/* + * Copyright (c) 2018 Liuht + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/sysctl.h" +#include "pinctrl-ctc.h" +#include "core.h" +#include "pinconf.h" + +#define CTC_PIN_BANK_NUM 2 + +struct ctc_pin_bank { + u32 pin_base; + u8 nr_pins; + char *name; +}; + +struct ctc_pin_ctrl { + struct ctc_pin_bank *pin_banks; + u32 nr_banks; + u32 nr_pins; + char *label; +}; + +struct ctc_pin_config { + unsigned int func; + unsigned long *configs; + unsigned int nconfigs; +}; + +struct ctc_pin_group { + const char *name; + unsigned int npins; + unsigned int *pins; + struct ctc_pin_config *data; +}; + +struct ctc_pmx_func { + const char *name; + const char **groups; + u8 ngroups; +}; + +struct ctc_pinctrl { + struct regmap *regmap_base; + struct device *dev; + struct pinctrl_desc pctl; + struct pinctrl_dev *pctl_dev; + struct ctc_pin_ctrl *ctrl; + struct ctc_pin_group *groups; + unsigned int ngroups; + struct ctc_pmx_func *functions; + unsigned int nfunctions; +}; + +static void ctc_pinctrl_child_count(struct ctc_pinctrl *info, + struct device_node *np) +{ + struct device_node *child; + + for_each_child_of_node(np, child) { + info->nfunctions++; + info->ngroups += of_get_child_count(child); + } +} + +static struct ctc_pin_bank *ctc_bank_num_to_bank(struct ctc_pinctrl *info, + unsigned int num) +{ + struct ctc_pin_bank *b = info->ctrl->pin_banks; + + if (num < info->ctrl->nr_banks) + return &b[num]; + + return ERR_PTR(-EINVAL); +} + +static int ctc_pinctrl_parse_groups(struct device_node *np, + struct ctc_pin_group *grp, + struct ctc_pinctrl *info, u32 index) +{ + struct ctc_pin_bank *bank; + int size; + const __be32 *list; + int num; + int i, j; + + dev_dbg(info->dev, "group(%d): %s\n", index, np->name); + + /* Initialise group */ + grp->name = np->name; + + /* + * the binding format is ctc,pins = , + * do sanity check and calculate pins number + */ + list = of_get_property(np, "ctc,pins", &size); + /* we do not check return since it's safe node passed down */ + size /= sizeof(*list); + if (!size || size % 3) { + dev_err(info->dev, + "wrong pins number or pins and configs should be by 4\n"); + return -EINVAL; + } + + grp->npins = size / 3; + + grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), + GFP_KERNEL); + grp->data = devm_kzalloc(info->dev, grp->npins * + sizeof(struct ctc_pin_config), GFP_KERNEL); + if (!grp->pins || !grp->data) + return -ENOMEM; + + for (i = 0, j = 0; i < size; i += 3, j++) { + num = be32_to_cpu(*list++); + bank = ctc_bank_num_to_bank(info, num); + if (IS_ERR(bank)) + return PTR_ERR(bank); + + grp->pins[j] = bank->pin_base + be32_to_cpu(*list++); + grp->data[j].func = be32_to_cpu(*list++); + } + + return 0; +} + +static int ctc_pinctrl_parse_functions(struct device_node *np, + struct ctc_pinctrl *info, u32 index) +{ + struct device_node *child; + struct ctc_pmx_func *func; + struct ctc_pin_group *grp; + int ret; + static u32 grp_index; + u32 i = 0; + + dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name); + + func = &info->functions[index]; + + /* Initialise function */ + func->name = np->name; + func->ngroups = of_get_child_count(np); + if (func->ngroups <= 0) + return 0; + + func->groups = devm_kzalloc(info->dev, + func->ngroups * sizeof(char *), GFP_KERNEL); + if (!func->groups) + return -ENOMEM; + + for_each_child_of_node(np, child) { + func->groups[i] = child->name; + grp = &info->groups[grp_index++]; + ret = ctc_pinctrl_parse_groups(child, grp, info, i++); + if (ret) { + of_node_put(child); + return ret; + } + } + + return 0; +} + +static int ctc_pinctrl_parse_dt(struct platform_device *pdev, + struct ctc_pinctrl *info) +{ + int ret, i; + u32 bank0_pins, bank1_pins; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *child; + + info->ctrl = devm_kzalloc(dev, sizeof(struct ctc_pin_ctrl), GFP_KERNEL); + if (!info->ctrl) + return -EINVAL; + + ret = of_property_read_u32(np, "ctc,pinctrl-bank0", &bank0_pins); + if (ret < 0) { + dev_err(dev, "failed to get bank0 pin information\n"); + return -EINVAL; + } + ret = of_property_read_u32(np, "ctc,pinctrl-bank1", &bank1_pins); + if (ret < 0) { + dev_err(dev, "failed to get bank1 pin information\n"); + return -EINVAL; + } + info->ctrl->pin_banks = + devm_kzalloc(dev, sizeof(struct ctc_pin_bank) * CTC_PIN_BANK_NUM, + GFP_KERNEL); + if (!info->ctrl->pin_banks) { + dev_err(dev, "failed to allocate memory for pin banks\n"); + return -EINVAL; + } + info->ctrl->nr_banks = CTC_PIN_BANK_NUM; + info->ctrl->nr_pins = bank0_pins + bank1_pins; + info->ctrl->pin_banks[0].pin_base = 0; + info->ctrl->pin_banks[0].nr_pins = bank0_pins; + info->ctrl->pin_banks[1].pin_base = bank0_pins + 1; + info->ctrl->pin_banks[1].nr_pins = bank1_pins; + + ctc_pinctrl_child_count(info, np); + + dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions); + dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups); + + info->functions = devm_kzalloc(dev, info->nfunctions * + sizeof(struct ctc_pmx_func), GFP_KERNEL); + if (!info->functions) + return -EINVAL; + + info->groups = devm_kzalloc(dev, info->ngroups * + sizeof(struct ctc_pin_group), GFP_KERNEL); + if (!info->groups) + return -EINVAL; + + i = 0; + for_each_child_of_node(np, child) { + ret = ctc_pinctrl_parse_functions(child, info, i++); + if (ret) { + dev_err(&pdev->dev, "failed to parse function\n"); + of_node_put(child); + return ret; + } + } + + return 0; +} + +static int ctc_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct ctc_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + return info->ngroups; +} + +static const char *ctc_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct ctc_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + return info->groups[selector].name; +} + +static int ctc_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, const unsigned int **pins, + unsigned int *npins) +{ + struct ctc_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + if (selector >= info->ngroups) + return -EINVAL; + + *pins = info->groups[selector].pins; + *npins = info->groups[selector].npins; + + return 0; +} + +static inline const struct ctc_pin_group *ctc_pinctrl_name_to_group(const struct + ctc_pinctrl + *info, + const char + *name) +{ + int i; + + for (i = 0; i < info->ngroups; i++) { + if (!strcmp(info->groups[i].name, name)) + return &info->groups[i]; + } + + return NULL; +} + +static int ctc_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map, unsigned int *num_maps) +{ + struct ctc_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + const struct ctc_pin_group *grp; + struct pinctrl_map *new_map; + struct device_node *parent; + int map_num; + + /* + * first find the group of this node and check if we need to create + * config maps for pins + */ + grp = ctc_pinctrl_name_to_group(info, np->name); + if (!grp) { + dev_err(info->dev, "unable to find group for node %s\n", + np->name); + return -EINVAL; + } + + map_num = 1; + new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num, + GFP_KERNEL); + if (!new_map) + return -ENOMEM; + + *map = new_map; + *num_maps = map_num; + + /* create mux map */ + parent = of_get_parent(np); + if (!parent) { + devm_kfree(pctldev->dev, new_map); + return -EINVAL; + } + new_map[0].type = PIN_MAP_TYPE_MUX_GROUP; + new_map[0].data.mux.function = parent->name; + new_map[0].data.mux.group = np->name; + of_node_put(parent); + + return 0; +} + +static int ctc_pmx_get_funcs_count(struct pinctrl_dev *pctldev) +{ + struct ctc_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + return info->nfunctions; +} + +static const char *ctc_pmx_get_func_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct ctc_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + return info->functions[selector].name; +} + +static int ctc_pmx_get_groups(struct pinctrl_dev *pctldev, + unsigned int selector, const char *const **groups, + unsigned int *const num_groups) +{ + struct ctc_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + + *groups = info->functions[selector].groups; + *num_groups = info->functions[selector].ngroups; + + return 0; +} + +static struct ctc_pin_bank *ctc_pin_to_bank(struct ctc_pinctrl *info, + unsigned int pin) +{ + struct ctc_pin_bank *b = info->ctrl->pin_banks; + + while (pin >= (b->pin_base + b->nr_pins)) + b++; + + return b; +} + +static int ctc_set_pin_mux(struct ctc_pinctrl *info, struct ctc_pin_bank *bank, + int pin, int mux) +{ + + if (!bank->pin_base) { + regmap_update_bits(info->regmap_base, + offsetof(struct SysCtl_regs, + SysGpioMultiCtl), 3 << pin * 2, + mux << pin * 2); + } else { + regmap_update_bits(info->regmap_base, + offsetof(struct SysCtl_regs, + SysGpioHsMultiCtl), 3 << pin * 2, + mux << pin * 2); + } + return 0; +} + +static int ctc_pmx_set(struct pinctrl_dev *pctldev, unsigned int selector, + unsigned int group) +{ + struct ctc_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + const unsigned int *pins = info->groups[group].pins; + const struct ctc_pin_config *data = info->groups[group].data; + struct ctc_pin_bank *bank; + int cnt, ret = 0; + + dev_dbg(info->dev, "enable function %s group %s\n", + info->functions[selector].name, info->groups[group].name); + + /* for each pin in the pin group selected, program the corresponding pin + * pin function number in the config register. + */ + for (cnt = 0; cnt < info->groups[group].npins; cnt++) { + bank = ctc_pin_to_bank(info, pins[cnt]); + ret = ctc_set_pin_mux(info, bank, pins[cnt] - bank->pin_base, + data[cnt].func); + if (ret) + break; + } + + return 0; +} + +static void ctc_dt_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, unsigned int num_maps) +{ +} + +static const struct pinctrl_ops ctc_pctrl_ops = { + .get_groups_count = ctc_get_groups_count, + .get_group_name = ctc_get_group_name, + .get_group_pins = ctc_get_group_pins, + .dt_node_to_map = ctc_dt_node_to_map, + .dt_free_map = ctc_dt_free_map, +}; + +static const struct pinmux_ops ctc_pmx_ops = { + .get_functions_count = ctc_pmx_get_funcs_count, + .get_function_name = ctc_pmx_get_func_name, + .get_function_groups = ctc_pmx_get_groups, + .set_mux = ctc_pmx_set, +}; + +static int ctc_pinctrl_register(struct platform_device *pdev, + struct ctc_pinctrl *info) +{ + struct pinctrl_desc *ctrldesc = &info->pctl; + struct pinctrl_pin_desc *pindesc, *pdesc; + struct ctc_pin_bank *pin_bank; + int pin, bank, ret; + int k; + + ret = ctc_pinctrl_parse_dt(pdev, info); + if (ret) + return ret; + + ctrldesc->name = "ctc-pinctrl"; + ctrldesc->owner = THIS_MODULE; + ctrldesc->pctlops = &ctc_pctrl_ops; + ctrldesc->pmxops = &ctc_pmx_ops; + ctrldesc->confops = NULL; + + pindesc = + devm_kzalloc(&pdev->dev, sizeof(*pindesc) * info->ctrl->nr_pins, + GFP_KERNEL); + if (!pindesc) { + dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n"); + return -ENOMEM; + } + ctrldesc->pins = pindesc; + ctrldesc->npins = info->ctrl->nr_pins; + + pdesc = pindesc; + for (bank = 0, k = 0; bank < info->ctrl->nr_banks; bank++) { + pin_bank = &info->ctrl->pin_banks[bank]; + for (pin = 0; pin < pin_bank->nr_pins; pin++, k++) { + pdesc->number = k; + pdesc->name = kasprintf(GFP_KERNEL, "gpio%d-%d", + bank, pin); + pdesc++; + } + } + + info->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, info); + if (IS_ERR(info->pctl_dev)) { + dev_err(&pdev->dev, "could not register pinctrl driver\n"); + return PTR_ERR(info->pctl_dev); + } + + return 0; +} + +static int ctc_pinctrl_probe(struct platform_device *pdev) +{ + struct ctc_pinctrl *info; + struct device *dev = &pdev->dev; + + info = devm_kzalloc(dev, sizeof(struct ctc_pinctrl), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->dev = dev; + info->regmap_base = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "ctc,sysctrl"); + if (IS_ERR(info->regmap_base)) + return PTR_ERR(info->regmap_base); + + ctc_pinctrl_register(pdev, info); + + platform_set_drvdata(pdev, info); + + return 0; +} + +static const struct of_device_id ctc_pinctrl_dt_match[] = { + {.compatible = "ctc,ctc5236-pinctrl"}, + {}, +}; + +static struct platform_driver ctc_pinctrl_driver = { + .probe = ctc_pinctrl_probe, + .driver = { + .name = "ctc-pinctrl", + .of_match_table = ctc_pinctrl_dt_match, + }, +}; + +//static int __init ctc_pinctrl_drv_register(void) +//{ +// return platform_driver_register(&ctc_pinctrl_driver); +//} +// +//postcore_initcall(ctc_pinctrl_drv_register); + +module_platform_driver(ctc_pinctrl_driver); +MODULE_LICENSE("GPL"); diff --git a/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/pinctrl-ctc.h b/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/pinctrl-ctc.h new file mode 100644 index 000000000000..91188a84d9df --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/pinctrl-ctc/pinctrl-ctc.h @@ -0,0 +1,24 @@ +/* + * Header providing constants for centec pinctrl. + * + * Copyright (c) 2018 Liuht + * + * 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. + */ + +#ifndef __PINCTRL_CTC_H__ +#define __PINCTRL_CTC_H__ + +#define PIN_FUNC_SPI 1 +#define PIN_FUNC_PWM 2 +#define PIN_FUNC_UART 1 +#define PIN_FUNC_FC 1 +#endif diff --git a/platform/centec-arm64/tsingma-bsp/src/pwm-ctc/Makefile b/platform/centec-arm64/tsingma-bsp/src/pwm-ctc/Makefile new file mode 100644 index 000000000000..4d187265224f --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/pwm-ctc/Makefile @@ -0,0 +1 @@ +obj-m = pwm-ctc.o diff --git a/platform/centec-arm64/tsingma-bsp/src/pwm-ctc/pwm-ctc.c b/platform/centec-arm64/tsingma-bsp/src/pwm-ctc/pwm-ctc.c new file mode 100644 index 000000000000..8b2a031a46fa --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/pwm-ctc/pwm-ctc.c @@ -0,0 +1,247 @@ +/* Centec PWM driver + * + * Author: wangyb + * + * Copyright 2005-2018, Centec Networks (Suzhou) Co., Ltd. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../pinctrl-ctc/pinctrl-ctc.h" +#include "../pinctrl-ctc/core.h" +#include "../include/sysctl.h" +#include +#include +#include + +#define CTC_NUM_PWM 4 +#define CTC_CR_PWM 0x0 +#define CTC_DUTY_PWM 0x4 + +#define CTC_MAX_PERIOD_PWM 0xFFFFFF +#define CTC_MAX_DUTY_PWM 0xFFFFFF + +#define CTC_PWM_ENABLE 0x80000000 + +#define CTC_PERIOD_TACH 0x0 +#define CTC_DUTY_TACH 0x4 + +struct ctc_pwm_chip { + void __iomem *base; + struct regmap *regmap_base; + struct pwm_chip chip; +}; + +static inline struct ctc_pwm_chip *to_ctc_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct ctc_pwm_chip, chip); +} + +static inline void ctc_pwm_writel(struct ctc_pwm_chip *chip, unsigned int num, + unsigned long offset, unsigned long val) +{ + regmap_write(chip->regmap_base, + offsetof(struct SysCtl_regs, + SysPwmCtl) + offset + num * 0x8, val); +} + +static inline u32 ctc_pwm_readl(struct ctc_pwm_chip *chip, unsigned int num, + unsigned long offset) +{ + u32 val; + + regmap_read(chip->regmap_base, + offsetof(struct SysCtl_regs, + SysPwmCtl) + offset + num * 0x8, &val); + return val; +} + +static inline u32 ctc_tach_readl(struct ctc_pwm_chip *chip, unsigned int num, + unsigned long offset) +{ + u32 val; + + regmap_read(chip->regmap_base, + offsetof(struct SysCtl_regs, + SysTachLog) + offset + num * 0x8, &val); + return val; +} + +static int ctc_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct ctc_pwm_chip *pc = to_ctc_pwm_chip(chip); + u32 cur_value; + + duty_ns = duty_ns / 1000; + period_ns = period_ns / 1000; + + /* duty cycle */ + duty_ns = duty_ns & CTC_MAX_DUTY_PWM; + ctc_pwm_writel(pc, pwm->hwpwm, CTC_DUTY_PWM, duty_ns); + + /* period cycle */ + period_ns = period_ns & CTC_MAX_PERIOD_PWM; + cur_value = ctc_pwm_readl(pc, pwm->hwpwm, CTC_CR_PWM); + cur_value &= ~(CTC_MAX_PERIOD_PWM); + cur_value |= period_ns << 0; + ctc_pwm_writel(pc, pwm->hwpwm, CTC_CR_PWM, cur_value); + + return 0; +} + +static int ctc_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct ctc_pwm_chip *pc = to_ctc_pwm_chip(chip); + u32 cur_value; + + cur_value = ctc_pwm_readl(pc, pwm->hwpwm, CTC_CR_PWM); + cur_value |= 1 << 31; + ctc_pwm_writel(pc, pwm->hwpwm, CTC_CR_PWM, cur_value); + return 0; +} + +static void ctc_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct ctc_pwm_chip *pc = to_ctc_pwm_chip(chip); + u32 cur_value; + + cur_value = ctc_pwm_readl(pc, pwm->hwpwm, CTC_CR_PWM); + cur_value &= ~(1 << 31); + + ctc_pwm_writel(pc, pwm->hwpwm, CTC_CR_PWM, cur_value); +} + +static void ctc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct ctc_pwm_chip *pc = to_ctc_pwm_chip(chip); + u32 cur_value; + u32 cur_value_2; + + cur_value = ctc_pwm_readl(pc, pwm->hwpwm, CTC_CR_PWM); + + if (cur_value & CTC_PWM_ENABLE) + state->enabled = true; + else + state->enabled = false; + + state->polarity = PWM_POLARITY_NORMAL; + + state->period = (cur_value & (~CTC_PWM_ENABLE)) * 1000; + + cur_value_2 = ctc_pwm_readl(pc, pwm->hwpwm, CTC_DUTY_PWM); + + state->duty_cycle = cur_value_2 * 1000; +} + +static int ctc_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_capture *result, unsigned long timeout) +{ + struct ctc_pwm_chip *pc = to_ctc_pwm_chip(chip); + u32 period_tach; + u32 duty_tach; + + period_tach = ctc_tach_readl(pc, pwm->hwpwm, CTC_PERIOD_TACH) / 4; + result->period = period_tach * 1000; + + duty_tach = ctc_tach_readl(pc, pwm->hwpwm, CTC_DUTY_TACH) / 4; + result->duty_cycle = duty_tach * 1000; + + return 0; +} + +static const struct pwm_ops ctc_pwm_ops = { + .config = ctc_pwm_config, + .enable = ctc_pwm_enable, + .disable = ctc_pwm_disable, + .get_state = ctc_pwm_get_state, + .capture = ctc_pwm_capture, + .owner = THIS_MODULE, +}; + +static int ctc_pwm_probe(struct platform_device *pdev) +{ + struct pinctrl_dev *pctldev; + struct ctc_pwm_chip *pc; + struct pinctrl_state *state; + + int ret; + int i; + u32 cur_value; + + pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); + if (!pc) + return -ENOMEM; + + pc->regmap_base = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "ctc,sysctrl"); + pctldev = devm_kzalloc(&pdev->dev, sizeof(*pctldev), GFP_KERNEL); + if (!pctldev) + return -1; + pctldev->p = pinctrl_get(&pdev->dev); + state = pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT); + pinctrl_select_state(pctldev->p, state); + pr_info("Select PWM Function\n"); + + for (i = 0; i < CTC_NUM_PWM; i++) { + cur_value = ctc_pwm_readl(pc, i, CTC_CR_PWM); + cur_value |= 1 << 31; + ctc_pwm_writel(pc, i, CTC_CR_PWM, cur_value); + } + + platform_set_drvdata(pdev, pc); + pc->chip.dev = &pdev->dev; + pc->chip.ops = &ctc_pwm_ops; + pc->chip.base = -1; + pc->chip.npwm = CTC_NUM_PWM; + + ret = pwmchip_add(&pc->chip); + if (ret < 0) + return -1; + + return 0; +} + +static int ctc_pwm_remove(struct platform_device *pdev) +{ + struct ctc_pwm_chip *pc = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < CTC_NUM_PWM; i++) + pwm_disable(&pc->chip.pwms[i]); + + return pwmchip_remove(&pc->chip); +} + +static const struct of_device_id ctc_pwm_of_match[] = { + {.compatible = "centec-pwm"}, + {} +}; + +MODULE_DEVICE_TABLE(of, ctc_pwm_of_match); + +static struct platform_driver ctc_pwm_driver = { + .driver = { + .name = "ctc-pwm", + .of_match_table = ctc_pwm_of_match, + }, + .probe = ctc_pwm_probe, + .remove = ctc_pwm_remove, +}; + +module_platform_driver(ctc_pwm_driver); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:centec-pwm"); diff --git a/platform/centec-arm64/tsingma-bsp/src/rtc-sd2405/Makefile b/platform/centec-arm64/tsingma-bsp/src/rtc-sd2405/Makefile new file mode 100644 index 000000000000..7e34f8c9367f --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/rtc-sd2405/Makefile @@ -0,0 +1 @@ +obj-m = rtc-sd2405.o diff --git a/platform/centec-arm64/tsingma-bsp/src/rtc-sd2405/rtc-sd2405.c b/platform/centec-arm64/tsingma-bsp/src/rtc-sd2405/rtc-sd2405.c new file mode 100644 index 000000000000..77c76353cd60 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/rtc-sd2405/rtc-sd2405.c @@ -0,0 +1,249 @@ +/* rtc class driver for the SD2405 chip + * + * Author: Dale Farnsworth + * + * based on previously existing rtc class drivers + * + * 2007 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include + +#define DRV_VERSION "0.1" + +/* + * register indices + */ +#define SD2405_REG_SC 0x0 /* seconds 00-59 */ +#define SD2405_REG_MN 0x1 /* minutes 00-59 */ +#define SD2405_REG_HR 0x2 /* hours 00-23 */ +#define SD2405_REG_DW 0x3 /* day of week 1-7 */ +#define SD2405_REG_DT 0x4 /* day of month 00-31 */ +#define SD2405_REG_MO 0x5 /* month 01-12 */ +#define SD2405_REG_YR 0x6 /* year 00-99 */ + +#define SD2405_REG_CTRL1 0xf /* control 1 */ +#define SD2405_REG_CTRL2 0x10 /* control 2 */ +#define SD2405_REG_CTRL3 0x11 /* control 3 ARST */ + +#define SD2405_REG_LEN 7 + +/* + * register write protect + */ +#define SD2405_REG_CONTROL1_WRITE 0x80 +#define SD2405_REG_CONTROL2_WRITE 0x84 + +#define SD2405_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ + +static struct i2c_driver sd2405_driver; + +static int sd2405_i2c_read_regs(struct i2c_client *client, u8 *buf) +{ + struct i2c_msg msgs[1] = { + { + .addr = client->addr, + .flags = I2C_M_RD, /* read */ + .len = SD2405_REG_LEN, + .buf = buf} + }; + int rc; + + rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (rc != ARRAY_SIZE(msgs)) { + dev_err(&client->dev, "%s: register read failed\n", __func__); + return -EIO; + } + return 0; +} + +static int sd2405_i2c_write_regs(struct i2c_client *client, u8 const *buf) +{ + int rc; + u8 temp_reg[SD2405_REG_LEN + 1] = { 0 }; + + struct i2c_msg msgs[1] = { + { + .addr = client->addr, + .flags = 0, /* write */ + .len = SD2405_REG_LEN + 1, + .buf = temp_reg} + }; + + memcpy(&temp_reg[1], buf, SD2405_REG_LEN); + + rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (rc != ARRAY_SIZE(msgs)) + goto write_failed; + msleep(SD2405_IDLE_TIME_AFTER_WRITE); + + return 0; + +write_failed: + dev_err(&client->dev, "%s: register write failed\n", __func__); + return -EIO; +} + +static int sd2405_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) +{ + int rc; + u8 regs[SD2405_REG_LEN]; + + rc = sd2405_i2c_read_regs(client, regs); + if (rc < 0) + return rc; + + tm->tm_sec = bcd2bin(regs[SD2405_REG_SC]); + tm->tm_min = bcd2bin(regs[SD2405_REG_MN]); + tm->tm_hour = bcd2bin(regs[SD2405_REG_HR] & 0x3f); + tm->tm_wday = bcd2bin(regs[SD2405_REG_DW]); + tm->tm_mday = bcd2bin(regs[SD2405_REG_DT]); + tm->tm_mon = bcd2bin(regs[SD2405_REG_MO]) - 1; + tm->tm_year = bcd2bin(regs[SD2405_REG_YR]) + 100; + + return 0; +} + +static int sd2405_i2c_set_write_protect(struct i2c_client *client) +{ + int rc; + + rc = i2c_smbus_write_byte_data(client, SD2405_REG_CTRL1, 0); + rc += i2c_smbus_write_byte_data(client, SD2405_REG_CTRL2, 0); + if (rc < 0) { + dev_err(&client->dev, "%s: control register write failed\n", + __func__); + return -EIO; + } + return 0; +} + +static int sd2405_i2c_clear_write_protect(struct i2c_client *client) +{ + int rc; + + rc = i2c_smbus_write_byte_data(client, SD2405_REG_CTRL2, + SD2405_REG_CONTROL1_WRITE); + rc += + i2c_smbus_write_byte_data(client, SD2405_REG_CTRL1, + SD2405_REG_CONTROL2_WRITE); + if (rc < 0) { + dev_err(&client->dev, "%s: control register write failed\n", + __func__); + return -EIO; + } + return 0; +} + +static int +sd2405_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) +{ + u8 regs[SD2405_REG_LEN]; + int rc; + + rc = sd2405_i2c_clear_write_protect(client); + if (rc < 0) + return rc; + + regs[SD2405_REG_SC] = bin2bcd(tm->tm_sec); + regs[SD2405_REG_MN] = bin2bcd(tm->tm_min); + regs[SD2405_REG_HR] = bin2bcd(tm->tm_hour) | 0x80; + regs[SD2405_REG_DW] = bin2bcd(tm->tm_wday); + regs[SD2405_REG_DT] = bin2bcd(tm->tm_mday); + regs[SD2405_REG_MO] = bin2bcd(tm->tm_mon + 1); + regs[SD2405_REG_YR] = bin2bcd(tm->tm_year - 100); + + rc = sd2405_i2c_write_regs(client, regs); + if (rc < 0) + return rc; + + rc = sd2405_i2c_set_write_protect(client); + if (rc < 0) + return rc; + + return 0; +} + +static int sd2405_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + return sd2405_i2c_read_time(to_i2c_client(dev), tm); +} + +static int sd2405_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return sd2405_i2c_set_time(to_i2c_client(dev), tm); +} + +static int sd2405_remove(struct i2c_client *client) +{ + struct rtc_device *rtc = i2c_get_clientdata(client); + + if (rtc) + rtc_device_unregister(rtc); + + return 0; +} + +static const struct rtc_class_ops sd2405_rtc_ops = { + .read_time = sd2405_rtc_read_time, + .set_time = sd2405_rtc_set_time, +}; + +static int +sd2405_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct rtc_device *rtc; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); + + rtc = rtc_device_register(sd2405_driver.driver.name, + &client->dev, &sd2405_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + i2c_set_clientdata(client, rtc); + + return 0; +} + +static struct i2c_device_id sd2405_id[] = { + {"sd2405", 0}, + {} +}; + +static struct i2c_driver sd2405_driver = { + .driver = { + .name = "rtc-sd2405", + }, + .probe = sd2405_probe, + .remove = sd2405_remove, + .id_table = sd2405_id, +}; + +static int __init sd2405_init(void) +{ + return i2c_add_driver(&sd2405_driver); +} + +static void __exit sd2405_exit(void) +{ + i2c_del_driver(&sd2405_driver); +} + +MODULE_DESCRIPTION("Maxim SD2405 RTC driver"); +MODULE_AUTHOR("Dale Farnsworth "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(sd2405_init); +module_exit(sd2405_exit); diff --git a/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/Makefile b/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/Makefile new file mode 100644 index 000000000000..82c8485d0ee9 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/Makefile @@ -0,0 +1 @@ +obj-m = sdhci-ctc5236.o diff --git a/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/sdhci-ctc5236.c b/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/sdhci-ctc5236.c new file mode 100644 index 000000000000..b9981e8b0c54 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/sdhci-ctc5236.c @@ -0,0 +1,307 @@ +/* sdhci-ctc5236.c Support for SDHCI on Centec TsingMa SoC's + * + * Copyright (C) 2004-2017 Centec Networks (suzhou) Co., LTD. + * + * Author: Jay Cao + * + * 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 +#include "sdhci-pltfm.h" +#include "../pinctrl-ctc/pinctrl-ctc.h" +#include "../include/sysctl.h" +#include +#include +#include +#include +#include + +#define REG_OFFSET_ADDR 0x500 +#define MSHC_CTRL_R 0x8 +#define AT_CTRL_R 0x40 +#define SW_TUNE_EN 0x10 +#define SD_CLK_EN_MASK 0x00000001 +#define AT_STAT_R 0x44 +#define MAX_TUNING_LOOP 0x80 +#define MIN_TUNING_LOOP 0x0 +#define TUNE_CTRL_STEP 1 + +struct regmap *regmap_base; +#define SDHCI_REFCLK_150M 150000000 + +static u16 sdhci_ctc5236_readw(struct sdhci_host *host, int reg) +{ + if (unlikely(reg == SDHCI_HOST_VERSION)) + return SDHCI_SPEC_300; + + return readw(host->ioaddr + reg); +} + +static u32 sdhci_ctc5236_readl(struct sdhci_host *host, int reg) +{ + u32 ret = readl(host->ioaddr + reg); + + if (reg == SDHCI_CAPABILITIES_1) + ret &= + ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | + SDHCI_SUPPORT_DDR50); + if (reg == SDHCI_CAPABILITIES) + ret &= ~(SDHCI_CAN_64BIT); + + return ret; +} + +static void ctc5236_mmc_init_card(struct sdhci_host *host) +{ + int CLK_CTRL_R_value = 0x0; + int AT_CTRL_R_value = 0x0; + int MSHC_CTRL_R_value = 0x0; + + /* Disable command conflict check for 150M */ + sdhci_writel(host, MSHC_CTRL_R_value, REG_OFFSET_ADDR + MSHC_CTRL_R); + dev_dbg(mmc_dev(host->mmc), "MSHC_CTRL_R is %x\n", + sdhci_readl(host, REG_OFFSET_ADDR + MSHC_CTRL_R)); + + /* Disable auto-tuning function */ + CLK_CTRL_R_value = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + CLK_CTRL_R_value &= (~SDHCI_CLOCK_CARD_EN); + sdhci_writew(host, CLK_CTRL_R_value, SDHCI_CLOCK_CONTROL); + AT_CTRL_R_value = sdhci_readl(host, REG_OFFSET_ADDR + AT_CTRL_R); + AT_CTRL_R_value &= (~SD_CLK_EN_MASK); + sdhci_writel(host, AT_CTRL_R_value, REG_OFFSET_ADDR + AT_CTRL_R); + dev_dbg(mmc_dev(host->mmc), "AT_CTRL_R is %x\n", + sdhci_readl(host, REG_OFFSET_ADDR + AT_CTRL_R)); +} + +void sdhci_ctc5236_reset(struct sdhci_host *host, u8 mask) +{ + unsigned long timeout; + + sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); + + /* Wait max 100 ms */ + timeout = 100; + + /* hw clears the bit when it's done */ + while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { + if (timeout == 0) { + pr_err("%s: Reset 0x%x never completed.\n", + mmc_hostname(host->mmc), (int)mask); + return; + } + timeout--; + mdelay(1); + } + + if (mask & SDHCI_RESET_ALL) { + host->clock = 0; + ctc5236_mmc_init_card(host); + } + +} + +void ctc_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) +{ + int val = 0; + + if (clock == SDHCI_REFCLK_150M) { + /* SDHCI reference clock change 150M */ + regmap_read(regmap_base, + offsetof(struct SysCtl_regs, SysClkPeriCfg), &val); + val = val & (~SYS_CLK_PERI_CFG_W0_CFG_DIV_MSH_REF_CNT_MASK); + val |= + ((0x8 & SYS_CLK_PERI_CFG_W0_CFG_DIV_MSH_REF_CNT_MASK)) << 0; + regmap_write(regmap_base, + offsetof(struct SysCtl_regs, SysClkPeriCfg), val); + } + + sdhci_set_clock(host, clock); +} + +static int sdhci_ctc5236_prepare_tuning(struct sdhci_host *host, + int CENTER_PH_CODE) +{ + int CLK_CTRL_R_value = 0x0; + int HOST_CTRL2_R_value = 0x0; + int AT_CTRL_R_value = 0x0; + + /* Turn-off Sampling Clock */ + CLK_CTRL_R_value = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + CLK_CTRL_R_value &= (~SDHCI_CLOCK_CARD_EN); + sdhci_writew(host, CLK_CTRL_R_value, SDHCI_CLOCK_CONTROL); + + /* Reset Tuning Engine */ + HOST_CTRL2_R_value = sdhci_readw(host, SDHCI_HOST_CONTROL2); + HOST_CTRL2_R_value &= (~SDHCI_CTRL_TUNED_CLK); + sdhci_writew(host, HOST_CTRL2_R_value, SDHCI_HOST_CONTROL2); + + /* Set up registers for CMD21 operation */ + if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) + sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128), SDHCI_BLOCK_SIZE); + else if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) + sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE); + + sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); + + /* Enable Software tuning */ + AT_CTRL_R_value = sdhci_readl(host, REG_OFFSET_ADDR + AT_CTRL_R); + AT_CTRL_R_value |= SW_TUNE_EN; + sdhci_writel(host, AT_CTRL_R_value, REG_OFFSET_ADDR + AT_CTRL_R); + + /* Set tuning_cclk_sel to 0 */ + sdhci_writel(host, CENTER_PH_CODE, REG_OFFSET_ADDR + AT_STAT_R); + + /* Turn-on Sampling Clock */ + CLK_CTRL_R_value |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, CLK_CTRL_R_value, SDHCI_CLOCK_CONTROL); + + return 0; +} + +static int sdhci_ctc5236_execute_tuning(struct sdhci_host *host, u32 opcode) +{ + int min, max, avg, ret; + int val = 0; + + /* Disable Rx bypass when tuning */ + regmap_read(regmap_base, offsetof(struct SysCtl_regs, SysMshCfg), &val); + val &= (~SYS_MSH_CFG_W0_MSH_INTF_RX_DLL_MASTER_BYPASS_MASK); + regmap_write(regmap_base, offsetof(struct SysCtl_regs, SysMshCfg), val); + + /* find the mininum delay first which can pass tuning */ + min = MIN_TUNING_LOOP; + sdhci_ctc5236_prepare_tuning(host, min); + while (min < MAX_TUNING_LOOP) { + dev_dbg(mmc_dev(host->mmc), "#1# AT_STAT_R is %x\n", + sdhci_readl(host, REG_OFFSET_ADDR + AT_STAT_R)); + if (!mmc_send_tuning(host->mmc, opcode, NULL)) + break; + + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + + min += TUNE_CTRL_STEP; + sdhci_writel(host, min, REG_OFFSET_ADDR + AT_STAT_R); + } + + /* find the maxinum delay which can not pass tuning */ + max = min + TUNE_CTRL_STEP; + sdhci_ctc5236_prepare_tuning(host, max); + while (max < MAX_TUNING_LOOP) { + dev_dbg(mmc_dev(host->mmc), "#2# AT_STAT_R is %x\n", + sdhci_readl(host, REG_OFFSET_ADDR + AT_STAT_R)); + if (mmc_send_tuning(host->mmc, opcode, NULL)) { + max -= TUNE_CTRL_STEP; + break; + } + + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + + max += TUNE_CTRL_STEP; + sdhci_writel(host, max, REG_OFFSET_ADDR + AT_STAT_R); + } + + /* use average delay to get the best timing */ + avg = (min + max) / 2; + sdhci_ctc5236_prepare_tuning(host, avg); + ret = mmc_send_tuning(host->mmc, opcode, NULL); + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + sdhci_writel(host, avg, REG_OFFSET_ADDR + AT_STAT_R); + + dev_info(mmc_dev(host->mmc), "Tuning %s at 0x%x ret %d\n", + ret ? "failed" : "passed", avg, ret); + + return ret; +} + +static const struct sdhci_ops sdhci_ctc5236_ops = { + .read_w = sdhci_ctc5236_readw, + .read_l = sdhci_ctc5236_readl, + .set_clock = ctc_sdhci_set_clock, + .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_ctc5236_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, + .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .platform_execute_tuning = sdhci_ctc5236_execute_tuning, +}; + +static struct sdhci_pltfm_data sdhci_ctc5236_pdata = { + .ops = &sdhci_ctc5236_ops, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | SDHCI_QUIRK2_BROKEN_HS200, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | SDHCI_QUIRK_BROKEN_ADMA, +}; + +static int sdhci_ctc5236_probe(struct platform_device *pdev) +{ + struct sdhci_host *host; + struct sdhci_pltfm_host *pltfm_host; + struct clk *clk; + int ret; + + host = sdhci_pltfm_init(pdev, &sdhci_ctc5236_pdata, 0); + if (IS_ERR(host)) + return PTR_ERR(host); + + clk = devm_clk_get(&pdev->dev, "mmc_clk"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "Peripheral clk not found\n"); + return PTR_ERR(clk); + } + pltfm_host = sdhci_priv(host); + pltfm_host->clk = clk; + clk_prepare_enable(clk); + + regmap_base = + syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "ctc,sysctrl"); + if (IS_ERR(regmap_base)) + return PTR_ERR(regmap_base); + + mmc_of_parse_voltage(pdev->dev.of_node, &host->ocr_mask); + + ret = mmc_of_parse(host->mmc); + if (ret) + goto err_sdhci_add; + + ret = sdhci_add_host(host); + if (ret) + goto err_sdhci_add; + return 0; + +err_sdhci_add: + sdhci_pltfm_free(pdev); + return ret; +} + +static const struct of_device_id sdhci_ctc5236_of_match[] = { + {.compatible = "centec,ctc5236-sdhci"}, + {}, +}; + +MODULE_DEVICE_TABLE(of, sdhci_ctc5236_of_match); + +static struct platform_driver sdhci_ctc5236_driver = { + .driver = { + .name = "sdhci-ctc5236", + .pm = &sdhci_pltfm_pmops, + .of_match_table = of_match_ptr(sdhci_ctc5236_of_match), + }, + .probe = sdhci_ctc5236_probe, + .remove = sdhci_pltfm_unregister, +}; + +module_platform_driver(sdhci_ctc5236_driver); + +MODULE_DESCRIPTION("SDHCI driver for Centec TsingMa SoCs"); +MODULE_AUTHOR("Jay Cao "); +MODULE_LICENSE("GPL v2"); diff --git a/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/sdhci-pltfm.h b/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/sdhci-pltfm.h new file mode 100644 index 000000000000..1e91fb1c020e --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/sdhci-pltfm.h @@ -0,0 +1,116 @@ +/* + * Copyright 2010 MontaVista Software, LLC. + * + * Author: Anton Vorontsov + * + * 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. + */ + +#ifndef _DRIVERS_MMC_SDHCI_PLTFM_H +#define _DRIVERS_MMC_SDHCI_PLTFM_H + +#include +#include +#include "sdhci.h" + +struct sdhci_pltfm_data { + const struct sdhci_ops *ops; + unsigned int quirks; + unsigned int quirks2; +}; + +struct sdhci_pltfm_host { + struct clk *clk; + + /* migrate from sdhci_of_host */ + unsigned int clock; + u16 xfer_mode_shadow; + + unsigned long private[0] ____cacheline_aligned; +}; + +#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER +/* + * These accessors are designed for big endian hosts doing I/O to + * little endian controllers incorporating a 32-bit hardware byte swapper. + */ +static inline u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg) +{ + return in_be32(host->ioaddr + reg); +} + +static inline u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg) +{ + return in_be16(host->ioaddr + (reg ^ 0x2)); +} + +static inline u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg) +{ + return in_8(host->ioaddr + (reg ^ 0x3)); +} + +static inline void sdhci_be32bs_writel(struct sdhci_host *host, + u32 val, int reg) +{ + out_be32(host->ioaddr + reg, val); +} + +static inline void sdhci_be32bs_writew(struct sdhci_host *host, + u16 val, int reg) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + int base = reg & ~0x3; + int shift = (reg & 0x2) * 8; + + switch (reg) { + case SDHCI_TRANSFER_MODE: + /* + * Postpone this write, we must do it together with a + * command write that is down below. + */ + pltfm_host->xfer_mode_shadow = val; + return; + case SDHCI_COMMAND: + sdhci_be32bs_writel(host, + val << 16 | pltfm_host->xfer_mode_shadow, + SDHCI_TRANSFER_MODE); + return; + } + clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift); +} + +static inline void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg) +{ + int base = reg & ~0x3; + int shift = (reg & 0x3) * 8; + + clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift); +} +#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */ + +extern void sdhci_get_of_property(struct platform_device *pdev); + +extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, + const struct sdhci_pltfm_data *pdata, + size_t priv_size); +extern void sdhci_pltfm_free(struct platform_device *pdev); + +extern int sdhci_pltfm_register(struct platform_device *pdev, + const struct sdhci_pltfm_data *pdata, + size_t priv_size); +extern int sdhci_pltfm_unregister(struct platform_device *pdev); + +extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); + +static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host) +{ + return host->private; +} + +int sdhci_pltfm_suspend(struct device *dev); +int sdhci_pltfm_resume(struct device *dev); +extern const struct dev_pm_ops sdhci_pltfm_pmops; + +#endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */ diff --git a/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/sdhci.h b/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/sdhci.h new file mode 100644 index 000000000000..0f8c4f3ccafc --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/sdhci-ctc5236/sdhci.h @@ -0,0 +1,761 @@ +/* + * linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver + * + * Header file for Host Controller registers and I/O accessors. + * + * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. + * + * 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. + */ +#ifndef __SDHCI_HW_H +#define __SDHCI_HW_H + +#include +#include +#include +#include +#include +#include + +#include + +/* + * Controller registers + */ + +#define SDHCI_DMA_ADDRESS 0x00 +#define SDHCI_ARGUMENT2 SDHCI_DMA_ADDRESS + +#define SDHCI_BLOCK_SIZE 0x04 +#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF)) + +#define SDHCI_BLOCK_COUNT 0x06 + +#define SDHCI_ARGUMENT 0x08 + +#define SDHCI_TRANSFER_MODE 0x0C +#define SDHCI_TRNS_DMA 0x01 +#define SDHCI_TRNS_BLK_CNT_EN 0x02 +#define SDHCI_TRNS_AUTO_CMD12 0x04 +#define SDHCI_TRNS_AUTO_CMD23 0x08 +#define SDHCI_TRNS_READ 0x10 +#define SDHCI_TRNS_MULTI 0x20 + +#define SDHCI_COMMAND 0x0E +#define SDHCI_CMD_RESP_MASK 0x03 +#define SDHCI_CMD_CRC 0x08 +#define SDHCI_CMD_INDEX 0x10 +#define SDHCI_CMD_DATA 0x20 +#define SDHCI_CMD_ABORTCMD 0xC0 + +#define SDHCI_CMD_RESP_NONE 0x00 +#define SDHCI_CMD_RESP_LONG 0x01 +#define SDHCI_CMD_RESP_SHORT 0x02 +#define SDHCI_CMD_RESP_SHORT_BUSY 0x03 + +#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff)) +#define SDHCI_GET_CMD(c) ((c>>8) & 0x3f) + +#define SDHCI_RESPONSE 0x10 + +#define SDHCI_BUFFER 0x20 + +#define SDHCI_PRESENT_STATE 0x24 +#define SDHCI_CMD_INHIBIT 0x00000001 +#define SDHCI_DATA_INHIBIT 0x00000002 +#define SDHCI_DOING_WRITE 0x00000100 +#define SDHCI_DOING_READ 0x00000200 +#define SDHCI_SPACE_AVAILABLE 0x00000400 +#define SDHCI_DATA_AVAILABLE 0x00000800 +#define SDHCI_CARD_PRESENT 0x00010000 +#define SDHCI_WRITE_PROTECT 0x00080000 +#define SDHCI_DATA_LVL_MASK 0x00F00000 +#define SDHCI_DATA_LVL_SHIFT 20 +#define SDHCI_DATA_0_LVL_MASK 0x00100000 +#define SDHCI_CMD_LVL 0x01000000 + +#define SDHCI_HOST_CONTROL 0x28 +#define SDHCI_CTRL_LED 0x01 +#define SDHCI_CTRL_4BITBUS 0x02 +#define SDHCI_CTRL_HISPD 0x04 +#define SDHCI_CTRL_DMA_MASK 0x18 +#define SDHCI_CTRL_SDMA 0x00 +#define SDHCI_CTRL_ADMA1 0x08 +#define SDHCI_CTRL_ADMA32 0x10 +#define SDHCI_CTRL_ADMA64 0x18 +#define SDHCI_CTRL_8BITBUS 0x20 +#define SDHCI_CTRL_CDTEST_INS 0x40 +#define SDHCI_CTRL_CDTEST_EN 0x80 + +#define SDHCI_POWER_CONTROL 0x29 +#define SDHCI_POWER_ON 0x01 +#define SDHCI_POWER_180 0x0A +#define SDHCI_POWER_300 0x0C +#define SDHCI_POWER_330 0x0E + +#define SDHCI_BLOCK_GAP_CONTROL 0x2A + +#define SDHCI_WAKE_UP_CONTROL 0x2B +#define SDHCI_WAKE_ON_INT 0x01 +#define SDHCI_WAKE_ON_INSERT 0x02 +#define SDHCI_WAKE_ON_REMOVE 0x04 + +#define SDHCI_CLOCK_CONTROL 0x2C +#define SDHCI_DIVIDER_SHIFT 8 +#define SDHCI_DIVIDER_HI_SHIFT 6 +#define SDHCI_DIV_MASK 0xFF +#define SDHCI_DIV_MASK_LEN 8 +#define SDHCI_DIV_HI_MASK 0x300 +#define SDHCI_PROG_CLOCK_MODE 0x0020 +#define SDHCI_CLOCK_CARD_EN 0x0004 +#define SDHCI_CLOCK_INT_STABLE 0x0002 +#define SDHCI_CLOCK_INT_EN 0x0001 + +#define SDHCI_TIMEOUT_CONTROL 0x2E + +#define SDHCI_SOFTWARE_RESET 0x2F +#define SDHCI_RESET_ALL 0x01 +#define SDHCI_RESET_CMD 0x02 +#define SDHCI_RESET_DATA 0x04 + +#define SDHCI_INT_STATUS 0x30 +#define SDHCI_INT_ENABLE 0x34 +#define SDHCI_SIGNAL_ENABLE 0x38 +#define SDHCI_INT_RESPONSE 0x00000001 +#define SDHCI_INT_DATA_END 0x00000002 +#define SDHCI_INT_BLK_GAP 0x00000004 +#define SDHCI_INT_DMA_END 0x00000008 +#define SDHCI_INT_SPACE_AVAIL 0x00000010 +#define SDHCI_INT_DATA_AVAIL 0x00000020 +#define SDHCI_INT_CARD_INSERT 0x00000040 +#define SDHCI_INT_CARD_REMOVE 0x00000080 +#define SDHCI_INT_CARD_INT 0x00000100 +#define SDHCI_INT_RETUNE 0x00001000 +#define SDHCI_INT_CQE 0x00004000 +#define SDHCI_INT_ERROR 0x00008000 +#define SDHCI_INT_TIMEOUT 0x00010000 +#define SDHCI_INT_CRC 0x00020000 +#define SDHCI_INT_END_BIT 0x00040000 +#define SDHCI_INT_INDEX 0x00080000 +#define SDHCI_INT_DATA_TIMEOUT 0x00100000 +#define SDHCI_INT_DATA_CRC 0x00200000 +#define SDHCI_INT_DATA_END_BIT 0x00400000 +#define SDHCI_INT_BUS_POWER 0x00800000 +#define SDHCI_INT_AUTO_CMD_ERR 0x01000000 +#define SDHCI_INT_ADMA_ERROR 0x02000000 + +#define SDHCI_INT_NORMAL_MASK 0x00007FFF +#define SDHCI_INT_ERROR_MASK 0xFFFF8000 + +#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ + SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | \ + SDHCI_INT_AUTO_CMD_ERR) +#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ + SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ + SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ + SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \ + SDHCI_INT_BLK_GAP) +#define SDHCI_INT_ALL_MASK ((unsigned int)-1) + +#define SDHCI_CQE_INT_ERR_MASK ( \ + SDHCI_INT_ADMA_ERROR | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | \ + SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | \ + SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT) + +#define SDHCI_CQE_INT_MASK (SDHCI_CQE_INT_ERR_MASK | SDHCI_INT_CQE) + +#define SDHCI_AUTO_CMD_STATUS 0x3C +#define SDHCI_AUTO_CMD_TIMEOUT 0x00000002 +#define SDHCI_AUTO_CMD_CRC 0x00000004 +#define SDHCI_AUTO_CMD_END_BIT 0x00000008 +#define SDHCI_AUTO_CMD_INDEX 0x00000010 + +#define SDHCI_HOST_CONTROL2 0x3E +#define SDHCI_CTRL_UHS_MASK 0x0007 +#define SDHCI_CTRL_UHS_SDR12 0x0000 +#define SDHCI_CTRL_UHS_SDR25 0x0001 +#define SDHCI_CTRL_UHS_SDR50 0x0002 +#define SDHCI_CTRL_UHS_SDR104 0x0003 +#define SDHCI_CTRL_UHS_DDR50 0x0004 +#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */ +#define SDHCI_CTRL_VDD_180 0x0008 +#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 +#define SDHCI_CTRL_DRV_TYPE_B 0x0000 +#define SDHCI_CTRL_DRV_TYPE_A 0x0010 +#define SDHCI_CTRL_DRV_TYPE_C 0x0020 +#define SDHCI_CTRL_DRV_TYPE_D 0x0030 +#define SDHCI_CTRL_EXEC_TUNING 0x0040 +#define SDHCI_CTRL_TUNED_CLK 0x0080 +#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 + +#define SDHCI_CAPABILITIES 0x40 +#define SDHCI_TIMEOUT_CLK_MASK 0x0000003F +#define SDHCI_TIMEOUT_CLK_SHIFT 0 +#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080 +#define SDHCI_CLOCK_BASE_MASK 0x00003F00 +#define SDHCI_CLOCK_V3_BASE_MASK 0x0000FF00 +#define SDHCI_CLOCK_BASE_SHIFT 8 +#define SDHCI_MAX_BLOCK_MASK 0x00030000 +#define SDHCI_MAX_BLOCK_SHIFT 16 +#define SDHCI_CAN_DO_8BIT 0x00040000 +#define SDHCI_CAN_DO_ADMA2 0x00080000 +#define SDHCI_CAN_DO_ADMA1 0x00100000 +#define SDHCI_CAN_DO_HISPD 0x00200000 +#define SDHCI_CAN_DO_SDMA 0x00400000 +#define SDHCI_CAN_DO_SUSPEND 0x00800000 +#define SDHCI_CAN_VDD_330 0x01000000 +#define SDHCI_CAN_VDD_300 0x02000000 +#define SDHCI_CAN_VDD_180 0x04000000 +#define SDHCI_CAN_64BIT 0x10000000 + +#define SDHCI_SUPPORT_SDR50 0x00000001 +#define SDHCI_SUPPORT_SDR104 0x00000002 +#define SDHCI_SUPPORT_DDR50 0x00000004 +#define SDHCI_DRIVER_TYPE_A 0x00000010 +#define SDHCI_DRIVER_TYPE_C 0x00000020 +#define SDHCI_DRIVER_TYPE_D 0x00000040 +#define SDHCI_RETUNING_TIMER_COUNT_MASK 0x00000F00 +#define SDHCI_RETUNING_TIMER_COUNT_SHIFT 8 +#define SDHCI_USE_SDR50_TUNING 0x00002000 +#define SDHCI_RETUNING_MODE_MASK 0x0000C000 +#define SDHCI_RETUNING_MODE_SHIFT 14 +#define SDHCI_CLOCK_MUL_MASK 0x00FF0000 +#define SDHCI_CLOCK_MUL_SHIFT 16 +#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */ + +#define SDHCI_CAPABILITIES_1 0x44 + +#define SDHCI_MAX_CURRENT 0x48 +#define SDHCI_MAX_CURRENT_LIMIT 0xFF +#define SDHCI_MAX_CURRENT_330_MASK 0x0000FF +#define SDHCI_MAX_CURRENT_330_SHIFT 0 +#define SDHCI_MAX_CURRENT_300_MASK 0x00FF00 +#define SDHCI_MAX_CURRENT_300_SHIFT 8 +#define SDHCI_MAX_CURRENT_180_MASK 0xFF0000 +#define SDHCI_MAX_CURRENT_180_SHIFT 16 +#define SDHCI_MAX_CURRENT_MULTIPLIER 4 + +/* 4C-4F reserved for more max current */ + +#define SDHCI_SET_ACMD12_ERROR 0x50 +#define SDHCI_SET_INT_ERROR 0x52 + +#define SDHCI_ADMA_ERROR 0x54 + +/* 55-57 reserved */ + +#define SDHCI_ADMA_ADDRESS 0x58 +#define SDHCI_ADMA_ADDRESS_HI 0x5C + +/* 60-FB reserved */ + +#define SDHCI_PRESET_FOR_SDR12 0x66 +#define SDHCI_PRESET_FOR_SDR25 0x68 +#define SDHCI_PRESET_FOR_SDR50 0x6A +#define SDHCI_PRESET_FOR_SDR104 0x6C +#define SDHCI_PRESET_FOR_DDR50 0x6E +#define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */ +#define SDHCI_PRESET_DRV_MASK 0xC000 +#define SDHCI_PRESET_DRV_SHIFT 14 +#define SDHCI_PRESET_CLKGEN_SEL_MASK 0x400 +#define SDHCI_PRESET_CLKGEN_SEL_SHIFT 10 +#define SDHCI_PRESET_SDCLK_FREQ_MASK 0x3FF +#define SDHCI_PRESET_SDCLK_FREQ_SHIFT 0 + +#define SDHCI_SLOT_INT_STATUS 0xFC + +#define SDHCI_HOST_VERSION 0xFE +#define SDHCI_VENDOR_VER_MASK 0xFF00 +#define SDHCI_VENDOR_VER_SHIFT 8 +#define SDHCI_SPEC_VER_MASK 0x00FF +#define SDHCI_SPEC_VER_SHIFT 0 +#define SDHCI_SPEC_100 0 +#define SDHCI_SPEC_200 1 +#define SDHCI_SPEC_300 2 + +/* + * End of controller registers. + */ + +#define SDHCI_MAX_DIV_SPEC_200 256 +#define SDHCI_MAX_DIV_SPEC_300 2046 + +/* + * Host SDMA buffer boundary. Valid values from 4K to 512K in powers of 2. + */ +#define SDHCI_DEFAULT_BOUNDARY_SIZE (512 * 1024) +#define SDHCI_DEFAULT_BOUNDARY_ARG (ilog2(SDHCI_DEFAULT_BOUNDARY_SIZE) - 12) + +/* ADMA2 32-bit DMA descriptor size */ +#define SDHCI_ADMA2_32_DESC_SZ 8 + +/* ADMA2 32-bit descriptor */ +struct sdhci_adma2_32_desc { + __le16 cmd; + __le16 len; + __le32 addr; +} __packed __aligned(4); + +/* ADMA2 data alignment */ +#define SDHCI_ADMA2_ALIGN 4 +#define SDHCI_ADMA2_MASK (SDHCI_ADMA2_ALIGN - 1) + +/* + * ADMA2 descriptor alignment. Some controllers (e.g. Intel) require 8 byte + * alignment for the descriptor table even in 32-bit DMA mode. Memory + * allocation is at least 8 byte aligned anyway, so just stipulate 8 always. + */ +#define SDHCI_ADMA2_DESC_ALIGN 8 + +/* ADMA2 64-bit DMA descriptor size */ +#define SDHCI_ADMA2_64_DESC_SZ 12 + +/* + * ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte + * aligned. + */ +struct sdhci_adma2_64_desc { + __le16 cmd; + __le16 len; + __le32 addr_lo; + __le32 addr_hi; +} __packed __aligned(4); + +#define ADMA2_TRAN_VALID 0x21 +#define ADMA2_NOP_END_VALID 0x3 +#define ADMA2_END 0x2 + +/* + * Maximum segments assuming a 512KiB maximum requisition size and a minimum + * 4KiB page size. + */ +#define SDHCI_MAX_SEGS 128 + +/* Allow for a a command request and a data request at the same time */ +#define SDHCI_MAX_MRQS 2 + +/* + * 48bit command and 136 bit response in 100KHz clock could take upto 2.48ms. + * However since the start time of the command, the time between + * command and response, and the time between response and start of data is + * not known, set the command transfer time to 10ms. + */ +#define MMC_CMD_TRANSFER_TIME (10 * NSEC_PER_MSEC) /* max 10 ms */ + +enum sdhci_cookie { + COOKIE_UNMAPPED, + COOKIE_PRE_MAPPED, /* mapped by sdhci_pre_req() */ + COOKIE_MAPPED, /* mapped by sdhci_prepare_data() */ +}; + +struct sdhci_host { + /* Data set by hardware interface driver */ + const char *hw_name; /* Hardware bus name */ + + unsigned int quirks; /* Deviations from spec. */ + +/* Controller doesn't honor resets unless we touch the clock register */ +#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) +/* Controller has bad caps bits, but really supports DMA */ +#define SDHCI_QUIRK_FORCE_DMA (1<<1) +/* Controller doesn't like to be reset when there is no card inserted. */ +#define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) +/* Controller doesn't like clearing the power reg before a change */ +#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) +/* Controller has flaky internal state so reset it on each ios change */ +#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) +/* Controller has an unusable DMA engine */ +#define SDHCI_QUIRK_BROKEN_DMA (1<<5) +/* Controller has an unusable ADMA engine */ +#define SDHCI_QUIRK_BROKEN_ADMA (1<<6) +/* Controller can only DMA from 32-bit aligned addresses */ +#define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<7) +/* Controller can only DMA chunk sizes that are a multiple of 32 bits */ +#define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<8) +/* Controller can only ADMA chunks that are a multiple of 32 bits */ +#define SDHCI_QUIRK_32BIT_ADMA_SIZE (1<<9) +/* Controller needs to be reset after each request to stay stable */ +#define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<10) +/* Controller needs voltage and power writes to happen separately */ +#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<11) +/* Controller provides an incorrect timeout value for transfers */ +#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) +/* Controller has an issue with buffer bits for small transfers */ +#define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) +/* Controller does not provide transfer-complete interrupt when not busy */ +#define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) +/* Controller has unreliable card detection */ +#define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15) +/* Controller reports inverted write-protect state */ +#define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) +/* Controller does not like fast PIO transfers */ +#define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) +/* Controller has to be forced to use block size of 2048 bytes */ +#define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) +/* Controller cannot do multi-block transfers */ +#define SDHCI_QUIRK_NO_MULTIBLOCK (1<<21) +/* Controller can only handle 1-bit data transfers */ +#define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22) +/* Controller needs 10ms delay between applying power and clock */ +#define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) +/* Controller uses SDCLK instead of TMCLK for data timeouts */ +#define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24) +/* Controller reports wrong base clock capability */ +#define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1<<25) +/* Controller cannot support End Attribute in NOP ADMA descriptor */ +#define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1<<26) +/* Controller is missing device caps. Use caps provided by host */ +#define SDHCI_QUIRK_MISSING_CAPS (1<<27) +/* Controller uses Auto CMD12 command to stop the transfer */ +#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1<<28) +/* Controller doesn't have HISPD bit field in HI-SPEED SD card */ +#define SDHCI_QUIRK_NO_HISPD_BIT (1<<29) +/* Controller treats ADMA descriptors with length 0000h incorrectly */ +#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30) +/* The read-only detection via SDHCI_PRESENT_STATE register is unstable */ +#define SDHCI_QUIRK_UNSTABLE_RO_DETECT (1<<31) + + unsigned int quirks2; /* More deviations from spec. */ + +#define SDHCI_QUIRK2_HOST_OFF_CARD_ON (1<<0) +#define SDHCI_QUIRK2_HOST_NO_CMD23 (1<<1) +/* The system physically doesn't support 1.8v, even if the host does */ +#define SDHCI_QUIRK2_NO_1_8_V (1<<2) +#define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) +#define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) +/* Controller has a non-standard host control register */ +#define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) +/* Controller does not support HS200 */ +#define SDHCI_QUIRK2_BROKEN_HS200 (1<<6) +/* Controller does not support DDR50 */ +#define SDHCI_QUIRK2_BROKEN_DDR50 (1<<7) +/* Stop command (CMD12) can set Transfer Complete when not using MMC_RSP_BUSY */ +#define SDHCI_QUIRK2_STOP_WITH_TC (1<<8) +/* Controller does not support 64-bit DMA */ +#define SDHCI_QUIRK2_BROKEN_64_BIT_DMA (1<<9) +/* need clear transfer mode register before send cmd */ +#define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1<<10) +/* Capability register bit-63 indicates HS400 support */ +#define SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 (1<<11) +/* forced tuned clock */ +#define SDHCI_QUIRK2_TUNING_WORK_AROUND (1<<12) +/* disable the block count for single block transactions */ +#define SDHCI_QUIRK2_SUPPORT_SINGLE (1<<13) +/* Controller broken with using ACMD23 */ +#define SDHCI_QUIRK2_ACMD23_BROKEN (1<<14) +/* Broken Clock divider zero in controller */ +#define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN (1<<15) +/* Controller has CRC in 136 bit Command Response */ +#define SDHCI_QUIRK2_RSP_136_HAS_CRC (1<<16) +/* + * Disable HW timeout if the requested timeout is more than the maximum + * obtainable timeout. + */ +#define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT (1<<17) + + int irq; /* Device IRQ */ + void __iomem *ioaddr; /* Mapped address */ + char *bounce_buffer; /* For packing SDMA reads/writes */ + dma_addr_t bounce_addr; + unsigned int bounce_buffer_size; + + const struct sdhci_ops *ops; /* Low level hw interface */ + + /* Internal data */ + struct mmc_host *mmc; /* MMC structure */ + struct mmc_host_ops mmc_host_ops; /* MMC host ops */ + u64 dma_mask; /* custom DMA mask */ + +#if IS_ENABLED(CONFIG_LEDS_CLASS) + struct led_classdev led; /* LED control */ + char led_name[32]; +#endif + + spinlock_t lock; /* Mutex */ + + int flags; /* Host attributes */ +#define SDHCI_USE_SDMA (1<<0) /* Host is SDMA capable */ +#define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */ +#define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */ +#define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ +#define SDHCI_SDR50_NEEDS_TUNING (1<<4) /* SDR50 needs tuning */ +#define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */ +#define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ +#define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */ +#define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ +#define SDHCI_USE_64_BIT_DMA (1<<12) /* Use 64-bit DMA */ +#define SDHCI_HS400_TUNING (1<<13) /* Tuning for HS400 */ +#define SDHCI_SIGNALING_330 (1<<14) /* Host is capable of 3.3V signaling */ +#define SDHCI_SIGNALING_180 (1<<15) /* Host is capable of 1.8V signaling */ +#define SDHCI_SIGNALING_120 (1<<16) /* Host is capable of 1.2V signaling */ + + unsigned int version; /* SDHCI spec. version */ + + unsigned int max_clk; /* Max possible freq (MHz) */ + unsigned int timeout_clk; /* Timeout freq (KHz) */ + unsigned int clk_mul; /* Clock Muliplier value */ + + unsigned int clock; /* Current clock (MHz) */ + u8 pwr; /* Current voltage */ + + bool runtime_suspended; /* Host is runtime suspended */ + bool bus_on; /* Bus power prevents runtime suspend */ + bool preset_enabled; /* Preset is enabled */ + bool pending_reset; /* Cmd/data reset is pending */ + bool irq_wake_enabled; /* IRQ wakeup is enabled */ + + struct mmc_request *mrqs_done[SDHCI_MAX_MRQS]; /* Requests done */ + struct mmc_command *cmd; /* Current command */ + struct mmc_command *data_cmd; /* Current data command */ + struct mmc_data *data; /* Current data request */ + unsigned int data_early:1; /* Data finished before cmd */ + + struct sg_mapping_iter sg_miter; /* SG state for PIO */ + unsigned int blocks; /* remaining PIO blocks */ + + int sg_count; /* Mapped sg entries */ + + void *adma_table; /* ADMA descriptor table */ + void *align_buffer; /* Bounce buffer */ + + size_t adma_table_sz; /* ADMA descriptor table size */ + size_t align_buffer_sz; /* Bounce buffer size */ + + dma_addr_t adma_addr; /* Mapped ADMA descr. table */ + dma_addr_t align_addr; /* Mapped bounce buffer */ + + unsigned int desc_sz; /* ADMA descriptor size */ + + struct tasklet_struct finish_tasklet; /* Tasklet structures */ + + struct timer_list timer; /* Timer for timeouts */ + struct timer_list data_timer; /* Timer for data timeouts */ + + u32 caps; /* CAPABILITY_0 */ + u32 caps1; /* CAPABILITY_1 */ + bool read_caps; /* Capability flags have been read */ + + unsigned int ocr_avail_sdio; /* OCR bit masks */ + unsigned int ocr_avail_sd; + unsigned int ocr_avail_mmc; + u32 ocr_mask; /* available voltages */ + + unsigned timing; /* Current timing */ + + u32 thread_isr; + + /* cached registers */ + u32 ier; + + bool cqe_on; /* CQE is operating */ + u32 cqe_ier; /* CQE interrupt mask */ + u32 cqe_err_ier; /* CQE error interrupt mask */ + + wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */ + unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */ + + unsigned int tuning_count; /* Timer count for re-tuning */ + unsigned int tuning_mode; /* Re-tuning mode supported by host */ +#define SDHCI_TUNING_MODE_1 0 +#define SDHCI_TUNING_MODE_2 1 +#define SDHCI_TUNING_MODE_3 2 + /* Delay (ms) between tuning commands */ + int tuning_delay; + + /* Host SDMA buffer boundary. */ + u32 sdma_boundary; + + u64 data_timeout; + + unsigned long private[0] ____cacheline_aligned; +}; + +struct sdhci_ops { +#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS + u32 (*read_l)(struct sdhci_host *host, int reg); + u16 (*read_w)(struct sdhci_host *host, int reg); + u8 (*read_b)(struct sdhci_host *host, int reg); + void (*write_l)(struct sdhci_host *host, u32 val, int reg); + void (*write_w)(struct sdhci_host *host, u16 val, int reg); + void (*write_b)(struct sdhci_host *host, u8 val, int reg); +#endif + + void (*set_clock)(struct sdhci_host *host, unsigned int clock); + void (*set_power)(struct sdhci_host *host, unsigned char mode, + unsigned short vdd); + + u32 (*irq)(struct sdhci_host *host, u32 intmask); + + int (*enable_dma)(struct sdhci_host *host); + unsigned int (*get_max_clock)(struct sdhci_host *host); + unsigned int (*get_min_clock)(struct sdhci_host *host); + /* get_timeout_clock should return clk rate in unit of Hz */ + unsigned int (*get_timeout_clock)(struct sdhci_host *host); + unsigned int (*get_max_timeout_count)(struct sdhci_host *host); + void (*set_timeout)(struct sdhci_host *host, + struct mmc_command *cmd); + void (*set_bus_width)(struct sdhci_host *host, int width); + void (*platform_send_init_74_clocks)(struct sdhci_host *host, + u8 power_mode); + unsigned int (*get_ro)(struct sdhci_host *host); + void (*reset)(struct sdhci_host *host, u8 mask); + int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode); + void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); + void (*hw_reset)(struct sdhci_host *host); + void (*adma_workaround)(struct sdhci_host *host, u32 intmask); + void (*card_event)(struct sdhci_host *host); + void (*voltage_switch)(struct sdhci_host *host); +}; + +#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS + +static inline void sdhci_writel(struct sdhci_host *host, u32 val, int reg) +{ + if (unlikely(host->ops->write_l)) + host->ops->write_l(host, val, reg); + else + writel(val, host->ioaddr + reg); +} + +static inline void sdhci_writew(struct sdhci_host *host, u16 val, int reg) +{ + if (unlikely(host->ops->write_w)) + host->ops->write_w(host, val, reg); + else + writew(val, host->ioaddr + reg); +} + +static inline void sdhci_writeb(struct sdhci_host *host, u8 val, int reg) +{ + if (unlikely(host->ops->write_b)) + host->ops->write_b(host, val, reg); + else + writeb(val, host->ioaddr + reg); +} + +static inline u32 sdhci_readl(struct sdhci_host *host, int reg) +{ + if (unlikely(host->ops->read_l)) + return host->ops->read_l(host, reg); + else + return readl(host->ioaddr + reg); +} + +static inline u16 sdhci_readw(struct sdhci_host *host, int reg) +{ + if (unlikely(host->ops->read_w)) + return host->ops->read_w(host, reg); + else + return readw(host->ioaddr + reg); +} + +static inline u8 sdhci_readb(struct sdhci_host *host, int reg) +{ + if (unlikely(host->ops->read_b)) + return host->ops->read_b(host, reg); + else + return readb(host->ioaddr + reg); +} + +#else + +static inline void sdhci_writel(struct sdhci_host *host, u32 val, int reg) +{ + writel(val, host->ioaddr + reg); +} + +static inline void sdhci_writew(struct sdhci_host *host, u16 val, int reg) +{ + writew(val, host->ioaddr + reg); +} + +static inline void sdhci_writeb(struct sdhci_host *host, u8 val, int reg) +{ + writeb(val, host->ioaddr + reg); +} + +static inline u32 sdhci_readl(struct sdhci_host *host, int reg) +{ + return readl(host->ioaddr + reg); +} + +static inline u16 sdhci_readw(struct sdhci_host *host, int reg) +{ + return readw(host->ioaddr + reg); +} + +static inline u8 sdhci_readb(struct sdhci_host *host, int reg) +{ + return readb(host->ioaddr + reg); +} + +#endif /* CONFIG_MMC_SDHCI_IO_ACCESSORS */ + +struct sdhci_host *sdhci_alloc_host(struct device *dev, size_t priv_size); +void sdhci_free_host(struct sdhci_host *host); + +static inline void *sdhci_priv(struct sdhci_host *host) +{ + return host->private; +} + +void sdhci_card_detect(struct sdhci_host *host); +void __sdhci_read_caps(struct sdhci_host *host, u16 *ver, u32 *caps, + u32 *caps1); +int sdhci_setup_host(struct sdhci_host *host); +void sdhci_cleanup_host(struct sdhci_host *host); +int __sdhci_add_host(struct sdhci_host *host); +int sdhci_add_host(struct sdhci_host *host); +void sdhci_remove_host(struct sdhci_host *host, int dead); +void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); + +static inline void sdhci_read_caps(struct sdhci_host *host) +{ + __sdhci_read_caps(host, NULL, NULL, NULL); +} + +static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host) +{ + return !!(host->flags & SDHCI_SDIO_IRQ_ENABLED); +} + +u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, + unsigned int *actual_clock); +void sdhci_set_clock(struct sdhci_host *host, unsigned int clock); +void sdhci_enable_clk(struct sdhci_host *host, u16 clk); +void sdhci_set_power(struct sdhci_host *host, unsigned char mode, + unsigned short vdd); +void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, + unsigned short vdd); +void sdhci_set_bus_width(struct sdhci_host *host, int width); +void sdhci_reset(struct sdhci_host *host, u8 mask); +void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing); +int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); +void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); +int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, + struct mmc_ios *ios); +void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable); + +#ifdef CONFIG_PM +int sdhci_suspend_host(struct sdhci_host *host); +int sdhci_resume_host(struct sdhci_host *host); +int sdhci_runtime_suspend_host(struct sdhci_host *host); +int sdhci_runtime_resume_host(struct sdhci_host *host); +#endif + +void sdhci_cqe_enable(struct mmc_host *mmc); +void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery); +bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, + int *data_error); + +void sdhci_dumpregs(struct sdhci_host *host); + +void sdhci_start_tuning(struct sdhci_host *host); +void sdhci_end_tuning(struct sdhci_host *host); +void sdhci_reset_tuning(struct sdhci_host *host); +void sdhci_send_tuning(struct sdhci_host *host, u32 opcode); + +#endif /* __SDHCI_HW_H */ diff --git a/platform/centec-arm64/tsingma-bsp/src/spi-ctc-qspi/Makefile b/platform/centec-arm64/tsingma-bsp/src/spi-ctc-qspi/Makefile new file mode 100644 index 000000000000..f42732b694cb --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/spi-ctc-qspi/Makefile @@ -0,0 +1 @@ +obj-m = spi-ctc-qspi.o diff --git a/platform/centec-arm64/tsingma-bsp/src/spi-ctc-qspi/spi-ctc-qspi.c b/platform/centec-arm64/tsingma-bsp/src/spi-ctc-qspi/spi-ctc-qspi.c new file mode 100644 index 000000000000..936459bd3e73 --- /dev/null +++ b/platform/centec-arm64/tsingma-bsp/src/spi-ctc-qspi/spi-ctc-qspi.c @@ -0,0 +1,639 @@ +/* + * Centec QSPI controller driver + * + * Author: wangyb + * + * Copyright 2005-2018, Centec Networks (Suzhou) Co., Ltd. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPI_MODE 0x00 + +#define PIO_MODE_1 0x01 +#define PIO_MODE_2 0x02 + +#define PIO_BASE(NR) (0x20*(NR-1)) +#define PIO_GO(NR) (0x10 + PIO_BASE(NR)) +#define PIO_CTRL(NR) (0x14 + PIO_BASE(NR)) +#define PIO_STEP0_CONF(NR) (0x20 + PIO_BASE(NR)) +#define PIO_STEP1_CONF(NR) (0x24 + PIO_BASE(NR)) +#define PIO_STEP2_CONF(NR) (0x28 + PIO_BASE(NR)) +#define PIO_STEP3_CONF(NR) (0x2c + PIO_BASE(NR)) + +#define PP_GO 0x80 +#define PP_CTRL 0x84 +#define PP_CMD_CODE 0x90 +#define PP_CMD_CONF 0x94 +#define PP_ADDR_CODE 0x98 +#define PP_ADDR_CONF 0X9c +#define PP_DUMMY_CODE 0xa0 +#define PP_DUMMY_CONF 0xa4 +#define PP_DATA_CONF 0xa8 + +#define CTRL_IDLE_CYCLE(V) (((V)&3)<<24) +#define CTRL_PRE_CYCLE(V) (((V)&3)<<22) +#define CTRL_POST_CYCLE(V) (((V)&3)<<20) +#define CTRL_SCLK_DEFAULT(V) (((V)&1)<<19) +#define CTRL_SOUT3_DEFAULT(V) (((V)&1)<<18) +#define CTRL_SOUT2_DEFAULT(V) (((V)&1)<<17) +#define CTRL_SOUT1_DEFAULT(V) (((V)&1)<<16) +#define CTRL_CS(V) (((V)&0xff)<<8) +#define CTRL_DIV_SCLK(V) (((V)&0xff)<<0) + +#define CTC_QSPI_TX_BUFF 0x100 +#define CTC_QSPI_RX_BUFF 0x180 + +#define CTC_QSPI_RX_BUFFER_SIZE 128 +#define CTC_QSPI_TX_BUFFER_SIZE 256 + +#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ + +#define TIMEOUT_COUNT 65535 + +#define SPI_INT_EN 0x04 +#define SPI_INT_STATUS 0x0c + +struct ctc_qspi { + void __iomem *regs; + u32 speed_hz; + u32 bus_clk; + u32 num_chipselect; + u32 idlecycle; + u32 precycle; + u32 postcycle; + u32 sout1def; + u32 sout2def; + u32 sout3def; + u32 qspi_mode; + u32 clkdiv; + u32 sclkdef; + u32 cs_select; + u32 bytes_to_transfer; + u8 step; + u32 tx_entry; +}; + +enum ctc_qspi_mode { + PIO_MODE1 = 1, + PIO_MODE2, + PP_MODE, + BOOT_MODE, + XIP_MODE, + MODE_MAX +}; + +enum type_mode { + TYPE_PP = 1, + TYPE_PIO, + TYPE_MAX +}; + +static int ctc_reg_read(struct ctc_qspi *ctc_qspi, u32 reg, u32 *value) +{ + *value = readl(ctc_qspi->regs + reg); + return *value; +} + +static int ctc_reg_write(struct ctc_qspi *ctc_qspi, u32 reg, u32 value) +{ + writel(value, ctc_qspi->regs + reg); + + return 0; +} + +static int ctc_reg_write_mask(struct ctc_qspi *ctc_qspi, u32 reg, u32 value, + u32 mask) +{ + u32 temp; + + ctc_reg_read(ctc_qspi, reg, &temp); + temp &= ~mask; + temp |= value; + ctc_reg_write(ctc_qspi, reg, temp); + + return 0; +} + +static int ctc_qspi_setup(struct spi_device *spi) +{ + struct ctc_qspi *ctc_qspi = spi_master_get_devdata(spi->master); + + if (spi->master->busy) + return -EBUSY; + + ctc_qspi->sout1def = 1; + ctc_qspi->sout2def = 1; + ctc_qspi->sout3def = 1; + + ctc_qspi->speed_hz = spi->max_speed_hz; + + ctc_qspi->clkdiv = (ctc_qspi->bus_clk / (ctc_qspi->speed_hz * 2)); + + if ((spi->mode & 0x3) == SPI_MODE_0) + ctc_qspi->sclkdef = 0; + else if ((spi->mode & 0x3) == SPI_MODE_3) + ctc_qspi->sclkdef = 1; + else + ctc_qspi->sclkdef = 1; + return 0; +} + +static noinline int ctc_write_tx_buf(struct ctc_qspi *ctc_qspi, u8 offset, + u32 value) +{ + writel(value, ctc_qspi->regs + CTC_QSPI_TX_BUFF + offset); + + return 0; +} + +static noinline int check_buf_ok(u8 *buf, int i) +{ + return buf && (buf + i); +} + +static noinline int fill_tx_entry(struct ctc_qspi *ctc_qspi, u8 *buf, int i, + u8 off) +{ + ctc_qspi->tx_entry |= buf[i] << (off % 4) * 8; + + return 0; +} + +static noinline void update_offset(u8 *offset, u8 off) +{ + *offset = off; +} + +static void ctc_fill_tx_buf(struct ctc_qspi *ctc_qspi, u8 *offset, u8 *buf, + u32 len) +{ + + int i = 0; + u8 off = *offset; + + while (i < len) { + if (check_buf_ok(buf, i)) + fill_tx_entry(ctc_qspi, buf, i, off); + + if (off % 4 == 0) { + ctc_write_tx_buf(ctc_qspi, off, ctc_qspi->tx_entry); + ctc_qspi->tx_entry = 0; + } + i++; + off--; + } + + update_offset(offset, off); + +} + +static void ctc_fill_pp_buf(struct ctc_qspi *ctc_qspi, u32 *offset, u8 *buf, + u32 len) +{ + u32 i = 0, j = 0; + u32 off = *offset; + + while (i < len) { + for (j = 0; j < 4; j++) { + if (buf && (buf + i)) + ctc_qspi->tx_entry |= buf[i + j] << (j % 4) * 8; + } + ctc_write_tx_buf(ctc_qspi, off, ctc_qspi->tx_entry); + ctc_qspi->tx_entry = 0; + + i = i + 4; + off += 4; + } + *offset = off; +} + +static void ctc_stepx_conf_init(struct ctc_qspi *ctc_qspi) +{ + ctc_qspi->step = 0; + + ctc_reg_write_mask(ctc_qspi, PIO_STEP0_CONF(ctc_qspi->qspi_mode), 0, + 0xffffffff); + ctc_reg_write_mask(ctc_qspi, PIO_STEP1_CONF(ctc_qspi->qspi_mode), 0, + 0xffffffff); + ctc_reg_write_mask(ctc_qspi, PIO_STEP2_CONF(ctc_qspi->qspi_mode), 0, + 0xffffffff); + ctc_reg_write_mask(ctc_qspi, PIO_STEP3_CONF(ctc_qspi->qspi_mode), 0, + 0xffffffff); +} + +static void ctc_stepx_conf(struct ctc_qspi *ctc_qspi, u8 lanes, u32 bytes, + u32 output_en) +{ + u32 cycle = 0; + u32 stepx_conf = 0; + + if (bytes <= 0) + return; + + cycle = (bytes * 8) / lanes; + + if (lanes == 1) { + stepx_conf = (0xd << 20) | (lanes << 16) | (cycle); + } else if (lanes == 2) { + stepx_conf = output_en ? (0x3 << 20) | (lanes << 16) | (cycle) : + (0xc << 20) | (lanes << 16) | (cycle); + } else if (lanes == 4) { + stepx_conf = output_en ? (0xf << 20) | (lanes << 16) | (cycle) : + (0x0 << 20) | (lanes << 16) | (cycle); + } + + if (ctc_qspi->step == 0) { + ctc_reg_write_mask(ctc_qspi, + PIO_STEP0_CONF(ctc_qspi->qspi_mode), + stepx_conf, 0xffffffff); + ctc_qspi->step++; + } else if (ctc_qspi->step == 1) { + ctc_reg_write_mask(ctc_qspi, + PIO_STEP1_CONF(ctc_qspi->qspi_mode), + stepx_conf, 0xffffffff); + ctc_qspi->step++; + } else if (ctc_qspi->step == 2) { + ctc_reg_write_mask(ctc_qspi, + PIO_STEP2_CONF(ctc_qspi->qspi_mode), + stepx_conf, 0xffffffff); + ctc_qspi->step++; + } else if (ctc_qspi->step == 3) { + ctc_reg_write_mask(ctc_qspi, + PIO_STEP3_CONF(ctc_qspi->qspi_mode), + stepx_conf, 0xffffffff); + ctc_qspi->step++; + } + +} + +static void ctc_select_qspi_mode(struct ctc_qspi *ctc_qspi, u32 qspi_mode) +{ + if ((qspi_mode == PIO_MODE1) || (qspi_mode == PIO_MODE2)) { + ctc_reg_write_mask(ctc_qspi, SPI_MODE, ctc_qspi->qspi_mode, + 0xffffffff); + } else if (qspi_mode == PP_MODE) { + ctc_reg_write_mask(ctc_qspi, SPI_MODE, 0x100, 0xffffffff); + } +} + +static void ctc_qspi_pio_ctrl(struct ctc_qspi *ctc_qspi) +{ + u32 ctrl = 0; + + ctrl = CTRL_IDLE_CYCLE(ctc_qspi->idlecycle) | + CTRL_PRE_CYCLE(ctc_qspi->precycle) | + CTRL_POST_CYCLE(ctc_qspi->postcycle) | + CTRL_SCLK_DEFAULT(ctc_qspi->sclkdef) | + CTRL_SOUT3_DEFAULT(ctc_qspi->sout3def) | + CTRL_SOUT2_DEFAULT(ctc_qspi->sout2def) | + CTRL_SOUT1_DEFAULT(ctc_qspi->sout1def) | + CTRL_CS(ctc_qspi->cs_select) | + CTRL_DIV_SCLK(ctc_qspi->clkdiv); + + ctc_reg_write_mask(ctc_qspi, PIO_CTRL(ctc_qspi->qspi_mode), ctrl, + 0xffffffff); +} + +static void ctc_qspi_pp_ctrl(struct ctc_qspi *ctc_qspi) +{ + u32 ctrl = 0; + + ctrl = CTRL_IDLE_CYCLE(ctc_qspi->idlecycle) | + CTRL_PRE_CYCLE(ctc_qspi->precycle) | + CTRL_POST_CYCLE(ctc_qspi->postcycle) | + CTRL_SCLK_DEFAULT(ctc_qspi->sclkdef) | + CTRL_SOUT3_DEFAULT(ctc_qspi->sout3def) | + CTRL_SOUT2_DEFAULT(ctc_qspi->sout2def) | + CTRL_SOUT1_DEFAULT(ctc_qspi->sout1def) | + CTRL_CS(ctc_qspi->cs_select) | + CTRL_DIV_SCLK(ctc_qspi->clkdiv); + + ctc_reg_write_mask(ctc_qspi, PP_CTRL, ctrl, 0xffffffff); +} + +static u32 ctc_pp_conf(u8 lanes, u32 len) +{ + u32 cycle = 0; + + cycle = (len * 8) / lanes; + + return (lanes << 16) | (cycle); +} + +static int ctc_read_rx_buf(struct ctc_qspi *ctc_qspi, u8 offset, u8 *value) +{ + *value = readb(ctc_qspi->regs + CTC_QSPI_RX_BUFF + offset); + + return 0; +} + +static void ctc_extra_rx_buf(struct ctc_qspi *ctc_qspi, u8 offset, u8 *buf, + u8 len) +{ + int i = 0; + + while (i < len) { + ctc_read_rx_buf(ctc_qspi, offset, &buf[i++]); + offset--; + } +} + +static int ctc_transfer_for_PP_mode(struct ctc_qspi *ctc_qspi, + struct spi_transfer *p_xfers[], + u8 xfers_num, u32 msg_len) +{ + u8 i; + u32 pp_conf; + u32 timeout = 0; + u32 temp; + u32 offset; + struct spi_mem_op mem_ops; + + memset(&mem_ops, 0, sizeof(mem_ops)); + + mem_ops.cmd.opcode = ((u8 *) p_xfers[0]->tx_buf)[0]; + mem_ops.cmd.buswidth = p_xfers[0]->tx_nbits; + + mem_ops.addr.nbytes = p_xfers[1]->len; + mem_ops.addr.buswidth = p_xfers[1]->tx_nbits; + for (i = 0; i < mem_ops.addr.nbytes; i++) { + mem_ops.addr.val |= + ((u8 *) p_xfers[1]->tx_buf)[i] << (8 * + (mem_ops.addr.nbytes - + i - 1)); + } + + if (xfers_num >= 4) { + mem_ops.addr.nbytes = p_xfers[2]->len; + mem_ops.addr.buswidth = p_xfers[2]->tx_nbits; + } + + mem_ops.data.nbytes = p_xfers[xfers_num - 1]->len; + mem_ops.data.buswidth = p_xfers[xfers_num - 1]->tx_nbits; + mem_ops.data.buf.out = p_xfers[xfers_num - 1]->tx_buf; + + ctc_qspi->qspi_mode = PP_MODE; + ctc_select_qspi_mode(ctc_qspi, ctc_qspi->qspi_mode); + ctc_qspi_pp_ctrl(ctc_qspi); + + /* Fill buffer */ + offset = 0; + ctc_qspi->tx_entry = 0; + ctc_fill_pp_buf(ctc_qspi, &offset, (u8 *) mem_ops.data.buf.out, + mem_ops.data.nbytes); + + /* PP CMD */ + ctc_reg_write_mask(ctc_qspi, PP_CMD_CODE, mem_ops.cmd.opcode, + 0xffffffff); + pp_conf = ctc_pp_conf(mem_ops.cmd.buswidth, 1); + ctc_reg_write_mask(ctc_qspi, PP_CMD_CONF, pp_conf, 0xffffffff); + + /* PP ADDR */ + ctc_reg_write_mask(ctc_qspi, PP_ADDR_CODE, mem_ops.addr.val, + 0xffffffff); + pp_conf = ctc_pp_conf(mem_ops.addr.buswidth, mem_ops.addr.nbytes); + ctc_reg_write_mask(ctc_qspi, PP_ADDR_CONF, pp_conf, 0xffffffff); + + /* PP DUMMY */ + ctc_reg_write_mask(ctc_qspi, PP_DUMMY_CODE, 0x00000000, 0xffffffff); + pp_conf = ctc_pp_conf(mem_ops.dummy.buswidth, mem_ops.dummy.nbytes); + ctc_reg_write_mask(ctc_qspi, PP_DUMMY_CONF, pp_conf, 0xffffffff); + + /* PP DATA */ + pp_conf = ctc_pp_conf(mem_ops.data.buswidth, mem_ops.data.nbytes); + ctc_reg_write_mask(ctc_qspi, PP_DATA_CONF, pp_conf, 0xffffffff); + + /* PP GO */ + ctc_reg_write_mask(ctc_qspi, PP_GO, 0x01, 0xffffffff); + while (ctc_reg_read(ctc_qspi, PP_GO, &temp) & 0x1) { + if (timeout++ > TIMEOUT_COUNT) + break; + udelay(1); + } + + return msg_len; +} + +static int ctc_transfer_for_PIO(struct ctc_qspi *ctc_qspi, + struct spi_transfer *p_xfers[], u8 xfers_num, + u32 msg_len) +{ + u8 i; + u8 offset; + u32 timeout = 0; + u32 temp; + + ctc_qspi->qspi_mode = PIO_MODE1; + ctc_select_qspi_mode(ctc_qspi, ctc_qspi->qspi_mode); + ctc_qspi_pio_ctrl(ctc_qspi); + ctc_stepx_conf_init(ctc_qspi); + + offset = msg_len - 1; + ctc_qspi->tx_entry = 0; + for (i = 0; i < xfers_num; i++) { + if (p_xfers[i]->tx_buf) { + ctc_fill_tx_buf(ctc_qspi, &offset, + (u8 *) p_xfers[i]->tx_buf, + p_xfers[i]->len); + ctc_stepx_conf(ctc_qspi, p_xfers[i]->tx_nbits, + p_xfers[i]->len, 1); + } else { + ctc_fill_tx_buf(ctc_qspi, &offset, + (u8 *) p_xfers[i]->rx_buf, + p_xfers[i]->len); + ctc_stepx_conf(ctc_qspi, p_xfers[i]->rx_nbits, + p_xfers[i]->len, 0); + } + } + + /* PIO write start transfer */ + ctc_reg_write_mask(ctc_qspi, PIO_GO(ctc_qspi->qspi_mode), 0x01, + 0xffffffff); + while (ctc_reg_read(ctc_qspi, PIO_GO(ctc_qspi->qspi_mode), &temp) & 0x1) { + if (timeout++ > TIMEOUT_COUNT) + break; + udelay(1); + } + + if (p_xfers[xfers_num - 1]->rx_buf) { + ctc_extra_rx_buf(ctc_qspi, p_xfers[xfers_num - 1]->len - 1, + p_xfers[xfers_num - 1]->rx_buf, + p_xfers[xfers_num - 1]->len); + } + + return msg_len; +} + +static int ctc_qspi_start_transfer_one(struct spi_master *master, + struct spi_message *msg) +{ + struct ctc_qspi *ctc_qspi = spi_master_get_devdata(master); + struct spi_device *spi = msg->spi; + struct spi_transfer *t; + u8 xfer_num = 0; + struct spi_transfer *xfers[4]; + u32 msg_len = 0; + + ctc_qspi->cs_select = (0x1 << spi->chip_select); + list_for_each_entry(t, &msg->transfers, transfer_list) { + xfers[xfer_num] = t; + xfer_num++; + msg_len += t->len; + } + + if (xfers[xfer_num - 1]->tx_buf && xfer_num >= 3) { + msg->actual_length = + ctc_transfer_for_PP_mode(ctc_qspi, xfers, xfer_num, + msg_len); + } else { + msg->actual_length = + ctc_transfer_for_PIO(ctc_qspi, xfers, xfer_num, msg_len); + } + + msg->status = 0; + spi_finalize_current_message(master); + + return 0; +} + +int ctc_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) +{ + //max data transfer size = tx buffer size - (cmd - addr -dummy ) + if (op->data.dir == SPI_MEM_DATA_IN) { + if (op->data.nbytes > CTC_QSPI_RX_BUFFER_SIZE - 6) + op->data.nbytes = CTC_QSPI_RX_BUFFER_SIZE - 6; + } else { + if (op->data.nbytes > CTC_QSPI_TX_BUFFER_SIZE) + op->data.nbytes = CTC_QSPI_TX_BUFFER_SIZE; + } + + return 0; +} + +static int ctc_qspi_exec_mem_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + return -ENOTSUPP; +} + +static const struct spi_controller_mem_ops ctc_qspi_mem_ops = { + .adjust_op_size = ctc_qspi_adjust_op_size, + .exec_op = ctc_qspi_exec_mem_op, +}; + +static int ctc_qspi_probe(struct platform_device *pdev) +{ + int ret = 0, irq; + struct spi_master *master; + struct ctc_qspi *ctc_qspi; + struct resource *res; + struct device_node *np = pdev->dev.of_node; + u32 tmp; + + master = spi_alloc_master(&pdev->dev, sizeof(*ctc_qspi)); + if (!master) + return -ENOMEM; + + master->mode_bits = + SPI_MODE_3 | SPI_MODE_1 | SPI_TX_DUAL | SPI_RX_DUAL | SPI_TX_QUAD | + SPI_RX_QUAD; + master->setup = ctc_qspi_setup; + master->transfer_one_message = ctc_qspi_start_transfer_one; + master->bits_per_word_mask = + SPI_BPW_MASK(32) | SPI_BPW_MASK(16) | SPI_BPW_MASK(8); + master->mem_ops = &ctc_qspi_mem_ops; + if (!of_property_read_u32(np, "num-cs", &tmp)) + master->num_chipselect = tmp; + + ctc_qspi = spi_master_get_devdata(master); + master->dev.of_node = pdev->dev.of_node; + platform_set_drvdata(pdev, master); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + ctc_qspi->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(ctc_qspi->regs)) { + ret = PTR_ERR(ctc_qspi->regs); + goto remove_master; + } + + if (!of_property_read_u32(np, "pclk", &tmp)) + ctc_qspi->bus_clk = tmp; + if (!of_property_read_u32(np, "idle-cycle", &tmp)) + ctc_qspi->idlecycle = tmp; + if (!of_property_read_u32(np, "pre-cycle", &tmp)) + ctc_qspi->precycle = tmp; + if (!of_property_read_u32(np, "post-cycle", &tmp)) + ctc_qspi->postcycle = tmp; + if (!of_property_read_u32(np, "qspi-mode", &tmp)) + ctc_qspi->qspi_mode = tmp; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no irq resource?\n"); + return irq; + } + ret = devm_spi_register_master(&pdev->dev, master); + if (!ret) + return 0; + return 0; + +remove_master: + spi_master_put(master); + + return ret; +} + +static int ctc_qspi_remove(struct platform_device *pdev) +{ + struct spi_master *master = platform_get_drvdata(pdev); + + spi_unregister_master(master); + return 0; +} + +static const struct of_device_id ctc_qspi_match[] = { + { + .compatible = "ctc, igdaxi001a-qspi", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, ctc_qspi_match); + +/* Structure for a device driver */ +static struct platform_driver ctc_qspi_driver = { + .driver = { + .name = "ctc-qspi", + .of_match_table = ctc_qspi_match, + }, + .probe = ctc_qspi_probe, + .remove = ctc_qspi_remove, +}; + +module_platform_driver(ctc_qspi_driver); + +MODULE_AUTHOR("Centec, Inc."); +MODULE_LICENSE("GPL"); diff --git a/platform/centec/centec-dal/Makefile b/platform/centec/centec-dal/Makefile new file mode 100644 index 000000000000..a0837a80cd18 --- /dev/null +++ b/platform/centec/centec-dal/Makefile @@ -0,0 +1,7 @@ +ifeq ($(CONFIGURED_ARCH), arm64) +EXTRA_CFLAGS += -DSOC_ACTIVE +EXTRA_CFLAGS += -DDMA_MEM_MODE_PLATFORM +endif + +obj-m := dal.o +dal-y := dal_kernel.o dal_mpool.o diff --git a/platform/centec/centec-dal/dal_common.h b/platform/centec/centec-dal/dal_common.h new file mode 100644 index 000000000000..d8d4d6a67c0d --- /dev/null +++ b/platform/centec/centec-dal/dal_common.h @@ -0,0 +1,119 @@ +/** + @file dal.h + + @author Copyright (C) 2012 Centec Networks Inc. All rights reserved. + + @date 2012-4-9 + + @version v2.0 + +*/ +#ifndef _DAL_COMMON_H_ +#define _DAL_COMMON_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define DAL_MAX_CHIP_NUM 8 /* DAL support max chip num is 8 */ +#define DAL_MAX_INTR_NUM 8 + +#define DAL_NETIF_T_PORT 0 +#define DAL_NETIF_T_VLAN 1 + +#define DAL_MAX_KNET_NETIF 64 +#define DAL_MAX_KNET_NAME_LEN 32 + +enum dal_operate_code_e +{ + DAL_OP_CREATE, + DAL_OP_DESTORY, + DAL_OP_GET, + DAL_OP_MAX, +}; +typedef enum dal_operate_code_e dal_operate_code_t; + +struct dal_dma_info_s +{ + unsigned int lchip; + unsigned int phy_base; + unsigned int phy_base_hi; + unsigned int size; + unsigned int knet_tx_offset; + unsigned int knet_tx_size; + unsigned int* virt_base; +}; +typedef struct dal_dma_info_s dal_dma_info_t; + +struct dal_dma_chan_s +{ + unsigned char lchip; + unsigned char channel_id; + unsigned char dmasel; + unsigned char active; + unsigned short current_index; + unsigned short desc_num; + unsigned short desc_depth; + unsigned short data_size; + unsigned long long mem_base; + void* virt_base; /**< don't use when register chan*/ + unsigned char* p_desc_used; /**< don't use when register chan*/ +}; +typedef struct dal_dma_chan_s dal_dma_chan_t; + +struct dal_netif_s +{ + unsigned char op_type; + unsigned char netif_id; + unsigned char type; + unsigned char lchip; + unsigned short vlan; + unsigned int gport; + unsigned char mac[6]; + char name[DAL_MAX_KNET_NAME_LEN]; +}; +typedef struct dal_netif_s dal_netif_t; + +/** + @brief define dal error type +*/ +enum dal_err_e +{ + DAL_E_NONE = 0, /**< NO error */ + DAL_E_INVALID_PTR = -1000, /**< invalid pointer */ + DAL_E_INVALID_FD = -999, /**< invalid FD */ + DAL_E_TIME_OUT = -998, /**< time out */ + DAL_E_INVALID_ACCESS = -997, /**< invalid access type*/ + DAL_E_MPOOL_NOT_CREATE = -996, /**< mpool not create*/ + DAL_E_INVALID_IRQ = -995, + DAL_E_DEV_NOT_FOUND = -994, + DAL_E_EXCEED_MAX = -993, + DAL_E_NOT_INIT = -992, + DAL_E_ENVALID_MSI_PARA = -991, + + DAL_E_ERROR_CODE_END +}; + +enum dal_access_type_e +{ + DAL_PCI_IO, /* [HB]humber is access as pci device, using ioctrl */ + DAL_SUPER_IF, /* [HB]humber is controled by fpga device */ + DAL_PCIE_MM, /* [GB]Gb is access as pcie device, using mmap */ + DAL_SPECIAL_EMU, /* [GB]special for emulation */ + DAL_MAX_ACCESS_TYPE +}; +typedef enum dal_access_type_e dal_access_type_t; + +struct dal_pci_dev_s +{ + unsigned int busNo; + unsigned int devNo; + unsigned int funNo; +}; +typedef struct dal_pci_dev_s dal_pci_dev_t; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/platform/centec/centec-dal/dal_kernel.c b/platform/centec/centec-dal/dal_kernel.c new file mode 100644 index 000000000000..23fc6e736575 --- /dev/null +++ b/platform/centec/centec-dal/dal_kernel.c @@ -0,0 +1,2234 @@ +/** + @file dal_kernal.c + + @date 2012-10-18 + + @version v2.0 + + +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) +#include +#endif +#include "dal_kernel.h" +#include "dal_common.h" +#include "dal_mpool.h" +#include +#if defined(SOC_ACTIVE) +#include +#endif +MODULE_AUTHOR("Centec Networks Inc."); +MODULE_DESCRIPTION("DAL kernel module"); +MODULE_LICENSE("GPL"); + +/* DMA memory pool size */ +static char* dma_pool_size; +module_param(dma_pool_size, charp, 0); +MODULE_PARM_DESC(dma_pool_size, + "Specify DMA memory pool size (default 4MB)"); + +/***************************************************************************** + * defines + *****************************************************************************/ +#define MB_SIZE 0x100000 +#define CTC_MAX_INTR_NUM 8 + +#define MEM_MAP_RESERVE SetPageReserved +#define MEM_MAP_UNRESERVE ClearPageReserved + +#define CTC_VENDOR_VID 0xc001 +#define CTC_HUMBER_DEVICE_ID 0x6048 +#define CTC_GOLDENGATE_DEVICE_ID 0xc010 +#define CTC_PCIE_VENDOR_ID 0xcb10 +#define CTC_DUET2_DEVICE_ID 0x7148 +#define CTC_TSINGMA_DEVICE_ID 0x5236 + +#define MEM_MAP_RESERVE SetPageReserved +#define MEM_MAP_UNRESERVE ClearPageReserved + +#define CTC_GREATBELT_DEVICE_ID 0x03e8 /* TBD */ +#define DAL_MAX_CHIP_NUM 8 +#define VIRT_TO_PAGE(p) virt_to_page((p)) +#define DAL_UNTAG_BLOCK 0 +#define DAL_DISCARD_BLOCK 1 +#define DAL_MATCHED_BLOCK 2 +#define DAL_CUR_MATCH_BLOCk 3 +/***************************************************************************** + * typedef + *****************************************************************************/ +typedef enum dal_cpu_mode_type_e +{ + DAL_CPU_MODE_TYPE_NONE, + DAL_CPU_MODE_TYPE_PCIE, /*use pcie*/ + DAL_CPU_MODE_TYPE_LOCAL, /*use local bus*/ + DAL_CPU_MODE_MAX_TYPE, + +} dal_cpu_mode_type_t; +/* Control Data */ +typedef struct dal_isr_s +{ + int irq; + void (* isr)(void*); + void (* isr_knet)(void*); + void* isr_data; + void* isr_knet_data; + int trigger; + int count; + wait_queue_head_t wqh; +} dal_isr_t; + +#if defined(SOC_ACTIVE) +typedef struct dal_kernel_local_dev_s +{ + struct list_head list; + struct platform_device* pci_dev; + + /* PCI I/O mapped base address */ + void __iomem * logic_address; + + /* Physical address */ + uintptr phys_address; +} dal_kern_local_dev_t; +#endif + +typedef struct dal_kernel_pcie_dev_s +{ + struct list_head list; + struct pci_dev* pci_dev; + + /* PCI I/O mapped base address */ + uintptr logic_address; + + /* Physical address */ + unsigned long long phys_address; +} dal_kern_pcie_dev_t; + +typedef struct _dma_segment +{ + struct list_head list; + unsigned long req_size; /* Requested DMA segment size */ + unsigned long blk_size; /* DMA block size */ + unsigned long blk_order; /* DMA block size in alternate format */ + unsigned long seg_size; /* Current DMA segment size */ + unsigned long seg_begin; /* Logical address of segment */ + unsigned long seg_end; /* Logical end address of segment */ + unsigned long* blk_ptr; /* Array of logical DMA block addresses */ + int blk_cnt_max; /* Maximum number of block to allocate */ + int blk_cnt; /* Current number of blocks allocated */ +} dma_segment_t; + +typedef irqreturn_t (*p_func) (int irq, void* dev_id); + +/*************************************************************************** + *declared + ***************************************************************************/ +static unsigned int linux_dal_poll0(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll1(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll2(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll3(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll4(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll5(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll6(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll7(struct file* filp, struct poll_table_struct* p); + +/***************************************************************************** + * global variables + *****************************************************************************/ +static void* dal_dev[DAL_MAX_CHIP_NUM]={0}; +static dal_isr_t dal_isr[CTC_MAX_INTR_NUM]; +#if defined(SOC_ACTIVE) +static dal_isr_t dal_int[CTC_MAX_INTR_NUM] = {0}; +#endif +static int dal_chip_num = 0; +static int dal_version = 0; +static int dal_intr_num = 0; +static int use_high_memory = 0; +static unsigned int* dma_virt_base[DAL_MAX_CHIP_NUM]; +static unsigned long long dma_phy_base[DAL_MAX_CHIP_NUM]; +static unsigned int dma_mem_size = 0xc00000; +static unsigned int msi_irq_base[DAL_MAX_CHIP_NUM]; +static unsigned int msi_irq_num[DAL_MAX_CHIP_NUM]; +static unsigned int msi_used = 0; +static unsigned int active_type[DAL_MAX_CHIP_NUM] = {0}; +static struct class *dal_class; + +static LIST_HEAD(_dma_seg); +static int dal_debug = 0; +module_param(dal_debug, int, 0); +MODULE_PARM_DESC(dal_debug, "Set debug level (default 0)"); + +static struct pci_device_id dal_id_table[] = +{ + {PCI_DEVICE(CTC_VENDOR_VID, CTC_GREATBELT_DEVICE_ID)}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_GOLDENGATE_DEVICE_ID)}, + {PCI_DEVICE((CTC_PCIE_VENDOR_ID+1), (CTC_GOLDENGATE_DEVICE_ID+1))}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_DUET2_DEVICE_ID)}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_TSINGMA_DEVICE_ID)}, + {0, }, +}; +#if defined(SOC_ACTIVE) +static const struct of_device_id linux_dal_of_match[] = { + { .compatible = "centec,dal-localbus",}, + {}, +}; +MODULE_DEVICE_TABLE(of, linux_dal_of_match); +#endif + +static wait_queue_head_t poll_intr[CTC_MAX_INTR_NUM]; + +p_func intr_handler_fun[CTC_MAX_INTR_NUM]; + +static int poll_intr_trigger[CTC_MAX_INTR_NUM]; + +static struct file_operations dal_intr_fops[CTC_MAX_INTR_NUM] = +{ + { + .owner = THIS_MODULE, + .poll = linux_dal_poll0, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll1, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll2, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll3, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll4, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll5, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll6, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll7, + }, +}; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +#include +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt +#endif +/***************************************************************************** + * macros + *****************************************************************************/ +#define VERIFY_CHIP_INDEX(n) (n < dal_chip_num) + +#define _KERNEL_INTERUPT_PROCESS +static irqreturn_t +intr0_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + + if(poll_intr_trigger[0]) + { + return IRQ_HANDLED; + } + + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[0] = 1; + wake_up(&poll_intr[0]); + } + + if (p_dal_isr->isr_knet) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr1_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + + if(poll_intr_trigger[1]) + { + return IRQ_HANDLED; + } + + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[1] = 1; + wake_up(&poll_intr[1]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr2_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[2]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[2] = 1; + wake_up(&poll_intr[2]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr3_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[3]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[3] = 1; + wake_up(&poll_intr[3]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr4_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[4]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[4] = 1; + wake_up(&poll_intr[4]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr5_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[5]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[5] = 1; + wake_up(&poll_intr[5]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr6_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[6]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[6] = 1; + wake_up(&poll_intr[6]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr7_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[7]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[7] = 1; + wake_up(&poll_intr[7]); + } + } + + return IRQ_HANDLED; +} + +int +dal_interrupt_register(unsigned int irq, int prio, void (* isr)(void*), void* data) +{ + int ret; + unsigned char str[16]; + unsigned char* int_name = NULL; + unsigned int intr_num_tmp = 0; + unsigned int intr_num = CTC_MAX_INTR_NUM; + unsigned long irq_flags = 0; + + if (dal_intr_num >= CTC_MAX_INTR_NUM) + { + printk("Interrupt numbers exceeds max.\n"); + return -1; + } + + if (msi_used) + { + int_name = "dal_msi"; + } + else + { + int_name = "dal_intr"; + } + + + for (intr_num_tmp=0;intr_num_tmp < CTC_MAX_INTR_NUM; intr_num_tmp++) + { + if (irq == dal_isr[intr_num_tmp].irq) + { + if (0 == msi_used) + { + dal_isr[intr_num_tmp].count++; + printk("Interrupt irq %d register count %d.\n", irq, dal_isr[intr_num_tmp].count); + } + return 0; + } + if ((0 == dal_isr[intr_num_tmp].irq) && (CTC_MAX_INTR_NUM == intr_num)) + { + intr_num = intr_num_tmp; + dal_isr[intr_num].count = 0; + } + } + dal_isr[intr_num].irq = irq; + dal_isr[intr_num].isr = isr; + dal_isr[intr_num].isr_data = data; + dal_isr[intr_num].count++; + + init_waitqueue_head(&poll_intr[intr_num]); + + /* only user mode */ + if ((NULL == isr) && (NULL == data)) + { + snprintf(str, 16, "%s%d", "dal_intr", intr_num); + ret = register_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_num, + str, &dal_intr_fops[intr_num]); + if (ret < 0) + { + printk("Register character device for irq %d failed, ret= %d", irq, ret); + return ret; + } + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) + irq_flags = 0; +#else + irq_flags = IRQF_DISABLED; +#endif + if ((ret = request_irq(irq, + intr_handler_fun[intr_num], + irq_flags, + int_name, + &dal_isr[intr_num])) < 0) + { + printk("Cannot request irq %d, ret %d.\n", irq, ret); + unregister_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_num, str); + } + + if (0 == ret) + { + dal_intr_num++; + } + + return ret; +} + +int +dal_interrupt_unregister(unsigned int irq) +{ + unsigned char str[16]; + int intr_idx = 0; + int find_flag = 0; + + /* get intr device index */ + for (intr_idx = 0; intr_idx < CTC_MAX_INTR_NUM; intr_idx++) + { + if (dal_isr[intr_idx].irq == irq) + { + find_flag = 1; + break; + } + } + + if (find_flag == 0) + { + printk ("irq%d is not registered! unregister failed \n", irq); + return -1; + } + + dal_isr[intr_idx].count--; + if (0 != dal_isr[intr_idx].count) + { + printk("Interrupt irq %d unregister count %d.\n", irq, dal_isr[intr_idx].count); + return -1; + } + snprintf(str, 16, "%s%d", "dal_intr", intr_idx); + + unregister_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_idx, str); + + free_irq(irq, &dal_isr[intr_idx]); + + dal_isr[intr_idx].irq = 0; + + dal_intr_num--; + + return 0; +} + +int +dal_interrupt_connect(unsigned int irq, int prio, void (* isr)(void*), void* data) +{ + int irq_idx = 0; + + for (irq_idx = 0; irq_idx < dal_intr_num; irq_idx++) + { + if (dal_isr[irq_idx].irq == irq) + { + dal_isr[irq_idx].isr_knet = isr; + dal_isr[irq_idx].isr_knet_data = data; + + return 0; + } + } + + return -1; +} + +int +dal_interrupt_disconnect(unsigned int irq) +{ + int irq_idx = 0; + + for (irq_idx = 0; irq_idx < dal_intr_num; irq_idx++) + { + if (dal_isr[irq_idx].irq == irq) + { + dal_isr[irq_idx].isr_knet = NULL; + dal_isr[irq_idx].isr_knet_data = NULL; + + return 0; + } + } + + return -1; +} + +static dal_ops_t g_dal_ops = +{ + interrupt_connect:dal_interrupt_connect, + interrupt_disconnect:dal_interrupt_disconnect, +}; + +int +dal_get_dal_ops(dal_ops_t **dal_ops) +{ + *dal_ops = &g_dal_ops; + + return 0; +} + +int +dal_interrupt_set_en(unsigned int irq, unsigned int enable) +{ + enable ? enable_irq(irq) : disable_irq_nosync(irq); + return 0; +} + +static int +_dal_set_msi_enabe(unsigned int lchip, unsigned int irq_num) +{ + int ret = 0; + dal_kern_pcie_dev_t* dev = NULL; + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + dev = dal_dev[lchip]; + if (NULL == dev) + { + return -1; + } + if (irq_num == 1) + { + ret = pci_enable_msi(dev->pci_dev); + if (ret) + { + printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + pci_disable_msi(dev->pci_dev); + msi_used = 0; + } + + msi_irq_base[lchip] = dev->pci_dev->irq; + msi_irq_num[lchip] = 1; + } + else + { +#if 0 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 79)) + ret = pci_enable_msi_exact(dev->pci_dev, irq_num); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 26, 32)) + ret = pci_enable_msi_block(dev->pci_dev, irq_num); +#else + ret = -1; +#endif + if (ret) + { + printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + pci_disable_msi(dev->pci_dev); + msi_used = 0; + } + + msi_irq_base[lchip] = dev->pci_dev->irq; + msi_irq_num[lchip] = irq_num; +#endif + } + } + + return ret; +} + +static int +_dal_set_msi_disable(unsigned int lchip) +{ + dal_kern_pcie_dev_t* dev = NULL; + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + dev = dal_dev[lchip]; + if (NULL == dev) + { + return -1; + } + pci_disable_msi(dev->pci_dev); + + msi_irq_base[lchip] = 0; + msi_irq_num[lchip] = 0; + } + + return 0; +} + +int +dal_set_msi_cap(unsigned long arg) +{ + int ret = 0; + int index = 0; + dal_msi_info_t msi_info; + + if (copy_from_user(&msi_info, (void*)arg, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + + printk("####dal_set_msi_cap lchip %d base %d num:%d\n", msi_info.lchip, msi_info.irq_base, msi_info.irq_num); + if (DAL_CPU_MODE_TYPE_PCIE == active_type[msi_info.lchip]) + { + if (msi_info.irq_num > 0) + { + if (0 == msi_used) + { + msi_used = 1; + ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num); + } + else if ((1 == msi_used) && (msi_info.irq_num != msi_irq_num[msi_info.lchip])) + { + for (index = 0; index < msi_irq_num[msi_info.lchip]; index++) + { + dal_interrupt_unregister(msi_irq_base[msi_info.lchip]+index); + } + _dal_set_msi_disable(msi_info.lchip); + msi_used = 1; + ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num); + } + } + else + { + msi_used = 0; + ret = _dal_set_msi_disable(msi_info.lchip); + } + } + + return ret; +} + +int +dal_user_interrupt_register(unsigned long arg) +{ + int irq = 0; + if (copy_from_user(&irq, (void*)arg, sizeof(int))) + { + return -EFAULT; + } + printk("####register interrupt irq:%d\n", irq); + return dal_interrupt_register(irq, 0, NULL, NULL); +} + +int +dal_user_interrupt_unregister(unsigned long arg) +{ + int irq = 0; + if (copy_from_user(&irq, (void*)arg, sizeof(int))) + { + return -EFAULT; + } + printk("####unregister interrupt irq:%d\n", irq); + return dal_interrupt_unregister(irq); +} + +int +dal_user_interrupt_set_en(unsigned long arg) +{ + dal_intr_parm_t dal_intr_parm; + + if (copy_from_user(&dal_intr_parm, (void*)arg, sizeof(dal_intr_parm_t))) + { + return -EFAULT; + } + + return dal_interrupt_set_en(dal_intr_parm.irq, dal_intr_parm.enable); +} + +/* + * Function: _dal_dma_segment_free + */ + +/* + * Function: _find_largest_segment + * + * Purpose: + * Find largest contiguous segment from a pool of DMA blocks. + * Parameters: + * dseg - DMA segment descriptor + * Returns: + * 0 on success, < 0 on error. + * Notes: + * Assembly stops if a segment of the requested segment size + * has been obtained. + * + * Lower address bits of the DMA blocks are used as follows: + * 0: Untagged + * 1: Discarded block + * 2: Part of largest contiguous segment + * 3: Part of current contiguous segment + */ +#ifndef DMA_MEM_MODE_PLATFORM +static int +_dal_find_largest_segment(dma_segment_t* dseg) +{ + int i, j, blks, found; + unsigned long seg_begin; + unsigned long seg_end; + unsigned long seg_tmp; + + blks = dseg->blk_cnt; + + /* Clear all block tags */ + for (i = 0; i < blks; i++) + { + dseg->blk_ptr[i] &= ~3; + } + + for (i = 0; i < blks && dseg->seg_size < dseg->req_size; i++) + { + /* First block must be an untagged block */ + if ((dseg->blk_ptr[i] & 3) == DAL_UNTAG_BLOCK) + { + /* Initial segment size is the block size */ + seg_begin = dseg->blk_ptr[i]; + seg_end = seg_begin + dseg->blk_size; + dseg->blk_ptr[i] |= DAL_CUR_MATCH_BLOCk; + + /* Loop looking for adjacent blocks */ + do + { + found = 0; + + for (j = i + 1; j < blks && (seg_end - seg_begin) < dseg->req_size; j++) + { + seg_tmp = dseg->blk_ptr[j]; + /* Check untagged blocks only */ + if ((seg_tmp & 3) == DAL_UNTAG_BLOCK) + { + if (seg_tmp == (seg_begin - dseg->blk_size)) + { + /* Found adjacent block below current segment */ + dseg->blk_ptr[j] |= DAL_CUR_MATCH_BLOCk; + seg_begin = seg_tmp; + found = 1; + } + else if (seg_tmp == seg_end) + { + /* Found adjacent block above current segment */ + dseg->blk_ptr[j] |= DAL_CUR_MATCH_BLOCk; + seg_end += dseg->blk_size; + found = 1; + } + } + } + } + while (found); + + if ((seg_end - seg_begin) > dseg->seg_size) + { + /* The current block is largest so far */ + dseg->seg_begin = seg_begin; + dseg->seg_end = seg_end; + dseg->seg_size = seg_end - seg_begin; + + /* Re-tag current and previous largest segment */ + for (j = 0; j < blks; j++) + { + if ((dseg->blk_ptr[j] & 3) == DAL_CUR_MATCH_BLOCk) + { + /* Tag current segment as the largest */ + dseg->blk_ptr[j] &= ~1; + } + else if ((dseg->blk_ptr[j] & 3) == DAL_MATCHED_BLOCK) + { + /* Discard previous largest segment */ + dseg->blk_ptr[j] ^= 3; + } + } + } + else + { + /* Discard all blocks in current segment */ + for (j = 0; j < blks; j++) + { + if ((dseg->blk_ptr[j] & 3) == DAL_CUR_MATCH_BLOCk) + { + dseg->blk_ptr[j] &= ~2; + } + } + } + } + } + + return 0; +} + +/* + * Function: _alloc_dma_blocks + */ +static int +_dal_alloc_dma_blocks(dma_segment_t* dseg, int blks) +{ + int i, start; + unsigned long addr; + + if (dseg->blk_cnt + blks > dseg->blk_cnt_max) + { + printk("No more DMA blocks\n"); + return -1; + } + + start = dseg->blk_cnt; + dseg->blk_cnt += blks; + + for (i = start; i < dseg->blk_cnt; i++) + { + addr = __get_free_pages(GFP_ATOMIC, dseg->blk_order); + if (addr) + { + dseg->blk_ptr[i] = addr; + } + else + { + printk("DMA allocation failed\n"); + return -1; + } + } + + return 0; +} + +/* + * Function: _dal_dma_segment_alloc + */ +static dma_segment_t* +_dal_dma_segment_alloc(unsigned int size, unsigned int blk_size) +{ + dma_segment_t* dseg; + int i, blk_ptr_size; + unsigned long page_addr; + struct sysinfo si; + + /* Sanity check */ + if (size == 0 || blk_size == 0) + { + return NULL; + } + + /* Allocate an initialize DMA segment descriptor */ + if ((dseg = kmalloc(sizeof(dma_segment_t), GFP_ATOMIC)) == NULL) + { + return NULL; + } + + memset(dseg, 0, sizeof(dma_segment_t)); + dseg->req_size = size; + dseg->blk_size = PAGE_ALIGN(blk_size); + + while ((PAGE_SIZE << dseg->blk_order) < dseg->blk_size) + { + dseg->blk_order++; + } + + si_meminfo(&si); + dseg->blk_cnt_max = (si.totalram << PAGE_SHIFT) / dseg->blk_size; + blk_ptr_size = dseg->blk_cnt_max * sizeof(unsigned long); + /* Allocate an initialize DMA block pool */ + dseg->blk_ptr = kmalloc(blk_ptr_size, GFP_KERNEL); + if (dseg->blk_ptr == NULL) + { + kfree(dseg); + return NULL; + } + + memset(dseg->blk_ptr, 0, blk_ptr_size); + /* Allocate minimum number of blocks */ + _dal_alloc_dma_blocks(dseg, dseg->req_size / dseg->blk_size); + + /* Allocate more blocks until we have a complete segment */ + do + { + _dal_find_largest_segment(dseg); + if (dseg->seg_size >= dseg->req_size) + { + break; + } + } + while (_dal_alloc_dma_blocks(dseg, 8) == 0); + + /* Reserve all pages in the DMA segment and free unused blocks */ + for (i = 0; i < dseg->blk_cnt; i++) + { + if ((dseg->blk_ptr[i] & 3) == 2) + { + dseg->blk_ptr[i] &= ~3; + + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) + { + MEM_MAP_RESERVE(VIRT_TO_PAGE((void*)page_addr)); + } + } + else if (dseg->blk_ptr[i]) + { + dseg->blk_ptr[i] &= ~3; + free_pages(dseg->blk_ptr[i], dseg->blk_order); + dseg->blk_ptr[i] = 0; + } + } + + return dseg; +} + +/* + * Function: _dal_dma_segment_free + */ +static void +_dal_dma_segment_free(dma_segment_t* dseg) +{ + int i; + unsigned long page_addr; + + if (dseg->blk_ptr) + { + for (i = 0; i < dseg->blk_cnt; i++) + { + if (dseg->blk_ptr[i]) + { + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) + { + MEM_MAP_UNRESERVE(VIRT_TO_PAGE(page_addr)); + } + + free_pages(dseg->blk_ptr[i], dseg->blk_order); + } + } + + kfree(dseg->blk_ptr); + kfree(dseg); + } +} + +/* + * Function: -dal_pgalloc + */ +static void* +_dal_pgalloc(unsigned int size) +{ + dma_segment_t* dseg; + unsigned int blk_size; + + blk_size = (size < DMA_BLOCK_SIZE) ? size : DMA_BLOCK_SIZE; + if ((dseg = _dal_dma_segment_alloc(size, blk_size)) == NULL) + { + return NULL; + } + + if (dseg->seg_size < size) + { + /* If we didn't get the full size then forget it */ + printk("Notice: Can not get enough memory for requset!!\n"); + printk("actual size:0x%lx, request size:0x%x\n", dseg->seg_size, size); + /*-_dal_dma_segment_free(dseg);*/ + /*-return NULL;*/ + } + + list_add(&dseg->list, &_dma_seg); + return (void*)dseg->seg_begin; +} + +/* + * Function: _dal_pgfree + */ +static int +_dal_pgfree(void* ptr) +{ + struct list_head* pos; + + list_for_each(pos, &_dma_seg) + { + dma_segment_t* dseg = list_entry(pos, dma_segment_t, list); + if (ptr == (void*)dseg->seg_begin) + { + list_del(&dseg->list); + _dal_dma_segment_free(dseg); + return 0; + } + } + return -1; +} +#endif + +static void +dal_alloc_dma_pool(int lchip, int size) +{ +#if defined(DMA_MEM_MODE_PLATFORM) || defined(SOC_ACTIVE) + struct device * dev = NULL; +#endif + + if (use_high_memory) + { + dma_phy_base[lchip] = virt_to_bus(high_memory); + dma_virt_base[lchip] = ioremap_nocache(dma_phy_base[lchip], size); + } + else + { +#if defined(DMA_MEM_MODE_PLATFORM) || defined(SOC_ACTIVE) + if ((DAL_CPU_MODE_TYPE_PCIE != active_type[lchip]) && (DAL_CPU_MODE_TYPE_LOCAL != active_type[lchip])) + { + printk("active type %d error, not cpu and soc!\n", active_type[lchip]); + return; + } + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + dev = &(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev->dev); + } +#if defined (SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + dev = &(((dal_kern_local_dev_t*)(dal_dev[lchip]))->pci_dev->dev); + } +#endif + dma_virt_base[lchip] = dma_alloc_coherent(dev, dma_mem_size, + &dma_phy_base[lchip], GFP_KERNEL); + + printk("dma_phy_base[lchip] 0x%llx dma_virt_base[lchip] %p \n", dma_phy_base[lchip], dma_virt_base[lchip]); + printk(KERN_WARNING "########Using DMA_MEM_MODE_PLATFORM \n"); +#else + /* Get DMA memory from kernel */ + dma_virt_base[lchip] = _dal_pgalloc(size); + dma_phy_base[lchip] = virt_to_bus(dma_virt_base[lchip]); + //dma_virt_base [lchip]= ioremap_nocache(dma_phy_base[lchip], size); +#endif + } +} + +static void +dal_free_dma_pool(int lchip) +{ + int ret = 0; +#if defined(DMA_MEM_MODE_PLATFORM) || defined(SOC_ACTIVE) + struct device * dev = NULL; +#endif + + ret = ret; + if (use_high_memory) + { + iounmap(dma_virt_base[lchip]); + } + else + { +#if defined(DMA_MEM_MODE_PLATFORM) || defined(SOC_ACTIVE) + if ((DAL_CPU_MODE_TYPE_PCIE != active_type[lchip]) && (DAL_CPU_MODE_TYPE_LOCAL != active_type[lchip])) + { + return; + } + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + dev = &(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev->dev); + } +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + dev = &(((dal_kern_local_dev_t*)(dal_dev[lchip]))->pci_dev->dev); + } +#endif + dma_free_coherent(dev, dma_mem_size, + dma_virt_base[lchip], dma_phy_base[lchip]); +#else + iounmap(dma_virt_base[lchip]); + ret = _dal_pgfree(dma_virt_base[lchip]); + if(ret<0) + { + printk("Dma free memory fail !!!!!! \n"); + } +#endif + } +} + +#define _KERNEL_DAL_IO +static int +_dal_pci_read(unsigned char lchip, unsigned int offset, unsigned int* value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + if ((DAL_CPU_MODE_TYPE_PCIE != active_type[lchip]) && (DAL_CPU_MODE_TYPE_LOCAL != active_type[lchip])) + { + return -1; + } + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + *value = *(volatile unsigned int*)(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->logic_address + offset); + } +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + *value = *(volatile unsigned int*)(((dal_kern_local_dev_t*)(dal_dev[lchip]))->logic_address + offset); + } +#endif + return 0; +} + +int +dal_create_irq_mapping(unsigned long arg) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) + +#ifndef NO_IRQ +#define NO_IRQ (-1) +#endif + dal_irq_mapping_t irq_map; + + if (copy_from_user(&irq_map, (void*)arg, sizeof(dal_irq_mapping_t))) + { + return -EFAULT; + } + + irq_map.sw_irq = irq_create_mapping(NULL, irq_map.hw_irq); + if (irq_map.sw_irq == NO_IRQ) + { + printk("IRQ mapping fail !!!!!! \n"); + return -1; + } + + if (copy_to_user((dal_irq_mapping_t*)arg, (void*)&irq_map, sizeof(dal_irq_mapping_t))) + { + return -EFAULT; + } +#endif + return 0; +} + +int +dal_pci_read(unsigned long arg) +{ + dal_chip_parm_t cmdpara_chip; + + if (copy_from_user(&cmdpara_chip, (void*)arg, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + _dal_pci_read((unsigned char)cmdpara_chip.lchip, (unsigned int)cmdpara_chip.reg_addr, + (unsigned int*)(&(cmdpara_chip.value))); + + if (copy_to_user((dal_chip_parm_t*)arg, (void*)&cmdpara_chip, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + return 0; +} + +static int +_dal_pci_write(unsigned char lchip, unsigned int offset, unsigned int value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + if ((DAL_CPU_MODE_TYPE_PCIE != active_type[lchip]) && (DAL_CPU_MODE_TYPE_LOCAL != active_type[lchip])) + { + return -1; + } + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + *(volatile unsigned int*)(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->logic_address + offset) = value; + } +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + *(volatile unsigned int*)(((dal_kern_local_dev_t*)(dal_dev[lchip]))->logic_address + offset) = value; + } +#endif + + return 0; +} + +int +dal_pci_write(unsigned long arg) +{ + dal_chip_parm_t cmdpara_chip; + + if (copy_from_user(&cmdpara_chip, (void*)arg, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + _dal_pci_write((unsigned char)cmdpara_chip.lchip, (unsigned int)cmdpara_chip.reg_addr, + (unsigned int)cmdpara_chip.value); + + return 0; +} + +int +dal_pci_conf_read(unsigned char lchip, unsigned int offset, unsigned int* value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + pci_read_config_dword(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev, offset, value); + } + + return 0; +} + +int +dal_pci_conf_write(unsigned char lchip, unsigned int offset, unsigned int value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + pci_write_config_dword(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev, offset, value); + } + + return 0; +} +int +dal_user_read_pci_conf(unsigned long arg) +{ + dal_pci_cfg_ioctl_t dal_cfg; + + if (copy_from_user(&dal_cfg, (void*)arg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + if (dal_pci_conf_read(dal_cfg.lchip, dal_cfg.offset, &dal_cfg.value)) + { + printk("dal_pci_conf_read failed.\n"); + return -EFAULT; + } + + if (copy_to_user((dal_pci_cfg_ioctl_t*)arg, (void*)&dal_cfg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + return 0; +} + +int +dal_user_write_pci_conf(unsigned long arg) +{ + dal_pci_cfg_ioctl_t dal_cfg; + + if (copy_from_user(&dal_cfg, (void*)arg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + return dal_pci_conf_write(dal_cfg.lchip, dal_cfg.offset, dal_cfg.value); +} + +static int +linux_get_device(unsigned long arg) +{ + dal_user_dev_t user_dev; + int lchip = 0; + + if (copy_from_user(&user_dev, (void*)arg, sizeof(user_dev))) + { + return -EFAULT; + } + + user_dev.chip_num = dal_chip_num; + lchip = user_dev.lchip; + + if (lchip < dal_chip_num) + { + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + user_dev.phy_base0 = (unsigned int)((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->phys_address; + user_dev.phy_base1 = (unsigned int)(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->phys_address >> 32); + user_dev.bus_no = ((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev->bus->number; + user_dev.dev_no = ((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev->device; + user_dev.fun_no = ((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev->devfn; + user_dev.soc_active = 0; + } +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + user_dev.phy_base0 = (unsigned int)((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->phys_address; + user_dev.phy_base1 = (unsigned int)(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->phys_address >> 32); + user_dev.bus_no = 0; + user_dev.dev_no = CTC_TSINGMA_DEVICE_ID; + user_dev.fun_no = 0; + user_dev.soc_active = 1; + } +#endif + } + + if (copy_to_user((dal_user_dev_t*)arg, (void*)&user_dev, sizeof(user_dev))) + { + return -EFAULT; + } + + return 0; +} + +/* set dal version, copy to user */ +static int +linux_get_dal_version(unsigned long arg) +{ + int dal_ver = VERSION_1DOT2; /* set dal version */ + + if (copy_to_user((int*)arg, (void*)&dal_ver, sizeof(dal_ver))) + { + return -EFAULT; + } + + dal_version = dal_ver; /* up sw */ + + return 0; +} + +static int +linux_get_dma_info(unsigned long arg) +{ + dal_dma_info_t dma_para; + + if (copy_from_user(&dma_para, (void*)arg, sizeof(dal_dma_info_t))) + { + return -EFAULT; + } + + dma_para.phy_base = (unsigned int)dma_phy_base[dma_para.lchip]; + dma_para.phy_base_hi = dma_phy_base[dma_para.lchip] >> 32; + dma_para.virt_base = dma_virt_base[dma_para.lchip]; + dma_para.size = dma_mem_size; + + printk("dal dma phy addr: 0x%llx, virt addr: %p.\n", dma_phy_base[dma_para.lchip], dma_virt_base[dma_para.lchip]); + + if (copy_to_user((dal_dma_info_t*)arg, (void*)&dma_para, sizeof(dal_dma_info_t))) + { + return -EFAULT; + } + + return 0; +} + +static int +dal_get_msi_info(unsigned long arg) +{ + dal_msi_info_t msi_para; + unsigned int lchip = 0; + + /* get lchip form user mode */ + if (copy_from_user(&msi_para, (void*)arg, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + lchip = msi_para.lchip; + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + msi_para.irq_base = msi_irq_base[lchip]; + msi_para.irq_num = msi_irq_num[lchip]; + } +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + msi_para.irq_base = dal_int[0].irq; + msi_para.irq_num = CTC_MAX_INTR_NUM; + } +#endif + + /* send msi info to user mode */ + if (copy_to_user((dal_msi_info_t*)arg, (void*)&msi_para, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + + return 0; +} + + +static int +dal_get_intr_info(unsigned long arg) +{ + dal_intr_info_t intr_para; + unsigned int intr_num = 0; + + /* get lchip form user mode */ + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_intr_info_t))) + { + return -EFAULT; + } + + intr_para.irq_idx = CTC_MAX_INTR_NUM; + for (intr_num=0; intr_num< CTC_MAX_INTR_NUM; intr_num++) + { + if (intr_para.irq == dal_isr[intr_num].irq) + { + intr_para.irq_idx = intr_num; + break; + } + } + + if (CTC_MAX_INTR_NUM == intr_para.irq_idx) + { + printk("Interrupt %d cann't find.\n", intr_para.irq); + } + /* send msi info to user mode */ + if (copy_to_user((dal_intr_info_t*)arg, (void*)&intr_para, sizeof(dal_intr_info_t))) + { + return -EFAULT; + } + + return 0; +} + +int +dal_cache_inval(unsigned long ptr, unsigned int length) +{ +#ifdef DMA_CACHE_COHERENCE_EN + /*dma_cache_wback_inv((unsigned long)intr_para.ptr, intr_para.length);*/ + + dma_sync_single_for_cpu(NULL, ptr, length, DMA_FROM_DEVICE); + + /*dma_cache_sync(NULL, (void*)bus_to_virt(intr_para.ptr), intr_para.length, DMA_FROM_DEVICE);*/ +#endif + return 0; +} + +int +dal_cache_flush(unsigned long ptr, unsigned int length) +{ +#ifdef DMA_CACHE_COHERENCE_EN + /*dma_cache_wback_inv(intr_para.ptr, intr_para.length);*/ + + dma_sync_single_for_device(NULL, ptr, length, DMA_TO_DEVICE); + + /*dma_cache_sync(NULL, (void*)bus_to_virt(intr_para.ptr), intr_para.length, DMA_TO_DEVICE);*/ +#endif + return 0; +} + +static int +dal_user_cache_inval(unsigned long arg) +{ +#ifndef DMA_MEM_MODE_PLATFORM + dal_dma_cache_info_t intr_para; + + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_dma_cache_info_t))) + { + return -EFAULT; + } + + dal_cache_inval(intr_para.ptr, intr_para.length); +#endif + return 0; +} + +static int +dal_user_cache_flush(unsigned long arg) +{ +#ifndef DMA_MEM_MODE_PLATFORM + dal_dma_cache_info_t intr_para; + + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_dma_cache_info_t))) + { + return -EFAULT; + } + + dal_cache_flush(intr_para.ptr, intr_para.length); +#endif + return 0; +} + +#if defined(SOC_ACTIVE) +static int linux_dal_local_probe(struct platform_device *pdev) +{ + dal_kern_local_dev_t* dev = NULL; + unsigned int temp = 0; + unsigned int lchip = 0; + int i = 0; + int irq = 0; + struct resource * res = NULL; + + printk(KERN_WARNING "********found soc dal device*****\n"); + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + if (NULL == dal_dev[lchip]) + { + break; + } + } + + if (lchip >= DAL_MAX_CHIP_NUM) + { + printk("Exceed max local chip num\n"); + return -1; + } + + if (NULL == dal_dev[lchip]) + { + dal_dev[lchip] = kmalloc(sizeof(dal_kern_local_dev_t), GFP_ATOMIC); + if (NULL == dal_dev[lchip]) + { + printk("no memory for dal soc dev, lchip %d\n", lchip); + return -1; + } + } + dev = dal_dev[lchip]; + if (NULL == dev) + { + printk("Cannot obtain PCI resources\n"); + } + + lchip = lchip; + dal_chip_num += 1; + + dev->pci_dev = pdev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dev->phys_address = res->start; + dev->logic_address = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dev->logic_address)) + { + kfree(dev); + return PTR_ERR(dev->logic_address); + } + + for (i = 0; i < CTC_MAX_INTR_NUM; i++) + { + irq = platform_get_irq(pdev, i); + if (irq < 0) + { + printk( "can't get irq number\n"); + kfree(dev); + return irq; + } + dal_int[i].irq = irq; + printk( "irq %d vector %d\n", i, irq); + } + + active_type[lchip] = DAL_CPU_MODE_TYPE_LOCAL; + _dal_pci_read(lchip, 0x48, &temp); + if (((temp >> 8) & 0xffff) == 0x3412) + { + printk("Little endian Cpu detected!!! \n"); + _dal_pci_write(lchip, 0x48, 0xFFFFFFFF); + } + + /* alloc dma_mem_size for every chip */ + if (dma_mem_size) + { + dal_alloc_dma_pool(lchip, dma_mem_size); + + /*add check Dma memory pool cannot cross 4G space*/ + if ((0==(dma_phy_base[lchip]>>32)) && (0!=((dma_phy_base[lchip]+dma_mem_size)>>32))) + { + printk("Dma malloc memory cross 4G space!!!!!! \n"); + kfree(dev); + return -1; + } + } + + printk(KERN_WARNING "linux_dal_probe end*****\n"); + + return 0; +} +#endif + +int linux_dal_pcie_probe(struct pci_dev* pdev, const struct pci_device_id* id) +{ + dal_kern_pcie_dev_t* dev = NULL; + unsigned int temp = 0; + unsigned int lchip = 0; + int bar = 0; + int ret = 0; + /*unsigned int devid = 0;*/ + + printk(KERN_WARNING "********found cpu dal device*****\n"); + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + if (NULL == dal_dev[lchip]) + { + break; + } + } + + if (lchip >= DAL_MAX_CHIP_NUM) + { + printk("Exceed max local chip num\n"); + return -1; + } + + if (NULL == dal_dev[lchip]) + { + dal_dev[lchip] = kmalloc(sizeof(dal_kern_pcie_dev_t), GFP_ATOMIC); + if (NULL == dal_dev[lchip]) + { + printk("no memory for dal cpu dev, lchip %d\n", lchip); + return -1; + } + } + dev = dal_dev[lchip]; + if (NULL == dev) + { + printk("Cannot obtain PCI resources\n"); + } + + lchip = lchip; + dal_chip_num += 1; + + dev->pci_dev = pdev; + + if (pdev->device == 0x5236) + { + printk("use bar2 to config memory space\n"); + bar = 2; + } + + if (pci_enable_device(pdev) < 0) + { + printk("Cannot enable PCI device: vendor id = %x, device id = %x\n", + pdev->vendor, pdev->device); + } + + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (ret) + { + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) + { + printk("Could not set PCI DMA Mask\n"); + kfree(dev); + return ret; + } + } + + if (pci_request_regions(pdev, DAL_NAME) < 0) + { + printk("Cannot obtain PCI resources\n"); + } + + dev->phys_address = pci_resource_start(pdev, bar); + dev->logic_address = (uintptr)ioremap_nocache(dev->phys_address, + pci_resource_len(dev->pci_dev, bar)); + + active_type[lchip] = DAL_CPU_MODE_TYPE_PCIE; + + _dal_pci_read(lchip, 0x48, &temp); + if (((temp >> 8) & 0xffff) == 0x3412) + { + printk("Little endian Cpu detected!!! \n"); + _dal_pci_write(lchip, 0x48, 0xFFFFFFFF); + } + + pci_set_master(pdev); + + + /* alloc dma_mem_size for every chip */ + if (dma_mem_size) + { + dal_alloc_dma_pool(lchip, dma_mem_size); + + /*add check Dma memory pool cannot cross 4G space*/ + if ((0==(dma_phy_base[lchip]>>32)) && (0!=((dma_phy_base[lchip]+dma_mem_size)>>32))) + { + printk("Dma malloc memory cross 4G space!!!!!! \n"); + kfree(dev); + return -1; + } + } + + printk(KERN_WARNING "linux_dal_probe end*****\n"); + + return 0; +} + +#if defined(SOC_ACTIVE) +static int +linux_dal_local_remove(struct platform_device *pdev) +{ + unsigned int lchip = 0; + unsigned int flag = 0; + dal_kern_local_dev_t* dev = NULL; + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + dev = dal_dev[lchip]; + if ((NULL != dev )&& (pdev == dev->pci_dev)) + { + flag = 1; + break; + } + } + + if (1 == flag) + { + dal_free_dma_pool(lchip); + dev->pci_dev = NULL; + kfree(dev); + dal_chip_num--; + active_type[lchip] = DAL_CPU_MODE_TYPE_NONE; + } + + return 0; +} +#endif + +void +linux_dal_pcie_remove(struct pci_dev* pdev) +{ + unsigned int lchip = 0; + unsigned int flag = 0; + dal_kern_pcie_dev_t* dev = NULL; + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + dev = dal_dev[lchip]; + if ((NULL != dev )&& (pdev == dev->pci_dev)) + { + flag = 1; + break; + } + } + + if (1 == flag) + { + dal_free_dma_pool(lchip); + pci_release_regions(pdev); + pci_disable_device(pdev); + dev->pci_dev = NULL; + kfree(dev); + dal_chip_num--; + active_type[lchip] = DAL_CPU_MODE_TYPE_NONE; + } +} + +#ifdef CONFIG_COMPAT +static long +linux_dal_ioctl(struct file* file, + unsigned int cmd, unsigned long arg) +#else + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) +static long +linux_dal_ioctl(struct file* file, + unsigned int cmd, unsigned long arg) +#else +static int +linux_dal_ioctl(struct inode* inode, struct file* file, + unsigned int cmd, unsigned long arg) +#endif + +#endif +{ + switch (cmd) + { + + case CMD_READ_CHIP: + return dal_pci_read(arg); + + case CMD_WRITE_CHIP: + return dal_pci_write(arg); + + case CMD_GET_DEVICES: + return linux_get_device(arg); + + case CMD_GET_DAL_VERSION: + return linux_get_dal_version(arg); + + case CMD_GET_DMA_INFO: + return linux_get_dma_info(arg); + + case CMD_PCI_CONFIG_READ: + return dal_user_read_pci_conf(arg); + + case CMD_PCI_CONFIG_WRITE: + return dal_user_write_pci_conf(arg); + + case CMD_REG_INTERRUPTS: + return dal_user_interrupt_register(arg); + + case CMD_UNREG_INTERRUPTS: + return dal_user_interrupt_unregister(arg); + + case CMD_EN_INTERRUPTS: + return dal_user_interrupt_set_en(arg); + + case CMD_SET_MSI_CAP: + return dal_set_msi_cap(arg); + + case CMD_GET_MSI_INFO: + return dal_get_msi_info(arg); + + case CMD_IRQ_MAPPING: + return dal_create_irq_mapping(arg); + + case CMD_GET_INTR_INFO: + return dal_get_intr_info(arg); + + case CMD_CACHE_INVAL: + return dal_user_cache_inval(arg); + + case CMD_CACHE_FLUSH: + return dal_user_cache_flush(arg); + + default: + break; + } + + return 0; +} + +static unsigned int +linux_dal_poll0(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[0], p); + local_irq_save(flags); + if (poll_intr_trigger[0]) + { + poll_intr_trigger[0] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll1(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[1], p); + local_irq_save(flags); + if (poll_intr_trigger[1]) + { + poll_intr_trigger[1] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll2(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[2], p); + local_irq_save(flags); + if (poll_intr_trigger[2]) + { + poll_intr_trigger[2] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll3(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[3], p); + local_irq_save(flags); + if (poll_intr_trigger[3]) + { + poll_intr_trigger[3] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll4(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[4], p); + local_irq_save(flags); + if (poll_intr_trigger[4]) + { + poll_intr_trigger[4] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll5(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[5], p); + local_irq_save(flags); + if (poll_intr_trigger[5]) + { + poll_intr_trigger[5] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll6(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[6], p); + local_irq_save(flags); + if (poll_intr_trigger[6]) + { + poll_intr_trigger[6] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll7(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[7], p); + local_irq_save(flags); + if (poll_intr_trigger[7]) + { + poll_intr_trigger[7] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static struct pci_driver linux_dal_pcie_driver = +{ + .name = DAL_NAME, + .id_table = dal_id_table, + .probe = linux_dal_pcie_probe, + .remove = linux_dal_pcie_remove, +}; +#if defined(SOC_ACTIVE) +static struct platform_driver linux_dal_local_driver = +{ + .probe = linux_dal_local_probe, + .remove = linux_dal_local_remove, + .driver = { + .name = DAL_NAME, + .of_match_table = of_match_ptr(linux_dal_of_match), + }, +}; +#endif + +static struct file_operations fops = +{ + .owner = THIS_MODULE, +#ifdef CONFIG_COMPAT + .compat_ioctl = linux_dal_ioctl, + .unlocked_ioctl = linux_dal_ioctl, +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) + .unlocked_ioctl = linux_dal_ioctl, +#else + .ioctl = linux_dal_ioctl, +#endif +#endif +}; + +static int __init +linux_dal_init(void) +{ + int ret = 0; + + /* Get DMA memory pool size form dal.ok input param, or use default dma_mem_size */ + if (dma_pool_size) + { + if ((dma_pool_size[strlen(dma_pool_size) - 1] & ~0x20) == 'M') + { + dma_mem_size = simple_strtoul(dma_pool_size, NULL, 0); + printk("dma_mem_size: 0x%x \n", dma_mem_size); + + dma_mem_size *= MB_SIZE; + } + else + { + printk("DMA memory pool size must be specified as e.g. dma_pool_size=8M\n"); + } + + if (dma_mem_size & (dma_mem_size - 1)) + { + printk("dma_mem_size must be a power of 2 (1M, 2M, 4M, 8M etc.)\n"); + dma_mem_size = 0; + } + } + + ret = register_chrdev(DAL_DEV_MAJOR, DAL_NAME, &fops); + if (ret < 0) + { + printk(KERN_WARNING "Register linux_dal device, ret %d\n", ret); + return ret; + } + + ret = pci_register_driver(&linux_dal_pcie_driver); + if (ret < 0) + { + printk(KERN_WARNING "Register ASIC PCI driver failed, ret %d\n", ret); + return ret; + } +#if defined(SOC_ACTIVE) + ret = platform_driver_register(&linux_dal_local_driver); + if (ret < 0) + { + printk(KERN_WARNING "Register ASIC LOCALBUS driver failed, ret %d\n", ret); + } +#endif + + /* alloc /dev/linux_dal node */ + dal_class = class_create(THIS_MODULE, DAL_NAME); + device_create(dal_class, NULL, MKDEV(DAL_DEV_MAJOR, 0), NULL, DAL_NAME); + + /* init interrupt function */ + intr_handler_fun[0] = intr0_handler; + intr_handler_fun[1] = intr1_handler; + intr_handler_fun[2] = intr2_handler; + intr_handler_fun[3] = intr3_handler; + intr_handler_fun[4] = intr4_handler; + intr_handler_fun[5] = intr5_handler; + intr_handler_fun[6] = intr6_handler; + intr_handler_fun[7] = intr7_handler; + + return ret; +} + +static void __exit +linux_dal_exit(void) +{ + device_destroy(dal_class, MKDEV(DAL_DEV_MAJOR, 0)); + class_destroy(dal_class); + unregister_chrdev(DAL_DEV_MAJOR, "linux_dal"); + pci_unregister_driver(&linux_dal_pcie_driver); +#if defined(SOC_ACTIVE) + platform_driver_unregister(&linux_dal_local_driver); +#endif +} + +module_init(linux_dal_init); +module_exit(linux_dal_exit); +EXPORT_SYMBOL(dal_get_dal_ops); +EXPORT_SYMBOL(dal_cache_inval); +EXPORT_SYMBOL(dal_cache_flush); + diff --git a/platform/centec/centec-dal/dal_kernel.h b/platform/centec/centec-dal/dal_kernel.h new file mode 100644 index 000000000000..1055dba26952 --- /dev/null +++ b/platform/centec/centec-dal/dal_kernel.h @@ -0,0 +1,180 @@ +/** + @file dal_kernel_io.h + + @author Copyright (C) 2012 Centec Networks Inc. All rights reserved. + + @date 2012-4-9 + + @version v2.0 + +*/ +#ifndef _DAL_KERNEL_H_ +#define _DAL_KERNEL_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(CONFIG_RESOURCES_64BIT) || defined(CONFIG_PHYS_ADDR_T_64BIT) +#define PHYS_ADDR_IS_64BIT +#endif + +#ifndef SDK_IN_USERMODE +#ifdef PHYS_ADDR_IS_64BIT +typedef long long intptr; +typedef unsigned long long uintptr; +#else +typedef int intptr; +typedef unsigned int uintptr; +#endif +#endif + +#ifndef STATIC +#define STATIC static +#endif +#define DAL_PCI_READ_ADDR 0x0 +#define DAL_PCI_READ_DATA 0xc +#define DAL_PCI_WRITE_ADDR 0x8 +#define DAL_PCI_WRITE_DATA 0x4 +#define DAL_PCI_STATUS 0x10 + +#define DAL_PCI_STATUS_IN_PROCESS 31 +#define DAL_PCI_STATUS_BAD_PARITY 5 +#define DAL_PCI_STATUS_CPU_ACCESS_ERR 4 +#define DAL_PCI_STATUS_READ_CMD 3 +#define DAL_PCI_STATUS_REGISTER_ERR 1 +#define DAL_PCI_STATUS_REGISTER_ACK 0 + +#define DAL_PCI_ACCESS_TIMEOUT 0x64 + +#define DAL_NAME "linux_dal" /* "linux_dal" */ + +#define DAL_DEV_MAJOR 198 + +#define DAL_DEV_INTR_MAJOR_BASE 200 + +#define DAL_DEV_NAME "/dev/" DAL_NAME +#define DAL_ONE_KB 1024 +#define DAL_ONE_MB (1024*1024) +struct dal_chip_parm_s +{ + unsigned int lchip; /*tmp should be uint8*/ + unsigned int fpga_id; /*tmp add*/ + unsigned int reg_addr; + unsigned int value; +}; +typedef struct dal_chip_parm_s dal_chip_parm_t; + +struct dal_intr_parm_s +{ + unsigned int irq; + unsigned int enable; +}; +typedef struct dal_intr_parm_s dal_intr_parm_t; + +struct dal_irq_mapping_s +{ + unsigned int hw_irq; + unsigned int sw_irq; +}; +typedef struct dal_irq_mapping_s dal_irq_mapping_t; + +struct dal_user_dev_s +{ + unsigned int chip_num; /*output: local chip number*/ + unsigned int lchip; /*input: local chip id*/ + unsigned int phy_base0; /* low 32bits physical base address */ + unsigned int phy_base1; /* high 32bits physical base address */ + unsigned int bus_no; + unsigned int dev_no; + unsigned int fun_no; + unsigned int soc_active; + void* virt_base[2]; /* !!!!warning!!!!Virtual base address; pointer void* must be last member */ +}; +typedef struct dal_user_dev_s dal_user_dev_t; + +struct dal_pci_cfg_ioctl_s +{ + unsigned int lchip; /* Device ID */ + unsigned int offset; + unsigned int value; +}; +typedef struct dal_pci_cfg_ioctl_s dal_pci_cfg_ioctl_t; + +struct dal_msi_info_s +{ + unsigned int lchip; + unsigned int irq_base; + unsigned int irq_num; +}; +typedef struct dal_msi_info_s dal_msi_info_t; + +struct dal_intr_info_s +{ + unsigned int irq; + unsigned int irq_idx; +}; +typedef struct dal_intr_info_s dal_intr_info_t; + +struct dal_dma_cache_info_s +{ + unsigned long ptr; + unsigned int length; +}; +typedef struct dal_dma_cache_info_s dal_dma_cache_info_t; + +#define CMD_MAGIC 'C' +#define CMD_WRITE_CHIP _IO(CMD_MAGIC, 0) /* for humber ioctrol*/ +#define CMD_READ_CHIP _IO(CMD_MAGIC, 1) /* for humber ioctrol*/ +#define CMD_GET_DEVICES _IO(CMD_MAGIC, 2) +#define CMD_GET_DAL_VERSION _IO(CMD_MAGIC, 3) +#define CMD_PCI_CONFIG_WRITE _IO(CMD_MAGIC, 4) +#define CMD_PCI_CONFIG_READ _IO(CMD_MAGIC, 5) +#define CMD_GET_DMA_INFO _IO(CMD_MAGIC, 6) +#define CMD_REG_INTERRUPTS _IO(CMD_MAGIC, 7) +#define CMD_UNREG_INTERRUPTS _IO(CMD_MAGIC, 8) +#define CMD_EN_INTERRUPTS _IO(CMD_MAGIC, 9) +#define CMD_I2C_READ _IO(CMD_MAGIC, 10) +#define CMD_I2C_WRITE _IO(CMD_MAGIC, 11) +#define CMD_GET_MSI_INFO _IO(CMD_MAGIC, 12) +#define CMD_SET_MSI_CAP _IO(CMD_MAGIC, 13) +#define CMD_IRQ_MAPPING _IO(CMD_MAGIC, 14) +#define CMD_GET_INTR_INFO _IO(CMD_MAGIC, 15) +#define CMD_CACHE_INVAL _IO(CMD_MAGIC, 16) +#define CMD_CACHE_FLUSH _IO(CMD_MAGIC, 17) +#define CMD_GET_KNET_VERSION _IO(CMD_MAGIC, 18) +#define CMD_CONNECT_INTERRUPTS _IO(CMD_MAGIC, 19) +#define CMD_DISCONNECT_INTERRUPTS _IO(CMD_MAGIC, 20) +#define CMD_SET_DMA_INFO _IO(CMD_MAGIC, 21) +#define CMD_REG_DMA_CHAN _IO(CMD_MAGIC, 22) +#define CMD_HANDLE_NETIF _IO(CMD_MAGIC, 23) + +enum dal_version_e +{ + VERSION_MIN, + VERSION_1DOT0, + VERSION_1DOT1, + VERSION_1DOT2, + + VERSION_MAX +}; +typedef enum dal_version_e dal_version_t; + +struct dal_ops_s { + int (*interrupt_connect)(unsigned int irq, int prio, void (*)(void*), void *data); + int (*interrupt_disconnect)(unsigned int irq); +}; +typedef struct dal_ops_s dal_ops_t; + +/* We try to assemble a contiguous segment from chunks of this size */ +#define DMA_BLOCK_SIZE (512 * DAL_ONE_KB) + +extern int dal_get_dal_ops(dal_ops_t **dal_ops); +extern int dal_cache_inval(unsigned long ptr, unsigned int length); +extern int dal_cache_flush(unsigned long ptr, unsigned int length); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/platform/centec/centec-dal/dal_mpool.c b/platform/centec/centec-dal/dal_mpool.c new file mode 100644 index 000000000000..f3b5f85e5ecd --- /dev/null +++ b/platform/centec/centec-dal/dal_mpool.c @@ -0,0 +1,360 @@ + +/*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ +//#include "sal.h" +#include "dal_mpool.h" +#define DAL_MAX_CHIP_NUM 32 +#ifdef __KERNEL__ +#include +#include + +#define DAL_MALLOC(x) kmalloc(x, GFP_ATOMIC) +#define DAL_FREE(x) kfree(x) + +static spinlock_t dal_mpool_lock[DAL_MAX_CHIP_NUM]; +#define MPOOL_LOCK_INIT() spin_lock_init(&dal_mpool_lock[lchip]) +#define MPOOL_LOCK_DEINIT() +#define MPOOL_LOCK() unsigned long flags; spin_lock_irqsave(&dal_mpool_lock[lchip], flags) +#define MPOOL_UNLOCK() spin_unlock_irqrestore(&dal_mpool_lock[lchip], flags) +#define DAL_PRINT(fmt,arg...) printk(fmt,##arg) +#else /* !__KERNEL__*/ + +#include +#include "sal.h" +#define DAL_MALLOC(x) sal_malloc(x) +#define DAL_FREE(x) sal_free(x) +static sal_mutex_t* dal_mpool_lock[DAL_MAX_CHIP_NUM]; +#define MPOOL_LOCK_INIT() sal_mutex_create(&dal_mpool_lock[lchip]) +#define MPOOL_LOCK_DEINIT() sal_mutex_destroy(dal_mpool_lock[lchip]) +#define MPOOL_LOCK() sal_mutex_lock(dal_mpool_lock[lchip]) +#define MPOOL_UNLOCK() sal_mutex_unlock(dal_mpool_lock[lchip]) +#define DAL_PRINT(fmt,arg...) sal_printf(fmt,##arg) + +#endif /* __KERNEL__ */ +dal_mpool_mem_t* g_free_block_ptr = NULL; + +/* System cache line size */ +#ifndef DAL_CACHE_LINE_BYTES +#define DAL_CACHE_LINE_BYTES 256 +#endif + +static dal_mpool_mem_t* p_desc_pool[DAL_MAX_CHIP_NUM] = {0}; +static dal_mpool_mem_t* p_data_pool[DAL_MAX_CHIP_NUM] = {0}; + +/*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ +int +dal_mpool_init(uint8_t lchip) +{ + MPOOL_LOCK_INIT(); + return 0; +} +/*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ +int +dal_mpool_deinit(uint8_t lchip) +{ + MPOOL_LOCK_DEINIT(); + return 0; +} + +dal_mpool_mem_t* +_dal_mpool_create(void* base, int size, int type) +{ + dal_mpool_mem_t* head = NULL; + dal_mpool_mem_t* tail = NULL; + + head = (dal_mpool_mem_t*)DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (head == NULL) + { + return NULL; + } + + tail = (dal_mpool_mem_t*)DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (tail == NULL) + { + DAL_FREE(head); + return NULL; + } + + head->size = tail->size = 0; + head->type = type; + head->address = base; + tail->address = head->address + size; + head->next = tail; + tail->next = NULL; + + return head; +} + +dal_mpool_mem_t* +dal_mpool_create(unsigned char lchip, void* base, int size) +{ + dal_mpool_mem_t* head = NULL; + int mod = (int)(((unsigned long)base) & (DAL_CACHE_LINE_BYTES - 1)); + + MPOOL_LOCK(); + + if (mod) + { + base = (char*)base + (DAL_CACHE_LINE_BYTES - mod); + size -= (DAL_CACHE_LINE_BYTES - mod); + } + + size &= ~(DAL_CACHE_LINE_BYTES - 1); + + /* init for common linkptr, only used for GB */ + head = _dal_mpool_create(base, size, DAL_MPOOL_TYPE_USELESS); + if (NULL == head) + { + MPOOL_UNLOCK(); + return NULL; + } + + /* init for desc linkptr */ + p_desc_pool[lchip] = _dal_mpool_create(base, DAL_MPOOL_MAX_DESX_SIZE, DAL_MPOOL_TYPE_DESC); + if (NULL == p_desc_pool[lchip]) + { + MPOOL_UNLOCK(); + DAL_FREE(head->next); + DAL_FREE(head); + return NULL; + } + + /* init for data linkptr */ + p_data_pool[lchip] = _dal_mpool_create(((char*)base+DAL_MPOOL_MAX_DESX_SIZE), (size - DAL_MPOOL_MAX_DESX_SIZE), DAL_MPOOL_TYPE_DATA); + if (NULL == p_data_pool[lchip]) + { + MPOOL_UNLOCK(); + DAL_FREE(head->next); + DAL_FREE(head); + DAL_FREE(p_desc_pool[lchip]->next); + DAL_FREE(p_desc_pool[lchip]); + return NULL; + } + + MPOOL_UNLOCK(); + + return head; +} + +dal_mpool_mem_t* +_dal_mpool_alloc_comon(dal_mpool_mem_t* ptr, int size, int type) +{ + dal_mpool_mem_t* new_ptr = NULL; + + while (ptr && ptr->next) + { + if (ptr->next->address - (ptr->address + ptr->size) >= size) + { + break; + } + + ptr = ptr->next; + } + + if (!(ptr && ptr->next)) + { + return NULL; + } + + new_ptr = DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (!new_ptr) + { + return NULL; + } + + new_ptr->type = type; + new_ptr->address = ptr->address + ptr->size; + new_ptr->size = size; + new_ptr->next = ptr->next; + ptr->next = new_ptr; + + return new_ptr; +} + +void* +dal_mpool_alloc(unsigned char lchip, dal_mpool_mem_t* pool, int size, int type) +{ + dal_mpool_mem_t* ptr = NULL; + dal_mpool_mem_t* new_ptr = NULL; + int mod; + + MPOOL_LOCK(); + + mod = size & (DAL_CACHE_LINE_BYTES - 1); + if (mod != 0) + { + size += (DAL_CACHE_LINE_BYTES - mod); + } + + switch(type) + { + case DAL_MPOOL_TYPE_USELESS: + ptr = pool; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + case DAL_MPOOL_TYPE_DESC: + ptr = p_desc_pool[lchip]; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + case DAL_MPOOL_TYPE_DATA: + ptr = p_data_pool[lchip]; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + default: + MPOOL_UNLOCK(); + return NULL; + break; + } + + MPOOL_UNLOCK(); + if( NULL == new_ptr ) + { + return NULL; + } + + return new_ptr->address; +} + +void +_dal_mpool_free(dal_mpool_mem_t* ptr, void* addr, int type) +{ + unsigned char* address = (unsigned char*)addr; + dal_mpool_mem_t* prev = NULL; + + while (ptr && ptr->next) + { + if (ptr->next->address == address) + { + break; + } + + ptr = ptr->next; + } + + if (ptr && ptr->next) + { + prev = ptr; + ptr = ptr->next; + prev->next = ptr->next; + DAL_FREE(ptr); + } + + return; +} + +void +dal_mpool_free(unsigned char lchip, dal_mpool_mem_t* pool, void* addr) +{ + dal_mpool_mem_t* ptr = pool; + + MPOOL_LOCK(); + + switch(pool->type) + { + case DAL_MPOOL_TYPE_USELESS: + ptr = pool; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_USELESS); + break; + case DAL_MPOOL_TYPE_DESC: + ptr = p_desc_pool[lchip]; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_DESC); + break; + case DAL_MPOOL_TYPE_DATA: + ptr = p_data_pool[lchip]; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_DATA); + break; + default: + break; + } + + MPOOL_UNLOCK(); + return; +} + +int +dal_mpool_destroy(unsigned char lchip, dal_mpool_mem_t* pool) +{ + dal_mpool_mem_t* ptr, * next; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + for (ptr = p_desc_pool[lchip]; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + for (ptr = p_data_pool[lchip]; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + MPOOL_UNLOCK(); + + return 0; +} + +int +dal_mpool_usage(dal_mpool_mem_t* pool, int type) +{ + int usage = 0; + dal_mpool_mem_t* ptr; + /*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ + uint8_t lchip = 0; + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = ptr->next) + { + if (ptr->type == type || ptr->type == -1) + { + usage += ptr->size; + } + } + + MPOOL_UNLOCK(); + + return usage; +} + +int +dal_mpool_debug(dal_mpool_mem_t* pool) +{ + dal_mpool_mem_t* ptr; + int index = 0; + /*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ + uint8_t lchip = 0; + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = ptr->next) + { + /* DAL_PRINT("%2dst mpool block: address=0x%8x, size=0x%x \n", index, (unsigned int)ptr->address, ptr->size);*/ + DAL_PRINT("%2dst mpool block: address=%p, size=0x%x \n", index, ptr->address, ptr->size); /* note*/ + index++; + } + + MPOOL_UNLOCK(); + + return 0; +} + diff --git a/platform/centec/centec-dal/dal_mpool.h b/platform/centec/centec-dal/dal_mpool.h new file mode 100644 index 000000000000..4c2e3487e394 --- /dev/null +++ b/platform/centec/centec-dal/dal_mpool.h @@ -0,0 +1,74 @@ +/** + @file dal_mpool.h + + @author Copyright (C) 2011 Centec Networks Inc. All rights reserved. + + @date 2012-5-10 + + @version v2.0 + + This file contains the dma memory init, allocation and free APIs +*/ + +#ifndef _DMA_MPOOL_H +#define _DMA_MPOOL_H +#ifdef __cplusplus +extern "C" { +#endif + +#define DAL_MPOOL_MAX_DESX_SIZE (1024*1024) + +enum dal_mpool_type_e +{ + DAL_MPOOL_TYPE_USELESS, /* just compatible with GB */ + DAL_MPOOL_TYPE_DESC, /* dma mpool op for desc */ + DAL_MPOOL_TYPE_DATA /* dma mpool op for data */ +}; +typedef enum dal_mpool_type_e dal_mpool_type_t; + +struct dal_mpool_mem_s +{ + unsigned char* address; + int size; + int type; + struct dal_mpool_mem_s* next; +}; +typedef struct dal_mpool_mem_s dal_mpool_mem_t; + +/** + @brief This function is to alloc dma memory + + @param[in] size size of memory + + @return NULL + +*/ +extern int +dal_mpool_init(unsigned char lchip); + +extern int +dal_mpool_deinit(unsigned char lchip); + +extern dal_mpool_mem_t* +dal_mpool_create(unsigned char lchip, void* base_ptr, int size); + +extern void* +dal_mpool_alloc(unsigned char lchip, dal_mpool_mem_t* pool, int size, int type); + +extern void +dal_mpool_free(unsigned char lchip, dal_mpool_mem_t* pool, void* addr); + +extern int +dal_mpool_destroy(unsigned char lchip, dal_mpool_mem_t* pool); + +extern int +dal_mpool_usage(dal_mpool_mem_t* pool, int type); + +extern int +dal_mpool_debug(dal_mpool_mem_t* pool); +#ifdef __cplusplus +} +#endif + +#endif /* !_DMA_MPOOL_H */ + diff --git a/platform/centec/docker-syncd-centec-rpc.mk b/platform/centec/docker-syncd-centec-rpc.mk new file mode 100644 index 000000000000..6b912185b7da --- /dev/null +++ b/platform/centec/docker-syncd-centec-rpc.mk @@ -0,0 +1,23 @@ +# docker image for centec syncd with rpc + +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) $(PTF) +$(DOCKER_SYNCD_CENTEC_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_CENTEC_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_CENTEC_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_CENTEC_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_CENTEC_RPC) +endif + +$(DOCKER_SYNCD_CENTEC_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += --privileged -t +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/centec/docker-syncd-centec-rpc/Dockerfile.j2 b/platform/centec/docker-syncd-centec-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..bec9c7f4426b --- /dev/null +++ b/platform/centec/docker-syncd-centec-rpc/Dockerfile.j2 @@ -0,0 +1,57 @@ +FROM docker-syncd-centec + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_centec_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get purge -y syncd + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + python-setuptools \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_centec_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip2 install cffi==1.7.0 \ + && pip2 install --upgrade cffi==1.7.0 \ + && pip2 install wheel \ + && pip2 install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/centec/docker-syncd-centec-rpc/ptf_nn_agent.conf b/platform/centec/docker-syncd-centec-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/centec/docker-syncd-centec-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/centec/docker-syncd-centec.mk b/platform/centec/docker-syncd-centec.mk new file mode 100644 index 000000000000..75cc45c28559 --- /dev/null +++ b/platform/centec/docker-syncd-centec.mk @@ -0,0 +1,17 @@ +# docker image for centec syncd + +DOCKER_SYNCD_PLATFORM_CODE = centec +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) + +$(DOCKER_SYNCD_CENTEC)_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) + +$(DOCKER_SYNCD_CENTEC)_RUN_OPT += --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/Dockerfile.j2 b/platform/centec/docker-syncd-centec/Dockerfile.j2 new file mode 100755 index 000000000000..ce3b47bcdd77 --- /dev/null +++ b/platform/centec/docker-syncd-centec/Dockerfile.j2 @@ -0,0 +1,33 @@ +FROM docker-config-engine-buster + +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 + +COPY \ +{% for deb in docker_syncd_centec_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_syncd_centec_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +## TODO: add kmod into Depends +RUN apt-get install -yf kmod + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin/"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] 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..61e290e3189e --- /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 program syncd|syncd with path "/usr/bin/process_checker syncd /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/platform/centec/docker-syncd-centec/critical_processes b/platform/centec/docker-syncd-centec/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/centec/docker-syncd-centec/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/platform/centec/docker-syncd-centec/supervisord.conf b/platform/centec/docker-syncd-centec/supervisord.conf new file mode 100644 index 000000000000..6df1893a0be0 --- /dev/null +++ b/platform/centec/docker-syncd-centec/supervisord.conf @@ -0,0 +1,37 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python2 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE + +[eventlistener:supervisor-proc-exit-listener] +command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running diff --git a/platform/centec/libsaithrift-dev.mk b/platform/centec/libsaithrift-dev.mk new file mode 100644 index 000000000000..fdcbfd664e1f --- /dev/null +++ b/platform/centec/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_amd64.deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(CENTEC_SAI) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(CENTEC_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_amd64.deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_amd64.deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(BRCM_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_amd64.deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/centec/one-image.mk b/platform/centec/one-image.mk new file mode 100644 index 000000000000..a92c97078846 --- /dev/null +++ b/platform/centec/one-image.mk @@ -0,0 +1,16 @@ +# sonic centec one image installer + +SONIC_ONE_IMAGE = sonic-centec.bin +$(SONIC_ONE_IMAGE)_MACHINE = centec +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS = $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E582_48X6Q_PLATFORM_MODULE) \ + $(CENTEC_E582_48X2Q4Z_PLATFORM_MODULE) \ + $(EMBEDWAY_ES6220_PLATFORM_MODULE) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/centec/platform-modules-centec-e582.mk b/platform/centec/platform-modules-centec-e582.mk new file mode 100644 index 000000000000..e86c428a7403 --- /dev/null +++ b/platform/centec/platform-modules-centec-e582.mk @@ -0,0 +1,19 @@ +# Centec E582-48X6Q Platform modules + + +CENTEC_E582_48X6Q_PLATFORM_MODULE_VERSION =1.1 +CENTEC_E582_48X2Q4Z_PLATFORM_MODULE_VERSION =1.1 + +export CENTEC_E582_48X6Q_PLATFORM_MODULE_VERSION +export CENTEC_E582_48X2Q4Z_PLATFORM_MODULE_VERSION + +CENTEC_E582_48X6Q_PLATFORM_MODULE = platform-modules-e582-48x6q_$(CENTEC_E582_48X6Q_PLATFORM_MODULE_VERSION)_amd64.deb + +$(CENTEC_E582_48X6Q_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-e582 +$(CENTEC_E582_48X6Q_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(CENTEC_E582_48X6Q_PLATFORM_MODULE)_PLATFORM = x86_64-centec_e582_48x6q-r0 +SONIC_DPKG_DEBS += $(CENTEC_E582_48X6Q_PLATFORM_MODULE) + +CENTEC_E582_48X2Q4Z_PLATFORM_MODULE = platform-modules-e582-48x2q4z_$(CENTEC_E582_48X2Q4Z_PLATFORM_MODULE_VERSION)_amd64.deb +$(CENTEC_E582_48X2Q4Z_PLATFORM_MODULE)_PLATFORM = x86_64-centec_e582_48x2q4z-r0 +$(eval $(call add_extra_package,$(CENTEC_E582_48X6Q_PLATFORM_MODULE),$(CENTEC_E582_48X2Q4Z_PLATFORM_MODULE))) diff --git a/platform/centec/platform-modules-embedway.mk b/platform/centec/platform-modules-embedway.mk new file mode 100644 index 000000000000..c2ddfc327542 --- /dev/null +++ b/platform/centec/platform-modules-embedway.mk @@ -0,0 +1,12 @@ +# embedway es6220 Platform modules + +EMBEDWAY_ES6220_PLATFORM_MODULE_VERSION =1.1 + +export EMBEDWAY_ES6220_PLATFORM_MODULE_VERSION + +EMBEDWAY_ES6220_PLATFORM_MODULE = platform-modules-embedway-es6220_$(EMBEDWAY_ES6220_PLATFORM_MODULE_VERSION)_amd64.deb + +$(EMBEDWAY_ES6220_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-embedway +$(EMBEDWAY_ES6220_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(EMBEDWAY_ES6220_PLATFORM_MODULE)_PLATFORM = x86_64-ew_es6220_x48q2h4-r0 +SONIC_DPKG_DEBS += $(EMBEDWAY_ES6220_PLATFORM_MODULE) diff --git a/platform/centec/platform.conf b/platform/centec/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/centec/rules.mk b/platform/centec/rules.mk new file mode 100644 index 000000000000..182248ec1ac6 --- /dev/null +++ b/platform/centec/rules.mk @@ -0,0 +1,20 @@ +include $(PLATFORM_PATH)/platform-modules-centec-e582.mk +include $(PLATFORM_PATH)/platform-modules-embedway.mk +include $(PLATFORM_PATH)/sdk.mk +include $(PLATFORM_PATH)/docker-syncd-centec.mk +include $(PLATFORM_PATH)/docker-syncd-centec-rpc.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) + +# Inject centec sai into syncd +$(SYNCD)_DEPENDS += $(CENTEC_SAI) +$(SYNCD)_UNINSTALLS += $(CENTEC_SAI) + +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV) +endif + +# Runtime dependency on centec sai is set only for syncd +$(SYNCD)_RDEPENDS += $(CENTEC_SAI) diff --git a/platform/centec/sdk.mk b/platform/centec/sdk.mk new file mode 100644 index 000000000000..588b2b244130 --- /dev/null +++ b/platform/centec/sdk.mk @@ -0,0 +1,6 @@ +# Centec SAI +CENTEC_SAI = libsai_1.6.3-1_amd64.deb +$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/amd64/$(CENTEC_SAI) +$(eval $(call add_conflict_package,$(CENTEC_SAI),$(LIBSAIVS_DEV))) + +SONIC_ONLINE_DEBS += $(CENTEC_SAI) diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/48x2q4z-modules.conf b/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/48x2q4z-modules.conf new file mode 100644 index 000000000000..7a7881c8c0d3 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/cfg/48x2q4z-modules.conf @@ -0,0 +1,14 @@ +# /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-dev +i2c-mux +i2c-smbus + +i2c-mux-pca954x +lm77 +adt7470 +tun diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/Makefile b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/Makefile new file mode 100644 index 000000000000..645ca1c2e9e1 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/Makefile @@ -0,0 +1 @@ +obj-m := centec_e582_48x2q4z_platform.o centec_at24c64.o diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_at24c64.c b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_at24c64.c new file mode 100644 index 000000000000..e1835df88625 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_at24c64.c @@ -0,0 +1,602 @@ +/* + * at24.c - handle most I2C EEPROMs + * + * Copyright (C) 2005-2007 David Brownell + * Copyright (C) 2008 Wolfram Sang, Pengutronix + * + * 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 + +/* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. + * Differences between different vendor product lines (like Atmel AT24C or + * MicroChip 24LC, etc) won't much matter for typical read/write access. + * There are also I2C RAM chips, likewise interchangeable. One example + * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). + * + * However, misconfiguration can lose data. "Set 16-bit memory address" + * to a part with 8-bit addressing will overwrite data. Writing with too + * big a page size also loses data. And it's not safe to assume that the + * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC + * uses 0x51, for just one example. + * + * Accordingly, explicit board-specific configuration data should be used + * in almost all cases. (One partial exception is an SMBus used to access + * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) + * + * So this driver uses "new style" I2C driver binding, expecting to be + * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or + * similar kernel-resident tables; or, configuration data coming from + * a bootloader. + * + * Other than binding model, current differences from "eeprom" driver are + * that this one handles write access and isn't restricted to 24c02 devices. + * It also handles larger devices (32 kbit and up) with two-byte addresses, + * which won't work on pure SMBus systems. + */ + +struct at24_data { + struct at24_platform_data chip; + int use_smbus; + + /* + * Lock protects against activities from other Linux tasks, + * but not from changes by other I2C masters. + */ + struct mutex lock; + struct bin_attribute bin; + + u8 *writebuf; + unsigned write_max; + unsigned num_addresses; + + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. + */ + struct i2c_client *client[]; +}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 128; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + +#define AT24_SIZE_BYTELEN 5 +#define AT24_SIZE_FLAGS 8 + +#define AT24_BITMASK(x) (BIT(x) - 1) + +/* create non-zero magic value for given eeprom parameters */ +#define AT24_DEVICE_MAGIC(_len, _flags) \ + ((1 << AT24_SIZE_FLAGS | (_flags)) \ + << AT24_SIZE_BYTELEN | ilog2(_len)) + +static const struct i2c_device_id at24_ctc_ids[] = { + { "24c64-ctc", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16 | AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, at24_ctc_ids); + +/*-------------------------------------------------------------------------*/ + +/* + * This routine supports chips which consume multiple I2C addresses. It + * computes the addressing information to be used for a given r/w request. + * Assumes that sanity checks for offset happened at sysfs-layer. + */ +static struct i2c_client *at24_translate_offset(struct at24_data *at24, + unsigned *offset) +{ + unsigned i = 0; + + if (at24->chip.flags & AT24_FLAG_ADDR16) { + i = *offset >> 16; + *offset &= 0xffff; + } else { + i = *offset >> 8; + *offset &= 0xff; + } + + return at24->client[i]; +} + +static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + struct i2c_client *client; + unsigned long timeout, read_time; + int status; + + memset(msg, 0, sizeof(msg)); + + /* + * REVISIT some multi-address chips don't rollover page reads to + * the next slave address, so we may need to truncate the count. + * Those chips might need another quirk flag. + * + * If the real hardware used four adjacent 24c02 chips and that + * were misconfigured as one 24c08, that would be a similar effect: + * one "eeprom" file not four, but larger reads would fail when + * they crossed certain pages. + */ + + /* + * Slave address and byte offset derive from the offset. Always + * set the byte address; on a multi-master board, another master + * may have changed the chip's "current" address pointer. + */ + client = at24_translate_offset(at24, &offset); + + if (count > io_limit) + count = io_limit; + + count = 1; + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + + status = i2c_smbus_write_byte_data(client, (offset >> 8) & 0x0ff, offset & 0x0ff ); + status = i2c_smbus_read_byte(client); + if (status >= 0) { + buf[0] = status; + status = count; + } + + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_read(struct at24_data *at24, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + memset(buf, 0, count); + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_read(at24, buf, off, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return at24_read(at24, buf, off, count); +} + + +/* + * Note that if the hardware write-protect pin is pulled high, the whole + * chip is normally write protected. But there are plenty of product + * variants here, including OTP fuses and partial chip protect. + * + * We only use page mode writes; the alternative is sloooow. This routine + * writes at most one page. + */ +static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + unsigned offset, size_t count) +{ + struct i2c_client *client; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page; + + /* Get corresponding I2C address and adjust offset */ + client = at24_translate_offset(at24, &offset); + + /* write_max is at most a page */ + if (count > at24->write_max) + count = at24->write_max; + + /* Never roll over backwards, to the start of this page */ + next_page = roundup(offset + 1, at24->chip.page_size); + if (offset + count > next_page) + count = next_page - offset; + + /* + * Writes fail if the previous one didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + + status = i2c_smbus_write_word_data(client, (offset >> 8) & 0x0ff, (offset & 0xFF) | buf[0]); + if (status == 0) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, + size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_write(at24, buf, off, 1); /* only one-byte to write; TODO page wirte */ + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + + if (unlikely(off >= attr->size)) + return -EFBIG; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return at24_write(at24, buf, off, count); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_OF +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ + const __be32 *val; + struct device_node *node = client->dev.of_node; + + if (node) { + if (of_get_property(node, "read-only", NULL)) + chip->flags |= AT24_FLAG_READONLY; + val = of_get_property(node, "pagesize", NULL); + if (val) + chip->page_size = be32_to_cpup(val); + } +} +#else +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ } +#endif /* CONFIG_OF */ + +static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct at24_platform_data chip; + bool writable; + int use_smbus = 0; + struct at24_data *at24; + int err; + unsigned i, num_addresses; + kernel_ulong_t magic; + + if (client->dev.platform_data) { + chip = *(struct at24_platform_data *)client->dev.platform_data; + } else { + if (!id->driver_data) + return -ENODEV; + + magic = id->driver_data; + chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); + magic >>= AT24_SIZE_BYTELEN; + chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); + + /* + * This is slow, but we can't know all eeproms, so we better + * play safe. Specifying custom eeprom-types via platform_data + * is recommended anyhow. + */ + chip.page_size = 1; + + /* update chipdata if OF is present */ + at24_get_ofdata(client, &chip); + + chip.setup = NULL; + chip.context = NULL; + } + + if (!is_power_of_2(chip.byte_len)) + dev_warn(&client->dev, + "byte_len looks suspicious (no power of 2)!\n"); + if (!chip.page_size) { + dev_err(&client->dev, "page_size must not be 0!\n"); + return -EINVAL; + } + if (!is_power_of_2(chip.page_size)) + dev_warn(&client->dev, + "page_size looks suspicious (no power of 2)!\n"); + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) { + use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + return -EPFNOSUPPORT; + } + use_smbus = I2C_SMBUS_BYTE_DATA; + } + + if (chip.flags & AT24_FLAG_TAKE8ADDR) + num_addresses = 8; + else + num_addresses = DIV_ROUND_UP(chip.byte_len, (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); + + at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); + if (!at24) + return -ENOMEM; + + mutex_init(&at24->lock); + at24->use_smbus = use_smbus; + at24->chip = chip; + at24->num_addresses = num_addresses; + + printk(KERN_ALERT "at24_probe chip.byte_len = 0x%x\n", chip.byte_len); + printk(KERN_ALERT "at24_probe chip.flags = 0x%x\n", chip.flags); + printk(KERN_ALERT "at24_probe chip.magic = 0x%lx\n", id->driver_data); + printk(KERN_ALERT "at24_probe use_smbus = %d\n", at24->use_smbus); + printk(KERN_ALERT "at24_probe num_addresses = %d\n", at24->num_addresses); + + /* + * Export the EEPROM bytes through sysfs, since that's convenient. + * By default, only root should see the data (maybe passwords etc) + */ + sysfs_bin_attr_init(&at24->bin); + at24->bin.attr.name = "eeprom"; + at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR; + at24->bin.read = at24_bin_read; + at24->bin.size = chip.byte_len; + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { + if (!use_smbus || i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + unsigned write_max = chip.page_size; + + at24->bin.write = at24_bin_write; + at24->bin.attr.mode |= S_IWUSR; + + if (write_max > io_limit) + write_max = io_limit; + if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + at24->write_max = write_max; + + /* buffer (data + address at the beginning) */ + at24->writebuf = devm_kzalloc(&client->dev, write_max + 2, GFP_KERNEL); + if (!at24->writebuf) + return -ENOMEM; + } else { + dev_warn(&client->dev, "cannot write due to controller restrictions."); + } + } + + at24->client[0] = client; + + /* use dummy devices for multiple-address chips */ + for (i = 1; i < num_addresses; i++) { + at24->client[i] = i2c_new_dummy(client->adapter, client->addr + i); + if (!at24->client[i]) { + dev_err(&client->dev, "address 0x%02x unavailable\n", client->addr + i); + err = -EADDRINUSE; + goto err_clients; + } + } + + err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin); + if (err) + goto err_clients; + + i2c_set_clientdata(client, at24); + + printk(KERN_ALERT "at24_probe %s done\n", client->name); + + return 0; + +err_clients: + for (i = 1; i < num_addresses; i++) + if (at24->client[i]) + i2c_unregister_device(at24->client[i]); + + return err; +} + +static int at24_remove(struct i2c_client *client) +{ + struct at24_data *at24; + int i; + + at24 = i2c_get_clientdata(client); + sysfs_remove_bin_file(&client->dev.kobj, &at24->bin); + + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct i2c_board_info i2c_devs = { + I2C_BOARD_INFO("24c64-ctc", 0x57), +}; + +static struct i2c_adapter *adapter = NULL; +static struct i2c_client *client = NULL; + +static int ctc_at24c64_init(void) +{ + printk(KERN_ALERT "ctc_at24c64_init\n"); + + adapter = i2c_get_adapter(0); + if(adapter == NULL){ + printk(KERN_ALERT "i2c_get_adapter == NULL\n"); + return -1; + } + + client = i2c_new_device(adapter, &i2c_devs); + if(client == NULL){ + printk(KERN_ALERT "i2c_new_device == NULL\n"); + i2c_put_adapter(adapter); + adapter = NULL; + return -1; + } + + return 0; +} + +static void ctc_at24c64_exit(void) +{ + printk(KERN_ALERT "ctc_at24c64_exit\n"); + if(client){ + i2c_unregister_device(client); + } + if(adapter){ + i2c_put_adapter(adapter); + } +} + +static struct i2c_driver at24_ctc_driver = { + .driver = { + .name = "at24-ctc", + .owner = THIS_MODULE, + }, + .probe = at24_probe, + .remove = at24_remove, + .id_table = at24_ctc_ids, +}; + +static int __init at24_ctc_init(void) +{ + if (!io_limit) { + pr_err("at24_ctc: io_limit must not be 0!\n"); + return -EINVAL; + } + + io_limit = rounddown_pow_of_two(io_limit); + + ctc_at24c64_init(); + + return i2c_add_driver(&at24_ctc_driver); +} +module_init(at24_ctc_init); + +static void __exit at24_ctc_exit(void) +{ + ctc_at24c64_exit(); + i2c_del_driver(&at24_ctc_driver); +} +module_exit(at24_ctc_exit); + +MODULE_DESCRIPTION("Driver for most I2C EEPROMs"); +MODULE_AUTHOR("David Brownell and Wolfram Sang"); +MODULE_LICENSE("GPL"); +/* XXX */ + diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_e582_48x2q4z_platform.c b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_e582_48x2q4z_platform.c new file mode 100644 index 000000000000..6e06a67f8dd2 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/modules/centec_e582_48x2q4z_platform.c @@ -0,0 +1,1457 @@ +#include +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define PCA9548_CHANNEL_NUM 8 +#define PCA9548_ADAPT_ID_START 10 +#define SFP_NUM 48 +#define QSFP_NUM 6 +#define PORT_NUM (SFP_NUM+QSFP_NUM) +#endif + +#if SEP("i2c:master") +static struct i2c_adapter *i2c_adp_master = NULL; /* i2c-0-cpu */ + +static int e582_48x2q4z_init_i2c_master(void) +{ + /* find i2c-core master */ + i2c_adp_master = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e582_48x2q4z_init_i2c_master can't find i2c-core bus\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_master(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_adp_master)) { + i2c_put_adapter(i2c_adp_master); + i2c_adp_master = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:pca9548") +static struct pca954x_platform_mode i2c_dev_pca9548_platform_mode[PCA9548_CHANNEL_NUM] = { + [0] = { + .adap_id = PCA9548_ADAPT_ID_START, + .deselect_on_exit = 1, + .class = 0, + }, + [1] = { + .adap_id = PCA9548_ADAPT_ID_START + 1, + .deselect_on_exit = 1, + .class = 0, + }, + [2] = { + .adap_id = PCA9548_ADAPT_ID_START + 2, + .deselect_on_exit = 1, + .class = 0, + }, + [3] = { + .adap_id = PCA9548_ADAPT_ID_START + 3, + .deselect_on_exit = 1, + .class = 0, + }, + [4] = { + .adap_id = PCA9548_ADAPT_ID_START + 4, + .deselect_on_exit = 1, + .class = 0, + }, + [5] = { + .adap_id = PCA9548_ADAPT_ID_START + 5, + .deselect_on_exit = 1, + .class = 0, + }, + [6] = { + .adap_id = PCA9548_ADAPT_ID_START + 6, + .deselect_on_exit = 1, + .class = 0, + }, + [7] = { + .adap_id = PCA9548_ADAPT_ID_START + 7, + .deselect_on_exit = 1, + .class = 0, + } +}; +static struct pca954x_platform_data i2c_dev_pca9548_platform_data = { + .modes = i2c_dev_pca9548_platform_mode, + .num_modes = PCA9548_CHANNEL_NUM, +}; +static struct i2c_board_info i2c_dev_pca9548 = { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &i2c_dev_pca9548_platform_data, +}; +static struct i2c_client *i2c_client_pca9548x = NULL; + +static int e582_48x2q4z_init_i2c_pca9548(void) +{ + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e582_48x2q4z_init_i2c_pca9548 can't find i2c-core bus\n"); + return -1; + } + + /* install i2c-mux */ + i2c_client_pca9548x = i2c_new_device(i2c_adp_master, &i2c_dev_pca9548); + if(IS_INVALID_PTR(i2c_client_pca9548x)) + { + i2c_client_pca9548x = NULL; + printk(KERN_CRIT "install e582_48x2q4z board pca9548 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_pca9548(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_client_pca9548x)) { + i2c_unregister_device(i2c_client_pca9548x); + i2c_client_pca9548x = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:adt7470") +static struct i2c_board_info i2c_dev_adt7470 = { + I2C_BOARD_INFO("adt7470", 0x2F), +}; +static struct i2c_adapter *i2c_adp_adt7470 = NULL; /* pca9548x-channel 4 */ +static struct i2c_client *i2c_client_adt7470 = NULL; + +static int e582_48x2q4z_init_i2c_adt7470(void) +{ + i2c_adp_adt7470 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 4); + if(IS_INVALID_PTR(i2c_adp_adt7470)) + { + i2c_adp_adt7470 = NULL; + printk(KERN_CRIT "install e582_48x2q4z board adt7470 failed\n"); + return -1; + } + + i2c_client_adt7470 = i2c_new_device(i2c_adp_adt7470, &i2c_dev_adt7470); + if(IS_INVALID_PTR(i2c_client_adt7470)){ + i2c_client_adt7470 = NULL; + printk(KERN_CRIT "install e582_48x2q4z board adt7470 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_adt7470(void) +{ + if(IS_VALID_PTR(i2c_client_adt7470)) { + i2c_unregister_device(i2c_client_adt7470); + i2c_client_adt7470 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_adt7470)) { + i2c_put_adapter(i2c_adp_adt7470); + i2c_adp_adt7470 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:psu") +static struct i2c_adapter *i2c_adp_psu1 = NULL; /* psu1 channel 1 */ +static struct i2c_adapter *i2c_adp_psu2 = NULL; /* psu2 channel 0 */ +static struct i2c_board_info i2c_dev_psu1 = { + I2C_BOARD_INFO("i2c-psu1", 0x38), +}; +static struct i2c_board_info i2c_dev_psu2 = { + I2C_BOARD_INFO("i2c-psu2", 0x38), +}; +static struct i2c_client *i2c_client_psu1 = NULL; +static struct i2c_client *i2c_client_psu2 = NULL; + +static int e582_48x2q4z_init_i2c_psu(void) +{ + i2c_adp_psu1 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 1); + if(IS_INVALID_PTR(i2c_adp_psu1)) + { + i2c_adp_psu1 = NULL; + printk(KERN_CRIT "get e582_48x2q4z psu1 i2c-adp failed\n"); + return -1; + } + + i2c_adp_psu2 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 0); + if(IS_INVALID_PTR(i2c_adp_psu2)) + { + i2c_adp_psu2 = NULL; + printk(KERN_CRIT "get e582_48x2q4z psu2 i2c-adp failed\n"); + return -1; + } + + i2c_client_psu1 = i2c_new_device(i2c_adp_psu1, &i2c_dev_psu1); + if(IS_INVALID_PTR(i2c_client_psu1)){ + i2c_client_psu1 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client psu1 failed\n"); + return -1; + } + + i2c_client_psu2 = i2c_new_device(i2c_adp_psu2, &i2c_dev_psu2); + if(IS_INVALID_PTR(i2c_client_psu2)){ + i2c_client_psu2 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client psu2 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_psu(void) +{ + if(IS_VALID_PTR(i2c_client_psu1)) { + i2c_unregister_device(i2c_client_psu1); + i2c_client_psu1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_psu2)) { + i2c_unregister_device(i2c_client_psu2); + i2c_client_psu2 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_psu1)) + { + i2c_put_adapter(i2c_adp_psu1); + i2c_adp_psu1 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_psu2)) + { + i2c_put_adapter(i2c_adp_psu2); + i2c_adp_psu2 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:epld") +static struct i2c_board_info i2c_dev_epld = { + I2C_BOARD_INFO("i2c-epld", 0x58), +}; +static struct i2c_client *i2c_client_epld = NULL; + +static int e582_48x2q4z_init_i2c_epld(void) +{ + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e582_48x2q4z_init_i2c_epld can't find i2c-core bus\n"); + return -1; + } + + i2c_client_epld = i2c_new_device(i2c_adp_master, &i2c_dev_epld); + if(IS_INVALID_PTR(i2c_client_epld)) + { + i2c_client_epld = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client epld failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_epld(void) +{ + if(IS_VALID_PTR(i2c_client_epld)) { + i2c_unregister_device(i2c_client_epld); + i2c_client_epld = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:gpio") +static struct i2c_adapter *i2c_adp_gpio0 = NULL; /* gpio0 channel 5 */ +static struct i2c_adapter *i2c_adp_gpio1 = NULL; /* gpio1 channel 5 */ +static struct i2c_adapter *i2c_adp_gpio2 = NULL; /* gpio2 channel 5 */ +static struct i2c_adapter *i2c_adp_gpio3 = NULL; /* gpio3 channel 6 */ +static struct i2c_adapter *i2c_adp_gpio4 = NULL; /* gpio4 channel 7 */ +static struct i2c_board_info i2c_dev_gpio0 = { + I2C_BOARD_INFO("i2c-gpio0", 0x21), +}; +static struct i2c_board_info i2c_dev_gpio1 = { + I2C_BOARD_INFO("i2c-gpio1", 0x22), +}; +static struct i2c_board_info i2c_dev_gpio2 = { + I2C_BOARD_INFO("i2c-gpio2", 0x23), +}; +static struct i2c_board_info i2c_dev_gpio3 = { + I2C_BOARD_INFO("i2c-gpio3", 0x21), +}; +static struct i2c_board_info i2c_dev_gpio4 = { + I2C_BOARD_INFO("i2c-gpio4", 0x22), +}; +static struct i2c_client *i2c_client_gpio0 = NULL; +static struct i2c_client *i2c_client_gpio1 = NULL; +static struct i2c_client *i2c_client_gpio2 = NULL; +static struct i2c_client *i2c_client_gpio3 = NULL; +static struct i2c_client *i2c_client_gpio4 = NULL; + +static int e582_48x2q4z_init_i2c_gpio(void) +{ + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e582_48x2q4z_init_i2c_gpio can't find i2c-core bus\n"); + return -1; + } + + i2c_adp_gpio0 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 5); + if(IS_INVALID_PTR(i2c_adp_gpio0)) + { + i2c_adp_gpio0 = NULL; + printk(KERN_CRIT "get e582_48x2q4z gpio0 i2c-adp failed\n"); + return -1; + } + + i2c_adp_gpio1 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 5); + if(IS_INVALID_PTR(i2c_adp_gpio1)) + { + i2c_adp_gpio1 = NULL; + printk(KERN_CRIT "get e582_48x2q4z gpio1 i2c-adp failed\n"); + return -1; + } + + i2c_adp_gpio2 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 5); + if(IS_INVALID_PTR(i2c_adp_gpio2)) + { + i2c_adp_gpio2 = NULL; + printk(KERN_CRIT "get e582_48x2q4z gpio2 i2c-adp failed\n"); + return -1; + } + + i2c_adp_gpio3 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 6); + if(IS_INVALID_PTR(i2c_adp_gpio3)) + { + i2c_adp_gpio3 = NULL; + printk(KERN_CRIT "get e582_48x2q4z gpio3 i2c-adp failed\n"); + return -1; + } + + i2c_adp_gpio4 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 7); + if(IS_INVALID_PTR(i2c_adp_gpio4)) + { + i2c_adp_gpio4 = NULL; + printk(KERN_CRIT "get e582_48x2q4z gpio4 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio0 = i2c_new_device(i2c_adp_gpio0, &i2c_dev_gpio0); + if(IS_INVALID_PTR(i2c_client_gpio0)) + { + i2c_client_gpio0 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client gpio0 failed\n"); + return -1; + } + + i2c_client_gpio1 = i2c_new_device(i2c_adp_gpio1, &i2c_dev_gpio1); + if(IS_INVALID_PTR(i2c_client_gpio1)) + { + i2c_client_gpio1 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client gpio1 failed\n"); + return -1; + } + + i2c_client_gpio2 = i2c_new_device(i2c_adp_gpio2, &i2c_dev_gpio2); + if(IS_INVALID_PTR(i2c_client_gpio2)) + { + i2c_client_gpio2 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client gpio2 failed\n"); + return -1; + } + + i2c_client_gpio3 = i2c_new_device(i2c_adp_gpio3, &i2c_dev_gpio3); + if(IS_INVALID_PTR(i2c_client_gpio3)) + { + i2c_client_gpio3 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client gpio3 failed\n"); + return -1; + } + + i2c_client_gpio4 = i2c_new_device(i2c_adp_gpio4, &i2c_dev_gpio4); + if(IS_INVALID_PTR(i2c_client_gpio4)) + { + i2c_client_gpio4 = NULL; + printk(KERN_CRIT "create e582_48x2q4z board i2c client gpio4 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_i2c_gpio(void) +{ + if(IS_VALID_PTR(i2c_client_gpio0)) { + i2c_unregister_device(i2c_client_gpio0); + i2c_client_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio1)) { + i2c_unregister_device(i2c_client_gpio1); + i2c_client_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio2)) { + i2c_unregister_device(i2c_client_gpio2); + i2c_client_gpio2 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio3)) { + i2c_unregister_device(i2c_client_gpio3); + i2c_client_gpio3 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio4)) { + i2c_unregister_device(i2c_client_gpio4); + i2c_client_gpio4 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio0)) + { + i2c_put_adapter(i2c_adp_gpio0); + i2c_adp_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio1)) + { + i2c_put_adapter(i2c_adp_gpio1); + i2c_adp_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio2)) + { + i2c_put_adapter(i2c_adp_gpio2); + i2c_adp_gpio2 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio3)) + { + i2c_put_adapter(i2c_adp_gpio3); + i2c_adp_gpio3 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio4)) + { + i2c_put_adapter(i2c_adp_gpio4); + i2c_adp_gpio4 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:smbus") +static int e582_48x2q4z_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + } + else + { + *value = 0; + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} + +static int e582_48x2q4z_smbus_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_write_byte_data(client, reg, value); + if (ret != 0) + { + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} +#endif + +#if SEP("drivers:psu") +static struct class* psu_class = NULL; +static struct device* psu_dev_psu1 = NULL; +static struct device* psu_dev_psu2 = NULL; + +static ssize_t e582_48x2q4z_psu_read_presence(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char present_no = 0; + unsigned char present = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio2; + present_no = 30; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio2; + present_no = 29; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e582_48x2q4z_smbus_read_reg(i2c_psu_client, present_no/8, &present); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((present & (1<<(present_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x2q4z_psu_read_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char workstate_no = 0; + unsigned char workstate = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio2; + workstate_no = 36; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio2; + workstate_no = 35; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e582_48x2q4z_smbus_read_reg(i2c_psu_client, workstate_no/8, &workstate); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((workstate & (1<<(workstate_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static DEVICE_ATTR(psu_presence, S_IRUGO, e582_48x2q4z_psu_read_presence, NULL); +static DEVICE_ATTR(psu_status, S_IRUGO, e582_48x2q4z_psu_read_status, NULL); + +static int e582_48x2q4z_init_psu(void) +{ + int ret = 0; + + psu_class = class_create(THIS_MODULE, "psu"); + if (IS_INVALID_PTR(psu_class)) + { + psu_class = NULL; + printk(KERN_CRIT "create e582_48x2q4z class psu failed\n"); + return -1; + } + + psu_dev_psu1 = device_create(psu_class, NULL, MKDEV(222,0), NULL, "psu1"); + if (IS_INVALID_PTR(psu_dev_psu1)) + { + psu_dev_psu1 = NULL; + printk(KERN_CRIT "create e582_48x2q4z psu1 device failed\n"); + return -1; + } + + psu_dev_psu2 = device_create(psu_class, NULL, MKDEV(222,1), NULL, "psu2"); + if (IS_INVALID_PTR(psu_dev_psu2)) + { + psu_dev_psu2 = NULL; + printk(KERN_CRIT "create e582_48x2q4z psu2 device failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z psu1 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z psu1 device attr:status failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z psu2 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z psu2 device attr:status failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x2q4z_exit_psu(void) +{ + if (IS_VALID_PTR(psu_dev_psu1)) + { + device_remove_file(psu_dev_psu1, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu1, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,0)); + } + + if (IS_VALID_PTR(psu_dev_psu2)) + { + device_remove_file(psu_dev_psu2, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu2, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,1)); + } + + if (IS_VALID_PTR(psu_class)) + { + class_destroy(psu_class); + psu_class = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:leds") +extern void e582_48x2q4z_led_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e582_48x2q4z_led_get(struct led_classdev *led_cdev); +extern void e582_48x2q4z_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e582_48x2q4z_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_system = { + .name = "system", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_idn = { + .name = "idn", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_fan1 = { + .name = "fan1", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_fan2 = { + .name = "fan2", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_fan3 = { + .name = "fan3", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_fan4 = { + .name = "fan4", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_psu1 = { + .name = "psu1", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_psu2 = { + .name = "psu2", + .brightness_set = e582_48x2q4z_led_set, + .brightness_get = e582_48x2q4z_led_get, +}; +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port1", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port2", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port3", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port4", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port5", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port6", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port7", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port8", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port9", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port10", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port11", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port12", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port13", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port14", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port15", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port16", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port17", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port18", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port19", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port20", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port21", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port22", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port23", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port24", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port25", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port26", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port27", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port28", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port29", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port30", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port31", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port32", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port33", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port34", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port35", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port36", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port37", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port38", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port39", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port40", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port41", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port42", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port43", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port44", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port45", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port46", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port47", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port48", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port49", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port50", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port51", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port52", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port53", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,}, +{ .name = "port54", .brightness_set = e582_48x2q4z_led_port_set, .brightness_get = e582_48x2q4z_led_port_get,} +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void e582_48x2q4z_led_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_epld; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x0F; + shift = 4; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x3; + mask = 0xFE; + shift = 0; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e582_48x2q4z_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return; + } + + led_value = ((led_value & mask) | ((set_value << shift) & (~mask))); + + ret = e582_48x2q4z_smbus_write_reg(i2c_led_client, reg, led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s led attr failed\n", led_cdev->name); + return; + } + + return; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return; +} + +enum led_brightness e582_48x2q4z_led_get(struct led_classdev *led_cdev) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_epld; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0xF0; + shift = 4; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x3; + mask = 0x01; + shift = 0; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e582_48x2q4z_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return 0; + } + + led_value = ((led_value & mask) >> shift); + + return led_value; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return 0; +} + +void e582_48x2q4z_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum-1] = set_value; + + return; +} + +enum led_brightness e582_48x2q4z_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum-1]; +} + +static int e582_48x2q4z_init_led(void) +{ + int ret = 0; + int i = 0; + + ret = led_classdev_register(NULL, &led_dev_system); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_system device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_idn); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_idn device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan1); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_fan1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan2); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_fan2 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan3); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_fan3 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan4); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_fan4 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu1); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_psu1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu2); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z led_dev_psu2 device failed\n"); + return -1; + } + + for (i=0; i PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + value = 0; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum + 31;/*32-39*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum - 9;/*0-7*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum - 17;/*0-7*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 17;/*8-15*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 1;/*32-39*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 41;/*0-7*/ + i2c_sfp_client = i2c_client_gpio4; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + reg_no = portNum - 33;/*16-21*/ + i2c_sfp_client = i2c_client_gpio4; + } + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x2q4z_smbus_write_reg(i2c_sfp_client, dir_bank, 0xff); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + } + + input_bank = (reg_no/8) + 0x0; + ret = e582_48x2q4z_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 );/*1:PRESENT 0:ABSENT*/ + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x2q4z_sfp_read_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char value = 0; + unsigned char reg_no = 0; + unsigned char dir_bank = 0; + unsigned char input_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + value = 0; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum - 1;/*0-7*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum - 1;/*8-15*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum - 9;/*8-15*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 9;/*16-23*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 33;/*0-7*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 33;/*8-15*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + printk(KERN_INFO "%s not supported!\n", name); + return sprintf(buf, "%d\n", 0); + } + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x2q4z_smbus_write_reg(i2c_sfp_client, dir_bank, 0xff); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + } + + input_bank = (reg_no/8) + 0x8; + ret = e582_48x2q4z_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x2q4z_sfp_write_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned char value = 0; + unsigned char set_value = simple_strtol(buf, NULL, 10); + unsigned char reg_no = 0; + unsigned char dir_bank = 0; + unsigned char input_bank = 0; + unsigned char output_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + return size; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum - 1;/*0-7*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum - 1;/*8-15*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum - 9;/*8-15*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 9;/*16-23*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 33;/*0-7*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 33;/*8-13*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + printk(KERN_INFO "%s not supported!\n", name); + return size; + } + + set_value = ((set_value > 0) ? 0 : 1 ); + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x2q4z_smbus_write_reg(i2c_sfp_client, dir_bank, 0x0); + if (ret != 0) + { + printk(KERN_CRIT "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + return size; + } + + input_bank = (reg_no/8) + 0x8; + ret = e582_48x2q4z_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s presence failed\n", name); + return size; + } + + if (set_value) + { + value = (value | (1<<(reg_no % 8))); + } + else + { + value = (value & (~(1<<(reg_no % 8)))); + } + + output_bank = (reg_no/8) + 0x8; + ret = e582_48x2q4z_smbus_write_reg(i2c_sfp_client, output_bank, value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s presence failed\n", name); + return size; + } + + return size; +} + +static DEVICE_ATTR(sfp_presence, S_IRUGO, e582_48x2q4z_sfp_read_presence, NULL); +static DEVICE_ATTR(sfp_enable, S_IRUGO|S_IWUSR, e582_48x2q4z_sfp_read_enable, e582_48x2q4z_sfp_write_enable); +static int e582_48x2q4z_init_sfp(void) +{ + int ret = 0; + int i = 0; + + sfp_class = class_create(THIS_MODULE, "sfp"); + if (IS_INVALID_PTR(sfp_class)) + { + sfp_class = NULL; + printk(KERN_CRIT "create e582_48x2q4z class sfp failed\n"); + return -1; + } + + for (i=1; i<=PORT_NUM; i++) + { + sfp_dev[i] = device_create(sfp_class, NULL, MKDEV(223,i), NULL, "sfp%d", i); + if (IS_INVALID_PTR(sfp_dev[i])) + { + sfp_dev[i] = NULL; + printk(KERN_CRIT "create e582_48x2q4z sfp[%d] device failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z sfp[%d] device attr:presence failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_enable); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x2q4z sfp[%d] device attr:enable failed\n", i); + continue; + } + } + + return ret; +} + +static int e582_48x2q4z_exit_sfp(void) +{ + int i = 0; + + for (i=1; i<=PORT_NUM; i++) + { + if (IS_VALID_PTR(sfp_dev[i])) + { + device_remove_file(sfp_dev[i], &dev_attr_sfp_presence); + device_remove_file(sfp_dev[i], &dev_attr_sfp_enable); + device_destroy(sfp_class, MKDEV(223,i)); + sfp_dev[i] = NULL; + } + } + + if (IS_VALID_PTR(sfp_class)) + { + class_destroy(sfp_class); + sfp_class = NULL; + } + + return 0; +} +#endif + +static int e582_48x2q4z_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "install e582_48x2q4z board dirver...\n"); + + ret = e582_48x2q4z_init_i2c_master(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_i2c_pca9548(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_i2c_adt7470(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_i2c_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_i2c_epld(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_i2c_gpio(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_led(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x2q4z_init_sfp(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "install e582_48x2q4z board driver failed\n"); + else + printk(KERN_ALERT "install e582_48x2q4z board dirver...ok\n"); + + return 0; +} + +static void e582_48x2q4z_exit(void) +{ + printk(KERN_INFO "uninstall e582_48x2q4z board dirver...\n"); + + e582_48x2q4z_exit_sfp(); + e582_48x2q4z_exit_led(); + e582_48x2q4z_exit_psu(); + e582_48x2q4z_exit_i2c_gpio(); + e582_48x2q4z_exit_i2c_epld(); + e582_48x2q4z_exit_i2c_psu(); + e582_48x2q4z_exit_i2c_adt7470(); + e582_48x2q4z_exit_i2c_pca9548(); + e582_48x2q4z_exit_i2c_master(); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("yangbs centecNetworks, Inc"); +MODULE_DESCRIPTION("e582-48x2q4z board driver"); +module_init(e582_48x2q4z_init); +module_exit(e582_48x2q4z_exit); + + diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform.sh b/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform.sh new file mode 100755 index 000000000000..0edb50901425 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +#platform init script for centec e582-48x2q4z + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # I801 adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus I801 adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find I801" && exit 1 +} + +init_devnum + +if [ "$1" == "init" ]; then + #install drivers and dependencies + depmod -a + modprobe i2c-i801 + modprobe i2c-dev + modprobe i2c-mux + modprobe i2c-smbus + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + i2cset -y 0 0x58 0x8 0x3f + modprobe lm77 + modprobe tun + modprobe dal + modprobe centec_at24c64 + modprobe centec_e582_48x2q4z_platform + i2cset -y 15 0x21 0x18 0x0 + i2cset -y 15 0x21 0x19 0x0 + i2cset -y 15 0x21 0x1a 0xff + i2cset -y 15 0x21 0x1b 0xff + i2cset -y 15 0x21 0x1c 0xff + i2cset -y 15 0x21 0x8 0x0 + i2cset -y 15 0x21 0x9 0x0 + i2cset -y 15 0x22 0x18 0xff + i2cset -y 15 0x22 0x19 0x0 + i2cset -y 15 0x22 0x1a 0x0 + i2cset -y 15 0x22 0x1b 0xff + i2cset -y 15 0x22 0x1c 0xff + i2cset -y 15 0x22 0x9 0x0 + i2cset -y 15 0x22 0xa 0x0 + i2cset -y 16 0x21 0x18 0x0 + i2cset -y 16 0x21 0x19 0x0 + i2cset -y 16 0x21 0x1a 0xff + i2cset -y 16 0x21 0x1b 0xff + i2cset -y 16 0x21 0x1c 0xff + i2cset -y 16 0x21 0x8 0x0 + i2cset -y 16 0x21 0x9 0x0 + i2cset -y 17 0x22 0x18 0xff + i2cset -y 17 0x22 0x19 0x0 + i2cset -y 17 0x22 0x1a 0xff + i2cset -y 17 0x22 0x1b 0x0 + i2cset -y 17 0x22 0x1c 0xff + i2cset -y 17 0x22 0x9 0xf0 + i2cset -y 17 0x22 0xb 0x0c + + #start platform monitor + rm -rf /usr/bin/platform_monitor + ln -s /usr/bin/48x2q4z_platform_monitor.py /usr/bin/platform_monitor + python /usr/bin/platform_monitor & +elif [ "$1" == "deinit" ]; then + kill -9 $(pidof platform_monitor) > /dev/null 2>&1 + rm -rf /usr/bin/platform_monitor + modprobe -r centec_e582_48x2q4z_platform + modprobe -r centec_at24c64 + modprobe -r dal + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev +else + echo "e582-48x2q4z_platform : Invalid option !" +fi diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform_monitor.py b/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform_monitor.py new file mode 100644 index 000000000000..2d8d2c440a8f --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/scripts/48x2q4z_platform_monitor.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of sfp presence scan logic +# +############################################################################# + +try: + import os + import os.path + import threading + import time + import logging + import struct + import syslog + import swsssdk + from socket import * + from select import * +except ImportError, e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-pmon") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + +PORT_NUMBER = (48+6) + +class PlatformMonitor: + + """init board platform default config""" + def __init__(self): + """[ctlid, slavedevid]""" + self.fiber_mapping = [(0, 0)] # res + self.fiber_mapping.extend([(1, 7), (1, 6), (1, 5), (1, 4), (1, 3), (1, 2), (1, 1), (1, 0)]) # panel port 1~8 + self.fiber_mapping.extend([(1, 15), (1, 14), (1, 13), (1, 12), (1, 11), (1, 10), (1, 9), (1, 8)]) # panel port 9~16 + self.fiber_mapping.extend([(1, 19), (1, 17), (1, 16), (1, 18), (0, 7), (0, 6), (0, 5), (0, 4)]) # panel port 17~24 + self.fiber_mapping.extend([(0, 3), (0, 2), (0, 1), (0, 0), (0, 15), (0, 14), (0, 13), (0, 12)]) # panel port 25~32 + self.fiber_mapping.extend([(0, 11), (0, 10), (0, 9), (0, 8), (0, 23), (0, 22), (0, 21), (0, 20)]) # panel port 33~40 + self.fiber_mapping.extend([(0, 19), (0, 18), (0, 17), (0, 16), (0, 31), (0, 26), (0, 29), (0, 27)]) # panel port 41~48 + self.fiber_mapping.extend([(0, 24), (0, 25), (1, 23), (1, 22), (1, 21), (1, 20)]) # panel port 49~54 + + self.udpClient = socket(AF_INET, SOCK_DGRAM) + self.sfp_present = [0]*(PORT_NUMBER+1) + self.sfp_enable = [0]*(PORT_NUMBER+1) + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + self.sfp_scan_timer = 0 + + def is_qsfp(self, port): + if port <= 48: + return False + else: + return True + + def get_sfp_present(self, port): + with open(self.f_sfp_present.format(port), 'r') as sfp_file: + return int(sfp_file.read()) + + def set_sfp_present(self, port, present): + self.sfp_present[port] = present + + def set_sfp_enable(self, port, enable): + if self.is_qsfp(port): + if enable: + with open(self.f_sfp_enable.format(port), 'w') as sfp_file: + sfp_file.write("1") + self.sfp_enable[port] = 1 + else: + with open(self.f_sfp_enable.format(port), 'w') as sfp_file: + sfp_file.write("0") + self.sfp_enable[port] = 0 + else: + (ctlid, devid) = self.fiber_mapping[port] + req = struct.pack('=HHHBBHIBBBBI', 0, 9, 16, ctlid, devid, 0x50, 0, 0x56, 1, 0xf, 0, 1) + self.udpClient.sendto(req, ('localhost', 8101)) + rsp, addr = self.udpClient.recvfrom(1024) + rsp_data = struct.unpack('=HHHBBHIBBBBIi512B', rsp) + enable_v = rsp_data[13] + if enable: + enable_v &= 0xf0 + else: + enable_v |= 0x0f + data = struct.pack('=HHHBBHBBBB', 0, 11, 8, ctlid, 0x56, 0x50, devid, enable_v, 0xf, 0) + self.udpClient.sendto(data, ('localhost', 8101)) + DBG_PRINT("set sfp{} to {}".format(port, ("enable" if enable else "disable"))) + + def initialize_configdb(self): + try: + f_mac = os.popen('ip link show eth0 | grep ether | awk \'{print $2}\'') + mac_addr = f_mac.read(17) + last_byte = mac_addr[-2:] + aligned_last_byte = format(int(int(str(last_byte), 16) + 1), '02x') + mac_addr = mac_addr[:-2] + aligned_last_byte + DBG_PRINT("start connect swss config-db to set device mac-address") + swss = swsssdk.SonicV2Connector() + swss.connect(swss.CONFIG_DB) + swss.set(swss.CONFIG_DB, "DEVICE_METADATA|localhost", 'mac', mac_addr) + mac_addr = swss.get(swss.CONFIG_DB, "DEVICE_METADATA|localhost", 'mac') + DBG_PRINT("set device mac-address: %s" % mac_addr) + except IOError as e: + DBG_PRINT(str(e)) + + def initialize_rpc(self): + while True: + try: + r_sel = [self.udpClient] + echo_req = struct.pack('=HHH', 0, 1, 0) + self.udpClient.sendto(echo_req, ('localhost', 8101)) + result = select(r_sel, [], [], 1) + if self.udpClient in result[0]: + echo_rsp, srv_addr = self.udpClient.recvfrom(1024) + if echo_rsp: + break + DBG_PRINT("connect to sdk rpc server timeout, try again.") + except IOError as e: + DBG_PRINT(str(e)) + + DBG_PRINT("connect to sdk rpc server success.") + + def initialize_gpio(self): + # set gpio 1,2,3,4,5,6,7,8 output mode + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 1, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 2, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 3, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 4, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 5, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 6, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 7, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 8, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + # set gpio 1,2,3,4,5,6,7,8 output 0 to reset i2c bridge + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 1, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 2, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 3, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 4, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 5, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 6, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 7, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 8, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + # set gpio 1,2,3,4,5,6,7,8 output 1 to release i2c bridge + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 1, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 2, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 3, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 4, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 5, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 6, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 7, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 8, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + DBG_PRINT("config ctc chip gpio done.") + + def initialize_sfp(self): + try: + for port in range(1, PORT_NUMBER+1): + if self.get_sfp_present(port): + self.set_sfp_present(port, 1) + self.set_sfp_enable(port, 1) + else: + self.set_sfp_present(port, 0) + self.set_sfp_enable(port, 0) + except IOError as e: + DBG_PRINT(str(e)) + + def initialize(self): + DBG_PRINT("start connect to sdk rpc server.") + + self.initialize_configdb() + self.initialize_rpc() + self.initialize_gpio() + self.initialize_sfp() + + def sfp_scan(self): + try: + for port in range(1, PORT_NUMBER+1): + cur_present = self.get_sfp_present(port) + if self.sfp_present[port] != cur_present: + self.set_sfp_present(port, cur_present) + self.set_sfp_enable(port, cur_present) + except IOError as e: + DBG_PRINT(str(e)) + + def start(self): + while True: + self.sfp_scan() + time.sleep(1) + +if __name__ == "__main__": + monitor = PlatformMonitor() + monitor.initialize() + monitor.start() + diff --git a/platform/centec/sonic-platform-modules-e582/48x2q4z/service/48x2q4z_platform.service b/platform/centec/sonic-platform-modules-e582/48x2q4z/service/48x2q4z_platform.service new file mode 100644 index 000000000000..008db145b110 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x2q4z/service/48x2q4z_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec e582 48x2q4z platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-e582-48x2q4z start +ExecStop=-/etc/init.d/platform-modules-e582-48x2q4z stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/cfg/48x6q-modules.conf b/platform/centec/sonic-platform-modules-e582/48x6q/cfg/48x6q-modules.conf new file mode 100644 index 000000000000..7a7881c8c0d3 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/cfg/48x6q-modules.conf @@ -0,0 +1,14 @@ +# /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-dev +i2c-mux +i2c-smbus + +i2c-mux-pca954x +lm77 +adt7470 +tun diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/modules/Makefile b/platform/centec/sonic-platform-modules-e582/48x6q/modules/Makefile new file mode 100644 index 000000000000..2462555c8714 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/modules/Makefile @@ -0,0 +1 @@ +obj-m := centec_e582_48x6q_platform.o centec_at24c64.o diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_at24c64.c b/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_at24c64.c new file mode 100644 index 000000000000..e1835df88625 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_at24c64.c @@ -0,0 +1,602 @@ +/* + * at24.c - handle most I2C EEPROMs + * + * Copyright (C) 2005-2007 David Brownell + * Copyright (C) 2008 Wolfram Sang, Pengutronix + * + * 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 + +/* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. + * Differences between different vendor product lines (like Atmel AT24C or + * MicroChip 24LC, etc) won't much matter for typical read/write access. + * There are also I2C RAM chips, likewise interchangeable. One example + * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). + * + * However, misconfiguration can lose data. "Set 16-bit memory address" + * to a part with 8-bit addressing will overwrite data. Writing with too + * big a page size also loses data. And it's not safe to assume that the + * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC + * uses 0x51, for just one example. + * + * Accordingly, explicit board-specific configuration data should be used + * in almost all cases. (One partial exception is an SMBus used to access + * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) + * + * So this driver uses "new style" I2C driver binding, expecting to be + * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or + * similar kernel-resident tables; or, configuration data coming from + * a bootloader. + * + * Other than binding model, current differences from "eeprom" driver are + * that this one handles write access and isn't restricted to 24c02 devices. + * It also handles larger devices (32 kbit and up) with two-byte addresses, + * which won't work on pure SMBus systems. + */ + +struct at24_data { + struct at24_platform_data chip; + int use_smbus; + + /* + * Lock protects against activities from other Linux tasks, + * but not from changes by other I2C masters. + */ + struct mutex lock; + struct bin_attribute bin; + + u8 *writebuf; + unsigned write_max; + unsigned num_addresses; + + /* + * Some chips tie up multiple I2C addresses; dummy devices reserve + * them for us, and we'll use them with SMBus calls. + */ + struct i2c_client *client[]; +}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 128; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + +#define AT24_SIZE_BYTELEN 5 +#define AT24_SIZE_FLAGS 8 + +#define AT24_BITMASK(x) (BIT(x) - 1) + +/* create non-zero magic value for given eeprom parameters */ +#define AT24_DEVICE_MAGIC(_len, _flags) \ + ((1 << AT24_SIZE_FLAGS | (_flags)) \ + << AT24_SIZE_BYTELEN | ilog2(_len)) + +static const struct i2c_device_id at24_ctc_ids[] = { + { "24c64-ctc", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16 | AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, + { /* END OF LIST */ } +}; +MODULE_DEVICE_TABLE(i2c, at24_ctc_ids); + +/*-------------------------------------------------------------------------*/ + +/* + * This routine supports chips which consume multiple I2C addresses. It + * computes the addressing information to be used for a given r/w request. + * Assumes that sanity checks for offset happened at sysfs-layer. + */ +static struct i2c_client *at24_translate_offset(struct at24_data *at24, + unsigned *offset) +{ + unsigned i = 0; + + if (at24->chip.flags & AT24_FLAG_ADDR16) { + i = *offset >> 16; + *offset &= 0xffff; + } else { + i = *offset >> 8; + *offset &= 0xff; + } + + return at24->client[i]; +} + +static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + struct i2c_client *client; + unsigned long timeout, read_time; + int status; + + memset(msg, 0, sizeof(msg)); + + /* + * REVISIT some multi-address chips don't rollover page reads to + * the next slave address, so we may need to truncate the count. + * Those chips might need another quirk flag. + * + * If the real hardware used four adjacent 24c02 chips and that + * were misconfigured as one 24c08, that would be a similar effect: + * one "eeprom" file not four, but larger reads would fail when + * they crossed certain pages. + */ + + /* + * Slave address and byte offset derive from the offset. Always + * set the byte address; on a multi-master board, another master + * may have changed the chip's "current" address pointer. + */ + client = at24_translate_offset(at24, &offset); + + if (count > io_limit) + count = io_limit; + + count = 1; + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + + status = i2c_smbus_write_byte_data(client, (offset >> 8) & 0x0ff, offset & 0x0ff ); + status = i2c_smbus_read_byte(client); + if (status >= 0) { + buf[0] = status; + status = count; + } + + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_read(struct at24_data *at24, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + memset(buf, 0, count); + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_read(at24, buf, off, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return at24_read(at24, buf, off, count); +} + + +/* + * Note that if the hardware write-protect pin is pulled high, the whole + * chip is normally write protected. But there are plenty of product + * variants here, including OTP fuses and partial chip protect. + * + * We only use page mode writes; the alternative is sloooow. This routine + * writes at most one page. + */ +static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + unsigned offset, size_t count) +{ + struct i2c_client *client; + ssize_t status; + unsigned long timeout, write_time; + unsigned next_page; + + /* Get corresponding I2C address and adjust offset */ + client = at24_translate_offset(at24, &offset); + + /* write_max is at most a page */ + if (count > at24->write_max) + count = at24->write_max; + + /* Never roll over backwards, to the start of this page */ + next_page = roundup(offset + 1, at24->chip.page_size); + if (offset + count > next_page) + count = next_page - offset; + + /* + * Writes fail if the previous one didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + write_time = jiffies; + + status = i2c_smbus_write_word_data(client, (offset >> 8) & 0x0ff, (offset & 0xFF) | buf[0]); + if (status == 0) + status = count; + + dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(write_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, + size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&at24->lock); + + while (count) { + ssize_t status; + + status = at24_eeprom_write(at24, buf, off, 1); /* only one-byte to write; TODO page wirte */ + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&at24->lock); + + return retval; +} + +static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct at24_data *at24; + + if (unlikely(off >= attr->size)) + return -EFBIG; + + at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); + return at24_write(at24, buf, off, count); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_OF +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ + const __be32 *val; + struct device_node *node = client->dev.of_node; + + if (node) { + if (of_get_property(node, "read-only", NULL)) + chip->flags |= AT24_FLAG_READONLY; + val = of_get_property(node, "pagesize", NULL); + if (val) + chip->page_size = be32_to_cpup(val); + } +} +#else +static void at24_get_ofdata(struct i2c_client *client, + struct at24_platform_data *chip) +{ } +#endif /* CONFIG_OF */ + +static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct at24_platform_data chip; + bool writable; + int use_smbus = 0; + struct at24_data *at24; + int err; + unsigned i, num_addresses; + kernel_ulong_t magic; + + if (client->dev.platform_data) { + chip = *(struct at24_platform_data *)client->dev.platform_data; + } else { + if (!id->driver_data) + return -ENODEV; + + magic = id->driver_data; + chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); + magic >>= AT24_SIZE_BYTELEN; + chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); + + /* + * This is slow, but we can't know all eeproms, so we better + * play safe. Specifying custom eeprom-types via platform_data + * is recommended anyhow. + */ + chip.page_size = 1; + + /* update chipdata if OF is present */ + at24_get_ofdata(client, &chip); + + chip.setup = NULL; + chip.context = NULL; + } + + if (!is_power_of_2(chip.byte_len)) + dev_warn(&client->dev, + "byte_len looks suspicious (no power of 2)!\n"); + if (!chip.page_size) { + dev_err(&client->dev, "page_size must not be 0!\n"); + return -EINVAL; + } + if (!is_power_of_2(chip.page_size)) + dev_warn(&client->dev, + "page_size looks suspicious (no power of 2)!\n"); + + /* Use I2C operations unless we're stuck with SMBus extensions. */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; + } else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) { + use_smbus = I2C_SMBUS_WORD_DATA; + } else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + use_smbus = I2C_SMBUS_BYTE_DATA; + } else { + return -EPFNOSUPPORT; + } + use_smbus = I2C_SMBUS_BYTE_DATA; + } + + if (chip.flags & AT24_FLAG_TAKE8ADDR) + num_addresses = 8; + else + num_addresses = DIV_ROUND_UP(chip.byte_len, (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); + + at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); + if (!at24) + return -ENOMEM; + + mutex_init(&at24->lock); + at24->use_smbus = use_smbus; + at24->chip = chip; + at24->num_addresses = num_addresses; + + printk(KERN_ALERT "at24_probe chip.byte_len = 0x%x\n", chip.byte_len); + printk(KERN_ALERT "at24_probe chip.flags = 0x%x\n", chip.flags); + printk(KERN_ALERT "at24_probe chip.magic = 0x%lx\n", id->driver_data); + printk(KERN_ALERT "at24_probe use_smbus = %d\n", at24->use_smbus); + printk(KERN_ALERT "at24_probe num_addresses = %d\n", at24->num_addresses); + + /* + * Export the EEPROM bytes through sysfs, since that's convenient. + * By default, only root should see the data (maybe passwords etc) + */ + sysfs_bin_attr_init(&at24->bin); + at24->bin.attr.name = "eeprom"; + at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR; + at24->bin.read = at24_bin_read; + at24->bin.size = chip.byte_len; + + writable = !(chip.flags & AT24_FLAG_READONLY); + if (writable) { + if (!use_smbus || i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + unsigned write_max = chip.page_size; + + at24->bin.write = at24_bin_write; + at24->bin.attr.mode |= S_IWUSR; + + if (write_max > io_limit) + write_max = io_limit; + if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) + write_max = I2C_SMBUS_BLOCK_MAX; + at24->write_max = write_max; + + /* buffer (data + address at the beginning) */ + at24->writebuf = devm_kzalloc(&client->dev, write_max + 2, GFP_KERNEL); + if (!at24->writebuf) + return -ENOMEM; + } else { + dev_warn(&client->dev, "cannot write due to controller restrictions."); + } + } + + at24->client[0] = client; + + /* use dummy devices for multiple-address chips */ + for (i = 1; i < num_addresses; i++) { + at24->client[i] = i2c_new_dummy(client->adapter, client->addr + i); + if (!at24->client[i]) { + dev_err(&client->dev, "address 0x%02x unavailable\n", client->addr + i); + err = -EADDRINUSE; + goto err_clients; + } + } + + err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin); + if (err) + goto err_clients; + + i2c_set_clientdata(client, at24); + + printk(KERN_ALERT "at24_probe %s done\n", client->name); + + return 0; + +err_clients: + for (i = 1; i < num_addresses; i++) + if (at24->client[i]) + i2c_unregister_device(at24->client[i]); + + return err; +} + +static int at24_remove(struct i2c_client *client) +{ + struct at24_data *at24; + int i; + + at24 = i2c_get_clientdata(client); + sysfs_remove_bin_file(&client->dev.kobj, &at24->bin); + + for (i = 1; i < at24->num_addresses; i++) + i2c_unregister_device(at24->client[i]); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct i2c_board_info i2c_devs = { + I2C_BOARD_INFO("24c64-ctc", 0x57), +}; + +static struct i2c_adapter *adapter = NULL; +static struct i2c_client *client = NULL; + +static int ctc_at24c64_init(void) +{ + printk(KERN_ALERT "ctc_at24c64_init\n"); + + adapter = i2c_get_adapter(0); + if(adapter == NULL){ + printk(KERN_ALERT "i2c_get_adapter == NULL\n"); + return -1; + } + + client = i2c_new_device(adapter, &i2c_devs); + if(client == NULL){ + printk(KERN_ALERT "i2c_new_device == NULL\n"); + i2c_put_adapter(adapter); + adapter = NULL; + return -1; + } + + return 0; +} + +static void ctc_at24c64_exit(void) +{ + printk(KERN_ALERT "ctc_at24c64_exit\n"); + if(client){ + i2c_unregister_device(client); + } + if(adapter){ + i2c_put_adapter(adapter); + } +} + +static struct i2c_driver at24_ctc_driver = { + .driver = { + .name = "at24-ctc", + .owner = THIS_MODULE, + }, + .probe = at24_probe, + .remove = at24_remove, + .id_table = at24_ctc_ids, +}; + +static int __init at24_ctc_init(void) +{ + if (!io_limit) { + pr_err("at24_ctc: io_limit must not be 0!\n"); + return -EINVAL; + } + + io_limit = rounddown_pow_of_two(io_limit); + + ctc_at24c64_init(); + + return i2c_add_driver(&at24_ctc_driver); +} +module_init(at24_ctc_init); + +static void __exit at24_ctc_exit(void) +{ + ctc_at24c64_exit(); + i2c_del_driver(&at24_ctc_driver); +} +module_exit(at24_ctc_exit); + +MODULE_DESCRIPTION("Driver for most I2C EEPROMs"); +MODULE_AUTHOR("David Brownell and Wolfram Sang"); +MODULE_LICENSE("GPL"); +/* XXX */ + diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_e582_48x6q_platform.c b/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_e582_48x6q_platform.c new file mode 100644 index 000000000000..f72efee2a0d6 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/modules/centec_e582_48x6q_platform.c @@ -0,0 +1,1381 @@ +#include +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define PCA9548_CHANNEL_NUM 8 +#define PCA9548_ADAPT_ID_START 10 +#define SFP_NUM 48 +#define QSFP_NUM 6 +#define PORT_NUM (SFP_NUM+QSFP_NUM) +#endif + +#if SEP("i2c:master") +static struct i2c_adapter *i2c_adp_master = NULL; /* i2c-0-cpu */ + +static int e582_48x6q_init_i2c_master(void) +{ + /* find i2c-core master */ + i2c_adp_master = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e582_48x6q_init_i2c_master can't find i2c-core bus\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_master(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_adp_master)) { + i2c_put_adapter(i2c_adp_master); + i2c_adp_master = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:pca9548") +static struct pca954x_platform_mode i2c_dev_pca9548_platform_mode[PCA9548_CHANNEL_NUM] = { + [0] = { + .adap_id = PCA9548_ADAPT_ID_START, + .deselect_on_exit = 1, + .class = 0, + }, + [1] = { + .adap_id = PCA9548_ADAPT_ID_START + 1, + .deselect_on_exit = 1, + .class = 0, + }, + [2] = { + .adap_id = PCA9548_ADAPT_ID_START + 2, + .deselect_on_exit = 1, + .class = 0, + }, + [3] = { + .adap_id = PCA9548_ADAPT_ID_START + 3, + .deselect_on_exit = 1, + .class = 0, + }, + [4] = { + .adap_id = PCA9548_ADAPT_ID_START + 4, + .deselect_on_exit = 1, + .class = 0, + }, + [5] = { + .adap_id = PCA9548_ADAPT_ID_START + 5, + .deselect_on_exit = 1, + .class = 0, + }, + [6] = { + .adap_id = PCA9548_ADAPT_ID_START + 6, + .deselect_on_exit = 1, + .class = 0, + }, + [7] = { + .adap_id = PCA9548_ADAPT_ID_START + 7, + .deselect_on_exit = 1, + .class = 0, + } +}; +static struct pca954x_platform_data i2c_dev_pca9548_platform_data = { + .modes = i2c_dev_pca9548_platform_mode, + .num_modes = PCA9548_CHANNEL_NUM, +}; +static struct i2c_board_info i2c_dev_pca9548 = { + I2C_BOARD_INFO("pca9548", 0x70), + .platform_data = &i2c_dev_pca9548_platform_data, +}; +static struct i2c_client *i2c_client_pca9548x = NULL; + +static int e582_48x6q_init_i2c_pca9548(void) +{ + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e582_48x6q_init_i2c_pca9548 can't find i2c-core bus\n"); + return -1; + } + + /* install i2c-mux */ + i2c_client_pca9548x = i2c_new_device(i2c_adp_master, &i2c_dev_pca9548); + if(IS_INVALID_PTR(i2c_client_pca9548x)) + { + i2c_client_pca9548x = NULL; + printk(KERN_CRIT "install e582_48x6q board pca9548 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_pca9548(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_client_pca9548x)) { + i2c_unregister_device(i2c_client_pca9548x); + i2c_client_pca9548x = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:adt7470") +static struct i2c_board_info i2c_dev_adt7470 = { + I2C_BOARD_INFO("adt7470", 0x2F), +}; +static struct i2c_adapter *i2c_adp_adt7470 = NULL; /* pca9548x-channel 5 */ +static struct i2c_client *i2c_client_adt7470 = NULL; + +static int e582_48x6q_init_i2c_adt7470(void) +{ + i2c_adp_adt7470 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 5); + if(IS_INVALID_PTR(i2c_adp_adt7470)) + { + i2c_adp_adt7470 = NULL; + printk(KERN_CRIT "install e582_48x6q board adt7470 failed\n"); + return -1; + } + + i2c_client_adt7470 = i2c_new_device(i2c_adp_adt7470, &i2c_dev_adt7470); + if(IS_INVALID_PTR(i2c_client_adt7470)){ + i2c_client_adt7470 = NULL; + printk(KERN_CRIT "install e582_48x6q board adt7470 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_adt7470(void) +{ + if(IS_VALID_PTR(i2c_client_adt7470)) { + i2c_unregister_device(i2c_client_adt7470); + i2c_client_adt7470 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_adt7470)) { + i2c_put_adapter(i2c_adp_adt7470); + i2c_adp_adt7470 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:psu") +static struct i2c_adapter *i2c_adp_psu1 = NULL; /* psu1 channel 3 */ +static struct i2c_adapter *i2c_adp_psu2 = NULL; /* psu2 channel 1 */ +static struct i2c_board_info i2c_dev_psu1 = { + I2C_BOARD_INFO("i2c-psu1", 0x38), +}; +static struct i2c_board_info i2c_dev_psu2 = { + I2C_BOARD_INFO("i2c-psu2", 0x38), +}; +static struct i2c_client *i2c_client_psu1 = NULL; +static struct i2c_client *i2c_client_psu2 = NULL; + +static int e582_48x6q_init_i2c_psu(void) +{ + i2c_adp_psu1 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 3); + if(IS_INVALID_PTR(i2c_adp_psu1)) + { + i2c_adp_psu1 = NULL; + printk(KERN_CRIT "get e582_48x6q psu1 i2c-adp failed\n"); + return -1; + } + + i2c_adp_psu2 = i2c_get_adapter(PCA9548_ADAPT_ID_START + 1); + if(IS_INVALID_PTR(i2c_adp_psu2)) + { + i2c_adp_psu2 = NULL; + printk(KERN_CRIT "get e582_48x6q psu2 i2c-adp failed\n"); + return -1; + } + + i2c_client_psu1 = i2c_new_device(i2c_adp_psu1, &i2c_dev_psu1); + if(IS_INVALID_PTR(i2c_client_psu1)){ + i2c_client_psu1 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client psu1 failed\n"); + return -1; + } + + i2c_client_psu2 = i2c_new_device(i2c_adp_psu2, &i2c_dev_psu2); + if(IS_INVALID_PTR(i2c_client_psu2)){ + i2c_client_psu2 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client psu2 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_psu(void) +{ + if(IS_VALID_PTR(i2c_client_psu1)) { + i2c_unregister_device(i2c_client_psu1); + i2c_client_psu1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_psu2)) { + i2c_unregister_device(i2c_client_psu2); + i2c_client_psu2 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_psu1)) + { + i2c_put_adapter(i2c_adp_psu1); + i2c_adp_psu1 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_psu2)) + { + i2c_put_adapter(i2c_adp_psu2); + i2c_adp_psu2 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:epld") +static struct i2c_board_info i2c_dev_epld = { + I2C_BOARD_INFO("i2c-epld", 0x58), +}; +static struct i2c_client *i2c_client_epld = NULL; + +static int e582_48x6q_init_i2c_epld(void) +{ + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e582_48x6q_init_i2c_epld can't find i2c-core bus\n"); + return -1; + } + + i2c_client_epld = i2c_new_device(i2c_adp_master, &i2c_dev_epld); + if(IS_INVALID_PTR(i2c_client_epld)) + { + i2c_client_epld = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client epld failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_epld(void) +{ + if(IS_VALID_PTR(i2c_client_epld)) { + i2c_unregister_device(i2c_client_epld); + i2c_client_epld = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:gpio") +static struct i2c_board_info i2c_dev_gpio0 = { + I2C_BOARD_INFO("i2c-gpio0", 0x20), +}; +static struct i2c_board_info i2c_dev_gpio1 = { + I2C_BOARD_INFO("i2c-gpio1", 0x21), +}; +static struct i2c_board_info i2c_dev_gpio2 = { + I2C_BOARD_INFO("i2c-gpio2", 0x22), +}; +static struct i2c_board_info i2c_dev_gpio3 = { + I2C_BOARD_INFO("i2c-gpio3", 0x23), +}; +static struct i2c_board_info i2c_dev_gpio4 = { + I2C_BOARD_INFO("i2c-gpio4", 0x24), +}; +static struct i2c_client *i2c_client_gpio0 = NULL; +static struct i2c_client *i2c_client_gpio1 = NULL; +static struct i2c_client *i2c_client_gpio2 = NULL; +static struct i2c_client *i2c_client_gpio3 = NULL; +static struct i2c_client *i2c_client_gpio4 = NULL; + +static int e582_48x6q_init_i2c_gpio(void) +{ + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e582_48x6q_init_i2c_gpio can't find i2c-core bus\n"); + return -1; + } + + i2c_client_gpio0 = i2c_new_device(i2c_adp_master, &i2c_dev_gpio0); + if(IS_INVALID_PTR(i2c_client_gpio0)) + { + i2c_client_gpio0 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client gpio0 failed\n"); + return -1; + } + + i2c_client_gpio1 = i2c_new_device(i2c_adp_master, &i2c_dev_gpio1); + if(IS_INVALID_PTR(i2c_client_gpio1)) + { + i2c_client_gpio1 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client gpio1 failed\n"); + return -1; + } + + i2c_client_gpio2 = i2c_new_device(i2c_adp_master, &i2c_dev_gpio2); + if(IS_INVALID_PTR(i2c_client_gpio2)) + { + i2c_client_gpio2 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client gpio2 failed\n"); + return -1; + } + + i2c_client_gpio3 = i2c_new_device(i2c_adp_master, &i2c_dev_gpio3); + if(IS_INVALID_PTR(i2c_client_gpio3)) + { + i2c_client_gpio3 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client gpio3 failed\n"); + return -1; + } + + i2c_client_gpio4 = i2c_new_device(i2c_adp_master, &i2c_dev_gpio4); + if(IS_INVALID_PTR(i2c_client_gpio4)) + { + i2c_client_gpio4 = NULL; + printk(KERN_CRIT "create e582_48x6q board i2c client gpio4 failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_i2c_gpio(void) +{ + if(IS_VALID_PTR(i2c_client_gpio0)) { + i2c_unregister_device(i2c_client_gpio0); + i2c_client_gpio0 = NULL; + } + + if((i2c_client_gpio1)) { + i2c_unregister_device(i2c_client_gpio1); + i2c_client_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio2)) { + i2c_unregister_device(i2c_client_gpio2); + i2c_client_gpio2 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio3)) { + i2c_unregister_device(i2c_client_gpio3); + i2c_client_gpio3 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio4)) { + i2c_unregister_device(i2c_client_gpio4); + i2c_client_gpio4 = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:smbus") +static int e582_48x6q_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + } + else + { + *value = 0; + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} + +static int e582_48x6q_smbus_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_write_byte_data(client, reg, value); + if (ret != 0) + { + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} +#endif + +#if SEP("drivers:psu") +static struct class* psu_class = NULL; +static struct device* psu_dev_psu1 = NULL; +static struct device* psu_dev_psu2 = NULL; + +static ssize_t e582_48x6q_psu_read_presence(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char present_no = 0; + unsigned char present = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio0; + present_no = 17; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio0; + present_no = 9; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e582_48x6q_smbus_read_reg(i2c_psu_client, present_no/8, &present); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((present & (1<<(present_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x6q_psu_read_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char workstate_no = 0; + unsigned char workstate = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio0; + workstate_no = 21; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio0; + workstate_no = 13; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e582_48x6q_smbus_read_reg(i2c_psu_client, workstate_no/8, &workstate); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((workstate & (1<<(workstate_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static DEVICE_ATTR(psu_presence, S_IRUGO, e582_48x6q_psu_read_presence, NULL); +static DEVICE_ATTR(psu_status, S_IRUGO, e582_48x6q_psu_read_status, NULL); + +static int e582_48x6q_init_psu(void) +{ + int ret = 0; + + psu_class = class_create(THIS_MODULE, "psu"); + if (IS_INVALID_PTR(psu_class)) + { + psu_class = NULL; + printk(KERN_CRIT "create e582_48x6q class psu failed\n"); + return -1; + } + + psu_dev_psu1 = device_create(psu_class, NULL, MKDEV(222,0), NULL, "psu1"); + if (IS_INVALID_PTR(psu_dev_psu1)) + { + psu_dev_psu1 = NULL; + printk(KERN_CRIT "create e582_48x6q psu1 device failed\n"); + return -1; + } + + psu_dev_psu2 = device_create(psu_class, NULL, MKDEV(222,1), NULL, "psu2"); + if (IS_INVALID_PTR(psu_dev_psu2)) + { + psu_dev_psu2 = NULL; + printk(KERN_CRIT "create e582_48x6q psu2 device failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q psu1 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q psu1 device attr:status failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q psu2 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q psu2 device attr:status failed\n"); + return -1; + } + + return 0; +} + +static int e582_48x6q_exit_psu(void) +{ + if (IS_VALID_PTR(psu_dev_psu1)) + { + device_remove_file(psu_dev_psu1, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu1, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,0)); + } + + if (IS_VALID_PTR(psu_dev_psu2)) + { + device_remove_file(psu_dev_psu2, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu2, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,1)); + } + + if (IS_VALID_PTR(psu_class)) + { + class_destroy(psu_class); + psu_class = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:leds") +extern void e582_48x6q_led_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e582_48x6q_led_get(struct led_classdev *led_cdev); +extern void e582_48x6q_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e582_48x6q_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_system = { + .name = "system", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_idn = { + .name = "idn", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_fan1 = { + .name = "fan1", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_fan2 = { + .name = "fan2", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_fan3 = { + .name = "fan3", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_fan4 = { + .name = "fan4", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_psu1 = { + .name = "psu1", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_psu2 = { + .name = "psu2", + .brightness_set = e582_48x6q_led_set, + .brightness_get = e582_48x6q_led_get, +}; +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port1", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port2", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port3", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port4", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port5", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port6", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port7", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port8", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port9", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port10", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port11", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port12", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port13", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port14", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port15", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port16", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port17", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port18", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port19", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port20", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port21", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port22", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port23", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port24", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port25", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port26", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port27", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port28", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port29", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port30", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port31", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port32", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port33", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port34", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port35", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port36", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port37", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port38", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port39", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port40", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port41", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port42", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port43", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port44", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port45", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port46", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port47", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port48", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port49", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port50", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port51", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port52", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port53", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,}, +{ .name = "port54", .brightness_set = e582_48x6q_led_port_set, .brightness_get = e582_48x6q_led_port_get,} +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void e582_48x6q_led_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_epld; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x0F; + shift = 4; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x3; + mask = 0xFE; + shift = 0; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e582_48x6q_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return; + } + + led_value = ((led_value & mask) | ((set_value << shift) & (~mask))); + + ret = e582_48x6q_smbus_write_reg(i2c_led_client, reg, led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s led attr failed\n", led_cdev->name); + return; + } + + return; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return; +} + +enum led_brightness e582_48x6q_led_get(struct led_classdev *led_cdev) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_epld; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0xF0; + shift = 4; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x3; + mask = 0x01; + shift = 0; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e582_48x6q_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return 0; + } + + led_value = ((led_value & mask) >> shift); + + return led_value; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return 0; +} + +void e582_48x6q_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum-1] = set_value; + + return; +} + +enum led_brightness e582_48x6q_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum-1]; +} + +static int e582_48x6q_init_led(void) +{ + int ret = 0; + int i = 0; + + ret = led_classdev_register(NULL, &led_dev_system); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_system device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_idn); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_idn device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan1); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_fan1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan2); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_fan2 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan3); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_fan3 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan4); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_fan4 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu1); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_psu1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu2); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q led_dev_psu2 device failed\n"); + return -1; + } + + for (i=0; i PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + value = 0; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum + 31;/*32-39*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum + 7;/*16-23*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum - 17;/*0-7*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 1;/*24-31*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 25;/*8-15*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 9;/*32-39*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + reg_no = portNum - 25;/*24-29*/ + i2c_sfp_client = i2c_client_gpio4; + } + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x6q_smbus_write_reg(i2c_sfp_client, dir_bank, 0xff); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + } + + input_bank = (reg_no/8) + 0x0; + ret = e582_48x6q_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 );/*1:PRESENT 0:ABSENT*/ + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x6q_sfp_read_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char value = 0; + unsigned char reg_no = 0; + unsigned char dir_bank = 0; + unsigned char input_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + value = 0; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum + 23;/*24-31*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum - 1;/*8-15*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum + 15;/*32-39*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 9;/*16-23*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 33;/*0-7*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 17;/*24-31*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + printk(KERN_INFO "%s not supported!\n", name); + return sprintf(buf, "%d\n", 0); + } + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x6q_smbus_write_reg(i2c_sfp_client, dir_bank, 0xff); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + } + + input_bank = (reg_no/8) + 0x8; + ret = e582_48x6q_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp data:%s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e582_48x6q_sfp_write_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned char value = 0; + unsigned char set_value = simple_strtol(buf, NULL, 10); + unsigned char reg_no = 0; + unsigned char dir_bank = 0; + unsigned char input_bank = 0; + unsigned char output_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > PORT_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + return size; + } + + if ((portNum >= 1) && (portNum <= 8)) + { + reg_no = portNum + 23;/*24-31*/ + i2c_sfp_client = i2c_client_gpio0; + } + else if ((portNum >= 9) && (portNum <= 16)) + { + reg_no = portNum - 1;/*8-15*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 17) && (portNum <= 24)) + { + reg_no = portNum + 15;/*32-39*/ + i2c_sfp_client = i2c_client_gpio1; + } + else if ((portNum >= 25) && (portNum <= 32)) + { + reg_no = portNum - 9;/*16-23*/ + i2c_sfp_client = i2c_client_gpio2; + } + else if ((portNum >= 33) && (portNum <= 40)) + { + reg_no = portNum - 33;/*0-7*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 41) && (portNum <= 48)) + { + reg_no = portNum - 17;/*24-31*/ + i2c_sfp_client = i2c_client_gpio3; + } + else if ((portNum >= 49) && (portNum <= 54)) + { + printk(KERN_INFO "%s not supported!\n", name); + return size; + } + + set_value = ((set_value > 0) ? 0 : 1 ); + + dir_bank = (reg_no/8) + 0x18; + ret = e582_48x6q_smbus_write_reg(i2c_sfp_client, dir_bank, 0x0); + if (ret != 0) + { + printk(KERN_CRIT "Error: read sfp data:%s set dir-ctl failed\n", attr->attr.name); + return size; + } + + input_bank = (reg_no/8) + 0x8; + ret = e582_48x6q_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s presence failed\n", name); + return size; + } + + if (set_value) + { + value = (value | (1<<(reg_no % 8))); + } + else + { + value = (value & (~(1<<(reg_no % 8)))); + } + + output_bank = (reg_no/8) + 0x8; + ret = e582_48x6q_smbus_write_reg(i2c_sfp_client, output_bank, value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s presence failed\n", name); + return size; + } + + return size; +} + +static DEVICE_ATTR(sfp_presence, S_IRUGO, e582_48x6q_sfp_read_presence, NULL); +static DEVICE_ATTR(sfp_enable, S_IRUGO|S_IWUSR, e582_48x6q_sfp_read_enable, e582_48x6q_sfp_write_enable); +static int e582_48x6q_init_sfp(void) +{ + int ret = 0; + int i = 0; + + sfp_class = class_create(THIS_MODULE, "sfp"); + if (IS_INVALID_PTR(sfp_class)) + { + sfp_class = NULL; + printk(KERN_CRIT "create e582_48x6q class sfp failed\n"); + return -1; + } + + for (i=1; i<=PORT_NUM; i++) + { + sfp_dev[i] = device_create(sfp_class, NULL, MKDEV(223,i), NULL, "sfp%d", i); + if (IS_INVALID_PTR(sfp_dev[i])) + { + sfp_dev[i] = NULL; + printk(KERN_CRIT "create e582_48x6q sfp[%d] device failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q sfp[%d] device attr:presence failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_enable); + if (ret != 0) + { + printk(KERN_CRIT "create e582_48x6q sfp[%d] device attr:enable failed\n", i); + continue; + } + } + + return ret; +} + +static int e582_48x6q_exit_sfp(void) +{ + int i = 0; + + for (i=1; i<=PORT_NUM; i++) + { + if (IS_VALID_PTR(sfp_dev[i])) + { + device_remove_file(sfp_dev[i], &dev_attr_sfp_presence); + device_remove_file(sfp_dev[i], &dev_attr_sfp_enable); + device_destroy(sfp_class, MKDEV(223,i)); + sfp_dev[i] = NULL; + } + } + + if (IS_VALID_PTR(sfp_class)) + { + class_destroy(sfp_class); + sfp_class = NULL; + } + + return 0; +} +#endif + +static int e582_48x6q_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "install e582_48x6q board dirver...\n"); + + ret = e582_48x6q_init_i2c_master(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_i2c_pca9548(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_i2c_adt7470(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_i2c_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_i2c_epld(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_i2c_gpio(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_led(); + if (ret != 0) + { + failed = 1; + } + + ret = e582_48x6q_init_sfp(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "install e582_48x6q board driver failed\n"); + else + printk(KERN_ALERT "install e582_48x6q board dirver...ok\n"); + + return 0; +} + +static void e582_48x6q_exit(void) +{ + printk(KERN_INFO "uninstall e582_48x6q board dirver...\n"); + + e582_48x6q_exit_sfp(); + e582_48x6q_exit_led(); + e582_48x6q_exit_psu(); + e582_48x6q_exit_i2c_gpio(); + e582_48x6q_exit_i2c_epld(); + e582_48x6q_exit_i2c_psu(); + e582_48x6q_exit_i2c_adt7470(); + e582_48x6q_exit_i2c_pca9548(); + e582_48x6q_exit_i2c_master(); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("yangbs centecNetworks, Inc"); +MODULE_DESCRIPTION("e582-48x6q board driver"); +module_init(e582_48x6q_init); +module_exit(e582_48x6q_exit); + diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform.sh b/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform.sh new file mode 100755 index 000000000000..e8f81a20d9d1 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +#platform init script for centec e582-48x6q + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # I801 adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus I801 adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find I801" && exit 1 +} + +init_devnum + +if [ "$1" == "init" ]; then + #install drivers and dependencies + depmod -a + modprobe i2c-i801 + modprobe i2c-dev + modprobe i2c-mux + modprobe i2c-smbus + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + i2cset -y 0 0x58 0x8 0x3f + i2cset -y 0 0x20 0x1b 0x0 + i2cset -y 0 0x20 0xb 0x0 + i2cset -y 0 0x21 0x19 0x0 + i2cset -y 0 0x21 0x9 0x0 + i2cset -y 0 0x21 0x1c 0x0 + i2cset -y 0 0x21 0xc 0x0 + i2cset -y 0 0x22 0x1a 0x0 + i2cset -y 0 0x22 0xa 0x0 + i2cset -y 0 0x23 0x18 0x0 + i2cset -y 0 0x23 0x8 0x0 + i2cset -y 0 0x23 0x1b 0x0 + i2cset -y 0 0x23 0xb 0x0 + modprobe lm77 + modprobe tun + modprobe dal + modprobe centec_at24c64 + modprobe centec_e582_48x6q_platform + + #start platform monitor + rm -rf /usr/bin/platform_monitor + ln -s /usr/bin/48x6q_platform_monitor.py /usr/bin/platform_monitor + python /usr/bin/platform_monitor & +elif [ "$1" == "deinit" ]; then + kill -9 $(pidof platform_monitor) > /dev/null 2>&1 + rm -rf /usr/bin/platform_monitor + modprobe -r centec_e582_48x6q_platform + modprobe -r centec_at24c64 + modprobe -r dal + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev +else + echo "e582-48x6q_platform : Invalid option !" +fi diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform_monitor.py b/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform_monitor.py new file mode 100644 index 000000000000..d08802a35f3b --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/scripts/48x6q_platform_monitor.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of sfp presence scan logic +# +############################################################################# + +try: + import os + import os.path + import threading + import time + import logging + import struct + import syslog + import swsssdk + from socket import * + from select import * +except ImportError, e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-pmon") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + +PORT_NUMBER = (48+6) + +class PlatformMonitor: + + """init board platform default config""" + def __init__(self): + """[ctlid, slavedevid]""" + self.fiber_mapping = [(0, 0)] # res + self.fiber_mapping.extend([(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7)]) # panel port 1~8 + self.fiber_mapping.extend([(0, 14), (0, 13), (0, 15), (0, 12), (0, 8), (0, 11), (0, 9), (0, 10)]) # panel port 9~16 + self.fiber_mapping.extend([(0, 22), (0, 21), (0, 23), (0, 20), (0, 16), (0, 19), (0, 17), (0, 18)]) # panel port 17~24 + self.fiber_mapping.extend([(1, 4), (1, 3), (1, 5), (1, 2), (1, 6), (1, 1), (1, 7), (1, 0)]) # panel port 25~32 + self.fiber_mapping.extend([(1, 8), (1, 15), (1, 9), (1, 14), (1, 10), (1, 13), (1, 11), (1, 12)]) # panel port 33~40 + self.fiber_mapping.extend([(1, 22), (1, 21), (1, 23), (1, 20), (1, 16), (1, 19), (1, 17), (1, 18)]) # panel port 41~48 + self.fiber_mapping.extend([(1, 28), (1, 29), (1, 26), (1, 27), (1, 24), (1, 25)]) # panel port 49~54 + + self.udpClient = socket(AF_INET, SOCK_DGRAM) + self.sfp_present = [0]*(PORT_NUMBER+1) + self.sfp_enable = [0]*(PORT_NUMBER+1) + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + self.sfp_scan_timer = 0 + + def is_qsfp(self, port): + if port <= 48: + return False + else: + return True + + def get_sfp_present(self, port): + with open(self.f_sfp_present.format(port), 'r') as sfp_file: + return int(sfp_file.read()) + + def set_sfp_present(self, port, present): + self.sfp_present[port] = present + + def set_sfp_enable(self, port, enable): + if self.is_qsfp(port): + if enable: + with open(self.f_sfp_enable.format(port), 'w') as sfp_file: + sfp_file.write("1") + self.sfp_enable[port] = 1 + else: + with open(self.f_sfp_enable.format(port), 'w') as sfp_file: + sfp_file.write("0") + self.sfp_enable[port] = 0 + else: + (ctlid, devid) = self.fiber_mapping[port] + req = struct.pack('=HHHBBHIBBBBI', 0, 9, 16, ctlid, devid, 0x50, 0, 0x56, 1, 0xf, 0, 1) + self.udpClient.sendto(req, ('localhost', 8101)) + rsp, addr = self.udpClient.recvfrom(1024) + rsp_data = struct.unpack('=HHHBBHIBBBBIi512B', rsp) + enable_v = rsp_data[13] + if enable: + enable_v &= 0xf0 + else: + enable_v |= 0x0f + data = struct.pack('=HHHBBHBBBB', 0, 11, 8, ctlid, 0x56, 0x50, devid, enable_v, 0xf, 0) + self.udpClient.sendto(data, ('localhost', 8101)) + DBG_PRINT("set sfp{} to {}".format(port, ("enable" if enable else "disable"))) + + def initialize_configdb(self): + try: + f_mac = os.popen('ip link show eth0 | grep ether | awk \'{print $2}\'') + mac_addr = f_mac.read(17) + last_byte = mac_addr[-2:] + aligned_last_byte = format(int(int(str(last_byte), 16) + 1), '02x') + mac_addr = mac_addr[:-2] + aligned_last_byte + DBG_PRINT("start connect swss config-db to set device mac-address") + swss = swsssdk.SonicV2Connector() + swss.connect(swss.CONFIG_DB) + swss.set(swss.CONFIG_DB, "DEVICE_METADATA|localhost", 'mac', mac_addr) + mac_addr = swss.get(swss.CONFIG_DB, "DEVICE_METADATA|localhost", 'mac') + DBG_PRINT("set device mac-address: %s" % mac_addr) + except IOError as e: + DBG_PRINT(str(e)) + + def initialize_rpc(self): + while True: + try: + r_sel = [self.udpClient] + echo_req = struct.pack('=HHH', 0, 1, 0) + self.udpClient.sendto(echo_req, ('localhost', 8101)) + result = select(r_sel, [], [], 1) + if self.udpClient in result[0]: + echo_rsp, srv_addr = self.udpClient.recvfrom(1024) + if echo_rsp: + break + DBG_PRINT("connect to sdk rpc server timeout, try again.") + except IOError as e: + DBG_PRINT(str(e)) + + DBG_PRINT("connect to sdk rpc server success.") + + def initialize_gpio(self): + # set gpio 1,2,3,4,5,6,7,8 output mode + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 1, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 2, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 3, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 4, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 5, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 6, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 7, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 1, 8, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + # set gpio 1,2,3,4,5,6,7,8 output 0 to reset i2c bridge + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 1, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 2, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 3, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 4, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 5, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 6, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 7, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 8, 0) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + # set gpio 1,2,3,4,5,6,7,8 output 1 to release i2c bridge + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 1, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 2, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 3, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 4, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 5, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 6, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 7, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + gpio_init = struct.pack('=HHHBBB', 0, 13, 3, 2, 8, 1) + self.udpClient.sendto(gpio_init, ('localhost', 8101)) + DBG_PRINT("config ctc chip gpio done.") + + def initialize_sfp(self): + try: + for port in range(1, PORT_NUMBER+1): + if self.get_sfp_present(port): + self.set_sfp_present(port, 1) + self.set_sfp_enable(port, 1) + else: + self.set_sfp_present(port, 0) + self.set_sfp_enable(port, 0) + except IOError as e: + DBG_PRINT(str(e)) + + def initialize(self): + DBG_PRINT("start connect to sdk rpc server.") + + self.initialize_configdb() + self.initialize_rpc() + self.initialize_gpio() + self.initialize_sfp() + + def sfp_scan(self): + try: + for port in range(1, PORT_NUMBER+1): + cur_present = self.get_sfp_present(port) + if self.sfp_present[port] != cur_present: + self.set_sfp_present(port, cur_present) + self.set_sfp_enable(port, cur_present) + except IOError as e: + DBG_PRINT(str(e)) + + def start(self): + while True: + self.sfp_scan() + time.sleep(1) + +if __name__ == "__main__": + monitor = PlatformMonitor() + monitor.initialize() + monitor.start() + diff --git a/platform/centec/sonic-platform-modules-e582/48x6q/service/48x6q_platform.service b/platform/centec/sonic-platform-modules-e582/48x6q/service/48x6q_platform.service new file mode 100644 index 000000000000..ad9b1fb1b3a7 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/48x6q/service/48x6q_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec e582 48x6q platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-e582-48x6q start +ExecStop=-/etc/init.d/platform-modules-e582-48x6q stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec/sonic-platform-modules-e582/LICENSE b/platform/centec/sonic-platform-modules-e582/LICENSE new file mode 100644 index 000000000000..99228517bae7 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2017 Centec, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/centec/sonic-platform-modules-e582/README.md b/platform/centec/sonic-platform-modules-e582/README.md new file mode 100644 index 000000000000..61b3ef6c87f4 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/README.md @@ -0,0 +1 @@ +platform drivers for Centec E582 for the SONiC project diff --git a/platform/centec/sonic-platform-modules-e582/debian/changelog b/platform/centec/sonic-platform-modules-e582/debian/changelog new file mode 100644 index 000000000000..3f4ff89c1bee --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/changelog @@ -0,0 +1,11 @@ +sonic-centec-platform-modules (1.1) unstable; urgency=low + + * Add support for centec e582-48x2q4z + + -- yangbs Thu, 25 Jan 2018 13:43:40 +0800 + +sonic-centec-platform-modules (1.0) unstable; urgency=low + + * Initial release + + -- yangbs Mon, 22 Jan 2018 13:43:40 +0800 diff --git a/platform/centec/sonic-platform-modules-e582/debian/compat b/platform/centec/sonic-platform-modules-e582/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/centec/sonic-platform-modules-e582/debian/control b/platform/centec/sonic-platform-modules-e582/debian/control new file mode 100644 index 000000000000..97f617d4836a --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/control @@ -0,0 +1,17 @@ +Source: sonic-centec-platform-modules +Section: main +Priority: extra +Maintainer: yangbs +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-e582-48x2q4z +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-e582-48x6q +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.init b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.init new file mode 100755 index 000000000000..3ef5e7e30b6d --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.init @@ -0,0 +1,38 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup e582-48x2q4z board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + /usr/bin/48x2q4z_platform.sh init + + echo "done." + ;; + +stop) + /usr/bin/48x2q4z_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: service platform-modules-e582-48x2q4z {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.install b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.install new file mode 100644 index 000000000000..30a343ff53b1 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.install @@ -0,0 +1,4 @@ +48x2q4z/cfg/48x2q4z-modules.conf etc/modules-load.d +48x2q4z/scripts/48x2q4z_platform.sh usr/bin +48x2q4z/scripts/48x2q4z_platform_monitor.py usr/bin +48x2q4z/service/48x2q4z_platform.service lib/systemd/system diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.postinst b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.postinst new file mode 100644 index 000000000000..b4a1fcbe4e6c --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x2q4z.postinst @@ -0,0 +1,3 @@ +depmod -a +systemctl enable 48x2q4z_platform.service +systemctl start 48x2q4z_platform.service diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.init b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.init new file mode 100755 index 000000000000..1c5b0c1c4978 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.init @@ -0,0 +1,38 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup e582-48x6q board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + /usr/bin/48x6q_platform.sh init + + echo "done." + ;; + +stop) + /usr/bin/48x6q_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: service platform-modules-e582-48x6q {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.install b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.install new file mode 100644 index 000000000000..76254afb3a29 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.install @@ -0,0 +1,4 @@ +48x6q/cfg/48x6q-modules.conf etc/modules-load.d +48x6q/scripts/48x6q_platform.sh usr/bin +48x6q/scripts/48x6q_platform_monitor.py usr/bin +48x6q/service/48x6q_platform.service lib/systemd/system diff --git a/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.postinst b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.postinst new file mode 100644 index 000000000000..fea0c4eebda8 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/platform-modules-e582-48x6q.postinst @@ -0,0 +1,3 @@ +depmod -a +systemctl enable 48x6q_platform.service +systemctl start 48x6q_platform.service diff --git a/platform/centec/sonic-platform-modules-e582/debian/rules b/platform/centec/sonic-platform-modules-e582/debian/rules new file mode 100755 index 000000000000..b726f62c8c68 --- /dev/null +++ b/platform/centec/sonic-platform-modules-e582/debian/rules @@ -0,0 +1,39 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= 48x6q 48x2q4z + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/../centec-dal + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-e582-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp -f $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-e582-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp -f $(MOD_SRC_DIR)/../centec-dal/*.ko debian/platform-modules-e582-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/modules/*.ko; \ + rm -rf debian/platform-modules-e582-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR)/*.ko; \ + done) + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/../centec-dal clean; \ + rm -rf $(MOD_SRC_DIR)/../centec-dal/*.ko + diff --git a/platform/centec/sonic-platform-modules-embedway/LICENSE b/platform/centec/sonic-platform-modules-embedway/LICENSE new file mode 100644 index 000000000000..99228517bae7 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2017 Centec, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/centec/sonic-platform-modules-embedway/README.md b/platform/centec/sonic-platform-modules-embedway/README.md new file mode 100644 index 000000000000..61b3ef6c87f4 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/README.md @@ -0,0 +1 @@ +platform drivers for Centec E582 for the SONiC project diff --git a/platform/centec/sonic-platform-modules-embedway/debian/changelog b/platform/centec/sonic-platform-modules-embedway/debian/changelog new file mode 100644 index 000000000000..2a2f05ab70c6 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/debian/changelog @@ -0,0 +1,5 @@ +sonic-platform-modules-embedway (1.1) unstable; urgency=low + + * Initial release + + -- yangbs Mon, 22 Jan 2018 13:43:40 +0800 diff --git a/platform/centec/sonic-platform-modules-embedway/debian/compat b/platform/centec/sonic-platform-modules-embedway/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/centec/sonic-platform-modules-embedway/debian/control b/platform/centec/sonic-platform-modules-embedway/debian/control new file mode 100644 index 000000000000..6fb02a824826 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/debian/control @@ -0,0 +1,12 @@ +Source: sonic-platform-modules-embedway +Section: main +Priority: extra +Maintainer: yangbs +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-embedway-es6220 +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/centec/sonic-platform-modules-embedway/debian/platform-modules-embedway-es6220.init b/platform/centec/sonic-platform-modules-embedway/debian/platform-modules-embedway-es6220.init new file mode 100755 index 000000000000..76d758cf53c0 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/debian/platform-modules-embedway-es6220.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup e582-48x2q4z board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + /usr/bin/es6220_platform.sh init + /usr/bin/add_crontab_remove_syslog.sh + /usr/bin/remove_syslog.sh + /usr/bin/create_eeprom.sh + + echo "done." + ;; + +stop) + /usr/bin/es6220_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: service platform-modules-embedway-es6220 {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/centec/sonic-platform-modules-embedway/debian/platform-modules-embedway-es6220.install b/platform/centec/sonic-platform-modules-embedway/debian/platform-modules-embedway-es6220.install new file mode 100644 index 000000000000..004148fe9932 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/debian/platform-modules-embedway-es6220.install @@ -0,0 +1,5 @@ +es6220/scripts/es6220_platform.sh usr/bin +es6220/scripts/create_eeprom.sh usr/bin +es6220/scripts/add_crontab_remove_syslog.sh usr/bin +es6220/scripts/remove_syslog.sh usr/bin +es6220/service/es6220_platform.service lib/systemd/system diff --git a/platform/centec/sonic-platform-modules-embedway/debian/platform-modules-embedway-es6220.postinst b/platform/centec/sonic-platform-modules-embedway/debian/platform-modules-embedway-es6220.postinst new file mode 100644 index 000000000000..35f3ee2308a6 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/debian/platform-modules-embedway-es6220.postinst @@ -0,0 +1,3 @@ +depmod -a +systemctl enable es6220_platform.service +systemctl start es6220_platform.service diff --git a/platform/centec/sonic-platform-modules-embedway/debian/rules b/platform/centec/sonic-platform-modules-embedway/debian/rules new file mode 100755 index 000000000000..250c0861e196 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/debian/rules @@ -0,0 +1,25 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) + +%: + dh $@ + +override_dh_auto_build: + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/../centec-dal + +override_dh_auto_install: + dh_installdirs -pplatform-modules-embedway-es6220 \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp -f $(MOD_SRC_DIR)/../centec-dal/*.ko debian/platform-modules-embedway-es6220/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/../centec-dal clean; \ + rm -rf $(MOD_SRC_DIR)/../centec-dal/*.ko diff --git a/platform/centec/sonic-platform-modules-embedway/es6220/scripts/add_crontab_remove_syslog.sh b/platform/centec/sonic-platform-modules-embedway/es6220/scripts/add_crontab_remove_syslog.sh new file mode 100755 index 000000000000..f5db8f0fc68e --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/es6220/scripts/add_crontab_remove_syslog.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +#sed -n '7p' /etc/rsyslog.d/99-default.conf +sudo sed -i '7c !user.debug;*.*;cron,auth,authpriv.none -/var/log/syslog' /etc/rsyslog.d/99-default.conf +sudo sed -i '10c user.debug /var/log/sdkdebug' /etc/rsyslog.d/99-default.conf +#sed -n '7p' /etc/rsyslog.d/99-default.conf +sudo service rsyslog restart + +sudo sed -i '9c */5 * * * * root /usr/bin/remove_syslog.sh' /etc/crontab +#echo "*/5 * * * * root /usr/bin/remove_syslog.sh" >> /etc/crontab + +exit 0 diff --git a/platform/centec/sonic-platform-modules-embedway/es6220/scripts/create_eeprom.sh b/platform/centec/sonic-platform-modules-embedway/es6220/scripts/create_eeprom.sh new file mode 100755 index 000000000000..052191a33803 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/es6220/scripts/create_eeprom.sh @@ -0,0 +1,18 @@ +#! /bin/bash + +#find cache of eeprom and delete, otherwise will dislay cache +cache_file="/var/cache/sonic/decode-syseeprom/syseeprom_cache" +if [ -f $cache_file ]; then + rm -f $cache_file +fi + +#create new device for eeprom +tmp=`i2cdetect -l | grep CP` +bus_num=${tmp:4:1} + +path="/sys/bus/i2c/devices/i2c-${bus_num}" + +cd $path +echo "24c512 0x56" > new_device + +sudo dd if=/sys/bus/i2c/devices/${bus_num}-0056/eeprom of=/home/admin/eeprom.bin bs=1 count=512 diff --git a/platform/centec/sonic-platform-modules-embedway/es6220/scripts/es6220_platform.sh b/platform/centec/sonic-platform-modules-embedway/es6220/scripts/es6220_platform.sh new file mode 100755 index 000000000000..3f6990dc46d9 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/es6220/scripts/es6220_platform.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +#platform init script for embedway es6220 + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # I801 adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus I801 adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find I801" && exit 1 +} + +init_devnum + +if [ "$1" == "init" ]; then + #install drivers and dependencies + depmod -a + modprobe dal + +elif [ "$1" == "deinit" ]; then + modprobe -r dal +else + echo "e582-48x2q4z_platform : Invalid option !" +fi diff --git a/platform/centec/sonic-platform-modules-embedway/es6220/scripts/remove_syslog.sh b/platform/centec/sonic-platform-modules-embedway/es6220/scripts/remove_syslog.sh new file mode 100755 index 000000000000..1366ffbdd819 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/es6220/scripts/remove_syslog.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +#remove syslog + +sudo find /var/log/ -mtime +7 -name "syslog.*" | sudo xargs rm -rf + +#echo "remove_syslog.sh crontab is running" >> /home/admin/shell.txt + +exit 0 diff --git a/platform/centec/sonic-platform-modules-embedway/es6220/service/es6220_platform.service b/platform/centec/sonic-platform-modules-embedway/es6220/service/es6220_platform.service new file mode 100644 index 000000000000..111ed4952649 --- /dev/null +++ b/platform/centec/sonic-platform-modules-embedway/es6220/service/es6220_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=embedway es6220 platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-embedway-es6220 start +ExecStop=-/etc/init.d/platform-modules-embedway-es6220 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/generic/aboot-image.mk b/platform/generic/aboot-image.mk new file mode 100644 index 000000000000..c3f21b616254 --- /dev/null +++ b/platform/generic/aboot-image.mk @@ -0,0 +1,8 @@ +# sonic aboot installer + +SONIC_GENERIC_ABOOT_IMAGE = sonic-aboot-generic.swi +$(SONIC_GENERIC_ABOOT_IMAGE)_MACHINE = generic +$(SONIC_GENERIC_ABOOT_IMAGE)_IMAGE_TYPE = aboot +$(SONIC_GENERIC_ABOOT_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_GENERIC_ABOOT_IMAGE)_DOCKERS = +SONIC_INSTALLERS += $(SONIC_GENERIC_ABOOT_IMAGE) diff --git a/platform/generic/onie-image.mk b/platform/generic/onie-image.mk new file mode 100644 index 000000000000..5dc8bfb9f885 --- /dev/null +++ b/platform/generic/onie-image.mk @@ -0,0 +1,8 @@ +# sonic generic ONIE image installer + +SONIC_GENERIC_ONIE_IMAGE = sonic-generic.bin +$(SONIC_GENERIC_ONIE_IMAGE)_MACHINE = generic +$(SONIC_GENERIC_ONIE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_GENERIC_ONIE_IMAGE)_INSTALLS = $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_GENERIC_ONIE_IMAGE)_DOCKERS = +SONIC_INSTALLERS += $(SONIC_GENERIC_ONIE_IMAGE) diff --git a/platform/generic/platform.conf b/platform/generic/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/generic/rules.mk b/platform/generic/rules.mk new file mode 100644 index 000000000000..c836c1faec1a --- /dev/null +++ b/platform/generic/rules.mk @@ -0,0 +1,10 @@ +include $(PLATFORM_PATH)/aboot-image.mk +include $(PLATFORM_PATH)/onie-image.mk + +SONIC_ALL += $(DOCKER_DATABASE) \ + $(DOCKER_SNMP) \ + $(DOCKER_LLDP) \ + $(DOCKER_PLATFORM_MONITOR) \ + $(DOCKER_DHCP_RELAY) \ + $(DOCKER_PTF) \ + $(SONIC_GENERIC_ONIE_IMAGE) diff --git a/platform/innovium/docker-syncd-invm-rpc.mk b/platform/innovium/docker-syncd-invm-rpc.mk new file mode 100755 index 000000000000..62d6891bbc21 --- /dev/null +++ b/platform/innovium/docker-syncd-invm-rpc.mk @@ -0,0 +1,17 @@ +# docker image for innovium syncd with rpc + +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) $(PTF) +$(DOCKER_SYNCD_INVM_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_INVM_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_INVM_RPC) +endif + +$(DOCKER_SYNCD_INVM_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_INVM_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_INVM_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_INVM_RPC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_INVM_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_INVM_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/innovium/docker-syncd-invm-rpc/Dockerfile.j2 b/platform/innovium/docker-syncd-invm-rpc/Dockerfile.j2 new file mode 100755 index 000000000000..eea52e3398b8 --- /dev/null +++ b/platform/innovium/docker-syncd-invm-rpc/Dockerfile.j2 @@ -0,0 +1,57 @@ +FROM docker-syncd-invm + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_invm_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -P syncd + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + libpython2.7 \ + libjansson4 \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_invm_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/innovium/docker-syncd-invm-rpc/ptf_nn_agent.conf b/platform/innovium/docker-syncd-invm-rpc/ptf_nn_agent.conf new file mode 100755 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/innovium/docker-syncd-invm-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/innovium/docker-syncd-invm.mk b/platform/innovium/docker-syncd-invm.mk new file mode 100755 index 000000000000..52c11b90911d --- /dev/null +++ b/platform/innovium/docker-syncd-invm.mk @@ -0,0 +1,16 @@ +# docker image for innovium syncd + +DOCKER_SYNCD_PLATFORM_CODE = invm +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) $(PYTHON_SDK_API) $(INVM_LIBSAI) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) + +SONIC_STRETCH_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_STRETCH_DBG_DOCKERS += $(DOCKER_SYNCD_BASE_DBG) + +$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/innovium/docker-syncd-invm/Dockerfile.j2 b/platform/innovium/docker-syncd-invm/Dockerfile.j2 new file mode 100755 index 000000000000..ab4be823de66 --- /dev/null +++ b/platform/innovium/docker-syncd-invm/Dockerfile.j2 @@ -0,0 +1,33 @@ +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 + +COPY \ +{% for deb in docker_syncd_invm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +# Needed for Innovium Debug Shell +RUN apt-get install -y net-tools +RUN apt-get install -y libpython2.7 +RUN apt-get install -y libjansson4 + +RUN dpkg -i \ +{% for deb in docker_syncd_invm_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/innovium/docker-syncd-invm/supervisord.conf b/platform/innovium/docker-syncd-invm/supervisord.conf new file mode 100755 index 000000000000..ffdb5fd85c47 --- /dev/null +++ b/platform/innovium/docker-syncd-invm/supervisord.conf @@ -0,0 +1,32 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python2 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running diff --git a/platform/innovium/invm-sai.mk b/platform/innovium/invm-sai.mk new file mode 100755 index 000000000000..25e490e44f83 --- /dev/null +++ b/platform/innovium/invm-sai.mk @@ -0,0 +1,15 @@ +# INVM SAI + +INVM_SAI_ONLINE = https://github.com/Innovium/SONiC/raw/master/debian/master + +INVM_LIBSAI = isai.deb +INVM_HSAI = saihdr.deb +INVM_DRV = ipd.deb + +$(INVM_LIBSAI)_URL = $(INVM_SAI_ONLINE)/$(INVM_LIBSAI) +$(INVM_HSAI)_URL = $(INVM_SAI_ONLINE)/$(INVM_HSAI) +$(INVM_DRV)_URL = $(INVM_SAI_ONLINE)/$(INVM_DRV) + +$(eval $(call add_conflict_package,$(INVM_HSAI),$(LIBSAIVS_DEV))) + +SONIC_ONLINE_DEBS += $(INVM_LIBSAI) $(INVM_HSAI) $(INVM_DRV) diff --git a/platform/innovium/libsaithrift-dev.mk b/platform/innovium/libsaithrift-dev.mk new file mode 100755 index 000000000000..5357705bac98 --- /dev/null +++ b/platform/innovium/libsaithrift-dev.mk @@ -0,0 +1,7 @@ +# libsaithrift-dev package + +LIBSAITHRIFT_DEV_INVM = libsaithrift-dev_0.9.4_$(CONFIGURED_ARCH).deb +$(LIBSAITHRIFT_DEV_INVM)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV_INVM)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(THRIFT_COMPILER) $(INVM_LIBSAI) $(INVM_HSAI) +$(LIBSAITHRIFT_DEV_INVM)_RDEPENDS += $(LIBTHRIFT) $(INVM_HSAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV_INVM) diff --git a/platform/innovium/one-image.mk b/platform/innovium/one-image.mk new file mode 100755 index 000000000000..c88ec5e65cdf --- /dev/null +++ b/platform/innovium/one-image.mk @@ -0,0 +1,11 @@ +# sonic innovium ONE image installer + +SONIC_ONE_IMAGE = sonic-innovium.bin +$(SONIC_ONE_IMAGE)_MACHINE = innovium +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CEL_MIDSTONE_200I_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELTA_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_INSTALLS += $(INVM_DRV) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/innovium/platform-modules-cel.mk b/platform/innovium/platform-modules-cel.mk new file mode 100755 index 000000000000..4b394c36ec88 --- /dev/null +++ b/platform/innovium/platform-modules-cel.mk @@ -0,0 +1,11 @@ +# Celestica platform modules + +CEL_PLATFORM_MODULE_VERSION = 0.2.2 + +export CEL_PLATFORM_MODULE_VERSION + +CEL_MIDSTONE_200I_PLATFORM_MODULE = platform-modules-midstone-200i_$(CEL_PLATFORM_MODULE_VERSION)_$(CONFIGURED_ARCH).deb +$(CEL_MIDSTONE_200I_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cel +$(CEL_MIDSTONE_200I_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(CEL_MIDSTONE_200I_PLATFORM_MODULE)_PLATFORM = x86_64-cel_midstone-r0 +SONIC_DPKG_DEBS += $(CEL_MIDSTONE_200I_PLATFORM_MODULE) diff --git a/platform/innovium/platform-modules-delta.mk b/platform/innovium/platform-modules-delta.mk new file mode 100644 index 000000000000..6a6dc45763eb --- /dev/null +++ b/platform/innovium/platform-modules-delta.mk @@ -0,0 +1,12 @@ +# Delta Platform modules + +DELTA_ETC032IF_PLATFORM_MODULE_VERSION = 1.1 + +export DELTA_ETC032IF_PLATFORM_MODULE_VERSION + +DELTA_PLATFORM_MODULE = platform-modules-et-c032if_$(DELTA_ETC032IF_PLATFORM_MODULE_VERSION)_$(CONFIGURED_ARCH).deb +$(DELTA_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-delta +$(DELTA_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(DELTA_PLATFORM_MODULE)_PLATFORM = x86_64-delta_et-c032if-r0 + +SONIC_DPKG_DEBS += $(DELTA_PLATFORM_MODULE) diff --git a/platform/innovium/platform.conf b/platform/innovium/platform.conf new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/innovium/python-saithrift.mk b/platform/innovium/python-saithrift.mk new file mode 100755 index 000000000000..23d7df188346 --- /dev/null +++ b/platform/innovium/python-saithrift.mk @@ -0,0 +1,6 @@ +# python-saithrift package + +PYTHON_SAITHRIFT_INVM = python-saithrift_1.2.1_$(CONFIGURED_ARCH).deb +$(PYTHON_SAITHRIFT_INVM)_SRC_PATH = $(SRC_PATH)/SAI +$(PYTHON_SAITHRIFT_INVM)_DEPENDS += $(INVM_LIBSAI) $(INVM_HSAI) $(THRIFT_COMPILER) $(PYTHON_THRIFT) $(LIBTHRIFT_DEV) +SONIC_DPKG_DEBS += $(PYTHON_SAITHRIFT_INVM) diff --git a/platform/innovium/rules.mk b/platform/innovium/rules.mk new file mode 100755 index 000000000000..ea23466ad578 --- /dev/null +++ b/platform/innovium/rules.mk @@ -0,0 +1,20 @@ +include $(PLATFORM_PATH)/invm-sai.mk +include $(PLATFORM_PATH)/platform-modules-cel.mk +include $(PLATFORM_PATH)/platform-modules-delta.mk +include $(PLATFORM_PATH)/docker-syncd-invm.mk +include $(PLATFORM_PATH)/docker-syncd-invm-rpc.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/python-saithrift.mk + +SONIC_ALL += $(SONIC_INVM_ONE_IMAGE) \ + $(DOCKER_FPM) \ + $(DOCKER_PTF_INVM) \ + $(DOCKER_SYNCD_INVM_RPC) + +# Inject invm sai into syncd +$(SYNCD)_DEPENDS += $(INVM_HSAI) $(INVM_LIBSAI) $(LIBSAITHRIFT_DEV_INVM) +$(SYNCD)_UNINSTALLS += $(INVM_HSAI) + +# Runtime dependency on invm sai is set only for syncd +$(SYNCD)_RDEPENDS += $(INVM_HSAI) diff --git a/platform/innovium/sonic-platform-modules-cel/.gitignore b/platform/innovium/sonic-platform-modules-cel/.gitignore new file mode 100755 index 000000000000..f805e810e5c6 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/.gitignore @@ -0,0 +1,33 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su diff --git a/platform/innovium/sonic-platform-modules-cel/LICENSE b/platform/innovium/sonic-platform-modules-cel/LICENSE new file mode 100755 index 000000000000..2386a3920c07 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2017 Celestica, Inc + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/innovium/sonic-platform-modules-cel/README.md b/platform/innovium/sonic-platform-modules-cel/README.md new file mode 100755 index 000000000000..fbda62f91eae --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/README.md @@ -0,0 +1 @@ +# Platform drivers for Celestica Midstone-200i for the SONiC project diff --git a/platform/innovium/sonic-platform-modules-cel/debian/changelog b/platform/innovium/sonic-platform-modules-cel/debian/changelog new file mode 100755 index 000000000000..4a4e5ed2b0a0 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/debian/changelog @@ -0,0 +1,28 @@ +sonic-cel-platform-modules (0.2.2) unstable; urgency=low + + * Remove I2c mux ininitialization in init-script. + * Remapping virtual I2c ports number in sfputil. + * Fix qsfp driver, missing present status of sfp+ ports. + * Updated sfputil for decode sfp+ EEPROM. + * Add watchdog driver. + + -- Wirut Getbamrung Wed, 1 Feb 2018 16:00:00 +0700 + +sonic-cel-platform-modules (0.2.1) unstable; urgency=low + + * Fix module init-script not load CPLD virtual i2c driver properly. + + -- Pradchaya Phucharoen Mon, 9 Oct 2017 14:24:25 +0700 + +sonic-cel-platform-modules (0.2.0) unstable; urgency=low + + * Add sysfs interface to reset sfp ports. + * Fix qsfp driver, low power mode set/get incorrect bit. + + -- Pradchaya Phucharoen Tue, 26 Sep 2017 11:50:23 +0700 + +sonic-cel-platform-modules (0.1) unstable; urgency=low + + * Initial platform module. + + -- Pradchaya Phucharoen Tue, 23 Aug 2017 10:43:00 +0700 diff --git a/platform/innovium/sonic-platform-modules-cel/debian/compat b/platform/innovium/sonic-platform-modules-cel/debian/compat new file mode 100755 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/innovium/sonic-platform-modules-cel/debian/control b/platform/innovium/sonic-platform-modules-cel/debian/control new file mode 100755 index 000000000000..374f1f75d3aa --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/debian/control @@ -0,0 +1,11 @@ +Source: sonic-cel-platform-modules +Section: main +Priority: extra +Maintainer: Wirut Getbamrung +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-midstone-200i +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices diff --git a/platform/innovium/sonic-platform-modules-cel/debian/platform-modules-midstone-200i.init b/platform/innovium/sonic-platform-modules-cel/debian/platform-modules-midstone-200i.init new file mode 100755 index 000000000000..7074d2b58125 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/debian/platform-modules-midstone-200i.init @@ -0,0 +1,52 @@ +#!/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 200i board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + # Attach TLV 0x56 eeprom + echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-0/new_device + sleep 2 + + modprobe 200i-cpld + sleep 2 + + # Turn off/down lpmod by defult (0 - Normal, 1 - Low Pow) + echo 0x00 > /sys/devices/platform/ms200i_cpld/qsfp_lpmode + + # Attach 64 instances of EEPROM driver QSFP ports + for ((n=1;n<=66;n++)); + do + echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$n/new_device + sleep 0.1 + done + + echo "done." + ;; + +stop) + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-200i.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/innovium/sonic-platform-modules-cel/debian/platform-modules-midstone-200i.install b/platform/innovium/sonic-platform-modules-cel/debian/platform-modules-midstone-200i.install new file mode 100644 index 000000000000..4f298feb8300 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/debian/platform-modules-midstone-200i.install @@ -0,0 +1,2 @@ +midstone-200i/cfg/midstone-200i-modules.conf etc/modules-load.d +midstone-200i/systemd/platform-modules-midstone-200i.service lib/systemd/system \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cel/debian/platform-modules-midstone-200i.postinst b/platform/innovium/sonic-platform-modules-cel/debian/platform-modules-midstone-200i.postinst new file mode 100644 index 000000000000..213661ea1e84 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/debian/platform-modules-midstone-200i.postinst @@ -0,0 +1,3 @@ +depmod -a +systemctl enable platform-modules-midstone-200i.service +systemctl start platform-modules-midstone-200i.service \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-cel/debian/rules b/platform/innovium/sonic-platform-modules-cel/debian/rules new file mode 100755 index 000000000000..3b01ad7e6555 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/debian/rules @@ -0,0 +1,32 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= midstone-200i + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) diff --git a/platform/innovium/sonic-platform-modules-cel/midstone-200i/cfg/midstone-200i-modules.conf b/platform/innovium/sonic-platform-modules-cel/midstone-200i/cfg/midstone-200i-modules.conf new file mode 100755 index 000000000000..b2a3e351c4c9 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/midstone-200i/cfg/midstone-200i-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 +ipmi-devintf diff --git a/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/200i_cpld.c b/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/200i_cpld.c new file mode 100755 index 000000000000..3a99d2304029 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/200i_cpld.c @@ -0,0 +1,854 @@ +/* + * ms200i_cpld.c - driver for MidStone's CPLD + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "ms200i_cpld" + +#define RESET0102 0xA248 +#define RESET0310 0xA2DC +#define RESET1118 0xA2DD +#define RESET1926 0xA2DE +#define RESET2733 0xA2DF +#define RESET3441 0xA31C +#define RESET4249 0xA31D +#define RESET5057 0xA31E +#define RESET5864 0xA31F + +#define LPMOD0102 0xA249 +#define LPMOD0310 0xA2E0 +#define LPMOD1118 0xA2E1 +#define LPMOD1926 0xA2E2 +#define LPMOD2733 0xA2E3 +#define LPMOD3441 0xA320 +#define LPMOD4249 0xA321 +#define LPMOD5057 0xA322 +#define LPMOD5864 0xA323 + +#define ABS0102 0xA24A +#define ABS0310 0xA2E4 +#define ABS1118 0xA2E5 +#define ABS1926 0xA2E6 +#define ABS2733 0xA2E7 +#define ABS3441 0xA324 +#define ABS4249 0xA325 +#define ABS5057 0xA326 +#define ABS5864 0xA327 + +#define ABS6566 0xA244 + +#define INT0102 0xA24B +#define INT0310 0xA2E8 +#define INT1118 0xA2E9 +#define INT1926 0xA2EA +#define INT2733 0xA2EB +#define INT3441 0xA328 +#define INT4249 0xA329 +#define INT5057 0xA32A +#define INT5864 0xA32B + +#define LENGTH_PORT_CPLD 66 + +#define CPLD2_EX_CP_I2CFDR0_I2C 0xA230 +#define CPLD2_EX_CP_I2CCR0_I2C 0xA231 +#define CPLD2_EX_CP_I2CSR0_I2C 0xA232 +#define CPLD2_EX_CP_I2CDR0_I2C 0xA233 +#define CPLD2_EX_CP_I2CID0_I2C 0xA234 + +#define CPLD3_EX_CP_I2CFDR0_I2C 0xA2D0 +#define CPLD3_EX_CP_I2CCR0_I2C 0xA2D1 +#define CPLD3_EX_CP_I2CSR0_I2C 0xA2D2 +#define CPLD3_EX_CP_I2CDR0_I2C 0xA2D3 +#define CPLD3_EX_CP_I2CID0_I2C 0xA2D4 + +#define CPLD4_EX_CP_I2CFDR0_I2C 0xA310 +#define CPLD4_EX_CP_I2CCR0_I2C 0xA311 +#define CPLD4_EX_CP_I2CSR0_I2C 0xA312 +#define CPLD4_EX_CP_I2CDR0_I2C 0xA313 +#define CPLD4_EX_CP_I2CID0_I2C 0xA314 + +enum { + I2C_SR_BIT_RXAK = 0, + I2C_SR_BIT_MIF, + I2C_SR_BIT_SRW, + I2C_SR_BIT_BCSTM, + I2C_SR_BIT_MAL, + I2C_SR_BIT_MBB, + I2C_SR_BIT_MAAS, + I2C_SR_BIT_MCF +}; + +enum { + I2C_CR_BIT_BCST = 0, + I2C_CR_BIT_RSTA = 2, + I2C_CR_BIT_TXAK, + I2C_CR_BIT_MTX, + I2C_CR_BIT_MSTA, + I2C_CR_BIT_MIEN, + I2C_CR_BIT_MEN, +}; + +#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,inb(REG)); +#else +#define info(fmt,args...) +#define check(REG) +#endif + +#define GET_REG_BIT(REG,BIT) ((inb(REG) >> BIT) & 0x01) +#define SET_REG_BIT_H(REG,BIT) outb(inb(REG) | (0x01 << BIT),REG) +#define SET_REG_BIT_L(REG,BIT) outb(inb(REG) & ~(0x01 << BIT),REG) + +struct ms200i_i2c_data { + int portid; + unsigned REG_FDR0; + unsigned REG_CR0; + unsigned REG_SR0; + unsigned REG_DR0; + unsigned REG_ID0; +}; + +struct ms200i_cpld_data { + struct i2c_adapter *i2c_adapter[LENGTH_PORT_CPLD]; + struct mutex cpld_lock; + unsigned char sfpp_lpmode[2]; + unsigned char sfpp_reset[2]; +}; + +struct ms200i_cpld_data *cpld_data; + +int strtobp(const char* str,unsigned char *bytes){ + unsigned length = strlen(str); + if(length > 20){ + return 0; + } + int i,b=0; + memset(bytes,0,10); + for(i=0;i= '0' && c <= '9'){ + byte = c - '0'; + }else if(c >= 'a' && c <= 'f'){ + byte = c - 'a' + 0x0a; + }else if(c >= 'A' && c <= 'F'){ + byte = c - 'A' + 0x0a; + }else if(c == 'x' || c == 'X'){ + break; + }else{ + continue; + } + if(b%2==0) + bytes[b/2] = byte & 0x0F; + else + bytes[b/2] += (byte << 4) & 0xF0; + b++; + } + return (i/2) + (i%2); +} + +static ssize_t get_reset(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long reset = 0; + + mutex_lock(&cpld_data->cpld_lock); + + reset = + ((unsigned long)(inb(RESET5864) & 0x7F) << 57 )| + ((unsigned long) inb(RESET5057) << 49 )| + ((unsigned long) inb(RESET4249) << 41 )| + ((unsigned long) inb(RESET3441) << 33 )| + ((unsigned long)(inb(RESET2733) & 0x7F) << 26 )| + ((unsigned long) inb(RESET1926) << 18 )| + ((unsigned long) inb(RESET1118) << 10 )| + ((unsigned long) inb(RESET0310) << 2 )| + ((unsigned long)(inb(RESET0102) & 0x03) ); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%x%16.16lx\n", + cpld_data->sfpp_reset[1] << 1 | cpld_data->sfpp_reset[0], + reset & 0x3ffffffffffffffff); +} + +static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char reset[10]; + int num; + + mutex_lock(&cpld_data->cpld_lock); + + num = strtobp(buf,reset); + if (num <= 0) + { + mutex_unlock(&cpld_data->cpld_lock); + return 22; + } + + outb (( reset[0] & 0x03 ) ,RESET0102); + outb (((reset[0] >>2) & 0x3F) | + (((reset[1] ) & 0x03) << 6),RESET0310); + outb (((reset[1] >>2) & 0x3F) | + (((reset[2] ) & 0x03) << 6),RESET1118); + outb (((reset[2] >>2) & 0x3F) | + (((reset[3] ) & 0x03) << 6),RESET1926); + outb (((reset[3] >>2) & 0x3F) | + (((reset[4] ) & 0x01) << 6),RESET2733); + outb (((reset[4] >>1) & 0x7F) | + (((reset[5] ) & 0x01) << 7),RESET3441); + outb (((reset[5] >>1) & 0x7F) | + (((reset[6] ) & 0x01) << 7),RESET4249); + outb (((reset[6] >>1) & 0x7F) | + (((reset[7] ) & 0x01) << 7),RESET5057); + outb (((reset[7] >>1) & 0x7F) ,RESET5864); + + cpld_data->sfpp_reset[0] = reset[8] & 0x01; + cpld_data->sfpp_reset[1] = (reset[8]>>1) & 0x01; + + mutex_unlock(&cpld_data->cpld_lock); + + return count; +} + +static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long lpmod = 0; + + mutex_lock(&cpld_data->cpld_lock); + + lpmod = + ((unsigned long)(inb(LPMOD5864) & 0x7F) << 57 )| + ((unsigned long) inb(LPMOD5057) << 49 )| + ((unsigned long) inb(LPMOD4249) << 41 )| + ((unsigned long) inb(LPMOD3441) << 33 )| + ((unsigned long)(inb(LPMOD2733) & 0x7F) << 26 )| + ((unsigned long) inb(LPMOD1926) << 18 )| + ((unsigned long) inb(LPMOD1118) << 10 )| + ((unsigned long) inb(LPMOD0310) << 2 )| + ((unsigned long)(inb(LPMOD0102) & 0x03) ); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%x%16.16lx\n", + cpld_data->sfpp_lpmode[1] << 1 | cpld_data->sfpp_lpmode[0], + lpmod & 0xffffffffffffffff); +} + +static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + unsigned char lpmod[10]; + int num; + + mutex_lock(&cpld_data->cpld_lock); + + num = strtobp(buf,lpmod); + if (num <= 0) + { + mutex_unlock(&cpld_data->cpld_lock); + return 22; + } + + outb (( lpmod[0] & 0x03 ) ,LPMOD0102); + outb (((lpmod[0] >>2) & 0x3F) | + (((lpmod[1] ) & 0x03) << 6),LPMOD0310); + outb (((lpmod[1] >>2) & 0x3F) | + (((lpmod[2] ) & 0x03) << 6),LPMOD1118); + outb (((lpmod[2] >>2) & 0x3F) | + (((lpmod[3] ) & 0x03) << 6),LPMOD1926); + outb (((lpmod[3] >>2) & 0x3F) | + (((lpmod[4] ) & 0x01) << 6),LPMOD2733); + outb (((lpmod[4] >>1) & 0x7F) | + (((lpmod[5] ) & 0x01) << 7),LPMOD3441); + outb (((lpmod[5] >>1) & 0x7F) | + (((lpmod[6] ) & 0x01) << 7),LPMOD4249); + outb (((lpmod[6] >>1) & 0x7F) | + (((lpmod[7] ) & 0x01) << 7),LPMOD5057); + outb (((lpmod[7] >>1) & 0x7F) ,LPMOD5864); + + cpld_data->sfpp_lpmode[0] = lpmod[8] & 0x01; + cpld_data->sfpp_lpmode[1] = (lpmod[8]>>1) & 0x01; + + mutex_unlock(&cpld_data->cpld_lock); + + return count; +} + +static ssize_t get_modprs(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long present; + int present_sfp; + + mutex_lock(&cpld_data->cpld_lock); + present = + ((unsigned long)(inb(ABS5864) & 0x7F) << 57 )| + ((unsigned long) inb(ABS5057) << 49 )| + ((unsigned long) inb(ABS4249) << 41 )| + ((unsigned long) inb(ABS3441) << 33 )| + ((unsigned long)(inb(ABS2733) & 0x7F) << 26 )| + ((unsigned long) inb(ABS1926) << 18 )| + ((unsigned long) inb(ABS1118) << 10 )| + ((unsigned long) inb(ABS0310) << 2 )| + ((unsigned long)(inb(ABS0102) & 0x03) ); + + present_sfp = (inb(ABS6566) & 0x03); + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%d%16.16lx\n", present_sfp, present & 0xffffffffffffffff); +} + +static ssize_t get_modirq(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + unsigned long irq; + + mutex_lock(&cpld_data->cpld_lock); + + irq = + ((unsigned long)(inb(INT5864) & 0x7F) << 57 )| + ((unsigned long) inb(INT5057) << 49 )| + ((unsigned long) inb(INT4249) << 41 )| + ((unsigned long) inb(INT3441) << 33 )| + ((unsigned long)(inb(INT2733) & 0x7F) << 26 )| + ((unsigned long) inb(INT1926) << 18 )| + ((unsigned long) inb(INT1118) << 10 )| + ((unsigned long) inb(INT0310) << 2 )| + ((unsigned long)(inb(INT0102) & 0x03) ); + + mutex_unlock(&cpld_data->cpld_lock); + + return sprintf(buf,"0x%17.17lx\n", irq & 0x3ffffffffffffffff); +} + +static DEVICE_ATTR(qsfp_reset , S_IRUGO | S_IWUSR, get_reset, set_reset); +static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode); +static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL); +static DEVICE_ATTR(qsfp_modirq, S_IRUGO, get_modirq, NULL); + +static struct attribute *ms200i_lpc_attrs[] = { + &dev_attr_qsfp_reset.attr, + &dev_attr_qsfp_lpmode.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_qsfp_modirq.attr, + NULL, +}; + +static struct attribute_group ms200i_lpc_attr_grp = { + .attrs = ms200i_lpc_attrs, +}; + +static struct resource cel_ms200i_lpc_resources[] = { + { + .flags = IORESOURCE_IO, + }, +}; + +static void cel_ms200i_lpc_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device cel_ms200i_lpc_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(cel_ms200i_lpc_resources), + .resource = cel_ms200i_lpc_resources, + .dev = { + .release = cel_ms200i_lpc_dev_release, + } +}; + + +static int i2c_wait_ack(struct i2c_adapter *a,unsigned timeout,int writing){ + int error = 0; + unsigned tick=0; + int Status; + + struct ms200i_i2c_data *new_data = i2c_get_adapdata(a); + + check(new_data->REG_SR0); + check(new_data->REG_CR0); + + while(1){ + Status = inb(new_data->REG_SR0); + tick++; + if(tick > timeout){ + info("Status %2.2X",Status); + info("Error Timeout"); + error = -ETIMEDOUT; + break; + } + + + if(Status & (1 << I2C_SR_BIT_MIF)){ + break; + } + + if(writing == 0 && (Status & (1<REG_SR0); + outb(0, new_data->REG_SR0); + + if(error<0){ + info("Status %2.2X",Status); + return error; + } + + if(!(Status & (1 << I2C_SR_BIT_MCF))){ + info("Error Unfinish"); + return -EIO; + } + + if(Status & (1 <REG_CR0,1<cpld_lock); + + /* Write the command register */ + new_data = i2c_get_adapdata(a); + + unsigned int portid = new_data->portid; + +#ifdef DEBUG_KERN + printk(KERN_INFO "portid %2d|@ 0x%2.2X|f 0x%4.4X|(%d)%-5s| (%d)%-10s|CMD %2.2X |DAT %4.4X" + ,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" : "ERROR" + ,cmd,data->word); +#endif + /* 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: + break; + default: + printk(KERN_INFO "Unsupported transaction %d\n", size); + error = -EOPNOTSUPP; + goto Done; + } + + unsigned int REG_FDR0; + unsigned int REG_CR0; + unsigned int REG_SR0; + unsigned int REG_DR0; + unsigned int REG_ID0; + + REG_FDR0 = new_data->REG_FDR0; + REG_CR0 = new_data->REG_CR0; + REG_SR0 = new_data->REG_SR0; + REG_DR0 = new_data->REG_DR0; + REG_ID0 = new_data->REG_ID0; + outb(portid,REG_ID0); + + int timeout=0; + int cnt=0; + + ////[S][ADDR/R] + //Clear status register + outb( 0 , REG_SR0); + outb( 1 << I2C_CR_BIT_MIEN | 1 << I2C_CR_BIT_MTX | 1 << I2C_CR_BIT_MSTA ,REG_CR0); + SET_REG_BIT_H(REG_CR0,I2C_CR_BIT_MEN); + + if(rw == I2C_SMBUS_READ && + (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE)){ + // sent device address with Read mode + outb(addr << 1 | 0x01,REG_DR0); + }else{ + // sent device address with Write mode + outb(addr << 1 | 0x00,REG_DR0); + } + + + + info( "MS Start"); + + //// Wait {A} + error = i2c_wait_ack(a,50000,1); + if(error<0){ + info( "get error %d",error); + goto Done; + } + + //// [CMD]{A} + if(size == I2C_SMBUS_BYTE_DATA || + size == I2C_SMBUS_WORD_DATA || + size == I2C_SMBUS_BLOCK_DATA || + (size == I2C_SMBUS_BYTE && rw == I2C_SMBUS_WRITE)){ + + //sent command code to data register + outb(cmd,REG_DR0); + info( "MS Send CMD 0x%2.2X",cmd); + + // Wait {A} + error = i2c_wait_ack(a,50000,1); + if(error<0){ + info( "get error %d",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: + // in block data mode keep number of byte in block[0] + cnt = data->block[0]; + break; + default: + cnt = 0; break; + } + + // [CNT] used only bloack data write + if(size == I2C_SMBUS_BLOCK_DATA && rw == I2C_SMBUS_WRITE){ + + outb(cnt,REG_DR0); + info( "MS Send CNT 0x%2.2X",cnt); + + // Wait {A} + error = i2c_wait_ack(a,50000,1); + if(error<0){ + info( "get error %d",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 + )){ + int bid=0; + info( "MS prepare to sent [%d bytes]",cnt); + if(size == I2C_SMBUS_BLOCK_DATA ){ + bid=1; // block[0] is cnt; + cnt+=1; // offset from block[0] + } + for(;bidblock[bid],REG_DR0); + info( " Data > %2.2X",data->block[bid]); + // Wait {A} + error = i2c_wait_ack(a,50000,1); + if(error<0){ + goto Done; + } + } + + } + + //REPEATE START + if( rw == I2C_SMBUS_READ && ( + size == I2C_SMBUS_BYTE_DATA || + size == I2C_SMBUS_WORD_DATA || + size == I2C_SMBUS_BLOCK_DATA + )){ + info( "MS Repeated Start"); + + SET_REG_BIT_L(REG_CR0,I2C_CR_BIT_MEN); + outb(1 << I2C_CR_BIT_MIEN | + 1 << I2C_CR_BIT_MTX | + 1 << I2C_CR_BIT_MSTA | + 1 << I2C_CR_BIT_RSTA ,REG_CR0); + SET_REG_BIT_H(REG_CR0,I2C_CR_BIT_MEN); + + // sent Address with Read mode + outb( addr<<1 | 0x1 ,REG_DR0); + + // Wait {A} + error = i2c_wait_ack(a,50000,1); + if(error<0){ + 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 + )){ + + 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; + default: + cnt = 0; break; + } + + int bid = 0; + info( "MS Receive"); + + //set to Receive mode + outb(1 << I2C_CR_BIT_MEN | + 1 << I2C_CR_BIT_MIEN | + 1 << I2C_CR_BIT_MSTA , REG_CR0); + + for(bid=-1;bidblock[bid] = inb(REG_DR0); + + info( "DATA IN [%d] %2.2X",bid,data->block[bid]); + + if(size==I2C_SMBUS_BLOCK_DATA && bid == 0){ + cnt = data->block[0] + 1; + } + } + } + } + + +Stop: + //[P] + SET_REG_BIT_L(REG_CR0,I2C_CR_BIT_MSTA); + info( "MS STOP"); + +Done: + outb(1<cpld_lock); + + return error; +} + +static u32 ms200i_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; +} + +static const struct i2c_algorithm ms200i_i2c_algorithm = { + .smbus_xfer = ms200i_i2c_access, + .functionality = ms200i_i2c_func, +}; + +static struct i2c_adapter * cel_ms200i_i2c_init(struct platform_device *pdev, int portid) +{ + int error; + + struct i2c_adapter *new_adapter; + struct ms200i_i2c_data *new_data; + + new_adapter = kzalloc(sizeof(*new_adapter), GFP_KERNEL); + if (!new_adapter) + return NULL; + + new_adapter->dev.parent = &pdev->dev; + new_adapter->owner = THIS_MODULE; + new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + new_adapter->algo = &ms200i_i2c_algorithm; + + snprintf(new_adapter->name, sizeof(new_adapter->name), + "SMBus ms200i i2c Adapter portid@%04x", portid); + + new_data = kzalloc(sizeof(*new_data), GFP_KERNEL); + if (!new_data) + return NULL; + + new_data->portid = portid; + + // QSFP 1-2 and SFP 1-2 + if((portid >= 1 && portid <= 2) || (portid >= 65 && portid <= 66)){ + new_data->REG_FDR0 = CPLD2_EX_CP_I2CFDR0_I2C; + new_data->REG_CR0 = CPLD2_EX_CP_I2CCR0_I2C; + new_data->REG_SR0 = CPLD2_EX_CP_I2CSR0_I2C; + new_data->REG_DR0 = CPLD2_EX_CP_I2CDR0_I2C; + new_data->REG_ID0 = CPLD2_EX_CP_I2CID0_I2C; + + }else if((portid >= 3 && portid <= 33)){ + new_data->REG_FDR0 = CPLD3_EX_CP_I2CFDR0_I2C; + new_data->REG_CR0 = CPLD3_EX_CP_I2CCR0_I2C; + new_data->REG_SR0 = CPLD3_EX_CP_I2CSR0_I2C; + new_data->REG_DR0 = CPLD3_EX_CP_I2CDR0_I2C; + new_data->REG_ID0 = CPLD3_EX_CP_I2CID0_I2C; + + }else if((portid >= 34 && portid <= 64)){ + new_data->REG_FDR0 = CPLD4_EX_CP_I2CFDR0_I2C; + new_data->REG_CR0 = CPLD4_EX_CP_I2CCR0_I2C; + new_data->REG_SR0 = CPLD4_EX_CP_I2CSR0_I2C; + new_data->REG_DR0 = CPLD4_EX_CP_I2CDR0_I2C; + new_data->REG_ID0 = CPLD4_EX_CP_I2CID0_I2C; + } + outb(portid,new_data->REG_ID0); + outb(0x1F,new_data->REG_FDR0); // 0x1F 100kHz + + + i2c_set_adapdata(new_adapter,new_data); + + error = i2c_add_adapter(new_adapter); + if(error) + return NULL; + + return new_adapter; +}; + +static int cel_ms200i_lpc_drv_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret =0; + int portid_count; + + cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct ms200i_cpld_data), + GFP_KERNEL); + if (!cpld_data) + return -ENOMEM; + + mutex_init(&cpld_data->cpld_lock); + + 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, &ms200i_lpc_attr_grp); + if (ret) { + printk(KERN_ERR "Cannot create sysfs\n"); + } + + for(portid_count=1 ; portid_count<=LENGTH_PORT_CPLD ; portid_count++) + cpld_data->i2c_adapter[portid_count-1] = cel_ms200i_i2c_init(pdev, portid_count); + return 0; +} + +static int cel_ms200i_lpc_drv_remove(struct platform_device *pdev) +{ + int portid_count; + struct ms200i_i2c_data *new_data; + + sysfs_remove_group(&pdev->dev.kobj, &ms200i_lpc_attr_grp); + + for (portid_count=1 ; portid_count<=LENGTH_PORT_CPLD ; portid_count++) + i2c_del_adapter(cpld_data->i2c_adapter[portid_count-1]); + return 0; +} + +static struct platform_driver cel_ms200i_lpc_drv = { + .probe = cel_ms200i_lpc_drv_probe, + .remove = __exit_p(cel_ms200i_lpc_drv_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +int cel_ms200i_lpc_init(void) +{ + platform_device_register(&cel_ms200i_lpc_dev); + platform_driver_register(&cel_ms200i_lpc_drv); + + return 0; +} + +void cel_ms200i_lpc_exit(void) +{ + platform_driver_unregister(&cel_ms200i_lpc_drv); + platform_device_unregister(&cel_ms200i_lpc_dev); +} + +module_init(cel_ms200i_lpc_init); +module_exit(cel_ms200i_lpc_exit); + +MODULE_AUTHOR("Pariwat Leamsumran "); +MODULE_DESCRIPTION("Celestica MidStone ms200i LPC Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/200i_wdt.c b/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/200i_wdt.c new file mode 100755 index 000000000000..9b3d79cc5a67 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/200i_wdt.c @@ -0,0 +1,363 @@ +/* + * Watchdog driver for the Midstone 200i + * + * 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 +#include +#include +#include + + +#define DRIVER_NAME "ms200i_wdt" + +#define CONF_GPIOBASE 0x8000F848 +#define PCI_CONFIG_ADDRESS 0x0CF8 +#define PCI_CONFIG_DATA 0x0CFC + +// WDT_CTRL is GPIO 32 +// GPIOBUS: 2 ,bit: 0th +#define WDT_CTRL_ENB_REG 0x30 +#define WDT_CTRL_DIR_REG 0x34 +#define WDT_CTRL_LVL_REG 0x38 +#define WDT_CTRL_MASK (unsigned long)(1<<(32%32)) + +// WDT_FEED is GPIO 15 +// GPIOBUS: 1 ,bit: 15th +#define WDT_FEED_ENB_REG 0x00 +#define WDT_FEED_DIR_REG 0x04 +#define WDT_FEED_LVL_REG 0x0C +#define WDT_FEED_MASK (unsigned long)(1<<(15%32)) + +static bool nowayout = WATCHDOG_NOWAYOUT; + +// For enabling Debug message +//#define ENAB_DEBUG +//#define ENAB_DEBUG_GPIO + +struct ms200i_wdt_drvdata { + struct watchdog_device wdt; + struct mutex lock; + unsigned int gpiobase; +}; + +static struct resource ms200i_wdt_resources[] = { + { + .flags = IORESOURCE_IO, + }, +}; + +static void ms200i_wdt_dev_release( struct device * dev) +{ + return; +} + +static struct platform_device ms200i_wdt_dev = { + .name = DRIVER_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(ms200i_wdt_resources), + .resource = ms200i_wdt_resources, + .dev = { + .release = ms200i_wdt_dev_release, + } +}; + +static int ms200i_wdt_start(struct watchdog_device *wdt_dev) +{ + struct ms200i_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); + unsigned char reset_ctrl = 0x00; + unsigned long enab, gpio ,dir; + unsigned int base_addr; +#ifdef ENAB_DEBUG + printk(KERN_INFO "WDT Start"); +#endif + mutex_lock(&drvdata->lock); + + base_addr = drvdata->gpiobase; + + enab = inl(base_addr + WDT_CTRL_ENB_REG); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "ctrl enab %16X",enab); +#endif + enab |= WDT_CTRL_MASK; +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "ctrl enab %16X",enab); +#endif + outl(enab, base_addr + WDT_CTRL_ENB_REG); +#ifdef ENAB_DEBUG_GPIO + enab = inl(base_addr + WDT_CTRL_ENB_REG); + printk(KERN_INFO "ctrl enab %16X",enab); +#endif + + enab = inl(base_addr + WDT_FEED_ENB_REG); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "feed enab %16X",enab); +#endif + enab |= WDT_FEED_MASK; +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "feed enab %16X",enab); +#endif + outl(enab, base_addr + WDT_FEED_ENB_REG); +#ifdef ENAB_DEBUG_GPIO + enab = inl(base_addr + WDT_FEED_ENB_REG); + printk(KERN_INFO "feed enab %16X",enab); +#endif + + dir = inl(base_addr + WDT_CTRL_DIR_REG); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "ctrl dir %16X",dir); +#endif + dir &= ~WDT_FEED_MASK; +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "ctrl dir %16X",dir); +#endif + outl(dir, base_addr + WDT_CTRL_DIR_REG); +#ifdef ENAB_DEBUG_GPIO + dir = inl(base_addr + WDT_CTRL_DIR_REG); + printk(KERN_INFO "ctrl dir %16X",dir); +#endif + + dir = inl(base_addr + WDT_FEED_DIR_REG); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "feed dir %16X",dir); +#endif + dir &= ~WDT_FEED_MASK; +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "feed dir %16X",dir); +#endif + outl(dir, base_addr + WDT_FEED_DIR_REG); +#ifdef ENAB_DEBUG_GPIO + dir = inl(base_addr + WDT_FEED_DIR_REG); + printk(KERN_INFO "feed dir %16X",dir); +#endif + + gpio = inl(base_addr + WDT_CTRL_LVL_REG); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "ctrl gpio %16X",gpio); +#endif + gpio &= ~WDT_CTRL_MASK; +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "ctrl gpio %16X",gpio); +#endif + outl_p( gpio, base_addr + WDT_CTRL_LVL_REG); +#ifdef ENAB_DEBUG_GPIO + gpio = inl(base_addr + WDT_CTRL_LVL_REG); + printk(KERN_INFO "ctrl gpio %16X",gpio); +#endif + + mutex_unlock(&drvdata->lock); + printk(KERN_INFO "WDT Start Finish"); + return 0; +} + +static int ms200i_wdt_stop(struct watchdog_device *wdt_dev) +{ + struct ms200i_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); + unsigned long gpio; + unsigned long base_addr; +#ifdef ENAB_DEBUG + printk(KERN_INFO "WDT Stop"); +#endif + mutex_lock(&drvdata->lock); + + base_addr = drvdata->gpiobase; + + gpio = inl(base_addr + WDT_CTRL_ENB_REG); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "ctrl gpio %16X",gpio); +#endif + gpio &= ~(WDT_CTRL_MASK); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "ctrl gpio %16X",gpio); +#endif + outl_p(gpio, base_addr + WDT_CTRL_ENB_REG); +#ifdef ENAB_DEBUG_GPIO + gpio = inl(base_addr + WDT_CTRL_ENB_REG); + printk(KERN_INFO "ctrl gpio %16X",gpio); +#endif + + gpio = inl(base_addr + WDT_FEED_ENB_REG); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "feed gpio %16X",gpio); +#endif + gpio &= ~(WDT_CTRL_MASK); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "feed gpio %16X",gpio); +#endif + outl_p(gpio, base_addr + WDT_FEED_ENB_REG); +#ifdef ENAB_DEBUG_GPIO + gpio = inl(base_addr + WDT_FEED_ENB_REG); + printk(KERN_INFO "feed gpio %16X",gpio); +#endif + + mutex_unlock(&drvdata->lock); + + return 0; +} + +static int ms200i_wdt_ping(struct watchdog_device *wdt_dev) +{ + struct ms200i_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev); + unsigned long gpio; + unsigned long base_addr; + +#ifdef ENAB_DEBUG + printk(KERN_INFO "WDT PING"); +#endif + mutex_lock(&drvdata->lock); + + base_addr = drvdata->gpiobase; + + gpio = inl(base_addr + WDT_FEED_LVL_REG); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "feed gpio %16X",gpio); +#endif + gpio &= ~WDT_FEED_MASK; +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "feed gpio %16X",gpio); +#endif + outl_p( gpio, base_addr + WDT_FEED_LVL_REG); +#ifdef ENAB_DEBUG_GPIO + gpio = inl(base_addr + WDT_FEED_LVL_REG); + printk(KERN_INFO "feed gpio %16X",gpio); +#endif + mdelay(10); + + gpio = inl(base_addr + WDT_FEED_LVL_REG); +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "feed gpio %16X",gpio); +#endif + gpio |= WDT_FEED_MASK; +#ifdef ENAB_DEBUG_GPIO + printk(KERN_INFO "feed gpio %16X",gpio); +#endif + outl_p( gpio, base_addr + WDT_FEED_LVL_REG); +#ifdef ENAB_DEBUG_GPIO + gpio = inl(base_addr + WDT_FEED_LVL_REG); + printk(KERN_INFO "feed gpio %16X",gpio); +#endif + + mutex_unlock(&drvdata->lock); +#ifdef ENAB_DEBUG + printk(KERN_INFO "WDT PING FINISH"); +#endif + return 0; +} + +static const struct watchdog_info ms200i_wdt_info = { + .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .identity = "MS200i Watchdog", +}; + +static const struct watchdog_ops ms200i_wdt_ops = { + .owner = THIS_MODULE, + .start = ms200i_wdt_start, + .stop = ms200i_wdt_stop, + .ping = ms200i_wdt_ping, +}; + +static int ms200i_wdt_probe(struct platform_device *pdev) +{ + struct ms200i_wdt_drvdata *drvdata; + int ret; + unsigned int base_addr; + + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), + GFP_KERNEL); + if (!drvdata) { + ret = -ENOMEM; + goto err; + } + + outl(CONF_GPIOBASE, PCI_CONFIG_ADDRESS); + base_addr = inl(PCI_CONFIG_DATA); + // remove last bit , that is hardware inditcate. + base_addr &= ~(0x01); + + if(base_addr == 0){ + printk(KERN_INFO "can't get gpio base address"); + }else{ + printk(KERN_INFO "gpio base address : %8.8X",base_addr); + } + + mutex_init(&drvdata->lock); + + drvdata->gpiobase = base_addr; + drvdata->wdt.info = &ms200i_wdt_info; + drvdata->wdt.ops = &ms200i_wdt_ops; + + watchdog_set_nowayout(&drvdata->wdt, nowayout); + watchdog_set_drvdata(&drvdata->wdt, drvdata); + + ret = watchdog_register_device(&drvdata->wdt); + if (ret != 0) { + dev_err(&pdev->dev, "watchdog_register_device() failed: %d\n", + ret); + goto err; + } + + platform_set_drvdata(pdev, drvdata); + +err: + return ret; +} + +static int ms200i_wdt_remove(struct platform_device *pdev) +{ + struct ms200i_wdt_drvdata *drvdata = platform_get_drvdata(pdev); + + watchdog_unregister_device(&drvdata->wdt); +#ifdef ENAB_DEBUG + printk(KERN_INFO "MS200i WDT Remove"); +#endif + return 0; +} + +static struct platform_driver ms200i_wdt_drv = { + .probe = ms200i_wdt_probe, + .remove = ms200i_wdt_remove, + .driver = { + .name = DRIVER_NAME, + }, +}; + +int ms200i_wdt_init(void) +{ +#ifdef ENAB_DEBUG + printk(KERN_INFO "MS200i WDT Init"); +#endif + platform_device_register(&ms200i_wdt_dev); + platform_driver_register(&ms200i_wdt_drv); + + return 0; +} + +void ms200i_wdt_exit(void) +{ +#ifdef ENAB_DEBUG + printk(KERN_INFO "MS200i WDT Exit"); +#endif + platform_driver_unregister(&ms200i_wdt_drv); + platform_device_unregister(&ms200i_wdt_dev); +} + +module_init(ms200i_wdt_init); +module_exit(ms200i_wdt_exit); + +MODULE_AUTHOR("Sittisak Sinprem "); +MODULE_DESCRIPTION("Midstone ms200i Watchdog"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ms200i-watchdog"); diff --git a/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/Makefile b/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/Makefile new file mode 100755 index 000000000000..932a13cf8253 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/Makefile @@ -0,0 +1 @@ +obj-m := 200i_cpld.o mc24lc64t.o 200i_wdt.o diff --git a/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/mc24lc64t.c b/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/mc24lc64t.c new file mode 100755 index 000000000000..a391056d09a7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/midstone-200i/modules/mc24lc64t.c @@ -0,0 +1,142 @@ +/* + * 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 + +struct mc24lc64t_data { + struct i2c_client *fake_client; + 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 struct bin_attribute mc24lc64t_bit_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = 65536, + .read = mc24lc64t_read, +}; + +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; + + drvdata->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); + if (!drvdata->fake_client) + return -ENOMEM; + + i2c_set_clientdata(client, drvdata); + mutex_init(&drvdata->update_lock); + + err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr); + if (err) + i2c_unregister_device(drvdata->fake_client); + + return err; +} + +static int mc24lc64t_remove(struct i2c_client *client) +{ + struct mc24lc64t_data *drvdata = i2c_get_clientdata(client); + + i2c_unregister_device(drvdata->fake_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/innovium/sonic-platform-modules-cel/midstone-200i/systemd/platform-modules-midstone-200i.service b/platform/innovium/sonic-platform-modules-cel/midstone-200i/systemd/platform-modules-midstone-200i.service new file mode 100644 index 000000000000..dbb7aed39df7 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-cel/midstone-200i/systemd/platform-modules-midstone-200i.service @@ -0,0 +1,13 @@ +[Unit] +Description=Celestica Midstone 200i platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-midstone-200i start +ExecStop=-/etc/init.d/platform-modules-midstone-200i stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/platform/innovium/sonic-platform-modules-delta/LICENSE b/platform/innovium/sonic-platform-modules-delta/LICENSE new file mode 100644 index 000000000000..ea87fe9caabe --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Delta Networks, Inc. + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/innovium/sonic-platform-modules-delta/common/modules/dni_emc2305.c b/platform/innovium/sonic-platform-modules-delta/common/modules/dni_emc2305.c new file mode 100644 index 000000000000..73d9900af5b4 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/common/modules/dni_emc2305.c @@ -0,0 +1,381 @@ +/* + * + * + * Copyright (C) 2017 Delta Networks, Inc. + * + * This program is free software; you can redistribute it + * and/or modify it under the terms ofthe GNU General Public License as + * published by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * + * + * + * + * A hwmon driver for the SMSC EMC2305 fan controller + * Complete datasheet is available (6/2013) at: + * http://www.smsc.com/media/Downloads_Public/Data_Sheets/2305.pdf + */ + +#include +#include +#include +#include +#include + + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t set_fan_percentage(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_fan_percentage(struct device *dev, struct device_attribute * devattr, + char *buf); +static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, 0x2F, 0x4C, + 0x4D, I2C_CLIENT_END + }; + + +#define EMC2305_REG_DEVICE 0xFD +#define EMC2305_REG_VENDOR 0xFE + +//#define FAN_MINIMUN 0x33 /*20%*/ +#define FAN_MINIMUN 0x0 /*0%*/ +#define FAN_RPM_BASED 0xAB + +#define EMC2305_REG_FAN_DRIVE(n) (0x30 + 0x10 * n) +#define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * n) +#define EMC2305_REG_FAN_TACH(n) (0x3E + 0x10 * n) +#define EMC2305_REG_FAN_CONF(n) (0x32 + 0x10 * n) +#define EMC2305_REG_FAN_REAR_H_RPM(n) (0x3D + 0x10 * n) +#define EMC2305_REG_FAN_REAR_L_RPM(n) (0x3C + 0x10 * n) + +#define EMC2305_DEVICE 0x34 +#define EMC2305_VENDOR 0x5D +#define MAX_FAN_SPEED 23000 + +struct emc2305_data +{ + struct device *hwmon_dev; + struct attribute_group attrs; + struct mutex lock; +}; + +static int emc2305_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int emc2305_detect(struct i2c_client *client, + struct i2c_board_info *info); +static int emc2305_remove(struct i2c_client *client); + +static const struct i2c_device_id emc2305_id[] = +{ + { "emc2305", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2305_id); + +static struct i2c_driver emc2305_driver = +{ + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", + }, + .probe = emc2305_probe, + .remove = emc2305_remove, + .id_table = emc2305_id, + .detect = emc2305_detect, + .address_list = normal_i2c, +}; + +static SENSOR_DEVICE_ATTR(fan1_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 4); +static SENSOR_DEVICE_ATTR(fan1_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 0); +static SENSOR_DEVICE_ATTR(fan2_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 1); +static SENSOR_DEVICE_ATTR(fan3_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 2); +static SENSOR_DEVICE_ATTR(fan4_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 3); +static SENSOR_DEVICE_ATTR(fan5_input_percentage, S_IWUSR | S_IRUGO, show_fan_percentage, set_fan_percentage, 4); +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 4); + +static struct attribute *emc2305_attr[] = +{ + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan1_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan2_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan3_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan4_input_percentage.dev_attr.attr, + &sensor_dev_attr_fan5_input_percentage.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm5.dev_attr.attr, + NULL +}; + +static ssize_t show_fan_percentage(struct device *dev, struct device_attribute * devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2305_REG_FAN_TACH(attr->index)); + mutex_unlock(&data->lock); + /* Left shift 3 bits for showing correct RPM */ + val = val >> 3; + if ((int)(3932160 * 2 / (val > 0 ? val : 1) == 960))return sprintf(buf, "%d\n", 0); + return sprintf(buf, "%d\n", (int)(3932160 * 2 / (val > 0 ? val : 1) * 100 / MAX_FAN_SPEED)); +} + + +static ssize_t set_fan_percentage(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + unsigned long hsb, lsb; + unsigned long tech; + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 100) + { + return -EINVAL; + } + + if (val <= 5) + { + hsb = 0xff; /*high bit*/ + lsb = 0xe0; /*low bit*/ + } + else + { + val = val * 230; + tech = (3932160 * 2) / (val > 0 ? val : 1); + hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff); + lsb = (uint8_t)((tech << 3) & 0x0f8); + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_L_RPM(attr->index), lsb); + mutex_unlock(&data->lock); + return count; +} + + +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2305_REG_FAN_TACH(attr->index)); + mutex_unlock(&data->lock); + /* Left shift 3 bits for showing correct RPM */ + val = val >> 3; + return sprintf(buf, "%d\n", 3932160 * 2 / (val > 0 ? val : 1)); +} + +static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + unsigned long hsb, lsb; + unsigned long tech; + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 23000) + { + return -EINVAL; + } + + if (val <= 960) + { + hsb = 0xff; /*high bit*/ + lsb = 0xe0; /*low bit*/ + } + else + { + tech = (3932160 * 2) / (val > 0 ? val : 1); + hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff); + lsb = (uint8_t)((tech << 3) & 0x0f8); + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_L_RPM(attr->index), lsb); + mutex_unlock(&data->lock); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + mutex_lock(&data->lock); + val = i2c_smbus_read_byte_data(client, + EMC2305_REG_FAN_DRIVE(attr->index)); + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", val); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 255) + { + return -EINVAL; + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, + EMC2305_REG_FAN_DRIVE(attr->index), + val); + mutex_unlock(&data->lock); + return count; +} + +static int emc2305_detect(struct i2c_client *client, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + int vendor, device; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + { + return -ENODEV; + } + + vendor = i2c_smbus_read_byte_data(client, EMC2305_REG_VENDOR); + if (vendor != EMC2305_VENDOR) + { + return -ENODEV; + } + + device = i2c_smbus_read_byte_data(client, EMC2305_REG_DEVICE); + if (device != EMC2305_DEVICE) + { + return -ENODEV; + } + + strlcpy(info->type, "emc2305", I2C_NAME_SIZE); + + return 0; +} + +static int emc2305_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct emc2305_data *data; + int err; + int i; + + data = devm_kzalloc(&client->dev, sizeof(struct emc2305_data), + GFP_KERNEL); + if (!data) + { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s chip found\n", client->name); + + data->attrs.attrs = emc2305_attr; + err = sysfs_create_group(&client->dev.kobj, &data->attrs); + if (err) + { + return err; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) + { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + for (i = 0; i < 5; i++) + { + /* set minimum drive to 0% */ + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_MIN_DRIVE(i), FAN_MINIMUN); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_CONF(i), FAN_RPM_BASED); + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +} + +static int emc2305_remove(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return 0; +} + +module_i2c_driver(emc2305_driver); + +MODULE_AUTHOR("Neal Tai"); +MODULE_DESCRIPTION("SMSC EMC2305 fan controller driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/innovium/sonic-platform-modules-delta/debian/changelog b/platform/innovium/sonic-platform-modules-delta/debian/changelog new file mode 100644 index 000000000000..ec8327e8ae7a --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/debian/changelog @@ -0,0 +1,5 @@ +sonic-delta-platform-modules (1.1) unstable; urgency=low + + * Initial release + + -- Neal Tai Fri, 21 APR 2017 11:11:11 -0800 diff --git a/platform/innovium/sonic-platform-modules-delta/debian/compat b/platform/innovium/sonic-platform-modules-delta/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/innovium/sonic-platform-modules-delta/debian/control b/platform/innovium/sonic-platform-modules-delta/debian/control new file mode 100644 index 000000000000..bcfea2d42f1f --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/debian/control @@ -0,0 +1,13 @@ +Source: sonic-delta-platform-modules +Section: main +Priority: extra +Maintainer: Neal Tai +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-et-c032if +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + + diff --git a/platform/innovium/sonic-platform-modules-delta/debian/platform-modules-et-c032if.init b/platform/innovium/sonic-platform-modules-delta/debian/platform-modules-et-c032if.init new file mode 100755 index 000000000000..f2d24b04a0d4 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/debian/platform-modules-et-c032if.init @@ -0,0 +1,39 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup et-c032if board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + modprobe optoe + modprobe delta_et-c032if_platform + + /usr/local/bin/et-c032if_platform_init.sh + echo "done." + ;; + +stop) + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-et-c032if.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/innovium/sonic-platform-modules-delta/debian/platform-modules-et-c032if.install b/platform/innovium/sonic-platform-modules-delta/debian/platform-modules-et-c032if.install new file mode 100644 index 000000000000..45886664b870 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/debian/platform-modules-et-c032if.install @@ -0,0 +1,3 @@ +et-c032if/cfg/et-c032if-modules.conf etc/modules-load.d +et-c032if/scripts/et-c032if_platform_init.sh usr/local/bin +systemd/platform-modules-et-c032if.service lib/systemd/system diff --git a/platform/innovium/sonic-platform-modules-delta/debian/rules b/platform/innovium/sonic-platform-modules-delta/debian/rules new file mode 100755 index 000000000000..a84c235e5480 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/debian/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= et-c032if + +%: + dh $@ --with=systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -pplatform-modules-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ + debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/innovium/sonic-platform-modules-delta/et-c032if/cfg/et-c032if-modules.conf b/platform/innovium/sonic-platform-modules-delta/et-c032if/cfg/et-c032if-modules.conf new file mode 100644 index 000000000000..552b4103ed02 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/et-c032if/cfg/et-c032if-modules.conf @@ -0,0 +1,13 @@ +# /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/innovium/sonic-platform-modules-delta/et-c032if/modules/Makefile b/platform/innovium/sonic-platform-modules-delta/et-c032if/modules/Makefile new file mode 100644 index 000000000000..2e8feec0b405 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/et-c032if/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := delta_et-c032if_platform.o + diff --git a/platform/innovium/sonic-platform-modules-delta/et-c032if/modules/delta_et-c032if_platform.c b/platform/innovium/sonic-platform-modules-delta/et-c032if/modules/delta_et-c032if_platform.c new file mode 100644 index 000000000000..2e9db4278294 --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/et-c032if/modules/delta_et-c032if_platform.c @@ -0,0 +1,2100 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define CPULD_ADDR 0x31 +#define SWPLD2_ADDR 0x35 +#define SWPLD3_ADDR 0x36 +#define BUS0_BASE_NUM 10 +#define BUS0_DEV_NUM 3 +#define DEFAULT_NUM 0 +#define EEPROM_VAL 0xfc +#define SWPLD_VAL 0xfe +#define QSFP_VAL 0xff +#define BUS0_MUX_REG 0x14 +#define QSFP_PRESENCE_1 0x51 +#define QSFP_PRESENCE_2 0x52 +#define QSFP_PRESENCE_3 0x51 +#define QSFP_PRESENCE_4 0x52 +#define SFP_PRESENCE 0x71 +#define QSFP_RESPONDE_1 0x31 +#define QSFP_RESPONDE_2 0x32 +#define QSFP_RESPONDE_3 0x31 +#define QSFP_RESPONDE_4 0x32 +#define QSFP_LP_MODE_1 0x21 +#define QSFP_LP_MODE_2 0x22 +#define QSFP_LP_MODE_3 0x21 +#define QSFP_LP_MODE_4 0x22 +#define QSFP_RESET_1 0x11 +#define QSFP_RESET_2 0x12 +#define QSFP_RESET_3 0x11 +#define QSFP_RESET_4 0x12 +#define QSFP_INTERRUPT_1 0x61 +#define QSFP_INTERRUPT_2 0x62 +#define QSFP_INTERRUPT_3 0x61 +#define QSFP_INTERRUPT_4 0x62 + +#define EEPROM_SIZE 256 +#define EEPROM_MASK 29 +#define ATTR_R 1 +#define ATTR_W 2 + +#define et_c032if_i2c_device_num(NUM){ \ + .name = "delta-et-c032if-i2c-device", \ + .id = NUM, \ + .dev = { \ + .platform_data = &et_c032if_i2c_device_platform_data[NUM],\ + .release = device_release, \ + }, \ +} + +struct mutex dni_lock; + +/*Define struct to get client of i2c_new_deivce */ +struct i2c_client * i2c_client_9548_1; +struct i2c_client * i2c_client_9548_2; +struct i2c_client * i2c_client_9548_3; +struct i2c_client * i2c_client_9548_4; +struct i2c_client * i2c_client_9548_5; + +static struct kobject *kobj_cpld; +static struct kobject *kobj_swpld2; +static struct kobject *kobj_swpld3; +static struct kobject *kobj_sfp; + +enum{ + BUS0 = 0, + BUS1, + BUS2, + BUS3, + BUS4, + BUS5, + BUS6, + BUS7, + BUS8, + BUS9, + BUS10, + BUS11, + BUS12, + BUS13, + BUS14, + BUS15, + BUS16, + BUS17, + BUS18, + BUS19, +}; + +static struct cpld_attribute_data { + uint8_t bus; + uint8_t addr; + uint8_t reg; + uint8_t mask; + char note[350]; +}; + +unsigned char reverse_8bits(unsigned char c) +{ + unsigned char s = 0; + int i; + for (i = 0; i < 8; ++i) { + s <<= 1; + s |= c & 1; + c >>= 1; + } + return s; +} + +unsigned char dni_log2 (unsigned char num){ + unsigned char num_log2 = 0; + while(num > 0){ + num = num >> 1; + num_log2 += 1; + } + return num_log2 -1; +} + +/*---------------- I2C device - start ------------- */ +static void device_release(struct device *dev) +{ + return; +} + +struct i2c_device_platform_data { + int parent; + struct i2c_board_info info; + struct i2c_client *client; +}; +/* pca9548 - add 8 bus */ + +static struct pca954x_platform_mode pca954x_1_mode[] = +{ + { .adap_id = 30, + .deselect_on_exit = 1, + }, + { .adap_id = 31, + .deselect_on_exit = 1, + }, + { .adap_id = 32, + .deselect_on_exit = 1, + }, + { .adap_id = 33, + .deselect_on_exit = 1, + }, + { .adap_id = 34, + .deselect_on_exit = 1, + }, + { .adap_id = 35, + .deselect_on_exit = 1, + }, + { .adap_id = 36, + .deselect_on_exit = 1, + }, + { .adap_id = 37, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_mode pca954x_2_mode[] = +{ + { .adap_id = 38, + .deselect_on_exit = 1, + }, + { .adap_id = 39, + .deselect_on_exit = 1, + }, + { .adap_id = 40, + .deselect_on_exit = 1, + }, + { .adap_id = 41, + .deselect_on_exit = 1, + }, + { .adap_id = 42, + .deselect_on_exit = 1, + }, + { .adap_id = 43, + .deselect_on_exit = 1, + }, + { .adap_id = 44, + .deselect_on_exit = 1, + }, + { .adap_id = 45, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_mode pca954x_3_mode[] = +{ + { .adap_id = 46, + .deselect_on_exit = 1, + }, + { .adap_id = 47, + .deselect_on_exit = 1, + }, + { .adap_id = 48, + .deselect_on_exit = 1, + }, + { .adap_id = 49, + .deselect_on_exit = 1, + }, + { .adap_id = 50, + .deselect_on_exit = 1, + }, + { .adap_id = 51, + .deselect_on_exit = 1, + }, + { .adap_id = 52, + .deselect_on_exit = 1, + }, + { .adap_id = 53, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_mode pca954x_4_mode[] = +{ + { .adap_id = 54, + .deselect_on_exit = 1, + }, + { .adap_id = 55, + .deselect_on_exit = 1, + }, + { .adap_id = 56, + .deselect_on_exit = 1, + }, + { .adap_id = 57, + .deselect_on_exit = 1, + }, + { .adap_id = 58, + .deselect_on_exit = 1, + }, + { .adap_id = 59, + .deselect_on_exit = 1, + }, + { .adap_id = 60, + .deselect_on_exit = 1, + }, + { .adap_id = 61, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_mode pca954x_5_mode[] = +{ + { .adap_id = 62, + .deselect_on_exit = 1, + }, + { .adap_id = 63, + .deselect_on_exit = 1, + }, + { .adap_id = 64, + .deselect_on_exit = 1, + }, + { .adap_id = 65, + .deselect_on_exit = 1, + }, + { .adap_id = 66, + .deselect_on_exit = 1, + }, + { .adap_id = 67, + .deselect_on_exit = 1, + }, + { .adap_id = 68, + .deselect_on_exit = 1, + }, + { .adap_id = 69, + .deselect_on_exit = 1, + }, +}; + +static struct pca954x_platform_data pca954x_data[] = +{ + { + .modes = pca954x_1_mode, + .num_modes = ARRAY_SIZE(pca954x_1_mode), + }, + { + .modes = pca954x_2_mode, + .num_modes = ARRAY_SIZE(pca954x_2_mode), + }, + { + .modes = pca954x_3_mode, + .num_modes = ARRAY_SIZE(pca954x_3_mode), + }, + { + .modes = pca954x_4_mode, + .num_modes = ARRAY_SIZE(pca954x_4_mode), + }, + { + .modes = pca954x_5_mode, + .num_modes = ARRAY_SIZE(pca954x_5_mode), + }, +}; + +static struct i2c_board_info __initdata i2c_info_pca9548[] = +{ + { + I2C_BOARD_INFO("pca9548", 0x71), + .platform_data = &pca954x_data[0], + }, + { + I2C_BOARD_INFO("pca9548", 0x72), + .platform_data = &pca954x_data[1], + }, + { + I2C_BOARD_INFO("pca9548", 0x73), + .platform_data = &pca954x_data[2], + }, + { + I2C_BOARD_INFO("pca9548", 0x74), + .platform_data = &pca954x_data[3], + }, + { + I2C_BOARD_INFO("pca9548", 0x76), + .platform_data = &pca954x_data[4], + }, +}; + +static struct i2c_device_platform_data et_c032if_i2c_device_platform_data[] = { + { + /* id eeprom (0x53) */ + .parent = 10, + .info = { I2C_BOARD_INFO("24c02", 0x53) }, + .client = NULL, + }, + { + /* qsfp 1 (0x50) */ + .parent = 30, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 2 (0x50) */ + .parent = 31, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 3 (0x50) */ + .parent = 32, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 4 (0x50) */ + .parent = 33, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 5 (0x50) */ + .parent = 34, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 6 (0x50) */ + .parent = 35, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 7 (0x50) */ + .parent = 36, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 8 (0x50) */ + .parent = 37, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 9 (0x50) */ + .parent = 38, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 10 (0x50) */ + .parent = 39, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 11 (0x50) */ + .parent = 40, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 12 (0x50) */ + .parent = 41, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 13 (0x50) */ + .parent = 42, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 14 (0x50) */ + .parent = 43, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 15 (0x50) */ + .parent = 44, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 16 (0x50) */ + .parent = 45, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 17 (0x50) */ + .parent = 46, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 18 (0x50) */ + .parent = 47, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 19 (0x50) */ + .parent = 48, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 20 (0x50) */ + .parent = 49, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 21 (0x50) */ + .parent = 50, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 22 (0x50) */ + .parent = 51, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 23 (0x50) */ + .parent = 52, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 24 (0x50) */ + .parent = 53, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 25 (0x50) */ + .parent = 54, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 26 (0x50) */ + .parent = 55, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 27 (0x50) */ + .parent = 56, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 28 (0x50) */ + .parent = 57, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 29 (0x50) */ + .parent = 58, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 30 (0x50) */ + .parent = 59, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 31 (0x50) */ + .parent = 60, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* qsfp 32 (0x50) */ + .parent = 61, + .info = { .type = "optoe1", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 1 (0x50) */ + .parent = 62, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + { + /* sfp 2 (0x50) */ + .parent = 63, + .info = { .type = "optoe2", .addr = 0x50 }, + .client = NULL, + }, + +}; + + +static struct platform_device et_c032if_i2c_device[] = { + et_c032if_i2c_device_num(0), + et_c032if_i2c_device_num(1), + et_c032if_i2c_device_num(2), + et_c032if_i2c_device_num(3), + et_c032if_i2c_device_num(4), + et_c032if_i2c_device_num(5), + et_c032if_i2c_device_num(6), + et_c032if_i2c_device_num(7), + et_c032if_i2c_device_num(8), + et_c032if_i2c_device_num(9), + et_c032if_i2c_device_num(10), + et_c032if_i2c_device_num(11), + et_c032if_i2c_device_num(12), + et_c032if_i2c_device_num(13), + et_c032if_i2c_device_num(14), + et_c032if_i2c_device_num(15), + et_c032if_i2c_device_num(16), + et_c032if_i2c_device_num(17), + et_c032if_i2c_device_num(18), + et_c032if_i2c_device_num(19), + et_c032if_i2c_device_num(20), + et_c032if_i2c_device_num(21), + et_c032if_i2c_device_num(22), + et_c032if_i2c_device_num(23), + et_c032if_i2c_device_num(24), + et_c032if_i2c_device_num(25), + et_c032if_i2c_device_num(26), + et_c032if_i2c_device_num(27), + et_c032if_i2c_device_num(28), + et_c032if_i2c_device_num(29), + et_c032if_i2c_device_num(30), + et_c032if_i2c_device_num(31), + et_c032if_i2c_device_num(32), + et_c032if_i2c_device_num(33), + et_c032if_i2c_device_num(34), +}; + +/*---------------- I2C device - end ------------- */ + +/*---------------- I2C driver - start ------------- */ +static int __init i2c_device_probe(struct platform_device *pdev) +{ + struct i2c_device_platform_data *pdata; + struct i2c_adapter *parent; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -ENODEV; + } + + pdata->client = i2c_new_device(parent, &pdata->info); + if (!pdata->client) { + dev_err(&pdev->dev, "Failed to create i2c client %s at %d\n", + pdata->info.type, pdata->parent); + return -ENODEV; + } + + return 0; +} + +static int __exit i2c_deivce_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent; + struct i2c_device_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + if (pdata->client) { + parent = (pdata->client)->adapter; + i2c_unregister_device(pdata->client); + i2c_put_adapter(parent); + } + return 0; +} +static struct platform_driver i2c_device_driver = { + .probe = i2c_device_probe, + .remove = __exit_p(i2c_deivce_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-et-c032if-i2c-device", + } +}; + +/*---------------- I2C driver - end ------------- */ + +/*---------------- CPLD - start ------------- */ + +unsigned char cpupld_reg_addr; +unsigned char swpld2_reg_addr; +unsigned char swpld3_reg_addr; + +/* CPLD -- device */ + +enum cpld_type { + cpu_cpld, +}; + +enum swpld2_type { + swpld2, +}; + +enum swpld3_type { + swpld3, +}; + +enum cpld_attributes { +//CPLDs address and value + CPLD_REG_ADDR, + CPLD_REG_VALUE, + SWPLD2_REG_ADDR, + SWPLD2_REG_VALUE, + SWPLD3_REG_ADDR, + SWPLD3_REG_VALUE, + SFP_SELECT_PORT, + SFP_IS_PRESENT, + SFP_IS_PRESENT_ALL, + QSFP_LP_MODE, + QSFP_RESET, + QSFP_INTERRUPT, + QSFP_RESPONDE, +}; + +struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; +}; + +static struct cpld_platform_data et_c032if_cpld_platform_data[] = { + [cpu_cpld] = { + .reg_addr = CPULD_ADDR, + }, +}; + +static struct cpld_platform_data et_c032if_swpld2_platform_data[] = { + [swpld2] = { + .reg_addr = SWPLD2_ADDR, + }, +}; + +static struct cpld_platform_data et_c032if_swpld3_platform_data[] = { + [swpld3] = { + .reg_addr = SWPLD3_ADDR, + }, +}; + +static struct platform_device et_c032if_cpld = { + .name = "delta-et-c032if-cpld", + .id = 0, + .dev = { + .platform_data = et_c032if_cpld_platform_data, + .release = device_release, + }, +}; + +static struct platform_device et_c032if_swpld2 = { + .name = "delta-et-c032if-swpld2", + .id = 0, + .dev = { + .platform_data = et_c032if_swpld2_platform_data, + .release = device_release + }, +}; + +static struct platform_device et_c032if_swpld3 = { + .name = "delta-et-c032if-swpld3", + .id = 0, + .dev = { + .platform_data = et_c032if_swpld3_platform_data, + .release = device_release + }, +}; + +static ssize_t get_cpld_reg(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + int ret; + int mask; + int value; + char note[450]; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cpld_platform_data *pdata = dev->platform_data; + + mutex_lock(&dni_lock); + switch (attr->index) { + case CPLD_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", cpupld_reg_addr); + case SWPLD2_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld2_reg_addr); + case SWPLD3_REG_ADDR: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", swpld3_reg_addr); + case CPLD_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[cpu_cpld].client, cpupld_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case SWPLD2_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld2].client, swpld2_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + case SWPLD3_REG_VALUE: + ret = i2c_smbus_read_byte_data(pdata[swpld3].client, swpld3_reg_addr); + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x\n", ret); + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0xff: + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x%s", value, note); + case 0x0f: + case 0x07: + case 0x03: + break; + case 0x0c: + value = value >> 2; + break; + case 0xf0: + case 0x70: + case 0x30: + value = value >> 4; + break; + case 0xe0: + value = value >> 5; + break; + case 0xc0: + value = value >> 6; + break; + default : + value = value >> dni_log2(mask); + mutex_unlock(&dni_lock); + return sprintf(buf, "%d%s", value, note); + } + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%02x%s", value, note); +} + +static ssize_t set_cpld_reg(struct device *dev, struct device_attribute *dev_attr, + const char *buf, size_t count) +{ + int err; + int set_data; + unsigned long set_data_ul; + unsigned char mask; + unsigned char mask_out; + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 0, &set_data_ul); + if (err){ + return err; + } + + mutex_lock(&dni_lock); + set_data = (int)set_data_ul; + if (set_data > 0xff){ + printk(KERN_ALERT "address out of range (0x00-0xFF)\n"); + mutex_unlock(&dni_lock); + return count; + } + + switch (attr->index) { + case CPLD_REG_ADDR: + cpupld_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD2_REG_ADDR: + swpld2_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case SWPLD3_REG_ADDR: + swpld3_reg_addr = set_data; + mutex_unlock(&dni_lock); + return count; + case CPLD_REG_VALUE: + i2c_smbus_write_byte_data(pdata[cpu_cpld].client, cpupld_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD2_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld2].client, swpld2_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + case SWPLD3_REG_VALUE: + i2c_smbus_write_byte_data(pdata[swpld3].client, swpld3_reg_addr, set_data); + mutex_unlock(&dni_lock); + return count; + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } + + switch (mask) { + case 0x03: + case 0x07: + case 0x0f: + case 0xff: + set_data = mask_out | (set_data & mask); + break; + case 0x0c: + set_data = set_data << 2; + set_data = mask_out | (set_data & mask); + break; + case 0xf0: + case 0x70: + case 0x30: + set_data = set_data << 4; + set_data = mask_out | (set_data & mask); + break; + case 0xe0: + set_data = set_data << 5; + set_data = mask_out | (set_data & mask); + break; + case 0xc0: + set_data = set_data << 6; + set_data = mask_out | (set_data & mask); + break; + default : + set_data = mask_out | (set_data << dni_log2(mask) ); + } + switch (attr->index) { + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "cpld not found"); + } + mutex_unlock(&dni_lock); + return count; +} + +/* ---------------- SFP attribute read/write - start -------- */ + +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf){ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct device *i2cdev_1 = kobj_to_dev(kobj_swpld2); + struct device *i2cdev_2 = kobj_to_dev(kobj_swpld3); + struct cpld_platform_data *pdata1 = i2cdev_1->platform_data; + struct cpld_platform_data *pdata2 = i2cdev_2->platform_data; + + mutex_lock(&dni_lock); + int ret; + u32 data = 0; + int data2 = 0; + u8 save_bytes = 0x00; + + switch (attr->index) { + case SFP_IS_PRESENT: + /* Report the SFP/QSFP ALL PRESENCE status + * This data information form SWPLD2 and SWPLD3. */ + + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, QSFP_PRESENCE_4); + data = (u32)(ret & 0xff); + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, QSFP_PRESENCE_3); + data |= (u32)(ret & 0xff) << 8; + ret = i2c_smbus_read_byte_data(pdata1[swpld2].client, QSFP_PRESENCE_2); + data |= (u32)(ret & 0xff) << 16; + ret = i2c_smbus_read_byte_data(pdata1[swpld2].client, QSFP_PRESENCE_1); + data |= (u32)(ret & 0xff) << 24; + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, SFP_PRESENCE); + data2 = (ret & 0x44); + save_bytes = data2 & 0x40; + save_bytes = save_bytes << 1; + data2 &= 0x04; + data2 = data2 << 4; + data2 |= save_bytes; + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%x%02x\n", data, data2); + + case QSFP_LP_MODE: + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, QSFP_LP_MODE_4); + data = (u32)(ret & 0xff); + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, QSFP_LP_MODE_3); + data |= (u32)(ret & 0xff) << 8; + ret = i2c_smbus_read_byte_data(pdata1[swpld2].client, QSFP_LP_MODE_2); + data |= (u32)(ret & 0xff) << 16; + ret = i2c_smbus_read_byte_data(pdata1[swpld2].client, QSFP_LP_MODE_1); + data |= (u32)(ret & 0xff) << 24; + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%x\n", data); + + case QSFP_RESET: + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, QSFP_RESET_4); + data = (u32)(ret & 0xff); + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, QSFP_RESET_3); + data |= (u32)(ret & 0xff) << 8; + ret = i2c_smbus_read_byte_data(pdata1[swpld2].client, QSFP_RESET_2); + data |= (u32)(ret & 0xff) << 16; + ret = i2c_smbus_read_byte_data(pdata1[swpld2].client, QSFP_RESET_1); + data |= (u32)(ret & 0xff) << 24; + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%x\n", data); + + case QSFP_INTERRUPT: + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, QSFP_INTERRUPT_4); + data = (u32)(ret & 0xff); + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, QSFP_INTERRUPT_3); + data |= (u32)(ret & 0xff) << 8; + ret = i2c_smbus_read_byte_data(pdata1[swpld2].client, QSFP_INTERRUPT_2); + data |= (u32)(ret & 0xff) << 16; + ret = i2c_smbus_read_byte_data(pdata1[swpld2].client, QSFP_INTERRUPT_1); + data |= (u32)(ret & 0xff) << 24; + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%x\n", data); + + case QSFP_RESPONDE: + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, QSFP_RESPONDE_4); + data = (u32)(ret & 0xff); + ret = i2c_smbus_read_byte_data(pdata2[swpld3].client, QSFP_RESPONDE_3); + data |= (u32)(ret & 0xff) << 8; + ret = i2c_smbus_read_byte_data(pdata1[swpld2].client, QSFP_RESPONDE_2); + data |= (u32)(ret & 0xff) << 16; + ret = i2c_smbus_read_byte_data(pdata1[swpld2].client, QSFP_RESPONDE_1); + data |= (u32)(ret & 0xff) << 24; + mutex_unlock(&dni_lock); + return sprintf(buf, "0x%x\n", data); + + default: + mutex_unlock(&dni_lock); + return sprintf(buf, "%d not found", attr->index); + } +} + + +static ssize_t set_lpmode_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev_1 = kobj_to_dev(kobj_swpld2); + struct device *i2cdev_2 = kobj_to_dev(kobj_swpld3); + struct cpld_platform_data *pdata1 = i2cdev_1->platform_data; + struct cpld_platform_data *pdata2 = i2cdev_2->platform_data; + unsigned long long set_data; + int err; + int values = 0x00; + u8 reg_t = 0x00; + + err = kstrtoull(buf, 16, &set_data); + if (err){ + return err; + } + mutex_lock(&dni_lock); + reg_t = QSFP_LP_MODE_1; + values = ((set_data >> 24 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata1[swpld2].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + + reg_t = QSFP_LP_MODE_2; + values = ((set_data >> 16 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata1[swpld2].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + + reg_t = QSFP_LP_MODE_3; + values = ((set_data >> 8 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata2[swpld3].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + + reg_t = QSFP_LP_MODE_4; + values = (set_data & 0xff); + if (i2c_smbus_write_byte_data(pdata2[swpld3].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + + mutex_unlock(&dni_lock); + return count; + +ERROR: + mutex_unlock(&dni_lock); + return -EIO; +} + +static ssize_t set_reset_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev_1 = kobj_to_dev(kobj_swpld2); + struct device *i2cdev_2 = kobj_to_dev(kobj_swpld3); + struct cpld_platform_data *pdata1 = i2cdev_1->platform_data; + struct cpld_platform_data *pdata2 = i2cdev_2->platform_data; + unsigned long long set_data; + int err; + int values = 0x00; + u8 reg_t = 0x00; + + err = kstrtoull(buf, 16, &set_data); + if (err){ + return err; + } + + mutex_lock(&dni_lock); + reg_t = QSFP_RESET_1; + values = ((set_data >> 24 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata1[swpld2].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + reg_t = QSFP_RESET_2; + values = ((set_data >> 16 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata1[swpld2].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + reg_t = QSFP_RESET_3; + values = ((set_data >> 8 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata2[swpld3].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + reg_t = QSFP_RESET_4; + values = (set_data & 0xff); + if (i2c_smbus_write_byte_data(pdata2[swpld3].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + + mutex_unlock(&dni_lock); + return count; + +ERROR: + mutex_unlock(&dni_lock); + return -EIO; +} + +static ssize_t set_interrupt_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev_1 = kobj_to_dev(kobj_swpld2); + struct device *i2cdev_2 = kobj_to_dev(kobj_swpld3); + struct cpld_platform_data *pdata1 = i2cdev_1->platform_data; + struct cpld_platform_data *pdata2 = i2cdev_2->platform_data; + unsigned long long set_data; + int err; + int values = 0x00; + u8 reg_t = 0x00; + + err = kstrtoull(buf, 16, &set_data); + if (err){ + return err; + } + + mutex_lock(&dni_lock); + reg_t = QSFP_INTERRUPT_1; + values = ((set_data >> 24 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata1[swpld2].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + reg_t = QSFP_INTERRUPT_2; + values = ((set_data >> 16 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata1[swpld2].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + reg_t = QSFP_INTERRUPT_3; + values = ((set_data >> 8 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata2[swpld3].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + reg_t = QSFP_INTERRUPT_4; + values = (set_data & 0xff); + + if (i2c_smbus_write_byte_data(pdata2[swpld3].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + + mutex_unlock(&dni_lock); + return count; + +ERROR: + mutex_unlock(&dni_lock); + return -EIO; +} + +static ssize_t set_responde_data(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count) +{ + struct device *i2cdev_1 = kobj_to_dev(kobj_swpld2); + struct device *i2cdev_2 = kobj_to_dev(kobj_swpld3); + struct cpld_platform_data *pdata1 = i2cdev_1->platform_data; + struct cpld_platform_data *pdata2 = i2cdev_2->platform_data; + unsigned long long set_data; + int err; + int values = 0x00; + u8 reg_t = 0x00; + + err = kstrtoull(buf, 16, &set_data); + if (err){ + return err; + } + + mutex_lock(&dni_lock); + reg_t = QSFP_RESPONDE_1; + values = ((set_data >> 24 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata1[swpld2].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + reg_t = QSFP_RESPONDE_2; + values = ((set_data >> 16 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata1[swpld2].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + reg_t = QSFP_RESPONDE_3; + values = ((set_data >> 8 ) & 0xff); + if (i2c_smbus_write_byte_data(pdata2[swpld3].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + reg_t = QSFP_RESPONDE_4; + values = (set_data & 0xff); + if (i2c_smbus_write_byte_data(pdata2[swpld3].client, reg_t, (u8)values) < 0) + { + goto ERROR; + } + + mutex_unlock(&dni_lock); + return count; + +ERROR: + mutex_unlock(&dni_lock); + return -EIO; +} + +static SENSOR_DEVICE_ATTR(cpld_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_REG_ADDR); +static SENSOR_DEVICE_ATTR(cpld_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld2_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD2_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld2_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD2_REG_VALUE); +static SENSOR_DEVICE_ATTR(swpld3_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD3_REG_ADDR); +static SENSOR_DEVICE_ATTR(swpld3_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, SWPLD3_REG_VALUE); +//SFP, QSFP +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, for_status, NULL, SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_lp_mode, S_IWUSR | S_IRUGO, for_status, set_lpmode_data, QSFP_LP_MODE); +static SENSOR_DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, for_status, set_reset_data, QSFP_RESET); +static SENSOR_DEVICE_ATTR(sfp_interrupt, S_IWUSR | S_IRUGO, for_status, set_interrupt_data, QSFP_INTERRUPT); +static SENSOR_DEVICE_ATTR(sfp_responde, S_IWUSR | S_IRUGO, for_status, set_responde_data, QSFP_RESPONDE); + +static struct attribute *cpld_attrs[] = { + &sensor_dev_attr_cpld_reg_value.dev_attr.attr, + &sensor_dev_attr_cpld_reg_addr.dev_attr.attr, +//SFP, QSFP + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_lp_mode.dev_attr.attr, + &sensor_dev_attr_sfp_reset.dev_attr.attr, + &sensor_dev_attr_sfp_interrupt.dev_attr.attr, + &sensor_dev_attr_sfp_responde.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld2_attrs[] = { + &sensor_dev_attr_swpld2_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld2_reg_addr.dev_attr.attr, + NULL, +}; + +static struct attribute *swpld3_attrs[] = { + &sensor_dev_attr_swpld3_reg_value.dev_attr.attr, + &sensor_dev_attr_swpld3_reg_addr.dev_attr.attr, + NULL, +}; + +static struct attribute_group cpld_attr_grp = { + .attrs = cpld_attrs, +}; + +static struct attribute_group swpld2_attr_grp = { + .attrs = swpld2_attrs, +}; + +static struct attribute_group swpld3_attr_grp = { + .attrs = swpld3_attrs, +}; + +/* CPLD -- driver */ +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLD platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(BUS0); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", BUS0); + return -ENODEV; + } + + pdata[cpu_cpld].client = i2c_new_dummy(parent, pdata[cpu_cpld].reg_addr); + if (!pdata[cpu_cpld].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[cpu_cpld].reg_addr); + goto error; + } + + kobj_cpld = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &cpld_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create cpld attribute group"); + goto error; + } + + return 0; +error: + kobject_put(kobj_cpld); + i2c_unregister_device(pdata[cpu_cpld].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[cpu_cpld].client) { + if (!parent) { + parent = (pdata[cpu_cpld].client)->adapter; + } + i2c_unregister_device(pdata[cpu_cpld].client); + } + } + i2c_put_adapter(parent); + + return 0; +} + +static int __init swpld2_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD2 platform data not found\n"); + return -ENODEV; + } + parent = i2c_get_adapter(11); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", 11); + return -ENODEV; + } + + pdata[swpld2].client = i2c_new_dummy(parent, pdata[swpld2].reg_addr); + if (!pdata[swpld2].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld2].reg_addr); + goto error; + } + + kobj_swpld2 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld2_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + return 0; + +error: + kobject_put(kobj_swpld2); + i2c_unregister_device(pdata[swpld2].client); + i2c_put_adapter(parent); + return -ENODEV; +} + +static int __exit swpld2_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &swpld2_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld2].client) { + if (!parent) { + parent = (pdata[swpld2].client)->adapter; + } + i2c_unregister_device(pdata[swpld2].client); + } + } + i2c_put_adapter(parent); + return 0; +} + + +static int __init swpld3_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD3 platform data not found\n"); + return -ENODEV; + } + + parent = i2c_get_adapter(11); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", 11); + return -ENODEV; + } + + pdata[swpld3].client = i2c_new_dummy(parent, pdata[swpld3].reg_addr); + if (!pdata[swpld3].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[swpld3].reg_addr); + goto error; + } + + kobj_swpld3 = &pdev->dev.kobj; + ret = sysfs_create_group(&pdev->dev.kobj, &swpld3_attr_grp); + if (ret) { + printk(KERN_WARNING "Fail to create swpld attribute group"); + goto error; + } + + return 0; + +error: + kobject_put(kobj_swpld3); + i2c_unregister_device(pdata[swpld3].client); + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit swpld3_remove(struct platform_device *pdev) +{ + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + sysfs_remove_group(&pdev->dev.kobj, &swpld3_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } + else { + if (pdata[swpld3].client) { + if (!parent) { + parent = (pdata[swpld3].client)->adapter; + } + i2c_unregister_device(pdata[swpld3].client); + } + } + i2c_put_adapter(parent); + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-et-c032if-cpld", + }, +}; + +static struct platform_driver swpld2_driver = { + .probe = swpld2_probe, + .remove = __exit_p(swpld2_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-et-c032if-swpld2", + }, +}; + +static struct platform_driver swpld3_driver = { + .probe = swpld3_probe, + .remove = __exit_p(swpld3_remove), + .driver = { + .owner = THIS_MODULE, + .name = "delta-et-c032if-swpld3", + }, +}; + + +/*---------------- CPLD - end ------------- */ + +/*---------------- delta ATTR - start ------------- */ + +struct delta_bin_attribute { + struct bin_attribute attr; + int index; +}; + +#define to_delta_attr(x) container_of(x, struct delta_bin_attribute, attr) + +#define BIN_ATTR(_name, _mode, _read, _write, _size, _index) { \ + .attr = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .read = _read, \ + .write = _write, \ + .size = _size, \ + }, \ + .index = _index, \ +} + +#define DELTA_BIN_ATTR(_name, _mode, _read, _write, _size, _index) \ +struct delta_bin_attribute delta_attr_##_name \ + = BIN_ATTR(_name, _mode, _read, _write, _size, _index) + +static char eeprom_data[EEPROM_SIZE]; + +static ssize_t access_user_space(const char *name, char *buf, size_t len, loff_t offset, int mode) +{ + struct file *fp; + mm_segment_t fs; + loff_t pos = offset; + ssize_t vfs_ret = 0; + + fs = get_fs(); + set_fs(get_ds()); + + switch(mode) + { + case ATTR_W: + fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO); + if (IS_ERR(fp)){ + return -ENOENT; + } + vfs_ret = vfs_write(fp, buf, len, &pos); + break; + case ATTR_R: + fp = filp_open(name, O_RDONLY, S_IRUGO); + if (IS_ERR(fp)){ + return -ENOENT; + } + vfs_ret = vfs_read(fp, buf, len, &pos); + break; + } + + set_fs(fs); + filp_close(fp, NULL); + return vfs_ret; +} + +enum sfp_attributes{ + EEPROM_SYS, + EEPROM_SFP_1, + EEPROM_SFP_2, + EEPROM_SFP_3, + EEPROM_SFP_4, + EEPROM_SFP_5, + EEPROM_SFP_6, + EEPROM_SFP_7, + EEPROM_SFP_8, + EEPROM_SFP_9, + EEPROM_SFP_10, + EEPROM_SFP_11, + EEPROM_SFP_12, + EEPROM_SFP_13, + EEPROM_SFP_14, + EEPROM_SFP_15, + EEPROM_SFP_16, + EEPROM_SFP_17, + EEPROM_SFP_18, + EEPROM_SFP_19, + EEPROM_SFP_20, + EEPROM_SFP_21, + EEPROM_SFP_22, + EEPROM_SFP_23, + EEPROM_SFP_24, + EEPROM_SFP_25, + EEPROM_SFP_26, + EEPROM_SFP_27, + EEPROM_SFP_28, + EEPROM_SFP_29, + EEPROM_SFP_30, + EEPROM_SFP_31, + EEPROM_SFP_32, + EEPROM_SFP_33, + EEPROM_SFP_34, +}; + + +static ssize_t delta_bin_attr_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct delta_bin_attribute *delta_attr = to_delta_attr(attr); + char attr_path[100]; + + mutex_lock(&dni_lock); + memset(buf, 0, count); + switch(delta_attr->index) { + case EEPROM_SFP_1: + case EEPROM_SFP_2: + case EEPROM_SFP_3: + case EEPROM_SFP_4: + case EEPROM_SFP_5: + case EEPROM_SFP_6: + case EEPROM_SFP_7: + case EEPROM_SFP_8: + case EEPROM_SFP_9: + case EEPROM_SFP_10: + case EEPROM_SFP_11: + case EEPROM_SFP_12: + case EEPROM_SFP_13: + case EEPROM_SFP_14: + case EEPROM_SFP_15: + case EEPROM_SFP_16: + case EEPROM_SFP_17: + case EEPROM_SFP_18: + case EEPROM_SFP_19: + case EEPROM_SFP_20: + case EEPROM_SFP_21: + case EEPROM_SFP_22: + case EEPROM_SFP_23: + case EEPROM_SFP_24: + case EEPROM_SFP_25: + case EEPROM_SFP_26: + case EEPROM_SFP_27: + case EEPROM_SFP_28: + case EEPROM_SFP_29: + case EEPROM_SFP_30: + case EEPROM_SFP_31: + case EEPROM_SFP_32: + case EEPROM_SFP_33: + case EEPROM_SFP_34: + sprintf(attr_path, "/sys/bus/i2c/devices/%d-0050/eeprom", delta_attr->index + EEPROM_MASK); + if (access_user_space(attr_path, eeprom_data, EEPROM_SIZE, 0, ATTR_R) < 0) { + goto ACCESS_ERROR; + } + count = (count <= EEPROM_SIZE) ? count : EEPROM_SIZE; + memcpy(buf, eeprom_data + off, count); + break; + case EEPROM_SYS: + sprintf(attr_path, "/sys/bus/i2c/devices/10-0053/eeprom"); + if (access_user_space(attr_path, eeprom_data, EEPROM_SIZE, 0, ATTR_R) < 0) { + goto ACCESS_ERROR; + } + count = (count <= EEPROM_SIZE) ? count : EEPROM_SIZE; + memcpy(buf, eeprom_data + off, count); + break; + default: + goto ACCESS_ERROR; + } + mutex_unlock(&dni_lock); + return count; + +ACCESS_ERROR: + mutex_unlock(&dni_lock); + return -ENXIO; +} + +static ssize_t delta_bin_attr_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct delta_bin_attribute *delta_attr = to_delta_attr(attr); + char attr_path[100]; + + switch(delta_attr->index){ + case EEPROM_SFP_1: + case EEPROM_SFP_2: + case EEPROM_SFP_3: + case EEPROM_SFP_4: + case EEPROM_SFP_5: + case EEPROM_SFP_6: + case EEPROM_SFP_7: + case EEPROM_SFP_8: + case EEPROM_SFP_9: + case EEPROM_SFP_10: + case EEPROM_SFP_11: + case EEPROM_SFP_12: + case EEPROM_SFP_13: + case EEPROM_SFP_14: + case EEPROM_SFP_15: + case EEPROM_SFP_16: + case EEPROM_SFP_17: + case EEPROM_SFP_18: + case EEPROM_SFP_19: + case EEPROM_SFP_20: + case EEPROM_SFP_21: + case EEPROM_SFP_22: + case EEPROM_SFP_23: + case EEPROM_SFP_24: + case EEPROM_SFP_25: + case EEPROM_SFP_26: + case EEPROM_SFP_27: + case EEPROM_SFP_28: + case EEPROM_SFP_29: + case EEPROM_SFP_30: + case EEPROM_SFP_31: + case EEPROM_SFP_32: + case EEPROM_SFP_33: + case EEPROM_SFP_34: + sprintf(attr_path, "/sys/bus/i2c/devices/%d-0050/eeprom", delta_attr->index + EEPROM_MASK); + if (access_user_space(attr_path, buf, count, 0, ATTR_W) < 0) { + goto ACCESS_ERROR; + } + break; + case EEPROM_SYS: + sprintf(attr_path, "/sys/bus/i2c/devices/10-0053/eeprom"); + if (access_user_space(attr_path, buf, count, 0, ATTR_W) < 0) { + goto ACCESS_ERROR; + } + break; + default: + goto ACCESS_ERROR; + } + + mutex_unlock(&dni_lock); + return count; +ACCESS_ERROR: + mutex_unlock(&dni_lock); + return -ETIMEDOUT; +} + +DELTA_BIN_ATTR(eeprom_sys, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SYS); +DELTA_BIN_ATTR(eeprom_sfp_1, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_1); +DELTA_BIN_ATTR(eeprom_sfp_2, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_2); +DELTA_BIN_ATTR(eeprom_sfp_3, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_3); +DELTA_BIN_ATTR(eeprom_sfp_4, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_4); +DELTA_BIN_ATTR(eeprom_sfp_5, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_5); +DELTA_BIN_ATTR(eeprom_sfp_6, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_6); +DELTA_BIN_ATTR(eeprom_sfp_7, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_7); +DELTA_BIN_ATTR(eeprom_sfp_8, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_8); +DELTA_BIN_ATTR(eeprom_sfp_9, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_9); +DELTA_BIN_ATTR(eeprom_sfp_10, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_10); +DELTA_BIN_ATTR(eeprom_sfp_11, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_11); +DELTA_BIN_ATTR(eeprom_sfp_12, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_12); +DELTA_BIN_ATTR(eeprom_sfp_13, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_13); +DELTA_BIN_ATTR(eeprom_sfp_14, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_14); +DELTA_BIN_ATTR(eeprom_sfp_15, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_15); +DELTA_BIN_ATTR(eeprom_sfp_16, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_16); +DELTA_BIN_ATTR(eeprom_sfp_17, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_17); +DELTA_BIN_ATTR(eeprom_sfp_18, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_18); +DELTA_BIN_ATTR(eeprom_sfp_19, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_19); +DELTA_BIN_ATTR(eeprom_sfp_20, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_20); +DELTA_BIN_ATTR(eeprom_sfp_21, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_21); +DELTA_BIN_ATTR(eeprom_sfp_22, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_22); +DELTA_BIN_ATTR(eeprom_sfp_23, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_23); +DELTA_BIN_ATTR(eeprom_sfp_24, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_24); +DELTA_BIN_ATTR(eeprom_sfp_25, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_25); +DELTA_BIN_ATTR(eeprom_sfp_26, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_26); +DELTA_BIN_ATTR(eeprom_sfp_27, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_27); +DELTA_BIN_ATTR(eeprom_sfp_28, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_28); +DELTA_BIN_ATTR(eeprom_sfp_29, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_29); +DELTA_BIN_ATTR(eeprom_sfp_30, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_30); +DELTA_BIN_ATTR(eeprom_sfp_31, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_31); +DELTA_BIN_ATTR(eeprom_sfp_32, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_32); +DELTA_BIN_ATTR(eeprom_sfp_33, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_33); +DELTA_BIN_ATTR(eeprom_sfp_34, 0664, delta_bin_attr_read, delta_bin_attr_write, EEPROM_SIZE, EEPROM_SFP_34); + +static struct bin_attribute *sfp_attrs[] = { + &delta_attr_eeprom_sys.attr, + &delta_attr_eeprom_sfp_1.attr, + &delta_attr_eeprom_sfp_2.attr, + &delta_attr_eeprom_sfp_3.attr, + &delta_attr_eeprom_sfp_4.attr, + &delta_attr_eeprom_sfp_5.attr, + &delta_attr_eeprom_sfp_6.attr, + &delta_attr_eeprom_sfp_7.attr, + &delta_attr_eeprom_sfp_8.attr, + &delta_attr_eeprom_sfp_9.attr, + &delta_attr_eeprom_sfp_10.attr, + &delta_attr_eeprom_sfp_11.attr, + &delta_attr_eeprom_sfp_12.attr, + &delta_attr_eeprom_sfp_13.attr, + &delta_attr_eeprom_sfp_14.attr, + &delta_attr_eeprom_sfp_15.attr, + &delta_attr_eeprom_sfp_16.attr, + &delta_attr_eeprom_sfp_17.attr, + &delta_attr_eeprom_sfp_18.attr, + &delta_attr_eeprom_sfp_19.attr, + &delta_attr_eeprom_sfp_20.attr, + &delta_attr_eeprom_sfp_21.attr, + &delta_attr_eeprom_sfp_22.attr, + &delta_attr_eeprom_sfp_23.attr, + &delta_attr_eeprom_sfp_24.attr, + &delta_attr_eeprom_sfp_25.attr, + &delta_attr_eeprom_sfp_26.attr, + &delta_attr_eeprom_sfp_27.attr, + &delta_attr_eeprom_sfp_28.attr, + &delta_attr_eeprom_sfp_29.attr, + &delta_attr_eeprom_sfp_30.attr, + &delta_attr_eeprom_sfp_31.attr, + &delta_attr_eeprom_sfp_32.attr, + &delta_attr_eeprom_sfp_33.attr, + &delta_attr_eeprom_sfp_34.attr, + NULL, /* need to NULL terminate the list of attributes */ +}; + +static struct attribute_group sfp_attr_grp = { + .bin_attrs = sfp_attrs, +}; + +/*---------------- delta ATTR - end ------------- */ + +/*---------------- MUX - start ------------- */ + +struct cpld_mux_platform_data { + int parent; + int base_nr; + int reg_addr; + struct i2c_client *cpld; +}; + +struct cpld_mux { + struct i2c_adapter *parent; + struct i2c_adapter **child; + struct cpld_mux_platform_data data; +}; + +static struct cpld_mux_platform_data et_c032if_cpld_mux_platform_data[] = { + { + .parent = BUS0, + .base_nr = BUS0_BASE_NUM, + .cpld = NULL, + .reg_addr = BUS0_MUX_REG, + }, +}; + +static struct platform_device et_c032if_cpld_mux[] = +{ + { + .name = "delta-et-c032if-cpld-mux", + .id = 0, + .dev = { + .platform_data = &et_c032if_cpld_mux_platform_data[0], + .release = device_release, + }, + }, +}; + +static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); +} + +static int cpld_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct cpld_mux *mux = i2c_mux_priv(muxc); + u8 cpld_mux_val=0; + + if ( mux->data.base_nr == BUS0_BASE_NUM ) + { + switch (chan) { + case 0: + cpld_mux_val = EEPROM_VAL; + break; + case 1: + cpld_mux_val = SWPLD_VAL; + break; + case 2: + cpld_mux_val = QSFP_VAL; + break; + default: + cpld_mux_val = 0x00; + break; + } + } + else + { + cpld_mux_val = 0x00; + } + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, (u8)(cpld_mux_val & 0xff)); + +} + +static int __init cpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + struct cpld_mux *mux; + struct cpld_mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret, dev_num; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "SWPLD platform data not found\n"); + return -ENODEV; + } + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) { + printk(KERN_ERR "Failed to allocate memory for mux\n"); + return -ENOMEM; + } + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + kfree(mux); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent); + return -ENODEV; + } + /* Judge bus number to decide how many devices*/ + switch (pdata->parent) { + case BUS0: + dev_num = BUS0_DEV_NUM; + break; + default : + dev_num = DEFAULT_NUM; + break; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, dev_num, 0, 0,cpld_mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + platform_set_drvdata(pdev, muxc); + + for (i = 0; i < dev_num; i++) + { + int nr = pdata->base_nr + i; + unsigned int class = 0; + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_num, parent->name); + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + kfree(mux); + i2c_put_adapter(parent); + + return ret; +} + +static int __exit cpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + struct i2c_adapter *parent = muxc->parent; + + i2c_mux_del_adapters(muxc); + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_mux_driver = { + .probe = cpld_mux_probe, + .remove = __exit_p(cpld_mux_remove), /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "delta-et-c032if-cpld-mux", + }, +}; +/*---------------- MUX - end ------------- */ + +/*---------------- module initialization ------------- */ +static int __init delta_et_c032if_platform_init(void) +{ + struct i2c_adapter *adapter; + struct cpld_platform_data *cpld_pdata; + struct cpld_mux_platform_data *cpld_mux_pdata; + int ret,i = 0; + + mutex_init(&dni_lock); + printk("c032if_platform module initialization\n"); + + // set the CPLD prob and remove + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + + ret = platform_driver_register(&cpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + goto error_cpld_mux_driver; + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld2_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld2_driver; + } + + // set the SWPLD prob and remove + ret = platform_driver_register(&swpld3_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld driver\n"); + goto error_swpld3_driver; + } + + // register the i2c devices + ret = platform_driver_register(&i2c_device_driver); + if (ret) { + printk(KERN_WARNING "Fail to register i2c device driver\n"); + goto error_i2c_device_driver; + } + + // register the CPLD + ret = platform_device_register(&et_c032if_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_et_c032if_cpld; + } + + cpld_pdata = et_c032if_cpld.dev.platform_data; + cpld_mux_pdata = et_c032if_cpld_mux[0].dev.platform_data; + cpld_mux_pdata->cpld = cpld_pdata[cpu_cpld].client; + ret = platform_device_register(&et_c032if_cpld_mux[0]); + if (ret) { + printk(KERN_WARNING "Fail to create cpld mux\n"); + goto error_et_c032if_cpld_mux; + } + + adapter = i2c_get_adapter(12); + i2c_client_9548_1 = i2c_new_device(adapter, &i2c_info_pca9548[0]); + i2c_client_9548_2 = i2c_new_device(adapter, &i2c_info_pca9548[1]); + i2c_client_9548_3 = i2c_new_device(adapter, &i2c_info_pca9548[2]); + i2c_client_9548_4 = i2c_new_device(adapter, &i2c_info_pca9548[3]); + i2c_client_9548_5 = i2c_new_device(adapter, &i2c_info_pca9548[4]); + i2c_put_adapter(adapter); + + // register the SWPLD2 + ret = platform_device_register(&et_c032if_swpld2); + if (ret) { + printk(KERN_WARNING "Fail to create swpld2 device\n"); + goto error_swpld2_device; + } + + // register the SWPLD3 + ret = platform_device_register(&et_c032if_swpld3); + if (ret) { + printk(KERN_WARNING "Fail to create swpld3 device\n"); + goto error_swpld3_device; + } + for (i = 0; i < ARRAY_SIZE(et_c032if_i2c_device); i++) + { + ret = platform_device_register(&et_c032if_i2c_device[i]); + if (ret) { + printk(KERN_WARNING "Fail to create i2c device %d\n", i); + goto error_et_c032if_i2c_device; + } + } + + kobj_sfp = kobject_create_and_add("sfp", kernel_kobj); + if(!kobj_sfp) + { + return -ENOMEM; + } + ret = sysfs_create_group(kobj_sfp, &sfp_attr_grp); + if (ret) + { + printk(KERN_WARNING "Fail to create sysfs of sfp group\n"); + goto error_create_sfp_group; + } + if (ret) + goto error_create_sfp_group; + + return 0; + +error_create_sfp_group: + kobject_put(kobj_sfp); +error_et_c032if_i2c_device: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&et_c032if_i2c_device[i]); + } + i = ARRAY_SIZE(et_c032if_cpld_mux); + platform_device_unregister(&et_c032if_swpld3); +error_swpld3_device: + platform_device_unregister(&et_c032if_swpld2); +error_swpld2_device: + i2c_unregister_device(i2c_client_9548_1); + i2c_unregister_device(i2c_client_9548_2); + i2c_unregister_device(i2c_client_9548_3); + i2c_unregister_device(i2c_client_9548_4); + i2c_unregister_device(i2c_client_9548_5); +error_et_c032if_cpld_mux: + platform_device_unregister(&et_c032if_cpld_mux[0]); + platform_device_unregister(&et_c032if_cpld); +error_et_c032if_cpld: + platform_driver_unregister(&i2c_device_driver); +error_i2c_device_driver: + platform_driver_unregister(&swpld3_driver); +error_swpld3_driver: + platform_driver_unregister(&swpld2_driver); +error_swpld2_driver: + platform_driver_unregister(&cpld_mux_driver); +error_cpld_mux_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit delta_et_c032if_platform_exit(void) +{ + int i = 0; + + kobject_put(kobj_sfp); + for (i = 0; i < ARRAY_SIZE(et_c032if_i2c_device); i++) { + platform_device_unregister(&et_c032if_i2c_device[i]); + } + platform_device_unregister(&et_c032if_swpld2); + platform_device_unregister(&et_c032if_swpld3); + i2c_unregister_device(i2c_client_9548_1); + i2c_unregister_device(i2c_client_9548_2); + i2c_unregister_device(i2c_client_9548_3); + i2c_unregister_device(i2c_client_9548_4); + i2c_unregister_device(i2c_client_9548_5); + platform_device_unregister(&et_c032if_cpld_mux[0]); + platform_device_unregister(&et_c032if_cpld); + platform_driver_unregister(&i2c_device_driver); + platform_driver_unregister(&swpld2_driver); + platform_driver_unregister(&swpld3_driver); + platform_driver_unregister(&cpld_mux_driver); + platform_driver_unregister(&cpld_driver); +} + +module_init(delta_et_c032if_platform_init); +module_exit(delta_et_c032if_platform_exit); + +MODULE_DESCRIPTION("Delta et-c032if Platform Support"); +MODULE_AUTHOR("Johnson Lu "); +MODULE_LICENSE("GPL"); diff --git a/platform/innovium/sonic-platform-modules-delta/et-c032if/scripts/et-c032if_platform_init.sh b/platform/innovium/sonic-platform-modules-delta/et-c032if/scripts/et-c032if_platform_init.sh new file mode 100644 index 000000000000..522aabea26bc --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/et-c032if/scripts/et-c032if_platform_init.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +#platform init script for Delta et-c032if + + + +exit 0 + + diff --git a/platform/innovium/sonic-platform-modules-delta/systemd/platform-modules-et-c032if.service b/platform/innovium/sonic-platform-modules-delta/systemd/platform-modules-et-c032if.service new file mode 100644 index 000000000000..273a5ab65a4a --- /dev/null +++ b/platform/innovium/sonic-platform-modules-delta/systemd/platform-modules-et-c032if.service @@ -0,0 +1,13 @@ +[Unit] +Description=Delta et-c032if Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-et-c032if start +ExecStop=-/etc/init.d/platform-modules-et-c032if stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/marvell-arm64/docker-saiserver-mrvl.mk b/platform/marvell-arm64/docker-saiserver-mrvl.mk new file mode 100644 index 000000000000..a449e3e83e45 --- /dev/null +++ b/platform/marvell-arm64/docker-saiserver-mrvl.mk @@ -0,0 +1,15 @@ +# docker image for mrvl saiserver + +DOCKER_SAISERVER_MRVL = docker-saiserver-mrvl.gz +$(DOCKER_SAISERVER_MRVL)_PATH = $(PLATFORM_PATH)/docker-saiserver-mrvl +$(DOCKER_SAISERVER_MRVL)_DEPENDS += $(SAISERVER) +$(DOCKER_SAISERVER_MRVL)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_STRETCH) +SONIC_DOCKER_IMAGES += $(DOCKER_SAISERVER_MRVL) +SONIC_STRETCH_DOCKERS += $(DOCKER_SAISERVER_MRVL) + +$(DOCKER_SAISERVER_MRVL)_CONTAINER_NAME = saiserver +$(DOCKER_SAISERVER_MRVL)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SAISERVER_MRVL)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SAISERVER_MRVL)_RUN_OPT += -v /var/run/docker-saiserver:/var/run/sswsyncd +$(DOCKER_SAISERVER_MRVL)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SAISERVER_MRVL)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/marvell-arm64/docker-syncd-mrvl-rpc.mk b/platform/marvell-arm64/docker-syncd-mrvl-rpc.mk new file mode 100644 index 000000000000..c3ce6c10119c --- /dev/null +++ b/platform/marvell-arm64/docker-syncd-mrvl-rpc.mk @@ -0,0 +1,24 @@ +# docker image for mrvl syncd with rpc + +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) $(PTF) +$(DOCKER_SYNCD_MRVL_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_MRVL_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_MRVL_RPC) +SONIC_STRETCH_DOCKERS += $(DOCKER_SYNCD_MRVL_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_MRVL_RPC) +endif + +$(DOCKER_SYNCD_MRVL_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/marvell-arm64/docker-syncd-mrvl-rpc/99-syncd.conf b/platform/marvell-arm64/docker-syncd-mrvl-rpc/99-syncd.conf new file mode 100644 index 000000000000..3fabe208d815 --- /dev/null +++ b/platform/marvell-arm64/docker-syncd-mrvl-rpc/99-syncd.conf @@ -0,0 +1 @@ +sysctl -w net.core.rmem_max=509430500 diff --git a/platform/marvell-arm64/docker-syncd-mrvl-rpc/Dockerfile.j2 b/platform/marvell-arm64/docker-syncd-mrvl-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..118be5e1c5f2 --- /dev/null +++ b/platform/marvell-arm64/docker-syncd-mrvl-rpc/Dockerfile.j2 @@ -0,0 +1,55 @@ +FROM docker-syncd-mrvl + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_mrvl_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get purge -y syncd + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_mrvl_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/marvell-arm64/docker-syncd-mrvl-rpc/ptf_nn_agent.conf b/platform/marvell-arm64/docker-syncd-mrvl-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/marvell-arm64/docker-syncd-mrvl-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/marvell-arm64/docker-syncd-mrvl.mk b/platform/marvell-arm64/docker-syncd-mrvl.mk new file mode 100644 index 000000000000..dd01caab687b --- /dev/null +++ b/platform/marvell-arm64/docker-syncd-mrvl.mk @@ -0,0 +1,17 @@ +# docker image for mrvl syncd + +DOCKER_SYNCD_PLATFORM_CODE = mrvl +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) $(PYTHON_SDK_API) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) + +SONIC_STRETCH_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_STRETCH_DBG_DOCKERS += $(DOCKER_SYNCD_BASE_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/Dockerfile.j2 b/platform/marvell-arm64/docker-syncd-mrvl/Dockerfile.j2 new file mode 100755 index 000000000000..afaac3fd056c --- /dev/null +++ b/platform/marvell-arm64/docker-syncd-mrvl/Dockerfile.j2 @@ -0,0 +1,37 @@ +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 + +COPY \ +{% for deb in docker_syncd_mrvl_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + iputils-ping + +RUN apt-get -y install libpcap-dev libxml2-dev python-dev swig libsensors4-dev libjemalloc1 nfs-common + +RUN dpkg -i \ +{% for deb in docker_syncd_mrvl_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin/"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] 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..61e290e3189e --- /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 program syncd|syncd with path "/usr/bin/process_checker syncd /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/platform/marvell-arm64/docker-syncd-mrvl/critical_processes b/platform/marvell-arm64/docker-syncd-mrvl/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/marvell-arm64/docker-syncd-mrvl/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf b/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf new file mode 100644 index 000000000000..10f406129d9c --- /dev/null +++ b/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf @@ -0,0 +1,38 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python2 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running diff --git a/platform/marvell-arm64/docker-syncd-mrvl/syncd.sh b/platform/marvell-arm64/docker-syncd-mrvl/syncd.sh new file mode 100755 index 000000000000..993cf100f2f0 --- /dev/null +++ b/platform/marvell-arm64/docker-syncd-mrvl/syncd.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +function clean_up { + service syncd stop + exit +} + +trap clean_up SIGTERM SIGKILL + +service syncd start + +read diff --git a/platform/marvell-arm64/libsaithrift-dev.mk b/platform/marvell-arm64/libsaithrift-dev.mk new file mode 100644 index 000000000000..e1c3da156ec2 --- /dev/null +++ b/platform/marvell-arm64/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(MRVL_FPA) $(MRVL_SAI) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(MRVL_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(MRVL_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/marvell-arm64/linux-kernel-arm64.mk b/platform/marvell-arm64/linux-kernel-arm64.mk new file mode 100644 index 000000000000..a953c908234c --- /dev/null +++ b/platform/marvell-arm64/linux-kernel-arm64.mk @@ -0,0 +1,6 @@ +# linux kernel package for marvell arm64 + +# Add platform specific DTB +LINUX_KERNEL_DTB = linux-image-4.9.168-arm64.deb +$(LINUX_KERNEL_DTB)_URL = https://github.com/Marvell-switching/sonic-marvell-binaries/raw/master/arm64/kernel/$(LINUX_KERNEL_DTB) +SONIC_ONLINE_DEBS += $(LINUX_KERNEL_DTB) diff --git a/platform/marvell-arm64/linux/Makefile b/platform/marvell-arm64/linux/Makefile new file mode 100644 index 000000000000..89415f493c0b --- /dev/null +++ b/platform/marvell-arm64/linux/Makefile @@ -0,0 +1,10 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +LINUX_KERNEL_MRVL_URL = https://github.com/Marvell-switching/sonic-marvell-binaries/raw/master/arm64/kernel/$(LINUX_KERNEL_DTB) + +$(addprefix $(DEST)/, $(LINUX_KERNEL_DTB)): $(DEST)/% : + # get deb package + wget -O $(DEST)/$(LINUX_KERNEL_DTB) $(LINUX_KERNEL_MRVL_URL) + diff --git a/platform/marvell-arm64/one-image.mk b/platform/marvell-arm64/one-image.mk new file mode 100644 index 000000000000..3d916be4e852 --- /dev/null +++ b/platform/marvell-arm64/one-image.mk @@ -0,0 +1,14 @@ +# sonic marvell one image installer + +SONIC_ONE_IMAGE = sonic-marvell-arm64.bin +$(SONIC_ONE_IMAGE)_MACHINE = marvell-arm64 +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_IMAGE)_INSTALLS += $(LINUX_KERNEL_DTB) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/marvell-arm64/platform.conf b/platform/marvell-arm64/platform.conf new file mode 100644 index 000000000000..15f25a27b6b9 --- /dev/null +++ b/platform/marvell-arm64/platform.conf @@ -0,0 +1,226 @@ +# Copyright (C) Marvell Inc + +# over ride default behaviour + +echo "Preparing for installation ... " + +IS_MASS=0 +# global defines +kernel_addr=0x1100000 +fdt_addr=0x1000000 +fit_addr=0x1000000 +initrd_addr=0x2000000 +VAR_LOG=512 +DISK_SIZE=9 + +kernel_fname="/boot/vmlinuz-4.9.0-9-2-arm64" +initrd_fname="/boot/initrd.img-4.9.0-9-2-arm64" +fdt_fname="/boot/armada-7020-comexpress.dtb" +fit_fname="/boot/sonic_arm64.fit" + +# global mount defines +#demo_dev=/dev/sda1 +demo_mnt=/tmp +#mtd_dev=/dev/$(cat /proc/mtd | grep "ENV" | grep -o "mtd[0-9]") +FW_ENV_DEFAULT='/dev/mtd1 0x0 0x10000 0x100000' +UBOOT_FW_DEFAULT=1 + +# Skip VID Header in UBIFS +LINUX_MISC_CMD='apparmor=1 security=apparmor usbcore.autosuspend=-1' + +prepare_boot_menu() { + echo "Sync up cache ..." + sync + echo "Setting up U-Boot environment..." + + DTB_HAS_ENV_BLK=$(grep uboot-env /proc/mtd | sed -e 's/:.*$//') + if [ -c "/dev/$DTB_HAS_ENV_BLK" ]; then + PROC_ENV_FILE=$(find /proc/device-tree/ -name env_size) + if [ -n "$PROC_ENV_FILE" ] + then + UBOOT_ENV_SIZ="0x$(hd $PROC_ENV_FILE | awk 'FNR==1 {print $2 $3 $4 $5}')" + UBOOT_ENV_ERASE_SIZ="0x$(grep uboot-env /proc/mtd | awk '{print $3}')" + if [[ -n "$UBOOT_ENV_SIZ" && -n "$UBOOT_ENV_ERASE_SIZ" ]] + then + # Env info from DTB + FW_ENV_DTB="/dev/$DTB_HAS_ENV_BLK 0x00000000 $UBOOT_ENV_SIZ $UBOOT_ENV_ERASE_SIZ" + fi + fi + fi + if [ $UBOOT_FW_DEFAULT -eq 1 ] + then + echo $FW_ENV_DEFAULT > /etc/fw_env.config + echo "Using pre-configured uboot env" + fi + image_name=${image_dir}${kernel_fname} + initrd_name=${image_dir}${initrd_fname} + fdt_name=${image_dir}${fdt_fname} + fit_name=${image_dir}${fit_fname} + + if [ "$install_env" = "onie" ]; then + FW_ARG="-f" + image_dir_old="" + image_name_old="" + initrd_name_old="" + fdt_name_old="" + fit_name_old="" + sonic_version_2="None" + else + image_dir_old=$(fw_printenv -n image_dir || true) + image_name_old=$(fw_printenv -n image_name || true) + initrd_name_old=$(fw_printenv -n initrd_name || true) + fdt_name_old=$(fw_printenv -n fdt_name || true) + fit_name_old=$(fw_printenv -n fit_name || true) + sonic_version_2=$(fw_printenv -n sonic_version_1 || true) + if [ -z "$demo_dev" ] + then + get_install_device + if [ $? -ne 0 ]; then + echo "Error: Unable to detect $blk_dev $demo_dev" + exit 1 + fi + if [ ${IS_MASS} -eq 1 ] + then + demo_dev=${blk_dev}1 + else + #demo_dev=$(echo $blk_dev | sed -e 's/\(mmcblk[0-9]\)/\1p/')$demo_part + demo_dev=/dev/mmcblk0p1 + fi + fi + fi + + # Set boot variables + fw_setenv ${FW_ARG} image_dir $image_dir > /dev/null + fw_setenv ${FW_ARG} image_name $image_name > /dev/null + fw_setenv ${FW_ARG} initrd_name $initrd_name > /dev/null + fw_setenv ${FW_ARG} fdt_name $fdt_name > /dev/null + fw_setenv ${FW_ARG} fit_name $fit_name > /dev/null + fw_setenv ${FW_ARG} sonic_version_1 $demo_volume_revision_label > /dev/null + fw_setenv ${FW_ARG} image_dir_old $image_dir_old > /dev/null + fw_setenv ${FW_ARG} image_name_old $image_name_old > /dev/null + fw_setenv ${FW_ARG} initrd_name_old $initrd_name_old > /dev/null + fw_setenv ${FW_ARG} fdt_name_old $fdt_name_old > /dev/null + fw_setenv ${FW_ARG} fit_name_old $fit_name_old > /dev/null + fw_setenv ${FW_ARG} sonic_version_2 $sonic_version_2 > /dev/null + BOOT1='echo " > Boot1: $sonic_version_1 - run sonic_image_1";echo;' + BOOT2='echo " > Boot2: $sonic_version_2 - run sonic_image_2";echo;' + BOOT3='echo " > Boot3: ONIE - run onie-nand-boot";echo;' + BORDER='echo "---------------------------------------------------";echo;' + fw_setenv ${FW_ARG} print_menu $BORDER $BOOT1 $BOOT2 $BOOT3 $BORDER > /dev/null + + fw_setenv ${FW_ARG} linuxargs "net.ifnames=0 loopfstype=squashfs loop=$image_dir/$FILESYSTEM_SQUASHFS varlog_size=$VAR_LOG" > /dev/null + fw_setenv ${FW_ARG} linuxargs_old "net.ifnames=0 loopfstype=squashfs loop=$image_dir_old/$FILESYSTEM_SQUASHFS varlog_size=$VAR_LOG" > /dev/null + sonic_bootargs_old='setenv bootargs root='$demo_dev' rw rootwait rootfstype=ext4 panic=1 console=ttyS0,115200 ${othbootargs} ${mtdparts} ${linuxargs_old}' + fw_setenv ${FW_ARG} sonic_bootargs_old $sonic_bootargs_old > /dev/null || true + sonic_boot_load_old=$(fw_printenv -n sonic_boot_load || true) + old_str="_old" + fw_setenv ${FW_ARG} sonic_boot_load_old $sonic_boot_load_old$old_str > /dev/null || true + + fw_setenv ${FW_ARG} kernel_addr $kernel_addr > /dev/null + fw_setenv ${FW_ARG} fdt_addr $fdt_addr > /dev/null + fw_setenv ${FW_ARG} fit_addr $fit_addr > /dev/null + fw_setenv ${FW_ARG} initrd_addr $initrd_addr > /dev/null + # Set boot configs + if [ ${IS_MASS} -eq 1 ] + then + #USB_LOAD='ext4load usb 0 $kernel_addr $image_name; ext4load usb 0 $fdt_addr $fdt_name; ext4load usb 0 $initrd_addr $initrd_name' + USB_LOAD='ext4load usb 0 $fit_addr $fit_name' + fw_setenv ${FW_ARG} sonic_boot_load $USB_LOAD > /dev/null + else + #MMC_LOAD='ext4load mmc 0:'$demo_part' $kernel_addr $image_name; ext4load mmc 0:'$demo_part' $fdt_addr $fdt_name; ext4load mmc 0:'$demo_part' $initrd_addr $initrd_name' + MMC_LOAD='ext4load mmc 0:'$demo_part' $fit_addr $fit_name' + fw_setenv ${FW_ARG} sonic_boot_load $MMC_LOAD > /dev/null + fi + #SONIC_BOOT_CMD='run sonic_bootargs; run sonic_boot_load; booti $kernel_addr $initrd_addr $fdt_addr' + SONIC_BOOT_CMD='run sonic_bootargs; run sonic_boot_load; bootm $fit_addr' + SONIC_BOOT_CMD_OLD='run sonic_bootargs_old; run sonic_boot_load_old; bootm $fit_addr' + BOOTARGS='setenv bootargs root='$demo_dev' rw rootwait rootfstype=ext4 panic=1 console=ttyS0,115200 ${othbootargs} ${mtdparts} ${linuxargs}' + fw_setenv ${FW_ARG} sonic_bootargs $BOOTARGS > /dev/null + fw_setenv ${FW_ARG} sonic_bootcmd $SONIC_BOOT_CMD > /dev/null + fw_setenv ${FW_ARG} sonic_image_2 $SONIC_BOOT_CMD_OLD > /dev/null + fw_setenv ${FW_ARG} sonic_image_1 "$SONIC_BOOT_CMD" > /dev/null + fw_setenv ${FW_ARG} boot_next 'run sonic_image_1'> /dev/null + fw_setenv ${FW_ARG} bootcmd 'run print_menu; usb start; test -n "$boot_once" && run boot_once; run boot_next' > /dev/null + +} + +#Get block device +#Default block device is eMMC, if not look for usb storage +get_install_device() +{ + mass_bus="target0:0:0" + for i in a b c ; do + if $(ls -l /sys/block/sd$i/device 2>/dev/null | grep -q "$mass_bus") ; then + echo "/dev/sd$i" + blk_dev=/dev/sd$i + IS_MASS=1 + echo "Selected Mass storage $blk_dev" + return 0 + fi + done + mmc_bus="mmc0:aaaa" + for i in 0 1 2 ; do + if $(ls -l /sys/block/mmcblk$i/device 2>/dev/null | grep -q "$mmc_bus") ; then + echo "/dev/mmcblk$i" + blk_dev=/dev/mmcblk$i + echo "Selected mmc $blk_dev" + return 0 + fi + done + + echo "ERROR storage not found" + return 1 +} + +create_demo_partition() { + + if [ ${IS_MASS} -eq 1 ] + then + # USB drive + parted -s $blk_dev rm 1 || true + partprobe || true + parted -s --align optimal $blk_dev unit gb mkpart primary 1 $DISK_SIZE || true + partprobe || true + else + # SD CARD + parted -s /dev/mmcblk0 rm 1 + partprobe + parted -s --align optimal /dev/mmcblk0 unit gb mkpart primary 1 $DISK_SIZE + partprobe + fi +} + +create_partition() { + get_install_device + if [ $? -ne 0 ]; then + echo "Error: Unable to detect $blk_dev $demo_dev" + exit 1 + fi + # Platform specific partition + create_demo_partition +} + +mount_partition() { + if [ ${IS_MASS} -eq 1 ] + then + demo_dev=${blk_dev}1 + else + #demo_dev=$(echo $blk_dev | sed -e 's/\(mmcblk[0-9]\)/\1p/')$demo_part + demo_dev=/dev/mmcblk0p1 + fi + + # Make filesystem + echo "demo label: $demo_volume_label. $demo_dev..." + mkfs.ext4 -L $demo_volume_label $demo_dev + + mount -t ext4 -o defaults,rw $demo_dev $demo_mnt || { + echo "Error: Unable to mount $demo_dev on $demo_mnt" + exit 1 + } +} + +bootloader_menu_config() { + # Update uboot Environment + prepare_boot_menu +} + diff --git a/platform/marvell-arm64/rules.mk b/platform/marvell-arm64/rules.mk new file mode 100644 index 000000000000..f8e4c12a49ff --- /dev/null +++ b/platform/marvell-arm64/rules.mk @@ -0,0 +1,26 @@ +#include $(PLATFORM_PATH)/sdk.mk +include $(PLATFORM_PATH)/sai.mk +include $(PLATFORM_PATH)/docker-syncd-mrvl.mk +include $(PLATFORM_PATH)/docker-syncd-mrvl-rpc.mk +include $(PLATFORM_PATH)/docker-saiserver-mrvl.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/linux-kernel-arm64.mk +INCLUDE_SYSTEM_TELEMETRY = "" + + +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_FPM) \ + $(DOCKER_PTF_MRVL) \ + $(DOCKER_SYNCD_MRVL_RPC) + +# Inject mrvl sai into syncd +$(SYNCD)_DEPENDS += $(MRVL_SAI) +$(SYNCD)_UNINSTALLS += $(MRVL_DEV) + +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV) +endif + +# Runtime dependency on mrvl sai is set only for syncd +$(SYNCD)_RDEPENDS += $(MRVL_SAI) diff --git a/platform/marvell-arm64/sai.mk b/platform/marvell-arm64/sai.mk new file mode 100644 index 000000000000..6cf79472963f --- /dev/null +++ b/platform/marvell-arm64/sai.mk @@ -0,0 +1,9 @@ +# Marvell SAI + +export MRVL_SAI_VERSION = 1.5.1 +export MRVL_SAI = mrvllibsai_$(PLATFORM_ARCH)_$(MRVL_SAI_VERSION).deb + +$(MRVL_SAI)_SRC_PATH = $(PLATFORM_PATH)/sai +$(eval $(call add_conflict_package,$(MRVL_SAI),$(LIBSAIVS_DEV))) + +SONIC_MAKE_DEBS += $(MRVL_SAI) diff --git a/platform/marvell-arm64/sai/Makefile b/platform/marvell-arm64/sai/Makefile new file mode 100644 index 000000000000..3e990575cb54 --- /dev/null +++ b/platform/marvell-arm64/sai/Makefile @@ -0,0 +1,9 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MRVL_SAI_URL = https://github.com/Marvell-switching/sonic-marvell-binaries/raw/master/arm64/sai-plugin/$(MRVL_SAI) + +$(addprefix $(DEST)/, $(MRVL_SAI)): $(DEST)/% : + # get deb package + wget -O $(DEST)/$(MRVL_SAI) $(MRVL_SAI_URL) diff --git a/platform/marvell-arm64/sonic_fit.its b/platform/marvell-arm64/sonic_fit.its new file mode 100644 index 000000000000..9b09d4cd3d4c --- /dev/null +++ b/platform/marvell-arm64/sonic_fit.its @@ -0,0 +1,55 @@ +/dts-v1/; + +/ { + description = "U-Boot fitImage for SONIC Marvell Arm64"; + #address-cells = <1>; + + images { + kernel@0 { + description = "Linux Kernel"; + data = /incbin/("/boot/vmlinuz-4.9.0-9-2-arm64"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x6000000>; + entry = <0x6000000>; + hash@1 { + algo = "sha1"; + }; + }; + fdt@0 { + description = "Flattened Device Tree blob"; + data = /incbin/("/boot/armada-7020-comexpress.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + hash@1 { + algo = "sha1"; + }; + }; + ramdisk@0 { + description = "ramdisk"; + data = /incbin/("/boot/initrd.img-4.9.0-9-2-arm64"); + type = "ramdisk"; + arch = "arm64"; + os = "linux"; + compression = "gzip"; + hash@1 { + algo = "sha1"; + }; + }; + }; + configurations { + default = "conf@1"; + conf@1 { + description = "Boot Linux kernel with FDT blob + ramdisk"; + kernel = "kernel@0"; + fdt = "fdt@0"; + ramdisk = "ramdisk@0"; + hash@1 { + algo = "sha1"; + }; + }; + }; +}; diff --git a/platform/marvell-armhf/docker-saiserver-mrvl.mk b/platform/marvell-armhf/docker-saiserver-mrvl.mk new file mode 100644 index 000000000000..8720e3364688 --- /dev/null +++ b/platform/marvell-armhf/docker-saiserver-mrvl.mk @@ -0,0 +1,16 @@ +# docker image for mrvl saiserver + +DOCKER_SAISERVER_MRVL = docker-saiserver-mrvl.gz +$(DOCKER_SAISERVER_MRVL)_PATH = $(PLATFORM_PATH)/docker-saiserver-mrvl +$(DOCKER_SAISERVER_MRVL)_DEPENDS += $(SAISERVER) +$(DOCKER_SAISERVER_MRVL)_FILES += $(DSSERVE) $(BCMCMD) +$(DOCKER_SAISERVER_MRVL)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_STRETCH) +SONIC_DOCKER_IMAGES += $(DOCKER_SAISERVER_MRVL) +SONIC_STRETCH_DOCKERS += $(DOCKER_SAISERVER_MRVL) + +$(DOCKER_SAISERVER_MRVL)_CONTAINER_NAME = saiserver +$(DOCKER_SAISERVER_MRVL)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SAISERVER_MRVL)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SAISERVER_MRVL)_RUN_OPT += -v /var/run/docker-saiserver:/var/run/sswsyncd +$(DOCKER_SAISERVER_MRVL)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SAISERVER_MRVL)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/marvell-armhf/docker-syncd-mrvl-rpc.mk b/platform/marvell-armhf/docker-syncd-mrvl-rpc.mk new file mode 100644 index 000000000000..c3ce6c10119c --- /dev/null +++ b/platform/marvell-armhf/docker-syncd-mrvl-rpc.mk @@ -0,0 +1,24 @@ +# docker image for mrvl syncd with rpc + +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) $(PTF) +$(DOCKER_SYNCD_MRVL_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_MRVL_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_MRVL_RPC) +SONIC_STRETCH_DOCKERS += $(DOCKER_SYNCD_MRVL_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_MRVL_RPC) +endif + +$(DOCKER_SYNCD_MRVL_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/marvell-armhf/docker-syncd-mrvl-rpc/99-syncd.conf b/platform/marvell-armhf/docker-syncd-mrvl-rpc/99-syncd.conf new file mode 100644 index 000000000000..3fabe208d815 --- /dev/null +++ b/platform/marvell-armhf/docker-syncd-mrvl-rpc/99-syncd.conf @@ -0,0 +1 @@ +sysctl -w net.core.rmem_max=509430500 diff --git a/platform/marvell-armhf/docker-syncd-mrvl-rpc/Dockerfile.j2 b/platform/marvell-armhf/docker-syncd-mrvl-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..118be5e1c5f2 --- /dev/null +++ b/platform/marvell-armhf/docker-syncd-mrvl-rpc/Dockerfile.j2 @@ -0,0 +1,55 @@ +FROM docker-syncd-mrvl + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_mrvl_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get purge -y syncd + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_mrvl_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/marvell-armhf/docker-syncd-mrvl-rpc/ptf_nn_agent.conf b/platform/marvell-armhf/docker-syncd-mrvl-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/marvell-armhf/docker-syncd-mrvl-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/marvell-armhf/docker-syncd-mrvl.mk b/platform/marvell-armhf/docker-syncd-mrvl.mk new file mode 100644 index 000000000000..dd01caab687b --- /dev/null +++ b/platform/marvell-armhf/docker-syncd-mrvl.mk @@ -0,0 +1,17 @@ +# docker image for mrvl syncd + +DOCKER_SYNCD_PLATFORM_CODE = mrvl +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) $(PYTHON_SDK_API) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) + +SONIC_STRETCH_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_STRETCH_DBG_DOCKERS += $(DOCKER_SYNCD_BASE_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/Dockerfile.j2 b/platform/marvell-armhf/docker-syncd-mrvl/Dockerfile.j2 new file mode 100755 index 000000000000..afaac3fd056c --- /dev/null +++ b/platform/marvell-armhf/docker-syncd-mrvl/Dockerfile.j2 @@ -0,0 +1,37 @@ +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 + +COPY \ +{% for deb in docker_syncd_mrvl_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + iputils-ping + +RUN apt-get -y install libpcap-dev libxml2-dev python-dev swig libsensors4-dev libjemalloc1 nfs-common + +RUN dpkg -i \ +{% for deb in docker_syncd_mrvl_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin/"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] 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..61e290e3189e --- /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 program syncd|syncd with path "/usr/bin/process_checker syncd /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/platform/marvell-armhf/docker-syncd-mrvl/critical_processes b/platform/marvell-armhf/docker-syncd-mrvl/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/marvell-armhf/docker-syncd-mrvl/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf b/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf new file mode 100644 index 000000000000..e633b4fe115c --- /dev/null +++ b/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf @@ -0,0 +1,38 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python2 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running diff --git a/platform/marvell-armhf/libsaithrift-dev.mk b/platform/marvell-armhf/libsaithrift-dev.mk new file mode 100644 index 000000000000..e1c3da156ec2 --- /dev/null +++ b/platform/marvell-armhf/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(MRVL_FPA) $(MRVL_SAI) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(MRVL_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(MRVL_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/marvell-armhf/linux-kernel-armhf.mk b/platform/marvell-armhf/linux-kernel-armhf.mk new file mode 100644 index 000000000000..ac7aa3faf19a --- /dev/null +++ b/platform/marvell-armhf/linux-kernel-armhf.mk @@ -0,0 +1,6 @@ +# linux kernel package for marvell armhf + +# Add platform specific DTB +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) diff --git a/platform/marvell-armhf/linux/Makefile b/platform/marvell-armhf/linux/Makefile new file mode 100644 index 000000000000..dba660649abf --- /dev/null +++ b/platform/marvell-armhf/linux/Makefile @@ -0,0 +1,10 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +LINUX_KERNEL_MRVL_URL = https://github.com/Marvell-switching/sonic-marvell-binaries/raw/master/armhf/kernel/$(LINUX_KERNEL_DTB) + +$(addprefix $(DEST)/, $(LINUX_KERNEL_DTB)): $(DEST)/% : + # get deb package + wget -O $(DEST)/$(LINUX_KERNEL_DTB) $(LINUX_KERNEL_MRVL_URL) + diff --git a/platform/marvell-armhf/one-image.mk b/platform/marvell-armhf/one-image.mk new file mode 100644 index 000000000000..44bcd9595281 --- /dev/null +++ b/platform/marvell-armhf/one-image.mk @@ -0,0 +1,16 @@ +# sonic marvell one image installer + +SONIC_ONE_IMAGE = sonic-marvell-armhf.bin +$(SONIC_ONE_IMAGE)_MACHINE = marvell-armhf +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_IMAGE)_INSTALLS += $(LINUX_KERNEL_DTB) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(ET6448M_PLATFORM) \ + $(NOKIA_7215_PLATFORM) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/marvell-armhf/platform-et6448m.mk b/platform/marvell-armhf/platform-et6448m.mk new file mode 100644 index 000000000000..1f0ee201cc76 --- /dev/null +++ b/platform/marvell-armhf/platform-et6448m.mk @@ -0,0 +1,8 @@ +# ET6448M Platform + +ET6448M_VERSION=0.1 +ET6448M_PLATFORM = sonic-platform-et6448m_$(ET6448M_VERSION)_$(CONFIGURED_ARCH).deb +$(ET6448M_PLATFORM)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-et6448m +$(ET6448M_PLATFORM)_PLATFORM = armhf-marvell_et6448m_52x-r0 +SONIC_DPKG_DEBS += $(ET6448M_PLATFORM) + diff --git a/platform/marvell-armhf/platform-nokia.mk b/platform/marvell-armhf/platform-nokia.mk new file mode 100644 index 000000000000..7e7df9cb13cc --- /dev/null +++ b/platform/marvell-armhf/platform-nokia.mk @@ -0,0 +1,11 @@ +# Nokia Platform + +NOKIA_7215_PLATFORM_VERSION = 1.0 +export NOKIA_7215_PLATFORM_VERSION + +NOKIA_7215_PLATFORM = sonic-platform-nokia-7215_$(NOKIA_7215_PLATFORM_VERSION)_$(CONFIGURED_ARCH).deb +$(NOKIA_7215_PLATFORM)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-nokia +$(NOKIA_7215_PLATFORM)_PLATFORM = armhf-nokia_ixs7215_52x-r0 +SONIC_DPKG_DEBS += $(NOKIA_7215_PLATFORM) + +SONIC_STRETCH_DEBS += $(NOKIA_7215_PLATFORM) diff --git a/platform/marvell-armhf/platform.conf b/platform/marvell-armhf/platform.conf new file mode 100644 index 000000000000..78f64b6fbe18 --- /dev/null +++ b/platform/marvell-armhf/platform.conf @@ -0,0 +1,271 @@ +# Copyright (C) Marvell Inc + +# over ride default behaviour + +echo "Preparing for installation ... " + +# global defines +kernel_addr=0x1100000 +fdt_addr=0x1000000 +initrd_addr=0x2000000 +VAR_LOG=512 + +kernel_fname="/boot/vmlinuz-4.19.0-12-2-armmp" +initrd_fname="/boot/initrd.img-4.19.0-12-2-armmp" +fdt_fname="/boot/armada-385-ET6448M_4G_Nand.dtb" + +if [ "$install_env" = "onie" ]; then + MACH_FILE="/etc/machine.conf" +else + MACH_FILE="/host/machine.conf" +fi +# armhf-marvell_et6448m_52x-r0 - Platform = Et6448M +# armhf-nokia_ixs7215_52x-r0 - Platform = Nokia IPD6448M +PLATFORM=`sed -n 's/^onie_platform=\(.*\)/\1/p' $MACH_FILE` +echo "Intalling SONiC from $install_env on Platform $PLATFORM" + +# global mount defines +if [ "$PLATFORM" = "armhf-marvell_et6448m_52x-r0" ]; then + demo_dev=ubi0 + mtd_dev=/dev/$(cat /proc/mtd | grep "SONIC" | grep -o "mtd[0-9]") + mtd_num=$(echo $mtd_dev | grep -o "[0-9]") + + fdt_fname="/boot/armada-385-ET6448M_4G_Nand.dtb" + + BOOTARGS='setenv bootargs root='$demo_dev' rw rootwait ubi.mtd='$mtd_num' rootfstype=ubifs panic=1 console=ttyS0,115200 ${othbootargs} ${mtdparts} ${linuxargs}' + UBI_LOAD='run ubi_sonic_boot_mount_ubi; ubifsload $kernel_addr $image_name;ubifsload $fdt_addr $fdt_name; ubifsload $initrd_addr $initrd_name' + BOOTARGS_OLD='setenv bootargs root='$demo_dev' rw rootwait ubi.mtd='$mtd_num' rootfstype=ubifs panic=1 console=ttyS0,115200 ${othbootargs} ${mtdparts} ${linuxargs_old}' + UBI_LOAD_OLD='run ubi_sonic_boot_mount_ubi; ubifsload $kernel_addr $image_name_old;ubifsload $fdt_addr $fdt_name_old; ubifsload $initrd_addr $initrd_name_old' + UBIBOOTCMD='run ubi_sonic_boot_bootargs; run ubi_sonic_boot_load; test -n "$boot_once" && setenv boot_once "" && saveenv; bootz $kernel_addr $initrd_addr $fdt_addr' + UBIBOOTCMD_OLD='run ubi_sonic_boot_bootargs_old; run ubi_sonic_boot_load_old; test -n "$boot_once" && setenv boot_once "" && saveenv; bootz $kernel_addr $initrd_addr $fdt_addr' + LINUX_MISC_CMD='apparmor=1 security=apparmor usbcore.autosuspend=-1' + +elif [ "$PLATFORM" = "armhf-nokia_ixs7215_52x-r0" ]; then + demo_dev=sda2 + + fdt_fname="/boot/armada-385-ipd6448m.dtb" + + BOOTARGS='setenv bootargs root=/dev/'$demo_dev' rw rootwait rootfstype=ext4 panic=1 console=ttyS0,115200 ${othbootargs} ${mtdparts} ${linuxargs}' + UBI_LOAD='scsi init; ext4load scsi 0:2 $kernel_addr $image_name; ext4load scsi 0:2 $fdt_addr $fdt_name; ext4load scsi 0:2 $initrd_addr $initrd_name' + BOOTARGS_OLD='setenv bootargs root=/dev/'$demo_dev' rw rootwait rootfstype=ext4 panic=1 console=ttyS0,115200 ${othbootargs} ${mtdparts} ${linuxargs_old}' + UBI_LOAD_OLD='scsi init; ext4load scsi 0:2 $kernel_addr $image_name_old; ext4load scsi 0:2 $fdt_addr $fdt_name_old; ext4load scsi 0:2 $initrd_addr $initrd_name_old' + UBIBOOTCMD='run ubi_sonic_boot_bootargs; run ubi_sonic_boot_load; test -n "$boot_once" && setenv boot_once "" && saveenv; bootz $kernel_addr $initrd_addr $fdt_addr' + UBIBOOTCMD_OLD='run ubi_sonic_boot_bootargs_old; run ubi_sonic_boot_load_old; test -n "$boot_once" && setenv boot_once "" && saveenv; bootz $kernel_addr $initrd_addr $fdt_addr' + LINUX_MISC_CMD='apparmor=1 security=apparmor usbcore.autosuspend=-1' + +else + echo "Unsupported Platform $PLAFORM" + exit 2 +fi +demo_mnt=/tmp +FW_ENV_DEFAULT='/dev/mtd0 0x00500000 0x80000 0x100000 8' +UBOOT_FW_DEFAULT=1 + +prepare_boot_menu() { + echo "Sync up cache ..." + sync + echo "Setting up U-Boot environment..." + + DTB_HAS_ENV_BLK=$(grep uboot-env /proc/mtd | sed -e 's/:.*$//') + if [ -c "/dev/$DTB_HAS_ENV_BLK" ]; then + PROC_ENV_FILE=$(find /proc/device-tree/ -name env_size) + if [ -n "$PROC_ENV_FILE" ] + then + UBOOT_ENV_SIZ="0x$(hd $PROC_ENV_FILE | awk 'FNR==1 {print $2 $3 $4 $5}')" + UBOOT_ENV_ERASE_SIZ="0x$(grep uboot-env /proc/mtd | awk '{print $3}')" + if [[ -n "$UBOOT_ENV_SIZ" && -n "$UBOOT_ENV_ERASE_SIZ" ]] + then + # Env info from DTB + FW_ENV_DTB="/dev/$DTB_HAS_ENV_BLK 0x00000000 $UBOOT_ENV_SIZ $UBOOT_ENV_ERASE_SIZ" + fi + fi + fi + if [ -n "$FW_ENV_DTB" ] + then + echo $FW_ENV_DTB > /etc/fw_env.config + echo "Found uboot env offset in device tree" + UBOOT_ENV_CRC=$(fw_printenv 2>&1 | grep -c 'Warning: Bad CRC') || true + if [ "$UBOOT_ENV_CRC" -eq 0 ] + then + echo "Uboot env offset in device tree is valid" + UBOOT_FW_DEFAULT=0 + fdt_fname="/boot/armada-385-ET6448M_4G_Nand_r2019.dtb" + else + echo "Uboot env offset in device tree is NOT valid" + UBOOT_FW_DEFAULT=1 + fi + fi + if [ $UBOOT_FW_DEFAULT -eq 1 ] + then + echo $FW_ENV_DEFAULT > /etc/fw_env.config + echo "Using pre-configured uboot env" + fi + if [ "$PLATFORM" = "armhf-nokia_ixs7215_52x-r0" ]; then + FW_ENV_DEFAULT='/dev/mtd0 0x00100000 0x10000 0x10000' + echo $FW_ENV_DEFAULT > /etc/fw_env.config + echo "Using pre-configured uboot env for armhf-nokia_ixs7215_52x-r0" + fi + + image_name=${image_dir}${kernel_fname} + initrd_name=${image_dir}${initrd_fname} + fdt_name=${image_dir}${fdt_fname} + + if [ "$install_env" = "onie" ]; then + FW_ARG="-f" + image_dir_old="" + image_name_old="" + initrd_name_old="" + fdt_name_old="" + sonic_version_2="None" + else + image_dir_old=$(fw_printenv -n image_dir || true) + image_name_old=$(fw_printenv -n image_name || true) + initrd_name_old=$(fw_printenv -n initrd_name || true) + fdt_name_old=$(fw_printenv -n fdt_name || true) + sonic_version_2=$(fw_printenv -n sonic_version_1 || true) + fi + + # Set boot variables + fw_setenv ${FW_ARG} image_dir $image_dir > /dev/null + fw_setenv ${FW_ARG} image_name $image_name > /dev/null + fw_setenv ${FW_ARG} initrd_name $initrd_name > /dev/null + fw_setenv ${FW_ARG} fdt_name $fdt_name > /dev/null + fw_setenv ${FW_ARG} sonic_version_1 $demo_volume_revision_label > /dev/null + fw_setenv ${FW_ARG} image_dir_old $image_dir_old > /dev/null + fw_setenv ${FW_ARG} image_name_old $image_name_old > /dev/null + fw_setenv ${FW_ARG} initrd_name_old $initrd_name_old > /dev/null + fw_setenv ${FW_ARG} fdt_name_old $fdt_name_old > /dev/null + fw_setenv ${FW_ARG} sonic_version_2 $sonic_version_2 > /dev/null + BOOT1='echo " > Boot1: $sonic_version_1 - run sonic_image_1";echo;' + BOOT2='echo " > Boot2: $sonic_version_2 - run sonic_image_2";echo;' + if [ "$PLATFORM" = "armhf-nokia_ixs7215_52x-r0" ]; then + BOOT3='echo " > Boot3: ONIE - run onie_bootcmd";echo;' + else + BOOT3='echo " > Boot3: ONIE - run onie_nand_boot";echo;' + fi + BORDER='echo "---------------------------------------------------";echo;' + fw_setenv ${FW_ARG} print_menu $BORDER $BOOT1 $BOOT2 $BOOT3 $BORDER > /dev/null + + fw_setenv ${FW_ARG} linuxargs "net.ifnames=0 loopfstype=squashfs loop=$image_dir/$FILESYSTEM_SQUASHFS varlog_size=$VAR_LOG loglevel=4" > /dev/null + fw_setenv ${FW_ARG} linuxargs_old "net.ifnames=0 loopfstype=squashfs loop=$image_dir_old/$FILESYSTEM_SQUASHFS varlog_size=$VAR_LOG loglevel=4" > /dev/null + + # Set boot configs + fw_setenv ${FW_ARG} kernel_addr $kernel_addr > /dev/null + fw_setenv ${FW_ARG} fdt_addr $fdt_addr > /dev/null + fw_setenv ${FW_ARG} initrd_addr $initrd_addr > /dev/null + fw_setenv ${FW_ARG} mtdids 'nand0=armada-nand' > /dev/null + if [ $UBOOT_FW_DEFAULT -eq 1 ] + then + fw_setenv ${FW_ARG} mtdparts 'mtdparts=armada-nand:10m(U-Boot)ro,20m@10m(ONIE),-(SONIC)' > /dev/null + else + fw_setenv ${FW_ARG} mtdparts 'mtdparts=armada-nand:4m(uboot)ro,5m@5m(uboot-env),20m@10m(ONIE),-(SONIC)' > /dev/null + fi + if [ "$PLATFORM" = "armhf-nokia_ixs7215_52x-r0" ]; then + fw_setenv ${FW_ARG} mtdparts 'mtdparts=spi0.0:4m(boot),-(spi-rootfs)' > /dev/null + fi + fw_setenv ${FW_ARG} ubi_sonic_boot_mount_ubi 'ubi part SONIC; ubifsmount ubi0' > /dev/null + fw_setenv ${FW_ARG} ubi_sonic_boot_bootargs $BOOTARGS > /dev/null + fw_setenv ${FW_ARG} ubi_sonic_boot_load $UBI_LOAD > /dev/null + fw_setenv ${FW_ARG} sonic_image_1 "$UBIBOOTCMD" > /dev/null + fw_setenv ${FW_ARG} ubi_sonic_boot_bootargs_old $BOOTARGS_OLD > /dev/null + fw_setenv ${FW_ARG} ubi_sonic_boot_load_old $UBI_LOAD_OLD > /dev/null + fw_setenv ${FW_ARG} sonic_image_2 "$UBIBOOTCMD_OLD" > /dev/null + fw_setenv ${FW_ARG} boot_next 'run sonic_image_1'> /dev/null + fw_setenv ${FW_ARG} bootcmd 'run print_menu; usb start; test -n "$boot_once" && run boot_once; run boot_next' > /dev/null + +} + +create_ubi_partition() { + ubidetach /dev/ubi_ctrl -d 0 2>/dev/null || true + + trap_push "${onie_bin} ubidetach -d 0 /dev/ubi_ctrl || true" + echo -en "Format mtd partition '$mtd_dev' " + ubiformat $mtd_dev -y -q || { + echo "Failed" + } + + #attaches MTD devices (which describe raw flash) to UBI and creates corresponding UBI devices; ('-m 2' --> mtd2) + echo -en "ubiattach mtd '$mtd_num' " + ubiattach /dev/ubi_ctrl -m $mtd_num || { + echo "Failed" + } + + #creates UBI volumes on UBI devices + ubimkvol /dev/$demo_dev -N $demo_dev -s 3900MiB +} + +create_gpt_partition() { + blk_dev="/dev/sda" + demo_part=$(sgdisk -p $blk_dev | grep -e "$demo_volume_label" -e "$legacy_volume_label" | awk '{print $1}') + # ONIE partition size 168MB + onie_part_size=168 + + if [ -z "$demo_part" ] ; then + # Partition Does NOT Exists + echo "SONIC label [$demo_volume_label] is NOT found in Partition" + echo "Proceeding to create partition" + + attr_bitmask="0x0" + + sgdisk --new=${demo_part}::+${onie_part_size}MB \ + --attributes=${demo_part}:=:$attr_bitmask \ + --change-name=${demo_part}:$demo_volume_label $blk_dev \ + || { + echo "Warning: The first trial of creating partition failed, trying the largest aligned available block of sectors on the disk" + begin=$(sgdisk -F $blk_dev) + end=$(sgdisk -E $blk_dev) + sgdisk --new=${demo_part}:$begin:$end \ + --attributes=${demo_part}:=:$attr_bitmask \ + --change-name=${demo_part}:$demo_volume_label $blk_dev + } || { + echo "Error: Unable to create partition $demo_part on $blk_dev" + exit 1 + } + partprobe || true + else + # Partition Exists + echo "Partition exists $demo_part on $blk_dev" + fi + + # Make filesystem + mkfs.ext4 -L $demo_volume_label /dev/$demo_dev +} + +create_partition() { + # Platform speicific partition + if [ "$PLATFORM" = "armhf-marvell_et6448m_52x-r0" ]; then + echo "Doing UBI partition" + create_ubi_partition + else + echo "Doing GPT partition" + create_gpt_partition + fi +} + +mount_partition() { + + demo_mnt=$(mktemp -d) || { + echo "Error: Unable to create file sstem mount point" + exit 1 + } + + echo "Mounting $demo_dev on $demo_mnt " + if [ "$PLATFORM" = "armhf-marvell_et6448m_52x-r0" ]; then + trap_push "${onie_bin} umount /dev/ubi0_0|| true" + mount -t ubifs /dev/ubi0_0 $demo_mnt || { + echo "mount -t ubifs /dev/ubi0_0 $demo_mnt Failed" + exit 1 + } + else + trap_push "${onie_bin} umount /dev/sda2|| true" + mount -t ext4 /dev/sda2 $demo_mnt || { + echo "mount -t ext4 /dev/sda2 $demo_mnt Failed" + exit 1 + } + fi +} + +bootloader_menu_config() { + # Update uboot Environment + prepare_boot_menu +} diff --git a/platform/marvell-armhf/rules.mk b/platform/marvell-armhf/rules.mk new file mode 100644 index 000000000000..58b9654956f3 --- /dev/null +++ b/platform/marvell-armhf/rules.mk @@ -0,0 +1,28 @@ +#include $(PLATFORM_PATH)/sdk.mk +include $(PLATFORM_PATH)/sai.mk +include $(PLATFORM_PATH)/docker-syncd-mrvl.mk +include $(PLATFORM_PATH)/docker-syncd-mrvl-rpc.mk +include $(PLATFORM_PATH)/docker-saiserver-mrvl.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/linux-kernel-armhf.mk +include $(PLATFORM_PATH)/platform-et6448m.mk +include $(PLATFORM_PATH)/platform-nokia.mk + +ENABLE_SYNCD_RPC = "" +INCLUDE_MGMT_FRAMEWORK = "" + +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_FPM) + #$(DOCKER_SYNCD_MRVL_RPC) + +# Inject mrvl sai into syncd +$(SYNCD)_DEPENDS += $(MRVL_SAI) +$(SYNCD)_UNINSTALLS += $(MRVL_SAI) + +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV) +endif + +# Runtime dependency on mrvl sai is set only for syncd +$(SYNCD)_RDEPENDS += $(MRVL_SAI) diff --git a/platform/marvell-armhf/sai.mk b/platform/marvell-armhf/sai.mk new file mode 100644 index 000000000000..70aebfb514e3 --- /dev/null +++ b/platform/marvell-armhf/sai.mk @@ -0,0 +1,9 @@ +# Marvell SAI + +export MRVL_SAI_VERSION = 1.7.1 +export MRVL_SAI = mrvllibsai_m0_MASTER_$(PLATFORM_ARCH)_$(MRVL_SAI_VERSION).deb + +$(MRVL_SAI)_SRC_PATH = $(PLATFORM_PATH)/sai +$(eval $(call add_conflict_package,$(MRVL_SAI),$(LIBSAIVS_DEV))) + +SONIC_MAKE_DEBS += $(MRVL_SAI) diff --git a/platform/marvell-armhf/sai/Makefile b/platform/marvell-armhf/sai/Makefile new file mode 100644 index 000000000000..cf78504388c6 --- /dev/null +++ b/platform/marvell-armhf/sai/Makefile @@ -0,0 +1,9 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MRVL_SAI_URL = https://github.com/Marvell-switching/sonic-marvell-binaries/raw/master/armhf/sai-plugin/$(MRVL_SAI) + +$(addprefix $(DEST)/, $(MRVL_SAI)): $(DEST)/% : + # get deb package + wget -O $(DEST)/$(MRVL_SAI) $(MRVL_SAI_URL) diff --git a/platform/marvell-armhf/sonic-platform-et6448m/.gitignore b/platform/marvell-armhf/sonic-platform-et6448m/.gitignore new file mode 100644 index 000000000000..7f287d538227 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-et6448m/.gitignore @@ -0,0 +1,50 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +# Kernel Module Compile Results +*.mod* +*.cmd +*.o.d +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Debian packaging +*.debhelper.log +*.postinst.debhelper +*.postrm.debhelper +*.prerm.debhelper +*.substvars diff --git a/platform/marvell-armhf/sonic-platform-et6448m/debian/changelog b/platform/marvell-armhf/sonic-platform-et6448m/debian/changelog new file mode 100755 index 000000000000..98934823b4f5 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-et6448m/debian/changelog @@ -0,0 +1,5 @@ +sonic-platform-et6448m (0.1) unstable; urgency=low + + * Add support for ET6448M. + + -- Marvell Mon, 11 Nov 2019 09:35:58 +0800 diff --git a/platform/marvell-armhf/sonic-platform-et6448m/debian/compat b/platform/marvell-armhf/sonic-platform-et6448m/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-et6448m/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/marvell-armhf/sonic-platform-et6448m/debian/control b/platform/marvell-armhf/sonic-platform-et6448m/debian/control new file mode 100755 index 000000000000..52c9593a1ea5 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-et6448m/debian/control @@ -0,0 +1,15 @@ +Source: sonic-platform-et6448m +Section: unknown +Priority: optional +Maintainer: Marvell +Build-Depends: debhelper (>=9) +Standards-Version: 3.9.6 +Homepage: +#Vcs-Git: git://anonscm.debian.org/collab-maint/sonic-platform-et6448m.git +#Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/sonic-platform-et6448m.git + +Package: sonic-platform-et6448m +Architecture: armhf +Depends: ${misc:Depends} +Description: + diff --git a/platform/marvell-armhf/sonic-platform-et6448m/debian/install b/platform/marvell-armhf/sonic-platform-et6448m/debian/install new file mode 100644 index 000000000000..ceb6090c4058 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-et6448m/debian/install @@ -0,0 +1,3 @@ +et6448m_plt_setup.sh usr/sbin +entropy.py etc/ +inband_mgmt.sh etc/ diff --git a/platform/marvell-armhf/sonic-platform-et6448m/debian/postinst b/platform/marvell-armhf/sonic-platform-et6448m/debian/postinst new file mode 100644 index 000000000000..a3a727c7222c --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-et6448m/debian/postinst @@ -0,0 +1,40 @@ +#!/bin/sh +# postinst script for sonic-platform-et6448m +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + sh /usr/sbin/et6448m_plt_setup.sh + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/platform/marvell-armhf/sonic-platform-et6448m/debian/rules b/platform/marvell-armhf/sonic-platform-et6448m/debian/rules new file mode 100755 index 000000000000..2f54c4710f17 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-et6448m/debian/rules @@ -0,0 +1,25 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#export DH_VERBOSE = 1 + + +# see FEATURE AREAS in dpkg-buildflags(1) +#export DEB_BUILD_MAINT_OPTIONS = hardening=+all + +# see ENVIRONMENT in dpkg-buildflags(1) +# package maintainers to append CFLAGS +#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic +# package maintainers to append LDFLAGS +#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed + + +%: + dh $@ + + +# dh_make generated override targets +# This is example for Cmake (See https://bugs.debian.org/641051 ) +#override_dh_auto_configure: +# dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH) + diff --git a/platform/marvell-armhf/sonic-platform-et6448m/entropy.py b/platform/marvell-armhf/sonic-platform-et6448m/entropy.py new file mode 100644 index 000000000000..338e2ad9bcea --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-et6448m/entropy.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +import fcntl, struct +import time +from os import path + +RNDADDENTROPY=0x40085203 + +def avail(): + with open("/proc/sys/kernel/random/entropy_avail", mode='r') as avail: + return int(avail.read()) + +if path.exists("/proc/sys/kernel/random/entropy_avail"): + while 1: + while avail() < 2048: + with open('/dev/urandom', 'rb') as urnd, open("/dev/random", mode='wb') as rnd: + d = urnd.read(512) + t = struct.pack('ii', 4 * len(d), len(d)) + d + fcntl.ioctl(rnd, RNDADDENTROPY, t) + time.sleep(30) diff --git a/platform/marvell-armhf/sonic-platform-et6448m/et6448m_plt_setup.sh b/platform/marvell-armhf/sonic-platform-et6448m/et6448m_plt_setup.sh new file mode 100755 index 000000000000..a587b3b17ca5 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-et6448m/et6448m_plt_setup.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +fw_uboot_env_cfg() +{ + echo "Setting up U-Boot environment..." + FW_ENV_DEFAULT='/dev/mtd0 0x00500000 0x80000 0x100000 8' + UBOOT_FW_DFAULT=1 + + DTB_HAS_ENV_BLK=$(grep uboot-env /proc/mtd | sed -e 's/:.*$//') + if [ -c "/dev/$DTB_HAS_ENV_BLK" ]; then + PROC_ENV_FILE=$(find /proc/device-tree/ -name env_size) + if [ -n "$PROC_ENV_FILE" ] + then + UBOOT_ENV_SIZ="0x$(hd $PROC_ENV_FILE | awk 'FNR==1 {print $2 $3 $4 $5}')" + UBOOT_ENV_ERASE_SIZ="0x$(grep uboot-env /proc/mtd | awk '{print $3}')" + if [[ -n "$UBOOT_ENV_SIZ" && -n "$UBOOT_ENV_ERASE_SIZ" ]] + then + # Env info from DTB + FW_ENV_DTB="/dev/$DTB_HAS_ENV_BLK 0x00000000 $UBOOT_ENV_SIZ $UBOOT_ENV_ERASE_SIZ" + fi + fi + fi + if [ -n "$FW_ENV_DTB" ] + then + echo $FW_ENV_DTB > /etc/fw_env.config + echo "Found uboot env offset in device tree" + UBOOT_ENV_CRC=$(fw_printenv -c /etc/fw_env.config 2>&1 | grep -c 'Warning: Bad CRC') + if [ $UBOOT_ENV_CRC -eq 0 ] + then + echo "Uboot env offset in device tree is valid" + UBOOT_FW_DFAULT=0 + else + echo "Uboot env offset in device tree is NOT valid" + UBOOT_FW_DFAULT=1 + fi + fi + if [ $UBOOT_FW_DFAULT -eq 1 ] + then + echo $FW_ENV_DEFAULT > /etc/fw_env.config + echo "Using pre-configured uboot env" + fi +} + +et6448m_profile() +{ + MAC_ADDR=$(fw_printenv -n ethaddr) + sed -i "s/switchMacAddress=.*/switchMacAddress=$MAC_ADDR/g" /usr/share/sonic/device/armhf-marvell_et6448m_52x-r0/et6448m/profile.ini + echo "ET6448M: Updating switch mac address ${MAC_ADDR}" +} + +main() +{ + fw_uboot_env_cfg + et6448m_profile + + python /etc/entropy.py & + /bin/sh /etc/inband_mgmt.sh +} + +main $@ diff --git a/platform/marvell-armhf/sonic-platform-et6448m/inband_mgmt.sh b/platform/marvell-armhf/sonic-platform-et6448m/inband_mgmt.sh new file mode 100644 index 000000000000..3d3d77abeb33 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-et6448m/inband_mgmt.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +#inband_mgmt + +inband_mgmt(){ + +# The intent of this sequence is to ensure 12c bus enumeration order by +# controlling the order in which the various i2c device drivers are +# loaded. Hence the drivers are unloaded and then reloaded in the prescribed +# order. +# NOTE: In the nokia platform the following sequence is performed by the Nokia +# platform service init script and thus should not be performed here + if [ ! -f /host/machine.conf ]; then + exit 0 + fi + grep ^onie_platform /host/machine.conf 2>/dev/null | grep nokia >/dev/null + if [ $? != 0 ]; then + rmmod i2c-dev + rmmod i2c_mux_gpio + rmmod i2c_mv64xxx + modprobe i2c_mv64xxx + modprobe i2c-dev + modprobe i2c_mux_gpio + sleep 60 + fi + while :; do + ip -br link show eth0 2> /dev/null + if [ $? -eq 0 ]; then + ip address show eth0 | grep -qw "inet" 2>/dev/null + if [ $? -ne 0 ]; then + ifconfig eth0 down + systemctl restart networking + fi + sleep 120 + else + sleep 3 + fi + done +} +(inband_mgmt > /dev/null)& diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/scripts/nokia-7215init.sh b/platform/marvell-armhf/sonic-platform-nokia/7215/scripts/nokia-7215init.sh new file mode 100755 index 000000000000..3f23afe1fce2 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/scripts/nokia-7215init.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# Platform init script for Nokia IXS 7215 + +# Load required kernel-mode drivers +load_kernel_drivers() { + # Remove modules loaded during Linux init + # FIX-ME: This will be removed in the future when Linux init no longer loads these + rmmod i2c_mux_gpio + rmmod i2c_dev + rmmod i2c_mv64xxx + + # Carefully control the load order here to ensure consistent i2c bus numbering + modprobe i2c_mv64xxx + modprobe i2c_dev + modprobe i2c_mux_gpio + modprobe eeprom +} + + +nokia_7215_profile() +{ + MAC_ADDR=$(sudo decode-syseeprom -m) + sed -i "s/switchMacAddress=.*/switchMacAddress=$MAC_ADDR/g" /usr/share/sonic/device/armhf-nokia_ixs7215_52x-r0/Nokia-7215/profile.ini + echo "Nokia-7215: Updating switch mac address ${MAC_ADDR}" +} + +# - Main entry + +# Install kernel drivers required for i2c bus access +load_kernel_drivers + +# LOGIC to enumerate SFP eeprom devices - send 0x50 to kernel i2c driver - initialize devices +# the mux may be enumerated at number 4 or 5 so we check for the mux and skip if needed + +# Get list of the mux channels +ismux_bus=$(i2cdetect -l|grep mux|cut -f1) + +# Enumerate the SFP eeprom device on each mux channel +for mux in ${ismux_bus} +do + echo optoe2 0x50 > /sys/class/i2c-adapter/${mux}/new_device +done + +# Enumerate system eeprom +echo 24c02 0x53 > /sys/class/i2c-adapter/i2c-0/new_device +sleep 2 +chmod 644 /sys/class/i2c-adapter/i2c-0/0-0053/eeprom + +# Enumerate fan eeprom devices +echo eeprom 0x55 > /sys/class/i2c-adapter/i2c-0/new_device +echo eeprom 0x56 > /sys/class/i2c-adapter/i2c-0/new_device + +# Enumerate PSU eeprom devices +echo eeprom 0x51 > /sys/class/i2c-adapter/i2c-1/new_device +echo eeprom 0x52 > /sys/class/i2c-adapter/i2c-1/new_device + +# Enable optical SFP Tx +i2cset -y -m 0x0f 0 0x41 0x5 0x00 + +# Ensure switch is programmed with chassis base MAC addr +nokia_7215_profile + +echo "Nokia-7215 - completed platform init script" +exit 0 diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/service/nokia-7215init.service b/platform/marvell-armhf/sonic-platform-nokia/7215/service/nokia-7215init.service new file mode 100644 index 000000000000..8b17dbc8edc0 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/service/nokia-7215init.service @@ -0,0 +1,14 @@ +[Unit] +Description=Nokia-7215 Platform Service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/nokia-7215init.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL +#StandardOutput=tty + +[Install] +WantedBy=multi-user.target diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/setup.py b/platform/marvell-armhf/sonic-platform-nokia/7215/setup.py new file mode 100755 index 000000000000..65f4853bec83 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize Nokia IXS 7215 platforms', + + packages=['sonic_platform','sonic_platform.test'], + package_dir={'sonic_platform': '7215/sonic_platform'}, +) + diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/__init__.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/__init__.py new file mode 100755 index 000000000000..39c712316dc6 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/__init__.py @@ -0,0 +1,4 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * + + diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/chassis.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/chassis.py new file mode 100755 index 000000000000..a01aca24b684 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/chassis.py @@ -0,0 +1,394 @@ +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import sys + import glob + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.eeprom import Eeprom + from sonic_platform.fan import Fan + from .fan_drawer import RealDrawer + from sonic_platform.psu import Psu + from sonic_platform.thermal import Thermal + from sonic_platform.component import Component + from sonic_py_common import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +smbus_present = 1 +try: + import smbus +except ImportError as e: + smbus_present = 0 + +MAX_SELECT_DELAY = 3600 +COPPER_PORT_START = 1 +COPPER_PORT_END = 48 +SFP_PORT_START = 49 +SFP_PORT_END = 52 +PORT_END = 52 + +# Device counts +MAX_7215_FAN_DRAWERS = 2 +MAX_7215_FANS_PER_DRAWER = 1 +MAX_7215_PSU = 2 +MAX_7215_THERMAL = 6 + +# Temp - disable these to help with early debug +MAX_7215_COMPONENT = 2 + +SYSLOG_IDENTIFIER = "chassis" +sonic_logger = logger.Logger(SYSLOG_IDENTIFIER) + + +class Chassis(ChassisBase): + """ + Nokia platform-specific Chassis class + Derived from Dell S6000 platform. + customized for the 7215 platform. + """ + + def __init__(self): + ChassisBase.__init__(self) + self.system_led_supported_color = ['off', 'amber', 'green', 'amber_blink', 'green_blink'] + # Port numbers for SFP List Initialization + self.COPPER_PORT_START = COPPER_PORT_START + self.COPPER_PORT_END = COPPER_PORT_END + self.SFP_PORT_START = SFP_PORT_START + self.SFP_PORT_END = SFP_PORT_END + self.PORT_END = PORT_END + + # for non-sfp ports create dummy objects for copper / non-sfp ports + for index in range(self.COPPER_PORT_START, self.COPPER_PORT_END+1): + sfp_node = Sfp(index, 'COPPER', 'N/A', 'N/A') + self._sfp_list.append(sfp_node) + + # Verify optoe2 driver SFP eeprom devices were enumerated and exist + # then create the sfp nodes + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + mux_dev = sorted(glob.glob("/sys/class/i2c-adapter/i2c-0/i2c-[0-9]")) + y = 0 + for index in range(self.SFP_PORT_START, self.SFP_PORT_END+1): + mux_dev_num = mux_dev[y] + port_i2c_map = mux_dev_num[-1] + y = y + 1 + port_eeprom_path = eeprom_path.format(port_i2c_map) + if not os.path.exists(port_eeprom_path): + sonic_logger.log_info("path %s didnt exist" % port_eeprom_path) + sfp_node = Sfp(index, 'SFP', port_eeprom_path, port_i2c_map) + self._sfp_list.append(sfp_node) + self.sfp_event_initialized = False + + # Instantiate system eeprom object + self._eeprom = Eeprom() + + # Construct lists fans, power supplies, thermals & components + drawer_num = MAX_7215_FAN_DRAWERS + fan_num_per_drawer = MAX_7215_FANS_PER_DRAWER + drawer_ctor = RealDrawer + fan_index = 0 + for drawer_index in range(drawer_num): + drawer = drawer_ctor(drawer_index) + self._fan_drawer_list.append(drawer) + for index in range(fan_num_per_drawer): + fan = Fan(fan_index, drawer) + fan_index += 1 + drawer._fan_list.append(fan) + self._fan_list.append(fan) + + for i in range(MAX_7215_PSU): + psu = Psu(i) + self._psu_list.append(psu) + + for i in range(MAX_7215_THERMAL): + thermal = Thermal(i) + self._thermal_list.append(thermal) + + for i in range(MAX_7215_COMPONENT): + component = Component(i) + self._component_list.append(component) + + 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 physical SFP ports in a + chassis starting from 1. + + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + + try: + # The index will start from 1 + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + return sfp + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_service_tag(self): + """ + Retrieves the Service Tag of the chassis + Returns: + string: Service Tag of chassis + """ + return self._eeprom.service_tag_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr() + + def get_serial(self): + """ + Retrieves the hardware serial number for the chassis + + Returns: + A string containing the hardware serial number for this + chassis. + """ + return self._eeprom.serial_number_str() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the + chassis + + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their + corresponding values. + """ + return self._eeprom.system_eeprom_info() + + def get_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. + """ + # The ixs7215 CPLD does not have a hardware reboot cause register so + # the hardware portion of reboot cause can't be implemented + + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + # Initialize SFP event first + if not self.sfp_event_initialized: + from sonic_platform.sfp_event import sfp_event + self.sfp_event = sfp_event() + self.sfp_event.initialize() + self.MAX_SELECT_EVENT_RETURNED = self.PORT_END + self.sfp_event_initialized = True + + wait_for_ever = (timeout == 0) + port_dict = {} + if wait_for_ever: + # xrcvd will call this monitor loop in the "SYSTEM_READY" state + timeout = MAX_SELECT_DELAY + while True: + status = self.sfp_event.check_sfp_status(port_dict, timeout) + if not port_dict == {}: + break + else: + # At boot up and in "INIT" state call from xrcvd will have timeout + # value return true without change after timeout and will + # transition to "SYSTEM_READY" + status = self.sfp_event.check_sfp_status(port_dict, timeout) + + if status: + return True, {'sfp': port_dict} + else: + return True, {'sfp': {}} + + def get_thermal_manager(self): + from .thermal_manager import ThermalManager + return ThermalManager + + def set_status_led(self, color): + """ + Sets the state of the system LED + + Args: + color: A string representing the color with which to set the + system LED + + Returns: + bool: True if system LED state is set successfully, False if not + """ + if color not in self.system_led_supported_color: + return False + + if (color == 'off'): + value = 0x00 + elif (color == 'amber'): + value = 0x01 + elif (color == 'green'): + value = 0x02 + elif (color == 'amber_blink'): + value = 0x03 + elif (color == 'green_blink'): + value = 0x04 + else: + return False + + # Write sys led + if smbus_present == 0: + sonic_logger.log_warning("PMON LED SET -> smbus present = 0") + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICEREG = 0x7 + bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, value) + sonic_logger.log_info(" System LED set O.K. ") + return True + + return False + + def get_status_led(self): + """ + Gets the state of the system LED + + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + # Read sys led + if smbus_present == 0: + sonic_logger.log_warning("PMON LED GET -> smbus present = 0") + return False + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0x7 + value = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + + if value == 0x00: + color = 'off' + elif value == 0x01: + color = 'amber' + elif value == 0x02: + color = 'green' + elif value == 0x03: + color = 'amber_blink' + elif value == 0x04: + color = 'green_blink' + else: + return False + + return color + + def get_watchdog(self): + """ + Retrieves hardware watchdog device on this chassis + + Returns: + An object derived from WatchdogBase representing the hardware + watchdog device + + Note: + We overload this method to ensure that watchdog is only initialized + when it is referenced. Currently, only one daemon can open the + watchdog. To initialize watchdog in the constructor causes multiple + daemon try opening watchdog when loading and constructing a chassis + object and fail. By doing so we can eliminate that risk. + """ + try: + if self._watchdog is None: + from sonic_platform.watchdog import WatchdogImplBase + watchdog_device_path = "/dev/watchdog0" + self._watchdog = WatchdogImplBase(watchdog_device_path) + except Exception as e: + sonic_logger.log_warning(" Fail to load watchdog {}".format(repr(e))) + + return self._watchdog + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/component.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/component.py new file mode 100644 index 000000000000..1c219d7920a5 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/component.py @@ -0,0 +1,133 @@ +######################################################################## +# NOKIA IXS7215 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + import sys + import subprocess + import ntpath + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +smbus_present = 1 +try: + import smbus +except ImportError as e: + smbus_present = 0 + +if sys.version_info[0] < 3: + import commands as cmd +else: + import subprocess as cmd + + +class Component(ComponentBase): + """Nokia platform-specific Component class""" + + CHASSIS_COMPONENTS = [ + ["System-CPLD", "Used for managing SFPs, LEDs, PSUs and FANs "], + ["U-Boot", "Performs initialization during booting"], + ] + CPLD_UPDATE_COMMAND = 'cp /usr/sbin/vme /tmp; cp {} /tmp; cd /tmp; ./vme {};' + + def __init__(self, component_index): + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + except OSError: + result = None + + return result + + def _get_cpld_version(self, cpld_number): + + if smbus_present == 0: + cmdstatus, cpld_version = cmd.getstatusoutput('sudo i2cget -y 0 0x41 0x2') + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0x2 + cpld_version = str(bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)) + + return str(int(cpld_version, 16)) + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + if self.index == 0: + return self._get_cpld_version(self.index) + + if self.index == 1: + cmdstatus, uboot_version = cmd.getstatusoutput('grep --null-data U-Boot /dev/mtd0ro|head -1 | cut -d" " -f2-4') + return uboot_version + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + image_name = ntpath.basename(image_path) + print(" ixs7215 - install cpld {}".format(image_name)) + + # check whether the image file exists + if not os.path.isfile(image_path): + print("ERROR: the cpld image {} doesn't exist ".format(image_path)) + return False + + cmdline = self.CPLD_UPDATE_COMMAND.format(image_path, image_name) + + 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 + diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/eeprom.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/eeprom.py new file mode 100644 index 000000000000..d0e3e00fffc2 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/eeprom.py @@ -0,0 +1,274 @@ +######################################################################## +# Nokia IXS7215 +# +# Module contains platform specific implementation of SONiC Platform +# Base API and provides the EEPROMs' information. +# +# The different EEPROMs available are as follows: +# - System EEPROM : Contains Serial number, Service tag, Base MA +# address, etc. in ONIE TlvInfo EEPROM format. +# - PSU EEPROM : Contains Model name and Part number. +# - Fan EEPROM : Contains Part number, Serial number, Manufacture Date, +# and Service Tag. +######################################################################## + + +try: + from sonic_platform_base.sonic_eeprom.eeprom_base import EepromDecoder + from sonic_platform_base.sonic_eeprom.eeprom_tlvinfo import TlvInfoDecoder +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +# PSU eeprom fields in format required by EepromDecoder +psu_eeprom_format = [ + ('Model', 's', 15), ('burn', 'x', 1), + ('Part Number', 's', 14), ('burn', 'x', 40), + ('Serial Number', 's', 11) + ] + + +class Eeprom(TlvInfoDecoder): + """Nokia platform-specific EEPROM class""" + + I2C_DIR = "/sys/class/i2c-adapter/" + + def __init__(self, is_psu=False, psu_index=0, is_fan=False, fan_index=0): + self.is_psu_eeprom = is_psu + self.is_fan_eeprom = is_fan + self.is_sys_eeprom = not (is_psu | is_fan) + + if self.is_sys_eeprom: + self.start_offset = 0 + self.eeprom_path = self.I2C_DIR + "i2c-0/0-0053/eeprom" + + # System EEPROM is in ONIE TlvInfo EEPROM format + super(Eeprom, self).__init__(self.eeprom_path, + self.start_offset, '', True) + self._load_system_eeprom() + else: + if self.is_psu_eeprom: + self.index = psu_index + self.start_offset = 18 + self.eeprom_path = self.I2C_DIR \ + + "i2c-1/1-005{}/eeprom".format(self.index) + self.format = psu_eeprom_format + + # Decode device eeprom as per specified format + EepromDecoder.__init__(self, self.eeprom_path, self.format, + self.start_offset, '', True) + else: + self.index = fan_index + self.start_offset = 0 + self.eeprom_path = self.I2C_DIR \ + + "i2c-0/0-005{}/eeprom".format(self.index + 4) + + # Fan EEPROM is in ONIE TlvInfo EEPROM format + super(Eeprom, self).__init__(self.eeprom_path, + self.start_offset, '', True) + + self._load_device_eeprom() + + def _load_system_eeprom(self): + """ + Reads the system EEPROM and retrieves the values corresponding + to the codes defined as per ONIE TlvInfo EEPROM format and fills + them in a dictionary. + """ + try: + # Read System EEPROM as per ONIE TlvInfo EEPROM format. + self.eeprom_data = self.read_eeprom() + except Exception as e: + self.base_mac = 'NA' + self.serial_number = 'NA' + self.part_number = 'NA' + self.model_str = 'NA' + self.service_tag = 'NA' + self.eeprom_tlv_dict = dict() + else: + eeprom = self.eeprom_data + if not self.is_valid_tlvinfo_header(eeprom): + self.base_mac = 'NA' + self.serial_number = 'NA' + self.part_number = 'NA' + self.model_str = 'NA' + self.service_tag = 'NA' + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + # Construct dictionary of eeprom TLV entries + self.eeprom_tlv_dict = dict() + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + self.base_mac = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_MAC_BASE), 'NA') + self.serial_number = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_SERIAL_NUMBER), 'NA') + self.part_number = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_PART_NUMBER), 'NA') + self.model_str = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_PRODUCT_NAME), 'NA') + self.service_tag = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_SERVICE_TAG), 'NA') + + def _load_device_eeprom(self): + """ + Reads the Fan/PSU EEPROM and interprets as per the specified format + """ + self.serial_number = 'NA' + self.part_number = 'NA' + self.model_str = 'NA' + self.service_tag = 'NA' + self.mfg_date = 'NA' + + # PSU device eeproms use proprietary format + if self.is_psu_eeprom: + try: + # Read Fan/PSU EEPROM as per the specified format. + self.eeprom_data = EepromDecoder.read_eeprom(self) + except Exception as e: + return + + # Bail out if PSU eeprom unavailable + if self.eeprom_data[0] == 255: + return + + (valid, data) = self._get_eeprom_field("Model") + if valid: + self.model_str = data.decode() + + (valid, data) = self._get_eeprom_field("Part Number") + if valid: + self.part_number = data.decode() + + # Early PSU device eeproms were not programmed with serial # + try: + (valid, data) = self._get_eeprom_field("Serial Number") + if valid: + self.serial_number = data.decode() + except Exception as e: + return + + # Fan device eeproms use ONIE TLV format + else: + try: + # Read Fan EEPROM as per ONIE TlvInfo EEPROM format. + self.eeprom_data = self.read_eeprom() + except Exception as e: + return + + eeprom = self.eeprom_data + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + # Construct dictionary of eeprom TLV entries + self.eeprom_tlv_dict = dict() + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % (tlv[0]) + + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + self.serial_number = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_SERIAL_NUMBER), 'NA') + self.part_number = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_PART_NUMBER), 'NA') + self.model_str = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_PRODUCT_NAME), 'NA') + self.service_tag = self.eeprom_tlv_dict.get( + "0x%X" % (self._TLV_CODE_SERVICE_TAG), 'NA') + + def _get_eeprom_field(self, field_name, decode=False): + """ + For a field name specified in the EEPROM format, returns the + presence of the field and the value for the same. + """ + field_start = 0 + for field in self.format: + field_end = field_start + field[2] + if field[0] == field_name: + if decode: + return (True, self.eeprom_data[field_start:field_end].decode('ascii')) + else: + return (True, self.eeprom_data[field_start:field_end]) + field_start = field_end + + return (False, None) + + def serial_number_str(self): + """ + Returns the serial number. + """ + return self.serial_number + + def part_number_str(self): + """ + Returns the part number. + """ + return self.part_number + + def airflow_fan_type(self): + """ + Returns the airflow fan type. + """ + if self.is_psu_eeprom: + return int(self.psu_type.encode('hex'), 16) + else: + return int(self.fan_type.encode('hex'), 16) + + def modelstr(self): + """ + Returns the Model name. + """ + return self.model_str + + def base_mac_addr(self): + """ + Returns the base MAC address found in the system EEPROM. + """ + return self.base_mac + + def service_tag_str(self): + """ + Returns the servicetag number. + """ + return self.service_tag + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan.py new file mode 100644 index 000000000000..14c00c763dde --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan.py @@ -0,0 +1,388 @@ +######################################################################## +# Nokia IXS7215 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fans' information which are available in the platform +# +######################################################################## + + +try: + import os + import time + from sonic_platform_base.fan_base import FanBase + from sonic_platform.eeprom import Eeprom + from sonic_py_common import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +smbus_present = 1 +try: + import smbus +except ImportError as e: + smbus_present = 0 + +MAX_IXS7215_FAN_SPEED = 19000 +WORKING_IXS7215_FAN_SPEED = 960 + +sonic_logger = logger.Logger('fan') + + +class Fan(FanBase): + """Nokia platform-specific Fan class""" + + def __init__(self, fan_index, fan_drawer, psu_fan=False, dependency=None): + self.is_psu_fan = psu_fan + ADT7473_DIR = "/sys/bus/i2c/devices/0-002e/" + + if not self.is_psu_fan: + # Fan is 1-based in Nokia platforms + self.index = fan_index + 1 + self.fan_drawer = fan_drawer + self.set_fan_speed_reg = ADT7473_DIR+"pwm{}".format(self.index) + self.get_fan_speed_reg = ADT7473_DIR+"fan{}_input".format(self.index) + self.max_fan_speed = MAX_IXS7215_FAN_SPEED + self.supported_led_color = ['off', 'green', 'red'] + + # Fan eeprom + self.eeprom = Eeprom(is_fan=True, fan_index=self.index) + else: + # this is a PSU Fan + self.index = fan_index + self.dependency = dependency + + def _get_i2c_register(self, reg_file): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(reg_file)): + return rv + + try: + with open(reg_file, 'r') as fd: + rv = fd.read() + except Exception as e: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _set_i2c_register(self, reg_file, value): + # On successful write, the value read will be written on + # reg_name and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(reg_file)): + return rv + + try: + with open(reg_file, 'w') as fd: + rv = fd.write(str(value)) + except Exception as e: + rv = 'ERR' + + # Ensure that the write operation has succeeded + if (int(self._get_i2c_register(reg_file)) != value ): + time.sleep(3) + if (int(self._get_i2c_register(reg_file)) != value ): + rv = 'ERR' + + return rv + + def get_name(self): + """ + Retrieves the name of the Fan + + Returns: + string: The name of the Fan + """ + if not self.is_psu_fan: + return "Fan{}".format(self.index) + else: + return "PSU{} Fan".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Fan Unit + + Returns: + bool: True if Fan is present, False if not + """ + if smbus_present == 0: + sonic_logger.log_info("PMON fan-smbus ERROR - presence ") + return False + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0xb + fanstatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + + if self.index == 1: + fanstatus = fanstatus & 1 + if fanstatus == 1: + return False + if self.index == 2: + fanstatus = fanstatus & 2 + if fanstatus == 2: + return False + return True + + def get_model(self): + """ + Retrieves the model number of the Fan + + Returns: + string: Model number of Fan. Use part number for this. + """ + return self.eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the Fan + + Returns: + string: Serial number of Fan + """ + return self.eeprom.serial_number_str() + + def get_part_number(self): + """ + Retrieves the part number of the Fan + + Returns: + string: Part number of Fan + """ + return self.eeprom.part_number_str() + + def get_service_tag(self): + """ + Retrieves the service tag of the Fan + + Returns: + string: Service Tag of Fan + """ + return self.eeprom.service_tag_str() + + def get_status(self): + """ + Retrieves the operational status of the Fan + + Returns: + bool: True if Fan is operating properly, False if not + """ + status = False + + fan_speed = self._get_i2c_register(self.get_fan_speed_reg) + if (fan_speed != 'ERR'): + if (int(fan_speed) > WORKING_IXS7215_FAN_SPEED): + status = True + + return status + + def get_direction(self): + """ + Retrieves the fan airflow direction + Possible fan directions (relative to port-side of device) + Returns: + A string, either FAN_DIRECTION_INTAKE or + FAN_DIRECTION_EXHAUST depending on fan direction + """ + + return 'intake' + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device + Returns: + integer: The 1-based relative physical position in parent device + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + + def get_speed(self): + """ + Retrieves the speed of a Front FAN in the tray in revolutions per + minute defined by 1-based index + :param index: An integer, 1-based index of the FAN to query speed + :return: integer, denoting front FAN speed + """ + speed = 0 + + fan_speed = self._get_i2c_register(self.get_fan_speed_reg) + if (fan_speed != 'ERR'): + speed_in_rpm = int(fan_speed) + else: + speed_in_rpm = 0 + + speed = 100*speed_in_rpm//MAX_IXS7215_FAN_SPEED + if speed > 100: + speed = 100 + + return speed + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + + Returns: + An integer, the percentage of variance from target speed + which is considered tolerable + """ + if self.get_presence(): + # The tolerance value is fixed as 25% for this platform + tolerance = 25 + else: + tolerance = 0 + + return tolerance + + def set_speed(self, speed): + """ + Set fan speed to expected value + Args: + speed: An integer, the percentage of full fan speed to set + fan to, in the range 0 (off) to 100 (full speed) + Returns: + bool: True if set success, False if fail. + """ + if self.is_psu_fan: + return False + + # Set current fan duty cycle + # - 0x00 : fan off + # - 0x40 : 25% duty cycle + # - 0x80 : 50% duty cycle (default) + # - 0xff : 100% duty cycle (full speed) + if speed in range(0, 6): + fandutycycle = 0x00 + elif speed in range(6, 41): + fandutycycle = 64 + elif speed in range(41, 76): + fandutycycle = 128 + elif speed in range(76, 101): + fandutycycle = 255 + else: + return False + + rv = self._set_i2c_register(self.set_fan_speed_reg, fandutycycle) + if (rv != 'ERR'): + return True + else: + return False + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if set success, False if fail. + + off , red and green are the only settings 7215 fans + """ + + if self.is_psu_fan or (color not in self.supported_led_color): + return False + if (color == self.STATUS_LED_COLOR_AMBER): + return False + if (color == self.STATUS_LED_COLOR_RED): + value = 0x02 + elif (color == self.STATUS_LED_COLOR_GREEN): + value = 0x01 + elif (color == self.STATUS_LED_COLOR_OFF): + value = 0x00 + else: + return False + + if smbus_present == 0: + return False + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICEREG = 0x8 + original = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG) + if (self.index == 1): + new = value << 4 + ledstatus = original & 0xcf + ledstatus = ledstatus | new + elif self.index == 2: + new = value << 6 + ledstatus = original & 0x3f + ledstatus = ledstatus | new + else: + return False + + bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, ledstatus) + + return True + + def get_status_led(self): + """ + Gets the state of the fan status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + + if self.is_psu_fan: + return False + + if smbus_present == 0: + return False + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0x8 + ledstatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + + if self.index == 1: + ledstatus = (ledstatus & 0x30) + ledstatus = ledstatus >> 4 + elif self.index == 2: + ledstatus = (ledstatus & 0xC0) + ledstatus = ledstatus >> 6 + if ledstatus == 0x02: + return self.STATUS_LED_COLOR_RED + elif ledstatus == 0x1: + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + + 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) + """ + speed = 0 + + fan_duty = self._get_i2c_register(self.set_fan_speed_reg) + if (fan_duty != 'ERR'): + dutyspeed = int(fan_duty) + if dutyspeed == 0: + speed = 0 + elif dutyspeed == 64: + speed = 25 + elif dutyspeed == 128: + speed = 50 + elif dutyspeed == 255: + speed = 100 + + return speed + + + + diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..35b663cbb786 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py @@ -0,0 +1,86 @@ +############################################################################# +# Nokia +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan Drawer status which is available in the platform +# +############################################################################# + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_py_common import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +sonic_logger = logger.Logger('fan_drawer') + +class NokiaFanDrawer(FanDrawerBase): + def __init__(self, index): + super(NokiaFanDrawer, self).__init__() + self._index = index + 1 + self._led = None + + def get_index(self): + return self._index + + def get_presence(self): + return self._fan_list[0].get_presence() + + def get_model(self): + """ + Retrieves the model number of the Fan Drawer + Returns: + string: Part number of Fan Drawer + """ + return self._fan_list[0].get_model() + + def get_serial(self): + """ + Retrieves the serial number of the Fan Drawer + Returns: + string: Serial number of Fan + """ + return self._fan_list[0].get_serial() + + def get_status(self): + """ + Retrieves the operational status of the Fan Drawer + Returns: + bool: True if Fan is operating properly, False if not + """ + return self._fan_list[0].get_status() + + def get_direction(self): + return 'intake' + + def set_status_led(self, color): + return True + + def get_status_led(self, color): + return self._fan_list[0].get_status_led() + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device + Returns: + integer: The 1-based relative physical position in parent device + """ + return self._index + + +# For Nokia platforms with fan drawer(s) +class RealDrawer(NokiaFanDrawer): + def __init__(self, index): + super(RealDrawer, self).__init__(index) + self._name = 'drawer{}'.format(self._index) + + def get_name(self): + return self._name diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/platform.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/platform.py new file mode 100755 index 000000000000..7a3046bc7391 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/platform.py @@ -0,0 +1,22 @@ +############################################################################# +# +# 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): + """ + Nokia platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/psu.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/psu.py new file mode 100644 index 000000000000..9de9ebec3699 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/psu.py @@ -0,0 +1,235 @@ +######################################################################## +# Nokia IXS7215 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + +try: + import sys + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common import logger + from sonic_platform.eeprom import Eeprom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +if sys.version_info[0] < 3: + import commands as cmd +else: + import subprocess as cmd + +smbus_present = 1 +try: + import smbus +except ImportError as e: + smbus_present = 0 + +sonic_logger = logger.Logger('psu') + +class Psu(PsuBase): + """Nokia platform-specific PSU class for 7215 """ + + def __init__(self, psu_index): + # PSU is 1-based in Nokia platforms + self.index = psu_index + 1 + self._fan_list = [] + + # PSU eeprom + self.eeprom = Eeprom(is_psu=True, psu_index=self.index) + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + + if smbus_present == 0: # if called from psuutil outside of pmon + cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cget -y 0 0x41 0xa') + psustatus = int(psustatus, 16) + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0xa + psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + + if self.index == 1: + psustatus = psustatus & 1 + if psustatus == 1: + return False + if self.index == 2: + psustatus = psustatus & 2 + if psustatus == 2: + return False + + return True + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + return self.eeprom.modelstr() + + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + return self.eeprom.serial_number_str() + + + def get_part_number(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + return self.eeprom.part_number_str() + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + + if smbus_present == 0: + cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cget -y 0 0x41 0xa') + psustatus = int(psustatus, 16) + sonic_logger.log_warning("PMON psu-smbus - presence = 0 ") + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0xa + psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + + if self.index == 1: + psustatus = psustatus & 4 + if psustatus == 4: + return True + if self.index == 2: + psustatus = psustatus & 8 + if psustatus == 8: + return True + + return False + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + if smbus_present == 0: + cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cget -y 0 0x41 0xa') + psustatus = int(psustatus, 16) + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0xa + psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + + if self.index == 1: + psustatus = psustatus & 4 + if psustatus == 4: + psu_voltage = 12.0 + return psu_voltage + if self.index == 2: + psustatus = psustatus & 8 + if psustatus == 8: + psu_voltage = 12.0 + return psu_voltage + + psu_voltage = 0.0 + return psu_voltage + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device + Returns: + integer: The 1-based relative physical position in parent device + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + + if smbus_present == 0: + cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cget -y 0 0x41 0xa') + psustatus = int(psustatus, 16) + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0xa + psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + + if self.index == 1: + psustatus = psustatus & 4 + if psustatus == 4: + return True + if self.index == 2: + psustatus = psustatus & 8 + if psustatus == 8: + return True + + return False + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + Args: + color: A string representing the color with which to set the + PSU status LED + Returns: + bool: True if status LED state is set successfully, False if + not + """ + # The firmware running in the PSU controls the LED + # and the PSU LED state cannot be changed from CPU. + return False diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/sfp.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/sfp.py new file mode 100644 index 000000000000..57fcde16149d --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/sfp.py @@ -0,0 +1,948 @@ +############################################################################# +# Nokia +# +############################################################################# + +import os +import sys +import time + +try: + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from sonic_py_common import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +if sys.version_info[0] < 3: + import commands as cmd +else: + import subprocess as cmd + +smbus_present = 1 + +try: + import smbus +except ImportError as e: + smbus_present = 0 + + +INFO_OFFSET = 128 +DOM_OFFSET = 0 + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 + +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 + +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 + +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 +XCVR_INTERFACE_DATA_START = 0 +XCVR_INTERFACE_DATA_SIZE = 92 + +SFP_DOM_BULK_DATA_START = 96 +SFP_DOM_BULK_DATA_SIZE = 10 + +SFP_MODULE_ADDRA2_OFFSET = 256 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_CHANNL_STATUS_OFFSET = 110 +SFP_CHANNL_STATUS_WIDTH = 1 + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +COPPER_TYPE = "COPPER" +SFP_TYPE = "SFP" + +# SFP PORT numbers +SFP_PORT_START = 49 +SFP_PORT_END = 52 + +SYSLOG_IDENTIFIER = "xcvrd" +sonic_logger = logger.Logger(SYSLOG_IDENTIFIER) + + +class Sfp(SfpBase): + """Platform-specific Sfp class""" + """ + Nokia platform-specific Sfp class + """ + + # Paths + PLATFORM_ROOT_PATH = "/usr/share/sonic/device" + PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" + HOST_CHK_CMD = "docker > /dev/null 2>&1" + + PLATFORM = "armhf-nokia_ixs7215_52x-r0" + HWSKU = "Nokia-7215" + + port_to_i2c_mapping = 0 + + def __init__(self, index, sfp_type, eeprom_path, port_i2c_map): + SfpBase.__init__(self) + + self.index = index + self.port_num = index + self.sfp_type = sfp_type + self.eeprom_path = eeprom_path + self.port_to_i2c_mapping = port_i2c_map + self.port_name = sfp_type + str(index) + self.port_to_eeprom_mapping = {} + + self.port_to_eeprom_mapping[index] = eeprom_path + + self.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', + 'model', 'connector', 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', 'cable_length', + 'nominal_bit_rate', 'specification_compliance', + 'vendor_date', 'vendor_oui'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', + 'tx_disable', 'tx_disable_channel', 'temperature', + 'voltage', 'rx1power', 'rx2power', 'rx3power', + 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', + 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', + 'templowwarning', 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', + 'rxpowerhighwarning', 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', + 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning'] + + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + + def __convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + def __is_host(self): + return os.system(self.HOST_CHK_CMD) == 0 + + def __get_path_to_port_config_file(self): + platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) + hwsku_path = "/".join([platform_path, self.HWSKU] + ) if self.__is_host() else self.PMON_HWSKU_PATH + return "/".join([hwsku_path, "port_config.ini"]) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] + + try: + sysfsfile_eeprom = open( + sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) + except Exception as e: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + return eeprom_raw + + def _dom_capability_detect(self): + if self.sfp_type == "SFP": + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = ( + int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + application_advertisement |1*255VCHAR |supported applications advertisement + ======================================================================== + """ + + if self.sfp_type == COPPER_TYPE: + return None + + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + + if not self.get_presence(): + return transceiver_info_dict + + if self.sfp_type == SFP_TYPE: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + offset + XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE) + if sfp_interface_bulk_raw is None: + return None + + start = XCVR_INTFACE_BULK_OFFSET - XCVR_INTERFACE_DATA_START + end = start + interface_info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_NAME_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_NAME_WIDTH + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_PN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_PN_WIDTH + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_HW_REV_OFFSET - XCVR_INTERFACE_DATA_START + end = start + vendor_rev_width + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_SN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_SN_WIDTH + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_OUI_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_OUI_WIDTH + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( + sfp_interface_bulk_raw[start: end], 0) + + start = XCVR_VENDOR_DATE_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_DATE_WIDTH + sfp_vendor_date_data = sfpi_obj.parse_vendor_date( + sfp_interface_bulk_raw[start: end], 0) + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ + 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str( + sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str( + compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + transceiver_info_dict['application_advertisement'] = 'N/A' + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + + transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + + if self.sfp_type == COPPER_TYPE: + return transceiver_dom_info_dict + + if self.sfp_type == SFP_TYPE: + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + dom_data_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_DOM_BULK_DATA_START), SFP_DOM_BULK_DATA_SIZE) + + start = SFP_TEMPE_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature( + dom_data_raw[start: end], 0) + + start = SFP_VOLT_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage( + dom_data_raw[start: end], 0) + + start = SFP_CHANNL_MON_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_CHANNL_MON_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( + dom_data_raw[start: end], 0) + + transceiver_dom_info_dict['temperature'] = self.__convert_string_to_num( + dom_temperature_data['data']['Temperature']['value']) + transceiver_dom_info_dict['voltage'] = self.__convert_string_to_num( + dom_voltage_data['data']['Vcc']['value']) + transceiver_dom_info_dict['rx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['RXPower']['value']) + transceiver_dom_info_dict['tx1bias'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXBias']['value']) + transceiver_dom_info_dict['tx1power'] = self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXPower']['value']) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + transceiver_dom_threshold_info_dict = dict.fromkeys( + self.threshold_dict_keys, 'N/A') + + if self.sfp_type == COPPER_TYPE: + return transceiver_dom_threshold_info_dict + + if self.sfp_type == SFP_TYPE: + + offset = SFP_MODULE_ADDRA2_OFFSET + + self._dom_capability_detect() + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = sff8472Dom(None, self.calibration) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((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 + + # 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 + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + self._dom_capability_detect() + if not self.dom_supported: + return False + if self.sfp_type == COPPER_TYPE: + return False + + if self.sfp_type == SFP_TYPE: + offset = 0 + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + + if dom_channel_monitor_raw is not None: + return False + else: + return True + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + """ + if self.sfp_type == COPPER_TYPE: + return None + if not self.dom_supported: + return None + rx_los_list = [] + + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x02 != 0) + else: + return None + + return rx_los_list + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + if self.sfp_type == COPPER_TYPE: + return None + if not self.dom_supported: + return None + tx_fault_list = [] + + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + else: + return None + return tx_fault_list + + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + + if self.sfp_type == COPPER_TYPE: + return None + if not self.dom_supported: + return None + + tx_disable_list = [] + offset = 256 + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0xC0 != 0) + else: + return None + + return tx_disable_list + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + if self.sfp_type == COPPER_TYPE: + return False + if self.sfp_type == SFP_TYPE: + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + if self.sfp_type == COPPER_TYPE: + return False + if self.sfp_type == SFP_TYPE: + return False + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + if self.sfp_type == COPPER_TYPE: + return None + + transceiver_bulk_status = self.get_transceiver_bulk_status() + return transceiver_bulk_status.get("temperature", "N/A") + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + Returns: + An integer number of supply voltage in mV + """ + if self.sfp_type == COPPER_TYPE: + return None + + transceiver_bulk_status = self.get_transceiver_bulk_status() + return transceiver_bulk_status.get("voltage", "N/A") + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + Returns: + + """ + if self.sfp_type == COPPER_TYPE: + return None + + tx_bias_list = [] + transceiver_bulk_status = self.get_transceiver_bulk_status() + tx_bias_list.append(transceiver_bulk_status.get("tx1bias", "N/A")) + + return tx_bias_list + + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + rx_power_list = [] + if self.sfp_type == COPPER_TYPE: + return None + + if self.sfp_type == SFP_TYPE: + + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + self._dom_capability_detect() + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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) + rx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['RXPower']['value'])) + else: + return None + else: + return None + + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + tx_power_list = [] + + if self.sfp_type == COPPER_TYPE: + return None + + if self.sfp_type == SFP_TYPE: + + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + self._dom_capability_detect() + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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) + tx_power_list.append(self.__convert_string_to_num( + dom_channel_monitor_data['data']['TXPower']['value'])) + else: + return None + else: + return None + return tx_power_list + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + if self.sfp_type == COPPER_TYPE: + return False + + path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/sfp_port_reset" + port_ps = path.format(self.port_to_i2c_mapping) + + 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 tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + + return NotImplementedError + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + Returns: + A boolean, True if successful, False if not + """ + + return NotImplementedError + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + if self.sfp_type == COPPER_TYPE: + return False + if self.sfp_type == SFP_TYPE: + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + + return NotImplementedError + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence + Returns: + bool: True if is present, False if not + """ + if self.sfp_type == COPPER_TYPE: + return False + + if smbus_present == 0: # if called from sfputil outside of pmon + cmdstatus, sfpstatus = cmd.getstatusoutput('sudo i2cget -y 0 0x41 0x3') + sfpstatus = int(sfpstatus, 16) + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0x3 + sfpstatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + + pos = [1, 2, 4, 8] + bit_pos = pos[self.index-SFP_PORT_START] + sfpstatus = sfpstatus & (bit_pos) + + if sfpstatus == 0: + return True + + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("model", "N/A") + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + return transceiver_dom_info_dict.get("serial", "N/A") + + 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() + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + + if self.sfp_type == "SFP": + return True + else: + return False + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device + Returns: + integer: The 1-based relative physical position in parent device + """ + return self.index diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/sfp_event.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/sfp_event.py new file mode 100644 index 000000000000..fd494ca674f5 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/sfp_event.py @@ -0,0 +1,117 @@ +''' +listen for the SFP change event and return to chassis. +''' +import sys +import time +from sonic_py_common import logger + +smbus_present = 1 + +try: + import smbus +except ImportError as e: + smbus_present = 0 + +if sys.version_info[0] < 3: + import commands as cmd +else: + import subprocess as cmd + +# system level event/error +EVENT_ON_ALL_SFP = '-1' +SYSTEM_NOT_READY = 'system_not_ready' +SYSTEM_READY = 'system_become_ready' +SYSTEM_FAIL = 'system_fail' + +# SFP PORT numbers +SFP_PORT_START = 49 +SFP_PORT_END = 52 + +SYSLOG_IDENTIFIER = "sfp_event" +sonic_logger = logger.Logger(SYSLOG_IDENTIFIER) + + +class sfp_event: + ''' Listen to plugin/plugout cable events ''' + + def __init__(self): + self.handle = None + + def initialize(self): + self.modprs_register = 0 + # Get Transceiver status + time.sleep(5) + self.modprs_register = self._get_transceiver_status() + sonic_logger.log_info("Initial SFP presence=%d" % self.modprs_register) + + def deinitialize(self): + if self.handle is None: + return + + def _get_transceiver_status(self): + if smbus_present == 0: + sonic_logger.log_info(" PMON - smbus ERROR - DEBUG sfp_event ") + cmdstatus, sfpstatus = cmd.getstatusoutput('sudo i2cget -y 0 0x41 0x3') + sfpstatus = int(sfpstatus, 16) + else: + bus = smbus.SMBus(0) + DEVICE_ADDRESS = 0x41 + DEVICE_REG = 0x3 + sfpstatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) + + sfpstatus = ~sfpstatus + sfpstatus = sfpstatus & 0xF + + return sfpstatus + + def check_sfp_status(self, port_change, timeout): + """ + check_sfp_status called from get_change_event, this will return correct + status of all 4 SFP ports if there is a change in any of them + """ + start_time = time.time() + port = SFP_PORT_START + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + return False, {} + end_time = start_time + timeout + + if (start_time > end_time): + return False, {} # Time wrap or possibly incorrect timeout + + while (timeout >= 0): + # Check for OIR events and return updated port_change + reg_value = self._get_transceiver_status() + if (reg_value != self.modprs_register): + changed_ports = (self.modprs_register ^ reg_value) + while (port >= SFP_PORT_START and port <= SFP_PORT_END): + # Mask off the bit corresponding to our port + mask = (1 << port-SFP_PORT_START) + if (changed_ports & mask): + # ModPrsL is active high + if reg_value & mask == 0: + port_change[port] = '0' + else: + port_change[port] = '1' + port += 1 + + # Update reg value + self.modprs_register = reg_value + return True, port_change + + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + return False, {} diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/README b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/README new file mode 100644 index 000000000000..3efc8fabce08 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/README @@ -0,0 +1 @@ +This directory contains unit tests of the Platform API 2.0 diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-chassis.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-chassis.py new file mode 100755 index 000000000000..53c047ca2329 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-chassis.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +try: + import sonic_platform.platform + import sonic_platform.chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +def main(): + print("-----------------") + print("Chassis Unit Test") + print("-----------------") + + chassis = sonic_platform.platform.Platform().get_chassis() + print(" Chassis name: {}".format(chassis.get_name())) + + print(" Chassis presence: {}".format(chassis.get_presence())) + + print(" Chassis model: {}".format(chassis.get_model())) + + print(" Chassis serial: {}".format(chassis.get_serial())) + + print(" Chassis status: {}".format(chassis.get_status())) + + print(" Chassis base_mac: {}".format(chassis.get_base_mac())) + + print(" Chassis reboot cause: {}\n".format(chassis.get_reboot_cause())) + + print(" Chassis watchdog: {}".format(chassis.get_watchdog())) + + print(" Chassis num_components: {}".format(chassis.get_num_components())) + + print(" Chassis all_components: {}\n".format(chassis.get_all_components())) + + print(" Chassis num_modules: {}".format(chassis.get_num_modules())) + + print(" Chassis all_modules: {}\n".format(chassis.get_all_modules())) + + print(" Chassis num_fans: {}".format(chassis.get_num_fans())) + + print(" Chassis all_fans: {}\n".format(chassis.get_all_fans())) + + print(" Chassis num_psus: {}".format(chassis.get_num_psus())) + + print(" Chassis all_psus: {}\n".format(chassis.get_all_psus())) + + print(" Chassis num_thermals: {}".format(chassis.get_num_thermals())) + + print(" Chassis all_thermals: {}\n".format(chassis.get_all_thermals())) + + print(" Chassis num_sfps: {}".format(chassis.get_num_sfps())) + + print(" Chassis all_sfps: {}\n".format(chassis.get_all_sfps())) + + print(" Chassis eeprom: {}".format(chassis.get_eeprom())) + + print(" Chassis system_eeprom_info: {}\n".format(chassis.get_system_eeprom_info())) + + print(" Chassis get_status_led start : {}\n".format(chassis.get_status_led())) + chassis.set_status_led('amber') + print(" Chassis get_status_led amber: {}\n".format(chassis.get_status_led())) + chassis.set_status_led('green') + print(" Chassis get_status_led green: {}\n".format(chassis.get_status_led())) + + return + + +if __name__ == '__main__': + main() diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-component.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-component.py new file mode 100755 index 000000000000..1116cc7b5857 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-component.py @@ -0,0 +1,22 @@ +#!/usr/bin/python + +from sonic_platform.chassis import Chassis + + +def main(): + print("---------------------------") + print("Chassis Component Unit Test") + print("---------------------------") + + chassis = Chassis() + + for component in chassis.get_all_components(): + print(" Name: {}".format(component.get_name())) + print(" Description: {}".format(component.get_description())) + print(" FW version: {}\n".format(component.get_firmware_version())) + + return + + +if __name__ == '__main__': + main() diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-eeprom.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-eeprom.py new file mode 100755 index 000000000000..40836611692b --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-eeprom.py @@ -0,0 +1,25 @@ +#!/usr/bin/python + +from sonic_platform.chassis import Chassis + + +def main(): + print("------------------------") + print("Chassis eeprom Unit Test") + print("------------------------") + + chassis = Chassis() + + eeprom = chassis.get_eeprom() + + print(" Model: {}, Service Tag: {}".format(eeprom.modelstr(), + eeprom.service_tag_str())) + print(" Part#: {}, Serial#: {}".format(eeprom.part_number_str(), + eeprom.serial_number_str())) + print(" Base MAC: {}".format(eeprom.base_mac_addr())) + + return + + +if __name__ == '__main__': + main() diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-fan.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-fan.py new file mode 100755 index 000000000000..9bbf4d864acb --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-fan.py @@ -0,0 +1,32 @@ +#!/usr/bin/python + +from sonic_platform.chassis import Chassis + + +def main(): + print("---------------------") + print("Chassis Fan Unit Test") + print("---------------------") + + chassis = Chassis() + + for fan in chassis.get_all_fans(): + if not fan.get_presence(): + print(" Name: {} not present".format(fan.get_name())) + else: + print(" Name:", fan.get_name()) + print(" Presence: {}, Status: {}, LED: {}".format(fan.get_presence(), + fan.get_status(), + fan.get_status_led())) + print(" Model: {}, Serial#: {}".format(fan.get_model(), + fan.get_serial())) + print(" Part#: {}, Service Tag: {}".format(fan.get_part_number(), + fan.get_service_tag())) + print(" Direction: {}, Speed: {}RPM, Target Speed: {}%\n".format(fan.get_direction(), + str(fan.get_speed()), + str(fan.get_target_speed()))) + return + + +if __name__ == '__main__': + main() diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-psu.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-psu.py new file mode 100755 index 000000000000..e3979b8c4175 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-psu.py @@ -0,0 +1,40 @@ +#!/usr/bin/python + +from sonic_platform.chassis import Chassis + + +def main(): + print("---------------------") + print("Chassis PSU Unit Test") + print("---------------------") + + chassis = Chassis() + + for psu in chassis.get_all_psus(): + if not psu.get_presence(): + print(" Name: {} not present".format(psu.get_name())) + else: + print(" Name:", psu.get_name()) + print(" Presence: {}, Status: {}, LED: {}".format(psu.get_presence(), + psu.get_status(), + psu.get_status_led())) + print(" Model: {}, Serial#: {}, Part#: {}".format(psu.get_model(), + psu.get_serial(), + psu.get_part_number())) + try: + current = psu.get_current() + except NotImplementedError: + current = "NA" + try: + power = psu.get_power() + except NotImplementedError: + power = "NA" + + print(" Voltage: {}, Current: {}, Power: {}\n".format(psu.get_voltage(), + current, + power)) + return + + +if __name__ == '__main__': + main() diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-sfp.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-sfp.py new file mode 100755 index 000000000000..4d283fa2eb03 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-sfp.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +try: + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +def main(): + print("---------------------") + print("Chassis SFP Unit Test") + print("---------------------") + + chassis = Chassis() + + PORT_START = 1 + PORT_END = 52 + + for physical_port in range(PORT_START, PORT_END+1): + print(" ") + print(" SFP transceiver tests PORT = ", physical_port) + name = chassis.get_sfp(physical_port).get_name() + print(" SFP transceiver tests NAME = ", name) + + presence = chassis.get_sfp(physical_port).get_presence() + print("TEST 1 - sfp presence [ True ] ", physical_port, presence) + + status = chassis.get_sfp(physical_port).get_reset_status() + print("TEST 2 - sfp reset status [ False ] ", physical_port, status) + + txdisable = chassis.get_sfp(physical_port).get_tx_disable() + print("TEST 3 - sfp tx_disable [ False ] ", physical_port, txdisable) + + rxlos = chassis.get_sfp(physical_port).get_rx_los() + print("TEST 4 - sfp status rxlos [ False ] ", physical_port, rxlos) + + txfault = chassis.get_sfp(physical_port).get_tx_fault() + print("TEST 5 - sfp status txfault [ False ] ", physical_port, txfault) + + lpmode = chassis.get_sfp(physical_port).get_lpmode() + print("TEST 6 - sfp enable lpmode [ False ] ", physical_port, lpmode) + + trans_info = chassis.get_sfp(physical_port).get_transceiver_info() + print("TEST 7 - sfp transceiver info for port:", physical_port, trans_info) + + trans_status = chassis.get_sfp(physical_port).get_transceiver_bulk_status() + print("TEST 8 - sfp bulk status for port:", physical_port, trans_status) + + threshold = chassis.get_sfp(physical_port).get_transceiver_threshold_info() + print("TEST 9 - sfp bulk status for port:", physical_port, threshold) + + return + + +if __name__ == '__main__': + main() diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-thermal.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-thermal.py new file mode 100755 index 000000000000..91ef75d8f9a7 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/test/test-thermal.py @@ -0,0 +1,50 @@ +#!/usr/bin/python + +from sonic_platform.chassis import Chassis + +def main(): + print("-------------------------") + print("Chassis Thermal Unit Test") + print("-------------------------") + + chassis = Chassis() + + for thermal in chassis.get_all_thermals(): + if not thermal.get_presence(): + print(" Name: {} not present".format(thermal.get_name())) + else: + print(" Name:", thermal.get_name()) + print(" Presence: {}, Status: {}".format(thermal.get_presence(), + thermal.get_status())) + print(" Model: {}, Serial#: {}".format(thermal.get_model(), + thermal.get_serial())) + print(" Temperature(C): {}".format(thermal.get_temperature())) + + try: + low_thresh = thermal.get_low_threshold() + except NotImplementedError: + low_thresh = "NA" + try: + high_thresh = thermal.get_high_threshold() + except NotImplementedError: + high_thresh = "NA" + + print(" Low Threshold(C): {}, High Threshold(C): {}".format(low_thresh, + high_thresh)) + + try: + crit_low_thresh = thermal.get_low_critical_threshold() + except NotImplementedError: + crit_low_thresh = "NA" + try: + crit_high_thresh = thermal.get_high_critical_threshold() + except NotImplementedError: + crit_high_thresh = "NA" + + print(" Crit Low Threshold(C): {}, Crit High Threshold(C): {}\n".format(crit_low_thresh, + crit_high_thresh)) + return + + +if __name__ == '__main__': + main() diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal.py new file mode 100644 index 000000000000..528a6e49d924 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal.py @@ -0,0 +1,243 @@ +######################################################################## +# Nokia IXS7215 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + import os + from sonic_platform_base.thermal_base import ThermalBase + from sonic_py_common import logger +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +sonic_logger = logger.Logger('thermal') + +class Thermal(ThermalBase): + """Nokia platform-specific Thermal class""" + + I2C_CLASS_DIR = "/sys/class/i2c-adapter/" + I2C_DEV_MAPPING = (['i2c-0/0-004a/hwmon/', 1], + ['i2c-0/0-004b/hwmon/', 1], + ['i2c-0/0-002e/', 1], + ['i2c-0/0-002e/', 2], + ['i2c-0/0-002e/', 3]) + + HWMON_CLASS_DIR = "/sys/class/hwmon/" + + THERMAL_NAME = ("PCB PHY", "PCB MAC", + "ADT7473-CPU", "ADT7473-LOC", "ADT7473-MAC", + "CPU Core") + + def __init__(self, thermal_index): + self.index = thermal_index + 1 + self.is_psu_thermal = False + self.dependency = None + self.thermal_high_threshold_file = None + # PCB temperature sensors + if self.index < 3: + i2c_path = self.I2C_CLASS_DIR + self.I2C_DEV_MAPPING[self.index - 1][0] + sensor_index = self.I2C_DEV_MAPPING[self.index - 1][1] + sensor_max_suffix = "max" + sensor_crit_suffix = None + hwmon_node = os.listdir(i2c_path)[0] + self.SENSOR_DIR = i2c_path + hwmon_node + '/' + + # ADT7473 temperature sensors + elif self.index < 6: + i2c_path = self.I2C_CLASS_DIR + self.I2C_DEV_MAPPING[self.index - 1][0] + sensor_index = self.I2C_DEV_MAPPING[self.index - 1][1] + sensor_max_suffix = "max" + sensor_crit_suffix = "crit" + self.SENSOR_DIR = i2c_path + + # Armada 38x SOC temperature sensor + else: + dev_path = self.HWMON_CLASS_DIR + sensor_index = 1 + sensor_max_suffix = None + sensor_crit_suffix = None + hwmon_node = os.listdir(dev_path)[0] + self.SENSOR_DIR = dev_path + hwmon_node + '/' + + # sysfs file for current temperature value + self.thermal_temperature_file = self.SENSOR_DIR \ + + "temp{}_input".format(sensor_index) + + # sysfs file for high threshold value if supported for this sensor + if sensor_max_suffix: + self.thermal_high_threshold_file = self.SENSOR_DIR \ + + "temp{}_{}".format(sensor_index, sensor_max_suffix) + else: + self.thermal_high_threshold_file = None + + # sysfs file for crit high threshold value if supported for this sensor + if sensor_crit_suffix: + self.thermal_high_crit_threshold_file = self.SENSOR_DIR \ + + "temp{}_{}".format(sensor_index, sensor_crit_suffix) + else: + self.thermal_high_crit_threshold_file = None + + def _read_sysfs_file(self, sysfs_file): + # On successful read, returns the value read from given + # sysfs_file and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(sysfs_file)): + return rv + + try: + with open(sysfs_file, 'r') as fd: + rv = fd.read() + except Exception as e: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def get_name(self): + """ + Retrieves the name of the thermal + + Returns: + string: The name of the thermal + """ + return self.THERMAL_NAME[self.index - 1] + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + if self.dependency: + return self.dependency.get_presence() + else: + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return 'NA' + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + if self.dependency: + return self.dependency.get_status() + else: + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + thermal_temperature = self._read_sysfs_file( + self.thermal_temperature_file) + if (thermal_temperature != 'ERR'): + thermal_temperature = float(thermal_temperature) / 1000 + else: + thermal_temperature = 0 + + return float("{:.3f}".format(thermal_temperature)) + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + # Not implemented for this sensor + if not self.thermal_high_threshold_file: + raise NotImplementedError + + thermal_high_threshold = self._read_sysfs_file( + self.thermal_high_threshold_file) + if (thermal_high_threshold != 'ERR'): + thermal_high_threshold = float(thermal_high_threshold) / 1000 + else: + thermal_high_threshold = 0.0 + + return float("{:.3f}".format(thermal_high_threshold)) + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + + # Not implemented for this sensor + if not self.thermal_high_crit_threshold_file: + raise NotImplementedError + + thermal_high_crit_threshold = self._read_sysfs_file( + self.thermal_high_crit_threshold_file) + if (thermal_high_crit_threshold != 'ERR'): + thermal_high_crit_threshold = float(thermal_high_crit_threshold) / 1000 + else: + thermal_high_crit_threshold = 0.0 + + return float("{:.3f}".format(thermal_high_crit_threshold)) + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device + Returns: + integer: The 1-based relative physical position in parent device + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_actions.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_actions.py new file mode 100644 index 000000000000..a829fd80a5ba --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_actions.py @@ -0,0 +1,192 @@ +from sonic_platform_base.sonic_thermal_control.thermal_action_base import ThermalPolicyActionBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object + +from sonic_py_common import logger + +sonic_logger = logger.Logger('thermal_actions') + + +class SetFanSpeedAction(ThermalPolicyActionBase): + """ + Base thermal action class to set speed for fans + """ + # JSON field definition + JSON_FIELD_SPEED = 'speed' + JSON_FIELD_DEFAULT_SPEED = 'default_speed' + JSON_FIELD_HIGHTEMP_SPEED = 'hightemp_speed' + + def __init__(self): + """ + Constructor of SetFanSpeedAction + """ + self.default_speed = 50 + self.hightemp_speed = 100 + self.speed = self.default_speed + + def load_from_json(self, json_obj): + """ + Construct SetFanSpeedAction via JSON. JSON example: + { + "type": "fan.all.set_speed" + "speed": "100" + } + :param json_obj: A JSON object representing a SetFanSpeedAction action. + :return: + """ + if SetFanSpeedAction.JSON_FIELD_SPEED in json_obj: + speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED]) + if speed < 0 or speed > 100: + raise ValueError('SetFanSpeedAction invalid speed value {} in JSON policy file, valid value should be [0, 100]'. + format(speed)) + self.speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED]) + else: + raise ValueError('SetFanSpeedAction missing mandatory field {} in JSON policy file'. + format(SetFanSpeedAction.JSON_FIELD_SPEED)) + + @classmethod + def set_all_fan_speed(cls, thermal_info_dict, speed): + from .thermal_infos import FanInfo + if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo): + fan_info_obj = thermal_info_dict[FanInfo.INFO_NAME] + for fan in fan_info_obj.get_presence_fans(): + fan.set_speed(int(speed)) + + +@thermal_json_object('fan.all.set_speed') +class SetAllFanSpeedAction(SetFanSpeedAction): + """ + Action to set speed for all fans + """ + def execute(self, thermal_info_dict): + """ + Set speed for all fans + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + SetAllFanSpeedAction.set_all_fan_speed(thermal_info_dict, self.speed) + + +@thermal_json_object('thermal.temp_check_and_set_all_fan_speed') +class ThermalRecoverAction(SetFanSpeedAction): + """ + Action to check thermal sensor temperature change status and set speed for all fans + """ + + def load_from_json(self, json_obj): + """ + Construct ThermalRecoverAction via JSON. JSON example: + { + "type": "thermal.temp_check_and_set_all_fan_speed" + "default_speed": "50" + "hightemp_speed": "100" + } + :param json_obj: A JSON object representing a ThermalRecoverAction action. + :return: + """ + if SetFanSpeedAction.JSON_FIELD_DEFAULT_SPEED in json_obj: + default_speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_DEFAULT_SPEED]) + if default_speed < 0 or default_speed > 100: + raise ValueError('SetFanSpeedAction invalid default speed value {} in JSON policy file, valid value should be [0, 100]'. + format(default_speed)) + self.default_speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_DEFAULT_SPEED]) + else: + raise ValueError('SetFanSpeedAction missing mandatory field {} in JSON policy file'. + format(SetFanSpeedAction.JSON_FIELD_DEFAULT_SPEED)) + + if SetFanSpeedAction.JSON_FIELD_HIGHTEMP_SPEED in json_obj: + hightemp_speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_HIGHTEMP_SPEED]) + if hightemp_speed < 0 or hightemp_speed > 100: + raise ValueError('SetFanSpeedAction invalid hightemp speed value {} in JSON policy file, valid value should be [0, 100]'. + format(hightemp_speed)) + self.hightemp_speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_HIGHTEMP_SPEED]) + else: + raise ValueError('SetFanSpeedAction missing mandatory field {} in JSON policy file'. + format(SetFanSpeedAction.JSON_FIELD_HIGHTEMP_SPEED)) + + sonic_logger.log_warning("ThermalRecoverAction: default: {}, hightemp: {}".format(self.default_speed, self.hightemp_speed)) + + def execute(self, thermal_info_dict): + """ + Check check thermal sensor temperature change status and set speed for all fans + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + from .thermal_infos import ThermalInfo + if ThermalInfo.INFO_NAME in thermal_info_dict and \ + isinstance(thermal_info_dict[ThermalInfo.INFO_NAME], ThermalInfo): + + thermal_info_obj = thermal_info_dict[ThermalInfo.INFO_NAME] + if thermal_info_obj.is_warm_up_and_over_high_threshold(): + ThermalRecoverAction.set_all_fan_speed(thermal_info_dict, self.hightemp_speed) + elif thermal_info_obj.is_cool_down_and_below_low_threshold(): + ThermalRecoverAction.set_all_fan_speed(thermal_info_dict, self.default_speed) + + +@thermal_json_object('switch.shutdown') +class SwitchPolicyAction(ThermalPolicyActionBase): + """ + Base class for thermal action. Once all thermal conditions in a thermal policy are matched, + all predefined thermal action will be executed. + """ + def execute(self, thermal_info_dict): + """ + Take action when thermal condition matches. For example, adjust speed of fan or shut + down the switch. + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + sonic_logger.log_warning("Alarm for temperature critical is detected, reboot Device") + # import os + # os.system('reboot') + + +@thermal_json_object('thermal_control.control') +class ControlThermalAlgoAction(ThermalPolicyActionBase): + """ + Action to control the thermal control algorithm + """ + # JSON field definition + JSON_FIELD_STATUS = 'status' + + def __init__(self): + self.status = True + + def load_from_json(self, json_obj): + """ + Construct ControlThermalAlgoAction via JSON. JSON example: + { + "type": "thermal_control.control" + "status": "true" + } + :param json_obj: A JSON object representing a ControlThermalAlgoAction action. + :return: + """ + if ControlThermalAlgoAction.JSON_FIELD_STATUS in json_obj: + status_str = json_obj[ControlThermalAlgoAction.JSON_FIELD_STATUS].lower() + if status_str == 'true': + self.status = True + elif status_str == 'false': + self.status = False + else: + raise ValueError('Invalid {} field value, please specify true of false'. + format(ControlThermalAlgoAction.JSON_FIELD_STATUS)) + else: + raise ValueError('ControlThermalAlgoAction ' + 'missing mandatory field {} in JSON policy file'. + format(ControlThermalAlgoAction.JSON_FIELD_STATUS)) + + def execute(self, thermal_info_dict): + """ + Disable thermal control algorithm + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + from .thermal_infos import ChassisInfo + if ChassisInfo.INFO_NAME in thermal_info_dict: + chassis_info_obj = thermal_info_dict[ChassisInfo.INFO_NAME] + chassis = chassis_info_obj.get_chassis() + thermal_manager = chassis.get_thermal_manager() + if self.status: + thermal_manager.start_thermal_control_algorithm() + else: + thermal_manager.stop_thermal_control_algorithm() diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_conditions.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_conditions.py new file mode 100644 index 000000000000..4923d63d746b --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_conditions.py @@ -0,0 +1,81 @@ +from sonic_platform_base.sonic_thermal_control.thermal_condition_base import ThermalPolicyConditionBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object + + +class FanCondition(ThermalPolicyConditionBase): + def get_fan_info(self, thermal_info_dict): + from .thermal_infos import FanInfo + if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo): + return thermal_info_dict[FanInfo.INFO_NAME] + else: + return None + + +@thermal_json_object('fan.any.absence') +class AnyFanAbsenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fans()) > 0 if fan_info_obj else False + + +@thermal_json_object('fan.all.absence') +class AllFanAbsenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_presence_fans()) == 0 if fan_info_obj else False + + +@thermal_json_object('fan.all.presence') +class AllFanPresenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fans()) == 0 if fan_info_obj else False + + +class ThermalCondition(ThermalPolicyConditionBase): + def get_thermal_info(self, thermal_info_dict): + from .thermal_infos import ThermalInfo + if ThermalInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[ThermalInfo.INFO_NAME], ThermalInfo): + return thermal_info_dict[ThermalInfo.INFO_NAME] + else: + return None + + +@thermal_json_object('thermal.over.high_critical_threshold') +class ThermalOverHighCriticalCondition(ThermalCondition): + def is_match(self, thermal_info_dict): + thermal_info_obj = self.get_thermal_info(thermal_info_dict) + if thermal_info_obj: + return thermal_info_obj.is_over_high_critical_threshold() + else: + return False + + +class PsuCondition(ThermalPolicyConditionBase): + def get_psu_info(self, thermal_info_dict): + from .thermal_infos import PsuInfo + if PsuInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[PsuInfo.INFO_NAME], PsuInfo): + return thermal_info_dict[PsuInfo.INFO_NAME] + else: + return None + + +@thermal_json_object('psu.any.absence') +class AnyPsuAbsenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_absence_psus()) > 0 if psu_info_obj else False + + +@thermal_json_object('psu.all.absence') +class AllPsuAbsenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_presence_psus()) == 0 if psu_info_obj else False + + +@thermal_json_object('psu.all.presence') +class AllPsuPresenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_absence_psus()) == 0 if psu_info_obj else False diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_infos.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_infos.py new file mode 100644 index 000000000000..cd0a0591cd2a --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_infos.py @@ -0,0 +1,210 @@ +from sonic_platform_base.sonic_thermal_control.thermal_info_base import ThermalPolicyInfoBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object + + +@thermal_json_object('fan_info') +class FanInfo(ThermalPolicyInfoBase): + """ + Fan information needed by thermal policy + """ + + # Fan information name + INFO_NAME = 'fan_info' + + def __init__(self): + self._absence_fans = set() + self._presence_fans = set() + self._status_changed = False + + def collect(self, chassis): + """ + Collect absence and presence fans. + :param chassis: The chassis object + :return: + """ + self._status_changed = False + for fan in chassis.get_all_fans(): + if fan.get_presence() and fan not in self._presence_fans: + self._presence_fans.add(fan) + self._status_changed = True + if fan in self._absence_fans: + self._absence_fans.remove(fan) + elif not fan.get_presence() and fan not in self._absence_fans: + self._absence_fans.add(fan) + self._status_changed = True + if fan in self._presence_fans: + self._presence_fans.remove(fan) + + def get_absence_fans(self): + """ + Retrieves absence fans + :return: A set of absence fans + """ + return self._absence_fans + + def get_presence_fans(self): + """ + Retrieves presence fans + :return: A set of presence fans + """ + return self._presence_fans + + def is_status_changed(self): + """ + Retrieves if the status of fan information changed + :return: True if status changed else False + """ + return self._status_changed + + +@thermal_json_object('thermal_info') +class ThermalInfo(ThermalPolicyInfoBase): + """ + Thermal information needed by thermal policy + """ + + # Fan information name + INFO_NAME = 'thermal_info' + + def __init__(self): + self.init = False + self._old_avg_temp = 0 + self._current_avg_temp = 0 + self._high_crital_threshold = 75 + self._high_threshold = 45 + self._low_threshold = 40 + + def collect(self, chassis): + """ + Collect thermal sensor temperature change status + :param chassis: The chassis object + :return: + """ + self._temps = [] + self._over_high_critical_threshold = False + self._warm_up_and_over_high_threshold = False + self._cool_down_and_below_low_threshold = False + + # Calculate average temp within the device + temp = 0 + num_of_thermals = chassis.get_num_thermals() + for index in range(num_of_thermals): + self._temps.insert(index, chassis.get_thermal(index).get_temperature()) + temp += self._temps[index] + + self._current_avg_temp = temp / num_of_thermals + + # Special case if first time + if self.init is False: + self._old_avg_temp = self._current_avg_temp + self.init = True + + # Check if new average temp exceeds high threshold value + if self._current_avg_temp >= self._old_avg_temp and self._current_avg_temp >= self._high_threshold: + self._warm_up_and_over_high_threshold = True + + # Check if new average temp exceeds low threshold value + if self._current_avg_temp <= self._old_avg_temp and self._current_avg_temp <= self._low_threshold: + self._cool_down_and_below_low_threshold = True + + self._old_avg_temp = self._current_avg_temp + + def is_warm_up_and_over_high_threshold(self): + """ + Retrieves if the temperature is warm up and over high threshold + :return: True if the temperature is warm up and over high threshold else False + """ + return self._warm_up_and_over_high_threshold + + def is_cool_down_and_below_low_threshold(self): + """ + Retrieves if the temperature is cold down and below low threshold + :return: True if the temperature is cold down and below low threshold else False + """ + return self._cool_down_and_below_low_threshold + + def is_over_high_critical_threshold(self): + """ + Retrieves if the temperature is over high critical threshold + :return: True if the temperature is over high critical threshold else False + """ + return self._over_high_critical_threshold + + +@thermal_json_object('psu_info') +class PsuInfo(ThermalPolicyInfoBase): + """ + PSU information needed by thermal policy + """ + INFO_NAME = 'psu_info' + + def __init__(self): + self._absence_psus = set() + self._presence_psus = set() + self._status_changed = False + + def collect(self, chassis): + """ + Collect absence and presence PSUs. + :param chassis: The chassis object + :return: + """ + self._status_changed = False + for psu in chassis.get_all_psus(): + if psu.get_presence() and psu.get_powergood_status() and psu not in self._presence_psus: + self._presence_psus.add(psu) + self._status_changed = True + if psu in self._absence_psus: + self._absence_psus.remove(psu) + elif (not psu.get_presence() or not psu.get_powergood_status()) and psu not in self._absence_psus: + self._absence_psus.add(psu) + self._status_changed = True + if psu in self._presence_psus: + self._presence_psus.remove(psu) + + def get_absence_psus(self): + """ + Retrieves presence PSUs + :return: A set of absence PSUs + """ + return self._absence_psus + + def get_presence_psus(self): + """ + Retrieves presence PSUs + :return: A set of presence fans + """ + return self._presence_psus + + def is_status_changed(self): + """ + Retrieves if the status of PSU information changed + :return: True if status changed else False + """ + return self._status_changed + + +@thermal_json_object('chassis_info') +class ChassisInfo(ThermalPolicyInfoBase): + """ + Chassis information needed by thermal policy + """ + INFO_NAME = 'chassis_info' + + def __init__(self): + self._chassis = None + + def collect(self, chassis): + """ + Collect platform chassis. + :param chassis: The chassis object + :return: + """ + self._chassis = chassis + + def get_chassis(self): + """ + Retrieves platform chassis object + :return: A platform chassis object. + """ + return self._chassis diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_manager.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_manager.py new file mode 100644 index 000000000000..967cf175934e --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal_manager.py @@ -0,0 +1,49 @@ +from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase +from .thermal_actions import * +from .thermal_conditions import * +from .thermal_infos import * + + +class ThermalManager(ThermalManagerBase): + THERMAL_ALGORITHM_CONTROL_PATH = '/var/run/hw-management/config/suspend' + + @classmethod + def start_thermal_control_algorithm(cls): + """ + Start thermal control algorithm + + Returns: + bool: True if set success, False if fail. + """ + cls._control_thermal_control_algorithm(False) + + @classmethod + def stop_thermal_control_algorithm(cls): + """ + Stop thermal control algorithm + + Returns: + bool: True if set success, False if fail. + """ + cls._control_thermal_control_algorithm(True) + + @classmethod + def _control_thermal_control_algorithm(cls, suspend): + """ + Control thermal control algorithm + + Args: + suspend: Bool, indicate suspend the algorithm or not + + Returns: + bool: True if set success, False if fail. + """ + status = True + write_value = 1 if suspend else 0 + try: + with open(cls.THERMAL_ALGORITHM_CONTROL_PATH, 'w') as control_file: + control_file.write(str(write_value)) + except (ValueError, IOError): + status = False + + return status diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/watchdog.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/watchdog.py new file mode 100644 index 000000000000..75ec3ab177ae --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/watchdog.py @@ -0,0 +1,135 @@ +""" +ARMADA 38x Watchdog - one 32 bit cpu watchdog per cpu - 2 watchdogs ( page 662) + +Module contains an implementation of SONiC Platform Base API and +provides access to hardware watchdog +""" + +import os +import fcntl +import array + +from sonic_platform_base.watchdog_base import WatchdogBase +from sonic_py_common import logger + +""" ioctl constants """ +IO_READ = 0x80000000 +IO_SIZE_INT = 0x00040000 +IO_TYPE_WATCHDOG = ord('W') << 8 + +WDR_INT = IO_READ | IO_SIZE_INT | IO_TYPE_WATCHDOG + +""" Watchdog ioctl commands """ +WDIOC_SETOPTIONS = 4 | WDR_INT +WDIOC_KEEPALIVE = 5 | WDR_INT +WDIOC_GETTIMEOUT = 7 | WDR_INT + +""" Watchdog status constants """ +WDIOS_DISABLECARD = 0x0001 +WDIOS_ENABLECARD = 0x0002 + +""" watchdog sysfs """ +WD_SYSFS_PATH = "/sys/class/watchdog/" + +WD_COMMON_ERROR = -1 + +sonic_logger = logger.Logger() + + +class WatchdogImplBase(WatchdogBase): + """ + Base class that implements common logic for interacting + with watchdog using ioctl commands + """ + + def __init__(self, wd_device_path): + """ + Open a watchdog handle + @param wd_device_path Path to watchdog device + """ + + self.watchdog_path = wd_device_path + self.watchdog = os.open(self.watchdog_path, os.O_WRONLY) + + # Opening a watchdog descriptor starts + # watchdog timer; by default it should be stopped + self._disablewatchdog() + self.armed = False + self.timeout = self._gettimeout() + + def disarm(self): + """ + Disarm the hardware watchdog + + Returns: + A boolean, True if watchdog is disarmed successfully, False + if not + """ + sonic_logger.log_info(" Debug disarm watchdog ") + + try: + self._disablewatchdog() + self.armed = False + self.timeout = 0 + except IOError: + return False + + return True + + def _disablewatchdog(self): + """ + Turn off the watchdog timer + """ + + req = array.array('h', [WDIOS_DISABLECARD]) + fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False) + + def _gettimeout(self): + """ + Get watchdog timeout + @return watchdog timeout + """ + + req = array.array('I', [0]) + fcntl.ioctl(self.watchdog, WDIOC_GETTIMEOUT, req, True) + + return int(req[0]) + + def arm(self, seconds): + """ + Implements arm WatchdogBase API + """ + sonic_logger.log_info(" Debug arm watchdog4 ") + ret = WD_COMMON_ERROR + if seconds < 0: + return ret + + try: + if self.timeout != seconds: + self.timeout = self._settimeout(seconds) + if self.armed: + self._keepalive() + else: + sonic_logger.log_info(" Debug arm watchdog5 ") + self._enablewatchdog() + self.armed = True + ret = self.timeout + except IOError: + pass + + return ret + + def _enablewatchdog(self): + """ + Turn on the watchdog timer + """ + + req = array.array('h', [WDIOS_ENABLECARD]) + fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False) + + def _keepalive(self): + """ + Keep alive watchdog timer + """ + + fcntl.ioctl(self.watchdog, WDIOC_KEEPALIVE) diff --git a/platform/marvell-armhf/sonic-platform-nokia/debian/changelog b/platform/marvell-armhf/sonic-platform-nokia/debian/changelog new file mode 100755 index 000000000000..f4c860fab861 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/debian/changelog @@ -0,0 +1,5 @@ +sonic-platform-nokia-7215 (1.0) unstable; urgency=low + + * Add support for nokia-7215. + + -- Nokia Wed, 15 Apr 2020 09:35:58 +0800 diff --git a/platform/marvell-armhf/sonic-platform-nokia/debian/compat b/platform/marvell-armhf/sonic-platform-nokia/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/marvell-armhf/sonic-platform-nokia/debian/control b/platform/marvell-armhf/sonic-platform-nokia/debian/control new file mode 100755 index 000000000000..0da04ac89842 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/debian/control @@ -0,0 +1,15 @@ +Source: sonic-platform-nokia-7215 +Section: unknown +Priority: optional +Maintainer: Nokia +Build-Depends: debhelper (>=9) +Standards-Version: 3.9.6 +Homepage: +#Vcs-Git: git://anonscm.debian.org/collab-maint/sonic-platform-et6448m.git +#Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/sonic-platform-et6448m.git + +Package: sonic-platform-nokia-7215 +Architecture: armhf +Depends: ${misc:Depends} +Description: + diff --git a/platform/marvell-armhf/sonic-platform-nokia/debian/rules b/platform/marvell-armhf/sonic-platform-nokia/debian/rules new file mode 100755 index 000000000000..b7592c2b51e9 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/debian/rules @@ -0,0 +1,64 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#export DH_VERBOSE = 1 + +include /usr/share/dpkg/pkg-info.mk +#-------------------------------------------------------- + +PACKAGE_PRE_NAME := sonic-platform-nokia +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= 7215 +UTILS_DIR := utils +SERVICE_DIR := service +PLATFORM_DIR := sonic_platform + +%: + dh $@ --with systemd,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + (for mod in $(MODULE_DIRS); do \ + python3 $${mod}/setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} /usr/local/bin; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + python3 $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb + +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/marvell-armhf/sonic-platform-nokia/debian/sonic-platform-nokia-7215.install b/platform/marvell-armhf/sonic-platform-nokia/debian/sonic-platform-nokia-7215.install new file mode 100644 index 000000000000..ea347d79be3a --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/debian/sonic-platform-nokia-7215.install @@ -0,0 +1,6 @@ +nokia-7215_plt_setup.sh usr/sbin +7215/scripts/nokia-7215init.sh usr/local/bin +7215/service/nokia-7215init.service etc/systemd/system +7215/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/armhf-nokia_ixs7215_52x-r0 +entropy.py etc/ +inband_mgmt.sh etc/ diff --git a/platform/marvell-armhf/sonic-platform-nokia/debian/sonic-platform-nokia-7215.postinst b/platform/marvell-armhf/sonic-platform-nokia/debian/sonic-platform-nokia-7215.postinst new file mode 100644 index 000000000000..de91cedb4ec7 --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/debian/sonic-platform-nokia-7215.postinst @@ -0,0 +1,11 @@ +#!/bin/sh +# postinst script for sonic-platform-nokia-7215 +# +# see: dh_installdeb(1) + +sh /usr/sbin/nokia-7215_plt_setup.sh +systemctl enable nokia-7215init.service +systemctl start nokia-7215init.service + +exit 0 + diff --git a/platform/marvell-armhf/sonic-platform-nokia/entropy.py b/platform/marvell-armhf/sonic-platform-nokia/entropy.py new file mode 100644 index 000000000000..338e2ad9bcea --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/entropy.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +import fcntl, struct +import time +from os import path + +RNDADDENTROPY=0x40085203 + +def avail(): + with open("/proc/sys/kernel/random/entropy_avail", mode='r') as avail: + return int(avail.read()) + +if path.exists("/proc/sys/kernel/random/entropy_avail"): + while 1: + while avail() < 2048: + with open('/dev/urandom', 'rb') as urnd, open("/dev/random", mode='wb') as rnd: + d = urnd.read(512) + t = struct.pack('ii', 4 * len(d), len(d)) + d + fcntl.ioctl(rnd, RNDADDENTROPY, t) + time.sleep(30) diff --git a/platform/marvell-armhf/sonic-platform-nokia/inband_mgmt.sh b/platform/marvell-armhf/sonic-platform-nokia/inband_mgmt.sh new file mode 100644 index 000000000000..25455d16ecbf --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/inband_mgmt.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +#inband_mgmt + +inband_mgmt(){ + # In this platform, one of the network ports is used as mgmt interface. + # This script periodically monitors inband management port eth0 and + # assigns IP address to eth0 if needed. + if [ ! -f /host/machine.conf ]; then + exit 0 + fi + #wait for n/w port init to complete + sleep 60 + while :; do + ip -br link show eth0 2> /dev/null + if [ $? -eq 0 ]; then + ip address show eth0 | grep -qw "inet" 2>/dev/null + if [ $? -ne 0 ]; then + ifconfig eth0 down + systemctl restart networking + fi + sleep 120 + else + sleep 3 + fi + done +} +(inband_mgmt > /dev/null)& diff --git a/platform/marvell-armhf/sonic-platform-nokia/nokia-7215_plt_setup.sh b/platform/marvell-armhf/sonic-platform-nokia/nokia-7215_plt_setup.sh new file mode 100755 index 000000000000..8301999d0d0a --- /dev/null +++ b/platform/marvell-armhf/sonic-platform-nokia/nokia-7215_plt_setup.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +fw_uboot_env_cfg() +{ + echo "Setting up U-Boot environment..." + + MACH_FILE="/host/machine.conf" + PLATFORM=`sed -n 's/onie_platform=\(.*\)/\1/p' $MACH_FILE` + + if [ "$PLATFORM" = "armhf-nokia_ixs7215_52x-r0" ]; then + # Ixs7215 / IPD6448M board Uboot ENV offset + FW_ENV_DEFAULT='/dev/mtd0 0x00100000 0x10000 0x10000' + + demo_part=$(sgdisk -p /dev/sda | grep -e "SONiC-OS") + if [ -z "$demo_part" ]; then + # ET6448M Board - For Backward compatibility + FW_ENV_DEFAULT='/dev/mtd0 0x00500000 0x80000 0x100000 8' + fi + else + FW_ENV_DEFAULT='/dev/mtd0 0x00500000 0x80000 0x100000 8' + fi + + echo "Using pre-configured uboot env" + echo $FW_ENV_DEFAULT > /etc/fw_env.config + +} + + +main() +{ + fw_uboot_env_cfg + echo "Nokia-IXS7215: /dev/mtd0 FW_ENV_DEFAULT" + + python /etc/entropy.py & + /bin/sh /etc/inband_mgmt.sh +} + +main $@ diff --git a/platform/marvell/docker-syncd-mrvl-rpc.mk b/platform/marvell/docker-syncd-mrvl-rpc.mk new file mode 100644 index 000000000000..c3ce6c10119c --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl-rpc.mk @@ -0,0 +1,24 @@ +# docker image for mrvl syncd with rpc + +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) $(PTF) +$(DOCKER_SYNCD_MRVL_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_MRVL_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_MRVL_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_MRVL_RPC) +SONIC_STRETCH_DOCKERS += $(DOCKER_SYNCD_MRVL_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_MRVL_RPC) +endif + +$(DOCKER_SYNCD_MRVL_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_MRVL_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/marvell/docker-syncd-mrvl-rpc/99-syncd.conf b/platform/marvell/docker-syncd-mrvl-rpc/99-syncd.conf new file mode 100644 index 000000000000..f3b57e3b1964 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl-rpc/99-syncd.conf @@ -0,0 +1,2 @@ +sysctl -w net.core.rmem_max=509430500 + diff --git a/platform/marvell/docker-syncd-mrvl-rpc/Dockerfile.j2 b/platform/marvell/docker-syncd-mrvl-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..118be5e1c5f2 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl-rpc/Dockerfile.j2 @@ -0,0 +1,55 @@ +FROM docker-syncd-mrvl + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_mrvl_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get purge -y syncd + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_mrvl_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/marvell/docker-syncd-mrvl-rpc/ptf_nn_agent.conf b/platform/marvell/docker-syncd-mrvl-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/marvell/docker-syncd-mrvl.mk b/platform/marvell/docker-syncd-mrvl.mk new file mode 100644 index 000000000000..d6d7d032b8ac --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl.mk @@ -0,0 +1,18 @@ +# docker image for mrvl syncd + +DOCKER_SYNCD_PLATFORM_CODE = mrvl +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) + +SONIC_STRETCH_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_STRETCH_DBG_DOCKERS += $(DOCKER_SYNCD_BASE_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/Dockerfile.j2 b/platform/marvell/docker-syncd-mrvl/Dockerfile.j2 new file mode 100755 index 000000000000..e91231e49791 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl/Dockerfile.j2 @@ -0,0 +1,33 @@ +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 + +COPY \ +{% for deb in docker_syncd_mrvl_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get -y install libpcap-dev libxml2-dev python-dev swig libsensors4-dev libatomic1 libjemalloc1 liblua5.1-0 lua-bitop lua-cjson nfs-common + +RUN dpkg -i \ +{% for deb in docker_syncd_mrvl_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["syncd.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] 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..61e290e3189e --- /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 program syncd|syncd with path "/usr/bin/process_checker syncd /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/platform/marvell/docker-syncd-mrvl/critical_processes b/platform/marvell/docker-syncd-mrvl/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/platform/marvell/docker-syncd-mrvl/supervisord.conf b/platform/marvell/docker-syncd-mrvl/supervisord.conf new file mode 100644 index 000000000000..94be9dd268f6 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl/supervisord.conf @@ -0,0 +1,38 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python2 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running diff --git a/platform/marvell/docker-syncd-mrvl/syncd.sh b/platform/marvell/docker-syncd-mrvl/syncd.sh new file mode 100755 index 000000000000..993cf100f2f0 --- /dev/null +++ b/platform/marvell/docker-syncd-mrvl/syncd.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +function clean_up { + service syncd stop + exit +} + +trap clean_up SIGTERM SIGKILL + +service syncd start + +read diff --git a/platform/marvell/libsaithrift-dev.mk b/platform/marvell/libsaithrift-dev.mk new file mode 100644 index 000000000000..d1607a1ba220 --- /dev/null +++ b/platform/marvell/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_amd64.deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(MRVL_FPA) $(MRVL_SAI) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(MRVL_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_amd64.deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_amd64.deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(BRCM_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_amd64.deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/marvell/one-image.mk b/platform/marvell/one-image.mk new file mode 100644 index 000000000000..fcac03854348 --- /dev/null +++ b/platform/marvell/one-image.mk @@ -0,0 +1,13 @@ +# sonic marvell one image installer + +SONIC_ONE_IMAGE = sonic-marvell.bin +$(SONIC_ONE_IMAGE)_MACHINE = marvell +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/marvell/platform.conf b/platform/marvell/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/marvell/rules.mk b/platform/marvell/rules.mk new file mode 100644 index 000000000000..da23e53f26bc --- /dev/null +++ b/platform/marvell/rules.mk @@ -0,0 +1,20 @@ +include $(PLATFORM_PATH)/sai.mk +include $(PLATFORM_PATH)/docker-syncd-mrvl.mk +include $(PLATFORM_PATH)/docker-syncd-mrvl-rpc.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/one-image.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_FPM) \ + $(DOCKER_SYNCD_MRVL_RPC) + +# Inject mrvl sai into syncd +$(SYNCD)_DEPENDS += $(MRVL_FPA) $(MRVL_SAI) +$(SYNCD)_UNINSTALLS += $(MRVL_SAI) + +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV) +endif + +# Runtime dependency on mrvl sai is set only for syncd +$(SYNCD)_RDEPENDS += $(MRVL_SAI) diff --git a/platform/marvell/sai.mk b/platform/marvell/sai.mk new file mode 100644 index 000000000000..ac05bc8f0470 --- /dev/null +++ b/platform/marvell/sai.mk @@ -0,0 +1,9 @@ +# Marvell SAI + +export MRVL_SAI_VERSION = 1.5.1 +export MRVL_SAI = mrvllibsai_amd64_$(MRVL_SAI_VERSION).deb + +$(MRVL_SAI)_SRC_PATH = $(PLATFORM_PATH)/sai +$(eval $(call add_conflict_package,$(MRVL_SAI),$(LIBSAIVS_DEV))) + +SONIC_MAKE_DEBS += $(MRVL_SAI) diff --git a/platform/marvell/sai/Makefile b/platform/marvell/sai/Makefile new file mode 100644 index 000000000000..1cd6d0267fa2 --- /dev/null +++ b/platform/marvell/sai/Makefile @@ -0,0 +1,9 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MRVL_SAI_URL = https://github.com/Marvell-switching/sonic-marvell-binaries/raw/master/amd64/sai-plugin/$(MRVL_SAI) + +$(addprefix $(DEST)/, $(MRVL_SAI)): $(DEST)/% : + # get deb package + wget -O $(DEST)/$(MRVL_SAI) $(MRVL_SAI_URL) diff --git a/platform/mellanox/.gitignore b/platform/mellanox/.gitignore new file mode 100644 index 000000000000..1f3d15d640d4 --- /dev/null +++ b/platform/mellanox/.gitignore @@ -0,0 +1,22 @@ +# Subdirectories +mlnx-sai/* +!mlnx-sai/Makefile +hw-management/* +!hw-management/Makefile +!hw-management/*.patch +mft/* +!mft/Makefile +sdk-src/*/* +!sdk-src/*/Makefile +!sdk-src/sx-kernel/Switch-SDK-drivers/ +!sdk-src/*/*.patch +*/build +*/deb_dist +*/dist +*/*.gz +*/*.egg-info + +# Autogenerated Dockerfiles +docker-syncd-mlnx/Dockerfile +docker-syncd-mlnx-rpc/Dockerfile +docker-saiserver-mlnx/Dockerfile diff --git a/platform/mellanox/asic_table.j2 b/platform/mellanox/asic_table.j2 new file mode 100644 index 000000000000..4afc780b0b06 --- /dev/null +++ b/platform/mellanox/asic_table.j2 @@ -0,0 +1,59 @@ +{%- if DEVICE_METADATA is defined and DEVICE_METADATA['localhost']['platform'] is defined %} +{%- set platform = DEVICE_METADATA['localhost']['platform'] %} +{%- else -%} +{%- set platform = "vs-platform" %} +{%- endif -%} + + +[ +{% set platform2asic = { + 'x86_64-mlnx_lssn2700-r0':'MELLANOX-SPECTRUM', + 'x86_64-mlnx_msn2010-r0':'MELLANOX-SPECTRUM', + 'x86_64-mlnx_msn2100-r0':'MELLANOX-SPECTRUM', + 'x86_64-mlnx_msn2410-r0':'MELLANOX-SPECTRUM', + 'x86_64-mlnx_msn2700-r0':'MELLANOX-SPECTRUM', + 'x86_64-mlnx_msn2700_simx-r0':'MELLANOX-SPECTRUM', + 'x86_64-mlnx_msn2740-r0':'MELLANOX-SPECTRUM', + 'x86_64-mlnx_msn3700c-r0':'MELLANOX-SPECTRUM-2', + 'x86_64-mlnx_msn3700-r0':'MELLANOX-SPECTRUM-2', + 'x86_64-mlnx_msn3700_simx-r0':'MELLANOX-SPECTRUM-2', + 'x86_64-mlnx_msn3800-r0':'MELLANOX-SPECTRUM-2', + 'x86_64-mlnx_msn4700_simx-r0':'MELLANOX-SPECTRUM-3', + 'x86_64-mlnx_msn4700-r0':'MELLANOX-SPECTRUM-3', + 'x86_64-mlnx_msn4600c-r0':'MELLANOX-SPECTRUM-3', + 'vs-platform':'vs' + } +%} +{% set asic_type = platform2asic[platform] %} +{% if asic_type == 'MELLANOX-SPECTRUM' %} + { + "ASIC_TABLE:MELLANOX-SPECTRUM": { + "cell_size": "96", + "pipeline_latency": "19", + "mac_phy_delay": "0.8", + "peer_response_time": "3.8" + }, + "OP": "SET" + } +{% elif asic_type == 'MELLANOX-SPECTRUM-2' %} + { + "ASIC_TABLE:MELLANOX-SPECTRUM-2": { + "cell_size": "144", + "pipeline_latency": "19", + "mac_phy_delay": "0.8", + "peer_response_time": "3.8" + }, + "OP": "SET" + } +{% elif asic_type == 'MELLANOX-SPECTRUM-3' %} + { + "ASIC_TABLE:MELLANOX-SPECTRUM-3": { + "cell_size": "144", + "pipeline_latency": "19", + "mac_phy_delay": "0.8", + "peer_response_time": "3.8" + }, + "OP": "SET" + } +{% endif %} +] diff --git a/platform/mellanox/docker-saiserver-mlnx.dep b/platform/mellanox/docker-saiserver-mlnx.dep new file mode 100644 index 000000000000..7a4e4fdcbb34 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx.dep @@ -0,0 +1,10 @@ +# DPKG FRK + +DPATH := $($(DOCKER_SAISERVER_MLNX)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/docker-saiserver-mlnx.mk $(PLATFORM_PATH)/docker-saiserver-mlnx.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(DPATH)) + +$(DOCKER_SAISERVER_MLNX)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SAISERVER_MLNX)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SAISERVER_MLNX)_DEP_FILES := $(DEP_FILES) diff --git a/platform/mellanox/docker-saiserver-mlnx.mk b/platform/mellanox/docker-saiserver-mlnx.mk new file mode 100644 index 000000000000..6515fa9846b1 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx.mk @@ -0,0 +1,15 @@ +# docker image for mlnx saiserver + +DOCKER_SAISERVER_MLNX = docker-saiserver-mlnx.gz +$(DOCKER_SAISERVER_MLNX)_PATH = $(PLATFORM_PATH)/docker-saiserver-mlnx +$(DOCKER_SAISERVER_MLNX)_DEPENDS += $(SAISERVER) $(PYTHON_SDK_API) +$(DOCKER_SAISERVER_MLNX)_PYTHON_DEBS += $(MLNX_SFPD) +$(DOCKER_SAISERVER_MLNX)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_STRETCH) +SONIC_DOCKER_IMAGES += $(DOCKER_SAISERVER_MLNX) +SONIC_STRETCH_DOCKERS += $(DOCKER_SAISERVER_MLNX) + +$(DOCKER_SAISERVER_MLNX)_CONTAINER_NAME = saiserver +$(DOCKER_SAISERVER_MLNX)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SAISERVER_MLNX)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SAISERVER_MLNX)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_BASE)_RUN_OPT += --tmpfs /run/criu diff --git a/platform/mellanox/docker-saiserver-mlnx/Dockerfile.j2 b/platform/mellanox/docker-saiserver-mlnx/Dockerfile.j2 new file mode 100644 index 000000000000..39223131ee43 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/Dockerfile.j2 @@ -0,0 +1,47 @@ +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 + +COPY \ +{% for deb in docker_saiserver_mlnx_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +COPY \ +{% for deb in docker_saiserver_mlnx_pydebs.split(' ') -%} +python-debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get install -y --no-install-recommends libxml2 iptables libbsd0 protobuf-c-compiler protobuf-compiler python-protobuf libprotobuf-c1 python-future python-ipaddr libnet1 pkg-config asciidoc xmlto + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_saiserver_mlnx_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_saiserver_mlnx_pydebs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +COPY ["profile.ini", "portmap.ini", "/etc/sai/"] + +COPY ["sai_2700.xml", "/usr/share/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/mellanox/docker-saiserver-mlnx/portmap.ini b/platform/mellanox/docker-saiserver-mlnx/portmap.ini new file mode 100644 index 000000000000..4d3be08ce5f8 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/portmap.ini @@ -0,0 +1,33 @@ +# alias lanes +Ethernet1 0,1,2,3 +Ethernet2 4,5,6,7 +Ethernet3 8,9,10,11 +Ethernet4 12,13,14,15 +Ethernet5 16,17,18,19 +Ethernet6 20,21,22,23 +Ethernet7 24,25,26,27 +Ethernet8 28,29,30,31 +Ethernet9 32,33,34,35 +Ethernet10 36,37,38,39 +Ethernet11 40,41,42,43 +Ethernet12 44,45,46,47 +Ethernet13 48,49,50,51 +Ethernet14 52,53,54,55 +Ethernet15 56,57,58,59 +Ethernet16 60,61,62,63 +Ethernet17 64,65,66,67 +Ethernet18 68,69,70,71 +Ethernet19 72,73,74,75 +Ethernet20 76,77,78,79 +Ethernet21 80,81,82,83 +Ethernet22 84,85,86,87 +Ethernet23 88,89,90,91 +Ethernet24 92,93,94,95 +Ethernet25 96,97,98,99 +Ethernet26 100,101,102,103 +Ethernet27 104,105,106,107 +Ethernet28 108,109,110,111 +Ethernet29 112,113,114,115 +Ethernet30 116,117,118,119 +Ethernet31 120,121,122,123 +Ethernet32 124,125,126,127 \ No newline at end of file diff --git a/platform/mellanox/docker-saiserver-mlnx/profile.ini b/platform/mellanox/docker-saiserver-mlnx/profile.ini new file mode 100644 index 000000000000..c67be49f3c45 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/profile.ini @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sai_2700.xml \ No newline at end of file diff --git a/platform/mellanox/docker-saiserver-mlnx/sai_2700.xml b/platform/mellanox/docker-saiserver-mlnx/sai_2700.xml new file mode 100644 index 000000000000..42b576311453 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/sai_2700.xml @@ -0,0 +1,243 @@ + + + + + + 00:77:66:55:44:00 + + + 32 + + + + + 1 + 4 + 16 + + + 3 + + + 98368 + + + 3 + 4 + 17 + 1 + 98368 + + + 5 + 4 + 18 + 3 + 98368 + + + 7 + 4 + 19 + 1 + 98368 + + + 9 + 4 + 20 + 3 + 98368 + + + 11 + 4 + 21 + 1 + 98368 + + + 13 + 4 + 22 + 3 + 98368 + + + 15 + 4 + 23 + 1 + 98368 + + + 17 + 4 + 24 + 3 + 98368 + + + 19 + 4 + 25 + 1 + 98368 + + + 21 + 4 + 26 + 3 + 98368 + + + 23 + 4 + 27 + 1 + 98368 + + + 25 + 4 + 28 + 3 + 98368 + + + 27 + 4 + 29 + 1 + 98368 + + + 29 + 4 + 30 + 3 + 98368 + + + 31 + 4 + 31 + 1 + 98368 + + + 33 + 4 + 14 + 3 + 98368 + + + 35 + 4 + 15 + 1 + 98368 + + + 37 + 4 + 12 + 3 + 98368 + + + 39 + 4 + 13 + 1 + 98368 + + + 41 + 4 + 10 + 3 + 98368 + + + 43 + 4 + 11 + 1 + 98368 + + + 45 + 4 + 8 + 3 + 98368 + + + 47 + 4 + 9 + 1 + 98368 + + + 49 + 4 + 6 + 3 + 98368 + + + 51 + 4 + 7 + 1 + 98368 + + + 53 + 4 + 4 + 3 + 98368 + + + 55 + 4 + 5 + 1 + 98368 + + + 57 + 4 + 2 + 3 + 98368 + + + 59 + 4 + 3 + 1 + 98368 + + + 61 + 4 + 0 + 3 + 98368 + + + 63 + 4 + 1 + 1 + 98368 + + + + diff --git a/platform/mellanox/docker-saiserver-mlnx/start.sh b/platform/mellanox/docker-saiserver-mlnx/start.sh new file mode 100755 index 000000000000..58a0c316add3 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/start.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +start_mlnx() +{ + [ -e /dev/sxdevs/sxcdev ] || ( mkdir -p /dev/sxdevs && mknod /dev/sxdevs/sxcdev c 231 193 ) +} + + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +start_mlnx + +supervisorctl start saiserver diff --git a/platform/mellanox/docker-saiserver-mlnx/supervisord.conf b/platform/mellanox/docker-saiserver-mlnx/supervisord.conf new file mode 100644 index 000000000000..cb67a0fc9a47 --- /dev/null +++ b/platform/mellanox/docker-saiserver-mlnx/supervisord.conf @@ -0,0 +1,28 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[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=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:saiserver] +command=/usr/bin/saiserver -p /etc/sai/profile.ini -f /etc/sai/portmap.ini +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/mellanox/docker-syncd-mlnx-rpc.dep b/platform/mellanox/docker-syncd-mlnx-rpc.dep new file mode 100644 index 000000000000..c79c94d2c03a --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx-rpc.dep @@ -0,0 +1,10 @@ +# DPKG FRK + +DPATH := $($(DOCKER_SYNCD_MLNX_RPC)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/docker-syncd-mlnx-rpc.mk $(PLATFORM_PATH)/docker-syncd-mlnx-rpc.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(DPATH)) + +$(DOCKER_SYNCD_MLNX_RPC)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SYNCD_MLNX_RPC)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SYNCD_MLNX_RPC)_DEP_FILES := $(DEP_FILES) diff --git a/platform/mellanox/docker-syncd-mlnx-rpc.mk b/platform/mellanox/docker-syncd-mlnx-rpc.mk new file mode 100644 index 000000000000..806b40035f23 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx-rpc.mk @@ -0,0 +1,26 @@ +# docker image for mlnx syncd with rpc + +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) $(PTF) +$(DOCKER_SYNCD_MLNX_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_MLNX_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif + +$(DOCKER_SYNCD_MLNX_RPC)_PYTHON_DEBS += $(MLNX_SFPD) +$(DOCKER_SYNCD_MLNX_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_MLNX_RPC) +SONIC_BUSTER_DOCKERS += $(DOCKER_SYNCD_MLNX_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_MLNX_RPC) +endif + +$(DOCKER_SYNCD_MLNX_RPC)_CONTAINER_NAME = syncd +$(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 new file mode 100644 index 000000000000..b48d4ac3c793 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2 @@ -0,0 +1,76 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +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() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_syncd_mlnx_rpc_debs.split(' '), "/debs/") }} +{% endif %} + +{% if docker_syncd_mlnx_rpc_pydebs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("python-debs/", docker_syncd_mlnx_rpc_pydebs.split(' '), "/debs/") }} +{% endif %} + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + python-setuptools \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +{% if docker_syncd_mlnx_rpc_debs.strip() -%} +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_syncd_mlnx_rpc_debs.split(' ')) }} +{% endif %} + +{% if docker_syncd_mlnx_rpc_pydebs.strip() -%} +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_syncd_mlnx_rpc_pydebs.split(' ')) }} +{% endif %} + + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip2 install cffi==1.7.0 \ + && pip2 install --upgrade cffi==1.7.0 \ + && pip2 install wheel \ + && pip2 install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/mellanox/docker-syncd-mlnx-rpc/ptf_nn_agent.conf b/platform/mellanox/docker-syncd-mlnx-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..cd6a7d4db75d --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-nn-rcv-buffer=109430400 --set-iface-rcv-buffer=109430400 --set-nn-snd-buffer=109430400 --set-iface-snd-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/mellanox/docker-syncd-mlnx.dep b/platform/mellanox/docker-syncd-mlnx.dep new file mode 100644 index 000000000000..659b09cec8f4 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx.dep @@ -0,0 +1,12 @@ +# DPKG FRK + +DPATH := $($(DOCKER_SYNCD_BASE)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/docker-syncd-mlnx.mk $(PLATFORM_PATH)/docker-syncd-mlnx.dep platform/mellanox/mlnx-sai.mk +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(DPATH)) + +$(DOCKER_SYNCD_BASE)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SYNCD_BASE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SYNCD_BASE)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_SYNCD_BASE),$(DOCKER_SYNCD_BASE_DBG))) diff --git a/platform/mellanox/docker-syncd-mlnx.mk b/platform/mellanox/docker-syncd-mlnx.mk new file mode 100644 index 000000000000..9bdc5a8ad8ec --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx.mk @@ -0,0 +1,18 @@ +# docker image for mlnx syncd + +DOCKER_SYNCD_PLATFORM_CODE = mlnx +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) $(PYTHON_SDK_API) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) + +ifeq ($(SDK_FROM_SRC), y) +$(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 new file mode 100755 index 000000000000..c862106c2b63 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx/Dockerfile.j2 @@ -0,0 +1,48 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} +FROM docker-config-engine-buster + +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 + +RUN apt-get update && \ + apt-get install -y \ + libxml2 \ + python-pip \ + python-dev \ + python-setuptools + +RUN pip2 install --upgrade pip +RUN apt-get purge -y python-pip + +{% if docker_syncd_mlnx_debs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("debs/", docker_syncd_mlnx_debs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_syncd_mlnx_debs.split(' ')) }} +{% endif %} + +{% if docker_syncd_mlnx_pydebs.strip() -%} +# Copy locally-built Debian package dependencies +{{ copy_files("python-debs/", docker_syncd_mlnx_pydebs.split(' '), "/debs/") }} + +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_syncd_mlnx_pydebs.split(' ')) }} +{% endif %} + +## Clean up +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] 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..61e290e3189e --- /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 program syncd|syncd with path "/usr/bin/process_checker syncd /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/platform/mellanox/docker-syncd-mlnx/critical_processes b/platform/mellanox/docker-syncd-mlnx/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/platform/mellanox/docker-syncd-mlnx/supervisord.conf b/platform/mellanox/docker-syncd-mlnx/supervisord.conf new file mode 100644 index 000000000000..8491d762bf51 --- /dev/null +++ b/platform/mellanox/docker-syncd-mlnx/supervisord.conf @@ -0,0 +1,38 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running diff --git a/platform/mellanox/fw.dep b/platform/mellanox/fw.dep new file mode 100644 index 000000000000..228f6dc87e36 --- /dev/null +++ b/platform/mellanox/fw.dep @@ -0,0 +1,16 @@ +# DPKG FRK + +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/fw.mk $(PLATFORM_PATH)/fw.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) + +$(MLNX_SPC_FW_FILE)_CACHE_MODE := GIT_CONTENT_SHA +$(MLNX_SPC_FW_FILE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MLNX_SPC_FW_FILE)_DEP_FILES := $(DEP_FILES) + +$(MLNX_SPC2_FW_FILE)_CACHE_MODE := GIT_CONTENT_SHA +$(MLNX_SPC2_FW_FILE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MLNX_SPC2_FW_FILE)_DEP_FILES := $(DEP_FILES) + +$(MLNX_SPC3_FW_FILE)_CACHE_MODE := GIT_CONTENT_SHA +$(MLNX_SPC3_FW_FILE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MLNX_SPC3_FW_FILE)_DEP_FILES := $(DEP_FILES) diff --git a/platform/mellanox/fw.mk b/platform/mellanox/fw.mk new file mode 100644 index 000000000000..5b21692173c0 --- /dev/null +++ b/platform/mellanox/fw.mk @@ -0,0 +1,41 @@ +# mellanox asic firmware + +MLNX_FW_BASE_PATH = $(MLNX_SDK_BASE_PATH) + +# Place an URL here to FW if you want to download FW instead +MLNX_FW_BASE_URL = + +ifneq ($(MLNX_FW_BASE_URL), ) +FW_FROM_URL = y +else +FW_FROM_URL = n +endif + +MLNX_SPC_FW_VERSION = 13.2008.2314 +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.2008.2314 +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.2008.2314 +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_FW_FILES) +else +SONIC_ONLINE_FILES += $(MLNX_FW_FILES) +endif + +MLNX_FILES += $(MLNX_FW_FILES) + +export MLNX_SPC_FW_FILE +export MLNX_SPC2_FW_FILE +export MLNX_SPC3_FW_FILE diff --git a/platform/mellanox/hw-management.dep b/platform/mellanox/hw-management.dep new file mode 100644 index 000000000000..b69ca22b4c57 --- /dev/null +++ b/platform/mellanox/hw-management.dep @@ -0,0 +1,15 @@ +# DPKG FRK + +SPATH := $($(MLNX_HW_MANAGEMENT)_SRC_PATH) +SLINKS := $(shell find $(SPATH) -type l -exec echo {} \; | grep -Ev ' ') +SMDEP_PATHS := $(shell git submodule status --recursive -- $(SPATH) | awk '{print $$2}' | grep -Ev ' ') +SMDEP_FILES := $(foreach path,$(SMDEP_PATHS),$(filter-out $(SMDEP_PATHS),$(addprefix $(path)/,$(shell cd $(path) && git ls-files | grep -Ev ' ')))) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/hw-management.mk $(PLATFORM_PATH)/hw-management.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(filter-out $(SMDEP_PATHS),$(shell git ls-files -- $(SPATH) | grep -Ev ' ')) + +$(MLNX_HW_MANAGEMENT)_CACHE_MODE := GIT_CONTENT_SHA +$(MLNX_HW_MANAGEMENT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MLNX_HW_MANAGEMENT)_DEP_FILES := $(filter-out $(SLINKS),$(DEP_FILES)) +$(MLNX_HW_MANAGEMENT)_SMDEP_FILES := $(filter-out $(SLINKS),$(SMDEP_FILES)) +$(MLNX_HW_MANAGEMENT)_SMDEP_PATHS := $(SMDEP_PATHS) diff --git a/platform/mellanox/hw-management.mk b/platform/mellanox/hw-management.mk new file mode 100644 index 000000000000..521daa1c7c3b --- /dev/null +++ b/platform/mellanox/hw-management.mk @@ -0,0 +1,10 @@ +# Mellanox HW Management + +MLNX_HW_MANAGEMENT_VERSION = 7.0010.1300 + +export MLNX_HW_MANAGEMENT_VERSION + +MLNX_HW_MANAGEMENT = hw-management_1.mlnx.$(MLNX_HW_MANAGEMENT_VERSION)_amd64.deb +$(MLNX_HW_MANAGEMENT)_SRC_PATH = $(PLATFORM_PATH)/hw-management +$(MLNX_HW_MANAGEMENT)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_MAKE_DEBS += $(MLNX_HW_MANAGEMENT) diff --git a/platform/mellanox/hw-management/0001-Make-SONiC-determine-reboot-cause-service-start-afte.patch b/platform/mellanox/hw-management/0001-Make-SONiC-determine-reboot-cause-service-start-afte.patch new file mode 100644 index 000000000000..11539e606369 --- /dev/null +++ b/platform/mellanox/hw-management/0001-Make-SONiC-determine-reboot-cause-service-start-afte.patch @@ -0,0 +1,26 @@ +From 1a1011b6da491d35001df5a7204d4eecb2769767 Mon Sep 17 00:00:00 2001 +From: keboliu +Date: Fri, 15 Jan 2021 14:41:16 +0800 +Subject: [PATCH] Make SONiC determine-reboot-cause service start after hw-mgmt + service + +Signed-off-by: Kebo Liu +--- + debian/hw-management.hw-management.service | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/debian/hw-management.hw-management.service b/debian/hw-management.hw-management.service +index 39a2a54..2104b87 100755 +--- a/debian/hw-management.hw-management.service ++++ b/debian/hw-management.hw-management.service +@@ -1,6 +1,7 @@ + [Unit] + Description=Chassis HW management service of Mellanox systems + Documentation=man:hw-management.service(8) ++Before=determine-reboot-cause.service + + [Service] + Type=oneshot +-- +1.9.1 + diff --git a/platform/mellanox/hw-management/0002-hw-mgmt-events-Add-support-for-SDK-OFFLINE-event-for.patch b/platform/mellanox/hw-management/0002-hw-mgmt-events-Add-support-for-SDK-OFFLINE-event-for.patch new file mode 100644 index 000000000000..6c58f7299c2c --- /dev/null +++ b/platform/mellanox/hw-management/0002-hw-mgmt-events-Add-support-for-SDK-OFFLINE-event-for.patch @@ -0,0 +1,30 @@ +From 3e511778248403968e0a02857b7003f352669ba3 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 13 Jan 2021 13:19:17 +0200 +Subject: [PATCH] hw-mgmt: events: Add support for SDK OFFLINE event for + handling flow with in service firmware upgrade + +In order to prevent "mlxsw_minimal" driver access to ASIC during in +service firmware upgrade flow, SDK will raise "OFFLINE" 'udev' event +at early beginning of such flow. When this event is received, +hw-managemnet will remove "mlxsw_minimal" driver. +There is no need to implement opposite "ONLINE" event, since this flow +is ended up with "kexec". + +Signed-off-by: Vadim Pasternak +--- + usr/lib/udev/rules.d/50-hw-management-events.rules | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/usr/lib/udev/rules.d/50-hw-management-events.rules b/usr/lib/udev/rules.d/50-hw-management-events.rules +index cf4219e..33ea1bc 100644 +--- a/usr/lib/udev/rules.d/50-hw-management-events.rules ++++ b/usr/lib/udev/rules.d/50-hw-management-events.rules +@@ -269,3 +269,4 @@ SUBSYSTEM=="i2c", DEVPATH=="/devices/platform/mlxplat/i2c_mlxcpld*/i2c-*/i2c-*/* + # SDK + SUBSYSTEM=="pci", DRIVERS=="sx_core", ACTION=="add", RUN+="/usr/bin/hw-management-thermal-events.sh add sxcore add" + SUBSYSTEM=="pci", DRIVERS=="sx_core", ACTION=="remove", RUN+="/usr/bin/hw-management-thermal-events.sh rm sxcore remove" ++SUBSYSTEM=="pci", DRIVERS=="sx_core", ACTION=="offline", RUN+="/usr/bin/hw-management-thermal-events.sh rm sxcore remove" +-- +1.9.1 + diff --git a/platform/mellanox/hw-management/Makefile b/platform/mellanox/hw-management/Makefile new file mode 100644 index 000000000000..eb087b47bfff --- /dev/null +++ b/platform/mellanox/hw-management/Makefile @@ -0,0 +1,14 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = hw-management_1.mlnx.$(MLNX_HW_MANAGEMENT_VERSION)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + + pushd hw-mgmt + git am ../*.patch + chmod +x ./debian/rules + KVERSION=$(KVERSION) dpkg-buildpackage -us -uc -b -rfakeroot -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $* $(DEST)/ diff --git a/platform/mellanox/hw-management/hw-mgmt b/platform/mellanox/hw-management/hw-mgmt new file mode 160000 index 000000000000..dec7935777b5 --- /dev/null +++ b/platform/mellanox/hw-management/hw-mgmt @@ -0,0 +1 @@ +Subproject commit dec7935777b52d31a2220bad8b0cec4b71ec0961 diff --git a/platform/mellanox/issu-version.dep b/platform/mellanox/issu-version.dep new file mode 100644 index 000000000000..c4a178aef712 --- /dev/null +++ b/platform/mellanox/issu-version.dep @@ -0,0 +1,10 @@ +# DPKG FRK + +SPATH := $($(ISSU_VERSION_FILE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/issu-version.mk $(PLATFORM_PATH)/issu-version.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(ISSU_VERSION_FILE)_CACHE_MODE := GIT_CONTENT_SHA +$(ISSU_VERSION_FILE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(ISSU_VERSION_FILE)_DEP_FILES := $(DEP_FILES) diff --git a/platform/mellanox/issu-version.mk b/platform/mellanox/issu-version.mk new file mode 100644 index 000000000000..db368ffd8c10 --- /dev/null +++ b/platform/mellanox/issu-version.mk @@ -0,0 +1,10 @@ +# ISSU version + +ISSU_VERSION_FILE = issu-version +$(ISSU_VERSION_FILE)_SRC_PATH = $(PLATFORM_PATH)/issu-version +$(ISSU_VERSION_FILE)_DEPENDS += $(APPLIBS) +SONIC_MAKE_FILES += $(ISSU_VERSION_FILE) + +MLNX_FILES += $(ISSU_VERSION_FILE) + +export ISSU_VERSION_FILE diff --git a/platform/mellanox/issu-version/Makefile b/platform/mellanox/issu-version/Makefile new file mode 100644 index 000000000000..1f7d7fba3a3f --- /dev/null +++ b/platform/mellanox/issu-version/Makefile @@ -0,0 +1,12 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = issu-version + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + sx_sdk --version | egrep -o 'ISSU [0-9]+' > $(DEST)/$(MAIN_TARGET) || { + echo "ISSU version is undefined: $(sx_sdk --version)" + rm $(DEST)/$(MAIN_TARGET) + exit 1 + } diff --git a/platform/mellanox/libsaithrift-dev.dep b/platform/mellanox/libsaithrift-dev.dep new file mode 100644 index 000000000000..a6fd20007c77 --- /dev/null +++ b/platform/mellanox/libsaithrift-dev.dep @@ -0,0 +1,32 @@ +# DPKG FRK + +SPATH := $($(LIBSAITHRIFT_DEV)_SRC_PATH) +SLINKS := $(shell find $(SPATH) -type l -exec echo {} \; | grep -Ev ' ') +SMDEP_PATHS := $(SPATH) $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git submodule status --recursive | awk '{print $$2}' | grep -Ev ' ')) +SMDEP_FILES := $(foreach path,$(SMDEP_PATHS),$(filter-out $(SMDEP_PATHS),$(addprefix $(path)/,$(shell cd $(path) && git ls-files | grep -Ev ' ')))) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/libsaithrift-dev.mk $(PLATFORM_PATH)/libsaithrift-dev.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) + +$(LIBSAITHRIFT_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBSAITHRIFT_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBSAITHRIFT_DEV)_DEP_FILES := $(DEP_FILES) +$(LIBSAITHRIFT_DEV)_SMDEP_FILES := $(filter-out $(SLINKS),$(SMDEP_FILES)) +$(LIBSAITHRIFT_DEV)_SMDEP_PATHS := $(SMDEP_PATHS) + +$(PYTHON_SAITHRIFT)_CACHE_MODE := GIT_CONTENT_SHA +$(PYTHON_SAITHRIFT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(PYTHON_SAITHRIFT)_DEP_FILES := $(DEP_FILES) +$(PYTHON_SAITHRIFT)_SMDEP_FILES := $(filter-out $(SLINKS),$(SMDEP_FILES)) +$(PYTHON_SAITHRIFT)_SMDEP_PATHS := $(SMDEP_PATHS) + +$(SAISERVER)_CACHE_MODE := GIT_CONTENT_SHA +$(SAISERVER)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SAISERVER)_DEP_FILES := $(DEP_FILES) +$(SAISERVER)_SMDEP_FILES := $(filter-out $(SLINKS),$(SMDEP_FILES)) +$(SAISERVER)_SMDEP_PATHS := $(SMDEP_PATHS) + +$(SAISERVER_DBG)_CACHE_MODE := GIT_CONTENT_SHA +$(SAISERVER_DBG)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SAISERVER_DBG)_DEP_FILES := $(DEP_FILES) +$(SAISERVER_DBG)_SMDEP_FILES := $(filter-out $(SLINKS),$(SMDEP_FILES)) +$(SAISERVER_DBG)_SMDEP_PATHS := $(SMDEP_PATHS) diff --git a/platform/mellanox/libsaithrift-dev.mk b/platform/mellanox/libsaithrift-dev.mk new file mode 100644 index 000000000000..b0ef5746db73 --- /dev/null +++ b/platform/mellanox/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_amd64.deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(MLNX_SAI) $(MLNX_SAI_DEV) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(MLNX_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_amd64.deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_amd64.deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(MLNX_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_amd64.deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/mellanox/mft.dep b/platform/mellanox/mft.dep new file mode 100644 index 000000000000..7dcdaf1d305d --- /dev/null +++ b/platform/mellanox/mft.dep @@ -0,0 +1,18 @@ +# DPKG FRK + +SPATH := $($(MFT)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/mft.mk $(PLATFORM_PATH)/mft.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(MFT)_CACHE_MODE := GIT_CONTENT_SHA +$(MFT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MFT)_DEP_FILES := $(DEP_FILES) + +$(KERNEL_MFT)_CACHE_MODE := GIT_CONTENT_SHA +$(KERNEL_MFT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(KERNEL_MFT)_DEP_FILES := $(DEP_FILES) + +$(MFT_OEM)_CACHE_MODE := GIT_CONTENT_SHA +$(MFT_OEM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MFT_OEM)_DEP_FILES := $(DEP_FILES) diff --git a/platform/mellanox/mft.mk b/platform/mellanox/mft.mk new file mode 100644 index 000000000000..4529343931e3 --- /dev/null +++ b/platform/mellanox/mft.mk @@ -0,0 +1,17 @@ +# Mellanox SAI + +MFT_VERSION = 4.15.3 +MFT_REVISION = 3 + +export MFT_VERSION MFT_REVISION + +MFT = mft_$(MFT_VERSION)-$(MFT_REVISION)_amd64.deb +$(MFT)_SRC_PATH = $(PLATFORM_PATH)/mft +$(MFT)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_MAKE_DEBS += $(MFT) + +KERNEL_MFT = kernel-mft-dkms-modules-$(KVERSION)_$(MFT_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(MFT),$(KERNEL_MFT))) + +MFT_OEM = mft-oem_$(MFT_VERSION)-$(MFT_REVISION)_amd64.deb +$(eval $(call add_derived_package,$(MFT),$(MFT_OEM))) diff --git a/platform/mellanox/mft/Makefile b/platform/mellanox/mft/Makefile new file mode 100644 index 000000000000..84a587730386 --- /dev/null +++ b/platform/mellanox/mft/Makefile @@ -0,0 +1,54 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MFT_NAME = mft-$(MFT_VERSION)-$(MFT_REVISION)-x86_64-deb +MFT_TGZ = $(MFT_NAME).tgz + +SRC_DEB = kernel-mft-dkms_$(MFT_VERSION)-$(MFT_REVISION)_all.deb +MOD_DEB = kernel-mft-dkms-modules-$(KVERSION)_$(MFT_VERSION)_amd64.deb + +MAIN_TARGET = mft_$(MFT_VERSION)-$(MFT_REVISION)_amd64.deb +DERIVED_TARGETS = $(MOD_DEB) mft-oem_$(MFT_VERSION)-$(MFT_REVISION)_amd64.deb + +DKMS_BMDEB = /var/lib/dkms/kernel-mft-dkms/$(MFT_VERSION)/bmdeb +DKMS_TMP := $(shell mktemp -u -d -t dkms.XXXXXXXXXX) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf $(MFT_NAME) + wget -O $(MFT_TGZ) http://www.mellanox.com/downloads/MFT/$(MFT_TGZ) + tar xzf $(MFT_TGZ) + + pushd $(MFT_NAME)/SDEBS + + # put a lock here because dpkg does not allow installing packages in parallel + while true; do + if mkdir $(DEST)/dpkg_lock &> /dev/null; then + { sudo dpkg -i $(SRC_DEB) && rm -d $(DEST)/dpkg_lock && break; } || { rm -d $(DEST)/dpkg_lock && exit 1 ; } + fi + done + + popd + + sudo dkms build kernel-mft-dkms/$(MFT_VERSION) -k $(KVERSION) -a amd64 + sudo dkms mkbmdeb kernel-mft-dkms/$(MFT_VERSION) -k $(KVERSION) -a amd64 + + # w/a: remove dependencies + mkdir -p $(DKMS_TMP)/DEBIAN + + dpkg -e $(DKMS_BMDEB)/$(MOD_DEB) $(DKMS_TMP)/DEBIAN + dpkg -x $(DKMS_BMDEB)/$(MOD_DEB) $(DKMS_TMP) + + sed -i '/^Depends:/c\Depends:' $(DKMS_TMP)/DEBIAN/control + + pushd $(MFT_NAME)/DEBS + dpkg -b $(DKMS_TMP) . + popd + + rm -rf $(DKMS_TMP) + + # fix timestamp because we do not actually build tools, only kernel + touch $(MFT_NAME)/DEBS/*.deb + mv $(MFT_NAME)/DEBS/*.deb $(DEST) + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/mlnx-ffb.dep b/platform/mellanox/mlnx-ffb.dep new file mode 100644 index 000000000000..efaadd2767ae --- /dev/null +++ b/platform/mellanox/mlnx-ffb.dep @@ -0,0 +1,10 @@ +# DPKG FRK + +DPATH := $($(MLNX_FFB_SCRIPT)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/mlnx-ffb.mk $(PLATFORM_PATH)/mlnx-ffb.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(addprefix $(DPATH),$(MLNX_FFB_SCRIPT)) + +$(MLNX_FFB_SCRIPT)_CACHE_MODE := GIT_CONTENT_SHA +$(MLNX_FFB_SCRIPT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MLNX_FFB_SCRIPT)_DEP_FILES := $(DEP_FILES) diff --git a/platform/mellanox/mlnx-ffb.mk b/platform/mellanox/mlnx-ffb.mk new file mode 100755 index 000000000000..6c3c925b5996 --- /dev/null +++ b/platform/mellanox/mlnx-ffb.mk @@ -0,0 +1,9 @@ +# mellanox fast fast boot script + +MLNX_FFB_SCRIPT = mlnx-ffb.sh +$(MLNX_FFB_SCRIPT)_PATH = $(PLATFORM_PATH)/ +SONIC_COPY_FILES += $(MLNX_FFB_SCRIPT) + +MLNX_FILES += $(MLNX_FFB_SCRIPT) + +export MLNX_FFB_SCRIPT diff --git a/platform/mellanox/mlnx-ffb.sh b/platform/mellanox/mlnx-ffb.sh new file mode 100755 index 000000000000..d0bef9d57761 --- /dev/null +++ b/platform/mellanox/mlnx-ffb.sh @@ -0,0 +1,89 @@ +#!/bin/bash + +FFB_SUCCESS=0 +FFB_FAILURE=1 + +# Check if ISSU is enabled on this device +check_issu_enabled() +{ + CHECK_RESULT="${FFB_FAILURE}" + ISSU_CHECK_CMD="show platform mlnx issu" + + # Check whether show ISSU status outputs ENABLED + if [[ `$ISSU_CHECK_CMD` =~ "enabled" ]]; then + # ISSU enabled, return success + CHECK_RESULT="${FFB_SUCCESS}" + fi + + return "${CHECK_RESULT}" +} + +# Check if ISSU upgrade from current SDK to next image SDK is supported +check_sdk_upgrade() +{ + CHECK_RESULT="${FFB_FAILURE}" + + NEXT_SONIC_IMAGE="$(sonic-installer list | grep "Next: " | cut -f2 -d' ')" + CURRENT_SONIC_IMAGE="$(sonic-installer list | grep "Current: " | cut -f2 -d' ')" + + FS_PATH="/host/image-${NEXT_SONIC_IMAGE#SONiC-OS-}/fs.squashfs" + FS_MOUNTPOINT="/tmp/image-${NEXT_SONIC_IMAGE#SONiC-OS-}-fs" + + if [[ "${CURRENT_SONIC_IMAGE}" == "${NEXT_SONIC_IMAGE}" ]]; then + return "${FFB_SUCCESS}" + fi + + while :; do + mkdir -p "${FS_MOUNTPOINT}" + mount -t squashfs "${FS_PATH}" "${FS_MOUNTPOINT}" || { + >&2 echo "Failed to mount next SONiC image" + break + } + + ISSU_VERSION_FILE_PATH="/etc/mlnx/issu-version" + + [ -f "${ISSU_VERSION_FILE_PATH}" ] || { + >&2 echo "No ISSU version file found ${ISSU_VERSION_FILE_PATH}" + break + } + + [ -f "${FS_MOUNTPOINT}/${ISSU_VERSION_FILE_PATH}" ] || { + >&2 echo "No ISSU version file found ${ISSU_VERSION_FILE_PATH} in ${NEXT_SONIC_IMAGE}" + break + } + + CURRENT_ISSU_VERSION="$(cat ${ISSU_VERSION_FILE_PATH})" + NEXT_ISSU_VERSION="$(cat ${FS_MOUNTPOINT}/${ISSU_VERSION_FILE_PATH})" + + if [[ "${CURRENT_ISSU_VERSION}" == "${NEXT_ISSU_VERSION}" ]]; then + CHECK_RESULT="${FFB_SUCCESS}" + else + >&2 echo "Current and next ISSU version do not match:" + >&2 echo "Current ISSU version: ${CURRENT_ISSU_VERSION}" + >&2 echo "Next ISSU version: ${NEXT_ISSU_VERSION}" + fi + + break + done + + umount -rf "${FS_MOUNTPOINT}" 2> /dev/null || true + rm -rf "${FS_MOUNTPOINT}" 2> /dev/null || true + + return "${CHECK_RESULT}" +} + +check_ffb() +{ + check_issu_enabled || { + >&2 echo "ISSU is not enabled on this HWSKU" + return "${FFB_FAILURE}" + } + + check_sdk_upgrade || { + >&2 echo "SDK upgrade check failued" + return "${FFB_FAILURE}" + } + + return "${FFB_SUCCESS}" +} + diff --git a/platform/mellanox/mlnx-fw-upgrade.j2 b/platform/mellanox/mlnx-fw-upgrade.j2 new file mode 100755 index 000000000000..245ce75d5f18 --- /dev/null +++ b/platform/mellanox/mlnx-fw-upgrade.j2 @@ -0,0 +1,271 @@ +#!/bin/bash + +declare -r SCRIPT_NAME="$(basename "$0")" +declare -r SCRIPT_PATH="$(readlink -f "$0")" +declare -r SCRIPT_DIR="$(dirname "$SCRIPT_PATH")" + +declare -r YES_PARAM="yes" +declare -r NO_PARAM="no" + +declare -r VERBOSE_ERROR="1" +declare -r VERBOSE_WARNING="2" +declare -r VERBOSE_NOTICE="3" +declare -r VERBOSE_INFO="4" + +declare -r VERBOSE_MAX="${VERBOSE_INFO}" +declare -r VERBOSE_MIN="${VERBOSE_ERROR}" + +declare -r EXIT_SUCCESS="0" +declare -r EXIT_FAILURE="1" + +declare -r QUERY_CMD="mlxfwmanager --query" +declare -r LIST_CONTENT_CMD="mlxfwmanager --list-content" +declare -r BURN_CMD="mlxfwmanager -u -f -y" + +declare -r QUERY_FILE="/tmp/mlxfwmanager-query.log" +declare -r LIST_CONTENT_FILE="/tmp/mlxfwmanager-list-content.log" + +declare -r SPC1_ASIC="spc1" +declare -r SPC2_ASIC="spc2" +declare -r SPC3_ASIC="spc3" +declare -r UNKN_ASIC="unknown" +declare -r UNKN_MST="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" \ +) + +IMAGE_UPGRADE="${NO_PARAM}" +VERBOSE_LEVEL="${VERBOSE_MIN}" + +function PrintHelp() { + echo + echo "Usage: ./${SCRIPT_NAME} [OPTIONS]" + echo + echo "OPTIONS:" + echo " -u, --upgrade Upgrade ASIC firmware using next boot image (useful after SONiC-To-SONiC update)" + echo " -v, --verbose Verbose mode" + echo " -h, --help Print help" + echo + echo "Examples:" + echo " ./${SCRIPT_NAME} --verbose" + echo " ./${SCRIPT_NAME} --upgrade" + echo " ./${SCRIPT_NAME} --help" + echo +} + +function ParseArguments() { + while [ "$#" -ge "1" ]; do + case "$1" in + -u|--upgrade) + IMAGE_UPGRADE="${YES_PARAM}" + ;; + -v|--verbose) + VERBOSE_LEVEL="${VERBOSE_MAX}" + ;; + -h|--help) + PrintHelp + exit "${EXIT_SUCCESS}" + ;; + esac + shift + done +} + +function LogError() { + if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_ERROR}" ]]; then + echo "ERROR: $*" + fi +} + +function LogWarning() { + if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_WARNING}" ]]; then + echo "WARNING: $*" + fi +} + +function LogNotice() { + if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_NOTICE}" ]]; then + echo "NOTICE: $*" + fi +} + +function LogInfo() { + if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_INFO}" ]]; then + echo "INFO: $*" + fi +} + +function ExitFailure() { + if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_ERROR}" ]]; then + echo + LogError "$@" + echo + fi + + exit "${EXIT_FAILURE}" +} + +function ExitSuccess() { + if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_INFO}" ]]; then + echo + LogInfo "$@" + echo + fi + + exit "${EXIT_SUCCESS}" +} + +function WaitForDevice() { + local -i QUERY_RETRY_COUNT_MAX="10" + local -i QUERY_RETRY_COUNT="0" + + ${QUERY_CMD} > /dev/null + + while [[ ("${QUERY_RETRY_COUNT}" -lt "${QUERY_RETRY_COUNT_MAX}") && ("$?" -ne "${EXIT_SUCCESS}") ]]; do + sleep 1s + ((QUERY_RETRY_COUNT++)) + ${QUERY_CMD} > /dev/null + done +} + +function GetAsicType() { + local -r VENDOR_ID="15b3" + + 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}" + exit "${EXIT_SUCCESS}" + 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}" + exit "${EXIT_FAILURE}" +} + +function GetMstDevice() { + local _MST_DEVICE="$(ls /dev/mst/*_pci_cr0 2>&1)" + + if [[ ! -c "${_MST_DEVICE}" ]]; then + echo "${UNKN_MST}" + else + echo "${_MST_DEVICE}" + fi + + exit "${EXIT_SUCCESS}" +} + +function RunCmd() { + local ERROR_CODE="${EXIT_SUCCESS}" + + if [[ "${VERBOSE_LEVEL}" -eq "${VERBOSE_MAX}" ]]; then + eval "$@" + else + eval "$@" &>/dev/null + fi + + ERROR_CODE="$?" + if [[ "${ERROR_CODE}" != "${EXIT_SUCCESS}" ]]; then + ExitFailure "command failed: $@" + fi +} + +function UpgradeFW() { + local -r _FS_MOUNTPOINT="$1" + + local -r _ASIC_TYPE="$(GetAsicType)" + if [[ "${_ASIC_TYPE}" = "${UNKN_ASIC}" ]]; then + ExitFailure "failed to detect ASIC type" + fi + + if [ ! -z "${_FS_MOUNTPOINT}" ]; then + local -r _FW_FILE="${_FS_MOUNTPOINT}/${FW_FILE_MAP[$_ASIC_TYPE]}" + else + local -r _FW_FILE="${FW_FILE_MAP[$_ASIC_TYPE]}" + fi + + if [ ! -f "${_FW_FILE}" ]; then + ExitFailure "no such file: ${_FW_FILE}" + fi + + RunCmd "${QUERY_CMD} -o ${QUERY_FILE}" + local -r _FW_CURRENT_INFO="$(grep FW ${QUERY_FILE})" + local -r _FW_CURRENT="$(echo ${_FW_CURRENT_INFO} | cut -f2 -d' ')" + local -r _PSID_INFO="$(grep PSID ${QUERY_FILE})" + local -r _PSID="$(echo ${_PSID_INFO} | cut -f2 -d' ')" + + RunCmd "${LIST_CONTENT_CMD} -i ${_FW_FILE} -o ${LIST_CONTENT_FILE}" + local -r _FW_AVAILABLE_INFO="$(grep ${_PSID} ${LIST_CONTENT_FILE})" + local -r _FW_AVAILABLE="$(echo ${_FW_AVAILABLE_INFO} | cut -f4 -d' ')" + + if [[ -z "${_FW_CURRENT}" ]]; then + ExitFailure "could not retreive current FW version" + fi + + if [[ -z "${_FW_AVAILABLE}" ]]; then + ExitFailure "could not retreive available FW version" + fi + + if [[ "${_FW_CURRENT}" == "${_FW_AVAILABLE}" ]]; then + ExitSuccess "firmware is up to date" + else + LogNotice "firmware upgrade is required. Installing compatible version..." + local -r _MST_DEVICE="$(GetMstDevice)" + if [[ "${_MST_DEVICE}" = "${UNKN_MST}" ]]; then + LogWarning "could not find fastest mst device, using default device" + RunCmd "${BURN_CMD} -i ${_FW_FILE}" + else + RunCmd "${BURN_CMD} -d ${_MST_DEVICE} -i ${_FW_FILE}" + fi + fi +} + +function UpgradeFWFromImage() { + local -r _NEXT_SONIC_IMAGE="$(sonic-installer list | grep "Next: " | cut -f2 -d' ')" + local -r _CURRENT_SONIC_IMAGE="$(sonic-installer list | grep "Current: " | cut -f2 -d' ')" + + local -r _FS_PATH="/host/image-${_NEXT_SONIC_IMAGE#SONiC-OS-}/fs.squashfs" + local -r _FS_MOUNTPOINT="/tmp/image-${_NEXT_SONIC_IMAGE#SONiC-OS-}-fs" + + if [[ "${_CURRENT_SONIC_IMAGE}" == "${_NEXT_SONIC_IMAGE}" ]]; then + ExitSuccess "firmware is up to date" + else + mkdir -p "${_FS_MOUNTPOINT}" + mount -t squashfs "${_FS_PATH}" "${_FS_MOUNTPOINT}" + + UpgradeFW "${_FS_MOUNTPOINT}" + + umount -rf "${_FS_MOUNTPOINT}" + rm -rf "${_FS_MOUNTPOINT}" + fi +} + +function ExitIfQEMU() { + if [[ $(cat /sys/devices/virtual/dmi/id/chassis_vendor) = "QEMU" ]]; then + ExitSuccess "No FW upgrade for SimX platform" + fi +} + +ParseArguments "$@" + +ExitIfQEMU + +WaitForDevice + +if [ "${IMAGE_UPGRADE}" != "${YES_PARAM}" ]; then + UpgradeFW +else + UpgradeFWFromImage +fi + +ExitSuccess "firmware upgrade is completed" diff --git a/platform/mellanox/mlnx-onie-fw-update.dep b/platform/mellanox/mlnx-onie-fw-update.dep new file mode 100644 index 000000000000..f22352ed0cba --- /dev/null +++ b/platform/mellanox/mlnx-onie-fw-update.dep @@ -0,0 +1,10 @@ +# DPKG FRK + +DPATH := $($(MLNX_ONIE_FW_UPDATE)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/mlnx-onie-fw-update.mk $(PLATFORM_PATH)/mlnx-onie-fw-update.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(addprefix $(DPATH),$(MLNX_ONIE_FW_UPDATE)) + +$(MLNX_ONIE_FW_UPDATE)_CACHE_MODE := GIT_CONTENT_SHA +$(MLNX_ONIE_FW_UPDATE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MLNX_ONIE_FW_UPDATE)_DEP_FILES := $(DEP_FILES) diff --git a/platform/mellanox/mlnx-onie-fw-update.mk b/platform/mellanox/mlnx-onie-fw-update.mk new file mode 100644 index 000000000000..13f68ce4671f --- /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_PATH)/ +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..0abc55ef76b4 --- /dev/null +++ b/platform/mellanox/mlnx-onie-fw-update.sh @@ -0,0 +1,205 @@ +#!/bin/bash + +# Copyright (C) 2019 Mellanox Technologies Ltd. +# Copyright (C) 2019 Michael Shych +# +# SPDX-License-Identifier: GPL-2.0 + +this_script="$(basename $(realpath ${0}))" +lock_file="/var/run/${this_script%.*}.lock" + +onie_mount=/mnt/onie-boot +onie_lib=/lib/onie +os_boot=/host + +print_help() { +cat <${lock_file} + /usr/bin/flock -x ${lock_fd} + register_unlock_handler ${lock_fd} +} + +# Multiprocessing synchronization +lock_script_state_change + +# Process command arguments +cmd="${1}" + +# Optional argument +arg="${2}" + +if [[ -z "${cmd}" ]]; then + # Default to 'show' if no command is specified. + cmd="show" +fi + +case "${cmd}" in + add|remove) + if [[ -z "${arg}" ]]; then + echo "ERROR: This command requires a firmware update file name" + echo "Run: '${this_script} help' for complete details" + exit 1 + fi + ;; + update) + enable_onie_access + show_pending + rc=$? + if [[ ${rc} -ne 0 ]]; then + enable_onie_fw_update_mode + rc=$? + disable_onie_access + if [[ ${rc} -eq 0 ]]; then + system_reboot + else + echo "ERROR: failed to enable ONIE firmware update mode" + exit ${rc} + fi + else + echo "ERROR: No firmware images for update" + echo "Run: '${this_script} add ' before update" + disable_onie_access + exit 1 + fi + ;; + purge|show-pending|show-results|show|show-log|help) + ;; + *) + echo "ERROR: Unknown command: ${cmd}" + exit 1 + ;; +esac + +enable_onie_access +${onie_mount}/onie/tools/bin/onie-fwpkg "$@" +rc=$? +if [[ "${cmd}" = "help" ]]; then + print_help +fi +disable_onie_access + +exit ${rc} diff --git a/platform/mellanox/mlnx-platform-api.dep b/platform/mellanox/mlnx-platform-api.dep new file mode 100644 index 000000000000..b66c0b9c3bdf --- /dev/null +++ b/platform/mellanox/mlnx-platform-api.dep @@ -0,0 +1,15 @@ +# DPKG FRK + +SPATH := $($(SONIC_PLATFORM_API_PY2)_SRC_PATH) +SLINKS := $(shell find $(SPATH) -type l -exec echo {} \; | grep -Ev ' ') +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/mlnx-platform-api.mk $(PLATFORM_PATH)/mlnx-platform-api.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH) | grep -Ev ' ') + +$(SONIC_PLATFORM_API_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_PLATFORM_API_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_PLATFORM_API_PY2)_DEP_FILES := $(filter-out $(SLINKS),$(DEP_FILES)) + +$(SONIC_PLATFORM_API_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_PLATFORM_API_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_PLATFORM_API_PY3)_DEP_FILES := $(filter-out $(SLINKS),$(DEP_FILES)) diff --git a/platform/mellanox/mlnx-platform-api.mk b/platform/mellanox/mlnx-platform-api.mk new file mode 100644 index 000000000000..e7e36c1f67b8 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api.mk @@ -0,0 +1,19 @@ +# SONIC_PLATFORM_API_PY2 package + +SONIC_PLATFORM_API_PY2 = mlnx_platform_api-1.0-py2-none-any.whl +$(SONIC_PLATFORM_API_PY2)_SRC_PATH = $(PLATFORM_PATH)/mlnx-platform-api +$(SONIC_PLATFORM_API_PY2)_PYTHON_VERSION = 2 +$(SONIC_PLATFORM_API_PY2)_DEPENDS = $(SONIC_PY_COMMON_PY2) $(SONIC_PLATFORM_COMMON_PY2) $(SONIC_CONFIG_ENGINE_PY2) +SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY2) + +export mlnx_platform_api_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_API_PY2))" + +# SONIC_PLATFORM_API_PY3 package + +SONIC_PLATFORM_API_PY3 = mlnx_platform_api-1.0-py3-none-any.whl +$(SONIC_PLATFORM_API_PY3)_SRC_PATH = $(PLATFORM_PATH)/mlnx-platform-api +$(SONIC_PLATFORM_API_PY3)_PYTHON_VERSION = 3 +$(SONIC_PLATFORM_API_PY3)_DEPENDS = $(SONIC_PY_COMMON_PY3) $(SONIC_PLATFORM_COMMON_PY3) $(SONIC_CONFIG_ENGINE_PY3) $(SONIC_PLATFORM_API_PY2) +SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY3) + +export mlnx_platform_api_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_API_PY3))" diff --git a/platform/mellanox/mlnx-platform-api/.gitignore b/platform/mellanox/mlnx-platform-api/.gitignore new file mode 100644 index 000000000000..07f8a98e1f4a --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/.gitignore @@ -0,0 +1,2 @@ +*.pyc +.cache/ diff --git a/platform/mellanox/mlnx-platform-api/pytest.ini b/platform/mellanox/mlnx-platform-api/pytest.ini new file mode 100644 index 000000000000..c24fe5bb9e65 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +filterwarnings = + ignore::DeprecationWarning diff --git a/platform/mellanox/mlnx-platform-api/setup.cfg b/platform/mellanox/mlnx-platform-api/setup.cfg new file mode 100644 index 000000000000..b7e478982ccf --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/setup.cfg @@ -0,0 +1,2 @@ +[aliases] +test=pytest diff --git a/platform/mellanox/mlnx-platform-api/setup.py b/platform/mellanox/mlnx-platform-api/setup.py new file mode 100644 index 000000000000..df1a8cadbb09 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/setup.py @@ -0,0 +1,40 @@ +from setuptools import setup + +setup( + name='mlnx-platform-api', + version='1.0', + description='SONiC platform API implementation on Mellanox platform', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + maintainer='Kevin Wang', + maintainer_email='kevinw@mellanox.com', + packages=[ + 'sonic_platform', + 'tests' + ], + setup_requires= [ + 'pytest-runner' + ], + tests_require = [ + 'pytest', + 'mock>=2.0.0' + ], + 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', + 'Programming Language :: Python :: 3.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', + test_suite='setup.get_test_suite' +) + diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/__init__.py b/platform/mellanox/mlnx-platform-api/sonic_platform/__init__.py new file mode 100644 index 000000000000..d82f3749319c --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py new file mode 100644 index 000000000000..b5ca79286d1f --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -0,0 +1,538 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Chassis information which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform_base.component_base import ComponentBase + from sonic_py_common import device_info + from sonic_py_common.logger import Logger + from os import listdir + from os.path import isfile, join + import sys + import io + import re + import syslog +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +MAX_SELECT_DELAY = 3600 + +MLNX_NUM_PSU = 2 + +EEPROM_CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +EEPROM_CACHE_FILE = 'syseeprom_cache' + +HWMGMT_SYSTEM_ROOT = '/var/run/hw-management/system/' + +MST_DEVICE_NAME_PATTERN = '/dev/mst/mt[0-9]*_pciconf0' +MST_DEVICE_RE_PATTERN = '/dev/mst/mt([0-9]*)_pciconf0' +SPECTRUM1_CHIP_ID = '52100' + +#reboot cause related definitions +REBOOT_CAUSE_ROOT = HWMGMT_SYSTEM_ROOT + +REBOOT_CAUSE_FILE_LENGTH = 1 + +# Global logger class instance +logger = Logger() + +# magic code defnition for port number, qsfp port position of each Platform +# port_position_tuple = (PORT_START, QSFP_PORT_START, PORT_END, PORT_IN_BLOCK, EEPROM_OFFSET) +platform_dict_port = {'x86_64-mlnx_msn2010-r0': 3, 'x86_64-mlnx_msn2100-r0': 1, 'x86_64-mlnx_msn2410-r0': 2, 'x86_64-mlnx_msn2700-r0': 0, 'x86_64-mlnx_lssn2700':0, 'x86_64-mlnx_msn2740-r0': 0, 'x86_64-mlnx_msn3420-r0':5, 'x86_64-mlnx_msn3700-r0': 0, 'x86_64-mlnx_msn3700c-r0': 0, 'x86_64-mlnx_msn3800-r0': 4, 'x86_64-mlnx_msn4600c-r0':4, 'x86_64-mlnx_msn4700-r0': 0, 'x86_64-mlnx_msn4410-r0': 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), (0, 48, 59, 60, 1)] + +class Chassis(ChassisBase): + """Platform-specific Chassis class""" + + # System status LED + _led = None + + def __init__(self): + super(Chassis, self).__init__() + + self.name = "Undefined" + self.model = "Undefined" + + # Initialize Platform name + self.platform_name = device_info.get_platform() + + # move the initialization of each components to their dedicated initializer + # which will be called from platform + self.sfp_module_initialized = False + self.sfp_event_initialized = False + self.reboot_cause_initialized = False + self.sdk_handle = None + logger.log_info("Chassis loaded successfully") + + + def __del__(self): + if self.sfp_event_initialized: + self.sfp_event.deinitialize() + + if self.sdk_handle: + from sonic_platform.sfp import deinitialize_sdk_handle + deinitialize_sdk_handle(self.sdk_handle) + + + def initialize_psu(self): + from sonic_platform.psu import Psu + # Initialize PSU list + self.psu_module = Psu + for index in range(MLNX_NUM_PSU): + psu = Psu(index, self.platform_name) + self._psu_list.append(psu) + + + def initialize_fan(self): + from .device_data import DEVICE_DATA + from sonic_platform.fan import Fan + from .fan_drawer import RealDrawer, VirtualDrawer + + fan_data = DEVICE_DATA[self.platform_name]['fans'] + drawer_num = fan_data['drawer_num'] + drawer_type = fan_data['drawer_type'] + fan_num_per_drawer = fan_data['fan_num_per_drawer'] + drawer_ctor = RealDrawer if drawer_type == 'real' else VirtualDrawer + fan_index = 0 + for drawer_index in range(drawer_num): + drawer = drawer_ctor(drawer_index, fan_data) + self._fan_drawer_list.append(drawer) + for index in range(fan_num_per_drawer): + fan = Fan(fan_index, drawer, index + 1) + fan_index += 1 + drawer._fan_list.append(fan) + self._fan_list.append(fan) + + + def initialize_sfp(self): + from sonic_platform.sfp import SFP + + self.sfp_module = SFP + + # Initialize SFP list + port_position_tuple = self._get_port_position_tuple_by_platform_name() + self.PORT_START = port_position_tuple[0] + self.QSFP_PORT_START = port_position_tuple[1] + self.PORT_END = port_position_tuple[2] + self.PORTS_IN_BLOCK = port_position_tuple[3] + + for index in range(self.PORT_START, self.PORT_END + 1): + if index in range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1): + sfp_module = SFP(index, 'QSFP', self.get_sdk_handle, self.platform_name) + else: + sfp_module = SFP(index, 'SFP', self.get_sdk_handle, self.platform_name) + + self._sfp_list.append(sfp_module) + + self.sfp_module_initialized = True + + + def get_sdk_handle(self): + if not self.sdk_handle: + from sonic_platform.sfp import initialize_sdk_handle + self.sdk_handle = initialize_sdk_handle() + if self.sdk_handle is None: + logger.log_error('Failed to open SDK handle') + return self.sdk_handle + + + def initialize_thermals(self): + from sonic_platform.thermal import initialize_chassis_thermals + # Initialize thermals + initialize_chassis_thermals(self.platform_name, self._thermal_list) + + + def initialize_eeprom(self): + from .eeprom import Eeprom + # Initialize EEPROM + self._eeprom = Eeprom() + # Get chassis name and model from eeprom + self.name = self._eeprom.get_product_name() + self.model = self._eeprom.get_part_number() + + + def initialize_components(self): + # Initialize component list + from sonic_platform.component import ComponentONIE, ComponentSSD, ComponentBIOS, ComponentCPLD + self._component_list.append(ComponentONIE()) + self._component_list.append(ComponentSSD()) + self._component_list.append(ComponentBIOS()) + self._component_list.extend(ComponentCPLD.get_component_list()) + + def initizalize_system_led(self): + from .led import SystemLed + Chassis._led = SystemLed() + + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return self.name + + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + return self.model + + ############################################## + # SFP methods + ############################################## + def get_num_sfps(self): + """ + Retrieves the number of sfps available on this chassis + + Returns: + An integer, the number of sfps available on this chassis + """ + if not self.sfp_module_initialized: + self.initialize_sfp() + return len(self._sfp_list) + + + def get_all_sfps(self): + """ + Retrieves all sfps available on this chassis + + Returns: + A list of objects derived from SfpBase representing all sfps + available on this chassis + """ + if not self.sfp_module_initialized: + self.initialize_sfp() + return self._sfp_list + + + 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, 1 for Ethernet0, 2 for Ethernet4 and so on. + + Returns: + An object dervied from SfpBase representing the specified sfp + """ + if not self.sfp_module_initialized: + self.initialize_sfp() + + sfp = None + index -= 1 + try: + sfp = self._sfp_list[index] + except IndexError: + sys.stderr.write("SFP index {} out of range (0-{})\n".format( + index, len(self._sfp_list)-1)) + + return sfp + + + def _extract_num_of_fans_and_fan_drawers(self): + num_of_fan = 0 + num_of_drawer = 0 + for f in listdir(self.fan_path): + if isfile(join(self.fan_path, f)): + match_obj = re.match('fan(\d+)_speed_get', f) + if match_obj != None: + if int(match_obj.group(1)) > num_of_fan: + num_of_fan = int(match_obj.group(1)) + else: + match_obj = re.match('fan(\d+)_status', f) + if match_obj != None and int(match_obj.group(1)) > num_of_drawer: + num_of_drawer = int(match_obj.group(1)) + + return num_of_fan, num_of_drawer + + def _get_port_position_tuple_by_platform_name(self): + position_tuple = port_position_tuple_list[platform_dict_port[self.platform_name]] + return position_tuple + + + def get_watchdog(self): + """ + Retrieves hardware watchdog device on this chassis + + Returns: + An object derived from WatchdogBase representing the hardware + watchdog device + + Note: + We overload this method to ensure that watchdog is only initialized + when it is referenced. Currently, only one daemon can open the watchdog. + To initialize watchdog in the constructor causes multiple daemon + try opening watchdog when loading and constructing a chassis object + and fail. By doing so we can eliminate that risk. + """ + try: + if self._watchdog is None: + from sonic_platform.watchdog import get_watchdog + self._watchdog = get_watchdog() + except Exception as e: + logger.log_info("Fail to load watchdog due to {}".format(repr(e))) + + return self._watchdog + + + 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_base_mac() + + + def get_serial(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_number() + + + 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_system_eeprom_info() + + + def _read_generic_file(self, filename, len): + """ + Read a generic file, returns the contents of the file + """ + result = '' + try: + fileobj = io.open(filename) + result = fileobj.read(len) + fileobj.close() + return result + except Exception as e: + logger.log_info("Fail to read file {} due to {}".format(filename, repr(e))) + return '0' + + + def _verify_reboot_cause(self, filename): + ''' + Open and read the reboot cause file in + /var/run/hwmanagement/system (which is defined as REBOOT_CAUSE_ROOT) + If a reboot cause file doesn't exists, returns '0'. + ''' + return bool(int(self._read_generic_file(join(REBOOT_CAUSE_ROOT, filename), REBOOT_CAUSE_FILE_LENGTH).rstrip('\n'))) + + + def initialize_reboot_cause(self): + self.reboot_major_cause_dict = { + 'reset_main_pwr_fail' : self.REBOOT_CAUSE_POWER_LOSS, + 'reset_aux_pwr_or_ref' : self.REBOOT_CAUSE_POWER_LOSS, + 'reset_asic_thermal' : self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC, + 'reset_hotswap_or_wd' : self.REBOOT_CAUSE_WATCHDOG, + 'reset_swb_wd' : self.REBOOT_CAUSE_WATCHDOG, + 'reset_sff_wd' : self.REBOOT_CAUSE_WATCHDOG + } + self.reboot_minor_cause_dict = { + 'reset_fw_reset' : "Reset by ASIC firmware", + 'reset_long_pb' : "Reset by long press on power button", + 'reset_short_pb' : "Reset by short press on power button", + 'reset_comex_thermal' : "ComEx thermal shutdown", + 'reset_comex_pwr_fail' : "ComEx power fail", + 'reset_comex_wd' : "Reset requested from ComEx", + 'reset_from_asic' : "Reset requested from ASIC", + 'reset_reload_bios' : "Reset caused by BIOS reload", + 'reset_hotswap_or_halt' : "Reset caused by hotswap or halt", + 'reset_from_comex' : "Reset from ComEx", + 'reset_voltmon_upgrade_fail': "Reset due to voltage monitor devices upgrade failure" + } + self.reboot_by_software = 'reset_sw_reset' + self.reboot_cause_initialized = True + + + 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. + """ + #read reboot causes files in the following order + if not self.reboot_cause_initialized: + self.initialize_reboot_cause() + + for reset_file, reset_cause in self.reboot_major_cause_dict.items(): + if self._verify_reboot_cause(reset_file): + return reset_cause, '' + + for reset_file, reset_cause in self.reboot_minor_cause_dict.items(): + if self._verify_reboot_cause(reset_file): + return self.REBOOT_CAUSE_HARDWARE_OTHER, reset_cause + + if self._verify_reboot_cause(self.reboot_by_software): + logger.log_info("Hardware reboot cause: the system was rebooted due to software requesting") + else: + logger.log_info("Hardware reboot cause: no hardware reboot cause found") + + return self.REBOOT_CAUSE_NON_HARDWARE, '' + + + def _show_capabilities(self): + """ + This function is for debug purpose + Some features require a xSFP module to support some capabilities but it's unrealistic to + check those modules one by one. + So this function is introduce to show some capabilities of all xSFP modules mounted on the device. + """ + for s in self._sfp_list: + try: + print("index {} tx disable {} dom {} calibration {} temp {} volt {} power (tx {} rx {})".format(s.index, + s.dom_tx_disable_supported, + s.dom_supported, + s.calibration, + s.dom_temp_supported, + s.dom_volt_supported, + s.dom_rx_power_supported, + s.dom_tx_power_supported + )) + except: + print("fail to retrieve capabilities for module index {}".format(s.index)) + + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + # Initialize SFP event first + if not self.sfp_event_initialized: + from sonic_platform.sfp_event import sfp_event + self.sfp_event = sfp_event() + self.sfp_event.initialize() + self.MAX_SELECT_EVENT_RETURNED = self.PORT_END + self.sfp_event_initialized = True + + wait_for_ever = (timeout == 0) + port_dict = {} + if wait_for_ever: + timeout = MAX_SELECT_DELAY + while True: + status = self.sfp_event.check_sfp_status(port_dict, timeout) + if bool(port_dict): + break + else: + status = self.sfp_event.check_sfp_status(port_dict, timeout) + + if status: + self.reinit_sfps(port_dict) + return True, {'sfp':port_dict} + else: + return True, {'sfp':{}} + + def reinit_sfps(self, port_dict): + """ + Re-initialize SFP if there is any newly inserted SFPs + :param port_dict: SFP event data + :return: + """ + # SFP not initialize yet, do nothing + if not self.sfp_module_initialized: + return + + from . import sfp + for index, status in port_dict.items(): + if status == sfp.SFP_STATUS_INSERTED: + try: + self.get_sfp(index).reinit() + except Exception as e: + logger.log_error("Fail to re-initialize SFP {} - {}".format(index, repr(e))) + + def get_thermal_manager(self): + from .thermal_manager import ThermalManager + return ThermalManager + + def set_status_led(self, color): + """ + Sets the state of the system LED + + Args: + color: A string representing the color with which to set the + system LED + + Returns: + bool: True if system LED state is set successfully, False if not + """ + return False if not Chassis._led else Chassis._led.set_status(color) + + def get_status_led(self): + """ + Gets the state of the system LED + + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + return None if not Chassis._led else Chassis._led.get_status() + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/component.py b/platform/mellanox/mlnx-platform-api/sonic_platform/component.py new file mode 100644 index 000000000000..e70007e96562 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/component.py @@ -0,0 +1,751 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# implementation of new platform api +############################################################################# + + +try: + import os + import io + import re + import sys + import glob + import tempfile + import subprocess + if sys.version_info[0] > 2: + import configparser + else: + import ConfigParser as configparser + + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class MPFAManager(object): + MPFA_EXTENSION = '.mpfa' + + MPFA_EXTRACT_COMMAND = 'tar xzf {} -C {}' + MPFA_CLEANUP_COMMAND = 'rm -rf {}' + + def __init__(self, mpfa_path): + self.__mpfa_path = mpfa_path + self.__contents_path = None + self.__metadata = None + + def __enter__(self): + self.extract() + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.cleanup() + + def __validate_path(self, mpfa_path): + if not os.path.isfile(mpfa_path): + raise RuntimeError("MPFA doesn't exist: path={}".format(mpfa_path)) + + name, ext = os.path.splitext(mpfa_path) + if ext != self.MPFA_EXTENSION: + raise RuntimeError("MPFA doesn't have valid extension: path={}".format(mpfa_path)) + + def __extract_contents(self, mpfa_path): + contents_path = tempfile.mkdtemp(prefix='mpfa-') + + cmd = self.MPFA_EXTRACT_COMMAND.format(mpfa_path, contents_path) + subprocess.check_call(cmd.split(), universal_newlines=True) + + self.__contents_path = contents_path + + def __parse_metadata(self, contents_path): + metadata_path = os.path.join(contents_path, 'metadata.ini') + + if not os.path.isfile(metadata_path): + raise RuntimeError("MPFA metadata doesn't exist: path={}".format(metadata_path)) + + cp = configparser.ConfigParser() + with io.open(metadata_path, 'r') as metadata_ini: + cp.readfp(metadata_ini) + + self.__metadata = cp + + def extract(self): + if self.is_extracted(): + return + + self.__validate_path(self.__mpfa_path) + self.__extract_contents(self.__mpfa_path) + self.__parse_metadata(self.__contents_path) + + def cleanup(self): + if os.path.exists(self.__contents_path): + cmd = self.MPFA_CLEANUP_COMMAND.format(self.__contents_path) + subprocess.check_call(cmd.split(), universal_newlines=True) + + self.__contents_path = None + self.__metadata = None + + def get_path(self): + return self.__contents_path + + def get_metadata(self): + return self.__metadata + + def is_extracted(self): + return self.__contents_path is not None and os.path.exists(self.__contents_path) + + +class ONIEUpdater(object): + 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_PENDING = '/usr/bin/mlnx-onie-fw-update.sh show-pending' + + ONIE_VERSION_PARSE_PATTERN = '([0-9]{4})\.([0-9]{2})-([0-9]+)\.([0-9]+)\.([0-9]+)-([0-9]+)' + ONIE_VERSION_BASE_PARSE_PATTERN = '([0-9]+)\.([0-9]+)\.([0-9]+)' + ONIE_VERSION_REQUIRED = '5.2.0016' + + ONIE_VERSION_ATTR = 'onie_version' + ONIE_NO_PENDING_UPDATES_ATTR = 'No pending firmware updates present' + + ONIE_IMAGE_INFO_COMMAND = '/bin/bash {} -q -i' + + def __mount_onie_fs(self): + fs_mountpoint = '/mnt/onie-fs' + onie_path = '/lib/onie' + + if os.path.lexists(onie_path) or os.path.exists(fs_mountpoint): + self.__umount_onie_fs() + + cmd = "fdisk -l | grep 'ONIE boot' | awk '{print $1}'" + fs_path = subprocess.check_output(cmd, + stderr=subprocess.STDOUT, + shell=True, + universal_newlines=True).rstrip('\n') + + os.mkdir(fs_mountpoint) + cmd = "mount -n -r -t ext4 {} {}".format(fs_path, fs_mountpoint) + subprocess.check_call(cmd, shell=True, universal_newlines=True) + + fs_onie_path = os.path.join(fs_mountpoint, 'onie/tools/lib/onie') + os.symlink(fs_onie_path, onie_path) + + return fs_mountpoint + + def __umount_onie_fs(self): + fs_mountpoint = '/mnt/onie-fs' + onie_path = '/lib/onie' + + if os.path.islink(onie_path): + os.unlink(onie_path) + + if os.path.ismount(fs_mountpoint): + cmd = "umount -rf {}".format(fs_mountpoint) + subprocess.check_call(cmd, shell=True, universal_newlines=True) + + if os.path.exists(fs_mountpoint): + os.rmdir(fs_mountpoint) + + def __stage_update(self, image_path): + cmd = self.ONIE_FW_UPDATE_CMD_ADD.format(image_path) + + try: + subprocess.check_call(cmd.split(), universal_newlines=True) + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to stage firmware update: {}".format(str(e))) + + def __unstage_update(self, image_path): + cmd = self.ONIE_FW_UPDATE_CMD_REMOVE.format(os.path.basename(image_path)) + + try: + subprocess.check_call(cmd.split(), universal_newlines=True) + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to unstage firmware update: {}".format(str(e))) + + def __trigger_update(self): + cmd = self.ONIE_FW_UPDATE_CMD_UPDATE + + try: + subprocess.check_call(cmd.split(), universal_newlines=True) + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to trigger firmware update: {}".format(str(e))) + + def __is_update_staged(self, image_path): + cmd = self.ONIE_FW_UPDATE_CMD_SHOW_PENDING + + try: + output = subprocess.check_output(cmd.split(), + stderr=subprocess.STDOUT, + universal_newlines=True).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get pending firmware updates: {}".format(str(e))) + + basename = os.path.basename(image_path) + + for line in output.splitlines(): + if line.startswith(basename): + return True + + return False + + def parse_onie_version(self, version, is_base=False): + onie_year = None + onie_month = None + onie_major = None + onie_minor = None + onie_release = None + onie_baudrate = None + + if is_base: + pattern = self.ONIE_VERSION_BASE_PARSE_PATTERN + + m = re.search(pattern, version) + if not m: + raise RuntimeError("Failed to parse ONIE version: pattern={}, version={}".format(pattern, version)) + + onie_major = m.group(1) + onie_minor = m.group(2) + onie_release = m.group(3) + + return onie_year, onie_month, onie_major, onie_minor, onie_release, onie_baudrate + + pattern = self.ONIE_VERSION_PARSE_PATTERN + + m = re.search(pattern, version) + if not m: + raise RuntimeError("Failed to parse ONIE version: pattern={}, version={}".format(pattern, version)) + + onie_year = m.group(1) + onie_month = m.group(2) + onie_major = m.group(3) + onie_minor = m.group(4) + onie_release = m.group(5) + onie_baudrate = m.group(6) + + return onie_year, onie_month, onie_major, onie_minor, onie_release, onie_baudrate + + def get_onie_required_version(self): + return self.ONIE_VERSION_REQUIRED + + def get_onie_version(self): + version = None + + try: + fs_mountpoint = self.__mount_onie_fs() + machine_conf_path = os.path.join(fs_mountpoint, 'onie/grub/grub-machine.cfg') + + with open(machine_conf_path, 'r') as machine_conf: + for line in machine_conf: + if line.startswith(self.ONIE_VERSION_ATTR): + items = line.rstrip('\n').split('=') + + if len(items) != 2: + raise RuntimeError("Failed to parse ONIE info: line={}".format(line)) + + version = items[1] + break + + if version is None: + raise RuntimeError("Failed to parse ONIE version") + finally: + self.__umount_onie_fs() + + return version + + def get_onie_firmware_info(self, image_path): + firmware_info = { } + + try: + self.__mount_onie_fs() + + cmd = self.ONIE_IMAGE_INFO_COMMAND.format(image_path) + + try: + output = subprocess.check_output(cmd.split(), + stderr=subprocess.STDOUT, + universal_newlines=True).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get ONIE firmware info: {}".format(str(e))) + + for line in output.splitlines(): + items = line.split('=') + + if len(items) != 2: + raise RuntimeError("Failed to parse ONIE firmware info: line={}".format(line)) + + firmware_info[items[0]] = items[1] + finally: + self.__umount_onie_fs() + + return firmware_info + + def update_firmware(self, image_path): + cmd = self.ONIE_FW_UPDATE_CMD_SHOW_PENDING + + try: + output = subprocess.check_output(cmd.split(), + stderr=subprocess.STDOUT, + universal_newlines=True).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get pending firmware updates: {}".format(str(e))) + + no_pending_updates = False + + for line in output.splitlines(): + if line.startswith(self.ONIE_NO_PENDING_UPDATES_ATTR): + no_pending_updates = True + break + + if not no_pending_updates: + raise RuntimeError("Failed to complete firmware update: pending updates are present") + + try: + self.__stage_update(image_path) + self.__trigger_update() + except: + if self.__is_update_staged(image_path): + self.__unstage_update(image_path) + raise + + def is_non_onie_firmware_update_supported(self): + current_version = self.get_onie_version() + _, _, major1, minor1, release1, _ = self.parse_onie_version(current_version) + version1 = int("{}{}{}".format(major1, minor1, release1)) + + required_version = self.get_onie_required_version() + _, _, major2, minor2, release2, _ = self.parse_onie_version(required_version, True) + version2 = int("{}{}{}".format(major2, minor2, release2)) + + return version1 >= version2 + + +class Component(ComponentBase): + def __init__(self): + self.name = None + self.description = None + self.image_ext_name = None + + def get_name(self): + return self.name + + def get_description(self): + return self.description + + @staticmethod + def _read_generic_file(filename, len, ignore_errors=False): + """ + Read a generic file, returns the contents of the file + """ + result = None + + try: + with io.open(filename, 'r') as fileobj: + result = fileobj.read(len) + except IOError as e: + if not ignore_errors: + raise RuntimeError("Failed to read file {} due to {}".format(filename, repr(e))) + + return result + + @staticmethod + def _get_command_result(cmdline): + try: + proc = subprocess.Popen(cmdline, + stdout=subprocess.PIPE, + shell=True, + stderr=subprocess.STDOUT, + universal_newlines=True) + stdout = proc.communicate()[0] + 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))) + + return result + + def _check_file_validity(self, image_path): + if not os.path.isfile(image_path): + print("ERROR: File {} doesn't exist or is not a file".format(image_path)) + return False + + name_list = os.path.splitext(image_path) + if self.image_ext_name is not None: + 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 + else: + if name_list[1]: + print("ERROR: Extend name of file {} is wrong. Image for {} shouldn't have extension".format(image_path, self.name)) + return False + + return True + + +class ComponentONIE(Component): + COMPONENT_NAME = 'ONIE' + COMPONENT_DESCRIPTION = 'ONIE - Open Network Install Environment' + + ONIE_IMAGE_VERSION_ATTR = 'image_version' + + def __init__(self): + super(ComponentONIE, self).__init__() + + self.name = self.COMPONENT_NAME + self.description = self.COMPONENT_DESCRIPTION + self.onie_updater = ONIEUpdater() + + def __install_firmware(self, image_path): + if not self._check_file_validity(image_path): + return False + + try: + print("INFO: Staging {} firmware update with ONIE updater".format(self.name)) + self.onie_updater.update_firmware(image_path) + except Exception as e: + print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e))) + return False + + return True + + def get_firmware_version(self): + return self.onie_updater.get_onie_version() + + def get_available_firmware_version(self, image_path): + firmware_info = self.onie_updater.get_onie_firmware_info(image_path) + if self.ONIE_IMAGE_VERSION_ATTR not in firmware_info: + raise RuntimeError("Failed to get {} available firmware version".format(self.name)) + + return firmware_info[self.ONIE_IMAGE_VERSION_ATTR] + + def get_firmware_update_notification(self, image_path): + return "Immediate cold reboot is required to complete {} firmware update".format(self.name) + + def install_firmware(self, image_path): + return self.__install_firmware(image_path) + + def update_firmware(self, image_path): + self.__install_firmware(image_path) + + +class ComponentSSD(Component): + COMPONENT_NAME = 'SSD' + COMPONENT_DESCRIPTION = 'SSD - Solid-State Drive' + COMPONENT_FIRMWARE_EXTENSION = '.pkg' + + FIRMWARE_VERSION_ATTR = 'Firmware Version' + AVAILABLE_FIRMWARE_VERSION_ATTR = 'Available Firmware Version' + POWER_CYCLE_REQUIRED_ATTR = 'Power Cycle Required' + UPGRADE_REQUIRED_ATTR = 'Upgrade Required' + + SSD_INFO_COMMAND = "/usr/bin/mlnx-ssd-fw-update.sh -q" + SSD_FIRMWARE_INFO_COMMAND = "/usr/bin/mlnx-ssd-fw-update.sh -q -i {}" + SSD_FIRMWARE_UPDATE_COMMAND = "/usr/bin/mlnx-ssd-fw-update.sh -y -u -i {}" + + def __init__(self): + super(ComponentSSD, self).__init__() + + self.name = self.COMPONENT_NAME + self.description = self.COMPONENT_DESCRIPTION + self.image_ext_name = self.COMPONENT_FIRMWARE_EXTENSION + + def __install_firmware(self, image_path): + if not self._check_file_validity(image_path): + return False + + cmd = self.SSD_FIRMWARE_UPDATE_COMMAND.format(image_path) + + try: + print("INFO: Installing {} firmware update".format(self.name)) + subprocess.check_call(cmd.split(), universal_newlines=True) + except subprocess.CalledProcessError as e: + print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e))) + return False + + return True + + def get_firmware_version(self): + cmd = self.SSD_INFO_COMMAND + + try: + output = subprocess.check_output(cmd.split(), + stderr=subprocess.STDOUT, + universal_newlines=True).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get {} info: {}".format(self.name, str(e))) + + for line in output.splitlines(): + if line.startswith(self.FIRMWARE_VERSION_ATTR): + return line.split(':')[1].lstrip(' \t') + + raise RuntimeError("Failed to parse {} version".format(self.name)) + + def get_available_firmware_version(self, image_path): + cmd = self.SSD_FIRMWARE_INFO_COMMAND.format(image_path) + + try: + output = subprocess.check_output(cmd.split(), + stderr=subprocess.STDOUT, + universal_newlines=True).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get {} firmware info: {}".format(self.name, str(e))) + + current_firmware_version = None + available_firmware_version = None + upgrade_required = None + + for line in output.splitlines(): + if line.startswith(self.FIRMWARE_VERSION_ATTR): + current_firmware_version = line.split(':')[1].lstrip(' \t') + if line.startswith(self.AVAILABLE_FIRMWARE_VERSION_ATTR): + available_firmware_version = line.split(':')[1].lstrip(' \t') + if line.startswith(self.UPGRADE_REQUIRED_ATTR): + upgrade_required = line.split(':')[1].lstrip(' \t') + + if upgrade_required is None or upgrade_required not in ['yes', 'no']: + raise RuntimeError("Failed to parse {} firmware upgrade status".format(self.name)) + + if upgrade_required == 'no': + if current_firmware_version is None: + raise RuntimeError("Failed to parse {} current firmware version".format(self.name)) + return current_firmware_version + + if available_firmware_version is None: + raise RuntimeError("Failed to parse {} available firmware version".format(self.name)) + + return available_firmware_version + + def get_firmware_update_notification(self, image_path): + cmd = self.SSD_FIRMWARE_INFO_COMMAND.format(image_path) + + try: + output = subprocess.check_output(cmd.split(), + stderr=subprocess.STDOUT, + universal_newlines=True).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get {} firmware info: {}".format(self.name, str(e))) + + power_cycle_required = None + upgrade_required = None + + for line in output.splitlines(): + if line.startswith(self.POWER_CYCLE_REQUIRED_ATTR): + power_cycle_required = line.split(':')[1].lstrip(' \t') + if line.startswith(self.UPGRADE_REQUIRED_ATTR): + upgrade_required = line.split(':')[1].lstrip(' \t') + + if upgrade_required is None or upgrade_required not in ['yes', 'no']: + raise RuntimeError("Failed to parse {} firmware upgrade status".format(self.name)) + + if upgrade_required == 'no': + return None + + if power_cycle_required is None or power_cycle_required not in ['yes', 'no']: + raise RuntimeError("Failed to parse {} firmware power policy".format(self.name)) + + notification = None + + if power_cycle_required == 'yes': + notification = "Immediate power cycle is required to complete {} firmware update".format(self.name) + + return notification + + def install_firmware(self, image_path): + return self.__install_firmware(image_path) + + def update_firmware(self, image_path): + self.__install_firmware(image_path) + + +class ComponentBIOS(Component): + COMPONENT_NAME = 'BIOS' + COMPONENT_DESCRIPTION = 'BIOS - Basic Input/Output System' + COMPONENT_FIRMWARE_EXTENSION = '.rom' + + BIOS_VERSION_COMMAND = 'dmidecode --oem-string 1' + + def __init__(self): + super(ComponentBIOS, self).__init__() + + self.name = self.COMPONENT_NAME + self.description = self.COMPONENT_DESCRIPTION + self.image_ext_name = self.COMPONENT_FIRMWARE_EXTENSION + self.onie_updater = ONIEUpdater() + + def __install_firmware(self, image_path): + if not self.onie_updater.is_non_onie_firmware_update_supported(): + print("ERROR: ONIE {} or later is required".format(self.onie_updater.get_onie_required_version())) + return False + + if not self._check_file_validity(image_path): + return False + + try: + print("INFO: Staging {} firmware update with ONIE updater".format(self.name)) + self.onie_updater.update_firmware(image_path) + except Exception as e: + print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e))) + return False + + return True + + def get_firmware_version(self): + cmd = self.BIOS_VERSION_COMMAND + + try: + version = subprocess.check_output(cmd.split(), + stderr=subprocess.STDOUT, + universal_newlines=True).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get {} version: {}".format(self.name, str(e))) + + return version + + def get_available_firmware_version(self, image_path): + raise NotImplementedError("{} component doesn't support firmware version query".format(self.name)) + + def get_firmware_update_notification(self, image_path): + return "Immediate cold reboot is required to complete {} firmware update".format(self.name) + + def install_firmware(self, image_path): + return self.__install_firmware(image_path) + + def update_firmware(self, image_path): + self.__install_firmware(image_path) + + +class ComponentCPLD(Component): + COMPONENT_NAME = 'CPLD{}' + COMPONENT_DESCRIPTION = 'CPLD - Complex Programmable Logic Device' + COMPONENT_FIRMWARE_EXTENSION = '.vme' + + MST_DEVICE_PATH = '/dev/mst' + MST_DEVICE_PATTERN = 'mt[0-9]*_pci_cr0' + + 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_min' + + 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 = '0' + CPLD_VERSION_MINOR_DEFAULT = '0' + + CPLD_FIRMWARE_UPDATE_COMMAND = 'cpldupdate --dev {} --print-progress {}' + + def __init__(self, idx): + super(ComponentCPLD, self).__init__() + + 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_mst_device(self): + if not os.path.exists(self.MST_DEVICE_PATH): + print("ERROR: mst driver is not loaded") + return None + + pattern = os.path.join(self.MST_DEVICE_PATH, self.MST_DEVICE_PATTERN) + + mst_dev_list = glob.glob(pattern) + if not mst_dev_list or len(mst_dev_list) != 1: + devices = str(os.listdir(self.MST_DEVICE_PATH)) + print("ERROR: Failed to get mst device: pattern={}, devices={}".format(pattern, devices)) + return None + + return mst_dev_list[0] + + def __install_firmware(self, image_path): + if not self._check_file_validity(image_path): + return False + + mst_dev = self.__get_mst_device() + if mst_dev is None: + return False + + cmd = self.CPLD_FIRMWARE_UPDATE_COMMAND.format(mst_dev, image_path) + + try: + print("INFO: Installing {} firmware update: path={}".format(self.name, image_path)) + subprocess.check_call(cmd.split(), universal_newlines=True) + except subprocess.CalledProcessError as e: + print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e))) + return False + + return True + + def get_firmware_version(self): + 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('\n').zfill(self.CPLD_PART_NUMBER_MAX_LENGTH) + version = version.rstrip('\n').zfill(self.CPLD_VERSION_MAX_LENGTH) + version_minor = version_minor.rstrip('\n').zfill(self.CPLD_VERSION_MINOR_MAX_LENGTH) + + return "CPLD{}_REV{}{}".format(part_number, version, version_minor) + + def get_available_firmware_version(self, image_path): + with MPFAManager(image_path) as mpfa: + if not mpfa.get_metadata().has_option('version', self.name): + raise RuntimeError("Failed to get {} available firmware version".format(self.name)) + + return mpfa.get_metadata().get('version', self.name) + + def get_firmware_update_notification(self, image_path): + name, ext = os.path.splitext(os.path.basename(image_path)) + if ext == self.COMPONENT_FIRMWARE_EXTENSION: + return "Power cycle (with 30 sec delay) or refresh image is required to complete {} firmware update".format(self.name) + + return "Immediate power cycle is required to complete {} firmware update".format(self.name) + + def install_firmware(self, image_path): + return self.__install_firmware(image_path) + + def update_firmware(self, image_path): + with MPFAManager(image_path) as mpfa: + if not mpfa.get_metadata().has_option('firmware', 'burn'): + raise RuntimeError("Failed to get {} burn firmware".format(self.name)) + if not mpfa.get_metadata().has_option('firmware', 'refresh'): + raise RuntimeError("Failed to get {} refresh firmware".format(self.name)) + + burn_firmware = mpfa.get_metadata().get('firmware', 'burn') + refresh_firmware = mpfa.get_metadata().get('firmware', 'refresh') + + print("INFO: Processing {} burn file: firmware install".format(self.name)) + if not self.__install_firmware(os.path.join(mpfa.get_path(), burn_firmware)): + return + + print("INFO: Processing {} refresh file: firmware update".format(self.name)) + self.__install_firmware(os.path.join(mpfa.get_path(), refresh_firmware)) + + @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('\n') + + for cpld_idx in range(1, int(cpld_number) + 1): + component_list.append(cls(cpld_idx)) + + return component_list diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py b/platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py new file mode 100644 index 000000000000..3853cac3f713 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py @@ -0,0 +1,254 @@ +DEVICE_DATA = { + 'x86_64-mlnx_msn2700-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:30":13, "31:40":14 , "41:120":15}, + "unk_untrust": {"-127:25":13, "26:30":14 , "31:35":15, "36:120":16} + } + }, + 'fans': { + 'drawer_num': 4, + 'drawer_type': 'real', + 'fan_num_per_drawer': 2, + 'support_fan_direction': False, + 'hot_swappable': True + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': True, + 'led_num': 1 + } + }, + 'x86_64-mlnx_msn2740-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:120":13}, + "unk_untrust": {"-127:15":13, "16:25":14 , "26:30":15, "31:120":17}, + } + }, + 'fans': { + 'drawer_num': 4, + 'drawer_type': 'real', + 'fan_num_per_drawer': 1, + 'support_fan_direction': False, + 'hot_swappable': True + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': True, + 'led_num': 1 + } + }, + 'x86_64-mlnx_msn2100-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:40":12, "41:120":13}, + "unk_untrust": {"-127:15":12, "16:25":13, "26:30":14, "31:35":15, "36:120":16} + } + }, + 'fans': { + 'drawer_num': 1, + 'drawer_type': 'virtual', + 'fan_num_per_drawer': 4, + 'support_fan_direction': False, + 'hot_swappable': False + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': False, + 'led_num': 2 + } + }, + 'x86_64-mlnx_msn2410-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:30":13, "31:40":14 , "41:120":15}, + "unk_untrust": {"-127:25":13, "26:30":14 , "31:35":15, "36:120":16} + } + }, + 'fans': { + 'drawer_num': 4, + 'drawer_type': 'real', + 'fan_num_per_drawer': 2, + 'support_fan_direction': False, + 'hot_swappable': True + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': True, + 'led_num': 1 + } + }, + 'x86_64-mlnx_msn2010-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:120":12}, + "unk_untrust": {"-127:15":12, "16:20":13 , "21:30":14, "31:35":15, "36:120":16} + } + }, + 'fans': { + 'drawer_num': 1, + 'drawer_type': 'virtual', + 'fan_num_per_drawer': 4, + 'support_fan_direction': False, + 'hot_swappable': False + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': False, + 'led_num': 2 + } + }, + 'x86_64-mlnx_msn3700-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:25":12, "26:40":13 , "41:120":14}, + "unk_untrust": {"-127:15":12, "16:30":13 , "31:35":14, "36:40":15, "41:120":16}, + } + }, + 'fans': { + 'drawer_num': 6, + 'drawer_type': 'real', + 'fan_num_per_drawer': 2, + 'support_fan_direction': True, + 'hot_swappable': True + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': True, + 'led_num': 1 + } + }, + 'x86_64-mlnx_msn3700c-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:40":12, "41:120":13}, + "unk_untrust": {"-127:10":12, "11:20":13 , "21:30":14, "31:35":15, "36:120":16}, + } + }, + 'fans': { + 'drawer_num': 4, + 'drawer_type': 'real', + 'fan_num_per_drawer': 2, + 'support_fan_direction': True, + 'hot_swappable': True + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': True, + 'led_num': 1 + } + }, + 'x86_64-mlnx_msn3800-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:30":12, "31:40":13 , "41:120":14}, + "unk_untrust": {"-127:0":12, "1:10":13 , "11:15":14, "16:20":15, "21:35":16, "36:120":17}, + } + }, + 'fans': { + 'drawer_num': 3, + 'drawer_type': 'real', + 'fan_num_per_drawer': 1, + 'support_fan_direction': True, + 'hot_swappable': True + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': True, + 'led_num': 1 + } + }, + 'x86_64-mlnx_msn4700-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:35":14, "36:120":15}, + "unk_untrust": {"-127:35":14, "36:120":15}, + } + }, + 'fans': { + 'drawer_num': 6, + 'drawer_type': 'real', + 'fan_num_per_drawer': 2, + 'support_fan_direction': True, + 'hot_swappable': True + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': True, + 'led_num': 1 + } + }, + 'x86_64-mlnx_msn4410-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:120":16}, + "unk_untrust": {"-127:120":16}, + } + }, + 'fans': { + 'drawer_num': 6, + 'drawer_type': 'real', + 'fan_num_per_drawer': 2, + 'support_fan_direction': True, + 'hot_swappable': True + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': True, + 'led_num': 1 + } + }, + 'x86_64-mlnx_msn3420-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:120":12}, + "unk_untrust": {"-127:25":12, "26:35":13, "36:40":14, "41:120":16}, + } + }, + 'fans': { + 'drawer_num': 5, + 'drawer_type': 'real', + 'fan_num_per_drawer': 2, + 'support_fan_direction': True, + 'hot_swappable': True + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': True, + 'led_num': 1 + } + }, + 'x86_64-mlnx_msn4600c-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:40":12, "41:120":13}, + "unk_untrust": {"-127:5":12, "6:20":13, "21:30":14, "31:35":15, "36:40":16, "41:120":17}, + } + }, + 'fans': { + 'drawer_num': 3, + 'drawer_type': 'real', + 'fan_num_per_drawer': 1, + 'support_fan_direction': True, + 'hot_swappable': True + }, + 'psus': { + 'psu_num': 2, + 'fan_num_per_psu': 1, + 'hot_swappable': True, + 'led_num': 1 + } + } +} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/eeprom.py b/platform/mellanox/mlnx-platform-api/sonic_platform/eeprom.py new file mode 100644 index 000000000000..ef13bbd89e27 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/eeprom.py @@ -0,0 +1,201 @@ +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC Platform Base API and +# provides the eeprom information which are available in the platform +# +############################################################################# +import os +import sys +import re +import time + +if sys.version_info.major == 3: + from io import StringIO +else: + from cStringIO import StringIO + +from sonic_py_common.logger import Logger + +try: + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +logger = Logger() + +# +# CACHE_XXX stuffs are supposted to be moved to the base classes +# since they are common for all vendors +# they are defined in decode-syseeprom which might be removed in the future +# currently we just copy them here +# +CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' +CACHE_FILE = 'syseeprom_cache' + +# +# this is mlnx-specific +# should this be moved to chass.py or here, which better? +# +EEPROM_SYMLINK = "/var/run/hw-management/eeprom/vpd_info" + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + RETRIES = 3 + EEPROM_DECODE_HEADLINES = 6 + EEPROM_DECODE_MAXITEM = 3 + EEPROM_DECODE_OFFSET = 0 + EEPROM_DECODE_CONTENT = 2 + + def __init__(self): + for attempt in range(self.RETRIES): + if not os.path.islink(EEPROM_SYMLINK): + time.sleep(1) + else: + break + + if not (os.path.exists(EEPROM_SYMLINK) \ + or os.path.isfile(os.path.join(CACHE_ROOT, 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 + super(Eeprom, self).__init__(self.eeprom_path, 0, '', True) + self._eeprom_loaded = False + self._load_eeprom() + self._eeprom_loaded = True + + def _load_eeprom(self): + cache_file = os.path.join(CACHE_ROOT, CACHE_FILE) + if not os.path.exists(CACHE_ROOT): + try: + os.makedirs(CACHE_ROOT) + except: + pass + else: + try: + # Make sure first time always read eeprom data from hardware + if os.path.exists(cache_file): + os.remove(cache_file) + except Exception as e: + logger.log_error('Failed to remove cache file {} - {}'.format(cache_file, repr(e))) + + try: + self.set_cache_name(cache_file) + except: + pass + + eeprom = self.read_eeprom() + if eeprom is None : + return 0 + + try: + self.update_cache(eeprom) + except: + pass + + self._base_mac = self.mgmtaddrstr(eeprom) + if self._base_mac is None: + self._base_mac = "Undefined." + else: + self._base_mac = self._base_mac.strip('\0') + + self._serial_str = self.serial_number_str(eeprom) + if self._serial_str is None: + self._serial_str = "Undefined." + else: + self._serial_str = self._serial_str.strip('\0') + + self._product_name = self.modelstr(eeprom) + if self._product_name is None: + self._product_name = "Undefined." + else: + self._product_name = self._product_name.strip('\0') + + self._part_number = self.part_number_str(eeprom) + if self._part_number is None: + self._part_number = "Undefined." + else: + self._part_number = self._part_number.strip('\0') + + original_stdout = sys.stdout + sys.stdout = StringIO() + self.decode_eeprom(eeprom) + decode_output = sys.stdout.getvalue() + sys.stdout = original_stdout + + #parse decode_output into a dictionary + decode_output.replace('\0', '') + lines = decode_output.split('\n') + lines = lines[self.EEPROM_DECODE_HEADLINES:] + self._eeprom_info_dict = dict() + + for line in lines: + try: + match = re.search('(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+[\s]*[\S]*)', line) + if match is not None: + idx = match.group(1) + value = match.group(3).rstrip('\0') + + self._eeprom_info_dict[idx] = value + except: + pass + + return 0 + + 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' + """ + if not self._eeprom_loaded: + self._load_eeprom() + return self._base_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. + """ + if not self._eeprom_loaded: + self._load_eeprom() + return self._serial_str + + def get_product_name(self): + """ + Retrieves the hardware product name for the chassis + + Returns: + A string containing the hardware product name for this chassis. + """ + if not self._eeprom_loaded: + self._load_eeprom() + return self._product_name + + def get_part_number(self): + """ + Retrieves the hardware part number for the chassis + + Returns: + A string containing the hardware part number for this chassis. + """ + if not self._eeprom_loaded: + self._load_eeprom() + return self._part_number + + 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. + """ + if not self._eeprom_loaded: + self._load_eeprom() + return self._eeprom_info_dict diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py b/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py new file mode 100644 index 000000000000..cad7d014e0f7 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC Platform Base API and +# provides the FANs status which are available in the platform +# +############################################################################# + +import os.path +import subprocess + +try: + from sonic_platform_base.fan_base import FanBase + from .led import FanLed, ComponentFaultyIndicator + from .utils import read_int_from_file, read_str_from_file, write_file +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +PWM_MAX = 255 + +FAN_PATH = "/var/run/hw-management/thermal/" +CONFIG_PATH = "/var/run/hw-management/config" +# fan_dir isn't supported on Spectrum 1. It is supported on Spectrum 2 and later switches +FAN_DIR = "/var/run/hw-management/system/fan_dir" +COOLING_STATE_PATH = "/var/run/hw-management/thermal/cooling_cur_state" + +class Fan(FanBase): + """Platform-specific Fan class""" + + STATUS_LED_COLOR_ORANGE = "orange" + min_cooling_level = 2 + MIN_VALID_COOLING_LEVEL = 1 + MAX_VALID_COOLING_LEVEL = 10 + # PSU fan speed vector + PSU_FAN_SPEED = ['0x3c', '0x3c', '0x3c', '0x3c', '0x3c', + '0x3c', '0x3c', '0x46', '0x50', '0x5a', '0x64'] + + def __init__(self, fan_index, fan_drawer, position, psu_fan = False, psu=None): + super(Fan, self).__init__() + + # API index is starting from 0, Mellanox platform index is starting from 1 + self.index = fan_index + 1 + self.fan_drawer = fan_drawer + self.position = position + + self.is_psu_fan = psu_fan + self.psu = psu + if self.fan_drawer: + self.led = ComponentFaultyIndicator(self.fan_drawer.get_led()) + elif self.is_psu_fan: + from .psu import Psu + self.led = ComponentFaultyIndicator(Psu.get_shared_led()) + else: + self.led = FanLed(self.index) + + if not self.is_psu_fan: + self.fan_speed_get_path = "fan{}_speed_get".format(self.index) + self.fan_speed_set_path = "fan{}_speed_set".format(self.index) + self.fan_max_speed_path = os.path.join(FAN_PATH, "fan{}_max".format(self.index)) + self.fan_min_speed_path = os.path.join(FAN_PATH, "fan{}_min".format(self.index)) + self._name = "fan{}".format(self.index) + else: + self.fan_speed_get_path = "psu{}_fan1_speed_get".format(self.index) + self.fan_presence_path = "psu{}_fan1_speed_get".format(self.index) + self._name = 'psu_{}_fan_{}'.format(self.index, 1) + self.fan_max_speed_path = os.path.join(CONFIG_PATH, "psu_fan_max") + self.fan_min_speed_path = os.path.join(CONFIG_PATH, "psu_fan_min") + self.psu_i2c_bus_path = os.path.join(CONFIG_PATH, 'psu{0}_i2c_bus'.format(self.index)) + self.psu_i2c_addr_path = os.path.join(CONFIG_PATH, 'psu{0}_i2c_addr'.format(self.index)) + self.psu_i2c_command_path = os.path.join(CONFIG_PATH, 'fan_command') + + self.fan_status_path = "fan{}_fault".format(self.index) + self.fan_pwm_path = "pwm1" + + + def get_direction(self): + """ + Retrieves the fan's direction + + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + What Mellanox calls forward: + Air flows from fans side to QSFP side, for example: MSN2700-CS2F + which means intake in community + What Mellanox calls reverse: + Air flow from QSFP side to fans side, for example: MSN2700-CS2R + which means exhaust in community + According to hw-mgmt: + 1 stands for forward, in other words intake + 0 stands for reverse, in other words exhaust + """ + if self.is_psu_fan: + return self.FAN_DIRECTION_NOT_APPLICABLE + else: + return self.fan_drawer.get_direction() + + def get_name(self): + return self._name + + def get_status(self): + """ + Retrieves the operational status of fan + + Returns: + bool: True if fan is operating properly, False if not + """ + status = 0 + if self.is_psu_fan: + status = 0 + else: + status = read_int_from_file(os.path.join(FAN_PATH, self.fan_status_path), 1) + + return status == 0 + + + def get_presence(self): + """ + Retrieves the presence status of fan + + Returns: + bool: True if fan is present, False if not + """ + if self.is_psu_fan: + return self.psu.get_presence() and self.psu.get_powergood_status() and os.path.exists(os.path.join(FAN_PATH, self.fan_presence_path)) + else: + return self.fan_drawer.get_presence() + + def get_speed(self): + """ + Retrieves the speed of fan + + Returns: + int: percentage of the max fan speed + """ + speed = 0 + speed_in_rpm = read_int_from_file(os.path.join(FAN_PATH, self.fan_speed_get_path)) + + max_speed_in_rpm = read_int_from_file(self.fan_max_speed_path) + if max_speed_in_rpm == 0: + return speed_in_rpm + + speed = 100*speed_in_rpm//max_speed_in_rpm + if speed > 100: + speed = 100 + + return speed + + + def get_target_speed(self): + """ + Retrieves the expected speed of fan + + Returns: + int: percentage of the max fan speed + """ + if self.is_psu_fan: + try: + # Get PSU fan target speed according to current system cooling level + cooling_level = self.get_cooling_level() + return int(self.PSU_FAN_SPEED[cooling_level], 16) + except Exception: + return self.get_speed() + + pwm = read_int_from_file(os.path.join(FAN_PATH, self.fan_speed_set_path)) + return int(round(pwm*100.0/PWM_MAX)) + + + def set_speed(self, speed): + """ + Set fan speed to expected value + + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + + Returns: + bool: True if set success, False if fail. + """ + status = True + + if self.is_psu_fan: + if not self.get_presence(): + return False + from .thermal import logger + try: + bus = read_str_from_file(self.psu_i2c_bus_path, raise_exception=True) + addr = read_str_from_file(self.psu_i2c_addr_path, raise_exception=True) + command = read_str_from_file(self.psu_i2c_command_path, raise_exception=True) + speed = Fan.PSU_FAN_SPEED[int(speed // 10)] + command = "i2cset -f -y {0} {1} {2} {3} wp".format(bus, addr, command, speed) + subprocess.check_call(command, shell = True, universal_newlines=True) + return True + except subprocess.CalledProcessError as ce: + logger.log_error('Failed to call command {}, return code={}, command output={}'.format(ce.cmd, ce.returncode, ce.output)) + return False + except Exception as e: + logger.log_error('Failed to set PSU FAN speed - {}'.format(e)) + return False + + try: + cooling_level = int(speed // 10) + if cooling_level < self.min_cooling_level: + cooling_level = self.min_cooling_level + speed = self.min_cooling_level * 10 + self.set_cooling_level(cooling_level, cooling_level) + pwm = int(round(PWM_MAX*speed/100.0)) + write_file(os.path.join(FAN_PATH, self.fan_speed_set_path), pwm, raise_exception=True) + except (ValueError, IOError): + status = False + + return status + + + def set_status_led(self, color): + """ + Set led to expected color + + Args: + color: A string representing the color with which to set the + fan module status LED + + Returns: + bool: True if set success, False if fail. + """ + return self.led.set_status(color) + + + 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 + """ + return self.led.get_status() + + + 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 + """ + # The tolerance value is fixed as 50% for all the Mellanox platform + return 50 + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device + Returns: + integer: The 1-based relative physical position in parent device + """ + return self.position + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + @classmethod + def set_cooling_level(cls, level, cur_state): + """ + Change cooling level. The input level should be an integer value [1, 10]. + 1 means 10%, 2 means 20%, 10 means 100%. + """ + if not isinstance(level, int): + raise RuntimeError("Failed to set cooling level, input parameter must be integer") + + if level < cls.MIN_VALID_COOLING_LEVEL or level > cls.MAX_VALID_COOLING_LEVEL: + raise RuntimeError("Failed to set cooling level, level value must be in range [{}, {}], got {}".format( + cls.MIN_VALID_COOLING_LEVEL, + cls.MAX_VALID_COOLING_LEVEL, + level + )) + + try: + # Reset FAN cooling level vector. According to low level team, + # if we need set cooling level to X, we need first write a (10+X) + # to cooling_cur_state file to reset the cooling level vector. + write_file(COOLING_STATE_PATH, level + 10, raise_exception=True) + + # We need set cooling level after resetting the cooling level vector + write_file(COOLING_STATE_PATH, cur_state, raise_exception=True) + except (ValueError, IOError) as e: + raise RuntimeError("Failed to set cooling level - {}".format(e)) + + @classmethod + def get_cooling_level(cls): + try: + return read_int_from_file(COOLING_STATE_PATH, raise_exception=True) + except (ValueError, IOError) as e: + raise RuntimeError("Failed to get cooling level - {}".format(e)) diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/fan_drawer.py b/platform/mellanox/mlnx-platform-api/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..66ee39491735 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/fan_drawer.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan Drawer status which are available in the platform +# +############################################################################# + +import os + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform_base.fan_base import FanBase + from .led import FanLed, SharedLed +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +class MellanoxFanDrawer(FanDrawerBase): + def __init__(self, index, fan_data): + from .fan import FAN_PATH + super(MellanoxFanDrawer, self).__init__() + self._index = index + 1 + self._fan_data = fan_data + self._presence_path = os.path.join(FAN_PATH, 'fan{}_status'.format(self._index)) + self._led = None + + def get_index(self): + return self._index + + def get_led(self): + return self._led + + def get_presence(self): + if not self._fan_data['hot_swappable']: + return True + + status = 0 + try: + with open(self._presence_path, 'r') as presence_status: + status = int(presence_status.read()) + except (ValueError, IOError) as e: + status = 0 + + return status == 1 + + def get_direction(self): + if not self._fan_data['support_fan_direction'] or not self.get_presence(): + return FanBase.FAN_DIRECTION_NOT_APPLICABLE + + try: + from .fan import FAN_DIR + with open(FAN_DIR, 'r') as fan_dir: + fan_dir_bits = int(fan_dir.read()) + fan_mask = 1 << self._index - 1 + if fan_dir_bits & fan_mask: + return FanBase.FAN_DIRECTION_INTAKE + else: + return FanBase.FAN_DIRECTION_EXHAUST + except (ValueError, IOError) as e: + raise RuntimeError("Failed to read fan direction status to {}".format(repr(e))) + + def set_status_led(self, color): + """ + Sets the state of the fan drawer status LED + + Args: + color: A string representing the color with which to set the + fan drawer status LED + + Returns: + bool: True if status LED state is set successfully, False if not + """ + return True + + def get_status_led(self): + """ + Gets the state of the fan drawer LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + return self._led.get_status() + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device + Returns: + integer: The 1-based relative physical position in parent device + """ + return self._index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return self._fan_data['hot_swappable'] + + +class RealDrawer(MellanoxFanDrawer): + def __init__(self, index, fan_data): + super(RealDrawer, self).__init__(index, fan_data) + self._name = 'drawer{}'.format(self._index) + self._led = SharedLed(FanLed(self._index)) + + def get_name(self): + return self._name + + +class VirtualDrawer(MellanoxFanDrawer): + def __init__(self, index, fan_data): + super(VirtualDrawer, self).__init__(index, fan_data) + self._led = SharedLed(FanLed(None)) + + def get_name(self): + return 'N/A' diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/led.py b/platform/mellanox/mlnx-platform-api/sonic_platform/led.py new file mode 100644 index 000000000000..2e6002b77e6f --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/led.py @@ -0,0 +1,319 @@ +import os + + +class Led(object): + STATUS_LED_COLOR_GREEN = 'green' + STATUS_LED_COLOR_GREEN_BLINK = 'green_blink' + STATUS_LED_COLOR_RED = 'red' + STATUS_LED_COLOR_RED_BLINK = 'red_blink' + STATUS_LED_COLOR_ORANGE = 'orange' + STATUS_LED_COLOR_ORANGE_BLINK = 'orange_blink' + STATUS_LED_COLOR_OFF = 'off' + + LED_ON = '1' + LED_OFF = '0' + LED_BLINK = '50' + + LED_PATH = "/var/run/hw-management/led/" + + def set_status(self, color): + led_cap_list = self.get_capability() + if led_cap_list is None: + return False + + status = False + try: + self._stop_blink(led_cap_list) + blink_pos = color.find('blink') + if blink_pos != -1: + return self._set_status_blink(color, blink_pos, led_cap_list) + + if color == Led.STATUS_LED_COLOR_GREEN: + with open(self.get_green_led_path(), 'w') as led: + led.write(Led.LED_ON) + status = True + elif color == Led.STATUS_LED_COLOR_RED: + # Some led don't support red led but support orange led, in this case we set led to orange + if Led.STATUS_LED_COLOR_RED in led_cap_list: + led_path = self.get_red_led_path() + elif Led.STATUS_LED_COLOR_ORANGE in led_cap_list: + led_path = self.get_orange_led_path() + else: + return False + + with open(led_path, 'w') as led: + led.write(Led.LED_ON) + status = True + elif color == Led.STATUS_LED_COLOR_OFF: + if Led.STATUS_LED_COLOR_GREEN in led_cap_list: + with open(self.get_green_led_path(), 'w') as led: + led.write(Led.LED_OFF) + if Led.STATUS_LED_COLOR_RED in led_cap_list: + with open(self.get_red_led_path(), 'w') as led: + led.write(Led.LED_OFF) + if Led.STATUS_LED_COLOR_ORANGE in led_cap_list: + with open(self.get_orange_led_path(), 'w') as led: + led.write(Led.LED_OFF) + + status = True + else: + status = False + except (ValueError, IOError): + status = False + + return status + + def _set_status_blink(self, color, blink_pos, led_cap_list): + if color not in led_cap_list: + if color == Led.STATUS_LED_COLOR_RED_BLINK and Led.STATUS_LED_COLOR_ORANGE_BLINK in led_cap_list: + color = Led.STATUS_LED_COLOR_ORANGE_BLINK + elif color == Led.STATUS_LED_COLOR_ORANGE_BLINK and Led.STATUS_LED_COLOR_RED_BLINK in led_cap_list: + color = Led.STATUS_LED_COLOR_RED_BLINK + else: + return False + + if Led.STATUS_LED_COLOR_GREEN_BLINK == color: + self._set_led_blink_status(self.get_green_led_delay_on_path(), self.get_green_led_delay_off_path(), Led.LED_BLINK) + elif Led.STATUS_LED_COLOR_RED_BLINK == color: + self._set_led_blink_status(self.get_red_led_delay_on_path(), self.get_red_led_delay_off_path(), Led.LED_BLINK) + elif Led.STATUS_LED_COLOR_ORANGE_BLINK == color: + self._set_led_blink_status(self.get_orange_led_delay_on_path(), self.get_orange_led_delay_off_path(), Led.LED_BLINK) + else: + return False + + return True + + def _stop_blink(self, led_cap_list): + try: + if Led.STATUS_LED_COLOR_GREEN_BLINK in led_cap_list: + self._set_led_blink_status(self.get_green_led_delay_on_path(), self.get_green_led_delay_off_path(), Led.LED_OFF) + if Led.STATUS_LED_COLOR_RED_BLINK in led_cap_list: + self._set_led_blink_status(self.get_red_led_delay_on_path(), self.get_red_led_delay_off_path(), Led.LED_OFF) + if Led.STATUS_LED_COLOR_ORANGE_BLINK in led_cap_list: + self._set_led_blink_status(self.get_orange_led_delay_on_path(), self.get_orange_led_delay_off_path(), Led.LED_OFF) + except Exception as e: + return + + def _set_led_blink_status(self, delay_on_file, delay_off_file, value): + with open(delay_on_file, 'w') as led: + led.write(value) + with open(delay_off_file, 'w') as led: + led.write(value) + + def get_status(self): + led_cap_list = self.get_capability() + if led_cap_list is None: + return Led.STATUS_LED_COLOR_OFF + + try: + blink_status = self._get_blink_status(led_cap_list) + if blink_status is not None: + return blink_status + + with open(self.get_green_led_path(), 'r') as led: + if Led.LED_OFF != led.read().rstrip('\n'): + return Led.STATUS_LED_COLOR_GREEN + + if Led.STATUS_LED_COLOR_RED in led_cap_list: + with open(self.get_red_led_path(), 'r') as led: + if Led.LED_OFF != led.read().rstrip('\n'): + return Led.STATUS_LED_COLOR_RED + if Led.STATUS_LED_COLOR_ORANGE in led_cap_list: + with open(self.get_orange_led_path(), 'r') as led: + if Led.LED_OFF != led.read().rstrip('\n'): + return Led.STATUS_LED_COLOR_RED + except (ValueError, IOError) as e: + raise RuntimeError("Failed to read led status due to {}".format(repr(e))) + + return Led.STATUS_LED_COLOR_OFF + + def _get_blink_status(self, led_cap_list): + try: + if Led.STATUS_LED_COLOR_GREEN_BLINK in led_cap_list: + if self._is_led_blinking(self.get_green_led_delay_on_path(), self.get_green_led_delay_off_path()): + return Led.STATUS_LED_COLOR_GREEN_BLINK + if Led.STATUS_LED_COLOR_RED_BLINK in led_cap_list: + if self._is_led_blinking(self.get_red_led_delay_on_path(), self.get_red_led_delay_off_path()): + return Led.STATUS_LED_COLOR_RED_BLINK + if Led.STATUS_LED_COLOR_ORANGE_BLINK in led_cap_list: + if self._is_led_blinking(self.get_orange_led_delay_on_path(), self.get_orange_led_delay_off_path()): + return Led.STATUS_LED_COLOR_ORANGE_BLINK + except Exception as e: + return None + + return None + + def _is_led_blinking(self, delay_on_file, delay_off_file): + with open(delay_on_file, 'r') as led: + delay_on = led.read().rstrip('\n') + with open(delay_off_file, 'r') as led: + delay_off = led.read().rstrip('\n') + return delay_on != Led.LED_OFF and delay_off != Led.LED_OFF + + def get_capability(self): + cap_list = None + try: + with open(self.get_led_cap_path(), 'r') as led_cap: + caps = led_cap.read() + cap_list = set(caps.split()) + except (ValueError, IOError): + pass + + return cap_list + + def get_green_led_path(self): + pass + + def get_green_led_delay_off_path(self): + return '{}_delay_off'.format(self.get_green_led_path()) + + def get_green_led_delay_on_path(self): + return '{}_delay_on'.format(self.get_green_led_path()) + + def get_red_led_path(self): + pass + + def get_red_led_delay_off_path(self): + return '{}_delay_off'.format(self.get_red_led_path()) + + def get_red_led_delay_on_path(self): + return '{}_delay_on'.format(self.get_red_led_path()) + + def get_orange_led_path(self): + pass + + def get_orange_led_delay_off_path(self): + return '{}_delay_off'.format(self.get_orange_led_path()) + + def get_orange_led_delay_on_path(self): + return '{}_delay_on'.format(self.get_orange_led_path()) + + def get_led_cap_path(self): + pass + + +class FanLed(Led): + LED_PATH = "/var/run/hw-management/led/" + + def __init__(self, index): + if index is not None: + self._green_led_path = os.path.join(Led.LED_PATH, "led_fan{}_green".format(index)) + self._red_led_path = os.path.join(Led.LED_PATH, "led_fan{}_red".format(index)) + self._orange_led_path = os.path.join(Led.LED_PATH, "led_fan{}_orange".format(index)) + self._led_cap_path = os.path.join(Led.LED_PATH, "led_fan{}_capability".format(index)) + else: + self._green_led_path = os.path.join(Led.LED_PATH, "led_fan_green") + self._red_led_path = os.path.join(Led.LED_PATH, "led_fan_red") + self._orange_led_path = os.path.join(Led.LED_PATH, "led_fan_orange") + self._led_cap_path = os.path.join(Led.LED_PATH, "led_fan_capability") + + self.set_status(Led.STATUS_LED_COLOR_GREEN) + + def get_green_led_path(self): + return self._green_led_path + + def get_red_led_path(self): + return self._red_led_path + + def get_orange_led_path(self): + return self._orange_led_path + + def get_led_cap_path(self): + return self._led_cap_path + + +class PsuLed(Led): + def __init__(self, index): + if index is not None: + self._green_led_path = os.path.join(Led.LED_PATH, "led_psu{}_green".format(index)) + self._red_led_path = os.path.join(Led.LED_PATH, "led_psu{}_red".format(index)) + self._orange_led_path = os.path.join(Led.LED_PATH, "led_psu{}_orange".format(index)) + self._led_cap_path = os.path.join(Led.LED_PATH, "led_psu{}_capability".format(index)) + else: + self._green_led_path = os.path.join(Led.LED_PATH, "led_psu_green") + self._red_led_path = os.path.join(Led.LED_PATH, "led_psu_red") + self._orange_led_path = os.path.join(Led.LED_PATH, "led_psu_orange") + self._led_cap_path = os.path.join(Led.LED_PATH, "led_psu_capability") + + self.set_status(Led.STATUS_LED_COLOR_GREEN) + + def get_green_led_path(self): + return self._green_led_path + + def get_red_led_path(self): + return self._red_led_path + + def get_orange_led_path(self): + return self._orange_led_path + + def get_led_cap_path(self): + return self._led_cap_path + + +class SystemLed(Led): + def __init__(self): + self._green_led_path = os.path.join(Led.LED_PATH, "led_status_green") + self._red_led_path = os.path.join(Led.LED_PATH, "led_status_red") + self._orange_led_path = os.path.join(Led.LED_PATH, "led_status_orange") + self._led_cap_path = os.path.join(Led.LED_PATH, "led_status_capability") + + def get_green_led_path(self): + return self._green_led_path + + def get_red_led_path(self): + return self._red_led_path + + def get_orange_led_path(self): + return self._orange_led_path + + def get_led_cap_path(self): + return self._led_cap_path + + +class SharedLed(object): + LED_PRIORITY = { + Led.STATUS_LED_COLOR_RED: 0, + Led.STATUS_LED_COLOR_GREEN: 1 + } + + def __init__(self, led): + self._led = led + self._virtual_leds = [] + + def add_virtual_leds(self, led): + self._virtual_leds.append(led) + + def update_status_led(self): + target_color = Led.STATUS_LED_COLOR_GREEN + for virtual_led in self._virtual_leds: + try: + if SharedLed.LED_PRIORITY[virtual_led.get_led_color()] < SharedLed.LED_PRIORITY[target_color]: + target_color = virtual_led.get_led_color() + except KeyError: + return False + return self._led.set_status(target_color) + + def get_status(self): + return self._led.get_status() + + +class ComponentFaultyIndicator(object): + def __init__(self, shared_led): + self._color = Led.STATUS_LED_COLOR_GREEN + self._shared_led = shared_led + self._shared_led.add_virtual_leds(self) + + def set_status(self, color): + current_color = self._color + self._color = color + if self._shared_led.update_status_led(): + return True + else: + self._color = current_color + return False + + def get_led_color(self): + return self._color + + def get_status(self): + return self._shared_led.get_status() diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py b/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py new file mode 100644 index 000000000000..f2a8af954790 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# implementation of new platform api +############################################################################# + +try: + import subprocess + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Platform(PlatformBase): + def __init__(self): + PlatformBase.__init__(self) + if self._is_host(): + self._chassis = Chassis() + self._chassis.initialize_components() + self._chassis.initizalize_system_led() + self._chassis.initialize_eeprom() + else: + self._chassis = Chassis() + self._chassis.initialize_psu() + self._chassis.initialize_fan() + self._chassis.initialize_eeprom() + self._chassis.initialize_thermals() + + def _is_host(self): + """ + Test whether current process is running on the host or an docker + return True for host and False for docker + """ + is_host = False + try: + proc = subprocess.Popen("docker --version 2>/dev/null", + stdout=subprocess.PIPE, + shell=True, + stderr=subprocess.STDOUT, + universal_newlines=True) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + if result != '': + is_host = True + + except OSError as e: + pass + + return is_host diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py b/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py new file mode 100644 index 000000000000..7b73b7196ce2 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py @@ -0,0 +1,327 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +try: + import os.path + from sonic_platform_base.psu_base import PsuBase + from sonic_py_common.logger import Logger + from sonic_platform.fan import Fan + from .led import PsuLed, SharedLed, ComponentFaultyIndicator + from .device_data import DEVICE_DATA +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +# Global logger class instance +logger = Logger() + +psu_list = [] + +PSU_CURRENT = "current" +PSU_VOLTAGE = "voltage" +PSU_POWER = "power" + +# in most platforms 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 + +platform_dict_psu = {'x86_64-mlnx_msn3420-r0':1, 'x86_64-mlnx_msn3700-r0': 1, 'x86_64-mlnx_msn3700c-r0': 1, 'x86_64-mlnx_msn3800-r0': 1, 'x86_64-mlnx_msn4600c-r0':1, 'x86_64-mlnx_msn4700-r0': 1, 'x86_64-mlnx_msn4410-r0': 1} + +psu_profile_list = [ + # default filename convention + { + PSU_CURRENT : "power/psu{}_curr", + PSU_VOLTAGE : "power/psu{}_volt", + PSU_POWER : "power/psu{}_power" + }, + # for 3420, 3700, 3700c, 3800, 4600c, 4700 + { + PSU_CURRENT : "power/psu{}_curr", + PSU_VOLTAGE : "power/psu{}_volt_out2", + PSU_POWER : "power/psu{}_power" + } +] + +class Psu(PsuBase): + """Platform-specific Psu class""" + + shared_led = None + + def __init__(self, psu_index, platform): + global psu_list + PsuBase.__init__(self) + # PSU is 1-based on Mellanox platform + self.index = psu_index + 1 + psu_list.append(self.index) + self.psu_path = "/var/run/hw-management/" + psu_oper_status = "thermal/psu{}_pwr_status".format(self.index) + #psu_oper_status should always be present for all platforms + self.psu_oper_status = os.path.join(self.psu_path, psu_oper_status) + self._name = "PSU{}".format(psu_index + 1) + + if platform in platform_dict_psu: + filemap = psu_profile_list[platform_dict_psu[platform]] + else: + filemap = psu_profile_list[0] + + self.psu_data = DEVICE_DATA[platform]['psus'] + + if not self.psu_data['hot_swappable']: + self.always_present = True + self.psu_voltage = None + self.psu_current = None + self.psu_power = None + self.psu_presence = None + self.psu_temp = None + self.psu_temp_threshold = None + else: + self.always_present = False + psu_voltage = filemap[PSU_VOLTAGE].format(self.index) + psu_voltage = os.path.join(self.psu_path, psu_voltage) + self.psu_voltage = psu_voltage + + psu_current = filemap[PSU_CURRENT].format(self.index) + psu_current = os.path.join(self.psu_path, psu_current) + self.psu_current = psu_current + + psu_power = filemap[PSU_POWER].format(self.index) + psu_power = os.path.join(self.psu_path, psu_power) + self.psu_power = psu_power + + psu_presence = "thermal/psu{}_status".format(self.index) + psu_presence = os.path.join(self.psu_path, psu_presence) + self.psu_presence = psu_presence + + self.psu_temp = os.path.join(self.psu_path, 'thermal/psu{}_temp'.format(self.index)) + self.psu_temp_threshold = os.path.join(self.psu_path, 'thermal/psu{}_temp_max'.format(self.index)) + + # unplugable PSU has no FAN + if self.psu_data['hot_swappable']: + fan = Fan(psu_index, None, 1, True, self) + self._fan_list.append(fan) + + if self.psu_data['led_num'] == 1: + self.led = ComponentFaultyIndicator(Psu.get_shared_led()) + else: # 2010/2100 + self.led = PsuLed(self.index) + + # initialize thermal for PSU + from .thermal import initialize_psu_thermals + initialize_psu_thermals(platform, self._thermal_list, self.index, self.get_power_available_status) + + + def get_name(self): + return self._name + + + def _read_generic_file(self, filename, len): + """ + Read a generic file, returns the contents of the file + """ + result = 0 + try: + if not os.path.exists(filename): + return result + with open(filename, 'r') as fileobj: + result = int(fileobj.read().strip()) + except Exception as e: + logger.log_info("Fail to read file {} due to {}".format(filename, repr(e))) + return result + + + def get_powergood_status(self): + """ + Retrieves the operational status of power supply unit (PSU) defined + + Returns: + bool: True if PSU is operating properly, False if not + """ + status = self._read_generic_file(os.path.join(self.psu_path, self.psu_oper_status), 0) + + return status == 1 + + + def get_presence(self): + """ + Retrieves the presence status of power supply unit (PSU) defined + + Returns: + bool: True if PSU is present, False if not + """ + if self.always_present: + return self.always_present + else: + status = self._read_generic_file(self.psu_presence, 0) + return status == 1 + + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + if self.psu_voltage is not None and self.get_powergood_status(): + voltage = self._read_generic_file(self.psu_voltage, 0) + return float(voltage) / 1000 + else: + return None + + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + if self.psu_current is not None and self.get_powergood_status(): + amperes = self._read_generic_file(self.psu_current, 0) + return float(amperes) / 1000 + else: + return None + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, e.g. 302.6 + """ + if self.psu_power is not None and self.get_powergood_status(): + power = self._read_generic_file(self.psu_power, 0) + return float(power) / 1000000 + else: + return None + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + + Args: + color: A string representing the color with which to set the + PSU status LED + + Returns: + bool: True if status LED state is set successfully, False if not + + Notes: + Only one led for all PSUs. + """ + return self.led.set_status(color) + + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + if self.psu_data['led_num'] == 1: + return Psu.get_shared_led().get_status() + else: + return self.led.get_status() + + + def get_power_available_status(self): + """ + Gets the power available status + + Returns: + True if power is present and power on. + False and "absence of PSU" if power is not present. + False and "absence of power" if power is present but not power on. + """ + if not self.get_presence(): + return False, "absence of PSU" + elif not self.get_powergood_status(): + return False, "absence of power" + else: + return True, "" + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device + Returns: + integer: The 1-based relative physical position in parent device + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return self.psu_data['hot_swappable'] + + @classmethod + def get_shared_led(cls): + if not cls.shared_led: + cls.shared_led = SharedLed(PsuLed(None)) + return cls.shared_led + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.psu_temp is not None and self.get_powergood_status(): + try: + temp = self._read_generic_file(self.psu_temp, 0) + return float(temp) / 1000 + except Exception as e: + logger.log_info("Fail to get temperature for PSU {} due to - {}".format(self._name, repr(e))) + + return None + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.psu_temp_threshold is not None and self.get_powergood_status(): + try: + temp_threshold = self._read_generic_file(self.psu_temp_threshold, 0) + return float(temp_threshold) / 1000 + except Exception as e: + logger.log_info("Fail to get temperature threshold for PSU {} due to - {}".format(self._name, repr(e))) + + return None + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + # hw-management doesn't expose those sysfs for now + raise NotImplementedError + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + # hw-management doesn't expose those sysfs for now + raise NotImplementedError diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py new file mode 100644 index 000000000000..39ced89fcd59 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py @@ -0,0 +1,2068 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC Platform Base API and +# provides the FANs status which are available in the platform +# +############################################################################# + +try: + import subprocess + import time + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_eeprom import eeprom_dts + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.inf8628 import inf8628InterfaceId + from sonic_platform_base.sonic_sfp.qsfp_dd import qsfp_dd_InterfaceId + from sonic_platform_base.sonic_sfp.qsfp_dd import qsfp_dd_Dom + from sonic_py_common.logger import Logger + +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +try: + # python_sdk_api does not support python3 for now. Daemons like thermalctld or psud + # also import this file without actually use the sdk lib. So we catch the ImportError + # and ignore it here. Meanwhile, we have to trigger xcvrd using python2 now because it + # uses the sdk lib. + from python_sdk_api.sxd_api import * + from python_sdk_api.sx_api import * +except ImportError as e: + pass + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_EXT_SPECIFICATION_COMPLIANCE_OFFSET = 64 +XCVR_EXT_SPECIFICATION_COMPLIANCE_WIDTH = 1 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 2 + +# definitions of the offset and width for values in XCVR_QSFP_DD info eeprom +XCVR_EXT_TYPE_OFFSET_QSFP_DD = 72 +XCVR_EXT_TYPE_WIDTH_QSFP_DD = 2 +XCVR_CONNECTOR_OFFSET_QSFP_DD = 75 +XCVR_CONNECTOR_WIDTH_QSFP_DD = 1 +XCVR_CABLE_LENGTH_OFFSET_QSFP_DD = 74 +XCVR_CABLE_LENGTH_WIDTH_QSFP_DD = 1 +XCVR_HW_REV_OFFSET_QSFP_DD = 36 +XCVR_HW_REV_WIDTH_QSFP_DD = 2 +XCVR_VENDOR_DATE_OFFSET_QSFP_DD = 54 +XCVR_VENDOR_DATE_WIDTH_QSFP_DD = 8 +XCVR_DOM_CAPABILITY_OFFSET_QSFP_DD = 2 +XCVR_DOM_CAPABILITY_WIDTH_QSFP_DD = 1 +XCVR_MEDIA_TYPE_OFFSET_QSFP_DD = 85 +XCVR_MEDIA_TYPE_WIDTH_QSFP_DD = 1 +XCVR_FIRST_APPLICATION_LIST_OFFSET_QSFP_DD = 86 +XCVR_FIRST_APPLICATION_LIST_WIDTH_QSFP_DD = 32 +XCVR_SECOND_APPLICATION_LIST_OFFSET_QSFP_DD = 351 +XCVR_SECOND_APPLICATION_LIST_WIDTH_QSFP_DD = 28 + +# to improve performance we retrieve all eeprom data via a single ethtool command +# in function get_transceiver_info and get_transceiver_bulk_status +# XCVR_INTERFACE_DATA_SIZE stands for the max size to be read +# this variable is only used by get_transceiver_info. +# please be noted that each time some new value added to the function +# we should make sure that it falls into the area +# [XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE] or +# adjust XCVR_INTERFACE_MAX_SIZE to contain the new data +# It's same for [QSFP_DOM_BULK_DATA_START, QSFP_DOM_BULK_DATA_SIZE] and +# [SFP_DOM_BULK_DATA_START, SFP_DOM_BULK_DATA_SIZE] which are used by +# get_transceiver_bulk_status +XCVR_INTERFACE_DATA_START = 0 +XCVR_INTERFACE_DATA_SIZE = 92 +SFP_MODULE_ADDRA2_OFFSET = 256 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 56 + +QSFP_DOM_BULK_DATA_START = 22 +QSFP_DOM_BULK_DATA_SIZE = 36 +SFP_DOM_BULK_DATA_START = 96 +SFP_DOM_BULK_DATA_SIZE = 10 + +QSFP_DD_DOM_BULK_DATA_START = 14 +QSFP_DD_DOM_BULK_DATA_SIZE = 4 + +# definitions of the offset for values in OSFP info eeprom +OSFP_TYPE_OFFSET = 0 +OSFP_VENDOR_NAME_OFFSET = 129 +OSFP_VENDOR_PN_OFFSET = 148 +OSFP_HW_REV_OFFSET = 164 +OSFP_VENDOR_SN_OFFSET = 166 + +# definitions of the offset for values in QSFP_DD info eeprom +QSFP_DD_TYPE_OFFSET = 0 +QSFP_DD_VENDOR_NAME_OFFSET = 1 +QSFP_DD_VENDOR_PN_OFFSET = 20 +QSFP_DD_VENDOR_SN_OFFSET = 38 +QSFP_DD_VENDOR_OUI_OFFSET = 17 + +#definitions of the offset and width for values in DOM info eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_VERSION_COMPLIANCE_OFFSET = 1 +QSFP_VERSION_COMPLIANCE_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_MODULE_MONITOR_OFFSET = 0 +QSFP_MODULE_MONITOR_WIDTH = 9 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_POWEROVERRIDE_BIT = 0 +QSFP_POWERSET_BIT = 1 +QSFP_OPTION_VALUE_OFFSET = 192 +QSFP_OPTION_VALUE_WIDTH = 4 + +QSFP_MODULE_UPPER_PAGE3_START = 384 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNL_THRESHOLD_OFFSET = 176 +QSFP_CHANNL_THRESHOLD_WIDTH = 24 + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_CHANNL_STATUS_OFFSET = 110 +SFP_CHANNL_STATUS_WIDTH = 1 + +QSFP_DD_TEMPE_OFFSET = 14 +QSFP_DD_TEMPE_WIDTH = 2 +QSFP_DD_VOLT_OFFSET = 16 +QSFP_DD_VOLT_WIDTH = 2 +QSFP_DD_TX_BIAS_OFFSET = 42 +QSFP_DD_TX_BIAS_WIDTH = 16 +QSFP_DD_RX_POWER_OFFSET = 58 +QSFP_DD_RX_POWER_WIDTH = 16 +QSFP_DD_TX_POWER_OFFSET = 26 +QSFP_DD_TX_POWER_WIDTH = 16 +QSFP_DD_CHANNL_MON_OFFSET = 26 +QSFP_DD_CHANNL_MON_WIDTH = 48 +QSFP_DD_CHANNL_DISABLE_STATUS_OFFSET = 86 +QSFP_DD_CHANNL_DISABLE_STATUS_WIDTH = 1 +QSFP_DD_CHANNL_RX_LOS_STATUS_OFFSET = 19 +QSFP_DD_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_DD_CHANNL_TX_FAULT_STATUS_OFFSET = 7 +QSFP_DD_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_DD_MODULE_THRESHOLD_OFFSET = 0 +QSFP_DD_MODULE_THRESHOLD_WIDTH = 72 +QSFP_DD_CHANNL_STATUS_OFFSET = 26 +QSFP_DD_CHANNL_STATUS_WIDTH = 1 + +# identifier value of xSFP module which is in the first byte of the EEPROM +# if the identifier value falls into SFP_TYPE_CODE_LIST the module is treated as a SFP module and parsed according to 8472 +# for QSFP_TYPE_CODE_LIST the module is treated as a QSFP module and parsed according to 8436/8636 +# Originally the type (SFP/QSFP) of each module is determined according to the SKU dictionary +# where the type of each FP port is defined. The content of EEPROM is parsed according to its type. +# However, sometimes the SFP module can be fit in an adapter and then pluged into a QSFP port. +# In this case the EEPROM content is in format of SFP but parsed as QSFP, causing failure. +# To resolve that issue the type field of the xSFP module is also fetched so that we can know exectly what type the +# module is. Currently only the following types are recognized as SFP/QSFP module. +# Meanwhile, if the a module's identifier value can't be recognized, it will be parsed according to the SKU dictionary. +# This is because in the future it's possible that some new identifier value which is not regonized but backward compatible +# with the current format and by doing so it can be parsed as much as possible. +SFP_TYPE_CODE_LIST = [ + '03' # SFP/SFP+/SFP28 +] +QSFP_TYPE_CODE_LIST = [ + '0d', # QSFP+ or later + '11' # QSFP28 or later +] +QSFP_DD_TYPE_CODE_LIST = [ + '18' # QSFP-DD Double Density 8X Pluggable Transceiver +] + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes','FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia','FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +SFP_PATH = "/var/run/hw-management/qsfp/" +SFP_TYPE = "SFP" +QSFP_TYPE = "QSFP" +OSFP_TYPE = "OSFP" +QSFP_DD_TYPE = "QSFP_DD" + +#variables for sdk +REGISTER_NUM = 1 +DEVICE_ID = 1 +SWITCH_ID = 0 +SX_PORT_ATTR_ARR_SIZE = 64 + +PMAOS_ASE = 1 +PMAOS_EE = 1 +PMAOS_E = 2 +PMAOS_RST = 0 +PMAOS_ENABLE = 1 +PMAOS_DISABLE = 2 + +PMMP_LPMODE_BIT = 8 +MCION_TX_DISABLE_BIT = 1 + +#on page 0 +#i2c address 0x50 +MCIA_ADDR_TX_CHANNEL_DISABLE = 86 + +MCIA_ADDR_POWER_OVERRIDE = 93 +#power set bit +MCIA_ADDR_POWER_OVERRIDE_PS_BIT = 1 +#power override bit +MCIA_ADDR_POWER_OVERRIDE_POR_BIT = 0 + +#on page 0 +#i2c address 0x51 +MCIA_ADDR_TX_DISABLE = 110 +MCIA_ADDR_TX_DISABLE_BIT = 6 + +PORT_TYPE_NVE = 8 +PORT_TYPE_CPU = 4 +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) + +# parameters for SFP presence +SFP_STATUS_INSERTED = '1' + +# Global logger class instance +logger = Logger() + + +# SDK initializing stuff, called from chassis +def initialize_sdk_handle(): + rc, sdk_handle = sx_api_open(None) + if (rc != SX_STATUS_SUCCESS): + logger.log_warning("Failed to open api handle, please check whether SDK is running.") + sdk_handle = None + + return sdk_handle + +def deinitialize_sdk_handle(sdk_handle): + if sdk_handle is not None: + rc = sx_api_close(sdk_handle) + if (rc != SX_STATUS_SUCCESS): + logger.log_warning("Failed to close api handle.") + + return rc == SXD_STATUS_SUCCESS + else: + logger.log_warning("Sdk handle is none") + return False + +class SFP(SfpBase): + """Platform-specific SFP class""" + + def __init__(self, sfp_index, sfp_type, sdk_handle_getter, platform): + SfpBase.__init__(self) + self.index = sfp_index + 1 + self.sfp_eeprom_path = "qsfp{}".format(self.index) + self.sfp_status_path = "qsfp{}_status".format(self.index) + self._detect_sfp_type(sfp_type) + self.dom_tx_disable_supported = False + self._dom_capability_detect() + self.sdk_handle_getter = sdk_handle_getter + self.sdk_index = sfp_index + + # initialize SFP thermal list + from .thermal import initialize_sfp_thermals + initialize_sfp_thermals(platform, self._thermal_list, self.index) + + @property + def sdk_handle(self): + return self.sdk_handle_getter() + + def reinit(self): + + """ + Re-initialize this SFP object when a new SFP inserted + :return: + """ + self._detect_sfp_type(self.sfp_type) + self._dom_capability_detect() + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + ethtool_cmd = "ethtool -m sfp{} hex on offset 0 length 1 2>/dev/null".format(self.index) + try: + proc = subprocess.Popen(ethtool_cmd, + stdout=subprocess.PIPE, + shell=True, + stderr=subprocess.STDOUT, + universal_newlines=True) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + if result != '': + presence = True + + except OSError as e: + raise OSError("Cannot detect sfp") + + return presence + + + # Read out any bytes from any offset + def _read_eeprom_specific_bytes(self, offset, num_bytes): + eeprom_raw = [] + ethtool_cmd = "ethtool -m sfp{} hex on offset {} length {}".format(self.index, offset, num_bytes) + try: + output = subprocess.check_output(ethtool_cmd, + shell=True, + universal_newlines=True) + output_lines = output.splitlines() + first_line_raw = output_lines[0] + if "Offset" in first_line_raw: + for line in output_lines[2:]: + line_split = line.split() + eeprom_raw = eeprom_raw + line_split[1:] + except subprocess.CalledProcessError as e: + return None + + return eeprom_raw + + + def _detect_sfp_type(self, sfp_type): + eeprom_raw = [] + eeprom_raw = self._read_eeprom_specific_bytes(XCVR_TYPE_OFFSET, XCVR_TYPE_WIDTH) + if eeprom_raw: + if eeprom_raw[0] in SFP_TYPE_CODE_LIST: + self.sfp_type = SFP_TYPE + elif eeprom_raw[0] in QSFP_TYPE_CODE_LIST: + self.sfp_type = QSFP_TYPE + elif eeprom_raw[0] in QSFP_DD_TYPE_CODE_LIST: + self.sfp_type = QSFP_DD_TYPE + else: + # we don't regonize this identifier value, treat the xSFP module as the default type + self.sfp_type = sfp_type + logger.log_info("Identifier value of {} module {} is {} which isn't regonized and will be treated as default type ({})".format( + sfp_type, self.index, eeprom_raw[0], sfp_type + )) + else: + # eeprom_raw being None indicates the module is not present. + # in this case we treat it as the default type according to the SKU + self.sfp_type = sfp_type + + + def _dom_capability_detect(self): + if not self.get_presence(): + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_bias_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + return + + if self.sfp_type == QSFP_TYPE: + self.calibration = 1 + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + offset = 128 + + # 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((offset + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qsfp_version_compliance_raw = self._read_eeprom_specific_bytes(QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH) + qsfp_version_compliance = int(qsfp_version_compliance_raw[0], 16) + dom_capability = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) + if qsfp_version_compliance >= 0x08: + self.dom_temp_supported = dom_capability['data']['Temp_support']['value'] == 'On' + self.dom_volt_supported = dom_capability['data']['Voltage_support']['value'] == 'On' + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = dom_capability['data']['Tx_power_support']['value'] == 'On' + else: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = dom_capability['data']['Rx_power_support']['value'] == 'On' + self.dom_tx_power_supported = True + self.dom_supported = True + self.calibration = 1 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + qsfp_option_value_raw = self._read_eeprom_specific_bytes(QSFP_OPTION_VALUE_OFFSET, QSFP_OPTION_VALUE_WIDTH) + if qsfp_option_value_raw is not None: + optional_capability = sfpd_obj.parse_option_params(qsfp_option_value_raw, 0) + self.dom_tx_disable_supported = optional_capability['data']['TxDisable']['value'] == 'On' + dom_status_indicator = sfpd_obj.parse_dom_status_indicator(qsfp_version_compliance_raw, 1) + self.qsfp_page3_available = dom_status_indicator['data']['FlatMem']['value'] == 'Off' + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.qsfp_page3_available = False + + elif self.sfp_type == QSFP_DD_TYPE: + sfpi_obj = qsfp_dd_InterfaceId() + if sfpi_obj is None: + self.dom_supported = False + + offset = 0 + # two types of QSFP-DD cable types supported: Copper and Optical. + qsfp_dom_capability_raw = self._read_eeprom_specific_bytes((offset + XCVR_DOM_CAPABILITY_OFFSET_QSFP_DD), XCVR_DOM_CAPABILITY_WIDTH_QSFP_DD) + if qsfp_dom_capability_raw is not None: + self.dom_temp_supported = True + self.dom_volt_supported = True + dom_capability = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) + if dom_capability['data']['Flat_MEM']['value'] == 'Off': + self.dom_supported = True + self.second_application_list = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + self.dom_tx_bias_power_supported = True + self.dom_thresholds_supported = True + self.dom_rx_tx_power_bias_supported = True + else: + self.dom_supported = False + self.second_application_list = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.dom_tx_bias_power_supported = False + self.dom_thresholds_supported = False + self.dom_rx_tx_power_bias_supported = False + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.dom_tx_bias_power_supported = False + self.dom_thresholds_supported = False + self.dom_rx_tx_power_bias_supported = False + + elif self.sfp_type == SFP_TYPE: + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + return None + sfp_dom_capability_raw = self._read_eeprom_specific_bytes(XCVR_DOM_CAPABILITY_OFFSET, XCVR_DOM_CAPABILITY_WIDTH) + if sfp_dom_capability_raw is not None: + sfp_dom_capability = int(sfp_dom_capability_raw[0], 16) + self.dom_supported = (sfp_dom_capability & 0x40 != 0) + if self.dom_supported: + self.dom_temp_supported = True + self.dom_volt_supported = True + self.dom_rx_power_supported = True + self.dom_tx_power_supported = True + if sfp_dom_capability & 0x20 != 0: + self.calibration = 1 + elif sfp_dom_capability & 0x10 != 0: + self.calibration = 2 + else: + self.calibration = 0 + else: + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + self.calibration = 0 + self.dom_tx_disable_supported = (int(sfp_dom_capability_raw[1], 16) & 0x40 != 0) + else: + self.dom_supported = False + self.dom_temp_supported = False + self.dom_volt_supported = False + self.dom_rx_power_supported = False + self.dom_tx_power_supported = False + + + def _convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + + Returns: + A dict which contains following keys/values : + ================================================================================ + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + mominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + application_advertisement |1*255VCHAR |supported applications advertisement + ================================================================================ + """ + transceiver_info_dict = {} + compliance_code_dict = {} + + # ToDo: OSFP tranceiver info parsing not fully supported. + # in inf8628.py lack of some memory map definition + # will be implemented when the inf8628 memory map ready + if self.sfp_type == OSFP_TYPE: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP + + sfpi_obj = inf8628InterfaceId() + if sfpi_obj is None: + return None + + sfp_type_raw = self._read_eeprom_specific_bytes((offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes((offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes((offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes((offset + OSFP_HW_REV_OFFSET), vendor_rev_width) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes((offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = 'N/A' + transceiver_info_dict['vendor_date'] = 'N/A' + transceiver_info_dict['connector'] = 'N/A' + transceiver_info_dict['encoding'] = 'N/A' + transceiver_info_dict['ext_identifier'] = 'N/A' + transceiver_info_dict['ext_rateselect_compliance'] = 'N/A' + transceiver_info_dict['cable_type'] = 'N/A' + transceiver_info_dict['cable_length'] = 'N/A' + transceiver_info_dict['specification_compliance'] = 'N/A' + transceiver_info_dict['nominal_bit_rate'] = 'N/A' + transceiver_info_dict['application_advertisement'] = 'N/A' + + elif self.sfp_type == QSFP_TYPE: + offset = 128 + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + cable_length_width = XCVR_CABLE_LENGTH_WIDTH_QSFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + sfp_type = 'QSFP' + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + elif self.sfp_type == QSFP_DD_TYPE: + offset = 128 + + sfpi_obj = qsfp_dd_InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + sfp_type_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + else: + return None + + sfp_vendor_name_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + if sfp_vendor_name_raw is not None: + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + else: + return None + + sfp_vendor_pn_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + if sfp_vendor_pn_raw is not None: + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + else: + return None + + sfp_vendor_rev_raw = self._read_eeprom_specific_bytes((offset + XCVR_HW_REV_OFFSET_QSFP_DD), XCVR_HW_REV_WIDTH_QSFP_DD) + if sfp_vendor_rev_raw is not None: + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + else: + return None + + sfp_vendor_sn_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + if sfp_vendor_sn_raw is not None: + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + else: + return None + + sfp_vendor_oui_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + else: + return None + + sfp_vendor_date_raw = self._read_eeprom_specific_bytes((offset + XCVR_VENDOR_DATE_OFFSET_QSFP_DD), XCVR_VENDOR_DATE_WIDTH_QSFP_DD) + if sfp_vendor_date_raw is not None: + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + else: + return None + + sfp_connector_raw = self._read_eeprom_specific_bytes((offset + XCVR_CONNECTOR_OFFSET_QSFP_DD), XCVR_CONNECTOR_WIDTH_QSFP_DD) + if sfp_connector_raw is not None: + sfp_connector_data = sfpi_obj.parse_connector(sfp_connector_raw, 0) + else: + return None + + sfp_ext_identifier_raw = self._read_eeprom_specific_bytes((offset + XCVR_EXT_TYPE_OFFSET_QSFP_DD), XCVR_EXT_TYPE_WIDTH_QSFP_DD) + if sfp_ext_identifier_raw is not None: + sfp_ext_identifier_data = sfpi_obj.parse_ext_iden(sfp_ext_identifier_raw, 0) + else: + return None + + sfp_cable_len_raw = self._read_eeprom_specific_bytes((offset + XCVR_CABLE_LENGTH_OFFSET_QSFP_DD), XCVR_CABLE_LENGTH_WIDTH_QSFP_DD) + if sfp_cable_len_raw is not None: + sfp_cable_len_data = sfpi_obj.parse_cable_len(sfp_cable_len_raw, 0) + else: + return None + + sfp_media_type_raw = self._read_eeprom_specific_bytes(XCVR_MEDIA_TYPE_OFFSET_QSFP_DD, XCVR_MEDIA_TYPE_WIDTH_QSFP_DD) + if sfp_media_type_raw is not None: + sfp_media_type_dict = sfpi_obj.parse_media_type(sfp_media_type_raw, 0) + if sfp_media_type_dict is None: + return None + + host_media_list = "" + sfp_application_type_first_list = self._read_eeprom_specific_bytes((XCVR_FIRST_APPLICATION_LIST_OFFSET_QSFP_DD), XCVR_FIRST_APPLICATION_LIST_WIDTH_QSFP_DD) + if self.second_application_list: + possible_application_count = 15 + sfp_application_type_second_list = self._read_eeprom_specific_bytes((XCVR_SECOND_APPLICATION_LIST_OFFSET_QSFP_DD), XCVR_SECOND_APPLICATION_LIST_WIDTH_QSFP_DD) + if sfp_application_type_first_list is not None and sfp_application_type_second_list is not None: + sfp_application_type_list = sfp_application_type_first_list + sfp_application_type_second_list + else: + return None + else: + possible_application_count = 8 + if sfp_application_type_first_list is not None: + sfp_application_type_list = sfp_application_type_first_list + else: + return None + + for i in range(0, possible_application_count): + if sfp_application_type_list[i * 4] == 'ff': + break + host_electrical, media_interface = sfpi_obj.parse_application(sfp_media_type_dict, sfp_application_type_list[i * 4], sfp_application_type_list[i * 4 + 1]) + host_media_list = host_media_list + host_electrical + ' - ' + media_interface + '\n\t\t\t\t ' + else: + return None + + transceiver_info_dict['type'] = str(sfp_type_data['data']['type']['value']) + transceiver_info_dict['manufacturer'] = str(sfp_vendor_name_data['data']['Vendor Name']['value']) + transceiver_info_dict['model'] = str(sfp_vendor_pn_data['data']['Vendor PN']['value']) + transceiver_info_dict['hardware_rev'] = str(sfp_vendor_rev_data['data']['Vendor Rev']['value']) + transceiver_info_dict['serial'] = str(sfp_vendor_sn_data['data']['Vendor SN']['value']) + transceiver_info_dict['vendor_oui'] = str(sfp_vendor_oui_data['data']['Vendor OUI']['value']) + transceiver_info_dict['vendor_date'] = str(sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value']) + transceiver_info_dict['connector'] = str(sfp_connector_data['data']['Connector']['value']) + transceiver_info_dict['encoding'] = "Not supported for CMIS cables" + transceiver_info_dict['ext_identifier'] = str(sfp_ext_identifier_data['data']['Extended Identifier']['value']) + transceiver_info_dict['ext_rateselect_compliance'] = "Not supported for CMIS cables" + transceiver_info_dict['specification_compliance'] = "Not supported for CMIS cables" + transceiver_info_dict['cable_type'] = "Length Cable Assembly(m)" + transceiver_info_dict['cable_length'] = str(sfp_cable_len_data['data']['Length Cable Assembly(m)']['value']) + transceiver_info_dict['nominal_bit_rate'] = "Not supported for CMIS cables" + transceiver_info_dict['application_advertisement'] = host_media_list + + else: + offset = 0 + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + cable_length_width = XCVR_CABLE_LENGTH_WIDTH_SFP + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + sfp_type = 'SFP' + + sfpi_obj = sff8472InterfaceId() + if sfpi_obj is None: + print("Error: sfp_object open failed") + return None + + if self.sfp_type != QSFP_DD_TYPE: + sfp_interface_bulk_raw = self._read_eeprom_specific_bytes(offset + XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE) + if sfp_interface_bulk_raw is None: + return None + + start = XCVR_INTFACE_BULK_OFFSET - XCVR_INTERFACE_DATA_START + end = start + interface_info_bulk_width + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_NAME_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_NAME_WIDTH + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_PN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_PN_WIDTH + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_HW_REV_OFFSET - XCVR_INTERFACE_DATA_START + end = start + vendor_rev_width + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_SN_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_SN_WIDTH + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_OUI_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_OUI_WIDTH + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_interface_bulk_raw[start : end], 0) + + start = XCVR_VENDOR_DATE_OFFSET - XCVR_INTERFACE_DATA_START + end = start + XCVR_VENDOR_DATE_WIDTH + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_interface_bulk_raw[start : end], 0) + + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + transceiver_info_dict['application_advertisement'] = 'N/A' + + if self.sfp_type == QSFP_TYPE: + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + sfp_ext_specification_compliance_raw = self._read_eeprom_specific_bytes(offset + XCVR_EXT_SPECIFICATION_COMPLIANCE_OFFSET, XCVR_EXT_SPECIFICATION_COMPLIANCE_WIDTH) + if sfp_ext_specification_compliance_raw is not None: + sfp_ext_specification_compliance_data = sfpi_obj.parse_ext_specification_compliance(sfp_ext_specification_compliance_raw[0 : 1], 0) + if sfp_ext_specification_compliance_data['data']['Extended Specification compliance']['value'] != "Unspecified": + compliance_code_dict['Extended Specification compliance'] = sfp_ext_specification_compliance_data['data']['Extended Specification compliance']['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return transceiver_info_dict + + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + RX LOS |BOOLEAN |RX lost-of-signal status, + | |True if has RX los, False if not. + TX FAULT |BOOLEAN |TX fault status, + | |True if has TX fault, False if not. + Reset status |BOOLEAN |reset status, + | |True if SFP in reset, False if not. + LP mode |BOOLEAN |low power mode status, + | |True in lp mode, False if not. + TX disable |BOOLEAN |TX disable status, + | |True TX disabled, False if not. + TX disabled channel |HEX |disabled TX channles in hex, + | |bits 0 to 3 represent channel 0 + | |to channel 3. + Temperature |INT |module temperature in Celsius + Voltage |INT |supply voltage in mV + TX bias |INT |TX Bias Current in mA + RX power |INT |received optical power in mW + TX power |INT |TX output power in mW + ======================================================================== + """ + transceiver_dom_info_dict = {} + + dom_info_dict_keys = ['temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'rx5power', 'rx6power', + 'rx7power', 'rx8power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx5bias', 'tx6bias', + 'tx7bias', 'tx8bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power', + 'tx5power', 'tx6power', + 'tx7power', 'tx8power' + ] + transceiver_dom_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') + + if self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + + dom_data_raw = self._read_eeprom_specific_bytes((offset + QSFP_DOM_BULK_DATA_START), QSFP_DOM_BULK_DATA_SIZE) + if dom_data_raw is None: + return transceiver_dom_info_dict + + if self.dom_temp_supported: + start = QSFP_TEMPE_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature(dom_data_raw[start : end], 0) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + if temp is not None: + transceiver_dom_info_dict['temperature'] = temp + + if self.dom_volt_supported: + start = QSFP_VOLT_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage(dom_data_raw[start : end], 0) + volt = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + if volt is not None: + transceiver_dom_info_dict['voltage'] = volt + + start = QSFP_CHANNL_MON_OFFSET - QSFP_DOM_BULK_DATA_START + end = start + QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_data_raw[start : end], 0) + + if self.dom_tx_power_supported: + transceiver_dom_info_dict['tx1power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value']) + transceiver_dom_info_dict['tx2power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value']) + transceiver_dom_info_dict['tx3power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value']) + transceiver_dom_info_dict['tx4power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value']) + + if self.dom_rx_power_supported: + transceiver_dom_info_dict['rx1power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value']) + transceiver_dom_info_dict['rx2power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value']) + transceiver_dom_info_dict['rx3power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value']) + transceiver_dom_info_dict['rx4power'] = self._convert_string_to_num(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'] + + elif self.sfp_type == QSFP_DD_TYPE: + + offset = 0 + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + + dom_data_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_DOM_BULK_DATA_START), QSFP_DD_DOM_BULK_DATA_SIZE) + if dom_data_raw is None: + return transceiver_dom_info_dict + + if self.dom_temp_supported: + start = QSFP_DD_TEMPE_OFFSET - QSFP_DD_DOM_BULK_DATA_START + end = start + QSFP_DD_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature(dom_data_raw[start : end], 0) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + if temp is not None: + transceiver_dom_info_dict['temperature'] = temp + + if self.dom_volt_supported: + start = QSFP_DD_VOLT_OFFSET - QSFP_DD_DOM_BULK_DATA_START + end = start + QSFP_DD_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage(dom_data_raw[start : end], 0) + volt = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + if volt is not None: + transceiver_dom_info_dict['voltage'] = volt + + if self.dom_rx_tx_power_bias_supported: + # page 11h + offset = 512 + dom_data_raw = self._read_eeprom_specific_bytes(offset + QSFP_DD_CHANNL_MON_OFFSET, QSFP_DD_CHANNL_MON_WIDTH) + if dom_data_raw is None: + return transceiver_dom_info_dict + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_data_raw, 0) + + if self.dom_tx_power_supported: + transceiver_dom_info_dict['tx1power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value'])) + transceiver_dom_info_dict['tx2power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value'])) + transceiver_dom_info_dict['tx3power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value'])) + transceiver_dom_info_dict['tx4power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value'])) + transceiver_dom_info_dict['tx5power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX5Power']['value'])) + transceiver_dom_info_dict['tx6power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX6Power']['value'])) + transceiver_dom_info_dict['tx7power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX7Power']['value'])) + transceiver_dom_info_dict['tx8power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['TX8Power']['value'])) + + if self.dom_rx_power_supported: + transceiver_dom_info_dict['rx1power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value'])) + transceiver_dom_info_dict['rx2power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value'])) + transceiver_dom_info_dict['rx3power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value'])) + transceiver_dom_info_dict['rx4power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value'])) + transceiver_dom_info_dict['rx5power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX5Power']['value'])) + transceiver_dom_info_dict['rx6power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX6Power']['value'])) + transceiver_dom_info_dict['rx7power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX7Power']['value'])) + transceiver_dom_info_dict['rx8power'] = str(self._convert_string_to_num(dom_channel_monitor_data['data']['RX8Power']['value'])) + + if self.dom_tx_bias_power_supported: + transceiver_dom_info_dict['tx1bias'] = str(dom_channel_monitor_data['data']['TX1Bias']['value']) + transceiver_dom_info_dict['tx2bias'] = str(dom_channel_monitor_data['data']['TX2Bias']['value']) + transceiver_dom_info_dict['tx3bias'] = str(dom_channel_monitor_data['data']['TX3Bias']['value']) + transceiver_dom_info_dict['tx4bias'] = str(dom_channel_monitor_data['data']['TX4Bias']['value']) + transceiver_dom_info_dict['tx5bias'] = str(dom_channel_monitor_data['data']['TX5Bias']['value']) + transceiver_dom_info_dict['tx6bias'] = str(dom_channel_monitor_data['data']['TX6Bias']['value']) + transceiver_dom_info_dict['tx7bias'] = str(dom_channel_monitor_data['data']['TX7Bias']['value']) + transceiver_dom_info_dict['tx8bias'] = str(dom_channel_monitor_data['data']['TX8Bias']['value']) + + return transceiver_dom_info_dict + + else: + if not self.dom_supported: + return transceiver_dom_info_dict + + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return transceiver_dom_info_dict + sfpd_obj._calibration_type = self.calibration + + dom_data_raw = self._read_eeprom_specific_bytes((offset + SFP_DOM_BULK_DATA_START), SFP_DOM_BULK_DATA_SIZE) + + start = SFP_TEMPE_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_TEMPE_WIDTH + dom_temperature_data = sfpd_obj.parse_temperature(dom_data_raw[start: end], 0) + + start = SFP_VOLT_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_VOLT_WIDTH + dom_voltage_data = sfpd_obj.parse_voltage(dom_data_raw[start: end], 0) + + start = SFP_CHANNL_MON_OFFSET - SFP_DOM_BULK_DATA_START + end = start + SFP_CHANNL_MON_WIDTH + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_data_raw[start: end], 0) + + transceiver_dom_info_dict['temperature'] = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + transceiver_dom_info_dict['voltage'] = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + transceiver_dom_info_dict['rx1power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['RXPower']['value']) + transceiver_dom_info_dict['tx1bias'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TXBias']['value']) + transceiver_dom_info_dict['tx1power'] = self._convert_string_to_num(dom_channel_monitor_data['data']['TXPower']['value']) + + return transceiver_dom_info_dict + + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + 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 self.sfp_type == OSFP_TYPE: + pass + + elif self.sfp_type == QSFP_TYPE: + if not self.dom_supported or not self.qsfp_page3_available: + return transceiver_dom_threshold_info_dict + + # Dom Threshold data starts from offset 384 + # Revert offset back to 0 once data is retrieved + offset = QSFP_MODULE_UPPER_PAGE3_START + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_specific_bytes((offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + + dom_channel_threshold_raw = self._read_eeprom_specific_bytes((offset + QSFP_CHANNL_THRESHOLD_OFFSET), + QSFP_CHANNL_THRESHOLD_WIDTH) + if dom_channel_threshold_raw is None: + return transceiver_dom_threshold_info_dict + dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) + + # 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'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] + + elif self.sfp_type == QSFP_DD_TYPE: + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + if not self.dom_thresholds_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + # page 02 + offset = 384 + dom_module_threshold_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_MODULE_THRESHOLD_OFFSET), QSFP_DD_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + + # 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_module_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['TxBiasLowWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TxPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TxPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TxPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TxPowerLowWarning']['value'] + + else: + offset = SFP_MODULE_ADDRA2_OFFSET + + if not self.dom_supported: + return transceiver_dom_threshold_info_dict + + sfpd_obj = sff8472Dom(None, self.calibration) + if sfpd_obj is None: + return transceiver_dom_threshold_info_dict + + dom_module_threshold_raw = self._read_eeprom_specific_bytes((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 + + # 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 + + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + + for QSFP, originally I would like to make use of Initialization complete flag bit + which is at Page a0 offset 6 bit 0 to test whether reset is complete. + However as unit testing was carried out I find this approach may fail because: + 1. we make use of ethtool to read data on I2C bus rather than to read directly + 2. ethtool is unable to access I2C during QSFP module being reset + In other words, whenever the flag is able to be retrived, the value is always be 1 + As a result, it doesn't make sense to retrieve that flag. Just treat successfully + retrieving data as "data ready". + for SFP it seems that there is not flag indicating whether reset succeed. However, + we can also do it in the way for QSFP. + """ + if not self.dom_supported: + return False + + if self.sfp_type == OSFP_TYPE: + return False + elif self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + dom_module_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_MODULE_MONITOR_OFFSET), QSFP_MODULE_MONITOR_WIDTH) + + if dom_module_monitor_raw is not None: + return True + else: + return False + elif self.sfp_type == SFP_TYPE: + offset = 0 + sfpd_obj = sff8472Dom() + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + + if dom_channel_monitor_raw is not None: + return True + else: + return False + elif self.sfp_type == QSFP_DD_TYPE: + offset = 0 + sfpd_obj = qsfp_dd_Dom() + dom_channel_status_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_CHANNL_STATUS_OFFSET), QSFP_DD_CHANNL_STATUS_WIDTH) + + if dom_channel_status_raw is None: + return False + + dom_channel_status_data = sfpd_obj.parse_dom_channel_status(dom_channel_status_raw, 0) + return dom_channel_status_data['data']['Status']['value'] == 'On' + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + if not self.dom_supported: + return None + + rx_los_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + + elif self.sfp_type == QSFP_DD_TYPE: + # page 11h + if self.dom_rx_tx_power_bias_supported: + offset = 512 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_CHANNL_RX_LOS_STATUS_OFFSET), QSFP_DD_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 8) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + rx_los_list.append(rx_los_data & 0x10 != 0) + rx_los_list.append(rx_los_data & 0x20 != 0) + rx_los_list.append(rx_los_data & 0x40 != 0) + rx_los_list.append(rx_los_data & 0x80 != 0) + + else: + offset = 256 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x02 != 0) + else: + return None + return rx_los_list + + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + if not self.dom_supported: + return None + + tx_fault_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + + elif self.sfp_type == QSFP_DD_TYPE: + return None + # page 11h + if self.dom_rx_tx_power_bias_supported: + offset = 512 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_CHANNL_TX_FAULT_STATUS_OFFSET), QSFP_DD_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 8) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + tx_fault_list.append(tx_fault_data & 0x10 != 0) + tx_fault_list.append(tx_fault_data & 0x20 != 0) + tx_fault_list.append(tx_fault_data & 0x40 != 0) + tx_fault_list.append(tx_fault_data & 0x80 != 0) + + else: + offset = 256 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + else: + return None + return tx_fault_list + + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + + for QSFP, the disable states of each channel which are the lower 4 bits in byte 85 page a0 + for SFP, the TX Disable State and Soft TX Disable Select is ORed as the tx_disable status returned + These two bits are bit 7 & 6 in byte 110 page a2 respectively + """ + if not self.dom_supported: + return None + + tx_disable_list = [] + if self.sfp_type == OSFP_TYPE: + return None + elif self.sfp_type == QSFP_TYPE: + offset = 0 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_CHANNL_DISABLE_STATUS_OFFSET), QSFP_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0x01 != 0) + tx_disable_list.append(tx_disable_data & 0x02 != 0) + tx_disable_list.append(tx_disable_data & 0x04 != 0) + tx_disable_list.append(tx_disable_data & 0x08 != 0) + + elif self.sfp_type == QSFP_DD_TYPE: + if self.dom_rx_tx_power_bias_supported: + offset = 128 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_CHANNL_DISABLE_STATUS_OFFSET), QSFP_DD_CHANNL_DISABLE_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0x01 != 0) + tx_disable_list.append(tx_disable_data & 0x02 != 0) + tx_disable_list.append(tx_disable_data & 0x04 != 0) + tx_disable_list.append(tx_disable_data & 0x08 != 0) + tx_disable_list.append(tx_disable_data & 0x10 != 0) + tx_disable_list.append(tx_disable_data & 0x20 != 0) + tx_disable_list.append(tx_disable_data & 0x40 != 0) + tx_disable_list.append(tx_disable_data & 0x80 != 0) + + else: + offset = 256 + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_STATUS_OFFSET), SFP_CHANNL_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_disable_data = int(dom_channel_monitor_raw[0], 16) + tx_disable_list.append(tx_disable_data & 0xC0 != 0) + else: + return None + return tx_disable_list + + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + + + def mgmt_phy_mod_pwr_attr_get(self, power_attr_type): + sx_mgmt_phy_mod_pwr_attr_p = new_sx_mgmt_phy_mod_pwr_attr_t_p() + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t() + sx_mgmt_phy_mod_pwr_attr.power_attr_type = power_attr_type + sx_mgmt_phy_mod_pwr_attr_t_p_assign(sx_mgmt_phy_mod_pwr_attr_p, sx_mgmt_phy_mod_pwr_attr) + try: + rc = sx_mgmt_phy_mod_pwr_attr_get(self.sdk_handle, self.sdk_index, sx_mgmt_phy_mod_pwr_attr_p) + assert SX_STATUS_SUCCESS == rc, "sx_mgmt_phy_mod_pwr_attr_get failed" + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t_p_value(sx_mgmt_phy_mod_pwr_attr_p) + pwr_mode_attr = sx_mgmt_phy_mod_pwr_attr.pwr_mode_attr + return pwr_mode_attr.admin_pwr_mode_e, pwr_mode_attr.oper_pwr_mode_e + finally: + delete_sx_mgmt_phy_mod_pwr_attr_t_p(sx_mgmt_phy_mod_pwr_attr_p) + + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + admin_pwr_mode, oper_pwr_mode = self.mgmt_phy_mod_pwr_attr_get(SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E) + + return oper_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E + + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + if self.sfp_type == QSFP_TYPE: + offset = 0 + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self._read_eeprom_specific_bytes((offset + QSFP_CONTROL_OFFSET), QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + return ('On' == dom_control_data['data']['PowerOverride']) + else: + return NotImplementedError + + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + if not self.dom_supported: + return None + if self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_temp_supported: + dom_temperature_raw = self._read_eeprom_specific_bytes((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) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + return temp + else: + return None + else: + return None + + elif self.sfp_type == QSFP_DD_TYPE: + offset = 0 + + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return None + + if self.dom_temp_supported: + dom_temperature_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_TEMPE_OFFSET), QSFP_DD_TEMPE_WIDTH) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + return temp + return None + + else: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + sfpd_obj._calibration_type = 1 + + dom_temperature_raw = self._read_eeprom_specific_bytes((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) + temp = self._convert_string_to_num(dom_temperature_data['data']['Temperature']['value']) + return temp + else: + return None + + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + if not self.dom_supported: + return None + if self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_volt_supported: + dom_voltage_raw = self._read_eeprom_specific_bytes((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) + voltage = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + return voltage + else: + return None + return None + + if self.sfp_type == QSFP_DD_TYPE: + offset = 128 + + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return None + + if self.dom_volt_supported: + dom_voltage_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_VOLT_OFFSET), QSFP_DD_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + voltage = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + return voltage + return None + + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + sfpd_obj._calibration_type = self.calibration + + dom_voltage_raw = self._read_eeprom_specific_bytes((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) + voltage = self._convert_string_to_num(dom_voltage_data['data']['Vcc']['value']) + return voltage + else: + return None + + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + tx_bias_list = [] + if self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((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) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Bias']['value'])) + + elif self.sfp_type == QSFP_DD_TYPE: + # page 11h + if self.dom_rx_tx_power_bias_supported: + offset = 512 + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return None + + if dom_tx_bias_power_supported: + dom_tx_bias_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_TX_BIAS_OFFSET), QSFP_DD_TX_BIAS_WIDTH) + if dom_tx_bias_raw is not None: + dom_tx_bias_data = sfpd_obj.parse_dom_tx_bias(dom_tx_bias_raw, 0) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX1Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX2Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX3Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX4Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX5Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX6Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX7Bias']['value'])) + tx_bias_list.append(self._convert_string_to_num(dom_tx_bias_data['data']['TX8Bias']['value'])) + + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + sfpd_obj._calibration_type = self.calibration + + if self.dom_supported: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_MON_OFFSET), SFP_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) + tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXBias']['value'])) + else: + return None + else: + return None + + return tx_bias_list + + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + rx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((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) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RX4Power']['value'])) + else: + return None + else: + return None + + elif self.sfp_type == QSFP_DD_TYPE: + # page 11 + if self.dom_rx_tx_power_bias_supported: + offset = 512 + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return None + + if self.dom_rx_power_supported: + dom_rx_power_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_RX_POWER_OFFSET), QSFP_DD_RX_POWER_WIDTH) + if dom_rx_power_raw is not None: + dom_rx_power_data = sfpd_obj.parse_dom_rx_power(dom_rx_power_raw, 0) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX1Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX2Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX3Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX4Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX5Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX6Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX7Power']['value'])) + rx_power_list.append(self._convert_string_to_num(dom_rx_power_data['data']['RX8Power']['value'])) + + else: + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_MON_OFFSET), SFP_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) + rx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['RXPower']['value'])) + else: + return None + else: + return None + return rx_power_list + + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + tx_power_list = [] + if self.sfp_type == OSFP_TYPE: + # OSFP not supported on our platform yet. + return None + + elif self.sfp_type == QSFP_TYPE: + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + if self.dom_tx_power_supported: + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((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) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Power']['value'])) + else: + return None + else: + return None + + elif self.sfp_type == QSFP_DD_TYPE: + return None + # page 11 + if self.dom_rx_tx_power_bias_supported: + offset = 512 + sfpd_obj = qsfp_dd_Dom() + if sfpd_obj is None: + return None + + if self.dom_tx_power_supported: + dom_tx_power_raw = self._read_eeprom_specific_bytes((offset + QSFP_DD_TX_POWER_OFFSET), QSFP_DD_TX_POWER_WIDTH) + if dom_tx_power_raw is not None: + dom_tx_power_data = sfpd_obj.parse_dom_tx_power(dom_tx_power_raw, 0) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX1Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX2Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX3Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX4Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX5Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX6Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX7Power']['value'])) + tx_power_list.append(self._convert_string_to_num(dom_tx_power_data['data']['TX8Power']['value'])) + + else: + offset = 256 + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + if self.dom_supported: + sfpd_obj._calibration_type = self.calibration + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes((offset + SFP_CHANNL_MON_OFFSET), SFP_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) + tx_power_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TXPower']['value'])) + else: + return None + else: + return None + return tx_power_list + + + def reset(self): + """ + Reset SFP and return all user module settings to their default state. + + Returns: + A boolean, True if successful, False if not + + refer plugins/sfpreset.py + """ + rc = sx_mgmt_phy_mod_reset(self.sdk_handle, self.sdk_index) + if rc != SX_STATUS_SUCCESS: + logger.log_warning("sx_mgmt_phy_mod_reset failed, rc = %d" % rc) + + return rc == SX_STATUS_SUCCESS + + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + + for SFP, make use of bit 6 of byte at (offset 110, a2h (i2c addr 0x51)) to disable/enable tx + for QSFP, set all channels to disable/enable tx + """ + return NotImplementedError + + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + + QSFP: page a0, address 86, lower 4 bits + """ + return NotImplementedError + + + def is_nve(self, port): + return (port & NVE_MASK) != 0 + + + def is_cpu(self, port): + return (port & CPU_MASK) != 0 + + + def is_port_admin_status_up(self, log_port): + oper_state_p = new_sx_port_oper_state_t_p() + admin_state_p = new_sx_port_admin_state_t_p() + module_state_p = new_sx_port_module_state_t_p() + rc = sx_api_port_state_get(self.sdk_handle, log_port, oper_state_p, admin_state_p, module_state_p) + assert rc == SXD_STATUS_SUCCESS, "sx_api_port_state_get failed, rc = %d" % rc + + admin_state = sx_port_admin_state_t_p_value(admin_state_p) + + delete_sx_port_oper_state_t_p(oper_state_p) + delete_sx_port_admin_state_t_p(admin_state_p) + delete_sx_port_module_state_t_p(module_state_p) + + if admin_state == SX_PORT_ADMIN_STATUS_UP: + return True + else: + return False + + + def set_port_admin_status_by_log_port(self, log_port, admin_status): + rc = sx_api_port_state_set(self.sdk_handle, log_port, admin_status) + if SX_STATUS_SUCCESS != rc: + logger.log_error("sx_api_port_state_set failed, rc = %d" % rc) + + return SX_STATUS_SUCCESS == rc + + + def get_logical_ports(self): + # Get all the ports related to the sfp, if port admin status is up, put it to list + port_attributes_list = new_sx_port_attributes_t_arr(SX_PORT_ATTR_ARR_SIZE) + port_cnt_p = new_uint32_t_p() + uint32_t_p_assign(port_cnt_p, SX_PORT_ATTR_ARR_SIZE) + + rc = sx_api_port_device_get(self.sdk_handle, DEVICE_ID , SWITCH_ID, port_attributes_list, port_cnt_p) + assert rc == SX_STATUS_SUCCESS, "sx_api_port_device_get failed, rc = %d" % rc + + port_cnt = uint32_t_p_value(port_cnt_p) + log_port_list = [] + for i in range(0, port_cnt): + port_attributes = sx_port_attributes_t_arr_getitem(port_attributes_list, i) + if not self.is_nve(int(port_attributes.log_port)) \ + and not self.is_cpu(int(port_attributes.log_port)) \ + and port_attributes.port_mapping.module_port == self.sdk_index \ + and self.is_port_admin_status_up(port_attributes.log_port): + log_port_list.append(port_attributes.log_port) + + delete_sx_port_attributes_t_arr(port_attributes_list) + delete_uint32_t_p(port_cnt_p) + return log_port_list + + + def mgmt_phy_mod_pwr_attr_set(self, power_attr_type, admin_pwr_mode): + result = False + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t() + sx_mgmt_phy_mod_pwr_mode_attr = sx_mgmt_phy_mod_pwr_mode_attr_t() + sx_mgmt_phy_mod_pwr_attr.power_attr_type = power_attr_type + sx_mgmt_phy_mod_pwr_mode_attr.admin_pwr_mode_e = admin_pwr_mode + sx_mgmt_phy_mod_pwr_attr.pwr_mode_attr = sx_mgmt_phy_mod_pwr_mode_attr + sx_mgmt_phy_mod_pwr_attr_p = new_sx_mgmt_phy_mod_pwr_attr_t_p() + sx_mgmt_phy_mod_pwr_attr_t_p_assign(sx_mgmt_phy_mod_pwr_attr_p, sx_mgmt_phy_mod_pwr_attr) + try: + rc = sx_mgmt_phy_mod_pwr_attr_set(self.sdk_handle, SX_ACCESS_CMD_SET, self.sdk_index, sx_mgmt_phy_mod_pwr_attr_p) + if SX_STATUS_SUCCESS != rc: + logger.log_error("sx_mgmt_phy_mod_pwr_attr_set failed, rc = %d" % rc) + result = False + else: + result = True + finally: + delete_sx_mgmt_phy_mod_pwr_attr_t_p(sx_mgmt_phy_mod_pwr_attr_p) + + return result + + + def _set_lpmode_raw(self, ports, attr_type, power_mode): + result = False + # Check if the module already works in the same mode + admin_pwr_mode, oper_pwr_mode = self.mgmt_phy_mod_pwr_attr_get(attr_type) + if (power_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E and oper_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E) \ + or (power_mode == SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E and admin_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E): + return True + try: + # Bring the port down + for port in ports: + self.set_port_admin_status_by_log_port(port, SX_PORT_ADMIN_STATUS_DOWN) + # Set the desired power mode + result = self.mgmt_phy_mod_pwr_attr_set(attr_type, power_mode) + finally: + # Bring the port up + for port in ports: + self.set_port_admin_status_by_log_port(port, SX_PORT_ADMIN_STATUS_UP) + + return result + + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + log_port_list = self.get_logical_ports() + if lpmode: + self._set_lpmode_raw(log_port_list, SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E, SX_MGMT_PHY_MOD_PWR_MODE_LOW_E) + logger.log_info("Enabled low power mode for module [%d]" % (self.sdk_index)) + else: + self._set_lpmode_raw(log_port_list, SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E, SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E) + logger.log_info( "Disabled low power mode for module [%d]" % (self.sdk_index)) + + return True + + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + return NotImplementedError + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py new file mode 100644 index 000000000000..ba3ab68a9576 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py @@ -0,0 +1,325 @@ +#!/usr/bin/env python +''' +listen to the SDK for the SFP change event and return to chassis. +''' + + +import sys, errno +import os +import time +import select +from python_sdk_api.sx_api import * +from sonic_py_common.logger import Logger + +# 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_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_ERR: STATUS_ERROR, + SDK_SFP_STATE_DIS: STATUS_PLUGOUT, +} + +# system level event/error +EVENT_ON_ALL_SFP = '-1' +SYSTEM_NOT_READY = 'system_not_ready' +SYSTEM_READY = 'system_become_ready' +SYSTEM_FAIL = 'system_fail' + +SDK_DAEMON_READY_FILE = '/tmp/sdk_ready' + +PMPE_PACKET_SIZE = 2000 + +logger = Logger() + +class sfp_event: + ''' Listen to plugin/plugout cable events ''' + + SX_OPEN_RETRIES = 30 + SX_OPEN_TIMEOUT = 5 + SELECT_TIMEOUT = 1 + + def __init__(self): + self.swid = 0 + self.handle = None + + # Allocate SDK fd and user channel structures + self.rx_fd_p = new_sx_fd_t_p() + self.user_channel_p = new_sx_user_channel_t_p() + + def initialize(self): + swid_cnt_p = None + + try: + # Wait for SDK daemon to be started with detect the sdk_ready file + retry = 0 + while not os.path.exists(SDK_DAEMON_READY_FILE): + if retry >= self.SX_OPEN_RETRIES: + raise RuntimeError("SDK daemon failed to start after {} retries and {} seconds waiting, exiting..." + .format(retry, self.SX_OPEN_TIMEOUT * self.SX_OPEN_RETRIES)) + else: + logger.log_info("SDK daemon not started yet, retry {} times".format(retry)) + retry += 1 + time.sleep(self.SX_OPEN_TIMEOUT) + + # After SDK daemon started, sx_api_open and sx_api_host_ifc_open is ready for call + rc, self.handle = sx_api_open(None) + if rc != SX_STATUS_SUCCESS: + raise RuntimeError("failed to call sx_api_open with rc {}, exiting...".format(rc)) + + rc = sx_api_host_ifc_open(self.handle, self.rx_fd_p) + if rc != SX_STATUS_SUCCESS: + raise RuntimeError("failed to call sx_api_host_ifc_open with rc {}, exiting...".format(rc)) + + self.user_channel_p.type = SX_USER_CHANNEL_TYPE_FD + self.user_channel_p.channel.fd = self.rx_fd_p + + # Wait for switch to be created and initialized inside SDK + retry = 0 + swid_cnt_p = new_uint32_t_p() + uint32_t_p_assign(swid_cnt_p, 0) + swid_cnt = 0 + while True: + if retry >= self.SX_OPEN_RETRIES: + raise RuntimeError("switch not created after {} retries and {} seconds waiting, exiting..." + .format(retry, self.SX_OPEN_RETRIES * self.SX_OPEN_TIMEOUT)) + else: + rc = sx_api_port_swid_list_get(self.handle, None, swid_cnt_p) + if rc == SX_STATUS_SUCCESS: + swid_cnt = uint32_t_p_value(swid_cnt_p) + if swid_cnt > 0: + delete_uint32_t_p(swid_cnt_p) + swid_cnt_p = None + break + else: + logger.log_info("switch not created yet, swid_cnt {}, retry {} times and wait for {} seconds" + .format(swid_cnt, retry, self.SX_OPEN_TIMEOUT * retry)) + else: + raise RuntimeError("sx_api_port_swid_list_get fail with rc {}, retry {} times and wait for {} seconds". + format(rc, retry, self.SX_OPEN_TIMEOUT * retry)) + + retry += 1 + time.sleep(self.SX_OPEN_TIMEOUT) + + # After switch was created inside SDK, sx_api_host_ifc_trap_id_register_set is ready to call + rc = sx_api_host_ifc_trap_id_register_set(self.handle, + SX_ACCESS_CMD_REGISTER, + self.swid, + SX_TRAP_ID_PMPE, + self.user_channel_p) + + if rc != SX_STATUS_SUCCESS: + raise RuntimeError("sx_api_host_ifc_trap_id_register_set failed with rc {}, exiting...".format(rc)) + except Exception as e: + logger.log_error("sfp_event initialization failed due to {}, exiting...".format(repr(e))) + if swid_cnt_p is not None: + delete_uint32_t_p(swid_cnt_p) + self.deinitialize() + + def deinitialize(self): + if self.handle is None: + return + + # unregister trap id + rc = sx_api_host_ifc_trap_id_register_set(self.handle, + SX_ACCESS_CMD_DEREGISTER, + self.swid, + SX_TRAP_ID_PMPE, + self.user_channel_p) + if rc != SX_STATUS_SUCCESS: + logger.log_error("sx_api_host_ifc_trap_id_register_set exited with error, rc {}".format(rc)) + + rc = sx_api_host_ifc_close(self.handle, self.rx_fd_p) + if rc != SX_STATUS_SUCCESS: + logger.log_error("sx_api_host_ifc_close exited with error, rc {}".format(rc)) + + rc = sx_api_close(self.handle) + if rc != SX_STATUS_SUCCESS: + logger.log_error("sx_api_close exited with error, rc {}".format(rc)) + + delete_sx_fd_t_p(self.rx_fd_p) + delete_sx_user_channel_t_p(self.user_channel_p) + + def check_sfp_status(self, port_change, timeout): + """ + the meaning of timeout is aligned with select.select, which has the following meaning: + 0: poll, returns without blocked + arbitrary positive value: doesn't returns until at least fd in the set is ready or + seconds elapsed + Note: + check_sfp_status makes the use of select to retrieve the notifications, which means + it should has the logic of reading out all the notifications in the fd selected without blocked. + However, it fails to do that due to some sdk API's characteristics: + sx_lib_host_ifc_recv can only read one notification each time and will block when no notification in that fd. + sx_lib_host_ifc_recv_list can return all notification in the fd via a single reading operation but + not supported by PMPE register (I've tested it but failed) + as a result the only way to satisfy the logic is to call sx_lib_host_ifc_recv in a loop until all notifications + has been read and we have to find a way to check that. it seems the only way to check that is via using select. + in this sense, we return one notification each time check_sfp_status called and let the caller, get_change_event, + to repeat calling it with timeout = 0 in a loop until no new notification read (in this case it returns false). + by doing so all the notifications in the fd can be retrieved through a single call to get_change_event. + """ + found = 0 + + try: + read, _, _ = select.select([self.rx_fd_p.fd], [], [], timeout) + except select.error as err: + rc, msg = err + if rc == errno.EAGAIN or rc == errno.EINTR: + return False + else: + raise + + for fd in read: + if fd == self.rx_fd_p.fd: + 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 + + sfp_state = sfp_value_status_dict.get(module_state, STATUS_UNKNOWN) + if sfp_state == STATUS_UNKNOWN: + # in the following sequence, STATUS_UNKNOWN can be returned. + # so we shouldn't raise exception here. + # 1. some sfp module is inserted + # 2. sfp_event gets stuck and fails to fetch the change event instantaneously + # 3. and then the sfp module is removed + # 4. sfp_event starts to try fetching the change event + # in this case found is increased so that True will be returned + logger.log_info("unknown module state {}, maybe the port suffers two adjacent insertion/removal".format(module_state)) + 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+1] = sfp_state + found += 1 + + return found != 0 + + def on_pmpe(self, fd_p): + ''' on port module plug event handler ''' + + # recv parameters + pkt_size = PMPE_PACKET_SIZE + pkt_size_p = new_uint32_t_p() + uint32_t_p_assign(pkt_size_p, pkt_size) + pkt = new_uint8_t_arr(pkt_size) + recv_info_p = new_sx_receive_info_t_p() + pmpe_t = sx_event_pmpe_t() + port_attributes_list = new_sx_port_attributes_t_arr(64) + port_cnt_p = new_uint32_t_p() + uint32_t_p_assign(port_cnt_p,64) + label_port_list = [] + label_port = None + module_state = 0 + + rc = sx_lib_host_ifc_recv(fd_p, pkt, pkt_size_p, recv_info_p) + if rc != 0: + logger.log_error("sx_lib_host_ifc_recv exited with error, rc %d" % rc) + status = False + else: + status = True + pmpe_t = recv_info_p.event_info.pmpe + 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 range(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) + port_cnt = uint32_t_p_value(port_cnt_p) + + for i in range(port_cnt): + port_attributes = sx_port_attributes_t_arr_getitem(port_attributes_list,i) + if port_attributes.log_port == logical_port: + label_port = port_attributes.port_mapping.module_port + break + + if label_port is not None: + label_port_list.append(label_port) + + delete_uint32_t_p(pkt_size_p) + delete_uint8_t_arr(pkt) + delete_sx_receive_info_t_p(recv_info_p) + delete_sx_port_attributes_t_arr(port_attributes_list) + delete_uint32_t_p(port_cnt_p) + + 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 new file mode 100644 index 000000000000..c942b0d89d35 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py @@ -0,0 +1,652 @@ +#!/usr/bin/env python + +############################################################################# +# Mellanox +# +# Module contains an implementation of SONiC Platform Base API and +# provides the thermals data which are available in the platform +# +############################################################################# + +try: + from sonic_platform_base.thermal_base import ThermalBase + from sonic_py_common.logger import Logger + from os import listdir + from os.path import isfile, join + import io + import os.path +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +# Global logger class instance +logger = Logger() + +THERMAL_DEV_CATEGORY_CPU_CORE = "cpu_core" +THERMAL_DEV_CATEGORY_CPU_PACK = "cpu_pack" +THERMAL_DEV_CATEGORY_MODULE = "module" +THERMAL_DEV_CATEGORY_PSU = "psu" +THERMAL_DEV_CATEGORY_GEARBOX = "gearbox" +THERMAL_DEV_CATEGORY_AMBIENT = "ambient" + +THERMAL_DEV_ASIC_AMBIENT = "asic_amb" +THERMAL_DEV_FAN_AMBIENT = "fan_amb" +THERMAL_DEV_PORT_AMBIENT = "port_amb" +THERMAL_DEV_COMEX_AMBIENT = "comex_amb" +THERMAL_DEV_BOARD_AMBIENT = "board_amb" + +THERMAL_API_GET_TEMPERATURE = "get_temperature" +THERMAL_API_GET_HIGH_THRESHOLD = "get_high_threshold" +THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD = "get_high_critical_threshold" + +THERMAL_API_INVALID_HIGH_THRESHOLD = 0.0 + +HW_MGMT_THERMAL_ROOT = "/var/run/hw-management/thermal/" + +THERMAL_ZONE_ASIC_PATH = "/var/run/hw-management/thermal/mlxsw/" +THERMAL_ZONE_MODULE_PATH = "/var/run/hw-management/thermal/mlxsw-module{}/" +THERMAL_ZONE_GEARBOX_PATH = "/var/run/hw-management/thermal/mlxsw-gearbox{}/" +THERMAL_ZONE_MODE = "thermal_zone_mode" +THERMAL_ZONE_POLICY = "thermal_zone_policy" +THERMAL_ZONE_TEMPERATURE = "thermal_zone_temp" +THERMAL_ZONE_NORMAL_TEMPERATURE = "temp_trip_norm" + +MODULE_TEMPERATURE_FAULT_PATH = "/var/run/hw-management/thermal/module{}_temp_fault" + +thermal_api_handler_asic = { + THERMAL_API_GET_TEMPERATURE: 'asic', + THERMAL_API_GET_HIGH_THRESHOLD: 'mlxsw/temp_trip_hot', + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD: 'mlxsw/temp_trip_crit' +} + +thermal_api_handler_cpu_core = { + THERMAL_API_GET_TEMPERATURE:"cpu_core{}", + THERMAL_API_GET_HIGH_THRESHOLD:"cpu_core{}_max", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD:"cpu_core{}_crit" +} +thermal_api_handler_cpu_pack = { + THERMAL_API_GET_TEMPERATURE:"cpu_pack", + THERMAL_API_GET_HIGH_THRESHOLD:"cpu_pack_max", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD:"cpu_pack_crit" +} +thermal_api_handler_module = { + THERMAL_API_GET_TEMPERATURE:"module{}_temp_input", + THERMAL_API_GET_HIGH_THRESHOLD:"module{}_temp_crit", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD:"module{}_temp_emergency" +} +thermal_api_handler_psu = { + THERMAL_API_GET_TEMPERATURE:"psu{}_temp", + THERMAL_API_GET_HIGH_THRESHOLD:"psu{}_temp_max", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD:None +} +thermal_api_handler_gearbox = { + THERMAL_API_GET_TEMPERATURE:"gearbox{}_temp_input", + THERMAL_API_GET_HIGH_THRESHOLD:"mlxsw-gearbox{}/temp_trip_hot", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD:"mlxsw-gearbox{}/temp_trip_crit" +} +thermal_ambient_apis = { + THERMAL_DEV_ASIC_AMBIENT : thermal_api_handler_asic, + THERMAL_DEV_PORT_AMBIENT : "port_amb", + THERMAL_DEV_FAN_AMBIENT : "fan_amb", + THERMAL_DEV_COMEX_AMBIENT : "comex_amb", + THERMAL_DEV_BOARD_AMBIENT : "board_amb" +} +thermal_ambient_name = { + THERMAL_DEV_ASIC_AMBIENT : 'ASIC', + THERMAL_DEV_PORT_AMBIENT : "Ambient Port Side Temp", + THERMAL_DEV_FAN_AMBIENT : "Ambient Fan Side Temp", + THERMAL_DEV_COMEX_AMBIENT : "Ambient COMEX Temp", + THERMAL_DEV_BOARD_AMBIENT : "Ambient Board Temp" +} +thermal_api_handlers = { + THERMAL_DEV_CATEGORY_CPU_CORE : thermal_api_handler_cpu_core, + THERMAL_DEV_CATEGORY_CPU_PACK : thermal_api_handler_cpu_pack, + THERMAL_DEV_CATEGORY_MODULE : thermal_api_handler_module, + THERMAL_DEV_CATEGORY_PSU : thermal_api_handler_psu, + THERMAL_DEV_CATEGORY_GEARBOX : thermal_api_handler_gearbox +} +thermal_name = { + THERMAL_DEV_CATEGORY_CPU_CORE : "CPU Core {} Temp", + THERMAL_DEV_CATEGORY_CPU_PACK : "CPU Pack Temp", + THERMAL_DEV_CATEGORY_MODULE : "xSFP module {} Temp", + THERMAL_DEV_CATEGORY_PSU : "PSU-{} Temp", + THERMAL_DEV_CATEGORY_GEARBOX : "Gearbox {} Temp" +} + +thermal_device_categories_all = [ + THERMAL_DEV_CATEGORY_AMBIENT, + THERMAL_DEV_CATEGORY_CPU_PACK, + THERMAL_DEV_CATEGORY_CPU_CORE, + THERMAL_DEV_CATEGORY_GEARBOX, +] + +thermal_device_categories_singleton = [ + THERMAL_DEV_CATEGORY_CPU_PACK, + THERMAL_DEV_CATEGORY_AMBIENT +] +thermal_api_names = [ + THERMAL_API_GET_TEMPERATURE, + THERMAL_API_GET_HIGH_THRESHOLD +] + +platform_dict_thermal = {'x86_64-mlnx_msn2700-r0': 0, 'x86_64-mlnx_lssn2700-r0':0, 'x86_64-mlnx_msn2740-r0': 3, 'x86_64-mlnx_msn2100-r0': 1, 'x86_64-mlnx_msn2410-r0': 2, 'x86_64-mlnx_msn2010-r0': 4, 'x86_64-mlnx_msn3420-r0':9, 'x86_64-mlnx_msn3700-r0': 5, 'x86_64-mlnx_msn3700c-r0': 6, 'x86_64-mlnx_msn3800-r0': 7, 'x86_64-mlnx_msn4600c-r0':9, 'x86_64-mlnx_msn4700-r0': 8, 'x86_64-mlnx_msn4410-r0': 8} +thermal_profile_list = [ + # 2700 + { + THERMAL_DEV_CATEGORY_CPU_CORE:(0, 2), + 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_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT + ] + ) + }, + # 2100 + { + THERMAL_DEV_CATEGORY_CPU_CORE:(0, 4), + THERMAL_DEV_CATEGORY_MODULE:(1, 16), + THERMAL_DEV_CATEGORY_PSU:(0, 0), + THERMAL_DEV_CATEGORY_CPU_PACK:(0,0), + THERMAL_DEV_CATEGORY_GEARBOX:(0,0), + THERMAL_DEV_CATEGORY_AMBIENT:(0, + [ + THERMAL_DEV_ASIC_AMBIENT, + THERMAL_DEV_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT, + ] + ) + }, + # 2410 + { + THERMAL_DEV_CATEGORY_CPU_CORE:(0, 2), + THERMAL_DEV_CATEGORY_MODULE:(1, 56), + 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_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT, + ] + ) + }, + # 2740 + { + 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,0), + THERMAL_DEV_CATEGORY_GEARBOX:(0,0), + THERMAL_DEV_CATEGORY_AMBIENT:(0, + [ + THERMAL_DEV_ASIC_AMBIENT, + THERMAL_DEV_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT, + ] + ) + }, + # 2010 + { + THERMAL_DEV_CATEGORY_CPU_CORE:(0, 4), + THERMAL_DEV_CATEGORY_MODULE:(1, 22), + THERMAL_DEV_CATEGORY_PSU:(0, 0), + THERMAL_DEV_CATEGORY_CPU_PACK:(0,0), + THERMAL_DEV_CATEGORY_GEARBOX:(0,0), + THERMAL_DEV_CATEGORY_AMBIENT:(0, + [ + THERMAL_DEV_ASIC_AMBIENT, + THERMAL_DEV_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT, + ] + ) + }, + # 3700 + { + 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 + ] + ) + }, + # 3700c + { + THERMAL_DEV_CATEGORY_CPU_CORE:(0, 2), + 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 + ] + ) + }, + # 3800 + { + THERMAL_DEV_CATEGORY_CPU_CORE:(0, 4), + THERMAL_DEV_CATEGORY_MODULE:(1, 64), + THERMAL_DEV_CATEGORY_PSU:(1, 2), + THERMAL_DEV_CATEGORY_CPU_PACK:(0,1), + THERMAL_DEV_CATEGORY_GEARBOX:(1,32), + THERMAL_DEV_CATEGORY_AMBIENT:(0, + [ + THERMAL_DEV_ASIC_AMBIENT, + THERMAL_DEV_COMEX_AMBIENT, + THERMAL_DEV_PORT_AMBIENT, + THERMAL_DEV_FAN_AMBIENT + ] + ) + }, + # 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 + ] + ) + }, + # 3420 + { + THERMAL_DEV_CATEGORY_CPU_CORE:(0, 2), + THERMAL_DEV_CATEGORY_MODULE:(1, 60), + 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 + ] + ) + }, + # 4600C + { + THERMAL_DEV_CATEGORY_CPU_CORE:(0, 4), + THERMAL_DEV_CATEGORY_MODULE:(1, 64), + 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 + ] + ) + }, + # 4410 + { + 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_psu_thermals(platform, thermal_list, psu_index, dependency): + tp_index = platform_dict_thermal[platform] + thermal_profile = thermal_profile_list[tp_index] + _, count = thermal_profile[THERMAL_DEV_CATEGORY_PSU] + if count == 0: + return + thermal = Thermal(THERMAL_DEV_CATEGORY_PSU, psu_index, True, 1, dependency) + thermal_list.append(thermal) + + +def initialize_sfp_thermals(platform, thermal_list, sfp_index): + thermal = Thermal(THERMAL_DEV_CATEGORY_MODULE, sfp_index, True, 1) + thermal_list.append(thermal) + + +def initialize_chassis_thermals(platform, thermal_list): + # create thermal objects for all categories of sensors + tp_index = platform_dict_thermal[platform] + thermal_profile = thermal_profile_list[tp_index] + Thermal.thermal_profile = thermal_profile + position = 1 + for category in thermal_device_categories_all: + if category == THERMAL_DEV_CATEGORY_AMBIENT: + count, ambient_list = thermal_profile[category] + for ambient in ambient_list: + thermal = Thermal(category, ambient, True, position) + thermal_list.append(thermal), + position += 1 + else: + start, count = 0, 0 + if category in thermal_profile: + start, count = thermal_profile[category] + if count == 0: + continue + if count == 1: + thermal = Thermal(category, 0, False, position) + thermal_list.append(thermal) + position += 1 + else: + for index in range(count): + thermal = Thermal(category, start + index, True, position) + thermal_list.append(thermal) + position += 1 + + + +class Thermal(ThermalBase): + thermal_profile = None + thermal_algorithm_status = False + + def __init__(self, category, index, has_index, position, dependency = None): + """ + index should be a string for category ambient and int for other categories + """ + if category == THERMAL_DEV_CATEGORY_AMBIENT: + self.name = thermal_ambient_name[index] + self.index = index + elif has_index: + self.name = thermal_name[category].format(index) + self.index = index + else: + self.name = thermal_name[category] + self.index = 0 + + self.category = category + self.position = position + self.temperature = self._get_file_from_api(THERMAL_API_GET_TEMPERATURE) + self.high_threshold = self._get_file_from_api(THERMAL_API_GET_HIGH_THRESHOLD) + self.high_critical_threshold = self._get_file_from_api(THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD) + self.dependency = dependency + + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return self.name + + + @classmethod + def _read_generic_file(cls, filename, len): + """ + Read a generic file, returns the contents of the file + """ + result = None + try: + with open(filename, 'r') as fileobj: + result = fileobj.read().strip() + except Exception as e: + logger.log_info("Fail to read file {} due to {}".format(filename, repr(e))) + return result + + + def _get_file_from_api(self, api_name): + if self.category == THERMAL_DEV_CATEGORY_AMBIENT: + handler = thermal_ambient_apis[self.index] + if isinstance(handler, str): + if api_name == THERMAL_API_GET_TEMPERATURE: + filename = thermal_ambient_apis[self.index] + else: + return None + elif isinstance(handler, dict): + filename = handler[api_name] + else: + return None + else: + handler = thermal_api_handlers[self.category][api_name] + if self.category in thermal_device_categories_singleton: + filename = handler + else: + if handler: + filename = handler.format(self.index) + else: + return None + return join(HW_MGMT_THERMAL_ROOT, filename) + + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + if self.dependency: + status, hint = self.dependency() + if not status: + logger.log_debug("get_temperature for {} failed due to {}".format(self.name, hint)) + return None + value_str = self._read_generic_file(self.temperature, 0) + if value_str is None: + return None + value_float = float(value_str) + if self.category == THERMAL_DEV_CATEGORY_MODULE and value_float == THERMAL_API_INVALID_HIGH_THRESHOLD: + return None + return value_float / 1000.0 + + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_threshold is None: + return None + if self.dependency: + status, hint = self.dependency() + if not status: + logger.log_debug("get_high_threshold for {} failed due to {}".format(self.name, hint)) + return None + value_str = self._read_generic_file(self.high_threshold, 0) + if value_str is None: + return None + value_float = float(value_str) + if self.category == THERMAL_DEV_CATEGORY_MODULE and value_float == THERMAL_API_INVALID_HIGH_THRESHOLD: + return None + return value_float / 1000.0 + + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_critical_threshold is None: + return None + if self.dependency: + status, hint = self.dependency() + if not status: + logger.log_debug("get_high_critical_threshold for {} failed due to {}".format(self.name, hint)) + return None + value_str = self._read_generic_file(self.high_critical_threshold, 0) + if value_str is None: + return None + value_float = float(value_str) + if self.category == THERMAL_DEV_CATEGORY_MODULE and value_float == THERMAL_API_INVALID_HIGH_THRESHOLD: + return None + return value_float / 1000.0 + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device + Returns: + integer: The 1-based relative physical position in parent device + """ + return self.position + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + @classmethod + def _write_generic_file(cls, filename, content): + """ + Generic functions to write content to a specified file path if + the content has changed. + """ + try: + with open(filename, 'w+') as file_obj: + origin_content = file_obj.read() + if origin_content != content: + file_obj.write(content) + except Exception as e: + logger.log_info("Fail to write file {} due to {}".format(filename, repr(e))) + + @classmethod + def set_thermal_algorithm_status(cls, status, force=True): + """ + Enable/disable kernel thermal algorithm. + When enable kernel thermal algorithm, kernel will adjust fan speed + according to thermal zones temperature. Please note that kernel will + only adjust fan speed when temperature across some "edge", e.g temperature + changes to exceed high threshold. + When disable kernel thermal algorithm, kernel no longer adjust fan speed. + We usually disable the algorithm when we want to set a fix speed. E.g, when + a fan unit is removed from system, we will set fan speed to 100% and disable + the algorithm to avoid it adjust the speed. + + Returns: + True if thermal algorithm status changed. + """ + if not cls.thermal_profile: + raise Exception("Fail to get thermal profile for this switch") + + if not force and cls.thermal_algorithm_status == status: + return False + + cls.thermal_algorithm_status = status + content = "enabled" if status else "disabled" + policy = "step_wise" if status else "user_space" + cls._write_generic_file(join(THERMAL_ZONE_ASIC_PATH, THERMAL_ZONE_MODE), content) + cls._write_generic_file(join(THERMAL_ZONE_ASIC_PATH, THERMAL_ZONE_POLICY), policy) + + if THERMAL_DEV_CATEGORY_MODULE in cls.thermal_profile: + start, count = cls.thermal_profile[THERMAL_DEV_CATEGORY_MODULE] + if count != 0: + for index in range(count): + cls._write_generic_file(join(THERMAL_ZONE_MODULE_PATH.format(start + index), THERMAL_ZONE_MODE), content) + cls._write_generic_file(join(THERMAL_ZONE_MODULE_PATH.format(start + index), THERMAL_ZONE_POLICY), policy) + + if THERMAL_DEV_CATEGORY_GEARBOX in cls.thermal_profile: + start, count = cls.thermal_profile[THERMAL_DEV_CATEGORY_GEARBOX] + if count != 0: + for index in range(count): + cls._write_generic_file(join(THERMAL_ZONE_GEARBOX_PATH.format(start + index), THERMAL_ZONE_MODE), content) + cls._write_generic_file(join(THERMAL_ZONE_GEARBOX_PATH.format(start + index), THERMAL_ZONE_POLICY), policy) + return True + + @classmethod + def check_thermal_zone_temperature(cls): + """ + Check thermal zone current temperature with normal temperature + + Returns: + True if all thermal zones current temperature less or equal than normal temperature + """ + if not cls.thermal_profile: + raise Exception("Fail to get thermal profile for this switch") + + if not cls._check_thermal_zone_temperature(THERMAL_ZONE_ASIC_PATH): + return False + + if THERMAL_DEV_CATEGORY_MODULE in cls.thermal_profile: + start, count = cls.thermal_profile[THERMAL_DEV_CATEGORY_MODULE] + if count != 0: + for index in range(count): + if not cls._check_thermal_zone_temperature(THERMAL_ZONE_MODULE_PATH.format(start + index)): + return False + + if THERMAL_DEV_CATEGORY_GEARBOX in cls.thermal_profile: + start, count = cls.thermal_profile[THERMAL_DEV_CATEGORY_GEARBOX] + if count != 0: + for index in range(count): + if not cls._check_thermal_zone_temperature(THERMAL_ZONE_GEARBOX_PATH.format(start + index)): + return False + + return True + + @classmethod + def _check_thermal_zone_temperature(cls, thermal_zone_path): + normal_temp_path = join(thermal_zone_path, THERMAL_ZONE_NORMAL_TEMPERATURE) + current_temp_path = join(thermal_zone_path, THERMAL_ZONE_TEMPERATURE) + normal = None + current = None + try: + with open(normal_temp_path, 'r') as file_obj: + normal = float(file_obj.read()) + + with open(current_temp_path, 'r') as file_obj: + current = float(file_obj.read()) + + return current <= normal + except Exception as e: + logger.log_info("Fail to check thermal zone temperature for file {} due to {}".format(thermal_zone_path, repr(e))) + + @classmethod + def check_module_temperature_trustable(cls): + if not cls.thermal_profile: + raise Exception("Fail to get thermal profile for this switch") + + start, count = cls.thermal_profile[THERMAL_DEV_CATEGORY_MODULE] + for index in range(count): + fault_file_path = MODULE_TEMPERATURE_FAULT_PATH.format(index + start) + fault = cls._read_generic_file(fault_file_path, 0) + if fault.strip() != '0': + return 'untrust' + return 'trust' + + @classmethod + def get_min_amb_temperature(cls): + fan_ambient_path = join(HW_MGMT_THERMAL_ROOT, THERMAL_DEV_FAN_AMBIENT) + port_ambient_path = join(HW_MGMT_THERMAL_ROOT, THERMAL_DEV_PORT_AMBIENT) + + # if there is any exception, let it raise + fan_ambient_temp = int(cls._read_generic_file(fan_ambient_path, 0)) + port_ambient_temp = int(cls._read_generic_file(port_ambient_path, 0)) + return fan_ambient_temp if fan_ambient_temp < port_ambient_temp else port_ambient_temp diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_actions.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_actions.py new file mode 100644 index 000000000000..e7436bd0a5b7 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_actions.py @@ -0,0 +1,209 @@ +from sonic_platform_base.sonic_thermal_control.thermal_action_base import ThermalPolicyActionBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object +from .thermal import logger + + +class SetFanSpeedAction(ThermalPolicyActionBase): + """ + Base thermal action class to set speed for fans + """ + # JSON field definition + JSON_FIELD_SPEED = 'speed' + + def __init__(self): + """ + Constructor of SetFanSpeedAction which actually do nothing. + """ + self.speed = None + + def load_from_json(self, json_obj): + """ + Construct SetFanSpeedAction via JSON. JSON example: + { + "type": "fan.all.set_speed" + "speed": "100" + } + :param json_obj: A JSON object representing a SetFanSpeedAction action. + :return: + """ + if SetFanSpeedAction.JSON_FIELD_SPEED in json_obj: + speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED]) + if speed < 0 or speed > 100: + raise ValueError('SetFanSpeedAction invalid speed value {} in JSON policy file, valid value should be [0, 100]'. + format(speed)) + self.speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED]) + else: + raise ValueError('SetFanSpeedAction missing mandatory field {} in JSON policy file'. + format(SetFanSpeedAction.JSON_FIELD_SPEED)) + + +@thermal_json_object('fan.all.set_speed') +class SetAllFanSpeedAction(SetFanSpeedAction): + """ + Action to set speed for all fans + """ + def execute(self, thermal_info_dict): + """ + Set speed for all fans + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + from .thermal_infos import FanInfo + if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo): + fan_info_obj = thermal_info_dict[FanInfo.INFO_NAME] + for fan in fan_info_obj.get_presence_fans(): + fan.set_speed(self.speed) + logger.log_info('Set all system FAN speed to {}'.format(self.speed)) + + SetAllFanSpeedAction.set_psu_fan_speed(thermal_info_dict, self.speed) + + @classmethod + def set_psu_fan_speed(cls, thermal_info_dict, speed): + from .thermal_infos import ChassisInfo + if ChassisInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[ChassisInfo.INFO_NAME], ChassisInfo): + chassis = thermal_info_dict[ChassisInfo.INFO_NAME].get_chassis() + for psu in chassis.get_all_psus(): + for psu_fan in psu.get_all_fans(): + psu_fan.set_speed(speed) + + +@thermal_json_object('fan.all.check_and_set_speed') +class CheckAndSetAllFanSpeedAction(SetAllFanSpeedAction): + """ + Action to check thermal zone temperature and recover speed for all fans + """ + def execute(self, thermal_info_dict): + """ + Check thermal zone and set speed for all fans + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + from .thermal import Thermal + if Thermal.check_thermal_zone_temperature(): + SetAllFanSpeedAction.execute(self, thermal_info_dict) + + +@thermal_json_object('thermal_control.control') +class ControlThermalAlgoAction(ThermalPolicyActionBase): + """ + Action to control the thermal control algorithm + """ + # JSON field definition + JSON_FIELD_STATUS = 'status' + + def __init__(self): + self.status = True + + def load_from_json(self, json_obj): + """ + Construct ControlThermalAlgoAction via JSON. JSON example: + { + "type": "thermal_control.control" + "status": "true" + } + :param json_obj: A JSON object representing a ControlThermalAlgoAction action. + :return: + """ + if ControlThermalAlgoAction.JSON_FIELD_STATUS in json_obj: + status_str = json_obj[ControlThermalAlgoAction.JSON_FIELD_STATUS].lower() + if status_str == 'true': + self.status = True + elif status_str == 'false': + self.status = False + else: + raise ValueError('Invalid {} field value, please specify true of false'. + format(ControlThermalAlgoAction.JSON_FIELD_STATUS)) + else: + raise ValueError('ControlThermalAlgoAction ' + 'missing mandatory field {} in JSON policy file'. + format(ControlThermalAlgoAction.JSON_FIELD_STATUS)) + + def execute(self, thermal_info_dict): + """ + Disable thermal control algorithm + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + from .thermal_infos import FanInfo + from .thermal import Thermal + from .thermal_conditions import UpdateCoolingLevelToMinCondition + from .fan import Fan + status_changed = Thermal.set_thermal_algorithm_status(self.status, False) + + # Only update cooling level if thermal algorithm status changed + if status_changed: + if self.status: + # Check thermal zone temperature, if all thermal zone temperature + # back to normal, set it to minimum allowed speed to + # save power + UpdateCoolingLevelToMinAction.update_cooling_level_to_minimum(thermal_info_dict) + + logger.log_info('Changed thermal algorithm status to {}'.format(self.status)) + + +@thermal_json_object('thermal.recover') +class ThermalRecoverAction(ThermalPolicyActionBase): + def execute(self, thermal_info_dict): + UpdateCoolingLevelToMinAction.update_cooling_level_to_minimum(thermal_info_dict) + + +class ChangeMinCoolingLevelAction(ThermalPolicyActionBase): + UNKNOWN_SKU_COOLING_LEVEL = 6 + def execute(self, thermal_info_dict): + from .device_data import DEVICE_DATA + from .fan import Fan + from .thermal_infos import ChassisInfo + from .thermal_conditions import MinCoolingLevelChangeCondition + from .thermal_conditions import UpdateCoolingLevelToMinCondition + + chassis = thermal_info_dict[ChassisInfo.INFO_NAME].get_chassis() + if chassis.platform_name not in DEVICE_DATA or 'thermal' not in DEVICE_DATA[chassis.platform_name] or 'minimum_table' not in DEVICE_DATA[chassis.platform_name]['thermal']: + Fan.min_cooling_level = ChangeMinCoolingLevelAction.UNKNOWN_SKU_COOLING_LEVEL + else: + trust_state = MinCoolingLevelChangeCondition.trust_state + temperature = MinCoolingLevelChangeCondition.temperature + minimum_table = DEVICE_DATA[chassis.platform_name]['thermal']['minimum_table']['unk_{}'.format(trust_state)] + + for key, cooling_level in minimum_table.items(): + temp_range = key.split(':') + temp_min = int(temp_range[0].strip()) + temp_max = int(temp_range[1].strip()) + if temp_min <= temperature <= temp_max: + Fan.min_cooling_level = cooling_level - 10 + break + + current_cooling_level = Fan.get_cooling_level() + if current_cooling_level < Fan.min_cooling_level: + Fan.set_cooling_level(Fan.min_cooling_level, Fan.min_cooling_level) + SetAllFanSpeedAction.set_psu_fan_speed(thermal_info_dict, Fan.min_cooling_level * 10) + else: + Fan.set_cooling_level(Fan.min_cooling_level, current_cooling_level) + UpdateCoolingLevelToMinAction.update_cooling_level_to_minimum(thermal_info_dict) + + +class UpdatePsuFanSpeedAction(ThermalPolicyActionBase): + def execute(self, thermal_info_dict): + from .thermal_conditions import CoolingLevelChangeCondition + SetAllFanSpeedAction.set_psu_fan_speed(thermal_info_dict, CoolingLevelChangeCondition.cooling_level * 10) + + +class UpdateCoolingLevelToMinAction(ThermalPolicyActionBase): + def execute(self, thermal_info_dict): + self.update_cooling_level_to_minimum(thermal_info_dict) + + @classmethod + def update_cooling_level_to_minimum(cls, thermal_info_dict): + from .fan import Fan + from .thermal import Thermal + from .thermal_conditions import UpdateCoolingLevelToMinCondition + from .thermal_infos import FanInfo + if Thermal.check_thermal_zone_temperature(): + fan_info_obj = thermal_info_dict[FanInfo.INFO_NAME] + speed = Fan.min_cooling_level * 10 + for fan in fan_info_obj.get_presence_fans(): + fan.set_speed(speed) + SetAllFanSpeedAction.set_psu_fan_speed(thermal_info_dict, speed) + UpdateCoolingLevelToMinCondition.enable = False + else: + UpdateCoolingLevelToMinCondition.enable = True + diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py new file mode 100644 index 000000000000..a682061d12a8 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py @@ -0,0 +1,126 @@ +from sonic_platform_base.sonic_thermal_control.thermal_condition_base import ThermalPolicyConditionBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object + + +class FanCondition(ThermalPolicyConditionBase): + def get_fan_info(self, thermal_info_dict): + from .thermal_infos import FanInfo + if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo): + return thermal_info_dict[FanInfo.INFO_NAME] + else: + return None + + +@thermal_json_object('fan.any.absence') +class AnyFanAbsenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fans()) > 0 if fan_info_obj else False + + +@thermal_json_object('fan.all.absence') +class AllFanAbsenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_presence_fans()) == 0 if fan_info_obj else False + + +@thermal_json_object('fan.all.presence') +class AllFanPresenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fans()) == 0 if fan_info_obj else False + + +@thermal_json_object('fan.any.fault') +class AnyFanFaultCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_fault_fans()) > 0 if fan_info_obj else False + + +@thermal_json_object('fan.all.good') +class AllFanGoodCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_fault_fans()) == 0 if fan_info_obj else False + + +class PsuCondition(ThermalPolicyConditionBase): + def get_psu_info(self, thermal_info_dict): + from .thermal_infos import PsuInfo + if PsuInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[PsuInfo.INFO_NAME], PsuInfo): + return thermal_info_dict[PsuInfo.INFO_NAME] + else: + return None + + +@thermal_json_object('psu.any.absence') +class AnyPsuAbsenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_absence_psus()) > 0 if psu_info_obj else False + + +@thermal_json_object('psu.all.absence') +class AllPsuAbsenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_presence_psus()) == 0 if psu_info_obj else False + + +@thermal_json_object('psu.all.presence') +class AllPsuPresenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_absence_psus()) == 0 if psu_info_obj else False + + +class MinCoolingLevelChangeCondition(ThermalPolicyConditionBase): + trust_state = None + temperature = None + + def is_match(self, thermal_info_dict): + from .thermal import Thermal + + trust_state = Thermal.check_module_temperature_trustable() + temperature = Thermal.get_min_amb_temperature() + temperature = int(temperature / 1000) + + change_cooling_level = False + if trust_state != MinCoolingLevelChangeCondition.trust_state: + MinCoolingLevelChangeCondition.trust_state = trust_state + change_cooling_level = True + + if temperature != MinCoolingLevelChangeCondition.temperature: + MinCoolingLevelChangeCondition.temperature = temperature + change_cooling_level = True + + return change_cooling_level + + +class CoolingLevelChangeCondition(ThermalPolicyConditionBase): + cooling_level = None + + def is_match(self, thermal_info_dict): + from .fan import Fan + current_cooling_level = Fan.get_cooling_level() + if current_cooling_level != CoolingLevelChangeCondition.cooling_level: + CoolingLevelChangeCondition.cooling_level = current_cooling_level + return True + else: + return False + + +class UpdateCoolingLevelToMinCondition(ThermalPolicyConditionBase): + enable = False + def is_match(self, thermal_info_dict): + if not UpdateCoolingLevelToMinCondition.enable: + return False + + from .fan import Fan + current_cooling_level = Fan.get_cooling_level() + if current_cooling_level == Fan.min_cooling_level: + UpdateCoolingLevelToMinCondition.enable = False + return False + return True diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py new file mode 100644 index 000000000000..e810a5646456 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py @@ -0,0 +1,154 @@ +from sonic_platform_base.sonic_thermal_control.thermal_info_base import ThermalPolicyInfoBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object + + +@thermal_json_object('fan_info') +class FanInfo(ThermalPolicyInfoBase): + """ + Fan information needed by thermal policy + """ + + # Fan information name + INFO_NAME = 'fan_info' + + def __init__(self): + self._absence_fans = set() + self._presence_fans = set() + self._fault_fans = set() + self._status_changed = False + + def collect(self, chassis): + """ + Collect absence and presence fans. + :param chassis: The chassis object + :return: + """ + self._status_changed = False + for fan in chassis.get_all_fans(): + presence = fan.get_presence() + status = fan.get_status() + if presence and fan not in self._presence_fans: + self._presence_fans.add(fan) + self._status_changed = True + if fan in self._absence_fans: + self._absence_fans.remove(fan) + elif not presence and fan not in self._absence_fans: + self._absence_fans.add(fan) + self._status_changed = True + if fan in self._presence_fans: + self._presence_fans.remove(fan) + + if not status and fan not in self._fault_fans: + self._fault_fans.add(fan) + self._status_changed = True + elif status and fan in self._fault_fans: + self._fault_fans.remove(fan) + self._status_changed = True + + + def get_absence_fans(self): + """ + Retrieves absence fans + :return: A set of absence fans + """ + return self._absence_fans + + def get_presence_fans(self): + """ + Retrieves presence fans + :return: A set of presence fans + """ + return self._presence_fans + + def get_fault_fans(self): + """ + Retrieves fault fans + :return: A set of fault fans + """ + return self._fault_fans + + def is_status_changed(self): + """ + Retrieves if the status of fan information changed + :return: True if status changed else False + """ + return self._status_changed + + +@thermal_json_object('psu_info') +class PsuInfo(ThermalPolicyInfoBase): + """ + PSU information needed by thermal policy + """ + INFO_NAME = 'psu_info' + + def __init__(self): + self._absence_psus = set() + self._presence_psus = set() + self._status_changed = False + + def collect(self, chassis): + """ + Collect absence and presence PSUs. + :param chassis: The chassis object + :return: + """ + self._status_changed = False + for psu in chassis.get_all_psus(): + if psu.get_presence() and psu.get_powergood_status() and psu not in self._presence_psus: + self._presence_psus.add(psu) + self._status_changed = True + if psu in self._absence_psus: + self._absence_psus.remove(psu) + elif (not psu.get_presence() or not psu.get_powergood_status()) and psu not in self._absence_psus: + self._absence_psus.add(psu) + self._status_changed = True + if psu in self._presence_psus: + self._presence_psus.remove(psu) + + def get_absence_psus(self): + """ + Retrieves presence PSUs + :return: A set of absence PSUs + """ + return self._absence_psus + + def get_presence_psus(self): + """ + Retrieves presence PSUs + :return: A set of presence fans + """ + return self._presence_psus + + def is_status_changed(self): + """ + Retrieves if the status of PSU information changed + :return: True if status changed else False + """ + return self._status_changed + + +@thermal_json_object('chassis_info') +class ChassisInfo(ThermalPolicyInfoBase): + """ + Chassis information needed by thermal policy + """ + INFO_NAME = 'chassis_info' + + def __init__(self): + self._chassis = None + + def collect(self, chassis): + """ + Collect platform chassis. + :param chassis: The chassis object + :return: + """ + self._chassis = chassis + + def get_chassis(self): + """ + Retrieves platform chassis object + :return: A platform chassis object. + """ + return self._chassis diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_manager.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_manager.py new file mode 100644 index 000000000000..914eec79816c --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_manager.py @@ -0,0 +1,65 @@ +import os +from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase +from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy +from .thermal_actions import * +from .thermal_conditions import * +from .thermal_infos import * + + +class ThermalManager(ThermalManagerBase): + @classmethod + def initialize(cls): + """ + Initialize thermal manager, including register thermal condition types and thermal action types + and any other vendor specific initialization. + :return: + """ + cls._add_private_thermal_policy() + + @classmethod + def deinitialize(cls): + """ + Destroy thermal manager, including any vendor specific cleanup. The default behavior of this function + is a no-op. + :return: + """ + cls.start_thermal_control_algorithm() + + @classmethod + def start_thermal_control_algorithm(cls): + """ + Start thermal control algorithm + + Returns: + bool: True if set success, False if fail. + """ + from .thermal import Thermal + Thermal.set_thermal_algorithm_status(True) + + @classmethod + def stop_thermal_control_algorithm(cls): + """ + Stop thermal control algorithm + + Returns: + bool: True if set success, False if fail. + """ + from .thermal import Thermal + Thermal.set_thermal_algorithm_status(False) + + @classmethod + def _add_private_thermal_policy(cls): + dynamic_min_speed_policy = ThermalPolicy() + dynamic_min_speed_policy.conditions[MinCoolingLevelChangeCondition] = MinCoolingLevelChangeCondition() + dynamic_min_speed_policy.actions[ChangeMinCoolingLevelAction] = ChangeMinCoolingLevelAction() + cls._policy_dict['DynamicMinCoolingLevelPolicy'] = dynamic_min_speed_policy + + update_psu_fan_speed_policy = ThermalPolicy() + update_psu_fan_speed_policy.conditions[CoolingLevelChangeCondition] = CoolingLevelChangeCondition() + update_psu_fan_speed_policy.actions[UpdatePsuFanSpeedAction] = UpdatePsuFanSpeedAction() + cls._policy_dict['UpdatePsuFanSpeedPolicy'] = update_psu_fan_speed_policy + + update_cooling_level_policy = ThermalPolicy() + update_cooling_level_policy.conditions[UpdateCoolingLevelToMinCondition] = UpdateCoolingLevelToMinCondition() + update_cooling_level_policy.actions[UpdateCoolingLevelToMinAction] = UpdateCoolingLevelToMinAction() + cls._policy_dict['UpdateCoolingLevelPolicy'] = update_cooling_level_policy diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/utils.py b/platform/mellanox/mlnx-platform-api/sonic_platform/utils.py new file mode 100644 index 000000000000..d5175acf8d0e --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/utils.py @@ -0,0 +1,57 @@ +def read_str_from_file(file_path, default='', raise_exception=False): + """ + Read string content from file + :param file_path: File path + :param default: Default return value if any exception occur + :param raise_exception: Raise exception to caller if True else just return default value + :return: String content of the file + """ + try: + with open(file_path, 'r') as f: + value = f.read().strip() + except (ValueError, IOError) as e: + if not raise_exception: + value = default + else: + raise e + + return value + + +def read_int_from_file(file_path, default=0, raise_exception=False): + """ + Read content from file and cast it to integer + :param file_path: File path + :param default: Default return value if any exception occur + :param raise_exception: Raise exception to caller if True else just return default value + :return: Integer value of the file content + """ + try: + with open(file_path, 'r') as f: + value = int(f.read().strip()) + except (ValueError, IOError) as e: + if not raise_exception: + value = default + else: + raise e + + return value + + +def write_file(file_path, content, raise_exception=False): + """ + Write the given value to a file + :param file_path: File path + :param content: Value to write to the file + :param raise_exception: Raise exception to caller if True + :return: True if write success else False + """ + try: + with open(file_path, 'w') as f: + f.write(str(content)) + except (ValueError, IOError) as e: + if not raise_exception: + return False + else: + raise e + return True diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/watchdog.py b/platform/mellanox/mlnx-platform-api/sonic_platform/watchdog.py new file mode 100644 index 000000000000..e9694f1b2a59 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/watchdog.py @@ -0,0 +1,288 @@ +#!/usr/bin/env python + +""" +Mellanox + +Module contains an implementation of SONiC Platform Base API and +provides access to hardware watchdog on Mellanox platforms +""" + +import os +import fcntl +import array +import time + +from sonic_platform_base.watchdog_base import WatchdogBase + +""" ioctl constants """ +IO_WRITE = 0x40000000 +IO_READ = 0x80000000 +IO_READ_WRITE = 0xC0000000 +IO_SIZE_INT = 0x00040000 +IO_SIZE_40 = 0x00280000 +IO_TYPE_WATCHDOG = ord('W') << 8 + +WDR_INT = IO_READ | IO_SIZE_INT | IO_TYPE_WATCHDOG +WDR_40 = IO_READ | IO_SIZE_40 | IO_TYPE_WATCHDOG +WDWR_INT = IO_READ_WRITE | IO_SIZE_INT | IO_TYPE_WATCHDOG + +""" Watchdog ioctl commands """ +WDIOC_GETSUPPORT = 0 | WDR_40 +WDIOC_GETSTATUS = 1 | WDR_INT +WDIOC_GETBOOTSTATUS = 2 | WDR_INT +WDIOC_GETTEMP = 3 | WDR_INT +WDIOC_SETOPTIONS = 4 | WDR_INT +WDIOC_KEEPALIVE = 5 | WDR_INT +WDIOC_SETTIMEOUT = 6 | WDWR_INT +WDIOC_GETTIMEOUT = 7 | WDR_INT +WDIOC_SETPRETIMEOUT = 8 | WDWR_INT +WDIOC_GETPRETIMEOUT = 9 | WDR_INT +WDIOC_GETTIMELEFT = 10 | WDR_INT + +""" Watchdog status constants """ +WDIOS_DISABLECARD = 0x0001 +WDIOS_ENABLECARD = 0x0002 + +""" Mellanox main watchdog identity string """ +WD_MLNX_MAIN_IDENTITY = "mlx-wdt-main" +""" watchdog sysfs """ +WD_SYSFS_PATH = "/sys/class/watchdog/" + + +WD_COMMON_ERROR = -1 + + +class WatchdogImplBase(WatchdogBase): + """ + Base class that implements common logic for interacting + with watchdog using ioctl commands + """ + + def __init__(self, wd_device_path): + """ + Open a watchdog handle + @param wd_device_path Path to watchdog device + """ + + self.watchdog_path = wd_device_path + self.watchdog = os.open(self.watchdog_path, os.O_WRONLY) + + # Opening a watchdog descriptor starts + # watchdog timer; + # by default it should be stopped + self._disablecard() + self.armed = False + + self.timeout = self._gettimeout() + + def _enablecard(self): + """ + Turn on the watchdog timer + """ + + req = array.array('h', [WDIOS_ENABLECARD]) + fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False) + + def _disablecard(self): + """ + Turn off the watchdog timer + """ + + req = array.array('h', [WDIOS_DISABLECARD]) + fcntl.ioctl(self.watchdog, WDIOC_SETOPTIONS, req, False) + + def _keepalive(self): + """ + Keep alive watchdog timer + """ + + fcntl.ioctl(self.watchdog, WDIOC_KEEPALIVE) + + def _settimeout(self, seconds): + """ + Set watchdog timer timeout + @param seconds - timeout in seconds + @return is the actual set timeout + """ + + req = array.array('I', [seconds]) + fcntl.ioctl(self.watchdog, WDIOC_SETTIMEOUT, req, True) + + return int(req[0]) + + def _gettimeout(self): + """ + Get watchdog timeout + @return watchdog timeout + """ + + req = array.array('I', [0]) + fcntl.ioctl(self.watchdog, WDIOC_GETTIMEOUT, req, True) + + return int(req[0]) + + def _gettimeleft(self): + """ + Get time left before watchdog timer expires + @return time left in seconds + """ + + req = array.array('I', [0]) + fcntl.ioctl(self.watchdog, WDIOC_GETTIMELEFT, req, True) + + return int(req[0]) + + def arm(self, seconds): + """ + Implements arm WatchdogBase API + """ + + ret = WD_COMMON_ERROR + if seconds < 0: + return ret + + try: + if self.timeout != seconds: + self.timeout = self._settimeout(seconds) + if self.armed: + self._keepalive() + else: + self._enablecard() + self.armed = True + ret = self.timeout + except IOError: + pass + + return ret + + def disarm(self): + """ + Implements disarm WatchdogBase API + """ + + disarmed = False + if self.armed: + try: + self._disablecard() + self.armed = False + disarmed = True + except IOError: + pass + + return disarmed + + def is_armed(self): + """ + Implements is_armed WatchdogBase API + """ + + return self.armed + + def get_remaining_time(self): + """ + Implements get_remaining_time WatchdogBase API + """ + + timeleft = WD_COMMON_ERROR + + if self.armed: + try: + timeleft = self._gettimeleft() + except IOError: + pass + + return timeleft + + def __del__(self): + """ + Close watchdog + """ + + os.close(self.watchdog) + + +class WatchdogType1(WatchdogImplBase): + """ + Watchdog type 1 + """ + + def arm(self, seconds): + """ + Call arm from WatchdgoImplBase and save the timestamp + when the watchdog was armed + """ + + ret = WatchdogImplBase.arm(self, seconds) + # Save the watchdog arm timestamp + # requiered for get_remaining_time() + self.arm_timestamp = time.time() + + return ret + + def get_remaining_time(self): + """ + Watchdog Type 1 does not support timeleft + operation, we will calculate timeleft based + on timeout and arm timestamp + """ + + timeleft = WD_COMMON_ERROR + + if self.armed: + timeleft = int(self.timeout - (time.time() - self.arm_timestamp)) + + return timeleft + +class WatchdogType2(WatchdogImplBase): + """ + Watchdog type 2 + """ + + pass + + +def is_mlnx_wd_main(dev): + """ + Checks if dev is Mellanox main watchdog + """ + + try: + with open("{}/{}/identity".format(WD_SYSFS_PATH, dev)) as identity_file: + identity = identity_file.read().strip() + if identity == WD_MLNX_MAIN_IDENTITY: + return True + except IOError: + pass + + return False + + +def is_wd_type2(dev): + """ + Checks if dev is Mellanox type 2 watchdog + """ + + return os.path.exists("{}/{}/timeleft".format(WD_SYSFS_PATH, dev)) + + +def get_watchdog(): + """ + Return WatchdogType1 or WatchdogType2 based on system + """ + + watchdog_main_device_name = None + + for device in os.listdir("/dev/"): + if device.startswith("watchdog") and is_mlnx_wd_main(device): + watchdog_main_device_name = device + + watchdog_device_path = "/dev/{}".format(watchdog_main_device_name) + + watchdog = None + + if is_wd_type2(watchdog_main_device_name): + watchdog = WatchdogType2(watchdog_device_path) + else: + watchdog = WatchdogType1(watchdog_device_path) + + return watchdog diff --git a/platform/mellanox/mlnx-platform-api/tests/__init__.py b/platform/mellanox/mlnx-platform-api/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/mellanox/mlnx-platform-api/tests/duplicate_action.json b/platform/mellanox/mlnx-platform-api/tests/duplicate_action.json new file mode 100644 index 000000000000..c19787aa26e0 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/duplicate_action.json @@ -0,0 +1,18 @@ +{ + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] +} diff --git a/platform/mellanox/mlnx-platform-api/tests/duplicate_condition.json b/platform/mellanox/mlnx-platform-api/tests/duplicate_condition.json new file mode 100644 index 000000000000..c25d84762e2a --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/duplicate_condition.json @@ -0,0 +1,17 @@ +{ + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + }, + { + "type": "fan.any.absence" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] +} diff --git a/platform/mellanox/mlnx-platform-api/tests/empty_action.json b/platform/mellanox/mlnx-platform-api/tests/empty_action.json new file mode 100644 index 000000000000..b1051b5a6f60 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/empty_action.json @@ -0,0 +1,10 @@ +{ + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + } + ], + "actions": [ + ] +} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/tests/empty_condition.json b/platform/mellanox/mlnx-platform-api/tests/empty_condition.json new file mode 100644 index 000000000000..e7a588459246 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/empty_condition.json @@ -0,0 +1,11 @@ +{ + "name": "any fan absence", + "conditions": [ + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] +} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/tests/mock_platform.py b/platform/mellanox/mlnx-platform-api/tests/mock_platform.py new file mode 100644 index 000000000000..8edb9d4fb163 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/mock_platform.py @@ -0,0 +1,62 @@ +class MockFan: + speed = 60 + def __init__(self): + self.presence = True + self.name = None + self.status = True + + def get_presence(self): + return self.presence + + def set_speed(self, speed): + MockFan.speed = speed + + def get_status(self): + return self.status + + def get_target_speed(self): + return MockFan.speed + + def get_name(self): + return self.name + + +class MockPsu: + def __init__(self): + self.presence = True + self.powergood = True + + def get_presence(self): + return self.presence + + def get_powergood_status(self): + return self.powergood + + def get_all_fans(self): + return [] + + +class MockChassis: + def __init__(self): + self.fan_list = [] + self.psu_list = [] + + def get_all_psus(self): + return self.psu_list + + def get_all_fans(self): + return self.fan_list + + def get_thermal_manager(self): + from sonic_platform.thermal_manager import ThermalManager + return ThermalManager + + def make_fan_absence(self): + fan = MockFan() + fan.presence = False + self.fan_list.append(fan) + + def make_psu_absence(self): + psu = MockPsu() + psu.presence = False + self.psu_list.append(psu) diff --git a/platform/mellanox/mlnx-platform-api/tests/policy_with_same_conditions.json b/platform/mellanox/mlnx-platform-api/tests/policy_with_same_conditions.json new file mode 100644 index 000000000000..ace291be1c55 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/policy_with_same_conditions.json @@ -0,0 +1,75 @@ +{ + "thermal_control_algorithm": { + "run_at_boot_up": "false", + "fan_speed_when_suspend": "60" + }, + "info_types": [ + { + "type": "fan_info" + }, + { + "type": "psu_info" + }, + { + "type": "chassis_info" + } + ], + "policies": [ + { + "name": "all fan and psu presence", + "conditions": [ + { + "type": "fan.all.presence" + }, + { + "type": "psu.all.presence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any psu absence", + "conditions": [ + { + "type": "psu.any.absence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "all fan and psu presence 1", + "conditions": [ + { + "type": "fan.all.presence" + }, + { + "type": "psu.all.presence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "true" + } + ] + } + ] +} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py b/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py new file mode 100644 index 000000000000..bb9ee7e125a2 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py @@ -0,0 +1,57 @@ +import os +import sys +import pytest +from mock import MagicMock +from .mock_platform import MockFan + +test_path = os.path.dirname(os.path.abspath(__file__)) +modules_path = os.path.dirname(test_path) +sys.path.insert(0, modules_path) + +from sonic_platform.fan import Fan +from sonic_platform.led import FanLed +from sonic_platform.fan_drawer import RealDrawer +from sonic_platform.device_data import DEVICE_DATA + + +def test_get_absence_fan_direction(): + fan_drawer = RealDrawer(0, DEVICE_DATA['x86_64-mlnx_msn2700-r0']['fans']) + fan = Fan(0, fan_drawer, 1) + fan_drawer.get_presence = MagicMock(return_value=False) + + assert not fan.is_psu_fan + assert fan.get_direction() == Fan.FAN_DIRECTION_NOT_APPLICABLE + + +def test_fan_drawer_set_status_led(): + fan_drawer = RealDrawer(0, DEVICE_DATA['x86_64-mlnx_msn2700-r0']['fans']) + with pytest.raises(Exception): + fan_drawer.set_status_led(None, 'Invalid color') + + with pytest.raises(Exception): + fan_drawer.set_status_led(None, Fan.STATUS_LED_COLOR_RED) + + fan1 = Fan(0, fan_drawer, 1) + fan2 = Fan(1, fan_drawer, 2) + fan_list = fan_drawer.get_all_fans() + fan_list.append(fan1) + fan_list.append(fan2) + + FanLed.set_status = MagicMock() + + fan1.set_status_led(Fan.STATUS_LED_COLOR_RED) + fan_drawer.set_status_led(Fan.STATUS_LED_COLOR_RED) + FanLed.set_status.assert_called_with(Fan.STATUS_LED_COLOR_RED) + + fan2.set_status_led(Fan.STATUS_LED_COLOR_GREEN) + fan_drawer.set_status_led(Fan.STATUS_LED_COLOR_GREEN) + FanLed.set_status.assert_called_with(Fan.STATUS_LED_COLOR_RED) + + fan1.set_status_led(Fan.STATUS_LED_COLOR_GREEN) + fan_drawer.set_status_led(Fan.STATUS_LED_COLOR_GREEN) + FanLed.set_status.assert_called_with(Fan.STATUS_LED_COLOR_GREEN) + + fan1.set_status_led(Fan.STATUS_LED_COLOR_RED) + fan_drawer.set_status_led(Fan.STATUS_LED_COLOR_RED) + FanLed.set_status.assert_called_with(Fan.STATUS_LED_COLOR_RED) + diff --git a/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py b/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py new file mode 100644 index 000000000000..4d69a39c58a1 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py @@ -0,0 +1,514 @@ +import os +import sys +import pytest +import json +from mock import MagicMock +from .mock_platform import MockChassis, MockFan, MockPsu + +test_path = os.path.dirname(os.path.abspath(__file__)) +modules_path = os.path.dirname(test_path) +sys.path.insert(0, modules_path) + +from sonic_platform.thermal_manager import ThermalManager +from sonic_platform.thermal_infos import FanInfo, PsuInfo +from sonic_platform.fan import Fan +from sonic_platform.thermal import Thermal + +Thermal.check_thermal_zone_temperature = MagicMock() +Thermal.set_thermal_algorithm_status = MagicMock() + + +@pytest.fixture(scope='session', autouse=True) +def thermal_manager(): + policy_file = os.path.join(test_path, 'thermal_policy.json') + ThermalManager.load(policy_file) + return ThermalManager + + +def test_load_policy(thermal_manager): + assert 'psu_info' in thermal_manager._thermal_info_dict + assert 'fan_info' in thermal_manager._thermal_info_dict + assert 'chassis_info' in thermal_manager._thermal_info_dict + + assert 'any fan absence' in thermal_manager._policy_dict + assert 'any psu absence' in thermal_manager._policy_dict + assert 'any fan broken' in thermal_manager._policy_dict + assert 'all fan and psu presence' in thermal_manager._policy_dict + + assert thermal_manager._fan_speed_when_suspend == 60 + assert thermal_manager._run_thermal_algorithm_at_boot_up == False + + +def test_fan_info(): + chassis = MockChassis() + chassis.make_fan_absence() + fan_info = FanInfo() + fan_info.collect(chassis) + assert len(fan_info.get_absence_fans()) == 1 + assert len(fan_info.get_presence_fans()) == 0 + assert len(fan_info.get_fault_fans()) == 0 + assert fan_info.is_status_changed() + + fan_list = chassis.get_all_fans() + fan_list[0].presence = True + fan_info.collect(chassis) + assert len(fan_info.get_absence_fans()) == 0 + assert len(fan_info.get_presence_fans()) == 1 + assert len(fan_info.get_fault_fans()) == 0 + assert fan_info.is_status_changed() + + fan_list[0].status = False + fan_info.collect(chassis) + assert len(fan_info.get_absence_fans()) == 0 + assert len(fan_info.get_presence_fans()) == 1 + assert len(fan_info.get_fault_fans()) == 1 + assert fan_info.is_status_changed() + +def test_psu_info(): + chassis = MockChassis() + chassis.make_psu_absence() + psu_info = PsuInfo() + psu_info.collect(chassis) + assert len(psu_info.get_absence_psus()) == 1 + assert len(psu_info.get_presence_psus()) == 0 + assert psu_info.is_status_changed() + + psu_list = chassis.get_all_psus() + psu_list[0].presence = True + psu_info.collect(chassis) + assert len(psu_info.get_absence_psus()) == 0 + assert len(psu_info.get_presence_psus()) == 1 + assert psu_info.is_status_changed() + + psu_list[0].powergood = False + psu_info.collect(chassis) + assert len(psu_info.get_absence_psus()) == 1 + assert len(psu_info.get_presence_psus()) == 0 + assert psu_info.is_status_changed() + + +def test_fan_policy(thermal_manager): + chassis = MockChassis() + chassis.make_fan_absence() + chassis.fan_list.append(MockFan()) + thermal_manager.run_policy(chassis) + + fan_list = chassis.get_all_fans() + assert fan_list[1].speed == 100 + Thermal.set_thermal_algorithm_status.assert_called_with(False, False) + + fan_list[0].presence = True + Thermal.check_thermal_zone_temperature = MagicMock(return_value=True) + thermal_manager.run_policy(chassis) + Thermal.set_thermal_algorithm_status.assert_called_with(True, False) + assert Thermal.check_thermal_zone_temperature.call_count == 2 + assert fan_list[0].speed == 60 + assert fan_list[1].speed == 60 + + fan_list[0].status = False + thermal_manager.run_policy(chassis) + Thermal.set_thermal_algorithm_status.assert_called_with(False, False) + + fan_list[0].status = True + Thermal.check_thermal_zone_temperature = MagicMock(return_value=False) + thermal_manager.run_policy(chassis) + Thermal.set_thermal_algorithm_status.assert_called_with(True, False) + assert Thermal.check_thermal_zone_temperature.call_count == 2 + assert fan_list[0].speed == 100 + assert fan_list[1].speed == 100 + + +def test_psu_policy(thermal_manager): + chassis = MockChassis() + chassis.make_psu_absence() + chassis.fan_list.append(MockFan()) + thermal_manager.run_policy(chassis) + + fan_list = chassis.get_all_fans() + assert fan_list[0].speed == 100 + Thermal.set_thermal_algorithm_status.assert_called_with(False, False) + + psu_list = chassis.get_all_psus() + psu_list[0].presence = True + thermal_manager.run_policy(chassis) + Thermal.set_thermal_algorithm_status.assert_called_with(True, False) + + +def test_any_fan_absence_condition(): + chassis = MockChassis() + chassis.make_fan_absence() + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_conditions import AnyFanAbsenceCondition + condition = AnyFanAbsenceCondition() + assert condition.is_match({'fan_info': fan_info}) + + fan = chassis.get_all_fans()[0] + fan.presence = True + fan_info.collect(chassis) + assert not condition.is_match({'fan_info': fan_info}) + + +def test_all_fan_absence_condition(): + chassis = MockChassis() + chassis.make_fan_absence() + fan = MockFan() + fan_list = chassis.get_all_fans() + fan_list.append(fan) + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_conditions import AllFanAbsenceCondition + condition = AllFanAbsenceCondition() + assert not condition.is_match({'fan_info': fan_info}) + + fan.presence = False + fan_info.collect(chassis) + assert condition.is_match({'fan_info': fan_info}) + + +def test_all_fan_presence_condition(): + chassis = MockChassis() + chassis.make_fan_absence() + fan = MockFan() + fan_list = chassis.get_all_fans() + fan_list.append(fan) + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_conditions import AllFanPresenceCondition + condition = AllFanPresenceCondition() + assert not condition.is_match({'fan_info': fan_info}) + + fan_list[0].presence = True + fan_info.collect(chassis) + assert condition.is_match({'fan_info': fan_info}) + +def test_any_fan_fault_condition(): + chassis = MockChassis() + fan = MockFan() + fan_list = chassis.get_all_fans() + fan_list.append(fan) + fault_fan = MockFan() + fault_fan.status = False + fan_list.append(fault_fan) + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_conditions import AnyFanFaultCondition + condition = AnyFanFaultCondition() + assert condition.is_match({'fan_info': fan_info}) + + fault_fan.status = True + fan_info.collect(chassis) + assert not condition.is_match({'fan_info': fan_info}) + +def test_all_fan_good_condition(): + chassis = MockChassis() + fan = MockFan() + fan_list = chassis.get_all_fans() + fan_list.append(fan) + fault_fan = MockFan() + fault_fan.status = False + fan_list.append(fault_fan) + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_conditions import AllFanGoodCondition + condition = AllFanGoodCondition() + assert not condition.is_match({'fan_info': fan_info}) + + fault_fan.status = True + fan_info.collect(chassis) + assert condition.is_match({'fan_info': fan_info}) + + +def test_any_psu_absence_condition(): + chassis = MockChassis() + chassis.make_psu_absence() + psu_info = PsuInfo() + psu_info.collect(chassis) + + from sonic_platform.thermal_conditions import AnyPsuAbsenceCondition + condition = AnyPsuAbsenceCondition() + assert condition.is_match({'psu_info': psu_info}) + + psu = chassis.get_all_psus()[0] + psu.presence = True + psu_info.collect(chassis) + assert not condition.is_match({'psu_info': psu_info}) + + +def test_all_psu_absence_condition(): + chassis = MockChassis() + chassis.make_psu_absence() + psu = MockPsu() + psu_list = chassis.get_all_psus() + psu_list.append(psu) + psu_info = PsuInfo() + psu_info.collect(chassis) + + from sonic_platform.thermal_conditions import AllPsuAbsenceCondition + condition = AllPsuAbsenceCondition() + assert not condition.is_match({'psu_info': psu_info}) + + psu.presence = False + psu_info.collect(chassis) + assert condition.is_match({'psu_info': psu_info}) + + +def test_all_fan_presence_condition(): + chassis = MockChassis() + chassis.make_psu_absence() + psu = MockPsu() + psu_list = chassis.get_all_psus() + psu_list.append(psu) + psu_info = PsuInfo() + psu_info.collect(chassis) + + from sonic_platform.thermal_conditions import AllPsuPresenceCondition + condition = AllPsuPresenceCondition() + assert not condition.is_match({'psu_info': psu_info}) + + psu_list[0].presence = True + psu_info.collect(chassis) + assert condition.is_match({'psu_info': psu_info}) + + +def test_load_set_fan_speed_action(): + from sonic_platform.thermal_actions import SetAllFanSpeedAction + action = SetAllFanSpeedAction() + json_str = '{\"speed\": \"50\"}' + json_obj = json.loads(json_str) + action.load_from_json(json_obj) + assert action.speed == 50 + + json_str = '{\"speed\": \"-1\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + json_str = '{\"speed\": \"101\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + json_str = '{\"invalid\": \"101\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + +def test_execute_set_fan_speed_action(): + chassis = MockChassis() + fan_list = chassis.get_all_fans() + fan_list.append(MockFan()) + fan_list.append(MockFan()) + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_actions import SetAllFanSpeedAction + action = SetAllFanSpeedAction() + action.speed = 99 + action.execute({'fan_info': fan_info}) + assert fan_list[0].speed == 99 + assert fan_list[1].speed == 99 + + +def test_load_control_thermal_algo_action(): + from sonic_platform.thermal_actions import ControlThermalAlgoAction + action = ControlThermalAlgoAction() + json_str = '{\"status\": \"false\"}' + json_obj = json.loads(json_str) + action.load_from_json(json_obj) + assert not action.status + + json_str = '{\"status\": \"true\"}' + json_obj = json.loads(json_str) + action.load_from_json(json_obj) + assert action.status + + json_str = '{\"status\": \"invalid\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + json_str = '{\"invalid\": \"true\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + +def test_load_check_and_set_speed_action(): + from sonic_platform.thermal_actions import CheckAndSetAllFanSpeedAction + action = CheckAndSetAllFanSpeedAction() + json_str = '{\"speed\": \"40\"}' + json_obj = json.loads(json_str) + action.load_from_json(json_obj) + assert action.speed == 40 + + json_str = '{\"speed\": \"-1\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + json_str = '{\"speed\": \"101\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + json_str = '{\"invalid\": \"60\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + +def test_execute_check_and_set_fan_speed_action(): + chassis = MockChassis() + fan_list = chassis.get_all_fans() + fan_list.append(MockFan()) + fan_list.append(MockFan()) + fan_info = FanInfo() + fan_info.collect(chassis) + Thermal.check_thermal_zone_temperature = MagicMock(return_value=True) + + from sonic_platform.thermal_actions import CheckAndSetAllFanSpeedAction + action = CheckAndSetAllFanSpeedAction() + action.speed = 99 + action.execute({'fan_info': fan_info}) + assert fan_list[0].speed == 99 + assert fan_list[1].speed == 99 + + Thermal.check_thermal_zone_temperature = MagicMock(return_value=False) + fan_list[0].speed = 100 + fan_list[1].speed = 100 + action.speed = 60 + action.execute({'fan_info': fan_info}) + assert fan_list[0].speed == 100 + assert fan_list[1].speed == 100 + +def test_load_duplicate_condition(): + from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy + with open(os.path.join(test_path, 'duplicate_condition.json')) as f: + json_obj = json.load(f) + policy = ThermalPolicy() + with pytest.raises(Exception): + policy.load_from_json(json_obj) + +def test_load_duplicate_action(): + from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy + with open(os.path.join(test_path, 'duplicate_action.json')) as f: + json_obj = json.load(f) + policy = ThermalPolicy() + with pytest.raises(Exception): + policy.load_from_json(json_obj) + +def test_load_empty_condition(): + from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy + with open(os.path.join(test_path, 'empty_condition.json')) as f: + json_obj = json.load(f) + policy = ThermalPolicy() + with pytest.raises(Exception): + policy.load_from_json(json_obj) + +def test_load_empty_action(): + from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy + with open(os.path.join(test_path, 'empty_action.json')) as f: + json_obj = json.load(f) + policy = ThermalPolicy() + with pytest.raises(Exception): + policy.load_from_json(json_obj) + +def test_load_policy_with_same_conditions(): + from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase + class MockThermalManager(ThermalManagerBase): + pass + + with pytest.raises(Exception): + MockThermalManager.load(os.path.join(test_path, 'policy_with_same_conditions.json')) + +def test_dynamic_minimum_table_data(): + from sonic_platform.device_data import DEVICE_DATA + for platform, platform_data in DEVICE_DATA.items(): + if 'thermal' in platform_data and 'minimum_table' in platform_data['thermal']: + minimum_table = platform_data['thermal']['minimum_table'] + check_minimum_table_data(platform, minimum_table) + +def check_minimum_table_data(platform, minimum_table): + valid_dir = ['p2c', 'c2p', 'unk'] + valid_trust_state = ['trust', 'untrust'] + + for category, data in minimum_table.items(): + key_data = category.split('_') + assert key_data[0] in valid_dir + assert key_data[1] in valid_trust_state + + data_list = [(value, key) for key, value in data.items()] + data_list.sort(key=lambda x : x[0]) + + previous_edge = None + previous_cooling_level = None + for item in data_list: + cooling_level = item[0] + range_str = item[1] + + ranges = range_str.split(':') + low = int(ranges[0]) + high = int(ranges[1]) + assert low < high + + if previous_edge is None: + assert low == -127 + else: + assert low - previous_edge == 1, '{}-{}-{} error, item={}'.format(platform, key_data[0], key_data[1], item) + previous_edge = high + + assert 10 <= cooling_level <= 20 + if previous_cooling_level is not None: + assert cooling_level > previous_cooling_level + previous_cooling_level = cooling_level + +def test_dynamic_minimum_policy(thermal_manager): + from sonic_platform.thermal_conditions import MinCoolingLevelChangeCondition + from sonic_platform.thermal_actions import ChangeMinCoolingLevelAction + from sonic_platform.thermal_infos import ChassisInfo + from sonic_platform.thermal import Thermal + from sonic_platform.fan import Fan + ThermalManager.initialize() + assert 'DynamicMinCoolingLevelPolicy' in thermal_manager._policy_dict + policy = thermal_manager._policy_dict['DynamicMinCoolingLevelPolicy'] + assert MinCoolingLevelChangeCondition in policy.conditions + assert ChangeMinCoolingLevelAction in policy.actions + + condition = policy.conditions[MinCoolingLevelChangeCondition] + action = policy.actions[ChangeMinCoolingLevelAction] + Thermal.check_module_temperature_trustable = MagicMock(return_value='trust') + Thermal.get_min_amb_temperature = MagicMock(return_value=35001) + assert condition.is_match(None) + assert MinCoolingLevelChangeCondition.trust_state == 'trust' + assert MinCoolingLevelChangeCondition.temperature == 35 + assert not condition.is_match(None) + + Thermal.check_module_temperature_trustable = MagicMock(return_value='untrust') + assert condition.is_match(None) + assert MinCoolingLevelChangeCondition.trust_state == 'untrust' + + Thermal.get_min_amb_temperature = MagicMock(return_value=25999) + assert condition.is_match(None) + assert MinCoolingLevelChangeCondition.temperature == 25 + + chassis = MockChassis() + chassis.platform_name = 'invalid' + info = ChassisInfo() + info._chassis = chassis + thermal_info_dict = {ChassisInfo.INFO_NAME: info} + Fan.get_cooling_level = MagicMock(return_value=5) + Fan.set_cooling_level = MagicMock() + action.execute(thermal_info_dict) + assert Fan.min_cooling_level == 6 + Fan.set_cooling_level.assert_called_with(6, 6) + Fan.set_cooling_level.call_count = 0 + + chassis.platform_name = 'x86_64-mlnx_msn2700-r0' + action.execute(thermal_info_dict) + assert Fan.min_cooling_level == 3 + Fan.set_cooling_level.assert_called_with(3, 5) diff --git a/platform/mellanox/mlnx-platform-api/tests/thermal_policy.json b/platform/mellanox/mlnx-platform-api/tests/thermal_policy.json new file mode 100644 index 000000000000..413211b21220 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/thermal_policy.json @@ -0,0 +1,97 @@ +{ + "thermal_control_algorithm": { + "run_at_boot_up": "false", + "fan_speed_when_suspend": "60" + }, + "info_types": [ + { + "type": "fan_info" + }, + { + "type": "psu_info" + }, + { + "type": "chassis_info" + } + ], + "policies": [ + { + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any psu absence", + "conditions": [ + { + "type": "psu.any.absence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any fan broken", + "conditions": [ + { + "type": "fan.any.fault" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "all fan and psu presence", + "conditions": [ + { + "type": "fan.all.presence" + }, + { + "type": "psu.all.presence" + }, + { + "type": "fan.all.good" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "true" + }, + { + "type": "fan.all.check_and_set_speed", + "speed": "60" + } + ] + } + ] +} \ No newline at end of file diff --git a/platform/mellanox/mlnx-sai.dep b/platform/mellanox/mlnx-sai.dep new file mode 100644 index 000000000000..2a3862caa8e8 --- /dev/null +++ b/platform/mellanox/mlnx-sai.dep @@ -0,0 +1,21 @@ +# DPKG FRK + +SPATH := $($(MLNX_SAI)_SRC_PATH) +SLINKS := $(shell find $(SPATH) -type l -exec echo {} \; | grep -Ev ' ') +SMDEP_PATHS := $(shell git submodule status --recursive -- $(SPATH) | awk '{print $$2}' | grep -Ev ' ') +SMDEP_FILES := $(foreach path,$(SMDEP_PATHS),$(filter-out $(SMDEP_PATHS),$(addprefix $(path)/,$(shell cd $(path) && git ls-files | grep -Ev ' ')))) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/mlnx-sai.mk $(PLATFORM_PATH)/mlnx-sai.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(filter-out $(SMDEP_PATHS),$(shell git ls-files -- $(SPATH) | grep -Ev ' ')) + +$(MLNX_SAI)_CACHE_MODE := GIT_CONTENT_SHA +$(MLNX_SAI)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MLNX_SAI)_DEP_FILES := $(filter-out $(SLINKS),$(DEP_FILES)) +$(MLNX_SAI)_SMDEP_FILES := $(filter-out $(SLINKS),$(SMDEP_FILES)) +$(MLNX_SAI)_SMDEP_PATHS := $(SMDEP_PATHS) + +$(MLNX_SAI_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(MLNX_SAI_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MLNX_SAI_DBGSYM)_DEP_FILES := $(filter-out $(SLINKS),$(DEP_FILES)) +$(MLNX_SAI_DBGSYM)_SMDEP_FILES := $(filter-out $(SLINKS),$(SMDEP_FILES)) +$(MLNX_SAI_DBGSYM)_SMDEP_PATHS := $(SMDEP_PATHS) diff --git a/platform/mellanox/mlnx-sai.mk b/platform/mellanox/mlnx-sai.mk new file mode 100644 index 000000000000..7f16a72cc076 --- /dev/null +++ b/platform/mellanox/mlnx-sai.mk @@ -0,0 +1,14 @@ +# Mellanox SAI + +MLNX_SAI_VERSION = SAIRel1.18.1.0 + +export MLNX_SAI_VERSION + +MLNX_SAI = mlnx-sai_1.mlnx.$(MLNX_SAI_VERSION)_amd64.deb +$(MLNX_SAI)_SRC_PATH = $(PLATFORM_PATH)/mlnx-sai +$(MLNX_SAI)_DEPENDS += $(MLNX_SDK_DEBS) +$(MLNX_SAI)_RDEPENDS += $(MLNX_SDK_RDEBS) $(MLNX_SDK_DEBS) +$(eval $(call add_conflict_package,$(MLNX_SAI),$(LIBSAIVS_DEV))) +MLNX_SAI_DBGSYM = mlnx-sai-dbgsym_1.mlnx.$(MLNX_SAI_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(MLNX_SAI),$(MLNX_SAI_DBGSYM))) +SONIC_MAKE_DEBS += $(MLNX_SAI) diff --git a/platform/mellanox/mlnx-sai/Makefile b/platform/mellanox/mlnx-sai/Makefile new file mode 100644 index 000000000000..715f43ef0355 --- /dev/null +++ b/platform/mellanox/mlnx-sai/Makefile @@ -0,0 +1,17 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = mlnx-sai_1.mlnx.$(MLNX_SAI_VERSION)_amd64.deb +DERIVED_TARGETS = mlnx-sai-dbgsym_1.mlnx.$(MLNX_SAI_VERSION)_amd64.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + pushd SAI-Implementation + pushd mlnx_sai + + chmod a+x autogen.sh + debuild -e 'make_extra_flags="DEFS=-DACS_OS -DCONFIG_SYSLOG"' -us -uc -d -b + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + popd diff --git a/platform/mellanox/mlnx-sai/SAI-Implementation b/platform/mellanox/mlnx-sai/SAI-Implementation new file mode 160000 index 000000000000..aa467f9462d0 --- /dev/null +++ b/platform/mellanox/mlnx-sai/SAI-Implementation @@ -0,0 +1 @@ +Subproject commit aa467f9462d063c79875b3a6ea699e9d0b1d8b57 diff --git a/platform/mellanox/mlnx-ssd-fw-update.dep b/platform/mellanox/mlnx-ssd-fw-update.dep new file mode 100644 index 000000000000..60e587a64f07 --- /dev/null +++ b/platform/mellanox/mlnx-ssd-fw-update.dep @@ -0,0 +1,10 @@ +# DPKG FRK + +DPATH := $($(MLNX_SSD_FW_UPDATE)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/mlnx-ssd-fw-update.mk $(PLATFORM_PATH)/mlnx-ssd-fw-update.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(addprefix $(DPATH),$(MLNX_SSD_FW_UPDATE)) + +$(MLNX_SSD_FW_UPDATE)_CACHE_MODE := GIT_CONTENT_SHA +$(MLNX_SSD_FW_UPDATE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MLNX_SSD_FW_UPDATE)_DEP_FILES := $(DEP_FILES) diff --git a/platform/mellanox/mlnx-ssd-fw-update.mk b/platform/mellanox/mlnx-ssd-fw-update.mk new file mode 100644 index 000000000000..024710efbf9b --- /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_PATH)/ +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..4a2204adacf8 --- /dev/null +++ b/platform/mellanox/mlnx-ssd-fw-update.sh @@ -0,0 +1,729 @@ +#!/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.5" +#===== +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 + export LC_ALL= + export LANG="en_US.UTF-8" +} + +#==============================================================================# +#= 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 --ignore-time-conflict --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 [[ "yes" == "$power_policy" || $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 is not required, latest version based on given package is in use." + print_ssd_info "no" + fi + + echo -e "" + erase_extract_package "$extraction_path" + exit 0 +fi + +exit 0 diff --git a/platform/mellanox/one-image.dep b/platform/mellanox/one-image.dep new file mode 100644 index 000000000000..c29b43a7bba9 --- /dev/null +++ b/platform/mellanox/one-image.dep @@ -0,0 +1,3 @@ +# DPKG FRK + +$(SONIC_ONE_IMAGE)_CACHE_MODE := none diff --git a/platform/mellanox/one-image.mk b/platform/mellanox/one-image.mk new file mode 100644 index 000000000000..0f69b7335bf1 --- /dev/null +++ b/platform/mellanox/one-image.mk @@ -0,0 +1,15 @@ +# sonic mellanox one image installer + +SONIC_ONE_IMAGE = sonic-mellanox.bin +$(SONIC_ONE_IMAGE)_MACHINE = mellanox +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(SX_KERNEL) $(KERNEL_MFT) $(MFT_OEM) $(MFT) $(MLNX_HW_MANAGEMENT) +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +$(SONIC_ONE_IMAGE)_FILES += $(MLNX_FILES) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/mellanox/peripheral_table.j2 b/platform/mellanox/peripheral_table.j2 new file mode 100644 index 000000000000..730fd681bc61 --- /dev/null +++ b/platform/mellanox/peripheral_table.j2 @@ -0,0 +1,17 @@ +{%- if DEVICE_METADATA is defined and DEVICE_METADATA['localhost']['platform'] is defined %} +{%- set platform = DEVICE_METADATA['localhost']['platform'] %} +{%- endif -%} + +{% set platform2gearbox = { + 'x86_64-mlnx_msn3800-r0':'MELLANOX-GEARBOX-3800' + } +%} +{% set gearbox_type = platform2gearbox[platform] %} +{% if gearbox_type == 'MELLANOX-GEARBOX-3800' %} +{ + "PERIPHERAL_TABLE:MELLANOX-GEARBOX-3800": { + "gearbox_delay": "400" + }, + "OP": "SET" +} +{% endif %} diff --git a/platform/mellanox/platform.conf b/platform/mellanox/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/mellanox/rules.dep b/platform/mellanox/rules.dep new file mode 100644 index 000000000000..409857592159 --- /dev/null +++ b/platform/mellanox/rules.dep @@ -0,0 +1,17 @@ +# DPKG FRK + +include $(PLATFORM_PATH)/sdk.dep +include $(PLATFORM_PATH)/fw.dep +include $(PLATFORM_PATH)/mft.dep +include $(PLATFORM_PATH)/mlnx-sai.dep +include $(PLATFORM_PATH)/hw-management.dep +include $(PLATFORM_PATH)/mlnx-platform-api.dep +include $(PLATFORM_PATH)/docker-syncd-mlnx.dep +include $(PLATFORM_PATH)/docker-syncd-mlnx-rpc.dep +include $(PLATFORM_PATH)/docker-saiserver-mlnx.dep +include $(PLATFORM_PATH)/one-image.dep +include $(PLATFORM_PATH)/libsaithrift-dev.dep +include $(PLATFORM_PATH)/mlnx-ffb.dep +include $(PLATFORM_PATH)/issu-version.dep +include $(PLATFORM_PATH)/mlnx-onie-fw-update.dep +include $(PLATFORM_PATH)/mlnx-ssd-fw-update.dep diff --git a/platform/mellanox/rules.mk b/platform/mellanox/rules.mk new file mode 100644 index 000000000000..179e20f3fff5 --- /dev/null +++ b/platform/mellanox/rules.mk @@ -0,0 +1,34 @@ +include $(PLATFORM_PATH)/sdk.mk +include $(PLATFORM_PATH)/fw.mk +include $(PLATFORM_PATH)/mft.mk +include $(PLATFORM_PATH)/mlnx-sai.mk +include $(PLATFORM_PATH)/hw-management.mk +include $(PLATFORM_PATH)/mlnx-platform-api.mk +include $(PLATFORM_PATH)/docker-syncd-mlnx.mk +include $(PLATFORM_PATH)/docker-syncd-mlnx-rpc.mk +include $(PLATFORM_PATH)/docker-saiserver-mlnx.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.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) + +# Inject mlnx sai into syncd +$(SYNCD)_DEPENDS += $(MLNX_SAI) +$(SYNCD)_UNINSTALLS += $(MLNX_SAI) + +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV) +endif + +# Runtime dependency on mlnx sai is set only for syncd +$(SYNCD)_RDEPENDS += $(MLNX_SAI) + +# Inject mlnx sdk libs to platform monitor +$(DOCKER_PLATFORM_MONITOR)_DEPENDS += $(APPLIBS) $(SX_COMPLIB) $(SXD_LIBS) $(SX_GEN_UTILS) $(PYTHON_SDK_API) $(APPLIBS_DEV) $(SX_COMPLIB_DEV) $(SXD_LIBS_DEV) $(SX_GEN_UTILS_DEV) + +export SONIC_BUFFER_MODEL=dynamic diff --git a/platform/mellanox/sdk-src/applibs/Makefile b/platform/mellanox/sdk-src/applibs/Makefile new file mode 100644 index 000000000000..1068da0c5c16 --- /dev/null +++ b/platform/mellanox/sdk-src/applibs/Makefile @@ -0,0 +1,30 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = applibs_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = applibs-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb applibs-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = applibs + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + + # build + pushd $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + sed -i "s/sx-libnl/$(LIBNL3)/g" ./debian/control + sed -i "s/-Werror//g" ./configure.in + + if [ -f autogen.sh ]; then + ./autogen.sh + fi + + debuild -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk-src/iproute2/Makefile b/platform/mellanox/sdk-src/iproute2/Makefile new file mode 100644 index 000000000000..0e32fe1426c4 --- /dev/null +++ b/platform/mellanox/sdk-src/iproute2/Makefile @@ -0,0 +1,27 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = iproute2_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = iproute2-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb iproute2-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = iproute2-3.19.0 + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + + # build + pushd $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + if [ -f autogen.sh ]; then + ./autogen.sh + fi + + debuild -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk-src/python-sdk-api/Makefile b/platform/mellanox/sdk-src/python-sdk-api/Makefile new file mode 100644 index 000000000000..9c41be75725b --- /dev/null +++ b/platform/mellanox/sdk-src/python-sdk-api/Makefile @@ -0,0 +1,27 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = python-sdk-api_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = python-sdk-api-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = python_sdk_api + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + + # build + pushd $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + if [ -f autogen.sh ]; then + ./autogen.sh + fi + + debuild -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk-src/sx-acl-helper/Makefile b/platform/mellanox/sdk-src/sx-acl-helper/Makefile new file mode 100644 index 000000000000..d9d0aef8775b --- /dev/null +++ b/platform/mellanox/sdk-src/sx-acl-helper/Makefile @@ -0,0 +1,29 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = sx-acl-helper_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = sx-acl-helper-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb \ + sx-acl-helper-dev-static_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb \ + sx-acl-helper-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = sx_acl_helper + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + + # build + pushd $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + if [ -f autogen.sh ]; then + ./autogen.sh + fi + + debuild -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk-src/sx-complib/Makefile b/platform/mellanox/sdk-src/sx-complib/Makefile new file mode 100644 index 000000000000..6e51b779ef23 --- /dev/null +++ b/platform/mellanox/sdk-src/sx-complib/Makefile @@ -0,0 +1,29 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = sx-complib_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = sx-complib-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb \ + sx-complib-dev-static_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb \ + sx-complib-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = sx_complib + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + + # build + pushd $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + if [ -f autogen.sh ]; then + ./autogen.sh + fi + + debuild -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk-src/sx-examples/Makefile b/platform/mellanox/sdk-src/sx-examples/Makefile new file mode 100644 index 000000000000..06de0f475062 --- /dev/null +++ b/platform/mellanox/sdk-src/sx-examples/Makefile @@ -0,0 +1,27 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = sx-examples_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = sx-examples-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb sx-examples-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = sx_examples + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + + # build + pushd $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + if [ -f autogen.sh ]; then + ./autogen.sh + fi + + debuild -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk-src/sx-gen-utils/Makefile b/platform/mellanox/sdk-src/sx-gen-utils/Makefile new file mode 100644 index 000000000000..1f6f31d9acd4 --- /dev/null +++ b/platform/mellanox/sdk-src/sx-gen-utils/Makefile @@ -0,0 +1,27 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = sx-gen-utils_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = sx-gen-utils-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb sx-gen-utils-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = sx_gen_utils + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + + # build + pushd $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + if [ -f autogen.sh ]; then + ./autogen.sh + fi + + debuild -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk-src/sx-kernel/Makefile b/platform/mellanox/sdk-src/sx-kernel/Makefile new file mode 100644 index 000000000000..422f2ae95aae --- /dev/null +++ b/platform/mellanox/sdk-src/sx-kernel/Makefile @@ -0,0 +1,29 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = sx-kernel_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = sx-kernel-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = sx_kernel + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + + if [ ! -z "$(MLNX_SDK_SOURCE_BASE_URL)" ]; then + rm -rf sx_kernel-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + pushd sx_kernel-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + else + pushd Switch-SDK-drivers + git reset --hard + git clean -xfd + fi + + # build + + debuild -e KVERSION=$(KVERSION) -e KSRC_EXT=/lib/modules/$(KVERSION)/source/ -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers b/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers new file mode 160000 index 000000000000..78d452b90836 --- /dev/null +++ b/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers @@ -0,0 +1 @@ +Subproject commit 78d452b90836005784cd6345bacf0a5df109f742 diff --git a/platform/mellanox/sdk-src/sx-scew/Makefile b/platform/mellanox/sdk-src/sx-scew/Makefile new file mode 100644 index 000000000000..9b8c5bd56c39 --- /dev/null +++ b/platform/mellanox/sdk-src/sx-scew/Makefile @@ -0,0 +1,29 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = sx-scew_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = sx-scew-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb \ + sx-scew-dev-static_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb \ + sx-scew-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = sx_scew + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + + # build + pushd $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + if [ -f autogen.sh ]; then + ./autogen.sh + fi + + debuild -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk-src/sxd-libs/Makefile b/platform/mellanox/sdk-src/sxd-libs/Makefile new file mode 100644 index 000000000000..0b142c920828 --- /dev/null +++ b/platform/mellanox/sdk-src/sxd-libs/Makefile @@ -0,0 +1,29 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = sxd-libs_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = sxd-libs-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb \ + sxd-libs-dev-static_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb \ + sxd-libs-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = sxd_libs + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + + # build + pushd $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + if [ -f autogen.sh ]; then + ./autogen.sh + fi + + debuild -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk-src/wjh-libs/Makefile b/platform/mellanox/sdk-src/wjh-libs/Makefile new file mode 100644 index 000000000000..ecc437258ec2 --- /dev/null +++ b/platform/mellanox/sdk-src/wjh-libs/Makefile @@ -0,0 +1,29 @@ +.ONESHELL: +SHELL = /bin/bash + +MAIN_TARGET = wjh-libs_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +DERIVED_TARGETS = wjh-libs-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb \ + wjh-libs-dev-static_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb \ + wjh-libs-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +PACKAGE_NAME = wjh_libs + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # get sources + rm -rf $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + wget -c $(MLNX_SDK_SOURCE_BASE_URL)/$(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION).tar.gz -O - | tar -xz + + # build + pushd $(PACKAGE_NAME)-$(MLNX_SDK_VERSION)-$(MLNX_SDK_ISSU_VERSION) + + if [ -f autogen.sh ]; then + ./autogen.sh + fi + + debuild -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/platform/mellanox/sdk.dep b/platform/mellanox/sdk.dep new file mode 100644 index 000000000000..bf3ecb95d8ae --- /dev/null +++ b/platform/mellanox/sdk.dep @@ -0,0 +1,229 @@ +# DPKG FRK + +# APPLIBS + +SPATH := $($(APPLIBS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(APPLIBS)_CACHE_MODE := GIT_CONTENT_SHA +$(APPLIBS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(APPLIBS)_DEP_FILES := $(DEP_FILES) + +$(APPLIBS_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(APPLIBS_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(APPLIBS_DEV)_DEP_FILES := $(DEP_FILES) + +ifeq ($(SDK_FROM_SRC),y) +$(APPLIBS_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(APPLIBS_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(APPLIBS_DBGSYM)_DEP_FILES := $(DEP_FILES) +endif + +# IPROUTE2_MLNX + +SPATH := $($(IPROUTE2_MLNX)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(IPROUTE2_MLNX)_CACHE_MODE := GIT_CONTENT_SHA +$(IPROUTE2_MLNX)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(IPROUTE2_MLNX)_DEP_FILES := $(DEP_FILES) + +$(IPROUTE2_MLNX_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(IPROUTE2_MLNX_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(IPROUTE2_MLNX_DEV)_DEP_FILES := $(DEP_FILES) + +ifeq ($(SDK_FROM_SRC),y) +$(IPROUTE2_MLNX_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(IPROUTE2_MLNX_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(IPROUTE2_MLNX_DBGSYM)_DEP_FILES := $(DEP_FILES) +endif + +# SX_COMPLIB + +SPATH := $($(SX_COMPLIB)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(SX_COMPLIB)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_COMPLIB)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_COMPLIB)_DEP_FILES := $(DEP_FILES) + +$(SX_COMPLIB_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_COMPLIB_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_COMPLIB_DEV)_DEP_FILES := $(DEP_FILES) + +ifeq ($(SDK_FROM_SRC),y) +$(SX_COMPLIB_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_COMPLIB_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_COMPLIB_DBGSYM)_DEP_FILES := $(DEP_FILES) +endif + +# SX_EXAMPLES + +SPATH := $($(SX_EXAMPLES)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(SX_EXAMPLES)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_EXAMPLES)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_EXAMPLES)_DEP_FILES := $(DEP_FILES) + +$(SX_EXAMPLES_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_EXAMPLES_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_EXAMPLES_DEV)_DEP_FILES := $(DEP_FILES) + +ifeq ($(SDK_FROM_SRC),y) +$(SX_EXAMPLES_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_EXAMPLES_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_EXAMPLES_DBGSYM)_DEP_FILES := $(DEP_FILES) +endif + +# SX_GEN_UTILS + +SPATH := $($(SX_GEN_UTILS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(SX_GEN_UTILS)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_GEN_UTILS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_GEN_UTILS)_DEP_FILES := $(DEP_FILES) + +$(SX_GEN_UTILS_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_GEN_UTILS_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_GEN_UTILS_DEV)_DEP_FILES := $(DEP_FILES) + +ifeq ($(SDK_FROM_SRC),y) +$(SX_GEN_UTILS_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_GEN_UTILS_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_GEN_UTILS_DBGSYM)_DEP_FILES := $(DEP_FILES) +endif + +# SX_SCEW + +SPATH := $($(SX_SCEW)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(SX_SCEW)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_SCEW)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_SCEW)_DEP_FILES := $(DEP_FILES) + +$(SX_SCEW_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_SCEW_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_SCEW_DEV)_DEP_FILES := $(DEP_FILES) + +ifeq ($(SDK_FROM_SRC),y) +$(SX_SCEW_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_SCEW_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_SCEW_DBGSYM)_DEP_FILES := $(DEP_FILES) +endif + +# SXD_LIBS + +SPATH := $($(SXD_LIBS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(SXD_LIBS)_CACHE_MODE := GIT_CONTENT_SHA +$(SXD_LIBS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SXD_LIBS)_DEP_FILES := $(DEP_FILES) + +$(SXD_LIBS_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(SXD_LIBS_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SXD_LIBS_DEV)_DEP_FILES := $(DEP_FILES) + +ifeq ($(SDK_FROM_SRC),y) +$(SXD_LIBS_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(SXD_LIBS_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SXD_LIBS_DBGSYM)_DEP_FILES := $(DEP_FILES) +endif + +# PYTHON_SDK_API + +SPATH := $($(PYTHON_SDK_API)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(PYTHON_SDK_API)_CACHE_MODE := GIT_CONTENT_SHA +$(PYTHON_SDK_API)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(PYTHON_SDK_API)_DEP_FILES := $(DEP_FILES) + +ifeq ($(SDK_FROM_SRC),y) +$(PYTHON_SDK_API_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(PYTHON_SDK_API_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(PYTHON_SDK_API_DBGSYM)_DEP_FILES := $(DEP_FILES) +endif + +# SX_ACL_HELPER + +SPATH := $($(SX_ACL_HELPER)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(SX_ACL_HELPER)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_ACL_HELPER)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_ACL_HELPER)_DEP_FILES := $(DEP_FILES) + +$(SX_ACL_HELPER_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_ACL_HELPER_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_ACL_HELPER_DEV)_DEP_FILES := $(DEP_FILES) + +ifeq ($(SDK_FROM_SRC),y) +$(SX_ACL_HELPER_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_ACL_HELPER_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_ACL_HELPER_DBGSYM)_DEP_FILES := $(DEP_FILES) +endif + +# WJH_LIBS + +SPATH := $($(WJH_LIBS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files -- $(SPATH)) + +$(WJH_LIBS)_CACHE_MODE := GIT_CONTENT_SHA +$(WJH_LIBS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(WJH_LIBS)_DEP_FILES := $(DEP_FILES) + +$(WJH_LIBS_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(WJH_LIBS_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(WJH_LIBS_DEV)_DEP_FILES := $(DEP_FILES) + +ifeq ($(SDK_FROM_SRC),y) +$(WJH_LIBS_DBGSYM)_CACHE_MODE := GIT_CONTENT_SHA +$(WJH_LIBS_DBGSYM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(WJH_LIBS_DBGSYM)_DEP_FILES := $(DEP_FILES) +endif + +# SX_KERNEL + +SPATH := $($(SX_KERNEL)_SRC_PATH) +SLINKS := $(shell find $(SPATH) -type l -exec echo {} \; | grep -Ev ' ') +SMDEP_PATHS := $(shell git submodule status --recursive -- $(SPATH) | awk '{print $$2}' | grep -Ev ' ') +SMDEP_FILES := $(foreach path,$(SMDEP_PATHS),$(filter-out $(SMDEP_PATHS),$(addprefix $(path)/,$(shell cd $(path) && git ls-files | grep -Ev ' ')))) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/sdk.mk $(PLATFORM_PATH)/sdk.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(filter-out $(SMDEP_PATHS),$(shell git ls-files -- $(SPATH) | grep -Ev ' ')) + +$(SX_KERNEL)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_KERNEL)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_KERNEL)_DEP_FILES := $(filter-out $(SLINKS),$(DEP_FILES)) +$(SX_KERNEL)_SMDEP_FILES := $(filter-out $(SLINKS),$(SMDEP_FILES)) +$(SX_KERNEL)_SMDEP_PATHS := $(SMDEP_PATHS) + +$(SX_KERNEL_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(SX_KERNEL_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SX_KERNEL_DEV)_DEP_FILES := $(filter-out $(SLINKS),$(DEP_FILES)) +$(SX_KERNEL_DEV)_SMDEP_FILES := $(filter-out $(SLINKS),$(SMDEP_FILES)) +$(SX_KERNEL_DEV)_SMDEP_PATHS := $(SMDEP_PATHS) diff --git a/platform/mellanox/sdk.mk b/platform/mellanox/sdk.mk new file mode 100644 index 000000000000..d35eb67a1f11 --- /dev/null +++ b/platform/mellanox/sdk.mk @@ -0,0 +1,158 @@ +MLNX_SDK_BASE_PATH = $(PLATFORM_PATH)/sdk-src/sx-kernel/Switch-SDK-drivers/bin/ +MLNX_SDK_PKG_BASE_PATH = $(MLNX_SDK_BASE_PATH)/$(BLDENV)/ +MLNX_SDK_VERSION = 4.4.2318 +MLNX_SDK_ISSU_VERSION = 101 + +MLNX_SDK_DEB_VERSION = $(subst -,.,$(subst _,.,$(MLNX_SDK_VERSION))) + +# Place here URL where SDK sources exist +MLNX_SDK_SOURCE_BASE_URL = + +ifneq ($(MLNX_SDK_SOURCE_BASE_URL), ) +SDK_FROM_SRC = y +else +SDK_FROM_SRC = n +endif + +export MLNX_SDK_SOURCE_BASE_URL MLNX_SDK_VERSION MLNX_SDK_ISSU_VERSION MLNX_SDK_DEB_VERSION + +MLNX_SDK_RDEBS += $(APPLIBS) $(IPROUTE2_MLNX) $(SX_COMPLIB) $(SX_EXAMPLES) \ + $(SX_GEN_UTILS) $(SX_SCEW) $(SXD_LIBS) $(WJH_LIBS) $(SX_ACL_HELPER) + +MLNX_SDK_DEBS += $(APPLIBS_DEV) $(IPROUTE2_MLNX_DEV) $(SX_COMPLIB_DEV) \ + $(SX_COMPLIB_DEV_STATIC) $(SX_EXAMPLES_DEV) $(SX_GEN_UTILS_DEV) \ + $(SX_SCEW_DEV) $(SX_SCEW_DEV_STATIC) $(SXD_LIBS_DEV)\ + $(SXD_LIBS_DEV_STATIC) $(WJH_LIBS_DEV) $(SX_ACL_HELPER_DEV) + +MLNX_SDK_DBG_DEBS += $(APPLIBS_DBGSYM) $(IPROUTE2_MLNX_DBGSYM) $(SX_COMPLIB_DBGSYM) \ + $(SX_EXAMPLES_DBGSYM) $(SX_GEN_UTILS_DBGSYM) $(SX_SCEW_DBGSYM) \ + $(SXD_LIBS_DBGSYM) $(WJH_LIBS_DBGSYM) $(SX_ACL_HELPER_DBGSYM) + +APPLIBS = applibs_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(APPLIBS)_SRC_PATH = $(PLATFORM_PATH)/sdk-src/applibs +$(APPLIBS)_DEPENDS += $(SX_COMPLIB_DEV) $(SX_GEN_UTILS_DEV) $(SXD_LIBS_DEV) $(LIBNL3_DEV) $(LIBNL_GENL3_DEV) +$(APPLIBS)_RDEPENDS += $(SX_COMPLIB) $(SX_GEN_UTILS) $(SXD_LIBS) $(LIBNL3) $(LIBNL_GENL3) +APPLIBS_DEV = applibs-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(APPLIBS),$(APPLIBS_DEV))) +APPLIBS_DBGSYM = applibs-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +ifeq ($(SDK_FROM_SRC),y) +$(eval $(call add_derived_package,$(APPLIBS),$(APPLIBS_DBGSYM))) +endif + +IPROUTE2_MLNX = iproute2_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(IPROUTE2_MLNX)_SRC_PATH = $(PLATFORM_PATH)/sdk-src/iproute2 +IPROUTE2_MLNX_DEV = iproute2-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(IPROUTE2_MLNX),$(IPROUTE2_MLNX_DEV))) +IPROUTE2_MLNX_DBGSYM = iproute2-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +ifeq ($(SDK_FROM_SRC),y) +$(eval $(call add_derived_package,$(IPROUTE2_MLNX),$(IPROUTE2_MLNX_DBGSYM))) +endif + +SX_COMPLIB = sx-complib_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(SX_COMPLIB)_SRC_PATH = $(PLATFORM_PATH)/sdk-src/sx-complib +SX_COMPLIB_DEV = sx-complib-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_COMPLIB),$(SX_COMPLIB_DEV))) +SX_COMPLIB_DBGSYM = sx-complib-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +ifeq ($(SDK_FROM_SRC),y) +$(eval $(call add_derived_package,$(SX_COMPLIB),$(SX_COMPLIB_DBGSYM))) +endif + +SX_EXAMPLES = sx-examples_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(SX_EXAMPLES)_SRC_PATH = $(PLATFORM_PATH)/sdk-src/sx-examples +$(SX_EXAMPLES)_DEPENDS += $(APPLIBS_DEV) $(SX_SCEW_DEV) $(SXD_LIBS_DEV) +$(SX_EXAMPLES)_RDEPENDS += $(APPLIBS) $(SX_SCEW) $(SXD_LIBS) +SX_EXAMPLES_DEV = sx-examples-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_EXAMPLES),$(SX_EXAMPLES_DEV))) +SX_EXAMPLES_DBGSYM = sx-examples-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +ifeq ($(SDK_FROM_SRC),y) +$(eval $(call add_derived_package,$(SX_EXAMPLES),$(SX_EXAMPLES_DBGSYM))) +endif + +SX_GEN_UTILS = sx-gen-utils_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(SX_GEN_UTILS)_SRC_PATH += $(PLATFORM_PATH)/sdk-src/sx-gen-utils +$(SX_GEN_UTILS)_DEPENDS += $(SX_COMPLIB_DEV) +$(SX_GEN_UTILS)_RDEPENDS += $(SX_COMPLIB) +SX_GEN_UTILS_DEV = sx-gen-utils-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_GEN_UTILS),$(SX_GEN_UTILS_DEV))) +SX_GEN_UTILS_DBGSYM = sx-gen-utils-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +ifeq ($(SDK_FROM_SRC),y) +$(eval $(call add_derived_package,$(SX_GEN_UTILS),$(SX_GEN_UTILS_DBGSYM))) +endif + +SX_SCEW = sx-scew_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(SX_SCEW)_SRC_PATH = $(PLATFORM_PATH)/sdk-src/sx-scew +SX_SCEW_DEV = sx-scew-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_SCEW),$(SX_SCEW_DEV))) +SX_SCEW_DBGSYM = sx-scew-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +ifeq ($(SDK_FROM_SRC),y) +$(eval $(call add_derived_package,$(SX_SCEW),$(SX_SCEW_DBGSYM))) +endif + +SXD_LIBS = sxd-libs_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(SXD_LIBS)_SRC_PATH = $(PLATFORM_PATH)/sdk-src/sxd-libs +$(SXD_LIBS)_DEPENDS += $(SX_COMPLIB_DEV) $(SX_GEN_UTILS_DEV) +SXD_LIBS_DEV = sxd-libs-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SXD_LIBS),$(SXD_LIBS_DEV))) +SXD_LIBS_DBGSYM = sxd-libs-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +ifeq ($(SDK_FROM_SRC),y) +$(eval $(call add_derived_package,$(SXD_LIBS),$(SXD_LIBS_DBGSYM))) +endif + +#packages that are required for runtime only +PYTHON_SDK_API = python-sdk-api_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(PYTHON_SDK_API)_SRC_PATH = $(PLATFORM_PATH)/sdk-src/python-sdk-api +$(PYTHON_SDK_API)_DEPENDS += $(APPLIBS_DEV) $(SXD_LIBS_DEV) $(SWIG) +$(PYTHON_SDK_API)_RDEPENDS += $(APPLIBS) $(SXD_LIBS) +PYTHON_SDK_API_DBGSYM = python-sdk-api-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +ifeq ($(SDK_FROM_SRC),y) +$(eval $(call add_derived_package,$(PYTHON_SDK_API),$(PYTHON_SDK_API_DBGSYM))) +endif + +SX_ACL_HELPER = sx-acl-helper_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(SX_ACL_HELPER)_SRC_PATH = $(PLATFORM_PATH)/sdk-src/sx-acl-helper +$(SX_ACL_HELPER)_DEPENDS += $(SX_COMPLIB_DEV) $(SXD_LIBS_DEV) $(APPLIBS_DEV) +$(SX_ACL_HELPER)_RDEPENDS += $(SX_COMPLIB) $(PYTHON_SDK_API) +SX_ACL_HELPER_DEV = sx-acl-helper-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_ACL_HELPER),$(SX_ACL_HELPER_DEV))) +SX_ACL_HELPER_DBGSYM = sx-acl-helper-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +ifeq ($(SDK_FROM_SRC),y) +$(eval $(call add_derived_package,$(SX_ACL_HELPER),$(SX_ACL_HELPER_DBGSYM))) +endif + +WJH_LIBS = wjh-libs_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(WJH_LIBS)_SRC_PATH = $(PLATFORM_PATH)/sdk-src/wjh-libs +$(WJH_LIBS)_DEPENDS += $(SX_COMPLIB_DEV) $(SXD_LIBS_DEV) $(APPLIBS_DEV) $(SX_ACL_HELPER_DEV) $(SX_SCEW_DEV) +$(WJH_LIBS)_RDEPENDS += $(SX_COMPLIB) $(PYTHON_SDK_API) $(SX_ACL_HELPER) +WJH_LIBS_DEV = wjh-libs-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(WJH_LIBS),$(WJH_LIBS_DEV))) +WJH_LIBS_DBGSYM = wjh-libs-dbgsym_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +ifeq ($(SDK_FROM_SRC),y) +$(eval $(call add_derived_package,$(WJH_LIBS),$(WJH_LIBS_DBGSYM))) +endif + +SX_KERNEL = sx-kernel_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(SX_KERNEL)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(SX_KERNEL)_SRC_PATH = $(PLATFORM_PATH)/sdk-src/sx-kernel +SX_KERNEL_DEV = sx-kernel-dev_1.mlnx.$(MLNX_SDK_DEB_VERSION)_amd64.deb +$(eval $(call add_derived_package,$(SX_KERNEL),$(SX_KERNEL_DEV))) + +define make_path + $(1)_PATH = $(MLNX_SDK_PKG_BASE_PATH) + +endef + +$(eval $(foreach deb,$(MLNX_SDK_DEBS),$(call make_path,$(deb)))) +$(eval $(foreach deb,$(MLNX_SDK_RDEBS),$(call make_path,$(deb)))) +$(eval $(foreach deb,$(PYTHON_SDK_API) $(SX_KERNEL) $(SX_KERNEL_DEV),$(call make_path,$(deb)))) + +SONIC_MAKE_DEBS += $(SX_KERNEL) + +ifeq ($(SDK_FROM_SRC), y) +SONIC_MAKE_DEBS += $(MLNX_SDK_RDEBS) $(PYTHON_SDK_API) +else +SONIC_COPY_DEBS += $(MLNX_SDK_RDEBS) $(PYTHON_SDK_API) +endif + +mlnx-sdk-packages: $(addprefix $(DEBS_PATH)/, $(MLNX_SDK_RDEBS) $(PYTHON_SDK_API) $(SX_KERNEL)) + +SONIC_PHONY_TARGETS += mlnx-sdk-packages diff --git a/platform/nephos/docker-syncd-nephos-rpc.mk b/platform/nephos/docker-syncd-nephos-rpc.mk new file mode 100644 index 000000000000..39240c1913e4 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos-rpc.mk @@ -0,0 +1,25 @@ +# docker image for nephos syncd with rpc + +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) $(PTF) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_NEPHOS_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_NEPHOS_RPC)_FILES += $(DSSERVE) $(NPX_DIAG) +$(DOCKER_SYNCD_NEPHOS_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_NEPHOS_RPC) +SONIC_STRETCH_DOCKERS += $(DOCKER_SYNCD_NEPHOS_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_NEPHOS_RPC) +endif + +$(DOCKER_SYNCD_NEPHOS_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_NEPHOS_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_NEPHOS_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_NEPHOS_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot +$(DOCKER_SYNCD_NEPHOS_RPC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_NEPHOS_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/nephos/docker-syncd-nephos-rpc/Dockerfile.j2 b/platform/nephos/docker-syncd-nephos-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..6c63efb69bb6 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos-rpc/Dockerfile.j2 @@ -0,0 +1,55 @@ +FROM docker-syncd-nephos + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_nephos_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get purge -y syncd + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + libqt5core5a \ + libqt5network5 \ + libboost-atomic1.71.0 + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_nephos_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +RUN wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/nephos/docker-syncd-nephos-rpc/ptf_nn_agent.conf b/platform/nephos/docker-syncd-nephos-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/nephos/docker-syncd-nephos.mk b/platform/nephos/docker-syncd-nephos.mk new file mode 100644 index 000000000000..146523ec1c64 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos.mk @@ -0,0 +1,21 @@ +# docker image for nephos syncd + +DOCKER_SYNCD_PLATFORM_CODE = nephos +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) +$(DOCKER_SYNCD_BASE)_FILES += $(DSSERVE) $(NPX_DIAG) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) + +SONIC_STRETCH_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_STRETCH_DBG_DOCKERS += $(DOCKER_SYNCD_BASE_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 += 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/Dockerfile.j2 b/platform/nephos/docker-syncd-nephos/Dockerfile.j2 new file mode 100755 index 000000000000..e142fa04d57d --- /dev/null +++ b/platform/nephos/docker-syncd-nephos/Dockerfile.j2 @@ -0,0 +1,46 @@ +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 + +COPY \ +{% for deb in docker_syncd_nephos_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +COPY \ +{% for deb in docker_syncd_nephos_pydebs.split(' ') -%} +python-debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get install -y libxml2 + +RUN dpkg -i \ +{% for deb in docker_syncd_nephos_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +##RUN dpkg -i \ +##{% for deb in docker_syncd_nephos_pydebs.split(' ') -%} +##debs/{{ deb }}{{' '}} +##{%- endfor %} + +COPY ["files/dsserve", "files/npx_diag", "/usr/bin/"] +RUN chmod +x /usr/bin/npx_diag /usr/bin/dsserve + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] 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..d63346d9ee20 --- /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 program syncd|syncd with path "/usr/bin/process_checker syncd /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles + +check program syncd|dsserve with path "/usr/bin/process_checker syncd /usr/bin/dsserve /usr/bin/syncd" + if status != 0 for 5 times within 5 cycles then alert repeat every 1 cycles diff --git a/platform/nephos/docker-syncd-nephos/base_image_files/npx_diag b/platform/nephos/docker-syncd-nephos/base_image_files/npx_diag new file mode 100755 index 000000000000..876bc1816ecc --- /dev/null +++ b/platform/nephos/docker-syncd-nephos/base_image_files/npx_diag @@ -0,0 +1,3 @@ +#!/bin/bash + +docker exec -i syncd npx_diag "$@" diff --git a/platform/nephos/docker-syncd-nephos/critical_processes b/platform/nephos/docker-syncd-nephos/critical_processes new file mode 100644 index 000000000000..d1163a9c3046 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos/critical_processes @@ -0,0 +1,2 @@ +program:dsserve +program:syncd diff --git a/platform/nephos/docker-syncd-nephos/supervisord.conf b/platform/nephos/docker-syncd-nephos/supervisord.conf new file mode 100644 index 000000000000..955021ad2d51 --- /dev/null +++ b/platform/nephos/docker-syncd-nephos/supervisord.conf @@ -0,0 +1,38 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python2 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running diff --git a/platform/nephos/libsaithrift-dev.mk b/platform/nephos/libsaithrift-dev.mk new file mode 100644 index 000000000000..e21ebc5c6828 --- /dev/null +++ b/platform/nephos/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_amd64.deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(NEPHOS_SAI) $(NEPHOS_SAI_DEV) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(NEPHOS_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_amd64.deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_amd64.deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(NEPHOS_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_amd64.deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/nephos/nephos-modules.mk b/platform/nephos/nephos-modules.mk new file mode 100644 index 000000000000..5e055537a428 --- /dev/null +++ b/platform/nephos/nephos-modules.mk @@ -0,0 +1,9 @@ +# Nephos Platform modules + +NPS_PLATFORM_MODULE_VERSION = 1.0.1 + +NEPHOS_MODULE = nephos-modules_$(NPS_PLATFORM_MODULE_VERSION)_amd64.deb +$(NEPHOS_MODULE)_SRC_PATH = $(PLATFORM_PATH)/nephos-modules +$(NEPHOS_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_DPKG_DEBS += $(NEPHOS_MODULE) + diff --git a/platform/nephos/nephos-modules/README.md b/platform/nephos/nephos-modules/README.md new file mode 100644 index 000000000000..6bb4cf6bf658 --- /dev/null +++ b/platform/nephos/nephos-modules/README.md @@ -0,0 +1,2 @@ +# Nephos-modules +Device drivers for support of Nephos platform for the SONiC project diff --git a/platform/nephos/nephos-modules/debian/changelog b/platform/nephos/nephos-modules/debian/changelog new file mode 100644 index 000000000000..94c7aa7d3915 --- /dev/null +++ b/platform/nephos/nephos-modules/debian/changelog @@ -0,0 +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 diff --git a/platform/nephos/nephos-modules/debian/compat b/platform/nephos/nephos-modules/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/nephos/nephos-modules/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/nephos/nephos-modules/debian/control b/platform/nephos/nephos-modules/debian/control new file mode 100644 index 000000000000..1b485d808f3e --- /dev/null +++ b/platform/nephos/nephos-modules/debian/control @@ -0,0 +1,12 @@ +Source: nephos-modules +Section: main +Priority: extra +Maintainer: support +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: nephos-modules +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for nephos asic + diff --git a/platform/nephos/nephos-modules/debian/rules b/platform/nephos/nephos-modules/debian/rules new file mode 100755 index 000000000000..acf96c80e104 --- /dev/null +++ b/platform/nephos/nephos-modules/debian/rules @@ -0,0 +1,34 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_NAME := nephos-modules +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +SERVICE_DIR := service +INITD_DIR := init.d +MODULE_SRC := $(shell pwd)/modules +CURRENT_DIR := $(cd "$(dirname "$0")"; pwd) + +%: + dh $@ + +override_dh_auto_build: + make -C $(MODULE_SRC) + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) $(KERNEL_SRC)/extra + cp $(MODULE_SRC)/build/module/*.ko debian/$(PACKAGE_NAME)/$(KERNEL_SRC)/extra + dh_installdirs -p$(PACKAGE_NAME) /lib/systemd/system + cp $(MODULE_SRC)/service/*.service debian/$(PACKAGE_NAME)/lib/systemd/system/ + dh_installdirs -p$(PACKAGE_NAME) /etc/init.d + cp $(MODULE_SRC)/init.d/* debian/$(PACKAGE_NAME)/etc/init.d/ + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + test -d $(MODULE_SRC)/build || rm -rf $(MODULE_SRC)/build + diff --git a/platform/nephos/nephos-modules/modules/Makefile b/platform/nephos/nephos-modules/modules/Makefile new file mode 100755 index 000000000000..8351996b04ea --- /dev/null +++ b/platform/nephos/nephos-modules/modules/Makefile @@ -0,0 +1,50 @@ +################################################################################ +# Copyright (C) 2019 Nephos, 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. +################################################################################ +NPS_MODULES_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST)))) +SRC_PATH := $(NPS_MODULES_DIR)/src +INC_PATH := $(SRC_PATH)/inc +################################################################################ +include $(NPS_MODULES_DIR)/config.mk +################################################################################ +MODULE_OUTPUT_DIR := $(BUILD_OUTPUT_DIR)/module +################################################################################ +all: compile install +################################################################################ +EXTRA_CFLAGS += -I$(INC_PATH) +EXTRA_CFLAGS += -DNPS_EN_NETIF +EXTRA_CFLAGS += -DNPS_EN_TAURUS +EXTRA_CFLAGS += -DNPS_LINUX_USER_MODE +EXTRA_CFLAGS += -DNPS_EN_LITTLE_ENDIAN +ifeq ($(shell uname -m),x86_64) +EXTRA_CFLAGS += -DNPS_EN_HOST_64_BIT_LITTLE_ENDIAN +else +EXTRA_CFLAGS += -DNPS_EN_HOST_32_BIT_LITTLE_ENDIAN +endif +################################################################################ +include $(SRC_PATH)/make.mk +################################################################################ +compile:: + +install:: + $(TEST_PATH) $(MODULE_OUTPUT_DIR) || $(MKDIR) $(MODULE_OUTPUT_DIR) + $(MV) $(BUILD_OUTPUT_DIR)/$(DEV_MODULE_NAME).ko $(MODULE_OUTPUT_DIR)/$(DEV_MODULE_NAME).ko + $(MV) $(BUILD_OUTPUT_DIR)/$(NETIF_MODULE_NAME).ko $(MODULE_OUTPUT_DIR)/$(NETIF_MODULE_NAME).ko + +clean:: + $(RM) $(BUILD_OUTPUT_DIR) + +.PHONY: all compile install clean +.NOTPARALLEL: all compile install clean diff --git a/platform/nephos/nephos-modules/modules/README b/platform/nephos/nephos-modules/modules/README new file mode 100644 index 000000000000..b2e6fb147936 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/README @@ -0,0 +1,32 @@ +################################################################################ +# Copyright (C) 2019 Nephos, 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. +################################################################################ +Step 1~4 show how to build and execute NPS kernel modules. + +1. Modify nps-modules/config.mk to specify the output directory to BUILD_OUTPUT_DIR. + The default output path is nps-modules/build. + +2. Compile: + cd nps-modules/ && make + +3. The output kernel modules will be found in $(BUILD_OUTPUT_DIR)/modules/ + - nps_dev.ko + - nps_netif.ko + +4. Load modules: + (1) insmod nps_dev.ko + (2) insmod nps_netif.ko + + Note that the module inserting sequence cannot be changed. diff --git a/platform/nephos/nephos-modules/modules/config.mk b/platform/nephos/nephos-modules/modules/config.mk new file mode 100755 index 000000000000..b7a106ea0a4b --- /dev/null +++ b/platform/nephos/nephos-modules/modules/config.mk @@ -0,0 +1,30 @@ +################################################################################ +# Copyright (C) 2019 Nephos, 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. +################################################################################ +BUILD_OUTPUT_DIR := $(NPS_MODULES_DIR)/build +################################################################################ +#OS_PATH := /lib/modules/$(shell uname -r)/build +OS_PATH := /lib/modules/$(KVERSION)/build + +################################################################################ +MAKE := make +RM := rm -rf +MKDIR := mkdir -p +CP := cp +MV := mv +TEST_PATH := test -d +################################################################################ +export BUILD_OUTPUT_DIR +export OS_PATH diff --git a/platform/nephos/nephos-modules/modules/init.d/nps-modules b/platform/nephos/nephos-modules/modules/init.d/nps-modules new file mode 100755 index 000000000000..d6f841ee02e7 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/init.d/nps-modules @@ -0,0 +1,54 @@ +#!/bin/bash +# This script load/unload nps kernel modules + +### BEGIN INIT INFO +# Provides: load-nps-modules +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load nps kernel modules +### END INIT INFO + +case "$1" in +start) + echo -n "Load nps kernel modules... " + + RMEM_SIZE=`cat /proc/sys/net/core/rmem_max` + if [ $RMEM_SIZE -lt 8388608 ]; then + echo "8388608" > /proc/sys/net/core/rmem_max + fi + WMEM_SIZE=`cat /proc/sys/net/core/wmem_max` + if [ $WMEM_SIZE -lt 25165824 ]; then + echo "25165824" > /proc/sys/net/core/wmem_max + fi + + modprobe nps_dev + modprobe nps_netif + + echo "done." + ;; + +stop) + echo -n "Unload nps kernel modules... " + + rmmod nps_netif + rmmod nps_dev + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/nps-modules {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/nephos/nephos-modules/modules/service/nps-modules.service b/platform/nephos/nephos-modules/modules/service/nps-modules.service new file mode 100644 index 000000000000..22aa9a7510c6 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/service/nps-modules.service @@ -0,0 +1,13 @@ +[Unit] +Description=Nephos kernel modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/nps-modules start +ExecStop=-/etc/init.d/nps-modules stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target 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 new file mode 100755 index 000000000000..a67b1d5f8868 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/hal_tau_pkt_knl.c @@ -0,0 +1,6409 @@ +/* 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: hal_tau_pkt_knl.c + * PURPOSE: + * To provide Linux kernel for PDMA TX/RX control. + * + * NOTES: + * + */ + +/***************************************************************************** + * INCLUDE FILE DECLARATIONS + ***************************************************************************** + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* netif */ +#include +#include +#if defined(NETIF_EN_NETLINK) +#include +#endif +#include + +/* nps_sdk */ +#include + +/***************************************************************************** + * CHIP DEPENDENT VARIABLES + ***************************************************************************** + */ +/* Interrupt */ +#define HAL_TAU_PKT_ERR_REG(__unit__) (_hal_tau_pkt_intr_vec[0].intr_reg) +#define HAL_TAU_PKT_TCH_REG(__unit__, __channel__) (_hal_tau_pkt_intr_vec[1 + (__channel__)].intr_reg) +#define HAL_TAU_PKT_RCH_REG(__unit__, __channel__) (_hal_tau_pkt_intr_vec[5 + (__channel__)].intr_reg) + +#define HAL_TAU_PKT_ERR_EVENT(__unit__) (&_hal_tau_pkt_intr_vec[0].intr_event) +#define HAL_TAU_PKT_TCH_EVENT(__unit__, __channel__) (&_hal_tau_pkt_intr_vec[1 + (__channel__)].intr_event) +#define HAL_TAU_PKT_RCH_EVENT(__unit__, __channel__) (&_hal_tau_pkt_intr_vec[5 + (__channel__)].intr_event) + +#define HAL_TAU_PKT_ERR_CNT(__unit__) (_hal_tau_pkt_intr_vec[0].intr_cnt) +#define HAL_TAU_PKT_TCH_CNT(__unit__, __channel__) (_hal_tau_pkt_intr_vec[1 + (__channel__)].intr_cnt) +#define HAL_TAU_PKT_RCH_CNT(__unit__, __channel__) (_hal_tau_pkt_intr_vec[5 + (__channel__)].intr_cnt) + + +/* This flag value will be specified when user inserts kernel module. */ +#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 */ +UI32_T ext_dbg_flag = 0; + +#define HAL_TAU_PKT_DBG(__flag__, ...) do \ +{ \ + if (0 != ((__flag__) & (ext_dbg_flag))) \ + { \ + osal_printf(__VA_ARGS__); \ + } \ +}while (0) + +typedef struct +{ + UI32_T intr_reg; + NPS_SEMAPHORE_ID_T intr_event; + UI32_T intr_cnt; + +} HAL_TAU_PKT_INTR_VEC_T; + +typedef struct HAL_TAU_PKT_PROFILE_NODE_S +{ + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile; + struct HAL_TAU_PKT_PROFILE_NODE_S *ptr_next_node; + +} HAL_TAU_PKT_PROFILE_NODE_T; + +typedef struct +{ + HAL_TAU_PKT_NETIF_INTF_T meta; + struct net_device *ptr_net_dev; + HAL_TAU_PKT_PROFILE_NODE_T *ptr_profile_list; /* the profiles binding to this interface */ + +} HAL_TAU_PKT_NETIF_PORT_DB_T; + + +static HAL_TAU_PKT_INTR_VEC_T _hal_tau_pkt_intr_vec[] = +{ + { /* 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 }, +}; + +/***************************************************************************** + * NAMING CONSTANT DECLARATIONS + ***************************************************************************** + */ +/* Sleep Time Definitions */ +#define HAL_TAU_PKT_TX_DEQUE_SLEEP() osal_sleepThread(1000) /* us */ +#define HAL_TAU_PKT_RX_DEQUE_SLEEP() osal_sleepThread(1000) /* us */ +#define HAL_TAU_PKT_TX_ENQUE_RETRY_SLEEP() osal_sleepThread(1000) /* us */ +#define HAL_TAU_PKT_RX_ENQUE_RETRY_SLEEP() osal_sleepThread(1000) /* us */ +#define HAL_TAU_PKT_ALLOC_MEM_RETRY_SLEEP() osal_sleepThread(1000) /* us */ + +/* Network Device Definitions */ +/* 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_PORT_NUM + 1) /* CPU port */ + +#define HAL_TAU_PKT_NET_PROFILE_NUM_MAX (256) + +static HAL_TAU_PKT_NETIF_PROFILE_T *_ptr_hal_tau_pkt_profile_entry[HAL_TAU_PKT_NET_PROFILE_NUM_MAX] = {0}; +static HAL_TAU_PKT_NETIF_PORT_DB_T _hal_tau_pkt_port_db[HAL_TAU_PKT_MAX_PORT_NUM]; + +/***************************************************************************** + * MACRO VLAUE DECLARATIONS + ***************************************************************************** + */ + +/***************************************************************************** + * MACRO FUNCTION DECLARATIONS + ***************************************************************************** + */ +/*---------------------------------------------------------------------------*/ +#define HAL_TAU_PKT_GET_DRV_CB_PTR(unit) (&_hal_tau_pkt_drv_cb[unit]) +/*---------------------------------------------------------------------------*/ +#define HAL_TAU_PKT_GET_TX_CB_PTR(unit) (&_hal_tau_pkt_tx_cb[unit]) +#define HAL_TAU_PKT_GET_TX_PDMA_PTR(unit, channel) (&_hal_tau_pkt_tx_cb[unit].pdma[channel]) +#define HAL_TAU_PKT_GET_TX_GPD_PTR(unit, channel, gpd) (&_hal_tau_pkt_tx_cb[unit].pdma[channel].ptr_gpd_align_start_addr[gpd]) +/*---------------------------------------------------------------------------*/ +#define HAL_TAU_PKT_GET_RX_CB_PTR(unit) (&_hal_tau_pkt_rx_cb[unit]) +#define HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel) (&_hal_tau_pkt_rx_cb[unit].pdma[channel]) +#define HAL_TAU_PKT_GET_RX_GPD_PTR(unit, channel, gpd) (&_hal_tau_pkt_rx_cb[unit].pdma[channel].ptr_gpd_align_start_addr[gpd]) +/*---------------------------------------------------------------------------*/ +#define HAL_TAU_PKT_GET_PORT_DB(port) (&_hal_tau_pkt_port_db[port]) +#define HAL_TAU_PKT_GET_PORT_PROFILE_LIST(port) (_hal_tau_pkt_port_db[port].ptr_profile_list) +#define HAL_TAU_PKT_GET_PORT_NETDEV(port) _hal_tau_pkt_port_db[port].ptr_net_dev + +/***************************************************************************** + * DATA TYPE DECLARATIONS + ***************************************************************************** + */ +/* ----------------------------------------------------------------------------------- General structure */ +typedef struct +{ + UI32_T unit; + UI32_T channel; + +} HAL_TAU_PKT_ISR_COOKIE_T; + +typedef struct +{ + NPS_HUGE_T que_id; + NPS_SEMAPHORE_ID_T sema; + UI32_T len; /* Software CPU queue maximum length. */ + UI32_T weight; /* The weight for thread de-queue algorithm. */ + +} HAL_TAU_PKT_SW_QUEUE_T; + +typedef struct +{ + /* handleErrorTask */ + NPS_THREAD_ID_T err_task_id; + + /* INTR dispatcher */ + NPS_ISRLOCK_ID_T intr_lock; + UI32_T intr_bitmap; + +#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; + +} HAL_TAU_PKT_DRV_CB_T; + +/* ----------------------------------------------------------------------------------- TX structure */ +typedef struct +{ + /* NPS_SEMAPHORE_ID_T sema; */ + + /* since the Tx GPD ring may be accessed by multiple process including + * ndo_start_xmit (SW IRQ), it must be protected with an ISRLOCK + * instead of the original semaphore + */ + NPS_ISRLOCK_ID_T ring_lock; + + UI32_T used_idx; /* SW send index = LAMP simulate the Tx HW index */ + UI32_T free_idx; /* SW free index */ + UI32_T used_gpd_num; + UI32_T free_gpd_num; + UI32_T gpd_num; + + HAL_TAU_PKT_TX_GPD_T *ptr_gpd_start_addr; + HAL_TAU_PKT_TX_GPD_T *ptr_gpd_align_start_addr; + BOOL_T err_flag; + + /* ASYNC */ + HAL_TAU_PKT_TX_SW_GPD_T **pptr_sw_gpd_ring; + HAL_TAU_PKT_TX_SW_GPD_T **pptr_sw_gpd_bulk; /* temporary store packets to be enque */ + + /* SYNC_INTR */ + NPS_SEMAPHORE_ID_T sync_intr_sema; + +} HAL_TAU_PKT_TX_PDMA_T; + +typedef struct +{ + HAL_TAU_PKT_TX_WAIT_T wait_mode; + HAL_TAU_PKT_TX_PDMA_T pdma[HAL_TAU_PKT_TX_CHANNEL_LAST]; + HAL_TAU_PKT_TX_CNT_T cnt; + + /* handleTxDoneTask */ + NPS_THREAD_ID_T isr_task_id[HAL_TAU_PKT_TX_CHANNEL_LAST]; + HAL_TAU_PKT_ISR_COOKIE_T isr_task_cookie[HAL_TAU_PKT_TX_CHANNEL_LAST]; + + /* txTask */ + HAL_TAU_PKT_SW_QUEUE_T sw_queue; + NPS_SEMAPHORE_ID_T sync_sema; + NPS_THREAD_ID_T task_id; + 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; + +/* ----------------------------------------------------------------------------------- RX structure */ +typedef struct +{ + NPS_SEMAPHORE_ID_T sema; + UI32_T cur_idx; /* SW free index */ + UI32_T gpd_num; + + HAL_TAU_PKT_RX_GPD_T *ptr_gpd_start_addr; + HAL_TAU_PKT_RX_GPD_T *ptr_gpd_align_start_addr; + BOOL_T err_flag; + struct sk_buff **pptr_skb_ring; +} HAL_TAU_PKT_RX_PDMA_T; + +typedef struct +{ + /* Rx system configuration */ + UI32_T buf_len; + + HAL_TAU_PKT_RX_SCHED_T sched_mode; + HAL_TAU_PKT_RX_PDMA_T pdma[HAL_TAU_PKT_RX_CHANNEL_LAST]; + HAL_TAU_PKT_RX_CNT_T cnt; + + /* handleRxDoneTask */ + NPS_THREAD_ID_T isr_task_id[HAL_TAU_PKT_RX_CHANNEL_LAST]; + HAL_TAU_PKT_ISR_COOKIE_T isr_task_cookie[HAL_TAU_PKT_RX_CHANNEL_LAST]; + + /* rxTask */ + HAL_TAU_PKT_SW_QUEUE_T sw_queue[HAL_TAU_PKT_RX_QUEUE_NUM]; + UI32_T deque_idx; + NPS_SEMAPHORE_ID_T sync_sema; + NPS_THREAD_ID_T task_id; + NPS_SEMAPHORE_ID_T deinit_sema; /* To sync-up the Rx-stop and thread flush queues */ + BOOL_T running; /* TRUE when rxStart + * FALSE when rxStop + */ + +} HAL_TAU_PKT_RX_CB_T; + +/* ----------------------------------------------------------------------------------- Network Device */ +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; +}; + +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; + +/***************************************************************************** + * GLOBAL VARIABLE DECLARATIONS + ***************************************************************************** + */ + +/***************************************************************************** + * STATIC VARIABLE DECLARATIONS + ***************************************************************************** + */ +/*---------------------------------------------------------------------------*/ +static HAL_TAU_PKT_DRV_CB_T _hal_tau_pkt_drv_cb[NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM]; +static HAL_TAU_PKT_TX_CB_T _hal_tau_pkt_tx_cb[NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM]; +static HAL_TAU_PKT_RX_CB_T _hal_tau_pkt_rx_cb[NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM]; +/*---------------------------------------------------------------------------*/ + +/***************************************************************************** + * LOCAL SUBPROGRAM DECLARATIONS + ***************************************************************************** + */ +/* ----------------------------------------------------------------------------------- Interrupt */ +static NPS_ERROR_NO_T +_hal_tau_pkt_enableIntr( + const UI32_T unit, + const UI32_T intr_bitmap) +{ + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + NPS_IRQ_FLAGS_T irq_flag = 0; + UI32_T intr_en = 0; + + osal_takeIsrLock(&ptr_cb->intr_lock, &irq_flag); + osal_mdc_readPciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_CP_COMMON_INT_EN_HI), &intr_en, sizeof(intr_en)); + intr_en |= intr_bitmap; + osal_mdc_writePciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_CP_COMMON_INT_EN_HI), &intr_en, sizeof(intr_en)); + osal_giveIsrLock(&ptr_cb->intr_lock, &irq_flag); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_disableIntr( + const UI32_T unit, + const UI32_T intr_bitmap) +{ + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + NPS_IRQ_FLAGS_T irq_flag = 0; + UI32_T intr_en = 0; + + osal_takeIsrLock(&ptr_cb->intr_lock, &irq_flag); + osal_mdc_readPciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_CP_COMMON_INT_EN_HI), &intr_en, sizeof(intr_en)); + intr_en &= ~intr_bitmap; + osal_mdc_writePciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_CP_COMMON_INT_EN_HI), &intr_en, sizeof(intr_en)); + osal_giveIsrLock(&ptr_cb->intr_lock, &irq_flag); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_maskIntr( + const UI32_T unit, + const UI32_T intr_bitmap) +{ + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + NPS_IRQ_FLAGS_T irq_flag = 0; + + osal_takeIsrLock(&ptr_cb->intr_lock, &irq_flag); + osal_mdc_writePciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_CP_COMMON_INT_MASK_CLR_HI), &intr_bitmap, sizeof(intr_bitmap)); + osal_giveIsrLock(&ptr_cb->intr_lock, &irq_flag); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_unmaskIntr( + const UI32_T unit, + const UI32_T intr_bitmap) +{ + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + NPS_IRQ_FLAGS_T irq_flag = 0; + + osal_takeIsrLock(&ptr_cb->intr_lock, &irq_flag); + osal_mdc_writePciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_CP_COMMON_INT_MASK_SET_HI), &intr_bitmap, sizeof(intr_bitmap)); + osal_giveIsrLock(&ptr_cb->intr_lock, &irq_flag); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_dispatcher( + void *ptr_cookie) +{ + UI32_T unit = (UI32_T)((NPS_HUGE_T)ptr_cookie); + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + NPS_IRQ_FLAGS_T irq_flag = 0; + + UI32_T idx = 0, vec = sizeof(_hal_tau_pkt_intr_vec) / sizeof(HAL_TAU_PKT_INTR_VEC_T); + UI32_T intr_mask = ptr_cb->intr_bitmap; + UI32_T intr_unmask = 0; + UI32_T intr_status = 0; + + /* MASK, READ and CLEAR PKT IRQs */ + osal_takeIsrLock(&ptr_cb->intr_lock, &irq_flag); + osal_mdc_writePciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_CP_COMMON_INT_MASK_CLR_HI), &intr_mask, sizeof(UI32_T)); + osal_mdc_readPciReg (unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_CP_COMMON_INT_STAT_HI), &intr_status, sizeof(UI32_T)); + intr_status = intr_status & intr_mask; + osal_mdc_writePciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_CP_COMMON_INT_CLR_HI), &intr_status, sizeof(UI32_T)); + osal_giveIsrLock(&ptr_cb->intr_lock, &irq_flag); + + /* Module thread handle and unmask the interrupt */ + intr_unmask = intr_status ^ intr_mask; + if (0x0 != intr_status) + { + for (idx = 0; idx < vec; idx++) + { + if (_hal_tau_pkt_intr_vec[idx].intr_reg & intr_status) + { + osal_triggerEvent(&_hal_tau_pkt_intr_vec[idx].intr_event); + _hal_tau_pkt_intr_vec[idx].intr_cnt++; + } + } + } + + /* UNMASK other PKT IRQs */ + osal_takeIsrLock(&ptr_cb->intr_lock, &irq_flag); + osal_mdc_writePciReg(unit, HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_CP_COMMON_INT_MASK_SET_HI), &intr_unmask, sizeof(UI32_T)); + osal_giveIsrLock(&ptr_cb->intr_lock, &irq_flag); + + return (NPS_E_OK); +} + +/* ----------------------------------------------------------------------------------- RW HW Regs */ +/* FUNCTION NAME: _hal_tau_pkt_startTxChannelReg + * PURPOSE: + * To issue "START" command to the target TX channel. + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * gpd_num -- The GPD ring length of the channel + * OUTPUT: + * None. + * RETURN: + * NPS_E_OK -- Successfully configure the register. + * NPS_E_OTHERS -- Configure the register failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_startTxChannelReg( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel, + const UI32_T gpd_num) +{ + HAL_TAU_PKT_TCH_CMD_REG_T tch_cmd; + + tch_cmd.reg = 0x0; + tch_cmd.field.tch_start = 0x1; + tch_cmd.field.tch_gpd_add_no_lo = gpd_num & 0xff; + tch_cmd.field.tch_gpd_add_no_hi = (gpd_num & 0xff00) >> 8; + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_TCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_TCH_CMD), channel), + &tch_cmd.reg, sizeof(HAL_TAU_PKT_TCH_CMD_REG_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_startRxChannelReg + * PURPOSE: + * To issue "START" command to the target RX channel. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * gpd_num -- The GPD ring length of the channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure the register. + * NPS_E_OTHERS -- Configure the register failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_startRxChannelReg( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel, + const UI32_T gpd_num) +{ + HAL_TAU_PKT_RCH_CMD_REG_T rch_cmd; + + rch_cmd.reg = 0x0; + rch_cmd.field.rch_start = 0x1; + rch_cmd.field.rch_gpd_add_no_lo = gpd_num & 0xff; + rch_cmd.field.rch_gpd_add_no_hi = (gpd_num & 0xff00) >> 8; + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_RCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_RCH_CMD), channel), + &rch_cmd.reg, sizeof(HAL_TAU_PKT_RCH_CMD_REG_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_resumeTxChannelReg + * PURPOSE: + * To issue "RESUME" command to the target TX channel. + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * gpd_num -- The GPD ring length of the channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure the register. + * NPS_E_OTHERS -- Configure the register failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_resumeTxChannelReg( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel, + const UI32_T gpd_num) +{ + HAL_TAU_PKT_TCH_CMD_REG_T tch_cmd; + + tch_cmd.reg = 0x0; + tch_cmd.field.tch_resume = 0x1; + tch_cmd.field.tch_gpd_add_no_lo = gpd_num & 0xff; + tch_cmd.field.tch_gpd_add_no_hi = (gpd_num & 0xff00) >> 8; + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_TCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_TCH_CMD), channel), + &tch_cmd.reg, sizeof(HAL_TAU_PKT_TCH_CMD_REG_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_resumeRxChannelReg + * PURPOSE: + * To issue "RESUME" command to the target RX channel. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * gpd_num -- The GPD ring length of the channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure the register. + * NPS_E_OTHERS -- Configure the register failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_resumeRxChannelReg( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel, + const UI32_T gpd_num) +{ + HAL_TAU_PKT_RCH_CMD_REG_T rch_cmd; + + rch_cmd.reg = 0x0; + rch_cmd.field.rch_resume = 0x1; + rch_cmd.field.rch_gpd_add_no_lo = gpd_num & 0xff; + rch_cmd.field.rch_gpd_add_no_hi = (gpd_num & 0xff00) >> 8; + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_RCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_RCH_CMD), channel), + &rch_cmd.reg, sizeof(HAL_TAU_PKT_RCH_CMD_REG_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_stopTxChannelReg + * PURPOSE: + * To issue "STOP" command to the target TX channel. + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure the register. + * NPS_E_OTHERS -- Configure the register failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_stopTxChannelReg( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel) +{ + HAL_TAU_PKT_TCH_CMD_REG_T tch_cmd; + + tch_cmd.reg = 0x0; + tch_cmd.field.tch_stop = 0x1; + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_TCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_TCH_CMD), channel), + &tch_cmd.reg, sizeof(HAL_TAU_PKT_TCH_CMD_REG_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_stopRxChannelReg + * PURPOSE: + * To issue "STOP" command to the target RX channel. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure the register. + * NPS_E_OTHERS -- Configure the register failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_stopRxChannelReg( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + HAL_TAU_PKT_RCH_CMD_REG_T rch_cmd; + + rch_cmd.reg = 0x0; + rch_cmd.field.rch_stop = 0x1; + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_RCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_RCH_CMD), channel), + &rch_cmd.reg, sizeof(HAL_TAU_PKT_RCH_CMD_REG_T)); + + return (NPS_E_OK); +} + +/* ----------------------------------------------------------------------------------- Init HW Regs */ +/* FUNCTION NAME: _hal_tau_pkt_setTxGpdStartAddrReg + * PURPOSE: + * To configure the start address and the length of target GPD ring of TX channel. + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * gpd_start_addr -- The start address of the GPD ring + * gpd_ring_sz -- The size of the GPD ring + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure the register. + * NPS_E_OTHERS -- Configure the register failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_setTxGpdStartAddrReg( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel, + const NPS_ADDR_T gpd_start_addr, + const UI32_T gpd_ring_sz) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + UI32_T tch_gpd_ring_start_addr_lo = 0; + UI32_T tch_gpd_ring_start_addr_hi = 0; + UI32_T tch_gpd_ring_size = 0; + + /* Configure the low 32-bit address. */ + tch_gpd_ring_start_addr_lo = (UI32_T)NPS_ADDR_64_LOW(gpd_start_addr); + + rc = osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_TCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_TCH_GPD_RING_START_ADDR_LO), channel), + &tch_gpd_ring_start_addr_lo, sizeof(UI32_T)); + + /* Configure the high 32-bit address. */ + if (NPS_E_OK == rc) + { + tch_gpd_ring_start_addr_hi = (UI32_T)NPS_ADDR_64_HI(gpd_start_addr); + + rc = osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_TCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_TCH_GPD_RING_START_ADDR_HI), channel), + &tch_gpd_ring_start_addr_hi, sizeof(UI32_T)); + } + + /* Configure the GPD ring size. */ + if (NPS_E_OK == rc) + { + tch_gpd_ring_size = gpd_ring_sz; + + rc = osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_TCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_TCH_GPD_RING_SIZE), channel), + &tch_gpd_ring_size, sizeof(UI32_T)); + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_setRxGpdStartAddrReg + * PURPOSE: + * To configure the start address and the length of target GPD ring of RX channel. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * gpd_start_addr -- The start address of the GPD ring + * gpd_ring_sz -- The size of the GPD ring + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure the register. + * NPS_E_OTHERS -- Configure the register failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_setRxGpdStartAddrReg( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel, + const NPS_ADDR_T gpd_start_addr, + const UI32_T gpd_ring_sz) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + UI32_T rch_gpd_ring_start_addr_lo = 0; + UI32_T rch_gpd_ring_start_addr_hi = 0; + UI32_T rch_gpd_ring_size = 0; + + /* Configure the low 32-bit address. */ + rch_gpd_ring_start_addr_lo = (UI32_T)NPS_ADDR_64_LOW(gpd_start_addr); + + rc = osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_RCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_RCH_GPD_RING_START_ADDR_LO), channel), + &rch_gpd_ring_start_addr_lo, sizeof(UI32_T)); + + /* Configure the high 32-bit address. */ + if (NPS_E_OK == rc) + { + rch_gpd_ring_start_addr_hi = (UI32_T)NPS_ADDR_64_HI(gpd_start_addr); + + rc = osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_RCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_RCH_GPD_RING_START_ADDR_HI), channel), + &rch_gpd_ring_start_addr_hi, sizeof(UI32_T)); + } + + /* Configure the GPD ring size. */ + if (NPS_E_OK == rc) + { + rch_gpd_ring_size = gpd_ring_sz; + + rc = osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_RCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_RCH_GPD_RING_SIZE), channel), + &rch_gpd_ring_size, sizeof(UI32_T)); + } + + return (rc); +} + +/* ----------------------------------------------------------------------------------- ISR HW Regs */ +/* FUNCTION NAME: _hal_tau_pkt_maskAllTxL2IsrReg + * PURPOSE: + * To mask all the TX L2 interrupts for the specified channel. + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully mask all the TX L2 interrupts. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_maskAllTxL2IsrReg( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel) +{ + UI32_T reg = 0; + + HAL_TAU_PKT_CLR_BITMAP(reg, + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_HWO_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_NO_OVFL_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_DMA_READ_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_BUF_SIZE_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_RUNT_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_OVSZ_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_LEN_MISMATCH_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PKTPL_DMA_READ_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_COS_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_GT255_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PFC | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_CREDIT_UDFL_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_DMA_WRITE_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_STOP_CMD_CPLT); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_TCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_TCH_INT_MASK), channel), + ®, sizeof(UI32_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_maskAllRxL2IsrReg + * PURPOSE: + * To mask all the L2 interrupts for the specified channel. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully mask all the L2 interrupts. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_maskAllRxL2IsrReg( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + UI32_T reg = 0; + + HAL_TAU_PKT_CLR_BITMAP(reg, + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_LOW | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_EMPTY | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_ERROR | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_READ_ERROR | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_WRITE_ERROR | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_STOP_CMD_CPLT | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_GT255_ERROR | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_TOD_UNINIT | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_PKT_ERROR_DROP | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_UDSZ_DROP | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_OVSZ_DROP | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_CMDQ_OVF_DROP | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_FIFO_OVF_DROP); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_RCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_RCH_INT_MASK), channel), + ®, sizeof(UI32_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_unmaskAllTxL2IsrReg + * PURPOSE: + * To unmask all the TX L2 interrupts for the specified channel. + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully unmask all the TX L2 interrupts. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_unmaskAllTxL2IsrReg( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel) +{ + UI32_T reg = 0; + + HAL_TAU_PKT_SET_BITMAP(reg, + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_HWO_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_NO_OVFL_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_DMA_READ_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_BUF_SIZE_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_RUNT_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_OVSZ_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_LEN_MISMATCH_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PKTPL_DMA_READ_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_COS_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_GT255_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PFC | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_CREDIT_UDFL_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_DMA_WRITE_ERROR | + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_STOP_CMD_CPLT); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_TCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_TCH_INT_MASK), channel), + ®, sizeof(UI32_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_unmaskAllRxL2IsrReg + * PURPOSE: + * To unmask all the L2 interrupts for the specified channel. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully unmask all the L2 interrupts. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_unmaskAllRxL2IsrReg( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + UI32_T reg = 0; + + HAL_TAU_PKT_SET_BITMAP(reg, + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_LOW | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_EMPTY | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_ERROR | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_READ_ERROR | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_WRITE_ERROR | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_STOP_CMD_CPLT | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_GT255_ERROR | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_TOD_UNINIT | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_PKT_ERROR_DROP | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_UDSZ_DROP | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_OVSZ_DROP | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_CMDQ_OVF_DROP | + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_FIFO_OVF_DROP); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_RCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_RCH_INT_MASK), channel), + ®, sizeof(UI32_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_clearTxL2IsrStatusReg + * PURPOSE: + * To clear the status of TX L2 interrupts for the specified channel. + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * isr_bitmap -- The bitmap used to specify the target ISRs + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully clear L1 ISR status. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_clearTxL2IsrStatusReg( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel, + const HAL_TAU_PKT_TX_CHANNEL_L2_ISR_T isr_bitmap) +{ + UI32_T reg = 0; + + HAL_TAU_PKT_SET_BITMAP(reg, isr_bitmap); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_TCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_TCH_INT_CLR), channel), + ®, sizeof(UI32_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_clearRxL2IsrStatusReg + * PURPOSE: + * To clear the status of RX L2 interrupts for the specified channel. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * isr_bitmap -- The bitmap used to specify the target ISRs + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully clear RX L2 ISR status. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_clearRxL2IsrStatusReg( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel, + const HAL_TAU_PKT_RX_CHANNEL_L2_ISR_T isr_bitmap) +{ + UI32_T reg = 0; + + HAL_TAU_PKT_SET_BITMAP(reg, isr_bitmap); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_PDMA_RCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_RCH_INT_CLR), channel), + ®, sizeof(UI32_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: hal_tau_pkt_getTxIntrCnt + * PURPOSE: + * To get the PDMA TX interrupt counters of the target channel. + * INPUT: + * unit -- The unit ID + * channel -- The target channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully get the counters. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_getTxIntrCnt( + const UI32_T unit, + const UI32_T channel, + UI32_T *ptr_intr_cnt) +{ + *ptr_intr_cnt = HAL_TAU_PKT_TCH_CNT(unit, channel); + return (NPS_E_OK); +} + +/* FUNCTION NAME: hal_tau_pkt_getRxIntrCnt + * PURPOSE: + * To get the PDMA RX interrupt counters of the target channel. + * INPUT: + * unit -- The unit ID + * channel -- The target channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully get the counters. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_getRxIntrCnt( + const UI32_T unit, + const UI32_T channel, + UI32_T *ptr_intr_cnt) +{ + *ptr_intr_cnt = HAL_TAU_PKT_RCH_CNT(unit, channel); + return (NPS_E_OK); +} + +/* FUNCTION NAME: hal_tau_pkt_getTxKnlCnt + * PURPOSE: + * To get the PDMA TX counters of the target channel. + * INPUT: + * unit -- The unit ID + * ptr_cookie -- Pointer of the TX cookie + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully get the counters. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_getTxKnlCnt( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_CH_CNT_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_TX_CB_T *ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit); + + osal_io_copyToUser(&ptr_cookie->tx_cnt, &ptr_tx_cb->cnt, sizeof(HAL_TAU_PKT_TX_CNT_T)); + return (NPS_E_OK); +} + +/* FUNCTION NAME: hal_tau_pkt_getRxKnlCnt + * PURPOSE: + * To get the PDMA RX counters of the target channel. + * INPUT: + * unit -- The unit ID + * ptr_cookie -- Pointer of the RX cookie + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully get the counters. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_getRxKnlCnt( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_CH_CNT_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + + osal_io_copyToUser(&ptr_cookie->rx_cnt, &ptr_rx_cb->cnt, sizeof(HAL_TAU_PKT_RX_CNT_T)); + return (NPS_E_OK); +} + +/* FUNCTION NAME: hal_tau_pkt_clearTxKnlCnt + * PURPOSE: + * To clear the PDMA TX counters of the target channel. + * INPUT: + * unit -- The unit ID + * ptr_cookie -- Pointer of the TX cookie + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully clear the counters. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_clearTxKnlCnt( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_TX_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_TX_CB_T *ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit); + + osal_memset(&ptr_tx_cb->cnt, 0, sizeof(HAL_TAU_PKT_TX_CNT_T)); + return (NPS_E_OK); +} + +/* FUNCTION NAME: hal_tau_pkt_clearRxKnlCnt + * PURPOSE: + * To clear the PDMA RX counters of the target channel. + * INPUT: + * unit -- The unit ID + * ptr_cookie -- Pointer of the RX cookie + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully clear the counters. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_clearRxKnlCnt( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_RX_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + + osal_memset(&ptr_rx_cb->cnt, 0, sizeof(HAL_TAU_PKT_RX_CNT_T)); + return (NPS_E_OK); +} + +/* FUNCTION NAME: hal_tau_pkt_setPortAttr + * PURPOSE: + * To set the port attributes such as status or speeds. + * INPUT: + * unit -- The unit ID + * ptr_cookie -- Pointer of the Port cookie + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully set the attributes. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_setPortAttr( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_PORT_COOKIE_T *ptr_cookie) +{ +#define HAL_TAU_PKT_PORT_STATUS_UP (1) +#define HAL_TAU_PKT_PORT_STATUS_DOWN (0) + struct net_device *ptr_net_dev; + struct net_device_priv *ptr_priv; + UI32_T port; + UI32_T status; + NPS_PORT_SPEED_T speed; + + osal_io_copyFromUser(&port, &ptr_cookie->port, sizeof(UI32_T)); + osal_io_copyFromUser(&status, &ptr_cookie->status, sizeof(UI32_T)); + osal_io_copyFromUser(&speed, &ptr_cookie->speed, sizeof(NPS_PORT_SPEED_T)); + + ptr_net_dev = HAL_TAU_PKT_GET_PORT_NETDEV(port); + if ((NULL != ptr_net_dev) && (portspeed = SPEED_1000; + break; + case NPS_PORT_SPEED_10G: + ptr_priv->speed = SPEED_10000; + break; + case NPS_PORT_SPEED_25G: + ptr_priv->speed = 25000; + break; + case NPS_PORT_SPEED_40G: + ptr_priv->speed = 40000; + break; + case NPS_PORT_SPEED_50G: + ptr_priv->speed = 50000; + break; + case NPS_PORT_SPEED_100G: + ptr_priv->speed = 100000; + break; + default: + break; + } + } + 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: + * To enqueue the target data. + * INPUT: + * ptr_que -- Pointer for the target queue + * ptr_data -- Pointer for the data to be enqueued + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully enqueue the data. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_enQueue( + HAL_TAU_PKT_SW_QUEUE_T *ptr_que, + void *ptr_data) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + + osal_takeSemaphore(&ptr_que->sema, NPS_SEMAPHORE_WAIT_FOREVER); + rc = osal_que_enque(&ptr_que->que_id, ptr_data); + osal_giveSemaphore(&ptr_que->sema); + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_deQueue + * PURPOSE: + * To dequeue the target data. + * INPUT: + * ptr_que -- Pointer for the target queue + * pptr_data -- Pointer for the data pointer to be dequeued + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully dequeue the data. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_deQueue( + HAL_TAU_PKT_SW_QUEUE_T *ptr_que, + void **pptr_data) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + + osal_takeSemaphore(&ptr_que->sema, NPS_SEMAPHORE_WAIT_FOREVER); + rc = osal_que_deque(&ptr_que->que_id, pptr_data); + osal_giveSemaphore(&ptr_que->sema); + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_getQueueCount + * PURPOSE: + * To obtain the current GPD number in the target RX queue. + * INPUT: + * ptr_que -- Pointer for the target queue + * ptr_count -- Pointer for the data count + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully obtain the GPD count. + * NPS_E_BAD_PARAMETER -- Parameter pointer is null. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_getQueueCount( + HAL_TAU_PKT_SW_QUEUE_T *ptr_que, + UI32_T *ptr_count) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + + osal_takeSemaphore(&ptr_que->sema, NPS_SEMAPHORE_WAIT_FOREVER); + osal_que_getCount(&ptr_que->que_id, ptr_count); + osal_giveSemaphore(&ptr_que->sema); + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_allocRxPayloadBuf + * PURPOSE: + * To allocate the RX packet payload buffer for the GPD. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * gpd_idx -- The current GPD index + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully allocate the buffer. + * NPS_E_NO_MEMORY -- Allocate the buffer failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_allocRxPayloadBuf( + const UI32_T unit, + const UI32_T channel, + const UI32_T gpd_idx) +{ + NPS_ERROR_NO_T rc = NPS_E_NO_MEMORY; + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd = HAL_TAU_PKT_GET_RX_GPD_PTR(unit, channel, gpd_idx); + NPS_ADDR_T phy_addr = 0; + + HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + struct sk_buff *ptr_skb = NULL; + + ptr_skb = osal_skb_alloc(ptr_rx_cb->buf_len); + if (NULL != ptr_skb) + { + /* map skb to dma */ + phy_addr = osal_skb_mapDma(ptr_skb, DMA_FROM_DEVICE); + if (0x0 == phy_addr) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, + "u=%u, rxch=%u, skb dma map err, size=%u\n", + unit, channel, ptr_skb->len); + osal_skb_free(ptr_skb); + rc = NPS_E_NO_MEMORY; + } + else + { + ptr_rx_pdma->pptr_skb_ring[gpd_idx] = ptr_skb; + rc = NPS_E_OK; + } + } + + if (NPS_E_OK == rc) + { + ptr_rx_gpd->data_buf_addr_hi = NPS_ADDR_64_HI(phy_addr); + ptr_rx_gpd->data_buf_addr_lo = NPS_ADDR_64_LOW(phy_addr); + ptr_rx_gpd->avbl_buf_len = ptr_rx_cb->buf_len; + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_freeRxPayloadBuf + * PURPOSE: + * To free the RX packet payload buffer for the GPD. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * gpd_idx -- The current GPD index + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully free the buffer. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_freeRxPayloadBuf( + const UI32_T unit, + const UI32_T channel, + const UI32_T gpd_idx) +{ + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd = HAL_TAU_PKT_GET_RX_GPD_PTR(unit, channel, gpd_idx); + NPS_ADDR_T phy_addr = 0; + + HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + struct sk_buff *ptr_skb = NULL; + + phy_addr = NPS_ADDR_32_TO_64(ptr_rx_gpd->data_buf_addr_hi, ptr_rx_gpd->data_buf_addr_lo); + if (0x0 != phy_addr) + { + /* unmap dma */ + ptr_skb = ptr_rx_pdma->pptr_skb_ring[gpd_idx]; + osal_skb_unmapDma(phy_addr, ptr_skb->len, DMA_FROM_DEVICE); + osal_skb_free(ptr_skb); + rc = NPS_E_OK; + } + + if (NPS_E_OK == rc) + { + ptr_rx_gpd->data_buf_addr_hi = 0x0; + ptr_rx_gpd->data_buf_addr_lo = 0x0; + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_freeRxPayloadBufGpd + * PURPOSE: + * To free the RX packet payload buffer for the GPD. + * INPUT: + * unit -- The unit ID + * ptr_sw_gpd -- The pointer of RX SW GPD + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully free the buffer. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_freeRxPayloadBufGpd( + const UI32_T unit, + HAL_TAU_PKT_RX_SW_GPD_T *ptr_sw_gpd) +{ + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + NPS_ADDR_T phy_addr = 0; + + struct sk_buff *ptr_skb = NULL; + + phy_addr = NPS_ADDR_32_TO_64(ptr_sw_gpd->rx_gpd.data_buf_addr_hi, ptr_sw_gpd->rx_gpd.data_buf_addr_lo); + if (0x0 != phy_addr) + { + ptr_skb = ptr_sw_gpd->ptr_cookie; + osal_skb_free(ptr_skb); + rc = NPS_E_OK; + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_initTxPdmaRing + * PURPOSE: + * To initialize the GPD ring of target TX channel. + * + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully initialize the GPD ring. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_initTxPdmaRing( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + 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; + NPS_ADDR_T phy_addr = 0; + UI32_T gpd_idx = 0; + + for (gpd_idx = 0; gpd_idx < ptr_tx_pdma->gpd_num; gpd_idx++) + { + ptr_tx_gpd = HAL_TAU_PKT_GET_TX_GPD_PTR(unit, channel, gpd_idx); + osal_memset((void *)ptr_tx_gpd, 0x0, sizeof(HAL_TAU_PKT_TX_GPD_T)); + ptr_tx_gpd->ioc = HAL_TAU_PKT_IOC_HAS_INTR; + ptr_tx_gpd->ch = HAL_TAU_PKT_CH_LAST_GPD; + ptr_tx_gpd->hwo = HAL_TAU_PKT_HWO_SW_OWN; + osal_dma_flushCache((void *)ptr_tx_gpd, sizeof(HAL_TAU_PKT_TX_GPD_T)); + } + + phy_addr = osal_dma_convertVirtToPhy(ptr_tx_pdma->ptr_gpd_align_start_addr); + rc = _hal_tau_pkt_setTxGpdStartAddrReg(unit, channel, phy_addr, ptr_tx_pdma->gpd_num); + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_initRxPdmaRing + * PURPOSE: + * To initialize the RX GPD ring. + * INPUT: + * unit -- The target unit + * channel -- The target RX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully initialize the RX GPD ring. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_initRxPdmaRing( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd = NULL; + NPS_ADDR_T phy_addr = 0; + UI32_T gpd_idx = 0; + + for (gpd_idx = 0; gpd_idx < ptr_rx_pdma->gpd_num; gpd_idx++) + { + ptr_rx_gpd = HAL_TAU_PKT_GET_RX_GPD_PTR(unit, channel, gpd_idx); + osal_memset((void *)ptr_rx_gpd, 0x0, sizeof(HAL_TAU_PKT_RX_GPD_T)); + ptr_rx_gpd->ioc = HAL_TAU_PKT_IOC_NO_INTR; + ptr_rx_gpd->hwo = HAL_TAU_PKT_HWO_SW_OWN; + osal_dma_flushCache((void *)ptr_rx_gpd, sizeof(HAL_TAU_PKT_RX_GPD_T)); + } + + phy_addr = osal_dma_convertVirtToPhy(ptr_rx_pdma->ptr_gpd_align_start_addr); + rc = _hal_tau_pkt_setRxGpdStartAddrReg(unit, channel, phy_addr, ptr_rx_pdma->gpd_num); + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_initRxPdmaRingBuf + * PURPOSE: + * To de-init the Rx PDMA ring configuration. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully de-init the Rx PDMA ring. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_initRxPdmaRingBuf( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd = NULL; + UI32_T gpd_idx = 0; + + if (0 == ptr_rx_cb->buf_len) + { + return (NPS_E_BAD_PARAMETER); + } + + for (gpd_idx = 0; gpd_idx < ptr_rx_pdma->gpd_num; gpd_idx++) + { + ptr_rx_gpd = HAL_TAU_PKT_GET_RX_GPD_PTR(unit, channel, gpd_idx); + osal_dma_invalidateCache((void *)ptr_rx_gpd, sizeof(HAL_TAU_PKT_RX_GPD_T)); + + rc = _hal_tau_pkt_allocRxPayloadBuf(unit, channel, gpd_idx); + if (NPS_E_OK == rc) + { + ptr_rx_gpd->ioc = HAL_TAU_PKT_IOC_HAS_INTR; + ptr_rx_gpd->hwo = HAL_TAU_PKT_HWO_HW_OWN; + osal_dma_flushCache((void *)ptr_rx_gpd, sizeof(HAL_TAU_PKT_RX_GPD_T)); + } + else + { + ptr_rx_cb->cnt.no_memory++; + break; + } + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_deinitRxPdmaRingBuf + * PURPOSE: + * To de-init the Rx PDMA ring configuration. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully de-init the Rx PDMA ring. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_deinitRxPdmaRingBuf( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd = NULL; + UI32_T gpd_idx = 0; + + for (gpd_idx = 0; ((gpd_idx < ptr_rx_pdma->gpd_num) && (NPS_E_OK == rc)); gpd_idx++) + { + /* mark the GPD as invalid to prevent Rx-done task to process it */ + ptr_rx_gpd = HAL_TAU_PKT_GET_RX_GPD_PTR(unit, channel, gpd_idx); + ptr_rx_gpd->hwo = HAL_TAU_PKT_HWO_HW_OWN; + osal_dma_flushCache((void *)ptr_rx_gpd, sizeof(HAL_TAU_PKT_RX_GPD_T)); + + rc = _hal_tau_pkt_freeRxPayloadBuf(unit, channel, gpd_idx); + } + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_recoverTxPdma + * PURPOSE: + * To recover the PDMA status to the initial state. + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully recover PDMA. + * NOTES: + * + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_recoverTxPdma( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_TX_PDMA_T *ptr_tx_pdma = HAL_TAU_PKT_GET_TX_PDMA_PTR(unit, channel); + + /* Release the software GPD ring and configure it again. */ + 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 = ptr_tx_pdma->gpd_num; + + _hal_tau_pkt_stopTxChannelReg(unit, channel); + rc = _hal_tau_pkt_initTxPdmaRing(unit, channel); + _hal_tau_pkt_startTxChannelReg(unit, channel, 0); + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_recoverRxPdma + * PURPOSE: + * To recover the RX PDMA from the error state. + * INPUT: + * unit -- The unit ID + * channel -- The target RX channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully recovery the PDMA. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_recoverRxPdma( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + + /* Release the software GPD ring and configure it again. */ + ptr_rx_pdma->cur_idx = 0; + + _hal_tau_pkt_stopRxChannelReg(unit, channel); + rc = _hal_tau_pkt_deinitRxPdmaRingBuf(unit, channel); + if (NPS_E_OK != rc) + { + return (rc); + } + rc = _hal_tau_pkt_initRxPdmaRing(unit, channel); + if (NPS_E_OK != rc) + { + return (rc); + } + rc = _hal_tau_pkt_initRxPdmaRingBuf(unit, channel); + if (NPS_E_OK != rc) + { + return (rc); + } + _hal_tau_pkt_startRxChannelReg(unit, channel, ptr_rx_pdma->gpd_num); + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_freeTxGpdList + * PURPOSE: + * To free the TX SW GPD link list. + * INPUT: + * unit -- The unit ID + * ptr_sw_gpd -- The pointer of TX SW GPD + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully free the GPD list. + * NOTES: + * None + */ +static void +_hal_tau_pkt_freeTxGpdList( + UI32_T unit, + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd) +{ + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd_cur = NULL; + + while (NULL != ptr_sw_gpd) + { + ptr_sw_gpd_cur = ptr_sw_gpd; + ptr_sw_gpd = ptr_sw_gpd->ptr_next; + osal_free(ptr_sw_gpd_cur); + } +} + +/* FUNCTION NAME: _hal_tau_pkt_freeRxGpdList + * PURPOSE: + * To free the RX SW GPD link list. + * INPUT: + * unit -- The unit ID + * ptr_sw_gpd -- The pointer of RX SW GPD + * free_payload -- TRUE: To free the buf in SDK, FALSE: in user process. + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully recovery the PDMA. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_freeRxGpdList( + UI32_T unit, + HAL_TAU_PKT_RX_SW_GPD_T *ptr_sw_gpd, + BOOL_T free_payload) +{ + HAL_TAU_PKT_RX_SW_GPD_T *ptr_sw_gpd_cur = NULL; + + while (NULL != ptr_sw_gpd) + { + ptr_sw_gpd_cur = ptr_sw_gpd; + ptr_sw_gpd = ptr_sw_gpd->ptr_next; + if (TRUE == free_payload) + { + _hal_tau_pkt_freeRxPayloadBufGpd(unit, ptr_sw_gpd_cur); + } + osal_free(ptr_sw_gpd_cur); + } + + return (NPS_E_OK); +} + +/* ----------------------------------------------------------------------------------- pkt_drv */ +/* FUNCTION NAME: _hal_tau_pkt_txEnQueueBulk + * PURPOSE: + * To enqueue numbers of packet in the bulk buffer + * INPUT: + * unit -- The unit ID + * channel -- The target channel + * number -- The number of packet to be enqueue + * OUTPUT: + * None + * RETURN: + * None + * NOTES: + * None + */ +static void +_hal_tau_pkt_txEnQueueBulk( + const UI32_T unit, + const UI32_T channel, + const UI32_T number) +{ + HAL_TAU_PKT_TX_PDMA_T *ptr_tx_pdma = HAL_TAU_PKT_GET_TX_PDMA_PTR(unit, channel); + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd = NULL; + UI32_T idx; + + for (idx = 0; idx < number; idx++) + { + ptr_sw_gpd = ptr_tx_pdma->pptr_sw_gpd_bulk[idx]; + ptr_tx_pdma->pptr_sw_gpd_bulk[idx] = NULL; + if (NULL != ptr_sw_gpd->callback) + { + ptr_sw_gpd->callback(unit, ptr_sw_gpd, ptr_sw_gpd->ptr_cookie); + } + } +} + + +/* FUNCTION NAME: _hal_tau_pkt_strictTxDeQueue + * PURPOSE: + * To dequeue the packets based on the strict algorithm. + * INPUT: + * unit -- The unit ID + * ptr_cookie -- Pointer of the TX cookie + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully dequeue the packets. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_strictTxDeQueue( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_TX_COOKIE_T *ptr_cookie) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_TX_CB_T *ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit); + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd = NULL; + NPS_ADDR_T sw_gpd_addr; + UI32_T que_cnt = 0; + + /* get queue count */ + _hal_tau_pkt_getQueueCount(&ptr_tx_cb->sw_queue, &que_cnt); + + /* wait txTask event */ + if (0 == que_cnt) + { + osal_waitEvent(&ptr_tx_cb->sync_sema); + if (FALSE == ptr_tx_cb->running) + { + return (NPS_E_OTHERS); /* deinit */ + } + + ptr_tx_cb->cnt.wait_event++; + + /* re-get queue count */ + _hal_tau_pkt_getQueueCount(&ptr_tx_cb->sw_queue, &que_cnt); + } + + /* deque */ + if (que_cnt > 0) + { + rc = _hal_tau_pkt_deQueue(&ptr_tx_cb->sw_queue, (void **)&ptr_sw_gpd); + if (NPS_E_OK == rc) + { + ptr_tx_cb->cnt.deque_ok++; + + sw_gpd_addr = (NPS_ADDR_T)ptr_sw_gpd->ptr_cookie; + + /* Give the address of pre-saved SW GPD back to userspace */ + osal_io_copyToUser(&ptr_cookie->done_sw_gpd_addr, + &sw_gpd_addr, + sizeof(NPS_ADDR_T)); + + /* free kernel sw_gpd */ + _hal_tau_pkt_freeTxGpdList(unit, ptr_sw_gpd); + } + else + { + ptr_tx_cb->cnt.deque_fail++; + } + } + else + { + /* It may happen at last gpd, return error and do not invoke callback. */ + rc = NPS_E_OTHERS; + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_rxCheckReason + * PURPOSE: + * To check the packets to linux kernel/user. + * INPUT: + * ptr_rx_gpd -- Pointer of the RX GPD + * ptr_hit_prof -- Pointer of the hit flag + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully dispatch the packets. + * NOTES: + * Reference to pkt_srv. + */ +static void +_hal_tau_pkt_rxCheckReason( + volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd, + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile, + BOOL_T *ptr_hit_prof) +{ + HAL_PKT_RX_REASON_BITMAP_T *ptr_reason_bitmap = &ptr_profile->reason_bitmap; + UI32_T bitval = 0; + UI32_T bitmap = 0x0; + + if (0 == (ptr_profile->flags & HAL_TAU_PKT_NETIF_PROFILE_FLAGS_REASON)) + { + /* It means that reason doesn't metters */ + *ptr_hit_prof = TRUE; + return; + } + +#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) + { + case HAL_TAU_PKT_TMH_TYPE_ITMH_ETH: + + /* IPP non-L3 exception */ + if (ptr_rx_gpd->itmh_eth.dst_idx >= HAL_TAU_PKT_DI_NON_L3_CPU_MIN && + 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 = 1UL << (bitval % 32); + if (0 != (ptr_reason_bitmap->ipp_excpt_bitmap[bitval / 32] & bitmap)) + { + *ptr_hit_prof = TRUE; + break; + } + } + + /* IPP L3 exception */ + if (ptr_rx_gpd->itmh_eth.dst_idx >= HAL_TAU_PKT_DI_L3_CPU_MIN && + ptr_rx_gpd->itmh_eth.dst_idx <= HAL_TAU_PKT_DI_L3_CPU_MAX) + { + bitmap = ptr_rx_gpd->itmh_eth.dst_idx - HAL_TAU_PKT_DI_L3_CPU_MIN; + if (0 != (ptr_reason_bitmap->ipp_l3_excpt_bitmap[0] & bitmap)) + { + *ptr_hit_prof = TRUE; + break; + } + } + + /* IPP cp_to_cpu_bmap */ + bitmap = ptr_rx_gpd->itmh_eth.cp_to_cpu_bmap; + if (0 != (ptr_reason_bitmap->ipp_copy2cpu_bitmap[0] & bitmap)) + { + *ptr_hit_prof = TRUE; + break; + } + + /* IPP cp_to_cpu_rsn */ + bitval = ptr_rx_gpd->itmh_eth.cp_to_cpu_code; + bitmap = 1UL << (bitval % 32); + if (0 != (ptr_reason_bitmap->ipp_rsn_bitmap[bitval / 32] & bitmap)) + { + *ptr_hit_prof = TRUE; + break; + } + break; + + case HAL_TAU_PKT_TMH_TYPE_ITMH_FAB: + case HAL_TAU_PKT_TMH_TYPE_ETMH_FAB: + break; + + case HAL_TAU_PKT_TMH_TYPE_ETMH_ETH: + + /* EPP exception */ + if (1 == ptr_rx_gpd->etmh_eth.redir) + { + bitval = ptr_rx_gpd->etmh_eth.excpt_code_mir_bmap; + bitmap = 1UL << (bitval % 32); + if (0 != (ptr_reason_bitmap->epp_excpt_bitmap[bitval / 32] & bitmap)) + { + *ptr_hit_prof = TRUE; + break; + } + } + + /* EPP cp_to_cpu_bmap */ + bitmap = ((ptr_rx_gpd->etmh_eth.cp_to_cpu_bmap_w0 << 7) | + (ptr_rx_gpd->etmh_eth.cp_to_cpu_bmap_w1)); + if (0 != (ptr_reason_bitmap->epp_copy2cpu_bitmap[0] & bitmap)) + { + *ptr_hit_prof = TRUE; + break; + } + break; + + default: + *ptr_hit_prof = FALSE; + break; + } +} + +static BOOL_T +_hal_tau_pkt_comparePatternWithPayload( + volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd, + const UI8_T *ptr_pattern, + const UI8_T *ptr_mask, + const UI32_T offset) +{ + NPS_ADDR_T phy_addr = 0; + UI8_T *ptr_virt_addr = NULL; + UI32_T idx; + + /* Get the packet payload */ + phy_addr = NPS_ADDR_32_TO_64(ptr_rx_gpd->data_buf_addr_hi, ptr_rx_gpd->data_buf_addr_lo); + ptr_virt_addr = (C8_T *) osal_dma_convertPhyToVirt(phy_addr); + + for (idx=0; idxflags & (HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_0 | + HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_1 | + HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_2 | + HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_3)) != 0) + { + /* Need to compare the payload with at least one of the four patterns */ + /* Pre-assume that the result is positive */ + *ptr_hit_prof = TRUE; + + /* If any of the following comparison fails, the result will be changed to negtive */ + } + else + { + return; + } + + for (idx=0; idxflags & (HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PATTERN_0 << idx))) + { + match = _hal_tau_pkt_comparePatternWithPayload(ptr_rx_gpd, + ptr_profile->pattern[idx], + ptr_profile->mask[idx], + ptr_profile->offset[idx]); + if (TRUE == match) + { + /* Do nothing */ + } + else + { + /* Change the result to negtive */ + *ptr_hit_prof = FALSE; + break; + } + } + } +} + +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, + 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, &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, &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; + } + } + + /* Seach the next profile (priority lower) */ + ptr_curr_node = ptr_curr_node->ptr_next_node; + } +} + +static void +_hal_tau_pkt_getPacketDest( + volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd, + HAL_TAU_PKT_DEST_T *ptr_dest, + void **pptr_cookie) +{ + 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, + &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 + { + *ptr_dest = HAL_TAU_PKT_DEST_NETDEV; + } +} + +/* FUNCTION NAME: _hal_tau_pkt_rxEnQueue + * PURPOSE: + * To enqueue the packets to multiple queues. + * INPUT: + * unit -- The unit ID + * channel -- The target channel + * ptr_sw_gpd -- Pointer for the SW Rx GPD link list + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully enqueue the packets. + * NOTES: + * None + */ +static void +_hal_tau_pkt_rxEnQueue( + const UI32_T unit, + const UI32_T channel, + HAL_TAU_PKT_RX_SW_GPD_T *ptr_sw_gpd) +{ + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + 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 dest_type; + + /* skb meta */ + UI32_T port = 0, len = 0, total_len = 0; + struct net_device *ptr_net_dev = NULL; + 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 */ + if (NPS_E_OK == perf_rxTest()) + { + while (NULL != ptr_sw_gpd) + { + len += (HAL_TAU_PKT_CH_LAST_GPD == ptr_sw_gpd->rx_gpd.ch)? + ptr_sw_gpd->rx_gpd.cnsm_buf_len : ptr_sw_gpd->rx_gpd.avbl_buf_len; + + total_len += len; + + /* unmap dma */ + phy_addr = NPS_ADDR_32_TO_64(ptr_sw_gpd->rx_gpd.data_buf_addr_hi, ptr_sw_gpd->rx_gpd.data_buf_addr_lo); + osal_skb_unmapDma(phy_addr, len, DMA_FROM_DEVICE); + /* next */ + ptr_sw_gpd = ptr_sw_gpd->ptr_next; + } + perf_rxCallback(total_len); + _hal_tau_pkt_freeRxGpdList(unit, ptr_sw_first_gpd, TRUE); + return ; + } +#endif + + _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) + { + len = (HAL_TAU_PKT_CH_LAST_GPD == ptr_sw_gpd->rx_gpd.ch)? + ptr_sw_gpd->rx_gpd.cnsm_buf_len : ptr_sw_gpd->rx_gpd.avbl_buf_len; + + total_len += len; + + /* unmap dma */ + phy_addr = NPS_ADDR_32_TO_64(ptr_sw_gpd->rx_gpd.data_buf_addr_hi, ptr_sw_gpd->rx_gpd.data_buf_addr_lo); + ptr_virt_addr = ptr_sw_gpd->ptr_cookie; + + ptr_skb = (struct sk_buff *)ptr_virt_addr; + + /* note here ptr_skb->len is the total buffer size not means the actual Rx packet len + * it should be updated later + */ + osal_skb_unmapDma(phy_addr, ptr_skb->len, DMA_FROM_DEVICE); + + /* reset ptr_skb->len with real packet len instead of total buffer size */ + if (NULL == ptr_sw_gpd->ptr_next) + { + /* strip CRC padded by asic for the last gpd segment */ + ptr_skb->len = len - ETH_FCS_LEN; + } + else + { + ptr_skb->len = len; + } + + skb_set_tail_pointer(ptr_skb, ptr_skb->len); + + /* next */ + 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) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rxch=%u, rcv pkt size=%u > gpd buf size=%u\n", + unit, channel, total_len, ptr_rx_cb->buf_len); + ptr_merge_skb = osal_skb_alloc(total_len - ETH_FCS_LEN); + if (NULL != ptr_merge_skb) + { + copy_offset = 0; + ptr_sw_gpd = ptr_sw_first_gpd; + while (NULL != ptr_sw_gpd) + { + ptr_skb = (struct sk_buff *)ptr_sw_gpd->ptr_cookie; + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rxch=%u, copy size=%u to buf offset=%u\n", + unit, channel, ptr_skb->len, copy_offset); + + memcpy(&(((UI8_T *)ptr_merge_skb->data)[copy_offset]), + ptr_skb->data, ptr_skb->len); + copy_offset += ptr_skb->len; + ptr_sw_gpd = ptr_sw_gpd->ptr_next; + } + /* put the merged skb to ptr_skb for the following process */ + ptr_skb = ptr_merge_skb; + } + else + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_RX), + "u=%u, rxch=%u, alloc skb failed, size=%u\n", + unit, channel, (total_len - ETH_FCS_LEN)); + } + + /* free both sw_gpd and the skb attached on it */ + _hal_tau_pkt_freeRxGpdList(unit, ptr_sw_first_gpd, TRUE); + } + else + { + /* free only sw_gpd */ + _hal_tau_pkt_freeRxGpdList(unit, ptr_sw_first_gpd, FALSE); + } + + /* if NULL netdev, drop the skb */ + if (NULL == ptr_net_dev) + { + ptr_rx_cb->cnt.channel[channel].netdev_miss++; + osal_skb_free(ptr_skb); + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_RX), + "u=%u, rxch=%u, find netdev failed\n", + unit, channel); + return; + } + + /* skb handling */ + ptr_skb->dev = ptr_net_dev; + ptr_skb->pkt_type = PACKET_HOST; /* this packet is for me */ + ptr_skb->ip_summed = CHECKSUM_UNNECESSARY; /* skip checksum */ + + /* send to linux */ + 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; +#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 + } + else if (HAL_TAU_PKT_DEST_SDK == dest_type) + { + while (0 != _hal_tau_pkt_enQueue(&ptr_rx_cb->sw_queue[channel], ptr_sw_gpd)) + { + ptr_rx_cb->cnt.channel[channel].enque_retry++; + HAL_TAU_PKT_RX_ENQUE_RETRY_SLEEP(); + } + ptr_rx_cb->cnt.channel[channel].enque_ok++; + + osal_triggerEvent(&ptr_rx_cb->sync_sema); + ptr_rx_cb->cnt.channel[channel].trig_event++; + } + else if (HAL_TAU_PKT_DEST_DROP == dest_type) + { + _hal_tau_pkt_freeRxGpdList(unit, ptr_sw_first_gpd, TRUE); + } + else + { + 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, 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. + * INPUT: + * unit -- The unit ID + * ptr_cookie -- Pointer of the RX cookie + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully dequeue the packets. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_schedRxDeQueue( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_RX_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_IOCTL_RX_COOKIE_T ioctl_data; + HAL_TAU_PKT_IOCTL_RX_GPD_T ioctl_gpd; + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + HAL_TAU_PKT_RX_SW_GPD_T *ptr_sw_gpd_knl = NULL; + HAL_TAU_PKT_RX_SW_GPD_T *ptr_sw_first_gpd_knl = NULL; + UI32_T que_cnt = 0; + UI32_T queue = 0; + UI32_T idx = 0; + UI32_T gpd_idx = 0; + /* copy Rx sw_gpd */ + volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd = NULL; + void *ptr_virt_addr = NULL; + NPS_ADDR_T phy_addr = 0; + UI32_T buf_len = 0; + NPS_ERROR_NO_T rc = NPS_E_OK; + + /* normal process */ + if (TRUE == ptr_rx_cb->running) + { + /* 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) + { + osal_waitEvent(&ptr_rx_cb->sync_sema); + + ptr_rx_cb->cnt.wait_event++; + + /* re-get queue and count */ + for (queue = 0; queue < HAL_TAU_PKT_RX_QUEUE_NUM; queue++) + { + _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; + } + } + } + + /* 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; + + osal_io_copyFromUser(&ioctl_data, ptr_cookie, sizeof(HAL_TAU_PKT_IOCTL_RX_COOKIE_T)); + + 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++; + } + + /* 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++; + } + } + else + { + /* it means that all queue's are flush -> rx stop flow */ + rc = NPS_E_OTHERS; + } + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_waitTxDone + * PURPOSE: + * To determine the next action after transfer the packet to HW. + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * ptr_sw_gpd -- Pointer for the SW Tx GPD link list + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully perform the target action. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_waitTxDone( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel, + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + 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); + volatile HAL_TAU_PKT_TX_GPD_T *ptr_tx_gpd = NULL; + UI32_T last_gpd_idx = 0; + UI32_T loop_cnt = 0; + + if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode) + { + ; + } + else if (HAL_TAU_PKT_TX_WAIT_SYNC_INTR == ptr_tx_cb->wait_mode) + { + osal_takeSemaphore(&ptr_tx_pdma->sync_intr_sema, HAL_TAU_PKT_PDMA_TX_INTR_TIMEOUT); + /* rc = _hal_tau_pkt_invokeTxGpdCallback(unit, ptr_sw_gpd); */ + } + else if (HAL_TAU_PKT_TX_WAIT_SYNC_POLL == ptr_tx_cb->wait_mode) + { + last_gpd_idx = ptr_tx_pdma->free_idx + ptr_tx_pdma->used_gpd_num; + last_gpd_idx %= ptr_tx_pdma->gpd_num; + ptr_tx_gpd = HAL_TAU_PKT_GET_TX_GPD_PTR(unit, channel, last_gpd_idx); + + while (HAL_TAU_PKT_HWO_HW_OWN == ptr_tx_gpd->hwo) + { + osal_dma_invalidateCache((void *)ptr_tx_gpd, sizeof(HAL_TAU_PKT_TX_GPD_T)); + loop_cnt++; + if (0 == loop_cnt % HAL_TAU_PKT_PDMA_TX_POLL_MAX_LOOP) + { + ptr_tx_cb->cnt.channel[channel].poll_timeout++; + rc = NPS_E_OTHERS; + break; + } + } + if (HAL_TAU_PKT_ECC_ERROR_OCCUR == ptr_tx_gpd->ecce) + { + ptr_tx_cb->cnt.channel[channel].ecc_err++; + } + if (NPS_E_OK == rc) + { + ptr_tx_pdma->free_gpd_num += ptr_tx_pdma->used_gpd_num; + ptr_tx_pdma->used_gpd_num = 0; + ptr_tx_pdma->free_idx = ptr_tx_pdma->used_idx; + /* rc = _hal_tau_pkt_invokeTxGpdCallback(unit, ptr_sw_gpd); */ + } + } + + return (rc); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_resumeAllIntf( + 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) + { + if (netif_queue_stopped(ptr_net_dev)) + { + netif_wake_queue(ptr_net_dev); + } + } + } + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_suspendAllIntf( + 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_stop_queue(ptr_net_dev); + } + } + + 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. + * INPUT: + * unit -- The unit ID + * channel -- The target TX channel + * ptr_sw_gpd -- Pointer for the SW Tx GPD link list + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully perform the transferring. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_sendGpd( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel, + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + 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); + 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); + + if (0 != (ptr_cb->init_flag & HAL_TAU_PKT_INIT_TASK)) + { + osal_takeIsrLock(&ptr_tx_pdma->ring_lock, &irq_flags); + + /* If not PDMA error */ + if (FALSE == ptr_tx_pdma->err_flag) + { + /* Make Sure GPD is enough */ + if (ptr_tx_pdma->free_gpd_num >= used_gpd_num) + { + used_idx = ptr_tx_pdma->used_idx; + while (NULL != ptr_sw_gpd) + { + 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) + { + 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; + } + + /* 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)); + + /* next */ + used_idx++; + used_idx %= ptr_tx_pdma->gpd_num; + ptr_sw_gpd = ptr_sw_gpd->ptr_next; + } + + 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_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_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 + { + rc = NPS_E_TABLE_FULL; + } + } + 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); + rc = NPS_E_OTHERS; + } + + osal_giveIsrLock(&ptr_tx_pdma->ring_lock, &irq_flags); + } + else + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, + "Tx failed, task already deinit\n"); + rc = NPS_E_OTHERS; + } + + return (rc); +} + +/* ----------------------------------------------------------------------------------- pkt_srv */ +/* ----------------------------------------------------------------------------------- Rx Init */ +static NPS_ERROR_NO_T +_hal_tau_pkt_rxStop( + const UI32_T unit) +{ + 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; + + /* Check if Rx is already stopped*/ + if (0 == (ptr_cb->init_flag & HAL_TAU_PKT_INIT_RX_START)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR), + "u=%u, rx stop failed, not started\n", unit); + return (NPS_E_OK); + } + + /* Check if PKT Drv/Task were de-init before stopping Rx */ + /* Currently, we help to stop Rx when deinit Drv/Task, so it shouldn't enter below logic */ + if ((0 == (ptr_cb->init_flag & HAL_TAU_PKT_INIT_TASK)) || + (0 == (ptr_cb->init_flag & HAL_TAU_PKT_INIT_DRV))) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR), + "u=%u, rx stop failed, pkt task & pkt drv not init\n", unit); + return (NPS_E_OK); + } + + /* Deinit Rx PDMA and free buf for Rx GPD */ + for (channel = 0; channel < HAL_TAU_PKT_RX_CHANNEL_LAST; channel++) + { + ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + + osal_takeSemaphore(&ptr_rx_pdma->sema, NPS_SEMAPHORE_WAIT_FOREVER); + _hal_tau_pkt_stopRxChannelReg(unit, channel); + rc = _hal_tau_pkt_deinitRxPdmaRingBuf(unit, channel); + 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); + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rx stop done, init flag=0x%x\n", unit, ptr_cb->init_flag); + + osal_triggerEvent(&ptr_rx_cb->sync_sema); + + return (rc); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_rxStart( + const UI32_T unit) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_RX_CHANNEL_T channel = 0; + 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; + + if (0 != (ptr_cb->init_flag & HAL_TAU_PKT_INIT_RX_START)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR), + "u=%u, rx start failed, already started\n", unit); + return (NPS_E_OK); + } + + /* init Rx PDMA and alloc buf for Rx GPD */ + for (channel = 0; channel < HAL_TAU_PKT_RX_CHANNEL_LAST; channel++) + { + ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + + osal_takeSemaphore(&ptr_rx_pdma->sema, NPS_SEMAPHORE_WAIT_FOREVER); + rc = _hal_tau_pkt_initRxPdmaRingBuf(unit, channel); + if (NPS_E_OK == rc) + { + ptr_rx_pdma->cur_idx = 0; + _hal_tau_pkt_startRxChannelReg(unit, channel, ptr_rx_pdma->gpd_num); + } + osal_giveSemaphore(&ptr_rx_pdma->sema); + } + + /* enable to dequeue rx packets */ + ptr_rx_cb->running = TRUE; + + /* set the flag to record init state */ + ptr_cb->init_flag |= HAL_TAU_PKT_INIT_RX_START; + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rx start done, init flag=0x%x\n", unit, ptr_cb->init_flag); + return (rc); +} + +/* FUNCTION NAME: hal_tau_pkt_setRxKnlConfig + * PURPOSE: + * 1. To stop the Rx channel and deinit the Rx subsystem. + * 2. To init the Rx subsystem and start the Rx channel. + * 3. To restart the Rx subsystem + * INPUT: + * unit -- The unit ID + * ptr_cookie -- Pointer of the RX cookie + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure the RX parameters. + * NPS_E_OTHERS -- Configure the parameter failed. + * NOTES: + * + */ +NPS_ERROR_NO_T +hal_tau_pkt_setRxKnlConfig( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_RX_COOKIE_T *ptr_cookie) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + 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_IOCTL_RX_TYPE_T rx_type = HAL_TAU_PKT_IOCTL_RX_TYPE_LAST; + + osal_io_copyFromUser(&rx_type, &ptr_cookie->rx_type, sizeof(HAL_TAU_PKT_IOCTL_RX_TYPE_T)); + + if (HAL_TAU_PKT_IOCTL_RX_TYPE_DEINIT == rx_type) + { + _hal_tau_pkt_rxStop(unit); + } + if (HAL_TAU_PKT_IOCTL_RX_TYPE_INIT == rx_type) + { + /* To prevent buffer size from being on-the-fly changed */ + if (0 != (ptr_cb->init_flag & HAL_TAU_PKT_INIT_RX_START)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR), + "u=%u, rx stop failed, not started\n", unit); + return (NPS_E_OK); + } + + osal_io_copyFromUser(&ptr_rx_cb->buf_len, &ptr_cookie->buf_len, sizeof(UI32_T)); + _hal_tau_pkt_rxStart(unit); + } + + return (rc); +} + +/* FUNCTION NAME: hal_tau_pkt_getRxKnlConfig + * PURPOSE: + * To get the Rx subsystem configuration. + * INPUT: + * unit -- The unit ID + * ptr_cookie -- Pointer of the RX cookie + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure the RX parameters. + * NPS_E_OTHERS -- Configure the parameter failed. + * NOTES: + * + */ +NPS_ERROR_NO_T +hal_tau_pkt_getRxKnlConfig( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_RX_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + + osal_io_copyToUser(&ptr_cookie->buf_len, &ptr_rx_cb->buf_len, sizeof(UI32_T)); + + return (NPS_E_OK); +} + +/* ----------------------------------------------------------------------------------- Deinit */ +/* FUNCTION NAME: hal_tau_pkt_deinitTask + * PURPOSE: + * To de-initialize the Task for packet module. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully dinitialize the control block. + * NPS_E_OTHERS -- Initialize the control block failed. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_deinitTask( + const UI32_T unit) +{ + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + HAL_TAU_PKT_TX_CB_T *ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit); + 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), + "u=%u, rx stop failed, not started\n", unit); + return (NPS_E_OK); + } + + /* Need to stop Rx before de-init Task */ + if (0 != (ptr_cb->init_flag & HAL_TAU_PKT_INIT_RX_START)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR), + "u=%u, pkt task deinit failed, rx not stop\n", unit); + + _hal_tau_pkt_rxStop(unit); + } + + /* Make the Rx IOCTL from userspace return back*/ + osal_triggerEvent(&ptr_rx_cb->sync_sema); + + /* Destroy txTask */ + if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode) + { + ptr_tx_cb->running = FALSE; + osal_triggerEvent(&ptr_tx_cb->sync_sema); + } + + /* Destroy handleRxDoneTask */ + for (channel = 0; channel < HAL_TAU_PKT_RX_CHANNEL_LAST; channel++) + { + osal_stopThread(&ptr_rx_cb->isr_task_id[channel]); + osal_triggerEvent(HAL_TAU_PKT_RCH_EVENT(unit, channel)); + osal_destroyThread(&ptr_rx_cb->isr_task_id[channel]); + } + + /* Destroy handleTxDoneTask */ + for (channel = 0; channel < HAL_TAU_PKT_TX_CHANNEL_LAST; channel++) + { + osal_stopThread(&ptr_tx_cb->isr_task_id[channel]); + osal_triggerEvent(HAL_TAU_PKT_TCH_EVENT(unit, channel)); + osal_destroyThread(&ptr_tx_cb->isr_task_id[channel]); + } + + /* Destroy handleErrorTask */ + osal_stopThread(&ptr_cb->err_task_id); + osal_triggerEvent(HAL_TAU_PKT_ERR_EVENT(unit)); + osal_destroyThread(&ptr_cb->err_task_id); + + /* Set the flag to record init state */ + ptr_cb->init_flag &= (~HAL_TAU_PKT_INIT_TASK); + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, pkt task deinit done, init flag=0x%x\n", + unit, ptr_cb->init_flag); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_deinitTxPdma + * PURPOSE: + * To de-initialize the Tx PDMA configuration of the specified channel. + * INPUT: + * unit -- The unit ID + * channel -- The target Tx channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully de-init the Tx PDMA. + * NPS_E_OTHERS -- De-init the Tx PDMA failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_deinitTxPdma( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel) +{ + 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); + + _hal_tau_pkt_stopTxChannelReg(unit, channel); + + /* Free DMA and flush queue */ + osal_dma_free(ptr_tx_pdma->ptr_gpd_start_addr); + + if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode) + { + osal_free(ptr_tx_pdma->pptr_sw_gpd_ring); + osal_free(ptr_tx_pdma->pptr_sw_gpd_bulk); + } + else if (HAL_TAU_PKT_TX_WAIT_SYNC_INTR == ptr_tx_cb->wait_mode) + { + osal_destroySemaphore(&ptr_tx_pdma->sync_intr_sema); + } + + osal_destroyIsrLock(&ptr_tx_pdma->ring_lock); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_deinitRxPdma + * PURPOSE: + * To de-initialize the Rx PDMA configuration of the specified channel. + * INPUT: + * unit -- The unit ID + * channel -- The target Rx channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully de-init the Rx PDMA. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_deinitRxPdma( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + + /* Free DMA */ + osal_takeSemaphore(&ptr_rx_pdma->sema, NPS_SEMAPHORE_WAIT_FOREVER); + osal_dma_free(ptr_rx_pdma->ptr_gpd_start_addr); + osal_giveSemaphore(&ptr_rx_pdma->sema); + osal_destroySemaphore(&ptr_rx_pdma->sema); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_deinitPktCb + * PURPOSE: + * To de-init the control block of Drv. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully de-init the control block. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_deinitPktCb( + const UI32_T unit) +{ + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + UI32_T idx = 0, vec = sizeof(_hal_tau_pkt_intr_vec) / sizeof(HAL_TAU_PKT_INTR_VEC_T); + + for (idx = 0; idx < vec; idx++) + { + osal_destroyEvent(&_hal_tau_pkt_intr_vec[idx].intr_event); + ptr_cb->intr_bitmap &= ~(_hal_tau_pkt_intr_vec[idx].intr_reg); + } + + /* Unregister PKT interrupt functions */ + osal_mdc_registerIsr(unit, NULL, NULL); + osal_destroyIsrLock(&ptr_cb->intr_lock); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_deinitPktTxCb + * PURPOSE: + * To de-init the control block of Tx PDMA. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully de-init the control block. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_deinitPktTxCb( + const UI32_T unit) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_TX_CB_T *ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit); + HAL_TAU_PKT_TX_CHANNEL_T channel = 0; + + /* Deinitialize TX PDMA sub-system.*/ + for (channel = 0; channel < HAL_TAU_PKT_TX_CHANNEL_LAST; channel++) + { + _hal_tau_pkt_deinitTxPdma(unit, channel); + } + + if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode) + { + /* Destroy the sync semaphore of txTask */ + osal_destroyEvent(&ptr_tx_cb->sync_sema); + + /* Deinitialize Tx GPD-queue (of first SW-GPD) from handleTxDoneTask to txTask */ + osal_destroySemaphore(&ptr_tx_cb->sw_queue.sema); + osal_que_destroy(&ptr_tx_cb->sw_queue.que_id); + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_deinitPktRxCb + * PURPOSE: + * To de-init the control block of Rx PDMA. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully de-init the control block. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_deinitPktRxCb( + const UI32_T unit) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + HAL_TAU_PKT_RX_CHANNEL_T channel = 0; + UI32_T queue = 0; + + /* Deinitialize RX PDMA sub-system */ + for (channel = 0; channel < HAL_TAU_PKT_RX_CHANNEL_LAST; channel++) + { + _hal_tau_pkt_deinitRxPdma(unit, channel); + } + + /* Destroy the sync semaphore of rxTask */ + osal_destroyEvent(&ptr_rx_cb->sync_sema); + + /* Deinitialize Rx GPD-queue (of first SW-GPD) from handleRxDoneTask to rxTask */ + for (queue = 0; queue < HAL_TAU_PKT_RX_QUEUE_NUM; queue++) + { + osal_destroySemaphore(&ptr_rx_cb->sw_queue[queue].sema); + osal_que_destroy(&ptr_rx_cb->sw_queue[queue].que_id); + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_deinitL1Isr + * PURPOSE: + * To de-initialize the PDMA L1 ISR configuration. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully de-initialize for the L1 ISR. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_deinitL1Isr( + const UI32_T unit) +{ + UI32_T idx = 0, vec = sizeof(_hal_tau_pkt_intr_vec) / sizeof(HAL_TAU_PKT_INTR_VEC_T); + + for (idx = 0; idx < vec; idx++) + { + _hal_tau_pkt_maskIntr(unit, _hal_tau_pkt_intr_vec[idx].intr_reg); + _hal_tau_pkt_disableIntr(unit, _hal_tau_pkt_intr_vec[idx].intr_reg); + } + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_deinitL2Isr + * PURPOSE: + * To initialize the PDMA L2 ISR configuration. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure for the L2 ISR. + * NPS_E_OTHERS -- Configure failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_deinitL2Isr( + const UI32_T unit) +{ + HAL_TAU_PKT_L2_ISR_T isr_status = 0x0; + + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RCH0); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RCH1); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RCH2); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RCH3); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_TCH0); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_TCH1); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_TCH2); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_TCH3); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RX_QID_MAP_ERR); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RX_FRAME_ERR); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_ERR_INT_MASK_SET), + &isr_status, sizeof(UI32_T)); + + isr_status = 0x0; + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_ERR_INT_EN), + &isr_status, sizeof(UI32_T)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: hal_tau_pkt_deinitPktDrv + * PURPOSE: + * To invoke the functions to de-initialize the control block for each + * PDMA subsystem. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully de-initialize the control blocks. + * NPS_E_OTHERS -- De-initialize the control blocks failed. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_deinitPktDrv( + const UI32_T unit) +{ + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + NPS_ERROR_NO_T rc = NPS_E_OK; + + if (0 == (ptr_cb->init_flag & HAL_TAU_PKT_INIT_DRV)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR), + "u=%u, pkt drv deinit failed, not inited\n", unit); + return (NPS_E_OK); + } + + rc = _hal_tau_pkt_deinitL2Isr(unit); + + if (NPS_E_OK == rc) + { + rc = _hal_tau_pkt_deinitL1Isr(unit); + } + if (NPS_E_OK == rc) + { + rc = _hal_tau_pkt_deinitPktRxCb(unit); + } + if (NPS_E_OK == rc) + { + rc = _hal_tau_pkt_deinitPktTxCb(unit); + } + if (NPS_E_OK == rc) + { + rc = _hal_tau_pkt_deinitPktCb(unit); + } + + ptr_cb->init_flag &= (~HAL_TAU_PKT_INIT_DRV); + + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, + "u=%u, pkt drv deinit done, init flag=0x%x\n", + unit, ptr_cb->init_flag); + return (rc); +} + +/* ----------------------------------------------------------------------------------- Init */ +/* FUNCTION NAME: _hal_tau_pkt_handleTxErrStat + * PURPOSE: + * To handle the TX flow control ISR. + * INPUT: + * unit -- The unit ID + * channel -- The target channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully handle the interrpt. + * NOTES: + * + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_handleTxErrStat( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel) +{ + 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; + + if (HAL_TAU_PKT_TX_WAIT_SYNC_INTR == ptr_tx_cb->wait_mode) + { + /* Notify the TX process to make it release the channel semaphore. */ + osal_giveSemaphore(&ptr_tx_pdma->sync_intr_sema); + } + + /* Set the error flag. */ + + osal_takeIsrLock(&ptr_tx_pdma->ring_lock, &irg_flags); + ptr_tx_pdma->err_flag = TRUE; + osal_giveIsrLock(&ptr_tx_pdma->ring_lock, &irg_flags); + + osal_triggerEvent(HAL_TAU_PKT_TCH_EVENT(unit, channel)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_handleRxErrStat + * PURPOSE: + * To handle the error which occurs in RX channels. + * INPUT: + * unit -- The unit ID + * channel -- The channel where the error occurs + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully handle the error situation. + * NOTES: + * + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_handleRxErrStat( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + + /* Set the error flag. */ + osal_takeSemaphore(&ptr_rx_pdma->sema, NPS_SEMAPHORE_WAIT_FOREVER); + ptr_rx_pdma->err_flag = TRUE; + osal_giveSemaphore(&ptr_rx_pdma->sema); + + osal_triggerEvent(HAL_TAU_PKT_RCH_EVENT(unit, channel)); + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_handleTxL2Isr + * PURPOSE: + * To handle the TX L2 interrupt according to the ISR status. + * INPUT: + * unit -- The unit ID + * channel -- The channel where the interrupt occurs + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully handle the L2 interrupt. + * NOTES: + * + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_handleTxL2Isr( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel) +{ + HAL_TAU_PKT_TX_CHANNEL_L2_ISR_T isr_status = 0x0; + HAL_TAU_PKT_TX_CB_T *ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit); + + osal_mdc_readPciReg(unit, + HAL_TAU_PKT_GET_PDMA_TCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_TCH_INT_STAT), channel), + &isr_status, sizeof(isr_status)); + + _hal_tau_pkt_maskAllTxL2IsrReg(unit, channel); + + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_HWO_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma gpd hwo err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_HWO_ERROR); + ptr_tx_cb->cnt.channel[channel].gpd_hwo_err++; + _hal_tau_pkt_handleTxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma gpd chksum err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR); + ptr_tx_cb->cnt.channel[channel].gpd_chksm_err++; + _hal_tau_pkt_handleTxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_NO_OVFL_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma gpd num overflow err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_NO_OVFL_ERROR); + ptr_tx_cb->cnt.channel[channel].gpd_no_ovfl_err++; + _hal_tau_pkt_handleTxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_DMA_READ_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma gpd dma read err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_DMA_READ_ERROR); + ptr_tx_cb->cnt.channel[channel].gpd_dma_read_err++; + _hal_tau_pkt_handleTxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_BUF_SIZE_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma buf size err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_BUF_SIZE_ERROR); + ptr_tx_cb->cnt.channel[channel].buf_size_err++; + _hal_tau_pkt_handleTxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_RUNT_ERROR)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_TX, + "u=%u, txch=%u, pdma pkt runt\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_RUNT_ERROR); + ptr_tx_cb->cnt.channel[channel].runt_err++; + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_OVSZ_ERROR)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_TX, + "u=%u, txch=%u, pdma pkt over size\n", unit, channel);; + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_OVSZ_ERROR); + ptr_tx_cb->cnt.channel[channel].ovsz_err++; + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_LEN_MISMATCH_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma len mismatch err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_LEN_MISMATCH_ERROR); + ptr_tx_cb->cnt.channel[channel].len_mismatch_err++; + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PKTPL_DMA_READ_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma pkt buf dma read err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PKTPL_DMA_READ_ERROR); + ptr_tx_cb->cnt.channel[channel].pktpl_dma_read_err++; + _hal_tau_pkt_handleTxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_COS_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma tx cos err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_COS_ERROR); + ptr_tx_cb->cnt.channel[channel].cos_err++; + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_GT255_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma gpd num > 255 err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_GPD_GT255_ERROR); + ptr_tx_cb->cnt.channel[channel].gpd_gt255_err++; + _hal_tau_pkt_handleTxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PFC)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_TX, + "u=%u, txch=%u, pdma flow ctrl\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_PFC); + ptr_tx_cb->cnt.channel[channel].pfc++; + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_CREDIT_UDFL_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma credit underflow err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_CREDIT_UDFL_ERROR); + ptr_tx_cb->cnt.channel[channel].credit_udfl_err++; + _hal_tau_pkt_handleTxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_DMA_WRITE_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_TX), + "u=%u, txch=%u, pdma dma write err\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_DMA_WRITE_ERROR); + ptr_tx_cb->cnt.channel[channel].dma_write_err++; + _hal_tau_pkt_handleTxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_TX_CHANNEL_L2_ISR_STOP_CMD_CPLT)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_TX, + "u=%u, txch=%u, pdma stop done\n", unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_TX_CHANNEL_L2_ISR_STOP_CMD_CPLT); + ptr_tx_cb->cnt.channel[channel].sw_issue_stop++; + } + if (0 != isr_status) + { + _hal_tau_pkt_unmaskAllTxL2IsrReg(unit, channel); + } + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_handleRxL2Isr + * PURPOSE: + * To handle the RX L2 interrupt according to the ISR status. + * INPUT: + * unit -- The unit ID + * channel -- The channel where the interrupt occurs + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully handle the L2 interrupt. + * NOTES: + * + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_handleRxL2Isr( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + HAL_TAU_PKT_RX_CHANNEL_L2_ISR_T isr_status = 0x0; + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + + osal_mdc_readPciReg(unit, + HAL_TAU_PKT_GET_PDMA_RCH_REG(HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_RCH_INT_STAT), channel), + &isr_status, sizeof(isr_status)); + + _hal_tau_pkt_maskAllRxL2IsrReg(unit, channel); + + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_LOW)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rxch=%u, pdma avbl gpd low\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_LOW); + ptr_rx_cb->cnt.channel[channel].avbl_gpd_low++; + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_EMPTY)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rxch=%u, pdma avbl gpd empty\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_EMPTY); + ptr_rx_cb->cnt.channel[channel].avbl_gpd_empty++; + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_RX), + "u=%u, rxch=%u, pdma avbl gpd err\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_AVAIL_GPD_ERROR); + ptr_rx_cb->cnt.channel[channel].avbl_gpd_err++; + _hal_tau_pkt_handleRxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_RX), + "u=%u, rxch=%u, pdma gpd chksum err\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_CHKSM_ERROR); + ptr_rx_cb->cnt.channel[channel].gpd_chksm_err++; + _hal_tau_pkt_handleRxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_READ_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_RX), + "u=%u, rxch=%u, pdma dma read err\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_READ_ERROR); + ptr_rx_cb->cnt.channel[channel].dma_read_err++; + _hal_tau_pkt_handleRxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_WRITE_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_RX), + "u=%u, rxch=%u, pdma dma write err\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_DMA_WRITE_ERROR); + ptr_rx_cb->cnt.channel[channel].dma_write_err++; + _hal_tau_pkt_handleRxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_STOP_CMD_CPLT)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rxch=%u, pdma stop done\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_STOP_CMD_CPLT); + ptr_rx_cb->cnt.channel[channel].sw_issue_stop++; + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_GT255_ERROR)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_RX), + "u=%u, rxch=%u, pdma gpd num > 255 err\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_GPD_GT255_ERROR); + ptr_rx_cb->cnt.channel[channel].gpd_gt255_err++; + _hal_tau_pkt_handleRxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_TOD_UNINIT)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_RX), + "u=%u, rxch=%u, pdma tod ununit err\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_TOD_UNINIT); + ptr_rx_cb->cnt.channel[channel].tod_uninit++; + _hal_tau_pkt_handleRxErrStat(unit, channel); + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_PKT_ERROR_DROP)) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_RX), + "u=%u, rxch=%u, pdma pkt err drop\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_PKT_ERROR_DROP); + ptr_rx_cb->cnt.channel[channel].pkt_err_drop++; + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_UDSZ_DROP)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rxch=%u, pdma pkt under size\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_UDSZ_DROP); + ptr_rx_cb->cnt.channel[channel].udsz_drop++; + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_OVSZ_DROP)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rxch=%u, pdma pkt over size\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_OVSZ_DROP); + ptr_rx_cb->cnt.channel[channel].ovsz_drop++; + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_CMDQ_OVF_DROP)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rxch=%u, pdma cmdq overflow\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_CMDQ_OVF_DROP); + ptr_rx_cb->cnt.channel[channel].cmdq_ovf_drop++; + } + if (0 != (isr_status & HAL_TAU_PKT_RX_CHANNEL_L2_ISR_FIFO_OVF_DROP)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rxch=%u, pdma fifo overflow\n", unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, HAL_TAU_PKT_RX_CHANNEL_L2_ISR_FIFO_OVF_DROP); + ptr_rx_cb->cnt.channel[channel].fifo_ovf_drop++; + } + if (0 != isr_status) + { + _hal_tau_pkt_unmaskAllRxL2IsrReg(unit, channel); + } + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_handleErrorTask + * PURPOSE: + * To invoke the corresponding handler for the L2 interrupts. + * INPUT: + * ptr_argv -- The unit ID + * OUTPUT: + * None + * RETURN: + * None + * NOTES: + * None + */ +static void +_hal_tau_pkt_handleErrorTask( + void *ptr_argv) +{ + UI32_T unit = (UI32_T)((NPS_HUGE_T)ptr_argv); + HAL_TAU_PKT_L2_ISR_T isr_status = 0x0; + + osal_initRunThread(); + do + { + /* receive Error-ISR */ + osal_waitEvent(HAL_TAU_PKT_ERR_EVENT(unit)); + if (NPS_E_OK != osal_isRunThread()) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, + "u=%u, err task destroyed\n", unit); + break; /* deinit-thread */ + } + + osal_mdc_readPciReg(unit, + HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_ERR_INT_STAT), + &isr_status, sizeof(UI32_T)); + + if (0 != (HAL_TAU_PKT_L2_ISR_RCH0 & isr_status)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, rxch=0, rcv err isr, status=0x%x\n", + unit, isr_status); + _hal_tau_pkt_handleRxL2Isr(unit, HAL_TAU_PKT_RX_CHANNEL_0); + } + if (0 != (HAL_TAU_PKT_L2_ISR_RCH1 & isr_status)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, rxch=1, rcv err isr, status=0x%x\n", + unit, isr_status); + _hal_tau_pkt_handleRxL2Isr(unit, HAL_TAU_PKT_RX_CHANNEL_1); + } + if (0 != (HAL_TAU_PKT_L2_ISR_RCH2 & isr_status)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, rxch=2, rcv err isr, status=0x%x\n", + unit, isr_status); + _hal_tau_pkt_handleRxL2Isr(unit, HAL_TAU_PKT_RX_CHANNEL_2); + } + if (0 != (HAL_TAU_PKT_L2_ISR_RCH3 & isr_status)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, rxch=3, rcv err isr, status=0x%x\n", + unit, isr_status); + _hal_tau_pkt_handleRxL2Isr(unit, HAL_TAU_PKT_RX_CHANNEL_3); + } + if (0 != (HAL_TAU_PKT_L2_ISR_TCH0 & isr_status)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, txch=0, rcv err isr, status=0x%x\n", + unit, isr_status); + _hal_tau_pkt_handleTxL2Isr(unit, HAL_TAU_PKT_TX_CHANNEL_0); + } + if (0 != (HAL_TAU_PKT_L2_ISR_TCH1 & isr_status)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, txch=1, rcv err isr, status=0x%x\n", + unit, isr_status); + _hal_tau_pkt_handleTxL2Isr(unit, HAL_TAU_PKT_TX_CHANNEL_1); + } + if (0 != (HAL_TAU_PKT_L2_ISR_TCH2 & isr_status)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, txch=2, rcv err isr, status=0x%x\n", + unit, isr_status); + _hal_tau_pkt_handleTxL2Isr(unit, HAL_TAU_PKT_TX_CHANNEL_2); + } + if (0 != (HAL_TAU_PKT_L2_ISR_TCH3 & isr_status)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, txch=3, rcv err isr, status=0x%x\n", + unit, isr_status); + _hal_tau_pkt_handleTxL2Isr(unit, HAL_TAU_PKT_TX_CHANNEL_3); + } + if (0 != (HAL_TAU_PKT_L2_ISR_RX_QID_MAP_ERR & isr_status)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, rcv rx qid map err isr, status=0x%x\n", + unit, isr_status); + } + if (0 != (HAL_TAU_PKT_L2_ISR_RX_FRAME_ERR & isr_status)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, rcv rx frame err isr, status=0x%x\n", + unit, isr_status); + } + if (0 != isr_status) + { + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_ERR_INT_CLR), + &isr_status, sizeof(UI32_T)); + + _hal_tau_pkt_unmaskIntr(unit, HAL_TAU_PKT_ERR_REG(unit)); + } + + } while (NPS_E_OK == osal_isRunThread()); + osal_exitRunThread(); +} + +/* FUNCTION NAME: _hal_tau_pkt_handleTxDoneTask + * PURPOSE: + * To handle the TX done interrupt for the specified TX channel. + * INPUT: + * ptr_argv -- The unit ID and channel ID + * OUTPUT: + * None + * RETURN: + * None + * NOTES: + * None + */ +static void +_hal_tau_pkt_handleTxDoneTask( + void *ptr_argv) +{ + /* cookie or index */ + UI32_T unit = ((HAL_TAU_PKT_ISR_COOKIE_T *)ptr_argv)->unit; + HAL_TAU_PKT_TX_CHANNEL_T channel = (HAL_TAU_PKT_TX_CHANNEL_T) + ((HAL_TAU_PKT_ISR_COOKIE_T *)ptr_argv)->channel; + /* control block */ + 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); + volatile HAL_TAU_PKT_TX_GPD_T *ptr_tx_gpd = NULL; + UI32_T first_gpd_idx = 0; /* To record the first GPD */ + UI32_T loop_cnt = 0; + NPS_IRQ_FLAGS_T irg_flags; + unsigned long timeout = 0; + UI32_T bulk_pkt_cnt = 0, idx; + + osal_initRunThread(); + do + { + /* receive Tx-Done-ISR */ + osal_waitEvent(HAL_TAU_PKT_TCH_EVENT(unit, channel)); + if (NPS_E_OK != osal_isRunThread()) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_TX, + "u=%u, txch=%u, tx done task destroyed\n", unit, channel); + break; /* deinit-thread */ + } + + /* protect Tx PDMA + * for sync-intr, the sema is locked by sendGpd + */ + if (HAL_TAU_PKT_TX_WAIT_SYNC_INTR != ptr_tx_cb->wait_mode) + { + osal_takeIsrLock(&ptr_tx_pdma->ring_lock, &irg_flags); + } + + loop_cnt = ptr_tx_pdma->used_gpd_num; + while (loop_cnt > 0) + { + ptr_tx_gpd = HAL_TAU_PKT_GET_TX_GPD_PTR(unit, channel, ptr_tx_pdma->free_idx); + osal_dma_invalidateCache((void *)ptr_tx_gpd, sizeof(HAL_TAU_PKT_TX_GPD_T)); + + /* If hwo=HW, it might be: + * 1. err_flag=TRUE -> HW breakdown -> enque and recover -> break + * 2. err_flag=FALSE -> HW busy -> break + */ + if (HAL_TAU_PKT_HWO_HW_OWN == ptr_tx_gpd->hwo) + { + if (TRUE == ptr_tx_pdma->err_flag) + { + /* flush the incomplete Tx packet */ + if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode) + { + for (idx = 0; idx < ptr_tx_pdma->gpd_num; idx++) + { + if (NULL != ptr_tx_pdma->pptr_sw_gpd_ring[idx]) + { + ptr_tx_pdma->pptr_sw_gpd_bulk[bulk_pkt_cnt] + = ptr_tx_pdma->pptr_sw_gpd_ring[idx]; + ptr_tx_pdma->pptr_sw_gpd_ring[idx] = NULL; + bulk_pkt_cnt++; + } + } + } + + /* do error recover */ + first_gpd_idx = 0; + if (NPS_E_OK == _hal_tau_pkt_recoverTxPdma(unit, channel)) + { + ptr_tx_pdma->err_flag = FALSE; + ptr_tx_cb->cnt.channel[channel].err_recover++; + } + else + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_TX | HAL_TAU_PKT_DBG_ERR), + "u=%u, txch=%u, err recover failed\n", + unit, channel); + } + } + else + { + } + break; + } + + if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode) + { + /* If hwo=SW and ch=0, record the head of sw gpd in bulk buf */ + if (HAL_TAU_PKT_CH_LAST_GPD == ptr_tx_gpd->ch) + { + ptr_tx_pdma->pptr_sw_gpd_bulk[bulk_pkt_cnt] + = ptr_tx_pdma->pptr_sw_gpd_ring[first_gpd_idx]; + + bulk_pkt_cnt++; + ptr_tx_pdma->pptr_sw_gpd_ring[first_gpd_idx] = NULL; + + /* next SW-GPD must be the head of another PKT->SW-GPD */ + first_gpd_idx = ptr_tx_pdma->free_idx + 1; + first_gpd_idx %= ptr_tx_pdma->gpd_num; + } + } + + if (HAL_TAU_PKT_ECC_ERROR_OCCUR == ptr_tx_gpd->ecce) + { + ptr_tx_cb->cnt.channel[channel].ecc_err++; + } + + /* update Tx PDMA */ + ptr_tx_pdma->free_idx++; + ptr_tx_pdma->free_idx %= ptr_tx_pdma->gpd_num; + ptr_tx_pdma->used_gpd_num--; + ptr_tx_pdma->free_gpd_num++; + loop_cnt--; + } + + /* let the netdev resume Tx */ + _hal_tau_pkt_resumeAllIntf(unit); + + /* update ISR and counter */ + ptr_tx_cb->cnt.channel[channel].tx_done++; + + _hal_tau_pkt_unmaskIntr(unit, HAL_TAU_PKT_TCH_REG(unit, channel)); + + if (HAL_TAU_PKT_TX_WAIT_SYNC_INTR != ptr_tx_cb->wait_mode) + { + osal_giveIsrLock(&ptr_tx_pdma->ring_lock, &irg_flags); + } + else + { + osal_giveSemaphore(&ptr_tx_pdma->sync_intr_sema); + } + + /* enque packet after releasing the spinlock */ + _hal_tau_pkt_txEnQueueBulk(unit, channel, bulk_pkt_cnt); + bulk_pkt_cnt = 0; + + /* prevent this task from executing too long */ + if (!(time_before(jiffies, timeout))) + { + schedule(); + timeout = jiffies + 1; /* continuously free tx descriptor for 1 tick */ + } + + } while (NPS_E_OK == osal_isRunThread()); + osal_exitRunThread(); +} + +/* FUNCTION NAME: _hal_tau_pkt_handleRxDoneTask + * PURPOSE: + * To handle the RX done interrupt for the specified RX channel. + * INPUT: + * ptr_argv -- The unit ID and channel ID + * OUTPUT: + * None + * RETURN: + * None + * NOTES: + * None + */ +static void +_hal_tau_pkt_handleRxDoneTask( + void *ptr_argv) +{ + /* cookie or index */ + UI32_T unit = ((HAL_TAU_PKT_ISR_COOKIE_T *)ptr_argv)->unit; + HAL_TAU_PKT_RX_CHANNEL_T channel = (HAL_TAU_PKT_RX_CHANNEL_T) + ((HAL_TAU_PKT_ISR_COOKIE_T *)ptr_argv)->channel; + + /* control block */ + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + volatile HAL_TAU_PKT_RX_GPD_T *ptr_rx_gpd = NULL; + + BOOL_T first = TRUE; + BOOL_T last = FALSE; + HAL_TAU_PKT_RX_SW_GPD_T *ptr_sw_gpd = NULL; + HAL_TAU_PKT_RX_SW_GPD_T *ptr_sw_first_gpd = NULL; + UI32_T loop_cnt = 0; + unsigned long timeout = 0; + + osal_initRunThread(); + do + { + /* receive Rx-Done-ISR */ + osal_waitEvent(HAL_TAU_PKT_RCH_EVENT(unit, channel)); + if (NPS_E_OK != osal_isRunThread()) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_RX, + "u=%u, rxch=%u, rx done task destroyed\n", unit, channel); + break; /* deinit-thread */ + } + + /* check if Rx-system is inited */ + if (0 == ptr_rx_cb->buf_len) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR), + "u=%u, rxch=%u, rx gpd buf len=0\n", + unit, channel); + continue; + } + + /* protect Rx PDMA */ + osal_takeSemaphore(&ptr_rx_pdma->sema, NPS_SEMAPHORE_WAIT_FOREVER); + loop_cnt = ptr_rx_pdma->gpd_num; + while (loop_cnt > 0) + { + ptr_rx_gpd = HAL_TAU_PKT_GET_RX_GPD_PTR(unit, channel, ptr_rx_pdma->cur_idx); + osal_dma_invalidateCache((void *)ptr_rx_gpd, sizeof(HAL_TAU_PKT_RX_GPD_T)); + + /* If hwo=HW, it might be: + * 1. err_flag=TRUE -> HW breakdown -> enque and recover -> break + * 2. err_flag=FALSE -> HW busy -> break + */ + if (HAL_TAU_PKT_HWO_HW_OWN == ptr_rx_gpd->hwo) + { + if (TRUE == ptr_rx_pdma->err_flag) + { + /* free the last incomplete Rx packet */ + if ((NULL != ptr_sw_first_gpd) && + (NULL != ptr_sw_gpd)) + { + 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 */ + first = TRUE; + last = FALSE; + if (NPS_E_OK == _hal_tau_pkt_recoverRxPdma(unit, channel)) + { + ptr_rx_pdma->err_flag = FALSE; + ptr_rx_cb->cnt.channel[channel].err_recover++; + } + else + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_RX | HAL_TAU_PKT_DBG_ERR), + "u=%u, rxch=%u, err recover failed\n", + unit, channel); + } + } + else + { + } + break; + } + + /* Move HW-GPD to SW-GPD and append to a link-list */ + if (TRUE == first) + { + ptr_sw_first_gpd = (HAL_TAU_PKT_RX_SW_GPD_T *)osal_alloc(sizeof(HAL_TAU_PKT_RX_SW_GPD_T)); + ptr_sw_gpd = ptr_sw_first_gpd; + if (NULL != ptr_sw_gpd) + { + memcpy(&ptr_sw_gpd->rx_gpd, (void *)ptr_rx_gpd, sizeof(HAL_TAU_PKT_RX_GPD_T)); + first = FALSE; + } + else + { + 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=%zu\n", + unit, channel, sizeof(HAL_TAU_PKT_RX_SW_GPD_T)); + break; + } + } + else + { + ptr_sw_gpd->ptr_next = (HAL_TAU_PKT_RX_SW_GPD_T *)osal_alloc(sizeof(HAL_TAU_PKT_RX_SW_GPD_T)); + ptr_sw_gpd = ptr_sw_gpd->ptr_next; + if (NULL != ptr_sw_gpd) + { + memcpy(&ptr_sw_gpd->rx_gpd, (void *)ptr_rx_gpd, sizeof(HAL_TAU_PKT_RX_GPD_T)); + } + else + { + 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=%zu\n", + unit, channel, sizeof(HAL_TAU_PKT_RX_SW_GPD_T)); + break; + } + } + + ptr_sw_gpd->ptr_cookie = ptr_rx_pdma->pptr_skb_ring[ptr_rx_pdma->cur_idx]; + + /* If hwo=SW and ch=0, enque SW-GPD and signal rxTask */ + if (HAL_TAU_PKT_CH_LAST_GPD == ptr_rx_gpd->ch) + { + last = TRUE; + } + + /* If hwo=SW and ch=*, re-alloc-buf and resume */ + while (NPS_E_OK != _hal_tau_pkt_allocRxPayloadBuf(unit, channel, ptr_rx_pdma->cur_idx)) + { + ptr_rx_cb->cnt.no_memory++; + HAL_TAU_PKT_ALLOC_MEM_RETRY_SLEEP(); + } + ptr_rx_gpd->ioc = HAL_TAU_PKT_IOC_HAS_INTR; + ptr_rx_gpd->hwo = HAL_TAU_PKT_HWO_HW_OWN; + osal_dma_flushCache((void *)ptr_rx_gpd, sizeof(HAL_TAU_PKT_RX_GPD_T)); + + /* Enque the SW-GPD to rxTask */ + if (TRUE == last) + { + 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; + last = FALSE; + } + + _hal_tau_pkt_resumeRxChannelReg(unit, channel, 1); + + /* update Rx PDMA */ + ptr_rx_pdma->cur_idx++; + ptr_rx_pdma->cur_idx %= ptr_rx_pdma->gpd_num; + loop_cnt--; + } + + osal_giveSemaphore(&ptr_rx_pdma->sema); + + /* update ISR and counter */ + ptr_rx_cb->cnt.channel[channel].rx_done++; + + _hal_tau_pkt_unmaskIntr(unit, HAL_TAU_PKT_RCH_REG(unit, channel)); + + /* prevent this task from executing too long */ + if (!(time_before(jiffies, timeout))) + { + schedule(); + timeout = jiffies + 1; /* continuously rx for 1 tick */ + } + + } while (NPS_E_OK == osal_isRunThread()); + osal_exitRunThread(); +} + +static void +_hal_tau_pkt_net_dev_tx_callback( + const UI32_T unit, + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd, + struct sk_buff *ptr_skb) +{ + NPS_ADDR_T phy_addr = 0; + + /* unmap dma */ + phy_addr = NPS_ADDR_32_TO_64(ptr_sw_gpd->tx_gpd.data_buf_addr_hi, ptr_sw_gpd->tx_gpd.data_buf_addr_lo); + osal_skb_unmapDma(phy_addr, ptr_skb->len, DMA_TO_DEVICE); + + /* free skb */ + osal_skb_free(ptr_skb); + + /* free gpd */ + osal_free(ptr_sw_gpd); +} + +/* FUNCTION NAME: hal_tau_pkt_initTask + * PURPOSE: + * To initialize the Task for packet module. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully dinitialize the control block. + * NPS_E_OTHERS -- Initialize the control block failed. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_initTask( + const UI32_T unit) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + HAL_TAU_PKT_TX_CB_T *ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit); + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + UI32_T channel = 0; + + if (0 != (ptr_cb->init_flag & HAL_TAU_PKT_INIT_TASK)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, + "u=%u, pkt task init failed, not inited\n", unit); + return (rc); + } + + /* Init 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 */ + for (channel = 0; ((channel < HAL_TAU_PKT_TX_CHANNEL_LAST) && (NPS_E_OK == rc)); channel++) + { + ptr_tx_cb->isr_task_cookie[channel].unit = unit; + ptr_tx_cb->isr_task_cookie[channel].channel = channel; + + 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]); + } + + /* Init handleRxDoneTask */ + for (channel = 0; ((channel < HAL_TAU_PKT_RX_CHANNEL_LAST) && (NPS_E_OK == rc)); channel++) + { + ptr_rx_cb->isr_task_cookie[channel].unit = unit; + ptr_rx_cb->isr_task_cookie[channel].channel = channel; + + 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]); + } + + /* Init txTask */ + if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode) + { + ptr_tx_cb->running = TRUE; + } + + ptr_cb->init_flag |= HAL_TAU_PKT_INIT_TASK; + + 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); +} + +/* FUNCTION NAME: _hal_tau_pkt_initTxPdma + * PURPOSE: + * To initialize the TX PDMA. + * INPUT: + * unit -- The unit ID + * channel -- The target Tx channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully initialize the TX PDMA. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_initTxPdma( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + 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; + + /* Isr lock to protect Tx PDMA */ + osal_createIsrLock("TCH_LCK", &ptr_tx_pdma->ring_lock); + + if (HAL_TAU_PKT_TX_WAIT_SYNC_INTR == ptr_tx_cb->wait_mode) + { + /* Sync semaphore to signal sendTxPacket */ + osal_createSemaphore("TCH_SYN", NPS_SEMAPHORE_SYNC, &ptr_tx_pdma->sync_intr_sema); + } + + /* Reset Tx PDMA */ + osal_takeIsrLock(&ptr_tx_pdma->ring_lock, &irg_flags); + + 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_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( + (ptr_tx_pdma->gpd_num + 1) * sizeof(HAL_TAU_PKT_TX_GPD_T)); + + if (NULL != ptr_tx_pdma->ptr_gpd_start_addr) + { + osal_memset(ptr_tx_pdma->ptr_gpd_start_addr, 0x0, + (ptr_tx_pdma->gpd_num + 1) * sizeof(HAL_TAU_PKT_TX_GPD_T)); + + ptr_tx_pdma->ptr_gpd_align_start_addr = (HAL_TAU_PKT_TX_GPD_T *)HAL_TAU_PKT_PDMA_ALIGN_ADDR( + (NPS_HUGE_T)ptr_tx_pdma->ptr_gpd_start_addr, sizeof(HAL_TAU_PKT_TX_GPD_T)); + + rc = _hal_tau_pkt_initTxPdmaRing(unit, channel); + if (NPS_E_OK == rc) + { + _hal_tau_pkt_startTxChannelReg(unit, channel, 0); + } + } + else + { + ptr_tx_cb->cnt.no_memory++; + rc = NPS_E_NO_MEMORY; + } + + if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode) + { + if (NPS_E_OK == rc) + { + /* Prepare the SW-GPD ring */ + ptr_tx_pdma->pptr_sw_gpd_ring = (HAL_TAU_PKT_TX_SW_GPD_T **)osal_alloc( + ptr_tx_pdma->gpd_num * sizeof(HAL_TAU_PKT_TX_SW_GPD_T *)); + + if (NULL != ptr_tx_pdma->pptr_sw_gpd_ring) + { + osal_memset(ptr_tx_pdma->pptr_sw_gpd_ring, 0x0, + ptr_tx_pdma->gpd_num * sizeof(HAL_TAU_PKT_TX_SW_GPD_T *)); + } + else + { + ptr_tx_cb->cnt.no_memory++; + rc = NPS_E_NO_MEMORY; + } + + /* a temp buffer to store the 1st sw gpd for each packet to be enque + * we cannot enque packet before release a spinlock + */ + ptr_tx_pdma->pptr_sw_gpd_bulk = (HAL_TAU_PKT_TX_SW_GPD_T **)osal_alloc( + ptr_tx_pdma->gpd_num * sizeof(HAL_TAU_PKT_TX_SW_GPD_T *)); + + if (NULL != ptr_tx_pdma->pptr_sw_gpd_bulk) + { + osal_memset(ptr_tx_pdma->pptr_sw_gpd_bulk, 0x0, + ptr_tx_pdma->gpd_num * sizeof(HAL_TAU_PKT_TX_SW_GPD_T *)); + } + else + { + ptr_tx_cb->cnt.no_memory++; + rc = NPS_E_NO_MEMORY; + } + } + } + + osal_giveIsrLock(&ptr_tx_pdma->ring_lock, &irg_flags); + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_initRxPdma + * PURPOSE: + * To initialize the RX PDMA. + * INPUT: + * unit -- The unit ID + * channel -- The target Rx channel + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully initialize the RX PDMA. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_initRxPdma( + const UI32_T unit, + const HAL_TAU_PKT_RX_CHANNEL_T channel) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + HAL_TAU_PKT_RX_PDMA_T *ptr_rx_pdma = HAL_TAU_PKT_GET_RX_PDMA_PTR(unit, channel); + + /* Binary semaphore to protect Rx PDMA */ + osal_createSemaphore("RCH_LCK", NPS_SEMAPHORE_BINARY, &ptr_rx_pdma->sema); + + /* 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_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( + (ptr_rx_pdma->gpd_num + 1) * sizeof(HAL_TAU_PKT_RX_GPD_T)); + + if (NULL != ptr_rx_pdma->ptr_gpd_start_addr) + { + osal_memset(ptr_rx_pdma->ptr_gpd_start_addr, 0, + (ptr_rx_pdma->gpd_num + 1) * sizeof(HAL_TAU_PKT_RX_GPD_T)); + + ptr_rx_pdma->ptr_gpd_align_start_addr = (HAL_TAU_PKT_RX_GPD_T *)HAL_TAU_PKT_PDMA_ALIGN_ADDR( + (NPS_HUGE_T)ptr_rx_pdma->ptr_gpd_start_addr, sizeof(HAL_TAU_PKT_RX_GPD_T)); + + /* will initRxPdmaRingBuf and start RCH after setRxConfig */ + rc = _hal_tau_pkt_initRxPdmaRing(unit, channel); + } + else + { + ptr_rx_cb->cnt.no_memory++; + rc = NPS_E_NO_MEMORY; + } + + if (NPS_E_OK == rc) + { + /* Prepare the SKB ring */ + ptr_rx_pdma->pptr_skb_ring = (struct sk_buff **)osal_alloc( + ptr_rx_pdma->gpd_num * sizeof(struct sk_buff *)); + + if (NULL != ptr_rx_pdma->pptr_skb_ring) + { + osal_memset(ptr_rx_pdma->pptr_skb_ring, 0x0, + ptr_rx_pdma->gpd_num * sizeof(struct sk_buff *)); + } + else + { + ptr_rx_cb->cnt.no_memory++; + rc = NPS_E_NO_MEMORY; + } + } + + osal_giveSemaphore(&ptr_rx_pdma->sema); + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_initPktCb + * PURPOSE: + * To initialize the control block of Drv. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully initialize the control block. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_initPktCb( + const UI32_T unit) +{ + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + UI32_T idx = 0, vec = sizeof(_hal_tau_pkt_intr_vec) / sizeof(HAL_TAU_PKT_INTR_VEC_T); + + osal_memset(ptr_cb, 0x0, sizeof(HAL_TAU_PKT_DRV_CB_T)); + + /* Register PKT interrupt functions */ + osal_createIsrLock("ISR_LOCK", &ptr_cb->intr_lock); + osal_mdc_registerIsr(unit, _hal_tau_pkt_dispatcher, (void *)((NPS_HUGE_T)unit)); + + for (idx = 0; idx < vec; idx++) + { + osal_createEvent("ISR_EVENT", &_hal_tau_pkt_intr_vec[idx].intr_event); + ptr_cb->intr_bitmap |= (_hal_tau_pkt_intr_vec[idx].intr_reg); + } + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_initPktTxCb + * PURPOSE: + * To initialize the control block of Rx PDMA. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully initialize the control block. + * NPS_E_OTHERS -- Configure failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_initPktTxCb( + const UI32_T unit) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_TX_CB_T *ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit); + HAL_TAU_PKT_TX_CHANNEL_T channel = 0; + + osal_memset(ptr_tx_cb, 0x0, sizeof(HAL_TAU_PKT_TX_CB_T)); + + ptr_tx_cb->wait_mode = HAL_TAU_PKT_TX_WAIT_MODE; + + if (HAL_TAU_PKT_TX_WAIT_ASYNC == ptr_tx_cb->wait_mode) + { + /* Sync semaphore to signal txTask */ + 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_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); + osal_que_create(&ptr_tx_cb->sw_queue.que_id, ptr_tx_cb->sw_queue.len); + } + else if (HAL_TAU_PKT_TX_WAIT_SYNC_POLL == ptr_tx_cb->wait_mode) + { + /* Disable TX done ISR. */ + for (channel = 0; channel < HAL_TAU_PKT_TX_CHANNEL_LAST; channel++) + { + _hal_tau_pkt_disableIntr(unit, HAL_TAU_PKT_TCH_REG(unit, channel)); + } + } + + /* Init Tx PDMA */ + for (channel = 0; ((channel < HAL_TAU_PKT_TX_CHANNEL_LAST) && (NPS_E_OK == rc)); channel++) + { + rc = _hal_tau_pkt_initTxPdma(unit, channel); + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_initPktRxCb + * PURPOSE: + * To initialize the control block of Rx PDMA. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully initialize the control block. + * NPS_E_OTHERS -- Configure failed. + * NOTES: + * + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_initPktRxCb( + const UI32_T unit) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + HAL_TAU_PKT_RX_CB_T *ptr_rx_cb = HAL_TAU_PKT_GET_RX_CB_PTR(unit); + HAL_TAU_PKT_RX_CHANNEL_T channel = 0; + UI32_T queue = 0; + + osal_memset(ptr_rx_cb, 0x0, sizeof(HAL_TAU_PKT_RX_CB_T)); + + 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); + + /* 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_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); + } + + /* Init Rx PDMA */ + for (channel = 0; ((channel < HAL_TAU_PKT_RX_CHANNEL_LAST) && (NPS_E_OK == rc)); channel++) + { + rc = _hal_tau_pkt_initRxPdma(unit, channel); + } + + return (rc); +} + +/* FUNCTION NAME: _hal_tau_pkt_initL1Isr + * PURPOSE: + * To initialize the PDMA L1 ISR configuration. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully initialize the L1 ISR. + * NPS_E_OTHERS -- Configure failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_initL1Isr( + const UI32_T unit) +{ + UI32_T idx = 0, vec = sizeof(_hal_tau_pkt_intr_vec) / sizeof(HAL_TAU_PKT_INTR_VEC_T); + + for (idx = 0; idx < vec; idx++) + { + _hal_tau_pkt_enableIntr(unit, _hal_tau_pkt_intr_vec[idx].intr_reg); + _hal_tau_pkt_unmaskIntr(unit, _hal_tau_pkt_intr_vec[idx].intr_reg); + } + + return (NPS_E_OK); +} + +/* FUNCTION NAME: _hal_tau_pkt_initL2Isr + * PURPOSE: + * To initialize the PDMA L2 ISR configuration. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully configure for the L2 ISR. + * NPS_E_OTHERS -- Configure failed. + * NOTES: + * None + */ +static NPS_ERROR_NO_T +_hal_tau_pkt_initL2Isr( + const UI32_T unit) +{ + HAL_TAU_PKT_L2_ISR_T isr_status = 0x0; + + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RCH0); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RCH1); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RCH2); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RCH3); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_TCH0); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_TCH1); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_TCH2); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_TCH3); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RX_QID_MAP_ERR); + HAL_TAU_PKT_SET_BITMAP(isr_status, HAL_TAU_PKT_L2_ISR_RX_FRAME_ERR); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_ERR_INT_EN), + &isr_status, sizeof(UI32_T)); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_ERR_INT_MASK_SET), + &isr_status, sizeof(UI32_T)); + + return (NPS_E_OK); + +} + +NPS_ERROR_NO_T +_hal_tau_pkt_resetIosCreditCfg( + const UI32_T unit) +{ +#define HAL_TAU_PKT_PDMA_CREDIT_CFG_RESET_OFFSET (16) + + UI32_T credit_cfg = 0x0; + UI32_T idx; + + for (idx=0; idxptr_profile = ptr_new_profile; + + /* Create the 1st node in the interface profile list */ + if (NULL == *pptr_profile_list) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "prof list empty\n"); + *pptr_profile_list = ptr_new_prof_node; + ptr_new_prof_node->ptr_next_node = NULL; + } + else + { + ptr_prev_node = *pptr_profile_list; + ptr_curr_node = *pptr_profile_list; + + while (ptr_curr_node != NULL) + { + if (ptr_curr_node->ptr_profile->priority <= ptr_new_profile->priority) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "find prof id=%d (%s) higher priority=%d, search next\n", + ptr_curr_node->ptr_profile->id, + ptr_curr_node->ptr_profile->name, + ptr_curr_node->ptr_profile->priority); + /* Search the next node */ + ptr_prev_node = ptr_curr_node; + ptr_curr_node = ptr_curr_node->ptr_next_node; + } + else + { + /* Insert intermediate node */ + ptr_new_prof_node->ptr_next_node = ptr_curr_node; + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "insert prof id=%d (%s) before prof id=%d (%s) (priority=%d >= %d)\n", + ptr_new_prof_node->ptr_profile->id, + ptr_new_prof_node->ptr_profile->name, + ptr_curr_node->ptr_profile->id, + ptr_curr_node->ptr_profile->name, + ptr_new_prof_node->ptr_profile->priority, + ptr_curr_node->ptr_profile->priority); + + if (ptr_prev_node == ptr_curr_node) + { + /* There is no previous node: change the root */ + *pptr_profile_list = ptr_new_prof_node; + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "insert prof id=%d (%s) to head (priority=%d)\n", + ptr_new_prof_node->ptr_profile->id, + ptr_new_prof_node->ptr_profile->name, + ptr_new_prof_node->ptr_profile->priority); + } + else + { + ptr_prev_node->ptr_next_node = ptr_new_prof_node; + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "insert prof id=%d (%s) after prof id=%d (%s) (priority=%d <= %d)\n", + ptr_new_prof_node->ptr_profile->id, + ptr_new_prof_node->ptr_profile->name, + ptr_prev_node->ptr_profile->id, + ptr_prev_node->ptr_profile->name, + ptr_new_prof_node->ptr_profile->priority, + ptr_prev_node->ptr_profile->priority); + } + + return (NPS_E_OK); + } + } + + /* Insert node to the tail of list */ + ptr_prev_node->ptr_next_node = ptr_new_prof_node; + ptr_new_prof_node->ptr_next_node = NULL; + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "insert prof id=%d (%s) to tail, after prof id=%d (%s) (priority=%d <= %d)\n", + ptr_new_prof_node->ptr_profile->id, + ptr_new_prof_node->ptr_profile->name, + ptr_prev_node->ptr_profile->id, + ptr_prev_node->ptr_profile->name, + ptr_new_prof_node->ptr_profile->priority, + ptr_prev_node->ptr_profile->priority); + } + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_addProfToAllIntf( + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_new_profile) +{ + UI32_T port; + HAL_TAU_PKT_NETIF_PORT_DB_T *ptr_port_db; + + 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 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); + } + } + + return (NPS_E_OK); +} + +static HAL_TAU_PKT_NETIF_PROFILE_T * +_hal_tau_pkt_delProfFromListById( + const UI32_T id, + HAL_TAU_PKT_PROFILE_NODE_T **pptr_profile_list) +{ + HAL_TAU_PKT_PROFILE_NODE_T *ptr_temp_node; + HAL_TAU_PKT_PROFILE_NODE_T *ptr_curr_node, *ptr_prev_node; + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile = NULL;; + + if (NULL != *pptr_profile_list) + { + /* Check the 1st node */ + if (id == (*pptr_profile_list)->ptr_profile->id) + { + ptr_profile = (*pptr_profile_list)->ptr_profile; + ptr_temp_node = (*pptr_profile_list); + (*pptr_profile_list) = ptr_temp_node->ptr_next_node; + + if (NULL != ptr_temp_node->ptr_next_node) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "choose prof id=%d (%s) as new head\n", + ptr_temp_node->ptr_next_node->ptr_profile->id, + ptr_temp_node->ptr_next_node->ptr_profile->name); + } + else + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "prof list is empty\n"); + } + + + osal_free(ptr_temp_node); + } + else + { + ptr_prev_node = *pptr_profile_list; + ptr_curr_node = ptr_prev_node->ptr_next_node; + + while (NULL != ptr_curr_node) + { + if (id != ptr_curr_node->ptr_profile->id) + { + ptr_prev_node = ptr_curr_node; + ptr_curr_node = ptr_curr_node->ptr_next_node; + } + else + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "find prof id=%d, free done\n", id); + + ptr_profile = ptr_curr_node->ptr_profile; + ptr_prev_node->ptr_next_node = ptr_curr_node->ptr_next_node; + osal_free(ptr_curr_node); + break; + } + } + } + } + + if (NULL == ptr_profile) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_PROFILE | HAL_TAU_PKT_DBG_ERR), + "find prof failed, id=%d\n", id); + } + + return (ptr_profile); +} + + +static NPS_ERROR_NO_T +_hal_tau_pkt_delProfFromAllIntfById( + const UI32_T id) +{ + UI32_T port; + HAL_TAU_PKT_NETIF_PORT_DB_T *ptr_port_db; + + 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 on the port?? */ + /* if (NULL != ptr_port_db->ptr_net_dev) */ + if (1) + { + _hal_tau_pkt_delProfFromListById(id, &ptr_port_db->ptr_profile_list); + } + } + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_allocProfEntry( + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile) +{ + UI32_T idx; + + for (idx=0; idxid = idx; + return (NPS_E_OK); + } + } + return (NPS_E_TABLE_FULL); +} + +static HAL_TAU_PKT_NETIF_PROFILE_T * +_hal_tau_pkt_freeProfEntry( + const UI32_T id) +{ + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile = NULL; + + if (id < HAL_TAU_PKT_NET_PROFILE_NUM_MAX) + { + ptr_profile = _ptr_hal_tau_pkt_profile_entry[id]; + _ptr_hal_tau_pkt_profile_entry[id] = NULL; + } + + return (ptr_profile); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_destroyAllIntf( + const UI32_T unit) +{ + HAL_TAU_PKT_NETIF_PORT_DB_T *ptr_port_db; + UI32_T port = 0; + + /* Unregister net devices by id, although the "id" is now relavent to "port" we still perform a search */ + for (port = 0; port < HAL_TAU_PKT_MAX_PORT_NUM; port++) + { + ptr_port_db = HAL_TAU_PKT_GET_PORT_DB(port); + if (NULL != ptr_port_db->ptr_net_dev) /* valid intf */ + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_INTF, + "u=%u, find intf %s (id=%d) on phy port=%d, destroy done\n", + unit, + ptr_port_db->meta.name, + ptr_port_db->meta.port, + ptr_port_db->meta.port); + + 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); + + /* Don't need to remove profiles on this port. + * In fact, the profile is binding to "port" not "intf". + */ + /* _hal_tau_pkt_destroyProfList(ptr_port_db->ptr_profile_list); */ + + osal_memset(ptr_port_db, 0x0, sizeof(HAL_TAU_PKT_NETIF_PORT_DB_T)); + } + } + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_delProfListOnAllIntf( + const UI32_T unit) +{ + HAL_TAU_PKT_NETIF_PORT_DB_T *ptr_port_db; + UI32_T port = 0; + HAL_TAU_PKT_PROFILE_NODE_T *ptr_curr_node, *ptr_next_node; + + /* Unregister net devices by id, although the "id" is now relavent to "port" we still perform a search */ + for (port = 0; port < HAL_TAU_PKT_MAX_PORT_NUM; port++) + { + ptr_port_db = HAL_TAU_PKT_GET_PORT_DB(port); + if (NULL != ptr_port_db->ptr_profile_list) /* valid intf */ + { + ptr_curr_node = ptr_port_db->ptr_profile_list; + while (NULL != ptr_curr_node) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "u=%u, del prof id=%d on phy port=%d\n", + unit, ptr_curr_node->ptr_profile->id, port); + + ptr_next_node = ptr_curr_node->ptr_next_node; + osal_free(ptr_curr_node); + ptr_curr_node = ptr_next_node; + } + } + } + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_destroyAllProfile( + const UI32_T unit) +{ + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile; + UI32_T prof_id; + + _hal_tau_pkt_delProfListOnAllIntf(unit); + + for (prof_id=0; prof_idid, + ptr_profile->name, + ptr_profile->priority, + ptr_profile->flags); + osal_free(ptr_profile); + } + } + + return (NPS_E_OK); +} + +/* FUNCTION NAME: hal_tau_pkt_initPktDrv + * PURPOSE: + * To invoke the functions to initialize the control block for each + * PDMA subsystem. + * INPUT: + * unit -- The unit ID + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successfully initialize the control blocks. + * NPS_E_OTHERS -- Initialize the control blocks failed. + * NOTES: + * None + */ +NPS_ERROR_NO_T +hal_tau_pkt_initPktDrv( + const UI32_T unit) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + UI32_T channel = 0; + UI32_T flush_intr = 0x0; + UI32_T clear_intr = 0xffffffff; + HAL_TAU_PKT_DRV_CB_T *ptr_cb = HAL_TAU_PKT_GET_DRV_CB_PTR(unit); + + /* There's a case that PDMA Tx is on-going when doing chip reset, + * where PDMA may hang and be not programmable since current Tx packet + * stucks due to IOS credit too low. + * Thus, we always reset IOS credit value before progrmming Tx PDMA. + */ + _hal_tau_pkt_resetIosCreditCfg(unit); + + /* Since the users may kill SDK application without a de-init flow, + * we help to detect if NETIF is ever init before, and perform deinit. + * (Because the users cannot perform Task init bypassing Drv init, this + * check is required only in here) + */ + if (0 != (ptr_cb->init_flag & HAL_TAU_PKT_INIT_DRV)) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, + "u=%u, init pkt drv failed, inited\n", unit); + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, + "u=%u, stop rx pkt\n", unit); + _hal_tau_pkt_rxStop(unit); + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, + "u=%u, stop all intf\n", unit); + _hal_tau_pkt_stopAllIntf(unit); + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, + "u=%u, deinit pkt task\n", unit); + + hal_tau_pkt_deinitTask(unit); + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, + "u=%u, deinit pkt drv\n", unit); + hal_tau_pkt_deinitPktDrv(unit); + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, + "u=%u, destroy all prof\n", unit); + _hal_tau_pkt_destroyAllProfile(unit); + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, + "u=%u, destroy all intf\n", unit); + _hal_tau_pkt_destroyAllIntf(unit); + } + + /* [cold-boot] 1. stop DMA channel + * 2. disable/mask/clear the interrupt status. + */ + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_ERR_INT_EN), + &flush_intr, sizeof(UI32_T)); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_ERR_INT_MASK_SET), + &clear_intr, sizeof(UI32_T)); + + osal_mdc_writePciReg(unit, + HAL_TAU_PKT_GET_MMIO(HAL_TAU_PKT_PDMA_ERR_INT_CLR), + &clear_intr, sizeof(UI32_T)); + + for (channel = 0; channel < HAL_TAU_PKT_TX_CHANNEL_LAST; channel++) + { + _hal_tau_pkt_stopTxChannelReg(unit, channel); + _hal_tau_pkt_maskAllTxL2IsrReg(unit, channel); + _hal_tau_pkt_clearTxL2IsrStatusReg(unit, channel, clear_intr); + } + + for (channel = 0; channel < HAL_TAU_PKT_RX_CHANNEL_LAST; channel++) + { + _hal_tau_pkt_stopRxChannelReg(unit, channel); + _hal_tau_pkt_maskAllRxL2IsrReg(unit, channel); + _hal_tau_pkt_clearRxL2IsrStatusReg(unit, channel, clear_intr); + } + + rc = _hal_tau_pkt_initPktCb(unit); + if (NPS_E_OK == rc) + { + rc = _hal_tau_pkt_initPktTxCb(unit); + } + if (NPS_E_OK == rc) + { + rc = _hal_tau_pkt_initPktRxCb(unit); + } + if (NPS_E_OK == rc) + { + rc = _hal_tau_pkt_initL1Isr(unit); + } + if (NPS_E_OK == rc) + { + rc = _hal_tau_pkt_initL2Isr(unit); + } + + /* Set the flag to record init state */ + ptr_cb->init_flag |= HAL_TAU_PKT_INIT_DRV; + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, + "u=%u, pkt drv init done, init flag=0x%x\n", unit, ptr_cb->init_flag); + + return (rc); +} + +/* ----------------------------------------------------------------------------------- Init: I/O */ +NPS_ERROR_NO_T +hal_tau_pkt_getNetDev( + const UI32_T unit, + const UI32_T port, + struct net_device **pptr_net_dev) +{ + *pptr_net_dev = HAL_TAU_PKT_GET_PORT_NETDEV(port); + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +hal_tau_pkt_prepareGpd( + const UI32_T unit, + const NPS_ADDR_T phy_addr, + const UI32_T len, + const UI32_T port, + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd) +{ + /* fill up tx_gpd */ + ptr_sw_gpd->tx_gpd.data_buf_addr_hi = NPS_ADDR_64_HI(phy_addr); + ptr_sw_gpd->tx_gpd.data_buf_addr_lo = NPS_ADDR_64_LOW(phy_addr); + ptr_sw_gpd->tx_gpd.data_buf_size = len; + ptr_sw_gpd->tx_gpd.chksum = 0x0; + ptr_sw_gpd->tx_gpd.ipc = 0; /* Raw mode, sent to plane 0 */ + ptr_sw_gpd->tx_gpd.prg = HAL_TAU_PKT_PRG_PROCESS_GPD; + ptr_sw_gpd->tx_gpd.hwo = HAL_TAU_PKT_HWO_HW_OWN; + ptr_sw_gpd->tx_gpd.ch = HAL_TAU_PKT_CH_LAST_GPD; + ptr_sw_gpd->tx_gpd.ioc = HAL_TAU_PKT_IOC_HAS_INTR; + ptr_sw_gpd->tx_gpd.pkt_len = len; + ptr_sw_gpd->tx_gpd.crcc = HAL_TAU_PKT_CRCC_SUM_BY_HW; + + /* fill up cpu header */ + ptr_sw_gpd->tx_gpd.itmh_eth.skip_ipp = 1; + ptr_sw_gpd->tx_gpd.itmh_eth.skip_epp = 1; + ptr_sw_gpd->tx_gpd.itmh_eth.color = 0; /* Green */ + ptr_sw_gpd->tx_gpd.itmh_eth.tc = 15; /* Max tc */ + ptr_sw_gpd->tx_gpd.itmh_eth.igr_phy_port = 0; + + ptr_sw_gpd->tx_gpd.pph_l2.mrk_pcp_val = 7; /* Max pcp */ + ptr_sw_gpd->tx_gpd.pph_l2.mrk_pcp_dei_en = 1; + + /* destination index + * 1. to local ETH port + * 2. to remote ETH port + * 3. to remote CPU + */ + ptr_sw_gpd->tx_gpd.itmh_eth.dst_idx = port; + + /* [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; + ptr_sw_gpd->tx_gpd.itmh_eth.intf_fdid = 0x3fff; + ptr_sw_gpd->tx_gpd.itmh_eth.src_supp_tag = 0x1f; + ptr_sw_gpd->tx_gpd.itmh_eth.nvo3_mgid = 0x6fff; + ptr_sw_gpd->tx_gpd.itmh_eth.nvo3_src_supp_tag_w0 = 0x1; + 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_INVALID_NVO3_ENCAP_IDX; + ptr_sw_gpd->tx_gpd.pph_l2.nvo3_adj_idx = HAL_INVALID_NVO3_ADJ_IDX; + + return (NPS_E_OK); +} + +/* ----------------------------------------------------------------------------------- Init: net_dev_ops */ +static int +_hal_tau_pkt_net_dev_init( + struct net_device *ptr_net_dev) +{ + return 0; +} + +static int +_hal_tau_pkt_net_dev_open( + struct net_device *ptr_net_dev) +{ + netif_start_queue(ptr_net_dev); + +#if defined(PERF_EN_TEST) + /* Tx (len, tx_channel, rx_channel, test_skb) */ + perf_test(64, 1, 0, FALSE); + perf_test(64, 2, 0, FALSE); + perf_test(64, 4, 0, FALSE); + + perf_test(1518, 1, 0, FALSE); + perf_test(1518, 2, 0, FALSE); + perf_test(1518, 4, 0, FALSE); + + perf_test(9216, 1, 0, FALSE); + perf_test(9216, 2, 0, FALSE); + perf_test(9216, 4, 0, FALSE); + + /* Rx (len, tx_channel, rx_channel, test_skb) */ + perf_test(64, 0, 1, FALSE); + perf_test(64, 0, 3, FALSE); + perf_test(64, 0, 4, FALSE); + + perf_test(1518, 0, 1, FALSE); + perf_test(1518, 0, 3, FALSE); + perf_test(1518, 0, 4, FALSE); + + perf_test(9216, 0, 1, FALSE); + perf_test(9216, 0, 3, FALSE); + perf_test(9216, 0, 4, FALSE); +#endif + + return 0; +} + +static int +_hal_tau_pkt_net_dev_stop( + struct net_device *ptr_net_dev) +{ + netif_stop_queue(ptr_net_dev); + return 0; +} + +static int +_hal_tau_pkt_net_dev_ioctl( + struct net_device *ptr_net_dev, + struct ifreq *ptr_ifreq, + int cmd) +{ + return 0; +} + +static netdev_tx_t +_hal_tau_pkt_net_dev_tx( + struct sk_buff *ptr_skb, + 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; + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd = NULL; + void *ptr_virt_addr = NULL; + NPS_ADDR_T phy_addr = 0x0; + + if (NULL == ptr_priv) + { + /* in case that the netdev has been freed/reset somewhere */ + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, "get netdev_priv failed\n"); + return -EFAULT; + } + + /* check skb */ + if (NULL == ptr_skb) + { + ptr_priv->stats.tx_errors++; + return -EFAULT; + } + + 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) + { + skb_pad(ptr_skb, ETH_ZLEN - ptr_skb->len); + skb_set_tail_pointer(ptr_skb, ETH_ZLEN); + ptr_skb->len = ETH_ZLEN; + } + + /* pad 4-bytes for chip-crc */ + skb_pad(ptr_skb, ETH_FCS_LEN); + skb_set_tail_pointer(ptr_skb, ETH_FCS_LEN); + ptr_skb->len += ETH_FCS_LEN; + + /* alloc gpd */ + ptr_sw_gpd = osal_alloc(sizeof(HAL_TAU_PKT_TX_SW_GPD_T)); + if (NULL == ptr_sw_gpd) + { + ptr_priv->stats.tx_errors++; + osal_skb_free(ptr_skb); + } + else + { + /* map skb to dma */ + ptr_virt_addr = ptr_skb->data; + phy_addr = osal_skb_mapDma(ptr_skb, DMA_TO_DEVICE); + if (0x0 == phy_addr) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_ERR, "u=%u, txch=%u, skb dma map err\n", + unit, channel); + ptr_priv->stats.tx_errors++; + osal_skb_free(ptr_skb); + osal_free(ptr_sw_gpd); + } + else + { + /* trans skb to gpd */ + memset(ptr_sw_gpd, 0x0, sizeof(HAL_TAU_PKT_TX_SW_GPD_T)); + ptr_sw_gpd->callback = (void *)_hal_tau_pkt_net_dev_tx_callback; + ptr_sw_gpd->ptr_cookie = (void *)ptr_skb; + ptr_sw_gpd->gpd_num = 1; + ptr_sw_gpd->ptr_next = NULL; + ptr_sw_gpd->channel = channel; + + /* prepare gpd */ + hal_tau_pkt_prepareGpd(unit, phy_addr, ptr_skb->len, ptr_priv->port, ptr_sw_gpd); + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,6,7) + ptr_net_dev->trans_start = jiffies; +#else + netdev_get_tx_queue(ptr_net_dev, 0)->trans_start = jiffies; +#endif + /* send gpd */ + if (NPS_E_OK == hal_tau_pkt_sendGpd(unit, channel, ptr_sw_gpd)) + { + ptr_priv->stats.tx_packets++; + ptr_priv->stats.tx_bytes += ptr_skb->len; + } + else + { + ptr_priv->stats.tx_fifo_errors++; /* to record the extreme cases where packets are dropped */ + ptr_priv->stats.tx_dropped++; + + 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; +} + +static void +_hal_tau_pkt_net_dev_tx_timeout( + struct net_device *ptr_net_dev) +{ + netif_stop_queue(ptr_net_dev); + osal_sleepThread(1000); + netif_wake_queue(ptr_net_dev); +} + +static struct net_device_stats * +_hal_tau_pkt_net_dev_get_stats( + struct net_device *ptr_net_dev) +{ + struct net_device_priv *ptr_priv = netdev_priv(ptr_net_dev); + + return (&ptr_priv->stats); +} + +static int +_hal_tau_pkt_net_dev_set_mtu( + struct net_device *ptr_net_dev, + int new_mtu) +{ + if (new_mtu < 64 || new_mtu > 9216) + { + return -EINVAL; + } + ptr_net_dev->mtu = new_mtu; /* This mtu need to be synced to chip's */ + return 0; +} + +static int +_hal_tau_pkt_net_dev_set_mac( + struct net_device *ptr_net_dev, + void *ptr_mac_addr) +{ + struct sockaddr *ptr_addr = ptr_mac_addr; + + memcpy(ptr_net_dev->dev_addr, ptr_addr->sa_data, ptr_net_dev->addr_len); + return 0; +} + +static void +_hal_tau_pkt_net_dev_set_rx_mode( + struct net_device *ptr_dev) +{ + if (ptr_dev->flags & IFF_PROMISC) + { + } + else + { + if (ptr_dev->flags & IFF_ALLMULTI) + { + } + else + { + if (netdev_mc_empty(ptr_dev)) + { + return; + } + } + } +} + +static struct net_device_ops _hal_tau_pkt_net_dev_ops = +{ + .ndo_init = _hal_tau_pkt_net_dev_init, + .ndo_open = _hal_tau_pkt_net_dev_open, + .ndo_stop = _hal_tau_pkt_net_dev_stop, + .ndo_do_ioctl = _hal_tau_pkt_net_dev_ioctl, + .ndo_start_xmit = _hal_tau_pkt_net_dev_tx, + .ndo_tx_timeout = _hal_tau_pkt_net_dev_tx_timeout, + .ndo_get_stats = _hal_tau_pkt_net_dev_get_stats, + .ndo_change_mtu = _hal_tau_pkt_net_dev_set_mtu, + .ndo_set_mac_address = _hal_tau_pkt_net_dev_set_mac, + .ndo_set_rx_mode = _hal_tau_pkt_net_dev_set_rx_mode, +}; + +static int +_hal_tau_pkt_net_dev_ethtool_get( + struct net_device *ptr_dev, + struct ethtool_cmd *ptr_cmd) +{ + struct net_device_priv *ptr_priv; + + ptr_cmd->supported = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE; + ptr_cmd->port = PORT_FIBRE; + ptr_cmd->duplex = DUPLEX_FULL; + + ptr_priv = netdev_priv(ptr_dev); + ethtool_cmd_speed_set(ptr_cmd, ptr_priv->speed); + + return 0; +} + +static struct ethtool_ops _hal_tau_pkt_net_dev_ethtool_ops = +{ + .get_settings = _hal_tau_pkt_net_dev_ethtool_get, + .get_link = ethtool_op_get_link, +}; + +static void +_hal_tau_pkt_setup( + struct net_device *ptr_net_dev) +{ + struct net_device_priv *ptr_priv = netdev_priv(ptr_net_dev); + + /* setup net device */ + ether_setup(ptr_net_dev); + ptr_net_dev->netdev_ops = &_hal_tau_pkt_net_dev_ops; + ptr_net_dev->ethtool_ops = &_hal_tau_pkt_net_dev_ethtool_ops; + ptr_net_dev->watchdog_timeo = HAL_TAU_PKT_TX_TIMEOUT; + ptr_net_dev->mtu = HAL_TAU_PKT_MAX_ETH_FRAME_SIZE; /* This mtu need to be synced to chip's */ + random_ether_addr(ptr_net_dev->dev_addr); /* Please use the mac-addr of interface. */ + + /* setup private data */ + ptr_priv->ptr_net_dev = ptr_net_dev; + memset(&ptr_priv->stats, 0, sizeof(struct net_device_stats)); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_createIntf( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_NETIF_INTF_T net_intf = {0}; + HAL_TAU_PKT_NETIF_PORT_DB_T *ptr_port_db; + struct net_device *ptr_net_dev = NULL; + struct net_device_priv *ptr_priv = NULL; + NPS_ERROR_NO_T rc = NPS_E_OK; + + /* Lock all Rx tasks to avoid any access to the intf during packet processing */ + /* Only Rx tasks are locked since Tx action is performed under a spinlock protection */ + _hal_tau_pkt_lockRxChannelAll(unit); + + osal_io_copyFromUser(&net_intf, &ptr_cookie->net_intf, sizeof(HAL_TAU_PKT_NETIF_INTF_T)); + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_INTF, "u=%u, create intf name=%s, phy port=%d\n", + unit, net_intf.name, net_intf.port); + + /* To check if the interface with the same name exists in kernel */ + ptr_net_dev = dev_get_by_name(&init_net, net_intf.name); + if (NULL != ptr_net_dev) + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_ERR | HAL_TAU_PKT_DBG_INTF), + "u=%u, create intf failed, exist same name=%s\n", + unit, net_intf.name); + + dev_put(ptr_net_dev); + +#if defined(HAL_TAU_PKT_FORCR_REMOVE_DUPLICATE_NETDEV) + ptr_net_dev->operstate = IF_OPER_DOWN; + netif_carrier_off(ptr_net_dev); + netif_tx_disable(ptr_net_dev); + unregister_netdev(ptr_net_dev); + free_netdev(ptr_net_dev); +#endif + _hal_tau_pkt_unlockRxChannelAll(unit); + return (NPS_E_ENTRY_EXISTS); + } + + /* Bind the net dev and intf meta data to internel port-based array */ + ptr_port_db = HAL_TAU_PKT_GET_PORT_DB(net_intf.port); + if (ptr_port_db->ptr_net_dev == NULL) + { + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) + ptr_net_dev = alloc_netdev(sizeof(struct net_device_priv), + net_intf.name, NET_NAME_UNKNOWN, _hal_tau_pkt_setup); +#else + ptr_net_dev = alloc_netdev(sizeof(struct net_device_priv), + net_intf.name, _hal_tau_pkt_setup); +#endif + memcpy(ptr_net_dev->dev_addr, net_intf.mac, ptr_net_dev->addr_len); + + ptr_priv = netdev_priv(ptr_net_dev); + + /* Port info will be used when packet sent from this netdev */ + ptr_priv->port = net_intf.port; + ptr_priv->id = net_intf.port; + ptr_priv->unit = unit; + + 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)); + + ptr_port_db->ptr_net_dev = ptr_net_dev; + + /* Copy the intf-id to user space */ + osal_io_copyToUser(&ptr_cookie->net_intf, &net_intf, sizeof(HAL_TAU_PKT_NETIF_INTF_T)); + } + else + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_INTF | HAL_TAU_PKT_DBG_ERR), + "u=%u, create intf failed, exist on phy port=%d\n", + unit, net_intf.port); + /* The user needs to delete the existing intf binding to the same port */ + rc = NPS_E_ENTRY_EXISTS; + } + + osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T)); + + _hal_tau_pkt_unlockRxChannelAll(unit); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_destroyIntf( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_NETIF_INTF_T net_intf = {0}; + HAL_TAU_PKT_NETIF_PORT_DB_T *ptr_port_db; + UI32_T port = 0; + NPS_ERROR_NO_T rc = NPS_E_ENTRY_NOT_FOUND; + + /* Lock all Rx tasks to avoid any access to the intf during packet processing */ + /* Only Rx tasks are locked since Tx action is performed under a spinlock protection */ + _hal_tau_pkt_lockRxChannelAll(unit); + + osal_io_copyFromUser(&net_intf, &ptr_cookie->net_intf, sizeof(HAL_TAU_PKT_NETIF_INTF_T)); + + /* Unregister net devices by id, although the "id" is now relavent to "port" we still perform a search */ + for (port = 0; port < HAL_TAU_PKT_MAX_PORT_NUM; port++) + { + ptr_port_db = HAL_TAU_PKT_GET_PORT_DB(port); + if (NULL != ptr_port_db->ptr_net_dev) /* valid intf */ + { + if (ptr_port_db->meta.id == net_intf.id) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_INTF, + "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_tx_disable(ptr_port_db->ptr_net_dev); + unregister_netdev(ptr_port_db->ptr_net_dev); + free_netdev(ptr_port_db->ptr_net_dev); + + /* Don't need to remove profiles on this port. + * In fact, the profile is binding to "port" not "intf". + */ + /* _hal_tau_pkt_destroyProfList(ptr_port_db->ptr_profile_list); */ + + osal_memset(ptr_port_db, 0x0, sizeof(HAL_TAU_PKT_NETIF_PORT_DB_T)); + rc = NPS_E_OK; + break; + } + } + } + + osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T)); + + _hal_tau_pkt_unlockRxChannelAll(unit); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_traverseProfList( + UI32_T intf_id, + HAL_TAU_PKT_PROFILE_NODE_T *ptr_prof_list) +{ + HAL_TAU_PKT_PROFILE_NODE_T *ptr_curr_node; + + ptr_curr_node = ptr_prof_list; + + 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) => ", + ptr_curr_node->ptr_profile->name, + ptr_curr_node->ptr_profile->priority); + ptr_curr_node = ptr_curr_node->ptr_next_node; + } + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_INTF, "null\n"); + return (NPS_E_OK); +} + + +static NPS_ERROR_NO_T +_hal_tau_pkt_getIntf( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_NETIF_INTF_T net_intf = {0}; + HAL_TAU_PKT_NETIF_PORT_DB_T *ptr_port_db; + UI32_T port = 0; + NPS_ERROR_NO_T rc = NPS_E_ENTRY_NOT_FOUND; + + osal_io_copyFromUser(&net_intf, &ptr_cookie->net_intf, sizeof(HAL_TAU_PKT_NETIF_INTF_T)); + + for (port = 0; port < HAL_TAU_PKT_MAX_PORT_NUM; port++) + { + ptr_port_db = HAL_TAU_PKT_GET_PORT_DB(port); + if (NULL != ptr_port_db->ptr_net_dev) /* valid intf */ + { + if (ptr_port_db->meta.id == net_intf.id) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_INTF, "u=%u, find intf id=%d\n", unit, net_intf.id); + _hal_tau_pkt_traverseProfList(net_intf.id, ptr_port_db->ptr_profile_list); + osal_io_copyToUser(&ptr_cookie->net_intf, &ptr_port_db->meta, sizeof(HAL_TAU_PKT_NETIF_INTF_T)); + rc = NPS_E_OK; + break; + } + } + } + + osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T)); + + return (NPS_E_OK); +} + +static HAL_TAU_PKT_NETIF_PROFILE_T * +_hal_tau_pkt_getProfEntry( + const UI32_T id) +{ + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile = NULL; + + if (id < HAL_TAU_PKT_NET_PROFILE_NUM_MAX) + { + if (NULL != _ptr_hal_tau_pkt_profile_entry[id]) + { + ptr_profile = _ptr_hal_tau_pkt_profile_entry[id]; + } + } + + return (ptr_profile); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_createProfile( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile; + HAL_TAU_PKT_NETIF_PORT_DB_T *ptr_port_db; + NPS_ERROR_NO_T rc; + + /* Lock all Rx tasks to avoid profiles being refered during packet processing */ + /* Need to lock all Rx tasks since packets from all Rx channels do profile lookup */ + _hal_tau_pkt_lockRxChannelAll(unit); + + ptr_profile = osal_alloc(sizeof(HAL_TAU_PKT_NETIF_PROFILE_T)); + osal_io_copyFromUser(ptr_profile, &ptr_cookie->net_profile, + sizeof(HAL_TAU_PKT_NETIF_PROFILE_T)); + + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "u=%u, create prof name=%s, priority=%d, flag=0x%x\n", + unit, + ptr_profile->name, + ptr_profile->priority, + ptr_profile->flags); + + /* Save the profile to the profile array and assign the index to ptr_profile->id */ + rc = _hal_tau_pkt_allocProfEntry(ptr_profile); + if (NPS_E_OK == rc) + { + /* Insert the profile to the corresponding (port) interface */ + if ((ptr_profile->flags & HAL_TAU_PKT_NETIF_PROFILE_FLAGS_PORT) != 0) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "u=%u, bind prof to phy port=%d\n", unit, ptr_profile->port); + ptr_port_db = HAL_TAU_PKT_GET_PORT_DB(ptr_profile->port); + _hal_tau_pkt_addProfToList(ptr_profile, &ptr_port_db->ptr_profile_list); + } + else + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "u=%u, bind prof to all intf\n", unit); + _hal_tau_pkt_addProfToAllIntf(ptr_profile); + } + + /* Copy the ptr_profile->id to user space */ + osal_io_copyToUser(&ptr_cookie->net_profile, ptr_profile, sizeof(HAL_TAU_PKT_NETIF_PROFILE_T)); + } + else + { + HAL_TAU_PKT_DBG((HAL_TAU_PKT_DBG_PROFILE | HAL_TAU_PKT_DBG_ERR), + "u=%u, alloc prof entry failed, tbl full\n", unit); + osal_free(ptr_profile); + } + + osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T)); + + _hal_tau_pkt_unlockRxChannelAll(unit); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_destroyProfile( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_NETIF_PROFILE_T profile = {0}; + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile; + NPS_ERROR_NO_T rc = NPS_E_OK; + + /* Lock all Rx tasks to avoid profiles being refered during packet processing */ + /* Need to lock all Rx tasks since packets from all Rx channels do profile lookup */ + _hal_tau_pkt_lockRxChannelAll(unit); + + osal_io_copyFromUser(&profile, &ptr_cookie->net_profile, + sizeof(HAL_TAU_PKT_NETIF_PROFILE_T)); + + /* Remove the profile from corresponding interface (port) */ + _hal_tau_pkt_delProfFromAllIntfById(profile.id); + + ptr_profile = _hal_tau_pkt_freeProfEntry(profile.id); + if (NULL != ptr_profile) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_PROFILE, + "u=%u, destroy prof id=%d, name=%s, priority=%d, flag=0x%x\n", + unit, + ptr_profile->id, + ptr_profile->name, + ptr_profile->priority, + ptr_profile->flags); + osal_free(ptr_profile); + } + + osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T)); + + _hal_tau_pkt_unlockRxChannelAll(unit); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_getProfile( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_NETIF_PROFILE_T profile = {0}; + HAL_TAU_PKT_NETIF_PROFILE_T *ptr_profile; + NPS_ERROR_NO_T rc = NPS_E_OK; + + osal_io_copyFromUser(&profile, &ptr_cookie->net_profile, sizeof(HAL_TAU_PKT_NETIF_PROFILE_T)); + + ptr_profile = _hal_tau_pkt_getProfEntry(profile.id); + if (NULL != ptr_profile) + { + osal_io_copyToUser(&ptr_cookie->net_profile, ptr_profile, sizeof(HAL_TAU_PKT_NETIF_PROFILE_T)); + } + else + { + rc = NPS_E_ENTRY_NOT_FOUND; + } + + osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T)); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_getIntfCnt( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_NETIF_INTF_T net_intf = {0}; + HAL_TAU_PKT_NETIF_INTF_CNT_T intf_cnt = {0}; + HAL_TAU_PKT_NETIF_PORT_DB_T *ptr_port_db; + struct net_device_priv *ptr_priv; + UI32_T port = 0; + NPS_ERROR_NO_T rc = NPS_E_ENTRY_NOT_FOUND; + + osal_io_copyFromUser(&net_intf, &ptr_cookie->net_intf, sizeof(HAL_TAU_PKT_NETIF_INTF_T)); + + for (port = 0; port < HAL_TAU_PKT_MAX_PORT_NUM; port++) + { + ptr_port_db = HAL_TAU_PKT_GET_PORT_DB(port); + if (NULL != ptr_port_db->ptr_net_dev) /* valid intf */ + { + if (ptr_port_db->meta.id == net_intf.id) + { + ptr_priv = netdev_priv(ptr_port_db->ptr_net_dev); + intf_cnt.rx_pkt = ptr_priv->stats.rx_packets; + intf_cnt.tx_pkt = ptr_priv->stats.tx_packets; + intf_cnt.tx_error = ptr_priv->stats.tx_errors; + intf_cnt.tx_queue_full = ptr_priv->stats.tx_fifo_errors; + + rc = NPS_E_OK; + break; + } + } + } + + osal_io_copyToUser(&ptr_cookie->cnt, &intf_cnt, sizeof(HAL_TAU_PKT_NETIF_INTF_CNT_T)); + osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T)); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_hal_tau_pkt_clearIntfCnt( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *ptr_cookie) +{ + HAL_TAU_PKT_NETIF_INTF_T net_intf = {0}; + HAL_TAU_PKT_NETIF_PORT_DB_T *ptr_port_db; + struct net_device_priv *ptr_priv; + UI32_T port = 0; + NPS_ERROR_NO_T rc = NPS_E_ENTRY_NOT_FOUND; + + osal_io_copyFromUser(&net_intf, &ptr_cookie->net_intf, sizeof(HAL_TAU_PKT_NETIF_INTF_T)); + + for (port = 0; port < HAL_TAU_PKT_MAX_PORT_NUM; port++) + { + ptr_port_db = HAL_TAU_PKT_GET_PORT_DB(port); + if (NULL != ptr_port_db->ptr_net_dev) /* valid intf */ + { + if (ptr_port_db->meta.id == net_intf.id) + { + ptr_priv = netdev_priv(ptr_port_db->ptr_net_dev); + ptr_priv->stats.rx_packets = 0; + ptr_priv->stats.tx_packets = 0; + ptr_priv->stats.tx_errors = 0; + ptr_priv->stats.tx_fifo_errors = 0; + + rc = NPS_E_OK; + break; + } + } + } + + osal_io_copyToUser(&ptr_cookie->rc, &rc, sizeof(NPS_ERROR_NO_T)); + + return (NPS_E_OK); +} + +/* ----------------------------------------------------------------------------------- Init: dev_ops */ +static int +_hal_tau_pkt_dev_open( + struct inode *inode, + struct file *file) +{ + return (0); +} + +static int +_hal_tau_pkt_dev_close( + struct inode *inode, + struct file *file) +{ + return (0); +} + +static void +_hal_tau_pkt_dev_tx_callback( + const UI32_T unit, + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd, + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd_usr) +{ + UI32_T channel = ptr_sw_gpd->channel; + HAL_TAU_PKT_TX_CB_T *ptr_tx_cb = HAL_TAU_PKT_GET_TX_CB_PTR(unit); + + while (0 != _hal_tau_pkt_enQueue(&ptr_tx_cb->sw_queue, ptr_sw_gpd)) + { + ptr_tx_cb->cnt.channel[channel].enque_retry++; + HAL_TAU_PKT_TX_ENQUE_RETRY_SLEEP(); + } + ptr_tx_cb->cnt.channel[channel].enque_ok++; + + osal_triggerEvent(&ptr_tx_cb->sync_sema); + ptr_tx_cb->cnt.channel[channel].trig_event++; +} + +static ssize_t +_hal_tau_pkt_dev_tx( + struct file *file, + const char __user *buf, + size_t count, + loff_t *pos) +{ + int ret = 0; + int idx = 0; + unsigned int unit = 0; + unsigned int channel = 0; + HAL_TAU_PKT_IOCTL_TX_COOKIE_T tx_cookie; + HAL_TAU_PKT_IOCTL_TX_GPD_T ioctl_gpd; + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd_knl = NULL; + HAL_TAU_PKT_TX_SW_GPD_T *ptr_first_sw_gpd_knl = NULL; + + /* copy the tx-cookie */ + osal_io_copyFromUser(&tx_cookie, (void *)buf, sizeof(HAL_TAU_PKT_IOCTL_TX_COOKIE_T)); + + unit = tx_cookie.unit; + channel = tx_cookie.channel; + + ptr_sw_gpd_knl = osal_alloc(sizeof(HAL_TAU_PKT_TX_SW_GPD_T)); + ptr_first_sw_gpd_knl = ptr_sw_gpd_knl; + + /* create SW GPD based on the content of each IOCTL GPD */ + while (1) + { + osal_io_copyFromUser(&ioctl_gpd, + ((void *)((NPS_HUGE_T)tx_cookie.ioctl_gpd_addr)) + +idx*sizeof(HAL_TAU_PKT_IOCTL_TX_GPD_T), + sizeof(HAL_TAU_PKT_IOCTL_TX_GPD_T)); + + ptr_sw_gpd_knl->channel = ioctl_gpd.channel; + ptr_sw_gpd_knl->gpd_num = ioctl_gpd.gpd_num; + ptr_sw_gpd_knl->ptr_cookie = (void *)ioctl_gpd.cookie; + + /* directly copy user's HW GPD */ + osal_io_copyFromUser(&ptr_sw_gpd_knl->tx_gpd, + (void *)((NPS_HUGE_T)ioctl_gpd.hw_gpd_addr), + sizeof(HAL_TAU_PKT_TX_GPD_T)); + + /* replace the callback */ + ptr_sw_gpd_knl->callback = (void *)_hal_tau_pkt_dev_tx_callback; + + /* save the first SW GPD address from userspace since + * we have replaced the original callback + */ + ptr_sw_gpd_knl->ptr_cookie = (void *)ioctl_gpd.sw_gpd_addr; + + if (HAL_TAU_PKT_CH_LAST_GPD == ptr_sw_gpd_knl->tx_gpd.ch) + { + ptr_sw_gpd_knl->ptr_next = NULL; + break; + } + else + { + ptr_sw_gpd_knl->ptr_next = (HAL_TAU_PKT_TX_SW_GPD_T *)osal_alloc( + sizeof(HAL_TAU_PKT_TX_SW_GPD_T)); + ptr_sw_gpd_knl = ptr_sw_gpd_knl->ptr_next; + idx++; + } + } + + ret = hal_tau_pkt_sendGpd(unit, channel, ptr_first_sw_gpd_knl); + if (NPS_E_OK != ret) + { + _hal_tau_pkt_freeTxGpdList(unit, ptr_first_sw_gpd_knl); + } + + /* return 0 if success */ + return (ret); +} + +static ssize_t +_hal_tau_pkt_dev_rx( + struct file *file, + char __user *buf, + size_t count, + loff_t *pos) +{ + return (0); +} + +static long +_hal_tau_pkt_dev_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long arg) +{ + int ret = 0; + + /* cmd */ + HAL_TAU_PKT_IOCTL_CMD_T *ptr_cmd = (HAL_TAU_PKT_IOCTL_CMD_T *)&cmd; + unsigned int unit = ptr_cmd->field.unit; + HAL_TAU_PKT_IOCTL_TYPE_T type = ptr_cmd->field.type; + + switch (type) + { + HAL_TAU_PKT_DBG(HAL_TAU_PKT_DBG_COMMON, "u=%u, ioctl type=%u, cmd=%u\n", + unit, type, cmd); + + /* network interface */ + case HAL_TAU_PKT_IOCTL_TYPE_CREATE_INTF: + ret = _hal_tau_pkt_createIntf(unit, (HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_DESTROY_INTF: + ret = _hal_tau_pkt_destroyIntf(unit, (HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_GET_INTF: + ret = _hal_tau_pkt_getIntf(unit, (HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_CREATE_PROFILE: + ret = _hal_tau_pkt_createProfile(unit, (HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_DESTROY_PROFILE: + ret = _hal_tau_pkt_destroyProfile(unit, (HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_GET_PROFILE: + ret = _hal_tau_pkt_getProfile(unit, (HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_GET_INTF_CNT: + ret = _hal_tau_pkt_getIntfCnt(unit, (HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_CLEAR_INTF_CNT: + ret = _hal_tau_pkt_clearIntfCnt(unit, (HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T *)arg); + break; + + /* driver */ + case HAL_TAU_PKT_IOCTL_TYPE_WAIT_RX_FREE: + ret = _hal_tau_pkt_schedRxDeQueue(unit, (HAL_TAU_PKT_IOCTL_RX_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_WAIT_TX_FREE: + ret = _hal_tau_pkt_strictTxDeQueue(unit, (HAL_TAU_PKT_IOCTL_TX_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_SET_RX_CFG: + ret = hal_tau_pkt_setRxKnlConfig(unit, (HAL_TAU_PKT_IOCTL_RX_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_GET_RX_CFG: + ret = hal_tau_pkt_getRxKnlConfig(unit, (HAL_TAU_PKT_IOCTL_RX_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_DEINIT_TASK: + ret = hal_tau_pkt_deinitTask(unit); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_DEINIT_DRV: + ret = hal_tau_pkt_deinitPktDrv(unit); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_INIT_TASK: + ret = hal_tau_pkt_initTask(unit); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_INIT_DRV: + ret = hal_tau_pkt_initPktDrv(unit); + break; + + /* counter */ + case HAL_TAU_PKT_IOCTL_TYPE_GET_TX_CNT: + ret = hal_tau_pkt_getTxKnlCnt(unit, (HAL_TAU_PKT_IOCTL_CH_CNT_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_GET_RX_CNT: + ret = hal_tau_pkt_getRxKnlCnt(unit, (HAL_TAU_PKT_IOCTL_CH_CNT_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_CLEAR_TX_CNT: + ret = hal_tau_pkt_clearTxKnlCnt(unit, (HAL_TAU_PKT_IOCTL_TX_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_CLEAR_RX_CNT: + ret = hal_tau_pkt_clearRxKnlCnt(unit, (HAL_TAU_PKT_IOCTL_RX_COOKIE_T *)arg); + break; + + case HAL_TAU_PKT_IOCTL_TYPE_SET_PORT_ATTR: + 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; + } + + return (ret); +} + +#ifdef CONFIG_COMPAT +static long +_hal_tau_pkt_dev_compat_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long arg) +{ + return _hal_tau_pkt_dev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + +static struct file_operations _hal_tau_pkt_dev_ops = +{ + .owner = THIS_MODULE, + .open = _hal_tau_pkt_dev_open, + .release = _hal_tau_pkt_dev_close, + .write = _hal_tau_pkt_dev_tx, + .read = _hal_tau_pkt_dev_rx, + .unlocked_ioctl = _hal_tau_pkt_dev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = _hal_tau_pkt_dev_compat_ioctl, +#endif +}; + +static struct miscdevice _hal_tau_pkt_dev = +{ + .minor = HAL_TAU_PKT_DRIVER_MINOR_NUM, + .name = HAL_TAU_PKT_DRIVER_NAME, + .fops = &_hal_tau_pkt_dev_ops, +}; + +/* ----------------------------------------------------------------------------------- Init/Deinit */ +static int __init +_hal_tau_pkt_init(void) +{ + /* Register device */ + misc_register(&_hal_tau_pkt_dev); + + /* Init Thread */ + osal_init(); + + /* Reset all database*/ + osal_memset(_hal_tau_pkt_port_db, 0x0, + (HAL_TAU_PKT_MAX_PORT_NUM * sizeof(HAL_TAU_PKT_NETIF_PORT_DB_T))); + osal_memset(_hal_tau_pkt_rx_cb, 0x0, + NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM*sizeof(HAL_TAU_PKT_RX_CB_T)); + osal_memset(_hal_tau_pkt_tx_cb, 0x0, + NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM*sizeof(HAL_TAU_PKT_TX_CB_T)); + 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); +} + +static void __exit +_hal_tau_pkt_exit(void) +{ + UI32_T unit = 0; + + /* 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); + + /* 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); + + /* 4th. Stop all the internal tasks (if any) */ + hal_tau_pkt_deinitTask(unit); + + /* 5th. Deinit pkt driver for common database/interrupt source (if required) */ + hal_tau_pkt_deinitPktDrv(unit); + + /* 6th. Clean up those intf/profiles not been destroyed */ + _hal_tau_pkt_destroyAllProfile(unit); + _hal_tau_pkt_destroyAllIntf(unit); + + osal_deinit(); + + /* Unregister device */ + misc_deregister(&_hal_tau_pkt_dev); +} + +module_init(_hal_tau_pkt_init); +module_exit(_hal_tau_pkt_exit); + +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("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 new file mode 100755 index 000000000000..682eaa5ea318 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/inc/aml.h @@ -0,0 +1,366 @@ +/* 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: aml.h + * PURPOSE: + * 1. Provide whole AML resource initialization API. + * 2. Provide configuration access APIs. + * 3. Provide ISR registration and deregistration APIs. + * 4. Provide memory access. + * 5. Provide DMA management APIs. + * 6. Provide address translation APIs. + * NOTES: + */ + +#ifndef AML_H +#define AML_H + + +/* INCLUDE FILE DECLARATIONS + */ +#include +#include +#include + + +/* NAMING CONSTANT DECLARATIONS + */ + +/* #define AML_EN_I2C */ +/* #define AML_EN_CUSTOM_DMA_ADDR */ + +/* MACRO FUNCTION DECLARATIONS + */ + +/* DATA TYPE DECLARATIONS + */ +typedef enum +{ + AML_DEV_TYPE_PCI, + AML_DEV_TYPE_I2C, + AML_DEV_TYPE_SPI, + AML_DEV_TYPE_LAST + +} AML_HW_IF_T; + +typedef NPS_ERROR_NO_T +(*AML_DEV_READ_FUNC_T)( + const UI32_T unit, + const UI32_T addr_offset, + UI32_T *ptr_data, + const UI32_T len); + +typedef NPS_ERROR_NO_T +(*AML_DEV_WRITE_FUNC_T)( + const UI32_T unit, + const UI32_T addr_offset, + const UI32_T *ptr_data, + const UI32_T len); + +typedef NPS_ERROR_NO_T +(*AML_DEV_ISR_FUNC_T)( + void *ptr_data); + +/* To mask the chip interrupt in kernel interrupt routine. */ +typedef struct +{ + UI32_T mask_addr; + UI32_T mask_val; + +} AML_DEV_ISR_DATA_T; + +/* To read or write the HW-intf registers. */ +typedef struct +{ + AML_DEV_READ_FUNC_T read_callback; + AML_DEV_WRITE_FUNC_T write_callback; + +} AML_DEV_ACCESS_T; + +typedef struct +{ + UI32_T vendor; + UI32_T device; + UI32_T revision; + +} AML_DEV_ID_T; + + +typedef struct +{ + AML_HW_IF_T if_type; + AML_DEV_ID_T id; + AML_DEV_ACCESS_T access; + +} AML_DEV_T; + +/* EXPORTED SUBPROGRAM SPECIFICATIONS + */ + +/* FUNCTION NAME: aml_getRunMode + * PURPOSE: + * To get current SDK running mode. + * INPUT: + * unit -- the device unit + * OUTPUT: + * ptr_mode -- current running mode + * RETURN: + * NPS_E_OK -- Successfully get the running mode. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_getRunMode( + const UI32_T unit, + UI32_T *ptr_mode); + +/* FUNCTION NAME: aml_init + * PURPOSE: + * To initialize the DMA memory and interface-related kernel source + * such as PCIe/I2C/SPI. + * INPUT: + * none + * OUTPUT: + * none + * RETURN: + * NPS_E_OK -- Successfully initialize AML module. + * NPS_E_OTHERS -- Failed to initialize AML module. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_deinit(void); + +/* FUNCTION NAME: aml_init + * PURPOSE: + * To initialize the DMA memory and interface-related kernel source + * such as PCIe/I2C/SPI. + * INPUT: + * none + * OUTPUT: + * none + * RETURN: + * NPS_E_OK -- Successfully initialize AML module. + * NPS_E_OTHERS -- Failed to initialize AML module. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_init(void); + +/* FUNCTION NAME: aml_getNumberOfChip + * PURPOSE: + * To get the number of chips connected to host CPU. + * INPUT: + * none + * OUTPUT: + * ptr_num -- pointer for the chip number + * RETURN: + * NPS_E_OK -- Successfully get the number of chips. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_getNumberOfChip( + UI32_T *ptr_num); + +/* FUNCTION NAME: aml_connectIsr + * PURPOSE: + * To enable the system intterupt and specify the ISR handler. + * INPUT: + * unit -- the device unit + * handler -- the ISR hanlder + * ptr_cookie -- pointer for the data as an argument of the handler + * OUTPUT: + * none + * RETURN: + * NPS_E_OK -- Successfully connect the ISR handler to the system. + * NPS_E_OTHERS -- Failed to connect the ISR handler to the system. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_connectIsr( + const UI32_T unit, + AML_DEV_ISR_FUNC_T handler, + AML_DEV_ISR_DATA_T *ptr_cookie); + +/* FUNCTION NAME: aml_disconnectIsr + * PURPOSE: + * To disable the system intterupt notification. + * INPUT: + * unit -- the device unit + * OUTPUT: + * none + * RETURN: + * NPS_E_OK -- Successfully disconnect the ISR handler to the system. + * NPS_E_OTHERS -- Failed to disconnect the ISR handler to the system. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_disconnectIsr( + const UI32_T unit); + +/* FUNCTION NAME: aml_getDeviceId + * PURPOSE: + * To get the vendor/device/revision ID of the specified chip unit. + * INPUT: + * unit -- the device unit + * OUTPUT: + * ptr_vendor_id -- pointer for the vendor ID + * ptr_device_id -- pointer for the device ID + * ptr_revision_id -- pointer for the revision ID + * RETURN: + * NPS_E_OK -- Successfully get the IDs. + * NPS_E_OTHERS -- Failed to get the IDs. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_getDeviceId( + const UI32_T unit, + UI32_T *ptr_vendor_id, + UI32_T *ptr_device_id, + UI32_T *ptr_revision_id); + +/* FUNCTION NAME: aml_readReg + * PURPOSE: + * To read data from the register of the specified chip unit. + * INPUT: + * unit -- the device unit + * addr_offset -- the address of register + * len -- data size read + * OUTPUT: + * ptr_data -- pointer for the register data + * RETURN: + * NPS_E_OK -- Successfully read the data. + * NPS_E_OTHERS -- Failed to read the data. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_readReg( + const UI32_T unit, + const UI32_T addr_offset, + UI32_T *ptr_data, + const UI32_T len); + +/* FUNCTION NAME: aml_writeReg + * PURPOSE: + * To write data to the register of the specified chip unit. + * INPUT: + * unit -- the device unit + * addr_offset -- the address of register + * ptr_data -- pointer for the written data + * len -- data size read + * OUTPUT: + * none + * RETURN: + * NPS_E_OK -- Successfully write the data. + * NPS_E_OTHERS -- Failed to write the data. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_writeReg( + const UI32_T unit, + const UI32_T addr_offset, + const UI32_T *ptr_data, + const UI32_T len); + +/* FUNCTION NAME: aml_convertVirtToPhy + * PURPOSE: + * To get the physical address of the corresponding virtual + * address input. + * INPUT: + * ptr_virt_addr -- pointer to the virtual address + * OUTPUT: + * ptr_phy_addr -- pointer to the physical address + * RETURN: + * NPS_E_OK -- Successfully convert the address. + * NPS_E_OTHERS -- Failed to convert the address. + * The memory might be not allocated by AML. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_convertVirtToPhy( + void *ptr_virt_addr, + NPS_ADDR_T *ptr_phy_addr); + +/* FUNCTION NAME: aml_convertPhyToVirt + * PURPOSE: + * To get the virtual address of the corresponding physical + * address input. + * INPUT: + * ptr_virt_addr -- pointer for the physical address + * OUTPUT: + * pptr_virt_addr -- pointer for the virtual address pointer + * RETURN: + * NPS_E_OK -- Successfully convert the address. + * NPS_E_OTHERS -- Failed to convert the address. + * The memory might be not allocated by AML. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_convertPhyToVirt( + const NPS_ADDR_T phy_addr, + void **pptr_virt_addr); + +/* FUNCTION NAME: aml_flushCache + * PURPOSE: + * To update the data from CPU cache to the physical memory. + * INPUT: + * ptr_virt_addr -- pointer for the data + * size -- target data size to be updated + * OUTPUT: + * none + * RETURN: + * NPS_E_OK -- Successfully update the data from CPU cache + * to the physical memory. + * NPS_E_OTHERS -- Failed to pdate the data from CPU cache + * to the physical memory. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_flushCache( + void *ptr_virt_addr, + const UI32_T size); + +/* FUNCTION NAME: aml_invalidateCache + * PURPOSE: + * To update the data from physical memory to the CPU cache. + * INPUT: + * ptr_virt_addr -- pointer for the data + * size -- target data size to be updated + * OUTPUT: + * none + * RETURN: + * NPS_E_OK -- Successfully update the data from physical memory + * to the CPU cache. + * NPS_E_OTHERS -- Failed to pdate the data from physical memory + * to the CPU cache. + * NOTES: + * none + */ +NPS_ERROR_NO_T +aml_invalidateCache( + void *ptr_virt_addr, + const UI32_T size); + +#endif /* #ifndef AML_H */ diff --git a/platform/nephos/nephos-modules/modules/src/inc/hal_dev.h b/platform/nephos/nephos-modules/modules/src/inc/hal_dev.h new file mode 100755 index 000000000000..e8d491358c77 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/inc/hal_dev.h @@ -0,0 +1,48 @@ +/* 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: hal_dev.h + * PURPOSE: + * Provide a list of device IDs. + * + * NOTES: + */ + +#ifndef HAL_DEV_H +#define HAL_DEV_H + +/* INCLUDE FILE DECLARATIONS + */ +/* NAMING CONSTANT DECLARATIONS + */ +#define HAL_MTK_VENDOR_ID (0x0E8D) +#define HAL_NP_VENDOR_ID (0x1D9F) + +#define HAL_DEVICE_ID_MT3257 (0x3257) +#define HAL_DEVICE_ID_MT3258 (0x3258) + +#define HAL_DEVICE_ID_NP8363 (0x8363) /* 1.08T 1Bin */ +#define HAL_DEVICE_ID_NP8365 (0x8365) /* 1.8T 1Bin */ +#define HAL_DEVICE_ID_NP8366 (0x8366) /* 2.4T 1Bin */ +#define HAL_DEVICE_ID_NP8367 (0x8367) /* 3.2T 1Bin */ +#define HAL_DEVICE_ID_NP8368 (0x8368) /* 3.2T 2Bin */ +#define HAL_DEVICE_ID_NP8369 (0x8369) /* 6.4T 2Bin */ + +#define HAL_REVISION_ID_E1 (0x01) +#define HAL_REVISION_ID_E2 (0x02) + +#define HAL_INVALID_DEVICE_ID (0xFFFFFFFF) + +#endif /* #ifndef HAL_DEV_H */ 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 new file mode 100755 index 000000000000..3605323a5955 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/inc/hal_tau_pkt_knl.h @@ -0,0 +1,2377 @@ +/* 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: hal_tau_pkt_knl.h + * PURPOSE: + * To provide Linux kernel for PDMA TX/RX control. + * + * NOTES: + */ + +#ifndef HAL_TAU_PKT_KNL_H +#define HAL_TAU_PKT_KNL_H + + +/* CP_COMMON */ +#define HAL_TAU_PKT_CP_COMMON_INT_EN_HI (0x012C0000) +#define HAL_TAU_PKT_CP_COMMON_INT_LO_HI (0x012C0004) +#define HAL_TAU_PKT_CP_COMMON_INT_LVL_HI (0x012C0008) +#define HAL_TAU_PKT_CP_COMMON_INT_LVL_LO (0x012C000C) +#define HAL_TAU_PKT_CP_COMMON_INT_MASK_SET_HI (0x012C0010) +#define HAL_TAU_PKT_CP_COMMON_INT_MASK_SET_LO (0x012C0014) +#define HAL_TAU_PKT_CP_COMMON_INT_MASK_CLR_HI (0x012C0018) +#define HAL_TAU_PKT_CP_COMMON_INT_MASK_CLR_LO (0x012C001C) +#define HAL_TAU_PKT_CP_COMMON_INT_MASK_VAL_HI (0x012C0020) +#define HAL_TAU_PKT_CP_COMMON_INT_MASK_VAL_LO (0x012C0024) +#define HAL_TAU_PKT_CP_COMMON_INT_STAT_HI (0x012C0028) +#define HAL_TAU_PKT_CP_COMMON_INT_STAT_LO (0x012C002C) +#define HAL_TAU_PKT_CP_COMMON_INT_CLR_HI (0x012C0030) +#define HAL_TAU_PKT_CP_COMMON_INT_CLR_LO (0x012C0034) +#define HAL_TAU_PKT_CP_COMMON_INT_SET_HI (0x012C0038) +#define HAL_TAU_PKT_CP_COMMON_INT_SET_LO (0x012C003C) + +/* PDMA */ +#define HAL_TAU_PKT_PDMA_ERR_INT_STAT (0x013F1000) +#define HAL_TAU_PKT_PDMA_ERR_INT_CLR (0x013F1004) +#define HAL_TAU_PKT_PDMA_ERR_INT_EN (0x013F1010) +#define HAL_TAU_PKT_PDMA_ERR_INT_LVL (0x013F1014) +#define HAL_TAU_PKT_PDMA_ERR_INT_MASK_SET (0x013F1018) +#define HAL_TAU_PKT_PDMA_ERR_INT_MASK_CLR (0x013F101C) +#define HAL_TAU_PKT_PDMA_ERR_INT_MASK_VAL (0x013F1020) +#define HAL_TAU_PKT_PDMA_ERR_INT_SET (0x013F1024) +#define HAL_TAU_PKT_PDMA_CREDIT_CFG (0x013F1100) + +/* Rx */ +#define HAL_TAU_PKT_PDMA_RCH_GPD_RING_START_ADDR_LO (0x013F12E4) +#define HAL_TAU_PKT_PDMA_RCH_GPD_RING_START_ADDR_HI (0x013F12E8) +#define HAL_TAU_PKT_PDMA_RCH_GPD_RING_SIZE (0x013F12EC) +#define HAL_TAU_PKT_PDMA_RCH_CMD (0x013F1300) +#define HAL_TAU_PKT_PDMA_RCH_INT_EN (0x013F1360) +#define HAL_TAU_PKT_PDMA_RCH_INT_LVL (0x013F1364) +#define HAL_TAU_PKT_PDMA_RCH_INT_MASK (0x013F1368) +#define HAL_TAU_PKT_PDMA_RCH_INT_SET (0x013F1370) +#define HAL_TAU_PKT_PDMA_RCH_INT_CLR (0x013F1374) +#define HAL_TAU_PKT_PDMA_RCH_INT_STAT (0x013F1378) + +/* Tx */ +#define HAL_TAU_PKT_PDMA_TCH_GPD_RING_START_ADDR_LO (0x013F1A00) +#define HAL_TAU_PKT_PDMA_TCH_GPD_RING_START_ADDR_HI (0x013F1A04) +#define HAL_TAU_PKT_PDMA_TCH_GPD_RING_SIZE (0x013F1A08) +#define HAL_TAU_PKT_PDMA_TCH_CMD (0x013F1A20) +#define HAL_TAU_PKT_PDMA_TCH_INT_EN (0x013F1A40) +#define HAL_TAU_PKT_PDMA_TCH_INT_LVL (0x013F1A44) +#define HAL_TAU_PKT_PDMA_TCH_INT_MASK (0x013F1A48) +#define HAL_TAU_PKT_PDMA_TCH_INT_SET (0x013F1A50) +#define HAL_TAU_PKT_PDMA_TCH_INT_CLR (0x013F1A54) +#define HAL_TAU_PKT_PDMA_TCH_INT_STAT (0x013F1A58) + +#define HAL_TAU_PKT_GET_MMIO(__tbl__) (0x00FFFFFF & (__tbl__)) +#define HAL_TAU_PKT_GET_PDMA_RCH_REG(__tbl__, __channel__) ((__tbl__) + (0x200 * (__channel__))) +#define HAL_TAU_PKT_GET_PDMA_TCH_REG(__tbl__, __channel__) ((__tbl__) + (0x100 * (__channel__))) + + + +#define NPS_NETIF_NAME_LEN (16) +#define NPS_NETIF_PROFILE_NUM_MAX (256) +#define NPS_NETIF_PROFILE_PATTERN_NUM (4) +#define NPS_NETIF_PROFILE_PATTERN_LEN (8) + +/* nps_port.h */ +typedef enum +{ + NPS_PORT_SPEED_1G = 1000, + NPS_PORT_SPEED_10G = 10000, + NPS_PORT_SPEED_25G = 25000, + NPS_PORT_SPEED_40G = 40000, + NPS_PORT_SPEED_50G = 50000, + NPS_PORT_SPEED_100G = 100000, + NPS_PORT_SPEED_200G = 200000, + NPS_PORT_SPEED_400G = 400000, + NPS_PORT_SPEED_LAST +} NPS_PORT_SPEED_T; + + +/* hal_tau_const.h */ +#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) +#define HAL_TAU_PKT_EPP_EXCPT_LAST (64) + +#define HAL_TAU_PKT_IPP_EXCPT_IEV_SDK_REDIRECT_TO_CPU_L2UC \ + (192 + IEV_CFG_EXCPT_EN_W1_SDK_REDIRECT_TO_CPU_L2UC_FIELD_ID ) +#define HAL_TAU_PKT_IPP_EXCPT_IEV_SDK_REDIRECT_TO_CPU_L3UC \ + (192 + IEV_CFG_EXCPT_EN_W1_SDK_REDIRECT_TO_CPU_L3UC_FIELD_ID ) +#define HAL_TAU_PKT_IPP_EXCPT_IEV_SDK_L3UC_DA_MISS \ + (192 + IEV_CFG_EXCPT_EN_W1_SDK_L3UC_DA_MISS_FIELD_ID ) +#define HAL_TAU_PKT_IPP_EXCPT_IEV_SDK_L3MC_PIM_REGISTER \ + (192 + IEV_CFG_EXCPT_EN_W1_SDK_L3MC_PIM_REGISTER_FIELD_ID ) +#define HAL_TAU_PKT_IPP_EXCPT_IEV_SDK_FLEX_DECAP_0_REASON_0 \ + (224 + IEV_CFG_EXCPT_EN_W0_SDK_FLEX_DECAP_0_REASON_0_FIELD_ID) + +/* offset of ITM_RSLT_CPU_CP */ +#define HAL_TAU_PKT_IPP_COPY2CPU_OFFSET (16) +#define HAL_TAU_PKT_EPP_COPY2CPU_OFFSET (32) + +typedef UI32_T HAL_TAU_PKT_IPP_EXCPT_T; +typedef UI32_T HAL_TAU_PKT_EPP_EXCPT_T; + +typedef enum +{ + HAL_TAU_PKT_IPP_L3_EXCPT_FCOE_ZONING = 0, + HAL_TAU_PKT_IPP_L3_EXCPT_RPF, + HAL_TAU_PKT_IPP_L3_EXCPT_ICMP_REDIR, + HAL_TAU_PKT_IPP_L3_EXCPT_SW_FWD, + HAL_TAU_PKT_IPP_L3_EXCPT_MTU, + HAL_TAU_PKT_IPP_L3_EXCPT_TTL, + HAL_TAU_PKT_IPP_L3_EXCPT_LAST +} HAL_TAU_PKT_IPP_L3_EXCPT_T; + +typedef enum +{ + HAL_TAU_PKT_IPP_RSN_RSVD_0 = 0, + HAL_TAU_PKT_IPP_RSN_IDS_MPLS_MP_LSP_INNER_IP_LCL, + HAL_TAU_PKT_IPP_RSN_IDS_IP_MC_TNL_LCL_INTF_MISS, + HAL_TAU_PKT_IPP_RSN_IDS_IP_MC_TNL_GRE_ISIS, + HAL_TAU_PKT_IPP_RSN_IDS_IP_MC_TNL_GRE_KA, + HAL_TAU_PKT_IPP_RSN_IDS_IP_MC_TNL_INNER_IP_LCL, + HAL_TAU_PKT_IPP_RSN_IDS_TRILL_MC_LCL_INTF_MISS, + HAL_TAU_PKT_IPP_RSN_IDS_INNER_SRV_1ST_MISS, + HAL_TAU_PKT_IPP_RSN_IDS_INNER_SRV_2ND_MISS, + HAL_TAU_PKT_IPP_RSN_IEV_IP_MC_TTL0, + HAL_TAU_PKT_IPP_RSN_IEV_IP_MC_TTL1, + HAL_TAU_PKT_IPP_RSN_RSVD_1, + HAL_TAU_PKT_IPP_RSN_RSVD_2, + HAL_TAU_PKT_IPP_RSN_IDS_ECN, + HAL_TAU_PKT_IPP_RSN_IEV_ICMP_REDIR, + HAL_TAU_PKT_IPP_RSN_IEV_ICMP_REDIR_WITH_RSN_IDS_ECN, + HAL_TAU_PKT_IPP_RSN_LAST +} HAL_TAU_PKT_IPP_RSN_T; + +typedef enum +{ + /* IEV.cp_to_cpu_bmap |= + * (1 << sw_plane.iev_cp_to_cpu_bit_pos_{i}) | + * (1 << sw_plane.iev_sflw_cp_to_cpu_bidx_{i}) | + * (1 << (IEV_RSLT_CTL2CPU_PROF.code - 1)) | + * (1 << (ICIA_RSLT_TCAM_UCP_POLICY.cp_to_cpu_idx - 1)); + */ + HAL_TAU_PKT_IPP_COPY2CPU_ICIA_0 = 0, + HAL_TAU_PKT_IPP_COPY2CPU_ICIA_1, + HAL_TAU_PKT_IPP_COPY2CPU_ICIA_2, + HAL_TAU_PKT_IPP_COPY2CPU_ICIA_3, + HAL_TAU_PKT_IPP_COPY2CPU_ICIA_4, + HAL_TAU_PKT_IPP_COPY2CPU_ICIA_5, + HAL_TAU_PKT_IPP_COPY2CPU_COPY_TO_CPU_L2UC, + HAL_TAU_PKT_IPP_COPY2CPU_COPY_TO_CPU_L3UC, + HAL_TAU_PKT_IPP_COPY2CPU_PORT_SFLOW, + HAL_TAU_PKT_IPP_COPY2CPU_ICIA_SFLOW, + HAL_TAU_PKT_IPP_COPY2CPU_FLOW_SFLOW, + HAL_TAU_PKT_IPP_COPY2CPU_L3MC_SPT_READY_UNSET, + HAL_TAU_PKT_IPP_COPY2CPU_COPY_TO_CPU_L2MC, + HAL_TAU_PKT_IPP_COPY2CPU_COPY_TO_CPU_L3MC, + HAL_TAU_PKT_IPP_COPY2CPU_USR_DEFINE_0, + HAL_TAU_PKT_IPP_COPY2CPU_USR_DEFINE_1, + HAL_TAU_PKT_IPP_COPY2CPU_LAST +} HAL_TAU_PKT_IPP_COPY2CPU_T; + +typedef enum +{ + /* The value of: + * 1. emi_sflw_cp_to_cpu_idx_bidx_* + * 2. ECIA.cp_to_cpu_idx (last is invalid) + */ + HAL_TAU_PKT_EPP_COPY2CPU_ECIA_0 = 0, + HAL_TAU_PKT_EPP_COPY2CPU_ECIA_1, + HAL_TAU_PKT_EPP_COPY2CPU_ECIA_2, + HAL_TAU_PKT_EPP_COPY2CPU_ECIA_3, + HAL_TAU_PKT_EPP_COPY2CPU_PORT_SFLOW, + HAL_TAU_PKT_EPP_COPY2CPU_ECIA_SFLOW, + HAL_TAU_PKT_EPP_COPY2CPU_RSVD_0, + HAL_TAU_PKT_EPP_COPY2CPU_RSVD_1, + HAL_TAU_PKT_EPP_COPY2CPU_LAST +} HAL_TAU_PKT_EPP_COPY2CPU_T; + +#define HAL_TAU_PKT_IPP_EXCPT_BITMAP_SIZE (NPS_BITMAP_SIZE(HAL_TAU_PKT_IPP_EXCPT_LAST)) +#define HAL_TAU_PKT_IPP_L3_EXCPT_BITMAP_SIZE (NPS_BITMAP_SIZE(HAL_TAU_PKT_IPP_L3_EXCPT_LAST)) +#define HAL_TAU_PKT_EPP_EXCPT_BITMAP_SIZE (NPS_BITMAP_SIZE(HAL_TAU_PKT_EPP_EXCPT_LAST)) +#define HAL_TAU_PKT_IPP_RSN_BITMAP_SIZE (NPS_BITMAP_SIZE(HAL_TAU_PKT_IPP_RSN_LAST)) +#define HAL_TAU_PKT_IPP_COPY2CPU_BITMAP_SIZE (NPS_BITMAP_SIZE(HAL_TAU_PKT_IPP_COPY2CPU_LAST)) +#define HAL_TAU_PKT_EPP_COPY2CPU_BITMAP_SIZE (NPS_BITMAP_SIZE(HAL_TAU_PKT_EPP_COPY2CPU_LAST)) + +typedef UI32_T HAL_TAU_PKT_IPP_EXCPT_BITMAP_T[HAL_TAU_PKT_IPP_EXCPT_BITMAP_SIZE]; +typedef UI32_T HAL_TAU_PKT_IPP_L3_EXCPT_BITMAP_T[HAL_TAU_PKT_IPP_L3_EXCPT_BITMAP_SIZE]; +typedef UI32_T HAL_TAU_PKT_EPP_EXCPT_BITMAP_T[HAL_TAU_PKT_EPP_EXCPT_BITMAP_SIZE]; +typedef UI32_T HAL_TAU_PKT_IPP_RSN_BITMAP_T[HAL_TAU_PKT_IPP_RSN_BITMAP_SIZE]; +typedef UI32_T HAL_TAU_PKT_IPP_COPY2CPU_BITMAP_T[HAL_TAU_PKT_IPP_COPY2CPU_BITMAP_SIZE]; +typedef UI32_T HAL_TAU_PKT_EPP_COPY2CPU_BITMAP_T[HAL_TAU_PKT_EPP_COPY2CPU_BITMAP_SIZE]; + +typedef struct +{ + /* excpt */ + HAL_TAU_PKT_IPP_EXCPT_BITMAP_T ipp_excpt_bitmap; + HAL_TAU_PKT_IPP_L3_EXCPT_BITMAP_T ipp_l3_excpt_bitmap; + HAL_TAU_PKT_EPP_EXCPT_BITMAP_T epp_excpt_bitmap; + + /* cp */ + HAL_TAU_PKT_IPP_RSN_BITMAP_T ipp_rsn_bitmap; + HAL_TAU_PKT_IPP_COPY2CPU_BITMAP_T ipp_copy2cpu_bitmap; + HAL_TAU_PKT_EPP_COPY2CPU_BITMAP_T epp_copy2cpu_bitmap; + +} HAL_PKT_RX_REASON_BITMAP_T; + + +/* hal_tau_pkt.h */ + +/* NAMING DECLARATIONS + */ +/* PKT related configurable parameters */ +#define HAL_DFLT_CFG_PKT_RX_FREE_STACK_SIZE (64 * 1024) +#define HAL_DFLT_CFG_PKT_RX_FREE_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_DFLT_CFG_PKT_TX_FREE_STACK_SIZE (64 * 1024) +#define HAL_DFLT_CFG_PKT_TX_FREE_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_DFLT_CFG_PKT_TX_NET_STACK_SIZE (64 * 1024) +#define HAL_DFLT_CFG_PKT_TX_NET_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) +#define HAL_TAU_PKT_RX_MAX_LEN (9216 + 86) /* EPP tunnel header */ +#define HAL_TAU_PKT_MIN_LEN (64) /* Ethernet definition */ +#define HAL_TAU_PKT_TMH_HDR_SZ (20) +#define HAL_TAU_PKT_PPH_HDR_SZ (20) +#define HAL_TAU_PKT_CRC_LEN (4) + +/* CH */ +#define HAL_TAU_PKT_CH_LAST_GPD (0) +#define HAL_TAU_PKT_CH_MIDDLE_GPD (1) + +/* PRG */ +#define HAL_TAU_PKT_PRG_PROCESS_GPD (0) /* Normal */ +#define HAL_TAU_PKT_PRG_SKIP_GPD (1) /* Skip */ + +/* CRCC */ +#define HAL_TAU_PKT_CRCC_SUM_BY_HW (0) /* calculated by HW */ +#define HAL_TAU_PKT_CRCC_SUM_BY_SW (1) /* calculated by SW */ + +/* IOC */ +#define HAL_TAU_PKT_IOC_NO_INTR (0) /* trigger interrupt each GPD */ +#define HAL_TAU_PKT_IOC_HAS_INTR (1) /* trigger interrupt when ch=0, default setting */ + +/* HWO */ +#define HAL_TAU_PKT_HWO_SW_OWN (0) +#define HAL_TAU_PKT_HWO_HW_OWN (1) + +/* ECC */ +#define HAL_TAU_PKT_ECC_ERROR_OCCUR (1) + +/* CPU queue number */ +#define HAL_TAU_PKT_CPU_QUE_NUM (48) + +/* PDMA Definitions */ +#define HAL_TAU_PKT_PDMA_MAX_GPD_PER_PKT (10) /* <= 256 */ +#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_DFLT_CFG_PKT_RX_SCHED_MODE (HAL_TAU_PKT_RX_SCHED_RR) + +/* TX Queue */ +#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_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 + */ +/*---------------------------------------------------------------------------*/ +/* [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 +#define HAL_TAU_PKT_PDMA_ALIGN_ADDR(pdma_addr, align_sz) (((pdma_addr) + (align_sz)) & 0xFFFFFFC0) +#endif +/*---------------------------------------------------------------------------*/ +#if defined(NPS_EN_BIG_ENDIAN) +#define HAL_TAU_PKT_ENDIAN_SWAP32(val) (val) +#else +#define HAL_TAU_PKT_ENDIAN_SWAP32(val) ((((UI32_T)(val) & 0xFF) << 24) | \ + (((UI32_T)(val) & 0xFF00) << 8) | \ + (((UI32_T)(val) & 0xFF0000) >> 8) | \ + (((UI32_T)(val) & 0xFF000000) >> 24)) +#endif +/*---------------------------------------------------------------------------*/ +#define HAL_TAU_PKT_GET_BIT(flags, bit) ((((flags) & (bit)) > 0)? 1 : 0) +/*---------------------------------------------------------------------------*/ +#define HAL_TAU_PKT_SET_BITMAP(bitmap, mask_bitmap) (bitmap = ((bitmap) | (mask_bitmap))) +#define HAL_TAU_PKT_CLR_BITMAP(bitmap, mask_bitmap) (bitmap = ((bitmap) & (~(mask_bitmap)))) +/*---------------------------------------------------------------------------*/ +#define HAL_TAU_PKT_GET_TX_INTR_TYPE(channel) (HAL_INTR_TX_CH0 + channel) +#define HAL_TAU_PKT_GET_RX_INTR_TYPE(channel) (HAL_INTR_RX_CH0 + channel) + +/* DATA TYPE DECLARATIONS + */ +typedef enum +{ + HAL_TAU_PKT_TX_WAIT_ASYNC = 0, + HAL_TAU_PKT_TX_WAIT_SYNC_INTR = 1, + HAL_TAU_PKT_TX_WAIT_SYNC_POLL = 2 + +} HAL_TAU_PKT_TX_WAIT_T; + +typedef enum +{ + HAL_TAU_PKT_RX_SCHED_RR = 0, + HAL_TAU_PKT_RX_SCHED_WRR = 1 + +} HAL_TAU_PKT_RX_SCHED_T; + +/* GPD and Packet Strucutre Definition */ +#if defined(NPS_EN_BIG_ENDIAN) + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T typ : 2; + UI32_T tc : 4; + UI32_T color : 2; + UI32_T srv : 3; + UI32_T trig : 1; + UI32_T igr_phy_port :12; + UI32_T hsh_val_w0 : 8; + /* NPS DWORD 1 */ + UI32_T hsh_val_w1 : 2; + UI32_T dst_idx :15; + UI32_T src_idx :15; + /* NPS DWORD 2 */ + UI32_T intf_fdid :14; + UI32_T nvo3_mgid_is_transit : 1; + UI32_T skip_epp : 1; + UI32_T steer_applied : 1; + UI32_T nvo3_ip_tnl_decap_prop_ttl : 1; + UI32_T nvo3_mpls_uhp_prop_ttl : 1; + UI32_T ecn : 2; + UI32_T store_and_forward : 1; + UI32_T lag_epoch : 1; + UI32_T src_supp_tag : 5; + UI32_T one_arm_rte_srv_fdid : 1; + UI32_T fab_one_arm_rte : 1; + UI32_T skip_ipp : 1; + UI32_T igr_fab_port_grp : 1; + /* NPS DWORD 3 */ + UI32_T : 2; + UI32_T nvo3_mgid :15; + UI32_T nvo3_intf :14; + UI32_T nvo3_src_supp_tag_w0 : 1; + /* NPS DWORD 4 */ + UI32_T nvo3_src_supp_tag_w1 : 4; + UI32_T mir_bmap : 8; + UI32_T cp_to_cpu_code : 4; + UI32_T cp_to_cpu_bmap :16; +} HAL_TAU_PKT_ITMH_ETH_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T typ : 2; + UI32_T tc : 4; + UI32_T color : 2; + UI32_T srv : 3; + UI32_T trig : 1; + UI32_T igr_phy_port :12; + UI32_T hsh_val_w0 : 8; + /* NPS DWORD 1 */ + UI32_T hsh_val_w1 : 2; + UI32_T dst_idx :15; + UI32_T src_idx :15; + /* NPS DWORD 2 */ + UI32_T intf_fdid :14; + UI32_T nvo3_mgid_is_transit : 1; + UI32_T skip_epp : 1; + UI32_T steer_applied : 1; + UI32_T nvo3_ip_tnl_decap_prop_ttl : 1; + UI32_T nvo3_mpls_uhp_prop_ttl : 1; + UI32_T ecn : 2; + UI32_T store_and_forward : 1; + UI32_T lag_epoch : 1; + UI32_T src_supp_tag : 5; + UI32_T one_arm_rte_srv_fdid : 1; + UI32_T fab_one_arm_rte : 1; + UI32_T : 2; + /* NPS DWORD 3 */ + UI32_T :32; + /* NPS DWORD 4 */ + UI32_T :23; + UI32_T excpt_code : 8; + UI32_T exp_dscp_mrkd : 1; +} HAL_TAU_PKT_ETMH_FAB_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T typ : 2; + UI32_T tc : 4; + UI32_T color : 2; + UI32_T srv : 3; + UI32_T trig : 1; + UI32_T igr_phy_port :12; + UI32_T hsh_val_w0 : 8; + /* NPS DWORD 1 */ + UI32_T hsh_val_w1 : 2; + UI32_T dst_idx :15; + UI32_T src_idx :15; + /* NPS DWORD 2 */ + UI32_T intf_fdid :14; + UI32_T nvo3_mgid_is_transit : 1; + UI32_T skip_epp : 1; + UI32_T steer_applied : 1; + UI32_T nvo3_ip_tnl_decap_prop_ttl : 1; + UI32_T nvo3_mpls_uhp_prop_ttl : 1; + UI32_T ecn : 2; + UI32_T igr_fab_port_grp : 1; + UI32_T redir : 1; + UI32_T excpt_code_mir_bmap : 8; + UI32_T cp_to_cpu_bmap_w0 : 1; + /* NPS DWORD 3 */ + UI32_T cp_to_cpu_bmap_w1 : 7; + UI32_T egr_phy_port :12; + UI32_T src_supp_pnd : 1; + UI32_T mc_vid_ctl : 3; + UI32_T mc_vid_1st_w0 : 9; + /* NPS DWORD 4 */ + UI32_T mc_vid_1st_w1 : 3; + UI32_T mc_vid_2nd :12; + UI32_T mc_decr_ttl : 1; + UI32_T mc_is_routed : 1; + UI32_T mc_mel_vld : 1; + UI32_T mc_cp_idx :13; + UI32_T exp_dscp_mrkd : 1; +} HAL_TAU_PKT_ETMH_ETH_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T decap_act : 3; + UI32_T igr_l2_vid_num : 2; + UI32_T nvo3_encap_idx :14; + UI32_T mpls_pw_cw_vld : 1; + UI32_T hit_idx_w0 :12; + /* NPS DWORD 1 */ + UI32_T hit_idx_w1 : 7; + UI32_T nvo3_adj_idx : 8; + UI32_T seg_vmid_w0 :17; + /* NPS DWORD 2 */ + UI32_T seg_vmid_w1 : 7; + UI32_T : 1; + UI32_T l2_sa_lrn_en_hw_cvs : 1; + UI32_T l2_sa_lrn_en_hw : 1; + UI32_T vid_ctl : 3; + UI32_T vid_1st :12; + UI32_T vid_2nd_w0 : 7; + /* NPS DWORD 3 */ + UI32_T vid_2nd_w1 : 5; + UI32_T flw_lbl :10; + UI32_T rewr_idx_ctl : 2; + UI32_T rewr_idx_0 :13; + UI32_T rewr_idx_1_w0 : 2; + /* NPS DWORD 4 */ + UI32_T rewr_idx_1_w1 :11; + UI32_T mrk_pcp_dei_en : 1; + UI32_T mrk_pcp_val : 3; + UI32_T mrk_dei_val : 1; + UI32_T ts :16; +} HAL_TAU_PKT_PPH_L2_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T decap_act : 3; + UI32_T igr_l2_vid_num : 2; + UI32_T nvo3_encap_idx :14; + UI32_T mpls_pw_cw_vld : 1; + UI32_T hit_idx_w0 :12; + /* NPS DWORD 1 */ + UI32_T hit_idx_w1 : 7; + UI32_T nvo3_adj_idx : 8; + UI32_T seg_vmid_w0 :17; + /* NPS DWORD 2 */ + UI32_T seg_vmid_w1 : 7; + UI32_T : 1; + UI32_T rpf_pnd : 1; + UI32_T adj_idx :18; + UI32_T is_mc : 1; + UI32_T decr_ttl : 1; + UI32_T decap_prop_ttl : 1; + UI32_T mrk_dscp_en : 1; + UI32_T mrk_dscp_val_w0 : 1; + /* NPS DWORD 3 */ + UI32_T mrk_dscp_val_w1 : 5; + UI32_T flw_lbl :10; + UI32_T rewr_idx_ctl : 2; + UI32_T rewr_idx_0 :13; + UI32_T rewr_idx_1_w0 : 2; + /* NPS DWORD 4 */ + UI32_T rewr_idx_1_w1 :11; + UI32_T mrk_pcp_dei_en : 1; + UI32_T mrk_pcp_val : 3; + UI32_T mrk_dei_val : 1; + UI32_T ts :16; +} HAL_TAU_PKT_PPH_L3UC_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T decap_act : 3; + UI32_T igr_l2_vid_num : 2; + UI32_T nvo3_encap_idx :14; + UI32_T mpls_pw_cw_vld : 1; + UI32_T hit_idx_w0 :12; + /* NPS DWORD 1 */ + UI32_T hit_idx_w1 : 7; + UI32_T nvo3_adj_idx : 8; + UI32_T vid_1st :12; + UI32_T vid_2nd_w0 : 5; + /* NPS DWORD 2 */ + UI32_T vid_2nd_w1 : 7; + UI32_T :15; + UI32_T l2_sa_lrn_en_hw_cvs : 1; + UI32_T l2_sa_lrn_en_hw : 1; + UI32_T vid_ctl : 3; + UI32_T is_mc : 1; + UI32_T : 1; + UI32_T decap_prop_ttl : 1; + UI32_T mrk_dscp_en : 1; + UI32_T mrk_dscp_val_w0 : 1; + /* NPS DWORD 3 */ + UI32_T mrk_dscp_val_w1 : 5; + UI32_T flw_lbl :10; + UI32_T rewr_idx_ctl : 2; + UI32_T rewr_idx_0 :13; + UI32_T rewr_idx_1_w0 : 2; + /* NPS DWORD 4 */ + UI32_T rewr_idx_1_w1 :11; + UI32_T mrk_pcp_dei_en : 1; + UI32_T mrk_pcp_val : 3; + UI32_T mrk_dei_val : 1; + UI32_T ts :16; +} HAL_TAU_PKT_PPH_L3MC_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T decap_act : 3; + UI32_T igr_l2_vid_num : 2; + UI32_T nvo3_encap_idx :14; + UI32_T : 1; + UI32_T hit_idx_w0 :12; + /* NPS DWORD 1 */ + UI32_T hit_idx_w1 : 7; + UI32_T nvo3_adj_idx : 8; + UI32_T seg_vmid_w0 :17; + /* NPS DWORD 2 */ + UI32_T seg_vmid_w1 : 7; + UI32_T : 2; + UI32_T adj_idx :18; + UI32_T : 1; + UI32_T decr_ttl : 1; + UI32_T decap_prop_ttl : 1; + UI32_T mrk_exp_en : 1; + UI32_T : 1; + /* NPS DWORD 3 */ + UI32_T : 2; + UI32_T mrk_exp_val : 3; + UI32_T php_pop_keep_inner_qos : 1; + UI32_T :26; + /* NPS DWORD 4 */ + UI32_T :11; + UI32_T mrk_pcp_dei_en : 1; + UI32_T mrk_pcp_val : 3; + UI32_T mrk_dei_val : 1; + UI32_T ts :16; +} HAL_TAU_PKT_PPH_L25_T; + +#elif defined(NPS_EN_LITTLE_ENDIAN) + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T hsh_val_w0 : 8; + UI32_T igr_phy_port :12; + UI32_T trig : 1; + UI32_T srv : 3; + UI32_T color : 2; + UI32_T tc : 4; + UI32_T typ : 2; + /* NPS DWORD 1 */ + UI32_T src_idx :15; + UI32_T dst_idx :15; + UI32_T hsh_val_w1 : 2; + /* NPS DWORD 2 */ + UI32_T igr_fab_port_grp : 1; + UI32_T skip_ipp : 1; + UI32_T fab_one_arm_rte : 1; + UI32_T one_arm_rte_srv_fdid : 1; + UI32_T src_supp_tag : 5; + UI32_T lag_epoch : 1; + UI32_T store_and_forward : 1; + UI32_T ecn : 2; + UI32_T nvo3_mpls_uhp_prop_ttl : 1; + UI32_T nvo3_ip_tnl_decap_prop_ttl : 1; + UI32_T steer_applied : 1; + UI32_T skip_epp : 1; + UI32_T nvo3_mgid_is_transit : 1; + UI32_T intf_fdid :14; + /* NPS DWORD 3 */ + UI32_T nvo3_src_supp_tag_w0 : 1; + UI32_T nvo3_intf :14; + UI32_T nvo3_mgid :15; + UI32_T : 2; + /* NPS DWORD 4 */ + UI32_T cp_to_cpu_bmap :16; + UI32_T cp_to_cpu_code : 4; + UI32_T mir_bmap : 8; + UI32_T nvo3_src_supp_tag_w1 : 4; +} HAL_TAU_PKT_ITMH_ETH_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T hsh_val_w0 : 8; + UI32_T igr_phy_port :12; + UI32_T trig : 1; + UI32_T srv : 3; + UI32_T color : 2; + UI32_T tc : 4; + UI32_T typ : 2; + /* NPS DWORD 1 */ + UI32_T src_idx :15; + UI32_T dst_idx :15; + UI32_T hsh_val_w1 : 2; + /* NPS DWORD 2 */ + UI32_T : 2; + UI32_T fab_one_arm_rte : 1; + UI32_T one_arm_rte_srv_fdid : 1; + UI32_T src_supp_tag : 5; + UI32_T lag_epoch : 1; + UI32_T store_and_forward : 1; + UI32_T ecn : 2; + UI32_T nvo3_mpls_uhp_prop_ttl : 1; + UI32_T nvo3_ip_tnl_decap_prop_ttl : 1; + UI32_T steer_applied : 1; + UI32_T skip_epp : 1; + UI32_T nvo3_mgid_is_transit : 1; + UI32_T intf_fdid :14; + /* NPS DWORD 3 */ + UI32_T :32; + /* NPS DWORD 4 */ + UI32_T exp_dscp_mrkd : 1; + UI32_T excpt_code : 8; + UI32_T :23; +} HAL_TAU_PKT_ETMH_FAB_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T hsh_val_w0 : 8; + UI32_T igr_phy_port :12; + UI32_T trig : 1; + UI32_T srv : 3; + UI32_T color : 2; + UI32_T tc : 4; + UI32_T typ : 2; + /* NPS DWORD 1 */ + UI32_T src_idx :15; + UI32_T dst_idx :15; + UI32_T hsh_val_w1 : 2; + /* NPS DWORD 2 */ + UI32_T cp_to_cpu_bmap_w0 : 1; + UI32_T excpt_code_mir_bmap : 8; + UI32_T redir : 1; + UI32_T igr_fab_port_grp : 1; + UI32_T ecn : 2; + UI32_T nvo3_mpls_uhp_prop_ttl : 1; + UI32_T nvo3_ip_tnl_decap_prop_ttl : 1; + UI32_T steer_applied : 1; + UI32_T skip_epp : 1; + UI32_T nvo3_mgid_is_transit : 1; + UI32_T intf_fdid :14; + /* NPS DWORD 3 */ + UI32_T mc_vid_1st_w0 : 9; + UI32_T mc_vid_ctl : 3; + UI32_T src_supp_pnd : 1; + UI32_T egr_phy_port :12; + UI32_T cp_to_cpu_bmap_w1 : 7; + /* NPS DWORD 4 */ + UI32_T exp_dscp_mrkd : 1; + UI32_T mc_cp_idx :13; + UI32_T mc_mel_vld : 1; + UI32_T mc_is_routed : 1; + UI32_T mc_decr_ttl : 1; + UI32_T mc_vid_2nd :12; + UI32_T mc_vid_1st_w1 : 3; +} HAL_TAU_PKT_ETMH_ETH_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T hit_idx_w0 :12; + UI32_T mpls_pw_cw_vld : 1; + UI32_T nvo3_encap_idx :14; + UI32_T igr_l2_vid_num : 2; + UI32_T decap_act : 3; + /* NPS DWORD 1 */ + UI32_T seg_vmid_w0 :17; + UI32_T nvo3_adj_idx : 8; + UI32_T hit_idx_w1 : 7; + /* NPS DWORD 2 */ + UI32_T vid_2nd_w0 : 7; + UI32_T vid_1st :12; + UI32_T vid_ctl : 3; + UI32_T l2_sa_lrn_en_hw : 1; + UI32_T l2_sa_lrn_en_hw_cvs : 1; + UI32_T : 1; + UI32_T seg_vmid_w1 : 7; + /* NPS DWORD 3 */ + UI32_T rewr_idx_1_w0 : 2; + UI32_T rewr_idx_0 :13; + UI32_T rewr_idx_ctl : 2; + UI32_T flw_lbl :10; + UI32_T vid_2nd_w1 : 5; + /* NPS DWORD 4 */ + UI32_T ts :16; + UI32_T mrk_dei_val : 1; + UI32_T mrk_pcp_val : 3; + UI32_T mrk_pcp_dei_en : 1; + UI32_T rewr_idx_1_w1 :11; +} HAL_TAU_PKT_PPH_L2_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T hit_idx_w0 :12; + UI32_T mpls_pw_cw_vld : 1; + UI32_T nvo3_encap_idx :14; + UI32_T igr_l2_vid_num : 2; + UI32_T decap_act : 3; + /* NPS DWORD 1 */ + UI32_T seg_vmid_w0 :17; + UI32_T nvo3_adj_idx : 8; + UI32_T hit_idx_w1 : 7; + /* NPS DWORD 2 */ + UI32_T mrk_dscp_val_w0 : 1; + UI32_T mrk_dscp_en : 1; + UI32_T decap_prop_ttl : 1; + UI32_T decr_ttl : 1; + UI32_T is_mc : 1; + UI32_T adj_idx :18; + UI32_T rpf_pnd : 1; + UI32_T : 1; + UI32_T seg_vmid_w1 : 7; + /* NPS DWORD 3 */ + UI32_T rewr_idx_1_w0 : 2; + UI32_T rewr_idx_0 :13; + UI32_T rewr_idx_ctl : 2; + UI32_T flw_lbl :10; + UI32_T mrk_dscp_val_w1 : 5; + /* NPS DWORD 4 */ + UI32_T ts :16; + UI32_T mrk_dei_val : 1; + UI32_T mrk_pcp_val : 3; + UI32_T mrk_pcp_dei_en : 1; + UI32_T rewr_idx_1_w1 :11; +} HAL_TAU_PKT_PPH_L3UC_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T hit_idx_w0 :12; + UI32_T mpls_pw_cw_vld : 1; + UI32_T nvo3_encap_idx :14; + UI32_T igr_l2_vid_num : 2; + UI32_T decap_act : 3; + /* NPS DWORD 1 */ + UI32_T vid_2nd_w0 : 5; + UI32_T vid_1st :12; + UI32_T nvo3_adj_idx : 8; + UI32_T hit_idx_w1 : 7; + /* NPS DWORD 2 */ + UI32_T mrk_dscp_val_w0 : 1; + UI32_T mrk_dscp_en : 1; + UI32_T decap_prop_ttl : 1; + UI32_T : 1; + UI32_T is_mc : 1; + UI32_T vid_ctl : 3; + UI32_T l2_sa_lrn_en_hw : 1; + UI32_T l2_sa_lrn_en_hw_cvs : 1; + UI32_T :15; + UI32_T vid_2nd_w1 : 7; + /* NPS DWORD 3 */ + UI32_T rewr_idx_1_w0 : 2; + UI32_T rewr_idx_0 :13; + UI32_T rewr_idx_ctl : 2; + UI32_T flw_lbl :10; + UI32_T mrk_dscp_val_w1 : 5; + /* NPS DWORD 4 */ + UI32_T ts :16; + UI32_T mrk_dei_val : 1; + UI32_T mrk_pcp_val : 3; + UI32_T mrk_pcp_dei_en : 1; + UI32_T rewr_idx_1_w1 :11; +} HAL_TAU_PKT_PPH_L3MC_T; + +typedef struct +{ + /* NPS DWORD 0 */ + UI32_T hit_idx_w0 :12; + UI32_T : 1; + UI32_T nvo3_encap_idx :14; + UI32_T igr_l2_vid_num : 2; + UI32_T decap_act : 3; + /* NPS DWORD 1 */ + UI32_T seg_vmid_w0 :17; + UI32_T nvo3_adj_idx : 8; + UI32_T hit_idx_w1 : 7; + /* NPS DWORD 2 */ + UI32_T : 1; + UI32_T mrk_exp_en : 1; + UI32_T decap_prop_ttl : 1; + UI32_T decr_ttl : 1; + UI32_T : 1; + UI32_T adj_idx :18; + UI32_T : 2; + UI32_T seg_vmid_w1 : 7; + /* NPS DWORD 3 */ + UI32_T :26; + UI32_T php_pop_keep_inner_qos : 1; + UI32_T mrk_exp_val : 3; + UI32_T : 2; + /* NPS DWORD 4 */ + UI32_T ts :16; + UI32_T mrk_dei_val : 1; + UI32_T mrk_pcp_val : 3; + UI32_T mrk_pcp_dei_en : 1; + UI32_T :11; +} HAL_TAU_PKT_PPH_L25_T; + +#else +#error "Host GPD endian is not defined!!\n" +#endif + +#if defined(NPS_EN_BIG_ENDIAN) + +/* RX GPD STRUCTURE */ +typedef struct +{ + UI32_T data_buf_addr_lo; + UI32_T data_buf_addr_hi; + UI32_T chksum : 16; + UI32_T ioc : 1; + UI32_T : 1; + UI32_T avbl_buf_len : 14; + UI32_T : 32; + + union + { + HAL_TAU_PKT_ITMH_ETH_T itmh_eth; + HAL_TAU_PKT_ETMH_FAB_T etmh_fab; + HAL_TAU_PKT_ETMH_ETH_T etmh_eth; + }; + union + { + HAL_TAU_PKT_PPH_L2_T pph_l2; + HAL_TAU_PKT_PPH_L3UC_T pph_l3uc; + HAL_TAU_PKT_PPH_L3MC_T pph_l3mc; + HAL_TAU_PKT_PPH_L25_T pph_l25; + }; + + UI32_T : 32; + UI32_T hwo : 1; + UI32_T ch : 1; + UI32_T trn : 1; + UI32_T ecce : 1; + UI32_T errf : 1; + UI32_T : 5; + UI32_T queue : 6; + UI32_T : 2; + UI32_T cnsm_buf_len : 14; + +} HAL_TAU_PKT_RX_GPD_T; + +/* TX GPD STRUCTURE */ +typedef struct +{ + UI32_T data_buf_addr_lo; + UI32_T data_buf_addr_hi; + UI32_T chksum : 16; + UI32_T ioc : 1; + UI32_T : 1; + UI32_T data_buf_size : 14; + UI32_T : 32; + + union + { + HAL_TAU_PKT_ITMH_ETH_T itmh_eth; + HAL_TAU_PKT_ETMH_FAB_T etmh_fab; + HAL_TAU_PKT_ETMH_ETH_T etmh_eth; + }; + union + { + HAL_TAU_PKT_PPH_L2_T pph_l2; + HAL_TAU_PKT_PPH_L3UC_T pph_l3uc; + HAL_TAU_PKT_PPH_L3MC_T pph_l3mc; + HAL_TAU_PKT_PPH_L25_T pph_l25; + }; + + UI32_T : 16; + UI32_T ptp_hdr : 16; + UI32_T hwo : 1; + UI32_T ch : 1; + UI32_T : 1; + UI32_T ecce : 1; + UI32_T : 4; + UI32_T cos : 3; + UI32_T phc : 1; /* PTP Header Control */ + UI32_T ipc : 2; /* Ingress Plane Control */ + UI32_T crcc : 1; + UI32_T prg : 1; /* Purge */ + UI32_T : 2; + UI32_T pkt_len : 14; /* Total packet length */ + +} HAL_TAU_PKT_TX_GPD_T; + +#elif defined(NPS_EN_LITTLE_ENDIAN) + +/* RX GPD STRUCTURE */ +typedef struct +{ + UI32_T data_buf_addr_lo; + UI32_T data_buf_addr_hi; + UI32_T avbl_buf_len : 14; + UI32_T : 1; + UI32_T ioc : 1; + UI32_T chksum : 16; + UI32_T : 32; + + union + { + HAL_TAU_PKT_ITMH_ETH_T itmh_eth; + HAL_TAU_PKT_ETMH_FAB_T etmh_fab; + HAL_TAU_PKT_ETMH_ETH_T etmh_eth; + }; + union + { + HAL_TAU_PKT_PPH_L2_T pph_l2; + HAL_TAU_PKT_PPH_L3UC_T pph_l3uc; + HAL_TAU_PKT_PPH_L3MC_T pph_l3mc; + HAL_TAU_PKT_PPH_L25_T pph_l25; + }; + + UI32_T : 32; + UI32_T cnsm_buf_len : 14; + UI32_T : 2; + UI32_T queue : 6; + UI32_T : 5; + UI32_T errf : 1; + UI32_T ecce : 1; + UI32_T trn : 1; + UI32_T ch : 1; + UI32_T hwo : 1; + +} HAL_TAU_PKT_RX_GPD_T; + +/* TX GPD STRUCTURE */ +typedef struct +{ + UI32_T data_buf_addr_lo; + UI32_T data_buf_addr_hi; + UI32_T data_buf_size : 14; + UI32_T : 1; + UI32_T ioc : 1; + UI32_T chksum : 16; + UI32_T : 32; + + union + { + HAL_TAU_PKT_ITMH_ETH_T itmh_eth; + HAL_TAU_PKT_ETMH_FAB_T etmh_fab; + HAL_TAU_PKT_ETMH_ETH_T etmh_eth; + }; + union + { + HAL_TAU_PKT_PPH_L2_T pph_l2; + HAL_TAU_PKT_PPH_L3UC_T pph_l3uc; + HAL_TAU_PKT_PPH_L3MC_T pph_l3mc; + HAL_TAU_PKT_PPH_L25_T pph_l25; + }; + + UI32_T ptp_hdr : 16; + UI32_T : 16; + UI32_T pkt_len : 14; /* Total packet length */ + UI32_T : 2; + UI32_T prg : 1; /* Purge */ + UI32_T crcc : 1; + UI32_T ipc : 2; /* Ingress Plane Control */ + UI32_T phc : 1; /* PTP Header Control */ + UI32_T cos : 3; + UI32_T : 4; + UI32_T ecce : 1; + UI32_T : 1; + UI32_T ch : 1; + UI32_T hwo : 1; +} HAL_TAU_PKT_TX_GPD_T; + +#else +#error "Host GPD endian is not defined\n" +#endif + +/* ----------------------------------------------------------------------------------- PP Type */ +typedef enum +{ + HAL_TAU_PKT_TMH_TYPE_ITMH_ETH = 0, + HAL_TAU_PKT_TMH_TYPE_ITMH_FAB, + HAL_TAU_PKT_TMH_TYPE_ETMH_FAB, + HAL_TAU_PKT_TMH_TYPE_ETMH_ETH, + HAL_TAU_PKT_TMH_TYPE_LAST + +} HAL_TAU_PKT_TMH_TYPE_T; + +typedef enum +{ + HAL_TAU_PKT_TMH_SRV_L2 = 0, + HAL_TAU_PKT_TMH_SRV_L25_MPLS, + HAL_TAU_PKT_TMH_SRV_L3, + HAL_TAU_PKT_TMH_SRV_EGR, /* L3 downgrade L2 */ + HAL_TAU_PKT_TMH_SRV_L25_NSH, + HAL_TAU_PKT_TMH_SRV_L25_TRILL, + HAL_TAU_PKT_TMH_SRV_LAST + +} HAL_TAU_PKT_TMH_SRV_T; + +typedef enum +{ + HAL_TAU_PKT_TMH_DECAP_NONE = 0, + HAL_TAU_PKT_TMH_DECAP_1_MPLS_LABEL, + HAL_TAU_PKT_TMH_DECAP_2_MPLS_LABEL, + HAL_TAU_PKT_TMH_DECAP_3_MPLS_LABEL, + HAL_TAU_PKT_TMH_DECAP_4_MPLS_LABEL, + HAL_TAU_PKT_TMH_DECAP_IP_TRILL_NSH, + HAL_TAU_PKT_TMH_DECAP_LAST + +} HAL_TAU_PKT_TMH_DECAP_T; + +typedef struct +{ + union + { + HAL_TAU_PKT_ITMH_ETH_T itmh_eth; + HAL_TAU_PKT_ETMH_FAB_T etmh_fab; + HAL_TAU_PKT_ETMH_ETH_T etmh_eth; + }; +} HAL_TAU_PKT_TMH_T; + +typedef struct +{ + union + { + HAL_TAU_PKT_PPH_L2_T pph_l2; + HAL_TAU_PKT_PPH_L3UC_T pph_l3uc; + HAL_TAU_PKT_PPH_L3MC_T pph_l3mc; + HAL_TAU_PKT_PPH_L25_T pph_l25; + }; +} HAL_TAU_PKT_PPH_T; + +/* ----------------------------------------------------------------------------------- Reg Type */ +typedef enum +{ + 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 = (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 = (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 = (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 = (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; + +/* ----------------------------------------------------------------------------------- Tx */ +typedef enum +{ + HAL_TAU_PKT_TX_CHANNEL_0 = 0, + HAL_TAU_PKT_TX_CHANNEL_1, + HAL_TAU_PKT_TX_CHANNEL_2, + HAL_TAU_PKT_TX_CHANNEL_3, + HAL_TAU_PKT_TX_CHANNEL_LAST + +} HAL_TAU_PKT_TX_CHANNEL_T; + +typedef void +(*HAL_TAU_PKT_TX_FUNC_T)( + const UI32_T unit, + const void *ptr_sw_gpd, /* SW-GPD to be processed */ + void *ptr_coockie); /* Private data of SDK */ + +typedef struct HAL_TAU_PKT_TX_SW_GPD_S +{ + HAL_TAU_PKT_TX_FUNC_T callback; /* (unit, ptr_sw_gpd, ptr_cookie) */ + void *ptr_cookie; /* Pointer of NPS_PKT_TX_PKT_T */ + HAL_TAU_PKT_TX_GPD_T tx_gpd; + UI32_T gpd_num; + struct HAL_TAU_PKT_TX_SW_GPD_S *ptr_next; + +#if defined (NPS_EN_NETIF) + UI32_T channel; /* For counter */ +#endif + +} HAL_TAU_PKT_TX_SW_GPD_T; + +typedef struct +{ + UI32_T send_ok; + UI32_T gpd_empty; + UI32_T poll_timeout; + + /* queue */ + UI32_T enque_ok; + UI32_T enque_retry; + + /* event */ + UI32_T trig_event; + + /* normal interrupt */ + UI32_T tx_done; + + /* abnormal interrupt */ + UI32_T gpd_hwo_err; /* bit-0 */ + UI32_T gpd_chksm_err; /* bit-1 */ + UI32_T gpd_no_ovfl_err; /* bit-2 */ + UI32_T gpd_dma_read_err; /* bit-3 */ + UI32_T buf_size_err; /* bit-4 */ + UI32_T runt_err; /* bit-5 */ + UI32_T ovsz_err; /* bit-6 */ + UI32_T len_mismatch_err; /* bit-7 */ + UI32_T pktpl_dma_read_err; /* bit-8 */ + UI32_T cos_err; /* bit-9 */ + UI32_T gpd_gt255_err; /* bit-10 */ + UI32_T pfc; /* bit-11 */ + UI32_T credit_udfl_err; /* bit-12 */ + UI32_T dma_write_err; /* bit-13 */ + UI32_T sw_issue_stop; /* bit-14 */ + + /* others */ + UI32_T err_recover; + UI32_T ecc_err; + +} HAL_TAU_PKT_TX_CHANNEL_CNT_T; + +typedef struct +{ + HAL_TAU_PKT_TX_CHANNEL_CNT_T channel[HAL_TAU_PKT_TX_CHANNEL_LAST]; + UI32_T invoke_gpd_callback; + UI32_T no_memory; + + /* queue */ + UI32_T deque_ok; + UI32_T deque_fail; + + /* event */ + UI32_T wait_event; + +} HAL_TAU_PKT_TX_CNT_T; + +/* ----------------------------------------------------------------------------------- Rx */ +typedef enum +{ + HAL_TAU_PKT_RX_CHANNEL_0 = 0, + HAL_TAU_PKT_RX_CHANNEL_1, + HAL_TAU_PKT_RX_CHANNEL_2, + HAL_TAU_PKT_RX_CHANNEL_3, + HAL_TAU_PKT_RX_CHANNEL_LAST +} HAL_TAU_PKT_RX_CHANNEL_T; + +typedef enum +{ + HAL_TAU_PKT_C_NEXT = 0, /* callback continuous */ + HAL_TAU_PKT_C_STOP = 1, + HAL_TAU_PKT_C_OTHERS = 2 +} HAL_TAU_PKT_CALLBACK_NO_T; + +typedef enum +{ + HAL_TAU_PKT_RX_CALLBACK_ACTION_INSERT = 0, + HAL_TAU_PKT_RX_CALLBACK_ACTION_APPEND = 1, + HAL_TAU_PKT_RX_CALLBACK_ACTION_DELETE = 2, + HAL_TAU_PKT_RX_CALLBACK_ACTION_DELETE_ALL = 3 +} HAL_TAU_PKT_RX_CALLBACK_ACTION_T; + +typedef HAL_TAU_PKT_CALLBACK_NO_T +(*HAL_TAU_PKT_RX_FUNC_T)( + const UI32_T unit, + const void *ptr_sw_gpd, /* SW-GPD to be processed */ + void *ptr_cookie); /* Private data of SDK */ + +typedef struct HAL_TAU_PKT_RX_CALLBACK_S +{ + HAL_TAU_PKT_RX_FUNC_T callback; /* (unit, ptr_sw_gpd, ptr_cookie) */ + void *ptr_cookie; + struct HAL_TAU_PKT_RX_CALLBACK_S *ptr_next; +} HAL_TAU_PKT_RX_CALLBACK_T; + +typedef struct HAL_TAU_PKT_RX_SW_GPD_S +{ + BOOL_T rx_complete; /* FALSE when PDMA error occurs */ + HAL_TAU_PKT_RX_GPD_T rx_gpd; + struct HAL_TAU_PKT_RX_SW_GPD_S *ptr_next; + +#if defined (NPS_EN_NETIF) + void *ptr_cookie; /* Pointer of virt-addr */ +#endif + +} HAL_TAU_PKT_RX_SW_GPD_T; + +typedef struct +{ + /* queue */ + UI32_T enque_ok; + UI32_T enque_retry; + UI32_T deque_ok; + UI32_T deque_fail; + + /* event */ + UI32_T trig_event; + + /* normal interrupt */ + UI32_T rx_done; + + /* abnormal interrupt */ + UI32_T avbl_gpd_low; /* bit-0 */ + UI32_T avbl_gpd_empty; /* bit-1 */ + UI32_T avbl_gpd_err; /* bit-2 */ + UI32_T gpd_chksm_err; /* bit-3 */ + UI32_T dma_read_err; /* bit-4 */ + UI32_T dma_write_err; /* bit-5 */ + UI32_T sw_issue_stop; /* bit-6 */ + UI32_T gpd_gt255_err; /* bit-7 */ + UI32_T tod_uninit; /* bit-8 */ + UI32_T pkt_err_drop; /* bit-9 */ + UI32_T udsz_drop; /* bit-10 */ + UI32_T ovsz_drop; /* bit-11 */ + UI32_T cmdq_ovf_drop; /* bit-12 */ + UI32_T fifo_ovf_drop; /* bit-13 */ + + /* others */ + UI32_T err_recover; + UI32_T ecc_err; + +#if defined (NPS_EN_NETIF) + /* it means that user doesn't create intf on that port */ + UI32_T netdev_miss; +#endif + + +} HAL_TAU_PKT_RX_CHANNEL_CNT_T; + +typedef struct +{ + HAL_TAU_PKT_RX_CHANNEL_CNT_T channel[HAL_TAU_PKT_RX_CHANNEL_LAST]; + UI32_T invoke_gpd_callback; + UI32_T no_memory; + + /* event */ + UI32_T wait_event; + +} HAL_TAU_PKT_RX_CNT_T; + +/* ----------------------------------------------------------------------------------- Reg */ +#if defined(NPS_EN_LITTLE_ENDIAN) + +typedef union +{ + UI32_T reg; + struct + { + UI32_T tch_axlen_cfg : 3; + UI32_T : 5; + UI32_T tch_axi_free_arvalid : 1; + UI32_T : 7; + UI32_T tch_arvalid_thrhold_cfg : 2; + UI32_T : 6; + UI32_T tch_rready_low_4_hdr : 1; + UI32_T tch_ios_crdt_add_en : 1; + UI32_T : 6; + } field; +} HAL_TAU_PKT_AXI_LEN_CFG_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T pdma_lbk_en : 1; + UI32_T : 3; + UI32_T pdma_lbk_plane : 2; + UI32_T : 2; + UI32_T pm_lbk_en : 1; + UI32_T : 7; + UI32_T pm_lbk_rqid : 6; + UI32_T : 2; + UI32_T : 8; + } field; +} HAL_TAU_PKT_LBK_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T pdma_lbk_rqid0 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid1 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid2 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid3 : 6; + UI32_T : 2; + } field; +} HAL_TAU_PKT_LBK_RQID0_3_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T pdma_lbk_rqid4 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid5 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid6 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid7 : 6; + UI32_T : 2; + } field; +} HAL_TAU_PKT_LBK_RQID4_7_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T cos_pfc_sts0 : 8; + UI32_T cos_pfc_sts1 : 8; + UI32_T cos_pfc_sts2 : 8; + UI32_T cos_pfc_sts3 : 8; + } field; +} HAL_TAU_PKT_COS_PFC_STS_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T pdma_ela_en : 1; + UI32_T : 7; + UI32_T pdma_ela_valid_sel : 8; + UI32_T : 8; + UI32_T : 8; + } field; +} HAL_TAU_PKT_ELA_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T pdma_ela_word0_sel : 8; + UI32_T pdma_ela_word1_sel : 8; + UI32_T pdma_ela_word2_sel : 8; + UI32_T pdma_ela_word3_sel : 8; + } field; +} HAL_TAU_PKT_ELA_SEL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T ingr_pln_ios_credit_base_size_lo : 8; + UI32_T ingr_pln_ios_credit_base_size_hi : 8; + UI32_T ingr_pln_ios_credit_set : 1; + UI32_T : 7; + UI32_T : 1; + UI32_T ingr_pln_full_pkt_mode : 1; + UI32_T : 6; + } field; +} HAL_TAU_PKT_IGR_PLN_CREDIT_CFG_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T ingr_pln_cur_ios_credit_lo : 8; + UI32_T ingr_pln_cur_ios_credit_hi : 8; + UI32_T ingr_pln_ios_credit_ovfl : 1; + UI32_T ingr_pln_ios_credit_udfl : 1; + UI32_T : 6; + UI32_T : 8; + } field; +} HAL_TAU_PKT_IGR_PLN_CREDIT_STS_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T ingr_pln_ios_credit_rdy_lo_bound : 8; + UI32_T ingr_pln_ios_credit_rdy_hi_bound : 8; + UI32_T : 8; + UI32_T : 8; + } field; +} HAL_TAU_PKT_IGR_PLN_CREDIT_THR_REG_T; + + +typedef union +{ + UI32_T reg; + struct + { + UI32_T rch_stomp_crc_en : 1; + UI32_T : 7; + UI32_T rch_crc_regen_en : 1; + UI32_T : 7; + UI32_T rch_pfc_fun_en : 1; + UI32_T : 7; + UI32_T : 8; + } field; +} HAL_TAU_PKT_RCH_STOMP_CRC_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T rch_ioc_en : 1; + UI32_T : 7; + UI32_T rch_chksm_en : 1; + UI32_T : 7; + UI32_T : 8; + UI32_T : 8; + } field; +} HAL_TAU_PKT_RCH_MISC_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T rch_gpd_pfc_lo : 8; + UI32_T rch_gpd_pfc_hi : 8; + UI32_T : 8; + UI32_T : 8; + } field; +} HAL_TAU_PKT_RCH_GPD_PFC_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T rch_fifo_pfc_lo_lo : 8; + UI32_T rch_fifo_pfc_lo_hi : 3; + UI32_T : 5; + UI32_T rch_fifo_pfc_hi_lo : 8; + UI32_T rch_fifo_pfc_hi_hi : 3; + UI32_T : 5; + } field; +} HAL_TAU_PKT_RCH_FIFO_PFC_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T rch_cmdq_pfc_lo : 5; + UI32_T : 3; + UI32_T rch_cmdq_pfc_hi : 5; + UI32_T : 3; + UI32_T : 8; + UI32_T : 8; + } field; +} HAL_TAU_PKT_RCH_CMDQ_PFC_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T rch_start : 1; + UI32_T rch_resume : 1; + UI32_T rch_stop : 1; + UI32_T : 5; + UI32_T : 8; + UI32_T rch_gpd_add_no_lo : 8; + UI32_T rch_gpd_add_no_hi : 8; + } field; +} HAL_TAU_PKT_RCH_CMD_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T rch_fifo_ovf_drop_cnt_clr : 1; + UI32_T rch_cmdq_ovf_drop_cnt_clr : 1; + UI32_T rch_ovsz_drop_cnt_clr : 1; + UI32_T rch_udsz_drop_cnt_clr : 1; + UI32_T rch_pkterr_drop_cnt_clr : 1; + UI32_T rch_flush_cnt_clr : 1; + UI32_T : 2; + UI32_T : 8; + UI32_T : 8; + UI32_T : 8; + } field; +} HAL_TAU_PKT_RCH_CNT_CLR_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T rch_active : 1; + UI32_T rch_avbl_gpd_pfc : 1; + UI32_T rch_fifo_pfc : 1; + UI32_T rch_cmdq_pfc : 1; + UI32_T rch_pfc : 1; + UI32_T : 3; + UI32_T : 8; + UI32_T rch_avbl_gpd_no_lo : 8; + UI32_T rch_avbl_gpd_no_hi : 8; + } field; +} HAL_TAU_PKT_RCH_STATUS_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T tch_ioc_en : 1; + UI32_T tch_chksm_en : 1; + UI32_T tch_pfc_en : 1; + UI32_T tch_pktlen_chk_en : 1; + UI32_T tch_early_done_irq : 1; + UI32_T tch_chk_cos_en : 1; + UI32_T tch_adv_gpd_wrbk : 1; + UI32_T tch_gpd_wrbk_full_pkt_len : 1; + UI32_T : 8; + UI32_T : 8; + UI32_T : 8; + } field; +} HAL_TAU_PKT_TCH_CFG_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T tch_start : 1; + UI32_T tch_resume : 1; + UI32_T tch_stop : 1; + UI32_T : 5; + UI32_T : 8; + UI32_T tch_gpd_add_no_lo : 8; + UI32_T tch_gpd_add_no_hi : 8; + } field; +} HAL_TAU_PKT_TCH_CMD_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T tch_active : 1; + UI32_T tch_pfc : 1; + UI32_T tch_gpd_rd_dma_act : 1; + UI32_T : 5; + UI32_T : 8; + UI32_T tch_avbl_gpd_no : 1; + UI32_T : 7; + UI32_T : 8; + } field; +} HAL_TAU_PKT_TCH_STS_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T tch_gpd_dmar_qos : 4; + UI32_T : 4; + UI32_T tch_pkt_dmar_qos : 4; + UI32_T : 4; + UI32_T tch_gpd_dmaw_qos : 4; + UI32_T : 4; + UI32_T : 8; + } field; +} HAL_TAU_PKT_TCH_QOS_CFG_REG_T; + +#elif defined(NPS_EN_BIG_ENDIAN) + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 6; + UI32_T tch_ios_crdt_add_en : 1; + UI32_T tch_rready_low_4_hdr : 1; + UI32_T : 6; + UI32_T tch_arvalid_thrhold_cfg : 2; + UI32_T : 7; + UI32_T tch_axi_free_arvalid : 1; + UI32_T : 5; + UI32_T tch_axlen_cfg : 3; + } field; +} HAL_TAU_PKT_AXI_LEN_CFG_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 2; + UI32_T pm_lbk_rqid : 6; + UI32_T : 7; + UI32_T pm_lbk_en : 1; + UI32_T : 2; + UI32_T pdma_lbk_plane : 2; + UI32_T : 3; + UI32_T pdma_lbk_en : 1; + } field; +} HAL_TAU_PKT_LBK_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 2; + UI32_T pdma_lbk_rqid3 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid2 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid1 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid0 : 6; + } field; +} HAL_TAU_PKT_LBK_RQID0_3_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 2; + UI32_T pdma_lbk_rqid7 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid6 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid5 : 6; + UI32_T : 2; + UI32_T pdma_lbk_rqid4 : 6; + } field; +} HAL_TAU_PKT_LBK_RQID4_7_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T cos_pfc_sts3 : 8; + UI32_T cos_pfc_sts2 : 8; + UI32_T cos_pfc_sts1 : 8; + UI32_T cos_pfc_sts0 : 8; + } field; +} HAL_TAU_PKT_COS_PFC_STS_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 8; + UI32_T pdma_ela_valid_sel : 8; + UI32_T : 7; + UI32_T pdma_ela_en : 1; + } field; +} HAL_TAU_PKT_ELA_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T pdma_ela_word3_sel : 8; + UI32_T pdma_ela_word2_sel : 8; + UI32_T pdma_ela_word1_sel : 8; + UI32_T pdma_ela_word0_sel : 8; + } field; +} HAL_TAU_PKT_ELA_SEL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 6; + UI32_T ingr_pln_full_pkt_mode : 1; + UI32_T : 1; + UI32_T : 7; + UI32_T ingr_pln_ios_credit_set : 1; + UI32_T ingr_pln_ios_credit_base_size_hi : 8; + UI32_T ingr_pln_ios_credit_base_size_lo : 8; + } field; +} HAL_TAU_PKT_IGR_PLN_CREDIT_CFG_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 6; + UI32_T ingr_pln_ios_credit_udfl : 1; + UI32_T ingr_pln_ios_credit_ovfl : 1; + UI32_T ingr_pln_cur_ios_credit_hi : 8; + UI32_T ingr_pln_cur_ios_credit_lo : 8; + } field; +} HAL_TAU_PKT_IGR_PLN_CREDIT_STS_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 8; + UI32_T ingr_pln_ios_credit_rdy_hi_bound : 8; + UI32_T ingr_pln_ios_credit_rdy_lo_bound : 8; + } field; +} HAL_TAU_PKT_IGR_PLN_CREDIT_THR_REG_T; + + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 7; + UI32_T rch_pfc_fun_en : 1; + UI32_T : 7; + UI32_T rch_crc_regen_en : 1; + UI32_T : 7; + UI32_T rch_stomp_crc_en : 1; + } field; +} HAL_TAU_PKT_RCH_STOMP_CRC_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 8; + UI32_T : 7; + UI32_T rch_chksm_en : 1; + UI32_T : 7; + UI32_T rch_ioc_en : 1; + } field; +} HAL_TAU_PKT_RCH_MISC_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 8; + UI32_T rch_gpd_pfc_hi : 8; + UI32_T rch_gpd_pfc_lo : 8; + } field; +} HAL_TAU_PKT_RCH_GPD_PFC_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 5; + UI32_T rch_fifo_pfc_hi_hi : 3; + UI32_T rch_fifo_pfc_hi_lo : 8; + UI32_T : 5; + UI32_T rch_fifo_pfc_lo_hi : 3; + UI32_T rch_fifo_pfc_lo_lo : 8; + } field; +} HAL_TAU_PKT_RCH_FIFO_PFC_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 8; + UI32_T : 3; + UI32_T rch_cmdq_pfc_hi : 5; + UI32_T : 3; + UI32_T rch_cmdq_pfc_lo : 5; + } field; +} HAL_TAU_PKT_RCH_CMDQ_PFC_CTRL_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T rch_gpd_add_no_hi : 8; + UI32_T rch_gpd_add_no_lo : 8; + UI32_T : 8; + UI32_T : 5; + UI32_T rch_stop : 1; + UI32_T rch_resume : 1; + UI32_T rch_start : 1; + } field; +} HAL_TAU_PKT_RCH_CMD_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 8; + UI32_T : 8; + UI32_T : 2; + UI32_T rch_flush_cnt_clr : 1; + UI32_T rch_pkterr_drop_cnt_clr : 1; + UI32_T rch_udsz_drop_cnt_clr : 1; + UI32_T rch_ovsz_drop_cnt_clr : 1; + UI32_T rch_cmdq_ovf_drop_cnt_clr : 1; + UI32_T rch_fifo_ovf_drop_cnt_clr : 1; + } field; +} HAL_TAU_PKT_RCH_CNT_CLR_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T rch_avbl_gpd_no_hi : 8; + UI32_T rch_avbl_gpd_no_lo : 8; + UI32_T : 8; + UI32_T : 3; + UI32_T rch_pfc : 1; + UI32_T rch_cmdq_pfc : 1; + UI32_T rch_fifo_pfc : 1; + UI32_T rch_avbl_gpd_pfc : 1; + UI32_T rch_active : 1; + } field; +} HAL_TAU_PKT_RCH_STATUS_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 8; + UI32_T : 8; + UI32_T tch_gpd_wrbk_full_pkt_len : 1; + UI32_T tch_adv_gpd_wrbk : 1; + UI32_T tch_chk_cos_en : 1; + UI32_T tch_early_done_irq : 1; + UI32_T tch_pktlen_chk_en : 1; + UI32_T tch_pfc_en : 1; + UI32_T tch_chksm_en : 1; + UI32_T tch_ioc_en : 1; + } field; +} HAL_TAU_PKT_TCH_CFG_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T tch_gpd_add_no_hi : 8; + UI32_T tch_gpd_add_no_lo : 8; + UI32_T : 8; + UI32_T : 5; + UI32_T tch_stop : 1; + UI32_T tch_resume : 1; + UI32_T tch_start : 1; + } field; +} HAL_TAU_PKT_TCH_CMD_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 7; + UI32_T tch_avbl_gpd_no : 1; + UI32_T : 8; + UI32_T : 5; + UI32_T tch_gpd_rd_dma_act : 1; + UI32_T tch_pfc : 1; + UI32_T tch_active : 1; + } field; +} HAL_TAU_PKT_TCH_STS_REG_T; + +typedef union +{ + UI32_T reg; + struct + { + UI32_T : 8; + UI32_T : 4; + UI32_T tch_gpd_dmaw_qos : 4; + UI32_T : 4; + UI32_T tch_pkt_dmar_qos : 4; + UI32_T : 4; + UI32_T tch_gpd_dmar_qos : 4; + } field; +} HAL_TAU_PKT_TCH_QOS_CFG_REG_T; + +#else +#error "Host GPD endian is not defined\n" +#endif + +/* ----------------------------------------------------------------------------------- NPS_EN_NETIF */ +#if defined (NPS_EN_NETIF) +#define HAL_TAU_PKT_DRIVER_MAJOR_NUM (10) +#define HAL_TAU_PKT_DRIVER_MINOR_NUM (252) /* DO NOT use MISC_DYNAMIC_MINOR */ +#define HAL_TAU_PKT_DRIVER_NAME "nps_netif" +#define HAL_TAU_PKT_DRIVER_PATH "/dev/"HAL_TAU_PKT_DRIVER_NAME + +/* These requirements come from NPS_NETIF APIs. + * nps_netif -> hal_pkt_drv -> hal_pkt_knl + */ + +typedef struct +{ + UI32_T tx_pkt; + UI32_T tx_queue_full; + UI32_T tx_error; + UI32_T rx_pkt; + +} HAL_TAU_PKT_NETIF_INTF_CNT_T; + +typedef struct +{ + /* unique key */ + UI32_T id; + C8_T name[NPS_NETIF_NAME_LEN]; + UI32_T port; /* only support unit port and local port */ + + /* metadata */ + UI8_T mac[6]; + +#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; + + /* match fields */ + 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 (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; + + +/* These requirements come from NPS_PKT APIs. + * nps_pkt -> hal_pkt_srv -> hal_pkt_drv -> hal_pkt_knl + */ +typedef enum +{ + /* network interface */ + HAL_TAU_PKT_IOCTL_TYPE_CREATE_INTF = 0, + HAL_TAU_PKT_IOCTL_TYPE_DESTROY_INTF, + HAL_TAU_PKT_IOCTL_TYPE_GET_INTF, + HAL_TAU_PKT_IOCTL_TYPE_CREATE_PROFILE, + HAL_TAU_PKT_IOCTL_TYPE_DESTROY_PROFILE, + HAL_TAU_PKT_IOCTL_TYPE_GET_PROFILE, + HAL_TAU_PKT_IOCTL_TYPE_GET_INTF_CNT, + HAL_TAU_PKT_IOCTL_TYPE_CLEAR_INTF_CNT, + /* driver */ + HAL_TAU_PKT_IOCTL_TYPE_WAIT_RX_FREE, + HAL_TAU_PKT_IOCTL_TYPE_WAIT_TX_FREE, /* waitTxFree(ASYNC) */ + HAL_TAU_PKT_IOCTL_TYPE_SET_RX_CFG, /* setRxConfig */ + HAL_TAU_PKT_IOCTL_TYPE_GET_RX_CFG, /* getRxConfig */ + HAL_TAU_PKT_IOCTL_TYPE_DEINIT_TASK, /* deinitTask */ + HAL_TAU_PKT_IOCTL_TYPE_DEINIT_DRV, /* deinitDrv */ + HAL_TAU_PKT_IOCTL_TYPE_INIT_TASK, /* initTask */ + HAL_TAU_PKT_IOCTL_TYPE_INIT_DRV, /* initDrv */ + /* counter */ + HAL_TAU_PKT_IOCTL_TYPE_GET_TX_CNT, + HAL_TAU_PKT_IOCTL_TYPE_GET_RX_CNT, + HAL_TAU_PKT_IOCTL_TYPE_CLEAR_TX_CNT, + 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; + +typedef enum +{ + HAL_TAU_PKT_IOCTL_RX_TYPE_INIT = 0, + HAL_TAU_PKT_IOCTL_RX_TYPE_DEINIT, + HAL_TAU_PKT_IOCTL_RX_TYPE_LAST, + +} HAL_TAU_PKT_IOCTL_RX_TYPE_T; + +typedef struct +{ + UI32_T unit; + UI32_T channel; + HAL_TAU_PKT_RX_CNT_T rx_cnt; + HAL_TAU_PKT_TX_CNT_T tx_cnt; + NPS_ERROR_NO_T rc; + +} HAL_TAU_PKT_IOCTL_CH_CNT_COOKIE_T; + +typedef struct +{ + UI32_T unit; + HAL_TAU_PKT_NETIF_INTF_T net_intf; /* addIntf[In,Out], delIntf[In] */ + HAL_TAU_PKT_NETIF_PROFILE_T net_profile; /* createProfile[In,Out], destroyProfile[In] */ + HAL_TAU_PKT_NETIF_INTF_CNT_T cnt; + NPS_ERROR_NO_T rc; + +} HAL_TAU_PKT_IOCTL_NETIF_COOKIE_T; + +typedef struct +{ + NPS_ADDR_T callback; /* (unit, ptr_sw_gpd, ptr_cookie) */ + NPS_ADDR_T cookie; /* Pointer of NPS_PKT_TX_PKT_T */ + UI32_T channel; + UI32_T gpd_num; + NPS_ADDR_T hw_gpd_addr; + NPS_ADDR_T sw_gpd_addr; + +} HAL_TAU_PKT_IOCTL_TX_GPD_T; + +typedef struct +{ + UI32_T unit; + UI32_T channel; /* sendGpd[In] */ + NPS_ADDR_T ioctl_gpd_addr; /* sendGpd[In] */ + NPS_ADDR_T done_sw_gpd_addr; /* waitTxFree[Out] */ + +} HAL_TAU_PKT_IOCTL_TX_COOKIE_T; + +typedef struct +{ + BOOL_T rx_complete; /* FALSE when PDMA error occurs */ + NPS_ADDR_T hw_gpd_addr; /* Pointer to HW GPD in user's SW GPD struct */ + NPS_ADDR_T dma_buf_addr; /* Pointer to DMA buffer allocated by the user (virtual) */ + +} HAL_TAU_PKT_IOCTL_RX_GPD_T; + +typedef struct +{ + UI32_T unit; + UI32_T channel; /* getRxCnt[In], clearRxInt[In] */ + NPS_ADDR_T ioctl_gpd_addr; /* waitRxFree[Out] */ + UI32_T buf_len; /* setRxCfg[In] */ + HAL_TAU_PKT_IOCTL_RX_TYPE_T rx_type; /* setRxCfg[In] */ + +} HAL_TAU_PKT_IOCTL_RX_COOKIE_T; + +typedef struct +{ + UI32_T port; + UI32_T status; + UI32_T speed; + +} 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; + struct + { + UI32_T unit : 6; /* Maximum unit number is 64. */ + HAL_TAU_PKT_IOCTL_TYPE_T type : 10; /* Maximum 1024 IOCTL types */ + UI32_T rsvd : 16; + } field; + +} HAL_TAU_PKT_IOCTL_CMD_T; + + +#endif /* End of NPS_EN_NETIF */ + +NPS_ERROR_NO_T +hal_tau_pkt_sendGpd( + const UI32_T unit, + const HAL_TAU_PKT_TX_CHANNEL_T channel, + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd); + +/*---------------------------------------------------------------------------*/ +/* perf */ +NPS_ERROR_NO_T +hal_tau_pkt_getTxIntrCnt( + const UI32_T unit, + const UI32_T channel, + UI32_T *ptr_intr_cnt); + +NPS_ERROR_NO_T +hal_tau_pkt_getRxIntrCnt( + const UI32_T unit, + const UI32_T channel, + UI32_T *ptr_intr_cnt); + +/* ioctl */ +NPS_ERROR_NO_T +hal_tau_pkt_getTxKnlCnt( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_CH_CNT_COOKIE_T *ptr_cookie); + +NPS_ERROR_NO_T +hal_tau_pkt_getRxKnlCnt( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_CH_CNT_COOKIE_T *ptr_cookie); + +NPS_ERROR_NO_T +hal_tau_pkt_clearTxKnlCnt( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_TX_COOKIE_T *ptr_cookie); + +NPS_ERROR_NO_T +hal_tau_pkt_clearRxKnlCnt( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_RX_COOKIE_T *ptr_cookie); + +NPS_ERROR_NO_T +hal_tau_pkt_setRxKnlConfig( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_RX_COOKIE_T *ptr_cookie); + +NPS_ERROR_NO_T +hal_tau_pkt_getRxKnlConfig( + const UI32_T unit, + HAL_TAU_PKT_IOCTL_RX_COOKIE_T *ptr_cookie); + +/* perf */ +NPS_ERROR_NO_T +hal_tau_pkt_getNetDev( + const UI32_T unit, + const UI32_T port, + struct net_device **pptr_net_dev); + +NPS_ERROR_NO_T +hal_tau_pkt_prepareGpd( + const UI32_T unit, + const NPS_ADDR_T phy_addr, + const UI32_T len, + const UI32_T port, + HAL_TAU_PKT_TX_SW_GPD_T *ptr_sw_gpd); + +#endif /* end of HAL_TAU_PKT_KNL_H */ 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 new file mode 100755 index 000000000000..93f30fc61ce1 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/inc/netif_osal.h @@ -0,0 +1,379 @@ +/* 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_osal.h + * PURPOSE: + * It provide customer linux API. + * NOTES: + */ + +#ifndef NETIF_OSAL_H +#define NETIF_OSAL_H + +/* + * ENOMEM : 12 - Out of memory + * EFAULT : 14 - Bad address + * EBUSY : 16 - Device or resource busy + * ENODEV : 19 - No such device + * EINVAL : 22 - Invalid argument + + * + * NETDEV_TX_OK : 0x00 + * NETDEV_TX_BUSY : 0x10 + + * + * ETH_HLEN : 14 dmac + smac + etyp + * ETH_ZLEN : 60 minimum ethernet frame size + * ETH_DATA_LEN : 1500 + * ETH_FRAME_LEN : 1514 + * ETH_FCS_LEN : 4 + * + * ETH_P_IP : 0x0800 + * ETH_P_ARP : 0x0806 + * ETH_P_IPV6 : 0x86DD + * ETH_P_SLOW : 0x8809 + * ETH_P_1588 : 0x88F7 + + * + * NET_IP_ALIGN : 2 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* ----------------------------------------------------------------------------------- macro value */ +/* Thread */ +#define OSAL_THREAD_NAME_LEN (16) +#define OSAL_THREAD_DFT_NAME ("Unknown") + +/* Semaphore */ +#define OSAL_SEMA_NAME_LEN (16) +#define OSAL_SEMA_DFT_NAME ("Unknown") + +/* Event */ +#define OSAL_EVENT_NAME_LEN (16) +#define OSAL_EVENT_DFT_NAME ("Unknown") + +/* Spinlock */ +#define OSAL_SPIN_NAME_LEN (16) +#define OSAL_SPIN_DFT_NAME ("Unknown") + +/* Queue */ +#define OSAL_QUEUE_NAME_LEN (16) +#define OSAL_QUEUE_DFT_NAME ("Unknown") + +#define OSAL_PRN_BUF_SZ (256) +#define OSAL_TICKS_PER_SEC (1000000) + +/* ----------------------------------------------------------------------------------- struct */ +typedef struct linux_thread_s +{ + char name[OSAL_THREAD_NAME_LEN + 1]; + struct task_struct *ptr_task; + unsigned int is_stop; + struct linux_thread_s *ptr_prev; + struct linux_thread_s *ptr_next; + +} linux_thread_t; + +typedef struct +{ + char name[OSAL_SEMA_NAME_LEN + 1]; + struct semaphore lock; + +} linux_sema_t; + +typedef struct +{ + char name[OSAL_EVENT_NAME_LEN + 1]; + wait_queue_head_t wait_que; + unsigned int condition; + +} linux_event_t; + +typedef struct +{ + char name[OSAL_SPIN_NAME_LEN + 1]; + spinlock_t spinlock; + +} linux_isrlock_t; + +typedef struct +{ + void *ptr_data; +} linux_queue_entry_t; + +typedef struct +{ + char name[OSAL_QUEUE_NAME_LEN + 1]; + int head; /* index of the queue head entry can be read */ + int tail; /* index of the queue tail entry can be write */ + unsigned int wr_cnt; /* enqueue total count */ + unsigned int rd_cnt; /* dequeue total count */ + unsigned int capacity; /* the queue size */ + linux_queue_entry_t *ptr_entry; /* the queue entry buffer */ + +} linux_queue_t; + +typedef struct +{ + unsigned int size; + dma_addr_t phy_addr; + char data[0]; + +} linux_dma_t; + +/* ----------------------------------------------------------------------------------- function */ +void * +osal_memset( + void *ptr_mem, + const I32_T value, + const UI32_T num); + +void * +osal_memcpy( + void *ptr_dst, + const void *ptr_src, + const UI32_T num); + +UI32_T +osal_strlen( + const C8_T *ptr_str); + +void +osal_printf( + const C8_T *ptr_fmt, + ...); + +void * +osal_alloc( + const UI32_T size); + +void +osal_free( + const void *ptr_mem); + +/* thread */ +NPS_ERROR_NO_T +osal_init(void); + +NPS_ERROR_NO_T +osal_deinit(void); + +NPS_ERROR_NO_T +osal_createThread ( + const C8_T *ptr_thread_name, + const UI32_T stack_size, + const UI32_T priority, + void (function)(void*), + void *ptr_arg, + NPS_THREAD_ID_T *ptr_thread_id); + +NPS_ERROR_NO_T +osal_stopThread( + NPS_THREAD_ID_T *ptr_thread_id); + +NPS_ERROR_NO_T +osal_destroyThread( + NPS_THREAD_ID_T *ptr_thread_id); + +void +osal_initRunThread( + void); + +NPS_ERROR_NO_T +osal_isRunThread( + void); + +void +osal_exitRunThread( + void); + +/* semaphore */ +NPS_ERROR_NO_T +osal_createSemaphore( + const C8_T *ptr_sema_name, + const UI32_T sema_count, + NPS_SEMAPHORE_ID_T *ptr_semaphore_id); + +NPS_ERROR_NO_T +osal_takeSemaphore( + NPS_SEMAPHORE_ID_T *ptr_semaphore_id, + UI32_T time_out); + +NPS_ERROR_NO_T +osal_giveSemaphore( + NPS_SEMAPHORE_ID_T *ptr_semaphore_id); + +NPS_ERROR_NO_T +osal_destroySemaphore( + NPS_SEMAPHORE_ID_T *ptr_semaphore_id); + +/* event */ +NPS_ERROR_NO_T +osal_createEvent( + const C8_T *ptr_event_name, + NPS_SEMAPHORE_ID_T *ptr_event_id); + +NPS_ERROR_NO_T +osal_waitEvent( + NPS_SEMAPHORE_ID_T *ptr_event_id); + +NPS_ERROR_NO_T +osal_triggerEvent( + NPS_SEMAPHORE_ID_T *ptr_event_id); + +NPS_ERROR_NO_T +osal_destroyEvent( + NPS_SEMAPHORE_ID_T *ptr_event_id); + +/* isr_lock */ +NPS_ERROR_NO_T +osal_createIsrLock( + const C8_T *ptr_isrlock_name, + NPS_ISRLOCK_ID_T *ptr_isrlock_id); + +NPS_ERROR_NO_T +osal_takeIsrLock( + NPS_ISRLOCK_ID_T *ptr_isrlock_id, + NPS_IRQ_FLAGS_T *ptr_irq_flags); + +NPS_ERROR_NO_T +osal_giveIsrLock( + NPS_ISRLOCK_ID_T *ptr_isrlock_id, + NPS_IRQ_FLAGS_T *ptr_irq_flags); + +NPS_ERROR_NO_T +osal_destroyIsrLock( + NPS_ISRLOCK_ID_T *ptr_isrlock_id); + +/* timer */ +NPS_ERROR_NO_T +osal_sleepThread( + const UI32_T usecond); + +NPS_ERROR_NO_T +osal_getTime( + NPS_TIME_T *ptr_time); + +/* queue */ +NPS_ERROR_NO_T +osal_que_create( + NPS_HUGE_T *ptr_queue_id, + UI32_T capacity); + +NPS_ERROR_NO_T +osal_que_enque( + NPS_HUGE_T *ptr_queue_id, + void *ptr_data); + +NPS_ERROR_NO_T +osal_que_deque( + NPS_HUGE_T *ptr_queue_id, + void **pptr_data); + +NPS_ERROR_NO_T +osal_que_destroy( + NPS_HUGE_T *ptr_queue_id); + +NPS_ERROR_NO_T +osal_que_getCount( + NPS_HUGE_T *ptr_queue_id, + unsigned int *ptr_count); + +/* IO */ +int +osal_io_copyToUser( + void *ptr_usr_buf, + void *ptr_knl_buf, + unsigned int size); + +int +osal_io_copyFromUser( + void *ptr_knl_buf, + void *ptr_usr_buf, + unsigned int size); + +/* dma */ +void * +osal_dma_alloc( + const UI32_T size); + +NPS_ERROR_NO_T +osal_dma_free( + void *ptr_dma_mem); + +dma_addr_t +osal_dma_convertVirtToPhy( + void *ptr_virt_addr); + +void * +osal_dma_convertPhyToVirt( + const dma_addr_t phy_addr); + +int +osal_dma_flushCache( + void *ptr_virt_addr, + const unsigned int size); + +int +osal_dma_invalidateCache( + void *ptr_virt_addr, + const unsigned int size); + +/* skb */ +struct sk_buff * +osal_skb_alloc( + UI32_T size); + +void +osal_skb_free( + struct sk_buff *ptr_skb); + +dma_addr_t +osal_skb_mapDma( + struct sk_buff *ptr_skb, + enum dma_data_direction dir); + +void +osal_skb_unmapDma( + const dma_addr_t phy_addr, + UI32_T size, + enum dma_data_direction dir); + +void +osal_skb_send( + struct sk_buff *ptr_skb); + +void +osal_skb_recv( + struct sk_buff *ptr_skb); + +#endif /* end of NETIF_OSAL_H */ diff --git a/platform/nephos/nephos-modules/modules/src/inc/netif_perf.h b/platform/nephos/nephos-modules/modules/src/inc/netif_perf.h new file mode 100755 index 000000000000..5309f01b62d8 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/inc/netif_perf.h @@ -0,0 +1,81 @@ +/* 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_perf.h + * PURPOSE: + * It provide customer performance test API. + * NOTES: + */ + +#ifndef NETIF_PERF_H +#define NETIF_PERF_H + +/* #define PERF_EN_TEST */ + +/* FUNCTION NAME: perf_rxCallback + * PURPOSE: + * To count the Rx-gpd for Rx-test. + * INPUT: + * len -- To check if the Rx-gpd length equals to test length. + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successful operation. + * NOTES: + * None + */ +NPS_ERROR_NO_T +perf_rxCallback( + const UI32_T len); + +/* FUNCTION NAME: perf_rxTest + * PURPOSE: + * To check if Rx-test is going. + * INPUT: + * None + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successful operation. + * NOTES: + * None + */ +NPS_ERROR_NO_T +perf_rxTest( + void); + +/* FUNCTION NAME: perf_test + * PURPOSE: + * To do Tx-test or Rx-test. + * INPUT: + * len -- Test length + * tx_channel -- Test Tx channel numbers + * rx_channel -- Test Rx channel numbers + * test_skb -- Test GPD or SKB + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successful operation. + * NOTES: + * None + */ +NPS_ERROR_NO_T +perf_test( + UI32_T len, + UI32_T tx_channel, + UI32_T rx_channel, + BOOL_T test_skb); + +#endif /* end of NETIF_PERF_H */ diff --git a/platform/nephos/nephos-modules/modules/src/inc/nps_cfg.h b/platform/nephos/nephos-modules/modules/src/inc/nps_cfg.h new file mode 100755 index 000000000000..36de3cc70863 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/inc/nps_cfg.h @@ -0,0 +1,317 @@ +/* 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: nps_cfg.h + * PURPOSE: + * Customer configuration on NPS SDK. + * NOTES: + */ + +#ifndef NPS_CFG_H +#define NPS_CFG_H + +/* INCLUDE FILE DECLARATIONS + */ + +#include +#include + + +/* NAMING CONSTANT DECLARATIONS + */ + +/* MACRO FUNCTION DECLARATIONS + */ +#define NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM (16) +#define NPS_CFG_USER_PORT_NUM (96) + +/* DATA TYPE DECLARATIONS + */ +typedef enum +{ + NPS_CFG_TYPE_CHIP_MODE, /* chip operating mode. 0: legacy mode, 1:hybrid mode */ + + NPS_CFG_TYPE_PORT_MAX_SPEED, /* Reference to NPS_PORT_SPEED_XXX */ + NPS_CFG_TYPE_PORT_LANE_NUM, + NPS_CFG_TYPE_PORT_TX_LANE, + NPS_CFG_TYPE_PORT_RX_LANE, + NPS_CFG_TYPE_PORT_TX_POLARITY_REV, + NPS_CFG_TYPE_PORT_RX_POLARITY_REV, + NPS_CFG_TYPE_PORT_EXT_LANE, + NPS_CFG_TYPE_PORT_VALID, + + /* l2 module related configuration */ + NPS_CFG_TYPE_L2_THREAD_PRI, + NPS_CFG_TYPE_L2_THREAD_STACK, /* customize L2 thread stack size in bytes */ + NPS_CFG_TYPE_L2_ADDR_MODE, /* L2 address operation mode. 0: Polling mode, 1: FIFO mode */ + + /* PKT module related configuration */ + NPS_CFG_TYPE_PKT_TX_GPD_NUM, + NPS_CFG_TYPE_PKT_RX_GPD_NUM, + NPS_CFG_TYPE_PKT_RX_SCHED_MODE, /* 0: RR mode, 1: WRR mode */ + NPS_CFG_TYPE_PKT_TX_QUEUE_LEN, + NPS_CFG_TYPE_PKT_RX_QUEUE_LEN, + NPS_CFG_TYPE_PKT_RX_QUEUE_WEIGHT, /* valid while NPS_CFG_TYPE_PKT_RX_SCHED_MODE is 1 + * param0: queue + * param1: NA + * value : weight + */ + NPS_CFG_TYPE_PKT_RX_ISR_THREAD_PRI, + NPS_CFG_TYPE_PKT_RX_ISR_THREAD_STACK, /* customize PKT RX ISR thread stack size in bytes */ + NPS_CFG_TYPE_PKT_RX_FREE_THREAD_PRI, + NPS_CFG_TYPE_PKT_RX_FREE_THREAD_STACK, /* customize PKT RX free thread stack size in bytes */ + NPS_CFG_TYPE_PKT_TX_ISR_THREAD_PRI, + NPS_CFG_TYPE_PKT_TX_ISR_THREAD_STACK, /* customize PKT TX ISR thread stack size in bytes */ + NPS_CFG_TYPE_PKT_TX_FREE_THREAD_PRI, + NPS_CFG_TYPE_PKT_TX_FREE_THREAD_STACK, /* customize PKT TX free thread stack size in bytes */ + NPS_CFG_TYPE_PKT_ERROR_ISR_THREAD_PRI, + NPS_CFG_TYPE_PKT_ERROR_ISR_THREAD_STACK, /* customize PKT ERROR ISR thread stack size in bytes */ + + /* STAT module related configuration */ + NPS_CFG_TYPE_CNT_THREAD_PRI, + NPS_CFG_TYPE_CNT_THREAD_STACK, /* customize CNT thread stack size in bytes */ + + /* IFMON module related configuration */ + NPS_CFG_TYPE_IFMON_THREAD_PRI, + NPS_CFG_TYPE_IFMON_THREAD_STACK, /* customize IFMON thread stack size in bytes */ + + /* share memory related configuration */ + NPS_CFG_TYPE_SHARE_MEM_SDN_ENTRY_NUM, /* SDN flow table entry number from share memory */ + NPS_CFG_TYPE_SHARE_MEM_L3_ENTRY_NUM, /* L3 entry number from share memory */ + NPS_CFG_TYPE_SHARE_MEM_L2_ENTRY_NUM, /* L2 entry number from share memory */ + + /* DLB related configuration */ + NPS_CFG_TYPE_DLB_MONITOR_MODE, /* DLB monitor mode. 1: async, 0: sync */ + NPS_CFG_TYPE_DLB_LAG_MONITOR_THREAD_PRI, + NPS_CFG_TYPE_DLB_LAG_MONITOR_THREAD_SLEEP_TIME, + NPS_CFG_TYPE_DLB_L3_MONITOR_THREAD_PRI, + NPS_CFG_TYPE_DLB_L3_MONITOR_THREAD_SLEEP_TIME, + NPS_CFG_TYPE_DLB_L3_INTR_THREAD_PRI, + NPS_CFG_TYPE_DLB_NVO3_MONITOR_THREAD_PRI, + NPS_CFG_TYPE_DLB_NVO3_MONITOR_THREAD_SLEEP_TIME, + NPS_CFG_TYPE_DLB_NVO3_INTR_THREAD_PRI, + + /* l3 related configuration */ + NPS_CFG_TYPE_L3_ECMP_MIN_BLOCK_SIZE, + NPS_CFG_TYPE_L3_ECMP_BLOCK_SIZE, + NPS_CFG_TYPE_TCAM_L3_WITH_IPV6_PREFIX_128_REGION_ENTRY_NUM, + NPS_CFG_TYPE_TCAM_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM, + + /* share memory related configuration */ + NPS_CFG_TYPE_HASH_L2_FDB_REGION_ENTRY_NUM, + NPS_CFG_TYPE_HASH_L2_GROUP_REGION_ENTRY_NUM, + NPS_CFG_TYPE_HASH_SECURITY_REGION_ENTRY_NUM, + NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_128_REGION_ENTRY_NUM, + NPS_CFG_TYPE_HASH_L3_WITH_IPV6_PREFIX_64_REGION_ENTRY_NUM, + NPS_CFG_TYPE_HASH_L3_WITHOUT_PREFIX_REGION_ENTRY_NUM, + NPS_CFG_TYPE_HASH_L3_RPF_REGION_ENTRY_NUM, + NPS_CFG_TYPE_HASH_FLOW_REGION_ENTRY_NUM, + + NPS_CFG_TYPE_PORT_FC_MODE, /* only use to init port TM buffer + * configuration for specific FC mode, + * which not enable/disable FC/PFC + * for the port/pcp. + * param0: port. + * param1: Invalid. + * value : 0, FC disable; + * 1, 802.3x FC; + * 2, PFC. + */ + NPS_CFG_TYPE_PORT_PFC_STATE, /* valid while NPS_CFG_TYPE_PORT_TYPE_FC_MODE + * of the port is PFC. + * param0: port. + * param1: pcp. + * value : 0, PFC disable; + * 1, PFC enable. + */ + NPS_CFG_TYPE_PORT_PFC_QUEUE_STATE, /* valid while NPS_CFG_TYPE_PORT_TYPE_FC_MODE + * of the port is PFC. + * param0: port. + * param1: queue. + * value : 0, PFC disable; + * 1, PFC enable; + */ + NPS_CFG_TYPE_PORT_PFC_MAPPING, /* valid while NPS_CFG_TYPE_PORT_FC_MODE + * of the port is PFC. + * param0: port. + * param1: queue. + * value : PCP bitmap; + * + */ + NPS_CFG_TYPE_TRILL_ENABLE, /* TRILL module related configuration */ + NPS_CFG_TYPE_USE_UNIT_PORT, /* use UNIT_PORT or native port of NPS_PORT_T + * 1 : UNIT_PORT, 0 : native port + */ + NPS_CFG_TYPE_MAC_VLAN_ENABLE, /* use dadicate mac vlan table */ + NPS_CFG_TYPE_CPI_PORT_MODE, /* use to init CPI port working mode. + * param0: CPI port number. + * param1: NA. + * value : 0, CPI mode. + * 1, Ether mode. + */ + NPS_CFG_TYPE_PHY_ADDR, + NPS_CFG_TYPE_LED_CFG, + NPS_CFG_TYPE_USER_BUF_CTRL, + NPS_CFG_TYPE_ARIES_SDP_MODE, /* Select which Aries parser to use + * value: 0, GTP (default) + * 1, PPPOE + * 2, TCP_SPLICING + */ + NPS_CFG_TYPE_FAIR_BUF_CTRL, /* to enable the fairness in flow-control traffic. + * value : 0, disable fairness. + * 1, enable fairness. + */ + NPS_CFG_TYPE_HRM_BUF_SIZE, /* to assign the head room size of port speed. + * param0: Port speed. + * 0, 1G (default) + * 1, 10G + * 2, 25G + * 3, 40G + * 4, 50G + * 5, 100G + * value : cell number. + */ + NPS_CFG_TYPE_STEERING_TRUNCATE_ENABLE, /* set value 0: Do not truncate steering packets. + * set value 1: steering packets will be trucated to 1 cell and + * the cell size is based on chip. + */ + NPS_CFG_TYPE_FABRIC_MODE_ENABLE, /* set value 0: Non-farbic chip mode. (default) + * set value 1: Fabric chip mode. + */ + NPS_CFG_TYPE_ACL_TCP_FLAGS_ENCODE_ENABLE, /* set value 0: Do not encode tcp flags at acl entry. + * (Can only match bit 0-6 of tcp flags.) + * set value 1: Encode tcp flags at acl entry. (default) + */ + NPS_CFG_TYPE_TCAM_ECC_SCAN_ENABLE, /* set value 0: Disable ECC TCAM scanning. (default) + * set value 1: Enable ECC TCAM scanning. + */ + NPS_CFG_TYPE_PORT_BUF_MAX, /* + * Port max buffer threshold and unit is cell count. + * param0: port. + * param1: 0, ingress; + * 1, egress. + * value : 0, disable; + * others, enable max threshold. + */ + NPS_CFG_TYPE_INGRESS_DYNAMIC_BUF, /* + * Queue dynamic alpha setting and value will be + * enlarge to multiple of 256. For example, set value + * as 16 to indicate alpha as 1/16. Set value + * as 256 to indicate alpha as 1. + * param0: port. + * param1: queue (0~7: sc). + * value : alpha * 256. + */ + NPS_CFG_TYPE_EGRESS_DYNAMIC_BUF, /* + * Queue dynamic alpha setting and value will be + * enlarge to multiple of 256. For example, set value + * as 16 to indicate alpha as 1/16. Set value + * as 256 to indicate alpha as 1. + * param0: port. + * param1: queue (0~7: uc, 8~15: mc). + * value : alpha * 256. + */ + + + NPS_CFG_TYPE_DCQCN_ENABLE, /* set value 0: Disable DCQCN. (default) + * set value 1: Enable DCQCN. + */ + + + NPS_CFG_TYPE_LAST + +}NPS_CFG_TYPE_T; + +typedef struct NPS_CFG_VALUE_S +{ + UI32_T param0; /*(Optional) The optional parameter which is available + * when the NPS_CFG_TYPE_T needs the first arguments*/ + UI32_T param1; /*(Optional) The optional parameter which is available + * when the NPS_CFG_TYPE_T needs the second arguments*/ + I32_T value; + +}NPS_CFG_VALUE_T; + +typedef NPS_ERROR_NO_T + (*NPS_CFG_GET_FUNC_T)( + const UI32_T unit, + const NPS_CFG_TYPE_T cfg_type, + NPS_CFG_VALUE_T *ptr_cfg_value); + +typedef NPS_ERROR_NO_T + (*NPS_CFG_GET_LED_FUNC_T) +( + const UI32_T unit, + UI32_T **pptr_led_cfg, + UI32_T *ptr_cfg_size); + +/* EXPORTED SUBPROGRAM SPECIFICATIONS + */ + +/* FUNCTION NAME: nps_cfg_register + * PURPOSE: + * The function is to register NPS_CFG_GET_FUNC to SDK. + * + * INPUT: + * unit -- Device unit number. + * ptr_cfg_callback -- function to get the configuration value. + * + * OUTPUT: + * None + * + * RETURN: + * NPS_E_OK -- Operate success. + * NPS_E_BAD_PARAMETER -- Bad parameter. + * + * NOTES: + * 1. During SDK initializtion, it will call registered NPS_CFG_GET_FUNC to get configuration + * and apply them. + * If No registered NPS_CFG_GET_FUNC or can not get specified NPS_CFG_TYPE_T + * configuration, SDK will apply default setting. + * 2. This function should be called before calling nps_init + */ +NPS_ERROR_NO_T +nps_cfg_register( + const UI32_T unit, + NPS_CFG_GET_FUNC_T ptr_cfg_callback); + +/* FUNCTION NAME: nps_cfg_led_register + * PURPOSE: + * The function is to register NPS_CFG_GET_FUNC to SDK. + * + * INPUT: + * unit -- Device unit number. + * ptr_led_cfg_callback -- function to get LED configuration array. + * + * OUTPUT: + * None + * + * RETURN: + * NPS_E_OK -- Operate success. + * NPS_E_BAD_PARAMETER -- Bad parameter. + * + * NOTES: + * 1. During SDK initializtion, it will call registered NPS_CFG_GET_FUNC to get configuration + * and apply them. + * If No registered NPS_CFG_GET_LED_FUNC or can not get specified external LED cfg + * configuration, SDK will apply default setting. + * 2. This function should be called before calling nps_init + */ +NPS_ERROR_NO_T +nps_cfg_led_register( + const UI32_T unit, + NPS_CFG_GET_LED_FUNC_T ptr_led_cfg_callback); + +#endif /* NPS_CFG_H */ diff --git a/platform/nephos/nephos-modules/modules/src/inc/nps_error.h b/platform/nephos/nephos-modules/modules/src/inc/nps_error.h new file mode 100755 index 000000000000..3cf0a14adc0b --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/inc/nps_error.h @@ -0,0 +1,77 @@ +/* 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: nps_error.h + * PURPOSE: + * Define the generic error code on NPS SDK. + * NOTES: + */ + +#ifndef NPS_ERROR_H +#define NPS_ERROR_H + +/* INCLUDE FILE DECLARATIONS + */ +#include + + +/* NAMING CONSTANT DECLARATIONS + */ + +/* MACRO FUNCTION DECLARATIONS + */ + +/* DATA TYPE DECLARATIONS + */ + +typedef enum +{ + NPS_E_OK = 0, /* Ok and no error */ + NPS_E_BAD_PARAMETER, /* Parameter is wrong */ + NPS_E_NO_MEMORY, /* No memory is available */ + NPS_E_TABLE_FULL, /* Table is full */ + NPS_E_ENTRY_NOT_FOUND, /* Entry is not found */ + NPS_E_ENTRY_EXISTS, /* Entry already exists */ + NPS_E_NOT_SUPPORT, /* Feature is not supported */ + NPS_E_ALREADY_INITED, /* Module is reinitialized */ + NPS_E_NOT_INITED, /* Module is not initialized */ + NPS_E_OTHERS, /* Other errors */ + NPS_E_ENTRY_IN_USE, /* Entry is in use */ + NPS_E_LAST +} NPS_ERROR_NO_T; + +/* EXPORTED SUBPROGRAM SPECIFICATIONS + */ +/* FUNCTION NAME: nps_error_getString + * PURPOSE: + * To obtain the error string of the specified error code + * + * INPUT: + * cause -- The specified error code + * OUTPUT: + * None + * RETURN: + * Pointer to the target error string + * + * NOTES: + * + * + */ +C8_T * +nps_error_getString( + const NPS_ERROR_NO_T cause ); + +#endif /* NPS_ERROR_H */ + diff --git a/platform/nephos/nephos-modules/modules/src/inc/nps_types.h b/platform/nephos/nephos-modules/modules/src/inc/nps_types.h new file mode 100755 index 000000000000..88100f69738f --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/inc/nps_types.h @@ -0,0 +1,308 @@ +/* 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: nps_types.h + * PURPOSE: + * Define the commom data type in NPS SDK. + * NOTES: + */ + +#ifndef NPS_TYPES_H +#define NPS_TYPES_H + +/* INCLUDE FILE DECLARATIONS + */ + +#include + +/* NAMING CONSTANT DECLARATIONS + */ + +#define NPS_BIT_OFF 0 +#define NPS_BIT_ON 1 + +#define NPS_PORT_INVALID (0xFFFFFFFF) +#define NPS_SEG_INVALID (0xFFFFFFFF) + +/* for CPU Rx packet, indicate that the packet + * is not received from remote switch + */ +#define NPS_PATH_INVALID (0xFFFFFFFF) + + +#define NPS_SEMAPHORE_BINARY (1) +#define NPS_SEMAPHORE_SYNC (0) +#define NPS_SEMAPHORE_WAIT_FOREVER (0xFFFFFFFF) + +/* MACRO FUNCTION DECLARATIONS + */ +#if defined(NPS_EN_HOST_32_BIT_BIG_ENDIAN) || defined(NPS_EN_HOST_32_BIT_LITTLE_ENDIAN) +typedef unsigned int NPS_HUGE_T; +#elif defined(NPS_EN_HOST_64_BIT_BIG_ENDIAN) || defined(NPS_EN_HOST_64_BIT_LITTLE_ENDIAN) +typedef unsigned long long int NPS_HUGE_T; +#else +#error "The 32bit and 64bit compatible data type are not defined !!" +#endif + +#if defined(NPS_EN_64BIT_ADDR) +typedef unsigned long long int NPS_ADDR_T; +#else +typedef NPS_HUGE_T NPS_ADDR_T; +#endif + +#if defined(NPS_EN_HOST_64_BIT_BIG_ENDIAN) || defined(NPS_EN_HOST_64_BIT_LITTLE_ENDIAN) || defined(NPS_EN_64BIT_ADDR) +#define NPS_ADDR_64_HI(__addr__) ((__addr__) >> 32) +#define NPS_ADDR_64_LOW(__addr__) ((__addr__) & 0xFFFFFFFF) +#define NPS_ADDR_32_TO_64(__hi32__,__low32__) (((unsigned long long int)(__low32__)) | \ + (((unsigned long long int)(__hi32__)) << 32)) +#else +#define NPS_ADDR_64_HI(__addr__) (0) +#define NPS_ADDR_64_LOW(__addr__) (__addr__) +#define NPS_ADDR_32_TO_64(__hi32__,__low32__) (__low32__) +#endif + +#define NPS_BITMAP_SIZE(bit_num) ((((bit_num) - 1) / 32) + 1) +#define NPS_IPV4_IS_MULTICAST(addr) (0xE0000000 == ((addr) & 0xF0000000)) +#define NPS_IPV6_IS_MULTICAST(addr) (0xFF == (((UI8_T *)(addr))[0])) +#define NPS_MAC_IS_MULTICAST(mac) ((mac[0]) & (0x1)) + +/* DATA TYPE DECLARATIONS + */ +typedef UI8_T NPS_BIT_MASK_8_T; +typedef UI16_T NPS_BIT_MASK_16_T; +typedef UI32_T NPS_BIT_MASK_32_T; +typedef UI64_T NPS_BIT_MASK_64_T; + +typedef UI8_T NPS_MAC_T[6]; +typedef UI32_T NPS_IPV4_T; +typedef UI8_T NPS_IPV6_T[16]; + +typedef UI32_T NPS_TIME_T; + +/* Bridge Domain id data type. */ +typedef UI32_T NPS_BRIDGE_DOMAIN_T; + +/* TRILL nickname type. */ +typedef UI16_T NPS_TRILL_NICKNAME_T; + +typedef union NPS_IP_U +{ + + NPS_IPV4_T ipv4_addr; + NPS_IPV6_T ipv6_addr; + +}NPS_IP_T; + +typedef struct NPS_IP_ADDR_S +{ + NPS_IP_T ip_addr; + BOOL_T ipv4 ; +}NPS_IP_ADDR_T; + +/* Tunnel type*/ +typedef enum +{ + NPS_TUNNEL_TYPE_IPV4INIPV4 = 0, /* RFC2003, IPv4-in-IPv4 tunnel */ + NPS_TUNNEL_TYPE_IPV4INIPV6, /* RFC2003, IPv4-in-IPv6 tunnel */ + NPS_TUNNEL_TYPE_IPV6INIPV4, /* RFC2003, IPv6-in-IPv4 tunnel */ + NPS_TUNNEL_TYPE_IPV6INIPV6, /* RFC2003, IPv6-in-IPv6 tunnel */ + NPS_TUNNEL_TYPE_GREIPV4INIPV4, /* RFC2784/RFC2890,GRE IPv4-in-IPv4 tunnel */ + NPS_TUNNEL_TYPE_GREIPV6INIPV4, /* RFC2784/RFC2890,GRE IPv6-in-IPv4 tunnel */ + NPS_TUNNEL_TYPE_GREIPV4INIPV6, /* RFC2784/RFC2890,GRE IPv4-in-IPv6 tunnel */ + NPS_TUNNEL_TYPE_GREIPV6INIPV6, /* RFC2784/RFC2890,GRE IPv6-in-IPv6 tunnel */ + NPS_TUNNEL_TYPE_GRE_NSH, + NPS_TUNNEL_TYPE_6TO4, /* RFC3056, 6to4 tunnel*/ + NPS_TUNNEL_TYPE_ISATAP, /* RFC5214, ISATAP tunnel */ + NPS_TUNNEL_TYPE_NVGRE_L2, + NPS_TUNNEL_TYPE_NVGRE_V4, + NPS_TUNNEL_TYPE_NVGRE_V6, + NPS_TUNNEL_TYPE_NVGRE_NSH, + NPS_TUNNEL_TYPE_VXLAN, + NPS_TUNNEL_TYPE_GTP_V4, + NPS_TUNNEL_TYPE_GTP_V6, + NPS_TUNNEL_TYPE_MPLSINGRE, + NPS_TUNNEL_TYPE_VXLANGPE_L2, + NPS_TUNNEL_TYPE_VXLANGPE_V4, + NPS_TUNNEL_TYPE_VXLANGPE_V6, + NPS_TUNNEL_TYPE_VXLANGPE_NSH, + NPS_TUNNEL_TYPE_FLEX0_L2, + NPS_TUNNEL_TYPE_FLEX0_V4, + NPS_TUNNEL_TYPE_FLEX0_V6, + NPS_TUNNEL_TYPE_FLEX0_NSH, + NPS_TUNNEL_TYPE_FLEX1_L2, + NPS_TUNNEL_TYPE_FLEX1_V4, + NPS_TUNNEL_TYPE_FLEX1_V6, + NPS_TUNNEL_TYPE_FLEX1_NSH, + NPS_TUNNEL_TYPE_FLEX2_L2, + NPS_TUNNEL_TYPE_FLEX2_V4, + NPS_TUNNEL_TYPE_FLEX2_V6, + NPS_TUNNEL_TYPE_FLEX2_NSH, + NPS_TUNNEL_TYPE_FLEX3_L2, + NPS_TUNNEL_TYPE_FLEX3_V4, + NPS_TUNNEL_TYPE_FLEX3_V6, + NPS_TUNNEL_TYPE_FLEX3_NSH, + NPS_TUNNEL_TYPE_LAST +} NPS_TUNNEL_TYPE_T; + +/* tunnel key */ +typedef struct NPS_TUNNEL_KEY_S +{ + NPS_IP_ADDR_T src_ip; /* key: The outer source IP address used by tunnel encapsulation.*/ + NPS_IP_ADDR_T dst_ip; /* key: The outer destination IP address used by tunnel encapsulation. + * For automatic tunnel, this is not required. If not specified, + * its ip address value must be set to 0, but the IP version + * must be same with src_ip. + */ + NPS_TUNNEL_TYPE_T tunnel_type; /*key: The tunnel type.*/ +}NPS_TUNNEL_KEY_T; + +typedef UI16_T NPS_VLAN_T; +typedef UI32_T NPS_PORT_T; + +typedef enum{ + NPS_PORT_TYPE_NORMAL = 0, + NPS_PORT_TYPE_UNIT_PORT, + NPS_PORT_TYPE_LAG, + NPS_PORT_TYPE_VM_ETAG, + NPS_PORT_TYPE_VM_VNTAG, + NPS_PORT_TYPE_VM_VEPA, + NPS_PORT_TYPE_FCOE, + NPS_PORT_TYPE_IP_TUNNEL, + NPS_PORT_TYPE_TRILL, + NPS_PORT_TYPE_MPLS, + NPS_PORT_TYPE_MPLS_PW, + NPS_PORT_TYPE_CPU_PORT, + NPS_PORT_TYPE_SFC, + NPS_PORT_TYPE_LAST +}NPS_PORT_TYPE_T; + +/*support Green/Yellow/Red color*/ +typedef enum +{ + NPS_COLOR_GREEN = 0, + NPS_COLOR_YELLOW, + NPS_COLOR_RED, + NPS_COLOR_LAST +}NPS_COLOR_T; +typedef enum +{ + NPS_FWD_ACTION_FLOOD = 0, + NPS_FWD_ACTION_NORMAL, + NPS_FWD_ACTION_DROP, + NPS_FWD_ACTION_COPY_TO_CPU, + NPS_FWD_ACTION_REDIRECT_TO_CPU, + NPS_FWD_ACTION_FLOOD_COPY_TO_CPU, + NPS_FWD_ACTION_DROP_COPY_TO_CPU, + NPS_FWD_ACTION_LAST +} NPS_FWD_ACTION_T; + +typedef NPS_HUGE_T NPS_THREAD_ID_T; +typedef NPS_HUGE_T NPS_SEMAPHORE_ID_T; +typedef NPS_HUGE_T NPS_ISRLOCK_ID_T; +typedef NPS_HUGE_T NPS_IRQ_FLAGS_T; + +typedef enum +{ + NPS_DIR_INGRESS = 0, + NPS_DIR_EGRESS, + NPS_DIR_BOTH, + NPS_DIR_LAST +}NPS_DIR_T; + +typedef enum +{ + NPS_VLAN_ACTION_SET, + NPS_VLAN_ACTION_KEEP, + NPS_VLAN_ACTION_REMOVE, + NPS_VLAN_ACTION_LAST +} NPS_VLAN_ACTION_T; + +/* VLAN Precedence */ +/* 000 = SUBNET_PROTOCOL_MAC_PORT + * 001 = SUBNET_MAC_PROTOCOL_PORT + * 010 = PROTOCOL_SUBNET_MAC_PORT + * 011 = PROTOCOL_MAC_SUBNET_PORT + * 100 = MAC_SUBNET_PROTOCOL_PORT + * 101 = MAC_PROTOCOL_SUBNET_PORT + */ +typedef enum +{ + NPS_VLAN_PRECEDENCE_SUBNET_MAC_PROTOCOL_PORT = 1, + NPS_VLAN_PRECEDENCE_MAC_SUBNET_PROTOCOL_PORT = 4, + NPS_VLAN_PRECEDENCE_PORT_ONLY = 7, + NPS_VLAN_PRECEDENCE_FAVOR_TYPE = 8, + NPS_VLAN_PRECEDENCE_FAVOR_ADDR = 9, + NPS_VLAN_PRECEDENCE_LAST +} NPS_VLAN_PRECEDENCE_T; + +/* VLAN Tag Type */ +typedef enum +{ + NPS_VLAN_TAG_NONE = 0, /* UnTag */ + NPS_VLAN_TAG_SINGLE_PRI, /* Single Customer/Service Priority Tag */ + NPS_VLAN_TAG_SINGLE, /* Single Customer/Service Tag */ + NPS_VLAN_TAG_DOUBLE_PRI, /* Double Tag with any VID=0 */ + NPS_VLAN_TAG_DOUBLE, /* Double Tag */ + NPS_VLAN_TAG_LAST +} NPS_VLAN_TAG_T; + +typedef struct NPS_BUM_INFO_S +{ + UI32_T mcast_id; + UI32_T group_label; /* l2 da group label */ + UI32_T vid; /* used when FLAGS_ADD_VID is set */ + +#define NPS_BUM_INFO_FLAGS_MCAST_VALID (1 << 0) +#define NPS_BUM_INFO_FLAGS_TO_CPU (1 << 1) +#define NPS_BUM_INFO_FLAGS_ADD_VID (1 << 2) /* single tag to double tag (i.e) QinQ */ +#define NPS_BUM_INFO_FLAGS_TRILL_ALL_TREE (1 << 3) + UI32_T flags; +} NPS_BUM_INFO_T; + +typedef enum +{ + NPS_PHY_TYPE_INTERNAL = 0x0, + NPS_PHY_TYPE_EXTERNAL, + NPS_PHY_TYPE_LAST +} NPS_PHY_TYPE_T; + +typedef enum +{ + NPS_PHY_DEVICE_ADDR_PMA_PMD = 1, + NPS_PHY_DEVICE_ADDR_WIS = 2, + NPS_PHY_DEVICE_ADDR_PCS = 3, + NPS_PHY_DEVICE_ADDR_PHY_XS = 4, + NPS_PHY_DEVICE_ADDR_DTE_XS = 5, + NPS_PHY_DEVICE_ADDR_TC = 6, + NPS_PHY_DEVICE_ADDR_AN = 7, + NPS_PHY_DEVICE_ADDR_VENDOR_1 = 30, + NPS_PHY_DEVICE_ADDR_VENDOR_2 = 31, + NPS_PHY_DEVICE_ADDR_LAST +} NPS_PHY_DEVICE_ADDR_T; + +typedef struct NPS_RANGE_INFO_S +{ + UI32_T min_id; + UI32_T max_id; + UI32_T max_member_cnt; + +#define NPS_RANGE_INFO_FLAGS_MAX_MEMBER_CNT (1 << 0) + UI32_T flags; +} NPS_RANGE_INFO_T; + +/* EXPORTED SUBPROGRAM SPECIFICATIONS + */ + +#endif /* NPS_TYPES_H */ diff --git a/platform/nephos/nephos-modules/modules/src/inc/osal_mdc.h b/platform/nephos/nephos-modules/modules/src/inc/osal_mdc.h new file mode 100755 index 000000000000..0add2c8216b1 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/inc/osal_mdc.h @@ -0,0 +1,251 @@ +/* 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: osal_mdc.h + * PURPOSE: + * 1. Provide device operate from AML interface + * NOTES: + * + */ + +#ifndef OSAL_MDC_H +#define OSAL_MDC_H + +/* INCLUDE FILE DECLARATIONS */ +#include +#include + +#define OSAL_MDC_DRIVER_NAME "nps_dev" +#define OSAL_MDC_DRIVER_MISC_MAJOR_NUM (10) +#define OSAL_MDC_DRIVER_MISC_MINOR_NUM (250) +#define OSAL_MDC_PCI_BUS_WIDTH (4) + +#define OSAL_MDC_DMA_LIST_SZ_UNLIMITED (0) +#define OSAL_MDC_DMA_LIST_NAME "RSRV_DMA" +#define OSAL_MDC_DMA_SEMAPHORE_NAME "DMALIST" + +/* NAMING CONSTANT DECLARATIONS + */ + +/* linked list node */ +#if defined(NPS_LINUX_KERNEL_MODE) + +typedef struct OSAL_MDC_LIST_NODE_S +{ + void *ptr_data; /* node data */ + struct OSAL_MDC_LIST_NODE_S *ptr_next; /* point to next link node */ + struct OSAL_MDC_LIST_NODE_S *ptr_prev; /* point to previous link node */ +} OSAL_MDC_LIST_NODE_T; + +/* linked list head */ +typedef struct OSAL_MDC_LIST_S +{ + OSAL_MDC_LIST_NODE_T *ptr_head_node; /* linked list head node */ + OSAL_MDC_LIST_NODE_T *ptr_tail_node; /* linked list tail node */ + UI32_T capacity; /* max count of nodes in list + * size=0: the capacity is unlimited. + * size>0: the capacity is limited. + */ + UI32_T node_cnt; /* the count of nodes in the list */ +} OSAL_MDC_LIST_T; + +#endif /* End of defined(NPS_LINUX_KERNEL_MODE) */ + +typedef struct +{ + NPS_ADDR_T phy_addr; + void *ptr_virt_addr; + NPS_ADDR_T size; + +#if defined(NPS_EN_DMA_RESERVED) + BOOL_T available; +#endif + +} OSAL_MDC_DMA_NODE_T; + +typedef struct +{ +#if defined(NPS_EN_DMA_RESERVED) + void *ptr_rsrv_virt_addr; + NPS_ADDR_T rsrv_phy_addr; + NPS_ADDR_T rsrv_size; +#else + struct device *ptr_dma_dev; /* for allocate/free system memory */ +#endif + void *ptr_dma_list; /* the type should be casted again when use */ + NPS_SEMAPHORE_ID_T sema; + +} OSAL_MDC_DMA_INFO_T; + +#if defined(NPS_LINUX_USER_MODE) + +/* Data type of IOCTL argument for DMA management */ +typedef struct +{ +#if defined(NPS_EN_DMA_RESERVED) + NPS_ADDR_T rsrv_dma_phy_addr; /* information of reserved memory */ + NPS_ADDR_T rsrv_dma_size; +#else + NPS_ADDR_T phy_addr; /* information of system memory */ + NPS_ADDR_T size; +#endif +} OSAL_MDC_IOCTL_DMA_DATA_T; + +/* Data type of IOCTL argument for device initialization */ +#pragma pack (push,1) +typedef struct +{ + AML_DEV_ID_T id[NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM]; + NPS_ADDR_T pci_mmio_phy_start[NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM]; + NPS_ADDR_T pci_mmio_size[NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM]; + UI32_T dev_num; +} OSAL_MDC_IOCTL_DEV_DATA_T; +#pragma pack (pop) + +typedef enum +{ + OSAL_MDC_IOCTL_ACCESS_READ = 0, + OSAL_MDC_IOCTL_ACCESS_WRITE, + OSAL_MDC_IOCTL_ACCESS_READ_WRITE, + OSAL_MDC_IOCTL_ACCESS_NONE, + OSAL_MDC_IOCTL_ACCESS_LAST + +} OSAL_MDC_IOCTL_ACCESS_T; + +typedef enum +{ + OSAL_MDC_IOCTL_TYPE_MDC_INIT_DEV = 0, + OSAL_MDC_IOCTL_TYPE_MDC_DEINIT_DEV, + OSAL_MDC_IOCTL_TYPE_MDC_INIT_RSRV_DMA_MEM, + OSAL_MDC_IOCTL_TYPE_MDC_DEINIT_RSRV_DMA_MEM, + OSAL_MDC_IOCTL_TYPE_MDC_ALLOC_SYS_DMA_MEM, + 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; + +typedef union +{ + UI32_T value; + struct + { + UI32_T access : 2; /* 0:read, 1:write, 2:read and write, 3:none */ + UI32_T unit : 6; /* Maximum unit number is 64. */ + UI32_T size :14; /* Maximum IOCTL data size is 16KB. */ + UI32_T type :10; /* Maximum 1024 IOCTL types */ + } field; +} OSAL_MDC_IOCTL_CMD_T; + +typedef NPS_ERROR_NO_T +(*OSAL_MDC_IOCTL_CALLBACK_FUNC_T)( + const UI32_T unit, + void *ptr_data); + +#endif /* End of NPS_LINUX_USER_MODE */ + + +/* MACRO FUNCTION DECLARATIONS + */ + +/* DATA TYPE DECLARATIONS + */ + +/* EXPORTED SUBPROGRAM SPECIFICATIONS + */ +NPS_ERROR_NO_T +osal_mdc_readPciReg( + const UI32_T unit, + const UI32_T offset, + UI32_T *ptr_data, + const UI32_T len); + +NPS_ERROR_NO_T +osal_mdc_writePciReg( + const UI32_T unit, + const UI32_T offset, + const UI32_T *ptr_data, + const UI32_T len); + +NPS_ERROR_NO_T +osal_mdc_initDevice( + AML_DEV_T *ptr_dev_list, + UI32_T *ptr_dev_num); + +NPS_ERROR_NO_T +osal_mdc_deinitDevice(void); + +NPS_ERROR_NO_T +osal_mdc_initDmaMem(void); + +NPS_ERROR_NO_T +osal_mdc_deinitDmaMem(void); + +void * +osal_mdc_allocDmaMem( + const UI32_T size); + +NPS_ERROR_NO_T +osal_mdc_freeDmaMem( + void *ptr_virt_addr); + +NPS_ERROR_NO_T +osal_mdc_convertVirtToPhy( + void *ptr_virt_addr, + NPS_ADDR_T *ptr_phy_addr); + +NPS_ERROR_NO_T +osal_mdc_convertPhyToVirt( + const NPS_ADDR_T phy_addr, + void **pptr_virt_addr); + +NPS_ERROR_NO_T +osal_mdc_registerIsr( + const UI32_T unit, + AML_DEV_ISR_FUNC_T handler, + void *ptr_cookie); + +NPS_ERROR_NO_T +osal_mdc_connectIsr( + const UI32_T unit, + AML_DEV_ISR_FUNC_T handler, + AML_DEV_ISR_DATA_T *ptr_cookie); + +NPS_ERROR_NO_T +osal_mdc_disconnectIsr( + const UI32_T unit); + +NPS_ERROR_NO_T +osal_mdc_flushCache( + void *ptr_virt_addr, + const UI32_T size); + +NPS_ERROR_NO_T +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 new file mode 100755 index 000000000000..59fd3df1260d --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/inc/osal_types.h @@ -0,0 +1,319 @@ +/* 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: osal_types.h + * PURPOSE: + * Define the commom data type in NPS SDK. + * NOTES: + */ + +#ifndef OSAL_TYPES_H +#define OSAL_TYPES_H + +/* INCLUDE FILE DECLARATIONS + */ + +/* NAMING CONSTANT DECLARATIONS + */ + + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef NULL +#define NULL (void *)0 +#endif + + +#if defined(NPS_EN_HOST_64_BIT_BIG_ENDIAN) +#define UI64_MSW 0 +#define UI64_LSW 1 +#elif defined(NPS_EN_HOST_64_BIT_LITTLE_ENDIAN) +#define UI64_MSW 1 +#define UI64_LSW 0 +#else +#define UI64_MSW 1 +#define UI64_LSW 0 +#endif + +#if defined(NPS_EN_COMPILER_SUPPORT_LONG_LONG) +#define UI64_HI(dst) ((UI32_T)((dst) >> 32)) +#define UI64_LOW(dst) ((UI32_T)((dst) & 0xffffffff)) +#define UI64_ASSIGN(dst, high, low) ((dst) = ((long long)(high) << 32 | (long long)(low))) +#define UI64_SET(dst, src) ((dst) = (src)) +#define UI64_ADD_UI32(dst, src) ((dst) += ((long long)(src))) +#define UI64_SUB_UI32(dst, src) ((dst) -= ((long long)(src))) +#define UI64_ADD_UI64(dst, src) ((dst) += (src)) +#define UI64_SUB_UI64(dst, src) ((dst) -= (src)) +#define UI64_AND(dst, src) ((dst) &= (src)) +#define UI64_OR(dst, src) ((dst) |= (src)) +#define UI64_XOR(dst, src) ((dst) ^= (src)) +#define UI64_NOT(dst) ((dst) = ~(dst)) +#define UI64_MULT_UI32(dst, src) ((dst) *= (src)) +#define UI64_MULT_UI64(dst, src) ((dst) *= (src)) +/* UI64_T type data comparion: + * if data1 > data2 return 1 + * if data1 < data2 return -1 + * if data1 == data2 return 0 + */ +#define UI64_CMP(data1, data2) (((data1) > (data2)) ? 1 : (((data1) < (data2)) ? -1 : 0)) + +#else +#define UI64_HI(dst) ((dst).ui64[UI64_MSW]) +#define UI64_LOW(dst) ((dst).ui64[UI64_LSW]) +#define UI64_ASSIGN(dst, high, low) \ + do \ + { \ + UI64_HI(dst) = (high); \ + UI64_LOW(dst) = (low); \ + } while(0) + +#define UI64_SET(dst, src) \ + do \ + { \ + UI64_HI(dst) = UI64_HI(src); \ + UI64_LOW(dst) = UI64_LOW(src); \ + } while(0) + + +#define UI64_ADD_UI32(dst, src) \ + do \ + { \ + UI32_T _i_ = UI64_LOW(dst); \ + UI64_LOW(dst) += (src); \ + if (UI64_LOW(dst) < _i_) \ + { \ + UI64_HI(dst)++; \ + } \ + } while(0) + +#define UI64_SUB_UI32(dst, src) \ + do \ + { \ + UI32_T _i_ = UI64_LOW(dst); \ + UI64_LOW(dst) -= src; \ + if (UI64_LOW(dst) > _i_) \ + { \ + UI64_HI(dst)--; \ + } \ + } while(0) + + +#define UI64_ADD_UI64(dst, src) \ + do \ + { \ + UI32_T _i_ = UI64_LOW(dst); \ + UI64_LOW(dst) += UI64_LOW(src); \ + if (UI64_LOW(dst) < _i_) \ + { \ + UI64_HI(dst)++; \ + } \ + UI64_HI(dst) += UI64_HI(src); \ + } while(0) + +#define UI64_SUB_UI64(dst, src) \ + do { \ + UI32_T _i_ = UI64_LOW(dst); \ + UI64_LOW(dst) -= UI64_LOW(src); \ + if (UI64_LOW(dst) > _i_) \ + { \ + UI64_HI(dst)--; \ + } \ + UI64_HI(dst) -= UI64_HI(src); \ + } while(0) + + +#define UI64_AND(dst, src) \ + do { \ + UI64_HI(dst) &= UI64_HI(src); \ + UI64_LOW(dst) &= UI64_LOW(src); \ + } while(0) + +#define UI64_OR(dst, src) \ + do { \ + UI64_HI(dst) |= UI64_HI(src); \ + UI64_LOW(dst) |= UI64_LOW(src); \ + } while(0) + +#define UI64_XOR(dst, src) \ + do { \ + UI64_HI(dst) ^= UI64_HI(src); \ + UI64_LOW(dst) ^= UI64_LOW(src); \ + } while(0) + +#define UI64_NOT(dst) \ + do { \ + UI64_HI(dst) = ~UI64_HI(dst); \ + UI64_LOW(dst) = ~UI64_LOW(dst); \ + } while(0) + +/* UI64_T type data comparion: + * if data1 > data2 return 1 + * if data1 < data2 return -1 + * if data1 == data2 return 0 + */ +#define UI64_CMP(data1, data2) \ + (((data1).ui64[UI64_MSW] > (data2).ui64[UI64_MSW]) \ + ? 1 : (((data1).ui64[UI64_MSW] == (data2).ui64[UI64_MSW]) \ + ? (((data1).ui64[UI64_LSW] == (data2).ui64[UI64_LSW]) \ + ? 0 :(((data1).ui64[UI64_LSW] > (data2).ui64[UI64_LSW]) \ + ? 1 : -1)) : -1)) + +#define UI64_MULT_UI64(dst, src) \ + do \ + { \ + UI32_T _ret_low_ = 0; \ + UI32_T _ret_high_ = 0; \ + UI32_T _i_ = 0; \ + UI32_T _j_ = 0; \ + UI32_T _temp_ = 0; \ + UI32_T dst_t[4] = {0, 0, 0, 0}; \ + UI32_T src_t[4] = {0, 0, 0, 0}; \ + dst_t[0] = UI64_LOW(dst) & 0xFFFF; \ + dst_t[1] = UI64_LOW(dst) >> 16; \ + dst_t[2] = UI64_HI(dst) & 0xFFFF; \ + dst_t[3] = UI64_HI(dst) >> 16; \ + src_t[0] = UI64_LOW(src) & 0xFFFF; \ + src_t[1] = UI64_LOW(src) >> 16; \ + src_t[2] = UI64_HI(src) & 0xFFFF; \ + src_t[3] = UI64_HI(src) >> 16; \ + for(_i_ = 0; _i_ < 4; _i_++) \ + { \ + for(_j_ = 0; _j_ < 4; _j_++) \ + { \ + if((dst_t[_i_] != 0) && (src_t[_j_] != 0)) \ + { \ + _temp_ = dst_t[_i_] * src_t[_j_]; \ + if(0 == (_i_ + _j_)) \ + { \ + _ret_low_ += _temp_; \ + if (_ret_low_ < _temp_) \ + { \ + _ret_high_++; \ + } \ + } \ + if(1 == (_i_ + _j_)) \ + { \ + _ret_low_ += (_temp_ << 16); \ + if (_ret_low_ < (_temp_ << 16)) \ + { \ + _ret_high_++; \ + } \ + _ret_high_ += (_temp_ >> 16); \ + } \ + if(2 == (_i_+_j_)) \ + { \ + _ret_high_ += _temp_; \ + } \ + if(3 == (_i_ + _j_)) \ + { \ + _ret_high_ += (_temp_ << 16); \ + } \ + } \ + } \ + } \ + UI64_HI(dst) = _ret_high_; \ + UI64_LOW(dst) = _ret_low_; \ + } while(0) + +#define UI64_MULT_UI32(dst, src) \ + do \ + { \ + UI32_T _ret_low_ = 0; \ + UI32_T _ret_high_ = 0; \ + UI32_T _i_ = 0; \ + UI32_T _j_ = 0; \ + UI32_T _temp_ = 0; \ + UI32_T dst_t[4] = {0, 0, 0, 0}; \ + UI32_T src_t[2] = {0, 0}; \ + dst_t[0] = UI64_LOW(dst) & 0xFFFF; \ + dst_t[1] = UI64_LOW(dst) >> 16; \ + dst_t[2] = UI64_HI(dst) & 0xFFFF; \ + dst_t[3] = UI64_HI(dst) >> 16; \ + src_t[0] = src & 0xFFFF; \ + src_t[1] = src >> 16; \ + for(_i_ = 0; _i_ < 4; _i_++) \ + { \ + for(_j_ = 0; _j_ < 2; _j_++) \ + { \ + if((dst_t[_i_] != 0) && (src_t[_j_] != 0)) \ + { \ + _temp_ = dst_t[_i_] * src_t[_j_]; \ + if(0 == (_i_ + _j_)) \ + { \ + _ret_low_ += _temp_; \ + if (_ret_low_ < _temp_) \ + { \ + _ret_high_++; \ + } \ + } \ + if(1 == (_i_ + _j_)) \ + { \ + _ret_low_ += (_temp_ << 16); \ + if (_ret_low_ < (_temp_ << 16)) \ + { \ + _ret_high_++; \ + } \ + _ret_high_ += (_temp_ >> 16); \ + } \ + if(2 == (_i_ + _j_)) \ + { \ + _ret_high_ += _temp_; \ + } \ + if(3 == (_i_ + _j_)) \ + { \ + _ret_high_ += (_temp_ << 16); \ + } \ + } \ + } \ + } \ + UI64_HI(dst) = _ret_high_; \ + UI64_LOW(dst) = _ret_low_; \ + } while(0) + +#endif + +/* DATA TYPE DECLARATIONS + */ +typedef int BOOL_T; +typedef signed char I8_T; +typedef unsigned char UI8_T; +typedef signed short I16_T; +typedef unsigned short UI16_T; +typedef signed int I32_T; +typedef unsigned int UI32_T; +typedef char C8_T; + +#if defined(NPS_EN_COMPILER_SUPPORT_LONG_LONG) +typedef signed long long int I64_T; +typedef unsigned long long int UI64_T; +#else +typedef struct +{ + I32_T i64[2]; +} I64_T; + +typedef struct +{ + UI32_T ui64[2]; +} UI64_T; +#endif + +#endif /* OSAL_TYPES_H */ diff --git a/platform/nephos/nephos-modules/modules/src/make.mk b/platform/nephos/nephos-modules/modules/src/make.mk new file mode 100755 index 000000000000..b49da8b43cdf --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/make.mk @@ -0,0 +1,37 @@ +################################################################################ +# 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. +################################################################################ +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 ./src/netif_nl.o + +obj-m := $(DEV_MODULE_NAME).o $(NETIF_MODULE_NAME).o +$(DEV_MODULE_NAME)-objs := $(DEV_OBJS_TOTAL) +$(NETIF_MODULE_NAME)-objs := $(NETIF_OBJS_TOTAL) + +KBUILD_EXTRA_SYMBOLS := $(BUILD_OUTPUT_DIR)/Module.symvers +################################################################################ +folder: + $(TEST_PATH) $(BUILD_OUTPUT_DIR) || $(MKDIR) $(BUILD_OUTPUT_DIR) + $(TEST_PATH) $(BUILD_OUTPUT_DIR)/src || $(MKDIR) $(BUILD_OUTPUT_DIR)/src + +compile:: folder + touch $(BUILD_OUTPUT_DIR)/Makefile + $(MAKE) -C $(OS_PATH) M=$(BUILD_OUTPUT_DIR) src=$(shell pwd) modules EXTRA_CFLAGS="$(EXTRA_CFLAGS)" KBUILD_EXTRA_SYMBOLS=$(KBUILD_EXTRA_SYMBOLS) +install:: + +clean:: 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 new file mode 100755 index 000000000000..51af7fcb3ad9 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/netif_osal.c @@ -0,0 +1,753 @@ +/* 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_osal.c + * PURPOSE: + * It provide customer linux API. + * NOTES: + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) +#include +#endif +#include + +/* ----------------------------------------------------------------------------------- macro value */ +#define OSAL_US_PER_SECOND (1000000) /* macro second per second */ +#define OSAL_NS_PER_USECOND (1000) /* nano second per macro second */ + +/* ----------------------------------------------------------------------------------- macro function */ +#define OSAL_LOG_ERR(msg, ...) \ + osal_printf("\033[31m\033[0m"msg, __LINE__, ##__VA_ARGS__) + +/* ----------------------------------------------------------------------------------- struct */ +extern struct pci_dev *_ptr_ext_pci_dev; + +static linux_thread_t _osal_thread_head = {{0}}; + +/* ----------------------------------------------------------------------------------- function */ +/* general */ +void * +osal_memset( + void *ptr_mem, + const I32_T value, + const UI32_T num) +{ + return memset(ptr_mem, value, num); +} + +void * +osal_memcpy( + void *ptr_dst, + const void *ptr_src, + const UI32_T num) +{ + return memcpy(ptr_dst, ptr_src, num); +} + +UI32_T +osal_strlen( + const C8_T *ptr_str) +{ + return strlen(ptr_str); +} + +void +osal_printf( + const C8_T *ptr_fmt, + ...) +{ + va_list ap; + char buf[OSAL_PRN_BUF_SZ]; + + if (NULL != ptr_fmt) + { + va_start(ap, ptr_fmt); + vsnprintf(buf, OSAL_PRN_BUF_SZ, ptr_fmt, ap); + va_end(ap); + + printk("%s", buf); + } +} + +void * +osal_alloc( + const UI32_T size) +{ + return kmalloc(size, GFP_ATOMIC); +} + +void +osal_free( + const void *ptr_mem) +{ + kfree(ptr_mem); +} + +/* thread */ +NPS_ERROR_NO_T +osal_init(void) +{ + linux_thread_t *ptr_thread_head = &_osal_thread_head; + + memset(ptr_thread_head, 0x0, sizeof(linux_thread_t)); + + /* init */ + ptr_thread_head->ptr_prev = ptr_thread_head; + ptr_thread_head->ptr_next = ptr_thread_head; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_deinit(void) +{ + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_createThread( + const C8_T *ptr_thread_name, + const UI32_T stack_size, + const UI32_T priority, + void (function)(void*), + void *ptr_arg, + NPS_THREAD_ID_T *ptr_thread_id) +{ + char dft_name[OSAL_THREAD_NAME_LEN + 1] = OSAL_THREAD_DFT_NAME; + linux_thread_t *ptr_thread_head = &_osal_thread_head; + linux_thread_t *ptr_thread_node = osal_alloc(sizeof(linux_thread_t)); + + /* process name */ + osal_memcpy(ptr_thread_node->name, (0 == osal_strlen(ptr_thread_name))? + dft_name : ptr_thread_name, OSAL_THREAD_NAME_LEN); + ptr_thread_node->name[OSAL_THREAD_NAME_LEN] = '\0'; + + /* init */ + ptr_thread_node->ptr_task = kthread_create((int(*)(void *))function, ptr_arg, ptr_thread_name); + ptr_thread_node->ptr_task->policy = SCHED_RR; + ptr_thread_node->ptr_task->rt_priority = priority; + ptr_thread_node->is_stop = FALSE; + + *ptr_thread_id = (NPS_THREAD_ID_T)ptr_thread_node; + + wake_up_process(ptr_thread_node->ptr_task); + + /* append the thread_node */ + ptr_thread_node->ptr_prev = ptr_thread_head->ptr_prev; + ptr_thread_head->ptr_prev->ptr_next = ptr_thread_node; + ptr_thread_node->ptr_next = ptr_thread_head; + ptr_thread_head->ptr_prev = ptr_thread_node; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_stopThread( + NPS_THREAD_ID_T *ptr_thread_id) +{ + linux_thread_t *ptr_thread_node = (linux_thread_t *)(*ptr_thread_id); + + ptr_thread_node->is_stop = TRUE; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_destroyThread( + NPS_THREAD_ID_T *ptr_thread_id) +{ + linux_thread_t *ptr_thread_node = (linux_thread_t *)(*ptr_thread_id); + + kthread_stop(ptr_thread_node->ptr_task); + + /* remove the thread_node */ + ptr_thread_node->ptr_next->ptr_prev = ptr_thread_node->ptr_prev; + ptr_thread_node->ptr_prev->ptr_next = ptr_thread_node->ptr_next; + + osal_free(ptr_thread_node); + *ptr_thread_id = 0; + + return (NPS_E_OK); +} + +void +osal_initRunThread(void) +{ + /* for reboot or shutdown without stopping kthread */ + allow_signal(SIGTERM); +} + +NPS_ERROR_NO_T +osal_isRunThread(void) +{ + linux_thread_t *ptr_thread_node = _osal_thread_head.ptr_next; + + while (1) + { + if (ptr_thread_node == &_osal_thread_head) + { + OSAL_LOG_ERR("Cannot find task 0x%x.\n", current); + break; + } + if (ptr_thread_node->ptr_task == current) + { + break; + } + ptr_thread_node = ptr_thread_node->ptr_next; + } + + if ((TRUE == ptr_thread_node->is_stop) || (signal_pending(current))) + { + return (NPS_E_OTHERS); + } + + return (NPS_E_OK); +} + +void +osal_exitRunThread(void) +{ + while (!kthread_should_stop() && !signal_pending(current)) + { + osal_sleepThread(OSAL_NS_PER_USECOND); + } +} + +/* semaphore */ +NPS_ERROR_NO_T +osal_createSemaphore( + const C8_T *ptr_sema_name, + const UI32_T sema_count, + NPS_SEMAPHORE_ID_T *ptr_semaphore_id) +{ + char dft_name[OSAL_SEMA_NAME_LEN + 1] = OSAL_SEMA_DFT_NAME; + linux_sema_t *ptr_sema = osal_alloc(sizeof(linux_sema_t)); + + /* process name */ + osal_memcpy(ptr_sema->name, (0 == osal_strlen(ptr_sema_name))? + dft_name : ptr_sema_name, OSAL_SEMA_NAME_LEN); + ptr_sema->name[OSAL_SEMA_NAME_LEN] = '\0'; + + /* init */ + sema_init(&ptr_sema->lock, NPS_SEMAPHORE_BINARY); + + *ptr_semaphore_id = (NPS_SEMAPHORE_ID_T)ptr_sema; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_takeSemaphore( + NPS_SEMAPHORE_ID_T *ptr_semaphore_id, + UI32_T time_out) +{ + linux_sema_t *ptr_sema = (linux_sema_t *)(*ptr_semaphore_id); + + if (in_interrupt()) + { + return (NPS_E_OTHERS); + } + + if (!down_interruptible(&ptr_sema->lock)) + { + return (NPS_E_OK); + } + + return (NPS_E_OTHERS); +} + +NPS_ERROR_NO_T +osal_giveSemaphore( + NPS_SEMAPHORE_ID_T *ptr_semaphore_id) +{ + linux_sema_t *ptr_sema = (linux_sema_t *)(*ptr_semaphore_id); + + up(&ptr_sema->lock); + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_destroySemaphore( + NPS_SEMAPHORE_ID_T *ptr_semaphore_id) +{ + linux_sema_t *ptr_sema = (linux_sema_t *)(*ptr_semaphore_id); + + osal_free(ptr_sema); + *ptr_semaphore_id = 0; + + return (NPS_E_OK); +} + +/* event */ +NPS_ERROR_NO_T +osal_createEvent( + const C8_T *ptr_event_name, + NPS_SEMAPHORE_ID_T *ptr_event_id) +{ + char dft_name[OSAL_EVENT_NAME_LEN + 1] = OSAL_EVENT_DFT_NAME; + linux_event_t *ptr_event = osal_alloc(sizeof(linux_event_t)); + + /* process name */ + osal_memcpy(ptr_event->name, (0 == osal_strlen(ptr_event_name))? + dft_name : ptr_event_name, OSAL_EVENT_NAME_LEN); + ptr_event->name[OSAL_EVENT_NAME_LEN] = '\0'; + + /* init */ + ptr_event->condition = FALSE; + init_waitqueue_head(&ptr_event->wait_que); + + *ptr_event_id = (NPS_SEMAPHORE_ID_T)ptr_event; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_waitEvent( + NPS_SEMAPHORE_ID_T *ptr_event_id) +{ + linux_event_t *ptr_event = (linux_event_t *)(*ptr_event_id); + + if (!wait_event_interruptible(ptr_event->wait_que, ptr_event->condition)) + { + ptr_event->condition = FALSE; + + return (NPS_E_OK); + } + + return (NPS_E_OTHERS); +} + +NPS_ERROR_NO_T +osal_triggerEvent( + NPS_SEMAPHORE_ID_T *ptr_event_id) +{ + linux_event_t *ptr_event = (linux_event_t *)(*ptr_event_id); + + ptr_event->condition = TRUE; + wake_up_interruptible(&ptr_event->wait_que); + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_destroyEvent( + NPS_SEMAPHORE_ID_T *ptr_event_id) +{ + linux_event_t *ptr_event = (linux_event_t *)(*ptr_event_id); + + osal_free(ptr_event); + *ptr_event_id = 0; + + return (NPS_E_OK); +} + +/* isr_lock */ +NPS_ERROR_NO_T +osal_createIsrLock( + const C8_T *ptr_isrlock_name, + NPS_ISRLOCK_ID_T *ptr_isrlock_id) +{ + char dft_name[OSAL_SPIN_NAME_LEN + 1] = OSAL_SPIN_DFT_NAME; + linux_isrlock_t *ptr_isrlock = osal_alloc(sizeof(linux_isrlock_t)); + + /* process name */ + osal_memcpy(ptr_isrlock->name, (0 == osal_strlen(ptr_isrlock_name))? + dft_name : ptr_isrlock_name, OSAL_SPIN_NAME_LEN); + ptr_isrlock->name[OSAL_SPIN_NAME_LEN] = '\0'; + + /* init */ + spin_lock_init(&ptr_isrlock->spinlock); + + *ptr_isrlock_id = (NPS_ISRLOCK_ID_T)ptr_isrlock; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_takeIsrLock( + NPS_ISRLOCK_ID_T *ptr_isrlock_id, + NPS_IRQ_FLAGS_T *ptr_irq_flags) +{ + linux_isrlock_t *ptr_isrlock = (linux_isrlock_t *)(*ptr_isrlock_id); + unsigned long flags = 0; + + spin_lock_irqsave(&ptr_isrlock->spinlock, flags); + *ptr_irq_flags = (NPS_IRQ_FLAGS_T)flags; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_giveIsrLock( + NPS_ISRLOCK_ID_T *ptr_isrlock_id, + NPS_IRQ_FLAGS_T *ptr_irq_flags) +{ + linux_isrlock_t *ptr_isrlock = (linux_isrlock_t *)(*ptr_isrlock_id); + unsigned long flags = 0; + + flags = (unsigned long)(*ptr_irq_flags); + spin_unlock_irqrestore(&ptr_isrlock->spinlock, flags); + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_destroyIsrLock( + NPS_ISRLOCK_ID_T *ptr_isrlock_id) +{ + linux_isrlock_t *ptr_isrlock = (linux_isrlock_t *)(*ptr_isrlock_id); + + osal_free(ptr_isrlock); + *ptr_isrlock_id = 0; + + return (NPS_E_OK); +} + +/* time */ +NPS_ERROR_NO_T +osal_sleepThread( + const UI32_T usecond) +{ + UI32_T tick_usec; /* how many usec per second */ + UI32_T jiffies; + + if (0 != usecond) + { + /* HZ : times/sec, tick = 1/HZ */ + tick_usec = OSAL_TICKS_PER_SEC / HZ; + if (in_interrupt() || (usecond < tick_usec)) + { + return (-1); + } + else + { + DECLARE_WAIT_QUEUE_HEAD(suspend_queue); + + if (usecond > 0xFFFFFFFF - (tick_usec - 1)) + { + jiffies = 0xFFFFFFFF / tick_usec; + } + else + { + jiffies = (usecond + (tick_usec - 1)) / tick_usec; + } + + return wait_event_interruptible_timeout(suspend_queue, 0, jiffies); + } + } + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_getTime( + NPS_TIME_T *ptr_time) +{ + struct timeval usec_time; + + do_gettimeofday(&usec_time); + *(NPS_TIME_T *)ptr_time = (usec_time.tv_sec * OSAL_US_PER_SECOND) + usec_time.tv_usec; + + return (NPS_E_OK); +} + +/* queue */ +NPS_ERROR_NO_T +osal_que_create( + NPS_HUGE_T *ptr_queue_id, + UI32_T capacity) +{ + linux_queue_t *ptr_queue = osal_alloc(sizeof(linux_queue_t)); + + ptr_queue->head = 0; + ptr_queue->tail = 0; + ptr_queue->wr_cnt = 0; + ptr_queue->rd_cnt = 0; + ptr_queue->capacity = capacity; + ptr_queue->ptr_entry = osal_alloc(sizeof(linux_queue_entry_t) * capacity); + memset(ptr_queue->ptr_entry, 0x0, sizeof(linux_queue_entry_t) * capacity); + + *ptr_queue_id = (NPS_HUGE_T)ptr_queue; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_que_enque( + NPS_HUGE_T *ptr_queue_id, + void *ptr_data) +{ + linux_queue_t *ptr_queue = (linux_queue_t *)(*ptr_queue_id); + + if (ptr_queue->wr_cnt - ptr_queue->rd_cnt >= ptr_queue->capacity) + { + return (NPS_E_OTHERS); + } + + /* save data to the tail */ + ptr_queue->ptr_entry[ptr_queue->tail].ptr_data = ptr_data; + + /* calculate tail and wr_cnt */ + ptr_queue->tail++; + if (ptr_queue->tail >= ptr_queue->capacity) + { + ptr_queue->tail = 0; + } + + ptr_queue->wr_cnt++; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_que_deque( + NPS_HUGE_T *ptr_queue_id, + void **pptr_data) +{ + linux_queue_t *ptr_queue = (linux_queue_t *)(*ptr_queue_id); + + if (ptr_queue->wr_cnt == ptr_queue->rd_cnt) + { + return (NPS_E_OTHERS); + } + + /* get data from head */ + *pptr_data = ptr_queue->ptr_entry[ptr_queue->head].ptr_data; + ptr_queue->ptr_entry[ptr_queue->head].ptr_data = NULL; + + /* calculate head and rd_cnt */ + ptr_queue->head++; + if (ptr_queue->head >= ptr_queue->capacity) + { + ptr_queue->head = 0; + } + + ptr_queue->rd_cnt++; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_que_destroy( + NPS_HUGE_T *ptr_queue_id) +{ + linux_queue_t *ptr_queue = (linux_queue_t *)(*ptr_queue_id); + + osal_free(ptr_queue->ptr_entry); + osal_free(ptr_queue); + *ptr_queue_id = 0; + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_que_getCount( + NPS_HUGE_T *ptr_queue_id, + unsigned int *ptr_count) +{ + linux_queue_t *ptr_queue = (linux_queue_t *)(*ptr_queue_id); + + *ptr_count = ptr_queue->wr_cnt - ptr_queue->rd_cnt; + + return (NPS_E_OK); +} + +/* IO */ +int +osal_io_copyToUser( + void *ptr_usr_buf, + void *ptr_knl_buf, + unsigned int size) +{ + return copy_to_user(ptr_usr_buf, ptr_knl_buf, size); +} + +int +osal_io_copyFromUser( + void *ptr_knl_buf, + void *ptr_usr_buf, + unsigned int size) +{ + return copy_from_user(ptr_knl_buf, ptr_usr_buf, size); +} + +/* dma */ +void * +osal_dma_alloc( + const UI32_T size) +{ + struct device *ptr_dev = &_ptr_ext_pci_dev->dev; + linux_dma_t *ptr_dma_node = NULL; + dma_addr_t phy_addr = 0x0; + + ptr_dma_node = dma_alloc_coherent(ptr_dev, sizeof(linux_dma_t) + size, &phy_addr, GFP_ATOMIC); + ptr_dma_node->size = sizeof(linux_dma_t) + size; + ptr_dma_node->phy_addr = phy_addr; + + return (void *)ptr_dma_node->data; +} + +NPS_ERROR_NO_T +osal_dma_free( + void *ptr_dma_mem) +{ + struct device *ptr_dev = &_ptr_ext_pci_dev->dev; + linux_dma_t *ptr_dma_node = (linux_dma_t *)(ptr_dma_mem - sizeof(linux_dma_t)); + + dma_free_coherent(ptr_dev, ptr_dma_node->size, ptr_dma_node, ptr_dma_node->phy_addr); + + return (NPS_E_OK); +} + +dma_addr_t +osal_dma_convertVirtToPhy( + void *ptr_virt_addr) +{ + return virt_to_phys(ptr_virt_addr); +} + +void * +osal_dma_convertPhyToVirt( + const dma_addr_t phy_addr) +{ + return phys_to_virt(phy_addr); +} + +int +osal_dma_flushCache( + void *ptr_virt_addr, + const unsigned int size) +{ +#if defined(CONFIG_NOT_COHERENT_CACHE) || defined(CONFIG_DMA_NONCOHERENT) +#if defined(dma_cache_wback_inv) + dma_cache_wback_inv((NPS_HUGE_T)ptr_virt_addr, size); +#else + dma_cache_sync(NULL, ptr_virt_addr, size, DMA_TO_DEVICE); +#endif +#endif + return (0); +} + +int +osal_dma_invalidateCache( + void *ptr_virt_addr, + const unsigned int size) +{ +#if defined(CONFIG_NOT_COHERENT_CACHE) || defined(CONFIG_DMA_NONCOHERENT) +#if defined(dma_cache_wback_inv) + dma_cache_wback_inv((NPS_HUGE_T)ptr_virt_addr, size); +#else + dma_cache_sync(NULL, ptr_virt_addr, size, DMA_FROM_DEVICE); +#endif +#endif + return (0); +} + +/* skb */ +struct sk_buff * +osal_skb_alloc( + UI32_T size) +{ + struct sk_buff *ptr_skb = NULL; + + /* + * 1. alloc_skb (len, flag) : GFP_KERNEL + * 2. netdev_alloc_skb (dev, len) : GFP_ATOMIC + * 3. dev_alloc_skb (len) : GFP_ATOMIC + * 4. netdev_alloc_skb_ip_align (dev, len) : GFP_ATOMIC + * + * note: Eth header is 14-bytes, we reservd 2-bytes to alignment Ip header + */ + ptr_skb = dev_alloc_skb(size + NET_IP_ALIGN); + skb_reserve(ptr_skb, NET_IP_ALIGN); + skb_put(ptr_skb, size); + + return (ptr_skb); +} + +void +osal_skb_free( + struct sk_buff *ptr_skb) +{ + /* + * 1. dev_kfree_skb (*skb) : release in process context + * 2. dev_kfree_skb_irq (*skb) : release in interrupt context + * 3. dev_kfree_skb_any (*skb) : release in any context + */ + dev_kfree_skb_any(ptr_skb); +} + +dma_addr_t +osal_skb_mapDma( + struct sk_buff *ptr_skb, + enum dma_data_direction dir) +{ + struct device *ptr_dev = &_ptr_ext_pci_dev->dev; + dma_addr_t phy_addr = 0x0; + + phy_addr = dma_map_single(ptr_dev, ptr_skb->data, ptr_skb->len, dir); + if (dma_mapping_error(ptr_dev, phy_addr)) + { + phy_addr = 0x0; + } + + return (phy_addr); +} + +void +osal_skb_unmapDma( + const dma_addr_t phy_addr, + UI32_T size, + enum dma_data_direction dir) +{ + struct device *ptr_dev = &_ptr_ext_pci_dev->dev; + + dma_unmap_single(ptr_dev, phy_addr, size, dir); +} + +void +osal_skb_send( + struct sk_buff *ptr_skb) +{ + dev_queue_xmit(ptr_skb); +} + +void +osal_skb_recv( + struct sk_buff *ptr_skb) +{ + /* 1. netif_rx() : handle skb in process context + * 2. netif_rx_ni() : handle skb in interrupt context + * 3. netif_receive_skb() : for NAPI + */ + netif_rx(ptr_skb); +} + diff --git a/platform/nephos/nephos-modules/modules/src/netif_perf.c b/platform/nephos/nephos-modules/modules/src/netif_perf.c new file mode 100755 index 000000000000..11dd03b58eb5 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/netif_perf.c @@ -0,0 +1,656 @@ +/* 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_perf.c + * PURPOSE: + * It provide customer performance test API. + * NOTES: + */ +#include +#include + +#include +#include + +#if defined (NPS_EN_TAURUS) +#include +#endif + +/* -------------------------------------------------------------- switch */ +#if defined (NPS_EN_ARIES) +#define PERF_TX_CHANNEL_NUM_MAX (HAL_ARI_PKT_TX_CHANNEL_LAST) +#define PERF_RX_CHANNEL_NUM_MAX (HAL_ARI_PKT_RX_CHANNEL_LAST) +typedef HAL_ARI_PKT_TX_SW_GPD_T PERF_TX_SW_GPD; +typedef HAL_ARI_PKT_RX_SW_GPD_T PERF_RX_SW_GPD; +#endif + +#if defined (NPS_EN_TAURUS) +#define PERF_TX_CHANNEL_NUM_MAX (HAL_TAU_PKT_TX_CHANNEL_LAST) +#define PERF_RX_CHANNEL_NUM_MAX (HAL_TAU_PKT_RX_CHANNEL_LAST) +typedef HAL_TAU_PKT_TX_SW_GPD_T PERF_TX_SW_GPD; +typedef HAL_TAU_PKT_RX_SW_GPD_T PERF_RX_SW_GPD; +#endif + +/* -------------------------------------------------------------- common */ +#define PERF_TX_PERF_NUM (1000000) /* max: 4294967 */ +#define PERF_TX_PERF_MESG (50000) +#define PERF_TX_PERF_FAIL (10000) +#define PERF_RX_PERF_NUM (1000000) /* max: 4294967 */ +#define PERF_RX_PERF_MESG (50000) +#define PERF_RX_PERF_FAIL (10000) + +/* -------------------------------------------------------------- callbacks for chip dependency */ +/* Tx */ +typedef NPS_ERROR_NO_T +(*PERF_TX_GET_INTR_T)( + const UI32_T unit, + const UI32_T channel, + UI32_T *ptr_intr_cnt); + +typedef NPS_ERROR_NO_T +(*PERF_TX_GET_NETDEV_T)( + const UI32_T unit, + const UI32_T port, + struct net_device **pptr_net_dev); + +typedef NPS_ERROR_NO_T +(*PERF_TX_PREPARE_GPD_T)( + const UI32_T unit, + const NPS_ADDR_T phy_addr, + const UI32_T len, + const UI32_T port, + PERF_TX_SW_GPD *ptr_sw_gpd); + +typedef NPS_ERROR_NO_T +(*PERF_TX_SEND_GPD_T)( + const UI32_T unit, + const UI32_T channel, + PERF_TX_SW_GPD *ptr_sw_gpd); + +/* Rx */ +typedef NPS_ERROR_NO_T +(*PERF_RX_GET_INTR_T)( + const UI32_T unit, + const UI32_T channel, + UI32_T *ptr_intr_cnt); + +/* -------------------------------------------------------------- structs */ +typedef enum +{ + PERF_DIR_TX = 0, + PERF_DIR_RX, + PERF_DIR_LAST, + +} PERF_DIR_T; + +typedef struct +{ + UI32_T unit; + UI32_T channel; + UI32_T len; + UI32_T num; + UI32_T port; + BOOL_T test_skb; + +} PERF_COOKIE_T; + +typedef struct +{ + /* netif-only */ + PERF_COOKIE_T tx_cookie [PERF_TX_CHANNEL_NUM_MAX]; + + NPS_THREAD_ID_T tx_task [PERF_TX_CHANNEL_NUM_MAX]; + NPS_SEMAPHORE_ID_T start_sync [PERF_TX_CHANNEL_NUM_MAX]; + NPS_SEMAPHORE_ID_T end_sync [PERF_TX_CHANNEL_NUM_MAX]; + UI32_T send_ok [PERF_TX_CHANNEL_NUM_MAX]; + UI32_T send_fail [PERF_TX_CHANNEL_NUM_MAX]; + + /* chip dependent callbacks */ + PERF_TX_GET_INTR_T get_intr_cnt; + PERF_TX_GET_NETDEV_T get_netdev; + PERF_TX_PREPARE_GPD_T prepare_gpd; + PERF_TX_SEND_GPD_T send_gpd; + +} PERF_TX_PERF_CB_T; + +typedef struct +{ + /* netif-only */ + BOOL_T rx_test; + + NPS_SEMAPHORE_ID_T start_sync; + NPS_SEMAPHORE_ID_T end_sync; + UI32_T target_num; + UI32_T target_len; + UI32_T recv_pass; + UI32_T recv_fail; + + /* duplicate packets */ + UI32_T rch_qid_map_lo [PERF_RX_CHANNEL_NUM_MAX]; + UI32_T rch_qid_map_hi [PERF_RX_CHANNEL_NUM_MAX]; + + /* chip dependent callbacks */ + PERF_RX_GET_INTR_T get_intr_cnt; + +} PERF_RX_PERF_CB_T; + +/* -------------------------------------------------------------- statics */ +static PERF_TX_PERF_CB_T _perf_tx_perf_cb = +{ +#if defined (NPS_EN_ARIES) + .get_intr_cnt = hal_ari_pkt_getTxIntrCnt, + .get_netdev = hal_ari_pkt_getNetDev, /* test_skb = TRUE */ + .prepare_gpd = hal_ari_pkt_prepareGpd, /* test_skb = FALSE */ + .send_gpd = hal_ari_pkt_sendGpd, /* test_skb = FALSE */ +#endif +#if defined (NPS_EN_TAURUS) + .get_intr_cnt = hal_tau_pkt_getTxIntrCnt, + .get_netdev = hal_tau_pkt_getNetDev, /* test_skb = TRUE */ + .prepare_gpd = hal_tau_pkt_prepareGpd, /* test_skb = FALSE */ + .send_gpd = hal_tau_pkt_sendGpd, /* test_skb = FALSE */ +#endif +}; + +static PERF_RX_PERF_CB_T _perf_rx_perf_cb = +{ +#if defined (NPS_EN_ARIES) + .get_intr_cnt = hal_ari_pkt_getRxIntrCnt, +#endif +#if defined (NPS_EN_TAURUS) + .get_intr_cnt = hal_tau_pkt_getRxIntrCnt, +#endif +}; + +/* -------------------------------------------------------------- functions */ +static void +_perf_duplicateRxPacket( + const UI32_T unit, + const UI32_T rx_channel, + const BOOL_T enable) +{ + ; +} + +static void +_perf_showPerf( + PERF_DIR_T dir, + UI32_T channel, + UI32_T len, + UI32_T num, + UI32_T intr, + UI32_T duration) +{ + UI32_T tx_channel = 0; + UI32_T tx_fail = 0; + + if (duration < 1000) + { + osal_printf("***Error***, %d packets cost < 1000 us.\n", num); + return ; + } + + osal_printf("\n"); + + if (PERF_DIR_TX == dir) + { + osal_printf("Tx-perf\n"); + } + else + { + osal_printf("Rx-perf\n"); + } + + osal_printf("------------------------------------\n"); + osal_printf("channel number : %d\n", channel); + osal_printf("packet length (bytes): %d\n", len); + osal_printf("packet number : %d\n", num); + osal_printf("time duration (us) : %d\n", duration); + osal_printf("------------------------------------\n"); + osal_printf("avg. packet rate (pps) : %d\n", (num * 1000) / (duration / 1000)); + osal_printf("avg. throughput (Mbps) : %d\n", ((num / 1000) * len * 8) / (duration / 1000)); + osal_printf("interrupt number : %d\n", intr); + + if (PERF_DIR_TX == dir) + { + for (tx_channel = 0; tx_channel < channel; tx_channel++) + { + tx_fail += _perf_tx_perf_cb.send_fail[tx_channel]; + } + osal_printf("Tx fail : %d\n", tx_fail); + } + + osal_printf("------------------------------------\n"); +} + +static void +_perf_getIntrCnt( + UI32_T unit, + PERF_DIR_T dir, + UI32_T *ptr_intr_cnt) +{ + UI32_T intr_cnt = 0; + UI32_T channel = 0; + + if (PERF_DIR_TX == dir) + { + for (channel = 0; channel < PERF_TX_CHANNEL_NUM_MAX; channel++) + { + _perf_tx_perf_cb.get_intr_cnt(unit, channel, &intr_cnt); + *ptr_intr_cnt += intr_cnt; + } + } + else + { + for (channel = 0; channel < PERF_RX_CHANNEL_NUM_MAX; channel++) + { + _perf_rx_perf_cb.get_intr_cnt(unit, channel, &intr_cnt); + *ptr_intr_cnt += intr_cnt; + } + } +} + +static void +_perf_txCallback( + const UI32_T unit, + PERF_TX_SW_GPD *ptr_sw_gpd, + void *ptr_virt_addr) +{ + /* free dma */ + osal_dma_free(ptr_virt_addr); + + /* free gpd */ + osal_free(ptr_sw_gpd); +} + +static void +_perf_txTask( + void *ptr_argv) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + UI32_T unit = ((PERF_COOKIE_T *)ptr_argv)->unit; + UI32_T channel = ((PERF_COOKIE_T *)ptr_argv)->channel; + UI32_T len = ((PERF_COOKIE_T *)ptr_argv)->len; + UI32_T num = ((PERF_COOKIE_T *)ptr_argv)->num; + UI32_T port = ((PERF_COOKIE_T *)ptr_argv)->port; + BOOL_T test_skb = ((PERF_COOKIE_T *)ptr_argv)->test_skb; + + /* test targets */ + PERF_TX_SW_GPD *ptr_sw_gpd = NULL; + struct sk_buff *ptr_skb = NULL; + + /* temp variables */ + UI32_T send_fail = 0; + void *ptr_virt_addr = NULL; + NPS_ADDR_T phy_addr = 0x0; + + osal_initRunThread(); + do + { + rc = osal_waitEvent(&_perf_tx_perf_cb.start_sync[channel]); + if (NPS_E_OK != osal_isRunThread()) + { + break; /* deinit-thread */ + } + + while (_perf_tx_perf_cb.send_ok[channel] < num) + { + if (0 == (_perf_tx_perf_cb.send_ok[channel] % PERF_TX_PERF_MESG)) + { + printk("T"); + } + + if (TRUE == test_skb) + { + ptr_skb = osal_skb_alloc(len); + ptr_skb->len = len; + _perf_tx_perf_cb.get_netdev(unit, port, &ptr_skb->dev); + + /* send skb */ + osal_skb_send(ptr_skb); + } + else + { + ptr_sw_gpd = osal_alloc(sizeof(PERF_TX_SW_GPD)); + if (NULL == ptr_sw_gpd) + { + osal_printf("***Error***, alloc sw-gpd fail.\n"); + break; + } + + /* prepare buf */ + ptr_virt_addr = osal_dma_alloc(len); + phy_addr = osal_dma_convertVirtToPhy(ptr_virt_addr); + + /* trans skb to gpd */ + osal_memset(ptr_sw_gpd, 0x0, sizeof(PERF_TX_SW_GPD)); + ptr_sw_gpd->callback = (void *)_perf_txCallback; + ptr_sw_gpd->ptr_cookie = (void *)ptr_virt_addr; + ptr_sw_gpd->gpd_num = 1; + ptr_sw_gpd->ptr_next = NULL; + ptr_sw_gpd->channel = channel; + + /* prepare gpd */ + rc = _perf_tx_perf_cb.prepare_gpd(unit, phy_addr, len, port, ptr_sw_gpd); + + /* send gpd */ + rc = _perf_tx_perf_cb.send_gpd(unit, channel, ptr_sw_gpd); + if (NPS_E_OK == rc) + { + _perf_tx_perf_cb.send_ok[channel]++; + send_fail = 0; + } + else + { + _perf_tx_perf_cb.send_fail[channel]++; + if (send_fail++ >= PERF_TX_PERF_FAIL) + { + osal_printf("***Error***, Tch-%d send fail over %d packet(s). (rc: %d)\n", + channel, PERF_TX_PERF_FAIL, rc); + break; + } + + _perf_txCallback(unit, ptr_sw_gpd, ptr_virt_addr); + osal_sleepThread(1000); + } + } + } + + osal_triggerEvent(&_perf_tx_perf_cb.end_sync[channel]); + } + while (NPS_E_OK == osal_isRunThread()); + osal_exitRunThread(); +} + +static void +_perf_txDeinit( + const UI32_T unit, + const UI32_T tx_channel) +{ + UI32_T channel = 0; + + for (channel = 0; channel < tx_channel; channel++) + { + /* destroy Tx resources */ + osal_stopThread (&_perf_tx_perf_cb.tx_task [channel]); + osal_triggerEvent(&_perf_tx_perf_cb.start_sync [channel]); + osal_destroyThread(&_perf_tx_perf_cb.tx_task [channel]); + osal_destroyEvent(&_perf_tx_perf_cb.end_sync [channel]); + osal_destroyEvent(&_perf_tx_perf_cb.start_sync [channel]); + } +} + +static void +_perf_txInit( + const UI32_T unit, + const UI32_T tx_channel, + const UI32_T len, + BOOL_T test_skb) +{ + UI32_T channel = 0; + + for (channel = 0; channel < tx_channel; channel++) + { + _perf_tx_perf_cb.send_ok [channel] = 0; + _perf_tx_perf_cb.send_fail[channel] = 0; + + /* create Tx resources */ + osal_createEvent("TX_START", &_perf_tx_perf_cb.start_sync [channel]); + osal_createEvent("TX_END", &_perf_tx_perf_cb.end_sync [channel]); + + _perf_tx_perf_cb.tx_cookie[channel].unit = unit; + _perf_tx_perf_cb.tx_cookie[channel].channel = channel; + _perf_tx_perf_cb.tx_cookie[channel].len = len; + _perf_tx_perf_cb.tx_cookie[channel].num = PERF_TX_PERF_NUM / tx_channel; + _perf_tx_perf_cb.tx_cookie[channel].port = 0; + _perf_tx_perf_cb.tx_cookie[channel].test_skb = test_skb; + + osal_createThread( + "TX_PERF", 64 * 1024, 90, + _perf_txTask, + (void *)&_perf_tx_perf_cb.tx_cookie[channel], + &_perf_tx_perf_cb.tx_task[channel]); + } +} + +static void +_perf_rxDeinit( + const UI32_T unit, + const UI32_T rx_channel) +{ + /* turn-off Rx test */ + _perf_rx_perf_cb.rx_test = FALSE; + + /* destroy Rx resources */ + osal_destroyEvent(&_perf_rx_perf_cb.end_sync); + osal_destroyEvent(&_perf_rx_perf_cb.start_sync); + + /* disable duplicate Rx packets to channels */ + _perf_duplicateRxPacket(unit, rx_channel, FALSE); +} + +static void +_perf_rxInit( + const UI32_T unit, + const UI32_T rx_channel, + const UI32_T len) +{ + /* enable duplicate Rx packets to channels */ + _perf_duplicateRxPacket(unit, rx_channel, TRUE); + + /* create Rx callback resources */ + _perf_rx_perf_cb.target_num = PERF_RX_PERF_NUM; + _perf_rx_perf_cb.target_len = len; + _perf_rx_perf_cb.recv_pass = 0; + + osal_createEvent("RX_START", &_perf_rx_perf_cb.start_sync); + osal_createEvent("RX_END", &_perf_rx_perf_cb.end_sync); + + /* turn-on Rx test */ + _perf_rx_perf_cb.rx_test = TRUE; +} + +/* FUNCTION NAME: perf_rxCallback + * PURPOSE: + * To count the Rx-gpd for Rx-test. + * INPUT: + * len -- To check if the Rx-gpd length equals to test length. + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successful operation. + * NOTES: + * None + */ +NPS_ERROR_NO_T +perf_rxCallback( + const UI32_T len) +{ + /* check length */ + if (len == _perf_rx_perf_cb.target_len) + { + _perf_rx_perf_cb.recv_pass++; + } + else + { + if (_perf_rx_perf_cb.recv_fail++ >= PERF_RX_PERF_FAIL) + { + _perf_rx_perf_cb.recv_fail = 0; + } + } + + /* send signals */ + if (0 == _perf_rx_perf_cb.recv_pass) + { + ; /* do nothing */ + } + else if (1 == _perf_rx_perf_cb.recv_pass) + { + osal_triggerEvent(&_perf_rx_perf_cb.start_sync); + } + else if (_perf_rx_perf_cb.recv_pass == _perf_rx_perf_cb.target_num) + { + osal_triggerEvent(&_perf_rx_perf_cb.end_sync); + } + else if (0 == (_perf_rx_perf_cb.recv_pass % PERF_RX_PERF_MESG)) + { + printk("R"); + } + + return (NPS_E_OK); +} + +/* FUNCTION NAME: perf_rxTest + * PURPOSE: + * To check if Rx-test is going. + * INPUT: + * None + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successful operation. + * NOTES: + * None + */ +NPS_ERROR_NO_T +perf_rxTest(void) +{ + if (FALSE == _perf_rx_perf_cb.rx_test) + { + return (NPS_E_OTHERS); + } + + return (NPS_E_OK); +} + +/* FUNCTION NAME: perf_test + * PURPOSE: + * To do Tx-test or Rx-test. + * INPUT: + * len -- Test length + * tx_channel -- Test Tx channel numbers + * rx_channel -- Test Rx channel numbers + * test_skb -- Test GPD or SKB + * OUTPUT: + * None + * RETURN: + * NPS_E_OK -- Successful operation. + * NOTES: + * None + */ +NPS_ERROR_NO_T +perf_test( + UI32_T len, + UI32_T tx_channel, + UI32_T rx_channel, + BOOL_T test_skb) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + NPS_TIME_T start_time; + NPS_TIME_T end_time; + UI32_T unit = 0, channel = 0; + UI32_T tx_pkt_cnt = 0, tx_start_intr = 0, tx_end_intr = 0; + UI32_T rx_pkt_cnt = 0, rx_start_intr = 0, rx_end_intr = 0; + + if ((0 == tx_channel) && (0 == rx_channel)) + { + return (NPS_E_NOT_SUPPORT); + } + + /* start test */ + if ((tx_channel > 0) && (rx_channel > 0)) + { + _perf_getIntrCnt(unit, PERF_DIR_TX, &tx_start_intr); + _perf_getIntrCnt(unit, PERF_DIR_RX, &rx_start_intr); + _perf_txInit(unit, tx_channel, len, test_skb); + _perf_rxInit(unit, rx_channel, len); + + /* wait 1st Rx GPD done */ + osal_waitEvent(&_perf_rx_perf_cb.start_sync); + + /* ------------- in-time ------------- */ + osal_getTime(&start_time); + for (channel = 0; channel < tx_channel; channel++) + { + osal_triggerEvent(&_perf_tx_perf_cb.start_sync[channel]); + } + for (channel = 0; channel < tx_channel; channel++) + { + osal_waitEvent(&_perf_tx_perf_cb.end_sync[channel]); + tx_pkt_cnt += _perf_tx_perf_cb.send_ok[channel]; + } + rx_pkt_cnt = _perf_rx_perf_cb.recv_pass; + osal_getTime(&end_time); + /* ------------- in-time ------------- */ + + _perf_txDeinit(unit, tx_channel); + _perf_rxDeinit(unit, rx_channel); + _perf_getIntrCnt(unit, PERF_DIR_TX, &tx_end_intr); + _perf_getIntrCnt(unit, PERF_DIR_RX, &rx_end_intr); + + _perf_showPerf(PERF_DIR_TX, + tx_channel, len, tx_pkt_cnt, tx_end_intr - tx_start_intr, end_time - start_time); + + _perf_showPerf(PERF_DIR_RX, + rx_channel, len, rx_pkt_cnt, rx_end_intr - rx_start_intr, end_time - start_time); + } + else if (tx_channel > 0) + { + _perf_getIntrCnt(unit, PERF_DIR_TX, &tx_start_intr); + _perf_txInit(unit, tx_channel, len, test_skb); + + /* ------------- in-time ------------- */ + osal_getTime(&start_time); + for (channel = 0; channel < tx_channel; channel++) + { + osal_triggerEvent(&_perf_tx_perf_cb.start_sync[channel]); + } + for (channel = 0; channel < tx_channel; channel++) + { + osal_waitEvent(&_perf_tx_perf_cb.end_sync[channel]); + tx_pkt_cnt += _perf_tx_perf_cb.send_ok[channel]; + } + osal_getTime(&end_time); + /* ------------- in-time ------------- */ + + _perf_txDeinit(unit, tx_channel); + _perf_getIntrCnt(unit, PERF_DIR_TX, &tx_end_intr); + + _perf_showPerf(PERF_DIR_TX, + tx_channel, len, tx_pkt_cnt, tx_end_intr - tx_start_intr, end_time - start_time); + } + else if (rx_channel > 0) + { + _perf_getIntrCnt(unit, PERF_DIR_RX, &rx_start_intr); + _perf_rxInit(unit, rx_channel, len); + + /* wait 1st Rx GPD done */ + osal_waitEvent(&_perf_rx_perf_cb.start_sync); + + /* ------------- in-time ------------- */ + osal_getTime(&start_time); + osal_waitEvent(&_perf_rx_perf_cb.end_sync); + osal_getTime(&end_time); + /* ------------- in-time ------------- */ + + _perf_rxDeinit(unit, rx_channel); + _perf_getIntrCnt(unit, PERF_DIR_RX, &rx_end_intr); + + _perf_showPerf(PERF_DIR_RX, + rx_channel, len, PERF_RX_PERF_NUM, rx_end_intr - rx_start_intr, end_time - start_time); + } + + return (rc); +} + diff --git a/platform/nephos/nephos-modules/modules/src/osal_isymbol.c b/platform/nephos/nephos-modules/modules/src/osal_isymbol.c new file mode 100755 index 000000000000..f908c2325966 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/osal_isymbol.c @@ -0,0 +1,38 @@ +/* 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: osal_isymbol.c +* PURPOSE: +* It provide global OSAL symbol export for linux kernel module +* NOTES: +*/ +#include +#include + +/* ----------------------------------------------------- */ +#include +/* dma */ +extern struct pci_dev *_ptr_ext_pci_dev; +EXPORT_SYMBOL(_ptr_ext_pci_dev); + +#if defined(NPS_LINUX_USER_MODE) +EXPORT_SYMBOL(osal_mdc_readPciReg); +EXPORT_SYMBOL(osal_mdc_writePciReg); +#if defined(NPS_EN_NETIF) +/* intr */ +/* for kernel module, this API will be exported by script with other OSAL functions in osal_symbol.c */ +EXPORT_SYMBOL(osal_mdc_registerIsr); +#endif +#endif diff --git a/platform/nephos/nephos-modules/modules/src/osal_mdc.c b/platform/nephos/nephos-modules/modules/src/osal_mdc.c new file mode 100755 index 000000000000..d0a25e48fc32 --- /dev/null +++ b/platform/nephos/nephos-modules/modules/src/osal_mdc.c @@ -0,0 +1,2512 @@ +/* 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: osal_mdc.c + * PURPOSE: + * 1. Provide device operate from AML interface + * NOTES: + * + */ + +/* INCLUDE FILE DECLARATIONS + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(NPS_LINUX_USER_MODE) +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +/* #define OSAL_MDC_EN_MSI */ +/* #define OSAL_MDC_DMA_RESERVED_MEM_CACHEABLE */ +/* #define OSAL_MDC_EN_TEST */ + +/* NAMING CONSTANT DECLARATIONS + */ +#define OSAL_MDC_PCI_BAR0_OFFSET (0x0) +#define OSAL_MDC_ERR printk + +/* MACRO FUNCTION DECLARATIONS + */ + +/* DATA TYPE DECLARATIONS + */ +typedef struct +{ + UI32_T unit; + struct pci_dev *ptr_pci_dev; + UI32_T *ptr_mmio_virt_addr; + int irq; + AML_DEV_ISR_FUNC_T isr_callback; + void *ptr_isr_data; + +} OSAL_MDC_DEV_T; + +typedef struct +{ + OSAL_MDC_DEV_T dev[NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM]; + UI32_T dev_num; + OSAL_MDC_DMA_INFO_T dma_info; + +} OSAL_MDC_CB_T; + +#if defined(NPS_LINUX_USER_MODE) + +typedef struct +{ + OSAL_MDC_IOCTL_CALLBACK_FUNC_T callback[OSAL_MDC_IOCTL_TYPE_LAST]; + +} OSAL_MDC_IOCTL_CB_T; + +#if !defined(NPS_EN_DMA_RESERVED) +typedef struct +{ + NPS_ADDR_T phy_addr; + UI32_T size; + struct list_head list; + +} OSAL_MDC_USER_MODE_DMA_NODE_T; +#endif + +#endif + + +#if defined(NPS_LINUX_KERNEL_MODE) + +/* re-define the interface to align OSAL_MDC's implementation with the prototype of CMLIB */ +#define osal_mdc_list_create(__capa__, __type__, __name__, __list__) _osal_mdc_list_create(__capa__, __list__) +#define osal_mdc_list_destroy(__list__, __callback__) _osal_mdc_list_destroy(__list__) +#define osal_mdc_list_getNodeData(__list__, __node__, __data__) _osal_mdc_list_getNodeData(__list__, __node__, __data__) +#define osal_mdc_list_next(__list__, __node__, __next__) _osal_mdc_list_next(__list__, __node__, __next__) +#define osal_mdc_list_locateHead(__list__, __node__) _osal_mdc_list_locateHead(__list__, __node__) +#define osal_mdc_list_insertToHead(__list__, __data__) _osal_mdc_list_insertToHead(__list__, __data__) +#define osal_mdc_list_deleteByData(__list__, __data__) _osal_mdc_list_deleteByData(__list__, __data__) + +#if defined(NPS_EN_DMA_RESERVED) +#define osal_mdc_list_insertBefore(__list__, __node__, __data__) _osal_mdc_list_insertBefore(__list__, __node__, __data__) +#define osal_mdc_list_prev(__list__, __node__, __prev__) _osal_mdc_list_prev(__list__, __node__, __prev__) +#endif + +#define OSAL_MDC_LIST_TYPE_DOUBLE (1) /* don't care the type, always be double */ +#define OSAL_MDC_LIST_TYPE_SINGLE (0) /* don't care the type, always be double */ + +static NPS_ERROR_NO_T +_osal_mdc_list_create( + const UI32_T capacity, + OSAL_MDC_LIST_T **pptr_list ) +{ + NPS_ERROR_NO_T rc = NPS_E_NO_MEMORY; + + *pptr_list = NULL; + + *pptr_list = osal_alloc(sizeof(OSAL_MDC_LIST_T)); + if (NULL != *pptr_list) + { + (*pptr_list)->capacity = capacity; + (*pptr_list)->node_cnt = 0; + (*pptr_list)->ptr_head_node = NULL; + (*pptr_list)->ptr_tail_node = NULL; + rc = NPS_E_OK; + } + + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_list_destroy( + OSAL_MDC_LIST_T *ptr_list ) +{ + OSAL_MDC_LIST_NODE_T *ptr_cur_node, *ptr_next_node; + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + + if (NULL != ptr_list) + { + if (ptr_list->node_cnt != 0) + { + OSAL_MDC_ERR("dma list not empty, node num=%d\n", + ptr_list->node_cnt); + ptr_cur_node = ptr_list->ptr_head_node; + while(NULL != ptr_cur_node) + { + ptr_next_node = ptr_cur_node->ptr_next; + osal_free(ptr_cur_node); + ptr_list->node_cnt--; + ptr_cur_node = ptr_next_node; + } + } + + osal_free(ptr_list); + rc = NPS_E_OK; + } + + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_list_getNodeData( + OSAL_MDC_LIST_T *ptr_list, + OSAL_MDC_LIST_NODE_T *ptr_node, + void **pptr_node_data ) +{ + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + + if (NULL != ptr_list) + { + if (NULL != ptr_node) + { + *pptr_node_data = ptr_node->ptr_data; + rc = NPS_E_OK; + } + } + + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_list_insertToHead( + OSAL_MDC_LIST_T *ptr_list, + void *ptr_data ) +{ + OSAL_MDC_LIST_NODE_T *ptr_new_node = NULL; + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + + if (NULL != ptr_list) + { + ptr_new_node = osal_alloc(sizeof(OSAL_MDC_LIST_NODE_T)); + if (NULL != ptr_new_node) + { + ptr_new_node->ptr_data = ptr_data; + + /* no former node */ + ptr_new_node->ptr_prev = NULL; + + if (NULL != ptr_list->ptr_head_node) + { + ptr_list->ptr_head_node->ptr_prev = ptr_new_node; + ptr_new_node->ptr_next = ptr_list->ptr_head_node; + } + else + { + /* 1st node insertion */ + ptr_list->ptr_tail_node = ptr_new_node; + ptr_new_node->ptr_next = NULL; + } + + ptr_list->ptr_head_node = ptr_new_node; + ptr_list->node_cnt++; + rc = NPS_E_OK; + } + } + + return (rc); +} + +#if defined(NPS_EN_DMA_RESERVED) +static NPS_ERROR_NO_T +_osal_mdc_list_insertBefore( + OSAL_MDC_LIST_T *ptr_list, + OSAL_MDC_LIST_NODE_T *ptr_node, + void *ptr_data ) +{ + OSAL_MDC_LIST_NODE_T *ptr_new_node = NULL; + OSAL_MDC_LIST_NODE_T *ptr_prev_node = ptr_node->ptr_prev; + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + + if (NULL != ptr_list) + { + if (NULL != ptr_node) + { + ptr_new_node = osal_alloc(sizeof(OSAL_MDC_LIST_NODE_T)); + if (NULL != ptr_new_node) + { + ptr_new_node->ptr_data = ptr_data; + + /* location */ + if (NULL != ptr_prev_node) + { + ptr_prev_node->ptr_next = ptr_new_node; + } + ptr_new_node->ptr_prev = ptr_prev_node; + ptr_new_node->ptr_next = ptr_node; + ptr_node->ptr_prev = ptr_new_node; + + /* update head if necessary */ + if (ptr_list->ptr_head_node == ptr_node) + { + ptr_list->ptr_head_node = ptr_new_node; + } + + ptr_list->node_cnt++; + rc = NPS_E_OK; + } + } + } + + return (rc); +} +#endif + +static NPS_ERROR_NO_T +_osal_mdc_list_deleteTargetNode( + OSAL_MDC_LIST_T *ptr_list, + OSAL_MDC_LIST_NODE_T *ptr_target_node) +{ + OSAL_MDC_LIST_NODE_T *ptr_prev_node = ptr_target_node->ptr_prev; + OSAL_MDC_LIST_NODE_T *ptr_next_node = ptr_target_node->ptr_next; + + if (ptr_target_node == ptr_list->ptr_head_node) + { + ptr_list->ptr_head_node = ptr_next_node; + if (NULL != ptr_next_node) + { + ptr_next_node->ptr_prev = NULL; + } + else + { + /* there's only 1 node in the list, and it gets removed */ + ptr_list->ptr_tail_node = NULL; + } + } + else if (ptr_target_node == ptr_list->ptr_tail_node) + { + /* at least 2 nodes in the list, and the target node locates tail */ + ptr_list->ptr_tail_node = ptr_prev_node; + ptr_prev_node->ptr_next = NULL; + } + else + { + /* intermediate node */ + ptr_prev_node->ptr_next = ptr_next_node; + ptr_next_node->ptr_prev = ptr_prev_node; + } + + osal_free(ptr_target_node); + ptr_list->node_cnt--; + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_osal_mdc_list_deleteByData( + OSAL_MDC_LIST_T *ptr_list, + void *ptr_delete_data) +{ + OSAL_MDC_LIST_NODE_T *ptr_tmp_node; + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + + if (NULL != ptr_list) + { + ptr_tmp_node = ptr_list->ptr_head_node; + while (NULL != ptr_tmp_node) + { + if (ptr_tmp_node->ptr_data == ptr_delete_data) + { + rc = _osal_mdc_list_deleteTargetNode(ptr_list, ptr_tmp_node); + break; + } + else + { + ptr_tmp_node = ptr_tmp_node->ptr_next; + } + } + } + + return (rc); +} + + +static NPS_ERROR_NO_T +_osal_mdc_list_locateHead( + OSAL_MDC_LIST_T *ptr_list, + OSAL_MDC_LIST_NODE_T **pptr_node ) +{ + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + + if (NULL != ptr_list) + { + *pptr_node = ptr_list->ptr_head_node; + if (NULL != *pptr_node) + { + rc = NPS_E_OK; + } + } + + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_list_next( + OSAL_MDC_LIST_T *ptr_list, + OSAL_MDC_LIST_NODE_T *ptr_node, + OSAL_MDC_LIST_NODE_T **pptr_next_node ) +{ + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + + if (NULL != ptr_list) + { + if (NULL != ptr_node) + { + *pptr_next_node = ptr_node->ptr_next; + if (NULL != *pptr_next_node) + { + rc = NPS_E_OK; + } + } + } + + return (rc); +} + +#if defined(NPS_EN_DMA_RESERVED) +static NPS_ERROR_NO_T +_osal_mdc_list_prev( + OSAL_MDC_LIST_T *ptr_list, + OSAL_MDC_LIST_NODE_T *ptr_node, + OSAL_MDC_LIST_NODE_T **pptr_prev_node ) +{ + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + + if (NULL != ptr_list) + { + if (NULL != ptr_node) + { + *pptr_prev_node = ptr_node->ptr_prev; + if (NULL != *pptr_prev_node) + { + rc = NPS_E_OK; + } + } + } + + return (rc); +} +#endif /* End of defined(NPS_EN_DMA_RESERVED) */ + +#endif /* End if defined(NPS_LINUX_KERNEL_MODE) */ + +/* GLOBAL VARIABLE DECLARATIONS + */ +static OSAL_MDC_CB_T _osal_mdc_cb; + +/* To let system callback function to access AML database */ +static AML_DEV_T *_ptr_osal_mdc_dev; + +/* Interface */ +struct pci_dev *_ptr_ext_pci_dev; + + +/* STATIC VARIABLE DECLARATIONS + */ +/* --------------------------------------------------------------------------- I2C interface */ +#if defined(AML_EN_I2C) +extern NPS_ERROR_NO_T +dev_switch_readBuffer( + const UI32_T addr, + const UI32_T addr_len, + UI8_T *ptr_buf, + const UI32_T buf_len); + +extern NPS_ERROR_NO_T +dev_switch_writeBuffer( + const UI32_T addr, + const UI32_T addr_len, + const UI8_T *ptr_buf, + const UI32_T buf_len); + +static NPS_ERROR_NO_T +_osal_mdc_readI2cReg( + const UI32_T unit, + const UI32_T offset, + UI32_T *ptr_data, + const UI32_T len) +{ + return dev_switch_readBuffer(offset, sizeof(offset), (UI8_T *)ptr_data, len); +} + +static NPS_ERROR_NO_T +_osal_mdc_writeI2cReg( + const UI32_T unit, + const UI32_T offset, + const UI32_T *ptr_data, + const UI32_T len) +{ + return dev_switch_writeBuffer(offset, sizeof(offset), (UI8_T *)ptr_data, len); +} + +static NPS_ERROR_NO_T +_osal_mdc_probeI2cDevice(void) +{ + /* I2C interface will be probed in BSP. */ + _ptr_osal_mdc_dev->if_type = AML_DEV_TYPE_I2C; + _ptr_osal_mdc_dev->access.read_callback = _osal_mdc_readI2cReg; + _ptr_osal_mdc_dev->access.write_callback = _osal_mdc_writeI2cReg; + + _ptr_osal_mdc_dev->id.device = HAL_DEVICE_ID_MT3258; + _ptr_osal_mdc_dev->id.vendor = HAL_MTK_VENDOR_ID; + _ptr_osal_mdc_dev->id.revision = HAL_REVISION_ID_E2; + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_osal_mdc_removeI2cDevice(void) +{ + /* I2C interface will be removed in BSP. */ + return (NPS_E_OK); +} + +/* --------------------------------------------------------------------------- PCI interface */ +#else + +static NPS_ERROR_NO_T +_osal_mdc_getPciMmioInfo( + struct pci_dev *pdev, + UI32_T **pptr_base_addr) +{ + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + NPS_ADDR_T phy_addr; + UI32_T reg_space_sz; + + phy_addr = pci_resource_start(pdev, OSAL_MDC_PCI_BAR0_OFFSET); + reg_space_sz = pci_resource_len(pdev, OSAL_MDC_PCI_BAR0_OFFSET); + + if (0 == pci_request_region(pdev, OSAL_MDC_PCI_BAR0_OFFSET, OSAL_MDC_DRIVER_NAME)) + { + *pptr_base_addr = ioremap_nocache(phy_addr, reg_space_sz); + if (NULL != *pptr_base_addr) + { + rc = NPS_E_OK; + } + } + return (rc); +} + +NPS_ERROR_NO_T +osal_mdc_readPciReg( + const UI32_T unit, + const UI32_T offset, + UI32_T *ptr_data, + const UI32_T len) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + UI32_T idx; + UI32_T count; + volatile UI32_T *ptr_base_addr = _osal_mdc_cb.dev[unit].ptr_mmio_virt_addr; + + if (NULL != ptr_base_addr) + { + if (OSAL_MDC_PCI_BUS_WIDTH == len) + { + *ptr_data = *((UI32_T *)((NPS_HUGE_T)ptr_base_addr + offset)); + } + else + { + if (0 == (len % OSAL_MDC_PCI_BUS_WIDTH)) + { + count = len / OSAL_MDC_PCI_BUS_WIDTH; + for (idx = 0; idx < count; idx++) + { + *(ptr_data + idx) = *((UI32_T *)((NPS_HUGE_T)ptr_base_addr + offset + idx * 4)); + } + } + else + { + rc = NPS_E_OTHERS; + } + } + } + else + { + rc = NPS_E_NOT_INITED; + } + + return (rc); +} + +NPS_ERROR_NO_T +osal_mdc_writePciReg( + const UI32_T unit, + const UI32_T offset, + const UI32_T *ptr_data, + const UI32_T len) +{ + UI32_T idx; + UI32_T count; + volatile UI32_T *ptr_base_addr = _osal_mdc_cb.dev[unit].ptr_mmio_virt_addr; + NPS_ERROR_NO_T rc = NPS_E_OK; + + if (NULL != ptr_base_addr) + { + if (OSAL_MDC_PCI_BUS_WIDTH == len) + { + *((UI32_T *)((NPS_HUGE_T)ptr_base_addr + offset)) = *ptr_data; + } + else + { + if (0 == (len % OSAL_MDC_PCI_BUS_WIDTH)) + { + count = len / OSAL_MDC_PCI_BUS_WIDTH; + for (idx = 0; idx < count; idx++) + { + *((UI32_T *)((NPS_HUGE_T)ptr_base_addr + offset + idx * 4)) = *(ptr_data + idx); + } + } + else + { + rc = NPS_E_OTHERS; + } + } + } + else + { + rc = NPS_E_NOT_INITED; + } + + return (rc); +} + +static int +_osal_mdc_probePciCallback( + struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int linux_rc; + UI16_T device_id; + UI16_T vendor_id; + UI8_T revision_id; + NPS_ERROR_NO_T rc = NPS_E_OK; + + linux_rc = pci_enable_device(pdev); + if (0 == linux_rc) + { + _ptr_osal_mdc_dev->if_type = AML_DEV_TYPE_PCI; + + pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id); + pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id); + pci_read_config_byte(pdev, PCI_REVISION_ID, &revision_id); + + _ptr_osal_mdc_dev->id.device = (UI32_T)device_id; + _ptr_osal_mdc_dev->id.vendor = (UI32_T)vendor_id; + _ptr_osal_mdc_dev->id.revision = (UI32_T)revision_id; + +#if defined(NPS_LINUX_KERNEL_MODE) + _ptr_osal_mdc_dev->access.read_callback = osal_mdc_readPciReg; + _ptr_osal_mdc_dev->access.write_callback = osal_mdc_writePciReg; +#endif + + rc = _osal_mdc_getPciMmioInfo(pdev, &_osal_mdc_cb.dev[_osal_mdc_cb.dev_num].ptr_mmio_virt_addr); + if (NPS_E_OK == rc) + { + /* Save the database to pdev structure for system callback to release recource, + * such like disconnecting ISR etc. + */ + _osal_mdc_cb.dev[_osal_mdc_cb.dev_num].irq = pdev->irq; + _osal_mdc_cb.dev[_osal_mdc_cb.dev_num].ptr_pci_dev = pdev; + _osal_mdc_cb.dev[_osal_mdc_cb.dev_num].unit = _osal_mdc_cb.dev_num; + + pci_set_drvdata(pdev, &_osal_mdc_cb.dev[_osal_mdc_cb.dev_num]); + + /* To set the bus master bit on device to enable the DMA transaction from PCIe EP to RC + * The bus master bit gets cleared when pci_disable_device() is called + */ + pci_set_master(pdev); + +#if !defined(NPS_EN_DMA_RESERVED) + if (NULL == _osal_mdc_cb.dma_info.ptr_dma_dev) + { + /* This variable is for dma_alloc_coherent */ + _osal_mdc_cb.dma_info.ptr_dma_dev = &pdev->dev; + } +#endif + _osal_mdc_cb.dev_num++; + _ptr_osal_mdc_dev++; + } + } + else + { + OSAL_MDC_ERR("enable pci dev failed, linux_rc=%d\n", linux_rc); + } + + return (0); +} + +static void +_osal_mdc_removePciCallback( + struct pci_dev *pdev) +{ + OSAL_MDC_DEV_T *ptr_dev = (OSAL_MDC_DEV_T *)pci_get_drvdata(pdev); + + iounmap(ptr_dev->ptr_mmio_virt_addr); + pci_release_region(pdev, OSAL_MDC_PCI_BAR0_OFFSET); + pci_disable_device(pdev); + _osal_mdc_cb.dev_num--; +} + +static struct pci_device_id _osal_mdc_id_table[] = +{ + {PCI_DEVICE(HAL_MTK_VENDOR_ID, PCI_ANY_ID)}, + {PCI_DEVICE(HAL_NP_VENDOR_ID, PCI_ANY_ID)}, +}; + +static struct pci_driver _osal_mdc_pci_driver = +{ + .name = OSAL_MDC_DRIVER_NAME, + .id_table = _osal_mdc_id_table, + .probe = _osal_mdc_probePciCallback, + .remove = _osal_mdc_removePciCallback, +}; + +static NPS_ERROR_NO_T +_osal_mdc_probePciDevice(void) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + + if (pci_register_driver(&_osal_mdc_pci_driver) < 0) + { + OSAL_MDC_ERR("Cannot find PCI device\n"); + rc = NPS_E_OTHERS; + } + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_removePciDevice(void) +{ + pci_unregister_driver(&_osal_mdc_pci_driver); + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_osal_mdc_maskStatus( + const UI32_T unit) +{ + struct pci_dev *ptr_ep_dev = _osal_mdc_cb.dev[unit].ptr_pci_dev; + struct pci_dev *ptr_rc_dev = ptr_ep_dev->bus->self; + int ext_cap = 0; + UI32_T data_32 = 0; + + ext_cap = pci_find_ext_capability(ptr_rc_dev, 0x1); + if (0 != ext_cap) + { + /* Mask */ + pci_read_config_dword(ptr_rc_dev, ext_cap + 0x8, &data_32); + data_32 |= 0x20; + pci_write_config_dword(ptr_rc_dev, ext_cap + 0x8, data_32); + } + + return NPS_E_OK; +} + +static NPS_ERROR_NO_T +_osal_mdc_clearStatus( + const UI32_T unit) +{ + struct pci_dev *ptr_ep_dev = _osal_mdc_cb.dev[unit].ptr_pci_dev; + struct pci_dev *ptr_rc_dev = ptr_ep_dev->bus->self; + int ext_cap = 0; + UI32_T data_32 = 0; + + ext_cap = pci_find_ext_capability(ptr_rc_dev, 0x1); + if (0 != ext_cap) + { + /* Clear */ + pci_write_config_word(ptr_rc_dev, ptr_rc_dev->pcie_cap + 0xa, 0x04); + pci_write_config_word(ptr_rc_dev, ptr_rc_dev->pcie_cap + 0x12, 0x8000); + pci_write_config_dword(ptr_rc_dev, ext_cap + 0x4, 0x20); + + /* UnMask */ + pci_read_config_dword(ptr_rc_dev, ext_cap + 0x8, &data_32); + data_32 &= ~0x20; + pci_write_config_dword(ptr_rc_dev, ext_cap + 0x8, data_32); + } + + return NPS_E_OK; +} + +static NPS_ERROR_NO_T +_osal_mdc_savePciConfig( + const UI32_T unit) +{ + struct pci_dev *ptr_dev = _osal_mdc_cb.dev[unit].ptr_pci_dev; + NPS_ERROR_NO_T rc = NPS_E_OK; + + rc = _osal_mdc_maskStatus(unit); + + if (NPS_E_OK == rc) + { + pci_save_state(ptr_dev); + } + + return rc; +} + +static NPS_ERROR_NO_T +_osal_mdc_restorePciConfig( + const UI32_T unit) +{ +#define OSAL_MDC_PCI_PRESENT_POLL_CNT (100) +#define OSAL_MDC_PCI_PRESENT_POLL_INTERVAL (10) /* ms */ + + struct pci_dev *ptr_dev = _osal_mdc_cb.dev[unit].ptr_pci_dev; + UI32_T poll_cnt = 0; + NPS_ERROR_NO_T rc = NPS_E_OK; + + /* standard: at least 100ms for link recovery */ + msleep(100); + + /* make sure pci device is there before restoring the config space */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) + while ((0 == pci_device_is_present(ptr_dev)) && +#else + while ((0 == pci_dev_present(_osal_mdc_id_table)) && +#endif + (poll_cnt < OSAL_MDC_PCI_PRESENT_POLL_CNT)) + { + msleep(OSAL_MDC_PCI_PRESENT_POLL_INTERVAL); + poll_cnt++; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) + if (1 == pci_device_is_present(ptr_dev)) +#else + if (1 == pci_dev_present(_osal_mdc_id_table)) +#endif + { + pci_restore_state(ptr_dev); + rc = NPS_E_OK; + } + else + { + OSAL_MDC_ERR("detect pci device failed\n"); + rc = NPS_E_OTHERS; + } + + if (NPS_E_OK == rc) + { + rc = _osal_mdc_clearStatus(unit); + } + + return (rc); +} + +#endif /* End of AML_EN_I2C */ + +/* --------------------------------------------------------------------------- DMA */ +#if defined(NPS_LINUX_KERNEL_MODE) + +static NPS_ERROR_NO_T +_osal_mdc_searchDmaVirtAddr( + OSAL_MDC_LIST_T *ptr_dma_list, + const void *ptr_virt_addr, + OSAL_MDC_LIST_NODE_T **pptr_node, + OSAL_MDC_DMA_NODE_T **pptr_node_data) +{ + OSAL_MDC_LIST_NODE_T *ptr_curr_node; + OSAL_MDC_DMA_NODE_T *ptr_curr_node_data; + NPS_ERROR_NO_T rc; + + rc = osal_mdc_list_locateHead(ptr_dma_list, &ptr_curr_node); + while (NPS_E_OK == rc) + { + rc = osal_mdc_list_getNodeData(ptr_dma_list, ptr_curr_node, (void **)&ptr_curr_node_data); + if (NPS_E_OK == rc) + { + if (ptr_curr_node_data->ptr_virt_addr == ptr_virt_addr) + { + *pptr_node = ptr_curr_node; + *pptr_node_data = ptr_curr_node_data; + break; + } + rc = osal_mdc_list_next(ptr_dma_list, ptr_curr_node, &ptr_curr_node); + } + } + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_destroyDmaNodeList( + OSAL_MDC_DMA_INFO_T *ptr_dma_info) +{ + OSAL_MDC_LIST_T *ptr_dma_list = (OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list; + OSAL_MDC_LIST_NODE_T *ptr_curr_node = NULL; + OSAL_MDC_DMA_NODE_T *ptr_curr_node_data = NULL; + NPS_ERROR_NO_T rc = NPS_E_NOT_INITED; + + if (NULL != ptr_dma_list) + { + rc = osal_mdc_list_locateHead(ptr_dma_list, &ptr_curr_node); + while (NPS_E_OK == rc) + { + rc = osal_mdc_list_getNodeData(ptr_dma_list, ptr_curr_node, (void **)&ptr_curr_node_data); + if ((NPS_E_OK == rc) && (NULL != ptr_curr_node_data)) + { + rc = osal_mdc_list_deleteByData(ptr_dma_list, ptr_curr_node_data); + if (NPS_E_OK == rc) + { + kfree(ptr_curr_node_data); + } + } + rc = osal_mdc_list_locateHead(ptr_dma_list, &ptr_curr_node); + } + rc = osal_mdc_list_destroy(ptr_dma_list, NULL); + if (NPS_E_OK == rc) + { + ptr_dma_info->ptr_dma_list = NULL; + } + } + return (rc); +} + +#endif /* End of NPS_LINUX_KERNEL_MODE */ + +#if defined(NPS_EN_DMA_RESERVED) + +#if defined(NPS_LINUX_KERNEL_MODE) + +#if defined(OSAL_MDC_EN_TEST) +static NPS_ERROR_NO_T +_osal_mdc_dumpRsrvDmaList(void) +{ + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + OSAL_MDC_LIST_NODE_T *ptr_curr_node; + OSAL_MDC_DMA_NODE_T *ptr_curr_node_data; + UI32_T node = 0; + NPS_ERROR_NO_T rc = NPS_E_OK; + + rc = osal_mdc_list_locateHead((OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list, + &ptr_curr_node); + while (NPS_E_OK == rc) + { + rc = osal_mdc_list_getNodeData((OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list, + ptr_curr_node, (void **)&ptr_curr_node_data); + if (NPS_E_OK == rc) + { + OSAL_MDC_ERR( + "node %d. virt addr=%p, phy addr=%p, size=%d, avbl=%d\n", node, + ptr_curr_node_data->ptr_virt_addr, ptr_curr_node_data->phy_addr, + ptr_curr_node_data->size, ptr_curr_node_data->available); + } + rc = osal_mdc_list_next((OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list, + ptr_curr_node, &ptr_curr_node); + node++; + } + return (rc); +} +#endif + +static NPS_ERROR_NO_T +_osal_mdc_createRsrvDmaNodeList( + OSAL_MDC_DMA_INFO_T *ptr_dma_info) +{ + OSAL_MDC_DMA_NODE_T *ptr_node_data; + NPS_ERROR_NO_T rc; + + rc = osal_mdc_list_create(OSAL_MDC_DMA_LIST_SZ_UNLIMITED, + OSAL_MDC_LIST_TYPE_DOUBLE, + OSAL_MDC_DMA_LIST_NAME, + (OSAL_MDC_LIST_T **)&ptr_dma_info->ptr_dma_list); + if (NPS_E_OK == rc) + { + /* The first node, which contains all of the reserved memory */ + ptr_node_data = kmalloc(sizeof(OSAL_MDC_DMA_NODE_T), GFP_KERNEL); + if (NULL != ptr_node_data) + { + ptr_node_data->ptr_virt_addr = ptr_dma_info->ptr_rsrv_virt_addr; + ptr_node_data->phy_addr = ptr_dma_info->rsrv_phy_addr; + ptr_node_data->size = ptr_dma_info->rsrv_size; + ptr_node_data->available = TRUE; + rc = osal_mdc_list_insertToHead((OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list, + ptr_node_data); + } + else + { + rc = NPS_E_NO_MEMORY; + } + } + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_searchAvblRsrvDmaNode( + OSAL_MDC_LIST_T *ptr_dma_list, + const UI32_T size, + OSAL_MDC_LIST_NODE_T **pptr_avbl_node) +{ + OSAL_MDC_LIST_NODE_T *ptr_curr_node; + OSAL_MDC_DMA_NODE_T *ptr_curr_node_data; + NPS_ERROR_NO_T rc; + + rc = osal_mdc_list_locateHead(ptr_dma_list, &ptr_curr_node); + while (NPS_E_OK == rc) + { + rc = osal_mdc_list_getNodeData(ptr_dma_list, ptr_curr_node, (void **)&ptr_curr_node_data); + if (NPS_E_OK == rc) + { + if ((TRUE == ptr_curr_node_data->available) && (ptr_curr_node_data->size >= size)) + { + *pptr_avbl_node = ptr_curr_node; + break; + } + } + rc = osal_mdc_list_next(ptr_dma_list, ptr_curr_node, &ptr_curr_node); + } + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_splitRsrvDmaNodes( + OSAL_MDC_LIST_T *ptr_dma_list, + OSAL_MDC_LIST_NODE_T *ptr_ori_node, + const UI32_T size, + OSAL_MDC_DMA_NODE_T **pptr_new_node_data) +{ + OSAL_MDC_DMA_NODE_T *ptr_ori_node_data; + NPS_ERROR_NO_T rc; + + rc = osal_mdc_list_getNodeData(ptr_dma_list, ptr_ori_node, (void **)&ptr_ori_node_data); + + if (NPS_E_OK == rc) + { + *pptr_new_node_data = kmalloc(sizeof(OSAL_MDC_DMA_NODE_T), GFP_KERNEL); + + /* Create a new node */ + (*pptr_new_node_data)->size = size; + (*pptr_new_node_data)->phy_addr = ptr_ori_node_data->phy_addr; + (*pptr_new_node_data)->ptr_virt_addr = ptr_ori_node_data->ptr_virt_addr; + (*pptr_new_node_data)->available = TRUE; + + /* Update the original node */ + ptr_ori_node_data->size -= size; + ptr_ori_node_data->phy_addr += size; + ptr_ori_node_data->ptr_virt_addr = + (void *)((NPS_HUGE_T)ptr_ori_node_data->ptr_virt_addr + (NPS_HUGE_T)size); + + rc = osal_mdc_list_insertBefore(ptr_dma_list, ptr_ori_node, (void *)*pptr_new_node_data); + if (NPS_E_OK != rc) + { + OSAL_MDC_ERR("insert rsrv dma node to list failed, size=%d, rc=%d\n", size, rc); + /* Recovery */ + ptr_ori_node_data->size += size; + ptr_ori_node_data->phy_addr -= size; + ptr_ori_node_data->ptr_virt_addr = + (void *)((NPS_HUGE_T)ptr_ori_node_data->ptr_virt_addr - (NPS_HUGE_T)size); + kfree(*pptr_new_node_data); + } + } + return (rc); +} + +static void * +_osal_mdc_allocRsrvDmaMem( + OSAL_MDC_DMA_INFO_T *ptr_dma_info, + const UI32_T size) +{ + OSAL_MDC_LIST_T *ptr_dma_list = (OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list; + OSAL_MDC_LIST_NODE_T *ptr_node = NULL; + OSAL_MDC_DMA_NODE_T *ptr_node_data; + OSAL_MDC_DMA_NODE_T *ptr_new_node_data; + void *ptr_virt_addr = NULL; + NPS_ERROR_NO_T rc; + + rc = _osal_mdc_searchAvblRsrvDmaNode(ptr_dma_list, size, &ptr_node); + if (NPS_E_OK == rc) + { + rc = osal_mdc_list_getNodeData(ptr_dma_list, ptr_node, (void **)&ptr_node_data); + if (NPS_E_OK == rc) + { + /* If the node size just fit the user's requirement, just give it to user */ + if (ptr_node_data->size == size) + { + ptr_node_data->available = FALSE; + ptr_virt_addr = ptr_node_data->ptr_virt_addr; + } + /* or split a new node with user required size. */ + else + { + rc = _osal_mdc_splitRsrvDmaNodes(ptr_dma_list, ptr_node, size, &ptr_new_node_data); + if (NPS_E_OK == rc) + { + ptr_new_node_data->available = FALSE; + ptr_virt_addr = ptr_new_node_data->ptr_virt_addr; + } + } + } + } + return (ptr_virt_addr); +} + +static NPS_ERROR_NO_T +_osal_mdc_mergeTwoRsrvDmaNodes( + OSAL_MDC_LIST_T *ptr_dma_list, + OSAL_MDC_DMA_NODE_T *ptr_first_node_data, + OSAL_MDC_DMA_NODE_T *ptr_second_node_data) +{ + ptr_first_node_data->size += ptr_second_node_data->size; + + osal_mdc_list_deleteByData(ptr_dma_list, ptr_second_node_data); + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_osal_mdc_mergeRsrvDmaNodes( + OSAL_MDC_LIST_T *ptr_dma_list, + OSAL_MDC_LIST_NODE_T *ptr_curr_node) +{ + OSAL_MDC_LIST_NODE_T *ptr_prev_node; + OSAL_MDC_LIST_NODE_T *ptr_next_node; + OSAL_MDC_DMA_NODE_T *ptr_curr_node_data; + OSAL_MDC_DMA_NODE_T *ptr_prev_node_data; + OSAL_MDC_DMA_NODE_T *ptr_next_node_data; + NPS_ERROR_NO_T rc; + + rc = osal_mdc_list_getNodeData(ptr_dma_list, ptr_curr_node, (void **)&ptr_curr_node_data); + if (NPS_E_OK == rc) + { + /* First, check if the previous node is available */ + rc = osal_mdc_list_prev(ptr_dma_list, ptr_curr_node, &ptr_prev_node); + if (NPS_E_OK == rc) + { + osal_mdc_list_getNodeData(ptr_dma_list, ptr_prev_node, (void **)&ptr_prev_node_data); + if (TRUE == ptr_prev_node_data->available) + { + _osal_mdc_mergeTwoRsrvDmaNodes(ptr_dma_list, ptr_prev_node_data, ptr_curr_node_data); + ptr_curr_node = ptr_prev_node; + ptr_curr_node_data = ptr_prev_node_data; + } + } + + /* then, check if the next node is available */ + rc = osal_mdc_list_next(ptr_dma_list, ptr_curr_node, &ptr_next_node); + if (NPS_E_OK == rc) + { + rc = osal_mdc_list_getNodeData(ptr_dma_list, ptr_next_node, (void **)&ptr_next_node_data); + if (NPS_E_OK == rc) + { + if (TRUE == ptr_next_node_data->available) + { + _osal_mdc_mergeTwoRsrvDmaNodes(ptr_dma_list, ptr_curr_node_data, ptr_next_node_data); + } + } + } + } + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_freeRsrvDmaMem( + OSAL_MDC_DMA_INFO_T *ptr_dma_info, + void *ptr_virt_addr) +{ + OSAL_MDC_LIST_T *ptr_dma_list = (OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list; + OSAL_MDC_LIST_NODE_T *ptr_node = NULL; + OSAL_MDC_DMA_NODE_T *ptr_node_data = NULL; + NPS_ERROR_NO_T rc; + + rc = _osal_mdc_searchDmaVirtAddr(ptr_dma_list, ptr_virt_addr, &ptr_node, &ptr_node_data); + if (NPS_E_OK == rc) + { + ptr_node_data->available = TRUE; + _osal_mdc_mergeRsrvDmaNodes(ptr_dma_list, ptr_node); + } + return (rc); +} + +#endif /* End of NPS_LINUX_KERNEL_MODE */ + +static NPS_ERROR_NO_T +_osal_mdc_initRsrvDmaMem( + OSAL_MDC_DMA_INFO_T *ptr_dma_info) +{ + struct resource *ptr_res; + NPS_ERROR_NO_T rc = NPS_E_OK; + + ptr_dma_info->rsrv_size = (NPS_ADDR_T)NPS_DMA_RESERVED_SZ * 1024 * 1024; + ptr_dma_info->rsrv_phy_addr = (NPS_ADDR_T)NPS_OS_MEMORY_SZ * 1024 * 1024; + ptr_res = request_mem_region(ptr_dma_info->rsrv_phy_addr, + ptr_dma_info->rsrv_size, "nps_rsrv_mem"); + if (NULL != ptr_res) + { +#if defined(OSAL_MDC_DMA_RESERVED_MEM_CACHEABLE) + ptr_dma_info->ptr_rsrv_virt_addr = ioremap(ptr_dma_info->rsrv_phy_addr, + ptr_dma_info->rsrv_size); +#else + ptr_dma_info->ptr_rsrv_virt_addr = ioremap_nocache(ptr_dma_info->rsrv_phy_addr, + ptr_dma_info->rsrv_size); +#endif + if (NULL == ptr_dma_info->ptr_rsrv_virt_addr) + { +#if defined(NPS_EN_64BIT_ADDR) || defined(NPS_EN_HOST_64_BIT_BIG_ENDIAN) || defined(NPS_EN_HOST_64_BIT_LITTLE_ENDIAN) + OSAL_MDC_ERR( + "ioremap_nocache() failed, phy addr=0x%llx, size=%llu\n", + ptr_dma_info->rsrv_phy_addr, ptr_dma_info->rsrv_size); +#else + OSAL_MDC_ERR( + "ioremap_nocache() failed, phy addr=0x%x, size=%u\n", + ptr_dma_info->rsrv_phy_addr, ptr_dma_info->rsrv_size); +#endif + rc = NPS_E_OTHERS; + } + } + else + { +#if defined(NPS_EN_64BIT_ADDR) || defined(NPS_EN_HOST_64_BIT_BIG_ENDIAN) || defined(NPS_EN_HOST_64_BIT_LITTLE_ENDIAN) + OSAL_MDC_ERR( + "request_mem_region() failed, phy addr=0x%llx, size=%llu\n", + ptr_dma_info->rsrv_phy_addr, ptr_dma_info->rsrv_size); +#else + OSAL_MDC_ERR( + "request_mem_region() failed, phy addr=0x%x, size=%u\n", + ptr_dma_info->rsrv_phy_addr, ptr_dma_info->rsrv_size); +#endif + rc = NPS_E_OTHERS; + } + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_deinitRsrvDmaMem( + OSAL_MDC_DMA_INFO_T *ptr_dma_info) +{ + if (NULL != ptr_dma_info->ptr_rsrv_virt_addr) + { + iounmap(ptr_dma_info->ptr_rsrv_virt_addr); + } + if (0x0 != ptr_dma_info->rsrv_phy_addr) + { + release_mem_region(ptr_dma_info->rsrv_phy_addr, + ptr_dma_info->rsrv_size); + } + return (NPS_E_OK); +} + + +#else /* Else of NPS_EN_DMA_RESERVED */ + + +#if defined(NPS_LINUX_KERNEL_MODE) + +#if defined(OSAL_MDC_EN_TEST) +static NPS_ERROR_NO_T +_osal_mdc_dumpSysDmaList(void) +{ + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + OSAL_MDC_LIST_NODE_T *ptr_curr_node; + OSAL_MDC_DMA_NODE_T *ptr_curr_node_data; + UI32_T node = 0; + NPS_ERROR_NO_T rc = NPS_E_OK; + + rc = osal_mdc_list_locateHead((OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list, + &ptr_curr_node); + while (NPS_E_OK == rc) + { + rc = osal_mdc_list_getNodeData((OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list, + ptr_curr_node, (void **)&ptr_curr_node_data); + if (NPS_E_OK == rc) + { + OSAL_MDC_ERR( + "node %d. virt addr=%p, phy addr=%p, size=%d\n", node, + ptr_curr_node_data->ptr_virt_addr, ptr_curr_node_data->phy_addr, + ptr_curr_node_data->size); + } + + rc = osal_mdc_list_next((OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list, + ptr_curr_node, &ptr_curr_node); + node++; + + } + return (rc); +} +#endif + +static NPS_ERROR_NO_T +_osal_mdc_createSysDmaNodeList( + OSAL_MDC_DMA_INFO_T *ptr_dma_info) +{ + NPS_ERROR_NO_T rc; + + rc = osal_mdc_list_create(OSAL_MDC_DMA_LIST_SZ_UNLIMITED, + OSAL_MDC_LIST_TYPE_SINGLY, + OSAL_MDC_DMA_LIST_NAME, + (OSAL_MDC_LIST_T **)&ptr_dma_info->ptr_dma_list); + return (rc); +} +#if !defined(NPS_LAMP) + +static void * +_osal_mdc_allocSysDmaMem( + OSAL_MDC_DMA_INFO_T *ptr_dma_info, + const UI32_T size) +{ + dma_addr_t phy_addr; + OSAL_MDC_DMA_NODE_T *ptr_node_data; + void *ptr_virt_addr = NULL; + NPS_ERROR_NO_T rc = NPS_E_OK; + + ptr_virt_addr = dma_alloc_coherent(ptr_dma_info->ptr_dma_dev, size, &phy_addr, GFP_ATOMIC); + if (NULL != ptr_virt_addr) + { + ptr_node_data = kmalloc(sizeof(OSAL_MDC_DMA_NODE_T), GFP_KERNEL); + ptr_node_data->phy_addr = (NPS_ADDR_T)phy_addr; + ptr_node_data->ptr_virt_addr = ptr_virt_addr; + ptr_node_data->size = size; + + rc = osal_mdc_list_insertToHead((OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list, ptr_node_data); + if (NPS_E_OK != rc) + { + kfree(ptr_node_data); + dma_free_coherent(ptr_dma_info->ptr_dma_dev, size, + ptr_virt_addr, phy_addr); + ptr_virt_addr = NULL; + } + } + return (ptr_virt_addr); +} + +static NPS_ERROR_NO_T +_osal_mdc_freeSysDmaMem( + OSAL_MDC_DMA_INFO_T *ptr_dma_info, + void *ptr_virt_addr) +{ + OSAL_MDC_LIST_NODE_T *ptr_node = NULL; + OSAL_MDC_DMA_NODE_T *ptr_node_data = NULL; + NPS_ERROR_NO_T rc; + + rc = _osal_mdc_searchDmaVirtAddr((OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list, + ptr_virt_addr, &ptr_node, &ptr_node_data); + if (NPS_E_OK == rc) + { + dma_free_coherent(ptr_dma_info->ptr_dma_dev, ptr_node_data->size, + ptr_virt_addr, ptr_node_data->phy_addr); + + osal_mdc_list_deleteByData((OSAL_MDC_LIST_T *)ptr_dma_info->ptr_dma_list, + ptr_node_data); + kfree(ptr_node_data); + } + return (rc); +} +#endif +#endif /* End of NPS_LINUX_KERNEL_MODE */ + +#endif /* End of NPS_EN_DMA_RESERVED */ + +#if defined(NPS_LINUX_KERNEL_MODE) + +void * +osal_mdc_allocDmaMem( + const UI32_T size) +{ + void *ptr_virt_addr = NULL; + +#if defined(NPS_LAMP) + ptr_virt_addr = osal_alloc(size); +#else + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + osal_takeSemaphore(&ptr_dma_info->sema, NPS_SEMAPHORE_WAIT_FOREVER); + +#if defined(NPS_EN_DMA_RESERVED) + ptr_virt_addr = _osal_mdc_allocRsrvDmaMem(ptr_dma_info, size); +#else + ptr_virt_addr = _osal_mdc_allocSysDmaMem(ptr_dma_info, size); +#endif + + osal_giveSemaphore(&ptr_dma_info->sema); +#endif + + return ptr_virt_addr; +} + +NPS_ERROR_NO_T +osal_mdc_freeDmaMem( + void *ptr_virt_addr) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + +#if defined(NPS_LAMP) + osal_free(ptr_virt_addr); +#else + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + + osal_takeSemaphore(&ptr_dma_info->sema, NPS_SEMAPHORE_WAIT_FOREVER); + +#if defined(NPS_EN_DMA_RESERVED) + rc = _osal_mdc_freeRsrvDmaMem(ptr_dma_info, ptr_virt_addr); +#else + + rc = _osal_mdc_freeSysDmaMem(ptr_dma_info, ptr_virt_addr); +#endif + osal_giveSemaphore(&ptr_dma_info->sema); + + if (NPS_E_OK != rc) + { + OSAL_MDC_ERR("free dma mem failed, virt addr=%p\n", ptr_virt_addr); + } +#endif + + return (rc); +} + +NPS_ERROR_NO_T +osal_mdc_convertPhyToVirt( + const NPS_ADDR_T phy_addr, + void **pptr_virt_addr) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + +#if defined(NPS_EN_DMA_RESERVED) + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + NPS_HUGE_T rsrv_virt_base = (NPS_HUGE_T)ptr_dma_info->ptr_rsrv_virt_addr; + NPS_ADDR_T rsrv_phy_base = ptr_dma_info->rsrv_phy_addr; +#endif + +#if defined(NPS_EN_DMA_RESERVED) + *pptr_virt_addr = (void *)(rsrv_virt_base + (NPS_HUGE_T)(phy_addr - rsrv_phy_base)); +#else + *pptr_virt_addr = NULL; + *pptr_virt_addr = phys_to_virt(phy_addr); + rc = (NULL == *pptr_virt_addr) ? (NPS_E_ENTRY_NOT_FOUND) : (NPS_E_OK); +#endif + +#if defined(AML_EN_CUSTOM_DMA_ADDR) + if (NPS_E_OK != rc) + { + /* Here the user may invoke the API for their private DMA + * address conversion. + */ + } +#endif + return (rc); +} + +NPS_ERROR_NO_T +osal_mdc_convertVirtToPhy( + void *ptr_virt_addr, + NPS_ADDR_T *ptr_phy_addr) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + +#if defined(NPS_EN_DMA_RESERVED) + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + NPS_HUGE_T rsrv_virt_base = (NPS_HUGE_T)ptr_dma_info->ptr_rsrv_virt_addr; + NPS_ADDR_T rsrv_phy_base = ptr_dma_info->rsrv_phy_addr; +#endif + +#if defined(NPS_EN_DMA_RESERVED) + *ptr_phy_addr = (NPS_ADDR_T)((NPS_HUGE_T)rsrv_phy_base + + (NPS_HUGE_T)ptr_virt_addr - rsrv_virt_base); +#else + *ptr_phy_addr = 0x0; + *ptr_phy_addr = virt_to_phys(ptr_virt_addr); + rc = (0x0 == *ptr_phy_addr) ? (NPS_E_ENTRY_NOT_FOUND) : (NPS_E_OK); +#endif + +#if defined(AML_EN_CUSTOM_DMA_ADDR) + if (NPS_E_OK != rc) + { + /* Here the user may invoke the API for their private DMA + * address conversion. + */ + } +#endif + return (rc); +} + +NPS_ERROR_NO_T +osal_mdc_initDmaMem(void) +{ + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + NPS_ERROR_NO_T rc = NPS_E_OK; + + rc = osal_createSemaphore(OSAL_MDC_DMA_SEMAPHORE_NAME, + NPS_SEMAPHORE_BINARY, &ptr_dma_info->sema); + if (NPS_E_OK == rc) + { +#if defined(NPS_EN_DMA_RESERVED) + rc = _osal_mdc_initRsrvDmaMem(ptr_dma_info); + if (NPS_E_OK == rc) + { + rc = _osal_mdc_createRsrvDmaNodeList(ptr_dma_info); + } +#else + rc = _osal_mdc_createSysDmaNodeList(ptr_dma_info); +#endif + } + return (rc); +} + +NPS_ERROR_NO_T +osal_mdc_deinitDmaMem(void) +{ + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + + /* Common function for both reserved/system memory. */ + _osal_mdc_destroyDmaNodeList(ptr_dma_info); + +#if defined(NPS_EN_DMA_RESERVED) + _osal_mdc_deinitRsrvDmaMem(ptr_dma_info); +#endif + + osal_destroySemaphore(&ptr_dma_info->sema); + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_mdc_flushCache( + void *ptr_virt_addr, + const UI32_T size) +{ +#if defined(CONFIG_NOT_COHERENT_CACHE) || defined(CONFIG_DMA_NONCOHERENT) + +#if defined(dma_cache_wback_inv) + dma_cache_wback_inv((NPS_HUGE_T)ptr_virt_addr, size); +#else + dma_cache_sync(NULL, ptr_virt_addr, size, DMA_TO_DEVICE); +#endif + +#endif + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_mdc_invalidateCache( + void *ptr_virt_addr, + const UI32_T size) +{ +#if defined(CONFIG_NOT_COHERENT_CACHE) || defined(CONFIG_DMA_NONCOHERENT) + +#if defined(dma_cache_wback_inv) + dma_cache_wback_inv((NPS_HUGE_T)ptr_virt_addr, size); +#else + dma_cache_sync(NULL, ptr_virt_addr, size, DMA_FROM_DEVICE); +#endif + +#endif + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_mdc_savePciConfig( + const UI32_T unit) +{ + return _osal_mdc_savePciConfig(unit); +} + +NPS_ERROR_NO_T +osal_mdc_restorePciConfig( + const UI32_T unit) +{ + return _osal_mdc_restorePciConfig(unit); +} + +#endif /* End of NPS_LINUX_KERNEL_MODE */ + +/* --------------------------------------------------------------------------- Interrupt */ +#if defined(NPS_LINUX_USER_MODE) +static UI32_T _osal_mdc_isr_init_bitmap = 0; /* To record the dev request_irq */ +static UI32_T _osal_mdc_isr_dev_bitmap; /* To record the dev bitmap */ +static spinlock_t _osal_mdc_isr_dev_bitmap_lock; +static wait_queue_head_t _osal_mdc_isr_wait; +static UI32_T _osal_mdc_isr_mask_addr; +static UI32_T _osal_mdc_isr_mask_val; + + +static inline NPS_ERROR_NO_T +_osal_mdc_initInterrupt(void) +{ + /* init top and bottom halves */ + init_waitqueue_head(&_osal_mdc_isr_wait); + + /* init lock and clear device bitmap */ + spin_lock_init(&_osal_mdc_isr_dev_bitmap_lock); + _osal_mdc_isr_dev_bitmap = 0; + _osal_mdc_isr_init_bitmap = 0; + + /* clear chip interrupt mask address and value */ + _osal_mdc_isr_mask_addr = 0; + _osal_mdc_isr_mask_val = 0; + + return (NPS_E_OK); +} + +/* top half */ +static inline NPS_ERROR_NO_T +_osal_mdc_notifyUserProcess( + const UI32_T unit) +{ + unsigned long flags = 0; + + /* mask chip interrupt */ + osal_mdc_writePciReg(unit, _osal_mdc_isr_mask_addr, + &_osal_mdc_isr_mask_val, sizeof(UI32_T)); + + /* set the device bitmap. */ + spin_lock_irqsave(&_osal_mdc_isr_dev_bitmap_lock, flags); + _osal_mdc_isr_dev_bitmap |= (1U << unit); + spin_unlock_irqrestore(&_osal_mdc_isr_dev_bitmap_lock, flags); + + /* notify user process. */ + wake_up_interruptible(&_osal_mdc_isr_wait); + + return (NPS_E_OK); +} + +static inline NPS_ERROR_NO_T +_osal_mdc_waitEvent( + UI32_T *ptr_dev_bitmap) +{ + unsigned long flags = 0; + + wait_event_interruptible(_osal_mdc_isr_wait, (0 != _osal_mdc_isr_dev_bitmap)); + + /* save and clear the device bitmap. */ + spin_lock_irqsave(&_osal_mdc_isr_dev_bitmap_lock, flags); + *ptr_dev_bitmap = _osal_mdc_isr_dev_bitmap; + _osal_mdc_isr_dev_bitmap = 0; + spin_unlock_irqrestore(&_osal_mdc_isr_dev_bitmap_lock, flags); + + return (NPS_E_OK); +} + +static ssize_t +_osal_mdc_read( + struct file *filep, + char __user *buf, + size_t count, + loff_t *ppos) +{ + ssize_t ret; + UI32_T dev_bitmap = 0; + + if (count != sizeof(UI32_T)) + { + return -EINVAL; + } + + /* check if request_irq is inited. */ + if (0 != _osal_mdc_isr_init_bitmap) + { + _osal_mdc_waitEvent(&dev_bitmap); + } + + /* copy the device bitmap to user process. */ + if (0 != copy_to_user(buf, &dev_bitmap, count)) + { + ret = -EFAULT; + } + else + { + ret = count; + } + + return ret; +} +#endif /* End of NPS_LINUX_USER_MODE */ + +static irqreturn_t +_osal_mdc_systemIntrCallback( + int irq, + void *ptr_cookie) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + int linux_rc = IRQ_HANDLED; + OSAL_MDC_DEV_T *ptr_dev = (OSAL_MDC_DEV_T *)ptr_cookie; + + /* Invoke kernel callback, the callback function exist only in below cases: + * 1. SDK built in kernel mode + * 2. SDK built in user mode, NetIF kernel module is enabled + */ + if (NULL != ptr_dev->isr_callback) + { + rc = ptr_dev->isr_callback(ptr_dev->ptr_isr_data); + if (NPS_E_OK != rc) + { + OSAL_MDC_ERR("handle irq failed, rc=%d\n", rc); + linux_rc = IRQ_NONE; + } + } + +#if defined(NPS_LINUX_USER_MODE) + /* Notify user process */ + rc = _osal_mdc_notifyUserProcess(ptr_dev->unit); + if (NPS_E_OK != rc) + { + OSAL_MDC_ERR("notify intr to usr failed, rc=%d\n", rc); + linux_rc = IRQ_NONE; + } +#endif + + return (linux_rc); +} + +NPS_ERROR_NO_T +osal_mdc_registerIsr( + const UI32_T unit, + AML_DEV_ISR_FUNC_T handler, + void *ptr_cookie) +{ + OSAL_MDC_DEV_T *ptr_dev = &_osal_mdc_cb.dev[unit]; + + ptr_dev->isr_callback = handler; + ptr_dev->ptr_isr_data = (void *)((NPS_HUGE_T)unit); + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_mdc_connectIsr( + const UI32_T unit, + AML_DEV_ISR_FUNC_T handler, + AML_DEV_ISR_DATA_T *ptr_cookie) +{ + OSAL_MDC_DEV_T *ptr_dev = &_osal_mdc_cb.dev[unit]; + int linux_rc = 0; + NPS_ERROR_NO_T rc = NPS_E_OK; + +#if defined(NPS_LINUX_USER_MODE) + if (NULL != ptr_cookie) + { + _osal_mdc_isr_mask_addr = ptr_cookie->mask_addr; + _osal_mdc_isr_mask_val = ptr_cookie->mask_val; + } +#endif + + if (NULL == ptr_dev->isr_callback) + { +#if defined(NPS_LINUX_KERNEL_MODE) + /* In user mode, the following database is created in user space. */ + ptr_dev->isr_callback = handler; + ptr_dev->ptr_isr_data = (void *)((NPS_HUGE_T)unit); +#endif + +#if defined(OSAL_MDC_EN_MSI) + /* If "no_msi" flag is set, it means the device doesn't support MSI. */ + if (1 != ptr_dev->ptr_pci_dev->no_msi) + { + linux_rc = pci_enable_msi(ptr_dev->ptr_pci_dev); + if (0 == linux_rc) + { + /* The system gives a new irq number if MSI is enabled sucessfully. */ + ptr_dev->irq = ptr_dev->ptr_pci_dev->irq; + } + else + { + OSAL_MDC_ERR("pci_enable_msi() failed, rc=%d\n", linux_rc); + rc = NPS_E_OTHERS; + } + } +#endif + + linux_rc = request_irq(ptr_dev->irq, _osal_mdc_systemIntrCallback, + 0, OSAL_MDC_DRIVER_NAME, (void *)ptr_dev); + + if (0 != linux_rc) + { + OSAL_MDC_ERR("request_irq() failed, rc=%d\n", linux_rc); + rc = NPS_E_OTHERS; + } + } + else + { + OSAL_MDC_ERR("double req isr err\n"); + rc = NPS_E_OTHERS; + } + return (rc); +} + +NPS_ERROR_NO_T +osal_mdc_disconnectIsr( + const UI32_T unit) +{ + OSAL_MDC_DEV_T *ptr_dev = &_osal_mdc_cb.dev[unit]; + + free_irq(ptr_dev->irq, (void *)ptr_dev); + +#if defined(OSAL_MDC_EN_MSI) + /* Must free the irq before disabling MSI */ + pci_disable_msi(ptr_dev->ptr_pci_dev); +#endif + +#if defined(NPS_LINUX_KERNEL_MODE) + ptr_dev->isr_callback = NULL; + ptr_dev->ptr_isr_data = NULL; +#endif + +#if defined(NPS_LINUX_USER_MODE) + _osal_mdc_isr_mask_addr = 0x0; + _osal_mdc_isr_mask_val = 0x0; +#endif + + return (NPS_E_OK); +} + +NPS_ERROR_NO_T +osal_mdc_initDevice( + AML_DEV_T *ptr_dev_list, + UI32_T *ptr_dev_num) +{ + OSAL_MDC_CB_T *ptr_cb = &_osal_mdc_cb; + NPS_ERROR_NO_T rc = NPS_E_OK; + + _ptr_osal_mdc_dev = ptr_dev_list; + + memset(ptr_cb, 0x0, sizeof(OSAL_MDC_CB_T)); + +#if defined(AML_EN_I2C) + rc = _osal_mdc_probeI2cDevice(); + *ptr_dev_num = 1; +#else + rc = _osal_mdc_probePciDevice(); + *ptr_dev_num = ptr_cb->dev_num; + + _ptr_ext_pci_dev = _osal_mdc_cb.dev[0].ptr_pci_dev; +#endif /* End of AML_EN_I2C */ + + return (rc); +} + +NPS_ERROR_NO_T +osal_mdc_deinitDevice(void) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + +#if defined(AML_EN_I2C) + rc = _osal_mdc_removeI2cDevice(); +#else + if (NULL != _ptr_ext_pci_dev) + { + rc = _osal_mdc_removePciDevice(); + _ptr_ext_pci_dev = NULL; + } +#endif + + return (rc); +} + +/*****************************************************************************/ +#if defined(NPS_LINUX_USER_MODE) +/* Interface */ +static UI32_T _osal_mdc_devInited = 0; + +/* DMA */ +#if defined(NPS_EN_DMA_RESERVED) +static UI32_T _osal_mdc_rsvDmaInited = 0; +#else +static struct list_head _osal_mdc_sysDmaList[2]; /* To avoid memory corruption when cold-boot */ +static UI32_T _osal_mdc_sysCurDmaListIdx = 0; +#endif + +/* IOCTL */ +static OSAL_MDC_IOCTL_CB_T _osal_mdc_ioctl_cb; +static AML_DEV_T _osal_mdc_ioctl_dev[NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM] = {}; + +static int +_osal_mdc_open( + struct inode *ptr_inode, + struct file *ptr_file) +{ + return (0); +} + +static int +_osal_mdc_release( + struct inode *ptr_inode, + struct file *ptr_file) +{ + return (0); +} + +static struct vm_operations_struct _osal_mdc_remap_vm_ops = +{ + .open = NULL, + .close = NULL, +}; + +static int +_osal_mdc_mmap( + struct file *filp, + struct vm_area_struct *vma) +{ + size_t size = vma->vm_end - vma->vm_start; + int linux_rc = 0; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,0,48) + pgprot_val(vma->vm_page_prot) |= (_PAGE_NO_CACHE | _PAGE_GUARDED); +#else + UI32_T dev_idx; + OSAL_MDC_DEV_T *ptr_dev; + NPS_ADDR_T phy_addr = vma->vm_pgoff << PAGE_SHIFT; + + /* check mmio base phy addr */ + for (dev_idx = 0, ptr_dev = &_osal_mdc_cb.dev[0]; + dev_idx < _osal_mdc_cb.dev_num; + dev_idx++, ptr_dev++) + { + if ((NULL != ptr_dev->ptr_pci_dev) && + (phy_addr == pci_resource_start(ptr_dev->ptr_pci_dev, OSAL_MDC_PCI_BAR0_OFFSET))) + { + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + break; + } + } +#endif + + vma->vm_flags |= VM_IO; + if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + size, vma->vm_page_prot)) + { + linux_rc = -EAGAIN; + } + vma->vm_ops = &_osal_mdc_remap_vm_ops; + return (linux_rc); +} + +#if defined(NPS_EN_DMA_RESERVED) + +static NPS_ERROR_NO_T +_osal_mdc_ioctl_initRsrvDmaMemCallback( + const UI32_T unit, + void *ptr_data) +{ + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + OSAL_MDC_IOCTL_DMA_DATA_T *ptr_ioctl_data = (OSAL_MDC_IOCTL_DMA_DATA_T *)ptr_data; + NPS_ERROR_NO_T rc = NPS_E_OK; + + if (0 == _osal_mdc_rsvDmaInited) + { + rc = _osal_mdc_initRsrvDmaMem(ptr_dma_info); + _osal_mdc_rsvDmaInited = 1; + } + ptr_ioctl_data->rsrv_dma_phy_addr = ptr_dma_info->rsrv_phy_addr; + ptr_ioctl_data->rsrv_dma_size = ptr_dma_info->rsrv_size; + + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_ioctl_deinitRsrvDmaMemCallback( + const UI32_T unit, + void *ptr_data) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + + rc = _osal_mdc_deinitRsrvDmaMem(&_osal_mdc_cb.dma_info); + _osal_mdc_rsvDmaInited = 0; + + return (rc); +} + +#else + +static NPS_ERROR_NO_T +_osal_mdc_clearSysDmaList( + UI32_T dmaListIdx) +{ + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + OSAL_MDC_USER_MODE_DMA_NODE_T *ptr_curr_node_data = NULL; + OSAL_MDC_USER_MODE_DMA_NODE_T *ptr_next_node_data = NULL; + void *ptr_virt_addr; + + list_for_each_entry_safe(ptr_curr_node_data, ptr_next_node_data, + &_osal_mdc_sysDmaList[dmaListIdx], list) + { + list_del(&(ptr_curr_node_data->list)); + ptr_virt_addr = phys_to_virt(ptr_curr_node_data->phy_addr); + dma_free_coherent(ptr_dma_info->ptr_dma_dev, + ptr_curr_node_data->size, ptr_virt_addr, + ptr_curr_node_data->phy_addr); + kfree(ptr_curr_node_data); + } + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_osal_mdc_ioctl_allocSysDmaMemCallback( + const UI32_T unit, + void *ptr_data) +{ + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + OSAL_MDC_IOCTL_DMA_DATA_T *ptr_ioctl_data = (OSAL_MDC_IOCTL_DMA_DATA_T *)ptr_data; + OSAL_MDC_USER_MODE_DMA_NODE_T *ptr_node_data = NULL; + +/* To defense the compatible data type of 32bit and 64bit are not synchronized */ +#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) /* Bus addressing is 64-bit */\ +&& !defined(NPS_EN_64BIT_ADDR) /* SDK follows HOST with 32-bit addr*/\ +&& (defined(NPS_EN_HOST_32_BIT_LITTLE_ENDIAN) || defined(NPS_EN_HOST_32_BIT_BIG_ENDIAN))/* HOST is 32-bit */ +#error "The DMA address of OS is 64bit. Please enable NPS_EN_64BIT_ADDR in SDK." +#endif + +#if !defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) && defined(NPS_EN_64BIT_ADDR) +#error "The DMA address of OS is not 64bit. Please disable NPS_EN_64BIT_ADDR in SDK." +#endif + + if (NULL == dma_alloc_coherent(ptr_dma_info->ptr_dma_dev, ptr_ioctl_data->size, + (dma_addr_t *)&ptr_ioctl_data->phy_addr, GFP_ATOMIC)) + { + return (NPS_E_NO_MEMORY); + } + + ptr_node_data = kmalloc(sizeof(OSAL_MDC_USER_MODE_DMA_NODE_T), GFP_KERNEL); + if (NULL != ptr_node_data) + { + memset(ptr_node_data, 0, sizeof(OSAL_MDC_USER_MODE_DMA_NODE_T)); + ptr_node_data->phy_addr = ptr_ioctl_data->phy_addr; + ptr_node_data->size = ptr_ioctl_data->size; + list_add(&(ptr_node_data->list), &_osal_mdc_sysDmaList[_osal_mdc_sysCurDmaListIdx]); + } + else + { + dma_free_coherent(ptr_dma_info->ptr_dma_dev, ptr_ioctl_data->size, + phys_to_virt(ptr_ioctl_data->phy_addr), ptr_ioctl_data->phy_addr); + + return (NPS_E_NO_MEMORY); + } + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_osal_mdc_ioctl_freeSysDmaMemCallback( + const UI32_T unit, + void *ptr_data) +{ + OSAL_MDC_DMA_INFO_T *ptr_dma_info = &_osal_mdc_cb.dma_info; + OSAL_MDC_IOCTL_DMA_DATA_T *ptr_ioctl_data = (OSAL_MDC_IOCTL_DMA_DATA_T *)ptr_data; + void *ptr_virt_addr; + + OSAL_MDC_USER_MODE_DMA_NODE_T *ptr_curr_node_data = NULL; + OSAL_MDC_USER_MODE_DMA_NODE_T *ptr_next_node_data = NULL; + + + list_for_each_entry_safe(ptr_curr_node_data, ptr_next_node_data, + &_osal_mdc_sysDmaList[_osal_mdc_sysCurDmaListIdx], list) + { + if (ptr_curr_node_data->phy_addr == ptr_ioctl_data->phy_addr) + { + list_del(&(ptr_curr_node_data->list)); + kfree(ptr_curr_node_data); + break; + } + } + + ptr_virt_addr = phys_to_virt(ptr_ioctl_data->phy_addr); + dma_free_coherent(ptr_dma_info->ptr_dma_dev, ptr_ioctl_data->size, + ptr_virt_addr, ptr_ioctl_data->phy_addr); + + return (NPS_E_OK); +} + +#endif + +static NPS_ERROR_NO_T +_osal_mdc_getPciInfoToIoctlData( + const OSAL_MDC_DEV_T *ptr_dev_list, + OSAL_MDC_IOCTL_DEV_DATA_T *ptr_dev_data) +{ + UI32_T idx; + + /* Search for PCIe device and get the MMIO base address. */ + for (idx = 0; idx < _osal_mdc_cb.dev_num; idx++) + { + if (NULL != ptr_dev_list[idx].ptr_pci_dev) + { + ptr_dev_data->pci_mmio_phy_start[idx] = + pci_resource_start(ptr_dev_list[idx].ptr_pci_dev, OSAL_MDC_PCI_BAR0_OFFSET); + + ptr_dev_data->pci_mmio_size[idx] = + pci_resource_len(ptr_dev_list[idx].ptr_pci_dev, OSAL_MDC_PCI_BAR0_OFFSET); + } + } + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_osal_mdc_getDeviceIdToIoctlData( + AML_DEV_T *ptr_dev, + OSAL_MDC_IOCTL_DEV_DATA_T *ptr_dev_data, + const UI32_T dev_num) +{ + UI32_T idx; + + for (idx = 0; idx < ptr_dev_data->dev_num; idx++) + { + ptr_dev_data->id[idx].device = ptr_dev[idx].id.device; + ptr_dev_data->id[idx].vendor = ptr_dev[idx].id.vendor; + ptr_dev_data->id[idx].revision = ptr_dev[idx].id.revision; + } + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_osal_mdc_ioctl_initDeviceCallback( + const UI32_T unit, + void *ptr_data) +{ + OSAL_MDC_CB_T *ptr_cb = &_osal_mdc_cb; + OSAL_MDC_DEV_T *ptr_dev_list = _osal_mdc_cb.dev; + OSAL_MDC_IOCTL_DEV_DATA_T *ptr_ioctl_data = (OSAL_MDC_IOCTL_DEV_DATA_T *)ptr_data; + + /* "dev" is just created for invoking osal_mdc_initDevice, + * it is no use once the device IDs are copy to ptr_ioctl_data. + */ + + NPS_ERROR_NO_T rc = NPS_E_OK; + + if (0 == _osal_mdc_devInited) + { + rc = osal_mdc_initDevice(_osal_mdc_ioctl_dev, &ptr_ioctl_data->dev_num); + } + else + { + /* ptr_cb->dev_num was initialized in osal_mdc_initDevice(); */ + ptr_ioctl_data->dev_num = ptr_cb->dev_num; + } + + if (ptr_cb->dev_num >= NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM) + { + OSAL_MDC_ERR("dev num=%d > max support num=%d\n", + ptr_ioctl_data->dev_num, NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM); + } + +#if !defined(NPS_EN_DMA_RESERVED) + if (0 == _osal_mdc_devInited) + { + /* Create two DMA memory lists and use 1st. */ + INIT_LIST_HEAD(&_osal_mdc_sysDmaList[0]); + INIT_LIST_HEAD(&_osal_mdc_sysDmaList[1]); + _osal_mdc_sysCurDmaListIdx = 0; + } + else + { + /* Delay free the old list until the chip is reset. + * When we kill the process, the chip continues to write to the DMA memory. + * If we free the old DMA memory before stopping the chip, there could be memory corruption. + */ + _osal_mdc_sysCurDmaListIdx = ((_osal_mdc_sysCurDmaListIdx + 1) & 0x1); + rc = _osal_mdc_clearSysDmaList(_osal_mdc_sysCurDmaListIdx); + } +#endif + + if (NPS_E_OK == rc) + { + rc = _osal_mdc_getDeviceIdToIoctlData(_osal_mdc_ioctl_dev, ptr_ioctl_data, ptr_ioctl_data->dev_num); + } + if (NPS_E_OK == rc) + { + rc = _osal_mdc_getPciInfoToIoctlData(ptr_dev_list, ptr_ioctl_data); + } + + _osal_mdc_devInited = 1; + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_ioctl_deinitDeviceCallback( + const UI32_T unit, + void *ptr_data) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + +#if !defined(NPS_EN_DMA_RESERVED) + _osal_mdc_clearSysDmaList(0); + _osal_mdc_clearSysDmaList(1); +#endif + + if (0 != _osal_mdc_devInited) + { + rc = osal_mdc_deinitDevice(); + _osal_mdc_devInited = 0; + } + + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_ioctl_connectIsrCallback( + const UI32_T unit, + void *ptr_data) +{ + NPS_ERROR_NO_T rc = NPS_E_OK; + + if (0 == (_osal_mdc_isr_init_bitmap & (1U << unit))) + { + rc = osal_mdc_connectIsr(unit, NULL, ptr_data); + if (NPS_E_OK == rc) + { + _osal_mdc_isr_init_bitmap |= (1U << unit); + } + } + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_ioctl_disconnectIsrCallback( + const UI32_T unit, + void *ptr_data) +{ + /* To make the user-space polling task return from read. */ + _osal_mdc_notifyUserProcess(unit); + + osal_mdc_disconnectIsr(unit); + _osal_mdc_isr_init_bitmap &= ~(1U << unit); + + return (NPS_E_OK); +} + +static NPS_ERROR_NO_T +_osal_mdc_ioctl_savePciConfigCallback( + const UI32_T unit, + void *ptr_data) +{ + return _osal_mdc_savePciConfig(unit); +} + +static NPS_ERROR_NO_T +_osal_mdc_ioctl_restorePciConfigCallback( + const UI32_T unit, + void *ptr_data) +{ + return _osal_mdc_restorePciConfig(unit); +} + +static NPS_ERROR_NO_T +_osal_mdc_registerIoctlCallback( + const OSAL_MDC_IOCTL_TYPE_T type, + const OSAL_MDC_IOCTL_CALLBACK_FUNC_T func) +{ + OSAL_MDC_IOCTL_CB_T *ptr_cb = &_osal_mdc_ioctl_cb; + NPS_ERROR_NO_T rc = NPS_E_OTHERS; + + if (type < OSAL_MDC_IOCTL_TYPE_LAST) + { + if (NULL == ptr_cb->callback[type]) + { + ptr_cb->callback[type] = func; + rc = NPS_E_OK; + } + else + { + OSAL_MDC_ERR("register ioctl callback failed, type=%d exist\n", type); + } + } + else + { + OSAL_MDC_ERR("register ioctl callback failed, type=%d >= max=%d\n", + type, OSAL_MDC_IOCTL_TYPE_LAST); + } + return (rc); +} + +static NPS_ERROR_NO_T +_osal_mdc_initIoctl(void) +{ + memset(&_osal_mdc_ioctl_cb, 0x0, sizeof(OSAL_MDC_IOCTL_CB_T)); + + _osal_mdc_registerIoctlCallback(OSAL_MDC_IOCTL_TYPE_MDC_INIT_DEV, + _osal_mdc_ioctl_initDeviceCallback); + + _osal_mdc_registerIoctlCallback(OSAL_MDC_IOCTL_TYPE_MDC_DEINIT_DEV, + _osal_mdc_ioctl_deinitDeviceCallback); +#if defined(NPS_EN_DMA_RESERVED) + _osal_mdc_registerIoctlCallback(OSAL_MDC_IOCTL_TYPE_MDC_INIT_RSRV_DMA_MEM, + _osal_mdc_ioctl_initRsrvDmaMemCallback); + + _osal_mdc_registerIoctlCallback(OSAL_MDC_IOCTL_TYPE_MDC_DEINIT_RSRV_DMA_MEM, + _osal_mdc_ioctl_deinitRsrvDmaMemCallback); +#else + _osal_mdc_registerIoctlCallback(OSAL_MDC_IOCTL_TYPE_MDC_ALLOC_SYS_DMA_MEM, + _osal_mdc_ioctl_allocSysDmaMemCallback); + + _osal_mdc_registerIoctlCallback(OSAL_MDC_IOCTL_TYPE_MDC_FREE_SYS_DMA_MEM, + _osal_mdc_ioctl_freeSysDmaMemCallback); +#endif + _osal_mdc_registerIoctlCallback(OSAL_MDC_IOCTL_TYPE_MDC_CONNECT_ISR, + _osal_mdc_ioctl_connectIsrCallback); + + _osal_mdc_registerIoctlCallback(OSAL_MDC_IOCTL_TYPE_MDC_DISCONNECT_ISR, + _osal_mdc_ioctl_disconnectIsrCallback); + + _osal_mdc_registerIoctlCallback(OSAL_MDC_IOCTL_TYPE_MDC_SAVE_PCI_CONFIG, + _osal_mdc_ioctl_savePciConfigCallback); + + _osal_mdc_registerIoctlCallback(OSAL_MDC_IOCTL_TYPE_MDC_RESTORE_PCI_CONFIG, + _osal_mdc_ioctl_restorePciConfigCallback); + return (NPS_E_OK); +} + +static long +_osal_mdc_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long arg) +{ +#define OSAL_MDC_IOCTL_LOCAL_BUF_SIZE (128) + + OSAL_MDC_IOCTL_CB_T *ptr_cb = &_osal_mdc_ioctl_cb; + OSAL_MDC_IOCTL_CMD_T *ptr_cmd = (OSAL_MDC_IOCTL_CMD_T *)&cmd; + UI32_T unit = ptr_cmd->field.unit; + OSAL_MDC_IOCTL_TYPE_T type = ptr_cmd->field.type; + OSAL_MDC_IOCTL_ACCESS_T access = ptr_cmd->field.access; + UI32_T data_size = ptr_cmd->field.size; + UI8_T temp_buf[OSAL_MDC_IOCTL_LOCAL_BUF_SIZE]; + UI8_T *ptr_temp_buf; + int linux_rc = 0; + + if (NULL != ptr_cb->callback[type]) + { + if (data_size > OSAL_MDC_IOCTL_LOCAL_BUF_SIZE) + { + ptr_temp_buf = kmalloc(data_size, GFP_KERNEL); + } + else + { + ptr_temp_buf = temp_buf; + } + + /*************************************************************/ + if (OSAL_MDC_IOCTL_ACCESS_WRITE == access) + { + /* type: FREE_SYS_DMA_MEM : DMA physical address + * CONNECT_ISR : Chip interrupt mask address and value + */ + if (copy_from_user(ptr_temp_buf, (int __user *)arg, data_size)) + { + linux_rc = -EFAULT; + } + else + { + if (NPS_E_OK != ptr_cb->callback[type](unit, (void *)ptr_temp_buf)) + { + linux_rc = -EFAULT; + } + } + } + else if (OSAL_MDC_IOCTL_ACCESS_READ == access) + { + /* type: INIT_DEV : PCIe device and vendor ID, mmio address and size + * INIT_RSRV_DMA_MEM : Reserved DMA physical address and size + */ + if (NPS_E_OK != ptr_cb->callback[type](unit, (void *)ptr_temp_buf)) + { + linux_rc = -EFAULT; + } + else + { + if (copy_to_user((int __user *)arg, ptr_temp_buf, data_size)) + { + linux_rc = -EFAULT; + } + } + } + else if (OSAL_MDC_IOCTL_ACCESS_READ_WRITE == access) + { + /* type: ALLOC_SYS_DMA_MEM : DMA physical address + */ + if (copy_from_user(ptr_temp_buf, (int __user *)arg, data_size)) + { + linux_rc = -EFAULT; + } + else + { + if (NPS_E_OK != ptr_cb->callback[type](unit, (void *)ptr_temp_buf)) + { + linux_rc = -EFAULT; + } + else + { + if (copy_to_user((int __user *)arg, ptr_temp_buf, data_size)) + { + linux_rc = -EFAULT; + } + } + } + } + else if (OSAL_MDC_IOCTL_ACCESS_NONE == access) + { + /* type: DEINIT_DEV + * DEINIT_RSRV_DMA_MEM + * DISCONNECT_ISR + * SAVE_PCI_CONFIG + * RESTORE_PCI_CONFIG + */ + if (NPS_E_OK != ptr_cb->callback[type](unit, (void *)ptr_temp_buf)) + { + linux_rc = -EFAULT; + } + } + /*************************************************************/ + + if (data_size > OSAL_MDC_IOCTL_LOCAL_BUF_SIZE) + { + kfree(ptr_temp_buf); + } + } + else + { + OSAL_MDC_ERR("invalid ioctl, cmd=%u, arg=%lu, type=%d\n", cmd, arg, type); + } + return (linux_rc); +} + +#ifdef CONFIG_COMPAT +static long +_osal_mdc_compat_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long arg) +{ + return _osal_mdc_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + +static struct file_operations _osal_mdc_fops = +{ + .owner = THIS_MODULE, + .open = _osal_mdc_open, + .read = _osal_mdc_read, + .release = _osal_mdc_release, + .unlocked_ioctl = _osal_mdc_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = _osal_mdc_compat_ioctl, +#endif + .mmap = _osal_mdc_mmap, +}; + +static struct miscdevice _osal_mdc_misc = +{ + .minor = OSAL_MDC_DRIVER_MISC_MINOR_NUM, + .name = OSAL_MDC_DRIVER_NAME, + .fops = & _osal_mdc_fops, +}; + +static int __init +osal_mdc_module_init(void) +{ + int linux_rc; + + _osal_mdc_initIoctl(); /* To register IOCTL callback functions. */ + _osal_mdc_initInterrupt(); /* To init structs for top and bottom halves */ + + linux_rc = misc_register(&_osal_mdc_misc); + if (0 != linux_rc) + { + OSAL_MDC_ERR("register dev %s failed, linux_rc=%d\n", OSAL_MDC_DRIVER_NAME, linux_rc); + } + return (linux_rc); +} + +static void __exit +osal_mdc_module_exit(void) +{ + int unit = 0; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,2,8) + int linux_rc; + + linux_rc = misc_deregister(&_osal_mdc_misc); + if (0 != linux_rc) + { + OSAL_MDC_ERR("de-register dev %s failed, linux_rc=%d\n", OSAL_MDC_DRIVER_NAME, linux_rc); + } +#else + misc_deregister(&_osal_mdc_misc); +#endif + + /* ref: _osal_mdc_ioctl_disconnectIsrCallback */ + for (unit = 0; unit < NPS_CFG_MAXIMUM_CHIPS_PER_SYSTEM; unit++) + { + if (0 != (_osal_mdc_isr_init_bitmap & (1U << unit))) + { + osal_mdc_disconnectIsr(unit); + _osal_mdc_isr_init_bitmap &= ~(1U << unit); + } + } + + /* ref: _osal_mdc_ioctl_deinitRsrvDmaMemCallback */ +#if defined(NPS_EN_DMA_RESERVED) + if (1 == _osal_mdc_rsvDmaInited) + { + _osal_mdc_deinitRsrvDmaMem(&_osal_mdc_cb.dma_info); + _osal_mdc_rsvDmaInited = 0; + } +#endif + + /* ref: _osal_mdc_ioctl_deinitDeviceCallback */ + if (1 == _osal_mdc_devInited) + { +#if !defined(NPS_EN_DMA_RESERVED) + _osal_mdc_clearSysDmaList(0); + _osal_mdc_clearSysDmaList(1); +#endif + osal_mdc_deinitDevice(); + _osal_mdc_devInited = 0; + } +} + +#else + +static int __init +osal_mdc_module_init(void) +{ + return (0); +} + +static void __exit +osal_mdc_module_exit(void) +{ + +} + +#endif /* End of NPS_LINUX_USER_MODE */ + +module_init(osal_mdc_module_init); +module_exit(osal_mdc_module_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("MediaTek"); +MODULE_DESCRIPTION("SDK Kernel Module"); diff --git a/platform/nephos/one-image.mk b/platform/nephos/one-image.mk new file mode 100644 index 000000000000..60254051c5b5 --- /dev/null +++ b/platform/nephos/one-image.mk @@ -0,0 +1,21 @@ +# sonic nephos one image installer + +SONIC_ONE_IMAGE = sonic-nephos.bin +$(SONIC_ONE_IMAGE)_MACHINE = nephos +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(NEPHOS_MODULE) +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9130_32X_PLATFORM_MODULE) \ + $(INGRASYS_S9230_64X_PLATFORM_MODULE) \ + $(ACCTON_AS7116_54X_PLATFORM_MODULE) \ + $(CIG_CS6436_56P_PLATFORM_MODULE) \ + $(CIG_CS6436_54P_PLATFORM_MODULE) \ + $(CIG_CS5435_54P_PLATFORM_MODULE) + +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/nephos/platform-modules-accton.mk b/platform/nephos/platform-modules-accton.mk new file mode 100644 index 000000000000..1ecb76a2fbb8 --- /dev/null +++ b/platform/nephos/platform-modules-accton.mk @@ -0,0 +1,12 @@ +# Accton AS7116 54X Platform modules + +ACCTON_AS7116_54X_PLATFORM_MODULE_VERSION = 1.0.1 + +export ACCTON_AS7116_54X_PLATFORM_MODULE_VERSION + +ACCTON_AS7116_54X_PLATFORM_MODULE = sonic-platform-accton-as7116-54x_$(ACCTON_AS7116_54X_PLATFORM_MODULE_VERSION)_amd64.deb +$(ACCTON_AS7116_54X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton +$(ACCTON_AS7116_54X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(ACCTON_AS7116_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as7116_54x-r0 +SONIC_DPKG_DEBS += $(ACCTON_AS7116_54X_PLATFORM_MODULE) + diff --git a/platform/nephos/platform-modules-cig.mk b/platform/nephos/platform-modules-cig.mk new file mode 100644 index 000000000000..48e7072f6da3 --- /dev/null +++ b/platform/nephos/platform-modules-cig.mk @@ -0,0 +1,23 @@ +# Cig Nephos Switch Platform modules + +CIG_MTK_PLATFORM_MODULE_VERSION = 1.0.0 + +export CIG_MTK_PLATFORM_MODULE_VERSION + +CIG_CS6436_56P_PLATFORM_MODULE = sonic-platform-cig-cs6436-56p_$(CIG_MTK_PLATFORM_MODULE_VERSION)_amd64.deb +$(CIG_CS6436_56P_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cig +$(CIG_CS6436_56P_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(CIG_CS6436_56P_PLATFORM_MODULE)_PLATFORM = x86_64-cig_cs6436_56p-r0 +SONIC_DPKG_DEBS += $(CIG_CS6436_56P_PLATFORM_MODULE) + +CIG_CS6436_54P_PLATFORM_MODULE = sonic-platform-cig-cs6436-54p_$(CIG_MTK_PLATFORM_MODULE_VERSION)_amd64.deb +$(CIG_CS6436_54P_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cig +$(CIG_CS6436_54P_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(CIG_CS6436_54P_PLATFORM_MODULE)_PLATFORM = x86_64-cig_cs6436_54p-r0 +SONIC_DPKG_DEBS += $(CIG_CS6436_54P_PLATFORM_MODULE) + +CIG_CS5435_54P_PLATFORM_MODULE = sonic-platform-cig-cs5435-54p_$(CIG_MTK_PLATFORM_MODULE_VERSION)_amd64.deb +$(CIG_CS5435_54P_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-cig +$(CIG_CS5435_54P_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(CIG_CS5435_54P_PLATFORM_MODULE)_PLATFORM = x86_64-cig_cs5435_54p-r0 +SONIC_DPKG_DEBS += $(CIG_CS5435_54P_PLATFORM_MODULE) diff --git a/platform/nephos/platform-modules-ingrasys.mk b/platform/nephos/platform-modules-ingrasys.mk new file mode 100644 index 000000000000..03818ca8465d --- /dev/null +++ b/platform/nephos/platform-modules-ingrasys.mk @@ -0,0 +1,19 @@ +# Ingrasys S9130-32X and S9230-64X Platform modules + +INGRASYS_S9130_32X_PLATFORM_MODULE_VERSION = 1.0.0 +INGRASYS_S9230_64X_PLATFORM_MODULE_VERSION = 1.0.0 + +export INGRASYS_S9130_32X_PLATFORM_MODULE_VERSION +export INGRASYS_S9230_64X_PLATFORM_MODULE_VERSION + +INGRASYS_S9130_32X_PLATFORM_MODULE = sonic-platform-ingrasys-s9130-32x_$(INGRASYS_S9130_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9130_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ingrasys +$(INGRASYS_S9130_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(INGRASYS_S9130_32X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9130_32x-r0 +SONIC_DPKG_DEBS += $(INGRASYS_S9130_32X_PLATFORM_MODULE) + +INGRASYS_S9230_64X_PLATFORM_MODULE = sonic-platform-ingrasys-s9230-64x_$(INGRASYS_S9230_64X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9230_64X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9230_64x-r0 + +$(eval $(call add_extra_package,$(INGRASYS_S9130_32X_PLATFORM_MODULE),$(INGRASYS_S9230_64X_PLATFORM_MODULE))) + diff --git a/platform/nephos/platform-modules-pegatron.mk b/platform/nephos/platform-modules-pegatron.mk new file mode 100755 index 000000000000..9a411763cec2 --- /dev/null +++ b/platform/nephos/platform-modules-pegatron.mk @@ -0,0 +1,13 @@ +# Pegatron Platform modules + +PEGATRON_PORSCHE_PLATFORM_MODULE_VERSION = 0.1 + +export PEGATRON_PORSCHE_PLATFORM_MODULE_VERSION + +PEGATRON_PORSCHE_PLATFORM_MODULE = sonic-platform-pegatron-porsche_$(PEGATRON_PORSCHE_PLATFORM_MODULE_VERSION)_amd64.deb +$(PEGATRON_PORSCHE_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-pegatron +$(PEGATRON_PORSCHE_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(PEGATRON_PORSCHE_PLATFORM_MODULE)_PLATFORM = x86_64-pegatron_porsche-r0 +SONIC_DPKG_DEBS += $(PEGATRON_PORSCHE_PLATFORM_MODULE) + +$(eval $(call add_extra_package,$(PEGATRON_PORSCHE_PLATFORM_MODULE))) diff --git a/platform/nephos/platform.conf b/platform/nephos/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/rules.mk b/platform/nephos/rules.mk new file mode 100644 index 000000000000..4ee2443e7585 --- /dev/null +++ b/platform/nephos/rules.mk @@ -0,0 +1,33 @@ +include $(PLATFORM_PATH)/sai.mk +include $(PLATFORM_PATH)/nephos-modules.mk +include $(PLATFORM_PATH)/platform-modules-ingrasys.mk +include $(PLATFORM_PATH)/platform-modules-accton.mk +include $(PLATFORM_PATH)/platform-modules-cig.mk +include $(PLATFORM_PATH)/docker-syncd-nephos.mk +include $(PLATFORM_PATH)/docker-syncd-nephos-rpc.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk + +NPX_DIAG = npx_diag +$(NPX_DIAG)_URL = "https://github.com/NephosInc/SONiC/raw/master/sdk/npx_diag" + +WARM_VERIFIER = warm-verifier +$(WARM_VERIFIER)_URL = "https://github.com/NephosInc/SONiC/raw/master/sai/warm-verifier" + +DSSERVE = dsserve +$(DSSERVE)_URL = "https://sonicstorage.blob.core.windows.net/packages/20190307/dsserve?sv=2015-04-05&sr=b&sig=lk7BH3DtW%2F5ehc0Rkqfga%2BUCABI0UzQmDamBsZH9K6w%3D&se=2038-05-06T22%3A34%3A45Z&sp=r" + +SONIC_ONLINE_FILES += $(NPX_DIAG) $(WARM_VERIFIER) $(DSSERVE) + +SONIC_ALL += $(SONIC_ONE_IMAGE) $(DOCKER_FPM) + +# Inject nephos sai into syncd +$(SYNCD)_DEPENDS += $(NEPHOS_SAI) $(NEPHOS_SAI_DEV) +$(SYNCD)_UNINSTALLS += $(NEPHOS_SAI_DEV) + +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV) +endif + +# Runtime dependency on nephos sai is set only for syncd +$(SYNCD)_RDEPENDS += $(NEPHOS_SAI) diff --git a/platform/nephos/sai.mk b/platform/nephos/sai.mk new file mode 100644 index 000000000000..8bbeb9899b58 --- /dev/null +++ b/platform/nephos/sai.mk @@ -0,0 +1,36 @@ +SDK_VERSION = 3.0.0 +SAI_VERSION = 1.5.0 +SAI_COMMIT_ID = 06a67d + +# Place here URL where SAI deb exist +NEPHOS_SAI_DEB_LOCAL_URL = +export NEPHOS_SAI_DEB_LOCAL_URL +# +ifneq ($(NEPHOS_SAI_DEB_LOCAL_URL), ) +SAI_FROM_LOCAL = y +else +SAI_FROM_LOCAL = n +endif + +NEPHOS_SAI = libsainps_$(SDK_VERSION)_sai_$(SAI_VERSION)_$(SAI_COMMIT_ID)_amd64.deb +ifeq ($(SAI_FROM_LOCAL), y) +$(NEPHOS_SAI)_PATH = $(NEPHOS_SAI_DEB_LOCAL_URL) +else +$(NEPHOS_SAI)_URL = "https://github.com/NephosInc/SONiC/raw/master/sai/libsainps_$(SDK_VERSION)_sai_$(SAI_VERSION)_$(SAI_COMMIT_ID)_amd64.deb" +endif + +NEPHOS_SAI_DEV = libsainps-dev_$(SDK_VERSION)_sai_$(SAI_VERSION)_$(SAI_COMMIT_ID)_amd64.deb +$(eval $(call add_derived_package,$(NEPHOS_SAI),$(NEPHOS_SAI_DEV))) +ifeq ($(SAI_FROM_LOCAL), y) +$(NEPHOS_SAI_DEV)_PATH = $(NEPHOS_SAI_DEB_LOCAL_URL) +else +$(NEPHOS_SAI_DEV)_URL = "https://github.com/NephosInc/SONiC/raw/master/sai/libsainps-dev_$(SDK_VERSION)_sai_$(SAI_VERSION)_$(SAI_COMMIT_ID)_amd64.deb" +endif + +ifeq ($(SAI_FROM_LOCAL), y) +SONIC_COPY_DEBS += $(NEPHOS_SAI) $(NEPHOS_SAI_DEV) +else +SONIC_ONLINE_DEBS += $(NEPHOS_SAI) $(NEPHOS_SAI_DEV) +endif +$(NEPHOS_SAI_DEV)_DEPENDS += $(NEPHOS_SAI) +$(eval $(call add_conflict_package,$(NEPHOS_SAI_DEV),$(LIBSAIVS_DEV))) diff --git a/platform/nephos/sonic-platform-modules-accton/LICENSE b/platform/nephos/sonic-platform-modules-accton/LICENSE new file mode 100644 index 000000000000..bc693f7a4c40 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Accton Technology Corporation + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/nephos/sonic-platform-modules-accton/README.md b/platform/nephos/sonic-platform-modules-accton/README.md new file mode 100644 index 000000000000..0ff20bb2d21b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/README.md @@ -0,0 +1 @@ +platform drivers of Accton products for the SONiC project diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/Makefile b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/Makefile new file mode 100644 index 000000000000..2d838864a27a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := x86-64-accton-as7116-54x-cpld.o x86-64-accton-as7116-54x-fan.o \ + x86-64-accton-as7116-54x-led.o x86-64-accton-as7116-54x-psu.o x86-64-accton-as7116-54x-sfp.o \ No newline at end of file diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-cpld.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-cpld.c new file mode 100644 index 000000000000..eb52512343a8 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-cpld.c @@ -0,0 +1,242 @@ +/* + * A hwmon driver for the as7116_54x_cpld + * + * Copyright (C) 2017 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +/* Addresses scanned for as7116_54x_cpld + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + +static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL); + +static void as7116_54x_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as7116_54x_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int as7116_54x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + status = sysfs_create_file(&client->dev.kobj, &ver.attr); + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + as7116_54x_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int as7116_54x_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_file(&client->dev.kobj, &ver.attr); + as7116_54x_cpld_remove_client(client); + + return 0; +} + +enum cpld_chips +{ + as7116_54x_cpld1, + as7116_54x_cpld2, + as7116_54x_cpld3 +}; + +static const struct i2c_device_id as7116_54x_cpld_id[] = { + { "as7116_54x_cpld1", as7116_54x_cpld1 }, + { "as7116_54x_cpld2", as7116_54x_cpld2 }, + { "as7116_54x_cpld3", as7116_54x_cpld3 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7116_54x_cpld_id); + +static struct i2c_driver as7116_54x_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7116_54x_cpld", + }, + .probe = as7116_54x_cpld_probe, + .remove = as7116_54x_cpld_remove, + .id_table = as7116_54x_cpld_id, + .address_list = normal_i2c, +}; + +int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7116_54x_cpld_read); + +int as7116_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7116_54x_cpld_write); + +static int __init as7116_54x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7116_54x_cpld_driver); +} + +static void __exit as7116_54x_cpld_exit(void) +{ + i2c_del_driver(&as7116_54x_cpld_driver); +} + +static struct dmi_system_id as7116_54x_dmi_table[] = { + { + .ident = "Accton AS7716", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Accton"), + DMI_MATCH(DMI_PRODUCT_NAME, "AS7116"), + }, + } +}; + +int platform_accton_as7116_54x(void) +{ + //return dmi_check_system(as7116_54x_dmi_table); + return 1; +} +EXPORT_SYMBOL(platform_accton_as7116_54x); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7116_54x driver"); +MODULE_LICENSE("GPL"); + +module_init(as7116_54x_cpld_init); +module_exit(as7116_54x_cpld_exit); + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-fan.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-fan.c new file mode 100644 index 000000000000..f5159c8f166e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-fan.c @@ -0,0 +1,544 @@ +/* + * A hwmon driver for the Accton as7716 32x fan + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7116_54x_fan" + +static struct as7116_54x_fan_data *as7116_54x_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x02, /* fan 1-6 present status */ + 0x03, /* fan 1-6 direction(0:F2B 1:B2F) */ + 0x06, /* fan PWM(for all fan) */ + 0x04, /* front fan fault */ + 0x05, /* rear fan fault */ + 0x07, /* front fan 1 speed(rpm) */ + 0x08, /* front fan 2 speed(rpm) */ + 0x09, /* front fan 3 speed(rpm) */ + 0x0A, /* front fan 4 speed(rpm) */ + 0x0B, /* front fan 5 speed(rpm) */ + 0x0C, /* rear fan 1 speed(rpm) */ + 0x0D, /* rear fan 2 speed(rpm) */ + 0x0E, /* rear fan 3 speed(rpm) */ + 0x0f, /* rear fan 4 speed(rpm) */ + 0x10, /* rear fan 5 speed(rpm) */ +}; + +/* Each client has this additional data */ +struct as7116_54x_fan_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID +}; + +enum sysfs_fan_attributes { + FAN_PRESENT_REG, + FAN_DIRECTION_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN_FRONT_FAULT_REG, + FAN_REAR_FAULT_REG, + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN1_FRONT_FAULT, + FAN2_FRONT_FAULT, + FAN3_FRONT_FAULT, + FAN4_FRONT_FAULT, + FAN5_FRONT_FAULT, + FAN1_REAR_FAULT, + FAN2_REAR_FAULT, + FAN3_REAR_FAULT, + FAN4_REAR_FAULT, + FAN5_REAR_FAULT, + FAN1_INPUT, /* FAN1_FRONT_SPEED_RPM, */ + FAN2_INPUT, /* FAN2_FRONT_SPEED_RPM, */ + FAN3_INPUT, /* FAN3_FRONT_SPEED_RPM, */ + FAN4_INPUT, /* FAN4_FRONT_SPEED_RPM, */ + FAN5_INPUT, /* FAN5_FRONT_SPEED_RPM, */ + FAN6_INPUT, /* FAN1_REAR_SPEED_RPM, */ + FAN7_INPUT, /* FAN2_REAR_SPEED_RPM, */ + FAN8_INPUT, /* FAN3_REAR_SPEED_RPM, */ + FAN9_INPUT, /* FAN4_REAR_SPEED_RPM, */ + FAN10_INPUT, /* FAN5_REAR_SPEED_RPM */ +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_FAULT);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_front_fault.dev_attr.attr,\ + &sensor_dev_attr_fan##index##_rear_fault.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT) +#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr + +#define DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_INPUT) +#define DECLARE_FAN_INPUT_ATTR(index) &sensor_dev_attr_fan##index##_input.dev_attr.attr + +/* 6 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5); +/* 6 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5); +/* 6 fan present attributes in this platform */ +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); + +/* fan input attributes in this platform */ +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(5); + +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(6); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(7); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(8); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(9); +DECLARE_FAN_INPUT_SENSOR_DEV_ATTR(10); + +static struct attribute *as7116_54x_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1), + DECLARE_FAN_FAULT_ATTR(2), + DECLARE_FAN_FAULT_ATTR(3), + DECLARE_FAN_FAULT_ATTR(4), + DECLARE_FAN_FAULT_ATTR(5), + DECLARE_FAN_SPEED_RPM_ATTR(1), + DECLARE_FAN_SPEED_RPM_ATTR(2), + DECLARE_FAN_SPEED_RPM_ATTR(3), + DECLARE_FAN_SPEED_RPM_ATTR(4), + DECLARE_FAN_SPEED_RPM_ATTR(5), + DECLARE_FAN_PRESENT_ATTR(1), + DECLARE_FAN_PRESENT_ATTR(2), + DECLARE_FAN_PRESENT_ATTR(3), + DECLARE_FAN_PRESENT_ATTR(4), + DECLARE_FAN_PRESENT_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_INPUT_ATTR(1), + DECLARE_FAN_INPUT_ATTR(2), + DECLARE_FAN_INPUT_ATTR(3), + DECLARE_FAN_INPUT_ATTR(4), + DECLARE_FAN_INPUT_ATTR(5), + DECLARE_FAN_INPUT_ATTR(6), + DECLARE_FAN_INPUT_ATTR(7), + DECLARE_FAN_INPUT_ATTR(8), + DECLARE_FAN_INPUT_ATTR(9), + DECLARE_FAN_INPUT_ATTR(10), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0x1F +#define FAN_MIN_DUTY_CYCLE 20 +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150 + +static int as7116_54x_fan_read_value(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int as7116_54x_fan_write_value(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + return (reg_val & FAN_DUTY_CYCLE_REG_MASK) * 5; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + return (duty_cycle / 5); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + return !!(reg_val & (1 << id)); +} + +static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) +{ + return !(reg_val & (1 << id)); +} + +static u8 is_fan_fault(u8 reg_val, enum fan_id id) +{ + return !!(reg_val & (1 << id)); +} +#if 0 +static u8 is_fan_fault(struct as7116_54x_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} +#endif + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct i2c_client *client = to_i2c_client(dev); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < FAN_MIN_DUTY_CYCLE) { + value = FAN_MIN_DUTY_CYCLE; + } + + if (value > FAN_MAX_DUTY_CYCLE) { + value = FAN_MAX_DUTY_CYCLE; + } + + as7116_54x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7116_54x_fan_data *data = as7116_54x_fan_update_device(dev); + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG], + attr->index - FAN1_PRESENT)); + break; + case FAN1_FRONT_FAULT: + case FAN2_FRONT_FAULT: + case FAN3_FRONT_FAULT: + case FAN4_FRONT_FAULT: + case FAN5_FRONT_FAULT: + ret = sprintf(buf, "%d\n", + is_fan_fault(data->reg_val[FAN_FRONT_FAULT_REG], + attr->index - FAN1_FRONT_FAULT)); + break; + case FAN1_REAR_FAULT: + case FAN2_REAR_FAULT: + case FAN3_REAR_FAULT: + case FAN4_REAR_FAULT: + case FAN5_REAR_FAULT: + ret = sprintf(buf, "%d\n", + is_fan_fault(data->reg_val[FAN_REAR_FAULT_REG], + attr->index - FAN1_REAR_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + case FAN4_INPUT: + case FAN5_INPUT: + case FAN6_INPUT: + case FAN7_INPUT: + case FAN8_INPUT: + case FAN9_INPUT: + case FAN10_INPUT: + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index + - FAN1_INPUT + FAN1_FRONT_SPEED_RPM])); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group as7116_54x_fan_group = { + .attrs = as7116_54x_fan_attributes, +}; + +static struct as7116_54x_fan_data *as7116_54x_fan_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7116_54x_fan_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&client->dev, "Starting as7116_54x_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7116_54x_fan_read_value(client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int as7116_54x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7116_54x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7116_54x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7116_54x_fan_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7116_54x_fan_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7116_54x_fan_remove(struct i2c_client *client) +{ + struct as7116_54x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7116_54x_fan_group); + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END }; + +static const struct i2c_device_id as7116_54x_fan_id[] = { + { "as7116_54x_fan", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7116_54x_fan_id); + +static struct i2c_driver as7116_54x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7116_54x_fan_probe, + .remove = as7116_54x_fan_remove, + .id_table = as7116_54x_fan_id, + .address_list = normal_i2c, +}; + +static int __init as7116_54x_fan_init(void) +{ +#if 0 + extern int platform_accton_as7116_54x(void); + if (!platform_accton_as7116_54x()) { + return -ENODEV; + } +#endif + return i2c_add_driver(&as7116_54x_fan_driver); +} + +static void __exit as7116_54x_fan_exit(void) +{ + i2c_del_driver(&as7116_54x_fan_driver); +} + +module_init(as7116_54x_fan_init); +module_exit(as7116_54x_fan_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7116_54x_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-led.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-led.c new file mode 100644 index 000000000000..cd69f711c826 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-led.c @@ -0,0 +1,448 @@ +/* + * A LED driver for the accton_as7116_54x_led + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7116_54x_fan" + +#define DEBUG_MODE 0 +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +extern int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as7116_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +struct as7116_54x_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[1]; /* LOC/DIAG LED */ +}; + +static struct as7116_54x_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_DIAG_REG_MASK (0x0C) +#define LED_MODE_DIAG_GREEN_VALUE (0x08) +#define LED_MODE_DIAG_AMBER_VALUE (0x04) +#define LED_MODE_DIAG_YELLOW_VALUE (0x00) +#define LED_MODE_DIAG_OFF_VALUE (0x0C) + +#define LED_TYPE_FAN_REG_MASK (0x03) +#define LED_MODE_FAN_GREEN_VALUE (0x02) +#define LED_MODE_FAN_AMBER_VALUE (0x01) +#define LED_MODE_FAN_OFF_VALUE (0x03) +#define LED_MODE_FAN_AUTO_VALUE (0x00) + +#define LED_TYPE_PSU1_REG_MASK (0x03) +#define LED_MODE_PSU1_GREEN_VALUE (0x02) +#define LED_MODE_PSU1_AMBER_VALUE (0x01) +#define LED_MODE_PSU1_OFF_VALUE (0x03) +#define LED_MODE_PSU1_AUTO_VALUE (0x00) + +#define LED_TYPE_PSU2_REG_MASK (0x0C) +#define LED_MODE_PSU2_GREEN_VALUE (0x08) +#define LED_MODE_PSU2_AMBER_VALUE (0x04) +#define LED_MODE_PSU2_OFF_VALUE (0x0C) +#define LED_MODE_PSU2_AUTO_VALUE (0x00) + +#define LED_TYPE_LOC_REG_MASK (0x30) +#define LED_MODE_LOC_AMBER_VALUE (0x00) +#define LED_MODE_LOC_AMBER_BLINKING_VALUE1 (0x20) +#define LED_MODE_LOC_AMBER_BLINKING_VALUE2 (0x30) +#define LED_MODE_LOC_OFF_VALUE (0x10) + +static const u8 led_reg[] = { + 0x0A, /* LOC/DIAG/FAN LED */ + 0x0B, /* PSU1/PSU2 LED */ +}; + +enum led_type { + LED_TYPE_DIAG, + LED_TYPE_LOC, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER, + LED_MODE_AMBER_BLINK, + LED_MODE_YELLOW, + LED_MODE_YELLOW_BLINK, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int type_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_FAN, LED_MODE_OFF, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_OFF_VALUE}, +{LED_TYPE_FAN, LED_MODE_GREEN, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_GREEN_VALUE}, +{LED_TYPE_FAN, LED_MODE_AMBER, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_AMBER_VALUE}, +{LED_TYPE_FAN, LED_MODE_AUTO, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_AUTO_VALUE}, +{LED_TYPE_PSU1, LED_MODE_OFF, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_OFF_VALUE}, +{LED_TYPE_PSU1, LED_MODE_GREEN, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_GREEN_VALUE}, +{LED_TYPE_PSU1, LED_MODE_AMBER, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_AMBER_VALUE}, +{LED_TYPE_PSU1, LED_MODE_AUTO, LED_TYPE_PSU1_REG_MASK, LED_MODE_PSU1_AUTO_VALUE}, +{LED_TYPE_PSU2, LED_MODE_OFF, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_OFF_VALUE}, +{LED_TYPE_PSU2, LED_MODE_GREEN, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_GREEN_VALUE}, +{LED_TYPE_PSU2, LED_MODE_AMBER, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_AMBER_VALUE}, +{LED_TYPE_PSU2, LED_MODE_AUTO, LED_TYPE_PSU2_REG_MASK, LED_MODE_PSU2_AUTO_VALUE}, +{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE}, +{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE}, +{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE}, +{LED_TYPE_DIAG, LED_MODE_YELLOW, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_YELLOW_VALUE}, +{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_VALUE}, +{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINKING_VALUE1}, +{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINKING_VALUE2} +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) { + continue; + } + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_value) { + return led_type_mode_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + int type_mask, mode_value; + + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + type_mask = led_type_mode_data[i].type_mask; + mode_value = led_type_mode_data[i].mode_value; + reg_val = (reg_val & ~type_mask) | mode_value; + } + + return reg_val; +} + +static int as7116_54x_led_read_value(u8 reg) +{ + return as7116_54x_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int as7116_54x_led_write_value(u8 reg, u8 value) +{ + return as7116_54x_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void as7116_54x_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_as7116_54x_led update\n"); + ledctl->valid = 0; + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as7116_54x_led_read_value(led_reg[i]); + + if (status < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as7116_54x_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + + reg_val = as7116_54x_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + as7116_54x_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void as7116_54x_led_diag_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7116_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG); +} + +static enum led_brightness as7116_54x_led_diag_get(struct led_classdev *cdev) +{ + as7116_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]); +} + +static void as7116_54x_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7116_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness as7116_54x_led_loc_get(struct led_classdev *cdev) +{ + as7116_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void as7116_54x_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7116_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_FAN); +} + +static enum led_brightness as7116_54x_led_fan_get(struct led_classdev *cdev) +{ + as7116_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + +static void as7116_54x_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7116_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness as7116_54x_led_psu1_get(struct led_classdev *cdev) +{ + as7116_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void as7116_54x_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as7116_54x_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness as7116_54x_led_psu2_get(struct led_classdev *cdev) +{ + as7116_54x_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static struct led_classdev as7116_54x_leds[] = { + [LED_TYPE_DIAG] = { + .name = "as7116_54x_led::diag", + .default_trigger = "unused", + .brightness_set = as7116_54x_led_diag_set, + .brightness_get = as7116_54x_led_diag_get, + .max_brightness = LED_MODE_YELLOW, + }, + [LED_TYPE_LOC] = { + .name = "as7116_54x_led::loc", + .default_trigger = "unused", + .brightness_set = as7116_54x_led_loc_set, + .brightness_get = as7116_54x_led_loc_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_FAN] = { + .name = "as7116_54x_led::fan", + .default_trigger = "unused", + .brightness_set = as7116_54x_led_fan_set, + .brightness_get = as7116_54x_led_fan_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "as7116_54x_led::psu1", + .default_trigger = "unused", + .brightness_set = as7116_54x_led_psu1_set, + .brightness_get = as7116_54x_led_psu1_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as7116_54x_led::psu2", + .default_trigger = "unused", + .brightness_set = as7116_54x_led_psu2_set, + .brightness_get = as7116_54x_led_psu2_get, + .max_brightness = LED_MODE_AUTO, + }, +}; + + +static int as7116_54x_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(as7116_54x_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as7116_54x_leds[i]); + + if (ret < 0) { + break; + } + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as7116_54x_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&as7116_54x_leds[i]); + } + } + + return ret; +} + +static int as7116_54x_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as7116_54x_leds); i++) { + led_classdev_unregister(&as7116_54x_leds[i]); + } + + return 0; +} + +static struct platform_driver as7116_54x_led_driver = { + .probe = as7116_54x_led_probe, + .remove = as7116_54x_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as7116_54x_led_init(void) +{ + int ret; + +#if 0 + extern int platform_accton_as7116_54x(void); + if (!platform_accton_as7116_54x()) { + return -ENODEV; + } +#endif + + ret = platform_driver_register(&as7116_54x_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct as7116_54x_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + goto exit_driver; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + goto exit_free; + } + + return 0; + +exit_free: + kfree(ledctl); +exit_driver: + platform_driver_unregister(&as7116_54x_led_driver); +exit: + return ret; +} + +static void __exit as7116_54x_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as7116_54x_led_driver); + kfree(ledctl); +} + +module_init(as7116_54x_led_init); +module_exit(as7116_54x_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_as7116_54x_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-psu.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-psu.c new file mode 100644 index 000000000000..b4e14297f414 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-psu.c @@ -0,0 +1,349 @@ +/* + * An hwmon driver for accton as7116_54x Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PSU_STATUS_I2C_ADDR 0x60 +#define PSU_STATUS_I2C_REG_OFFSET 0x2 + +#define MODEL_NAME_LEN 11 +#define MODEL_NAME_REG_OFFSET 0x20 + +#define SERIAL_NUM_LEN 18 +#define SERIAL_NUM_REG_OFFSET 0x35 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); +static int as7116_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); +extern int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg); +static struct as7116_54x_psu_data *as7116_54x_psu_update_device(struct device *dev, u8 update_eeprom); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7116_54x_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MODEL_NAME_LEN+1]; /* Model name, read from eeprom */ + char serial[SERIAL_NUM_LEN+1]; /* Serial number, read from eeprom*/ +}; + +enum as7116_54x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_numer, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + +static struct attribute *as7116_54x_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_numer.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7116_54x_psu_data *data = as7116_54x_psu_update_device(dev, 0); + u8 status = 0; + + if (!data->valid) { + return -EIO; + } + + if (attr->index == PSU_PRESENT) { + status = IS_PRESENT(data->index, data->status); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + } + + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7116_54x_psu_data *data = as7116_54x_psu_update_device(dev, 1); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + if (!IS_PRESENT(data->index, data->status)) { + return -ENXIO; + } + + if (attr->index == PSU_MODEL_NAME) { + ptr = data->model_name; + } + else { /* PSU_SERIAL_NUBMER */ + ptr = data->serial; + } + + return sprintf(buf, "%s\n", ptr); +} + +static const struct attribute_group as7116_54x_psu_group = { + .attrs = as7116_54x_psu_attributes, +}; + +static int as7116_54x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7116_54x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7116_54x_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7116_54x_psu_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as7116_54x_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int as7116_54x_psu_remove(struct i2c_client *client) +{ + struct as7116_54x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7116_54x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7116_54x_psu1, + as7116_54x_psu2 +}; + +static const struct i2c_device_id as7116_54x_psu_id[] = { + { "as7116_54x_psu1", as7116_54x_psu1 }, + { "as7116_54x_psu2", as7116_54x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7116_54x_psu_id); + +static struct i2c_driver as7116_54x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "as7116_54x_psu", + }, + .probe = as7116_54x_psu_probe, + .remove = as7116_54x_psu_remove, + .id_table = as7116_54x_psu_id, + .address_list = normal_i2c, +}; + +static int as7116_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 5; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +static struct as7116_54x_psu_data *as7116_54x_psu_update_device(struct device *dev, u8 update_eeprom) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7116_54x_psu_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + + data->valid = 0; + dev_dbg(&client->dev, "Starting as7116_54x update\n"); + + /* Read psu status */ + status = as7116_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); + goto exit; + } + else { + data->status = status; + } + + + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial, 0, sizeof(data->serial)); + + if (update_eeprom && IS_PRESENT(data->index, data->status)) { + /* Read model name */ + status = as7116_54x_psu_read_block(client, MODEL_NAME_REG_OFFSET, data->model_name, + ARRAY_SIZE(data->model_name)-1); + + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + goto exit; + } + else { + /* Skip the meaningless data byte 8*/ + data->model_name[8] = data->model_name[9]; + data->model_name[9] = data->model_name[10]; + data->model_name[10] = '\0'; + } + + /* Read serial number */ + status = as7116_54x_psu_read_block(client, SERIAL_NUM_REG_OFFSET, data->serial, + ARRAY_SIZE(data->serial)-1); + + if (status < 0) { + data->serial[0] = '\0'; + dev_dbg(&client->dev, "unable to read serial number from (0x%x)\n", client->addr); + goto exit; + } + else { + data->serial[SERIAL_NUM_LEN] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init as7116_54x_psu_init(void) +{ + //extern int platform_accton_as7116_54x(void); + //if (!platform_accton_as7116_54x()) { + // return -ENODEV; + //} + + return i2c_add_driver(&as7116_54x_psu_driver); +} + +static void __exit as7116_54x_psu_exit(void) +{ + i2c_del_driver(&as7116_54x_psu_driver); +} + +module_init(as7116_54x_psu_init); +module_exit(as7116_54x_psu_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7116_54x_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-sfp.c b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-sfp.c new file mode 100644 index 000000000000..540ceb21722f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/modules/x86-64-accton-as7116-54x-sfp.c @@ -0,0 +1,1384 @@ +/* + * SFP driver for accton as7116_54x sfp + * + * Copyright (C) Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "as7116_54x_sfp" /* Platform dependent */ + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) +#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +extern int as7116_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as7116_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL +}; + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + NULL +}; + +/* SFP msa attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); +static struct attribute *sfp_msa_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + NULL +}; + +/* SFP ddm attributes for sysfs */ +static struct attribute *sfp_ddm_attributes[] = { + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +as7116_54x_sfp1, as7116_54x_sfp2, as7116_54x_sfp3, as7116_54x_sfp4, +as7116_54x_sfp5, as7116_54x_sfp6, as7116_54x_sfp7, as7116_54x_sfp8, +as7116_54x_sfp9, as7116_54x_sfp10, as7116_54x_sfp11, as7116_54x_sfp12, +as7116_54x_sfp13, as7116_54x_sfp14, as7116_54x_sfp15, as7116_54x_sfp16, +as7116_54x_sfp17, as7116_54x_sfp18, as7116_54x_sfp19, as7116_54x_sfp20, +as7116_54x_sfp21, as7116_54x_sfp22, as7116_54x_sfp23, as7116_54x_sfp24, +as7116_54x_sfp25, as7116_54x_sfp26, as7116_54x_sfp27, as7116_54x_sfp28, +as7116_54x_sfp29, as7116_54x_sfp30, as7116_54x_sfp31, as7116_54x_sfp32, +as7116_54x_sfp33, as7116_54x_sfp34, as7116_54x_sfp35, as7116_54x_sfp36, +as7116_54x_sfp37, as7116_54x_sfp38, as7116_54x_sfp39, as7116_54x_sfp40, +as7116_54x_sfp41, as7116_54x_sfp42, as7116_54x_sfp43, as7116_54x_sfp44, +as7116_54x_sfp45, as7116_54x_sfp46, as7116_54x_sfp47, as7116_54x_sfp48, +as7116_54x_sfp49, as7116_54x_sfp50, as7116_54x_sfp51, as7116_54x_sfp52, +as7116_54x_sfp53, as7116_54x_sfp54 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { +I2C_DEV_ID(as7116_54x_sfp1), +I2C_DEV_ID(as7116_54x_sfp2), +I2C_DEV_ID(as7116_54x_sfp3), +I2C_DEV_ID(as7116_54x_sfp4), +I2C_DEV_ID(as7116_54x_sfp5), +I2C_DEV_ID(as7116_54x_sfp6), +I2C_DEV_ID(as7116_54x_sfp7), +I2C_DEV_ID(as7116_54x_sfp8), +I2C_DEV_ID(as7116_54x_sfp9), +I2C_DEV_ID(as7116_54x_sfp10), +I2C_DEV_ID(as7116_54x_sfp11), +I2C_DEV_ID(as7116_54x_sfp12), +I2C_DEV_ID(as7116_54x_sfp13), +I2C_DEV_ID(as7116_54x_sfp14), +I2C_DEV_ID(as7116_54x_sfp15), +I2C_DEV_ID(as7116_54x_sfp16), +I2C_DEV_ID(as7116_54x_sfp17), +I2C_DEV_ID(as7116_54x_sfp18), +I2C_DEV_ID(as7116_54x_sfp19), +I2C_DEV_ID(as7116_54x_sfp20), +I2C_DEV_ID(as7116_54x_sfp21), +I2C_DEV_ID(as7116_54x_sfp22), +I2C_DEV_ID(as7116_54x_sfp23), +I2C_DEV_ID(as7116_54x_sfp24), +I2C_DEV_ID(as7116_54x_sfp25), +I2C_DEV_ID(as7116_54x_sfp26), +I2C_DEV_ID(as7116_54x_sfp27), +I2C_DEV_ID(as7116_54x_sfp28), +I2C_DEV_ID(as7116_54x_sfp29), +I2C_DEV_ID(as7116_54x_sfp30), +I2C_DEV_ID(as7116_54x_sfp31), +I2C_DEV_ID(as7116_54x_sfp32), +I2C_DEV_ID(as7116_54x_sfp33), +I2C_DEV_ID(as7116_54x_sfp34), +I2C_DEV_ID(as7116_54x_sfp35), +I2C_DEV_ID(as7116_54x_sfp36), +I2C_DEV_ID(as7116_54x_sfp37), +I2C_DEV_ID(as7116_54x_sfp38), +I2C_DEV_ID(as7116_54x_sfp39), +I2C_DEV_ID(as7116_54x_sfp40), +I2C_DEV_ID(as7116_54x_sfp41), +I2C_DEV_ID(as7116_54x_sfp42), +I2C_DEV_ID(as7116_54x_sfp43), +I2C_DEV_ID(as7116_54x_sfp44), +I2C_DEV_ID(as7116_54x_sfp45), +I2C_DEV_ID(as7116_54x_sfp46), +I2C_DEV_ID(as7116_54x_sfp47), +I2C_DEV_ID(as7116_54x_sfp48), +I2C_DEV_ID(as7116_54x_sfp49), +I2C_DEV_ID(as7116_54x_sfp50), +I2C_DEV_ID(as7116_54x_sfp51), +I2C_DEV_ID(as7116_54x_sfp52), +I2C_DEV_ID(as7116_54x_sfp53), +I2C_DEV_ID(as7116_54x_sfp54), +{ /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[6]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss + 3 => device id + 4 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 5 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + +/* Platform dependent +++ */ +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + int i = 0, j = 0, status = -1; + u8 reg; + unsigned short cpld_addr; + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + data->present = 0; + + /* Read present status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + cpld_addr = 0x61+i; + reg = 0x6+j; + status = as7116_54x_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); + data->present |= (u64)status << ((i*24) + (j%3)*8); + } + } + + /* Read present status of port 49-54(QSFP port) */ + cpld_addr = 0x62; + reg = 0x14; + status = as7116_54x_cpld_read(cpld_addr, reg); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + else { + data->present |= (u64)status << 48; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0, j = 0; + int status = -1; + + if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { + return data; + } + + DEBUG_PRINT("Starting as7116_54x sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->msa->valid = 0; + memset(data->msa->status, 0, sizeof(data->msa->status)); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 9; j++) { + u8 reg; + unsigned short cpld_addr; + reg = 0x9+j; + cpld_addr = 0x61+i; + + status = as7116_54x_cpld_read(cpld_addr, reg); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); + goto exit; + } + + data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); + } + } + + data->msa->valid = 1; + data->msa->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + unsigned short cpld_addr = 0; + u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; + long disable; + int error; + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_set_tx_disable(dev, da, buf, count); + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + if(data->port < 24) { + cpld_addr = 0x61; + cpld_reg = 0xC + data->port / 8; + cpld_bit = 1 << (data->port % 8); + } + else { /* port 24 ~ 48 */ + cpld_addr = 0x62; + cpld_reg = 0xC + (data->port - 24) / 8; + cpld_bit = 1 << (data->port % 8); + } + + /* Read current status */ + cpld_val = as7116_54x_cpld_read(cpld_addr, cpld_reg); + + /* Update tx_disable status */ + if (disable) { + data->msa->status[1] |= BIT_INDEX(data->port); + cpld_val |= cpld_bit; + } + else { + data->msa->status[1] &= ~BIT_INDEX(data->port); + cpld_val &= ~cpld_bit; + } + + as7116_54x_cpld_write(cpld_addr, cpld_reg, cpld_val); + mutex_unlock(&data->update_lock); + return count; +} +/* Platform dependent --- */ + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = sfp_update_present(client); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + return !(data->present & BIT_INDEX(data->port)); /* Platform dependent */ +} + +/* Platform dependent +++ */ +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if (PRESENT_ALL == attr->index) { + int i; + u8 values[7] = {0}; + struct sfp_port_data *data = sfp_update_present(client); + + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = ~(u8)(data->present >> (i * 8)); + } + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6] & 0x3F); + } + else { + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + /* PRESENT */ + return sprintf(buf, "%d\n", present); + } +} +/* Platform dependent --- */ + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + if (!present) { + /* port is not present */ + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + DEBUG_PRINT(""); + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + DEBUG_PRINT("Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + DEBUG_PRINT(""); + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + DEBUG_PRINT(""); + goto exit; + } + } + msleep(200); + DEBUG_PRINT(""); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + DEBUG_PRINT(""); + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + DEBUG_PRINT(""); + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + +exit: + DEBUG_PRINT(""); + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + int present; + u8 val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT(""); + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + DEBUG_PRINT(""); + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + DEBUG_PRINT(""); + data = qsfp_update_tx_rx_status(dev); + DEBUG_PRINT(""); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + DEBUG_PRINT(""); + switch (attr->index) { + case TX_FAULT: + val = !!(data->qsfp->status[2] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + case TX_DISABLE: + val = data->qsfp->status[1] & 0xF; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + case RX_LOS: + val = !!(data->qsfp->status[0] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); + break; + default: + break; + } + + DEBUG_PRINT(""); + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (!status) { + /* port is not present */ + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + mutex_lock(&data->update_lock); + + if (attr->index == TX_DISABLE) { + data->qsfp->status[1] = disable & 0xF; + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (status == 0) { + /* port is not present */ + return -ENODEV; + } + + status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (unlikely(status < 0)) { + return status; + } + + return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK)); +} + +/* Platform dependent +++ */ +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("driver type = (%d)", data->driver_type); + if (data->driver_type == DRIVER_TYPE_QSFP) { + DEBUG_PRINT(""); + return qsfp_show_tx_rx_status(dev, da, buf); + } + + DEBUG_PRINT(""); + data = sfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + if(attr->index == RX_LOS_ALL) { + int i = 0; + u8 values[6] = {0}; + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = (u8)(data->msa->status[2] >> (i * 8)); + } + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + case RX_LOS: + index = 2; + break; + default: + break; + } + + val = !!(data->msa->status[index] & BIT_INDEX(data->port)); + return sprintf(buf, "%d\n", val); +} +/* Platform dependent --- */ +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, command, *data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return 1; +#endif + + +} + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return status; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + status = 1; + +abort: + return status; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + + /* Bring QSFPs out of reset */ + as7116_54x_cpld_write(0x62, 0x15, 0x3F); + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +/* Platform dependent +++ */ +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if (dev_id->driver_data >= as7116_54x_sfp1 && dev_id->driver_data <= as7116_54x_sfp48) { + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_SFP_MSA; + return sfp_msa_probe(client, dev_id, &data->msa); + } + else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_SFP_DDM; + return sfp_ddm_probe(client, dev_id, &data->ddm); + } + } + else { /* as7116_54x_sfp49 ~ as7116_54x_sfp54 */ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); + } + } + + return -ENODEV; +} +/* Platform dependent --- */ + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +static int __init sfp_init(void) +{ + //extern int platform_accton_as7116_54x(void); + //if (!platform_accton_as7116_54x()) { + // return -ENODEV; + //} + + return i2c_add_driver(&sfp_driver); +} + +static void __exit sfp_exit(void) +{ + i2c_del_driver(&sfp_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton as7116_54x_sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(sfp_init); +module_exit(sfp_exit); + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/as7116-platform-init.service b/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/as7116-platform-init.service new file mode 100755 index 000000000000..6eaf4745210c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/as7116-platform-init.service @@ -0,0 +1,14 @@ +[Unit] +Description=Accton AS7116-54X Platform initialization service +Before=pmon.service +After=sysinit.target +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/accton_as7116_util.py install +ExecStop=/usr/local/bin/accton_as7116_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/platform_api/platform_api_mgnt.sh b/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/platform_api/platform_api_mgnt.sh new file mode 100755 index 000000000000..e1d330357894 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/service/platform_api/platform_api_mgnt.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +PREV_REBOOT_CAUSE="/host/reboot-cause/" +DEVICE="/usr/share/sonic/device" +PLATFORM=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) +FILES=$DEVICE/$PLATFORM/api_files + +install() { + # Install sonic-platform package + if [ -e $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl ]; then + pip install $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl + fi +} + +init() { + # mount needed files for sonic-platform package + mkdir -p $FILES + + mkdir -p $FILES/reboot-cause + mount -B $PREV_REBOOT_CAUSE $FILES/reboot-cause +} + +deinit() { + # deinit sonic-platform package + umount -f $PREV_REBOOT_CAUSE $FILES/reboot-cause >/dev/null 2>/dev/null +} + +uninstall() { + # Uninstall sonic-platform package + pip uninstall -y sonic-platform >/dev/null 2>/dev/null +} + +case "$1" in +install | uninstall | init | deinit) + $1 + ;; +*) + echo "Usage: $0 {install|uninstall|init|deinit}" + exit 1 + ;; +esac diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/setup.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/setup.py new file mode 100644 index 000000000000..088e1f30355a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/setup.py @@ -0,0 +1,34 @@ +from setuptools import setup + +DEVICE_NAME = 'accton' +HW_SKU = 'x86_64-accton_as7116_54x-r0' + +setup( + name='sonic-platform', + version='1.0', + description='SONiC platform API implementation on Accton Platforms', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + maintainer='Simon Ji', + maintainer_email='Simon.Ji@mediatek.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/nephos/sonic-platform-modules-accton/as7116-54x/utils/README b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/README new file mode 100755 index 000000000000..0b9fc1633999 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/README @@ -0,0 +1,60 @@ +Copyright (C) 2016 Accton Networks, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +To initialize the system, run "accton_as7712_util.py install". +To clean up the drivers & devices, run "accton_as7712_util.py clean". +To dump information of sensors, run "accton_as7712_util.py show". +To dump SFP EEPROM, run "accton_as7712_util.py sff". +To set fan speed, run "accton_as7712_util.py set fan". +To enable/disable SFP emission, run "accton_as7712_util.py set sfp". +To set system LEDs' color, run "accton_as7712_util.py set led" +For more information, run "accton_as7712_util.py --help". + +==================================================================== +Besides applying accton_as7712_util.py to access peripherals, you can +access peripherals by sysfs nodes directly after the installation is run. + +LED controls can be found under /sys/class/leds. The sysfs interface +color mappings are as follows: +Brightness: + 0 => off + 1 => green + 2 => amber + 3 => red + 4 => blue + +There are 5 system LEDs, loc, diag, fan, ps1, and ps2. +They are lit automatically by CPLD, but the loc and diag. +The loc led has only 1 color, blue. +The diag one has 3 colors: red, amber, and green. + +Fan controls can be found in /sys/bus/i2c/devices/2-0066. +There are 12 fans inside 6 fan modules. +All fans share 1 duty setting, ranged from 0~100. + +Three temperature sensors are controlled by the lm75 kernel modules. +They should already be visible under /sys/bus/i2c/drivers/lm75/. + +Two power supplies are controlled by the CPLD. +Here provide their status under +/sys/bus/i2c/devices/10-0050 and /sys/bus/i2c/devices/11-0053. + +There are 32 QSFP+ modules are equipped. +Apply "accton_as7712_util.py show" to get their status. +Apply "accton_as7712_util.py set sfp" to turn on/off light transmission. +Apply "accton_as7712_util.py sff" to dump EEPROM information. +Before operating on that QSFP+, please make sure it is well plugged. +Otherwise, operation is going to fail. + diff --git a/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/accton_as7116_util.py b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/accton_as7116_util.py new file mode 100755 index 000000000000..2d9ea128f976 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/as7116-54x/utils/accton_as7116_util.py @@ -0,0 +1,533 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 Accton Networks, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'as7116_54x' +version = '0.1.0' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':5, 'fan':1, 'thermal':3, 'psu':2, 'sfp':54} +FORCE = 0 +#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) +#logging.basicConfig(level=logging.INFO) + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep accton", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ + 'depmod', + 'modprobe i2c_dev', + 'modprobe i2c_mux_pca954x force_deselect_on_exit=1', + 'modprobe x86-64-accton-as7116-54x-cpld' , + 'modprobe x86-64-accton-as7116-54x-fan' , + 'modprobe x86-64-accton-as7116-54x-psu' , + 'modprobe x86-64-accton-as7116-54x-sfp' , + 'modprobe x86-64-accton-as7116-54x-led' ] + +def driver_install(): + global FORCE + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'fan': ['1-0063'] , + 'thermal': ['17-004b','19-0049', '20-004a'] , + 'psu': ['10-0050','11-0058'], + 'sfp': ['-0050']} +i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , + 'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable_all']} + +sfp_map = [37,38,39,40, + 41,42,43,44,45,46,47,48,49,50, + 51,52,53,54,55,56,57,58,59,60, + 61,62,63,64,65,66,67,68,69,70, + 71,72,73,74,75,76,77,78,79,80, + 81,82,83,84, + 21,22,23,24,25,26] + +mknod =[ + 'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9545 0x71 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo as7116_54x_fan 0x63 > /sys/bus/i2c/devices/i2c-1/new_device', + 'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-17/new_device', + 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-19/new_device', + 'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-20/new_device', + 'echo as7116_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo as7116_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo as7116_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo as7116_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-10/new_device', + 'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-10/new_device', + 'echo as7116_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-11/new_device', + 'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-11/new_device', + 'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-29/new_device', + 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-30/new_device', + 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-31/new_device', + 'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-32/new_device', + 'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-33/new_device', + 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-34/new_device', + 'echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-0/new_device'] + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #for pca954x need times to built new i2c buses + if mknod[i].find('pca954') != -1: + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo as7116_54x_sfp"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + if i <= 47: + status, output =log_os_system("echo as7116_54x_sfp"+str(i+1)+" 0x51 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + status, output =log_os_system("ls /sys/bus/i2c/devices/1-0077", 0) + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + + status, output = log_os_system( + "/bin/sh /usr/local/bin/platform_api_mgnt.sh init", 1) + if status: + print output + if FORCE == 0: + return status + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'fan' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + elif 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +#get digits inside a string. +#Ex: 31 for "sfp31" +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + print " "+j+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) + return not(ret1 or ret2) + +if __name__ == "__main__": + main() diff --git a/platform/nephos/sonic-platform-modules-accton/debian/changelog b/platform/nephos/sonic-platform-modules-accton/debian/changelog new file mode 100755 index 000000000000..595fe0985c06 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/debian/changelog @@ -0,0 +1,5 @@ +sonic-accton-platform-modules (1.0.1) unstable; urgency=low + + * Add support for AS7116-54X series + + -- developer Wed, 29 Mar 2017 11:00:00 +0800 \ No newline at end of file diff --git a/platform/nephos/sonic-platform-modules-accton/debian/compat b/platform/nephos/sonic-platform-modules-accton/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/nephos/sonic-platform-modules-accton/debian/control b/platform/nephos/sonic-platform-modules-accton/debian/control new file mode 100755 index 000000000000..3020b86408d6 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/debian/control @@ -0,0 +1,11 @@ +Source: sonic-accton-platform-modules +Section: main +Priority: extra +Maintainer: simon.ji@nephosinc.com +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-accton-as7116-54x +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/nephos/sonic-platform-modules-accton/debian/rules b/platform/nephos/sonic-platform-modules-accton/debian/rules new file mode 100755 index 000000000000..de84b23d55ae --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/debian/rules @@ -0,0 +1,40 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2.7 + +PACKAGE_PRE_NAME := sonic-platform-accton +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= as7116-54x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} /$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) + +override_dh_usrlocal: + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) diff --git a/platform/nephos/sonic-platform-modules-accton/debian/sonic-platform-accton-as7116-54x.install b/platform/nephos/sonic-platform-modules-accton/debian/sonic-platform-accton-as7116-54x.install new file mode 100644 index 000000000000..61423affe7ac --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/debian/sonic-platform-accton-as7116-54x.install @@ -0,0 +1,4 @@ +as7116-54x/utils/* usr/local/bin +as7116-54x/service/*.service lib/systemd/system +as7116-54x/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-accton_as7116_54x-r0 +as7116-54x/service/platform_api/platform_api_mgnt.sh usr/local/bin diff --git a/platform/nephos/sonic-platform-modules-accton/debian/sonic-platform-accton-as7116-54x.postinst b/platform/nephos/sonic-platform-modules-accton/debian/sonic-platform-accton-as7116-54x.postinst new file mode 100644 index 000000000000..a9947af877b6 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-accton/debian/sonic-platform-accton-as7116-54x.postinst @@ -0,0 +1,5 @@ +depmod -a +systemctl enable as7116-platform-init.service +systemctl start as7116-platform-init.service + +/usr/local/bin/platform_api_mgnt.sh install diff --git a/platform/nephos/sonic-platform-modules-cig/LICENSE b/platform/nephos/sonic-platform-modules-cig/LICENSE new file mode 100755 index 000000000000..baf27e167418 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2017 Cambridgeig Technology Corporation + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/nephos/sonic-platform-modules-cig/README.md b/platform/nephos/sonic-platform-modules-cig/README.md new file mode 100755 index 000000000000..9dc23910b59e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/README.md @@ -0,0 +1 @@ +platform drivers of Cambridgeig products for the SONiC project diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/classes/__init__.py b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/classes/fanutil.py b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/classes/fanutil.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/classes/thermalutil.py b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/classes/thermalutil.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/Makefile b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/Makefile new file mode 100644 index 000000000000..446fde4b0a70 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/Makefile @@ -0,0 +1,6 @@ +obj-m :=x86-64-cig-cs5435-54p-sysfs.o \ + x86-64-cig-cs5435-54p-cpld.o \ + x86-64-cig-cs5435-54p-fan.o \ + x86-64-cig-cs5435-54p-led.o \ + x86-64-cig-cs5435-54p-psu.o \ + x86-64-cig-cs5435-54p-sfp.o diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/i2c-algo-lpc.h b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/i2c-algo-lpc.h new file mode 100644 index 000000000000..dc9e30d16ddd --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/i2c-algo-lpc.h @@ -0,0 +1,222 @@ +/* -------------------------------------------------------------------- + + * A hwmon driver for the CIG cs5435-54P + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* -------------------------------------------------------------------- */ + +#ifndef I2C_LPC_H +#define I2C_LPC_H 1 + +/* ----- Control register bits ---------------------------------------- */ +#define I2C_LPC_PIN 0x80 +#define I2C_LPC_ESO 0x40 +#define I2C_LPC_ES1 0x20 +#define I2C_LPC_ES2 0x10 +#define I2C_LPC_ENI 0x08 + +#define I2C_LPC_STO 0x40 +#define I2C_LPC_ACK 0x01 + +/*command register*/ +#define I2C_LPC_STA 0x80 +#define I2C_LPC_ABT 0x40 + +/*status register*/ +#define I2C_LPC_TBE 0x02 +#define I2C_LPC_IBB 0x80 +#define I2C_LPC_RBF 0x01 +#define I2C_LPC_TD 0x08 + +#define I2C_LPC_START I2C_LPC_STA +#define I2C_LPC_STOP I2C_LPC_STO +#define I2C_LPC_REPSTART I2C_LPC_STA +#define I2C_LPC_IDLE + +/* ----- Status register bits ----------------------------------------- */ +/*#define I2C_LPC_PIN 0x80 as above*/ + +#define I2C_LPC_INI 0x40 /* 1 if not initialized */ +#define I2C_LPC_STS 0x20 +#define I2C_LPC_BER 0x10 +#define I2C_LPC_AD0 0x08 +#define I2C_LPC_LRB 0x08 +#define I2C_LPC_AAS 0x04 +#define I2C_LPC_LAB 0x02 +#define I2C_LPC_BB 0x80 + +/* ----- Chip clock frequencies --------------------------------------- */ +#define I2C_LPC_CLK3 0x00 +#define I2C_LPC_CLK443 0x10 +#define I2C_LPC_CLK6 0x14 +#define I2C_LPC_CLK 0x18 +#define I2C_LPC_CLK12 0x1c + +/* ----- transmission frequencies ------------------------------------- */ +#define I2C_LPC_TRNS90 0x00 /* 90 kHz */ +#define I2C_LPC_TRNS45 0x01 /* 45 kHz */ +#define I2C_LPC_TRNS11 0x02 /* 11 kHz */ +#define I2C_LPC_TRNS15 0x03 /* 1.5 kHz */ + + +#define I2C_LPC_OWNADR 0 +#define I2C_LPC_INTREG I2C_LPC_ES2 +#define I2C_LPC_CLKREG I2C_LPC_ES1 + +#define I2C_LPC_REG_TEST 0x01 +#define I2C_LPC_REG_BUS_SEL 0x80 +#define I2C_LPC_REG_DEVICE_ADDR 0x81 +#define I2C_LPC_REG_BYTE_COUNT 0x83 +#define I2C_LPC_REG_COMMAND 0x84 +#define I2C_LPC_REG_STATUS 0x85 +#define I2C_LPC_REG_DATA_RX1 0x86 +#define I2C_LPC_REG_DATA_RX2 0x87 +#define I2C_LPC_REG_DATA_RX3 0x88 +#define I2C_LPC_REG_DATA_RX4 0x89 +#define I2C_LPC_REG_DATA_TX1 0x8a +#define I2C_LPC_REG_DATA_TX2 0x8b +#define I2C_LPC_REG_DATA_TX3 0x8c +#define I2C_LPC_REG_DATA_TX4 0x8d + + +#define ADDR_REG_SFP_STATUS_ADDR 0X62 //reg addr +R/W# //1031 +#define ADDR_REG_SFP_STATUS_TX 0X63 // write data +#define ADDR_REG_SFP_STATUS_RX 0X64 //read data +#define ADDR_REG_SFP_STATUS_COMMAND 0X65 //cmd bit7=1,go +#define ADDR_REG_SFP_STATUS_STATUS 0X66 //status + +#define CPLD_MASTER_INTERRUPT_STATUS_REG 0x20 +#define CPLD_MASTER_INTERRUPT_MASK_REG 0x21 +#define CPLD_MASTER_INTERRUPT_ALL 0x3f +#define CPLD_MASTER_INTERRUPT_CPLD2 0x20 +#define CPLD_MASTER_INTERRUPT_CPLD1 0x10 +#define CPLD_MASTER_INTERRUPT_PSU2 0x08 +#define CPLD_MASTER_INTERRUPT_PSU1 0x04 +#define CPLD_MASTER_INTERRUPT_6320 0x02 +#define CPLD_MASTER_INTERRUPT_LSW 0x01 + + + +#define CPLD_SLAVE1_INTERRUPT_STATUS_L_REG 0x20 +#define CPLD_SLAVE1_INTERRUPT_STATUS_H_REG 0x21 +#define CPLD_SLAVE2_INTERRUPT_STATUS_L_REG 0x22 +#define CPLD_SLAVE2_INTERRUPT_STATUS_H_REG 0x23 +#define CPLD_SLAVE1_INTERRUPT_MASK_REG 0x24 +#define CPLD_SLAVE2_INTERRUPT_MASK_REG 0x25 + + +#define CPLD_SLAVE1_PRESENT08_REG 0x01 +#define CPLD_SLAVE1_PRESENT16_REG 0x02 +#define CPLD_SLAVE1_PRESENT24_REG 0x03 +#define CPLD_SLAVE2_PRESENT32_REG 0x04 +#define CPLD_SLAVE2_PRESENT40_REG 0x05 +#define CPLD_SLAVE2_PRESENT48_REG 0x06 + +#define CPLD_SLAVE1_RX_LOST08_REG 0x07 +#define CPLD_SLAVE1_RX_LOST16_REG 0x08 +#define CPLD_SLAVE1_RX_LOST24_REG 0x09 +#define CPLD_SLAVE2_RX_LOST32_REG 0x0a +#define CPLD_SLAVE2_RX_LOST40_REG 0x0b +#define CPLD_SLAVE2_RX_LOST48_REG 0x0c + +#define CPLD_SLAVE1_TX_FAULT08_REG 0x0d +#define CPLD_SLAVE1_TX_FAULT16_REG 0x0e +#define CPLD_SLAVE1_TX_FAULT24_REG 0x0f +#define CPLD_SLAVE2_TX_FAULT32_REG 0x10 +#define CPLD_SLAVE2_TX_FAULT40_REG 0x11 +#define CPLD_SLAVE2_TX_FAULT48_REG 0x12 + +#define CPLD_SLAVE2_PRESENT56_REG 0x19 +#define CPLD_SLAVE2_QSFP_CR56_REG 0x1a + + +#define CPLD_SLAVE1_INTERRUPT_PRESENT08 0x0001 +#define CPLD_SLAVE1_INTERRUPT_PRESENT16 0x0002 +#define CPLD_SLAVE1_INTERRUPT_PRESENT24 0x0004 +#define CPLD_SLAVE2_INTERRUPT_PRESENT32 0x0001 +#define CPLD_SLAVE2_INTERRUPT_PRESENT40 0x0002 +#define CPLD_SLAVE2_INTERRUPT_PRESENT48 0x0004 + +#define CPLD_SLAVE2_INTERRUPT_QSFP_CR56 0x0200 +#define CPLD_SLAVE2_INTERRUPT_PRESENT56 0x0400 + +#define CPLD_SLAVE1_INTERRUPT_RX_LOST08 0x0008 +#define CPLD_SLAVE1_INTERRUPT_RX_LOST16 0x0010 +#define CPLD_SLAVE1_INTERRUPT_RX_LOST24 0x0020 +#define CPLD_SLAVE2_INTERRUPT_RX_LOST32 0x0008 +#define CPLD_SLAVE2_INTERRUPT_RX_LOST40 0x0010 +#define CPLD_SLAVE2_INTERRUPT_RX_LOST48 0x0020 + +#define CPLD_SLAVE1_INTERRUPT_TX_FAULT08 0x0040 +#define CPLD_SLAVE1_INTERRUPT_TX_FAULT16 0x0080 +#define CPLD_SLAVE1_INTERRUPT_TX_FAULT24 0x0100 +#define CPLD_SLAVE2_INTERRUPT_TX_FAULT32 0x0040 +#define CPLD_SLAVE2_INTERRUPT_TX_FAULT40 0x0080 +#define CPLD_SLAVE2_INTERRUPT_TX_FAULT48 0x0100 + + + + + + + +#define WAIT_TIME_OUT_COUNT 100 + + +struct i2c_algo_lpc_data { + void *data; /* private data for lolevel routines */ + void (*setlpc) (void *data, int ctl, int val); + int (*getlpc) (void *data, int ctl); + int (*getown) (void *data); + int (*getclock) (void *data); + void (*waitforpin) (void *data); + + int (*xfer_begin) (void *data); + int (*xfer_end) (void *data); + + /* Multi-master lost arbitration back-off delay (msecs) + * This should be set by the bus adapter or knowledgable client + * if bus is multi-mastered, else zero + */ + unsigned long lab_mdelay; +}; + + +struct subsys_private { + struct kset subsys; + struct kset *devices_kset; + struct list_head interfaces; + struct mutex mutex; + + struct kset *drivers_kset; + struct klist klist_devices; + struct klist klist_drivers; + struct blocking_notifier_head bus_notifier; + unsigned int drivers_autoprobe:1; + struct bus_type *bus; + + struct kset glue_dirs; + struct class *class; +}; + +void cs5435_54p_sysfs_add_client(struct i2c_client *client); +void cs5435_54p_sysfs_remove_client(struct i2c_client *client); + + +#endif /* I2C_LPC8584_H */ diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-cpld.c b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-cpld.c new file mode 100644 index 000000000000..68f1192e58b1 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-cpld.c @@ -0,0 +1,2209 @@ +/* + * A hwmon driver for the CIG cs5435-54P CPLD + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-algo-lpc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CPLD_USER +# include +#else +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + + + + + +/********************************************** Start ********************************************************/ + +/* + * ISA bus. + */ + +static void platform_isa_bus_release(struct device * dev) +{ + return ; +} + + +static struct device isa_bus = { + .init_name = "lpc-isa", + .release = platform_isa_bus_release, +}; + +struct isa_dev { + struct device dev; + struct device *next; + unsigned int id; +}; + +#define to_isa_dev(x) container_of((x), struct isa_dev, dev) + +static int isa_bus_match(struct device *dev, struct device_driver *driver) +{ + struct isa_driver *isa_driver = to_isa_driver(driver); + + if (dev->platform_data == isa_driver) { + if (!isa_driver->match || + isa_driver->match(dev, to_isa_dev(dev)->id)) + return 1; + dev->platform_data = NULL; + } + return 0; +} + +static int isa_bus_probe(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->probe) + return isa_driver->probe(dev, to_isa_dev(dev)->id); + + return 0; +} + +static int isa_bus_remove(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->remove) + return isa_driver->remove(dev, to_isa_dev(dev)->id); + + return 0; +} + +static void isa_bus_shutdown(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->shutdown) + isa_driver->shutdown(dev, to_isa_dev(dev)->id); +} + +static int isa_bus_suspend(struct device *dev, pm_message_t state) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->suspend) + return isa_driver->suspend(dev, to_isa_dev(dev)->id, state); + + return 0; +} + +static int isa_bus_resume(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->resume) + return isa_driver->resume(dev, to_isa_dev(dev)->id); + + return 0; +} + +static struct bus_type isa_bus_type = { + .name = "lpc-isa", + .match = isa_bus_match, + .probe = isa_bus_probe, + .remove = isa_bus_remove, + .shutdown = isa_bus_shutdown, + .suspend = isa_bus_suspend, + .resume = isa_bus_resume +}; + +static void isa_dev_release(struct device *dev) +{ + kfree(to_isa_dev(dev)); +} + +void lpc_unregister_driver(struct isa_driver *isa_driver) +{ + struct device *dev = isa_driver->devices; + + while (dev) { + struct device *tmp = to_isa_dev(dev)->next; + device_unregister(dev); + dev = tmp; + } + driver_unregister(&isa_driver->driver); +} + + +int lpc_register_driver(struct isa_driver *isa_driver, unsigned int ndev) +{ + int error; + unsigned int id; + + isa_driver->driver.bus = &isa_bus_type; + isa_driver->devices = NULL; + + error = driver_register(&isa_driver->driver); + if (error) + return error; + + for (id = 0; id < ndev; id++) { + struct isa_dev *isa_dev; + + isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL); + if (!isa_dev) { + error = -ENOMEM; + break; + } + + isa_dev->dev.parent = &isa_bus; + isa_dev->dev.bus = &isa_bus_type; + + dev_set_name(&isa_dev->dev, "%s.%u", + isa_driver->driver.name, id); + isa_dev->dev.platform_data = isa_driver; + isa_dev->dev.release = isa_dev_release; + isa_dev->id = id; + + isa_dev->dev.coherent_dma_mask = DMA_BIT_MASK(24); + isa_dev->dev.dma_mask = &isa_dev->dev.coherent_dma_mask; + + error = device_register(&isa_dev->dev); + if (error) { + put_device(&isa_dev->dev); + break; + } + + if (isa_dev->dev.platform_data) { + isa_dev->next = isa_driver->devices; + isa_driver->devices = &isa_dev->dev; + } else + device_unregister(&isa_dev->dev); + } + + if (!error && !isa_driver->devices) + error = -ENODEV; + + if (error) + isa_unregister_driver(isa_driver); + + return error; +} + + +int lpc_bus_init(void) +{ + int error; + + error = bus_register(&isa_bus_type); + if (!error) { + error = device_register(&isa_bus); + if (error) + bus_unregister(&isa_bus_type); + } + return error; +} + +void lpc_bus_exit(void) +{ + + device_unregister(&isa_bus); + + bus_unregister(&isa_bus_type); +} + + +/********************************************** End ********************************************************/ + + + + + + +/********************************************** Start ********************************************************/ +/* + * module parameters: + */ +static int i2c_debug = 0; +static struct mutex lpc_lock; + + +#define DEB2(x) if (i2c_debug == 2) x +#define DEB3(x) if (i2c_debug == 3) x + /* print several statistical values */ +#define DEBPROTO(x) if (i2c_debug == 9) x; + /* debug the protocol by showing transferred bits */ +#define DEF_TIMEOUT 160 + + + +/* setting states on the bus with the right timing: */ + +#define set_lpc(adap, ctl, val) adap->setlpc(adap->data, ctl, val) +#define get_lpc(adap, ctl) adap->getlpc(adap->data, ctl) +#define get_own(adap) adap->getown(adap->data) +#define get_clock(adap) adap->getclock(adap->data) +#define i2c_outaddr(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DEVICE_ADDR, val) + +#define i2c_outbyte1(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX1, val) +#define i2c_outbyte2(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX2, val) +#define i2c_outbyte3(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX3, val) +#define i2c_outbyte4(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX4, val) +#define i2c_inbyte1(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX1) +#define i2c_inbyte2(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX2) +#define i2c_inbyte3(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX3) +#define i2c_inbyte4(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX4) + + + +#define LPC_FPRINTF_LOG_PATH "/tmp/file.log" +struct file *lpc_fprintf_file = NULL; + +static int lpc_fprintf_debug(const char *fmt, ...) +{ + char lpc_fprintf_buf[256]={0}; + struct va_format vaf; + va_list args; + int r; + mm_segment_t old_fs; + struct timeval tv; + struct rtc_time tm; + + do_gettimeofday(&tv); + + rtc_time_to_tm(tv.tv_sec,&tm); + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + r=snprintf(lpc_fprintf_buf,sizeof(lpc_fprintf_buf),"[%04d.%08d] %pV\n",tm.tm_sec, (int)tv.tv_usec, &vaf); + va_end(args); + old_fs = get_fs(); + set_fs(KERNEL_DS); + vfs_write(lpc_fprintf_file, (char *)&lpc_fprintf_buf, strlen(lpc_fprintf_buf), &lpc_fprintf_file->f_pos); + set_fs(old_fs); + memset(lpc_fprintf_buf,0x0,sizeof(lpc_fprintf_buf)); + return r; + +} + + + +static int lpc_fprintf_init(void) +{ + printk("lpc_fprintf_init.\n"); + + if(lpc_fprintf_file == NULL) + lpc_fprintf_file = filp_open(LPC_FPRINTF_LOG_PATH, O_RDWR | O_APPEND | O_CREAT, 0644); + + if (IS_ERR(lpc_fprintf_file)) { + printk("Error occured while opening file %s, exiting...\n", LPC_FPRINTF_LOG_PATH); + return -1; + } + + return 0; +} + +static int lpc_fprintf_exit(void) +{ + printk("lpc_fprintf_exit.\n"); + + if(lpc_fprintf_file != NULL) + filp_close(lpc_fprintf_file, NULL); + + return 0; +} + + +/* other auxiliary functions */ + + +void print_reg(struct i2c_algo_lpc_data *adap) +{ + unsigned char status; + DEBPROTO(lpc_fprintf_debug("================================================\n");) + status = get_lpc(adap, I2C_LPC_REG_BUS_SEL); + DEBPROTO(lpc_fprintf_debug("%s select reg %x : %x\n",__func__,I2C_LPC_REG_BUS_SEL, status);) + status = get_lpc(adap, I2C_LPC_REG_BYTE_COUNT); + DEBPROTO(lpc_fprintf_debug("%s count reg %x : %x\n",__func__,I2C_LPC_REG_BYTE_COUNT, status);) + + status = get_lpc(adap, I2C_LPC_REG_COMMAND); + DEBPROTO(lpc_fprintf_debug("%s command reg %x : %x\n",__func__,I2C_LPC_REG_COMMAND, status);) + status = get_lpc(adap, I2C_LPC_REG_DEVICE_ADDR); + DEBPROTO(lpc_fprintf_debug("%s address reg %x : %x\n",__func__,I2C_LPC_REG_DEVICE_ADDR, status);) + + status = get_lpc(adap, I2C_LPC_REG_STATUS); + DEBPROTO(lpc_fprintf_debug("%s status reg %x : %x\n",__func__,I2C_LPC_REG_STATUS, status);) +} + + + +static void i2c_repstart(struct i2c_algo_lpc_data *adap) +{ + DEBPROTO(lpc_fprintf_debug("%s :\n",__func__);) + set_lpc(adap, I2C_LPC_REG_COMMAND, I2C_LPC_REPSTART); +} + +static void i2c_stop(struct i2c_algo_lpc_data *adap) +{ + DEBPROTO(lpc_fprintf_debug("%s :\n",__func__);) + set_lpc(adap, I2C_LPC_REG_COMMAND, I2C_LPC_STOP); + udelay(60); + set_lpc(adap, I2C_LPC_REG_COMMAND, 0x00); +} + + + + +static void i2c_start(struct i2c_algo_lpc_data *adap) +{ + print_reg(adap); + + set_lpc(adap, I2C_LPC_REG_COMMAND, I2C_LPC_START); + + print_reg(adap); +} + + + + +static int wait_for_bb(struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + int status; + + while (--timeout) { + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus free status : %x\n",__func__,status);) + + if(status == I2C_LPC_TD) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is free status : %x\n",__func__,status);) + break; + } + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout for free busy status : %x\n",__func__,status);) + return -ETIMEDOUT; + } + + + + return 0; +} + + +static int wait_for_be(int mode,struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + unsigned char status; + + + while (--timeout) { + + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus empty status : %x\n",__func__,status);) + + if(mode == 1) + { + if((status & I2C_LPC_IBB) && (status & I2C_LPC_TBE)) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is empty status : %x\n",__func__,status);) + break; + } + } + else + { + if(status & I2C_LPC_TD) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is empty status : %x\n",__func__,status);) + break; + } + } + + status = get_lpc(adap, I2C_LPC_REG_TEST); + + DEBPROTO(lpc_fprintf_debug("%s : The test register data : %x\n",__func__,status);) + udelay(1); /* wait for 100 us */ + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout waiting for Bus Empty\n",__func__);) + return -ETIMEDOUT; + } + + return 0; +} + + +static int wait_for_bf(struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + int status; + + + while (--timeout) { + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus full status : %x\n",__func__,status);) + + if(status & I2C_LPC_RBF) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is full status : %x\n",__func__,status);) + break; + } + + status = get_lpc(adap, I2C_LPC_REG_TEST); + + DEBPROTO(lpc_fprintf_debug("%s : The test register data : %x\n",__func__,status);) + udelay(1); /* wait for 100 us */ + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout waiting for Bus Full\n",__func__);) + return -ETIMEDOUT; + } + + return 0; +} + +static int wait_for_td(struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + int status=0; + + while (--timeout) { + udelay(4); + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus done status : %x\n",__func__,status);) + + if(status == I2C_LPC_TD) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is done status : %x\n",__func__,status);) + break; + } + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout waiting for Bus Done\n",__func__);) + return -ETIMEDOUT; + } + + return 0; +} + + + +static int wait_for_pin(struct i2c_algo_lpc_data *adap, int *status) +{ + int timeout = DEF_TIMEOUT; + *status = get_lpc(adap, I2C_LPC_REG_STATUS); + + while ((*status & I2C_LPC_TBE) && --timeout) { + *status = get_lpc(adap, I2C_LPC_REG_STATUS); + } + + if (timeout == 0) + return -ETIMEDOUT; + + + return 0; +} + + +static int lpc_doAddress(struct i2c_algo_lpc_data *adap,struct i2c_msg *msg) +{ + unsigned short flags = msg->flags; + unsigned char addr; + + addr = msg->addr << 1; + if (flags & I2C_M_RD) + { + addr |= 1; + DEBPROTO(lpc_fprintf_debug("step 7 : read mode then write device address 0x%x\n",addr);) + } + else + { + DEBPROTO(lpc_fprintf_debug("step 2 : write mode then write device address 0x%x\n",addr);) + } + + if (flags & I2C_M_REV_DIR_ADDR) + { + addr ^= 1; + + } + i2c_outaddr(adap, addr); + return 0; + +} + + +static int lpc_sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) +{ + struct i2c_algo_lpc_data *adap = i2c_adap->algo_data; + int i = 0,timeout=0; + + unsigned int count = msg->len; + unsigned char *buf = msg->buf; + + do{ + lpc_doAddress(adap,msg); + set_lpc(adap, I2C_LPC_REG_BYTE_COUNT, (count-i) >= 4 ? 4:(count - i)); + DEBPROTO(lpc_fprintf_debug("step 3 : write register count %x\n",count);) + + if((count -i) >= 4) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + i2c_outbyte2(adap, buf[i+1] & 0xff); + i2c_outbyte3(adap, buf[i+2] & 0xff); + i2c_outbyte4(adap, buf[i+3] & 0xff); + + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+2,buf[i+2]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+3,buf[i+3]);) + i += 4; + } + else if((count -i) == 3) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + i2c_outbyte2(adap, buf[i+1] & 0xff); + i2c_outbyte3(adap, buf[i+2] & 0xff); + + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+2,buf[i+2]);) + + i += 3; + } + else if((count -i) == 2) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + i2c_outbyte2(adap, buf[i+1] & 0xff); + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+1,buf[i+1]);) + i += 2; + } + else if((count -i) == 1) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + i += 1; + } + + /* Send START */ + DEBPROTO(lpc_fprintf_debug("step 5-1 : Delay 6mS \n");) + udelay(6000); + DEBPROTO(lpc_fprintf_debug("step 5-2 : Start to transfrom \n");) + i2c_stop(adap); + i2c_start(adap); + DEBPROTO(lpc_fprintf_debug("step 5-3 : Start done\n");) + + udelay(400); + DEBPROTO(lpc_fprintf_debug("step 6 : Waiting for BE\n");) + timeout = wait_for_td(adap); + if (timeout) { + DEBPROTO(lpc_fprintf_debug("step 6 : Timeout waiting for BE \n");) + return -EREMOTEIO; + } + }while (i < count); + + if(i == count) + { + DEBPROTO(lpc_fprintf_debug("Writen %d bytes successd !\n",count);) + return i; + } + else + { + DEBPROTO(lpc_fprintf_debug("Writen %d bytes failed \n",count);) + return -EIO; + } +} + +static int lpc_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) +{ + int i=0,timeout=0; + struct i2c_algo_lpc_data *adap = i2c_adap->algo_data; + + unsigned int count = msg->len; + unsigned char *buf = msg->buf; + + do{ + lpc_doAddress(adap,msg); + set_lpc(adap, I2C_LPC_REG_BYTE_COUNT, (count-i) >= 4 ? 4:(count - i)); + DEBPROTO(lpc_fprintf_debug("step 8 : write register count %d\n",count);) + + /* Send START */ + DEBPROTO(lpc_fprintf_debug("step 9-1 : Delay 6mS\n");) + udelay(6000); + DEBPROTO(lpc_fprintf_debug("step 9-2 : Start to receive data\n");) + i2c_stop(adap); + i2c_start(adap); + DEBPROTO(lpc_fprintf_debug("step 9-3 : Start done\n");) + + udelay(400); + DEBPROTO(lpc_fprintf_debug("step 10 : Waiting for TD\n");) + timeout = wait_for_td(adap); + if (timeout) { + DEBPROTO(lpc_fprintf_debug("step 10 : Timeout waiting for TD \n");) + return -EREMOTEIO; + } + + if((count -i) >= 4) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + buf[i+1] = 0xff & i2c_inbyte2(adap); + buf[i+2] = 0xff & i2c_inbyte3(adap); + buf[i+3] = 0xff & i2c_inbyte4(adap); + + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+2,buf[i+2]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+3,buf[i+3]);) + + i += 4; + } + else if((count -i) == 3) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + buf[i+1] = 0xff & i2c_inbyte2(adap); + buf[i+2] = 0xff & i2c_inbyte3(adap); + + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+2,buf[i+2]);) + + i += 3; + } + else if((count -i) == 2) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + buf[i+1] = 0xff & i2c_inbyte2(adap); + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+1,buf[i+1]);) + i += 2; + } + else if((count -i) == 1) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + i += 1; + } + + + }while(i < count); + + if(i == count) + { + DEBPROTO(lpc_fprintf_debug("Read %d bytes successd !\n",count);) + return i; + } + else + { + DEBPROTO(lpc_fprintf_debug("Read %d bytes failed \n",count);) + return -EIO; + } +} + + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; +#define LPC_I2C_MAX_NCHANS 6 + + +struct lpc_iic { + struct i2c_adapter *virt_adaps[LPC_I2C_MAX_NCHANS]; + u8 last_chan; /* last register value */ +}; + + +static int lpc_master_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, + int num) +{ + struct i2c_algo_lpc_data *adap = i2c_adap->algo_data; + struct i2c_msg *pmsg; + int i; + int ret=0; + + mutex_lock(&lpc_lock); + + if (adap->xfer_begin) + adap->xfer_begin(&i2c_adap->nr); + + + for (i = 0;ret >= 0 && i < num; i++) { + pmsg = &msgs[i]; + + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n", + pmsg->flags & I2C_M_RD ? "read" : "write", + pmsg->len, pmsg->addr, i + 1, num);) + + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n", + i, msgs[i].addr, msgs[i].flags, msgs[i].len);) + + if (pmsg->flags & I2C_M_RD) { + ret = lpc_readbytes(i2c_adap, pmsg); + + if (ret != pmsg->len) { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: fail: " + "only read %d bytes.\n",ret)); + } else { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: read %d bytes.\n",ret)); + } + } else { + + ret = lpc_sendbytes(i2c_adap, pmsg); + + if (ret != pmsg->len) { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: fail: " + "only wrote %d bytes.\n",ret)); + } else { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: wrote %d bytes.\n",ret)); + } + } + } + + if (adap->xfer_end) + adap->xfer_end(&i2c_adap->nr); + + mutex_unlock(&lpc_lock); + + DEBPROTO(lpc_fprintf_debug("ret = 0x%x num = 0x%x i = 0x%x.\n",ret,num,i)); + + return ret = (ret < 0) ? ret : num; +} + + +static u32 lpc_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_QUICK; +} + +/* exported algorithm data: */ +static const struct i2c_algorithm lpc_algo = { + .master_xfer = lpc_master_xfer, + //.smbus_xfer = lpc_smbus_xfer, + .functionality = lpc_func, +}; + + +/********************************************** End ********************************************************/ + + + + + + +/********************************************** Start ********************************************************/ +#define DEFAULT_BASE 0x0a00 + +static int lpc_base= 0x0a00; +static u8 __iomem *lpc_base_iomem; + +static int lpc_irq; +static int lpc_clock = 0x1c; +static int lpc_own = 0x55; +static int lpc_mmapped; + +static unsigned long lpc_base_addr = 0x0a00; +static unsigned int lpc_io_space_size = 2; + +static unsigned long LPC_INDEX_REG; +static unsigned long LPC_DATA_REG; + + +/* notice : removed static struct i2c_lpc_iic gpi; code - + this module in real supports only one device, due to missing arguments + in some functions, called from the algo-lpc module. Sometimes it's + need to be rewriten - but for now just remove this for simpler reading */ + +static wait_queue_head_t lpc_wait; +static int lpc_pending; +static spinlock_t lock; +static spinlock_t lpc_slock; + +static struct i2c_adapter lpc_iic_ops; + +struct cpld_dev_type { + struct resource *io_resource; + struct semaphore sem; + struct cdev cdev; +}; + +struct cpld_dev_type *cpld_device; + + +/* ----- local functions ---------------------------------------------- */ + +static void lpc_cpld_setbyte(void *data, int ctl, int val) +{ + outb(ctl, LPC_INDEX_REG); + mb(); + + outb(val, LPC_DATA_REG); + mb(); +} + +static int lpc_cpld_getbyte(void *data, int ctl) +{ + u8 val = 0; + + outb(ctl, LPC_INDEX_REG); + mb(); + + val = inb(LPC_DATA_REG); + mb(); + + return val; +} + +static void lpc_iic_setbyte(void *data, int ctl, int val) +{ + if (!cpld_device) + { + return ; + } + + if (down_interruptible(&cpld_device->sem)) + { + return ; + } + + + lpc_cpld_setbyte(data,ctl,val); + + up(&cpld_device->sem); + DEBPROTO(lpc_fprintf_debug("%s REG[%x] = %x\n",__func__,ctl,val);) +} + + +static int lpc_iic_getbyte(void *data, int ctl) +{ + u8 val = 0; + if (!cpld_device) + return -ENOTTY; + + if (down_interruptible(&cpld_device->sem)) + return -ERESTARTSYS; + + val = lpc_cpld_getbyte(data,ctl); + + up(&cpld_device->sem); + DEBPROTO(lpc_fprintf_debug("%s REG[%x] = %x\n",__func__,ctl,val);) + return val; +} + +int cig_cpld_read_register(u8 reg_off, u8 *val) +{ + if (!cpld_device) + return -ENOTTY; + + if (down_interruptible(&cpld_device->sem)) + return -ERESTARTSYS; + + *val = lpc_cpld_getbyte(cpld_device, reg_off); + + up(&cpld_device->sem); + + return 0; +} +EXPORT_SYMBOL(cig_cpld_read_register); + +int cig_cpld_write_register(u8 reg_off, u8 val) +{ + if (!cpld_device) + return -ENOTTY; + + if (down_interruptible(&cpld_device->sem)) + return -ERESTARTSYS; + + lpc_cpld_setbyte(cpld_device, reg_off, val); + up(&cpld_device->sem); + return 0; +} +EXPORT_SYMBOL(cig_cpld_write_register); + + + +static int lpc_iic_getown(void *data) +{ + return (lpc_own); +} + + +static int lpc_iic_getclock(void *data) +{ + return (lpc_clock); +} + +static void lpc_iic_waitforpin(void *data) +{ + DEFINE_WAIT(wait); + int timeout = 2; + unsigned long flags; + + if (lpc_irq > 0) { + spin_lock_irqsave(&lock, flags); + if (lpc_pending == 0) { + spin_unlock_irqrestore(&lock, flags); + prepare_to_wait(&lpc_wait, &wait, TASK_INTERRUPTIBLE); + if (schedule_timeout(timeout*HZ)) { + spin_lock_irqsave(&lock, flags); + if (lpc_pending == 1) { + lpc_pending = 0; + } + spin_unlock_irqrestore(&lock, flags); + } + finish_wait(&lpc_wait, &wait); + } else { + lpc_pending = 0; + spin_unlock_irqrestore(&lock, flags); + } + } else { + udelay(100); + } +} + + +static irqreturn_t lpc_iic_handler(int this_irq, void *dev_id) { + spin_lock(&lock); + lpc_pending = 1; + spin_unlock(&lock); + wake_up_interruptible(&lpc_wait); + return IRQ_HANDLED; +} + +static int board_id = 0; + + +static int lpc_iic_select(void *data) +{ + unsigned int chan_id=0; + chan_id = *(unsigned int *)data; + chan_id -= 2; + DEBPROTO(lpc_fprintf_debug("step 1 : selest channel id = %d\n",chan_id);) + lpc_iic_setbyte(data,I2C_LPC_REG_BUS_SEL,chan_id); + + return 0; +} + +static int lpc_iic_deselect(void *data) +{ + + unsigned int chan_id=0; + chan_id = *(unsigned int *)data; + chan_id -= 2; + DEBPROTO(lpc_fprintf_debug("step last :deselect channel id = %d\n",chan_id);) + + return 0; +} + + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ +static struct i2c_algo_lpc_data lpc_iic_data = { + .setlpc = lpc_iic_setbyte, + .getlpc = lpc_iic_getbyte, + .getown = lpc_iic_getown, + .getclock = lpc_iic_getclock, + .waitforpin = lpc_iic_waitforpin, + .xfer_begin = lpc_iic_select, + .xfer_end = lpc_iic_deselect, +}; + +#include + +static struct i2c_adapter lpc_iic_arr_ops[LPC_I2C_MAX_NCHANS] = {0}; + +static void dummy_setscl(void *data, int state) +{ + return; +} + +static void dummy_setsda(void *data, int state) +{ + return; + +} + +static int dummy_getscl(void *data) +{ + return 1; + +} + +static int dummy_getsda(void *data) +{ + return 1; +} + + +static struct i2c_algo_bit_data dummy_algo_data = { + .setsda = dummy_setsda, + .setscl = dummy_setscl, + .getsda = dummy_getsda, + .getscl = dummy_getscl, + .udelay = 50, + .timeout = HZ, +}; + + +static int dummy_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, + int num) +{ + return 1; +} + +static u32 dummy_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_QUICK; +} + + +static const struct i2c_algorithm dummy_algo = { + .master_xfer = dummy_xfer, + .functionality = dummy_func, +}; + + + +static struct i2c_adapter i2c_dummy = { + .owner = THIS_MODULE, + .class = I2C_CLASS_HWMON, + .algo_data = &dummy_algo_data, + .algo = &dummy_algo, + .name = "i2c_dummy", +}; + + +static int lpc_iic_match(struct device *dev, unsigned int id) +{ + /* sanity checks for lpc_mmapped I/O */ + + DEB2(printk("lpc_iic_match\n");) + + + if (lpc_base < DEFAULT_BASE) { + dev_err(dev, "incorrect lpc_base address (%#x) specified " + "for lpc_mmapped I/O\n", lpc_base); + return 0; + } + + if (lpc_base == 0) { + lpc_base = DEFAULT_BASE; + } + return 1; +} + +static int lpc_iic_probe(struct device *dev, unsigned int id) +{ + int rval,num; + + lpc_fprintf_init(); + + DEB2(printk("lpc_iic_probe\n");) + + mutex_init(&lpc_lock); + + for(num = 0; num < LPC_I2C_MAX_NCHANS;num++) + { + lpc_iic_arr_ops[num].dev.parent = dev; + lpc_iic_arr_ops[num].owner = THIS_MODULE; + lpc_iic_arr_ops[num].class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + lpc_iic_arr_ops[num].algo = &lpc_algo; + lpc_iic_arr_ops[num].algo_data = &lpc_iic_data, + lpc_iic_arr_ops[num].nr=num; + snprintf(lpc_iic_arr_ops[num].name, sizeof(lpc_iic_arr_ops[num].name), "i2c-%d-lpc", i2c_adapter_id(&lpc_iic_arr_ops[num])); + rval |= i2c_add_adapter(&lpc_iic_arr_ops[num]); + DEB2(printk("%s\n",lpc_iic_arr_ops[num].name);) + } + + return 0; +} + +static int lpc_iic_remove(struct device *dev, unsigned int id) +{ + int num; + DEB2(printk("lpc_iic_remove\n")); + + lpc_fprintf_exit(); + for(num = LPC_I2C_MAX_NCHANS - 1; num >= 0 ;num--) + i2c_del_adapter(&lpc_iic_arr_ops[num]); + + + return 0; +} + +static struct isa_driver i2c_lpc_driver = { + .match = lpc_iic_match, + .probe = lpc_iic_probe, + .remove = lpc_iic_remove, + .driver = { + .owner = THIS_MODULE, + .name = "lpc-iic", + }, +}; + +/********************************************** End ********************************************************/ + + + + + + +/********************************************** Start ********************************************************/ + +static int cpld_major = 0; +static int cpld_minor = 0; + +struct cpld_rw_msg { + unsigned char addr; + unsigned char data; +}; + + +static struct cpld_rw_msg param_read = {-1}; +static struct cpld_rw_msg param_write = {-1}; +static struct cpld_rw_msg param_reads = {-1}; +static struct cpld_rw_msg param_writes = {-1}; + +void cpld_sysfs_kobj_release(struct kobject *kobj) +{ + return; +} + +int cpld_sysfs_add_attr(struct kobject* kobj, char* attr_name) +{ + + struct attribute *attr; + + attr = kmalloc(sizeof(struct attribute), GFP_KERNEL); + attr->name = attr_name; + attr->mode = 0644; + + return sysfs_create_file(kobj, attr); +} + +static int cig_cpld_write_slave_cpld_register(u8 reg_addr, u8 reg_data); +static int cig_cpld_read_slave_cpld_register(u8 reg_addr, u8 *reg_data); + + +static ssize_t cpld_sysfs_show(struct kobject *kobj, struct attribute *attr, char *buffer) +{ + u8 val=0,ret=0,year=0,month=0,day=0,cpld_m=0,cpld_1=0,cpld_2=0; + + if (0 == strcmp(attr->name, "read")) + { + val = lpc_iic_getbyte(NULL,param_read.addr); + ret = sprintf(buffer,"read : addr = 0x%x val = 0x%x\n",param_read.addr, val); + + } + else if (0 == strcmp(attr->name, "write")) + { + lpc_iic_setbyte(NULL, param_write.addr,param_write.data); + ret = sprintf(buffer,"write : addr = 0x%x val = 0x%x\n",param_write.addr, param_write.data); + } + else if (0 == strcmp(attr->name, "version")) + { + cpld_m = lpc_iic_getbyte(NULL, 0x02); + year = lpc_iic_getbyte(NULL, 0x03); + month = lpc_iic_getbyte(NULL, 0x04); + day = lpc_iic_getbyte(NULL, 0x05); + + cig_cpld_read_slave_cpld_register(0x1d,&cpld_1); + cig_cpld_read_slave_cpld_register(0x1e,&cpld_2); + + ret = sprintf(buffer,"Main CPLD version : V%02x\n"\ + "Main CPLD date : 20%02x-%02x-%02x\n"\ + "Slave 1 CPLD version : V%02x\n"\ + "Slave 2 CPLD version : V%02x\n",cpld_m,year,month,day,cpld_1,cpld_2); + } + if (0 == strcmp(attr->name, "reads")) + { + ret = cig_cpld_read_slave_cpld_register(param_reads.addr,&val); + if (ret < 0) + printk("ERROR:Failed to read slave cpld.\n"); + ret = sprintf(buffer,"reads : addr = 0x%x val = 0x%x\n",param_reads.addr, val); + + } + else if (0 == strcmp(attr->name, "writes")) + { + ret = cig_cpld_write_slave_cpld_register(param_writes.addr,param_writes.data); + if (ret < 0) + printk("ERROR:Failed to read slave cpld.\n"); + ret = sprintf(buffer,"writes : addr = 0x%x val = 0x%x\n",param_writes.addr, param_writes.data); + } + + + return ret; + +} + +static ssize_t cpld_sysfs_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t count) +{ + int param[3]; + + if (0 == strcmp(attr->name, "read")) + { + sscanf(buffer, "0x%02x", ¶m[0]); + param_read.addr = param[0]; + } + else if (0 == strcmp(attr->name, "write")) + { + sscanf(buffer, "0x%2x 0x%02x", ¶m[0], ¶m[1]); + param_write.addr = param[0]; + param_write.data = param[1]; + } + if (0 == strcmp(attr->name, "reads")) + { + sscanf(buffer, "0x%02x", ¶m[0]); + param_reads.addr = param[0]; + } + else if (0 == strcmp(attr->name, "writes")) + { + sscanf(buffer, "0x%2x 0x%02x", ¶m[0], ¶m[1]); + param_writes.addr = param[0]; + param_writes.data = param[1]; + } + return count; +} + + + +static struct sysfs_ops cpld_sysfs_ops = +{ + .show = cpld_sysfs_show, + .store = cpld_sysfs_store, +}; + +static struct kobj_type cpld_kobj_type = +{ + .release = cpld_sysfs_kobj_release, + .sysfs_ops = &cpld_sysfs_ops, + .default_attrs = NULL, +}; + + +static const char driver_name[] = "cpld_drv"; +static atomic_t cpld_available = ATOMIC_INIT(1); +static struct class *cpld_class; +static struct device *cpld_dev; + + + +#define CPLD_IOC_MAGIC '[' + +#define CPLD_IOC_RDREG _IOR(CPLD_IOC_MAGIC, 0, struct cpld_rw_msg) +#define CPLD_IOC_WRREG _IOW(CPLD_IOC_MAGIC, 1, struct cpld_rw_msg) + +#define CPLD_IOC_MAXNR 2 + + +int cpld_open(struct inode *inode, struct file *filp) +{ + struct cpld_dev_type *dev; + + if (! atomic_dec_and_test(&cpld_available)) { + atomic_inc(&cpld_available); + return -EBUSY; + } + + dev = container_of(inode->i_cdev, struct cpld_dev_type, cdev); + filp->private_data = dev; + + return 0; +} + +int cpld_release(struct inode *inode, struct file *flip) +{ + atomic_inc(&cpld_available); + return 0; +} + + +long cpld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int rc = 0; + int err = 0; + struct cpld_dev_type *dev = (struct cpld_dev_type *)filp->private_data; + struct cpld_rw_msg msg; + + if (_IOC_TYPE(cmd) != CPLD_IOC_MAGIC) + return -ENOTTY; + if (_IOC_NR(cmd) > CPLD_IOC_MAXNR) + return -ENOTTY; + + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; + + switch(cmd){ + case CPLD_IOC_RDREG: + rc = copy_from_user(&msg, (void __user *)arg, sizeof(msg)); + if (!rc) { + msg.data = lpc_cpld_getbyte(dev, msg.addr); + rc = copy_to_user((void __user *)arg, &msg, sizeof(msg)); + } + break; + + case CPLD_IOC_WRREG: + rc = copy_from_user(&msg, (void __user *)arg, sizeof(msg)); + if (!rc) { + lpc_cpld_setbyte(dev, msg.addr, msg.data); + } + break; + default: + rc = -ENOTTY; + break; + } + up(&dev->sem); + + return rc; +} + +struct file_operations cpld_fops = { + .owner = THIS_MODULE, + .open = cpld_open, + .unlocked_ioctl = cpld_ioctl, + .release = cpld_release, +}; + + +static void cpld_setup_cdev(struct cpld_dev_type *dev) +{ + int err, devno = MKDEV(cpld_major, cpld_minor); + + cdev_init(&dev->cdev, &cpld_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &cpld_fops; + err = cdev_add(&dev->cdev, devno, 1); + + if (err) + DEB2(printk(KERN_NOTICE "Error %d adding cpld", err);) +} +/********************************************** End ********************************************************/ + + + + +/********************************************** Start ********************************************************/ +#include +#include +#include + +static spinlock_t irq_inter_lock; +static struct delayed_work irq_inter_work; +static unsigned long irq_inter_delay; + + +static int cig_cpld_write_slave_cpld_register(u8 reg_addr, u8 reg_data) +{ + u8 read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + DEB2(printk("<=======write=========>")); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, reg_addr << 1); + DEB2(printk("[62]=%x\n",reg_addr << 1)); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_TX, reg_data); + DEB2(printk("[63]=%x\n",reg_data)); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + DEB2(printk("[65]=%x\n",0x80)); + do{ + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &read_status); + DEB2(printk("[66]=%x\n",read_status)); + udelay(60); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(read_status != 0x02); + DEB2(printk("<=======write=========>")); + + + if(wait_time_out == 0) + return -1; + + return 1; +} + + +static int cig_cpld_read_slave_cpld_register(u8 reg_addr, u8 *reg_data) +{ + u8 read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + DEB2(printk("<========read=========>")); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, reg_addr << 1 | 1); + DEB2(printk("[62]=%x\n",reg_addr << 1 | 1)); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + DEB2(printk("[65]=%x\n",0x80)); + do{ + udelay(60); + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &read_status); + DEB2(printk("[66]=%x\n",read_status)); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(read_status != 0x01); + + cig_cpld_read_register(ADDR_REG_SFP_STATUS_RX,reg_data); + DEB2(printk("[64]=%x\n",*reg_data)); + DEB2(printk("<========read=========>")); + + if(wait_time_out == 0) + return -1; + + return 1; +} + + + +struct sock *nlsk = NULL; +extern struct net init_net; +#define NETLINK_TEST 26 +#define MSG_LEN 125 +#define USER_PORT 100 +static u32 irq_present_status_low_current,irq_present_status_low_next; +static u32 irq_present_status_high_current,irq_present_status_high_next; +static u32 irq_tx_fault_status_low_current,irq_tx_fault_status_low_next; +static u32 irq_tx_fault_status_high_current,irq_tx_fault_status_high_next; +static u32 irq_rx_lost_status_low_current,irq_rx_lost_status_low_next; +static u32 irq_rx_lost_status_high_current,irq_rx_lost_status_high_next; + +static u8 irq_present_qsfp_current,irq_present_qsfp_next; +static u8 irq_interrupt_qsfp_current,irq_interrupt_qsfp_next; + +struct input_dev *cpld_input_dev; + + + +int send_usrmsg(char *pbuf, uint16_t len) +{ + struct sk_buff *nl_skb; + struct nlmsghdr *nlh; + + int ret; + + + nl_skb = nlmsg_new(len, GFP_ATOMIC); + if(!nl_skb) + { + printk("netlink alloc failure\n"); + return -1; + } + + + nlh = nlmsg_put(nl_skb, 0, 0, NETLINK_TEST, len, 0); + if(nlh == NULL) + { + printk("nlmsg_put failaure \n"); + nlmsg_free(nl_skb); + return -1; + } + + memcpy(nlmsg_data(nlh), pbuf, len); + ret = netlink_unicast(nlsk, nl_skb, USER_PORT, MSG_DONTWAIT); + + return ret; +} + +static void netlink_rcv_msg(struct sk_buff *skb) +{ + + struct nlmsghdr *nlh = NULL; + char *umsg = NULL; + char kmsg[1024] = {0}; + char kmsg_tmp[16] = {0}; + u8 i = 0; + u8 tmp[3]={0}; + + if(skb->len >= nlmsg_total_size(0)) + { + nlh = nlmsg_hdr(skb); + umsg = NLMSG_DATA(nlh); + if(umsg) + { + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_low_current & (0x1 << i))) + { + tmp[0] = 1; + } + else + { + tmp[0] = 0; + } + + if(!(irq_rx_lost_status_low_current & (0x1 << i))) + { + tmp[1] = 1; + } + else + { + tmp[1] = 0; + } + + if(!(irq_tx_fault_status_low_current & (0x1 << i))) + { + tmp[2] = 1; + } + else + { + tmp[2] = 0; + } + memset(kmsg_tmp,0xff,sizeof(kmsg_tmp)); + sprintf(kmsg_tmp,"sfp%02d:%1d:%1d:%1d ",i+1,tmp[0],tmp[1],tmp[2]); + strcat(kmsg,kmsg_tmp); + } + + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_high_current & (0x1 << i))) + { + tmp[0] = 1; + } + else + { + tmp[0] = 0; + } + + if(!(irq_rx_lost_status_high_current & (0x1 << i))) + { + tmp[1] = 1; + } + else + { + tmp[1] = 0; + } + + if(!(irq_tx_fault_status_high_current & (0x1 << i))) + { + tmp[2] = 1; + } + else + { + tmp[2] = 0; + } + memset(kmsg_tmp,0xff,sizeof(kmsg_tmp)); + sprintf(kmsg_tmp,"sfp%02d:%1d:%1d:%1d ",i+25,tmp[0],tmp[1],tmp[2]); + strcat(kmsg,kmsg_tmp); + } + + + for(i = 0;i < 8;i++) + { + if(!(irq_present_qsfp_current & (0x1 << i))) + { + tmp[0] = 1; + } + else + { + tmp[0] = 0; + } + + if(!(irq_interrupt_qsfp_current & (0x1 << i))) + { + tmp[1] = 1; + } + else + { + tmp[1] = 0; + } + + memset(kmsg_tmp,0xff,sizeof(kmsg_tmp)); + sprintf(kmsg_tmp,"qsfp%02d:%1d:%1d:%1d ",i+49,tmp[0],tmp[1],0); + strcat(kmsg,kmsg_tmp); + } + + printk("kernel recv from user: %s\n", umsg); + send_usrmsg(kmsg, strlen(kmsg)); + } + } + + return ; +} + + + +struct netlink_kernel_cfg cfg = { + .input = netlink_rcv_msg, /* set recv callback */ +}; + + + +#define RANGE_OF_BYTE_SHIFT(to_arg,shift,from_arg) {to_arg &= ~(0xff << shift); to_arg |= from_arg << shift;} + + +static void irq_inter_wapper(struct work_struct * work) +{ + + u8 m_data = 0; + u8 data_high8 = 0,data_low8 = 0; + u16 data_16 = 0; + u8 status = 0; + u8 i = 0; + char kmsg[64]={0}; + u8 tmp[3] = {0}; + + DEB2(printk("CPLD_MASTER_INTERRUPT\r\n")); + + m_data = lpc_iic_getbyte(NULL,CPLD_MASTER_INTERRUPT_STATUS_REG); + lpc_iic_setbyte(NULL,CPLD_MASTER_INTERRUPT_STATUS_REG,0xff); + + cig_cpld_write_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_MASK_REG,0xff); + cig_cpld_write_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_MASK_REG,0xff); + if(!(m_data & CPLD_MASTER_INTERRUPT_CPLD1)) + { + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_STATUS_H_REG,&data_high8); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_STATUS_L_REG,&data_low8); + data_16 = data_low8 | data_high8 << 8; + if( + !(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT08) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT16) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT24) + ) + { + if(!(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT08)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT08\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_PRESENT08_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_low_current,0,status); + + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT16)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT16\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_PRESENT16_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_low_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT24)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT24\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_PRESENT24_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_low_current,16,status); + } + DEB2(printk("irq_present_status_low_next = %08x irq_present_status_low_current = %08x \n",irq_present_status_low_next,irq_present_status_low_current)); + } + + if( + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST08) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST16) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST24) + ) + { + if(!(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST08)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_RX_LOST08\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_RX_LOST08_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_low_current,0,status); + + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST16)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT16\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_RX_LOST16_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_low_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST24)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT24\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_RX_LOST24_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_low_current,16,status); + } + DEB2(printk("irq_rx_lost_status_low_next = %08x irq_rx_lost_status_low_current = %08x \n",irq_rx_lost_status_low_next,irq_rx_lost_status_low_current)); + } + + if( + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST08) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST16) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST24) + ) + { + if(!(data_16 & CPLD_SLAVE1_INTERRUPT_TX_FAULT08)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_TX_FAULT08\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_TX_FAULT08_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_low_current,0,status); + + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_TX_FAULT16)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_TX_FAULT16\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_TX_FAULT16_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_low_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_TX_FAULT24)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_TX_FAULT24\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_TX_FAULT24_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_low_current,16,status); + } + DEB2(printk("irq_tx_fault_status_low_next = %08x irq_tx_fault_status_low_current = %08x \n",irq_tx_fault_status_low_next,irq_tx_fault_status_low_current)); + + } + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_CPLD2)) + { + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_STATUS_H_REG,&data_high8); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_STATUS_L_REG,&data_low8); + data_16 = data_low8 | data_high8 << 8; + if( + !(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT32) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT40) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT48) + ) + { + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT32)) + { + DEB2(printk("CPLD_SLAVE2_PRESENT32_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT32_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_high_current,0,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT40)) + { + DEB2(printk("CPLD_SLAVE2_PRESENT40_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT40_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_high_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT48)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT48\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT48_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_high_current,16,status); + } + } + + if( + !(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST32) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST40) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST48) + ) + { + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST32)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_RX_LOST32\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_RX_LOST32_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_high_current,0,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST40)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT40\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_RX_LOST40_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_high_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST48)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT48\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_RX_LOST48_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_high_current,16,status); + } + + } + + if( + !(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT32) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT40) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT48) + ) + { + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT32)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_RX_LOST32\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_TX_FAULT32_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_high_current,0,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT40)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT40\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_TX_FAULT40_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_high_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT48)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT48\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_TX_FAULT48_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_high_current,16,status); + } + } + + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT56)) + { + DEB2(printk("CPLD_SLAVE2_PRESENT56_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT56_REG,&status); + irq_present_qsfp_current = status; + } + + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_QSFP_CR56)) + { + DEB2(printk("CPLD_SLAVE2_QSFP_CR56_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_QSFP_CR56_REG,&status); + irq_interrupt_qsfp_current = status; + } + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_LSW)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_LSW\r\n")); + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_PSU1)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_PSU1\r\n")); + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_PSU2)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_PSU2\r\n")); + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_6320)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_6320\r\n")); + } + cig_cpld_write_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_MASK_REG,0x0); + cig_cpld_write_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_MASK_REG,0x0); + + memset(tmp,0xff,sizeof(tmp)); + + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_low_current & (0x1 << i)) && (irq_present_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d is present\r\n",i+1)); + tmp[0] = 1; + } + else if((irq_present_status_low_current & (0x1 << i)) && !(irq_present_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d is absent\r\n",i+1)); + tmp[0] = 0; + } + + if(!(irq_tx_fault_status_low_current & (0x1 << i)) && (irq_tx_fault_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is right\r\n",i+1)); + tmp[1] = 1; + } + else if((irq_tx_fault_status_low_current & (0x1 << i)) && !(irq_tx_fault_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is fault\r\n",i+1)); + tmp[1] = 0; + } + + if(!(irq_rx_lost_status_low_current & (0x1 << i)) && (irq_rx_lost_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is meet\r\n",i+1)); + tmp[2] = 1; + } + else if((irq_rx_lost_status_low_current & (0x1 << i)) && !(irq_rx_lost_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is lost\r\n",i+1)); + tmp[2] = 0; + } + + if((tmp[0] != 0xff) || (tmp[1] != 0xff) || (tmp[2] != 0xff)) + { + memset(kmsg,0xff,sizeof(kmsg)); + snprintf(kmsg,sizeof(kmsg),"sfp%02d:%1d:%1d:%1d ",i+1,(tmp[0] == 0xff) ? 0:tmp[0],(tmp[1] == 0xff) ? 0:tmp[1],(tmp[2] == 0xff) ? 0:tmp[2]); + break; + } + } + + memset(tmp,0xff,sizeof(tmp)); + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_high_current & (0x1 << i)) && (irq_present_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d is present\r\n",i+25)); + tmp[0] = 1; + } + else if((irq_present_status_high_current & (0x1 << i)) && !(irq_present_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d is absent\r\n",i+25)); + tmp[0] = 0; + + } + + if(!(irq_rx_lost_status_high_current & (0x1 << i)) && (irq_rx_lost_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is meet\r\n",i+25)); + tmp[1] = 1; + } + else if((irq_rx_lost_status_high_current & (0x1 << i)) && !(irq_rx_lost_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is lost\r\n",i+25)); + tmp[1] = 0; + } + + if(!(irq_tx_fault_status_high_current & (0x1 << i)) && (irq_tx_fault_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is right\r\n",i+25)); + tmp[2] = 1; + } + else if((irq_tx_fault_status_high_current & (0x1 << i)) && !(irq_tx_fault_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is fault\r\n",i+25)); + tmp[2] = 0; + } + + if((tmp[0] != 0xff) || (tmp[1] != 0xff) || (tmp[2] != 0xff)) + { + memset(kmsg,0xff,sizeof(kmsg)); + snprintf(kmsg,sizeof(kmsg),"sfp%02d:%1d:%1d:%1d ",i+25,(tmp[0] == 0xff) ? 0:tmp[0],(tmp[1] == 0xff) ? 0:tmp[1],(tmp[2] == 0xff) ? 0:tmp[2]); + break; + } + } + + memset(tmp,0xff,sizeof(tmp)); + for(i = 0 ; i < 8; i++) + { + if(!(irq_present_qsfp_current & (0x1 << i)) && (irq_present_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d is present\r\n",i+49)); + tmp[0] = 1; + } + else if((irq_present_qsfp_current & (0x1 << i)) && !(irq_present_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d is absent\r\n",i+49)); + tmp[0] = 0; + } + + if(!(irq_interrupt_qsfp_current & (0x1 << i)) && (irq_interrupt_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d interrupt is occured \r\n",i+49)); + tmp[1] = 1; + } + else if((irq_interrupt_qsfp_current & (0x1 << i)) && !(irq_interrupt_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d interrupt is cleaned\r\n",i+49)); + tmp[1] = 0; + } + + if((tmp[0] != 0xff) || (tmp[1] != 0xff)) + { + memset(kmsg,0xff,sizeof(kmsg)); + snprintf(kmsg,sizeof(kmsg),"qsfp%02d:%1d:%1d:%1d ",i+49,(tmp[0] == 0xff) ? 0:tmp[0],(tmp[1] == 0xff) ? 0:tmp[1],0); + break; + } + } + + + irq_present_status_low_next = irq_present_status_low_current; + irq_rx_lost_status_low_next = irq_rx_lost_status_low_current; + irq_tx_fault_status_low_next = irq_tx_fault_status_low_current; + irq_present_status_high_next = irq_present_status_high_current; + irq_rx_lost_status_high_next = irq_rx_lost_status_high_current; + irq_tx_fault_status_high_next = irq_tx_fault_status_high_current; + irq_present_qsfp_next = irq_present_qsfp_current; + irq_interrupt_qsfp_next = irq_interrupt_qsfp_current; + + send_usrmsg(kmsg, strlen(kmsg)); +} + +static void disableIrq(unsigned short maskReg, unsigned short mask) +{ + u8 data = 0; + + data = lpc_iic_getbyte(NULL,maskReg); + data |= mask; + lpc_iic_setbyte(NULL,maskReg, data); +} + +static void enableIrq(unsigned short maskReg, unsigned short mask) +{ + unsigned short data; + + data = lpc_iic_getbyte(NULL,maskReg); + data &= ~mask; + lpc_iic_setbyte(NULL,maskReg, data); +} + + +static irqreturn_t irq_inter_isr(int irq, void *handle) +{ + + /* + * use keventd context to read the event fifo registers + * Schedule readout at least 25ms after notification for + * REVID < 4 + */ + + schedule_delayed_work(&irq_inter_work, irq_inter_delay); + + return IRQ_HANDLED; +} + + +#define CIG_CPLD_CHR_NAME "cpld" + + +static int __init cpld_init(void) +{ + int rval,rc=0; + dev_t dev; + u8 s_data; + int isr_GPIO_num = 289; + + DEB2(printk("cpld_init\n");) + +/**************************************************************************************/ + + LPC_INDEX_REG = lpc_base_addr; + LPC_DATA_REG = lpc_base_addr + 1; + + cpld_device = kzalloc(sizeof(struct cpld_dev_type), GFP_KERNEL); + if (!cpld_device) + goto error3; + cpld_device->io_resource = request_region(lpc_base_addr, + lpc_io_space_size, "lpc-i2c"); + if (!cpld_device->io_resource) { + printk("lpc: claim I/O resource fail\n"); + goto error2; + } + sema_init(&cpld_device->sem, 1); + + if (cpld_major) { + dev = MKDEV(cpld_major, cpld_minor); + rc = register_chrdev_region(dev, 1, CIG_CPLD_CHR_NAME); + } else { + rc = alloc_chrdev_region(&dev, cpld_major, 1, CIG_CPLD_CHR_NAME); + cpld_major = MAJOR(dev); + } + + cpld_setup_cdev(cpld_device); + + cpld_class = class_create(THIS_MODULE,CIG_CPLD_CHR_NAME); + if (!cpld_class) { + DEB2(printk("failed to create class\n");) + goto error1; + } + + cpld_class->p->subsys.kobj.ktype= &cpld_kobj_type; + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "read"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "write"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "reads"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "writes"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "version"); + + cpld_dev = device_create(cpld_class, NULL, dev, NULL, CIG_CPLD_CHR_NAME); + +/**************************************************************************************/ + + rval = lpc_bus_init(); + rval = lpc_register_driver(&i2c_lpc_driver, 1); + +/**************************************************************************************/ + return 0; +error1: + cdev_del(&cpld_device->cdev); + unregister_chrdev_region(dev, 1); +error2: + release_resource(cpld_device->io_resource); +error3: + kfree(cpld_device); + + return rc; +} + +static void __exit cpld_exit(void) +{ + DEB2(printk("cpld_exit\n")); + + if (nlsk){ + netlink_kernel_release(nlsk); /* release ..*/ + nlsk = NULL; + } + + + lpc_unregister_driver(&i2c_lpc_driver); + lpc_bus_exit(); + dev_t devno = MKDEV(cpld_major, cpld_minor); + + cdev_del(&cpld_device->cdev); + if (cpld_class) { + device_destroy(cpld_class, devno); + class_destroy(cpld_class); + } + + if (cpld_device) { + if (cpld_device->io_resource) + release_resource(cpld_device->io_resource); + + kfree(cpld_device); + } + unregister_chrdev_region(devno, 1); + + +} + +module_param(cpld_major, int, S_IRUGO); +module_param(cpld_minor, int, S_IRUGO); +module_param(i2c_debug, int, S_IRUGO); +module_param(board_id, int, S_IRUGO); + +module_init(cpld_init); +module_exit(cpld_exit); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs5435-54p-cpld driver"); +MODULE_LICENSE("GPL"); + + +/********************************************** End ********************************************************/ + + + diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-fan.c b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-fan.c new file mode 100644 index 000000000000..a254dae33c2c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-fan.c @@ -0,0 +1,521 @@ +/* + * A hwmon driver for the CIG cs5435-54p fan + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#define FAN_SPEED_DUTY_TO_CPLD_STEP 10 + +static struct cs5435_54p_fan_data *cs5435_54p_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + + +extern int cig_cpld_write_register(u8 reg_off, u8 val); +extern int cig_cpld_read_register(u8 reg_off, u8 *val); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x41, /* fan enable/disable */ + 0x40, /* fan PWM(for all fan) */ + 0x42, /* front fan 1 speed(rpm) */ + 0x44, /* front fan 2 speed(rpm) */ + 0x46, /* front fan 3 speed(rpm) */ + 0x48, /* front fan 4 speed(rpm) */ + 0x4a, /* front fan 5 speed(rpm) */ + 0x43, /* rear fan 1 speed(rpm) */ + 0x45, /* rear fan 2 speed(rpm) */ + 0x47, /* rear fan 3 speed(rpm) */ + 0x49, /* rear fan 4 speed(rpm) */ + 0x4b, /* rear fan 5 speed(rpm) */ + 0x4c, /* fan direction rear to front or front to rear */ +}; + + +/* Each client has this additional data */ +struct cs5435_54p_fan_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +static struct cs5435_54p_fan_data *fan_data = NULL; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, +}; + +enum sysfs_fan_attributes { + FAN_STATE_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN_DIRECTION, + FAN1_STATE, + FAN2_STATE, + FAN3_STATE, + FAN4_STATE, + FAN5_STATE, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, +}; + +/* Define attributes + */ +#define DECLARE_FAN_STATE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_state, S_IRUGO, fan_show_value, NULL, FAN##index##_STATE) +#define DECLARE_FAN_STATE_ATTR(index) &sensor_dev_attr_fan##index##_state.dev_attr.attr + +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IWUSR | S_IRUGO, fan_show_value, set_fan_direction, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + + +/* 5 fan state attributes in this platform */ +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(1); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(2); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(3); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(4); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(5); + + +/* 5 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5); + +/* 5 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5); + +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); + +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); + + +static struct attribute *cs5435_54p_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_STATE_ATTR(1), + DECLARE_FAN_STATE_ATTR(2), + DECLARE_FAN_STATE_ATTR(3), + DECLARE_FAN_STATE_ATTR(4), + DECLARE_FAN_STATE_ATTR(5), + DECLARE_FAN_FAULT_ATTR(1), + DECLARE_FAN_FAULT_ATTR(2), + DECLARE_FAN_FAULT_ATTR(3), + DECLARE_FAN_FAULT_ATTR(4), + DECLARE_FAN_FAULT_ATTR(5), + DECLARE_FAN_SPEED_RPM_ATTR(1), + DECLARE_FAN_SPEED_RPM_ATTR(2), + DECLARE_FAN_SPEED_RPM_ATTR(3), + DECLARE_FAN_SPEED_RPM_ATTR(4), + DECLARE_FAN_SPEED_RPM_ATTR(5), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + NULL +}; + +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + if (reg_val +== 0xFF) { + return 100; + } + return ((u32)(reg_val) * 100)/ 255; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle >= FAN_MAX_DUTY_CYCLE) { + return 0xFF; + } + + return 255 / 10 * (duty_cycle / 10); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_is_state(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct cs5435_54p_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value <= 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + cig_cpld_write_register(fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + + return count; +} + +static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value,fan_index; + u8 mask,reg_val; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + fan_index = attr->index - FAN1_DIRECTION; + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (!(value == 0 || value == 1)) + return -EINVAL; + + + cig_cpld_read_register(fan_reg[FAN_DIRECTION],®_val); + + if(value == 1) + { + reg_val |= (1 << fan_index); + } + else + { + reg_val &= ~(1 << fan_index); + } + + cig_cpld_write_register(fan_reg[FAN_DIRECTION], reg_val); + + return count; +} + + + + + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + cs5435_54p_fan_update_device(dev); + + struct cs5435_54p_fan_data *data = fan_data; + + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + + case FAN1_STATE: + case FAN2_STATE: + case FAN3_STATE: + case FAN4_STATE: + case FAN5_STATE: + //printk("FAN_STATE_REG: 0x%x\n", data->reg_val[FAN_STATE_REG]); + //printk("index: %d\n", attr->index); + ret = sprintf(buf, "%d\n", + reg_val_to_is_state(data->reg_val[FAN_STATE_REG], + attr->index - FAN1_STATE)); + break; + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: +// printk("FAN_seed_REG: 0x%x\n", data->reg_val[attr->index]); +// printk("index: %d\n", attr->index); + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + ret = sprintf(buf, "%d\n",reg_val_to_is_state(data->reg_val[FAN_DIRECTION],attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group cs5435_54p_fan_group = { + .attrs = cs5435_54p_fan_attributes, +}; + +static struct cs5435_54p_fan_data *cs5435_54p_fan_update_device(struct device *dev) +{ + struct cs5435_54p_fan_data *data = fan_data; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + u8 status; + (void)cig_cpld_read_register(fan_reg[i], &status); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int cs5435_54p_fan_probe(struct platform_device *pdev) +{ + int status = -1; + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &cs5435_54p_fan_group); + if (status) { + goto exit; + + } + + fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(fan_data->hwmon_dev)) { + status = PTR_ERR(fan_data->hwmon_dev); + goto exit_remove; + } + + dev_info(&pdev->dev, "cs5435_54p_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &cs5435_54p_fan_group); +exit: + return status; +} + +static int cs5435_54p_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&fan_data->pdev->dev.kobj, &cs5435_54p_fan_group); + + return 0; +} + +#define DRVNAME "cs5435_54p_fan" + +static struct platform_driver cs5435_54p_fan_driver = { + .probe = cs5435_54p_fan_probe, + .remove = cs5435_54p_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + + + + + +static int __init cs5435_54p_fan_init(void) +{ + int ret; + + cig_cpld_write_register(0x40, duty_cycle_to_reg_val(50)); + + ret = platform_driver_register(&cs5435_54p_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct cs5435_54p_fan_data), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&cs5435_54p_fan_driver); + goto exit; + } + + mutex_init(&fan_data->update_lock); + fan_data->valid = 0; + + fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fan_data->pdev)) { + ret = PTR_ERR(fan_data->pdev); + platform_driver_unregister(&cs5435_54p_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit cs5435_54p_fan_exit(void) +{ + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&cs5435_54p_fan_driver); + kfree(fan_data); +} + +MODULE_AUTHOR("CIG"); +MODULE_DESCRIPTION("cs5435_54p_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(cs5435_54p_fan_init); +module_exit(cs5435_54p_fan_exit); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs5435_54p_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-led.c b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-led.c new file mode 100644 index 000000000000..dae49967592e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-led.c @@ -0,0 +1,594 @@ +/* + * A hwmon driver for the CIG cs5435-54P LED + * + * Copyright (C) 2018 Cambridge, Inc. + + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int cig_cpld_write_register(u8 reg_off, u8 val); + +extern int cig_cpld_read_register(u8 reg_off, u8 *val); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "cs5435_54p_led" + +struct cs5435_54p_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[6]; /* 0: system & location + 1: PSU1 &PSU12 + 2: fan & management + 3: console & ToD + 4-5 : fan1-fan5*/ +}; + +static struct cs5435_54p_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_TYPE_PSU1_REG_MASK 0x0C +#define LED_MODE_PSU1_GREEN_MASK 0x08 +#define LED_MODE_PSU1_RED_MASK 0x04 +#define LED_MODE_PSU1_AMBER_MASK 0x0C +#define LED_MODE_PSU1_OFF_MASK 0x00 + +#define LED_TYPE_PSU2_REG_MASK 0x30 +#define LED_MODE_PSU2_GREEN_MASK 0x20 +#define LED_MODE_PSU2_RED_MASK 0x10 +#define LED_MODE_PSU2_AMBER_MASK 0x30 +#define LED_MODE_PSU2_OFF_MASK 0x00 + +#define LED_TYPE_SYS_REG_MASK 0xF0 +#define LED_MODE_SYS_GREEN_MASK 0x40 +#define LED_MODE_SYS_RED_MASK 0x20 +#define LED_MODE_SYS_AMBER_MASK 0x60 +#define LED_MODE_SYS_AMBER_FLASHING_MASK 0x70 +#define LED_MODE_SYS_OFF_MASK 0x00 + +#define LED_TYPE_RES_REG_MASK 0x0F +#define LED_MODE_RES_GREEN_MASK 0x04 +#define LED_MODE_RES_RED_MASK 0x02 +#define LED_MODE_RES_AMBER_MASK 0x06 +#define LED_MODE_RES_AMBER_FLASHING_MASK 0x07 +#define LED_MODE_RES_OFF_MASK 0x00 + +#define LED_TYPE_FAN_REG_MASK 0x03 +#define LED_MODE_FAN_GREEN_MASK 0x02 +#define LED_MODE_FAN_RED_MASK 0x01 +#define LED_MODE_FAN_AMBER_MASK 0x03 +#define LED_MODE_FAN_OFF_MASK 0x00 + +#define LED_TYPE_FAN1_REG_MASK 0x03 +#define LED_TYPE_FAN2_REG_MASK 0x0C +#define LED_TYPE_FAN3_REG_MASK 0x30 +#define LED_TYPE_FAN4_REG_MASK 0xC0 +#define LED_TYPE_FAN5_REG_MASK 0x03 + +#define LED_MODE_FANX_GREEN_MASK 0x02 +#define LED_MODE_FANX_RED_MASK 0x01 +#define LED_MODE_FANX_AMBER_MASK 0x03 +#define LED_MODE_FANX_OFF_MASK 0x00 + +enum led_type { + LED_TYPE_SYS, + LED_TYPE_PSU2, + LED_TYPE_PSU1, + LED_TYPE_FAN, + LED_TYPE_FAN1, + LED_TYPE_FAN2, + LED_TYPE_FAN3, + LED_TYPE_FAN4, + LED_TYPE_FAN5, +}; + +static const u8 led_reg[] = { + 0x30, /* system & reserved*/ + 0x31, /* fan & PSU1 & PSU2 */ + 0x32, /* FAN5 LED */ + 0x33, /* FAN1-4 LED */ +}; + + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_GREEN_FLASHING, + LED_MODE_AMBER_FLASHING, + LED_MODE_RED_FLASHING, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + int type_mask; + enum led_light_mode mode; + int mode_mask; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_RED, LED_MODE_PSU1_RED_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK}, + +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_RED, LED_MODE_PSU2_RED_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK}, + +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_GREEN, LED_MODE_SYS_GREEN_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_AMBER, LED_MODE_SYS_AMBER_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_RED, LED_MODE_SYS_RED_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_AMBER_FLASHING, LED_MODE_SYS_AMBER_FLASHING_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_OFF, LED_MODE_SYS_OFF_MASK}, + +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_RED, LED_MODE_FAN_RED_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK}, + +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +}; + +struct fanx_info_s { + u8 cname; /* device name */ + enum led_type type; + u8 reg_id; /* map to led_reg & reg_val */ +}; + +static struct fanx_info_s fanx_info[] = { + {'1', LED_TYPE_FAN1, 3}, + {'2', LED_TYPE_FAN2, 3}, + {'3', LED_TYPE_FAN3, 3}, + {'4', LED_TYPE_FAN4, 3}, + {'5', LED_TYPE_FAN5, 2}, +}; + + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + break; + } + + return reg_val; +} + +static void cs5435_54p_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting cs5435_54p_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + u8 status; + cig_cpld_read_register(led_reg[i], &status); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void cs5435_54p_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + u8 reg_val; + mutex_lock(&ledctl->update_lock); + + cig_cpld_read_register(reg, ®_val); + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + + cig_cpld_write_register(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void cs5435_54p_led_fanx_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (led_cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + + cs5435_54p_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1); + return; + } + } +} + + +static enum led_brightness cs5435_54p_led_fanx_get(struct led_classdev *cdev) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + cs5435_54p_led_update(); + return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]); + } + } + + return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[5]); +} + + +static void cs5435_54p_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs5435_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness cs5435_54p_led_psu1_get(struct led_classdev *cdev) +{ + cs5435_54p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void cs5435_54p_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs5435_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness cs5435_54p_led_psu2_get(struct led_classdev *cdev) +{ + cs5435_54p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static void cs5435_54p_led_sys_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs5435_54p_led_set(led_cdev, led_light_mode,led_reg[0], LED_TYPE_SYS); +} + +static enum led_brightness cs5435_54p_led_sys_get(struct led_classdev *cdev) +{ + cs5435_54p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_SYS, ledctl->reg_val[0]); +} + + +static enum led_brightness cs5435_54p_led_fan_get(struct led_classdev *cdev) +{ + cs5435_54p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[1]); +} + +static void cs5435_54p_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs5435_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_FAN); +} + + +static struct led_classdev cs5435_54p_leds[] = { + [LED_TYPE_SYS] = { + .name = "cs5435_54p_led::sys", + .default_trigger = "unused", + .brightness_set = cs5435_54p_led_sys_set, + .brightness_get = cs5435_54p_led_sys_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "cs5435_54p_led::fan", + .default_trigger = "unused", + .brightness_set = cs5435_54p_led_fan_set, + .brightness_get = cs5435_54p_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + + [LED_TYPE_PSU1] = { + .name = "cs5435_54p_led::psu1", + .default_trigger = "unused", + .brightness_set = cs5435_54p_led_psu1_set, + .brightness_get = cs5435_54p_led_psu1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "cs5435_54p_led::psu2", + .default_trigger = "unused", + .brightness_set = cs5435_54p_led_psu2_set, + .brightness_get = cs5435_54p_led_psu2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + + [LED_TYPE_FAN1] = { + .name = "cs5435_54p_led::fan1", + .default_trigger = "unused", + .brightness_set = cs5435_54p_led_fanx_set, + .brightness_get = cs5435_54p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN2] = { + .name = "cs5435_54p_led::fan2", + .default_trigger = "unused", + .brightness_set = cs5435_54p_led_fanx_set, + .brightness_get = cs5435_54p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN3] = { + .name = "cs5435_54p_led::fan3", + .default_trigger = "unused", + .brightness_set = cs5435_54p_led_fanx_set, + .brightness_get = cs5435_54p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN4] = { + .name = "cs5435_54p_led::fan4", + .default_trigger = "unused", + .brightness_set = cs5435_54p_led_fanx_set, + .brightness_get = cs5435_54p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN5] = { + .name = "cs5435_54p_led::fan5", + .default_trigger = "unused", + .brightness_set = cs5435_54p_led_fanx_set, + .brightness_get = cs5435_54p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + } +}; + +static int cs5435_54p_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(cs5435_54p_leds); i++) { + led_classdev_suspend(&cs5435_54p_leds[i]); + } + + return 0; +} + +static int cs5435_54p_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(cs5435_54p_leds); i++) { + led_classdev_resume(&cs5435_54p_leds[i]); + } + + return 0; +} + +static int cs5435_54p_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(cs5435_54p_leds); i++) { + ret = led_classdev_register(&pdev->dev, &cs5435_54p_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(cs5435_54p_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&cs5435_54p_leds[i]); + } + } + + return ret; +} + +static int cs5435_54p_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(cs5435_54p_leds); i++) { + led_classdev_unregister(&cs5435_54p_leds[i]); + } + + return 0; +} + +static struct platform_driver cs5435_54p_led_driver = { + .probe = cs5435_54p_led_probe, + .remove = cs5435_54p_led_remove, + .suspend = cs5435_54p_led_suspend, + .resume = cs5435_54p_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int cs5435_54p_led_default(void) +{ + cig_cpld_write_register(0x30, 0x40);// system green led solid on +} + +static int __init cs5435_54p_led_init(void) +{ + int ret; + + ret = platform_driver_register(&cs5435_54p_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct cs5435_54p_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&cs5435_54p_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&cs5435_54p_led_driver); + kfree(ledctl); + goto exit; + } + + cs5435_54p_led_default(); + +exit: + return ret; +} + +static void __exit cs5435_54p_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&cs5435_54p_led_driver); + kfree(ledctl); +} + +module_init(cs5435_54p_led_init); +module_exit(cs5435_54p_led_exit); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs5435_54p_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-psu.c b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-psu.c new file mode 100644 index 000000000000..5a7942653fc3 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-psu.c @@ -0,0 +1,946 @@ +/* + * A hwmon driver for the CIG cs5435-54P Power Module + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-algo-lpc.h" + + + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Address scanned */ +static const unsigned short normal_i2c[] = {I2C_CLIENT_END }; + +/* This is additional data */ +struct cs5435_54p_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; /* In jiffies */ + + /* Registers value */ + u8 vout_mode; + u16 v_in; + u16 v_out; + u16 i_in; + u16 i_out; + u16 p_in; + u16 p_out; + u16 temp_input[3]; + u8 temp_fault; + u8 fan_fault; + u16 fan_duty_cycle[2]; + u16 fan_speed[2]; + u8 mfr_id[8]; + u8 mfr_model[20]; + u8 mfr_serial[20]; + u8 psu_is_present; + u8 psu_is_good; + struct i2c_client *client; + struct bin_attribute *bin; /* eeprom data */ +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count); +static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_fan_fault(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_fan_warning(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_temp_fault(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_temp_warning(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_vout_data(struct device *dev, struct device_attribute *dev_attr, char *buf); +static int cs5435_54p_psu_read_byte(struct i2c_client *client, u8 reg); +static int cs5435_54p_psu_read_word(struct i2c_client *client, u8 reg); +static int cs5435_54p_psu_write_word(struct i2c_client *client, u8 reg, u16 value); +static int cs5435_54p_psu_read_block(struct i2c_client *client, u8 command, u8 *data, int data_len); +static struct cs5435_54p_psu_data *cs5435_54p_psu_update_device(struct device *dev); +static ssize_t for_ascii(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf); + +enum cs5435_54p_psu_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_TEMP2_INPUT, + PSU_TEMP3_INPUT, + PSU_TEMP_FAULT, + PSU_TEMP_WARN, + PSU_FAN1_FAULT, + PSU_FAN1_WARN, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_SERIAL, + PSU_PRESENT, + PSU_P_GOOD, +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + + bool is_negative = valid_data >> (valid_bit - 1); + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct i2c_client *client = to_i2c_client(dev); + struct cs5435_54p_psu_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + if (data->valid != 1) + { + return -ENODEV; + } + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cs5435_54p_psu_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + if (data->valid != 1) + { + return -ENODEV; + } + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_TEMP2_INPUT: + value = data->temp_input[1]; + break; + case PSU_TEMP3_INPUT: + value = data->temp_input[2]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_fan_fault(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev); + + if (data->valid != 1) + { + return -ENODEV; + } + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t for_fan_warning(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev); + + if (data->valid != 1) + { + return -ENODEV; + } + + u8 shift = (attr->index == PSU_FAN1_WARN) ? 5 : 4; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t for_temp_fault(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev); + + if (data->valid != 1) + { + return -ENODEV; + } + + + + return sprintf(buf, "%d\n", data->temp_fault >> 7); +} + +static ssize_t for_temp_warning(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev); + if (data->valid != 1) + { + return -ENODEV; + } + + + return sprintf(buf, "%d\n", data->temp_fault >> 6); +} +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + if (data->valid != 1) + { + return -ENODEV; + } + + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", ((mantissa * multiplier) >> (-exponent))); +} + +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev); + u8 *ptr = NULL; + + if (data->valid != 1) + { + return -ENODEV; + } + + switch (attr->index) { + case PSU_MFR_ID: + ptr = data->mfr_id + 1; + break; + case PSU_MFR_MODEL: + ptr = data->mfr_model + 1; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial + 1; + break; + default: + return 0; + } + return sprintf(buf, "%s\n", ptr); +} + + +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs5435_54p_psu_data *data = cs5435_54p_psu_update_device(dev); + u8 *ptr = NULL; + + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = data->psu_is_present; + } + else { /* PSU_POWER_GOOD */ + if (!data->valid) { + return -ENODEV; + } + + status = data->psu_is_good; + } + + return sprintf(buf, "%d\n", status); +} + + +static int cs5435_54p_psu_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cs5435_54p_psu_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cs5435_54p_psu_write_word(struct i2c_client *client, u8 reg, \ + u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags |= I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, reg, + I2C_SMBUS_WORD_DATA, &data); + +} + +static int cs5435_54p_psu_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, + data); + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; +abort: + return result; + +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + + + +#define EEPROM_NAME "psu_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ + +/* Platform dependent --- */ +static ssize_t psu_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ + int status, retry = 3; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(100); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; + +} + + +static ssize_t psu_page_write(struct i2c_client *client,const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + + + while (count) { + ssize_t status; + + status = psu_eeprom_write(client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + + return retval; +} + + + +static ssize_t psu_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct cs5435_54p_psu_data *data; + ssize_t retval = 0; + struct i2c_client *client; + + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + client = to_i2c_client(container_of(kobj, struct device, kobj)); + + mutex_lock(&data->update_lock); + retval = psu_page_write(client, buf, off, count); + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t psu_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int status, retry = 3; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(100); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + +abort: + return status; +} + + + +static ssize_t psu_page_read(struct i2c_client *client,char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + printk("Count = 0, return"); + return count; + } + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + + + while (count) { + ssize_t status; + + status = psu_eeprom_read(client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + + return retval; + +} + + +static ssize_t psu_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct cs5435_54p_psu_data *data; + struct i2c_client *client; + ssize_t retval = 0; + + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + client = to_i2c_client(container_of(kobj, struct device, kobj)); + mutex_lock(&data->update_lock); + retval = psu_page_read(client, buf, off, count); + mutex_unlock(&data->update_lock); + + return retval; +} + + + +static int psu_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = psu_bin_read; + eeprom->write = psu_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + + +static int psu_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + + +static int psu_i2c_check_functionality(struct i2c_client *client) +{ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK); +} + + + +static int psu_eeprom_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + int status; + + struct cs5435_54p_psu_data *data; + + if (!psu_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + data->bin = kzalloc(sizeof(struct bin_attribute), GFP_KERNEL); + if (!data->bin) { + status = -ENOMEM; + goto eeprom_bin_error; + } + + /* init eeprom */ + status = psu_sysfs_eeprom_init(&client->dev.kobj, data->bin); + if (status) { + status = -ENOMEM; + goto sys_init_error; + } + + dev_info(&client->dev, "psu eeprom '%s'\n", client->name); + + return 0; + + sys_init_error: + kfree(data->bin); + + eeprom_bin_error: + kfree(data); + + exit: + return status; +} + + + + +static struct cs5435_54p_psu_data *cs5435_54p_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cs5435_54p_psu_data *data = i2c_get_clientdata(client); + + + mutex_lock(&data->update_lock); + + + if (time_after(jiffies, data->last_updated)) { + int i, status; + u8 command; + struct reg_data_byte regs_byte[] = { + {0x20, &data->vout_mode}, + {0x81, &data->fan_fault}, + {0x7d, &data->temp_fault}, + }; + struct reg_data_word regs_word[] = { + {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x90, &(data->fan_speed[0])}, + }; + data->valid = 1; + + dev_dbg(&client->dev, "start data update\n"); + + /* one milliseconds from now */ + data->last_updated = jiffies + HZ / 1000; + + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cs5435_54p_psu_read_byte(client, + regs_byte[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + data->valid = 0; + } else { + *(regs_byte[i].value) = status; + } + } + + for (i = 0; i < ARRAY_SIZE(regs_word); i++) + { + status = cs5435_54p_psu_read_word(client,regs_word[i].reg); + if (status < 0) + { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + data->valid = 0; + } + else + { + *(regs_word[i].value) = status; + } + } + + command = 0x99; /* PSU mfr_id */ + status = cs5435_54p_psu_read_block(client, command, + data->mfr_id, ARRAY_SIZE(data->mfr_id) - 1); + data->mfr_id[ARRAY_SIZE(data->mfr_id) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + memset(data->mfr_id, 0, sizeof(data->mfr_id)); + data->valid = 0; + } + + command = 0x9a; /* PSU mfr_model */ + status = cs5435_54p_psu_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + memset(data->mfr_model, 0, sizeof(data->mfr_id)); + data->valid = 0; + } + + command = 0x9e; /* PSU mfr_serial */ + status = cs5435_54p_psu_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + memset(data->mfr_serial, 0, sizeof(data->mfr_id)); + data->valid = 0; + } + + data->psu_is_present = strlen(data->mfr_id) > 1 ? 1:0; + if(data->psu_is_present) + { + data->psu_is_good = ((data->fan_fault) || (data->temp_fault))? 0:1; + } + else + { + data->valid = 0; + data->psu_is_good = 0; + } + } + + mutex_unlock(&data->update_lock); + + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp2_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp3_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP3_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, for_temp_fault, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_temp_warning, S_IRUGO, for_temp_warning, NULL, PSU_TEMP_WARN); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, for_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_warning, S_IRUGO, for_fan_warning, NULL, PSU_FAN1_WARN); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, for_linear_data, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, for_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, for_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, for_status, NULL, PSU_P_GOOD); + + + +static struct attribute *cs5435_54p_psu_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_temp2_input.dev_attr.attr, + &sensor_dev_attr_psu_temp3_input.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_temp_warning.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_warning.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static const struct attribute_group cs5435_54p_psu_group = { + .attrs = cs5435_54p_psu_attributes, +}; + + +static int psu_register_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int status; + + + struct cs5435_54p_psu_data *data; + + if (!psu_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cs5435_54p_psu_group); + if (status) + goto exit_sysfs_create_group; + + cs5435_54p_sysfs_add_client(client); + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_hwmon_device_register; + } + + /* init eeprom */ + + return 0; + + exit_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &cs5435_54p_psu_group); + exit_sysfs_create_group: + kfree(data); + exit: + return status; + +} + + +static int cs5435_54p_psu_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int status; + + if((client->addr == 0x52) ||(client->addr == 0x53)) + { + status = psu_eeprom_probe(client, id); + } + else if((client->addr == 0x5a) ||(client->addr == 0x5b)) + { + status = psu_register_probe(client, id); + } + return status; +} + +static int cs5435_54p_psu_remove(struct i2c_client *client) +{ + cs5435_54p_sysfs_remove_client(client); + + if((client->addr == 0x52) ||(client->addr == 0x53)) + { + struct cs5435_54p_psu_data *data; + data = i2c_get_clientdata(client); + psu_sysfs_eeprom_cleanup(&client->dev.kobj,data->bin); + kfree(data); + } + else if((client->addr == 0x5a) ||(client->addr == 0x5b)) + { + struct cs5435_54p_psu_data *data; + data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cs5435_54p_psu_group); + kfree(data); + } + + return 0; +} + +enum psu_index +{ + cs5435_54p_psu1, + cs5435_54p_psu2 +}; + +static const struct i2c_device_id cs5435_54p_psu_id[] = { + { "cs5435_54p_psu1", cs5435_54p_psu1 }, + { "cs5435_54p_psu2", cs5435_54p_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs5435_54p_psu_id); + +static struct i2c_driver cs5435_54p_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cs5435_54p_psu", + }, + .probe = cs5435_54p_psu_probe, + .remove = cs5435_54p_psu_remove, + .id_table = cs5435_54p_psu_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(cs5435_54p_psu_driver); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs5435_54p_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-sfp.c b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-sfp.c new file mode 100644 index 000000000000..3bdb3d2de791 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-sfp.c @@ -0,0 +1,1713 @@ +/* + * A hwmon driver for the CIG cs5435-54P SFP Module + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-algo-lpc.h" + +#define DRIVER_NAME "cs5435_54p_sfp" /* Platform dependent */ + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) +#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 +#define QSFP_RESET_ADDR 0x1b +#define QSFP_INTER_ADDR 0x1a +#define QSFP_LPMODE_ADDR 0x1c + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +extern int cig_cpld_read_register(u8 reg_off, u8 *val); +extern int cig_cpld_write_register(u8 reg_off, u8 val); + +static ssize_t qsfp_reset_read(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_reset_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_inter_read(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_lpmode_read(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_lpmode_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL, + QSFPRESET, + QSFPINT, + QSFPLPMODE +}; + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static SENSOR_DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, qsfp_reset_read, qsfp_reset_write, QSFPRESET); +static SENSOR_DEVICE_ATTR(sfp_inter, S_IRUGO, qsfp_inter_read, NULL, QSFPINT); +static SENSOR_DEVICE_ATTR(sfp_lpmode, S_IWUSR | S_IRUGO, qsfp_lpmode_read, qsfp_lpmode_write, QSFPLPMODE); +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + &sensor_dev_attr_sfp_reset.dev_attr.attr, + &sensor_dev_attr_sfp_inter.dev_attr.attr, + &sensor_dev_attr_sfp_lpmode.dev_attr.attr, + NULL +}; + +/* SFP msa attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); +static struct attribute *sfp_msa_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + NULL +}; + +/* SFP ddm attributes for sysfs */ +static struct attribute *sfp_ddm_attributes[] = { + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +cs5435_54p_sfp1, cs5435_54p_sfp2, cs5435_54p_sfp3, cs5435_54p_sfp4, +cs5435_54p_sfp5, cs5435_54p_sfp6, cs5435_54p_sfp7, cs5435_54p_sfp8, +cs5435_54p_sfp9, cs5435_54p_sfp10, cs5435_54p_sfp11, cs5435_54p_sfp12, +cs5435_54p_sfp13, cs5435_54p_sfp14, cs5435_54p_sfp15, cs5435_54p_sfp16, +cs5435_54p_sfp17, cs5435_54p_sfp18, cs5435_54p_sfp19, cs5435_54p_sfp20, +cs5435_54p_sfp21, cs5435_54p_sfp22, cs5435_54p_sfp23, cs5435_54p_sfp24, +cs5435_54p_sfp25, cs5435_54p_sfp26, cs5435_54p_sfp27, cs5435_54p_sfp28, +cs5435_54p_sfp29, cs5435_54p_sfp30, cs5435_54p_sfp31, cs5435_54p_sfp32, +cs5435_54p_sfp33, cs5435_54p_sfp34, cs5435_54p_sfp35, cs5435_54p_sfp36, +cs5435_54p_sfp37, cs5435_54p_sfp38, cs5435_54p_sfp39, cs5435_54p_sfp40, +cs5435_54p_sfp41, cs5435_54p_sfp42, cs5435_54p_sfp43, cs5435_54p_sfp44, +cs5435_54p_sfp45, cs5435_54p_sfp46, cs5435_54p_sfp47, cs5435_54p_sfp48, +cs5435_54p_sfp49, cs5435_54p_sfp50, cs5435_54p_sfp51, cs5435_54p_sfp52, +cs5435_54p_sfp53, cs5435_54p_sfp54, cs5435_54p_sfp55, cs5435_54p_sfp56 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { +I2C_DEV_ID(cs5435_54p_sfp1), +I2C_DEV_ID(cs5435_54p_sfp2), +I2C_DEV_ID(cs5435_54p_sfp3), +I2C_DEV_ID(cs5435_54p_sfp4), +I2C_DEV_ID(cs5435_54p_sfp5), +I2C_DEV_ID(cs5435_54p_sfp6), +I2C_DEV_ID(cs5435_54p_sfp7), +I2C_DEV_ID(cs5435_54p_sfp8), +I2C_DEV_ID(cs5435_54p_sfp9), +I2C_DEV_ID(cs5435_54p_sfp10), +I2C_DEV_ID(cs5435_54p_sfp11), +I2C_DEV_ID(cs5435_54p_sfp12), +I2C_DEV_ID(cs5435_54p_sfp13), +I2C_DEV_ID(cs5435_54p_sfp14), +I2C_DEV_ID(cs5435_54p_sfp15), +I2C_DEV_ID(cs5435_54p_sfp16), +I2C_DEV_ID(cs5435_54p_sfp17), +I2C_DEV_ID(cs5435_54p_sfp18), +I2C_DEV_ID(cs5435_54p_sfp19), +I2C_DEV_ID(cs5435_54p_sfp20), +I2C_DEV_ID(cs5435_54p_sfp21), +I2C_DEV_ID(cs5435_54p_sfp22), +I2C_DEV_ID(cs5435_54p_sfp23), +I2C_DEV_ID(cs5435_54p_sfp24), +I2C_DEV_ID(cs5435_54p_sfp25), +I2C_DEV_ID(cs5435_54p_sfp26), +I2C_DEV_ID(cs5435_54p_sfp27), +I2C_DEV_ID(cs5435_54p_sfp28), +I2C_DEV_ID(cs5435_54p_sfp29), +I2C_DEV_ID(cs5435_54p_sfp30), +I2C_DEV_ID(cs5435_54p_sfp31), +I2C_DEV_ID(cs5435_54p_sfp32), +I2C_DEV_ID(cs5435_54p_sfp33), +I2C_DEV_ID(cs5435_54p_sfp34), +I2C_DEV_ID(cs5435_54p_sfp35), +I2C_DEV_ID(cs5435_54p_sfp36), +I2C_DEV_ID(cs5435_54p_sfp37), +I2C_DEV_ID(cs5435_54p_sfp38), +I2C_DEV_ID(cs5435_54p_sfp39), +I2C_DEV_ID(cs5435_54p_sfp40), +I2C_DEV_ID(cs5435_54p_sfp41), +I2C_DEV_ID(cs5435_54p_sfp42), +I2C_DEV_ID(cs5435_54p_sfp43), +I2C_DEV_ID(cs5435_54p_sfp44), +I2C_DEV_ID(cs5435_54p_sfp45), +I2C_DEV_ID(cs5435_54p_sfp46), +I2C_DEV_ID(cs5435_54p_sfp47), +I2C_DEV_ID(cs5435_54p_sfp48), +I2C_DEV_ID(cs5435_54p_sfp49), +I2C_DEV_ID(cs5435_54p_sfp50), +I2C_DEV_ID(cs5435_54p_sfp51), +I2C_DEV_ID(cs5435_54p_sfp52), +I2C_DEV_ID(cs5435_54p_sfp53), +I2C_DEV_ID(cs5435_54p_sfp54), +I2C_DEV_ID(cs5435_54p_sfp55), +I2C_DEV_ID(cs5435_54p_sfp56), +{ /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[6]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss + 3 => device id + 4 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 5 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + + + +static int cig_cpld_write_sfp_register(u8 sfp_reg_addr, u8 sfp_write_reg_data) +{ + u8 sfp_read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, sfp_reg_addr << 1); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_TX, sfp_write_reg_data); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + do{ + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &sfp_read_status); + udelay(60); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(sfp_read_status != 0x02); + + if(wait_time_out == 0) + return -1; + + return 1; +} + + +static int cig_cpld_read_sfp_register(u8 sfp_reg_addr, u8 *sfp_read_reg_data) +{ + u8 sfp_read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, sfp_reg_addr << 1 | 1); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + do{ + udelay(60); + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &sfp_read_status); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(sfp_read_status != 0x01); + + cig_cpld_read_register(ADDR_REG_SFP_STATUS_RX,sfp_read_reg_data); + + if(wait_time_out == 0) + return -1; + + return 1; +} + + + + + + +/* Platform dependent +++ */ +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + int i = 0, j = 0, status = -1; + unsigned char cpld_reg_data = 0,cpld_reg_addr = 0; + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + data->present = 0; + + udelay(6000); + + /* Read present status of port 1~48(SFP port) */ + for (i = 0; i < 6; i++) { + cpld_reg_addr = 1 + i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->present |= (u64)cpld_reg_data << (i*8); + + DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); + } + + /* Read present status of port 49-56(QSFP port) */ + cpld_reg_addr = 25; + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + else { + data->present |= (u64)cpld_reg_data << 48; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0, j = 0; + int status = -1; + unsigned char cpld_reg_data = 0,cpld_reg_addr = 0; + + if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { + return data; + } + + DEBUG_PRINT("Starting cs5435_54p sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->msa->valid = 0; + memset(data->msa->status, 0, sizeof(data->msa->status)); + + udelay(6000); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 6; i++) { + cpld_reg_addr = 13+i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->msa->status[0] |= (u64)cpld_reg_data << (i * 8); + + DEBUG_PRINT("tx rx status[0] = 0x%lx\r\n", data->msa->status[0]); + } + + + for (i = 0; i < 6; i++) { + cpld_reg_addr = 19+i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->msa->status[1] |= (u64)cpld_reg_data << (i * 8); + + DEBUG_PRINT("tx rx status[1] = 0x%lx\r\n", data->msa->status[1]); + } + + for (i = 0; i < 6; i++) { + cpld_reg_addr = 7+i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->msa->status[2] |= (u64)cpld_reg_data << (i * 8); + + DEBUG_PRINT("tx rx status[2] = 0x%lx\r\n", data->msa->status[2]); + } + + data->msa->valid = 1; + data->msa->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + unsigned char cpld_reg_data = 0,cpld_reg_addr = 0,cpld_reg_bit = 0,cpld_reg_val = 0; + long disable; + int error; + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_set_tx_disable(dev, da, buf, count); + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + + if(data->port <= 48) { + cpld_reg_addr = 19 + data->port / 8; + cpld_reg_bit = 1 << ((data->port) % 8); + } + + /* Read current status */ + error = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + + /* Update tx_disable status */ + if (disable) { + data->msa->status[1] |= BIT_INDEX(data->port); + cpld_reg_data |= cpld_reg_bit; + } + else { + data->msa->status[1] &= ~ BIT_INDEX(data->port); + cpld_reg_data &= ~cpld_reg_bit; + } + + error = cig_cpld_write_sfp_register(cpld_reg_addr,cpld_reg_data); + + mutex_unlock(&data->update_lock); + return count; +} +/* Platform dependent --- */ + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = sfp_update_present(client); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + return !(data->present & BIT_INDEX(data->port)); /* Platform dependent */ +} + +/* Platform dependent +++ */ +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if (PRESENT_ALL == attr->index) { + int i; + u8 values[7] = {0}; + struct sfp_port_data *data = sfp_update_present(client); + + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = ~(u8)(data->present >> (i * 8)); + } + + /* Return values 1 -> 56 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6]); + } + else { + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + /* PRESENT */ + return sprintf(buf, "%d\n", present); + } +} +/* Platform dependent --- */ + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = buf; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + if (!present) { + /* port is not present */ + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + DEBUG_PRINT(""); + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + DEBUG_PRINT("Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + DEBUG_PRINT(""); + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + DEBUG_PRINT(""); + goto exit; + } + } + msleep(200); + DEBUG_PRINT(""); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + DEBUG_PRINT(""); + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + DEBUG_PRINT(""); + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + +exit: + DEBUG_PRINT(""); + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t qsfp_inter_read(struct device *dev, struct device_attribute *da, char *buf) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_INTER_ADDR, &cpld_reg_data); + index = data->port - 48; + index = 1 << index; + val = (cpld_reg_data & index) > 0 ? 1 : 0; + + printk("inter read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t qsfp_reset_read(struct device *dev, struct device_attribute *da, char *buf) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_RESET_ADDR, &cpld_reg_data); + index = data->port - 48; + index = 1 << index; + val = (cpld_reg_data & index) > 0 ? 1 : 0; + + printk("reset read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_reset_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + long usrdata; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + ret = kstrtol(buf, 10, &usrdata); + if (ret) { + return ret; + } + + usrdata = usrdata > 0 ? 1 : 0; + index = data->port - 48; + + DEBUG_PRINT("usrdata = %u, index = %hhu\n", usrdata, index); + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_RESET_ADDR, &cpld_reg_data); + if (ret == 1) + { + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + cpld_reg_data &= ~(1 << index); + cpld_reg_data |= usrdata << index; + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + ret = cig_cpld_write_sfp_register(QSFP_RESET_ADDR, cpld_reg_data); + if (1 != ret) + { + DEBUG_PRINT("write failed\n"); + } + } + else + { + DEBUG_PRINT("read failed\n"); + } + + mutex_unlock(&data->update_lock); + + if (ret != 1) + return -1; + + return count; +} + + + + +static ssize_t qsfp_lpmode_read(struct device *dev, struct device_attribute *da, char *buf) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_LPMODE_ADDR, &cpld_reg_data); + index = data->port - 48; + index = 1 << index; + val = (cpld_reg_data & index) > 0 ? 1 : 0; + + printk("lpmode read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_lpmode_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + long usrdata; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + ret = kstrtol(buf, 10, &usrdata); + if (ret) { + return ret; + } + + usrdata = usrdata > 0 ? 1 : 0; + index = data->port - 48; + + DEBUG_PRINT("usrdata = %u, index = %hhu\n", usrdata, index); + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_LPMODE_ADDR, &cpld_reg_data); + if (ret == 1) + { + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + cpld_reg_data &= ~(1 << index); + cpld_reg_data |= usrdata << index; + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + ret = cig_cpld_write_sfp_register(QSFP_LPMODE_ADDR, cpld_reg_data); + if (1 != ret) + { + DEBUG_PRINT("write failed\n"); + } + } + else + { + DEBUG_PRINT("read failed\n"); + } + + mutex_unlock(&data->update_lock); + + if (ret != 1) + return -1; + + return count; +} + + + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + int present; + u8 val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT(""); + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + DEBUG_PRINT(""); + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + DEBUG_PRINT(""); + data = qsfp_update_tx_rx_status(dev); + DEBUG_PRINT(""); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + DEBUG_PRINT(""); + switch (attr->index) { + case TX_FAULT: + val = !!(data->qsfp->status[2] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + case TX_DISABLE: + val = data->qsfp->status[1] & 0xF; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + case RX_LOS: + val = !!(data->qsfp->status[0] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); + break; + default: + break; + } + + DEBUG_PRINT(""); + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (!status) { + /* port is not present */ + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + mutex_lock(&data->update_lock); + + if (attr->index == TX_DISABLE) { + data->qsfp->status[1] = disable & 0xF; + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (status == 0) { + /* port is not present */ + return -ENODEV; + } + + status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (unlikely(status < 0)) { + return status; + } + + return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK)); +} + +/* Platform dependent +++ */ +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("driver type = (%d)", data->driver_type); + if (data->driver_type == DRIVER_TYPE_QSFP) { + DEBUG_PRINT(""); + return qsfp_show_tx_rx_status(dev, da, buf); + } + + DEBUG_PRINT(""); + data = sfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + if(attr->index == RX_LOS_ALL) { + int i = 0; + u8 values[6] = {0}; + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = (u8)(data->msa->status[2] >> (i * 8)); + } + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + case RX_LOS: + index = 2; + break; + default: + break; + } + + val = !!(data->msa->status[index] & BIT_INDEX(data->port)); + return sprintf(buf, "%d\n", val); +} +/* Platform dependent --- */ +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, command, *data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return 1; +#endif + + +} + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return status; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + status = 1; + +abort: + return status; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + cs5435_54p_sysfs_add_client(client); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + + /* Bring QSFPs out of reset */ + //cig_lpc_write(0x62, 0x15, 0x3F); + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +/* Platform dependent +++ */ +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if (dev_id->driver_data >= cs5435_54p_sfp1 && dev_id->driver_data <= cs5435_54p_sfp48) { + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_SFP_MSA; + return sfp_msa_probe(client, dev_id, &data->msa); + } + else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_SFP_DDM; + return sfp_ddm_probe(client, dev_id, &data->ddm); + } + } + else { /* cs5435_54p_sfp49 ~ cs5435_54p_sfp56 */ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); + } + } + + return -ENODEV; +} +/* Platform dependent --- */ + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + cs5435_54p_sysfs_remove_client(client); + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver cs5435_54p_sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(cs5435_54p_sfp_driver); + + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs5435_54p_sfp driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-sysfs.c b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-sysfs.c new file mode 100644 index 000000000000..0ba8836cf33a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/modules/x86-64-cig-cs5435-54p-sysfs.c @@ -0,0 +1,335 @@ +/* + * A hwmon driver for the CIG cs5435-54P sysfs Module + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i2c-algo-lpc.h" + + +static LIST_HEAD(sysfs_client_list); +static struct mutex list_lock; + +struct sysfs_client_node { + struct i2c_client *client; + struct list_head list; +}; + +#define DEVICE_NAME "cigfs" +static int dev_major; +static struct class *dev_class; +static struct cdev *dev_cdev; +static struct device *dev_device; +static struct class *psu_class; +static struct class *sfp_class; + + +void cs5435_54p_sysfs_add_client(struct i2c_client *client) +{ + struct sysfs_client_node *node = kzalloc(sizeof(struct sysfs_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate sysfs_client_node (0x%x)\n", client->addr); + return; + } + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &sysfs_client_list); + mutex_unlock(&list_lock); +} + +EXPORT_SYMBOL(cs5435_54p_sysfs_add_client); + +void cs5435_54p_sysfs_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct sysfs_client_node *sysfs_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &sysfs_client_list) + { + sysfs_node = list_entry(list_node, struct sysfs_client_node, list); + if (IS_ERR(sysfs_node)) + { + break; + } + if (sysfs_node->client == client) { + found = 1; + break; + } + } + if (found) { + list_del(list_node); + kfree(sysfs_node); + } + + mutex_unlock(&list_lock); +} + +EXPORT_SYMBOL(cs5435_54p_sysfs_remove_client); + +struct class * cs5435_54p_sysfs_create_symclass(char *cls_name) +{ + int rc = 0; + struct class *my_class; +/**************************************************************************************/ + my_class = class_create(THIS_MODULE,cls_name); + if (IS_ERR(my_class)) { + pr_err("failed to create my class\n"); + } + return my_class; + +/**************************************************************************************/ +} + +void cs5435_54p_sysfs_delete_symclass(struct class *my_class) +{ +/**************************************************************************************/ + + if (IS_ERR(my_class)) { + pr_err("Pointer is invaild\n"); + } + class_destroy(my_class); + +/**************************************************************************************/ +} + + + + + +int cs5435_54p_sysfs_create_symlink(struct class *my_class,char * driver_name,char *device_name) +{ + struct list_head *list_node = NULL; + struct sysfs_client_node *sysfs_node = NULL; + int ret = -EPERM; + int rc = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &sysfs_client_list) + { + sysfs_node = list_entry(list_node, struct sysfs_client_node, list); + if (!strcmp(sysfs_node->client->name,driver_name)) { + rc = sysfs_create_link(&my_class->p->subsys.kobj, &sysfs_node->client->dev.kobj,device_name); + if(rc) + { + pr_err("failed to create symlink %d\n",rc); + } + break; + } + } + mutex_unlock(&list_lock); + return ret; +} + + +int cs5435_54p_sysfs_delete_symlink(struct class *my_class,char * driver_name,char *device_name) +{ + struct list_head *list_node = NULL; + struct sysfs_client_node *sysfs_node = NULL; + int ret = -EPERM; + int rc = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &sysfs_client_list) + { + sysfs_node = list_entry(list_node, struct sysfs_client_node, list); + if (!strcmp(sysfs_node->client->name,driver_name)) { + sysfs_remove_link(&my_class->p->subsys.kobj,device_name); + break; + } + } + mutex_unlock(&list_lock); + return ret; +} + + +static int cs5435_54p_sysfs_open(struct inode *inode, struct file *file) +{ + return 0; +} + + + +static ssize_t cs5435_54p_sysfs_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) +{ + char str[10],name[18],port[8]; + int ret; + int i; + memset(str, 0, sizeof(str)); + ret = copy_from_user(str, buf, count); + if (ret) + { + printk(KERN_ERR "copy_from_user fail\n"); + return -EINVAL; + } + + if(!strncmp(str,"start",5)) + { + psu_class = cs5435_54p_sysfs_create_symclass("psu"); + cs5435_54p_sysfs_create_symlink(psu_class,"cs5435_54p_psu1","psu1"); + cs5435_54p_sysfs_create_symlink(psu_class,"cs5435_54p_psu2","psu2"); + sfp_class = cs5435_54p_sysfs_create_symclass("swps"); + for(i = 1; i <= 48;i++) + { + memset(name,0xff,sizeof(name)); + memset(port,0xff,sizeof(port)); + snprintf(name,sizeof(name),"cs5435_54p_sfp%d",i); + snprintf(port,sizeof(port),"port%d",i); + cs5435_54p_sysfs_create_symlink(sfp_class,name,port); + } + } + else if(!strncmp(str,"stop",4)) + { + cs5435_54p_sysfs_delete_symlink(psu_class,"cs5435_54p_psu1","psu1"); + cs5435_54p_sysfs_delete_symlink(psu_class,"cs5435_54p_psu2","psu2"); + cs5435_54p_sysfs_delete_symclass(psu_class); + + for(i = 1; i <= 48;i++) + { + memset(name,0xff,sizeof(name)); + memset(port,0xff,sizeof(port)); + snprintf(name,sizeof(name),"cs5435_54p_sfp%d",i); + snprintf(port,sizeof(port),"port%d",i); + cs5435_54p_sysfs_delete_symlink(sfp_class,name,port); + } + cs5435_54p_sysfs_delete_symclass(sfp_class); + } + return count; +} + + +static struct file_operations cs5435_54p_sysfs_fops = { + .owner = THIS_MODULE, + .open = cs5435_54p_sysfs_open, + .write = cs5435_54p_sysfs_write, +}; + + +static int __init cs5435_54p_sysfs_init(void) +{ + int result = 0; + int err = 0; + dev_t dev = MKDEV(dev_major, 0); + + if (dev_major) + result = register_chrdev_region(dev, 1, DEVICE_NAME); + else { + result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME); + dev_major = MAJOR(dev); + } + if (result < 0) + { + printk("unable to get major %d\n", dev_major); + err= -EINVAL; + } + printk("get major is %d\n", dev_major); + if (dev_major == 0) + dev_major = result; + + dev_cdev= kmalloc(sizeof(struct cdev), GFP_KERNEL); + if(IS_ERR(dev_cdev)) { + err= -ENOMEM; + } + + cdev_init(dev_cdev, &cs5435_54p_sysfs_fops); + dev_cdev->owner = THIS_MODULE; + dev_cdev->ops = &cs5435_54p_sysfs_fops; + err = cdev_add(dev_cdev, dev, 1); + if (err) + { + printk("error %d add fpga ", err); + goto err_malloc; + } + + dev_class = class_create(THIS_MODULE, DEVICE_NAME); + if (IS_ERR(dev_class)) + { + printk("Err:failed in creating class.\n"); + goto err_cdev_add; + } + + dev_device = device_create(dev_class, NULL, MKDEV(dev_major, 0), NULL, DEVICE_NAME); + if (IS_ERR(dev_device)) + { + printk("Err:failed in creating device.\n"); + goto err_class_crt; + } + + mutex_init(&list_lock); + + return err; + + err_class_crt: + cdev_del(dev_cdev); + err_cdev_add: + kfree(dev_cdev); + err_malloc: + unregister_chrdev_region(MKDEV(dev_major,0), 1); + + return err; + +} + +static void __exit cs5435_54p_sysfs_exit(void) +{ + cdev_del(dev_cdev); + printk("cdev_del ok\n"); + device_destroy(dev_class, MKDEV(dev_major, 0)); + + class_destroy(dev_class); + + if(dev_cdev != NULL) + kfree(dev_cdev); + + unregister_chrdev_region(MKDEV(dev_major, 0), 1); + printk("cs5435_54p_sysfs_exit...\r\n"); +} + + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs5435-54p-sysfs driver"); +MODULE_LICENSE("GPL"); + +module_init(cs5435_54p_sysfs_init); +module_exit(cs5435_54p_sysfs_exit); + + diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/service/cs5435-platform-init.service b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/service/cs5435-platform-init.service new file mode 100644 index 000000000000..b609a2be45c7 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/service/cs5435-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Cig CS5435-54P Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/cig_cs5435_util.py install +ExecStop=/usr/local/bin/cig_cs5435_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/service/cs5435-platform-misc.service b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/service/cs5435-platform-misc.service new file mode 100644 index 000000000000..852ab5689a70 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/service/cs5435-platform-misc.service @@ -0,0 +1,15 @@ +[Unit] +Description=Cig CS5435-54P Platform miscellaneous service +After=cs5435-platform-init.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/cig_cs5435_misc.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/setup.py b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/setup.py new file mode 100755 index 000000000000..1d4fa7f36452 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='cs5435-54p', + version='1.0.0', + description='Module to initialize Cig CS5435-54P platforms', + + packages=['cs5435-54p'], + package_dir={'cs5435-54p': 'cs5435-54p/classes'}, + ) diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/utils/cig_cs5435_misc.py b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/utils/cig_cs5435_misc.py new file mode 100755 index 000000000000..0a1a887642d6 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/utils/cig_cs5435_misc.py @@ -0,0 +1,574 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Cambridge, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import commands +import sys, getopt +import logging +import re +import time +import datetime +from collections import namedtuple +from threading import Thread + +DEBUG = False +i2c_prefix = '/sys/bus/i2c/devices/' +leds_prefix = '/sys/devices/platform/cs5435_54p_led/leds/' +fans_prefix = '/sys/devices/platform/cs5435_54p_fan/' +fansdir_prefix = fans_prefix + 'fan{}_direction' + +ageing_controlfile = '/etc/sonic/agcontrol' +AGFlag = 0 + + +platform_misc_log = '/var/log/platform_misc.log' +misclogger = logging.getLogger('platform_misc') +misclogger.setLevel(logging.INFO) +miscformatter = logging.Formatter('%(asctime)s-%(levelname)s-%(message)s') + +if not os.path.isfile(platform_misc_log): + try: + os.mknod(platform_misc_log) + except: + print 'Failed to creat platform_misc.log' + +fileHandler = logging.FileHandler(platform_misc_log) +fileHandler.setLevel(logging.INFO) +fileHandler.setFormatter(miscformatter) +misclogger.addHandler(fileHandler) + + +starttime = datetime.datetime.now() +IsGetlswt = 0 +coretemp_prefix = '/sys/class/hwmon/hwmon1/' +coretemp_ps = [] +psu1_p = '/sys/bus/i2c/devices/5-005a/psu_present' +psu2_p = '/sys/bus/i2c/devices/5-005b/psu_present' +psu1_d = '/sys/bus/i2c/devices/5-0052/psu_eeprom' +psu2_d = '/sys/bus/i2c/devices/5-0053/psu_eeprom' +psu1led_d = leds_prefix + 'cs5435_54p_led::psu1/brightness' +psu2led_d = leds_prefix + 'cs5435_54p_led::psu2/brightness' +cs5435_ledpath = {'fan':leds_prefix + 'cs5435_54p_led::fan/brightness', + 'fan1':leds_prefix + 'cs5435_54p_led::fan1/brightness', + 'fan2':leds_prefix + 'cs5435_54p_led::fan2/brightness', + 'fan3':leds_prefix + 'cs5435_54p_led::fan3/brightness', + 'fan4':leds_prefix + 'cs5435_54p_led::fan4/brightness', + 'fan5':leds_prefix + 'cs5435_54p_led::fan5/brightness', + 'psu1':leds_prefix + 'cs5435_54p_led::psu1/brightness', + 'psu2':leds_prefix + 'cs5435_54p_led::psu2/brightness', + 'sys':leds_prefix + 'cs5435_54p_led::sys/brightness'} + + +def system_read_filestr(node): + with open(node, 'r') as f: + try: + str = f.read() + except IOError as e: + misclogger.error('Failed to get node, str={}'.format(node)) + return "0" + return str + + +def system_bright_leds(dev, colour): + global AGFlag + + if AGFlag == 1: + return + + cmd = 'echo {} > {}'.format(colour, dev) + log_os_system(cmd, 1) + return + +''' +1: front in tail out +0: front out tail in +''' +def system_getpsu_direction(dev): + try: + with open(dev) as f: + f.seek(0x30) + str = f.read(2) + except IOError as e: + misclogger.error('Failed to get psu eep') + return 1 + if str == 'AA': ## front in tail out + return 1 + elif str == 'RA':## tail in front out + return 0 + else: + misclogger.error('Failed to get psu eep, str={}'.format(str)) + return -1 + + +def system_get_cputype(): + cmdretfd = os.popen("lscpu | grep 'Model name'") + retstring = cmdretfd.read() + endindex = retstring.find('@') - 1 + startindex = retstring[:endindex].rfind(' ') + 1 + cputype = retstring[startindex:endindex] + + return cputype + + +def system_init_coretemppath(): + global coretemp_ps + + cmdstr = "ls {} | grep 'input'".format(coretemp_prefix) + cmdretfd = os.popen(cmdstr) + + coretemppss = cmdretfd.read().splitlines() + if len(coretemppss) < 3: + cputype = system_get_cputype() + misclogger.error('Failed to init core temperature path.' + ' cpu type = {}, num thermal = {}'.format(cputype, len(coretemp_ps))) + return 1 + + for i in range(0,3): + coretemp_ps.append(coretemp_prefix + coretemppss[i]) + + print coretemp_ps + + return 0 + + +class cs5435_fanattr: + def __init__(self, name): + self.name = name + self.direction = 0 + self.direction_p = '' + self.rear = 0 + self.rear_p = '' + self.front = 0 + self.front_p = '' + self.fault = 0 + self.fault_p = '' + self.status = 0 + self.setpath() + self.updatedevice() + + return + + def setpath(self): + self.direction_p = fans_prefix + '{}_direction'.format(self.name) + self.rear_p = fans_prefix + '{}_rear_speed_rpm'.format(self.name) + self.front_p = fans_prefix + '{}_front_speed_rpm'.format(self.name) + self.fault_p = fans_prefix + '{}_fault'.format(self.name) + + return + + def updatedevice(self): + self.direction = int(system_read_filestr(self.direction_p)) + self.rear = int(system_read_filestr(self.rear_p)) + self.front = int(system_read_filestr(self.front_p)) + self.fault = int(system_read_filestr(self.fault_p)) + + return + + def checkspeedrpm(self, speedrpm): + frontrpmexp = speedrpm * 21000 / 100 + rearrpmexp = speedrpm * 19000 / 100 + deviationfront = abs(frontrpmexp - self.front) / float(frontrpmexp) + deviationrear = abs(rearrpmexp - self.rear) / float(rearrpmexp) + + if deviationfront < 0.3 and deviationrear < 0.3: + return 0 + else: + misclogger.error(':{} speed wrong. frontexp is {}, but rpm is {}.rearexp is {}, but rpm is {}'.format(self.name, frontrpmexp, self.front, rearrpmexp, self.rear)) + return 1 + + def checkstatus(self, speedrpm, totaldirct): + speedstatus = self.checkspeedrpm(speedrpm) + if self.direction != totaldirct: + self.status = 1 + misclogger.error(':{} direction = {}.fan direction is not ok.'.format(self.name, self.direction)) + elif speedstatus != 0: + self.status = 1 + elif self.fault != 0: + misclogger.error(':{} fault.'.format(self.name)) + self.status = 1 + else: + self.status = 0 + + if self.status == 1: + system_bright_leds(cs5435_ledpath[self.name], 3) + else: + system_bright_leds(cs5435_ledpath[self.name], 1) + + return self.status + +cs5435_fanattrnodes = [] + + +class cs5435_psuattr: + def __init__(self, name): + self.name = name + self.direction = 0 + self.direction_p = '' + self.present = 0 + self.present_p = '' + self.status = 0 + + self.setpath() + self.updatepresent() + self.updatedirection() + + return + + def setpath(self): + if self.name == 'psu1': + self.present_p = psu1_p + self.direction_p = psu1_d + if self.name == 'psu2': + self.present_p = psu2_p + self.direction_p = psu2_d + + return + + def updatepresent(self): + self.present = int(system_read_filestr(self.present_p)) + + return + + def updatedirection(self): + if self.present == 1: + self.direction = system_getpsu_direction(self.direction_p) + else: + self.direction = 2 + + return + + def checkstatus(self, totaldirct): + if self.present != 1: + self.status = 1 + misclogger.error(':{} not present.'.format(self.name)) + elif self.direction == 2: + self.status = 0 + misclogger.info(':{} direction need to be update.'.format(self.name)) + elif self.direction != totaldirct: + self.status = 1 + misclogger.info(':{} direction is wrong.'.format(self.name)) + else: + self.status = 0 + + if self.status == 1: + system_bright_leds(cs5435_ledpath[self.name], 3) + else: + system_bright_leds(cs5435_ledpath[self.name], 1) + + return self.status + +cs5435_psuattrnodes = [] + + + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"5-005a", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"5-005b", 0) + ret3, log = log_os_system("ls "+leds_prefix+"cs5435_54p_led*", 0) + return not(ret1 or ret2 or ret3) + + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + + +def system_get_coretemp(): + temp1 = system_read_filestr(coretemp_ps[0]).strip() + temp2 = system_read_filestr(coretemp_ps[1]).strip() + temp3 = system_read_filestr(coretemp_ps[2]).strip() + + return int(temp1), int(temp2), int(temp3) + +def system_get_boardtemp(): + for i in range(0,16): + temp1path = "/sys/bus/i2c/devices/5-004a/hwmon/hwmon%d/temp1_input" % i + if os.access(temp1path, os.F_OK): + break + for i in range(0,16): + temp2path = "/sys/bus/i2c/devices/5-004b/hwmon/hwmon%d/temp1_input" % i + if os.access(temp2path, os.F_OK): + break + temp1 = system_read_filestr(temp1path).strip() + temp2 = system_read_filestr(temp2path).strip() + + return int(temp1), int(temp2) + + +def system_get_lswtemp(): + global IsGetlswt + global starttime + if IsGetlswt == 0: + now = datetime.datetime.now() + misclogger.info("time wait.") + misclogger.info("start = {}, now = {}.".format(starttime, now)) + if (now - starttime).seconds > 150: + misclogger.info("time = ".format((now - starttime).seconds)) + IsGetlswt = 1 + + return 25 + +# chp = subprocess.Popen("docker ps --filter name=syncd", shell=True, stdout=subprocess.PIPE) +# if chp.poll() is None: +# misclogger.info("No subp.") +# chp.kill() +# +# return 25 + +# retstring = chp.stdout.read() +# chp.kill() +# if 'Up' not in retstring: +# misclogger.info("lsw not up.") +# +# return 25 + + status, output = log_os_system('npx_diag swc show temperature', 1) + if status: + misclogger.error('failed to show lsw temperature') + + return 25 + + output = output.strip() + if output.find("it 0, temperature ") > 0: + startindex = output.find('temperature') + len('temperature') + 1 + endindex = output[startindex:].find(" ") + endindex = startindex + endindex + temp = output[startindex:endindex] + b = temp.find('.') + if b > 0: + temp=temp[:b] + temp = int(temp) + else: + misclogger.error("Failed to get temperature.") + temp = 0 + + return int(temp) + +def system_monitor_temperature(): + + ctemp1, ctemp2, ctemp3 = system_get_coretemp() + btemp1, btemp2 = system_get_boardtemp() + ltemp = system_get_lswtemp() + fan_speed_str = system_cs5435_getfanexspeed() + fan_speed = int(fan_speed_str) + policy = 'stay' + pos = 0 + #speed c1 c2 c3 b1 b2 lsw + fan_policy_up = ([30, 40000, 40000, 40000, 42000, 35000, 95], + [40, 44000, 44000, 44000, 44000, 39000, 96], + [50, 49000, 49000, 49000, 47000, 44000, 91], + [60, 52000, 52000, 52000, 51500, 47500, 92], + [70, 53000, 53000, 53000, 52000, 49000, 93], + [100,999999,999999,999999,999999,999999,999]) + + fan_policy_down=([30, 0, 0, 0, 0, 0, 0], + [40, 34000, 34000, 34000, 34000, 30000, 80], + [50, 38000, 38000, 38000, 37000, 33000, 81], + [60, 44000, 44000, 44000, 43000, 39000, 84], + [70, 44000, 44000, 44000, 43000, 40000, 84], + [100, 48000, 48000, 48000, 46000, 42000, 85],) + + for policytable in fan_policy_up: + if fan_speed <= policytable[0]: + break + pos = pos + 1 + fan_speed = policytable[0] + if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]): + policy = 'stay' + policytable = fan_policy_down[pos] + if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]): + policy = 'down' + else: + policy = 'up' + + if policy == 'up': + misclogger.info("speed = %d." % fan_speed) + misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3)) + misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2)) + misclogger.info("lsw = %d" % ltemp) + fan_speed = fan_policy_down[pos + 1][0] + misclogger.info("fan policy: up. speedexp = {}".format(fan_speed)) + + if policy == 'stay': + fan_speed = fan_policy_down[pos] + return + + if policy == 'down': + misclogger.info("speed = %d." % fan_speed) + misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3)) + misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2)) + misclogger.info("lsw = %d" % ltemp) + fan_speed = fan_policy_down[pos - 1][0] + misclogger.info("fan policy: down.speedexp = {}".format(fan_speed)) + + cmd = "echo %d > /sys/devices/platform/cs5435_54p_fan/fan_duty_cycle_percentage" % fan_speed + status, output = log_os_system(cmd, 1) + if status: + misclogger.error("set fan speed fault") + + return + + +def system_cs5435_setfanexspeed(num): + fanspeednode = fans_prefix + 'fan_duty_cycle_percentage' + numstr = str(num) + with open(fanspeednode, 'w') as f: + f.write(numstr) + + +def system_cs5435_getfanexspeed(): + fanspeednode = fans_prefix + 'fan_duty_cycle_percentage' + fanspeedstr = system_read_filestr(fanspeednode) + fanspeedexp = int(fanspeedstr) + + return fanspeedexp + + +def system_cs5435_getdirection(): + global cs5435_fanattrnodes + direction = 0 + + for fan in cs5435_fanattrnodes: + direction = direction + fan.direction + + if direction > 2: + direction = 1 + else: + direction = 0 + + return direction + + +def system_check_psusdirection(): + global cs5435_psuattrnodes + cs5435totaldirct = system_cs5435_getdirection() + psutatus = 0 + + for psu in cs5435_psuattrnodes: + psu.updatedirection() + psu.checkstatus(cs5435totaldirct) + psutatus = psu.status + psutatus + + return (psutatus != 0) + + +def system_check_psuspresent(): + global cs5435_psuattrnodes + cs5435totaldirct = system_cs5435_getdirection() + psutatus = 0 + + for psu in cs5435_psuattrnodes: + psu.updatepresent() + psu.checkstatus(cs5435totaldirct) + psutatus = psu.status + psutatus + + return (psutatus != 0) + + +def system_check_fansstate(): + global cs5435_fanattrnodes + global cs5435_ledpath + cs5435totaldirct = system_cs5435_getdirection() + fanstatus = 0 + fanexspeed = 0 + + fanexspeed = system_cs5435_getfanexspeed() + + for fan in cs5435_fanattrnodes: + fan.updatedevice() + fan.checkstatus(fanexspeed, cs5435totaldirct) + fanstatus = fanstatus + fan.status + + if fanstatus > 0: + misclogger.error(':fan error.set fans speed 100.') + system_cs5435_setfanexspeed(100) + system_bright_leds(cs5435_ledpath['fan'], 3) + else: + system_bright_leds(cs5435_ledpath['fan'], 1) + + return (fanstatus != 0) + + +def system_misc_polling(threadName,delay): + for count in range(1,5): + if device_exist() == False: + time.sleep(delay+3) + print "%s: %s, count=%d" % ( threadName, time.ctime(time.time()), count) + else: + break + + if count == 4: + return + + status, output = log_os_system("echo 1 > /sys/devices/platform/cs5435_54p_led/leds/cs5435_54p_led::sys/brightness", 1) + status, output = log_os_system("hwconfig -cfp 1", 1) + + global AGFlag + if os.access(ageing_controlfile, os.F_OK): + AGFlag = 1 + else: + AGFlag = 0 + + os.system('csw_daemon &') + + + global cs5435_fanattrnodes + global cs5435_psuattrnodes + + for num in range(1,6): + name = 'fan{}'.format(num) + fannode = cs5435_fanattr(name) + cs5435_fanattrnodes.append(fannode) + for num in range(1,3): + name = 'psu{}'.format(num) + psunode = cs5435_psuattr(name) + cs5435_psuattrnodes.append(psunode) + + tempcontrol = system_init_coretemppath() + + misclogger.info("%s: %s misc start." % ( threadName, time.ctime(time.time()))) + count = 0 + while 1: + count = count + 1 + ret = system_check_psuspresent() + ret = system_check_fansstate() + + if count % 10 == 0: + misclogger.info(": adjust fans and check psu direction.") + system_check_psusdirection() + if tempcontrol == 0: + system_monitor_temperature() + count = 0 + time.sleep(delay) + + return + +if __name__ == '__main__': + target=system_misc_polling("Thread-misc",10) + diff --git a/platform/nephos/sonic-platform-modules-cig/cs5435-54p/utils/cig_cs5435_util.py b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/utils/cig_cs5435_util.py new file mode 100755 index 000000000000..03302592257c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs5435-54p/utils/cig_cs5435_util.py @@ -0,0 +1,563 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Cambridge, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'cs5435_54p' +version = '0.1.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':9, 'fan':5, 'thermal':4, 'psu':2, 'sfp':54} +FORCE = 0 +CPU_TYPE = 'C3308' + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + for count in range(1,5): + time.sleep(1) + ret, lsmod = log_os_system("lsmod| grep i2c_i801", 0) + if len(lsmod) > 2: + log_os_system("rmmod i2c_i801", 0) + break + + ret, lsmod = log_os_system("lsmod| grep i2c_designware_platform", 0) + if len(lsmod) > 2: + log_os_system("rmmod i2c_designware_platform", 0) + log_os_system("modprobe i2c-designware-platform", 0) + + ret, lsmod = log_os_system("lsmod| grep cig", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ + 'depmod', + 'modprobe i2c_dev', + 'modprobe i2c_mux_pca954x force_deselect_on_exit=1', + 'modprobe x86-64-cig-cs5435-54p-sysfs ' , + 'modprobe x86-64-cig-cs5435-54p-cpld ' , + 'modprobe x86-64-cig-cs5435-54p-fan' , + 'modprobe x86-64-cig-cs5435-54p-psu' , + 'modprobe x86-64-cig-cs5435-54p-sfp' , + 'modprobe x86-64-cig-cs5435-54p-led' ] + +def driver_install(): + global FORCE + + for i in range(0,len(kos)): + if i == 4: + ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 32-39 | head -n 1", 0) + if CPU_TYPE=='i3-6100U': + kos[i] =kos[i] + 'board_id=1' + ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 36-40 | head -n 1", 0) + if CPU_TYPE=='C3758' or CPU_TYPE=='C3308': + kos[i] =kos[i] + 'board_id=2' + + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['sys','fan','fan1','fan2','fan3','fan4','fan5','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['4-0048','4-0049', '5-004a', '5-004b'] , + 'psu': ['5-005a','5-005b'], + 'sfp': ['-0050']} +i2c_nodes = {'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +fan_prefix ='/sys/bus/platform/devices/'+PROJECT_NAME+'_fan' +fan_types = {'fan': ['fan1','fan2', 'fan3', 'fan4', 'fan5']} +fan_nodes = {'fan': ['state', 'front_speed_rpm', 'rear_speed_rpm', 'fault']} + + +sfp_map = [8,9,10,11,12,13,14,15,16, + 17,18,19,20,21,22,23,24,25,26, + 27,28,29,30,31,32,33,34,35,36, + 37,38,39,40,41,42,43,44,45,46, + 47,48,49,50,51,52,53,54,55,56, + 57,60,61,62,63] + +mknod =[ + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-4/new_device', + 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-4/new_device', + 'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs5435_54p_psu1 0x5a > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs5435_54p_psu2 0x5b > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs5435_54p_psu1 0x52 > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs5435_54p_psu2 0x53 > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo 24c128 0x57 > /sys/bus/i2c/devices/i2c-7/new_device'] + +port = 0 + +def device_install(): + global FORCE + global port + for i in range(0,len(mknod)): + #all nodes need times to built new i2c buses + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + if (i == 50): + port = port + 3 + else: + port = port + 1 + + + status, output =log_os_system("echo cs5435_54p_sfp"+str(port)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + if port <= 48: + status, output =log_os_system("echo cs5435_54p_sfp"+str(port)+" 0x51 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types, fan_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + for key in fan_types: + itypes = fan_types[key] + nodes = fan_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = fan_prefix+"/"+ itypes[i]+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + + +def get_ledname(ledx): + name_table={'led1':'SYS','led2':'FSTUS','led3':'FAN1','led4':'FAN2','led5':'FAN3','led6':'FAN4','led7':'FAN5','led8':'PSU1','led9':'PSU2'} + if name_table.has_key(ledx): + name = name_table[ledx] + else: + name = ledx + return name + + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + nwnamex = get_ledname(j) + if nwnamex == j: + print " "+j+":", + else: + print " "+nwnamex+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-3", 0) + return not(ret1 or ret2) + + +if __name__ == "__main__": + main() diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/classes/__init__.py b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/classes/fanutil.py b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/classes/fanutil.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/classes/thermalutil.py b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/classes/thermalutil.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/Makefile b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/Makefile new file mode 100644 index 000000000000..e37e985a2147 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/Makefile @@ -0,0 +1,6 @@ +obj-m :=x86-64-cig-cs6436-54p-sysfs.o \ + x86-64-cig-cs6436-54p-cpld.o \ + x86-64-cig-cs6436-54p-fan.o \ + x86-64-cig-cs6436-54p-led.o \ + x86-64-cig-cs6436-54p-psu.o \ + x86-64-cig-cs6436-54p-sfp.o diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/i2c-algo-lpc.h b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/i2c-algo-lpc.h new file mode 100644 index 000000000000..749aa94ef934 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/i2c-algo-lpc.h @@ -0,0 +1,222 @@ +/* -------------------------------------------------------------------- + + * A hwmon driver for the CIG cs6436-54P + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* -------------------------------------------------------------------- */ + +#ifndef I2C_LPC_H +#define I2C_LPC_H 1 + +/* ----- Control register bits ---------------------------------------- */ +#define I2C_LPC_PIN 0x80 +#define I2C_LPC_ESO 0x40 +#define I2C_LPC_ES1 0x20 +#define I2C_LPC_ES2 0x10 +#define I2C_LPC_ENI 0x08 + +#define I2C_LPC_STO 0x40 +#define I2C_LPC_ACK 0x01 + +/*command register*/ +#define I2C_LPC_STA 0x80 +#define I2C_LPC_ABT 0x40 + +/*status register*/ +#define I2C_LPC_TBE 0x02 +#define I2C_LPC_IBB 0x80 +#define I2C_LPC_RBF 0x01 +#define I2C_LPC_TD 0x08 + +#define I2C_LPC_START I2C_LPC_STA +#define I2C_LPC_STOP I2C_LPC_STO +#define I2C_LPC_REPSTART I2C_LPC_STA +#define I2C_LPC_IDLE + +/* ----- Status register bits ----------------------------------------- */ +/*#define I2C_LPC_PIN 0x80 as above*/ + +#define I2C_LPC_INI 0x40 /* 1 if not initialized */ +#define I2C_LPC_STS 0x20 +#define I2C_LPC_BER 0x10 +#define I2C_LPC_AD0 0x08 +#define I2C_LPC_LRB 0x08 +#define I2C_LPC_AAS 0x04 +#define I2C_LPC_LAB 0x02 +#define I2C_LPC_BB 0x80 + +/* ----- Chip clock frequencies --------------------------------------- */ +#define I2C_LPC_CLK3 0x00 +#define I2C_LPC_CLK443 0x10 +#define I2C_LPC_CLK6 0x14 +#define I2C_LPC_CLK 0x18 +#define I2C_LPC_CLK12 0x1c + +/* ----- transmission frequencies ------------------------------------- */ +#define I2C_LPC_TRNS90 0x00 /* 90 kHz */ +#define I2C_LPC_TRNS45 0x01 /* 45 kHz */ +#define I2C_LPC_TRNS11 0x02 /* 11 kHz */ +#define I2C_LPC_TRNS15 0x03 /* 1.5 kHz */ + + +#define I2C_LPC_OWNADR 0 +#define I2C_LPC_INTREG I2C_LPC_ES2 +#define I2C_LPC_CLKREG I2C_LPC_ES1 + +#define I2C_LPC_REG_TEST 0x01 +#define I2C_LPC_REG_BUS_SEL 0x80 +#define I2C_LPC_REG_DEVICE_ADDR 0x81 +#define I2C_LPC_REG_BYTE_COUNT 0x83 +#define I2C_LPC_REG_COMMAND 0x84 +#define I2C_LPC_REG_STATUS 0x85 +#define I2C_LPC_REG_DATA_RX1 0x86 +#define I2C_LPC_REG_DATA_RX2 0x87 +#define I2C_LPC_REG_DATA_RX3 0x88 +#define I2C_LPC_REG_DATA_RX4 0x89 +#define I2C_LPC_REG_DATA_TX1 0x8a +#define I2C_LPC_REG_DATA_TX2 0x8b +#define I2C_LPC_REG_DATA_TX3 0x8c +#define I2C_LPC_REG_DATA_TX4 0x8d + + +#define ADDR_REG_SFP_STATUS_ADDR 0X62 //reg addr +R/W# //1031 +#define ADDR_REG_SFP_STATUS_TX 0X63 // write data +#define ADDR_REG_SFP_STATUS_RX 0X64 //read data +#define ADDR_REG_SFP_STATUS_COMMAND 0X65 //cmd bit7=1,go +#define ADDR_REG_SFP_STATUS_STATUS 0X66 //status + +#define CPLD_MASTER_INTERRUPT_STATUS_REG 0x20 +#define CPLD_MASTER_INTERRUPT_MASK_REG 0x21 +#define CPLD_MASTER_INTERRUPT_ALL 0x3f +#define CPLD_MASTER_INTERRUPT_CPLD2 0x20 +#define CPLD_MASTER_INTERRUPT_CPLD1 0x10 +#define CPLD_MASTER_INTERRUPT_PSU2 0x08 +#define CPLD_MASTER_INTERRUPT_PSU1 0x04 +#define CPLD_MASTER_INTERRUPT_6320 0x02 +#define CPLD_MASTER_INTERRUPT_LSW 0x01 + + + +#define CPLD_SLAVE1_INTERRUPT_STATUS_L_REG 0x20 +#define CPLD_SLAVE1_INTERRUPT_STATUS_H_REG 0x21 +#define CPLD_SLAVE2_INTERRUPT_STATUS_L_REG 0x22 +#define CPLD_SLAVE2_INTERRUPT_STATUS_H_REG 0x23 +#define CPLD_SLAVE1_INTERRUPT_MASK_REG 0x24 +#define CPLD_SLAVE2_INTERRUPT_MASK_REG 0x25 + + +#define CPLD_SLAVE1_PRESENT08_REG 0x01 +#define CPLD_SLAVE1_PRESENT16_REG 0x02 +#define CPLD_SLAVE1_PRESENT24_REG 0x03 +#define CPLD_SLAVE2_PRESENT32_REG 0x04 +#define CPLD_SLAVE2_PRESENT40_REG 0x05 +#define CPLD_SLAVE2_PRESENT48_REG 0x06 + +#define CPLD_SLAVE1_RX_LOST08_REG 0x07 +#define CPLD_SLAVE1_RX_LOST16_REG 0x08 +#define CPLD_SLAVE1_RX_LOST24_REG 0x09 +#define CPLD_SLAVE2_RX_LOST32_REG 0x0a +#define CPLD_SLAVE2_RX_LOST40_REG 0x0b +#define CPLD_SLAVE2_RX_LOST48_REG 0x0c + +#define CPLD_SLAVE1_TX_FAULT08_REG 0x0d +#define CPLD_SLAVE1_TX_FAULT16_REG 0x0e +#define CPLD_SLAVE1_TX_FAULT24_REG 0x0f +#define CPLD_SLAVE2_TX_FAULT32_REG 0x10 +#define CPLD_SLAVE2_TX_FAULT40_REG 0x11 +#define CPLD_SLAVE2_TX_FAULT48_REG 0x12 + +#define CPLD_SLAVE2_PRESENT56_REG 0x19 +#define CPLD_SLAVE2_QSFP_CR56_REG 0x1a + + +#define CPLD_SLAVE1_INTERRUPT_PRESENT08 0x0001 +#define CPLD_SLAVE1_INTERRUPT_PRESENT16 0x0002 +#define CPLD_SLAVE1_INTERRUPT_PRESENT24 0x0004 +#define CPLD_SLAVE2_INTERRUPT_PRESENT32 0x0001 +#define CPLD_SLAVE2_INTERRUPT_PRESENT40 0x0002 +#define CPLD_SLAVE2_INTERRUPT_PRESENT48 0x0004 + +#define CPLD_SLAVE2_INTERRUPT_QSFP_CR56 0x0200 +#define CPLD_SLAVE2_INTERRUPT_PRESENT56 0x0400 + +#define CPLD_SLAVE1_INTERRUPT_RX_LOST08 0x0008 +#define CPLD_SLAVE1_INTERRUPT_RX_LOST16 0x0010 +#define CPLD_SLAVE1_INTERRUPT_RX_LOST24 0x0020 +#define CPLD_SLAVE2_INTERRUPT_RX_LOST32 0x0008 +#define CPLD_SLAVE2_INTERRUPT_RX_LOST40 0x0010 +#define CPLD_SLAVE2_INTERRUPT_RX_LOST48 0x0020 + +#define CPLD_SLAVE1_INTERRUPT_TX_FAULT08 0x0040 +#define CPLD_SLAVE1_INTERRUPT_TX_FAULT16 0x0080 +#define CPLD_SLAVE1_INTERRUPT_TX_FAULT24 0x0100 +#define CPLD_SLAVE2_INTERRUPT_TX_FAULT32 0x0040 +#define CPLD_SLAVE2_INTERRUPT_TX_FAULT40 0x0080 +#define CPLD_SLAVE2_INTERRUPT_TX_FAULT48 0x0100 + + + + + + + +#define WAIT_TIME_OUT_COUNT 100 + + +struct i2c_algo_lpc_data { + void *data; /* private data for lolevel routines */ + void (*setlpc) (void *data, int ctl, int val); + int (*getlpc) (void *data, int ctl); + int (*getown) (void *data); + int (*getclock) (void *data); + void (*waitforpin) (void *data); + + int (*xfer_begin) (void *data); + int (*xfer_end) (void *data); + + /* Multi-master lost arbitration back-off delay (msecs) + * This should be set by the bus adapter or knowledgable client + * if bus is multi-mastered, else zero + */ + unsigned long lab_mdelay; +}; + + +struct subsys_private { + struct kset subsys; + struct kset *devices_kset; + struct list_head interfaces; + struct mutex mutex; + + struct kset *drivers_kset; + struct klist klist_devices; + struct klist klist_drivers; + struct blocking_notifier_head bus_notifier; + unsigned int drivers_autoprobe:1; + struct bus_type *bus; + + struct kset glue_dirs; + struct class *class; +}; + +void cs6436_54p_sysfs_add_client(struct i2c_client *client); +void cs6436_54p_sysfs_remove_client(struct i2c_client *client); + + +#endif /* I2C_LPC8584_H */ diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-cpld.c b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-cpld.c new file mode 100644 index 000000000000..1c7930b3d268 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-cpld.c @@ -0,0 +1,2202 @@ +/* + * A hwmon driver for the CIG cs6436-54P CPLD + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-algo-lpc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CPLD_USER +# include +#else +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + + + + + +/********************************************** Start ********************************************************/ + +/* + * ISA bus. + */ + +static void platform_isa_bus_release(struct device * dev) +{ + return ; +} + + +static struct device isa_bus = { + .init_name = "lpc-isa", + .release = platform_isa_bus_release, +}; + +struct isa_dev { + struct device dev; + struct device *next; + unsigned int id; +}; + +#define to_isa_dev(x) container_of((x), struct isa_dev, dev) + +static int isa_bus_match(struct device *dev, struct device_driver *driver) +{ + struct isa_driver *isa_driver = to_isa_driver(driver); + + if (dev->platform_data == isa_driver) { + if (!isa_driver->match || + isa_driver->match(dev, to_isa_dev(dev)->id)) + return 1; + dev->platform_data = NULL; + } + return 0; +} + +static int isa_bus_probe(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->probe) + return isa_driver->probe(dev, to_isa_dev(dev)->id); + + return 0; +} + +static int isa_bus_remove(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->remove) + return isa_driver->remove(dev, to_isa_dev(dev)->id); + + return 0; +} + +static void isa_bus_shutdown(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->shutdown) + isa_driver->shutdown(dev, to_isa_dev(dev)->id); +} + +static int isa_bus_suspend(struct device *dev, pm_message_t state) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->suspend) + return isa_driver->suspend(dev, to_isa_dev(dev)->id, state); + + return 0; +} + +static int isa_bus_resume(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->resume) + return isa_driver->resume(dev, to_isa_dev(dev)->id); + + return 0; +} + +static struct bus_type isa_bus_type = { + .name = "lpc-isa", + .match = isa_bus_match, + .probe = isa_bus_probe, + .remove = isa_bus_remove, + .shutdown = isa_bus_shutdown, + .suspend = isa_bus_suspend, + .resume = isa_bus_resume +}; + +static void isa_dev_release(struct device *dev) +{ + kfree(to_isa_dev(dev)); +} + +void lpc_unregister_driver(struct isa_driver *isa_driver) +{ + struct device *dev = isa_driver->devices; + + while (dev) { + struct device *tmp = to_isa_dev(dev)->next; + device_unregister(dev); + dev = tmp; + } + driver_unregister(&isa_driver->driver); +} + + +int lpc_register_driver(struct isa_driver *isa_driver, unsigned int ndev) +{ + int error; + unsigned int id; + + isa_driver->driver.bus = &isa_bus_type; + isa_driver->devices = NULL; + + error = driver_register(&isa_driver->driver); + if (error) + return error; + + for (id = 0; id < ndev; id++) { + struct isa_dev *isa_dev; + + isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL); + if (!isa_dev) { + error = -ENOMEM; + break; + } + + isa_dev->dev.parent = &isa_bus; + isa_dev->dev.bus = &isa_bus_type; + + dev_set_name(&isa_dev->dev, "%s.%u", + isa_driver->driver.name, id); + isa_dev->dev.platform_data = isa_driver; + isa_dev->dev.release = isa_dev_release; + isa_dev->id = id; + + isa_dev->dev.coherent_dma_mask = DMA_BIT_MASK(24); + isa_dev->dev.dma_mask = &isa_dev->dev.coherent_dma_mask; + + error = device_register(&isa_dev->dev); + if (error) { + put_device(&isa_dev->dev); + break; + } + + if (isa_dev->dev.platform_data) { + isa_dev->next = isa_driver->devices; + isa_driver->devices = &isa_dev->dev; + } else + device_unregister(&isa_dev->dev); + } + + if (!error && !isa_driver->devices) + error = -ENODEV; + + if (error) + isa_unregister_driver(isa_driver); + + return error; +} + + +int lpc_bus_init(void) +{ + int error; + + error = bus_register(&isa_bus_type); + if (!error) { + error = device_register(&isa_bus); + if (error) + bus_unregister(&isa_bus_type); + } + return error; +} + +void lpc_bus_exit(void) +{ + + device_unregister(&isa_bus); + + bus_unregister(&isa_bus_type); +} + + +/********************************************** End ********************************************************/ + + + + + + +/********************************************** Start ********************************************************/ +/* + * module parameters: + */ +static int i2c_debug = 0; +static struct mutex lpc_lock; + + +#define DEB2(x) if (i2c_debug == 2) x +#define DEB3(x) if (i2c_debug == 3) x + /* print several statistical values */ +#define DEBPROTO(x) if (i2c_debug == 9) x; + /* debug the protocol by showing transferred bits */ +#define DEF_TIMEOUT 160 + + + +/* setting states on the bus with the right timing: */ + +#define set_lpc(adap, ctl, val) adap->setlpc(adap->data, ctl, val) +#define get_lpc(adap, ctl) adap->getlpc(adap->data, ctl) +#define get_own(adap) adap->getown(adap->data) +#define get_clock(adap) adap->getclock(adap->data) +#define i2c_outaddr(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DEVICE_ADDR, val) + +#define i2c_outbyte1(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX1, val) +#define i2c_outbyte2(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX2, val) +#define i2c_outbyte3(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX3, val) +#define i2c_outbyte4(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX4, val) +#define i2c_inbyte1(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX1) +#define i2c_inbyte2(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX2) +#define i2c_inbyte3(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX3) +#define i2c_inbyte4(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX4) + + + +#define LPC_FPRINTF_LOG_PATH "/tmp/file.log" +struct file *lpc_fprintf_file = NULL; + +static int lpc_fprintf_debug(const char *fmt, ...) +{ + char lpc_fprintf_buf[256]={0}; + struct va_format vaf; + va_list args; + int r; + mm_segment_t old_fs; + struct timeval tv; + struct rtc_time tm; + + do_gettimeofday(&tv); + + rtc_time_to_tm(tv.tv_sec,&tm); + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + r=snprintf(lpc_fprintf_buf,sizeof(lpc_fprintf_buf),"[%04d.%08d] %pV\n",tm.tm_sec, (int)tv.tv_usec, &vaf); + va_end(args); + old_fs = get_fs(); + set_fs(KERNEL_DS); + vfs_write(lpc_fprintf_file, (char *)&lpc_fprintf_buf, strlen(lpc_fprintf_buf), &lpc_fprintf_file->f_pos); + set_fs(old_fs); + memset(lpc_fprintf_buf,0x0,sizeof(lpc_fprintf_buf)); + return r; + +} + + + +static int lpc_fprintf_init(void) +{ + printk("lpc_fprintf_init.\n"); + + if(lpc_fprintf_file == NULL) + lpc_fprintf_file = filp_open(LPC_FPRINTF_LOG_PATH, O_RDWR | O_APPEND | O_CREAT, 0644); + + if (IS_ERR(lpc_fprintf_file)) { + printk("Error occured while opening file %s, exiting...\n", LPC_FPRINTF_LOG_PATH); + return -1; + } + + return 0; +} + +static int lpc_fprintf_exit(void) +{ + printk("lpc_fprintf_exit.\n"); + + if(lpc_fprintf_file != NULL) + filp_close(lpc_fprintf_file, NULL); + + return 0; +} + + +/* other auxiliary functions */ + + +void print_reg(struct i2c_algo_lpc_data *adap) +{ + unsigned char status; + DEBPROTO(lpc_fprintf_debug("================================================\n");) + status = get_lpc(adap, I2C_LPC_REG_BUS_SEL); + DEBPROTO(lpc_fprintf_debug("%s select reg %x : %x\n",__func__,I2C_LPC_REG_BUS_SEL, status);) + status = get_lpc(adap, I2C_LPC_REG_BYTE_COUNT); + DEBPROTO(lpc_fprintf_debug("%s count reg %x : %x\n",__func__,I2C_LPC_REG_BYTE_COUNT, status);) + + status = get_lpc(adap, I2C_LPC_REG_COMMAND); + DEBPROTO(lpc_fprintf_debug("%s command reg %x : %x\n",__func__,I2C_LPC_REG_COMMAND, status);) + status = get_lpc(adap, I2C_LPC_REG_DEVICE_ADDR); + DEBPROTO(lpc_fprintf_debug("%s address reg %x : %x\n",__func__,I2C_LPC_REG_DEVICE_ADDR, status);) + + status = get_lpc(adap, I2C_LPC_REG_STATUS); + DEBPROTO(lpc_fprintf_debug("%s status reg %x : %x\n",__func__,I2C_LPC_REG_STATUS, status);) +} + + + +static void i2c_repstart(struct i2c_algo_lpc_data *adap) +{ + DEBPROTO(lpc_fprintf_debug("%s :\n",__func__);) + set_lpc(adap, I2C_LPC_REG_COMMAND, I2C_LPC_REPSTART); +} + +static void i2c_stop(struct i2c_algo_lpc_data *adap) +{ + DEBPROTO(lpc_fprintf_debug("%s :\n",__func__);) + set_lpc(adap, I2C_LPC_REG_COMMAND, I2C_LPC_STOP); + udelay(60); + set_lpc(adap, I2C_LPC_REG_COMMAND, 0x00); +} + + + + +static void i2c_start(struct i2c_algo_lpc_data *adap) +{ + print_reg(adap); + + set_lpc(adap, I2C_LPC_REG_COMMAND, I2C_LPC_START); + + print_reg(adap); +} + + + + +static int wait_for_bb(struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + int status; + + while (--timeout) { + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus free status : %x\n",__func__,status);) + + if(status == I2C_LPC_TD) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is free status : %x\n",__func__,status);) + break; + } + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout for free busy status : %x\n",__func__,status);) + return -ETIMEDOUT; + } + + + + return 0; +} + + +static int wait_for_be(int mode,struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + unsigned char status; + + + while (--timeout) { + + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus empty status : %x\n",__func__,status);) + + if(mode == 1) + { + if((status & I2C_LPC_IBB) && (status & I2C_LPC_TBE)) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is empty status : %x\n",__func__,status);) + break; + } + } + else + { + if(status & I2C_LPC_TD) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is empty status : %x\n",__func__,status);) + break; + } + } + + status = get_lpc(adap, I2C_LPC_REG_TEST); + + DEBPROTO(lpc_fprintf_debug("%s : The test register data : %x\n",__func__,status);) + udelay(1); /* wait for 100 us */ + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout waiting for Bus Empty\n",__func__);) + return -ETIMEDOUT; + } + + return 0; +} + + +static int wait_for_bf(struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + int status; + + + while (--timeout) { + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus full status : %x\n",__func__,status);) + + if(status & I2C_LPC_RBF) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is full status : %x\n",__func__,status);) + break; + } + + status = get_lpc(adap, I2C_LPC_REG_TEST); + + DEBPROTO(lpc_fprintf_debug("%s : The test register data : %x\n",__func__,status);) + udelay(1); /* wait for 100 us */ + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout waiting for Bus Full\n",__func__);) + return -ETIMEDOUT; + } + + return 0; +} + +static int wait_for_td(struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + int status=0; + + while (--timeout) { + udelay(4); + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus done status : %x\n",__func__,status);) + + if(status == I2C_LPC_TD) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is done status : %x\n",__func__,status);) + break; + } + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout waiting for Bus Done\n",__func__);) + return -ETIMEDOUT; + } + + return 0; +} + + + +static int wait_for_pin(struct i2c_algo_lpc_data *adap, int *status) +{ + int timeout = DEF_TIMEOUT; + *status = get_lpc(adap, I2C_LPC_REG_STATUS); + + while ((*status & I2C_LPC_TBE) && --timeout) { + *status = get_lpc(adap, I2C_LPC_REG_STATUS); + } + + if (timeout == 0) + return -ETIMEDOUT; + + + return 0; +} + + +static int lpc_doAddress(struct i2c_algo_lpc_data *adap,struct i2c_msg *msg) +{ + unsigned short flags = msg->flags; + unsigned char addr; + + addr = msg->addr << 1; + if (flags & I2C_M_RD) + { + addr |= 1; + DEBPROTO(lpc_fprintf_debug("step 7 : read mode then write device address 0x%x\n",addr);) + } + else + { + DEBPROTO(lpc_fprintf_debug("step 2 : write mode then write device address 0x%x\n",addr);) + } + + if (flags & I2C_M_REV_DIR_ADDR) + { + addr ^= 1; + + } + i2c_outaddr(adap, addr); + return 0; + +} + + +static int lpc_sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) +{ + struct i2c_algo_lpc_data *adap = i2c_adap->algo_data; + int i = 0,timeout=0; + + unsigned int count = msg->len; + unsigned char *buf = msg->buf; + + do{ + lpc_doAddress(adap,msg); + set_lpc(adap, I2C_LPC_REG_BYTE_COUNT, (count-i) >= 4 ? 4:(count - i)); + DEBPROTO(lpc_fprintf_debug("step 3 : write register count %x\n",count);) + + if((count -i) >= 4) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + i2c_outbyte2(adap, buf[i+1] & 0xff); + i2c_outbyte3(adap, buf[i+2] & 0xff); + i2c_outbyte4(adap, buf[i+3] & 0xff); + + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+2,buf[i+2]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+3,buf[i+3]);) + i += 4; + } + else if((count -i) == 3) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + i2c_outbyte2(adap, buf[i+1] & 0xff); + i2c_outbyte3(adap, buf[i+2] & 0xff); + + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+2,buf[i+2]);) + + i += 3; + } + else if((count -i) == 2) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + i2c_outbyte2(adap, buf[i+1] & 0xff); + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+1,buf[i+1]);) + i += 2; + } + else if((count -i) == 1) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + i += 1; + } + + /* Send START */ + DEBPROTO(lpc_fprintf_debug("step 5-1 : Delay 6mS \n");) + udelay(6000); + DEBPROTO(lpc_fprintf_debug("step 5-2 : Start to transfrom \n");) + i2c_stop(adap); + i2c_start(adap); + DEBPROTO(lpc_fprintf_debug("step 5-3 : Start done\n");) + + udelay(400); + DEBPROTO(lpc_fprintf_debug("step 6 : Waiting for BE\n");) + timeout = wait_for_td(adap); + if (timeout) { + DEBPROTO(lpc_fprintf_debug("step 6 : Timeout waiting for BE \n");) + return -EREMOTEIO; + } + }while (i < count); + + if(i == count) + { + DEBPROTO(lpc_fprintf_debug("Writen %d bytes successd !\n",count);) + return i; + } + else + { + DEBPROTO(lpc_fprintf_debug("Writen %d bytes failed \n",count);) + return -EIO; + } +} + +static int lpc_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) +{ + int i=0,timeout=0; + struct i2c_algo_lpc_data *adap = i2c_adap->algo_data; + + unsigned int count = msg->len; + unsigned char *buf = msg->buf; + + do{ + lpc_doAddress(adap,msg); + set_lpc(adap, I2C_LPC_REG_BYTE_COUNT, (count-i) >= 4 ? 4:(count - i)); + DEBPROTO(lpc_fprintf_debug("step 8 : write register count %d\n",count);) + + /* Send START */ + DEBPROTO(lpc_fprintf_debug("step 9-1 : Delay 6mS\n");) + udelay(6000); + DEBPROTO(lpc_fprintf_debug("step 9-2 : Start to receive data\n");) + i2c_stop(adap); + i2c_start(adap); + DEBPROTO(lpc_fprintf_debug("step 9-3 : Start done\n");) + + udelay(400); + DEBPROTO(lpc_fprintf_debug("step 10 : Waiting for TD\n");) + timeout = wait_for_td(adap); + if (timeout) { + DEBPROTO(lpc_fprintf_debug("step 10 : Timeout waiting for TD \n");) + return -EREMOTEIO; + } + + if((count -i) >= 4) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + buf[i+1] = 0xff & i2c_inbyte2(adap); + buf[i+2] = 0xff & i2c_inbyte3(adap); + buf[i+3] = 0xff & i2c_inbyte4(adap); + + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+2,buf[i+2]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+3,buf[i+3]);) + + i += 4; + } + else if((count -i) == 3) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + buf[i+1] = 0xff & i2c_inbyte2(adap); + buf[i+2] = 0xff & i2c_inbyte3(adap); + + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+2,buf[i+2]);) + + i += 3; + } + else if((count -i) == 2) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + buf[i+1] = 0xff & i2c_inbyte2(adap); + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+1,buf[i+1]);) + i += 2; + } + else if((count -i) == 1) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + i += 1; + } + + + }while(i < count); + + if(i == count) + { + DEBPROTO(lpc_fprintf_debug("Read %d bytes successd !\n",count);) + return i; + } + else + { + DEBPROTO(lpc_fprintf_debug("Read %d bytes failed \n",count);) + return -EIO; + } +} + + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; +#define LPC_I2C_MAX_NCHANS 6 + + +struct lpc_iic { + struct i2c_adapter *virt_adaps[LPC_I2C_MAX_NCHANS]; + u8 last_chan; /* last register value */ +}; + + +static int lpc_master_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, + int num) +{ + struct i2c_algo_lpc_data *adap = i2c_adap->algo_data; + struct i2c_msg *pmsg; + int i; + int ret=0; + + mutex_lock(&lpc_lock); + + if (adap->xfer_begin) + adap->xfer_begin(&i2c_adap->nr); + + + for (i = 0;ret >= 0 && i < num; i++) { + pmsg = &msgs[i]; + + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n", + pmsg->flags & I2C_M_RD ? "read" : "write", + pmsg->len, pmsg->addr, i + 1, num);) + + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n", + i, msgs[i].addr, msgs[i].flags, msgs[i].len);) + + if (pmsg->flags & I2C_M_RD) { + ret = lpc_readbytes(i2c_adap, pmsg); + + if (ret != pmsg->len) { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: fail: " + "only read %d bytes.\n",ret)); + } else { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: read %d bytes.\n",ret)); + } + } else { + + ret = lpc_sendbytes(i2c_adap, pmsg); + + if (ret != pmsg->len) { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: fail: " + "only wrote %d bytes.\n",ret)); + } else { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: wrote %d bytes.\n",ret)); + } + } + } + + if (adap->xfer_end) + adap->xfer_end(&i2c_adap->nr); + + mutex_unlock(&lpc_lock); + + DEBPROTO(lpc_fprintf_debug("ret = 0x%x num = 0x%x i = 0x%x.\n",ret,num,i)); + + return ret = (ret < 0) ? ret : num; +} + + +static u32 lpc_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_QUICK; +} + +/* exported algorithm data: */ +static const struct i2c_algorithm lpc_algo = { + .master_xfer = lpc_master_xfer, + //.smbus_xfer = lpc_smbus_xfer, + .functionality = lpc_func, +}; + + +/********************************************** End ********************************************************/ + + + + + + +/********************************************** Start ********************************************************/ +#define DEFAULT_BASE 0x0a00 + +static int lpc_base= 0x0a00; +static u8 __iomem *lpc_base_iomem; + +static int lpc_irq; +static int lpc_clock = 0x1c; +static int lpc_own = 0x55; +static int lpc_mmapped; + +static unsigned long lpc_base_addr = 0x0a00; +static unsigned int lpc_io_space_size = 2; + +static unsigned long LPC_INDEX_REG; +static unsigned long LPC_DATA_REG; + + +/* notice : removed static struct i2c_lpc_iic gpi; code - + this module in real supports only one device, due to missing arguments + in some functions, called from the algo-lpc module. Sometimes it's + need to be rewriten - but for now just remove this for simpler reading */ + +static wait_queue_head_t lpc_wait; +static int lpc_pending; +static spinlock_t lock; +static spinlock_t lpc_slock; + +static struct i2c_adapter lpc_iic_ops; + +struct cpld_dev_type { + struct resource *io_resource; + struct semaphore sem; + struct cdev cdev; +}; + +struct cpld_dev_type *cpld_device; + + +/* ----- local functions ---------------------------------------------- */ + +static void lpc_cpld_setbyte(void *data, int ctl, int val) +{ + outb(ctl, LPC_INDEX_REG); + mb(); + + outb(val, LPC_DATA_REG); + mb(); +} + +static int lpc_cpld_getbyte(void *data, int ctl) +{ + u8 val = 0; + + outb(ctl, LPC_INDEX_REG); + mb(); + + val = inb(LPC_DATA_REG); + mb(); + + return val; +} + +static void lpc_iic_setbyte(void *data, int ctl, int val) +{ + if (!cpld_device) + { + return ; + } + + if (down_interruptible(&cpld_device->sem)) + { + return ; + } + + + lpc_cpld_setbyte(data,ctl,val); + + up(&cpld_device->sem); + DEBPROTO(lpc_fprintf_debug("%s REG[%x] = %x\n",__func__,ctl,val);) +} + + +static int lpc_iic_getbyte(void *data, int ctl) +{ + u8 val = 0; + if (!cpld_device) + return -ENOTTY; + + if (down_interruptible(&cpld_device->sem)) + return -ERESTARTSYS; + + val = lpc_cpld_getbyte(data,ctl); + + up(&cpld_device->sem); + DEBPROTO(lpc_fprintf_debug("%s REG[%x] = %x\n",__func__,ctl,val);) + return val; +} + +int cig_cpld_read_register(u8 reg_off, u8 *val) +{ + if (!cpld_device) + return -ENOTTY; + + if (down_interruptible(&cpld_device->sem)) + return -ERESTARTSYS; + + *val = lpc_cpld_getbyte(cpld_device, reg_off); + + up(&cpld_device->sem); + + return 0; +} +EXPORT_SYMBOL(cig_cpld_read_register); + +int cig_cpld_write_register(u8 reg_off, u8 val) +{ + if (!cpld_device) + return -ENOTTY; + + if (down_interruptible(&cpld_device->sem)) + return -ERESTARTSYS; + + lpc_cpld_setbyte(cpld_device, reg_off, val); + up(&cpld_device->sem); + return 0; +} +EXPORT_SYMBOL(cig_cpld_write_register); + + + +static int lpc_iic_getown(void *data) +{ + return (lpc_own); +} + + +static int lpc_iic_getclock(void *data) +{ + return (lpc_clock); +} + +static void lpc_iic_waitforpin(void *data) +{ + DEFINE_WAIT(wait); + int timeout = 2; + unsigned long flags; + + if (lpc_irq > 0) { + spin_lock_irqsave(&lock, flags); + if (lpc_pending == 0) { + spin_unlock_irqrestore(&lock, flags); + prepare_to_wait(&lpc_wait, &wait, TASK_INTERRUPTIBLE); + if (schedule_timeout(timeout*HZ)) { + spin_lock_irqsave(&lock, flags); + if (lpc_pending == 1) { + lpc_pending = 0; + } + spin_unlock_irqrestore(&lock, flags); + } + finish_wait(&lpc_wait, &wait); + } else { + lpc_pending = 0; + spin_unlock_irqrestore(&lock, flags); + } + } else { + udelay(100); + } +} + + +static irqreturn_t lpc_iic_handler(int this_irq, void *dev_id) { + spin_lock(&lock); + lpc_pending = 1; + spin_unlock(&lock); + wake_up_interruptible(&lpc_wait); + return IRQ_HANDLED; +} + +static int board_id = 0; + + +static int lpc_iic_select(void *data) +{ + unsigned int chan_id=0; + chan_id = *(unsigned int *)data; + chan_id -= 2; + DEBPROTO(lpc_fprintf_debug("step 1 : selest channel id = %d\n",chan_id);) + lpc_iic_setbyte(data,I2C_LPC_REG_BUS_SEL,chan_id); + + return 0; +} + +static int lpc_iic_deselect(void *data) +{ + + unsigned int chan_id=0; + chan_id = *(unsigned int *)data; + chan_id -= 2; + DEBPROTO(lpc_fprintf_debug("step last :deselect channel id = %d\n",chan_id);) + + return 0; +} + + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ +static struct i2c_algo_lpc_data lpc_iic_data = { + .setlpc = lpc_iic_setbyte, + .getlpc = lpc_iic_getbyte, + .getown = lpc_iic_getown, + .getclock = lpc_iic_getclock, + .waitforpin = lpc_iic_waitforpin, + .xfer_begin = lpc_iic_select, + .xfer_end = lpc_iic_deselect, +}; + +#include + +static struct i2c_adapter lpc_iic_arr_ops[LPC_I2C_MAX_NCHANS] = {0}; + +static void dummy_setscl(void *data, int state) +{ + return; +} + +static void dummy_setsda(void *data, int state) +{ + return; + +} + +static int dummy_getscl(void *data) +{ + return 1; + +} + +static int dummy_getsda(void *data) +{ + return 1; +} + + +static struct i2c_algo_bit_data dummy_algo_data = { + .setsda = dummy_setsda, + .setscl = dummy_setscl, + .getsda = dummy_getsda, + .getscl = dummy_getscl, + .udelay = 50, + .timeout = HZ, +}; + + +static int dummy_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, + int num) +{ + return 1; +} + +static u32 dummy_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_QUICK; +} + + +static const struct i2c_algorithm dummy_algo = { + .master_xfer = dummy_xfer, + .functionality = dummy_func, +}; + + + +static struct i2c_adapter i2c_dummy = { + .owner = THIS_MODULE, + .class = I2C_CLASS_HWMON, + .algo_data = &dummy_algo_data, + .algo = &dummy_algo, + .name = "i2c_dummy", +}; + + +static int lpc_iic_match(struct device *dev, unsigned int id) +{ + /* sanity checks for lpc_mmapped I/O */ + + DEB2(printk("lpc_iic_match\n");) + + + if (lpc_base < DEFAULT_BASE) { + dev_err(dev, "incorrect lpc_base address (%#x) specified " + "for lpc_mmapped I/O\n", lpc_base); + return 0; + } + + if (lpc_base == 0) { + lpc_base = DEFAULT_BASE; + } + return 1; +} + +static int lpc_iic_probe(struct device *dev, unsigned int id) +{ + int rval,num; + + lpc_fprintf_init(); + + DEB2(printk("lpc_iic_probe\n");) + + mutex_init(&lpc_lock); + + for(num = 0; num < LPC_I2C_MAX_NCHANS;num++) + { + lpc_iic_arr_ops[num].dev.parent = dev; + lpc_iic_arr_ops[num].owner = THIS_MODULE; + lpc_iic_arr_ops[num].class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + lpc_iic_arr_ops[num].algo = &lpc_algo; + lpc_iic_arr_ops[num].algo_data = &lpc_iic_data, + lpc_iic_arr_ops[num].nr=num; + snprintf(lpc_iic_arr_ops[num].name, sizeof(lpc_iic_arr_ops[num].name), "i2c-%d-lpc", i2c_adapter_id(&lpc_iic_arr_ops[num])); + rval |= i2c_add_adapter(&lpc_iic_arr_ops[num]); + DEB2(printk("%s\n",lpc_iic_arr_ops[num].name);) + } + + return 0; +} + +static int lpc_iic_remove(struct device *dev, unsigned int id) +{ + int num; + DEB2(printk("lpc_iic_remove\n")); + + lpc_fprintf_exit(); + for(num = LPC_I2C_MAX_NCHANS - 1; num >= 0 ;num--) + i2c_del_adapter(&lpc_iic_arr_ops[num]); + + + return 0; +} + +static struct isa_driver i2c_lpc_driver = { + .match = lpc_iic_match, + .probe = lpc_iic_probe, + .remove = lpc_iic_remove, + .driver = { + .owner = THIS_MODULE, + .name = "lpc-iic", + }, +}; + +/********************************************** End ********************************************************/ + + + + + + +/********************************************** Start ********************************************************/ + +static int cpld_major = 0; +static int cpld_minor = 0; + +struct cpld_rw_msg { + unsigned char addr; + unsigned char data; +}; + + +static struct cpld_rw_msg param_read = {-1}; +static struct cpld_rw_msg param_write = {-1}; +static struct cpld_rw_msg param_reads = {-1}; +static struct cpld_rw_msg param_writes = {-1}; + +void cpld_sysfs_kobj_release(struct kobject *kobj) +{ + return; +} + +int cpld_sysfs_add_attr(struct kobject* kobj, char* attr_name) +{ + + struct attribute *attr; + + attr = kmalloc(sizeof(struct attribute), GFP_KERNEL); + attr->name = attr_name; + attr->mode = 0644; + + return sysfs_create_file(kobj, attr); +} + +static int cig_cpld_write_slave_cpld_register(u8 reg_addr, u8 reg_data); +static int cig_cpld_read_slave_cpld_register(u8 reg_addr, u8 *reg_data); + + +static ssize_t cpld_sysfs_show(struct kobject *kobj, struct attribute *attr, char *buffer) +{ + u8 val=0,ret=0,year=0,month=0,day=0,cpld_m=0,cpld_1=0,cpld_2=0; + + if (0 == strcmp(attr->name, "read")) + { + val = lpc_iic_getbyte(NULL,param_read.addr); + ret = sprintf(buffer,"read : addr = 0x%x val = 0x%x\n",param_read.addr, val); + + } + else if (0 == strcmp(attr->name, "write")) + { + lpc_iic_setbyte(NULL, param_write.addr,param_write.data); + ret = sprintf(buffer,"write : addr = 0x%x val = 0x%x\n",param_write.addr, param_write.data); + } + else if (0 == strcmp(attr->name, "version")) + { + cpld_m = lpc_iic_getbyte(NULL, 0x02); + year = lpc_iic_getbyte(NULL, 0x03); + month = lpc_iic_getbyte(NULL, 0x04); + day = lpc_iic_getbyte(NULL, 0x05); + + cig_cpld_read_slave_cpld_register(0x1d,&cpld_1); + cig_cpld_read_slave_cpld_register(0x1e,&cpld_2); + + ret = sprintf(buffer,"Main CPLD version : V%02x\n"\ + "Main CPLD date : 20%02x-%02x-%02x\n"\ + "Slave 1 CPLD version : V%02x\n"\ + "Slave 2 CPLD version : V%02x\n",cpld_m,year,month,day,cpld_1,cpld_2); + } + if (0 == strcmp(attr->name, "reads")) + { + ret = cig_cpld_read_slave_cpld_register(param_reads.addr,&val); + if (ret < 0) + printk("ERROR:Failed to read slave cpld.\n"); + ret = sprintf(buffer,"reads : addr = 0x%x val = 0x%x\n",param_reads.addr, val); + + } + else if (0 == strcmp(attr->name, "writes")) + { + ret = cig_cpld_write_slave_cpld_register(param_writes.addr,param_writes.data); + if (ret < 0) + printk("ERROR:Failed to read slave cpld.\n"); + ret = sprintf(buffer,"writes : addr = 0x%x val = 0x%x\n",param_writes.addr, param_writes.data); + } + + + return ret; + +} + +static ssize_t cpld_sysfs_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t count) +{ + int param[3]; + + if (0 == strcmp(attr->name, "read")) + { + sscanf(buffer, "0x%02x", ¶m[0]); + param_read.addr = param[0]; + } + else if (0 == strcmp(attr->name, "write")) + { + sscanf(buffer, "0x%2x 0x%02x", ¶m[0], ¶m[1]); + param_write.addr = param[0]; + param_write.data = param[1]; + } + if (0 == strcmp(attr->name, "reads")) + { + sscanf(buffer, "0x%02x", ¶m[0]); + param_reads.addr = param[0]; + } + else if (0 == strcmp(attr->name, "writes")) + { + sscanf(buffer, "0x%2x 0x%02x", ¶m[0], ¶m[1]); + param_writes.addr = param[0]; + param_writes.data = param[1]; + } + return count; +} + + + +static struct sysfs_ops cpld_sysfs_ops = +{ + .show = cpld_sysfs_show, + .store = cpld_sysfs_store, +}; + +static struct kobj_type cpld_kobj_type = +{ + .release = cpld_sysfs_kobj_release, + .sysfs_ops = &cpld_sysfs_ops, + .default_attrs = NULL, +}; + + +static const char driver_name[] = "cpld_drv"; +static atomic_t cpld_available = ATOMIC_INIT(1); +static struct class *cpld_class; +static struct device *cpld_dev; + + + +#define CPLD_IOC_MAGIC '[' + +#define CPLD_IOC_RDREG _IOR(CPLD_IOC_MAGIC, 0, struct cpld_rw_msg) +#define CPLD_IOC_WRREG _IOW(CPLD_IOC_MAGIC, 1, struct cpld_rw_msg) + +#define CPLD_IOC_MAXNR 2 + + +int cpld_open(struct inode *inode, struct file *filp) +{ + struct cpld_dev_type *dev; + + if (! atomic_dec_and_test(&cpld_available)) { + atomic_inc(&cpld_available); + return -EBUSY; + } + + dev = container_of(inode->i_cdev, struct cpld_dev_type, cdev); + filp->private_data = dev; + + return 0; +} + +int cpld_release(struct inode *inode, struct file *flip) +{ + atomic_inc(&cpld_available); + return 0; +} + + +long cpld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int rc = 0; + int err = 0; + struct cpld_dev_type *dev = (struct cpld_dev_type *)filp->private_data; + struct cpld_rw_msg msg; + + if (_IOC_TYPE(cmd) != CPLD_IOC_MAGIC) + return -ENOTTY; + if (_IOC_NR(cmd) > CPLD_IOC_MAXNR) + return -ENOTTY; + + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; + + switch(cmd){ + case CPLD_IOC_RDREG: + rc = copy_from_user(&msg, (void __user *)arg, sizeof(msg)); + if (!rc) { + msg.data = lpc_cpld_getbyte(dev, msg.addr); + rc = copy_to_user((void __user *)arg, &msg, sizeof(msg)); + } + break; + + case CPLD_IOC_WRREG: + rc = copy_from_user(&msg, (void __user *)arg, sizeof(msg)); + if (!rc) { + lpc_cpld_setbyte(dev, msg.addr, msg.data); + } + break; + default: + rc = -ENOTTY; + break; + } + up(&dev->sem); + + return rc; +} + +struct file_operations cpld_fops = { + .owner = THIS_MODULE, + .open = cpld_open, + .unlocked_ioctl = cpld_ioctl, + .release = cpld_release, +}; + + +static void cpld_setup_cdev(struct cpld_dev_type *dev) +{ + int err, devno = MKDEV(cpld_major, cpld_minor); + + cdev_init(&dev->cdev, &cpld_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &cpld_fops; + err = cdev_add(&dev->cdev, devno, 1); + + if (err) + DEB2(printk(KERN_NOTICE "Error %d adding cpld", err);) +} +/********************************************** End ********************************************************/ + + + + +/********************************************** Start ********************************************************/ +#include +#include +#include + +static spinlock_t irq_inter_lock; +static struct delayed_work irq_inter_work; +static unsigned long irq_inter_delay; + + +static int cig_cpld_write_slave_cpld_register(u8 reg_addr, u8 reg_data) +{ + u8 read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + DEB2(printk("<=======write=========>")); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, reg_addr << 1); + DEB2(printk("[62]=%x\n",reg_addr << 1)); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_TX, reg_data); + DEB2(printk("[63]=%x\n",reg_data)); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + DEB2(printk("[65]=%x\n",0x80)); + do{ + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &read_status); + DEB2(printk("[66]=%x\n",read_status)); + udelay(60); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(read_status != 0x02); + DEB2(printk("<=======write=========>")); + + + if(wait_time_out == 0) + return -1; + + return 1; +} + + +static int cig_cpld_read_slave_cpld_register(u8 reg_addr, u8 *reg_data) +{ + u8 read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + DEB2(printk("<========read=========>")); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, reg_addr << 1 | 1); + DEB2(printk("[62]=%x\n",reg_addr << 1 | 1)); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + DEB2(printk("[65]=%x\n",0x80)); + do{ + udelay(60); + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &read_status); + DEB2(printk("[66]=%x\n",read_status)); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(read_status != 0x01); + + cig_cpld_read_register(ADDR_REG_SFP_STATUS_RX,reg_data); + DEB2(printk("[64]=%x\n",*reg_data)); + DEB2(printk("<========read=========>")); + + if(wait_time_out == 0) + return -1; + + return 1; +} + + + +struct sock *nlsk = NULL; +extern struct net init_net; +#define NETLINK_TEST 26 +#define MSG_LEN 125 +#define USER_PORT 100 +static u32 irq_present_status_low_current,irq_present_status_low_next; +static u32 irq_present_status_high_current,irq_present_status_high_next; +static u32 irq_tx_fault_status_low_current,irq_tx_fault_status_low_next; +static u32 irq_tx_fault_status_high_current,irq_tx_fault_status_high_next; +static u32 irq_rx_lost_status_low_current,irq_rx_lost_status_low_next; +static u32 irq_rx_lost_status_high_current,irq_rx_lost_status_high_next; + +static u8 irq_present_qsfp_current,irq_present_qsfp_next; +static u8 irq_interrupt_qsfp_current,irq_interrupt_qsfp_next; + +struct input_dev *cpld_input_dev; + + + +int send_usrmsg(char *pbuf, uint16_t len) +{ + struct sk_buff *nl_skb; + struct nlmsghdr *nlh; + + int ret; + + + nl_skb = nlmsg_new(len, GFP_ATOMIC); + if(!nl_skb) + { + printk("netlink alloc failure\n"); + return -1; + } + + + nlh = nlmsg_put(nl_skb, 0, 0, NETLINK_TEST, len, 0); + if(nlh == NULL) + { + printk("nlmsg_put failaure \n"); + nlmsg_free(nl_skb); + return -1; + } + + memcpy(nlmsg_data(nlh), pbuf, len); + ret = netlink_unicast(nlsk, nl_skb, USER_PORT, MSG_DONTWAIT); + + return ret; +} + +static void netlink_rcv_msg(struct sk_buff *skb) +{ + + struct nlmsghdr *nlh = NULL; + char *umsg = NULL; + char kmsg[1024] = {0}; + char kmsg_tmp[16] = {0}; + u8 i = 0; + u8 tmp[3]={0}; + + if(skb->len >= nlmsg_total_size(0)) + { + nlh = nlmsg_hdr(skb); + umsg = NLMSG_DATA(nlh); + if(umsg) + { + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_low_current & (0x1 << i))) + { + tmp[0] = 1; + } + else + { + tmp[0] = 0; + } + + if(!(irq_rx_lost_status_low_current & (0x1 << i))) + { + tmp[1] = 1; + } + else + { + tmp[1] = 0; + } + + if(!(irq_tx_fault_status_low_current & (0x1 << i))) + { + tmp[2] = 1; + } + else + { + tmp[2] = 0; + } + memset(kmsg_tmp,0xff,sizeof(kmsg_tmp)); + sprintf(kmsg_tmp,"sfp%02d:%1d:%1d:%1d ",i+1,tmp[0],tmp[1],tmp[2]); + strcat(kmsg,kmsg_tmp); + } + + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_high_current & (0x1 << i))) + { + tmp[0] = 1; + } + else + { + tmp[0] = 0; + } + + if(!(irq_rx_lost_status_high_current & (0x1 << i))) + { + tmp[1] = 1; + } + else + { + tmp[1] = 0; + } + + if(!(irq_tx_fault_status_high_current & (0x1 << i))) + { + tmp[2] = 1; + } + else + { + tmp[2] = 0; + } + memset(kmsg_tmp,0xff,sizeof(kmsg_tmp)); + sprintf(kmsg_tmp,"sfp%02d:%1d:%1d:%1d ",i+25,tmp[0],tmp[1],tmp[2]); + strcat(kmsg,kmsg_tmp); + } + + + for(i = 0;i < 8;i++) + { + if(!(irq_present_qsfp_current & (0x1 << i))) + { + tmp[0] = 1; + } + else + { + tmp[0] = 0; + } + + if(!(irq_interrupt_qsfp_current & (0x1 << i))) + { + tmp[1] = 1; + } + else + { + tmp[1] = 0; + } + + memset(kmsg_tmp,0xff,sizeof(kmsg_tmp)); + sprintf(kmsg_tmp,"qsfp%02d:%1d:%1d:%1d ",i+49,tmp[0],tmp[1],0); + strcat(kmsg,kmsg_tmp); + } + + printk("kernel recv from user: %s\n", umsg); + send_usrmsg(kmsg, strlen(kmsg)); + } + } + + return ; +} + + + +struct netlink_kernel_cfg cfg = { + .input = netlink_rcv_msg, /* set recv callback */ +}; + + + +#define RANGE_OF_BYTE_SHIFT(to_arg,shift,from_arg) {to_arg &= ~(0xff << shift); to_arg |= from_arg << shift;} + + +static void irq_inter_wapper(struct work_struct * work) +{ + + u8 m_data = 0; + u8 data_high8 = 0,data_low8 = 0; + u16 data_16 = 0; + u8 status = 0; + u8 i = 0; + char kmsg[64]={0}; + u8 tmp[3] = {0}; + + DEB2(printk("CPLD_MASTER_INTERRUPT\r\n")); + + m_data = lpc_iic_getbyte(NULL,CPLD_MASTER_INTERRUPT_STATUS_REG); + lpc_iic_setbyte(NULL,CPLD_MASTER_INTERRUPT_STATUS_REG,0xff); + + cig_cpld_write_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_MASK_REG,0xff); + cig_cpld_write_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_MASK_REG,0xff); + if(!(m_data & CPLD_MASTER_INTERRUPT_CPLD1)) + { + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_STATUS_H_REG,&data_high8); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_STATUS_L_REG,&data_low8); + data_16 = data_low8 | data_high8 << 8; + if( + !(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT08) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT16) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT24) + ) + { + if(!(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT08)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT08\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_PRESENT08_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_low_current,0,status); + + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT16)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT16\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_PRESENT16_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_low_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT24)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT24\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_PRESENT24_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_low_current,16,status); + } + DEB2(printk("irq_present_status_low_next = %08x irq_present_status_low_current = %08x \n",irq_present_status_low_next,irq_present_status_low_current)); + } + + if( + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST08) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST16) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST24) + ) + { + if(!(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST08)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_RX_LOST08\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_RX_LOST08_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_low_current,0,status); + + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST16)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT16\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_RX_LOST16_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_low_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST24)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT24\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_RX_LOST24_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_low_current,16,status); + } + DEB2(printk("irq_rx_lost_status_low_next = %08x irq_rx_lost_status_low_current = %08x \n",irq_rx_lost_status_low_next,irq_rx_lost_status_low_current)); + } + + if( + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST08) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST16) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST24) + ) + { + if(!(data_16 & CPLD_SLAVE1_INTERRUPT_TX_FAULT08)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_TX_FAULT08\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_TX_FAULT08_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_low_current,0,status); + + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_TX_FAULT16)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_TX_FAULT16\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_TX_FAULT16_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_low_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_TX_FAULT24)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_TX_FAULT24\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_TX_FAULT24_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_low_current,16,status); + } + DEB2(printk("irq_tx_fault_status_low_next = %08x irq_tx_fault_status_low_current = %08x \n",irq_tx_fault_status_low_next,irq_tx_fault_status_low_current)); + + } + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_CPLD2)) + { + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_STATUS_H_REG,&data_high8); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_STATUS_L_REG,&data_low8); + data_16 = data_low8 | data_high8 << 8; + if( + !(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT32) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT40) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT48) + ) + { + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT32)) + { + DEB2(printk("CPLD_SLAVE2_PRESENT32_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT32_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_high_current,0,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT40)) + { + DEB2(printk("CPLD_SLAVE2_PRESENT40_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT40_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_high_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT48)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT48\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT48_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_high_current,16,status); + } + } + + if( + !(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST32) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST40) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST48) + ) + { + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST32)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_RX_LOST32\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_RX_LOST32_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_high_current,0,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST40)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT40\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_RX_LOST40_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_high_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST48)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT48\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_RX_LOST48_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_high_current,16,status); + } + + } + + if( + !(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT32) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT40) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT48) + ) + { + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT32)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_RX_LOST32\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_TX_FAULT32_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_high_current,0,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT40)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT40\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_TX_FAULT40_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_high_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT48)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT48\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_TX_FAULT48_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_high_current,16,status); + } + } + + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT56)) + { + DEB2(printk("CPLD_SLAVE2_PRESENT56_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT56_REG,&status); + irq_present_qsfp_current = status; + } + + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_QSFP_CR56)) + { + DEB2(printk("CPLD_SLAVE2_QSFP_CR56_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_QSFP_CR56_REG,&status); + irq_interrupt_qsfp_current = status; + } + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_LSW)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_LSW\r\n")); + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_PSU1)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_PSU1\r\n")); + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_PSU2)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_PSU2\r\n")); + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_6320)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_6320\r\n")); + } + cig_cpld_write_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_MASK_REG,0x0); + cig_cpld_write_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_MASK_REG,0x0); + + memset(tmp,0xff,sizeof(tmp)); + + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_low_current & (0x1 << i)) && (irq_present_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d is present\r\n",i+1)); + tmp[0] = 1; + } + else if((irq_present_status_low_current & (0x1 << i)) && !(irq_present_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d is absent\r\n",i+1)); + tmp[0] = 0; + } + + if(!(irq_tx_fault_status_low_current & (0x1 << i)) && (irq_tx_fault_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is right\r\n",i+1)); + tmp[1] = 1; + } + else if((irq_tx_fault_status_low_current & (0x1 << i)) && !(irq_tx_fault_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is fault\r\n",i+1)); + tmp[1] = 0; + } + + if(!(irq_rx_lost_status_low_current & (0x1 << i)) && (irq_rx_lost_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is meet\r\n",i+1)); + tmp[2] = 1; + } + else if((irq_rx_lost_status_low_current & (0x1 << i)) && !(irq_rx_lost_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is lost\r\n",i+1)); + tmp[2] = 0; + } + + if((tmp[0] != 0xff) || (tmp[1] != 0xff) || (tmp[2] != 0xff)) + { + memset(kmsg,0xff,sizeof(kmsg)); + snprintf(kmsg,sizeof(kmsg),"sfp%02d:%1d:%1d:%1d ",i+1,(tmp[0] == 0xff) ? 0:tmp[0],(tmp[1] == 0xff) ? 0:tmp[1],(tmp[2] == 0xff) ? 0:tmp[2]); + break; + } + } + + memset(tmp,0xff,sizeof(tmp)); + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_high_current & (0x1 << i)) && (irq_present_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d is present\r\n",i+25)); + tmp[0] = 1; + } + else if((irq_present_status_high_current & (0x1 << i)) && !(irq_present_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d is absent\r\n",i+25)); + tmp[0] = 0; + + } + + if(!(irq_rx_lost_status_high_current & (0x1 << i)) && (irq_rx_lost_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is meet\r\n",i+25)); + tmp[1] = 1; + } + else if((irq_rx_lost_status_high_current & (0x1 << i)) && !(irq_rx_lost_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is lost\r\n",i+25)); + tmp[1] = 0; + } + + if(!(irq_tx_fault_status_high_current & (0x1 << i)) && (irq_tx_fault_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is right\r\n",i+25)); + tmp[2] = 1; + } + else if((irq_tx_fault_status_high_current & (0x1 << i)) && !(irq_tx_fault_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is fault\r\n",i+25)); + tmp[2] = 0; + } + + if((tmp[0] != 0xff) || (tmp[1] != 0xff) || (tmp[2] != 0xff)) + { + memset(kmsg,0xff,sizeof(kmsg)); + snprintf(kmsg,sizeof(kmsg),"sfp%02d:%1d:%1d:%1d ",i+25,(tmp[0] == 0xff) ? 0:tmp[0],(tmp[1] == 0xff) ? 0:tmp[1],(tmp[2] == 0xff) ? 0:tmp[2]); + break; + } + } + + memset(tmp,0xff,sizeof(tmp)); + for(i = 0 ; i < 8; i++) + { + if(!(irq_present_qsfp_current & (0x1 << i)) && (irq_present_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d is present\r\n",i+49)); + tmp[0] = 1; + } + else if((irq_present_qsfp_current & (0x1 << i)) && !(irq_present_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d is absent\r\n",i+49)); + tmp[0] = 0; + } + + if(!(irq_interrupt_qsfp_current & (0x1 << i)) && (irq_interrupt_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d interrupt is occured \r\n",i+49)); + tmp[1] = 1; + } + else if((irq_interrupt_qsfp_current & (0x1 << i)) && !(irq_interrupt_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d interrupt is cleaned\r\n",i+49)); + tmp[1] = 0; + } + + if((tmp[0] != 0xff) || (tmp[1] != 0xff)) + { + memset(kmsg,0xff,sizeof(kmsg)); + snprintf(kmsg,sizeof(kmsg),"qsfp%02d:%1d:%1d:%1d ",i+49,(tmp[0] == 0xff) ? 0:tmp[0],(tmp[1] == 0xff) ? 0:tmp[1],0); + break; + } + } + + + irq_present_status_low_next = irq_present_status_low_current; + irq_rx_lost_status_low_next = irq_rx_lost_status_low_current; + irq_tx_fault_status_low_next = irq_tx_fault_status_low_current; + irq_present_status_high_next = irq_present_status_high_current; + irq_rx_lost_status_high_next = irq_rx_lost_status_high_current; + irq_tx_fault_status_high_next = irq_tx_fault_status_high_current; + irq_present_qsfp_next = irq_present_qsfp_current; + irq_interrupt_qsfp_next = irq_interrupt_qsfp_current; + + send_usrmsg(kmsg, strlen(kmsg)); +} + +static void disableIrq(unsigned short maskReg, unsigned short mask) +{ + u8 data = 0; + + data = lpc_iic_getbyte(NULL,maskReg); + data |= mask; + lpc_iic_setbyte(NULL,maskReg, data); +} + +static void enableIrq(unsigned short maskReg, unsigned short mask) +{ + unsigned short data; + + data = lpc_iic_getbyte(NULL,maskReg); + data &= ~mask; + lpc_iic_setbyte(NULL,maskReg, data); +} + + +static irqreturn_t irq_inter_isr(int irq, void *handle) +{ + + /* + * use keventd context to read the event fifo registers + * Schedule readout at least 25ms after notification for + * REVID < 4 + */ + + schedule_delayed_work(&irq_inter_work, irq_inter_delay); + + return IRQ_HANDLED; +} + + +#define CIG_CPLD_CHR_NAME "cpld" + + +static int __init cpld_init(void) +{ + int rval,rc=0; + dev_t dev; + u8 s_data; + + DEB2(printk("cpld_init\n");) + +/**************************************************************************************/ + + LPC_INDEX_REG = lpc_base_addr; + LPC_DATA_REG = lpc_base_addr + 1; + + cpld_device = kzalloc(sizeof(struct cpld_dev_type), GFP_KERNEL); + if (!cpld_device) + goto error3; + cpld_device->io_resource = request_region(lpc_base_addr, + lpc_io_space_size, "lpc-i2c"); + if (!cpld_device->io_resource) { + printk("lpc: claim I/O resource fail\n"); + goto error2; + } + sema_init(&cpld_device->sem, 1); + + if (cpld_major) { + dev = MKDEV(cpld_major, cpld_minor); + rc = register_chrdev_region(dev, 1, CIG_CPLD_CHR_NAME); + } else { + rc = alloc_chrdev_region(&dev, cpld_major, 1, CIG_CPLD_CHR_NAME); + cpld_major = MAJOR(dev); + } + + cpld_setup_cdev(cpld_device); + + cpld_class = class_create(THIS_MODULE,CIG_CPLD_CHR_NAME); + if (!cpld_class) { + DEB2(printk("failed to create class\n");) + goto error1; + } + + cpld_class->p->subsys.kobj.ktype= &cpld_kobj_type; + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "read"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "write"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "reads"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "writes"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "version"); + + cpld_dev = device_create(cpld_class, NULL, dev, NULL, CIG_CPLD_CHR_NAME); + +/**************************************************************************************/ + + rval = lpc_bus_init(); + rval = lpc_register_driver(&i2c_lpc_driver, 1); + +/**************************************************************************************/ + return 0; +error1: + cdev_del(&cpld_device->cdev); + unregister_chrdev_region(dev, 1); +error2: + release_resource(cpld_device->io_resource); +error3: + kfree(cpld_device); + + return rc; +} + +static void __exit cpld_exit(void) +{ + DEB2(printk("cpld_exit\n")); + + lpc_unregister_driver(&i2c_lpc_driver); + lpc_bus_exit(); + dev_t devno = MKDEV(cpld_major, cpld_minor); + + cdev_del(&cpld_device->cdev); + if (cpld_class) { + device_destroy(cpld_class, devno); + class_destroy(cpld_class); + } + + if (cpld_device) { + if (cpld_device->io_resource) + release_resource(cpld_device->io_resource); + + kfree(cpld_device); + } + unregister_chrdev_region(devno, 1); + + +} + +module_param(cpld_major, int, S_IRUGO); +module_param(cpld_minor, int, S_IRUGO); +module_param(i2c_debug, int, S_IRUGO); +module_param(board_id, int, S_IRUGO); + +module_init(cpld_init); +module_exit(cpld_exit); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436-54p-cpld driver"); +MODULE_LICENSE("GPL"); + + +/********************************************** End ********************************************************/ + + + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-fan.c b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-fan.c new file mode 100644 index 000000000000..881cb7304b06 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-fan.c @@ -0,0 +1,521 @@ +/* + * A hwmon driver for the CIG cs6436-54p fan + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#define FAN_SPEED_DUTY_TO_CPLD_STEP 10 + +static struct cs6436_54p_fan_data *cs6436_54p_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + + +extern int cig_cpld_write_register(u8 reg_off, u8 val); +extern int cig_cpld_read_register(u8 reg_off, u8 *val); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x41, /* fan enable/disable */ + 0x40, /* fan PWM(for all fan) */ + 0x42, /* front fan 1 speed(rpm) */ + 0x44, /* front fan 2 speed(rpm) */ + 0x46, /* front fan 3 speed(rpm) */ + 0x48, /* front fan 4 speed(rpm) */ + 0x4a, /* front fan 5 speed(rpm) */ + 0x43, /* rear fan 1 speed(rpm) */ + 0x45, /* rear fan 2 speed(rpm) */ + 0x47, /* rear fan 3 speed(rpm) */ + 0x49, /* rear fan 4 speed(rpm) */ + 0x4b, /* rear fan 5 speed(rpm) */ + 0x4c, /* fan direction rear to front or front to rear */ +}; + + +/* Each client has this additional data */ +struct cs6436_54p_fan_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +static struct cs6436_54p_fan_data *fan_data = NULL; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, +}; + +enum sysfs_fan_attributes { + FAN_STATE_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN_DIRECTION, + FAN1_STATE, + FAN2_STATE, + FAN3_STATE, + FAN4_STATE, + FAN5_STATE, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, +}; + +/* Define attributes + */ +#define DECLARE_FAN_STATE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_state, S_IRUGO, fan_show_value, NULL, FAN##index##_STATE) +#define DECLARE_FAN_STATE_ATTR(index) &sensor_dev_attr_fan##index##_state.dev_attr.attr + +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IWUSR | S_IRUGO, fan_show_value, set_fan_direction, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + + +/* 5 fan state attributes in this platform */ +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(1); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(2); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(3); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(4); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(5); + + +/* 5 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5); + +/* 5 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5); + +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); + +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); + + +static struct attribute *cs6436_54p_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_STATE_ATTR(1), + DECLARE_FAN_STATE_ATTR(2), + DECLARE_FAN_STATE_ATTR(3), + DECLARE_FAN_STATE_ATTR(4), + DECLARE_FAN_STATE_ATTR(5), + DECLARE_FAN_FAULT_ATTR(1), + DECLARE_FAN_FAULT_ATTR(2), + DECLARE_FAN_FAULT_ATTR(3), + DECLARE_FAN_FAULT_ATTR(4), + DECLARE_FAN_FAULT_ATTR(5), + DECLARE_FAN_SPEED_RPM_ATTR(1), + DECLARE_FAN_SPEED_RPM_ATTR(2), + DECLARE_FAN_SPEED_RPM_ATTR(3), + DECLARE_FAN_SPEED_RPM_ATTR(4), + DECLARE_FAN_SPEED_RPM_ATTR(5), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + NULL +}; + +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + if (reg_val +== 0xFF) { + return 100; + } + return ((u32)(reg_val) * 100)/ 255; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle >= FAN_MAX_DUTY_CYCLE) { + return 0xFF; + } + + return 255 / 10 * (duty_cycle / 10); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_is_state(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct cs6436_54p_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value <= 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + cig_cpld_write_register(fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + + return count; +} + +static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value,fan_index; + u8 mask,reg_val; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + fan_index = attr->index - FAN1_DIRECTION; + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (!(value == 0 || value == 1)) + return -EINVAL; + + + cig_cpld_read_register(fan_reg[FAN_DIRECTION],®_val); + + if(value == 1) + { + reg_val |= (1 << fan_index); + } + else + { + reg_val &= ~(1 << fan_index); + } + + cig_cpld_write_register(fan_reg[FAN_DIRECTION], reg_val); + + return count; +} + + + + + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + cs6436_54p_fan_update_device(dev); + + struct cs6436_54p_fan_data *data = fan_data; + + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + + case FAN1_STATE: + case FAN2_STATE: + case FAN3_STATE: + case FAN4_STATE: + case FAN5_STATE: + //printk("FAN_STATE_REG: 0x%x\n", data->reg_val[FAN_STATE_REG]); + //printk("index: %d\n", attr->index); + ret = sprintf(buf, "%d\n", + reg_val_to_is_state(data->reg_val[FAN_STATE_REG], + attr->index - FAN1_STATE)); + break; + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: +// printk("FAN_seed_REG: 0x%x\n", data->reg_val[attr->index]); +// printk("index: %d\n", attr->index); + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + ret = sprintf(buf, "%d\n",reg_val_to_is_state(data->reg_val[FAN_DIRECTION],attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group cs6436_54p_fan_group = { + .attrs = cs6436_54p_fan_attributes, +}; + +static struct cs6436_54p_fan_data *cs6436_54p_fan_update_device(struct device *dev) +{ + struct cs6436_54p_fan_data *data = fan_data; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + u8 status; + (void)cig_cpld_read_register(fan_reg[i], &status); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int cs6436_54p_fan_probe(struct platform_device *pdev) +{ + int status = -1; + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &cs6436_54p_fan_group); + if (status) { + goto exit; + + } + + fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(fan_data->hwmon_dev)) { + status = PTR_ERR(fan_data->hwmon_dev); + goto exit_remove; + } + + dev_info(&pdev->dev, "cs6436_54p_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &cs6436_54p_fan_group); +exit: + return status; +} + +static int cs6436_54p_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&fan_data->pdev->dev.kobj, &cs6436_54p_fan_group); + + return 0; +} + +#define DRVNAME "cs6436_54p_fan" + +static struct platform_driver cs6436_54p_fan_driver = { + .probe = cs6436_54p_fan_probe, + .remove = cs6436_54p_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + + + + + +static int __init cs6436_54p_fan_init(void) +{ + int ret; + + cig_cpld_write_register(0x40, duty_cycle_to_reg_val(50)); + + ret = platform_driver_register(&cs6436_54p_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct cs6436_54p_fan_data), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&cs6436_54p_fan_driver); + goto exit; + } + + mutex_init(&fan_data->update_lock); + fan_data->valid = 0; + + fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fan_data->pdev)) { + ret = PTR_ERR(fan_data->pdev); + platform_driver_unregister(&cs6436_54p_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit cs6436_54p_fan_exit(void) +{ + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&cs6436_54p_fan_driver); + kfree(fan_data); +} + +MODULE_AUTHOR("CIG"); +MODULE_DESCRIPTION("cs6436_54p_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(cs6436_54p_fan_init); +module_exit(cs6436_54p_fan_exit); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436_54p_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-led.c b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-led.c new file mode 100644 index 000000000000..74c8b6d0b10e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-led.c @@ -0,0 +1,594 @@ +/* + * A hwmon driver for the CIG cs6436-54P LED + * + * Copyright (C) 2018 Cambridge, Inc. + + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int cig_cpld_write_register(u8 reg_off, u8 val); + +extern int cig_cpld_read_register(u8 reg_off, u8 *val); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "cs6436_54p_led" + +struct cs6436_54p_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[6]; /* 0: system & location + 1: PSU1 &PSU12 + 2: fan & management + 3: console & ToD + 4-5 : fan1-fan5*/ +}; + +static struct cs6436_54p_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_TYPE_PSU1_REG_MASK 0x0C +#define LED_MODE_PSU1_GREEN_MASK 0x08 +#define LED_MODE_PSU1_RED_MASK 0x04 +#define LED_MODE_PSU1_AMBER_MASK 0x0C +#define LED_MODE_PSU1_OFF_MASK 0x00 + +#define LED_TYPE_PSU2_REG_MASK 0x30 +#define LED_MODE_PSU2_GREEN_MASK 0x20 +#define LED_MODE_PSU2_RED_MASK 0x10 +#define LED_MODE_PSU2_AMBER_MASK 0x30 +#define LED_MODE_PSU2_OFF_MASK 0x00 + +#define LED_TYPE_SYS_REG_MASK 0xF0 +#define LED_MODE_SYS_GREEN_MASK 0x40 +#define LED_MODE_SYS_RED_MASK 0x20 +#define LED_MODE_SYS_AMBER_MASK 0x60 +#define LED_MODE_SYS_AMBER_FLASHING_MASK 0x70 +#define LED_MODE_SYS_OFF_MASK 0x00 + +#define LED_TYPE_RES_REG_MASK 0x0F +#define LED_MODE_RES_GREEN_MASK 0x04 +#define LED_MODE_RES_RED_MASK 0x02 +#define LED_MODE_RES_AMBER_MASK 0x06 +#define LED_MODE_RES_AMBER_FLASHING_MASK 0x07 +#define LED_MODE_RES_OFF_MASK 0x00 + +#define LED_TYPE_FAN_REG_MASK 0x03 +#define LED_MODE_FAN_GREEN_MASK 0x02 +#define LED_MODE_FAN_RED_MASK 0x01 +#define LED_MODE_FAN_AMBER_MASK 0x03 +#define LED_MODE_FAN_OFF_MASK 0x00 + +#define LED_TYPE_FAN1_REG_MASK 0x03 +#define LED_TYPE_FAN2_REG_MASK 0x0C +#define LED_TYPE_FAN3_REG_MASK 0x30 +#define LED_TYPE_FAN4_REG_MASK 0xC0 +#define LED_TYPE_FAN5_REG_MASK 0x03 + +#define LED_MODE_FANX_GREEN_MASK 0x02 +#define LED_MODE_FANX_RED_MASK 0x01 +#define LED_MODE_FANX_AMBER_MASK 0x03 +#define LED_MODE_FANX_OFF_MASK 0x00 + +enum led_type { + LED_TYPE_SYS, + LED_TYPE_PSU2, + LED_TYPE_PSU1, + LED_TYPE_FAN, + LED_TYPE_FAN1, + LED_TYPE_FAN2, + LED_TYPE_FAN3, + LED_TYPE_FAN4, + LED_TYPE_FAN5, +}; + +static const u8 led_reg[] = { + 0x30, /* system & reserved*/ + 0x31, /* fan & PSU1 & PSU2 */ + 0x32, /* FAN5 LED */ + 0x33, /* FAN1-4 LED */ +}; + + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_GREEN_FLASHING, + LED_MODE_AMBER_FLASHING, + LED_MODE_RED_FLASHING, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + int type_mask; + enum led_light_mode mode; + int mode_mask; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_RED, LED_MODE_PSU1_RED_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK}, + +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_RED, LED_MODE_PSU2_RED_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK}, + +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_GREEN, LED_MODE_SYS_GREEN_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_AMBER, LED_MODE_SYS_AMBER_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_RED, LED_MODE_SYS_RED_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_AMBER_FLASHING, LED_MODE_SYS_AMBER_FLASHING_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_OFF, LED_MODE_SYS_OFF_MASK}, + +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_RED, LED_MODE_FAN_RED_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK}, + +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +}; + +struct fanx_info_s { + u8 cname; /* device name */ + enum led_type type; + u8 reg_id; /* map to led_reg & reg_val */ +}; + +static struct fanx_info_s fanx_info[] = { + {'1', LED_TYPE_FAN1, 3}, + {'2', LED_TYPE_FAN2, 3}, + {'3', LED_TYPE_FAN3, 3}, + {'4', LED_TYPE_FAN4, 3}, + {'5', LED_TYPE_FAN5, 2}, +}; + + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + break; + } + + return reg_val; +} + +static void cs6436_54p_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting cs6436_54p_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + u8 status; + cig_cpld_read_register(led_reg[i], &status); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void cs6436_54p_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + u8 reg_val; + mutex_lock(&ledctl->update_lock); + + cig_cpld_read_register(reg, ®_val); + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + + cig_cpld_write_register(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void cs6436_54p_led_fanx_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (led_cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + + cs6436_54p_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1); + return; + } + } +} + + +static enum led_brightness cs6436_54p_led_fanx_get(struct led_classdev *cdev) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + cs6436_54p_led_update(); + return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]); + } + } + + return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[5]); +} + + +static void cs6436_54p_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs6436_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness cs6436_54p_led_psu1_get(struct led_classdev *cdev) +{ + cs6436_54p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void cs6436_54p_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs6436_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness cs6436_54p_led_psu2_get(struct led_classdev *cdev) +{ + cs6436_54p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static void cs6436_54p_led_sys_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs6436_54p_led_set(led_cdev, led_light_mode,led_reg[0], LED_TYPE_SYS); +} + +static enum led_brightness cs6436_54p_led_sys_get(struct led_classdev *cdev) +{ + cs6436_54p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_SYS, ledctl->reg_val[0]); +} + + +static enum led_brightness cs6436_54p_led_fan_get(struct led_classdev *cdev) +{ + cs6436_54p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[1]); +} + +static void cs6436_54p_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs6436_54p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_FAN); +} + + +static struct led_classdev cs6436_54p_leds[] = { + [LED_TYPE_SYS] = { + .name = "cs6436_54p_led::sys", + .default_trigger = "unused", + .brightness_set = cs6436_54p_led_sys_set, + .brightness_get = cs6436_54p_led_sys_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "cs6436_54p_led::fan", + .default_trigger = "unused", + .brightness_set = cs6436_54p_led_fan_set, + .brightness_get = cs6436_54p_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + + [LED_TYPE_PSU1] = { + .name = "cs6436_54p_led::psu1", + .default_trigger = "unused", + .brightness_set = cs6436_54p_led_psu1_set, + .brightness_get = cs6436_54p_led_psu1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "cs6436_54p_led::psu2", + .default_trigger = "unused", + .brightness_set = cs6436_54p_led_psu2_set, + .brightness_get = cs6436_54p_led_psu2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + + [LED_TYPE_FAN1] = { + .name = "cs6436_54p_led::fan1", + .default_trigger = "unused", + .brightness_set = cs6436_54p_led_fanx_set, + .brightness_get = cs6436_54p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN2] = { + .name = "cs6436_54p_led::fan2", + .default_trigger = "unused", + .brightness_set = cs6436_54p_led_fanx_set, + .brightness_get = cs6436_54p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN3] = { + .name = "cs6436_54p_led::fan3", + .default_trigger = "unused", + .brightness_set = cs6436_54p_led_fanx_set, + .brightness_get = cs6436_54p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN4] = { + .name = "cs6436_54p_led::fan4", + .default_trigger = "unused", + .brightness_set = cs6436_54p_led_fanx_set, + .brightness_get = cs6436_54p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN5] = { + .name = "cs6436_54p_led::fan5", + .default_trigger = "unused", + .brightness_set = cs6436_54p_led_fanx_set, + .brightness_get = cs6436_54p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + } +}; + +static int cs6436_54p_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(cs6436_54p_leds); i++) { + led_classdev_suspend(&cs6436_54p_leds[i]); + } + + return 0; +} + +static int cs6436_54p_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(cs6436_54p_leds); i++) { + led_classdev_resume(&cs6436_54p_leds[i]); + } + + return 0; +} + +static int cs6436_54p_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(cs6436_54p_leds); i++) { + ret = led_classdev_register(&pdev->dev, &cs6436_54p_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(cs6436_54p_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&cs6436_54p_leds[i]); + } + } + + return ret; +} + +static int cs6436_54p_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(cs6436_54p_leds); i++) { + led_classdev_unregister(&cs6436_54p_leds[i]); + } + + return 0; +} + +static struct platform_driver cs6436_54p_led_driver = { + .probe = cs6436_54p_led_probe, + .remove = cs6436_54p_led_remove, + .suspend = cs6436_54p_led_suspend, + .resume = cs6436_54p_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int cs6436_54p_led_default(void) +{ + cig_cpld_write_register(0x30, 0x40);// system green led solid on +} + +static int __init cs6436_54p_led_init(void) +{ + int ret; + + ret = platform_driver_register(&cs6436_54p_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct cs6436_54p_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&cs6436_54p_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&cs6436_54p_led_driver); + kfree(ledctl); + goto exit; + } + + cs6436_54p_led_default(); + +exit: + return ret; +} + +static void __exit cs6436_54p_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&cs6436_54p_led_driver); + kfree(ledctl); +} + +module_init(cs6436_54p_led_init); +module_exit(cs6436_54p_led_exit); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436_54p_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-psu.c b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-psu.c new file mode 100644 index 000000000000..e8fc896ea13a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-psu.c @@ -0,0 +1,943 @@ +/* + * A hwmon driver for the CIG cs6436-54P Power Module + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-algo-lpc.h" + + + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Address scanned */ +static const unsigned short normal_i2c[] = {I2C_CLIENT_END }; + +/* This is additional data */ +struct cs6436_54p_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; /* In jiffies */ + + /* Registers value */ + u8 vout_mode; + u16 v_in; + u16 v_out; + u16 i_in; + u16 i_out; + u16 p_in; + u16 p_out; + u16 temp_input[3]; + u8 temp_fault; + u8 fan_fault; + u16 fan_duty_cycle[2]; + u16 fan_speed[2]; + u8 mfr_id[8]; + u8 mfr_model[20]; + u8 mfr_serial[20]; + u8 psu_is_present; + u8 psu_is_good; + struct i2c_client *client; + struct bin_attribute *bin; /* eeprom data */ +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count); +static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_fan_fault(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_fan_warning(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_temp_fault(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_temp_warning(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_vout_data(struct device *dev, struct device_attribute *dev_attr, char *buf); +static int cs6436_54p_psu_read_byte(struct i2c_client *client, u8 reg); +static int cs6436_54p_psu_read_word(struct i2c_client *client, u8 reg); +static int cs6436_54p_psu_write_word(struct i2c_client *client, u8 reg, u16 value); +static int cs6436_54p_psu_read_block(struct i2c_client *client, u8 command, u8 *data, int data_len); +static struct cs6436_54p_psu_data *cs6436_54p_psu_update_device(struct device *dev); +static ssize_t for_ascii(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf); + +enum cs6436_54p_psu_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_TEMP2_INPUT, + PSU_TEMP3_INPUT, + PSU_TEMP_FAULT, + PSU_TEMP_WARN, + PSU_FAN1_FAULT, + PSU_FAN1_WARN, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_SERIAL, + PSU_PRESENT, + PSU_P_GOOD, +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + + bool is_negative = valid_data >> (valid_bit - 1); + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct i2c_client *client = to_i2c_client(dev); + struct cs6436_54p_psu_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + if (data->valid != 1) + { + return -ENODEV; + } + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cs6436_54p_psu_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + if (data->valid != 1) + { + return -ENODEV; + } + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_TEMP2_INPUT: + value = data->temp_input[1]; + break; + case PSU_TEMP3_INPUT: + value = data->temp_input[2]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_fan_fault(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev); + + if (data->valid != 1) + { + return -ENODEV; + } + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t for_fan_warning(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev); + + if (data->valid != 1) + { + return -ENODEV; + } + + u8 shift = (attr->index == PSU_FAN1_WARN) ? 5 : 4; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t for_temp_fault(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev); + + if (data->valid != 1) + { + return -ENODEV; + } + + + + return sprintf(buf, "%d\n", data->temp_fault >> 7); +} + +static ssize_t for_temp_warning(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev); + if (data->valid != 1) + { + return -ENODEV; + } + + + return sprintf(buf, "%d\n", data->temp_fault >> 6); +} +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + if (data->valid != 1) + { + return -ENODEV; + } + + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", ((mantissa * multiplier) >> (-exponent))); +} + +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev); + u8 *ptr = NULL; + + if (data->valid != 1) + { + return -ENODEV; + } + + switch (attr->index) { + case PSU_MFR_ID: + ptr = data->mfr_id + 1; + break; + case PSU_MFR_MODEL: + ptr = data->mfr_model + 1; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial + 1; + break; + default: + return 0; + } + return sprintf(buf, "%s\n", ptr); +} + + +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_54p_psu_data *data = cs6436_54p_psu_update_device(dev); + u8 *ptr = NULL; + + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = data->psu_is_present; + } + else { /* PSU_POWER_GOOD */ + if (!data->valid) { + return -ENODEV; + } + + status = data->psu_is_good; + } + + return sprintf(buf, "%d\n", status); +} + + +static int cs6436_54p_psu_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cs6436_54p_psu_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cs6436_54p_psu_write_word(struct i2c_client *client, u8 reg, \ + u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags |= I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, reg, + I2C_SMBUS_WORD_DATA, &data); + +} + +static int cs6436_54p_psu_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, + data); + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; +abort: + return result; + +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + + + +#define EEPROM_NAME "psu_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ + +/* Platform dependent --- */ +static ssize_t psu_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ + int status, retry = 3; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(100); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; + +} + + +static ssize_t psu_page_write(struct i2c_client *client,const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + + + while (count) { + ssize_t status; + + status = psu_eeprom_write(client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + + return retval; +} + + + +static ssize_t psu_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct cs6436_54p_psu_data *data; + ssize_t retval = 0; + struct i2c_client *client; + + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + client = to_i2c_client(container_of(kobj, struct device, kobj)); + + mutex_lock(&data->update_lock); + retval = psu_page_write(client, buf, off, count); + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t psu_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int status, retry = 3; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(100); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + +abort: + return status; +} + + + +static ssize_t psu_page_read(struct i2c_client *client,char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + printk("Count = 0, return"); + return count; + } + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + + + while (count) { + ssize_t status; + + status = psu_eeprom_read(client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + + return retval; + +} + + +static ssize_t psu_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct cs6436_54p_psu_data *data; + struct i2c_client *client; + ssize_t retval = 0; + + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + client = to_i2c_client(container_of(kobj, struct device, kobj)); + mutex_lock(&data->update_lock); + retval = psu_page_read(client, buf, off, count); + mutex_unlock(&data->update_lock); + + return retval; +} + + + +static int psu_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = psu_bin_read; + eeprom->write = psu_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + + +static int psu_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + + +static int psu_i2c_check_functionality(struct i2c_client *client) +{ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK); +} + + + +static int psu_eeprom_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + int status; + + struct cs6436_54p_psu_data *data; + + if (!psu_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + data->bin = kzalloc(sizeof(struct bin_attribute), GFP_KERNEL); + if (!data->bin) { + status = -ENOMEM; + goto eeprom_bin_error; + } + + /* init eeprom */ + status = psu_sysfs_eeprom_init(&client->dev.kobj, data->bin); + if (status) { + status = -ENOMEM; + goto sys_init_error; + } + + dev_info(&client->dev, "psu eeprom '%s'\n", client->name); + + return 0; + + sys_init_error: + kfree(data->bin); + + eeprom_bin_error: + kfree(data); + + exit: + return status; +} + + + + +static struct cs6436_54p_psu_data *cs6436_54p_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cs6436_54p_psu_data *data = i2c_get_clientdata(client); + + + mutex_lock(&data->update_lock); + + + if (time_after(jiffies, data->last_updated)) { + int i, status; + u8 command; + struct reg_data_byte regs_byte[] = { + {0x20, &data->vout_mode}, + {0x81, &data->fan_fault}, + {0x7d, &data->temp_fault}, + }; + struct reg_data_word regs_word[] = { + {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x90, &(data->fan_speed[0])}, + }; + data->valid = 1; + + dev_dbg(&client->dev, "start data update\n"); + + /* one milliseconds from now */ + data->last_updated = jiffies + HZ / 1000; + + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cs6436_54p_psu_read_byte(client, + regs_byte[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + data->valid = 0; + } else { + *(regs_byte[i].value) = status; + } + } + + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = cs6436_54p_psu_read_word(client, + regs_word[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + data->valid = 0; + } else { + *(regs_word[i].value) = status; + } + } + + command = 0x99; /* PSU mfr_id */ + status = cs6436_54p_psu_read_block(client, command, + data->mfr_id, ARRAY_SIZE(data->mfr_id) - 1); + data->mfr_id[ARRAY_SIZE(data->mfr_id) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + memset(data->mfr_id, 0, sizeof(data->mfr_id)); + data->valid = 0; + } + + command = 0x9a; /* PSU mfr_model */ + status = cs6436_54p_psu_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + memset(data->mfr_model, 0, sizeof(data->mfr_id)); + data->valid = 0; + } + + command = 0x9e; /* PSU mfr_serial */ + status = cs6436_54p_psu_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + memset(data->mfr_serial, 0, sizeof(data->mfr_id)); + data->valid = 0; + } + + data->psu_is_present = strlen(data->mfr_id) > 1 ? 1:0; + if(data->psu_is_present) + { + data->psu_is_good = ((data->fan_fault) || (data->temp_fault))? 0:1; + } + else + { + data->valid = 0; + data->psu_is_good = 0; + } + } + + mutex_unlock(&data->update_lock); + + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp2_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp3_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP3_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, for_temp_fault, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_temp_warning, S_IRUGO, for_temp_warning, NULL, PSU_TEMP_WARN); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, for_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_warning, S_IRUGO, for_fan_warning, NULL, PSU_FAN1_WARN); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, for_linear_data, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, for_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, for_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, for_status, NULL, PSU_P_GOOD); + + + +static struct attribute *cs6436_54p_psu_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_temp2_input.dev_attr.attr, + &sensor_dev_attr_psu_temp3_input.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_temp_warning.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_warning.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static const struct attribute_group cs6436_54p_psu_group = { + .attrs = cs6436_54p_psu_attributes, +}; + + +static int psu_register_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int status; + + + struct cs6436_54p_psu_data *data; + + if (!psu_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cs6436_54p_psu_group); + if (status) + goto exit_sysfs_create_group; + + cs6436_54p_sysfs_add_client(client); + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_hwmon_device_register; + } + + /* init eeprom */ + + return 0; + + exit_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &cs6436_54p_psu_group); + exit_sysfs_create_group: + kfree(data); + exit: + return status; + +} + + +static int cs6436_54p_psu_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int status; + + if((client->addr == 0x52) ||(client->addr == 0x53)) + { + status = psu_eeprom_probe(client, id); + } + else if((client->addr == 0x5a) ||(client->addr == 0x5b)) + { + status = psu_register_probe(client, id); + } + return status; +} + +static int cs6436_54p_psu_remove(struct i2c_client *client) +{ + cs6436_54p_sysfs_remove_client(client); + + if((client->addr == 0x52) ||(client->addr == 0x53)) + { + struct cs6436_54p_psu_data *data; + data = i2c_get_clientdata(client); + psu_sysfs_eeprom_cleanup(&client->dev.kobj,data->bin); + kfree(data); + } + else if((client->addr == 0x5a) ||(client->addr == 0x5b)) + { + struct cs6436_54p_psu_data *data; + data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cs6436_54p_psu_group); + kfree(data); + } + + return 0; +} + +enum psu_index +{ + cs6436_54p_psu1, + cs6436_54p_psu2 +}; + +static const struct i2c_device_id cs6436_54p_psu_id[] = { + { "cs6436_54p_psu1", cs6436_54p_psu1 }, + { "cs6436_54p_psu2", cs6436_54p_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs6436_54p_psu_id); + +static struct i2c_driver cs6436_54p_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cs6436_54p_psu", + }, + .probe = cs6436_54p_psu_probe, + .remove = cs6436_54p_psu_remove, + .id_table = cs6436_54p_psu_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(cs6436_54p_psu_driver); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436_54p_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-sfp.c b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-sfp.c new file mode 100644 index 000000000000..5d02bd849a5f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-sfp.c @@ -0,0 +1,1713 @@ +/* + * A hwmon driver for the CIG cs6436-54P SFP Module + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-algo-lpc.h" + +#define DRIVER_NAME "cs6436_54p_sfp" /* Platform dependent */ + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) +#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 +#define QSFP_RESET_ADDR 0x1b +#define QSFP_INTER_ADDR 0x1a +#define QSFP_LPMODE_ADDR 0x1c + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +extern int cig_cpld_read_register(u8 reg_off, u8 *val); +extern int cig_cpld_write_register(u8 reg_off, u8 val); + +static ssize_t qsfp_reset_read(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_reset_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_inter_read(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_lpmode_read(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_lpmode_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL, + QSFPRESET, + QSFPINT, + QSFPLPMODE +}; + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static SENSOR_DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, qsfp_reset_read, qsfp_reset_write, QSFPRESET); +static SENSOR_DEVICE_ATTR(sfp_inter, S_IRUGO, qsfp_inter_read, NULL, QSFPINT); +static SENSOR_DEVICE_ATTR(sfp_lpmode, S_IWUSR | S_IRUGO, qsfp_lpmode_read, qsfp_lpmode_write, QSFPLPMODE); +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + &sensor_dev_attr_sfp_reset.dev_attr.attr, + &sensor_dev_attr_sfp_inter.dev_attr.attr, + &sensor_dev_attr_sfp_lpmode.dev_attr.attr, + NULL +}; + +/* SFP msa attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); +static struct attribute *sfp_msa_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + NULL +}; + +/* SFP ddm attributes for sysfs */ +static struct attribute *sfp_ddm_attributes[] = { + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +cs6436_54p_sfp1, cs6436_54p_sfp2, cs6436_54p_sfp3, cs6436_54p_sfp4, +cs6436_54p_sfp5, cs6436_54p_sfp6, cs6436_54p_sfp7, cs6436_54p_sfp8, +cs6436_54p_sfp9, cs6436_54p_sfp10, cs6436_54p_sfp11, cs6436_54p_sfp12, +cs6436_54p_sfp13, cs6436_54p_sfp14, cs6436_54p_sfp15, cs6436_54p_sfp16, +cs6436_54p_sfp17, cs6436_54p_sfp18, cs6436_54p_sfp19, cs6436_54p_sfp20, +cs6436_54p_sfp21, cs6436_54p_sfp22, cs6436_54p_sfp23, cs6436_54p_sfp24, +cs6436_54p_sfp25, cs6436_54p_sfp26, cs6436_54p_sfp27, cs6436_54p_sfp28, +cs6436_54p_sfp29, cs6436_54p_sfp30, cs6436_54p_sfp31, cs6436_54p_sfp32, +cs6436_54p_sfp33, cs6436_54p_sfp34, cs6436_54p_sfp35, cs6436_54p_sfp36, +cs6436_54p_sfp37, cs6436_54p_sfp38, cs6436_54p_sfp39, cs6436_54p_sfp40, +cs6436_54p_sfp41, cs6436_54p_sfp42, cs6436_54p_sfp43, cs6436_54p_sfp44, +cs6436_54p_sfp45, cs6436_54p_sfp46, cs6436_54p_sfp47, cs6436_54p_sfp48, +cs6436_54p_sfp49, cs6436_54p_sfp50, cs6436_54p_sfp51, cs6436_54p_sfp52, +cs6436_54p_sfp53, cs6436_54p_sfp54, cs6436_54p_sfp55, cs6436_54p_sfp56 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { +I2C_DEV_ID(cs6436_54p_sfp1), +I2C_DEV_ID(cs6436_54p_sfp2), +I2C_DEV_ID(cs6436_54p_sfp3), +I2C_DEV_ID(cs6436_54p_sfp4), +I2C_DEV_ID(cs6436_54p_sfp5), +I2C_DEV_ID(cs6436_54p_sfp6), +I2C_DEV_ID(cs6436_54p_sfp7), +I2C_DEV_ID(cs6436_54p_sfp8), +I2C_DEV_ID(cs6436_54p_sfp9), +I2C_DEV_ID(cs6436_54p_sfp10), +I2C_DEV_ID(cs6436_54p_sfp11), +I2C_DEV_ID(cs6436_54p_sfp12), +I2C_DEV_ID(cs6436_54p_sfp13), +I2C_DEV_ID(cs6436_54p_sfp14), +I2C_DEV_ID(cs6436_54p_sfp15), +I2C_DEV_ID(cs6436_54p_sfp16), +I2C_DEV_ID(cs6436_54p_sfp17), +I2C_DEV_ID(cs6436_54p_sfp18), +I2C_DEV_ID(cs6436_54p_sfp19), +I2C_DEV_ID(cs6436_54p_sfp20), +I2C_DEV_ID(cs6436_54p_sfp21), +I2C_DEV_ID(cs6436_54p_sfp22), +I2C_DEV_ID(cs6436_54p_sfp23), +I2C_DEV_ID(cs6436_54p_sfp24), +I2C_DEV_ID(cs6436_54p_sfp25), +I2C_DEV_ID(cs6436_54p_sfp26), +I2C_DEV_ID(cs6436_54p_sfp27), +I2C_DEV_ID(cs6436_54p_sfp28), +I2C_DEV_ID(cs6436_54p_sfp29), +I2C_DEV_ID(cs6436_54p_sfp30), +I2C_DEV_ID(cs6436_54p_sfp31), +I2C_DEV_ID(cs6436_54p_sfp32), +I2C_DEV_ID(cs6436_54p_sfp33), +I2C_DEV_ID(cs6436_54p_sfp34), +I2C_DEV_ID(cs6436_54p_sfp35), +I2C_DEV_ID(cs6436_54p_sfp36), +I2C_DEV_ID(cs6436_54p_sfp37), +I2C_DEV_ID(cs6436_54p_sfp38), +I2C_DEV_ID(cs6436_54p_sfp39), +I2C_DEV_ID(cs6436_54p_sfp40), +I2C_DEV_ID(cs6436_54p_sfp41), +I2C_DEV_ID(cs6436_54p_sfp42), +I2C_DEV_ID(cs6436_54p_sfp43), +I2C_DEV_ID(cs6436_54p_sfp44), +I2C_DEV_ID(cs6436_54p_sfp45), +I2C_DEV_ID(cs6436_54p_sfp46), +I2C_DEV_ID(cs6436_54p_sfp47), +I2C_DEV_ID(cs6436_54p_sfp48), +I2C_DEV_ID(cs6436_54p_sfp49), +I2C_DEV_ID(cs6436_54p_sfp50), +I2C_DEV_ID(cs6436_54p_sfp51), +I2C_DEV_ID(cs6436_54p_sfp52), +I2C_DEV_ID(cs6436_54p_sfp53), +I2C_DEV_ID(cs6436_54p_sfp54), +I2C_DEV_ID(cs6436_54p_sfp55), +I2C_DEV_ID(cs6436_54p_sfp56), +{ /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[6]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss + 3 => device id + 4 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 5 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + + + +static int cig_cpld_write_sfp_register(u8 sfp_reg_addr, u8 sfp_write_reg_data) +{ + u8 sfp_read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, sfp_reg_addr << 1); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_TX, sfp_write_reg_data); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + do{ + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &sfp_read_status); + udelay(60); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(sfp_read_status != 0x02); + + if(wait_time_out == 0) + return -1; + + return 1; +} + + +static int cig_cpld_read_sfp_register(u8 sfp_reg_addr, u8 *sfp_read_reg_data) +{ + u8 sfp_read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, sfp_reg_addr << 1 | 1); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + do{ + udelay(60); + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &sfp_read_status); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(sfp_read_status != 0x01); + + cig_cpld_read_register(ADDR_REG_SFP_STATUS_RX,sfp_read_reg_data); + + if(wait_time_out == 0) + return -1; + + return 1; +} + + + + + + +/* Platform dependent +++ */ +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + int i = 0, j = 0, status = -1; + unsigned char cpld_reg_data = 0,cpld_reg_addr = 0; + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + data->present = 0; + + udelay(6000); + + /* Read present status of port 1~48(SFP port) */ + for (i = 0; i < 6; i++) { + cpld_reg_addr = 1 + i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->present |= (u64)cpld_reg_data << (i*8); + + DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); + } + + /* Read present status of port 49-56(QSFP port) */ + cpld_reg_addr = 25; + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + else { + data->present |= (u64)cpld_reg_data << 48; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0, j = 0; + int status = -1; + unsigned char cpld_reg_data = 0,cpld_reg_addr = 0; + + if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { + return data; + } + + DEBUG_PRINT("Starting cs6436_54p sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->msa->valid = 0; + memset(data->msa->status, 0, sizeof(data->msa->status)); + + udelay(6000); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 6; i++) { + cpld_reg_addr = 13+i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->msa->status[0] |= (u64)cpld_reg_data << (i * 8); + + DEBUG_PRINT("tx rx status[0] = 0x%lx\r\n", data->msa->status[0]); + } + + + for (i = 0; i < 6; i++) { + cpld_reg_addr = 19+i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->msa->status[1] |= (u64)cpld_reg_data << (i * 8); + + DEBUG_PRINT("tx rx status[1] = 0x%lx\r\n", data->msa->status[1]); + } + + for (i = 0; i < 6; i++) { + cpld_reg_addr = 7+i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->msa->status[2] |= (u64)cpld_reg_data << (i * 8); + + DEBUG_PRINT("tx rx status[2] = 0x%lx\r\n", data->msa->status[2]); + } + + data->msa->valid = 1; + data->msa->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + unsigned char cpld_reg_data = 0,cpld_reg_addr = 0,cpld_reg_bit = 0,cpld_reg_val = 0; + long disable; + int error; + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_set_tx_disable(dev, da, buf, count); + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + + if(data->port <= 48) { + cpld_reg_addr = 19 + data->port / 8; + cpld_reg_bit = 1 << ((data->port) % 8); + } + + /* Read current status */ + error = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + + /* Update tx_disable status */ + if (disable) { + data->msa->status[1] |= BIT_INDEX(data->port); + cpld_reg_data |= cpld_reg_bit; + } + else { + data->msa->status[1] &= ~ BIT_INDEX(data->port); + cpld_reg_data &= ~cpld_reg_bit; + } + + error = cig_cpld_write_sfp_register(cpld_reg_addr,cpld_reg_data); + + mutex_unlock(&data->update_lock); + return count; +} +/* Platform dependent --- */ + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = sfp_update_present(client); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + return !(data->present & BIT_INDEX(data->port)); /* Platform dependent */ +} + +/* Platform dependent +++ */ +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if (PRESENT_ALL == attr->index) { + int i; + u8 values[7] = {0}; + struct sfp_port_data *data = sfp_update_present(client); + + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = ~(u8)(data->present >> (i * 8)); + } + + /* Return values 1 -> 56 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6]); + } + else { + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + /* PRESENT */ + return sprintf(buf, "%d\n", present); + } +} +/* Platform dependent --- */ + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = buf; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + if (!present) { + /* port is not present */ + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + DEBUG_PRINT(""); + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + DEBUG_PRINT("Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + DEBUG_PRINT(""); + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + DEBUG_PRINT(""); + goto exit; + } + } + msleep(200); + DEBUG_PRINT(""); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + DEBUG_PRINT(""); + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + DEBUG_PRINT(""); + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + +exit: + DEBUG_PRINT(""); + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t qsfp_inter_read(struct device *dev, struct device_attribute *da, char *buf) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_INTER_ADDR, &cpld_reg_data); + index = data->port - 48; + index = 1 << index; + val = (cpld_reg_data & index) > 0 ? 1 : 0; + + printk("inter read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t qsfp_reset_read(struct device *dev, struct device_attribute *da, char *buf) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_RESET_ADDR, &cpld_reg_data); + index = data->port - 48; + index = 1 << index; + val = (cpld_reg_data & index) > 0 ? 1 : 0; + + printk("reset read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_reset_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + long usrdata; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + ret = kstrtol(buf, 10, &usrdata); + if (ret) { + return ret; + } + + usrdata = usrdata > 0 ? 1 : 0; + index = data->port - 48; + + DEBUG_PRINT("usrdata = %u, index = %hhu\n", usrdata, index); + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_RESET_ADDR, &cpld_reg_data); + if (ret == 1) + { + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + cpld_reg_data &= ~(1 << index); + cpld_reg_data |= usrdata << index; + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + ret = cig_cpld_write_sfp_register(QSFP_RESET_ADDR, cpld_reg_data); + if (1 != ret) + { + DEBUG_PRINT("write failed\n"); + } + } + else + { + DEBUG_PRINT("read failed\n"); + } + + mutex_unlock(&data->update_lock); + + if (ret != 1) + return -1; + + return count; +} + + + + +static ssize_t qsfp_lpmode_read(struct device *dev, struct device_attribute *da, char *buf) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_LPMODE_ADDR, &cpld_reg_data); + index = data->port - 48; + index = 1 << index; + val = (cpld_reg_data & index) > 0 ? 1 : 0; + + printk("lpmode read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_lpmode_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + long usrdata; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + ret = kstrtol(buf, 10, &usrdata); + if (ret) { + return ret; + } + + usrdata = usrdata > 0 ? 1 : 0; + index = data->port - 48; + + DEBUG_PRINT("usrdata = %u, index = %hhu\n", usrdata, index); + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_LPMODE_ADDR, &cpld_reg_data); + if (ret == 1) + { + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + cpld_reg_data &= ~(1 << index); + cpld_reg_data |= usrdata << index; + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + ret = cig_cpld_write_sfp_register(QSFP_LPMODE_ADDR, cpld_reg_data); + if (1 != ret) + { + DEBUG_PRINT("write failed\n"); + } + } + else + { + DEBUG_PRINT("read failed\n"); + } + + mutex_unlock(&data->update_lock); + + if (ret != 1) + return -1; + + return count; +} + + + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + int present; + u8 val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT(""); + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + DEBUG_PRINT(""); + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + DEBUG_PRINT(""); + data = qsfp_update_tx_rx_status(dev); + DEBUG_PRINT(""); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + DEBUG_PRINT(""); + switch (attr->index) { + case TX_FAULT: + val = !!(data->qsfp->status[2] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + case TX_DISABLE: + val = data->qsfp->status[1] & 0xF; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + case RX_LOS: + val = !!(data->qsfp->status[0] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); + break; + default: + break; + } + + DEBUG_PRINT(""); + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (!status) { + /* port is not present */ + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + mutex_lock(&data->update_lock); + + if (attr->index == TX_DISABLE) { + data->qsfp->status[1] = disable & 0xF; + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (status == 0) { + /* port is not present */ + return -ENODEV; + } + + status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (unlikely(status < 0)) { + return status; + } + + return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK)); +} + +/* Platform dependent +++ */ +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("driver type = (%d)", data->driver_type); + if (data->driver_type == DRIVER_TYPE_QSFP) { + DEBUG_PRINT(""); + return qsfp_show_tx_rx_status(dev, da, buf); + } + + DEBUG_PRINT(""); + data = sfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + if(attr->index == RX_LOS_ALL) { + int i = 0; + u8 values[6] = {0}; + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = (u8)(data->msa->status[2] >> (i * 8)); + } + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + case RX_LOS: + index = 2; + break; + default: + break; + } + + val = !!(data->msa->status[index] & BIT_INDEX(data->port)); + return sprintf(buf, "%d\n", val); +} +/* Platform dependent --- */ +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, command, *data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return 1; +#endif + + +} + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return status; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + status = 1; + +abort: + return status; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + cs6436_54p_sysfs_add_client(client); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + + /* Bring QSFPs out of reset */ + //cig_lpc_write(0x62, 0x15, 0x3F); + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +/* Platform dependent +++ */ +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if (dev_id->driver_data >= cs6436_54p_sfp1 && dev_id->driver_data <= cs6436_54p_sfp48) { + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_SFP_MSA; + return sfp_msa_probe(client, dev_id, &data->msa); + } + else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_SFP_DDM; + return sfp_ddm_probe(client, dev_id, &data->ddm); + } + } + else { /* cs6436_54p_sfp49 ~ cs6436_54p_sfp56 */ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); + } + } + + return -ENODEV; +} +/* Platform dependent --- */ + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + cs6436_54p_sysfs_remove_client(client); + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver cs6436_54p_sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(cs6436_54p_sfp_driver); + + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436_54p_sfp driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-sysfs.c b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-sysfs.c new file mode 100644 index 000000000000..1383fcfd40f3 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/modules/x86-64-cig-cs6436-54p-sysfs.c @@ -0,0 +1,335 @@ +/* + * A hwmon driver for the CIG cs6436-54P sysfs Module + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i2c-algo-lpc.h" + + +static LIST_HEAD(sysfs_client_list); +static struct mutex list_lock; + +struct sysfs_client_node { + struct i2c_client *client; + struct list_head list; +}; + +#define DEVICE_NAME "cigfs" +static int dev_major; +static struct class *dev_class; +static struct cdev *dev_cdev; +static struct device *dev_device; +static struct class *psu_class; +static struct class *sfp_class; + + +void cs6436_54p_sysfs_add_client(struct i2c_client *client) +{ + struct sysfs_client_node *node = kzalloc(sizeof(struct sysfs_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate sysfs_client_node (0x%x)\n", client->addr); + return; + } + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &sysfs_client_list); + mutex_unlock(&list_lock); +} + +EXPORT_SYMBOL(cs6436_54p_sysfs_add_client); + +void cs6436_54p_sysfs_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct sysfs_client_node *sysfs_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &sysfs_client_list) + { + sysfs_node = list_entry(list_node, struct sysfs_client_node, list); + if (IS_ERR(sysfs_node)) + { + break; + } + if (sysfs_node->client == client) { + found = 1; + break; + } + } + if (found) { + list_del(list_node); + kfree(sysfs_node); + } + + mutex_unlock(&list_lock); +} + +EXPORT_SYMBOL(cs6436_54p_sysfs_remove_client); + +struct class * cs6436_54p_sysfs_create_symclass(char *cls_name) +{ + int rc = 0; + struct class *my_class; +/**************************************************************************************/ + my_class = class_create(THIS_MODULE,cls_name); + if (IS_ERR(my_class)) { + pr_err("failed to create my class\n"); + } + return my_class; + +/**************************************************************************************/ +} + +void cs6436_54p_sysfs_delete_symclass(struct class *my_class) +{ +/**************************************************************************************/ + + if (IS_ERR(my_class)) { + pr_err("Pointer is invaild\n"); + } + class_destroy(my_class); + +/**************************************************************************************/ +} + + + + + +int cs6436_54p_sysfs_create_symlink(struct class *my_class,char * driver_name,char *device_name) +{ + struct list_head *list_node = NULL; + struct sysfs_client_node *sysfs_node = NULL; + int ret = -EPERM; + int rc = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &sysfs_client_list) + { + sysfs_node = list_entry(list_node, struct sysfs_client_node, list); + if (!strcmp(sysfs_node->client->name,driver_name)) { + rc = sysfs_create_link(&my_class->p->subsys.kobj, &sysfs_node->client->dev.kobj,device_name); + if(rc) + { + pr_err("failed to create symlink %d\n",rc); + } + break; + } + } + mutex_unlock(&list_lock); + return ret; +} + + +int cs6436_54p_sysfs_delete_symlink(struct class *my_class,char * driver_name,char *device_name) +{ + struct list_head *list_node = NULL; + struct sysfs_client_node *sysfs_node = NULL; + int ret = -EPERM; + int rc = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &sysfs_client_list) + { + sysfs_node = list_entry(list_node, struct sysfs_client_node, list); + if (!strcmp(sysfs_node->client->name,driver_name)) { + sysfs_remove_link(&my_class->p->subsys.kobj,device_name); + break; + } + } + mutex_unlock(&list_lock); + return ret; +} + + +static int cs6436_54p_sysfs_open(struct inode *inode, struct file *file) +{ + return 0; +} + + + +static ssize_t cs6436_54p_sysfs_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) +{ + char str[10],name[18],port[8]; + int ret; + int i; + memset(str, 0, sizeof(str)); + ret = copy_from_user(str, buf, count); + if (ret) + { + printk(KERN_ERR "copy_from_user fail\n"); + return -EINVAL; + } + + if(!strncmp(str,"start",5)) + { + psu_class = cs6436_54p_sysfs_create_symclass("psu"); + cs6436_54p_sysfs_create_symlink(psu_class,"cs6436_54p_psu1","psu1"); + cs6436_54p_sysfs_create_symlink(psu_class,"cs6436_54p_psu2","psu2"); + sfp_class = cs6436_54p_sysfs_create_symclass("swps"); + for(i = 1; i <= 48;i++) + { + memset(name,0xff,sizeof(name)); + memset(port,0xff,sizeof(port)); + snprintf(name,sizeof(name),"cs6436_54p_sfp%d",i); + snprintf(port,sizeof(port),"port%d",i); + cs6436_54p_sysfs_create_symlink(sfp_class,name,port); + } + } + else if(!strncmp(str,"stop",4)) + { + cs6436_54p_sysfs_delete_symlink(psu_class,"cs6436_54p_psu1","psu1"); + cs6436_54p_sysfs_delete_symlink(psu_class,"cs6436_54p_psu2","psu2"); + cs6436_54p_sysfs_delete_symclass(psu_class); + + for(i = 1; i <= 48;i++) + { + memset(name,0xff,sizeof(name)); + memset(port,0xff,sizeof(port)); + snprintf(name,sizeof(name),"cs6436_54p_sfp%d",i); + snprintf(port,sizeof(port),"port%d",i); + cs6436_54p_sysfs_delete_symlink(sfp_class,name,port); + } + cs6436_54p_sysfs_delete_symclass(sfp_class); + } + return count; +} + + +static struct file_operations cs6436_54p_sysfs_fops = { + .owner = THIS_MODULE, + .open = cs6436_54p_sysfs_open, + .write = cs6436_54p_sysfs_write, +}; + + +static int __init cs6436_54p_sysfs_init(void) +{ + int result = 0; + int err = 0; + dev_t dev = MKDEV(dev_major, 0); + + if (dev_major) + result = register_chrdev_region(dev, 1, DEVICE_NAME); + else { + result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME); + dev_major = MAJOR(dev); + } + if (result < 0) + { + printk("unable to get major %d\n", dev_major); + err= -EINVAL; + } + printk("get major is %d\n", dev_major); + if (dev_major == 0) + dev_major = result; + + dev_cdev= kmalloc(sizeof(struct cdev), GFP_KERNEL); + if(IS_ERR(dev_cdev)) { + err= -ENOMEM; + } + + cdev_init(dev_cdev, &cs6436_54p_sysfs_fops); + dev_cdev->owner = THIS_MODULE; + dev_cdev->ops = &cs6436_54p_sysfs_fops; + err = cdev_add(dev_cdev, dev, 1); + if (err) + { + printk("error %d add fpga ", err); + goto err_malloc; + } + + dev_class = class_create(THIS_MODULE, DEVICE_NAME); + if (IS_ERR(dev_class)) + { + printk("Err:failed in creating class.\n"); + goto err_cdev_add; + } + + dev_device = device_create(dev_class, NULL, MKDEV(dev_major, 0), NULL, DEVICE_NAME); + if (IS_ERR(dev_device)) + { + printk("Err:failed in creating device.\n"); + goto err_class_crt; + } + + mutex_init(&list_lock); + + return err; + + err_class_crt: + cdev_del(dev_cdev); + err_cdev_add: + kfree(dev_cdev); + err_malloc: + unregister_chrdev_region(MKDEV(dev_major,0), 1); + + return err; + +} + +static void __exit cs6436_54p_sysfs_exit(void) +{ + cdev_del(dev_cdev); + printk("cdev_del ok\n"); + device_destroy(dev_class, MKDEV(dev_major, 0)); + + class_destroy(dev_class); + + if(dev_cdev != NULL) + kfree(dev_cdev); + + unregister_chrdev_region(MKDEV(dev_major, 0), 1); + printk("cs6436_54p_sysfs_exit...\r\n"); +} + + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436-54p-sysfs driver"); +MODULE_LICENSE("GPL"); + +module_init(cs6436_54p_sysfs_init); +module_exit(cs6436_54p_sysfs_exit); + + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/service/cs6436-platform-init.service b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/service/cs6436-platform-init.service new file mode 100644 index 000000000000..ad18c2c2703a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/service/cs6436-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Cig CS6436-54P Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/cig_cs6436_util.py install +ExecStop=/usr/local/bin/cig_cs6436_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/service/cs6436-platform-misc.service b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/service/cs6436-platform-misc.service new file mode 100644 index 000000000000..33f99935cd95 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/service/cs6436-platform-misc.service @@ -0,0 +1,15 @@ +[Unit] +Description=Cig CS6436-54P Platform miscellaneous service +After=cs6436-platform-init.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/cig_cs6436_misc.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/setup.py b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/setup.py new file mode 100755 index 000000000000..05ee2c6e36ac --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='cs6436-54p', + version='1.0.0', + description='Module to initialize Cig CS6436-54P platforms', + + packages=['cs6436-54p'], + package_dir={'cs6436-54p': 'cs6436-54p/classes'}, + ) diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/utils/cig_cs6436_misc.py b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/utils/cig_cs6436_misc.py new file mode 100755 index 000000000000..b4627a081d78 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/utils/cig_cs6436_misc.py @@ -0,0 +1,574 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Cambridge, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import commands +import sys, getopt +import logging +import re +import time +import datetime +from collections import namedtuple +from threading import Thread + +DEBUG = False +i2c_prefix = '/sys/bus/i2c/devices/' +leds_prefix = '/sys/devices/platform/cs6436_54p_led/leds/' +fans_prefix = '/sys/devices/platform/cs6436_54p_fan/' +fansdir_prefix = fans_prefix + 'fan{}_direction' + +ageing_controlfile = '/etc/sonic/agcontrol' +AGFlag = 0 + + +platform_misc_log = '/var/log/platform_misc.log' +misclogger = logging.getLogger('platform_misc') +misclogger.setLevel(logging.INFO) +miscformatter = logging.Formatter('%(asctime)s-%(levelname)s-%(message)s') + +if not os.path.isfile(platform_misc_log): + try: + os.mknod(platform_misc_log) + except: + print 'Failed to creat platform_misc.log' + +fileHandler = logging.FileHandler(platform_misc_log) +fileHandler.setLevel(logging.INFO) +fileHandler.setFormatter(miscformatter) +misclogger.addHandler(fileHandler) + + +starttime = datetime.datetime.now() +IsGetlswt = 0 +coretemp_prefix = '/sys/class/hwmon/hwmon1/' +coretemp_ps = [] +psu1_p = '/sys/bus/i2c/devices/5-005a/psu_present' +psu2_p = '/sys/bus/i2c/devices/5-005b/psu_present' +psu1_d = '/sys/bus/i2c/devices/5-0052/psu_eeprom' +psu2_d = '/sys/bus/i2c/devices/5-0053/psu_eeprom' +psu1led_d = leds_prefix + 'cs6436_54p_led::psu1/brightness' +psu2led_d = leds_prefix + 'cs6436_54p_led::psu2/brightness' +cs6436_ledpath = {'fan':leds_prefix + 'cs6436_54p_led::fan/brightness', + 'fan1':leds_prefix + 'cs6436_54p_led::fan1/brightness', + 'fan2':leds_prefix + 'cs6436_54p_led::fan2/brightness', + 'fan3':leds_prefix + 'cs6436_54p_led::fan3/brightness', + 'fan4':leds_prefix + 'cs6436_54p_led::fan4/brightness', + 'fan5':leds_prefix + 'cs6436_54p_led::fan5/brightness', + 'psu1':leds_prefix + 'cs6436_54p_led::psu1/brightness', + 'psu2':leds_prefix + 'cs6436_54p_led::psu2/brightness', + 'sys':leds_prefix + 'cs6436_54p_led::sys/brightness'} + + +def system_read_filestr(node): + with open(node, 'r') as f: + try: + str = f.read() + except IOError as e: + misclogger.error('Failed to get node, str={}'.format(node)) + return "0" + return str + + +def system_bright_leds(dev, colour): + global AGFlag + + if AGFlag == 1: + return + + cmd = 'echo {} > {}'.format(colour, dev) + log_os_system(cmd, 1) + return + +''' +1: front in tail out +0: front out tail in +''' +def system_getpsu_direction(dev): + try: + with open(dev) as f: + f.seek(0x30) + str = f.read(2) + except IOError as e: + misclogger.error('Failed to get psu eep') + return 1 + if str == 'AA': ## front in tail out + return 1 + elif str == 'RA':## tail in front out + return 0 + else: + misclogger.error('Failed to get psu eep, str={}'.format(str)) + return -1 + + +def system_get_cputype(): + cmdretfd = os.popen("lscpu | grep 'Model name'") + retstring = cmdretfd.read() + endindex = retstring.find('@') - 1 + startindex = retstring[:endindex].rfind(' ') + 1 + cputype = retstring[startindex:endindex] + + return cputype + + +def system_init_coretemppath(): + global coretemp_ps + + cmdstr = "ls {} | grep 'input'".format(coretemp_prefix) + cmdretfd = os.popen(cmdstr) + + coretemppss = cmdretfd.read().splitlines() + if len(coretemppss) < 3: + cputype = system_get_cputype() + misclogger.error('Failed to init core temperature path.' + ' cpu type = {}, num thermal = {}'.format(cputype, len(coretemp_ps))) + return 1 + + for i in range(0,3): + coretemp_ps.append(coretemp_prefix + coretemppss[i]) + + print coretemp_ps + + return 0 + + +class cs6436_fanattr: + def __init__(self, name): + self.name = name + self.direction = 0 + self.direction_p = '' + self.rear = 0 + self.rear_p = '' + self.front = 0 + self.front_p = '' + self.fault = 0 + self.fault_p = '' + self.status = 0 + self.setpath() + self.updatedevice() + + return + + def setpath(self): + self.direction_p = fans_prefix + '{}_direction'.format(self.name) + self.rear_p = fans_prefix + '{}_rear_speed_rpm'.format(self.name) + self.front_p = fans_prefix + '{}_front_speed_rpm'.format(self.name) + self.fault_p = fans_prefix + '{}_fault'.format(self.name) + + return + + def updatedevice(self): + self.direction = int(system_read_filestr(self.direction_p)) + self.rear = int(system_read_filestr(self.rear_p)) + self.front = int(system_read_filestr(self.front_p)) + self.fault = int(system_read_filestr(self.fault_p)) + + return + + def checkspeedrpm(self, speedrpm): + frontrpmexp = speedrpm * 21000 / 100 + rearrpmexp = speedrpm * 19000 / 100 + deviationfront = abs(frontrpmexp - self.front) / float(frontrpmexp) + deviationrear = abs(rearrpmexp - self.rear) / float(rearrpmexp) + + if deviationfront < 0.3 and deviationrear < 0.3: + return 0 + else: + misclogger.error(':{} speed wrong. frontexp is {}, but rpm is {}.rearexp is {}, but rpm is {}'.format(self.name, frontrpmexp, self.front, rearrpmexp, self.rear)) + return 1 + + def checkstatus(self, speedrpm, totaldirct): + speedstatus = self.checkspeedrpm(speedrpm) + if self.direction != totaldirct: + self.status = 1 + misclogger.error(':{} direction = {}.fan direction is not ok.'.format(self.name, self.direction)) + elif speedstatus != 0: + self.status = 1 + elif self.fault != 0: + misclogger.error(':{} fault.'.format(self.name)) + self.status = 1 + else: + self.status = 0 + + if self.status == 1: + system_bright_leds(cs6436_ledpath[self.name], 3) + else: + system_bright_leds(cs6436_ledpath[self.name], 1) + + return self.status + +cs6436_fanattrnodes = [] + + +class cs6436_psuattr: + def __init__(self, name): + self.name = name + self.direction = 0 + self.direction_p = '' + self.present = 0 + self.present_p = '' + self.status = 0 + + self.setpath() + self.updatepresent() + self.updatedirection() + + return + + def setpath(self): + if self.name == 'psu1': + self.present_p = psu1_p + self.direction_p = psu1_d + if self.name == 'psu2': + self.present_p = psu2_p + self.direction_p = psu2_d + + return + + def updatepresent(self): + self.present = int(system_read_filestr(self.present_p)) + + return + + def updatedirection(self): + if self.present == 1: + self.direction = system_getpsu_direction(self.direction_p) + else: + self.direction = 2 + + return + + def checkstatus(self, totaldirct): + if self.present != 1: + self.status = 1 + misclogger.error(':{} not present.'.format(self.name)) + elif self.direction == 2: + self.status = 0 + misclogger.info(':{} direction need to be update.'.format(self.name)) + elif self.direction != totaldirct: + self.status = 1 + misclogger.info(':{} direction is wrong.'.format(self.name)) + else: + self.status = 0 + + if self.status == 1: + system_bright_leds(cs6436_ledpath[self.name], 3) + else: + system_bright_leds(cs6436_ledpath[self.name], 1) + + return self.status + +cs6436_psuattrnodes = [] + + + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"5-005a", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"5-005b", 0) + ret3, log = log_os_system("ls "+leds_prefix+"cs6436_54p_led*", 0) + return not(ret1 or ret2 or ret3) + + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + + +def system_get_coretemp(): + temp1 = system_read_filestr(coretemp_ps[0]).strip() + temp2 = system_read_filestr(coretemp_ps[1]).strip() + temp3 = system_read_filestr(coretemp_ps[2]).strip() + + return int(temp1), int(temp2), int(temp3) + +def system_get_boardtemp(): + for i in range(0,16): + temp1path = "/sys/bus/i2c/devices/5-004a/hwmon/hwmon%d/temp1_input" % i + if os.access(temp1path, os.F_OK): + break + for i in range(0,16): + temp2path = "/sys/bus/i2c/devices/5-004b/hwmon/hwmon%d/temp1_input" % i + if os.access(temp2path, os.F_OK): + break + temp1 = system_read_filestr(temp1path).strip() + temp2 = system_read_filestr(temp2path).strip() + + return int(temp1), int(temp2) + + +def system_get_lswtemp(): + global IsGetlswt + global starttime + if IsGetlswt == 0: + now = datetime.datetime.now() + misclogger.info("time wait.") + misclogger.info("start = {}, now = {}.".format(starttime, now)) + if (now - starttime).seconds > 150: + misclogger.info("time = ".format((now - starttime).seconds)) + IsGetlswt = 1 + + return 25 + +# chp = subprocess.Popen("docker ps --filter name=syncd", shell=True, stdout=subprocess.PIPE) +# if chp.poll() is None: +# misclogger.info("No subp.") +# chp.kill() +# +# return 25 + +# retstring = chp.stdout.read() +# chp.kill() +# if 'Up' not in retstring: +# misclogger.info("lsw not up.") +# +# return 25 + + status, output = log_os_system('npx_diag swc show temperature', 1) + if status: + misclogger.error('failed to show lsw temperature') + + return 25 + + output = output.strip() + if output.find("it 0, temperature ") > 0: + startindex = output.find('temperature') + len('temperature') + 1 + endindex = output[startindex:].find(" ") + endindex = startindex + endindex + temp = output[startindex:endindex] + b = temp.find('.') + if b > 0: + temp=temp[:b] + temp = int(temp) + else: + misclogger.error("Failed to get temperature.") + temp = 0 + + return int(temp) + +def system_monitor_temperature(): + + ctemp1, ctemp2, ctemp3 = system_get_coretemp() + btemp1, btemp2 = system_get_boardtemp() + ltemp = system_get_lswtemp() + fan_speed_str = system_cs6436_getfanexspeed() + fan_speed = int(fan_speed_str) + policy = 'stay' + pos = 0 + #speed c1 c2 c3 b1 b2 lsw + fan_policy_up = ([30, 40000, 40000, 40000, 42000, 35000, 95], + [40, 44000, 44000, 44000, 44000, 39000, 96], + [50, 49000, 49000, 49000, 47000, 44000, 91], + [60, 52000, 52000, 52000, 51500, 47500, 92], + [70, 53000, 53000, 53000, 52000, 49000, 93], + [100,999999,999999,999999,999999,999999,999]) + + fan_policy_down=([30, 0, 0, 0, 0, 0, 0], + [40, 34000, 34000, 34000, 34000, 30000, 80], + [50, 38000, 38000, 38000, 37000, 33000, 81], + [60, 44000, 44000, 44000, 43000, 39000, 84], + [70, 44000, 44000, 44000, 43000, 40000, 84], + [100, 48000, 48000, 48000, 46000, 42000, 85],) + + for policytable in fan_policy_up: + if fan_speed <= policytable[0]: + break + pos = pos + 1 + fan_speed = policytable[0] + if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]): + policy = 'stay' + policytable = fan_policy_down[pos] + if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]): + policy = 'down' + else: + policy = 'up' + + if policy == 'up': + misclogger.info("speed = %d." % fan_speed) + misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3)) + misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2)) + misclogger.info("lsw = %d" % ltemp) + fan_speed = fan_policy_down[pos + 1][0] + misclogger.info("fan policy: up. speedexp = {}".format(fan_speed)) + + if policy == 'stay': + fan_speed = fan_policy_down[pos] + return + + if policy == 'down': + misclogger.info("speed = %d." % fan_speed) + misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3)) + misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2)) + misclogger.info("lsw = %d" % ltemp) + fan_speed = fan_policy_down[pos - 1][0] + misclogger.info("fan policy: down.speedexp = {}".format(fan_speed)) + + cmd = "echo {} > /sys/devices/platform/cs6436_54p_fan/fan_duty_cycle_percentage".format(fan_speed) + status, output = log_os_system(cmd, 1) + if status: + misclogger.error("set fan speed fault") + + return + + +def system_cs6436_setfanexspeed(num): + fanspeednode = fans_prefix + 'fan_duty_cycle_percentage' + numstr = str(num) + with open(fanspeednode, 'w') as f: + f.write(numstr) + + +def system_cs6436_getfanexspeed(): + fanspeednode = fans_prefix + 'fan_duty_cycle_percentage' + fanspeedstr = system_read_filestr(fanspeednode) + fanspeedexp = int(fanspeedstr) + + return fanspeedexp + + +def system_cs6436_getdirection(): + global cs6436_fanattrnodes + direction = 0 + + for fan in cs6436_fanattrnodes: + direction = direction + fan.direction + + if direction > 2: + direction = 1 + else: + direction = 0 + + return direction + + +def system_check_psusdirection(): + global cs6436_psuattrnodes + cs6436totaldirct = system_cs6436_getdirection() + psutatus = 0 + + for psu in cs6436_psuattrnodes: + psu.updatedirection() + psu.checkstatus(cs6436totaldirct) + psutatus = psu.status + psutatus + + return (psutatus != 0) + + +def system_check_psuspresent(): + global cs6436_psuattrnodes + cs6436totaldirct = system_cs6436_getdirection() + psutatus = 0 + + for psu in cs6436_psuattrnodes: + psu.updatepresent() + psu.checkstatus(cs6436totaldirct) + psutatus = psu.status + psutatus + + return (psutatus != 0) + + +def system_check_fansstate(): + global cs6436_fanattrnodes + global cs6436_ledpath + cs6436totaldirct = system_cs6436_getdirection() + fanstatus = 0 + fanexspeed = 0 + + fanexspeed = system_cs6436_getfanexspeed() + + for fan in cs6436_fanattrnodes: + fan.updatedevice() + fan.checkstatus(fanexspeed, cs6436totaldirct) + fanstatus = fanstatus + fan.status + + if fanstatus > 0: + misclogger.error(':fan error.set fans speed 100.') + system_cs6436_setfanexspeed(100) + system_bright_leds(cs6436_ledpath['fan'], 3) + else: + system_bright_leds(cs6436_ledpath['fan'], 1) + + return (fanstatus != 0) + + +def system_misc_polling(threadName,delay): + for count in range(1,5): + if device_exist() == False: + time.sleep(delay+3) + print "%s: %s, count=%d" % ( threadName, time.ctime(time.time()), count) + else: + break + + if count == 4: + return + + status, output = log_os_system("echo 1 > /sys/devices/platform/cs6436_54p_led/leds/cs6436_54p_led::sys/brightness", 1) + status, output = log_os_system("hwconfig -cfp 1", 1) + + global AGFlag + if os.access(ageing_controlfile, os.F_OK): + AGFlag = 1 + else: + AGFlag = 0 + + os.system('csw_daemon &') + + + global cs6436_fanattrnodes + global cs6436_psuattrnodes + + for num in range(1,6): + name = 'fan{}'.format(num) + fannode = cs6436_fanattr(name) + cs6436_fanattrnodes.append(fannode) + for num in range(1,3): + name = 'psu{}'.format(num) + psunode = cs6436_psuattr(name) + cs6436_psuattrnodes.append(psunode) + + tempcontrol = system_init_coretemppath() + + misclogger.info("%s: %s misc start." % ( threadName, time.ctime(time.time()))) + count = 0 + while 1: + count = count + 1 + ret = system_check_psuspresent() + ret = system_check_fansstate() + + if count % 10 == 0: + misclogger.info(": adjust fans and check psu direction.") + system_check_psusdirection() + if tempcontrol == 0: + system_monitor_temperature() + count = 0 + time.sleep(delay) + + return + +if __name__ == '__main__': + target=system_misc_polling("Thread-misc",10) + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-54p/utils/cig_cs6436_util.py b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/utils/cig_cs6436_util.py new file mode 100755 index 000000000000..81e6bb7c0b6b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-54p/utils/cig_cs6436_util.py @@ -0,0 +1,565 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Cambridge, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'cs6436_54p' +version = '0.1.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':9, 'fan':5, 'thermal':4, 'psu':2, 'sfp':54} +FORCE = 0 +CPU_TYPE = 'C3308' + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + for count in range(1,5): + time.sleep(1) + ret, lsmod = log_os_system("lsmod| grep i2c_i801", 0) + if len(lsmod) > 2: + log_os_system("rmmod i2c_i801", 0) + break + + ret, lsmod = log_os_system("lsmod| grep i2c_designware_platform", 0) + if len(lsmod) > 2: + log_os_system("rmmod i2c_designware_platform", 0) + log_os_system("modprobe i2c-designware-platform", 0) + + ret, lsmod = log_os_system("lsmod| grep cig", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ + 'depmod', + 'modprobe i2c_dev', + 'modprobe i2c_mux_pca954x force_deselect_on_exit=1', + 'modprobe x86-64-cig-cs6436-54p-sysfs ' , + 'modprobe x86-64-cig-cs6436-54p-cpld ' , + 'modprobe x86-64-cig-cs6436-54p-fan' , + 'modprobe x86-64-cig-cs6436-54p-psu' , + 'modprobe x86-64-cig-cs6436-54p-sfp' , + 'modprobe x86-64-cig-cs6436-54p-led' ] + +def driver_install(): + global FORCE + + for i in range(0,len(kos)): + if i == 4: + ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 32-39 | head -n 1", 0) + if CPU_TYPE=='i3-6100U': + kos[i] =kos[i] + 'board_id=1' + ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 36-40 | head -n 1", 0) + if CPU_TYPE=='C3758' or CPU_TYPE=='C3308': + kos[i] =kos[i] + 'board_id=2' + + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['sys','fan','fan1','fan2','fan3','fan4','fan5','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['4-0048','4-0049', '5-004a', '5-004b'] , + 'psu': ['5-005a','5-005b'], + 'sfp': ['-0050']} +i2c_nodes = {'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +fan_prefix ='/sys/bus/platform/devices/'+PROJECT_NAME+'_fan' +fan_types = {'fan': ['fan1','fan2', 'fan3', 'fan4', 'fan5']} +fan_nodes = {'fan': ['state', 'front_speed_rpm', 'rear_speed_rpm', 'fault']} + + +sfp_map = [8,9,10,11,12,13,14,15,16, + 17,18,19,20,21,22,23,24,25,26, + 27,28,29,30,31,32,33,34,35,36, + 37,38,39,40,41,42,43,44,45,46, + 47,48,49,50,51,52,53,54,55,56, + 57,60,61,62,63] + +mknod =[ + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-4/new_device', + 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-4/new_device', + 'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs6436_54p_psu1 0x5a > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs6436_54p_psu2 0x5b > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs6436_54p_psu1 0x52 > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs6436_54p_psu2 0x53 > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo 24c128 0x57 > /sys/bus/i2c/devices/i2c-7/new_device'] + +port = 0 + +def device_install(): + global FORCE + global port + + for i in range(0,len(mknod)): + #all nodes need times to built new i2c buses + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + if (i == 50): + port = port + 3 + else: + port = port + 1 + + + status, output =log_os_system("echo cs6436_54p_sfp"+str(port)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + if port <= 48: + status, output =log_os_system("echo cs6436_54p_sfp"+str(port)+" 0x51 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types, fan_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + for key in fan_types: + itypes = fan_types[key] + nodes = fan_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = fan_prefix+"/"+ itypes[i]+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + + +def get_ledname(ledx): + name_table={'led1':'SYS','led2':'FSTUS','led3':'FAN1','led4':'FAN2','led5':'FAN3','led6':'FAN4','led7':'FAN5','led8':'PSU1','led9':'PSU2'} + if name_table.has_key(ledx): + name = name_table[ledx] + else: + name = ledx + return name + + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + nwnamex = get_ledname(j) + if nwnamex == j: + print " "+j+":", + else: + print " "+nwnamex+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-3", 0) + return not(ret1 or ret2) + + +if __name__ == "__main__": + main() diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/classes/__init__.py b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/classes/fanutil.py b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/classes/fanutil.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/classes/thermalutil.py b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/classes/thermalutil.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/Makefile b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/Makefile new file mode 100644 index 000000000000..b0b4f1f7df06 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/Makefile @@ -0,0 +1,6 @@ +obj-m :=x86-64-cig-cs6436-56p-sysfs.o \ + x86-64-cig-cs6436-56p-cpld.o \ + x86-64-cig-cs6436-56p-fan.o \ + x86-64-cig-cs6436-56p-led.o \ + x86-64-cig-cs6436-56p-psu.o \ + x86-64-cig-cs6436-56p-sfp.o diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/i2c-algo-lpc.h b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/i2c-algo-lpc.h new file mode 100644 index 000000000000..9f1acd52ea68 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/i2c-algo-lpc.h @@ -0,0 +1,222 @@ +/* -------------------------------------------------------------------- + + * A hwmon driver for the CIG cs6436-56P + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* -------------------------------------------------------------------- */ + +#ifndef I2C_LPC_H +#define I2C_LPC_H 1 + +/* ----- Control register bits ---------------------------------------- */ +#define I2C_LPC_PIN 0x80 +#define I2C_LPC_ESO 0x40 +#define I2C_LPC_ES1 0x20 +#define I2C_LPC_ES2 0x10 +#define I2C_LPC_ENI 0x08 + +#define I2C_LPC_STO 0x40 +#define I2C_LPC_ACK 0x01 + +/*command register*/ +#define I2C_LPC_STA 0x80 +#define I2C_LPC_ABT 0x40 + +/*status register*/ +#define I2C_LPC_TBE 0x02 +#define I2C_LPC_IBB 0x80 +#define I2C_LPC_RBF 0x01 +#define I2C_LPC_TD 0x08 + +#define I2C_LPC_START I2C_LPC_STA +#define I2C_LPC_STOP I2C_LPC_STO +#define I2C_LPC_REPSTART I2C_LPC_STA +#define I2C_LPC_IDLE + +/* ----- Status register bits ----------------------------------------- */ +/*#define I2C_LPC_PIN 0x80 as above*/ + +#define I2C_LPC_INI 0x40 /* 1 if not initialized */ +#define I2C_LPC_STS 0x20 +#define I2C_LPC_BER 0x10 +#define I2C_LPC_AD0 0x08 +#define I2C_LPC_LRB 0x08 +#define I2C_LPC_AAS 0x04 +#define I2C_LPC_LAB 0x02 +#define I2C_LPC_BB 0x80 + +/* ----- Chip clock frequencies --------------------------------------- */ +#define I2C_LPC_CLK3 0x00 +#define I2C_LPC_CLK443 0x10 +#define I2C_LPC_CLK6 0x14 +#define I2C_LPC_CLK 0x18 +#define I2C_LPC_CLK12 0x1c + +/* ----- transmission frequencies ------------------------------------- */ +#define I2C_LPC_TRNS90 0x00 /* 90 kHz */ +#define I2C_LPC_TRNS45 0x01 /* 45 kHz */ +#define I2C_LPC_TRNS11 0x02 /* 11 kHz */ +#define I2C_LPC_TRNS15 0x03 /* 1.5 kHz */ + + +#define I2C_LPC_OWNADR 0 +#define I2C_LPC_INTREG I2C_LPC_ES2 +#define I2C_LPC_CLKREG I2C_LPC_ES1 + +#define I2C_LPC_REG_TEST 0x01 +#define I2C_LPC_REG_BUS_SEL 0x80 +#define I2C_LPC_REG_DEVICE_ADDR 0x81 +#define I2C_LPC_REG_BYTE_COUNT 0x83 +#define I2C_LPC_REG_COMMAND 0x84 +#define I2C_LPC_REG_STATUS 0x85 +#define I2C_LPC_REG_DATA_RX1 0x86 +#define I2C_LPC_REG_DATA_RX2 0x87 +#define I2C_LPC_REG_DATA_RX3 0x88 +#define I2C_LPC_REG_DATA_RX4 0x89 +#define I2C_LPC_REG_DATA_TX1 0x8a +#define I2C_LPC_REG_DATA_TX2 0x8b +#define I2C_LPC_REG_DATA_TX3 0x8c +#define I2C_LPC_REG_DATA_TX4 0x8d + + +#define ADDR_REG_SFP_STATUS_ADDR 0X62 //reg addr +R/W# //1031 +#define ADDR_REG_SFP_STATUS_TX 0X63 // write data +#define ADDR_REG_SFP_STATUS_RX 0X64 //read data +#define ADDR_REG_SFP_STATUS_COMMAND 0X65 //cmd bit7=1,go +#define ADDR_REG_SFP_STATUS_STATUS 0X66 //status + +#define CPLD_MASTER_INTERRUPT_STATUS_REG 0x20 +#define CPLD_MASTER_INTERRUPT_MASK_REG 0x21 +#define CPLD_MASTER_INTERRUPT_ALL 0x3f +#define CPLD_MASTER_INTERRUPT_CPLD2 0x20 +#define CPLD_MASTER_INTERRUPT_CPLD1 0x10 +#define CPLD_MASTER_INTERRUPT_PSU2 0x08 +#define CPLD_MASTER_INTERRUPT_PSU1 0x04 +#define CPLD_MASTER_INTERRUPT_6320 0x02 +#define CPLD_MASTER_INTERRUPT_LSW 0x01 + + + +#define CPLD_SLAVE1_INTERRUPT_STATUS_L_REG 0x20 +#define CPLD_SLAVE1_INTERRUPT_STATUS_H_REG 0x21 +#define CPLD_SLAVE2_INTERRUPT_STATUS_L_REG 0x22 +#define CPLD_SLAVE2_INTERRUPT_STATUS_H_REG 0x23 +#define CPLD_SLAVE1_INTERRUPT_MASK_REG 0x24 +#define CPLD_SLAVE2_INTERRUPT_MASK_REG 0x25 + + +#define CPLD_SLAVE1_PRESENT08_REG 0x01 +#define CPLD_SLAVE1_PRESENT16_REG 0x02 +#define CPLD_SLAVE1_PRESENT24_REG 0x03 +#define CPLD_SLAVE2_PRESENT32_REG 0x04 +#define CPLD_SLAVE2_PRESENT40_REG 0x05 +#define CPLD_SLAVE2_PRESENT48_REG 0x06 + +#define CPLD_SLAVE1_RX_LOST08_REG 0x07 +#define CPLD_SLAVE1_RX_LOST16_REG 0x08 +#define CPLD_SLAVE1_RX_LOST24_REG 0x09 +#define CPLD_SLAVE2_RX_LOST32_REG 0x0a +#define CPLD_SLAVE2_RX_LOST40_REG 0x0b +#define CPLD_SLAVE2_RX_LOST48_REG 0x0c + +#define CPLD_SLAVE1_TX_FAULT08_REG 0x0d +#define CPLD_SLAVE1_TX_FAULT16_REG 0x0e +#define CPLD_SLAVE1_TX_FAULT24_REG 0x0f +#define CPLD_SLAVE2_TX_FAULT32_REG 0x10 +#define CPLD_SLAVE2_TX_FAULT40_REG 0x11 +#define CPLD_SLAVE2_TX_FAULT48_REG 0x12 + +#define CPLD_SLAVE2_PRESENT56_REG 0x19 +#define CPLD_SLAVE2_QSFP_CR56_REG 0x1a + + +#define CPLD_SLAVE1_INTERRUPT_PRESENT08 0x0001 +#define CPLD_SLAVE1_INTERRUPT_PRESENT16 0x0002 +#define CPLD_SLAVE1_INTERRUPT_PRESENT24 0x0004 +#define CPLD_SLAVE2_INTERRUPT_PRESENT32 0x0001 +#define CPLD_SLAVE2_INTERRUPT_PRESENT40 0x0002 +#define CPLD_SLAVE2_INTERRUPT_PRESENT48 0x0004 + +#define CPLD_SLAVE2_INTERRUPT_QSFP_CR56 0x0200 +#define CPLD_SLAVE2_INTERRUPT_PRESENT56 0x0400 + +#define CPLD_SLAVE1_INTERRUPT_RX_LOST08 0x0008 +#define CPLD_SLAVE1_INTERRUPT_RX_LOST16 0x0010 +#define CPLD_SLAVE1_INTERRUPT_RX_LOST24 0x0020 +#define CPLD_SLAVE2_INTERRUPT_RX_LOST32 0x0008 +#define CPLD_SLAVE2_INTERRUPT_RX_LOST40 0x0010 +#define CPLD_SLAVE2_INTERRUPT_RX_LOST48 0x0020 + +#define CPLD_SLAVE1_INTERRUPT_TX_FAULT08 0x0040 +#define CPLD_SLAVE1_INTERRUPT_TX_FAULT16 0x0080 +#define CPLD_SLAVE1_INTERRUPT_TX_FAULT24 0x0100 +#define CPLD_SLAVE2_INTERRUPT_TX_FAULT32 0x0040 +#define CPLD_SLAVE2_INTERRUPT_TX_FAULT40 0x0080 +#define CPLD_SLAVE2_INTERRUPT_TX_FAULT48 0x0100 + + + + + + + +#define WAIT_TIME_OUT_COUNT 100 + + +struct i2c_algo_lpc_data { + void *data; /* private data for lolevel routines */ + void (*setlpc) (void *data, int ctl, int val); + int (*getlpc) (void *data, int ctl); + int (*getown) (void *data); + int (*getclock) (void *data); + void (*waitforpin) (void *data); + + int (*xfer_begin) (void *data); + int (*xfer_end) (void *data); + + /* Multi-master lost arbitration back-off delay (msecs) + * This should be set by the bus adapter or knowledgable client + * if bus is multi-mastered, else zero + */ + unsigned long lab_mdelay; +}; + + +struct subsys_private { + struct kset subsys; + struct kset *devices_kset; + struct list_head interfaces; + struct mutex mutex; + + struct kset *drivers_kset; + struct klist klist_devices; + struct klist klist_drivers; + struct blocking_notifier_head bus_notifier; + unsigned int drivers_autoprobe:1; + struct bus_type *bus; + + struct kset glue_dirs; + struct class *class; +}; + +void cs6436_56p_sysfs_add_client(struct i2c_client *client); +void cs6436_56p_sysfs_remove_client(struct i2c_client *client); + + +#endif /* I2C_LPC8584_H */ diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/i2c-algo-lpc2iic.h b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/i2c-algo-lpc2iic.h new file mode 100644 index 000000000000..6963bef734f1 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/i2c-algo-lpc2iic.h @@ -0,0 +1,48 @@ +/* -------------------------------------------------------------------- + + * A hwmon driver for the CIG cs6436-56P + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* -------------------------------------------------------------------- */ + + +#ifndef _LINUX_I2C_ALGO_LPC_H +#define _LINUX_I2C_ALGO_LPC_H + +struct i2c_algo_lpc_data { + void *data; /* private data for lolevel routines */ + void (*setlpc) (void *data, int ctl, int val); + int (*getlpc) (void *data, int ctl); + int (*getown) (void *data); + int (*getclock) (void *data); + void (*waitforpin) (void *data); + + int (*xfer_begin) (void *data); + int (*xfer_end) (void *data); + + /* Multi-master lost arbitration back-off delay (msecs) + * This should be set by the bus adapter or knowledgable client + * if bus is multi-mastered, else zero + */ + unsigned long lab_mdelay; +}; + +int lpc_add_iic_bus(struct i2c_adapter * adap, unsigned int id); + +#endif /* _LINUX_I2C_ALGO_LPC_H */ diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-cpld.c b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-cpld.c new file mode 100644 index 000000000000..dcff94085f09 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-cpld.c @@ -0,0 +1,2204 @@ +/* + * A hwmon driver for the CIG cs6436-56P CPLD + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-algo-lpc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CPLD_USER +# include +#else +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + + + + + +/********************************************** Start ********************************************************/ + +/* + * ISA bus. + */ + +static void platform_isa_bus_release(struct device * dev) +{ + return ; +} + + +static struct device isa_bus = { + .init_name = "lpc-isa", + .release = platform_isa_bus_release, +}; + +struct isa_dev { + struct device dev; + struct device *next; + unsigned int id; +}; + +#define to_isa_dev(x) container_of((x), struct isa_dev, dev) + +static int isa_bus_match(struct device *dev, struct device_driver *driver) +{ + struct isa_driver *isa_driver = to_isa_driver(driver); + + if (dev->platform_data == isa_driver) { + if (!isa_driver->match || + isa_driver->match(dev, to_isa_dev(dev)->id)) + return 1; + dev->platform_data = NULL; + } + return 0; +} + +static int isa_bus_probe(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->probe) + return isa_driver->probe(dev, to_isa_dev(dev)->id); + + return 0; +} + +static int isa_bus_remove(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->remove) + return isa_driver->remove(dev, to_isa_dev(dev)->id); + + return 0; +} + +static void isa_bus_shutdown(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->shutdown) + isa_driver->shutdown(dev, to_isa_dev(dev)->id); +} + +static int isa_bus_suspend(struct device *dev, pm_message_t state) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->suspend) + return isa_driver->suspend(dev, to_isa_dev(dev)->id, state); + + return 0; +} + +static int isa_bus_resume(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->resume) + return isa_driver->resume(dev, to_isa_dev(dev)->id); + + return 0; +} + +static struct bus_type isa_bus_type = { + .name = "lpc-isa", + .match = isa_bus_match, + .probe = isa_bus_probe, + .remove = isa_bus_remove, + .shutdown = isa_bus_shutdown, + .suspend = isa_bus_suspend, + .resume = isa_bus_resume +}; + +static void isa_dev_release(struct device *dev) +{ + kfree(to_isa_dev(dev)); +} + +void lpc_unregister_driver(struct isa_driver *isa_driver) +{ + struct device *dev = isa_driver->devices; + + while (dev) { + struct device *tmp = to_isa_dev(dev)->next; + device_unregister(dev); + dev = tmp; + } + driver_unregister(&isa_driver->driver); +} + + +int lpc_register_driver(struct isa_driver *isa_driver, unsigned int ndev) +{ + int error; + unsigned int id; + + isa_driver->driver.bus = &isa_bus_type; + isa_driver->devices = NULL; + + error = driver_register(&isa_driver->driver); + if (error) + return error; + + for (id = 0; id < ndev; id++) { + struct isa_dev *isa_dev; + + isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL); + if (!isa_dev) { + error = -ENOMEM; + break; + } + + isa_dev->dev.parent = &isa_bus; + isa_dev->dev.bus = &isa_bus_type; + + dev_set_name(&isa_dev->dev, "%s.%u", + isa_driver->driver.name, id); + isa_dev->dev.platform_data = isa_driver; + isa_dev->dev.release = isa_dev_release; + isa_dev->id = id; + + isa_dev->dev.coherent_dma_mask = DMA_BIT_MASK(24); + isa_dev->dev.dma_mask = &isa_dev->dev.coherent_dma_mask; + + error = device_register(&isa_dev->dev); + if (error) { + put_device(&isa_dev->dev); + break; + } + + if (isa_dev->dev.platform_data) { + isa_dev->next = isa_driver->devices; + isa_driver->devices = &isa_dev->dev; + } else + device_unregister(&isa_dev->dev); + } + + if (!error && !isa_driver->devices) + error = -ENODEV; + + if (error) + isa_unregister_driver(isa_driver); + + return error; +} + + +int lpc_bus_init(void) +{ + int error; + + error = bus_register(&isa_bus_type); + if (!error) { + error = device_register(&isa_bus); + if (error) + bus_unregister(&isa_bus_type); + } + return error; +} + +void lpc_bus_exit(void) +{ + + device_unregister(&isa_bus); + + bus_unregister(&isa_bus_type); +} + + +/********************************************** End ********************************************************/ + + + + + + +/********************************************** Start ********************************************************/ +/* + * module parameters: + */ +static int i2c_debug = 0; +static struct mutex lpc_lock; + + +#define DEB2(x) if (i2c_debug == 2) x +#define DEB3(x) if (i2c_debug == 3) x + /* print several statistical values */ +#define DEBPROTO(x) if (i2c_debug == 9) x; + /* debug the protocol by showing transferred bits */ +#define DEF_TIMEOUT 160 + + + +/* setting states on the bus with the right timing: */ + +#define set_lpc(adap, ctl, val) adap->setlpc(adap->data, ctl, val) +#define get_lpc(adap, ctl) adap->getlpc(adap->data, ctl) +#define get_own(adap) adap->getown(adap->data) +#define get_clock(adap) adap->getclock(adap->data) +#define i2c_outaddr(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DEVICE_ADDR, val) + +#define i2c_outbyte1(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX1, val) +#define i2c_outbyte2(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX2, val) +#define i2c_outbyte3(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX3, val) +#define i2c_outbyte4(adap, val) adap->setlpc(adap->data, I2C_LPC_REG_DATA_TX4, val) +#define i2c_inbyte1(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX1) +#define i2c_inbyte2(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX2) +#define i2c_inbyte3(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX3) +#define i2c_inbyte4(adap) adap->getlpc(adap->data, I2C_LPC_REG_DATA_RX4) + + + +#define LPC_FPRINTF_LOG_PATH "/tmp/file.log" +struct file *lpc_fprintf_file = NULL; + +static int lpc_fprintf_debug(const char *fmt, ...) +{ + char lpc_fprintf_buf[256]={0}; + struct va_format vaf; + va_list args; + int r; + mm_segment_t old_fs; + struct timeval tv; + struct rtc_time tm; + + do_gettimeofday(&tv); + + rtc_time_to_tm(tv.tv_sec,&tm); + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + r=snprintf(lpc_fprintf_buf,sizeof(lpc_fprintf_buf),"[%04d.%08d] %pV\n",tm.tm_sec, (int)tv.tv_usec, &vaf); + va_end(args); + old_fs = get_fs(); + set_fs(KERNEL_DS); + vfs_write(lpc_fprintf_file, (char *)&lpc_fprintf_buf, strlen(lpc_fprintf_buf), &lpc_fprintf_file->f_pos); + set_fs(old_fs); + memset(lpc_fprintf_buf,0x0,sizeof(lpc_fprintf_buf)); + return r; + +} + + + +static int lpc_fprintf_init(void) +{ + printk("lpc_fprintf_init.\n"); + + if(lpc_fprintf_file == NULL) + lpc_fprintf_file = filp_open(LPC_FPRINTF_LOG_PATH, O_RDWR | O_APPEND | O_CREAT, 0644); + + if (IS_ERR(lpc_fprintf_file)) { + printk("Error occured while opening file %s, exiting...\n", LPC_FPRINTF_LOG_PATH); + return -1; + } + + return 0; +} + +static int lpc_fprintf_exit(void) +{ + printk("lpc_fprintf_exit.\n"); + + if(lpc_fprintf_file != NULL) + filp_close(lpc_fprintf_file, NULL); + + return 0; +} + + +/* other auxiliary functions */ + + +void print_reg(struct i2c_algo_lpc_data *adap) +{ + unsigned char status; + DEBPROTO(lpc_fprintf_debug("================================================\n");) + status = get_lpc(adap, I2C_LPC_REG_BUS_SEL); + DEBPROTO(lpc_fprintf_debug("%s select reg %x : %x\n",__func__,I2C_LPC_REG_BUS_SEL, status);) + status = get_lpc(adap, I2C_LPC_REG_BYTE_COUNT); + DEBPROTO(lpc_fprintf_debug("%s count reg %x : %x\n",__func__,I2C_LPC_REG_BYTE_COUNT, status);) + + status = get_lpc(adap, I2C_LPC_REG_COMMAND); + DEBPROTO(lpc_fprintf_debug("%s command reg %x : %x\n",__func__,I2C_LPC_REG_COMMAND, status);) + status = get_lpc(adap, I2C_LPC_REG_DEVICE_ADDR); + DEBPROTO(lpc_fprintf_debug("%s address reg %x : %x\n",__func__,I2C_LPC_REG_DEVICE_ADDR, status);) + + status = get_lpc(adap, I2C_LPC_REG_STATUS); + DEBPROTO(lpc_fprintf_debug("%s status reg %x : %x\n",__func__,I2C_LPC_REG_STATUS, status);) +} + + + +static void i2c_repstart(struct i2c_algo_lpc_data *adap) +{ + DEBPROTO(lpc_fprintf_debug("%s :\n",__func__);) + set_lpc(adap, I2C_LPC_REG_COMMAND, I2C_LPC_REPSTART); +} + +static void i2c_stop(struct i2c_algo_lpc_data *adap) +{ + DEBPROTO(lpc_fprintf_debug("%s :\n",__func__);) + set_lpc(adap, I2C_LPC_REG_COMMAND, I2C_LPC_STOP); + udelay(60); + set_lpc(adap, I2C_LPC_REG_COMMAND, 0x00); +} + + + + +static void i2c_start(struct i2c_algo_lpc_data *adap) +{ + print_reg(adap); + + set_lpc(adap, I2C_LPC_REG_COMMAND, I2C_LPC_START); + + print_reg(adap); +} + + + + +static int wait_for_bb(struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + int status; + + while (--timeout) { + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus free status : %x\n",__func__,status);) + + if(status == I2C_LPC_TD) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is free status : %x\n",__func__,status);) + break; + } + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout for free busy status : %x\n",__func__,status);) + return -ETIMEDOUT; + } + + + + return 0; +} + + +static int wait_for_be(int mode,struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + unsigned char status; + + + while (--timeout) { + + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus empty status : %x\n",__func__,status);) + + if(mode == 1) + { + if((status & I2C_LPC_IBB) && (status & I2C_LPC_TBE)) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is empty status : %x\n",__func__,status);) + break; + } + } + else + { + if(status & I2C_LPC_TD) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is empty status : %x\n",__func__,status);) + break; + } + } + + status = get_lpc(adap, I2C_LPC_REG_TEST); + + DEBPROTO(lpc_fprintf_debug("%s : The test register data : %x\n",__func__,status);) + udelay(1); /* wait for 100 us */ + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout waiting for Bus Empty\n",__func__);) + return -ETIMEDOUT; + } + + return 0; +} + + +static int wait_for_bf(struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + int status; + + + while (--timeout) { + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus full status : %x\n",__func__,status);) + + if(status & I2C_LPC_RBF) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is full status : %x\n",__func__,status);) + break; + } + + status = get_lpc(adap, I2C_LPC_REG_TEST); + + DEBPROTO(lpc_fprintf_debug("%s : The test register data : %x\n",__func__,status);) + udelay(1); /* wait for 100 us */ + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout waiting for Bus Full\n",__func__);) + return -ETIMEDOUT; + } + + return 0; +} + +static int wait_for_td(struct i2c_algo_lpc_data *adap) +{ + + int timeout = DEF_TIMEOUT; + int status=0; + + while (--timeout) { + udelay(4); + status = get_lpc(adap, I2C_LPC_REG_STATUS); + + DEBPROTO(lpc_fprintf_debug("%s : Waiting for bus done status : %x\n",__func__,status);) + + if(status == I2C_LPC_TD) + { + DEBPROTO(lpc_fprintf_debug("%s : Bus is done status : %x\n",__func__,status);) + break; + } + } + + if (timeout == 0) { + DEBPROTO(lpc_fprintf_debug("%s : Timeout waiting for Bus Done\n",__func__);) + return -ETIMEDOUT; + } + + return 0; +} + + + +static int wait_for_pin(struct i2c_algo_lpc_data *adap, int *status) +{ + int timeout = DEF_TIMEOUT; + *status = get_lpc(adap, I2C_LPC_REG_STATUS); + + while ((*status & I2C_LPC_TBE) && --timeout) { + *status = get_lpc(adap, I2C_LPC_REG_STATUS); + } + + if (timeout == 0) + return -ETIMEDOUT; + + + return 0; +} + + +static int lpc_doAddress(struct i2c_algo_lpc_data *adap,struct i2c_msg *msg) +{ + unsigned short flags = msg->flags; + unsigned char addr; + + addr = msg->addr << 1; + if (flags & I2C_M_RD) + { + addr |= 1; + DEBPROTO(lpc_fprintf_debug("step 7 : read mode then write device address 0x%x\n",addr);) + } + else + { + DEBPROTO(lpc_fprintf_debug("step 2 : write mode then write device address 0x%x\n",addr);) + } + + if (flags & I2C_M_REV_DIR_ADDR) + { + addr ^= 1; + + } + i2c_outaddr(adap, addr); + return 0; + +} + + +static int lpc_sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) +{ + struct i2c_algo_lpc_data *adap = i2c_adap->algo_data; + int i = 0,timeout=0; + + unsigned int count = msg->len; + unsigned char *buf = msg->buf; + + do{ + lpc_doAddress(adap,msg); + set_lpc(adap, I2C_LPC_REG_BYTE_COUNT, (count-i) >= 4 ? 4:(count - i)); + DEBPROTO(lpc_fprintf_debug("step 3 : write register count %x\n",count);) + + if((count -i) >= 4) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + i2c_outbyte2(adap, buf[i+1] & 0xff); + i2c_outbyte3(adap, buf[i+2] & 0xff); + i2c_outbyte4(adap, buf[i+3] & 0xff); + + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+2,buf[i+2]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+3,buf[i+3]);) + i += 4; + } + else if((count -i) == 3) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + i2c_outbyte2(adap, buf[i+1] & 0xff); + i2c_outbyte3(adap, buf[i+2] & 0xff); + + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+2,buf[i+2]);) + + i += 3; + } + else if((count -i) == 2) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + i2c_outbyte2(adap, buf[i+1] & 0xff); + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+1,buf[i+1]);) + i += 2; + } + else if((count -i) == 1) + { + i2c_outbyte1(adap, buf[i+0] & 0xff); + DEBPROTO(lpc_fprintf_debug("step 4 : Send data[%d] = %x\n",i+0,buf[i+0]);) + i += 1; + } + + /* Send START */ + DEBPROTO(lpc_fprintf_debug("step 5-1 : Delay 6mS \n");) + udelay(6000); + DEBPROTO(lpc_fprintf_debug("step 5-2 : Start to transfrom \n");) + i2c_stop(adap); + i2c_start(adap); + DEBPROTO(lpc_fprintf_debug("step 5-3 : Start done\n");) + + udelay(400); + DEBPROTO(lpc_fprintf_debug("step 6 : Waiting for BE\n");) + timeout = wait_for_td(adap); + if (timeout) { + DEBPROTO(lpc_fprintf_debug("step 6 : Timeout waiting for BE \n");) + return -EREMOTEIO; + } + }while (i < count); + + if(i == count) + { + DEBPROTO(lpc_fprintf_debug("Writen %d bytes successd !\n",count);) + return i; + } + else + { + DEBPROTO(lpc_fprintf_debug("Writen %d bytes failed \n",count);) + return -EIO; + } +} + +static int lpc_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) +{ + int i=0,timeout=0; + struct i2c_algo_lpc_data *adap = i2c_adap->algo_data; + + unsigned int count = msg->len; + unsigned char *buf = msg->buf; + + do{ + lpc_doAddress(adap,msg); + set_lpc(adap, I2C_LPC_REG_BYTE_COUNT, (count-i) >= 4 ? 4:(count - i)); + DEBPROTO(lpc_fprintf_debug("step 8 : write register count %d\n",count);) + + /* Send START */ + DEBPROTO(lpc_fprintf_debug("step 9-1 : Delay 6mS\n");) + udelay(6000); + DEBPROTO(lpc_fprintf_debug("step 9-2 : Start to receive data\n");) + i2c_stop(adap); + i2c_start(adap); + DEBPROTO(lpc_fprintf_debug("step 9-3 : Start done\n");) + + udelay(400); + DEBPROTO(lpc_fprintf_debug("step 10 : Waiting for TD\n");) + timeout = wait_for_td(adap); + if (timeout) { + DEBPROTO(lpc_fprintf_debug("step 10 : Timeout waiting for TD \n");) + return -EREMOTEIO; + } + + if((count -i) >= 4) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + buf[i+1] = 0xff & i2c_inbyte2(adap); + buf[i+2] = 0xff & i2c_inbyte3(adap); + buf[i+3] = 0xff & i2c_inbyte4(adap); + + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+2,buf[i+2]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+3,buf[i+3]);) + + i += 4; + } + else if((count -i) == 3) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + buf[i+1] = 0xff & i2c_inbyte2(adap); + buf[i+2] = 0xff & i2c_inbyte3(adap); + + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+1,buf[i+1]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+2,buf[i+2]);) + + i += 3; + } + else if((count -i) == 2) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + buf[i+1] = 0xff & i2c_inbyte2(adap); + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+1,buf[i+1]);) + i += 2; + } + else if((count -i) == 1) + { + buf[i+0] = 0xff & i2c_inbyte1(adap); + DEBPROTO(lpc_fprintf_debug("step 11 : Receive data[%d] = %x\n",i+0,buf[i+0]);) + i += 1; + } + + + }while(i < count); + + if(i == count) + { + DEBPROTO(lpc_fprintf_debug("Read %d bytes successd !\n",count);) + return i; + } + else + { + DEBPROTO(lpc_fprintf_debug("Read %d bytes failed \n",count);) + return -EIO; + } +} + + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; +#define LPC_I2C_MAX_NCHANS 6 + + +struct lpc_iic { + struct i2c_adapter *virt_adaps[LPC_I2C_MAX_NCHANS]; + u8 last_chan; /* last register value */ +}; + + +static int lpc_master_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, + int num) +{ + struct i2c_algo_lpc_data *adap = i2c_adap->algo_data; + struct i2c_msg *pmsg; + int i; + int ret=0; + + mutex_lock(&lpc_lock); + + if (adap->xfer_begin) + adap->xfer_begin(&i2c_adap->nr); + + + for (i = 0;ret >= 0 && i < num; i++) { + pmsg = &msgs[i]; + + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n", + pmsg->flags & I2C_M_RD ? "read" : "write", + pmsg->len, pmsg->addr, i + 1, num);) + + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n", + i, msgs[i].addr, msgs[i].flags, msgs[i].len);) + + if (pmsg->flags & I2C_M_RD) { + ret = lpc_readbytes(i2c_adap, pmsg); + + if (ret != pmsg->len) { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: fail: " + "only read %d bytes.\n",ret)); + } else { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: read %d bytes.\n",ret)); + } + } else { + + ret = lpc_sendbytes(i2c_adap, pmsg); + + if (ret != pmsg->len) { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: fail: " + "only wrote %d bytes.\n",ret)); + } else { + DEBPROTO(lpc_fprintf_debug("lpc_xfer.o: wrote %d bytes.\n",ret)); + } + } + } + + if (adap->xfer_end) + adap->xfer_end(&i2c_adap->nr); + + mutex_unlock(&lpc_lock); + + DEBPROTO(lpc_fprintf_debug("ret = 0x%x num = 0x%x i = 0x%x.\n",ret,num,i)); + + return ret = (ret < 0) ? ret : num; +} + + +static u32 lpc_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_QUICK; +} + +/* exported algorithm data: */ +static const struct i2c_algorithm lpc_algo = { + .master_xfer = lpc_master_xfer, + //.smbus_xfer = lpc_smbus_xfer, + .functionality = lpc_func, +}; + + +/********************************************** End ********************************************************/ + + + + + + +/********************************************** Start ********************************************************/ +#define DEFAULT_BASE 0x0a00 + +static int lpc_base= 0x0a00; +static u8 __iomem *lpc_base_iomem; + +static int lpc_irq; +static int lpc_clock = 0x1c; +static int lpc_own = 0x55; +static int lpc_mmapped; + +static unsigned long lpc_base_addr = 0x0a00; +static unsigned int lpc_io_space_size = 2; + +static unsigned long LPC_INDEX_REG; +static unsigned long LPC_DATA_REG; + + +/* notice : removed static struct i2c_lpc_iic gpi; code - + this module in real supports only one device, due to missing arguments + in some functions, called from the algo-lpc module. Sometimes it's + need to be rewriten - but for now just remove this for simpler reading */ + +static wait_queue_head_t lpc_wait; +static int lpc_pending; +static spinlock_t lock; +static spinlock_t lpc_slock; + +static struct i2c_adapter lpc_iic_ops; + +struct cpld_dev_type { + struct resource *io_resource; + struct semaphore sem; + struct cdev cdev; +}; + +struct cpld_dev_type *cpld_device; + + +/* ----- local functions ---------------------------------------------- */ + +static void lpc_cpld_setbyte(void *data, int ctl, int val) +{ + outb(ctl, LPC_INDEX_REG); + mb(); + + outb(val, LPC_DATA_REG); + mb(); +} + +static int lpc_cpld_getbyte(void *data, int ctl) +{ + u8 val = 0; + + outb(ctl, LPC_INDEX_REG); + mb(); + + val = inb(LPC_DATA_REG); + mb(); + + return val; +} + +static void lpc_iic_setbyte(void *data, int ctl, int val) +{ + if (!cpld_device) + { + return ; + } + + if (down_interruptible(&cpld_device->sem)) + { + return ; + } + + + lpc_cpld_setbyte(data,ctl,val); + + up(&cpld_device->sem); + DEBPROTO(lpc_fprintf_debug("%s REG[%x] = %x\n",__func__,ctl,val);) +} + + +static int lpc_iic_getbyte(void *data, int ctl) +{ + u8 val = 0; + if (!cpld_device) + return -ENOTTY; + + if (down_interruptible(&cpld_device->sem)) + return -ERESTARTSYS; + + val = lpc_cpld_getbyte(data,ctl); + + up(&cpld_device->sem); + DEBPROTO(lpc_fprintf_debug("%s REG[%x] = %x\n",__func__,ctl,val);) + return val; +} + +int cig_cpld_read_register(u8 reg_off, u8 *val) +{ + if (!cpld_device) + return -ENOTTY; + + if (down_interruptible(&cpld_device->sem)) + return -ERESTARTSYS; + + *val = lpc_cpld_getbyte(cpld_device, reg_off); + + up(&cpld_device->sem); + + return 0; +} +EXPORT_SYMBOL(cig_cpld_read_register); + +int cig_cpld_write_register(u8 reg_off, u8 val) +{ + if (!cpld_device) + return -ENOTTY; + + if (down_interruptible(&cpld_device->sem)) + return -ERESTARTSYS; + + lpc_cpld_setbyte(cpld_device, reg_off, val); + up(&cpld_device->sem); + return 0; +} +EXPORT_SYMBOL(cig_cpld_write_register); + + + +static int lpc_iic_getown(void *data) +{ + return (lpc_own); +} + + +static int lpc_iic_getclock(void *data) +{ + return (lpc_clock); +} + +static void lpc_iic_waitforpin(void *data) +{ + DEFINE_WAIT(wait); + int timeout = 2; + unsigned long flags; + + if (lpc_irq > 0) { + spin_lock_irqsave(&lock, flags); + if (lpc_pending == 0) { + spin_unlock_irqrestore(&lock, flags); + prepare_to_wait(&lpc_wait, &wait, TASK_INTERRUPTIBLE); + if (schedule_timeout(timeout*HZ)) { + spin_lock_irqsave(&lock, flags); + if (lpc_pending == 1) { + lpc_pending = 0; + } + spin_unlock_irqrestore(&lock, flags); + } + finish_wait(&lpc_wait, &wait); + } else { + lpc_pending = 0; + spin_unlock_irqrestore(&lock, flags); + } + } else { + udelay(100); + } +} + + +static irqreturn_t lpc_iic_handler(int this_irq, void *dev_id) { + spin_lock(&lock); + lpc_pending = 1; + spin_unlock(&lock); + wake_up_interruptible(&lpc_wait); + return IRQ_HANDLED; +} + +static int board_id = 0; + + +static int lpc_iic_select(void *data) +{ + unsigned int chan_id=0; + chan_id = *(unsigned int *)data; + chan_id -= 2; + DEBPROTO(lpc_fprintf_debug("step 1 : selest channel id = %d\n",chan_id);) + lpc_iic_setbyte(data,I2C_LPC_REG_BUS_SEL,chan_id); + + return 0; +} + +static int lpc_iic_deselect(void *data) +{ + + unsigned int chan_id=0; + chan_id = *(unsigned int *)data; + chan_id -= 2; + DEBPROTO(lpc_fprintf_debug("step last :deselect channel id = %d\n",chan_id);) + + return 0; +} + + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ +static struct i2c_algo_lpc_data lpc_iic_data = { + .setlpc = lpc_iic_setbyte, + .getlpc = lpc_iic_getbyte, + .getown = lpc_iic_getown, + .getclock = lpc_iic_getclock, + .waitforpin = lpc_iic_waitforpin, + .xfer_begin = lpc_iic_select, + .xfer_end = lpc_iic_deselect, +}; + +#include + +static struct i2c_adapter lpc_iic_arr_ops[LPC_I2C_MAX_NCHANS] = {0}; + +static void dummy_setscl(void *data, int state) +{ + return; +} + +static void dummy_setsda(void *data, int state) +{ + return; + +} + +static int dummy_getscl(void *data) +{ + return 1; + +} + +static int dummy_getsda(void *data) +{ + return 1; +} + + +static struct i2c_algo_bit_data dummy_algo_data = { + .setsda = dummy_setsda, + .setscl = dummy_setscl, + .getsda = dummy_getsda, + .getscl = dummy_getscl, + .udelay = 50, + .timeout = HZ, +}; + + +static int dummy_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, + int num) +{ + return 1; +} + +static u32 dummy_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_QUICK; +} + + +static const struct i2c_algorithm dummy_algo = { + .master_xfer = dummy_xfer, + .functionality = dummy_func, +}; + + + +static struct i2c_adapter i2c_dummy = { + .owner = THIS_MODULE, + .class = I2C_CLASS_HWMON, + .algo_data = &dummy_algo_data, + .algo = &dummy_algo, + .name = "i2c_dummy", +}; + + +static int lpc_iic_match(struct device *dev, unsigned int id) +{ + /* sanity checks for lpc_mmapped I/O */ + + DEB2(printk("lpc_iic_match\n");) + + + if (lpc_base < DEFAULT_BASE) { + dev_err(dev, "incorrect lpc_base address (%#x) specified " + "for lpc_mmapped I/O\n", lpc_base); + return 0; + } + + if (lpc_base == 0) { + lpc_base = DEFAULT_BASE; + } + return 1; +} + +static int lpc_iic_probe(struct device *dev, unsigned int id) +{ + int rval,num; + + lpc_fprintf_init(); + + DEB2(printk("lpc_iic_probe\n");) + + mutex_init(&lpc_lock); + + for(num = 0; num < LPC_I2C_MAX_NCHANS;num++) + { + lpc_iic_arr_ops[num].dev.parent = dev; + lpc_iic_arr_ops[num].owner = THIS_MODULE; + lpc_iic_arr_ops[num].class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + lpc_iic_arr_ops[num].algo = &lpc_algo; + lpc_iic_arr_ops[num].algo_data = &lpc_iic_data, + lpc_iic_arr_ops[num].nr=num; + snprintf(lpc_iic_arr_ops[num].name, sizeof(lpc_iic_arr_ops[num].name), "i2c-%d-lpc", i2c_adapter_id(&lpc_iic_arr_ops[num])); + rval |= i2c_add_adapter(&lpc_iic_arr_ops[num]); + DEB2(printk("%s\n",lpc_iic_arr_ops[num].name);) + } + + return 0; +} + +static int lpc_iic_remove(struct device *dev, unsigned int id) +{ + int num; + DEB2(printk("lpc_iic_remove\n")); + + lpc_fprintf_exit(); + for(num = LPC_I2C_MAX_NCHANS - 1; num >= 0 ;num--) + i2c_del_adapter(&lpc_iic_arr_ops[num]); + + + return 0; +} + +static struct isa_driver i2c_lpc_driver = { + .match = lpc_iic_match, + .probe = lpc_iic_probe, + .remove = lpc_iic_remove, + .driver = { + .owner = THIS_MODULE, + .name = "lpc-iic", + }, +}; + +/********************************************** End ********************************************************/ + + + + + + +/********************************************** Start ********************************************************/ + +static int cpld_major = 0; +static int cpld_minor = 0; + +struct cpld_rw_msg { + unsigned char addr; + unsigned char data; +}; + + +static struct cpld_rw_msg param_read = {-1}; +static struct cpld_rw_msg param_write = {-1}; +static struct cpld_rw_msg param_reads = {-1}; +static struct cpld_rw_msg param_writes = {-1}; + +void cpld_sysfs_kobj_release(struct kobject *kobj) +{ + return; +} + +int cpld_sysfs_add_attr(struct kobject* kobj, char* attr_name) +{ + + struct attribute *attr; + + attr = kmalloc(sizeof(struct attribute), GFP_KERNEL); + attr->name = attr_name; + attr->mode = 0644; + + return sysfs_create_file(kobj, attr); +} + +static int cig_cpld_write_slave_cpld_register(u8 reg_addr, u8 reg_data); +static int cig_cpld_read_slave_cpld_register(u8 reg_addr, u8 *reg_data); + + +static ssize_t cpld_sysfs_show(struct kobject *kobj, struct attribute *attr, char *buffer) +{ + u8 val=0,ret=0,year=0,month=0,day=0,cpld_m=0,cpld_1=0,cpld_2=0; + + if (0 == strcmp(attr->name, "read")) + { + val = lpc_iic_getbyte(NULL,param_read.addr); + ret = sprintf(buffer,"read : addr = 0x%x val = 0x%x\n",param_read.addr, val); + + } + else if (0 == strcmp(attr->name, "write")) + { + lpc_iic_setbyte(NULL, param_write.addr,param_write.data); + ret = sprintf(buffer,"write : addr = 0x%x val = 0x%x\n",param_write.addr, param_write.data); + } + else if (0 == strcmp(attr->name, "version")) + { + cpld_m = lpc_iic_getbyte(NULL, 0x02); + year = lpc_iic_getbyte(NULL, 0x03); + month = lpc_iic_getbyte(NULL, 0x04); + day = lpc_iic_getbyte(NULL, 0x05); + + cig_cpld_read_slave_cpld_register(0x1d,&cpld_1); + cig_cpld_read_slave_cpld_register(0x1e,&cpld_2); + + ret = sprintf(buffer,"Main CPLD version : V%02x\n"\ + "Main CPLD date : 20%02x-%02x-%02x\n"\ + "Slave 1 CPLD version : V%02x\n"\ + "Slave 2 CPLD version : V%02x\n",cpld_m,year,month,day,cpld_1,cpld_2); + } + if (0 == strcmp(attr->name, "reads")) + { + ret = cig_cpld_read_slave_cpld_register(param_reads.addr,&val); + if (ret < 0) + printk("ERROR:Failed to read slave cpld.\n"); + ret = sprintf(buffer,"reads : addr = 0x%x val = 0x%x\n",param_reads.addr, val); + + } + else if (0 == strcmp(attr->name, "writes")) + { + ret = cig_cpld_write_slave_cpld_register(param_writes.addr,param_writes.data); + if (ret < 0) + printk("ERROR:Failed to read slave cpld.\n"); + ret = sprintf(buffer,"writes : addr = 0x%x val = 0x%x\n",param_writes.addr, param_writes.data); + } + + + return ret; + +} + +static ssize_t cpld_sysfs_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t count) +{ + int param[3]; + + if (0 == strcmp(attr->name, "read")) + { + sscanf(buffer, "0x%02x", ¶m[0]); + param_read.addr = param[0]; + } + else if (0 == strcmp(attr->name, "write")) + { + sscanf(buffer, "0x%2x 0x%02x", ¶m[0], ¶m[1]); + param_write.addr = param[0]; + param_write.data = param[1]; + } + if (0 == strcmp(attr->name, "reads")) + { + sscanf(buffer, "0x%02x", ¶m[0]); + param_reads.addr = param[0]; + } + else if (0 == strcmp(attr->name, "writes")) + { + sscanf(buffer, "0x%2x 0x%02x", ¶m[0], ¶m[1]); + param_writes.addr = param[0]; + param_writes.data = param[1]; + } + return count; +} + + + +static struct sysfs_ops cpld_sysfs_ops = +{ + .show = cpld_sysfs_show, + .store = cpld_sysfs_store, +}; + +static struct kobj_type cpld_kobj_type = +{ + .release = cpld_sysfs_kobj_release, + .sysfs_ops = &cpld_sysfs_ops, + .default_attrs = NULL, +}; + + +static const char driver_name[] = "cpld_drv"; +static atomic_t cpld_available = ATOMIC_INIT(1); +static struct class *cpld_class; +static struct device *cpld_dev; + + + +#define CPLD_IOC_MAGIC '[' + +#define CPLD_IOC_RDREG _IOR(CPLD_IOC_MAGIC, 0, struct cpld_rw_msg) +#define CPLD_IOC_WRREG _IOW(CPLD_IOC_MAGIC, 1, struct cpld_rw_msg) + +#define CPLD_IOC_MAXNR 2 + + +int cpld_open(struct inode *inode, struct file *filp) +{ + struct cpld_dev_type *dev; + + if (! atomic_dec_and_test(&cpld_available)) { + atomic_inc(&cpld_available); + return -EBUSY; + } + + dev = container_of(inode->i_cdev, struct cpld_dev_type, cdev); + filp->private_data = dev; + + return 0; +} + +int cpld_release(struct inode *inode, struct file *flip) +{ + atomic_inc(&cpld_available); + return 0; +} + + +long cpld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int rc = 0; + int err = 0; + struct cpld_dev_type *dev = (struct cpld_dev_type *)filp->private_data; + struct cpld_rw_msg msg; + + if (_IOC_TYPE(cmd) != CPLD_IOC_MAGIC) + return -ENOTTY; + if (_IOC_NR(cmd) > CPLD_IOC_MAXNR) + return -ENOTTY; + + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; + + switch(cmd){ + case CPLD_IOC_RDREG: + rc = copy_from_user(&msg, (void __user *)arg, sizeof(msg)); + if (!rc) { + msg.data = lpc_cpld_getbyte(dev, msg.addr); + rc = copy_to_user((void __user *)arg, &msg, sizeof(msg)); + } + break; + + case CPLD_IOC_WRREG: + rc = copy_from_user(&msg, (void __user *)arg, sizeof(msg)); + if (!rc) { + lpc_cpld_setbyte(dev, msg.addr, msg.data); + } + break; + default: + rc = -ENOTTY; + break; + } + up(&dev->sem); + + return rc; +} + +struct file_operations cpld_fops = { + .owner = THIS_MODULE, + .open = cpld_open, + .unlocked_ioctl = cpld_ioctl, + .release = cpld_release, +}; + + +static void cpld_setup_cdev(struct cpld_dev_type *dev) +{ + int err, devno = MKDEV(cpld_major, cpld_minor); + + cdev_init(&dev->cdev, &cpld_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &cpld_fops; + err = cdev_add(&dev->cdev, devno, 1); + + if (err) + DEB2(printk(KERN_NOTICE "Error %d adding cpld", err);) +} +/********************************************** End ********************************************************/ + + + + +/********************************************** Start ********************************************************/ +#include +#include +#include + +static spinlock_t irq_inter_lock; +static struct delayed_work irq_inter_work; +static unsigned long irq_inter_delay; + + +static int cig_cpld_write_slave_cpld_register(u8 reg_addr, u8 reg_data) +{ + u8 read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + DEB2(printk("<=======write=========>")); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, reg_addr << 1); + DEB2(printk("[62]=%x\n",reg_addr << 1)); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_TX, reg_data); + DEB2(printk("[63]=%x\n",reg_data)); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + DEB2(printk("[65]=%x\n",0x80)); + do{ + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &read_status); + DEB2(printk("[66]=%x\n",read_status)); + udelay(60); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(read_status != 0x02); + DEB2(printk("<=======write=========>")); + + + if(wait_time_out == 0) + return -1; + + return 1; +} + + +static int cig_cpld_read_slave_cpld_register(u8 reg_addr, u8 *reg_data) +{ + u8 read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + DEB2(printk("<========read=========>")); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, reg_addr << 1 | 1); + DEB2(printk("[62]=%x\n",reg_addr << 1 | 1)); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + DEB2(printk("[65]=%x\n",0x80)); + do{ + udelay(60); + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &read_status); + DEB2(printk("[66]=%x\n",read_status)); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(read_status != 0x01); + + cig_cpld_read_register(ADDR_REG_SFP_STATUS_RX,reg_data); + DEB2(printk("[64]=%x\n",*reg_data)); + DEB2(printk("<========read=========>")); + + if(wait_time_out == 0) + return -1; + + return 1; +} + + + +struct sock *nlsk = NULL; +extern struct net init_net; +#define NETLINK_TEST 26 +#define MSG_LEN 125 +#define USER_PORT 100 +static u32 irq_present_status_low_current,irq_present_status_low_next; +static u32 irq_present_status_high_current,irq_present_status_high_next; +static u32 irq_tx_fault_status_low_current,irq_tx_fault_status_low_next; +static u32 irq_tx_fault_status_high_current,irq_tx_fault_status_high_next; +static u32 irq_rx_lost_status_low_current,irq_rx_lost_status_low_next; +static u32 irq_rx_lost_status_high_current,irq_rx_lost_status_high_next; + +static u8 irq_present_qsfp_current,irq_present_qsfp_next; +static u8 irq_interrupt_qsfp_current,irq_interrupt_qsfp_next; + +struct input_dev *cpld_input_dev; + + + +int send_usrmsg(char *pbuf, uint16_t len) +{ + struct sk_buff *nl_skb; + struct nlmsghdr *nlh; + + int ret; + + + nl_skb = nlmsg_new(len, GFP_ATOMIC); + if(!nl_skb) + { + printk("netlink alloc failure\n"); + return -1; + } + + + nlh = nlmsg_put(nl_skb, 0, 0, NETLINK_TEST, len, 0); + if(nlh == NULL) + { + printk("nlmsg_put failaure \n"); + nlmsg_free(nl_skb); + return -1; + } + + memcpy(nlmsg_data(nlh), pbuf, len); + ret = netlink_unicast(nlsk, nl_skb, USER_PORT, MSG_DONTWAIT); + + return ret; +} + +static void netlink_rcv_msg(struct sk_buff *skb) +{ + + struct nlmsghdr *nlh = NULL; + char *umsg = NULL; + char kmsg[1024] = {0}; + char kmsg_tmp[16] = {0}; + u8 i = 0; + u8 tmp[3]={0}; + + if(skb->len >= nlmsg_total_size(0)) + { + nlh = nlmsg_hdr(skb); + umsg = NLMSG_DATA(nlh); + if(umsg) + { + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_low_current & (0x1 << i))) + { + tmp[0] = 1; + } + else + { + tmp[0] = 0; + } + + if(!(irq_rx_lost_status_low_current & (0x1 << i))) + { + tmp[1] = 1; + } + else + { + tmp[1] = 0; + } + + if(!(irq_tx_fault_status_low_current & (0x1 << i))) + { + tmp[2] = 1; + } + else + { + tmp[2] = 0; + } + memset(kmsg_tmp,0xff,sizeof(kmsg_tmp)); + sprintf(kmsg_tmp,"sfp%02d:%1d:%1d:%1d ",i+1,tmp[0],tmp[1],tmp[2]); + strcat(kmsg,kmsg_tmp); + } + + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_high_current & (0x1 << i))) + { + tmp[0] = 1; + } + else + { + tmp[0] = 0; + } + + if(!(irq_rx_lost_status_high_current & (0x1 << i))) + { + tmp[1] = 1; + } + else + { + tmp[1] = 0; + } + + if(!(irq_tx_fault_status_high_current & (0x1 << i))) + { + tmp[2] = 1; + } + else + { + tmp[2] = 0; + } + memset(kmsg_tmp,0xff,sizeof(kmsg_tmp)); + sprintf(kmsg_tmp,"sfp%02d:%1d:%1d:%1d ",i+25,tmp[0],tmp[1],tmp[2]); + strcat(kmsg,kmsg_tmp); + } + + + for(i = 0;i < 8;i++) + { + if(!(irq_present_qsfp_current & (0x1 << i))) + { + tmp[0] = 1; + } + else + { + tmp[0] = 0; + } + + if(!(irq_interrupt_qsfp_current & (0x1 << i))) + { + tmp[1] = 1; + } + else + { + tmp[1] = 0; + } + + memset(kmsg_tmp,0xff,sizeof(kmsg_tmp)); + sprintf(kmsg_tmp,"qsfp%02d:%1d:%1d:%1d ",i+49,tmp[0],tmp[1],0); + strcat(kmsg,kmsg_tmp); + } + + printk("kernel recv from user: %s\n", umsg); + send_usrmsg(kmsg, strlen(kmsg)); + } + } + + return ; +} + + + +struct netlink_kernel_cfg cfg = { + .input = netlink_rcv_msg, /* set recv callback */ +}; + + + +#define RANGE_OF_BYTE_SHIFT(to_arg,shift,from_arg) {to_arg &= ~(0xff << shift); to_arg |= from_arg << shift;} + + +static void irq_inter_wapper(struct work_struct * work) +{ + + u8 m_data = 0; + u8 data_high8 = 0,data_low8 = 0; + u16 data_16 = 0; + u8 status = 0; + u8 i = 0; + char kmsg[64]={0}; + u8 tmp[3] = {0}; + + DEB2(printk("CPLD_MASTER_INTERRUPT\r\n")); + + m_data = lpc_iic_getbyte(NULL,CPLD_MASTER_INTERRUPT_STATUS_REG); + lpc_iic_setbyte(NULL,CPLD_MASTER_INTERRUPT_STATUS_REG,0xff); + + cig_cpld_write_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_MASK_REG,0xff); + cig_cpld_write_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_MASK_REG,0xff); + if(!(m_data & CPLD_MASTER_INTERRUPT_CPLD1)) + { + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_STATUS_H_REG,&data_high8); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_STATUS_L_REG,&data_low8); + data_16 = data_low8 | data_high8 << 8; + if( + !(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT08) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT16) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT24) + ) + { + if(!(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT08)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT08\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_PRESENT08_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_low_current,0,status); + + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT16)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT16\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_PRESENT16_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_low_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_PRESENT24)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT24\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_PRESENT24_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_low_current,16,status); + } + DEB2(printk("irq_present_status_low_next = %08x irq_present_status_low_current = %08x \n",irq_present_status_low_next,irq_present_status_low_current)); + } + + if( + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST08) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST16) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST24) + ) + { + if(!(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST08)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_RX_LOST08\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_RX_LOST08_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_low_current,0,status); + + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST16)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT16\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_RX_LOST16_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_low_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST24)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_PRESENT24\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_RX_LOST24_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_low_current,16,status); + } + DEB2(printk("irq_rx_lost_status_low_next = %08x irq_rx_lost_status_low_current = %08x \n",irq_rx_lost_status_low_next,irq_rx_lost_status_low_current)); + } + + if( + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST08) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST16) || + !(data_16 & CPLD_SLAVE1_INTERRUPT_RX_LOST24) + ) + { + if(!(data_16 & CPLD_SLAVE1_INTERRUPT_TX_FAULT08)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_TX_FAULT08\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_TX_FAULT08_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_low_current,0,status); + + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_TX_FAULT16)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_TX_FAULT16\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_TX_FAULT16_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_low_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE1_INTERRUPT_TX_FAULT24)) + { + DEB2(printk("CPLD_SLAVE1_INTERRUPT_TX_FAULT24\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE1_TX_FAULT24_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_low_current,16,status); + } + DEB2(printk("irq_tx_fault_status_low_next = %08x irq_tx_fault_status_low_current = %08x \n",irq_tx_fault_status_low_next,irq_tx_fault_status_low_current)); + + } + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_CPLD2)) + { + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_STATUS_H_REG,&data_high8); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_STATUS_L_REG,&data_low8); + data_16 = data_low8 | data_high8 << 8; + if( + !(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT32) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT40) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT48) + ) + { + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT32)) + { + DEB2(printk("CPLD_SLAVE2_PRESENT32_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT32_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_high_current,0,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT40)) + { + DEB2(printk("CPLD_SLAVE2_PRESENT40_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT40_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_high_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT48)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT48\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT48_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_present_status_high_current,16,status); + } + } + + if( + !(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST32) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST40) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST48) + ) + { + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST32)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_RX_LOST32\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_RX_LOST32_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_high_current,0,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST40)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT40\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_RX_LOST40_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_high_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_RX_LOST48)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT48\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_RX_LOST48_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_rx_lost_status_high_current,16,status); + } + + } + + if( + !(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT32) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT40) || + !(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT48) + ) + { + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT32)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_RX_LOST32\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_TX_FAULT32_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_high_current,0,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT40)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT40\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_TX_FAULT40_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_high_current,8,status); + } + else if(!(data_16 & CPLD_SLAVE2_INTERRUPT_TX_FAULT48)) + { + DEB2(printk("CPLD_SLAVE2_INTERRUPT_PRESENT48\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_TX_FAULT48_REG,&status); + RANGE_OF_BYTE_SHIFT(irq_tx_fault_status_high_current,16,status); + } + } + + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_PRESENT56)) + { + DEB2(printk("CPLD_SLAVE2_PRESENT56_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_PRESENT56_REG,&status); + irq_present_qsfp_current = status; + } + + if(!(data_16 & CPLD_SLAVE2_INTERRUPT_QSFP_CR56)) + { + DEB2(printk("CPLD_SLAVE2_QSFP_CR56_REG\r\n")); + cig_cpld_read_slave_cpld_register(CPLD_SLAVE2_QSFP_CR56_REG,&status); + irq_interrupt_qsfp_current = status; + } + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_LSW)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_LSW\r\n")); + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_PSU1)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_PSU1\r\n")); + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_PSU2)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_PSU2\r\n")); + } + else if(!(m_data & CPLD_MASTER_INTERRUPT_6320)) + { + DEB2(printk("CPLD_MASTER_INTERRUPT_6320\r\n")); + } + cig_cpld_write_slave_cpld_register(CPLD_SLAVE1_INTERRUPT_MASK_REG,0x0); + cig_cpld_write_slave_cpld_register(CPLD_SLAVE2_INTERRUPT_MASK_REG,0x0); + + memset(tmp,0xff,sizeof(tmp)); + + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_low_current & (0x1 << i)) && (irq_present_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d is present\r\n",i+1)); + tmp[0] = 1; + } + else if((irq_present_status_low_current & (0x1 << i)) && !(irq_present_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d is absent\r\n",i+1)); + tmp[0] = 0; + } + + if(!(irq_tx_fault_status_low_current & (0x1 << i)) && (irq_tx_fault_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is right\r\n",i+1)); + tmp[1] = 1; + } + else if((irq_tx_fault_status_low_current & (0x1 << i)) && !(irq_tx_fault_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is fault\r\n",i+1)); + tmp[1] = 0; + } + + if(!(irq_rx_lost_status_low_current & (0x1 << i)) && (irq_rx_lost_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is meet\r\n",i+1)); + tmp[2] = 1; + } + else if((irq_rx_lost_status_low_current & (0x1 << i)) && !(irq_rx_lost_status_low_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is lost\r\n",i+1)); + tmp[2] = 0; + } + + if((tmp[0] != 0xff) || (tmp[1] != 0xff) || (tmp[2] != 0xff)) + { + memset(kmsg,0xff,sizeof(kmsg)); + snprintf(kmsg,sizeof(kmsg),"sfp%02d:%1d:%1d:%1d ",i+1,(tmp[0] == 0xff) ? 0:tmp[0],(tmp[1] == 0xff) ? 0:tmp[1],(tmp[2] == 0xff) ? 0:tmp[2]); + break; + } + } + + memset(tmp,0xff,sizeof(tmp)); + for(i = 0;i < 24;i++) + { + if(!(irq_present_status_high_current & (0x1 << i)) && (irq_present_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d is present\r\n",i+25)); + tmp[0] = 1; + } + else if((irq_present_status_high_current & (0x1 << i)) && !(irq_present_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d is absent\r\n",i+25)); + tmp[0] = 0; + + } + + if(!(irq_rx_lost_status_high_current & (0x1 << i)) && (irq_rx_lost_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is meet\r\n",i+25)); + tmp[1] = 1; + } + else if((irq_rx_lost_status_high_current & (0x1 << i)) && !(irq_rx_lost_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d optical is lost\r\n",i+25)); + tmp[1] = 0; + } + + if(!(irq_tx_fault_status_high_current & (0x1 << i)) && (irq_tx_fault_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is right\r\n",i+25)); + tmp[2] = 1; + } + else if((irq_tx_fault_status_high_current & (0x1 << i)) && !(irq_tx_fault_status_high_next & (0x1 << i))) + { + DEB2(printk("SFP%d transmission is fault\r\n",i+25)); + tmp[2] = 0; + } + + if((tmp[0] != 0xff) || (tmp[1] != 0xff) || (tmp[2] != 0xff)) + { + memset(kmsg,0xff,sizeof(kmsg)); + snprintf(kmsg,sizeof(kmsg),"sfp%02d:%1d:%1d:%1d ",i+25,(tmp[0] == 0xff) ? 0:tmp[0],(tmp[1] == 0xff) ? 0:tmp[1],(tmp[2] == 0xff) ? 0:tmp[2]); + break; + } + } + + memset(tmp,0xff,sizeof(tmp)); + for(i = 0 ; i < 8; i++) + { + if(!(irq_present_qsfp_current & (0x1 << i)) && (irq_present_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d is present\r\n",i+49)); + tmp[0] = 1; + } + else if((irq_present_qsfp_current & (0x1 << i)) && !(irq_present_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d is absent\r\n",i+49)); + tmp[0] = 0; + } + + if(!(irq_interrupt_qsfp_current & (0x1 << i)) && (irq_interrupt_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d interrupt is occured \r\n",i+49)); + tmp[1] = 1; + } + else if((irq_interrupt_qsfp_current & (0x1 << i)) && !(irq_interrupt_qsfp_next & (0x1 << i))) + { + DEB2(printk("SFP%d interrupt is cleaned\r\n",i+49)); + tmp[1] = 0; + } + + if((tmp[0] != 0xff) || (tmp[1] != 0xff)) + { + memset(kmsg,0xff,sizeof(kmsg)); + snprintf(kmsg,sizeof(kmsg),"qsfp%02d:%1d:%1d:%1d ",i+49,(tmp[0] == 0xff) ? 0:tmp[0],(tmp[1] == 0xff) ? 0:tmp[1],0); + break; + } + } + + + irq_present_status_low_next = irq_present_status_low_current; + irq_rx_lost_status_low_next = irq_rx_lost_status_low_current; + irq_tx_fault_status_low_next = irq_tx_fault_status_low_current; + irq_present_status_high_next = irq_present_status_high_current; + irq_rx_lost_status_high_next = irq_rx_lost_status_high_current; + irq_tx_fault_status_high_next = irq_tx_fault_status_high_current; + irq_present_qsfp_next = irq_present_qsfp_current; + irq_interrupt_qsfp_next = irq_interrupt_qsfp_current; + + send_usrmsg(kmsg, strlen(kmsg)); +} + +static void disableIrq(unsigned short maskReg, unsigned short mask) +{ + u8 data = 0; + + data = lpc_iic_getbyte(NULL,maskReg); + data |= mask; + lpc_iic_setbyte(NULL,maskReg, data); +} + +static void enableIrq(unsigned short maskReg, unsigned short mask) +{ + unsigned short data; + + data = lpc_iic_getbyte(NULL,maskReg); + data &= ~mask; + lpc_iic_setbyte(NULL,maskReg, data); +} + + +static irqreturn_t irq_inter_isr(int irq, void *handle) +{ + + /* + * use keventd context to read the event fifo registers + * Schedule readout at least 25ms after notification for + * REVID < 4 + */ + + schedule_delayed_work(&irq_inter_work, irq_inter_delay); + + return IRQ_HANDLED; +} + + +#define CIG_CPLD_CHR_NAME "cpld" + + +static int __init cpld_init(void) +{ + int rval,rc=0; + dev_t dev; + u8 s_data; + int isr_GPIO_num = 289; + + DEB2(printk("cpld_init\n");) + +/**************************************************************************************/ + + LPC_INDEX_REG = lpc_base_addr; + LPC_DATA_REG = lpc_base_addr + 1; + + cpld_device = kzalloc(sizeof(struct cpld_dev_type), GFP_KERNEL); + if (!cpld_device) + goto error3; + cpld_device->io_resource = request_region(lpc_base_addr, + lpc_io_space_size, "lpc-i2c"); + if (!cpld_device->io_resource) { + printk("lpc: claim I/O resource fail\n"); + goto error2; + } + sema_init(&cpld_device->sem, 1); + + if (cpld_major) { + dev = MKDEV(cpld_major, cpld_minor); + rc = register_chrdev_region(dev, 1, CIG_CPLD_CHR_NAME); + } else { + rc = alloc_chrdev_region(&dev, cpld_major, 1, CIG_CPLD_CHR_NAME); + cpld_major = MAJOR(dev); + } + + cpld_setup_cdev(cpld_device); + + cpld_class = class_create(THIS_MODULE,CIG_CPLD_CHR_NAME); + if (!cpld_class) { + DEB2(printk("failed to create class\n");) + goto error1; + } + + cpld_class->p->subsys.kobj.ktype= &cpld_kobj_type; + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "read"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "write"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "reads"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "writes"); + cpld_sysfs_add_attr(&cpld_class->p->subsys.kobj, "version"); + + cpld_dev = device_create(cpld_class, NULL, dev, NULL, CIG_CPLD_CHR_NAME); + +/**************************************************************************************/ + + rval = lpc_bus_init(); + rval = lpc_register_driver(&i2c_lpc_driver, 1); + +/**************************************************************************************/ + return 0; +error1: + cdev_del(&cpld_device->cdev); + unregister_chrdev_region(dev, 1); +error2: + release_resource(cpld_device->io_resource); +error3: + kfree(cpld_device); + + return rc; +} + +static void __exit cpld_exit(void) +{ + + DEB2(printk("cpld_exit\n")); + + lpc_unregister_driver(&i2c_lpc_driver); + lpc_bus_exit(); + dev_t devno = MKDEV(cpld_major, cpld_minor); + + cdev_del(&cpld_device->cdev); + if (cpld_class) { + device_destroy(cpld_class, devno); + class_destroy(cpld_class); + } + + if (cpld_device) { + if (cpld_device->io_resource) + release_resource(cpld_device->io_resource); + + kfree(cpld_device); + } + unregister_chrdev_region(devno, 1); + + +} + +module_param(cpld_major, int, S_IRUGO); +module_param(cpld_minor, int, S_IRUGO); +module_param(i2c_debug, int, S_IRUGO); +module_param(board_id, int, S_IRUGO); + +module_init(cpld_init); +module_exit(cpld_exit); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436-56p-cpld driver"); +MODULE_LICENSE("GPL"); + + +/********************************************** End ********************************************************/ + + + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-fan.c b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-fan.c new file mode 100644 index 000000000000..33eaaa840305 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-fan.c @@ -0,0 +1,521 @@ +/* + * A hwmon driver for the CIG cs6436-56P fan + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#define FAN_SPEED_DUTY_TO_CPLD_STEP 10 + +static struct cs6436_56p_fan_data *cs6436_56p_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + + +extern int cig_cpld_write_register(u8 reg_off, u8 val); +extern int cig_cpld_read_register(u8 reg_off, u8 *val); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x41, /* fan enable/disable */ + 0x40, /* fan PWM(for all fan) */ + 0x42, /* front fan 1 speed(rpm) */ + 0x44, /* front fan 2 speed(rpm) */ + 0x46, /* front fan 3 speed(rpm) */ + 0x48, /* front fan 4 speed(rpm) */ + 0x4a, /* front fan 5 speed(rpm) */ + 0x43, /* rear fan 1 speed(rpm) */ + 0x45, /* rear fan 2 speed(rpm) */ + 0x47, /* rear fan 3 speed(rpm) */ + 0x49, /* rear fan 4 speed(rpm) */ + 0x4b, /* rear fan 5 speed(rpm) */ + 0x4c, /* fan direction rear to front or front to rear */ +}; + + +/* Each client has this additional data */ +struct cs6436_56p_fan_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +static struct cs6436_56p_fan_data *fan_data = NULL; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID, +}; + +enum sysfs_fan_attributes { + FAN_STATE_REG, + FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ + FAN1_FRONT_SPEED_RPM, + FAN2_FRONT_SPEED_RPM, + FAN3_FRONT_SPEED_RPM, + FAN4_FRONT_SPEED_RPM, + FAN5_FRONT_SPEED_RPM, + FAN1_REAR_SPEED_RPM, + FAN2_REAR_SPEED_RPM, + FAN3_REAR_SPEED_RPM, + FAN4_REAR_SPEED_RPM, + FAN5_REAR_SPEED_RPM, + FAN_DIRECTION, + FAN1_STATE, + FAN2_STATE, + FAN3_STATE, + FAN4_STATE, + FAN5_STATE, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, +}; + +/* Define attributes + */ +#define DECLARE_FAN_STATE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_state, S_IRUGO, fan_show_value, NULL, FAN##index##_STATE) +#define DECLARE_FAN_STATE_ATTR(index) &sensor_dev_attr_fan##index##_state.dev_attr.attr + +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\ + static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr + +#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IWUSR | S_IRUGO, fan_show_value, set_fan_direction, FAN##index##_DIRECTION) +#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr + + +/* 5 fan state attributes in this platform */ +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(1); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(2); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(3); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(4); +DECLARE_FAN_STATE_SENSOR_DEV_ATTR(5); + + +/* 5 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5); + +/* 5 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5); + +/* 1 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); + +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); + + +static struct attribute *cs6436_56p_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_STATE_ATTR(1), + DECLARE_FAN_STATE_ATTR(2), + DECLARE_FAN_STATE_ATTR(3), + DECLARE_FAN_STATE_ATTR(4), + DECLARE_FAN_STATE_ATTR(5), + DECLARE_FAN_FAULT_ATTR(1), + DECLARE_FAN_FAULT_ATTR(2), + DECLARE_FAN_FAULT_ATTR(3), + DECLARE_FAN_FAULT_ATTR(4), + DECLARE_FAN_FAULT_ATTR(5), + DECLARE_FAN_SPEED_RPM_ATTR(1), + DECLARE_FAN_SPEED_RPM_ATTR(2), + DECLARE_FAN_SPEED_RPM_ATTR(3), + DECLARE_FAN_SPEED_RPM_ATTR(4), + DECLARE_FAN_SPEED_RPM_ATTR(5), + DECLARE_FAN_DUTY_CYCLE_ATTR(), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + NULL +}; + +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + if (reg_val +== 0xFF) { + return 100; + } + return ((u32)(reg_val) * 100)/ 255; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle >= FAN_MAX_DUTY_CYCLE) { + return 0xFF; + } + + return 255 / 10 * (duty_cycle / 10); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 reg_val_to_is_state(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 0 : 1; +} + +static u8 is_fan_fault(struct cs6436_56p_fan_data *data, enum fan_id id) +{ + u8 ret = 1; + int front_fan_index = FAN1_FRONT_SPEED_RPM + id; + int rear_fan_index = FAN1_REAR_SPEED_RPM + id; + + /* Check if the speed of front or rear fan is ZERO, + */ + if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) && + reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) { + ret = 0; + } + + return ret; +} + + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value <= 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + cig_cpld_write_register(fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); + + return count; +} + +static ssize_t set_fan_direction(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value,fan_index; + u8 mask,reg_val; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + fan_index = attr->index - FAN1_DIRECTION; + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (!(value == 0 || value == 1)) + return -EINVAL; + + + cig_cpld_read_register(fan_reg[FAN_DIRECTION],®_val); + + if(value == 1) + { + reg_val |= (1 << fan_index); + } + else + { + reg_val &= ~(1 << fan_index); + } + + cig_cpld_write_register(fan_reg[FAN_DIRECTION], reg_val); + + return count; +} + + + + + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + cs6436_56p_fan_update_device(dev); + + struct cs6436_56p_fan_data *data = fan_data; + + ssize_t ret = 0; + + if (data->valid) { + switch (attr->index) { + + case FAN1_STATE: + case FAN2_STATE: + case FAN3_STATE: + case FAN4_STATE: + case FAN5_STATE: + //printk("FAN_STATE_REG: 0x%x\n", data->reg_val[FAN_STATE_REG]); + //printk("index: %d\n", attr->index); + ret = sprintf(buf, "%d\n", + reg_val_to_is_state(data->reg_val[FAN_STATE_REG], + attr->index - FAN1_STATE)); + break; + case FAN_DUTY_CYCLE_PERCENTAGE: + { + u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_FRONT_SPEED_RPM: + case FAN2_FRONT_SPEED_RPM: + case FAN3_FRONT_SPEED_RPM: + case FAN4_FRONT_SPEED_RPM: + case FAN5_FRONT_SPEED_RPM: + case FAN1_REAR_SPEED_RPM: + case FAN2_REAR_SPEED_RPM: + case FAN3_REAR_SPEED_RPM: + case FAN4_REAR_SPEED_RPM: + case FAN5_REAR_SPEED_RPM: +// printk("FAN_seed_REG: 0x%x\n", data->reg_val[attr->index]); +// printk("index: %d\n", attr->index); + ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + ret = sprintf(buf, "%d\n",reg_val_to_is_state(data->reg_val[FAN_DIRECTION],attr->index - FAN1_DIRECTION)); + break; + default: + break; + } + } + + return ret; +} + +static const struct attribute_group cs6436_56p_fan_group = { + .attrs = cs6436_56p_fan_attributes, +}; + +static struct cs6436_56p_fan_data *cs6436_56p_fan_update_device(struct device *dev) +{ + struct cs6436_56p_fan_data *data = fan_data; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + u8 status; + (void)cig_cpld_read_register(fan_reg[i], &status); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + return data; + } + else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int cs6436_56p_fan_probe(struct platform_device *pdev) +{ + int status = -1; + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &cs6436_56p_fan_group); + if (status) { + goto exit; + + } + + fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(fan_data->hwmon_dev)) { + status = PTR_ERR(fan_data->hwmon_dev); + goto exit_remove; + } + + dev_info(&pdev->dev, "cs6436_56p_fan\n"); + + return 0; + +exit_remove: + sysfs_remove_group(&pdev->dev.kobj, &cs6436_56p_fan_group); +exit: + return status; +} + +static int cs6436_56p_fan_remove(struct platform_device *pdev) +{ + hwmon_device_unregister(fan_data->hwmon_dev); + sysfs_remove_group(&fan_data->pdev->dev.kobj, &cs6436_56p_fan_group); + + return 0; +} + +#define DRVNAME "cs6436_56p_fan" + +static struct platform_driver cs6436_56p_fan_driver = { + .probe = cs6436_56p_fan_probe, + .remove = cs6436_56p_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + + + + + +static int __init cs6436_56p_fan_init(void) +{ + int ret; + + cig_cpld_write_register(0x40, duty_cycle_to_reg_val(50)); + + ret = platform_driver_register(&cs6436_56p_fan_driver); + if (ret < 0) { + goto exit; + } + + fan_data = kzalloc(sizeof(struct cs6436_56p_fan_data), GFP_KERNEL); + if (!fan_data) { + ret = -ENOMEM; + platform_driver_unregister(&cs6436_56p_fan_driver); + goto exit; + } + + mutex_init(&fan_data->update_lock); + fan_data->valid = 0; + + fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(fan_data->pdev)) { + ret = PTR_ERR(fan_data->pdev); + platform_driver_unregister(&cs6436_56p_fan_driver); + kfree(fan_data); + goto exit; + } + +exit: + return ret; +} + +static void __exit cs6436_56p_fan_exit(void) +{ + platform_device_unregister(fan_data->pdev); + platform_driver_unregister(&cs6436_56p_fan_driver); + kfree(fan_data); +} + +MODULE_AUTHOR("CIG"); +MODULE_DESCRIPTION("cs6436_56p_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(cs6436_56p_fan_init); +module_exit(cs6436_56p_fan_exit); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436_56p_fan driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-led.c b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-led.c new file mode 100644 index 000000000000..2f442bac2603 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-led.c @@ -0,0 +1,593 @@ +/* + * A hwmon driver for the CIG cs6436-56P LED + * + * Copyright (C) 2018 Cambridge, Inc. + + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int cig_cpld_write_register(u8 reg_off, u8 val); + +extern int cig_cpld_read_register(u8 reg_off, u8 *val); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern void led_classdev_resume(struct led_classdev *led_cdev); +extern void led_classdev_suspend(struct led_classdev *led_cdev); + +#define DRVNAME "cs6436_56p_led" + +struct cs6436_56p_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[6]; /* 0: system & location + 1: PSU1 &PSU12 + 2: fan & management + 3: console & ToD + 4-5 : fan1-fan5*/ +}; + +static struct cs6436_56p_led_data *ledctl = NULL; + +/* LED related data + */ +#define LED_TYPE_PSU1_REG_MASK 0x0C +#define LED_MODE_PSU1_GREEN_MASK 0x08 +#define LED_MODE_PSU1_RED_MASK 0x04 +#define LED_MODE_PSU1_AMBER_MASK 0x0C +#define LED_MODE_PSU1_OFF_MASK 0x00 + +#define LED_TYPE_PSU2_REG_MASK 0x30 +#define LED_MODE_PSU2_GREEN_MASK 0x20 +#define LED_MODE_PSU2_RED_MASK 0x10 +#define LED_MODE_PSU2_AMBER_MASK 0x30 +#define LED_MODE_PSU2_OFF_MASK 0x00 + +#define LED_TYPE_SYS_REG_MASK 0xF0 +#define LED_MODE_SYS_GREEN_MASK 0x40 +#define LED_MODE_SYS_RED_MASK 0x20 +#define LED_MODE_SYS_AMBER_MASK 0x60 +#define LED_MODE_SYS_AMBER_FLASHING_MASK 0x70 +#define LED_MODE_SYS_OFF_MASK 0x00 + +#define LED_TYPE_RES_REG_MASK 0x0F +#define LED_MODE_RES_GREEN_MASK 0x04 +#define LED_MODE_RES_RED_MASK 0x02 +#define LED_MODE_RES_AMBER_MASK 0x06 +#define LED_MODE_RES_AMBER_FLASHING_MASK 0x07 +#define LED_MODE_RES_OFF_MASK 0x00 + +#define LED_TYPE_FAN_REG_MASK 0x03 +#define LED_MODE_FAN_GREEN_MASK 0x02 +#define LED_MODE_FAN_RED_MASK 0x01 +#define LED_MODE_FAN_AMBER_MASK 0x03 +#define LED_MODE_FAN_OFF_MASK 0x00 + +#define LED_TYPE_FAN1_REG_MASK 0x03 +#define LED_TYPE_FAN2_REG_MASK 0x0C +#define LED_TYPE_FAN3_REG_MASK 0x30 +#define LED_TYPE_FAN4_REG_MASK 0xC0 +#define LED_TYPE_FAN5_REG_MASK 0x03 + +#define LED_MODE_FANX_GREEN_MASK 0x02 +#define LED_MODE_FANX_RED_MASK 0x01 +#define LED_MODE_FANX_AMBER_MASK 0x03 +#define LED_MODE_FANX_OFF_MASK 0x00 + +enum led_type { + LED_TYPE_SYS, + LED_TYPE_PSU2, + LED_TYPE_PSU1, + LED_TYPE_FAN, + LED_TYPE_FAN1, + LED_TYPE_FAN2, + LED_TYPE_FAN3, + LED_TYPE_FAN4, + LED_TYPE_FAN5, +}; + +static const u8 led_reg[] = { + 0x30, /* system & reserved*/ + 0x31, /* fan & PSU1 & PSU2 */ + 0x32, /* FAN5 LED */ + 0x33, /* FAN1-4 LED */ +}; + + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_GREEN_FLASHING, + LED_MODE_AMBER_FLASHING, + LED_MODE_RED_FLASHING, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + int type_mask; + enum led_light_mode mode; + int mode_mask; +}; + +static struct led_type_mode led_type_mode_data[] = { +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU1_GREEN_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU1_AMBER_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_RED, LED_MODE_PSU1_RED_MASK}, +{LED_TYPE_PSU1, LED_TYPE_PSU1_REG_MASK, LED_MODE_OFF, LED_MODE_PSU1_OFF_MASK}, + +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_GREEN, LED_MODE_PSU2_GREEN_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_AMBER, LED_MODE_PSU2_AMBER_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_RED, LED_MODE_PSU2_RED_MASK}, +{LED_TYPE_PSU2, LED_TYPE_PSU2_REG_MASK, LED_MODE_OFF, LED_MODE_PSU2_OFF_MASK}, + +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_GREEN, LED_MODE_SYS_GREEN_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_AMBER, LED_MODE_SYS_AMBER_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_RED, LED_MODE_SYS_RED_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_AMBER_FLASHING, LED_MODE_SYS_AMBER_FLASHING_MASK}, +{LED_TYPE_SYS, LED_TYPE_SYS_REG_MASK, LED_MODE_OFF, LED_MODE_SYS_OFF_MASK}, + +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_GREEN, LED_MODE_FAN_GREEN_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_AMBER, LED_MODE_FAN_AMBER_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_RED, LED_MODE_FAN_RED_MASK}, +{LED_TYPE_FAN, LED_TYPE_FAN_REG_MASK, LED_MODE_OFF, LED_MODE_FAN_OFF_MASK}, + +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 0}, +{LED_TYPE_FAN1, LED_TYPE_FAN1_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 2}, +{LED_TYPE_FAN2, LED_TYPE_FAN2_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 2}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 4}, +{LED_TYPE_FAN3, LED_TYPE_FAN3_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 4}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 6}, +{LED_TYPE_FAN4, LED_TYPE_FAN4_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 6}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_GREEN, LED_MODE_FANX_GREEN_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_RED, LED_MODE_FANX_RED_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_AMBER, LED_MODE_FANX_AMBER_MASK << 0}, +{LED_TYPE_FAN5, LED_TYPE_FAN5_REG_MASK, LED_MODE_OFF, LED_MODE_FANX_OFF_MASK << 0}, +}; + +struct fanx_info_s { + u8 cname; /* device name */ + enum led_type type; + u8 reg_id; /* map to led_reg & reg_val */ +}; + +static struct fanx_info_s fanx_info[] = { + {'1', LED_TYPE_FAN1, 3}, + {'2', LED_TYPE_FAN2, 3}, + {'3', LED_TYPE_FAN3, 3}, + {'4', LED_TYPE_FAN4, 3}, + {'5', LED_TYPE_FAN5, 2}, +}; + + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_mask) + { + return led_type_mode_data[i].mode; + } + } + + return 0; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + reg_val = led_type_mode_data[i].mode_mask | + (reg_val & (~led_type_mode_data[i].type_mask)); + break; + } + + return reg_val; +} + +static void cs6436_56p_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting cs6436_56p_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + u8 status; + cig_cpld_read_register(led_reg[i], &status); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void cs6436_56p_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + u8 reg_val; + mutex_lock(&ledctl->update_lock); + + cig_cpld_read_register(reg, ®_val); + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + + cig_cpld_write_register(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void cs6436_56p_led_fanx_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (led_cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + + cs6436_56p_led_set(led_cdev, led_light_mode, led_reg[reg_id], led_type1); + return; + } + } +} + + +static enum led_brightness cs6436_56p_led_fanx_get(struct led_classdev *cdev) +{ + enum led_type led_type1; + int reg_id; + int i, nsize; + int ncount = sizeof(fanx_info)/sizeof(struct fanx_info_s); + + for(i=0;iname); + + if (cdev->name[nsize-1] == fanx_info[i].cname) + { + led_type1 = fanx_info[i].type; + reg_id = fanx_info[i].reg_id; + cs6436_56p_led_update(); + return led_reg_val_to_light_mode(led_type1, ledctl->reg_val[reg_id]); + } + } + + return led_reg_val_to_light_mode(LED_TYPE_FAN1, ledctl->reg_val[5]); +} + + +static void cs6436_56p_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs6436_56p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU1); +} + +static enum led_brightness cs6436_56p_led_psu1_get(struct led_classdev *cdev) +{ + cs6436_56p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[1]); +} + +static void cs6436_56p_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs6436_56p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_PSU2); +} + +static enum led_brightness cs6436_56p_led_psu2_get(struct led_classdev *cdev) +{ + cs6436_56p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[1]); +} + +static void cs6436_56p_led_sys_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs6436_56p_led_set(led_cdev, led_light_mode,led_reg[0], LED_TYPE_SYS); +} + +static enum led_brightness cs6436_56p_led_sys_get(struct led_classdev *cdev) +{ + cs6436_56p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_SYS, ledctl->reg_val[0]); +} + + +static enum led_brightness cs6436_56p_led_fan_get(struct led_classdev *cdev) +{ + cs6436_56p_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[1]); +} + +static void cs6436_56p_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + cs6436_56p_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_FAN); +} + + +static struct led_classdev cs6436_56p_leds[] = { + [LED_TYPE_SYS] = { + .name = "cs6436_56p_led::sys", + .default_trigger = "unused", + .brightness_set = cs6436_56p_led_sys_set, + .brightness_get = cs6436_56p_led_sys_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "cs6436_56p_led::fan", + .default_trigger = "unused", + .brightness_set = cs6436_56p_led_fan_set, + .brightness_get = cs6436_56p_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + + [LED_TYPE_PSU1] = { + .name = "cs6436_56p_led::psu1", + .default_trigger = "unused", + .brightness_set = cs6436_56p_led_psu1_set, + .brightness_get = cs6436_56p_led_psu1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "cs6436_56p_led::psu2", + .default_trigger = "unused", + .brightness_set = cs6436_56p_led_psu2_set, + .brightness_get = cs6436_56p_led_psu2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + + [LED_TYPE_FAN1] = { + .name = "cs6436_56p_led::fan1", + .default_trigger = "unused", + .brightness_set = cs6436_56p_led_fanx_set, + .brightness_get = cs6436_56p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN2] = { + .name = "cs6436_56p_led::fan2", + .default_trigger = "unused", + .brightness_set = cs6436_56p_led_fanx_set, + .brightness_get = cs6436_56p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN3] = { + .name = "cs6436_56p_led::fan3", + .default_trigger = "unused", + .brightness_set = cs6436_56p_led_fanx_set, + .brightness_get = cs6436_56p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN4] = { + .name = "cs6436_56p_led::fan4", + .default_trigger = "unused", + .brightness_set = cs6436_56p_led_fanx_set, + .brightness_get = cs6436_56p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN5] = { + .name = "cs6436_56p_led::fan5", + .default_trigger = "unused", + .brightness_set = cs6436_56p_led_fanx_set, + .brightness_get = cs6436_56p_led_fanx_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + } +}; + +static int cs6436_56p_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(cs6436_56p_leds); i++) { + led_classdev_suspend(&cs6436_56p_leds[i]); + } + + return 0; +} + +static int cs6436_56p_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(cs6436_56p_leds); i++) { + led_classdev_resume(&cs6436_56p_leds[i]); + } + + return 0; +} + +static int cs6436_56p_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(cs6436_56p_leds); i++) { + ret = led_classdev_register(&pdev->dev, &cs6436_56p_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(cs6436_56p_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&cs6436_56p_leds[i]); + } + } + + return ret; +} + +static int cs6436_56p_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(cs6436_56p_leds); i++) { + led_classdev_unregister(&cs6436_56p_leds[i]); + } + + return 0; +} + +static struct platform_driver cs6436_56p_led_driver = { + .probe = cs6436_56p_led_probe, + .remove = cs6436_56p_led_remove, + .suspend = cs6436_56p_led_suspend, + .resume = cs6436_56p_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int cs6436_56p_led_default(void) +{ + cig_cpld_write_register(0x30, 0x40);// system green led solid on +} + +static int __init cs6436_56p_led_init(void) +{ + int ret; + + ret = platform_driver_register(&cs6436_56p_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct cs6436_56p_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&cs6436_56p_led_driver); + goto exit; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + platform_driver_unregister(&cs6436_56p_led_driver); + kfree(ledctl); + goto exit; + } + + cs6436_56p_led_default(); + +exit: + return ret; +} + +static void __exit cs6436_56p_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&cs6436_56p_led_driver); + kfree(ledctl); +} + +module_init(cs6436_56p_led_init); +module_exit(cs6436_56p_led_exit); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436_56p_led driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-psu.c b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-psu.c new file mode 100644 index 000000000000..1a4734d4ba25 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-psu.c @@ -0,0 +1,943 @@ +/* + * A hwmon driver for the CIG cs6436-56P Power Module + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-algo-lpc.h" + + + +#define MAX_FAN_DUTY_CYCLE 100 + +/* Address scanned */ +static const unsigned short normal_i2c[] = {I2C_CLIENT_END }; + +/* This is additional data */ +struct cs6436_56p_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; /* In jiffies */ + + /* Registers value */ + u8 vout_mode; + u16 v_in; + u16 v_out; + u16 i_in; + u16 i_out; + u16 p_in; + u16 p_out; + u16 temp_input[3]; + u8 temp_fault; + u8 fan_fault; + u16 fan_duty_cycle[2]; + u16 fan_speed[2]; + u8 mfr_id[8]; + u8 mfr_model[20]; + u8 mfr_serial[20]; + u8 psu_is_present; + u8 psu_is_good; + struct i2c_client *client; + struct bin_attribute *bin; /* eeprom data */ +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *dev_attr, const char *buf, size_t count); +static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_fan_fault(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_fan_warning(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_temp_fault(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_temp_warning(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_vout_data(struct device *dev, struct device_attribute *dev_attr, char *buf); +static int cs6436_56p_psu_read_byte(struct i2c_client *client, u8 reg); +static int cs6436_56p_psu_read_word(struct i2c_client *client, u8 reg); +static int cs6436_56p_psu_write_word(struct i2c_client *client, u8 reg, u16 value); +static int cs6436_56p_psu_read_block(struct i2c_client *client, u8 command, u8 *data, int data_len); +static struct cs6436_56p_psu_data *cs6436_56p_psu_update_device(struct device *dev); +static ssize_t for_ascii(struct device *dev, struct device_attribute *dev_attr, char *buf); +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf); + +enum cs6436_56p_psu_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_TEMP2_INPUT, + PSU_TEMP3_INPUT, + PSU_TEMP_FAULT, + PSU_TEMP_WARN, + PSU_FAN1_FAULT, + PSU_FAN1_WARN, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_MFR_ID, + PSU_MFR_MODEL, + PSU_MFR_SERIAL, + PSU_PRESENT, + PSU_P_GOOD, +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + + bool is_negative = valid_data >> (valid_bit - 1); + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct i2c_client *client = to_i2c_client(dev); + struct cs6436_56p_psu_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + if (data->valid != 1) + { + return -ENODEV; + } + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + cs6436_56p_psu_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t for_linear_data(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + if (data->valid != 1) + { + return -ENODEV; + } + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_TEMP2_INPUT: + value = data->temp_input[1]; + break; + case PSU_TEMP3_INPUT: + value = data->temp_input[2]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? \ + sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) :\ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_fan_fault(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev); + + if (data->valid != 1) + { + return -ENODEV; + } + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t for_fan_warning(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev); + + if (data->valid != 1) + { + return -ENODEV; + } + + u8 shift = (attr->index == PSU_FAN1_WARN) ? 5 : 4; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t for_temp_fault(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev); + + if (data->valid != 1) + { + return -ENODEV; + } + + + + return sprintf(buf, "%d\n", data->temp_fault >> 7); +} + +static ssize_t for_temp_warning(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev); + if (data->valid != 1) + { + return -ENODEV; + } + + + return sprintf(buf, "%d\n", data->temp_fault >> 6); +} +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + if (data->valid != 1) + { + return -ENODEV; + } + + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", ((mantissa * multiplier) >> (-exponent))); +} + +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev); + u8 *ptr = NULL; + + if (data->valid != 1) + { + return -ENODEV; + } + + switch (attr->index) { + case PSU_MFR_ID: + ptr = data->mfr_id + 1; + break; + case PSU_MFR_MODEL: + ptr = data->mfr_model + 1; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial + 1; + break; + default: + return 0; + } + return sprintf(buf, "%s\n", ptr); +} + + +static ssize_t for_status(struct device *dev, struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct cs6436_56p_psu_data *data = cs6436_56p_psu_update_device(dev); + u8 *ptr = NULL; + + u8 status = 0; + + if (attr->index == PSU_PRESENT) { + status = data->psu_is_present; + } + else { /* PSU_POWER_GOOD */ + if (!data->valid) { + return -ENODEV; + } + + status = data->psu_is_good; + } + + return sprintf(buf, "%d\n", status); +} + + +static int cs6436_56p_psu_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cs6436_56p_psu_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int cs6436_56p_psu_write_word(struct i2c_client *client, u8 reg, \ + u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags |= I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, reg, + I2C_SMBUS_WORD_DATA, &data); + +} + +static int cs6436_56p_psu_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, + data); + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; +abort: + return result; + +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + + + +#define EEPROM_NAME "psu_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ + +/* Platform dependent --- */ +static ssize_t psu_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ + int status, retry = 3; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(100); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; + +} + + +static ssize_t psu_page_write(struct i2c_client *client,const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + + + while (count) { + ssize_t status; + + status = psu_eeprom_write(client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + + return retval; +} + + + +static ssize_t psu_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct cs6436_56p_psu_data *data; + ssize_t retval = 0; + struct i2c_client *client; + + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + client = to_i2c_client(container_of(kobj, struct device, kobj)); + + mutex_lock(&data->update_lock); + retval = psu_page_write(client, buf, off, count); + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t psu_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int status, retry = 3; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(100); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + +abort: + return status; +} + + + +static ssize_t psu_page_read(struct i2c_client *client,char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + printk("Count = 0, return"); + return count; + } + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + + + while (count) { + ssize_t status; + + status = psu_eeprom_read(client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + + return retval; + +} + + +static ssize_t psu_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct cs6436_56p_psu_data *data; + struct i2c_client *client; + ssize_t retval = 0; + + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + client = to_i2c_client(container_of(kobj, struct device, kobj)); + mutex_lock(&data->update_lock); + retval = psu_page_read(client, buf, off, count); + mutex_unlock(&data->update_lock); + + return retval; +} + + + +static int psu_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = psu_bin_read; + eeprom->write = psu_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + + +static int psu_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + + +static int psu_i2c_check_functionality(struct i2c_client *client) +{ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK); +} + + + +static int psu_eeprom_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + int status; + + struct cs6436_56p_psu_data *data; + + if (!psu_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + data->bin = kzalloc(sizeof(struct bin_attribute), GFP_KERNEL); + if (!data->bin) { + status = -ENOMEM; + goto eeprom_bin_error; + } + + /* init eeprom */ + status = psu_sysfs_eeprom_init(&client->dev.kobj, data->bin); + if (status) { + status = -ENOMEM; + goto sys_init_error; + } + + dev_info(&client->dev, "psu eeprom '%s'\n", client->name); + + return 0; + + sys_init_error: + kfree(data->bin); + + eeprom_bin_error: + kfree(data); + + exit: + return status; +} + + + + +static struct cs6436_56p_psu_data *cs6436_56p_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cs6436_56p_psu_data *data = i2c_get_clientdata(client); + + + mutex_lock(&data->update_lock); + + + if (time_after(jiffies, data->last_updated)) { + int i, status; + u8 command; + struct reg_data_byte regs_byte[] = { + {0x20, &data->vout_mode}, + {0x81, &data->fan_fault}, + {0x7d, &data->temp_fault}, + }; + struct reg_data_word regs_word[] = { + {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x90, &(data->fan_speed[0])}, + }; + data->valid = 1; + + dev_dbg(&client->dev, "start data update\n"); + + /* one milliseconds from now */ + data->last_updated = jiffies + HZ / 1000; + + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = cs6436_56p_psu_read_byte(client, + regs_byte[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + *(regs_byte[i].value) = 0; + data->valid = 0; + } else { + *(regs_byte[i].value) = status; + } + } + + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = cs6436_56p_psu_read_word(client, + regs_word[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + *(regs_word[i].value) = 0; + data->valid = 0; + } else { + *(regs_word[i].value) = status; + } + } + + command = 0x99; /* PSU mfr_id */ + status = cs6436_56p_psu_read_block(client, command, + data->mfr_id, ARRAY_SIZE(data->mfr_id) - 1); + data->mfr_id[ARRAY_SIZE(data->mfr_id) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + memset(data->mfr_id, 0, sizeof(data->mfr_id)); + data->valid = 0; + } + + command = 0x9a; /* PSU mfr_model */ + status = cs6436_56p_psu_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + memset(data->mfr_model, 0, sizeof(data->mfr_id)); + data->valid = 0; + } + + command = 0x9e; /* PSU mfr_serial */ + status = cs6436_56p_psu_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + memset(data->mfr_serial, 0, sizeof(data->mfr_id)); + data->valid = 0; + } + + data->psu_is_present = strlen(data->mfr_id) > 1 ? 1:0; + if(data->psu_is_present) + { + data->psu_is_good = ((data->fan_fault) || (data->temp_fault))? 0:1; + } + else + { + data->valid = 0; + data->psu_is_good = 0; + } + } + + mutex_unlock(&data->update_lock); + + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp2_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp3_input, S_IRUGO, for_linear_data, NULL, PSU_TEMP3_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, for_temp_fault, NULL, PSU_TEMP_FAULT); +static SENSOR_DEVICE_ATTR(psu_temp_warning, S_IRUGO, for_temp_warning, NULL, PSU_TEMP_WARN); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, for_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_warning, S_IRUGO, for_fan_warning, NULL, PSU_FAN1_WARN); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, for_linear_data, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, for_ascii, NULL, PSU_MFR_ID); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, for_status, NULL, PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, for_status, NULL, PSU_P_GOOD); + + + +static struct attribute *cs6436_56p_psu_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_temp2_input.dev_attr.attr, + &sensor_dev_attr_psu_temp3_input.dev_attr.attr, + &sensor_dev_attr_psu_temp_fault.dev_attr.attr, + &sensor_dev_attr_psu_temp_warning.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_warning.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_mfr_id.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + NULL +}; + +static const struct attribute_group cs6436_56p_psu_group = { + .attrs = cs6436_56p_psu_attributes, +}; + + +static int psu_register_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int status; + + + struct cs6436_56p_psu_data *data; + + if (!psu_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cs6436_56p_psu_group); + if (status) + goto exit_sysfs_create_group; + + cs6436_56p_sysfs_add_client(client); + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_hwmon_device_register; + } + + /* init eeprom */ + + return 0; + + exit_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &cs6436_56p_psu_group); + exit_sysfs_create_group: + kfree(data); + exit: + return status; + +} + + +static int cs6436_56p_psu_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int status; + + if((client->addr == 0x52) ||(client->addr == 0x53)) + { + status = psu_eeprom_probe(client, id); + } + else if((client->addr == 0x5a) ||(client->addr == 0x5b)) + { + status = psu_register_probe(client, id); + } + return status; +} + +static int cs6436_56p_psu_remove(struct i2c_client *client) +{ + cs6436_56p_sysfs_remove_client(client); + + if((client->addr == 0x52) ||(client->addr == 0x53)) + { + struct cs6436_56p_psu_data *data; + data = i2c_get_clientdata(client); + psu_sysfs_eeprom_cleanup(&client->dev.kobj,data->bin); + kfree(data); + } + else if((client->addr == 0x5a) ||(client->addr == 0x5b)) + { + struct cs6436_56p_psu_data *data; + data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &cs6436_56p_psu_group); + kfree(data); + } + + return 0; +} + +enum psu_index +{ + cs6436_56p_psu1, + cs6436_56p_psu2 +}; + +static const struct i2c_device_id cs6436_56p_psu_id[] = { + { "cs6436_56p_psu1", cs6436_56p_psu1 }, + { "cs6436_56p_psu2", cs6436_56p_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs6436_56p_psu_id); + +static struct i2c_driver cs6436_56p_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "cs6436_56p_psu", + }, + .probe = cs6436_56p_psu_probe, + .remove = cs6436_56p_psu_remove, + .id_table = cs6436_56p_psu_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(cs6436_56p_psu_driver); + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436_56p_psu driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-sfp.c b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-sfp.c new file mode 100644 index 000000000000..5665fa33048b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-sfp.c @@ -0,0 +1,1713 @@ +/* + * A hwmon driver for the CIG cs6436-56P SFP Module + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-algo-lpc.h" + +#define DRIVER_NAME "cs6436_56p_sfp" /* Platform dependent */ + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#define EEPROM_NAME "sfp_eeprom" +#define EEPROM_SIZE 256 /* 256 byte eeprom */ +#define BIT_INDEX(i) (1ULL << (i)) +#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) +#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) + +#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 +#define SFF8024_DEVICE_ID_SFP 0x3 +#define SFF8024_DEVICE_ID_QSFP 0xC +#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD +#define SFF8024_DEVICE_ID_QSFP28 0x11 + +#define SFF8472_DIAG_MON_TYPE_ADDR 92 +#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 +#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 +#define SFF8472_10G_BASE_MASK 0xF0 + +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 +#define QSFP_RESET_ADDR 0x1b +#define QSFP_INTER_ADDR 0x1a +#define QSFP_LPMODE_ADDR 0x1c + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); +static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); +extern int cig_cpld_read_register(u8 reg_off, u8 *val); +extern int cig_cpld_write_register(u8 reg_off, u8 val); + +static ssize_t qsfp_reset_read(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_reset_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t qsfp_inter_read(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_lpmode_read(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t qsfp_lpmode_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +enum sfp_sysfs_attributes { + PRESENT, + PRESENT_ALL, + PORT_NUMBER, + PORT_TYPE, + DDM_IMPLEMENTED, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + RX_LOS_ALL, + QSFPRESET, + QSFPINT, + QSFPLPMODE +}; + +/* SFP/QSFP common attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); +static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); +static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); + +/* QSFP attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); +static SENSOR_DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, qsfp_reset_read, qsfp_reset_write, QSFPRESET); +static SENSOR_DEVICE_ATTR(sfp_inter, S_IRUGO, qsfp_inter_read, NULL, QSFPINT); +static SENSOR_DEVICE_ATTR(sfp_lpmode, S_IWUSR | S_IRUGO, qsfp_lpmode_read, qsfp_lpmode_write, QSFPLPMODE); +static struct attribute *qsfp_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, + &sensor_dev_attr_sfp_reset.dev_attr.attr, + &sensor_dev_attr_sfp_inter.dev_attr.attr, + &sensor_dev_attr_sfp_lpmode.dev_attr.attr, + NULL +}; + +/* SFP msa attributes for sysfs */ +static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); +static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); +static struct attribute *sfp_msa_attributes[] = { + &sensor_dev_attr_sfp_port_number.dev_attr.attr, + &sensor_dev_attr_sfp_port_type.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, + &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los.dev_attr.attr, + &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, + &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, + NULL +}; + +/* SFP ddm attributes for sysfs */ +static struct attribute *sfp_ddm_attributes[] = { + NULL +}; + +/* Platform dependent +++ */ +#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) + +enum port_numbers { +cs6436_56p_sfp1, cs6436_56p_sfp2, cs6436_56p_sfp3, cs6436_56p_sfp4, +cs6436_56p_sfp5, cs6436_56p_sfp6, cs6436_56p_sfp7, cs6436_56p_sfp8, +cs6436_56p_sfp9, cs6436_56p_sfp10, cs6436_56p_sfp11, cs6436_56p_sfp12, +cs6436_56p_sfp13, cs6436_56p_sfp14, cs6436_56p_sfp15, cs6436_56p_sfp16, +cs6436_56p_sfp17, cs6436_56p_sfp18, cs6436_56p_sfp19, cs6436_56p_sfp20, +cs6436_56p_sfp21, cs6436_56p_sfp22, cs6436_56p_sfp23, cs6436_56p_sfp24, +cs6436_56p_sfp25, cs6436_56p_sfp26, cs6436_56p_sfp27, cs6436_56p_sfp28, +cs6436_56p_sfp29, cs6436_56p_sfp30, cs6436_56p_sfp31, cs6436_56p_sfp32, +cs6436_56p_sfp33, cs6436_56p_sfp34, cs6436_56p_sfp35, cs6436_56p_sfp36, +cs6436_56p_sfp37, cs6436_56p_sfp38, cs6436_56p_sfp39, cs6436_56p_sfp40, +cs6436_56p_sfp41, cs6436_56p_sfp42, cs6436_56p_sfp43, cs6436_56p_sfp44, +cs6436_56p_sfp45, cs6436_56p_sfp46, cs6436_56p_sfp47, cs6436_56p_sfp48, +cs6436_56p_sfp49, cs6436_56p_sfp50, cs6436_56p_sfp51, cs6436_56p_sfp52, +cs6436_56p_sfp53, cs6436_56p_sfp54, cs6436_56p_sfp55, cs6436_56p_sfp56 +}; + +#define I2C_DEV_ID(x) { #x, x} + +static const struct i2c_device_id sfp_device_id[] = { +I2C_DEV_ID(cs6436_56p_sfp1), +I2C_DEV_ID(cs6436_56p_sfp2), +I2C_DEV_ID(cs6436_56p_sfp3), +I2C_DEV_ID(cs6436_56p_sfp4), +I2C_DEV_ID(cs6436_56p_sfp5), +I2C_DEV_ID(cs6436_56p_sfp6), +I2C_DEV_ID(cs6436_56p_sfp7), +I2C_DEV_ID(cs6436_56p_sfp8), +I2C_DEV_ID(cs6436_56p_sfp9), +I2C_DEV_ID(cs6436_56p_sfp10), +I2C_DEV_ID(cs6436_56p_sfp11), +I2C_DEV_ID(cs6436_56p_sfp12), +I2C_DEV_ID(cs6436_56p_sfp13), +I2C_DEV_ID(cs6436_56p_sfp14), +I2C_DEV_ID(cs6436_56p_sfp15), +I2C_DEV_ID(cs6436_56p_sfp16), +I2C_DEV_ID(cs6436_56p_sfp17), +I2C_DEV_ID(cs6436_56p_sfp18), +I2C_DEV_ID(cs6436_56p_sfp19), +I2C_DEV_ID(cs6436_56p_sfp20), +I2C_DEV_ID(cs6436_56p_sfp21), +I2C_DEV_ID(cs6436_56p_sfp22), +I2C_DEV_ID(cs6436_56p_sfp23), +I2C_DEV_ID(cs6436_56p_sfp24), +I2C_DEV_ID(cs6436_56p_sfp25), +I2C_DEV_ID(cs6436_56p_sfp26), +I2C_DEV_ID(cs6436_56p_sfp27), +I2C_DEV_ID(cs6436_56p_sfp28), +I2C_DEV_ID(cs6436_56p_sfp29), +I2C_DEV_ID(cs6436_56p_sfp30), +I2C_DEV_ID(cs6436_56p_sfp31), +I2C_DEV_ID(cs6436_56p_sfp32), +I2C_DEV_ID(cs6436_56p_sfp33), +I2C_DEV_ID(cs6436_56p_sfp34), +I2C_DEV_ID(cs6436_56p_sfp35), +I2C_DEV_ID(cs6436_56p_sfp36), +I2C_DEV_ID(cs6436_56p_sfp37), +I2C_DEV_ID(cs6436_56p_sfp38), +I2C_DEV_ID(cs6436_56p_sfp39), +I2C_DEV_ID(cs6436_56p_sfp40), +I2C_DEV_ID(cs6436_56p_sfp41), +I2C_DEV_ID(cs6436_56p_sfp42), +I2C_DEV_ID(cs6436_56p_sfp43), +I2C_DEV_ID(cs6436_56p_sfp44), +I2C_DEV_ID(cs6436_56p_sfp45), +I2C_DEV_ID(cs6436_56p_sfp46), +I2C_DEV_ID(cs6436_56p_sfp47), +I2C_DEV_ID(cs6436_56p_sfp48), +I2C_DEV_ID(cs6436_56p_sfp49), +I2C_DEV_ID(cs6436_56p_sfp50), +I2C_DEV_ID(cs6436_56p_sfp51), +I2C_DEV_ID(cs6436_56p_sfp52), +I2C_DEV_ID(cs6436_56p_sfp53), +I2C_DEV_ID(cs6436_56p_sfp54), +I2C_DEV_ID(cs6436_56p_sfp55), +I2C_DEV_ID(cs6436_56p_sfp56), +{ /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, sfp_device_id); + +/* + * list of valid port types + * note OOM_PORT_TYPE_NOT_PRESENT to indicate no + * module is present in this port + */ +typedef enum oom_driver_port_type_e { + OOM_DRIVER_PORT_TYPE_INVALID, + OOM_DRIVER_PORT_TYPE_NOT_PRESENT, + OOM_DRIVER_PORT_TYPE_SFP, + OOM_DRIVER_PORT_TYPE_SFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP, + OOM_DRIVER_PORT_TYPE_QSFP_PLUS, + OOM_DRIVER_PORT_TYPE_QSFP28 +} oom_driver_port_type_t; + +enum driver_type_e { + DRIVER_TYPE_SFP_MSA, + DRIVER_TYPE_SFP_DDM, + DRIVER_TYPE_QSFP +}; + +/* Each client has this additional data + */ +struct eeprom_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct bin_attribute bin; /* eeprom data */ +}; + +struct sfp_msa_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u64 status[6]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss + 3 => device id + 4 => 10G Ethernet Compliance Codes + to distinguish SFP or SFP+ + 5 => DIAGNOSTIC MONITORING TYPE */ + struct eeprom_data eeprom; +}; + +struct sfp_ddm_data { + struct eeprom_data eeprom; +}; + +struct qsfp_data { + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status[3]; /* bit0:port0, bit1:port1 and so on */ + /* index 0 => tx_fail + 1 => tx_disable + 2 => rx_loss */ + + u8 device_id; + struct eeprom_data eeprom; +}; + +struct sfp_port_data { + struct mutex update_lock; + enum driver_type_e driver_type; + int port; /* CPLD port index */ + oom_driver_port_type_t port_type; + u64 present; /* present status, bit0:port0, bit1:port1 and so on */ + + struct sfp_msa_data *msa; + struct sfp_ddm_data *ddm; + struct qsfp_data *qsfp; + + struct i2c_client *client; +}; + +static ssize_t show_port_number(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); +} + + + +static int cig_cpld_write_sfp_register(u8 sfp_reg_addr, u8 sfp_write_reg_data) +{ + u8 sfp_read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, sfp_reg_addr << 1); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_TX, sfp_write_reg_data); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + do{ + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &sfp_read_status); + udelay(60); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(sfp_read_status != 0x02); + + if(wait_time_out == 0) + return -1; + + return 1; +} + + +static int cig_cpld_read_sfp_register(u8 sfp_reg_addr, u8 *sfp_read_reg_data) +{ + u8 sfp_read_status = 0; + u8 wait_time_out = WAIT_TIME_OUT_COUNT; + + cig_cpld_write_register(ADDR_REG_SFP_STATUS_ADDR, sfp_reg_addr << 1 | 1); + cig_cpld_write_register(ADDR_REG_SFP_STATUS_COMMAND, 0x80); + do{ + udelay(60); + cig_cpld_read_register(ADDR_REG_SFP_STATUS_STATUS, &sfp_read_status); + wait_time_out--; + if(wait_time_out == 0) + break; + }while(sfp_read_status != 0x01); + + cig_cpld_read_register(ADDR_REG_SFP_STATUS_RX,sfp_read_reg_data); + + if(wait_time_out == 0) + return -1; + + return 1; +} + + + + + + +/* Platform dependent +++ */ +static struct sfp_port_data *sfp_update_present(struct i2c_client *client) +{ + int i = 0, j = 0, status = -1; + unsigned char cpld_reg_data = 0,cpld_reg_addr = 0; + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("Starting sfp present status update"); + mutex_lock(&data->update_lock); + data->present = 0; + + udelay(6000); + + /* Read present status of port 1~48(SFP port) */ + for (i = 0; i < 6; i++) { + cpld_reg_addr = 1 + i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->present |= (u64)cpld_reg_data << (i*8); + + DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); + } + + /* Read present status of port 49-56(QSFP port) */ + cpld_reg_addr = 25; + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + else { + data->present |= (u64)cpld_reg_data << 48; + } + + DEBUG_PRINT("Present status = 0x%lx", data->present); +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i = 0, j = 0; + int status = -1; + unsigned char cpld_reg_data = 0,cpld_reg_addr = 0; + + if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { + return data; + } + + DEBUG_PRINT("Starting cs6436_56p sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->msa->valid = 0; + memset(data->msa->status, 0, sizeof(data->msa->status)); + + udelay(6000); + + /* Read status of port 1~48(SFP port) */ + for (i = 0; i < 6; i++) { + cpld_reg_addr = 13+i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->msa->status[0] |= (u64)cpld_reg_data << (i * 8); + + DEBUG_PRINT("tx rx status[0] = 0x%lx\r\n", data->msa->status[0]); + } + + + for (i = 0; i < 6; i++) { + cpld_reg_addr = 19+i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->msa->status[1] |= (u64)cpld_reg_data << (i * 8); + + DEBUG_PRINT("tx rx status[1] = 0x%lx\r\n", data->msa->status[1]); + } + + for (i = 0; i < 6; i++) { + cpld_reg_addr = 7+i; + + status = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_reg_addr, cpld_reg_data, status); + goto exit; + } + + data->msa->status[2] |= (u64)cpld_reg_data << (i * 8); + + DEBUG_PRINT("tx rx status[2] = 0x%lx\r\n", data->msa->status[2]); + } + + data->msa->valid = 1; + data->msa->last_updated = jiffies; + +exit: + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + unsigned char cpld_reg_data = 0,cpld_reg_addr = 0,cpld_reg_bit = 0,cpld_reg_val = 0; + long disable; + int error; + + if (data->driver_type == DRIVER_TYPE_QSFP) { + return qsfp_set_tx_disable(dev, da, buf, count); + } + + error = kstrtol(buf, 10, &disable); + if (error) { + return error; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + + if(data->port <= 48) { + cpld_reg_addr = 19 + data->port / 8; + cpld_reg_bit = 1 << ((data->port) % 8); + } + + /* Read current status */ + error = cig_cpld_read_sfp_register(cpld_reg_addr, &cpld_reg_data); + + /* Update tx_disable status */ + if (disable) { + data->msa->status[1] |= BIT_INDEX(data->port); + cpld_reg_data |= cpld_reg_bit; + } + else { + data->msa->status[1] &= ~ BIT_INDEX(data->port); + cpld_reg_data &= ~cpld_reg_bit; + } + + error = cig_cpld_write_sfp_register(cpld_reg_addr,cpld_reg_data); + + mutex_unlock(&data->update_lock); + return count; +} +/* Platform dependent --- */ + +static int sfp_is_port_present(struct i2c_client *client, int port) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + data = sfp_update_present(client); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + return !(data->present & BIT_INDEX(data->port)); /* Platform dependent */ +} + +/* Platform dependent +++ */ +static ssize_t show_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + + if (PRESENT_ALL == attr->index) { + int i; + u8 values[7] = {0}; + struct sfp_port_data *data = sfp_update_present(client); + + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = ~(u8)(data->present >> (i * 8)); + } + + /* Return values 1 -> 56 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6]); + } + else { + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + /* PRESENT */ + return sprintf(buf, "%d\n", present); + } +} +/* Platform dependent --- */ + +static struct sfp_port_data *sfp_update_port_type(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + u8 buf = 0; + int status; + + mutex_lock(&data->update_lock); + + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + { + status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + if (buf != SFF8024_DEVICE_ID_SFP) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); + data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; + break; + } + case DRIVER_TYPE_QSFP: + { + status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); + if (unlikely(status < 0)) { + data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; + break; + } + + DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); + switch (buf) { + case SFF8024_DEVICE_ID_QSFP: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; + break; + case SFF8024_DEVICE_ID_QSFP_PLUS: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + case SFF8024_DEVICE_ID_QSFP28: + data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; + break; + default: + data->port_type = buf; + break; + } + + break; + } + default: + break; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static ssize_t show_port_type(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int present = sfp_is_port_present(client, data->port); + + if (IS_ERR_VALUE(present)) { + return present; + } + + if (!present) { + /* port is not present */ + return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); + } + + sfp_update_port_type(dev); + return sprintf(buf, "%d\n", data->port_type); +} + +static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + int i, status = -1; + u8 buf = 0; + u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; + + DEBUG_PRINT(""); + if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { + return data; + } + + DEBUG_PRINT("Starting sfp tx rx status update"); + mutex_lock(&data->update_lock); + data->qsfp->valid = 0; + memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); + + DEBUG_PRINT(""); + /* Notify device to update tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + DEBUG_PRINT(""); + goto exit; + } + } + msleep(200); + DEBUG_PRINT(""); + + /* Read actual tx fault/ tx disable/ rx los status */ + for (i = 0; i < ARRAY_SIZE(reg); i++) { + status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); + if (unlikely(status < 0)) { + DEBUG_PRINT(""); + goto exit; + } + + DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); + data->qsfp->status[i] = (buf & 0xF); + } + + DEBUG_PRINT(""); + data->qsfp->valid = 1; + data->qsfp->last_updated = jiffies; + +exit: + DEBUG_PRINT(""); + mutex_unlock(&data->update_lock); + return (status < 0) ? ERR_PTR(status) : data; +} + +static ssize_t qsfp_inter_read(struct device *dev, struct device_attribute *da, char *buf) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_INTER_ADDR, &cpld_reg_data); + index = data->port - 48; + index = 1 << index; + val = (cpld_reg_data & index) > 0 ? 1 : 0; + + printk("inter read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t qsfp_reset_read(struct device *dev, struct device_attribute *da, char *buf) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_RESET_ADDR, &cpld_reg_data); + index = data->port - 48; + index = 1 << index; + val = (cpld_reg_data & index) > 0 ? 1 : 0; + + printk("reset read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_reset_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + long usrdata; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + ret = kstrtol(buf, 10, &usrdata); + if (ret) { + return ret; + } + + usrdata = usrdata > 0 ? 1 : 0; + index = data->port - 48; + + DEBUG_PRINT("usrdata = %u, index = %hhu\n", usrdata, index); + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_RESET_ADDR, &cpld_reg_data); + if (ret == 1) + { + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + cpld_reg_data &= ~(1 << index); + cpld_reg_data |= usrdata << index; + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + ret = cig_cpld_write_sfp_register(QSFP_RESET_ADDR, cpld_reg_data); + if (1 != ret) + { + DEBUG_PRINT("write failed\n"); + } + } + else + { + DEBUG_PRINT("read failed\n"); + } + + mutex_unlock(&data->update_lock); + + if (ret != 1) + return -1; + + return count; +} + + + + +static ssize_t qsfp_lpmode_read(struct device *dev, struct device_attribute *da, char *buf) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_LPMODE_ADDR, &cpld_reg_data); + index = data->port - 48; + index = 1 << index; + val = (cpld_reg_data & index) > 0 ? 1 : 0; + + printk("lpmode read:data->port = %d, index = %hhu, cpld_reg_data = %hhu\n", data->port, index, cpld_reg_data); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_lpmode_write(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int present; + int status; + u8 val = 0; + int ret = 0; + u8 cpld_reg_data = 0; + u8 index = 0; + long usrdata; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + ret = kstrtol(buf, 10, &usrdata); + if (ret) { + return ret; + } + + usrdata = usrdata > 0 ? 1 : 0; + index = data->port - 48; + + DEBUG_PRINT("usrdata = %u, index = %hhu\n", usrdata, index); + + mutex_lock(&data->update_lock); + + udelay(6000); + /* Read current status */ + ret = cig_cpld_read_sfp_register(QSFP_LPMODE_ADDR, &cpld_reg_data); + if (ret == 1) + { + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + cpld_reg_data &= ~(1 << index); + cpld_reg_data |= usrdata << index; + + DEBUG_PRINT("cpld_reg_data = %x\n", cpld_reg_data); + ret = cig_cpld_write_sfp_register(QSFP_LPMODE_ADDR, cpld_reg_data); + if (1 != ret) + { + DEBUG_PRINT("write failed\n"); + } + } + else + { + DEBUG_PRINT("read failed\n"); + } + + mutex_unlock(&data->update_lock); + + if (ret != 1) + return -1; + + return count; +} + + + +static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + int present; + u8 val = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT(""); + present = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + DEBUG_PRINT(""); + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + DEBUG_PRINT(""); + data = qsfp_update_tx_rx_status(dev); + DEBUG_PRINT(""); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + DEBUG_PRINT(""); + switch (attr->index) { + case TX_FAULT: + val = !!(data->qsfp->status[2] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + case TX_DISABLE: + val = data->qsfp->status[1] & 0xF; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + case RX_LOS: + val = !!(data->qsfp->status[0] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); + break; + default: + break; + } + + DEBUG_PRINT(""); + return sprintf(buf, "%d\n", val); +} + +static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long disable; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (!status) { + /* port is not present */ + return -ENXIO; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + data = qsfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + mutex_lock(&data->update_lock); + + if (attr->index == TX_DISABLE) { + data->qsfp->status[1] = disable & 0xF; + } + else {/* TX_DISABLE1 ~ TX_DISABLE4*/ + if (disable) { + data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); + } + else { + data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); + } + } + + DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); + status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); + if (unlikely(status < 0)) { + count = status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, + char *buf) +{ + int status; + char ddm; + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + status = sfp_is_port_present(client, data->port); + if (IS_ERR_VALUE(status)) { + return status; + } + + if (status == 0) { + /* port is not present */ + return -ENODEV; + } + + status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); + if (unlikely(status < 0)) { + return status; + } + + return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK)); +} + +/* Platform dependent +++ */ +static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + u8 val = 0, index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct sfp_port_data *data = i2c_get_clientdata(client); + + DEBUG_PRINT("driver type = (%d)", data->driver_type); + if (data->driver_type == DRIVER_TYPE_QSFP) { + DEBUG_PRINT(""); + return qsfp_show_tx_rx_status(dev, da, buf); + } + + DEBUG_PRINT(""); + data = sfp_update_tx_rx_status(dev); + if (IS_ERR(data)) { + return PTR_ERR(data); + } + + if(attr->index == RX_LOS_ALL) { + int i = 0; + u8 values[6] = {0}; + + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = (u8)(data->msa->status[2] >> (i * 8)); + } + + /** Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], + values[3], values[4], values[5]); + } + + switch (attr->index) { + case TX_FAULT: + index = 0; + break; + case TX_DISABLE: + index = 1; + break; + case RX_LOS: + index = 2; + break; + default: + break; + } + + val = !!(data->msa->status[index] & BIT_INDEX(data->port)); + return sprintf(buf, "%d\n", val); +} +/* Platform dependent --- */ +static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return data_len; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, command, *data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + return status; + } + + return 1; +#endif + + +} + +static ssize_t sfp_port_write(struct sfp_port_data *data, + const char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Write data to chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_write(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + return sfp_port_write(data, buf, off, count); +} + +static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ +#if USE_I2C_BLOCK_READ + int status, retry = I2C_RW_RETRY_COUNT; + + if (data_len > I2C_SMBUS_BLOCK_MAX) { + data_len = I2C_SMBUS_BLOCK_MAX; + } + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + goto abort; + } + if (unlikely(status != data_len)) { + status = -EIO; + goto abort; + } + + //result = data_len; + +abort: + return status; +#else + int status, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); + goto abort; + } + + *data = (u8)status; + status = 1; + +abort: + return status; +#endif +} + +static ssize_t sfp_port_read(struct sfp_port_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + DEBUG_PRINT("Count = 0, return"); + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(data->client, off, buf, count); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int present; + struct sfp_port_data *data; + DEBUG_PRINT("offset = (%d), count = (%d)", off, count); + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + present = sfp_is_port_present(data->client, data->port); + if (IS_ERR_VALUE(present)) { + return present; + } + + if (present == 0) { + /* port is not present */ + return -ENODEV; + } + + return sfp_port_read(data, buf, off, count); +} + +static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + int err; + + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IWUSR | S_IRUGO; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + err = sysfs_create_bin_file(kobj, eeprom); + if (err) { + return err; + } + + return 0; +} + +static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static const struct attribute_group sfp_msa_group = { + .attrs = sfp_msa_attributes, +}; + +static int sfp_i2c_check_functionality(struct i2c_client *client) +{ +#if USE_I2C_BLOCK_READ + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); +#else + return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); +#endif +} + +static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_msa_data **data) +{ + int status; + struct sfp_msa_data *msa; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); + if (!msa) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = msa; + dev_info(&client->dev, "sfp msa '%s'\n", client->name); + + cs6436_56p_sysfs_add_client(client); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); +exit_free: + kfree(msa); +exit: + + return status; +} + +static const struct attribute_group sfp_ddm_group = { + .attrs = sfp_ddm_attributes, +}; + +static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct sfp_ddm_data **data) +{ + int status; + struct sfp_ddm_data *ddm; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); + if (!ddm) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); + if (status) { + goto exit_remove; + } + + *data = ddm; + dev_info(&client->dev, "sfp ddm '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); +exit_free: + kfree(ddm); +exit: + + return status; +} + +static const struct attribute_group qsfp_group = { + .attrs = qsfp_attributes, +}; + +static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, + struct qsfp_data **data) +{ + int status; + struct qsfp_data *qsfp; + + if (!sfp_i2c_check_functionality(client)) { + status = -EIO; + goto exit; + } + + qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); + if (!qsfp) { + status = -ENOMEM; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &qsfp_group); + if (status) { + goto exit_free; + } + + /* init eeprom */ + status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); + if (status) { + goto exit_remove; + } + + /* Bring QSFPs out of reset */ + //cig_lpc_write(0x62, 0x15, 0x3F); + + *data = qsfp; + dev_info(&client->dev, "qsfp '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &qsfp_group); +exit_free: + kfree(qsfp); +exit: + + return status; +} + +/* Platform dependent +++ */ +static int sfp_device_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct sfp_port_data *data = NULL; + + data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); + if (!data) { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->port = dev_id->driver_data; + data->client = client; + + if (dev_id->driver_data >= cs6436_56p_sfp1 && dev_id->driver_data <= cs6436_56p_sfp48) { + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_SFP_MSA; + return sfp_msa_probe(client, dev_id, &data->msa); + } + else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_SFP_DDM; + return sfp_ddm_probe(client, dev_id, &data->ddm); + } + } + else { /* cs6436_56p_sfp49 ~ cs6436_56p_sfp56 */ + if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { + data->driver_type = DRIVER_TYPE_QSFP; + return qsfp_probe(client, dev_id, &data->qsfp); + } + } + + return -ENODEV; +} +/* Platform dependent --- */ + +static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); + kfree(data); + return 0; +} + +static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); + kfree(data); + return 0; +} + +static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) +{ + sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); + sysfs_remove_group(&client->dev.kobj, &qsfp_group); + kfree(data); + return 0; +} + +static int sfp_device_remove(struct i2c_client *client) +{ + struct sfp_port_data *data = i2c_get_clientdata(client); + + cs6436_56p_sysfs_remove_client(client); + switch (data->driver_type) { + case DRIVER_TYPE_SFP_MSA: + return sfp_msa_remove(client, data->msa); + case DRIVER_TYPE_SFP_DDM: + return sfp_ddm_remove(client, data->ddm); + case DRIVER_TYPE_QSFP: + return qfp_remove(client, data->qsfp); + } + + return 0; +} + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static struct i2c_driver cs6436_56p_sfp_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = sfp_device_probe, + .remove = sfp_device_remove, + .id_table = sfp_device_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(cs6436_56p_sfp_driver); + + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436_56p_sfp driver"); +MODULE_LICENSE("GPL"); + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-sysfs.c b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-sysfs.c new file mode 100644 index 000000000000..89f6bba3aab2 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/modules/x86-64-cig-cs6436-56p-sysfs.c @@ -0,0 +1,335 @@ +/* + * A hwmon driver for the CIG cs6436-56P sysfs Module + * + * Copyright (C) 2018 Cambridge, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i2c-algo-lpc.h" + + +static LIST_HEAD(sysfs_client_list); +static struct mutex list_lock; + +struct sysfs_client_node { + struct i2c_client *client; + struct list_head list; +}; + +#define DEVICE_NAME "cigfs" +static int dev_major; +static struct class *dev_class; +static struct cdev *dev_cdev; +static struct device *dev_device; +static struct class *psu_class; +static struct class *sfp_class; + + +void cs6436_56p_sysfs_add_client(struct i2c_client *client) +{ + struct sysfs_client_node *node = kzalloc(sizeof(struct sysfs_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate sysfs_client_node (0x%x)\n", client->addr); + return; + } + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &sysfs_client_list); + mutex_unlock(&list_lock); +} + +EXPORT_SYMBOL(cs6436_56p_sysfs_add_client); + +void cs6436_56p_sysfs_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct sysfs_client_node *sysfs_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &sysfs_client_list) + { + sysfs_node = list_entry(list_node, struct sysfs_client_node, list); + if (IS_ERR(sysfs_node)) + { + break; + } + if (sysfs_node->client == client) { + found = 1; + break; + } + } + if (found) { + list_del(list_node); + kfree(sysfs_node); + } + + mutex_unlock(&list_lock); +} + +EXPORT_SYMBOL(cs6436_56p_sysfs_remove_client); + +struct class * cs6436_56p_sysfs_create_symclass(char *cls_name) +{ + int rc = 0; + struct class *my_class; +/**************************************************************************************/ + my_class = class_create(THIS_MODULE,cls_name); + if (IS_ERR(my_class)) { + pr_err("failed to create my class\n"); + } + return my_class; + +/**************************************************************************************/ +} + +void cs6436_56p_sysfs_delete_symclass(struct class *my_class) +{ +/**************************************************************************************/ + + if (IS_ERR(my_class)) { + pr_err("Pointer is invaild\n"); + } + class_destroy(my_class); + +/**************************************************************************************/ +} + + + + + +int cs6436_56p_sysfs_create_symlink(struct class *my_class,char * driver_name,char *device_name) +{ + struct list_head *list_node = NULL; + struct sysfs_client_node *sysfs_node = NULL; + int ret = -EPERM; + int rc = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &sysfs_client_list) + { + sysfs_node = list_entry(list_node, struct sysfs_client_node, list); + if (!strcmp(sysfs_node->client->name,driver_name)) { + rc = sysfs_create_link(&my_class->p->subsys.kobj, &sysfs_node->client->dev.kobj,device_name); + if(rc) + { + pr_err("failed to create symlink %d\n",rc); + } + break; + } + } + mutex_unlock(&list_lock); + return ret; +} + + +int cs6436_56p_sysfs_delete_symlink(struct class *my_class,char * driver_name,char *device_name) +{ + struct list_head *list_node = NULL; + struct sysfs_client_node *sysfs_node = NULL; + int ret = -EPERM; + int rc = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &sysfs_client_list) + { + sysfs_node = list_entry(list_node, struct sysfs_client_node, list); + if (!strcmp(sysfs_node->client->name,driver_name)) { + sysfs_remove_link(&my_class->p->subsys.kobj,device_name); + break; + } + } + mutex_unlock(&list_lock); + return ret; +} + + +static int cs6436_56p_sysfs_open(struct inode *inode, struct file *file) +{ + return 0; +} + + + +static ssize_t cs6436_56p_sysfs_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) +{ + char str[10],name[18],port[8]; + int ret; + int i; + memset(str, 0, sizeof(str)); + ret = copy_from_user(str, buf, count); + if (ret) + { + printk(KERN_ERR "copy_from_user fail\n"); + return -EINVAL; + } + + if(!strncmp(str,"start",5)) + { + psu_class = cs6436_56p_sysfs_create_symclass("psu"); + cs6436_56p_sysfs_create_symlink(psu_class,"cs6436_56p_psu1","psu1"); + cs6436_56p_sysfs_create_symlink(psu_class,"cs6436_56p_psu2","psu2"); + sfp_class = cs6436_56p_sysfs_create_symclass("swps"); + for(i = 1; i <= 48;i++) + { + memset(name,0xff,sizeof(name)); + memset(port,0xff,sizeof(port)); + snprintf(name,sizeof(name),"cs6436_56p_sfp%d",i); + snprintf(port,sizeof(port),"port%d",i); + cs6436_56p_sysfs_create_symlink(sfp_class,name,port); + } + } + else if(!strncmp(str,"stop",4)) + { + cs6436_56p_sysfs_delete_symlink(psu_class,"cs6436_56p_psu1","psu1"); + cs6436_56p_sysfs_delete_symlink(psu_class,"cs6436_56p_psu2","psu2"); + cs6436_56p_sysfs_delete_symclass(psu_class); + + for(i = 1; i <= 48;i++) + { + memset(name,0xff,sizeof(name)); + memset(port,0xff,sizeof(port)); + snprintf(name,sizeof(name),"cs6436_56p_sfp%d",i); + snprintf(port,sizeof(port),"port%d",i); + cs6436_56p_sysfs_delete_symlink(sfp_class,name,port); + } + cs6436_56p_sysfs_delete_symclass(sfp_class); + } + return count; +} + + +static struct file_operations cs6436_56p_sysfs_fops = { + .owner = THIS_MODULE, + .open = cs6436_56p_sysfs_open, + .write = cs6436_56p_sysfs_write, +}; + + +static int __init cs6436_56p_sysfs_init(void) +{ + int result = 0; + int err = 0; + dev_t dev = MKDEV(dev_major, 0); + + if (dev_major) + result = register_chrdev_region(dev, 1, DEVICE_NAME); + else { + result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME); + dev_major = MAJOR(dev); + } + if (result < 0) + { + printk("unable to get major %d\n", dev_major); + err= -EINVAL; + } + printk("get major is %d\n", dev_major); + if (dev_major == 0) + dev_major = result; + + dev_cdev= kmalloc(sizeof(struct cdev), GFP_KERNEL); + if(IS_ERR(dev_cdev)) { + err= -ENOMEM; + } + + cdev_init(dev_cdev, &cs6436_56p_sysfs_fops); + dev_cdev->owner = THIS_MODULE; + dev_cdev->ops = &cs6436_56p_sysfs_fops; + err = cdev_add(dev_cdev, dev, 1); + if (err) + { + printk("error %d add fpga ", err); + goto err_malloc; + } + + dev_class = class_create(THIS_MODULE, DEVICE_NAME); + if (IS_ERR(dev_class)) + { + printk("Err:failed in creating class.\n"); + goto err_cdev_add; + } + + dev_device = device_create(dev_class, NULL, MKDEV(dev_major, 0), NULL, DEVICE_NAME); + if (IS_ERR(dev_device)) + { + printk("Err:failed in creating device.\n"); + goto err_class_crt; + } + + mutex_init(&list_lock); + + return err; + + err_class_crt: + cdev_del(dev_cdev); + err_cdev_add: + kfree(dev_cdev); + err_malloc: + unregister_chrdev_region(MKDEV(dev_major,0), 1); + + return err; + +} + +static void __exit cs6436_56p_sysfs_exit(void) +{ + cdev_del(dev_cdev); + printk("cdev_del ok\n"); + device_destroy(dev_class, MKDEV(dev_major, 0)); + + class_destroy(dev_class); + + if(dev_cdev != NULL) + kfree(dev_cdev); + + unregister_chrdev_region(MKDEV(dev_major, 0), 1); + printk("cs6436_56p_sysfs_exit...\r\n"); +} + + +MODULE_AUTHOR("Zhang Peng "); +MODULE_DESCRIPTION("cs6436-56p-sysfs driver"); +MODULE_LICENSE("GPL"); + +module_init(cs6436_56p_sysfs_init); +module_exit(cs6436_56p_sysfs_exit); + + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/service/cs6436-platform-init.service b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/service/cs6436-platform-init.service new file mode 100644 index 000000000000..3936b54dee2f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/service/cs6436-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Cig CS6436-56P Platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/cig_cs6436_util.py install +ExecStop=/usr/local/bin/cig_cs6436_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/service/cs6436-platform-misc.service b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/service/cs6436-platform-misc.service new file mode 100644 index 000000000000..ed44bc0b3438 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/service/cs6436-platform-misc.service @@ -0,0 +1,15 @@ +[Unit] +Description=Cig CS6436-56P Platform miscellaneous service +After=cs6436-platform-init.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/cig_cs6436_misc.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/setup.py b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/setup.py new file mode 100755 index 000000000000..c17c10c83190 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='cs6436-56p', + version='1.0.0', + description='Module to initialize Cig CS6436-56P platforms', + + packages=['cs6436-56p'], + package_dir={'cs6436-56p': 'cs6436-56p/classes'}, + ) diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/utils/cig_cs6436_misc.py b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/utils/cig_cs6436_misc.py new file mode 100755 index 000000000000..56add80221bb --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/utils/cig_cs6436_misc.py @@ -0,0 +1,574 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Cambridge, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import commands +import sys, getopt +import logging +import re +import time +import datetime +from collections import namedtuple +from threading import Thread + +DEBUG = False +i2c_prefix = '/sys/bus/i2c/devices/' +leds_prefix = '/sys/devices/platform/cs6436_56p_led/leds/' +fans_prefix = '/sys/devices/platform/cs6436_56p_fan/' +fansdir_prefix = fans_prefix + 'fan{}_direction' + +ageing_controlfile = '/etc/sonic/agcontrol' +AGFlag = 0 + + +platform_misc_log = '/var/log/platform_misc.log' +misclogger = logging.getLogger('platform_misc') +misclogger.setLevel(logging.INFO) +miscformatter = logging.Formatter('%(asctime)s-%(levelname)s-%(message)s') + +if not os.path.isfile(platform_misc_log): + try: + os.mknod(platform_misc_log) + except: + print 'Failed to creat platform_misc.log' + +fileHandler = logging.FileHandler(platform_misc_log) +fileHandler.setLevel(logging.INFO) +fileHandler.setFormatter(miscformatter) +misclogger.addHandler(fileHandler) + + +starttime = datetime.datetime.now() +IsGetlswt = 0 +coretemp_prefix = '/sys/class/hwmon/hwmon1/' +coretemp_ps = [] +psu1_p = '/sys/bus/i2c/devices/5-005a/psu_present' +psu2_p = '/sys/bus/i2c/devices/5-005b/psu_present' +psu1_d = '/sys/bus/i2c/devices/5-0052/psu_eeprom' +psu2_d = '/sys/bus/i2c/devices/5-0053/psu_eeprom' +psu1led_d = leds_prefix + 'cs6436_56p_led::psu1/brightness' +psu2led_d = leds_prefix + 'cs6436_56p_led::psu2/brightness' +cs6436_ledpath = {'fan':leds_prefix + 'cs6436_56p_led::fan/brightness', + 'fan1':leds_prefix + 'cs6436_56p_led::fan1/brightness', + 'fan2':leds_prefix + 'cs6436_56p_led::fan2/brightness', + 'fan3':leds_prefix + 'cs6436_56p_led::fan3/brightness', + 'fan4':leds_prefix + 'cs6436_56p_led::fan4/brightness', + 'fan5':leds_prefix + 'cs6436_56p_led::fan5/brightness', + 'psu1':leds_prefix + 'cs6436_56p_led::psu1/brightness', + 'psu2':leds_prefix + 'cs6436_56p_led::psu2/brightness', + 'sys':leds_prefix + 'cs6436_56p_led::sys/brightness'} + + +def system_read_filestr(node): + with open(node, 'r') as f: + try: + str = f.read() + except IOError as e: + misclogger.error('Failed to get node, str={}'.format(node)) + return "0" + return str + + +def system_bright_leds(dev, colour): + global AGFlag + + if AGFlag == 1: + return + + cmd = 'echo {} > {}'.format(colour, dev) + log_os_system(cmd, 1) + return + +''' +1: front in tail out +0: front out tail in +''' +def system_getpsu_direction(dev): + try: + with open(dev) as f: + f.seek(0x30) + str = f.read(2) + except IOError as e: + misclogger.error('Failed to get psu eep') + return 1 + if str == 'AA': ## front in tail out + return 1 + elif str == 'RA':## tail in front out + return 0 + else: + misclogger.error('Failed to get psu eep, str={}'.format(str)) + return -1 + + +def system_get_cputype(): + cmdretfd = os.popen("lscpu | grep 'Model name'") + retstring = cmdretfd.read() + endindex = retstring.find('@') - 1 + startindex = retstring[:endindex].rfind(' ') + 1 + cputype = retstring[startindex:endindex] + + return cputype + + +def system_init_coretemppath(): + global coretemp_ps + + cmdstr = "ls {} | grep 'input'".format(coretemp_prefix) + cmdretfd = os.popen(cmdstr) + + coretemppss = cmdretfd.read().splitlines() + if len(coretemppss) < 3: + cputype = system_get_cputype() + misclogger.error('Failed to init core temperature path.' + ' cpu type = {}, num thermal = {}'.format(cputype, len(coretemp_ps))) + return 1 + + for i in range(0,3): + coretemp_ps.append(coretemp_prefix + coretemppss[i]) + + print coretemp_ps + + return 0 + + +class cs6436_fanattr: + def __init__(self, name): + self.name = name + self.direction = 0 + self.direction_p = '' + self.rear = 0 + self.rear_p = '' + self.front = 0 + self.front_p = '' + self.fault = 0 + self.fault_p = '' + self.status = 0 + self.setpath() + self.updatedevice() + + return + + def setpath(self): + self.direction_p = fans_prefix + '{}_direction'.format(self.name) + self.rear_p = fans_prefix + '{}_rear_speed_rpm'.format(self.name) + self.front_p = fans_prefix + '{}_front_speed_rpm'.format(self.name) + self.fault_p = fans_prefix + '{}_fault'.format(self.name) + + return + + def updatedevice(self): + self.direction = int(system_read_filestr(self.direction_p)) + self.rear = int(system_read_filestr(self.rear_p)) + self.front = int(system_read_filestr(self.front_p)) + self.fault = int(system_read_filestr(self.fault_p)) + + return + + def checkspeedrpm(self, speedrpm): + frontrpmexp = speedrpm * 21000 / 100 + rearrpmexp = speedrpm * 19000 / 100 + deviationfront = abs(frontrpmexp - self.front) / float(frontrpmexp) + deviationrear = abs(rearrpmexp - self.rear) / float(rearrpmexp) + + if deviationfront < 0.3 and deviationrear < 0.3: + return 0 + else: + misclogger.error(':{} speed wrong. frontexp is {}, but rpm is {}.rearexp is {}, but rpm is {}'.format(self.name, frontrpmexp, self.front, rearrpmexp, self.rear)) + return 1 + + def checkstatus(self, speedrpm, totaldirct): + speedstatus = self.checkspeedrpm(speedrpm) + if self.direction != totaldirct: + self.status = 1 + misclogger.error(':{} direction = {}.fan direction is not ok.'.format(self.name, self.direction)) + elif speedstatus != 0: + self.status = 1 + elif self.fault != 0: + misclogger.error(':{} fault.'.format(self.name)) + self.status = 1 + else: + self.status = 0 + + if self.status == 1: + system_bright_leds(cs6436_ledpath[self.name], 3) + else: + system_bright_leds(cs6436_ledpath[self.name], 1) + + return self.status + +cs6436_fanattrnodes = [] + + +class cs6436_psuattr: + def __init__(self, name): + self.name = name + self.direction = 0 + self.direction_p = '' + self.present = 0 + self.present_p = '' + self.status = 0 + + self.setpath() + self.updatepresent() + self.updatedirection() + + return + + def setpath(self): + if self.name == 'psu1': + self.present_p = psu1_p + self.direction_p = psu1_d + if self.name == 'psu2': + self.present_p = psu2_p + self.direction_p = psu2_d + + return + + def updatepresent(self): + self.present = int(system_read_filestr(self.present_p)) + + return + + def updatedirection(self): + if self.present == 1: + self.direction = system_getpsu_direction(self.direction_p) + else: + self.direction = 2 + + return + + def checkstatus(self, totaldirct): + if self.present != 1: + self.status = 1 + misclogger.error(':{} not present.'.format(self.name)) + elif self.direction == 2: + self.status = 0 + misclogger.info(':{} direction need to be update.'.format(self.name)) + elif self.direction != totaldirct: + self.status = 1 + misclogger.info(':{} direction is wrong.'.format(self.name)) + else: + self.status = 0 + + if self.status == 1: + system_bright_leds(cs6436_ledpath[self.name], 3) + else: + system_bright_leds(cs6436_ledpath[self.name], 1) + + return self.status + +cs6436_psuattrnodes = [] + + + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"5-005a", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"5-005b", 0) + ret3, log = log_os_system("ls "+leds_prefix+"cs6436_56p_led*", 0) + return not(ret1 or ret2 or ret3) + + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + + +def system_get_coretemp(): + temp1 = system_read_filestr(coretemp_ps[0]).strip() + temp2 = system_read_filestr(coretemp_ps[1]).strip() + temp3 = system_read_filestr(coretemp_ps[2]).strip() + + return int(temp1), int(temp2), int(temp3) + +def system_get_boardtemp(): + for i in range(0,16): + temp1path = "/sys/bus/i2c/devices/5-004a/hwmon/hwmon%d/temp1_input" % i + if os.access(temp1path, os.F_OK): + break + for i in range(0,16): + temp2path = "/sys/bus/i2c/devices/5-004b/hwmon/hwmon%d/temp1_input" % i + if os.access(temp2path, os.F_OK): + break + temp1 = system_read_filestr(temp1path).strip() + temp2 = system_read_filestr(temp2path).strip() + + return int(temp1), int(temp2) + + +def system_get_lswtemp(): + global IsGetlswt + global starttime + if IsGetlswt == 0: + now = datetime.datetime.now() + misclogger.info("time wait.") + misclogger.info("start = {}, now = {}.".format(starttime, now)) + if (now - starttime).seconds > 150: + misclogger.info("time = ".format((now - starttime).seconds)) + IsGetlswt = 1 + + return 25 + +# chp = subprocess.Popen("docker ps --filter name=syncd", shell=True, stdout=subprocess.PIPE) +# if chp.poll() is None: +# misclogger.info("No subp.") +# chp.kill() +# +# return 25 + +# retstring = chp.stdout.read() +# chp.kill() +# if 'Up' not in retstring: +# misclogger.info("lsw not up.") +# +# return 25 + + status, output = log_os_system('npx_diag swc show temperature', 1) + if status: + misclogger.error('failed to show lsw temperature') + + return 25 + + output = output.strip() + if output.find("it 0, temperature ") > 0: + startindex = output.find('temperature') + len('temperature') + 1 + endindex = output[startindex:].find(" ") + endindex = startindex + endindex + temp = output[startindex:endindex] + b = temp.find('.') + if b > 0: + temp=temp[:b] + temp = int(temp) + else: + misclogger.error("Failed to get temperature.") + temp = 0 + + return int(temp) + +def system_monitor_temperature(): + + ctemp1, ctemp2, ctemp3 = system_get_coretemp() + btemp1, btemp2 = system_get_boardtemp() + ltemp = system_get_lswtemp() + fan_speed_str = system_cs6436_getfanexspeed() + fan_speed = int(fan_speed_str) + policy = 'stay' + pos = 0 + #speed c1 c2 c3 b1 b2 lsw + fan_policy_up = ([30, 40000, 40000, 40000, 42000, 35000, 95], + [40, 44000, 44000, 44000, 44000, 39000, 96], + [50, 49000, 49000, 49000, 47000, 44000, 91], + [60, 52000, 52000, 52000, 51500, 47500, 92], + [70, 53000, 53000, 53000, 52000, 49000, 93], + [100,999999,999999,999999,999999,999999,999]) + + fan_policy_down=([30, 0, 0, 0, 0, 0, 0], + [40, 34000, 34000, 34000, 34000, 30000, 80], + [50, 38000, 38000, 38000, 37000, 33000, 81], + [60, 44000, 44000, 44000, 43000, 39000, 84], + [70, 44000, 44000, 44000, 43000, 40000, 84], + [100, 48000, 48000, 48000, 46000, 42000, 85],) + + for policytable in fan_policy_up: + if fan_speed <= policytable[0]: + break + pos = pos + 1 + fan_speed = policytable[0] + if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]): + policy = 'stay' + policytable = fan_policy_down[pos] + if (ctemp1 < policytable[1]) and (ctemp2 < policytable[2]) and (ctemp3 < policytable[3]) and (btemp1 < policytable[4]) and (btemp2 < policytable[5]) and (ltemp < policytable[6]): + policy = 'down' + else: + policy = 'up' + + if policy == 'up': + misclogger.info("speed = %d." % fan_speed) + misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3)) + misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2)) + misclogger.info("lsw = %d" % ltemp) + fan_speed = fan_policy_down[pos + 1][0] + misclogger.info("fan policy: up. speedexp = {}".format(fan_speed)) + + if policy == 'stay': + fan_speed = fan_policy_down[pos] + return + + if policy == 'down': + misclogger.info("speed = %d." % fan_speed) + misclogger.info("core1 = %d, core2 = %d, core3 = %d." % (ctemp1, ctemp2, ctemp3)) + misclogger.info("board1 = %d, board2 = %d." % (btemp1, btemp2)) + misclogger.info("lsw = %d" % ltemp) + fan_speed = fan_policy_down[pos - 1][0] + misclogger.info("fan policy: down.speedexp = {}".format(fan_speed)) + + cmd = "echo %d > /sys/devices/platform/cs6436_56p_fan/fan_duty_cycle_percentage" % fan_speed + status, output = log_os_system(cmd, 1) + if status: + misclogger.error("set fan speed fault") + + return + + +def system_cs6436_setfanexspeed(num): + fanspeednode = fans_prefix + 'fan_duty_cycle_percentage' + numstr = str(num) + with open(fanspeednode, 'w') as f: + f.write(numstr) + + +def system_cs6436_getfanexspeed(): + fanspeednode = fans_prefix + 'fan_duty_cycle_percentage' + fanspeedstr = system_read_filestr(fanspeednode) + fanspeedexp = int(fanspeedstr) + + return fanspeedexp + + +def system_cs6436_getdirection(): + global cs6436_fanattrnodes + direction = 0 + + for fan in cs6436_fanattrnodes: + direction = direction + fan.direction + + if direction > 2: + direction = 1 + else: + direction = 0 + + return direction + + +def system_check_psusdirection(): + global cs6436_psuattrnodes + cs6436totaldirct = system_cs6436_getdirection() + psutatus = 0 + + for psu in cs6436_psuattrnodes: + psu.updatedirection() + psu.checkstatus(cs6436totaldirct) + psutatus = psu.status + psutatus + + return (psutatus != 0) + + +def system_check_psuspresent(): + global cs6436_psuattrnodes + cs6436totaldirct = system_cs6436_getdirection() + psutatus = 0 + + for psu in cs6436_psuattrnodes: + psu.updatepresent() + psu.checkstatus(cs6436totaldirct) + psutatus = psu.status + psutatus + + return (psutatus != 0) + + +def system_check_fansstate(): + global cs6436_fanattrnodes + global cs6436_ledpath + cs6436totaldirct = system_cs6436_getdirection() + fanstatus = 0 + fanexspeed = 0 + + fanexspeed = system_cs6436_getfanexspeed() + + for fan in cs6436_fanattrnodes: + fan.updatedevice() + fan.checkstatus(fanexspeed, cs6436totaldirct) + fanstatus = fanstatus + fan.status + + if fanstatus > 0: + misclogger.error(':fan error.set fans speed 100.') + system_cs6436_setfanexspeed(100) + system_bright_leds(cs6436_ledpath['fan'], 3) + else: + system_bright_leds(cs6436_ledpath['fan'], 1) + + return (fanstatus != 0) + + +def system_misc_polling(threadName,delay): + for count in range(1,5): + if device_exist() == False: + time.sleep(delay+3) + print "%s: %s, count=%d" % ( threadName, time.ctime(time.time()), count) + else: + break + + if count == 4: + return + + status, output = log_os_system("echo 1 > /sys/devices/platform/cs6436_56p_led/leds/cs6436_56p_led::sys/brightness", 1) + status, output = log_os_system("hwconfig -cfp 1", 1) + + global AGFlag + if os.access(ageing_controlfile, os.F_OK): + AGFlag = 1 + else: + AGFlag = 0 + + os.system('csw_daemon &') + + + global cs6436_fanattrnodes + global cs6436_psuattrnodes + + for num in range(1,6): + name = 'fan{}'.format(num) + fannode = cs6436_fanattr(name) + cs6436_fanattrnodes.append(fannode) + for num in range(1,3): + name = 'psu{}'.format(num) + psunode = cs6436_psuattr(name) + cs6436_psuattrnodes.append(psunode) + + tempcontrol = system_init_coretemppath() + + misclogger.info("%s: %s misc start." % ( threadName, time.ctime(time.time()))) + count = 0 + while 1: + count = count + 1 + ret = system_check_psuspresent() + ret = system_check_fansstate() + + if count % 10 == 0: + misclogger.info(": adjust fans and check psu direction.") + system_check_psusdirection() + if tempcontrol == 0: + system_monitor_temperature() + count = 0 + time.sleep(delay) + + return + +if __name__ == '__main__': + target=system_misc_polling("Thread-misc",10) + diff --git a/platform/nephos/sonic-platform-modules-cig/cs6436-56p/utils/cig_cs6436_util.py b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/utils/cig_cs6436_util.py new file mode 100755 index 000000000000..86285c7e4106 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/cs6436-56p/utils/cig_cs6436_util.py @@ -0,0 +1,556 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Cambridge, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + sff : dump SFP eeprom + set : change board setting with fan|led|sfp +""" + +import os +import commands +import sys, getopt +import logging +import re +import time +from collections import namedtuple + + + + +PROJECT_NAME = 'cs6436_56p' +version = '0.1.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +DEVICE_NO = {'led':9, 'fan':5, 'thermal':4, 'psu':2, 'sfp':56} +FORCE = 0 +CPU_TYPE = 'C3308' + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + + +def main(): + global DEBUG + global args + global FORCE + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'show': + device_traversal() + elif arg == 'sff': + if len(args)!=2: + show_eeprom_help() + elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']: + show_eeprom_help() + else: + show_eeprom(args[1]) + return + elif arg == 'set': + if len(args)<3: + show_set_help() + else: + set_device(args[1:]) + return + else: + show_help() + + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def show_set_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print cmd +" [led|sfp|fan]" + print " use \""+ cmd + " led 0-4 \" to set led color" + print " use \""+ cmd + " fan 0-100\" to set fan duty percetage" + print " use \""+ cmd + " sfp 1-56 {0|1}\" to set sfp# tx_disable" + sys.exit(0) + +def show_eeprom_help(): + cmd = sys.argv[0].split("/")[-1]+ " " + args[0] + print " use \""+ cmd + " 1-56 \" to dump sfp# eeprom" + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[ROY]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + for count in range(1,5): + time.sleep(1) + ret, lsmod = log_os_system("lsmod| grep i2c_i801", 0) + if len(lsmod) > 2: + log_os_system("rmmod i2c_i801", 0) + break + + ret, lsmod = log_os_system("lsmod| grep i2c_designware_platform", 0) + if len(lsmod) > 2: + log_os_system("rmmod i2c_designware_platform", 0) + log_os_system("modprobe i2c-designware-platform", 0) + + ret, lsmod = log_os_system("lsmod| grep cig", 0) + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + + +kos = [ + 'depmod', + 'modprobe i2c_dev', + 'modprobe i2c_mux_pca954x force_deselect_on_exit=1', + 'modprobe x86-64-cig-cs6436-56p-sysfs ' , + 'modprobe x86-64-cig-cs6436-56p-cpld ' , + 'modprobe x86-64-cig-cs6436-56p-fan' , + 'modprobe x86-64-cig-cs6436-56p-psu' , + 'modprobe x86-64-cig-cs6436-56p-sfp' , + 'modprobe x86-64-cig-cs6436-56p-led' ] + +def driver_install(): + global FORCE + + for i in range(0,len(kos)): + if i == 4: + ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 32-39 | head -n 1", 0) + if CPU_TYPE=='i3-6100U': + kos[i] =kos[i] + 'board_id=1' + ret, CPU_TYPE = log_os_system("cat /proc/cpuinfo | grep \"model name\" | cut -b 36-40 | head -n 1", 0) + if CPU_TYPE=='C3758' or CPU_TYPE=='C3308': + kos[i] =kos[i] + 'board_id=2' + + status, output = log_os_system(kos[i], 1) + if status: + if FORCE == 0: + return status + return 0 + +def driver_uninstall(): + global FORCE + for i in range(0,len(kos)): + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + if FORCE == 0: + return status + return 0 + +led_prefix ='/sys/class/leds/'+PROJECT_NAME+'_led::' +hwmon_types = {'led': ['sys','fan','fan1','fan2','fan3','fan4','fan5','psu1','psu2']} +hwmon_nodes = {'led': ['brightness'] } +hwmon_prefix ={'led': led_prefix} + +i2c_prefix = '/sys/bus/i2c/devices/' +i2c_bus = {'thermal': ['4-0048','4-0049', '5-004a', '5-004b'] , + 'psu': ['5-005a','5-005b'], + 'sfp': ['-0050']} +i2c_nodes = {'thermal': ['hwmon/hwmon*/temp1_input'] , + 'psu': ['psu_present ', 'psu_power_good'] , + 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + +fan_prefix ='/sys/bus/platform/devices/'+PROJECT_NAME+'_fan' +fan_types = {'fan': ['fan1','fan2', 'fan3', 'fan4', 'fan5']} +fan_nodes = {'fan': ['state', 'front_speed_rpm', 'rear_speed_rpm', 'fault']} + + +sfp_map = [8,9,10,11,12,13,14,15,16, + 17,18,19,20,21,22,23,24,25,26, + 27,28,29,30,31,32,33,34,35,36, + 37,38,39,40,41,42,43,44,45,46, + 47,48,49,50,51,52,53,54,55,56, + 57,58,59,60,61,62,63] + +mknod =[ + 'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-2/new_device', + 'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-3/new_device', + 'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-4/new_device', + 'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-4/new_device', + 'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs6436_56p_psu1 0x5a > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs6436_56p_psu2 0x5b > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs6436_56p_psu1 0x52 > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo cs6436_56p_psu2 0x53 > /sys/bus/i2c/devices/i2c-5/new_device', + 'echo 24c128 0x57 > /sys/bus/i2c/devices/i2c-7/new_device'] + + +def device_install(): + global FORCE + + for i in range(0,len(mknod)): + #all nodes need times to built new i2c buses + time.sleep(1) + + status, output = log_os_system(mknod[i], 1) + if status: + print output + if FORCE == 0: + return status + + for i in range(0,len(sfp_map)): + status, output =log_os_system("echo cs6436_56p_sfp"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + if i <= 47: + status, output =log_os_system("echo cs6436_56p_sfp"+str(i+1)+" 0x51 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + if status: + print output + if FORCE == 0: + return status + + return + +def device_uninstall(): + global FORCE + + for i in range(0,len(sfp_map)): + target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device" + status, output =log_os_system("echo 0x50 > "+ target, 1) + if status: + print output + if FORCE == 0: + return status + + nodelist = mknod + + for i in range(len(nodelist)): + target = nodelist[-(i+1)] + temp = target.split() + del temp[1] + temp[-1] = temp[-1].replace('new_device', 'delete_device') + status, output = log_os_system(" ".join(temp), 1) + if status: + print output + if FORCE == 0: + return status + + return + +def system_ready(): + if driver_check() == False: + return False + if not device_exist(): + return False + return True + +def do_install(): + print "Checking system...." + if driver_check() == False: + print "No driver, installing...." + status = driver_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" drivers detected...." + if not device_exist(): + print "No device, installing...." + status = device_install() + if status: + if FORCE == 0: + return status + else: + print PROJECT_NAME.upper()+" devices detected...." + return + +def do_uninstall(): + print "Checking system...." + if not device_exist(): + print PROJECT_NAME.upper() +" has no device installed...." + else: + print "Removing device...." + status = device_uninstall() + if status: + if FORCE == 0: + return status + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + + return + +def devices_info(): + global DEVICE_NO + global ALL_DEVICE + global i2c_bus, hwmon_types, fan_types + for key in DEVICE_NO: + ALL_DEVICE[key]= {} + for i in range(0,DEVICE_NO[key]): + ALL_DEVICE[key][key+str(i+1)] = [] + + for key in i2c_bus: + buses = i2c_bus[key] + nodes = i2c_nodes[key] + for i in range(0,len(buses)): + for j in range(0,len(nodes)): + if 'sfp' == key: + for k in range(0,DEVICE_NO[key]): + node = key+str(k+1) + path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + else: + node = key+str(i+1) + path = i2c_prefix+ buses[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][node].append(path) + + for key in hwmon_types: + itypes = hwmon_types[key] + nodes = hwmon_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + for key in fan_types: + itypes = fan_types[key] + nodes = fan_nodes[key] + for i in range(0,len(itypes)): + for j in range(0,len(nodes)): + node = key+"_"+itypes[i] + path = fan_prefix+"/"+ itypes[i]+"_"+ nodes[j] + my_log(node+": "+ path) + ALL_DEVICE[key][ key+str(i+1)].append(path) + + #show dict all in the order + if DEBUG == True: + for i in sorted(ALL_DEVICE.keys()): + print(i+": ") + for j in sorted(ALL_DEVICE[i].keys()): + print(" "+j) + for k in (ALL_DEVICE[i][j]): + print(" "+" "+k) + return + +def show_eeprom(index): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] + node = node.replace(node.split("/")[-1], 'sfp_eeprom') + # check if got hexdump command in current environment + ret, log = log_os_system("which hexdump", 0) + ret, log2 = log_os_system("which busybox hexdump", 0) + if len(log): + hex_cmd = 'hexdump' + elif len(log2): + hex_cmd = ' busybox hexdump' + else: + log = 'Failed : no hexdump cmd!!' + logging.info(log) + print log + return 1 + + print node + ":" + ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + if ret==0: + print log + else: + print "**********device no found**********" + return + +def set_device(args): + global DEVICE_NO + global ALL_DEVICE + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + + if args[0]=='led': + if int(args[1])>4: + show_set_help() + return + #print ALL_DEVICE['led'] + for i in range(0,len(ALL_DEVICE['led'])): + for k in (ALL_DEVICE['led']['led'+str(i+1)]): + ret, log = log_os_system("echo "+args[1]+" >"+k, 1) + if ret: + return ret + elif args[0]=='fan': + if int(args[1])>100: + show_set_help() + return + #print ALL_DEVICE['fan'] + #fan1~6 is all fine, all fan share same setting + node = ALL_DEVICE['fan'] ['fan1'][0] + node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage') + ret, log = log_os_system("cat "+ node, 1) + if ret==0: + print ("Previous fan duty: " + log.strip() +"%") + ret, log = log_os_system("echo "+args[1]+" >"+node, 1) + if ret==0: + print ("Current fan duty: " + args[1] +"%") + return ret + elif args[0]=='sfp': + if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0: + show_set_help() + return + if len(args)<2: + show_set_help() + return + + if int(args[2])>1: + show_set_help() + return + + #print ALL_DEVICE[args[0]] + for i in range(0,len(ALL_DEVICE[args[0]])): + for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]: + if j.find('tx_disable')!= -1: + ret, log = log_os_system("echo "+args[2]+" >"+ j, 1) + if ret: + return ret + + return + +def get_value(input): + digit = re.findall('\d+', input) + return int(digit[0]) + + +def get_ledname(ledx): + name_table={'led1':'SYS','led2':'FSTUS','led3':'FAN1','led4':'FAN2','led5':'FAN3','led6':'FAN4','led7':'FAN5','led8':'PSU1','led9':'PSU2'} + if name_table.has_key(ledx): + name = name_table[ledx] + else: + name = ledx + return name + + +def device_traversal(): + if system_ready()==False: + print("System's not ready.") + print("Please install first!") + return + + if len(ALL_DEVICE)==0: + devices_info() + for i in sorted(ALL_DEVICE.keys()): + print("============================================") + print(i.upper()+": ") + print("============================================") + + for j in sorted(ALL_DEVICE[i].keys(), key=get_value): + nwnamex = get_ledname(j) + if nwnamex == j: + print " "+j+":", + else: + print " "+nwnamex+":", + for k in (ALL_DEVICE[i][j]): + ret, log = log_os_system("cat "+k, 0) + func = k.split("/")[-1].strip() + func = re.sub(j+'_','',func,1) + func = re.sub(i.lower()+'_','',func,1) + if ret==0: + print func+"="+log+" ", + else: + print func+"="+"X"+" ", + print + print("----------------------------------------------------------------") + + + print + return + +def device_exist(): + ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0) + ret2, log = log_os_system("ls "+i2c_prefix+"i2c-3", 0) + return not(ret1 or ret2) + + +if __name__ == "__main__": + main() diff --git a/platform/nephos/sonic-platform-modules-cig/debian/changelog b/platform/nephos/sonic-platform-modules-cig/debian/changelog new file mode 100644 index 000000000000..7a4aa7996fdc --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/debian/changelog @@ -0,0 +1,5 @@ +sonic-cig-platform-modules (1.0.0) unstable; urgency=low + + * Add support for CS6436-56P series + + -- developer Wed, 12 Sep 2018 10:00:00 +0800 diff --git a/platform/nephos/sonic-platform-modules-cig/debian/compat b/platform/nephos/sonic-platform-modules-cig/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/nephos/sonic-platform-modules-cig/debian/control b/platform/nephos/sonic-platform-modules-cig/debian/control new file mode 100644 index 000000000000..fc0c6736ffa2 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/debian/control @@ -0,0 +1,21 @@ +Source: sonic-cig-platform-modules +Section: main +Priority: extra +Maintainer: yanglijie@cigtech.com +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-cig-cs6436-56p +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-cig-cs6436-54p +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + +Package: sonic-platform-cig-cs5435-54p +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/nephos/sonic-platform-modules-cig/debian/rules b/platform/nephos/sonic-platform-modules-cig/debian/rules new file mode 100755 index 000000000000..b9ca7642b8bd --- /dev/null +++ b/platform/nephos/sonic-platform-modules-cig/debian/rules @@ -0,0 +1,87 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-cig +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= cs6436-56p cs6436-54p cs5435-54p +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} /$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/etc/sonic; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.py debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/nephos/sonic-platform-modules-ingrasys/.gitignore b/platform/nephos/sonic-platform-modules-ingrasys/.gitignore new file mode 100644 index 000000000000..c6127b38c1aa --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/.gitignore @@ -0,0 +1,52 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/platform/nephos/sonic-platform-modules-ingrasys/LICENSE b/platform/nephos/sonic-platform-modules-ingrasys/LICENSE new file mode 100644 index 000000000000..9cecc1d4669e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/changelog b/platform/nephos/sonic-platform-modules-ingrasys/debian/changelog new file mode 100644 index 000000000000..a3e3f92cc731 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/changelog @@ -0,0 +1,11 @@ +platform-driver (1.0.0) unstable; urgency=low + + * Add support for S9130-32X, S9230-64X series + + -- developer Wed, 29 Mar 2017 11:00:00 +0800 + +platform-driver (1.0.0) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- developer Wed, 05 Oct 2016 16:30:45 +0800 diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/compat b/platform/nephos/sonic-platform-modules-ingrasys/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/control b/platform/nephos/sonic-platform-modules-ingrasys/debian/control new file mode 100755 index 000000000000..3db0b5f3505f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/control @@ -0,0 +1,15 @@ +Source: platform-driver +Section: unknown +Priority: optional +Maintainer: Wade He +Build-Depends: debhelper (>= 9), dh-systemd +Standards-Version: 1.0.0 + +Package: sonic-platform-ingrasys-s9130-32x +Architecture: amd64 +Description: This package contains S9130-32X platform driver utility for SONiC project. + +Package: sonic-platform-ingrasys-s9230-64x +Architecture: amd64 +Description: This package contains S9230-64X platform driver utility for SONiC project. + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/rules b/platform/nephos/sonic-platform-modules-ingrasys/debian/rules new file mode 100755 index 000000000000..f03e1de42c1d --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/rules @@ -0,0 +1,42 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_PRE_NAME := sonic-platform-ingrasys +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= s9130-32x s9230-64x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CONF_DIR := conf + +%: + dh $@ --with systemd + +override_dh_auto_build: + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +override_dh_auto_install: + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} \ + $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/sbin; \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.sh \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/sbin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service \ + debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + done) + +override_dh_clean: + dh_clean + (for mod in $(MODULE_DIRS); do \ + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ + done) + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9130-32x.init b/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9130-32x.init new file mode 100644 index 000000000000..a925faf45fa8 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9130-32x.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9130-32X board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils.sh i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9130-32x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9230-64x.init b/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9230-64x.init new file mode 100644 index 000000000000..4389aee5f77c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9230-64x.init @@ -0,0 +1,41 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S9230-64X board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + depmod -a + + echo "done." + ;; + +stop) + + i2c_utils i2c_deinit + + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/sonic-platform-ingrasys-s9230-64x.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/README.md b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/README.md new file mode 100644 index 000000000000..1b3b14db343b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/README.md @@ -0,0 +1,167 @@ +# Ingrasys S9130-32X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9130-32X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9130-32X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9130-32X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for power monitor, FAN controller, HWM and thermal sensors. + +### I2C PCA9548 +The PCA9548 module on S9130-32X can be found in +`/sys/bus/i2c/devices/i2c-1/` , `/sys/bus/i2c/devices/i2c-2/`, +`/sys/bus/i2c/devices/i2c-3/`, `/sys/bus/i2c/devices/i2c-4/`, +`/sys/bus/i2c/devices/i2c-5/`, `/sys/bus/i2c/devices/i2c-6/`, +`/sys/bus/i2c/devices/i2c-7/`, `/sys/bus/i2c/devices/i2c-8/` + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9130-32X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9130-32X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9130-32x package is installed on the S9130-32X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x51" > /sys/bus/i2c/devices/i2c-0/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/0-0051/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon5/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/Makefile b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/Makefile new file mode 100755 index 000000000000..688bb4666444 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := eeprom_mb.o +obj-m += ingrasys_s9130_32x_psu.o diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/eeprom_mb.c b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/eeprom_mb.c new file mode 100755 index 000000000000..528864d93382 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/eeprom_mb.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +/* enable dev_dbg print out */ +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { /*0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57,*/ I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 512 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, (u8)((addr >> 8) & 0xFF), (u8)(addr & 0xFF)); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static ssize_t mb_eeprom_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + int ret; + int i; + u8 cmd; + u16 value16; + + dev_dbg(&client->dev, "mb_eeprom_write off=%d, count=%d\n", (int)off, (int)count); + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + mutex_lock(&data->update_lock); + + for(i=0; i < count; i++) { + /* write command */ + cmd = (off >> 8) & 0xff; + value16 = off & 0xff; + value16 |= buf[i] << 8; + ret = i2c_smbus_write_word_data(client, cmd, value16); + + if (ret < 0) { + dev_err(&client->dev, "write address failed at %d \n", (int)off); + goto exit; + } + + off++; + + /* need to wait for write complete */ + udelay(10000); + } +exit: + mutex_unlock(&data->update_lock); + /* force to update client when reading */ + for(i=0; i < SLICE_NUM; i++) { + data->last_updated[i] = 0; + } + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUSR, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, + .write = mb_eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x51 and 0x55. So decline + attaching to addresses >= 0x56 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_platform.h b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_platform.h new file mode 100644 index 000000000000..23dcf17a855b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_platform.h @@ -0,0 +1,148 @@ +#ifndef _S9130_32X_PLATFORM_H +#define _S9130_32X_PLATFORM_H + +#include + +// remove debug before release +#define DEBUG + +enum bus_order { + I2C_BUS_MAIN, + MUX_9548_0_CH0, + MUX_9548_0_CH1, + MUX_9548_0_CH2, + MUX_9548_0_CH3, + MUX_9548_0_CH4, + MUX_9548_0_CH5, + MUX_9548_0_CH6, + MUX_9548_0_CH7, + MUX_9548_1_CH0, + MUX_9548_1_CH1, + MUX_9548_1_CH2, + MUX_9548_1_CH3, + MUX_9548_1_CH4, + MUX_9548_1_CH5, + MUX_9548_1_CH6, + MUX_9548_1_CH7, + MUX_9546_0_CH0, + MUX_9546_0_CH1, + MUX_9546_0_CH2, + MUX_9546_0_CH3, + MUX_9546_1_CH0, + MUX_9546_1_CH1, + MUX_9546_1_CH2, + MUX_9546_1_CH3, + MUX_9548_2_CH0, + MUX_9548_2_CH1, + MUX_9548_2_CH2, + MUX_9548_2_CH3, + MUX_9548_2_CH4, + MUX_9548_2_CH5, + MUX_9548_2_CH6, + MUX_9548_2_CH7, + MUX_9548_3_CH0, + MUX_9548_3_CH1, + MUX_9548_3_CH2, + MUX_9548_3_CH3, + MUX_9548_3_CH4, + MUX_9548_3_CH5, + MUX_9548_3_CH6, + MUX_9548_3_CH7, + MUX_9548_4_CH0, + MUX_9548_4_CH1, + MUX_9548_4_CH2, + MUX_9548_4_CH3, + MUX_9548_4_CH4, + MUX_9548_4_CH5, + MUX_9548_4_CH6, + MUX_9548_4_CH7, + MUX_9548_5_CH0, + MUX_9548_5_CH1, + MUX_9548_5_CH2, + MUX_9548_5_CH3, + MUX_9548_5_CH4, + MUX_9548_5_CH5, + MUX_9548_5_CH6, + MUX_9548_5_CH7, + MUX_9548_6_CH0, + MUX_9548_6_CH1, + MUX_9548_6_CH2, + MUX_9548_6_CH3, + MUX_9548_6_CH4, + MUX_9548_6_CH5, + MUX_9548_6_CH6, + MUX_9548_6_CH7, + MUX_9548_7_CH0, + MUX_9548_7_CH1, + MUX_9548_7_CH2, + MUX_9548_7_CH3, + MUX_9548_7_CH4, + MUX_9548_7_CH5, + MUX_9548_7_CH6, + MUX_9548_7_CH7, + MUX_9548_8_CH0, + MUX_9548_8_CH1, + MUX_9548_8_CH2, + MUX_9548_8_CH3, + MUX_9548_8_CH4, + MUX_9548_8_CH5, + MUX_9548_8_CH6, + MUX_9548_8_CH7, + MUX_9548_9_CH0, + MUX_9548_9_CH1, + MUX_9548_9_CH2, + MUX_9548_9_CH3, + MUX_9548_9_CH4, + MUX_9548_9_CH5, + MUX_9548_9_CH6, + MUX_9548_9_CH7, + MUX_9548_10_CH0, + MUX_9548_10_CH1, + MUX_9548_10_CH2, + MUX_9548_10_CH3, + MUX_9548_10_CH4, + MUX_9548_10_CH5, + MUX_9548_10_CH6, + MUX_9548_10_CH7, +}; + +#define I2C_ADDR_MUX_9555_0 (0x20) +#define I2C_ADDR_MUX_9555_1 (0x24) +#define I2C_ADDR_MUX_9555_2 (0x25) +#define I2C_ADDR_MUX_9555_3 (0x26) +#define I2C_ADDR_MUX_9539_0 (0x76) +#define I2C_ADDR_MUX_9539_1 (0x76) +#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN) +#define I2C_BUS_SYS_LED (MUX_9548_1_CH1) + +#define NUM_OF_I2C_MUX (11) +#define NUM_OF_CPLD (5) +#define NUM_OF_QSFP_PORT (64) +#define NUM_OF_SFP_PORT (2) +#define QSFP_EEPROM_I2C_ADDR (0x50) + +enum gpio_reg { + REG_PORT0_IN, + REG_PORT1_IN, + REG_PORT0_OUT, + REG_PORT1_OUT, + REG_PORT0_POL, + REG_PORT1_POL, + REG_PORT0_DIR, + REG_PORT1_DIR, +}; + +struct ing_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +struct i2c_init_data { + __u16 ch; + __u16 addr; + __u8 reg; + __u8 value; +}; + +#endif diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_psu.c b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_psu.c new file mode 100644 index 000000000000..edf92b67241b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/modules/ingrasys_s9130_32x_psu.c @@ -0,0 +1,388 @@ +/* + * S9130-32x PSU driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9130_32x_platform.h" + +static ssize_t show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf); +static struct s9130_psu_data *s9130_psu_update_status(struct device *dev); +static struct s9130_psu_data *s9130_psu_update_eeprom(struct device *dev); +static int s9130_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len); + + +#define DRIVER_NAME "psu" + +// Addresses scanned +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* PSU EEPROM SIZE */ +#define EEPROM_SZ 256 +#define READ_EEPROM 1 +#define NREAD_EEPROM 0 + +static struct i2c_client pca9555_client; + +/* pca9555 gpio pin mapping */ +#define PSU2_PWROK 0 +#define PSU2_PRSNT_L 1 +#define PSU2_PWRON_L 2 +#define PSU1_PWROK 3 +#define PSU1_PRSNT_L 4 +#define PSU1_PWRON_L 5 +#define TMP_75_INT_L 6 + +/* Driver Private Data */ +struct s9130_psu_data { + struct mutex lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + s32 status; /* IO expander value */ + char eeprom[EEPROM_SZ]; /* psu eeprom data */ + char psuABS; /* PSU absent */ + char psuPG; /* PSU power good */ +}; + +enum psu_index +{ + s9130_psu1, + s9130_psu2 +}; + +/* + * display power good attribute + */ +static ssize_t +show_psu_pg(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9130_psu_data *data = s9130_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuPG; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + +/* + * display power absent attribute + */ +static ssize_t +show_psu_abs(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9130_psu_data *data = s9130_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuABS; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + + +/* + * sysfs attributes for psu + */ +static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL); +static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL); +static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL); + +static struct attribute *s9130_psu_attributes[] = { + &dev_attr_psu_pg.attr, + &dev_attr_psu_abs.attr, + &dev_attr_psu_eeprom.attr, + NULL +}; + +/* + * display psu eeprom content + */ +static ssize_t +show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct s9130_psu_data *data = s9130_psu_update_eeprom(dev); + + memcpy(buf, (char *)data->eeprom, EEPROM_SZ); + return EEPROM_SZ; +} + +static const struct attribute_group s9130_psu_group = { + .attrs = s9130_psu_attributes, +}; + +/* + * check gpio expander is accessible + */ +static int +pca9555_detect(struct i2c_client *client) +{ + if (i2c_smbus_read_byte_data(client, REG_PORT0_DIR) < 0) { + return -ENODEV; + } + + return 0; +} + +/* + * client address init + */ +static void +i2c_devices_client_address_init(struct i2c_client *client) +{ + pca9555_client = *client; + pca9555_client.addr = 0x25; +} + +static int +s9130_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct s9130_psu_data *data; + int status, err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct s9130_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct s9130_psu_data)); + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + i2c_devices_client_address_init(client); + + err = pca9555_detect(&pca9555_client); + if (err) { + return err; + } + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &s9130_psu_group); + if (status) { + goto exit_free; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &s9130_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int +s9130_psu_remove(struct i2c_client *client) +{ + struct s9130_psu_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &s9130_psu_group); + kfree(data); + + return 0; +} + + +/* + * psu eeprom read utility + */ +static int +s9130_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len) +{ + int i=0, ret=0; + int blk_max = 32; //max block read size + + /* read eeprom, 32 * 8 = 256 bytes */ + for (i=0; i < EEPROM_SZ/blk_max; i++) { + ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max, + data + (i*blk_max)); + if (ret < 0) { + return ret; + } + } + return ret; +} + +/* + * update eeprom content + */ +static struct s9130_psu_data +*s9130_psu_update_eeprom(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9130_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->last_updated + 300 * HZ) + || !data->valid) { + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9130_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + /* Read eeprom */ + if (!data->psuABS) { + //clear local eeprom data + memset(data->eeprom, 0, EEPROM_SZ); + + //read eeprom + status = s9130_psu_read_block(client, 0, data->eeprom, + ARRAY_SIZE(data->eeprom)); + + if (status < 0) { + memset(data->eeprom, 0, EEPROM_SZ); + dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status); + } else { + data->valid = 1; + } + } else { + memset(data->eeprom, 0, EEPROM_SZ); + } + data->last_updated = jiffies; + } + + mutex_unlock(&data->lock); + + return data; +} + +/* + * update psu status + */ +static struct s9130_psu_data +*s9130_psu_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9130_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9130_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + mutex_unlock(&data->lock); + + return data; +} + +static const struct i2c_device_id s9130_psu_id[] = { + { "psu1", s9130_psu1 }, + { "psu2", s9130_psu2 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, s9130_psu_id); + +static struct i2c_driver s9130_psu_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = s9130_psu_probe, + .remove = s9130_psu_remove, + .id_table = s9130_psu_id, + .address_list = normal_i2c, +}; + +static int __init s9130_psu_init(void) +{ + return i2c_add_driver(&s9130_psu_driver); +} + +static void __exit s9130_psu_exit(void) +{ + i2c_del_driver(&s9130_psu_driver); +} + +module_init(s9130_psu_init); +module_exit(s9130_psu_exit); + +MODULE_AUTHOR("Jason Tsai "); +MODULE_DESCRIPTION("S9130-32X psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/qsfp-monitor.service b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/qsfp-monitor.service new file mode 100644 index 000000000000..10b48f648b98 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9130-32x-monitor.service +After=s9130-32x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/s9130-32x-monitor.service b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/s9130-32x-monitor.service new file mode 100644 index 000000000000..3163b0af6f12 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/service/s9130-32x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9130_32x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/i2c_utils.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/i2c_utils.sh new file mode 100755 index 000000000000..ea238e01729a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/i2c_utils.sh @@ -0,0 +1,1720 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.1.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +QSFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 + +# MAIN MUX PCA9548#0 0x73 +NUM_MUX_9548_0_CH0=$(( ${NUM_I801_DEVICE} + 1 )) # ucd9090 0x34 +NUM_MUX_9548_0_CH1=$(( ${NUM_I801_DEVICE} + 2 )) # PCA9539 0x76 for fp LED & HW ID +NUM_MUX_9548_0_CH7=$(( ${NUM_I801_DEVICE} + 8 )) # W83795 0x2F + +# FRU MUX PCA9545#1 0x72 +NUM_MUX_9545_1_CH0=$(( ${NUM_I801_DEVICE} + 9 )) # PSU2 0x50 +NUM_MUX_9545_1_CH1=$(( ${NUM_I801_DEVICE} + 10 )) # PSU1 0x50 +NUM_MUX_9545_1_CH2=$(( ${NUM_I801_DEVICE} + 11 )) # FAN board IO exander 0x20 +NUM_MUX_9545_1_CH3=$(( ${NUM_I801_DEVICE} + 12 )) # TMP75#0 0x4C TMP75#1 0x49 + +# HOST MUX PCA9548#2 0X70 +NUM_MUX_9548_2_CH0=$(( ${NUM_I801_DEVICE} + 13 )) # PCA9548#3 0x71 +NUM_MUX_9548_2_CH1=$(( ${NUM_I801_DEVICE} + 14 )) # PCA9548#4 0x71 +NUM_MUX_9548_2_CH2=$(( ${NUM_I801_DEVICE} + 15 )) # PCA9548#5 0x71 +NUM_MUX_9548_2_CH3=$(( ${NUM_I801_DEVICE} + 16 )) # PCA9548#6 0x71 +NUM_MUX_9548_2_CH4=$(( ${NUM_I801_DEVICE} + 17 )) # PCA9535#3~6 0x20~0x23 ZQSFP ABS/INT +NUM_MUX_9548_2_CH5=$(( ${NUM_I801_DEVICE} + 18 )) # PCA9535#7~10 0x20~0x23 ZQSFP LPMODE/RST +NUM_MUX_9548_3_CH0=$(( ${NUM_I801_DEVICE} + 21 )) # QSFP 0 EEPROM +NUM_MUX_9548_4_CH0=$(( ${NUM_I801_DEVICE} + 29 )) # QSFP 8 EEPROM +NUM_MUX_9548_5_CH0=$(( ${NUM_I801_DEVICE} + 37 )) # QSFP 16 EEPROM +NUM_MUX_9548_6_CH0=$(( ${NUM_I801_DEVICE} + 45 )) # QSFP 24 EEPROM + +# MUX Alias +I2C_BUS_MAIN=${NUM_I801_DEVICE} +I2C_BUS_HWM=${NUM_MUX_9548_0_CH7} +I2C_BUS_FAN_STATUS=${NUM_MUX_9545_1_CH2} +I2C_BUS_SYS_LED=${NUM_MUX_9548_0_CH1} +I2C_BUS_HW_ID=${NUM_MUX_9548_0_CH1} +I2C_BUS_BMC_HW_ID=${I2C_BUS_MAIN} +I2C_BUS_PSU_STAT=${I2C_BUS_MAIN} +I2C_BUS_FANTRAY_LED=${NUM_MUX_9545_1_CH2} +I2C_BUS_MB_EEPROM=${I2C_BUS_MAIN} +I2C_BUS_CB_EEPROM=${I2C_BUS_MAIN} +I2C_BUS_PSU1_EEPROM=${NUM_MUX_9545_1_CH1} +I2C_BUS_PSU2_EEPROM=${NUM_MUX_9545_1_CH0} + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_SYS_GPIO="/sys/class/gpio" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon5" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_MUX_9548_0_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH0}" +PATH_MUX_9548_0_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH1}" +PATH_MUX_9548_0_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH7}" +PATH_MUX_9545_1_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_1_CH0}" +PATH_MUX_9545_1_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_1_CH1}" +PATH_MUX_9545_1_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_1_CH2}" +PATH_MUX_9545_1_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9545_1_CH3}" +PATH_MUX_9548_2_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH0}" +PATH_MUX_9548_2_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH1}" +PATH_MUX_9548_2_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH2}" +PATH_MUX_9548_2_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH3}" +PATH_MUX_9548_2_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH4}" +PATH_MUX_9548_2_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH5}" +PATH_MUX_9548_3_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_3_CH0}" +PATH_MUX_9548_4_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_4_CH0}" +PATH_MUX_9548_5_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_5_CH0}" +PATH_MUX_9548_6_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_6_CH0}" + +# I2C Address +### I2C MUX +I2C_ADDR_MUX_9548_0=0x73 # MAIN MUX +I2C_ADDR_MUX_9545_1=0x72 # FRU MUX +I2C_ADDR_MUX_9548_2=0x70 # HOST MUX +I2C_ADDR_MUX_9548_3=0x71 # ZQSFP MUX #1 EEPROM +I2C_ADDR_MUX_9548_4=0x71 # ZQSFP MUX #2 EEPROM +I2C_ADDR_MUX_9548_5=0x71 # ZQSFP MUX #3 EEPROM +I2C_ADDR_MUX_9548_6=0x71 # ZQSFP MUX #4 EEPROM +### GPIO Expander +I2C_ADDR_MUX_9539_0=0x76 # LED & HW ID +I2C_ADDR_MUX_9539_1=0x75 # BMC PRSNT & HWM reset +I2C_ADDR_MUX_9539_2=0x74 # SYS SEL & RST +I2C_ADDR_MUX_9535_3=0x20 # ZQSFP0~15 ABS +I2C_ADDR_MUX_9535_4=0x21 # ZQSFP16~31 ABS +I2C_ADDR_MUX_9535_5=0x22 # ZQSFP0~15 INT +I2C_ADDR_MUX_9535_6=0x23 # ZQSFP16~31 INT +I2C_ADDR_MUX_9535_7=0x20 # ZQSFP0~15 LPMODE +I2C_ADDR_MUX_9535_8=0x21 # ZQSFP16~31 LPMODE +I2C_ADDR_MUX_9535_9=0x22 # ZQSFP0~15 RST +I2C_ADDR_MUX_9535_10=0x23 # ZQSFP16~31 RST +I2C_ADDR_MUX_9535_11=0x20 # on FAN board, fan status and led config +I2C_ADDR_MUX_9555_12=0x24 # on BMC board, INT and HW ID +I2C_ADDR_MUX_9555_13=0x25 # on BMC board, PSU status +I2C_ADDR_MUX_9555_14=0x26 # on BMC board, RST and SEL +I2C_ADDR_MUX_9539_15=0x77 # on CPU board, STATUS and ERR from CPLD +### peripheral +I2C_ADDR_MB_EEPROM=0x55 # on main board +I2C_ADDR_CB_EEPROM=0x51 # on cpu board +I2C_ADDR_UCD9090=0x34 +I2C_ADDR_W83795=0x2F +I2C_ADDR_PSU1_EEPROM=0x50 +I2C_ADDR_PSU2_EEPROM=0x50 +I2C_ADDR_TMP75_REAR=0x4C +I2C_ADDR_TMP75_FRONT=0x49 +I2C_ADDR_TMP75_CB=0x4F # on cpu board +I2C_ADDR_TMP75_BB=0x4A # on bmc board +I2C_ADDR_QSFP_EEPROM=0x50 + +#sysfs +PATH_SYSFS_PSU1="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU1_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU1_EEPROM)" +PATH_SYSFS_PSU2="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU2_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU2_EEPROM)" + +#ACTIVE LOW enable flag +ACTIVE_LOW_EN=1 +ACTIVE_HIGH_EN=0 +#GPIO Direction In/Out +DIR_IN=in +DIR_OUT=out + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# IO expander register +# direction +REG_PORT0_DIR=6 +REG_PORT1_DIR=7 +# polarity +REG_PORT0_POL=4 +REG_PORT1_POL=5 +# output +REG_PORT0_OUT=2 +REG_PORT1_OUT=3 +# input +REG_PORT0_IN=0 +REG_PORT1_IN=1 + +#ZQSFP GPIO sysfs index +ZQSFP_PORT0_ABS_GPIO_IDX=240 # 240~255 +ZQSFP_PORT16_ABS_GPIO_IDX=224 # 224~239 + +# switch port number range +MIN_PORT_NUM=1 +MAX_PORT_NUM=32 + +#GPIO Offset +GPIO_OFFSET=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "# Version : ${VERSION}" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_fan_speed_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cb_eeprom_get" + echo " : ${0} i2c_eeprom_sync" + echo " : ${0} i2c_qsfp_eeprom_get [1-32]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_cb_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-32]" + echo " : ${0} i2c_qsfp_type_get [1-32]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_bmc_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_psu1_led green|amber on|off" + echo " : ${0} i2c_psu2_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + #rmmod i2c_ismt + _util_rmmod i2c_i801 + modprobe i2c_i801 disable_features=0x10 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + # add MUX PCA9548#0 on I801, assume to be i2c-1~8 + if [ ! -e ${PATH_MUX_9548_0_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_0}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_0} already init." + fi + # add MUX PCA9545#1 on I801, assume to be i2c-9~12 + if [ ! -e ${PATH_MUX_9545_1_CH0} ]; then + _retry "echo 'pca9545 ${I2C_ADDR_MUX_9545_1}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9545 ${I2C_ADDR_MUX_9545_1} already init." + fi + # add MUX PCA9548#2 on I801, assume to be i2c-13~20 + if [ ! -e ${PATH_MUX_9548_2_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_2}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_2} already init." + fi + # add MUX PCA9548#3 on PCA9548#2 CH0, assume to be i2c-21~28 + if [ ! -e ${PATH_MUX_9548_3_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_3}' > ${PATH_MUX_9548_2_CH0}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_3} already init." + fi + # add MUX PCA9548#4 on PCA9548#2 CH1, assume to be i2c-29~36 + if [ ! -e ${PATH_MUX_9548_4_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_4}' > ${PATH_MUX_9548_2_CH1}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_4} already init." + fi + # add MUX PCA9548#5 on PCA9548#2 CH2, assume to be i2c-37~44 + if [ ! -e ${PATH_MUX_9548_5_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_5}' > ${PATH_MUX_9548_2_CH2}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_5} already init." + fi + # add MUX PCA9548#6 on PCA9548#2 CH3, assume to be i2c-45~52 + if [ ! -e ${PATH_MUX_9548_6_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_6}' > ${PATH_MUX_9548_2_CH3}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_6} already init." + fi + + _i2c_hwm_init + _util_rmmod eeprom + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_io_exp_init + rmmod gpio_ich + _i2c_gpio_init + modprobe gpio_ich + _i2c_sensors_init + _i2c_psu_init + + # Init LED_CLR register (pull shift register out of reset), should be after io exp init + _port_led_clr_init + _i2c_qsfp_eeprom_init "new" + _i2c_mb_eeprom_init "new" + _i2c_cb_eeprom_init "new" + _i2c_fan_speed_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + + # sync eeprom content + _i2c_eeprom_sync + + # trun on sys led + echo "led_sys setup..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + echo "i2c deinit..." + _i2c_gpio_deinit + for mod in coretemp jc42 w83795 eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_i801 ingrasys_s9130_32x_psu; + do + _util_rmmod $mod + done + echo "Done" +} + +function _i2c_sensors_init { + echo "SENSORS init..." + local dev_path + # to make sure hwmon index in sysfs as expected, + # need to remove kernel module and then probe them in expected order + # remove all sensors kernel module + _util_rmmod coretemp + _util_rmmod jc42 + _util_rmmod w83795 + # probe coretemp kernel module + modprobe coretemp + # probe hwmon kernel module + modprobe w83795 + # add tmp75 to sysfs + ####Main board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9545_1_CH3}-$(printf "%04x" ${I2C_ADDR_TMP75_REAR})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_REAR}" > ${PATH_MUX_9545_1_CH3}/new_device # hwmon1 + else + echo "${dev_path} already exist" + fi + sleep 0.5 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9545_1_CH3}-$(printf "%04x" ${I2C_ADDR_TMP75_FRONT})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_FRONT}" > ${PATH_MUX_9545_1_CH3}/new_device #hwmon2 + else + echo "${dev_path} already exist" + fi + sleep 0.5 + ####BMC board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH7}-$(printf "%04x" ${I2C_ADDR_TMP75_BB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_BB}" > ${PATH_MUX_9548_0_CH7}/new_device #hwmon3 + else + echo "${dev_path} already exist" + fi + sleep 0.5 + ####CPU board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MAIN}-$(printf "%04x" ${I2C_ADDR_TMP75_CB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_CB}" > ${PATH_I801_DEVICE}/new_device #hwmon4 + else + echo "${dev_path} already exist" + fi + sleep 0.5 + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH7}-$(printf "%04x" ${I2C_ADDR_W83795})" + if ! [ -L ${dev_path} ]; then + echo "w83795adg ${I2C_ADDR_W83795}" > ${PATH_MUX_9548_0_CH7}/new_device #hwmon5 + else + echo "${dev_path} already exist" + fi + sleep 0.5 + + # probe jc42 kernel module + modprobe jc42 + + echo "Done" +} + +function _port_led_clr_init { + echo "port led init..." + # gpio pin on GPIO MUX PCA9539#2 I/O 0.2 + # pull high to out of reset + output_reg=${REG_PORT0_OUT} + mask=0x04 + value=0x04 + _util_i2cset -m ${mask} -y ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${output_reg} ${value} + echo "Done" +} + +#FAN Speed Init +function _i2c_fan_speed_init { + echo -n "FAN SPEED INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + # init fan speed + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi +} + +# HWM init +function _i2c_hwm_init { + echo "HWM INIT..." + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # SW reset, Disable monitor + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x9C + # disable TR5/TR6 DTS + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x04 0x0 + # enable FANIN1~8 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x06 0xFF + # disable FANIN9~14 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x07 0x00 + # CLKIN clock frequency set as 48Mhz + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x1C + # select bank 2 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x82 + # set PWM mode in FOMC + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x0F 0x00 + # set 25KHz fan output frequency in F1OPFP&F2OPFP + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x18 0x84 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x19 0x84 +} + +#Temperature sensor Init +function _i2c_temp_init { + echo "TEMP INIT..." + # enable temp monitor on w83795 + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # enable TR4 temperature monitoring + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x05 0x40 + # disable TR5/TR6 DTS + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x04 0x0 + echo "Done" +} + +#VOLMON Init +function _i2c_volmon_init { + echo "VOLMON INIT..." + # enable voltage monitor on w83795 + # VSEN1 P0V9 + # VSEN2 VDD + # VSEN3 P1V2 + # VSEN4 P1V8 + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # enable vsen1~4, disable vsen5~8 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x02 0x0F + # enable 3VDD,VBAT + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x03 0x50 + echo "Done" +} + +#FANIN Init +function _i2c_fan_init { + echo "FANIN INIT..." + # enable fan monitor on w83795 + # 4 fantray with 8 FANIN + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # enable FANIN1~8 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x06 0xFF + # disable FANIN9~14 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x07 0x00 + + # select bank 2 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x82 + # set PWM mode in FOMC + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x0F 0x00 + + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + + # need to init BMC io expander first due to some io expander are reset default + echo "Init BMC INT & HW ID IO Expander" + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_12} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_12} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_12} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_12} ${REG_PORT1_POL} 0x00 + + echo "Init BMC PSU status IO Expander" + # PWRON default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT0_OUT} 0x00 + # default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT1_OUT} 0x00 + # I/O 0.2 0.5 output(PWRON), rest input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT0_DIR} 0xDB + # I/O 1.0~1.1 input, 1.2~1.4 output (1.5~1.7 not enable) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT1_DIR} 0xE3 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_13} ${REG_PORT1_POL} 0x00 + + echo "Init BMC RST and SEL IO Expander" + # RST default is 1 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT0_OUT} 0x3F + # SEL default is 0 (HOST), EN default is 1 (ACTIVE_HIGH) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT1_OUT} 0x1F + # I/O 0.0~0.5 output, 0.6~0.7 not use + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT0_DIR} 0xC0 + # all output + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_14} ${REG_PORT1_POL} 0x00 + + echo "Init System LED & HW ID IO Expander" + # I/O_0.x for System LED default 0, I/O_1.x for HW ID + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_OUT} 0x00 + # System LED => all output + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_DIR} 0x00 + # HW ID => all input + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_POL} 0x00 + + echo "Init System PRSNT and HWM RST IO Expander" + # HWM_RST_L default 1 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_OUT} 0x04 + # all input expect HWM_RST_L (0.2) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_DIR} 0xFB + # port1 not used + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_1} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_1} ${REG_PORT1_POL} 0x00 + + echo "Init System SEL and RST IO Expander" + # RST 0.0~0.3 default 1 (ACTIVE low), rest default 0 + # SEL set to value 0 (host) + # LED_CLR also do init in _port_led_clr_init + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_OUT} 0x0F + # RST 1.6~1.7 default 1 (ACTIVE low), INT 1.0~1.4 default 1 (ACTIVE low) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_OUT} 0xDF + # all output, but MAC_RST_L 0.0 need to set as input to prevent reboot issue + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_DIR} 0x09 + # RST 1.5 !~ 1.7 output, rest are input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_DIR} 0x1F + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_POL} 0x00 + + echo "Init FAN Board Status IO Expander" + # LED_G_L set to 0, LED_Y_L set to 1 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT0_OUT} 0x22 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT1_OUT} 0x22 + # DIR/ABS is input, LED_Y/LED_G is output + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT0_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT1_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9535_11} ${REG_PORT1_POL} 0x00 + + echo "Init CPU CPLD IO Expander" + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_15} ${REG_PORT0_DIR} 0xFF + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_15} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_15} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_15} ${REG_PORT1_POL} 0x00 + + echo "Init ZQSFP IO Expender" + + echo "set ZQSFP ABS" + #zQSFP 0-15 ABS + # all input + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_3} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_3} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_3} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_3} ${REG_PORT1_POL} 0x00 + #zQSFP 16-31 ABS + # all input + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_4} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_4} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_4} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_4} ${REG_PORT1_POL} 0x00 + + echo "set ZQSFP INT" + #zQSFP 0-15 INT + # all input + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_5} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_5} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_5} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_5} ${REG_PORT1_POL} 0x00 + #zQSFP 16-31 INT + # all input + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_6} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_6} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_6} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH4} ${I2C_ADDR_MUX_9535_6} ${REG_PORT1_POL} 0x00 + + echo "set ZQSFP LP_MODE = 0" + #ZQSFP 0-15 LP_MODE + # default is 0 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT0_OUT} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT1_OUT} 0x00 + # all output + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT0_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_7} ${REG_PORT1_POL} 0x00 + #ZQSFP 16-31 LP_MODE + # default is 0 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT0_OUT} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT1_OUT} 0x00 + # all output + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT0_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_8} ${REG_PORT1_POL} 0x00 + + echo "set ZQSFP RST = 1" + #ZQSFP 0-15 RST + # default is 1 (ACTIVE_LOW) + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT0_OUT} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT1_OUT} 0xFF + # all output + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT0_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_9} ${REG_PORT1_POL} 0x00 + #ZQSFP 16-31 RST + # default is 1 (ACTIVE_LOW) + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT0_OUT} 0xFF + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT1_OUT} 0xFF + # all output + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT0_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_2_CH5} ${I2C_ADDR_MUX_9535_10} ${REG_PORT1_POL} 0x00 + +} + +# To set the global variable GPIO_OFFSET +function _set_gpio_offset { + GPIO_OFFSET=0 + for d in `ls /sys/class/gpio/ | grep gpiochip` + do + gpiochip_no=${d##gpiochip} + if [ $gpiochip_no -gt 255 ]; then + GPIO_OFFSET=256 + break + fi + done + #echo "set GPIO_OFFSET=${GPIO_OFFSET}" +} + +#GPIO Init +function _i2c_gpio_init { + local i=0 + local start=255 + local end=255 + local ch_num=16 + + #ABS Port 0-15 + echo "pca9535 ${I2C_ADDR_MUX_9535_3}" > ${PATH_MUX_9548_2_CH4}/new_device + _set_gpio_offset + start=$[ ${start}+${GPIO_OFFSET} ] + end=$[ ${end}+${GPIO_OFFSET} ] + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW_EN} + done + + #ABS Port 16-31 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_4}" > ${PATH_MUX_9548_2_CH4}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW_EN} + done + + #INT Port 0-15 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_5}" > ${PATH_MUX_9548_2_CH4}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW_EN} + done + + #INT Port 16-31 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_6}" > ${PATH_MUX_9548_2_CH4}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_IN} ${ACTIVE_LOW_EN} + done + + #LP Mode Port 0-15 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_7}" > ${PATH_MUX_9548_2_CH5}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_OUT} ${ACTIVE_HIGH_EN} + done + + #LP Mode Port 16-31 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_8}" > ${PATH_MUX_9548_2_CH5}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + _util_gpio_export ${i} ${DIR_OUT} ${ACTIVE_HIGH_EN} + done + + #RESET Port 0-15 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_9}" > ${PATH_MUX_9548_2_CH5}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + # need to set value to low (became ACTIVE_HIGH) to take port out of reset + _util_gpio_export ${i} ${DIR_OUT} ${ACTIVE_LOW_EN} 0 + done + + #RESET Port 16-31 + end=$[ ${start}-1] + echo "pca9535 ${I2C_ADDR_MUX_9535_10}" > ${PATH_MUX_9548_2_CH5}/new_device + start=$[ ${end}-${ch_num}+1] + for (( i=$start; i<=$end; i++ )) + do + # need to set value to low (became ACTIVE_HIGH) to take port out of reset + _util_gpio_export ${i} ${DIR_OUT} ${ACTIVE_LOW_EN} 0 + done +} + +#GPIO DeInit +function _i2c_gpio_deinit { + echo ${I2C_ADDR_MUX_9535_3} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH4}/delete_device + echo ${I2C_ADDR_MUX_9535_4} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH4}/delete_device + echo ${I2C_ADDR_MUX_9535_5} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH4}/delete_device + echo ${I2C_ADDR_MUX_9535_6} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH4}/delete_device + echo ${I2C_ADDR_MUX_9535_7} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH5}/delete_device + echo ${I2C_ADDR_MUX_9535_8} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH5}/delete_device + echo ${I2C_ADDR_MUX_9535_9} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH5}/delete_device + echo ${I2C_ADDR_MUX_9535_10} > /sys/bus/i2c/devices/i2c-${NUM_MUX_9548_2_CH5}/delete_device +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + + # check if io expander for fan tray exist + result=`i2cget -y ${I2C_BUS_FANTRAY_LED} ${I2C_ADDR_MUX_9535_11} ${REG_PORT0_IN} 2>/dev/null` + err_code=$? + if [ "$err_code" != "0" ]; then + echo "fan tray not exist!" + return + fi + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + echo "led_fan setup..." + # all fan ok + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + # all fan fail + elif [ "${FAN1_ALARM}" == "1" ] && [ "${FAN2_ALARM}" == "1" ] \ + && [ "${FAN3_ALARM}" == "1" ] && [ "${FAN4_ALARM}" == "1" ] \ + && [ "${FAN5_ALARM}" == "1" ] && [ "${FAN6_ALARM}" == "1" ] \ + && [ "${FAN7_ALARM}" == "1" ] && [ "${FAN8_ALARM}" == "1" ]; then + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + # partial fan fail + else + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + echo "led_psu1 setup..." + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + else + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + echo "led_psu2 setup..." + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + else + COLOR_LED="amber" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="green" + ONOFF_LED="off" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C SYSTEM LED TEST..." + echo "=========================================================" + local output_reg=${REG_PORT0_OUT} + local mask=0xFF + local value=0xFF + + #sys led (green) + # set sys_led_g (0.7) = 1 + mask=0x80 + value=0x80 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + # set sys_led_g (0.7) = 0 + mask=0x80 + value=0x00 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 0 + mask=0x60 + value=0x40 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 1 + mask=0x60 + value=0x60 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 0 + mask=0x18 + value=0x10 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 1 + mask=0x18 + value=0x18 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 0 + mask=0x06 + value=0x04 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 1 + mask=0x06 + value=0x06 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED (can't trun off system led) + # set set fan_led_en (0.6), psu1_pwr_ok_oe (0.4), psu0_pwr_ok_oe (0.2) = 0 + mask=0x54 + value=0x00 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check turn off all LEDs (exclude SYS LED) and Press [Enter] key to continue...' + + # restore sys led + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + + echo "Done" +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX_9548_2_CH4} + eeprombusbase=${NUM_MUX_9548_3_CH0} + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT0_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT0_ABS_GPIO_IDX} + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX_9548_2_CH4} + eeprombusbase=${NUM_MUX_9548_4_CH0} + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT0_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT0_ABS_GPIO_IDX} + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX_9548_2_CH4} + eeprombusbase=${NUM_MUX_9548_5_CH0} + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT16_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT16_ABS_GPIO_IDX} + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX_9548_2_CH4} + eeprombusbase=${NUM_MUX_9548_6_CH0} + gpioBase=$((${GPIO_OFFSET}+${ZQSFP_PORT16_ABS_GPIO_IDX})) + #gpioBase=${ZQSFP_PORT16_ABS_GPIO_IDX} + ;; + *) + echo "Please input 1~32" + exit + ;; + esac +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + local port=$1 + # port 1 => zqsfp0 + # port 2 => zqsfp1 + # ... + eeprombusidx=$(( (${port} - 1) % 8)) + eeprombus=$(( ${eeprombusbase} + ${eeprombusidx} )) + eepromAddr=${I2C_ADDR_QSFP_EEPROM} +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_PORT_NUM}" "${MAX_PORT_NUM}" + + _util_get_qsfp_abs + + if [ $status = 0 ]; then + exit + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + local i + for i in {1..32}; + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done + echo "Done" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init mb EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_MB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "$I2C_ADDR_MB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/delete_device + fi + echo "Done" +} + +#Init CPU Board EEPROM +function _i2c_cb_eeprom_init { + echo -n "CPU Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init cpu EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_CB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "$I2C_ADDR_CB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/delete_device + fi + echo "Done" +} + + +#get QSFP Status +function _i2c_qsfp_status_get { + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_PORT_NUM}" "${MAX_PORT_NUM}" + + local stat + _util_get_qsfp_abs + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_PORT_NUM}" "${MAX_PORT_NUM}" + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + _qsfp_eeprom_var_set ${QSFP_PORT} + + #Get QSFP EEPROM info + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Init PSU Kernel Module +function _i2c_psu_init { + echo "=========================================================" + echo "# Description: I2C PSU Init" + echo "=========================================================" + modprobe ingrasys_s9130_32x_psu + + echo "psu1 ${I2C_ADDR_PSU1_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/new_device + echo "psu2 ${I2C_ADDR_PSU2_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/new_device +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + local eeprom_psu1="" + local eeprom_psu2="" + + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + eeprom_psu1="${PATH_SYSFS_PSU1}/psu_eeprom" + cat ${eeprom_psu1} | hexdump -C + + eeprom_psu2="${PATH_SYSFS_PSU2}/psu_eeprom" + cat ${eeprom_psu2} | hexdump -C +} + +#Get Main Board EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get mb +} + +#Get CPU Board EEPROM Information +function _i2c_cb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C CB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get cb +} + +#Get system EEPROM Information +##input: "cb" for cpu board, "mb" for main board +function _i2c_sys_eeprom_get { + local eeprom_dev + + if [ "$1" == "cb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + elif [ "$1" == "mb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + else + echo "wrong eeprom type" + return + fi + + # check if eeprom device exist in sysfs + if [ ! -f ${eeprom_dev} ]; then + echo "eeprom device not init" + return + fi + + cat ${eeprom_dev} | hexdump -C + echo "Done" +} + +#sync eeprom content between mb and cb eeprom +function _i2c_eeprom_sync { + echo "=========================================================" + echo "# Description: EEPROM sync..." + echo "=========================================================" + + local mb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + local cb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + + # check if eeprom device exist in sysfs + if [[ ! -f ${mb_eeprom_dev} || ! -f ${cb_eeprom_dev} ]]; then + echo "eeprom device not init" + return + fi + + ## check if MB eeprom is empty + if [ ! -z "$(cat ${mb_eeprom_dev} | hexdump -n2 | grep ffff)" ]; then + echo "copy cb eeprom to mb eeprom..." + cat ${cb_eeprom_dev} > ${mb_eeprom_dev} + else + echo "no need to sync" + fi + + echo "Done" +} + +#Set System Status LED +function _i2c_sys_led { + # only green/amber, on/off can't control + if [ "${COLOR_LED}" == "green" ]; then + # set sys_led_g (0.7) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x80 + elif [ "${COLOR_LED}" == "amber" ]; then + # set sys_led_g (0.7) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x40 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + # set fan_led_en (0.6) = 0 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x60 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + # set fan_led_en (0.6) = 0 & fan_led_y (0.5) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x20 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x10 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + # set psu1_pwr_ok_oe (0.4) = 0 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x18 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + # set psu1_pwr_ok_oe (0.4) = 0 & psu1_led_y (0.3) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x08 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x04 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + # set psu0_pwr_ok_oe (0.2) = 0 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x06 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + # set psu0_pwr_ok_oe (0.2) = 0 & psu0_led_y (0.1) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x02 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + + i2cAddr=${I2C_ADDR_MUX_9535_11} + output_reg=${REG_PORT0_OUT} + + case ${FAN_TRAY} in + 4) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 3) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 2) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 1) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x33 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x33 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "Done" +} + +#Get Board Version and Type +function _i2c_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_HW_ID} ${I2C_ADDR_MUX_9539_0} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "MAIN_BOARD BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev +} + +#Get BMC Board Version and Type +function _i2c_bmc_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_BMC_HW_ID} ${I2C_ADDR_MUX_9555_12} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BMC_BOARD BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev +} + +#Get PSU Status +function _i2c_psu_status { + local psu_abs="" + + psu1PwGood=`cat ${PATH_SYSFS_PSU1}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU1}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu1Exist=1 + else + psu1Exist=0 + fi + + psu2PwGood=`cat ${PATH_SYSFS_PSU2}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU2}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu2Exist=1 + else + psu2Exist=0 + fi + + printf "PSU1 Exist:%x PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#util functions +function _util_i2cset { + if [ "$DEBUG" == "on" ]; then + i2cset $@ + else + i2cset $@ 1>/dev/null + fi +} + +function _util_rmmod { + local mod=$1 + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod +} + +# get qsfp presence +function _util_get_qsfp_abs { + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up (ACTIVE_LOW_EN) + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) % 16 )) ))/value` +} + +# gpio init util function +function _util_gpio_export { + local gpio_n=$1 + local direction=$2 + local active_low=$3 + local value=$4 + + if [ -z "${gpio_n}" ]; then + echo "[gpio_init] gpio_n(${gpio_n}) is not provided" + return + fi + if [[ ${gpio_n} < 0 || ${gpio_n} > $(( 255+${GPIO_OFFSET} )) ]]; then + echo "[gpio_init] gpio_n(${gpio_n}) is invalid value" + return + fi + + #export gpio + echo ${gpio_n} > /sys/class/gpio/export + #set gpio direction + echo ${direction} > /sys/class/gpio/gpio${gpio_n}/direction + #set gpio active_low + echo ${active_low} > /sys/class/gpio/gpio${gpio_n}/active_low + #set value + if [ ! -z "${value}" ]; then + echo ${value} > /sys/class/gpio/gpio${gpio_n}/value + fi +} + +# valid input number +function _util_input_check { + # input parameter validation + if [[ $1 -lt $2 || $1 -gt $3 ]]; then + echo "Please input number $2~$3" + exit + fi +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + _set_gpio_offset + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_fan_speed_init" ]; then + _i2c_fan_speed_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_get" ]; then + _i2c_cb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_eeprom_sync" ]; then + _i2c_eeprom_sync + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_init" ]; then + _i2c_cb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_bmc_board_type_get" ]; then + _i2c_bmc_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cb_eeprom_get + _i2c_board_type_get + _i2c_bmc_board_type_get + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/qsfp_monitor.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/qsfp_monitor.sh new file mode 100755 index 000000000000..7776493bc20a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..31}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`sonic-db-cli ASIC_DB HLEN HIDDEN` + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/s9130_32x_monitor.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/s9130_32x_monitor.sh new file mode 100755 index 000000000000..974da6d5001f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9130-32x/utils/s9130_32x_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/README.md b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/README.md new file mode 100644 index 000000000000..d1a2d5464aee --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/README.md @@ -0,0 +1,182 @@ +# Ingrasys S9230-64X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, Inc. + +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 3 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. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9230-64X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9230-64X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9230-64X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for power monitor, FAN controller, HWM and thermal sensors. + +### I2C PCA9548 +The PCA9548 module on S9230-64X can be found in +`/sys/bus/i2c/devices/i2c-1/` , `/sys/bus/i2c/devices/i2c-2/`, +`/sys/bus/i2c/devices/i2c-3/`, `/sys/bus/i2c/devices/i2c-4/`, +`/sys/bus/i2c/devices/i2c-5/`, `/sys/bus/i2c/devices/i2c-6/`, +`/sys/bus/i2c/devices/i2c-7/`, `/sys/bus/i2c/devices/i2c-8/` + +The pca9548 module for CPLD get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9230-64X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9230-64X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9230-64X package is installed on the S9230-64X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x55" > /sys/bus/i2c/devices/i2c-0/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/0-0055/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon7/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the CPLD 1~5 according to port number. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-64] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_status_get [1-64] + 0 => not insert + 1 => inserted +``` + +### SFP+ +SFP+ modules are managed by the CPLD 1~2 according to port number. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +SFP EEPROM: + i2c_utils.sh i2c_sfp_eeprom_get [1-2] + +SFP Insert Event: + i2c_utils.sh i2c_sfp_status_get [1-2] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/Makefile b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/Makefile new file mode 100755 index 000000000000..3107674e8712 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/Makefile @@ -0,0 +1,3 @@ +obj-m := eeprom_mb.o +obj-m += ingrasys_s9230_64x_i2c_cpld.o +obj-m += ingrasys_s9230_64x_psu.o diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/eeprom_mb.c b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/eeprom_mb.c new file mode 100755 index 000000000000..528864d93382 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/eeprom_mb.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * 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. + */ + +/* enable dev_dbg print out */ +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { /*0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57,*/ I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 512 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, (u8)((addr >> 8) & 0xFF), (u8)(addr & 0xFF)); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static ssize_t mb_eeprom_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + int ret; + int i; + u8 cmd; + u16 value16; + + dev_dbg(&client->dev, "mb_eeprom_write off=%d, count=%d\n", (int)off, (int)count); + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + mutex_lock(&data->update_lock); + + for(i=0; i < count; i++) { + /* write command */ + cmd = (off >> 8) & 0xff; + value16 = off & 0xff; + value16 |= buf[i] << 8; + ret = i2c_smbus_write_word_data(client, cmd, value16); + + if (ret < 0) { + dev_err(&client->dev, "write address failed at %d \n", (int)off); + goto exit; + } + + off++; + + /* need to wait for write complete */ + udelay(10000); + } +exit: + mutex_unlock(&data->update_lock); + /* force to update client when reading */ + for(i=0; i < SLICE_NUM; i++) { + data->last_updated[i] = 0; + } + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO | S_IWUSR, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, + .write = mb_eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x51 and 0x55. So decline + attaching to addresses >= 0x56 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x56) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.c b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.c new file mode 100644 index 000000000000..7d832fc0149f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.c @@ -0,0 +1,1259 @@ +/* + * A i2c cpld driver for the ingrasys_s9230_64x + * + * Copyright (C) 2017 Ingrasys Technology Corporation. + * Leo Lin + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9230_64x_i2c_cpld.h" + +#ifdef DEBUG +#define DEBUG_PRINT(fmt, args...) \ + printk(KERN_INFO "%s:%s[%d]: " fmt "\r\n", \ + __FILE__, __func__, __LINE__, ##args) +#else +#define DEBUG_PRINT(fmt, args...) +#endif + +#define I2C_READ_BYTE_DATA(ret, lock, i2c_client, reg) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_read_byte_data(i2c_client, reg); \ + mutex_unlock(lock); \ +} +#define I2C_WRITE_BYTE_DATA(ret, lock, i2c_client, reg, val) \ +{ \ + mutex_lock(lock); \ + ret = i2c_smbus_write_byte_data(i2c_client, reg, val); \ + mutex_unlock(lock); \ +} + +/* CPLD sysfs attributes index */ +enum s9230_64x_cpld_sysfs_attributes { + CPLD_ACCESS_REG, + CPLD_REGISTER_VAL, + CPLD_PORT_START, + CPLD_PORTS, + CPLD_VERSION, + CPLD_ID, + CPLD_BOARD_TYPE, + CPLD_EXT_BOARD_TYPE, + CPLD_QSFP_PORT_STATUS_1, + CPLD_QSFP_PORT_STATUS_2, + CPLD_QSFP_PORT_STATUS_3, + CPLD_QSFP_PORT_STATUS_4, + CPLD_QSFP_PORT_STATUS_5, + CPLD_QSFP_PORT_STATUS_6, + CPLD_QSFP_PORT_STATUS_7, + CPLD_QSFP_PORT_STATUS_8, + CPLD_QSFP_PORT_STATUS_9, + CPLD_QSFP_PORT_STATUS_10, + CPLD_QSFP_PORT_STATUS_11, + CPLD_QSFP_PORT_STATUS_12, + CPLD_QSFP_PORT_STATUS_13, + CPLD_QSFP_PORT_CONFIG_1, + CPLD_QSFP_PORT_CONFIG_2, + CPLD_QSFP_PORT_CONFIG_3, + CPLD_QSFP_PORT_CONFIG_4, + CPLD_QSFP_PORT_CONFIG_5, + CPLD_QSFP_PORT_CONFIG_6, + CPLD_QSFP_PORT_CONFIG_7, + CPLD_QSFP_PORT_CONFIG_8, + CPLD_QSFP_PORT_CONFIG_9, + CPLD_QSFP_PORT_CONFIG_10, + CPLD_QSFP_PORT_CONFIG_11, + CPLD_QSFP_PORT_CONFIG_12, + CPLD_QSFP_PORT_CONFIG_13, + CPLD_QSFP_PORT_INTERRUPT, + CPLD_SFP_PORT_STATUS, + CPLD_SFP_PORT_CONFIG, + CPLD_10GMUX_CONFIG, + CPLD_BMC_STATUS, + CPLD_BMC_WATCHDOG, + CPLD_USB_STATUS, +}; + +/* CPLD sysfs attributes hook functions */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t get_qsfp_port_start(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t get_qsfp_ports(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_cpld_id(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_qsfp_port_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_qsfp_port_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_qsfp_port_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_qsfp_port_interrupt(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_sfp_port_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_sfp_port_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_sfp_port_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_10gmux_config(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_10gmux_config(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_bmc_status(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t read_bmc_watchdog(struct device *dev, + struct device_attribute *da, char *buf); +static ssize_t write_bmc_watchdog(struct device *dev, + struct device_attribute *da, const char *buf, size_t count); +static ssize_t read_usb_status(struct device *dev, + struct device_attribute *da, char *buf); + +static LIST_HEAD(cpld_client_list); /* client list for cpld */ +static struct mutex list_lock; /* mutex for client list */ + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +struct cpld_data { + int index; /* CPLD index */ + struct mutex access_lock; /* mutex for cpld access */ + u8 access_reg; /* register to access */ +}; + +/* CPLD device id and data */ +static const struct i2c_device_id ingrasys_i2c_cpld_id[] = { + { "ingrasys_cpld1", cpld1 }, + { "ingrasys_cpld2", cpld2 }, + { "ingrasys_cpld3", cpld3 }, + { "ingrasys_cpld4", cpld4 }, + { "ingrasys_cpld5", cpld5 }, + {} +}; + +/* Addresses scanned for ingrasys_i2c_cpld */ +static const unsigned short cpld_i2c_addr[] = { 0x33, I2C_CLIENT_END }; + +/* define all support register access of cpld in attribute */ +static SENSOR_DEVICE_ATTR(cpld_access_register, S_IWUSR | S_IRUGO, + read_access_register, write_access_register, CPLD_ACCESS_REG); +static SENSOR_DEVICE_ATTR(cpld_register_value, S_IWUSR | S_IRUGO, + read_register_value, write_register_value, CPLD_REGISTER_VAL); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_start, S_IRUGO, + get_qsfp_port_start, NULL, CPLD_PORT_START); +static SENSOR_DEVICE_ATTR(cpld_qsfp_ports, S_IRUGO, + get_qsfp_ports, NULL, CPLD_PORTS); +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, + read_cpld_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(cpld_id, S_IRUGO, read_cpld_id, NULL, CPLD_ID); +static SENSOR_DEVICE_ATTR(cpld_board_type, S_IRUGO, + read_board_type, NULL, CPLD_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_ext_board_type, S_IRUGO, + read_ext_board_type, NULL, CPLD_EXT_BOARD_TYPE); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_1, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_1); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_2, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_2); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_3, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_3); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_4, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_4); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_5, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_5); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_6, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_6); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_7, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_7); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_8, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_8); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_9, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_9); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_10, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_10); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_11, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_11); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_12, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_12); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_status_13, S_IRUGO, + read_qsfp_port_status, NULL, CPLD_QSFP_PORT_STATUS_13); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_1, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, CPLD_QSFP_PORT_CONFIG_1); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_2, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_2); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_3, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_3); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_4, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_4); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_5, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_5); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_6, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_6); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_7, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_7); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_8, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_8); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_9, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_9); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_10, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_10); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_11, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_11); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_12, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_12); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_config_13, S_IWUSR | S_IRUGO, + read_qsfp_port_config, write_qsfp_port_config, + CPLD_QSFP_PORT_CONFIG_13); +static SENSOR_DEVICE_ATTR(cpld_qsfp_port_interrupt, S_IRUGO, + read_qsfp_port_interrupt, NULL, CPLD_QSFP_PORT_INTERRUPT); +static SENSOR_DEVICE_ATTR(cpld_sfp_port_status, S_IRUGO, + read_sfp_port_status, NULL, CPLD_SFP_PORT_STATUS); +static SENSOR_DEVICE_ATTR(cpld_sfp_port_config, S_IWUSR | S_IRUGO, + read_sfp_port_config, write_sfp_port_config, CPLD_SFP_PORT_CONFIG); +static SENSOR_DEVICE_ATTR(cpld_10gmux_config, S_IWUSR | S_IRUGO, + read_10gmux_config, write_10gmux_config, + CPLD_10GMUX_CONFIG); +static SENSOR_DEVICE_ATTR(cpld_bmc_status, S_IRUGO, + read_bmc_status, NULL, CPLD_BMC_STATUS); +static SENSOR_DEVICE_ATTR(cpld_bmc_watchdog, S_IWUSR | S_IRUGO, + read_bmc_watchdog, write_bmc_watchdog, + CPLD_BMC_WATCHDOG); +static SENSOR_DEVICE_ATTR(cpld_usb_status, S_IRUGO, + read_usb_status, NULL, CPLD_USB_STATUS); + + +/* define support attributes of cpldx , total 5 */ +/* cpld 1 */ +static struct attribute *s9230_64x_cpld1_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_start.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_ports.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_id.dev_attr.attr, + &sensor_dev_attr_cpld_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_ext_board_type.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_interrupt.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_status.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_config.dev_attr.attr, + &sensor_dev_attr_cpld_10gmux_config.dev_attr.attr, + &sensor_dev_attr_cpld_bmc_status.dev_attr.attr, + &sensor_dev_attr_cpld_bmc_watchdog.dev_attr.attr, + &sensor_dev_attr_cpld_usb_status.dev_attr.attr, + NULL +}; +/* cpld 2 */ +static struct attribute *s9230_64x_cpld2_attributes[] = { + &sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_start.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_ports.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_id.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_interrupt.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_status.dev_attr.attr, + &sensor_dev_attr_cpld_sfp_port_config.dev_attr.attr, + NULL +}; +/* cpld 3 / cpld 4 / cpld 5 */ +static struct attribute *s9230_64x_cpld345_attributes[] = { +&sensor_dev_attr_cpld_access_register.dev_attr.attr, + &sensor_dev_attr_cpld_register_value.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_start.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_ports.dev_attr.attr, + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_cpld_id.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_status_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_1.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_2.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_3.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_4.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_5.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_6.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_7.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_8.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_9.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_10.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_11.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_12.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_config_13.dev_attr.attr, + &sensor_dev_attr_cpld_qsfp_port_interrupt.dev_attr.attr, + NULL +}; + +/* cpld 1 attributes group */ +static const struct attribute_group s9230_64x_cpld1_group = { + .attrs = s9230_64x_cpld1_attributes, +}; +/* cpld 2 attributes group */ +static const struct attribute_group s9230_64x_cpld2_group = { + .attrs = s9230_64x_cpld2_attributes, +}; +/* cpld 3/4/5 attributes group */ +static const struct attribute_group s9230_64x_cpld345_group = { + .attrs = s9230_64x_cpld345_attributes, +}; + +/* read access register from cpld data */ +static ssize_t read_access_register(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + + return sprintf(buf, "0x%x\n", reg); +} + +/* write access register to cpld data */ +static ssize_t write_access_register(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + + if (kstrtou8(buf, 0, ®) < 0) + return -EINVAL; + + data->access_reg = reg; + return count; +} + +/* read the value of access register in cpld data */ +static ssize_t read_register_value(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg = data->access_reg; + int reg_val; + + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + + if (reg_val < 0) + return -1; + + return sprintf(buf, "0x%x\n", reg_val); +} + +/* wrtie the value to access register in cpld data */ +static ssize_t write_register_value(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ret = -EIO; + u8 reg = data->access_reg; + u8 reg_val; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, client, reg, reg_val); + + return count; +} + +/* get qsfp port start number of the cpld device */ +/* the start number use to tranlate qsfp port to cpld port */ +/* the cpld port use to access the qsfp port register in cpld */ +static ssize_t get_qsfp_port_start(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int port_base_num; + + if (attr->index == CPLD_PORT_START) { + if (data->index == cpld1) { + port_base_num = 1; + } else { + port_base_num = CPLD_1_PORT_NUM + + CPLD_2_PORT_NUM*(data->index - 1) + 1; + } + return sprintf(buf, "%d\n", port_base_num); + } + return -1; +} + +/* get total qsfp port which contain register in the cpld device */ +static ssize_t get_qsfp_ports(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + int ports; + + if (attr->index == CPLD_PORTS) { + if (data->index == cpld1) + ports = CPLD_1_PORT_NUM; + else + ports = CPLD_2_PORT_NUM; + return sprintf(buf, "%d\n", ports); + } + return -1; +} + +/* get cpdl version register value */ +static ssize_t read_cpld_version(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_VERSION) { + reg = CPLD_VERSION_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get cpdl id register value */ +static ssize_t read_cpld_id(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_ID) { + reg = CPLD_ID_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get board type register value */ +static ssize_t read_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BOARD_TYPE) { + reg = CPLD_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get extend board type register value */ +static ssize_t read_ext_board_type(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_EXT_BOARD_TYPE) { + reg = CPLD_EXT_BOARD_TYPE_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get qsfp port status register value */ +static ssize_t read_qsfp_port_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index >= CPLD_QSFP_PORT_STATUS_1 && + attr->index <= CPLD_QSFP_PORT_STATUS_13) { + reg = CPLD_QSFP_PORT_STATUS_BASE_REG + + (attr->index - CPLD_QSFP_PORT_STATUS_1); + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get qsfp port config register value */ +static ssize_t read_qsfp_port_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index >= CPLD_QSFP_PORT_CONFIG_1 && + attr->index <= CPLD_QSFP_PORT_CONFIG_13) { + reg = CPLD_QSFP_PORT_CONFIG_BASE_REG + + (attr->index - CPLD_QSFP_PORT_CONFIG_1); + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to qsfp port config register */ +static ssize_t write_qsfp_port_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index >= CPLD_QSFP_PORT_CONFIG_1 && + attr->index <= CPLD_QSFP_PORT_CONFIG_13) { + reg = CPLD_QSFP_PORT_CONFIG_BASE_REG + + (attr->index - CPLD_QSFP_PORT_CONFIG_1); + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get qsfp port interrupt register value */ +static ssize_t read_qsfp_port_interrupt(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_QSFP_PORT_INTERRUPT) { + reg = CPLD_QSFP_PORT_INTERRUPT_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get sfp port status register value */ +static ssize_t read_sfp_port_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_PORT_STATUS) { + reg = CPLD_SFP_PORT_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get sfp port config register value */ +static ssize_t read_sfp_port_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_SFP_PORT_CONFIG) { + reg = CPLD_SFP_PORT_CONFIG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to sfp port config register */ +static ssize_t write_sfp_port_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_SFP_PORT_CONFIG) { + reg = CPLD_SFP_PORT_CONFIG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get 10g mux config register value */ +static ssize_t read_10gmux_config(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_10GMUX_CONFIG) { + reg = CPLD_10GMUX_CONFIG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to 10g mux config register */ +static ssize_t write_10gmux_config(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_10GMUX_CONFIG) { + reg = CPLD_10GMUX_CONFIG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get bmc status register value */ +static ssize_t read_bmc_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BMC_STATUS) { + reg = CPLD_BMC_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* get bmc watchdog register value */ +static ssize_t read_bmc_watchdog(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_BMC_WATCHDOG) { + reg = CPLD_BMC_WATCHDOG_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* set value to bmc watchdog register */ +static ssize_t write_bmc_watchdog(struct device *dev, + struct device_attribute *da, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg, reg_val; + int ret; + + if (kstrtou8(buf, 0, ®_val) < 0) + return -EINVAL; + + if (attr->index == CPLD_BMC_WATCHDOG) { + reg = CPLD_BMC_WATCHDOG_REG; + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + client, reg, reg_val); + } + return count; +} + +/* get usb status register value */ +static ssize_t read_usb_status(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 reg; + int reg_val; + + if (attr->index == CPLD_USB_STATUS) { + reg = CPLD_USB_STATUS_REG; + I2C_READ_BYTE_DATA(reg_val, &data->access_lock, client, reg); + if (reg_val < 0) + return -1; + return sprintf(buf, "0x%02x\n", reg_val); + } + return -1; +} + +/* add valid cpld client to list */ +static void ingrasys_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = NULL; + + node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + if (!node) { + dev_info(&client->dev, + "Can't allocate cpld_client_node for index %d\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +/* remove exist cpld client in list */ +static void ingrasys_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + mutex_unlock(&list_lock); +} + +/* cpld drvier probe */ +static int ingrasys_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + struct cpld_data *data = NULL; + int ret = -EPERM; + int err; + int idx; + + data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* init cpld data for client */ + i2c_set_clientdata(client, data); + mutex_init(&data->access_lock); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_info(&client->dev, + "i2c_check_functionality failed (0x%x)\n", + client->addr); + status = -EIO; + goto exit; + } + + /* get cpld id from device */ + ret = i2c_smbus_read_byte_data(client, CPLD_ID_REG); + + if (ret < 0) { + dev_info(&client->dev, + "fail to get cpld id (0x%x) at addr (0x%x)\n", + CPLD_ID_REG, client->addr); + status = -EIO; + goto exit; + } + + CPLD_ID_ID_GET(ret, idx); + + if (INVALID(idx, cpld1, cpld5)) { + dev_info(&client->dev, + "cpld id %d(device) not valid\n", idx); + //status = -EPERM; + //goto exit; + } + +#if 0 + /* change client name for each cpld with index */ + snprintf(client->name, sizeof(client->name), "%s_%d", client->name, + data->index); +#endif + + data->index = dev_id->driver_data; + + /* register sysfs hooks for different cpld group */ + dev_info(&client->dev, "probe cpld with index %d\n", data->index); + switch (data->index) { + case cpld1: + status = sysfs_create_group(&client->dev.kobj, + &s9230_64x_cpld1_group); + break; + case cpld2: + status = sysfs_create_group(&client->dev.kobj, + &s9230_64x_cpld2_group); + break; + case cpld3: + case cpld4: + case cpld5: + status = sysfs_create_group(&client->dev.kobj, + &s9230_64x_cpld345_group); + break; + default: + status = -EINVAL; + } + + if (status) + goto exit; + + dev_info(&client->dev, "chip found\n"); + + /* add probe chip to client list */ + ingrasys_i2c_cpld_add_client(client); + + return 0; +exit: + sysfs_remove_group(&client->dev.kobj, &s9230_64x_cpld345_group); + return status; +} + +/* cpld drvier remove */ +static int ingrasys_i2c_cpld_remove(struct i2c_client *client) +{ + struct cpld_data *data = i2c_get_clientdata(client); + + switch (data->index) { + case cpld1: + sysfs_remove_group(&client->dev.kobj, &s9230_64x_cpld1_group); + break; + case cpld2: + sysfs_remove_group(&client->dev.kobj, &s9230_64x_cpld2_group); + break; + case cpld3: + case cpld4: + case cpld5: + sysfs_remove_group(&client->dev.kobj, + &s9230_64x_cpld345_group); + break; + } + + ingrasys_i2c_cpld_remove_client(client); + return 0; +} + +MODULE_DEVICE_TABLE(i2c, ingrasys_i2c_cpld_id); + +static struct i2c_driver ingrasys_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ingrasys_i2c_cpld", + }, + .probe = ingrasys_i2c_cpld_probe, + .remove = ingrasys_i2c_cpld_remove, + .id_table = ingrasys_i2c_cpld_id, + .address_list = cpld_i2c_addr, +}; + +/* provid cpld register read */ +/* cpld_idx indicate the index of cpld device */ +int ingrasys_i2c_cpld_read(u8 cpld_idx, + u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + struct cpld_data *data; + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + data = i2c_get_clientdata(cpld_node->client); + if (data->index == cpld_idx) { + DEBUG_PRINT("cpld_idx=%d, read reg 0x%02x", + cpld_idx, reg); + I2C_READ_BYTE_DATA(ret, &data->access_lock, + cpld_node->client, reg); + DEBUG_PRINT("cpld_idx=%d, read reg 0x%02x = 0x%02x", + cpld_idx, reg, ret); + break; + } + } + + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_read); + +/* provid cpld register write */ +/* cpld_idx indicate the index of cpld device */ +int ingrasys_i2c_cpld_write(u8 cpld_idx, + u8 reg, + u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + struct cpld_data *data; + + list_for_each(list_node, &cpld_client_list) { + cpld_node = list_entry(list_node, + struct cpld_client_node, list); + data = i2c_get_clientdata(cpld_node->client); + + if (data->index == cpld_idx) { + I2C_WRITE_BYTE_DATA(ret, &data->access_lock, + cpld_node->client, + reg, value); + DEBUG_PRINT("cpld_idx=%d, write reg 0x%02x val 0x%02x, ret=%d", + cpld_idx, reg, value, ret); + break; + } + } + + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_write); + +/* provid qsfp port status register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_qsfp_port_status_val(u8 port_num) +{ + u8 cpld_idx, cpld_port, reg; + int reg_val; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_STATUS_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_qsfp_port_status_val); + +/* provid qsfp port config register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_qsfp_port_config_val(u8 port_num) +{ + u8 cpld_idx, cpld_port, reg; + int reg_val; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_CONFIG_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_qsfp_port_config_val); + +/* provid qsfp port config register write */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_set_qsfp_port_config_val(u8 port_num, + u8 reg_val) +{ + u8 cpld_idx, cpld_port, reg, ret; + + if (INVALID(port_num, QSFP_MIN_PORT_NUM, QSFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + QSFP_TO_CPLD_IDX(port_num, cpld_idx, cpld_port); + reg = QSFP_PORT_CONFIG_REG(cpld_port); + DEBUG_PRINT("port_num=%d, cpld_idx=%d, cpld_port=%d, reg=0x%x", + port_num, cpld_idx, cpld_port, reg); + ret = ingrasys_i2c_cpld_write(cpld_idx, reg, reg_val); + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_set_qsfp_port_config_val); + +/* provid sfp port status register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_sfp_port_status_val(u8 port_num) +{ + u8 cpld_idx, reg; + int reg_val; + + if (INVALID(port_num, SFP_MIN_PORT_NUM, SFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + SFP_TO_CPLD_IDX(port_num, cpld_idx); + reg = CPLD_SFP_PORT_STATUS_REG; + DEBUG_PRINT("port_num=%d, cpld_idx=%d, reg=0x%x", + port_num, cpld_idx, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_sfp_port_status_val); + +/* provid qsfp port config register read */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_get_sfp_port_config_val(u8 port_num) +{ + u8 cpld_idx, reg; + int reg_val; + + if (INVALID(port_num, SFP_MIN_PORT_NUM, SFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + SFP_TO_CPLD_IDX(port_num, cpld_idx); + reg = CPLD_SFP_PORT_CONFIG_REG; + DEBUG_PRINT("port_num=%d, cpld_idx=%d, reg=0x%x", + port_num, cpld_idx, reg); + reg_val = ingrasys_i2c_cpld_read(cpld_idx, reg); + return reg_val; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_get_sfp_port_config_val); + +/* provid qsfp port config register write */ +/* port_num indicate the front panel qsfp port number */ +int ingrasys_i2c_cpld_set_sfp_port_config_val(u8 port_num, + u8 reg_val) +{ + u8 cpld_idx, reg, ret; + + if (INVALID(port_num, SFP_MIN_PORT_NUM, SFP_MAX_PORT_NUM)) { + DEBUG_PRINT("invalid input value %d", port_num); + return -1; + } + SFP_TO_CPLD_IDX(port_num, cpld_idx); + reg = CPLD_SFP_PORT_CONFIG_REG; + DEBUG_PRINT("port_num=%d, cpld_idx=%d, reg=0x%x", + port_num, cpld_idx, reg); + ret = ingrasys_i2c_cpld_write(cpld_idx, reg, reg_val); + return ret; +} +EXPORT_SYMBOL(ingrasys_i2c_cpld_set_sfp_port_config_val); + +static int __init ingrasys_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&ingrasys_i2c_cpld_driver); +} + +static void __exit ingrasys_i2c_cpld_exit(void) +{ + i2c_del_driver(&ingrasys_i2c_cpld_driver); +} + +MODULE_AUTHOR("Leo Lin "); +MODULE_DESCRIPTION("ingrasys_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(ingrasys_i2c_cpld_init); +module_exit(ingrasys_i2c_cpld_exit); + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.h b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.h new file mode 100644 index 000000000000..e0e53174d675 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_i2c_cpld.h @@ -0,0 +1,223 @@ +/* header file for i2c cpld driver of ingrasys_s9230_64x + * + * Copyright (C) 2017 Ingrasys Technology Corporation. + * Leo Lin + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef INGRASYS_S9230_64X_I2C_CPLD_H +#define INGRASYS_S9230_64X_I2C_CPLD_H + +/* CPLD device index value */ +enum cpld_id { + cpld1, + cpld2, + cpld3, + cpld4, + cpld5 +}; + +/* port number on CPLD */ +#define CPLD_1_PORT_NUM 12 +#define CPLD_2_PORT_NUM 13 + +/* QSFP port number */ +#define QSFP_MAX_PORT_NUM 64 +#define QSFP_MIN_PORT_NUM 1 + +/* SFP+ port number */ +#define SFP_MAX_PORT_NUM 2 +#define SFP_MIN_PORT_NUM 1 + + +/* CPLD registers */ +#define CPLD_BOARD_TYPE_REG 0x0 +#define CPLD_EXT_BOARD_TYPE_REG 0x7 +#define CPLD_VERSION_REG 0x1 +#define CPLD_ID_REG 0x2 +#define CPLD_QSFP_PORT_STATUS_BASE_REG 0x20 +#define CPLD_QSFP_PORT_CONFIG_BASE_REG 0x30 +#define CPLD_QSFP_PORT_INTERRUPT_REG 0x40 +#define CPLD_SFP_PORT_STATUS_REG 0x2F +#define CPLD_SFP_PORT_CONFIG_REG 0x3F +#define CPLD_QSFP_PORT_INTERRUPT_REG 0x40 +#define CPLD_10GMUX_CONFIG_REG 0x41 +#define CPLD_BMC_STATUS_REG 0x42 +#define CPLD_BMC_WATCHDOG_REG 0x43 +#define CPLD_USB_STATUS_REG 0x44 +#define CPLD_REST_CONTROL_REG 0x4A + + +/* bit definition for register value */ +enum CPLD_QSFP_PORT_STATUS_BITS { + CPLD_QSFP_PORT_STATUS_INT_BIT, + CPLD_QSFP_PORT_STATUS_ABS_BIT, +}; +enum CPLD_QSFP_PORT_CONFIG_BITS { + CPLD_QSFP_PORT_CONFIG_RESET_BIT, + CPLD_QSFP_PORT_CONFIG_RESERVE_BIT, + CPLD_QSFP_PORT_CONFIG_LPMODE_BIT, +}; +enum CPLD_SFP_PORT_STATUS_BITS { + CPLD_SFP_PORT_STATUS_PRESENT_BIT, + CPLD_SFP_PORT_STATUS_TXFAULT_BIT, + CPLD_SFP_PORT_STATUS_RXLOS_BIT, +}; +enum CPLD_SFP_PORT_CONFIG_BITS { + CPLD_SFP_PORT_CONFIG_TXDIS_BIT, + CPLD_SFP_PORT_CONFIG_RS_BIT, + CPLD_SFP_PORT_CONFIG_TS_BIT, +}; +enum CPLD_10GMUX_CONFIG_BITS { + CPLD_10GMUX_CONFIG_ENSMB_BIT, + CPLD_10GMUX_CONFIG_ENINPUT_BIT, + CPLD_10GMUX_CONFIG_SEL1_BIT, + CPLD_10GMUX_CONFIG_SEL0_BIT, +}; +enum CPLD_BMC_WATCHDOG_BITS { + CPLD_10GMUX_CONFIG_ENTIMER_BIT, + CPLD_10GMUX_CONFIG_TIMEOUT_BIT, +}; +enum CPLD_RESET_CONTROL_BITS { + CPLD_RESET_CONTROL_SWRST_BIT, + CPLD_RESET_CONTROL_CP2104RST_BIT, + CPLD_RESET_CONTROL_82P33814RST_BIT, + CPLD_RESET_CONTROL_BMCRST_BIT, +}; + +/* bit field structure for register value */ +struct cpld_reg_board_type_t { + u8 build_rev:2; + u8 hw_rev:2; + u8 board_id:4; +}; + +struct cpld_reg_version_t { + u8 revision:6; + u8 release:1; + u8 reserve:1; +}; + +struct cpld_reg_id_t { + u8 id:3; + u8 release:5; +}; + +/* common manipulation */ +#define INVALID(i, min, max) ((i < min) || (i > max) ? 1u : 0u) +#define READ_BIT(val, bit) ((0u == (val & (1<bf_name) +#define READ_BF_1(bf_struct, val, bf_name, bf_value) \ + bf_struct bf; \ + bf.data = val; \ + bf_value = bf.bf_name +#define BOARD_TYPE_BUILD_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, build_rev, res) +#define BOARD_TYPE_HW_REV_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, hw_rev, res) +#define BOARD_TYPE_BOARD_ID_GET(val, res) \ + READ_BF(cpld_reg_board_type_t, val, board_id, res) +#define CPLD_VERSION_REV_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, revision, res) +#define CPLD_VERSION_REL_GET(val, res) \ + READ_BF(cpld_reg_version_t, val, release, res) +#define CPLD_ID_ID_GET(val, res) \ + READ_BF(cpld_reg_id_t, val, id, res) +#define CPLD_ID_REL_GET(val, res) \ + READ_BF(cpld_reg_id_t, val, release, res) +/* QSFP/SFP registers manipulation */ +#define QSFP_TO_CPLD_IDX(qsfp_port, cpld_index, cpld_port) \ +{ \ + if (QSFP_MIN_PORT_NUM <= qsfp_port && qsfp_port <= CPLD_1_PORT_NUM) { \ + cpld_index = cpld1; \ + cpld_port = qsfp_port - 1; \ + } else if (CPLD_1_PORT_NUM < qsfp_port \ + && qsfp_port <= QSFP_MAX_PORT_NUM) { \ + cpld_index = cpld2 + (qsfp_port - 1 - CPLD_1_PORT_NUM) \ + / CPLD_2_PORT_NUM; \ + cpld_port = (qsfp_port - 1 - CPLD_1_PORT_NUM) % \ + CPLD_2_PORT_NUM; \ + } else { \ + cpld_index = 0; \ + cpld_port = 0; \ + } \ +} +#define SFP_TO_CPLD_IDX(sfp_port, cpld_index) \ + (cpld_index = sfp_port - SFP_MIN_PORT_NUM) +#define QSFP_PORT_STATUS_REG(cpld_port) \ + (CPLD_QSFP_PORT_STATUS_BASE_REG + cpld_port) +#define QSFP_PORT_CONFIG_REG(cpld_port) \ + (CPLD_QSFP_PORT_CONFIG_BASE_REG + cpld_port) +#define QSFP_PORT_INT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_INT_BIT) +#define QSFP_PORT_ABS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_QSFP_PORT_STATUS_ABS_BIT) +#define QSFP_PORT_RESET_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_RESET_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_RESET_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_RESET_BIT) +#define QSFP_PORT_LPMODE_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define QSFP_PORT_LPMODE_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_QSFP_PORT_CONFIG_LPMODE_BIT) +#define SFP_PORT_PRESENT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_PRESENT_BIT) + +#define SFP_PORT_TXFAULT_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_TXFAULT_BIT) +#define SFP_PORT_RXLOS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_STATUS_RXLOS_BIT) +#define SFP_PORT_TXDIS_BIT_GET(port_status_value) \ + READ_BIT(port_status_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_GET(port_config_value) \ + READ_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TXDIS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_TXDIS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TXDIS_BIT) +#define SFP_PORT_RS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_RS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_RS_BIT) +#define SFP_PORT_TS_BIT_SET(port_config_value) \ + SET_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) +#define SFP_PORT_TS_BIT_CLEAR(port_config_value) \ + CLEAR_BIT(port_config_value, CPLD_SFP_PORT_CONFIG_TS_BIT) + +/* CPLD access functions */ +extern int ingrasys_i2c_cpld_get_qsfp_port_status_val(u8 port_num); +extern int ingrasys_i2c_cpld_get_qsfp_port_config_val(u8 port_num); +extern int ingrasys_i2c_cpld_set_qsfp_port_config_val(u8 port_num, u8 reg_val); +extern int ingrasys_i2c_cpld_get_sfp_port_status_val(u8 port_num); +extern int ingrasys_i2c_cpld_get_sfp_port_config_val(u8 port_num); +extern int ingrasys_i2c_cpld_set_sfp_port_config_val(u8 port_num, u8 reg_val); +extern u8 fp_port_to_phy_port(u8 fp_port); +#endif + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_platform.h b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_platform.h new file mode 100644 index 000000000000..a14853fdae9c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_platform.h @@ -0,0 +1,148 @@ +#ifndef _S9230_64X_PLATFORM_H +#define _S9230_64X_PLATFORM_H + +#include + +// remove debug before release +#define DEBUG + +enum bus_order { + I2C_BUS_MAIN, + MUX_9548_0_CH0, + MUX_9548_0_CH1, + MUX_9548_0_CH2, + MUX_9548_0_CH3, + MUX_9548_0_CH4, + MUX_9548_0_CH5, + MUX_9548_0_CH6, + MUX_9548_0_CH7, + MUX_9548_1_CH0, + MUX_9548_1_CH1, + MUX_9548_1_CH2, + MUX_9548_1_CH3, + MUX_9548_1_CH4, + MUX_9548_1_CH5, + MUX_9548_1_CH6, + MUX_9548_1_CH7, + MUX_9546_0_CH0, + MUX_9546_0_CH1, + MUX_9546_0_CH2, + MUX_9546_0_CH3, + MUX_9546_1_CH0, + MUX_9546_1_CH1, + MUX_9546_1_CH2, + MUX_9546_1_CH3, + MUX_9548_2_CH0, + MUX_9548_2_CH1, + MUX_9548_2_CH2, + MUX_9548_2_CH3, + MUX_9548_2_CH4, + MUX_9548_2_CH5, + MUX_9548_2_CH6, + MUX_9548_2_CH7, + MUX_9548_3_CH0, + MUX_9548_3_CH1, + MUX_9548_3_CH2, + MUX_9548_3_CH3, + MUX_9548_3_CH4, + MUX_9548_3_CH5, + MUX_9548_3_CH6, + MUX_9548_3_CH7, + MUX_9548_4_CH0, + MUX_9548_4_CH1, + MUX_9548_4_CH2, + MUX_9548_4_CH3, + MUX_9548_4_CH4, + MUX_9548_4_CH5, + MUX_9548_4_CH6, + MUX_9548_4_CH7, + MUX_9548_5_CH0, + MUX_9548_5_CH1, + MUX_9548_5_CH2, + MUX_9548_5_CH3, + MUX_9548_5_CH4, + MUX_9548_5_CH5, + MUX_9548_5_CH6, + MUX_9548_5_CH7, + MUX_9548_6_CH0, + MUX_9548_6_CH1, + MUX_9548_6_CH2, + MUX_9548_6_CH3, + MUX_9548_6_CH4, + MUX_9548_6_CH5, + MUX_9548_6_CH6, + MUX_9548_6_CH7, + MUX_9548_7_CH0, + MUX_9548_7_CH1, + MUX_9548_7_CH2, + MUX_9548_7_CH3, + MUX_9548_7_CH4, + MUX_9548_7_CH5, + MUX_9548_7_CH6, + MUX_9548_7_CH7, + MUX_9548_8_CH0, + MUX_9548_8_CH1, + MUX_9548_8_CH2, + MUX_9548_8_CH3, + MUX_9548_8_CH4, + MUX_9548_8_CH5, + MUX_9548_8_CH6, + MUX_9548_8_CH7, + MUX_9548_9_CH0, + MUX_9548_9_CH1, + MUX_9548_9_CH2, + MUX_9548_9_CH3, + MUX_9548_9_CH4, + MUX_9548_9_CH5, + MUX_9548_9_CH6, + MUX_9548_9_CH7, + MUX_9548_10_CH0, + MUX_9548_10_CH1, + MUX_9548_10_CH2, + MUX_9548_10_CH3, + MUX_9548_10_CH4, + MUX_9548_10_CH5, + MUX_9548_10_CH6, + MUX_9548_10_CH7, +}; + +#define I2C_ADDR_MUX_9555_0 (0x20) +#define I2C_ADDR_MUX_9555_1 (0x24) +#define I2C_ADDR_MUX_9555_2 (0x25) +#define I2C_ADDR_MUX_9555_3 (0x26) +#define I2C_ADDR_MUX_9539_0 (0x76) +#define I2C_ADDR_MUX_9539_1 (0x76) +#define I2C_BUS_FAN_STATUS (I2C_BUS_MAIN) +#define I2C_BUS_SYS_LED (MUX_9548_1_CH1) + +#define NUM_OF_I2C_MUX (11) +#define NUM_OF_CPLD (5) +#define NUM_OF_QSFP_PORT (64) +#define NUM_OF_SFP_PORT (2) +#define QSFP_EEPROM_I2C_ADDR (0x50) + +enum gpio_reg { + REG_PORT0_IN, + REG_PORT1_IN, + REG_PORT0_OUT, + REG_PORT1_OUT, + REG_PORT0_POL, + REG_PORT1_POL, + REG_PORT0_DIR, + REG_PORT1_DIR, +}; + +struct ing_i2c_board_info { + int ch; + int size; + struct i2c_board_info *board_info; +}; + +struct i2c_init_data { + __u16 ch; + __u16 addr; + __u8 reg; + __u8 value; +}; + +#endif diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_psu.c b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_psu.c new file mode 100644 index 000000000000..694b57bd748d --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/modules/ingrasys_s9230_64x_psu.c @@ -0,0 +1,388 @@ +/* + * S9230-64x PSU driver + * + * Copyright (C) 2017 Ingrasys, Inc. + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ingrasys_s9230_64x_platform.h" + +static ssize_t show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf); +static struct s9230_psu_data *s9230_psu_update_status(struct device *dev); +static struct s9230_psu_data *s9230_psu_update_eeprom(struct device *dev); +static int s9230_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len); + + +#define DRIVER_NAME "psu" + +// Addresses scanned +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* PSU EEPROM SIZE */ +#define EEPROM_SZ 256 +#define READ_EEPROM 1 +#define NREAD_EEPROM 0 + +static struct i2c_client pca9555_client; + +/* pca9555 gpio pin mapping */ +#define PSU2_PWROK 0 +#define PSU2_PRSNT_L 1 +#define PSU2_PWRON_L 2 +#define PSU1_PWROK 3 +#define PSU1_PRSNT_L 4 +#define PSU1_PWRON_L 5 +#define TMP_75_INT_L 6 + +/* Driver Private Data */ +struct s9230_psu_data { + struct mutex lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + s32 status; /* IO expander value */ + char eeprom[EEPROM_SZ]; /* psu eeprom data */ + char psuABS; /* PSU absent */ + char psuPG; /* PSU power good */ +}; + +enum psu_index +{ + s9230_psu1, + s9230_psu2 +}; + +/* + * display power good attribute + */ +static ssize_t +show_psu_pg(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9230_psu_data *data = s9230_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuPG; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + +/* + * display power absent attribute + */ +static ssize_t +show_psu_abs(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct s9230_psu_data *data = s9230_psu_update_status(dev); + unsigned int value; + + mutex_lock(&data->lock); + value = data->psuABS; + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", value); +} + + +/* + * sysfs attributes for psu + */ +static DEVICE_ATTR(psu_pg, S_IRUGO, show_psu_pg, NULL); +static DEVICE_ATTR(psu_abs, S_IRUGO, show_psu_abs, NULL); +static DEVICE_ATTR(psu_eeprom, S_IRUGO, show_psu_eeprom, NULL); + +static struct attribute *s9230_psu_attributes[] = { + &dev_attr_psu_pg.attr, + &dev_attr_psu_abs.attr, + &dev_attr_psu_eeprom.attr, + NULL +}; + +/* + * display psu eeprom content + */ +static ssize_t +show_psu_eeprom(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct s9230_psu_data *data = s9230_psu_update_eeprom(dev); + + memcpy(buf, (char *)data->eeprom, EEPROM_SZ); + return EEPROM_SZ; +} + +static const struct attribute_group s9230_psu_group = { + .attrs = s9230_psu_attributes, +}; + +/* + * check gpio expander is accessible + */ +static int +pca9555_detect(struct i2c_client *client) +{ + if (i2c_smbus_read_byte_data(client, REG_PORT0_DIR) < 0) { + return -ENODEV; + } + + return 0; +} + +/* + * client address init + */ +static void +i2c_devices_client_address_init(struct i2c_client *client) +{ + pca9555_client = *client; + pca9555_client.addr = 0x25; +} + +static int +s9230_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct s9230_psu_data *data; + int status, err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct s9230_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct s9230_psu_data)); + i2c_set_clientdata(client, data); + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->lock); + + i2c_devices_client_address_init(client); + + err = pca9555_detect(&pca9555_client); + if (err) { + return err; + } + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &s9230_psu_group); + if (status) { + goto exit_free; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &s9230_psu_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int +s9230_psu_remove(struct i2c_client *client) +{ + struct s9230_psu_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &s9230_psu_group); + kfree(data); + + return 0; +} + + +/* + * psu eeprom read utility + */ +static int +s9230_psu_read_block(struct i2c_client *client, + u8 command, + u8 *data, + int data_len) +{ + int i=0, ret=0; + int blk_max = 32; //max block read size + + /* read eeprom, 32 * 8 = 256 bytes */ + for (i=0; i < EEPROM_SZ/blk_max; i++) { + ret = i2c_smbus_read_i2c_block_data(client, (i*blk_max), blk_max, + data + (i*blk_max)); + if (ret < 0) { + return ret; + } + } + return ret; +} + +/* + * update eeprom content + */ +static struct s9230_psu_data +*s9230_psu_update_eeprom(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9230_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + if (time_after(jiffies, data->last_updated + 300 * HZ) + || !data->valid) { + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9230_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + /* Read eeprom */ + if (!data->psuABS) { + //clear local eeprom data + memset(data->eeprom, 0, EEPROM_SZ); + + //read eeprom + status = s9230_psu_read_block(client, 0, data->eeprom, + ARRAY_SIZE(data->eeprom)); + + if (status < 0) { + memset(data->eeprom, 0, EEPROM_SZ); + dev_err(&client->dev, "Read eeprom failed, status=(%d)\n", status); + } else { + data->valid = 1; + } + } else { + memset(data->eeprom, 0, EEPROM_SZ); + } + data->last_updated = jiffies; + } + + mutex_unlock(&data->lock); + + return data; +} + +/* + * update psu status + */ +static struct s9230_psu_data +*s9230_psu_update_status(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct s9230_psu_data *data = i2c_get_clientdata(client); + s32 status = 0; + int psu_pwrok = 0; + int psu_prsnt_l = 0; + + mutex_lock(&data->lock); + + /* Read psu status */ + + status = i2c_smbus_read_word_data(&(pca9555_client), REG_PORT0_IN); + data->status = status; + + /*read psu status from io expander*/ + + if (data->index == s9230_psu1) { + psu_pwrok = PSU1_PWROK; + psu_prsnt_l = PSU1_PRSNT_L; + } else { + psu_pwrok = PSU2_PWROK; + psu_prsnt_l = PSU2_PRSNT_L; + } + data->psuPG = (status >> psu_pwrok) & 0x1; + data->psuABS = (status >> psu_prsnt_l) & 0x1; + + mutex_unlock(&data->lock); + + return data; +} + +static const struct i2c_device_id s9230_psu_id[] = { + { "psu1", s9230_psu1 }, + { "psu2", s9230_psu2 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, s9230_psu_id); + +static struct i2c_driver s9230_psu_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = s9230_psu_probe, + .remove = s9230_psu_remove, + .id_table = s9230_psu_id, + .address_list = normal_i2c, +}; + +static int __init s9230_psu_init(void) +{ + return i2c_add_driver(&s9230_psu_driver); +} + +static void __exit s9230_psu_exit(void) +{ + i2c_del_driver(&s9230_psu_driver); +} + +module_init(s9230_psu_init); +module_exit(s9230_psu_exit); + +MODULE_AUTHOR("Jason Tsai "); +MODULE_DESCRIPTION("S9230-64X psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/qsfp-monitor.service b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/qsfp-monitor.service new file mode 100644 index 000000000000..cf4a6a8ad41e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9230-64x-monitor.service +After=s9230-64x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/s9230-64x-monitor.service b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/s9230-64x-monitor.service new file mode 100644 index 000000000000..5caf968e659a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/service/s9230-64x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9230_64x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/i2c_utils.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/i2c_utils.sh new file mode 100755 index 000000000000..e899e64a7c3b --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/i2c_utils.sh @@ -0,0 +1,1850 @@ +#!/bin/bash + +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# trun on for more debug output +#DEBUG="on" + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +COLOR_LED=${2} +QSFP_PORT=${2} +SFP_PORT=${2} +QSFP_ACTION=${2} +SFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +TARGET_10G_MUX=${2} +ONOFF_LED=${3} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 + +# PCA9548#0 0x70 +NUM_MUX_9548_0_CH0=$(( ${NUM_I801_DEVICE} + 1 )) # CPLD1 +NUM_MUX_9548_0_CH1=$(( ${NUM_I801_DEVICE} + 2 )) # CPLD2 +NUM_MUX_9548_0_CH2=$(( ${NUM_I801_DEVICE} + 3 )) # CPLD3 +NUM_MUX_9548_0_CH3=$(( ${NUM_I801_DEVICE} + 4 )) # CPLD4 +NUM_MUX_9548_0_CH4=$(( ${NUM_I801_DEVICE} + 5 )) # CPLD5 +NUM_MUX_9548_0_CH5=$(( ${NUM_I801_DEVICE} + 6 )) # LM75_1 LM75_2 +NUM_MUX_9548_0_CH6=$(( ${NUM_I801_DEVICE} + 7 )) # LM75_3 LM75_4 + +# PCA9548#1 0x73 +NUM_MUX_9548_1_CH0=$(( ${NUM_I801_DEVICE} + 9 )) # UCD9090 +NUM_MUX_9548_1_CH1=$(( ${NUM_I801_DEVICE} + 10 )) # PCA9539 0x76 for FP LED & HW ID +NUM_MUX_9548_1_CH2=$(( ${NUM_I801_DEVICE} + 11 )) # PCA9539 0x76 for SYS control +NUM_MUX_9548_1_CH4=$(( ${NUM_I801_DEVICE} + 13 )) # 10G Mux +NUM_MUX_9548_1_CH7=$(( ${NUM_I801_DEVICE} + 16 )) # HWM & TMP75 on BMC + +# PCA9546#0 0X72 +NUM_MUX_9546_0_CH0=$(( ${NUM_I801_DEVICE} + 17 )) # PSU1 0x58 +NUM_MUX_9546_0_CH1=$(( ${NUM_I801_DEVICE} + 18 )) # PSU2 0x58 +NUM_MUX_9546_0_CH2=$(( ${NUM_I801_DEVICE} + 19 )) # PCA9548#2 0x71 +NUM_MUX_9546_0_CH3=$(( ${NUM_I801_DEVICE} + 20 )) # PCA9546#1 0x71 + +# PCA9546#1 0X71 +NUM_MUX_9546_1_CH0=$(( ${NUM_I801_DEVICE} + 21 )) # SFP0 EEPROM 0x50 +NUM_MUX_9546_1_CH1=$(( ${NUM_I801_DEVICE} + 22 )) # SFP1 EEPROM 0x50 + +# PCA9548#2 0X71 +NUM_MUX_9548_2_CH0=$(( ${NUM_I801_DEVICE} + 25 )) # PCA9548#3 0x74 +NUM_MUX_9548_2_CH1=$(( ${NUM_I801_DEVICE} + 26 )) # PCA9548#4 0x74 +NUM_MUX_9548_2_CH2=$(( ${NUM_I801_DEVICE} + 27 )) # PCA9548#5 0x74 +NUM_MUX_9548_2_CH3=$(( ${NUM_I801_DEVICE} + 28 )) # PCA9548#6 0x74 +NUM_MUX_9548_2_CH4=$(( ${NUM_I801_DEVICE} + 29 )) # PCA9548#7 0x74 +NUM_MUX_9548_2_CH5=$(( ${NUM_I801_DEVICE} + 30 )) # PCA9548#8 0x74 +NUM_MUX_9548_2_CH6=$(( ${NUM_I801_DEVICE} + 31 )) # PCA9548#9 0x74 +NUM_MUX_9548_2_CH7=$(( ${NUM_I801_DEVICE} + 32 )) # PCA9548#10 0x74 + +# PCA9548#3~10 0X74 +NUM_MUX_9548_3_CH0=$(( ${NUM_I801_DEVICE} + 33 )) # QSFP 0 EEPROM +NUM_MUX_9548_4_CH0=$(( ${NUM_I801_DEVICE} + 41 )) # QSFP 8 EEPROM +NUM_MUX_9548_5_CH0=$(( ${NUM_I801_DEVICE} + 49 )) # QSFP 16 EEPROM +NUM_MUX_9548_6_CH0=$(( ${NUM_I801_DEVICE} + 57 )) # QSFP 24 EEPROM +NUM_MUX_9548_7_CH0=$(( ${NUM_I801_DEVICE} + 65 )) # QSFP 32 EEPROM +NUM_MUX_9548_8_CH0=$(( ${NUM_I801_DEVICE} + 73 )) # QSFP 40 EEPROM +NUM_MUX_9548_9_CH0=$(( ${NUM_I801_DEVICE} + 81 )) # QSFP 48 EEPROM +NUM_MUX_9548_10_CH0=$(( ${NUM_I801_DEVICE} + 89 )) # QSFP 56 EEPROM + +# MUX Alias +I2C_BUS_MAIN=${NUM_I801_DEVICE} +I2C_BUS_HWM=${NUM_MUX_9548_1_CH7} +I2C_BUS_FAN_STATUS=${I2C_BUS_MAIN} +I2C_BUS_SYS_LED=${NUM_MUX_9548_1_CH1} +I2C_BUS_HW_ID=${NUM_MUX_9548_1_CH1} +I2C_BUS_BMC_HW_ID=${I2C_BUS_MAIN} +I2C_BUS_PSU_STAT=${I2C_BUS_MAIN} +I2C_BUS_FANTRAY_LED=${I2C_BUS_MAIN} +I2C_BUS_MB_EEPROM=${I2C_BUS_MAIN} +I2C_BUS_CB_EEPROM=${I2C_BUS_MAIN} +I2C_BUS_PSU1_EEPROM=${NUM_MUX_9546_0_CH1} +I2C_BUS_PSU2_EEPROM=${NUM_MUX_9546_0_CH0} +I2C_BUS_CPLD1=${NUM_MUX_9548_0_CH0} +I2C_BUS_CPLD2=${NUM_MUX_9548_0_CH1} +I2C_BUS_CPLD3=${NUM_MUX_9548_0_CH2} +I2C_BUS_CPLD4=${NUM_MUX_9548_0_CH3} +I2C_BUS_CPLD5=${NUM_MUX_9548_0_CH4} +I2C_BUS_10GMUX=${NUM_MUX_9548_1_CH4} + +# I2C BUS path +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +# TODO: need to verify HWM deivce path after board ready +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon7" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_MUX_9548_0_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH0}" +PATH_MUX_9548_0_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH1}" +PATH_MUX_9548_0_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH2}" +PATH_MUX_9548_0_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH3}" +PATH_MUX_9548_0_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH4}" +PATH_MUX_9548_0_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH5}" +PATH_MUX_9548_0_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_0_CH6}" +PATH_MUX_9548_1_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH0}" +PATH_MUX_9548_1_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH1}" +PATH_MUX_9548_1_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH2}" +PATH_MUX_9548_1_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_1_CH7}" +PATH_MUX_9546_0_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH0}" +PATH_MUX_9546_0_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH1}" +PATH_MUX_9546_0_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH2}" +PATH_MUX_9546_0_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_0_CH3}" +PATH_MUX_9546_1_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH0}" +PATH_MUX_9546_1_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9546_1_CH1}" +PATH_MUX_9548_2_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH0}" +PATH_MUX_9548_2_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH1}" +PATH_MUX_9548_2_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH2}" +PATH_MUX_9548_2_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH3}" +PATH_MUX_9548_2_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH4}" +PATH_MUX_9548_2_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH5}" +PATH_MUX_9548_2_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH6}" +PATH_MUX_9548_2_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_2_CH7}" +PATH_MUX_9548_3_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_3_CH0}" +PATH_MUX_9548_4_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_4_CH0}" +PATH_MUX_9548_5_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_5_CH0}" +PATH_MUX_9548_6_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_6_CH0}" +PATH_MUX_9548_7_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_7_CH0}" +PATH_MUX_9548_8_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_8_CH0}" +PATH_MUX_9548_9_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_9_CH0}" +PATH_MUX_9548_10_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_10_CH0}" +PATH_CPLD1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD1}" +PATH_CPLD2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD2}" +PATH_CPLD3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD3}" +PATH_CPLD4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD4}" +PATH_CPLD5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CPLD5}" +PATH_10GMUX=${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_10GMUX} + + +# I2C Address +### I2C MUX +I2C_ADDR_MUX_9548_0=0x70 +I2C_ADDR_MUX_9548_1=0x73 +I2C_ADDR_MUX_9546_0=0x72 +I2C_ADDR_MUX_9546_1=0x71 +I2C_ADDR_MUX_9548_2=0x71 +I2C_ADDR_MUX_9548_3=0x74 +I2C_ADDR_MUX_9548_4=0x74 +I2C_ADDR_MUX_9548_5=0x74 +I2C_ADDR_MUX_9548_6=0x74 +I2C_ADDR_MUX_9548_7=0x74 +I2C_ADDR_MUX_9548_8=0x74 +I2C_ADDR_MUX_9548_9=0x74 +I2C_ADDR_MUX_9548_10=0x74 + +### GPIO Expander +I2C_ADDR_MUX_9539_0=0x76 # LED & HW ID +I2C_ADDR_MUX_9539_1=0x76 # SYS config +I2C_ADDR_MUX_9539_2=0x77 # on CPU board, STATUS and ERR from CPLD +I2C_ADDR_MUX_9555_0=0x20 # on FAN board, fan status and led config +I2C_ADDR_MUX_9555_1=0x24 # on BMC board, INT and HW ID +I2C_ADDR_MUX_9555_2=0x25 # on BMC board, PSU status +I2C_ADDR_MUX_9555_3=0x26 # on BMC board, RST and SEL +I2C_ADDR_MUX_9555_3=0x26 # on BMC board, RST and SEL + + +### peripheral +I2C_ADDR_MB_EEPROM=0x55 # on main board +I2C_ADDR_CB_EEPROM=0x51 # on cpu board +I2C_ADDR_UCD9090=0x34 +I2C_ADDR_W83795=0x2F +I2C_ADDR_PSU1_EEPROM=0x50 +I2C_ADDR_PSU2_EEPROM=0x50 +I2C_ADDR_LM75_1=0x4D # Rear Panel +I2C_ADDR_LM75_2=0x4E # Rear MAC +I2C_ADDR_LM75_3=0x4D # Front Panel +I2C_ADDR_LM75_4=0x4E # Front MAC +I2C_ADDR_TMP75_CB=0x4F # on cpu board +I2C_ADDR_TMP75_BB=0x4A # on bmc board +I2C_ADDR_QSFP_EEPROM=0x50 +I2C_ADDR_SFP_EEPROM=0x50 +I2C_ADDR_CPLD=0x33 +I2C_ADDR_10GMUX=0x67 + +#sysfs +PATH_SYSFS_PSU1="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU1_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU1_EEPROM)" +PATH_SYSFS_PSU2="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_PSU2_EEPROM}-$(printf "%04x" $I2C_ADDR_PSU2_EEPROM)" + +#ACTIVE LOW enable flag +ACTIVE_LOW_EN=1 +ACTIVE_HIGH_EN=0 +#GPIO Direction In/Out +DIR_IN=in +DIR_OUT=out + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# IO expander register +# direction +REG_PORT0_DIR=6 +REG_PORT1_DIR=7 +# polarity +REG_PORT0_POL=4 +REG_PORT1_POL=5 +# output +REG_PORT0_OUT=2 +REG_PORT1_OUT=3 +# input +REG_PORT0_IN=0 +REG_PORT1_IN=1 + +# qsfp port number range +MIN_QSFP_PORT_NUM=1 +MAX_QSFP_PORT_NUM=64 + +# sfp+ port number range +MIN_SFP_PORT_NUM=1 +MAX_SFP_PORT_NUM=2 + +# CPLD access +# port status +CPLD_QSFP_STATUS_KEY=cpld_qsfp_port_status +CPLD_SFP_STATUS_KEY=cpld_sfp_port_status +# bit define +CPLD_QSFP_STATUS_ABS_BIT=1 +CPLD_SFP_STATUS_PRES_BIT=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_fan_speed_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_led_test" + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cb_eeprom_get" + #echo " : ${0} i2c_eeprom_sync" + echo " : ${0} i2c_qsfp_eeprom_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_eeprom_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_sfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_cb_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_status_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_qsfp_type_get [${MIN_QSFP_PORT_NUM}-${MAX_QSFP_PORT_NUM}]" + echo " : ${0} i2c_sfp_type_get [${MIN_SFP_PORT_NUM}-${MAX_SFP_PORT_NUM}]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_bmc_board_type_get" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_psu_status_set" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber|off" + echo " : ${0} i2c_psu1_led green|amber|off" + echo " : ${0} i2c_psu2_led green|amber|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo " : ${0} i2c_10g_mux cpu|fp" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#logical(front panel) to physical (falcon core) port mapping +function _port_logic2phy { + + local logic_port=$1 + local phy_port=0 + + if (( $logic_port >=1 && $logic_port <= 32 )) ; then + phy_port=$(( (logic_port-1)/2*4 + (logic_port-1)%2 + 1)) + elif (( $logic_port >=33 && $logic_port <= 64 )) ; then + phy_port=$(( (((logic_port-1)%32))/2*4 + (logic_port-1)%2 + 3)) + fi + + echo $phy_port +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + #rmmod i2c_ismt + _util_rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + # add MUX PCA9548#0 on I801, assume to be i2c-1~8 + if [ ! -e ${PATH_MUX_9548_0_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_0}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_0} already init." + fi + + # add MUX PCA9548#1 on I801, assume to be i2c-9~16 + if [ ! -e ${PATH_MUX_9548_1_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_1}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_1} already init." + fi + + # add MUX PCA9546#0 on I801, assume to be i2c-17~20 + if [ ! -e ${PATH_MUX_9546_0_CH0} ]; then + _retry "echo 'pca9546 ${I2C_ADDR_MUX_9546_0}' > ${PATH_I801_DEVICE}/new_device" + else + echo "pca9546 ${I2C_ADDR_MUX_9546_0} already init." + fi + + # add MUX PCA9546#1 on PCA9546#0 CH3, assume to be i2c-21~24 + if [ ! -e ${PATH_MUX_9546_1_CH0} ]; then + _retry "echo 'pca9546 ${I2C_ADDR_MUX_9546_1}' > ${PATH_MUX_9546_0_CH3}/new_device" + else + echo "pca9546 ${I2C_ADDR_MUX_9546_1} already init." + fi + + # add MUX PCA9548#2 on PCA9546#0 CH2, assume to be i2c-25~32 + if [ ! -e ${PATH_MUX_9548_2_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_2}' > ${PATH_MUX_9546_0_CH2}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_2} already init." + fi + + # add MUX PCA9548#3 on PCA9548#2 CH0, assume to be i2c-33~40 + if [ ! -e ${PATH_MUX_9548_3_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_3}' > ${PATH_MUX_9548_2_CH0}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_3} already init." + fi + + # add MUX PCA9548#4 on PCA9548#2 CH1, assume to be i2c-41~48 + if [ ! -e ${PATH_MUX_9548_4_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_4}' > ${PATH_MUX_9548_2_CH1}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_4} already init." + fi + + # add MUX PCA9548#5 on PCA9548#2 CH2, assume to be i2c-49~56 + if [ ! -e ${PATH_MUX_9548_5_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_5}' > ${PATH_MUX_9548_2_CH2}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_5} already init." + fi + + # add MUX PCA9548#6 on PCA9548#2 CH3, assume to be i2c-57~64 + if [ ! -e ${PATH_MUX_9548_6_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_6}' > ${PATH_MUX_9548_2_CH3}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_6} already init." + fi + + # add MUX PCA9548#7 on PCA9548#2 CH4, assume to be i2c-65~72 + if [ ! -e ${PATH_MUX_9548_7_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_7}' > ${PATH_MUX_9548_2_CH4}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_7} already init." + fi + + # add MUX PCA9548#8 on PCA9548#2 CH5, assume to be i2c-73~80 + if [ ! -e ${PATH_MUX_9548_8_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_8}' > ${PATH_MUX_9548_2_CH5}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_8} already init." + fi + + # add MUX PCA9548#9 on PCA9548#2 CH6, assume to be i2c-81~88 + if [ ! -e ${PATH_MUX_9548_9_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_9}' > ${PATH_MUX_9548_2_CH6}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_9} already init." + fi + + # add MUX PCA9548#10 on PCA9548#2 CH7, assume to be i2c-89~96 + if [ ! -e ${PATH_MUX_9548_10_CH0} ]; then + _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_10}' > ${PATH_MUX_9548_2_CH7}/new_device" + else + echo "pca9548 ${I2C_ADDR_MUX_9548_10} already init." + fi + + _i2c_hwm_init + _util_rmmod eeprom + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_io_exp_init + _i2c_sensors_init + _i2c_cpld_init + _i2c_psu_init + + _i2c_qsfp_eeprom_init "new" + _i2c_sfp_eeprom_init "new" + _i2c_mb_eeprom_init "new" + _i2c_cb_eeprom_init "new" + _i2c_fan_speed_init + _i2c_led_psu_status_set + _i2c_led_fan_status_set + + # trun on sys led + echo "led_sys setup..." + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led + + _config_rmem +} + +#I2C Deinit +function _i2c_deinit { + echo "i2c deinit..." + for mod in coretemp jc42 w83795 eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_i801 ingrasys_s9230_64x_psu; + do + _util_rmmod $mod + done + echo "Done" +} + +function _i2c_cpld_init { + echo "CPLD init..." + _util_rmmod ingrasys_s9230_64x_i2c_cpld + modprobe ingrasys_s9230_64x_i2c_cpld + + # add cpld 1~5 to sysfs + for i in {1..5}; + do + local cpld_bus="I2C_BUS_CPLD${i}" + local cpld_path="PATH_CPLD${i}_DEVICE" + dev_path="${PATH_SYS_I2C_DEVICES}/${!cpld_bus}-$(printf "%04x" ${I2C_ADDR_CPLD})" + if ! [ -L ${dev_path} ]; then + echo "ingrasys_cpld${i} ${I2C_ADDR_CPLD}" > ${!cpld_path}/new_device + else + echo "${dev_path} already exist" + fi + done + + echo "Done" +} + +function _i2c_sensors_init { + echo "SENSORS init..." + local dev_path + # to make sure hwmon index in sysfs as expected, + # need to remove kernel module and then probe them in expected order + # remove all sensors kernel module + _util_rmmod coretemp + _util_rmmod jc42 + _util_rmmod w83795 + # probe coretemp kernel module + modprobe coretemp + # probe hwmon kernel module + modprobe w83795 + # add lm75 to sysfs + ####Main board thermal + ####lm75_1 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH5}-$(printf "%04x" ${I2C_ADDR_LM75_1})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_1}" > ${PATH_MUX_9548_0_CH5}/new_device # hwmon1 + else + echo "${dev_path} already exist" + fi + ####lm75_2 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH5}-$(printf "%04x" ${I2C_ADDR_LM75_2})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_2}" > ${PATH_MUX_9548_0_CH5}/new_device #hwmon2 + else + echo "${dev_path} already exist" + fi + ####lm75_3 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH6}-$(printf "%04x" ${I2C_ADDR_LM75_3})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_1}" > ${PATH_MUX_9548_0_CH6}/new_device # hwmon3 + else + echo "${dev_path} already exist" + fi + ####lm75_4 + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_0_CH6}-$(printf "%04x" ${I2C_ADDR_LM75_4})" + if ! [ -L ${dev_path} ]; then + echo "lm75 ${I2C_ADDR_LM75_4}" > ${PATH_MUX_9548_0_CH6}/new_device #hwmon4 + else + echo "${dev_path} already exist" + fi + ####BMC board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_1_CH7}-$(printf "%04x" ${I2C_ADDR_TMP75_BB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_BB}" > ${PATH_MUX_9548_1_CH7}/new_device #hwmon5 + else + echo "${dev_path} already exist" + fi + ####CPU board thermal + dev_path="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MAIN}-$(printf "%04x" ${I2C_ADDR_TMP75_CB})" + if ! [ -L ${dev_path} ]; then + echo "tmp75 ${I2C_ADDR_TMP75_CB}" > ${PATH_I801_DEVICE}/new_device #hwmon6 + else + echo "${dev_path} already exist" + fi + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MUX_9548_1_CH7}-$(printf "%04x" ${I2C_ADDR_W83795})" + if ! [ -L ${dev_path} ]; then + echo "w83795adg ${I2C_ADDR_W83795}" > ${PATH_MUX_9548_1_CH7}/new_device #hwmon7 + else + echo "${dev_path} already exist" + fi + + # probe jc42 kernel module + modprobe jc42 + + echo "Done" +} + +#FAN Speed Init +function _i2c_fan_speed_init { + echo -n "FAN SPEED INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + # init fan speed + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi +} + +# HWM init +function _i2c_hwm_init { + echo "HWM INIT..." + # select bank0 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x80 + # SW reset, Disable monitor + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x9C + # disable TR5/TR6 DTS + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x04 0x0 + # enable FANIN1~8 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x06 0xFF + # disable FANIN9~14 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x07 0x00 + # CLKIN clock frequency set as 48Mhz + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x01 0x1C + # select bank 2 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x00 0x82 + # set PWM mode in FOMC + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x0F 0x00 + # set 25KHz fan output frequency in F1OPFP&F2OPFP + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x18 0x84 + _util_i2cset -y -r ${I2C_BUS_HWM} ${I2C_ADDR_W83795} 0x19 0x84 +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + + # need to init BMC io expander first due to some io expander are reset default + echo "Init BMC INT & HW ID IO Expander" + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT0_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_1} ${REG_PORT1_POL} 0x00 + + echo "Init BMC PSU status IO Expander" + # PWRON default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_OUT} 0x00 + # default 0 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_OUT} 0x00 + # I/O 0.2 0.5 output(PWRON), rest input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_DIR} 0xDB + # I/O 1.0~1.1 input, 1.2~1.4 output (1.5~1.7 not enable) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_DIR} 0xE3 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_2} ${REG_PORT1_POL} 0x00 + + echo "Init BMC RST and SEL IO Expander" + # RST default is 1 (ACTIVE_LOW) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_OUT} 0x3F + # SEL default is 0 (HOST), EN default is 1 (ACTIVE_HIGH) + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_OUT} 0x1F + # I/O 0.0~0.5 output, 0.6~0.7 not use + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_DIR} 0xC0 + # all output + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_DIR} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9555_3} ${REG_PORT1_POL} 0x00 + + echo "Init System LED & HW ID IO Expander" + # I/O_0.x for System LED default 0, I/O_1.x for HW ID + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_OUT} 0x00 + # System LED => all output + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_DIR} 0x00 + # HW ID => all input + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${REG_PORT1_POL} 0x00 + + echo "Init FAN Board Status IO Expander" + # LED_G_H set to 1, LED_Y_G set to 0 (ACTIVE_HIGH) + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_OUT} 0x11 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_OUT} 0x11 + # DIR/ABS is input, LED_Y/LED_G is output + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_DIR} 0xCC + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_FAN_STATUS} ${I2C_ADDR_MUX_9555_0} ${REG_PORT1_POL} 0x00 + + echo "Init System SEL and RST IO Expander" + # RST 0.0~0.3 default 1 (ACTIVE low), rest default 0 + # SEL set to value 0 (host) + # LED_CLR set to 0 will clear all switch LED bitmap, set to 1 here + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_OUT} 0x0F + # RST 1.6~1.7 default 1 (ACTIVE low), INT 1.0~1.4 default 1 (ACTIVE low) + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT1_OUT} 0xDF + # all output, but MAC_RST_L 0.0 need to set as input to prevent reboot issue + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_DIR} 0x09 + # RST 1.5 !~ 1.7 output, rest are input + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT1_DIR} 0x1F + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${REG_PORT1_POL} 0x00 + + echo "Init CPU CPLD IO Expander" + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_DIR} 0xFF + # all input + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_DIR} 0xFF + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT0_POL} 0x00 + _util_i2cset -y -r ${I2C_BUS_MAIN} ${I2C_ADDR_MUX_9539_2} ${REG_PORT1_POL} 0x00 +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + # check if io expander for fan tray exist + result=`i2cget -y ${I2C_BUS_FANTRAY_LED} ${I2C_ADDR_MUX_9555_0} ${REG_PORT0_IN} 2>/dev/null` + err_code=$? + if [ "$err_code" != "0" ]; then + echo "fan tray not exist!" + return + fi + + for FAN_TRAY in {1..4}; + do + FAN_ALARM="FAN${FAN_TRAY}_ALARM" + if [ "${!FAN_ALARM}" == "0" ]; then + COLOR_LED="green" + ONOFF_LED="on" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="off" + _i2c_fan_tray_led + + echo "set [FAN TRAY ${FAN_TRAY}] [Green]=on [Amber]=off" + else + COLOR_LED="green" + ONOFF_LED="off" + _i2c_fan_tray_led + + COLOR_LED="amber" + ONOFF_LED="on" + _i2c_fan_tray_led + + echo "set [FAN TRAY ${FAN_TRAY}] [Green]=off [Amber]=on" + fi + done +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + + echo "led_fan setup..." + # all fan ok + if [ "${FAN1_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_fan_led + # all fan fail + elif [ "${FAN1_ALARM}" == "1" ] \ + && [ "${FAN3_ALARM}" == "1" ] \ + && [ "${FAN5_ALARM}" == "1" ] \ + && [ "${FAN7_ALARM}" == "1" ] ; then + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_fan_led + # partial fan fail + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_fan_led + fi +} + +#Set Power Supply LED +function _i2c_led_psu_status_set { + echo "PSU LED Status Setup" + + #PSU Status set + _i2c_psu_status + + #PSU1 Status + echo "led_psu1 setup..." + if [ "${psu1Exist}" == ${PSU_EXIST} ]; then + if [ "${psu1PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_psu1_led + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_psu1_led + fi + else + COLOR_LED="off" + echo "${COLOR_LED}" + _i2c_psu1_led + fi + + #PSU2 Status + echo "led_psu2 setup..." + if [ "${psu2Exist}" == ${PSU_EXIST} ]; then + if [ "${psu2PwGood}" == ${PSU_DC_ON} ]; then + COLOR_LED="green" + echo "${COLOR_LED}" + _i2c_psu2_led + else + COLOR_LED="amber" + echo "${COLOR_LED}" + _i2c_psu2_led + fi + else + COLOR_LED="off" + echo "${COLOR_LED}" + _i2c_psu2_led + fi +} + +#LED Test +function _i2c_led_test { + echo "=========================================================" + echo "# Description: I2C SYSTEM LED TEST..." + echo "=========================================================" + local output_reg=${REG_PORT0_OUT} + local mask=0xFF + local value=0xFF + + #sys led (green) + # set sys_led_g (0.7) = 1 + mask=0x80 + value=0x80 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check SYS LED green light and Press [Enter] key to continue...' + #sys led (amber) + # set sys_led_g (0.7) = 0 + mask=0x80 + value=0x00 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check SYS LED amber light and Press [Enter] key to continue...' + + #FAN led (green) + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 0 + mask=0x60 + value=0x60 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check FAN LED green light and Press [Enter] key to continue...' + #FAN led (amber) + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 1 + mask=0x60 + value=0x40 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check FAN LED amber light and Press [Enter] key to continue...' + + #PSU1 led (green) + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 0 + mask=0x18 + value=0x18 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU1 LED green light and Press [Enter] key to continue...' + #PSU1 led (amber) + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 1 + mask=0x18 + value=0x10 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU1 LED amber light and Press [Enter] key to continue...' + + #PSU2 led (green) + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 0 + mask=0x06 + value=0x06 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU2 LED green light and Press [Enter] key to continue...' + #PSU2 led (amber) + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 1 + mask=0x06 + value=0x04 + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check PSU2 LED amber light and Press [Enter] key to continue...' + + #Turn OFF All LED (can't trun off system led) + # set set fan_led_en (0.6), psu1_pwr_ok_oe (0.4), psu0_pwr_ok_oe (0.2) = 0 + mask=0xFF + value=$((2#00000011)) + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + _pause 'Check turn off all LEDs (exclude SYS LED) and Press [Enter] key to continue...' + + # restore sys led + COLOR_LED="green" + ONOFF_LED="on" + echo "${COLOR_LED} ${ONOFF_LED}" + _i2c_sys_led +} + +#Set QSFP Port cpld variable +function _qsfp_cpld_var_set { + local port=$1 + local reg_port_base + local reg_port_shift + if [[ $1 -le 12 && $1 -ge 1 ]]; then + cpld_index=1 + reg_port_base=0 + elif [[ $1 -le 25 && $1 -ge 13 ]]; then + cpld_index=2 + reg_port_base=12 + elif [[ $1 -le 38 && $1 -ge 26 ]]; then + cpld_index=3 + reg_port_base=25 + elif [[ $1 -le 51 && $1 -ge 39 ]]; then + cpld_index=4 + reg_port_base=38 + elif [[ $1 -le 64 && $1 -ge 52 ]]; then + cpld_index=5 + reg_port_base=51 + else + echo "invalid port number" + fi + + cpld_port_index=$(( $port - $reg_port_base )) +} + +#Set QSFP Port eeporm variable +function _qsfp_eeprom_var_set { + local port=$1 + local eeprombusbase + local eeprombusshift + # port 1 => zqsfp0 + # port 2 => zqsfp1 + # ... + local port_group=$(( ($port - 1) / 8 )) + + case ${port_group} in + 0) + eeprombusbase=${NUM_MUX_9548_3_CH0} + ;; + 1) + eeprombusbase=${NUM_MUX_9548_4_CH0} + ;; + 2) + eeprombusbase=${NUM_MUX_9548_5_CH0} + ;; + 3) + eeprombusbase=${NUM_MUX_9548_6_CH0} + ;; + 4) + eeprombusbase=${NUM_MUX_9548_7_CH0} + ;; + 5) + eeprombusbase=${NUM_MUX_9548_8_CH0} + ;; + 6) + eeprombusbase=${NUM_MUX_9548_9_CH0} + ;; + 7) + eeprombusbase=${NUM_MUX_9548_10_CH0} + ;; + *) + ;; + esac + + eeprombusshift=$(( (${port} - 1) % 8)) + eepromBus=$(( ${eeprombusbase} + ${eeprombusshift} )) + eepromAddr=${I2C_ADDR_QSFP_EEPROM} +} + + +#Set SFP Port cpld variable +function _sfp_cpld_var_set { + local port=$1 + case ${port} in + 1) + cpld_index=1 + ;; + 2) + cpld_index=2 + ;; + *) + ;; + esac +} + +#Set QSFP Port eeporm variable +function _sfp_eeprom_var_set { + local port=$1 + + case ${port} in + 1) + eepromBus=${NUM_MUX_9546_1_CH0} + ;; + 2) + eepromBus=${NUM_MUX_9546_1_CH1} + ;; + *) + ;; + esac + + eepromAddr=${I2C_ADDR_SFP_EEPROM} +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + local phy_port=0 + + #get physical port + phy_port=$(_port_logic2phy $QSFP_PORT) + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + _qsfp_eeprom_var_set ${phy_port} + + _util_get_qsfp_abs + + if [ $status = 0 ]; then + exit + fi + + + cat ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-64 ports EEPROM + local i + for i in {1..64}; + do + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/delete_device + fi + done + echo "Done" +} + +#Get SFP EEPROM Information +function _i2c_sfp_eeprom_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + _util_get_sfp_pres + + if [ $status = 0 ]; then + exit + fi + + _sfp_eeprom_var_set ${SFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init SFP EEPROM +function _i2c_sfp_eeprom_init { + echo "SFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-2 sfp+ EEPROM + local i + for i in {1..2}; + do + _sfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eepromBus/delete_device + fi + done + echo "Done" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init mb EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_MB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM) ]; then + echo "$I2C_ADDR_MB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_MB_EEPROM}/delete_device + fi + echo "Done" +} + +#Init CPU Board EEPROM +function _i2c_cb_eeprom_init { + echo -n "CPU Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init cpu EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "mb_eeprom ${I2C_ADDR_CB_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM) ]; then + echo "$I2C_ADDR_CB_EEPROM" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_CB_EEPROM}/delete_device + fi + echo "Done" +} + +#Init PSU Kernel Module +function _i2c_psu_init { + echo "=========================================================" + echo "# Description: I2C PSU Init" + echo "=========================================================" + modprobe ingrasys_s9230_64x_psu + + echo "psu1 ${I2C_ADDR_PSU1_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/new_device + echo "psu2 ${I2C_ADDR_PSU2_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/new_device +} + +#Deinit PSU Kernel Module +function _i2c_psu_deinit { + echo "${I2C_ADDR_PSU1_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU1_EEPROM}/delete_device + echo "${I2C_ADDR_PSU2_EEPROM}" > ${PATH_SYS_I2C_DEVICES}/i2c-${I2C_BUS_PSU2_EEPROM}/delete_device + _util_rmmod ingrasys_s9230_64x_psu +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + local stat + _util_get_qsfp_abs + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + local phy_port=0 + + phy_port=$(_port_logic2phy ${QSFP_PORT}) + + # input parameter validation + _util_input_check "${QSFP_PORT}" "${MIN_QSFP_PORT_NUM}" "${MAX_QSFP_PORT_NUM}" + + #_qsfp_eeprom_var_set ${QSFP_PORT} + _qsfp_eeprom_var_set ${phy_port} + + #Get QSFP EEPROM info + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +function _i2c_sfp_status_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + + local stat + _util_get_sfp_pres + #status: 0 -> Down, 1 -> Up + if [ $status = 0 ]; then + stat="down" + else + stat="up" + fi + echo "status is $stat" +} + +#get SFP Type +function _i2c_sfp_type_get { + + # input parameter validation + _util_input_check "${SFP_PORT}" "${MIN_SFP_PORT_NUM}" "${MAX_SFP_PORT_NUM}" + + _sfp_eeprom_var_set ${SFP_PORT} + + #Get QSFP EEPROM info + sfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eepromBus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $sfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $sfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $sfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + local eeprom_psu1="" + local eeprom_psu2="" + + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + eeprom_psu1="${PATH_SYSFS_PSU1}/psu_eeprom" + cat ${eeprom_psu1} | hexdump -C + + eeprom_psu2="${PATH_SYSFS_PSU2}/psu_eeprom" + cat ${eeprom_psu2} | hexdump -C +} + +#Get Main Board EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get mb +} + +#Get CPU Board EEPROM Information +function _i2c_cb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C CB EEPROM Get..." + echo "=========================================================" + _i2c_sys_eeprom_get cb +} + +#Get system EEPROM Information +##input: "cb" for cpu board, "mb" for main board +function _i2c_sys_eeprom_get { + local eeprom_dev + + if [ "$1" == "cb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + elif [ "$1" == "mb" ]; then + eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + else + echo "wrong eeprom type" + return + fi + + # check if eeprom device exist in sysfs + if [ ! -f ${eeprom_dev} ]; then + echo "eeprom device not init" + return + fi + + cat ${eeprom_dev} | hexdump -C + echo "Done" +} + +#sync eeprom content between mb and cb eeprom +function _i2c_eeprom_sync { + echo "=========================================================" + echo "# Description: EEPROM sync..." + echo "=========================================================" + + local mb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_MB_EEPROM}-$(printf "%04x" $I2C_ADDR_MB_EEPROM)/eeprom" + local cb_eeprom_dev="${PATH_SYS_I2C_DEVICES}/${I2C_BUS_CB_EEPROM}-$(printf "%04x" $I2C_ADDR_CB_EEPROM)/eeprom" + + # check if eeprom device exist in sysfs + if [[ ! -f ${mb_eeprom_dev} || ! -f ${cb_eeprom_dev} ]]; then + echo "eeprom device not init" + return + fi + + ## check if MB eeprom is empty + if [ ! -z "$(cat ${mb_eeprom_dev} | hexdump -n2 | grep ffff)" ]; then + echo "copy cb eeprom to mb eeprom..." + cat ${cb_eeprom_dev} > ${mb_eeprom_dev} + else + echo "no need to sync" + fi + + echo "Done" +} + +#Set System Status LED +function _i2c_sys_led { + # only green/amber, on/off can't control + if [ "${COLOR_LED}" == "green" ]; then + # set sys_led_g (0.7) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x80 + elif [ "${COLOR_LED}" == "amber" ]; then + # set sys_led_g (0.7) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x80 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_LED}" == "green" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x60 + elif [ "${COLOR_LED}" == "amber" ]; then + # set fan_led_en (0.6) = 1 & fan_led_y (0.5) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x40 + elif [ "${COLOR_LED}" == "off" ]; then + # set fan_led_en (0.6) = 0 & fan_led_y (0.5) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x60 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU1 LED +function _i2c_psu1_led { + if [ "${COLOR_LED}" == "green" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x18 + elif [ "${COLOR_LED}" == "amber" ]; then + # set psu1_pwr_ok_oe (0.4) = 1 & psu1_led_y (0.3) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x10 + elif [ "${COLOR_LED}" == "off" ]; then + # set psu1_pwr_ok_oe (0.4) = 0 & psu1_led_y (0.3) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x18 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set PSU2 LED +function _i2c_psu2_led { + if [ "${COLOR_LED}" == "green" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x06 + elif [ "${COLOR_LED}" == "amber" ]; then + # set psu0_pwr_ok_oe (0.2) = 1 & psu0_led_y (0.1) = 1 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x04 + elif [ "${COLOR_LED}" == "off" ]; then + # set psu0_pwr_ok_oe (0.2) = 0 & psu0_led_y (0.1) = 0 + output_reg=${REG_PORT0_OUT} + mask=0x06 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + _util_i2cset -m ${mask} -y ${I2C_BUS_SYS_LED} ${I2C_ADDR_MUX_9539_0} ${output_reg} ${value} + echo "Done" +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + + i2cAddr=${I2C_ADDR_MUX_9555_0} + output_reg=${REG_PORT0_OUT} + + case ${FAN_TRAY} in + 1) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + output_reg=${REG_PORT0_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + output_reg=${REG_PORT1_OUT} + if [ "${COLOR_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + # LED PIN value is ACTIVE HIGH + if [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0xff + elif [ "${COLOR_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0xff + elif [ "${COLOR_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + _util_i2cset -m $mask -y -r ${I2C_BUS_FANTRAY_LED} $i2cAddr ${output_reg} 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "Done" +} + +#Get Board Version and Type +function _i2c_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_HW_ID} ${I2C_ADDR_MUX_9539_0} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "MAIN_BOARD BOARD_ID is 0x%02x, HW Rev 0x%02x, Build Rev 0x%02x\n" $boardId $boardHwRev $boardBuildRev +} + +#Get BMC Board Version and Type +function _i2c_bmc_board_type_get { + # read input port 1 value from io expander + input_reg=${REG_PORT1_IN} + boardType=`i2cget -y ${I2C_BUS_BMC_HW_ID} ${I2C_ADDR_MUX_9555_1} ${input_reg}` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BMC_BOARD BOARD_ID is 0x%02x, HW Rev 0x%02x, Build Rev 0x%02x\n" $boardId $boardHwRev $boardBuildRev +} + +#Get CPLD Version +function _i2c_cpld_version { + echo "=========================================================" + echo "# Description: CPLD Version" + echo "=========================================================" + + for i in {1..5}; + do + local cpld_bus="I2C_BUS_CPLD${i}" + local cpld_path="PATH_CPLD${i}_DEVICE" + local file_path="${PATH_SYS_I2C_DEVICES}/${!cpld_bus}-$(printf "%04x" ${I2C_ADDR_CPLD})/cpld_version" + printf "[CPLD %d] %s\n" ${i} $(cat ${file_path}) + done +} + +#Get PSU Status +function _i2c_psu_status { + local psu_abs="" + + psu1PwGood=`cat ${PATH_SYSFS_PSU1}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU1}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu1Exist=1 + else + psu1Exist=0 + fi + + psu2PwGood=`cat ${PATH_SYSFS_PSU2}/psu_pg` + psu_abs=`cat ${PATH_SYSFS_PSU2}/psu_abs` + if [ "$psu_abs" == "0" ]; then + psu2Exist=1 + else + psu2Exist=0 + fi + + printf "PSU1 Exist:%x PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + +#Get register value from CPLD +function _i2c_cpld_reg_read { + local idx=$1 + local file_name=$2 + local cpld_i2c_addr=${I2C_ADDR_CPLD} + local reg_file_path + + case ${idx} in + 1) + cpld_i2c_bus=${I2C_BUS_CPLD1} + ;; + 2) + cpld_i2c_bus=${I2C_BUS_CPLD2} + ;; + 3) + cpld_i2c_bus=${I2C_BUS_CPLD3} + ;; + 4) + cpld_i2c_bus=${I2C_BUS_CPLD4} + ;; + 5) + cpld_i2c_bus=${I2C_BUS_CPLD5} + ;; + *) + echo "invalid cpld index" + exit + ;; + esac + + reg_file_path="${PATH_SYS_I2C_DEVICES}/${cpld_i2c_bus}-$(printf "%04x" ${cpld_i2c_addr})/${file_name}" + cpld_reg_val=`cat ${reg_file_path}` +} + +#util functions +function _util_i2cset { + if [ "$DEBUG" == "on" ]; then + i2cset $@ + else + i2cset $@ 1>/dev/null + fi +} + +function _i2c_set { + local i2c_bus=$1 + local i2c_addr=$2 + local reg=$3 + local mask=$4 + local value=$5 + + echo `i2cset -m $mask -y -r ${i2c_bus} ${i2c_addr} ${reg} ${value}` +} + +function _util_rmmod { + local mod=$1 + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod +} + +# get qsfp presence +function _util_get_qsfp_abs { + local phy_port=0 + + #get physical port + phy_port=$(_port_logic2phy $QSFP_PORT) + + # read status from cpld + #_qsfp_cpld_var_set ${QSFP_PORT} + _qsfp_cpld_var_set ${phy_port} + cpld_reg_file_name="${CPLD_QSFP_STATUS_KEY}_${cpld_port_index}" + _i2c_cpld_reg_read ${cpld_index} ${cpld_reg_file_name} + #status: 0 -> Down, 1 -> Up (ACTIVE_LOW in ABS_BIT) + status=$(( $(( $((${cpld_reg_val})) & (1 << ($CPLD_QSFP_STATUS_ABS_BIT)) ))?0:1 )) +} + +# get sfp presence +function _util_get_sfp_pres { + + # read status from cpld + _sfp_cpld_var_set ${SFP_PORT} + cpld_reg_file_name="${CPLD_SFP_STATUS_KEY}" + _i2c_cpld_reg_read ${cpld_index} ${cpld_reg_file_name} + #status: 0 -> Down, 1 -> Up (ACTIVE_LOW in PRES_BIT) + status=$(( $(( $((${cpld_reg_val})) & (1 << ($CPLD_SFP_STATUS_PRES_BIT)) ))?0:1 )) +} + +# valid input number +function _util_input_check { + # input parameter validation + if [[ $1 -lt $2 || $1 -gt $3 ]]; then + echo "Please input number $2~$3" + exit + fi +} + +# clear all switch port led bitmap +function _util_port_led_clear { + echo "port led clear..." + # gpio pin on GPIO MUX PCA9539#1 I/O 0.2 + # pull low to reset bitamp + output_reg=${REG_PORT0_OUT} + mask=0x04 + value=0x00 + _util_i2cset -m ${mask} -y ${NUM_MUX_9548_1_CH2} ${I2C_ADDR_MUX_9539_1} ${output_reg} ${value} + echo "Done" +} + +#Increase read socket buffer for CoPP Test +function _config_rmem { + echo "109430400" > /proc/sys/net/core/rmem_max +} + +#Set 10G Mux to CPU or Front Panel +function _i2c_10g_mux { + + echo "=========================================================" + echo "# Description: 10G Mux" + echo "=========================================================" + + local target=${TARGET_10G_MUX} + local i2c_bus=${I2C_BUS_10GMUX} + local i2c_addr=${I2C_ADDR_10GMUX} + local reg=0 + local mask=0xff + local value=0 + local file_10g_mux="${PATH_CPLD1_DEVICE}/${I2C_BUS_CPLD1}-$(printf "%04x" ${I2C_ADDR_CPLD})/cpld_10gmux_config" + + #get current 10g mux register value on CPLD + value=`cat ${file_10g_mux}` + + if [ "${target}" == "cpu" ]; then + #Set XE0: slave address access + _i2c_set $i2c_bus $i2c_addr 0x06 $mask 0x18 + #Set XE0: CH4 D_IN0-S_OUTA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x2c $mask 0x00 + #Set XE0: CH5 NC-S_OUTB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x35 $mask 0x80 + #Set XE0: CH5 NC-S_OUTB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x34 $mask 0xab + #Set XE0: CH1 D_OUT0-S_INB0 EQ + _i2c_set $i2c_bus $i2c_addr 0x16 $mask 0x01 + #Set XE0: CH1 D_OUT0-S_INB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x18 0x1f 0x80 + #Set XE0: CH1 D_OUT0-S_INB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x17 $mask 0xab + #Set XE1: CH6 D_IN1-S_OUTA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x3a $mask 0x00 + #Set XE1: CH7 NC-S_OUTB1 EQ + _i2c_set $i2c_bus $i2c_addr 0x41 $mask 0x00 + #Set XE1: CH7 NC-S_OUTB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x43 $mask 0x80 + #Set XE1: CH7 NC-S_OUTB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x42 $mask 0xab + #Set XE1: CH3 D_OUT1-S_INB1 EQ + _i2c_set $i2c_bus $i2c_addr 0x24 $mask 0x01 + #Set XE1: CH3 D_OUT1-S_INB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x26 $mask 0x80 + #Set XE1: CH3 D_OUT1-S_INB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x25 $mask 0xab + #Enable auto negotiation of XE ports + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x11 data=0x80'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x10 data=0x01'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x0 data=0x3200'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x1 addr=0x96 data=0x2'" + #delay 1 sec + sleep 1 + + #switch 10G MUX to cpu on CPLD + value=$(( value & 0xf3 )) + echo "$(printf 0x"%x" ${value})" > ${file_10g_mux} + + echo "Switch 10G Mux to [CPU]" + + elif [ "${COLOR_LED}" == "fp" ]; then + #Set XE0: slave address access + _i2c_set $i2c_bus $i2c_addr 0x06 $mask 0x18 + #Set XE0: CH4 D_IN0-S_OUTA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x2c $mask 0x00 + #Set XE0: CH4 D_IN0-S_OUTA0 DEM + _i2c_set $i2c_bus $i2c_addr 0x2e $mask 0x80 + #Set XE0: CH4 D_IN0-S_OUTA0 VOD + _i2c_set $i2c_bus $i2c_addr 0x2d $mask 0xab + #Set XE0: CH0 NC-S_INA0 EQ + _i2c_set $i2c_bus $i2c_addr 0x0f $mask 0x00 + #Set XE0: CH1 D_OUT0-S_INB0 DEM + _i2c_set $i2c_bus $i2c_addr 0x18 0x18 0x80 + #Set XE0: CH1 D_OUT0-S_INB0 VOD + _i2c_set $i2c_bus $i2c_addr 0x17 $mask 0xab + #Set XE1: CH6 D_IN1-S_OUTA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x3a $mask 0x00 + #Set XE1: CH6 D_IN1-S_OUTA1 DEM + _i2c_set $i2c_bus $i2c_addr 0x3c $mask 0x80 + #Set XE1: CH6 D_IN1-S_OUTA1 VOD + _i2c_set $i2c_bus $i2c_addr 0x3b $mask 0xab + #Set XE1: CH2 NC-S_INA1 EQ + _i2c_set $i2c_bus $i2c_addr 0x1d $mask 0x00 + #Set XE1: CH3 D_OUT1-S_INB1 DEM + _i2c_set $i2c_bus $i2c_addr 0x26 $mask 0x80 + #Set XE1: CH3 D_OUT1-S_INB1 VOD + _i2c_set $i2c_bus $i2c_addr 0x25 $mask 0xab + #Enable auto negotiation of XE ports + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x11 data=0x0'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x10 data=0x0'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x7 addr=0x0 data=0x2200'" + eval "npx_diag 'phy set mdio portlist=129,130 devad=0x1 addr=0x96 data=0x2200'" + #delay 1 sec + sleep 1 + + #switch 10G MUX to front panel on CPLD + value=$(( value | 0x0c )) + echo "$(printf 0x"%x" ${value})" > ${file_10g_mux} + + echo "Switch 10G Mux to [Front Panel]" + else + echo "invalid target, please set target to cpu/fp" + fi +} + +#Main Function +function _main { + tart_time_str=`date` + start_time_sec=$(date +%s) + + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_fan_speed_init" ]; then + _i2c_fan_speed_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_led_test" ]; then + _i2c_led_test + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_get" ]; then + _i2c_cb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_eeprom_sync" ]; then + _i2c_eeprom_sync + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_get" ]; then + _i2c_sfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_init" ]; then + _i2c_sfp_eeprom_init ${SFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_cb_eeprom_init" ]; then + _i2c_cb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_status_get" ]; then + _i2c_sfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_sfp_type_get" ]; then + _i2c_sfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_psu_status_set" ]; then + _i2c_led_psu_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_psu1_led" ]; then + _i2c_psu1_led + elif [ "${EXEC_FUNC}" == "i2c_psu2_led" ]; then + _i2c_psu2_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_bmc_board_type_get" ]; then + _i2c_bmc_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_led_test + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cb_eeprom_get + _i2c_board_type_get + _i2c_bmc_board_type_get + _i2c_cpld_version + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_10g_mux" ]; then + _i2c_10g_mux + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + if [ "$DEBUG" == "on" ]; then + echo "-----------------------------------------------------" + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" + fi +} + +_main diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/qsfp_monitor.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/qsfp_monitor.sh new file mode 100755 index 000000000000..9213d115f656 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/qsfp_monitor.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..63}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`sonic-db-cli ASIC_DB HLEN HIDDEN` + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/s9230_64x_monitor.sh b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/s9230_64x_monitor.sh new file mode 100755 index 000000000000..8bfb22328003 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-ingrasys/s9230-64x/utils/s9230_64x_monitor.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_psu_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + _led_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main diff --git a/platform/nephos/sonic-platform-modules-pegatron/LICENSE b/platform/nephos/sonic-platform-modules-pegatron/LICENSE new file mode 100644 index 000000000000..a23cc2b232cd --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/LICENSE @@ -0,0 +1,16 @@ +Copyright (C) 2016 Microsoft, Inc +Copyright (C) 2018 Pegatron Corporation. + +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. + +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 Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/nephos/sonic-platform-modules-pegatron/README.md b/platform/nephos/sonic-platform-modules-pegatron/README.md new file mode 100644 index 000000000000..32444b4b8916 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/README.md @@ -0,0 +1 @@ +platform drivers of Pegatron products for the SONiC project diff --git a/platform/nephos/sonic-platform-modules-pegatron/common/modules/pegatron_hwmon_mcu.c b/platform/nephos/sonic-platform-modules-pegatron/common/modules/pegatron_hwmon_mcu.c new file mode 100644 index 000000000000..76cbd8844708 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/common/modules/pegatron_hwmon_mcu.c @@ -0,0 +1,1374 @@ +/* + * A MCU driver connect to hwmon + * + * Copyright (C) 2018 Pegatron Corporation. + * Peter5_Lin + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef pega_DEBUG +/*#define pega_DEBUG*/ +#ifdef pega_DEBUG +#define DBG(x) x +#else +#define DBG(x) +#endif /* DEBUG */ + +#define FW_UPGRADE_COMMAND 0xA5 +#define FAN_DISABLE_COMMAND 0x20 +#define FAN_ENABLE_COMMAND 0x21 +#define FAN_LED_SETTO_MANUAL_COMMAND 0x30 +#define FAN_LED_SETTO_AUTO_COMMAND 0x31 +#define FAN_LED_GREENON_COMMAND 0x40 +#define FAN_LED_GREENOFF_COMMAND 0x41 +#define FAN_LED_AMBERON_COMMAND 0x50 +#define FAN_LED_AMBEROFF_COMMAND 0x51 +#define SMART_FAN_ENABLE_BIT 0 +#define SMART_FAN_SETTING_ENABLE_BIT 0 +#define SA56004X_REMOTE_TEMP_ALERT_BIT 4 +#define I2C_FANBOARD_TIMEOUT_BIT 0 +#define ALERT_MODE_BIT 0 +#define GET_BIT(data, bit, value) value = (data >> bit) & 0x1 +#define SET_BIT(data, bit) data |= (1 << bit) +#define CLEAR_BIT(data, bit) data &= ~(1 << bit) + +enum chips +{ + mercedes3 = 0, + cadillac, + porsche, +}; + +enum fan_alert +{ + FAN_OUTER_RPM_OVER_ALERT_BIT = 0, + FAN_OUTER_RPM_UNDER_ALERT_BIT, + FAN_INNER_RPM_OVER_ALERT_BIT, + FAN_INNER_RPM_UNDER_ALERT_BIT, + FAN_CONNECT_ALERT_BIT, + FAN_DISCONNECT_ALERT_BIT, +}; + +enum fan_status +{ + FAN_ALERT_BIT = 2, + FAN_LED_AMBER_BIT, + FAN_LED_GREEN_BIT, + FAN_LED_AUTO_BIT, + FAN_ENABLE_BIT, + FAN_PRESENT_BIT, +}; + +enum hwmon_mcu_register +{ + MB_FW_UG_REG = 0, + FB_FW_UG_REG, + MB_HW_VER_REG, + FB_HW_SKUVER_REG, + MB_FW_VER_REG, + FB_FW_VER_REG, + + FAN_PWM_REG = 16, + + SF_ENABLE_REG, + SF_SETTING_ENABLE_REG, + SF_DEVICE_REG, + SF_UPDATE_REG, + SF_TEMP_MAX_REG, + SF_TEMP_MID_REG, + SF_TEMP_MIN_REG, + SF_PWM_MAX_REG, + SF_PWM_MID_REG, + SF_PWM_MIN_REG, + + FAN1_INNER_RPM_REG = 32, + FAN2_INNER_RPM_REG, + FAN3_INNER_RPM_REG, + FAN4_INNER_RPM_REG, + FAN5_INNER_RPM_REG, + + FAN1_OUTER_RPM_REG = 48, + FAN2_OUTER_RPM_REG, + FAN3_OUTER_RPM_REG, + FAN4_OUTER_RPM_REG, + FAN5_OUTER_RPM_REG, + + FAN1_STATUS_REG = 64, + FAN2_STATUS_REG, + FAN3_STATUS_REG, + FAN4_STATUS_REG, + FAN5_STATUS_REG, + + ADC_UNDER_VOL_ALERT_REG = 80, + ADC_OVER_VOL_ALERT_REG, + TS_OVER_TEMP_ALERT_REG, + + FAN1_ALERT_REG, + FAN2_ALERT_REG, + FAN3_ALERT_REG, + FAN4_ALERT_REG, + FAN5_ALERT_REG, + + I2C_BUS_ALERT_REG, + ALERT_MODE_REG, + + MONITOR_ADC_VOLTAGE_REG = 96, + + LM_0X49_TEMP_REG = 112, + LM_0X48_TEMP_REG, + SA56004X_LOCAL_TEMP_REG, + SA56004X_REMOTE_TEMP_REG, + +}; + +static struct mutex pega_hwmon_mcu_lock; + +static int pega_hwmon_mcu_read(struct i2c_client *client, u8 reg) +{ + int data = -EPERM; + + mutex_lock(&pega_hwmon_mcu_lock); + + data = i2c_smbus_read_word_data(client, reg); + + mutex_unlock(&pega_hwmon_mcu_lock); + + return data; +} + +static int pega_hwmon_mcu_write(struct i2c_client *client, u8 reg, u8 val) +{ + int ret = -EIO; + + mutex_lock(&pega_hwmon_mcu_lock); + + ret = i2c_smbus_write_byte_data(client, reg, val); + + mutex_unlock(&pega_hwmon_mcu_lock); + + return ret; +} + +static ssize_t mainBoardUpgrade(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = MB_FW_UG_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + if(val) + pega_hwmon_mcu_write(client, reg, FW_UPGRADE_COMMAND); + else + pega_hwmon_mcu_write(client, reg, 0xff); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, FW_UPGRADE_COMMAND)); + + return count; +} + +static ssize_t fanBoardUpgrade(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = FB_FW_UG_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + if(val) + pega_hwmon_mcu_write(client, reg, FW_UPGRADE_COMMAND); + else + pega_hwmon_mcu_write(client, reg, 0xff); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, FW_UPGRADE_COMMAND)); + + return count; +} + +static ssize_t get_MB_HW_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = MB_HW_VER_REG; + + data = pega_hwmon_mcu_read(client, reg); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + data &= 0x1f; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t get_FB_HW_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = FB_HW_SKUVER_REG; + + data = pega_hwmon_mcu_read(client, reg); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + data = (data >> 5) & 0x7; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t get_FB_boardId(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = FB_HW_SKUVER_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data &= 0x1f; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t get_MB_FW_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, major_ver = 0, minor_ver = 0; + u8 reg = MB_FW_VER_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + major_ver = (data >> 4) & 0xf; + minor_ver = data & 0xf; + + return sprintf(buf, "%d.%d\n", major_ver, minor_ver); +} + +static ssize_t get_FB_FW_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, major_ver = 0, minor_ver = 0; + u8 reg = FB_FW_VER_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + major_ver = (data >> 4) & 0xf; + minor_ver = data & 0xf; + + return sprintf(buf, "%d.%d\n", major_ver, minor_ver); +} + +static ssize_t get_fan_PWM(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = FAN_PWM_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = FAN_PWM_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = SF_ENABLE_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SMART_FAN_ENABLE_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t set_smartFan_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_ENABLE_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + if(val) + SET_BIT(data, SMART_FAN_ENABLE_BIT); + else + CLEAR_BIT(data, SMART_FAN_ENABLE_BIT); + pega_hwmon_mcu_write(client, reg, data); + + return count; +} + +static ssize_t get_smartFan_setting_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = SF_SETTING_ENABLE_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SMART_FAN_SETTING_ENABLE_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t set_smartFan_setting_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_SETTING_ENABLE_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + if(val) + SET_BIT(data, SMART_FAN_SETTING_ENABLE_BIT); + else + CLEAR_BIT(data, SMART_FAN_SETTING_ENABLE_BIT); + pega_hwmon_mcu_write(client, reg, data); + + return count; +} + +static ssize_t get_smartFan_device(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_DEVICE_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%x\n", data); +} + +static ssize_t set_smartFan_device(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_DEVICE_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_update(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_UPDATE_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_update(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_UPDATE_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_max_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MAX_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_max_temp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MAX_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_mid_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MID_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_mid_temp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_min_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MID_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_min_temp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_TEMP_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_max_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MAX_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_max_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MAX_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_mid_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_mid_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_smartFan_min_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MIN_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_smartFan_min_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MIN_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); + + pega_hwmon_mcu_write(client, reg, val); + + return count; +} + +static ssize_t get_fan_inner_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u16 data = 0; + u8 reg = FAN1_INNER_RPM_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_fan_outer_rpm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u16 data = 0; + u8 reg = FAN1_OUTER_RPM_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t get_fan_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_PRESENT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_ENABLE_BIT, val); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t set_fan_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + + if(val) + pega_hwmon_mcu_write(client, reg, FAN_ENABLE_COMMAND); + else + pega_hwmon_mcu_write(client, reg, FAN_DISABLE_COMMAND); + + return count; +} + +static ssize_t get_fan_led_auto(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_LED_AUTO_BIT, val); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t set_fan_led_auto(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + + if(val) + pega_hwmon_mcu_write(client, reg, FAN_LED_SETTO_AUTO_COMMAND); + else + pega_hwmon_mcu_write(client, reg, FAN_LED_SETTO_MANUAL_COMMAND); + + return count; +} + +static ssize_t get_fan_led_green(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_LED_GREEN_BIT, val); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t set_fan_led_green(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + + if(val) + pega_hwmon_mcu_write(client, reg, FAN_LED_GREENON_COMMAND); + else + pega_hwmon_mcu_write(client, reg, FAN_LED_GREENOFF_COMMAND); + + return count; +} + +static ssize_t get_fan_led_amber(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_LED_AMBER_BIT, val); + + return sprintf(buf, "%d\n", val); +} + + +static ssize_t set_fan_led_amber(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = SF_PWM_MID_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + + if(val) + pega_hwmon_mcu_write(client, reg, FAN_LED_AMBERON_COMMAND); + else + pega_hwmon_mcu_write(client, reg, FAN_LED_AMBEROFF_COMMAND); + + return count; +} + +static ssize_t get_fan_status_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_STATUS_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_adc_under_vol_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = ADC_UNDER_VOL_ALERT_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, attr->index, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_adc_over_vol_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = ADC_OVER_VOL_ALERT_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, attr->index, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_temp_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = TS_OVER_TEMP_ALERT_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SA56004X_REMOTE_TEMP_ALERT_BIT + attr->index, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_outerRPMOver_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_OUTER_RPM_OVER_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_outerRPMUnder_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_OUTER_RPM_UNDER_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_innerRPMOver_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_INNER_RPM_OVER_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_innerRPMUnder_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_INNER_RPM_UNDER_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_connect_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_CONNECT_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_fan_disconnect_alert(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = FAN1_ALERT_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, FAN_DISCONNECT_ALERT_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_i2c_timeout(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = I2C_BUS_ALERT_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, I2C_FANBOARD_TIMEOUT_BIT + attr->index, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_alert_mode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0; + u8 reg = ALERT_MODE_REG; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, ALERT_MODE_BIT, val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t set_alert_mode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = ALERT_MODE_REG; + long val = 0; + + if (kstrtol(buf, 10, &val)) + { + return -EINVAL; + } + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); + + if(val) + SET_BIT(data, ALERT_MODE_BIT); + else + CLEAR_BIT(data, ALERT_MODE_BIT); + pega_hwmon_mcu_write(client, reg, data); + + return count; +} + +static ssize_t get_adc_vol(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u16 data = 0, reg = MONITOR_ADC_VOLTAGE_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d.%02d\n", data/1000, (data/10)%12); +} + +static ssize_t get_hwmon_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0; + u8 reg = LM_0X49_TEMP_REG + attr->index; + + data = pega_hwmon_mcu_read(client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%d\n", data); +} +#define SET_FAN_ATTR(_num) \ + static SENSOR_DEVICE_ATTR(fan##_num##_inner_rpm, S_IRUGO, get_fan_inner_rpm, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_outer_rpm, S_IRUGO, get_fan_outer_rpm, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_present, S_IRUGO, get_fan_present, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_enable, S_IRUGO | S_IWUSR, get_fan_enable, set_fan_enable, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_led_auto, S_IRUGO | S_IWUSR, get_fan_led_auto, set_fan_led_auto, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_led_green, S_IRUGO | S_IWUSR, get_fan_led_green, set_fan_led_green, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_led_amber, S_IRUGO | S_IWUSR, get_fan_led_amber, set_fan_led_amber, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_status_alert, S_IRUGO, get_fan_status_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_outerRPMOver_alert, S_IRUGO, get_fan_outerRPMOver_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_outerRPMUnder_alert, S_IRUGO, get_fan_outerRPMUnder_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_innerRPMOver_alert, S_IRUGO, get_fan_innerRPMOver_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_innerRPMUnder_alert, S_IRUGO, get_fan_innerRPMUnder_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_connect_alert, S_IRUGO, get_fan_connect_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(fan##_num##_disconnect_alert, S_IRUGO, get_fan_disconnect_alert, NULL, _num-1) + +SET_FAN_ATTR(1);SET_FAN_ATTR(2);SET_FAN_ATTR(3);SET_FAN_ATTR(4);SET_FAN_ATTR(5); + +#define SET_ADC_ATTR(_num) \ + static SENSOR_DEVICE_ATTR(ADC##_num##_under_alert, S_IRUGO, get_adc_under_vol_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(ADC##_num##_over_alert, S_IRUGO, get_adc_over_vol_alert, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(ADC##_num##_vol, S_IRUGO, get_adc_vol, NULL, 8-_num) + +SET_ADC_ATTR(1);SET_ADC_ATTR(2);SET_ADC_ATTR(3);SET_ADC_ATTR(4);SET_ADC_ATTR(5);SET_ADC_ATTR(6);SET_ADC_ATTR(7);SET_ADC_ATTR(8); + +static SENSOR_DEVICE_ATTR(mb_fw_upgrade, S_IWUSR, NULL, mainBoardUpgrade, 0); +static SENSOR_DEVICE_ATTR(fb_fw_upgrade, S_IWUSR, NULL, fanBoardUpgrade, 0); +static SENSOR_DEVICE_ATTR(mb_hw_version, S_IRUGO, get_MB_HW_version, NULL, 0); +static SENSOR_DEVICE_ATTR(fb_hw_version, S_IRUGO, get_FB_HW_version, NULL, 0); +static SENSOR_DEVICE_ATTR(fb_board_id, S_IRUGO, get_FB_boardId, NULL, 0); +static SENSOR_DEVICE_ATTR(mb_fw_version, S_IRUGO, get_MB_FW_version, NULL, 0); +static SENSOR_DEVICE_ATTR(fb_fw_version, S_IRUGO, get_FB_FW_version, NULL, 0); +static SENSOR_DEVICE_ATTR(fan_pwm, S_IRUGO | S_IWUSR, get_fan_PWM, set_fan_pwm, 0); + +static SENSOR_DEVICE_ATTR(smartFan_enable, S_IRUGO | S_IWUSR, get_smartFan_enable, set_smartFan_enable, 0); +static SENSOR_DEVICE_ATTR(smartFan_setting_enable, S_IRUGO | S_IWUSR, get_smartFan_setting_enable, set_smartFan_setting_enable, 0); +static SENSOR_DEVICE_ATTR(smartFan_device, S_IRUGO | S_IWUSR, get_smartFan_device, set_smartFan_device, 0); +static SENSOR_DEVICE_ATTR(smartFan_update, S_IRUGO | S_IWUSR, get_smartFan_update, set_smartFan_update, 0); +static SENSOR_DEVICE_ATTR(smartFan_max_temp, S_IRUGO | S_IWUSR, get_smartFan_max_temp, set_smartFan_max_temp, 0); +static SENSOR_DEVICE_ATTR(smartFan_mid_temp, S_IRUGO | S_IWUSR, get_smartFan_mid_temp, set_smartFan_mid_temp, 0); +static SENSOR_DEVICE_ATTR(smartFan_min_temp, S_IRUGO | S_IWUSR, get_smartFan_min_temp, set_smartFan_min_temp, 0); +static SENSOR_DEVICE_ATTR(smartFan_max_pwm, S_IRUGO | S_IWUSR, get_smartFan_max_pwm, set_smartFan_max_pwm, 0); +static SENSOR_DEVICE_ATTR(smartFan_mid_pwm, S_IRUGO | S_IWUSR, get_smartFan_mid_pwm, set_smartFan_mid_pwm, 0); +static SENSOR_DEVICE_ATTR(smartFan_min_pwm, S_IRUGO | S_IWUSR, get_smartFan_min_pwm, set_smartFan_min_pwm, 0); + +static SENSOR_DEVICE_ATTR(lm75_49_temp_alert, S_IRUGO, get_temp_alert, NULL, 3); +static SENSOR_DEVICE_ATTR(lm75_48_temp_alert, S_IRUGO, get_temp_alert, NULL, 2); +static SENSOR_DEVICE_ATTR(SA56004X_Ltemp_alert, S_IRUGO, get_temp_alert, NULL, 1); +static SENSOR_DEVICE_ATTR(SA56004X_Rtemp_alert, S_IRUGO, get_temp_alert, NULL, 0); + +static SENSOR_DEVICE_ATTR(i2c_fb_timeout, S_IRUGO, get_i2c_timeout, NULL, 0); +static SENSOR_DEVICE_ATTR(i2c_remote_timeout, S_IRUGO, get_i2c_timeout, NULL, 1); +static SENSOR_DEVICE_ATTR(i2c_local_timeout, S_IRUGO, get_i2c_timeout, NULL, 2); +static SENSOR_DEVICE_ATTR(i2c_lm75_48_timeout, S_IRUGO, get_i2c_timeout, NULL, 3); +static SENSOR_DEVICE_ATTR(i2c_lm75_49_timeout, S_IRUGO, get_i2c_timeout, NULL, 4); +static SENSOR_DEVICE_ATTR(alert_mode, S_IRUGO | S_IWUSR, get_alert_mode, set_alert_mode, 0); + +static SENSOR_DEVICE_ATTR(lm75_49_temp, S_IRUGO, get_hwmon_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(lm75_48_temp, S_IRUGO, get_hwmon_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(SA56004_local_temp, S_IRUGO, get_hwmon_temp, NULL, 2); +static SENSOR_DEVICE_ATTR(SA56004_remote_temp, S_IRUGO, get_hwmon_temp, NULL, 3); + +static struct attribute *pega_hwmon_mcu_attributes[] = { + &sensor_dev_attr_mb_fw_upgrade.dev_attr.attr, + &sensor_dev_attr_fb_fw_upgrade.dev_attr.attr, + &sensor_dev_attr_mb_hw_version.dev_attr.attr, + &sensor_dev_attr_fb_hw_version.dev_attr.attr, + &sensor_dev_attr_fb_board_id.dev_attr.attr, + &sensor_dev_attr_mb_fw_version.dev_attr.attr, + &sensor_dev_attr_fb_fw_version.dev_attr.attr, + &sensor_dev_attr_fan_pwm.dev_attr.attr, + + &sensor_dev_attr_smartFan_enable.dev_attr.attr, + &sensor_dev_attr_smartFan_setting_enable.dev_attr.attr, + &sensor_dev_attr_smartFan_device.dev_attr.attr, + &sensor_dev_attr_smartFan_update.dev_attr.attr, + &sensor_dev_attr_smartFan_max_temp.dev_attr.attr, + &sensor_dev_attr_smartFan_mid_temp.dev_attr.attr, + &sensor_dev_attr_smartFan_min_temp.dev_attr.attr, + &sensor_dev_attr_smartFan_max_pwm.dev_attr.attr, + &sensor_dev_attr_smartFan_mid_pwm.dev_attr.attr, + &sensor_dev_attr_smartFan_min_pwm.dev_attr.attr, + + &sensor_dev_attr_fan1_inner_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_inner_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_inner_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_inner_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_inner_rpm.dev_attr.attr, + + &sensor_dev_attr_fan1_outer_rpm.dev_attr.attr, + &sensor_dev_attr_fan2_outer_rpm.dev_attr.attr, + &sensor_dev_attr_fan3_outer_rpm.dev_attr.attr, + &sensor_dev_attr_fan4_outer_rpm.dev_attr.attr, + &sensor_dev_attr_fan5_outer_rpm.dev_attr.attr, + + &sensor_dev_attr_fan1_present.dev_attr.attr, + &sensor_dev_attr_fan2_present.dev_attr.attr, + &sensor_dev_attr_fan3_present.dev_attr.attr, + &sensor_dev_attr_fan4_present.dev_attr.attr, + &sensor_dev_attr_fan5_present.dev_attr.attr, + + &sensor_dev_attr_fan1_enable.dev_attr.attr, + &sensor_dev_attr_fan2_enable.dev_attr.attr, + &sensor_dev_attr_fan3_enable.dev_attr.attr, + &sensor_dev_attr_fan4_enable.dev_attr.attr, + &sensor_dev_attr_fan5_enable.dev_attr.attr, + + &sensor_dev_attr_fan1_led_auto.dev_attr.attr, + &sensor_dev_attr_fan2_led_auto.dev_attr.attr, + &sensor_dev_attr_fan3_led_auto.dev_attr.attr, + &sensor_dev_attr_fan4_led_auto.dev_attr.attr, + &sensor_dev_attr_fan5_led_auto.dev_attr.attr, + + &sensor_dev_attr_fan1_led_green.dev_attr.attr, + &sensor_dev_attr_fan2_led_green.dev_attr.attr, + &sensor_dev_attr_fan3_led_green.dev_attr.attr, + &sensor_dev_attr_fan4_led_green.dev_attr.attr, + &sensor_dev_attr_fan5_led_green.dev_attr.attr, + + &sensor_dev_attr_fan1_led_amber.dev_attr.attr, + &sensor_dev_attr_fan2_led_amber.dev_attr.attr, + &sensor_dev_attr_fan3_led_amber.dev_attr.attr, + &sensor_dev_attr_fan4_led_amber.dev_attr.attr, + &sensor_dev_attr_fan5_led_amber.dev_attr.attr, + + &sensor_dev_attr_fan1_status_alert.dev_attr.attr, + &sensor_dev_attr_fan2_status_alert.dev_attr.attr, + &sensor_dev_attr_fan3_status_alert.dev_attr.attr, + &sensor_dev_attr_fan4_status_alert.dev_attr.attr, + &sensor_dev_attr_fan5_status_alert.dev_attr.attr, + + &sensor_dev_attr_ADC1_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC2_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC3_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC4_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC5_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC6_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC7_under_alert.dev_attr.attr, + &sensor_dev_attr_ADC8_under_alert.dev_attr.attr, + + &sensor_dev_attr_ADC1_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC2_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC3_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC4_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC5_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC6_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC7_over_alert.dev_attr.attr, + &sensor_dev_attr_ADC8_over_alert.dev_attr.attr, + + &sensor_dev_attr_lm75_48_temp_alert.dev_attr.attr, + &sensor_dev_attr_lm75_49_temp_alert.dev_attr.attr, + &sensor_dev_attr_SA56004X_Ltemp_alert.dev_attr.attr, + &sensor_dev_attr_SA56004X_Rtemp_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_outerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan2_outerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan3_outerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan4_outerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan5_outerRPMOver_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_outerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan2_outerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan3_outerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan4_outerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan5_outerRPMUnder_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_innerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan2_innerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan3_innerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan4_innerRPMOver_alert.dev_attr.attr, + &sensor_dev_attr_fan5_innerRPMOver_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_innerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan2_innerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan3_innerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan4_innerRPMUnder_alert.dev_attr.attr, + &sensor_dev_attr_fan5_innerRPMUnder_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_connect_alert.dev_attr.attr, + &sensor_dev_attr_fan2_connect_alert.dev_attr.attr, + &sensor_dev_attr_fan3_connect_alert.dev_attr.attr, + &sensor_dev_attr_fan4_connect_alert.dev_attr.attr, + &sensor_dev_attr_fan5_connect_alert.dev_attr.attr, + + &sensor_dev_attr_fan1_disconnect_alert.dev_attr.attr, + &sensor_dev_attr_fan2_disconnect_alert.dev_attr.attr, + &sensor_dev_attr_fan3_disconnect_alert.dev_attr.attr, + &sensor_dev_attr_fan4_disconnect_alert.dev_attr.attr, + &sensor_dev_attr_fan5_disconnect_alert.dev_attr.attr, + + &sensor_dev_attr_i2c_fb_timeout.dev_attr.attr, + &sensor_dev_attr_i2c_remote_timeout.dev_attr.attr, + &sensor_dev_attr_i2c_local_timeout.dev_attr.attr, + &sensor_dev_attr_i2c_lm75_48_timeout.dev_attr.attr, + &sensor_dev_attr_i2c_lm75_49_timeout.dev_attr.attr, + &sensor_dev_attr_alert_mode.dev_attr.attr, + + &sensor_dev_attr_ADC1_vol.dev_attr.attr, + &sensor_dev_attr_ADC2_vol.dev_attr.attr, + &sensor_dev_attr_ADC3_vol.dev_attr.attr, + &sensor_dev_attr_ADC4_vol.dev_attr.attr, + &sensor_dev_attr_ADC5_vol.dev_attr.attr, + &sensor_dev_attr_ADC6_vol.dev_attr.attr, + &sensor_dev_attr_ADC7_vol.dev_attr.attr, + &sensor_dev_attr_ADC8_vol.dev_attr.attr, + + &sensor_dev_attr_lm75_49_temp.dev_attr.attr, + &sensor_dev_attr_lm75_48_temp.dev_attr.attr, + &sensor_dev_attr_SA56004_local_temp.dev_attr.attr, + &sensor_dev_attr_SA56004_remote_temp.dev_attr.attr, + + NULL +}; + +static const struct attribute_group pega_hwmon_mcu_group = { .attrs = pega_hwmon_mcu_attributes}; + +static int pega_hwmon_mcu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + status = sysfs_create_group(&client->dev.kobj, &pega_hwmon_mcu_group); + + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + + return 0; + +exit: + return status; +} + +static int pega_hwmon_mcu_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &pega_hwmon_mcu_group); + return 0; +} + +static const struct i2c_device_id pega_hwmon_mcu_id[] = { + { "porsche_hwmon_mcu", porsche }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pega_hwmon_mcu_id); + +static struct i2c_driver pega_hwmon_mcu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "pegatron_hwmon_mcu", + }, + .probe = pega_hwmon_mcu_probe, + .remove = pega_hwmon_mcu_remove, + .id_table = pega_hwmon_mcu_id, +}; + +static int __init pega_hwmon_mcu_init(void) +{ + mutex_init(&pega_hwmon_mcu_lock); + + return i2c_add_driver(&pega_hwmon_mcu_driver); +} + +static void __exit pega_hwmon_mcu_exit(void) +{ + i2c_del_driver(&pega_hwmon_mcu_driver); +} + +MODULE_AUTHOR("Peter5 Lin "); +MODULE_DESCRIPTION("pega_hwmon_mcu driver"); +MODULE_LICENSE("GPL"); + +module_init(pega_hwmon_mcu_init); +module_exit(pega_hwmon_mcu_exit); \ No newline at end of file diff --git a/platform/nephos/sonic-platform-modules-pegatron/debian/changelog b/platform/nephos/sonic-platform-modules-pegatron/debian/changelog new file mode 100644 index 000000000000..39ecd34d960c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/debian/changelog @@ -0,0 +1,5 @@ +sonic-pegatron-platform-modules (0.1) unstable; urgency=low + + * Initial release + + -- Pegatron Mon, 12 Mar 2018 15:22:37 +0800 diff --git a/platform/nephos/sonic-platform-modules-pegatron/debian/compat b/platform/nephos/sonic-platform-modules-pegatron/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/nephos/sonic-platform-modules-pegatron/debian/control b/platform/nephos/sonic-platform-modules-pegatron/debian/control new file mode 100755 index 000000000000..8fc19980fc12 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/debian/control @@ -0,0 +1,12 @@ +Source: sonic-pegatron-platform-modules +Section: main +Priority: extra +Maintainer: Pegatron +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-pegatron-porsche +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/nephos/sonic-platform-modules-pegatron/debian/rules b/platform/nephos/sonic-platform-modules-pegatron/debian/rules new file mode 100755 index 000000000000..472ec939a47c --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/debian/rules @@ -0,0 +1,88 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-pegatron +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= porsche +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +SCRIPTS_DIR := scripts +CONF_DIR := conf + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + #$(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/usr/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SCRIPTS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/bin/; \ + #$(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/Makefile b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/Makefile new file mode 100644 index 000000000000..60e882a586d9 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/Makefile @@ -0,0 +1 @@ +obj-m:=pegatron_porsche_cpld.o pegatron_hwmon_mcu.o pegatron_porsche_sfp.o diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_hwmon_mcu.c b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_hwmon_mcu.c new file mode 120000 index 000000000000..1357104478a3 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_hwmon_mcu.c @@ -0,0 +1 @@ +../../common/modules/pegatron_hwmon_mcu.c \ No newline at end of file diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_cpld.c b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_cpld.c new file mode 100644 index 000000000000..154a68dcb836 --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_cpld.c @@ -0,0 +1,1132 @@ +/* + * A CPLD driver for the porsche + * + * Copyright (C) 2018 Pegatron Corporation. + * Peter5_Lin + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef pegatron_porsche_DEBUG +/*#define pegatron_porsche_DEBUG*/ +#ifdef pegatron_porsche_DEBUG +#define DBG(x) x +#else +#define DBG(x) +#endif /* DEBUG */ + +#define CPLD_SFP_MAX_GROUP 3 +#define SFP_PORT_MAX_NUM 54 +#define SFP_EEPROM_SIZE 256 +#define QSFP_FIRST_PORT 48 +#define CPLDA_SFP_NUM 24 +#define CPLDB_SFP_NUM 12 +#define CPLDC_SFP_NUM 18 +#define CPLDA_ADDRESS 0x74 +#define CPLDB_ADDRESS 0x75 +#define CPLDC_ADDRESS 0x76 +#define CPLD_VERSION_REG 0x0 +#define SYNC_CONTROL_REG 0x1 +#define CPLD_SYS_PWR_LED_REG 0xD +#define CPLD_LOC_FAN_LED_REG 0xE +#define CPLD_EEPROM_WRITE_REG 0x12 +#define CPLD_PSU_REG 0x15 +#define SFP_13_36_SCL_BASE 0x4 +#define SFP_1_12_SCL_BASE 0x2 +#define SFP_37_54_SCL_BASE 0x5 +#define SFP_13_36_STATUS_BASE 0x8 +#define SFP_1_12_STATUS_BASE 0x5 +#define SFP_37_54_STATUS_BASE 0x9 +#define QSFP_PRESENT_ADDRESS 0xF +#define QSFP_RESET_ADDRESS_BASE 0x10 +#define QSFP_MODSELN_ADDRESS 0x17 +#define QSFP_LOW_POWER_ADDRESS 0x18 +#define CPLD_SERIAL_LED_BIT 2 +#define CPLD_EEPROM_WRITE_BIT 2 +#define SFP_PRESENT_BASE 0 +#define SFP_RXLOSS_BASE 1 +#define SFP_TXFAULT_BASE 2 +#define SFP_TXDISABLE_BASE 3 +#define CPLD_PSU_PWOK_BASE 0 +#define CPLD_PSU_PRESENT_BASE 2 +#define GET_BIT(data, bit, value) value = (data >> bit) & 0x1 +#define SET_BIT(data, bit) data |= (1 << bit) +#define CLEAR_BIT(data, bit) data &= ~(1 << bit) + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; +/* Addresses scanned for pegatron_porsche_cpld + */ +static const unsigned short normal_i2c[] = { CPLDA_ADDRESS, CPLDB_ADDRESS, CPLDC_ADDRESS, I2C_CLIENT_END }; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +int pegatron_porsche_cpld_read(unsigned short addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int data = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == addr) { + data = i2c_smbus_read_byte_data(cpld_node->client, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, addr, reg, data)); + break; + } + } + + mutex_unlock(&list_lock); + + return data; +} +EXPORT_SYMBOL(pegatron_porsche_cpld_read); + +int pegatron_porsche_cpld_write(unsigned short addr, u8 reg, u8 val) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, val); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, addr, reg, val)); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(pegatron_porsche_cpld_write); + +static ssize_t read_cpld_HWversion(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_VERSION_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%02x\n", (data >> 5) & 0x7); +} + +static ssize_t read_cpld_SWversion(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_VERSION_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + + return sprintf(buf, "%02x\n", (data & 0x1f)); +} + +static ssize_t show_allled_ctrl(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = SYNC_CONTROL_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data &= 0x3; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t set_allled_ctrl(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = SYNC_CONTROL_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + data = val | (data & 0xfc); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t show_serial_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = SYNC_CONTROL_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, CPLD_SERIAL_LED_BIT, val); + + return sprintf(buf, "%02x\n", val); +} + +static ssize_t set_serial_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = SYNC_CONTROL_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + if(val) + SET_BIT(data, CPLD_SERIAL_LED_BIT); + else + CLEAR_BIT(data, CPLD_SERIAL_LED_BIT); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t show_sys_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_SYS_PWR_LED_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = (data >> 5) & 0x7; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t set_sys_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_SYS_PWR_LED_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + data = (val << 5) | (data & 0x1f); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} +static ssize_t show_pwr_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_SYS_PWR_LED_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = (data >> 2) & 0x7; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t set_pwr_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_SYS_PWR_LED_REG; + long val = 0; + + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + data = (val << 2) | (data & 0xe3); + + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} +static ssize_t show_loc_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_LOC_FAN_LED_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = (data>>4) & 0x3; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t set_loc_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_LOC_FAN_LED_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + data = (val << 4) | (data & 0xf); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t show_fan_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_LOC_FAN_LED_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data &= 0x7; + + return sprintf(buf, "%02x\n", data); +} + +static ssize_t set_fan_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_LOC_FAN_LED_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + data = val | (data & 0xf8); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t show_eeprom_write_enable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = CPLD_EEPROM_WRITE_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, reg, val); + + return sprintf(buf, "%02x\n", val); +} + +static ssize_t set_eeprom_write_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = CPLD_EEPROM_WRITE_REG; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + if(val) + SET_BIT(data, CPLD_EEPROM_WRITE_BIT); + else + CLEAR_BIT(data, CPLD_EEPROM_WRITE_BIT); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t read_psu_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = CPLD_PSU_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, (CPLD_PSU_PRESENT_BASE + attr->index), val); + + return sprintf(buf, "%02x\n", val); +} + +static ssize_t read_psu_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val=0, reg = CPLD_PSU_REG; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, (CPLD_PSU_PWOK_BASE + attr->index), val); + + return sprintf(buf, "%02x\n", val); +} + +#define GET_SFP_STATUS_ADDRESS(idx, reg) \ + if(idx < CPLDB_SFP_NUM) \ + reg = SFP_1_12_STATUS_BASE + (idx / 2); \ + else if(idx < CPLDA_SFP_NUM + CPLDB_SFP_NUM) \ + reg = SFP_13_36_STATUS_BASE + ((idx-CPLDB_SFP_NUM) / 2); \ + else \ + reg = SFP_37_54_STATUS_BASE + ((idx-CPLDB_SFP_NUM-CPLDA_SFP_NUM) / 2) + +static ssize_t get_sfp_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = 0, data = 0, val = 0; + + GET_SFP_STATUS_ADDRESS(attr->index, reg); + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SFP_PRESENT_BASE + 4*(attr->index % 2), val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_sfp_tx_disable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = 0, data = 0, val = 0; + + GET_SFP_STATUS_ADDRESS(attr->index, reg); + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SFP_TXDISABLE_BASE + 4*(attr->index % 2), val); + + return sprintf(buf, "%d\n", val); +} +static ssize_t set_sfp_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = 0, data = 0; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + GET_SFP_STATUS_ADDRESS(attr->index, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = pegatron_porsche_cpld_read(client->addr, reg); + + if(val) + SET_BIT(data, SFP_TXDISABLE_BASE + 4*(attr->index % 2)); + else + CLEAR_BIT(data, SFP_TXDISABLE_BASE + 4*(attr->index % 2)); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} +static ssize_t get_sfp_rx_loss(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = 0, data = 0, val = 0; + + GET_SFP_STATUS_ADDRESS(attr->index, reg); + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SFP_RXLOSS_BASE + 4*(attr->index % 2), val); + + return sprintf(buf, "%d\n", val); +} +static ssize_t get_sfp_tx_fault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = 0, data = 0, val = 0; + + GET_SFP_STATUS_ADDRESS(attr->index, reg); + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, SFP_TXFAULT_BASE + 4*(attr->index % 2), val); + + return sprintf(buf, "%d\n",val); +} + +static ssize_t get_qsfp_present(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = QSFP_PRESENT_ADDRESS; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, (attr->index % QSFP_FIRST_PORT), val); + + return sprintf(buf, "%d\n", val); +} + +static ssize_t get_qsfp_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = (QSFP_RESET_ADDRESS_BASE + attr->index % QSFP_FIRST_PORT / 4), data =0; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = (data >> ((attr->index % QSFP_FIRST_PORT % 4)*2)) & 0x3; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 reg = (QSFP_RESET_ADDRESS_BASE + attr->index % QSFP_FIRST_PORT / 4), data = 0; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + data = (val & 0x3) << ((attr->index % QSFP_FIRST_PORT % 4)*2); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t get_qsfp_lowpower(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = QSFP_LOW_POWER_ADDRESS; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, (attr->index % QSFP_FIRST_PORT), val); + return sprintf(buf, "%02x\n", val); +} + +static ssize_t set_qsfp_lowpower(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = QSFP_LOW_POWER_ADDRESS; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + if(val) + SET_BIT(data, (attr->index % QSFP_FIRST_PORT)); + else + CLEAR_BIT(data, (attr->index % QSFP_FIRST_PORT)); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static ssize_t get_qsfp_modeseln(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, val = 0, reg = QSFP_MODSELN_ADDRESS; + + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + GET_BIT(data, (attr->index % QSFP_FIRST_PORT), val); + return sprintf(buf, "%02x\n", val); +} + +static ssize_t set_qsfp_modeseln(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + u8 data = 0, reg = QSFP_MODSELN_ADDRESS; + long val = 0; + + if (kstrtol(buf, 16, &val)) + { + return -EINVAL; + } + data = pegatron_porsche_cpld_read(client->addr, reg); + DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); + if(val) + SET_BIT(data, (attr->index % QSFP_FIRST_PORT)); + else + CLEAR_BIT(data, (attr->index % QSFP_FIRST_PORT)); + + pegatron_porsche_cpld_write(client->addr, reg, data); + + return count; +} + +static SENSOR_DEVICE_ATTR(cpld_hw_version, S_IRUGO, read_cpld_HWversion, NULL, 0); +static SENSOR_DEVICE_ATTR(cpld_sw_version, S_IRUGO, read_cpld_SWversion, NULL, 0); +static SENSOR_DEVICE_ATTR(cpld_allled_ctrl, S_IRUGO | S_IWUSR, show_allled_ctrl, set_allled_ctrl, 0); +static SENSOR_DEVICE_ATTR(serial_led_enable, S_IRUGO | S_IWUSR, show_serial_led, set_serial_led, 0); +static SENSOR_DEVICE_ATTR(sys_led, S_IRUGO | S_IWUSR, show_sys_led, set_sys_led, 0); +static SENSOR_DEVICE_ATTR(pwr_led, S_IRUGO | S_IWUSR, show_pwr_led, set_pwr_led, 0); +static SENSOR_DEVICE_ATTR(loc_led, S_IRUGO | S_IWUSR, show_loc_led, set_loc_led, 0); +static SENSOR_DEVICE_ATTR(fan_led, S_IRUGO | S_IWUSR, show_fan_led, set_fan_led, 0); +static SENSOR_DEVICE_ATTR(eeprom_write_enable, S_IRUGO | S_IWUSR, show_eeprom_write_enable, set_eeprom_write_enable, 0); +static SENSOR_DEVICE_ATTR(psu_1_present, S_IRUGO, read_psu_present, NULL, 1); +static SENSOR_DEVICE_ATTR(psu_2_present, S_IRUGO, read_psu_present, NULL, 0); +static SENSOR_DEVICE_ATTR(psu_1_status, S_IRUGO, read_psu_status, NULL, 1); +static SENSOR_DEVICE_ATTR(psu_2_status, S_IRUGO, read_psu_status, NULL, 0); + +#define SET_SFP_ATTR(_num) \ + static SENSOR_DEVICE_ATTR(sfp##_num##_present, S_IRUGO, get_sfp_present, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_tx_disable, S_IRUGO | S_IWUSR, get_sfp_tx_disable, set_sfp_tx_disable, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_rx_loss, S_IRUGO, get_sfp_rx_loss, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_tx_fault, S_IRUGO, get_sfp_tx_fault, NULL, _num-1) + +#define SET_QSFP_ATTR(_num) \ + static SENSOR_DEVICE_ATTR(sfp##_num##_present, S_IRUGO, get_qsfp_present, NULL, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_reset, S_IRUGO | S_IWUSR, get_qsfp_reset, set_qsfp_reset, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_lowpower, S_IRUGO | S_IWUSR, get_qsfp_lowpower, set_qsfp_lowpower, _num-1); \ + static SENSOR_DEVICE_ATTR(sfp##_num##_modeseln, S_IRUGO | S_IWUSR, get_qsfp_modeseln, set_qsfp_modeseln, _num-1) + +SET_SFP_ATTR(1);SET_SFP_ATTR(2);SET_SFP_ATTR(3);SET_SFP_ATTR(4);SET_SFP_ATTR(5);SET_SFP_ATTR(6);SET_SFP_ATTR(7);SET_SFP_ATTR(8);SET_SFP_ATTR(9); +SET_SFP_ATTR(10);SET_SFP_ATTR(11);SET_SFP_ATTR(12);SET_SFP_ATTR(13);SET_SFP_ATTR(14);SET_SFP_ATTR(15);SET_SFP_ATTR(16);SET_SFP_ATTR(17);SET_SFP_ATTR(18); +SET_SFP_ATTR(19);SET_SFP_ATTR(20);SET_SFP_ATTR(21);SET_SFP_ATTR(22);SET_SFP_ATTR(23);SET_SFP_ATTR(24);SET_SFP_ATTR(25);SET_SFP_ATTR(26);SET_SFP_ATTR(27); +SET_SFP_ATTR(28);SET_SFP_ATTR(29);SET_SFP_ATTR(30);SET_SFP_ATTR(31);SET_SFP_ATTR(32);SET_SFP_ATTR(33);SET_SFP_ATTR(34);SET_SFP_ATTR(35);SET_SFP_ATTR(36); +SET_SFP_ATTR(37);SET_SFP_ATTR(38);SET_SFP_ATTR(39);SET_SFP_ATTR(40);SET_SFP_ATTR(41);SET_SFP_ATTR(42);SET_SFP_ATTR(43);SET_SFP_ATTR(44);SET_SFP_ATTR(45); +SET_SFP_ATTR(46);SET_SFP_ATTR(47);SET_SFP_ATTR(48); +SET_QSFP_ATTR(49);SET_QSFP_ATTR(50);SET_QSFP_ATTR(51);SET_QSFP_ATTR(52);SET_QSFP_ATTR(53);SET_QSFP_ATTR(54); + +static struct attribute *pegatron_porsche_cpldA_attributes[] = { + &sensor_dev_attr_cpld_hw_version.dev_attr.attr, + &sensor_dev_attr_cpld_sw_version.dev_attr.attr, + + &sensor_dev_attr_sfp13_present.dev_attr.attr, + &sensor_dev_attr_sfp13_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp13_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp13_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp14_present.dev_attr.attr, + &sensor_dev_attr_sfp14_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp14_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp14_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp15_present.dev_attr.attr, + &sensor_dev_attr_sfp15_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp15_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp15_tx_fault.dev_attr.attr, + + + &sensor_dev_attr_sfp16_present.dev_attr.attr, + &sensor_dev_attr_sfp16_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp16_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp16_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp17_present.dev_attr.attr, + &sensor_dev_attr_sfp17_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp17_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp17_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp18_present.dev_attr.attr, + &sensor_dev_attr_sfp18_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp18_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp18_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp19_present.dev_attr.attr, + &sensor_dev_attr_sfp19_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp19_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp19_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp20_present.dev_attr.attr, + &sensor_dev_attr_sfp20_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp20_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp20_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp21_present.dev_attr.attr, + &sensor_dev_attr_sfp21_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp21_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp21_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp22_present.dev_attr.attr, + &sensor_dev_attr_sfp22_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp22_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp22_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp23_present.dev_attr.attr, + &sensor_dev_attr_sfp23_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp23_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp23_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp24_present.dev_attr.attr, + &sensor_dev_attr_sfp24_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp24_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp24_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp25_present.dev_attr.attr, + &sensor_dev_attr_sfp25_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp25_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp25_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp26_present.dev_attr.attr, + &sensor_dev_attr_sfp26_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp26_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp26_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp27_present.dev_attr.attr, + &sensor_dev_attr_sfp27_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp27_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp27_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp28_present.dev_attr.attr, + &sensor_dev_attr_sfp28_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp28_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp28_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp29_present.dev_attr.attr, + &sensor_dev_attr_sfp29_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp29_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp29_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp30_present.dev_attr.attr, + &sensor_dev_attr_sfp30_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp30_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp30_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp31_present.dev_attr.attr, + &sensor_dev_attr_sfp31_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp31_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp31_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp32_present.dev_attr.attr, + &sensor_dev_attr_sfp32_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp32_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp32_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp33_present.dev_attr.attr, + &sensor_dev_attr_sfp33_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp33_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp33_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp34_present.dev_attr.attr, + &sensor_dev_attr_sfp34_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp34_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp34_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp35_present.dev_attr.attr, + &sensor_dev_attr_sfp35_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp35_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp35_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp36_present.dev_attr.attr, + &sensor_dev_attr_sfp36_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp36_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp36_tx_fault.dev_attr.attr, + + NULL +}; + +static struct attribute *pegatron_porsche_cpldB_attributes[] = { + &sensor_dev_attr_cpld_hw_version.dev_attr.attr, + &sensor_dev_attr_cpld_sw_version.dev_attr.attr, + &sensor_dev_attr_cpld_allled_ctrl.dev_attr.attr, + &sensor_dev_attr_serial_led_enable.dev_attr.attr, + &sensor_dev_attr_sys_led.dev_attr.attr, + &sensor_dev_attr_pwr_led.dev_attr.attr, + &sensor_dev_attr_loc_led.dev_attr.attr, + &sensor_dev_attr_fan_led.dev_attr.attr, + &sensor_dev_attr_eeprom_write_enable.dev_attr.attr, + &sensor_dev_attr_psu_1_present.dev_attr.attr, + &sensor_dev_attr_psu_2_present.dev_attr.attr, + &sensor_dev_attr_psu_1_status.dev_attr.attr, + &sensor_dev_attr_psu_2_status.dev_attr.attr, + + &sensor_dev_attr_sfp1_present.dev_attr.attr, + &sensor_dev_attr_sfp1_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp1_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp1_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp2_present.dev_attr.attr, + &sensor_dev_attr_sfp2_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp2_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp2_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp3_present.dev_attr.attr, + &sensor_dev_attr_sfp3_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp3_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp3_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp4_present.dev_attr.attr, + &sensor_dev_attr_sfp4_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp4_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp4_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp5_present.dev_attr.attr, + &sensor_dev_attr_sfp5_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp5_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp5_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp6_present.dev_attr.attr, + &sensor_dev_attr_sfp6_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp6_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp6_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp7_present.dev_attr.attr, + &sensor_dev_attr_sfp7_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp7_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp7_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp8_present.dev_attr.attr, + &sensor_dev_attr_sfp8_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp8_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp8_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp9_present.dev_attr.attr, + &sensor_dev_attr_sfp9_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp9_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp9_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp10_present.dev_attr.attr, + &sensor_dev_attr_sfp10_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp10_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp10_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp11_present.dev_attr.attr, + &sensor_dev_attr_sfp11_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp11_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp11_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp12_present.dev_attr.attr, + &sensor_dev_attr_sfp12_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp12_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp12_tx_fault.dev_attr.attr, + NULL +}; + +static struct attribute *pegatron_porsche_cpldC_attributes[] = { + &sensor_dev_attr_cpld_hw_version.dev_attr.attr, + &sensor_dev_attr_cpld_sw_version.dev_attr.attr, + + &sensor_dev_attr_sfp37_present.dev_attr.attr, + &sensor_dev_attr_sfp37_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp37_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp37_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp38_present.dev_attr.attr, + &sensor_dev_attr_sfp38_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp38_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp38_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp39_present.dev_attr.attr, + &sensor_dev_attr_sfp39_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp39_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp39_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp40_present.dev_attr.attr, + &sensor_dev_attr_sfp40_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp40_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp40_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp41_present.dev_attr.attr, + &sensor_dev_attr_sfp41_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp41_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp41_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp42_present.dev_attr.attr, + &sensor_dev_attr_sfp42_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp42_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp42_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp43_present.dev_attr.attr, + &sensor_dev_attr_sfp43_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp43_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp43_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp44_present.dev_attr.attr, + &sensor_dev_attr_sfp44_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp44_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp44_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp45_present.dev_attr.attr, + &sensor_dev_attr_sfp45_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp45_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp45_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp46_present.dev_attr.attr, + &sensor_dev_attr_sfp46_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp46_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp46_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp47_present.dev_attr.attr, + &sensor_dev_attr_sfp47_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp47_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp47_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp48_present.dev_attr.attr, + &sensor_dev_attr_sfp48_tx_disable.dev_attr.attr, + &sensor_dev_attr_sfp48_rx_loss.dev_attr.attr, + &sensor_dev_attr_sfp48_tx_fault.dev_attr.attr, + + &sensor_dev_attr_sfp49_present.dev_attr.attr, + &sensor_dev_attr_sfp49_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp49_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp49_reset.dev_attr.attr, + + &sensor_dev_attr_sfp50_present.dev_attr.attr, + &sensor_dev_attr_sfp50_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp50_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp50_reset.dev_attr.attr, + + &sensor_dev_attr_sfp51_present.dev_attr.attr, + &sensor_dev_attr_sfp51_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp51_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp51_reset.dev_attr.attr, + + &sensor_dev_attr_sfp52_present.dev_attr.attr, + &sensor_dev_attr_sfp52_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp52_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp52_reset.dev_attr.attr, + + &sensor_dev_attr_sfp53_present.dev_attr.attr, + &sensor_dev_attr_sfp53_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp53_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp53_reset.dev_attr.attr, + + &sensor_dev_attr_sfp54_present.dev_attr.attr, + &sensor_dev_attr_sfp54_lowpower.dev_attr.attr, + &sensor_dev_attr_sfp54_modeseln.dev_attr.attr, + &sensor_dev_attr_sfp54_reset.dev_attr.attr, + NULL +}; + +static const struct attribute_group pegatron_porsche_cpldA_group = { .attrs = pegatron_porsche_cpldA_attributes}; +static const struct attribute_group pegatron_porsche_cpldB_group = { .attrs = pegatron_porsche_cpldB_attributes}; +static const struct attribute_group pegatron_porsche_cpldC_group = { .attrs = pegatron_porsche_cpldC_attributes}; + +static void pegatron_porsche_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void pegatron_porsche_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int pegatron_porsche_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + /* Register sysfs hooks */ + switch(client->addr) + { + case CPLDA_ADDRESS: + status = sysfs_create_group(&client->dev.kobj, &pegatron_porsche_cpldA_group); + break; + case CPLDB_ADDRESS: + status = sysfs_create_group(&client->dev.kobj, &pegatron_porsche_cpldB_group); + break; + case CPLDC_ADDRESS: + status = sysfs_create_group(&client->dev.kobj, &pegatron_porsche_cpldC_group); + break; + default: + dev_dbg(&client->dev, "i2c_check_CPLD failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + break; + } + + if (status) { + goto exit; + } + + dev_info(&client->dev, "chip found\n"); + pegatron_porsche_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int pegatron_porsche_cpld_remove(struct i2c_client *client) +{ + switch(client->addr) + { + case CPLDA_ADDRESS: + sysfs_remove_group(&client->dev.kobj, &pegatron_porsche_cpldA_group); + break; + case CPLDB_ADDRESS: + sysfs_remove_group(&client->dev.kobj, &pegatron_porsche_cpldB_group); + break; + case CPLDC_ADDRESS: + sysfs_remove_group(&client->dev.kobj, &pegatron_porsche_cpldC_group); + break; + default: + dev_dbg(&client->dev, "i2c_remove_CPLD failed (0x%x)\n", client->addr); + break; + } + + + pegatron_porsche_cpld_remove_client(client); + return 0; +} + +static const struct i2c_device_id pegatron_porsche_cpld_id[] = { + { "porsche_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pegatron_porsche_cpld_id); + +static struct i2c_driver pegatron_porsche_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "pegatron_porsche_cpld", + }, + .probe = pegatron_porsche_cpld_probe, + .remove = pegatron_porsche_cpld_remove, + .id_table = pegatron_porsche_cpld_id, + .address_list = normal_i2c, +}; + +static int __init pegatron_porsche_cpld_init(void) +{ + mutex_init(&list_lock); + + return i2c_add_driver(&pegatron_porsche_cpld_driver); +} + +static void __exit pegatron_porsche_cpld_exit(void) +{ + i2c_del_driver(&pegatron_porsche_cpld_driver); +} + +MODULE_AUTHOR("Peter5 Lin "); +MODULE_DESCRIPTION("pegatron_porsche_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(pegatron_porsche_cpld_init); +module_exit(pegatron_porsche_cpld_exit); diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_sfp.c b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_sfp.c new file mode 100644 index 000000000000..5d5d64b15e1a --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/modules/pegatron_porsche_sfp.c @@ -0,0 +1,431 @@ +/* + * A SFP driver for the porsche platform + * + * Copyright (C) 2018 Pegatron Corporation. + * Peter5_Lin + * + * 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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef PEGA_DEBUG +/*#define PEGA_DEBUG*/ +#ifdef PEGA_DEBUG +#define DBG(x) x +#else +#define DBG(x) +#endif /* DEBUG */ + +#define SFP_EEPROM_SIZE 256 +#define SFP_EEPROM_A0_ADDR 0x50 +#define SFP_EEPROM_A2_ADDR 0x51 +#define SFP_EEPROM_BUS_TYPE I2C_SMBUS_I2C_BLOCK_DATA +#define CPLDA_SFP_NUM 24 +#define CPLDB_SFP_NUM 12 +#define CPLDC_SFP_NUM 18 +#define CPLDA_ADDRESS 0x74 +#define CPLDB_ADDRESS 0x75 +#define CPLDC_ADDRESS 0x76 +#define SFP_13_36_SCL_BASE 0x4 +#define SFP_1_12_SCL_BASE 0x2 +#define SFP_37_54_SCL_BASE 0x5 +#define QSFP_I2C_ENABLE_BASE 0x17 +#define GET_BIT(data, bit, value) value = (data >> bit) & 0x1 +#define SET_BIT(data, bit) data |= (1 << bit) +#define CLEAR_BIT(data, bit) data &= ~(1 << bit) + +enum cpld_croups { cpld_group_a, cpld_group_b, cpld_group_c}; + +static const unsigned short normal_i2c[] = { SFP_EEPROM_A0_ADDR, SFP_EEPROM_A2_ADDR, I2C_CLIENT_END }; +static char *SFP_CPLD_GROUPA_MAPPING[CPLDA_SFP_NUM][16]={0}; +static char *SFP_CPLD_GROUPB_MAPPING[CPLDB_SFP_NUM][16]={0}; +static char *SFP_CPLD_GROUPC_MAPPING[CPLDC_SFP_NUM][16]={0}; + +/* + * This parameter is to help this driver avoid blocking other drivers out + * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C + * clock, one 256 byte read takes about 1/43 second which is excessive; + * but the 1/170 second it takes at 400 kHz may be quite reasonable; and + * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. + * + * This value is forced to be a power of two so that writes align on pages. + */ +static unsigned io_limit = 128; +module_param(io_limit, uint, 0); +MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); + +/* + * Specs often allow 5 msec for a page write, sometimes 20 msec; + * it's important to recover from write timeouts. + */ +static unsigned write_timeout = 25; +module_param(write_timeout, uint, 0); +MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); + + +struct porsche_sfp_data { + struct mutex lock; + struct bin_attribute bin; + int use_smbus; + kernel_ulong_t driver_data; + + struct i2c_client *client; +}; + +extern int pegatron_porsche_cpld_read(unsigned short cpld_addr, u8 reg); +extern int pegatron_porsche_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t porsche_sfp_eeprom_read(struct porsche_sfp_data *data, char *buf, + unsigned offset, size_t count) +{ + struct i2c_msg msg[2]; + u8 msgbuf[2]; + struct i2c_client *client = data->client; + unsigned long timeout, read_time; + int status; + + memset(msg, 0, sizeof(msg)); + + if (count > io_limit) + count = io_limit; + + /* Smaller eeproms can work given some SMBus extension calls */ + if (count > I2C_SMBUS_BLOCK_MAX) + count = I2C_SMBUS_BLOCK_MAX; + + /* + * Reads fail if the previous write didn't complete yet. We may + * loop a few times until this one succeeds, waiting at least + * long enough for one entire page write to work. + */ + timeout = jiffies + msecs_to_jiffies(write_timeout); + do { + read_time = jiffies; + switch (data->use_smbus) { + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_read_i2c_block_data(client, offset, + count, buf); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(client, offset); + if (status >= 0) { + buf[0] = status & 0xff; + if (count == 2) + buf[1] = status >> 8; + status = count; + } + break; + case I2C_SMBUS_BYTE_DATA: + status = i2c_smbus_read_byte_data(client, offset); + if (status >= 0) { + buf[0] = status; + status = count; + } + break; + default: + status = i2c_transfer(client->adapter, msg, 2); + if (status == 2) + status = count; + } + dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", + count, offset, status, jiffies); + + if (status == count) + return count; + + /* REVISIT: at HZ=100, this is sloooow */ + msleep(1); + } while (time_before(read_time, timeout)); + + return -ETIMEDOUT; +} + +static ssize_t porsche_sfp_read(struct porsche_sfp_data *data, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) + return count; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ + mutex_lock(&data->lock); + + while (count) { + ssize_t status; + + status = porsche_sfp_eeprom_read(data, buf, off, count); + if (status <= 0) { + if (retval == 0) + retval = status; + break; + } + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->lock); + + return retval; +} + +static ssize_t +porsche_sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + int i; + u8 cpldData = 0; + struct porsche_sfp_data *data; + + /*SFP 1-12*/ + for(i=0; iattr.name, SFP_CPLD_GROUPB_MAPPING[i])) + { + pegatron_porsche_cpld_write(CPLDB_ADDRESS, SFP_1_12_SCL_BASE, i+1); + goto check_done; + } + } + /*SFP 13-36*/ + for(i=0; iattr.name, SFP_CPLD_GROUPA_MAPPING[i])) + { + pegatron_porsche_cpld_write(CPLDA_ADDRESS, SFP_13_36_SCL_BASE, i+1); + goto check_done; + } + } + + /*SFP 37-54*/ + for(i=0; iattr.name, SFP_CPLD_GROUPC_MAPPING[i])) + { + /* Enable QSFP i2c function */ + if(i >= 12) + { + cpldData = 0xff; + cpldData = pegatron_porsche_cpld_read(CPLDC_ADDRESS, QSFP_I2C_ENABLE_BASE); + CLEAR_BIT(cpldData, i-12); + pegatron_porsche_cpld_write(CPLDC_ADDRESS, QSFP_I2C_ENABLE_BASE, cpldData); + } + pegatron_porsche_cpld_write(CPLDC_ADDRESS, SFP_37_54_SCL_BASE, i+1); + goto check_done; + } + } + +check_done: + data = dev_get_drvdata(container_of(kobj, struct device, kobj)); + + return porsche_sfp_read(data, buf, off, count); +} + +#define SFP_EEPROM_ATTR(_num) \ + static struct bin_attribute sfp##_num##_eeprom_attr = { \ + .attr = { \ + .name = __stringify(sfp##_num##_eeprom), \ + .mode = S_IRUGO\ + }, \ + .size = SFP_EEPROM_SIZE, \ + .read = porsche_sfp_bin_read, \ + } + +SFP_EEPROM_ATTR(1);SFP_EEPROM_ATTR(2);SFP_EEPROM_ATTR(3);SFP_EEPROM_ATTR(4);SFP_EEPROM_ATTR(5);SFP_EEPROM_ATTR(6);SFP_EEPROM_ATTR(7);SFP_EEPROM_ATTR(8);SFP_EEPROM_ATTR(9); +SFP_EEPROM_ATTR(10);SFP_EEPROM_ATTR(11);SFP_EEPROM_ATTR(12);SFP_EEPROM_ATTR(13);SFP_EEPROM_ATTR(14);SFP_EEPROM_ATTR(15);SFP_EEPROM_ATTR(16);SFP_EEPROM_ATTR(17);SFP_EEPROM_ATTR(18); +SFP_EEPROM_ATTR(19);SFP_EEPROM_ATTR(20);SFP_EEPROM_ATTR(21);SFP_EEPROM_ATTR(22);SFP_EEPROM_ATTR(23);SFP_EEPROM_ATTR(24);SFP_EEPROM_ATTR(25);SFP_EEPROM_ATTR(26);SFP_EEPROM_ATTR(27); +SFP_EEPROM_ATTR(28);SFP_EEPROM_ATTR(29);SFP_EEPROM_ATTR(30);SFP_EEPROM_ATTR(31);SFP_EEPROM_ATTR(32);SFP_EEPROM_ATTR(33);SFP_EEPROM_ATTR(34);SFP_EEPROM_ATTR(35);SFP_EEPROM_ATTR(36); +SFP_EEPROM_ATTR(37);SFP_EEPROM_ATTR(38);SFP_EEPROM_ATTR(39);SFP_EEPROM_ATTR(40);SFP_EEPROM_ATTR(41);SFP_EEPROM_ATTR(42);SFP_EEPROM_ATTR(43);SFP_EEPROM_ATTR(44);SFP_EEPROM_ATTR(45); +SFP_EEPROM_ATTR(46);SFP_EEPROM_ATTR(47);SFP_EEPROM_ATTR(48);SFP_EEPROM_ATTR(49);SFP_EEPROM_ATTR(50);SFP_EEPROM_ATTR(51);SFP_EEPROM_ATTR(52);SFP_EEPROM_ATTR(53);SFP_EEPROM_ATTR(54); + +static struct bin_attribute *porsche_cpldA_sfp_epprom_attributes[] = { + &sfp13_eeprom_attr, &sfp14_eeprom_attr, &sfp15_eeprom_attr, &sfp16_eeprom_attr, &sfp17_eeprom_attr, &sfp18_eeprom_attr, &sfp19_eeprom_attr, &sfp20_eeprom_attr, + &sfp21_eeprom_attr, &sfp22_eeprom_attr, &sfp23_eeprom_attr, &sfp24_eeprom_attr, &sfp25_eeprom_attr, &sfp26_eeprom_attr, &sfp27_eeprom_attr, &sfp28_eeprom_attr, + &sfp29_eeprom_attr, &sfp30_eeprom_attr, &sfp31_eeprom_attr, &sfp32_eeprom_attr, &sfp33_eeprom_attr, &sfp34_eeprom_attr, &sfp35_eeprom_attr, &sfp36_eeprom_attr, + NULL +}; + +static struct bin_attribute *porsche_cpldB_sfp_epprom_attributes[] = { + &sfp1_eeprom_attr, &sfp2_eeprom_attr, &sfp3_eeprom_attr, &sfp4_eeprom_attr, &sfp5_eeprom_attr, &sfp6_eeprom_attr, &sfp7_eeprom_attr, &sfp8_eeprom_attr, + &sfp9_eeprom_attr, &sfp10_eeprom_attr, &sfp11_eeprom_attr, &sfp12_eeprom_attr, + NULL +}; + +static struct bin_attribute *porsche_cpldC_sfp_epprom_attributes[] = { + &sfp37_eeprom_attr, &sfp38_eeprom_attr, &sfp39_eeprom_attr, &sfp40_eeprom_attr, &sfp41_eeprom_attr, &sfp42_eeprom_attr, &sfp43_eeprom_attr, &sfp44_eeprom_attr, + &sfp45_eeprom_attr, &sfp46_eeprom_attr, &sfp47_eeprom_attr, &sfp48_eeprom_attr, &sfp49_eeprom_attr, &sfp50_eeprom_attr, &sfp51_eeprom_attr, &sfp52_eeprom_attr, + &sfp53_eeprom_attr, &sfp54_eeprom_attr, + NULL +}; + +static const struct attribute_group porsche_sfpA_group = { .bin_attrs = porsche_cpldA_sfp_epprom_attributes}; +static const struct attribute_group porsche_sfpB_group = { .bin_attrs = porsche_cpldB_sfp_epprom_attributes}; +static const struct attribute_group porsche_sfpC_group = { .bin_attrs = porsche_cpldC_sfp_epprom_attributes}; + +static int porsche_sfp_device_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + int use_smbus = SFP_EEPROM_BUS_TYPE; + struct porsche_sfp_data *data; + int err, i; + unsigned num_addresses; + kernel_ulong_t magic; + + data = kzalloc(sizeof(struct porsche_sfp_data) , GFP_KERNEL); + if (!data) + return -ENOMEM; + + mutex_init(&data->lock); + data->use_smbus = use_smbus; + /* + * Export the EEPROM bytes through sysfs, since that's convenient. + * By default, only root should see the data (maybe passwords etc) + */ + + data->client = client; + data->driver_data = dev_id->driver_data; + + sysfs_bin_attr_init(&data->bin); + + switch(dev_id->driver_data) + { + case cpld_group_a: + err = sysfs_create_group(&client->dev.kobj, &porsche_sfpA_group); + if (err) + goto err_clients; + break; + case cpld_group_b: + err = sysfs_create_group(&client->dev.kobj, &porsche_sfpB_group); + if (err) + goto err_clients; + break; + case cpld_group_c: + err = sysfs_create_group(&client->dev.kobj, &porsche_sfpC_group); + if (err) + goto err_clients; + break; + default: + printk(KERN_ALERT "i2c_check_CPLD failed\n"); + err = -EIO; + break; + } + + i2c_set_clientdata(client, data); + + return 0; + +err_clients: + kfree(data); + return err; +} + +static int porsche_sfp_device_remove(struct i2c_client *client) +{ + struct porsche_sfp_data *data; + int i; + + data = i2c_get_clientdata(client); + + switch(data->driver_data) + { + case cpld_group_a: + sysfs_remove_group(&client->dev.kobj, &porsche_sfpA_group); + break; + case cpld_group_b: + sysfs_remove_group(&client->dev.kobj, &porsche_sfpB_group); + break; + case cpld_group_c: + sysfs_remove_group(&client->dev.kobj, &porsche_sfpC_group); + break; + default: + dev_dbg(&client->dev, "i2c_remove_CPLD failed (0x%x)\n", client->addr); + break; + } + + + return 0; +} + +static const struct i2c_device_id porsche_sfp_id[] = { + { "porsche_sfpA", cpld_group_a }, + { "porsche_sfpB", cpld_group_b }, + { "porsche_sfpC", cpld_group_c }, + {} +}; +MODULE_DEVICE_TABLE(i2c, porsche_sfp_id); + +static struct i2c_driver porsche_sfp_driver = { + .driver = { + .name = "pegatron_porsche_sfp", + }, + .probe = porsche_sfp_device_probe, + .remove = porsche_sfp_device_remove, + .id_table = porsche_sfp_id, + .address_list = normal_i2c, +}; + +static int __init porsche_sfp_init(void) +{ + int i; + + /*SFP 1-12*/ + for(i=0; i"); +MODULE_DESCRIPTION("porsche_cpld_mux driver"); +MODULE_LICENSE("GPL"); + +module_init(porsche_sfp_init); +module_exit(porsche_sfp_exit); + diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/scripts/sensors b/platform/nephos/sonic-platform-modules-pegatron/porsche/scripts/sensors new file mode 100755 index 000000000000..7f9426a0c5ec --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/scripts/sensors @@ -0,0 +1,7 @@ +#!/bin/bash +docker exec -i pmon sensors "$@" + +#To probe sensors not part of lm-sensors +if [ -r /usr/local/bin/porsche_sensors.py ]; then + python /usr/local/bin/porsche_sensors.py get_sensors +fi diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/service/porsche-platform-init.service b/platform/nephos/sonic-platform-modules-pegatron/porsche/service/porsche-platform-init.service new file mode 100644 index 000000000000..8e6f4344715f --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/service/porsche-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Pegastron porsche Platform initialization service +After=local-fs.target +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/pegatron_porsche_util.py install +ExecStop=/usr/local/bin/pegatron_porsche_util.py uninstall +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/pegatron_porsche_util.py b/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/pegatron_porsche_util.py new file mode 100755 index 000000000000..16662081d0cb --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/pegatron_porsche_util.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Pegatron, Inc. +# +# 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 3 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import sys, getopt +import logging +import os +import commands +import threading + +DEBUG = False + +SFP_MAX_NUM = 48 +CPLDA_SFP_NUM = 24 +CPLDB_SFP_NUM = 12 +CPLDC_SFP_NUM = 18 + +kernel_module = ['i2c_dev', 'i2c-mux-pca954x force_deselect_on_exit=1', 'at24', 'pegatron_porsche_cpld', 'pegatron_hwmon_mcu', 'pegatron_porsche_sfp'] +moduleID = ['pca9544', 'pca9544', '24c02', 'porsche_hwmon_mcu', 'porsche_cpld', 'porsche_cpld', 'porsche_cpld', 'porsche_sfpA', 'porsche_sfpB', 'porsche_sfpC'] +i2c_check_node = ['i2c-0', 'i2c-1'] +device_address = ['0x72', '0x73', '0x54', '0x70', '0x74', '0x75', '0x76', '0x50', '0x50', '0x50'] +device_node= ['i2c-2', 'i2c-6', 'i2c-4', 'i2c-5', 'i2c-6', 'i2c-7', 'i2c-8', 'i2c-6', 'i2c-7', 'i2c-8'] + +i2c_prefix = '/sys/bus/i2c/devices/' +cpld_bus = ['6-0074', '7-0075', '8-0076'] +led_nodes = ['sys_led', 'pwr_led', 'loc_led', 'fan_led', "cpld_allled_ctrl", "serial_led_enable"] + +def dbg_print(string): + if DEBUG == True: + print string + return + +def do_cmd(cmd, show): + logging.info('Run :' + cmd) + status, output = commands.getstatusoutput(cmd) + dbg_print(cmd + "with result:" + str(status)) + dbg_print("output:" + output) + if status: + logging.info('Failed :' + cmd) + if show: + print('Failed :' + cmd) + return status, output + +def check_device_position(num): + for i in range(0, len(i2c_check_node)): + status, output = do_cmd("echo " + moduleID[num] + " " + device_address[num] + " > " + i2c_prefix + i2c_check_node[i] + "/new_device", 0) + status, output = do_cmd("ls " + i2c_prefix + device_node[num], 0) + device_node[num] = i2c_check_node[i] + + if status: + status, output = do_cmd("echo " + device_address[num] + " > " + i2c_prefix + i2c_check_node[i] + "/delete_device", 0) + else: + return + + return + +def install_device(): + for i in range(0, len(moduleID)): + if moduleID[i] == "pca9544": + check_device_position(i) + else: + status, output = do_cmd("echo " + moduleID[i] + " " + device_address[i] + " > " + i2c_prefix + device_node[i] + "/new_device", 1) + + return + +def check_driver(): + for i in range(0, len(kernel_module)): + status, output = do_cmd("lsmod | grep " + kernel_module[i], 0) + if status: + status, output = do_cmd("modprobe " + kernel_module[i], 1) + + return + +def do_install(): + status, output = do_cmd("depmod -a", 1) + + check_driver() + install_device() + + return + +def do_uninstall(): + for i in range(0, len(kernel_module)): + status, output = do_cmd("modprobe -r " + kernel_module[i], 1) + + for i in range(0, len(moduleID)): + status, output = do_cmd("echo " + device_address[i] + " > " + i2c_prefix + i2c_check_node[i] + "/delete_device", 0) + + return + +led_command = {'sys_led': {'green':'0', 'amber':'1', 'off':'2', 'blink_green':'3', 'blink_amber':'4'}, + 'pwr_led': {'green':'0', 'amber':'1', 'off':'2', 'blink_green':'3', 'blink_amber':'4'}, + 'loc_led': {'on':'0', 'off':'1', 'blink':'2'}, + 'fan_led': {'green':'0', 'amber':'1', 'off':'2', 'blink_green':'3', 'blink_amber':'4'}, + 'cpld_allled_ctrl': {'off':'0', 'mix':'1', 'amber':'2', 'normal':'3'}, + 'serial_led_enable': {'disable':'0', 'enable':'1'}} + +def set_led(args): + """ + Usage: %(scriptName)s set led object command + + object: + sys_led : set SYS led [command: off|green|amber|blink_green|blink_amber] + pwr_led : set PWR led [command: off|green|amber|blink_green|blink_amber] + loc_led : set LOCATOR led [command: off|on|blink] + fan_led : set FAN led [command: off|green|amber|blink_green|blink_amber] + """ + if args[0] not in led_command: + print set_led.__doc__ + sys.exit(0) + + for i in range(0,len(led_nodes)): + if args[0] == led_nodes[i]: + node = i2c_prefix + cpld_bus[1] + '/'+ led_nodes[i] + + command = led_command[args[0]] + data = command[args[1]] + + status, output = do_cmd("echo "+ str(data) + " > "+ node, 1) + + return + +def set_device(args): + """ + Usage: %(scriptName)s command object + + command: + led : set status led sys_led|pwr_led|loc_led|mst_led|fan_led|digit_led + """ + + if args[0] == 'led': + set_led(args[1:]) + return + else: + print set_device.__doc__ + + return + +device_init = {'led': [['led', 'sys_led', 'green'], ['led', 'pwr_led', 'green'], ['led', 'fan_led', 'green'], ['led', 'cpld_allled_ctrl', 'normal'], ['led', 'serial_led_enable', 'enable']]} + +def pega_init(): + #set led + for i in range(0,len(device_init['led'])): + set_device(device_init['led'][i]) + + #set tx_disable + for x in range(0, SFP_MAX_NUM-1): + if x < CPLDB_SFP_NUM: + bus = cpld_bus[1] + elif x < CPLDB_SFP_NUM + CPLDA_SFP_NUM: + bus = cpld_bus[0] + else: + bus = cpld_bus[2] + + nodes = i2c_prefix + bus + '/sfp' + str(x+1) + '_tx_disable' + dbg_print("SFP_TX_DISABLE NODES: " + nodes) + status, output = do_cmd("echo 0 > "+ nodes, 1) + + return + +def main(): + """ + Usage: %(scriptName)s command object + + command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + set : change board setting [led] + debug : debug info [on/off] + """ + + if len(sys.argv)<2: + print main.__doc__ + + for arg in sys.argv[1:]: + if arg == 'install': + do_install() + pega_init() + elif arg == 'uninstall': + do_uninstall() + elif arg == 'set': + if len(sys.argv[2:])<1: + print main.__doc__ + else: + set_device(sys.argv[2:]) + return + elif arg == 'debug': + if sys.argv[2] == 'on': + DEBUG = True + else: + DEBUG = False + else: + print main.__doc__ + +if __name__ == "__main__": + main() diff --git a/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/porsche_sensors.py b/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/porsche_sensors.py new file mode 100755 index 000000000000..40e23ef01b7e --- /dev/null +++ b/platform/nephos/sonic-platform-modules-pegatron/porsche/utils/porsche_sensors.py @@ -0,0 +1,141 @@ +#!/usr/bin/python + +import os +import sys +import logging + +FAN_NUM = 5 +sensors_path = '/sys/bus/i2c/devices/5-0070/' +sensors_nodes = {'fan_rpm': ['_inner_rpm', '_outer_rpm'], + 'fan_vol': ['ADC8_vol', 'ADC7_vol','ADC6_vol', 'ADC5_vol','ADC4_vol', 'ADC3_vol'], + 'temp':['lm75_49_temp', 'lm75_48_temp', 'SA56004_local_temp','SA56004_remote_temp']} +sensors_type = {'fan_rpm': ['Inner RPM', 'Outer RPM'], + 'fan_vol': ['P0.2', 'P0.6','P0.1', 'P1.5','P0.7', 'P1.6'], + 'temp':['lm75_49_temp', 'lm75_48_temp', 'SA56004_local_temp','SA56004_remote_temp']} + +# Get sysfs attribute +def get_attr_value(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 ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + fd.close() + return retval + +def get_fan_status(number): + attr_value = get_attr_value(sensors_path + "fan" + str(number+1) + "_present") + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + + if(attr_value == 0): + string = "Connect" + else: + string = "Disconnect" + return string + +def get_fan_alert(number): + attr_value = get_attr_value(sensors_path + "fan" + str(number+1) + "_status_alert") + if (attr_value != 'ERR'): + attr_value = int(attr_value, 16) + + if(attr_value == 0): + string = "Normal" + else: + string = "Abnormal" + return string + +def get_fan_inner_rpm(number): + return get_attr_value(sensors_path + "fan" + str(number+1) + "_inner_rpm") + +def get_fan_outer_rpm(number): + return get_attr_value(sensors_path + "fan" + str(number+1) + "_outer_rpm") + +def get_fan(): + for i in range(0,FAN_NUM): + print " " + #status + string = get_fan_status(i) + print "FAN " + str(i+1) + ":" + ' ' + string + if string=='Disconnect': + continue + + #alert + string = get_fan_alert(i) + print " Status:"+ ' ' + string + + #inner rpm + string = get_fan_inner_rpm(i) + print " Inner RPM:"+ string.rjust(10) + ' RPM' + + #outer rpm + string = get_fan_outer_rpm(i) + print " Outer RPM:"+ string.rjust(10) + ' RPM' + + return + +def get_hwmon(): + print " " + string = get_attr_value(sensors_path + "lm75_48_temp") + print "Sensor A: " + string + " C" + + string = get_attr_value(sensors_path + "lm75_49_temp") + print "Sensor B: " + string + " C" + + return + +def get_voltage(): + print " " + nodes = sensors_nodes['fan_vol'] + types = sensors_type['fan_vol'] + for i in range(0,len(nodes)): + string = get_attr_value(sensors_path + nodes[i]) + print types[i] + ': ' + string + " V" + + return + +def init_fan(): + return + +def main(): + """ + Usage: %(scriptName)s command object + + command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + show : show all systen status + set : change board setting with fan|led|sfp + """ + + if len(sys.argv)<2: + print main.__doc__ + + for arg in sys.argv[1:]: + if arg == 'fan_init': + init_fan() + elif arg == 'get_sensors': + ver = get_attr_value(sensors_path + "fb_hw_version") + print 'HW Version: ' + ver + ver = get_attr_value(sensors_path + "fb_fw_version") + print 'SW Version: ' + ver + get_fan() + get_hwmon() + get_voltage() + elif arg == 'fan_set': + if len(sys.argv[1:])<1: + print main.__doc__ + else: + set_fan(sys.argv[1:]) + return + else: + print main.__doc__ + +if __name__ == "__main__": + main() diff --git a/platform/p4/SAI-P4-BM b/platform/p4/SAI-P4-BM new file mode 160000 index 000000000000..c763924affd4 --- /dev/null +++ b/platform/p4/SAI-P4-BM @@ -0,0 +1 @@ +Subproject commit c763924affd416df9c4d3e40d4f8ac1cb2be5fff diff --git a/platform/p4/docker-sonic-p4.mk b/platform/p4/docker-sonic-p4.mk new file mode 100644 index 000000000000..940b85ed5d2a --- /dev/null +++ b/platform/p4/docker-sonic-p4.mk @@ -0,0 +1,31 @@ +# docker image for p4 sonic docker image + +DOCKER_SONIC_P4 = docker-sonic-p4.gz +$(DOCKER_SONIC_P4)_PATH = $(PLATFORM_PATH)/docker-sonic-p4 +$(DOCKER_SONIC_P4)_DEPENDS += $(SWSS) \ + $(SYNCD) \ + $(P4_SWITCH) \ + $(REDIS_TOOLS) \ + $(REDIS_SERVER) \ + $(PYTHON_SWSSCOMMON) \ + $(PYTHON3_SWSSCOMMON) \ + $(LIBTEAMDCTL) \ + $(LIBTEAM_UTILS) \ + $(SONIC_DEVICE_DATA) \ + $(SONIC_UTILITIES_PY3) \ + $(IPROUTE2) + +# ifeq ($(ROUTING_STACK), quagga) +$(DOCKER_SONIC_P4)_DEPENDS += $(QUAGGA) +# else ifeq ($(ROUTING_STACK), frr) +# $(DOCKER_SONIC_P4)_DEPENDS += $(FRR) +# else +# $(DOCKER_SONIC_P4)_DEPENDS += $(GOBGP) +# endif + +$(DOCKER_SONIC_P4)_FILES += $(CONFIGDB_LOAD_SCRIPT) \ + $(ARP_UPDATE_SCRIPT) \ + $(ARP_UPDATE_VARS_TEMPLATE) + +$(DOCKER_SONIC_P4)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SONIC_P4) diff --git a/platform/p4/docker-sonic-p4/Dockerfile.j2 b/platform/p4/docker-sonic-p4/Dockerfile.j2 new file mode 100644 index 000000000000..90ff15472248 --- /dev/null +++ b/platform/p4/docker-sonic-p4/Dockerfile.j2 @@ -0,0 +1,94 @@ +FROM docker-config-engine + +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 + +COPY ["sonic-dev.gpg.key", "/etc/apt/"] +RUN apt-key add /etc/apt/sonic-dev.gpg.key +RUN echo "deb http://packages.microsoft.com/repos/sonic-dev/ jessie main" >> /etc/apt/sources.list +RUN apt-get update + +RUN apt-get install -y net-tools \ + arping \ + ethtool \ + tcpdump \ + ifupdown \ + jq \ + bridge-utils \ + python-ply \ + libqt5core5a \ + libqt5network5 \ + libboost-program-options1.55.0 \ + libboost-system1.55.0 \ + libboost-thread1.55.0 \ + libgmp10 \ + libjudydebian1 \ + libnanomsg0 \ + libdaemon0 \ + libjansson4 \ + libatomic1 \ + libjemalloc1 \ + liblua5.1-0 \ + lua-bitop \ + lua-cjson \ + openssh-client \ + openssh-server \ + libc-ares2 \ + iproute \ + libpython2.7 \ + grub2-common \ + bash-completion \ + libelf1 \ + libmnl0 \ + # For installing Python m2crypto package + # (these can be uninstalled after installation) + build-essential \ + python-dev \ + python3-dev \ + libssl-dev \ + swig \ + # For using Python m2crypto package + openssl + +RUN pip install setuptools +RUN pip install py2_ipaddress + +COPY \ +{% for deb in docker_sonic_p4_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_sonic_p4_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +## Clean up +RUN apt-get purge -y build-essential libssl-dev swig +RUN apt-get purge -y python-dev python3-dev +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +RUN sed -ri 's/^(save .*$)/# \1/g; \ + s/^daemonize yes$/daemonize no/; \ + s/^logfile .*$/logfile ""/; \ + s/^# syslog-enabled no$/syslog-enabled no/; \ + s/^# unixsocket/unixsocket/; \ + s/notify-keyspace-events ""/notify-keyspace-events AKE/; \ + s/^client-output-buffer-limit pubsub [0-9]+mb [0-9]+mb [0-9]+/client-output-buffer-limit pubsub 0 0 0/ \ + ' /etc/redis/redis.conf + +ADD port_config.ini /port_config.ini +COPY ["start.sh", "orchagent.sh", "config_bm.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/configdb-load.sh", "/usr/bin/"] +COPY ["files/arp_update", "/usr/bin"] +COPY ["files/arp_update_vars.j2", "/usr/share/sonic/templates/"] +RUN echo "docker-sonic-p4" > /etc/hostname +RUN touch /etc/quagga/zebra.conf + +ENTRYPOINT ["/bin/bash"] diff --git a/platform/p4/docker-sonic-p4/config_bm.sh b/platform/p4/docker-sonic-p4/config_bm.sh new file mode 100755 index 000000000000..25de26b4da74 --- /dev/null +++ b/platform/p4/docker-sonic-p4/config_bm.sh @@ -0,0 +1,4 @@ +simple_switch_CLI --pre SimplePreLAG < /usr/share/p4-sai-bm/bridge_default_config.txt +simple_switch_CLI < /usr/share/p4-sai-bm/bridge_default_config_mirror.txt +simple_switch_CLI --pre SimplePreLAG --thrift-port 9091 < /usr/share/p4-sai-bm/router_default_config.txt +simple_switch_CLI --thrift-port 9091 < /usr/share/p4-sai-bm/router_default_config_mirror.txt \ No newline at end of file diff --git a/platform/p4/docker-sonic-p4/orchagent.sh b/platform/p4/docker-sonic-p4/orchagent.sh new file mode 100755 index 000000000000..1975e44753f1 --- /dev/null +++ b/platform/p4/docker-sonic-p4/orchagent.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +SWSS_VARS_FILE=/usr/share/sonic/templates/swss_vars.j2 + +# Retrieve SWSS vars from sonic-cfggen +SWSS_VARS=$(sonic-cfggen -d -y /etc/sonic/sonic_version.yml -t $SWSS_VARS_FILE) || exit 1 + +MAC_ADDRESS=$(echo $SWSS_VARS | jq -r '.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 SsWW record files +mkdir -p /var/log/swss +ORCHAGENT_ARGS="-d /var/log/swss " + +# Set orchagent pop batch size to 8192 +ORCHAGENT_ARGS+="-b 8192 " + +# Set synchronous mode if it is enabled in CONFIG_DB +SYNC_MODE=$(echo $SWSS_VARS | jq -r '.synchronous_mode') +if [ "$SYNC_MODE" == "enable" ]; then + ORCHAGENT_ARGS+="-s " +fi + +# Set mac address +ORCHAGENT_ARGS+="-m $MAC_ADDRESS" + +exec /usr/bin/orchagent ${ORCHAGENT_ARGS} diff --git a/platform/p4/docker-sonic-p4/port_config.ini b/platform/p4/docker-sonic-p4/port_config.ini new file mode 100644 index 000000000000..2a88c4a7235b --- /dev/null +++ b/platform/p4/docker-sonic-p4/port_config.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 0 +Ethernet1 1 +Ethernet2 2 +Ethernet3 3 +Ethernet4 4 +Ethernet5 5 +Ethernet6 6 +Ethernet7 7 +Ethernet8 8 +Ethernet9 9 +Ethernet10 10 +Ethernet11 11 +Ethernet12 12 +Ethernet13 13 +Ethernet14 14 +Ethernet15 15 +Ethernet16 16 +Ethernet17 17 +Ethernet18 18 +Ethernet19 19 +Ethernet20 20 +Ethernet21 21 +Ethernet22 22 +Ethernet23 23 +Ethernet24 24 +Ethernet25 25 +Ethernet26 26 +Ethernet27 27 +Ethernet28 28 +Ethernet29 29 +Ethernet30 30 +Ethernet31 31 \ No newline at end of file diff --git a/platform/p4/docker-sonic-p4/sonic-dev.gpg.key b/platform/p4/docker-sonic-p4/sonic-dev.gpg.key new file mode 100644 index 000000000000..fb9a37901bc7 --- /dev/null +++ b/platform/p4/docker-sonic-p4/sonic-dev.gpg.key @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQENBFQ1bTIBCAC7oGfkv/ck0XsLuG8cdcSB2ISqxFAcBvH9BitEtxmpW2uhykKk +xY4rVD/4Uys1s3PF1/64QfPR+hYcewueOwz0ZAcLyFXXk4McICXaPq3NrLiWYKKX +UZLnrPzcrGZoW/kHDDp4OmBiDmT1PGvZlpuimwkMCusUzIr7Cbbp2dIy8MERL5tA +LcgLu3KL6clJ+aTW2jgepI1D7sTepOeGd7eRSb5njKg2M7k/93v/7MipZxiVtyXH +B74YiK6jSbst5JpuYsLa/Dqryvx7Xq3n53oif892pv3euTduo1fYw8Hgh/OOYdeT +c9WCj03KA1jCSFURjdrug0kR8BPlfjqtRLXFABEBAAG0JE1TIE9wZW4gVGVjaCA8 +aW50ZXJvcEBtaWNyb3NvZnQuY29tPokBOAQTAQIAIgUCVDVtMgIbAwYLCQgHAwIG +FQgCCQoLBBYCAwECHgECF4AACgkQsCxG30F6CJO1uAf/cmL68bM8YgF/61hkaY56 +LqrppUTJH/w4fKq47Pf6KfgSLvxfNU6soi2KHYRjIvTRx3tV4vUM5n2plaQg2s8V +/Epg4FeIRTk75YwiHAzLhLnp5cdUaTvC4j4mwxoB6j9Ty+fXJwQ0MvpDhIZb9vM4 +GXw/fEQHCT4f3gx4nReeqE+FB2wVHleX9+Lpodu98JyJTKJRBRHYLqy6S+/lyp2W +aBlsI1LOqBcx1uRK24U7duIpbYwIyrx0cafSruqR2GjVdu+imkhHyUn52VbzYhq1 +af0rqYiZ1VOamVOG0By8+hVyNa1MLc1K2uWGs0o5fDe9F5/swbvLHVXI+M50Vs+m +J7kBDQRUNW0yAQgAu7DkTVj0ZQC4F7bFivAwrdby8gCakTXOl1kcK622hjRJ8nam +aZeW+eADfLRsTmdUmXgZu1YWS5Gn2ZVngC8SGPUBT071+oRETCz4uNB7IimB9QfP +++orI6o2vmnVVsq5wWCbEdNU+TCVv1zjrYev5lwckkKpjHt6o8MNoX2DFuQymSyR +eZKaqhdKmcji4Ke7OIYqwgPjch3wxzE1b5gNOR/iwxWyjjOffZPLr/VhIfIJRs86 +dSXrwjHtEh810SKDLghHM0VAdY34nyC5ZZ61yhts5HtQDFK+9mNpH1mkc4gDBlgG +266pVvknumK6lPNm/osF/cpjWmEw24ypcQIvOQARAQABiQEfBBgBAgAJBQJUNW0y +AhsMAAoJELAsRt9BegiTMBUH/0sZ6gZy7mCTSAYT+NSXLFtGC2zNUVL80SWvfgYm +k9XPVI22MrefZfQ6M01RylyxtWXjRM8UoN8SDKWPpXumzJf831f/7om5zwutaG7b +tjDPYqRKJSbAIFZu2mN+uLrNQ2SV6XK7FoV0dtcrEX9S7RICb6i19D+70+Oh/qgU +R04H1jqS29XBzqAlIzdBoA+sYAwbOIJsSL3YyNQcUv3B5+5yR/bo/L8pnUJt6iuL +nWW+mi7r8gWPHDSrcdYq1TmmlOM7CwZPgWRZzkQPSeZz52Tt7IP47eyGJ09U4PIf +FtMH1ElL2UgHoA/F9Q88e7LkztaTqE59uXWbIYyuSMJVvRU= +=sb3d +-----END PGP PUBLIC KEY BLOCK----- diff --git a/platform/p4/docker-sonic-p4/start.sh b/platform/p4/docker-sonic-p4/start.sh new file mode 100755 index 000000000000..2da8fe2249fd --- /dev/null +++ b/platform/p4/docker-sonic-p4/start.sh @@ -0,0 +1,91 @@ +#!/bin/bash -e + +# generate configuration +[ -d /etc/sonic ] || mkdir -p /etc/sonic + +if ! ip link show eth0 &> /dev/null; then + ip link add eth0 type dummy +fi + +SYSTEM_MAC_ADDRESS=$(ip link show eth0 | grep ether | awk '{print $2}') +sonic-cfggen -a '{"DEVICE_METADATA":{"localhost": {"mac": "'$SYSTEM_MAC_ADDRESS'"}}}' --print-data > /etc/sonic/init_cfg.json + +if [ -f /etc/sonic/config_db.json ]; then + sonic-cfggen -j /etc/sonic/init_cfg.json -j /etc/sonic/config_db.json --print-data > /tmp/config_db.json + mv /tmp/config_db.json /etc/sonic/config_db.json +else + sonic-cfggen -j /etc/sonic/init_cfg.json --print-data > /etc/sonic/config_db.json +fi + +mkdir -p /etc/swss/config.d/ + +rm -f /var/run/rsyslogd.pid + +echo "Start rsyslogd" +supervisorctl start rsyslogd + +mkdir -p /var/run/redis + +echo "Start redis" +supervisorctl start redis-server + +echo "Veth Setup" +veth_setup.sh > /tmp/veth_setup.log + +echo "Start BM" +rm -rf bm_logs/bridge_log.* +rm -rf bm_logs/router_log.* +rm -rf log.txt +mkdir -p bm_logs +supervisorctl start bm_bridge +supervisorctl start bm_router + +sleep 10 +echo "BM Default config" +config_bm.sh > /tmp/config_bm.log + +/usr/bin/configdb-load.sh + +echo "Start syncd" +supervisorctl start syncd + +echo "Start orchagent" +supervisorctl start orchagent + +echo "Start portsyncd" +supervisorctl start portsyncd + +echo "Start neighsyncd" +supervisorctl start neighsyncd + +echo "Start fdbsyncd" +supervisorctl start fdbsyncd + +echo "Start teamsyncd" +supervisorctl start teamsyncd + +echo "Start fpmsyncd" +supervisorctl start fpmsyncd + +echo "Start intfmgrd" +supervisorctl start intfmgrd + +echo "Start vlanmgrd" +supervisorctl start vlanmgrd + +echo "Start zebra" +supervisorctl start zebra + +echo "Start bgpd" +supervisorctl start bgpd + +if [ -f /etc/swss/config.d/default_config.json ]; then + swssconfig /etc/swss/config.d/default_config.json +fi + +# Start arp_update when VLAN exists +VLAN=`sonic-cfggen -d -v 'VLAN.keys() | join(" ") if VLAN'` +if [ "$VLAN" != "" ]; then + echo "Start arp_update" + supervisorctl start arp_update +fi diff --git a/platform/p4/docker-sonic-p4/supervisord.conf b/platform/p4/docker-sonic-p4/supervisord.conf new file mode 100644 index 000000000000..a4026f61c140 --- /dev/null +++ b/platform/p4/docker-sonic-p4/supervisord.conf @@ -0,0 +1,141 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=false + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bm_router] +command=ip netns exec sw_net simple_switch -i 0@router_port1 -i 250@router_cpu_port --thrift-port 9091 --log-file bm_logs/router_log --log-flush --notifications-addr ipc:///tmp/bmv2-router-notifications.ipc /usr/share/p4-sai-bm/sai_router.json +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bm_bridge] +command=ip netns exec sw_net simple_switch -i 0@sw_port0 -i 1@sw_port1 -i 2@sw_port2 -i 3@sw_port3 -i 4@sw_port4 -i 5@sw_port5 -i 6@sw_port6 -i 7@sw_port7 -i 7@sw_port7 -i 8@sw_port8 -i 9@sw_port9 -i 10@sw_port10 -i 11@sw_port11 -i 12@sw_port12 -i 13@sw_port13 -i 14@sw_port14 -i 15@sw_port15 -i 16@sw_port16 -i 17@sw_port17 -i 18@sw_port18 -i 19@sw_port19 -i 20@sw_port20 -i 21@sw_port21 -i 22@sw_port22 -i 23@sw_port23 -i 24@sw_port24 -i 25@sw_port25 -i 26@sw_port26 -i 27@sw_port27 -i 28@sw_port28 -i 29@sw_port29 -i 30@sw_port30 -i 31@sw_port31 -i 250@cpu_port -i 251@router_port0 --log-file bm_logs/bridge_log --log-flush /usr/share/p4-sai-bm/sai_bridge.json & +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:redis-server] +command=/usr/bin/redis-server /etc/redis/redis.conf +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:syncd] +command=/usr/bin/syncd -u +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:orchagent] +command=/usr/bin/orchagent.sh +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:portsyncd] +command=/usr/bin/portsyncd +priority=6 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:neighsyncd] +command=/usr/bin/neighsyncd +priority=8 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:teamsyncd] +command=/usr/bin/teamsyncd +priority=9 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:vlanmgrd] +command=/usr/bin/vlanmgrd +priority=10 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:intfmgrd] +command=/usr/bin/intfmgrd +priority=11 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:zebra] +command=/usr/lib/quagga/zebra -A 127.0.0.1 +priority=12 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bgpd] +command=/usr/lib/quagga/bgpd -A 127.0.0.1 -F +priority=13 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:fpmsyncd] +command=/usr/bin/fpmsyncd +priority=14 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:arp_update] +command=/usr/bin/arp_update +priority=15 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog + +[program:fdbsyncd] +command=/usr/bin/fdbsyncd +priority=16 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/p4/libsaithrift-dev.mk b/platform/p4/libsaithrift-dev.mk new file mode 100644 index 000000000000..68aec8ec3f2e --- /dev/null +++ b/platform/p4/libsaithrift-dev.mk @@ -0,0 +1,7 @@ +# libsaithrift-dev package + +LIBSAITHRIFT_DEV_P4 = libsaithrift-dev_1.0.4_amd64.deb +$(LIBSAITHRIFT_DEV_P4)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV_P4)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(THRIFT_COMPILER) $(P4_SWITCH) +$(LIBSAITHRIFT_DEV_P4)_RDEPENDS += $(LIBTHRIFT) $(P4_SWITCH) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV_P4) diff --git a/platform/p4/p4-bmv.mk b/platform/p4/p4-bmv.mk new file mode 100644 index 000000000000..affb0d5ac824 --- /dev/null +++ b/platform/p4/p4-bmv.mk @@ -0,0 +1,7 @@ +# p4 bmv package + +P4_BMV = sai-p4-bm_1.0.0_amd64.deb +$(P4_BMV)_DEPENDS += $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(P4C_BM) +$(P4_BMV)_RDEPENDS += $(LIBTHRIFT) $(PYTHON_THRIFT) $(THRIFT_COMPILER) +$(P4_BMV)_SRC_PATH = $(PLATFORM_PATH)/SAI-P4-BM/p4-switch +SONIC_DPKG_DEBS += $(P4_BMV) diff --git a/platform/p4/p4-hlir.mk b/platform/p4/p4-hlir.mk new file mode 100644 index 000000000000..61307c7ff79a --- /dev/null +++ b/platform/p4/p4-hlir.mk @@ -0,0 +1,9 @@ +# p4 bmv package + +P4_HLIR_V1_1 = python-p4-hlir-v1-1_1.1.7-1_all.deb +$(P4_HLIR_V1_1)_SRC_PATH = $(PLATFORM_PATH)/p4-hlir/p4-hlir-v1.1 +SONIC_PYTHON_STDEB_DEBS += $(P4_HLIR_V1_1) + +P4_HLIR = python-p4-hlir_0.9.36-1_all.deb +$(P4_HLIR)_SRC_PATH = $(PLATFORM_PATH)/p4-hlir/p4-hlir +SONIC_PYTHON_STDEB_DEBS += $(P4_HLIR) diff --git a/platform/p4/p4-hlir/p4-hlir b/platform/p4/p4-hlir/p4-hlir new file mode 160000 index 000000000000..0ab8e58f8a92 --- /dev/null +++ b/platform/p4/p4-hlir/p4-hlir @@ -0,0 +1 @@ +Subproject commit 0ab8e58f8a92ee469235028430795088af9cda77 diff --git a/platform/p4/p4-hlir/p4-hlir-v1.1 b/platform/p4/p4-hlir/p4-hlir-v1.1 new file mode 160000 index 000000000000..fdee55e2567f --- /dev/null +++ b/platform/p4/p4-hlir/p4-hlir-v1.1 @@ -0,0 +1 @@ +Subproject commit fdee55e2567fe65463f328d70558b5079894b420 diff --git a/platform/p4/p4-switch.mk b/platform/p4/p4-switch.mk new file mode 100644 index 000000000000..fb092fa2c5f3 --- /dev/null +++ b/platform/p4/p4-switch.mk @@ -0,0 +1,7 @@ +# p4 sai adapter package + +P4_SWITCH = p4-sai-adapter_0.1-0_amd64.deb +$(P4_SWITCH)_DEPENDS += $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(P4_BMV) +$(P4_SWITCH)_RDEPENDS += $(LIBTHRIFT) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(P4_BMV) +$(P4_SWITCH)_SRC_PATH = $(PLATFORM_PATH)/SAI-P4-BM/sai_adapter +SONIC_DPKG_DEBS += $(P4_SWITCH) diff --git a/platform/p4/p4c-bm.mk b/platform/p4/p4c-bm.mk new file mode 100644 index 000000000000..1982ee359212 --- /dev/null +++ b/platform/p4/p4c-bm.mk @@ -0,0 +1,7 @@ +# p4c bm package + +P4C_BM = python-p4c-bm_1.0.0-5415c416-1_all.deb +$(P4C_BM)_SRC_PATH = $(PLATFORM_PATH)/p4c-bm/p4c-bm +$(P4C_BM)_DEPENDS += $(TENJIN) $(P4_HLIR) $(P4_HLIR_V1_1) +$(P4C_BM)_RDEPENDS += $(TENJIN) $(P4_HLIR) $(P4_HLIR_V1_1) +SONIC_PYTHON_STDEB_DEBS += $(P4C_BM) diff --git a/platform/p4/p4c-bm/p4c-bm b/platform/p4/p4c-bm/p4c-bm new file mode 160000 index 000000000000..5415c4160aff --- /dev/null +++ b/platform/p4/p4c-bm/p4c-bm @@ -0,0 +1 @@ +Subproject commit 5415c4160aff025f27fe45301c62aa9aeb4bab40 diff --git a/platform/p4/rules.mk b/platform/p4/rules.mk new file mode 100644 index 000000000000..b33b04f43d41 --- /dev/null +++ b/platform/p4/rules.mk @@ -0,0 +1,17 @@ +# include $(PLATFORM_PATH)/p4-softswitch.mk +include $(PLATFORM_PATH)/tenjin.mk +include $(PLATFORM_PATH)/p4-hlir.mk +include $(PLATFORM_PATH)/p4c-bm.mk +# include $(PLATFORM_PATH)/p4-sai-bm.mk +include $(PLATFORM_PATH)/p4-bmv.mk +include $(PLATFORM_PATH)/p4-switch.mk +include $(PLATFORM_PATH)/docker-sonic-p4.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk + +SONIC_ALL += $(DOCKER_SONIC_P4) + +$(SYNCD)_DEPENDS += $(P4_SWITCH) +ifeq ($(ENABLE_SYNCD_RPC),y) +$(SYNCD)_DEPENDS += $(LIBSAITHRIFT_DEV_P4) +endif +$(SYNCD)_RDEPENDS += $(P4_SWITCH) diff --git a/platform/p4/tenjin.mk b/platform/p4/tenjin.mk new file mode 100644 index 000000000000..a9f38437d972 --- /dev/null +++ b/platform/p4/tenjin.mk @@ -0,0 +1,5 @@ +# tenjin package + +TENJIN = python-tenjin_1.1.1-1_all.deb +$(TENJIN)_SRC_PATH = $(PLATFORM_PATH)/tenjin +SONIC_MAKE_DEBS += $(TENJIN) diff --git a/platform/p4/tenjin/Makefile b/platform/p4/tenjin/Makefile new file mode 100644 index 000000000000..83b27d390abc --- /dev/null +++ b/platform/p4/tenjin/Makefile @@ -0,0 +1,19 @@ +SHELL = /bin/bash +.ONESHELL: + +TENJIN_VERSION = 1.1.1 +TENJIN_VERSION_FULL = $(TENJIN_VERSION)-1 + +MAIN_TARGET = python-tenjin_$(TENJIN_VERSION_FULL)_all.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf Tenjin-$(TENJIN_VERSION) + + wget -nc https://pypi.python.org/packages/source/T/Tenjin/Tenjin-$(TENJIN_VERSION).tar.gz + tar xzf Tenjin-$(TENJIN_VERSION).tar.gz + + pushd Tenjin-$(TENJIN_VERSION) + python setup.py --command-packages=stdeb.command bdist_deb + popd + + mv Tenjin-$(TENJIN_VERSION)/deb_dist/$* $(DEST)/ diff --git a/platform/pddf/README.md b/platform/pddf/README.md new file mode 100644 index 000000000000..b46bb6780b1e --- /dev/null +++ b/platform/pddf/README.md @@ -0,0 +1,19 @@ + Platform Driver Development Framework (PDDF) is part of SONiC Platform Development Kit (PDK) which optimizes the platform developement. + + SONiC PDDF (Platform driver development framework) supports the following HW devices on a given platform: + + - Fan + - PSU + - System EEPROM + - CPLD + - CPLDMUX + - GPIO + - Optic Transceivers + - System LED control via CPLD + - System Status Registers in CPLD + - Temp Sensors + + This folder for the PDDF consists of the following: + + - PDDF python utility scripts + - Generic PDDF HW device drivers in kernel space diff --git a/platform/pddf/i2c/Makefile b/platform/pddf/i2c/Makefile new file mode 100644 index 000000000000..1486370b5005 --- /dev/null +++ b/platform/pddf/i2c/Makefile @@ -0,0 +1 @@ +subdir-m := modules diff --git a/platform/pddf/i2c/debian/changelog b/platform/pddf/i2c/debian/changelog new file mode 100755 index 000000000000..505184c1fd80 --- /dev/null +++ b/platform/pddf/i2c/debian/changelog @@ -0,0 +1,12 @@ +sonic-pddf-platform-modules (1.1) unstable; urgency=low + + * Enhancing PDDF: Added support for cpldmux, gpio and some extra attributes + + -- Broadcom Wed, 10 Jun 2020 10:10:10 -0800 + +sonic-pddf-platform-modules (1.0) unstable; urgency=low + + * Basic tempelate for PDDF + * Initial release + + -- Broadcom Wed, 26 Jun 2019 10:10:10 -0800 diff --git a/platform/pddf/i2c/debian/compat b/platform/pddf/i2c/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/pddf/i2c/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/pddf/i2c/debian/control b/platform/pddf/i2c/debian/control new file mode 100755 index 000000000000..afd96c3d260a --- /dev/null +++ b/platform/pddf/i2c/debian/control @@ -0,0 +1,12 @@ +Source: sonic-pddf-platform-modules +Section: main +Priority: extra +Maintainer: Broadcom +Build-Depends: debhelper (>= 9), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-pddf +Architecture: amd64 +Description: kernel modules for platform devices such as psu, fan, sfp, led + + diff --git a/platform/pddf/i2c/debian/rules b/platform/pddf/i2c/debian/rules new file mode 100755 index 000000000000..35fca9a784ad --- /dev/null +++ b/platform/pddf/i2c/debian/rules @@ -0,0 +1,75 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-pddf +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= client cpld cpld/driver cpldmux cpldmux/driver fan fan/driver fan/vendor_api mux gpio led psu psu/driver sysstatus xcvr xcvr/driver +MODULE_DIR:= modules +UTILS_DIR := utils +SERVICE_DIR := service + +%: + echo =================RUNNING $@============= + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + echo ============CLEANING================= + dh_testdir + dh_testroot + dh_clean + make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR) clean + +build: + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR); \ + $(PYTHON) $(MOD_SRC_DIR)/setup.py build; \ + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +binary-indep: + dh_testdir + dh_installdirs + dh_installdirs -p$(PACKAGE_PRE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME) usr/local/bin; \ + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + cp $(MOD_SRC_DIR)/$(MODULE_DIR)/$${mod}/*.ko debian/$(PACKAGE_PRE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + done) ; \ + cp -r $(MOD_SRC_DIR)/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)/usr/local/bin/; \ + $(PYTHON) $(MOD_SRC_DIR)/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME) --install-layout=deb; + + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/pddf/i2c/modules/Makefile b/platform/pddf/i2c/modules/Makefile new file mode 100644 index 000000000000..67d3726c3202 --- /dev/null +++ b/platform/pddf/i2c/modules/Makefile @@ -0,0 +1 @@ +subdir-m := client cpld cpldmux xcvr mux gpio psu fan led sysstatus diff --git a/platform/pddf/i2c/modules/client/Makefile b/platform/pddf/i2c/modules/client/Makefile new file mode 100644 index 000000000000..c841a144f2db --- /dev/null +++ b/platform/pddf/i2c/modules/client/Makefile @@ -0,0 +1,3 @@ +obj-m:= pddf_client_module.o + +ccflags-y := -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/client/pddf_client_module.c b/platform/pddf/i2c/modules/client/pddf_client_module.c new file mode 100644 index 000000000000..f36596dbe970 --- /dev/null +++ b/platform/pddf/i2c/modules/client/pddf_client_module.c @@ -0,0 +1,330 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A pddf kernel module to create access-data attributes for client creation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" + + + +NEW_DEV_ATTR pddf_data={0}; +EXPORT_SYMBOL(pddf_data); +int showall = 0; + + +/* CLIENT CREATION DATA ATTR LIST */ +PDDF_DATA_ATTR(i2c_type, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&pddf_data.i2c_type, NULL); +PDDF_DATA_ATTR(i2c_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&pddf_data.i2c_name, NULL); +PDDF_DATA_ATTR(parent_bus, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_data.parent_bus, NULL); +PDDF_DATA_ATTR(dev_type, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&pddf_data.dev_type, NULL); +PDDF_DATA_ATTR(dev_id, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&pddf_data.dev_id, NULL); +PDDF_DATA_ATTR(dev_addr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_data.dev_addr, NULL); +PDDF_DATA_ATTR(error, S_IRUGO, show_error_code, NULL, PDDF_INT_DEC, sizeof(int), (void*)&pddf_data.error, (void*)&pddf_data.errstr); + + + +static struct attribute *pddf_clients_data_attributes[] = { + &attr_i2c_type.dev_attr.attr, + &attr_i2c_name.dev_attr.attr, + &attr_parent_bus.dev_attr.attr, + &attr_dev_type.dev_attr.attr, + &attr_dev_id.dev_attr.attr, + &attr_dev_addr.dev_attr.attr, + &attr_error.dev_attr.attr, + NULL +}; + +struct attribute_group pddf_clients_data_group = { + .attrs = pddf_clients_data_attributes, +}; +EXPORT_SYMBOL(pddf_clients_data_group); + + + +PDDF_DATA_ATTR(showall, S_IRUGO, show_all_devices, NULL, PDDF_INT_DEC, sizeof(int), (void *)&showall, NULL); + +static struct attribute *pddf_allclients_data_attributes[] = { + &attr_showall.dev_attr.attr, + NULL +}; +struct attribute_group pddf_allclients_data_group = { + .attrs = pddf_allclients_data_attributes, +}; + + + + + +void set_attr_data(void * ptr) +{ + pddf_data.data=ptr; +} + +ssize_t show_all_devices(struct device *dev, struct device_attribute *da, char *buf) +{ + int ret = 0; + PDDF_ATTR *pptr = (PDDF_ATTR *)da; + int *ptr = (int *)pptr->addr; + + traverse_device_table(); + ret = sprintf(buf, "Total Devices: %d\n", *ptr); + + return ret; +} + +ssize_t show_error_code(struct device *dev, struct device_attribute *da, char *buf) +{ + int ret = 0; + PDDF_ATTR *pptr = (PDDF_ATTR *)da; + NEW_DEV_ATTR *ptr = ( NEW_DEV_ATTR *)pptr->addr; + + ret = sprintf(buf, "0x%x:%s\n", (ptr->error), ptr->errstr); + + return ret; +} + +void set_error_code(int ecode, char *estr) +{ + pddf_data.error = ecode; + strcpy(pddf_data.errstr, estr); + return; +} +EXPORT_SYMBOL(set_error_code); + +ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, char *buf) +{ + int ret = 0; + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + /*pddf_dbg(KERN_ERR "[ READ ] DATA ATTR PTR TYPE:%d, ADDR=%p\n", ptr->type, ptr->addr);*/ + switch(ptr->type) + { + case PDDF_CHAR: + ret = sprintf(buf, "%s\n", ptr->addr); + break; + case PDDF_UCHAR: + ret = sprintf(buf, "%d\n", *(unsigned char*)(ptr->addr)); + break; + case PDDF_INT_DEC: + ret = sprintf(buf, "%d\n", *(int*)(ptr->addr)); + break; + case PDDF_INT_HEX: + ret = sprintf(buf, "0x%x\n", *(int*)(ptr->addr)); + break; + case PDDF_USHORT: + ret = sprintf(buf, "0x%x\n", *(unsigned short *)(ptr->addr)); + break; + case PDDF_UINT32: + ret = sprintf(buf, "0x%x\n", *(uint32_t *)(ptr->addr)); + break; + default: + break; + } + + return ret; +} +EXPORT_SYMBOL(show_pddf_data); + +ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int ret = 0, num = 0; + + + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + + switch(ptr->type) + { + case PDDF_CHAR: + strncpy(ptr->addr, buf, strlen(buf)-1); // to discard newline char form buf + ptr->addr[strlen(buf)-1] = '\0'; + break; + case PDDF_UCHAR: + ret = kstrtoint(buf,10,&num); + if (ret==0) + *(unsigned char *)(ptr->addr) = (unsigned char)num; + break; + case PDDF_INT_DEC: + ret = kstrtoint(buf,10,&num); + if (ret==0) + *(int *)(ptr->addr) = num; + break; + case PDDF_INT_HEX: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(int *)(ptr->addr) = num; + break; + case PDDF_USHORT: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(unsigned short *)(ptr->addr) = (unsigned short)num; + break; + case PDDF_UINT32: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(uint32_t *)(ptr->addr) = (uint32_t)num; + break; + default: + break; + } + + return count; +} +EXPORT_SYMBOL(store_pddf_data); + + + +DEFINE_HASHTABLE(htable, 8); + +int get_hash(char *name) +{ + int i=0; + int hash=0; + for(i=0; iname, name); + hdev->data = ptr; + pddf_dbg(CLIENT, KERN_ERR "%s: Adding ptr 0x%p to the hash table\n", __FUNCTION__, ptr); + hash_add(htable, &hdev->node, get_hash(hdev->name)); +} +EXPORT_SYMBOL(add_device_table); + +void* get_device_table(char *name) +{ + PDEVICE *dev=NULL; + int i=0; + + hash_for_each(htable, i, dev, node) { + if(strcmp(dev->name, name)==0) { + return (void *)dev->data; + } + } + + return NULL; +} +EXPORT_SYMBOL(get_device_table); + +void delete_device_table(char *name) +{ + PDEVICE *dev=NULL; + int i=0; + + hash_for_each(htable, i, dev, node) { + if(strcmp(dev->name, name)==0) { + pddf_dbg(CLIENT, KERN_ERR "found entry to delete: %s 0x%p\n", dev->name, dev->data); + hash_del(&(dev->node)); + } + } + return; +} +EXPORT_SYMBOL(delete_device_table); + +void traverse_device_table(void ) +{ + PDEVICE *dev=NULL; + int i=0; + hash_for_each(htable, i, dev, node) { + pddf_dbg(CLIENT, KERN_ERR "Entry[%d]: %s : 0x%p\n", i, dev->name, dev->data); + } + showall = i; +} +EXPORT_SYMBOL(traverse_device_table); + +struct kobject *device_kobj; +static struct kobject *pddf_kobj; + +struct kobject *get_device_i2c_kobj(void) +{ + return device_kobj; +} + +EXPORT_SYMBOL(get_device_i2c_kobj); + +int __init pddf_data_init(void) +{ + int ret = 0; + + + pddf_dbg(CLIENT, "PDDF_DATA MODULE.. init\n"); + + pddf_kobj = kobject_create_and_add("pddf", kernel_kobj); + if(!pddf_kobj) { + return -ENOMEM; + } + device_kobj = kobject_create_and_add("devices", pddf_kobj); + if(!device_kobj) { + return -ENOMEM; + } + + init_device_table(); + + ret = sysfs_create_group(device_kobj, &pddf_allclients_data_group); + if (ret) + { + kobject_put(device_kobj); + return ret; + } + pddf_dbg(CLIENT, "CREATED PDDF ALLCLIENTS CREATION SYSFS GROUP\n"); + + + + return ret; +} + +void __exit pddf_data_exit(void) +{ + + pddf_dbg(CLIENT, "PDDF_DATA MODULE.. exit\n"); + sysfs_remove_group(device_kobj, &pddf_allclients_data_group); + + kobject_put(device_kobj); + kobject_put(pddf_kobj); + pddf_dbg(CLIENT, KERN_ERR "%s: Removed the kernle object for 'pddf' and 'device' \n", __FUNCTION__); + return; +} + +module_init(pddf_data_init); +module_exit(pddf_data_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("pddf data"); +MODULE_LICENSE("GPL"); + diff --git a/platform/pddf/i2c/modules/cpld/Makefile b/platform/pddf/i2c/modules/cpld/Makefile new file mode 100644 index 000000000000..c6182ef4f93d --- /dev/null +++ b/platform/pddf/i2c/modules/cpld/Makefile @@ -0,0 +1,4 @@ +subdir-m := driver +obj-m := pddf_cpld_module.o + +CFLAGS_$(obj-m):= -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/cpld/driver/Makefile b/platform/pddf/i2c/modules/cpld/driver/Makefile new file mode 100644 index 000000000000..42704c2cfaec --- /dev/null +++ b/platform/pddf/i2c/modules/cpld/driver/Makefile @@ -0,0 +1,5 @@ +TARGET = pddf_cpld_driver +obj-m := $(TARGET).o + + +ccflags-y := -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/cpld/driver/pddf_cpld_driver.c b/platform/pddf/i2c/modules/cpld/driver/pddf_cpld_driver.c new file mode 100755 index 000000000000..a34c370b9af1 --- /dev/null +++ b/platform/pddf/i2c/modules/cpld/driver/pddf_cpld_driver.c @@ -0,0 +1,230 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A pddf kernel driver module for CPLD + */ + +#include +#include +#include +#include +#include +#include "pddf_cpld_defs.h" + +extern PDDF_CPLD_DATA pddf_cpld_data; + + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + //hw_preaccess_func_cpld_mux_default((uint32_t)cpld_addr, NULL); + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(board_i2c_cpld_read); + +int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(board_i2c_cpld_write); + +ssize_t regval_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int len = 0; + struct i2c_client *client = to_i2c_client(dev); + + mutex_lock(&pddf_cpld_data.cpld_lock); + // Put code here to read the register value and print it + if (pddf_cpld_data.reg_addr!=0) + len = sprintf(buf, "0x%2.2x\n", board_i2c_cpld_read(client->addr, pddf_cpld_data.reg_addr)); + else + len = sprintf(buf, "xx\n"); + + mutex_unlock(&pddf_cpld_data.cpld_lock); + return len; +} + +static DEVICE_ATTR_RO(regval); + +static struct attribute *cpld_attrs[] = { + &dev_attr_regval.attr, + NULL, +}; + +static struct attribute_group cpld_attribute_group = { + .attrs = cpld_attrs, +}; + + + + +/* Addresses scanned for board_i2c_cpld + */ +static const unsigned short normal_i2c[] = { 0x31, 0x32, 0x33, 0x35, 0x60, 0x61, 0x62, 0x64, I2C_CLIENT_END }; + +static void board_i2c_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void board_i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static int board_i2c_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); + status = -EIO; + goto exit; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld_attribute_group); + if (status) { + goto exit; + } + + dev_dbg(&client->dev, "chip found\n"); + board_i2c_cpld_add_client(client); + + return 0; + +exit: + return status; +} + +static int board_i2c_cpld_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &cpld_attribute_group); + board_i2c_cpld_remove_client(client); + + return 0; +} + +static const struct i2c_device_id board_i2c_cpld_id[] = { + { "i2c_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, board_i2c_cpld_id); + +static struct i2c_driver board_i2c_cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "i2c_cpld", + }, + .probe = board_i2c_cpld_probe, + .remove = board_i2c_cpld_remove, + .id_table = board_i2c_cpld_id, + .address_list = normal_i2c, +}; + +static int __init board_i2c_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&board_i2c_cpld_driver); +} + +static void __exit board_i2c_cpld_exit(void) +{ + i2c_del_driver(&board_i2c_cpld_driver); +} + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("board_i2c_cpld driver"); +MODULE_LICENSE("GPL"); + +module_init(board_i2c_cpld_init); +module_exit(board_i2c_cpld_exit); diff --git a/platform/pddf/i2c/modules/cpld/pddf_cpld_module.c b/platform/pddf/i2c/modules/cpld/pddf_cpld_module.c new file mode 100644 index 000000000000..af15e390265f --- /dev/null +++ b/platform/pddf/i2c/modules/cpld/pddf_cpld_module.c @@ -0,0 +1,219 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel module to create I2C client for a CPLD + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_cpld_defs.h" + +PDDF_CPLD_DATA pddf_cpld_data={0}; +EXPORT_SYMBOL(pddf_cpld_data); + +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t store_pddf_cpld_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t show_pddf_cpld_data(struct device *dev, struct device_attribute *da, char *buf); + +extern void *get_device_table(char *name); +extern void delete_device_table(char *name); + + +/* MUX CLIENT DATA */ +PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, NULL, (void*)&pddf_data); +PDDF_DATA_ATTR(reg_addr, S_IWUSR|S_IRUGO, show_pddf_cpld_data, store_pddf_cpld_data, PDDF_USHORT, sizeof(unsigned short), (void*)&pddf_cpld_data.reg_addr, NULL); + + + +static struct attribute *cpld_attributes[] = { + &attr_dev_ops.dev_attr.attr, + &attr_reg_addr.dev_attr.attr, + NULL +}; + +static const struct attribute_group pddf_cpld_client_data_group = { + .attrs = cpld_attributes, +}; + + +static ssize_t store_pddf_cpld_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int ret = 0; + int num = 0; + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + + ret = kstrtoint(buf,16,&num); + if (ret==0) + { + mutex_lock(&pddf_cpld_data.cpld_lock); + *(unsigned short *)(ptr->addr) = (unsigned short)num; + mutex_unlock(&pddf_cpld_data.cpld_lock); + pddf_dbg(CPLD, KERN_ERR "Stored value: 0x%x, num: 0x%x\n", *(int*)(ptr->addr), num); + } + + return count; +} +EXPORT_SYMBOL(store_pddf_cpld_data); + +ssize_t show_pddf_cpld_data(struct device *dev, struct device_attribute *da, char *buf) +{ + int ret = 0; + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + pddf_dbg(CPLD, KERN_ERR "[ READ ] DATA ATTR PTR TYPE:%d, ADDR=%p\n", ptr->type, ptr->addr); + + mutex_lock(&pddf_cpld_data.cpld_lock); + ret = sprintf(buf, "0x%x\n", *(unsigned short *)(ptr->addr)); + mutex_unlock(&pddf_cpld_data.cpld_lock); + + return ret; +} +EXPORT_SYMBOL(show_pddf_cpld_data); + +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + NEW_DEV_ATTR *device_ptr = (NEW_DEV_ATTR *)(ptr->data); + struct i2c_adapter *adapter; + static struct i2c_board_info board_info; + struct i2c_client *client_ptr; + + if (strncmp(buf, "add", strlen(buf)-1)==0) + { + adapter = i2c_get_adapter(device_ptr->parent_bus); + + if (strncmp(device_ptr->dev_type, "i2c_cpld", strlen("i2c_cpld"))==0) + { + board_info = (struct i2c_board_info) { + .platform_data = (void *)NULL, + }; + + board_info.addr = device_ptr->dev_addr; + strcpy(board_info.type, device_ptr->dev_type); + + /*pddf_dbg(KERN_ERR "Creating a client %s on 0x%x, platform_data 0x%x\n", board_info.type, board_info.addr, board_info.platform_data);*/ + client_ptr = i2c_new_device(adapter, &board_info); + + if (client_ptr != NULL) { + i2c_put_adapter(adapter); + pddf_dbg(CPLD, KERN_ERR "Created %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr); + add_device_table(device_ptr->i2c_name, (void*)client_ptr); + } + else { + i2c_put_adapter(adapter); + goto free_data; + } + + } + else + { + printk(KERN_ERR "%s: Unsupported type of cpld - unable to add i2c client\n", __FUNCTION__); + } + } + else if (strncmp(buf, "delete", strlen(buf)-1)==0) + { + /*Get the i2c_client handle for the created client*/ + client_ptr = (struct i2c_client *)get_device_table(device_ptr->i2c_name); + if (client_ptr) + { + pddf_dbg(CPLD, KERN_ERR "Removing %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr); + i2c_unregister_device(client_ptr); + delete_device_table(device_ptr->i2c_name); + } + else + { + printk(KERN_ERR "Unable to get the client handle for %s\n", device_ptr->i2c_name); + } + } + else + { + printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf); + } + +free_data: + /*TODO: free the device_ptr->data is dynamically allocated*/ + memset(device_ptr, 0 , sizeof(NEW_DEV_ATTR)); + + return count; +} + + +static struct kobject *cpld_kobj; + +int __init cpld_data_init(void) +{ + struct kobject *device_kobj; + int ret = 0; + + + pddf_dbg(CPLD, "CPLD_DATA MODULE.. init\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + cpld_kobj = kobject_create_and_add("cpld", device_kobj); + if(!cpld_kobj) + return -ENOMEM; + + + ret = sysfs_create_group(cpld_kobj, &pddf_clients_data_group); + if (ret) + { + kobject_put(cpld_kobj); + return ret; + } + pddf_dbg(CPLD, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n"); + + mutex_init(&pddf_cpld_data.cpld_lock); + + ret = sysfs_create_group(cpld_kobj, &pddf_cpld_client_data_group); + if (ret) + { + sysfs_remove_group(cpld_kobj, &pddf_clients_data_group); + kobject_put(cpld_kobj); + return ret; + } + pddf_dbg(CPLD, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n"); + return ret; +} + +void __exit cpld_data_exit(void) +{ + pddf_dbg(CPLD, "CPLD_DATA MODULE.. exit\n"); + sysfs_remove_group(cpld_kobj, &pddf_cpld_client_data_group); + sysfs_remove_group(cpld_kobj, &pddf_clients_data_group); + kobject_put(cpld_kobj); + pddf_dbg(CPLD, KERN_ERR "%s: Removed the kobjects for 'cpld'\n",__FUNCTION__); + return; +} + +module_init(cpld_data_init); +module_exit(cpld_data_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("cpld platform data"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/modules/cpldmux/Makefile b/platform/pddf/i2c/modules/cpldmux/Makefile new file mode 100644 index 000000000000..53816b98f750 --- /dev/null +++ b/platform/pddf/i2c/modules/cpldmux/Makefile @@ -0,0 +1,4 @@ +subdir-m := driver +obj-m := pddf_cpldmux_module.o + +CFLAGS_$(obj-m):= -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/cpldmux/driver/Makefile b/platform/pddf/i2c/modules/cpldmux/driver/Makefile new file mode 100644 index 000000000000..2c6aa6e60eea --- /dev/null +++ b/platform/pddf/i2c/modules/cpldmux/driver/Makefile @@ -0,0 +1,4 @@ +TARGET = pddf_cpldmux_driver +obj-m := $(TARGET).o + +ccflags-y := -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/cpldmux/driver/pddf_cpldmux_driver.c b/platform/pddf/i2c/modules/cpldmux/driver/pddf_cpldmux_driver.c new file mode 100755 index 000000000000..c9df1a60c1af --- /dev/null +++ b/platform/pddf/i2c/modules/cpldmux/driver/pddf_cpldmux_driver.c @@ -0,0 +1,209 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * A pddf kernel driver module for CPLDMUX + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_cpldmux_defs.h" + +extern PDDF_CPLDMUX_DATA pddf_cpldmux_data; + +/* Users may overwrite these select and delsect functions as per their requirements + * by overwriting them in custom driver + */ +PDDF_CPLDMUX_OPS pddf_cpldmux_ops = { + .select = pddf_cpldmux_select_default, + .deselect = NULL, /* pddf_cpldmux_deselct_default */ +}; +EXPORT_SYMBOL(pddf_cpldmux_ops); + + +/* NOTE: Never use i2c_smbus_write_byte_data() or i2c_smbus_xfer() since these operations + * locks the parent bus which might lead to mutex deadlock. + */ +static int cpldmux_byte_write(struct i2c_client *client, u8 regaddr, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); +} + +int pddf_cpldmux_select_default(struct i2c_mux_core *muxc, uint32_t chan) +{ + PDDF_CPLDMUX_PRIV_DATA *private = i2c_mux_priv(muxc); + PDDF_CPLDMUX_PDATA *pdata = NULL; + PDDF_CPLDMUX_CHAN_DATA *sdata = NULL; + int ret = 0; + + /* Select the chan_data based upon the chan */ + pdata = &private->data; + if (chan>=pdata->num_chan) + { + printk(KERN_ERR "%s: wrong channel number %d, supported channels %d\n",__FUNCTION__, chan, pdata->num_chan); + return 0; + } + + if ( (pdata->chan_cache!=1) || (private->last_chan!=chan) ) + { + sdata = &pdata->chan_data[chan]; + pddf_dbg(CPLDMUX, KERN_ERR "%s: Writing 0x%x at 0x%x offset of cpld 0x%x to enable chan %d\n", __FUNCTION__, sdata->cpld_sel, sdata->cpld_offset, sdata->cpld_devaddr, chan); + ret = cpldmux_byte_write(pdata->cpld, sdata->cpld_offset, (uint8_t)(sdata->cpld_sel & 0xff)); + private->last_chan = chan; + } + + return ret; +} + +int pddf_cpldmux_deselect_default(struct i2c_mux_core *muxc, uint32_t chan) +{ + PDDF_CPLDMUX_PRIV_DATA *private = i2c_mux_priv(muxc); + PDDF_CPLDMUX_PDATA *pdata = NULL; + PDDF_CPLDMUX_CHAN_DATA *sdata = NULL; + int ret = 0; + + /* Select the chan_data based upon the chan */ + pdata = &private->data; + if (chan>=pdata->num_chan) + { + printk(KERN_ERR "%s: wrong channel number %d, supported channels %d\n",__FUNCTION__, chan, pdata->num_chan); + return 0; + } + sdata = &pdata->chan_data[chan]; + + pddf_dbg(CPLDMUX, KERN_ERR "%s: Writing 0x%x at 0x%x offset of cpld 0x%x to disable chan %d", __FUNCTION__, sdata->cpld_desel, sdata->cpld_offset, sdata->cpld_devaddr, chan); + ret = cpldmux_byte_write(pdata->cpld, sdata->cpld_offset, (uint8_t)(sdata->cpld_desel)); + return ret; +} + +static int cpld_mux_probe(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc; + PDDF_CPLDMUX_PRIV_DATA *private; + PDDF_CPLDMUX_PDATA *pdata; + struct i2c_adapter *adap; + int i, ret, ndev; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "CPLDMUX platform data not found\n"); + return -ENODEV; + } + private = (PDDF_CPLDMUX_PRIV_DATA *)kzalloc(sizeof(PDDF_CPLDMUX_PRIV_DATA) , GFP_KERNEL); + if (!private) { + printk(KERN_ERR "Failed to allocate memory for priv data\n"); + return -ENOMEM; + } + + private->last_chan = 0xff; /*Giving imaginary high value so that proper channel is selected at first iteration*/ + memcpy(&private->data, pdata, sizeof(PDDF_CPLDMUX_PDATA)); + + adap = i2c_get_adapter(pdata->parent_bus); + if (!adap) { + kfree(private); + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent_bus); + return -ENODEV; + } + ndev = pdata->num_chan; + + muxc = i2c_mux_alloc(adap, &pdev->dev, ndev, 0, 0, pddf_cpldmux_ops.select, pddf_cpldmux_ops.deselect); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = private; + platform_set_drvdata(pdev, muxc); + + for (i = 0; i < ndev; i++) + { + int nr = pdata->base_chan + i; + unsigned int class = 0; + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + dev_info(&pdev->dev, "%d port mux on %s adapter\n", ndev, adap->name); + return 0; + +add_adapter_failed: + i2c_mux_del_adapters(muxc); +alloc_failed: + kfree(private); + i2c_put_adapter(adap); + return ret; +} + +static int cpld_mux_remove(struct platform_device *pdev) +{ + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + struct i2c_adapter *adap = muxc->parent; + PDDF_CPLDMUX_PDATA *cpldmux_pdata = pdev->dev.platform_data; + + i2c_mux_del_adapters(muxc); + if (muxc->priv) + kfree(muxc->priv); + i2c_put_adapter(adap); + + if (cpldmux_pdata) { + pddf_dbg(CPLDMUX, KERN_DEBUG "%s: Freeing cpldmux platform data\n", __FUNCTION__); + kfree(cpldmux_pdata); + } + + return 0; +} + +static struct platform_driver cpld_mux_driver = { + .probe = cpld_mux_probe, + .remove = cpld_mux_remove, /* TODO */ + .driver = { + .owner = THIS_MODULE, + .name = "cpld_mux", + }, +}; + +static int __init board_i2c_cpldmux_init(void) +{ + int ret; + ret = platform_driver_register(&cpld_mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register swpld mux driver\n"); + } + return (ret); +} + +static void __exit board_i2c_cpldmux_exit(void) +{ + platform_driver_unregister(&cpld_mux_driver); +} + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("board_i2c_cpldmux driver"); +MODULE_LICENSE("GPL"); + +module_init(board_i2c_cpldmux_init); +module_exit(board_i2c_cpldmux_exit); diff --git a/platform/pddf/i2c/modules/cpldmux/pddf_cpldmux_module.c b/platform/pddf/i2c/modules/cpldmux/pddf_cpldmux_module.c new file mode 100644 index 000000000000..f99def315820 --- /dev/null +++ b/platform/pddf/i2c/modules/cpldmux/pddf_cpldmux_module.c @@ -0,0 +1,254 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * PDDF generic module for cpldmux device + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_cpldmux_defs.h" + +PDDF_CPLDMUX_DATA pddf_cpldmux_data={0}; +PDDF_CPLDMUX_CHAN_DATA pddf_cpldmux_chan_data={0}; +EXPORT_SYMBOL(pddf_cpldmux_data); + +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t do_chan_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +extern void *get_device_table(char *name); +extern void delete_device_table(char *name); + + +/* CPLDMUX CLIENT DATA */ +PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&pddf_cpldmux_data, (void*)&pddf_data); +PDDF_DATA_ATTR(chan_ops, S_IWUSR, NULL, do_chan_operation, PDDF_CHAR, 8, (void*)&pddf_cpldmux_data, NULL); +PDDF_DATA_ATTR(base_chan, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_cpldmux_data.base_chan, NULL); +PDDF_DATA_ATTR(num_chan, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&pddf_cpldmux_data.num_chan, NULL); +PDDF_DATA_ATTR(chan_cache, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&pddf_cpldmux_data.chan_cache, NULL); +PDDF_DATA_ATTR(cpld_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&pddf_cpldmux_data.cpld_name, NULL); +PDDF_DATA_ATTR(chan, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&pddf_cpldmux_chan_data.chan_num, NULL); +PDDF_DATA_ATTR(dev, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 128, (void*)&pddf_cpldmux_chan_data.chan_device, NULL); +PDDF_DATA_ATTR(cpld_devaddr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_cpldmux_chan_data.cpld_devaddr, NULL); +PDDF_DATA_ATTR(cpld_offset, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_cpldmux_chan_data.cpld_offset, NULL); +PDDF_DATA_ATTR(cpld_sel, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_cpldmux_chan_data.cpld_sel, NULL); +PDDF_DATA_ATTR(cpld_desel, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_cpldmux_chan_data.cpld_desel, NULL); + + +static struct attribute *cpldmux_attributes[] = { + &attr_dev_ops.dev_attr.attr, + &attr_chan_ops.dev_attr.attr, + &attr_base_chan.dev_attr.attr, + &attr_num_chan.dev_attr.attr, + &attr_chan_cache.dev_attr.attr, + &attr_cpld_name.dev_attr.attr, + &attr_chan.dev_attr.attr, + &attr_dev.dev_attr.attr, + &attr_cpld_devaddr.dev_attr.attr, + &attr_cpld_offset.dev_attr.attr, + &attr_cpld_sel.dev_attr.attr, + &attr_cpld_desel.dev_attr.attr, + NULL +}; + +static const struct attribute_group pddf_cpldmux_client_data_group = { + .attrs = cpldmux_attributes, +}; + + + +static ssize_t do_chan_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + PDDF_CPLDMUX_DATA *cpldmux_data = (PDDF_CPLDMUX_DATA *)(ptr->addr); + int index; + + pddf_dbg(CPLDMUX, KERN_ERR "%s: Adding channel %d\n", __FUNCTION__, pddf_cpldmux_chan_data.chan_num); + index = pddf_cpldmux_chan_data.chan_num; + cpldmux_data->chan_data[index] = pddf_cpldmux_chan_data; + + memset(&pddf_cpldmux_chan_data, 0, sizeof(pddf_cpldmux_chan_data)); + + + return count; +} + +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + NEW_DEV_ATTR *device_ptr = (NEW_DEV_ATTR *)(ptr->data); + PDDF_CPLDMUX_DATA *cpldmux_data = (PDDF_CPLDMUX_DATA *)(ptr->addr); + PDDF_CPLDMUX_PDATA *cpldmux_platform_data = NULL; + struct platform_device *plat_dev = NULL; + struct i2c_client *client_ptr = NULL; + int ret=0, i=0; + + if (strncmp(buf, "add", strlen(buf)-1)==0) + { + if (strncmp(device_ptr->dev_type, "cpld_mux", strlen("cpld_mux"))==0) + { + /*Get the i2c_client handle for the CPLD which drives this cpldmux*/ + client_ptr = (struct i2c_client *)get_device_table(cpldmux_data->cpld_name); + if (client_ptr==NULL) + { + pddf_dbg(CPLDMUX, KERN_ERR "Unable to get the CPLD client %s for %s cpldmux\n", cpldmux_data->cpld_name, device_ptr->i2c_name); + printk(KERN_ERR "Unable to get the CPLD client %s for %s cpldmux\n", cpldmux_data->cpld_name, device_ptr->i2c_name); + goto clear_data; + } + + /* Allocate the cpldmux_platform_data */ + cpldmux_platform_data = (PDDF_CPLDMUX_PDATA *)kzalloc( sizeof(PDDF_CPLDMUX_PDATA) + cpldmux_data->num_chan*sizeof(PDDF_CPLDMUX_CHAN_DATA), GFP_KERNEL ); + cpldmux_platform_data->chan_data = (PDDF_CPLDMUX_CHAN_DATA *)(cpldmux_platform_data+1); + + cpldmux_platform_data->parent_bus = device_ptr->parent_bus; + cpldmux_platform_data->base_chan = cpldmux_data->base_chan; + cpldmux_platform_data->num_chan = cpldmux_data->num_chan; + cpldmux_platform_data->chan_cache = cpldmux_data->chan_cache; + cpldmux_platform_data->cpld = client_ptr; + for (i=0; inum_chan; i++) + { + cpldmux_platform_data->chan_data[i] = cpldmux_data->chan_data[i]; + } + + plat_dev = platform_device_alloc(device_ptr->dev_type, device_ptr->dev_id); + + plat_dev->dev.platform_data = cpldmux_platform_data; + + pddf_dbg(CPLDMUX, KERN_ERR "Creating a %s platform_device 0x%p, platform_data 0x%p\n", plat_dev->name, (void *)plat_dev, (void *)cpldmux_platform_data); + ret = platform_device_add(plat_dev); + if (ret) + { + pddf_dbg(CPLDMUX, KERN_ERR "Unable to create cpld_mux (%s) device: Error %d\n", device_ptr->i2c_name, ret); + goto free_data; + } + else + { + add_device_table(device_ptr->i2c_name, (void *)plat_dev); + } + + } + else + { + printk(KERN_ERR "%s: Unsupported type of cpldmux - unable to add i2c client\n", __FUNCTION__); + } + } + else if (strncmp(buf, "delete", strlen(buf)-1)==0) + { + /*Get the i2c_client handle for the created client*/ + plat_dev = (struct platform_device *)get_device_table(device_ptr->i2c_name); + if (plat_dev) + { + pddf_dbg(CPLDMUX, KERN_ERR "Removing %s device: 0x%p\n", device_ptr->i2c_name, (void *)plat_dev); + pddf_dbg(CPLDMUX, KERN_ERR "Freeing the memory held by device: 0x%p\n", (void *)plat_dev); + platform_device_del(plat_dev); + delete_device_table(device_ptr->i2c_name); + } + else + { + printk(KERN_ERR "Unable to get the client handle for %s\n", device_ptr->i2c_name); + } + } + else + { + printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf); + } + goto clear_data; + +free_data: + /* Free the allocated memory for platform and channel data */ + cpldmux_platform_data = plat_dev->dev.platform_data; + if (cpldmux_platform_data) + { + printk(KERN_ERR "%s: Unable to register a cpldmux device. Freeing the platform data\n", __FUNCTION__); + kfree(cpldmux_platform_data); + } + + /* Put the platform device structure */ + platform_device_put(plat_dev); +clear_data: + memset(cpldmux_data, 0, sizeof(PDDF_CPLDMUX_DATA)); + /*TODO: free the data device_ptr->data if data is dynamically allocated*/ + memset(device_ptr, 0, sizeof(NEW_DEV_ATTR)); + return count; +} + + +static struct kobject *cpldmux_kobj; + +int __init cpldmux_data_init(void) +{ + struct kobject *device_kobj; + int ret = 0; + + + pddf_dbg(CPLDMUX, "CPLDMUX_DATA MODULE.. init\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + cpldmux_kobj = kobject_create_and_add("cpldmux", device_kobj); + if(!cpldmux_kobj) + return -ENOMEM; + + + ret = sysfs_create_group(cpldmux_kobj, &pddf_clients_data_group); + if (ret) + { + kobject_put(cpldmux_kobj); + return ret; + } + pddf_dbg(CPLDMUX, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n"); + + + ret = sysfs_create_group(cpldmux_kobj, &pddf_cpldmux_client_data_group); + if (ret) + { + sysfs_remove_group(cpldmux_kobj, &pddf_clients_data_group); + kobject_put(cpldmux_kobj); + return ret; + } + pddf_dbg(CPLDMUX, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n"); + return ret; +} + +void __exit cpldmux_data_exit(void) +{ + pddf_dbg(CPLDMUX, "CPLDMUX_DATA MODULE.. exit\n"); + sysfs_remove_group(cpldmux_kobj, &pddf_cpldmux_client_data_group); + sysfs_remove_group(cpldmux_kobj, &pddf_clients_data_group); + kobject_put(cpldmux_kobj); + pddf_dbg(CPLDMUX, KERN_ERR "%s: Removed the kobjects for 'cpldmux'\n",__FUNCTION__); + return; +} + +module_init(cpldmux_data_init); +module_exit(cpldmux_data_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("cpldmux platform data"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/modules/fan/Makefile b/platform/pddf/i2c/modules/fan/Makefile new file mode 100644 index 000000000000..94b6b146c51d --- /dev/null +++ b/platform/pddf/i2c/modules/fan/Makefile @@ -0,0 +1,4 @@ +subdir-m := driver +obj-m := pddf_fan_module.o + +CFLAGS_$(obj-m):= -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/fan/driver/Makefile b/platform/pddf/i2c/modules/fan/driver/Makefile new file mode 100644 index 000000000000..c94f217d3bab --- /dev/null +++ b/platform/pddf/i2c/modules/fan/driver/Makefile @@ -0,0 +1,6 @@ +TARGET := pddf_fan_driver_module +obj-m := $(TARGET).o + +$(TARGET)-objs := pddf_fan_api.o pddf_fan_driver.o + +ccflags-y := -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/fan/driver/pddf_fan_api.c b/platform/pddf/i2c/modules/fan/driver/pddf_fan_api.c new file mode 100644 index 000000000000..167b0e183315 --- /dev/null +++ b/platform/pddf/i2c/modules/fan/driver/pddf_fan_api.c @@ -0,0 +1,526 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description of various APIs related to FAN component + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_fan_defs.h" +#include "pddf_fan_driver.h" + +/*#define FAN_DEBUG*/ +#ifdef FAN_DEBUG +#define fan_dbg(...) printk(__VA_ARGS__) +#else +#define fan_dbg(...) +#endif + +extern void *get_device_table(char *name); + +void get_fan_duplicate_sysfs(int idx, char *str) +{ + switch (idx) + { + default: + break; + } + + return; +} + + +int fan_update_hw(struct device *dev, struct fan_attr_info *info, FAN_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + FAN_SYSFS_ATTR_DATA *sysfs_attr_data = NULL; + + + mutex_lock(&info->update_lock); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_set != NULL) + { + status = (sysfs_attr_data->pre_set)(client, udata, info); + if (status!=0) + printk(KERN_ERR "%s: pre_set function fails for %s attribute\n", __FUNCTION__, udata->aname); + } + if (sysfs_attr_data->do_set != NULL) + { + status = (sysfs_attr_data->do_set)(client, udata, info); + if (status!=0) + printk(KERN_ERR "%s: do_set function fails for %s attribute\n", __FUNCTION__, udata->aname); + + } + if (sysfs_attr_data->post_set != NULL) + { + status = (sysfs_attr_data->post_set)(client, udata, info); + if (status!=0) + printk(KERN_ERR "%s: post_set function fails for %s attribute\n", __FUNCTION__, udata->aname); + } + + mutex_unlock(&info->update_lock); + + return 0; +} + +int fan_update_attr(struct device *dev, struct fan_attr_info *info, FAN_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + FAN_SYSFS_ATTR_DATA *sysfs_attr_data = NULL; + + + mutex_lock(&info->update_lock); + + if (time_after(jiffies, info->last_updated + HZ + HZ / 2) || !info->valid) + { + dev_dbg(&client->dev, "Starting pddf_fan update\n"); + info->valid = 0; + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_get != NULL) + { + status = (sysfs_attr_data->pre_get)(client, udata, info); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, udata->aname); + } + if (sysfs_attr_data->do_get != NULL) + { + status = (sysfs_attr_data->do_get)(client, udata, info); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, udata->aname); + + } + if (sysfs_attr_data->post_get != NULL) + { + status = (sysfs_attr_data->post_get)(client, udata, info); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, udata->aname); + } + + + info->last_updated = jiffies; + info->valid = 1; + } + + mutex_unlock(&info->update_lock); + + return 0; +} + +ssize_t fan_show_default(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct fan_data *data = i2c_get_clientdata(client); + FAN_PDATA *pdata = (FAN_PDATA *)(client->dev.platform_data); + FAN_DATA_ATTR *usr_data = NULL; + struct fan_attr_info *attr_info = NULL; + int i, status=0; + char new_str[ATTR_NAME_LEN] = ""; + FAN_SYSFS_ATTR_DATA *ptr = NULL; + + for (i=0;inum_attr;i++) + { + ptr = (FAN_SYSFS_ATTR_DATA *)pdata->fan_attrs[i].access_data; + get_fan_duplicate_sysfs(ptr->index , new_str); + if (strcmp(attr->dev_attr.attr.name, pdata->fan_attrs[i].aname) == 0 || strcmp(attr->dev_attr.attr.name, new_str) == 0) + { + attr_info = &data->attr_info[i]; + usr_data = &pdata->fan_attrs[i]; + strcpy(new_str, ""); + } + } + + if (attr_info==NULL || usr_data==NULL) + { + printk(KERN_ERR "%s is not supported attribute for this client\n", usr_data->aname); + goto exit; + } + + fan_update_attr(dev, attr_info, usr_data); + + /*Decide the o/p based on attribute type */ + switch(attr->index) + { + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + case FAN7_PRESENT: + case FAN8_PRESENT: + case FAN9_PRESENT: + case FAN10_PRESENT: + case FAN11_PRESENT: + case FAN12_PRESENT: + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + case FAN7_DIRECTION: + case FAN8_DIRECTION: + case FAN9_DIRECTION: + case FAN10_DIRECTION: + case FAN11_DIRECTION: + case FAN12_DIRECTION: + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + case FAN4_INPUT: + case FAN5_INPUT: + case FAN6_INPUT: + case FAN7_INPUT: + case FAN8_INPUT: + case FAN9_INPUT: + case FAN10_INPUT: + case FAN11_INPUT: + case FAN12_INPUT: + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + case FAN5_PWM: + case FAN6_PWM: + case FAN7_PWM: + case FAN8_PWM: + case FAN9_PWM: + case FAN10_PWM: + case FAN11_PWM: + case FAN12_PWM: + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + case FAN7_FAULT: + case FAN8_FAULT: + case FAN9_FAULT: + case FAN10_FAULT: + case FAN11_FAULT: + case FAN12_FAULT: + status = attr_info->val.intval; + break; + default: + fan_dbg(KERN_ERR "%s: Unable to find the attribute index for %s\n", __FUNCTION__, usr_data->aname); + status = 0; + } + +exit: + return sprintf(buf, "%d\n", status); +} + + +ssize_t fan_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct fan_data *data = i2c_get_clientdata(client); + FAN_PDATA *pdata = (FAN_PDATA *)(client->dev.platform_data); + FAN_DATA_ATTR *usr_data = NULL; + struct fan_attr_info *attr_info = NULL; + int i, ret ; + uint32_t val; + + for (i=0;inum_attr;i++) + { + if (strcmp(data->attr_info[i].name, attr->dev_attr.attr.name) == 0 && strcmp(pdata->fan_attrs[i].aname, attr->dev_attr.attr.name) == 0) + { + attr_info = &data->attr_info[i]; + usr_data = &pdata->fan_attrs[i]; + } + } + + if (attr_info==NULL || usr_data==NULL) { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + switch(attr->index) + { + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + case FAN5_PWM: + case FAN6_PWM: + case FAN7_PWM: + case FAN8_PWM: + case FAN9_PWM: + case FAN10_PWM: + case FAN11_PWM: + case FAN12_PWM: + ret = kstrtoint(buf, 10, &val); + if (ret) + { + printk(KERN_ERR "%s: Unable to convert string into value for %s\n", __FUNCTION__, usr_data->aname); + return ret; + } + /*Update the value of attr_info here, and use it to update the HW values*/ + attr_info->val.intval = val; + break; + default: + printk(KERN_ERR "%s: Unable to find the attr index for %s\n", __FUNCTION__, usr_data->aname); + goto exit; + } + + fan_dbg(KERN_ERR "%s: pwm to be set is %d\n", __FUNCTION__, val); + fan_update_hw(dev, attr_info, usr_data); + +exit: + return count; +} + +int fan_cpld_client_read(FAN_DATA_ATTR *udata) +{ + int status = -1; + + if (udata!=NULL) + { + if (udata->len==1) + { + status = board_i2c_cpld_read(udata->devaddr , udata->offset); + } + else + { + /* Get the I2C client for the CPLD */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(udata->devname); + if (client_ptr) + { + if (udata->len==2) + { + status = i2c_smbus_read_word_swapped(client_ptr, udata->offset); + } + else + printk(KERN_ERR "PDDF_FAN: Doesn't support block CPLD read yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname); + } + + } + + return status; +} + + +int sonic_i2c_get_fan_present_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + if (strcmp(udata->devtype, "cpld") == 0) + { + val = fan_cpld_client_read(udata); + } + else + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + + painfo->val.intval = ((val & udata->mask) == udata->cmpval); + + + return status; +} + +int sonic_i2c_get_fan_rpm_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + uint32_t val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + if (strcmp(udata->devtype, "cpld") == 0) + { + val = fan_cpld_client_read(udata); + } + else + { + if (udata->len == 1) + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + else if (udata->len ==2) + { + val = i2c_smbus_read_word_swapped((struct i2c_client *)client, udata->offset); + + } + } + + if (udata->is_divisor) + painfo->val.intval = udata->mult / (val >> 3); + else + painfo->val.intval = udata->mult * val; + + return status; +} + + +int sonic_i2c_get_fan_direction_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + uint32_t val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + if (strcmp(udata->devtype, "cpld") == 0) + { + val = fan_cpld_client_read(udata); + } + else + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + painfo->val.intval = ((val & udata->mask) == udata->cmpval); + + return status; +} + + +int sonic_i2c_set_fan_pwm_default(struct i2c_client *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + uint32_t val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + val = painfo->val.intval & udata->mask; + + if (val > 255) + { + return -EINVAL; + } + + if (strcmp(udata->devtype, "cpld") == 0) + { + if (udata->len==1) + { + status = board_i2c_cpld_write(udata->devaddr , udata->offset, val); + } + else + { + /* Get the I2C client for the CPLD */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(udata->devname); + if (client_ptr) + { + if (udata->len==2) + { + uint8_t val_lsb = val & 0xFF; + uint8_t val_hsb = (val >> 8) & 0xFF; + /* TODO: Check this logic for LE and BE */ + i2c_smbus_write_byte_data(client, udata->offset, val_lsb); + i2c_smbus_write_byte_data(client, udata->offset+1, val_hsb); + } + else + printk(KERN_ERR "PDDF_FAN: Doesn't support block CPLD write yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname); + } + + } + else + { + if (udata->len == 1) + i2c_smbus_write_byte_data(client, udata->offset, val); + else if (udata->len == 2) + { + uint8_t val_lsb = val & 0xFF; + uint8_t val_hsb = (val >> 8) & 0xFF; + /* TODO: Check this logic for LE and BE */ + i2c_smbus_write_byte_data(client, udata->offset, val_lsb); + i2c_smbus_write_byte_data(client, udata->offset+1, val_hsb); + } + else + { + printk(KERN_DEBUG "%s: pwm should be of len 1/2 bytes. Not setting the pwm as the length is %d\n", __FUNCTION__, udata->len); + } + } + + return status; +} + + +int sonic_i2c_get_fan_pwm_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + uint32_t val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + if (strcmp(udata->devtype, "cpld") == 0) + { + val = fan_cpld_client_read(udata); + } + else + { + if (udata->len == 1) + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + else if (udata->len ==2) + { + val = i2c_smbus_read_word_swapped((struct i2c_client *)client, udata->offset); + + } + } + + val = val & udata->mask; + painfo->val.intval = val; + return status; +} + +int sonic_i2c_get_fan_fault_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + uint32_t val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + /*Assuming fan fault to be denoted by 1 byte only*/ + if (strcmp(udata->devtype, "cpld") == 0) + { + val = fan_cpld_client_read(udata); + } + else + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + + val = val & udata->mask; + painfo->val.intval = val; + return status; +} + + +int pddf_fan_post_probe_default(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + + /*Dummy func for now - check the respective platform modules*/ + return 0; +} diff --git a/platform/pddf/i2c/modules/fan/driver/pddf_fan_driver.c b/platform/pddf/i2c/modules/fan/driver/pddf_fan_driver.c new file mode 100644 index 000000000000..da8275fccd64 --- /dev/null +++ b/platform/pddf/i2c/modules/fan/driver/pddf_fan_driver.c @@ -0,0 +1,496 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel driver module for a FAN controller + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_fan_defs.h" +#include "pddf_fan_driver.h" +#include "pddf_fan_api.h" + +#define DRVNAME "pddf_fan" + +struct pddf_ops_t pddf_fan_ops = { + .pre_init = NULL, + .post_init = NULL, + + .pre_probe = NULL, + .post_probe = pddf_fan_post_probe_default, + + .pre_remove = NULL, + .post_remove = NULL, + + .pre_exit = NULL, + .post_exit = NULL, +}; +EXPORT_SYMBOL(pddf_fan_ops); + + + +FAN_SYSFS_ATTR_DATA data_fan1_present = {FAN1_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_present); +FAN_SYSFS_ATTR_DATA data_fan2_present = {FAN2_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_present); +FAN_SYSFS_ATTR_DATA data_fan3_present = {FAN3_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_present); +FAN_SYSFS_ATTR_DATA data_fan4_present = {FAN4_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_present); +FAN_SYSFS_ATTR_DATA data_fan5_present = {FAN5_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_present); +FAN_SYSFS_ATTR_DATA data_fan6_present = {FAN6_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_present); +FAN_SYSFS_ATTR_DATA data_fan7_present = {FAN7_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_present); +FAN_SYSFS_ATTR_DATA data_fan8_present = {FAN8_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_present); +FAN_SYSFS_ATTR_DATA data_fan9_present = {FAN9_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_present); +FAN_SYSFS_ATTR_DATA data_fan10_present = {FAN10_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_present); +FAN_SYSFS_ATTR_DATA data_fan11_present = {FAN11_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_present); +FAN_SYSFS_ATTR_DATA data_fan12_present = {FAN12_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_present); + + +FAN_SYSFS_ATTR_DATA data_fan1_direction = {FAN1_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_direction); +FAN_SYSFS_ATTR_DATA data_fan2_direction = {FAN2_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_direction); +FAN_SYSFS_ATTR_DATA data_fan3_direction = {FAN3_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_direction); +FAN_SYSFS_ATTR_DATA data_fan4_direction = {FAN4_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_direction); +FAN_SYSFS_ATTR_DATA data_fan5_direction = {FAN5_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_direction); +FAN_SYSFS_ATTR_DATA data_fan6_direction = {FAN6_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_direction); +FAN_SYSFS_ATTR_DATA data_fan7_direction = {FAN7_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_direction); +FAN_SYSFS_ATTR_DATA data_fan8_direction = {FAN8_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_direction); +FAN_SYSFS_ATTR_DATA data_fan9_direction = {FAN9_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_direction); +FAN_SYSFS_ATTR_DATA data_fan10_direction = {FAN10_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_direction); +FAN_SYSFS_ATTR_DATA data_fan11_direction = {FAN11_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_direction); +FAN_SYSFS_ATTR_DATA data_fan12_direction = {FAN12_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_direction); + + +FAN_SYSFS_ATTR_DATA data_fan1_input = {FAN1_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_input); +FAN_SYSFS_ATTR_DATA data_fan2_input = {FAN2_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_input); +FAN_SYSFS_ATTR_DATA data_fan3_input = {FAN3_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_input); +FAN_SYSFS_ATTR_DATA data_fan4_input = {FAN4_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_input); +FAN_SYSFS_ATTR_DATA data_fan5_input = {FAN5_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_input); +FAN_SYSFS_ATTR_DATA data_fan6_input = {FAN6_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_input); +FAN_SYSFS_ATTR_DATA data_fan7_input = {FAN7_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_input); +FAN_SYSFS_ATTR_DATA data_fan8_input = {FAN8_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_input); +FAN_SYSFS_ATTR_DATA data_fan9_input = {FAN9_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_input); +FAN_SYSFS_ATTR_DATA data_fan10_input = {FAN10_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_input); +FAN_SYSFS_ATTR_DATA data_fan11_input = {FAN11_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_input); +FAN_SYSFS_ATTR_DATA data_fan12_input = {FAN12_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_input); + + +FAN_SYSFS_ATTR_DATA data_fan1_pwm = {FAN1_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_pwm); +FAN_SYSFS_ATTR_DATA data_fan2_pwm = {FAN2_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_pwm); +FAN_SYSFS_ATTR_DATA data_fan3_pwm = {FAN3_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_pwm); +FAN_SYSFS_ATTR_DATA data_fan4_pwm = {FAN4_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_pwm); +FAN_SYSFS_ATTR_DATA data_fan5_pwm = {FAN5_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_pwm); +FAN_SYSFS_ATTR_DATA data_fan6_pwm = {FAN6_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_pwm); +FAN_SYSFS_ATTR_DATA data_fan7_pwm = {FAN7_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_pwm); +FAN_SYSFS_ATTR_DATA data_fan8_pwm = {FAN8_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_pwm); +FAN_SYSFS_ATTR_DATA data_fan9_pwm = {FAN9_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_pwm); +FAN_SYSFS_ATTR_DATA data_fan10_pwm = {FAN10_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_pwm); +FAN_SYSFS_ATTR_DATA data_fan11_pwm = {FAN11_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_pwm); +FAN_SYSFS_ATTR_DATA data_fan12_pwm = {FAN12_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_pwm); + + +FAN_SYSFS_ATTR_DATA data_fan1_fault = {FAN1_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_fault); +FAN_SYSFS_ATTR_DATA data_fan2_fault = {FAN2_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_fault); +FAN_SYSFS_ATTR_DATA data_fan3_fault = {FAN3_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_fault); +FAN_SYSFS_ATTR_DATA data_fan4_fault = {FAN4_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_fault); +FAN_SYSFS_ATTR_DATA data_fan5_fault = {FAN5_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_fault); +FAN_SYSFS_ATTR_DATA data_fan6_fault = {FAN6_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_fault); +FAN_SYSFS_ATTR_DATA data_fan7_fault = {FAN7_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_fault); +FAN_SYSFS_ATTR_DATA data_fan8_fault = {FAN8_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_fault); +FAN_SYSFS_ATTR_DATA data_fan9_fault = {FAN9_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_fault); +FAN_SYSFS_ATTR_DATA data_fan10_fault = {FAN10_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_fault); +FAN_SYSFS_ATTR_DATA data_fan11_fault = {FAN11_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_fault); +FAN_SYSFS_ATTR_DATA data_fan12_fault = {FAN12_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_fault); + + +FAN_SYSFS_ATTR_DATA_ENTRY fan_sysfs_attr_data_tbl[]= +{ + { "fan1_present", &data_fan1_present}, + { "fan2_present", &data_fan2_present}, + { "fan3_present", &data_fan3_present}, + { "fan4_present", &data_fan4_present}, + { "fan5_present", &data_fan5_present}, + { "fan6_present", &data_fan6_present}, + { "fan7_present", &data_fan7_present}, + { "fan8_present", &data_fan8_present}, + { "fan9_present", &data_fan9_present}, + { "fan10_present", &data_fan10_present}, + { "fan11_present", &data_fan11_present}, + { "fan12_present", &data_fan12_present}, + { "fan1_direction", &data_fan1_direction}, + { "fan2_direction", &data_fan2_direction}, + { "fan3_direction", &data_fan3_direction}, + { "fan4_direction", &data_fan4_direction}, + { "fan5_direction", &data_fan5_direction}, + { "fan6_direction", &data_fan6_direction}, + { "fan7_direction", &data_fan7_direction}, + { "fan8_direction", &data_fan8_direction}, + { "fan9_direction", &data_fan9_direction}, + { "fan10_direction", &data_fan10_direction}, + { "fan11_direction", &data_fan11_direction}, + { "fan12_direction", &data_fan12_direction}, + { "fan1_input", &data_fan1_input}, + { "fan2_input", &data_fan2_input}, + { "fan3_input", &data_fan3_input}, + { "fan4_input", &data_fan4_input}, + { "fan5_input", &data_fan5_input}, + { "fan6_input", &data_fan6_input}, + { "fan7_input", &data_fan7_input}, + { "fan8_input", &data_fan8_input}, + { "fan9_input", &data_fan9_input}, + { "fan10_input", &data_fan10_input}, + { "fan11_input", &data_fan11_input}, + { "fan12_input", &data_fan12_input}, + { "fan1_pwm", &data_fan1_pwm}, + { "fan2_pwm", &data_fan2_pwm}, + { "fan3_pwm", &data_fan3_pwm}, + { "fan4_pwm", &data_fan4_pwm}, + { "fan5_pwm", &data_fan5_pwm}, + { "fan6_pwm", &data_fan6_pwm}, + { "fan7_pwm", &data_fan7_pwm}, + { "fan8_pwm", &data_fan8_pwm}, + { "fan9_pwm", &data_fan9_pwm}, + { "fan10_pwm", &data_fan10_pwm}, + { "fan11_pwm", &data_fan11_pwm}, + { "fan12_pwm", &data_fan12_pwm}, + { "fan1_fault", &data_fan1_fault}, + { "fan2_fault", &data_fan2_fault}, + { "fan3_fault", &data_fan3_fault}, + { "fan4_fault", &data_fan4_fault}, + { "fan5_fault", &data_fan5_fault}, + { "fan6_fault", &data_fan6_fault}, + { "fan7_fault", &data_fan7_fault}, + { "fan8_fault", &data_fan8_fault}, + { "fan9_fault", &data_fan9_fault}, + { "fan10_fault", &data_fan10_fault}, + { "fan11_fault", &data_fan11_fault}, + { "fan12_fault", &data_fan12_fault}, +}; + +void *get_fan_access_data(char *name) +{ + int i=0; + for(i=0; i<(sizeof(fan_sysfs_attr_data_tbl)/sizeof(fan_sysfs_attr_data_tbl[0])); i++) + { + if(strcmp(name, fan_sysfs_attr_data_tbl[i].name) ==0) + { + return &fan_sysfs_attr_data_tbl[i]; + } + } + return NULL; +} +EXPORT_SYMBOL(get_fan_access_data); + + + +static int pddf_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct fan_data *data; + int status=0,i,num, j=0; + FAN_PDATA *fan_platform_data; + FAN_DATA_ATTR *data_attr; + FAN_SYSFS_ATTR_DATA_ENTRY *sysfs_data_entry; + char new_str[ATTR_NAME_LEN] = ""; + + if (client == NULL) { + printk("NULL Client.. \n"); + goto exit; + } + + if (pddf_fan_ops.pre_probe) + { + status = (pddf_fan_ops.pre_probe)(client, dev_id); + if (status != 0) + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + /* Add support for a pre probe function */ + data = kzalloc(sizeof(struct fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + dev_info(&client->dev, "chip found\n"); + + + /*Take control of the platform data*/ + fan_platform_data = (FAN_PDATA *)(client->dev.platform_data); + num = fan_platform_data->len; + data->num_attr = num; + + for (i=0;ifan_attrs + i; + sysfs_data_entry = get_fan_access_data(data_attr->aname); + if (sysfs_data_entry == NULL) + { + printk(KERN_ERR "%s: Wrong attribute name provided by user '%s'\n", __FUNCTION__, data_attr->aname); + continue; + } + + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strcpy((char *)dy_ptr->dev_attr.attr.name, data_attr->aname); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->fan_attribute_list[i] = &dy_ptr->dev_attr.attr; + strcpy(data->attr_info[i].name, data_attr->aname); + data->attr_info[i].valid = 0; + mutex_init(&data->attr_info[i].update_lock); + + /*Create a duplicate entry*/ + get_fan_duplicate_sysfs(dy_ptr->index, new_str); + if (strcmp(new_str,"")) + { + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strcpy((char *)dy_ptr->dev_attr.attr.name, new_str); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->fan_attribute_list[num+j] = &dy_ptr->dev_attr.attr; + j++; + strcpy(new_str, ""); + } + } + data->fan_attribute_list[i+j] = NULL; + data->fan_attribute_group.attrs = data->fan_attribute_list; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->fan_attribute_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + /* Add a support for post probe function */ + if (pddf_fan_ops.post_probe) + { + status = (pddf_fan_ops.post_probe)(client, dev_id); + if (status != 0) + goto exit_remove; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->fan_attribute_group); +exit_free: + /* Free all the allocated attributes */ + for (i=0; data->fan_attribute_list[i]!=NULL; i++) + { + struct sensor_device_attribute *ptr = (struct sensor_device_attribute *)data->fan_attribute_list[i]; + kfree(ptr); + } + pddf_dbg(FAN, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + kfree(data); +exit: + return status; +} + +static int pddf_fan_remove(struct i2c_client *client) +{ + int i = 0, ret = 0; + struct sensor_device_attribute *ptr = NULL; + struct fan_data *data = i2c_get_clientdata(client); + FAN_PDATA *platdata = (FAN_PDATA *)client->dev.platform_data; + FAN_DATA_ATTR *platdata_sub = platdata->fan_attrs; + + if (pddf_fan_ops.pre_remove) + { + ret = (pddf_fan_ops.pre_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN pre_remove function failed\n"); + } + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->fan_attribute_group); + for (i=0; data->fan_attribute_list[i]!=NULL; i++) + { + ptr = (struct sensor_device_attribute *)data->fan_attribute_list[i]; + kfree(ptr); + } + pddf_dbg(FAN, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + kfree(data); + + if (platdata_sub) { + printk(KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__); + kfree(platdata_sub); + } + if (platdata) { + printk(KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__); + kfree(platdata); + } + + if (pddf_fan_ops.post_remove) + { + ret = (pddf_fan_ops.post_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN post_remove function failed\n"); + } + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static const struct i2c_device_id pddf_fan_id[] = { + { "fan_ctrl", 0 }, + { "fan_cpld", 1 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pddf_fan_id); + +static struct i2c_driver pddf_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = pddf_fan_probe, + .remove = pddf_fan_remove, + .id_table = pddf_fan_id, + .address_list = normal_i2c, +}; + +static int __init pddf_fan_init(void) +{ + int status = 0; + + if (pddf_fan_ops.pre_init) + { + status = (pddf_fan_ops.pre_init)(); + if (status!=0) + return status; + } + + status = i2c_add_driver(&pddf_fan_driver); + if (status!=0) + return status; + + if (pddf_fan_ops.post_init) + { + status = (pddf_fan_ops.post_init)(); + if (status!=0) + return status; + } + return status; + +} + +static void __exit pddf_fan_exit(void) +{ + if (pddf_fan_ops.pre_exit) (pddf_fan_ops.pre_exit)(); + i2c_del_driver(&pddf_fan_driver); + if (pddf_fan_ops.post_exit) (pddf_fan_ops.post_exit)(); +} + +module_init(pddf_fan_init); +module_exit(pddf_fan_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("pddf_fan driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/modules/fan/pddf_fan_module.c b/platform/pddf/i2c/modules/fan/pddf_fan_module.c new file mode 100644 index 000000000000..b910d6b4a351 --- /dev/null +++ b/platform/pddf/i2c/modules/fan/pddf_fan_module.c @@ -0,0 +1,280 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel module to create I2C client for FAN controller + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_fan_defs.h" + + +static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern void *get_fan_access_data(char *); +extern void* get_device_table(char *name); +extern void delete_device_table(char *name); + +FAN_DATA fan_data = {0}; + + + +/* FAN CLIENT DATA */ +PDDF_DATA_ATTR(num_fantrays, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&fan_data.num_fantrays, NULL); + +PDDF_DATA_ATTR(attr_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&fan_data.fan_attr.aname, NULL); +PDDF_DATA_ATTR(attr_devtype, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&fan_data.fan_attr.devtype, NULL); +PDDF_DATA_ATTR(attr_devname, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&fan_data.fan_attr.devname, NULL); +PDDF_DATA_ATTR(attr_devaddr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&fan_data.fan_attr.devaddr, NULL); +PDDF_DATA_ATTR(attr_offset, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&fan_data.fan_attr.offset, NULL); +PDDF_DATA_ATTR(attr_mask, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&fan_data.fan_attr.mask, NULL); +PDDF_DATA_ATTR(attr_cmpval, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&fan_data.fan_attr.cmpval, NULL); +PDDF_DATA_ATTR(attr_len, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&fan_data.fan_attr.len, NULL); +PDDF_DATA_ATTR(attr_mult, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&fan_data.fan_attr.mult, NULL); +PDDF_DATA_ATTR(attr_is_divisor, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UCHAR, sizeof(unsigned char), (void*)&fan_data.fan_attr.is_divisor, NULL); +PDDF_DATA_ATTR(attr_ops, S_IWUSR, NULL, do_attr_operation, PDDF_CHAR, 8, (void*)&fan_data, NULL); +PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&fan_data, (void*)&pddf_data); + + + +static struct attribute *fan_attributes[] = { + &attr_num_fantrays.dev_attr.attr, + &attr_attr_name.dev_attr.attr, + &attr_attr_devtype.dev_attr.attr, + &attr_attr_devname.dev_attr.attr, + &attr_attr_devaddr.dev_attr.attr, + &attr_attr_offset.dev_attr.attr, + &attr_attr_mask.dev_attr.attr, + &attr_attr_cmpval.dev_attr.attr, + &attr_attr_len.dev_attr.attr, + &attr_attr_mult.dev_attr.attr, + &attr_attr_is_divisor.dev_attr.attr, + &attr_attr_ops.dev_attr.attr, + &attr_dev_ops.dev_attr.attr, + NULL +}; + +static const struct attribute_group pddf_fan_client_data_group = { + .attrs = fan_attributes, +}; + + +static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + FAN_DATA *fdata = (FAN_DATA *)(ptr->addr); + FAN_SYSFS_ATTR_DATA_ENTRY *entry_ptr; + + + fdata->fan_attrs[fdata->len] = fdata->fan_attr; + entry_ptr = get_fan_access_data(fdata->fan_attrs[fdata->len].aname); + if (entry_ptr != NULL && entry_ptr->a_ptr != NULL) + { + fdata->fan_attrs[fdata->len].access_data = entry_ptr->a_ptr ; + } + + fdata->len++; + memset(&fdata->fan_attr, 0, sizeof(fdata->fan_attr)); + + + return count; +} + +struct i2c_board_info *i2c_get_fan_board_info(FAN_DATA *fdata, NEW_DEV_ATTR *cdata) +{ + int num = fdata->len; + int i = 0; + static struct i2c_board_info board_info; + FAN_PDATA *fan_platform_data; + + if (strcmp(cdata->dev_type, "fan_ctrl")==0 || + strcmp(cdata->dev_type, "fan_eeprom")==0 || + strcmp(cdata->dev_type, "fan_cpld")==0 ) + { + /* Allocate the fan_platform_data */ + fan_platform_data = (FAN_PDATA *)kzalloc(sizeof(FAN_PDATA), GFP_KERNEL); + fan_platform_data->fan_attrs = (FAN_DATA_ATTR *)kzalloc(num*sizeof(FAN_DATA_ATTR), GFP_KERNEL); + + + fan_platform_data->num_fantrays = fdata->num_fantrays; + fan_platform_data->len = fdata->len; + + for (i=0;ifan_attrs[i] = fdata->fan_attrs[i]; + } + + board_info = (struct i2c_board_info) { + .platform_data = fan_platform_data, + }; + + board_info.addr = cdata->dev_addr; + strcpy(board_info.type, cdata->dev_type); + } + else + { + printk(KERN_ERR "%s:Unknown type of device %s. Unable to create I2C client for it\n",__FUNCTION__, cdata->dev_type); + } + + return &board_info; +} + + +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + FAN_DATA *fdata = (FAN_DATA *)(ptr->addr); + NEW_DEV_ATTR *cdata = (NEW_DEV_ATTR *)(ptr->data); + struct i2c_adapter *adapter; + struct i2c_board_info *board_info; + struct i2c_client *client_ptr; + + if (strncmp(buf, "add", strlen(buf)-1)==0) + { + adapter = i2c_get_adapter(cdata->parent_bus); + board_info = i2c_get_fan_board_info(fdata, cdata); + + /* Populate the platform data for fan */ + client_ptr = i2c_new_device(adapter, board_info); + + if(client_ptr != NULL) + { + i2c_put_adapter(adapter); + pddf_dbg(FAN, KERN_ERR "Created a %s client: 0x%p\n", cdata->i2c_name, (void *)client_ptr); + add_device_table(cdata->i2c_name, (void*)client_ptr); + } + else + { + i2c_put_adapter(adapter); + goto free_data; + } + } + else if (strncmp(buf, "delete", strlen(buf)-1)==0) + { + /*Get the i2c_client handle for the created client*/ + client_ptr = (struct i2c_client *)get_device_table(cdata->i2c_name); + if (client_ptr) + { + pddf_dbg(FAN, KERN_ERR "Removing %s client: 0x%p\n", cdata->i2c_name, (void *)client_ptr); + i2c_unregister_device(client_ptr); + delete_device_table(cdata->i2c_name); + } + else + { + printk(KERN_ERR "Unable to get the client handle for %s\n", cdata->i2c_name); + } + } + else + { + printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf); + } + + goto clear_data; + +free_data: + if (board_info->platform_data) + { + FAN_PDATA *fan_platform_data = board_info->platform_data; + if (fan_platform_data->fan_attrs) + { + printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform subdata\n", __FUNCTION__); + kfree(fan_platform_data->fan_attrs); + } + printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform data\n", __FUNCTION__); + kfree(fan_platform_data); + } +clear_data: + memset(fdata, 0, sizeof(FAN_DATA)); + /*TODO: free the data cdata->data if data is dynal=mically allocated*/ + memset(cdata, 0, sizeof(NEW_DEV_ATTR)); + return count; +} + + +static struct kobject *fan_kobj; +static struct kobject *i2c_kobj; + +int __init pddf_data_init(void) +{ + struct kobject *device_kobj; + int ret = 0; + + + pddf_dbg(FAN, "PDDF FAN MODULE.. init\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + fan_kobj = kobject_create_and_add("fan", device_kobj); + if(!fan_kobj) + return -ENOMEM; + i2c_kobj = kobject_create_and_add("i2c", fan_kobj); + if(!i2c_kobj) + return -ENOMEM; + + ret = sysfs_create_group(i2c_kobj, &pddf_clients_data_group); + if (ret) + { + kobject_put(i2c_kobj); + kobject_put(fan_kobj); + return ret; + } + pddf_dbg(FAN, "CREATED FAN I2C CLIENTS CREATION SYSFS GROUP\n"); + + ret = sysfs_create_group(i2c_kobj, &pddf_fan_client_data_group); + if (ret) + { + sysfs_remove_group(i2c_kobj, &pddf_clients_data_group); + kobject_put(i2c_kobj); + kobject_put(fan_kobj); + return ret; + } + pddf_dbg(FAN, "CREATED PDDF FAN DATA SYSFS GROUP\n"); + + + + return ret; +} + +void __exit pddf_data_exit(void) +{ + pddf_dbg(FAN, "PDDF FAN MODULE.. exit\n"); + sysfs_remove_group(i2c_kobj, &pddf_fan_client_data_group); + sysfs_remove_group(i2c_kobj, &pddf_clients_data_group); + kobject_put(i2c_kobj); + kobject_put(fan_kobj); + pddf_dbg(FAN, KERN_ERR "%s: Removed the kobjects for 'i2c' and 'fan'\n",__FUNCTION__); + return; +} + +module_init(pddf_data_init); +module_exit(pddf_data_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("fan platform data"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/modules/gpio/Makefile b/platform/pddf/i2c/modules/gpio/Makefile new file mode 100644 index 000000000000..6d48c5884731 --- /dev/null +++ b/platform/pddf/i2c/modules/gpio/Makefile @@ -0,0 +1,4 @@ + +obj-m := pddf_gpio_module.o + +CFLAGS_$(obj-m):= -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/gpio/pddf_gpio_module.c b/platform/pddf/i2c/modules/gpio/pddf_gpio_module.c new file mode 100644 index 000000000000..afd37c3927df --- /dev/null +++ b/platform/pddf/i2c/modules/gpio/pddf_gpio_module.c @@ -0,0 +1,223 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * PDDF generic kernle module to create the I2C client for pca955x type of GPIO module + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_gpio_defs.h" + + +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern void* get_device_table(char *name); +extern void delete_device_table(char *name); + +static int base_gpio_num = 0xf0; +GPIO_DATA gpio_data = {0}; + +/* GPIO CLIENT DATA */ +PDDF_DATA_ATTR(gpio_base, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&gpio_data.gpio_base, NULL); +PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&gpio_data, (void*)&pddf_data); + + + +static struct attribute *gpio_attributes[] = { + &attr_gpio_base.dev_attr.attr, + &attr_dev_ops.dev_attr.attr, + NULL +}; + +static const struct attribute_group pddf_gpio_client_data_group = { + .attrs = gpio_attributes, +}; + + +struct i2c_board_info *i2c_get_gpio_board_info(GPIO_DATA* mdata, NEW_DEV_ATTR *device_data) +{ + static struct i2c_board_info board_info; + struct pca953x_platform_data *gpio_platform_data=NULL; + int def_num_gpios, base; + + gpio_platform_data = (struct pca953x_platform_data *)kzalloc(sizeof (struct pca953x_platform_data), GFP_KERNEL); + + if (strncmp(device_data->dev_type, "pca9554", strlen("pca9554")) == 0 || + strncmp(device_data->dev_type, "pca9534", strlen("pca9534")) == 0 || + strncmp(device_data->dev_type, "pca9538", strlen("pca9538")) == 0) + def_num_gpios = 0x8; + else if (strncmp(device_data->dev_type, "pca9555", strlen("pca9555")) == 0 || + strncmp(device_data->dev_type, "pca9535", strlen("pca9535")) == 0 || + strncmp(device_data->dev_type, "pca9539", strlen("pca9539")) == 0 || + strncmp(device_data->dev_type, "pca9575", strlen("pca9575")) == 0) + def_num_gpios = 0x10; + else if (strncmp(device_data->dev_type, "pca9698", strlen("pca9698")) == 0 || + strncmp(device_data->dev_type, "pca9505", strlen("pca9505")) == 0) + def_num_gpios = 0x28; + else + { + printk(KERN_ERR "%s: Unknown type of gpio device\n", __FUNCTION__); + return NULL; + } + + if(mdata->gpio_base == 0) { + base = base_gpio_num; + base_gpio_num += def_num_gpios; + } + else { + base = mdata->gpio_base; + } + + gpio_platform_data->gpio_base = base; + + board_info = (struct i2c_board_info) { + .platform_data = gpio_platform_data, + }; + + board_info.addr = device_data->dev_addr; + strcpy(board_info.type, device_data->dev_type); + + return &board_info; +} + + +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + GPIO_DATA *gpio_ptr = (GPIO_DATA *)(ptr->addr); + NEW_DEV_ATTR *device_ptr = (NEW_DEV_ATTR *)(ptr->data); + struct i2c_adapter *adapter; + struct i2c_board_info *board_info; + struct i2c_client *client_ptr; + + if (strncmp(buf, "add", strlen(buf)-1)==0) + { + adapter = i2c_get_adapter(device_ptr->parent_bus); + board_info = i2c_get_gpio_board_info(gpio_ptr, device_ptr); + + /*pddf_dbg(KERN_ERR "Creating a client %s on 0x%x, platform_data 0x%x\n", board_info->type, board_info->addr, board_info->platform_data);*/ + client_ptr = i2c_new_device(adapter, board_info); + + i2c_put_adapter(adapter); + if (client_ptr != NULL) + { + pddf_dbg(GPIO, KERN_ERR "Created %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr); + add_device_table(device_ptr->i2c_name, (void*)client_ptr); + } + else + { + kfree(board_info); + goto free_data; + } + } + else if (strncmp(buf, "delete", strlen(buf)-1)==0) + { + /*Get the i2c_client handle for the created client*/ + client_ptr = (struct i2c_client *)get_device_table(device_ptr->i2c_name); + if (client_ptr) + { + struct pca953x_platform_data *gpio_platform_data = (struct pca953x_platform_data *)client_ptr->dev.platform_data; + pddf_dbg(GPIO, KERN_ERR "Removing %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr); + i2c_unregister_device(client_ptr); + /*TODO: Nullyfy the platform data*/ + if (gpio_platform_data) + kfree(gpio_platform_data); + delete_device_table(device_ptr->i2c_name); + } + else + { + printk(KERN_ERR "Unable to get the client handle for %s\n", device_ptr->i2c_name); + } + } + else + { + printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf); + } + +free_data: + memset(gpio_ptr, 0, sizeof(GPIO_DATA)); + /*TODO: free the device_ptr->data is dynamically allocated*/ + memset(device_ptr, 0 , sizeof(NEW_DEV_ATTR)); + + return count; +} + + +static struct kobject *gpio_kobj; + +int __init gpio_data_init(void) +{ + struct kobject *device_kobj; + int ret = 0; + + + pddf_dbg(GPIO, "GPIO_DATA MODULE.. init\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + gpio_kobj = kobject_create_and_add("gpio", device_kobj); + if(!gpio_kobj) + return -ENOMEM; + + + ret = sysfs_create_group(gpio_kobj, &pddf_clients_data_group); + if (ret) + { + kobject_put(gpio_kobj); + return ret; + } + pddf_dbg(GPIO, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n"); + + ret = sysfs_create_group(gpio_kobj, &pddf_gpio_client_data_group); + if (ret) + { + sysfs_remove_group(gpio_kobj, &pddf_clients_data_group); + kobject_put(gpio_kobj); + return ret; + } + pddf_dbg(GPIO, "CREATED GPIO DATA SYSFS GROUP\n"); + + return ret; +} + +void __exit gpio_data_exit(void) +{ + pddf_dbg(GPIO, "GPIO_DATA MODULE.. exit\n"); + sysfs_remove_group(gpio_kobj, &pddf_gpio_client_data_group); + sysfs_remove_group(gpio_kobj, &pddf_clients_data_group); + kobject_put(gpio_kobj); + pddf_dbg(GPIO, KERN_ERR "%s: Removed the kobjects for 'gpio'\n",__FUNCTION__); + return; +} + +module_init(gpio_data_init); +module_exit(gpio_data_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("gpio platform data"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/modules/include/pddf_client_defs.h b/platform/pddf/i2c/modules/include/pddf_client_defs.h new file mode 100644 index 000000000000..1c98a73e6eb6 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_client_defs.h @@ -0,0 +1,135 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description: + * Platform I2C client defines/structures header file + */ + +#ifndef __PDDF_CLIENT_DEFS_H__ +#define __PDDF_CLIENT_DEFS_H__ + +#include + +#define PSU "PDDF_PSU" +#define LED "PDDF_LED" +#define FAN "PDDF_FAN" +#define CLIENT "PDDF_CLIENT" +#define CPLD "PDDF_CPLD" +#define CPLDMUX "PDDF_CPLDMUX" +#define MUX "PDDF_MUX" +#define GPIO "PDDF_GPIO" +#define SYSSTATUS "PDDF_SYSSTATUS" +#define XCVR "PDDF_XCVR" + +#define PDDF_DEBUG +#ifdef PDDF_DEBUG +#define pddf_dbg(filter,...) printk("%s\t", filter); printk(KERN_CONT __VA_ARGS__) +#else +#define pddf_dbg(...) +#endif + + +#define GEN_NAME_SIZE 32 +#define ERR_STR_SIZE 128 + + +typedef struct pddf_data_attribute{ + struct device_attribute dev_attr; + int type; + int len; + char *addr; + char *data; +}PDDF_ATTR; + +#define PDDF_DATA_ATTR(_name, _mode, _show, _store, _type, _len, _addr, _data) \ + struct pddf_data_attribute attr_##_name = { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .type = _type , \ + .len = _len , \ + .addr = _addr, \ + .data = _data } + + +enum attribute_data_type { + PDDF_CHAR, + PDDF_UCHAR, + PDDF_INT_HEX, // integer represented in HEX + PDDF_INT_DEC, // integer represented in DECIMAL + PDDF_USHORT, // HEX + PDDF_UINT32 // HEX +}; + + + + + +// PSU Specific details + +typedef struct NEW_DEV_ATTR +{ + char i2c_type[GEN_NAME_SIZE]; + char i2c_name[GEN_NAME_SIZE]; + int parent_bus; + char dev_type[GEN_NAME_SIZE]; + int dev_id; + int dev_addr; + char *data; + int error; + char errstr[ERR_STR_SIZE]; + +}NEW_DEV_ATTR; +extern NEW_DEV_ATTR pddf_data; + +extern struct attribute_group pddf_clients_data_group; +extern ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, char *buf); +struct kobject* get_device_i2c_kobj(void); +void set_attr_data(void * ptr); +void set_error_code(int, char *); +ssize_t show_error_code(struct device *dev, struct device_attribute *da, char *buf); +ssize_t show_all_devices(struct device *dev, struct device_attribute *da, char *buf); +void traverse_device_table(void ); + + + +/*Various Ops hook which can be used by vendors to provide some deviation from usual pddf functionality*/ +struct pddf_ops_t +{ + /*Module init ops*/ + int (*pre_init)(void); + int (*post_init)(void); + /*probe ops*/ + int (*pre_probe)(struct i2c_client *, const struct i2c_device_id *); + int (*post_probe)(struct i2c_client *, const struct i2c_device_id *); + /*remove ops*/ + int (*pre_remove)(struct i2c_client *); + int (*post_remove)(struct i2c_client *); + /*Module exit ops*/ + void (*pre_exit)(void); + void (*post_exit)(void); +}; + + +typedef struct PDEVICE +{ + struct hlist_node node; + char name[GEN_NAME_SIZE]; + void *data; + +}PDEVICE; + +void add_device_table(char *name, void *ptr); + + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_cpld_defs.h b/platform/pddf/i2c/modules/include/pddf_cpld_defs.h new file mode 100644 index 000000000000..c312f3277f75 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_cpld_defs.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description: + * Platform CPLD defines/structures header file + */ + +#ifndef __PDDF_CPLD_DEFS_H__ +#define __PDDF_CPLD_DEFS_H__ + +/* CPLD DATA - DATA FOR CPLD CLIENT READ/WRITE*/ +typedef struct CPLD_DATA +{ + struct mutex cpld_lock; + uint16_t reg_addr; +}PDDF_CPLD_DATA; + + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_cpldmux_defs.h b/platform/pddf/i2c/modules/include/pddf_cpldmux_defs.h new file mode 100644 index 000000000000..ab2aa901c884 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_cpldmux_defs.h @@ -0,0 +1,76 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description: + * Platform CPLDMUX defines/structures header file + */ + +#ifndef __PDDF_CPLDMUX_DEFS_H__ +#define __PDDF_CPLDMUX_DEFS_H__ + +#include + +#define MAX_CPLDMUX_CHAN 64 + +typedef struct CPLDMUX_CHAN_DATA +{ + int chan_num; + char chan_device[128]; /* Could be multiple devices, mentioned as " " seperated array */ + int cpld_devaddr; + int cpld_offset; + int cpld_sel; + int cpld_desel; +}PDDF_CPLDMUX_CHAN_DATA; + +/* CPLDMUX DATA - DATA FOR CPLDMUX CLIENT*/ +typedef struct CPLDMUX_DATA +{ + int base_chan; + int num_chan; + int chan_cache; + uint32_t cpld_addr; + char cpld_name[32]; + PDDF_CPLDMUX_CHAN_DATA chan_data[MAX_CPLDMUX_CHAN]; +}PDDF_CPLDMUX_DATA; + +typedef struct CPLDMUX_PDATA +{ + int parent_bus; + int base_chan; + int num_chan; + int chan_cache; + struct i2c_client *cpld; + PDDF_CPLDMUX_CHAN_DATA *chan_data; +}PDDF_CPLDMUX_PDATA; + +typedef struct CPLDMUX_PRIV_DATA{ + struct i2c_adapter *parent; + uint32_t last_chan; /* Will be used in case channel caching is enabled */ + PDDF_CPLDMUX_PDATA data; +}PDDF_CPLDMUX_PRIV_DATA; + +typedef struct pldmux_ops_t +{ + int (*select)(struct i2c_mux_core *muxc, uint32_t chan); + int (*deselect)(struct i2c_mux_core *muxc, uint32_t chan); +}PDDF_CPLDMUX_OPS; + +int pddf_cpldmux_select_default(struct i2c_mux_core *muxc, uint32_t chan); +int pddf_cpldmux_deselect_default(struct i2c_mux_core *muxc, uint32_t chan); + +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_fan_api.h b/platform/pddf/i2c/modules/include/pddf_fan_api.h new file mode 100644 index 000000000000..45b7751ccd43 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_fan_api.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * + * 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. + * + * Description + * FAN driver api declarations + */ + +#ifndef __PDDF_FAN_API_H__ +#define __PDDF_FAN_API_H__ + +extern int pddf_fan_post_probe_default(struct i2c_client *client, const struct i2c_device_id *dev_id); + +extern void get_fan_duplicate_sysfs(int idx, char *str); +extern ssize_t fan_show_default(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t fan_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + + +extern int sonic_i2c_get_fan_present_default(void *client, FAN_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_fan_rpm_default(void *client, FAN_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_fan_direction_default(void *client, FAN_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_fan_pwm_default(void *client, FAN_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_fan_fault_default(void *client, FAN_DATA_ATTR *adata, void *data); +extern int sonic_i2c_set_fan_pwm_default(void *client, FAN_DATA_ATTR *adata, void *data); + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_fan_defs.h b/platform/pddf/i2c/modules/include/pddf_fan_defs.h new file mode 100644 index 000000000000..7765e5446293 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_fan_defs.h @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description: + * Platform FAN defines/structures header file + */ + +#ifndef __PDDF_FAN_DEFS_H__ +#define __PDDF_FAN_DEFS_H__ + + +#define MAX_NUM_FAN 6 +#define MAX_FAN_ATTRS 128 +#define ATTR_NAME_LEN 32 +#define STR_ATTR_SIZE 32 +#define DEV_TYPE_LEN 32 + +/* Each client has this additional data + */ + +typedef struct FAN_DATA_ATTR +{ + char aname[ATTR_NAME_LEN]; // attr name, taken from enum fan_sysfs_attributes + char devtype[DEV_TYPE_LEN]; // Type of FAN controller, i.e EMC2305, EMC2302, or FAN-CPLD etc + char devname[DEV_TYPE_LEN]; // Name of the device from where this informatin is to be read + uint32_t devaddr; + uint32_t offset; + uint32_t mask; + uint32_t cmpval; + uint32_t len; + int mult; // Multiplication factor to get the actual data + uint8_t is_divisor; // Check if the value is a divisor and mult is dividend + void *access_data; + +}FAN_DATA_ATTR; + + +typedef struct FAN_SYSFS_ATTR_DATA +{ + int index; + unsigned short mode; + ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf); + int (*pre_get)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*do_get)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*post_get)(void *client, FAN_DATA_ATTR *adata, void *data); + ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + int (*pre_set)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*do_set)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*post_set)(void *client, FAN_DATA_ATTR *adata, void *data); + void *data; +} FAN_SYSFS_ATTR_DATA; + +typedef struct FAN_SYSFS_ATTR_DATA_ENTRY +{ + char name[ATTR_NAME_LEN]; + FAN_SYSFS_ATTR_DATA *a_ptr; +} FAN_SYSFS_ATTR_DATA_ENTRY; + + +/* FAN CLIENT DATA - PLATFORM DATA FOR FAN CLIENT */ +typedef struct FAN_DATA +{ + int num_fantrays; // num of fans controlled by this fan client + FAN_DATA_ATTR fan_attr; + int len; // no of valid attributes for this fan client + FAN_DATA_ATTR fan_attrs[MAX_FAN_ATTRS]; +}FAN_DATA; + +typedef struct FAN_PDATA +{ + int num_fantrays; // num of fans controlled by this fan client + int len; // no of valid attributes for this fan client + FAN_DATA_ATTR *fan_attrs; +}FAN_PDATA; + +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_fan_driver.h b/platform/pddf/i2c/modules/include/pddf_fan_driver.h new file mode 100644 index 000000000000..8404db20786a --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_fan_driver.h @@ -0,0 +1,107 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description + * FAN driver related data structures + */ +#ifndef __PDDF_FAN_DRIVER_H__ +#define __PDDF_FAN_DRIVER_H__ + +enum fan_sysfs_attributes { + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN7_PRESENT, + FAN8_PRESENT, + FAN9_PRESENT, + FAN10_PRESENT, + FAN11_PRESENT, + FAN12_PRESENT, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN7_DIRECTION, + FAN8_DIRECTION, + FAN9_DIRECTION, + FAN10_DIRECTION, + FAN11_DIRECTION, + FAN12_DIRECTION, + FAN1_INPUT, + FAN2_INPUT, + FAN3_INPUT, + FAN4_INPUT, + FAN5_INPUT, + FAN6_INPUT, + FAN7_INPUT, + FAN8_INPUT, + FAN9_INPUT, + FAN10_INPUT, + FAN11_INPUT, + FAN12_INPUT, + FAN1_PWM, + FAN2_PWM, + FAN3_PWM, + FAN4_PWM, + FAN5_PWM, + FAN6_PWM, + FAN7_PWM, + FAN8_PWM, + FAN9_PWM, + FAN10_PWM, + FAN11_PWM, + FAN12_PWM, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT, + FAN7_FAULT, + FAN8_FAULT, + FAN9_FAULT, + FAN10_FAULT, + FAN11_FAULT, + FAN12_FAULT, + FAN_MAX_ATTR +}; +/* Each client has this additional data */ +struct fan_attr_info { + char name[ATTR_NAME_LEN]; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + union { + char strval[STR_ATTR_SIZE]; + int intval; + u16 shortval; + u8 charval; + }val; +}; + +struct fan_data { + struct device *hwmon_dev; + int num_attr; + struct attribute *fan_attribute_list[MAX_FAN_ATTRS]; + struct attribute_group fan_attribute_group; + struct fan_attr_info attr_info[MAX_FAN_ATTRS]; +}; + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_gpio_defs.h b/platform/pddf/i2c/modules/include/pddf_gpio_defs.h new file mode 100644 index 000000000000..a8ee00189bce --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_gpio_defs.h @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description: + * Platform GPIO defines/structures header file + */ + +#ifndef __PAL_GPIO_DEFS_H__ +#define __PAL_GPIO_DEFS_H__ + +#include +/* GPIO CLIENT DATA*/ +typedef struct GPIO_DATA +{ + int gpio_base; // base bus number of the gpio pins +}GPIO_DATA; + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_led_defs.h b/platform/pddf/i2c/modules/include/pddf_led_defs.h new file mode 100644 index 000000000000..1603f8c5af8e --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_led_defs.h @@ -0,0 +1,120 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description + * Platform LED related defines and structures + */ + + +/***************************************** + * kobj list + *****************************************/ + +struct kobject *platform_kobj=NULL; +struct kobject *led_kobj=NULL; + +struct kobject *state_attr_kobj=NULL; +struct kobject *cur_state_kobj=NULL; + +/***************************************** + * Static Data provided from user + * space JSON data file + *****************************************/ +#define NAME_SIZE 32 +typedef enum { + STATUS_LED_COLOR_GREEN, + STATUS_LED_COLOR_GREEN_BLINK, + STATUS_LED_COLOR_RED, + STATUS_LED_COLOR_RED_BLINK, + STATUS_LED_COLOR_AMBER, + STATUS_LED_COLOR_AMBER_BLINK, + STATUS_LED_COLOR_BLUE, + STATUS_LED_COLOR_BLUE_BLINK, + STATUS_LED_COLOR_OFF, + MAX_LED_STATUS +}LED_STATUS; + +char* LED_STATUS_STR[] = { + "STATUS_LED_COLOR_GREEN", + "STATUS_LED_COLOR_GREEN_BLINK", + "STATUS_LED_COLOR_RED", + "STATUS_LED_COLOR_RED_BLINK", + "STATUS_LED_COLOR_AMBER", + "STATUS_LED_COLOR_AMBER_BLINK", + "STATUS_LED_COLOR_BLUE", + "STATUS_LED_COLOR_BLUE_BLINK", + "STATUS_LED_COLOR_OFF" +}; + + +typedef struct +{ + char bits[NAME_SIZE]; + int pos; + int mask_bits; +}MASK_BITS; + +typedef struct +{ + int swpld_addr; + int swpld_addr_offset; + MASK_BITS bits; + unsigned short value; +} LED_DATA; + +typedef struct +{ + int state; + char color[NAME_SIZE]; +} CUR_STATE_DATA; + +typedef struct +{ + CUR_STATE_DATA cur_state; + char device_name[NAME_SIZE]; + int index; + LED_DATA data[MAX_LED_STATUS]; + int swpld_addr; + int swpld_addr_offset; +} LED_OPS_DATA; + +typedef enum{ + LED_SYS, + LED_PSU, + LED_FAN, + LED_FANTRAY, + LED_DIAG, + LED_LOC, + LED_TYPE_MAX +} LED_TYPE; +char* LED_TYPE_STR[LED_TYPE_MAX] = +{ + "LED_SYS", + "LED_PSU", + "LED_FAN", + "LED_FANTRAY", + "LED_DIAG", + "LED_LOC", +}; + +/***************************************** + * Data exported from kernel for + * user space plugin to get/set + *****************************************/ +#define PDDF_LED_DATA_ATTR( _prefix, _name, _mode, _show, _store, _type, _len, _addr) \ + struct pddf_data_attribute pddf_dev_##_prefix##_attr_##_name = { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .type = _type , \ + .len = _len , \ + .addr = _addr } diff --git a/platform/pddf/i2c/modules/include/pddf_mux_defs.h b/platform/pddf/i2c/modules/include/pddf_mux_defs.h new file mode 100644 index 000000000000..c58a00e972c6 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_mux_defs.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description: + * Platform MUX defines/structures header file + */ + +#ifndef __PAL_MUX_DEFS_H__ +#define __PAL_MUX_DEFS_H__ + +#include + +/* MUX CLIENT DATA - PLATFORM DATA FOR PSU CLIENT */ +typedef struct MUX_DATA +{ + int virt_bus; // Virtual base bus number of the mux channels +}MUX_DATA; + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_psu_api.h b/platform/pddf/i2c/modules/include/pddf_psu_api.h new file mode 100644 index 000000000000..762863f02845 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_psu_api.h @@ -0,0 +1,41 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description + * PSU driver related api declarations + */ + +#ifndef __PDDF_PSU_API_H__ +#define __PDDF_PSU_API_H__ + +extern void get_psu_duplicate_sysfs(int idx, char *str); +extern ssize_t psu_show_default(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t psu_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +extern int sonic_i2c_get_psu_present_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_power_good_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_model_name_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_mfr_id_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_serial_num_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_fan_dir_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_v_out_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_i_out_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_p_out_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_fan1_speed_rpm_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_temp1_input_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_v_in_default(void *client, PSU_DATA_ATTR *adata, void *data); +extern int sonic_i2c_get_psu_i_in_default(void *client, PSU_DATA_ATTR *adata, void *data); + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_psu_defs.h b/platform/pddf/i2c/modules/include/pddf_psu_defs.h new file mode 100644 index 000000000000..60e81a9f5878 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_psu_defs.h @@ -0,0 +1,90 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description: + * Platform PSU defines/structures header file + */ + +#ifndef __PDDF_PSU_DEFS_H__ +#define __PDDF_PSU_DEFS_H__ + + +#define MAX_NUM_PSU 5 +#define MAX_PSU_ATTRS 32 +#define ATTR_NAME_LEN 32 +#define STR_ATTR_SIZE 32 +#define DEV_TYPE_LEN 32 + +/* Each client has this additional data + */ + +typedef struct PSU_DATA_ATTR +{ + char aname[ATTR_NAME_LEN]; // attr name, taken from enum psu_sysfs_attributes + char devtype[DEV_TYPE_LEN]; // either a 'eeprom' or 'cpld', or 'pmbus' attribute + char devname[DEV_TYPE_LEN]; // Name of the device from where this sysfs attr is read + uint32_t devaddr; + uint32_t offset; + uint32_t mask; + uint32_t cmpval; + uint32_t len; + void *access_data; + +}PSU_DATA_ATTR; + +typedef struct PSU_SYSFS_ATTR_DATA +{ + int index; + unsigned short mode; + ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf); + int (*pre_get)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*do_get)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*post_get)(void *client, PSU_DATA_ATTR *adata, void *data); + ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + int (*pre_set)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*do_set)(void *client, PSU_DATA_ATTR *adata, void *data); + int (*post_set)(void *client, PSU_DATA_ATTR *adata, void *data); + void *data; +} PSU_SYSFS_ATTR_DATA; + +typedef struct PSU_SYSFS_ATTR_DATA_ENTRY +{ + char name[ATTR_NAME_LEN]; + PSU_SYSFS_ATTR_DATA *a_ptr; +} PSU_SYSFS_ATTR_DATA_ENTRY; + + +/* PSU CLIENT DATA - PLATFORM DATA FOR PSU CLIENT */ +typedef struct PSU_DATA +{ + int idx; // psu index + int num_psu_fans; + PSU_DATA_ATTR psu_attr; + int len; // no of valid attributes for this psu client + PSU_DATA_ATTR psu_attrs[MAX_PSU_ATTRS]; +}PSU_DATA; + +typedef struct PSU_PDATA +{ + int idx; // psu index + int num_psu_fans; // num of fans supported by the PSU + int len; // no of valid attributes for this psu client + PSU_DATA_ATTR *psu_attrs; +}PSU_PDATA; + +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_psu_driver.h b/platform/pddf/i2c/modules/include/pddf_psu_driver.h new file mode 100644 index 000000000000..a2aa3f41d397 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_psu_driver.h @@ -0,0 +1,65 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description + * PSU driver data structures + */ +#ifndef __PDDF_PSU_DRIVER_H__ +#define __PDDF_PSU_DRIVER_H__ + +enum psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_MFR_ID, + PSU_SERIAL_NUM, + PSU_FAN_DIR, + PSU_V_OUT, + PSU_I_OUT, + PSU_P_OUT, /* This is in micro watts to comply with lm-sensors */ + PSU_FAN1_SPEED, + PSU_TEMP1_INPUT, + PSU_V_IN, + PSU_I_IN, + PSU_ATTR_MAX +}; + + +/* Every client has psu_data which is divided into per attribute data */ +struct psu_attr_info { + char name[ATTR_NAME_LEN]; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 status; + union { + char strval[STR_ATTR_SIZE]; + int intval; + u16 shortval; + u8 charval; + }val; +}; +struct psu_data { + struct device *hwmon_dev; + u8 index; + int num_psu_fans; + int num_attr; + struct attribute *psu_attribute_list[MAX_PSU_ATTRS]; + struct attribute_group psu_attribute_group; + struct psu_attr_info attr_info[MAX_PSU_ATTRS]; +}; + + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_sysstatus_defs.h b/platform/pddf/i2c/modules/include/pddf_sysstatus_defs.h new file mode 100644 index 000000000000..fd23f214d204 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_sysstatus_defs.h @@ -0,0 +1,51 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description + * Platform system status module structures + */ + +#ifndef __PDDF_SYSSTATUS_DEFS_H__ +#define __PDDF_SYSSTATUS_DEFS_H__ + + +#define ATTR_NAME_LEN 32 +#define MAX_ATTRS 32 + + +/* SYSSTATUS CLIENT DATA - PLATFORM DATA FOR SYSSTATUS CLIENT */ +typedef struct SYSSTATUS_ADDR_ATTR +{ + char aname[ATTR_NAME_LEN]; // attr name + uint32_t devaddr; + uint32_t offset; + uint32_t mask; + uint32_t len; + +}SYSSTATUS_ADDR_ATTR; + + +typedef struct SYSSTATUS_DATA +{ + int len; + SYSSTATUS_ADDR_ATTR sysstatus_addr_attr; + SYSSTATUS_ADDR_ATTR sysstatus_addr_attrs[MAX_ATTRS]; + +}SYSSTATUS_DATA; + + + + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_xcvr_api.h b/platform/pddf/i2c/modules/include/pddf_xcvr_api.h new file mode 100644 index 000000000000..4a1ce00d5581 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_xcvr_api.h @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description + * Optics driver related api declarations + */ +#ifndef __PDDF_XCVR_API_H__ +#define __PDDF_XCVR_API_H__ + +extern int sonic_i2c_get_mod_pres(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data); +extern int sonic_i2c_get_mod_reset(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data); +extern int sonic_i2c_get_mod_intr_status(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data); +extern int sonic_i2c_get_mod_lpmode(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data); +extern int sonic_i2c_get_mod_rxlos(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data); +extern int sonic_i2c_get_mod_txdisable(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data); +extern int sonic_i2c_get_mod_txfault(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data); +extern int sonic_i2c_set_mod_lpmode(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data); +extern int sonic_i2c_set_mod_reset(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data); +extern int sonic_i2c_set_mod_txdisable(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data); + +extern ssize_t get_module_presence(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t get_module_reset(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t set_module_reset(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern ssize_t get_module_intr_status(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t get_module_lpmode(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t set_module_lpmode(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern ssize_t get_module_rxlos(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t get_module_txdisable(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t set_module_txdisable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern ssize_t get_module_txfault(struct device *dev, struct device_attribute *da, char *buf); + +#endif diff --git a/platform/pddf/i2c/modules/include/pddf_xcvr_defs.h b/platform/pddf/i2c/modules/include/pddf_xcvr_defs.h new file mode 100644 index 000000000000..63de2eeae0c2 --- /dev/null +++ b/platform/pddf/i2c/modules/include/pddf_xcvr_defs.h @@ -0,0 +1,121 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description: + * Platform SFP defines/structures header file + */ + +#ifndef __PDDF_XCVR_DEFS_H__ +#define __PDDF_XCVR_DEFS_H__ + + +#define MAX_NUM_XCVR 5 +#define MAX_XCVR_ATTRS 20 + + +typedef struct XCVR_ATTR +{ + char aname[32]; // attr name, taken from enum xcvr_sysfs_attributes + char devtype[32]; // either a 'eeprom' or 'cpld', or 'pmbus' attribute + char devname[32]; // name of the device from where this sysfs is to be read + uint32_t devaddr; + uint32_t offset; + uint32_t mask; + uint32_t cmpval; + uint32_t len; + + int (*pre_access)(void *client, void *data); + int (*do_access)(void *client, void *data); + int (*post_access)(void *client, void *data); + +}XCVR_ATTR; + +/* XCVR CLIENT DATA - PLATFORM DATA FOR XCVR CLIENT */ +typedef struct XCVR_DATA +{ + int idx; // xcvr index + XCVR_ATTR xcvr_attr; + int len; // no of valid attributes for this xcvr client + XCVR_ATTR xcvr_attrs[MAX_XCVR_ATTRS]; +}XCVR_DATA; + +typedef struct XCVR_PDATA +{ + int idx; // xcvr index + unsigned short addr; // i2c address of the device + int len; // no of valid attributes for this xcvr client + XCVR_ATTR *xcvr_attrs; +}XCVR_PDATA; + + +#define BIT_INDEX(i) (1ULL << (i)) + +/* List of valid port types */ +typedef enum xcvr_port_type_e { + PDDF_PORT_TYPE_INVALID, + PDDF_PORT_TYPE_NOT_PRESENT, + PDDF_PORT_TYPE_SFP, + PDDF_PORT_TYPE_SFP_PLUS, + PDDF_PORT_TYPE_QSFP, + PDDF_PORT_TYPE_QSFP_PLUS, + PDDF_PORT_TYPE_QSFP28 +} xcvr_port_type_t; + +/* Each client has this additional data + */ +struct xcvr_data { + struct device *xdev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + int index; /* port index */ + xcvr_port_type_t port_type; + uint32_t modpres; + uint32_t reset; + uint32_t intr_status; + uint32_t lpmode; + uint32_t rxlos; + uint32_t txdisable; + uint32_t txfault; +}; + +typedef struct XCVR_SYSFS_ATTR_OPS +{ + int index; + ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf); + int (*pre_get)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data); + int (*do_get)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data); + int (*post_get)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data); + ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + int (*pre_set)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data); + int (*do_set)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data); + int (*post_set)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data); +} XCVR_SYSFS_ATTR_OPS; + +enum xcvr_sysfs_attributes { + XCVR_PRESENT, + XCVR_RESET, + XCVR_INTR_STATUS, + XCVR_LPMODE, + XCVR_RXLOS, + XCVR_TXDISABLE, + XCVR_TXFAULT, + XCVR_ATTR_MAX +}; + +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#endif diff --git a/platform/pddf/i2c/modules/led/Makefile b/platform/pddf/i2c/modules/led/Makefile new file mode 100644 index 000000000000..0c450ec70b4c --- /dev/null +++ b/platform/pddf/i2c/modules/led/Makefile @@ -0,0 +1,4 @@ +TARGET := pddf_led_module +obj-m := $(TARGET).o + +CFLAGS_$(obj-m):= -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/led/pddf_led_module.c b/platform/pddf/i2c/modules/led/pddf_led_module.c new file mode 100644 index 000000000000..362467e5ab98 --- /dev/null +++ b/platform/pddf/i2c/modules/led/pddf_led_module.c @@ -0,0 +1,659 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel module to manage various LEDs of a switch + */ + +#include +#include +#include +#include +#include +#include +#include "pddf_led_defs.h" +#include "pddf_client_defs.h" +#include +#include +#include + +#define DEBUG 0 +LED_OPS_DATA sys_led_ops_data[1]={0}; +LED_OPS_DATA* psu_led_ops_data=NULL; +LED_OPS_DATA diag_led_ops_data[1]= {0}; +LED_OPS_DATA fan_led_ops_data[1]= {0}; +LED_OPS_DATA loc_led_ops_data[1]= {0}; +LED_OPS_DATA* fantray_led_ops_data=NULL; +LED_OPS_DATA temp_data={0}; +LED_OPS_DATA* dev_list[LED_TYPE_MAX] = { + sys_led_ops_data, + NULL, + fan_led_ops_data, + NULL, + diag_led_ops_data, + loc_led_ops_data, +}; +int num_psus = 0; +int num_fantrays = 0; + +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, char *buf); +extern ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + +static LED_STATUS find_state_index(const char* state_str) { + int index; + char *ptr = (char *)state_str; + while (*ptr && *ptr!= '\n' && *ptr !='\0') ptr++; + *ptr='\0'; + for ( index = 0; index < MAX_LED_STATUS; index++) { + /*int rc = strcmp(state_str, LED_STATUS_STR[index]) ;*/ + if (strcmp(state_str, LED_STATUS_STR[index]) == 0 ) { + return index; + } + } + return MAX_LED_STATUS; +} + +static LED_TYPE get_dev_type(char* name) +{ + LED_TYPE ret = LED_TYPE_MAX; + if(strcasecmp(name, "SYS_LED")==0) { + ret = LED_SYS; + } else if(strcasecmp(name, "FAN_LED")==0) { + ret = LED_FAN; + } else if(strstr(name, "PSU_LED")) { + ret = LED_PSU; + } else if(strcasecmp(name, "DIAG_LED")==0) { + ret = LED_DIAG; + } else if(strcasecmp(name, "LOC_LED")==0) { + ret = LED_LOC; + } else if(strstr(name, "FANTRAY_LED")) { + ret = LED_FANTRAY; + } +#if DEBUG > 1 + pddf_dbg(LED, KERN_INFO "LED get_dev_type: %s; %d\n", name, ret); +#endif + return (ret); +} +static int dev_index_check(LED_TYPE type, int index) +{ +#if DEBUG + pddf_dbg(LED, "dev_index_check: type:%s index:%d num_psus:%d num_fantrays:%d\n", + LED_TYPE_STR[type], index, num_psus, num_fantrays); +#endif + switch(type) + { + case LED_PSU: + if(index >= num_psus) return (-1); + break; + case LED_FANTRAY: + if(index >= num_fantrays) return (-1); + break; + default: + if(index >= 1) return (-1); + break; + } + return (0); +} + +static LED_OPS_DATA* find_led_ops_data(struct device_attribute *da) +{ + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* ptr=(LED_OPS_DATA*)_ptr->addr; + LED_TYPE led_type; + if(!ptr || strlen(ptr->device_name)==0 ) return(NULL); + + + if((led_type=get_dev_type(ptr->device_name))==LED_TYPE_MAX) { + printk(KERN_ERR "PDDF_LED ERROR *%s Unsupported Led Type\n", __func__); + return(NULL); + } + if(dev_index_check(led_type, ptr->index)==-1) { + printk(KERN_ERR "PDDF_LED ERROR %s invalid index: %d for type:%s\n", __func__, ptr->index, ptr->device_name); + return(NULL); + } +#if DEBUG > 1 + pddf_dbg(LED, "find_led_ops_data: name:%s; index=%d tempAddr:%p actualAddr:%p\n", + ptr->device_name, ptr->index, ptr, dev_list[led_type]+ptr->index); +#endif + return (dev_list[led_type]+ptr->index); +} + +static void print_led_data(LED_OPS_DATA *ptr, LED_STATUS state) +{ + int i = 0; + if(!ptr) return ; + pddf_dbg(LED, KERN_INFO "Print %s index:%d num_psus:%d num_fantrays:%d ADDR=%p\n", + ptr->device_name, ptr->index, num_psus, num_fantrays, ptr); + pddf_dbg(LED, KERN_INFO "\tindex: %d\n", ptr->index); + pddf_dbg(LED, KERN_INFO "\tcur_state: %d; %s \n", ptr->cur_state.state, ptr->cur_state.color); + for (i = 0; i< MAX_LED_STATUS; i++) { + if(ptr->data[i].swpld_addr && (i == state || state == -1)) { + pddf_dbg(LED, KERN_INFO "\t\t[%s]: addr/offset:0x%x;0x%x color:%s; value:%x; mask_bits: 0x%x; pos:%d\n", + LED_STATUS_STR[i], + ptr->data[i].swpld_addr, ptr->data[i].swpld_addr_offset, + LED_STATUS_STR[i], ptr->data[i].value, ptr->data[i].bits.mask_bits, ptr->data[i].bits.pos); + } + } +} + +ssize_t get_status_led(struct device_attribute *da) +{ + int ret=0; + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* temp_data_ptr=(LED_OPS_DATA*)_ptr->addr; + LED_OPS_DATA* ops_ptr=find_led_ops_data(da); + uint32_t color_val=0, sys_val=0; + int state=0; + if (!ops_ptr) { + pddf_dbg(LED, KERN_ERR "ERROR %s: Cannot find LED Ptr", __func__); + return (-1); + } + if (ops_ptr->swpld_addr == 0x0) { + pddf_dbg(LED, KERN_ERR "ERROR %s: device: %s %d not configured\n", __func__, + temp_data_ptr->device_name, temp_data_ptr->index); + return (-1); + } + sys_val = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + if (sys_val < 0) + return sys_val; + + strcpy(temp_data.cur_state.color, "None"); + for (state=0; statedata[state].bits.mask_bits); + if ((color_val ^ (ops_ptr->data[state].value<data[state].bits.pos))==0) { + strcpy(temp_data.cur_state.color, LED_STATUS_STR[state]); + } + } +#if DEBUG > 1 + pddf_dbg(LED, KERN_ERR "Get : %s:%d addr/offset:0x%x; 0x%x value=0x%x [%s]\n", + ops_ptr->device_name, ops_ptr->index, + ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, sys_val, + temp_data.cur_state.color); +#endif + + return(ret); +} + +ssize_t set_status_led(struct device_attribute *da) +{ + int ret=0; + uint32_t sys_val=0, new_val=0; + LED_STATUS cur_state = MAX_LED_STATUS; + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* temp_data_ptr=(LED_OPS_DATA*)_ptr->addr; + LED_OPS_DATA* ops_ptr=find_led_ops_data(da); + char* _buf=temp_data_ptr->cur_state.color; + + if (!ops_ptr) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s: Cannot find LED Ptr", __func__); + return (-1); + } + if (ops_ptr->swpld_addr == 0x0) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s: device: %s %d not configured\n", + __func__, ops_ptr->device_name, ops_ptr->index); + return (-1); + } + pddf_dbg(LED, KERN_ERR "%s: Set [%s;%d] color[%s]\n", __func__, + temp_data_ptr->device_name, temp_data_ptr->index, + temp_data_ptr->cur_state.color); + cur_state = find_state_index(_buf); + + if (cur_state == MAX_LED_STATUS) { + pddf_dbg(LED, KERN_ERR "ERROR %s: not supported: %s\n", _buf, __func__); + return (-1); + } + + if(ops_ptr->data[cur_state].swpld_addr != 0x0) { + sys_val = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + if (sys_val < 0) + return sys_val; + + new_val = (sys_val & ops_ptr->data[cur_state].bits.mask_bits) | + (ops_ptr->data[cur_state].value << ops_ptr->data[cur_state].bits.pos); + + } else { + pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d state %d; %s not configured\n",__func__, + ops_ptr->device_name, ops_ptr->index, cur_state, _buf); + return (-1); + } + + board_i2c_cpld_write(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, new_val); + pddf_dbg(LED, KERN_INFO "Set color:%s; 0x%x:0x%x sys_val:0x%x new_val:0x%x read:0x%x\n", + LED_STATUS_STR[cur_state], + ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, + sys_val, new_val, + ret = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset)); + if (ret < 0) + { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s: Error %d in reading from cpld(0x%x) offset 0x%x\n", __FUNCTION__, ret, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset); + return ret; + } + return(ret); +} + + +ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, + char *buf) +{ + int ret = 0; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + switch(ptr->type) + { + case PDDF_CHAR: + ret = sprintf(buf, "%s\n", ptr->addr); + break; + case PDDF_INT_DEC: + ret = sprintf(buf, "%d\n", *(int*)(ptr->addr)); + break; + case PDDF_INT_HEX: + ret = sprintf(buf, "0x%x\n", *(int*)(ptr->addr)); + break; + case PDDF_USHORT: + ret = sprintf(buf, "0x%x\n", *(unsigned short *)(ptr->addr)); + break; + case PDDF_UINT32: + ret = sprintf(buf, "0x%x\n", *(uint32_t *)(ptr->addr)); + break; + default: + break; + } +#if DEBUG > 1 + pddf_dbg(LED, "[ READ ] DATA ATTR PTR [%s] TYPE:%d, Value:[%s]\n", + ptr->dev_attr.attr.name, ptr->type, buf); +#endif + return ret; +} + +ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int ret = 0, num = 0; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + switch(ptr->type) + { + case PDDF_CHAR: + strncpy(ptr->addr, buf, strlen(buf)-1); // to discard newline char form buf + ptr->addr[strlen(buf)-1] = '\0'; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_CHAR VALUE:%s\n", + ptr->dev_attr.attr.name, ptr->addr); +#endif + break; + case PDDF_INT_DEC: + ret = kstrtoint(buf,10,&num); + if (ret==0) + *(int *)(ptr->addr) = num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_DEC VALUE:%d\n", + ptr->dev_attr.attr.name, *(int *)(ptr->addr)); +#endif + break; + case PDDF_INT_HEX: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(int *)(ptr->addr) = num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_HEX VALUE:0x%x\n", + ptr->dev_attr.attr.name, *(int *)(ptr->addr)); +#endif + break; + case PDDF_USHORT: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(unsigned short *)(ptr->addr) = (unsigned short)num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_USHORT VALUE:%x\n", + ptr->dev_attr.attr.name, *(unsigned short *)(ptr->addr)); +#endif + break; + case PDDF_UINT32: + ret = kstrtoint(buf,16,&num); + if (ret==0) + *(uint32_t *)(ptr->addr) = (uint32_t)num; +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_UINT32 VALUE:%d\n", + ptr->dev_attr.attr.name, *(uint32_t *)(ptr->addr)); +#endif + break; + default: + break; + } + return count; +} + +static int load_led_ops_data(struct device_attribute *da, LED_STATUS state) +{ + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* ptr=(LED_OPS_DATA*)_ptr->addr; + LED_TYPE led_type; + LED_OPS_DATA* ops_ptr=NULL; + if(!ptr || strlen(ptr->device_name)==0 ) { + pddf_dbg(LED, KERN_INFO "SYSTEM_LED: load_led_ops_data return -1 device_name:%s\n", ptr? ptr->device_name:"NULL"); + return(-1); + } + if(ptr->device_name) + { + pddf_dbg(LED, KERN_INFO "[%s]: load_led_ops_data: index=%d addr=0x%x;0x%x valu=0x%x\n", + ptr->device_name, ptr->index, ptr->swpld_addr, ptr->swpld_addr_offset, ptr->data[0].value); + } + if((led_type=get_dev_type(ptr->device_name))==LED_TYPE_MAX) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR *%s Unsupported Led Type\n", __func__); + return(-1); + } + if(dev_index_check(led_type, ptr->index)==-1) { + pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s invalid index: %d for type:%d\n", __func__, ptr->index, led_type); + return(-1); + } + ops_ptr = dev_list[led_type]+ptr->index; + + memcpy(ops_ptr->device_name, ptr->device_name, sizeof(ops_ptr->device_name)); + ops_ptr->index = ptr->index; + memcpy(&ops_ptr->data[state], &ptr->data[0], sizeof(LED_DATA)); + ops_ptr->data[state].swpld_addr = ptr->swpld_addr; + ops_ptr->data[state].swpld_addr_offset = ptr->swpld_addr_offset; + ops_ptr->swpld_addr = ptr->swpld_addr; + ops_ptr->swpld_addr_offset = ptr->swpld_addr_offset; + + print_led_data(dev_list[led_type]+ptr->index, state); + + memset(ptr, 0, sizeof(LED_OPS_DATA)); + return (0); +} + +static int show_led_ops_data(struct device_attribute *da) +{ + LED_OPS_DATA* ops_ptr=find_led_ops_data(da); + print_led_data(ops_ptr, -1); + return(0); +} + +static int verify_led_ops_data(struct device_attribute *da) +{ + struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da; + LED_OPS_DATA* ptr=(LED_OPS_DATA*)_ptr->addr; + LED_OPS_DATA* ops_ptr=find_led_ops_data(da); + + if(ops_ptr) + memcpy(ptr, ops_ptr, sizeof(LED_OPS_DATA)); + else + { + pddf_dbg(LED, "SYSTEM_LED: verify_led_ops_data: Failed to find ops_ptr name:%s; index=%d\n", ptr->device_name, ptr->index); + } + return (0); +} + + +ssize_t dev_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ +#if DEBUG + pddf_dbg(LED, KERN_INFO "dev_operation [%s]\n", buf); +#endif + if(strstr(buf, "STATUS_LED_COLOR")!= NULL) { + LED_STATUS index = find_state_index(buf); + if (index < MAX_LED_STATUS ) { + load_led_ops_data(da, index); + } else { + printk(KERN_ERR "PDDF_ERROR %s: Invalid state for dev_ops %s", __FUNCTION__, buf); + } + } + else if(strncmp(buf, "show", strlen("show"))==0 ) { + show_led_ops_data(da); + } + else if(strncmp(buf, "verify", strlen("verify"))==0 ) { + verify_led_ops_data(da); + } + else if(strncmp(buf, "get_status", strlen("get_status"))==0 ) { + get_status_led(da); + } + else if(strncmp(buf, "set_status", strlen("set_status"))==0 ) { + set_status_led(da); + } + else { + printk(KERN_ERR "PDDF_ERROR %s: Invalid value for dev_ops %s", __FUNCTION__, buf); + } + return(count); +} + +ssize_t store_config_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int ret, num; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + if(strncmp(ptr->dev_attr.attr.name, "num_psus", strlen("num_psus"))==0 ) { + ret = kstrtoint(buf,10,&num); + if (ret==0) + *(int *)(ptr->addr) = num; + if(psu_led_ops_data == NULL) { + if ((psu_led_ops_data = kzalloc(num * sizeof(LED_OPS_DATA), GFP_KERNEL)) == NULL) { + printk(KERN_ERR "PDDF_LED ERROR failed to allocate memory for PSU LED\n"); + return (count); + } + pddf_dbg(LED, "Allocate PSU LED Memory ADDR=%p\n", psu_led_ops_data); + dev_list[LED_PSU]=psu_led_ops_data; + } +#if DEBUG + pddf_dbg(LED, "[ WRITE ] ATTR CONFIG [%s] VALUE:%d; %d\n", + ptr->dev_attr.attr.name, num, num_psus); +#endif + return(count); + } + if(strncmp(ptr->dev_attr.attr.name, "num_fantrays", strlen("num_fantrays"))==0 ) { + ret = kstrtoint(buf,10,&num); + if (ret==0) + *(int *)(ptr->addr) = num; + if (fantray_led_ops_data == NULL) { + if ((fantray_led_ops_data = kzalloc(num * sizeof(LED_OPS_DATA), GFP_KERNEL)) == NULL) { + printk(KERN_ERR "PDDF_LED ERROR failed to allocate memory for FANTRAY LED\n"); + return (count); + } + pddf_dbg(LED, "Allocate FanTray LED Memory ADDR=%p\n", fantray_led_ops_data); + dev_list[LED_FANTRAY]=fantray_led_ops_data; + } +#if DEBUG + pddf_dbg(LED, "[ WRITE ] ATTR CONFIG [%s] VALUE:%d; %d\n", + ptr->dev_attr.attr.name, num, num_fantrays); +#endif + return(count); + } + return (count); +} + +ssize_t store_bits_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int len = 0, num1 = 0, num2 = 0, i=0, rc1=0, rc2=0; + char mask=0xFF; + char *pptr=NULL; + char bits[NAME_SIZE]; + struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da; + MASK_BITS* bits_ptr=(MASK_BITS*)(ptr->addr); + strncpy(bits_ptr->bits, buf, strlen(buf)-1); // to discard newline char form buf + bits_ptr->bits[strlen(buf)-1] = '\0'; + if((pptr=strstr(buf,":")) != NULL) { + len=pptr-buf; + sprintf(bits, buf); + bits[len]='\0'; + rc1=kstrtoint(bits,16,&num1); + if (rc1==0) + { + sprintf(bits, ++pptr); + rc2=kstrtoint(bits,16,&num2); + if (rc2==0) + { + for (i=num2; i<=num1; i++) { + mask &= ~(1 << i); + } + bits_ptr->mask_bits = mask; + bits_ptr->pos = num2; + } + } + } else { + rc1=kstrtoint(buf,16,&num1); + if (rc1==0) + { + bits_ptr->mask_bits = mask & ~(1 << num1); + bits_ptr->pos = num1; + } + } +#if DEBUG + pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR Bits [%s] VALUE:%s mask:0x%x; pos:0x%x\n", + ptr->dev_attr.attr.name, bits_ptr->bits, bits_ptr->mask_bits, bits_ptr->pos); +#endif + return (count); +} + +/************************************************************************** + * platform/ attributes + **************************************************************************/ +PDDF_LED_DATA_ATTR(platform, num_psus, S_IWUSR|S_IRUGO, show_pddf_data, + store_config_data, PDDF_INT_DEC, sizeof(int), (void*)&num_psus); +PDDF_LED_DATA_ATTR(platform, num_fantrays, S_IWUSR|S_IRUGO, show_pddf_data, + store_config_data, PDDF_INT_DEC, sizeof(int), (void*)&num_fantrays); + +struct attribute* attrs_platform[]={ + &pddf_dev_platform_attr_num_psus.dev_attr.attr, + &pddf_dev_platform_attr_num_fantrays.dev_attr.attr, + NULL, +}; +struct attribute_group attr_group_platform={ + .attrs = attrs_platform, +}; + +/************************************************************************** + * led/ attributes + **************************************************************************/ +PDDF_LED_DATA_ATTR(dev, device_name, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.device_name); +PDDF_LED_DATA_ATTR(dev, index, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&temp_data.index); +PDDF_LED_DATA_ATTR(dev, swpld_addr, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&temp_data.swpld_addr); +PDDF_LED_DATA_ATTR(dev, swpld_addr_offset, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&temp_data.swpld_addr_offset); +PDDF_LED_DATA_ATTR(dev, dev_ops , S_IWUSR, NULL, + dev_operation, PDDF_CHAR, NAME_SIZE, (void*)&temp_data); + +struct attribute* attrs_dev[]={ + &pddf_dev_dev_attr_device_name.dev_attr.attr, + &pddf_dev_dev_attr_index.dev_attr.attr, + &pddf_dev_dev_attr_swpld_addr.dev_attr.attr, + &pddf_dev_dev_attr_swpld_addr_offset.dev_attr.attr, + &pddf_dev_dev_attr_dev_ops.dev_attr.attr, + NULL, +}; +struct attribute_group attr_group_dev={ + .attrs = attrs_dev, +}; + +/************************************************************************** + * state_attr/ attributes + **************************************************************************/ +#define LED_DEV_STATE_ATTR_GROUP(name, func) \ + PDDF_LED_DATA_ATTR(name, bits, S_IWUSR|S_IRUGO, show_pddf_data, \ + store_bits_data, PDDF_CHAR, NAME_SIZE, func.bits.bits); \ + PDDF_LED_DATA_ATTR(name, value, S_IWUSR|S_IRUGO, show_pddf_data, \ + store_pddf_data, PDDF_USHORT, sizeof(unsigned short), func.value); \ + struct attribute* attrs_##name[]={ \ + &pddf_dev_##name##_attr_bits.dev_attr.attr, \ + &pddf_dev_##name##_attr_value.dev_attr.attr, \ + NULL, \ + }; \ + struct attribute_group attr_group_##name={ \ + .attrs = attrs_##name, \ + }; \ + + +LED_DEV_STATE_ATTR_GROUP(state_attr, (void*)&temp_data.data[0]) + +/************************************************************************** + * cur_state/ attributes + **************************************************************************/ +PDDF_LED_DATA_ATTR(cur_state, color, S_IWUSR|S_IRUGO, show_pddf_data, + store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.cur_state.color); + +struct attribute* attrs_cur_state[]={ + &pddf_dev_cur_state_attr_color.dev_attr.attr, + NULL, +}; +struct attribute_group attr_group_cur_state={ + .attrs = attrs_cur_state, +}; + +/*************************************************************************/ +#define KOBJ_FREE(obj) \ + if(obj) kobject_put(obj); \ + +void free_kobjs(void) +{ + KOBJ_FREE(cur_state_kobj) + KOBJ_FREE(state_attr_kobj) + KOBJ_FREE(led_kobj) + KOBJ_FREE(platform_kobj) +} + +int KBOJ_CREATE(char* name, struct kobject* parent, struct kobject** child) +{ + if (parent) { + *child = kobject_create_and_add(name, parent); + } else { + printk(KERN_ERR "PDDF_LED ERROR to create %s kobj; null parent\n", name); + free_kobjs(); + return (-ENOMEM); + } + return (0); +} + +int LED_DEV_ATTR_CREATE(struct kobject *kobj, const struct attribute_group *attr, const char* name) +{ + int status = sysfs_create_group(kobj, attr); + if(status) { + pddf_dbg(LED, KERN_ERR "Driver ERROR: sysfs_create %s failed rc=%d\n", name, status); + } + return (status); +} + + +static int __init led_init(void) { + struct kobject *device_kobj; + pddf_dbg(LED, KERN_INFO "PDDF GENERIC LED MODULE init..\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + KBOJ_CREATE("platform", device_kobj, &platform_kobj); + KBOJ_CREATE("led", device_kobj, &led_kobj); + KBOJ_CREATE("state_attr", led_kobj, &state_attr_kobj); + KBOJ_CREATE("cur_state", led_kobj, &cur_state_kobj); + + LED_DEV_ATTR_CREATE(platform_kobj, &attr_group_platform, "attr_group_platform"); + LED_DEV_ATTR_CREATE(led_kobj, &attr_group_dev, "attr_group_dev"); + LED_DEV_ATTR_CREATE(state_attr_kobj, &attr_group_state_attr, "attr_group_state_attr"); + LED_DEV_ATTR_CREATE(cur_state_kobj, &attr_group_cur_state, "attr_group_cur_state"); + return (0); +} + + +static void __exit led_exit(void) { + pddf_dbg(LED, "PDDF GENERIC LED MODULE exit..\n"); + free_kobjs(); + if(psu_led_ops_data) kfree(psu_led_ops_data); + if(fantray_led_ops_data) kfree(fantray_led_ops_data); +} + +module_init(led_init); +module_exit(led_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("led driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/modules/mux/Makefile b/platform/pddf/i2c/modules/mux/Makefile new file mode 100644 index 000000000000..486e7033435f --- /dev/null +++ b/platform/pddf/i2c/modules/mux/Makefile @@ -0,0 +1,4 @@ + +obj-m := pddf_mux_module.o + +CFLAGS_$(obj-m):= -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/mux/pddf_mux_module.c b/platform/pddf/i2c/modules/mux/pddf_mux_module.c new file mode 100644 index 000000000000..b0cd9e761ca7 --- /dev/null +++ b/platform/pddf/i2c/modules/mux/pddf_mux_module.c @@ -0,0 +1,211 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel module to create I2C client for pca954x type of multiplexer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_mux_defs.h" + + +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern void* get_device_table(char *name); +extern void delete_device_table(char *name); + + +MUX_DATA mux_data = {0}; + +/* MUX CLIENT DATA */ +PDDF_DATA_ATTR(virt_bus, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&mux_data.virt_bus, NULL); +PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&mux_data, (void*)&pddf_data); + + + +static struct attribute *mux_attributes[] = { + &attr_virt_bus.dev_attr.attr, + &attr_dev_ops.dev_attr.attr, + NULL +}; + +static const struct attribute_group pddf_mux_client_data_group = { + .attrs = mux_attributes, +}; + +struct i2c_board_info *i2c_get_mux_board_info(MUX_DATA* mdata, NEW_DEV_ATTR *device_data) +{ + static struct i2c_board_info board_info; + static struct pca954x_platform_mode platform_modes[8]; + static struct pca954x_platform_data mux_platform_data; + int num_modes, i; + + if (strncmp(device_data->dev_type, "pca9548", strlen("pca9548")) == 0) + num_modes = 8; + else if (strncmp(device_data->dev_type, "pca9546", strlen("pca9546")) == 0) + num_modes = 6; + else + { + printk(KERN_ERR "%s: Unknown type of mux device\n", __FUNCTION__); + return NULL; + } + + for(i = 0; i < num_modes; i++) { + platform_modes[i] = (struct pca954x_platform_mode) { + .adap_id = (mdata->virt_bus + i), + .deselect_on_exit = 1, + }; + } + + mux_platform_data = (struct pca954x_platform_data) { + .modes = platform_modes, + .num_modes = num_modes, + }; + + board_info = (struct i2c_board_info) { + .platform_data = &mux_platform_data, + }; + + board_info.addr = device_data->dev_addr; + strcpy(board_info.type, device_data->dev_type); + + return &board_info; +} + + +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + MUX_DATA *mux_ptr = (MUX_DATA *)(ptr->addr); + NEW_DEV_ATTR *device_ptr = (NEW_DEV_ATTR *)(ptr->data); + struct i2c_adapter *adapter; + struct i2c_board_info *board_info; + struct i2c_client *client_ptr; + + if (strncmp(buf, "add", strlen(buf)-1)==0) + { + adapter = i2c_get_adapter(device_ptr->parent_bus); + board_info = i2c_get_mux_board_info(mux_ptr, device_ptr); + + client_ptr = i2c_new_device(adapter, board_info); + + if (client_ptr != NULL) + { + i2c_put_adapter(adapter); + pddf_dbg(MUX, KERN_ERR "Created %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr); + add_device_table(device_ptr->i2c_name, (void*)client_ptr); + } + else + { + i2c_put_adapter(adapter); + goto free_data; + } + } + else if (strncmp(buf, "delete", strlen(buf)-1)==0) + { + /*Get the i2c_client handle for the created client*/ + client_ptr = (struct i2c_client *)get_device_table(device_ptr->i2c_name); + if (client_ptr) + { + pddf_dbg(MUX, KERN_ERR "Removing %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr); + i2c_unregister_device(client_ptr); + /*TODO: Nullyfy the platform data*/ + delete_device_table(device_ptr->i2c_name); + } + else + { + printk(KERN_ERR "Unable to get the client handle for %s\n", device_ptr->i2c_name); + } + } + else + { + printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf); + } + +free_data: + memset(mux_ptr, 0, sizeof(MUX_DATA)); + /*TODO: free the device_ptr->data is dynamically allocated*/ + memset(device_ptr, 0 , sizeof(NEW_DEV_ATTR)); + + return count; +} + + +static struct kobject *mux_kobj; + +int __init mux_data_init(void) +{ + struct kobject *device_kobj; + int ret = 0; + + + pddf_dbg(MUX, "MUX_DATA MODULE.. init\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + mux_kobj = kobject_create_and_add("mux", device_kobj); + if(!mux_kobj) + return -ENOMEM; + + + ret = sysfs_create_group(mux_kobj, &pddf_clients_data_group); + if (ret) + { + kobject_put(mux_kobj); + return ret; + } + pddf_dbg(MUX, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n"); + + ret = sysfs_create_group(mux_kobj, &pddf_mux_client_data_group); + if (ret) + { + sysfs_remove_group(mux_kobj, &pddf_clients_data_group); + kobject_put(mux_kobj); + return ret; + } + pddf_dbg(MUX, "CREATED MUX DATA SYSFS GROUP\n"); + + return ret; +} + +void __exit mux_data_exit(void) +{ + pddf_dbg(MUX, "MUX_DATA MODULE.. exit\n"); + sysfs_remove_group(mux_kobj, &pddf_mux_client_data_group); + sysfs_remove_group(mux_kobj, &pddf_clients_data_group); + kobject_put(mux_kobj); + pddf_dbg(MUX, KERN_ERR "%s: Removed the kobjects for 'mux'\n",__FUNCTION__); + return; +} + +module_init(mux_data_init); +module_exit(mux_data_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("mux platform data"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/modules/psu/Makefile b/platform/pddf/i2c/modules/psu/Makefile new file mode 100644 index 000000000000..04db30dfb48b --- /dev/null +++ b/platform/pddf/i2c/modules/psu/Makefile @@ -0,0 +1,4 @@ +subdir-m := driver +obj-m := pddf_psu_module.o + +CFLAGS_$(obj-m):= -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/psu/driver/Makefile b/platform/pddf/i2c/modules/psu/driver/Makefile new file mode 100644 index 000000000000..86d508051382 --- /dev/null +++ b/platform/pddf/i2c/modules/psu/driver/Makefile @@ -0,0 +1,6 @@ +TARGET = pddf_psu_driver_module +obj-m := $(TARGET).o + +$(TARGET)-objs := pddf_psu_api.o pddf_psu_driver.o + +ccflags-y := -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/psu/driver/pddf_psu_api.c b/platform/pddf/i2c/modules/psu/driver/pddf_psu_api.c new file mode 100644 index 000000000000..b6b5e306a000 --- /dev/null +++ b/platform/pddf/i2c/modules/psu/driver/pddf_psu_api.c @@ -0,0 +1,707 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description of various APIs related to PSU component + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_psu_defs.h" +#include "pddf_psu_driver.h" + + +/*#define PSU_DEBUG*/ +#ifdef PSU_DEBUG +#define psu_dbg(...) printk(__VA_ARGS__) +#else +#define psu_dbg(...) +#endif + + +void get_psu_duplicate_sysfs(int idx, char *str) +{ + switch (idx) + { + case PSU_V_OUT: + strcpy(str, "in3_input"); + break; + case PSU_I_OUT: + strcpy(str, "curr2_input"); + break; + case PSU_P_OUT: + strcpy(str, "power2_input"); + break; + case PSU_FAN1_SPEED: + strcpy(str, "fan1_input"); + break; + case PSU_TEMP1_INPUT: + strcpy(str, "temp1_input"); + break; + default: + break; + } + + return; +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +int psu_update_hw(struct device *dev, struct psu_attr_info *info, PSU_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + PSU_SYSFS_ATTR_DATA *sysfs_attr_data = NULL; + + + mutex_lock(&info->update_lock); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_set != NULL) + { + status = (sysfs_attr_data->pre_set)(client, udata, info); + if (status!=0) + printk(KERN_ERR "%s: pre_set function fails for %s attribute\n", __FUNCTION__, udata->aname); + } + if (sysfs_attr_data->do_set != NULL) + { + status = (sysfs_attr_data->do_set)(client, udata, info); + if (status!=0) + printk(KERN_ERR "%s: do_set function fails for %s attribute\n", __FUNCTION__, udata->aname); + + } + if (sysfs_attr_data->post_set != NULL) + { + status = (sysfs_attr_data->post_set)(client, udata, info); + if (status!=0) + printk(KERN_ERR "%s: post_set function fails for %s attribute\n", __FUNCTION__, udata->aname); + } + + mutex_unlock(&info->update_lock); + + return 0; +} + + +int psu_update_attr(struct device *dev, struct psu_attr_info *data, PSU_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + PSU_SYSFS_ATTR_DATA *sysfs_attr_data=NULL; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) + { + dev_dbg(&client->dev, "Starting update for %s\n", data->name); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_get != NULL) + { + status = (sysfs_attr_data->pre_get)(client, udata, data); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, udata->aname); + } + if (sysfs_attr_data->do_get != NULL) + { + status = (sysfs_attr_data->do_get)(client, udata, data); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, udata->aname); + + } + if (sysfs_attr_data->post_get != NULL) + { + status = (sysfs_attr_data->post_get)(client, udata, data); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, udata->aname); + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + return 0; +} + +ssize_t psu_show_default(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + PSU_PDATA *pdata = (PSU_PDATA *)(client->dev.platform_data); + PSU_DATA_ATTR *usr_data = NULL; + struct psu_attr_info *sysfs_attr_info = NULL; + int i, status=0; + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + char new_str[ATTR_NAME_LEN] = ""; + PSU_SYSFS_ATTR_DATA *ptr = NULL; + + for (i=0;inum_attr;i++) + { + ptr = (PSU_SYSFS_ATTR_DATA *)pdata->psu_attrs[i].access_data; + get_psu_duplicate_sysfs(ptr->index , new_str); + if ( strcmp(attr->dev_attr.attr.name, pdata->psu_attrs[i].aname) == 0 || strcmp(attr->dev_attr.attr.name, new_str) == 0 ) + { + sysfs_attr_info = &data->attr_info[i]; + usr_data = &pdata->psu_attrs[i]; + strcpy(new_str, ""); + } + } + + if (sysfs_attr_info==NULL || usr_data==NULL) + { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + psu_update_attr(dev, sysfs_attr_info, usr_data); + + switch(attr->index) + { + case PSU_PRESENT: + case PSU_POWER_GOOD: + status = sysfs_attr_info->val.intval; + return sprintf(buf, "%d\n", status); + break; + case PSU_MODEL_NAME: + case PSU_MFR_ID: + case PSU_SERIAL_NUM: + case PSU_FAN_DIR: + return sprintf(buf, "%s\n", sysfs_attr_info->val.strval); + break; + case PSU_V_OUT: + case PSU_I_OUT: + case PSU_V_IN: + case PSU_I_IN: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + + break; + case PSU_P_OUT: + multiplier = 1000000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + + break; + case PSU_FAN1_SPEED: + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent)); + else + return sprintf(buf, "%d\n", (mantissa) / (1 << -exponent)); + + break; + case PSU_TEMP1_INPUT: + multiplier = 1000; + value = sysfs_attr_info->val.shortval; + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + if (exponent >= 0) + return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier); + else + return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); + + break; + default: + printk(KERN_ERR "%s: Unable to find attribute index for %s\n", __FUNCTION__, usr_data->aname); + goto exit; + } + +exit: + return sprintf(buf, "%d\n", status); +} + + +ssize_t psu_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct psu_data *data = i2c_get_clientdata(client); + PSU_PDATA *pdata = (PSU_PDATA *)(client->dev.platform_data); + PSU_DATA_ATTR *usr_data = NULL; + struct psu_attr_info *sysfs_attr_info = NULL; + int i; + + for (i=0;inum_attr;i++) + { + if (strcmp(data->attr_info[i].name, attr->dev_attr.attr.name) == 0 && strcmp(pdata->psu_attrs[i].aname, attr->dev_attr.attr.name) == 0) + { + sysfs_attr_info = &data->attr_info[i]; + usr_data = &pdata->psu_attrs[i]; + } + } + + if (sysfs_attr_info==NULL || usr_data==NULL) { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + switch(attr->index) + { + /*No write attributes for now in PSU*/ + default: + goto exit; + } + + psu_update_hw(dev, sysfs_attr_info, usr_data); + +exit: + return count; +} + +int sonic_i2c_get_psu_present_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + int status = 0; + int val = 0; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + + + if (strncmp(adata->devtype, "cpld", strlen("cpld")) == 0) + { + val = board_i2c_cpld_read(adata->devaddr , adata->offset); + if (val < 0) + return val; + padata->val.intval = ((val & adata->mask) == adata->cmpval); + psu_dbg(KERN_ERR "%s: status_value = 0x%x\n", __FUNCTION__, padata->val.intval); + } + + return status; +} + +int sonic_i2c_get_psu_power_good_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + int status = 0; + int val = 0; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + + if (strncmp(adata->devtype, "cpld", strlen("cpld")) == 0) + { + val = board_i2c_cpld_read(adata->devaddr , adata->offset); + if (val < 0) + return val; + padata->val.intval = ((val & adata->mask) == adata->cmpval); + psu_dbg(KERN_ERR "%s: status_value = 0x%x\n", __FUNCTION__, padata->val.intval); + } + + return status; +} + +int sonic_i2c_get_psu_model_name_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + char model[32]=""; //temporary placeholder for model name + uint8_t offset = (uint8_t)adata->offset; + int data_len = adata->len; + + while (retry) + { + status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, model); + if (unlikely(status<0)) + { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + model[0] = '\0'; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read model name from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + model[data_len-1] = '\0'; + } + + if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0) + strncpy(padata->val.strval, model+1, data_len-1); + else + strncpy(padata->val.strval, model, data_len); + + psu_dbg(KERN_ERR "%s: status = %d, model_name : %s\n", __FUNCTION__, status, padata->val.strval); + return 0; +} + +int sonic_i2c_get_psu_mfr_id_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + char mfr_id[16] = ""; // temporary place holder for mfr_id + uint8_t offset = (uint8_t)adata->offset; + int data_len = adata->len; + + while (retry) + { + status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, mfr_id); + if (unlikely(status<0)) + { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + mfr_id[0] = '\0'; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read mfr_id from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + mfr_id[data_len-1] = '\0'; + } + + if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0) + strncpy(padata->val.strval, mfr_id+1, data_len-1); + else + strncpy(padata->val.strval, mfr_id, data_len); + + psu_dbg(KERN_ERR "%s: status = %d, mfr_id : %s\n", __FUNCTION__, status, padata->val.strval); + return 0; +} + +int sonic_i2c_get_psu_serial_num_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + char serial[32] = ""; // temporary string to store the serial num + uint8_t offset = (uint8_t)adata->offset; + int data_len = adata->len; + + while (retry) + { + status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, serial); + if (unlikely(status<0)) + { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + serial[0] = '\0'; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read serial num from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + serial[data_len-1] = '\0'; + } + + if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0) + strncpy(padata->val.strval, serial+1, data_len-1); + else + strncpy(padata->val.strval, serial, data_len); + + psu_dbg(KERN_ERR "%s: status = %d, serial_num : %s\n", __FUNCTION__, status, padata->val.strval); + return 0; +} + +int sonic_i2c_get_psu_fan_dir_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + char fan_dir[5] = ""; + uint8_t offset = (uint8_t)adata->offset; + int data_len = adata->len; + + while (retry) + { + status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, fan_dir); + if (unlikely(status<0)) + { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + fan_dir[0] = '\0'; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read fan_dir from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + fan_dir[data_len-1] = '\0'; + } + + if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0) + strncpy(padata->val.strval, fan_dir+1, data_len-1); + else + strncpy(padata->val.strval, fan_dir, data_len); + + psu_dbg(KERN_ERR "%s: status = %d, fan_dir : %s\n", __FUNCTION__, status, padata->val.strval); + return 0; +} + +int sonic_i2c_get_psu_v_out_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + uint8_t offset = (uint8_t)adata->offset; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + padata->val.shortval = 0; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read v_out from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + padata->val.shortval = status; + } + + psu_dbg(KERN_ERR "%s: v_out : %d\n", __FUNCTION__, padata->val.shortval); + return 0; +} + +int sonic_i2c_get_psu_i_out_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + uint8_t offset = (uint8_t)adata->offset; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + padata->val.shortval = 0; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read i_out from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + padata->val.shortval = status; + } + + psu_dbg(KERN_ERR "%s: i_out : %d\n", __FUNCTION__, padata->val.shortval); + return 0; +} + +int sonic_i2c_get_psu_p_out_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + uint8_t offset = (uint8_t)adata->offset; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + padata->val.shortval = 0; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read p_out from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + padata->val.shortval = status; + } + + psu_dbg(KERN_ERR "%s: p_out : %d\n", __FUNCTION__, padata->val.shortval); + return 0; +} + +int sonic_i2c_get_psu_v_in_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + uint8_t offset = (uint8_t)adata->offset; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + padata->val.shortval = 0; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read v_in from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + padata->val.shortval = status; + } + + psu_dbg(KERN_ERR "%s: v_in : %d\n", __FUNCTION__, padata->val.shortval); + return 0; +} + +int sonic_i2c_get_psu_i_in_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + uint8_t offset = (uint8_t)adata->offset; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + padata->val.shortval = 0; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read i_in from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + padata->val.shortval = status; + } + + psu_dbg(KERN_ERR "%s: i_in : %d\n", __FUNCTION__, padata->val.shortval); + return 0; +} + +int sonic_i2c_get_psu_fan1_speed_rpm_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + uint8_t offset = (uint8_t)adata->offset; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + padata->val.shortval = 0; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read fan1_speed_rpm from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + padata->val.shortval = status; + } + + psu_dbg(KERN_ERR "%s: fan1_speed_rpm : %d\n", __FUNCTION__, padata->val.shortval); + return 0; +} + +int sonic_i2c_get_psu_temp1_input_default(void *client, PSU_DATA_ATTR *adata, void *data) +{ + + int status = 0, retry = 10; + struct psu_attr_info *padata = (struct psu_attr_info *)data; + uint8_t offset = (uint8_t)adata->offset; + + while (retry) { + status = i2c_smbus_read_word_data((struct i2c_client *)client, offset); + if (unlikely(status < 0)) { + msleep(60); + retry--; + continue; + } + break; + } + + if (status < 0) + { + padata->val.shortval = 0; + dev_dbg(&((struct i2c_client *)client)->dev, "unable to read temp1_input from (0x%x)\n", ((struct i2c_client *)client)->addr); + } + else + { + padata->val.shortval = status; + } + + psu_dbg(KERN_ERR "%s: temp1_input : %d\n", __FUNCTION__, padata->val.shortval); + return 0; +} diff --git a/platform/pddf/i2c/modules/psu/driver/pddf_psu_driver.c b/platform/pddf/i2c/modules/psu/driver/pddf_psu_driver.c new file mode 100644 index 000000000000..ad71e45eca20 --- /dev/null +++ b/platform/pddf/i2c/modules/psu/driver/pddf_psu_driver.c @@ -0,0 +1,381 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel module driver for PSU + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_psu_defs.h" +#include "pddf_psu_driver.h" +#include "pddf_psu_api.h" + + +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +struct pddf_ops_t pddf_psu_ops = { + .pre_init = NULL, + .post_init = NULL, + + .pre_probe = NULL, + .post_probe = NULL, + + .pre_remove = NULL, + .post_remove = NULL, + + .pre_exit = NULL, + .post_exit = NULL, +}; +EXPORT_SYMBOL(pddf_psu_ops); + + +PSU_SYSFS_ATTR_DATA access_psu_present = {PSU_PRESENT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_present_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_present); + +PSU_SYSFS_ATTR_DATA access_psu_model_name = {PSU_MODEL_NAME, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_model_name_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_model_name); + +PSU_SYSFS_ATTR_DATA access_psu_power_good = {PSU_POWER_GOOD, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_power_good_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_power_good); + +PSU_SYSFS_ATTR_DATA access_psu_mfr_id = {PSU_MFR_ID, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_mfr_id_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_mfr_id); + +PSU_SYSFS_ATTR_DATA access_psu_serial_num = {PSU_SERIAL_NUM, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_serial_num_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_serial_num); + +PSU_SYSFS_ATTR_DATA access_psu_fan_dir = {PSU_FAN_DIR, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_fan_dir_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_fan_dir); + +PSU_SYSFS_ATTR_DATA access_psu_v_out = {PSU_V_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_v_out_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_out); + +PSU_SYSFS_ATTR_DATA access_psu_i_out = {PSU_I_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_i_out_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_i_out); + +PSU_SYSFS_ATTR_DATA access_psu_p_out = {PSU_P_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_p_out_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_p_out); + +PSU_SYSFS_ATTR_DATA access_psu_fan1_speed_rpm = {PSU_FAN1_SPEED, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_fan1_speed_rpm_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_fan1_speed_rpm); + +PSU_SYSFS_ATTR_DATA access_psu_temp1_input = {PSU_TEMP1_INPUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_temp1_input_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_temp1_input); + +PSU_SYSFS_ATTR_DATA access_psu_v_in = {PSU_V_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_v_in_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_v_in); + +PSU_SYSFS_ATTR_DATA access_psu_i_in = {PSU_I_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_i_in_default, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(access_psu_i_in); + + +PSU_SYSFS_ATTR_DATA_ENTRY psu_sysfs_attr_data_tbl[]= +{ + { "psu_present", &access_psu_present}, + { "psu_model_name", &access_psu_model_name}, + { "psu_power_good" , &access_psu_power_good}, + { "psu_mfr_id" , &access_psu_mfr_id}, + { "psu_serial_num" , &access_psu_serial_num}, + { "psu_fan_dir" , &access_psu_fan_dir}, + { "psu_v_out" , &access_psu_v_out}, + { "psu_i_out" , &access_psu_i_out}, + { "psu_p_out" , &access_psu_p_out}, + { "psu_fan1_speed_rpm" , &access_psu_fan1_speed_rpm}, + { "psu_temp1_input" , &access_psu_temp1_input}, + { "psu_v_in" , &access_psu_v_in}, + { "psu_i_in" , &access_psu_i_in} +}; + +void *get_psu_access_data(char *name) +{ + int i=0; + for(i=0; i<(sizeof(psu_sysfs_attr_data_tbl)/sizeof(psu_sysfs_attr_data_tbl[0])); i++) + { + if(strcmp(name, psu_sysfs_attr_data_tbl[i].name) ==0) + { + return &psu_sysfs_attr_data_tbl[i]; + } + } + return NULL; +} +EXPORT_SYMBOL(get_psu_access_data); + + +static int psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct psu_data *data; + int status =0; + int i,num, j=0; + PSU_PDATA *psu_platform_data; + PSU_DATA_ATTR *data_attr; + PSU_SYSFS_ATTR_DATA_ENTRY *sysfs_data_entry; + char new_str[ATTR_NAME_LEN] = ""; + + + if (client == NULL) { + printk("NULL Client.. \n"); + goto exit; + } + + if (pddf_psu_ops.pre_probe) + { + status = (pddf_psu_ops.pre_probe)(client, dev_id); + if (status != 0) + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + dev_info(&client->dev, "chip found\n"); + + /* Take control of the platform data */ + psu_platform_data = (PSU_PDATA *)(client->dev.platform_data); + num = psu_platform_data->len; + data->index = psu_platform_data->idx - 1; + data->num_psu_fans = psu_platform_data->num_psu_fans; + data->num_attr = num; + + + + /* Create and Add supported attr in the 'attributes' list */ + for (i=0; ipsu_attrs + i; + sysfs_data_entry = get_psu_access_data(data_attr->aname); + if (sysfs_data_entry == NULL) + { + printk(KERN_ERR "%s: Wrong attribute name provided by user '%s'\n", __FUNCTION__, data_attr->aname); + continue; + } + + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strcpy((char *)dy_ptr->dev_attr.attr.name, data_attr->aname); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->psu_attribute_list[i] = &dy_ptr->dev_attr.attr; + strcpy(data->attr_info[i].name, data_attr->aname); + data->attr_info[i].valid = 0; + mutex_init(&data->attr_info[i].update_lock); + + /*Create a duplicate entry*/ + get_psu_duplicate_sysfs(dy_ptr->index, new_str); + if (strcmp(new_str,"")) + { + dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL); + dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1]; + strcpy((char *)dy_ptr->dev_attr.attr.name, new_str); + dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode; + dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show; + dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->psu_attribute_list[num+j] = &dy_ptr->dev_attr.attr; + j++; + strcpy(new_str,""); + } + } + data->psu_attribute_list[i+j] = NULL; + data->psu_attribute_group.attrs = data->psu_attribute_list; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->psu_attribute_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + /* Add a support for post probe function */ + if (pddf_psu_ops.post_probe) + { + status = (pddf_psu_ops.post_probe)(client, dev_id); + if (status != 0) + goto exit_remove; + } + + return 0; + + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->psu_attribute_group); +exit_free: + /* Free all the allocated attributes */ + for (i=0;data->psu_attribute_list[i]!=NULL;i++) + { + struct sensor_device_attribute *ptr = (struct sensor_device_attribute *)data->psu_attribute_list[i]; + kfree(ptr); + data->psu_attribute_list[i] = NULL; + pddf_dbg(PSU, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + } + kfree(data); +exit: + return status; +} + +static int psu_remove(struct i2c_client *client) +{ + int i=0, ret = 0; + struct psu_data *data = i2c_get_clientdata(client); + PSU_PDATA *platdata = (PSU_PDATA *)client->dev.platform_data; // use dev_get_platdata() + PSU_DATA_ATTR *platdata_sub = platdata->psu_attrs; + struct sensor_device_attribute *ptr = NULL; + + if (pddf_psu_ops.pre_remove) + { + ret = (pddf_psu_ops.pre_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN pre_remove function failed\n"); + } + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->psu_attribute_group); + for (i=0; data->psu_attribute_list[i]!=NULL; i++) + { + ptr = (struct sensor_device_attribute *)data->psu_attribute_list[i]; + kfree(ptr); + data->psu_attribute_list[i] = NULL; + } + pddf_dbg(PSU, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + kfree(data); + if (platdata_sub) { + printk(KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__); + kfree(platdata_sub); + } + if (platdata) { + printk(KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__); + kfree(platdata); + } + + if (pddf_psu_ops.post_remove) + { + ret = (pddf_psu_ops.post_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN post_remove function failed\n"); + } + + return ret; +} + +enum psu_intf +{ + eeprom_intf, + smbus_intf +}; + +static const struct i2c_device_id psu_id[] = { + {"psu_eeprom", eeprom_intf}, + {"psu_pmbus", smbus_intf}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, psu_id); + +static struct i2c_driver psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "psu", + }, + .probe = psu_probe, + .remove = psu_remove, + .id_table = psu_id, + .address_list = normal_i2c, +}; + +int example_fun(void) +{ + pddf_dbg(PSU, KERN_ERR "CALLING FUN...\n"); + return 0; +} +EXPORT_SYMBOL(example_fun); + + +int psu_init(void) +{ + int status = 0; + + if (pddf_psu_ops.pre_init) + { + status = (pddf_psu_ops.pre_init)(); + if (status!=0) + return status; + } + + pddf_dbg(PSU, KERN_ERR "GENERIC_PSU_DRIVER.. init Invoked..\n"); + status = i2c_add_driver(&psu_driver); + if (status!=0) + return status; + + if (pddf_psu_ops.post_init) + { + status = (pddf_psu_ops.post_init)(); + if (status!=0) + return status; + } + + return status; +} +EXPORT_SYMBOL(psu_init); + +void __exit psu_exit(void) +{ + pddf_dbg(PSU, "GENERIC_PSU_DRIVER.. exit\n"); + if (pddf_psu_ops.pre_exit) (pddf_psu_ops.pre_exit)(); + i2c_del_driver(&psu_driver); + if (pddf_psu_ops.post_exit) (pddf_psu_ops.post_exit)(); +} +EXPORT_SYMBOL(psu_exit); + +module_init(psu_init); +module_exit(psu_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("psu driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/modules/psu/pddf_psu_module.c b/platform/pddf/i2c/modules/psu/pddf_psu_module.c new file mode 100644 index 000000000000..cf9713b407cd --- /dev/null +++ b/platform/pddf/i2c/modules/psu/pddf_psu_module.c @@ -0,0 +1,283 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel module to create I2C client for PSU + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_psu_defs.h" + + +static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern void *get_psu_access_data(char *); +extern void* get_device_table(char *name); +extern void delete_device_table(char *name); + +PSU_DATA psu_data = {0}; + + + +/* PSU CLIENT DATA */ +PDDF_DATA_ATTR(psu_idx, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&psu_data.idx, NULL); +PDDF_DATA_ATTR(psu_fans, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&psu_data.num_psu_fans, NULL); + +PDDF_DATA_ATTR(attr_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&psu_data.psu_attr.aname, NULL); +PDDF_DATA_ATTR(attr_devtype, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&psu_data.psu_attr.devtype, NULL); +PDDF_DATA_ATTR(attr_devname, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&psu_data.psu_attr.devname, NULL); +PDDF_DATA_ATTR(attr_devaddr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&psu_data.psu_attr.devaddr, NULL); +PDDF_DATA_ATTR(attr_offset, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&psu_data.psu_attr.offset, NULL); +PDDF_DATA_ATTR(attr_mask, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&psu_data.psu_attr.mask, NULL); +PDDF_DATA_ATTR(attr_cmpval, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&psu_data.psu_attr.cmpval, NULL); +PDDF_DATA_ATTR(attr_len, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&psu_data.psu_attr.len, NULL); +PDDF_DATA_ATTR(attr_ops, S_IWUSR, NULL, do_attr_operation, PDDF_CHAR, 8, (void*)&psu_data, NULL); +PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&psu_data, (void*)&pddf_data); + + + +static struct attribute *psu_attributes[] = { + &attr_psu_idx.dev_attr.attr, + &attr_psu_fans.dev_attr.attr, + + &attr_attr_name.dev_attr.attr, + &attr_attr_devtype.dev_attr.attr, + &attr_attr_devname.dev_attr.attr, + &attr_attr_devaddr.dev_attr.attr, + &attr_attr_offset.dev_attr.attr, + &attr_attr_mask.dev_attr.attr, + &attr_attr_cmpval.dev_attr.attr, + &attr_attr_len.dev_attr.attr, + &attr_attr_ops.dev_attr.attr, + &attr_dev_ops.dev_attr.attr, + NULL +}; + +static const struct attribute_group pddf_psu_client_data_group = { + .attrs = psu_attributes, +}; + + +static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + PSU_DATA *pdata = (PSU_DATA *)(ptr->addr); + PSU_SYSFS_ATTR_DATA_ENTRY *access_ptr; + + + pdata->psu_attrs[pdata->len] = pdata->psu_attr; + access_ptr = get_psu_access_data(pdata->psu_attrs[pdata->len].aname); + if (access_ptr != NULL && access_ptr->a_ptr != NULL) + { + pdata->psu_attrs[pdata->len].access_data = access_ptr->a_ptr ; + } + + + pdata->len++; + memset(&pdata->psu_attr, 0, sizeof(pdata->psu_attr)); + + + return count; +} + +struct i2c_board_info *i2c_get_psu_board_info(PSU_DATA *pdata, NEW_DEV_ATTR *cdata) +{ + int num = pdata->len; + int i = 0; + static struct i2c_board_info board_info; + PSU_PDATA *psu_platform_data; + + + if (strcmp(cdata->dev_type, "psu_pmbus")==0 || strcmp(cdata->dev_type, "psu_eeprom")==0 ) + { + /* Allocate the psu_platform_data */ + psu_platform_data = (PSU_PDATA *)kzalloc(sizeof(PSU_PDATA), GFP_KERNEL); + psu_platform_data->psu_attrs = (PSU_DATA_ATTR *)kzalloc(num*sizeof(PSU_DATA_ATTR), GFP_KERNEL); + + + psu_platform_data->idx = pdata->idx; + psu_platform_data->num_psu_fans = pdata->num_psu_fans; + psu_platform_data->len = pdata->len; + + for (i=0;ipsu_attrs[i] = pdata->psu_attrs[i]; + } + + board_info = (struct i2c_board_info) { + .platform_data = psu_platform_data, + }; + + board_info.addr = cdata->dev_addr; + strcpy(board_info.type, cdata->dev_type); + } + else + { + printk(KERN_ERR "%s:Unknown type of device %s. Unable to clreate I2C client for it\n",__FUNCTION__, cdata->dev_type); + } + + return &board_info; +} + + +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + PSU_DATA *pdata = (PSU_DATA *)(ptr->addr); + NEW_DEV_ATTR *cdata = (NEW_DEV_ATTR *)(ptr->data); + struct i2c_adapter *adapter; + struct i2c_board_info *board_info; + struct i2c_client *client_ptr; + + + if (strncmp(buf, "add", strlen(buf)-1)==0) + { + adapter = i2c_get_adapter(cdata->parent_bus); + board_info = i2c_get_psu_board_info(pdata, cdata); + + /* Populate the platform data for psu */ + client_ptr = i2c_new_device(adapter, board_info); + + if(client_ptr != NULL) + { + i2c_put_adapter(adapter); + pddf_dbg(PSU, KERN_ERR "Created a %s client: 0x%p\n", cdata->i2c_name , (void *)client_ptr); + add_device_table(cdata->i2c_name, (void*)client_ptr); + } + else + { + i2c_put_adapter(adapter); + goto free_data; + } + } + else if (strncmp(buf, "delete", strlen(buf)-1)==0) + { + /*Get the i2c_client handle for the created client*/ + client_ptr = (struct i2c_client *)get_device_table(cdata->i2c_name); + if (client_ptr) + { + pddf_dbg(PSU, KERN_ERR "Removing %s client: 0x%p\n", cdata->i2c_name, (void *)client_ptr); + i2c_unregister_device(client_ptr); + delete_device_table(cdata->i2c_name); + } + else + { + printk(KERN_ERR "Unable to get the client handle for %s\n", cdata->i2c_name); + } + + } + else + { + printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf); + } + + goto clear_data; + +free_data: + if (board_info->platform_data) + { + PSU_PDATA *psu_platform_data = board_info->platform_data; + if (psu_platform_data->psu_attrs) + { + printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform subdata\n", __FUNCTION__); + kfree(psu_platform_data->psu_attrs); + } + printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform data\n", __FUNCTION__); + kfree(psu_platform_data); + } + +clear_data: + memset(pdata, 0, sizeof(PSU_DATA)); + /*TODO: free the data cdata->data if data is dynal=mically allocated*/ + memset(cdata, 0, sizeof(NEW_DEV_ATTR)); + return count; +} + + +static struct kobject *psu_kobj; +static struct kobject *i2c_kobj; + +int __init pddf_data_init(void) +{ + struct kobject *device_kobj; + int ret = 0; + + + pddf_dbg(PSU, "PDDF_DATA MODULE.. init\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + psu_kobj = kobject_create_and_add("psu", device_kobj); + if(!psu_kobj) + return -ENOMEM; + i2c_kobj = kobject_create_and_add("i2c", psu_kobj); + if(!i2c_kobj) + return -ENOMEM; + + ret = sysfs_create_group(i2c_kobj, &pddf_clients_data_group); + if (ret) + { + kobject_put(i2c_kobj); + kobject_put(psu_kobj); + return ret; + } + pddf_dbg(PSU, "CREATED PSU I2C CLIENTS CREATION SYSFS GROUP\n"); + + ret = sysfs_create_group(i2c_kobj, &pddf_psu_client_data_group); + if (ret) + { + sysfs_remove_group(i2c_kobj, &pddf_clients_data_group); + kobject_put(i2c_kobj); + kobject_put(psu_kobj); + return ret; + } + pddf_dbg(PSU, "CREATED PDDF PSU DATA SYSFS GROUP\n"); + + return ret; +} + +void __exit pddf_data_exit(void) +{ + + pddf_dbg(PSU, "PDDF_DATA MODULE.. exit\n"); + sysfs_remove_group(i2c_kobj, &pddf_psu_client_data_group); + sysfs_remove_group(i2c_kobj, &pddf_clients_data_group); + kobject_put(i2c_kobj); + kobject_put(psu_kobj); + pddf_dbg(PSU, KERN_ERR "%s: Removed the kobjects for 'i2c' and 'psu'\n",__FUNCTION__); + + return; +} + +module_init(pddf_data_init); +module_exit(pddf_data_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("psu platform data"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/modules/sysstatus/Makefile b/platform/pddf/i2c/modules/sysstatus/Makefile new file mode 100644 index 000000000000..150d160eae15 --- /dev/null +++ b/platform/pddf/i2c/modules/sysstatus/Makefile @@ -0,0 +1,4 @@ +TARGET := pddf_sysstatus_module +obj-m := $(TARGET).o + +CFLAGS_$(obj-m):= -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/sysstatus/pddf_sysstatus_module.c b/platform/pddf/i2c/modules/sysstatus/pddf_sysstatus_module.c new file mode 100644 index 000000000000..bd892d924265 --- /dev/null +++ b/platform/pddf/i2c/modules/sysstatus/pddf_sysstatus_module.c @@ -0,0 +1,235 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel module for system status registers + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_sysstatus_defs.h" + + + +SYSSTATUS_DATA sysstatus_data = {0}; + +extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +ssize_t show_sysstatus_data(struct device *dev, struct device_attribute *da, char *buf); + + +PDDF_DATA_ATTR(attr_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, + (void*)&sysstatus_data.sysstatus_addr_attr.aname, NULL); +PDDF_DATA_ATTR(attr_devaddr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, + sizeof(uint32_t), (void*)&sysstatus_data.sysstatus_addr_attr.devaddr , NULL); +PDDF_DATA_ATTR(attr_offset, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, + sizeof(uint32_t), (void*)&sysstatus_data.sysstatus_addr_attr.offset, NULL); +PDDF_DATA_ATTR(attr_mask, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, + sizeof(uint32_t), (void*)&sysstatus_data.sysstatus_addr_attr.mask , NULL); +PDDF_DATA_ATTR(attr_len, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, + sizeof(uint32_t), (void*)&sysstatus_data.sysstatus_addr_attr.len , NULL); +PDDF_DATA_ATTR(attr_ops, S_IWUSR, NULL, do_attr_operation, PDDF_CHAR, 8, (void*)&sysstatus_data, NULL); + + + +static struct attribute *sysstatus_addr_attributes[] = { + &attr_attr_name.dev_attr.attr, + &attr_attr_devaddr.dev_attr.attr, + &attr_attr_offset.dev_attr.attr, + &attr_attr_mask.dev_attr.attr, + &attr_attr_len.dev_attr.attr, + &attr_attr_ops.dev_attr.attr, + NULL +}; + +PDDF_DATA_ATTR(board_info, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, 32, NULL, NULL); +PDDF_DATA_ATTR(cpld1_version, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(cpld2_version, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(cpld3_version, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(power_module_status, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(system_reset1, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(system_reset2, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(system_reset3, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(system_reset4, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(system_reset5, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(system_reset6, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(system_reset7, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(system_reset8, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(misc1, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(misc2, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); +PDDF_DATA_ATTR(misc3, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL); + + + +static struct attribute *sysstatus_data_attributes[] = { + &attr_board_info.dev_attr.attr, + &attr_cpld1_version.dev_attr.attr, + &attr_cpld2_version.dev_attr.attr, + &attr_cpld3_version.dev_attr.attr, + &attr_power_module_status.dev_attr.attr, + &attr_system_reset1.dev_attr.attr, + &attr_system_reset2.dev_attr.attr, + &attr_system_reset3.dev_attr.attr, + &attr_system_reset4.dev_attr.attr, + &attr_system_reset5.dev_attr.attr, + &attr_system_reset6.dev_attr.attr, + &attr_system_reset7.dev_attr.attr, + &attr_system_reset8.dev_attr.attr, + &attr_misc1.dev_attr.attr, + &attr_misc2.dev_attr.attr, + &attr_misc3.dev_attr.attr, + NULL +}; + + + +static const struct attribute_group pddf_sysstatus_addr_group = { + .attrs = sysstatus_addr_attributes, +}; + + +static const struct attribute_group pddf_sysstatus_data_group = { + .attrs = sysstatus_data_attributes, +}; + + +static struct kobject *sysstatus_addr_kobj; +static struct kobject *sysstatus_data_kobj; + + + +ssize_t show_sysstatus_data(struct device *dev, struct device_attribute *da, char *buf) +{ + + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + SYSSTATUS_DATA *data = &sysstatus_data; + struct SYSSTATUS_ADDR_ATTR *sysstatus_addr_attrs = NULL; + int i, status ; + + + for (i=0;isysstatus_addr_attrs[i].aname, attr->dev_attr.attr.name) == 0 ) + { + sysstatus_addr_attrs = &data->sysstatus_addr_attrs[i]; + + } + } + + if (sysstatus_addr_attrs==NULL ) + { + printk(KERN_DEBUG "%s is not supported attribute for this client\n",data->sysstatus_addr_attrs[i].aname); + status = 0; + } + else + { + status = board_i2c_cpld_read( sysstatus_addr_attrs->devaddr, sysstatus_addr_attrs->offset); + } + + return sprintf(buf, "0x%x\n", (status&sysstatus_addr_attrs->mask)); + +} + + + +static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + SYSSTATUS_DATA *pdata = (SYSSTATUS_DATA *)(ptr->addr); + + pdata->sysstatus_addr_attrs[pdata->len] = pdata->sysstatus_addr_attr; + pdata->len++; + pddf_dbg(SYSSTATUS, KERN_ERR "%s: Populating the data for %s\n", __FUNCTION__, pdata->sysstatus_addr_attr.aname); + memset(&pdata->sysstatus_addr_attr, 0, sizeof(pdata->sysstatus_addr_attr)); + + + return count; +} + + + + +int __init sysstatus_data_init(void) +{ + struct kobject *device_kobj; + int ret = 0; + + + pddf_dbg(SYSSTATUS, "PDDF SYSSTATUS MODULE.. init\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + sysstatus_addr_kobj = kobject_create_and_add("sysstatus", device_kobj); + if(!sysstatus_addr_kobj) + return -ENOMEM; + + sysstatus_data_kobj = kobject_create_and_add("sysstatus_data", sysstatus_addr_kobj); + if(!sysstatus_data_kobj) + return -ENOMEM; + + + ret = sysfs_create_group(sysstatus_addr_kobj, &pddf_sysstatus_addr_group); + if (ret) + { + kobject_put(sysstatus_addr_kobj); + return ret; + } + + ret = sysfs_create_group(sysstatus_data_kobj, &pddf_sysstatus_data_group); + if (ret) + { + sysfs_remove_group(sysstatus_addr_kobj, &pddf_sysstatus_addr_group); + kobject_put(sysstatus_data_kobj); + kobject_put(sysstatus_addr_kobj); + return ret; + } + + + return ret; +} + +void __exit sysstatus_data_exit(void) +{ + pddf_dbg(SYSSTATUS, "PDDF SYSSTATUS MODULE.. exit\n"); + sysfs_remove_group(sysstatus_data_kobj, &pddf_sysstatus_data_group); + sysfs_remove_group(sysstatus_addr_kobj, &pddf_sysstatus_addr_group); + kobject_put(sysstatus_data_kobj); + kobject_put(sysstatus_addr_kobj); + pddf_dbg(SYSSTATUS, KERN_ERR "%s: Removed the kobjects for 'SYSSTATUS'\n",__FUNCTION__); + return; +} + +module_init(sysstatus_data_init); +module_exit(sysstatus_data_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("SYSSTATUS platform data"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/modules/xcvr/Makefile b/platform/pddf/i2c/modules/xcvr/Makefile new file mode 100644 index 000000000000..e72ad6b44233 --- /dev/null +++ b/platform/pddf/i2c/modules/xcvr/Makefile @@ -0,0 +1,4 @@ +subdir-m := driver +obj-m := pddf_xcvr_module.o + +CFLAGS_$(obj-m):= -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/xcvr/driver/Makefile b/platform/pddf/i2c/modules/xcvr/driver/Makefile new file mode 100644 index 000000000000..0b381d1fc2fe --- /dev/null +++ b/platform/pddf/i2c/modules/xcvr/driver/Makefile @@ -0,0 +1,7 @@ +TARGET = pddf_xcvr_driver_module + +obj-m := $(TARGET).o + +$(TARGET)-objs := pddf_xcvr_api.o pddf_xcvr_driver.o + +ccflags-y := -I$(M)/modules/include diff --git a/platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_api.c b/platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_api.c new file mode 100644 index 000000000000..ddb7a1b3a2b3 --- /dev/null +++ b/platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_api.c @@ -0,0 +1,909 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description of various APIs related to transciever component + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_xcvr_defs.h" + +/*#define SFP_DEBUG*/ +#ifdef SFP_DEBUG +#define sfp_dbg(...) printk(__VA_ARGS__) +#else +#define sfp_dbg(...) +#endif + +extern XCVR_SYSFS_ATTR_OPS xcvr_ops[]; +extern void *get_device_table(char *name); + +int get_xcvr_module_attr_data(struct i2c_client *client, struct device *dev, + struct device_attribute *da); + +int xcvr_i2c_cpld_read(XCVR_ATTR *info) +{ + int status = -1; + + if (info!=NULL) + { + if (info->len==1) + { + status = board_i2c_cpld_read(info->devaddr , info->offset); + } + else + { + /* Get the I2C client for the CPLD */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(info->devname); + if (client_ptr) + { + if (info->len==2) + { + status = i2c_smbus_read_word_swapped(client_ptr, info->offset); + } + else + printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD read yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", info->devname); + } + + } + + return status; +} + +int sonic_i2c_get_mod_pres(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data) +{ + int status = 0; + uint32_t modpres = 0; + + if ( strcmp(info->devtype, "cpld") == 0) + { + status = xcvr_i2c_cpld_read(info); + + if (status < 0) + return status; + else + { + modpres = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0; + sfp_dbg(KERN_INFO "\nMod presence :0x%x, reg_value = 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", modpres, status, info->devaddr, info->mask, info->offset); + } + } + else if(strcmp(info->devtype, "eeprom") == 0) + { + /* get client client for eeprom - Not Applicable */ + } + data->modpres = modpres; + + return 0; +} + +int sonic_i2c_get_mod_reset(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data) +{ + int status = 0; + uint32_t modreset=0; + + if (strcmp(info->devtype, "cpld") == 0) + { + status = xcvr_i2c_cpld_read(info); + if (status < 0) + return status; + else + { + modreset = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0; + sfp_dbg(KERN_INFO "\nMod Reset :0x%x, reg_value = 0x%x\n", modreset, status); + } + } + else if(strcmp(info->devtype, "eeprom") == 0) + { + /* get client client for eeprom - Not Applicable */ + } + + data->reset = modreset; + return 0; +} + +int sonic_i2c_get_mod_intr_status(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data) +{ + int status = 0; + uint32_t mod_intr = 0; + + if (strcmp(info->devtype, "cpld") == 0) + { + status = xcvr_i2c_cpld_read(info); + if (status < 0) + return status; + else + { + mod_intr = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0; + sfp_dbg(KERN_INFO "\nModule Interrupt :0x%x, reg_value = 0x%x\n", mod_intr, status); + } + } + else if(strcmp(info->devtype, "eeprom") == 0) + { + /* get client client for eeprom - Not Applicable */ + } + + data->intr_status = mod_intr; + return 0; +} + + +int sonic_i2c_get_mod_lpmode(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data) +{ + int status = 0; + uint32_t lpmode = 0; + + if (strcmp(info->devtype, "cpld") == 0) + { + status = xcvr_i2c_cpld_read(info); + if (status < 0) + return status; + else + { + lpmode = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0; + sfp_dbg(KERN_INFO "\nModule LPmode :0x%x, reg_value = 0x%x\n", lpmode, status); + } + } + else if (strcmp(info->devtype, "eeprom") == 0) + { + /* get client client for eeprom - Not Applicable */ + } + + data->lpmode = lpmode; + return 0; +} + +int sonic_i2c_get_mod_rxlos(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data) +{ + int status = 0; + uint32_t rxlos = 0; + + + if (strcmp(info->devtype, "cpld") == 0) + { + status = xcvr_i2c_cpld_read(info); + if (status < 0) + return status; + else + { + rxlos = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0; + sfp_dbg(KERN_INFO "\nModule RxLOS :0x%x, reg_value = 0x%x\n", rxlos, status); + } + } + data->rxlos = rxlos; + + return 0; +} + +int sonic_i2c_get_mod_txdisable(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data) +{ + int status = 0; + uint32_t txdis = 0; + + if (strcmp(info->devtype, "cpld") == 0) + { + status = xcvr_i2c_cpld_read(info); + if (status < 0) + return status; + else + { + txdis = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0; + sfp_dbg(KERN_INFO "\nModule TxDisable :0x%x, reg_value = 0x%x\n", txdis, status); + } + } + data->txdisable = txdis; + + return 0; +} + +int sonic_i2c_get_mod_txfault(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data) +{ + int status = 0; + uint32_t txflt = 0; + + if (strcmp(info->devtype, "cpld") == 0) + { + status = xcvr_i2c_cpld_read(info); + if (status < 0) + return status; + else + { + txflt = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0; + sfp_dbg(KERN_INFO "\nModule TxFault :0x%x, reg_value = 0x%x\n", txflt, status); + } + + } + data->txfault = txflt; + + return 0; +} + +int sonic_i2c_set_mod_reset(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data) +{ + int status = 0; + unsigned int val_mask = 0, dnd_value = 0; + uint32_t reg; + struct i2c_client *client_ptr=NULL; + + if (strcmp(info->devtype, "cpld") == 0) + { + val_mask = BIT_INDEX(info->mask); + /* Get the I2C client for the CPLD */ + client_ptr = (struct i2c_client *)get_device_table(info->devname); + + if (client_ptr) + { + if (info->len == 1) + status = board_i2c_cpld_read(info->devaddr , info->offset); + else if (info->len == 2) + status = i2c_smbus_read_word_data(client_ptr, info->offset); + else + { + printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD read yet"); + status = -1; + } + } + else + { + printk(KERN_ERR "Unable to get the client handle for %s\n", info->devname); + status = -1; + } + /*printk(KERN_ERR "sonic_i2c_set_mod_reset:client_ptr=0x%x, status=0x%x, offset=0x%x, len=%d\n", client_ptr, status, info->offset, info->len);*/ + + if (status < 0) + return status; + else + { + dnd_value = status & ~val_mask; + if (((data->reset == 1) && (info->cmpval != 0)) || ((data->reset == 0) && (info->cmpval == 0))) + reg = dnd_value | val_mask; + else + reg = dnd_value; + if (info->len == 1) + status = board_i2c_cpld_write(info->devaddr, info->offset, (uint8_t)reg); + else if (info->len == 2) + status = i2c_smbus_write_word_swapped(client_ptr, info->offset, (uint16_t)reg); + else + { + printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD write yet"); + status = -1; + } + } + } + + return status; +} + +int sonic_i2c_set_mod_lpmode(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data) +{ + int status = 0; + unsigned int val_mask = 0, dnd_value = 0; + uint32_t reg; + struct i2c_client *client_ptr=NULL; + + if (strcmp(info->devtype, "cpld") == 0) + { + val_mask = BIT_INDEX(info->mask); + /* Get the I2C client for the CPLD */ + client_ptr = (struct i2c_client *)get_device_table(info->devname); + + if (client_ptr) + { + if (info->len == 1) + status = board_i2c_cpld_read(info->devaddr , info->offset); + else if (info->len == 2) + status = i2c_smbus_read_word_data(client_ptr, info->offset); + else + { + printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD read yet"); + status = -1; + } + } + else + { + printk(KERN_ERR "Unable to get the client handle for %s\n", info->devname); + status = -1; + } + + if (status < 0) + return status; + else + { + dnd_value = status & ~val_mask; + if (((data->lpmode == 1) && (info->cmpval != 0)) || ((data->lpmode == 0) && (info->cmpval == 0))) + reg = dnd_value | val_mask; + else + reg = dnd_value; + if (info->len == 1) + status = board_i2c_cpld_write(info->devaddr, info->offset, (uint8_t)reg); + else if (info->len == 2) + status = i2c_smbus_write_word_swapped(client_ptr, info->offset, (uint16_t)reg); + else + { + printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD write yet"); + status = -1; + } + } + } + + return status; +} + +int sonic_i2c_set_mod_txdisable(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data) +{ + int status = 0; + unsigned int val_mask = 0, dnd_value = 0; + uint32_t reg; + struct i2c_client *client_ptr=NULL; + + if (strcmp(info->devtype, "cpld") == 0) + { + val_mask = BIT_INDEX(info->mask); + /* Get the I2C client for the CPLD */ + client_ptr = (struct i2c_client *)get_device_table(info->devname); + + if (client_ptr) + { + if (info->len == 1) + status = board_i2c_cpld_read(info->devaddr , info->offset); + else if (info->len == 2) + status = i2c_smbus_read_word_data(client_ptr, info->offset); + else + { + printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD read yet"); + status = -1; + } + } + else + { + printk(KERN_ERR "Unable to get the client handle for %s\n", info->devname); + status = -1; + } + + if (status < 0) + return status; + else + { + dnd_value = status & ~val_mask; + if (((data->txdisable == 1) && (info->cmpval != 0)) || ((data->txdisable == 0) && (info->cmpval == 0))) + reg = dnd_value | val_mask; + else + reg = dnd_value; + if (info->len == 1) + status = board_i2c_cpld_write(info->devaddr, info->offset, (uint8_t)reg); + else if (info->len == 2) + status = i2c_smbus_write_word_swapped(client_ptr, info->offset, (uint16_t)reg); + else + { + printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD write yet"); + status = -1; + } + } + } + + return status; +} + +ssize_t get_module_presence(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct xcvr_data *data = i2c_get_clientdata(client); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + XCVR_ATTR *attr_data = NULL; + XCVR_SYSFS_ATTR_OPS *attr_ops = NULL; + int status = 0, i; + + for (i=0; ilen; i++) + { + attr_data = &pdata->xcvr_attrs[i]; + if (strcmp(attr_data->aname, attr->dev_attr.attr.name) == 0) + { + attr_ops = &xcvr_ops[attr->index]; + + mutex_lock(&data->update_lock); + if (attr_ops->pre_get != NULL) + { + status = (attr_ops->pre_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + if (attr_ops->do_get != NULL) + { + status = (attr_ops->do_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute. ret %d\n", __FUNCTION__, attr_data->aname, status); + + } + if (attr_ops->post_get != NULL) + { + status = (attr_ops->post_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", data->modpres); + } + } + return sprintf(buf, "%s",""); +} + +ssize_t get_module_reset(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct xcvr_data *data = i2c_get_clientdata(client); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + XCVR_ATTR *attr_data = NULL; + XCVR_SYSFS_ATTR_OPS *attr_ops = NULL; + int status = 0, i; + + for (i=0; ilen; i++) + { + attr_data = &pdata->xcvr_attrs[i]; + if (strcmp(attr_data->aname, attr->dev_attr.attr.name) == 0) + { + attr_ops = &xcvr_ops[attr->index]; + + mutex_lock(&data->update_lock); + if (attr_ops->pre_get != NULL) + { + status = (attr_ops->pre_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + if (attr_ops->do_get != NULL) + { + status = (attr_ops->do_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + + } + if (attr_ops->post_get != NULL) + { + status = (attr_ops->post_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", data->reset); + } + } + return sprintf(buf, "%s",""); +} + +ssize_t set_module_reset(struct device *dev, struct device_attribute *da, const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct xcvr_data *data = i2c_get_clientdata(client); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + XCVR_ATTR *attr_data = NULL; + XCVR_SYSFS_ATTR_OPS *attr_ops = NULL; + int status = 0, i; + unsigned int set_value; + + for (i=0; ilen; i++) + { + attr_data = &pdata->xcvr_attrs[i]; + if (strcmp(attr_data->aname, attr->dev_attr.attr.name) == 0) + { + attr_ops = &xcvr_ops[attr->index]; + if(kstrtoint(buf, 10, &set_value)) + return -EINVAL; + if ((set_value != 1) && (set_value != 0)) + return -EINVAL; + + data->reset = set_value; + + mutex_lock(&data->update_lock); + + if (attr_ops->pre_set != NULL) + { + status = (attr_ops->pre_set)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + if (attr_ops->do_set != NULL) + { + status = (attr_ops->do_set)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + + } + if (attr_ops->post_set != NULL) + { + status = (attr_ops->post_set)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + mutex_unlock(&data->update_lock); + + return count; + } + } + return -EINVAL; +} + +ssize_t get_module_intr_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct xcvr_data *data = i2c_get_clientdata(client); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + XCVR_ATTR *attr_data = NULL; + XCVR_SYSFS_ATTR_OPS *attr_ops = NULL; + int status = 0, i; + + for (i=0; ilen; i++) + { + attr_data = &pdata->xcvr_attrs[i]; + if (strcmp(attr_data->aname, attr->dev_attr.attr.name) == 0) + { + attr_ops = &xcvr_ops[attr->index]; + + mutex_lock(&data->update_lock); + if (attr_ops->pre_get != NULL) + { + status = (attr_ops->pre_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + if (attr_ops->do_get != NULL) + { + status = (attr_ops->do_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + + } + if (attr_ops->post_get != NULL) + { + status = (attr_ops->post_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", data->intr_status); + } + } + return sprintf(buf, "%s",""); +} + +int get_xcvr_module_attr_data(struct i2c_client *client, struct device *dev, + struct device_attribute *da) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + XCVR_ATTR *attr_data = NULL; + int i; + + for (i=0; i < pdata->len; i++) + { + attr_data = &pdata->xcvr_attrs[i]; + if (strcmp(attr_data->aname, attr->dev_attr.attr.name) == 0) + { + return i; + } + } + return -1; +} + +ssize_t get_module_lpmode(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + struct xcvr_data *data = i2c_get_clientdata(client); + XCVR_ATTR *attr_data = NULL; + XCVR_SYSFS_ATTR_OPS *attr_ops = NULL; + int idx, status = 0; + + idx = get_xcvr_module_attr_data(client, dev, da); + + if (idx>=0) attr_data = &pdata->xcvr_attrs[idx]; + + if (attr_data!=NULL) + { + + attr_ops = &xcvr_ops[attr->index]; + + mutex_lock(&data->update_lock); + if (attr_ops->pre_get != NULL) + { + status = (attr_ops->pre_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + if (attr_ops->do_get != NULL) + { + status = (attr_ops->do_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + + } + if (attr_ops->post_get != NULL) + { + status = (attr_ops->post_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", data->lpmode); + } + else + return sprintf(buf,"%s",""); +} + +ssize_t set_module_lpmode(struct device *dev, struct device_attribute *da, const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct xcvr_data *data = i2c_get_clientdata(client); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + int idx, status = 0; + uint32_t set_value; + XCVR_ATTR *attr_data = NULL; + XCVR_SYSFS_ATTR_OPS *attr_ops = NULL; + + idx = get_xcvr_module_attr_data(client, dev, da); + + if (idx>=0) attr_data = &pdata->xcvr_attrs[idx]; + + if (attr_data!=NULL) + { + attr_ops = &xcvr_ops[attr->index]; + if(kstrtoint(buf, 10, &set_value)) + return -EINVAL; + if ((set_value != 1) && (set_value != 0)) + return -EINVAL; + + data->lpmode = set_value; + + mutex_lock(&data->update_lock); + + if (attr_ops->pre_set != NULL) + { + status = (attr_ops->pre_set)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + if (attr_ops->do_set != NULL) + { + status = (attr_ops->do_set)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + + } + if (attr_ops->post_set != NULL) + { + status = (attr_ops->post_set)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + mutex_unlock(&data->update_lock); + } + return count; +} + +ssize_t get_module_rxlos(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct xcvr_data *data = i2c_get_clientdata(client); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + int idx, status = 0; + XCVR_ATTR *attr_data = NULL; + XCVR_SYSFS_ATTR_OPS *attr_ops = NULL; + + idx = get_xcvr_module_attr_data(client, dev, da); + + if (idx>=0) attr_data = &pdata->xcvr_attrs[idx]; + + if (attr_data!=NULL) + { + attr_ops = &xcvr_ops[attr->index]; + + mutex_lock(&data->update_lock); + if (attr_ops->pre_get != NULL) + { + status = (attr_ops->pre_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + if (attr_ops->do_get != NULL) + { + status = (attr_ops->do_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + + } + if (attr_ops->post_get != NULL) + { + status = (attr_ops->post_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", data->rxlos); + } + else + return sprintf(buf,"%s",""); +} + +ssize_t get_module_txdisable(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct xcvr_data *data = i2c_get_clientdata(client); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + int idx, status = 0; + XCVR_ATTR *attr_data = NULL; + XCVR_SYSFS_ATTR_OPS *attr_ops = NULL; + + idx = get_xcvr_module_attr_data(client, dev, da); + + if (idx>=0) attr_data = &pdata->xcvr_attrs[idx]; + + if (attr_data!=NULL) + { + attr_ops = &xcvr_ops[attr->index]; + + mutex_lock(&data->update_lock); + if (attr_ops->pre_get != NULL) + { + status = (attr_ops->pre_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + if (attr_ops->do_get != NULL) + { + status = (attr_ops->do_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + + } + if (attr_ops->post_get != NULL) + { + status = (attr_ops->post_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", data->txdisable); + } + else + return sprintf(buf,"%s",""); +} + +ssize_t set_module_txdisable(struct device *dev, struct device_attribute *da, const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct xcvr_data *data = i2c_get_clientdata(client); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + int idx, status = 0; + uint32_t set_value; + XCVR_ATTR *attr_data = NULL; + XCVR_SYSFS_ATTR_OPS *attr_ops = NULL; + + idx = get_xcvr_module_attr_data(client, dev, da); + + if (idx>=0) attr_data = &pdata->xcvr_attrs[idx]; + + if (attr_data!=NULL) + { + attr_ops = &xcvr_ops[attr->index]; + if(kstrtoint(buf, 10, &set_value)) + return -EINVAL; + if ((set_value != 1) && (set_value != 0)) + return -EINVAL; + + data->txdisable = set_value; + + mutex_lock(&data->update_lock); + + if (attr_ops->pre_set != NULL) + { + status = (attr_ops->pre_set)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: pre_set function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + if (attr_ops->do_set != NULL) + { + status = (attr_ops->do_set)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: do_set function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + + } + if (attr_ops->post_set != NULL) + { + status = (attr_ops->post_set)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: post_set function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + mutex_unlock(&data->update_lock); + } + return count; +} + +ssize_t get_module_txfault(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data); + struct xcvr_data *data = i2c_get_clientdata(client); + int idx, status = 0; + XCVR_ATTR *attr_data = NULL; + XCVR_SYSFS_ATTR_OPS *attr_ops = NULL; + + idx = get_xcvr_module_attr_data(client, dev, da); + + if (idx>=0) attr_data = &pdata->xcvr_attrs[idx]; + + if (attr_data!=NULL) + { + attr_ops = &xcvr_ops[attr->index]; + + mutex_lock(&data->update_lock); + if (attr_ops->pre_get != NULL) + { + status = (attr_ops->pre_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + if (attr_ops->do_get != NULL) + { + status = (attr_ops->do_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + + } + if (attr_ops->post_get != NULL) + { + status = (attr_ops->post_get)(client, attr_data, data); + if (status!=0) + printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname); + } + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", data->txfault); + } + return sprintf(buf,"%s",""); +} diff --git a/platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_driver.c b/platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_driver.c new file mode 100644 index 000000000000..142d38a2ff2b --- /dev/null +++ b/platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_driver.c @@ -0,0 +1,296 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel driver module for Optic component + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_xcvr_defs.h" +#include "pddf_xcvr_api.h" + + +struct pddf_ops_t pddf_xcvr_ops = { + .pre_init = NULL, + .post_init = NULL, + + .pre_probe = NULL, + .post_probe = NULL, + + .pre_remove = NULL, + .post_remove = NULL, + + .pre_exit = NULL, + .post_exit = NULL, +}; +EXPORT_SYMBOL(pddf_xcvr_ops); + +XCVR_SYSFS_ATTR_OPS xcvr_ops[XCVR_ATTR_MAX] = { + {XCVR_PRESENT, get_module_presence, NULL, sonic_i2c_get_mod_pres, NULL, NULL, NULL, NULL, NULL}, + {XCVR_RESET, get_module_reset, NULL, sonic_i2c_get_mod_reset, NULL, set_module_reset, NULL, sonic_i2c_set_mod_reset, NULL}, + {XCVR_INTR_STATUS, get_module_intr_status, NULL, sonic_i2c_get_mod_intr_status, NULL, NULL, NULL, NULL, NULL}, + {XCVR_LPMODE, get_module_lpmode, NULL, sonic_i2c_get_mod_lpmode, NULL, set_module_lpmode, NULL, sonic_i2c_set_mod_lpmode, NULL}, + {XCVR_RXLOS, get_module_rxlos, NULL, sonic_i2c_get_mod_rxlos, NULL, NULL, NULL, NULL, NULL}, + {XCVR_TXDISABLE, get_module_txdisable, NULL, sonic_i2c_get_mod_txdisable, NULL, set_module_txdisable, NULL, sonic_i2c_set_mod_txdisable, NULL}, + {XCVR_TXFAULT, get_module_txfault, NULL, sonic_i2c_get_mod_txfault, NULL, NULL, NULL, NULL, NULL}, +}; +EXPORT_SYMBOL(xcvr_ops); + + +/* sysfs attributes + */ +static SENSOR_DEVICE_ATTR(xcvr_present, S_IWUSR|S_IRUGO, get_module_presence, NULL, XCVR_PRESENT); +static SENSOR_DEVICE_ATTR(xcvr_reset, S_IWUSR|S_IRUGO, get_module_reset, set_module_reset, XCVR_RESET); +static SENSOR_DEVICE_ATTR(xcvr_intr_status, S_IWUSR|S_IRUGO, get_module_intr_status, NULL, XCVR_INTR_STATUS); +static SENSOR_DEVICE_ATTR(xcvr_lpmode, S_IWUSR|S_IRUGO, get_module_lpmode, set_module_lpmode, XCVR_LPMODE); +static SENSOR_DEVICE_ATTR(xcvr_rxlos, S_IWUSR|S_IRUGO, get_module_rxlos, NULL, XCVR_RXLOS); +static SENSOR_DEVICE_ATTR(xcvr_txdisable, S_IWUSR|S_IRUGO, get_module_txdisable, set_module_txdisable, XCVR_TXDISABLE); +static SENSOR_DEVICE_ATTR(xcvr_txfault, S_IWUSR|S_IRUGO, get_module_txfault, NULL, XCVR_TXFAULT); + +/* List of all the xcvr attribute structures + * to get name, use sensor_dev_attr_<>.dev_attr.attr.name + * to get the id, use sensor_dev_attr_<>.dev_attr.index + */ +static struct sensor_device_attribute *xcvr_attr_list[MAX_XCVR_ATTRS] = { + &sensor_dev_attr_xcvr_present, + &sensor_dev_attr_xcvr_reset, + &sensor_dev_attr_xcvr_intr_status, + &sensor_dev_attr_xcvr_lpmode, + &sensor_dev_attr_xcvr_rxlos, + &sensor_dev_attr_xcvr_txdisable, + &sensor_dev_attr_xcvr_txfault, +}; + +static struct attribute *xcvr_attributes[MAX_XCVR_ATTRS] = {NULL}; + +static const struct attribute_group xcvr_group = { + .attrs = xcvr_attributes, +}; + +static int xcvr_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct xcvr_data *data; + int status =0; + int i,j,num; + XCVR_PDATA *xcvr_platform_data; + XCVR_ATTR *attr_data; + + if (client == NULL) { + pddf_dbg(XCVR, "NULL Client.. \n"); + goto exit; + } + + if (pddf_xcvr_ops.pre_probe) + { + status = (pddf_xcvr_ops.pre_probe)(client, dev_id); + if (status != 0) + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct xcvr_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + + dev_info(&client->dev, "chip found\n"); + + /* Take control of the platform data */ + xcvr_platform_data = (XCVR_PDATA *)(client->dev.platform_data); + num = xcvr_platform_data->len; + data->index = xcvr_platform_data->idx - 1; + mutex_init(&data->update_lock); + + /* Add supported attr in the 'attributes' list */ + for (i=0; ixcvr_attrs + i; + for(j=0;jdev_attr.attr; + + if (strncmp(aptr->name, attr_data->aname, strlen(attr_data->aname))==0) + break; + } + + if (jdev_attr.attr; + + } + xcvr_attributes[i] = NULL; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &xcvr_group); + if (status) { + goto exit_free; + } + + data->xdev = hwmon_device_register(&client->dev); + if (IS_ERR(data->xdev)) { + status = PTR_ERR(data->xdev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: xcvr '%s'\n", + dev_name(data->xdev), client->name); + + /* Add a support for post probe function */ + if (pddf_xcvr_ops.post_probe) + { + status = (pddf_xcvr_ops.post_probe)(client, dev_id); + if (status != 0) + goto exit_remove; + } + + + return 0; + + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &xcvr_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int xcvr_remove(struct i2c_client *client) +{ + int ret = 0; + struct xcvr_data *data = i2c_get_clientdata(client); + XCVR_PDATA *platdata = (XCVR_PDATA *)client->dev.platform_data; + XCVR_ATTR *platdata_sub = platdata->xcvr_attrs; + + if (pddf_xcvr_ops.pre_remove) + { + ret = (pddf_xcvr_ops.pre_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN pre_remove function failed\n"); + } + + hwmon_device_unregister(data->xdev); + sysfs_remove_group(&client->dev.kobj, &xcvr_group); + kfree(data); + + if (platdata_sub) { + pddf_dbg(XCVR, KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__); + kfree(platdata_sub); + } + if (platdata) { + pddf_dbg(XCVR, KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__); + kfree(platdata); + } + + if (pddf_xcvr_ops.post_remove) + { + ret = (pddf_xcvr_ops.post_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN post_remove function failed\n"); + } + + return 0; +} + +enum xcvr_intf +{ + XCVR_CTRL_INTF, +}; + +static const struct i2c_device_id xcvr_ids[] = { + { "pddf_xcvr", XCVR_CTRL_INTF }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, xcvr_ids); + +static struct i2c_driver xcvr_driver = { + /*.class = I2C_CLASS_HWMON,*/ + .driver = { + .name = "xcvr", + .owner = THIS_MODULE, + }, + .probe = xcvr_probe, + .remove = xcvr_remove, + .id_table = xcvr_ids, +}; + + +/*int __init xcvr_init(void)*/ +int xcvr_init(void) +{ + int ret = 0; + + if (pddf_xcvr_ops.pre_init) + { + ret = (pddf_xcvr_ops.pre_init)(); + if (ret!=0) + return ret; + } + + pddf_dbg(XCVR, KERN_ERR "PDDF XCVR DRIVER.. init Invoked..\n"); + ret = i2c_add_driver(&xcvr_driver); + if (ret!=0) + return ret; + + if (pddf_xcvr_ops.post_init) + { + ret = (pddf_xcvr_ops.post_init)(); + if (ret!=0) + return ret; + } + + return ret; +} +EXPORT_SYMBOL(xcvr_init); + +void __exit xcvr_exit(void) +{ + pddf_dbg(XCVR, "PDDF XCVR DRIVER.. exit\n"); + if (pddf_xcvr_ops.pre_exit) (pddf_xcvr_ops.pre_exit)(); + i2c_del_driver(&xcvr_driver); + if (pddf_xcvr_ops.post_exit) (pddf_xcvr_ops.post_exit)(); + +} +EXPORT_SYMBOL(xcvr_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("Driver for transceiver operations"); +MODULE_LICENSE("GPL"); + +module_init(xcvr_init); +module_exit(xcvr_exit); diff --git a/platform/pddf/i2c/modules/xcvr/pddf_xcvr_module.c b/platform/pddf/i2c/modules/xcvr/pddf_xcvr_module.c new file mode 100644 index 000000000000..65c555b742a2 --- /dev/null +++ b/platform/pddf/i2c/modules/xcvr/pddf_xcvr_module.c @@ -0,0 +1,275 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel module to create i2C client for optics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_client_defs.h" +#include "pddf_xcvr_defs.h" + +static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern void* get_device_table(char *name); +extern void delete_device_table(char *name); + +XCVR_DATA xcvr_data = {0}; + +/* XCVR CLIENT DATA */ +PDDF_DATA_ATTR(dev_idx, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&xcvr_data.idx, NULL); + +PDDF_DATA_ATTR(attr_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&xcvr_data.xcvr_attr.aname, NULL); +PDDF_DATA_ATTR(attr_devtype, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&xcvr_data.xcvr_attr.devtype, NULL); +PDDF_DATA_ATTR(attr_devname, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&xcvr_data.xcvr_attr.devname, NULL); +PDDF_DATA_ATTR(attr_devaddr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&xcvr_data.xcvr_attr.devaddr, NULL); +PDDF_DATA_ATTR(attr_offset, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&xcvr_data.xcvr_attr.offset, NULL); +PDDF_DATA_ATTR(attr_mask, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&xcvr_data.xcvr_attr.mask, NULL); +PDDF_DATA_ATTR(attr_cmpval, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&xcvr_data.xcvr_attr.cmpval, NULL); +PDDF_DATA_ATTR(attr_len, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&xcvr_data.xcvr_attr.len, NULL); +PDDF_DATA_ATTR(attr_ops, S_IWUSR, NULL, do_attr_operation, PDDF_CHAR, 8, (void*)&xcvr_data, NULL); +PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&xcvr_data, (void*)&pddf_data); + + +static struct attribute *xcvr_attributes[] = { + &attr_dev_idx.dev_attr.attr, + + &attr_attr_name.dev_attr.attr, + &attr_attr_devtype.dev_attr.attr, + &attr_attr_devname.dev_attr.attr, + &attr_attr_devaddr.dev_attr.attr, + &attr_attr_offset.dev_attr.attr, + &attr_attr_mask.dev_attr.attr, + &attr_attr_cmpval.dev_attr.attr, + &attr_attr_len.dev_attr.attr, + &attr_attr_ops.dev_attr.attr, + &attr_dev_ops.dev_attr.attr, + NULL +}; + +static const struct attribute_group pddf_xcvr_client_data_group = { + .attrs = xcvr_attributes, +}; + + +static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + XCVR_DATA *pdata = (XCVR_DATA *)(ptr->addr); + + pdata->xcvr_attrs[pdata->len] = pdata->xcvr_attr; + pdata->len++; + memset(&pdata->xcvr_attr, 0, sizeof(pdata->xcvr_attr)); + + + return count; +} + +/*PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&pddf_attr, (void*)NULL);*/ +static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + int i = 0; + PDDF_ATTR *ptr = (PDDF_ATTR *)da; + XCVR_DATA *pdata = (XCVR_DATA *)(ptr->addr); + NEW_DEV_ATTR *cdata = (NEW_DEV_ATTR *)(ptr->data); + + struct i2c_adapter *adapter; + struct i2c_board_info board_info; + struct i2c_client *client_ptr; + + /* Populate the platform data for xcvr */ + if (strncmp(buf, "add", strlen(buf)-1)==0) + { + if (strcmp(cdata->dev_type, "pddf_xcvr")==0) + { + int num = pdata->len; + XCVR_PDATA *xcvr_platform_data; + + adapter = i2c_get_adapter(cdata->parent_bus); + /* Allocate the xcvr_platform_data */ + xcvr_platform_data = (XCVR_PDATA *)kzalloc(sizeof(XCVR_PDATA), GFP_KERNEL); + xcvr_platform_data->xcvr_attrs = (XCVR_ATTR *)kzalloc(num*sizeof(XCVR_ATTR), GFP_KERNEL); + + + xcvr_platform_data->idx = pdata->idx; + xcvr_platform_data->len = pdata->len; + + for (i=0;ixcvr_attrs[i] = pdata->xcvr_attrs[i]; + } + + board_info = (struct i2c_board_info) { + .platform_data = xcvr_platform_data, + }; + + board_info.addr = cdata->dev_addr; + strcpy(board_info.type, cdata->dev_type); + + client_ptr = i2c_new_device(adapter, &board_info); + if (client_ptr != NULL) { + i2c_put_adapter(adapter); + pddf_dbg(XCVR, KERN_ERR "Created a %s client: 0x%p\n", cdata->i2c_name, (void *)client_ptr); + add_device_table(cdata->i2c_name, (void*)client_ptr); + } + else + { + i2c_put_adapter(adapter); + goto free_data; + } + } + else if((strcmp(cdata->dev_type, "optoe1")==0) || (strcmp(cdata->dev_type, "optoe2")==0)) + { + + adapter = i2c_get_adapter(cdata->parent_bus); + board_info = (struct i2c_board_info) { + .platform_data = (void *)NULL, + }; + + board_info.addr = cdata->dev_addr; + strcpy(board_info.type, cdata->dev_type); + + client_ptr = i2c_new_device(adapter, &board_info); + if(client_ptr != NULL) { + i2c_put_adapter(adapter); + pddf_dbg(XCVR, KERN_ERR "Created %s, type:%s client: 0x%p\n", cdata->i2c_name, cdata->dev_type, (void *)client_ptr); + add_device_table(cdata->i2c_name, (void*)client_ptr); + } + else + { + i2c_put_adapter(adapter); + printk(KERN_ERR "Error creating a client %s on 0x%x, client_ptr:0x%p\n", board_info.type, board_info.addr, (void *)client_ptr); + goto free_data; + } + } + else + { + printk(KERN_ERR "%s:Unknown type of device %s. Unable to create I2C client for it\n",__FUNCTION__, cdata->dev_type); + } + } + else if (strncmp(buf, "delete", strlen(buf)-1)==0) + { + /*Get the i2c_client handle for the created client*/ + client_ptr = (struct i2c_client *)get_device_table(cdata->i2c_name); + if (client_ptr) + { + pddf_dbg(XCVR, KERN_ERR "Removing %s client: 0x%p\n", cdata->i2c_name, (void *)client_ptr); + i2c_unregister_device(client_ptr); + delete_device_table(cdata->i2c_name); + } + else + { + pddf_dbg(XCVR, KERN_ERR "Unable to get the client handle for %s\n", cdata->i2c_name); + } + } + else + { + printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf); + } + + goto clear_data; + +free_data: + if (board_info.platform_data) + { + XCVR_PDATA *xcvr_platform_data = board_info.platform_data; + if (xcvr_platform_data->xcvr_attrs) + { + printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform subdata\n", __FUNCTION__); + kfree(xcvr_platform_data->xcvr_attrs); + } + printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform data\n", __FUNCTION__); + kfree(xcvr_platform_data); + } + +clear_data: + memset(pdata, 0, sizeof(XCVR_DATA)); + /*TODO: free the data cdata->data if data is dynal=mically allocated*/ + memset(cdata, 0, sizeof(NEW_DEV_ATTR)); + return count; +} + +struct kobject *xcvr_kobj; +struct kobject *i2c_kobj; +int __init pddf_data_init(void) +{ + struct kobject *device_kobj; + int ret = 0; + + pddf_dbg(XCVR, KERN_ERR "XCVR PDDF MODULE.. init\n"); + + device_kobj = get_device_i2c_kobj(); + if(!device_kobj) + return -ENOMEM; + + xcvr_kobj = kobject_create_and_add("xcvr", device_kobj); + if(!xcvr_kobj) + return -ENOMEM; + i2c_kobj = kobject_create_and_add("i2c", xcvr_kobj); + if(!i2c_kobj) + return -ENOMEM; + + ret = sysfs_create_group(i2c_kobj, &pddf_clients_data_group); + if (ret) + { + kobject_put(i2c_kobj); + kobject_put(xcvr_kobj); + return ret; + } + pddf_dbg(XCVR, "CREATED SFP I2C CLIENTS CREATION SYSFS GROUP\n"); + + ret = sysfs_create_group(i2c_kobj, &pddf_xcvr_client_data_group); + if (ret) + { + sysfs_remove_group(i2c_kobj, &pddf_clients_data_group); + kobject_put(i2c_kobj); + kobject_put(xcvr_kobj); + return ret; + } + pddf_dbg(XCVR, "CREATED PDDF SFP DATA SYSFS GROUP\n"); + + return ret; +} + +void __exit pddf_data_exit(void) +{ + + pddf_dbg(XCVR, "XCVR PDDF MODULE.. exit\n"); + sysfs_remove_group(i2c_kobj, &pddf_xcvr_client_data_group); + sysfs_remove_group(i2c_kobj, &pddf_clients_data_group); + kobject_put(i2c_kobj); + kobject_put(xcvr_kobj); + pddf_dbg(XCVR, KERN_ERR "%s: Removed the kobjects for 'i2c' and 'xcvr'\n",__FUNCTION__); + + return; +} + +module_init(pddf_data_init); +module_exit(pddf_data_exit); + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("sfp platform data"); +MODULE_LICENSE("GPL"); diff --git a/platform/pddf/i2c/service/pddf-platform-init.service b/platform/pddf/i2c/service/pddf-platform-init.service new file mode 100644 index 000000000000..ccb8d1110fb7 --- /dev/null +++ b/platform/pddf/i2c/service/pddf-platform-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=PDDF module and device initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/pddf_util.py install +ExecStop=/usr/local/bin/pddf_util.py clean +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/pddf/i2c/setup.py b/platform/pddf/i2c/setup.py new file mode 100755 index 000000000000..04da78cd5330 --- /dev/null +++ b/platform/pddf/i2c/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +from setuptools import setup +import os + +setup( + name='pddf-platform', + version='%s' % os.environ.get('PLATFORM_MODULE_VERSION', '1.0'), + description='Module to initialize Platform', + packages=[ + 'modules', + ], +) + diff --git a/platform/pddf/i2c/utils/pddf_util.py b/platform/pddf/i2c/utils/pddf_util.py new file mode 100755 index 000000000000..127f37d6b2f0 --- /dev/null +++ b/platform/pddf/i2c/utils/pddf_util.py @@ -0,0 +1,605 @@ +#!/usr/bin/env python + + +""" +Usage: %(scriptName)s [options] command object + +options: + -h | --help : this help message + -d | --debug : run with debug mode + -f | --force : ignore error during installation or clean +command: + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + switch-pddf : switch to pddf mode, installing pddf drivers and generating sysfs nodes + switch-nonpddf : switch to per platform, non-pddf mode +""" + +import commands +import logging +import getopt +import os +import shutil +import subprocess +import sys + +import pddfparse + +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' + +PROJECT_NAME = 'PDDF' +version = '1.1' +verbose = False +DEBUG = False +args = [] +ALL_DEVICE = {} +FORCE = 0 +kos = [] +perm_kos = [] +devs = [] + +# Instantiate the class pddf_obj +try: + pddf_obj = pddfparse.PddfParse() +except Exception as e: + print "%s" % str(e) + sys.exit() + + + +if DEBUG == True: + print sys.argv[0] + print 'ARGV :', sys.argv[1:] + +def main(): + global DEBUG + global args + global FORCE + global kos + + if len(sys.argv)<2: + show_help() + + options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', + 'debug', + 'force', + ]) + if DEBUG == True: + print options + print args + print len(sys.argv) + + # generate the KOS list from pddf device JSON file + if 'std_perm_kos' in pddf_obj.data['PLATFORM'].keys(): + kos.extend(pddf_obj.data['PLATFORM']['std_perm_kos']) + perm_kos.extend(pddf_obj.data['PLATFORM']['std_perm_kos']) + kos.extend(pddf_obj.data['PLATFORM']['std_kos']) + kos.extend(pddf_obj.data['PLATFORM']['pddf_kos']) + + kos = ['modprobe '+i for i in kos] + + if 'custom_kos' in pddf_obj.data['PLATFORM']: + custom_kos = pddf_obj.data['PLATFORM']['custom_kos'] + kos.extend(['modprobe -f '+i for i in custom_kos]) + + for opt, arg in options: + if opt in ('-h', '--help'): + show_help() + elif opt in ('-d', '--debug'): + DEBUG = True + logging.basicConfig(level=logging.INFO) + elif opt in ('-f', '--force'): + FORCE = 1 + else: + logging.info('no option') + for arg in args: + if arg == 'install': + do_install() + elif arg == 'clean': + do_uninstall() + elif arg == 'switch-pddf': + do_switch_pddf() + elif arg == 'switch-nonpddf': + do_switch_nonpddf() + else: + show_help() + + return 0 + +def show_help(): + print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]} + sys.exit(0) + +def my_log(txt): + if DEBUG == True: + print "[PDDF]"+txt + return + +def log_os_system(cmd, show): + logging.info('Run :'+cmd) + status, output = commands.getstatusoutput(cmd) + my_log (cmd +"with result:" + str(status)) + my_log (" output:"+output) + if status: + logging.info('Failed :'+cmd) + if show: + print('Failed :'+cmd) + return status, output + +def driver_check(): + ret, lsmod = log_os_system("lsmod| grep pddf", 0) + if ret: + return False + logging.info('mods:'+lsmod) + if len(lsmod) ==0: + return False + return True + + +# 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) + +def get_path_to_device(): + # Get platform and hwsku + (platform, hwsku) = get_platform_and_hwsku() + + # Load platform module from source + platform_path = "/".join([PLATFORM_ROOT_PATH, platform]) + + return platform_path + +def get_path_to_pddf_plugin(): + pddf_path = "/".join([PLATFORM_ROOT_PATH, "pddf/plugins"]) + return pddf_path + +def config_pddf_utils(): + device_path = get_path_to_device() + pddf_path = get_path_to_pddf_plugin() + + # ########################################################################## + SONIC_PLATFORM_BSP_WHL_PKG = "/".join([device_path, 'sonic_platform-1.0-py2-none-any.whl']) + SONIC_PLATFORM_PDDF_WHL_PKG = "/".join([device_path, 'pddf', 'sonic_platform-1.0-py2-none-any.whl']) + SONIC_PLATFORM_BSP_WHL_PKG_BK = "/".join([device_path, 'sonic_platform-1.0-py2-none-any.whl.orig']) + status, output = log_os_system("pip show sonic-platform > /dev/null 2>&1", 1) + if status: + if os.path.exists(SONIC_PLATFORM_PDDF_WHL_PKG): + # Platform API 2.0 is supported + if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG): + # bsp whl pkg is present but not installed on host + if not os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_BK): + log_os_system('mv '+SONIC_PLATFORM_BSP_WHL_PKG+' '+SONIC_PLATFORM_BSP_WHL_PKG_BK, 1) + # PDDF whl package exist ... this must be the whl package created from + # PDDF 2.0 ref API classes and some changes on top of it ... install it + shutil.copy(SONIC_PLATFORM_PDDF_WHL_PKG, SONIC_PLATFORM_BSP_WHL_PKG) + print "Attemting to install the PDDF sonic_platform wheel package ..." + status, output = log_os_system("pip install "+ SONIC_PLATFORM_BSP_WHL_PKG, 1) + if status: + print "Error: Failed to install {}".format(SONIC_PLATFORM_BSP_WHL_PKG) + return status + else: + print "Successfully installed {} package".format(SONIC_PLATFORM_BSP_WHL_PKG) + else: + # PDDF with platform APIs 1.5 must be supported + device_plugin_path = "/".join([device_path, "plugins"]) + backup_path = "/".join([device_plugin_path, "orig"]) + print "Loading PDDF generic plugins (1.0)" + if os.path.exists(backup_path) is False: + os.mkdir(backup_path) + log_os_system("mv "+device_plugin_path+"/*.*"+" "+backup_path, 0) + + for item in os.listdir(pddf_path): + shutil.copy(pddf_path+"/"+item, device_plugin_path+"/"+item) + + shutil.copy('/usr/local/bin/pddfparse.py', device_plugin_path+"/pddfparse.py") + + else: + # sonic_platform whl pkg is installed 2 possibilities, 1) bsp 2.0 classes + # are installed, 2) system rebooted and either pddf/bsp 2.0 classes are already installed + if os.path.exists(SONIC_PLATFORM_PDDF_WHL_PKG): + if not os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_BK): + # bsp 2.0 classes are installed. Take a backup and copy pddf 2.0 whl pkg + log_os_system('mv '+SONIC_PLATFORM_BSP_WHL_PKG+' '+SONIC_PLATFORM_BSP_WHL_PKG_BK, 1) + shutil.copy(SONIC_PLATFORM_PDDF_WHL_PKG, SONIC_PLATFORM_BSP_WHL_PKG) + # uninstall the existing bsp whl pkg + status, output = log_os_system("pip uninstall sonic-platform -y &> /dev/null", 1) + if status: + print "Error: Unable to uninstall BSP sonic-platform whl package" + return status + print "Attemting to install the PDDF sonic_platform wheel package ..." + status, output = log_os_system("pip install "+ SONIC_PLATFORM_BSP_WHL_PKG, 1) + if status: + print "Error: Failed to install {}".format(SONIC_PLATFORM_BSP_WHL_PKG) + return status + else: + print "Successfully installed {} package".format(SONIC_PLATFORM_BSP_WHL_PKG) + else: + # system rebooted in pddf mode + print "System rebooted in PDDF mode, hence keeping the PDDF 2.0 classes" + else: + # pddf whl package doesnt exist + print "Error: PDDF 2.0 classes doesnt exist. PDDF mode can not be enabled" + sys.exit(1) + + # ########################################################################## + # Take a backup of orig fancontrol + if os.path.exists(device_path+"/fancontrol"): + log_os_system("mv "+device_path+"/fancontrol"+" "+device_path+"/fancontrol.bak", 0) + + # Create a link to fancontrol of PDDF + if os.path.exists(device_path+"/pddf/fancontrol") and not os.path.exists(device_path+"/fancontrol"): + shutil.copy(device_path+"/pddf/fancontrol",device_path+"/fancontrol") + + # BMC support + f_sensors="/usr/bin/sensors" + f_sensors_org="/usr/bin/sensors.org" + f_pddf_sensors="/usr/local/bin/pddf_sensors" + if os.path.exists(f_pddf_sensors) is True: + if os.path.exists(f_sensors_org) is False: + shutil.copy(f_sensors, f_sensors_org) + shutil.copy(f_pddf_sensors, f_sensors) + + + return 0 + +def cleanup_pddf_utils(): + device_path = get_path_to_device() + SONIC_PLATFORM_BSP_WHL_PKG = "/".join([device_path, 'sonic_platform-1.0-py2-none-any.whl']) + SONIC_PLATFORM_PDDF_WHL_PKG = "/".join([device_path, 'pddf', 'sonic_platform-1.0-py2-none-any.whl']) + SONIC_PLATFORM_BSP_WHL_PKG_BK = "/".join([device_path, 'sonic_platform-1.0-py2-none-any.whl.orig']) + # ########################################################################## + status, output = log_os_system("pip show sonic-platform > /dev/null 2>&1", 1) + if status: + # PDDF Platform API 2.0 is not supported but system is in PDDF mode, hence PDDF 1.0 plugins are present + device_plugin_path = "/".join([device_path, "plugins"]) + backup_path = "/".join([device_plugin_path, "orig"]) + if os.path.exists(backup_path) is True: + for item in os.listdir(device_plugin_path): + if os.path.isdir(device_plugin_path+"/"+item) is False: + os.remove(device_plugin_path+"/"+item) + + log_os_system("mv "+backup_path+"/*"+" "+device_plugin_path, 1) + os.rmdir(backup_path) + else: + print "\nERR: Unable to locate original device files...\n" + + else: + # PDDF 2.0 apis are supported and PDDF whl package is installed + if os.path.exists(SONIC_PLATFORM_PDDF_WHL_PKG): + if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_BK): + # platform is 2.0 compliant and original bsp 2.0 whl package exist + log_os_system('mv '+SONIC_PLATFORM_BSP_WHL_PKG_BK+' '+SONIC_PLATFORM_BSP_WHL_PKG, 1) + status, output = log_os_system("pip uninstall sonic-platform -y &> /dev/null", 1) + if status: + print "Error: Unable to uninstall PDDF sonic-platform whl package" + return status + print "Attemting to install the BSP sonic_platform wheel package ..." + status, output = log_os_system("pip install "+ SONIC_PLATFORM_BSP_WHL_PKG, 1) + if status: + print "Error: Failed to install {}".format(SONIC_PLATFORM_BSP_WHL_PKG) + return status + else: + print "Successfully installed {} package".format(SONIC_PLATFORM_BSP_WHL_PKG) + else: + # platform doesnt support 2.0 APIs but PDDF is 2.0 based + # remove and uninstall the PDDF whl package + if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG): + os.remove(SONIC_PLATFORM_BSP_WHL_PKG) + status, output = log_os_system("pip uninstall sonic-platform -y &> /dev/null", 1) + if status: + print "Error: Unable to uninstall PDDF sonic-platform whl package" + return status + else: + # something seriously wrong. System is in PDDF mode but pddf whl pkg is not present + print "Error: Fatal error as the system is in PDDF mode but the pddf .whl original is not present" + # ################################################################################################################ + + if os.path.exists(device_path+"/fancontrol"): + os.remove(device_path+"/fancontrol") + + if os.path.exists(device_path+"/fancontrol.bak"): + log_os_system("mv "+device_path+"/fancontrol.bak"+" "+device_path+"/fancontrol", 0) + + # BMC support + f_sensors="/usr/bin/sensors" + f_sensors_org="/usr/bin/sensors.org" + if os.path.exists(f_sensors_org) is True: + shutil.copy(f_sensors_org, f_sensors) + + return 0 + +def create_pddf_log_files(): + if not os.path.exists('/var/log/pddf'): + log_os_system("sudo mkdir /var/log/pddf", 1) + + log_os_system("sudo touch /var/log/pddf/led.txt", 1) + log_os_system("sudo touch /var/log/pddf/psu.txt", 1) + log_os_system("sudo touch /var/log/pddf/fan.txt", 1) + log_os_system("sudo touch /var/log/pddf/xcvr.txt", 1) + log_os_system("sudo touch /var/log/pddf/sysstatus.txt", 1) + log_os_system("sudo touch /var/log/pddf/cpld.txt", 1) + log_os_system("sudo touch /var/log/pddf/cpldmux.txt", 1) + log_os_system("sudo touch /var/log/pddf/client.txt", 1) + log_os_system("sudo touch /var/log/pddf/mux.txt", 1) + +def driver_install(): + global FORCE + + # check for pre_driver_install script + if os.path.exists('/usr/local/bin/pddf_pre_driver_install.sh'): + status, output = log_os_system('/usr/local/bin/pddf_pre_driver_install.sh', 1) + if status: + print "Error: pddf_pre_driver_install script failed with error %d"%status + return status + + log_os_system("depmod", 1) + for i in range(0,len(kos)): + status, output = log_os_system(kos[i], 1) + if status: + print "driver_install() failed with error %d"%status + if FORCE == 0: + return status + + output = config_pddf_utils() + if output: + print "config_pddf_utils() failed with error %d"%output + # check for post_driver_install script + if os.path.exists('/usr/local/bin/pddf_post_driver_install.sh'): + status, output = log_os_system('/usr/local/bin/pddf_post_driver_install.sh', 1) + if status: + print "Error: pddf_post_driver_install script failed with error %d"%status + return status + + + return 0 + +def driver_uninstall(): + global FORCE + + status = cleanup_pddf_utils() + if status: + print "cleanup_pddf_utils() failed with error %d"%status + + for i in range(0,len(kos)): + # if it is in perm_kos, do not remove + if (kos[-(i+1)].split())[-1] in perm_kos or 'i2c-i801' in kos[-(i+1)]: + continue + + rm = kos[-(i+1)].replace("modprobe", "modprobe -rq") + rm = rm.replace("insmod", "rmmod") + status, output = log_os_system(rm, 1) + if status: + print "driver_uninstall() failed with error %d"%status + if FORCE == 0: + return status + return 0 + +def device_install(): + global FORCE + + # check for pre_device_creation script + if os.path.exists('/usr/local/bin/pddf_pre_device_create.sh'): + status, output = log_os_system('/usr/local/bin/pddf_pre_device_create.sh', 1) + if status: + print "Error: pddf_pre_device_create script failed with error %d"%status + return status + + # trigger the pddf_obj script for FAN, PSU, CPLD, MUX, etc + status = pddf_obj.create_pddf_devices() + if status: + print "Error: create_pddf_devices() failed with error %d"%status + if FORCE == 0: + return status + + # check for post_device_create script + if os.path.exists('/usr/local/bin/pddf_post_device_create.sh'): + status, output = log_os_system('/usr/local/bin/pddf_post_device_create.sh', 1) + if status: + print "Error: pddf_post_device_create script failed with error %d"%status + return status + + return + +def device_uninstall(): + global FORCE + # Trigger the paloparse script for deletion of FAN, PSU, OPTICS, CPLD clients + status = pddf_obj.delete_pddf_devices() + if status: + print "Error: delete_pddf_devices() failed with error %d"%status + if FORCE == 0: + return status + return + +def do_install(): + print "Checking system...." + if not os.path.exists('/usr/share/sonic/platform/pddf_support'): + print PROJECT_NAME.upper() +" mode is not enabled" + return + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no PDDF driver installed...." + create_pddf_log_files() + print "Installing ..." + status = driver_install() + if status: + return status + else: + print PROJECT_NAME.upper() +" drivers detected...." + + print "Creating devices ..." + status = device_install() + if status: + return status + + return + +def do_uninstall(): + print "Checking system...." + if not os.path.exists('/usr/share/sonic/platform/pddf_support'): + print PROJECT_NAME.upper() +" mode is not enabled" + return + + + if os.path.exists('/var/log/pddf'): + print "Remove pddf log files....." + log_os_system("sudo rm -rf /var/log/pddf", 1) + + print "Remove all the devices..." + status = device_uninstall() + if status: + return status + + + if driver_check()== False : + print PROJECT_NAME.upper() +" has no PDDF driver installed...." + else: + print "Removing installed driver...." + status = driver_uninstall() + if status: + if FORCE == 0: + return status + return + +def do_switch_pddf(): + try: + import pddf_switch_svc + except ImportError: + print "Unable to find pddf_switch_svc.py. PDDF might not be supported on this platform" + sys.exit() + print "Check the pddf support..." + status = pddf_switch_svc.check_pddf_support() + if not status: + print "PDDF is not supported on this platform" + return status + + + print "Checking system...." + if os.path.exists('/usr/share/sonic/platform/pddf_support'): + print PROJECT_NAME.upper() +" system is already in pddf mode...." + else: + print "Check if the native sonic-platform whl package is installed in the pmon docker" + status, output = log_os_system("docker exec -it pmon pip show sonic-platform", 1) + if not status: + # Need to remove this whl module + status, output = log_os_system("docker exec -it pmon pip uninstall sonic-platform -y", 1) + if not status: + print "Successfully uninstalled the native sonic-platform whl pkg from pmon container" + else: + print "Error: Unable to uninstall the sonic-platform whl pkg from pmon container.\ + Do it manually before moving to nonpddf mode" + return status + print "Stopping the pmon service ..." + status, output = log_os_system("systemctl stop pmon.service", 1) + if status: + print "Pmon stop failed" + if FORCE==0: + return status + + print "Stopping the platform services.." + status = pddf_switch_svc.stop_platform_svc() + if not status: + if FORCE==0: + return status + + print "Creating the pddf_support file..." + if os.path.exists('/usr/share/sonic/platform'): + log_os_system("touch /usr/share/sonic/platform/pddf_support", 1) + else: + print "/usr/share/sonic/platform path doesn't exist. Unable to set pddf mode" + return -1 + + print "Starting the PDDF platform service..." + status = pddf_switch_svc.start_platform_pddf() + if not status: + if FORCE==0: + return status + + print "Restart the pmon service ..." + status, output = log_os_system("systemctl start pmon.service", 1) + if status: + print "Pmon restart failed" + if FORCE==0: + return status + + return + +def do_switch_nonpddf(): + try: + import pddf_switch_svc + except ImportError: + print "Unable to find pddf_switch_svc.py. PDDF might not be supported on this platform" + sys.exit() + print "Checking system...." + if not os.path.exists('/usr/share/sonic/platform/pddf_support'): + print PROJECT_NAME.upper() +" system is already in non-pddf mode...." + else: + print "Check if the sonic-platform whl package is installed in the pmon docker" + status, output = log_os_system("docker exec -it pmon pip show sonic-platform", 1) + if not status: + # Need to remove this whl module + status, output = log_os_system("docker exec -it pmon pip uninstall sonic-platform -y", 1) + if not status: + print "Successfully uninstalled the sonic-platform whl pkg from pmon container" + else: + print "Error: Unable to uninstall the sonic-platform whl pkg from pmon container.\ + Do it manually before moving to nonpddf mode" + return status + print "Stopping the pmon service ..." + status, output = log_os_system("systemctl stop pmon.service", 1) + if status: + print "Stopping pmon service failed" + if FORCE==0: + return status + + print "Stopping the PDDF platform service..." + status = pddf_switch_svc.stop_platform_pddf() + if not status: + if FORCE==0: + return status + + print "Removing the pddf_support file..." + if os.path.exists('/usr/share/sonic/platform'): + log_os_system("rm -f /usr/share/sonic/platform/pddf_support", 1) + else: + print "/usr/share/sonic/platform path doesnt exist. Unable to set non-pddf mode" + return -1 + + print "Starting the platform services..." + status = pddf_switch_svc.start_platform_svc() + if not status: + if FORCE==0: + return status + + print "Restart the pmon service ..." + status, output = log_os_system("systemctl start pmon.service", 1) + if status: + print "Restarting pmon service failed" + if FORCE==0: + return status + + return + +if __name__ == "__main__": + main() diff --git a/platform/pddf/i2c/utils/pddfparse.py b/platform/pddf/i2c/utils/pddfparse.py new file mode 100755 index 000000000000..f9ce8fca0b42 --- /dev/null +++ b/platform/pddf/i2c/utils/pddfparse.py @@ -0,0 +1,1949 @@ +#!/usr/bin/env python +import argparse +import glob +import json +from jsonschema import validate +import os +import re +import subprocess +import sys +import time +import unicodedata + +bmc_cache={} +cache={} +SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen' +HWSKU_KEY = 'DEVICE_METADATA.localhost.hwsku' +PLATFORM_KEY = 'DEVICE_METADATA.localhost.platform' + +dirname=os.path.dirname(os.path.realpath(__file__)) + +color_map = { + "STATUS_LED_COLOR_GREEN" : "green", + "STATUS_LED_COLOR_RED" : "red", + "STATUS_LED_COLOR_AMBER" : "amber", + "STATUS_LED_COLOR_BLUE" : "blue", + "STATUS_LED_COLOR_GREEN_BLINK" : "blinking green", + "STATUS_LED_COLOR_RED_BLINK" : "blinking red", + "STATUS_LED_COLOR_AMBER_BLINK" : "blinking amber", + "STATUS_LED_COLOR_BLUE_BLINK" : "blinking blue", + "STATUS_LED_COLOR_OFF" : "off" +} + + + + +class PddfParse(): + def __init__(self): + if not os.path.exists("/usr/share/sonic/platform"): + platform, hwsku = self.get_platform_and_hwsku() + os.symlink("/usr/share/sonic/device/"+platform, "/usr/share/sonic/platform") + + try: + with open('/usr/share/sonic/platform/pddf/pddf-device.json') as f: + self.data = json.load(f) + except IOError: + if os.path.exists('/usr/share/sonic/platform'): + os.unlink("/usr/share/sonic/platform") + raise Exception('PDDF JSON file not found. PDDF is not supported on this platform') + + + self.data_sysfs_obj={} + self.sysfs_obj={} + + + # Returns platform and HW SKU + def get_platform_and_hwsku(self): + 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) + + ################################################################################################################### + # GENERIC DEFS + ################################################################################################################### + def runcmd(self, cmd): + rc = os.system(cmd) + if rc!=0: + print "%s -- command failed"%cmd + return rc + + def get_dev_idx(self, dev, ops): + parent=dev['dev_info']['virt_parent'] + pdev=self.data[parent] + + return pdev['dev_attr']['dev_idx'] + + + def get_path(self, target, attr): + aa = target + attr + + if aa in cache: + return cache[aa] + + string = None + p = re.search(r'\d+$', target) + if p is None: + for bb in filter(re.compile(target).search,self.data.keys()): + path = self.dev_parse(self.data[bb], { "cmd": "show_attr", "target":bb, "attr":attr }) + if path != "": + string = path + else: + if target in self.data.keys(): + path = self.dev_parse(self.data[target], { "cmd": "show_attr", "target":target, "attr":attr }) + if path != "": + string = path + + + if string is not None: + string = string.rstrip() + + cache[aa]=string + return string + + + def get_device_type(self, key): + if not key in self.data.keys(): + return None + return self.data[key]['dev_info']['device_type'] + + def get_platform(self): + return self.data['PLATFORM'] + + def get_num_psu_fans(self, dev): + if not dev in self.data.keys(): + return 0 + + if not 'num_psu_fans' in self.data[dev]['dev_attr']: + return 0 + + return self.data[dev]['dev_attr']['num_psu_fans'] + + def get_led_path(self): + return ("pddf/devices/led") + + def get_led_cur_state_path(self): + return ("pddf/devices/led/cur_state") + + def get_led_color(self): + color_f="/sys/kernel/pddf/devices/led/cur_state/color" + try: + with open(color_f, 'r') as f: + color = f.read().strip("\r\n") + except IOError: + return ("Error") + + return (color_map[color]) + + ################################################################################################################### + # CREATE DEFS + ################################################################################################################### + def create_device(self, attr, path, ops): + ret = 0 + for key in attr.keys(): + if type(attr[key]) is list: + val = " ".join(attr[key]) + else: + val = attr[key] + + cmd="echo '%s' > /sys/kernel/%s/%s"%(val, path, key) + ret=self.runcmd(cmd) + if ret!=0: + return ret + return ret + + + def create_psu_i2c_device(self, dev, ops): + create_ret = 0 + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PSU']: + create_ret = self.create_device(dev['i2c']['topo_info'], "pddf/devices/psu/i2c", ops) + if create_ret!=0: + return create_ret + cmd= "echo '%s' > /sys/kernel/pddf/devices/psu/i2c/i2c_name"%(dev['dev_info']['device_name']) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + cmd= "echo '%s' > /sys/kernel/pddf/devices/psu/i2c/psu_idx"%( self.get_dev_idx(dev, ops)) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + for attr in dev['i2c']['attr_list']: + create_ret = self.create_device(attr, "pddf/devices/psu/i2c", ops) + if create_ret!=0: + return create_ret + cmd= "echo 'add' > /sys/kernel/pddf/devices/psu/i2c/attr_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + cmd = "echo 'add' > /sys/kernel/pddf/devices/psu/i2c/dev_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + else: + cmd = "echo %s 0x%x > /sys/bus/i2c/devices/i2c-%d/new_device" % (dev['i2c']['topo_info']['dev_type'], + int(dev['i2c']['topo_info']['dev_addr'], 0), int(dev['i2c']['topo_info']['parent_bus'], 0)) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + + return create_ret + + + + def create_psu_bmc_device(self, dev, ops): + print "" + + + def create_psu_device(self, dev, ops): + return self.create_psu_i2c_device(dev, ops ) + + def create_fan_device(self, dev, ops): + create_ret = 0 + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['FAN']: + create_ret = self.create_device(dev['i2c']['topo_info'], "pddf/devices/fan/i2c", ops) + if create_ret!=0: + return create_ret + cmd= "echo '%s' > /sys/kernel/pddf/devices/fan/i2c/i2c_name"%(dev['dev_info']['device_name']) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + create_ret = self.create_device(dev['i2c']['dev_attr'], "pddf/devices/fan/i2c", ops) + if create_ret!=0: + return create_ret + for attr in dev['i2c']['attr_list']: + create_ret = self.create_device(attr, "pddf/devices/fan/i2c", ops) + if create_ret!=0: + return create_ret + cmd= "echo 'add' > /sys/kernel/pddf/devices/fan/i2c/attr_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + cmd= "echo 'add' > /sys/kernel/pddf/devices/fan/i2c/dev_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + else: + cmd= "echo %s 0x%x > /sys/bus/i2c/devices/i2c-%d/new_device" % (dev['i2c']['topo_info']['dev_type'], + int(dev['i2c']['topo_info']['dev_addr'], 0), int(dev['i2c']['topo_info']['parent_bus'], 0)) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + return create_ret + + def create_temp_sensor_device(self, dev, ops): + create_ret = 0 + # NO PDDF driver for temp_sensors device + cmd= "echo %s 0x%x > /sys/bus/i2c/devices/i2c-%d/new_device" % (dev['i2c']['topo_info']['dev_type'], + int(dev['i2c']['topo_info']['dev_addr'], 0), int(dev['i2c']['topo_info']['parent_bus'], 0)) + create_ret = self.runcmd(cmd) + return create_ret + + + + + def create_cpld_device(self, dev, ops): + create_ret = 0 + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['CPLD']: + create_ret = self.create_device(dev['i2c']['topo_info'], "pddf/devices/cpld", ops) + if create_ret!=0: + return create_ret + + cmd= "echo '%s' > /sys/kernel/pddf/devices/cpld/i2c_name"%(dev['dev_info']['device_name']) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + # TODO: If attributes are provided then, use 'self.create_device' for them too + cmd= "echo 'add' > /sys/kernel/pddf/devices/cpld/dev_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + else: + cmd= "echo %s 0x%x > /sys/bus/i2c/devices/i2c-%d/new_device" % (dev['i2c']['topo_info']['dev_type'], + int(dev['i2c']['topo_info']['dev_addr'], 0), int(dev['i2c']['topo_info']['parent_bus'], 0)) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + return create_ret + + def create_cpldmux_device(self, dev, ops): + create_ret = 0 + create_ret = self.create_device(dev['i2c']['topo_info'], "pddf/devices/cpldmux", ops) + if create_ret!=0: + return create_ret + cmd= "echo '%s' > /sys/kernel/pddf/devices/mux/i2c_name"%(dev['dev_info']['device_name']) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + self.create_device(dev['i2c']['dev_attr'], "pddf/devices/cpldmux", ops) + # Parse channel info + for chan in dev['i2c']['channel']: + self.create_device(chan, "pddf/devices/cpldmux", ops) + cmd="echo 'add' > /sys/kernel/pddf/devices/cpldmux/chan_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + cmd= "echo 'add' > /sys/kernel/pddf/devices/cpldmux/dev_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + def create_gpio_device(self, dev, ops): + create_ret = 0 + create_ret = self.create_device(dev['i2c']['topo_info'], "pddf/devices/gpio", ops) + if create_ret!=0: + return create_ret + cmd= "echo '%s' > /sys/kernel/pddf/devices/gpio/i2c_name"%(dev['dev_info']['device_name']) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + create_ret = self.create_device(dev['i2c']['dev_attr'], "pddf/devices/gpio", ops) + if create_ret!=0: + return create_ret + cmd= "echo 'add' > /sys/kernel/pddf/devices/gpio/dev_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + time.sleep(2) + base = dev['i2c']['dev_attr']['gpio_base'] + for inst in dev['i2c']['ports']: + if inst['port_num']!="": + port_no = int(base, 16) + int(inst['port_num']) + cmd= "echo %d > /sys/class/gpio/export"%port_no + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + if inst['direction']!="": + cmd= "echo %s >/sys/class/gpio/gpio%d/direction"%(inst['direction'], port_no) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + if inst['value']!="": + for i in inst['value'].split(','): + cmd= "echo %s >/sys/class/gpio/gpio%d/value"%(i.rstrip(), port_no) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + return create_ret + + def create_mux_device(self, dev, ops): + create_ret = 0 + create_ret = self.create_device(dev['i2c']['topo_info'], "pddf/devices/mux", ops) + if create_ret!=0: + return create_ret + cmd= "echo '%s' > /sys/kernel/pddf/devices/mux/i2c_name"%(dev['dev_info']['device_name']) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + self.create_device(dev['i2c']['dev_attr'], "pddf/devices/mux", ops) + cmd= "echo 'add' > /sys/kernel/pddf/devices/mux/dev_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + + def create_xcvr_i2c_device(self, dev, ops): + create_ret = 0 + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PORT_MODULE']: + self.create_device(dev['i2c']['topo_info'], "pddf/devices/xcvr/i2c", ops) + cmd= "echo '%s' > /sys/kernel/pddf/devices/xcvr/i2c/i2c_name"%(dev['dev_info']['device_name']) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + cmd="echo '%s' > /sys/kernel/pddf/devices/xcvr/i2c/dev_idx"%( self.get_dev_idx(dev, ops)) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + for attr in dev['i2c']['attr_list']: + self.create_device(attr, "pddf/devices/xcvr/i2c", ops) + cmd="echo 'add' > /sys/kernel/pddf/devices/xcvr/i2c/attr_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + cmd="echo 'add' > /sys/kernel/pddf/devices/xcvr/i2c/dev_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + else: + cmd="echo %s 0x%x > /sys/bus/i2c/devices/i2c-%d/new_device" % (dev['i2c']['topo_info']['dev_type'], + int(dev['i2c']['topo_info']['dev_addr'], 0), int(dev['i2c']['topo_info']['parent_bus'], 0)) + create_ret = self.runcmd(cmd) + #print "\n" + if create_ret!=0: + return create_ret + # Add port name + port_name_sysfs = '/sys/bus/i2c/devices/{}-00{:02x}/port_name'.format( + int(dev['i2c']['topo_info']['parent_bus'], 0),int(dev['i2c']['topo_info']['dev_addr'], 0)) + + if os.path.exists(port_name_sysfs): + cmd="echo {} > /sys/bus/i2c/devices/{}-00{:02x}/port_name".format( + dev['dev_info']['virt_parent'].lower(), int(dev['i2c']['topo_info']['parent_bus'], 0), + int(dev['i2c']['topo_info']['dev_addr'], 0)) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + return create_ret + + def create_xcvr_bmc_device(self, dev, ops): + print "" + + def create_xcvr_device(self, dev, ops): + return self.create_xcvr_i2c_device(dev, ops ) + + def create_sysstatus_device(self, dev, ops): + create_ret = 0 + for attr in dev['attr_list']: + self.create_device(attr, "pddf/devices/sysstatus", ops) + cmd= "echo 'add' > /sys/kernel/pddf/devices/sysstatus/attr_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + def create_eeprom_device(self, dev, ops): + create_ret = 0 + if "EEPROM" in self.data['PLATFORM']['pddf_dev_types'] and \ + dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['EEPROM']: + self.create_device(dev['i2c']['topo_info'], "pddf/devices/eeprom/i2c", ops) + cmd= "echo '%s' > /sys/kernel/pddf/devices/eeprom/i2c/i2c_name"%(dev['dev_info']['device_name']) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + self.create_device(dev['i2c']['dev_attr'], "pddf/devices/eeprom/i2c", ops) + cmd = "echo 'add' > /sys/kernel/pddf/devices/eeprom/i2c/dev_ops" + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + else: + cmd= "echo %s 0x%x > /sys/bus/i2c/devices/i2c-%d/new_device" % (dev['i2c']['topo_info']['dev_type'], + int(dev['i2c']['topo_info']['dev_addr'], 0), int(dev['i2c']['topo_info']['parent_bus'], 0)) + create_ret = self.runcmd(cmd) + if create_ret!=0: + return create_ret + + return create_ret + + ################################################################################################################### + # DELETE DEFS + ################################################################################################################### + def delete_eeprom_device(self, dev, ops): + if "EEPROM" in self.data['PLATFORM']['pddf_dev_types'] and \ + dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['EEPROM']: + cmd= "echo '%s' > /sys/kernel/pddf/devices/eeprom/i2c/i2c_name"%(dev['dev_info']['device_name']) + self.runcmd(cmd) + cmd = "echo 'delete' > /sys/kernel/pddf/devices/eeprom/i2c/dev_ops" + self.runcmd(cmd) + else: + cmd= "echo 0x%x > /sys/bus/i2c/devices/i2c-%d/delete_device" % (int(dev['i2c']['topo_info']['dev_addr'], 0), + int(dev['i2c']['topo_info']['parent_bus'], 0)) + self.runcmd(cmd) + + def delete_sysstatus_device(self, dev, ops): + # NOT A PHYSICAL DEVICE.... rmmod on module would remove all the artifacts + pass + + + def delete_xcvr_i2c_device(self, dev, ops): + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PORT_MODULE']: + cmd= "echo '%s' > /sys/kernel/pddf/devices/xcvr/i2c/i2c_name"%(dev['dev_info']['device_name']) + self.runcmd(cmd) + cmd="echo 'delete' > /sys/kernel/pddf/devices/xcvr/i2c/dev_ops" + self.runcmd(cmd) + else: + cmd="echo 0x%x > /sys/bus/i2c/devices/i2c-%d/delete_device" % (int(dev['i2c']['topo_info']['dev_addr'], 0), + int(dev['i2c']['topo_info']['parent_bus'], 0)) + self.runcmd(cmd) + + def delete_xcvr_device(self, dev, ops): + self.delete_xcvr_i2c_device(dev, ops) + return + + def delete_gpio_device(self, dev, ops): + cmd= "echo '%s' > /sys/kernel/pddf/devices/gpio/i2c_name"%(dev['dev_info']['device_name']) + self.runcmd(cmd) + cmd= "echo 'delete' > /sys/kernel/pddf/devices/gpio/dev_ops" + self.runcmd(cmd) + + def delete_mux_device(self, dev, ops): + cmd= "echo '%s' > /sys/kernel/pddf/devices/mux/i2c_name"%(dev['dev_info']['device_name']) + self.runcmd(cmd) + cmd= "echo 'delete' > /sys/kernel/pddf/devices/mux/dev_ops" + self.runcmd(cmd) + + def delete_cpld_device(self, dev, ops): + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['CPLD']: + cmd= "echo '%s' > /sys/kernel/pddf/devices/cpld/i2c_name"%(dev['dev_info']['device_name']) + self.runcmd(cmd) + cmd= "echo 'delete' > /sys/kernel/pddf/devices/cpld/dev_ops" + self.runcmd(cmd) + else: + cmd= "echo 0x%x > /sys/bus/i2c/devices/i2c-%d/delete_device" % (int(dev['i2c']['topo_info']['dev_addr'], 0), + int(dev['i2c']['topo_info']['parent_bus'], 0)) + self.runcmd(cmd) + + def delete_cpldmux_device(self, dev, ops): + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['CPLDMUX']: + cmd= "echo '%s' > /sys/kernel/pddf/devices/cpldmux/i2c_name"%(dev['dev_info']['device_name']) + self.runcmd(cmd) + cmd= "echo 'delete' > /sys/kernel/pddf/devices/cpldmux/dev_ops" + self.runcmd(cmd) + + def delete_temp_sensor_device(self, dev, ops): + # NO PDDF driver for temp_sensors device + cmd= "echo 0x%x > /sys/bus/i2c/devices/i2c-%d/delete_device" % (int(dev['i2c']['topo_info']['dev_addr'], 0), + int(dev['i2c']['topo_info']['parent_bus'], 0)) + self.runcmd(cmd) + + def delete_fan_device(self, dev, ops): + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['FAN']: + cmd= "echo '%s' > /sys/kernel/pddf/devices/fan/i2c/i2c_name"%(dev['dev_info']['device_name']) + self.runcmd(cmd) + cmd= "echo 'delete' > /sys/kernel/pddf/devices/fan/i2c/dev_ops" + self.runcmd(cmd) + else: + cmd= "echo 0x%x > /sys/bus/i2c/devices/i2c-%d/delete_device" % (int(dev['i2c']['topo_info']['dev_addr'], 0), + int(dev['i2c']['topo_info']['parent_bus'], 0)) + self.runcmd(cmd) + + + def delete_psu_i2c_device(self, dev, ops): + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PSU']: + cmd= "echo '%s' > /sys/kernel/pddf/devices/psu/i2c/i2c_name"%(dev['dev_info']['device_name']) + self.runcmd(cmd) + cmd = "echo 'delete' > /sys/kernel/pddf/devices/psu/i2c/dev_ops" + self.runcmd(cmd) + else: + cmd = "echo 0x%x > /sys/bus/i2c/devices/i2c-%d/delete_device" %(int(dev['i2c']['topo_info']['dev_addr'], 0), + int(dev['i2c']['topo_info']['parent_bus'], 0)) + self.runcmd(cmd) + + def delete_psu_device(self, dev, ops): + self.delete_psu_i2c_device(dev, ops ) + return + + + ################################################################################################################### + # SHOW ATTRIBIUTES DEFS + ################################################################################################################### + def is_led_device_configured(self, device_name, attr_name): + if device_name in self.data.keys(): + attr_list=self.data[device_name]['i2c']['attr_list'] + for attr in attr_list: + if attr['attr_name'].strip() == attr_name.strip(): + return (True) + return (False) + + + def show_device_sysfs(self, dev, ops): + parent=dev['dev_info']['device_parent'] + pdev=self.data[parent] + if pdev['dev_info']['device_parent'] == 'SYSTEM': + return "/sys/bus/i2c/devices/"+"i2c-%d"%int(pdev['i2c']['topo_info']['dev_addr'], 0) + return self.show_device_sysfs(pdev, ops) + "/" + "i2c-%d" % int(dev['i2c']['topo_info']['parent_bus'], 0) + + + # This is alid for 'at24' type of EEPROM devices. Only one attribtue 'eeprom' + def show_attr_eeprom_device(self, dev, ops): + str = "" + attr_name=ops['attr'] + attr_list=dev['i2c']['attr_list'] + KEY="eeprom" + dsysfs_path="" + + if not KEY in self.data_sysfs_obj: + self.data_sysfs_obj[KEY]=[] + + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all': + if 'drv_attr_name' in attr.keys(): + real_name = attr['drv_attr_name'] + else: + real_name = attr['attr_name'] + + dsysfs_path = self.show_device_sysfs(dev, ops)+"/%d-00%x"%(int(dev['i2c']['topo_info']['parent_bus'],0), + int(dev['i2c']['topo_info']['dev_addr'], 0))+"/%s"%real_name + if not dsysfs_path in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + str += dsysfs_path+"\n" + return str + + def show_attr_gpio_device(self, dev, ops): + ret = "" + KEY="gpio" + if not KEY in self.data_sysfs_obj: + self.data_sysfs_obj[KEY]=[] + + return ret + + + def show_attr_mux_device(self, dev, ops): + ret = "" + KEY="mux" + if not KEY in self.data_sysfs_obj: + self.data_sysfs_obj[KEY]=[] + + return ret + + def show_attr_psu_i2c_device(self, dev, ops): + target=ops['target'] + attr_name=ops['attr'] + ret = "" + KEY="psu" + dsysfs_path="" + + if not KEY in self.data_sysfs_obj: + self.data_sysfs_obj[KEY]=[] + + if target == 'all' or target == dev['dev_info']['virt_parent'] : + attr_list=dev['i2c']['attr_list'] + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all' : + if 'attr_devtype' in attr.keys() and attr['attr_devtype'] == "gpio": + # Check and enable the gpio from class + gpio_dev = self.data[attr['attr_devname']] + base = int(gpio_dev['i2c']['dev_attr']['gpio_base'], 16) + port_num = base + int(attr['attr_offset'], 16) + gpio_name = 'gpio'+str(port_num) + attr_path = '/sys/class/gpio/'+gpio_name+'/value' + if (os.path.exists(attr_path)): + if not attr_path in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(attr_path) + ret += attr_path + '\n' + else: + if 'drv_attr_name' in attr.keys(): + real_name = attr['drv_attr_name'] + else: + real_name = attr['attr_name'] + + dsysfs_path = self.show_device_sysfs(dev, ops) + \ + "/%d-00%x"%(int(dev['i2c']['topo_info']['parent_bus'], 0), + int(dev['i2c']['topo_info']['dev_addr'], 0)) + \ + "/%s"%real_name + if not dsysfs_path in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + ret += dsysfs_path+"\n" + return ret + + + def show_attr_psu_device(self, dev, ops): + return self.show_attr_psu_i2c_device(dev, ops ) + + + def show_attr_fan_device(self, dev, ops): + ret_str = "" + attr_name=ops['attr'] + attr_list=dev['i2c']['attr_list'] + KEY="fan" + dsysfs_path="" + + if not KEY in self.data_sysfs_obj: + self.data_sysfs_obj[KEY]=[] + + + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all': + if 'drv_attr_name' in attr.keys(): + real_name = attr['drv_attr_name'] + else: + real_name = attr['attr_name'] + + dsysfs_path= self.show_device_sysfs(dev, ops) + \ + "/%d-00%x" %(int(dev['i2c']['topo_info']['parent_bus'], 0), + int(dev['i2c']['topo_info']['dev_addr'], 0)) + \ + "/%s"%real_name + if not dsysfs_path in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + ret_str += dsysfs_path+"\n" + return ret_str + + # This is only valid for LM75 + def show_attr_temp_sensor_device(self, dev, ops): + ret_str = "" + attr_name=ops['attr'] + attr_list=dev['i2c']['attr_list'] + KEY="temp-sensors" + dsysfs_path="" + + if not KEY in self.data_sysfs_obj: + self.data_sysfs_obj[KEY]=[] + + + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all': + path = self.show_device_sysfs(dev, ops) + \ + "/%d-00%x/" %(int(dev['i2c']['topo_info']['parent_bus'], 0), + int(dev['i2c']['topo_info']['dev_addr'], 0)) + if 'drv_attr_name' in attr.keys(): + real_name = attr['drv_attr_name'] + else: + real_name = attr['attr_name'] + + if (os.path.exists(path)): + full_path = glob.glob(path + 'hwmon/hwmon*/' + real_name)[0] + dsysfs_path=full_path + if not dsysfs_path in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + ret_str += full_path + "\n" + return ret_str + + def show_attr_sysstatus_device(self, dev, ops): + ret = "" + attr_name=ops['attr'] + attr_list=dev['attr_list'] + KEY="sys-status" + dsysfs_path="" + + if not KEY in self.data_sysfs_obj: + self.data_sysfs_obj[KEY]=[] + + + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all': + dsysfs_path = "/sys/kernel/pddf/devices/sysstatus/sysstatus_data/" + attr['attr_name'] + if not dsysfs_path in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + ret += dsysfs_path+"\n" + return ret + + + def show_attr_xcvr_i2c_device(self, dev, ops): + target=ops['target'] + attr_name=ops['attr'] + ret = "" + dsysfs_path = "" + KEY="xcvr" + if not KEY in self.data_sysfs_obj: + self.data_sysfs_obj[KEY]=[] + + if target == 'all' or target == dev['dev_info']['virt_parent'] : + attr_list=dev['i2c']['attr_list'] + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all' : + if 'attr_devtype' in attr.keys() and attr['attr_devtype'] == "gpio": + # Check and enable the gpio from class + gpio_dev = self.data[attr['attr_devname']] + base = int(gpio_dev['i2c']['dev_attr']['gpio_base'], 16) + port_num = base + int(attr['attr_offset'], 16) + gpio_name = 'gpio'+str(port_num) + attr_path = '/sys/class/gpio/'+gpio_name+'/value' + if (os.path.exists(attr_path)): + if not attr_path in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(attr_path) + ret += attr_path + '\n' + else: + if 'drv_attr_name' in attr.keys(): + real_name = attr['drv_attr_name'] + else: + real_name = attr['attr_name'] + + dsysfs_path = self.show_device_sysfs(dev, ops) + \ + "/%d-00%x" %(int(dev['i2c']['topo_info']['parent_bus'], 0), + int(dev['i2c']['topo_info']['dev_addr'], 0)) + \ + "/%s"%real_name + if not dsysfs_path in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + ret += dsysfs_path+"\n" + return ret + + + def show_attr_xcvr_device(self, dev, ops): + return self.show_attr_xcvr_i2c_device(dev, ops ) + + def show_attr_cpld_device(self, dev, ops): + ret = "" + KEY="cpld" + if not KEY in self.data_sysfs_obj: + self.data_sysfs_obj[KEY]=[] + + return ret + + def show_attr_cpldmux_device(self, dev, ops): + ret = "" + KEY="cpldmux" + if not KEY in self.data_sysfs_obj: + self.data_sysfs_obj[KEY]=[] + + return ret + + + ################################################################################################################### + # SHOW DEFS + ################################################################################################################### + def check_led_cmds(self, key, ops): + name = ops['target']+'_LED' + if (ops['target']=='config' or ops['attr']=='all') or \ + (name==self.data[key]['dev_info']['device_name'] and + ops['attr']==self.data[key]['dev_attr']['index']): + return (True) + else: + return (False) + + def dump_sysfs_obj(self, obj, key_type): + if (key_type == 'keys'): + for key in obj.keys(): + print key + return + + for key in obj: + if (key == key_type or key_type == 'all'): + print key+":" + for entry in obj[key]: + print "\t"+entry + + def add_list_sysfs_obj(self, obj, KEY, list): + for sysfs in list: + if not sysfs in obj[KEY]: + obj[KEY].append(sysfs) + + def sysfs_attr(self, key, value, path, obj, obj_key): + sysfs_path="/sys/kernel/%s/%s"%(path, key) + if not sysfs_path in obj[obj_key]: + obj[obj_key].append(sysfs_path) + + + def sysfs_device(self, attr, path, obj, obj_key): + for key in attr.keys(): + sysfs_path="/sys/kernel/%s/%s"%(path, key) + if not sysfs_path in obj[obj_key]: + obj[obj_key].append(sysfs_path) + + def show_eeprom_device(self, dev, ops): + return + + + def show_mux_device(self, dev, ops): + KEY ='mux' + if not KEY in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + self.sysfs_device(dev['i2c']['topo_info'], "pddf/devices/mux", self.sysfs_obj, KEY) + self.sysfs_device(dev['i2c']['dev_attr'], "pddf/devices/mux", self.sysfs_obj, KEY) + sysfs_path= "/sys/kernel/pddf/devices/mux/dev_ops" + if not sysfs_path in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list=['/sys/kernel/pddf/devices/mux/i2c_type', + '/sys/kernel/pddf/devices/mux/i2c_name', + '/sys/kernel/pddf/devices/mux/error'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + def show_gpio_device(self, dev, ops): + KEY ='gpio' + if not KEY in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + self.sysfs_device(dev['i2c']['topo_info'], "pddf/devices/gpio", self.sysfs_obj, KEY) + self.sysfs_device(dev['i2c']['dev_attr'], "pddf/devices/gpio", self.sysfs_obj, KEY) + sysfs_path= "/sys/kernel/pddf/devices/gpio/dev_ops" + if not sysfs_path in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list=['/sys/kernel/pddf/devices/gpio/i2c_type', + '/sys/kernel/pddf/devices/gpio/i2c_name', + '/sys/kernel/pddf/devices/gpio/error'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + + def show_psu_i2c_device(self, dev, ops): + KEY ='psu' + path='pddf/devices/psu/i2c' + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PSU']: + if not KEY in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + self.sysfs_device(dev['i2c']['topo_info'], path, self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/psu/i2c/psu_idx" + self.sysfs_obj[KEY].append(sysfs_path) + + for attr in dev['i2c']['attr_list']: + self.sysfs_device(attr, "pddf/devices/psu/i2c", self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/psu/i2c/dev_ops" + if not sysfs_path in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list=['/sys/kernel/pddf/devices/psu/i2c/i2c_type', + '/sys/kernel/pddf/devices/fan/i2c/i2c_name', + '/sys/kernel/pddf/devices/psu/i2c/error', + '/sys/kernel/pddf/devices/psu/i2c/attr_ops'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + + def show_psu_device(self, dev, ops): + self.show_psu_i2c_device(dev, ops ) + return + + def show_client_device(self): + KEY ='client' + if not KEY in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + list=['/sys/kernel/pddf/devices/showall'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + + def show_fan_device(self, dev, ops): + KEY ='fan' + path='pddf/devices/fan/i2c' + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['FAN']: + if not KEY in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + + self.sysfs_device(dev['i2c']['topo_info'], path, self.sysfs_obj, KEY) + self.sysfs_device(dev['i2c']['dev_attr'], path, self.sysfs_obj, KEY) + for attr in dev['i2c']['attr_list']: + self.sysfs_device(attr, path, self.sysfs_obj, KEY) + list=['/sys/kernel/pddf/devices/fan/i2c/i2c_type', + '/sys/kernel/pddf/devices/fan/i2c/i2c_name', + '/sys/kernel/pddf/devices/fan/i2c/error', + '/sys/kernel/pddf/devices/fan/i2c/attr_ops', + '/sys/kernel/pddf/devices/fan/i2c/dev_ops'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + + def show_temp_sensor_device(self, dev, ops): + return + + def show_sysstatus_device(self, dev, ops): + KEY ='sysstatus' + if not KEY in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + for attr in dev['attr_list']: + self.sysfs_device(attr, "pddf/devices/sysstatus", self.sysfs_obj, KEY) + sysfs_path= "/sys/kernel/pddf/devices/sysstatus/attr_ops" + if not sysfs_path in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + + + def show_xcvr_i2c_device(self, dev, ops): + KEY ='xcvr' + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PORT_MODULE']: + if not KEY in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + self.sysfs_device(dev['i2c']['topo_info'], "pddf/devices/xcvr/i2c", self.sysfs_obj, KEY) + + for attr in dev['i2c']['attr_list']: + self.sysfs_device(attr, "pddf/devices/xcvr/i2c", self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/xcvr/i2c/dev_ops" + if not sysfs_path in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list=['/sys/kernel/pddf/devices/xcvr/i2c/i2c_type', + '/sys/kernel/pddf/devices/xcvr/i2c/i2c_name', + '/sys/kernel/pddf/devices/xcvr/i2c/error', + '/sys/kernel/pddf/devices/xcvr/i2c/attr_ops'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + + def show_xcvr_device(self, dev, ops): + self.show_xcvr_i2c_device(dev, ops ) + return + + def show_cpld_device(self, dev, ops): + KEY ='cpld' + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['CPLD']: + if not KEY in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + self.sysfs_device(dev['i2c']['topo_info'], "pddf/devices/cpld", self.sysfs_obj, KEY) + sysfs_path= "/sys/kernel/pddf/devices/cpld/dev_ops" + if not sysfs_path in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list=['/sys/kernel/pddf/devices/cpld/i2c_type', + '/sys/kernel/pddf/devices/cpld/i2c_name', + '/sys/kernel/pddf/devices/cpld/error'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + def show_led_platform_device(self, key, ops): + if ops['attr']=='all' or ops['attr']=='PLATFORM': + KEY='platform' + if not KEY in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + path='pddf/devices/platform' + self.sysfs_attr('num_psus', self.data['PLATFORM']['num_psus'], path, self.sysfs_obj, KEY) + self.sysfs_attr('num_fantrays', self.data['PLATFORM']['num_fantrays'], path, self.sysfs_obj, KEY) + + def show_led_device(self, key, ops): + if self.check_led_cmds(key, ops): + KEY='led' + if not KEY in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + path="pddf/devices/led" + for attr in self.data[key]['i2c']['attr_list']: + self.sysfs_attr('device_name', self.data[key]['dev_info']['device_name'],path,self.sysfs_obj,KEY) + self.sysfs_attr('swpld_addr', self.data[key]['dev_info']['device_name'],path,self.sysfs_obj, KEY) + self.sysfs_attr('swpld_addr_offset',self.data[key]['dev_info']['device_name'], + path,self.sysfs_obj, KEY) + self.sysfs_device(self.data[key]['dev_attr'], path, self.sysfs_obj, KEY) + for attr_key in attr.keys(): + attr_path="pddf/devices/led/" + attr['attr_name'] + if (attr_key != 'attr_name' and attr_key != 'swpld_addr' and attr_key != 'swpld_addr_offset'): + self.sysfs_attr(attr_key, attr[attr_key], attr_path, self.sysfs_obj, KEY) + sysfs_path="/sys/kernel/pddf/devices/led/dev_ops" + if not sysfs_path in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list=['/sys/kernel/pddf/devices/led/cur_state/color'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + + def validate_xcvr_device(self, dev, ops): + devtype_list = ['optoe1', 'optoe2'] + dev_attribs = ['xcvr_present', 'xcvr_reset', 'xcvr_intr_status', 'xcvr_lpmode'] + ret_val = "xcvr validation failed" + + if dev['i2c']['topo_info']['dev_type'] in devtype_list: + for attr in dev['i2c']['attr_list']: + if 'attr_name' in attr.keys() and 'eeprom' in attr.values(): + ret_val = "xcvr validation success" + else: + print "xcvr validation Failed" + return + + elif dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PORT_MODULE']: + for attr in dev['i2c']['attr_list']: + if attr.get("attr_name") in dev_attribs: + ret_val = "Success" + else: + print "xcvr validation Failed" + return + print ret_val + + def validate_eeprom_device(self, dev, ops): + devtype_list = ['24c02'] + dev_access_mode = ['BLOCK', 'BYTE'] + dev_attribs = ['eeprom'] + ret_val = "eeprom failed" + + if dev['i2c']['topo_info']['dev_type'] in devtype_list: + if dev['i2c']['dev_attr']['access_mode'] in dev_access_mode: + for attr in dev['i2c']['attr_list']: + if attr.get("attr_name") in dev_attribs: + ret_val = "eeprom success" + print ret_val + + def validate_mux_device(self, dev, ops): + devtype_list = ['pca9548', 'pca954x'] + dev_channels = ["0", "1", "2", "3", "4", "5", "6", "7"] + ret_val = "mux failed" + + if dev['i2c']['topo_info']['dev_type'] in devtype_list: + for attr in dev['i2c']['channel']: + if attr.get("chn") in dev_channels: + ret_val = "Mux success" + print ret_val + + def validate_cpld_device(self, dev, ops): + devtype_list = ['i2c_cpld'] + ret_val = "cpld failed" + + if dev['i2c']['topo_info']['dev_type'] in devtype_list: + ret_val = "cpld success" + print ret_val + + + def validate_sysstatus_device(self, dev, ops): + dev_attribs = ['board_info', 'cpld1_version', 'power_module_status', 'system_reset5', + 'system_reset6', 'system_reset7', 'misc1', 'cpld2_version', 'cpld3_version' + ] + ret_val = "sysstatus failed" + + if dev['dev_info']['device_type'] == "SYSSTAT": + for attr in dev['attr_list']: + if attr.get("attr_name") in dev_attribs: + ret_val = "sysstatus success" + print ret_val + + def validate_temp_sensor_device(self, dev, ops): + devtype_list = ['lm75'] + dev_attribs = ['temp1_max', 'temp1_max_hyst', 'temp1_input'] + ret_val = "temp sensor failed" + + if dev['dev_info']['device_type'] == "TEMP_SENSOR": + if dev['i2c']['topo_info']['dev_type'] in devtype_list: + for attr in dev['i2c']['attr_list']: + if attr.get("attr_name") in dev_attribs: + ret_val = "tempsensor success" + print ret_val + + def validate_fan_device(self, dev, ops): + ret_val = "fan failed" + + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['FAN']: + if dev['i2c']['dev_attr']['num_fan'] is not None: + ret_val = "fan success" + + print ret_val + + def validate_psu_device(self, dev, ops): + dev_attribs = ['psu_present', 'psu_model_name', 'psu_power_good', 'psu_mfr_id', 'psu_serial_num', + 'psu_fan_dir', 'psu_v_out', 'psu_i_out', 'psu_p_out', 'psu_fan1_speed_rpm' + ] + ret_val = "psu failed" + + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PSU']: + for attr in dev['i2c']['attr_list']: + if attr.get("attr_name") in dev_attribs: + if attr.get("attr_devaddr") is not None: + if attr.get("attr_offset") is not None: + if attr.get("attr_mask") is not None: + if attr.get("attr_len") is not None: + ret_val = "psu success" + else: + ret_val = "psu failed" + + print ret_val + + ################################################################################################################### + # SPYTEST + ################################################################################################################### + def verify_attr(self, key, attr, path): + node="/sys/kernel/%s/%s"%(path, key) + try: + with open(node, 'r') as f: + status = f.read() + except IOError: + print "PDDF_VERIFY_ERR: IOError: node:%s key:%s"%(node, key) + return + + status=status.rstrip("\n\r") + if attr[key]!=status: + print "PDDF_VERIFY_ERR: node: %s switch:%s"%(node, status) + + def verify_device(self, attr, path, ops): + for key in attr.keys(): + self.verify_attr(key, attr, path) + + + def get_led_device(self, device_name): + self.create_attr('device_name', self.data[device_name]['dev_info']['device_name'], "pddf/devices/led") + self.create_attr('index', self.data[device_name]['dev_attr']['index'], "pddf/devices/led") + cmd="echo 'verify' > /sys/kernel/pddf/devices/led/dev_ops" + self.runcmd(cmd) + + def validate_sysfs_creation(self, obj, validate_type): + dir = '/sys/kernel/pddf/devices/'+validate_type + if (os.path.exists(dir) or validate_type=='client'): + for sysfs in obj[validate_type]: + if(not os.path.exists(sysfs)): + print "[SYSFS FILE] " + sysfs + ": does not exist" + else: + print "[SYSFS DIR] " + dir + ": does not exist" + + def validate_dsysfs_creation(self, obj, validate_type): + if validate_type in obj.keys(): + # There is a possibility that some components dont have any device-self.data attr + if not obj[validate_type]: + print "[SYSFS ATTR] for " + validate_type + ": empty " + else: + for sysfs in obj[validate_type]: + if(not os.path.exists(sysfs)): + print "[SYSFS FILE] " + sysfs + ": does not exist" + else: + print "[SYSFS KEY] for " + validate_type + ": not configured" + + def verify_sysfs_data(self, verify_type): + if (verify_type=='LED'): + for key in self.data.keys(): + if key != 'PLATFORM': + attr=self.data[key]['dev_info'] + if attr['device_type'] == 'LED': + self.get_led_device(key) + self.verify_attr('device_name', self.data[key]['dev_info'], "pddf/devices/led") + self.verify_attr('index', self.data[key]['dev_attr'], "pddf/devices/led") + for attr in self.data[key]['i2c']['attr_list']: + path="pddf/devices/led/" + attr['attr_name'] + for entry in attr.keys(): + if (entry != 'attr_name' and entry != 'swpld_addr' and entry != 'swpld_addr_offset'): + self.verify_attr(entry, attr, path) + if ( entry == 'swpld_addr' or entry == 'swpld_addr_offset'): + self.verify_attr(entry, attr, 'pddf/devices/led') + + + + def schema_validation(self, validate_type): + process_validate_type = 0 + for key in self.data.keys(): + if (key != 'PLATFORM'): + temp_obj={} + schema_list=[] + try: + device_type=self.data[key]["dev_info"]["device_type"] + except Exception as e: + print "dev_info or device_type ERROR: " + key + print e + + if validate_type == 'mismatch': + process_validate_type = 1 + device_type="PSU" + schema_file="/usr/local/bin/schema/FAN.schema" + schema_list.append(schema_file) + elif validate_type == 'missing': + process_validate_type = 1 + schema_file="/usr/local/bin/schema/PLATFORM.schema" + schema_list.append(schema_file) + + elif validate_type == 'empty': + process_validate_type = 1 + if not device_type: + print "Empty device_type for " + key + continue + elif (validate_type=='all' or validate_type==device_type): + process_validate_type = 1 + if "bmc" in self.data[key].keys(): + schema_file="/usr/local/bin/schema/"+device_type + "_BMC.schema" + schema_list.append(schema_file) + + if "i2c" in self.data[key].keys(): + schema_file="/usr/local/bin/schema/"+device_type + ".schema" + schema_list.append(schema_file) + if device_type: + temp_obj[device_type]=self.data[key] + for schema_file in schema_list: + if (os.path.exists(schema_file)): + print "Validate " + schema_file + ";" + key + json_data=json.dumps(temp_obj) + with open(schema_file, 'r') as f: + schema=json.load(f) + try: + validate(temp_obj, schema) + except Exception as e: + print "Validation ERROR: " + schema_file + ";" + key + if validate_type == 'mismatch': + return + else: + print e + else: + print "ERROR Missing File: " + schema_file + if not process_validate_type: + print "device_type: " + validate_type + " not configured" + + def modules_validation(self, validate_type): + kos = [] + supported_type = False + module_validation_status=[] + + if validate_type == "bmc": + kos=['ipmi_devintf', 'ipmi_si', 'ipmi_msghandler'] + validate_type = 'ipmi' + else: + # generate the KOS list from pddf device JSON file + kos.extend(self.data['PLATFORM']['pddf_kos']) + + if 'custom_kos' in self.data['PLATFORM']: + kos.extend(self.data['PLATFORM']['custom_kos']) + + for mod in kos: + if validate_type in mod or validate_type == "pddf": + supported_type=True + cmd = "lsmod | grep " + mod + try: + subprocess.check_output(cmd, shell=True) + except Exception as e: + module_validation_status.append(mod) + if supported_type: + if module_validation_status: + module_validation_status.append(":ERROR not loaded") + print str(module_validation_status)[1:-1] + else: + print "Loaded" + else: + print validate_type + " not configured" + + + + + + ################################################################################################################### + # PARSE DEFS + ################################################################################################################### + def psu_parse(self, dev, ops): + parse_str="" + ret="" + for ifce in dev['i2c']['interface']: + ret=getattr(self, ops['cmd']+"_psu_device")(self.data[ifce['dev']], ops ) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_psu_device failed".format(ops['cmd']) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str+=ret + return parse_str + + def fan_parse(self, dev, ops): + parse_str="" + ret=getattr(self, ops['cmd']+"_fan_device")(dev, ops ) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_fan_device failed".format(ops['cmd']) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str+=ret + + return parse_str + + def temp_sensor_parse(self, dev, ops): + parse_str="" + ret=getattr(self, ops['cmd']+"_temp_sensor_device")(dev, ops ) + if not ret is None: + if str(ret).isdigit() : + if ret!=0: + # in case if 'create' functions + print "{}_temp_sensor_device failed".format(ops['cmd']) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str+=ret + + return parse_str + + def cpld_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_cpld_device")(dev, ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_cpld_device failed".format(ops['cmd']) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str+=ret + + return parse_str + + def cpldmux_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_cpldmux_device")(dev, ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_cpldmux_device() cmd failed".format(ops['cmd']) + return ret + else: + pass + else: + parse_str += ret + + for chan in dev['i2c']['channel']: + for device in chan['dev']: + ret = self.dev_parse(self.data[device], ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + return ret + else: + pass + else: + parse_str += ret + + return parse_str + + def cpldmux_parse_reverse(self, dev, ops): + parse_str = "" + for chan in reversed(dev['i2c']['channel']): + for device in reversed(chan['dev']): + ret = self.dev_parse(self.data[device], ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + return ret + else: + pass + else: + parse_str += ret + + ret = getattr(self, ops['cmd']+"_cpldmux_device")(dev, ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_cpldmux_device() cmd failed".format(ops['cmd']) + return ret + else: + pass + else: + parse_str += ret + + return parse_str + + + def sysstatus_parse(self, dev,ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_sysstatus_device")(dev, ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_sysstatus_device failed".format(ops['cmd']) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str+=ret + + return parse_str + + def gpio_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_gpio_device")(dev, ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_temp_sensor_device failed".format(ops['cmd']) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str += ret + + return parse_str + + + def mux_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_mux_device")(dev, ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_mux_device() cmd failed".format(ops['cmd']) + return ret + else: + pass + else: + parse_str += ret + + for ch in dev['i2c']['channel']: + ret = self.dev_parse(self.data[ch['dev']], ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + return ret + else: + pass + else: + parse_str += ret + return parse_str + + def mux_parse_reverse(self, dev, ops): + parse_str = "" + for ch in reversed(dev['i2c']['channel']): + ret = self.dev_parse(self.data[ch['dev']], ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + return ret + else: + pass + else: + parse_str += ret + + ret = getattr(self, ops['cmd']+"_mux_device")(dev, ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_mux_device() cmd failed".format(ops['cmd']) + return ret + else: + pass + else: + parse_str += ret + + return parse_str + + + def eeprom_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_eeprom_device")(dev, ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_eeprom_device() cmd failed".format(ops['cmd']) + return ret + else: + pass + else: + parse_str += ret + + return parse_str + + def optic_parse(self, dev, ops): + parse_str="" + ret="" + for ifce in dev['i2c']['interface']: + ret=getattr(self, ops['cmd']+"_xcvr_device")(self.data[ifce['dev']], ops ) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + print "{}_eeprom_device() cmd failed".format(ops['cmd']) + return ret + else: + pass + else: + parse_str+=ret + return parse_str + + def cpu_parse(self, bus, ops): + parse_str = "" + for dev in bus['i2c']['CONTROLLERS']: + dev1 = self.data[dev['dev']] + for d in dev1['i2c']['DEVICES']: + ret=self.dev_parse(self.data[d['dev']], ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + return ret + else: + pass + else: + parse_str += ret + return parse_str + + def cpu_parse_reverse(self, bus, ops): + parse_str = "" + for dev in reversed(bus['i2c']['CONTROLLERS']): + dev1 = self.data[dev['dev']] + for d in reversed(dev1['i2c']['DEVICES']): + ret=self.dev_parse(self.data[d['dev']], ops) + if not ret is None: + if str(ret).isdigit(): + if ret!=0: + # in case if 'create' functions + return ret + else: + pass + else: + parse_str += ret + return parse_str + + + def dev_parse(self, dev, ops): + attr=dev['dev_info'] + if attr['device_type'] == 'CPU': + if ops['cmd']=='delete': + return self.cpu_parse_reverse(dev, ops) + else: + return self.cpu_parse(dev, ops) + + if attr['device_type'] == 'EEPROM': + return self.eeprom_parse(dev, ops) + + if attr['device_type'] == 'MUX': + if ops['cmd']=='delete': + return self.mux_parse_reverse(dev, ops) + else: + return self.mux_parse(dev, ops) + + if attr['device_type'] == 'GPIO': + return self.gpio_parse(dev, ops) + + if attr['device_type'] == 'PSU': + return self.psu_parse(dev, ops) + + if attr['device_type'] == 'FAN': + return self.fan_parse(dev, ops) + + if attr['device_type'] == 'TEMP_SENSOR': + return self.temp_sensor_parse(dev, ops) + + if attr['device_type'] == 'SFP' or attr['device_type'] == 'SFP28' or \ + attr['device_type'] == 'QSFP' or attr['device_type'] == 'QSFP28': + return self.optic_parse(dev, ops) + + if attr['device_type'] == 'CPLD': + return self.cpld_parse(dev, ops) + + if attr['device_type'] == 'CPLDMUX': + if ops['cmd']=='delete': + return self.cpldmux_parse_reverse(dev, ops) + else: + return self.cpldmux_parse(dev, ops) + + if attr['device_type'] == 'SYSSTAT': + return self.sysstatus_parse(dev,ops) + + def is_supported_sysled_state(self, sysled_name, sysled_state): + if not sysled_name in self.data.keys(): + return False, "[FAILED] " + sysled_name + " is not configured" + for attr in self.data[sysled_name]['i2c']['attr_list']: + if attr['attr_name'] == sysled_state: + return True, "[PASS] supported" + return False, "[FAILED]: Invalid color" + + + def create_attr(self, key, value, path): + cmd = "echo '%s' > /sys/kernel/%s/%s"%(value, path, key) + self.runcmd(cmd) + + def create_led_platform_device(self, key, ops): + if ops['attr']=='all' or ops['attr']=='PLATFORM': + path='pddf/devices/platform' + self.create_attr('num_psus', self.data['PLATFORM']['num_psus'], path) + self.create_attr('num_fantrays', self.data['PLATFORM']['num_fantrays'], path) + + def create_led_device(self, key, ops): + if ops['attr']=='all' or ops['attr']==self.data[key]['dev_info']['device_name']: + path="pddf/devices/led" + for attr in self.data[key]['i2c']['attr_list']: + self.create_attr('device_name', self.data[key]['dev_info']['device_name'], path) + self.create_device(self.data[key]['dev_attr'], path, ops) + for attr_key in attr.keys(): + if (attr_key == 'swpld_addr_offset' or attr_key == 'swpld_addr'): + self.create_attr(attr_key, attr[attr_key], path) + elif (attr_key != 'attr_name' and attr_key != 'descr' and + attr_key != 'attr_devtype' and attr_key != 'attr_devname'): + state_path=path+'/state_attr' + self.create_attr(attr_key, attr[attr_key],state_path) + cmd="echo '" + attr['attr_name']+"' > /sys/kernel/pddf/devices/led/dev_ops" + self.runcmd(cmd) + + + + def led_parse(self, ops): + getattr(self, ops['cmd']+"_led_platform_device")("PLATFORM", ops) + for key in self.data.keys(): + if key != 'PLATFORM' and 'dev_info' in self.data[key]: + attr=self.data[key]['dev_info'] + if attr['device_type'] == 'LED': + getattr(self, ops['cmd']+"_led_device")(key, ops) + + + def get_device_list(self, list, type): + for key in self.data.keys(): + if key != 'PLATFORM' and 'dev_info' in self.data[key]: + attr=self.data[key]['dev_info'] + if attr['device_type'] == type: + list.append(self.data[key]) + + + def create_pddf_devices(self): + self.led_parse({ "cmd": "create", "target":"all", "attr":"all" }) + create_ret = 0 + create_ret = self.dev_parse(self.data['SYSTEM'], { "cmd": "create", "target":"all", "attr":"all" } ) + if create_ret!=0: + return create_ret + if 'SYSSTATUS' in self.data: + create_ret = self.dev_parse(self.data['SYSSTATUS'], { "cmd": "create", "target":"all", "attr":"all" } ) + if create_ret!=0: + return create_ret + + def delete_pddf_devices(self): + self.dev_parse(self.data['SYSTEM'], { "cmd": "delete", "target":"all", "attr":"all" } ) + if 'SYSSTATUS' in self.data: + self.dev_parse(self.data['SYSSTATUS'], { "cmd": "delete", "target":"all", "attr":"all" } ) + + def populate_pddf_sysfsobj(self): + self.dev_parse(self.data['SYSTEM'], { "cmd": "show", "target":"all", "attr":"all" } ) + if 'SYSSTATUS' in self.data: + self.dev_parse(self.data['SYSSTATUS'], { "cmd": "show", "target":"all", "attr":"all" } ) + self.led_parse({ "cmd": "show", "target":"all", "attr":"all" }) + self.show_client_device() + + def cli_dump_dsysfs(self, component): + self.dev_parse(self.data['SYSTEM'], { "cmd": "show_attr", "target":"all", "attr":"all" } ) + if 'SYSSTATUS' in self.data: + self.dev_parse(self.data['SYSSTATUS'], { "cmd": "show_attr", "target":"all", "attr":"all" } ) + if component in self.data_sysfs_obj: + return self.data_sysfs_obj[component] + else: + return None + + + def validate_pddf_devices(self, *args): + self.populate_pddf_sysfsobj() + v_ops = { 'cmd': 'validate', 'target':'all', 'attr':'all' } + self.dev_parse(self.data['SYSTEM'], v_ops ) + + ################################################################################################################## + # BMC APIs + ################################################################################################################## + def populate_bmc_cache_db(self, bmc_attr): + bmc_cmd = str(bmc_attr['bmc_cmd']).strip() + + if 'delimiter' in bmc_attr.keys(): + delim = str(bmc_attr['delimiter']).strip() + else: + delim = None + + o_list = subprocess.check_output(bmc_cmd, shell=True).strip().split('\n') + bmc_cache[bmc_cmd]={} + bmc_cache[bmc_cmd]['time']=time.time() + for entry in o_list: + name = entry.split(delim)[0].strip() + bmc_cache[bmc_cmd][name]=entry + + def non_raw_ipmi_get_request(self, bmc_attr): + bmc_db_update_time=1 + value = 'N/A' + bmc_cmd = str(bmc_attr['bmc_cmd']).strip() + field_name = str(bmc_attr['field_name']).strip() + field_pos= int(bmc_attr['field_pos'])-1 + + if 'delimiter' in bmc_attr.keys(): + delim = str(bmc_attr['delimiter']).strip() + else: + delim = None + + if not bmc_cmd in bmc_cache: + self.populate_bmc_cache_db(bmc_attr) + else: + now = time.time() + if (int(now - bmc_cache[bmc_cmd]['time']) > bmc_db_update_time): + self.populate_bmc_cache_db(bmc_attr) + + try: + data=bmc_cache[bmc_cmd][field_name] + value = data.split(delim)[field_pos].strip() + except Exception as e: + pass + + if 'mult' in bmc_attr.keys() and not value.isalpha(): + if value.isalpha(): + value = 0.0 + value = float(value) * float(bmc_attr['mult']) + + return str(value) + + def raw_ipmi_get_request(self, bmc_attr): + value = 'N/A' + cmd = bmc_attr['bmc_cmd'] + " 2>/dev/null" + if bmc_attr['type'] == 'raw': + try: + value = subprocess.check_output(cmd, shell=True).strip() + except Exception as e: + pass + + if value != 'N/A': + value = str(int(value, 16)) + return value + + if bmc_attr['type'] == 'mask': + mask = int(bmc_attr['mask'].encode('utf-8'), 16) + try: + value = subprocess.check_output(cmd, shell=True).strip() + except Exception as e: + pass + + # value should either be '1' or '0' + if value != 'N/A': + value = '1' if bool(int(value, 16) & mask) else '0' + + return value + + if bmc_attr['type'] == 'ascii': + try: + value = subprocess.check_output(cmd, shell=True) + except Exception as e: + pass + + if value != 'N/A': + tmp = ''.join(chr(int(i, 16)) for i in value.split()) + tmp = "".join(i for i in unicode(tmp) if unicodedata.category(i)[0]!="C") + value = str(tmp) + + return (value) + + return value + + def bmc_get_cmd(self, bmc_attr): + if int(bmc_attr['raw']) == 1: + value = self.raw_ipmi_get_request(bmc_attr) + else: + value = self.non_raw_ipmi_get_request(bmc_attr) + return (value) + + def non_raw_ipmi_set_request(self, bmc_attr, val): + value = 'N/A' + # TODO: Implement it + return value + + def raw_ipmi_set_request(self, bmc_attr, val): + value = 'N/A' + # TODO: Implement this + return value + + def bmc_set_cmd(self, bmc_attr, val): + if int(bmc_attr['raw']) == 1: + value = self.raw_ipmi_set_request(bmc_attr, val) + else: + value = self.non_raw_ipmi_set_request(bmc_attr, val) + return (value) + + # bmc-based attr: return attr obj + # non-bmc-based attr: return empty obj + def check_bmc_based_attr(self, device_name, attr_name): + if device_name in self.data.keys(): + if "bmc" in self.data[device_name].keys() and 'ipmitool' in self.data[device_name]['bmc'].keys(): + attr_list = self.data[device_name]['bmc']['ipmitool']['attr_list'] + for attr in attr_list: + if attr['attr_name'].strip() == attr_name.strip(): + return attr + # Required attr_name is not supported in BMC object + return {} + return None + + def get_attr_name_output(self, device_name, attr_name): + bmc_attr = self.check_bmc_based_attr(device_name, attr_name) + output={"mode":"", "status":""} + + if bmc_attr is not None: + if bmc_attr=={}: + return {} + output['mode']="bmc" + output['status']=self.bmc_get_cmd(bmc_attr) + else: + output['mode']="i2c" + node = self.get_path(device_name, attr_name) + if node is None: + return {} + try: + with open(node, 'r') as f: + output['status'] = f.read() + except IOError: + return {} + return output + + def set_attr_name_output(self, device_name, attr_name, val): + bmc_attr = self.check_bmc_based_attr(device_name, attr_name) + output={"mode":"", "status":""} + + if bmc_attr is not None: + if bmc_attr=={}: + return {} + output['mode']="bmc" + output['status']=False # No set operation allowed for BMC attributes as they are handled by BMC itself + else: + output['mode']="i2c" + node = self.get_path(device_name, attr_name) + if node is None: + return {} + try: + with open(node, 'w') as f: + f.write(str(val)) + except IOError: + return {} + + output['status'] = True + + return output + + ################################################################################################################### + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--create", action='store_true', help="create the I2C topology") + parser.add_argument("--sysfs", action='store', nargs="+", help="show access-attributes sysfs for the I2C topology") + parser.add_argument("--dsysfs", action='store', nargs="+", help="show data-attributes sysfs for the I2C topology") + parser.add_argument("--delete", action='store_true', help="Remove all the created I2C clients from topology") + parser.add_argument("--validate", action='store', help="Validate the device specific attribute data elements") + parser.add_argument("--schema", action='store', nargs="+", help="Schema Validation") + parser.add_argument("--modules", action='store', nargs="+", help="Loaded modules validation") + + args = parser.parse_args() + + # Create the object + try: + pddf_obj = PddfParse() + except Exception as e: + print "%s" % str(e) + sys.exit() + + if args.create: + pddf_obj.create_pddf_devices() + + if args.sysfs: + if args.sysfs[0] == 'all': + pddf_obj.populate_pddf_sysfsobj() + if args.sysfs[0] == 'print': + pddf_obj.populate_pddf_sysfsobj() + pddf_obj.dump_sysfs_obj(pddf_obj.sysfs_obj, args.sysfs[1]) + if args.sysfs[0] == 'validate': + pddf_obj.populate_pddf_sysfsobj() + pddf_obj.validate_sysfs_creation(pddf_obj.sysfs_obj, args.sysfs[1]) + if args.sysfs[0] == 'verify': + pddf_obj.verify_sysfs_data(args.sysfs[1]) + + + if args.dsysfs: + if args.dsysfs[0] == 'validate': + pddf_obj.dev_parse(pddf_obj.data['SYSTEM'], { "cmd": "show_attr", "target":"all", "attr":"all" } ) + if 'SYSSTATUS' in pddf_obj.data: + pddf_obj.dev_parse(pddf_obj.data['SYSSTATUS'], { "cmd": "show_attr", "target":"all", "attr":"all" } ) + pddf_obj.validate_dsysfs_creation(pddf_obj.data_sysfs_obj, args.dsysfs[1]) + + elif args.dsysfs[0] == 'print': + pddf_obj.dev_parse(pddf_obj.data['SYSTEM'], { "cmd": "show_attr", "target":"all", "attr":"all" } ) + if 'SYSSTATUS' in pddf_obj.data: + pddf_obj.dev_parse(pddf_obj.data['SYSSTATUS'], { "cmd": "show_attr", "target":"all", "attr":"all" } ) + pddf_obj.dump_sysfs_obj(pddf_obj.data_sysfs_obj, args.dsysfs[1]) + + elif args.dsysfs[0] == 'all': + ret = pddf_obj.dev_parse(pddf_obj.data['SYSTEM'], { "cmd": "show_attr", "target":"all", "attr":"all" } ) + if 'SYSSTATUS' in pddf_obj.data: + ret += pddf_obj.dev_parse(pddf_obj.data['SYSSTATUS'], { "cmd": "show_attr", "target":"all", + "attr":"all" } ) + pddf_obj.dump_sysfs_obj(pddf_obj.data_sysfs_obj, 'all') + else: + pddf_obj.dev_parse(pddf_obj.data[args.dsysfs[0]], { "cmd": "show_attr", "target":args.dsysfs[0], + "attr":args.dsysfs[1] }) + + if args.delete: + pddf_obj.delete_pddf_devices() + + if args.validate: + if args.validate[0] == 'all': + pddf_obj.validate_pddf_devices(args.validate[1:]) + else: + pass + + if args.schema: + pddf_obj.schema_validation(args.schema[0]) + + if args.modules: + pddf_obj.modules_validation(args.modules[0]) + + + +if __name__ == "__main__" : + main() diff --git a/platform/pddf/i2c/utils/schema/CPLD.schema b/platform/pddf/i2c/utils/schema/CPLD.schema new file mode 100644 index 000000000000..c2f8c0de842f --- /dev/null +++ b/platform/pddf/i2c/utils/schema/CPLD.schema @@ -0,0 +1,67 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "CPLD": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + }, + "device_parent": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_name", + "device_parent" + ] + }, + "i2c": { + "type": "object", + "properties": { + "topo_info": { + "type": "object", + "properties": { + "parent_bus": { + "type": "string" + }, + "dev_addr": { + "type": "string" + }, + "dev_type": { + "type": "string" + } + }, + "required": [ + "parent_bus", + "dev_addr", + "dev_type" + ] + }, + "dev_attr": { + "type": "object" + } + }, + "required": [ + "topo_info" + ] + } + }, + "required": [ + "dev_info", + "i2c" + ] + } + }, + "required": [ + "CPLD" + ] +} diff --git a/platform/pddf/i2c/utils/schema/CPU.schema b/platform/pddf/i2c/utils/schema/CPU.schema new file mode 100644 index 000000000000..9bb07ae0f6bb --- /dev/null +++ b/platform/pddf/i2c/utils/schema/CPU.schema @@ -0,0 +1,80 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "CPU": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + }, + "device_parent": { + "type": "null" + } + }, + "required": [ + "device_type", + "device_name", + "device_parent" + ] + }, + "i2c": { + "type": "object", + "properties": { + "CONTROLLERS": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "dev_name": { + "type": "string" + }, + "dev": { + "type": "string" + } + }, + "required": [ + "dev_name", + "dev" + ] + }, + { + "type": "object", + "properties": { + "dev_name": { + "type": "string" + }, + "dev": { + "type": "string" + } + }, + "required": [ + "dev_name", + "dev" + ] + } + ] + } + }, + "required": [ + "CONTROLLERS" + ] + } + }, + "required": [ + "dev_info", + "i2c" + ] + } + }, + "required": [ + "CPU" + ] +} diff --git a/platform/pddf/i2c/utils/schema/EEPROM.schema b/platform/pddf/i2c/utils/schema/EEPROM.schema new file mode 100644 index 000000000000..a8e8885e3ad1 --- /dev/null +++ b/platform/pddf/i2c/utils/schema/EEPROM.schema @@ -0,0 +1,93 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "EEPROM": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + }, + "device_parent": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_name", + "device_parent" + ] + }, + "i2c": { + "type": "object", + "properties": { + "topo_info": { + "type": "object", + "properties": { + "parent_bus": { + "type": "string" + }, + "dev_addr": { + "type": "string" + }, + "dev_type": { + "type": "string" + } + }, + "required": [ + "parent_bus", + "dev_addr", + "dev_type" + ] + }, + "dev_attr": { + "type": "object", + "properties": { + "access_mode": { + "type": "string" + } + }, + "required": [ + "access_mode" + ] + }, + "attr_list": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + } + }, + "required": [ + "attr_name" + ] + } + ] + } + }, + "required": [ + "topo_info", + "dev_attr", + "attr_list" + ] + } + }, + "required": [ + "dev_info", + "i2c" + ] + } + }, + "required": [ + "EEPROM" + ] +} diff --git a/platform/pddf/i2c/utils/schema/FAN.schema b/platform/pddf/i2c/utils/schema/FAN.schema new file mode 100644 index 000000000000..069007533130 --- /dev/null +++ b/platform/pddf/i2c/utils/schema/FAN.schema @@ -0,0 +1,113 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "FAN": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + }, + "device_parent": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_name", + "device_parent" + ] + }, + "i2c": { + "type": "object", + "properties": { + "topo_info": { + "type": "object", + "properties": { + "parent_bus": { + "type": "string" + }, + "dev_addr": { + "type": "string" + }, + "dev_type": { + "type": "string" + } + }, + "required": [ + "parent_bus", + "dev_addr", + "dev_type" + ] + }, + "dev_attr": { + "type": "object", + "properties": { + "num_fantrays": { + "type": "string" + } + }, + "required": [ + "num_fantrays" + ] + }, + "attr_list": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devtype": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_cmpval": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devtype", + "attr_offset", + "attr_mask", + "attr_cmpval", + "attr_len" + ] + } + ] + } + }, + "required": [ + "topo_info", + "dev_attr", + "attr_list" + ] + } + }, + "required": [ + "dev_info", + "i2c" + ] + } + }, + "required": [ + "FAN" + ] +} diff --git a/platform/pddf/i2c/utils/schema/FAN_BMC.schema b/platform/pddf/i2c/utils/schema/FAN_BMC.schema new file mode 100644 index 000000000000..41d774dfa6bd --- /dev/null +++ b/platform/pddf/i2c/utils/schema/FAN_BMC.schema @@ -0,0 +1,69 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "FAN": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + } + }, + "required": [ + "device_type" + ] + }, + "bmc": { + "type": "object", + "properties": { + "ipmitool": { + "type": "object", + "properties": { + "attr_list": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw" + ] + } + ] + } + }, + "required": [ + "attr_list" + ] + } + }, + "required": [ + "ipmitool" + ] + } + }, + "required": [ + "dev_info", + "bmc" + ] + } + }, + "required": [ + "FAN" + ] +} diff --git a/platform/pddf/i2c/utils/schema/LED.schema b/platform/pddf/i2c/utils/schema/LED.schema new file mode 100644 index 000000000000..04583ee660aa --- /dev/null +++ b/platform/pddf/i2c/utils/schema/LED.schema @@ -0,0 +1,120 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "LED": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_name" + ] + }, + "dev_attr": { + "type": "object", + "properties": { + "index": { + "type": "string" + } + }, + "required": [ + "index" + ] + }, + "i2c": { + "type": "object", + "properties": { + "attr_list": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bits": { + "type": "string" + }, + "color": { + "type": "string" + }, + "value": { + "type": "string" + }, + "swpld_addr": { + "type": "string" + }, + "swpld_addr_offset": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bits", + "color", + "value", + "swpld_addr", + "swpld_addr_offset" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bits": { + "type": "string" + }, + "color": { + "type": "string" + }, + "value": { + "type": "string" + }, + "swpld_addr": { + "type": "string" + }, + "swpld_addr_offset": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bits", + "color", + "value", + "swpld_addr", + "swpld_addr_offset" + ] + } + ] + } + }, + "required": [ + "attr_list" + ] + } + }, + "required": [ + "dev_info", + "dev_attr", + "i2c" + ] + } + }, + "required": [ + "LED" + ] +} diff --git a/platform/pddf/i2c/utils/schema/MUX.schema b/platform/pddf/i2c/utils/schema/MUX.schema new file mode 100644 index 000000000000..6ef46e8dd2a9 --- /dev/null +++ b/platform/pddf/i2c/utils/schema/MUX.schema @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "MUX": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + }, + "device_parent": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_name", + "device_parent" + ] + }, + "i2c": { + "type": "object", + "properties": { + "topo_info": { + "type": "object", + "properties": { + "parent_bus": { + "type": "string" + }, + "dev_addr": { + "type": "string" + }, + "dev_type": { + "type": "string" + } + }, + "required": [ + "parent_bus", + "dev_addr", + "dev_type" + ] + }, + "dev_attr": { + "type": "object", + "properties": { + "virt_bus": { + "type": "string" + } + }, + "required": [ + "virt_bus" + ] + }, + "channel": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "chn": { + "type": "string" + }, + "dev": { + "type": "string" + } + }, + "required": [ + "chn", + "dev" + ] + } + ] + } + }, + "required": [ + "topo_info", + "dev_attr", + "channel" + ] + } + }, + "required": [ + "dev_info", + "i2c" + ] + } + }, + "required": [ + "MUX" + ] +} diff --git a/platform/pddf/i2c/utils/schema/PSU-PMBUS.schema b/platform/pddf/i2c/utils/schema/PSU-PMBUS.schema new file mode 100644 index 000000000000..6516d2321371 --- /dev/null +++ b/platform/pddf/i2c/utils/schema/PSU-PMBUS.schema @@ -0,0 +1,109 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "PSU-PMBUS": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + }, + "device_parent": { + "type": "string" + }, + "virt_parent": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_name", + "device_parent", + "virt_parent" + ] + }, + "i2c": { + "type": "object", + "properties": { + "topo_info": { + "type": "object", + "properties": { + "parent_bus": { + "type": "string" + }, + "dev_addr": { + "type": "string" + }, + "dev_type": { + "type": "string" + } + }, + "required": [ + "parent_bus", + "dev_addr", + "dev_type" + ] + }, + "attr_list": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devaddr": { + "type": "string" + }, + "attr_devtype": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_cmpval": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devaddr", + "attr_devtype", + "attr_offset", + "attr_mask", + "attr_cmpval", + "attr_len" + ] + } + ] + } + }, + "required": [ + "topo_info", + "attr_list" + ] + } + }, + "required": [ + "dev_info", + "i2c" + ] + } + }, + "required": [ + "PSU-PMBUS" + ] +} diff --git a/platform/pddf/i2c/utils/schema/PSU.schema b/platform/pddf/i2c/utils/schema/PSU.schema new file mode 100644 index 000000000000..5ed53df4572f --- /dev/null +++ b/platform/pddf/i2c/utils/schema/PSU.schema @@ -0,0 +1,81 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "PSU": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + }, + "device_parent": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_name", + "device_parent" + ] + }, + "dev_attr": { + "type": "object", + "properties": { + "dev_idx": { + "type": "string" + }, + "num_psu_fans": { + "type": "string" + } + }, + "required": [ + "dev_idx", + "num_psu_fans" + ] + }, + "i2c": { + "type": "object", + "properties": { + "interface": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "itf": { + "type": "string" + }, + "dev": { + "type": "string" + } + }, + "required": [ + "itf", + "dev" + ] + } + ] + } + }, + "required": [ + "interface" + ] + } + }, + "required": [ + "dev_info", + "dev_attr", + "i2c" + ] + } + }, + "required": [ + "PSU" + ] +} diff --git a/platform/pddf/i2c/utils/schema/PSU_BMC.schema b/platform/pddf/i2c/utils/schema/PSU_BMC.schema new file mode 100644 index 000000000000..299e79dd7854 --- /dev/null +++ b/platform/pddf/i2c/utils/schema/PSU_BMC.schema @@ -0,0 +1,336 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "PSU": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + } + }, + "required": [ + "device_type" + ] + }, + "dev_attr": { + "type": "object", + "properties": { + "dev_idx": { + "type": "string" + }, + "num_psu_fans": { + "type": "string" + } + }, + "required": [ + "dev_idx", + "num_psu_fans" + ] + }, + "bmc": { + "type": "object", + "properties": { + "ipmitool": { + "type": "object", + "properties": { + "attr_list": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "field_name": { + "type": "string" + }, + "field_pos": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "field_name", + "field_pos" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "type": { + "type": "string" + }, + "mask": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "type", + "mask" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "type" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "type" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "type" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "type" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "field_name": { + "type": "string" + }, + "field_pos": { + "type": "string" + }, + "mult": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "field_name", + "field_pos", + "mult" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "field_name": { + "type": "string" + }, + "field_pos": { + "type": "string" + }, + "mult": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "field_name", + "field_pos", + "mult" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "field_name": { + "type": "string" + }, + "field_pos": { + "type": "string" + }, + "mult": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "field_name", + "field_pos", + "mult" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "field_name": { + "type": "string" + }, + "field_pos": { + "type": "string" + }, + "mult": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "field_name", + "field_pos", + "mult" + ] + } + ] + } + }, + "required": [ + "attr_list" + ] + } + }, + "required": [ + "ipmitool" + ] + } + }, + "required": [ + "dev_info", + "dev_attr", + "bmc" + ] + } + }, + "required": [ + "PSU" + ] +} diff --git a/platform/pddf/i2c/utils/schema/QSFP.schema b/platform/pddf/i2c/utils/schema/QSFP.schema new file mode 100644 index 000000000000..be8e75a9cd1f --- /dev/null +++ b/platform/pddf/i2c/utils/schema/QSFP.schema @@ -0,0 +1,92 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "QSFP": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + }, + "device_parent": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_name", + "device_parent" + ] + }, + "dev_attr": { + "type": "object", + "properties": { + "dev_idx": { + "type": "string" + } + }, + "required": [ + "dev_idx" + ] + }, + "i2c": { + "type": "object", + "properties": { + "interface": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "itf": { + "type": "string" + }, + "dev": { + "type": "string" + } + }, + "required": [ + "itf", + "dev" + ] + }, + { + "type": "object", + "properties": { + "itf": { + "type": "string" + }, + "dev": { + "type": "string" + } + }, + "required": [ + "itf", + "dev" + ] + } + ] + } + }, + "required": [ + "interface" + ] + } + }, + "required": [ + "dev_info", + "dev_attr", + "i2c" + ] + } + }, + "required": [ + "QSFP" + ] +} diff --git a/platform/pddf/i2c/utils/schema/SMBUS.schema b/platform/pddf/i2c/utils/schema/SMBUS.schema new file mode 100644 index 000000000000..91429a1d7ee8 --- /dev/null +++ b/platform/pddf/i2c/utils/schema/SMBUS.schema @@ -0,0 +1,128 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "SMBUS": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + }, + "device_parent": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_name", + "device_parent" + ] + }, + "i2c": { + "type": "object", + "properties": { + "topo_info": { + "type": "object", + "properties": { + "dev_addr": { + "type": "string" + } + }, + "required": [ + "dev_addr" + ] + }, + "DEVICES": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "dev": { + "type": "string" + } + }, + "required": [ + "dev" + ] + }, + { + "type": "object", + "properties": { + "dev": { + "type": "string" + } + }, + "required": [ + "dev" + ] + }, + { + "type": "object", + "properties": { + "dev": { + "type": "string" + } + }, + "required": [ + "dev" + ] + }, + { + "type": "object", + "properties": { + "dev": { + "type": "string" + } + }, + "required": [ + "dev" + ] + }, + { + "type": "object", + "properties": { + "dev": { + "type": "string" + } + }, + "required": [ + "dev" + ] + }, + { + "type": "object", + "properties": { + "dev": { + "type": "string" + } + }, + "required": [ + "dev" + ] + } + ] + } + }, + "required": [ + "topo_info", + "DEVICES" + ] + } + }, + "required": [ + "dev_info", + "i2c" + ] + } + }, + "required": [ + "SMBUS" + ] +} diff --git a/platform/pddf/i2c/utils/schema/SYSSTAT.schema b/platform/pddf/i2c/utils/schema/SYSSTAT.schema new file mode 100644 index 000000000000..d31e10c27222 --- /dev/null +++ b/platform/pddf/i2c/utils/schema/SYSSTAT.schema @@ -0,0 +1,285 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "SYSSTAT": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_name" + ] + }, + "dev_attr": { + "type": "object" + }, + "attr_list": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devaddr": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devaddr", + "attr_offset", + "attr_mask", + "attr_len" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devaddr": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devaddr", + "attr_offset", + "attr_mask", + "attr_len" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devaddr": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devaddr", + "attr_offset", + "attr_mask", + "attr_len" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devaddr": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devaddr", + "attr_offset", + "attr_mask", + "attr_len" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devaddr": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devaddr", + "attr_offset", + "attr_mask", + "attr_len" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devaddr": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devaddr", + "attr_offset", + "attr_mask", + "attr_len" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devaddr": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devaddr", + "attr_offset", + "attr_mask", + "attr_len" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devaddr": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devaddr", + "attr_offset", + "attr_mask", + "attr_len" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "attr_devaddr": { + "type": "string" + }, + "attr_offset": { + "type": "string" + }, + "attr_mask": { + "type": "string" + }, + "attr_len": { + "type": "string" + } + }, + "required": [ + "attr_name", + "attr_devaddr", + "attr_offset", + "attr_mask", + "attr_len" + ] + } + ] + } + }, + "required": [ + "dev_info", + "dev_attr", + "attr_list" + ] + } + }, + "required": [ + "SYSSTAT" + ] +} diff --git a/platform/pddf/i2c/utils/schema/TEMP_SENSOR.schema b/platform/pddf/i2c/utils/schema/TEMP_SENSOR.schema new file mode 100644 index 000000000000..0bc2ce8b8303 --- /dev/null +++ b/platform/pddf/i2c/utils/schema/TEMP_SENSOR.schema @@ -0,0 +1,102 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "TEMP_SENSOR": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + }, + "device_name": { + "type": "string" + }, + "device_parent": { + "type": "string" + } + }, + "required": [ + "device_type", + "device_parent" + ] + }, + "i2c": { + "type": "object", + "properties": { + "topo_info": { + "type": "object", + "properties": { + "parent_bus": { + "type": "string" + }, + "dev_addr": { + "type": "string" + }, + "dev_type": { + "type": "string" + } + }, + "required": [ + "parent_bus", + "dev_addr", + "dev_type" + ] + }, + "attr_list": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + } + }, + "required": [ + "attr_name" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + } + }, + "required": [ + "attr_name" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + } + }, + "required": [ + "attr_name" + ] + } + ] + } + }, + "required": [ + "topo_info", + "attr_list" + ] + } + }, + "required": [ + "dev_info", + "i2c" + ] + } + }, + "required": [ + "TEMP_SENSOR" + ] +} diff --git a/platform/pddf/i2c/utils/schema/TEMP_SENSOR_BMC.schema b/platform/pddf/i2c/utils/schema/TEMP_SENSOR_BMC.schema new file mode 100644 index 000000000000..c8f7c447b718 --- /dev/null +++ b/platform/pddf/i2c/utils/schema/TEMP_SENSOR_BMC.schema @@ -0,0 +1,143 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "TEMP_SENSOR": { + "type": "object", + "properties": { + "dev_info": { + "type": "object", + "properties": { + "device_type": { + "type": "string" + } + }, + "required": [ + "device_type" + ] + }, + "dev_attr": { + "type": "object", + "properties": { + "display_name": { + "type": "string" + } + }, + "required": [ + "display_name" + ] + }, + "bmc": { + "type": "object", + "properties": { + "ipmitool": { + "type": "object", + "properties": { + "attr_list": { + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "field_name": { + "type": "string" + }, + "field_pos": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "field_name", + "field_pos" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "field_name": { + "type": "string" + }, + "field_pos": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "field_name", + "field_pos" + ] + }, + { + "type": "object", + "properties": { + "attr_name": { + "type": "string" + }, + "bmc_cmd": { + "type": "string" + }, + "raw": { + "type": "string" + }, + "field_name": { + "type": "string" + }, + "field_pos": { + "type": "string" + } + }, + "required": [ + "attr_name", + "bmc_cmd", + "raw", + "field_name", + "field_pos" + ] + } + ] + } + }, + "required": [ + "attr_list" + ] + } + }, + "required": [ + "ipmitool" + ] + } + }, + "required": [ + "dev_info", + "dev_attr", + "bmc" + ] + } + }, + "required": [ + "TEMP_SENSOR" + ] +} diff --git a/platform/pddf/platform-api-pddf-base.dep b/platform/pddf/platform-api-pddf-base.dep new file mode 100644 index 000000000000..aaaedb068384 --- /dev/null +++ b/platform/pddf/platform-api-pddf-base.dep @@ -0,0 +1,13 @@ + +MPATH := $($(PDDF_PLATFORM_API_BASE_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/pddf/platform-api-pddf-base.mk platform/pddf/platform-api-pddf-base.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(PDDF_PLATFORM_API_BASE_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(PDDF_PLATFORM_API_BASE_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(PDDF_PLATFORM_API_BASE_PY2)_DEP_FILES := $(DEP_FILES) + +$(PDDF_PLATFORM_API_BASE_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(PDDF_PLATFORM_API_BASE_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(PDDF_PLATFORM_API_BASE_PY3)_DEP_FILES := $(DEP_FILES) diff --git a/platform/pddf/platform-api-pddf-base.mk b/platform/pddf/platform-api-pddf-base.mk new file mode 100644 index 000000000000..ce818707ba7e --- /dev/null +++ b/platform/pddf/platform-api-pddf-base.mk @@ -0,0 +1,28 @@ +#################################################### +# PDDF Generic 2.0 Platform API base classes +#################################################### +PDDF_PLATFORM_API_BASE_VERSION = 1.0 + +export PDDF_PLATFORM_API_BASE_VERSION + +PDDF_PLATFORM_API_BASE_PY2 = sonic_platform_pddf_common-$(PDDF_PLATFORM_API_BASE_VERSION)-py2-none-any.whl +$(PDDF_PLATFORM_API_BASE_PY2)_SRC_PATH = $(PLATFORM_PDDF_PATH)/platform-api-pddf-base +$(PDDF_PLATFORM_API_BASE_PY2)_PYTHON_VERSION = 2 +$(PDDF_PLATFORM_API_BASE_PY2)_DEPENDS = $(SONIC_CONFIG_ENGINE) +SONIC_PYTHON_WHEELS += $(PDDF_PLATFORM_API_BASE_PY2) + +export pddf_platform_api_base_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(PDDF_PLATFORM_API_BASE_PY2))" +export PDDF_PLATFORM_API_BASE_PY2 + +PDDF_PLATFORM_API_BASE_PY3 = sonic_platform_pddf_common-$(PDDF_PLATFORM_API_BASE_VERSION)-py3-none-any.whl +$(PDDF_PLATFORM_API_BASE_PY3)_SRC_PATH = $(PLATFORM_PDDF_PATH)/platform-api-pddf-base +$(PDDF_PLATFORM_API_BASE_PY3)_PYTHON_VERSION = 3 +$(PDDF_PLATFORM_API_BASE_PY3)_DEPENDS = $(SONIC_CONFIG_ENGINE) +# Synthetic dependency to avoid building the Python 2 and 3 packages +# simultaneously and any potential conflicts which may arise +$(PDDF_PLATFORM_API_BASE_PY3)_DEPENDS += $(PDDF_PLATFORM_API_BASE_PY2) +$(PDDF_PLATFORM_API_BASE_PY3)_TEST = n +SONIC_PYTHON_WHEELS += $(PDDF_PLATFORM_API_BASE_PY3) + +export pddf_platform_api_base_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(PDDF_PLATFORM_API_BASE_PY3))" +export PDDF_PLATFORM_API_BASE_PY3 diff --git a/platform/pddf/platform-api-pddf-base/setup.py b/platform/pddf/platform-api-pddf-base/setup.py new file mode 100755 index 000000000000..0d8b4a6b2df2 --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/setup.py @@ -0,0 +1,34 @@ + +from setuptools import setup + +setup( + name='sonic-platform-pddf-common', + version='1.0', + description='SONIC platform APIs base (2.0) implementation on PDDF supported platforms', + license='Apache 2.0', + author='SONiC Team', + author_email='linuxnetdev@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + maintainer='Fuzail Khan', + maintainer_email='fuzail.khan@broadcom.com', + packages=[ + 'sonic_platform_pddf_base', + ], + install_requires=[ + 'jsonschema==2.6.0' + ], + 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', + 'Programming Language :: Python :: 3.7', + 'Topic :: Utilities', + ], + keywords='sonic SONiC platform PLATFORM', +) diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/__init__.py b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_chassis.py b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_chassis.py new file mode 100755 index 000000000000..0e77a90dbab1 --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_chassis.py @@ -0,0 +1,512 @@ +#!/usr/bin/env python + +############################################################################# +# PDDF +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import sys + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.psu import Psu + from sonic_platform.fan import Fan + from sonic_platform.thermal import Thermal + from sonic_platform.eeprom import Eeprom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PddfChassis(ChassisBase): + """ + PDDF Generic Chassis class + """ + pddf_obj = {} + plugin_data = {} + + def __init__(self, pddf_data=None, pddf_plugin_data=None): + + ChassisBase.__init__(self) + + self.pddf_obj = pddf_data if pddf_data else None + self.plugin_data = pddf_plugin_data if pddf_plugin_data else None + if not self.pddf_obj or not self.plugin_data: + try: + from . import pddfparse + import json + self.pddf_obj = pddfparse.PddfParse() + with open('/usr/share/sonic/platform/pddf/pd-plugin.json') as pd: + self.plugin_data = json.load(pd) + except Exception as e: + raise Exception("Error: Unable to load PDDF JSON data - %s" % str(e)) + + self.platform_inventory = self.pddf_obj.get_platform() + + # Initialize EEPROM + self.sys_eeprom = Eeprom(self.pddf_obj, self.plugin_data) + + # FANs + for i in range(self.platform_inventory['num_fantrays']): + for j in range(self.platform_inventory['num_fans_pertray']): + fan = Fan(i, j, self.pddf_obj, self.plugin_data) + self._fan_list.append(fan) + + # PSUs + for i in range(self.platform_inventory['num_psus']): + psu = Psu(i, self.pddf_obj, self.plugin_data) + self._psu_list.append(psu) + + # OPTICs + for index in range(self.platform_inventory['num_ports']): + sfp = Sfp(index, self.pddf_obj, self.plugin_data) + self._sfp_list.append(sfp) + + # THERMALs + for i in range(self.platform_inventory['num_temps']): + thermal = Thermal(i, self.pddf_obj, self.plugin_data) + self._thermal_list.append(thermal) + + # SYSTEM LED Test Cases + """ + #comment out test cases + sys_led_list= { "LOC":0, + "DIAG":0, + "FAN":0, + "SYS":0, + "PSU1":0, + "PSU2":1 + } + + for led in sys_led_list: + color=self.get_system_led(led, sys_led_list[led]) + print color + + self.set_system_led("LOC_LED","STATUS_LED_COLOR_GREEN") + color=self.get_system_led("LOC_LED") + print "Set Green: " + color + self.set_system_led("LOC_LED", "STATUS_LED_COLOR_OFF") + color=self.get_system_led("LOC_LED") + print "Set off: " + color + """ + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self.sys_eeprom.modelstr() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self.sys_eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self.sys_eeprom.serial_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self.sys_eeprom.base_mac_addr() + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + + Returns: + A string containing the hardware serial number for this + chassis. + """ + return self.sys_eeprom.serial_number_str() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self.sys_eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + raise NotImplementedError + + def get_component_name_list(self): + """ + Retrieves a list of the names of components available on the chassis (e.g., BIOS, CPLD, FPGA, etc.) + + Returns: + A list containing the names of components available on the chassis + """ + return self._component_name_list + + def get_firmware_version(self, component_name): + """ + Retrieves platform-specific hardware/firmware versions for chassis + componenets such as BIOS, CPLD, FPGA, etc. + Args: + component_name: A string, the component name. + + Returns: + A string containing platform-specific component versions + """ + raise NotImplementedError + + def install_component_firmware(self, component_name, image_path): + """ + Install firmware to component + Args: + component_name: A string, the component name. + image_path: A string, path to firmware image. + + Returns: + A boolean, True if install was successful, False if not + """ + raise NotImplementedError + + ############################################## + # Module methods + ############################################## + + def get_num_modules(self): + """ + Retrieves the number of modules available on this chassis + + Returns: + An integer, the number of modules available on this chassis + """ + return len(self._module_list) + + def get_all_modules(self): + """ + Retrieves all modules available on this chassis + + Returns: + A list of objects derived from ModuleBase representing all + modules available on this chassis + """ + return self._module_list + + def get_module(self, index): + """ + Retrieves module represented by (0-based) index + + Args: + index: An integer, the index (0-based) of the module to + retrieve + + Returns: + An object dervied from ModuleBase representing the specified + module + """ + module = None + + try: + module = self._module_list[index] + except IndexError: + sys.stderr.write("Module index {} out of range (0-{})\n".format( + index, len(self._module_list)-1)) + + return module + ############################################## + # Fan methods + ############################################## + + def get_num_fans(self): + """ + Retrieves the number of fans available on this chassis + + Returns: + An integer, the number of fan modules available on this chassis + """ + return len(self._fan_list) + + def get_all_fans(self): + """ + Retrieves all fan modules available on this chassis + + Returns: + A list of objects derived from FanBase representing all fan + modules available on this chassis + """ + return self._fan_list + + def get_fan(self, index): + """ + Retrieves fan module represented by (0-based) index + + Args: + index: An integer, the index (0-based) of the fan module to + retrieve + + Returns: + An object dervied from FanBase representing the specified fan + module + """ + fan = None + + try: + fan = self._fan_list[index] + except IndexError: + sys.stderr.write("Fan index {} out of range (0-{})\n".format( + index, len(self._fan_list)-1)) + + return fan + + ############################################## + # PSU methods + ############################################## + + def get_num_psus(self): + """ + Retrieves the number of power supply units available on this chassis + + Returns: + An integer, the number of power supply units available on this + chassis + """ + return len(self._psu_list) + + def get_all_psus(self): + """ + Retrieves all power supply units available on this chassis + + Returns: + A list of objects derived from PsuBase representing all power + supply units available on this chassis + """ + return self._psu_list + + def get_psu(self, index): + """ + Retrieves power supply unit represented by (0-based) index + + Args: + index: An integer, the index (0-based) of the power supply unit to + retrieve + + Returns: + An object dervied from PsuBase representing the specified power + supply unit + """ + psu = None + + try: + psu = self._psu_list[index] + except IndexError: + sys.stderr.write("PSU index {} out of range (0-{})\n".format( + index, len(self._psu_list)-1)) + + return psu + + ############################################## + # THERMAL methods + ############################################## + + def get_num_thermals(self): + """ + Retrieves the number of thermals available on this chassis + + Returns: + An integer, the number of thermals available on this chassis + """ + return len(self._thermal_list) + + def get_all_thermals(self): + """ + Retrieves all thermals available on this chassis + + Returns: + A list of objects derived from ThermalBase representing all thermals + available on this chassis + """ + return self._thermal_list + + def get_thermal(self, index): + """ + Retrieves thermal unit represented by (0-based) index + + Args: + index: An integer, the index (0-based) of the thermal to + retrieve + + Returns: + An object dervied from ThermalBase representing the specified thermal + """ + thermal = None + + try: + thermal = self._thermal_list[index] + except IndexError: + sys.stderr.write("THERMAL index {} out of range (0-{})\n".format( + index, len(self._thermal_list)-1)) + + return thermal + + ############################################## + # SFP methods + ############################################## + + def get_num_sfps(self): + """ + Retrieves the number of sfps available on this chassis + + Returns: + An integer, the number of sfps available on this chassis + """ + return len(self._sfp_list) + + def get_all_sfps(self): + """ + Retrieves all sfps available on this chassis + + Returns: + A list of objects derived from SfpBase representing all sfps + available on this chassis + """ + return self._sfp_list + + def get_sfp(self, index): + """ + Retrieves sfp represented by (0-based) index + + Args: + index: An integer, the index (0-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 0. + For example, 0 for Ethernet0, 1 for Ethernet4 and so on. + + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + + try: + sfp = self._sfp_list[index] + except IndexError: + sys.stderr.write("SFP index {} out of range (0-{})\n".format( + index, len(self._sfp_list)-1)) + + return sfp + + ############################################## + # System LED methods + ############################################## + def set_system_led(self, led_device_name, color): + result, msg = self.pddf_obj.is_supported_sysled_state(led_device_name, color) + if result == False: + print(msg) + return (False) + + index = self.pddf_obj.data[led_device_name]['dev_attr']['index'] + device_name = self.pddf_obj.data[led_device_name]['dev_info']['device_name'] + self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('color', color, self.pddf_obj.get_led_cur_state_path()) + self.pddf_obj.create_attr('dev_ops', 'set_status', self.pddf_obj.get_led_path()) + return (True) + + def get_system_led(self, led_device_name): + if led_device_name not in self.pddf_obj.data.keys(): + status = "[FAILED] " + led_device_name + " is not configured" + return (status) + + index = self.pddf_obj.data[led_device_name]['dev_attr']['index'] + device_name = self.pddf_obj.data[led_device_name]['dev_info']['device_name'] + self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('dev_ops', 'get_status', self.pddf_obj.get_led_path()) + color = self.pddf_obj.get_led_color() + return (color) + + ############################################## + # Other methods + ############################################## + + def get_watchdog(self): + """ + Retreives hardware watchdog device on this chassis + + Returns: + An object derived from WatchdogBase representing the hardware + watchdog device + """ + return self._watchdog + + def get_eeprom(self): + """ + Retreives eeprom device on this chassis + + Returns: + An object derived from WatchdogBase representing the hardware + eeprom device + """ + return self.sys_eeprom + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the format of + {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + raise NotImplementedError diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_eeprom.py b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_eeprom.py new file mode 100644 index 000000000000..592485d617e4 --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_eeprom.py @@ -0,0 +1,116 @@ +############################################################################# +# PDDF +# +# PDDF syseeprom base class inherited from the base class +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PddfEeprom(eeprom_tlvinfo.TlvInfoDecoder): + _TLV_INFO_MAX_LEN = 256 + pddf_obj = {} + plugin_data = {} + + def __init__(self, pddf_data=None, pddf_plugin_data=None): + if not pddf_data or not pddf_plugin_data: + raise ValueError('PDDF JSON data error') + + self.pddf_obj = pddf_data + self.plugin_data = pddf_plugin_data + + # system EEPROM always has device name EEPROM1 + self.eeprom_path = self.pddf_obj.get_path("EEPROM1", "eeprom") + if self.eeprom_path is None: + return + + super(PddfEeprom, self).__init__(self.eeprom_path, 0, '', True) + self.eeprom_tlv_dict = dict() + try: + self.eeprom_data = self.read_eeprom() + except: + self.eeprom_data = "N/A" + raise RuntimeError("PddfEeprom is not Programmed") + else: + eeprom = self.eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + ord(eeprom[tlv_index + 1])] + code = "0x%02X" % (ord(tlv[0])) + + if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT: + value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) | + (ord(tlv[4]) << 8) | ord(tlv[5])) + value += str(tlv[6:6 + ord(tlv[1])]) + else: + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32: + break + + tlv_index += ord(eeprom[tlv_index+1]) + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field(self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2] + + def base_mac_addr(self): + (is_valid, t) = self.get_tlv_field(self.eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field(self.eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field(self.eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2] + + def serial_str(self): + (is_valid, results) = self.get_tlv_field(self.eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2] + + def revision_str(self): + (is_valid, results) = self.get_tlv_field(self.eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2] + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_fan.py b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_fan.py new file mode 100755 index 000000000000..5930345070b4 --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_fan.py @@ -0,0 +1,329 @@ +#!/usr/bin/env python + +# All the supported FAN SysFS aattributes are +#- fan_present +#- fan_direction +#- fan_input +#- fan_pwm +#- fan_fault +# where idx is in the range [1-32] +# + +try: + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PddfFan(FanBase): + """PDDF generic Fan class""" + + pddf_obj = {} + plugin_data = {} + + def __init__(self, tray_idx, fan_idx=0, pddf_data=None, pddf_plugin_data=None, is_psu_fan=False, psu_index=0): + # idx is 0-based + if not pddf_data or not pddf_plugin_data: + raise ValueError('PDDF JSON data error') + + self.pddf_obj = pddf_data + self.plugin_data = pddf_plugin_data + self.platform = self.pddf_obj.get_platform() + + if tray_idx < 0 or tray_idx >= self.platform['num_fantrays']: + print("Invalid fantray index %d\n" % tray_idx) + return + + if fan_idx < 0 or fan_idx >= self.platform['num_fans_pertray']: + print("Invalid fan index (within a tray) %d\n" % fan_idx) + return + + self.fantray_index = tray_idx+1 + self.fan_index = fan_idx+1 + self.is_psu_fan = is_psu_fan + if self.is_psu_fan: + self.fans_psu_index = psu_index + + def get_name(self): + """ + Retrieves the fan name + Returns: String containing fan-name + """ + if self.is_psu_fan: + return "PSU{}_FAN{}".format(self.fans_psu_index, self.fan_index) + else: + if 'name' in self.plugin_data['FAN']: + return self.plugin_data['FAN']['name'][str(self.fantray_index)] + else: + return "Fantray{}_{}".format(self.fantray_index, self.fan_index) + + def get_presence(self): + if self.is_psu_fan: + return True + else: + idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index + attr_name = "fan" + str(idx) + "_present" + output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr_name) + if not output: + return False + + mode = output['mode'] + presence = output['status'].rstrip() + + vmap = self.plugin_data['FAN']['present'][mode]['valmap'] + + if presence in vmap: + status = vmap[presence] + else: + status = False + + return status + + def get_status(self): + speed = self.get_speed() + status = True if (speed != 0) else False + return status + + def get_direction(self): + """ + Retrieves the direction of fan + + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + if self.is_psu_fan: + device = "PSU{}".format(self.fans_psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_fan_dir") + if not output: + return False + + mode = output['mode'] + val = output['status'] + + val = val.rstrip() + vmap = self.plugin_data['PSU']['psu_fan_dir'][mode]['valmap'] + + if val in vmap: + direction = vmap[val] + else: + direction = val + + else: + idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index + attr = "fan" + str(idx) + "_direction" + output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr) + if not output: + return False + + mode = output['mode'] + val = output['status'] + + val = val.rstrip() + vmap = self.plugin_data['FAN']['direction'][mode]['valmap'] + if val in vmap: + direction = vmap[val] + else: + direction = val + + 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) + """ + if self.is_psu_fan: + attr = "psu_fan{}_speed_rpm".format(self.fan_index) + device = "PSU{}".format(self.fans_psu_index) + output = self.pddf_obj.get_attr_name_output(device, attr) + if not output: + return 0 + + output['status'] = output['status'].rstrip() + if output['status'].isalpha(): + return 0 + else: + speed = int(output['status']) + + max_speed = int(self.plugin_data['PSU']['PSU_FAN_MAX_SPEED']) + speed_percentage = (speed*100)/max_speed + return speed_percentage + else: + # TODO This calculation should change based on MAX FAN SPEED + idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index + attr = "fan" + str(idx) + "_pwm" + output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr) + + if not output: + return 0 + + output['status'] = output['status'].rstrip() + if output['status'].isalpha(): + return 0 + else: + fpwm = int(output['status']) + + pwm_to_dc = eval(self.plugin_data['FAN']['pwm_to_duty_cycle']) + speed_percentage = int(round(pwm_to_dc(fpwm))) + + return speed_percentage + + def get_speed_rpm(self): + """ + Retrieves the speed of fan in RPM + + Returns: + An integer, Speed of fan in RPM + """ + if self.is_psu_fan: + attr = "psu_fan{}_speed_rpm".format(self.fan_index) + device = "PSU{}".format(self.fans_psu_index) + output = self.pddf_obj.get_attr_name_output(device, attr) + if not output: + return 0 + + output['status'] = output['status'].rstrip() + if output['status'].isalpha(): + return 0 + else: + speed = int(float(output['status'])) + + rpm_speed = speed + return rpm_speed + else: + idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index + attr = "fan" + str(idx) + "_input" + output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr) + + if output is None: + return 0 + + output['status'] = output['status'].rstrip() + if output['status'].isalpha(): + return 0 + else: + rpm_speed = int(float(output['status'])) + + return rpm_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) + """ + target_speed = 0 + if self.is_psu_fan: + # Target speed not usually supported for PSU fans + target_speed = 0 + else: + idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index + attr = "fan" + str(idx) + "_pwm" + output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr) + + if not output: + return 0 + + output['status'] = output['status'].rstrip() + if output['status'].isalpha(): + return 0 + else: + fpwm = int(output['status']) + + pwm_to_dc = eval(self.plugin_data['FAN']['pwm_to_duty_cycle']) + speed_percentage = int(round(pwm_to_dc(fpwm))) + target_speed = speed_percentage + + return target_speed + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + # Fix the speed vairance to 10 percent. If it changes based on platforms, overwrite + # this value in derived pddf fan class + return 10 + + def set_speed(self, speed): + """ + Sets the fan speed + + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + + Returns: + A boolean, True if speed is set successfully, False if not + """ + if self.is_psu_fan: + print("Setting PSU fan speed is not allowed") + return False + else: + if speed < 0 or speed > 100: + print("Error: Invalid speed %d. Please provide a valid speed percentage" % speed) + return False + + if 'duty_cycle_to_pwm' not in self.plugin_data['FAN']: + print("Setting fan speed is not allowed !") + return False + else: + duty_cycle_to_pwm = eval(self.plugin_data['FAN']['duty_cycle_to_pwm']) + pwm = int(round(duty_cycle_to_pwm(speed))) + + status = False + idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index + attr = "fan" + str(idx) + "_pwm" + output = self.pddf_obj.set_attr_name_output("FAN-CTRL", attr, pwm) + if not output: + return False + + status = output['status'] + + return status + + def set_status_led(self, color): + index = str(self.fantray_index-1) + led_device_name = "FANTRAY{}".format(self.fantray_index) + "_LED" + + result, msg = self.pddf_obj.is_supported_sysled_state(led_device_name, color) + if result == False: + print(msg) + return (False) + + device_name = self.pddf_obj.data[led_device_name]['dev_info']['device_name'] + self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('color', color, self.pddf_obj.get_led_cur_state_path()) + self.pddf_obj.create_attr('dev_ops', 'set_status', self.pddf_obj.get_led_path()) + return (True) + + def get_status_led(self): + index = str(self.fantray_index-1) + fan_led_device = "FANTRAY{}".format(self.fantray_index) + "_LED" + + if fan_led_device not in self.pddf_obj.data.keys(): + # Implement a generic status_led color scheme + if self.get_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + + device_name = self.pddf_obj.data[fan_led_device]['dev_info']['device_name'] + self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('dev_ops', 'get_status', self.pddf_obj.get_led_path()) + color = self.pddf_obj.get_led_color() + return (color) + + def dump_sysfs(self): + return self.pddf_obj.cli_dump_dsysfs('fan') diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_platform.py b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_platform.py new file mode 100755 index 000000000000..00eefc9a815e --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_platform.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +############################################################################# +# PDDF +# Module contains an implementation of SONiC Platform API and +# provides the platform information +# +############################################################################# + + +try: + import json + from . import pddfparse + 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 PddfPlatform(PlatformBase): + """ + PDDF Generic Platform class + """ + pddf_data = {} + pddf_plugin_data = {} + + def __init__(self): + # Initialize the JSON data + self.pddf_data = pddfparse.PddfParse() + with open('/usr/share/sonic/platform/pddf/pd-plugin.json') as pd: + self.pddf_plugin_data = json.load(pd) + + if not self.pddf_data or not self.pddf_plugin_data: + print("Error: PDDF JSON data is not loaded properly ... Exiting") + raise ValueError + + PlatformBase.__init__(self) + self._chassis = Chassis(self.pddf_data, self.pddf_plugin_data) diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_psu.py b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_psu.py new file mode 100755 index 000000000000..58b69ce0aa73 --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_psu.py @@ -0,0 +1,297 @@ +#!/usr/bin/env python +# +# All the supported PSU SysFS aattributes are +#- psu_present +#- psu_model_name +#- psu_power_good +#- psu_mfr_id +#- psu_serial_num +#- psu_fan_dir +#- psu_v_out +#- psu_i_out +#- psu_p_out +#- psu_fan1_speed_rpm +# + + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PddfPsu(PsuBase): + """PDDF generic PSU class""" + + pddf_obj = {} + plugin_data = {} + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + PsuBase.__init__(self) + if not pddf_data or not pddf_plugin_data: + raise ValueError('PDDF JSON data error') + + self.pddf_obj = pddf_data + self.plugin_data = pddf_plugin_data + self.platform = self.pddf_obj.get_platform() + self.psu_index = index + 1 + + self._fan_list = [] # _fan_list under PsuBase class is a global variable, hence we need to use _fan_list per class instatiation + self.num_psu_fans = int(self.pddf_obj.get_num_psu_fans('PSU{}'.format(index+1))) + for psu_fan_idx in range(self.num_psu_fans): + psu_fan = Fan(0, psu_fan_idx, pddf_data, pddf_plugin_data, True, self.psu_index) + self._fan_list.append(psu_fan) + + def get_num_fans(self): + """ + Retrieves the number of fan modules available on this PSU + + Returns: + An integer, the number of fan modules available on this PSU + """ + return len(self._fan_list) + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + if 'name' in self.plugin_data['PSU']: + return self.plugin_data['PSU']['name'][str(self.psu_index)] + else: + return "PSU{}".format(self.psu_index) + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + status = 0 + device = "PSU{}".format(self.psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_present") + if not output: + return False + + mode = output['mode'] + status = output['status'] + + vmap = self.plugin_data['PSU']['psu_present'][mode]['valmap'] + + if status.rstrip('\n') in vmap: + return vmap[status.rstrip('\n')] + else: + return False + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + device = "PSU{}".format(self.psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_model_name") + if not output: + return None + + model = output['status'] + + # strip_non_ascii + stripped = (c for c in model if 0 < ord(c) < 127) + model = ''.join(stripped) + + return model.rstrip('\n') + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + device = "PSU{}".format(self.psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_serial_num") + if not output: + return None + + serial = output['status'] + + return serial.rstrip('\n') + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + device = "PSU{}".format(self.psu_index) + + output = self.pddf_obj.get_attr_name_output(device, "psu_power_good") + if not output: + return False + + mode = output['mode'] + status = output['status'] + + vmap = self.plugin_data['PSU']['psu_power_good'][mode]['valmap'] + + if status.rstrip('\n') in vmap: + return vmap[status.rstrip('\n')] + else: + return False + + def get_mfr_id(self): + """ + Retrieves the manufacturer id of the device + + Returns: + string: Manufacturer Id of device + """ + device = "PSU{}".format(self.psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_mfr_id") + if not output: + return None + + mfr = output['status'] + + return mfr.rstrip('\n') + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + device = "PSU{}".format(self.psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_v_out") + if not output: + return 0.0 + + v_out = output['status'] + + return float(v_out)/1000 + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + device = "PSU{}".format(self.psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_i_out") + if not output: + return 0.0 + + i_out = output['status'] + + # current in mA + return float(i_out)/1000 + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + device = "PSU{}".format(self.psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_p_out") + if not output: + return 0.0 + + p_out = output['status'] + + # power is returned in micro watts + return float(p_out)/1000000 + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + return self.get_status() + + def set_status_led(self, color): + index = str(self.psu_index-1) + led_device_name = "PSU{}".format(self.psu_index) + "_LED" + + result, msg = self.pddf_obj.is_supported_sysled_state(led_device_name, color) + if result == False: + print(msg) + return (False) + + device_name = self.pddf_obj.data[led_device_name]['dev_info']['device_name'] + self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('color', color, self.pddf_obj.get_led_cur_state_path()) + self.pddf_obj.create_attr('dev_ops', 'set_status', self.pddf_obj.get_led_path()) + return (True) + + def get_status_led(self): + index = str(self.psu_index-1) + psu_led_device = "PSU{}_LED".format(self.psu_index) + if psu_led_device not in self.pddf_obj.data.keys(): + # Implement a generic status_led color scheme + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + + device_name = self.pddf_obj.data[psu_led_device]['dev_info']['device_name'] + self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path()) + self.pddf_obj.create_attr('dev_ops', 'get_status', self.pddf_obj.get_led_path()) + color = self.pddf_obj.get_led_color() + return (color) + + def get_input_voltage(self): + """ + Retrieves current PSU input voltage + + Returns: + A float number, the input voltage in volts, + e.g. 12.1 + """ + device = "PSU{}".format(self.psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_v_in") + if not output: + return 0.0 + + v_in = output['status'] + + return float(v_in)/1000 + + def get_input_current(self): + """ + Retrieves present electric current supplied to the PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + device = "PSU{}".format(self.psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_i_in") + if not output: + return 0.0 + + i_in = output['status'] + + # current in mA + return float(i_in)/1000 + + def dump_sysfs(self): + return self.pddf_obj.cli_dump_dsysfs('psu') diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_sfp.py b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_sfp.py new file mode 100755 index 000000000000..dc37bba6e888 --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_sfp.py @@ -0,0 +1,1395 @@ +#!/usr/bin/env python + +try: + import time + from ctypes import create_string_buffer + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8472 import sffbase + from sonic_platform_base.sonic_sfp.inf8628 import inf8628InterfaceId +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +# definitions of the offset and width for values in XCVR info eeprom +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_TYPE_OFFSET = 0 +XCVR_TYPE_WIDTH = 1 +XCVR_EXT_TYPE_OFFSET = 1 +XCVR_EXT_TYPE_WIDTH = 1 +XCVR_CONNECTOR_OFFSET = 2 +XCVR_CONNECTOR_WIDTH = 1 +XCVR_COMPLIANCE_CODE_OFFSET = 3 +XCVR_COMPLIANCE_CODE_WIDTH = 8 +XCVR_ENCODING_OFFSET = 11 +XCVR_ENCODING_WIDTH = 1 +XCVR_NBR_OFFSET = 12 +XCVR_NBR_WIDTH = 1 +XCVR_EXT_RATE_SEL_OFFSET = 13 +XCVR_EXT_RATE_SEL_WIDTH = 1 +XCVR_CABLE_LENGTH_OFFSET = 14 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_CABLE_LENGTH_WIDTH_SFP = 6 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + +# definitions of the offset for values in OSFP info eeprom +OSFP_TYPE_OFFSET = 0 +OSFP_VENDOR_NAME_OFFSET = 129 +OSFP_VENDOR_PN_OFFSET = 148 +OSFP_HW_REV_OFFSET = 164 +OSFP_VENDOR_SN_OFFSET = 166 + +# definitions of the offset and width for values in DOM info eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNEL_THRESHOLD_OFFSET = 176 +QSFP_CHANNEL_THRESHOLD_WIDTH = 16 + + +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 40 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 1 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', + 'Length Cable Assembly(m)') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', 'Fibre Channel Speed') + +PAGE_OFFSET = 0 +KEY_OFFSET = 1 +KEY_WIDTH = 2 +FUNC_NAME = 3 + +INFO_OFFSET = 128 +DOM_OFFSET = 0 +DOM_OFFSET1 = 384 + + +class PddfSfp(SfpBase): + """ + PDDF generic Sfp class + """ + + pddf_obj = {} + plugin_data = {} + _port_to_eeprom_mapping = {} + _port_start = 0 + _port_end = 0 + _port_to_type_mapping = {} + _qsfp_ports = [] + _sfp_ports = [] + + # Read out any bytes from any offset + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + sysfsfile_eeprom = open(self.eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + for n in range(0, num_bytes): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except Exception as e: + print("Error: Unable to open eeprom_path: %s" % (str(e))) + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + if not pddf_data or not pddf_plugin_data: + raise ValueError('PDDF JSON data error') + + self.pddf_obj = pddf_data + self.plugin_data = pddf_plugin_data + + self.platform = self.pddf_obj.get_platform() + + # index is 0-based + self._port_start = 0 + self._port_end = int(self.platform['num_ports']) + if index < self._port_start or index >= self._port_end: + print("Invalid port index %d" % index) + return + + self.port_index = index+1 + self.device = 'PORT{}'.format(self.port_index) + self.sfp_type = self.pddf_obj.get_device_type(self.device) + self.is_qsfp_port = True if (self.sfp_type == 'QSFP' or self.sfp_type == 'QSFP28') else False + self.is_osfp_port = True if (self.sfp_type == 'OSFP' or self.sfp_type == 'QSFP-DD') else False + self.eeprom_path = self.pddf_obj.get_path(self.device, 'eeprom') + + self.info_dict_keys = ['type', 'hardware_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', + 'ext_identifier', 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', 'vendor_oui', 'application_advertisement'] + + self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] + + self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', + 'rxpowerhighwarning', 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', + 'txbiaslowwarning'] + + SfpBase.__init__(self) + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardware_rev |1*255VCHAR |hardware version of SFP + serial |1*255VCHAR |serial number of the SFP + manufacturer |1*255VCHAR |SFP vendor name + model |1*255VCHAR |SFP model name + connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + nominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + application_advertisement |1*255VCHAR |supported applications advertisement + ======================================================================== + """ + # check present status + if not self.get_presence(): + return None + + if self.is_osfp_port: + sfpi_obj = inf8628InterfaceId() + offset = 0 + type_offset = OSFP_TYPE_OFFSET + vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP + hw_rev_offset = OSFP_HW_REV_OFFSET + vendor_name_offset = OSFP_VENDOR_NAME_OFFSET + vendor_pn_offset = OSFP_VENDOR_PN_OFFSET + vendor_sn_offset = OSFP_VENDOR_SN_OFFSET + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + sfp_type = 'OSFP' + + elif self.is_qsfp_port: + sfpi_obj = sff8436InterfaceId() + offset = 128 + type_offset = XCVR_TYPE_OFFSET + vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP + hw_rev_offset = XCVR_HW_REV_OFFSET + vendor_name_offset = XCVR_VENDOR_NAME_OFFSET + vendor_pn_offset = XCVR_VENDOR_PN_OFFSET + vendor_sn_offset = XCVR_VENDOR_SN_OFFSET + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP + sfp_type = 'QSFP' + else: + sfpi_obj = sff8472InterfaceId() + offset = 0 + type_offset = XCVR_TYPE_OFFSET + vendor_rev_width = XCVR_HW_REV_WIDTH_SFP + hw_rev_offset = XCVR_HW_REV_OFFSET + vendor_name_offset = XCVR_VENDOR_NAME_OFFSET + vendor_pn_offset = XCVR_VENDOR_PN_OFFSET + vendor_sn_offset = XCVR_VENDOR_SN_OFFSET + interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP + sfp_type = 'SFP' + + if sfpi_obj is None: + return None + + if self.is_osfp_port: + sfp_type_raw = self.__read_eeprom_specific_bytes((offset + type_offset), XCVR_TYPE_WIDTH) + if sfp_type_raw is not None: + sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) + sfp_type_abbrv_name = sfpi_obj.parse_sfp_type_abbrv_name(sfp_typ_raw, 0) + else: + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_INTFACE_BULK_OFFSET), interface_info_bulk_width) + if sfp_interface_bulk_raw is not None: + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) + + sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + + sfp_vendor_date_raw = self.__read_eeprom_specific_bytes( + (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + if sfp_vendor_date_raw is not None: + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes( + (offset + vendor_name_offset), XCVR_VENDOR_NAME_WIDTH) + sfp_vendor_name_data = sfpi_obj.parse_vendor_name( + sfp_vendor_name_raw, 0) + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes( + (offset + vendor_pn_offset), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( + sfp_vendor_pn_raw, 0) + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( + (offset + hw_rev_offset), vendor_rev_width) + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( + sfp_vendor_rev_raw, 0) + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes( + (offset + vendor_sn_offset), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( + sfp_vendor_sn_raw, 0) + + xcvr_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') + compliance_code_dict = dict() + + if sfp_interface_bulk_data: + xcvr_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + xcvr_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + xcvr_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + xcvr_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + xcvr_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + xcvr_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + else: + xcvr_info_dict['type'] = sfp_type_data['data']['type']['value'] if sfp_type_data else 'N/A' + xcvr_info_dict['type_abbrv_name'] = sfp_type_abbrv_name['data']['type_abbrv_name']['value'] if sfp_type_abbrv_name else 'N/A' + + xcvr_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' + xcvr_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + xcvr_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' + xcvr_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + xcvr_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' + xcvr_info_dict['vendor_date'] = sfp_vendor_date_data['data'][ + 'VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' + xcvr_info_dict['cable_type'] = "Unknown" + xcvr_info_dict['cable_length'] = "Unknown" + + if sfp_type == 'QSFP': + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + xcvr_info_dict['cable_type'] = key + xcvr_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + xcvr_info_dict['specification_compliance'] = str(compliance_code_dict) + + nkey = 'Nominal Bit Rate(100Mbs)' + if nkey in sfp_interface_bulk_data['data']: + xcvr_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + else: + xcvr_info_dict['nominal_bit_rate'] = 'N/A' + elif sfp_type == 'OSFP': + pass + else: + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + xcvr_info_dict['cable_type'] = key + xcvr_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + xcvr_info_dict['specification_compliance'] = str(compliance_code_dict) + + xcvr_info_dict['nominal_bit_rate'] = str( + sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + return xcvr_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + # check present status + if not self.get_presence(): + return None + + xcvr_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') + + if self.is_osfp_port: + # Below part is added to avoid fail xcvrd, shall be implemented later + pass + elif self.is_qsfp_port: + # QSFPs + offset = 0 + offset_xcvr = 128 + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + sfpi_obj = sff8436InterfaceId() + if sfpi_obj is None: + return None + + qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes( + (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_dom_capability( + qsfp_dom_capability_raw, 0) + else: + return None + + dom_temperature_raw = self.__read_eeprom_specific_bytes((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 None + + dom_voltage_raw = self.__read_eeprom_specific_bytes((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 None + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes((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 None + + xcvr_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + xcvr_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( + (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 None + + xcvr_dom_info_dict['tx1power'] = 'N/A' + xcvr_dom_info_dict['tx2power'] = 'N/A' + xcvr_dom_info_dict['tx3power'] = 'N/A' + xcvr_dom_info_dict['tx4power'] = 'N/A' + else: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (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 + + xcvr_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value'] + xcvr_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value'] + xcvr_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value'] + xcvr_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value'] + + if dom_channel_monitor_raw: + xcvr_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + xcvr_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + xcvr_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value'] + xcvr_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value'] + xcvr_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value'] + xcvr_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value'] + xcvr_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] + xcvr_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] + xcvr_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] + xcvr_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] + + else: + # SFPs + offset = 256 + + sfpd_obj = sff8472Dom() + if sfpd_obj is None: + return None + + dom_temperature_raw = self.__read_eeprom_specific_bytes((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 None + + dom_voltage_raw = self.__read_eeprom_specific_bytes((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 None + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + (offset + SFP_CHANNL_MON_OFFSET), SFP_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 None + + xcvr_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + xcvr_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + xcvr_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value'] + xcvr_dom_info_dict['rx2power'] = 'N/A' + xcvr_dom_info_dict['rx3power'] = 'N/A' + xcvr_dom_info_dict['rx4power'] = 'N/A' + xcvr_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + xcvr_dom_info_dict['tx2bias'] = 'N/A' + xcvr_dom_info_dict['tx3bias'] = 'N/A' + xcvr_dom_info_dict['tx4bias'] = 'N/A' + xcvr_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + xcvr_dom_info_dict['tx2power'] = 'N/A' + xcvr_dom_info_dict['tx3power'] = 'N/A' + xcvr_dom_info_dict['tx4power'] = 'N/A' + + xcvr_dom_info_dict['rx_los'] = self.get_rx_los() + xcvr_dom_info_dict['tx_fault'] = self.get_tx_fault() + xcvr_dom_info_dict['reset_status'] = self.get_reset_status() + xcvr_dom_info_dict['lp_mode'] = self.get_lpmode() + + return xcvr_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + # check present status + if not self.get_presence(): + return None + + xcvr_dom_threshold_info_dict = dict.fromkeys(self.threshold_dict_keys, 'N/A') + + if self.is_osfp_port: + # Below part is added to avoid fail xcvrd, shall be implemented later + pass + elif self.is_qsfp_port: + # QSFPs + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return None + + dom_thres_raw = self.__read_eeprom_specific_bytes(QSFP_MODULE_THRESHOLD_OFFSET, QSFP_MODULE_THRESHOLD_WIDTH) + + if dom_thres_raw: + module_threshold_values = sfpd_obj.parse_module_threshold_values( + dom_thres_raw, 0) + module_threshold_data = module_threshold_values.get('data') + if module_threshold_data: + xcvr_dom_threshold_info_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value'] + xcvr_dom_threshold_info_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value'] + xcvr_dom_threshold_info_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value'] + xcvr_dom_threshold_info_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value'] + xcvr_dom_threshold_info_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value'] + xcvr_dom_threshold_info_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value'] + xcvr_dom_threshold_info_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value'] + xcvr_dom_threshold_info_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value'] + + dom_thres_raw = self.__read_eeprom_specific_bytes( + QSFP_CHANNEL_THRESHOLD_OFFSET, QSFP_CHANNEL_THRESHOLD_WIDTH) + if dom_thres_raw: + channel_threshold_values = sfpd_obj.parse_channel_threshold_values( + dom_thres_raw, 0) + channel_threshold_data = channel_threshold_values.get('data') + if channel_threshold_data: + xcvr_dom_threshold_info_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value'] + xcvr_dom_threshold_info_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value'] + xcvr_dom_threshold_info_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value'] + xcvr_dom_threshold_info_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value'] + xcvr_dom_threshold_info_dict['txpowerhighalarm'] = "0.0dBm" + xcvr_dom_threshold_info_dict['txpowerlowalarm'] = "0.0dBm" + xcvr_dom_threshold_info_dict['txpowerhighwarning'] = "0.0dBm" + xcvr_dom_threshold_info_dict['txpowerlowwarning'] = "0.0dBm" + xcvr_dom_threshold_info_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value'] + xcvr_dom_threshold_info_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value'] + xcvr_dom_threshold_info_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value'] + xcvr_dom_threshold_info_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value'] + + else: + # SFPs + sfpd_obj = sff8472Dom() + offset = 256 + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, offset) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes( + (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) + + xcvr_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + xcvr_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + xcvr_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + xcvr_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + xcvr_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value'] + xcvr_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value'] + xcvr_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data[ + 'data']['VoltageHighWarning']['value'] + xcvr_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value'] + xcvr_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + xcvr_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + xcvr_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + xcvr_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + xcvr_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + xcvr_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + xcvr_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + xcvr_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + xcvr_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + xcvr_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + xcvr_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + xcvr_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + + return xcvr_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + reset_status = None + if not self.get_presence(): + return reset_status + + device = 'PORT{}'.format(self.port_index) + output = self.pddf_obj.get_attr_name_output(device, 'xcvr_reset') + if not output: + return False + + status = int(output['status'].rstrip()) + + if status == 1: + reset_status = True + else: + reset_status = False + + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + rx_los = None + if not self.get_presence(): + return rx_los + + device = 'PORT{}'.format(self.port_index) + output = self.pddf_obj.get_attr_name_output(device, 'xcvr_rxlos') + + if not output: + # read the values from EEPROM + if self.is_osfp_port: + pass + elif self.is_qsfp_port: + rx_los_list = [] + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + QSFP_CHANNL_RX_LOS_STATUS_OFFSET, QSFP_CHANNL_RX_LOS_STATUS_WIDTH) if self.get_presence() else None + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + rx_los = rx_los_list[0] and rx_los_list[1] and rx_los_list[2] and rx_los_list[3] + else: + # SFP ports + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + rx_los = (sffbase().test_bit(data, 1) != 0) + + else: + status = int(output['status'].rstrip()) + + if status == 1: + rx_los = True + else: + rx_los = False + + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + tx_fault = None + if not self.get_presence(): + return tx_fault + + device = 'PORT{}'.format(self.port_index) + output = self.pddf_obj.get_attr_name_output(device, 'xcvr_txfault') + + if not output: + # read the values from EEPROM + if self.is_osfp_port: + pass + elif self.is_qsfp_port: + tx_fault_list = [] + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( + QSFP_CHANNL_TX_FAULT_STATUS_OFFSET, QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) if self.get_presence() else None + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + tx_fault = tx_fault_list[0] and tx_fault_list[1] and tx_fault_list[2] and tx_fault_list[3] + else: + # SFP + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + tx_fault = (sffbase().test_bit(data, 2) != 0) + else: + status = int(output['status'].rstrip()) + + if status == 1: + tx_fault = True + else: + tx_fault = False + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + tx_disable = False + if not self.get_presence(): + return tx_disable + + device = 'PORT{}'.format(self.port_index) + output = self.pddf_obj.get_attr_name_output(device, 'xcvr_txdisable') + + if not output: + # read the values from EEPROM + if self.is_osfp_port: + return tx_disable + elif self.is_qsfp_port: + tx_disable_list = [] + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + tx_disable_list.append( + 'On' == dom_control_data['data']['TX1Disable']['value']) + tx_disable_list.append( + 'On' == dom_control_data['data']['TX2Disable']['value']) + tx_disable_list.append( + 'On' == dom_control_data['data']['TX3Disable']['value']) + tx_disable_list.append( + 'On' == dom_control_data['data']['TX4Disable']['value']) + + return tx_disable_list + else: + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + tx_disable_hard = (sffbase().test_bit( + data, SFP_TX_DISABLE_HARD_BIT) != 0) + tx_disable_soft = (sffbase().test_bit( + data, SFP_TX_DISABLE_SOFT_BIT) != 0) + tx_disable = tx_disable_hard | tx_disable_soft + + return tx_disable + else: + status = int(output['status'].rstrip()) + + if status == 1: + tx_disable = True + else: + tx_disable = False + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + if not self.get_presence(): + return 0 + + if self.is_osfp_port: + return 0 + elif self.is_qsfp_port: + tx_disable_list = self.get_tx_disable() + if tx_disable_list is None: + return 0 + tx_disabled = 0 + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disabled |= 1 << i + return tx_disabled + else: + # SFP doesnt support this + return 0 + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + lpmode = False + if not self.get_presence(): + return lpmode + + device = 'PORT{}'.format(self.port_index) + output = self.pddf_obj.get_attr_name_output(device, 'xcvr_lpmode') + + if not output: + # Read from EEPROM + if self.is_osfp_port: + pass + elif self.is_qsfp_port: + try: + eeprom = None + ctype = self.get_connector_type() + if ctype in ['Copper pigtail', 'No separable connector']: + return False + + eeprom = open(self.eeprom_path, "rb") + eeprom.seek(93) + status = ord(eeprom.read(1)) + + if ((status & 0x3) == 0x3): + # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 + lpmode = True + else: + # High Power Mode if one of the following conditions is matched: + # 1. "Power override" bit is 0 + # 2. "Power override" bit is 1 and "Power set" bit is 0 + lpmode = False + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + else: + # SFP + pass + else: + status = int(output['status'].rstrip()) + + if status == 1: + lpmode = True + else: + lpmode = False + + return lpmode + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + power_override = False + if not self.get_presence(): + return power_override + + if self.is_osfp_port: + pass + elif self.is_qsfp_port: + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return False + + dom_control_raw = self.__read_eeprom_specific_bytes( + QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + power_override = ('On' == dom_control_data['data']['PowerOverride']['value']) + else: + # SFP doesnt suppor this + pass + + return power_override + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + Returns: + An integer number of current temperature in Celsius + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + if transceiver_dom_info_dict is not None: + # returns None if temperature is not found in the dictionary + return transceiver_dom_info_dict.get("temperature") + else: + return None + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + Returns: + An integer number of supply voltage in mV + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + # returns None if voltage is not found in the dictionary + if transceiver_dom_info_dict is not None: + return transceiver_dom_info_dict.get("voltage") + else: + return None + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + if transceiver_dom_info_dict is not None: + tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A") + tx2_bs = transceiver_dom_info_dict.get("tx2bias", "N/A") + tx3_bs = transceiver_dom_info_dict.get("tx3bias", "N/A") + tx4_bs = transceiver_dom_info_dict.get("tx4bias", "N/A") + return [tx1_bs, tx2_bs, tx3_bs, tx4_bs] if transceiver_dom_info_dict else [] + else: + return None + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + if transceiver_dom_info_dict is not None: + rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A") + rx2_pw = transceiver_dom_info_dict.get("rx2power", "N/A") + rx3_pw = transceiver_dom_info_dict.get("rx3power", "N/A") + rx4_pw = transceiver_dom_info_dict.get("rx4power", "N/A") + return [rx1_pw, rx2_pw, rx3_pw, rx4_pw] if transceiver_dom_info_dict else [] + else: + return None + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + if transceiver_dom_info_dict is not None: + tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A") + tx2_pw = transceiver_dom_info_dict.get("tx2power", "N/A") + tx3_pw = transceiver_dom_info_dict.get("tx3power", "N/A") + tx4_pw = transceiver_dom_info_dict.get("tx4power", "N/A") + return [tx1_pw, tx2_pw, tx3_pw, tx4_pw] + else: + return None + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + Returns: + A boolean, True if successful, False if not + """ + status = False + if not self.get_presence(): + return status + + device = 'PORT{}'.format(self.port_index) + # TODO: Implement a wrapper set function to write the sequence + path = self.pddf_obj.get_path(device, 'xcvr_reset') + + # TODO: put the optic based reset logic using EEPROM + if path is None: + pass + else: + try: + f = open(path, 'r+') + except IOError as e: + return False + + try: + f.seek(0) + f.write('1') + time.sleep(1) + f.seek(0) + f.write('0') + + f.close() + status = True + except IOError as e: + status = False + + return status + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + # find out a generic implementation of tx_disable for SFP, QSFP and OSFP + status = False + if not self.get_presence(): + return tx_disable + + device = 'PORT{}'.format(self.port_index) + path = self.pddf_obj.get_path(device, 'xcvr_txdisable') + + # TODO: put the optic based reset logic using EEPROM + if path is None: + if self.is_osfp_port: + pass + elif self.is_qsfp_port: + eeprom_f = None + try: + txdisable_ctl = 0xf if tx_disable else 0x0 + buf = create_string_buffer(1) + buf[0] = chr(txdisable_ctl) + # Write to eeprom + eeprom_f = open(self.eeprom_path, "r+b") + eeprom_f.seek(QSFP_CONTROL_OFFSET) + eeprom_f.write(buf[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom_f is not None: + eeprom_f.close() + time.sleep(0.01) + + status = True + else: + status_control_raw = self.__read_eeprom_specific_bytes( + SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw is not None: + # Set bit 6 for Soft TX Disable Select + # 01000000 = 64 and 10111111 = 191 + txdisable_bit = 64 if tx_disable else 191 + status_control = int(status_control_raw[0], 16) + txdisable_ctl = (status_control | txdisable_bit) if tx_disable else ( + status_control & txdisable_bit) + try: + eeprom_f = open(self.eeprom_path, mode="r+b", buffering=0) + buf = create_string_buffer(1) + buf[0] = chr(txdisable_ctl) + # Write to eeprom + eeprom_f.seek(SFP_STATUS_CONTROL_OFFSET) + eeprom_f.write(buf[0]) + except Exception as e: + print(("Error: unable to open file: %s" % str(e))) + return False + finally: + if eeprom_f: + eeprom_f.close() + time.sleep(0.01) + status = True + else: + try: + f = open(path, 'r+') + except IOError as e: + return False + + try: + if tx_disable: + f.write('1') + else: + f.write('0') + f.close() + status = True + except IOError as e: + status = False + + return status + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + Returns: + A boolean, True if successful, False if not + """ + # TODO: find a implementation + status = False + if not self.get_presence(): + return status + + if self.is_osfp_port: + pass + elif self.is_qsfp_port: + eeprom_f = None + try: + channel_state = self.get_tx_disable_channel() + txdisable_ctl = (channel_state | channel) if disable else (channel_state & ~channel) + buf = create_string_buffer(1) + buf[0] = chr(txdisable_ctl) + # Write to eeprom + eeprom_f = open(self.eeprom_path, "r+b") + eeprom_f.seek(QSFP_CONTROL_OFFSET) + eeprom_f.write(buf[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom_f is not None: + eeprom_f.close() + time.sleep(0.01) + status = True + else: + pass + + return status + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + status = False + if not self.get_presence(): + return status + + device = 'PORT{}'.format(self.port_index) + path = self.pddf_obj.get_path(device, 'xcvr_lpmode') + + # TODO: put the optic based reset logic using EEPROM + if path is None: + if self.is_osfp_port: + pass + elif self.is_qsfp_port: + try: + eeprom_f = None + ctype = self.get_connector_type() + if ctype in ['Copper pigtail', 'No separable connector']: + return False + + # Fill in write buffer + regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode + buffer = create_string_buffer(1) + buffer[0] = chr(regval) + + # Write to eeprom + eeprom_f = open(self.eeprom_path, "r+b") + eeprom_f.seek(93) + eeprom_f.write(buffer[0]) + return True + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom_f is not None: + eeprom_f.close() + time.sleep(0.01) + else: + pass + + else: + try: + f = open(path, 'r+') + except IOError as e: + return False + + try: + if lpmode: + f.write('1') + else: + f.write('0') + + f.close() + status = True + except IOError as e: + status = False + + return status + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + status = False + if not self.get_presence(): + return status + + if self.is_osfp_port: + pass + elif self.is_qsfp_port: + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + eeprom_f = open(self.eeprom_path, "r+b") + eeprom_f.seek(QSFP_POWEROVERRIDE_OFFSET) + eeprom_f.write(buffer[0]) + except IOError as e: + print("Error: unable to open file: %s" % str(e)) + return False + finally: + if eeprom_f is not None: + eeprom_f.close() + time.sleep(0.01) + return True + else: + pass + + return status + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + # Name of the port/sfp ? + return 'PORT{}'.format(self.port_index) + + def get_presence(self): + """ + Retrieves the presence of the PSU + Returns: + bool: True if PSU is present, False if not + """ + output = self.pddf_obj.get_attr_name_output(self.device, 'xcvr_present') + if not output: + return False + + mode = output['mode'] + modpres = output['status'].rstrip() + if 'XCVR' in self.plugin_data: + if 'xcvr_present' in self.plugin_data['XCVR']: + ptype = self.sfp_type + vtype = 'valmap-'+ptype + if vtype in self.plugin_data['XCVR']['xcvr_present'][mode]: + vmap = self.plugin_data['XCVR']['xcvr_present'][mode][vtype] + if modpres in vmap: + return vmap[modpres] + else: + return False + # if self.plugin_data doesn't specify anything regarding Transceivers + if modpres == '1': + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + if transceiver_dom_info_dict is not None: + return transceiver_dom_info_dict.get("model", "N/A") + else: + return None + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + transceiver_dom_info_dict = self.get_transceiver_info() + if transceiver_dom_info_dict is not None: + return transceiver_dom_info_dict.get("serial", "N/A") + else: + return None + + 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_transceiver_bulk_status() + + def get_connector_type(self): + """ + Retrieves the device connector type + Returns: + enum: connector_code + """ + transceiver_dom_info_dict = self.get_transceiver_info() + if transceiver_dom_info_dict is not None: + return transceiver_dom_info_dict.get("connector", "N/A") + else: + return None + + 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 + + def dump_sysfs(self): + return self.pddf_obj.cli_dump_dsysfs('xcvr') diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_thermal.py b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_thermal.py new file mode 100755 index 000000000000..cd09041e152f --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_thermal.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python + +# All the supported Temperature Sensor SysFS aattributes are +#- temp1_high_crit_threshold +#- temp1_high_threshold +#- temp1_input +#- temp_low_threshold +#- temp1_low_crit_threshold + +try: + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PddfThermal(ThermalBase): + """PDDF generic Thermal class""" + pddf_obj = {} + plugin_data = {} + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + if not pddf_data or not pddf_plugin_data: + raise ValueError('PDDF JSON data error') + + self.pddf_obj = pddf_data + self.plugin_data = pddf_plugin_data + + self.platform = self.pddf_obj.get_platform() + + self.thermal_index = index + 1 + self.thermal_obj_name = "TEMP{}".format(self.thermal_index) + self.thermal_obj = self.pddf_obj.data[self.thermal_obj_name] + + def get_name(self): + if 'dev_attr' in self.thermal_obj.keys(): + if 'display_name' in self.thermal_obj['dev_attr']: + return str(self.thermal_obj['dev_attr']['display_name']) + # In case of errors + return (self.thermal_obj_name) + + def get_temperature(self): + output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_input") + if not output: + return None + + if output['status'].isalpha(): + attr_value = None + else: + attr_value = float(output['status']) + + if output['mode'] == 'bmc': + return attr_value + else: + return (attr_value/float(1000)) + + def get_high_threshold(self): + output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_high_threshold") + if not output: + return None + + if output['status'].isalpha(): + attr_value = None + else: + attr_value = float(output['status']) + + if output['mode'] == 'bmc': + return attr_value + else: + return (attr_value/float(1000)) + + def get_low_threshold(self): + output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_low_threshold") + if not output: + return None + + if output['status'].isalpha(): + attr_value = None + else: + attr_value = float(output['status']) + + if output['mode'] == 'bmc': + return attr_value + else: + return (attr_value/float(1000)) + + def set_high_threshold(self, temperature): + node = self.pddf_obj.get_path(self.thermal_obj_name, "temp1_high_threshold") + if node is None: + print("ERROR %s does not exist" % node) + return None + + cmd = "echo '%d' > %s" % (temperature * 1000, node) + os.system(cmd) + + return (True) + + def set_low_threshold(self, temperature): + node = self.pddf_obj.get_path(self.thermal_obj_name, "temp1_low_threshold") + if node is None: + print("ERROR %s does not exist" % node) + return None + cmd = "echo '%d' > %s" % (temperature * 1000, node) + os.system(cmd) + + return (True) + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_high_crit_threshold") + if not output: + return None + + if output['status'].isalpha(): + attr_value = None + else: + attr_value = float(output['status']) + + if output['mode'] == 'bmc': + return attr_value + else: + return (attr_value/float(1000)) + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature of thermal + + Returns: + A float number, the low critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_low_crit_threshold") + if not output: + return None + + if output['status'].isalpha(): + attr_value = None + else: + attr_value = float(output['status']) + + if output['mode'] == 'bmc': + return attr_value + else: + return (attr_value/float(1000)) + + # Helper Functions + + def get_temp_label(self): + if 'bmc' in self.pddf_obj.data[self.thermal_obj_name].keys(): + return None + else: + if self.thermal_obj_name in self.pddf_obj.data.keys(): + dev = self.pddf_obj.data[self.thermal_obj_name] + topo_info = dev['i2c']['topo_info'] + label = "%s-i2c-%d-%x" % (topo_info['dev_type'], int(topo_info['parent_bus'], 0), + int(topo_info['dev_addr'], 0)) + return (label) + else: + return None + + def dump_sysfs(self): + return self.pddf_obj.cli_dump_dsysfs('temp-sensors') diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddfparse.py b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddfparse.py new file mode 100755 index 000000000000..6ca59206fd56 --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddfparse.py @@ -0,0 +1,1465 @@ +#!/usr/bin/env python +import glob +import json +from jsonschema import validate +import os +import re +import subprocess +import time +import unicodedata + +bmc_cache = {} +cache = {} +SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen' +HWSKU_KEY = 'DEVICE_METADATA.localhost.hwsku' +PLATFORM_KEY = 'DEVICE_METADATA.localhost.platform' + +dirname = os.path.dirname(os.path.realpath(__file__)) + +color_map = { + "STATUS_LED_COLOR_GREEN": "green", + "STATUS_LED_COLOR_RED": "red", + "STATUS_LED_COLOR_AMBER": "amber", + "STATUS_LED_COLOR_BLUE": "blue", + "STATUS_LED_COLOR_GREEN_BLINK": "blinking green", + "STATUS_LED_COLOR_RED_BLINK": "blinking red", + "STATUS_LED_COLOR_AMBER_BLINK": "blinking amber", + "STATUS_LED_COLOR_BLUE_BLINK": "blinking blue", + "STATUS_LED_COLOR_OFF": "off" +} + + +class PddfParse(): + def __init__(self): + if not os.path.exists("/usr/share/sonic/platform"): + self.platform, self.hwsku = self.get_platform_and_hwsku() + os.symlink("/usr/share/sonic/device/"+self.platform, "/usr/share/sonic/platform") + + try: + with open('/usr/share/sonic/platform/pddf/pddf-device.json') as f: + self.data = json.load(f) + except IOError: + if os.path.exists('/usr/share/sonic/platform'): + os.unlink("/usr/share/sonic/platform") + + self.data_sysfs_obj = {} + self.sysfs_obj = {} + + # Returns platform and HW SKU + + def get_platform_and_hwsku(self): + 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 as e: + raise OSError("Cannot detect platform") + + return (platform, hwsku) + + ################################################################################################################# + # GENERIC DEFS + ################################################################################################################# + def runcmd(self, cmd): + rc = os.system(cmd) + if rc != 0: + print("%s -- command failed" % cmd) + return rc + + def get_dev_idx(self, dev, ops): + parent = dev['dev_info']['virt_parent'] + pdev = self.data[parent] + + return pdev['dev_attr']['dev_idx'] + + def get_path(self, target, attr): + aa = target + attr + + if aa in cache: + return cache[aa] + + string = None + p = re.search(r'\d+$', target) + if p is None: + for bb in filter(re.compile(target).search, self.data.keys()): + path = self.dev_parse(self.data[bb], {"cmd": "show_attr", "target": bb, "attr": attr}) + if path != "": + string = path + else: + if target in self.data.keys(): + path = self.dev_parse(self.data[target], {"cmd": "show_attr", "target": target, "attr": attr}) + if path != "": + string = path + + if string is not None: + string = string.rstrip() + + cache[aa] = string + return string + + def get_device_type(self, key): + if key not in self.data.keys(): + return None + return self.data[key]['dev_info']['device_type'] + + def get_platform(self): + return self.data['PLATFORM'] + + def get_num_psu_fans(self, dev): + if dev not in self.data.keys(): + return 0 + + if 'num_psu_fans' not in self.data[dev]['dev_attr']: + return 0 + + return self.data[dev]['dev_attr']['num_psu_fans'] + + def get_led_path(self): + return ("pddf/devices/led") + + def get_led_cur_state_path(self): + return ("pddf/devices/led/cur_state") + + def get_led_color(self): + color_f = "/sys/kernel/pddf/devices/led/cur_state/color" + try: + with open(color_f, 'r') as f: + color = f.read().strip("\r\n") + except IOError: + return ("Error") + + return (color_map[color]) + + def get_led_color_devtype(self, key): + attr_list = self.data[key]['i2c']['attr_list'] + for attr in attr_list: + if 'attr_devtype' in attr: + return attr['attr_devtype'].strip() + else: + return 'cpld' + + def get_led_color_from_gpio(self, led_device_name): + attr_list = self.data[led_device_name]['i2c']['attr_list'] + attr = attr_list[0] + if ':' in attr['bits']: + bits_list = attr['bits'].split(':') + bits_list.sort(reverse=True) + max_bit = int(bits_list[0]) + else: + max_bit = 0 + base_offset = int(attr['swpld_addr_offset'], 16) + value = 0 + bit = 0 + while bit <= max_bit: + offset = base_offset + bit + if 'attr_devname' in attr: + attr_path = self.get_gpio_attr_path(self.data[attr['attr_devname']], hex(offset)) + else: + status = "[FAILED] attr_devname is not configured" + return (status) + if not os.path.exists(attr_path): + status = "[FAILED] {} does not exist".format(attr_path) + return (status) + cmd = 'cat ' + attr_path + gpio_value = subprocess.check_output(cmd, shell=True) + value |= int(gpio_value) << bit + bit += 1 + + for attr in attr_list: + if int(attr['value'].strip(), 16) == value: + return(color_map[attr['attr_name']]) + return (color_map['STATUS_LED_COLOR_OFF']) + + def get_led_color_from_cpld(self, led_device_name): + index = self.data[led_device_name]['dev_attr']['index'] + device_name = self.data[led_device_name]['dev_info']['device_name'] + self.create_attr('device_name', device_name, self.get_led_path()) + self.create_attr('index', index, self.get_led_path()) + self.create_attr('dev_ops', 'get_status', self.get_led_path()) + return self.get_led_color() + + def set_led_color_from_gpio(self, led_device_name, color): + attr_list = self.data[led_device_name]['i2c']['attr_list'] + for attr in attr_list: + if attr['attr_name'].strip() == color.strip(): + base_offset = int(attr['swpld_addr_offset'], 16) + if ':' in attr['bits']: + bits_list = attr['bits'].split(':') + bits_list.sort(reverse=True) + max_bit = int(bits_list[0]) + else: + max_bit = 0 + value = int(attr['value'], 16) + i = 0 + while i <= max_bit: + _value = (value >> i) & 1 + base_offset += i + attr_path = self.get_gpio_attr_path(self.data[attr['attr_devname']], hex(base_offset)) + i += 1 + try: + cmd = "echo {} > {}".format(_value, attr_path) + self.runcmd(cmd) + except Exception as e: + print("Invalid gpio path : " + attr_path) + return (False) + return (True) + + def set_led_color_from_cpld(self, led_device_name, color): + index = self.data[led_device_name]['dev_attr']['index'] + device_name = self.data[led_device_name]['dev_info']['device_name'] + self.create_attr('device_name', device_name, self.get_led_path()) + self.create_attr('index', index, self.get_led_path()) + self.create_attr('color', color, self.get_led_cur_state_path()) + self.create_attr('dev_ops', 'set_status', self.get_led_path()) + return (True) + + def get_system_led_color(self, led_device_name): + if led_device_name not in self.data.keys(): + status = "[FAILED] " + led_device_name + " is not configured" + return (status) + + type = self.get_led_color_devtype(led_device_name) + + if type == 'gpio': + color = self.get_led_color_from_gpio(led_device_name) + elif type == 'cpld': + color = self.get_led_color_from_cpld(led_device_name) + return color + + def set_system_led_color(self, led_device_name, color): + result, msg = self.is_supported_sysled_state(led_device_name, color) + if result == False: + print(msg) + return (result) + + type = self.get_led_color_devtype(led_device_name) + + if type == 'gpio': + return (self.set_led_color_from_gpio(led_device_name, color)) + else: + return (self.set_led_color_from_cpld(led_device_name, color)) + + ################################################################################################################### + # SHOW ATTRIBIUTES DEFS + ################################################################################################################### + def is_led_device_configured(self, device_name, attr_name): + if device_name in self.data.keys(): + attr_list = self.data[device_name]['i2c']['attr_list'] + for attr in attr_list: + if attr['attr_name'].strip() == attr_name.strip(): + return (True) + return (False) + + def show_device_sysfs(self, dev, ops): + parent = dev['dev_info']['device_parent'] + pdev = self.data[parent] + if pdev['dev_info']['device_parent'] == 'SYSTEM': + return "/sys/bus/i2c/devices/"+"i2c-%d" % int(pdev['i2c']['topo_info']['dev_addr'], 0) + return self.show_device_sysfs(pdev, ops) + "/" + "i2c-%d" % int(dev['i2c']['topo_info']['parent_bus'], 0) + + # This is alid for 'at24' type of EEPROM devices. Only one attribtue 'eeprom' + + def show_attr_eeprom_device(self, dev, ops): + str = "" + attr_name = ops['attr'] + attr_list = dev['i2c']['attr_list'] + KEY = "eeprom" + dsysfs_path = "" + + if KEY not in self.data_sysfs_obj: + self.data_sysfs_obj[KEY] = [] + + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all': + if 'drv_attr_name' in attr.keys(): + real_name = attr['drv_attr_name'] + else: + real_name = attr['attr_name'] + + dsysfs_path = self.show_device_sysfs(dev, ops) + \ + "/%d-00%x" % (int(dev['i2c']['topo_info']['parent_bus'], 0), + int(dev['i2c']['topo_info']['dev_addr'], 0)) + \ + "/%s" % real_name + if dsysfs_path not in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + str += dsysfs_path+"\n" + return str + + def show_attr_gpio_device(self, dev, ops): + ret = "" + KEY = "gpio" + if KEY not in self.data_sysfs_obj: + self.data_sysfs_obj[KEY] = [] + + return ret + + def show_attr_mux_device(self, dev, ops): + ret = "" + KEY = "mux" + if KEY not in self.data_sysfs_obj: + self.data_sysfs_obj[KEY] = [] + + return ret + + def get_gpio_attr_path(self, dev, offset): + base = int(dev['i2c']['dev_attr']['gpio_base'], 16) + port_num = base + int(offset, 16) + gpio_name = 'gpio'+str(port_num) + path = '/sys/class/gpio/'+gpio_name+'/value' + return path + + def show_attr_psu_i2c_device(self, dev, ops): + target = ops['target'] + attr_name = ops['attr'] + ret = "" + KEY = "psu" + dsysfs_path = "" + + if KEY not in self.data_sysfs_obj: + self.data_sysfs_obj[KEY] = [] + + if target == 'all' or target == dev['dev_info']['virt_parent']: + attr_list = dev['i2c']['attr_list'] + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all': + if 'attr_devtype' in attr.keys() and attr['attr_devtype'] == "gpio": + # Check and enable the gpio from class + attr_path = self.get_gpio_attr_path(self.data[attr['attr_devname']], attr['attr_offset']) + if (os.path.exists(attr_path)): + if attr_path not in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(attr_path) + ret += attr_path + '\n' + else: + if 'drv_attr_name' in attr.keys(): + real_name = attr['drv_attr_name'] + else: + real_name = attr['attr_name'] + + dsysfs_path = self.show_device_sysfs(dev, ops) + \ + "/%d-00%x" % (int(dev['i2c']['topo_info']['parent_bus'], 0), + int(dev['i2c']['topo_info']['dev_addr'], 0)) + \ + "/%s" % real_name + if dsysfs_path not in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + ret += dsysfs_path+"\n" + return ret + + def show_attr_psu_device(self, dev, ops): + return self.show_attr_psu_i2c_device(dev, ops) + + def show_attr_fan_device(self, dev, ops): + ret = "" + attr_name = ops['attr'] + attr_list = dev['i2c']['attr_list'] + KEY = "fan" + dsysfs_path = "" + + if KEY not in self.data_sysfs_obj: + self.data_sysfs_obj[KEY] = [] + + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all': + if 'attr_devtype' in attr.keys() and attr['attr_devtype'] == "gpio": + # Check and enable the gpio from class + attr_path = self.get_gpio_attr_path(self.data[attr['attr_devname']], attr['attr_offset']) + if (os.path.exists(attr_path)): + if attr_path not in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(attr_path) + ret += attr_path + '\n' + else: + if 'drv_attr_name' in attr.keys(): + real_name = attr['drv_attr_name'] + else: + real_name = attr['attr_name'] + + dsysfs_path = self.show_device_sysfs(dev, ops) + \ + "/%d-00%x" % (int(dev['i2c']['topo_info']['parent_bus'], 0), + int(dev['i2c']['topo_info']['dev_addr'], 0)) + \ + "/%s" % real_name + if dsysfs_path not in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + ret += dsysfs_path+"\n" + return ret + + # This is only valid for LM75 + def show_attr_temp_sensor_device(self, dev, ops): + str = "" + attr_name = ops['attr'] + attr_list = dev['i2c']['attr_list'] + KEY = "temp-sensors" + dsysfs_path = "" + + if KEY not in self.data_sysfs_obj: + self.data_sysfs_obj[KEY] = [] + + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all': + path = self.show_device_sysfs(dev, ops)+"/%d-00%x/" % (int(dev['i2c']['topo_info']['parent_bus'], 0), + int(dev['i2c']['topo_info']['dev_addr'], 0)) + if 'drv_attr_name' in attr.keys(): + real_name = attr['drv_attr_name'] + else: + real_name = attr['attr_name'] + + if (os.path.exists(path)): + full_path = glob.glob(path + 'hwmon/hwmon*/' + real_name)[0] + dsysfs_path = full_path + if dsysfs_path not in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + str += full_path + "\n" + return str + + def show_attr_sysstatus_device(self, dev, ops): + ret = "" + attr_name = ops['attr'] + attr_list = dev['attr_list'] + KEY = "sys-status" + dsysfs_path = "" + + if KEY not in self.data_sysfs_obj: + self.data_sysfs_obj[KEY] = [] + + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all': + dsysfs_path = "/sys/kernel/pddf/devices/sysstatus/sysstatus_data/" + attr['attr_name'] + if dsysfs_path not in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + ret += dsysfs_path+"\n" + return ret + + def show_attr_xcvr_i2c_device(self, dev, ops): + target = ops['target'] + attr_name = ops['attr'] + ret = "" + dsysfs_path = "" + KEY = "xcvr" + if KEY not in self.data_sysfs_obj: + self.data_sysfs_obj[KEY] = [] + + if target == 'all' or target == dev['dev_info']['virt_parent']: + attr_list = dev['i2c']['attr_list'] + for attr in attr_list: + if attr_name == attr['attr_name'] or attr_name == 'all': + if 'attr_devtype' in attr.keys() and attr['attr_devtype'] == "gpio": + # Check and enable the gpio from class + attr_path = self.get_gpio_attr_path(self.data[attr['attr_devname']], attr['attr_offset']) + if (os.path.exists(attr_path)): + if attr_path not in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(attr_path) + ret += attr_path + '\n' + else: + if 'drv_attr_name' in attr.keys(): + real_name = attr['drv_attr_name'] + else: + real_name = attr['attr_name'] + + dsysfs_path = self.show_device_sysfs(dev, ops) + \ + "/%d-00%x" % (int(dev['i2c']['topo_info']['parent_bus'], 0), + int(dev['i2c']['topo_info']['dev_addr'], 0)) + \ + "/%s" % real_name + if dsysfs_path not in self.data_sysfs_obj[KEY]: + self.data_sysfs_obj[KEY].append(dsysfs_path) + ret += dsysfs_path+"\n" + return ret + + def show_attr_xcvr_device(self, dev, ops): + return self.show_attr_xcvr_i2c_device(dev, ops) + + def show_attr_cpld_device(self, dev, ops): + ret = "" + KEY = "cpld" + if KEY not in self.data_sysfs_obj: + self.data_sysfs_obj[KEY] = [] + + return ret + + ################################################################################################################### + # SHOW DEFS + ################################################################################################################### + + def check_led_cmds(self, key, ops): + name = ops['target']+'_LED' + if (ops['target'] == 'config' or ops['attr'] == 'all') or \ + (name == self.data[key]['dev_info']['device_name'] and + ops['attr'] == self.data[key]['dev_attr']['index']): + return (True) + else: + return (False) + + def dump_sysfs_obj(self, obj, key_type): + if (key_type == 'keys'): + for key in obj.keys(): + print(key) + return + + for key in obj: + if (key == key_type or key_type == 'all'): + print(key+":") + for entry in obj[key]: + print("\t"+entry) + + def add_list_sysfs_obj(self, obj, KEY, list): + for sysfs in list: + if sysfs not in obj[KEY]: + obj[KEY].append(sysfs) + + def sysfs_attr(self, key, value, path, obj, obj_key): + sysfs_path = "/sys/kernel/%s/%s" % (path, key) + if sysfs_path not in obj[obj_key]: + obj[obj_key].append(sysfs_path) + + def sysfs_device(self, attr, path, obj, obj_key): + for key in attr.keys(): + sysfs_path = "/sys/kernel/%s/%s" % (path, key) + if sysfs_path not in obj[obj_key]: + obj[obj_key].append(sysfs_path) + + def show_eeprom_device(self, dev, ops): + return + + def show_mux_device(self, dev, ops): + KEY = 'mux' + if KEY not in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + self.sysfs_device(dev['i2c']['topo_info'], "pddf/devices/mux", self.sysfs_obj, KEY) + self.sysfs_device(dev['i2c']['dev_attr'], "pddf/devices/mux", self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/mux/dev_ops" + if sysfs_path not in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list = ['/sys/kernel/pddf/devices/mux/i2c_type', + '/sys/kernel/pddf/devices/mux/i2c_name', + '/sys/kernel/pddf/devices/mux/error'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + def show_gpio_device(self, dev, ops): + KEY = 'gpio' + if KEY not in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + self.sysfs_device(dev['i2c']['topo_info'], "pddf/devices/gpio", self.sysfs_obj, KEY) + self.sysfs_device(dev['i2c']['dev_attr'], "pddf/devices/gpio", self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/gpio/dev_ops" + if sysfs_path not in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list = ['/sys/kernel/pddf/devices/gpio/i2c_type', + '/sys/kernel/pddf/devices/gpio/i2c_name', + '/sys/kernel/pddf/devices/gpio/error'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + def show_psu_i2c_device(self, dev, ops): + KEY = 'psu' + path = 'pddf/devices/psu/i2c' + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PSU']: + if KEY not in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + self.sysfs_device(dev['i2c']['topo_info'], path, self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/psu/i2c/psu_idx" + self.sysfs_obj[KEY].append(sysfs_path) + + for attr in dev['i2c']['attr_list']: + self.sysfs_device(attr, "pddf/devices/psu/i2c", self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/psu/i2c/dev_ops" + if sysfs_path not in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list = ['/sys/kernel/pddf/devices/psu/i2c/i2c_type', + '/sys/kernel/pddf/devices/fan/i2c/i2c_name', + '/sys/kernel/pddf/devices/psu/i2c/error', + '/sys/kernel/pddf/devices/psu/i2c/attr_ops'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + def show_psu_device(self, dev, ops): + self.show_psu_i2c_device(dev, ops) + return + + def show_client_device(self): + KEY = 'client' + if KEY not in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + list = ['/sys/kernel/pddf/devices/showall'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + def show_fan_device(self, dev, ops): + KEY = 'fan' + path = 'pddf/devices/fan/i2c' + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['FAN']: + if KEY not in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + + self.sysfs_device(dev['i2c']['topo_info'], path, self.sysfs_obj, KEY) + self.sysfs_device(dev['i2c']['dev_attr'], path, self.sysfs_obj, KEY) + for attr in dev['i2c']['attr_list']: + self.sysfs_device(attr, path, self.sysfs_obj, KEY) + list = ['/sys/kernel/pddf/devices/fan/i2c/i2c_type', + '/sys/kernel/pddf/devices/fan/i2c/i2c_name', + '/sys/kernel/pddf/devices/fan/i2c/error', + '/sys/kernel/pddf/devices/fan/i2c/attr_ops', + '/sys/kernel/pddf/devices/fan/i2c/dev_ops'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + def show_temp_sensor_device(self, dev, ops): + return + + def show_sysstatus_device(self, dev, ops): + KEY = 'sysstatus' + if KEY not in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + for attr in dev['attr_list']: + self.sysfs_device(attr, "pddf/devices/sysstatus", self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/sysstatus/attr_ops" + if sysfs_path not in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + + def show_xcvr_i2c_device(self, dev, ops): + KEY = 'xcvr' + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PORT_MODULE']: + if KEY not in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + self.sysfs_device(dev['i2c']['topo_info'], "pddf/devices/xcvr/i2c", self.sysfs_obj, KEY) + + for attr in dev['i2c']['attr_list']: + self.sysfs_device(attr, "pddf/devices/xcvr/i2c", self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/xcvr/i2c/dev_ops" + if sysfs_path not in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list = ['/sys/kernel/pddf/devices/xcvr/i2c/i2c_type', + '/sys/kernel/pddf/devices/xcvr/i2c/i2c_name', + '/sys/kernel/pddf/devices/xcvr/i2c/error', + '/sys/kernel/pddf/devices/xcvr/i2c/attr_ops'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + def show_xcvr_device(self, dev, ops): + self.show_xcvr_i2c_device(dev, ops) + return + + def show_cpld_device(self, dev, ops): + KEY = 'cpld' + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['CPLD']: + if KEY not in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + self.sysfs_device(dev['i2c']['topo_info'], "pddf/devices/cpld", self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/cpld/dev_ops" + if sysfs_path not in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list = ['/sys/kernel/pddf/devices/cpld/i2c_type', + '/sys/kernel/pddf/devices/cpld/i2c_name', + '/sys/kernel/pddf/devices/cpld/error'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + def show_led_platform_device(self, key, ops): + if ops['attr'] == 'all' or ops['attr'] == 'PLATFORM': + KEY = 'platform' + if KEY not in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + path = 'pddf/devices/platform' + self.sysfs_attr('num_psus', self.data['PLATFORM']['num_psus'], path, self.sysfs_obj, KEY) + self.sysfs_attr('num_fantrays', self.data['PLATFORM']['num_fantrays'], path, self.sysfs_obj, KEY) + + def show_led_device(self, key, ops): + if self.check_led_cmds(key, ops): + KEY = 'led' + if KEY not in self.sysfs_obj: + self.sysfs_obj[KEY] = [] + path = "pddf/devices/led" + for attr in self.data[key]['i2c']['attr_list']: + self.sysfs_attr('device_name', self.data[key]['dev_info']['device_name'], path, self.sysfs_obj, KEY) + self.sysfs_attr('swpld_addr', self.data[key]['dev_info']['device_name'], path, self.sysfs_obj, KEY) + self.sysfs_attr('swpld_addr_offset', self.data[key]['dev_info']['device_name'], path, + self.sysfs_obj, KEY) + self.sysfs_device(self.data[key]['dev_attr'], path, self.sysfs_obj, KEY) + for attr_key in attr.keys(): + attr_path = "pddf/devices/led/" + attr['attr_name'] + if (attr_key != 'attr_name' and attr_key != 'swpld_addr' and attr_key != 'swpld_addr_offset'): + self.sysfs_attr(attr_key, attr[attr_key], attr_path, self.sysfs_obj, KEY) + sysfs_path = "/sys/kernel/pddf/devices/led/dev_ops" + if sysfs_path not in self.sysfs_obj[KEY]: + self.sysfs_obj[KEY].append(sysfs_path) + list = ['/sys/kernel/pddf/devices/led/cur_state/color', + '/sys/kernel/pddf/devices/led/cur_state/color_state'] + self.add_list_sysfs_obj(self.sysfs_obj, KEY, list) + + def validate_xcvr_device(self, dev, ops): + devtype_list = ['optoe1', 'optoe2'] + dev_attribs = ['xcvr_present', 'xcvr_reset', 'xcvr_intr_status', 'xcvr_lpmode'] + ret_val = "xcvr validation failed" + + if dev['i2c']['topo_info']['dev_type'] in devtype_list: + for attr in dev['i2c']['attr_list']: + if 'attr_name' in attr.keys() and 'eeprom' in attr.values(): + ret_val = "xcvr validation success" + else: + print("xcvr validation Failed") + return + + elif dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PORT_MODULE']: + for attr in dev['i2c']['attr_list']: + if attr.get("attr_name") in dev_attribs: + ret_val = "Success" + else: + print("xcvr validation Failed") + return + print(ret_val) + + def validate_eeprom_device(self, dev, ops): + devtype_list = ['24c02'] + dev_access_mode = ['BLOCK', 'BYTE'] + dev_attribs = ['eeprom'] + ret_val = "eeprom failed" + + if dev['i2c']['topo_info']['dev_type'] in devtype_list: + if dev['i2c']['dev_attr']['access_mode'] in dev_access_mode: + for attr in dev['i2c']['attr_list']: + if attr.get("attr_name") in dev_attribs: + ret_val = "eeprom success" + print(ret_val) + + def validate_mux_device(self, dev, ops): + devtype_list = ['pca9548', 'pca954x'] + dev_channels = ["0", "1", "2", "3", "4", "5", "6", "7"] + ret_val = "mux failed" + + if dev['i2c']['topo_info']['dev_type'] in devtype_list: + for attr in dev['i2c']['channel']: + if attr.get("chn") in dev_channels: + ret_val = "Mux success" + print(ret_val) + + def validate_cpld_device(self, dev, ops): + devtype_list = ['i2c_cpld'] + ret_val = "cpld failed" + + if dev['i2c']['topo_info']['dev_type'] in devtype_list: + ret_val = "cpld success" + print(ret_val) + + def validate_sysstatus_device(self, dev, ops): + dev_attribs = ['board_info', 'cpld1_version', 'power_module_status', 'system_reset5', + 'system_reset6', 'system_reset7', 'misc1', 'cpld2_version', 'cpld3_version' + ] + ret_val = "sysstatus failed" + + if dev['dev_info']['device_type'] == "SYSSTAT": + for attr in dev['attr_list']: + if attr.get("attr_name") in dev_attribs: + ret_val = "sysstatus success" + print(ret_val) + + def validate_temp_sensor_device(self, dev, ops): + devtype_list = ['lm75'] + dev_attribs = ['temp1_max', 'temp1_max_hyst', 'temp1_input'] + ret_val = "temp sensor failed" + + if dev['dev_info']['device_type'] == "TEMP_SENSOR": + if dev['i2c']['topo_info']['dev_type'] in devtype_list: + for attr in dev['i2c']['attr_list']: + if attr.get("attr_name") in dev_attribs: + ret_val = "tempsensor success" + print(ret_val) + + def validate_fan_device(self, dev, ops): + ret_val = "fan failed" + + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['FAN']: + if dev['i2c']['dev_attr']['num_fan'] is not None: + ret_val = "fan success" + + print(ret_val) + + def validate_psu_device(self, dev, ops): + dev_attribs = ['psu_present', 'psu_model_name', 'psu_power_good', 'psu_mfr_id', 'psu_serial_num', + 'psu_fan_dir', 'psu_v_out', 'psu_i_out', 'psu_p_out', 'psu_fan1_speed_rpm' + ] + ret_val = "psu failed" + + if dev['i2c']['topo_info']['dev_type'] in self.data['PLATFORM']['pddf_dev_types']['PSU']: + for attr in dev['i2c']['attr_list']: + if attr.get("attr_name") in dev_attribs: + if attr.get("attr_devaddr") is not None: + if attr.get("attr_offset") is not None: + if attr.get("attr_mask") is not None: + if attr.get("attr_len") is not None: + ret_val = "psu success" + else: + ret_val = "psu failed" + + print(ret_val) + + ################################################################################################################### + # SPYTEST + ################################################################################################################### + def verify_attr(self, key, attr, path): + node = "/sys/kernel/%s/%s" % (path, key) + try: + with open(node, 'r') as f: + status = f.read() + except IOError: + print("PDDF_VERIFY_ERR: IOError: node:%s key:%s" % (node, key)) + return + + status = status.rstrip("\n\r") + if attr[key] != status: + print("PDDF_VERIFY_ERR: node: %s switch:%s" % (node, status)) + + def verify_device(self, attr, path, ops): + for key in attr.keys(): + self.verify_attr(key, attr, path) + + def get_led_device(self, device_name): + self.create_attr('device_name', self.data[device_name]['dev_info']['device_name'], "pddf/devices/led") + self.create_attr('index', self.data[device_name]['dev_attr']['index'], "pddf/devices/led") + cmd = "echo 'verify' > /sys/kernel/pddf/devices/led/dev_ops" + self.runcmd(cmd) + + def validate_sysfs_creation(self, obj, validate_type): + dir = '/sys/kernel/pddf/devices/'+validate_type + if (os.path.exists(dir) or validate_type == 'client'): + for sysfs in obj[validate_type]: + if not os.path.exists(sysfs): + print("[SYSFS FILE] " + sysfs + ": does not exist") + else: + print("[SYSFS DIR] " + dir + ": does not exist") + + def validate_dsysfs_creation(self, obj, validate_type): + if validate_type in obj.keys(): + # There is a possibility that some components dont have any device-self.data attr + if not obj[validate_type]: + print("[SYSFS ATTR] for " + validate_type + ": empty") + else: + for sysfs in obj[validate_type]: + if not os.path.exists(sysfs): + print("[SYSFS FILE] " + sysfs + ": does not exist") + else: + print("[SYSFS DIR] " + dir + ": not configured") + + def verify_sysfs_data(self, verify_type): + if (verify_type == 'LED'): + for key in self.data.keys(): + if key != 'PLATFORM': + attr = self.data[key]['dev_info'] + if attr['device_type'] == 'LED': + self.get_led_device(key) + self.verify_attr('device_name', self.data[key]['dev_info'], "pddf/devices/led") + self.verify_attr('index', self.data[key]['dev_attr'], "pddf/devices/led") + for attr in self.data[key]['i2c']['attr_list']: + path = "pddf/devices/led/" + attr['attr_name'] + for entry in attr.keys(): + if (entry != 'attr_name' and entry != 'swpld_addr' and entry != 'swpld_addr_offset'): + self.verify_attr(entry, attr, path) + if (entry == 'swpld_addr' or entry == 'swpld_addr_offset'): + self.verify_attr(entry, attr, 'pddf/devices/led') + + def schema_validation(self, validate_type): + process_validate_type = 0 + for key in self.data.keys(): + if (key != 'PLATFORM'): + temp_obj = {} + schema_list = [] + try: + device_type = self.data[key]["dev_info"]["device_type"] + except Exception as e: + print("dev_info or device_type ERROR: " + key) + print(e) + + if validate_type == 'mismatch': + process_validate_type = 1 + device_type = "PSU" + schema_file = "/usr/local/bin/schema/FAN.schema" + schema_list.append(schema_file) + elif validate_type == 'missing': + process_validate_type = 1 + schema_file = "/usr/local/bin/schema/PLATFORM.schema" + schema_list.append(schema_file) + + elif validate_type == 'empty': + process_validate_type = 1 + if not device_type: + print("Empty device_type for " + key) + continue + elif (validate_type == 'all' or validate_type == device_type): + process_validate_type = 1 + if "bmc" in self.data[key].keys(): + schema_file = "/usr/local/bin/schema/"+device_type + "_BMC.schema" + schema_list.append(schema_file) + + if "i2c" in self.data[key].keys(): + schema_file = "/usr/local/bin/schema/"+device_type + ".schema" + schema_list.append(schema_file) + if device_type: + temp_obj[device_type] = self.data[key] + for schema_file in schema_list: + if (os.path.exists(schema_file)): + print("Validate " + schema_file + ";" + key) + json_data = json.dumps(temp_obj) + with open(schema_file, 'r') as f: + schema = json.load(f) + try: + validate(temp_obj, schema) + except Exception as e: + print("Validation ERROR: " + schema_file + ";" + key) + if validate_type == 'mismatch': + return + else: + print(e) + else: + print("ERROR Missing File: " + schema_file) + if not process_validate_type: + print("device_type: " + validate_type + " not configured") + + def modules_validation(self, validate_type): + kos = [] + supported_type = False + module_validation_status = [] + + if validate_type == "bmc": + kos = ['ipmi_devintf', 'ipmi_si', 'ipmi_msghandler'] + validate_type = 'ipmi' + else: + # generate the KOS list from pddf device JSON file + kos.extend(self.data['PLATFORM']['pddf_kos']) + + if 'custom_kos' in self.data['PLATFORM']: + kos.extend(self.data['PLATFORM']['custom_kos']) + + for mod in kos: + if validate_type in mod or validate_type == "pddf": + supported_type = True + cmd = "lsmod | grep " + mod + try: + subprocess.check_output(cmd, shell=True) + except Exception as e: + module_validation_status.append(mod) + if supported_type: + if module_validation_status: + module_validation_status.append(":ERROR not loaded") + print(str(module_validation_status)[1:-1]) + else: + print("Loaded") + else: + print(validate_type + " not configured") + + ################################################################################################################### + # PARSE DEFS + ################################################################################################################### + + def psu_parse(self, dev, ops): + parse_str = "" + ret = "" + for ifce in dev['i2c']['interface']: + ret = getattr(self, ops['cmd']+"_psu_device")(self.data[ifce['dev']], ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + print("{}_psu_device failed".format(ops['cmd'])) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str += ret + return parse_str + + def fan_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_fan_device")(dev, ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + print("{}_fan_device failed".format(ops['cmd'])) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str += ret + + return parse_str + + def temp_sensor_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_temp_sensor_device")(dev, ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + print("{}_temp_sensor_device failed".format(ops['cmd'])) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str += ret + + return parse_str + + def cpld_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_cpld_device")(dev, ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + print("{}_cpld_device failed".format(ops['cmd'])) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str += ret + + return parse_str + + def sysstatus_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_sysstatus_device")(dev, ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + print("{}_sysstatus_device failed".format(ops['cmd'])) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str += ret + + return parse_str + + def gpio_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_gpio_device")(dev, ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + print("{}_temp_sensor_device failed".format(ops['cmd'])) + return ret + else: + pass + else: + # in case of 'show_attr' functions + parse_str += ret + + return parse_str + + def mux_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_mux_device")(dev, ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + print("{}_mux_device() cmd failed".format(ops['cmd'])) + return ret + else: + pass + else: + parse_str += ret + + for ch in dev['i2c']['channel']: + ret = self.dev_parse(self.data[ch['dev']], ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + return ret + else: + pass + else: + parse_str += ret + return parse_str + + def mux_parse_reverse(self, dev, ops): + parse_str = "" + for ch in reversed(dev['i2c']['channel']): + ret = self.dev_parse(self.data[ch['dev']], ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + return ret + else: + pass + else: + parse_str += ret + + ret = getattr(self, ops['cmd']+"_mux_device")(dev, ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + print("{}_mux_device() cmd failed".format(ops['cmd'])) + return ret + else: + pass + else: + parse_str += ret + + return parse_str + + def eeprom_parse(self, dev, ops): + parse_str = "" + ret = getattr(self, ops['cmd']+"_eeprom_device")(dev, ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + print("{}_eeprom_device() cmd failed".format(ops['cmd'])) + return ret + else: + pass + else: + parse_str += ret + + return parse_str + + def optic_parse(self, dev, ops): + parse_str = "" + ret = "" + for ifce in dev['i2c']['interface']: + ret = getattr(self, ops['cmd']+"_xcvr_device")(self.data[ifce['dev']], ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + print("{}_eeprom_device() cmd failed".format(ops['cmd'])) + return ret + else: + pass + else: + parse_str += ret + return parse_str + + def cpu_parse(self, bus, ops): + parse_str = "" + for dev in bus['i2c']['CONTROLLERS']: + dev1 = self.data[dev['dev']] + for d in dev1['i2c']['DEVICES']: + ret = self.dev_parse(self.data[d['dev']], ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + return ret + else: + pass + else: + parse_str += ret + return parse_str + + def cpu_parse_reverse(self, bus, ops): + parse_str = "" + for dev in reversed(bus['i2c']['CONTROLLERS']): + dev1 = self.data[dev['dev']] + for d in dev1['i2c']['DEVICES']: + ret = self.dev_parse(self.data[d['dev']], ops) + if ret is not None: + if str(ret).isdigit(): + if ret != 0: + # in case if 'create' functions + return ret + else: + pass + else: + parse_str += ret + return parse_str + + def dev_parse(self, dev, ops): + attr = dev['dev_info'] + if attr['device_type'] == 'CPU': + if ops['cmd'] == 'delete': + return self.cpu_parse_reverse(dev, ops) + else: + return self.cpu_parse(dev, ops) + + if attr['device_type'] == 'EEPROM': + return self.eeprom_parse(dev, ops) + + if attr['device_type'] == 'MUX': + if ops['cmd'] == 'delete': + return self.mux_parse_reverse(dev, ops) + else: + return self.mux_parse(dev, ops) + + if attr['device_type'] == 'GPIO': + return self.gpio_parse(dev, ops) + + if attr['device_type'] == 'PSU': + return self.psu_parse(dev, ops) + + if attr['device_type'] == 'FAN': + return self.fan_parse(dev, ops) + + if attr['device_type'] == 'TEMP_SENSOR': + return self.temp_sensor_parse(dev, ops) + + if attr['device_type'] == 'SFP' or attr['device_type'] == 'QSFP' or \ + attr['device_type'] == 'SFP28' or attr['device_type'] == 'QSFP28' or \ + attr['device_type'] == 'QSFP-DD': + return self.optic_parse(dev, ops) + + if attr['device_type'] == 'CPLD': + return self.cpld_parse(dev, ops) + + if attr['device_type'] == 'SYSSTAT': + return self.sysstatus_parse(dev, ops) + + def is_supported_sysled_state(self, sysled_name, sysled_state): + if sysled_name not in self.data.keys(): + return False, "[FAILED] " + sysled_name + " is not configured" + for attr in self.data[sysled_name]['i2c']['attr_list']: + if attr['attr_name'] == sysled_state: + return True, "supported" + return False, "[FAILED]: Invalid color" + + def create_attr(self, key, value, path): + cmd = "echo '%s' > /sys/kernel/%s/%s" % (value, path, key) + self.runcmd(cmd) + + def create_led_platform_device(self, key, ops): + if ops['attr'] == 'all' or ops['attr'] == 'PLATFORM': + path = 'pddf/devices/platform' + self.create_attr('num_psus', self.data['PLATFORM']['num_psus'], path) + self.create_attr('num_fantrays', self.data['PLATFORM']['num_fantrays'], path) + + def create_led_device(self, key, ops): + if ops['attr'] == 'all' or ops['attr'] == self.data[key]['dev_info']['device_name']: + path = "pddf/devices/led" + for attr in self.data[key]['i2c']['attr_list']: + self.create_attr('device_name', self.data[key]['dev_info']['device_name'], path) + self.create_device(self.data[key]['dev_attr'], path, ops) + for attr_key in attr.keys(): + if (attr_key == 'swpld_addr_offset' or attr_key == 'swpld_addr'): + self.create_attr(attr_key, attr[attr_key], path) + elif (attr_key != 'attr_name' and attr_key != 'descr' and attr_key != 'attr_devtype' and + attr_key != 'attr_devname'): + state_path = path+'/state_attr' + self.create_attr(attr_key, attr[attr_key], state_path) + cmd = "echo '" + attr['attr_name']+"' > /sys/kernel/pddf/devices/led/dev_ops" + self.runcmd(cmd) + + def led_parse(self, ops): + getattr(self, ops['cmd']+"_led_platform_device")("PLATFORM", ops) + for key in self.data.keys(): + if key != 'PLATFORM' and 'dev_info' in self.data[key]: + attr = self.data[key]['dev_info'] + if attr['device_type'] == 'LED': + getattr(self, ops['cmd']+"_led_device")(key, ops) + + def get_device_list(self, list, type): + for key in self.data.keys(): + if key != 'PLATFORM' and 'dev_info' in self.data[key]: + attr = self.data[key]['dev_info'] + if attr['device_type'] == type: + list.append(self.data[key]) + + def create_pddf_devices(self): + self.led_parse({"cmd": "create", "target": "all", "attr": "all"}) + create_ret = 0 + create_ret = self.dev_parse(self.data['SYSTEM'], {"cmd": "create", "target": "all", "attr": "all"}) + if create_ret != 0: + return create_ret + if 'SYSSTATUS' in self.data: + create_ret = self.dev_parse(self.data['SYSSTATUS'], {"cmd": "create", "target": "all", "attr": "all"}) + if create_ret != 0: + return create_ret + + def delete_pddf_devices(self): + self.dev_parse(self.data['SYSTEM'], {"cmd": "delete", "target": "all", "attr": "all"}) + if 'SYSSTATUS' in self.data: + self.dev_parse(self.data['SYSSTATUS'], {"cmd": "delete", "target": "all", "attr": "all"}) + + def populate_pddf_sysfsobj(self): + self.dev_parse(self.data['SYSTEM'], {"cmd": "show", "target": "all", "attr": "all"}) + if 'SYSSTATUS' in self.data: + self.dev_parse(self.data['SYSSTATUS'], {"cmd": "show", "target": "all", "attr": "all"}) + self.led_parse({"cmd": "show", "target": "all", "attr": "all"}) + self.show_client_device() + + def cli_dump_dsysfs(self, component): + self.dev_parse(self.data['SYSTEM'], {"cmd": "show_attr", "target": "all", "attr": "all"}) + if 'SYSSTATUS' in self.data: + self.dev_parse(self.data['SYSSTATUS'], {"cmd": "show_attr", "target": "all", "attr": "all"}) + if component in self.data_sysfs_obj: + return self.data_sysfs_obj[component] + else: + return None + + def validate_pddf_devices(self, *args): + self.populate_pddf_sysfsobj() + v_ops = {'cmd': 'validate', 'target': 'all', 'attr': 'all'} + self.dev_parse(self.data['SYSTEM'], v_ops) + + ################################################################################################################### + # BMC APIs + ################################################################################################################### + def populate_bmc_cache_db(self, bmc_attr): + bmc_cmd = str(bmc_attr['bmc_cmd']).strip() + + o_list = subprocess.check_output(bmc_cmd, shell=True).strip().split('\n') + bmc_cache[bmc_cmd] = {} + bmc_cache[bmc_cmd]['time'] = time.time() + for entry in o_list: + name = entry.split()[0] + bmc_cache[bmc_cmd][name] = entry + + def non_raw_ipmi_get_request(self, bmc_attr): + bmc_db_update_time = 1 + value = 'N/A' + bmc_cmd = str(bmc_attr['bmc_cmd']).strip() + field_name = str(bmc_attr['field_name']).strip() + field_pos = int(bmc_attr['field_pos'])-1 + + if bmc_cmd not in bmc_cache: + self.populate_bmc_cache_db(bmc_attr) + else: + now = time.time() + if (int(now - bmc_cache[bmc_cmd]['time']) > bmc_db_update_time): + self.populate_bmc_cache_db(bmc_attr) + + try: + data = bmc_cache[bmc_cmd][field_name] + value = data.split()[field_pos] + except Exception as e: + pass + + if 'mult' in bmc_attr.keys() and not value.isalpha(): + if value.isalpha(): + value = 0.0 + value = float(value) * float(bmc_attr['mult']) + + return str(value) + + def raw_ipmi_get_request(self, bmc_attr): + value = 'N/A' + cmd = bmc_attr['bmc_cmd'] + " 2>/dev/null" + if bmc_attr['type'] == 'raw': + try: + value = subprocess.check_output(cmd, shell=True).strip() + except Exception as e: + pass + + if value != 'N/A': + value = str(int(value, 16)) + return value + + if bmc_attr['type'] == 'mask': + mask = int(bmc_attr['mask'].encode('utf-8'), 16) + try: + value = subprocess.check_output(cmd, shell=True).strip() + except Exception as e: + pass + + if value != 'N/A': + value = str(int(value, 16) & mask) + + return value + + if bmc_attr['type'] == 'ascii': + try: + value = subprocess.check_output(cmd, shell=True) + except Exception as e: + pass + + if value != 'N/A': + tmp = ''.join(chr(int(i, 16)) for i in value.split()) + tmp = "".join(i for i in str(tmp) if unicodedata.category(i)[0] != "C") + value = str(tmp) + + return (value) + + return value + + def bmc_get_cmd(self, bmc_attr): + if int(bmc_attr['raw']) == 1: + value = self.raw_ipmi_get_request(bmc_attr) + else: + value = self.non_raw_ipmi_get_request(bmc_attr) + return (value) + + def non_raw_ipmi_set_request(self, bmc_attr, val): + value = 'N/A' + # TODO: Implement it + return value + + def raw_ipmi_set_request(self, bmc_attr, val): + value = 'N/A' + # TODO: Implement this + return value + + def bmc_set_cmd(self, bmc_attr, val): + if int(bmc_attr['raw']) == 1: + value = self.raw_ipmi_set_request(bmc_attr, val) + else: + value = self.non_raw_ipmi_set_request(bmc_attr, val) + return (value) + + # bmc-based attr: return attr obj + # non-bmc-based attr: return empty obj + def check_bmc_based_attr(self, device_name, attr_name): + if device_name in self.data.keys(): + if "bmc" in self.data[device_name].keys() and 'ipmitool' in self.data[device_name]['bmc'].keys(): + attr_list = self.data[device_name]['bmc']['ipmitool']['attr_list'] + for attr in attr_list: + if attr['attr_name'].strip() == attr_name.strip(): + return attr + # Required attr_name is not supported in BMC object + return {} + return None + + def get_attr_name_output(self, device_name, attr_name): + bmc_attr = self.check_bmc_based_attr(device_name, attr_name) + output = {"mode": "", "status": ""} + + if bmc_attr is not None: + if bmc_attr == {}: + return {} + output['mode'] = "bmc" + output['status'] = self.bmc_get_cmd(bmc_attr) + else: + output['mode'] = "i2c" + node = self.get_path(device_name, attr_name) + if node is None: + return {} + try: + with open(node, 'r') as f: + output['status'] = f.read() + except IOError: + return {} + return output + + def set_attr_name_output(self, device_name, attr_name, val): + bmc_attr = self.check_bmc_based_attr(device_name, attr_name) + output = {"mode": "", "status": ""} + + if bmc_attr is not None: + if bmc_attr == {}: + return {} + output['mode'] = "bmc" + output['status'] = False # No set operation allowed for BMC attributes as they are handled by BMC itself + else: + output['mode'] = "i2c" + node = self.get_path(device_name, attr_name) + if node is None: + return {} + try: + with open(node, 'w') as f: + f.write(str(val)) + except IOError: + return {} + + output['status'] = True + + return output diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_ref/__init__.py b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/__init__.py new file mode 100644 index 000000000000..d9a604cf816e --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/__init__.py @@ -0,0 +1,7 @@ +# All the derived classes for PDDF +__all__ = ["platform", "chassis", "sfp", "psu", "thermal"] + +# Commenting the below code as this just for the reference for the ODMs. +# It can be uncommented when this reference code is used + +#from sonic_platform import * diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_ref/chassis.py b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/chassis.py new file mode 100644 index 000000000000..72f1858a776c --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/chassis.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# PDDF +# Module contains an implementation of SONiC Chassis API +# +############################################################################# + +try: + from sonic_platform_pddf_base.pddf_chassis import PddfChassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Chassis(PddfChassis): + """ + PDDF Platform-specific Chassis class + """ + + def __init__(self, pddf_data=None, pddf_plugin_data=None): + PddfChassis.__init__(self, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_ref/eeprom.py b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/eeprom.py new file mode 100644 index 000000000000..c25d711354f5 --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/eeprom.py @@ -0,0 +1,12 @@ +try: + from sonic_platform_pddf_base.pddf_eeprom import PddfEeprom +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Eeprom(PddfEeprom): + + def __init__(self, pddf_data=None, pddf_plugin_data=None): + PddfEeprom.__init__(self, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_ref/fan.py b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/fan.py new file mode 100644 index 000000000000..027a2f4a6148 --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/fan.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + + +try: + from sonic_platform_pddf_base.pddf_fan import PddfFan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Fan(PddfFan): + """PDDF Platform-Specific Fan class""" + + def __init__(self, tray_idx, fan_idx=0, pddf_data=None, pddf_plugin_data=None, is_psu_fan=False, psu_index=0): + # idx is 0-based + PddfFan.__init__(self, tray_idx, fan_idx, pddf_data, pddf_plugin_data, is_psu_fan, psu_index) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_ref/platform.py b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/platform.py new file mode 100644 index 000000000000..406b1179ae1b --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/platform.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +############################################################################# +# PDDF +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + + +try: + from sonic_platform_pddf_base.pddf_platform import PddfPlatform +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PddfPlatform): + """ + PDDF Platform-Specific Platform Class + """ + + def __init__(self): + PddfPlatform.__init__(self) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_ref/psu.py b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/psu.py new file mode 100644 index 000000000000..edd747e9963b --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/psu.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + + +try: + from sonic_platform_pddf_base.pddf_psu import PddfPsu +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +class Psu(PddfPsu): + """PDDF Platform-Specific PSU class""" + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + PddfPsu.__init__(self, index, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_ref/sfp.py b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/sfp.py new file mode 100644 index 000000000000..9588db53283c --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/sfp.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +try: + from sonic_platform_pddf_base.pddf_sfp import PddfSfp +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class Sfp(PddfSfp): + """ + PDDF Platform-Specific Sfp class + """ + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + PddfSfp.__init__(self, index, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_ref/thermal.py b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/thermal.py new file mode 100644 index 000000000000..5b829fc26caa --- /dev/null +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_ref/thermal.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + + +try: + from sonic_platform_pddf_base.pddf_thermal import PddfThermal +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + + +class Thermal(PddfThermal): + """PDDF Platform-Specific Thermal class""" + + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): + PddfThermal.__init__(self, index, pddf_data, pddf_plugin_data) + + # Provide the functions/variables below for which implementation is to be overwritten diff --git a/platform/pddf/platform-modules-pddf.dep b/platform/pddf/platform-modules-pddf.dep new file mode 100644 index 000000000000..19a4bb344759 --- /dev/null +++ b/platform/pddf/platform-modules-pddf.dep @@ -0,0 +1,10 @@ + +MPATH := $($(PDDF_PLATFORM_MODULE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/pddf/platform-modules-pddf.mk platform/pddf/platform-modules-pddf.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(MPATH)) + +$(PDDF_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA +$(PDDF_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(PDDF_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/pddf/platform-modules-pddf.mk b/platform/pddf/platform-modules-pddf.mk new file mode 100644 index 000000000000..5947c1806565 --- /dev/null +++ b/platform/pddf/platform-modules-pddf.mk @@ -0,0 +1,12 @@ +# PDDF Generic Platform modules +#################################################### +PDDF_PLATFORM_MODULE_VERSION = 1.1 + +export PDDF_PLATFORM_MODULE_VERSION + +PDDF_PLATFORM_MODULE = sonic-platform-pddf_$(PDDF_PLATFORM_MODULE_VERSION)_amd64.deb +$(PDDF_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PDDF_PATH)/i2c +$(PDDF_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_DPKG_DEBS += $(PDDF_PLATFORM_MODULE) + +SONIC_STRETCH_DEBS += $(PDDF_PLATFORM_MODULE) diff --git a/platform/pddf/rules.dep b/platform/pddf/rules.dep new file mode 100644 index 000000000000..de40f6e88c2f --- /dev/null +++ b/platform/pddf/rules.dep @@ -0,0 +1,3 @@ +#DPKG FRK +include $(PLATFORM_PDDF_PATH)/platform-modules-pddf.dep +include $(PLATFORM_PDDF_PATH)/platform-api-pddf-base.dep diff --git a/platform/pddf/rules.mk b/platform/pddf/rules.mk new file mode 100644 index 000000000000..6c2fdfb89b58 --- /dev/null +++ b/platform/pddf/rules.mk @@ -0,0 +1,3 @@ +include $(PLATFORM_PDDF_PATH)/platform-modules-pddf.mk +include $(PLATFORM_PDDF_PATH)/platform-api-pddf-base.mk + diff --git a/platform/template/docker-gbsyncd-base.mk b/platform/template/docker-gbsyncd-base.mk new file mode 100644 index 000000000000..aa4f574141b2 --- /dev/null +++ b/platform/template/docker-gbsyncd-base.mk @@ -0,0 +1,30 @@ +# docker image for gbsyncd + + +DOCKER_GBSYNCD_BASE_STEM = docker-gbsyncd-$(DOCKER_GBSYNCD_PLATFORM_CODE) +DOCKER_GBSYNCD_BASE = $(DOCKER_GBSYNCD_BASE_STEM).gz +DOCKER_GBSYNCD_BASE_DBG = $(DOCKER_GBSYNCD_BASE_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_GBSYNCD_BASE)_PATH = $(PLATFORM_PATH)/docker-gbsyncd-$(DOCKER_GBSYNCD_PLATFORM_CODE) + +$(DOCKER_GBSYNCD_BASE)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) + +$(DOCKER_GBSYNCD_BASE)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +$(DOCKER_GBSYNCD_BASE)_DBG_DEPENDS += $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) + +$(DOCKER_GBSYNCD_BASE)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +SONIC_DOCKER_IMAGES += $(DOCKER_GBSYNCD_BASE) +SONIC_BUSTER_DOCKERS += $(DOCKER_GBSYNCD_BASE) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_GBSYNCD_BASE) + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_GBSYNCD_BASE_DBG) +SONIC_BUSTER_DBG_DOCKERS += $(DOCKER_GBSYNCD_BASE_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_GBSYNCD_BASE_DBG) + +$(DOCKER_GBSYNCD_BASE)_CONTAINER_NAME = gbsyncd +$(DOCKER_GBSYNCD_BASE)_RUN_OPT += --net=host --privileged -t +$(DOCKER_GBSYNCD_BASE)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_GBSYNCD_BASE)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + diff --git a/platform/template/docker-syncd-base.mk b/platform/template/docker-syncd-base.mk new file mode 100644 index 000000000000..d95d7a141920 --- /dev/null +++ b/platform/template/docker-syncd-base.mk @@ -0,0 +1,40 @@ +# docker image for syncd + + +DOCKER_SYNCD_BASE_STEM = docker-syncd-$(DOCKER_SYNCD_PLATFORM_CODE) +DOCKER_SYNCD_BASE = $(DOCKER_SYNCD_BASE_STEM).gz +DOCKER_SYNCD_BASE_DBG = $(DOCKER_SYNCD_BASE_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_SYNCD_BASE)_PATH = $(PLATFORM_PATH)/docker-syncd-$(DOCKER_SYNCD_PLATFORM_CODE) + +$(DOCKER_SYNCD_BASE)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) + +ifeq ($(BLDENV),stretch) +$(DOCKER_SYNCD_BASE)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_STRETCH) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $($(DOCKER_CONFIG_ENGINE_STRETCH)_DBG_DEPENDS) + +$(DOCKER_SYNCD_BASE)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_STRETCH)_DBG_IMAGE_PACKAGES) +else +$(DOCKER_SYNCD_BASE)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) + +$(DOCKER_SYNCD_BASE)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) +endif + +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_BASE) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_BASE) +endif + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_SYNCD_BASE_DBG) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_SYNCD_BASE_DBG) +endif + +$(DOCKER_SYNCD_BASE)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_BASE)_RUN_OPT += --privileged -t +$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + diff --git a/platform/vs/README.gns3.md b/platform/vs/README.gns3.md new file mode 100644 index 000000000000..c434d5e9b405 --- /dev/null +++ b/platform/vs/README.gns3.md @@ -0,0 +1,17 @@ +HOWTO Create a GNS3 Appliance File (.gns3a) + + +Execute the command sonic-gns3.sh + + +For instance: + +./sonic-gns3a.sh -h + +sonic-gns3a.sh [ -r ] -b +e.g.: sonic-gns3a.sh -r 1.1 -b /sonic-vs.img + +For more information about GNS3, please refer to: + +https://gns3.com/ + diff --git a/platform/vs/README.vsdocker.md b/platform/vs/README.vsdocker.md new file mode 100644 index 000000000000..694631f095db --- /dev/null +++ b/platform/vs/README.vsdocker.md @@ -0,0 +1,47 @@ +HOWTO Use Virtual Switch (Docker) + + +1. Create a docker with two front panel ports + +``` +$ docker run -id --name sw debian bash +$ sudo ./create_vnet.sh -n 2 sw +$ ip netns list +sw-srv1 (id: 6) +sw-srv0 (id: 5) +``` + +2. Start sonic virtual switch docker + +``` +$ docker run --privileged --network container:sw --name vs -d docker-sonic-vs +``` + +3. Setup IP in the virtual switch docker + +``` +$ docker exec -it vs bash +root@2e9b5c2dc2a2:/# config interface ip add Ethernet0 10.0.0.0/31 +root@2e9b5c2dc2a2:/# config interface ip add Ethernet4 10.0.0.2/31 +root@2e9b5c2dc2a2:/# config interface startup Ethernet0 +root@2e9b5c2dc2a2:/# config interface startup Ethernet4 +``` + +4. Setup IP in the server network namespace + +``` +$ sudo ip netns exec sw-srv0 ifconfig eth0 10.0.0.1/31 +$ sudo ip netns exec sw-srv0 ip route add default via 10.0.0.0 +$ sudo ip netns exec sw-srv1 ifconfig eth0 10.0.0.3/31 +$ sudo ip netns exec sw-srv1 ip route add default via 10.0.0.2 +``` + +5. Ping from sw-srv0 to sw-srv1 + +``` +$ sudo ip netns exec sw-srv0 ping 10.0.0.3 +PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data. +64 bytes from 10.0.0.3: icmp_seq=1 ttl=63 time=0.137 ms +64 bytes from 10.0.0.3: icmp_seq=2 ttl=63 time=0.148 ms +64 bytes from 10.0.0.3: icmp_seq=3 ttl=63 time=0.149 ms +``` diff --git a/platform/vs/README.vsvm.md b/platform/vs/README.vsvm.md new file mode 100644 index 000000000000..68f7d0244017 --- /dev/null +++ b/platform/vs/README.vsvm.md @@ -0,0 +1,75 @@ +HOWTO Use Virtual Switch (VM) + +1. Install libvirt, kvm, qemu + +``` +sudo apt-get install libvirt-clients qemu-kvm libvirt-bin +``` + +2. Create SONiC VM for single ASIC HWSKU + +``` +$ sudo virsh +Welcome to virsh, the virtualization interactive terminal. + +Type: 'help' for help with commands + 'quit' to quit + +virsh # +virsh # create sonic.xml +Domain sonic created from sonic.xml + +virsh # +``` + +2. Create SONiC VM for multi-ASIC HWSKU +Update sonic_multiasic.xml with the external interfaces +required for HWSKU. + +``` +$ sudo virsh +Welcome to virsh, the virtualization interactive terminal. + +Type: 'help' for help with commands + 'quit' to quit + +virsh # +virsh # create sonic_multiasic.xml +Domain sonic created from sonic.xml + +virsh # + +Once booted up, create a file "asic.conf" with the content: +NUM_ASIC= +under /usr/share/sonic/device/x86_64-kvm_x86_64-r0/ +Also, create a "topology.sh" file which will simulate the internal +asic connectivity of the hardware under +/usr/share/sonic/device/x86_64-kvm_x86_64-r0/ +The HWSKU directory will have the required files like port_config.ini +for each ASIC. + +Having done this, a new service "topology.service" will be started +during bootup which will invoke topology.sh script. + +3. Access virtual switch: + + 1. Connect SONiC VM via console + ``` + $ telnet 127.0.0.1 7000 + ``` + + OR + + 2. Connect SONiC VM via SSH + + 1. Connect via console (see 3.1 above) + + 2. Request a new DHCP address + ``` + sudo dhclient -v + ``` + + 3. Connect via SSH + ``` + $ ssh -p 3040 admin@127.0.0.1 + ``` diff --git a/platform/vs/create_vnet.sh b/platform/vs/create_vnet.sh new file mode 100755 index 000000000000..2217bbbd0220 --- /dev/null +++ b/platform/vs/create_vnet.sh @@ -0,0 +1,58 @@ +#!/bin/bash -e + +usage() { + echo "Usage: $0 [-n ] swname" 1>&2 + exit 1 +} + +SERVERS=2 + +while getopts ":n:" opt; do + case $opt in + n) + SERVERS=$((OPTARG)) + ;; + *) + usage + ;; + esac +done + +shift $((OPTIND-1)) + +SWNAME=$1 + +pid=$(docker inspect --format '{{.State.Pid}}' $SWNAME) + +echo Seting up servers + + +for srv in `seq 0 $((SERVERS-1))`; do + + SRV="$SWNAME-srv$srv" + + NSS="ip netns exec $SRV" + + ip netns add $SRV + + $NSS ip addr add 127.0.0.1/8 dev lo + $NSS ip addr add ::1/128 dev lo + $NSS ip link set dev lo up + + # add virtual link between neighbor and the virtual switch docker + + IF="eth$((srv+1))" + + ip link add ${SRV}eth0 type veth peer name $SWNAME-$IF + ip link set ${SRV}eth0 netns $SRV + ip link set $SWNAME-$IF netns ${pid} + nsenter -t $pid -n ip link set dev $SWNAME-$IF name $IF + + echo "Bring ${SRV}eth0 up" + $NSS ip link set dev ${SRV}eth0 name eth0 + $NSS ip link set dev eth0 up + + echo "Bring $IF up in the virtual switch docker" + nsenter -t $pid -n ip link set dev $IF up + +done diff --git a/platform/vs/docker-gbsyncd-vs.dep b/platform/vs/docker-gbsyncd-vs.dep new file mode 100644 index 000000000000..a3db18642abf --- /dev/null +++ b/platform/vs/docker-gbsyncd-vs.dep @@ -0,0 +1,11 @@ +#DPKG FRK +DPATH := $($(DOCKER_GBSYNCD_BASE)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/vs/docker-gbsyncd-vs.mk platform/vs/docker-gbsyncd-vs.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_GBSYNCD_BASE)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_GBSYNCD_BASE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_GBSYNCD_BASE)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_GBSYNCD_BASE),$(DOCKER_GBSYNCD_BASE_DBG))) diff --git a/platform/vs/docker-gbsyncd-vs.mk b/platform/vs/docker-gbsyncd-vs.mk new file mode 100644 index 000000000000..2013132d6281 --- /dev/null +++ b/platform/vs/docker-gbsyncd-vs.mk @@ -0,0 +1,14 @@ +# docker image for vs gbsyncd + +DOCKER_GBSYNCD_PLATFORM_CODE = vs +include $(PLATFORM_PATH)/../template/docker-gbsyncd-base.mk + +$(DOCKER_GBSYNCD_BASE)_DEPENDS += $(SYNCD_VS) + +$(DOCKER_GBSYNCD_BASE)_DBG_DEPENDS += $(SYNCD_VS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) \ + $(LIBSAIVS_DBG) + +$(DOCKER_GBSYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/vs/docker-gbsyncd-vs/Dockerfile.j2 b/platform/vs/docker-gbsyncd-vs/Dockerfile.j2 new file mode 100644 index 000000000000..ae7e1c99b7c0 --- /dev/null +++ b/platform/vs/docker-gbsyncd-vs/Dockerfile.j2 @@ -0,0 +1,34 @@ +FROM docker-config-engine-buster + +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 + +RUN apt-get install -f -y iproute2 libcap2-bin + +COPY \ +{% for deb in docker_gbsyncd_vs_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_gbsyncd_vs_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/vs/docker-gbsyncd-vs/critical_processes b/platform/vs/docker-gbsyncd-vs/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/vs/docker-gbsyncd-vs/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/platform/vs/docker-gbsyncd-vs/start.sh b/platform/vs/docker-gbsyncd-vs/start.sh new file mode 100755 index 000000000000..e59a2322bbf8 --- /dev/null +++ b/platform/vs/docker-gbsyncd-vs/start.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +HWSKU_DIR=/usr/share/sonic/hwsku + +mkdir -p /etc/sai.d/ + +# Create/Copy the pai.profile to /etc/sai.d/pai.profile +if [ -f $HWSKU_DIR/pai.profile.j2 ]; then + sonic-cfggen -d -t $HWSKU_DIR/pai.profile.j2 > /etc/sai.d/pai.profile +else + if [ -f $HWSKU_DIR/pai.profile ]; then + cp $HWSKU_DIR/pai.profile /etc/sai.d/pai.profile + fi +fi + +# Create/Copy the gearbox configs to /etc/sai.d +if [[ x"$sonic_asic_platform" == x"broadcom" ]]; then + if [ -d $HWSKU_DIR/gearbox ]; then + cp $HWSKU_DIR/gearbox/*.bcm /etc/sai.d/. + fi +fi diff --git a/platform/vs/docker-gbsyncd-vs/supervisord.conf b/platform/vs/docker-gbsyncd-vs/supervisord.conf new file mode 100644 index 000000000000..52267c8fa58f --- /dev/null +++ b/platform/vs/docker-gbsyncd-vs/supervisord.conf @@ -0,0 +1,48 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name gbsyncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:syncd] +command=/usr/bin/gbsyncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited diff --git a/platform/vs/docker-ptf.dep b/platform/vs/docker-ptf.dep new file mode 100644 index 000000000000..8cd9f7b7a279 --- /dev/null +++ b/platform/vs/docker-ptf.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_PTF)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/vs/docker-ptf.mk platform/vs/docker-ptf.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_PTF)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_PTF)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_PTF)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/vs/docker-ptf.mk b/platform/vs/docker-ptf.mk new file mode 100644 index 000000000000..4fde844fe24b --- /dev/null +++ b/platform/vs/docker-ptf.mk @@ -0,0 +1,7 @@ +# docker image for docker-ptf + +DOCKER_PTF = docker-ptf.gz +$(DOCKER_PTF)_PATH = $(DOCKERS_PATH)/docker-ptf +$(DOCKER_PTF)_DEPENDS += $(LIBTHRIFT) $(PYTHON_THRIFT) $(PTF) $(PYTHON_SAITHRIFT) +SONIC_DOCKER_IMAGES += $(DOCKER_PTF) +SONIC_STRETCH_DOCKERS += $(DOCKER_PTF) diff --git a/platform/vs/docker-sonic-vs.dep b/platform/vs/docker-sonic-vs.dep new file mode 100644 index 000000000000..d544423171dc --- /dev/null +++ b/platform/vs/docker-sonic-vs.dep @@ -0,0 +1,10 @@ +#DPKG FRK +DPATH := $($(DOCKER_SONIC_VS)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/vs/docker-sonic-vs.mk platform/vs/docker-sonic-vs.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_SONIC_VS)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SONIC_VS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SONIC_VS)_DEP_FILES := $(DEP_FILES) + diff --git a/platform/vs/docker-sonic-vs.mk b/platform/vs/docker-sonic-vs.mk new file mode 100644 index 000000000000..c48c8f12c704 --- /dev/null +++ b/platform/vs/docker-sonic-vs.mk @@ -0,0 +1,55 @@ +# docker image for virtual switch based sonic docker image + +DOCKER_SONIC_VS = docker-sonic-vs.gz +$(DOCKER_SONIC_VS)_PATH = $(PLATFORM_PATH)/docker-sonic-vs +$(DOCKER_SONIC_VS)_DEPENDS += $(SWSS) \ + $(SYNCD_VS) \ + $(PYTHON_SWSSCOMMON) \ + $(PYTHON3_SWSSCOMMON) \ + $(LIBTEAMDCTL) \ + $(LIBTEAM_UTILS) \ + $(SONIC_DEVICE_DATA) \ + $(LIBYANG) \ + $(LIBYANG_CPP) \ + $(LIBYANG_PY2) \ + $(LIBYANG_PY3) \ + $(SONIC_UTILITIES_DATA) \ + $(SONIC_HOST_SERVICES_DATA) + +# swsssdk is a dependency of sonic-py-common +# TODO: sonic-py-common should depend on swsscommon instead +$(DOCKER_SONIC_VS)_PYTHON_WHEELS += $(SWSSSDK_PY3) \ + $(SONIC_PY_COMMON_PY3) \ + $(SONIC_PLATFORM_COMMON_PY3) \ + $(SONIC_YANG_MODELS_PY3) \ + $(SONIC_YANG_MGMT_PY3) \ + $(SONIC_UTILITIES_PY3) \ + $(SONIC_HOST_SERVICES_PY3) + +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SONIC_VS)_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) \ + $(LIBSAIVS_DBG) \ + $(SYNCD_VS_DBG) +endif + +ifeq ($(SONIC_ROUTING_STACK), quagga) +$(DOCKER_SONIC_VS)_DEPENDS += $(QUAGGA) +else ifeq ($(SONIC_ROUTING_STACK), frr) +$(DOCKER_SONIC_VS)_DEPENDS += $(FRR) +else +$(DOCKER_SONIC_VS)_DEPENDS += $(GOBGP) +endif + +$(DOCKER_SONIC_VS)_FILES += $(CONFIGDB_LOAD_SCRIPT) \ + $(ARP_UPDATE_SCRIPT) \ + $(ARP_UPDATE_VARS_TEMPLATE) \ + $(BUFFERS_CONFIG_TEMPLATE) \ + $(QOS_CONFIG_TEMPLATE) \ + $(SONIC_VERSION) \ + $(UPDATE_CHASSISDB_CONFIG_SCRIPT) \ + $(COPP_CONFIG_TEMPLATE) + +$(DOCKER_SONIC_VS)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) +SONIC_DOCKER_IMAGES += $(DOCKER_SONIC_VS) diff --git a/platform/vs/docker-sonic-vs/50-default.conf b/platform/vs/docker-sonic-vs/50-default.conf new file mode 100644 index 000000000000..d672d83af789 --- /dev/null +++ b/platform/vs/docker-sonic-vs/50-default.conf @@ -0,0 +1,68 @@ +# Default rules for rsyslog. +# +# For more information see rsyslog.conf(5) and /etc/rsyslog.conf + +# +# First some standard log files. Log by facility. +# +auth,authpriv.* /var/log/auth.log +*.*;auth,authpriv.none -/var/log/syslog +#cron.* /var/log/cron.log +#daemon.* -/var/log/daemon.log +kern.* -/var/log/kern.log +#lpr.* -/var/log/lpr.log +mail.* -/var/log/mail.log +#user.* -/var/log/user.log + +# +# Logging for the mail system. Split it up so that +# it is easy to write scripts to parse these files. +# +#mail.info -/var/log/mail.info +#mail.warn -/var/log/mail.warn +mail.err /var/log/mail.err + +# +# Logging for INN news system. +# +news.crit /var/log/news/news.crit +news.err /var/log/news/news.err +news.notice -/var/log/news/news.notice + +# +# Some "catch-all" log files. +# +#*.=debug;\ +# auth,authpriv.none;\ +# news.none;mail.none -/var/log/debug +#*.=info;*.=notice;*.=warn;\ +# auth,authpriv.none;\ +# cron,daemon.none;\ +# mail,news.none -/var/log/messages + +# +# Emergencies are sent to everybody logged in. +# +*.emerg :omusrmsg:* + +# +# I like to have messages displayed on the console, but only on a virtual +# console I usually leave idle. +# +#daemon,mail.*;\ +# news.=crit;news.=err;news.=notice;\ +# *.=debug;*.=info;\ +# *.=notice;*.=warn /dev/tty8 + +# The named pipe /dev/xconsole is for the `xconsole' utility. To use it, +# you must invoke `xconsole' with the `-file' option: +# +# $ xconsole -file /dev/xconsole [...] +# +# NOTE: adjust the list below, or you'll go crazy if you have a reasonably +# busy site.. +# +daemon.*;mail.*;\ + news.err;\ + *.=debug;*.=info;\ + *.=notice;*.=warn |/dev/xconsole diff --git a/platform/vs/docker-sonic-vs/Dockerfile.j2 b/platform/vs/docker-sonic-vs/Dockerfile.j2 new file mode 100644 index 000000000000..4313d84a237d --- /dev/null +++ b/platform/vs/docker-sonic-vs/Dockerfile.j2 @@ -0,0 +1,195 @@ +FROM docker-config-engine-buster + +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 install -y gnupg +COPY ["sonic-dev.gpg.key", "/etc/apt/"] +RUN apt-key add /etc/apt/sonic-dev.gpg.key +RUN echo "deb http://packages.microsoft.com/repos/sonic-dev/ jessie main" >> /etc/apt/sources.list +RUN apt-get update + +RUN apt-get install -y net-tools \ + arping \ + ndisc6 \ + ethtool \ + tcpdump \ + ifupdown \ + bridge-utils \ + python-ply \ + libqt5core5a \ + libqt5network5 \ + libboost-program-options1.71.0 \ + libboost-system1.71.0 \ + libboost-thread1.71.0 \ + libgmp10 \ + libjudydebian1 \ + openssh-client \ + openssh-server \ + libc-ares2 \ + iproute2 \ + grub2-common \ + bash-completion \ + libelf1 \ + libmnl0 \ + logrotate \ + apt-utils \ + psmisc \ + tcpdump \ + python-scapy \ + conntrack \ + iptables \ + jq \ + libzmq5 \ + # For installing Python m2crypto package + # (these can be uninstalled after installation) + build-essential \ + python-dev \ + python-pip \ + python3-dev \ + libssl-dev \ + swig \ + # For using Python m2crypto package + openssl \ + # For installing dependent Python packages of sonic-host-services + # (these can be uninstalled after installation) + libcairo2-dev \ + libdbus-1-dev \ + libgirepository1.0-dev \ + libsystemd-dev \ + pkg-config \ + # For installing dependent Python packages of sonic-host-services + # these packages are needed at runtime + gir1.2-glib-2.0 \ + libdbus-1-3 \ + libgirepository-1.0-1 \ + libsystemd0 + +# Install redis-server +{% if CONFIGURED_ARCH == "armhf" %} +RUN curl -k -o redis-tools_6.0.6-1~bpo10+1_armhf.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1_bpo10+1_armhf.deb?sv=2015-04-05&sr=b&sig=67vHAMxsl%2BS3X1KsqhdYhakJkGdg5FKSPgU8kUiw4as%3D&se=2030-10-24T04%3A22%3A40Z&sp=r" +RUN curl -k -o redis-server_6.0.6-1~bpo10+1_armhf.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-server_6.0.6-1_bpo10+1_armhf.deb?sv=2015-04-05&sr=b&sig=xTdayvm0RBguxi9suyv855jKRjU%2FmKQ8nHuct4WSX%2FA%3D&se=2030-10-24T04%3A22%3A05Z&sp=r" +RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_armhf.deb redis-server_6.0.6-1~bpo10+1_armhf.deb || apt-get install -f +RUN rm redis-tools_6.0.6-1~bpo10+1_armhf.deb redis-server_6.0.6-1~bpo10+1_armhf.deb +{% elif CONFIGURED_ARCH == "arm64" %} +RUN curl -o redis-tools_6.0.6-1~bpo10+1_arm64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1_bpo10+1_arm64.deb?sv=2015-04-05&sr=b&sig=GbkJV2wWln3hoz27zKi5erdk3NDKrAFrQriA97bcRCY%3D&se=2030-10-24T04%3A22%3A21Z&sp=r" +RUN curl -o redis-server_6.0.6-1~bpo10+1_arm64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-server_6.0.6-1_bpo10+1_arm64.deb?sv=2015-04-05&sr=b&sig=622w2KzIKIjAaaA0Bz12MzU%2BUBzY2AiXFIFfuKNoKSk%3D&se=2030-10-24T04%3A21%3A44Z&sp=r" +RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_arm64.deb redis-server_6.0.6-1~bpo10+1_arm64.deb || apt-get install -f +RUN rm redis-tools_6.0.6-1~bpo10+1_arm64.deb redis-server_6.0.6-1~bpo10+1_arm64.deb +{% else %} +RUN curl -o redis-tools_6.0.6-1~bpo10+1_amd64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-tools_6.0.6-1~bpo10+1_amd64.deb?sv=2015-04-05&sr=b&sig=73zbmjkf3pi%2Bn0R8Hy7CWT2EUvOAyzM5aLYJWCLySGM%3D&se=2030-09-06T19%3A44%3A59Z&sp=r" +RUN curl -o redis-server_6.0.6-1~bpo10+1_amd64.deb "https://sonicstorage.blob.core.windows.net/packages/redis/redis-server_6.0.6-1~bpo10+1_amd64.deb?sv=2015-04-05&sr=b&sig=2Ketg7BmkZEaTxR%2FgvAFVmhjn7ywdmkc7l2T2rsL57o%3D&se=2030-09-06T19%3A45%3A20Z&sp=r" +RUN dpkg -i redis-tools_6.0.6-1~bpo10+1_amd64.deb redis-server_6.0.6-1~bpo10+1_amd64.deb || apt-get install -f +RUN rm redis-tools_6.0.6-1~bpo10+1_amd64.deb redis-server_6.0.6-1~bpo10+1_amd64.deb +{% endif %} + +RUN pip2 install --upgrade 'pip<21' +RUN apt-get purge -y python-pip +RUN pip2 install setuptools==40.8.0 +RUN pip2 install wheel==0.33.6 +RUN pip2 install py2_ipaddress +RUN pip2 install six +RUN pip2 install pyroute2==0.5.3 netifaces==0.10.7 +RUN pip2 install monotonic==1.5 +RUN pip2 install urllib3 +RUN pip2 install requests +RUN pip2 install crontab + +# For sonic-config-engine Python 3 package +# Install pyangbind here, outside sonic-config-engine dependencies, as pyangbind causes enum34 to be installed. +# Then immediately uninstall enum34, as enum34 should not be installed for Python >= 3.4, as it causes a +# conflict with the new 'enum' module in the standard library +# https://github.com/robshakir/pyangbind/issues/232 +RUN pip3 install pyangbind==0.8.1 +RUN pip3 uninstall -y enum34 + +# Dependencies of restore_neighbors.py +RUN pip3 install \ + scapy==2.4.4 \ + pyroute2==0.5.14 \ + netifaces==0.10.9 + +{% if docker_sonic_vs_debs.strip() -%} +# Copy locally-built Debian package dependencies +COPY {%- for deb in docker_sonic_vs_debs.split(' ') %} debs/{{ deb }}{%- endfor %} /debs/ + +# Install locally-built Debian packages and implicitly install their dependencies +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; {%- for deb in docker_sonic_vs_debs.split(' ') %} dpkg_apt /debs/{{ deb }};{%- endfor %} +{%- endif %} + +{% if docker_sonic_vs_pydebs.strip() -%} +# Copy locally-built Debian package dependencies +COPY {%- for deb in docker_sonic_vs_pydebs.split(' ') %} python-debs/{{ deb }}{%- endfor %} /debs/ + +# Install locally-built Debian packages and implicitly install their dependencies +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; {%- for deb in docker_sonic_vs_pydebs.split(' ') %} dpkg_apt /debs/{{ deb }};{%- endfor %} +{%- endif %} + +{% if docker_sonic_vs_whls.strip() %} +# copy all whl PKGs first, +copy {%- for whl in docker_sonic_vs_whls.split(' ') %} python-wheels/{{ whl }}{%- endfor %} python-wheels/ + +# install PKGs after copying all PKGs to avoid dependency failure +# use py3 to find python3 package, which is forced by wheel as of now +{%- for whl in docker_sonic_vs_whls.split(' ') %} +RUN pip{% if 'py3' in whl %}3{% else %}2{% endif %} install python-wheels/{{ whl }} +{%- endfor %} +{% endif %} + +# Clean up +RUN apt-get purge -y build-essential libssl-dev swig +RUN apt-get purge -y python-dev python3-dev +RUN apt-get purge -y libcairo2-dev libdbus-1-dev libgirepository1.0-dev libsystemd-dev pkg-config +RUN apt-get clean -y +RUN apt-get autoclean -y +RUN apt-get autoremove -y +RUN rm -rf /debs ~/.cache + +RUN sed -ri 's/^(save .*$)/# \1/g; \ + s/^daemonize yes$/daemonize no/; \ + s/^logfile .*$/logfile ""/; \ + s/^# syslog-enabled no$/syslog-enabled no/; \ + s/^# unixsocket/unixsocket/; \ + s/notify-keyspace-events ""/notify-keyspace-events AKE/; \ + s/redis-server.sock/redis.sock/g; \ + s/^client-output-buffer-limit pubsub [0-9]+mb [0-9]+mb [0-9]+/client-output-buffer-limit pubsub 0 0 0/ \ + ' /etc/redis/redis.conf + +COPY ["50-default.conf", "/etc/rsyslog.d/"] +COPY ["start.sh", "orchagent.sh", "files/update_chassisdb_config", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/configdb-load.sh", "/usr/bin/"] +COPY ["files/arp_update", "/usr/bin/"] +COPY ["files/buffers_config.j2", "files/qos_config.j2", "files/arp_update_vars.j2", "files/copp_cfg.j2", "/usr/share/sonic/templates/"] +COPY ["files/sonic_version.yml", "/etc/sonic/"] +COPY ["port_breakout_config_db.json", "/etc/sonic/"] +COPY ["database_config.json", "/etc/default/sonic-db/"] +COPY ["hostname.j2", "/usr/share/sonic/templates/"] +COPY ["default_chassis_cfg.json", "/etc/default/sonic-db/"] +COPY ["asic_table.json", "/etc/sonic/"] +COPY ["buffermgrd.sh", "/usr/bin/"] + +COPY ["platform.json", "/usr/share/sonic/device/x86_64-kvm_x86_64-r0/"] +COPY ["hwsku.json", "/usr/share/sonic/device/x86_64-kvm_x86_64-r0/Force10-S6000/"] + +# Workaround the tcpdump issue +RUN mv /usr/sbin/tcpdump /usr/bin/tcpdump + +RUN echo "docker-sonic-vs" > /etc/hostname +RUN mkdir -p /etc/quagga +RUN touch /etc/quagga/zebra.conf + +# disable integrated vtysh config +RUN rm /etc/frr/frr.conf + +# Create /var/warmboot/teamd folder for teammgrd +RUN mkdir -p /var/warmboot/teamd + +# Set PLATFORM and HWSKU environment variables +ENV PLATFORM=x86_64-kvm_x86_64-r0 +ENV HWSKU=Force10-S6000 + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/vs/docker-sonic-vs/asic_table.json b/platform/vs/docker-sonic-vs/asic_table.json new file mode 100644 index 000000000000..f0ed93864e2f --- /dev/null +++ b/platform/vs/docker-sonic-vs/asic_table.json @@ -0,0 +1,11 @@ +[ + { + "ASIC_TABLE:VS-ASIC": { + "cell_size": "128", + "pipeline_latency": "18", + "mac_phy_delay": "0.8", + "peer_response_time": "3.8" + }, + "OP": "SET" + } +] diff --git a/platform/vs/docker-sonic-vs/buffermgrd.sh b/platform/vs/docker-sonic-vs/buffermgrd.sh new file mode 100755 index 000000000000..9cdc57434a8f --- /dev/null +++ b/platform/vs/docker-sonic-vs/buffermgrd.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +BUFFER_CALCULATION_MODE=$(redis-cli -n 4 hget "DEVICE_METADATA|localhost" buffer_model) +export ASIC_VENDOR=vs + +if [ "$BUFFER_CALCULATION_MODE" == "dynamic" ]; then + BUFFERMGRD_ARGS="-a /etc/sonic/asic_table.json" +else + # Should we use the fallback MAC in case it is not found in Device.Metadata + BUFFERMGRD_ARGS="-l /usr/share/sonic/hwsku/pg_profile_lookup.ini" +fi + +exec /usr/bin/buffermgrd ${BUFFERMGRD_ARGS} diff --git a/platform/vs/docker-sonic-vs/database_config.json b/platform/vs/docker-sonic-vs/database_config.json new file mode 100644 index 000000000000..953c23f22710 --- /dev/null +++ b/platform/vs/docker-sonic-vs/database_config.json @@ -0,0 +1,83 @@ +{ + "INSTANCES": { + "redis":{ + "hostname" : "127.0.0.1", + "port" : 6379, + "unix_socket_path" : "/var/run/redis/redis.sock" + }, + + "redis_chassis":{ + "hostname" : "redis_chassis.server", + "port": 6380, + "unix_socket_path": "/var/run/redis/redis_chassis.sock" + } + }, + "DATABASES" : { + "APPL_DB" : { + "id" : 0, + "separator": ":", + "instance" : "redis" + }, + "ASIC_DB" : { + "id" : 1, + "separator": ":", + "instance" : "redis" + }, + "COUNTERS_DB" : { + "id" : 2, + "separator": ":", + "instance" : "redis" + }, + "LOGLEVEL_DB" : { + "id" : 3, + "separator": ":", + "instance" : "redis" + }, + "CONFIG_DB" : { + "id" : 4, + "separator": "|", + "instance" : "redis" + }, + "PFC_WD_DB" : { + "id" : 5, + "separator": ":", + "instance" : "redis" + }, + "FLEX_COUNTER_DB" : { + "id" : 5, + "separator": ":", + "instance" : "redis" + }, + "STATE_DB" : { + "id" : 6, + "separator": "|", + "instance" : "redis" + }, + "SNMP_OVERLAY_DB" : { + "id" : 7, + "separator": "|", + "instance" : "redis" + }, + "GB_ASIC_DB" : { + "id" : 8, + "separator": "|", + "instance" : "redis" + }, + "GB_COUNTERS_DB" : { + "id" : 9, + "separator": "|", + "instance" : "redis" + }, + "GB_FLEX_COUNTER_DB" : { + "id" : 10, + "separator": "|", + "instance" : "redis" + }, + "CHASSIS_APP_DB" : { + "id" : 12, + "separator": "|", + "instance" : "redis_chassis" + } + }, + "VERSION" : "1.0" +} diff --git a/platform/vs/docker-sonic-vs/default_chassis_cfg.json b/platform/vs/docker-sonic-vs/default_chassis_cfg.json new file mode 100644 index 000000000000..673a4791faeb --- /dev/null +++ b/platform/vs/docker-sonic-vs/default_chassis_cfg.json @@ -0,0 +1,7 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "chassis_db_address" : "10.8.1.200" + } + } +} diff --git a/platform/vs/docker-sonic-vs/hostname.j2 b/platform/vs/docker-sonic-vs/hostname.j2 new file mode 100644 index 000000000000..91d7cbaaeb3e --- /dev/null +++ b/platform/vs/docker-sonic-vs/hostname.j2 @@ -0,0 +1,3 @@ +{% if DEVICE_METADATA.localhost.chassis_db_address %} +{{ DEVICE_METADATA.localhost.chassis_db_address }} redis_chassis.server +{% endif %} diff --git a/platform/vs/docker-sonic-vs/hwsku.json b/platform/vs/docker-sonic-vs/hwsku.json new file mode 100644 index 000000000000..ed121868c9f5 --- /dev/null +++ b/platform/vs/docker-sonic-vs/hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[40G]" + } + } +} diff --git a/platform/vs/docker-sonic-vs/orchagent.sh b/platform/vs/docker-sonic-vs/orchagent.sh new file mode 100755 index 000000000000..4a035a26b292 --- /dev/null +++ b/platform/vs/docker-sonic-vs/orchagent.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +if [[ -z "$fake_platform" ]]; then + export platform=vs +else + export platform=$fake_platform +fi + +SWSS_VARS_FILE=/usr/share/sonic/templates/swss_vars.j2 + +# Retrieve SWSS vars from sonic-cfggen +SWSS_VARS=$(sonic-cfggen -d -y /etc/sonic/sonic_version.yml -t $SWSS_VARS_FILE) || exit 1 + +MAC_ADDRESS=$(echo $SWSS_VARS | jq -r '.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 +ORCHAGENT_ARGS="-d /var/log/swss " + +# Set orchagent pop batch size to 8192 +ORCHAGENT_ARGS+="-b 8192 " + +# Set synchronous mode if it is enabled in CONFIG_DB +SYNC_MODE=$(echo $SWSS_VARS | jq -r '.synchronous_mode') +if [ "$SYNC_MODE" == "enable" ]; then + ORCHAGENT_ARGS+="-s " +fi + +# Set mac address +ORCHAGENT_ARGS+="-m $MAC_ADDRESS" + +exec /usr/bin/orchagent ${ORCHAGENT_ARGS} diff --git a/platform/vs/docker-sonic-vs/platform.json b/platform/vs/docker-sonic-vs/platform.json new file mode 100644 index 000000000000..1d14ff3ca842 --- /dev/null +++ b/platform/vs/docker-sonic-vs/platform.json @@ -0,0 +1,352 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "0,0,0,0", + "lanes": "25,26,27,28", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/0"], + "2x50G": ["fortyGigE0/0", "fortyGigE0/2"], + "4x25G[10G]": ["fortyGigE0/0", "fortyGigE0/1", "fortyGigE0/2", "fortyGigE0/3"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/0", "fortyGigE0/1", "fortyGigE0/2"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/0", "fortyGigE0/2", "fortyGigE0/3"] + } + }, + "Ethernet4": { + "index": "1,1,1,1", + "lanes": "29,30,31,32", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/4"], + "2x50G": ["fortyGigE0/4", "fortyGigE0/6"], + "4x25G[10G]": ["fortyGigE0/4", "fortyGigE0/5", "fortyGigE0/6", "fortyGigE0/7"] + } + }, + "Ethernet8": { + "index": "2,2,2,2", + "lanes": "33,34,35,36", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/8"], + "2x50G": ["fortyGigE0/8", "fortyGigE0/10"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/8", "fortyGigE0/9", "fortyGigE0/10"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/8", "fortyGigE0/10", "fortyGigE0/11"] + } + }, + "Ethernet12": { + "index": "3,3,3,3", + "lanes": "37,38,39,40", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/12"], + "2x50G": ["fortyGigE0/12", "fortyGigE0/14"], + "4x25G[10G]": ["fortyGigE0/12", "fortyGigE0/13", "fortyGigE0/14", "fortyGigE0/15"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/12", "fortyGigE0/13", "fortyGigE0/14"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/12", "fortyGigE0/14", "fortyGigE0/15"] + } + }, + "Ethernet16": { + "index": "4,4,4,4", + "lanes": "45,46,47,48", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/16"], + "2x50G": ["fortyGigE0/16", "fortyGigE0/18"], + "4x25G[10G]": ["fortyGigE0/16", "fortyGigE0/17", "fortyGigE0/18", "fortyGigE0/19"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/16", "fortyGigE0/17", "fortyGigE0/18"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/16", "fortyGigE0/18", "fortyGigE0/19"] + } + }, + "Ethernet20": { + "index": "5,5,5,5", + "lanes": "41,42,43,44", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/20"], + "2x50G": ["fortyGigE0/20", "fortyGigE0/22"], + "4x25G[10G]": ["fortyGigE0/20", "fortyGigE0/21", "fortyGigE0/22", "fortyGigE0/23"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/20", "fortyGigE0/21", "fortyGigE0/22"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/20", "fortyGigE0/22", "fortyGigE0/23"] + } + }, + "Ethernet24": { + "index": "6,6,6,6", + "lanes": "1,2,3,4", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/24"], + "4x25G[10G]": ["fortyGigE0/24", "fortyGigE0/25", "fortyGigE0/26", "fortyGigE0/27"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/24", "fortyGigE0/25", "fortyGigE0/26"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/24", "fortyGigE0/26", "fortyGigE0/27"] + } + }, + "Ethernet28": { + "index": "7,7,7,7", + "lanes": "5,6,7,8", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/28"], + "2x50G": ["fortyGigE0/28", "fortyGigE0/30"], + "4x25G[10G]": ["fortyGigE0/28", "fortyGigE0/29", "fortyGigE0/30", "fortyGigE0/31"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/28", "fortyGigE0/29", "fortyGigE0/30"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/28", "fortyGigE0/30", "fortyGigE0/31"] + } + }, + "Ethernet32": { + "index": "8,8,8,8", + "lanes": "13,14,15,16", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/32"], + "2x50G": ["fortyGigE0/32", "fortyGigE0/34"], + "4x25G[10G]": ["fortyGigE0/32", "fortyGigE0/33", "fortyGigE0/34", "fortyGigE0/35"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/32", "fortyGigE0/33", "fortyGigE0/34"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/32", "fortyGigE0/34", "fortyGigE0/35"] + } + }, + "Ethernet36": { + "index": "9,9,9,9", + "lanes": "9,10,11,12", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/36"], + "2x50G": ["fortyGigE0/36", "fortyGigE0/38"], + "4x25G[10G]": ["fortyGigE0/36", "fortyGigE0/37", "fortyGigE0/38", "fortyGigE0/39"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/36", "fortyGigE0/37", "fortyGigE0/38"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/36", "fortyGigE0/38", "fortyGigE0/39"] + } + }, + "Ethernet40": { + "index": "10,10,10,10", + "lanes": "17,18,19,20", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/40"], + "2x50G": ["fortyGigE0/40", "fortyGigE0/42"], + "4x25G[10G]": ["fortyGigE0/40", "fortyGigE0/41", "fortyGigE0/42", "fortyGigE0/43"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/40", "fortyGigE0/41", "fortyGigE0/42"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/40", "fortyGigE0/42", "fortyGigE0/43"] + } + }, + "Ethernet44": { + "index": "11,11,11,11", + "lanes": "21,22,23,24", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/44"], + "2x50G": ["fortyGigE0/44", "fortyGigE0/46"], + "4x25G[10G]": ["fortyGigE0/44", "fortyGigE0/45", "fortyGigE0/46", "fortyGigE0/47"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/44", "fortyGigE0/45", "fortyGigE0/46"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/44", "fortyGigE0/46", "fortyGigE0/47"] + } + }, + "Ethernet48": { + "index": "12,12,12,12", + "lanes": "53,54,55,56", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/48"], + "2x50G": ["fortyGigE0/48", "fortyGigE0/50"], + "4x25G[10G]": ["fortyGigE0/48", "fortyGigE0/49", "fortyGigE0/50", "fortyGigE0/51"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/48", "fortyGigE0/49", "fortyGigE0/50"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/48", "fortyGigE0/50", "fortyGigE0/51"] + } + }, + "Ethernet52": { + "index": "13,13,13,13", + "lanes": "49,50,51,52", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/52"], + "2x50G": ["fortyGigE0/52", "fortyGigE0/54"], + "4x25G[10G]": ["fortyGigE0/52", "fortyGigE0/53", "fortyGigE0/54", "fortyGigE0/55"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/52", "fortyGigE0/53", "fortyGigE0/54"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/52", "fortyGigE0/54", "fortyGigE0/55"] + } + }, + "Ethernet56": { + "index": "14,14,14,14", + "lanes": "57,58,59,60", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/56"], + "2x50G": ["fortyGigE0/56", "fortyGigE0/58"], + "4x25G[10G]": ["fortyGigE0/56", "fortyGigE0/57", "fortyGigE0/58", "fortyGigE0/59"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/56", "fortyGigE0/57", "fortyGigE0/58"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/56", "fortyGigE0/58", "fortyGigE0/59"] + } + }, + "Ethernet60": { + "index": "15,15,15,15", + "lanes": "61,62,63,64", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/60"], + "2x50G": ["fortyGigE0/60", "fortyGigE0/62"], + "4x25G[10G]": ["fortyGigE0/60", "fortyGigE0/61", "fortyGigE0/62", "fortyGigE0/63"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/60", "fortyGigE0/61", "fortyGigE0/62"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/60", "fortyGigE0/62", "fortyGigE0/63"] + } + }, + "Ethernet64": { + "index": "16,16,16,16", + "lanes": "69,70,71,72", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/64"], + "2x50G": ["fortyGigE0/64", "fortyGigE0/65"], + "4x25G[10G]": ["fortyGigE0/64", "fortyGigE0/65", "fortyGigE0/66", "fortyGigE0/67"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/64", "fortyGigE0/65", "fortyGigE0/66"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/64", "fortyGigE0/66", "fortyGigE0/67"] + } + }, + "Ethernet68": { + "index": "17,17,17,17", + "lanes": "65,66,67,68", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/68"], + "2x50G": ["fortyGigE0/68", "fortyGigE0/70"], + "4x25G[10G]": ["fortyGigE0/68", "fortyGigE0/69", "fortyGigE0/70", "fortyGigE0/71"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/68", "fortyGigE0/69", "fortyGigE0/70"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/68", "fortyGigE0/70", "fortyGigE0/71"] + } + }, + "Ethernet72": { + "index": "18,18,18,18", + "lanes": "73,74,75,76", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/72"], + "2x50G": ["fortyGigE0/72", "fortyGigE0/74"], + "4x25G[10G]": ["fortyGigE0/72", "fortyGigE0/73", "fortyGigE0/74", "fortyGigE0/75"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/72", "fortyGigE0/73", "fortyGigE0/74"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/72", "fortyGigE0/74", "fortyGigE0/75"] + } + }, + "Ethernet76": { + "index": "19,19,19,19", + "lanes": "77,78,79,80", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/76"], + "2x50G": ["fortyGigE0/76", "fortyGigE0/78"], + "4x25G[10G]": ["fortyGigE0/76", "fortyGigE0/77", "fortyGigE0/78", "fortyGigE0/79"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/76", "fortyGigE0/77", "fortyGigE0/78"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/76", "fortyGigE0/78", "fortyGigE0/79"] + } + }, + "Ethernet80": { + "index": "20,20,20,20", + "lanes": "109,110,111,112", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/80"], + "2x50G": ["fortyGigE0/80", "fortyGigE0/82"], + "4x25G[10G]": ["fortyGigE0/80", "fortyGigE0/81", "fortyGigE0/82", "fortyGigE0/83"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/80", "fortyGigE0/81", "fortyGigE0/82"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/80", "fortyGigE0/82", "fortyGigE0/83"] + } + }, + "Ethernet84": { + "index": "21,21,21,21", + "lanes": "105,106,107,108", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/84"], + "2x50G": ["fortyGigE0/84", "fortyGigE0/86"], + "4x25G[10G]": ["fortyGigE0/84", "fortyGigE0/85", "fortyGigE0/86", "fortyGigE0/87"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/84", "fortyGigE0/85", "fortyGigE0/86"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/84", "fortyGigE0/86", "fortyGigE0/87"] + } + }, + "Ethernet88": { + "index": "22,22,22,22", + "lanes": "113,114,115,116", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/88"], + "2x50G": ["fortyGigE0/88", "fortyGigE0/90"], + "4x25G[10G]": ["fortyGigE0/88", "fortyGigE0/89", "fortyGigE0/90", "fortyGigE0/91"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/88", "fortyGigE0/89", "fortyGigE0/90"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/88", "fortyGigE0/90", "fortyGigE0/91"] + } + }, + "Ethernet92": { + "index": "23,23,23,23", + "lanes": "117,118,119,120", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/92"], + "2x50G": ["fortyGigE0/92", "fortyGigE0/94"], + "4x25G[10G]": ["fortyGigE0/92", "fortyGigE0/93", "fortyGigE0/94", "fortyGigE0/95"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/92", "fortyGigE0/93", "fortyGigE0/94"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/92", "fortyGigE0/94", "fortyGigE0/95"] + } + }, + "Ethernet96": { + "index": "24,24,24,24", + "lanes": "125,126,127,128", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/96"], + "2x50G": ["fortyGigE0/96", "fortyGigE0/98"], + "4x25G[10G]": ["fortyGigE0/96", "fortyGigE0/97", "fortyGigE0/98", "fortyGigE0/99"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/96", "fortyGigE0/97", "fortyGigE0/98"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/96", "fortyGigE0/98", "fortyGigE0/99"] + } + }, + "Ethernet100": { + "index": "25,25,25,25", + "lanes": "121,122,123,124", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/100"], + "2x50G": ["fortyGigE0/100", "fortyGigE0/102"], + "4x25G[10G]": ["fortyGigE0/100", "fortyGigE0/101", "fortyGigE0/102", "fortyGigE0/103"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/100", "fortyGigE0/101", "fortyGigE0/102"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/100", "fortyGigE0/102", "fortyGigE0/103"] + } + }, + "Ethernet104": { + "index": "26,26,26,26", + "lanes": "81,82,83,84", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/104"], + "2x50G": ["fortyGigE0/104", "fortyGigE0/106"], + "4x25G[10G]": ["fortyGigE0/104", "fortyGigE0/105", "fortyGigE0/106", "fortyGigE0/107"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/104", "fortyGigE0/105", "fortyGigE0/106"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/104", "fortyGigE0/106", "fortyGigE0/107"] + } + }, + "Ethernet108": { + "index": "27,27,27,27", + "lanes": "85,86,87,88", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/108"], + "2x50G": ["fortyGigE0/108", "fortyGigE0/110"], + "4x25G[10G]": ["fortyGigE0/108", "fortyGigE0/109", "fortyGigE0/110", "fortyGigE0/111"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/108", "fortyGigE0/109", "fortyGigE0/110"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/108", "fortyGigE0/110", "fortyGigE0/111"] + } + }, + "Ethernet112": { + "index": "28,28,28,28", + "lanes": "93,94,95,96", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/112"], + "2x50G": ["fortyGigE0/112", "fortyGigE0/114"], + "4x25G[10G]": ["fortyGigE0/112", "fortyGigE0/113", "fortyGigE0/114", "fortyGigE0/115"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/112", "fortyGigE0/113", "fortyGigE0/114"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/112", "fortyGigE0/114", "fortyGigE0/115"] + } + }, + "Ethernet116": { + "index": "29,29,29,29", + "lanes": "89,90,91,92", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/116"], + "2x50G": ["fortyGigE0/116", "fortyGigE0/118"], + "4x25G[10G]": ["fortyGigE0/116", "fortyGigE0/117", "fortyGigE0/118", "fortyGigE0/119"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/116", "fortyGigE0/117", "fortyGigE0/118"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/116", "fortyGigE0/118", "fortyGigE0/119"] + } + }, + "Ethernet120": { + "index": "30,30,30,30", + "lanes": "101,102,103,104", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/120"], + "2x50G": ["fortyGigE0/120", "fortyGigE0/122"], + "4x25G[10G]": ["fortyGigE0/120", "fortyGigE0/121", "fortyGigE0/122", "fortyGigE0/123"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/120", "fortyGigE0/121", "fortyGigE0/122"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/120", "fortyGigE0/122", "fortyGigE0/123"] + } + }, + "Ethernet124": { + "index": "31,31,31,31", + "lanes": "97,98,99,100", + "breakout_modes": { + "1x100G[40G]": ["fortyGigE0/124"], + "2x50G": ["fortyGigE0/124", "fortyGigE0/126"], + "4x25G[10G]": ["fortyGigE0/124", "fortyGigE0/125", "fortyGigE0/126", "fortyGigE0/127"], + "2x25G(2)+1x50G(2)": ["fortyGigE0/124", "fortyGigE0/125", "fortyGigE0/126"], + "1x50G(2)+2x25G(2)": ["fortyGigE0/124", "fortyGigE0/126", "fortyGigE0/127"] + } + } + } +} diff --git a/platform/vs/docker-sonic-vs/port_breakout_config_db.json b/platform/vs/docker-sonic-vs/port_breakout_config_db.json new file mode 100644 index 000000000000..16b40e14f8f0 --- /dev/null +++ b/platform/vs/docker-sonic-vs/port_breakout_config_db.json @@ -0,0 +1,61 @@ +{ + "ACL_TABLE": { + "DPB_ACL_TBL_1": { + "policy_desc": "ACL table to test DPB/ACL dependency", + "ports": [ + "Ethernet0", + "Ethernet1", + "Ethernet2", + "Ethernet3", + "Ethernet4", + "Ethernet5" + ], + "type": "L3" + }, + "DPB_ACL_TBL_2": { + "policy_desc": "ACL table to test DPB/ACL dependency", + "ports": [ + "Ethernet0", + "Ethernet1", + "Ethernet2", + "Ethernet3", + "Ethernet6", + "Ethernet7" + ], + "type": "L3" + } + }, + "INTERFACE": { + "Ethernet8": {}, + "Ethernet8|10.0.0.8/31": { + "family": "IPv4", + "scope": "global" + } + }, + "VLAN_MEMBER": { + "Vlan100|Ethernet0": { + "tagging_mode": "untagged" + }, + "Vlan100|Ethernet1": { + "tagging_mode": "untagged" + }, + "Vlan100|Ethernet2": { + "tagging_mode": "untagged" + }, + "Vlan100|Ethernet3": { + "tagging_mode": "untagged" + }, + "Vlan100|Ethernet4": { + "tagging_mode": "untagged" + }, + "Vlan100|Ethernet5": { + "tagging_mode": "untagged" + }, + "Vlan101|Ethernet6": { + "tagging_mode": "tagged" + }, + "Vlan101|Ethernet7": { + "tagging_mode": "tagged" + } + } +} diff --git a/platform/vs/docker-sonic-vs/sonic-dev.gpg.key b/platform/vs/docker-sonic-vs/sonic-dev.gpg.key new file mode 100644 index 000000000000..fb9a37901bc7 --- /dev/null +++ b/platform/vs/docker-sonic-vs/sonic-dev.gpg.key @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQENBFQ1bTIBCAC7oGfkv/ck0XsLuG8cdcSB2ISqxFAcBvH9BitEtxmpW2uhykKk +xY4rVD/4Uys1s3PF1/64QfPR+hYcewueOwz0ZAcLyFXXk4McICXaPq3NrLiWYKKX +UZLnrPzcrGZoW/kHDDp4OmBiDmT1PGvZlpuimwkMCusUzIr7Cbbp2dIy8MERL5tA +LcgLu3KL6clJ+aTW2jgepI1D7sTepOeGd7eRSb5njKg2M7k/93v/7MipZxiVtyXH +B74YiK6jSbst5JpuYsLa/Dqryvx7Xq3n53oif892pv3euTduo1fYw8Hgh/OOYdeT +c9WCj03KA1jCSFURjdrug0kR8BPlfjqtRLXFABEBAAG0JE1TIE9wZW4gVGVjaCA8 +aW50ZXJvcEBtaWNyb3NvZnQuY29tPokBOAQTAQIAIgUCVDVtMgIbAwYLCQgHAwIG +FQgCCQoLBBYCAwECHgECF4AACgkQsCxG30F6CJO1uAf/cmL68bM8YgF/61hkaY56 +LqrppUTJH/w4fKq47Pf6KfgSLvxfNU6soi2KHYRjIvTRx3tV4vUM5n2plaQg2s8V +/Epg4FeIRTk75YwiHAzLhLnp5cdUaTvC4j4mwxoB6j9Ty+fXJwQ0MvpDhIZb9vM4 +GXw/fEQHCT4f3gx4nReeqE+FB2wVHleX9+Lpodu98JyJTKJRBRHYLqy6S+/lyp2W +aBlsI1LOqBcx1uRK24U7duIpbYwIyrx0cafSruqR2GjVdu+imkhHyUn52VbzYhq1 +af0rqYiZ1VOamVOG0By8+hVyNa1MLc1K2uWGs0o5fDe9F5/swbvLHVXI+M50Vs+m +J7kBDQRUNW0yAQgAu7DkTVj0ZQC4F7bFivAwrdby8gCakTXOl1kcK622hjRJ8nam +aZeW+eADfLRsTmdUmXgZu1YWS5Gn2ZVngC8SGPUBT071+oRETCz4uNB7IimB9QfP +++orI6o2vmnVVsq5wWCbEdNU+TCVv1zjrYev5lwckkKpjHt6o8MNoX2DFuQymSyR +eZKaqhdKmcji4Ke7OIYqwgPjch3wxzE1b5gNOR/iwxWyjjOffZPLr/VhIfIJRs86 +dSXrwjHtEh810SKDLghHM0VAdY34nyC5ZZ61yhts5HtQDFK+9mNpH1mkc4gDBlgG +266pVvknumK6lPNm/osF/cpjWmEw24ypcQIvOQARAQABiQEfBBgBAgAJBQJUNW0y +AhsMAAoJELAsRt9BegiTMBUH/0sZ6gZy7mCTSAYT+NSXLFtGC2zNUVL80SWvfgYm +k9XPVI22MrefZfQ6M01RylyxtWXjRM8UoN8SDKWPpXumzJf831f/7om5zwutaG7b +tjDPYqRKJSbAIFZu2mN+uLrNQ2SV6XK7FoV0dtcrEX9S7RICb6i19D+70+Oh/qgU +R04H1jqS29XBzqAlIzdBoA+sYAwbOIJsSL3YyNQcUv3B5+5yR/bo/L8pnUJt6iuL +nWW+mi7r8gWPHDSrcdYq1TmmlOM7CwZPgWRZzkQPSeZz52Tt7IP47eyGJ09U4PIf +FtMH1ElL2UgHoA/F9Q88e7LkztaTqE59uXWbIYyuSMJVvRU= +=sb3d +-----END PGP PUBLIC KEY BLOCK----- diff --git a/platform/vs/docker-sonic-vs/start.sh b/platform/vs/docker-sonic-vs/start.sh new file mode 100755 index 000000000000..7ee70efa0815 --- /dev/null +++ b/platform/vs/docker-sonic-vs/start.sh @@ -0,0 +1,146 @@ +#!/bin/bash -e + +# Generate configuration + +# NOTE: 'PLATFORM' and 'HWSKU' environment variables are set +# in the Dockerfile so that they persist for the life of the container + +ln -sf /usr/share/sonic/device/$PLATFORM /usr/share/sonic/platform +ln -sf /usr/share/sonic/device/$PLATFORM/$HWSKU /usr/share/sonic/hwsku + +pushd /usr/share/sonic/hwsku + +# filter available front panel ports in lanemap.ini +[ -f lanemap.ini.orig ] || cp lanemap.ini lanemap.ini.orig +for p in $(ip link show | grep -oE "eth[0-9]+" | grep -v eth0); do + grep ^$p: lanemap.ini.orig +done > lanemap.ini + +# filter available sonic front panel ports in port_config.ini +[ -f port_config.ini.orig ] || cp port_config.ini port_config.ini.orig +grep ^# port_config.ini.orig > port_config.ini +for lanes in $(awk -F ':' '{print $2}' lanemap.ini); do + grep -E "\s$lanes\s" port_config.ini.orig +done >> port_config.ini + +popd + +[ -d /etc/sonic ] || mkdir -p /etc/sonic + +if [[ -f /usr/share/sonic/virtual_chassis/default_config.json ]]; then + CHASS_CFG="-j /usr/share/sonic/virtual_chassis/default_config.json" +fi + +# Note: libswsscommon requires a dabase_config file in /var/run/redis/sonic-db/ +# Prepare this file before any dependent application, such as sonic-cfggen +mkdir -p /var/run/redis/sonic-db +cp /etc/default/sonic-db/database_config.json /var/run/redis/sonic-db/ + +SYSTEM_MAC_ADDRESS=$(ip link show eth0 | grep ether | awk '{print $2}') +sonic-cfggen -a '{"DEVICE_METADATA":{"localhost": {"mac": "'$SYSTEM_MAC_ADDRESS'", "buffer_model": "traditional"}}}' $CHASS_CFG --print-data > /etc/sonic/init_cfg.json + +if [ -f /etc/sonic/config_db.json ]; then + sonic-cfggen -j /etc/sonic/init_cfg.json -j /etc/sonic/config_db.json --print-data > /tmp/config_db.json + mv /tmp/config_db.json /etc/sonic/config_db.json +else + # generate and merge buffers configuration into config file + sonic-cfggen -k $HWSKU -p /usr/share/sonic/device/$PLATFORM/platform.json -t /usr/share/sonic/hwsku/buffers.json.j2 > /tmp/buffers.json + sonic-cfggen -j /etc/sonic/init_cfg.json -t /usr/share/sonic/hwsku/qos.json.j2 > /tmp/qos.json + sonic-cfggen -p /usr/share/sonic/device/$PLATFORM/platform.json -k $HWSKU --print-data > /tmp/ports.json + # change admin_status from up to down; Test cases dependent + sed -i "s/up/down/g" /tmp/ports.json + sonic-cfggen -j /etc/sonic/init_cfg.json -j /tmp/buffers.json -j /tmp/qos.json -j /tmp/ports.json --print-data > /etc/sonic/config_db.json +fi +sonic-cfggen -t /usr/share/sonic/templates/copp_cfg.j2 > /etc/sonic/copp_cfg.json + +mkdir -p /etc/swss/config.d/ + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisord_cfg="/etc/supervisor/conf.d/supervisord.conf" +chassisdb_cfg_file="/usr/share/sonic/virtual_chassis/default_config.json" +chassisdb_cfg_file_default="/etc/default/sonic-db/default_chassis_cfg.json" +host_template="/usr/share/sonic/templates/hostname.j2" +db_cfg_file="/var/run/redis/sonic-db/database_config.json" +db_cfg_file_tmp="/var/run/redis/sonic-db/database_config.json.tmp" + +if [ -r "$chassisdb_cfg_file" ]; then + echo $(sonic-cfggen -j $chassisdb_cfg_file -t $host_template) >> /etc/hosts +else + chassisdb_cfg_file="$chassisdb_cfg_file_default" + echo "10.8.1.200 redis_chassis.server" >> /etc/hosts +fi + +supervisorctl start redis-server + +start_chassis_db=`sonic-cfggen -v DEVICE_METADATA.localhost.start_chassis_db -y $chassisdb_cfg_file` +if [[ "$HOSTNAME" == *"supervisor"* ]] || [ "$start_chassis_db" == "1" ]; then + supervisorctl start redis-chassis +fi + +conn_chassis_db=`sonic-cfggen -v DEVICE_METADATA.localhost.connect_to_chassis_db -y $chassisdb_cfg_file` +if [ "$start_chassis_db" != "1" ] && [ "$conn_chassis_db" != "1" ]; then + cp $db_cfg_file $db_cfg_file_tmp + update_chassisdb_config -j $db_cfg_file_tmp -d + cp $db_cfg_file_tmp $db_cfg_file +fi + +if [ "$conn_chassis_db" == "1" ]; then + if [ -f /usr/share/sonic/virtual_chassis/coreportindexmap.ini ]; then + cp /usr/share/sonic/virtual_chassis/coreportindexmap.ini /usr/share/sonic/hwsku/ + fi +fi + +/usr/bin/configdb-load.sh + +supervisorctl start syncd + +supervisorctl start portsyncd + +supervisorctl start orchagent + +supervisorctl start coppmgrd + +supervisorctl start neighsyncd + +supervisorctl start fdbsyncd + +supervisorctl start teamsyncd + +supervisorctl start fpmsyncd + +supervisorctl start teammgrd + +supervisorctl start vrfmgrd + +supervisorctl start portmgrd + +supervisorctl start intfmgrd + +supervisorctl start vlanmgrd + +supervisorctl start zebra + +supervisorctl start staticd + +supervisorctl start buffermgrd + +supervisorctl start nbrmgrd + +supervisorctl start vxlanmgrd + +supervisorctl start sflowmgrd + +supervisorctl start natmgrd + +supervisorctl start natsyncd + +supervisorctl start tunnelmgrd + +# Start arp_update when VLAN exists +VLAN=`sonic-cfggen -d -v 'VLAN.keys() | join(" ") if VLAN'` +if [ "$VLAN" != "" ]; then + supervisorctl start arp_update +fi diff --git a/platform/vs/docker-sonic-vs/supervisord.conf b/platform/vs/docker-sonic-vs/supervisord.conf new file mode 100644 index 000000000000..977b84117e3e --- /dev/null +++ b/platform/vs/docker-sonic-vs/supervisord.conf @@ -0,0 +1,238 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[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=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:redis-server] +command=/usr/bin/redis-server /etc/redis/redis.conf +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:redis-chassis] +command=/bin/bash -c "{ [[ -s /var/lib/redis_chassis/dump.rdb ]] || rm -f /var/lib/redis_chassis/dump.rdb; } && mkdir -p /var/lib/redis_chassis && exec /usr/bin/redis-server /etc/redis/redis.conf --bind redis_chassis.server --port 6380 --unixsocket /var/run/redis/redis_chassis.sock --pidfile /var/run/redis/redis_chassis.pid --dir /var/lib/redis_chassis" +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:portsyncd] +command=/usr/bin/portsyncd +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:orchagent] +command=/usr/bin/orchagent.sh +priority=6 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:coppmgrd] +command=/usr/bin/coppmgrd +priority=7 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:neighsyncd] +command=/usr/bin/neighsyncd +priority=8 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:teamsyncd] +command=/usr/bin/teamsyncd +priority=9 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:vlanmgrd] +command=/usr/bin/vlanmgrd +priority=10 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:intfmgrd] +command=/usr/bin/intfmgrd +priority=11 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:portmgrd] +command=/usr/bin/portmgrd +priority=12 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:teammgrd] +command=/usr/bin/teammgrd +priority=12 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:zebra] +command=/usr/lib/frr/zebra -A 127.0.0.1 -s 90000000 -M fpm +priority=13 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:bgpd] +command=/usr/lib/frr/bgpd -A 127.0.0.1 +priority=14 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:staticd] +command=/usr/lib/frr/staticd -A 127.0.0.1 +priority=14 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:fpmsyncd] +command=/usr/bin/fpmsyncd +priority=15 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:arp_update] +command=/usr/bin/arp_update +priority=16 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog + +[program:buffermgrd] +command=/usr/bin/buffermgrd.sh +priority=17 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:vrfmgrd] +command=/usr/bin/vrfmgrd +priority=18 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:restore_neighbors] +command=/usr/bin/restore_neighbors.py +priority=19 +autostart=false +autorestart=false +startsecs=0 +startretries=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:nbrmgrd] +command=/usr/bin/nbrmgrd +priority=20 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:vxlanmgrd] +command=/usr/bin/vxlanmgrd +priority=21 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:sflowmgrd] +command=/usr/bin/sflowmgrd +priority=22 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:natmgrd] +command=/usr/bin/natmgrd +priority=23 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:natsyncd] +command=/usr/bin/natsyncd +priority=24 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:fdbsyncd] +command=/usr/bin/fdbsyncd +priority=25 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:tunnelmgrd] +command=/usr/bin/tunnelmgrd +priority=26 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/vs/docker-syncd-vs.dep b/platform/vs/docker-syncd-vs.dep new file mode 100644 index 000000000000..e0330f8fcc4f --- /dev/null +++ b/platform/vs/docker-syncd-vs.dep @@ -0,0 +1,11 @@ +#DPKG FRK +DPATH := $($(DOCKER_SYNCD_BASE)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/vs/docker-syncd-vs.mk platform/vs/docker-syncd-vs.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_SYNCD_BASE)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SYNCD_BASE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SYNCD_BASE)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_SYNCD_BASE),$(DOCKER_SYNCD_BASE_DBG))) diff --git a/platform/vs/docker-syncd-vs.mk b/platform/vs/docker-syncd-vs.mk new file mode 100644 index 000000000000..15d94c5854d2 --- /dev/null +++ b/platform/vs/docker-syncd-vs.mk @@ -0,0 +1,14 @@ +# docker image for vs syncd + +DOCKER_SYNCD_PLATFORM_CODE = vs +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD_VS) + +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_VS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) \ + $(LIBSAIVS_DBG) + +$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/vs/docker-syncd-vs/Dockerfile.j2 b/platform/vs/docker-syncd-vs/Dockerfile.j2 new file mode 100644 index 000000000000..b3d7dcef490b --- /dev/null +++ b/platform/vs/docker-syncd-vs/Dockerfile.j2 @@ -0,0 +1,34 @@ +FROM docker-config-engine-buster + +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 + +RUN apt-get install -f -y iproute2 libcap2-bin + +COPY \ +{% for deb in docker_syncd_vs_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_syncd_vs_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/platform/vs/docker-syncd-vs/critical_processes b/platform/vs/docker-syncd-vs/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/vs/docker-syncd-vs/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/platform/vs/docker-syncd-vs/start.sh b/platform/vs/docker-syncd-vs/start.sh new file mode 100755 index 000000000000..40178f13e004 --- /dev/null +++ b/platform/vs/docker-syncd-vs/start.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +HWSKU_DIR=/usr/share/sonic/hwsku + +mkdir -p /etc/sai.d/ + +# Create/Copy the sai.profile to /etc/sai.d/sai.profile +if [ -f $HWSKU_DIR/sai.profile.j2 ]; then + sonic-cfggen -d -t $HWSKU_DIR/sai.profile.j2 > /etc/sai.d/sai.profile +else + if [ -f $HWSKU_DIR/sai.profile ]; then + cp $HWSKU_DIR/sai.profile /etc/sai.d/sai.profile + fi +fi diff --git a/platform/vs/docker-syncd-vs/supervisord.conf b/platform/vs/docker-syncd-vs/supervisord.conf new file mode 100644 index 000000000000..6a6d946632e0 --- /dev/null +++ b/platform/vs/docker-syncd-vs/supervisord.conf @@ -0,0 +1,49 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=25 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name syncd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited diff --git a/platform/vs/gbsyncd-vs.mk b/platform/vs/gbsyncd-vs.mk new file mode 100644 index 000000000000..2013132d6281 --- /dev/null +++ b/platform/vs/gbsyncd-vs.mk @@ -0,0 +1,14 @@ +# docker image for vs gbsyncd + +DOCKER_GBSYNCD_PLATFORM_CODE = vs +include $(PLATFORM_PATH)/../template/docker-gbsyncd-base.mk + +$(DOCKER_GBSYNCD_BASE)_DEPENDS += $(SYNCD_VS) + +$(DOCKER_GBSYNCD_BASE)_DBG_DEPENDS += $(SYNCD_VS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) \ + $(LIBSAIVS_DBG) + +$(DOCKER_GBSYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/vs/kvm-image.dep b/platform/vs/kvm-image.dep new file mode 100644 index 000000000000..05c083a51597 --- /dev/null +++ b/platform/vs/kvm-image.dep @@ -0,0 +1,2 @@ +#DPKG FRK +$(SONIC_KVM_IMAGE)_CACHE_MODE := none diff --git a/platform/vs/kvm-image.mk b/platform/vs/kvm-image.mk new file mode 100644 index 000000000000..439a6fc1e418 --- /dev/null +++ b/platform/vs/kvm-image.mk @@ -0,0 +1,14 @@ +# sonic kvm image + +SONIC_KVM_IMAGE = sonic-vs.img.gz +$(SONIC_KVM_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_KVM_IMAGE)_MACHINE = vs +$(SONIC_KVM_IMAGE)_IMAGE_TYPE = kvm +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_KVM_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_KVM_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_KVM_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +$(SONIC_KVM_IMAGE)_FILES = $(ONIE_RECOVERY_IMAGE) +SONIC_INSTALLERS += $(SONIC_KVM_IMAGE) diff --git a/platform/vs/libsaithrift-dev.dep b/platform/vs/libsaithrift-dev.dep new file mode 100644 index 000000000000..be1d3f74b23f --- /dev/null +++ b/platform/vs/libsaithrift-dev.dep @@ -0,0 +1,13 @@ +#DPKG FRK +SPATH := $($(LIBSAITHRIFT_DEV)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/libsaithrift-dev.mk platform/broadcom/libsaithrift-dev.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_PATHS := $(SPATH) $(SPATH)/bm/behavioral-model $(SPATH)/test/ptf $(SPATH)/test/saithrift/ctypesgen +$(foreach path, $(SMDEP_PATHS), $(eval $(path) :=$(filter-out $(SMDEP_PATHS),$(addprefix $(path)/, $(shell cd $(path) && git ls-files | grep -Ev " " ))))) + +$(LIBSAITHRIFT_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBSAITHRIFT_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBSAITHRIFT_DEV)_DEP_FILES := $(DEP_FILES) +$(LIBSAITHRIFT_DEV)_SMDEP_FILES := $(foreach path, $(SMDEP_PATHS), $($(path))) +$(LIBSAITHRIFT_DEV)_SMDEP_PATHS := $(SMDEP_PATHS) + diff --git a/platform/vs/libsaithrift-dev.mk b/platform/vs/libsaithrift-dev.mk new file mode 100644 index 000000000000..ba8a63d539ac --- /dev/null +++ b/platform/vs/libsaithrift-dev.mk @@ -0,0 +1,22 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) \ + $(LIBSAIVS) $(LIBSAIVS_DEV) $(LIBSAIMETADATA) $(LIBSAIMETADATA_DEV) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(LIBSAIVS) $(LIBSAIMETADATA) +$(LIBSAITHRIFT_DEV)_BUILD_ENV = platform=vs +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(LIBSAIVS) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/vs/one-image.dep b/platform/vs/one-image.dep new file mode 100644 index 000000000000..c5399d808172 --- /dev/null +++ b/platform/vs/one-image.dep @@ -0,0 +1,2 @@ +#DPKG FRK +$(SONIC_ONE_IMAGE)_CACHE_MODE := none diff --git a/platform/vs/one-image.mk b/platform/vs/one-image.mk new file mode 100644 index 000000000000..a0e176df1497 --- /dev/null +++ b/platform/vs/one-image.mk @@ -0,0 +1,13 @@ +# sonic vs one image installer + +SONIC_ONE_IMAGE = sonic-vs.bin +$(SONIC_ONE_IMAGE)_MACHINE = vs +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/vs/onie.dep b/platform/vs/onie.dep new file mode 100644 index 000000000000..36de83ce8ea3 --- /dev/null +++ b/platform/vs/onie.dep @@ -0,0 +1,2 @@ +#DPKG FRK +$(ONIE_RECOVERY_IMAGE)_CACHE_MODE := none diff --git a/platform/vs/onie.mk b/platform/vs/onie.mk new file mode 100644 index 000000000000..09a807c25b2a --- /dev/null +++ b/platform/vs/onie.mk @@ -0,0 +1,4 @@ +ONIE_RECOVERY_IMAGE = onie-recovery-x86_64-kvm_x86_64-r0.iso +$(ONIE_RECOVERY_IMAGE)_URL = "https://sonicstorage.blob.core.windows.net/packages/onie/onie-recovery-x86_64-kvm_x86_64-r0.iso?sv=2015-04-05&sr=b&sig=XMAk1cttBFM369CMbihe5oZgXwe4uaDVfwg4CTLT%2F5U%3D&se=2155-10-13T10%3A40%3A13Z&sp=r" + +SONIC_ONLINE_FILES += $(ONIE_RECOVERY_IMAGE) diff --git a/platform/vs/platform.conf b/platform/vs/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/vs/raw-image.dep b/platform/vs/raw-image.dep new file mode 100644 index 000000000000..500ba2a70fef --- /dev/null +++ b/platform/vs/raw-image.dep @@ -0,0 +1,2 @@ +#DPKG FRK +$(SONIC_RAW_IMAGE)_CACHE_MODE := none diff --git a/platform/vs/raw-image.mk b/platform/vs/raw-image.mk new file mode 100644 index 000000000000..becb9012f552 --- /dev/null +++ b/platform/vs/raw-image.mk @@ -0,0 +1,8 @@ +# sonic vs raw image installer + +SONIC_RAW_IMAGE = sonic-vs.raw +$(SONIC_RAW_IMAGE)_MACHINE = vs +$(SONIC_RAW_IMAGE)_IMAGE_TYPE = raw +$(SONIC_RAW_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_RAW_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_RAW_IMAGE) diff --git a/platform/vs/rules.dep b/platform/vs/rules.dep new file mode 100644 index 000000000000..0d485e8004d1 --- /dev/null +++ b/platform/vs/rules.dep @@ -0,0 +1,11 @@ +include $(PLATFORM_PATH)/syncd-vs.dep +include $(PLATFORM_PATH)/sonic-version.dep +include $(PLATFORM_PATH)/docker-sonic-vs.dep +include $(PLATFORM_PATH)/docker-syncd-vs.dep +include $(PLATFORM_PATH)/docker-gbsyncd-vs.dep +include $(PLATFORM_PATH)/docker-ptf.dep +include $(PLATFORM_PATH)/libsaithrift-dev.dep +include $(PLATFORM_PATH)/one-image.dep +include $(PLATFORM_PATH)/onie.dep +include $(PLATFORM_PATH)/kvm-image.dep + diff --git a/platform/vs/rules.mk b/platform/vs/rules.mk new file mode 100644 index 000000000000..cbb52847edfa --- /dev/null +++ b/platform/vs/rules.mk @@ -0,0 +1,13 @@ +include $(PLATFORM_PATH)/syncd-vs.mk +include $(PLATFORM_PATH)/sonic-version.mk +include $(PLATFORM_PATH)/docker-sonic-vs.mk +include $(PLATFORM_PATH)/docker-syncd-vs.mk +include $(PLATFORM_PATH)/docker-gbsyncd-vs.mk +include $(PLATFORM_PATH)/docker-ptf.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/onie.mk +include $(PLATFORM_PATH)/kvm-image.mk +include $(PLATFORM_PATH)/raw-image.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) $(SONIC_KVM_IMAGE) $(DOCKER_SONIC_VS) $(SONIC_RAW_IMAGE) diff --git a/platform/vs/sonic-gns3a.sh b/platform/vs/sonic-gns3a.sh new file mode 100644 index 000000000000..41e39cd8686a --- /dev/null +++ b/platform/vs/sonic-gns3a.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +# This script creates a .gns3a SONiC appliance file +IMGFILE="sonic-vs.image" +RELEASE="latest" + +usage() { + echo "`basename $0` [ -r ] -b " + echo "e.g.: `basename $0` -r 1.1 -b /sonic-vs.image" + exit 0 +} + +while getopts "r:b:h" arg; do + case $arg in + h) + usage + ;; + r) + RELEASE=$OPTARG + ;; + b) + IMGFILE=$OPTARG + ;; + esac +done + +if [ ! -e ${IMGFILE} ]; then + echo "ERROR: ${IMGFILE} not found" + exit 2 +fi + + +MD5SUMIMGFILE=`md5sum ${IMGFILE} | cut -f 1 -d " "` +LENIMGFILE=`stat -c %s ${IMGFILE}` +GNS3APPNAME="SONiC-${RELEASE}.gns3a" +NAMEIMGFILE=`basename $IMGFILE` + +echo " +{ + \"name\": \"SONiC\", + \"category\": \"router\", + \"description\": \"SONiC Virtual Switch/Router\", + \"vendor_name\": \"SONiC\", + \"vendor_url\": \"https://azure.github.io/SONiC/\", + \"product_name\": \"SONiC\", + \"product_url\": \"https://azure.github.io/SONiC/\", + \"registry_version\": 3, + \"status\": \"experimental\", + \"maintainer\": \"SONiC\", + \"maintainer_email\": \"sonicproject@googlegroups.com\", + \"usage\": \"Supports SONiC release: ${RELEASE}\", + \"first_port_name\": \"eth0\", + \"qemu\": { + \"adapter_type\": \"e1000\", + \"adapters\": 10, + \"ram\": 2048, + \"hda_disk_interface\": \"virtio\", + \"arch\": \"x86_64\", + \"console_type\": \"telnet\", + \"boot_priority\": \"d\", + \"kvm\": \"require\" + }, + \"images\": [ + { + \"filename\": \"${NAMEIMGFILE}\", + \"version\": \"${RELEASE}\", + \"md5sum\": \"${MD5SUMIMGFILE}\", + \"filesize\": ${LENIMGFILE} + } + ], + \"versions\": [ + { + \"name\": \"${RELEASE}\", + \"images\": { + \"hda_disk_image\": \"${NAMEIMGFILE}\" + } + } + ] +} + +" > ${GNS3APPNAME} + diff --git a/platform/vs/sonic-version.dep b/platform/vs/sonic-version.dep new file mode 100644 index 000000000000..1398415bdad5 --- /dev/null +++ b/platform/vs/sonic-version.dep @@ -0,0 +1,2 @@ +#DPKG FRK +$(SONIC_VERSION)_CACHE_MODE := none diff --git a/platform/vs/sonic-version.mk b/platform/vs/sonic-version.mk new file mode 100644 index 000000000000..9e21573227b3 --- /dev/null +++ b/platform/vs/sonic-version.mk @@ -0,0 +1,13 @@ +# sonic version yml file + +sonic_version=$(SONIC_GET_VERSION) +sonic_asic_platform=$(CONFIGURED_PLATFORM) + +export sonic_version +export sonic_asic_platform + +SONIC_VERSION = sonic_version.yml +$(SONIC_VERSION)_SRC_PATH = $(PLATFORM_PATH)/sonic-version +SONIC_MAKE_FILES += $(SONIC_VERSION) + +SONIC_PHONY_TARGETS += $(addprefix $(FILES_PATH)/, $(SONIC_VERSION)) diff --git a/platform/vs/sonic-version/Makefile b/platform/vs/sonic-version/Makefile new file mode 100644 index 000000000000..2b2386031c9b --- /dev/null +++ b/platform/vs/sonic-version/Makefile @@ -0,0 +1,10 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = sonic_version.yml + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + ./build_sonic_version.sh $(MAIN_TARGET) + + mv $(MAIN_TARGET) $(DEST)/ diff --git a/platform/vs/sonic-version/build_sonic_version.sh b/platform/vs/sonic-version/build_sonic_version.sh new file mode 100755 index 000000000000..f118a1c20a6d --- /dev/null +++ b/platform/vs/sonic-version/build_sonic_version.sh @@ -0,0 +1,8 @@ +tee $1 > /dev/null < + sonic + 2048000 + 2048000 + 1 + + /machine + + + hvm + + + + + + + + destroy + restart + restart + + /usr/bin/qemu-system-x86_64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + diff --git a/platform/vs/sonic_multiasic.xml b/platform/vs/sonic_multiasic.xml new file mode 100644 index 000000000000..b571b5122a52 --- /dev/null +++ b/platform/vs/sonic_multiasic.xml @@ -0,0 +1,110 @@ + + sonic + 8 + 8 + + /machine + + + hvm + + + + + + + + destroy + restart + restart + + /usr/bin/qemu-system-x86_64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + diff --git a/platform/vs/syncd-vs.dep b/platform/vs/syncd-vs.dep new file mode 100644 index 000000000000..3b0cf002c9cf --- /dev/null +++ b/platform/vs/syncd-vs.dep @@ -0,0 +1,11 @@ +#DPKG FRK +DPATH := $($(SYNCD_VS)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/vs/syncd-vs.mk platform/vs/syncd-vs.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(SYNCD_VS)_CACHE_MODE := GIT_CONTENT_SHA +$(SYNCD_VS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SYNCD_VS)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(SYNCD_VS),$(SYNCD_VS_DBG))) diff --git a/platform/vs/syncd-vs.mk b/platform/vs/syncd-vs.mk new file mode 100644 index 000000000000..22b34fbcaae3 --- /dev/null +++ b/platform/vs/syncd-vs.mk @@ -0,0 +1,10 @@ +$(LIBSAIREDIS)_DPKG_TARGET = binary-syncd-vs + +SYNCD_VS = syncd-vs_1.0.0_amd64.deb +$(SYNCD_VS)_RDEPENDS += $(LIBSAIREDIS) $(LIBSAIMETADATA) $(LIBSAIVS) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(SYNCD_VS))) + +SYNCD_VS_DBG = syncd-vs-dbg_1.0.0_amd64.deb +$(SYNCD_VS_DBG)_DEPENDS += $(SYNCD_VS) +$(SYNCD_VS_DBG)_RDEPENDS += $(SYNCD_VS) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(SYNCD_VS_DBG))) diff --git a/platform/vs/tests/README.md b/platform/vs/tests/README.md new file mode 100644 index 000000000000..29ba27db62fc --- /dev/null +++ b/platform/vs/tests/README.md @@ -0,0 +1,4 @@ +Requirements: + +- Enable IPv6 for docker engine +- pip install exabgp diff --git a/platform/vs/tests/bgp/files/default_route/bgpd.conf b/platform/vs/tests/bgp/files/default_route/bgpd.conf new file mode 100644 index 000000000000..bc0dffcdbb8b --- /dev/null +++ b/platform/vs/tests/bgp/files/default_route/bgpd.conf @@ -0,0 +1,4 @@ +router bgp 65501 + bgp router-id 1.1.1.1 + no bgp ebgp-requires-policy + neighbor 10.10.10.1 remote-as 65502 diff --git a/platform/vs/tests/bgp/files/default_route/default_route.conf b/platform/vs/tests/bgp/files/default_route/default_route.conf new file mode 100644 index 000000000000..9f9d3cf32f80 --- /dev/null +++ b/platform/vs/tests/bgp/files/default_route/default_route.conf @@ -0,0 +1,17 @@ +neighbor 10.10.10.0 { + router-id 1.2.3.4; + local-address 10.10.10.1; + local-as 65502; + peer-as 65501; + group-updates false; + + family { + ipv4 unicast; + } + + static { + route 0.0.0.0/0 { + next-hop 10.10.10.1; + } + } +} diff --git a/platform/vs/tests/bgp/files/gr_livelock/bgpd.conf b/platform/vs/tests/bgp/files/gr_livelock/bgpd.conf new file mode 100644 index 000000000000..dc861ed46934 --- /dev/null +++ b/platform/vs/tests/bgp/files/gr_livelock/bgpd.conf @@ -0,0 +1,15 @@ +router bgp 65501 + bgp router-id 1.1.1.1 + no bgp ebgp-requires-policy + bgp graceful-restart restart-time 180 + bgp graceful-restart + neighbor 10.0.0.1 remote-as 65502 + address-family ipv4 + neighbor 10.0.0.1 activate + maximum-paths 64 + exit-address-family + neighbor 10.0.0.3 remote-as 65503 + address-family ipv4 + neighbor 10.0.0.3 activate + maximum-paths 64 + exit-address-family diff --git a/platform/vs/tests/bgp/files/gr_livelock/exabgp1.conf b/platform/vs/tests/bgp/files/gr_livelock/exabgp1.conf new file mode 100644 index 000000000000..0e78bd61db42 --- /dev/null +++ b/platform/vs/tests/bgp/files/gr_livelock/exabgp1.conf @@ -0,0 +1,21 @@ +neighbor 10.0.0.0 { + router-id 1.1.1.2; + local-address 10.0.0.1; + local-as 65502; + peer-as 65501; + group-updates false; + + family{ + ipv4 unicast; + } + + static { + route 1.1.1.1/32{ + next-hop 10.0.0.1; + community no-export; + } + route 2.2.2.2/32{ + next-hop 10.0.0.1; + } + } +} diff --git a/platform/vs/tests/bgp/files/gr_livelock/exabgp1.graceful.conf b/platform/vs/tests/bgp/files/gr_livelock/exabgp1.graceful.conf new file mode 100644 index 000000000000..377ed024d09e --- /dev/null +++ b/platform/vs/tests/bgp/files/gr_livelock/exabgp1.graceful.conf @@ -0,0 +1,26 @@ +neighbor 10.0.0.0 { + router-id 1.1.1.2; + local-address 10.0.0.1; + local-as 65502; + peer-as 65501; + group-updates false; + manual-eor true; + + family{ + ipv4 unicast; + } + + capability { + graceful-restart 360; + } + + static { + route 1.1.1.1/32{ + next-hop 10.0.0.1; + community no-export; + } + route 2.2.2.2/32{ + next-hop 10.0.0.1; + } + } +} diff --git a/platform/vs/tests/bgp/files/gr_livelock/exabgp2.conf b/platform/vs/tests/bgp/files/gr_livelock/exabgp2.conf new file mode 100644 index 000000000000..3e67c18a82f6 --- /dev/null +++ b/platform/vs/tests/bgp/files/gr_livelock/exabgp2.conf @@ -0,0 +1,11 @@ +neighbor 10.0.0.2 { + router-id 1.1.1.3; + local-address 10.0.0.3; + local-as 65503; + peer-as 65501; + group-updates false; + + family { + ipv4 unicast; + } +} diff --git a/platform/vs/tests/bgp/files/invalid_nexthop/bgpd.conf b/platform/vs/tests/bgp/files/invalid_nexthop/bgpd.conf new file mode 100644 index 000000000000..33d235576dab --- /dev/null +++ b/platform/vs/tests/bgp/files/invalid_nexthop/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 65501 + bgp router-id 1.1.1.1 + no bgp default ipv4-unicast + no bgp ebgp-requires-policy + neighbor fc00::2 remote-as 65502 + address-family ipv6 + neighbor fc00::2 activate + exit-address-family diff --git a/platform/vs/tests/bgp/files/invalid_nexthop/invalid_nexthop.conf b/platform/vs/tests/bgp/files/invalid_nexthop/invalid_nexthop.conf new file mode 100644 index 000000000000..60a327d7121d --- /dev/null +++ b/platform/vs/tests/bgp/files/invalid_nexthop/invalid_nexthop.conf @@ -0,0 +1,19 @@ +neighbor fc00::1 { + router-id 1.2.3.4; + local-address fc00::2; + local-as 65502; + peer-as 65501; + group-updates false; + + family { + ipv4 unicast; + ipv6 unicast; + } + + static { + route 3333::0/64 { + next-hop 0.0.0.0; + next-hop fc00::2; + } + } +} diff --git a/platform/vs/tests/bgp/files/no_export/bgpd.conf b/platform/vs/tests/bgp/files/no_export/bgpd.conf new file mode 100644 index 000000000000..cd87c330c299 --- /dev/null +++ b/platform/vs/tests/bgp/files/no_export/bgpd.conf @@ -0,0 +1,14 @@ +router bgp 65501 + bgp router-id 1.1.1.1 + no bgp default ipv4-unicast + no bgp ebgp-requires-policy + neighbor 10.0.0.1 remote-as 65502 + address-family ipv4 + neighbor 10.0.0.1 activate + maximum-paths 64 + exit-address-family + neighbor 10.0.0.3 remote-as 65503 + address-family ipv4 + neighbor 10.0.0.3 activate + maximum-paths 64 + exit-address-family diff --git a/platform/vs/tests/bgp/files/no_export/exabgp1.conf b/platform/vs/tests/bgp/files/no_export/exabgp1.conf new file mode 100644 index 000000000000..0e78bd61db42 --- /dev/null +++ b/platform/vs/tests/bgp/files/no_export/exabgp1.conf @@ -0,0 +1,21 @@ +neighbor 10.0.0.0 { + router-id 1.1.1.2; + local-address 10.0.0.1; + local-as 65502; + peer-as 65501; + group-updates false; + + family{ + ipv4 unicast; + } + + static { + route 1.1.1.1/32{ + next-hop 10.0.0.1; + community no-export; + } + route 2.2.2.2/32{ + next-hop 10.0.0.1; + } + } +} diff --git a/platform/vs/tests/bgp/files/no_export/exabgp2.conf b/platform/vs/tests/bgp/files/no_export/exabgp2.conf new file mode 100644 index 000000000000..3e67c18a82f6 --- /dev/null +++ b/platform/vs/tests/bgp/files/no_export/exabgp2.conf @@ -0,0 +1,11 @@ +neighbor 10.0.0.2 { + router-id 1.1.1.3; + local-address 10.0.0.3; + local-as 65503; + peer-as 65501; + group-updates false; + + family { + ipv4 unicast; + } +} diff --git a/platform/vs/tests/bgp/test_default_route.py b/platform/vs/tests/bgp/test_default_route.py new file mode 100644 index 000000000000..2cc9021ba78e --- /dev/null +++ b/platform/vs/tests/bgp/test_default_route.py @@ -0,0 +1,48 @@ +from swsscommon import swsscommon +import os +import re +import time +import json +import pytest + +def test_DefaultRoute(dvs, testlog): + + dvs.copy_file("/etc/frr/", "bgp/files/default_route/bgpd.conf") + dvs.runcmd("supervisorctl start bgpd") + dvs.runcmd("ip addr add 10.10.10.0/31 dev Ethernet0") + dvs.runcmd("config interface startup Ethernet0") + dvs.runcmd("ip route del 0.0.0.0/0") + dvs.runcmd("vtysh -c \"confgure terminal\" -c \"ip route 0.0.0.0/0 via 172.17.0.1 200\"") + + dvs.servers[0].runcmd("ip addr add 10.10.10.1/31 dev eth0") + dvs.servers[0].runcmd("ifconfig eth0 up") + + time.sleep(5) + + print(dvs.runcmd("supervisorctl status")) + + p = dvs.servers[0].runcmd_async("exabgp -d bgp/files/default_route/default_route.conf") + + time.sleep(10) + + (exit_code, output) = dvs.runcmd(["redis-cli", "hgetall", "ROUTE_TABLE:0.0.0.0/0"]) + print(exit_code, output) + + # make sure 10.10.10.1 is the correct next hop for default route + assert "10.10.10.1" in output + + # insert default route for table default + dvs.runcmd("ip route add default via 172.17.0.1 table default") + + (exit_code, output) = dvs.runcmd(["redis-cli", "hgetall", "ROUTE_TABLE:0.0.0.0/0"]) + print(exit_code, output) + + time.sleep(10) + # make sure 10.10.10.1 is still the correct next hop for default route + assert "10.10.10.1" in output + + p.terminate() + p = p.wait() + + + diff --git a/platform/vs/tests/bgp/test_gr_livelock.py b/platform/vs/tests/bgp/test_gr_livelock.py new file mode 100644 index 000000000000..cd72ffef3e4f --- /dev/null +++ b/platform/vs/tests/bgp/test_gr_livelock.py @@ -0,0 +1,142 @@ +from swsscommon import swsscommon +import os +import re +import time +import json +import random + +def output(dvs, title): + print("=========================== %s ===========================" % title) + exit_cod, sum_res = dvs.runcmd(["vtysh", "-c", "show ip bgp sum"]) + exit_code, all_route = dvs.runcmd(["vtysh", "-c", "show ip bgp"]) + exit_code, neig_1 = dvs.runcmd(["vtysh", "-c", "show ip bgp neighbors 10.0.0.1"]) + exit_code, announce_route_1 = dvs.runcmd(["vtysh", "-c", "show ip bgp neighbors 10.0.0.1 advertised-routes"]) + exit_code, received_route_1 = dvs.runcmd(["vtysh", "-c", "show ip bgp neighbors 10.0.0.1 routes"]) + exit_code, announce_route_3 = dvs.runcmd(["vtysh", "-c", "show ip bgp neighbors 10.0.0.3 advertised-routes"]) + exit_code, received_route_3 = dvs.runcmd(["vtysh", "-c", "show ip bgp neighbors 10.0.0.3 routes"]) + print("Summary:") + print(sum_res) + print("Received routes:") + print("10.0.0.1") + print(received_route_1) + print("10.0.0.3") + print(received_route_3) + print("Announces routes:") + print("10.0.0.1") + print(announce_route_1) + print("10.0.0.3") + print(announce_route_3) + print("Neighbors") + print("10.0.0.1") + print(neig_1) + print("======================================================") + +def mkdir(path): + if not os.path.exists(path): + os.makedirs(path) + +def remove(path): + if os.path.exists(path): + os.unlink(path) + +def get_target_env(idx): + return '/usr/local/etc/exabgp/exabgp_%d.env' % idx + +def prepare_exa_env(dvs, idx): + mkdir('/usr/local/etc') + mkdir('/usr/local/etc/exabgp') + tmp_name = '/tmp/env.%d.%d' % (random.randint(0, 10000000), os.getpid()) + dvs.servers[idx].runcmd("exabgp --fi > %s" % tmp_name) + with open(tmp_name) as r_fp: + with open(get_target_env(idx), 'w') as w_fp: + for line in r_fp: + if line.startswith('pipename'): + line = "pipename = 'exabgp.%d'\n" % idx + w_fp.write(line) + os.unlink(tmp_name) + + +def run_exa(dvs, idx, cfg): + prepare_exa_env(dvs, idx) + run_dir = "/var/run/exabgp" + mkdir(run_dir) + fifo_in_path = "%s/exabgp.%d.in" % (run_dir, idx) + fifo_out_path = "%s/exabgp.%d.out" % (run_dir, idx) + remove(fifo_in_path) + remove(fifo_out_path) + os.mkfifo(fifo_in_path) + os.mkfifo(fifo_out_path) + os.chmod(fifo_in_path, 0o666) + os.chmod(fifo_out_path, 0o666) + print("!!! Start exabgp instance %d" % idx) + cmd = "exabgp -d --env %s %s" % (get_target_env(idx), cfg) + print("Cmd is ___ %s ___" % cmd) + return dvs.servers[idx].runcmd_async(cmd) + +def run_exacli(dvs, idx, cmd): + return dvs.servers[idx].runcmd('exabgpcli --env %s %s' % (get_target_env(idx), cmd)) + +def test_gr_livelock(dvs, testlog): + # update exabgp to version 4.0.10 + dvs.servers[0].runcmd("pip install 'exabgp==4.0.10' --force-reinstall ") + # + dvs.copy_file("/etc/frr/", "bgp/files/gr_livelock/bgpd.conf") + dvs.runcmd("supervisorctl stop bgpd") + time.sleep(5) + dvs.runcmd("supervisorctl start bgpd") + dvs.runcmd("ip addr add 10.0.0.0/31 dev Ethernet0") + dvs.runcmd("config interface startup Ethernet0") + + dvs.runcmd("ip addr add 10.0.0.2/31 dev Ethernet4") + dvs.runcmd("config interface startup Ethernet4") + + dvs.servers[0].runcmd("ip addr add 10.0.0.1/31 dev eth0") + dvs.servers[0].runcmd("ifconfig eth0 up") + + dvs.servers[1].runcmd("ip addr add 10.0.0.3/31 dev eth0") + dvs.servers[1].runcmd("ifconfig eth0 up") + + time.sleep(5) + + # Run two bgp neighbors + p1 = run_exa(dvs, 0, "bgp/files/gr_livelock/exabgp1.conf") + p2 = run_exa(dvs, 1, "bgp/files/gr_livelock/exabgp2.conf") + + time.sleep(30) + + output(dvs, "First neighbor doesn't have GR enabled") + + # Check that we announce routes from the 1st neigbbor to 2nd, if 1st neighbor doesn't support graceful restart + _, announced_routes = dvs.runcmd(["vtysh", "-c", "show ip bgp neighbors 10.0.0.3 advertised-routes"]) + assert '2.2.2.2/32' in announced_routes + + # Stop 1st neighbor + run_exacli(dvs, 0, 'shutdown') + p1 = p1.wait() + + # Wait until frr thinks that 1st neighbor was shut down + time.sleep(300) + + # Start the 1st neighbor again with graceful restart enabled + p1 = run_exa(dvs, 0, "bgp/files/gr_livelock/exabgp1.graceful.conf") + + time.sleep(60) + + output(dvs, "First neighbor has GR enalbed") + + run_exacli(dvs, 0, 'announce route 1.10.0.0/24 next-hop self') + + time.sleep(60) + + output(dvs, "Announced a new route from the first neighbor") + + # Check that we announce all routes from the 1st neighbor + _, announced_routes = dvs.runcmd(["vtysh", "-c", "show ip bgp neighbors 10.0.0.3 advertised-routes"]) + assert '2.2.2.2/32' in announced_routes + assert '1.10.0.0/24' in announced_routes + + run_exacli(dvs, 0, 'shutdown') + p1 = p1.wait() + + run_exacli(dvs, 1, 'shutdown') + p2 = p2.wait() diff --git a/platform/vs/tests/bgp/test_invalid_nexthop.py b/platform/vs/tests/bgp/test_invalid_nexthop.py new file mode 100644 index 000000000000..3e8acd94e20d --- /dev/null +++ b/platform/vs/tests/bgp/test_invalid_nexthop.py @@ -0,0 +1,33 @@ +from swsscommon import swsscommon +import os +import re +import time +import json +import pytest + +def test_InvalidNexthop(dvs, testlog): + + dvs.copy_file("/etc/frr/", "bgp/files/invalid_nexthop/bgpd.conf") + dvs.runcmd("supervisorctl start bgpd") + dvs.runcmd("ip addr add fc00::1/126 dev Ethernet0") + dvs.runcmd("config interface startup Ethernet0") + + dvs.servers[0].runcmd("ip addr add fc00::2/126 dev eth0") + dvs.servers[0].runcmd("ifconfig eth0 up") + + time.sleep(5) + + print(dvs.runcmd("supervisorctl status")) + + p = dvs.servers[0].runcmd_async("exabgp -d bgp/files/invalid_nexthop/invalid_nexthop.conf") + + time.sleep(10) + + (exit_code, output) = dvs.runcmd(["vtysh", "-c", "show bgp ipv6"]) + + p.terminate() + p = p.wait() + + print(exit_code, output) + + assert "3333::/64" in output diff --git a/platform/vs/tests/bgp/test_no_export.py b/platform/vs/tests/bgp/test_no_export.py new file mode 100644 index 000000000000..b2c7c5e7cbde --- /dev/null +++ b/platform/vs/tests/bgp/test_no_export.py @@ -0,0 +1,44 @@ +from swsscommon import swsscommon +import os +import re +import time +import json + +def test_bounce(dvs, testlog): + dvs.copy_file("/etc/frr/", "bgp/files/no_export/bgpd.conf") + dvs.runcmd("supervisorctl start bgpd") + dvs.runcmd("ip addr add 10.0.0.0/31 dev Ethernet0") + dvs.runcmd("config interface startup Ethernet0") + + dvs.runcmd("ip addr add 10.0.0.2/31 dev Ethernet4") + dvs.runcmd("config interface startup Ethernet4") + + dvs.servers[0].runcmd("ip addr add 10.0.0.1/31 dev eth0") + dvs.servers[0].runcmd("ifconfig eth0 up") + + dvs.servers[1].runcmd("ip addr add 10.0.0.3/31 dev eth0") + dvs.servers[1].runcmd("ifconfig eth0 up") + + time.sleep(5) + + p1 = dvs.servers[0].runcmd_async("exabgp -d bgp/files/no_export/exabgp1.conf") + p2 = dvs.servers[1].runcmd_async("exabgp -d bgp/files/no_export/exabgp2.conf") + + time.sleep(60) + + (exit_code, sum_res) = dvs.runcmd(["vtysh", "-c", "show ip bgp sum"]) + (exit_code, all_route) = dvs.runcmd(["vtysh", "-c", "show ip bgp"]) + (exit_code, announce_route) = dvs.runcmd(["vtysh", "-c", "show ip bgp neighbors 10.0.0.3 advertised-routes"]) + + p1.terminate() + p1 = p1.wait() + + p2.terminate() + p2 = p2.wait() + + print(sum_res) + print(announce_route) + assert "1.1.1.1/32" in all_route + assert "1.1.1.1/32" not in announce_route + assert "2.2.2.2/32" in all_route + assert "2.2.2.2/32" in announce_route diff --git a/platform/vs/tests/breakout/sample_output/sample_new_port_config.json b/platform/vs/tests/breakout/sample_output/sample_new_port_config.json new file mode 100644 index 000000000000..7c5c190a3330 --- /dev/null +++ b/platform/vs/tests/breakout/sample_output/sample_new_port_config.json @@ -0,0 +1,252 @@ +{ + "Ethernet0_2x50G": { + "Ethernet2": { + "alias": "fortyGigE0/2", + "admin_status": "up", + "lanes": "27,28", + "speed": "50000", + "index": "0" + }, + "Ethernet0": { + "alias": "fortyGigE0/0", + "admin_status": "up", + "lanes": "25,26", + "speed": "50000", + "index": "0" + } + }, + "Ethernet12_1x50G_2x25G": { + "Ethernet12": { + "alias": "fortyGigE0/12", + "admin_status": "up", + "lanes": "37,38", + "speed": "50000", + "index": "3" + }, + "Ethernet14": { + "alias": "fortyGigE0/14", + "admin_status": "up", + "lanes": "39", + "speed": "25000", + "index": "3" + }, + "Ethernet15": { + "alias": "fortyGigE0/15", + "admin_status": "up", + "lanes": "40", + "speed": "25000", + "index": "3" + } + }, + "Ethernet0_2x50G": { + "Ethernet2": { + "alias": "fortyGigE0/2", + "admin_status": "up", + "lanes": "27,28", + "speed": "50000", + "index": "0" + }, + "Ethernet0": { + "alias": "fortyGigE0/0", + "admin_status": "up", + "lanes": "25,26", + "speed": "50000", + "index": "0" + } + }, + "Ethernet0_1x100G": { + "Ethernet0": { + "alias": "fortyGigE0/0", + "admin_status": "up", + "lanes": "25,26,27,28", + "speed": "100000", + "index": "0" + } + }, + "Ethernet0_4x25G": { + "Ethernet2": { + "alias": "fortyGigE0/2", + "admin_status": "up", + "lanes": "27", + "speed": "25000", + "index": "0" + }, + "Ethernet3": { + "alias": "fortyGigE0/3", + "admin_status": "up", + "lanes": "28", + "speed": "25000", + "index": "0" + }, + "Ethernet0": { + "alias": "fortyGigE0/0", + "admin_status": "up", + "lanes": "25", + "speed": "25000", + "index": "0" + }, + "Ethernet1": { + "alias": "fortyGigE0/1", + "admin_status": "up", + "lanes": "26", + "speed": "25000", + "index": "0" + } + }, + "Ethernet0_2x25G_1x50G": { + "Ethernet2": { + "alias": "fortyGigE0/2", + "admin_status": "up", + "lanes": "27,28", + "speed": "50000", + "index": "0" + }, + "Ethernet0": { + "alias": "fortyGigE0/0", + "admin_status": "up", + "lanes": "25", + "speed": "25000", + "index": "0" + }, + "Ethernet1": { + "alias": "fortyGigE0/1", + "admin_status": "up", + "lanes": "26", + "speed": "25000", + "index": "0" + } + }, + "Ethernet0_1x50G_2x25G": { + "Ethernet2": { + "alias": "fortyGigE0/2", + "admin_status": "up", + "lanes": "27", + "speed": "25000", + "index": "0" + }, + "Ethernet3": { + "alias": "fortyGigE0/3", + "admin_status": "up", + "lanes": "28", + "speed": "25000", + "index": "0" + }, + "Ethernet0": { + "alias": "fortyGigE0/0", + "admin_status": "up", + "lanes": "25,26", + "speed": "50000", + "index": "0" + } + }, + "Ethernet4_4x25G": { + "Ethernet6": { + "alias": "fortyGigE0/6", + "admin_status": "up", + "lanes": "31", + "speed": "25000", + "index": "1" + }, + "Ethernet7": { + "alias": "fortyGigE0/7", + "admin_status": "up", + "lanes": "32", + "speed": "25000", + "index": "1" + }, + "Ethernet4": { + "alias": "fortyGigE0/4", + "admin_status": "up", + "lanes": "29", + "speed": "25000", + "index": "1" + }, + "Ethernet5": { + "alias": "fortyGigE0/5", + "admin_status": "up", + "lanes": "30", + "speed": "25000", + "index": "1" + } + }, + "Ethernet4_2x50G": { + "Ethernet6": { + "alias": "fortyGigE0/6", + "admin_status": "up", + "lanes": "31,32", + "speed": "50000", + "index": "1" + }, + "Ethernet4": { + "alias": "fortyGigE0/4", + "admin_status": "up", + "lanes": "29,30", + "speed": "50000", + "index": "1" + } + }, + "Ethernet8_2x50G": { + "Ethernet8": { + "alias": "fortyGigE0/8", + "admin_status": "up", + "lanes": "33,34", + "speed": "50000", + "index": "2" + }, + "Ethernet10": { + "alias": "fortyGigE0/10", + "admin_status": "up", + "lanes": "35,36", + "speed": "50000", + "index": "2" + } + }, + "Ethernet8_1x50G_2x25G": { + "Ethernet10": { + "alias": "fortyGigE0/10", + "admin_status": "up", + "lanes": "35", + "speed": "25000", + "index": "2" + }, + "Ethernet11": { + "alias": "fortyGigE0/11", + "admin_status": "up", + "lanes": "36", + "speed": "25000", + "index": "2" + } + }, + "Ethernet8_2x25G_1x50G": { + "Ethernet8": { + "alias": "fortyGigE0/8", + "admin_status": "up", + "lanes": "33", + "speed": "25000", + "index": "2" + }, + "Ethernet9": { + "alias": "fortyGigE0/9", + "admin_status": "up", + "lanes": "34", + "speed": "25000", + "index": "2" + }, + "Ethernet10": { + "alias": "fortyGigE0/10", + "admin_status": "up", + "lanes": "35,36", + "speed": "50000", + "index": "2" + } + }, + "Ethernet8_1x100G": { + "Ethernet8": { + "alias": "fortyGigE0/8", + "admin_status": "up", + "lanes": "33,34,35,36", + "speed": "100000", + "index": "2" + } + } +} diff --git a/platform/vs/tests/breakout/test_breakout_cli.py b/platform/vs/tests/breakout/test_breakout_cli.py new file mode 100755 index 000000000000..d93dc0e044a6 --- /dev/null +++ b/platform/vs/tests/breakout/test_breakout_cli.py @@ -0,0 +1,168 @@ +from swsscommon import swsscommon +import time +import os +import json +import ast +import pytest +import collections + +@pytest.mark.usefixtures('dpb_setup_fixture') +class TestBreakoutCli(object): + def setup_db(self, dvs): + self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) + + def read_Json(self, dvs): + test_dir = os.path.dirname(os.path.realpath(__file__)) + sample_output_file = os.path.join(test_dir, 'sample_output', 'sample_new_port_config.json') + with open(sample_output_file, 'rb') as fh: + fh_data = json.load(fh) + + if not fh_data: + return False + expected = ast.literal_eval(json.dumps(fh_data)) + return expected + + def breakout(self, dvs, interface, brkout_mode): + (exitcode, result) = dvs.runcmd("config interface breakout {} {} -y".format(interface, brkout_mode)) + + if result.strip("\n")[0] == "[ERROR] Breakout feature is not available without platform.json file" : + pytest.skip("**** This test is not needed ****") + root_dir = os.path.dirname('/') + (exitcode, output_dict) = dvs.runcmd("jq '.' new_port_config.json") + if output_dict is None: + raise Exception("Breakout output cant be None") + + output_dict = ast.literal_eval(output_dict.strip()) + return output_dict + + # Check Initial Brakout Mode + def test_InitialBreakoutMode(self, dvs, testlog): + self.setup_db(dvs) + + output_dict = {} + brkoutTbl = swsscommon.Table(self.cdb, "BREAKOUT_CFG") + brkout_entries = brkoutTbl.getKeys() + assert len(brkout_entries) == 32 + + for key in brkout_entries: + (status, fvs) = brkoutTbl.get(key) + assert status + + brkout_mode = fvs[0][1] + output_dict[key] = brkout_mode + output = collections.OrderedDict(sorted(output_dict.items(), key=lambda t: t[0])) + expected_dict = \ + {'Ethernet8': '1x100G[40G]', 'Ethernet0': '1x100G[40G]', 'Ethernet4': '1x100G[40G]', \ + 'Ethernet108': '1x100G[40G]', 'Ethernet100': '1x100G[40G]', 'Ethernet104': '1x100G[40G]', \ + 'Ethernet68': '1x100G[40G]', 'Ethernet96': '1x100G[40G]', 'Ethernet124': '1x100G[40G]', \ + 'Ethernet92': '1x100G[40G]', 'Ethernet120': '1x100G[40G]', 'Ethernet52': '1x100G[40G]', \ + 'Ethernet56': '1x100G[40G]', 'Ethernet76': '1x100G[40G]', 'Ethernet72': '1x100G[40G]', \ + 'Ethernet32': '1x100G[40G]', 'Ethernet16': '1x100G[40G]', 'Ethernet36': '1x100G[40G]', \ + 'Ethernet12': '1x100G[40G]', 'Ethernet28': '1x100G[40G]', 'Ethernet88': '1x100G[40G]', \ + 'Ethernet116': '1x100G[40G]', 'Ethernet80': '1x100G[40G]', 'Ethernet112': '1x100G[40G]', \ + 'Ethernet84': '1x100G[40G]', 'Ethernet48': '1x100G[40G]', 'Ethernet44': '1x100G[40G]', \ + 'Ethernet40': '1x100G[40G]', 'Ethernet64': '1x100G[40G]', 'Ethernet60': '1x100G[40G]', \ + 'Ethernet20': '1x100G[40G]', 'Ethernet24': '1x100G[40G]'} + expected = collections.OrderedDict(sorted(expected_dict.items(), key=lambda t: t[0])) + assert output == expected + + # Breakout Cli Test Mode + def test_breakout_modes(self, dvs): + expected = self.read_Json(dvs) + assert expected + + print("**** Breakout Cli test Starts ****") + output_dict = self.breakout(dvs, 'Ethernet0', '2x50G') + expected_dict = expected["Ethernet0_2x50G"] + assert output_dict == expected_dict + print("**** 1X100G --> 2x50G passed ****") + + output_dict = self.breakout(dvs, 'Ethernet4', '4x25G[10G]') + expected_dict = expected["Ethernet4_4x25G"] + assert output_dict == expected_dict + print("**** 1X100G --> 4x25G[10G] passed ****") + + output_dict = self.breakout(dvs, 'Ethernet8', '2x25G(2)+1x50G(2)') + expected_dict = expected["Ethernet8_2x25G_1x50G"] + assert output_dict == expected_dict + print("**** 1X100G --> 2x25G(2)+1x50G(2) passed ****") + + output_dict = self.breakout(dvs, 'Ethernet12', '1x50G(2)+2x25G(2)') + expected_dict = expected["Ethernet12_1x50G_2x25G"] + assert output_dict == expected_dict + print("**** 1X100G --> 1x50G(2)+2x25G(2) passed ****") + + # TODOFIX: remove comments once #4442 PR got merged and + # yang model for DEVICE_METADATA becomes available. + # As below test cases are dependent on DEVICE_METADATA to go + # from a non-default breakout mode to a different breakout mode. + """ + output_dict = self.breakout(dvs, 'Ethernet0', '1x100G[40G]') + expected_dict = expected["Ethernet0_1x100G"] + assert output_dict == expected_dict + print("**** 2x50G --> 1x100G[40G] passed ****") + + output_dict = self.breakout(dvs, 'Ethernet0', '4x25G[10G]') + expected_dict = expected["Ethernet0_4x25G"] + assert output_dict == expected_dict + print("**** 1X100G --> 4x25G[10G] passed ****") + + output_dict = self.breakout(dvs, 'Ethernet0', '1x100G[40G]') + expected_dict = expected["Ethernet0_1x100G"] + assert output_dict == expected_dict + print("**** 4x25G[10G] --> 1x100G[40G] passed ****") + + output_dict = self.breakout(dvs, 'Ethernet4', '2x50G') + print("**** 1X100G --> 2x50G mode change ****") + + output_dict = self.breakout(dvs, 'Ethernet4', '4x25G[10G]') + expected_dict = expected["Ethernet4_4x25G"] + assert output_dict == expected_dict + print("**** 2X50G --> 4x25G[10G] passed ****") + + output_dict = self.breakout(dvs, 'Ethernet4', '2x50G') + expected_dict = expected["Ethernet4_2x50G"] + assert output_dict == expected_dict + print("**** 4x25G[10G] --> 2X50G passed ****") + + output_dict = self.breakout(dvs, 'Ethernet4', '1x100G[40G]') + print("**** 2x50G -- > 1X100G mode change ****") + + output_dict = self.breakout(dvs, 'Ethernet0', '2x25G(2)+1x50G(2)') + expected_dict = expected["Ethernet0_2x25G_1x50G"] + assert output_dict == expected_dict + print("**** 1x100G[40G] --> 2x25G(2)+1x50G(2) passed ****") + + output_dict = self.breakout(dvs, 'Ethernet0', '1x100G[40G]') + expected_dict = expected["Ethernet0_1x100G"] + assert output_dict == expected_dict + print("**** 2x25G(2)+1x50G(2) --> 1x100G[40G] passed ****") + + output_dict = self.breakout(dvs, 'Ethernet0', '1x50G(2)+2x25G(2)') + expected_dict = expected["Ethernet0_1x50G_2x25G"] + assert output_dict == expected_dict + print("**** 1x100G[40G] --> 1x50G(2)+2x25G(2) passed ****") + + output_dict = self.breakout(dvs, 'Ethernet0', '1x100G[40G]') + expected_dict = expected["Ethernet0_1x100G"] + assert output_dict == expected_dict + print("**** 1x50G(2)+2x25G(2) --> 1x100G[40G] passed ****") + + output_dict = self.breakout(dvs, 'Ethernet8', '2x50G') + print("**** 1x100G[40G] --> 2x50G mode change ****") + + output_dict = self.breakout(dvs, 'Ethernet8', '1x50G(2)+2x25G(2)') + expected_dict = expected["Ethernet8_1x50G_2x25G"] + assert output_dict == expected_dict + print("**** 2x50G --> 2x25G(2)+1x50G(2) passed ****") + + output_dict = self.breakout(dvs, 'Ethernet8', '2x25G(2)+1x50G(2)') + expected_dict = expected["Ethernet8_2x25G_1x50G"] + assert output_dict == expected_dict + print("**** 1x50G(2)+2x25G(2) --> 2x25G(2)+1x50G(2) passed ****") + + output_dict = self.breakout(dvs, 'Ethernet8', '1x100G[40G]') + expected_dict = expected["Ethernet8_1x100G"] + assert output_dict == expected_dict + print("**** 2x25G(2)+1x50G(2) --> 1x100G[40G] passed ****") + """ diff --git a/platform/vs/tests/conftest.py b/platform/vs/tests/conftest.py new file mode 120000 index 000000000000..9fef6363db02 --- /dev/null +++ b/platform/vs/tests/conftest.py @@ -0,0 +1 @@ +../../../src/sonic-swss/tests/conftest.py \ No newline at end of file diff --git a/platform/vs/tests/dvslib b/platform/vs/tests/dvslib new file mode 120000 index 000000000000..4bab298a1800 --- /dev/null +++ b/platform/vs/tests/dvslib @@ -0,0 +1 @@ +../../../src/sonic-swss/tests/dvslib \ No newline at end of file diff --git a/platform/vs/tests/teamd/test_portchannel.py b/platform/vs/tests/teamd/test_portchannel.py new file mode 100644 index 000000000000..0632bf874e52 --- /dev/null +++ b/platform/vs/tests/teamd/test_portchannel.py @@ -0,0 +1,37 @@ +from swsscommon import swsscommon +import time +import re +import json + +def test_PortChannel(dvs, testlog): + appldb = swsscommon.DBConnector(0, dvs.redis_sock, 0) + statdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) + + # create the lag + dvs.runcmd("config portchannel add PortChannel0001") + time.sleep(1) + + # test lag table in appl db + tbl = swsscommon.Table(appldb, "LAG_TABLE") + (status, fvs) = tbl.get("PortChannel0001") + assert status == True + + # test lag table in state db + tbl = swsscommon.Table(statdb, "LAG_TABLE") + (status, fvs) = tbl.get("PortChannel0001") + assert status == True + + # create the lag member + dvs.runcmd("config portchannel member add PortChannel0001 Ethernet112") + time.sleep(1) + + # test lag member table in appl db + tbl = swsscommon.Table(appldb, "LAG_MEMBER_TABLE") + (status, fvs) = tbl.get("PortChannel0001:Ethernet112") + assert status == True + + # remove the lag member + dvs.runcmd("config portchannel member del PortChannel0001 Ethernet112") + + # remove the lag + dvs.runcmd("config portchannel del PortChannel0001") diff --git a/push_docker.sh b/push_docker.sh new file mode 100755 index 000000000000..3e2da08d0b83 --- /dev/null +++ b/push_docker.sh @@ -0,0 +1,79 @@ +#! /bin/bash + +sonic_version="" +sonic_platform="" + +while getopts ":v:p:" opt +do + case ${opt} in + v ) # SONiC image version + sonic_version=${OPTARG} + ;; + p ) # Platform info + sonic_platform=${OPTARG} + ;; + \? ) echo "\ +Usage: [-v ] [ -p ] \ + []" + ;; + esac +done + +shift $((OPTIND -1)) + +DOCKER_IMAGE_FILE=$1 +REGISTRY_SERVER=$2 +REGISTRY_PORT=$3 +REGISTRY_USERNAME=$4 +REGISTRY_PASSWD=$5 +DOCKER_IMAGE_TAG=$6 +REGISTRY_SERVER_WITH_PORT=${REGISTRY_SERVER}${REGISTRY_PORT:+:$REGISTRY_PORT} + +push_it() { + # $1 - Given image name + # $2 - Remote image name + + docker tag $1 $2 + echo "Pushing $2" + image_sha=$(docker push $2 | sed -n "s/.*: digest: sha256:\([0-9a-f]*\).*/\\1/p") + echo "Remove $2" + docker rmi $2 || true + echo "Image sha256: $image_sha" +} + +set -e + +echo "Loading image ${DOCKER_IMAGE_FILE}" +docker load < ${DOCKER_IMAGE_FILE} + +## Login the docker image registry server +## Note: user name and password are passed from command line +docker login -u ${REGISTRY_USERNAME} -p "${REGISTRY_PASSWD}" ${REGISTRY_SERVER_WITH_PORT} + +## Get Docker image name +docker_image_name=$(basename ${DOCKER_IMAGE_FILE} | cut -d. -f1) +remote_image_name=${REGISTRY_SERVER_WITH_PORT}/${docker_image_name} + +[ -z "${DOCKER_IMAGE_TAG}" ] || { + push_it ${docker_image_name} ${remote_image_name}:${DOCKER_IMAGE_TAG} +} + +if [ -n "${sonic_version}" ] && [ -n "${sonic_platform}" ] +then + remote_image_name=${REGISTRY_SERVER_WITH_PORT}/sonic-dockers/${sonic_platform}/${docker_image_name}:${sonic_version} + push_it ${docker_image_name} ${remote_image_name} +else + ## Fetch the Jenkins build number if inside it + [ ${BUILD_NUMBER} ] || { + echo "No BUILD_NUMBER found, setting to 0." + BUILD_NUMBER="0" + } + + timestamp="$(date -u +%Y%m%d)" + build_version="${timestamp}.bld-${BUILD_NUMBER}" + push_it ${docker_image_name} ${remote_image_name}:${build_version} +fi + +docker rmi $docker_image_name || true +echo "Job completed" + diff --git a/rules/asyncsnmp-py3.dep b/rules/asyncsnmp-py3.dep new file mode 100644 index 000000000000..42911cb94acc --- /dev/null +++ b/rules/asyncsnmp-py3.dep @@ -0,0 +1,12 @@ + +SPATH := $($(ASYNCSNMP_PY3)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/asyncsnmp-py3.mk rules/asyncsnmp-py3.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(ASYNCSNMP_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(ASYNCSNMP_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(ASYNCSNMP_PY3)_DEP_FILES := $(DEP_FILES) +$(ASYNCSNMP_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(ASYNCSNMP_PY3)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/asyncsnmp-py3.mk b/rules/asyncsnmp-py3.mk new file mode 100644 index 000000000000..2592eb004ee8 --- /dev/null +++ b/rules/asyncsnmp-py3.mk @@ -0,0 +1,9 @@ +# asyncsnmp python2 wheel + +ASYNCSNMP_PY3 = asyncsnmp-2.1.0-py3-none-any.whl +$(ASYNCSNMP_PY3)_SRC_PATH = $(SRC_PATH)/sonic-snmpagent +$(ASYNCSNMP_PY3)_PYTHON_VERSION = 3 +# Depends on sonic-platform-common so it is possible to import sonic_psu +$(ASYNCSNMP_PY3)_DEPENDS += $(SWSSSDK_PY3) $(SONIC_PLATFORM_COMMON_PY3) +$(ASYNCSNMP_PY3)_DEBS_DEPENDS += $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) +SONIC_PYTHON_WHEELS += $(ASYNCSNMP_PY3) diff --git a/rules/bash.dep b/rules/bash.dep new file mode 100644 index 000000000000..9f2758be6d40 --- /dev/null +++ b/rules/bash.dep @@ -0,0 +1,10 @@ + +SPATH := $($(BASH)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/bash.mk rules/bash.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(BASH)_CACHE_MODE := GIT_CONTENT_SHA +$(BASH)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(BASH)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/bash.mk b/rules/bash.mk new file mode 100644 index 000000000000..9c0d0c1e86d1 --- /dev/null +++ b/rules/bash.mk @@ -0,0 +1,17 @@ +# bash package +# +# Created to patch memory-leak issue in the bash-package included in Debian-8 (Jessie) +# release. This rule file, and the associated building-infra created to solve this +# bug (src/bash/), should be eliminated once the migration to Debian-9 (Stretch) is +# completed. + +# Bash major release-number corresponding to Debian-8 (Jessie) +BASH_VERSION_MAJOR = 4.3 +# Bash complete release-number. This image contains all 4.3 fixes up to patch '42'. +BASH_VERSION_FULL = $(BASH_VERSION_MAJOR)-14 + +export BASH_VERSION_MAJOR BASH_VERSION_FULL + +BASH = bash_$(BASH_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(BASH)_SRC_PATH = $(SRC_PATH)/bash +SONIC_MAKE_DEBS += $(BASH) diff --git a/rules/config b/rules/config new file mode 100644 index 000000000000..b45ce2152806 --- /dev/null +++ b/rules/config @@ -0,0 +1,191 @@ +############################################################################### +## Configuration parameters for SONiC build system +############################################################################### + +# SONIC_CONFIG_PRINT_DEPENDENCIES - show dependencies for each invoked target. +# Before executing rule for each target its dependencies are printed to console. +# Uncomment next line to enable: +# SONIC_CONFIG_PRINT_DEPENDENCIES = y + +# SONIC_CONFIG_BUILD_JOBS - set number of jobs for parallel build. +# Corresponding -j argument will be passed to make command inside docker +# container. +SONIC_CONFIG_BUILD_JOBS = 1 + +# SONIC_CONFIG_MAKE_JOBS - set number of parallel make jobs per package. +# Corresponding -j argument will be passed to make/dpkg commands that build separate packages +SONIC_CONFIG_MAKE_JOBS = $(shell nproc) + +# DEFAULT_BUILD_LOG_TIMESTAMP - add timestamp in build log +# Supported format: simple, none +DEFAULT_BUILD_LOG_TIMESTAMP = none + +# SONIC_USE_DOCKER_BUILDKIT - use docker buildkit for build. +# If set to y SONiC build system will set environment variable DOCKER_BUILDKIT=1 +# to enable docker buildkit. +# This options will speed up docker image build time. +# NOTE: SONIC_USE_DOCKER_BUILDKIT will produce larger installable SONiC image +# because of a docker bug (more details: https://github.com/moby/moby/issues/38903) +# SONIC_USE_DOCKER_BUILDKIT = y + +# SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD - use native dockerd for build. +# If set to y SONiC build container will use native dockerd instead of dind for faster build +# SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD = y + +# SONIC_CONFIG_ENABLE_COLORS - enable colored output in build system. +# Comment next line to disable: +# SONIC_CONFIG_ENABLE_COLORS = y + +# DEFAULT_USERNAME - default username for installer build +DEFAULT_USERNAME = admin + +# DEFAULT_PASSWORD - default password for installer build +DEFAULT_PASSWORD = YourPaSsWoRd + +# ENABLE_DHCP_GRAPH_SERVICE - specify the source of minigraph to generate configuration file. +# If set to y SONiC will get the minigraph from graph service. Graph service URL need to be +# passed through DHCP option 225. +# If not set (default behavior) the default minigraph built into the image will be used. +# ENABLE_DHCP_GRAPH_SERVICE = y + +# ENABLE_ZTP - installs Zero Touch Provisioning support. +# ENABLE_ZTP = y + +# SHUTDOWN_BGP_ON_START - if set to y all bgp sessions will be in admin down state when +# bgp service starts. +# SHUTDOWN_BGP_ON_START = y + +# ENABLE_PFCWD_ON_START - if set to y PFC Watchdog (PFCWD) will be enabled all server-facing ports +# by default for TOR switch +# ENABLE_PFCWD_ON_START = y + +# INSTALL_DEBUG_TOOLS - installs debugging tools in baseline docker +# Uncomment next line to enable: +# INSTALL_DEBUG_TOOLS = y + +# SONIC_USE_PDDF_FRAMEWORK - Use PDDF generic drivers and plugins +# Uncomment next line to enable: +SONIC_USE_PDDF_FRAMEWORK = y + +# SONIC_ROUTING_STACK - specify the routing-stack being elected to drive SONiC's control-plane. +# Supported routing stacks on SONiC are: +# routing-stacks: quagga, frr. +SONIC_ROUTING_STACK = frr + +# ENABLE_SYNCD_RPC - build docker-syncd with rpc packages for testing purposes. +# Uncomment to enable: +# ENABLE_SYNCD_RPC = y + +# Enable Origanization Extensions - Specific to the deployment scenarios of the Organization +ENABLE_ORGANIZATION_EXTENSIONS = y + +# Debugging option allows sonic debian packages to get built including symbols +# information. Profiling option, disables compiler optimizations (-O0) as well +# as includes symbols information. Given that 'profiling' option is a superset +# of 'debugging' one, user should only enable either one option or the other -- +# if both options are enabled, the 'profiling' one will prevail. +#SONIC_DEBUGGING_ON = y +#SONIC_PROFILING_ON = y + +# DEFAULT_KERNEL_PROCURE_METHOD - default method for obtaining kernel +# build: build kernel from source +# download: download pre-built kernel from Azure storage. +DEFAULT_KERNEL_PROCURE_METHOD = build + +# FRR user and group id values. These only take effect when SONIC_ROUTING_STACK is frr. +# Note: these values match the admin uid/gid of the host's admin account. If these values +# change and user doesn't want the frr uid/gid to potentially match a random user on the +# host, then either the appropriate account and group will need to be created on the host +# manually or changes need to be made when the image is built to create the account and +# group during installation. +FRR_USER_UID = 300 +FRR_USER_GID = 300 + +# DPKG cache allows the .deb files to be stored in the cache path. This allows the submodules +# package to be cached and restored back if its commit hash is not modified and its dependencies are not modified. +# SONIC_DPKG_CACHE_METHOD - Default method of deb package caching +# none : no caching +# rwcache : Use cache if exists else build the source and update the cache +# wcache : Dont use the cache and just build the source and update the cache +# rcache : Use cache if exists, but dont update the cache +# cache : Same as rwcache +# SONIC_DPKG_CACHE_SOURCE - Stores the cache location details +SONIC_DPKG_CACHE_METHOD ?= none +SONIC_DPKG_CACHE_SOURCE ?= /var/cache/sonic/artifacts + +# Default VS build memory preparation +DEFAULT_VS_PREPARE_MEM = yes + + +# INCLUDE_SYSTEM_TELEMETRY - build docker-sonic-telemetry for system telemetry support +INCLUDE_SYSTEM_TELEMETRY = y + +# INCLUDE_ICCPD - build docker-iccpd for mclag support +INCLUDE_ICCPD = n + +# INCLUDE_SFLOW - build docker-sflow for sFlow support +INCLUDE_SFLOW = y + +# INCLUDE_MGMT_FRAMEWORK - build docker-sonic-mgmt-framework for CLI and REST server support +INCLUDE_MGMT_FRAMEWORK = y + +# ENABLE_HOST_SERVICE_ON_START - enable sonic-host-server for mgmt-framework and/or +# telemetry containers to access host functionality by default +ENABLE_HOST_SERVICE_ON_START = n + +# INCLUDE_RESTAPI - build docker-sonic-restapi for configuring the switch using REST APIs +INCLUDE_RESTAPI = n + +# INCLUDE_NAT - build docker-nat for nat support +INCLUDE_NAT = y + +# TELEMETRY_WRITABLE - Enable write/config operations via the gNMI interface. +# Uncomment to enable: +# TELEMETRY_WRITABLE = y +# INCLUDE_KUBERNETES - if set to y kubernetes packages are installed to be able to +# run as worker node in kubernetes cluster. +INCLUDE_KUBERNETES = n + +# INCLUDE_MACSEC - build docker-macsec for macsec support +INCLUDE_MACSEC = y + +# KUBERNETES_VERSION - Set to the required version. +# K8s_GCR_IO_PAUSE_VERSION - Version of k8s universal pause container image +# These are Used *only* when INCLUDE_KUBERNETES=y +# NOTE: As a worker node it has to run version compatible to kubernetes master. +# +KUBERNETES_VERSION = 1.18.6 +KUBERNETES_CNI_VERSION = 0.8.6 +K8s_GCR_IO_PAUSE_VERSION = 3.2 + +# SONIC_ENABLE_IMAGE_SIGNATURE - enable image signature +# To not use the auto-generated self-signed certificate, the required files to sign the image as below: +# SIGNING_KEY = +# SIGNING_CERT = +# CA_CERT = +# The relative path is build root folder. +SONIC_ENABLE_IMAGE_SIGNATURE ?= n + +# PACKAGE_URL_PREFIX - the package url prefix +PACKAGE_URL_PREFIX ?= https://packages.trafficmanager.net/public/packages + +# TRUSTED_GPG_URLS - the trusted gpgs, separated by comma +TRUSTED_GPG_URLS = https://packages.trafficmanager.net/debian/public_key.gpg,https://packages.microsoft.com/keys/microsoft.asc + +# SONIC_VERSION_CONTROL_COMPONENTS - Valid values: none|all|components..., the components consist of one or multiple: deb,py2,py3,web,git,docker, seperated by comma +# none : disable the version control +# all : enable the version control for all components +# deb : debian packages +# py2 : python2 packages +# py3 : python3 pakcages +# web : web packages, downloaded by wget, curl +# git : git repositories, donloaded by git clone +# docker: docker base images +SONIC_VERSION_CONTROL_COMPONENTS ?= none + +# SONiC docker registry +# +# Uncomment below line to enable pulling sonic-slave docker from registry +# ENABLE_DOCKER_BASE_PULL = y +REGISTRY_PORT=443 +REGISTRY_SERVER=sonicdev-microsoft.azurecr.io diff --git a/rules/dbsyncd-py3.dep b/rules/dbsyncd-py3.dep new file mode 100644 index 000000000000..42a31c2c4972 --- /dev/null +++ b/rules/dbsyncd-py3.dep @@ -0,0 +1,11 @@ +SPATH := $($(DBSYNCD_PY3)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/dbsyncd-py3.mk rules/dbsyncd-py3.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(DBSYNCD_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(DBSYNCD_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DBSYNCD_PY3)_DEP_FILES := $(DEP_FILES) +$(DBSYNCD_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(DBSYNCD_PY3)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/dbsyncd-py3.mk b/rules/dbsyncd-py3.mk new file mode 100644 index 000000000000..12cf13cafe3b --- /dev/null +++ b/rules/dbsyncd-py3.mk @@ -0,0 +1,8 @@ +# sonic-dbsyncd python3 wheel + +DBSYNCD_PY3 = sonic_d-2.0.0-py3-none-any.whl +$(DBSYNCD_PY3)_SRC_PATH = $(SRC_PATH)/sonic-dbsyncd +$(DBSYNCD_PY3)_PYTHON_VERSION = 3 +$(DBSYNCD_PY3)_DEPENDS += $(SWSSSDK_PY3) +$(DBSYNCD_PY3)_DEBS_DEPENDS += $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) +SONIC_PYTHON_WHEELS += $(DBSYNCD_PY3) diff --git a/rules/dhcpmon.dep b/rules/dhcpmon.dep new file mode 100644 index 000000000000..cd8a410a8e95 --- /dev/null +++ b/rules/dhcpmon.dep @@ -0,0 +1,10 @@ + +SPATH := $($(SONIC_DHCPMON)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/dhcpmon.mk rules/dhcpmon.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_DHCPMON)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_DHCPMON)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_DHCPMON)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/dhcpmon.mk b/rules/dhcpmon.mk new file mode 100644 index 000000000000..3d80d227c156 --- /dev/null +++ b/rules/dhcpmon.mk @@ -0,0 +1,8 @@ +# SONiC DHCP MONitor package + +SONIC_DHCPMON_VERSION = 1.0.0-0 +SONIC_DHCPMON_PKG_NAME = dhcpmon + +SONIC_DHCPMON = sonic-$(SONIC_DHCPMON_PKG_NAME)_$(SONIC_DHCPMON_VERSION)_$(CONFIGURED_ARCH).deb +$(SONIC_DHCPMON)_SRC_PATH = $(SRC_PATH)/$(SONIC_DHCPMON_PKG_NAME) +SONIC_DPKG_DEBS += $(SONIC_DHCPMON) diff --git a/rules/docker-base-buster.dep b/rules/docker-base-buster.dep new file mode 100644 index 000000000000..2cfd2403f7fe --- /dev/null +++ b/rules/docker-base-buster.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_BASE_BUSTER)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-base-buster.mk rules/docker-base-buster.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_BASE_BUSTER)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_BASE_BUSTER)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_BASE_BUSTER)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/docker-base-buster.mk b/rules/docker-base-buster.mk new file mode 100644 index 000000000000..86bfc5781466 --- /dev/null +++ b/rules/docker-base-buster.mk @@ -0,0 +1,16 @@ +# Docker base image (based on Debian Buster) + +DOCKER_BASE_BUSTER = docker-base-buster.gz +$(DOCKER_BASE_BUSTER)_PATH = $(DOCKERS_PATH)/docker-base-buster + +$(DOCKER_BASE_BUSTER)_DEPENDS += $(SOCAT) + +GDB = gdb +GDBSERVER = gdbserver +VIM = vim +OPENSSH = openssh-client +SSHPASS = sshpass +STRACE = strace +$(DOCKER_BASE_BUSTER)_DBG_IMAGE_PACKAGES += $(GDB) $(GDBSERVER) $(VIM) $(OPENSSH) $(SSHPASS) $(STRACE) + +SONIC_DOCKER_IMAGES += $(DOCKER_BASE_BUSTER) diff --git a/rules/docker-base-stretch.dep b/rules/docker-base-stretch.dep new file mode 100644 index 000000000000..dbbdd6b786ef --- /dev/null +++ b/rules/docker-base-stretch.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_BASE_STRETCH)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-base-stretch.mk rules/docker-base-stretch.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_BASE_STRETCH)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_BASE_STRETCH)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_BASE_STRETCH)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/docker-base-stretch.mk b/rules/docker-base-stretch.mk new file mode 100644 index 000000000000..de10f808286e --- /dev/null +++ b/rules/docker-base-stretch.mk @@ -0,0 +1,16 @@ +# Docker base image (based on Debian Stretch) + +DOCKER_BASE_STRETCH = docker-base-stretch.gz +$(DOCKER_BASE_STRETCH)_PATH = $(DOCKERS_PATH)/docker-base-stretch +$(DOCKER_BASE_STRETCH)_DEPENDS += $(SOCAT) + +GDB = gdb +GDBSERVER = gdbserver +VIM = vim +OPENSSH = openssh-client +SSHPASS = sshpass +STRACE = strace +$(DOCKER_BASE_STRETCH)_DBG_IMAGE_PACKAGES += $(GDB) $(GDBSERVER) $(VIM) $(OPENSSH) $(SSHPASS) $(STRACE) + +SONIC_DOCKER_IMAGES += $(DOCKER_BASE_STRETCH) +SONIC_STRETCH_DOCKERS += $(DOCKER_BASE_STRETCH) diff --git a/rules/docker-base.dep b/rules/docker-base.dep new file mode 100644 index 000000000000..8de00ced7745 --- /dev/null +++ b/rules/docker-base.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_BASE)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-base.mk rules/docker-base.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_BASE)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_BASE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_BASE)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/docker-base.mk b/rules/docker-base.mk new file mode 100644 index 000000000000..3b2ede987a70 --- /dev/null +++ b/rules/docker-base.mk @@ -0,0 +1,18 @@ +# docker base image + +DOCKER_BASE = docker-base.gz +$(DOCKER_BASE)_PATH = $(DOCKERS_PATH)/docker-base +$(DOCKER_BASE)_DEPENDS += $(BASH) +$(DOCKER_BASE)_DEPENDS += $(SOCAT) + +ifeq ($(INSTALL_DEBUG_TOOLS),y) +GDB = gdb +GDBSERVER = gdbserver +VIM = vim +OPENSSH = openssh-client +SSHPASS = sshpass +STRACE = strace +$(DOCKER_BASE)_DBG_PACKAGES += $(GDB) $(GDBSERVER) $(VIM) $(OPENSSH) $(SSHPASS) $(STRACE) +endif + +SONIC_DOCKER_IMAGES += $(DOCKER_BASE) diff --git a/rules/docker-config-engine-buster.dep b/rules/docker-config-engine-buster.dep new file mode 100644 index 000000000000..ae1ec40ccc9e --- /dev/null +++ b/rules/docker-config-engine-buster.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_CONFIG_ENGINE_BUSTER)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-config-engine-buster.mk rules/docker-config-engine-buster.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_CONFIG_ENGINE_BUSTER)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_CONFIG_ENGINE_BUSTER)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_CONFIG_ENGINE_BUSTER)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/docker-config-engine-buster.mk b/rules/docker-config-engine-buster.mk new file mode 100644 index 000000000000..b386c882f4c5 --- /dev/null +++ b/rules/docker-config-engine-buster.mk @@ -0,0 +1,17 @@ +# docker image for sonic config engine + +DOCKER_CONFIG_ENGINE_BUSTER = docker-config-engine-buster.gz +$(DOCKER_CONFIG_ENGINE_BUSTER)_PATH = $(DOCKERS_PATH)/docker-config-engine-buster + +$(DOCKER_CONFIG_ENGINE_BUSTER)_DEPENDS += $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) +$(DOCKER_CONFIG_ENGINE_BUSTER)_PYTHON_WHEELS += $(SWSSSDK_PY3) +$(DOCKER_CONFIG_ENGINE_BUSTER)_PYTHON_WHEELS += $(SONIC_PY_COMMON_PY3) +$(DOCKER_CONFIG_ENGINE_BUSTER)_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE_PY3) +$(DOCKER_CONFIG_ENGINE_BUSTER)_LOAD_DOCKERS += $(DOCKER_BASE_BUSTER) +$(DOCKER_CONFIG_ENGINE_BUSTER)_FILES += $(SWSS_VARS_TEMPLATE) +$(DOCKER_CONFIG_ENGINE_BUSTER)_FILES += $($(SONIC_CTRMGRD)_CONTAINER_SCRIPT) + +$(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS = $($(DOCKER_BASE_BUSTER)_DBG_DEPENDS) +$(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES = $($(DOCKER_BASE_BUSTER)_DBG_IMAGE_PACKAGES) + +SONIC_DOCKER_IMAGES += $(DOCKER_CONFIG_ENGINE_BUSTER) diff --git a/rules/docker-config-engine-stretch.dep b/rules/docker-config-engine-stretch.dep new file mode 100644 index 000000000000..2562558f9fc0 --- /dev/null +++ b/rules/docker-config-engine-stretch.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_CONFIG_ENGINE_STRETCH)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-config-engine-stretch.mk rules/docker-config-engine-stretch.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_CONFIG_ENGINE_STRETCH)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_CONFIG_ENGINE_STRETCH)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_CONFIG_ENGINE_STRETCH)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/docker-config-engine-stretch.mk b/rules/docker-config-engine-stretch.mk new file mode 100644 index 000000000000..7e90c1587a9d --- /dev/null +++ b/rules/docker-config-engine-stretch.mk @@ -0,0 +1,16 @@ +# docker image for sonic config engine + +DOCKER_CONFIG_ENGINE_STRETCH = docker-config-engine-stretch.gz +$(DOCKER_CONFIG_ENGINE_STRETCH)_PATH = $(DOCKERS_PATH)/docker-config-engine-stretch +$(DOCKER_CONFIG_ENGINE_STRETCH)_DEPENDS += $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) +$(DOCKER_CONFIG_ENGINE_STRETCH)_PYTHON_WHEELS += $(SWSSSDK_PY2) +$(DOCKER_CONFIG_ENGINE_STRETCH)_PYTHON_WHEELS += $(SONIC_PY_COMMON_PY2) +$(DOCKER_CONFIG_ENGINE_STRETCH)_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE_PY2) +$(DOCKER_CONFIG_ENGINE_STRETCH)_LOAD_DOCKERS += $(DOCKER_BASE_STRETCH) +$(DOCKER_CONFIG_ENGINE_STRETCH)_FILES += $(SWSS_VARS_TEMPLATE) + +$(DOCKER_CONFIG_ENGINE_STRETCH)_DBG_DEPENDS = $($(DOCKER_BASE_STRETCH)_DBG_DEPENDS) +$(DOCKER_CONFIG_ENGINE_STRETCH)_DBG_IMAGE_PACKAGES = $($(DOCKER_BASE_STRETCH)_DBG_IMAGE_PACKAGES) + +SONIC_DOCKER_IMAGES += $(DOCKER_CONFIG_ENGINE_STRETCH) +SONIC_STRETCH_DOCKERS += $(DOCKER_CONFIG_ENGINE_STRETCH) diff --git a/rules/docker-config-engine.dep b/rules/docker-config-engine.dep new file mode 100644 index 000000000000..f9cbaa92f0bb --- /dev/null +++ b/rules/docker-config-engine.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_CONFIG_ENGINE)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-config-engine.mk rules/docker-config-engine.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_CONFIG_ENGINE)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_CONFIG_ENGINE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_CONFIG_ENGINE)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/docker-config-engine.mk b/rules/docker-config-engine.mk new file mode 100644 index 000000000000..518e73415a6b --- /dev/null +++ b/rules/docker-config-engine.mk @@ -0,0 +1,10 @@ +# docker image for sonic config engine + +DOCKER_CONFIG_ENGINE = docker-config-engine.gz +$(DOCKER_CONFIG_ENGINE)_PATH = $(DOCKERS_PATH)/docker-config-engine +$(DOCKER_CONFIG_ENGINE)_PYTHON_WHEELS += $(SWSSSDK_PY2) +$(DOCKER_CONFIG_ENGINE)_PYTHON_WHEELS += $(SONIC_PY_COMMON_PY2) +$(DOCKER_CONFIG_ENGINE)_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE_PY2) +$(DOCKER_CONFIG_ENGINE)_LOAD_DOCKERS += $(DOCKER_BASE) +$(DOCKER_CONFIG_ENGINE)_FILES += $(SWSS_VARS_TEMPLATE) +SONIC_DOCKER_IMAGES += $(DOCKER_CONFIG_ENGINE) diff --git a/rules/docker-database.dep b/rules/docker-database.dep new file mode 100644 index 000000000000..85e807d8cacf --- /dev/null +++ b/rules/docker-database.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_DATABASE)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-database.mk rules/docker-database.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_DATABASE)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_DATABASE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_DATABASE)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_DATABASE),$(DOCKER_DATABASE_DBG))) diff --git a/rules/docker-database.mk b/rules/docker-database.mk new file mode 100644 index 000000000000..0a2f46d19223 --- /dev/null +++ b/rules/docker-database.mk @@ -0,0 +1,28 @@ +# docker image for database + +DOCKER_DATABASE_STEM = docker-database +DOCKER_DATABASE = $(DOCKER_DATABASE_STEM).gz +DOCKER_DATABASE_DBG = $(DOCKER_DATABASE_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_DATABASE)_PATH = $(DOCKERS_PATH)/$(DOCKER_DATABASE_STEM) + +$(DOCKER_DATABASE)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) + +$(DOCKER_DATABASE)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_DATABASE)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_DATABASE) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_DATABASE) + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_DATABASE_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_DATABASE_DBG) + +$(DOCKER_DATABASE)_CONTAINER_NAME = database +$(DOCKER_DATABASE)_RUN_OPT += --privileged -t +$(DOCKER_DATABASE)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_DATABASE)_BASE_IMAGE_FILES += redis-cli:/usr/bin/redis-cli +$(DOCKER_DATABASE)_BASE_IMAGE_FILES += monit_database:/etc/monit/conf.d +$(DOCKER_DATABASE)_FILES += $(SYSCTL_NET_CONFIG) $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +$(DOCKER_DATABASE)_FILES += $(UPDATE_CHASSISDB_CONFIG_SCRIPT) diff --git a/rules/docker-dhcp-relay.dep b/rules/docker-dhcp-relay.dep new file mode 100644 index 000000000000..996e346da98a --- /dev/null +++ b/rules/docker-dhcp-relay.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_DHCP_RELAY)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-dhcp-relay.mk rules/docker-dhcp-relay.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_DHCP_RELAY)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_DHCP_RELAY)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_DHCP_RELAY)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_DHCP_RELAY),$(DOCKER_DHCP_RELAY_DBG))) diff --git a/rules/docker-dhcp-relay.mk b/rules/docker-dhcp-relay.mk new file mode 100644 index 000000000000..6be9bb79fda4 --- /dev/null +++ b/rules/docker-dhcp-relay.mk @@ -0,0 +1,28 @@ +# Docker image for DHCP relay + +DOCKER_DHCP_RELAY_STEM = docker-dhcp-relay +DOCKER_DHCP_RELAY = $(DOCKER_DHCP_RELAY_STEM).gz +DOCKER_DHCP_RELAY_DBG = $(DOCKER_DHCP_RELAY_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_DHCP_RELAY)_PATH = $(DOCKERS_PATH)/$(DOCKER_DHCP_RELAY_STEM) + +$(DOCKER_DHCP_RELAY)_DEPENDS += $(ISC_DHCP_RELAY) $(SONIC_DHCPMON) + +$(DOCKER_DHCP_RELAY)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_DHCP_RELAY)_DBG_DEPENDS += $(ISC_DHCP_RELAY_DBG) + +$(DOCKER_DHCP_RELAY)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_DHCP_RELAY)_LOAD_DOCKERS = $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_DHCP_RELAY) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_DHCP_RELAY) + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_DHCP_RELAY_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_DHCP_RELAY_DBG) + +$(DOCKER_DHCP_RELAY)_CONTAINER_NAME = dhcp_relay +$(DOCKER_DHCP_RELAY)_RUN_OPT += --privileged -t +$(DOCKER_DHCP_RELAY)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_DHCP_RELAY)_RUN_OPT += -v /usr/share/sonic/scripts:/usr/share/sonic/scripts:ro +$(DOCKER_DHCP_RELAY)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/docker-fpm-frr.dep b/rules/docker-fpm-frr.dep new file mode 100644 index 000000000000..47deac0c32fd --- /dev/null +++ b/rules/docker-fpm-frr.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_FPM_FRR)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-fpm-frr.mk rules/docker-fpm-frr.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_FPM_FRR)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_FPM_FRR)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_FPM_FRR)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_FPM_FRR),$(DOCKER_FPM_FRR_DBG))) diff --git a/rules/docker-fpm-frr.mk b/rules/docker-fpm-frr.mk new file mode 100644 index 000000000000..1ea79bc80a42 --- /dev/null +++ b/rules/docker-fpm-frr.mk @@ -0,0 +1,34 @@ +# docker image for fpm-frr + +DOCKER_FPM_FRR_STEM = docker-fpm-frr +DOCKER_FPM_FRR = $(DOCKER_FPM_FRR_STEM).gz +DOCKER_FPM_FRR_DBG = $(DOCKER_FPM_FRR_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_FPM_FRR)_PATH = $(DOCKERS_PATH)/$(DOCKER_FPM_FRR_STEM) +$(DOCKER_FPM_FRR)_PYTHON_WHEELS += $(SONIC_BGPCFGD) $(SONIC_FRR_MGMT_FRAMEWORK) + +$(DOCKER_FPM_FRR)_DEPENDS += $(FRR) $(FRR_SNMP) $(SWSS) $(LIBYANG1) +$(DOCKER_FPM_FRR)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_FPM_FRR)_DBG_DEPENDS += $(SWSS_DBG) $(LIBSWSSCOMMON_DBG) \ + $(FRR_DBG) $(FRR_SNMP_DBG) $(LIBYANG1_DBG) + +$(DOCKER_FPM_FRR)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_FPM_FRR)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_FPM_FRR) + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_FPM_FRR_DBG) + +$(DOCKER_FPM_FRR)_CONTAINER_NAME = bgp +$(DOCKER_FPM_FRR)_RUN_OPT += --privileged -t +$(DOCKER_FPM_FRR)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_FPM_FRR)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) + +$(DOCKER_FPM_FRR)_BASE_IMAGE_FILES += vtysh:/usr/bin/vtysh +$(DOCKER_FPM_FRR)_BASE_IMAGE_FILES += TSA:/usr/bin/TSA +$(DOCKER_FPM_FRR)_BASE_IMAGE_FILES += TSB:/usr/bin/TSB +$(DOCKER_FPM_FRR)_BASE_IMAGE_FILES += TSC:/usr/bin/TSC +$(DOCKER_FPM_FRR)_BASE_IMAGE_FILES += TS:/usr/bin/TS +$(DOCKER_FPM_FRR)_BASE_IMAGE_FILES += monit_bgp:/etc/monit/conf.d diff --git a/rules/docker-fpm-gobgp.dep b/rules/docker-fpm-gobgp.dep new file mode 100644 index 000000000000..4cbb49578754 --- /dev/null +++ b/rules/docker-fpm-gobgp.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_FPM_GOBGP)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-fpm-gobgp.mk rules/docker-fpm-gobgp.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_FPM_GOBGP)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_FPM_GOBGP)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_FPM_GOBGP)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/docker-fpm-gobgp.mk b/rules/docker-fpm-gobgp.mk new file mode 100644 index 000000000000..03ec88e85b56 --- /dev/null +++ b/rules/docker-fpm-gobgp.mk @@ -0,0 +1,12 @@ +# docker image for fpm-gobgp + +DOCKER_FPM_GOBGP = docker-fpm-gobgp.gz +$(DOCKER_FPM_GOBGP)_PATH = $(DOCKERS_PATH)/docker-fpm-gobgp +$(DOCKER_FPM_GOBGP)_DEPENDS += $(GOBGP) +$(DOCKER_FPM_GOBGP)_LOAD_DOCKERS += $(DOCKER_FPM_QUAGGA) +SONIC_DOCKER_IMAGES += $(DOCKER_FPM_GOBGP) + +$(DOCKER_FPM_GOBGP)_CONTAINER_NAME = bgp +$(DOCKER_FPM_GOBGP)_RUN_OPT += --privileged -t +$(DOCKER_FPM_GOBGP)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_FPM_GOBPG)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/docker-fpm-quagga.dep b/rules/docker-fpm-quagga.dep new file mode 100644 index 000000000000..987e22b596c6 --- /dev/null +++ b/rules/docker-fpm-quagga.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_FPM_QUAGGA)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-fpm-quagga.mk rules/docker-fpm-quagga.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_FPM_QUAGGA)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_FPM_QUAGGA)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_FPM_QUAGGA)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/docker-fpm-quagga.mk b/rules/docker-fpm-quagga.mk new file mode 100644 index 000000000000..5a384eedab2c --- /dev/null +++ b/rules/docker-fpm-quagga.mk @@ -0,0 +1,15 @@ +# docker image for fpm-quagga + +DOCKER_FPM_QUAGGA = docker-fpm-quagga.gz +$(DOCKER_FPM_QUAGGA)_PATH = $(DOCKERS_PATH)/docker-fpm-quagga +$(DOCKER_FPM_QUAGGA)_DEPENDS += $(QUAGGA) $(SWSS) +$(DOCKER_FPM_QUAGGA)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_FPM_QUAGGA) + +$(DOCKER_FPM_QUAGGA)_CONTAINER_NAME = bgp +$(DOCKER_FPM_QUAGGA)_RUN_OPT += --privileged -t +$(DOCKER_FPM_QUAGGA)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_FPM_QUAGGA)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) + +$(DOCKER_FPM_QUAGGA)_BASE_IMAGE_FILES += vtysh:/usr/bin/vtysh diff --git a/rules/docker-fpm.dep b/rules/docker-fpm.dep new file mode 100644 index 000000000000..126cdbbd9a20 --- /dev/null +++ b/rules/docker-fpm.dep @@ -0,0 +1,11 @@ +#DPKG FRK + +DOCKER_FPM := $(filter $(DOCKER_FPM_QUAGGA) $(DOCKER_FPM_FRR) $(DOCKER_FPM_GOBGP), $(SONIC_INSTALL_DOCKER_IMAGES) ) +DPATH := $($(DOCKER_FPM)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-fpm.mk rules/docker-fpm.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_FPM)_DEP_FILES += $(DEP_FILES) + + diff --git a/rules/docker-fpm.mk b/rules/docker-fpm.mk new file mode 100644 index 000000000000..72d89999c47a --- /dev/null +++ b/rules/docker-fpm.mk @@ -0,0 +1,10 @@ +# Docker-fpm rule-file is simply a wrapper containing routing-stack selection logic. + +ifeq ($(SONIC_ROUTING_STACK), quagga) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_FPM_QUAGGA) +else ifeq ($(SONIC_ROUTING_STACK), frr) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_FPM_FRR) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_FPM_FRR_DBG) +else +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_FPM_GOBGP) +endif diff --git a/rules/docker-iccpd.dep b/rules/docker-iccpd.dep new file mode 100644 index 000000000000..878d1711c3b1 --- /dev/null +++ b/rules/docker-iccpd.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_ICCPD)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-iccpd.mk rules/docker-iccpd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_ICCPD)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_ICCPD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_ICCPD)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_ICCPD),$(DOCKER_ICCPD_DBG))) diff --git a/rules/docker-iccpd.mk b/rules/docker-iccpd.mk new file mode 100644 index 000000000000..da77d9c9c1fd --- /dev/null +++ b/rules/docker-iccpd.mk @@ -0,0 +1,24 @@ +# docker image for iccpd agent + +DOCKER_ICCPD_STEM = docker-iccpd +DOCKER_ICCPD = $(DOCKER_ICCPD_STEM).gz +DOCKER_ICCPD_DBG = $(DOCKER_ICCPD_STEM)-$(DBG_IMAGE_MARK).gz +$(DOCKER_ICCPD)_PATH = $(DOCKERS_PATH)/$(DOCKER_ICCPD_STEM) +$(DOCKER_ICCPD)_DEPENDS += $(SWSS) $(ICCPD) +$(DOCKER_ICCPD)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_ICCPD)_DBG_DEPENDS += $(SWSS_DBG) $(LIBSWSSCOMMON_DBG) $(ICCPD_DBG) +$(DOCKER_ICCPD)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) +$(DOCKER_ICCPD)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +ifeq ($(INCLUDE_ICCPD), y) +SONIC_DOCKER_IMAGES += $(DOCKER_ICCPD) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ICCPD) +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_ICCPD_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_ICCPD_DBG) +endif + +$(DOCKER_ICCPD)_CONTAINER_NAME = iccpd +$(DOCKER_ICCPD)_RUN_OPT += --privileged -t +$(DOCKER_ICCPD)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_ICCPD)_BASE_IMAGE_FILES += mclagdctl:/usr/bin/mclagdctl diff --git a/rules/docker-lldp.dep b/rules/docker-lldp.dep new file mode 100644 index 000000000000..ee7935ea9222 --- /dev/null +++ b/rules/docker-lldp.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_LLDP)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-lldp.mk rules/docker-lldp.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_LLDP)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_LLDP)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_LLDP)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_LLDP),$(DOCKER_LLDP_DBG))) diff --git a/rules/docker-lldp.mk b/rules/docker-lldp.mk new file mode 100644 index 000000000000..5cd4fd02a04f --- /dev/null +++ b/rules/docker-lldp.mk @@ -0,0 +1,33 @@ +# docker image for lldp agent + +DOCKER_LLDP_STEM = docker-lldp +DOCKER_LLDP = $(DOCKER_LLDP_STEM).gz +DOCKER_LLDP_DBG = $(DOCKER_LLDP_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_LLDP)_PATH = $(DOCKERS_PATH)/docker-lldp + +$(DOCKER_LLDP)_DEPENDS += $(LLDPD) $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) + +$(DOCKER_LLDP)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_LLDP)_DBG_DEPENDS += $(LLDPD_DBG) $(LIBSWSSCOMMON_DBG) + +$(DOCKER_LLDP)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_LLDP)_PYTHON_WHEELS += $(DBSYNCD_PY3) +$(DOCKER_LLDP)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_LLDP) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_LLDP) + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_LLDP_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_LLDP_DBG) + +$(DOCKER_LLDP)_CONTAINER_NAME = lldp +$(DOCKER_LLDP)_RUN_OPT += --privileged -t +$(DOCKER_LLDP)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_LLDP)_RUN_OPT += -v /usr/share/sonic/scripts:/usr/share/sonic/scripts:ro + +$(DOCKER_LLDP)_BASE_IMAGE_FILES += lldpctl:/usr/bin/lldpctl +$(DOCKER_LLDP)_BASE_IMAGE_FILES += lldpcli:/usr/bin/lldpcli +$(DOCKER_LLDP)_BASE_IMAGE_FILES += monit_lldp:/etc/monit/conf.d +$(DOCKER_LLDP)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/docker-macsec.dep b/rules/docker-macsec.dep new file mode 100644 index 000000000000..3ceab4fff36a --- /dev/null +++ b/rules/docker-macsec.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_MACSEC)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-macsec.mk rules/docker-macsec.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_MACSEC)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_MACSEC)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_MACSEC)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_MACSEC),$(DOCKER_MACSEC_DBG))) diff --git a/rules/docker-macsec.mk b/rules/docker-macsec.mk new file mode 100644 index 000000000000..e112a8fd3d8a --- /dev/null +++ b/rules/docker-macsec.mk @@ -0,0 +1,33 @@ +# docker image for macsec agent + +DOCKER_MACSEC_STEM = docker-macsec +DOCKER_MACSEC = $(DOCKER_MACSEC_STEM).gz +DOCKER_MACSEC_DBG = $(DOCKER_MACSEC_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_MACSEC)_PATH = $(DOCKERS_PATH)/$(DOCKER_MACSEC_STEM) + +$(DOCKER_MACSEC)_DEPENDS += $(SWSS) $(WPASUPPLICANT) $(REDIS_TOOLS) $(LIBNL3) $(LIBNL_GENL3) $(LIBNL_ROUTE3) +$(DOCKER_MACSEC)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_MACSEC)_DBG_DEPENDS += $(SWSS_DBG) $(LIBSWSSCOMMON_DBG) +$(DOCKER_MACSEC)_DBG_DEPENDS += $(WPASUPPLICANT_DBG) + +$(DOCKER_MACSEC)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_MACSEC)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_MACSEC) +ifeq ($(INCLUDE_MACSEC), y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_MACSEC) +endif + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_MACSEC_DBG) +ifeq ($(INCLUDE_MACSEC), y) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_MACSEC_DBG) +endif + +$(DOCKER_MACSEC)_CONTAINER_NAME = macsec +$(DOCKER_MACSEC)_RUN_OPT += --privileged -t +$(DOCKER_MACSEC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_MACSEC)_RUN_OPT += -v /host/warmboot:/var/warmboot + +$(DOCKER_MACSEC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/docker-nat.dep b/rules/docker-nat.dep new file mode 100644 index 000000000000..a8f28f2ea30b --- /dev/null +++ b/rules/docker-nat.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_NAT)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-nat.mk rules/docker-nat.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_NAT)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_NAT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_NAT)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_NAT),$(DOCKER_NAT_DBG))) diff --git a/rules/docker-nat.mk b/rules/docker-nat.mk new file mode 100644 index 000000000000..981019dbcdb6 --- /dev/null +++ b/rules/docker-nat.mk @@ -0,0 +1,33 @@ +# docker image for nat + +DOCKER_NAT_STEM = docker-nat +DOCKER_NAT = $(DOCKER_NAT_STEM).gz +DOCKER_NAT_DBG = $(DOCKER_NAT_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_NAT)_PATH = $(DOCKERS_PATH)/$(DOCKER_NAT_STEM) + +$(DOCKER_NAT)_DEPENDS += $(SWSS) $(IPTABLESIP4TC) $(IPTABLESIP6TC) $(IPTABLESIPTC) $(IPXTABLES12) $(IPTABLES) +$(DOCKER_NAT)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_NAT)_DBG_DEPENDS += $(SWSS_DBG) $(LIBSWSSCOMMON_DBG) +$(DOCKER_NAT)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_NAT)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +ifeq ($(INCLUDE_NAT), y) +SONIC_DOCKER_IMAGES += $(DOCKER_NAT) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_NAT) +endif + +ifeq ($(INCLUDE_NAT), y) +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_NAT_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_NAT_DBG) +endif + +$(DOCKER_NAT)_CONTAINER_NAME = nat +$(DOCKER_NAT)_RUN_OPT += --privileged -t +$(DOCKER_NAT)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_NAT)_RUN_OPT += -v /host/warmboot:/var/warmboot + +$(DOCKER_NAT)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) + +$(DOCKER_NAT)_BASE_IMAGE_FILES += natctl:/usr/bin/natctl diff --git a/rules/docker-orchagent.dep b/rules/docker-orchagent.dep new file mode 100644 index 000000000000..7aff4d0d9f23 --- /dev/null +++ b/rules/docker-orchagent.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_ORCHAGENT)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-orchagent.mk rules/docker-orchagent.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_ORCHAGENT)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_ORCHAGENT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_ORCHAGENT)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_ORCHAGENT),$(DOCKER_ORCHAGENT_DBG))) diff --git a/rules/docker-orchagent.mk b/rules/docker-orchagent.mk new file mode 100644 index 000000000000..5e2e08ee2437 --- /dev/null +++ b/rules/docker-orchagent.mk @@ -0,0 +1,36 @@ +# docker image for orchagent + +DOCKER_ORCHAGENT_STEM = docker-orchagent +DOCKER_ORCHAGENT = $(DOCKER_ORCHAGENT_STEM).gz +DOCKER_ORCHAGENT_DBG = $(DOCKER_ORCHAGENT_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_ORCHAGENT)_DEPENDS += $(SWSS) + +$(DOCKER_ORCHAGENT)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_ORCHAGENT)_DBG_DEPENDS += $(SWSS_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIREDIS_DBG) + +$(DOCKER_ORCHAGENT)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_ORCHAGENT)_PATH = $(DOCKERS_PATH)/$(DOCKER_ORCHAGENT_STEM) + +$(DOCKER_ORCHAGENT)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_ORCHAGENT) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ORCHAGENT) + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_ORCHAGENT_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_ORCHAGENT_DBG) + +$(DOCKER_ORCHAGENT)_CONTAINER_NAME = swss +$(DOCKER_ORCHAGENT)_RUN_OPT += --privileged -t +$(DOCKER_ORCHAGENT)_RUN_OPT += -v /etc/network/interfaces:/etc/network/interfaces:ro +$(DOCKER_ORCHAGENT)_RUN_OPT += -v /etc/network/interfaces.d/:/etc/network/interfaces.d/:ro +$(DOCKER_ORCHAGENT)_RUN_OPT += -v /host/machine.conf:/host/machine.conf:ro +$(DOCKER_ORCHAGENT)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_ORCHAGENT)_RUN_OPT += -v /var/log/swss:/var/log/swss:rw + +$(DOCKER_ORCHAGENT)_BASE_IMAGE_FILES += swssloglevel:/usr/bin/swssloglevel +$(DOCKER_ORCHAGENT)_BASE_IMAGE_FILES += monit_swss:/etc/monit/conf.d +$(DOCKER_ORCHAGENT)_FILES += $(ARP_UPDATE_SCRIPT) $(ARP_UPDATE_VARS_TEMPLATE) $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/docker-platform-monitor.dep b/rules/docker-platform-monitor.dep new file mode 100644 index 000000000000..7b56d33c5134 --- /dev/null +++ b/rules/docker-platform-monitor.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_PLATFORM_MONITOR)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-platform-monitor.mk rules/docker-platform-monitor.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_PLATFORM_MONITOR)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_PLATFORM_MONITOR)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_PLATFORM_MONITOR)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_PLATFORM_MONITOR),$(DOCKER_PLATFORM_MONITOR_DBG))) diff --git a/rules/docker-platform-monitor.mk b/rules/docker-platform-monitor.mk new file mode 100644 index 000000000000..547fbf60813f --- /dev/null +++ b/rules/docker-platform-monitor.mk @@ -0,0 +1,69 @@ +# Docker image for SONiC platform monitoring tools + +DOCKER_PLATFORM_MONITOR_STEM = docker-platform-monitor +DOCKER_PLATFORM_MONITOR = $(DOCKER_PLATFORM_MONITOR_STEM).gz +DOCKER_PLATFORM_MONITOR_DBG = $(DOCKER_PLATFORM_MONITOR_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_PLATFORM_MONITOR)_PATH = $(DOCKERS_PATH)/$(DOCKER_PLATFORM_MONITOR_STEM) + +$(DOCKER_PLATFORM_MONITOR)_DEPENDS += $(LIBSENSORS) $(LM_SENSORS) $(FANCONTROL) $(SENSORD) $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) $(PYTHON3_SWSSCOMMON) $(SMARTMONTOOLS) + +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PLATFORM_COMMON_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PLATFORM_COMMON_PY3) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SWSSSDK_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SWSSSDK_PY3) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PY_COMMON_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PY_COMMON_PY3) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY3) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_LEDD_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PCIED_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PSUD_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_SYSEEPROMD_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_THERMALCTLD_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_XCVRD_PY2) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_LEDD_PY3) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PCIED_PY3) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PSUD_PY3) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_SYSEEPROMD_PY3) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_THERMALCTLD_PY3) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_XCVRD_PY3) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_CHASSISD_PY3) + +ifeq ($(PDDF_SUPPORT),y) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(PDDF_PLATFORM_API_BASE_PY2) +endif + +$(DOCKER_PLATFORM_MONITOR)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_PLATFORM_MONITOR)_DBG_DEPENDS += $(LIBSWSSCOMMON_DBG) $(LIBSENSORS_DBG) +$(DOCKER_PLATFORM_MONITOR)_DBG_DEPENDS += $(LM_SENSORS_DBG) $(SENSORD_DBG) + +$(DOCKER_PLATFORM_MONITOR)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_PLATFORM_MONITOR)_LOAD_DOCKERS = $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_PLATFORM_MONITOR) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_PLATFORM_MONITOR) + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_PLATFORM_MONITOR_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_PLATFORM_MONITOR_DBG) + +$(DOCKER_PLATFORM_MONITOR)_CONTAINER_NAME = pmon +$(DOCKER_PLATFORM_MONITOR)_RUN_OPT += --privileged -t +$(DOCKER_PLATFORM_MONITOR)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_PLATFORM_MONITOR)_RUN_OPT += -v /usr/share/sonic/scripts:/usr/share/sonic/scripts:ro +$(DOCKER_PLATFORM_MONITOR)_RUN_OPT += -v /var/run/platform_cache:/var/run/platform_cache:ro +$(DOCKER_PLATFORM_MONITOR)_RUN_OPT += -v /usr/share/sonic/device/pddf:/usr/share/sonic/device/pddf:ro + +# Mount Arista python library on Aboot images to be used by plugins +$(DOCKER_PLATFORM_MONITOR)_aboot_RUN_OPT += -v /usr/lib/python2.7/dist-packages/arista:/usr/lib/python2.7/dist-packages/arista:ro +$(DOCKER_PLATFORM_MONITOR)_aboot_RUN_OPT += -v /usr/lib/python3/dist-packages/arista:/usr/lib/python3/dist-packages/arista:ro +$(DOCKER_PLATFORM_MONITOR)_aboot_RUN_OPT += -v /usr/lib/python2.7/dist-packages/sonic_platform:/usr/lib/python2.7/dist-packages/sonic_platform:ro +$(DOCKER_PLATFORM_MONITOR)_aboot_RUN_OPT += -v /usr/lib/python3/dist-packages/sonic_platform:/usr/lib/python3/dist-packages/sonic_platform:ro + +$(DOCKER_PLATFORM_MONITOR)_BASE_IMAGE_FILES += cmd_wrapper:/usr/bin/sensors +$(DOCKER_PLATFORM_MONITOR)_BASE_IMAGE_FILES += cmd_wrapper:/usr/sbin/smartctl +$(DOCKER_PLATFORM_MONITOR)_BASE_IMAGE_FILES += cmd_wrapper:/usr/sbin/iSmart +$(DOCKER_PLATFORM_MONITOR)_BASE_IMAGE_FILES += cmd_wrapper:/usr/sbin/SmartCmd +$(DOCKER_PLATFORM_MONITOR)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/docker-restapi.mk b/rules/docker-restapi.mk new file mode 100644 index 000000000000..917a270266bd --- /dev/null +++ b/rules/docker-restapi.mk @@ -0,0 +1,26 @@ +# docker image for rest-api + +DOCKER_RESTAPI_STEM = docker-sonic-restapi +DOCKER_RESTAPI = $(DOCKER_RESTAPI_STEM).gz + +$(DOCKER_RESTAPI)_DEPENDS += $(LIBHIREDIS) $(LIBNL3) $(LIBNL_GENL3) \ + $(LIBNL_ROUTE3) $(LIBSWSSCOMMON) $(RESTAPI) + +$(DOCKER_RESTAPI)_PATH = $(DOCKERS_PATH)/$(DOCKER_RESTAPI_STEM) + +$(DOCKER_RESTAPI)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_STRETCH) + +ifeq ($(INCLUDE_RESTAPI), y) +SONIC_DOCKER_IMAGES += $(DOCKER_RESTAPI) +SONIC_STRETCH_DOCKERS += $(DOCKER_RESTAPI) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_RESTAPI) +endif + +$(DOCKER_RESTAPI)_CONTAINER_NAME = restapi +$(DOCKER_RESTAPI)_RUN_OPT += --cap-add NET_ADMIN --privileged -t +$(DOCKER_RESTAPI)_RUN_OPT += -v /var/run/redis/redis.sock:/var/run/redis/redis.sock +$(DOCKER_RESTAPI)_RUN_OPT += -v /etc/sonic/credentials:/etc/sonic/credentials:ro +$(DOCKER_RESTAPI)_RUN_OPT += -p=8081:8081/tcp + +$(DOCKER_RESTAPI)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +$(DOCKER_RESTAPI)_BASE_IMAGE_FILES += monit_restapi:/etc/monit/conf.d diff --git a/rules/docker-router-advertiser.dep b/rules/docker-router-advertiser.dep new file mode 100644 index 000000000000..1450462975db --- /dev/null +++ b/rules/docker-router-advertiser.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_ROUTER_ADVERTISER)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-router-advertiser.mk rules/docker-router-advertiser.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_ROUTER_ADVERTISER)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_ROUTER_ADVERTISER)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_ROUTER_ADVERTISER)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_ROUTER_ADVERTISER),$(DOCKER_ROUTER_ADVERTISER_DBG))) diff --git a/rules/docker-router-advertiser.mk b/rules/docker-router-advertiser.mk new file mode 100644 index 000000000000..38bd95905673 --- /dev/null +++ b/rules/docker-router-advertiser.mk @@ -0,0 +1,26 @@ +# Docker image for router advertiser + +DOCKER_ROUTER_ADVERTISER_STEM = docker-router-advertiser +DOCKER_ROUTER_ADVERTISER = $(DOCKER_ROUTER_ADVERTISER_STEM).gz +DOCKER_ROUTER_ADVERTISER_DBG = $(DOCKER_ROUTER_ADVERTISER_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_ROUTER_ADVERTISER)_PATH = $(DOCKERS_PATH)/$(DOCKER_ROUTER_ADVERTISER_STEM) + +$(DOCKER_ROUTER_ADVERTISER)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_ROUTER_ADVERTISER)_DBG_DEPENDS += $(RADVD_DBG) + +$(DOCKER_ROUTER_ADVERTISER)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_ROUTER_ADVERTISER)_LOAD_DOCKERS = $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_ROUTER_ADVERTISER) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ROUTER_ADVERTISER) + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_ROUTER_ADVERTISER_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_ROUTER_ADVERTISER_DBG) + +$(DOCKER_ROUTER_ADVERTISER)_CONTAINER_NAME = radv +$(DOCKER_ROUTER_ADVERTISER)_RUN_OPT += --privileged -t +$(DOCKER_ROUTER_ADVERTISER)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_ROUTER_ADVERTISER)_RUN_OPT += -v /usr/share/sonic/scripts:/usr/share/sonic/scripts:ro +$(DOCKER_ROUTER_ADVERTISER)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/docker-sflow.dep b/rules/docker-sflow.dep new file mode 100644 index 000000000000..8870549f41d1 --- /dev/null +++ b/rules/docker-sflow.dep @@ -0,0 +1,15 @@ + +DPATH := $($(DOCKER_SFLOW)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-sflow.mk rules/docker-sflow.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_SFLOW)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SFLOW)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SFLOW)_DEP_FILES := $(DEP_FILES) + + +#DPKG FRK +$(eval $(call add_dbg_docker,$(DOCKER_SFLOW),$(DOCKER_SFLOW_DBG))) + + diff --git a/rules/docker-sflow.mk b/rules/docker-sflow.mk new file mode 100644 index 000000000000..6888304b8bce --- /dev/null +++ b/rules/docker-sflow.mk @@ -0,0 +1,34 @@ +# docker image for sFlow agent + +DOCKER_SFLOW_STEM = docker-sflow +DOCKER_SFLOW = $(DOCKER_SFLOW_STEM).gz +DOCKER_SFLOW_DBG = $(DOCKER_SFLOW_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_SFLOW)_PATH = $(DOCKERS_PATH)/$(DOCKER_SFLOW_STEM) + +$(DOCKER_SFLOW)_DEPENDS += $(SWSS) $(HSFLOWD) $(SFLOWTOOL) $(PSAMPLE) +$(DOCKER_SFLOW)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_TEAMD)_DBG_DEPENDS += $(SWSS_DBG) $(LIBSWSSCOMMON_DBG) +$(DOCKER_SFLOW)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_SFLOW)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_SFLOW) +ifeq ($(INCLUDE_SFLOW), y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SFLOW) +endif + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_SFLOW_DBG) +ifeq ($(INCLUDE_SFLOW), y) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_SFLOW_DBG) +endif + +$(DOCKER_SFLOW)_CONTAINER_NAME = sflow +$(DOCKER_SFLOW)_RUN_OPT += --privileged -t +$(DOCKER_SFLOW)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SFLOW)_RUN_OPT += -v /host/warmboot:/var/warmboot + +$(DOCKER_SFLOW)_BASE_IMAGE_FILES += psample:/usr/bin/psample +$(DOCKER_SFLOW)_BASE_IMAGE_FILES += sflowtool:/usr/bin/sflowtool +$(DOCKER_SFLOW)_BASE_IMAGE_FILES += monit_sflow:/etc/monit/conf.d +$(DOCKER_SFLOW)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/docker-snmp.dep b/rules/docker-snmp.dep new file mode 100644 index 000000000000..580ee65d53fe --- /dev/null +++ b/rules/docker-snmp.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_SNMP)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-snmp.mk rules/docker-snmp.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_SNMP)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SNMP)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SNMP)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_SNMP),$(DOCKER_SNMP_DBG))) diff --git a/rules/docker-snmp.mk b/rules/docker-snmp.mk new file mode 100644 index 000000000000..cbc69dc92b1b --- /dev/null +++ b/rules/docker-snmp.mk @@ -0,0 +1,31 @@ +# docker image for snmp agent + +DOCKER_SNMP_STEM = docker-snmp +DOCKER_SNMP = $(DOCKER_SNMP_STEM).gz +DOCKER_SNMP_DBG = $(DOCKER_SNMP_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_SNMP)_PATH = $(DOCKERS_PATH)/docker-snmp + +## TODO: remove LIBPY3_DEV if we can get pip3 directly +$(DOCKER_SNMP)_DEPENDS += $(SNMP) $(SNMPD) + +$(DOCKER_SNMP)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_SNMP)_DBG_DEPENDS += $(SNMP_DBG) $(SNMPD_DBG) $(LIBSNMP_DBG) + +$(DOCKER_SNMP)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_SNMP)_PYTHON_WHEELS += $(SONIC_PY_COMMON_PY3) $(SONIC_PLATFORM_COMMON_PY3) $(SWSSSDK_PY3) $(ASYNCSNMP_PY3) +$(DOCKER_SNMP)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_SNMP) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SNMP) + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_SNMP_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_SNMP_DBG) + +$(DOCKER_SNMP)_CONTAINER_NAME = snmp +$(DOCKER_SNMP)_RUN_OPT += --privileged -t +$(DOCKER_SNMP)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SNMP)_RUN_OPT += -v /usr/share/sonic/scripts:/usr/share/sonic/scripts:ro +$(DOCKER_SNMP)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +$(DOCKER_SNMP)_BASE_IMAGE_FILES += monit_snmp:/etc/monit/conf.d diff --git a/rules/docker-sonic-mgmt-framework.dep b/rules/docker-sonic-mgmt-framework.dep new file mode 100644 index 000000000000..05ec104e26ab --- /dev/null +++ b/rules/docker-sonic-mgmt-framework.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_MGMT_FRAMEWORK)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-sonic-mgmt-framework.mk rules/docker-sonic-mgmt-framework.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_MGMT_FRAMEWORK)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_MGMT_FRAMEWORK)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_MGMT_FRAMEWORK)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_MGMT_FRAMEWORK),$(DOCKER_MGMT_FRAMEWORK_DBG))) diff --git a/rules/docker-sonic-mgmt-framework.mk b/rules/docker-sonic-mgmt-framework.mk new file mode 100644 index 000000000000..65bac8bd9ddc --- /dev/null +++ b/rules/docker-sonic-mgmt-framework.mk @@ -0,0 +1,34 @@ +# docker image for mgmt-framework + +DOCKER_MGMT_FRAMEWORK_STEM = docker-sonic-mgmt-framework +DOCKER_MGMT_FRAMEWORK = $(DOCKER_MGMT_FRAMEWORK_STEM).gz +DOCKER_MGMT_FRAMEWORK_DBG = $(DOCKER_MGMT_FRAMEWORK_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_MGMT_FRAMEWORK)_PATH = $(DOCKERS_PATH)/$(DOCKER_MGMT_FRAMEWORK_STEM) + +$(DOCKER_MGMT_FRAMEWORK)_DEPENDS += $(SONIC_MGMT_COMMON) +$(DOCKER_MGMT_FRAMEWORK)_DEPENDS += $(SONIC_MGMT_FRAMEWORK) +$(DOCKER_MGMT_FRAMEWORK)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_MGMT_FRAMEWORK)_DBG_DEPENDS += $(SONIC_MGMT_FRAMEWORK_DBG) + +SONIC_DOCKER_IMAGES += $(DOCKER_MGMT_FRAMEWORK) +$(DOCKER_MGMT_FRAMEWORK)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) +$(DOCKER_MGMT_FRAMEWORK)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +ifeq ($(INCLUDE_MGMT_FRAMEWORK), y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_MGMT_FRAMEWORK) +endif + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_MGMT_FRAMEWORK_DBG) +ifeq ($(INCLUDE_MGMT_FRAMEWORK), y) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_MGMT_FRAMEWORK_DBG) +endif + +$(DOCKER_MGMT_FRAMEWORK)_CONTAINER_NAME = mgmt-framework +$(DOCKER_MGMT_FRAMEWORK)_RUN_OPT += --privileged -t +$(DOCKER_MGMT_FRAMEWORK)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_MGMT_FRAMEWORK)_RUN_OPT += -v /etc:/host_etc:ro +$(DOCKER_MGMT_FRAMEWORK)_RUN_OPT += -v /var/run/dbus:/var/run/dbus:rw +$(DOCKER_MGMT_FRAMEWORK)_RUN_OPT += --mount type=bind,source="/var/platform/",target="/mnt/platform/" + +$(DOCKER_MGMT_FRAMEWORK)_BASE_IMAGE_FILES += sonic-cli:/usr/bin/sonic-cli diff --git a/rules/docker-sonic-mgmt-spytest.dep b/rules/docker-sonic-mgmt-spytest.dep new file mode 100644 index 000000000000..1f6c36eec72d --- /dev/null +++ b/rules/docker-sonic-mgmt-spytest.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_MGMT_SPYTEST)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-sonic-mgmt-spytest.mk rules/docker-sonic-mgmt-spytest.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_MGMT_SPYTEST)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_MGMT_SPYTEST)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_MGMT_SPYTEST)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_MGMT_SPYTEST),$(DOCKER_MGMT_SPYTEST_DBG))) diff --git a/rules/docker-sonic-mgmt.dep b/rules/docker-sonic-mgmt.dep new file mode 100644 index 000000000000..29e6d39475dc --- /dev/null +++ b/rules/docker-sonic-mgmt.dep @@ -0,0 +1,10 @@ + +DPATH := $($(DOCKER_SONIC_MGMT)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-sonic-mgmt.mk rules/docker-sonic-mgmt.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_SONIC_MGMT)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_SONIC_MGMT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_SONIC_MGMT)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/docker-sonic-mgmt.mk b/rules/docker-sonic-mgmt.mk new file mode 100644 index 000000000000..8d6901755f8a --- /dev/null +++ b/rules/docker-sonic-mgmt.mk @@ -0,0 +1,6 @@ +# docker image for sonic-mgmt +DOCKER_SONIC_MGMT = docker-sonic-mgmt.gz +$(DOCKER_SONIC_MGMT)_PATH = $(DOCKERS_PATH)/docker-sonic-mgmt +$(DOCKER_SONIC_MGMT)_DEPENDS += $(SONIC_DEVICE_DATA) $(PTF) +SONIC_DOCKER_IMAGES += $(DOCKER_SONIC_MGMT) +SONIC_STRETCH_DOCKERS += $(DOCKER_SONIC_MGMT) diff --git a/rules/docker-teamd.dep b/rules/docker-teamd.dep new file mode 100644 index 000000000000..b58d934241ef --- /dev/null +++ b/rules/docker-teamd.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_TEAMD)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-teamd.mk rules/docker-teamd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_TEAMD)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_TEAMD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_TEAMD)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_TEAMD),$(DOCKER_TEAMD_DBG))) diff --git a/rules/docker-teamd.mk b/rules/docker-teamd.mk new file mode 100644 index 000000000000..5442d5bf6b3f --- /dev/null +++ b/rules/docker-teamd.mk @@ -0,0 +1,31 @@ +# docker image for teamd agent + +DOCKER_TEAMD_STEM = docker-teamd +DOCKER_TEAMD = $(DOCKER_TEAMD_STEM).gz +DOCKER_TEAMD_DBG = $(DOCKER_TEAMD_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_TEAMD)_PATH = $(DOCKERS_PATH)/$(DOCKER_TEAMD_STEM) + +$(DOCKER_TEAMD)_DEPENDS += $(SWSS) $(LIBTEAMDCTL) $(LIBTEAM_UTILS) +$(DOCKER_TEAMD)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) +$(DOCKER_TEAMD)_DBG_DEPENDS += $(SWSS_DBG) $(LIBSWSSCOMMON_DBG) +$(DOCKER_TEAMD)_DBG_DEPENDS += $(LIBTEAMDCTL_DBG) $(LIBTEAM_UTILS_DBG) + +$(DOCKER_TEAMD)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +$(DOCKER_TEAMD)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) + +SONIC_DOCKER_IMAGES += $(DOCKER_TEAMD) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_TEAMD) + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_TEAMD_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_TEAMD_DBG) + +$(DOCKER_TEAMD)_CONTAINER_NAME = teamd +$(DOCKER_TEAMD)_RUN_OPT += --privileged -t +$(DOCKER_TEAMD)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_TEAMD)_RUN_OPT += -v /host/warmboot:/var/warmboot + +$(DOCKER_TEAMD)_BASE_IMAGE_FILES += teamdctl:/usr/bin/teamdctl +$(DOCKER_TEAMD)_BASE_IMAGE_FILES += monit_teamd:/etc/monit/conf.d +$(DOCKER_TEAMD)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/docker-telemetry.dep b/rules/docker-telemetry.dep new file mode 100644 index 000000000000..7748370845d6 --- /dev/null +++ b/rules/docker-telemetry.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_TELEMETRY)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-telemetry.mk rules/docker-telemetry.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_TELEMETRY)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_TELEMETRY)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_TELEMETRY)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_TELEMETRY),$(DOCKER_TELEMETRY_DBG))) diff --git a/rules/docker-telemetry.mk b/rules/docker-telemetry.mk new file mode 100644 index 000000000000..5152a386963b --- /dev/null +++ b/rules/docker-telemetry.mk @@ -0,0 +1,33 @@ +# docker image for telemetry agent + +DOCKER_TELEMETRY_STEM = docker-sonic-telemetry +DOCKER_TELEMETRY = $(DOCKER_TELEMETRY_STEM).gz +DOCKER_TELEMETRY_DBG = $(DOCKER_TELEMETRY_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_TELEMETRY)_PATH = $(DOCKERS_PATH)/$(DOCKER_TELEMETRY_STEM) + +$(DOCKER_TELEMETRY)_DEPENDS += $(SONIC_MGMT_COMMON) +$(DOCKER_TELEMETRY)_DEPENDS += $(SONIC_TELEMETRY) +$(DOCKER_TELEMETRY)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) + +$(DOCKER_TELEMETRY)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BUSTER) +$(DOCKER_TELEMETRY)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES) + +SONIC_DOCKER_IMAGES += $(DOCKER_TELEMETRY) +ifeq ($(INCLUDE_SYSTEM_TELEMETRY), y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_TELEMETRY) +endif + +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_TELEMETRY_DBG) +ifeq ($(INCLUDE_SYSTEM_TELEMETRY), y) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_TELEMETRY_DBG) +endif + +$(DOCKER_TELEMETRY)_CONTAINER_NAME = telemetry +$(DOCKER_TELEMETRY)_RUN_OPT += --privileged -t +$(DOCKER_TELEMETRY)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_TELEMETRY)_RUN_OPT += -v /usr/share/sonic/scripts:/usr/share/sonic/scripts:ro +$(DOCKER_TELEMETRY)_RUN_OPT += -v /var/run/dbus:/var/run/dbus:rw + +$(DOCKER_TELEMETRY)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +$(DOCKER_TELEMETRY)_BASE_IMAGE_FILES += monit_telemetry:/etc/monit/conf.d diff --git a/rules/frr.dep b/rules/frr.dep new file mode 100644 index 000000000000..e263cb8e881e --- /dev/null +++ b/rules/frr.dep @@ -0,0 +1,25 @@ + +SPATH := $($(FRR)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/frr.mk rules/frr.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files |grep -Ev '^frr$$$$')) + +# Account for source files under the frr submodule directory as well. +# Remove all the symbolic link files +FRR_SPATH := $(SPATH)/frr +SMDEP_FILES := $(addprefix $(FRR_SPATH)/,$(shell cd $(FRR_SPATH) && git ls-files \ + | grep -Ev -e 'debian/changelog$$$$' \ + -e '^tests/topotests/bgp_instance_del_test/ce[0-9]$$$$' \ + -e '^tests/topotests/bgp_instance_del_test/r[0-9]$$$$' \ + -e '^tests/topotests/bgp_instance_del_test/scripts$$$$' \ + -e '^tests/topotests/bgp_instance_del_test/customize.py$$$$' \ + -e '^tests/topotests/bgp_rfapi_basic_sanity_config2/customize.py$$$$' \ + -e '^tests/topotests/bgp_rfapi_basic_sanity_config2/scripts$$$$' \ + -e '^tests/topotests/bgp_rfapi_basic_sanity_config2/test_bgp_rfapi_basic_sanity_config2.py$$$$' \ + )) + +$(FRR)_CACHE_MODE := GIT_CONTENT_SHA +$(FRR)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(FRR)_DEP_FILES := $(DEP_FILES) +$(FRR)_SMDEP_FILES := $(SMDEP_FILES) +$(FRR)_SMDEP_PATHS := $(FRR_SPATH) diff --git a/rules/frr.mk b/rules/frr.mk new file mode 100644 index 000000000000..c8175339f444 --- /dev/null +++ b/rules/frr.mk @@ -0,0 +1,34 @@ +# FRRouting (frr) package + +FRR_VERSION = 7.5 +FRR_SUBVERSION = 0 +FRR_BRANCH = frr/7.5 +FRR_TAG = frr-7.5-s3 +export FRR_VERSION FRR_SUBVERSION FRR_BRANCH FRR_TAG + + +FRR = frr_$(FRR_VERSION)-sonic-$(FRR_SUBVERSION)_$(CONFIGURED_ARCH).deb +$(FRR)_DEPENDS += $(LIBSNMP_DEV) $(LIBYANG1) $(LIBYANG1_DEV) +$(FRR)_RDEPENDS += $(LIBYANG1) +$(FRR)_UNINSTALLS = $(LIBYANG1_DEV) $(LIBYANG1) +$(FRR)_SRC_PATH = $(SRC_PATH)/sonic-frr +SONIC_MAKE_DEBS += $(FRR) + +FRR_PYTHONTOOLS = frr-pythontools_$(FRR_VERSION)-sonic-$(FRR_SUBVERSION)_all.deb +$(eval $(call add_extra_package,$(FRR),$(FRR_PYTHONTOOLS))) + +FRR_DBG = frr-dbgsym_$(FRR_VERSION)-sonic-$(FRR_SUBVERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_extra_package,$(FRR),$(FRR_DBG))) + +FRR_SNMP = frr-snmp_$(FRR_VERSION)-sonic-$(FRR_SUBVERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_extra_package,$(FRR),$(FRR_SNMP))) + +FRR_SNMP_DBG = frr-snmp-dbgsym_$(FRR_VERSION)-sonic-$(FRR_SUBVERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_extra_package,$(FRR),$(FRR_SNMP_DBG))) + +export FRR FRR_PYTHONTOOLS FRR_DBG FRR_SNMP FRR_SNMP_DBG + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += sonic-frr diff --git a/rules/functions b/rules/functions new file mode 100644 index 000000000000..c6caebe82858 --- /dev/null +++ b/rules/functions @@ -0,0 +1,168 @@ +############################################################################### +## FUNCTIONS +############################################################################### + +############################################################################### +## Colored output +############################################################################### + +# Enable colored output +ifeq ($(SONIC_CONFIG_ENABLE_COLORS),y) +ifeq ($(MAKE_TERMOUT),) +RED=\033[1;31m +PURPLE=\033[1;35m +CYAN=\033[1;36m +GREEN=\033[1;32m +GRAY=\033[0m +endif +endif + +ifeq ($(BUILD_LOG_TIMESTAMP),simple) +PROCESS_LOG_OPTION = -t +endif + +# Print red colored output +# call: +# log_red message +log_red = echo -e "$(RED)$(1)$(GRAY)" + +# Print purple colored output +# call: +# log_purple message +log_purple = echo -e "$(PURPLE)$(1)$(GRAY)" + +# Print blue colored output +# call: +# log_blue message +log_blue = echo -e "$(CYAN)$(1)$(GRAY)" + +# Print green colored output +# call: +# log_green message +log_green = echo -e "$(GREEN)$(1)$(GRAY)" + +############################################################################### +## Logging +############################################################################### + +FLUSH_LOG = rm -f $@.log + +LOG_SIMPLE = &>> $(PROJECT_ROOT)/$@.log || { [ $$? -eq 0 ] || pushd $(PROJECT_ROOT) > /dev/null ; ./update_screen.sh -e $@ ; popd > /dev/null ; false ; } +LOG = < /dev/null |& $(PROJECT_ROOT)/scripts/process_log.sh $(PROCESS_LOG_OPTION) &>> $(PROJECT_ROOT)/$@.log ; test $${PIPESTATUS[-2]} -eq 0 || { [ $$? -eq 0 ] || pushd $(PROJECT_ROOT) > /dev/null ; ./update_screen.sh -e $@ ; popd > /dev/null ; false ; } + +############################################################################### +## Header and footer for each target +############################################################################### + +# Dump targets taht current depends on +ifeq ($(SONIC_CONFIG_PRINT_DEPENDENCIES),y) +PRINT_DEPENDENCIES = echo Dependencies for $@ are $^ $(LOG) +endif + +# header for each rule +define HEADER +@ +$(PRINT_DEPENDENCIES) +$(FLUSH_LOG) +./update_screen.sh -a $@ $* +endef + +# footer for each rule +define FOOTER +./update_screen.sh -d $@ $($*_CACHE_LOADED) +endef + +############################################################################### +## Definition of derived target +############################################################################### + +# call: +# add_derived_package some_deb.deb, some_derived_deb +define add_derived_package +$(2)_DEPENDS += $(1) +$(2)_RDEPENDS += $($(1)_RDEPENDS) +$(2)_MAIN_DEB = $(1) +$(1)_DERIVED_DEBS += $(2) +$(2)_URL = $($(1)_URL) +$(2)_SRC_PATH = $($(1)_SRC_PATH) +SONIC_DERIVED_DEBS += $(2) +endef + +# call: +# add_extra_package some_deb.deb, some_extra_deb +define add_extra_package +$(2)_MAIN_DEB = $(1) +$(1)_EXTRA_DEBS += $(2) +SONIC_EXTRA_DEBS += $(2) +endef + +############################################################################### +## Definition of conflict packages +############################################################################### + +# call: +# add_conflict_package some_deb.deb, conflict_deb +define add_conflict_package +$(1)_CONFLICT_DEBS += $(2) +$(2)_CONFLICT_DEBS += $(1) +endef + +############################################################################### +## Definition of debug dockers +############################################################################### + +# call: +# add_dbg_docker some_docker.gz, some-docker-dbg.gz +define add_dbg_docker +$(2)_PATH = $($(1)_PATH) +$(2)_DBG_DEPENDS += $($(1)_DBG_DEPENDS) +$(2)_DBG_IMAGE_PACKAGES += $($(1)_DBG_IMAGE_PACKAGES) +$(2)_PYTHON_DEBS += $($(1)_PYTHON_DEBS) +$(2)_PYTHON_WHEELS += $($(1)_PYTHON_WHEELS) +$(2)_LOAD_DOCKERS += $($(1)_LOAD_DOCKERS) +$(2)_CACHE_MODE += $($(1)_CACHE_MODE) +$(2)_DEP_FLAGS += $($(1)_DEP_FLAGS) +$(2)_DEP_FILES += $($(1)_DEP_FILES) +$(2)_SMDEP_FILES += $($(1)_SMDEP_FILES) +$(2)_SMDEP_PATHS += $($(1)_SMDEP_PATHS) +$(2)_DEPENDS += $($(1)_DEPENDS) +$(2)_RDEPENDS += $($(1)_RDEPENDS) +$(2)_MAIN_DOCKER = $(1) +$(1)_DBG_DOCKER += $(2) +SONIC_DBG_DOCKERS += $(2) +endef + + + +############################################################################### +## Utility functions +############################################################################### +# Recursive wildcard function +rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) + +expand = $(foreach d,$(1),$(call expand,$($(d)_$(2)),$(2))) $(1) + +############################################################################### +## Uninstall debs +############################################################################### +define UNINSTALL_DEBS +if [ -n "$(1)" ]; then \ + while true; do \ + if mkdir $(DEBS_PATH)/dpkg_lock &> /dev/null; then \ + { sudo DEBIAN_FRONTEND=noninteractive dpkg -P $(foreach deb,$(1),$(firstword $(subst _, ,$(basename $(deb))))) $(LOG) && rm -d $(DEBS_PATH)/dpkg_lock && break; } || { rm -d $(DEBS_PATH)/dpkg_lock && exit 1 ; } \ + fi; \ + done; \ +fi +endef + +############################################################################### +## Setup overlay fs for dpkg admin directory /var/lib/dpkg +############################################################################### +define SETUP_OVERLAYFS_FOR_DPKG_ADMINDIR +upperdir=$(shell mktemp -d -p $(DPKG_ADMINDIR_PATH)) +workdir=$(shell mktemp -d -p $(DPKG_ADMINDIR_PATH)) +mergedir=$(shell mktemp -d -p $(DPKG_ADMINDIR_PATH)) +sudo mount -t overlay overlay -olowerdir=/var/lib/dpkg,upperdir=$$upperdir,workdir=$$workdir $$mergedir +export SONIC_DPKG_ADMINDIR=$$mergedir +trap "sudo umount $$mergedir && rm -rf $$mergedir $$upperdir $$workdir" EXIT +endef diff --git a/rules/gobgp.dep b/rules/gobgp.dep new file mode 100644 index 000000000000..f7462c6b8dbc --- /dev/null +++ b/rules/gobgp.dep @@ -0,0 +1,10 @@ + +SPATH := $($(GOBGP)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/gobgp.mk rules/gobgp.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(GOBGP)_CACHE_MODE := GIT_CONTENT_SHA +$(GOBGP)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(GOBGP)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/gobgp.mk b/rules/gobgp.mk new file mode 100644 index 000000000000..2d8a9d3f9c32 --- /dev/null +++ b/rules/gobgp.mk @@ -0,0 +1,5 @@ +# gobgp package + +GOBGP = gobgp_1.16-01_$(CONFIGURED_ARCH).deb +$(GOBGP)_SRC_PATH = $(SRC_PATH)/gobgp +SONIC_DPKG_DEBS += $(GOBGP) diff --git a/rules/hiredis.dep b/rules/hiredis.dep new file mode 100644 index 000000000000..93bea540289f --- /dev/null +++ b/rules/hiredis.dep @@ -0,0 +1,10 @@ + +SPATH := $($(LIBHIREDIS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/hiredis.mk rules/hiredis.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LIBHIREDIS)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBHIREDIS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBHIREDIS)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/hiredis.mk b/rules/hiredis.mk new file mode 100644 index 000000000000..71a18a1d6aac --- /dev/null +++ b/rules/hiredis.mk @@ -0,0 +1,17 @@ +# libhiredis package + +HIREDIS_VERSION = 0.14.0 +HIREDIS_VERSION_FULL = $(HIREDIS_VERSION)-3~bpo9+1 + +export HIREDIS_VERSION HIREDIS_VERSION_FULL + +LIBHIREDIS = libhiredis0.14_$(HIREDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(LIBHIREDIS)_SRC_PATH = $(SRC_PATH)/hiredis +SONIC_MAKE_DEBS += $(LIBHIREDIS) + +LIBHIREDIS_DEV = libhiredis-dev_$(HIREDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBHIREDIS),$(LIBHIREDIS_DEV))) + +LIBHIREDIS_DBG = libhiredis-dbg_$(HIREDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +LIBHIREDIS_DBG = libhiredis0.14-dbgsym_$(HIREDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBHIREDIS),$(LIBHIREDIS_DBG))) diff --git a/rules/iccpd.dep b/rules/iccpd.dep new file mode 100644 index 000000000000..124cc5e421cb --- /dev/null +++ b/rules/iccpd.dep @@ -0,0 +1,10 @@ + +SPATH := $($(ICCPD)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/iccpd.mk rules/iccpd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(ICCPD)_CACHE_MODE := GIT_CONTENT_SHA +$(ICCPD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(ICCPD)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/iccpd.mk b/rules/iccpd.mk new file mode 100644 index 000000000000..eb97efc52b9f --- /dev/null +++ b/rules/iccpd.mk @@ -0,0 +1,19 @@ +# iccpd package + +ICCPD_VERSION = 0.0.5 + +ICCPD = iccpd_$(ICCPD_VERSION)_$(CONFIGURED_ARCH).deb +$(ICCPD)_DEPENDS += $(LIBNL_GENL3_DEV) $(LIBNL_CLI_DEV) +$(ICCPD)_RDEPENDS += $(LIBNL_GENL3) $(LIBNL_CLI) +$(ICCPD)_SRC_PATH = $(SRC_PATH)/iccpd +SONIC_DPKG_DEBS += $(ICCPD) + +ICCPD_DBG = iccpd-dbg_$(ICCPD_VERSION)_$(CONFIGURED_ARCH).deb +$(ICCPD_DBG)_DEPENDS += $(ICCPD) +$(ICCPD_DBG)_RDEPENDS += $(ICCPD) +$(eval $(call add_derived_package,$(ICCPD),$(ICCPD_DBG))) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += iccpd diff --git a/rules/ifupdown2.dep b/rules/ifupdown2.dep new file mode 100644 index 000000000000..ec9bd68ee9d4 --- /dev/null +++ b/rules/ifupdown2.dep @@ -0,0 +1,10 @@ + +SPATH := $($(IFUPDOWN2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/ifupdown2.mk rules/ifupdown2.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(IFUPDOWN2)_CACHE_MODE := GIT_CONTENT_SHA +$(IFUPDOWN2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(IFUPDOWN2)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/ifupdown2.mk b/rules/ifupdown2.mk new file mode 100644 index 000000000000..f81facd8ff26 --- /dev/null +++ b/rules/ifupdown2.mk @@ -0,0 +1,10 @@ +# ifupdown2 package + +IFUPDOWN2_VERSION = 1.2.8-1 +export IFUPDOWN2_VERSION + +IFUPDOWN2 = ifupdown2_$(IFUPDOWN2_VERSION)_all.deb +$(IFUPDOWN2)_SRC_PATH = $(SRC_PATH)/ifupdown2 +SONIC_MAKE_DEBS += $(IFUPDOWN2) + +export IFUPDOWN2 diff --git a/rules/initramfs-tools.dep b/rules/initramfs-tools.dep new file mode 100644 index 000000000000..5176544fd8f3 --- /dev/null +++ b/rules/initramfs-tools.dep @@ -0,0 +1,10 @@ + +SPATH := $($(INITRAMFS_TOOLS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/initramfs-tools.mk rules/initramfs-tools.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(INITRAMFS_TOOLS)_CACHE_MODE := GIT_CONTENT_SHA +$(INITRAMFS_TOOLS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(INITRAMFS_TOOLS)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/initramfs-tools.mk b/rules/initramfs-tools.mk new file mode 100644 index 000000000000..2f3e55acac76 --- /dev/null +++ b/rules/initramfs-tools.mk @@ -0,0 +1,11 @@ +# initramfs-tools package + +INITRAMFS_TOOLS_VERSION = 0.133 +export INITRAMFS_TOOLS_VERSION + +INITRAMFS_TOOLS = initramfs-tools_$(INITRAMFS_TOOLS_VERSION)_all.deb +$(INITRAMFS_TOOLS)_SRC_PATH = $(SRC_PATH)/initramfs-tools +SONIC_MAKE_DEBS += $(INITRAMFS_TOOLS) + +INITRAMFS_TOOLS_CORE = initramfs-tools-core_$(INITRAMFS_TOOLS_VERSION)_all.deb +$(eval $(call add_extra_package,$(INITRAMFS_TOOLS),$(INITRAMFS_TOOLS_CORE))) diff --git a/rules/iproute2.dep b/rules/iproute2.dep new file mode 100644 index 000000000000..9e445d9c209a --- /dev/null +++ b/rules/iproute2.dep @@ -0,0 +1,10 @@ + +SPATH := $($(IPROUTE2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/iproute2.mk rules/iproute2.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(IPROUTE2)_CACHE_MODE := GIT_CONTENT_SHA +$(IPROUTE2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(IPROUTE2)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/iproute2.mk b/rules/iproute2.mk new file mode 100644 index 000000000000..33d54f4de11c --- /dev/null +++ b/rules/iproute2.mk @@ -0,0 +1,7 @@ +# iproute2 package + +IPROUTE2_VERSION = 4.9.0-1 + +IPROUTE2 = iproute2_$(IPROUTE2_VERSION)_$(CONFIGURED_ARCH).deb +$(IPROUTE2)_SRC_PATH = $(SRC_PATH)/iproute2 +SONIC_MAKE_DEBS += $(IPROUTE2) diff --git a/rules/iptables.dep b/rules/iptables.dep new file mode 100644 index 000000000000..eb751214487d --- /dev/null +++ b/rules/iptables.dep @@ -0,0 +1,10 @@ + +SPATH := $($(IPTABLES)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/iptables.mk rules/iptables.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(IPTABLES)_CACHE_MODE := GIT_CONTENT_SHA +$(IPTABLES)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(IPTABLES)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/iptables.mk b/rules/iptables.mk new file mode 100644 index 000000000000..fcdcc3434e08 --- /dev/null +++ b/rules/iptables.mk @@ -0,0 +1,26 @@ +# iptables package + +IPTABLES_VERSION = 1.8.2 +IPTABLES_VERSION_SUFFIX = 4 +IPTABLES_VERSION_FULL = $(IPTABLES_VERSION)-$(IPTABLES_VERSION_SUFFIX) + +IPTABLES = iptables_$(IPTABLES_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(IPTABLES)_SRC_PATH = $(SRC_PATH)/iptables +SONIC_MAKE_DEBS += $(IPTABLES) + +IPTABLESIP4TC = libip4tc0_$(IPTABLES_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(IPTABLES),$(IPTABLESIP4TC))) + +IPTABLESIP6TC = libip6tc0_$(IPTABLES_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(IPTABLES),$(IPTABLESIP6TC))) + +IPTABLESIPTC = libiptc0_$(IPTABLES_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(IPTABLES),$(IPTABLESIPTC))) + +IPXTABLES12 = libxtables12_$(IPTABLES_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(IPTABLES),$(IPXTABLES12))) + +# Export these variables so they can be used in a sub-make +export IPTABLES_VERSION +export IPTABLES_VERSION_FULL +export IPTABLES diff --git a/rules/isc-dhcp.dep b/rules/isc-dhcp.dep new file mode 100644 index 000000000000..e98df450746e --- /dev/null +++ b/rules/isc-dhcp.dep @@ -0,0 +1,10 @@ + +SPATH := $($(ISC_DHCP_RELAY)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/isc-dhcp.mk rules/isc-dhcp.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(ISC_DHCP_RELAY)_CACHE_MODE := GIT_CONTENT_SHA +$(ISC_DHCP_RELAY)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(ISC_DHCP_RELAY)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/isc-dhcp.mk b/rules/isc-dhcp.mk new file mode 100644 index 000000000000..3edebfd0dde0 --- /dev/null +++ b/rules/isc-dhcp.mk @@ -0,0 +1,15 @@ +# isc-dhcp packages + +ISC_DHCP_VERSION = 4.4.1 +ISC_DHCP_VERSION_FULL = ${ISC_DHCP_VERSION}-2 + +export ISC_DHCP_VERSION ISC_DHCP_VERSION_FULL + +ISC_DHCP_RELAY = isc-dhcp-relay_$(ISC_DHCP_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(ISC_DHCP_RELAY)_SRC_PATH = $(SRC_PATH)/isc-dhcp +SONIC_MAKE_DEBS += $(ISC_DHCP_RELAY) + +ISC_DHCP_RELAY_DBG = isc-dhcp-relay-dbgsym_$(ISC_DHCP_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(ISC_DHCP_RELAY),$(ISC_DHCP_RELAY_DBG))) + +export ISC_DHCP_RELAY ISC_DHCP_RELAY_DBG diff --git a/rules/ixgbe.dep b/rules/ixgbe.dep new file mode 100644 index 000000000000..a8e1ef1f3145 --- /dev/null +++ b/rules/ixgbe.dep @@ -0,0 +1,10 @@ + +SPATH := $($(IXGBE_DRIVER)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/ixgbe.mk rules/ixgbe.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(IXGBE_DRIVER)_CACHE_MODE := GIT_CONTENT_SHA +$(IXGBE_DRIVER)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(IXGBE_DRIVER)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/ixgbe.mk b/rules/ixgbe.mk new file mode 100644 index 000000000000..c1b017905b53 --- /dev/null +++ b/rules/ixgbe.mk @@ -0,0 +1,9 @@ +# initramfs-tools package + +IXGBE_DRIVER_VERSION = 5.2.4 +export IXGBE_DRIVER_VERSION + +IXGBE_DRIVER = ixgbe.ko +$(IXGBE_DRIVER)_SRC_PATH = $(SRC_PATH)/ixgbe +$(IXGBE_DRIVER)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_MAKE_FILES += $(IXGBE_DRIVER) diff --git a/rules/kdump-tools.dep b/rules/kdump-tools.dep new file mode 100644 index 000000000000..041f2e83a99b --- /dev/null +++ b/rules/kdump-tools.dep @@ -0,0 +1,10 @@ + +SPATH := $($(KDUMP_TOOLS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/kdump-tools.mk rules/kdump-tools.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(KDUMP_TOOLS)_CACHE_MODE := GIT_CONTENT_SHA +$(KDUMP_TOOLS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(KDUMP_TOOLS)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/kdump-tools.mk b/rules/kdump-tools.mk new file mode 100644 index 000000000000..c4b0c792b04a --- /dev/null +++ b/rules/kdump-tools.mk @@ -0,0 +1,12 @@ +# kdump-tools package + +KDUMP_TOOLS_VERSION_BASE = 1.6.1 +KDUMP_TOOLS_VERSION = $(KDUMP_TOOLS_VERSION_BASE)-1 +export KDUMP_TOOLS_VERSION_BASE +export KDUMP_TOOLS_VERSION + +KDUMP_TOOLS = kdump-tools_$(KDUMP_TOOLS_VERSION)_all.deb +$(KDUMP_TOOLS)_SRC_PATH = $(SRC_PATH)/kdump-tools +SONIC_MAKE_DEBS += $(KDUMP_TOOLS) + +export KDUMP_TOOLS diff --git a/rules/libnl3.dep b/rules/libnl3.dep new file mode 100644 index 000000000000..a28b97a7df41 --- /dev/null +++ b/rules/libnl3.dep @@ -0,0 +1,10 @@ + +SPATH := $($(LIBNL3)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/libnl3.mk rules/libnl3.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LIBNL3)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBNL3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBNL3)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/libnl3.mk b/rules/libnl3.mk new file mode 100644 index 000000000000..cdd807b2f5c8 --- /dev/null +++ b/rules/libnl3.mk @@ -0,0 +1,53 @@ +# libnl3 + +LIBNL3_VERSION_BASE = 3.5.0 +LIBNL3_VERSION = $(LIBNL3_VERSION_BASE)-1 + +export LIBNL3_VERSION_BASE +export LIBNL3_VERSION + +LIBNL3 = libnl-3-200_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBNL3)_SRC_PATH = $(SRC_PATH)/libnl3 +SONIC_MAKE_DEBS += $(LIBNL3) + +LIBNL3_DEV = libnl-3-dev_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL3_DEV))) + +LIBNL_GENL3 = libnl-genl-3-200_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBNL_GENL3)_RDEPENDS += $(LIBNL3) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_GENL3))) + +LIBNL_GENL3_DEV = libnl-genl-3-dev_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBNL_GENL3_DEV)_DEPENDS += $(LIBNL_GENL3) $(LIBNL3_DEV) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_GENL3_DEV))) + +LIBNL_ROUTE3 = libnl-route-3-200_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBNL_ROUTE3)_RDEPENDS += $(LIBNL3) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_ROUTE3))) + +LIBNL_ROUTE3_DEV = libnl-route-3-dev_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBNL_ROUTE3_DEV)_DEPENDS += $(LIBNL_ROUTE3) $(LIBNL3_DEV) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_ROUTE3_DEV))) + +LIBNL_NF3 = libnl-nf-3-200_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBNL_NF3)_DEPENDS += $(LIBNL_ROUTE3_DEV) +$(LIBNL_NF3)_RDEPENDS += $(LIBNL_ROUTE3) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_NF3))) + +LIBNL_NF3_DEV = libnl-nf-3-dev_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBNL_NF3_DEV)_DEPENDS += $(LIBNL_NF3) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_NF3_DEV))) + +LIBNL_CLI = libnl-cli-3-200_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBNL_CLI)_DEPENDS += $(LIBNL_GENL3_DEV) $(LIBNL_NF3_DEV) $(LIBNL_ROUTE3_DEV) +$(LIBNL_CLI)_RDEPENDS += $(LIBNL_GENL3) $(LIBNL_NF3) $(LIBNL_ROUTE3) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_CLI))) + +LIBNL_CLI_DEV = libnl-cli-3-dev_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBNL_CLI_DEV)_DEPENDS += $(LIBNL_CLI) $(LIBNL_GENL3_DEV) $(LIBNL_NF3_DEV) $(LIBNL_ROUTE3_DEV) +$(eval $(call add_derived_package,$(LIBNL3),$(LIBNL_CLI_DEV))) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += libnl3 diff --git a/rules/libteam.dep b/rules/libteam.dep new file mode 100644 index 000000000000..e30ffe609711 --- /dev/null +++ b/rules/libteam.dep @@ -0,0 +1,10 @@ + +SPATH := $($(LIBTEAM)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/libteam.mk rules/libteam.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LIBTEAM)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBTEAM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBTEAM)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/libteam.mk b/rules/libteam.mk new file mode 100644 index 000000000000..0dd1b88b099a --- /dev/null +++ b/rules/libteam.mk @@ -0,0 +1,35 @@ +# libteam packages + +LIBTEAM_VERSION = 1.30-1 + +export LIBTEAM_VERSION + +LIBTEAM = libteam5_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBTEAM)_SRC_PATH = $(SRC_PATH)/libteam +$(LIBTEAM)_DEPENDS += $(LIBNL_GENL3_DEV) $(LIBNL_CLI_DEV) +SONIC_MAKE_DEBS += $(LIBTEAM) + +LIBTEAM_DBG = libteam5-dbgsym_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBTEAM),$(LIBTEAM_DBG))) + +LIBTEAM_DEV = libteam-dev_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBTEAM_DEV)_DEPENDS += $(LIBTEAMDCTL) +$(eval $(call add_derived_package,$(LIBTEAM),$(LIBTEAM_DEV))) + +LIBTEAMDCTL = libteamdctl0_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBTEAM),$(LIBTEAMDCTL))) + +LIBTEAMDCTL_DBG = libteamdctl0-dbgsym_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBTEAM),$(LIBTEAMDCTL_DBG))) + +LIBTEAM_UTILS = libteam-utils_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBTEAM_UTILS)_DEPENDS += $(LIBTEAMDCTL) +$(eval $(call add_derived_package,$(LIBTEAM),$(LIBTEAM_UTILS))) + +LIBTEAM_UTILS_DBG = libteam-utils-dbgsym_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBTEAM),$(LIBTEAM_UTILS_DBG))) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += libteam diff --git a/rules/libyang.dep b/rules/libyang.dep new file mode 100644 index 000000000000..681f0c86a067 --- /dev/null +++ b/rules/libyang.dep @@ -0,0 +1,10 @@ + +SPATH := $($(LIBYANG)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/libyang.mk rules/libyang.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LIBYANG)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBYANG)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBYANG)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/libyang.mk b/rules/libyang.mk new file mode 100644 index 000000000000..181db2368c6d --- /dev/null +++ b/rules/libyang.mk @@ -0,0 +1,39 @@ +# libyang + +LIBYANG_VERSION_BASE = 1.0 +LIBYANG_VERSION = $(LIBYANG_VERSION_BASE).73 +LIBYANG_SUBVERSION = 1 + +export LIBYANG_VERSION_BASE +export LIBYANG_VERSION +export LIBYANG_SUBVERSION + +LIBYANG = libyang_$(LIBYANG_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBYANG)_SRC_PATH = $(SRC_PATH)/libyang +# introduce artifical dependency between LIBYANG and FRR +# make sure LIBYANG is compile after FRR +$(LIBYANG)_AFTER = $(FRR) +SONIC_MAKE_DEBS += $(LIBYANG) + +LIBYANG_DEV = libyang-dev_$(LIBYANG_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBYANG),$(LIBYANG_DEV))) + +LIBYANG_DBG = libyang-dbg_$(LIBYANG_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBYANG),$(LIBYANG_DBG))) + +LIBYANG_CPP = libyang-cpp_$(LIBYANG_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBYANG_CPP)_DEPENDS += $(LIBYANG) +$(eval $(call add_derived_package,$(LIBYANG),$(LIBYANG_CPP))) + +LIBYANG_PY3 = python3-yang_$(LIBYANG_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBYANG_PY3)_DEPENDS += $(LIBYANG) $(LIBYANG_CPP) +$(eval $(call add_derived_package,$(LIBYANG),$(LIBYANG_PY3))) + +LIBYANG_PY2 = python2-yang_$(LIBYANG_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBYANG_PY2)_DEPENDS += $(LIBYANG) $(LIBYANG_CPP) +$(eval $(call add_derived_package,$(LIBYANG),$(LIBYANG_PY2))) + +$(eval $(call add_conflict_package,$(LIBYANG),$(LIBYANG1))) +$(eval $(call add_conflict_package,$(LIBYANG_DEV),$(LIBYANG1_DEV))) + +export LIBYANG LIBYANG_DBG LIBYANG_DEV LIBYANG_CPP LIBYANG_PY3 LIBYANG_PY2 diff --git a/rules/libyang1.dep b/rules/libyang1.dep new file mode 100644 index 000000000000..343b06cf9611 --- /dev/null +++ b/rules/libyang1.dep @@ -0,0 +1,10 @@ + +SPATH := $($(LIBYANG1)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/libyang1.mk rules/libyang1.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LIBYANG1)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBYANG1)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBYANG1)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/libyang1.mk b/rules/libyang1.mk new file mode 100644 index 000000000000..6d24e3fc5a4e --- /dev/null +++ b/rules/libyang1.mk @@ -0,0 +1,43 @@ +# libyang1 + +LIBYANG1_VERSION_BASE = 1.0 +LIBYANG1_VERSION = $(LIBYANG1_VERSION_BASE).184 +LIBYANG1_SUBVERSION = 2 +LIBYANG1_FULLVERSION = $(LIBYANG1_VERSION)-$(LIBYANG1_SUBVERSION) + +export LIBYANG1_VERSION_BASE +export LIBYANG1_VERSION +export LIBYANG1_SUBVERSION +export LIBYANG1_FULLVERSION + +LIBYANG1 = libyang1_$(LIBYANG1_FULLVERSION)_$(CONFIGURED_ARCH).deb +$(LIBYANG1)_SRC_PATH = $(SRC_PATH)/libyang1 +SONIC_MAKE_DEBS += $(LIBYANG1) + +LIBYANG1_DEV = libyang-dev_$(LIBYANG1_FULLVERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBYANG1),$(LIBYANG1_DEV))) + +LIBYANG1_DBG = libyang1-dbgsym_$(LIBYANG1_FULLVERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBYANG1),$(LIBYANG1_DBG))) + +LIBYANG1_CPP = libyang-cpp1_$(LIBYANG1_FULLVERSION)_$(CONFIGURED_ARCH).deb +$(LIBYANG1_CPP)_DEPENDS += $(LIBYANG1) +$(eval $(call add_derived_package,$(LIBYANG1),$(LIBYANG1_CPP))) + +LIBYANG1_CPP_DEV = libyang-cpp-dev_$(LIBYANG1_FULLVERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBYANG1),$(LIBYANG1_CPP_DEV))) + +LIBYANG1_CPP_DBG = libyang-cpp1-dbgsym_$(LIBYANG1_FULLVERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBYANG1),$(LIBYANG1_CPP_DBG))) + +YANG_TOOLS = yang-tools_$(LIBYANG1_FULLVERSION)_all.deb +$(YANG_TOOLS)_DEPENDS += $(LIBYANG1) +$(eval $(call add_derived_package,$(LIBYANG1),$(YANG_TOOLS))) + +LIBYANG1_TOOLS = libyang-tools_$(LIBYANG1_FULLVERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBYANG1),$(LIBYANG1_TOOLS))) + +LIBYANG1_TOOLS_DBG = libyang-tools-dbgsym_$(LIBYANG1_FULLVERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBYANG1),$(LIBYANG1_TOOLS_DBG))) + +export LIBYANG1 LIBYANG1_DBG LIBYANG1_DEV LIBYANG1_CPP LIBYANG1_CPP_DEV LIBYANG1_CPP_DBG YANG_TOOLS LIBYANG1_TOOLS LIBYANG1_TOOLS_DBG diff --git a/rules/linux-kernel.dep b/rules/linux-kernel.dep new file mode 100644 index 000000000000..6063ddded9d0 --- /dev/null +++ b/rules/linux-kernel.dep @@ -0,0 +1,15 @@ + +SPATH := $($(LINUX_HEADERS_COMMON)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/linux-kernel.mk rules/linux-kernel.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) \ + $(KERNEL_PROCURE_METHOD) $(KERNEL_CACHE_PATH) + +$(LINUX_HEADERS_COMMON)_CACHE_MODE := GIT_CONTENT_SHA +$(LINUX_HEADERS_COMMON)_DEP_FLAGS := $(DEP_FLAGS) +$(LINUX_HEADERS_COMMON)_DEP_FILES := $(DEP_FILES) +$(LINUX_HEADERS_COMMON)_SMDEP_FILES := $(SMDEP_FILES) +$(LINUX_HEADERS_COMMON)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/linux-kernel.mk b/rules/linux-kernel.mk new file mode 100644 index 000000000000..2d369361a9e5 --- /dev/null +++ b/rules/linux-kernel.mk @@ -0,0 +1,26 @@ +# linux kernel package + +KVERSION_SHORT = 4.19.0-12-2 +KVERSION = $(KVERSION_SHORT)-$(CONFIGURED_ARCH) +KERNEL_VERSION = 4.19.152 +KERNEL_SUBVERSION = 1 +ifeq ($(CONFIGURED_ARCH), armhf) +# Override kernel version for ARMHF as it uses arm MP (multi-platform) for short version +KVERSION = $(KVERSION_SHORT)-armmp +endif + +export KVERSION_SHORT KVERSION KERNEL_VERSION KERNEL_SUBVERSION + +LINUX_HEADERS_COMMON = linux-headers-$(KVERSION_SHORT)-common_$(KERNEL_VERSION)-$(KERNEL_SUBVERSION)_all.deb +$(LINUX_HEADERS_COMMON)_SRC_PATH = $(SRC_PATH)/sonic-linux-kernel +SONIC_MAKE_DEBS += $(LINUX_HEADERS_COMMON) + +LINUX_HEADERS = linux-headers-$(KVERSION)_$(KERNEL_VERSION)-$(KERNEL_SUBVERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LINUX_HEADERS_COMMON),$(LINUX_HEADERS))) + +ifeq ($(CONFIGURED_ARCH), armhf) + LINUX_KERNEL = linux-image-$(KVERSION)_$(KERNEL_VERSION)-$(KERNEL_SUBVERSION)_$(CONFIGURED_ARCH).deb +else + LINUX_KERNEL = linux-image-$(KVERSION)-unsigned_$(KERNEL_VERSION)-$(KERNEL_SUBVERSION)_$(CONFIGURED_ARCH).deb +endif +$(eval $(call add_derived_package,$(LINUX_HEADERS_COMMON),$(LINUX_KERNEL))) diff --git a/rules/lldpd.dep b/rules/lldpd.dep new file mode 100644 index 000000000000..65c2d015ab9f --- /dev/null +++ b/rules/lldpd.dep @@ -0,0 +1,10 @@ + +SPATH := $($(LLDPD)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/lldpd.mk rules/lldpd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LLDPD)_CACHE_MODE := GIT_CONTENT_SHA +$(LLDPD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LLDPD)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/lldpd.mk b/rules/lldpd.mk new file mode 100644 index 000000000000..acd28f3359d7 --- /dev/null +++ b/rules/lldpd.mk @@ -0,0 +1,29 @@ +# lldpd package + +LLDPD_VERSION = 1.0.4 +LLDPD_VERSION_SUFFIX = 1 +LLDPD_VERSION_FULL = $(LLDPD_VERSION)-$(LLDPD_VERSION_SUFFIX) + +LLDPD = lldpd_$(LLDPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(LLDPD)_DEPENDS += $(LIBSNMP_DEV) +$(LLDPD)_RDEPENDS += $(LIBSNMP) +$(LLDPD)_SRC_PATH = $(SRC_PATH)/lldpd +SONIC_MAKE_DEBS += $(LLDPD) + +LIBLLDPCTL = liblldpctl-dev_$(LLDPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LLDPD),$(LIBLLDPCTL))) + +LLDPD_DBG = lldpd-dbgsym_$(LLDPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LLDPD),$(LLDPD_DBG))) + +# Export these variables so they can be used in a sub-make +export LLDPD_VERSION +export LLDPD_VERSION_FULL +export LLDPD +export LIBLLDPCTL +export LLDPD_DBG + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += lldpd diff --git a/rules/lm-sensors.dep b/rules/lm-sensors.dep new file mode 100644 index 000000000000..cc8bb09368fe --- /dev/null +++ b/rules/lm-sensors.dep @@ -0,0 +1,10 @@ + +SPATH := $($(LM_SENSORS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/lm-sensors.mk rules/lm-sensors.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LM_SENSORS)_CACHE_MODE := GIT_CONTENT_SHA +$(LM_SENSORS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LM_SENSORS)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/lm-sensors.mk b/rules/lm-sensors.mk new file mode 100644 index 000000000000..414aeb72b229 --- /dev/null +++ b/rules/lm-sensors.mk @@ -0,0 +1,47 @@ +# lm-senensors package + +LM_SENSORS_MAJOR_VERSION = 3 +LM_SENSORS_MINOR_VERSION = 5 +LM_SENSORS_PATCH_VERSION = 0 + +LM_SENSORS_VERSION=$(LM_SENSORS_MAJOR_VERSION).$(LM_SENSORS_MINOR_VERSION).$(LM_SENSORS_PATCH_VERSION) +LM_SENSORS_VERSION_FULL=$(LM_SENSORS_VERSION)-3 + +LM_SENSORS = lm-sensors_$(LM_SENSORS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(LM_SENSORS)_SRC_PATH = $(SRC_PATH)/lm-sensors + +LM_SENSORS_DBG = lm-sensors-dbgsym_$(LM_SENSORS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LM_SENSORS),$(LM_SENSORS_DBG))) + +FANCONTROL = fancontrol_$(LM_SENSORS_VERSION_FULL)_all.deb +$(eval $(call add_derived_package,$(LM_SENSORS),$(FANCONTROL))) + +LIBSENSORS = libsensors$(LM_SENSORS_MINOR_VERSION)_$(LM_SENSORS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LM_SENSORS),$(LIBSENSORS))) + +LIBSENSORS_DBG = libsensors$(LM_SENSORS_MINOR_VERSION)-dbgsym_$(LM_SENSORS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LM_SENSORS),$(LIBSENSORS_DBG))) + +SENSORD = sensord_$(LM_SENSORS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LM_SENSORS),$(SENSORD))) +$(SENSORD)_DEPENDS += $(LIBSENSORS) $(LM_SENSORS) + +SENSORD_DBG = sensord-dbgsym_$(LM_SENSORS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LM_SENSORS),$(SENSORD_DBG))) + +SONIC_MAKE_DEBS += $(LM_SENSORS) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += lm-sensors + +export LM_SENSORS +export FANCONTROL +export LIBSENSORS +export SENSORD +export LM_SENSORS_VERSION +export LM_SENSORS_VERSION_FULL +export LM_SENSORS_DBG +export LIBSENSORS_DBG +export SENSORD_DBG diff --git a/rules/monit.dep b/rules/monit.dep new file mode 100644 index 000000000000..01d04f228c5b --- /dev/null +++ b/rules/monit.dep @@ -0,0 +1,10 @@ + +SPATH := $($(MONIT)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/monit.mk rules/monit.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(MONIT)_CACHE_MODE := GIT_CONTENT_SHA +$(MONIT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(MONIT)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/monit.mk b/rules/monit.mk new file mode 100644 index 000000000000..4c15bc0dfab1 --- /dev/null +++ b/rules/monit.mk @@ -0,0 +1,12 @@ +# monit package + +MONIT_VERSION = 5.20.0-6 + +export MONIT_VERSION + +MONIT = monit_$(MONIT_VERSION)_$(CONFIGURED_ARCH).deb +$(MONIT)_SRC_PATH = $(SRC_PATH)/monit +SONIC_MAKE_DEBS += $(MONIT) + +MONIT_DBG = monit-dbgsym_$(MONIT_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(MONIT),$(MONIT_DBG))) diff --git a/rules/mpdecimal.dep b/rules/mpdecimal.dep new file mode 100644 index 000000000000..583b1b5a1c37 --- /dev/null +++ b/rules/mpdecimal.dep @@ -0,0 +1,10 @@ + +SPATH := $($(LIBMPDECIMAL)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/mpdecimal.mk rules/mpdecimal.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LIBMPDECIMAL)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBMPDECIMAL)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBMPDECIMAL)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/mpdecimal.mk b/rules/mpdecimal.mk new file mode 100644 index 000000000000..9ab84577e35c --- /dev/null +++ b/rules/mpdecimal.mk @@ -0,0 +1,13 @@ +# mpdecimal package + +MPDECIMAL_VERSION = 2.4.2 +MPDECIMAL_VERSION_FULL = $(MPDECIMAL_VERSION)-2 + +export MPDECIMAL_VERSION MPDECIMAL_VERSION_FULL + +LIBMPDECIMAL = libmpdec2_$(MPDECIMAL_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(LIBMPDECIMAL)_SRC_PATH = $(SRC_PATH)/mpdecimal +SONIC_MAKE_DEBS += $(LIBMPDECIMAL) + +LIBMPDECIMAL_DEV = libmpdec-dev_$(MPDECIMAL_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBMPDECIMAL),$(LIBMPDECIMAL_DEV))) diff --git a/rules/ntp.dep b/rules/ntp.dep new file mode 100644 index 000000000000..c261482f9327 --- /dev/null +++ b/rules/ntp.dep @@ -0,0 +1,10 @@ + +SPATH := $($(NTP)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/ntp.mk rules/ntp.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(NTP)_CACHE_MODE := GIT_CONTENT_SHA +$(NTP)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(NTP)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/ntp.mk b/rules/ntp.mk new file mode 100644 index 000000000000..13cbb495f78f --- /dev/null +++ b/rules/ntp.mk @@ -0,0 +1,11 @@ +# ntp package + +NTP_VERSION = 4.2.8p12+dfsg +export NTP_VERSION + +NTP = ntp_$(NTP_VERSION)-4+deb10u2_$(CONFIGURED_ARCH).deb +$(NTP)_SRC_PATH = $(SRC_PATH)/ntp +SONIC_MAKE_DEBS += $(NTP) +SONIC_STRETCH_DEBS += $(NTP) + +export NTP diff --git a/rules/openssh.dep b/rules/openssh.dep new file mode 100644 index 000000000000..7450743e667b --- /dev/null +++ b/rules/openssh.dep @@ -0,0 +1,8 @@ +SPATH := $($(OPENSSH_SERVER)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/openssh.mk rules/openssh.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(OPENSSH_SERVER)_CACHE_MODE := GIT_CONTENT_SHA +$(OPENSSH_SERVER)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(OPENSSH_SERVER)_DEP_FILES := $(DEP_FILES) diff --git a/rules/openssh.mk b/rules/openssh.mk new file mode 100644 index 000000000000..0cc3de621039 --- /dev/null +++ b/rules/openssh.mk @@ -0,0 +1,14 @@ +# openssh package + +OPENSSH_VERSION = 7.9p1-10+deb10u2 + +export OPENSSH_VERSION + +OPENSSH_SERVER = openssh-server_$(OPENSSH_VERSION)_$(CONFIGURED_ARCH).deb +$(OPENSSH_SERVER)_SRC_PATH = $(SRC_PATH)/openssh +SONIC_MAKE_DEBS += $(OPENSSH_SERVER) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += openssh diff --git a/rules/phy-credo.dep b/rules/phy-credo.dep new file mode 100644 index 000000000000..5c0c9fe88fd9 --- /dev/null +++ b/rules/phy-credo.dep @@ -0,0 +1,8 @@ + +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/phy-credo.mk rules/phy-credo.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) + +$(PHY_CREDO)_CACHE_MODE := GIT_CONTENT_SHA +$(PHY_CREDO)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(PHY_CREDO)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/phy-credo.mk b/rules/phy-credo.mk new file mode 100644 index 000000000000..f132498ec211 --- /dev/null +++ b/rules/phy-credo.mk @@ -0,0 +1,3 @@ +PHY_CREDO = phy-credo_1.0_amd64.deb +$(PHY_CREDO)_URL = "https://github.com/aristanetworks/sonic-firmware/raw/78a3df2/phy/phy-credo_1.0_amd64.deb" +SONIC_ONLINE_DEBS += $(PHY_CREDO) diff --git a/rules/ptf.dep b/rules/ptf.dep new file mode 100644 index 000000000000..9df93e7624bd --- /dev/null +++ b/rules/ptf.dep @@ -0,0 +1,12 @@ + +SPATH := $($(PTF)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/ptf.mk rules/ptf.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(PTF)_CACHE_MODE := GIT_CONTENT_SHA +$(PTF)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(PTF)_DEP_FILES := $(DEP_FILES) +$(PTF)_SMDEP_FILES := $(SMDEP_FILES) +$(PTF)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/ptf.mk b/rules/ptf.mk new file mode 100644 index 000000000000..5fe275bdadae --- /dev/null +++ b/rules/ptf.mk @@ -0,0 +1,5 @@ +# ptf package + +PTF = python-ptf_0.9-1_all.deb +$(PTF)_SRC_PATH = $(SRC_PATH)/ptf +SONIC_DPKG_DEBS += $(PTF) diff --git a/rules/quagga.dep b/rules/quagga.dep new file mode 100644 index 000000000000..abaf234a4fee --- /dev/null +++ b/rules/quagga.dep @@ -0,0 +1,13 @@ + +SPATH := $($(QUAGGA)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/quagga.mk rules/quagga.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +#DPKG_FRK +$(QUAGGA)_CACHE_MODE := GIT_CONTENT_SHA +$(QUAGGA)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(QUAGGA)_DEP_FILES := $(DEP_FILES) +$(QUAGGA)_SMDEP_FILES := $(SMDEP_FILES) +$(QUAGGA)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/quagga.mk b/rules/quagga.mk new file mode 100644 index 000000000000..2caef76b2cfd --- /dev/null +++ b/rules/quagga.mk @@ -0,0 +1,11 @@ +# quagga package + +QUAGGA_VERSION_FULL = 0.99.24.1-2.1 + +QUAGGA = quagga_$(QUAGGA_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(QUAGGA)_DEPENDS += $(LIBSNMP_DEV) +$(QUAGGA)_SRC_PATH = $(SRC_PATH)/sonic-quagga +SONIC_DPKG_DEBS += $(QUAGGA) + +QUAGGA_DBG = quagga-dbg_$(QUAGGA_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(QUAGGA),$(QUAGGA_DBG))) diff --git a/rules/redis-dump-load-py2.dep b/rules/redis-dump-load-py2.dep new file mode 100644 index 000000000000..adc43905b7f3 --- /dev/null +++ b/rules/redis-dump-load-py2.dep @@ -0,0 +1,12 @@ + +SPATH := $($(REDIS_DUMP_LOAD_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/redis-dump-load-py2.mk rules/redis-dump-load-py2.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(REDIS_DUMP_LOAD_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(REDIS_DUMP_LOAD_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(REDIS_DUMP_LOAD_PY2)_DEP_FILES := $(DEP_FILES) +$(REDIS_DUMP_LOAD_PY2)_SMDEP_FILES := $(SMDEP_FILES) +$(REDIS_DUMP_LOAD_PY2)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/redis-dump-load-py2.mk b/rules/redis-dump-load-py2.mk new file mode 100644 index 000000000000..5f756caada9c --- /dev/null +++ b/rules/redis-dump-load-py2.mk @@ -0,0 +1,6 @@ +# redis_dump_load python2 wheel + +REDIS_DUMP_LOAD_PY2 = redis_dump_load-1.1-py2-none-any.whl +$(REDIS_DUMP_LOAD_PY2)_SRC_PATH = $(SRC_PATH)/redis-dump-load +$(REDIS_DUMP_LOAD_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(REDIS_DUMP_LOAD_PY2) diff --git a/rules/redis-dump-load-py3.dep b/rules/redis-dump-load-py3.dep new file mode 100644 index 000000000000..1c230acd1f7a --- /dev/null +++ b/rules/redis-dump-load-py3.dep @@ -0,0 +1,10 @@ +SPATH := $($(REDIS_DUMP_LOAD_PY3)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/redis-dump-load-py3.mk rules/redis-dump-load-py3.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(REDIS_DUMP_LOAD_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(REDIS_DUMP_LOAD_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(REDIS_DUMP_LOAD_PY3)_DEP_FILES := $(DEP_FILES) +$(REDIS_DUMP_LOAD_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(REDIS_DUMP_LOAD_PY3)_SMDEP_PATHS := $(SPATH) diff --git a/rules/redis-dump-load-py3.mk b/rules/redis-dump-load-py3.mk new file mode 100644 index 000000000000..875b5e1c8132 --- /dev/null +++ b/rules/redis-dump-load-py3.mk @@ -0,0 +1,9 @@ +# redis_dump_load python3 wheel + +REDIS_DUMP_LOAD_PY3 = redis_dump_load-1.1-py3-none-any.whl +$(REDIS_DUMP_LOAD_PY3)_SRC_PATH = $(SRC_PATH)/redis-dump-load +$(REDIS_DUMP_LOAD_PY3)_PYTHON_VERSION = 3 +# Synthetic dependency just to avoid race condition +$(REDIS_DUMP_LOAD_PY3)_DEPENDS += $(REDIS_DUMP_LOAD_PY2) +$(REDIS_DUMP_LOAD_PY3)_TEST = n +SONIC_PYTHON_WHEELS += $(REDIS_DUMP_LOAD_PY3) diff --git a/rules/redis.dep b/rules/redis.dep new file mode 100644 index 000000000000..1e0562bdef47 --- /dev/null +++ b/rules/redis.dep @@ -0,0 +1,10 @@ + +SPATH := $($(REDIS_TOOLS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/redis.mk rules/redis.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(REDIS_TOOLS)_CACHE_MODE := GIT_CONTENT_SHA +$(REDIS_TOOLS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(REDIS_TOOLS)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/redis.mk b/rules/redis.mk new file mode 100644 index 000000000000..53566b5cdf8b --- /dev/null +++ b/rules/redis.mk @@ -0,0 +1,30 @@ +# redis package +# TODO: docker-sonic-p4 depends on redis-tools in Jessie. +# Remove this file and src/redis after that resolved. +ifneq ($(BLDENV),buster) + + REDIS_VERSION = 5.0.3-3~bpo9+2 + + REDIS_TOOLS = redis-tools_$(REDIS_VERSION)_$(CONFIGURED_ARCH).deb + $(REDIS_TOOLS)_SRC_PATH = $(SRC_PATH)/redis + $(REDIS_TOOLS)_DEPENDS += $(LIBHIREDIS_DEV) + $(REDIS_TOOLS)_RDEPENDS += $(LIBHIREDIS) + SONIC_MAKE_DEBS += $(REDIS_TOOLS) + + REDIS_TOOLS_DBG = redis-tools-dbgsym_$(REDIS_VERSION)_$(CONFIGURED_ARCH).deb + $(eval $(call add_derived_package,$(REDIS_TOOLS),$(REDIS_TOOLS_DBG))) + + REDIS_SERVER = redis-server_$(REDIS_VERSION)_$(CONFIGURED_ARCH).deb + $(eval $(call add_derived_package,$(REDIS_TOOLS),$(REDIS_SERVER))) + + REDIS_SENTINEL = redis-sentinel_$(REDIS_VERSION)_$(CONFIGURED_ARCH).deb + $(REDIS_SENTINEL)_DEPENDS += $(REDIS_SERVER) + $(REDIS_SENTINEL)_RDEPENDS += $(REDIS_SERVER) + $(eval $(call add_derived_package,$(REDIS_TOOLS),$(REDIS_SENTINEL))) + + # The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} + # are archived into debug one image to facilitate debugging. + # + DBG_SRC_ARCHIVE += redis + +endif diff --git a/rules/restapi.dep b/rules/restapi.dep new file mode 100644 index 000000000000..97b69c44678e --- /dev/null +++ b/rules/restapi.dep @@ -0,0 +1,12 @@ + +SPATH := $($(RESTAPI)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/restapi.mk rules/restapi.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(RESTAPI)_CACHE_MODE := GIT_CONTENT_SHA +$(RESTAPI)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(RESTAPI)_DEP_FILES := $(DEP_FILES) +$(RESTAPI)_SMDEP_FILES := $(SMDEP_FILES) +$(RESTAPI)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/restapi.mk b/rules/restapi.mk new file mode 100644 index 000000000000..e66b4a1d976a --- /dev/null +++ b/rules/restapi.mk @@ -0,0 +1,9 @@ +# sonic-rest-api package + +RESTAPI = sonic-rest-api_1.0.1_amd64.deb +$(RESTAPI)_SRC_PATH = $(SRC_PATH)/sonic-restapi +$(RESTAPI)_DEPENDS += $(LIBHIREDIS_DEV) $(LIBNL3_DEV) $(LIBNL_GENL3_DEV) \ + $(LIBNL_ROUTE3_DEV) $(LIBSWSSCOMMON_DEV) $(LIBSWSSCOMMON) +$(RESTAPI)_RDEPENDS += $(LIBHIREDIS) $(LIBNL3) $(LIBNL_GENL3) \ + $(LIBNL_ROUTE3) $(LIBSWSSCOMMON) +SONIC_DPKG_DEBS += $(RESTAPI) diff --git a/rules/sairedis.dep b/rules/sairedis.dep new file mode 100644 index 000000000000..f501a78932c5 --- /dev/null +++ b/rules/sairedis.dep @@ -0,0 +1,17 @@ + +#DPKG FRK +SPATH := $($(LIBSAIREDIS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sairedis.mk rules/sairedis.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) + +SMDEP_PATHS := $(SPATH) $(SPATH)/SAI $(SPATH)/SAI/bm/behavioral-model $(SPATH)/SAI/test/ptf $(SPATH)/SAI/test/saithrift/ctypesgen +$(foreach path, $(SMDEP_PATHS), $(eval $(path) :=$(filter-out $(SMDEP_PATHS),$(addprefix $(path)/, \ + $(shell cd $(path) && git ls-files | grep -v " "))))) + + +$(LIBSAIREDIS)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBSAIREDIS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBSAIREDIS)_DEP_FILES := $(DEP_FILES) +$(LIBSAIREDIS)_SMDEP_FILES := $(foreach path, $(SMDEP_PATHS), $($(path))) +$(LIBSAIREDIS)_SMDEP_PATHS := $(SMDEP_PATHS) + diff --git a/rules/sairedis.mk b/rules/sairedis.mk new file mode 100644 index 000000000000..67148d1b5819 --- /dev/null +++ b/rules/sairedis.mk @@ -0,0 +1,46 @@ +# sairedis package + +LIBSAIREDIS = libsairedis_1.0.0_$(CONFIGURED_ARCH).deb +$(LIBSAIREDIS)_DPKG_TARGET = binary-sairedis +$(LIBSAIREDIS)_SRC_PATH = $(SRC_PATH)/sonic-sairedis +$(LIBSAIREDIS)_DEPENDS += $(LIBSWSSCOMMON_DEV) +$(LIBSAIREDIS)_RDEPENDS += $(LIBSWSSCOMMON) +$(LIBSAIREDIS)_DEB_BUILD_OPTIONS = nocheck +SONIC_DPKG_DEBS += $(LIBSAIREDIS) + +LIBSAIREDIS_DEV = libsairedis-dev_1.0.0_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIREDIS_DEV))) + +LIBSAIVS = libsaivs_1.0.0_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIVS))) + +LIBSAIVS_DEV = libsaivs-dev_1.0.0_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIVS_DEV))) +$(LIBSAIVS_DEV)_DEPENDS += $(LIBSAIVS) + +LIBSAIMETADATA = libsaimetadata_1.0.0_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIMETADATA))) + +LIBSAIMETADATA_DEV = libsaimetadata-dev_1.0.0_$(CONFIGURED_ARCH).deb +$(LIBSAIMETADATA_DEV)_DEPENDS += $(LIBSAIMETADATA) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIMETADATA_DEV))) + +LIBSAIREDIS_DBG = libsairedis-dbg_1.0.0_$(CONFIGURED_ARCH).deb +$(LIBSAIREDIS_DBG)_DEPENDS += $(LIBSAIREDIS) +$(LIBSAIREDIS_DBG)_RDEPENDS += $(LIBSAIREDIS) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIREDIS_DBG))) + +LIBSAIVS_DBG = libsaivs-dbg_1.0.0_$(CONFIGURED_ARCH).deb +$(LIBSAIVS_DBG)_DEPENDS += $(LIBSAIVS) +$(LIBSAIVS_DBG)_RDEPENDS += $(LIBSAIVS) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIVS_DBG))) + +LIBSAIMETADATA_DBG = libsaimetadata-dbg_1.0.0_$(CONFIGURED_ARCH).deb +$(LIBSAIMETADATA_DBG)_DEPENDS += $(LIBSAIMETADATA) +$(LIBSAIMETADATA_DBG)_RDEPENDS += $(LIBSAIMETADATA) +$(eval $(call add_derived_package,$(LIBSAIREDIS),$(LIBSAIMETADATA_DBG))) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += sonic-sairedis diff --git a/rules/scripts.dep b/rules/scripts.dep new file mode 100644 index 000000000000..929611852ea4 --- /dev/null +++ b/rules/scripts.dep @@ -0,0 +1,10 @@ +#DPKG FRK + +$(ARP_UPDATE_SCRIPT)_CACHE_MODE := none +$(ARP_UPDATE_VARS_TEMPLATE)_CACHE_MODE := none +$(CONFIGDB_LOAD_SCRIPT)_CACHE_MODE := none +$(BUFFERS_CONFIG_TEMPLATE)_CACHE_MODE := none +$(UPDATE_PROC_VARIABLES_SCRIPT)_CACHE_MODE := none +$(QOS_CONFIG_TEMPLATE)_CACHE_MODE := none +$(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)_CACHE_MODE := none +$(COPP_CONFIG_TEMPLATE)_CACHE_MODE := none diff --git a/rules/scripts.mk b/rules/scripts.mk new file mode 100644 index 000000000000..e0694a1cdf9b --- /dev/null +++ b/rules/scripts.mk @@ -0,0 +1,41 @@ + +ARP_UPDATE_SCRIPT = arp_update +$(ARP_UPDATE_SCRIPT)_PATH = files/scripts + +ARP_UPDATE_VARS_TEMPLATE = arp_update_vars.j2 +$(ARP_UPDATE_VARS_TEMPLATE)_PATH = files/build_templates + +CONFIGDB_LOAD_SCRIPT = configdb-load.sh +$(CONFIGDB_LOAD_SCRIPT)_PATH = files/scripts + +BUFFERS_CONFIG_TEMPLATE = buffers_config.j2 +$(BUFFERS_CONFIG_TEMPLATE)_PATH = files/build_templates + +QOS_CONFIG_TEMPLATE = qos_config.j2 +$(QOS_CONFIG_TEMPLATE)_PATH = files/build_templates + +SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT = supervisor-proc-exit-listener +$(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)_PATH = files/scripts + +SYSCTL_NET_CONFIG = sysctl-net.conf +$(SYSCTL_NET_CONFIG)_PATH = files/image_config/sysctl + +UPDATE_CHASSISDB_CONFIG_SCRIPT = update_chassisdb_config +$(UPDATE_CHASSISDB_CONFIG_SCRIPT)_PATH = files/scripts + +SWSS_VARS_TEMPLATE = swss_vars.j2 +$(SWSS_VARS_TEMPLATE)_PATH = files/build_templates + +COPP_CONFIG_TEMPLATE = copp_cfg.j2 +$(COPP_CONFIG_TEMPLATE)_PATH = files/image_config/copp + +SONIC_COPY_FILES += $(CONFIGDB_LOAD_SCRIPT) \ + $(ARP_UPDATE_SCRIPT) \ + $(ARP_UPDATE_VARS_TEMPLATE) \ + $(BUFFERS_CONFIG_TEMPLATE) \ + $(QOS_CONFIG_TEMPLATE) \ + $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) \ + $(SYSCTL_NET_CONFIG) \ + $(UPDATE_CHASSISDB_CONFIG_SCRIPT) \ + $(SWSS_VARS_TEMPLATE) \ + $(COPP_CONFIG_TEMPLATE) diff --git a/rules/sflow.dep b/rules/sflow.dep new file mode 100644 index 000000000000..b426959f481f --- /dev/null +++ b/rules/sflow.dep @@ -0,0 +1,19 @@ + +SPATH := $($(HSFLOWD)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sflow.mk rules/sflow.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(HSFLOWD)_CACHE_MODE := GIT_CONTENT_SHA +$(HSFLOWD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(HSFLOWD)_DEP_FILES := $(DEP_FILES) + + +$(SFLOWTOOL)_CACHE_MODE := GIT_CONTENT_SHA +$(SFLOWTOOL)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SFLOWTOOL)_DEP_FILES := $(DEP_FILES) + + +$(PSAMPLE)_CACHE_MODE := GIT_CONTENT_SHA +$(PSAMPLE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(PSAMPLE)_DEP_FILES := $(DEP_FILES) diff --git a/rules/sflow.mk b/rules/sflow.mk new file mode 100644 index 000000000000..7f0ac72bed3f --- /dev/null +++ b/rules/sflow.mk @@ -0,0 +1,46 @@ +# host-sflow package + +HSFLOWD_VERSION = 2.0.32 +HSFLOWD_SUBVERSION = 1 +export HSFLOWD_VERSION HSFLOWD_SUBVERSION + +HSFLOWD = hsflowd_$(HSFLOWD_VERSION)-$(HSFLOWD_SUBVERSION)_$(CONFIGURED_ARCH).deb +$(HSFLOWD)_DEPENDS += $(LIBHIREDIS_DEV) +$(HSFLOWD)_SRC_PATH = $(SRC_PATH)/sflow/hsflowd + +SONIC_MAKE_DEBS += $(HSFLOWD) + +HSFLOWD_DBG = hsflowd-dbg_$(HSFLOWD_VERSION)-$(HSFLOWD_SUBVERSION)_$(CONFIGURED_ARCH).deb +$(HSFLOWD_DBG)_DEPENDS += $(HSFLOWD) +$(HSFLOWD_DBG)_RDEPENDS += $(HSFLOWD) +$(eval $(call add_derived_package,$(HSFLOWD),$(HSFLOWD_DBG))) + +export HSFLOWD HSFLOWD_DBG + +# sflowtool package + +SFLOWTOOL_VERSION = 5.04 +export SFLOWTOOL_VERSION + +SFLOWTOOL = sflowtool_$(SFLOWTOOL_VERSION)_$(CONFIGURED_ARCH).deb +$(SFLOWTOOL)_SRC_PATH = $(SRC_PATH)/sflow/sflowtool + +SONIC_MAKE_DEBS += $(SFLOWTOOL) +export SFLOWTOOL + +# psample package + +PSAMPLE_VERSION = 1.1 +PSAMPLE_SUBVERSION = 1 +export PSAMPLE_VERSION PSAMPLE_SUBVERSION + +PSAMPLE = psample_$(PSAMPLE_VERSION)-$(PSAMPLE_SUBVERSION)_$(CONFIGURED_ARCH).deb +$(PSAMPLE)_SRC_PATH = $(SRC_PATH)/sflow/psample + +SONIC_MAKE_DEBS += $(PSAMPLE) +export PSAMPLE + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += sflow diff --git a/rules/smartmontools.dep b/rules/smartmontools.dep new file mode 100644 index 000000000000..0ca63f5f1fac --- /dev/null +++ b/rules/smartmontools.dep @@ -0,0 +1,10 @@ + +SPATH := $($(SMARTMONTOOLS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/smartmontools.mk rules/smartmontools.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SMARTMONTOOLS)_CACHE_MODE := GIT_CONTENT_SHA +$(SMARTMONTOOLS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SMARTMONTOOLS)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/smartmontools.mk b/rules/smartmontools.mk new file mode 100644 index 000000000000..7cc61eee6feb --- /dev/null +++ b/rules/smartmontools.mk @@ -0,0 +1,12 @@ +# smartmontools package +# + +SMARTMONTOOLS_VERSION_MAJOR = 6.6 +SMARTMONTOOLS_VERSION_FULL = $(SMARTMONTOOLS_VERSION_MAJOR)-1 + +export SMARTMONTOOLS_VERSION_MAJOR SMARTMONTOOLS_VERSION_FULL + +SMARTMONTOOLS = smartmontools_$(SMARTMONTOOLS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(SMARTMONTOOLS)_SRC_PATH = $(SRC_PATH)/smartmontools + +SONIC_MAKE_DEBS += $(SMARTMONTOOLS) diff --git a/rules/snmpd.dep b/rules/snmpd.dep new file mode 100644 index 000000000000..dcab16809bcf --- /dev/null +++ b/rules/snmpd.dep @@ -0,0 +1,10 @@ + +SPATH := $($(LIBSNMP_BASE)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/snmpd.mk rules/snmpd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LIBSNMP_BASE)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBSNMP_BASE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBSNMP_BASE)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/snmpd.mk b/rules/snmpd.mk new file mode 100644 index 000000000000..7922e2097ff0 --- /dev/null +++ b/rules/snmpd.mk @@ -0,0 +1,62 @@ +# snmpd package + +SNMPD_VERSION = 5.7.3+dfsg +SNMPD_VERSION_FULL = $(SNMPD_VERSION)-5 + +export SNMPD_VERSION SNMPD_VERSION_FULL + +LIBSNMP_BASE = libsnmp-base_$(SNMPD_VERSION_FULL)_all.deb +$(LIBSNMP_BASE)_SRC_PATH = $(SRC_PATH)/snmpd +$(LIBSNMP_BASE)_DEPENDS += $(LIBNL3_DEV) +$(LIBSNMP_BASE)_RDEPENDS += $(LIBNL3) +SONIC_MAKE_DEBS += $(LIBSNMP_BASE) + +SNMPTRAPD = snmptrapd_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(SNMPTRAPD)_DEPENDS += $(LIBSNMP) $(SNMPD) +$(SNMPTRAPD)_RDEPENDS += $(LIBSNMP) $(SNMPD) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(SNMPTRAPD))) + +SNMP = snmp_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(SNMP)_DEPENDS += $(LIBSNMP) +$(SNMP)_RDEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(SNMP))) + +SNMPD = snmpd_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(SNMPD)_DEPENDS += $(LIBSNMP) +$(SNMPD)_RDEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(SNMPD))) + +SNMP_DBG = snmp-dbgsym_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(SNMP_DBG))) + +SNMPD_DBG = snmpd-dbgsym_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(SNMPD_DBG))) + +LIBSNMP = libsnmp30_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(LIBSNMP)_RDEPENDS += $(LIBSNMP_BASE) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(LIBSNMP))) + +LIBSNMP_DBG = libsnmp30-dbg_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(LIBSNMP_DBG)_DEPENDS += $(LIBSNMP) +$(LIBSNMP_DBG)_RDEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(LIBSNMP_DBG))) + +LIBSNMP_DEV = libsnmp-dev_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(LIBSNMP_DEV)_DEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(LIBSNMP_DEV))) + +LIBSNMP_PERL = libsnmp-perl_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(LIBSNMP_PERL)_DEPENDS += $(LIBSNMP) +$(LIBSNMP_PERL)_RDEPENDS += $(LIBSNMP) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(LIBSNMP_PERL))) + +TKMIB = tkmib_$(SNMPD_VERSION_FULL)_all.deb +$(TKMIB)_DEPENDS += $(LIBSNMP_PERL) +$(TKMIB)_RDEPENDS += $(LIBSNMP_PERL) +$(eval $(call add_derived_package,$(LIBSNMP_BASE),$(TKMIB))) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += snmpd + diff --git a/rules/socat.dep b/rules/socat.dep new file mode 100644 index 000000000000..18dcd87c0adf --- /dev/null +++ b/rules/socat.dep @@ -0,0 +1,10 @@ + +SPATH := $($(SOCAT)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/socat.mk rules/socat.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SOCAT)_CACHE_MODE := GIT_CONTENT_SHA +$(SOCAT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SOCAT)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/socat.mk b/rules/socat.mk new file mode 100644 index 000000000000..3ee5d5d1c314 --- /dev/null +++ b/rules/socat.mk @@ -0,0 +1,9 @@ +# socat packages + +SOCAT_VERSION = 1.7.3.1-2+deb9u1 + +export SOCAT_VERSION + +SOCAT = socat_$(SOCAT_VERSION)_$(CONFIGURED_ARCH).deb +$(SOCAT)_SRC_PATH = $(SRC_PATH)/socat +SONIC_MAKE_DEBS += $(SOCAT) diff --git a/rules/sonic-chassisd.dep b/rules/sonic-chassisd.dep new file mode 100644 index 000000000000..bf27492937e8 --- /dev/null +++ b/rules/sonic-chassisd.dep @@ -0,0 +1,10 @@ +SPATH := $($(SONIC_CHASSISD_PY3)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-chassisd.mk rules/sonic-chassisd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_CHASSISD_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_CHASSISD_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_CHASSISD_PY3)_DEP_FILES := $(DEP_FILES) +$(SONIC_CHASSISD_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_CHASSISD_PY3)_SMDEP_PATHS := $(SPATH) diff --git a/rules/sonic-chassisd.mk b/rules/sonic-chassisd.mk new file mode 100644 index 000000000000..46a49d359769 --- /dev/null +++ b/rules/sonic-chassisd.mk @@ -0,0 +1,8 @@ +# sonic-chassisd (SONiC Chassis mgmt daemon) wheel package + +SONIC_CHASSISD_PY3 = sonic_chassisd-1.0-py3-none-any.whl +$(SONIC_CHASSISD_PY3)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-chassisd +$(SONIC_CHASSISD_PY3)_DEPENDS = $(SONIC_PY_COMMON_PY3) +$(SONIC_CHASSISD_PY3)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) +$(SONIC_CHASSISD_PY3)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_CHASSISD_PY3) diff --git a/rules/sonic-config.dep b/rules/sonic-config.dep new file mode 100644 index 000000000000..148e43a96a5c --- /dev/null +++ b/rules/sonic-config.dep @@ -0,0 +1,19 @@ +# SONIC_CONFIG_ENGINE_PY2 package + +SPATH := $($(SONIC_CONFIG_ENGINE_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-config.mk rules/sonic-config.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_CONFIG_ENGINE_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_CONFIG_ENGINE_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_CONFIG_ENGINE_PY2)_DEP_FILES := $(DEP_FILES) + +# SONIC_CONFIG_ENGINE_PY3 package + +SPATH := $($(SONIC_CONFIG_ENGINE_PY3)_SRC_PATH) + +$(SONIC_CONFIG_ENGINE_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_CONFIG_ENGINE_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_CONFIG_ENGINE_PY3)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/sonic-config.mk b/rules/sonic-config.mk new file mode 100644 index 000000000000..e8e59fc1b92d --- /dev/null +++ b/rules/sonic-config.mk @@ -0,0 +1,20 @@ +# SONIC_CONFIG_ENGINE_PY2 package + +SONIC_CONFIG_ENGINE_PY2 = sonic_config_engine-1.0-py2-none-any.whl +$(SONIC_CONFIG_ENGINE_PY2)_SRC_PATH = $(SRC_PATH)/sonic-config-engine +$(SONIC_CONFIG_ENGINE_PY2)_DEPENDS += $(SONIC_PY_COMMON_PY2) +$(SONIC_CONFIG_ENGINE_PY2)_DEBS_DEPENDS += $(PYTHON_SWSSCOMMON) +$(SONIC_CONFIG_ENGINE_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE_PY2) + +# SONIC_CONFIG_ENGINE_PY3 package + +SONIC_CONFIG_ENGINE_PY3 = sonic_config_engine-1.0-py3-none-any.whl +$(SONIC_CONFIG_ENGINE_PY3)_SRC_PATH = $(SRC_PATH)/sonic-config-engine +$(SONIC_CONFIG_ENGINE_PY3)_DEPENDS += $(SONIC_PY_COMMON_PY3) +$(SONIC_CONFIG_ENGINE_PY3)_DEBS_DEPENDS += $(PYTHON3_SWSSCOMMON) +# Synthetic dependency to avoid building the Python 2 and 3 packages +# simultaneously and any potential conflicts which may arise +$(SONIC_CONFIG_ENGINE_PY3)_DEPENDS += $(SONIC_CONFIG_ENGINE_PY2) +$(SONIC_CONFIG_ENGINE_PY3)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE_PY3) diff --git a/rules/sonic-ctrmgrd.dep b/rules/sonic-ctrmgrd.dep new file mode 100644 index 000000000000..b6564212769c --- /dev/null +++ b/rules/sonic-ctrmgrd.dep @@ -0,0 +1,8 @@ +SPATH := $($(SONIC_CTRMGRD)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-ctrmgrd.mk rules/sonic-ctrmgrd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_CTRMGRD)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_CTRMGRD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_CTRMGRD)_DEP_FILES := $(DEP_FILES) diff --git a/rules/sonic-ctrmgrd.mk b/rules/sonic-ctrmgrd.mk new file mode 100644 index 000000000000..659a2cf4ace1 --- /dev/null +++ b/rules/sonic-ctrmgrd.mk @@ -0,0 +1,31 @@ +# sonic-ctrmgrd package + +SONIC_CTRMGRD = sonic_ctrmgrd-1.0.0-py3-none-any.whl +$(SONIC_CTRMGRD)_SRC_PATH = $(SRC_PATH)/sonic-ctrmgrd +$(SONIC_CTRMGRD)_FILES_PATH = $($(SONIC_CTRMGRD)_SRC_PATH)/ctrmgr + +$(SONIC_CTRMGRD)_PYTHON_VERSION = 3 +$(SONIC_CTRMGRD)_DEBS_DEPENDS += $(PYTHON3_SWSSCOMMON) +$(SONIC_CTRMGRD)_DEPENDS += $(SONIC_PY_COMMON_PY3) + +$(SONIC_CTRMGRD)_CONTAINER_SCRIPT = container +$($(SONIC_CTRMGRD)_CONTAINER_SCRIPT)_PATH = $($(SONIC_CTRMGRD)_FILES_PATH) + +$(SONIC_CTRMGRD)_STARTUP_SCRIPT = container_startup.py +$($(SONIC_CTRMGRD)_STARTUP_SCRIPT)_PATH = $($(SONIC_CTRMGRD)_FILES_PATH) + +$(SONIC_CTRMGRD)_CFG_JSON = remote_ctr.config.json +$($(SONIC_CTRMGRD)_CFG_JSON)_PATH = $($(SONIC_CTRMGRD)_FILES_PATH) + +$(SONIC_CTRMGRD)_SERVICE = ctrmgrd.service +$($(SONIC_CTRMGRD)_SERVICE)_PATH = $($(SONIC_CTRMGRD)_FILES_PATH) + +SONIC_PYTHON_WHEELS += $(SONIC_CTRMGRD) + +$(SONIC_CTRMGRD)_FILES = $($(SONIC_CTRMGRD)_CONTAINER_SCRIPT) +$(SONIC_CTRMGRD)_FILES += $($(SONIC_CTRMGRD)_STARTUP_SCRIPT) +$(SONIC_CTRMGRD)_FILES += $($(SONIC_CTRMGRD)_CFG_JSON) +$(SONIC_CTRMGRD)_FILES += $($(SONIC_CTRMGRD)_SERVICE) + +SONIC_COPY_FILES += $($(SONIC_CTRMGRD)_FILES) + diff --git a/rules/sonic-device-data.dep b/rules/sonic-device-data.dep new file mode 100644 index 000000000000..325b1492ab49 --- /dev/null +++ b/rules/sonic-device-data.dep @@ -0,0 +1,11 @@ + +SPATH := $($(SONIC_DEVICE_DATA)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-device-data.mk rules/sonic-device-data.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) +DEP_FILES += $(shell find device -type l -prune -o -type f -print ) + +$(SONIC_DEVICE_DATA)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_DEVICE_DATA)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_DEVICE_DATA)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/sonic-device-data.mk b/rules/sonic-device-data.mk new file mode 100644 index 000000000000..abf7d0501f93 --- /dev/null +++ b/rules/sonic-device-data.mk @@ -0,0 +1,10 @@ +# sonic-device-data Debian package + +SONIC_DEVICE_DATA_VERSION = 1.0 +SONIC_DEVICE_DATA_VERSION_FULL = $(SONIC_DEVICE_DATA_VERSION)-1 + +export SONIC_DEVICE_DATA_VERSION SONIC_DEVICE_DATA_VERSION_FULL + +SONIC_DEVICE_DATA = sonic-device-data_$(SONIC_DEVICE_DATA_VERSION_FULL)_all.deb +$(SONIC_DEVICE_DATA)_SRC_PATH = $(SRC_PATH)/sonic-device-data +SONIC_MAKE_DEBS += $(SONIC_DEVICE_DATA) diff --git a/rules/sonic-frr-mgmt-framework.dep b/rules/sonic-frr-mgmt-framework.dep new file mode 100644 index 000000000000..318c4edd1da8 --- /dev/null +++ b/rules/sonic-frr-mgmt-framework.dep @@ -0,0 +1,8 @@ +SPATH := $($(SONIC_FRR_MGMT_FRAMEWORK)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-frr-mgmt-framework.mk rules/sonic-frr-mgmt-framework.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_FRR_MGMT_FRAMEWORK)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_FRR_MGMT_FRAMEWORK)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_FRR_MGMT_FRAMEWORK)_DEP_FILES := $(DEP_FILES) diff --git a/rules/sonic-frr-mgmt-framework.mk b/rules/sonic-frr-mgmt-framework.mk new file mode 100644 index 000000000000..dfe981b440a9 --- /dev/null +++ b/rules/sonic-frr-mgmt-framework.mk @@ -0,0 +1,13 @@ +# sonic-frr-mgmt-framework package + +SONIC_FRR_MGMT_FRAMEWORK = sonic_frr_mgmt_framework-1.0-py3-none-any.whl +$(SONIC_FRR_MGMT_FRAMEWORK)_SRC_PATH = $(SRC_PATH)/sonic-frr-mgmt-framework +# These dependencies are only needed because they are dependencies +# of sonic-config-engine and frrcfgd explicitly calls sonic-cfggen +# as part of its unit tests. +# TODO: Refactor unit tests so that these dependencies are not needed + +$(SONIC_FRR_MGMT_FRAMEWORK)_DEPENDS += $(SONIC_CONFIG_ENGINE_PY3) +$(SONIC_FRR_MGMT_FRAMEWORK)_DEBS_DEPENDS += $(PYTHON_SWSSCOMMON) +$(SONIC_FRR_MGMT_FRAMEWORK)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_FRR_MGMT_FRAMEWORK) diff --git a/rules/sonic-host-services-data.dep b/rules/sonic-host-services-data.dep new file mode 100644 index 000000000000..2b208317f1e2 --- /dev/null +++ b/rules/sonic-host-services-data.dep @@ -0,0 +1,8 @@ +SPATH := $($(SONIC_HOST_SERVICES_DATA)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-host-services-data.mk rules/sonic-host-services-data.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_HOST_SERVICES_DATA)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_HOST_SERVICES_DATA)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_HOST_SERVICES_DATA)_DEP_FILES := $(DEP_FILES) diff --git a/rules/sonic-host-services-data.mk b/rules/sonic-host-services-data.mk new file mode 100644 index 000000000000..64a65904820a --- /dev/null +++ b/rules/sonic-host-services-data.mk @@ -0,0 +1,5 @@ +# SONiC host services data package + +SONIC_HOST_SERVICES_DATA = sonic-host-services-data_1.0-1_all.deb +$(SONIC_HOST_SERVICES_DATA)_SRC_PATH = $(SRC_PATH)/sonic-host-services-data +SONIC_DPKG_DEBS += $(SONIC_HOST_SERVICES_DATA) diff --git a/rules/sonic-host-services.dep b/rules/sonic-host-services.dep new file mode 100644 index 000000000000..0e68ccb035c8 --- /dev/null +++ b/rules/sonic-host-services.dep @@ -0,0 +1,10 @@ +SPATH := $($(SONIC_HOST_SERVICES_PY3)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-host-services.mk rules/sonic-host-services.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_HOST_SERVICES_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_HOST_SERVICES_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_HOST_SERVICES_PY3)_DEP_FILES := $(DEP_FILES) +$(SONIC_HOST_SERVICES_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_HOST_SERVICES_PY3)_SMDEP_PATHS := $(SPATH) diff --git a/rules/sonic-host-services.mk b/rules/sonic-host-services.mk new file mode 100644 index 000000000000..022c237ee950 --- /dev/null +++ b/rules/sonic-host-services.mk @@ -0,0 +1,8 @@ +# SONiC host services package + +SONIC_HOST_SERVICES_PY3 = sonic_host_services-1.0-py3-none-any.whl +$(SONIC_HOST_SERVICES_PY3)_SRC_PATH = $(SRC_PATH)/sonic-host-services +$(SONIC_HOST_SERVICES_PY3)_PYTHON_VERSION = 3 +$(SONIC_HOST_SERVICES_PY3)_DEPENDS += $(SONIC_PY_COMMON_PY3) \ + $(SWSSSDK_PY3) +SONIC_PYTHON_WHEELS += $(SONIC_HOST_SERVICES_PY3) diff --git a/rules/sonic-ledd.dep b/rules/sonic-ledd.dep new file mode 100644 index 000000000000..d9ae18537c6d --- /dev/null +++ b/rules/sonic-ledd.dep @@ -0,0 +1,16 @@ +SPATH := $($(SONIC_LEDD_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-ledd.mk rules/sonic-ledd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_LEDD_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_LEDD_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_LEDD_PY2)_DEP_FILES := $(DEP_FILES) +$(SONIC_LEDD_PY2)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_LEDD_PY2)_SMDEP_PATHS := $(SPATH) + +$(SONIC_LEDD_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_LEDD_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_LEDD_PY3)_DEP_FILES := $(DEP_FILES) +$(SONIC_LEDD_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_LEDD_PY3)_SMDEP_PATHS := $(SPATH) diff --git a/rules/sonic-ledd.mk b/rules/sonic-ledd.mk new file mode 100644 index 000000000000..1439d2c506b0 --- /dev/null +++ b/rules/sonic-ledd.mk @@ -0,0 +1,19 @@ +# sonic-ledd (SONiC Front-panel LED control daemon) Debian package + +# SONIC_LEDD_PY2 package + +SONIC_LEDD_PY2 = sonic_ledd-1.1-py2-none-any.whl +$(SONIC_LEDD_PY2)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-ledd +$(SONIC_LEDD_PY2)_DEPENDS = $(SONIC_PY_COMMON_PY2) +$(SONIC_LEDD_PY2)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) +$(SONIC_LEDD_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_LEDD_PY2) + +# SONIC_LEDD_PY3 package + +SONIC_LEDD_PY3 = sonic_ledd-1.1-py3-none-any.whl +$(SONIC_LEDD_PY3)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-ledd +$(SONIC_LEDD_PY3)_DEPENDS = $(SONIC_PY_COMMON_PY3) $(SONIC_LEDD_PY2) +$(SONIC_LEDD_PY3)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) +$(SONIC_LEDD_PY3)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_LEDD_PY3) diff --git a/rules/sonic-mgmt-common.dep b/rules/sonic-mgmt-common.dep new file mode 100644 index 000000000000..69db9ac08859 --- /dev/null +++ b/rules/sonic-mgmt-common.dep @@ -0,0 +1,12 @@ + +SPATH := $($(SONIC_MGMT_COMMON)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-mgmt-common.mk rules/sonic-mgmt-common.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_MGMT_COMMON)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_MGMT_COMMON)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_MGMT_COMMON)_DEP_FILES := $(DEP_FILES) +$(SONIC_MGMT_COMMON)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_MGMT_COMMON)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/sonic-mgmt-common.mk b/rules/sonic-mgmt-common.mk new file mode 100644 index 000000000000..cde659484df6 --- /dev/null +++ b/rules/sonic-mgmt-common.mk @@ -0,0 +1,12 @@ +# SONiC mgmt-common package + +MGMT_COMMON_VERSION = 1.0.0 +SONIC_MGMT_COMMON = sonic-mgmt-common_$(MGMT_COMMON_VERSION)_$(CONFIGURED_ARCH).deb +$(SONIC_MGMT_COMMON)_SRC_PATH = $(SRC_PATH)/sonic-mgmt-common +$(SONIC_MGMT_COMMON)_DEPENDS = $(LIBYANG_DEV) $(LIBYANG) +$(SONIC_MGMT_COMMON)_RDEPENDS = $(LIBYANG) +SONIC_DPKG_DEBS += $(SONIC_MGMT_COMMON) + +SONIC_MGMT_COMMON_CODEGEN = sonic-mgmt-common-codegen_$(MGMT_COMMON_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(SONIC_MGMT_COMMON),$(SONIC_MGMT_COMMON_CODEGEN))) + diff --git a/rules/sonic-mgmt-framework.dep b/rules/sonic-mgmt-framework.dep new file mode 100644 index 000000000000..d7140821083f --- /dev/null +++ b/rules/sonic-mgmt-framework.dep @@ -0,0 +1,12 @@ + +SPATH := $($(SONIC_MGMT_FRAMEWORK)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-mgmt-framework.mk rules/sonic-mgmt-framework.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_MGMT_FRAMEWORK)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_MGMT_FRAMEWORK)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_MGMT_FRAMEWORK)_DEP_FILES := $(DEP_FILES) +$(SONIC_MGMT_FRAMEWORK)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_MGMT_FRAMEWORK)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/sonic-mgmt-framework.mk b/rules/sonic-mgmt-framework.mk new file mode 100644 index 000000000000..a423f7cd506b --- /dev/null +++ b/rules/sonic-mgmt-framework.mk @@ -0,0 +1,16 @@ +# SONiC mgmt-framework package + +ifeq ($(INCLUDE_MGMT_FRAMEWORK), y) + +SONIC_MGMT_FRAMEWORK = sonic-mgmt-framework_1.0-01_$(CONFIGURED_ARCH).deb +$(SONIC_MGMT_FRAMEWORK)_SRC_PATH = $(SRC_PATH)/sonic-mgmt-framework +$(SONIC_MGMT_FRAMEWORK)_DEPENDS = $(SONIC_MGMT_COMMON) $(SONIC_MGMT_COMMON_CODEGEN) +$(SONIC_MGMT_FRAMEWORK)_RDEPENDS = +SONIC_DPKG_DEBS += $(SONIC_MGMT_FRAMEWORK) + +SONIC_MGMT_FRAMEWORK_DBG = sonic-mgmt-framework-dbg_1.0-01_$(CONFIGURED_ARCH).deb +$(SONIC_MGMT_FRAMEWORK_DBG)_DEPENDS += $(SONIC_MGMT_FRAMEWORK) +$(SONIC_MGMT_FRAMEWORK_DBG)_RDEPENDS += $(SONIC_MGMT_FRAMEWORK) +$(eval $(call add_derived_package,$(SONIC_MGMT_FRAMEWORK),$(SONIC_MGMT_FRAMEWORK_DBG))) + +endif diff --git a/rules/sonic-pcied.dep b/rules/sonic-pcied.dep new file mode 100644 index 000000000000..ddb07f722f6d --- /dev/null +++ b/rules/sonic-pcied.dep @@ -0,0 +1,16 @@ +SPATH:= $($(SONIC_PCIED_PY2)_SRC_PATH) +DEP_FILES:= $(SONIC_COMMON_FILES_LIST) rules/sonic-pcied.mk rules/sonic-pcied.dep +DEP_FILES+= $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES:= $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_PCIED_PY2)_CACHE_MODE:= GIT_CONTENT_SHA +$(SONIC_PCIED_PY2)_DEP_FLAGS:= $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_PCIED_PY2)_DEP_FILES:= $(DEP_FILES) +$(SONIC_PCIED_PY2)_SMDEP_FILES:= $(SMDEP_FILES) +$(SONIC_PCIED_PY2)_SMDEP_PATHS:= $(SPATH) + +$(SONIC_PCIED_PY3)_CACHE_MODE:= GIT_CONTENT_SHA +$(SONIC_PCIED_PY3)_DEP_FLAGS:= $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_PCIED_PY3)_DEP_FILES:= $(DEP_FILES) +$(SONIC_PCIED_PY3)_SMDEP_FILES:= $(SMDEP_FILES) +$(SONIC_PCIED_PY3)_SMDEP_PATHS:= $(SPATH) diff --git a/rules/sonic-pcied.mk b/rules/sonic-pcied.mk new file mode 100644 index 000000000000..5c80ae276860 --- /dev/null +++ b/rules/sonic-pcied.mk @@ -0,0 +1,17 @@ +# sonic-pcied (SONiC PCIe Monitor daemon) Debian package + +# SONIC_PCIED_PY2 package + +SONIC_PCIED_PY2 = sonic_pcied-1.0-py2-none-any.whl +$(SONIC_PCIED_PY2)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-pcied +$(SONIC_PCIED_PY2)_DEPENDS = $(SONIC_PY_COMMON_PY2) +$(SONIC_PCIED_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_PCIED_PY2) + +# SONIC_PCIED_PY3 package + +SONIC_PCIED_PY3 = sonic_pcied-1.0-py3-none-any.whl +$(SONIC_PCIED_PY3)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-pcied +$(SONIC_PCIED_PY3)_DEPENDS = $(SONIC_PY_COMMON_PY3) $(SONIC_PCIED_PY2) +$(SONIC_PCIED_PY3)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_PCIED_PY3) diff --git a/rules/sonic-platform-common.dep b/rules/sonic-platform-common.dep new file mode 100644 index 000000000000..e921c4df01af --- /dev/null +++ b/rules/sonic-platform-common.dep @@ -0,0 +1,21 @@ + +SPATH := $($(SONIC_PLATFORM_COMMON_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-platform-common.mk rules/sonic-platform-common.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files|grep -Ev "^sonic_sfp|^sonic_eeprom")) + +$(SONIC_PLATFORM_COMMON_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_PLATFORM_COMMON_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_PLATFORM_COMMON_PY2)_DEP_FILES := $(DEP_FILES) +$(SONIC_PLATFORM_COMMON_PY2)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_PLATFORM_COMMON_PY2)_SMDEP_PATHS := $(SPATH) + + + +$(SONIC_PLATFORM_COMMON_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_PLATFORM_COMMON_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_PLATFORM_COMMON_PY3)_DEP_FILES := $(DEP_FILES) +$(SONIC_PLATFORM_COMMON_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_PLATFORM_COMMON_PY3)_SMDEP_PATHS := $(SPATH) + + diff --git a/rules/sonic-platform-common.mk b/rules/sonic-platform-common.mk new file mode 100644 index 000000000000..b3dd0155d59e --- /dev/null +++ b/rules/sonic-platform-common.mk @@ -0,0 +1,16 @@ +# sonic-platform-common package + +SONIC_PLATFORM_COMMON_PY2 = sonic_platform_common-1.0-py2-none-any.whl +$(SONIC_PLATFORM_COMMON_PY2)_SRC_PATH = $(SRC_PATH)/sonic-platform-common +$(SONIC_PLATFORM_COMMON_PY2)_PYTHON_VERSION = 2 +$(SONIC_PLATFORM_COMMON_PY2)_DEPENDS += $(SONIC_PY_COMMON_PY2) $(SONIC_CONFIG_ENGINE_PY2) +SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_COMMON_PY2) + +# Als build sonic-platform-common into python3 wheel, so we can use PSU code in SNMP docker +SONIC_PLATFORM_COMMON_PY3 = sonic_platform_common-1.0-py3-none-any.whl +$(SONIC_PLATFORM_COMMON_PY3)_SRC_PATH = $(SRC_PATH)/sonic-platform-common +$(SONIC_PLATFORM_COMMON_PY3)_PYTHON_VERSION = 3 +$(SONIC_PLATFORM_COMMON_PY3)_DEPENDS += $(SONIC_PY_COMMON_PY3) $(SONIC_CONFIG_ENGINE_PY3) +# Synthetic dependency just to avoid race condition +$(SONIC_PLATFORM_COMMON_PY3)_DEPENDS += $(SONIC_PLATFORM_COMMON_PY2) +SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_COMMON_PY3) diff --git a/rules/sonic-psud.dep b/rules/sonic-psud.dep new file mode 100644 index 000000000000..f58d57571d32 --- /dev/null +++ b/rules/sonic-psud.dep @@ -0,0 +1,16 @@ +SPATH := $($(SONIC_PSUD_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-psud.mk rules/sonic-psud.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_PSUD_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_PSUD_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_PSUD_PY2)_DEP_FILES := $(DEP_FILES) +$(SONIC_PSUD_PY2)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_PSUD_PY2)_SMDEP_PATHS := $(SPATH) + +$(SONIC_PSUD_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_PSUD_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_PSUD_PY3)_DEP_FILES := $(DEP_FILES) +$(SONIC_PSUD_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_PSUD_PY3)_SMDEP_PATHS := $(SPATH) diff --git a/rules/sonic-psud.mk b/rules/sonic-psud.mk new file mode 100644 index 000000000000..b07aa31b2002 --- /dev/null +++ b/rules/sonic-psud.mk @@ -0,0 +1,19 @@ +# sonic-psud (SONiC PSU daemon) Debian package + +# SONIC_PSUD_PY2 package + +SONIC_PSUD_PY2 = sonic_psud-1.0-py2-none-any.whl +$(SONIC_PSUD_PY2)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-psud +$(SONIC_PSUD_PY2)_DEPENDS = $(SONIC_PY_COMMON_PY2) +$(SONIC_PSUD_PY2)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) +$(SONIC_PSUD_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_PSUD_PY2) + +# SONIC_PSUD_PY3 package + +SONIC_PSUD_PY3 = sonic_psud-1.0-py3-none-any.whl +$(SONIC_PSUD_PY3)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-psud +$(SONIC_PSUD_PY3)_DEPENDS = $(SONIC_PY_COMMON_PY3) $(SONIC_PSUD_PY2) +$(SONIC_PSUD_PY3)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) +$(SONIC_PSUD_PY3)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_PSUD_PY3) diff --git a/rules/sonic-py-common.dep b/rules/sonic-py-common.dep new file mode 100644 index 000000000000..9ecedb068a4f --- /dev/null +++ b/rules/sonic-py-common.dep @@ -0,0 +1,12 @@ +SPATH := $($(SONIC_PY_COMMON_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-py-common.mk rules/sonic-py-common.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_PY_COMMON_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_PY_COMMON_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_PY_COMMON_PY2)_DEP_FILES := $(DEP_FILES) + +$(SONIC_PY_COMMON_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_PY_COMMON_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_PY_COMMON_PY3)_DEP_FILES := $(DEP_FILES) diff --git a/rules/sonic-py-common.mk b/rules/sonic-py-common.mk new file mode 100644 index 000000000000..6afe9a826c68 --- /dev/null +++ b/rules/sonic-py-common.mk @@ -0,0 +1,18 @@ +# SONIC_PY_COMMON_PY2 package + +SONIC_PY_COMMON_PY2 = sonic_py_common-1.0-py2-none-any.whl +$(SONIC_PY_COMMON_PY2)_SRC_PATH = $(SRC_PATH)/sonic-py-common +$(SONIC_PY_COMMON_PY2)_DEPENDS += $(SWSSSDK_PY2) +$(SONIC_PY_COMMON_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_PY_COMMON_PY2) + +# SONIC_PY_COMMON_PY3 package + +SONIC_PY_COMMON_PY3 = sonic_py_common-1.0-py3-none-any.whl +$(SONIC_PY_COMMON_PY3)_SRC_PATH = $(SRC_PATH)/sonic-py-common +$(SONIC_PY_COMMON_PY3)_DEPENDS += $(SWSSSDK_PY3) +# Synthetic dependency to avoid building the Python 2 and 3 packages +# simultaneously and any potential conflicts which may arise +$(SONIC_PY_COMMON_PY3)_DEPENDS += $(SONIC_PY_COMMON_PY2) +$(SONIC_PY_COMMON_PY3)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_PY_COMMON_PY3) diff --git a/rules/sonic-syseepromd.dep b/rules/sonic-syseepromd.dep new file mode 100644 index 000000000000..f27e436adfe1 --- /dev/null +++ b/rules/sonic-syseepromd.dep @@ -0,0 +1,16 @@ +SPATH := $($(SONIC_SYSEEPROMD_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-syseepromd.mk rules/sonic-syseepromd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_SYSEEPROMD_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_SYSEEPROMD_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_SYSEEPROMD_PY2)_DEP_FILES := $(DEP_FILES) +$(SONIC_SYSEEPROMD_PY2)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_SYSEEPROMD_PY2)_SMDEP_PATHS := $(SPATH) + +$(SONIC_SYSEEPROMD_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_SYSEEPROMD_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_SYSEEPROMD_PY3)_DEP_FILES := $(DEP_FILES) +$(SONIC_SYSEEPROMD_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_SYSEEPROMD_PY3)_SMDEP_PATHS := $(SPATH) diff --git a/rules/sonic-syseepromd.mk b/rules/sonic-syseepromd.mk new file mode 100644 index 000000000000..0732e3b531c5 --- /dev/null +++ b/rules/sonic-syseepromd.mk @@ -0,0 +1,19 @@ +# sonic-syseepromd (SONiC Syseeprom gathering daemon) Debian package + +# SONIC_SYSEEPROMD_PY2 package + +SONIC_SYSEEPROMD_PY2 = sonic_syseepromd-1.0-py2-none-any.whl +$(SONIC_SYSEEPROMD_PY2)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-syseepromd +$(SONIC_SYSEEPROMD_PY2)_DEPENDS = $(SONIC_PY_COMMON_PY2) +$(SONIC_SYSEEPROMD_PY2)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) +$(SONIC_SYSEEPROMD_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_SYSEEPROMD_PY2) + +# SONIC_SYSEEPROMD_PY3 package + +SONIC_SYSEEPROMD_PY3 = sonic_syseepromd-1.0-py3-none-any.whl +$(SONIC_SYSEEPROMD_PY3)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-syseepromd +$(SONIC_SYSEEPROMD_PY3)_DEPENDS = $(SONIC_PY_COMMON_PY3) $(SONIC_SYSEEPROMD_PY2) +$(SONIC_SYSEEPROMD_PY3)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) +$(SONIC_SYSEEPROMD_PY3)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_SYSEEPROMD_PY3) diff --git a/rules/sonic-thermalctld.dep b/rules/sonic-thermalctld.dep new file mode 100644 index 000000000000..5b9d05cb648e --- /dev/null +++ b/rules/sonic-thermalctld.dep @@ -0,0 +1,16 @@ +SPATH := $($(SONIC_THERMALCTLD_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-thermalctld.mk rules/sonic-thermalctld.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_THERMALCTLD_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_THERMALCTLD_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_THERMALCTLD_PY2)_DEP_FILES := $(DEP_FILES) +$(SONIC_THERMALCTLD_PY2)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_THERMALCTLD_PY2)_SMDEP_PATHS := $(SPATH) + +$(SONIC_THERMALCTLD_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_THERMALCTLD_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_THERMALCTLD_PY3)_DEP_FILES := $(DEP_FILES) +$(SONIC_THERMALCTLD_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_THERMALCTLD_PY3)_SMDEP_PATHS := $(SPATH) diff --git a/rules/sonic-thermalctld.mk b/rules/sonic-thermalctld.mk new file mode 100644 index 000000000000..6eb16c5eb3f7 --- /dev/null +++ b/rules/sonic-thermalctld.mk @@ -0,0 +1,19 @@ +# sonic-thermalctld (SONiC Thermal control daemon) Debian package + +# SONIC_THERMALCTLD_PY2 package + +SONIC_THERMALCTLD_PY2 = sonic_thermalctld-1.0-py2-none-any.whl +$(SONIC_THERMALCTLD_PY2)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-thermalctld +$(SONIC_THERMALCTLD_PY2)_DEPENDS = $(SONIC_PY_COMMON_PY2) +$(SONIC_THERMALCTLD_PY2)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) +$(SONIC_THERMALCTLD_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_THERMALCTLD_PY2) + +# SONIC_THERMALCTLD_PY3 package + +SONIC_THERMALCTLD_PY3 = sonic_thermalctld-1.0-py3-none-any.whl +$(SONIC_THERMALCTLD_PY3)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-thermalctld +$(SONIC_THERMALCTLD_PY3)_DEPENDS = $(SONIC_PY_COMMON_PY3) $(SONIC_THERMALCTLD_PY2) +$(SONIC_THERMALCTLD_PY3)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) +$(SONIC_THERMALCTLD_PY3)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_THERMALCTLD_PY3) diff --git a/rules/sonic-utilities-data.dep b/rules/sonic-utilities-data.dep new file mode 100644 index 000000000000..b11d0a554401 --- /dev/null +++ b/rules/sonic-utilities-data.dep @@ -0,0 +1,9 @@ +SPATH := $($(SONIC_UTILITIES_DATA)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-utilities-data.mk rules/sonic-utilities-data.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_UTILITIES_DATA)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_UTILITIES_DATA)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_UTILITIES_DATA)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/sonic-utilities-data.mk b/rules/sonic-utilities-data.mk new file mode 100644 index 000000000000..8eca8b1c9732 --- /dev/null +++ b/rules/sonic-utilities-data.mk @@ -0,0 +1,5 @@ +# SONiC command line utilities data package + +SONIC_UTILITIES_DATA = sonic-utilities-data_1.0-1_all.deb +$(SONIC_UTILITIES_DATA)_SRC_PATH = $(SRC_PATH)/sonic-utilities/sonic-utilities-data +SONIC_DPKG_DEBS += $(SONIC_UTILITIES_DATA) diff --git a/rules/sonic-utilities.dep b/rules/sonic-utilities.dep new file mode 100644 index 000000000000..848b8d66296e --- /dev/null +++ b/rules/sonic-utilities.dep @@ -0,0 +1,10 @@ +SPATH := $($(SONIC_UTILITIES_PY3)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-utilities.mk rules/sonic-utilities.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_UTILITIES_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_UTILITIES_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_UTILITIES_PY3)_DEP_FILES := $(DEP_FILES) +$(SONIC_UTILITIES_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_UTILITIES_PY3)_SMDEP_PATHS := $(SPATH) diff --git a/rules/sonic-utilities.mk b/rules/sonic-utilities.mk new file mode 100644 index 000000000000..4e5b5adbc5dc --- /dev/null +++ b/rules/sonic-utilities.mk @@ -0,0 +1,17 @@ +# sonic utilities package + +SONIC_UTILITIES_PY3 = sonic_utilities-1.2-py3-none-any.whl +$(SONIC_UTILITIES_PY3)_SRC_PATH = $(SRC_PATH)/sonic-utilities +$(SONIC_UTILITIES_PY3)_PYTHON_VERSION = 3 +$(SONIC_UTILITIES_PY3)_DEPENDS += $(SONIC_PY_COMMON_PY3) \ + $(SWSSSDK_PY3) \ + $(SONIC_CONFIG_ENGINE_PY3) \ + $(SONIC_PLATFORM_COMMON_PY3) \ + $(SONIC_YANG_MGMT_PY3) \ + $(SONIC_YANG_MODELS_PY3) +$(SONIC_UTILITIES_PY3)_DEBS_DEPENDS = $(LIBYANG) \ + $(LIBYANG_CPP) \ + $(LIBYANG_PY3) \ + $(LIBSWSSCOMMON) \ + $(PYTHON3_SWSSCOMMON) +SONIC_PYTHON_WHEELS += $(SONIC_UTILITIES_PY3) diff --git a/rules/sonic-xcvrd.dep b/rules/sonic-xcvrd.dep new file mode 100644 index 000000000000..0bda526b48b5 --- /dev/null +++ b/rules/sonic-xcvrd.dep @@ -0,0 +1,16 @@ +SPATH := $($(SONIC_XCVRD_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-xcvrd.mk rules/sonic-xcvrd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SONIC_XCVRD_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_XCVRD_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_XCVRD_PY2)_DEP_FILES := $(DEP_FILES) +$(SONIC_XCVRD_PY2)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_XCVRD_PY2)_SMDEP_PATHS := $(SPATH) + +$(SONIC_XCVRD_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_XCVRD_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_XCVRD_PY3)_DEP_FILES := $(DEP_FILES) +$(SONIC_XCVRD_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_XCVRD_PY3)_SMDEP_PATHS := $(SPATH) diff --git a/rules/sonic-xcvrd.mk b/rules/sonic-xcvrd.mk new file mode 100644 index 000000000000..018363f367fd --- /dev/null +++ b/rules/sonic-xcvrd.mk @@ -0,0 +1,19 @@ +# sonic-xcvrd (SONiC Transceiver monitoring daemon) Debian package + +# SONIC_XCVRD_PY2 package + +SONIC_XCVRD_PY2 = sonic_xcvrd-1.0-py2-none-any.whl +$(SONIC_XCVRD_PY2)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-xcvrd +$(SONIC_XCVRD_PY2)_DEPENDS = $(SONIC_PY_COMMON_PY2) $(SONIC_PLATFORM_COMMON_PY2) +$(SONIC_XCVRD_PY2)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) +$(SONIC_XCVRD_PY2)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_XCVRD_PY2) + +# SONIC_XCVRD_PY3 package + +SONIC_XCVRD_PY3 = sonic_xcvrd-1.0-py3-none-any.whl +$(SONIC_XCVRD_PY3)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-xcvrd +$(SONIC_XCVRD_PY3)_DEPENDS = $(SONIC_PY_COMMON_PY3) $(SONIC_XCVRD_PY2) $(SONIC_PLATFORM_COMMON_PY3) +$(SONIC_XCVRD_PY3)_DEBS_DEPENDS = $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) +$(SONIC_XCVRD_PY3)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_XCVRD_PY3) diff --git a/rules/sonic-yang-mgmt-py3.dep b/rules/sonic-yang-mgmt-py3.dep new file mode 100644 index 000000000000..e6528220c6d8 --- /dev/null +++ b/rules/sonic-yang-mgmt-py3.dep @@ -0,0 +1,10 @@ + +SPATH := $($(SONIC_YANG_MGMT_PY3)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-yang-mgmt-py3.mk rules/sonic-yang-mgmt-py3.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_YANG_MGMT_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_YANG_MGMT_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_YANG_MGMT_PY3)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/sonic-yang-mgmt-py3.mk b/rules/sonic-yang-mgmt-py3.mk new file mode 100644 index 000000000000..877fc6de3952 --- /dev/null +++ b/rules/sonic-yang-mgmt-py3.mk @@ -0,0 +1,11 @@ +# sonic-yang-mgmt python3 wheel + +SONIC_YANG_MGMT_PY3 = sonic_yang_mgmt-1.0-py3-none-any.whl +$(SONIC_YANG_MGMT_PY3)_SRC_PATH = $(SRC_PATH)/sonic-yang-mgmt +$(SONIC_YANG_MGMT_PY3)_PYTHON_VERSION = 3 +$(SONIC_YANG_MGMT_PY3)_DEBS_DEPENDS = $(LIBYANG) $(LIBYANG_CPP) $(LIBYANG_PY3) +$(SONIC_YANG_MGMT_PY3)_DEPENDS = $(SONIC_YANG_MODELS_PY3) +$(SONIC_YANG_MGMT_PY3)_RDEPENDS = $(SONIC_YANG_MODELS_PY3) $(LIBYANG) \ + $(LIBYANG_CPP) $(LIBYANG_PY3) + +SONIC_PYTHON_WHEELS += $(SONIC_YANG_MGMT_PY3) diff --git a/rules/sonic-yang-models-py3.dep b/rules/sonic-yang-models-py3.dep new file mode 100644 index 000000000000..34b8c785f4bf --- /dev/null +++ b/rules/sonic-yang-models-py3.dep @@ -0,0 +1,9 @@ +SPATH := $($(SONIC_YANG_MODELS_PY3)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-yang-models-py3.mk rules/sonic-yang-models-py3.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_YANG_MODELS_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_YANG_MODELS_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_YANG_MODELS_PY3)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/sonic-yang-models-py3.mk b/rules/sonic-yang-models-py3.mk new file mode 100644 index 000000000000..8c11a921a979 --- /dev/null +++ b/rules/sonic-yang-models-py3.mk @@ -0,0 +1,8 @@ +SONIC_YANG_MODELS_PY3 = sonic_yang_models-1.0-py3-none-any.whl +$(SONIC_YANG_MODELS_PY3)_SRC_PATH = $(SRC_PATH)/sonic-yang-models +$(SONIC_YANG_MODELS_PY3)_PYTHON_VERSION = 3 +$(SONIC_YANG_MODELS_PY3)_DEBS_DEPENDS = $(LIBYANG) $(LIBYANG_CPP) \ + $(LIBYANG_PY2) $(LIBYANG_PY3) + +SONIC_PYTHON_WHEELS += $(SONIC_YANG_MODELS_PY3) +export SONIC_YANG_MODELS_PY3 diff --git a/rules/sonic-ztp.dep b/rules/sonic-ztp.dep new file mode 100644 index 000000000000..bf6622ddb505 --- /dev/null +++ b/rules/sonic-ztp.dep @@ -0,0 +1,13 @@ + +SPATH := $($(SONIC_ZTP)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-ztp.mk rules/sonic-ztp.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files|grep -Ev "dhclient-enter-hooks.d|dhclient-exit-hooks.d")) + + +$(SONIC_ZTP)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_ZTP)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_ZTP)_DEP_FILES := $(DEP_FILES) +$(SONIC_ZTP)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_ZTP)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/sonic-ztp.mk b/rules/sonic-ztp.mk new file mode 100644 index 000000000000..0c4819ec6004 --- /dev/null +++ b/rules/sonic-ztp.mk @@ -0,0 +1,14 @@ +# SONiC ztp package +# + +SONIC_ZTP_VERSION = 1.0.0 + +SONIC_ZTP = sonic-ztp_$(SONIC_ZTP_VERSION)_all.deb +$(SONIC_ZTP)_SRC_PATH = $(SRC_PATH)/sonic-ztp +$(SONIC_ZTP)_WHEEL_DEPENDS += $(SWSSSDK_PY3) +SONIC_DPKG_DEBS += $(SONIC_ZTP) + +export SONIC_ZTP_VERSION +export SONIC_ZTP + + diff --git a/rules/sonic_bgpcfgd.dep b/rules/sonic_bgpcfgd.dep new file mode 100644 index 000000000000..abd51062b8bb --- /dev/null +++ b/rules/sonic_bgpcfgd.dep @@ -0,0 +1,10 @@ + +SPATH := $($(SONIC_BGPCFGD)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic_bgpcfgd.mk rules/sonic_bgpcfgd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_BGPCFGD)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_BGPCFGD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_BGPCFGD)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/sonic_bgpcfgd.mk b/rules/sonic_bgpcfgd.mk new file mode 100644 index 000000000000..3e1395842b51 --- /dev/null +++ b/rules/sonic_bgpcfgd.mk @@ -0,0 +1,13 @@ +# sonic-bgpcfgd package + +SONIC_BGPCFGD = sonic_bgpcfgd-1.0-py3-none-any.whl +$(SONIC_BGPCFGD)_SRC_PATH = $(SRC_PATH)/sonic-bgpcfgd +# These dependencies are only needed because they are dependencies +# of sonic-config-engine and bgpcfgd explicitly calls sonic-cfggen +# as part of its unit tests. +# TODO: Refactor unit tests so that these dependencies are not needed + +$(SONIC_BGPCFGD)_DEPENDS += $(SONIC_CONFIG_ENGINE_PY3) +$(SONIC_BGPCFGD)_DEBS_DEPENDS += $(PYTHON3_SWSSCOMMON) +$(SONIC_BGPCFGD)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_BGPCFGD) diff --git a/rules/swss-common.dep b/rules/swss-common.dep new file mode 100644 index 000000000000..b4e95a9917d6 --- /dev/null +++ b/rules/swss-common.dep @@ -0,0 +1,12 @@ + +SPATH := $($(LIBSWSSCOMMON)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/swss-common.mk rules/swss-common.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(LIBSWSSCOMMON)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBSWSSCOMMON)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBSWSSCOMMON)_DEP_FILES := $(DEP_FILES) +$(LIBSWSSCOMMON)_SMDEP_FILES := $(SMDEP_FILES) +$(LIBSWSSCOMMON)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/swss-common.mk b/rules/swss-common.mk new file mode 100644 index 000000000000..8a319ea62bc0 --- /dev/null +++ b/rules/swss-common.mk @@ -0,0 +1,30 @@ +# libswsscommon package + +LIBSWSSCOMMON = libswsscommon_1.0.0_$(CONFIGURED_ARCH).deb +$(LIBSWSSCOMMON)_SRC_PATH = $(SRC_PATH)/sonic-swss-common +$(LIBSWSSCOMMON)_DEPENDS += $(LIBHIREDIS_DEV) $(LIBNL3_DEV) $(LIBNL_GENL3_DEV) \ + $(LIBNL_ROUTE3_DEV) $(LIBNL_NF3_DEV) \ + $(LIBNL_CLI_DEV) +$(LIBSWSSCOMMON)_RDEPENDS += $(LIBHIREDIS) $(LIBNL3) $(LIBNL_GENL3) \ + $(LIBNL_ROUTE3) $(LIBNL_NF3) $(LIBNL_CLI) +SONIC_DPKG_DEBS += $(LIBSWSSCOMMON) + +LIBSWSSCOMMON_DEV = libswsscommon-dev_1.0.0_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBSWSSCOMMON),$(LIBSWSSCOMMON_DEV))) + +PYTHON_SWSSCOMMON = python-swsscommon_1.0.0_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBSWSSCOMMON),$(PYTHON_SWSSCOMMON))) + +PYTHON3_SWSSCOMMON = python3-swsscommon_1.0.0_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBSWSSCOMMON),$(PYTHON3_SWSSCOMMON))) + +LIBSWSSCOMMON_DBG = libswsscommon-dbg_1.0.0_$(CONFIGURED_ARCH).deb +$(LIBSWSSCOMMON_DBG)_DEPENDS += $(LIBSWSSCOMMON) +$(LIBSWSSCOMMON_DBG)_RDEPENDS += $(LIBSWSSCOMMON) +$(eval $(call add_derived_package,$(LIBSWSSCOMMON),$(LIBSWSSCOMMON_DBG))) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += sonic-swss-common + diff --git a/rules/swss.dep b/rules/swss.dep new file mode 100644 index 000000000000..e57a9e7a6314 --- /dev/null +++ b/rules/swss.dep @@ -0,0 +1,12 @@ + +SPATH := $($(SWSS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/swss.mk rules/swss.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SWSS)_CACHE_MODE := GIT_CONTENT_SHA +$(SWSS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SWSS)_DEP_FILES := $(DEP_FILES) +$(SWSS)_SMDEP_FILES := $(SMDEP_FILES) +$(SWSS)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/swss.mk b/rules/swss.mk new file mode 100644 index 000000000000..e4d18cf2eb3d --- /dev/null +++ b/rules/swss.mk @@ -0,0 +1,23 @@ +# swss package + +SWSS = swss_1.0.0_$(CONFIGURED_ARCH).deb +$(SWSS)_SRC_PATH = $(SRC_PATH)/sonic-swss +$(SWSS)_DEPENDS += $(LIBSAIREDIS_DEV) $(LIBSAIMETADATA_DEV) $(LIBTEAM_DEV) \ + $(LIBTEAMDCTL) $(LIBTEAM_UTILS) $(LIBSWSSCOMMON_DEV) \ + $(LIBSAIVS) $(LIBSAIVS_DEV) +$(SWSS)_UNINSTALLS = $(LIBSAIVS_DEV) + +$(SWSS)_RDEPENDS += $(LIBSAIREDIS) $(LIBSAIMETADATA) $(LIBTEAM) \ + $(LIBTEAMDCTL) $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) +SONIC_DPKG_DEBS += $(SWSS) + +SWSS_DBG = swss-dbg_1.0.0_$(CONFIGURED_ARCH).deb +$(SWSS_DBG)_DEPENDS += $(SWSS) +$(SWSS_DBG)_RDEPENDS += $(SWSS) +$(eval $(call add_derived_package,$(SWSS),$(SWSS_DBG))) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += sonic-swss + diff --git a/rules/swsssdk-py2.dep b/rules/swsssdk-py2.dep new file mode 100644 index 000000000000..2be9565fedcc --- /dev/null +++ b/rules/swsssdk-py2.dep @@ -0,0 +1,12 @@ + +SPATH := $($(SWSSSDK_PY2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/swsssdk-py2.mk rules/swsssdk-py2.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SWSSSDK_PY2)_CACHE_MODE := GIT_CONTENT_SHA +$(SWSSSDK_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SWSSSDK_PY2)_DEP_FILES := $(DEP_FILES) +$(SWSSSDK_PY2)_SMDEP_FILES := $(SMDEP_FILES) +$(SWSSSDK_PY2)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/swsssdk-py2.mk b/rules/swsssdk-py2.mk new file mode 100644 index 000000000000..8a98d1feda0a --- /dev/null +++ b/rules/swsssdk-py2.mk @@ -0,0 +1,7 @@ +# swsssdk python2 wheel + +SWSSSDK_PY2 = swsssdk-2.0.1-py2-none-any.whl +$(SWSSSDK_PY2)_SRC_PATH = $(SRC_PATH)/sonic-py-swsssdk +$(SWSSSDK_PY2)_PYTHON_VERSION = 2 +$(SWSSSDK_PY2)_DEPENDS += $(REDIS_DUMP_LOAD_PY2) +SONIC_PYTHON_WHEELS += $(SWSSSDK_PY2) diff --git a/rules/swsssdk-py3.dep b/rules/swsssdk-py3.dep new file mode 100644 index 000000000000..4119d9f2fa1b --- /dev/null +++ b/rules/swsssdk-py3.dep @@ -0,0 +1,12 @@ + +SPATH := $($(SWSSSDK_PY3)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/swsssdk-py3.mk rules/swsssdk-py3.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + +$(SWSSSDK_PY3)_CACHE_MODE := GIT_CONTENT_SHA +$(SWSSSDK_PY3)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SWSSSDK_PY3)_DEP_FILES := $(DEP_FILES) +$(SWSSSDK_PY3)_SMDEP_FILES := $(SMDEP_FILES) +$(SWSSSDK_PY3)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/swsssdk-py3.mk b/rules/swsssdk-py3.mk new file mode 100644 index 000000000000..681ba72f85b7 --- /dev/null +++ b/rules/swsssdk-py3.mk @@ -0,0 +1,8 @@ +# swsssdk python3 wheel + +SWSSSDK_PY3 = swsssdk-2.0.1-py3-none-any.whl +$(SWSSSDK_PY3)_SRC_PATH = $(SRC_PATH)/sonic-py-swsssdk +$(SWSSSDK_PY3)_PYTHON_VERSION = 3 +# Synthetic dependency just to avoid race condition +$(SWSSSDK_PY3)_DEPENDS += $(SWSSSDK_PY2) $(REDIS_DUMP_LOAD_PY3) +SONIC_PYTHON_WHEELS += $(SWSSSDK_PY3) diff --git a/rules/syncd.dep b/rules/syncd.dep new file mode 100644 index 000000000000..d9f40a8a0210 --- /dev/null +++ b/rules/syncd.dep @@ -0,0 +1,20 @@ + +ifneq ($(CONFIGURED_PLATFORM),vs) + +#DPKG FRK +SPATH := $($(SYNCD)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/syncd.mk rules/syncd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) + +SMDEP_PATHS := $(SPATH) $(SPATH)/SAI $(SPATH)/SAI/bm/behavioral-model $(SPATH)/SAI/test/ptf $(SPATH)/SAI/test/saithrift/ctypesgen +$(foreach path, $(SMDEP_PATHS), $(eval $(path) :=$(filter-out $(SMDEP_PATHS),$(addprefix $(path)/, \ + $(shell cd $(path) && git ls-files | grep -v " "))))) + + +$(SYNCD)_CACHE_MODE := GIT_CONTENT_SHA +$(SYNCD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SYNCD)_DEP_FILES := $(DEP_FILES) +$(SYNCD)_SMDEP_FILES := $(foreach path, $(SMDEP_PATHS), $($(path))) +$(SYNCD)_SMDEP_PATHS := $(SMDEP_PATHS) + +endif diff --git a/rules/syncd.mk b/rules/syncd.mk new file mode 100644 index 000000000000..2b7007d84d5b --- /dev/null +++ b/rules/syncd.mk @@ -0,0 +1,36 @@ +# only used for non-vs platforms + +ifneq ($(CONFIGURED_PLATFORM),vs) + +SYNCD = syncd_1.0.0_$(CONFIGURED_ARCH).deb +$(SYNCD)_RDEPENDS += $(LIBSAIREDIS) $(LIBSAIMETADATA) +$(SYNCD)_DPKG_TARGET = binary-syncd +$(SYNCD)_SRC_PATH = $(SRC_PATH)/sonic-sairedis +$(SYNCD)_DEPENDS += $(LIBSWSSCOMMON_DEV) $(LIBSAIREDIS) +$(SYNCD)_RDEPENDS += $(LIBSWSSCOMMON) +$(SYNCD)_DEB_BUILD_OPTIONS = nocheck +SONIC_DPKG_DEBS += $(SYNCD) + +ifeq ($(ENABLE_SYNCD_RPC),y) +SYNCD_RPC = syncd-rpc_1.0.0_$(CONFIGURED_ARCH).deb +$(SYNCD_RPC)_RDEPENDS += $(LIBSAIREDIS) $(LIBSAIMETADATA) +$(eval $(call add_derived_package,$(SYNCD),$(SYNCD_RPC))) + +# Inject libthrift build dependency for RPC build +$(SYNCD)_DEPENDS += $(LIBSWSSCOMMON_DEV) $(LIBTHRIFT_DEV) +$(SYNCD)_DPKG_TARGET = binary-syncd-rpc +endif + +SYNCD_DBG = syncd-dbg_1.0.0_$(CONFIGURED_ARCH).deb +$(SYNCD_DBG)_DEPENDS += $(SYNCD) +$(SYNCD_DBG)_RDEPENDS += $(SYNCD) +$(eval $(call add_derived_package,$(SYNCD),$(SYNCD_DBG))) + +ifeq ($(ENABLE_SYNCD_RPC),y) +SYNCD_RPC_DBG = syncd-rpc-dbg_1.0.0_$(CONFIGURED_ARCH).deb +$(SYNCD_RPC_DBG)_DEPENDS += $(SYNCD_RPC) +$(SYNCD_RPC_DBG)_RDEPENDS += $(SYNCD_RPC) +$(eval $(call add_derived_package,$(SYNCD),$(SYNCD_RPC_DBG))) +endif + +endif diff --git a/rules/system-health.dep b/rules/system-health.dep new file mode 100644 index 000000000000..31de25cb6d8c --- /dev/null +++ b/rules/system-health.dep @@ -0,0 +1,8 @@ +SPATH := $($(SYSTEM_HEALTH)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/system-health.mk rules/system-health.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SYSTEM_HEALTH)_CACHE_MODE := GIT_CONTENT_SHA +$(SYSTEM_HEALTH)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SYSTEM_HEALTH)_DEP_FILES := $(DEP_FILES) diff --git a/rules/system-health.mk b/rules/system-health.mk new file mode 100644 index 000000000000..bafc09daa70f --- /dev/null +++ b/rules/system-health.mk @@ -0,0 +1,9 @@ +# system health Python wheel + +SYSTEM_HEALTH = system_health-1.0-py3-none-any.whl +$(SYSTEM_HEALTH)_SRC_PATH = $(SRC_PATH)/system-health +$(SYSTEM_HEALTH)_PYTHON_VERSION = 3 +$(SYSTEM_HEALTH)_DEPENDS = $(SONIC_PY_COMMON_PY3) $(SWSSSDK_PY3) $(SONIC_CONFIG_ENGINE_PY3) +SONIC_PYTHON_WHEELS += $(SYSTEM_HEALTH) + +export system_health_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SYSTEM_HEALTH))" diff --git a/rules/systemd-sonic-generator.dep b/rules/systemd-sonic-generator.dep new file mode 100644 index 000000000000..d6094c0cd51b --- /dev/null +++ b/rules/systemd-sonic-generator.dep @@ -0,0 +1,10 @@ + +SPATH := $($(SYSTEMD_SONIC_GENERATOR)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/systemd-sonic-generator.mk rules/systemd-sonic-generator.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SYSTEMD_SONIC_GENERATOR)_CACHE_MODE := GIT_CONTENT_SHA +$(SYSTEMD_SONIC_GENERATOR)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SYSTEMD_SONIC_GENERATOR)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/systemd-sonic-generator.mk b/rules/systemd-sonic-generator.mk new file mode 100644 index 000000000000..cea08099177f --- /dev/null +++ b/rules/systemd-sonic-generator.mk @@ -0,0 +1,3 @@ +SYSTEMD_SONIC_GENERATOR = systemd-sonic-generator_1.0.0_$(CONFIGURED_ARCH).deb +$(SYSTEMD_SONIC_GENERATOR)_SRC_PATH = $(SRC_PATH)/systemd-sonic-generator +SONIC_MAKE_DEBS += $(SYSTEMD_SONIC_GENERATOR) diff --git a/rules/tacacs.dep b/rules/tacacs.dep new file mode 100644 index 000000000000..29de9262f557 --- /dev/null +++ b/rules/tacacs.dep @@ -0,0 +1,23 @@ +#DPKG FRK + +SPATH := $($(LIBTAC2)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/tacacs.mk rules/tacacs.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LIBTAC2)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBTAC2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBTAC2)_DEP_FILES := $(DEP_FILES) + + + + +SPATH := $($(LIBNSS_TACPLUS)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/tacacs.mk rules/tacacs.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LIBNSS_TACPLUS)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBNSS_TACPLUS)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBNSS_TACPLUS)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/tacacs.mk b/rules/tacacs.mk new file mode 100644 index 000000000000..1c620ebcedc5 --- /dev/null +++ b/rules/tacacs.mk @@ -0,0 +1,35 @@ +# libpam-tacplus packages + +PAM_TACPLUS_VERSION = 1.4.1-1 + +export PAM_TACPLUS_VERSION + +LIBTAC2 = libtac2_$(PAM_TACPLUS_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBTAC2)_SRC_PATH = $(SRC_PATH)/tacacs/pam +SONIC_MAKE_DEBS += $(LIBTAC2) + +LIBPAM_TACPLUS = libpam-tacplus_$(PAM_TACPLUS_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBPAM_TACPLUS)_RDEPENDS += $(LIBTAC2) +$(eval $(call add_extra_package,$(LIBTAC2),$(LIBPAM_TACPLUS))) + +LIBTAC_DEV = libtac-dev_$(PAM_TACPLUS_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBTAC_DEV)_DEPENDS += $(LIBTAC2) +$(eval $(call add_derived_package,$(LIBTAC2),$(LIBTAC_DEV))) + + + +# libnss-tacplus packages +NSS_TACPLUS_VERSION = 1.0.4-1 + +export NSS_TACPLUS_VERSION + +LIBNSS_TACPLUS = libnss-tacplus_$(NSS_TACPLUS_VERSION)_$(CONFIGURED_ARCH).deb +$(LIBNSS_TACPLUS)_DEPENDS += $(LIBTAC_DEV) +$(LIBNSS_TACPLUS)_RDEPENDS += $(LIBTAC2) +$(LIBNSS_TACPLUS)_SRC_PATH = $(SRC_PATH)/tacacs/nss +SONIC_MAKE_DEBS += $(LIBNSS_TACPLUS) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += tacacs diff --git a/rules/telemetry.dep b/rules/telemetry.dep new file mode 100644 index 000000000000..d759b3acac21 --- /dev/null +++ b/rules/telemetry.dep @@ -0,0 +1,13 @@ +#DPKG FRK +SPATH := $($(SONIC_TELEMETRY)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/telemetry.mk rules/telemetry.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + + +$(SONIC_TELEMETRY)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_TELEMETRY)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_TELEMETRY)_DEP_FILES := $(DEP_FILES) +$(SONIC_TELEMETRY)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_TELEMETRY)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/telemetry.mk b/rules/telemetry.mk new file mode 100644 index 000000000000..392ed4f28680 --- /dev/null +++ b/rules/telemetry.mk @@ -0,0 +1,7 @@ +# SONiC telemetry package + +SONIC_TELEMETRY = sonic-telemetry_0.1_$(CONFIGURED_ARCH).deb +$(SONIC_TELEMETRY)_SRC_PATH = $(SRC_PATH)/sonic-telemetry +$(SONIC_TELEMETRY)_DEPENDS = $(SONIC_MGMT_COMMON) $(SONIC_MGMT_COMMON_CODEGEN) +$(SONIC_TELEMETRY)_RDEPENDS = +SONIC_DPKG_DEBS += $(SONIC_TELEMETRY) diff --git a/rules/template.dep b/rules/template.dep new file mode 100644 index 000000000000..d110c2e20ad0 --- /dev/null +++ b/rules/template.dep @@ -0,0 +1,49 @@ +#DPKG FRK + +# This provides a template for adding a DPKG cache rule for a new module +# +# __NEW_MODULE__ => Name of the module to be cached +# __NEW_RULES__ => Module rule name +# If a module is linked as a submodule, all the depencency files should be added in the _SMDEP_FILES rule +# All other dependency files should be added in the _DEP_FILES rule +# All the ENV flags should be added in the _DEP_FLAGS rule +# If module has multiple source path as a submodule, it should be added as prt of _SMDEP_PATHS rule + +#Source path of the module +SPATH := $($(__NEW_MODULE__)_SRC_PATH) + +# Add all the dependendency files in the DEP_FILES variable +# SONIC_COMMON_FILES_LIST => It includes common files like .platform, slave.mk, rules/functions etc +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/__NEW_RULES__.mk rules/__NEW_RULES__.dep + +# SONIC_COMMON_BASE_FILES_LIST => It includes base docker files like Dockerfile, Dockerfile.user etc +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) + +# If a module source files are part of sonic-buildimage, add the source files to DEP_FILES variable +#DEP_FILES += $(shell git ls-files $(SPATH)) + +# If the module is a submodule, add all the submodule source files into SMDEP_FILES variable +#SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) + + + + +# Define the DPKG cache rule for a module +# Set the Cache mode, +# GIT_CONTENT_SHA => Cache SHA is derived from contents of the module dependency files +# GIT_COMMIT_SHA => Cache SHA is derived from the last commit id of a module +$(__NEW_MODULE__)_CACHE_MODE := GIT_CONTENT_SHA + +# List all the environment flags that module depends on +# SONIC_COMMON_FLAGS_LIST => It includes the defaults flags like SONIC_DEBUGGING_ON, SONIC_PROFILE_ON etc +$(__NEW_MODULE__)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) + +# List all the dependency files +$(__NEW_MODULE__)_DEP_FILES := $(DEP_FILES) + +# List all the sub module dependendency files +#$(__NEW_MODULE__)_SMDEP_FILES := $(SMDEP_FILES) + +# List all the sub module paths +#$(__NEW_MODULE__)_SMDEP_PATHS := $(SPATH) + diff --git a/rules/thrift.dep b/rules/thrift.dep new file mode 100644 index 000000000000..a1700a922837 --- /dev/null +++ b/rules/thrift.dep @@ -0,0 +1,10 @@ + +SPATH := $($(LIBTHRIFT)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/thrift.mk rules/thrift.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(LIBTHRIFT)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBTHRIFT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBTHRIFT)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/thrift.mk b/rules/thrift.mk new file mode 100644 index 000000000000..92d7ab2eeb0f --- /dev/null +++ b/rules/thrift.mk @@ -0,0 +1,17 @@ +# thrift package + +THRIFT_VERSION = 0.11.0 +THRIFT_VERSION_FULL = $(THRIFT_VERSION)-4 + +LIBTHRIFT = libthrift-$(THRIFT_VERSION)_$(THRIFT_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(LIBTHRIFT)_SRC_PATH = $(SRC_PATH)/thrift +SONIC_MAKE_DEBS += $(LIBTHRIFT) + +LIBTHRIFT_DEV = libthrift-dev_$(THRIFT_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBTHRIFT),$(LIBTHRIFT_DEV))) + +PYTHON_THRIFT = python-thrift_$(THRIFT_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBTHRIFT),$(PYTHON_THRIFT))) + +THRIFT_COMPILER = thrift-compiler_$(THRIFT_VERSION_FULL)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(LIBTHRIFT),$(THRIFT_COMPILER))) diff --git a/rules/wpasupplicant.dep b/rules/wpasupplicant.dep new file mode 100644 index 000000000000..cdab026f0c65 --- /dev/null +++ b/rules/wpasupplicant.dep @@ -0,0 +1,16 @@ + +SPATH := $($(WPASUPPLICANT)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/wpasupplicant.mk rules/wpasupplicant.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +# Account files under the src/wpasupplicant/ except submodule directory. +DEP_FILES += $(shell git ls-files $(SPATH) | grep -Ev 'sonic-wpa-supplicant') + +# Account for source files under the sonic-wpa-supplicant submodule directory as well. +WPASUPPLICANT_SPATH := $(SPATH)/sonic-wpa-supplicant +SMDEP_FILES := $(addprefix $(WPASUPPLICANT_SPATH)/,$(shell cd $(WPASUPPLICANT_SPATH) && git ls-files)) + +$(WPASUPPLICANT)_CACHE_MODE := GIT_CONTENT_SHA +$(WPASUPPLICANT)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(WPASUPPLICANT)_DEP_FILES := $(DEP_FILES) +$(WPASUPPLICANT)_SMDEP_FILES := $(SMDEP_FILES) +$(WPASUPPLICANT)_SMDEP_PATHS := $(WPASUPPLICANT_SPATH) diff --git a/rules/wpasupplicant.mk b/rules/wpasupplicant.mk new file mode 100644 index 000000000000..2e6d2ea6b2f1 --- /dev/null +++ b/rules/wpasupplicant.mk @@ -0,0 +1,19 @@ +# wpa package + +WPASUPPLICANT_VERSION = 2.9.0-14 + +export WPASUPPLICANT_VERSION + +WPASUPPLICANT = wpasupplicant_$(WPASUPPLICANT_VERSION)_$(CONFIGURED_ARCH).deb +$(WPASUPPLICANT)_SRC_PATH = $(SRC_PATH)/wpasupplicant +$(WPASUPPLICANT)_DEPENDS += $(LIBSWSSCOMMON_DEV) $(LIBNL3_DEV) $(LIBNL_GENL3_DEV) $(LIBNL_ROUTE3_DEV) +$(WPASUPPLICANT)_RDEPENDS += $(LIBSWSSCOMMON) $(LIBNL3) $(LIBNL_GENL3) $(LIBNL_ROUTE3) +SONIC_MAKE_DEBS += $(WPASUPPLICANT) + +WPASUPPLICANT_DBG = wpasupplicant-dbgsym_$(WPASUPPLICANT_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(WPASUPPLICANT),$(WPASUPPLICANT_DBG))) + +# The .c, .cpp, .h & .hpp files under src/{$DBG_SRC_ARCHIVE list} +# are archived into debug one image to facilitate debugging. +# +DBG_SRC_ARCHIVE += wpasupplicant diff --git a/scripts/build_debian_base_system.sh b/scripts/build_debian_base_system.sh new file mode 100755 index 000000000000..a85b3b5bf0ee --- /dev/null +++ b/scripts/build_debian_base_system.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +CONFIGURED_ARCH=$1 +IMAGE_DISTRO=$2 +FILESYSTEM_ROOT=$3 +http_proxy=$4 + +TARGET=$TARGET_PATH +[ -z "$TARGET" ] && TARGET=target + +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh + +TARGET_BASEIMAGE_PATH=$TARGET/versions/host-base-image +mkdir -p $TARGET_BASEIMAGE_PATH + +generate_version_file() +{ + sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "dpkg-query -W -f '\${Package}==\${Version}\n'" > $TARGET_BASEIMAGE_PATH/versions-deb-${IMAGE_DISTRO}-${CONFIGURED_ARCH} +} + +if [ "$ENABLE_VERSION_CONTROL_DEB" != "y" ]; then + if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then + # qemu arm bin executable for cross-building + sudo mkdir -p $FILESYSTEM_ROOT/usr/bin + sudo cp /usr/bin/qemu*static $FILESYSTEM_ROOT/usr/bin || true + sudo http_proxy=$HTTP_PROXY SKIP_BUILD_HOOK=y debootstrap --variant=minbase --arch $CONFIGURED_ARCH $IMAGE_DISTRO $FILESYSTEM_ROOT http://deb.debian.org/debian + else + sudo http_proxy=$HTTP_PROXY SKIP_BUILD_HOOK=y debootstrap --variant=minbase --arch $CONFIGURED_ARCH $IMAGE_DISTRO $FILESYSTEM_ROOT http://debian-archive.trafficmanager.net/debian + fi + RET=$? + if [ $RET -ne 0 ]; then + exit $RET + fi + + generate_version_file + exit $RET +fi + +ARCH=$(dpkg --print-architecture) +DISTRO=$(grep CODENAME /etc/os-release | cut -d= -f2) +if [ "$ARCH" != "$CONFIGURED_ARCH" ] || [ "$DISTRO" != "$IMAGE_DISTRO" ]; then + "Not support to build different ARCH/DISTRO ${CONFIGURED_ARCH}:${$IMAGE_DISTRO} in ${ARCH}:${DISTRO}." + exit 1 +fi + +BASE_VERSIONS=files/build/versions/host-base-image/versions-deb-${IMAGE_DISTRO} +BASEIMAGE_TARBALLPATH=$TARGET/baseimage +BASEIMAGE_TARBALL=$(realpath -e $TARGET)/baseimage.tgz + +rm -rf $BASEIMAGE_TARBALLPATH $BASEIMAGE_TARBALL + +ARCHIEVES=$BASEIMAGE_TARBALLPATH/var/cache/apt/archives +APTLIST=$BASEIMAGE_TARBALLPATH/var/lib/apt/lists +TARGET_DEBOOTSTRAP=$BASEIMAGE_TARBALLPATH/debootstrap +APTDEBIAN="$APTLIST/deb.debian.org_debian_dists_buster_main_binary-${CONFIGURED_ARCH}_Packages" +DEBPATHS=$TARGET_DEBOOTSTRAP/debpaths +DEBOOTSTRAP_BASE=$TARGET_DEBOOTSTRAP/base +DEBOOTSTRAP_REQUIRED=$TARGET_DEBOOTSTRAP/required +[ -d $BASEIMAGE_TARBALLPATH ] && rm -rf $BASEIMAGE_TARBALLPATH +mkdir -p $ARCHIEVES +mkdir -p $APTLIST +mkdir -p $TARGET_DEBOOTSTRAP +PACKAGES=$(sed -E 's/=(=[^=]*)$/\1/' $BASE_VERSIONS) +URL_ARR=($(apt-get download --print-uris $PACKAGES | cut -d" " -f1 | tr -d "'")) +PACKAGE_ARR=($PACKAGES) +LENGTH=${#PACKAGE_ARR[@]} +for ((i=0;i> $DEBOOTSTRAP_REQUIRED + echo "$packagename /var/cache/apt/archives/$filename" >> $DEBPATHS +done +touch $APTDEBIAN +touch $DEBOOTSTRAP_BASE +(cd $BASEIMAGE_TARBALLPATH && tar -zcf $BASEIMAGE_TARBALL .) + +sudo debootstrap --verbose --variant=minbase --arch $CONFIGURED_ARCH --unpack-tarball=$BASEIMAGE_TARBALL $IMAGE_DISTRO $FILESYSTEM_ROOT +RET=$? +if [ $RET -ne 0 ]; then + exit $RET +fi + +generate_version_file diff --git a/scripts/build_kvm_image.sh b/scripts/build_kvm_image.sh new file mode 100755 index 000000000000..06bb87509185 --- /dev/null +++ b/scripts/build_kvm_image.sh @@ -0,0 +1,97 @@ +#!/bin/bash -ex + +# Copyright (C) 2014 Curt Brune +# +# SPDX-License-Identifier: GPL-2.0 + +MEM=3072 +DISK=$1 +ONIE_RECOVERY_ISO=$2 +INSTALLER=$3 +DISK_SIZE=$4 + +INSTALLER_DISK="./sonic-installer.img" + +# VM will listen on telnet port $KVM_PORT +KVM_PORT=9000 + +on_exit() +{ + rm -f $kvm_log +} + +on_error() +{ + netstat -antp + ps aux + echo "============= kvm_log ==============" + cat $kvm_log +} + +create_disk() +{ + echo "Creating SONiC kvm disk : $DISK of size $DISK_SIZE GB" + qemu-img create -f qcow2 $DISK ${DISK_SIZE}G +} + +prepare_installer_disk() +{ + fallocate -l 2048M $INSTALLER_DISK + + mkfs.vfat $INSTALLER_DISK + + tmpdir=$(mktemp -d) + + mount -o loop $INSTALLER_DISK $tmpdir + + cp $INSTALLER $tmpdir/onie-installer.bin + + umount $tmpdir +} + +apt-get install -y net-tools +create_disk +prepare_installer_disk + +echo "Prepare memory for KVM build: $vs_build_prepare_mem" +mount proc /proc -t proc || true +free -m +if [[ "$vs_build_prepare_mem" == "yes" ]]; then + # Force o.s. to drop cache and compact memory so that KVM can get 2G memory + bash -c 'echo 1 > /proc/sys/vm/drop_caches' + bash -c 'echo 1 > /proc/sys/vm/compact_memory' + free -m +fi + +kvm_log=$(mktemp) +trap on_exit EXIT +trap on_error ERR + +/usr/bin/kvm -m $MEM \ + -name "onie" \ + -boot "order=cd,once=d" -cdrom "$ONIE_RECOVERY_ISO" \ + -device e1000,netdev=onienet \ + -netdev user,id=onienet,hostfwd=:0.0.0.0:3041-:22 \ + -vnc 0.0.0.0:0 \ + -vga std \ + -drive file=$DISK,media=disk,if=virtio,index=0 \ + -drive file=$INSTALLER_DISK,if=virtio,index=1 \ + -serial telnet:127.0.0.1:$KVM_PORT,server > $kvm_log 2>&1 & + +kvm_pid=$! + +sleep 2.0 + +[ -d "/proc/$kvm_pid" ] || { + echo "ERROR: kvm died." + cat $kvm_log + exit 1 +} + +echo "to kill kvm: sudo kill $kvm_pid" + +./check_install.py -u $SONIC_USERNAME -P $PASSWD -p $KVM_PORT + +kill $kvm_pid + +exit 0 diff --git a/scripts/collect_build_version_files.sh b/scripts/collect_build_version_files.sh new file mode 100755 index 000000000000..b650e421996b --- /dev/null +++ b/scripts/collect_build_version_files.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +RET=$1 +BLDENV=$2 +TARGET_PATH=$3 + +TIMESTAMP=$(date +"%Y%m%d%H%M%S") +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh + +[ -z "$BLDENV" ] && BLDENV=$(grep VERSION_CODENAME /etc/os-release | cut -d= -f2) +[ -z "$BLDENV" ] && exit $RET + +[ -z "$TARGET_PATH" ] && TARGET_PATH=./target + +VERSION_BUILD_PATH=$TARGET_PATH/versions/build +VERSION_SLAVE_PATH=$VERSION_BUILD_PATH/build-sonic-slave-${BLDENV} +LOG_VERSION_PATH=$VERSION_BUILD_PATH/log-${TIMESTAMP} + +sudo chmod -R a+rw $BUILDINFO_PATH +collect_version_files $LOG_VERSION_PATH +([ -d $BUILD_VERSION_PATH ] && [ ! -z "$(ls $BUILD_VERSION_PATH/)" ]) && cp -rf $BUILD_VERSION_PATH/* $LOG_VERSION_PATH/ +mkdir -p $VERSION_SLAVE_PATH + +scripts/versions_manager.py merge -t $VERSION_SLAVE_PATH -b $LOG_VERSION_PATH -e $POST_VERSION_PATH + +rm -rf $BUILD_VERSION_PATH/* + +exit $RET diff --git a/scripts/collect_docker_version_files.sh b/scripts/collect_docker_version_files.sh new file mode 100755 index 000000000000..73f0a9b53198 --- /dev/null +++ b/scripts/collect_docker_version_files.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +DOCKER_IMAGE=$1 +TARGET_PATH=$2 + +[ -z "$TARGET_PATH" ] && TARGET_PATH=./target + +DOCKER_IMAGE_NAME=$(echo $DOCKER_IMAGE | cut -d: -f1) +DOCKER_CONTAINER=$DOCKER_IMAGE_NAME +TARGET_VERSIONS_PATH=$TARGET_PATH/versions/dockers/$DOCKER_IMAGE_NAME + +[ -d $TARGET_VERSIONS_PATH ] && rm -rf $TARGET_VERSIONS_PATH +mkdir -p $TARGET_VERSIONS_PATH + +export DOCKER_CLI_EXPERIMENTAL=enabled + +# Remove the old docker container if existing +if docker container inspect $DOCKER_IMAGE > /dev/null 2>&1; then + docker container rm $DOCKER_IMAGE > /dev/null +fi +docker create --name $DOCKER_CONTAINER --entrypoint /bin/bash $DOCKER_IMAGE +docker cp -L $DOCKER_CONTAINER:/etc/os-release $TARGET_VERSIONS_PATH/ +docker cp -L $DOCKER_CONTAINER:/usr/local/share/buildinfo/pre-versions $TARGET_VERSIONS_PATH/ +docker cp -L $DOCKER_CONTAINER:/usr/local/share/buildinfo/post-versions $TARGET_VERSIONS_PATH/ +docker container rm $DOCKER_CONTAINER diff --git a/scripts/collect_host_image_version_files.sh b/scripts/collect_host_image_version_files.sh new file mode 100755 index 000000000000..2cabc049d9c7 --- /dev/null +++ b/scripts/collect_host_image_version_files.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +TARGET=$1 +FILESYSTEM_ROOT=$2 +VERSIONS_PATH=$TARGET/versions/host-image + +[ -d $VERSIONS_PATH ] && sudo rm -rf $VERSIONS_PATH +mkdir -p $VERSIONS_PATH + +sudo LANG=C chroot $FILESYSTEM_ROOT post_run_buildinfo + +cp -r $FILESYSTEM_ROOT/usr/local/share/buildinfo/pre-versions $VERSIONS_PATH/ +cp -r $FILESYSTEM_ROOT/usr/local/share/buildinfo/post-versions $VERSIONS_PATH/ diff --git a/scripts/convert-pfx-cert-format.sh b/scripts/convert-pfx-cert-format.sh new file mode 100755 index 000000000000..4615dbdf85a9 --- /dev/null +++ b/scripts/convert-pfx-cert-format.sh @@ -0,0 +1,36 @@ +#!/bin/bash -ex + +usage() +{ + echo "Usage: $0 -p -k -c -a " + exit 1 +} + +while getopts "p:k:c:a:" opt; do + case $opt in + p) + PFX_FILE=$OPTARG + ;; + k) + SIGNING_KEY=$OPTARG + ;; + c) + SIGNING_CERT=$OPTARG + ;; + a) + CA_CERT=$OPTARG + ;; + *) + usage + ;; + esac +done + + +( [ -z $PFX_FILE ] || [ -z $SIGNING_KEY ] || [ -z $SIGNING_CERT ] || [ -z $CA_CERT ] ) && exit 1 + +openssl pkcs12 -in "${PFX_FILE}" -clcerts -nokeys -nodes -passin pass: -out ${SIGNING_CERT} +openssl pkcs12 -in "${PFX_FILE}" -nocerts -nodes -passin pass: -out ${SIGNING_KEY} + +# Export the last intermediate CA ceritficate +openssl pkcs12 -in "${PFX_FILE}" -cacerts -nokeys -nodes -passin pass: | sed -z -e "s/.*\(-----BEGIN CERTIFICATE\)/\1/" > ${CA_CERT} diff --git a/scripts/dbg_files.sh b/scripts/dbg_files.sh new file mode 100755 index 000000000000..6624fca83f34 --- /dev/null +++ b/scripts/dbg_files.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# Provide file paths to archive for debug image as relative to src subdir +# +if [ "$DEBUG_IMG" == "y" ] +then + for i in $DEBUG_SRC_ARCHIVE_DIRS + do + find src/$i/ -name "*.c" -o -name "*.cpp" -o -name "*.h" -o -name "*.hpp" -type f + done | tar -czf $DEBUG_SRC_ARCHIVE_FILE -T - +fi + diff --git a/scripts/generate_buildinfo_config.sh b/scripts/generate_buildinfo_config.sh new file mode 100755 index 000000000000..fe7657a6b6c9 --- /dev/null +++ b/scripts/generate_buildinfo_config.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +BUILDINFO_PATH=src/sonic-build-hooks + +BUILDINFO_CONFIG=$BUILDINFO_PATH/buildinfo/config/buildinfo.config + +mkdir -p $BUILDINFO_PATH/buildinfo/config + +echo "PACKAGE_URL_PREFIX=$PACKAGE_URL_PREFIX" > $BUILDINFO_CONFIG +echo "SONIC_VERSION_CONTROL_COMPONENTS=$SONIC_VERSION_CONTROL_COMPONENTS" >> $BUILDINFO_CONFIG diff --git a/scripts/prepare_debian_image_buildinfo.sh b/scripts/prepare_debian_image_buildinfo.sh new file mode 100755 index 000000000000..912e0de0b25f --- /dev/null +++ b/scripts/prepare_debian_image_buildinfo.sh @@ -0,0 +1,29 @@ +#!/bin/bash + + +ARCH=$1 +DISTRO=$2 +FILESYSTEM_ROOT=$3 + +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh +VERSION_DEB_PREFERENCE="01-versions-deb" +BUILDINFO_PATH=${FILESYSTEM_ROOT}/usr/local/share/buildinfo +BUILDINFO_VERSION_PATH=${FILESYSTEM_ROOT}/usr/local/share/buildinfo/versions +BUILDINFO_VERSION_DEB=${BUILDINFO_VERSION_PATH}/${VERSION_DEB_PREFERENCE} +OVERRIDE_VERSION_PATH=files/build/versions/host-image +DIFF_VERSIONS_PATH=$BUILDINFO_PATH/diff-versions + +mkdir -p $BUILDINFO_PATH + +# Copy the build info config +cp -rf src/sonic-build-hooks/buildinfo/* $BUILDINFO_PATH/ + +# Generate version lock files +scripts/versions_manager.py generate -t "$BUILDINFO_VERSION_PATH" -m "$OVERRIDE_VERSION_PATH" -d "$DISTRO" -a "$ARCH" + +if [ "$ENABLE_VERSION_CONTROL_DEB" == "y" ]; then + cp -f $BUILDINFO_VERSION_DEB ${FILESYSTEM_ROOT}/etc/apt/preferences.d/ +fi + +sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "dpkg -i /usr/local/share/buildinfo/sonic-build-hooks_1.0_all.deb" +sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "pre_run_buildinfo" diff --git a/scripts/prepare_docker_buildinfo.sh b/scripts/prepare_docker_buildinfo.sh new file mode 100755 index 000000000000..aa3aaaa4bed5 --- /dev/null +++ b/scripts/prepare_docker_buildinfo.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +IMAGENAME=$1 +DOCKERFILE=$2 +ARCH=$3 +DOCKERFILE_TARGE=$4 +DISTRO=$5 + +[ -z "$BUILD_SLAVE" ] && BUILD_SLAVE=n +[ -z "$DOCKERFILE_TARGE" ] && DOCKERFILE_TARGE=$DOCKERFILE +DOCKERFILE_PATH=$(dirname "$DOCKERFILE_TARGE") +BUILDINFO_PATH="${DOCKERFILE_PATH}/buildinfo" +BUILDINFO_VERSION_PATH="${BUILDINFO_PATH}/versions" + +[ -d $BUILDINFO_PATH ] && rm -rf $BUILDINFO_PATH +mkdir -p $BUILDINFO_VERSION_PATH + +# Get the debian distribution from the docker base image +if [ -z "$DISTRO" ]; then + DOCKER_BASE_IMAGE=$(grep "^FROM" $DOCKERFILE | head -n 1 | awk '{print $2}') + DISTRO=$(docker run --rm --entrypoint "" $DOCKER_BASE_IMAGE cat /etc/os-release | grep VERSION_CODENAME | cut -d= -f2) + [ -z "$DISTRO" ] && DISTRO=jessie +fi + +DOCKERFILE_PRE_SCRIPT='# Auto-Generated for buildinfo +COPY ["buildinfo", "/usr/local/share/buildinfo"] +RUN dpkg -i /usr/local/share/buildinfo/sonic-build-hooks_1.0_all.deb +RUN pre_run_buildinfo' + +# Add the auto-generate code if it is not added in the target Dockerfile +if [ ! -f $DOCKERFILE_TARGE ] || ! grep -q "Auto-Generated for buildinfo" $DOCKERFILE_TARGE; then + # Insert the docker build script before the RUN command + LINE_NUMBER=$(grep -Fn -m 1 'RUN' $DOCKERFILE | cut -d: -f1) + TEMP_FILE=$(mktemp) + awk -v text="${DOCKERFILE_PRE_SCRIPT}" -v linenumber=$LINE_NUMBER 'NR==linenumber{print text}1' $DOCKERFILE > $TEMP_FILE + + # Append the docker build script at the end of the docker file + echo -e "\nRUN post_run_buildinfo" >> $TEMP_FILE + + cat $TEMP_FILE > $DOCKERFILE_TARGE + rm -f $TEMP_FILE +fi + +# Copy the build info config +cp -rf src/sonic-build-hooks/buildinfo/* $BUILDINFO_PATH + +# Generate the version lock files +scripts/versions_manager.py generate -t "$BUILDINFO_VERSION_PATH" -n "$IMAGENAME" -d "$DISTRO" -a "$ARCH" + +touch $BUILDINFO_VERSION_PATH/versions-deb diff --git a/scripts/prepare_slave_container_buildinfo.sh b/scripts/prepare_slave_container_buildinfo.sh new file mode 100755 index 000000000000..be6fe078bdfb --- /dev/null +++ b/scripts/prepare_slave_container_buildinfo.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +SLAVE_DIR=$1 +ARCH=$2 +DISTRO=$3 + +# Install the latest debian package sonic-build-hooks in the slave container +sudo dpkg -i --force-overwrite $SLAVE_DIR/buildinfo/sonic-build-hooks_*.deb > /dev/null + +# Enable the build hooks +symlink_build_hooks + +# Build the slave running config +cp -rf $SLAVE_DIR/buildinfo/* /usr/local/share/buildinfo/ +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh + +# Build the slave version config +[ -d /usr/local/share/buildinfo/versions ] && rm -rf /usr/local/share/buildinfo/versions +scripts/versions_manager.py generate -t "/usr/local/share/buildinfo/versions" -n "build-${SLAVE_DIR}" -d "$DISTRO" -a "$ARCH" +touch ${BUILDINFO_PATH}/versions/versions-deb + +rm -f /etc/apt/preferences.d/01-versions-deb +([ "$ENABLE_VERSION_CONTROL_DEB" == "y" ] && [ -f $VERSION_DEB_PREFERENCE ]) && cp -f $VERSION_DEB_PREFERENCE /etc/apt/preferences.d/ +exit 0 diff --git a/scripts/process_log.sh b/scripts/process_log.sh new file mode 100755 index 000000000000..9977535ed812 --- /dev/null +++ b/scripts/process_log.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +add_timestamp="" + +while getopts ":t" opt; do + case $opt in + t) + add_timestamp="y" + ;; + esac +done + +while IFS= read -r line; do + if [ $add_timestamp ]; then + printf '[%s] ' "$(date +%T)" + fi + printf '%s\n' "$line" +done + + diff --git a/scripts/sign_image.sh b/scripts/sign_image.sh new file mode 100755 index 000000000000..f726ad130cb8 --- /dev/null +++ b/scripts/sign_image.sh @@ -0,0 +1,69 @@ +#!/bin/bash -ex + + +IMAGE="" +SIGNING_KEY="" +SIGNING_CERT="" +CA_CERT="" + +usage() +{ + echo "Usage: $0 -i [-k -c -a ]" + exit 1 +} + +generate_signing_key() +{ + TMP_CERT_PATH=$(mktemp -d) + SIGNING_KEY="${TMP_CERT_PATH}/signing.key" + SIGNING_CERT="${TMP_CERT_PATH}/signing.crt" + SIGNING_CSR="${TMP_CERT_PATH}/signing.csr" + CA_KEY="${TMP_CERT_PATH}/ca.key" + + # Generate the CA key and certificate + openssl genrsa -out $CA_KEY 4096 + openssl req -x509 -new -nodes -key $CA_KEY -sha256 -days 3650 -subj "/C=US/ST=Test/L=Test/O=Test/CN=Test" -out $CA_CERT + + # Generate the signing key, certificate request and certificate + openssl genrsa -out $SIGNING_KEY 4096 + openssl req -new -key $SIGNING_KEY -subj "/C=US/ST=Test/L=Test/O=Test/CN=Test" -out $SIGNING_CSR + openssl x509 -req -in $SIGNING_CSR -CA $CA_CERT -CAkey $CA_KEY -CAcreateserial -out $SIGNING_CERT -days 1825 -sha256 +} + +while getopts "i:k:c:a:t:" opt; do + case $opt in + i) + IMAGE=$OPTARG + ;; + k) + SIGNING_KEY=$OPTARG + ;; + c) + SIGNING_CERT=$OPTARG + ;; + a) + CA_CERT=$OPTARG + ;; + *) + usage + ;; + esac +done + +[ -z $CA_CERT ] && echo "Not to sign the image since the CA certificate not provided" 1>&2 && exit 1 + +# Generate the self signed cert if not provided by input +[ ! -f $CA_CERT ] && generate_signing_key + +# Verify the required files existing +[ ! -f $SIGNING_KEY ] && echo "$SIGNING_KEY not exist" && exit 1 +[ ! -f $SIGNING_CERT ] && echo "$SIGNING_CERT not exist" && exit 1 +[ ! -f $CA_CERT ] && echo "$CA_CERT not exist" && exit 1 + +# Prepare the image +swi-signature prepare $IMAGE + +# Sign the image +swi-signature sign $IMAGE $SIGNING_CERT $CA_CERT --key $SIGNING_KEY + +exit 0 diff --git a/scripts/versions_manager.py b/scripts/versions_manager.py new file mode 100755 index 000000000000..336568bfb4e0 --- /dev/null +++ b/scripts/versions_manager.py @@ -0,0 +1,668 @@ +#!/usr/bin/python3 + +import argparse +import glob +import os +import sys + +ALL_DIST = 'all' +ALL_ARCH = 'all' +DEFAULT_MODULE = 'default' +DEFAULT_VERSION_PATH = 'files/build/versions' +VERSION_PREFIX="versions-" +VERSION_DEB_PREFERENCE = '01-versions-deb' +DEFAULT_OVERWRITE_COMPONENTS=['deb', 'py2', 'py3'] +SLAVE_INDIVIDULE_VERSION = False + + +class Component: + ''' + The component consists of mutiple packages + + ctype -- Component Type, such as deb, py2, etc + dist -- Distribution, such as stretch, buster, etc + arch -- Architectrue, such as amd64, arm64, etc + + ''' + def __init__(self, versions, ctype, dist=ALL_DIST, arch=ALL_ARCH): + self.versions = versions + self.ctype = ctype + if not dist: + dist = ALL_DIST + if not arch: + arch = ALL_ARCH + self.dist = dist + self.arch = arch + + @classmethod + def get_versions(cls, version_file): + result = {} + if not os.path.exists(version_file): + return result + with open(version_file) as fp: + for line in fp.readlines(): + offset = line.rfind('==') + if offset > 0: + package = line[:offset].strip() + version = line[offset+2:].strip() + result[package] = version + return result + + def clone(self): + return Component(self.versions.copy(), self.ctype, self.dist, self.arch) + + def merge(self, versions, overwritten=True): + for package in versions: + if overwritten or package not in self.versions: + self.versions[package] = versions[package] + + def subtract(self, versions): + for package in versions: + if package in self.versions and self.versions[package] == versions[package]: + del self.versions[package] + + def dump(self, config=False, priority=999): + result = [] + for package in sorted(self.versions.keys(), key=str.casefold): + if config and self.ctype == 'deb': + lines = 'Package: {0}\nPin: version {1}\nPin-Priority: {2}\n\n'.format(package, self.versions[package], priority) + result.append(lines) + else: + result.append('{0}=={1}'.format(package, self.versions[package])) + return "\n".join(result) + + def dump_to_file(self, version_file, config=False, priority=999): + if len(self.versions) <= 0: + return + with open(version_file, 'w') as f: + f.write(self.dump(config, priority)) + + def dump_to_path(self, file_path, config=False, priority=999): + if len(self.versions) <= 0: + return + if not os.path.exists(file_path): + os.makedirs(file_path) + filename = self.get_filename() + if config and self.ctype == 'deb': + none_config_file_path = os.path.join(file_path, filename) + self.dump_to_file(none_config_file_path, False, priority) + filename = VERSION_DEB_PREFERENCE + file_path = os.path.join(file_path, filename) + self.dump_to_file(file_path, config, priority) + + # Check if the self component can be overwritten by the input component + def check_overwritable(self, component, for_all_dist=False, for_all_arch=False): + if self.ctype != component.ctype: + return False + if self.dist != component.dist and not (for_all_dist and self.dist == ALL_DIST): + return False + if self.arch != component.arch and not (for_all_arch and self.arch == ALL_ARCH): + return False + return True + + # Check if the self component can inherit the package versions from the input component + def check_inheritable(self, component): + if self.ctype != component.ctype: + return False + if self.dist != component.dist and component.dist != ALL_DIST: + return False + if self.arch != component.arch and component.arch != ALL_ARCH: + return False + return True + + ''' + Get the file name + + The file name format: versions-{ctype}-{dist}-{arch} + If {arch} is all, then the file name format: versions-{ctype}-{dist} + if {arch} is all and {dist} is all, then the file name format: versions-{ctype} + ''' + def get_filename(self): + filename = VERSION_PREFIX + self.ctype + dist = self.dist + if self.arch and self.arch != ALL_ARCH: + if not dist: + dist = ALL_DIST + return filename + '-' + dist + '-' + self.arch + if dist and self.dist != ALL_DIST: + filename = filename + '-' + dist + return filename + + def get_order_keys(self): + dist = self.dist + if not dist or dist == ALL_DIST: + dist = '' + arch = self.arch + if not arch or arch == ALL_ARCH: + arch = '' + return (self.ctype, dist, arch) + + def clean_info(self, clean_dist=True, clean_arch=True, force=False): + if clean_dist: + if force or self.ctype != 'deb': + self.dist = ALL_DIST + if clean_arch: + self.arch = ALL_ARCH + + +class VersionModule: + ''' + The version module represents a build target, such as docker image, host image, consists of multiple components. + + name -- The name of the image, such as sonic-slave-buster, docker-lldp, etc + ''' + def __init__(self, name=None, components=None): + self.name = name + self.components = components + + # Overwrite the docker/host image/base image versions + def overwrite(self, module, for_all_dist=False, for_all_arch=False): + # Overwrite from generic one to detail one + # For examples: versions-deb overwrtten by versions-deb-buster, and versions-deb-buster overwritten by versions-deb-buster-amd64 + components = sorted(module.components, key = lambda x : x.get_order_keys()) + for merge_component in components: + merged = False + for component in self.components: + if component.check_overwritable(merge_component, for_all_dist=for_all_dist, for_all_arch=for_all_arch): + component.merge(merge_component.versions, True) + merged = True + if not merged: + tmp_component = merge_component.clone() + tmp_component.clean_info(clean_dist=for_all_dist, clean_arch=for_all_arch) + self.components.append(tmp_component) + self.adjust() + + def get_config_module(self, default_module, dist, arch): + if self.is_individule_version(): + return self + module = default_module + if not self.is_aggregatable_module(self.name): + module = default_module.clone(exclude_ctypes=DEFAULT_OVERWRITE_COMPONENTS) + return self._get_config_module(module, dist, arch) + + def _get_config_module(self, default_module, dist, arch): + module = default_module.clone() + default_ctype_components = module._get_components_per_ctypes() + module.overwrite(self) + config_components = [] + ctype_components = module._get_components_per_ctypes() + for ctype in default_ctype_components: + if ctype not in ctype_components: + ctype_components[ctype] = [] + for components in ctype_components.values(): + if len(components) == 0: + continue + config_component = self._get_config_for_ctype(components, dist, arch) + config_components.append(config_component) + config_module = VersionModule(self.name, config_components) + return config_module + + def _get_config_for_ctype(self, components, dist, arch): + result = Component({}, components[0].ctype, dist, arch) + for component in sorted(components, key = lambda x : x.get_order_keys()): + if result.check_inheritable(component): + result.merge(component.versions, True) + return result + + def subtract(self, default_module): + module = self.clone() + result = [] + ctype_components = module._get_components_per_ctypes() + for ctype in ctype_components: + components = ctype_components[ctype] + components = sorted(components, key = lambda x : x.get_order_keys()) + for i in range(0, len(components)): + component = components[i] + base_module = VersionModule(self.name, components[0:i]) + config_module = base_module._get_config_module(default_module, component.dist, component.arch) + config_components = config_module._get_components_by_ctype(ctype) + if len(config_components) > 0: + config_component = config_components[0] + component.subtract(config_component.versions) + if len(component.versions): + result.append(component) + self.components = result + + def adjust(self): + result_components = [] + ctype_components = self._get_components_per_ctypes() + for components in ctype_components.values(): + result_components += self._adjust_components_for_ctype(components) + self.components = result_components + + def _get_components_by_ctype(self, ctype): + components = [] + for component in self.components: + if component.ctype == ctype: + components.append(component) + return components + + def _adjust_components_for_ctype(self, components): + components = sorted(components, key = lambda x : x.get_order_keys()) + result = [] + for i in range(0, len(components)): + component = components[i] + inheritable_component = Component({}, component.ctype) + for j in range(0, i): + base_component = components[j] + if component.check_inheritable(base_component): + inheritable_component.merge(base_component.versions, True) + component.subtract(inheritable_component.versions) + if len(component.versions) > 0: + result.append(component) + return result + + def _get_components_per_ctypes(self): + result = {} + for component in self.components: + components = result.get(component.ctype, []) + components.append(component) + result[component.ctype] = components + return result + + def load(self, image_path, filter_ctype=None, filter_dist=None, filter_arch=None): + version_file_pattern = os.path.join(image_path, VERSION_PREFIX) + '*' + file_paths = glob.glob(version_file_pattern) + components = [] + self.name = os.path.basename(image_path) + self.components = components + for file_path in file_paths: + filename = os.path.basename(file_path) + items = filename.split('-') + if len(items) < 2: + continue + ctype = items[1] + if filter_ctype and filter_ctype != ctype: + continue + dist = '' + arch = '' + if len(items) > 2: + dist = items[2] + if filter_dist and dist and filter_dist != dist: + continue + if len(items) > 3: + arch = items[3] + if filter_arch and arch and filter_arch != arch: + continue + versions = Component.get_versions(file_path) + component = Component(versions, ctype, dist, arch) + components.append(component) + + def load_from_target(self, image_path): + post_versions = os.path.join(image_path, 'post-versions') + if os.path.exists(post_versions): + self.load(post_versions) + self.name = os.path.basename(image_path) + pre_versions = os.path.join(image_path, 'pre-versions') + if os.path.exists(pre_versions): + pre_module = VersionModule() + pre_module.load(pre_versions) + self.subtract(pre_module) + else: + self.load(image_path) + + def dump(self, module_path, config=False, priority=999): + version_file_pattern = os.path.join(module_path, VERSION_PREFIX + '*') + for filename in glob.glob(version_file_pattern): + os.remove(filename) + for component in self.components: + component.dump_to_path(module_path, config, priority) + + def filter(self, ctypes=[]): + if 'all' in ctypes: + return self + components = [] + for component in self.components: + if component.ctype in ctypes: + components.append(component) + self.components = components + + def clean_info(self, clean_dist=True, clean_arch=True, force=False): + for component in self.components: + component.clean_info(clean_dist=clean_dist, clean_arch=clean_arch, force=force) + + def clone(self, ctypes=None, exclude_ctypes=None): + components = [] + for component in self.components: + if exclude_ctypes and component.ctype in exclude_ctypes: + continue + if ctypes and component.ctype not in ctypes: + continue + components.append(component.clone()) + return VersionModule(self.name, components) + + def is_slave_module(self): + return self.name.startswith('sonic-slave-') + + # Do not inherit the version from the default module + def is_individule_version(self): + return self.is_slave_module() and SLAVE_INDIVIDULE_VERSION + + @classmethod + def is_aggregatable_module(cls, module_name): + if module_name.startswith('sonic-slave-'): + return False + if module_name.startswith('build-sonic-slave-'): + return False + if module_name == DEFAULT_MODULE: + return False + if module_name == 'host-image' or module_name == 'host-base-image': + return False + return True + + @classmethod + def get_module_path_by_name(cls, source_path, module_name): + common_modules = ['default', 'host-image', 'host-base-image'] + if module_name in common_modules: + return os.path.join(source_path, 'files/build/versions', module_name) + if module_name.startswith('build-sonic-slave-'): + return os.path.join(source_path, 'files/build/versions/build', module_name) + return os.path.join(source_path, 'files/build/versions/dockers', module_name) + +class VersionBuild: + ''' + The VersionBuild consists of multiple version modules. + + ''' + def __init__(self, target_path="./target", source_path='.'): + self.target_path = target_path + self.source_path = source_path + self.modules = {} + + def load_from_target(self): + dockers_path = os.path.join(self.target_path, 'versions/dockers') + build_path = os.path.join(self.target_path, 'versions/build') + modules = {} + self.modules = modules + file_paths = glob.glob(dockers_path + '/*') + file_paths += glob.glob(build_path + '/build-*') + file_paths.append(os.path.join(self.target_path, 'versions/host-image')) + file_paths.append(os.path.join(self.target_path, 'versions/host-base-image')) + for file_path in file_paths: + if not os.path.isdir(file_path): + continue + module = VersionModule() + module.load_from_target(file_path) + modules[module.name] = module + self._merge_dgb_modules() + + def load_from_source(self): + # Load default versions and host image versions + versions_path = os.path.join(self.source_path, 'files/build/versions') + dockers_path = os.path.join(versions_path, "dockers") + build_path = os.path.join(versions_path, "build") + paths = [os.path.join(versions_path, 'default')] + paths += glob.glob(versions_path + '/host-*') + paths += glob.glob(dockers_path + '/*') + paths += glob.glob(build_path + '/*') + modules = {} + self.modules = modules + for image_path in paths: + module = VersionModule() + module.load(image_path) + modules[module.name] = module + + def overwrite(self, build, for_all_dist=False, for_all_arch=False): + for target_module in build.modules.values(): + module = self.modules.get(target_module.name, None) + tmp_module = target_module.clone() + tmp_module.clean_info(for_all_dist, for_all_arch) + if module: + module.overwrite(tmp_module, for_all_dist=for_all_dist, for_all_arch=for_all_arch) + else: + self.modules[target_module.name] = tmp_module + + def dump(self): + for module in self.modules.values(): + module_path = self.get_module_path(module) + module.dump(module_path) + + def subtract(self, default_module): + none_aggregatable_module = default_module.clone(exclude_ctypes=DEFAULT_OVERWRITE_COMPONENTS) + for module in self.modules.values(): + if module.name == DEFAULT_MODULE: + continue + if module.name == 'host-base-image': + continue + if module.is_individule_version(): + continue + tmp_module = default_module + if not module.is_aggregatable_module(module.name): + tmp_module = none_aggregatable_module + module.subtract(tmp_module) + + def freeze(self, rebuild=False, for_all_dist=False, for_all_arch=False, ctypes=['all']): + if rebuild: + self.load_from_target() + self.filter(ctypes=ctypes) + default_module = self.get_default_module() + self._clean_component_info() + self.subtract(default_module) + self.modules[DEFAULT_MODULE] = default_module + self.dump() + return + self.load_from_source() + default_module = self.modules.get(DEFAULT_MODULE, None) + target_build = VersionBuild(self.target_path, self.source_path) + target_build.load_from_target() + target_build.filter(ctypes=ctypes) + if not default_module: + raise Exception("The default versions does not exist") + for module in target_build.modules.values(): + if module.is_individule_version(): + continue + tmp_module = module.clone(exclude_ctypes=DEFAULT_OVERWRITE_COMPONENTS) + default_module.overwrite(tmp_module, for_all_dist=True, for_all_arch=True) + target_build.subtract(default_module) + self.overwrite(target_build, for_all_dist=for_all_dist, for_all_arch=for_all_arch) + self.dump() + + def filter(self, ctypes=[]): + for module in self.modules.values(): + module.filter(ctypes=ctypes) + + def get_default_module(self): + if DEFAULT_MODULE in self.modules: + return self.modules[DEFAULT_MODULE] + ctypes = self.get_component_types() + dists = self.get_dists() + components = [] + for ctype in ctypes: + if ctype == 'deb': + for dist in dists: + versions = self._get_versions(ctype, dist) + common_versions = self._get_common_versions(versions) + component = Component(common_versions, ctype, dist) + components.append(component) + else: + versions = self._get_versions(ctype) + common_versions = self._get_common_versions(versions) + component = Component(common_versions, ctype) + components.append(component) + return VersionModule(DEFAULT_MODULE, components) + + def get_aggregatable_modules(self): + modules = {} + for module_name in self.modules: + if not VersionModule.is_aggregatable_module(module_name): + continue + module = self.modules[module_name] + modules[module_name] = module + return modules + + def get_components(self): + components = [] + for module_name in self.modules: + module = self.modules[module_name] + for component in module.components: + components.append(component) + return components + + def get_component_types(self): + ctypes = [] + for module_name in self.modules: + module = self.modules[module_name] + for component in module.components: + if component.ctype not in ctypes: + ctypes.append(component.ctype) + return ctypes + + def get_dists(self): + dists = [] + components = self.get_components() + for component in components: + if component.dist not in dists: + dists.append(component.dist) + return dists + + def get_archs(self): + archs = [] + components = self.get_components() + for component in components: + if component.arch not in archs: + archs.append(component.arch) + return archs + + def get_module_path(self, module): + return self.get_module_path_by_name(module.name) + + def get_module_path_by_name(self, module_name): + return VersionModule.get_module_path_by_name(self.source_path, module_name) + + def _merge_dgb_modules(self): + dbg_modules = [] + for module_name in self.modules: + if not module_name.endswith('-dbg'): + continue + dbg_modules.append(module_name) + base_module_name = module_name[:-4] + if base_module_name not in self.modules: + raise Exception('The Module {0} not found'.format(base_module_name)) + base_module = self.modules[base_module_name] + dbg_module = self.modules[module_name] + base_module.overwrite(dbg_module) + for module_name in dbg_modules: + del self.modules[module_name] + + def _clean_component_info(self, clean_dist=True, clean_arch=True): + for module in self.modules.values(): + module.clean_info(clean_dist, clean_arch) + + def _get_versions(self, ctype, dist=None, arch=None): + versions = {} + modules = self.get_aggregatable_modules() + for module_name in self.modules: + if module_name not in modules: + temp_module = self.modules[module_name].clone(exclude_ctypes=DEFAULT_OVERWRITE_COMPONENTS) + modules[module_name] = temp_module + for module in modules.values(): + for component in module.components: + if ctype != component.ctype: + continue + if dist and dist != component.dist: + continue + if arch and arch != component.arch: + continue + for package in component.versions: + version = component.versions[package] + package_versions = versions.get(package, []) + if version not in package_versions: + package_versions.append(version) + versions[package] = package_versions + return versions + + def _get_common_versions(self, versions): + common_versions = {} + for package in versions: + package_versions = versions[package] + if len(package_versions) == 1: + common_versions[package] = package_versions[0] + return common_versions + + +class VersionManagerCommands: + def __init__(self): + usage = 'version_manager.py []\n\n' + usage = usage + 'The most commonly used commands are:\n' + usage = usage + ' freeze Freeze the version files\n' + usage = usage + ' generate Generate the version files\n' + usage = usage + ' merge Merge the version files' + parser = argparse.ArgumentParser(description='Version manager', usage=usage) + parser.add_argument('command', help='Subcommand to run') + args = parser.parse_args(sys.argv[1:2]) + if not hasattr(self, args.command): + print('Unrecognized command: {0}'.format(args.command)) + parser.print_help() + exit(1) + getattr(self, args.command)() + + def freeze(self): + parser = argparse.ArgumentParser(description = 'Freeze the version files') + parser.add_argument('-t', '--target_path', default='./target', help='target path') + parser.add_argument('-s', '--source_path', default='.', help='source path') + + # store_true which implies default=False + parser.add_argument('-r', '--rebuild', action='store_true', help='rebuild all versions') + parser.add_argument('-d', '--for_all_dist', action='store_true', help='apply the versions for all distributions') + parser.add_argument('-a', '--for_all_arch', action='store_true', help='apply the versions for all architectures') + parser.add_argument('-c', '--ctypes', default='all', help='component types to freeze') + args = parser.parse_args(sys.argv[2:]) + ctypes = args.ctypes.split(',') + if len(ctypes) == 0: + ctypes = ['all'] + build = VersionBuild(target_path=args.target_path, source_path=args.source_path) + build.freeze(rebuild=args.rebuild, for_all_dist=args.for_all_dist, for_all_arch=args.for_all_arch, ctypes=ctypes) + + def merge(self): + parser = argparse.ArgumentParser(description = 'Merge the version files') + parser.add_argument('-t', '--target_path', required=True, help='target path to save the merged version files') + parser.add_argument('-m', '--module_path', default=None, help='merge path, use the target path if not specified') + parser.add_argument('-b', '--base_path', required=True, help='base path, merge to the module path') + parser.add_argument('-e', '--exclude_module_path', default=None, help='exclude module path') + args = parser.parse_args(sys.argv[2:]) + module_path = args.module_path + if not module_path: + module_path = args.target_path + if not os.path.exists(module_path): + print('The module path {0} does not exist'.format(module_path)) + if not os.path.exists(args.target_path): + os.makedirs(args.target_path) + module = VersionModule() + module.load(module_path) + base_module = VersionModule() + base_module.load(args.base_path) + module.overwrite(base_module) + if args.exclude_module_path: + exclude_module = VersionModule() + exclude_module.load(args.exclude_module_path) + module.subtract(exclude_module) + module.dump(args.target_path) + + def generate(self): + parser = argparse.ArgumentParser(description = 'Generate the version files') + parser.add_argument('-t', '--target_path', required=True, help='target path to generate the version lock files') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-n', '--module_name', help="module name, such as docker-lldp, sonic-slave-buster, etc") + group.add_argument('-m', '--module_path', help="module apth, such as files/docker/versions/dockers/docker-lldp, files/docker/versions/dockers/sonic-slave-buster, etc") + parser.add_argument('-s', '--source_path', default='.', help='source path') + parser.add_argument('-d', '--distribution', required=True, help="distribution") + parser.add_argument('-a', '--architecture', required=True, help="architecture") + parser.add_argument('-p', '--priority', default=999, help="priority of the debian apt preference") + + args = parser.parse_args(sys.argv[2:]) + module_path = args.module_path + if not module_path: + module_path = VersionModule.get_module_path_by_name(args.source_path, args.module_name) + if not os.path.exists(args.target_path): + os.makedirs(args.target_path) + module = VersionModule() + module.load(module_path, filter_dist=args.distribution, filter_arch=args.architecture) + default_module_path = VersionModule.get_module_path_by_name(args.source_path, DEFAULT_MODULE) + default_module = VersionModule() + default_module.load(default_module_path, filter_dist=args.distribution, filter_arch=args.architecture) + config = module.get_config_module(default_module, args.distribution, args.architecture) + config.clean_info(force=True) + config.dump(args.target_path, config=True, priority=args.priority) + +if __name__ == "__main__": + VersionManagerCommands() diff --git a/scripts/wait_for_docker.sh b/scripts/wait_for_docker.sh new file mode 100755 index 000000000000..744646732826 --- /dev/null +++ b/scripts/wait_for_docker.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +total_time=$1 +cnt=0 +while [ $cnt -le $total_time ]; do + docker info 1>/dev/null + rv=$? + if [ $rv -eq 0 ]; then + exit 0 + fi + sleep 1 + cnt=$((cnt+1)) +done + +exit 1 diff --git a/slave.mk b/slave.mk new file mode 100644 index 000000000000..7bde5d23923d --- /dev/null +++ b/slave.mk @@ -0,0 +1,1107 @@ +############################################################################### +## Presettings +############################################################################### + +# Select bash for commands +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e +USER = $(shell id -un) +UID = $(shell id -u) +GUID = $(shell id -g) + +ifeq ($(SONIC_IMAGE_VERSION),) + override SONIC_IMAGE_VERSION = $(shell export BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) && export BUILD_NUMBER=$(BUILD_NUMBER) && . functions.sh && sonic_get_version) +endif + +.SECONDEXPANSION: + +NULL := +SPACE := $(NULL) $(NULL) + +############################################################################### +## General definitions +############################################################################### + +SRC_PATH = src +RULES_PATH = rules +TARGET_PATH = target +DOCKERS_PATH = dockers +BLDENV = $(shell lsb_release -cs) +DEBS_PATH = $(TARGET_PATH)/debs/$(BLDENV) +FILES_PATH = $(TARGET_PATH)/files/$(BLDENV) +PYTHON_DEBS_PATH = $(TARGET_PATH)/python-debs +PYTHON_WHEELS_PATH = $(TARGET_PATH)/python-wheels +PROJECT_ROOT = $(shell pwd) +JESSIE_DEBS_PATH = $(TARGET_PATH)/debs/jessie +JESSIE_FILES_PATH = $(TARGET_PATH)/files/jessie +STRETCH_DEBS_PATH = $(TARGET_PATH)/debs/stretch +STRETCH_FILES_PATH = $(TARGET_PATH)/files/stretch +BUSTER_DEBS_PATH = $(TARGET_PATH)/debs/buster +BUSTER_FILES_PATH = $(TARGET_PATH)/files/buster +DBG_IMAGE_MARK = dbg +DBG_SRC_ARCHIVE_FILE = $(TARGET_PATH)/sonic_src.tar.gz +DPKG_ADMINDIR_PATH = /sonic/dpkg + +CONFIGURED_PLATFORM := $(shell [ -f .platform ] && cat .platform || echo generic) +PLATFORM_PATH = platform/$(CONFIGURED_PLATFORM) +CONFIGURED_ARCH := $(shell [ -f .arch ] && cat .arch || echo amd64) +ifeq ($(PLATFORM_ARCH),) + override PLATFORM_ARCH = $(CONFIGURED_ARCH) +endif +IMAGE_DISTRO := buster +IMAGE_DISTRO_DEBS_PATH = $(TARGET_PATH)/debs/$(IMAGE_DISTRO) +IMAGE_DISTRO_FILES_PATH = $(TARGET_PATH)/files/$(IMAGE_DISTRO) + +export BUILD_NUMBER +export BUILD_TIMESTAMP +export SONIC_IMAGE_VERSION +export CONFIGURED_PLATFORM +export CONFIGURED_ARCH +export PYTHON_WHEELS_PATH +export IMAGE_DISTRO +export IMAGE_DISTRO_DEBS_PATH + +############################################################################### +## Utility rules +## Define configuration, help etc. +############################################################################### + +.platform : +ifneq ($(CONFIGURED_PLATFORM),generic) + @echo Build system is not configured, please run make configure + @exit 1 +endif + +configure : + @mkdir -p $(DEBS_PATH) + @mkdir -p $(JESSIE_DEBS_PATH) + @mkdir -p $(STRETCH_DEBS_PATH) + @mkdir -p $(BUSTER_DEBS_PATH) + @mkdir -p $(FILES_PATH) + @mkdir -p $(JESSIE_FILES_PATH) + @mkdir -p $(STRETCH_FILES_PATH) + @mkdir -p $(BUSTER_FILES_PATH) + @mkdir -p $(PYTHON_DEBS_PATH) + @mkdir -p $(PYTHON_WHEELS_PATH) + @mkdir -p $(DPKG_ADMINDIR_PATH) + @echo $(PLATFORM) > .platform + @echo $(PLATFORM_ARCH) > .arch + +distclean : .platform clean + @rm -f .platform + @rm -f .arch + +list : + @$(foreach target,$(SONIC_TARGET_LIST),echo $(target);) + +############################################################################### +## Include other rules +############################################################################### + +include $(RULES_PATH)/config +-include $(RULES_PATH)/config.user + + +############################################################################### +## Version control related exports +############################################################################### +export PACKAGE_URL_PREFIX +export TRUSTED_GPG_URLS +export SONIC_VERSION_CONTROL_COMPONENTS + +ifeq ($(SONIC_ENABLE_PFCWD_ON_START),y) +ENABLE_PFCWD_ON_START = y +endif + +ifeq ($(SONIC_INCLUDE_SYSTEM_TELEMETRY),y) +INCLUDE_SYSTEM_TELEMETRY = y +endif + +ifeq ($(SONIC_INCLUDE_RESTAPI),y) +INCLUDE_RESTAPI = y +endif + +ifeq ($(SONIC_ENABLE_SYNCD_RPC),y) +ENABLE_SYNCD_RPC = y +endif + +ifeq ($(SONIC_INSTALL_DEBUG_TOOLS),y) +INSTALL_DEBUG_TOOLS = y +endif + +ifeq ($(SONIC_INCLUDE_SFLOW),y) +INCLUDE_SFLOW = y +endif + +ifeq ($(SONIC_INCLUDE_NAT),y) +INCLUDE_NAT = y +endif + +ifeq ($(SONIC_INCLUDE_MACSEC),y) +INCLUDE_MACSEC = y +endif + +include $(RULES_PATH)/functions + +ifeq ($(SONIC_USE_PDDF_FRAMEWORK),y) +PDDF_SUPPORT = y +else +PDDF_SUPPORT = n +endif +export PDDF_SUPPORT + +include $(RULES_PATH)/*.mk +ifneq ($(CONFIGURED_PLATFORM), undefined) +ifeq ($(PDDF_SUPPORT), y) +PDDF_DIR = pddf +PLATFORM_PDDF_PATH = platform/$(PDDF_DIR) +include $(PLATFORM_PDDF_PATH)/rules.mk +endif +include $(PLATFORM_PATH)/rules.mk +endif + +ifeq ($(USERNAME),) +override USERNAME := $(DEFAULT_USERNAME) +else +$(warning USERNAME given on command line: could be visible to other users) +endif + +ifeq ($(PASSWORD),) +override PASSWORD := $(DEFAULT_PASSWORD) +else +$(warning PASSWORD given on command line: could be visible to other users) +endif + +ifeq ($(SONIC_DEBUGGING_ON),y) +DEB_BUILD_OPTIONS_GENERIC := nostrip +endif + +ifeq ($(SONIC_PROFILING_ON),y) +DEB_BUILD_OPTIONS_GENERIC := nostrip noopt +endif + +ifeq ($(SONIC_BUILD_JOBS),) +override SONIC_BUILD_JOBS := $(SONIC_CONFIG_BUILD_JOBS) +endif + +ifeq ($(VS_PREPARE_MEM),) +override VS_PREPARE_MEM := $(DEFAULT_VS_PREPARE_MEM) +endif + +ifeq ($(KERNEL_PROCURE_METHOD),) +override KERNEL_PROCURE_METHOD := $(DEFAULT_KERNEL_PROCURE_METHOD) +endif + +ifeq ($(BUILD_LOG_TIMESTAMP),) +override BUILD_LOG_TIMESTAMP := $(DEFAULT_BUILD_LOG_TIMESTAMP) +endif + +MAKEFLAGS += -j $(SONIC_BUILD_JOBS) +export SONIC_CONFIG_MAKE_JOBS + +############################################################################### +## Routing stack related exports +############################################################################### + +export SONIC_ROUTING_STACK +export FRR_USER_UID +export FRR_USER_GID + +############################################################################### +## Dumping key config attributes associated to current building exercise +############################################################################### + +ifndef SONIC_BUILD_QUIETER +$(info SONiC Build System) +$(info ) +$(info Build Configuration) +$(info "CONFIGURED_PLATFORM" : "$(if $(PLATFORM),$(PLATFORM),$(CONFIGURED_PLATFORM))") +$(info "CONFIGURED_ARCH" : "$(if $(PLATFORM_ARCH),$(PLATFORM_ARCH),$(CONFIGURED_ARCH))") +$(info "SONIC_CONFIG_PRINT_DEPENDENCIES" : "$(SONIC_CONFIG_PRINT_DEPENDENCIES)") +$(info "SONIC_BUILD_JOBS" : "$(SONIC_BUILD_JOBS)") +$(info "SONIC_CONFIG_MAKE_JOBS" : "$(SONIC_CONFIG_MAKE_JOBS)") +$(info "SONIC_USE_DOCKER_BUILDKIT" : "$(SONIC_USE_DOCKER_BUILDKIT)") +$(info "USERNAME" : "$(USERNAME)") +$(info "PASSWORD" : "$(PASSWORD)") +$(info "ENABLE_DHCP_GRAPH_SERVICE" : "$(ENABLE_DHCP_GRAPH_SERVICE)") +$(info "SHUTDOWN_BGP_ON_START" : "$(SHUTDOWN_BGP_ON_START)") +$(info "ENABLE_PFCWD_ON_START" : "$(ENABLE_PFCWD_ON_START)") +$(info "SONIC_BUFFER_MODEL" : "$(SONIC_BUFFER_MODEL)") +$(info "INSTALL_DEBUG_TOOLS" : "$(INSTALL_DEBUG_TOOLS)") +$(info "ROUTING_STACK" : "$(SONIC_ROUTING_STACK)") +ifeq ($(SONIC_ROUTING_STACK),frr) +$(info "FRR_USER_UID" : "$(FRR_USER_UID)") +$(info "FRR_USER_GID" : "$(FRR_USER_GID)") +endif +$(info "ENABLE_SYNCD_RPC" : "$(ENABLE_SYNCD_RPC)") +$(info "ENABLE_ORGANIZATION_EXTENSIONS" : "$(ENABLE_ORGANIZATION_EXTENSIONS)") +$(info "HTTP_PROXY" : "$(HTTP_PROXY)") +$(info "HTTPS_PROXY" : "$(HTTPS_PROXY)") +$(info "ENABLE_ZTP" : "$(ENABLE_ZTP)") +$(info "SONIC_DEBUGGING_ON" : "$(SONIC_DEBUGGING_ON)") +$(info "SONIC_PROFILING_ON" : "$(SONIC_PROFILING_ON)") +$(info "KERNEL_PROCURE_METHOD" : "$(KERNEL_PROCURE_METHOD)") +$(info "BUILD_TIMESTAMP" : "$(BUILD_TIMESTAMP)") +$(info "BUILD_LOG_TIMESTAMP" : "$(BUILD_LOG_TIMESTAMP)") +$(info "SONIC_IMAGE_VERSION" : "$(SONIC_IMAGE_VERSION)") +$(info "BLDENV" : "$(BLDENV)") +$(info "VS_PREPARE_MEM" : "$(VS_PREPARE_MEM)") +$(info "INCLUDE_MGMT_FRAMEWORK" : "$(INCLUDE_MGMT_FRAMEWORK)") +$(info "INCLUDE_ICCPD" : "$(INCLUDE_ICCPD)") +$(info "INCLUDE_SYSTEM_TELEMETRY" : "$(INCLUDE_SYSTEM_TELEMETRY)") +$(info "ENABLE_HOST_SERVICE_ON_START" : "$(ENABLE_HOST_SERVICE_ON_START)") +$(info "INCLUDE_RESTAPI" : "$(INCLUDE_RESTAPI)") +$(info "INCLUDE_SFLOW" : "$(INCLUDE_SFLOW)") +$(info "INCLUDE_NAT" : "$(INCLUDE_NAT)") +$(info "INCLUDE_KUBERNETES" : "$(INCLUDE_KUBERNETES)") +$(info "INCLUDE_MACSEC" : "$(INCLUDE_MACSEC)") +$(info "TELEMETRY_WRITABLE" : "$(TELEMETRY_WRITABLE)") +$(info "PDDF_SUPPORT" : "$(PDDF_SUPPORT)") +$(info ) +else +$(info SONiC Build System for $(CONFIGURED_PLATFORM):$(CONFIGURED_ARCH)) +endif + +# Overwrite the buildinfo in slave container +$(shell sudo scripts/prepare_slave_container_buildinfo.sh $(SLAVE_DIR) $(CONFIGURED_ARCH) $(BLDENV)) + +include Makefile.cache + +ifeq ($(SONIC_USE_DOCKER_BUILDKIT),y) +$(warning "Using SONIC_USE_DOCKER_BUILDKIT will produce larger installable SONiC image because of a docker bug (more details: https://github.com/moby/moby/issues/38903)") +export DOCKER_BUILDKIT=1 +endif + + +############################################################################### +## Generic rules section +## All rules must go after includes for propper targets expansion +############################################################################### + +export kernel_procure_method=$(KERNEL_PROCURE_METHOD) +export vs_build_prepare_mem=$(VS_PREPARE_MEM) + +############################################################################### +## Local targets +############################################################################### + +# Copy debian packages from local directory +# Add new package for copy: +# SOME_NEW_DEB = some_new_deb.deb +# $(SOME_NEW_DEB)_PATH = path/to/some_new_deb.deb +# SONIC_COPY_DEBS += $(SOME_NEW_DEB) +$(addprefix $(DEBS_PATH)/, $(SONIC_COPY_DEBS)) : $(DEBS_PATH)/% : .platform + $(HEADER) + $(foreach deb,$* $($*_DERIVED_DEBS), \ + { cp $($(deb)_PATH)/$(deb) $(DEBS_PATH)/ $(LOG) || exit 1 ; } ; ) + $(FOOTER) + + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_COPY_DEBS)) + +# Copy regular files from local directory +# Add new package for copy: +# SOME_NEW_FILE = some_new_file +# $(SOME_NEW_FILE)_PATH = path/to/some_new_file +# SONIC_COPY_FILES += $(SOME_NEW_FILE) +$(addprefix $(FILES_PATH)/, $(SONIC_COPY_FILES)) : $(FILES_PATH)/% : .platform + $(HEADER) + cp $($*_PATH)/$* $(FILES_PATH)/ $(LOG) || exit 1 + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(FILES_PATH)/, $(SONIC_COPY_FILES)) + +############################################################################### +## Online targets +############################################################################### + +# Download debian packages from online location +# Add new package for download: +# SOME_NEW_DEB = some_new_deb.deb +# $(SOME_NEW_DEB)_URL = https://url/to/this/deb.deb +# SONIC_ONLINE_DEBS += $(SOME_NEW_DEB) +$(addprefix $(DEBS_PATH)/, $(SONIC_ONLINE_DEBS)) : $(DEBS_PATH)/% : .platform \ + $(call dpkg_depend,$(DEBS_PATH)/%.dep) + + $(HEADER) + # Load the target deb from DPKG cache + $(call LOAD_CACHE,$*,$@) + + # Skip building the target if it is already loaded from cache + if [ -z '$($*_CACHE_LOADED)' ] ; then + + $(foreach deb,$* $($*_DERIVED_DEBS), \ + { curl -L -f -o $(DEBS_PATH)/$(deb) $($(deb)_URL) $(LOG) || { exit 1 ; } } ; ) + + # Save the target deb into DPKG cache + $(call SAVE_CACHE,$*,$@) + fi + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_ONLINE_DEBS)) + +# Download regular files from online location +# Files are stored in deb packages directory for convenience +# Add new file for download: +# SOME_NEW_FILE = some_new_file +# $(SOME_NEW_FILE)_URL = https://url/to/this/file +# SONIC_ONLINE_FILES += $(SOME_NEW_FILE) +$(addprefix $(FILES_PATH)/, $(SONIC_ONLINE_FILES)) : $(FILES_PATH)/% : .platform + $(HEADER) + curl -L -f -o $@ $($*_URL) $(LOG) + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(FILES_PATH)/, $(SONIC_ONLINE_FILES)) + +############################################################################### +## Build targets +############################################################################### + +# Build project using build.sh script +# They are essentially a one-time build projects that get sources from some URL +# and compile them +# Add new file for build: +# SOME_NEW_FILE = some_new_deb.deb +# $(SOME_NEW_FILE)_SRC_PATH = $(SRC_PATH)/project_name +# $(SOME_NEW_FILE)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... +# SONIC_MAKE_FILES += $(SOME_NEW_FILE) +$(addprefix $(FILES_PATH)/, $(SONIC_MAKE_FILES)) : $(FILES_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) \ + $$(addprefix $(DEBS_PATH)/,$$($$*_AFTER)) \ + $(call dpkg_depend,$(FILES_PATH)/%.dep) + $(HEADER) + + # Load the target deb from DPKG cache + $(call LOAD_CACHE,$*,$@) + + # Skip building the target if it is already loaded from cache + if [ -z '$($*_CACHE_LOADED)' ] ; then + # Remove target to force rebuild + rm -f $(addprefix $(FILES_PATH)/, $*) + # Apply series of patches if exist + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; popd; fi + # Build project and take package + make DEST=$(shell pwd)/$(FILES_PATH) -C $($*_SRC_PATH) $(shell pwd)/$(FILES_PATH)/$* $(LOG) + # Clean up + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; [ -d .pc ] && rm -rf .pc; popd; fi + + # Save the target deb into DPKG cache + $(call SAVE_CACHE,$*,$@) + + fi + + # Uninstall unneeded build dependency + $(call UNINSTALL_DEBS,$($*_UNINSTALLS)) + + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(FILES_PATH)/, $(SONIC_MAKE_FILES)) + +############################################################################### +## Debian package related targets +############################################################################### + +# Build project using build.sh script +# They are essentially a one-time build projects that get sources from some URL +# and compile them +# Add new package for build: +# SOME_NEW_DEB = some_new_deb.deb +# $(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name +# $(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... +# SONIC_MAKE_DEBS += $(SOME_NEW_DEB) +$(addprefix $(DEBS_PATH)/, $(SONIC_MAKE_DEBS)) : $(DEBS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) \ + $$(addprefix $(DEBS_PATH)/,$$($$*_AFTER)) \ + $(call dpkg_depend,$(DEBS_PATH)/%.dep) + $(HEADER) + + # Load the target deb from DPKG cache + $(call LOAD_CACHE,$*,$@) + + # Skip building the target if it is already loaded from cache + if [ -z '$($*_CACHE_LOADED)' ] ; then + + # Remove target to force rebuild + rm -f $(addprefix $(DEBS_PATH)/, $* $($*_DERIVED_DEBS) $($*_EXTRA_DEBS)) + # Apply series of patches if exist + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; popd; fi + # Build project and take package + $(SETUP_OVERLAYFS_FOR_DPKG_ADMINDIR) + DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC}" make DEST=$(shell pwd)/$(DEBS_PATH) -C $($*_SRC_PATH) $(shell pwd)/$(DEBS_PATH)/$* $(LOG) + # Clean up + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; [ -d .pc ] && rm -rf .pc; popd; fi + + # Save the target deb into DPKG cache + $(call SAVE_CACHE,$*,$@) + + fi + + # Uninstall unneeded build dependency + $(call UNINSTALL_DEBS,$($*_UNINSTALLS)) + + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_MAKE_DEBS)) + +# Build project with dpkg-buildpackage +# Add new package for build: +# SOME_NEW_DEB = some_new_deb.deb +# $(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name +# $(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... +# SONIC_DPKG_DEBS += $(SOME_NEW_DEB) +$(addprefix $(DEBS_PATH)/, $(SONIC_DPKG_DEBS)) : $(DEBS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) \ + $$(addprefix $(DEBS_PATH)/,$$($$*_AFTER)) \ + $(call dpkg_depend,$(DEBS_PATH)/%.dep ) + $(HEADER) + + # Load the target deb from DPKG cache + $(call LOAD_CACHE,$*,$@) + + # Skip building the target if it is already loaded from cache + if [ -z '$($*_CACHE_LOADED)' ] ; then + + # Remove old build logs if they exist + rm -f $($*_SRC_PATH)/debian/*.debhelper.log + # Apply series of patches if exist + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; popd; fi + # Build project + pushd $($*_SRC_PATH) $(LOG_SIMPLE) + if [ -f ./autogen.sh ]; then ./autogen.sh $(LOG); fi + $(SETUP_OVERLAYFS_FOR_DPKG_ADMINDIR) + $(if $($*_DPKG_TARGET), + ${$*_BUILD_ENV} DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --as-root -T$($*_DPKG_TARGET) --admindir $$mergedir $(LOG), + ${$*_BUILD_ENV} DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $$mergedir $(LOG) + ) + popd $(LOG_SIMPLE) + # Clean up + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; [ -d .pc ] && rm -rf .pc; popd; fi + # Take built package(s) + mv -f $(addprefix $($*_SRC_PATH)/../, $* $($*_DERIVED_DEBS) $($*_EXTRA_DEBS)) $(DEBS_PATH) $(LOG) + + # Save the target deb into DPKG cache + $(call SAVE_CACHE,$*,$@) + fi + + # Uninstall unneeded build dependency + $(call UNINSTALL_DEBS,$($*_UNINSTALLS)) + + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_DPKG_DEBS)) + +# Rules for derived debian packages (dev, dbg, etc.) +# All noise takes place in main deb recipe, so we are just telling that +# we depend on it and move our deb to other targets +# Add new dev package: +# $(eval $(call add_derived_package,$(ORIGINAL_DEB),derived_deb_file.deb)) +$(addprefix $(DEBS_PATH)/, $(SONIC_DERIVED_DEBS)) : $(DEBS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) + $(HEADER) + # All noise takes place in main deb recipe, so we are just telling that + # we depend on it + # Put newer timestamp + [ -f $@ ] && touch $@ + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_DERIVED_DEBS)) + +# Rules for extra debian packages +# All noise takes place in main deb recipe, so we are just telling that +# we need to build the main deb and move our deb to other targets +# Add new dev package: +# $(eval $(call add_extra_package,$(ORIGINAL_DEB),extra_deb_file.deb)) +$(addprefix $(DEBS_PATH)/, $(SONIC_EXTRA_DEBS)) : $(DEBS_PATH)/% : .platform $$(addprefix $(DEBS_PATH)/,$$($$*_MAIN_DEB)) + $(HEADER) + # All noise takes place in main deb recipe, so we are just telling that + # we depend on it + # Put newer timestamp + [ -f $@ ] && touch $@ + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(DEBS_PATH)/, $(SONIC_EXTRA_DEBS)) + +# Targets for installing debian packages prior to build one that depends on them +SONIC_INSTALL_DEBS = $(addsuffix -install,$(addprefix $(DEBS_PATH)/, \ + $(SONIC_ONLINE_DEBS) \ + $(SONIC_COPY_DEBS) \ + $(SONIC_MAKE_DEBS) \ + $(SONIC_DPKG_DEBS) \ + $(SONIC_PYTHON_STDEB_DEBS) \ + $(SONIC_DERIVED_DEBS) \ + $(SONIC_EXTRA_DEBS))) +$(SONIC_INSTALL_DEBS) : $(DEBS_PATH)/%-install : .platform $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEPENDS))) $(DEBS_PATH)/$$* + $(HEADER) + [ -f $(DEBS_PATH)/$* ] || { echo $(DEBS_PATH)/$* does not exist $(LOG) && false $(LOG) } + while true; do + # wait for conflicted packages to be uninstalled + $(foreach deb, $($*_CONFLICT_DEBS), \ + { while dpkg -s $(firstword $(subst _, ,$(basename $(deb)))) | grep "^Version: $(word 2, $(subst _, ,$(basename $(deb))))" &> /dev/null; do echo "waiting for $(deb) to be uninstalled" $(LOG); sleep 1; done } ) + # put a lock here because dpkg does not allow installing packages in parallel + if mkdir $(DEBS_PATH)/dpkg_lock &> /dev/null; then + { sudo DEBIAN_FRONTEND=noninteractive dpkg -i $(DEBS_PATH)/$* $(LOG) && rm -d $(DEBS_PATH)/dpkg_lock && break; } || { rm -d $(DEBS_PATH)/dpkg_lock && exit 1 ; } + fi + done + $(FOOTER) + + +############################################################################### +## Python packages +############################################################################### + +# Build project with python setup.py --command-packages=stdeb.command +# Add new package for build: +# SOME_NEW_DEB = some_new_deb.deb +# $(SOME_NEW_DEB)_SRC_PATH = $(SRC_PATH)/project_name +# $(SOME_NEW_DEB)_DEPENDS = $(SOME_OTHER_DEB1) $(SOME_OTHER_DEB2) ... +# SONIC_PYTHON_STDEB_DEBS += $(SOME_NEW_DEB) +$(addprefix $(PYTHON_DEBS_PATH)/, $(SONIC_PYTHON_STDEB_DEBS)) : $(PYTHON_DEBS_PATH)/% : .platform \ + $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEBS_DEPENDS))) \ + $$(addsuffix -install,$$(addprefix $(PYTHON_DEBS_PATH)/,$$($$*_DEPENDS))) \ + $$(addsuffix -install,$$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*_WHEEL_DEPENDS))) \ + $(call dpkg_depend,$(PYTHON_DEBS_PATH)/%.dep) + + $(HEADER) + + # Load the target deb from DPKG cache + $(call LOAD_CACHE,$*,$@) + + # Skip building the target if it is already loaded from cache + if [ -z '$($*_CACHE_LOADED)' ] ; then + + # Apply series of patches if exist + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; popd; fi + # Build project + pushd $($*_SRC_PATH) $(LOG_SIMPLE) + rm -rf deb_dist/* $(LOG) + python setup.py --command-packages=stdeb.command bdist_deb $(LOG) + popd $(LOG_SIMPLE) + # Clean up + if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; [ -d .pc ] && rm -rf .pc; popd; fi + # Take built package(s) + mv -f $(addprefix $($*_SRC_PATH)/deb_dist/, $* $($*_DERIVED_DEBS)) $(PYTHON_DEBS_PATH) $(LOG) + + # Save the target deb into DPKG cache + $(call SAVE_CACHE,$*,$@) + fi + + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(PYTHON_DEBS_PATH)/, $(SONIC_PYTHON_STDEB_DEBS)) + +# Build project using python setup.py bdist_wheel +# Projects that generate python wheels +# Add new package for build: +# SOME_NEW_WHL = some_new_whl.whl +# $(SOME_NEW_WHL)_SRC_PATH = $(SRC_PATH)/project_name +# $(SOME_NEW_WHL)_PYTHON_VERSION = 2 (or 3) +# $(SOME_NEW_WHL)_DEPENDS = $(SOME_OTHER_WHL1) $(SOME_OTHER_WHL2) ... +# SONIC_PYTHON_WHEELS += $(SOME_NEW_WHL) +$(addprefix $(PYTHON_WHEELS_PATH)/, $(SONIC_PYTHON_WHEELS)) : $(PYTHON_WHEELS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*_DEPENDS))) \ + $(call dpkg_depend,$(PYTHON_WHEELS_PATH)/%.dep) \ + $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEBS_DEPENDS))) + $(HEADER) + + # Load the target deb from DPKG cache + $(call LOAD_CACHE,$*,$@) + + # Skip building the target if it is already loaded from cache + if [ -z '$($*_CACHE_LOADED)' ] ; then + + pushd $($*_SRC_PATH) $(LOG_SIMPLE) + # apply series of patches if exist + if [ -f ../$(notdir $($*_SRC_PATH)).patch/series ]; then QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; fi + if [ ! "$($*_TEST)" = "n" ]; then python$($*_PYTHON_VERSION) setup.py test $(LOG); fi + python$($*_PYTHON_VERSION) setup.py bdist_wheel $(LOG) + # clean up + if [ -f ../$(notdir $($*_SRC_PATH)).patch/series ]; then quilt pop -a -f; [ -d .pc ] && rm -rf .pc; fi + popd $(LOG_SIMPLE) + mv -f $($*_SRC_PATH)/dist/$* $(PYTHON_WHEELS_PATH) $(LOG) + + # Save the target deb into DPKG cache + $(call SAVE_CACHE,$*,$@) + fi + + # Uninstall unneeded build dependency + $(call UNINSTALL_DEBS,$($*_UNINSTALLS)) + + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(PYTHON_WHEELS_PATH)/, $(SONIC_PYTHON_WHEELS)) + +# Targets for installing python wheels. +# Autogenerated +SONIC_INSTALL_WHEELS = $(addsuffix -install, $(addprefix $(PYTHON_WHEELS_PATH)/, $(SONIC_PYTHON_WHEELS))) +$(SONIC_INSTALL_WHEELS) : $(PYTHON_WHEELS_PATH)/%-install : .platform $$(addsuffix -install,$$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*_DEPENDS))) $(PYTHON_WHEELS_PATH)/$$* + $(HEADER) + [ -f $(PYTHON_WHEELS_PATH)/$* ] || { echo $(PYTHON_WHEELS_PATH)/$* does not exist $(LOG) && exit 1; } + # put a lock here to avoid race conditions + while true; do + if mkdir $(PYTHON_WHEELS_PATH)/pip_lock &> /dev/null; then + { sudo -E pip$($*_PYTHON_VERSION) install $(PYTHON_WHEELS_PATH)/$* $(LOG) && rm -d $(PYTHON_WHEELS_PATH)/pip_lock && break; } || { rm -d $(PYTHON_WHEELS_PATH)/pip_lock && exit 1 ; } + fi + done + $(FOOTER) + +############################################################################### +## Docker images related targets +############################################################################### + +# start docker daemon +docker-start : + @sudo sed -i '/http_proxy/d' /etc/default/docker + @sudo bash -c "echo \"export http_proxy=$$http_proxy\" >> /etc/default/docker" + @test x$(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD) != x"y" && sudo service docker status &> /dev/null || ( sudo service docker start &> /dev/null && ./scripts/wait_for_docker.sh 60 ) + +# targets for building simple docker images that do not depend on any debian packages +$(addprefix $(TARGET_PATH)/, $(SONIC_SIMPLE_DOCKER_IMAGES)) : $(TARGET_PATH)/%.gz : .platform docker-start $$(addsuffix -load,$$(addprefix $(TARGET_PATH)/,$$($$*.gz_LOAD_DOCKERS))) + $(HEADER) + # Apply series of patches if exist + if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && QUILT_PATCHES=../$(notdir $($*.gz_PATH)).patch quilt push -a; popd; fi + # Prepare docker build info + scripts/prepare_docker_buildinfo.sh $* $($*.gz_PATH)/Dockerfile $(CONFIGURED_ARCH) $(TARGET_DOCKERFILE)/Dockerfile.buildinfo + docker info $(LOG) + docker build --squash --no-cache \ + --build-arg http_proxy=$(HTTP_PROXY) \ + --build-arg https_proxy=$(HTTPS_PROXY) \ + --build-arg user=$(USER) \ + --build-arg uid=$(UID) \ + --build-arg guid=$(GUID) \ + --build-arg docker_container_name=$($*.gz_CONTAINER_NAME) \ + --label Tag=$(SONIC_IMAGE_VERSION) \ + -f $(TARGET_DOCKERFILE)/Dockerfile.buildinfo \ + -t $* $($*.gz_PATH) $(LOG) + scripts/collect_docker_version_files.sh $* $(TARGET_PATH) + docker save $* | gzip -c > $@ + # Clean up + if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && quilt pop -a -f; [ -d .pc ] && rm -rf .pc; popd; fi + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(TARGET_PATH)/, $(SONIC_SIMPLE_DOCKER_IMAGES)) + +DOCKER_IMAGES_FOR_INSTALLERS := $(sort $(foreach installer,$(SONIC_INSTALLERS),$($(installer)_DOCKERS))) + +$(foreach DOCKER_IMAGE,$(SONIC_JESSIE_DOCKERS), $(eval $(DOCKER_IMAGE)_DEBS_PATH := $(JESSIE_DEBS_PATH))) +$(foreach DOCKER_IMAGE,$(SONIC_JESSIE_DOCKERS), $(eval $(DOCKER_IMAGE)_FILES_PATH := $(JESSIE_FILES_PATH))) +$(foreach DOCKER_IMAGE,$(SONIC_JESSIE_DBG_DOCKERS), $(eval $(DOCKER_IMAGE)_DEBS_PATH := $(JESSIE_DEBS_PATH))) +$(foreach DOCKER_IMAGE,$(SONIC_JESSIE_DBG_DOCKERS), $(eval $(DOCKER_IMAGE)_FILES_PATH := $(JESSIE_FILES_PATH))) +$(foreach DOCKER_IMAGE,$(SONIC_STRETCH_DOCKERS), $(eval $(DOCKER_IMAGE)_DEBS_PATH := $(STRETCH_DEBS_PATH))) +$(foreach DOCKER_IMAGE,$(SONIC_STRETCH_DOCKERS), $(eval $(DOCKER_IMAGE)_FILES_PATH := $(STRETCH_FILES_PATH))) +$(foreach DOCKER_IMAGE,$(SONIC_STRETCH_DBG_DOCKERS), $(eval $(DOCKER_IMAGE)_DEBS_PATH := $(STRETCH_DEBS_PATH))) +$(foreach DOCKER_IMAGE,$(SONIC_STRETCH_DBG_DOCKERS), $(eval $(DOCKER_IMAGE)_FILES_PATH := $(STRETCH_FILES_PATH))) + +ifeq ($(BLDENV),jessie) + DOCKER_IMAGES := $(SONIC_JESSIE_DOCKERS) + DOCKER_DBG_IMAGES := $(SONIC_JESSIE_DBG_DOCKERS) + JESSIE_DOCKER_IMAGES = $(filter $(SONIC_JESSIE_DOCKERS),$(DOCKER_IMAGES_FOR_INSTALLERS) $(EXTRA_DOCKER_TARGETS)) + JESSIE_DBG_DOCKER_IMAGES = $(filter $(SONIC_JESSIE_DBG_DOCKERS),$(DOCKER_IMAGES_FOR_INSTALLERS) $(EXTRA_DOCKER_TARGETS)) +else +ifeq ($(BLDENV),stretch) + DOCKER_IMAGES := $(SONIC_STRETCH_DOCKERS) + DOCKER_DBG_IMAGES := $(SONIC_STRETCH_DBG_DOCKERS) + STRETCH_DOCKER_IMAGES = $(filter $(SONIC_STRETCH_DOCKERS),$(DOCKER_IMAGES_FOR_INSTALLERS) $(EXTRA_DOCKER_TARGETS)) + STRETCH_DBG_DOCKER_IMAGES = $(filter $(SONIC_STRETCH_DBG_DOCKERS),$(DOCKER_IMAGES_FOR_INSTALLERS) $(EXTRA_DOCKER_TARGETS)) +else + DOCKER_IMAGES = $(filter-out $(SONIC_JESSIE_DOCKERS) $(SONIC_STRETCH_DOCKERS),$(SONIC_DOCKER_IMAGES)) + DOCKER_DBG_IMAGES = $(filter-out $(SONIC_JESSIE_DBG_DOCKERS) $(SONIC_STRETCH_DBG_DOCKERS), $(SONIC_DOCKER_DBG_IMAGES)) +endif +endif + +$(foreach IMAGE,$(DOCKER_IMAGES), $(eval $(IMAGE)_DEBS_PATH := $(DEBS_PATH))) +$(foreach IMAGE,$(DOCKER_IMAGES), $(eval $(IMAGE)_FILES_PATH := $(FILES_PATH))) +$(foreach IMAGE,$(DOCKER_DBG_IMAGES), $(eval $(IMAGE)_DEBS_PATH := $(DEBS_PATH))) +$(foreach IMAGE,$(DOCKER_DBG_IMAGES), $(eval $(IMAGE)_FILES_PATH := $(FILES_PATH))) + +# Targets for building docker images +$(addprefix $(TARGET_PATH)/, $(DOCKER_IMAGES)) : $(TARGET_PATH)/%.gz : .platform docker-start \ + $$(addprefix $$($$*.gz_DEBS_PATH)/,$$($$*.gz_DEPENDS)) \ + $$(addprefix $$($$*.gz_FILES_PATH)/,$$($$*.gz_FILES)) \ + $$(addprefix $(PYTHON_DEBS_PATH)/,$$($$*.gz_PYTHON_DEBS)) \ + $$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*.gz_PYTHON_WHEELS)) \ + $$(addsuffix -load,$$(addprefix $(TARGET_PATH)/,$$($$*.gz_LOAD_DOCKERS))) \ + $$($$*.gz_PATH)/Dockerfile.j2 \ + $(call dpkg_depend,$(TARGET_PATH)/%.gz.dep) + $(HEADER) + + # Load the target deb from DPKG cache + $(call LOAD_CACHE,$*.gz,$@) + + # Skip building the target if it is already loaded from cache + if [ -z '$($*.gz_CACHE_LOADED)' ] ; then + + # Apply series of patches if exist + if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && QUILT_PATCHES=../$(notdir $($*.gz_PATH)).patch quilt push -a; popd; fi + mkdir -p $($*.gz_PATH)/debs $(LOG) + mkdir -p $($*.gz_PATH)/files $(LOG) + mkdir -p $($*.gz_PATH)/python-debs $(LOG) + mkdir -p $($*.gz_PATH)/python-wheels $(LOG) + sudo mount --bind $($*.gz_DEBS_PATH) $($*.gz_PATH)/debs $(LOG) + sudo mount --bind $($*.gz_FILES_PATH) $($*.gz_PATH)/files $(LOG) + sudo mount --bind $(PYTHON_DEBS_PATH) $($*.gz_PATH)/python-debs $(LOG) + sudo mount --bind $(PYTHON_WHEELS_PATH) $($*.gz_PATH)/python-wheels $(LOG) + # Export variables for j2. Use path for unique variable names, e.g. docker_orchagent_debs + $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_debs=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_DEPENDS),RDEPENDS))\n" | awk '!a[$$0]++')) + $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_pydebs=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_PYTHON_DEBS)))\n" | awk '!a[$$0]++')) + $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_whls=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_PYTHON_WHEELS)))\n" | awk '!a[$$0]++')) + $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_dbgs=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_DBG_PACKAGES)))\n" | awk '!a[$$0]++')) + j2 $($*.gz_PATH)/Dockerfile.j2 > $($*.gz_PATH)/Dockerfile + # Prepare docker build info + PACKAGE_URL_PREFIX=$(PACKAGE_URL_PREFIX) \ + SONIC_ENFORCE_VERSIONS=$(SONIC_ENFORCE_VERSIONS) \ + TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) \ + scripts/prepare_docker_buildinfo.sh $* $($*.gz_PATH)/Dockerfile $(CONFIGURED_ARCH) + docker info $(LOG) + docker build --squash --no-cache \ + --build-arg http_proxy=$(HTTP_PROXY) \ + --build-arg https_proxy=$(HTTPS_PROXY) \ + --build-arg user=$(USER) \ + --build-arg uid=$(UID) \ + --build-arg guid=$(GUID) \ + --build-arg docker_container_name=$($*.gz_CONTAINER_NAME) \ + --build-arg frr_user_uid=$(FRR_USER_UID) \ + --build-arg frr_user_gid=$(FRR_USER_GID) \ + --build-arg image_version=$(SONIC_IMAGE_VERSION) \ + --label Tag=$(SONIC_IMAGE_VERSION) \ + -t $* $($*.gz_PATH) $(LOG) + scripts/collect_docker_version_files.sh $* $(TARGET_PATH) + docker save $* | gzip -c > $@ + # Clean up + if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && quilt pop -a -f; [ -d .pc ] && rm -rf .pc; popd; fi + + # Save the target deb into DPKG cache + $(call SAVE_CACHE,$*.gz,$@) + fi + + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(TARGET_PATH)/, $(DOCKER_IMAGES)) + +# Targets for building docker images +$(addprefix $(TARGET_PATH)/, $(DOCKER_DBG_IMAGES)) : $(TARGET_PATH)/%-$(DBG_IMAGE_MARK).gz : .platform docker-start \ + $$(addprefix $$($$*.gz_DEBS_PATH)/,$$($$*.gz_DBG_DEPENDS)) \ + $$(addsuffix -load,$$(addprefix $(TARGET_PATH)/,$$*.gz)) \ + $(call dpkg_depend,$(TARGET_PATH)/%-$(DBG_IMAGE_MARK).gz.dep) + $(HEADER) + + # Load the target deb from DPKG cache + $(call LOAD_CACHE,$*-$(DBG_IMAGE_MARK).gz,$@) + + # Skip building the target if it is already loaded from cache + if [ -z '$($*-$(DBG_IMAGE_MARK).gz_CACHE_LOADED)' ] ; then + + mkdir -p $($*.gz_PATH)/debs $(LOG) + sudo mount --bind $($*.gz_DEBS_PATH) $($*.gz_PATH)/debs $(LOG) + # Export variables for j2. Use path for unique variable names, e.g. docker_orchagent_debs + $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_dbg_debs=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_DBG_DEPENDS),RDEPENDS))\n" | awk '!a[$$0]++')) + $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_image_dbgs=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_DBG_IMAGE_PACKAGES)))\n" | awk '!a[$$0]++')) + ./build_debug_docker_j2.sh $* $(subst -,_,$(notdir $($*.gz_PATH)))_dbg_debs $(subst -,_,$(notdir $($*.gz_PATH)))_image_dbgs > $($*.gz_PATH)/Dockerfile-dbg.j2 + j2 $($*.gz_PATH)/Dockerfile-dbg.j2 > $($*.gz_PATH)/Dockerfile-dbg + # Prepare docker build info + PACKAGE_URL_PREFIX=$(PACKAGE_URL_PREFIX) \ + SONIC_ENFORCE_VERSIONS=$(SONIC_ENFORCE_VERSIONS) \ + TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) \ + scripts/prepare_docker_buildinfo.sh $* $($*.gz_PATH)/Dockerfile-dbg $(CONFIGURED_ARCH) + docker info $(LOG) + docker build \ + $(if $($*.gz_DBG_DEPENDS), --squash --no-cache, --no-cache) \ + --build-arg http_proxy=$(HTTP_PROXY) \ + --build-arg https_proxy=$(HTTPS_PROXY) \ + --build-arg docker_container_name=$($*.gz_CONTAINER_NAME) \ + --label Tag=$(SONIC_IMAGE_VERSION) \ + --file $($*.gz_PATH)/Dockerfile-dbg \ + -t $*-dbg $($*.gz_PATH) $(LOG) + scripts/collect_docker_version_files.sh $*-dbg $(TARGET_PATH) + docker save $*-dbg | gzip -c > $@ + # Clean up + if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && quilt pop -a -f; [ -d .pc ] && rm -rf .pc; popd; fi + + # Save the target deb into DPKG cache + $(call SAVE_CACHE,$*-$(DBG_IMAGE_MARK).gz,$@) + fi + + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(TARGET_PATH)/, $(DOCKER_DBG_IMAGES)) + +DOCKER_LOAD_TARGETS = $(addsuffix -load,$(addprefix $(TARGET_PATH)/, \ + $(SONIC_SIMPLE_DOCKER_IMAGES) \ + $(DOCKER_IMAGES))) + +$(DOCKER_LOAD_TARGETS) : $(TARGET_PATH)/%.gz-load : .platform docker-start $$(TARGET_PATH)/$$*.gz + $(HEADER) + docker load -i $(TARGET_PATH)/$*.gz $(LOG) + $(FOOTER) + +############################################################################### +## Installers +############################################################################### + +# targets for building installers with base image +$(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ + .platform \ + onie-image.conf \ + build_debian.sh \ + scripts/dbg_files.sh \ + build_image.sh \ + $$(addsuffix -install,$$(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$$($$*_DEPENDS))) \ + $$(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$$($$*_INSTALLS)) \ + $$(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$$($$*_LAZY_INSTALLS)) \ + $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(INITRAMFS_TOOLS) \ + $(LINUX_KERNEL) \ + $(SONIC_DEVICE_DATA) \ + $(IFUPDOWN2) \ + $(KDUMP_TOOLS) \ + $(NTP) \ + $(LIBPAM_TACPLUS) \ + $(LIBNSS_TACPLUS) \ + $(MONIT) \ + $(OPENSSH_SERVER) \ + $(PYTHON_SWSSCOMMON) \ + $(PYTHON3_SWSSCOMMON) \ + $(SONIC_UTILITIES_DATA) \ + $(SONIC_HOST_SERVICES_DATA)) \ + $$(addprefix $(TARGET_PATH)/,$$($$*_DOCKERS)) \ + $$(addprefix $(FILES_PATH)/,$$($$*_FILES)) \ + $(if $(findstring y,$(ENABLE_ZTP)),$(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(SONIC_ZTP))) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_UTILITIES_PY3)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PY_COMMON_PY2)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PY_COMMON_PY3)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CONFIG_ENGINE_PY2)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CONFIG_ENGINE_PY3)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_COMMON_PY2)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_COMMON_PY3)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(REDIS_DUMP_LOAD_PY2)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_API_PY2)) \ + $(if $(findstring y,$(PDDF_SUPPORT)),$(addprefix $(PYTHON_WHEELS_PATH)/,$(PDDF_PLATFORM_API_BASE_PY2))) \ + $(if $(findstring y,$(PDDF_SUPPORT)),$(addprefix $(PYTHON_WHEELS_PATH)/,$(PDDF_PLATFORM_API_BASE_PY3))) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_YANG_MODELS_PY3)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CTRMGRD)) \ + $(addprefix $(FILES_PATH)/,$($(SONIC_CTRMGRD)_FILES)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_YANG_MGMT_PY3)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SYSTEM_HEALTH)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_HOST_SERVICES_PY3)) + $(HEADER) + # Pass initramfs and linux kernel explicitly. They are used for all platforms + export debs_path="$(IMAGE_DISTRO_DEBS_PATH)" + export files_path="$(FILES_PATH)" + export python_debs_path="$(PYTHON_DEBS_PATH)" + export initramfs_tools="$(IMAGE_DISTRO_DEBS_PATH)/$(INITRAMFS_TOOLS)" + export linux_kernel="$(IMAGE_DISTRO_DEBS_PATH)/$(LINUX_KERNEL)" + export onie_recovery_image="$(FILES_PATH)/$(ONIE_RECOVERY_IMAGE)" + export kversion="$(KVERSION)" + export image_type="$($*_IMAGE_TYPE)" + export sonicadmin_user="$(USERNAME)" + export sonic_asic_platform="$(patsubst %-$(CONFIGURED_ARCH),%,$(CONFIGURED_PLATFORM))" + export enable_organization_extensions="$(ENABLE_ORGANIZATION_EXTENSIONS)" + export enable_dhcp_graph_service="$(ENABLE_DHCP_GRAPH_SERVICE)" + export enable_ztp="$(ENABLE_ZTP)" + export include_system_telemetry="$(INCLUDE_SYSTEM_TELEMETRY)" + export include_restapi="$(INCLUDE_RESTAPI)" + export include_nat="$(INCLUDE_NAT)" + export include_sflow="$(INCLUDE_SFLOW)" + export include_macsec="$(INCLUDE_MACSEC)" + export include_mgmt_framework="$(INCLUDE_MGMT_FRAMEWORK)" + export include_iccpd="$(INCLUDE_ICCPD)" + export pddf_support="$(PDDF_SUPPORT)" + export shutdown_bgp_on_start="$(SHUTDOWN_BGP_ON_START)" + export default_buffer_model="$(SONIC_BUFFER_MODEL)" + export include_kubernetes="$(INCLUDE_KUBERNETES)" + export enable_pfcwd_on_start="$(ENABLE_PFCWD_ON_START)" + export installer_debs="$(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$($*_INSTALLS))" + export lazy_installer_debs="$(foreach deb, $($*_LAZY_INSTALLS),$(foreach device, $($(deb)_PLATFORM),$(addprefix $(device)@, $(IMAGE_DISTRO_DEBS_PATH)/$(deb))))" + export installer_images="$(addprefix $(TARGET_PATH)/,$($*_DOCKERS))" + export sonic_py_common_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PY_COMMON_PY2))" + export sonic_py_common_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PY_COMMON_PY3))" + export config_engine_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CONFIG_ENGINE_PY2))" + export config_engine_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CONFIG_ENGINE_PY3))" + export swsssdk_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SWSSSDK_PY2))" + export swsssdk_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SWSSSDK_PY3))" + export platform_common_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_COMMON_PY2))" + export platform_common_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_COMMON_PY3))" + export redis_dump_load_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(REDIS_DUMP_LOAD_PY2))" + export redis_dump_load_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(REDIS_DUMP_LOAD_PY3))" + export install_debug_image="$(INSTALL_DEBUG_TOOLS)" + export sonic_yang_models_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_YANG_MODELS_PY3))" + export sonic_ctrmgmt_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CTRMGRD))" + export sonic_yang_mgmt_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_YANG_MGMT_PY3))" + export multi_instance="false" + export python_swss_debs="$(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$($(LIBSWSSCOMMON)_RDEPENDS))" + export python_swss_debs+=" $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(LIBSWSSCOMMON)) $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(PYTHON_SWSSCOMMON)) $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(PYTHON3_SWSSCOMMON))" + export sonic_utilities_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_UTILITIES_PY3))" + export sonic_host_services_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_HOST_SERVICES_PY3))" + + $(foreach docker, $($*_DOCKERS),\ + export docker_image="$(docker)" + export docker_image_name="$(basename $(docker))" + export docker_container_name="$($(docker:-dbg.gz=.gz)_CONTAINER_NAME)" + $(eval $(docker:-dbg.gz=.gz)_RUN_OPT += $($(docker:-dbg.gz=.gz)_$($*_IMAGE_TYPE)_RUN_OPT)) + export docker_image_run_opt="$($(docker:-dbg.gz=.gz)_RUN_OPT)" + + if [ -f files/build_templates/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 ]; then + j2 files/build_templates/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 > $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service + + # Set the flag GLOBAL for all the global system-wide dockers. + $(if $(shell ls files/build_templates/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 2>/dev/null),\ + $(eval $(docker:-dbg.gz=.gz)_GLOBAL = yes) + ) + fi + # Any service template, inside instance directory, will be used to generate .service and @.service file. + if [ -f files/build_templates/per_namespace/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 ]; then + export multi_instance="true" + j2 files/build_templates/per_namespace/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 > $($(docker:-dbg.gz=.gz)_CONTAINER_NAME)@.service + $(if $(shell ls files/build_templates/per_namespace/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 2>/dev/null),\ + $(eval $(docker:-dbg.gz=.gz)_TEMPLATE = yes) + ) + export multi_instance="false" + j2 files/build_templates/per_namespace/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 > $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service + fi + # Any service template, inside share_image directory, will be used to generate -chassis.service file. + # TODO: need better way to name the image-shared service + if [ -f files/build_templates/share_image/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 ]; then + j2 files/build_templates/share_image/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 > $($(docker:-dbg.gz=.gz)_CONTAINER_NAME)-chassis.service + $(if $(shell ls files/build_templates/share_image/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 2>/dev/null),\ + $(eval $(docker:-dbg.gz=.gz)_SHARE = yes) + ) + fi + + j2 files/build_templates/docker_image_ctl.j2 > $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).sh + chmod +x $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).sh + ) + + # Exported variables are used by sonic_debian_extension.sh + export installer_start_scripts="$(foreach docker, $($*_DOCKERS),$(addsuffix .sh, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME)))" + export feature_vs_image_names="$(foreach docker, $($*_DOCKERS), $(addsuffix :, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME):$(docker:-dbg.gz=.gz)))" + + # Marks template services with an "@" according to systemd convention + # If the $($docker)_TEMPLATE) variable is set, the service will be treated as a template + # If the $($docker)_GLOBAL) and $($docker)_TEMPLATE) variables are set the service will be added both as a global and template service. + $(foreach docker, $($*_DOCKERS),\ + $(if $($(docker:-dbg.gz=.gz)_TEMPLATE),\ + $(if $($(docker:-dbg.gz=.gz)_GLOBAL),\ + $(eval SERVICES += "$(addsuffix .service, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME))")\ + )\ + $(eval SERVICES += "$(addsuffix @.service, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME))"),\ + $(eval SERVICES += "$(addsuffix .service, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME))") + ) + $(if $($(docker:-dbg.gz=.gz)_SHARE),\ + $(eval SERVICES += "$(addsuffix -chassis.service, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME))") + ) + ) + export installer_services="$(SERVICES)" + + export installer_extra_files="$(foreach docker, $($*_DOCKERS), $(foreach file, $($(docker:-dbg.gz=.gz)_BASE_IMAGE_FILES), $($(docker:-dbg.gz=.gz)_PATH)/base_image_files/$(file)))" + + j2 -f env files/initramfs-tools/union-mount.j2 onie-image.conf > files/initramfs-tools/union-mount + j2 -f env files/initramfs-tools/arista-convertfs.j2 onie-image.conf > files/initramfs-tools/arista-convertfs + + $(if $($*_DOCKERS), + j2 files/build_templates/sonic_debian_extension.j2 > sonic_debian_extension.sh + chmod +x sonic_debian_extension.sh, + ) + + DEBUG_IMG="$(INSTALL_DEBUG_TOOLS)" \ + DEBUG_SRC_ARCHIVE_DIRS="$(DBG_SRC_ARCHIVE)" \ + DEBUG_SRC_ARCHIVE_FILE="$(DBG_SRC_ARCHIVE_FILE)" \ + scripts/dbg_files.sh + + DEBUG_IMG="$(INSTALL_DEBUG_TOOLS)" \ + DEBUG_SRC_ARCHIVE_FILE="$(DBG_SRC_ARCHIVE_FILE)" \ + USERNAME="$(USERNAME)" \ + PASSWORD="$(PASSWORD)" \ + IMAGE_TYPE=$($*_IMAGE_TYPE) \ + TARGET_PATH=$(TARGET_PATH) \ + SONIC_ENFORCE_VERSIONS=$(SONIC_ENFORCE_VERSIONS) \ + TRUSTED_GPG_URLS=$(TRUSTED_GPG_URLS) \ + PACKAGE_URL_PREFIX=$(PACKAGE_URL_PREFIX) \ + ./build_debian.sh $(LOG) + + USERNAME="$(USERNAME)" \ + PASSWORD="$(PASSWORD)" \ + TARGET_MACHINE=$($*_MACHINE) \ + IMAGE_TYPE=$($*_IMAGE_TYPE) \ + SONIC_ENABLE_IMAGE_SIGNATURE="$(SONIC_ENABLE_IMAGE_SIGNATURE)" \ + SIGNING_KEY="$(SIGNING_KEY)" \ + SIGNING_CERT="$(SIGNING_CERT)" \ + CA_CERT="$(CA_CERT)" \ + TARGET_PATH="$(TARGET_PATH)" \ + ./build_image.sh $(LOG) + + $(foreach docker, $($*_DOCKERS), \ + rm -f $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).sh + rm -f $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service + rm -f $($(docker:-dbg.gz=.gz)_CONTAINER_NAME)@.service + ) + + $(if $($*_DOCKERS), + rm sonic_debian_extension.sh, + ) + + chmod a+x $@ + $(FOOTER) + +SONIC_TARGET_LIST += $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) + +############################################################################### +## Clean targets +############################################################################### + +SONIC_CLEAN_DEBS = $(addsuffix -clean,$(addprefix $(DEBS_PATH)/, \ + $(SONIC_ONLINE_DEBS) \ + $(SONIC_COPY_DEBS) \ + $(SONIC_MAKE_DEBS) \ + $(SONIC_DPKG_DEBS) \ + $(SONIC_DERIVED_DEBS) \ + $(SONIC_EXTRA_DEBS))) + +SONIC_CLEAN_FILES = $(addsuffix -clean,$(addprefix $(FILES_PATH)/, \ + $(SONIC_ONLINE_FILES) \ + $(SONIC_COPY_FILES) \ + $(SONIC_MAKE_FILES))) + +$(SONIC_CLEAN_DEBS) :: $(DEBS_PATH)/%-clean : .platform $$(addsuffix -clean,$$(addprefix $(DEBS_PATH)/,$$($$*_MAIN_DEB))) + @# remove derived or extra targets if main one is removed, because we treat them + @# as part of one package + @rm -f $(addprefix $(DEBS_PATH)/, $* $($*_DERIVED_DEBS) $($*_EXTRA_DEBS)) + +$(SONIC_CLEAN_FILES) :: $(FILES_PATH)/%-clean : .platform + @rm -f $(FILES_PATH)/$* + +SONIC_CLEAN_TARGETS += $(addsuffix -clean,$(addprefix $(TARGET_PATH)/, \ + $(SONIC_DOCKER_IMAGES) \ + $(SONIC_DOCKER_DBG_IMAGES) \ + $(SONIC_SIMPLE_DOCKER_IMAGES) \ + $(SONIC_INSTALLERS))) +$(SONIC_CLEAN_TARGETS) :: $(TARGET_PATH)/%-clean : .platform + @rm -f $(TARGET_PATH)/$* + +SONIC_CLEAN_STDEB_DEBS = $(addsuffix -clean,$(addprefix $(PYTHON_DEBS_PATH)/, \ + $(SONIC_PYTHON_STDEB_DEBS))) +$(SONIC_CLEAN_STDEB_DEBS) :: $(PYTHON_DEBS_PATH)/%-clean : .platform + @rm -f $(PYTHON_DEBS_PATH)/$* + +SONIC_CLEAN_WHEELS = $(addsuffix -clean,$(addprefix $(PYTHON_WHEELS_PATH)/, \ + $(SONIC_PYTHON_WHEELS))) +$(SONIC_CLEAN_WHEELS) :: $(PYTHON_WHEELS_PATH)/%-clean : .platform + @rm -f $(PYTHON_WHEELS_PATH)/$* + +clean-logs :: .platform + @rm -f $(TARGET_PATH)/*.log $(DEBS_PATH)/*.log $(FILES_PATH)/*.log $(PYTHON_DEBS_PATH)/*.log $(PYTHON_WHEELS_PATH)/*.log + +clean :: .platform clean-logs $$(SONIC_CLEAN_DEBS) $$(SONIC_CLEAN_FILES) $$(SONIC_CLEAN_TARGETS) $$(SONIC_CLEAN_STDEB_DEBS) $$(SONIC_CLEAN_WHEELS) + +############################################################################### +## all +############################################################################### + +all : .platform $$(addprefix $(TARGET_PATH)/,$$(SONIC_ALL)) + +stretch : $$(addprefix $(TARGET_PATH)/,$$(STRETCH_DOCKER_IMAGES)) \ + $$(addprefix $(TARGET_PATH)/,$$(STRETCH_DBG_DOCKER_IMAGES)) + +jessie : $$(addprefix $(TARGET_PATH)/,$$(JESSIE_DOCKER_IMAGES)) \ + $$(addprefix $(TARGET_PATH)/,$$(JESSIE_DBG_DOCKER_IMAGES)) + +############################################################################### +## Standard targets +############################################################################### + +.PHONY : $(SONIC_CLEAN_DEBS) $(SONIC_CLEAN_FILES) $(SONIC_CLEAN_TARGETS) $(SONIC_CLEAN_STDEB_DEBS) $(SONIC_CLEAN_WHEELS) $(SONIC_PHONY_TARGETS) clean distclean configure + +.INTERMEDIATE : $(SONIC_INSTALL_DEBS) $(SONIC_INSTALL_WHEELS) $(DOCKER_LOAD_TARGETS) docker-start .platform diff --git a/sonic-slave-buster/Dockerfile.j2 b/sonic-slave-buster/Dockerfile.j2 new file mode 100644 index 000000000000..ed541ec5356a --- /dev/null +++ b/sonic-slave-buster/Dockerfile.j2 @@ -0,0 +1,516 @@ +{%- if CONFIGURED_ARCH == "armhf" %} +FROM multiarch/qemu-user-static:x86_64-arm-5.0.0-2 as qemu +FROM multiarch/debian-debootstrap:armhf-buster +COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin +{%- elif CONFIGURED_ARCH == "arm64" %} +FROM multiarch/debian-debootstrap:arm64-buster +{%- else -%} +FROM debian:buster +{%- endif %} + +MAINTAINER gulv@microsoft.com + +COPY ["no-check-valid-until", "/etc/apt/apt.conf.d/"] + +RUN echo "deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ buster main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian/ buster main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ buster/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ buster/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=amd64] http://debian-archive.trafficmanager.net/debian buster-backports main" >> /etc/apt/sources.list && \ + echo "deb [arch=amd64] http://packages.trafficmanager.net/debian/debian buster main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=amd64] http://packages.trafficmanager.net/debian/debian buster-updates main contrib non-free" >> /etc/apt/sources.list + +{%- if CONFIGURED_ARCH == "armhf" %} +RUN echo "deb [arch=armhf] http://deb.debian.org/debian buster main contrib non-free" > /etc/apt/sources.list && \ + echo "deb-src [arch=armhf] http://deb.debian.org/debian buster main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=armhf] http://deb.debian.org/debian buster-updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=armhf] http://deb.debian.org/debian buster-updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=armhf] http://security.debian.org buster/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=armhf] http://security.debian.org buster/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo 'deb [arch=armhf] http://ftp.debian.org/debian buster-backports main' >> /etc/apt/sources.list && \ + echo "deb [arch=armhf] http://packages.trafficmanager.net/debian/debian buster main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=armhf] http://packages.trafficmanager.net/debian/debian buster-updates main contrib non-free" >> /etc/apt/sources.list +{%- elif CONFIGURED_ARCH == "arm64" %} +RUN echo "deb [arch=arm64] http://deb.debian.org/debian buster main contrib non-free" > /etc/apt/sources.list && \ + echo "deb-src [arch=arm64] http://deb.debian.org/debian buster main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=arm64] http://deb.debian.org/debian buster-updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=arm64] http://deb.debian.org/debian buster-updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=arm64] http://security.debian.org buster/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=arm64] http://security.debian.org buster/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo 'deb [arch=arm64] http://ftp.debian.org/debian buster-backports main' >> /etc/apt/sources.list && \ + echo "deb [arch=arm64] http://packages.trafficmanager.net/debian/debian buster main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=arm64] http://packages.trafficmanager.net/debian/debian buster-updates main contrib non-free" >> /etc/apt/sources.list +{%- endif %} + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y \ + apt-utils \ + default-jre-headless \ + openssh-server \ + curl \ + wget \ + unzip \ + git \ + build-essential \ + libtool \ + lintian \ + sudo \ + dh-make \ + dh-exec \ + kmod \ + libtinyxml2-6a \ + libtinyxml2-dev \ + python \ + python-pip \ + python3 \ + python3-pip \ + libncurses5-dev \ + texinfo \ + dh-autoreconf \ + doxygen \ + devscripts \ + git-buildpackage \ + perl-modules \ + libswitch-perl \ + dh-systemd \ + libzmq5 \ + libzmq3-dev \ +# For quagga build + libreadline-dev \ + texlive-latex-base \ + texlive-generic-recommended \ + texlive-fonts-recommended \ + libpam0g-dev \ + libpam-dev \ + libcap-dev \ + imagemagick \ + ghostscript \ + groff \ + libpcre3-dev \ + gawk \ + chrpath \ +# For frr build + libc-ares-dev \ + libsnmp-dev \ + libjson-c3 \ + libjson-c-dev \ + libsystemd-dev \ + python-ipaddr \ + libcmocka-dev \ + python3-all-dev \ + python3-all-dbg \ + install-info \ + logrotate \ +# For libnl3 (local) build + cdbs \ +# For SAI meta build + libxml-simple-perl \ + graphviz \ + aspell \ +# For linux build + bc \ + fakeroot \ + build-essential \ + devscripts \ + quilt \ + stgit \ +# For platform-modules build + module-assistant \ +# For thrift build\ + gem2deb \ + libevent-dev \ + libglib2.0-dev \ + libqt4-dev \ + python-all-dev \ + python-twisted \ + phpunit \ + libbit-vector-perl \ + openjdk-11-jdk \ + javahelper \ + maven-debian-helper \ + ant \ + libhttpclient-java \ + libslf4j-java \ + libservlet3.1-java \ + qt5-default \ + pkg-php-tools \ +# For mellanox sdk build + libpcre3 \ + libpcre3-dev \ + byacc \ + flex \ + libglib2.0-dev \ + bison \ + expat \ + libexpat1-dev \ + dpatch \ + libdb-dev \ + iptables-dev \ + ctags \ +# For mellanox sai build + libtool-bin \ + libxml2-dev \ +# For BFN sdk build + libusb-1.0-0-dev \ + libcurl3-nss-dev \ + libunwind8-dev \ + telnet \ + libc-ares2 \ + libgoogle-perftools4 \ +# For build image + cpio \ + squashfs-tools \ + zip \ +# For broadcom sdk build +{%- if CONFIGURED_ARCH == "amd64" %} + linux-compiler-gcc-8-x86 \ +{%- endif %} +{%- if CONFIGURED_ARCH == "armhf" %} + linux-compiler-gcc-8-arm \ +{%- endif %} + linux-kbuild-4.19 \ +# teamd build + libdaemon-dev \ + libdbus-1-dev \ + libjansson-dev \ +# For cavium sdk build + libpcap-dev \ + dnsutils \ + libusb-dev \ +# For debian image reconfiguration + augeas-tools \ +# For p4 build + libyaml-dev \ + libevent-dev \ + libjudy-dev \ + libedit-dev \ + libnanomsg-dev \ + python-stdeb \ +# For redis build + libjemalloc-dev \ + liblua5.1-0-dev \ + lua-bitop-dev \ + lua-cjson-dev \ +# For mft kernel module build + dkms \ +# For Jenkins static analysis, unit testing and code coverage + cppcheck \ + clang \ + pylint \ + python-pytest \ + python3-pytest \ + gcovr \ + python-pytest-cov \ + python3-pytest-cov \ + python-parse \ +# For snmpd + default-libmysqlclient-dev \ + libssl-dev \ + libperl-dev \ + libpci-dev \ + libpci3 \ + libsensors5 \ + libsensors4-dev \ + libwrap0-dev \ +# For lldpd + debhelper \ + autotools-dev \ + libbsd-dev \ + pkg-config \ + check \ +# For mpdecimal + docutils-common \ + libjs-sphinxdoc \ + libjs-underscore \ + python-docutils \ + python-jinja2 \ + python-markupsafe \ + python-pygments \ + python-roman \ + python-sphinx \ + sphinx-common \ + python3-sphinx \ +# For sonic config engine testing + python-dev \ +{%- if CONFIGURED_ARCH == "armhf" or CONFIGURED_ARCH == "arm64" %} + libxslt-dev \ +{%- endif %} +# For lockfile + procmail \ +# For gtest + libgtest-dev \ + cmake \ +# For pam_tacplus build + autoconf-archive \ +# For iproute2 + cm-super-minimal \ + libatm1-dev \ + libelf-dev \ + libmnl-dev \ + libselinux1-dev \ + linuxdoc-tools \ + lynx \ + texlive-latex-extra \ + texlive-latex-recommended \ + iproute2 \ +# For bash + texi2html \ +# For initramfs + shellcheck \ + bash-completion \ +{%- if CONFIGURED_ARCH == "amd64" %} +# For sonic vs image build + dosfstools \ + qemu-kvm \ + libvirt-clients \ +{%- endif %} +# For ntp + autogen \ + libopts25-dev \ + pps-tools \ + dh-apparmor \ +# For lm-sensors + librrd8 \ + librrd-dev \ + rrdtool \ +# For smartmontools 6.6-1 + automake1.11 \ + libselinux1-dev \ +# For kdump-tools + liblzo2-dev \ +# For iptables + libnetfilter-conntrack-dev \ + libnftnl-dev \ +# For SAI3.7 + protobuf-compiler \ + libprotobuf-dev \ + xxd \ +# For DHCP Monitor tool + libexplain-dev \ + libevent-dev \ +# For libyang + swig \ +# For build dtb + device-tree-compiler \ +# For sonic-mgmt-framework + autoconf \ + m4 \ + libxml2-utils \ + xsltproc \ + python-lxml \ + libexpat1-dev \ +# For WPA supplication + qtbase5-dev \ + aspell-en \ + libhiredis-dev \ + libnl-3-dev \ + swig3.0 \ + libpython2.7-dev \ + libssl-dev \ + dbus \ + libdbus-1-dev \ + libdbus-glib-1-2 \ + libdbus-glib-1-dev \ + libreadline-dev \ + libncurses5-dev \ + libpcsclite-dev \ + docbook-to-man \ + docbook-utils \ +# For kdump-tools + libbz2-dev \ +# For linkmgrd + libboost1.71-dev \ + libboost-program-options1.71-dev \ + libboost-system1.71-dev \ + libboost-thread1.71-dev \ + libboost-atomic1.71-dev \ + libboost-chrono1.71-dev \ + libboost-container1.71-dev \ + libboost-context1.71-dev \ + libboost-contract1.71-dev \ + libboost-coroutine1.71-dev \ + libboost-date-time1.71-dev \ + libboost-fiber1.71-dev \ + libboost-filesystem1.71-dev \ + libboost-graph-parallel1.71-dev \ + libboost-log1.71-dev \ + libboost-regex1.71-dev \ + googletest \ + libgtest-dev \ + libgcc-8-dev \ +# For sonic-host-services build + libcairo2-dev \ + libdbus-1-dev \ + libgirepository1.0-dev \ + libsystemd-dev \ + pkg-config + +# Build fix for ARMHF buster libsairedis +{%- if CONFIGURED_ARCH == "armhf" %} + # Install doxygen build dependency packages + RUN apt install -y libxapian-dev yui-compressor libclang-3.9-dev texlive-extra-utils \ + texlive-font-utils rdfind llvm-6.0-dev libclang-6.0-dev sassc + + # Update doxygen with 64bit file offset patch + RUN dget -u http://deb.debian.org/debian/pool/main/d/doxygen/doxygen_1.8.13-10.dsc && \ + cd doxygen-1.8.13 && \ + sed -i '56 a add_definitions(-D_FILE_OFFSET_BITS=64)' CMakeLists.txt && \ + DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b && \ + cd .. && \ + dpkg -i ./doxygen_1.8.13-10_armhf.deb && \ + rm -fr doxygen* + + # Aspell is unable to locate the language dictionaries. + # Re-installing aspell-en dictionary to fix it. + RUN apt-get install --reinstall -y aspell-en +{%- endif %} + +## Config dpkg +## install the configuration file if it’s currently missing +RUN sudo augtool --autosave "set /files/etc/dpkg/dpkg.cfg/force-confmiss" +## combined with confold: overwrite configuration files that you have not modified +RUN sudo augtool --autosave "set /files/etc/dpkg/dpkg.cfg/force-confdef" +## do not modify the current configuration file, the new version is installed with a .dpkg-dist suffix +RUN sudo augtool --autosave "set /files/etc/dpkg/dpkg.cfg/force-confold" + +# For linux build +RUN apt-get -y build-dep linux + +# For gobgp and telemetry build +RUN export VERSION=1.14.2 \ +{%- if CONFIGURED_ARCH == "armhf" %} + && wget https://storage.googleapis.com/golang/go$VERSION.linux-armv6l.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-armv6l.tar.gz \ +{%- elif CONFIGURED_ARCH == "arm64" %} + && wget https://storage.googleapis.com/golang/go$VERSION.linux-arm64.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-arm64.tar.gz \ +{%- else %} + && wget https://storage.googleapis.com/golang/go$VERSION.linux-amd64.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-amd64.tar.gz \ +{%- endif %} + && echo 'export GOROOT=/usr/local/go' >> /etc/bash.bashrc \ + && echo 'export PATH=$PATH:$GOROOT/bin' >> /etc/bash.bashrc \ + && rm go$VERSION.linux-*.tar.gz + +RUN pip3 install --upgrade pip +RUN pip2 install --upgrade 'pip<21' +RUN apt-get purge -y python-pip python3-pip python3-yaml + +# For building Python packages +RUN pip2 install setuptools==40.8.0 +RUN pip2 install wheel==0.35.1 +RUN pip3 install setuptools==49.6.00 +RUN pip3 install wheel==0.35.1 + +# For building sonic-utilities +RUN pip2 install fastentrypoints +RUN pip3 install fastentrypoints + +# For running Python unit tests +RUN pip2 install pytest-runner==4.4 +RUN pip3 install pytest-runner==5.2 +RUN pip2 install mockredispy==2.9.3 +RUN pip3 install mockredispy==2.9.3 + +# For Python 2 unit tests, we need 'mock'. The last version of 'mock' +# which supports Python 2 is 3.0.5. In Python 3, 'mock' is part of 'unittest' +# in the standard library +RUN pip2 install mock==3.0.5 + +# For p4 build +RUN pip2 install \ + ctypesgen==1.0.2 \ + crc16 + +# For sonic config engine testing +# Install pyangbind here, outside sonic-config-engine dependencies, as pyangbind causes enum34 to be installed. +# enum34 causes Python 're' package to not work properly as it redefines an incompatible enum.py module +# https://github.com/robshakir/pyangbind/issues/232 +RUN pip3 install pyangbind==0.8.1 +RUN pip3 uninstall -y enum34 + +# For templating +RUN pip2 install j2cli==0.3.10 + +# For sonic-mgmt-framework +RUN pip2 install "PyYAML==5.4.1" +RUN pip3 install "PyYAML==5.4.1" +RUN pip2 install "lxml==4.6.2" +RUN pip3 install "lxml==4.6.2" + +# For sonic-platform-common testing +RUN pip3 install redis + +# For vs image build +RUN pip2 install pexpect==4.6.0 +RUN pip3 install pexpect==4.8.0 + +# For sonic-swss-common testing +RUN pip2 install Pympler==0.8 +RUN pip3 install Pympler==0.8 + +# For sonic_yang_model build +RUN pip2 install pyang==2.1.1 +RUN pip3 install pyang==2.1.1 + +# For mgmt-framework build +RUN pip2 install mmh3==2.5.1 +RUN pip3 install mmh3==2.5.1 + +RUN apt-get install -y xsltproc + +# Install dependencies for isc-dhcp-relay build +RUN apt-get -y build-dep isc-dhcp + +# Install vim +RUN apt-get install -y vim + +# Install rsyslog +RUN apt-get install -y rsyslog + +RUN cd /usr/src/gtest && cmake . && make -C /usr/src/gtest + +RUN mkdir /var/run/sshd +EXPOSE 22 + +# Install depot-tools (for git-retry) +RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools +ENV PATH /usr/share/depot_tools:$PATH + +# Install docker engine 17.03.2~ce-0 inside docker and enable experimental feature +RUN apt-get update +RUN apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg2 \ + software-properties-common +{%- if CONFIGURED_ARCH == "armhf" %} + RUN update-ca-certificates --fresh +{%- endif %} +RUN curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - +RUN add-apt-repository \ + "deb [arch={{ CONFIGURED_ARCH }}] https://download.docker.com/linux/debian \ + $(lsb_release -cs) \ + stable" +RUN apt-get update +RUN apt-get install -y docker-ce=5:18.09.5~3-0~debian-buster docker-ce-cli=5:18.09.5~3-0~debian-buster +RUN echo "DOCKER_OPTS=\"--experimental --storage-driver=vfs\"" >> /etc/default/docker +RUN update-alternatives --set iptables /usr/sbin/iptables-legacy + +# Install m2crypto package, needed by SWI tools +RUN pip2 install m2crypto==0.36.0 + +# Install swi tools +RUN pip3 install git+https://github.com/aristanetworks/swi-tools.git@bead66bf261770237f7dd21ace3774ba04a017e9 + +{% if CONFIGURED_ARCH != "amd64" -%} +# Install node.js for azure pipeline +RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - +RUN apt-get install -y nodejs + +# Tell azure pipeline to use node.js in the docker +LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/bin/node" +{% endif -%} diff --git a/sonic-slave-buster/Dockerfile.user.j2 b/sonic-slave-buster/Dockerfile.user.j2 new file mode 100644 index 000000000000..a1181524bd91 --- /dev/null +++ b/sonic-slave-buster/Dockerfile.user.j2 @@ -0,0 +1,34 @@ +ARG slave_base_tag_ref=latest +{%- if CONFIGURED_ARCH == "amd64" %} +FROM sonic-slave-buster:${slave_base_tag_ref} +{%- else %} +FROM sonic-slave-buster-{{ CONFIGURED_ARCH }}:${slave_base_tag_ref} +{%- endif %} + +# Add user +ARG user +ARG uid +ARG guid +ARG hostname + +ENV BUILD_HOSTNAME $hostname +ENV USER $user + +RUN groupadd -f -r -g $guid g$user + +RUN useradd $user -l -u $uid -g $guid -d /var/$user -m -s /bin/bash + +RUN gpasswd -a $user docker + +# Config git for stg +RUN su $user -c "git config --global user.name $user" +RUN su $user -c "git config --global user.email $user@contoso.com" + +COPY sonic-jenkins-id_rsa.pub /var/$user/.ssh/authorized_keys2 +RUN chown $user /var/$user/.ssh -R +RUN chmod go= /var/$user/.ssh -R + +# Add user to sudoers +RUN echo "$user ALL=(ALL) NOPASSWD:ALL" >>/etc/sudoers + +USER $user diff --git a/sonic-slave-buster/no-check-valid-until b/sonic-slave-buster/no-check-valid-until new file mode 100644 index 000000000000..c7c25d017f7f --- /dev/null +++ b/sonic-slave-buster/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/sonic-slave-buster/sonic-jenkins-id_rsa.pub b/sonic-slave-buster/sonic-jenkins-id_rsa.pub new file mode 100644 index 000000000000..2a19c9e70d3c --- /dev/null +++ b/sonic-slave-buster/sonic-jenkins-id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC769BQUJVeSIOyPsN4/Vo8xTqXQ6RI7ysVyCw/ABP3FIxf+fxmtm8t/Nbp9hq0uLHOjCw8UQbJ+XltsThFWJfH6RJY5NbfvwG7nUDjfjjp+SGEIHaVgIlpiuqiPbZ6QMjZ8Q0Sgi5p5ts1xe/4TFThwOJBHmhwydD5nk3BH7P3DDwlOCov5gjM40uMZJkketlO83zGG+25zu7O0hfDVt1vyK9bNWAhhPmGc79zdetfeFCxjimsff2m31B1KuVXiT5PDB1w+BSrUK6nNzJubnYCRgjg4prVTjA50EhlT2P7EoJAbW3TnTq8vUDkcstsGe/HZpfIB1VHBX97u4fAfGJZ root@acs-jenkins diff --git a/sonic-slave-jessie/Dockerfile.j2 b/sonic-slave-jessie/Dockerfile.j2 new file mode 100644 index 000000000000..f103dfb789b9 --- /dev/null +++ b/sonic-slave-jessie/Dockerfile.j2 @@ -0,0 +1,346 @@ +{%- if CONFIGURED_ARCH == "armhf" -%} +FROM multiarch/debian-debootstrap:armhf-jessie +{%- elif CONFIGURED_ARCH == "arm64" -%} +FROM multiarch/debian-debootstrap:arm64-jessie +{%- else -%} +FROM debian:jessie +{%- endif %} + +MAINTAINER johnar@microsoft.com + +COPY ["no-check-valid-until", "/etc/apt/apt.conf.d/"] + +## Remove retired jessie-updates repo +RUN sed -i '/http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + +RUN echo "deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ jessie main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian/ jessie main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ jessie/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ jessie/updates main contrib non-free" >> /etc/apt/sources.list + +{% if CONFIGURED_ARCH == "armhf" %} +RUN echo "deb [arch=armhf] http://deb.debian.org/debian jessie main contrib non-free" > /etc/apt/sources.list && \ + echo "deb-src [arch=armhf] http://deb.debian.org/debian jessie main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=armhf] http://security.debian.org jessie/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=armhf] http://security.debian.org jessie/updates main contrib non-free" >> /etc/apt/sources.list +{% elif CONFIGURED_ARCH == "arm64" %} +RUN echo "deb [arch=arm64] http://archive.debian.org/debian jessie main contrib non-free" > /etc/apt/sources.list && \ + echo "deb-src [arch=arm64] http://archive.debian.org/debian jessie main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=arm64] http://archive.debian.org/debian jessie-backports main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=arm64] http://archive.debian.org/debian jessie-backports main contrib non-free" >> /etc/apt/sources.list +{% endif %} + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y \ + apt-utils \ + default-jre-headless \ + openssh-server \ + curl \ + wget \ + unzip \ + git \ + build-essential \ + libtool \ + lintian \ + sudo \ + dh-make \ + dh-exec \ + kmod \ + libtinyxml2-2 \ + libboost-program-options1.55-dev \ + libtinyxml2-dev \ + python \ + python-pip \ + libncurses5-dev \ + texinfo \ + dh-autoreconf \ + python3-pip \ + doxygen \ + devscripts \ + git-buildpackage \ + perl-modules \ + libswitch-perl \ + dh-systemd \ +# For quagga build + libreadline-dev \ + texlive-latex-base \ + texlive-generic-recommended \ + texlive-fonts-recommended \ + libpam0g-dev \ + libpam-dev \ + libcap-dev \ + imagemagick \ + ghostscript \ + groff \ + libpcre3-dev \ + gawk \ + chrpath \ +# For frr build + libc-ares-dev \ + hardening-wrapper \ + libsnmp-dev \ + libjson0 \ + libjson0-dev \ + libsystemd-dev \ + python-ipaddr \ + install-info \ +# For libnl3 (local) build + cdbs \ +# For SAI meta build + libxml-simple-perl \ + graphviz \ + aspell \ +# For linux build + bc \ + fakeroot \ + build-essential \ + devscripts \ + quilt \ + stgit \ +# For platform-modules build + module-assistant \ +# For thrift build\ + gem2deb \ + libboost-all-dev \ + libevent-dev \ + libglib2.0-dev \ + libqt4-dev \ + python-all-dev \ + python-twisted \ + php5-dev \ + phpunit \ + libbit-vector-perl \ + openjdk-7-jdk \ + javahelper \ + maven-debian-helper \ + ant \ + libmaven-ant-tasks-java \ + libhttpclient-java \ + libslf4j-java \ + libservlet3.1-java \ + qt5-default \ + pkg-php-tools \ +# For mellanox sdk build + libpcre3 \ + libpcre3-dev \ + byacc \ + flex \ + libglib2.0-dev \ + bison \ + expat \ + libexpat1-dev \ + dpatch \ + libdb-dev \ + iptables-dev \ + swig \ + ctags \ +# For mellanox sai build + libtool-bin \ + libxml2-dev \ +# For BFN sdk build + libusb-1.0-0-dev \ + libcurl3-nss-dev \ + libunwind8-dev \ + telnet \ + libc-ares2 \ + libgoogle-perftools4 \ +# For build image + cpio \ + squashfs-tools \ + zip \ +{%- if CONFIGURED_ARCH == "amd64" %} +# For broadcom sdk build + linux-compiler-gcc-4.9-x86 \ +{%- endif %} + linux-kbuild-3.16 \ +# teamd build + libdaemon-dev \ + libdbus-1-dev \ + libjansson-dev \ +# For cavium sdk build + libpcap-dev \ + dnsutils \ + libusb-dev \ +# For debian image reconfiguration + augeas-tools \ +# For p4 build + libyaml-dev \ + libevent-dev \ + libjudy-dev \ + libedit-dev \ + libnanomsg-dev \ + python-stdeb \ +# For redis build + libjemalloc-dev \ +# For mft kernel module build + dkms \ +# For Jenkins static analysis, unit testing and code coverage + cppcheck \ + clang \ + pylint \ + gcovr \ + python-pytest=2.6.3* \ + python3-pytest=2.6.3* \ + python-pytest-cov \ + python3-pytest-cov \ + python-parse \ +# For snmpd + libmysqlclient-dev \ + libmysqld-dev \ + libperl-dev \ + libpci-dev \ + libpci3 \ + libsensors4 \ + libsensors4-dev \ + libwrap0-dev \ +# For mpdecimal + docutils-common \ + libjs-sphinxdoc \ + libjs-underscore \ + python-docutils \ + python-markupsafe \ + python-pygments \ + python-roman \ + sphinx-common \ +# For sonic config engine testing + python-lxml \ + python-netaddr \ + python-ipaddr \ + python-yaml \ +# For lockfile + procmail \ +# For gtest + libgtest-dev \ + cmake \ +# For pam_tacplus build + autoconf-archive \ +# For python-based swsscommon + swig3.0 \ +# For iproute2 + cm-super-minimal \ + libatm1-dev \ + libelf-dev \ + libmnl-dev \ + libselinux1-dev \ + linuxdoc-tools \ + lynx \ + texlive-latex-extra \ + texlive-latex-recommended \ +# For bash + texi2html \ +# For initramfs + bash-completion \ +{% if CONFIGURED_ARCH == "amd64" -%} +# For sonic vs image build + dosfstools \ + qemu-kvm \ + libvirt-bin +{%- else -%} + bash-completion +{%- endif %} + +# For jenkins slave +# RUN apt-get -y install ca-certificates-java=20161107~bpo8+1 openjdk-8-jdk + +# For linux build +{% if CONFIGURED_ARCH != "arm64" %} +RUN apt-get -y build-dep linux +{%- endif %} + +# For gobgp and telemetry build +RUN export VERSION=1.14.2 \ +{%- if CONFIGURED_ARCH == "armhf" %} + && wget https://storage.googleapis.com/golang/go$VERSION.linux-armv6l.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-armv6l.tar.gz \ +{%- elif CONFIGURED_ARCH == "arm64" %} + && wget https://storage.googleapis.com/golang/go$VERSION.linux-arm64.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-arm64.tar.gz \ +{%- else %} + && wget https://storage.googleapis.com/golang/go$VERSION.linux-amd64.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-amd64.tar.gz \ +{%- endif %} + && echo 'export GOROOT=/usr/local/go' >> /etc/bash.bashrc \ + && echo 'export PATH=$PATH:$GOROOT/bin' >> /etc/bash.bashrc \ + && rm go$VERSION.linux-*.tar.gz + +# Upgrade pip2 +# Note: use pip2 specific version so jinja2 2.10 will install +RUN python2 -m pip install -U pip==9.0.3 + +# For p4 build +RUN pip install \ + ctypesgen==0.r125 \ + crc16 + +# For sonic config engine testing +RUN pip install pyangbind==0.6.0 +# Note: force upgrade debian packaged jinja2, if installed +RUN pip install --force-reinstall --upgrade "jinja2>=2.10" + +# For templating (requiring jinja2) +RUN pip install j2cli==0.3.10 + +# For vs image build +RUN pip install pexpect==4.6.0 + +# For sonic-utilities build +RUN pip install mockredispy==2.9.3 +RUN pip install pytest-runner==4.4 +RUN pip install setuptools==40.8.0 + +# For sonic-swss-common testing +RUN pip install Pympler==0.8 + +# Install dependencies for isc-dhcp-relay build +RUN apt-get -y build-dep isc-dhcp + +# Install vim +RUN apt-get install -y vim + +# Install rsyslog +RUN apt-get install -y rsyslog + +RUN cd /usr/src/gtest && cmake . && make -C /usr/src/gtest + +RUN mkdir /var/run/sshd +EXPOSE 22 + +# Install depot-tools (for git-retry) +RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools +ENV PATH /usr/share/depot_tools:$PATH + +# Install docker engine 17.03.2~ce-0 inside docker and enable experimental feature +RUN apt-get update +RUN apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg2 \ + software-properties-common +RUN curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - +RUN add-apt-repository \ + "deb [arch={{ CONFIGURED_ARCH }}] https://download.docker.com/linux/debian \ + $(lsb_release -cs) \ + stable" +RUN apt-get update +{%- if CONFIGURED_ARCH == "amd64" %} +RUN apt-get install -y docker-ce=17.03.2~ce-0~debian-jessie +{%- elif CONFIGURED_ARCH == "arm64" %} +RUN apt-get install -y docker-ce=18.03.1~ce-0~debian +{%- elif CONFIGURED_ARCH == "armhf" %} +RUN apt-get install -y docker-ce=18.06.3~ce~3-0~debian +{%- endif %} +RUN echo "DOCKER_OPTS=\"--experimental --storage-driver=vfs\"" >> /etc/default/docker + +# For jenkins slave +RUN echo "deb [arch={{ CONFIGURED_ARCH }}] http://archive.debian.org/debian jessie-backports main" >> /etc/apt/sources.list +RUN apt-get -o Acquire::Check-Valid-Until=false update +RUN apt-get -y -o Acquire::Check-Valid-Until=false install ca-certificates-java=20161107~bpo8+1 openjdk-8-jdk + +# Install m2crypto package, needed by SWI tools +RUN pip install m2crypto==0.36.0 + +# Install swi tools +RUN python -m pip install git+https://github.com/aristanetworks/swi-tools.git@d51761ec0bb93c73039233f3c01ed48235ffad00 diff --git a/sonic-slave-jessie/Dockerfile.user.j2 b/sonic-slave-jessie/Dockerfile.user.j2 new file mode 100644 index 000000000000..4f9ed9da659b --- /dev/null +++ b/sonic-slave-jessie/Dockerfile.user.j2 @@ -0,0 +1,34 @@ +ARG slave_base_tag_ref=latest +{%- if CONFIGURED_ARCH == "amd64" %} +FROM sonic-slave-jessie:${slave_base_tag_ref} +{%- else %} +FROM sonic-slave-jessie-{{ CONFIGURED_ARCH }}:${slave_base_tag_ref} +{%- endif %} + +# Add user +ARG user +ARG uid +ARG guid +ARG hostname + +ENV BUILD_HOSTNAME $hostname +ENV USER $user + +RUN groupadd -f -r -g $guid g$user + +RUN useradd $user -l -u $uid -g $guid -d /var/$user -m -s /bin/bash + +RUN gpasswd -a $user docker + +# Config git for stg +RUN su $user -c "git config --global user.name $user" +RUN su $user -c "git config --global user.email $user@contoso.com" + +COPY sonic-jenkins-id_rsa.pub /var/$user/.ssh/authorized_keys2 +RUN chown $user /var/$user/.ssh -R +RUN chmod go= /var/$user/.ssh -R + +# Add user to sudoers +RUN echo "$user ALL=(ALL) NOPASSWD:ALL" >>/etc/sudoers + +USER $user diff --git a/sonic-slave-jessie/no-check-valid-until b/sonic-slave-jessie/no-check-valid-until new file mode 100644 index 000000000000..c7c25d017f7f --- /dev/null +++ b/sonic-slave-jessie/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/sonic-slave-jessie/sonic-jenkins-id_rsa.pub b/sonic-slave-jessie/sonic-jenkins-id_rsa.pub new file mode 100644 index 000000000000..2a19c9e70d3c --- /dev/null +++ b/sonic-slave-jessie/sonic-jenkins-id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC769BQUJVeSIOyPsN4/Vo8xTqXQ6RI7ysVyCw/ABP3FIxf+fxmtm8t/Nbp9hq0uLHOjCw8UQbJ+XltsThFWJfH6RJY5NbfvwG7nUDjfjjp+SGEIHaVgIlpiuqiPbZ6QMjZ8Q0Sgi5p5ts1xe/4TFThwOJBHmhwydD5nk3BH7P3DDwlOCov5gjM40uMZJkketlO83zGG+25zu7O0hfDVt1vyK9bNWAhhPmGc79zdetfeFCxjimsff2m31B1KuVXiT5PDB1w+BSrUK6nNzJubnYCRgjg4prVTjA50EhlT2P7EoJAbW3TnTq8vUDkcstsGe/HZpfIB1VHBX97u4fAfGJZ root@acs-jenkins diff --git a/sonic-slave-stretch/Dockerfile.j2 b/sonic-slave-stretch/Dockerfile.j2 new file mode 100644 index 000000000000..103a9cd77831 --- /dev/null +++ b/sonic-slave-stretch/Dockerfile.j2 @@ -0,0 +1,444 @@ +{%- if CONFIGURED_ARCH == "armhf" %} +FROM multiarch/debian-debootstrap:armhf-stretch +{%- elif CONFIGURED_ARCH == "arm64" %} +FROM multiarch/debian-debootstrap:arm64-stretch +{%- else -%} +FROM debian:stretch +{%- endif %} + +MAINTAINER gulv@microsoft.com + +COPY ["no-check-valid-until", "/etc/apt/apt.conf.d/"] + +RUN echo "deb [arch=amd64] http://debian-archive.trafficmanager.net/debian/ stretch main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian/ stretch main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ stretch/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=amd64] http://debian-archive.trafficmanager.net/debian-security/ stretch/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=amd64] http://debian-archive.trafficmanager.net/debian stretch-backports main" >> /etc/apt/sources.list && \ + echo "deb [arch=amd64] http://packages.trafficmanager.net/debian/debian stretch main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=amd64] http://packages.trafficmanager.net/debian/debian stretch-updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=amd64] http://packages.microsoft.com/debian/9/prod stretch main" >> /etc/apt/sources.list + +{%- if CONFIGURED_ARCH == "armhf" %} +RUN echo "deb [arch=armhf] http://deb.debian.org/debian stretch main contrib non-free" > /etc/apt/sources.list && \ + echo "deb-src [arch=armhf] http://deb.debian.org/debian stretch main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=armhf] http://deb.debian.org/debian stretch-updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=armhf] http://deb.debian.org/debian stretch-updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=armhf] http://security.debian.org stretch/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=armhf] http://security.debian.org stretch/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo 'deb [arch=armhf] http://ftp.debian.org/debian stretch-backports main' >> /etc/apt/sources.list && \ + echo "deb [arch=armhf] http://packages.trafficmanager.net/debian/debian stretch main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=armhf] http://packages.trafficmanager.net/debian/debian stretch-updates main contrib non-free" >> /etc/apt/sources.list +{%- elif CONFIGURED_ARCH == "arm64" %} +RUN echo "deb [arch=arm64] http://deb.debian.org/debian stretch main contrib non-free" > /etc/apt/sources.list && \ + echo "deb-src [arch=arm64] http://deb.debian.org/debian stretch main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=arm64] http://deb.debian.org/debian stretch-updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=arm64] http://deb.debian.org/debian stretch-updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=arm64] http://security.debian.org stretch/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb-src [arch=arm64] http://security.debian.org stretch/updates main contrib non-free" >> /etc/apt/sources.list && \ + echo 'deb [arch=arm64] http://ftp.debian.org/debian stretch-backports main' >> /etc/apt/sources.list && \ + echo "deb [arch=arm64] http://packages.trafficmanager.net/debian/debian stretch main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb [arch=arm64] http://packages.trafficmanager.net/debian/debian stretch-updates main contrib non-free" >> /etc/apt/sources.list +{%- endif %} + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y \ + apt-utils \ + default-jre-headless \ + openssh-server \ + curl \ + wget \ + unzip \ + git \ + build-essential \ + libtool \ + lintian \ + sudo \ + dh-make \ + dh-exec \ + kmod \ + libtinyxml2-4 \ + libboost-program-options1.62-dev \ + libtinyxml2-dev \ + python \ + python-pip \ + python3-pip \ + libncurses5-dev \ + texinfo \ + dh-autoreconf \ + doxygen \ + devscripts \ + git-buildpackage \ + perl-modules \ + libswitch-perl \ + dh-systemd \ + libzmq5 \ + libzmq3-dev \ +# For quagga build + libreadline-dev \ + texlive-latex-base \ + texlive-generic-recommended \ + texlive-fonts-recommended \ + libpam0g-dev \ + libpam-dev \ + libcap-dev \ + imagemagick \ + ghostscript \ + groff \ + libpcre3-dev \ + gawk \ + chrpath \ +# For frr build + libc-ares-dev \ + libsnmp-dev \ + libjson-c3 \ + libjson-c-dev \ + libsystemd-dev \ + python-ipaddr \ + libcmocka-dev \ + python3-all-dev \ + python3-all-dbg \ + install-info \ + logrotate \ +# For libnl3 (local) build + cdbs \ +# For SAI meta build + libxml-simple-perl \ + graphviz \ + aspell \ +# For linux build + bc \ + fakeroot \ + build-essential \ + devscripts \ + quilt \ + stgit \ +# For platform-modules build + module-assistant \ +# For thrift build\ + gem2deb \ + libboost-all-dev \ + libevent-dev \ + libglib2.0-dev \ + libqt4-dev \ + python-all-dev \ + python-twisted \ + phpunit \ + libbit-vector-perl \ + openjdk-8-jdk \ + javahelper \ + maven-debian-helper \ + ant \ + libmaven-ant-tasks-java \ + libhttpclient-java \ + libslf4j-java \ + libservlet3.1-java \ + qt5-default \ + pkg-php-tools \ +# For mellanox sdk build + libpcre3 \ + libpcre3-dev \ + byacc \ + flex \ + libglib2.0-dev \ + bison \ + expat \ + libexpat1-dev \ + dpatch \ + libdb-dev \ + iptables-dev \ + ctags \ +# For mellanox sai build + libtool-bin \ + libxml2-dev \ +# For BFN sdk build + libusb-1.0-0-dev \ + libcurl3-nss-dev \ + libunwind8-dev \ + telnet \ + libc-ares2 \ + libgoogle-perftools4 \ +# For build image + cpio \ + squashfs-tools \ + zip \ +# For broadcom sdk build +{%- if CONFIGURED_ARCH == "amd64" %} + linux-compiler-gcc-6-x86 \ +{%- endif %} +{%- if CONFIGURED_ARCH == "armhf" %} + linux-compiler-gcc-6-arm \ +{%- endif %} + linux-kbuild-4.9 \ +# teamd build + libdaemon-dev \ + libdbus-1-dev \ + libjansson-dev \ +# For cavium sdk build + libpcap-dev \ + dnsutils \ + libusb-dev \ +# For debian image reconfiguration + augeas-tools \ +# For p4 build + libyaml-dev \ + libevent-dev \ + libjudy-dev \ + libedit-dev \ + libnanomsg-dev \ + python-stdeb \ +# For redis build + libjemalloc-dev \ + liblua5.1-0-dev \ + lua-bitop-dev \ + lua-cjson-dev \ +# For mft kernel module build + dkms \ +# For Jenkins static analysis, unit testing and code coverage + cppcheck \ + clang \ + pylint \ + python-pytest \ + gcovr \ + python-pytest-cov \ + python-parse \ +# For snmpd + default-libmysqlclient-dev \ + libssl1.0-dev \ + libperl-dev \ + libpci-dev \ + libpci3 \ + libsensors4 \ + libsensors4-dev \ + libwrap0-dev \ +# For lldpd + debhelper \ + autotools-dev \ + libbsd-dev \ + pkg-config \ + check \ +# For mpdecimal + docutils-common \ + libjs-sphinxdoc \ + libjs-underscore \ + python-docutils \ + python-jinja2 \ + python-markupsafe \ + python-pygments \ + python-roman \ + python-sphinx \ + sphinx-common \ + python3-sphinx \ +# For sonic config engine testing + python-dev \ +{%- if CONFIGURED_ARCH == "armhf" or CONFIGURED_ARCH == "arm64" %} + libxslt-dev \ +{%- endif %} +# For lockfile + procmail \ +# For pam_tacplus build + autoconf-archive \ +# For iproute2 + cm-super-minimal \ + libatm1-dev \ + libelf-dev \ + libmnl-dev \ + libselinux1-dev \ + linuxdoc-tools \ + lynx \ + texlive-latex-extra \ + texlive-latex-recommended \ + iproute2 \ +# For bash + texi2html \ +# For initramfs + bash-completion \ +{%- if CONFIGURED_ARCH == "amd64" %} +# For sonic vs image build + dosfstools \ + qemu-kvm \ + libvirt-clients \ +{%- endif %} +# For lm-sensors + librrd8 \ + librrd-dev \ + rrdtool \ +# For smartmontools 6.6-1 + automake1.11 \ + libselinux1-dev \ +# For kdump-tools + liblzo2-dev \ +# For iptables + libnetfilter-conntrack-dev \ + libnftnl-dev \ +# For SAI3.7 + protobuf-compiler \ + libprotobuf-dev \ + xxd \ +# For DHCP Monitor tool + libexplain-dev \ + libevent-dev \ +# For libyang + swig \ +# For sonic-mgmt-framework + autoconf \ + m4 \ + libxml2-utils \ + xsltproc \ + python-lxml \ + libexpat1-dev + +## Config dpkg +## install the configuration file if it’s currently missing +RUN sudo augtool --autosave "set /files/etc/dpkg/dpkg.cfg/force-confmiss" +## combined with confold: overwrite configuration files that you have not modified +RUN sudo augtool --autosave "set /files/etc/dpkg/dpkg.cfg/force-confdef" +## do not modify the current configuration file, the new version is installed with a .dpkg-dist suffix +RUN sudo augtool --autosave "set /files/etc/dpkg/dpkg.cfg/force-confold" + +# For smartmontools 6.6-1 +RUN apt-get -t stretch-backports install -y debhelper + +# For linux build +RUN apt-get -y build-dep linux + +# For gobgp and telemetry build +RUN export VERSION=1.14.2 \ +{%- if CONFIGURED_ARCH == "armhf" %} + && wget https://storage.googleapis.com/golang/go$VERSION.linux-armv6l.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-armv6l.tar.gz \ +{%- elif CONFIGURED_ARCH == "arm64" %} + && wget https://storage.googleapis.com/golang/go$VERSION.linux-arm64.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-arm64.tar.gz \ +{%- else %} + && wget https://storage.googleapis.com/golang/go$VERSION.linux-amd64.tar.gz \ + && tar -C /usr/local -xzf go$VERSION.linux-amd64.tar.gz \ +{%- endif %} + && echo 'export GOROOT=/usr/local/go' >> /etc/bash.bashrc \ + && echo 'export PATH=$PATH:$GOROOT/bin' >> /etc/bash.bashrc \ + && rm go$VERSION.linux-*.tar.gz + +RUN pip3 install --upgrade pip +RUN pip2 install --upgrade 'pip<21' +RUN apt-get purge -y python-pip python3-pip + +# For p4 build +RUN pip2 install \ + ctypesgen==0.r125 \ + crc16 + +# Note: Stick with Jinja2 2.x branch as the 3.x dropped support for Python 2.7 +RUN pip2 install --force-reinstall --upgrade "Jinja2<3.0.0" + +# For sonic config engine testing +# Install pyangbind here, outside sonic-config-engine dependencies, as pyangbind causes enum34 to be installed. +# enum34 causes Python 're' package to not work properly as it redefines an incompatible enum.py module +# https://github.com/robshakir/pyangbind/issues/232 +RUN pip3 install pyangbind==0.8.1 +RUN pip3 uninstall -y enum34 + +# For templating +RUN pip2 install j2cli==0.3.10 + +# For sonic snmpagent mock testing +RUN pip3 install mockredispy==2.9.3 + +# For sonic-mgmt-framework +RUN pip2 install "PyYAML==5.3.1" +RUN pip3 install "PyYAML==5.3.1" +RUN pip2 install "lxml==4.6.2" +RUN pip3 install "lxml==4.6.2" + + +# For sonic-platform-common testing +RUN pip3 install redis + +# For vs image build +RUN pip2 install pexpect==4.6.0 + +# For sonic-utilities build +RUN pip2 install mockredispy==2.9.3 +RUN pip2 install pytest-runner==4.4 +RUN pip2 install setuptools==40.8.0 + +# For sonic-swss-common testing +RUN pip2 install Pympler==0.8 + +# For sonic_yang_model build +RUN pip2 install pyang==2.1.1 + +# For mgmt-framework build +RUN pip2 install mmh3 + +# Install dependencies for isc-dhcp-relay build +RUN apt-get -y build-dep isc-dhcp + +# Install vim +RUN apt-get install -y vim + +# Install rsyslog +RUN apt-get install -y rsyslog + +RUN apt-get install -y libgtest-dev +RUN apt-get install -y libarchive13 librhash0 +RUN apt-get -t stretch-backports install -y libuv1 +# Install cmake/cmake-data 3.13.2-1_bpo9+1 +# latest cmake 3.16.3 break the build libyang 1.0.73 +RUN wget -O cmake-data_3.13.2-1_bpo9+1_all.deb "https://sonicstorage.blob.core.windows.net/packages/cmake/cmake-data_3.13.2-1_bpo9%2B1_all.deb?st=2020-03-27T02%3A22%3A24Z&se=2100-03-26T19%3A00%3A00Z&sp=rl&sv=2018-03-28&sr=b&sig=Xby%2Bm3OZOjPB%2FSlDbHD65yDcPzAgoys%2FA3vK8RB4BzA%3D" +RUN dpkg -i cmake-data_3.13.2-1_bpo9+1_all.deb || apt-get install -f +{% if CONFIGURED_ARCH == "armhf" %} +RUN wget -O cmake_3.13.2-1_bpo9+1_armhf.deb "https://sonicstorage.blob.core.windows.net/packages/cmake/cmake_3.13.2-1_bpo9%2B1_armhf.deb?st=2020-03-27T02%3A29%3A41Z&se=2100-03-26T19%3A00%3A00Z&sp=rl&sv=2018-03-28&sr=b&sig=sWt7kxrFumn020d2GeutGJ716cuQsFwmAmgU%2BJ0kqnk%3D" +RUN dpkg -i cmake_3.13.2-1_bpo9+1_armhf.deb || apt-get install -f +{% elif CONFIGURED_ARCH == "arm64" %} +RUN wget -O cmake_3.13.2-1_bpo9+1_arm64.deb "https://sonicstorage.blob.core.windows.net/packages/cmake/cmake_3.13.2-1_bpo9%2B1_arm64.deb?st=2020-03-27T02%3A28%3A38Z&se=2100-03-26T19%3A00%3A00Z&sp=rl&sv=2018-03-28&sr=b&sig=rrHMkLi29aI8yH6s52ILCY8VcEbNFrzYT2DmC5RwOgs%3D" +RUN dpkg -i cmake_3.13.2-1_bpo9+1_arm64.deb || apt-get install -f +{% else %} +RUN wget -O cmake_3.13.2-1_bpo9+1_amd64.deb "https://sonicstorage.blob.core.windows.net/packages/cmake/cmake_3.13.2-1_bpo9%2B1_amd64.deb?st=2020-03-27T02%3A27%3A21Z&se=2100-03-26T19%3A00%3A00Z&sp=rl&sv=2018-03-28&sr=b&sig=4MvmmDBQuicFEJYakLm7xCNU19yJ8GIP4ankFSnITKY%3D" +RUN dpkg -i cmake_3.13.2-1_bpo9+1_amd64.deb || apt-get install -f +{% endif %} +RUN cd /usr/src/gtest && cmake . && make -C /usr/src/gtest + +RUN mkdir /var/run/sshd +EXPOSE 22 + +# Install depot-tools (for git-retry) +RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools +ENV PATH /usr/share/depot_tools:$PATH + +# Install docker engine 17.03.2~ce-0 inside docker and enable experimental feature +RUN apt-get update +RUN apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg2 \ + software-properties-common +RUN curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - +RUN add-apt-repository \ + "deb [arch={{ CONFIGURED_ARCH }}] https://download.docker.com/linux/debian \ + $(lsb_release -cs) \ + stable" +RUN apt-get update +{%- if CONFIGURED_ARCH == "amd64" %} +RUN apt-get install -y docker-ce=5:18.09.5~3-0~debian-stretch docker-ce-cli=5:18.09.5~3-0~debian-stretch +{%- else %} +RUN apt-get install -y docker-ce=18.06.3~ce~3-0~debian +{%- endif %} +RUN echo "DOCKER_OPTS=\"--experimental --storage-driver=vfs\"" >> /etc/default/docker + +# Install m2crypto package, needed by SWI tools +RUN pip install m2crypto==0.36.0 + +# Install swi tools +RUN pip2 install git+https://github.com/aristanetworks/swi-tools.git@d51761ec0bb93c73039233f3c01ed48235ffad00 + +{% if CONFIGURED_ARCH != "amd64" -%} +# Install node.js for azure pipeline +RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - +RUN apt-get install -y nodejs + +# Tell azure pipeline to use node.js in the docker +LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/bin/node" +{% endif -%} diff --git a/sonic-slave-stretch/Dockerfile.user.j2 b/sonic-slave-stretch/Dockerfile.user.j2 new file mode 100644 index 000000000000..8e94b7046ae3 --- /dev/null +++ b/sonic-slave-stretch/Dockerfile.user.j2 @@ -0,0 +1,34 @@ +ARG slave_base_tag_ref=latest +{%- if CONFIGURED_ARCH == "amd64" %} +FROM sonic-slave-stretch:${slave_base_tag_ref} +{%- else %} +FROM sonic-slave-stretch-{{ CONFIGURED_ARCH }}:${slave_base_tag_ref} +{%- endif %} + +# Add user +ARG user +ARG uid +ARG guid +ARG hostname + +ENV BUILD_HOSTNAME $hostname +ENV USER $user + +RUN groupadd -f -r -g $guid g$user + +RUN useradd $user -l -u $uid -g $guid -d /var/$user -m -s /bin/bash + +RUN gpasswd -a $user docker + +# Config git for stg +RUN su $user -c "git config --global user.name $user" +RUN su $user -c "git config --global user.email $user@contoso.com" + +COPY sonic-jenkins-id_rsa.pub /var/$user/.ssh/authorized_keys2 +RUN chown $user /var/$user/.ssh -R +RUN chmod go= /var/$user/.ssh -R + +# Add user to sudoers +RUN echo "$user ALL=(ALL) NOPASSWD:ALL" >>/etc/sudoers + +USER $user diff --git a/sonic-slave-stretch/no-check-valid-until b/sonic-slave-stretch/no-check-valid-until new file mode 100644 index 000000000000..c7c25d017f7f --- /dev/null +++ b/sonic-slave-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/sonic-slave-stretch/sonic-jenkins-id_rsa.pub b/sonic-slave-stretch/sonic-jenkins-id_rsa.pub new file mode 100644 index 000000000000..2a19c9e70d3c --- /dev/null +++ b/sonic-slave-stretch/sonic-jenkins-id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC769BQUJVeSIOyPsN4/Vo8xTqXQ6RI7ysVyCw/ABP3FIxf+fxmtm8t/Nbp9hq0uLHOjCw8UQbJ+XltsThFWJfH6RJY5NbfvwG7nUDjfjjp+SGEIHaVgIlpiuqiPbZ6QMjZ8Q0Sgi5p5ts1xe/4TFThwOJBHmhwydD5nk3BH7P3DDwlOCov5gjM40uMZJkketlO83zGG+25zu7O0hfDVt1vyK9bNWAhhPmGc79zdetfeFCxjimsff2m31B1KuVXiT5PDB1w+BSrUK6nNzJubnYCRgjg4prVTjA50EhlT2P7EoJAbW3TnTq8vUDkcstsGe/HZpfIB1VHBX97u4fAfGJZ root@acs-jenkins diff --git a/src/bash/.gitignore b/src/bash/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/bash/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/bash/Makefile b/src/bash/Makefile new file mode 100644 index 000000000000..6576ff92e74a --- /dev/null +++ b/src/bash/Makefile @@ -0,0 +1,16 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + +MAIN_TARGET = bash_$(BASH_VERSION_FULL)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf bash-$(BASH_VERSION_MAJOR) + + dget -u https://launchpad.net/debian/+archive/primary/+sourcefiles/bash/$(BASH_VERSION_FULL)/bash_$(BASH_VERSION_FULL).dsc + + pushd bash-$(BASH_VERSION_MAJOR) + DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $* $(DEST)/ diff --git a/src/dhcpmon/.gitignore b/src/dhcpmon/.gitignore new file mode 100644 index 000000000000..9d09ae6b3f1a --- /dev/null +++ b/src/dhcpmon/.gitignore @@ -0,0 +1,5 @@ +debian/* +!debian/changelog +!debian/compat +!debian/control +!debian/rules diff --git a/src/dhcpmon/Makefile b/src/dhcpmon/Makefile new file mode 100644 index 000000000000..61cde376730b --- /dev/null +++ b/src/dhcpmon/Makefile @@ -0,0 +1,44 @@ +RM := rm -rf +DHCPMON_TARGET := dhcpmon +CP := cp +MKDIR := mkdir +CC := gcc +MV := mv + +# All of the sources participating in the build are defined here +-include src/subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +endif + +# Add inputs and outputs from these tool invocations to the build variables + +# All Target +all: sonic-dhcpmon + +# Tool invocations +sonic-dhcpmon: $(OBJS) $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C Linker' + $(CC) -o "$(DHCPMON_TARGET)" $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +# Other Targets +install: + $(MKDIR) -p $(DESTDIR)/usr/sbin + $(MV) $(DHCPMON_TARGET) $(DESTDIR)/usr/sbin + +deinstall: + $(RM) $(DESTDIR)/usr/sbin/$(DHCPMON_TARGET) + $(RM) -rf $(DESTDIR)/usr/sbin + +clean: + -$(RM) $(EXECUTABLES)$(OBJS)$(C_DEPS) $(DHCPMON_TARGET) + -@echo ' ' + +.PHONY: all clean dependents diff --git a/src/dhcpmon/debian/changelog b/src/dhcpmon/debian/changelog new file mode 100644 index 000000000000..83b79d6d93bd --- /dev/null +++ b/src/dhcpmon/debian/changelog @@ -0,0 +1,5 @@ +sonic-dhcpmon (1.0.0-0) UNRELEASED; urgency=medium + + * Initial release. + + -- Tamer Ahmed Mon, 09 Dec 2019 12:00:00 -0700 diff --git a/src/dhcpmon/debian/compat b/src/dhcpmon/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/src/dhcpmon/debian/compat @@ -0,0 +1 @@ +9 diff --git a/src/dhcpmon/debian/control b/src/dhcpmon/debian/control new file mode 100644 index 000000000000..8623428462e3 --- /dev/null +++ b/src/dhcpmon/debian/control @@ -0,0 +1,16 @@ +Source: sonic-dhcpmon +Section: devel +Priority: optional +Maintainer: Tamer Ahmed +Build-Depends: debhelper (>= 8.0.0), + dh-systemd +Standards-Version: 3.9.3 +Homepage: https://github.com/Azure/sonic-buildimage +XS-Go-Import-Path: github.com/Azure/sonic-buildimage + +Package: sonic-dhcpmon +Architecture: any +Built-Using: ${misc:Built-Using} +Depends: libexplain51, + libevent-2.1-6 +Description: SONiC DHCP Monitor diff --git a/src/dhcpmon/debian/rules b/src/dhcpmon/debian/rules new file mode 100755 index 000000000000..00c628b6625f --- /dev/null +++ b/src/dhcpmon/debian/rules @@ -0,0 +1,7 @@ +#!/usr/bin/make -f + +DEB_CFLAGS_APPEND=-std=gnu11 +export DEB_CFLAGS_APPEND + +%: + dh $@ --parallel diff --git a/src/dhcpmon/objects.mk b/src/dhcpmon/objects.mk new file mode 100644 index 000000000000..c9b774a53921 --- /dev/null +++ b/src/dhcpmon/objects.mk @@ -0,0 +1,4 @@ +USER_OBJS := + +LIBS := -levent -lexplain + diff --git a/src/dhcpmon/src/dhcp_device.c b/src/dhcpmon/src/dhcp_device.c new file mode 100644 index 000000000000..f5cb705ee285 --- /dev/null +++ b/src/dhcpmon/src/dhcp_device.c @@ -0,0 +1,646 @@ +/** + * @file dhcp_device.c + * + * device (interface) module + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dhcp_device.h" + +/** Counter print width */ +#define DHCP_COUNTER_WIDTH 9 + +/** Start of Ether header of a captured frame */ +#define ETHER_START_OFFSET 0 +/** Start of IP header of a captured frame */ +#define IP_START_OFFSET (ETHER_START_OFFSET + ETHER_HDR_LEN) +/** Start of UDP header of a captured frame */ +#define UDP_START_OFFSET (IP_START_OFFSET + sizeof(struct ip)) +/** Start of DHCP header of a captured frame */ +#define DHCP_START_OFFSET (UDP_START_OFFSET + sizeof(struct udphdr)) +/** Start of DHCP Options segment of a captured frame */ +#define DHCP_OPTIONS_HEADER_SIZE 240 +/** Offset of DHCP GIADDR */ +#define DHCP_GIADDR_OFFSET 24 + +#define OP_LDHA (BPF_LD | BPF_H | BPF_ABS) /** bpf ldh Abs */ +#define OP_LDHI (BPF_LD | BPF_H | BPF_IND) /** bpf ldh Ind */ +#define OP_LDB (BPF_LD | BPF_B | BPF_ABS) /** bpf ldb Abs*/ +#define OP_JEQ (BPF_JMP | BPF_JEQ | BPF_K) /** bpf jeq */ +#define OP_JGT (BPF_JMP | BPF_JGT | BPF_K) /** bpf jgt */ +#define OP_RET (BPF_RET | BPF_K) /** bpf ret */ +#define OP_JSET (BPF_JMP | BPF_JSET | BPF_K) /** bpf jset */ +#define OP_LDXB (BPF_LDX | BPF_B | BPF_MSH) /** bpf ldxb */ + +/** Berkeley Packet Filter program for "udp and (port 67 or port 68)". + * This program is obtained using the following command tcpdump: + * `tcpdump -dd "udp and (port 67 or port 68)"` + */ +static struct sock_filter dhcp_bpf_code[] = { + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x0000000c}, // (000) ldh [12] + {.code = OP_JEQ, .jt = 0, .jf = 7, .k = 0x000086dd}, // (001) jeq #0x86dd jt 2 jf 9 + {.code = OP_LDB, .jt = 0, .jf = 0, .k = 0x00000014}, // (002) ldb [20] + {.code = OP_JEQ, .jt = 0, .jf = 18, .k = 0x00000011}, // (003) jeq #0x11 jt 4 jf 22 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x00000036}, // (004) ldh [54] + {.code = OP_JEQ, .jt = 15, .jf = 0, .k = 0x00000043}, // (005) jeq #0x43 jt 21 jf 6 + {.code = OP_JEQ, .jt = 14, .jf = 0, .k = 0x00000044}, // (006) jeq #0x44 jt 21 jf 7 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x00000038}, // (007) ldh [56] + {.code = OP_JEQ, .jt = 12, .jf = 11, .k = 0x00000043}, // (008) jeq #0x43 jt 21 jf 20 + {.code = OP_JEQ, .jt = 0, .jf = 12, .k = 0x00000800}, // (009) jeq #0x800 jt 10 jf 22 + {.code = OP_LDB, .jt = 0, .jf = 0, .k = 0x00000017}, // (010) ldb [23] + {.code = OP_JEQ, .jt = 0, .jf = 10, .k = 0x00000011}, // (011) jeq #0x11 jt 12 jf 22 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x00000014}, // (012) ldh [20] + {.code = OP_JSET, .jt = 8, .jf = 0, .k = 0x00001fff}, // (013) jset #0x1fff jt 22 jf 14 + {.code = OP_LDXB, .jt = 0, .jf = 0, .k = 0x0000000e}, // (014) ldxb 4*([14]&0xf) + {.code = OP_LDHI, .jt = 0, .jf = 0, .k = 0x0000000e}, // (015) ldh [x + 14] + {.code = OP_JEQ, .jt = 4, .jf = 0, .k = 0x00000043}, // (016) jeq #0x43 jt 21 jf 17 + {.code = OP_JEQ, .jt = 3, .jf = 0, .k = 0x00000044}, // (017) jeq #0x44 jt 21 jf 18 + {.code = OP_LDHI, .jt = 0, .jf = 0, .k = 0x00000010}, // (018) ldh [x + 16] + {.code = OP_JEQ, .jt = 1, .jf = 0, .k = 0x00000043}, // (019) jeq #0x43 jt 21 jf 20 + {.code = OP_JEQ, .jt = 0, .jf = 1, .k = 0x00000044}, // (020) jeq #0x44 jt 21 jf 22 + {.code = OP_RET, .jt = 0, .jf = 0, .k = 0x00040000}, // (021) ret #262144 + {.code = OP_RET, .jt = 0, .jf = 0, .k = 0x00000000}, // (022) ret #0 +}; + +/** Filter program socket struct */ +static struct sock_fprog dhcp_sock_bfp = { + .len = sizeof(dhcp_bpf_code) / sizeof(*dhcp_bpf_code), .filter = dhcp_bpf_code +}; + +/** Aggregate device of DHCP interfaces. It contains aggregate counters from + all interfaces + */ +static dhcp_device_context_t aggregate_dev = {0}; + +/** Monitored DHCP message type */ +static dhcp_message_type_t monitored_msgs[] = { + DHCP_MESSAGE_TYPE_DISCOVER, + DHCP_MESSAGE_TYPE_OFFER, + DHCP_MESSAGE_TYPE_REQUEST, + DHCP_MESSAGE_TYPE_ACK +}; + +/** Number of monitored DHCP message type */ +static uint8_t monitored_msg_sz = sizeof(monitored_msgs) / sizeof(*monitored_msgs); + +/** + * @code handle_dhcp_option_53(context, dhcp_option, dir, iphdr, dhcphdr); + * + * @brief handle the logic related to DHCP option 53 + * + * @param context Device (interface) context + * @param dhcp_option pointer to DHCP option buffer space + * @param dir packet direction + * @param iphdr pointer to packet IP header + * @param dhcphdr pointer to DHCP header + * + * @return none + */ +static void handle_dhcp_option_53(dhcp_device_context_t *context, + const u_char *dhcp_option, + dhcp_packet_direction_t dir, + struct ip *iphdr, + uint8_t *dhcphdr) +{ + in_addr_t giaddr; + switch (dhcp_option[2]) + { + // DHCP messages send by client + case DHCP_MESSAGE_TYPE_DISCOVER: + case DHCP_MESSAGE_TYPE_REQUEST: + case DHCP_MESSAGE_TYPE_DECLINE: + case DHCP_MESSAGE_TYPE_RELEASE: + case DHCP_MESSAGE_TYPE_INFORM: + giaddr = ntohl(dhcphdr[DHCP_GIADDR_OFFSET] << 24 | dhcphdr[DHCP_GIADDR_OFFSET + 1] << 16 | + dhcphdr[DHCP_GIADDR_OFFSET + 2] << 8 | dhcphdr[DHCP_GIADDR_OFFSET + 3]); + if ((context->vlan_ip == giaddr && context->is_uplink && dir == DHCP_TX) || + (!context->is_uplink && dir == DHCP_RX && iphdr->ip_dst.s_addr == INADDR_BROADCAST)) { + context->counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; + aggregate_dev.counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; + } + break; + // DHCP messages send by server + case DHCP_MESSAGE_TYPE_OFFER: + case DHCP_MESSAGE_TYPE_ACK: + case DHCP_MESSAGE_TYPE_NAK: + if ((context->vlan_ip == iphdr->ip_dst.s_addr && context->is_uplink && dir == DHCP_RX) || + (!context->is_uplink && dir == DHCP_TX)) { + context->counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; + aggregate_dev.counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; + } + break; + default: + syslog(LOG_WARNING, "handle_dhcp_option_53(%s): Unknown DHCP option 53 type %d", context->intf, dhcp_option[2]); + break; + } +} + +/** + * @code read_callback(fd, event, arg); + * + * @brief callback for libevent which is called every time out in order to read queued packet capture + * + * @param fd socket to read from + * @param event libevent triggered event + * @param arg user provided argument for callback (interface context) + * + * @return none + */ +static void read_callback(int fd, short event, void *arg) +{ + dhcp_device_context_t *context = (dhcp_device_context_t*) arg; + ssize_t buffer_sz; + + while ((event == EV_READ) && + ((buffer_sz = recv(fd, context->buffer, context->snaplen, MSG_DONTWAIT)) > 0)) { + struct ether_header *ethhdr = (struct ether_header*) context->buffer; + struct ip *iphdr = (struct ip*) (context->buffer + IP_START_OFFSET); + struct udphdr *udp = (struct udphdr*) (context->buffer + UDP_START_OFFSET); + uint8_t *dhcphdr = context->buffer + DHCP_START_OFFSET; + int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE; + + if ((buffer_sz > UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) && + (ntohs(udp->len) > DHCP_OPTIONS_HEADER_SIZE)) { + int dhcp_sz = ntohs(udp->len) < buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr) ? + ntohs(udp->len) : buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr); + int dhcp_option_sz = dhcp_sz - DHCP_OPTIONS_HEADER_SIZE; + const u_char *dhcp_option = context->buffer + dhcp_option_offset; + dhcp_packet_direction_t dir = (ethhdr->ether_shost[0] == context->mac[0] && + ethhdr->ether_shost[1] == context->mac[1] && + ethhdr->ether_shost[2] == context->mac[2] && + ethhdr->ether_shost[3] == context->mac[3] && + ethhdr->ether_shost[4] == context->mac[4] && + ethhdr->ether_shost[5] == context->mac[5]) ? + DHCP_TX : DHCP_RX; + int offset = 0; + int stop_dhcp_processing = 0; + while ((offset < (dhcp_option_sz + 1)) && dhcp_option[offset] != 255) { + switch (dhcp_option[offset]) + { + case 53: + if (offset < (dhcp_option_sz + 2)) { + handle_dhcp_option_53(context, &dhcp_option[offset], dir, iphdr, dhcphdr); + } + stop_dhcp_processing = 1; // break while loop since we are only interested in Option 53 + break; + default: + break; + } + + if (stop_dhcp_processing == 1) { + break; + } + + if (dhcp_option[offset] == 0) { // DHCP Option Padding + offset++; + } else { + offset += dhcp_option[offset + 1] + 2; + } + } + } else { + syslog(LOG_WARNING, "read_callback(%s): read length (%ld) is too small to capture DHCP options", + context->intf, buffer_sz); + } + } +} + +/** + * @code dhcp_device_is_dhcp_inactive(counters); + * + * @brief Check if there were no DHCP activity + * + * @param counters current/snapshot counter + * + * @return true if there were no DHCP activity, false otherwise + */ +static bool dhcp_device_is_dhcp_inactive(uint64_t counters[][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]) +{ + uint64_t *rx_counters = counters[DHCP_COUNTERS_CURRENT][DHCP_RX]; + uint64_t *rx_counter_snapshot = counters[DHCP_COUNTERS_SNAPSHOT][DHCP_RX]; + + bool rv = true; + for (uint8_t i = 0; (i < monitored_msg_sz) && rv; i++) { + rv = rx_counters[monitored_msgs[i]] == rx_counter_snapshot[monitored_msgs[i]]; + } + + return rv; +} + +/** + * @code dhcp_device_is_dhcp_msg_unhealthy(type, counters); + * + * @brief Check if DHCP relay is functioning properly for message of type 'type'. + * For every rx of message 'type', there should be increment of the same message type. + * + * @param type DHCP message type + * @param counters current/snapshot counter + * + * @return true if DHCP message 'type' is transmitted,false otherwise + */ +static bool dhcp_device_is_dhcp_msg_unhealthy(dhcp_message_type_t type, + uint64_t counters[][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]) +{ + // check if DHCP message 'type' is being relayed + return ((counters[DHCP_COUNTERS_CURRENT][DHCP_RX][type] > counters[DHCP_COUNTERS_SNAPSHOT][DHCP_RX][type]) && + (counters[DHCP_COUNTERS_CURRENT][DHCP_TX][type] <= counters[DHCP_COUNTERS_SNAPSHOT][DHCP_TX][type]) ); +} + +/** + * @code dhcp_device_check_positive_health(counters, counters_snapshot); + * + * @brief Check if DHCP relay is functioning properly for monitored messages (Discover, Offer, Request, ACK.) + * For every rx of monitored messages, there should be increment of the same message type. + * + * @param counters current/snapshot counter + * + * @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE + */ +static dhcp_mon_status_t dhcp_device_check_positive_health(uint64_t counters[][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]) +{ + dhcp_mon_status_t rv = DHCP_MON_STATUS_HEALTHY; + + bool is_dhcp_unhealthy = false; + for (uint8_t i = 0; (i < monitored_msg_sz) && !is_dhcp_unhealthy; i++) { + is_dhcp_unhealthy = dhcp_device_is_dhcp_msg_unhealthy(monitored_msgs[i], counters); + } + + // if we have rx DORA then we should have corresponding tx DORA (DORA being relayed) + if (is_dhcp_unhealthy) { + rv = DHCP_MON_STATUS_UNHEALTHY; + } + + return rv; +} + +/** + * @code dhcp_device_check_negative_health(counters); + * + * @brief Check that DHCP relayed messages are not being transmitted out of this interface/dev + * using its counters. The interface is negatively healthy if there are not DHCP message + * travelling through it. + * + * @param counters recent interface counter + * @param counters_snapshot snapshot counters + * + * @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE + */ +static dhcp_mon_status_t dhcp_device_check_negative_health(uint64_t counters[][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]) +{ + dhcp_mon_status_t rv = DHCP_MON_STATUS_HEALTHY; + + uint64_t *tx_counters = counters[DHCP_COUNTERS_CURRENT][DHCP_TX]; + uint64_t *tx_counter_snapshot = counters[DHCP_COUNTERS_SNAPSHOT][DHCP_TX]; + + bool is_dhcp_unhealthy = false; + for (uint8_t i = 0; (i < monitored_msg_sz) && !is_dhcp_unhealthy; i++) { + is_dhcp_unhealthy = tx_counters[monitored_msgs[i]] > tx_counter_snapshot[monitored_msgs[i]]; + } + + // for negative validation, return unhealthy if DHCP packet are being + // transmitted out of the device/interface + if (is_dhcp_unhealthy) { + rv = DHCP_MON_STATUS_UNHEALTHY; + } + + return rv; +} + +/** + * @code dhcp_device_check_health(check_type, counters, counters_snapshot); + * + * @brief Check that DHCP relay is functioning properly given a check type. Positive check + * indicates for every rx of DHCP message of type 'type', there would increment of + * the corresponding TX of the same message type. While negative check indicates the + * device should not be actively transmitting any DHCP messages. If it does, it is + * considered unhealthy. + * + * @param check_type type of health check + * @param counters current/snapshot counter + * + * @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE + */ +static dhcp_mon_status_t dhcp_device_check_health(dhcp_mon_check_t check_type, + uint64_t counters[][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]) +{ + dhcp_mon_status_t rv = DHCP_MON_STATUS_HEALTHY; + + if (dhcp_device_is_dhcp_inactive(aggregate_dev.counters)) { + rv = DHCP_MON_STATUS_INDETERMINATE; + } else if (check_type == DHCP_MON_CHECK_POSITIVE) { + rv = dhcp_device_check_positive_health(counters); + } else if (check_type == DHCP_MON_CHECK_NEGATIVE) { + rv = dhcp_device_check_negative_health(counters); + } + + return rv; +} + +/** + * @code dhcp_print_counters(vlan_intf, type, counters); + * + * @brief prints DHCP counters to sylsog. + * + * @param vlan_intf vlan interface name + * @param type counter type + * @param counters interface counter + * + * @return none + */ +static void dhcp_print_counters(const char *vlan_intf, + dhcp_counters_type_t type, + uint64_t counters[][DHCP_MESSAGE_TYPE_COUNT]) +{ + static const char *counter_desc[DHCP_COUNTERS_COUNT] = { + [DHCP_COUNTERS_CURRENT] = " Current", + [DHCP_COUNTERS_SNAPSHOT] = "Snapshot" + }; + + syslog( + LOG_NOTICE, + "[%*s-%*s rx/tx] Discover: %*lu/%*lu, Offer: %*lu/%*lu, Request: %*lu/%*lu, ACK: %*lu/%*lu\n", + IF_NAMESIZE, vlan_intf, + (int) strlen(counter_desc[type]), counter_desc[type], + DHCP_COUNTER_WIDTH, counters[DHCP_RX][DHCP_MESSAGE_TYPE_DISCOVER], + DHCP_COUNTER_WIDTH, counters[DHCP_TX][DHCP_MESSAGE_TYPE_DISCOVER], + DHCP_COUNTER_WIDTH, counters[DHCP_RX][DHCP_MESSAGE_TYPE_OFFER], + DHCP_COUNTER_WIDTH, counters[DHCP_TX][DHCP_MESSAGE_TYPE_OFFER], + DHCP_COUNTER_WIDTH, counters[DHCP_RX][DHCP_MESSAGE_TYPE_REQUEST], + DHCP_COUNTER_WIDTH, counters[DHCP_TX][DHCP_MESSAGE_TYPE_REQUEST], + DHCP_COUNTER_WIDTH, counters[DHCP_RX][DHCP_MESSAGE_TYPE_ACK], + DHCP_COUNTER_WIDTH, counters[DHCP_TX][DHCP_MESSAGE_TYPE_ACK] + ); +} + +/** + * @code init_socket(context, intf); + * + * @brief initializes socket, bind it to interface and bpf program, and + * associate with libevent base + * + * @param context pointer to device (interface) context + * @param intf interface name + * + * @return 0 on success, otherwise for failure + */ +static int init_socket(dhcp_device_context_t *context, const char *intf) +{ + int rv = -1; + + do { + context->sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL)); + if (context->sock < 0) { + syslog(LOG_ALERT, "socket: failed to open socket with '%s'\n", strerror(errno)); + break; + } + + struct sockaddr_ll addr; + memset(&addr, 0, sizeof(addr)); + addr.sll_ifindex = if_nametoindex(intf); + addr.sll_family = AF_PACKET; + addr.sll_protocol = htons(ETH_P_ALL); + if (bind(context->sock, (struct sockaddr *) &addr, sizeof(addr))) { + syslog(LOG_ALERT, "bind: failed to bind to interface '%s' with '%s'\n", intf, strerror(errno)); + break; + } + + strncpy(context->intf, intf, sizeof(context->intf) - 1); + context->intf[sizeof(context->intf) - 1] = '\0'; + + rv = 0; + } while (0); + + return rv; +} + +/** + * @code initialize_intf_mac_and_ip_addr(context); + * + * @brief initializes device (interface) mac/ip addresses + * + * @param context pointer to device (interface) context + * + * @return 0 on success, otherwise for failure + */ +static int initialize_intf_mac_and_ip_addr(dhcp_device_context_t *context) +{ + int rv = -1; + + do { + int fd; + struct ifreq ifr; + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + syslog(LOG_ALERT, "socket: %s", strerror(errno)); + break; + } + + ifr.ifr_addr.sa_family = AF_INET; + strncpy(ifr.ifr_name, context->intf, sizeof(ifr.ifr_name) - 1); + ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; + + // Get network address + if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) { + syslog(LOG_ALERT, "ioctl: %s", explain_ioctl(fd, SIOCGIFADDR, &ifr)); + break; + } + context->ip = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; + + // Get mac address + if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { + syslog(LOG_ALERT, "ioctl: %s", explain_ioctl(fd, SIOCGIFHWADDR, &ifr)); + break; + } + memcpy(context->mac, ifr.ifr_hwaddr.sa_data, sizeof(context->mac)); + + close(fd); + + rv = 0; + } while (0); + + return rv; +} + +/** + * @code dhcp_device_get_ip(context); + * + * @brief Accessor method + * + * @param context pointer to device (interface) context + * + * @return interface IP + */ +int dhcp_device_get_ip(dhcp_device_context_t *context, in_addr_t *ip) +{ + int rv = -1; + + if (context != NULL && ip != NULL) { + *ip = context->ip; + rv = 0; + } + + return rv; +} + +/** + * @code dhcp_device_get_aggregate_context(); + * + * @brief Accessor method + * + * @return pointer to aggregate device (interface) context + */ +dhcp_device_context_t* dhcp_device_get_aggregate_context() +{ + return &aggregate_dev; +} + +/** + * @code dhcp_device_init(context, intf, is_uplink); + * + * @brief initializes device (interface) that handles packet capture per interface. + */ +int dhcp_device_init(dhcp_device_context_t **context, const char *intf, uint8_t is_uplink) +{ + int rv = -1; + dhcp_device_context_t *dev_context = NULL; + + if ((context != NULL) && (strlen(intf) < sizeof(dev_context->intf))) { + + dev_context = (dhcp_device_context_t *) malloc(sizeof(dhcp_device_context_t)); + if (dev_context != NULL) { + if ((init_socket(dev_context, intf) == 0) && + (initialize_intf_mac_and_ip_addr(dev_context) == 0)) { + + dev_context->is_uplink = is_uplink; + + memset(dev_context->counters, 0, sizeof(dev_context->counters)); + + *context = dev_context; + rv = 0; + } + } + else { + syslog(LOG_ALERT, "malloc: failed to allocated device context memory for '%s'", dev_context->intf); + } + } + + return rv; +} + +/** + * @code dhcp_device_start_capture(context, snaplen, base, vlan_ip); + * + * @brief starts packet capture on this interface + */ +int dhcp_device_start_capture(dhcp_device_context_t *context, + size_t snaplen, + struct event_base *base, + in_addr_t vlan_ip) +{ + int rv = -1; + + do { + if (context == NULL) { + syslog(LOG_ALERT, "NULL interface context pointer'\n"); + break; + } + + if (snaplen < UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) { + syslog(LOG_ALERT, "dhcp_device_start_capture(%s): snap length is too low to capture DHCP options", context->intf); + break; + } + + context->vlan_ip = vlan_ip; + + context->buffer = (uint8_t *) malloc(snaplen); + if (context->buffer == NULL) { + syslog(LOG_ALERT, "malloc: failed to allocate memory for socket buffer '%s'\n", strerror(errno)); + break; + } + context->snaplen = snaplen; + + if (setsockopt(context->sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_sock_bfp, sizeof(dhcp_sock_bfp)) != 0) { + syslog(LOG_ALERT, "setsockopt: failed to attach filter with '%s'\n", strerror(errno)); + break; + } + + struct event *ev = event_new(base, context->sock, EV_READ | EV_PERSIST, read_callback, context); + if (ev == NULL) { + syslog(LOG_ALERT, "event_new: failed to allocate memory for libevent event '%s'\n", strerror(errno)); + break; + } + event_add(ev, NULL); + + rv = 0; + } while (0); + + return rv; +} + +/** + * @code dhcp_device_shutdown(context); + * + * @brief shuts down device (interface). Also, stops packet capture on interface and cleans up any allocated memory + */ +void dhcp_device_shutdown(dhcp_device_context_t *context) +{ + free(context); +} + +/** + * @code dhcp_device_get_status(check_type, context); + * + * @brief collects DHCP relay status info for a given interface. If context is null, it will report aggregate + * status + */ +dhcp_mon_status_t dhcp_device_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context) +{ + dhcp_mon_status_t rv = DHCP_MON_STATUS_HEALTHY; + + if (context != NULL) { + rv = dhcp_device_check_health(check_type, context->counters); + } + + return rv; +} + +/** + * @code dhcp_device_update_snapshot(context); + * + * @brief Update device/interface counters snapshot + */ +void dhcp_device_update_snapshot(dhcp_device_context_t *context) +{ + if (context != NULL) { + memcpy(context->counters[DHCP_COUNTERS_SNAPSHOT], + context->counters[DHCP_COUNTERS_CURRENT], + sizeof(context->counters[DHCP_COUNTERS_SNAPSHOT])); + } +} + +/** + * @code dhcp_device_print_status(context, type); + * + * @brief prints status counters to syslog. + */ +void dhcp_device_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type) +{ + if (context != NULL) { + dhcp_print_counters(context->intf, type, context->counters[type]); + } +} diff --git a/src/dhcpmon/src/dhcp_device.h b/src/dhcpmon/src/dhcp_device.h new file mode 100644 index 000000000000..133b9265a434 --- /dev/null +++ b/src/dhcpmon/src/dhcp_device.h @@ -0,0 +1,183 @@ +/** + * @file dhcp_device.h + * + * device (interface) module + */ + +#ifndef DHCP_DEVICE_H_ +#define DHCP_DEVICE_H_ + +#include +#include +#include +#include + +#include +#include +#include + + +/** + * DHCP message types + **/ +typedef enum +{ + DHCP_MESSAGE_TYPE_DISCOVER = 1, + DHCP_MESSAGE_TYPE_OFFER = 2, + DHCP_MESSAGE_TYPE_REQUEST = 3, + DHCP_MESSAGE_TYPE_DECLINE = 4, + DHCP_MESSAGE_TYPE_ACK = 5, + DHCP_MESSAGE_TYPE_NAK = 6, + DHCP_MESSAGE_TYPE_RELEASE = 7, + DHCP_MESSAGE_TYPE_INFORM = 8, + + DHCP_MESSAGE_TYPE_COUNT +} dhcp_message_type_t; + +/** packet direction */ +typedef enum +{ + DHCP_RX, /** RX DHCP packet */ + DHCP_TX, /** TX DHCP packet */ + + DHCP_DIR_COUNT +} dhcp_packet_direction_t; + +/** counters type */ +typedef enum +{ + DHCP_COUNTERS_CURRENT, /** DHCP current counters */ + DHCP_COUNTERS_SNAPSHOT, /** DHCP snapshot counters */ + + DHCP_COUNTERS_COUNT +} dhcp_counters_type_t; + +/** dhcp health status */ +typedef enum +{ + DHCP_MON_STATUS_HEALTHY, /** DHCP relay is healthy */ + DHCP_MON_STATUS_UNHEALTHY, /** DHCP relay is unhealthy and is missing out on some packets */ + DHCP_MON_STATUS_INDETERMINATE, /** DHCP relay health could not be determined */ +} dhcp_mon_status_t; + +/** dhcp check type */ +typedef enum +{ + DHCP_MON_CHECK_NEGATIVE, /** Presence of relayed DHCP packets activity is flagged as unhealthy state */ + DHCP_MON_CHECK_POSITIVE, /** Validate that received DORA packets are relayed */ +} dhcp_mon_check_t; + +/** DHCP device (interface) context */ +typedef struct +{ + int sock; /** Raw socket associated with this device/interface */ + in_addr_t ip; /** network address of this device (interface) */ + uint8_t mac[ETHER_ADDR_LEN]; /** hardware address of this device (interface) */ + in_addr_t vlan_ip; /** Vlan IP address */ + uint8_t is_uplink; /** north interface? */ + char intf[IF_NAMESIZE]; /** device (interface) name */ + uint8_t *buffer; /** buffer used to read socket data */ + size_t snaplen; /** snap length or buffer size */ + uint64_t counters[DHCP_COUNTERS_COUNT][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]; + /** current/snapshot counters of DHCP packets */ +} dhcp_device_context_t; + +/** + * @code dhcp_device_get_ip(context, ip); + * + * @brief Accessor method + * + * @param context pointer to device (interface) context + * @param ip(out) pointer to device IP + * + * @return 0 on success, otherwise for failure + */ +int dhcp_device_get_ip(dhcp_device_context_t *context, in_addr_t *ip); + +/** + * @code dhcp_device_get_aggregate_context(); + * + * @brief Accessor method + * + * @return pointer to aggregate device (interface) context + */ +dhcp_device_context_t* dhcp_device_get_aggregate_context(); + +/** + * @code dhcp_device_init(context, intf, is_uplink); + * + * @brief initializes device (interface) that handles packet capture per interface. + * + * @param context(inout) pointer to device (interface) context + * @param intf interface name + * @param is_uplink uplink interface + * + * @return 0 on success, otherwise for failure + */ +int dhcp_device_init(dhcp_device_context_t **context, + const char *intf, + uint8_t is_uplink); + +/** + * @code dhcp_device_start_capture(context, snaplen, base, vlan_ip); + * + * @brief starts packet capture on this interface + * + * @param context pointer to device (interface) context + * @param snaplen length of packet capture + * @param base pointer to libevent base + * @param vlan_ip vlan IP address + * + * @return 0 on success, otherwise for failure + */ +int dhcp_device_start_capture(dhcp_device_context_t *context, + size_t snaplen, + struct event_base *base, + in_addr_t vlan_ip); + +/** + * @code dhcp_device_shutdown(context); + * + * @brief shuts down device (interface). Also, stops packet capture on interface and cleans up any allocated memory + * + * @param context Device (interface) context + * + * @return nonedhcp_device_shutdown + */ +void dhcp_device_shutdown(dhcp_device_context_t *context); + +/** + * @code dhcp_device_get_status(check_type, context); + * + * @brief collects DHCP relay status info for a given interface. If context is null, it will report aggregate + * status + * + * @param check_type Type of validation + * @param context Device (interface) context + * + * @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE + */ +dhcp_mon_status_t dhcp_device_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context); + +/** + * @code dhcp_device_update_snapshot(context); + * + * @param context Device (interface) context + * + * @brief Update device/interface counters snapshot + */ +void dhcp_device_update_snapshot(dhcp_device_context_t *context); + +/** + * @code dhcp_device_print_status(context, type); + * + * @brief prints status counters to syslog. If context is null, it will print aggregate status + * + * @param context Device (interface) context + * @param counters_type Counter type to be printed + * + * @return none + */ +void dhcp_device_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type); + +#endif /* DHCP_DEVICE_H_ */ diff --git a/src/dhcpmon/src/dhcp_devman.c b/src/dhcpmon/src/dhcp_devman.c new file mode 100644 index 000000000000..35378a631ca7 --- /dev/null +++ b/src/dhcpmon/src/dhcp_devman.c @@ -0,0 +1,232 @@ +/** + * @file dhcp_devman.c + * + * Device (interface) manager + */ +#include +#include +#include +#include +#include +#include + +#include "dhcp_devman.h" + +/** Prefix appended to Aggregation device */ +#define AGG_DEV_PREFIX "Agg-" + +/** struct for interface information */ +struct intf +{ + const char *name; /** interface name */ + uint8_t is_uplink; /** is uplink (north) interface */ + dhcp_device_context_t *dev_context; /** device (interface_ context */ + LIST_ENTRY(intf) entry; /** list link/pointers entries */ +}; + +/** intfs list of interfaces */ +static LIST_HEAD(intf_list, intf) intfs; +/** dhcp_num_south_intf number of south interfaces */ +static uint32_t dhcp_num_south_intf = 0; +/** dhcp_num_north_intf number of north interfaces */ +static uint32_t dhcp_num_north_intf = 0; +/** dhcp_num_mgmt_intf number of mgmt interfaces */ +static uint32_t dhcp_num_mgmt_intf = 0; + +/** On Device vlan interface IP address corresponding vlan downlink IP + * This IP is used to filter Offer/Ack packet coming from DHCP server */ +static in_addr_t vlan_ip = 0; + +/** mgmt interface */ +static struct intf *mgmt_intf = NULL; + +/** + * @code dhcp_devman_get_vlan_intf(); + * + * Accessor method + */ +dhcp_device_context_t* dhcp_devman_get_agg_dev() +{ + return dhcp_device_get_aggregate_context(); +} + +/** + * @code dhcp_devman_get_mgmt_dev(); + * + * Accessor method + */ +dhcp_device_context_t* dhcp_devman_get_mgmt_dev() +{ + return mgmt_intf ? mgmt_intf->dev_context : NULL; +} + +/** + * @code dhcp_devman_init(); + * + * initializes device (interface) manager that keeps track of interfaces and assert that there is one south + * interface and as many north interfaces + */ +void dhcp_devman_init() +{ + LIST_INIT(&intfs); +} + +/** + * @code dhcp_devman_shutdown(); + * + * shuts down device (interface) manager. Also, stops packet capture on interface and cleans up any allocated + * memory + */ +void dhcp_devman_shutdown() +{ + struct intf *int_ptr, *prev_intf = NULL; + + LIST_FOREACH(int_ptr, &intfs, entry) { + dhcp_device_shutdown(int_ptr->dev_context); + if (prev_intf) { + LIST_REMOVE(prev_intf, entry); + free(prev_intf); + prev_intf = int_ptr; + } + } + + if (prev_intf) { + LIST_REMOVE(prev_intf, entry); + free(prev_intf); + } +} + +/** + * @code dhcp_devman_add_intf(name, is_uplink); + * + * @brief adds interface to the device manager. + */ +int dhcp_devman_add_intf(const char *name, char intf_type) +{ + int rv = -1; + struct intf *dev = malloc(sizeof(struct intf)); + + if (dev != NULL) { + dev->name = name; + dev->is_uplink = intf_type != 'd'; + + switch (intf_type) + { + case 'u': + dhcp_num_north_intf++; + break; + case 'd': + dhcp_num_south_intf++; + assert(dhcp_num_south_intf <= 1); + break; + case 'm': + dhcp_num_mgmt_intf++; + assert(dhcp_num_mgmt_intf <= 1); + mgmt_intf = dev; + break; + default: + break; + } + + rv = dhcp_device_init(&dev->dev_context, dev->name, dev->is_uplink); + if (rv == 0 && intf_type == 'd') { + rv = dhcp_device_get_ip(dev->dev_context, &vlan_ip); + + dhcp_device_context_t *agg_dev = dhcp_device_get_aggregate_context(); + + strncpy(agg_dev->intf, AGG_DEV_PREFIX, sizeof(AGG_DEV_PREFIX)); + strncpy(agg_dev->intf + sizeof(AGG_DEV_PREFIX) - 1, name, sizeof(agg_dev->intf) - sizeof(AGG_DEV_PREFIX)); + agg_dev->intf[sizeof(agg_dev->intf) - 1] = '\0'; + } + + LIST_INSERT_HEAD(&intfs, dev, entry); + } + else { + syslog(LOG_ALERT, "malloc: failed to allocate memory for intf '%s'\n", name); + } + + return rv; +} + +/** + * @code dhcp_devman_start_capture(snaplen, base); + * + * @brief start packet capture on the devman interface list + */ +int dhcp_devman_start_capture(size_t snaplen, struct event_base *base) +{ + int rv = -1; + struct intf *int_ptr; + + if ((dhcp_num_south_intf == 1) && (dhcp_num_north_intf >= 1)) { + LIST_FOREACH(int_ptr, &intfs, entry) { + rv = dhcp_device_start_capture(int_ptr->dev_context, snaplen, base, vlan_ip); + if (rv == 0) { + syslog(LOG_INFO, + "Capturing DHCP packets on interface %s, ip: 0x%08x, mac [%02x:%02x:%02x:%02x:%02x:%02x] \n", + int_ptr->name, int_ptr->dev_context->ip, int_ptr->dev_context->mac[0], + int_ptr->dev_context->mac[1], int_ptr->dev_context->mac[2], int_ptr->dev_context->mac[3], + int_ptr->dev_context->mac[4], int_ptr->dev_context->mac[5]); + } + else { + break; + } + } + } + else { + syslog(LOG_ERR, "Invalid number of interfaces, downlink/south %d, uplink/north %d\n", + dhcp_num_south_intf, dhcp_num_north_intf); + } + + return rv; +} + +/** + * @code dhcp_devman_get_status(check_type, context); + * + * @brief collects DHCP relay status info. + */ +dhcp_mon_status_t dhcp_devman_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context) +{ + return dhcp_device_get_status(check_type, context); +} + +/** + * @code dhcp_devman_update_snapshot(context); + * + * @brief Update device/interface counters snapshot + */ +void dhcp_devman_update_snapshot(dhcp_device_context_t *context) +{ + if (context == NULL) { + struct intf *int_ptr; + + LIST_FOREACH(int_ptr, &intfs, entry) { + dhcp_device_update_snapshot(int_ptr->dev_context); + } + + dhcp_device_update_snapshot(dhcp_devman_get_agg_dev()); + } else { + dhcp_device_update_snapshot(context); + } +} + +/** + * @code dhcp_devman_print_status(context, type); + * + * @brief prints status counters to syslog, if context is null, it prints status counters for all interfaces + */ +void dhcp_devman_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type) +{ + if (context == NULL) { + struct intf *int_ptr; + + LIST_FOREACH(int_ptr, &intfs, entry) { + dhcp_device_print_status(int_ptr->dev_context, type); + } + + dhcp_device_print_status(dhcp_devman_get_agg_dev(), type); + } else { + dhcp_device_print_status(context, type); + } +} diff --git a/src/dhcpmon/src/dhcp_devman.h b/src/dhcpmon/src/dhcp_devman.h new file mode 100644 index 000000000000..bba7076902cb --- /dev/null +++ b/src/dhcpmon/src/dhcp_devman.h @@ -0,0 +1,111 @@ +/** + * @file dhcp_devman.h + * + * Device (interface) manager + */ + +#ifndef DHCP_DEVMAN_H_ +#define DHCP_DEVMAN_H_ + +#include + +#include "dhcp_device.h" + +/** + * @code dhcp_devman_init(); + * + * @brief initializes device (interface) manager that keeps track of interfaces and assert that there is one south + * interface and as many north interfaces + * + * @return none + */ +void dhcp_devman_init(); + +/** + * @code dhcp_devman_shutdown(); + * + * @brief shuts down device (interface) manager. Also, stops packet capture on interface and cleans up any allocated + * memory + * + * @return none + */ +void dhcp_devman_shutdown(); + +/** + * @code dhcp_devman_get_vlan_intf(); + * + * @brief Accessor method + * + * @return pointer to aggregate device (interface) context + */ +dhcp_device_context_t* dhcp_devman_get_agg_dev(); + +/** + * @code dhcp_devman_get_mgmt_intf_context(); + * + * @brief Accessor method + * + * @return pointer to mgmt interface context + */ +dhcp_device_context_t* dhcp_devman_get_mgmt_dev(); + +/** + * @code dhcp_devman_add_intf(name, uplink); + * + * @brief adds interface to the device manager. + * + * @param name interface name + * @param intf_type 'u' for uplink (north) interface + * 'd' for downlink (south) interface + * 'm' for mgmt interface + * + * @return 0 on success, nonzero otherwise + */ +int dhcp_devman_add_intf(const char *name, char intf_type); + +/** + * @code dhcp_devman_start_capture(snaplen, base); + * + * @brief start packet capture on the devman interface list + * + * @param snaplen packet packet capture snap length + * @param base libevent base + * + * @return 0 on success, nonzero otherwise + */ +int dhcp_devman_start_capture(size_t snaplen, struct event_base *base); + +/** + * @code dhcp_devman_get_status(check_type, context); + * + * @brief collects DHCP relay status info. + * + * @param check_type Type of validation + * @param context pointer to device (interface) context + * + * @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE + */ +dhcp_mon_status_t dhcp_devman_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context); + +/** + * @code dhcp_devman_update_snapshot(context); + * + * @param context Device (interface) context + * + * @brief Update device/interface counters snapshot + */ +void dhcp_devman_update_snapshot(dhcp_device_context_t *context); + +/** + * @code dhcp_devman_print_status(context, type); + * + * @brief prints status counters to syslog + * + * @param context pointer to device (interface) context + * @param type Counter type to be printed + * + * @return none + */ +void dhcp_devman_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type); + +#endif /* DHCP_DEVMAN_H_ */ diff --git a/src/dhcpmon/src/dhcp_mon.c b/src/dhcpmon/src/dhcp_mon.c new file mode 100644 index 000000000000..74d9869741d1 --- /dev/null +++ b/src/dhcpmon/src/dhcp_mon.c @@ -0,0 +1,263 @@ +/** + * @file dhcp_mon.c + * + * @brief dhcp relay monitor module + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dhcp_mon.h" +#include "dhcp_devman.h" + +/** DHCP device/interface state */ +typedef struct +{ + dhcp_mon_check_t check_type; /** check type */ + dhcp_device_context_t* (*get_context)(); /** functor to a device context accessor function */ + int count; /** count in the number of unhealthy checks */ + const char *msg; /** message to be printed if unhealthy state is determined */ +} dhcp_mon_state_t; + +/** window_interval_sec monitoring window for dhcp relay health checks */ +static int window_interval_sec = 18; +/** dhcp_unhealthy_max_count max count of consecutive unhealthy statuses before reporting to syslog */ +static int dhcp_unhealthy_max_count = 10; +/** libevent base struct */ +static struct event_base *base; +/** libevent timeout event struct */ +static struct event *ev_timeout = NULL; +/** libevent SIGINT signal event struct */ +static struct event *ev_sigint; +/** libevent SIGTERM signal event struct */ +static struct event *ev_sigterm; +/** libevent SIGUSR1 signal event struct */ +static struct event *ev_sigusr1; + +/** DHCP monitor state data for aggregate device for mgmt device */ +static dhcp_mon_state_t state_data[] = { + [0] = { + .check_type = DHCP_MON_CHECK_POSITIVE, + .get_context = dhcp_devman_get_agg_dev, + .count = 0, + .msg = "dhcpmon detected disparity in DHCP Relay behavior. Duration: %d (sec) for vlan: '%s'\n" + }, + [1] = { + .check_type = DHCP_MON_CHECK_NEGATIVE, + .get_context = dhcp_devman_get_mgmt_dev, + .count = 0, + .msg = "dhcpmon detected DHCP packets traveling through mgmt interface (please check BGP routes.)" + " Duration: %d (sec) for intf: '%s'\n" + } +}; + +/** + * @code signal_callback(fd, event, arg); + * + * @brief signal handler for dhcpmon. It will initiate shutdown when signal is caught + * + * @param fd libevent socket + * @param event event triggered + * @param arg pointer to user provided context (libevent base) + * + * @return none + */ +static void signal_callback(evutil_socket_t fd, short event, void *arg) +{ + syslog(LOG_ALERT, "Received signal: '%s'\n", strsignal(fd)); + dhcp_devman_print_status(NULL, DHCP_COUNTERS_CURRENT); + if ((fd == SIGTERM) || (fd == SIGINT)) { + dhcp_mon_stop(); + } +} + +/** + * @code check_dhcp_relay_health(state_data); + * + * @brief check DHCP relay overall health + * + * @param state_data pointer to dhcpmon state data + * + * @return none + */ +static void check_dhcp_relay_health(dhcp_mon_state_t *state_data) +{ + dhcp_device_context_t *context = state_data->get_context(); + dhcp_mon_status_t dhcp_mon_status = dhcp_devman_get_status(state_data->check_type, context); + + switch (dhcp_mon_status) + { + case DHCP_MON_STATUS_UNHEALTHY: + if (++state_data->count > dhcp_unhealthy_max_count) { + syslog(LOG_ALERT, state_data->msg, state_data->count * window_interval_sec, context->intf); + dhcp_devman_print_status(context, DHCP_COUNTERS_SNAPSHOT); + dhcp_devman_print_status(context, DHCP_COUNTERS_CURRENT); + } + break; + case DHCP_MON_STATUS_HEALTHY: + state_data->count = 0; + break; + case DHCP_MON_STATUS_INDETERMINATE: + if (state_data->count) { + state_data->count++; + } + break; + default: + syslog(LOG_ERR, "DHCP Relay returned unknown status %d\n", dhcp_mon_status); + break; + } +} + +/** + * @code timeout_callback(fd, event, arg); + * + * @brief periodic timer call back + * + * @param fd libevent socket + * @param event event triggered + * @param arg pointer user provided context (libevent base) + * + * @return none + */ +static void timeout_callback(evutil_socket_t fd, short event, void *arg) +{ + for (uint8_t i = 0; i < sizeof(state_data) / sizeof(*state_data); i++) { + check_dhcp_relay_health(&state_data[i]); + } + + dhcp_devman_update_snapshot(NULL); +} + +/** + * @code dhcp_mon_init(window_sec, max_count); + * + * initializes event base and periodic timer event that continuously collects dhcp relay health status every window_sec + * seconds. It also writes to syslog when dhcp relay has been unhealthy for consecutive max_count checks. + * + */ +int dhcp_mon_init(int window_sec, int max_count) +{ + int rv = -1; + + do { + window_interval_sec = window_sec; + dhcp_unhealthy_max_count = max_count; + + base = event_base_new(); + if (base == NULL) { + syslog(LOG_ERR, "Could not initialize libevent!\n"); + break; + } + + ev_sigint = evsignal_new(base, SIGINT, signal_callback, base); + if (ev_sigint == NULL) { + syslog(LOG_ERR, "Could not create SIGINT libevent signal!\n"); + break; + } + + ev_sigterm = evsignal_new(base, SIGTERM, signal_callback, base); + if (ev_sigterm == NULL) { + syslog(LOG_ERR, "Could not create SIGTERM libevent signal!\n"); + break; + } + + ev_sigusr1 = evsignal_new(base, SIGUSR1, signal_callback, base); + if (ev_sigusr1 == NULL) { + syslog(LOG_ERR, "Could not create SIGUSER1 libevent signal!\n"); + break; + } + + ev_timeout = event_new(base, -1, EV_PERSIST, timeout_callback, base); + if (ev_timeout == NULL) { + syslog(LOG_ERR, "Could not create libevent timer!\n"); + break; + } + + rv = 0; + } while (0); + + return rv; +} + +/** + * @code dhcp_mon_shutdown(); + * + * @brief shuts down libevent loop + */ +void dhcp_mon_shutdown() +{ + event_del(ev_timeout); + event_del(ev_sigint); + event_del(ev_sigterm); + event_del(ev_sigusr1); + + event_free(ev_timeout); + event_free(ev_sigint); + event_free(ev_sigterm); + event_free(ev_sigusr1); + + event_base_free(base); +} + +/** + * @code dhcp_mon_start(snaplen); + * + * @brief start monitoring DHCP Relay + */ +int dhcp_mon_start(size_t snaplen) +{ + int rv = -1; + + do + { + if (dhcp_devman_start_capture(snaplen, base) != 0) { + break; + } + + if (evsignal_add(ev_sigint, NULL) != 0) { + syslog(LOG_ERR, "Could not add SIGINT libevent signal!\n"); + break; + } + + if (evsignal_add(ev_sigterm, NULL) != 0) { + syslog(LOG_ERR, "Could not add SIGTERM libevent signal!\n"); + break; + } + + if (evsignal_add(ev_sigusr1, NULL) != 0) { + syslog(LOG_ERR, "Could not add SIGUSR1 libevent signal!\n"); + break; + } + + struct timeval event_time = {.tv_sec = window_interval_sec, .tv_usec = 0}; + if (evtimer_add(ev_timeout, &event_time) != 0) { + syslog(LOG_ERR, "Could not add event timer to libevent!\n"); + break; + } + + if (event_base_dispatch(base) != 0) { + syslog(LOG_ERR, "Could not start libevent dispatching loop!\n"); + break; + } + + rv = 0; + } while (0); + + return rv; +} + +/** + * @code dhcp_mon_stop(); + * + * @brief stop monitoring DHCP Relay + */ +void dhcp_mon_stop() +{ + event_base_loopexit(base, NULL); +} diff --git a/src/dhcpmon/src/dhcp_mon.h b/src/dhcpmon/src/dhcp_mon.h new file mode 100644 index 000000000000..ae8911ab51fc --- /dev/null +++ b/src/dhcpmon/src/dhcp_mon.h @@ -0,0 +1,54 @@ +/** + * @file dhcp_mon.h + * + * @brief dhcp relay monitor module + * + */ + +#ifndef DHCP_MON_H_ +#define DHCP_MON_H_ + +/** + * @code dhcp_mon_init(window_ssec, max_count); + * + * @brief initializes event base and periodic timer event that continuously collects dhcp relay health status every + * window_sec seconds. It also writes to syslog when dhcp relay has been unhealthy for consecutive max_count + * checks. + * + * @param window_sec time interval between health checks + * @param max_count max count of consecutive unhealthy statuses before reporting to syslog + * + * @return 0 upon success, otherwise upon failure + */ +int dhcp_mon_init(int window_sec, int max_count); + +/** + * @code dhcp_mon_shutdown(); + * + * @brief shuts down libevent loop + * + * @return none + */ +void dhcp_mon_shutdown(); + +/** + * @code dhcp_mon_start(snaplen); + * + * @brief start monitoring DHCP Relay + * + * @param snaplen packet capture length + * + * @return 0 upon success, otherwise upon failure + */ +int dhcp_mon_start(size_t snaplen); + +/** + * @code dhcp_mon_stop(); + * + * @brief stop monitoring DHCP Relay + * + * @return none + */ +void dhcp_mon_stop(); + +#endif /* DHCP_MON_H_ */ diff --git a/src/dhcpmon/src/main.c b/src/dhcpmon/src/main.c new file mode 100644 index 000000000000..bb8c45867f66 --- /dev/null +++ b/src/dhcpmon/src/main.c @@ -0,0 +1,174 @@ +/** + * @file main.c + * + * @brief: Main entry point for dhcpmon utility. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dhcp_mon.h" +#include "dhcp_devman.h" + +/** dhcpmon_default_snaplen: default snap length of packet being captured */ +static const size_t dhcpmon_default_snaplen = 65535; +/** dhcpmon_default_health_check_window: default value for a time window, during which DHCP DORA packet counts are being + * collected */ +static const uint32_t dhcpmon_default_health_check_window = 18; +/** dhcpmon_default_unhealthy_max_count: default max consecutive unhealthy status reported before reporting an issue + * with DHCP relay */ +static const uint32_t dhcpmon_default_unhealthy_max_count = 10; + +/** + * @code usage(prog); + * + * @brief prints help message about how to use dhcpmon utility + * + * @param prog program name + * + * @return none + */ +static void usage(const char *prog) +{ + printf("Usage: %s -id {-iu }+ -im [-w ]" + "[-c ] [-s ] [-d]\n", prog); + printf("where\n"); + printf("\tsouth interface: is a vlan interface,\n"); + printf("\tnorth interface: is a TOR-T1 interface,\n"); + printf("\tsnapshot window: during which DHCP counters are gathered and DHCP status is validated (default %d),\n", + dhcpmon_default_health_check_window); + printf("\tunhealthy status count: count of consecutive unhealthy status before writing an alert to syslog " + "(default %d),\n", + dhcpmon_default_unhealthy_max_count); + printf("\tsnap length: snap length of packet capture (default %ld),\n", dhcpmon_default_snaplen); + printf("\t-d: daemonize %s.\n", prog); + + exit(EXIT_SUCCESS); +} + +/** + * @code dhcpmon_daemonize(); + * + * @brief make this utility run as a daemon. + * + * @return none + */ +static void dhcpmon_daemonize() +{ + pid_t pid, sid; + pid = fork(); + if (pid < 0) { + syslog(LOG_ALERT, "fork: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + if (pid > 0) { + exit(EXIT_SUCCESS); + } + + // this is the daemon running now + umask(0); + // Create a new SID for the child process + sid = setsid(); + if (sid < 0) { + syslog(LOG_ALERT, "setsid: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + // Change the current working directory + if ((chdir("/")) < 0) { + syslog(LOG_ALERT, "chdir: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); +} + +/** + * @code main(argc, argv); + * + * @brief main entry point of dhcpmon utility + * + * @return int 0 on success, otherwise on failure + */ +int main(int argc, char **argv) +{ + int rv = EXIT_FAILURE; + int i; + int window_interval = dhcpmon_default_health_check_window; + int max_unhealthy_count = dhcpmon_default_unhealthy_max_count; + size_t snaplen = dhcpmon_default_snaplen; + int make_daemon = 0; + + setlogmask(LOG_UPTO(LOG_INFO)); + openlog(basename(argv[0]), LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON); + + dhcp_devman_init(); + + for (i = 1; i < argc;) { + if ((argv[i] == NULL) || (argv[i][0] != '-')) { + break; + } + switch (argv[i][1]) + { + case 'h': + usage(basename(argv[0])); + break; + case 'i': + if (dhcp_devman_add_intf(argv[i + 1], argv[i][2]) != 0) { + usage(basename(argv[0])); + } + i += 2; + break; + case 'd': + make_daemon = 1; + i++; + break; + case 's': + snaplen = atoi(argv[i + 1]); + i += 2; + break; + case 'w': + window_interval = atoi(argv[i + 1]); + i += 2; + break; + case 'c': + max_unhealthy_count = atoi(argv[i + 1]); + i += 2; + break; + default: + fprintf(stderr, "%s: %c: Unknown option\n", basename(argv[0]), argv[i][1]); + usage(basename(argv[0])); + } + } + + if (make_daemon) { + dhcpmon_daemonize(); + } + + if ((dhcp_mon_init(window_interval, max_unhealthy_count) == 0) && + (dhcp_mon_start(snaplen) == 0)) { + + rv = EXIT_SUCCESS; + + dhcp_mon_shutdown(); + } + + dhcp_devman_shutdown(); + + closelog(); + + return rv; +} diff --git a/src/dhcpmon/src/subdir.mk b/src/dhcpmon/src/subdir.mk new file mode 100644 index 000000000000..324977aa39f7 --- /dev/null +++ b/src/dhcpmon/src/subdir.mk @@ -0,0 +1,29 @@ +# Add inputs and outputs from these tool invocations to the build variables +CC := gcc + +C_SRCS += \ +../src/dhcp_device.c \ +../src/dhcp_devman.c \ +../src/dhcp_mon.c \ +../src/main.c + +OBJS += \ +./src/dhcp_device.o \ +./src/dhcp_devman.o \ +./src/dhcp_mon.o \ +./src/main.o + +C_DEPS += \ +./src/dhcp_device.d \ +./src/dhcp_devman.d \ +./src/dhcp_mon.d \ +./src/main.d + + +# Each subdirectory must supply rules for building sources it contributes +src/%.o: ../src/%.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + $(CC) -O3 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' diff --git a/src/gobgp/Makefile b/src/gobgp/Makefile new file mode 100644 index 000000000000..4fda21013afb --- /dev/null +++ b/src/gobgp/Makefile @@ -0,0 +1,23 @@ +export GOPATH=/tmp/go + +INSTALL := /usr/bin/install + +all: gobgp gobgpd + +gobgpd: + /usr/local/go/bin/go get -v github.com/osrg/gobgp/cmd/gobgpd + +gobgp: + /usr/local/go/bin/go get -v github.com/osrg/gobgp/cmd/gobgp + +install: + $(INSTALL) -D ${GOPATH}/bin/gobgp $(DESTDIR)/usr/bin/gobgp + $(INSTALL) -D ${GOPATH}/bin/gobgpd $(DESTDIR)/usr/sbin/gobgpd + $(INSTALL) -D gobgpd.conf.sample $(DESTDIR)/etc/gobgp/gobgpd.conf.sample + +deinstall: + rm $(DESTDIR)/usr/bin/gobgp + rm $(DESTDIR)/usr/sbin/gobgpd + +clean: + rm -fr ${GOPATH} diff --git a/src/gobgp/debian/changelog b/src/gobgp/debian/changelog new file mode 100644 index 000000000000..ba412cc45ede --- /dev/null +++ b/src/gobgp/debian/changelog @@ -0,0 +1,5 @@ +gobgp (1.16-01) UNRELEASED; urgency=low + + * Initial release. + + -- Pavel Shirshov Sat, 25 Feb 2017 00:25:19 +0000 diff --git a/src/gobgp/debian/compat b/src/gobgp/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/src/gobgp/debian/compat @@ -0,0 +1 @@ +9 diff --git a/src/gobgp/debian/control b/src/gobgp/debian/control new file mode 100644 index 000000000000..7d534852a383 --- /dev/null +++ b/src/gobgp/debian/control @@ -0,0 +1,12 @@ +Source: gobgp +Maintainer: Pavel Shirshov +Build-Depends: debhelper (>= 8.0.0), + dh-systemd +Standards-Version: 3.9.3 +Section: net + +Package: gobgp +Priority: extra +Architecture: amd64 +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: gobgp BGP daemon diff --git a/src/gobgp/debian/gobgp.dirs b/src/gobgp/debian/gobgp.dirs new file mode 100644 index 000000000000..3e9f1c594d41 --- /dev/null +++ b/src/gobgp/debian/gobgp.dirs @@ -0,0 +1 @@ +etc/gobgp diff --git a/src/gobgp/debian/gobgp.init.d b/src/gobgp/debian/gobgp.init.d new file mode 100644 index 000000000000..189fdad05690 --- /dev/null +++ b/src/gobgp/debian/gobgp.init.d @@ -0,0 +1,50 @@ +#!/bin/bash +# +### BEGIN INIT INFO +# Provides: gobgp +# Required-Start: $local_fs $network $remote_fs $syslog +# Required-Stop: $local_fs $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop the gobgpd +# Description: gobgpd is an implementation of bgp daemon in Go +### END INIT INFO +# + +PATH=/bin:/usr/bin:/sbin:/usr/sbin +D_PATH=/usr/sbin +C_PATH=/etc/gobgp + +. /lib/lsb/init-functions + +######################################################### +# Main program # +######################################################### + +case "$1" in + start) + if [ -f /etc/gobgp/gobgpd.conf ] + then + /usr/sbin/gobgpd -f /etc/gobgp/gobgpd.conf -r + echo $! > /var/run/gobgpd.pid + else + echo /etc/gobgp/gobgpd.conf not found + fi + ;; + + stop) + kill -9 $(echo /var/run/gobgpd.pid) + ;; + + restart|force-reload) + $0 stop $2 + sleep 1 + $0 start $2 + ;; + *) + echo "Usage: /etc/init.d/gobgp {start|stop|restart|force-reload}" + exit 1 + ;; +esac + +exit 0 diff --git a/src/gobgp/debian/gobgp.service b/src/gobgp/debian/gobgp.service new file mode 100644 index 000000000000..68a0b595aa1d --- /dev/null +++ b/src/gobgp/debian/gobgp.service @@ -0,0 +1,16 @@ +[Unit] +Description=gobgp service +After=network.target +ConditionPathExists=/etc/gobgp/gobgpd.yml + +[Service] +EnvironmentFile=-/etc/default/gobgp +ExecStart=/usr/sbin/gobgpd $DAEMON_ARGS +#ExecReload=/bin/kill -HUP $MAINPID +KillMode=process +Restart=on-failure + +[Install] +WantedBy=multi-user.target +Alias=gobgpd.service + diff --git a/src/gobgp/debian/rules b/src/gobgp/debian/rules new file mode 100755 index 000000000000..b6bee2ee4e76 --- /dev/null +++ b/src/gobgp/debian/rules @@ -0,0 +1,3 @@ +#!/usr/bin/make -f +%: + dh $@ --with systemd diff --git a/src/gobgp/gobgpd.conf.sample b/src/gobgp/gobgpd.conf.sample new file mode 100644 index 000000000000..c308df15be2c --- /dev/null +++ b/src/gobgp/gobgpd.conf.sample @@ -0,0 +1,21 @@ +[global.config] + as = 65501 + router-id = "192.168.0.1" +[[neighbors]] + [neighbors.config] + peer-as = 65502 + neighbor-address = "192.168.0.2" + [neighbors.graceful-restart.config] + enabled = true + restart-time = 120 + [[neighbors.afi-safis]] + [neighbors.afi-safis.config] + afi-safi-name = "ipv4-unicast" + [neighbors.afi-safis.mp-graceful-restart.config] + enabled = true + +[zebra] + [zebra.config] + enabled = true + url = "unix:/var/run/quagga/zserv.api" + redistribute-route-type-list = ["connect"] diff --git a/src/hiredis/.gitignore b/src/hiredis/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/hiredis/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/hiredis/Makefile b/src/hiredis/Makefile new file mode 100644 index 000000000000..4935a039e0af --- /dev/null +++ b/src/hiredis/Makefile @@ -0,0 +1,22 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = libhiredis0.14_$(HIREDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +DERIVED_TARGETS = libhiredis0.14-dbgsym_$(HIREDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb libhiredis-dev_$(HIREDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf hiredis-$(HIREDIS_VERSION) + + wget -O hiredis_$(HIREDIS_VERSION).orig.tar.gz http://http.debian.net/debian/pool/main/h/hiredis/hiredis_$(HIREDIS_VERSION).orig.tar.gz + wget -O hiredis_$(HIREDIS_VERSION_FULL).debian.tar.xz http://http.debian.net/debian/pool/main/h/hiredis/hiredis_$(HIREDIS_VERSION_FULL).debian.tar.xz + wget -O hiredis_$(HIREDIS_VERSION_FULL).dsc http://http.debian.net/debian/pool/main/h/hiredis/hiredis_$(HIREDIS_VERSION_FULL).dsc + + dpkg-source -x hiredis_$(HIREDIS_VERSION_FULL).dsc + pushd hiredis-$(HIREDIS_VERSION) + dpkg-buildpackage -rfakeroot -d -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $* $(DERIVED_TARGETS) $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/iccpd/Makefile.am b/src/iccpd/Makefile.am new file mode 100644 index 000000000000..af437a64d6d8 --- /dev/null +++ b/src/iccpd/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/src/iccpd/autogen.sh b/src/iccpd/autogen.sh new file mode 100755 index 000000000000..c8d0bbe4a251 --- /dev/null +++ b/src/iccpd/autogen.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +libtoolize --force --copy && +autoreconf --force --install -I m4 +rm -Rf autom4te.cache + diff --git a/src/iccpd/configure.ac b/src/iccpd/configure.ac new file mode 100644 index 000000000000..9567d2b5cd7d --- /dev/null +++ b/src/iccpd/configure.ac @@ -0,0 +1,32 @@ +AC_INIT([iccpd],[0.5]) +AC_CONFIG_SRCDIR([]) +AC_CONFIG_AUX_DIR(config) +AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE([foreign]) +AC_LANG_C +AC_PROG_CC +AC_PROG_LIBTOOL +AC_HEADER_STDC + +AC_ARG_ENABLE(debug, +[ --enable-debug Compile with debugging flags], +[case "${enableval}" in + yes) debug=true ;; + no) debug=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; +esac],[debug=false]) +AM_CONDITIONAL(DEBUG, test x$debug = xtrue) + +CPPFLAGS="-D_FORTIFY_SOURCE=2" + +CFLAGS_COMMON="-Wno-unused-result" + +AC_SUBST(CFLAGS_COMMON) + +AC_CONFIG_FILES([ + Makefile + src/Makefile + src/mclagdctl/Makefile +]) + +AC_OUTPUT diff --git a/src/iccpd/debian/changelog b/src/iccpd/debian/changelog new file mode 100644 index 000000000000..a2b3b066bc82 --- /dev/null +++ b/src/iccpd/debian/changelog @@ -0,0 +1,6 @@ +sonic (0.0.5) stable; urgency=medium + + * Initial release. + + -- Tyler Li Thu, 23 Apr 2020 10:00:00 +0800 + diff --git a/src/iccpd/debian/compat b/src/iccpd/debian/compat new file mode 100644 index 000000000000..f599e28b8ab0 --- /dev/null +++ b/src/iccpd/debian/compat @@ -0,0 +1 @@ +10 diff --git a/src/iccpd/debian/control b/src/iccpd/debian/control new file mode 100644 index 000000000000..3c9334af0a65 --- /dev/null +++ b/src/iccpd/debian/control @@ -0,0 +1,18 @@ +Source: sonic +Maintainer: Tyler Li +Section: net +Priority: optional +Build-Depends: dh-exec (>=0.3), debhelper (>= 9), autotools-dev +Standards-Version: 0.0.5 + +Package: iccpd +Architecture: any +Depends: ${shlibs:Depends} +Description: This package contains Inter-Chassis Control Protocol for SONiC project. + +Package: iccpd-dbg +Architecture: any +Section: debug +Priority: extra +Depends: iccpd (=${binary:Version}) +Description: debugging symbols for iccpd diff --git a/src/iccpd/debian/rules b/src/iccpd/debian/rules new file mode 100755 index 000000000000..81f48423874e --- /dev/null +++ b/src/iccpd/debian/rules @@ -0,0 +1,34 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#export DH_VERBOSE = 1 + +# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/* +DPKG_EXPORT_BUILDFLAGS = 1 +include /usr/share/dpkg/default.mk + +# see FEATURE AREAS in dpkg-buildflags(1) +#export DEB_BUILD_MAINT_OPTIONS = hardening=+all + +# see ENVIRONMENT in dpkg-buildflags(1) +# package maintainers to append CFLAGS +#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic +# package maintainers to append LDFLAGS +#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed + + +# main packaging script based on dh7 syntax +%: + dh $@ --with autotools-dev + +# dh_make generated override targets +# This is example for Cmake (See https://bugs.debian.org/641051 ) +#override_dh_auto_configure: +# dh_auto_configure -- \ +# -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH) + +override_dh_auto_install: + dh_auto_install --destdir=debian/iccpd + +override_dh_strip: + dh_strip --dbg-package=iccpd-dbg diff --git a/src/iccpd/include/app_csm.h b/src/iccpd/include/app_csm.h new file mode 100644 index 000000000000..a0565556d24c --- /dev/null +++ b/src/iccpd/include/app_csm.h @@ -0,0 +1,73 @@ +/* + * app_csm.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef APP_CSM_H_ +#define APP_CSM_H_ + +#include + +#include "../include/mlacp_fsm.h" + +struct CSM; + +enum APP_CONNECTION_STATE +{ + APP_NONEXISTENT, + APP_RESET, + APP_CONNSENT, + APP_CONNREC, + APP_CONNECTING, + APP_OPERATIONAL +}; + +typedef enum APP_CONNECTION_STATE APP_CONNECTION_STATE_E; + +struct AppCSM +{ + struct mLACP mlacp; + APP_CONNECTION_STATE_E current_state; + + uint32_t rx_connect_msg_id; + uint32_t tx_connect_msg_id; + uint32_t invalid_msg_id; + + TAILQ_HEAD(app_msg_list, Msg) app_msg_list; + + uint8_t invalid_msg : 1; + uint8_t nak_msg : 1; +}; + +void app_csm_init(struct CSM*, int all); +void app_csm_finalize(struct CSM*); +void app_csm_transit(struct CSM*); +int app_csm_prepare_iccp_msg(struct CSM*, char*, size_t); +void app_csm_enqueue_msg(struct CSM*, struct Msg*); +struct Msg* app_csm_dequeue_msg(struct CSM*); +void app_csm_correspond_from_msg(struct CSM*, struct Msg*); +void app_csm_correspond_from_connect_msg(struct CSM*, struct Msg*); +void app_csm_correspond_from_connect_ack_msg(struct CSM*, struct Msg*); +int app_csm_prepare_nak_msg(struct CSM*, char*, size_t); +int app_csm_prepare_connect_msg(struct CSM*, char*, size_t); +int app_csm_prepare_connect_ack_msg(struct CSM*, char*, size_t); + +#endif /* APP_CSM_H_ */ diff --git a/src/iccpd/include/cmd_option.h b/src/iccpd/include/cmd_option.h new file mode 100644 index 000000000000..ca5582cfcc60 --- /dev/null +++ b/src/iccpd/include/cmd_option.h @@ -0,0 +1,84 @@ +/* + * cmd_option.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef CMD_OPTION_H_ +#define CMD_OPTION_H_ + +#include +#include +#include +#include +#include +#include + +#define OPTION_MAX_LEN 256 +#define MSG_LEN 81 + +#define CMD_OPTION_PARSER_INIT_VALUE \ + { \ + .log_file_path = "/var/log/iccpd.log", \ + .pid_file_path = "/var/run/iccpd/iccpd.pid", \ + .cmd_file_path = "/var/run/iccpd/iccpd.vty", \ + .config_file_path = "/etc/iccpd/iccpd.conf", \ + .mclagdctl_file_path = "/var/run/iccpd/mclagdctl.sock", \ + .console_log = 0, \ + .telnet_port = 2015, \ + .init = cmd_option_parser_init, \ + .finalize = cmd_option_parser_finalize, \ + .dump_usage = cmd_option_parser_dump_usage, \ + .parse = cmd_option_parser_parse, \ + } + +struct CmdOption +{ + char* desc; + char* option; + char* parameter; + LIST_ENTRY(CmdOption) next; +}; + +struct CmdOptionParser +{ + char* log_file_path; + char* pid_file_path; + char* cmd_file_path; + char* config_file_path; + char *mclagdctl_file_path; + uint8_t console_log; + uint16_t telnet_port; + LIST_HEAD(option_list, CmdOption) option_list; + int (*parse)(struct CmdOptionParser*, int, char*[]); + void (*init)(struct CmdOptionParser*); + void (*finalize)(struct CmdOptionParser*); + void (*dump_usage)(struct CmdOptionParser*, char*); +}; + +int cmd_option_parser_parse(struct CmdOptionParser*, int, char*[]); +struct CmdOption* cmd_option_add(struct CmdOptionParser*, char*); +struct CmdOption* cmd_option_find(struct CmdOptionParser*, char*); +void cmd_option_delete(struct CmdOption*); +void cmd_option_parser_init(struct CmdOptionParser*); +void cmd_option_parser_finalize(struct CmdOptionParser*); +void cmd_option_parser_dump_usage(struct CmdOptionParser*, char*); + +#endif /* CMD_OPTION_H_ */ diff --git a/src/iccpd/include/iccp_cli.h b/src/iccpd/include/iccp_cli.h new file mode 100644 index 000000000000..c85fc4316b5f --- /dev/null +++ b/src/iccpd/include/iccp_cli.h @@ -0,0 +1,67 @@ +/* + * iccp_cli.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef _ICCP_CLI_H +#define _ICCP_CLI_H + +#include + +struct CSM; + +typedef enum +{ + QU_TYPE_NONE, + QU_TYPE_MLAG_ADD_PO +} cli_queue_type_et; + +typedef struct cli_param_queue +{ + char ifname[16]; + cli_queue_type_et type; + int param; + int itf_add; + LIST_ENTRY(cli_param_queue) cli_queue_next; +} cli_param_queue_st; + +#define MCLAG_ID_STR "mclag_id" +#define LOCAL_IP_STR "local_ip" +#define PEER_IP_STR "peer_ip" +#define PEER_LINK_STR "peer_link" +#define MCLAG_INTF_STR "mclag_interface" +#define SYSTEM_MAC_STR "system_mac" + +int set_mc_lag_id(struct CSM* csm, uint16_t domain); +int set_peer_link(int mid, const char* ifname); +int set_local_address(int mid, const char* addr); +int set_peer_address(int mid, const char* addr); +int unset_mc_lag_id(struct CSM* csm, uint16_t domain); +int unset_peer_link(int mid); +int unset_local_address(int mid); +int unset_peer_address(int mid); + +int iccp_cli_attach_mclag_domain_to_port_channel(int domain, const char* ifname); +int iccp_cli_detach_mclag_domain_to_port_channel(const char* ifname); +int set_local_system_id(const char* mac); +int unset_local_system_id( ); + +#endif diff --git a/src/iccpd/include/iccp_cmd.h b/src/iccpd/include/iccp_cmd.h new file mode 100644 index 000000000000..01f37456b71d --- /dev/null +++ b/src/iccpd/include/iccp_cmd.h @@ -0,0 +1,29 @@ +/* + * iccp_cmd.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef ICCP_CMD_H_ +#define ICCP_CMD_H_ + +int iccp_config_from_file(char *config_default_dir); + +#endif /* ICCP_CMD_H_ */ diff --git a/src/iccpd/include/iccp_cmd_show.h b/src/iccpd/include/iccp_cmd_show.h new file mode 100644 index 000000000000..a41fbadf8c77 --- /dev/null +++ b/src/iccpd/include/iccp_cmd_show.h @@ -0,0 +1,36 @@ +/* + * iccp_cmd_show.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef _ICCP_CMD_SHOW_H +#define _ICCP_CMD_SHOW_H + +#define ICCP_MAX_PORT_NAME 20 +#define ICCP_MAX_IP_STR_LEN 16 + +extern int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id); +extern int iccp_arp_dump(char * *buf, int *num, int mclag_id); +extern int iccp_ndisc_dump(char * *buf, int *num, int mclag_id); +extern int iccp_mac_dump(char * *buf, int *num, int mclag_id); +extern int iccp_local_if_dump(char * *buf, int *num, int mclag_id); +extern int iccp_peer_if_dump(char * *buf, int *num, int mclag_id); +#endif diff --git a/src/iccpd/include/iccp_consistency_check.h b/src/iccpd/include/iccp_consistency_check.h new file mode 100644 index 000000000000..6fa8ea47e2f4 --- /dev/null +++ b/src/iccpd/include/iccp_consistency_check.h @@ -0,0 +1,43 @@ +/* + * iccp_consistency_check.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + * + */ + +#ifndef _ICCP_CONSISTENCY_CHECK_H +#define _ICCP_CONSISTENCY_CHECK_H + + +enum Reason_ID +{ + REASON_NONE = 0, + REASON_INTERRFACE_MODE_IS_ASYNC, + REASON_PEER_IF_IP_IS_ASYNC, + REASON_PEER_IF_VLAN_IS_ASYNC, + REASON_MAX_ARRAY_SIZE +}; + +extern const char *reasons[]; + +enum Reason_ID iccp_consistency_check(char* ifname); + + +#endif diff --git a/src/iccpd/include/iccp_csm.h b/src/iccpd/include/iccp_csm.h new file mode 100644 index 000000000000..01e424d13271 --- /dev/null +++ b/src/iccpd/include/iccp_csm.h @@ -0,0 +1,168 @@ +/* + * iccp_csm.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef ICCP_CSM_H_ +#define ICCP_CSM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/app_csm.h" +#include "../include/msg_format.h" +#include "../include/port.h" + +#define CSM_BUFFER_SIZE 65536 + +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif /*IFNAMSIZ*/ + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif /* INET_ADDRSTRLEN */ +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif /* INET6_ADDRSTRLEN */ +/* For socket binding */ +#define ICCP_TCP_PORT 8888 +#define MAX_ACCEPT_CONNETIONS 20 + +/* LDP message ID */ +extern uint32_t ICCP_MSG_ID; + +/* Global Buffer */ +extern char g_csm_buf[CSM_BUFFER_SIZE]; + +struct IccpInfo +{ + uint32_t icc_rg_id; + char sender_name[MAX_L_ICC_SENDER_NAME]; + uint32_t status_code; + uint8_t peer_capability_flag : 1; + uint8_t peer_rg_connect_flag : 1; + uint8_t sender_capability_flag : 1; + uint8_t sender_rg_connect_flag : 1; + uint32_t rejected_msg_id; +}; + +/* Receive message node */ +struct Msg +{ + char* buf; + size_t len; + TAILQ_ENTRY(Msg) tail; +}; + +/* Connection state */ +enum ICCP_CONNECTION_STATE +{ + ICCP_NONEXISTENT, + ICCP_INITIALIZED, + ICCP_CAPSENT, + ICCP_CAPREC, + ICCP_CONNECTING, + ICCP_OPERATIONAL +}; + +typedef enum ICCP_CONNECTION_STATE ICCP_CONNECTION_STATE_E; + +typedef enum stp_role_type_e +{ + STP_ROLE_NONE, /* mstp do nothing*/ + STP_ROLE_ACTIVE, /* mstp report port state*/ + STP_ROLE_STANDBY /* mstp fwd bpdu & set port state*/ +} stp_role_type_et; + +/* Connection state machine instance */ +struct CSM +{ + int mlag_id; + + /* Socket info */ + int sock_fd; + pthread_mutex_t conn_mutex; + time_t connTimePrev; + time_t heartbeat_send_time; + time_t heartbeat_update_time; + time_t peer_warm_reboot_time; + time_t warm_reboot_disconn_time; + char peer_itf_name[IFNAMSIZ]; + char peer_ip[INET_ADDRSTRLEN]; + char sender_ip[INET_ADDRSTRLEN]; + void* sock_read_event_ptr; + + /* Msg queue */ + TAILQ_HEAD(msg_list, Msg) msg_list; + + /* STP role */ + stp_role_type_et role_type; + + /* Peers msg */ + struct LocalInterface* peer_link_if; + struct IccpInfo iccp_info; + struct AppCSM app_csm; + ICCP_CONNECTION_STATE_E current_state; + + /* Statistic info */ + uint64_t icc_msg_in_count; /* ICC message input count */ + uint64_t icc_msg_out_count; /* ICC message Output count */ + uint64_t u_msg_in_count; /* Unknown message Input count */ + uint64_t i_msg_in_count; /* Illegal message Input count */ + + /* Log */ + struct MsgLog msg_log; + + LIST_ENTRY(CSM) next; + LIST_HEAD(csm_if_list, If_info) if_bind_list; +}; +int iccp_csm_send(struct CSM*, char*, int); +int iccp_csm_init_msg(struct Msg**, char*, int); +int iccp_csm_prepare_nak_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_iccp_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_capability_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_rg_connect_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_rg_disconnect_msg(struct CSM*, char*, size_t); +struct Msg* iccp_csm_dequeue_msg(struct CSM*); +void *iccp_get_csm(); +void iccp_csm_init(struct CSM*); +void iccp_csm_transit(struct CSM*); +void iccp_csm_finalize(struct CSM*); +void iccp_csm_status_reset(struct CSM*, int); +void iccp_csm_stp_role_count(struct CSM *csm); +void iccp_csm_msg_list_finalize(struct CSM*); +void iccp_csm_enqueue_msg(struct CSM*, struct Msg*); +void iccp_csm_fill_icc_rg_id_tlv(struct CSM*, ICCHdr*); +void iccp_csm_correspond_from_msg(struct CSM*, struct Msg*); +void iccp_csm_correspond_from_capability_msg(struct CSM*, struct Msg*); +void iccp_csm_correspond_from_rg_connect_msg(struct CSM*, struct Msg*); +void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM*, struct Msg*); + +int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname); + +#endif /* ICCP_CSM_H_ */ diff --git a/src/iccpd/include/iccp_ifm.h b/src/iccpd/include/iccp_ifm.h new file mode 100644 index 000000000000..bbb1af67ee90 --- /dev/null +++ b/src/iccpd/include/iccp_ifm.h @@ -0,0 +1,42 @@ +/* + * iccp_ifm.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef ICCP_IFM_H +#define ICCP_IFM_H + +#include + +int iccp_sys_local_if_list_get_init(); + +int iccp_neigh_get_init(); + +void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]); +void do_ndisc_update_from_reply_packet(unsigned int ifindex, char *ipv6_addr, uint8_t mac_addr[ETHER_ADDR_LEN]); + +int do_one_neigh_request(struct nlmsghdr *n); + +void iccp_from_netlink_port_state_handler( char * ifname, int state); + +void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n); +#endif // LACP_IFM_H + diff --git a/src/iccpd/include/iccp_netlink.h b/src/iccpd/include/iccp_netlink.h new file mode 100644 index 000000000000..a4f321736d0c --- /dev/null +++ b/src/iccpd/include/iccp_netlink.h @@ -0,0 +1,67 @@ +/* Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef ICCP_NETLINK_H +#define ICCP_NETLINK_H +#include +#include +#include +#include +#include +#include + +#include + +#include "../include/system.h" +#include "../include/port.h" +#include +#include + +#define NDISC_NEIGHBOUR_ADVERTISEMENT 136 +#define ND_OPT_TARGET_LL_ADDR 2 +#define NEXTHDR_ICMP 58 + +struct nd_msg +{ + struct icmp6_hdr icmph; + struct in6_addr target; + __u8 opt[0]; +}; + +struct in6_pktinfo +{ + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ +}; + +int iccp_get_port_member_list(struct LocalInterface* lif); +void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg); +void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg); +int iccp_system_init_netlink_socket(); +void iccp_system_dinit_netlink_socket(); +int iccp_init_netlink_event_fd(struct System *sys); +int iccp_handle_events(struct System * sys); +void update_if_ipmac_on_standby(struct LocalInterface* lif_po); +int iccp_sys_local_if_list_get_addr(); +int iccp_netlink_neighbor_request(int family, uint8_t *addr, int add, uint8_t *mac, char *portname); +int iccp_check_if_addr_from_netlink(int family, uint8_t *addr, struct LocalInterface *lif); + +#endif + diff --git a/src/iccpd/include/logger.h b/src/iccpd/include/logger.h new file mode 100644 index 000000000000..a90fece2a4d9 --- /dev/null +++ b/src/iccpd/include/logger.h @@ -0,0 +1,70 @@ +/* + * logger.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef LOGGER_H_ +#define LOGGER_H_ + +#include +#include + +#include "../include/cmd_option.h" + +typedef enum _iccpd_log_level_t +{ + CRITICAL_LOG_LEVEL = 0, + ERR_LOG_LEVEL = 1, + WARN_LOG_LEVEL = 2, + NOTICE_LOG_LEVEL = 3, + INFO_LOG_LEVEL = 4, + DEBUG_LOG_LEVEL = 5 +} _iccpd_log_level_t; + + +#define LOGBUF_SIZE 1024 +#define ICCPD_UTILS_SYSLOG (syslog) + +#define ICCPD_LOG_CRITICAL(tag, format, args ...) write_log(CRITICAL_LOG_LEVEL, tag, format, ## args) +#define ICCPD_LOG_ERR(tag, format, args ...) write_log(ERR_LOG_LEVEL, tag, format, ## args) +#define ICCPD_LOG_WARN(tag, format, args ...) write_log(WARN_LOG_LEVEL, tag, format, ## args) +#define ICCPD_LOG_NOTICE(tag, format, args ...) write_log(NOTICE_LOG_LEVEL, tag, format, ## args) +#define ICCPD_LOG_INFO(tag, format, args ...) write_log(INFO_LOG_LEVEL, tag, format, ## args) +#define ICCPD_LOG_DEBUG(tag, format, args ...) write_log(DEBUG_LOG_LEVEL, tag, format, ## args) + +struct LoggerConfig +{ + uint8_t console_log_enabled; + uint8_t log_level; + uint8_t init; +}; + +struct LoggerConfig* logger_get_configuration(); +void logger_set_configuration(int log_level); +char* log_level_to_string(int level); +void log_setup(char* progname, char* path); +void log_finalize(); +void log_init(struct CmdOptionParser* parser); +void write_log(const int level, const char* tag, const char *format, ...); + +#endif /* LOGGER_H_ */ + + diff --git a/src/iccpd/include/mlacp_fsm.h b/src/iccpd/include/mlacp_fsm.h new file mode 100644 index 000000000000..b335e78cd007 --- /dev/null +++ b/src/iccpd/include/mlacp_fsm.h @@ -0,0 +1,109 @@ +/* + * mlacp_fsm.h + * mLACP finite state machine handler. + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef _MLACP_FSM_H +#define _MLACP_FSM_H + +#include "../include/port.h" + +#define MLCAP_SYNC_PHY_DEV_SEC 1 /*every 1 sec*/ + +#define MLACP(csm_ptr) (csm_ptr->app_csm.mlacp) + +struct CSM; + +enum MLACP_APP_STATE +{ + MLACP_STATE_INIT, + MLACP_STATE_STAGE1, + MLACP_STATE_STAGE2, + MLACP_STATE_EXCHANGE, + MLACP_STATE_ERROR, +}; + +typedef enum MLACP_APP_STATE MLACP_APP_STATE_E; + +/* for sender only*/ +enum MLACP_SYNC_STATE +{ + MLACP_SYNC_SYSCONF=0, + MLACP_SYNC_AGGCONF, + MLACP_SYNC_AGGSTATE, + MLACP_SYNC_AGGINFO, + MLACP_SYNC_PEERLINKINFO, + MLACP_SYNC_ARP_INFO, + MLACP_SYNC_NDISC_INFO, + MLACP_SYNC_DONE, +}; + +typedef enum MLACP_SYNC_STATE MLACP_SYNC_STATE_E; + +struct Remote_System +{ + uint8_t system_id[ETHER_ADDR_LEN]; + uint16_t system_priority; + uint32_t node_id; +}; + +struct mLACP +{ + int id; + int sync_req_num; + + MLACP_APP_STATE_E current_state; + MLACP_SYNC_STATE_E sync_state; + + uint8_t wait_for_sync_data; + uint8_t need_to_sync; + uint8_t node_id; + uint8_t system_id[ETHER_ADDR_LEN]; + uint16_t system_priority; + uint8_t system_config_changed; + + struct Remote_System remote_system; + const char* error_msg; + TAILQ_HEAD(mlacp_msg_list, Msg) mlacp_msg_list; + TAILQ_HEAD(arp_msg_list, Msg) arp_msg_list; + TAILQ_HEAD(arp_info_list, Msg) arp_list; + TAILQ_HEAD(ndisc_msg_list, Msg) ndisc_msg_list; + TAILQ_HEAD(ndisc_info_list, Msg) ndisc_list; + TAILQ_HEAD(mac_msg_list, Msg) mac_msg_list; + TAILQ_HEAD(mac_info_list, Msg) mac_list; + + LIST_HEAD(lif_list, LocalInterface) lif_list; + LIST_HEAD(lif_purge_list, LocalInterface) lif_purge_list; + LIST_HEAD(pif_list, PeerInterface) pif_list; +}; + +void mlacp_init(struct CSM* csm, int all); +void mlacp_finalize(struct CSM* csm); +void mlacp_fsm_transit(struct CSM* csm); +void mlacp_enqueue_msg(struct CSM*, struct Msg*); +struct Msg* mlacp_dequeue_msg(struct CSM*); + +/* from app_csm*/ +extern int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* local_if); +extern int mlacp_unbind_local_if(struct LocalInterface* local_if); + +#endif /* _MLACP_HANDLER_H */ diff --git a/src/iccpd/include/mlacp_link_handler.h b/src/iccpd/include/mlacp_link_handler.h new file mode 100644 index 000000000000..624b4111a7ee --- /dev/null +++ b/src/iccpd/include/mlacp_link_handler.h @@ -0,0 +1,60 @@ +/* + * mlacp_link_handler.h + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef __MLACP_LINK_HANDLER__ +#define __MLACP_LINK_HANDLER__ + +#include "../include/iccp_csm.h" +#include "../include/mlacp_tlv.h" + +/***************************************** +* Link Handler +* +* ***************************************/ +void mlacp_portchannel_state_handler(struct CSM* csm, struct LocalInterface* local_if, int po_state); +void mlacp_peer_conn_handler(struct CSM* csm); +void mlacp_peer_disconn_handler(struct CSM* csm); +void mlacp_peerlink_up_handler(struct CSM* csm); +void mlacp_peerlink_down_handler(struct CSM* csm); +void update_stp_peer_link(struct CSM *csm, struct PeerInterface *peer_if, int po_state, int new_create); +void update_peerlink_isolate_from_pif(struct CSM *csm, struct PeerInterface *pif, int po_state, int new_create); +void mlacp_mlag_link_add_handler(struct CSM *csm, struct LocalInterface *lif); +void mlacp_mlag_link_del_handler(struct CSM *csm, struct LocalInterface *lif); +void set_peerlink_mlag_port_learn(struct LocalInterface *lif, int enable); +void peerlink_port_isolate_cleanup(struct CSM* csm); +void update_peerlink_isolate_from_all_csm_lif(struct CSM* csm); + +void del_mac_from_chip(struct MACMsg *mac_msg); +void add_mac_to_chip(struct MACMsg *mac_msg, uint8_t mac_type); +uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg *mac_msg, uint8_t set); +void iccp_get_fdb_change_from_syncd(void); + +extern int mclagd_ctl_sock_create(); +extern int mclagd_ctl_sock_accept(int fd); +extern int mclagd_ctl_interactive_process(int client_fd); +extern int parseMacString(const char *str_mac, uint8_t *bin_mac); +char *show_ip_str(uint32_t ipv4_addr); +char *show_ipv6_str(char *ipv6_addr); + +void syncd_info_close(); +int iccp_connect_syncd(); +#endif diff --git a/src/iccpd/include/mlacp_sync_prepare.h b/src/iccpd/include/mlacp_sync_prepare.h new file mode 100644 index 000000000000..17cd8f260155 --- /dev/null +++ b/src/iccpd/include/mlacp_sync_prepare.h @@ -0,0 +1,56 @@ +/* + * mlacp_sync_prepare.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef __MLACP_SYNC_PREPARE__ +#define __MLACP_SYNC_PREPARE__ + +struct CSM; +/***************************************** +* Tool Function +* +* ***************************************/ +void update_system_id(struct CSM* csm); + +/***************************************** +* LACP Sync +* +* ***************************************/ +int mlacp_sync_with_kernel_callback(); + +/***************************************** +* MLACP Sync +* +* ***************************************/ +int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_buf_size); +int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end); +int mlacp_prepare_for_sys_config(struct CSM* csm, char* buf, size_t max_buf_size); +int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg, int count); +int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count); +int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size, struct NDISCMsg *ndisc_msg, int count); +int mlacp_prepare_for_heartbeat(struct CSM* csm, char* buf, size_t max_buf_size); +int mlacp_prepare_for_Aggport_state(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* local_if); +int mlacp_prepare_for_Aggport_config(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* lif, int purge_flag); +int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* port_channel); +int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* peerlink_port); +int iccp_netlink_if_hwaddr_set(uint32_t ifindex, uint8_t *addr, unsigned int addr_len); +#endif \ No newline at end of file diff --git a/src/iccpd/include/mlacp_sync_update.h b/src/iccpd/include/mlacp_sync_update.h new file mode 100644 index 000000000000..2a5d5b598d05 --- /dev/null +++ b/src/iccpd/include/mlacp_sync_update.h @@ -0,0 +1,50 @@ +/* + * + * mlacp_sync_update.h + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef __MLACP_SYNC_UPDATE__ +#define __MLACP_SYNC_UPDATE__ + +#include "iccp_csm.h" +#include "mlacp_tlv.h" + +/***************************************** +* FSM Sync Update API +* +* ***************************************/ +int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV* tlv); + +int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv); + +int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv); +int mlacp_fsm_update_ndisc_info(struct CSM *csm, struct mLACPNDISCInfoTLV* tlv); + +int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv); + +int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv); +void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg); +void mlacp_enqueue_ndisc(struct CSM *csm, struct Msg* msg); +int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf); +int mlacp_fsm_update_port_channel_info(struct CSM* csm, struct mLACPPortChannelInfoTLV* tlv); +int mlacp_fsm_update_peerlink_info(struct CSM* csm, struct mLACPPeerLinkInfoTLV* tlv); +int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* tlv); +#endif \ No newline at end of file diff --git a/src/iccpd/include/mlacp_tlv.h b/src/iccpd/include/mlacp_tlv.h new file mode 100644 index 000000000000..7d3a4e18e4e2 --- /dev/null +++ b/src/iccpd/include/mlacp_tlv.h @@ -0,0 +1,475 @@ +/* + * mlacp_tlv.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef MLACP_TLV_H_ +#define MLACP_TLV_H_ + +#include + +#include "../include/msg_format.h" +#include "../include/port.h" + +#define MLACP_SYSCONF_NODEID_MSB_MASK 0x80 +#define MLACP_SYSCONF_NODEID_NODEID_MASK 0x70 +#define MLACP_SYSCONF_NODEID_FREE_MASK 0x0F + +/* + * RFC 7275 + * 7.2.3. mLACP System Config TLV + * [Page 51] + */ +struct mLACPSysConfigTLV +{ + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.3.2. */ + uint8_t sys_id[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.3.2. */ + uint16_t sys_priority; + /* + * RFC 7275 + * 7.2.3. mLACP System Config TLV + * [Page 51] + */ + uint8_t node_id; +} __attribute__ ((packed)); + +typedef struct mLACPSysConfigTLV mLACPSysConfigTLV; + +/* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 52] + * NOTE: In this project, Aggregator configuration and state TLV is not support. + */ +struct mLACPAggConfigTLV +{ + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ + uint8_t ro_id[8]; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ + uint8_t mac_addr[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ + uint16_t member_ports_priority; + uint8_t flags; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 54] + */ + uint8_t agg_name_len; + char agg_name[MAX_L_PORT_NAME]; +} __attribute__ ((packed)); + +typedef struct mLACPAggConfigTLV mLACPAggConfigTLV; + +/* + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 54] + */ +struct mLACPPortConfigTLV +{ + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t port_num; + /* + * RFC 7275 + * 7.2.5. mLACP Port Config TLV + * [Page 55] + */ + uint8_t mac_addr[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t port_priority; + /* IF-MIB [RFC2863] */ + uint32_t port_speed; + /* + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 55] + */ + uint8_t flags; + /* + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 56] + */ + uint8_t port_name_len; + /* IF-MIB [RFC2863] */ + char port_name[MAX_L_PORT_NAME]; + + /* NOS */ + uint8_t l3_mode; +} __attribute__ ((packed)); + +typedef struct mLACPPortConfigTLV mLACPPortConfigTLV; + +/* + * RFC 7275 + * 7.2.6. mLACP Port Priority TLV + * [Page 56] + */ +struct mLACPPortPriorityTLV +{ + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.6. mLACP Port Priority TLV + * [Page 57] + */ + uint16_t op_code; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t port_num; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t last_port_priority; + uint16_t current_port_priority; +} __attribute__ ((packed)); + +typedef struct mLACPPortPriorityTLV mLACPPortPriorityTLV; + +/* + * RFC 7275 + * 7.2.7. mLACP Port State TLV + * [Page 58] + */ +struct mLACPPortStateTLV +{ + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.4.2.2, item r. */ + uint8_t partner_sys_id[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.4.2.2, item q. */ + uint16_t partner_sys_priority; + /* [IEEE-802.1AX], Section 5.4.2.2, item u. */ + uint16_t partner_port_num; + /* [IEEE-802.1AX], Section 5.4.2.2, item t. */ + uint16_t partner_port_priority; + /* [IEEE-802.1AX], Section 5.4.2.2, item s. */ + uint16_t partner_key; + /* [IEEE-802.1AX], Section 5.4.2.2, item v. */ + uint8_t partner_state; + /* [IEEE-802.1AX], Section 5.4.2.2, item m. */ + uint8_t actor_state; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t actor_port_num; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* [IEEE-802.1AX], Section 5.4.8 */ + uint8_t selected; + /* + * RFC 7275 + * 7.2.7. mLACP Port State TLV + * [Page 60] + */ + uint8_t port_state; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + + /* NOS */ + uint16_t port_id; + uint8_t l3_mode; + uint8_t is_peer_link; +} __attribute__ ((packed)); + +typedef struct mLACPPortStateTLV mLACPPortStateTLV; + +/* + * RFC 7275 + * 7.2.8. mLACP Aggregator State TLV + * [Page 60] + * NOTE: In this project, Aggregator configuration and state TLV is not support. + */ +struct mLACPAggPortStateTLV +{ + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.4.2.2, item r. */ + uint8_t partner_sys_id[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.4.2.2, item q. */ + uint16_t partner_sys_priority; + /* [IEEE-802.1AX], Section 5.4.2.2, item s. */ + uint16_t partner_key; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* + * RFC 7275 + * 7.2.8. mLACP Aggregator State TLV + * [Page 61] + */ + uint8_t agg_state; +} __attribute__ ((packed)); + +typedef struct mLACPAggPortStateTLV mLACPAggPortStateTLV; + +/* + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 61] + */ +struct mLACPSyncReqTLV +{ + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 62] + */ + uint16_t req_num; + +#if __BYTE_ORDER == __BIG_ENDIAN + uint16_t c_bit : 1; + /* + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 63] + */ + uint16_t s_bit : 1; + uint16_t req_type : 14; +#elif __BYTE_ORDER == __LITTLE_ENDIAN + uint16_t req_type : 14; + /* + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 63] + */ + uint16_t s_bit : 1; + uint16_t c_bit : 1; +#endif + /* [IEEE-802.1AX], Section 5.3.4. */ + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t port_num_agg_id; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; +} __attribute__ ((packed)); + +typedef struct mLACPSyncReqTLV mLACPSyncReqTLV; + +/* + * RFC 7275 + * 7.2.10. mLACP Synchronization Data TLV + * [Page 63] + */ +struct mLACPSyncDataTLV +{ + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.10. mLACP Synchronization Data TLV + * [Page 64] + */ + uint16_t req_num; + uint16_t flags; +} __attribute__ ((packed)); + +typedef struct mLACPSyncDataTLV mLACPSyncDataTLV; + +/* VLAN Information TLV*/ +struct mLACPVLANData +{ + uint16_t vlan_id; +} __attribute__ ((packed)); + +/* + * Port Channel Information TLV + */ +struct mLACPPortChannelInfoTLV +{ + ICCParameter icc_parameter; + uint16_t agg_id; + char if_name[MAX_L_PORT_NAME]; + uint8_t if_name_len; + uint8_t l3_mode; + uint32_t ipv4_addr; + uint16_t po_id; + uint16_t num_of_vlan_id; + struct mLACPVLANData vlanData[0]; +} __attribute__ ((packed)); + +typedef struct mLACPPortChannelInfoTLV mLACPPortChannelInfoTLV; + +/* + * Port PeerLink Information TLV + */ +struct mLACPPeerLinkInfoTLV +{ + ICCParameter icc_parameter; + char if_name[MAX_L_PORT_NAME]; + uint8_t port_type; +} __attribute__ ((packed)); + +typedef struct mLACPPeerLinkInfoTLV mLACPPeerLinkInfoTLV; + +struct mLACPVLANInfoTLV +{ + ICCParameter icc_parameter; + uint16_t id; /* Local Interface ID, not VLAN ID */ + uint16_t num_of_vlan_id; + struct mLACPVLANData vlanData[0]; +} __attribute__ ((packed)); + +/* Mac entry Information TLV*/ +struct mLACPMACData +{ + uint8_t type;/*add or del*/ + char mac_str[ETHER_ADDR_STR_LEN]; + uint16_t vid; + /*Current if name that set in chip*/ + char ifname[MAX_L_PORT_NAME]; +} __attribute__ ((packed)); + +/* + * MAC Information TLV + */ +struct mLACPMACInfoTLV +{ + ICCParameter icc_parameter; + uint16_t num_of_entry; + struct mLACPMACData MacEntry[0]; +} __attribute__ ((packed)); + +struct ARPMsg +{ + uint8_t op_type; + char ifname[MAX_L_PORT_NAME]; + uint32_t ipv4_addr; + uint8_t mac_addr[ETHER_ADDR_LEN]; +}; + +struct NDISCMsg +{ + uint8_t op_type; + char ifname[MAX_L_PORT_NAME]; + uint32_t ipv6_addr[4]; + uint8_t mac_addr[ETHER_ADDR_LEN]; +}; + +/* + * ARP Information TLV + */ +struct mLACPARPInfoTLV +{ + ICCParameter icc_parameter; + /* Local Interface ID */ + uint16_t num_of_entry; + struct ARPMsg ArpEntry[0]; +} __attribute__ ((packed)); + +/* + * NDISC Information TLV + */ +struct mLACPNDISCInfoTLV +{ + ICCParameter icc_parameter; + /* Local Interface ID */ + uint16_t num_of_entry; + struct NDISCMsg NdiscEntry[0]; +} __attribute__ ((packed)); + +/* + * NOS: STP Information TLV + */ +struct stp_msg_s; +struct mLACPSTPInfoTLV +{ + ICCParameter icc_parameter; + uint8_t stp_msg[0]; +} __attribute__ ((packed)); + +/* + * NOS: Heartbeat + */ +struct mLACPHeartbeatTLV +{ + ICCParameter icc_parameter; + uint8_t heartbeat; +} __attribute__ ((packed)); + +/* + * NOS: Warm_reboot + */ +struct mLACPWarmbootTLV +{ + ICCParameter icc_parameter; + uint8_t warmboot; +} __attribute__ ((packed)); + +enum NEIGH_OP_TYPE +{ + NEIGH_SYNC_LIF, + NEIGH_SYNC_ADD, + NEIGH_SYNC_DEL, +}; + +enum MAC_AGE_TYPE +{ + MAC_AGE_LOCAL = 1, /*MAC in local switch is ageout*/ + MAC_AGE_PEER = 2, /*MAC in peer switch is ageout*/ +}; + +enum MAC_OP_TYPE +{ + MAC_SYNC_ADD = 1, + MAC_SYNC_DEL = 2, + MAC_SYNC_ACK = 4, +}; + +enum MAC_TYPE +{ + MAC_TYPE_STATIC = 1, + MAC_TYPE_DYNAMIC = 2, +}; + +struct MACMsg +{ + uint8_t op_type; /*add or del*/ + uint8_t fdb_type; /*static or dynamic*/ + char mac_str[ETHER_ADDR_STR_LEN]; + uint16_t vid; + /*Current if name that set in chip*/ + char ifname[MAX_L_PORT_NAME]; + /*if we set the mac to peer-link, origin_ifname store the + original if name that learned from chip*/ + char origin_ifname[MAX_L_PORT_NAME]; + uint8_t age_flag;/*local or peer is age?*/ +}; + +#endif /* MLACP_TLV_H_ */ diff --git a/src/iccpd/include/msg_format.h b/src/iccpd/include/msg_format.h new file mode 100644 index 000000000000..1af8bf8a46a8 --- /dev/null +++ b/src/iccpd/include/msg_format.h @@ -0,0 +1,500 @@ +/* + * msg_format.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef MSG_FORMAT_H_ +#define MSG_FORMAT_H_ +#include +#include +#include "../include/port.h" + +#define MAX_MSG_LOG_SIZE 128 + +/* + * RFC 5561 + * 4. Capability Message + * [Page 7] + */ +#define MSG_T_CAPABILITY 0x0202 + +/* + * RFC 7275 + * 6.1.1. ICC Header - Message Length + * [Page 25] + * 2-octet integer specifying the total length of this message in octets, + * excluding the "U-bit", "Message Type", and "Length" fields. + */ +#define MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS 4 + +/* + * RFC 7275 + * 12.1. Message Type Name Space + * [Page 79] + */ +#define MSG_T_RG_CONNECT 0x0700 +#define MSG_T_RG_DISCONNECT 0x0701 +#define MSG_T_NOTIFICATION 0x0702 +#define MSG_T_RG_APP_DATA 0x0703 + +/* + * RFC 7275 + * 12.2. TLV Type Name Space + * [Page 79] + */ +#define TLV_T_ICCP_CAPABILITY 0x0700 +#define TLV_L_ICCP_CAPABILITY 0x4 + +/* + * RFC 7275 + * 12.3. ICC RG Parameter Type Space + * [Page 80] + */ +#define TLV_T_ICC_SENDER_NAME 0x0001 +#define MAX_L_ICC_SENDER_NAME 80 +#define TLV_T_NAK 0x0002 +#define TLV_T_REQUESTED_PROTOCOL_VER 0x0003 +#define TLV_T_DISCONNECT_CODE 0x0004 +#define TLV_L_DISCONNECT_CODE 0x4 +#define TLV_T_ICC_RG_ID 0x0005 +#define TLV_L_ICC_RG_ID 0x4 + +#define TLV_T_MLACP_CONNECT 0x0030 +#define TLV_T_MLACP_DISCONNECT 0x0031 +#define TLV_T_MLACP_SYSTEM_CONFIG 0x0032 +#define TLV_T_MLACP_PORT_CONFIG 0x0033 //no support +#define TLV_T_MLACP_PORT_PRIORITY 0x0034 //no support +#define TLV_T_MLACP_PORT_STATE 0x0035 //no support +#define TLV_T_MLACP_AGGREGATOR_CONFIG 0x0036 +#define TLV_T_MLACP_AGGREGATOR_STATE 0x0037 +#define TLV_T_MLACP_SYNC_REQUEST 0x0038 +#define TLV_T_MLACP_SYNC_DATA 0x0039 +#define TLV_T_MLACP_HEARTBEAT 0x003A +#define TLV_T_MLACP_DISCONNECT_CAUSE 0x003B //not yet + +/* Self define Feature */ +#define TLV_T_MLACP_ORPHAN_PORT 0x1033 //not yet +#define TLV_T_MLACP_PORT_CHANNEL_INFO 0x1034 +#define TLV_T_MLACP_PEERLINK_INFO 0x1035 +#define TLV_T_MLACP_ARP_INFO 0x1036 +#define TLV_T_MLACP_STP_INFO 0x1037//no support +#define TLV_T_MLACP_MAC_INFO 0x1038 +#define TLV_T_MLACP_WARMBOOT_FLAG 0x1039 +#define TLV_T_MLACP_NDISC_INFO 0x103A +#define TLV_T_MLACP_LIST_END 0x104a // list end + +/* Debug */ +static char* get_tlv_type_string(int type) +{ + switch (type) + { + case TLV_T_ICCP_CAPABILITY: + return "TLV_T_ICCP_CAPABILITY"; + + case TLV_T_ICC_SENDER_NAME: + return "TLV_T_ICC_SENDER_NAME"; + + case TLV_T_NAK: + return "TLV_T_NAK"; + + case TLV_T_REQUESTED_PROTOCOL_VER: + return "TLV_T_REQUESTED_PROTOCOL_VER"; + + case TLV_T_DISCONNECT_CODE: + return "TLV_T_DISCONNECT_CODE"; + + case TLV_T_ICC_RG_ID: + return "TLV_T_ICC_RG_ID"; + + case TLV_T_MLACP_CONNECT: + return "TLV_T_MLACP_CONNECT"; + + case TLV_T_MLACP_DISCONNECT: + return "TLV_T_MLACP_DISCONNECT"; + + case TLV_T_MLACP_SYSTEM_CONFIG: + return "TLV_T_MLACP_SYSTEM_CONFIG"; + + case TLV_T_MLACP_PORT_CONFIG: + return "TLV_T_MLACP_PORT_CONFIG"; + + case TLV_T_MLACP_PORT_PRIORITY: + return "TLV_T_MLACP_PORT_PRIORITY"; + + case TLV_T_MLACP_PORT_STATE: + return "TLV_T_MLACP_PORT_STATE"; + + case TLV_T_MLACP_AGGREGATOR_CONFIG: + return "TLV_T_MLACP_AGGREGATOR_CONFIG"; + + case TLV_T_MLACP_AGGREGATOR_STATE: + return "TLV_T_MLACP_AGGREGATOR_STATE"; + + case TLV_T_MLACP_SYNC_REQUEST: + return "TLV_T_MLACP_SYNC_REQUEST"; + + case TLV_T_MLACP_SYNC_DATA: + return "TLV_T_MLACP_SYNC_DATA"; + + case TLV_T_MLACP_HEARTBEAT: + return "TLV_T_MLACP_HEARTBEAT"; + + case TLV_T_MLACP_DISCONNECT_CAUSE: + return "TLV_T_MLACP_DISCONNECT_CAUSE"; + + /* NOS Feature */ + case TLV_T_MLACP_ORPHAN_PORT: + return "TLV_T_MLACP_ORPHAN_PORT"; + + case TLV_T_MLACP_PORT_CHANNEL_INFO: + return "TLV_T_MLACP_PORT_CHANNEL_INFO"; + + case TLV_T_MLACP_PEERLINK_INFO: + return "TLV_T_MLACP_PEERLINK_INFO"; + + case TLV_T_MLACP_ARP_INFO: + return "TLV_T_MLACP_ARP_INFO"; + + case TLV_T_MLACP_MAC_INFO: + return "TLV_T_MLACP_MAC_INFO"; + + case TLV_T_MLACP_STP_INFO: + return "TLV_T_MLACP_STP_INFO"; + } + + return "UNKNOWN"; +} + +/* + * RFC 7275 + * 12.4. Status Code Name Space + * [Page 81] + */ +#define STATUS_CODE_U_ICCP_RG 0x00010001 +#define STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED 0x00010002 +#define STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED 0x00010003 +#define STATUS_CODE_ICCP_APP_NOT_IN_RG 0x00010004 +#define STATUS_CODE_INCOMPATIBLE_ICCP_PROTOCOL_VER 0x00010005 +#define STATUS_CODE_ICCP_REJECTED_MSG 0x00010006 +#define STATUS_CODE_ICCP_ADMINISTRATIVELY_DISABLED 0x00010007 +#define STATUS_CODE_ICCP_RG_REMOVED 0x00010010 +#define STATUS_CODE_ICCP_APP_REMOVED_FROM_RG 0x00010011 + + +/* Debug */ +static char* get_status_string(int status) +{ + switch (status) + { + case STATUS_CODE_U_ICCP_RG: + return "Unknown ICCP RG"; + + case STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED: + return "ICCP Connection Count Exceeded"; + + case STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED: + return "ICCP Application Connection Count Exceede"; + + case STATUS_CODE_ICCP_APP_NOT_IN_RG: + return "ICCP Application not in RG"; + + case STATUS_CODE_INCOMPATIBLE_ICCP_PROTOCOL_VER: + return "Incompatible ICCP Protocol Version"; + + case STATUS_CODE_ICCP_REJECTED_MSG: + return "ICCP Rejected Message"; + + case STATUS_CODE_ICCP_ADMINISTRATIVELY_DISABLED: + return "ICCP Administratively Disabled"; + + case STATUS_CODE_ICCP_RG_REMOVED: + return "ICCP RG Removed"; + + case STATUS_CODE_ICCP_APP_REMOVED_FROM_RG: + return "ICCP Application Removed from RG"; + } + + return "UNKNOWN"; +} +/* + * RFC 5036 + * 3.5. LDP Messages + * [Page 44] + */ +struct LDPHdr +{ +#if __BYTE_ORDER == __BIG_ENDIAN + uint16_t u_bit : 1; + uint16_t msg_type : 15; +#elif __BYTE_ORDER == __LITTLE_ENDIAN + uint16_t msg_type : 15; + uint16_t u_bit : 1; +#endif + uint16_t msg_len; + uint32_t msg_id; +} __attribute__ ((packed)); + +typedef struct LDPHdr LDPHdr; + +/* + * RFC 7275 + * 6.1.1. ICC Header + * [Page 24] + */ +struct ICCRGIDTLV +{ + uint16_t type; + uint16_t len; + uint32_t icc_rg_id; +} __attribute__ ((packed)); + +typedef struct ICCRGIDTLV ICCRGIDTLV; + +struct ICCHdr +{ + LDPHdr ldp_hdr; + ICCRGIDTLV icc_rg_id_tlv; +} __attribute__ ((packed)); + +typedef struct ICCHdr ICCHdr; + +/* + * RFC 7275 + * 6.1.2. ICC Parameter Encoding + * [Page 26] + */ +struct ICCParameter +{ +#if __BYTE_ORDER == __BIG_ENDIAN + uint16_t u_bit : 1; + uint16_t f_bit : 1; + uint16_t type : 14; +#elif __BYTE_ORDER == __LITTLE_ENDIAN + uint16_t type : 14; + uint16_t f_bit : 1; + uint16_t u_bit : 1; +#endif + uint16_t len; +} __attribute__ ((packed)); + +typedef struct ICCParameter ICCParameter; + +/* + * RFC 7275 + * 6.2.1. ICC Sender Name TLV + * [Page 28] + */ +struct ICCSenderNameTLV +{ + ICCParameter icc_parameter; + char sender_name[MAX_L_ICC_SENDER_NAME]; +} __attribute__ ((packed)); + +typedef struct ICCSenderNameTLV ICCSenderNameTLV; + +/* + * RFC 7275 + * 6.3. RG Disconnect Message + * [Page 29] + */ +struct DisconnectCodeTLV +{ + ICCParameter icc_parameter; + uint32_t iccp_status_code; +} __attribute__ ((packed)); + +typedef struct DisconnectCodeTLV DisconnectCodeTLV; + +/* + * RFC 7275 + * 6.4.1. Notification Message TLVs + * [Page 32] + */ +struct NAKTLV +{ + ICCParameter icc_parameter; + uint32_t iccp_status_code; + uint32_t rejected_msg_id; +} __attribute__ ((packed)); + +typedef struct NAKTLV NAKTLV; + +/* + * RFC 7275 + * 6.4.1. Notification Message TLVs + * [Page 34] + */ +struct RequestedProtocolVerTLV +{ + ICCParameter icc_parameter; + uint16_t connection_ref; + uint16_t requested_ver; +} __attribute__ ((packed)); + +typedef struct RequestedProtocolVerTLV RequestedProtocolVerTLV; + +/* + * RFC 7275 + * 8. LDP Capability Negotiation + * [Page 65] + */ +struct LDPICCPCapabilityTLV +{ + ICCParameter icc_parameter; +#if __BYTE_ORDER == __BIG_ENDIAN + uint16_t s_bit : 1; + uint16_t reserved : 15; +#elif __BYTE_ORDER == __LITTLE_ENDIAN + uint16_t reserved : 15; + uint16_t s_bit : 1; +#endif + uint8_t major_ver; + uint8_t minior_ver; +} __attribute__ ((packed)); + +typedef struct LDPICCPCapabilityTLV LDPICCPCapabilityTLV; + +/* + * RFC 7275 + * 7.2.1. mLACP Connect TLV + * [Page 47] + */ +struct AppConnectTLV +{ + ICCParameter icc_parameter; + uint16_t protocol_version; +#if __BYTE_ORDER == __BIG_ENDIAN + uint16_t a_bit : 1; + uint16_t reserved : 15; +#elif __BYTE_ORDER == __LITTLE_ENDIAN + uint16_t reserved : 15; + uint16_t a_bit : 1; +#endif + + /* Optional Sub-TLVs */ + /* No optional sub-TLVs in this version */ +} __attribute__ ((packed)); + +typedef struct AppConnectTLV AppConnectTLV; + +/* + * RFC 7275 + * 7.2.2. mLACP Disconnect TLV + * [Page 48] + */ +struct AppDisconnectTLV +{ + ICCParameter icc_parameter; + + /* Optional Sub-TLVs */ + /* mLACP Disconnect Cause TLV */ +} __attribute__ ((packed)); + +typedef struct AppDisconnectTLV AppDisconnectTLV; + +/* + * RFC 7275 + * 7.2.2.1. mLACP Disconnect Cause TLV + * [Page 49] + */ +struct AppDisconnectCauseTLV +{ + ICCParameter iccp_parameter; + + /* Disconnect Cause String */ + char cause_string[0]; /* Trick */ +} __attribute__ ((packed)); + +/*syncd send msg type to iccpd*/ +typedef enum mclag_syncd_msg_type_e_ +{ + MCLAG_SYNCD_MSG_TYPE_NONE = 0, + MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1 +}mclag_syncd_msg_type_e; + +typedef enum mclag_msg_type_e_ +{ + MCLAG_MSG_TYPE_NONE = 0, + MCLAG_MSG_TYPE_PORT_ISOLATE = 1, + MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE = 2, + MCLAG_MSG_TYPE_FLUSH_FDB = 3, + MCLAG_MSG_TYPE_SET_MAC = 4, + MCLAG_MSG_TYPE_SET_FDB = 5, + MCLAG_MSG_TYPE_GET_FDB_CHANGES = 20 +}mclag_msg_type_e; + + +typedef enum mclag_sub_option_type_e_ +{ + MCLAG_SUB_OPTION_TYPE_NONE = 0, + MCLAG_SUB_OPTION_TYPE_ISOLATE_SRC = 1, + MCLAG_SUB_OPTION_TYPE_ISOLATE_DST = 2, + MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE = 3, + MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE = 4, + MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC = 5, + MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6 +} mclag_sub_option_type_e; + + +struct IccpSyncdHDr +{ + uint8_t ver; + uint8_t type; + uint16_t len; +}; + +typedef struct mclag_sub_option_hdr_t_ +{ + + uint8_t op_type; + + /* + * Length of option value, not including the header. + */ + uint16_t op_len; + uint8_t data[]; +}mclag_sub_option_hdr_t; + +struct mclag_fdb_info +{ + char mac[ETHER_ADDR_STR_LEN]; + unsigned int vid; + char port_name[MAX_L_PORT_NAME]; + short type; /*dynamic or static*/ + short op_type; /*add or del*/ +}; + +/* For storing message log: For Notification TLV */ +struct MsgTypeSet +{ + uint32_t msg_id; + uint16_t type; + uint16_t tlv; + +}; + +struct MsgLog +{ + struct MsgTypeSet msg[MAX_MSG_LOG_SIZE]; + uint32_t end_index; +}; + +#endif /* MSG_FORMAT_H_ */ diff --git a/src/iccpd/include/port.h b/src/iccpd/include/port.h new file mode 100644 index 000000000000..dbd9d45fa83d --- /dev/null +++ b/src/iccpd/include/port.h @@ -0,0 +1,159 @@ +/* + * port.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef PORT_H_ +#define PORT_H_ + +#include +#include +#include + +#define ETHER_ADDR_LEN 6 +#define ETHER_ADDR_STR_LEN 18 +/* + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 56] + */ +#define MAX_L_PORT_NAME 20 + +/* defined in RFC 7275 - 7.2.7 (p.59) */ +#define PORT_STATE_UP 0x00 +#define PORT_STATE_DOWN 0x01 +#define PORT_STATE_ADMIN_DOWN 0x02 +#define PORT_STATE_TEST 0x03 + +/* Interface Type */ +#define IF_T_UNKNOW -1 +#define IF_T_PORT 0 +#define IF_T_PORT_CHANNEL 1 +#define IF_T_VLAN 2 +#define IF_T_VXLAN 3 +#define IF_T_BRIDGE 4 +typedef struct +{ + char *ifname; + int type; +} itf_type_t; + +struct If_info +{ + char name[MAX_L_PORT_NAME]; + LIST_ENTRY(If_info) csm_next; +}; + +struct VLAN_ID +{ + uint16_t vid; + uint16_t vlan_removed; + struct LocalInterface* vlan_itf; /* loacl vlan interface */ + LIST_ENTRY(VLAN_ID) port_next; +}; + +struct PeerInterface +{ + int ifindex; + int type; + char name[MAX_L_PORT_NAME]; + + uint8_t mac_addr[ETHER_ADDR_LEN]; + uint8_t state; + uint32_t ipv4_addr; + + uint8_t l3_mode; + uint8_t is_peer_link; + int po_id; + uint8_t po_active; + + struct CSM* csm; + + LIST_ENTRY(PeerInterface) mlacp_next; + LIST_HEAD(peer_vlan_list, VLAN_ID) vlan_list; +}; + +struct LocalInterface +{ + int ifindex; + int type; + char name[MAX_L_PORT_NAME]; + + uint8_t mac_addr[ETHER_ADDR_LEN]; + uint8_t mac_addr_ori[ETHER_ADDR_LEN]; + uint8_t state; + uint32_t ipv4_addr; + uint8_t prefixlen; + uint32_t ipv6_addr[4]; + uint8_t prefixlen_v6; + + uint8_t l3_mode; + uint8_t l3_mac_addr[ETHER_ADDR_LEN]; + uint8_t is_peer_link; + char portchannel_member_buf[512]; + uint8_t is_arp_accept; + int po_id; /* Port Channel ID */ + uint8_t po_active; /* Port Channel is in active status? */ + int mlacp_state; /* Record mlacp state */ + uint8_t isolate_to_peer_link; + + struct CSM* csm; + + uint8_t changed; + uint8_t port_config_sync; + + LIST_HEAD(local_vlan_list, VLAN_ID) vlan_list; + + LIST_ENTRY(LocalInterface) system_next; + LIST_ENTRY(LocalInterface) system_purge_next; + LIST_ENTRY(LocalInterface) mlacp_next; + LIST_ENTRY(LocalInterface) mlacp_purge_next; +}; + +struct LocalInterface* local_if_create(int ifindex, char* ifname, int type); +struct LocalInterface* local_if_find_by_name(const char* ifname); +struct LocalInterface* local_if_find_by_ifindex(int ifindex); +struct LocalInterface* local_if_find_by_po_id(int po_id); + +void local_if_destroy(char *ifname); +void local_if_change_flag_clear(void); +void local_if_purge_clear(void); +int local_if_is_l3_mode(struct LocalInterface* local_if); + +void local_if_init(struct LocalInterface*); +void local_if_finalize(struct LocalInterface*); + +void ether_mac_set_addr_with_if_name(char *name, uint8_t* mac); +struct PeerInterface* peer_if_create(struct CSM* csm, int peer_if_number, int type); +struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name); + +void peer_if_destroy(struct PeerInterface* pif); +int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id); +int peer_if_clean_unused_vlan(struct PeerInterface* peer_if); +/* VLAN manipulation */ +int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid); +void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid); +void local_if_del_all_vlan(struct LocalInterface* lif); + +/* ARP manipulation */ +int set_sys_arp_accept_flag(char* ifname, int flag); + +#endif /* PORT_H_ */ diff --git a/src/iccpd/include/scheduler.h b/src/iccpd/include/scheduler.h new file mode 100644 index 000000000000..a1b31039d794 --- /dev/null +++ b/src/iccpd/include/scheduler.h @@ -0,0 +1,60 @@ +/* + * scheduler.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef SCHEDULER_H_ +#define SCHEDULER_H_ + +#include + +#include +#include +#include + +#include +#include +#include + +struct CSM; +struct System; + +#define CONNECT_INTERVAL_SEC 1 +#define CONNECT_TIMEOUT_MSEC 100 +#define HEARTBEAT_TIMEOUT_SEC 15 +#define TRANSIT_INTERVAL_SEC 1 +#define EPOLL_TIMEOUT_MSEC 100 + +int scheduler_prepare_session(struct CSM*); +int scheduler_check_csm_config(struct CSM*); +int scheduler_unregister_sock_read_event_callback(struct CSM*); +void scheduler_session_disconnect_handler(struct CSM*); +void scheduler_init(); +void scheduler_finalize(); +void scheduler_loop(); +void scheduler_start(); +void scheduler_server_sock_init(); +int scheduler_csm_read_callback(struct CSM* csm); +int iccp_get_server_sock_fd(); +int scheduler_server_accept(); +int iccp_receive_signal_handler(struct System* sys); + +#endif /* SCHEDULER_H_ */ diff --git a/src/iccpd/include/system.h b/src/iccpd/include/system.h new file mode 100644 index 000000000000..3ee314d253aa --- /dev/null +++ b/src/iccpd/include/system.h @@ -0,0 +1,103 @@ +/* + * system.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#ifndef SYSTEM_H_ +#define SYSTEM_H_ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "../include/port.h" + +#define FRONT_PANEL_PORT_PREFIX "Ethernet" +#define PORTCHANNEL_PREFIX "PortChannel" +#define VLAN_PREFIX "Vlan" +#define VXLAN_TUNNEL_PREFIX "VTTNL" + +#define WARM_REBOOT 1 + +#define MCLAG_ERROR -1 + +struct CSM; + +#ifndef MAX_BUFSIZE + #define MAX_BUFSIZE 4096 +#endif + +struct System +{ + int server_fd;/* Peer-Link Socket*/ + int sync_fd; + int sync_ctrl_fd; + int arp_receive_fd; + int ndisc_receive_fd; + int epoll_fd; + + struct nl_sock * genric_sock; + int genric_sock_seq; + int family; + struct nl_sock * route_sock; + int route_sock_seq; + struct nl_sock * genric_event_sock; + struct nl_sock * route_event_sock; + + int sig_pipe_r; + int sig_pipe_w; + int warmboot_start; + int warmboot_exit; + + /* Info List*/ + LIST_HEAD(csm_list, CSM) csm_list; + LIST_HEAD(lif_all_list, LocalInterface) lif_list; + LIST_HEAD(lif_purge_all_list, LocalInterface) lif_purge_list; + + /* Settings */ + char* log_file_path; + char* cmd_file_path; + char* config_file_path; + char* mclagdctl_file_path; + int pid_file_fd; + int telnet_port; + fd_set readfd; /*record socket need to listen*/ + int readfd_count; + time_t csm_trans_time; + int need_sync_team_again; + int need_sync_netlink_again; +}; + +struct CSM* system_create_csm(); +struct CSM* system_get_csm_by_peer_ip(const char*); +struct CSM* system_get_csm_by_mlacp_id(int id); +struct System* system_get_instance(); +void system_finalize(); +void system_init(struct System*); + +#endif /* SYSTEM_H_ */ diff --git a/src/iccpd/src/Makefile.am b/src/iccpd/src/Makefile.am new file mode 100644 index 000000000000..9d19dbb5285c --- /dev/null +++ b/src/iccpd/src/Makefile.am @@ -0,0 +1,22 @@ +SUBDIRS = mclagdctl + +INCLUDES = -I$(top_srcdir)/include -I/usr/include/libnl3 + +bin_PROGRAMS = iccpd + +if DEBUG +DBGFLAGS = -ggdb -DDEBUG +else +DBGFLAGS = -g -DNDEBUG +endif + +iccpd_SOURCES = \ + app_csm.c cmd_option.c iccp_cli.c iccp_cmd_show.c iccp_cmd.c \ + iccp_csm.c iccp_ifm.c iccp_main.c logger.c \ + port.c scheduler.c system.c iccp_consistency_check.c \ + mlacp_link_handler.c \ + mlacp_sync_prepare.c mlacp_sync_update.c\ + mlacp_fsm.c \ + iccp_netlink.c +iccpd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) +iccpd_LDADD = -lnl-genl-3 -lnl-route-3 -lnl-3 -lpthread diff --git a/src/iccpd/src/app_csm.c b/src/iccpd/src/app_csm.c new file mode 100644 index 000000000000..589cf94015d8 --- /dev/null +++ b/src/iccpd/src/app_csm.c @@ -0,0 +1,316 @@ +/* + * app_csm.c + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include +#include +#include + +#include "../include/iccp_csm.h" +#include "../include/logger.h" +#include "../include/scheduler.h" +#include "../include/system.h" +#include "../include/iccp_netlink.h" +#include "../include/mlacp_link_handler.h" +/***************************************** +* Define +* +* ***************************************/ +#define APP_CSM_QUEUE_REINIT(list) \ + { \ + struct Msg* msg = NULL; \ + while (!TAILQ_EMPTY(&(list))) { \ + msg = TAILQ_FIRST(&(list)); \ + TAILQ_REMOVE(&(list), msg, tail); \ + free(msg->buf); \ + free(msg); \ + } \ + TAILQ_INIT(&(list)); \ + } + +/* Application State Machine instance initialization */ +void app_csm_init(struct CSM* csm, int all) +{ + if (csm == NULL ) + return; + + APP_CSM_QUEUE_REINIT(csm->app_csm.app_msg_list); + + if (all) + { + bzero(&(csm->app_csm), sizeof(struct AppCSM)); + APP_CSM_QUEUE_REINIT(csm->app_csm.app_msg_list); + } + + csm->app_csm.current_state = APP_NONEXISTENT; + csm->app_csm.rx_connect_msg_id = 0; + csm->app_csm.tx_connect_msg_id = 0; + csm->app_csm.invalid_msg_id = 0; + csm->app_csm.invalid_msg = 0; + csm->app_csm.nak_msg = 0; + + mlacp_init(csm, all); +} + +/* Application State Machine instance tear down */ +void app_csm_finalize(struct CSM* csm) +{ + mlacp_finalize(csm); +} + +/* Application State Machine Transition */ +void app_csm_transit(struct CSM* csm) +{ + if (csm == NULL ) + return; + + /* torn down event */ + if (csm->app_csm.current_state != APP_NONEXISTENT && csm->sock_fd <= 0) + { + csm->app_csm.current_state = APP_NONEXISTENT; + return; + } + + if (csm->app_csm.current_state != APP_OPERATIONAL && csm->current_state == ICCP_OPERATIONAL) + { + csm->app_csm.current_state = APP_OPERATIONAL; + } + + return; +} + +/* Add received message into application message list */ +void app_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + ICCParameter* param = NULL; + NAKTLV* naktlv = NULL; + int tlv = -1; + int i = 0; + + if (csm == NULL ) + { + if (msg != NULL ) + free(msg); + return; + } + if (msg == NULL ) + return; + + icc_hdr = (ICCHdr*)msg->buf; + param = (ICCParameter*)&msg->buf[sizeof(struct ICCHdr)]; + *(uint16_t *)param = ntohs(*(uint16_t *)param); + + if ( icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + if (param->type > TLV_T_MLACP_CONNECT && param->type < TLV_T_MLACP_LIST_END) + mlacp_enqueue_msg(csm, msg); + else + TAILQ_INSERT_TAIL(&(csm->app_csm.app_msg_list), msg, tail); + } + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + { + naktlv = (NAKTLV*)&msg->buf[sizeof(ICCHdr)]; + + for (i = 0; i < MAX_MSG_LOG_SIZE; ++i) + { + if (ntohl(naktlv->rejected_msg_id) == csm->msg_log.msg[i].msg_id) + { + tlv = csm->msg_log.msg[i].tlv; + break; + } + } + + if (tlv > TLV_T_MLACP_CONNECT && tlv <= TLV_T_MLACP_MAC_INFO) + mlacp_enqueue_msg(csm, msg); + else + TAILQ_INSERT_TAIL(&(csm->app_csm.app_msg_list), msg, tail); + } + else + { + /* This packet is not for me, ignore it. */ + ICCPD_LOG_DEBUG(__FUNCTION__, "Ignore the packet with msg_type = %d", icc_hdr->ldp_hdr.msg_type); + } +} + +/* Get received message from message list */ +struct Msg* app_csm_dequeue_msg(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (!TAILQ_EMPTY(&(csm->app_csm.app_msg_list))) + { + msg = TAILQ_FIRST(&(csm->app_csm.app_msg_list)); + TAILQ_REMOVE(&(csm->app_csm.app_msg_list), msg, tail); + } + + return msg; +} + +/* APP NAK message handle function */ +int app_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*)buf; + NAKTLV* naktlv = (NAKTLV*)&buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(NAKTLV); + + ICCPD_LOG_DEBUG(__FUNCTION__, " Response NAK"); + memset(buf, 0, max_buf_size); + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = htons(MSG_T_NOTIFICATION); + icc_hdr->ldp_hdr.msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); + icc_hdr->ldp_hdr.msg_id = htonl(ICCP_MSG_ID++); + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + naktlv->icc_parameter.u_bit = 0; + naktlv->icc_parameter.f_bit = 0; + naktlv->icc_parameter.type = htons(TLV_T_NAK); + naktlv->icc_parameter.len = htons(sizeof(NAKTLV) - 4); + + naktlv->iccp_status_code = htonl(STATUS_CODE_ICCP_REJECTED_MSG); + naktlv->rejected_msg_id = htonl(csm->app_csm.invalid_msg_id); + + return msg_len; +} + +int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) +{ + struct LocalInterface* lifp = NULL; + struct LocalInterface* lif_po = NULL; + + if (csm == NULL || lif == NULL) + return MCLAG_ERROR; + + if (lif->csm == csm) + return 0; + + /* remove purge from the csm*/ + do { + LIST_FOREACH(lifp, &(MLACP(csm).lif_purge_list), mlacp_purge_next) + { + if (lifp == lif) + break; + } + if (lifp) + LIST_REMOVE(lifp, mlacp_purge_next); + } while (lifp); + + /* already join csm?*/ + LIST_FOREACH(lifp, &(MLACP(csm).lif_list), mlacp_next) + { + if (lifp == lif) + return 0; + } + + /* join another csm beofre? remove from csm*/ + if (lif->csm != NULL) + mlacp_unbind_local_if(lif); + + /* join new csm*/ + LIST_INSERT_HEAD(&(MLACP(csm).lif_list), lif, mlacp_next); + lif->csm = csm; + if (lif->type == IF_T_PORT_CHANNEL) + lif->port_config_sync = 1; + + ICCPD_LOG_INFO(__FUNCTION__, "%s: MLACP bind on csm %p", lif->name, csm); + if (lif->type == IF_T_PORT_CHANNEL) + return 0; + + /* if join a po member, needs to check po joined also*/ + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type == IF_T_PORT_CHANNEL && lif_po->po_id == lif->po_id) + { + /*if join a po member, may swss restart, reset portchannel ip mac to mclagsyncd*/ + update_if_ipmac_on_standby(lif_po); + return 0; + } + } + + if (lif_po == NULL) + { + lif_po = local_if_find_by_po_id(lif->po_id); + if (lif_po == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to find port_channel instance for %d.", lif->po_id); + return MCLAG_ERROR; + } + + lif_po->csm = csm; + LIST_INSERT_HEAD(&(MLACP(csm).lif_list), lif_po, mlacp_next); + lif_po->port_config_sync = 1; + ICCPD_LOG_INFO(__FUNCTION__, "Add port_channel %d into local_if_list in CSM %p.", lif->po_id, csm); + } + + return 0; +} + +int mlacp_unbind_local_if(struct LocalInterface* lif) +{ + if (lif == NULL ) + return MCLAG_ERROR; + + if (lif->csm == NULL ) + return 0; + + ICCPD_LOG_INFO(__FUNCTION__, "%s: MLACP un-bind from csm %p", lif->name, lif->csm); + LIST_REMOVE(lif, mlacp_next); + + if (MLACP(lif->csm).current_state == MLACP_STATE_EXCHANGE && lif->type == IF_T_PORT_CHANNEL) + LIST_INSERT_HEAD(&(MLACP(lif->csm).lif_purge_list), lif, mlacp_purge_next); + if (lif->type == IF_T_PORT) + lif->po_id = -1; + lif->csm = NULL; + + return 0; +} + +int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname) +{ + struct System* sys = NULL; + struct LocalInterface *lif_po = NULL; + + sys = system_get_instance(); + if (sys == NULL) + return 0; + + if (csm == NULL) + return 0; + + /* bind po first*/ + lif_po = local_if_find_by_name(ifname); + if (lif_po) + { + mlacp_bind_local_if(csm, lif_po); + iccp_get_port_member_list(lif_po); + } + else + { + ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance .", ifname); + return 0; + } + /* process link state handler after attaching it.*/ + + mlacp_mlag_link_add_handler(csm, lif_po); + + /*ICCPD_LOG_WARN(tag, "po%d active = %d\n", po_id, po_is_active);*/ + return 0; +} + diff --git a/src/iccpd/src/cmd_option.c b/src/iccpd/src/cmd_option.c new file mode 100644 index 000000000000..596dafb73711 --- /dev/null +++ b/src/iccpd/src/cmd_option.c @@ -0,0 +1,266 @@ +/* + * cmd_option.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include "../include/cmd_option.h" + +struct CmdOption* cmd_option_find(struct CmdOptionParser* parser, char* opt_name) +{ + struct CmdOption* opt = NULL; + + if (opt_name == NULL) + return NULL; + + LIST_FOREACH(opt, &(parser->option_list), next) + { + if (strcmp(opt->option, opt_name) == 0) + return opt; + } + + return NULL; +} + +void cmd_option_delete(struct CmdOption* opt) +{ + if (opt == NULL) + return; + + LIST_REMOVE(opt, next); + if (opt->option != NULL) + free(opt->option); + if (opt->parameter != NULL) + free(opt->parameter); + if (opt->desc != NULL) + free(opt->desc); + free(opt); +} + +struct CmdOption* cmd_option_add(struct CmdOptionParser* parser, char* opt_name) +{ + struct CmdOption* opt = NULL; + + if (opt_name == NULL) + return NULL; + if ((opt = cmd_option_find(parser, opt_name)) != NULL) + return opt; + + if ((opt = (struct CmdOption*)malloc(sizeof(struct CmdOption))) == NULL) + { + strerror(errno); + } + else + { + opt->option = opt_name; + opt->parameter = NULL; + opt->desc = NULL; + LIST_INSERT_HEAD(&(parser->option_list), opt, next); + } + + return opt; +} + +static void cmd_option_register(struct CmdOptionParser* parser, char* syntax, char* desc) +{ + char buf[OPTION_MAX_LEN]; + struct CmdOption* opt = NULL; + char* opt_name = NULL; + char* param = NULL; + char* desc_copy = NULL; + char* token = NULL; + + if (parser == NULL) + return; + if (syntax == NULL) + return; + + memset(buf, 0, OPTION_MAX_LEN); + snprintf(buf, OPTION_MAX_LEN - 1, "%s", syntax); + + if ((token = strtok(buf, " ")) == NULL) + return; + + opt_name = strdup(token); + if ((token = strtok(NULL, " ")) != NULL) + param = strdup(token); + desc_copy = strdup(desc); + if ((opt = cmd_option_find(parser, opt_name)) != NULL) + goto failed; + if ((opt = cmd_option_add(parser, opt_name)) == NULL) + { + goto failed; + } + opt->parameter = param; + opt->desc = desc_copy; + + return; + + failed: + if (opt_name) + free(opt_name); + if (desc_copy != NULL) + free(desc_copy); + if (param != NULL) + free(param); + if (opt != NULL) + free(opt); +} + +void cmd_option_parser_init(struct CmdOptionParser* parser) +{ + if (parser == NULL) + return; + + LIST_INIT(&parser->option_list); + cmd_option_register(parser, "-l ", "Set log file path.\n(Default: /var/log/iccpd.log)"); + cmd_option_register(parser, "-p ", "Set the port used for telnet listening port.\n(Default: 2015)"); + cmd_option_register(parser, "-c", "Dump log message to console. (Default: No)"); + cmd_option_register(parser, "-h", "Show the usage."); +} + +void cmd_option_parser_finalize(struct CmdOptionParser* parser) +{ + while (!LIST_EMPTY(&(parser->option_list))) + { + struct CmdOption* opt = NULL; + opt = LIST_FIRST(&(parser->option_list)); + cmd_option_delete(opt); + } +} + +void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_name) +{ + char buf[MSG_LEN]; + struct CmdOption* opt = NULL; + int index, begin, length; + char first_line = 0; + + fprintf(stdout, "Usage: %s [Options]\n", prog_name); + fprintf(stdout, "\n"); + fprintf(stdout, "Options:\n"); + LIST_FOREACH(opt, &(parser->option_list), next) + { + index = 0; + begin = 0; + length = 0; + first_line = 1; + memset(buf, 0, MSG_LEN); + if (opt->parameter != NULL) + snprintf(buf, MSG_LEN - 1, "%s %s", opt->option, opt->parameter); + else + snprintf(buf, MSG_LEN - 1, "%s", opt->option); + fprintf(stdout, "%24s ", buf); + + while (index < strlen(opt->desc)) + { + while (index < strlen(opt->desc) + && opt->desc[index] != '\n' && length < 49) + { + ++index; + ++length; + } + + memset(buf, 0, MSG_LEN); + strncpy(buf, &(opt->desc[begin]), length); + if (length == 49 && index < strlen(opt->desc) + && opt->desc[index] != '\n' + && opt->desc[index - 1] != ' ' + && opt->desc[index] != ' ') + { + buf[length] = '-'; + buf[length + 1] = '\0'; + } + if (length < 49) + ++index; + begin = index; + length = 0; + if (first_line != 0) + { + fprintf(stdout, "%-52s\n", buf); + first_line = 0; + } + else + fprintf(stdout, "%28c%-52s\n", ' ', buf); + } + + fflush(stdout); + } +} + +int cmd_option_parser_parse(struct CmdOptionParser* parser, int argc, char* argv[]) +{ + int index = 1; + struct CmdOption* opt = NULL; + char* opt_name = NULL; + char* val = NULL; + int num = 0; + + if (parser == NULL) + return -255; + + while (index < argc) + { + opt_name = argv[index]; + opt = cmd_option_find(parser, opt_name); + if (opt == NULL) + { + fprintf(stderr, "Unknown option %s, skip it.\n", opt_name); + ++index; + continue; + } + + if (opt->parameter != NULL) + { + ++index; + if (index >= argc) + { + fprintf(stderr, "Error: Insufficient parameter for option %s\n", opt_name); + cmd_option_parser_dump_usage(parser, argv[0]); + return -1; + } + val = argv[index]; + } + + if (strncmp(opt_name, "-h", 2) == 0) + { + cmd_option_parser_dump_usage(parser, argv[0]); + return -1; + } + + if (strncmp(opt_name, "-l", 2) == 0) + parser->log_file_path = val; + + if (strncmp(opt_name, "-p", 2) == 0) + { + num = atoi(val); + if (num > 0 && num < 65535) + parser->telnet_port = num; + } + else if (strncmp(opt_name, "-c", 2) == 0) + parser->console_log = 1; + else + fprintf(stderr, "Unknown option name %s, skip it.\n", opt_name); + + ++index; + } + + return 0; +} diff --git a/src/iccpd/src/iccp_cli.c b/src/iccpd/src/iccp_cli.c new file mode 100644 index 000000000000..8d0ede8b3feb --- /dev/null +++ b/src/iccpd/src/iccp_cli.c @@ -0,0 +1,498 @@ +/* + * iccp_cli.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include + +#include "../include/system.h" +#include "../include/scheduler.h" +#include "../include/logger.h" +#include "../include/iccp_csm.h" +#include "../include/mlacp_link_handler.h" +#include "../include/iccp_netlink.h" +/* + * 'id <1-65535>' command + */ +int set_mc_lag_id( struct CSM *csm, uint16_t id) +{ + if (!csm) + return MCLAG_ERROR; + + ICCPD_LOG_INFO(__FUNCTION__, "Set mlag-id : %d", id); + + /* Mlag-ID, RG-ID, MLACP-ID + Temporary let the three id be the same*/ + csm->mlag_id = id; + csm->iccp_info.icc_rg_id = id; + csm->app_csm.mlacp.id = id; + return 0; +} + +int unset_mc_lag_id( struct CSM *csm, uint16_t id) +{ + if (!csm) + return MCLAG_ERROR; + + /* Mlag-ID, RG-ID, MLACP-ID*/ + csm->mlag_id = 0; + csm->iccp_info.icc_rg_id = 0; + csm->app_csm.mlacp.id = 0; + + iccp_csm_finalize(csm); + + return 0; +} + +/* + * 'peer-link WORD' command + */ +int set_peer_link(int mid, const char* ifname) +{ + struct CSM* csm = NULL; + struct LocalInterface *lif = NULL; + size_t len = 0; + + len = strlen(ifname); + + if (strncmp(ifname, FRONT_PANEL_PORT_PREFIX, strlen(FRONT_PANEL_PORT_PREFIX)) != 0 && strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0 && strncmp(ifname, VXLAN_TUNNEL_PREFIX, strlen(VXLAN_TUNNEL_PREFIX)) != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Peer-link is %s, must be Ethernet or PortChannel or VTTNL(Vxlan tunnel)", ifname); + return MCLAG_ERROR; + } + + csm = system_get_csm_by_mlacp_id(mid); + if (csm == NULL) + return MCLAG_ERROR; + + if (len > IFNAMSIZ) + return MCLAG_ERROR; + + if (strlen(csm->peer_itf_name) > 0) + { + if (strcmp(csm->peer_itf_name, ifname) == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Peer-link not be changed"); + return 0; + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Change peer-link : %s -> %s", + csm->peer_itf_name, ifname); + + /*disconnect the link for mac and arp sync up before change peer_itf_name*/ + scheduler_session_disconnect_handler(csm); + + if (csm->peer_link_if) + { + csm->peer_link_if->is_peer_link = 0; + csm->peer_link_if = NULL; + } + } + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Set mlag %d peer-link : %s", + csm->mlag_id, ifname); + } + + memset(csm->peer_itf_name, 0, IFNAMSIZ); + memcpy(csm->peer_itf_name, ifname, len); + + /* update peer-link link handler*/ + lif = local_if_find_by_name(csm->peer_itf_name); + if (lif) + { + /*When set peer-link, the local-if is already created*/ + csm->peer_link_if = lif; + lif->is_peer_link = 1; + MLACP(csm).system_config_changed = 1; + + if (lif->type == IF_T_PORT_CHANNEL) + iccp_get_port_member_list(lif); + } + + /*disconnect the link for mac and arp sync up*/ + scheduler_session_disconnect_handler(csm); + + return 0; +} + +int unset_peer_link(int mid) +{ + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if (csm == NULL) + return MCLAG_ERROR; + + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*must be enabled mac learn*/ + if (csm->peer_link_if) + set_peerlink_mlag_port_learn(csm->peer_link_if, 1); + } + + /* update peer-link link handler*/ + scheduler_session_disconnect_handler(csm); + + /* clean peer-link*/ + memset(csm->peer_itf_name, 0, IFNAMSIZ); + if (csm->peer_link_if) + { + csm->peer_link_if->is_peer_link = 0; + csm->peer_link_if = NULL; + MLACP(csm).system_config_changed = 1; + } + + return 0; +} + +/* + * 'local ip address A.B.C.D' command + */ +int set_local_address(int mid, const char* addr) +{ + struct CSM* csm = NULL; + size_t len = 0; + + csm = system_get_csm_by_mlacp_id(mid); + if (csm == NULL) + return MCLAG_ERROR; + if (addr == NULL) + return MCLAG_ERROR; + + if (strlen(csm->sender_ip) > 0) + { + if (strcmp(csm->sender_ip, addr) == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Local-address not be changed"); + return 0; + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Change local-address : %s -> %s", + csm->sender_ip, addr); + scheduler_session_disconnect_handler(csm); + } + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Set local-address : %s", addr); + } + + len = strlen(addr); + memset(csm->sender_ip, 0, INET_ADDRSTRLEN); + memcpy(csm->sender_ip, addr, len); + memset(csm->iccp_info.sender_name, 0, INET_ADDRSTRLEN); + memcpy(csm->iccp_info.sender_name, addr, len); + + return 0; +} + +int unset_local_address(int mid) +{ + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if (csm == NULL) + return MCLAG_ERROR; + + memset(csm->sender_ip, 0, INET_ADDRSTRLEN); + memset(csm->iccp_info.sender_name, 0, INET_ADDRSTRLEN); + + /* reset link*/ + scheduler_session_disconnect_handler(csm); + + return 0; +} + +/* + * 'peer-address A.B.C.D' command + */ +int set_peer_address(int mid, const char* addr) +{ + struct CSM* csm = NULL; + size_t len = 0; + + csm = system_get_csm_by_mlacp_id(mid); + if (csm == NULL) + return MCLAG_ERROR; + if (addr == NULL) + return MCLAG_ERROR; + + len = strlen(addr); + + if (strlen(csm->peer_ip) > 0) + { + if (strcmp(csm->peer_ip, addr) == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Peer-address not be changed"); + return 0; + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Change peer-address : %s -> %s", + csm->peer_ip, addr); + scheduler_session_disconnect_handler(csm); + } + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Set peer-address : %s", addr); + } + + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); + memcpy(csm->peer_ip, addr, len); + + return 0; +} + +int unset_peer_address(int mid) +{ + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if (csm == NULL) + return MCLAG_ERROR; + + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); + + /* reset link*/ + scheduler_session_disconnect_handler(csm); + + return 0; +} + +int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname) +{ + struct CSM* csm = NULL; + struct LocalInterface *lif = NULL; + struct If_info * cif = NULL; + + if (!ifname) + return MCLAG_ERROR; + + if (strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Attach interface(%s) is not a port-channel", ifname); + return MCLAG_ERROR; + } + + csm = system_get_csm_by_mlacp_id(domain); + if (csm == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "MC-LAG ID %d doesn't exist", domain); + return MCLAG_ERROR; + } + + lif = local_if_find_by_name(ifname); + if (lif) + { + mlacp_bind_port_channel_to_csm(csm, ifname); + } + + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + if (strcmp(cif->name, ifname) == 0) + break; + } + + if (cif == NULL) + { + cif = (struct If_info *)malloc(sizeof(struct If_info)); + if (!cif) + return MCLAG_ERROR; + + snprintf(cif->name, MAX_L_PORT_NAME, "%s", ifname); + LIST_INSERT_HEAD(&(csm->if_bind_list), cif, csm_next); + } + + return 0; +} + +int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) +{ + int unbind_poid = -1; + struct CSM *csm = NULL; + struct LocalInterface *lif_po = NULL; + struct LocalInterface *lif = NULL; + struct If_info * cif = NULL; + + if (!ifname) + return MCLAG_ERROR; + + if (strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Detach interface(%s) is not a port-channel", ifname); + return MCLAG_ERROR; + } + + /* find po*/ + if (!(lif_po = local_if_find_by_name(ifname)) + || lif_po->type != IF_T_PORT_CHANNEL + || lif_po->po_id <= 0 + || lif_po->csm == NULL) + { + return MCLAG_ERROR; + } + + /* find csm*/ + csm = lif_po->csm; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Detach mclag id = %d from ifname = %s", + csm->mlag_id, lif_po->name); + + /* process link state handler before detaching it.*/ + mlacp_mlag_link_del_handler(csm, lif_po); + + unbind_poid = lif_po->po_id; + mlacp_unbind_local_if(lif_po); + LIST_FOREACH(lif, &(csm->app_csm.mlacp.lif_list), mlacp_next) + { + if (lif->type == IF_T_PORT && lif->po_id == unbind_poid) + mlacp_unbind_local_if(lif); + } + + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + if (strcmp(ifname, cif->name) == 0) + LIST_REMOVE(cif, csm_next); + } + return 0; +} + +/* This function parses a string to a binary mac address (uint8_t[6]) + The string should contain mac address only. No spaces are allowed. + The mac address separators could be either ':' or '-'*/ +int parseMacString(const char * str_mac, uint8_t* bin_mac) +{ + int i; + + if (bin_mac == NULL) + { + return MCLAG_ERROR; + } + + /* 6 hexadecimal numbers (two digits each) + 5 delimiters*/ + if (strlen(str_mac) != ETHER_ADDR_LEN * 2 + 5) + { + return MCLAG_ERROR; + } + + /* first check that all mac address separators are equal to each other + 2, 5, 8, 11, and 14 are MAC address separator positions*/ + if (!(str_mac[2] == str_mac[5] + && str_mac[5] == str_mac[8] + && str_mac[8] == str_mac[11] + && str_mac[11] == str_mac[14])) + { + return MCLAG_ERROR; + } + + /* then check that the first separator is equal to ':' or '-'*/ + if (str_mac[2] != ':' && str_mac[2] != '-') + { + return MCLAG_ERROR; + } + + for (i = 0; i < ETHER_ADDR_LEN; ++i) + { + int left = i * 3; /* left digit position of hexadecimal number*/ + int right = left + 1; /* right digit position of hexadecimal number*/ + + if (str_mac[left] >= '0' && str_mac[left] <= '9') + { + bin_mac[i] = (uint8_t)(str_mac[left] - '0'); + } + else if (str_mac[left] >= 'A' && str_mac[left] <= 'F') + { + bin_mac[i] = (uint8_t)(str_mac[left] - 'A' + 0x0a); + } + else if (str_mac[left] >= 'a' && str_mac[left] <= 'f') + { + bin_mac[i] = (uint8_t)(str_mac[left] - 'a' + 0x0a); + } + else + { + return MCLAG_ERROR; + } + + bin_mac[i] = (uint8_t)(bin_mac[i] << 4); + + if (str_mac[right] >= '0' && str_mac[right] <= '9') + { + bin_mac[i] |= (uint8_t)(str_mac[right] - '0'); + } + else if (str_mac[right] >= 'A' && str_mac[right] <= 'F') + { + bin_mac[i] |= (uint8_t)(str_mac[right] - 'A' + 0x0a); + } + else if (str_mac[right] >= 'a' && str_mac[right] <= 'f') + { + bin_mac[i] |= (uint8_t)(str_mac[right] - 'a' + 0x0a); + } + else + { + return MCLAG_ERROR; + } + } + + return 0; +} + +int set_local_system_id(const char* mac) +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return 0; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + parseMacString(mac, MLACP(csm).system_id); + + ICCPD_LOG_DEBUG(__FUNCTION__, " Set local systemID [%02X:%02X:%02X:%02X:%02X:%02X].", + MLACP(csm).system_id[0], MLACP(csm).system_id[1], MLACP(csm).system_id[2], + MLACP(csm).system_id[3], MLACP(csm).system_id[4], MLACP(csm).system_id[5]); + } + + return 0; +} + +int unset_local_system_id( ) +{ + uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return 0; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + memcpy(MLACP(csm).system_id, null_mac, ETHER_ADDR_LEN); + } + + return 0; +} + diff --git a/src/iccpd/src/iccp_cmd.c b/src/iccpd/src/iccp_cmd.c new file mode 100644 index 000000000000..50025a8e3810 --- /dev/null +++ b/src/iccpd/src/iccp_cmd.c @@ -0,0 +1,168 @@ +/* + * iccp_cmd.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include +#include +#include + +#include "../include/iccp_csm.h" +#include "../include/msg_format.h" +#include "../include/system.h" + +#include "../include/iccp_cmd_show.h" +#include "../include/iccp_cli.h" +#include "../include/logger.h" + +int set_mc_lag_by_id(uint16_t mid) +{ + int ret = 0; + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if (!csm) + { + csm = (struct CSM*)iccp_get_csm(); + if (csm == NULL) + { + return MCLAG_ERROR; + } + + ret = set_mc_lag_id(csm, mid); + + return ret; + } + + return ret; +} + +#define CONFIG_LINE_LEN 512 + +int iccp_config_from_command(char * line) +{ + char *cp, *start; + char token[64]; + int slen; + static int mid = 0; + char *end; + + if (line == NULL) + return 0; + + cp = line; + + /* Skip white spaces. */ + while (isspace((int)*cp) && *cp != '\0') + cp++; + + /* Return if there is only white spaces */ + if (*cp == '\0') + return 0; + + end = cp; + + /* Skip end white spaces. */ + while (!isspace((int)*end) && *end != '\0') + end++; + + *end = '\0'; + /*mc-lag id*/ + if (strncmp(cp, MCLAG_ID_STR, strlen(MCLAG_ID_STR)) == 0 ) + { + cp += strlen(MCLAG_ID_STR) + 1; + mid = atoi(cp); + set_mc_lag_by_id(mid); + } + else if (strncmp(cp, LOCAL_IP_STR, strlen(LOCAL_IP_STR)) == 0) /*local ip*/ + { + cp += strlen(LOCAL_IP_STR) + 1; + set_local_address(mid, cp); + } + else if (strncmp(cp, PEER_IP_STR, strlen(PEER_IP_STR)) == 0) /*peer ip*/ + { + cp += strlen(PEER_IP_STR) + 1; + set_peer_address(mid, cp); + } + else if (strncmp(cp, PEER_LINK_STR, strlen(PEER_LINK_STR)) == 0)/*peer link*/ + { + cp += strlen(PEER_LINK_STR) + 1; + set_peer_link(mid, cp); + } + else if (strncmp(cp, MCLAG_INTF_STR, strlen(MCLAG_INTF_STR)) == 0)/*mclag interface*/ + { + cp += strlen(MCLAG_INTF_STR) + 1; + + while (1) + { + start = cp; + + while (!(*cp == ',' || *cp == '\r' || *cp == '\n') && + *cp != '\0') + cp++; + + slen = cp - start; + strncpy(token, start, slen); + *(token + slen) = '\0'; + iccp_cli_attach_mclag_domain_to_port_channel(mid, token); + + while ((isspace((int)*cp) || *cp == '\n' || *cp == '\r' || *cp == ',') && + *cp != '\0') + cp++; + + if (*cp == '\0') + break; + } + } + else if (strncmp(cp, SYSTEM_MAC_STR, strlen(SYSTEM_MAC_STR)) == 0)/*system mac*/ + { + cp += strlen(SYSTEM_MAC_STR) + 1; + set_local_system_id(cp); + } + else + { + /*error*/ + } + + return 1; +} + +/* Configration make from file. */ +int +iccp_config_from_file(char *config_default_dir) +{ + FILE *confp = NULL; + char command_buf[CONFIG_LINE_LEN]; + + confp = fopen(config_default_dir, "r"); + if (confp == NULL) + return (1); + + while (fgets(command_buf, CONFIG_LINE_LEN, confp)) + { + iccp_config_from_command(command_buf); + } + + fclose(confp); + + return 0; +} + diff --git a/src/iccpd/src/iccp_cmd_show.c b/src/iccpd/src/iccp_cmd_show.c new file mode 100644 index 000000000000..18b2e5bded8e --- /dev/null +++ b/src/iccpd/src/iccp_cmd_show.c @@ -0,0 +1,544 @@ +/* + * iccp_cmd_show.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ +#include +#include +#include +#include + +#include "../include/iccp_csm.h" +#include "../include/mlacp_tlv.h" +#include "../include/system.h" +#include "../include/logger.h" +#include "mclagdctl/mclagdctl.h" +#include "../include/iccp_cmd_show.h" +#include "../include/mlacp_link_handler.h" + +int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) +{ + struct mclagd_state state_info; + struct System *sys = NULL; + struct CSM *csm = NULL; + struct LocalInterface *peer_link_if = NULL; + struct LocalInterface *lif_po = NULL; + struct LoggerConfig* logconfig; + char unknown[] = { "Unknown" }; + int mclag_num = 0; + int id_exist = 0; + int str_size = 0; + int len = 0; + char *state_buf = NULL; + int state_buf_size = MCLAGDCTL_CMD_SIZE; + + if (!(sys = system_get_instance())) + { + return EXEC_TYPE_NO_EXIST_SYS; + } + + state_buf = (char*)malloc(state_buf_size); + if (!state_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + memset(&state_info, 0, sizeof(struct mclagd_state)); + + if (csm->current_state == ICCP_OPERATIONAL) + state_info.keepalive = 1; + else + state_info.keepalive = 0; + + if (mclag_id > 0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + peer_link_if = local_if_find_by_name(csm->peer_itf_name); + + if (csm->mlag_id <= 0) + state_info.mclag_id = -1; + else + state_info.mclag_id = csm->mlag_id; + + memcpy(state_info.local_ip, csm->sender_ip, ICCP_MAX_IP_STR_LEN); + memcpy(state_info.peer_ip, csm->peer_ip, ICCP_MAX_IP_STR_LEN); + + if (peer_link_if) + memcpy(state_info.peer_link_if, peer_link_if->name, ICCP_MAX_PORT_NAME); + else + memcpy(state_info.peer_link_if, unknown, strlen(unknown)); + + if (peer_link_if) + memcpy(state_info.peer_link_mac, peer_link_if->mac_addr, 6); + + logconfig = logger_get_configuration(); + memcpy(state_info.loglevel, log_level_to_string(logconfig->log_level), strlen( log_level_to_string(logconfig->log_level))); + + state_info.role = csm->role_type; + + str_size = MCLAGDCTL_PORT_MEMBER_BUF_LEN; + len = 0; + + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + + if (str_size - len < ICCP_MAX_PORT_NAME) + break; + + if (lif_po->type == IF_T_PORT_CHANNEL) + len += snprintf(state_info.enabled_po + len, str_size - len, "%s,", lif_po->name); + } + + /*Skip the last ','*/ + len = strlen(state_info.enabled_po); + if (len > 0) + { + state_info.enabled_po[len - 1] = '\0'; + } + + memcpy(state_buf + MCLAGD_REPLY_INFO_HDR + mclag_num * sizeof(struct mclagd_state), + &state_info, sizeof(struct mclagd_state)); + mclag_num++; + + if ((mclag_num + 1) * sizeof(struct mclagd_state) > (state_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + state_buf_size += MCLAGDCTL_CMD_SIZE; + state_buf = (char*)realloc(state_buf, state_buf_size); + if (!state_buf) + return EXEC_TYPE_FAILED; + } + } + + *buf = state_buf; + *num = mclag_num; + + if (mclag_id > 0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_arp_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct ARPMsg *iccpd_arp = NULL; + struct mclagd_arp_msg mclagd_arp; + int arp_num = 0; + int id_exist = 0; + char * arp_buf = NULL; + int arp_buf_size = MCLAGDCTL_CMD_SIZE; + + if (!(sys = system_get_instance())) + { + return EXEC_TYPE_NO_EXIST_SYS; + } + + arp_buf = (char*)malloc(arp_buf_size); + if (!arp_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id > 0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + memset(&mclagd_arp, 0, sizeof(struct mclagd_arp_msg)); + iccpd_arp = (struct ARPMsg*)msg->buf; + + mclagd_arp.op_type = iccpd_arp->op_type; + memcpy(mclagd_arp.ifname, iccpd_arp->ifname, strlen(iccpd_arp->ifname)); + memcpy(mclagd_arp.ipv4_addr, show_ip_str(iccpd_arp->ipv4_addr), 16); + memcpy(mclagd_arp.mac_addr, iccpd_arp->mac_addr, 6); + + memcpy(arp_buf + MCLAGD_REPLY_INFO_HDR + arp_num * sizeof(struct mclagd_arp_msg), + &mclagd_arp, sizeof(struct mclagd_arp_msg)); + + arp_num++; + + if ((arp_num + 1) * sizeof(struct mclagd_arp_msg) > (arp_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + arp_buf_size += MCLAGDCTL_CMD_SIZE; + arp_buf = (char*)realloc(arp_buf, arp_buf_size); + if (!arp_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = arp_buf; + *num = arp_num; + + if (mclag_id > 0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_ndisc_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct NDISCMsg *iccpd_ndisc = NULL; + struct mclagd_ndisc_msg mclagd_ndisc; + int ndisc_num = 0; + int id_exist = 0; + char *ndisc_buf = NULL; + int ndisc_buf_size = MCLAGDCTL_CMD_SIZE; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + ndisc_buf = (char *)malloc(ndisc_buf_size); + if (!ndisc_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id > 0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail) + { + memset(&mclagd_ndisc, 0, sizeof(struct mclagd_ndisc_msg)); + iccpd_ndisc = (struct NDISCMsg *)msg->buf; + + mclagd_ndisc.op_type = iccpd_ndisc->op_type; + memcpy(mclagd_ndisc.ifname, iccpd_ndisc->ifname, strlen(iccpd_ndisc->ifname)); + memcpy(mclagd_ndisc.ipv6_addr, show_ipv6_str((char *)iccpd_ndisc->ipv6_addr), 46); + memcpy(mclagd_ndisc.mac_addr, iccpd_ndisc->mac_addr, 6); + + memcpy(ndisc_buf + MCLAGD_REPLY_INFO_HDR + ndisc_num * sizeof(struct mclagd_ndisc_msg), + &mclagd_ndisc, sizeof(struct mclagd_ndisc_msg)); + + ndisc_num++; + + if ((ndisc_num + 1) * sizeof(struct mclagd_ndisc_msg) > (ndisc_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + ndisc_buf_size += MCLAGDCTL_CMD_SIZE; + ndisc_buf = (char *)realloc(ndisc_buf, ndisc_buf_size); + if (!ndisc_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = ndisc_buf; + *num = ndisc_num; + + if (mclag_id > 0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_mac_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct MACMsg *iccpd_mac = NULL; + struct mclagd_mac_msg mclagd_mac; + int mac_num = 0; + int id_exist = 0; + char * mac_buf = NULL; + int mac_buf_size = MCLAGDCTL_CMD_SIZE; + + if (!(sys = system_get_instance())) + { + return EXEC_TYPE_NO_EXIST_SYS; + } + + mac_buf = (char*)malloc(mac_buf_size); + if (!mac_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id > 0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + memset(&mclagd_mac, 0, sizeof(struct mclagd_mac_msg)); + iccpd_mac = (struct MACMsg*)msg->buf; + + mclagd_mac.op_type = iccpd_mac->op_type; + mclagd_mac.fdb_type = iccpd_mac->fdb_type; + memcpy(mclagd_mac.mac_str, iccpd_mac->mac_str, ETHER_ADDR_STR_LEN); + mclagd_mac.vid = iccpd_mac->vid; + memcpy(mclagd_mac.ifname, iccpd_mac->ifname, strlen(iccpd_mac->ifname)); + memcpy(mclagd_mac.origin_ifname, iccpd_mac->origin_ifname, strlen(iccpd_mac->origin_ifname)); + mclagd_mac.age_flag = iccpd_mac->age_flag; + + memcpy(mac_buf + MCLAGD_REPLY_INFO_HDR + mac_num * sizeof(struct mclagd_mac_msg), + &mclagd_mac, sizeof(struct mclagd_mac_msg)); + + mac_num++; + + if ((mac_num + 1) * sizeof(struct mclagd_mac_msg) > (mac_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + mac_buf_size += MCLAGDCTL_CMD_SIZE; + mac_buf = (char*)realloc(mac_buf, mac_buf_size); + if (!mac_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = mac_buf; + *num = mac_num; + + if (mclag_id > 0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_local_if_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct LocalInterface *lif_po = NULL; + struct mclagd_local_if mclagd_lif; + struct VLAN_ID* vlan_id = NULL; + char * str_buf = NULL; + int str_size = MCLAGDCTL_PARA3_LEN - 1; + int len = 0; + int lif_num = 0; + int id_exist = 0; + int lif_buf_size = MCLAGDCTL_CMD_SIZE; + char * lif_buf = NULL; + + if (!(sys = system_get_instance())) + { + return EXEC_TYPE_NO_EXIST_SYS; + } + + lif_buf = (char*)malloc(lif_buf_size); + if (!lif_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id > 0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + memset(&mclagd_lif, 0, sizeof(struct mclagd_local_if)); + + mclagd_lif.ifindex = lif_po->ifindex; + + if (lif_po->type == IF_T_UNKNOW) + memcpy(mclagd_lif.type, "Unknown", 6); + else if (lif_po->type == IF_T_PORT) + memcpy(mclagd_lif.type, "Ethernet", 8); + else if (lif_po->type == IF_T_PORT_CHANNEL) + memcpy(mclagd_lif.type, "PortChannel", 11); + + memcpy(mclagd_lif.name, lif_po->name, MAX_L_PORT_NAME); + memcpy(mclagd_lif.mac_addr, lif_po->mac_addr, ETHER_ADDR_LEN); + + if (lif_po->state == PORT_STATE_UP) + memcpy(mclagd_lif.state, "Up", 2); + else if (lif_po->state == PORT_STATE_DOWN) + memcpy(mclagd_lif.state, "Down", 4); + else if (lif_po->state == PORT_STATE_ADMIN_DOWN) + memcpy(mclagd_lif.state, "Admin-down", 10); + else if (lif_po->state == PORT_STATE_TEST) + memcpy(mclagd_lif.state, "Test", 4); + + memcpy(mclagd_lif.ipv4_addr, show_ip_str(htonl(lif_po->ipv4_addr)), 16); + mclagd_lif.prefixlen = lif_po->prefixlen; + + mclagd_lif.l3_mode = local_if_is_l3_mode(lif_po); + + mclagd_lif.is_peer_link = lif_po->is_peer_link; + + memcpy(mclagd_lif.portchannel_member_buf, lif_po->portchannel_member_buf, 512); + + mclagd_lif.po_id = lif_po->po_id; + mclagd_lif.po_active = lif_po->po_active; + /*mlacp_state*/ + if (lif_po->mlacp_state == MLACP_STATE_INIT) + memcpy(mclagd_lif.mlacp_state, "INIT", 4); + else if (lif_po->mlacp_state == MLACP_STATE_STAGE1) + memcpy(mclagd_lif.mlacp_state, "STAGE1", 6); + else if (lif_po->mlacp_state == MLACP_STATE_STAGE2) + memcpy(mclagd_lif.mlacp_state, "STAGE2", 6); + else if (lif_po->mlacp_state == MLACP_STATE_EXCHANGE) + memcpy(mclagd_lif.mlacp_state, "EXCHANGE", 8); + else if (lif_po->mlacp_state == MLACP_STATE_ERROR) + memcpy(mclagd_lif.mlacp_state, "ERROR", 5); + + mclagd_lif.isolate_to_peer_link = lif_po->isolate_to_peer_link; + + str_buf = mclagd_lif.vlanlist; + + len = 0; + LIST_FOREACH(vlan_id, &(lif_po->vlan_list), port_next) + { + if (vlan_id != NULL ) + { + if (str_size - len < 4) + break; + len += snprintf(str_buf + len, str_size - len, "%d ", vlan_id->vid); + } + } + + memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num * sizeof(struct mclagd_local_if), + &mclagd_lif, sizeof(struct mclagd_local_if)); + + lif_num++; + + if ((lif_num + 1) * sizeof(struct mclagd_local_if) > (lif_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + lif_buf_size += MCLAGDCTL_CMD_SIZE; + lif_buf = (char*)realloc(lif_buf, lif_buf_size); + if (!lif_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = lif_buf; + *num = lif_num; + + if (mclag_id > 0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_peer_if_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct PeerInterface *pif_po = NULL; + struct mclagd_peer_if mclagd_pif; + int pif_num = 0; + int id_exist = 0; + int pif_buf_size = MCLAGDCTL_CMD_SIZE; + char *pif_buf = NULL; + + if (!(sys = system_get_instance())) + { + return EXEC_TYPE_NO_EXIST_SYS; + } + + pif_buf = (char*)malloc(pif_buf_size); + if (!pif_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id > 0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + LIST_FOREACH(pif_po, &(MLACP(csm).pif_list), mlacp_next) + { + memset(&mclagd_pif, 0, sizeof(struct mclagd_peer_if)); + + mclagd_pif.ifindex = pif_po->ifindex; + + if (pif_po->type == IF_T_UNKNOW) + memcpy(mclagd_pif.type, "Unknown", 6); + else if (pif_po->type == IF_T_PORT) + memcpy(mclagd_pif.type, "Ethernet", 8); + else if (pif_po->type == IF_T_PORT_CHANNEL) + memcpy(mclagd_pif.type, "PortChannel", 11); + + memcpy(mclagd_pif.name, pif_po->name, MAX_L_PORT_NAME); + memcpy(mclagd_pif.mac_addr, pif_po->mac_addr, ETHER_ADDR_LEN); + + if (pif_po->state == PORT_STATE_UP) + memcpy(mclagd_pif.state, "Up", 2); + else if (pif_po->state == PORT_STATE_DOWN) + memcpy(mclagd_pif.state, "Down", 4); + else if (pif_po->state == PORT_STATE_ADMIN_DOWN) + memcpy(mclagd_pif.state, "Admin-down", 10); + else if (pif_po->state == PORT_STATE_TEST) + memcpy(mclagd_pif.state, "Test", 4); + + mclagd_pif.po_id = pif_po->po_id; + mclagd_pif.po_active = pif_po->po_active; + + memcpy(pif_buf + MCLAGD_REPLY_INFO_HDR + pif_num * sizeof(struct mclagd_peer_if), + &mclagd_pif, sizeof(struct mclagd_peer_if)); + + pif_num++; + + if ((pif_num + 1) * sizeof(struct mclagd_peer_if) > (pif_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + pif_buf_size += MCLAGDCTL_CMD_SIZE; + pif_buf = (char*)realloc(pif_buf, pif_buf_size); + if (!pif_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = pif_buf; + *num = pif_num; + + if (mclag_id > 0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + diff --git a/src/iccpd/src/iccp_consistency_check.c b/src/iccpd/src/iccp_consistency_check.c new file mode 100644 index 000000000000..90ac9cd9e790 --- /dev/null +++ b/src/iccpd/src/iccp_consistency_check.c @@ -0,0 +1,175 @@ +/* + * iccp_consistency_check.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + * + */ + +#include "../include/iccp_consistency_check.h" +#include "../include/system.h" +#include "../include/port.h" +#include "../include/logger.h" + +/* Return 0 if the checking procedure is failed; otherwise, 1 (non-zero) will be returned. */ +typedef int (*ConsistencyCheckFunc)(char* ifname); + +const char *reasons[] = { + /* REASON_NONE */ + "Success", + /* REASON_INTERRFACE_MODE_IS_ASYNC */ + "Port-channel interface is not in the same mode in local and peer device, please check whether the ip addr settings is correct or not.", + /* REASON_PEER_IF_IP_IS_ASYNC */ + "IP address of peer interface is not synchronized, please check the IP address setting on the corresponding interface.", + /* REASON_PEER_IF_VLAN_IS_ASYNC */ + "VLAN settings on this port-channel interface is not synchronized, please check your configuration.", + /* REASON_MAX_ARRAY_SIZE */ + NULL +}; + +/* Consistency Checking functions */ +static int iccp_check_interface_mode( char* ifname) +{ + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + struct PeerInterface* peer_if = NULL; + + local_if = local_if_find_by_name(ifname); + if (local_if == NULL) + return -2; + + csm = local_if->csm; + if (csm == NULL) + return -3; + + peer_if = peer_if_find_by_name(csm, ifname); + if (peer_if == NULL) + return -4; + + if (peer_if->l3_mode != local_if->l3_mode) + return -5; + + return 1; +} + +static int iccp_check_interface_layer3_addr(char* ifname) +{ + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + struct PeerInterface* peer_if = NULL; + + local_if = local_if_find_by_name(ifname); + if (local_if == NULL) + return -2; + + csm = local_if->csm; + if (csm == NULL) + return -3; + + peer_if = peer_if_find_by_name(csm, ifname); + if (peer_if == NULL) + return -4; + + if (peer_if->ipv4_addr != local_if->ipv4_addr) + return -5; + + return 1; +} + +static int iccp_check_interface_vlan(char* ifname) +{ + struct CSM* csm = NULL; + struct PeerInterface* peer_if = NULL; + struct VLAN_ID* local_vlan = NULL; + struct VLAN_ID* peer_vlan = NULL; + struct LocalInterface* local_if = NULL; + + local_if = local_if_find_by_name(ifname); + if (local_if == NULL) + return -2; + + csm = local_if->csm; + if (csm == NULL) + return -3; + + peer_if = peer_if_find_by_name(csm, ifname); + if (peer_if == NULL) + return -4; + + LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next) + { + LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) + { + if (peer_vlan->vid == local_vlan->vid) + break; + } + + if (peer_vlan == NULL) + { + return -5; + } + } + + LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) + { + + LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next) + { + if (peer_vlan->vid == local_vlan->vid) + break; + } + + if (local_vlan == NULL) + { + return -6; + } + } + + return 1; +} + +static const ConsistencyCheckFunc check_func[] = { + NULL, + iccp_check_interface_mode, /* REASON_INTERFACE_MODE_IS_ASYNC */ + iccp_check_interface_layer3_addr, /* REASON_PEER_IF_IP_IS_ASYNC */ + iccp_check_interface_vlan, /* REASON_PEER_IF_VLAN_IS_ASYNC */ + NULL /* REASON_MAX_ARRAY_SIZE */ +}; +#define ARRAY_SIZE(array_name) (sizeof(array_name) / sizeof(array_name[0])) + +enum Reason_ID iccp_consistency_check(char* ifname) +{ + int i = 0; + int ret = 0; + + for (i = REASON_INTERRFACE_MODE_IS_ASYNC; i < REASON_MAX_ARRAY_SIZE; ++i) + { + if (check_func[i] == NULL) + continue; + ret = check_func[i](ifname); + if (ret != 1) + { + ICCPD_LOG_WARN(__FUNCTION__, "%s ret = %d", reasons[i], ret); + fprintf(stdout, "%s \n", reasons[i]); + return i; + } + } + + return REASON_NONE; +} diff --git a/src/iccpd/src/iccp_csm.c b/src/iccpd/src/iccp_csm.c new file mode 100644 index 000000000000..79e17b9e1ba2 --- /dev/null +++ b/src/iccpd/src/iccp_csm.c @@ -0,0 +1,797 @@ +/* + * iccp_csm.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include +#include + +#include "../include/logger.h" +#include "../include/system.h" +#include "../include/scheduler.h" +#include "../include/msg_format.h" +#include "../include/iccp_csm.h" +#include "../include/mlacp_link_handler.h" +/***************************************** +* Define +* +* ***************************************/ +#define ICCP_CSM_QUEUE_REINIT(list) \ + { \ + struct Msg* msg = NULL; \ + while (!TAILQ_EMPTY(&(list))) { \ + msg = TAILQ_FIRST(&(list)); \ + TAILQ_REMOVE(&(list), msg, tail); \ + free(msg->buf); \ + free(msg); \ + } \ + TAILQ_INIT(&(list)); \ + } + +/***************************************** +* Global +* +* ***************************************/ +char g_csm_buf[CSM_BUFFER_SIZE] = { 0 }; + +uint32_t ICCP_MSG_ID = 0x1; + +/* Enter Connection State Machine NONEXISTENT handle function */ +static void iccp_csm_enter_state_nonexistent(struct CSM* csm) +{ + iccp_csm_finalize(csm); +} + +/* Enter Connection State Machine INITIALIZED handle function */ +static void iccp_csm_enter_state_initialized(struct CSM* csm) +{ + if (csm == NULL) + return; + + csm->iccp_info.sender_capability_flag = 0x1; +} + +/* Enter Connection State Machine CAPREC handle function */ +static void iccp_csm_enter_state_caprec(struct CSM* csm) +{ + if (csm == NULL) + return; + + csm->iccp_info.sender_capability_flag = 0x1; + csm->iccp_info.peer_capability_flag = 0x1; +} + +/* Enter Connection State Machine CONNECTING handle function */ +static void iccp_csm_enter_state_connecting(struct CSM* csm) +{ + if (csm == NULL) + return; + + csm->iccp_info.sender_rg_connect_flag = 0x1; +} + +/* Enter Connection State Machine OPERATIONAL handle function */ +static void iccp_csm_enter_state_operational(struct CSM* csm) +{ + if (csm == NULL) + return; + + csm->iccp_info.sender_rg_connect_flag = 0x1; + csm->iccp_info.peer_rg_connect_flag = 0x1; +} + +void *iccp_get_csm() +{ + struct CSM* csm = NULL; + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + { + return NULL; + } + + csm = system_create_csm(); + + return csm; +} + +/* Connection State Machine instance initialization */ +void iccp_csm_init(struct CSM* csm) +{ + iccp_csm_status_reset(csm, 1); + memset(csm->sender_ip, 0, INET_ADDRSTRLEN); + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); + memset(csm->iccp_info.sender_name, 0, MAX_L_ICC_SENDER_NAME); + csm->iccp_info.icc_rg_id = 0x0; +} + +/* Connection State Machine instance status reset */ +void iccp_csm_status_reset(struct CSM* csm, int all) +{ + ICCP_CSM_QUEUE_REINIT(csm->msg_list); + + if (all) + { + bzero(csm, sizeof(struct CSM)); + ICCP_CSM_QUEUE_REINIT(csm->msg_list); + } + + csm->sock_fd = -1; + pthread_mutex_init(&csm->conn_mutex, NULL); + csm->connTimePrev = 0; + csm->heartbeat_send_time = 0; + csm->heartbeat_update_time = 0; + csm->peer_warm_reboot_time = 0; + csm->warm_reboot_disconn_time = 0; + csm->role_type = STP_ROLE_NONE; + csm->sock_read_event_ptr = NULL; + csm->peer_link_if = NULL; + csm->u_msg_in_count = 0x0; + csm->i_msg_in_count = 0x0; + csm->icc_msg_in_count = 0x0; + csm->icc_msg_out_count = 0x0; + csm->iccp_info.status_code = 0x0; + csm->iccp_info.rejected_msg_id = 0x0; + csm->current_state = ICCP_NONEXISTENT; + csm->iccp_info.peer_capability_flag = 0x0; + csm->iccp_info.peer_rg_connect_flag = 0x0; + csm->iccp_info.sender_capability_flag = 0x0; + csm->iccp_info.sender_rg_connect_flag = 0x0; + app_csm_init(csm, all); + + memset(&csm->msg_log, 0, sizeof(struct MsgLog)); +} + +/* Connection State Machine instance tear down */ +void iccp_csm_finalize(struct CSM* csm) +{ + struct If_info * cif = NULL; + struct System* sys = NULL; + + if (csm == NULL) + return; + + if ((sys = system_get_instance()) == NULL) + return; + + /*If warm reboot, don't change port block and peer link MAC learning*/ + if (sys->warmboot_exit != WARM_REBOOT) + { + /*Enable peer link port MAC learning*/ + if (csm->peer_link_if) + set_peerlink_mlag_port_learn(csm->peer_link_if, 1); + } + + /* Disconnect from peer */ + scheduler_session_disconnect_handler(csm); + + /* Release all Connection State Machine instance */ + app_csm_finalize(csm); + + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + LIST_REMOVE(cif, csm_next); + } + + /* Release iccp_csm */ + pthread_mutex_destroy(&(csm->conn_mutex)); + iccp_csm_msg_list_finalize(csm); + LIST_REMOVE(csm, next); + free(csm); +} + +/* Message list of Connection State Machine instance tear down */ +void iccp_csm_msg_list_finalize(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (csm == NULL) + return; + + while (!TAILQ_EMPTY(&(csm->msg_list))) + { + msg = TAILQ_FIRST(&(csm->msg_list)); + TAILQ_REMOVE(&(csm->msg_list), msg, tail); + free(msg); + } +} + +/* Send message to peer */ +int iccp_csm_send(struct CSM* csm, char* buf, int msg_len) +{ + LDPHdr* ldp_hdr = (LDPHdr*)buf; + ICCParameter* param = NULL; + + if (csm == NULL || buf == NULL || csm->sock_fd <= 0 || msg_len <= 0) + return MCLAG_ERROR; + + if (ntohs(ldp_hdr->msg_type) == MSG_T_CAPABILITY) + param = (struct ICCParameter*)&buf[sizeof(LDPHdr)]; + else + param = (struct ICCParameter*)&buf[sizeof(ICCHdr)]; + + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Send(%d): len=[%d] msg_type=[%s (0x%X, 0x%X)]", csm->sock_fd, msg_len, get_tlv_type_string(param->type), ldp_hdr->msg_type, param->type);*/ + csm->msg_log.msg[csm->msg_log.end_index].msg_id = ntohl(ldp_hdr->msg_id); + csm->msg_log.msg[csm->msg_log.end_index].type = ntohs(ldp_hdr->msg_type); + csm->msg_log.msg[csm->msg_log.end_index].tlv = ntohs(param->type); + ++csm->msg_log.end_index; + if (csm->msg_log.end_index >= 128) + csm->msg_log.end_index = 0; + + return write(csm->sock_fd, buf, msg_len); +} + +/* Connection State Machine Transition */ +void iccp_csm_transit(struct CSM* csm) +{ + int len = -1; + struct Msg* msg = NULL; + ICCP_CONNECTION_STATE_E prev_state; + char *state_str[] = {"NONEXISTENT", "INITIALIZED", "CAPSENT", "CAPREC", "CONNECTING", "OPERATIONAL"}; + + if (!csm) + return; + + prev_state = csm->current_state; + + /* No connection, but have state change? reset it...*/ + if (csm->current_state != ICCP_NONEXISTENT && csm->sock_fd <= 0) + { + ICCPD_LOG_NOTICE(__FUNCTION__, "csm %d change state from %s to NONEXISTENT.", csm->mlag_id, state_str[csm->current_state]); + csm->current_state = ICCP_NONEXISTENT; + iccp_csm_enter_state_nonexistent(csm); + return; + } + + msg = iccp_csm_dequeue_msg(csm); + + switch (csm->current_state) + { + case ICCP_NONEXISTENT: + scheduler_prepare_session(csm); + if (csm->sock_fd > 0 && scheduler_check_csm_config(csm) > 0) + csm->current_state = ICCP_INITIALIZED; + break; + + case ICCP_INITIALIZED: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x0) + csm->current_state = ICCP_CAPSENT; + else if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x1) + csm->current_state = ICCP_CAPREC; + break; + + case ICCP_CAPSENT: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x1) + csm->current_state = ICCP_CAPREC; + break; + + case ICCP_CAPREC: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + if (csm->iccp_info.peer_rg_connect_flag == 0x0 && csm->iccp_info.status_code == 0x0) + csm->current_state = ICCP_CONNECTING; + else if (csm->iccp_info.peer_rg_connect_flag == 0x1 && csm->iccp_info.status_code == 0x0) + csm->current_state = ICCP_OPERATIONAL; + break; + + case ICCP_CONNECTING: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + if (csm->iccp_info.status_code > 0x0) + csm->current_state = ICCP_CAPREC; + else if (csm->iccp_info.peer_rg_connect_flag == 0x1 && csm->iccp_info.status_code == 0x0) + csm->current_state = ICCP_OPERATIONAL; + break; + + case ICCP_OPERATIONAL: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + if (csm->iccp_info.sender_rg_connect_flag == 0x0 || csm->iccp_info.peer_rg_connect_flag == 0x0) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + csm->current_state = ICCP_CAPREC; + } + break; + + default: + break; + } + + if (prev_state != csm->current_state || (csm->current_state && msg != NULL)) + { + if (prev_state != csm->current_state) + ICCPD_LOG_NOTICE(__FUNCTION__, "csm %d change state from %s to %s.", csm->mlag_id, state_str[prev_state], state_str[csm->current_state]); + + switch (csm->current_state) + { + case ICCP_NONEXISTENT: + iccp_csm_enter_state_nonexistent(csm); + break; + + case ICCP_INITIALIZED: + iccp_csm_enter_state_initialized(csm); + break; + + case ICCP_CAPSENT: + /* Do nothing on this state */ + break; + + case ICCP_CAPREC: + iccp_csm_enter_state_caprec(csm); + break; + + case ICCP_CONNECTING: + iccp_csm_enter_state_connecting(csm); + break; + + case ICCP_OPERATIONAL: + iccp_csm_enter_state_operational(csm); + break; + + default: + break; + } + } +} + +/* Set up ICCP message */ +int iccp_csm_prepare_iccp_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + size_t msg_len = -1; + + if (csm == NULL || buf == NULL) + return MCLAG_ERROR; + + switch (csm->current_state) + { + case ICCP_NONEXISTENT: + /* Do nothing on this state */ + break; + + case ICCP_INITIALIZED: + msg_len = iccp_csm_prepare_capability_msg(csm, buf, max_buf_size); + break; + + case ICCP_CAPSENT: + /* Do nothing on this state */ + break; + + case ICCP_CAPREC: + if (csm->iccp_info.status_code > 0x0) + { + msg_len = iccp_csm_prepare_nak_msg(csm, buf, max_buf_size); + break; + } + msg_len = iccp_csm_prepare_rg_connect_msg(csm, buf, max_buf_size); + break; + + case ICCP_CONNECTING: + if (csm->iccp_info.status_code > 0x0) + { + msg_len = iccp_csm_prepare_nak_msg(csm, buf, max_buf_size); + break; + } + break; + + case ICCP_OPERATIONAL: + if (csm->iccp_info.peer_rg_connect_flag == 0x0) + { + msg_len = iccp_csm_prepare_rg_disconnect_msg(csm, buf, max_buf_size); + break; + } + break; + } + + return msg_len; +} + +/* ICCP capability message handle function */ +int iccp_csm_prepare_capability_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + LDPHdr* ldp_hdr = (LDPHdr*)buf; + LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*)&buf[sizeof(LDPHdr)]; + size_t msg_len = sizeof(LDPHdr) + sizeof(LDPICCPCapabilityTLV); + + memset(buf, 0, max_buf_size); + + /* LDP header */ + ldp_hdr->u_bit = 0x0; + ldp_hdr->msg_type = htons(MSG_T_CAPABILITY); + ldp_hdr->msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); + ldp_hdr->msg_id = htonl(ICCP_MSG_ID++); + + /* LDP ICCP capability TLV */ + cap->icc_parameter.u_bit = 0x1; + cap->icc_parameter.f_bit = 0x0; + cap->icc_parameter.type = TLV_T_ICCP_CAPABILITY; + *(uint16_t *)cap = htons(*(uint16_t *)cap); + + cap->icc_parameter.len = htons(TLV_L_ICCP_CAPABILITY); + + cap->s_bit = csm->iccp_info.sender_capability_flag; + *(uint16_t *)((uint8_t *)cap + sizeof(ICCParameter)) = htons(*(uint16_t *)((uint8_t *)cap + sizeof(ICCParameter))); + + cap->major_ver = 0x1; + cap->minior_ver = 0x0; + + return msg_len; +} + +void iccp_csm_fill_icc_rg_id_tlv(struct CSM* csm, ICCHdr* icc_hdr) +{ + if (!csm || !icc_hdr) + return; + + icc_hdr->icc_rg_id_tlv.type = htons(TLV_T_ICC_RG_ID); + icc_hdr->icc_rg_id_tlv.len = htons(TLV_L_ICC_RG_ID); + icc_hdr->icc_rg_id_tlv.icc_rg_id = htonl(csm->iccp_info.icc_rg_id); +} + +/* ICCP NAK message handle function */ +int iccp_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*)buf; + NAKTLV* nak = (NAKTLV*)&buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(NAKTLV); + + memset(buf, 0, max_buf_size); + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = htons(MSG_T_NOTIFICATION); + icc_hdr->ldp_hdr.msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); + icc_hdr->ldp_hdr.msg_id = htonl(ICCP_MSG_ID++); + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + /* NAL TLV */ + nak->icc_parameter.u_bit = 0x0; + nak->icc_parameter.f_bit = 0x0; + nak->icc_parameter.type = htons(TLV_T_NAK); + nak->icc_parameter.len = htons(sizeof(((struct NAKTLV*)0)->iccp_status_code) + sizeof(((struct NAKTLV*)0)->rejected_msg_id)); + + switch (csm->iccp_info.status_code) + { + case STATUS_CODE_U_ICCP_RG: + nak->iccp_status_code = htonl(csm->iccp_info.status_code); + nak->rejected_msg_id = htonl(csm->iccp_info.rejected_msg_id); + break; + + /* Unsupported */ + case STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED: + case STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED: + case STATUS_CODE_ICCP_APP_NOT_IN_RG: + case STATUS_CODE_INCOMPATIBLE_ICCP_PROTOCOL_VER: + case STATUS_CODE_ICCP_REJECTED_MSG: + case STATUS_CODE_ICCP_ADMINISTRATIVELY_DISABLED: + case STATUS_CODE_ICCP_RG_REMOVED: + case STATUS_CODE_ICCP_APP_REMOVED_FROM_RG: + break; + } + + return msg_len; +} + +/* ICCP RG connect handle function */ +int iccp_csm_prepare_rg_connect_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*)buf; + ICCSenderNameTLV* sender = (ICCSenderNameTLV*)&buf[sizeof(ICCHdr)]; + size_t name_len = strlen(csm->iccp_info.sender_name); + size_t msg_len = sizeof(ICCHdr) + sizeof(ICCParameter) + name_len; + + memset(buf, 0, max_buf_size); + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = htons(MSG_T_RG_CONNECT); + icc_hdr->ldp_hdr.msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); + icc_hdr->ldp_hdr.msg_id = htonl(ICCP_MSG_ID++); + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + /* ICC sender name TLV */ + sender->icc_parameter.u_bit = 0x0; + sender->icc_parameter.f_bit = 0x0; + sender->icc_parameter.type = htons(TLV_T_ICC_SENDER_NAME); + sender->icc_parameter.len = htons(name_len); + memcpy(sender->sender_name, csm->iccp_info.sender_name, name_len); + + return msg_len; +} + +/* ICCP RG disconnect handle function */ +int iccp_csm_prepare_rg_disconnect_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*)buf; + DisconnectCodeTLV* disconn_code = (DisconnectCodeTLV*)&buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(DisconnectCodeTLV); + + memset(buf, 0, max_buf_size); + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = htons(MSG_T_RG_DISCONNECT); + icc_hdr->ldp_hdr.msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); + icc_hdr->ldp_hdr.msg_id = htonl(ICCP_MSG_ID++); + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + /* Disconnect code TLV */ + disconn_code->icc_parameter.u_bit = 0x0; + disconn_code->icc_parameter.f_bit = 0x0; + disconn_code->icc_parameter.type = htons(TLV_T_DISCONNECT_CODE); + disconn_code->icc_parameter.len = htons(sizeof(((struct DisconnectCodeTLV*)0)->iccp_status_code)); + disconn_code->iccp_status_code = htonl(csm->iccp_info.status_code); + + return msg_len; +} + +/* Check ID(MC-LAG ID, mLACP ID, RG ID) from received message */ +static void iccp_csm_check_id_from_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + + if (!csm || !msg || !msg->buf) + return; + + icc_hdr = (ICCHdr*)msg->buf; + + /* Capability Message doesn't have ICC RG ID TLV */ + if (icc_hdr->ldp_hdr.msg_type == MSG_T_CAPABILITY) + return; + + /* Check if received message ID same as local configuration */ + if (ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id) == csm->iccp_info.icc_rg_id) + { + if (csm->iccp_info.status_code == STATUS_CODE_U_ICCP_RG) + { + csm->iccp_info.status_code = 0x0; + csm->iccp_info.rejected_msg_id = 0x0; + } + } + else if (ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id) != csm->iccp_info.icc_rg_id) + { + csm->iccp_info.status_code = STATUS_CODE_U_ICCP_RG; + csm->iccp_info.rejected_msg_id = ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id); + } +} + +/* Receive message correspond function */ +void iccp_csm_correspond_from_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + + if (csm == NULL || msg == NULL || msg->buf == NULL) + return; + + icc_hdr = (ICCHdr*)msg->buf; + NAKTLV* nak = (NAKTLV*)( icc_hdr + sizeof(ICCHdr)); + iccp_csm_check_id_from_msg(csm, msg); + + if (icc_hdr->ldp_hdr.msg_type == MSG_T_CAPABILITY) + iccp_csm_correspond_from_capability_msg(csm, msg); + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_CONNECT) + iccp_csm_correspond_from_rg_connect_msg(csm, msg); + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_DISCONNECT) + iccp_csm_correspond_from_rg_disconnect_msg(csm, msg); + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Received MSG_T_NOTIFICATION ,err status %s reason of %s", get_status_string(ntohl(nak->iccp_status_code)), get_status_string(csm->iccp_info.status_code)); + sleep(1); + } + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + ;// do nothing + } + else + { + ++csm->u_msg_in_count; + } + + free(msg->buf); + free(msg); +} + +/* Receive capability message correspond function */ +void iccp_csm_correspond_from_capability_msg(struct CSM* csm, struct Msg* msg) +{ + LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*)&(msg->buf)[sizeof(LDPHdr)]; + + *(uint16_t *)cap = ntohs(*(uint16_t *)cap); + *(uint16_t *)((uint8_t *)cap + sizeof(ICCParameter)) = ntohs(*(uint16_t *)((uint8_t *)cap + sizeof(ICCParameter))); + + if (cap->icc_parameter.u_bit == 0x1 + && cap->icc_parameter.f_bit == 0x0 + && cap->icc_parameter.type == TLV_T_ICCP_CAPABILITY + && ntohs(cap->icc_parameter.len) == (TLV_L_ICCP_CAPABILITY) + && cap->s_bit == 1 + && cap->major_ver == 0x1 + && cap->minior_ver == 0x0) + { + csm->iccp_info.peer_capability_flag = 0x1; + } +} + +/* Receive RG connect message correspond function */ +void iccp_csm_correspond_from_rg_connect_msg(struct CSM* csm, struct Msg* msg) +{ + ICCSenderNameTLV* sender = (ICCSenderNameTLV*)&(msg->buf)[sizeof(ICCHdr)]; + + *(uint16_t *)sender = ntohs(*(uint16_t *)sender); + + if (sender->icc_parameter.u_bit == 0x0 && + sender->icc_parameter.f_bit == 0x0 && + sender->icc_parameter.type == TLV_T_ICC_SENDER_NAME) + { + csm->iccp_info.peer_rg_connect_flag = 0x1; + } +} + +/* Receive RG disconnect message correspond function */ +void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM* csm, struct Msg* msg) +{ + DisconnectCodeTLV* diconn_code = (DisconnectCodeTLV*)&(msg->buf)[sizeof(ICCHdr)]; + + *(uint16_t *)diconn_code = ntohs(*(uint16_t *)diconn_code); + + if (diconn_code->icc_parameter.u_bit == 0x0 + && diconn_code->icc_parameter.f_bit == 0x0 + && diconn_code->icc_parameter.type == TLV_T_DISCONNECT_CODE + && ntohs(diconn_code->icc_parameter.len) == (TLV_L_DISCONNECT_CODE) + && ntohl(diconn_code->iccp_status_code) == (STATUS_CODE_ICCP_RG_REMOVED)) + { + csm->iccp_info.sender_rg_connect_flag = 0x0; + csm->iccp_info.peer_rg_connect_flag = 0x0; + } +} + +/* Add received message into message list */ +void iccp_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + NAKTLV* naktlv = NULL; + int type = -1; + int i = 0; + + if (csm == NULL) + { + if (msg != NULL) + free(msg); + return; + } + + if (msg == NULL) + return; + + icc_hdr = (ICCHdr*)msg->buf; + + *(uint16_t *)icc_hdr = ntohs(*(uint16_t *)icc_hdr); + + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + app_csm_enqueue_msg(csm, msg); + } + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + { + naktlv = (NAKTLV*)&msg->buf[sizeof(ICCHdr)]; + + for (i = 0; i < MAX_MSG_LOG_SIZE; ++i) + { + if (ntohl(naktlv->rejected_msg_id) == csm->msg_log.msg[i].msg_id) + { + type = csm->msg_log.msg[i].type; + break; + } + } + + if (type == MSG_T_RG_APP_DATA) + app_csm_enqueue_msg(csm, msg); + else + TAILQ_INSERT_TAIL(&(csm->msg_list), msg, tail); + } + else + { + TAILQ_INSERT_TAIL(&(csm->msg_list), msg, tail); + } +} + +/* Get received message from message list */ +struct Msg* iccp_csm_dequeue_msg(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (!TAILQ_EMPTY(&(csm->msg_list))) + { + msg = TAILQ_FIRST(&(csm->msg_list)); + TAILQ_REMOVE(&(csm->msg_list), msg, tail); + + } + + return msg; +} + +/* Message initialization */ +int iccp_csm_init_msg(struct Msg** msg, char* data, int len) +{ + struct Msg* iccp_msg = NULL; + + if (msg == NULL) + return -2; + + if (data == NULL || len <= 0) + return MCLAG_ERROR; + + iccp_msg = (struct Msg*)malloc(sizeof(struct Msg)); + if (iccp_msg == NULL) + goto err_ret; + + iccp_msg->buf = (char*)malloc(len); + if (iccp_msg->buf == NULL) + goto err_ret; + + memcpy(iccp_msg->buf, data, len); + iccp_msg->len = len; + *msg = iccp_msg; + + return 0; + + err_ret: + if (iccp_msg) + { + if (iccp_msg->buf) + free(iccp_msg->buf); + free(iccp_msg); + } + + return MCLAG_ERROR; +} + +void iccp_csm_stp_role_count(struct CSM *csm) +{ + /* decide the role, lower ip to be active & socket client*/ + if (csm->role_type == STP_ROLE_NONE) + { + if (inet_addr(csm->sender_ip) < inet_addr(csm->peer_ip)) + { + /* Active*/ + ICCPD_LOG_INFO(__FUNCTION__, "Role: [Active]"); + csm->role_type = STP_ROLE_ACTIVE; + } + else + { + /* Standby*/ + ICCPD_LOG_INFO(__FUNCTION__, "Role [Standby]"); + csm->role_type = STP_ROLE_STANDBY; + } + } +} \ No newline at end of file diff --git a/src/iccpd/src/iccp_ifm.c b/src/iccpd/src/iccp_ifm.c new file mode 100644 index 000000000000..258c661e03a4 --- /dev/null +++ b/src/iccpd/src/iccp_ifm.c @@ -0,0 +1,1038 @@ +/* + * iccp_ifm.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "../include/system.h" +#include "../include/iccp_cli.h" +#include "../include/logger.h" +#include "../include/mlacp_sync_update.h" +#include "../include/mlacp_link_handler.h" +#include "../include/port.h" +#include "../include/iccp_netlink.h" + +#define fwd_neigh_state_valid(state) (state & (NUD_REACHABLE | NUD_STALE | NUD_DELAY | NUD_PROBE | NUD_PERMANENT)) + +#ifndef NDA_RTA +#define NDA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#endif + +static int iccp_valid_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + unsigned int event = 0; + + if (nlh->nlmsg_type != RTM_NEWLINK) + return 0; + + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) + ICCPD_LOG_ERR(__FUNCTION__, "Unknown message type."); + + return 0; +} + +/*Get kernel interfaces and ports during initialization*/ +int iccp_sys_local_if_list_get_init() +{ + struct System *sys = NULL; + struct nl_cb *cb; + struct nl_cb *orig_cb; + struct rtgenmsg rt_hdr = { + .rtgen_family = AF_UNSPEC, + }; + int ret; + int retry = 1; + + if (!(sys = system_get_instance())) + return MCLAG_ERROR; + + while (retry) + { + retry = 0; + ret = nl_send_simple(sys->route_sock, RTM_GETLINK, NLM_F_DUMP, + &rt_hdr, sizeof(rt_hdr)); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); + return ret; + } + + orig_cb = nl_socket_get_cb(sys->route_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + { + ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); + return -ENOMEM; + } + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_valid_handler, sys); + + ret = nl_recvmsgs(sys->route_sock, cb); + nl_cb_put(cb); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error. ret = %d errno = %d ", ret, errno); + if (ret != -NLE_DUMP_INTR) + return ret; + retry = 1; + } + } + + return ret; +} + +static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct ARPMsg *arp_msg = NULL, *arp_info = NULL; + struct VLAN_ID *vlan_id_list = NULL; + struct Msg *msg_send = NULL; + + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + + struct LocalInterface *lif_po = NULL, *arp_lif = NULL; + + int verify_arp = 0; + int arp_update = 0; + + if (!(sys = system_get_instance())) + return; + + /* Find local itf*/ + if (!(arp_lif = local_if_find_by_ifindex(ndm->ndm_ifindex))) + return; + + /* create ARP msg*/ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct ARPMsg); + arp_msg = (struct ARPMsg*)&buf; + arp_msg->op_type = NEIGH_SYNC_LIF; + sprintf(arp_msg->ifname, "%s", arp_lif->name); + if (tb[NDA_DST]) + memcpy(&arp_msg->ipv4_addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST])); + if (tb[NDA_LLADDR]) + memcpy(arp_msg->mac_addr, RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR])); + + arp_msg->ipv4_addr = arp_msg->ipv4_addr; + + ICCPD_LOG_NOTICE(__FUNCTION__, "ARP type %s, state (%04X)(%d) ifindex [%d] (%s) ip %s, mac [%02X:%02X:%02X:%02X:%02X:%02X]", + msgtype == RTM_NEWNEIGH ? "New":"Del", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state), + ndm->ndm_ifindex, arp_lif->name, + show_ip_str(arp_msg->ipv4_addr), + arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4], + arp_msg->mac_addr[5]); + + /* Find MLACP itf, member of port-channel*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if (!local_if_is_l3_mode(lif_po)) + { + /* Is the L2 MLAG itf belong to a vlan?*/ + LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) + { + if ( !(vlan_id_list->vlan_itf + && vlan_id_list->vlan_itf->ifindex == ndm->ndm_ifindex)) + continue; + break; + } + + if (!vlan_id_list) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from mclag enabled member port of vlan %s", + vlan_id_list->vlan_itf->name); + } + else + { + /* Is the ARP belong to a L3 mode MLAG itf?*/ + if (ndm->ndm_ifindex != lif_po->ifindex) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from mclag enabled intf %s", lif_po->name); + } + + verify_arp = 1; + + break; + } + + if (lif_po) + break; + } + + if (!(csm && lif_po)) + return; + if (!verify_arp) + return; + + /* update lif ARP*/ + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_info = (struct ARPMsg*)msg->buf; + if (arp_info->ipv4_addr != arp_msg->ipv4_addr) + continue; + + if (msgtype == RTM_DELNEIGH) + { + /* delete ARP*/ + TAILQ_REMOVE(&MLACP(csm).arp_list, msg, tail); + free(msg->buf); + free(msg); + msg = NULL; + ICCPD_LOG_DEBUG(__FUNCTION__, "Delete ARP %s", show_ip_str(arp_msg->ipv4_addr)); + } + else + { + /* update ARP*/ + if (arp_info->op_type != arp_msg->op_type + || strcmp(arp_info->ifname, arp_msg->ifname) != 0 + || memcmp(arp_info->mac_addr, arp_msg->mac_addr, + ETHER_ADDR_LEN) != 0) + { + arp_update = 1; + arp_info->op_type = arp_msg->op_type; + sprintf(arp_info->ifname, "%s", arp_msg->ifname); + memcpy(arp_info->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", show_ip_str(arp_msg->ipv4_addr)); + } + } + break; + } + + if (msg && !arp_update) + return; + + if (msgtype != RTM_DELNEIGH) + { + /* enquene lif_msg (add)*/ + if (!msg) + { + arp_msg->op_type = NEIGH_SYNC_LIF; + if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len) == 0) + { + mlacp_enqueue_arp(csm, msg); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", + arp_msg->ifname, show_ip_str(arp_msg->ipv4_addr));*/ + } + else + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", + arp_msg->ifname, show_ip_str(arp_msg->ipv4_addr)); + } + + /* enqueue iccp_msg (add)*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + arp_msg->op_type = NEIGH_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] message for %s", + show_ip_str(arp_msg->ipv4_addr));*/ + } + else + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[ADD] message for %s", + show_ip_str(arp_msg->ipv4_addr)); + + } + } + else + { + /* enqueue iccp_msg (delete)*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + arp_msg->op_type = NEIGH_SYNC_DEL; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[DEL] message for %s", + show_ip_str(arp_msg->ipv4_addr));*/ + } + else + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[DEL] message for %s", + show_ip_str(arp_msg->ipv4_addr)); + + } + } + + return; +} + +static void do_ndisc_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct NDISCMsg *ndisc_msg = NULL, *ndisc_info = NULL; + struct VLAN_ID *vlan_id_list = NULL; + struct Msg *msg_send = NULL; + + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + + struct LocalInterface *lif_po = NULL, *ndisc_lif = NULL; + + int verify_neigh = 0; + int neigh_update = 0; + + if (!(sys = system_get_instance())) + return; + + /* Find local itf */ + if (!(ndisc_lif = local_if_find_by_ifindex(ndm->ndm_ifindex))) + return; + + /* create NDISC msg */ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct NDISCMsg); + ndisc_msg = (struct NDISCMsg *)&buf; + ndisc_msg->op_type = NEIGH_SYNC_LIF; + sprintf(ndisc_msg->ifname, "%s", ndisc_lif->name); + if (tb[NDA_DST]) + memcpy(&ndisc_msg->ipv6_addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST])); + if (tb[NDA_LLADDR]) + memcpy(ndisc_msg->mac_addr, RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR])); + + ICCPD_LOG_NOTICE(__FUNCTION__, "ndisc type %s, state (%04X)(%d), ifindex [%d] (%s), ip %s, mac [%02X:%02X:%02X:%02X:%02X:%02X]", + msgtype == RTM_NEWNEIGH ? "New" : "Del", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state), + ndm->ndm_ifindex, ndisc_lif->name, + show_ipv6_str((char *)ndisc_msg->ipv6_addr), + ndisc_msg->mac_addr[0], ndisc_msg->mac_addr[1], ndisc_msg->mac_addr[2], ndisc_msg->mac_addr[3], ndisc_msg->mac_addr[4], + ndisc_msg->mac_addr[5]); + + /* Find MLACP itf, member of port-channel */ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if (!local_if_is_l3_mode(lif_po)) + { + /* Is the L2 MLAG itf belong to a vlan? */ + LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) + { + if (!(vlan_id_list->vlan_itf && vlan_id_list->vlan_itf->ifindex == ndm->ndm_ifindex)) + continue; + break; + } + + if (!vlan_id_list) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "ND is from mclag enabled member port of vlan %s", vlan_id_list->vlan_itf->name); + } + else + { + /* Is the ND belong to a L3 mode MLAG itf? */ + if (ndm->ndm_ifindex != lif_po->ifindex) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "ND is from mclag enabled intf %s", lif_po->name); + } + + verify_neigh = 1; + + break; + } + + if (lif_po) + break; + } + + if (!(csm && lif_po)) + return; + if (!verify_neigh) + return; + + /* update lif ND */ + TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail) + { + ndisc_info = (struct NDISCMsg *)msg->buf; + + if (memcmp(&ndisc_info->ipv6_addr, &ndisc_msg->ipv6_addr, 16) != 0) + continue; + + if (msgtype == RTM_DELNEIGH) + { + /* delete ND */ + TAILQ_REMOVE(&MLACP(csm).ndisc_list, msg, tail); + free(msg->buf); + free(msg); + msg = NULL; + ICCPD_LOG_DEBUG(__FUNCTION__, "Delete neighbor %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); + } + else + { + /* update ND */ + if (ndisc_info->op_type != ndisc_info->op_type + || strcmp(ndisc_info->ifname, ndisc_info->ifname) != 0 + || memcmp(ndisc_info->mac_addr, ndisc_info->mac_addr, ETHER_ADDR_LEN) != 0) + { + neigh_update = 1; + ndisc_info->op_type = ndisc_msg->op_type; + sprintf(ndisc_info->ifname, "%s", ndisc_msg->ifname); + memcpy(ndisc_info->mac_addr, ndisc_msg->mac_addr, ETHER_ADDR_LEN); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update neighbor for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); + } + } + break; + } + + if (msg && !neigh_update) + return; + + if (msgtype != RTM_DELNEIGH) + { + /* enquene lif_msg (add) */ + if (!msg) + { + ndisc_msg->op_type = NEIGH_SYNC_LIF; + if (iccp_csm_init_msg(&msg, (char *)ndisc_msg, msg_len) == 0) + { + mlacp_enqueue_ndisc(csm, msg); + /* ICCPD_LOG_DEBUG(__FUNCTION__, "Ndisc-list enqueue: %s, add %s", ndisc_msg->ifname, show_ipv6_str((char *)ndisc_msg->ipv6_addr)); */ + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue Ndisc-list: %s, add %s", + ndisc_msg->ifname, show_ipv6_str((char *)ndisc_msg->ipv6_addr)); + } + + /* enqueue iccp_msg (add) */ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + ndisc_msg->op_type = NEIGH_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char *)ndisc_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_msg_list), msg_send, tail); + /* ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue Ndisc[ADD] for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); */ + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue Ndisc[ADD] message for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); + + } + } + else + { + /* enqueue iccp_msg (delete) */ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + ndisc_msg->op_type = NEIGH_SYNC_DEL; + if (iccp_csm_init_msg(&msg_send, (char *)ndisc_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_msg_list), msg_send, tail); + /* ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue Ndisc[DEL] for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); */ + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue Ndisc[DEL] message for [%x:%x:%x:%x]", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); + + } + } + + return; +} + +int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta, int len, unsigned short flags) +{ + unsigned short type; + + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + while (RTA_OK(rta, len)) + { + type = rta->rta_type & ~flags; + if ((type <= max) && (!tb[type])) + tb[type] = rta; + rta = RTA_NEXT(rta, len); + } + return 0; +} + +int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) +{ + return parse_rtattr_flags(tb, max, rta, len, 0); +} + +void ifm_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len) +{ + while (RTA_OK(rta, len)) + { + if (rta->rta_type <= max) + tb[rta->rta_type] = rta; + rta = RTA_NEXT(rta, len); + } +} + +int do_one_neigh_request(struct nlmsghdr *n) +{ + struct ndmsg *ndm = NLMSG_DATA(n); + int len = n->nlmsg_len; + struct rtattr *tb[NDA_MAX + 1] = {0}; + + if (n->nlmsg_type == NLMSG_DONE) + { + return 0; + } + + /* process msg_type RTM_NEWNEIGH, RTM_GETNEIGH, RTM_DELNEIGH */ + if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH ) + return(0); + + len -= NLMSG_LENGTH(sizeof(*ndm)); + if (len < 0) + return MCLAG_ERROR; + + ifm_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); + + if (n->nlmsg_type == RTM_NEWNEIGH + && (ndm->ndm_state == NUD_INCOMPLETE + || ndm->ndm_state == NUD_FAILED + || ndm->ndm_state == NUD_NOARP + || ndm->ndm_state == NUD_PERMANENT + || ndm->ndm_state == NUD_NONE)) + { + return(0); + } + + if (!tb[NDA_DST] || ndm->ndm_type != RTN_UNICAST) + { + return(0); + } + + if (ndm->ndm_family == AF_INET) + { + do_arp_learn_from_kernel(ndm, tb, n->nlmsg_type); + } + + if (ndm->ndm_family == AF_INET6) + { + do_ndisc_learn_from_kernel(ndm, tb, n->nlmsg_type); + } + return(0); +} + +static int iccp_neigh_valid_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + + do_one_neigh_request(nlh); + + return 0; +} + +int iccp_neigh_get_init() +{ + struct System *sys = NULL; + struct nl_cb *cb; + struct nl_cb *orig_cb; + struct rtgenmsg rt_hdr = { + .rtgen_family = AF_UNSPEC, + }; + int ret; + int retry = 1; + + if (!(sys = system_get_instance())) + return MCLAG_ERROR; + + while (retry) + { + retry = 0; + ret = nl_send_simple(sys->route_sock, RTM_GETNEIGH, NLM_F_DUMP, + &rt_hdr, sizeof(rt_hdr)); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Send netlink msg error."); + return ret; + } + + orig_cb = nl_socket_get_cb(sys->route_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + { + ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); + return -ENOMEM; + } + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_neigh_valid_handler, sys); + + ret = nl_recvmsgs(sys->route_sock, cb); + nl_cb_put(cb); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Receive netlink msg error."); + if (ret != -NLE_DUMP_INTR) + return ret; + + retry = 1; + } + } + + return ret; +} + +/*When received ARP packets from kernel, update arp information*/ +void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct ARPMsg *arp_msg = NULL, *arp_info = NULL; + struct VLAN_ID *vlan_id_list = NULL; + struct Msg *msg_send = NULL; + + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + + struct LocalInterface *lif_po = NULL, *arp_lif = NULL; + + int verify_arp = 0; + + if (!(sys = system_get_instance())) + return; + + /* Find local itf*/ + if (!(arp_lif = local_if_find_by_ifindex(ifindex))) + return; + + /* create ARP msg*/ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct ARPMsg); + arp_msg = (struct ARPMsg*)&buf; + arp_msg->op_type = NEIGH_SYNC_LIF; + sprintf(arp_msg->ifname, "%s", arp_lif->name); + memcpy(&arp_msg->ipv4_addr, &addr, 4); + memcpy(arp_msg->mac_addr, mac_addr, 6); + + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP ifindex [%d] (%s) ip %s mac [%02X:%02X:%02X:%02X:%02X:%02X]", + ifindex, arp_lif->name, + show_ip_str(arp_msg->ipv4_addr), + arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4], + arp_msg->mac_addr[5]); + + /* Find MLACP itf, member of port-channel*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if (!local_if_is_l3_mode(lif_po)) + { + /* Is the L2 MLAG itf belong to a vlan?*/ + LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) + { + if ( !(vlan_id_list->vlan_itf + && vlan_id_list->vlan_itf->ifindex == ifindex)) + continue; + break; + } + + if (!vlan_id_list) + continue; + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from mclag enabled port %s of vlan %s", + lif_po->name, vlan_id_list->vlan_itf->name); + } + else + { + /* Is the ARP belong to a L3 mode MLAG itf?*/ + if (ifindex != lif_po->ifindex) + continue; + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from mclag enabled intf %s", lif_po->name); + } + + verify_arp = 1; + + break; + } + + if (lif_po) + break; + } + + if (!(csm && lif_po)) + return; + if (!verify_arp) + return; + + if (iccp_check_if_addr_from_netlink(AF_INET, (uint8_t *)&addr, arp_lif)) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP %s is identical with the ip address of interface %s", + show_ip_str(arp_msg->ipv4_addr), arp_lif->name); + return; + } + + /* update lif ARP*/ + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_info = (struct ARPMsg*)msg->buf; + if (arp_info->ipv4_addr != arp_msg->ipv4_addr) + continue; + + /* update ARP*/ + if (arp_info->op_type != arp_msg->op_type + || strcmp(arp_info->ifname, arp_msg->ifname) != 0 + || memcmp(arp_info->mac_addr, arp_msg->mac_addr, + ETHER_ADDR_LEN) != 0) + { + arp_info->op_type = arp_msg->op_type; + sprintf(arp_info->ifname, "%s", arp_msg->ifname); + memcpy(arp_info->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); + ICCPD_LOG_NOTICE(__FUNCTION__, "Update ARP for %s by ARP reply, intf %s mac [%02X:%02X:%02X:%02X:%02X:%02X]", + show_ip_str(arp_msg->ipv4_addr), arp_msg->ifname, + arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); + } + break; + } + + /* enquene lif_msg (add)*/ + if (!msg) + { + arp_msg->op_type = NEIGH_SYNC_LIF; + if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len) == 0) + { + mlacp_enqueue_arp(csm, msg); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", + arp_msg->ifname, show_ip_str(arp_msg->ipv4_addr));*/ + } + else + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", + arp_msg->ifname, show_ip_str(arp_msg->ipv4_addr)); + } + + /* enqueue iccp_msg (add)*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + arp_msg->op_type = NEIGH_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr));*/ + } + else + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[ADD] message for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + + return; +} + +void do_ndisc_update_from_reply_packet(unsigned int ifindex, char *ipv6_addr, uint8_t mac_addr[ETHER_ADDR_LEN]) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct NDISCMsg *ndisc_msg = NULL, *ndisc_info = NULL; + struct VLAN_ID *vlan_id_list = NULL; + struct Msg *msg_send = NULL; + char mac_str[18] = ""; + uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + + struct LocalInterface *lif_po = NULL, *ndisc_lif = NULL; + + int verify_ndisc = 0; + + if (!(sys = system_get_instance())) + return; + + /* Find local itf */ + if (!(ndisc_lif = local_if_find_by_ifindex(ifindex))) + return; + + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + + /* create Ndisc msg */ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct NDISCMsg); + ndisc_msg = (struct NDISCMsg *)&buf; + ndisc_msg->op_type = NEIGH_SYNC_LIF; + sprintf(ndisc_msg->ifname, "%s", ndisc_lif->name); + memcpy((char *)ndisc_msg->ipv6_addr, ipv6_addr, 16); + memcpy(ndisc_msg->mac_addr, mac_addr, ETHER_ADDR_LEN); + + ICCPD_LOG_DEBUG(__FUNCTION__, "nd ifindex [%d] (%s) ip %s mac %s", + ifindex, ndisc_lif->name, show_ipv6_str(ipv6_addr), mac_str); + + /* Find MLACP itf, member of port-channel */ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if (!local_if_is_l3_mode(lif_po)) + { + /* Is the L2 MLAG itf belong to a vlan? */ + LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) + { + if (!(vlan_id_list->vlan_itf && vlan_id_list->vlan_itf->ifindex == ifindex)) + continue; + break; + } + + if (!vlan_id_list) + continue; + ICCPD_LOG_DEBUG(__FUNCTION__, "ND is from mclag enabled port %s of vlan %s", lif_po->name, vlan_id_list->vlan_itf->name); + } + else + { + /* Is the ND belong to a L3 mode MLAG itf? */ + if (ifindex != lif_po->ifindex) + continue; + ICCPD_LOG_DEBUG(__FUNCTION__, "ND is from mclag enabled port %s", lif_po->name); + } + + verify_ndisc = 1; + + break; + } + + if (lif_po) + break; + } + + if (!(csm && lif_po)) + return; + if (!verify_ndisc) + return; + + if (iccp_check_if_addr_from_netlink(AF_INET6, (uint8_t *)ndisc_msg->ipv6_addr, ndisc_lif)) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "NA %s is identical with the ipv6 address of interface %s", + show_ipv6_str((char *)ndisc_msg->ipv6_addr), ndisc_lif->name); + return; + } + + /* update lif ND */ + TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail) + { + ndisc_info = (struct NDISCMsg *)msg->buf; + + if (memcmp((char *)ndisc_info->ipv6_addr, (char *)ndisc_msg->ipv6_addr, 16) != 0) + continue; + + /* If MAC addr is NULL, use the old one */ + if (memcmp(mac_addr, null_mac, ETHER_ADDR_LEN) == 0) + { + memcpy(ndisc_msg->mac_addr, ndisc_info->mac_addr, ETHER_ADDR_LEN); + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", ndisc_info->mac_addr[0], ndisc_info->mac_addr[1], + ndisc_info->mac_addr[2], ndisc_info->mac_addr[3], ndisc_info->mac_addr[4], ndisc_info->mac_addr[5]); + } + + /* update ND */ + if (ndisc_info->op_type != ndisc_msg->op_type + || strcmp(ndisc_info->ifname, ndisc_msg->ifname) != 0 + || memcmp(ndisc_info->mac_addr, ndisc_msg->mac_addr, ETHER_ADDR_LEN) != 0) + { + ndisc_info->op_type = ndisc_msg->op_type; + sprintf(ndisc_info->ifname, "%s", ndisc_msg->ifname); + memcpy(ndisc_info->mac_addr, ndisc_msg->mac_addr, ETHER_ADDR_LEN); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update ND for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); + } + break; + } + + /* enquene lif_msg (add) */ + if (!msg) + { + /* If MAC addr is NULL, and same ipv6 item is not exist in ndisc_list */ + if (memcmp(mac_addr, null_mac, ETHER_ADDR_LEN) == 0) + { + return; + } + + ndisc_msg->op_type = NEIGH_SYNC_LIF; + if (iccp_csm_init_msg(&msg, (char *)ndisc_msg, msg_len) == 0) + { + mlacp_enqueue_ndisc(csm, msg); + /* ICCPD_LOG_DEBUG(__FUNCTION__, "NDISC-list enqueue: %s, add %s", ndisc_msg->ifname, show_ipv6_str((char *)ndisc_msg->ipv6_addr)); */ + } + else + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue NDISC-list: %s, add %s", ndisc_msg->ifname, show_ipv6_str((char *)ndisc_msg->ipv6_addr)); + } + + if (iccp_netlink_neighbor_request(AF_INET6, (uint8_t *)ndisc_msg->ipv6_addr, 1, ndisc_msg->mac_addr, ndisc_msg->ifname) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to add ND entry(%s, %s, %s) to kernel", + ndisc_msg->ifname, show_ipv6_str((char *)ndisc_msg->ipv6_addr), mac_str); + return; + } + + /* enqueue iccp_msg (add) */ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + ndisc_msg->op_type = NEIGH_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char *)ndisc_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_msg_list), msg_send, tail); + /* ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ND[ADD] for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); */ + } + else + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ND[ADD] message for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); + } + + return; +} +void iccp_from_netlink_port_state_handler( char * ifname, int state) +{ + struct CSM *csm = NULL; + struct LocalInterface *lif_po = NULL; + struct System *sys; + int po_is_active = 0; + + if ((sys = system_get_instance()) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); + return; + } + + po_is_active = (state == PORT_STATE_UP); + + /* traverse all CSM */ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + /*If peer-link changes to down or up */ + if (strcmp(ifname, csm->peer_itf_name) == 0) + { + if (po_is_active == 0) + mlacp_peerlink_down_handler(csm); + else + mlacp_peerlink_up_handler(csm); + + break; + } + + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type == IF_T_PORT_CHANNEL && strncmp(lif_po->name, ifname, MAX_L_PORT_NAME) == 0) + { + mlacp_portchannel_state_handler(csm, lif_po, po_is_active); + } + } + } + + return; +} + +void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n) +{ + struct LocalInterface *lif = NULL; + int msglen = 0; + + msglen = n->nlmsg_len; + + while (NLMSG_OK(n, msglen)) + { + struct ifinfomsg *ifm = NLMSG_DATA(n); + int len = n->nlmsg_len; + struct rtattr *tb[IFLA_MAX + 1] = {0}; + + if (n->nlmsg_type != RTM_NEWLINK) + { + return; + } + + len -= NLMSG_LENGTH(sizeof(*ifm)); + if (len < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "BUG: wrong nlmsg len %d\n", len); + return; + } + + if (ifm->ifi_family != AF_BRIDGE) + { + return; + } + + if ((lif = local_if_find_by_ifindex(ifm->ifi_index)) != NULL) + { + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifm), len); + + /* if AF_SPEC isn't there, vlan table is not preset for this port */ + if (!tb[IFLA_AF_SPEC]) + { + ICCPD_LOG_WARN(__FUNCTION__, "Vlan table is not preset for %d", ifm->ifi_index); + return; + } + else + { + struct rtattr *i, *list = tb[IFLA_AF_SPEC]; + int rem = RTA_PAYLOAD(list); + struct VLAN_ID *vlan = NULL; + + /*set vlan flag is removed*/ + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + vlan->vlan_removed = 1; + } + + for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) + { + struct bridge_vlan_info *vinfo; + + if (i->rta_type != IFLA_BRIDGE_VLAN_INFO) + continue; + + vinfo = RTA_DATA(i); + + local_if_add_vlan(lif, vinfo->vid); + } + + /*After update vlan list, remove unused item*/ + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if (vlan->vlan_removed == 1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", lif->name, vlan->vid); + + LIST_REMOVE(vlan, port_next); + free(vlan); + } + } + } + } + + n = NLMSG_NEXT(n, msglen); + } +} diff --git a/src/iccpd/src/iccp_main.c b/src/iccpd/src/iccp_main.c new file mode 100644 index 000000000000..86920f07e1fb --- /dev/null +++ b/src/iccpd/src/iccp_main.c @@ -0,0 +1,272 @@ +/* + * iccp_main.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include +#include +#include +#include +#include +#include + +#include "../include/cmd_option.h" +#include "../include/logger.h" +#include "../include/scheduler.h" +#include "../include/system.h" + +int check_instance(char* pid_file_path) +{ + int pid_file = 0; + int rc = 0; + + if (pid_file_path == NULL) + return MCLAG_ERROR; + + pid_file = open(pid_file_path, O_CREAT | O_RDWR, 0666); + if (pid_file <= 0 ) + { + fprintf(stderr, "Can't open a pid file. Terminate.\n"); + close(pid_file); + exit(EXIT_FAILURE); + } + + rc = flock(pid_file, LOCK_EX | LOCK_NB); + + if (rc) + { + if (errno == EWOULDBLOCK) + { + fprintf(stderr, "There is another instance running. Terminate.\n"); + close(pid_file); + exit(EXIT_FAILURE); + } + } + + return pid_file; +} + +void init_daemon(char* pid_file_path, int pid_file) +{ + pid_t pid, sid; + + pid = fork(); + if (pid < 0) + { + fprintf(stderr, "Failed to enter daemon mode: %s\n", strerror(errno)); + fprintf(stderr, "Please try to check your system resources.\n"); + close(pid_file); + unlink(pid_file_path); + exit(EXIT_FAILURE); + } + + if (pid > 0) + exit(EXIT_SUCCESS); + + umask(0); + sid = setsid(); + if (sid < 0) + { + fprintf(stderr, "Failed to create a new SID for this program: %s\n", strerror(errno)); + fprintf(stderr, "Please try to check your system resources.\n"); + close(pid_file); + unlink(pid_file_path); + exit(EXIT_FAILURE); + } + + freopen("/dev/null", "r", stdin); + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); +} + +#ifndef ICCPD_RUN_DIR +#define ICCPD_RUN_DIR "/var/run/iccpd/" +#endif + +static inline int iccpd_make_rundir(void) +{ + int ret; + + ret = mkdir(ICCPD_RUN_DIR, 0755); + if (ret && errno != EEXIST) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to create directory \"%s\"", + ICCPD_RUN_DIR); + + return -errno; + } + + return 0; +} + +void iccpd_signal_handler(int sig) +{ + int err; + struct System* sys = NULL; + const char warmboot_flag = 'w'; + + sys = system_get_instance(); + if (!sys) + { + return; + } + + retry: + err = write(sys->sig_pipe_w, &warmboot_flag, 1); + if (err == -1 && errno == EINTR) + goto retry; + + return; +} + +static int iccpd_signal_init(struct System* sys) +{ + int fds[2]; + int err; + sigset_t ss; + struct sigaction sa; + struct epoll_event event; + + err = pipe(fds); + if (err) + return -errno; + + sys->sig_pipe_r = fds[0]; + sys->sig_pipe_w = fds[1]; + + if (sigemptyset(&ss) < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "sigemptyset(): %d", errno); + goto close_pipe; + } + + if (sigaddset(&ss, SIGUSR1) < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "sigaddset(): %d", errno); + goto close_pipe; + } + + if (sigprocmask(SIG_UNBLOCK, &ss, NULL) < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "sigprocmask(): %d", errno); + goto close_pipe; + } + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = iccpd_signal_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + if (sigaction(SIGUSR1, &sa, NULL) < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "sigaction(): %d", errno); + goto close_pipe; + } + + event.data.fd = fds[0]; + event.events = EPOLLIN; + err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, fds[0], &event); + if (err) + { + goto close_pipe; + } + + FD_SET( fds[0], &(sys->readfd)); + sys->readfd_count++; + + return 0; + + close_pipe: + close(sys->sig_pipe_r); + close(sys->sig_pipe_w); + return err; +} + +int main(int argc, char* argv[]) +{ + int pid_file_fd = 0; + struct System* sys = NULL; + int err; + struct CmdOptionParser parser = CMD_OPTION_PARSER_INIT_VALUE; + + err = iccpd_make_rundir(); + if (err) + return 0; + + if (getuid() != 0) + { + fprintf(stderr, + "This program needs root permission to do device manipulation. " + "Please use sudo to execute it or change your user to root.\n"); + exit(EXIT_FAILURE); + } + + parser.init(&parser); + if (parser.parse(&parser, argc, argv) != 0) + { + parser.finalize(&parser); + return MCLAG_ERROR; + } + + pid_file_fd = check_instance(parser.pid_file_path); + if (pid_file_fd < 0) + { + fprintf(stderr, "Check instance with invalidate arguments, iccpd is terminated.\n"); + parser.finalize(&parser); + exit(EXIT_FAILURE); + } + + sys = system_get_instance(); + if (!sys) + { + fprintf(stderr, "Can't get a system instance, iccpd is terminated.\n"); + parser.finalize(&parser); + exit(EXIT_FAILURE); + } + + /*if(!parser.console_log) + init_daemon(parser.pid_file_path, pid_file_fd);*/ + + log_init(&parser); + + if (sys->log_file_path != NULL) + free(sys->log_file_path); + if (sys->cmd_file_path != NULL) + free(sys->cmd_file_path); + if (sys->config_file_path != NULL) + free(sys->config_file_path); + sys->log_file_path = strdup(parser.log_file_path); + sys->cmd_file_path = strdup(parser.cmd_file_path); + sys->config_file_path = strdup(parser.config_file_path); + sys->mclagdctl_file_path = strdup(parser.mclagdctl_file_path); + sys->pid_file_fd = pid_file_fd; + sys->telnet_port = parser.telnet_port; + parser.finalize(&parser); + iccpd_signal_init(sys); + ICCPD_LOG_INFO(__FUNCTION__, "Iccpd is started, process id = %d. uid %d ", getpid(), getuid()); + scheduler_init(); + scheduler_start(); + system_finalize(); + /*scheduler_finalize(); + log_finalize();*/ + + return EXIT_SUCCESS; +} diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c new file mode 100644 index 000000000000..002c254ae9c1 --- /dev/null +++ b/src/iccpd/src/iccp_netlink.c @@ -0,0 +1,1847 @@ +/* + * iccp_netlink.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../include/system.h" +#include "../include/iccp_ifm.h" +#include "../include/port.h" +#include "../include/iccp_csm.h" +#include "../include/logger.h" +#include "../include/scheduler.h" +#include "../include/mlacp_link_handler.h" +#include "../include/msg_format.h" +#include "../include/iccp_netlink.h" + +/** + * SECTION: Netlink helpers + */ +/* \cond HIDDEN_SYMBOLS */ +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +#define ARRAY_SIZE(array_name) (sizeof(array_name) / sizeof(array_name[0])) + +#ifndef NETLINK_BROADCAST_SEND_ERROR +#define NETLINK_BROADCAST_SEND_ERROR 0x4 +#endif + +static int iccp_ack_handler(struct nl_msg *msg, void *arg) +{ + bool *acked = arg; + + *acked = true; + + return NL_STOP; +} + +static int iccp_seq_check_handler(struct nl_msg *msg, void *arg) +{ + unsigned int *seq = arg; + struct nlmsghdr *hdr = nlmsg_hdr(msg); + + if (hdr->nlmsg_seq != *seq) + return NL_SKIP; + + return NL_OK; +} + +int iccp_send_and_recv(struct System *sys, struct nl_msg *msg, + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) +{ + int ret; + struct nl_cb *cb; + struct nl_cb *orig_cb; + bool acked; + unsigned int seq = sys->genric_sock_seq++; + int err; + + ret = nl_send_auto(sys->genric_sock, msg); + nlmsg_free(msg); + if (ret < 0) + return ret; + + orig_cb = nl_socket_get_cb(sys->genric_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + return -ENOMEM; + + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, iccp_ack_handler, &acked); + nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, iccp_seq_check_handler, &seq); + if (valid_handler) + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); + + /* There is a bug in libnl. When implicit sequence number checking is in + * use the expected next number is increased when NLMSG_DONE is + * received. The ACK which comes after that correctly includes the + * original sequence number. However libnl is checking that number + * against the incremented one and therefore ack handler is never called + * and nl_recvmsgs finished with an error. To resolve this, custom + * sequence number checking is used here. + */ + + acked = false; + + while (!acked) + { + ret = nl_recvmsgs(sys->genric_sock, cb); + if (ret) + { + err = ret; + goto put_cb; + } + } + + err = 0; + put_cb: + nl_cb_put(cb); + return err; +} + +int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct nlattr *attrs[TEAM_ATTR_MAX + 1]; + struct nlattr *nl_port; + struct nlattr *port_attrs[TEAM_ATTR_PORT_MAX + 1]; + struct LocalInterface* lif = NULL; + struct LocalInterface* local_if_member = NULL; + struct CSM* csm; + int i; + uint32_t ifindex = 0; + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + char temp_buf[512]; + int len = 0; + + sys = system_get_instance(); + if (sys == NULL) + return 0; + + genlmsg_parse(nlh, 0, attrs, TEAM_ATTR_MAX, NULL); + + if (attrs[TEAM_ATTR_TEAM_IFINDEX]) + ifindex = nla_get_u32(attrs[TEAM_ATTR_TEAM_IFINDEX]); + + local_if = local_if_find_by_ifindex(ifindex); + + if (!local_if) + return NL_SKIP; + + if (local_if->type != IF_T_PORT_CHANNEL) + return NL_SKIP; + + csm = local_if->csm; + + if (csm) + { + if (!attrs[TEAM_ATTR_LIST_PORT]) + return NL_SKIP; + + nla_for_each_nested(nl_port, attrs[TEAM_ATTR_LIST_PORT], i) + { + uint32_t member_index; + + if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX, nl_port, NULL)) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to parse nested attributes."); + return NL_SKIP; + } + + if (!port_attrs[TEAM_ATTR_PORT_IFINDEX]) + { + ICCPD_LOG_ERR(__FUNCTION__, "ifindex port attribute not found."); + return NL_SKIP; + } + + member_index = nla_get_u32(port_attrs[TEAM_ATTR_PORT_IFINDEX]); + + local_if_member = local_if_find_by_ifindex(member_index); + if (local_if_member == NULL) + { + + ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance (%d).", + local_if->name, member_index); + continue; + } + + if (port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) + { + local_if_member->po_id = -1; + mlacp_unbind_local_if(local_if_member); + } + else if ( local_if_member->po_id == -1) + { + local_if_member->po_id = local_if->po_id; + mlacp_bind_local_if(local_if->csm, local_if_member); + } + } + + memset(temp_buf, 0, 512); + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type == IF_T_PORT && lif->po_id == local_if->po_id) + { + if (strlen(temp_buf) != 0) + len += snprintf(temp_buf + len, 512 - len, "%s", ","); + + len += snprintf(temp_buf + len, 512 - len, "%s", lif->name); + } + } + + if (strcmp(temp_buf, local_if->portchannel_member_buf)) + { + memset(local_if->portchannel_member_buf, 0, 512); + memcpy(local_if->portchannel_member_buf, temp_buf, sizeof(local_if->portchannel_member_buf) - 1); + + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /* portchannel member changed, update port isolate attribute*/ + update_peerlink_isolate_from_all_csm_lif(csm); + } + } + } + else /*peerlink portchannel */ + { + if (local_if->is_peer_link) + { + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (csm->peer_link_if == local_if ) + { + break; + } + } + + if (csm == NULL) + return 0; + + nla_for_each_nested(nl_port, attrs[TEAM_ATTR_LIST_PORT], i) + { + uint32_t member_index; + + if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX, nl_port, NULL)) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to parse nested attributes."); + return NL_SKIP; + } + + if (!port_attrs[TEAM_ATTR_PORT_IFINDEX]) + { + ICCPD_LOG_WARN(__FUNCTION__, "ifindex port attribute not found."); + return NL_SKIP; + } + + member_index = nla_get_u32(port_attrs[TEAM_ATTR_PORT_IFINDEX]); + + local_if_member = local_if_find_by_ifindex(member_index); + if (local_if_member == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance (%d).", + local_if->name, member_index); + continue; + } + + if (port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) + { + local_if_member->po_id = -1; + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*link removed from portchannel, must be enabled mac learn*/ + set_peerlink_mlag_port_learn(local_if_member, 1); + } + + continue; + } + else if ( local_if_member->po_id == -1) + { + local_if_member->po_id = local_if->po_id; + + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*link add to portchannel, must be disabled mac learn*/ + set_peerlink_mlag_port_learn(local_if, 0); + } + } + } + + memset(temp_buf, 0, 512); + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + if (lif->type == IF_T_PORT && lif->po_id == local_if->po_id) + { + if (strlen(temp_buf) != 0) + len += snprintf(temp_buf + len, 512 - len, "%s", ","); + + len += snprintf(temp_buf + len, 512 - len, "%s", lif->name); + } + } + + if (strcmp(temp_buf, local_if->portchannel_member_buf)) + { + memset(local_if->portchannel_member_buf, 0, 512); + memcpy(local_if->portchannel_member_buf, temp_buf, sizeof(local_if->portchannel_member_buf) - 1); + } + } + } + + return 0; +} + +int iccp_genric_socket_team_family_get() +{ + struct System* sys = NULL; + int err = 0; + int grp_id = 0; + + if ((sys = system_get_instance()) == NULL ) + return MCLAG_ERROR; + if (sys->family < 0) + { + sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); + + while (sys->family < 0) + { + sleep(1); + + /*If no portchannel configuration, teamd will not started, genl_ctrl_resolve() will return <0 forever */ + /*Only log error message 5 times*/ + + ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink family. %d of TEAM_GENL_NAME %s ", sys->family, TEAM_GENL_NAME); + sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); + + } + + grp_id = genl_ctrl_resolve_grp(sys->genric_sock, TEAM_GENL_NAME, + TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME); + if (grp_id < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink multicast groups. %d", grp_id); + } + + err = nl_socket_add_membership(sys->genric_event_sock, grp_id); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + + } + } + + return err; +} + +int iccp_get_port_member_list(struct LocalInterface* lif) +{ + struct System *sys; + struct nl_msg *msg; + int err; + + sys = system_get_instance(); + if (sys == NULL) + return 0; + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + err = iccp_genric_socket_team_family_get(); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "genric socket family get err err = %d . errno = %d", err, errno); + return err; + } + + genlmsg_put(msg, NL_AUTO_PID, sys->genric_sock_seq, sys->family, 0, 0, + TEAM_CMD_PORT_LIST_GET, 0); + nla_put_u32(msg, TEAM_ATTR_TEAM_IFINDEX, lif->ifindex); + + err = iccp_send_and_recv(sys, msg, iccp_get_portchannel_member_list_handler, lif); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "recv msg err err = %d . errno = %d", err, errno); + return err; + } + + return 0; +} + +int iccp_netlink_if_hwaddr_set(uint32_t ifindex, uint8_t *addr, unsigned int addr_len) +{ + struct rtnl_link *link; + int err; + struct nl_addr *nl_addr; + struct System* sys = NULL; + + if (!(sys = system_get_instance())) + return MCLAG_ERROR; + + link = rtnl_link_alloc(); + if (!link) + return -ENOMEM; + + nl_addr = nl_addr_build(AF_UNSPEC, (void *)addr, addr_len); + if (!nl_addr) + { + err = -ENOMEM; + goto errout; + } + + rtnl_link_set_ifindex(link, ifindex); + rtnl_link_set_addr(link, nl_addr); + + err = rtnl_link_change(sys->route_sock, link, link, 0); + + nl_addr_put(nl_addr); + + errout: + rtnl_link_put(link); + return err; +} + +#define SET_MAC_STR(buf, macArray) \ + snprintf(buf, 64, "%02x:%02x:%02x:%02x:%02x:%02x", \ + macArray[0], macArray[1], macArray[2], \ + macArray[3], macArray[4], macArray[5]); + +void iccp_set_interface_ipadd_mac(struct LocalInterface *lif, char * mac_addr ) +{ + struct IccpSyncdHDr * msg_hdr; + mclag_sub_option_hdr_t * sub_msg; + char msg_buf[4096]; + struct System *sys; + + int src_len = 0, dst_len = 0; + + sys = system_get_instance(); + if (sys == NULL) + return; + + memset(msg_buf, 0, 4095); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver = 1; + msg_hdr->type = MCLAG_MSG_TYPE_SET_MAC; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + /*sub msg src*/ + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC; + + /*src_len = snprintf((char *)sub_msg->data, 512, "%s:%s/%d", lif->name,show_ip_str(htonl(lif->ipv4_addr)),lif->prefixlen);*/ + src_len = snprintf((char *)sub_msg->data, 512, "%s", lif->name); + + sub_msg->op_len = src_len; + + /*sub msg dst */ + msg_hdr->len += sub_msg->op_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_SET_MAC_DST; + + dst_len = strlen(mac_addr); + memcpy(sub_msg->data, mac_addr, dst_len); + + ICCPD_LOG_NOTICE(__FUNCTION__, "If name %s ip %s mac %s", lif->name, show_ip_str(htonl(lif->ipv4_addr)), sub_msg->data); + + sub_msg->op_len = dst_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; + + /*send msg*/ + if (sys->sync_fd) + write(sys->sync_fd, msg_buf, msg_hdr->len); + + return; +} + +int iccp_netlink_if_startup_set(uint32_t ifindex) +{ + struct rtnl_link *link; + int err; + struct System *sys = NULL; + + if (!(sys = system_get_instance())) + return MCLAG_ERROR; + + link = rtnl_link_alloc(); + if (!link) + return -ENOMEM; + + rtnl_link_set_ifindex(link, ifindex); + rtnl_link_set_flags(link, IFF_UP); + + err = rtnl_link_change(sys->route_sock, link, link, 0); + +errout: + rtnl_link_put(link); + return err; +} + +int iccp_netlink_if_shutdown_set(uint32_t ifindex) +{ + struct rtnl_link *link; + int err; + struct System *sys = NULL; + + if (!(sys = system_get_instance())) + return MCLAG_ERROR; + + link = rtnl_link_alloc(); + if (!link) + return -ENOMEM; + + rtnl_link_set_ifindex(link, ifindex); + rtnl_link_unset_flags(link, IFF_UP); + + err = rtnl_link_change(sys->route_sock, link, link, 0); + +errout: + rtnl_link_put(link); + return err; +} +void update_if_ipmac_on_standby(struct LocalInterface* lif_po) +{ + struct CSM* csm; + uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + struct VLAN_ID *vlan = NULL; + + csm = lif_po->csm; + struct LocalInterface* lif_Bri; + char macaddr[64]; + int ret = 0; + + if (!csm) + return; + + if (lif_po->type != IF_T_PORT_CHANNEL) + return; + + if (csm->role_type != STP_ROLE_STANDBY) + { + return; + } + + if (memcmp(MLACP(csm).remote_system.system_id, null_mac, ETHER_ADDR_LEN) == 0) + return; + + /*Set new mac*/ + if (memcmp( lif_po->mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN) != 0) + { + /*Backup old sysmac*/ + memcpy(lif_po->mac_addr_ori, lif_po->mac_addr, ETHER_ADDR_LEN); + + ICCPD_LOG_NOTICE(__FUNCTION__, + "%s Change the system-id of %s from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", + (csm->role_type == STP_ROLE_STANDBY) ? "Standby" : "Active", + lif_po->name, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], + MLACP(csm).remote_system.system_id[0], MLACP(csm).remote_system.system_id[1], MLACP(csm).remote_system.system_id[2], MLACP(csm).remote_system.system_id[3], MLACP(csm).remote_system.system_id[4], MLACP(csm).remote_system.system_id[5]); + + ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", lif_po->name, ret); + } + + /* Refresh link local address according the new MAC */ + iccp_netlink_if_shutdown_set(lif_po->ifindex); + iccp_netlink_if_startup_set(lif_po->ifindex); + } + + /*Set portchannel ip mac */ + memset(macaddr, 0, 64); + SET_MAC_STR(macaddr, MLACP(csm).remote_system.system_id); + if (local_if_is_l3_mode(lif_po)) + { + if (memcmp(lif_po->l3_mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN) != 0) + { + iccp_set_interface_ipadd_mac(lif_po, macaddr ); + memcpy(lif_po->l3_mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); + } + } + else + { + LIST_FOREACH(vlan, &(lif_po->vlan_list), port_next) + { + if (!vlan->vlan_itf) + continue; + + /*If the po is under a vlan, update vlan mac*/ + if (local_if_is_l3_mode(vlan->vlan_itf)) + { + if (memcmp(vlan->vlan_itf->l3_mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN) != 0) + { + ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", vlan->vlan_itf->name, ret); + } + + /* Refresh link local address according the new MAC */ + iccp_netlink_if_shutdown_set(vlan->vlan_itf->ifindex); + iccp_netlink_if_startup_set(vlan->vlan_itf->ifindex); + + iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr); + memcpy(vlan->vlan_itf->l3_mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); + } + } + } + } + + return; +} + +void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) +{ + struct CSM* csm; + uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + struct VLAN_ID *vlan = NULL; + + csm = lif_po->csm; + char macaddr[64]; + int ret = 0; + + if (!csm) + return; + + if (lif_po->type != IF_T_PORT_CHANNEL) + return; + + if (csm->role_type != STP_ROLE_STANDBY) + { + return; + } + + /*Recover mac to origin mac, it is the 'mac' value in 'localhost' currently*/ + if (memcmp( lif_po->mac_addr, MLACP(csm).system_id, ETHER_ADDR_LEN) != 0) + { + ICCPD_LOG_NOTICE(__FUNCTION__, + "%s Recover the system-id of %s from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", + (csm->role_type == STP_ROLE_STANDBY) ? "Standby" : "Active", + lif_po->name, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], + MLACP(csm).system_id[0], MLACP(csm).system_id[1], MLACP(csm).system_id[2], MLACP(csm).system_id[3], MLACP(csm).system_id[4], MLACP(csm).system_id[5]); + + ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, MLACP(csm).system_id, ETHER_ADDR_LEN); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", lif_po->name, ret); + } + + /* Refresh link local address according the new MAC */ + iccp_netlink_if_shutdown_set(lif_po->ifindex); + iccp_netlink_if_startup_set(lif_po->ifindex); + } + + /*Set portchannel ip mac */ + memset(macaddr, 0, 64); + SET_MAC_STR(macaddr, MLACP(csm).system_id); + if (local_if_is_l3_mode(lif_po)) + { + iccp_set_interface_ipadd_mac(lif_po, macaddr ); + memcpy(lif_po->l3_mac_addr, MLACP(csm).system_id, ETHER_ADDR_LEN); + } + else + { + LIST_FOREACH(vlan, &(lif_po->vlan_list), port_next) + { + if (!vlan->vlan_itf) + continue; + + /*If the po is under a vlan, update vlan mac*/ + if (local_if_is_l3_mode(vlan->vlan_itf)) + { + ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, MLACP(csm).system_id, ETHER_ADDR_LEN); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", vlan->vlan_itf->name, ret); + } + + /* Refresh link local address according the new MAC */ + iccp_netlink_if_shutdown_set(vlan->vlan_itf->ifindex); + iccp_netlink_if_startup_set(vlan->vlan_itf->ifindex); + + iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr); + memcpy(vlan->vlan_itf->l3_mac_addr, MLACP(csm).system_id, ETHER_ADDR_LEN); + } + } + } + + return; +} + +int iccp_netlink_neighbor_request(int family, uint8_t *addr, int add, uint8_t *mac, char *portname) +{ + struct System *sys = NULL; + struct rtnl_neigh *neigh = NULL; + struct nl_addr *nl_addr_mac = NULL; + struct nl_addr *nl_addr_dst = NULL; + struct LocalInterface *lif = NULL; + struct nl_cache *link_cache; + char mac_str[18] = ""; + int err = 0; + + if (!(sys = system_get_instance())) + return MCLAG_ERROR; + + lif = local_if_find_by_name(portname); + if (!lif) + return MCLAG_ERROR; + + neigh = rtnl_neigh_alloc(); + if (!neigh) + { + ICCPD_LOG_INFO(__FUNCTION__, "Unable to allocate neighbour object"); + return MCLAG_ERROR; + } + + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + ICCPD_LOG_NOTICE(__FUNCTION__, "Notify kernel %s %s entry(ip:%s, mac:%s, intf:%s)", + add ? "add" : "del", (family == AF_INET) ? "ARP" : "ND", + (family == AF_INET) ? show_ip_str(*((int *)addr)) : show_ipv6_str(addr), mac_str, portname); + + nl_addr_mac = nl_addr_build(AF_LLC, (void *)mac, ETHER_ADDR_LEN); + if (!nl_addr_mac) + { + err = MCLAG_ERROR; + goto errout; + } + + if (family == AF_INET) + nl_addr_dst = nl_addr_build(family, (void *)addr, 4); + else + nl_addr_dst = nl_addr_build(family, (void *)addr, 16); + + if (!nl_addr_dst) + { + err = MCLAG_ERROR; + goto errout; + } + + rtnl_neigh_set_lladdr(neigh, nl_addr_mac); + rtnl_neigh_set_dst(neigh, nl_addr_dst); + rtnl_neigh_set_ifindex(neigh, lif->ifindex); + rtnl_neigh_set_state(neigh, NUD_REACHABLE); + + if (add) + { + if ((err = rtnl_neigh_add(sys->route_sock, neigh, NLM_F_REPLACE | NLM_F_CREATE)) < 0) + ICCPD_LOG_WARN(__FUNCTION__, "Add %s (ip:%s, mac:%s) error, err = %d", (family == AF_INET) ? "ARP" : "ND", + (family == AF_INET) ? show_ip_str(*((int *)addr)) : show_ipv6_str(addr), mac_str, err); + } + else + { + if ((err = rtnl_neigh_delete(sys->route_sock, neigh, 0)) < 0) + ICCPD_LOG_WARN(__FUNCTION__, "Del %s (ip:%s, mac:%s) error, err = %d", (family == AF_INET) ? "ARP" : "ND", + (family == AF_INET) ? show_ip_str(*((int *)addr)) : show_ipv6_str(addr), mac_str, err); + } + +errout: + nl_addr_put(nl_addr_mac); + nl_addr_put(nl_addr_dst); + rtnl_neigh_put(neigh); + return err; +} + +void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link; + unsigned int *event = arg; + uint32_t ifindex; + char * ifname, *p; + struct LocalInterface *lif = NULL; + struct nl_addr *nl_addr; + int addr_type = 0; + int op_state = 0; + int link_flag = 0; + + link = (struct rtnl_link *)obj; + ifindex = rtnl_link_get_ifindex(link); + op_state = rtnl_link_get_operstate(link); + ifname = rtnl_link_get_name(link); + nl_addr = rtnl_link_get_addr(link); + link_flag = rtnl_link_get_flags(link); + + if (nl_addr) + addr_type = nl_addr_guess_family(nl_addr); + + /*Vxlan tunnel dev name is like VTTNL0001-1000, VTTNL0001 is vxlan tunnel name, 1000 is vni*/ + /*If dev is vxlan tunnel, only create the tunnel with name no vni, like VTTNL0001*/ + if ((strncmp(ifname, VXLAN_TUNNEL_PREFIX, strlen(VXLAN_TUNNEL_PREFIX)) == 0)) + { + /*Change ifname from VTTNL0001-1000 to VTTNL0001*/ + if ((p = strchr(ifname, '-')) != NULL) + { + *p = '\0'; + } + /*Create vxlan tunnel dev, state is always UP*/ + lif = local_if_find_by_name(ifname); + if (!lif) + { + lif = local_if_create(ifindex, ifname, IF_T_VXLAN); + lif->state = PORT_STATE_UP; + } + return; + } + else + lif = local_if_find_by_ifindex(ifindex); + + if (!lif) + { + const itf_type_t if_whitelist[] = { + { PORTCHANNEL_PREFIX, IF_T_PORT_CHANNEL }, + { VLAN_PREFIX, IF_T_VLAN }, + { FRONT_PANEL_PORT_PREFIX, IF_T_PORT }, + { VXLAN_TUNNEL_PREFIX, IF_T_VXLAN }, + { NULL, 0 } + }; + int i = 0; + + for (i = 0; if_whitelist[i].ifname != NULL; ++i) + { + if ((strncmp(ifname, + if_whitelist[i].ifname, strlen(if_whitelist[i].ifname)) == 0)) + { + lif = local_if_create(ifindex, ifname, if_whitelist[i].type); + + lif->state = PORT_STATE_DOWN; + + if (IF_OPER_UP == op_state ) + { + lif->state = PORT_STATE_UP; + } + + switch (addr_type) + { + case AF_LLC: + memcpy( lif->mac_addr, nl_addr_get_binary_addr(nl_addr), ETHER_ADDR_LEN); + default: + break; + } + + break; + } + } + } + else /*update*/ + { + /*update*/ + if (lif->state == PORT_STATE_DOWN && op_state == IF_OPER_UP) + { + lif->state = PORT_STATE_UP; + /*if(lif->type ==IF_T_PORT_CHANNEL)*/ + ICCPD_LOG_NOTICE(__FUNCTION__, "Update local port %s state up", ifname); + + iccp_from_netlink_port_state_handler(lif->name, lif->state); + } + else if (lif->state == PORT_STATE_UP && ( IF_OPER_UP != op_state || !(link_flag & IFF_LOWER_UP))) + { + lif->state = PORT_STATE_DOWN; + /*if(lif->type ==IF_T_PORT_CHANNEL)*/ + ICCPD_LOG_NOTICE(__FUNCTION__, "Update local port %s state down", ifname); + + iccp_from_netlink_port_state_handler(lif->name, lif->state); + } + + switch (addr_type) + { + case AF_LLC: + if (memcmp(nl_addr_get_binary_addr(nl_addr), lif->mac_addr, ETHER_ADDR_LEN) != 0) + { + memcpy( lif->mac_addr, nl_addr_get_binary_addr(nl_addr), ETHER_ADDR_LEN); + lif->port_config_sync = 1; + } + + default: + break; + } + } + + return; +} + +void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link; + struct LocalInterface *lif; + uint32_t ifindex; + + link = (struct rtnl_link *)obj; + + ifindex = rtnl_link_get_ifindex(link); + if ((lif = local_if_find_by_ifindex(ifindex)) != NULL) + local_if_destroy(lif->name); + + return; +} + +void iccp_event_handler_obj_input_newaddr(struct nl_object *obj, void *arg) +{ + struct rtnl_addr *addr; + struct nl_addr *nl_addr; + struct LocalInterface *lif; + uint32_t ifindex; + char addrStr[65] = { 0 }; + char addr_null[16] = { 0 }; + addr = (struct rtnl_addr *)obj; + + ifindex = rtnl_addr_get_ifindex(addr); + nl_addr = rtnl_addr_get_local(addr); + + if (!(lif = local_if_find_by_ifindex(ifindex))) + return; + + if (rtnl_addr_get_family(addr) == AF_INET) + { + lif->ipv4_addr = *(uint32_t *) nl_addr_get_binary_addr(nl_addr); + lif->prefixlen = nl_addr_get_prefixlen(nl_addr); + lif->l3_mode = 1; + lif->port_config_sync = 1; + if (memcmp((char *)lif->ipv6_addr, addr_null, 16) == 0) + update_if_ipmac_on_standby(lif); + ICCPD_LOG_DEBUG(__FUNCTION__, "Ifname %s index %d address %s", lif->name, lif->ifindex, show_ip_str(lif->ipv4_addr)); + } + else if (rtnl_addr_get_family(addr) == AF_INET6) + { + if (memcmp(show_ipv6_str((char *)nl_addr_get_binary_addr(nl_addr)), "FE80", 4) == 0 + || memcmp(show_ipv6_str((char *)nl_addr_get_binary_addr(nl_addr)), "fe80", 4) == 0) + return; + + memcpy((char *)lif->ipv6_addr, nl_addr_get_binary_addr(nl_addr), 16); + lif->prefixlen = nl_addr_get_prefixlen(nl_addr); + lif->l3_mode = 1; + lif->port_config_sync = 1; + if (lif->ipv4_addr == 0) + update_if_ipmac_on_standby(lif); + ICCPD_LOG_DEBUG(__FUNCTION__, "Ifname %s index %d address %s", lif->name, lif->ifindex, show_ipv6_str((char *)lif->ipv6_addr)); + } + + return; +} + +void iccp_event_handler_obj_input_deladdr(struct nl_object *obj, void *arg) +{ + struct rtnl_addr *addr; + struct nl_addr *nl_addr; + struct LocalInterface *lif; + uint32_t ifindex; + char addr_null[16] = { 0 }; + + addr = (struct rtnl_addr *)obj; + + ifindex = rtnl_addr_get_ifindex(addr); + nl_addr = rtnl_addr_get_local(addr); + + if (!(lif = local_if_find_by_ifindex(ifindex))) + return; + + if (rtnl_addr_get_family(addr) == AF_INET) + { + lif->ipv4_addr = 0; + lif->prefixlen = 0; + } + else if (rtnl_addr_get_family(addr) == AF_INET6) + { + if (memcmp(show_ipv6_str((char *)nl_addr_get_binary_addr(nl_addr)), "FE80", 4) == 0 + || memcmp(show_ipv6_str((char *)nl_addr_get_binary_addr(nl_addr)), "fe80", 4) == 0) + return; + + memset((char *)lif->ipv6_addr, 0, 16); + lif->prefixlen_v6 = 0; + } + + if (lif->ipv4_addr == 0 && memcmp((char *)lif->ipv6_addr, addr_null, 16) == 0) + { + lif->l3_mode = 0; + memset(lif->l3_mac_addr, 0, ETHER_ADDR_LEN); + } + + return; +} + +int iccp_addr_valid_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + unsigned int event = 0; + if (nlh->nlmsg_type != RTM_NEWADDR) + return 0; + + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newaddr, &event) < 0) + ICCPD_LOG_ERR(__FUNCTION__, "Unknown message type."); + + return 0; +} + +int iccp_check_if_addr_from_netlink(int family, uint8_t *addr, struct LocalInterface *lif) +{ + struct + { + struct nlmsghdr nlh; + struct ifaddrmsg ifa; + } req; + + struct sockaddr_nl nladdr; + struct iovec iov; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + + int fd; + struct System *sys; + if ((sys = system_get_instance()) == NULL) + { + return 0; + } + + memset(&req, 0, sizeof(req)); + req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + req.nlh.nlmsg_type = RTM_GETADDR; + req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = 0; + req.ifa.ifa_family = family; + + fd = nl_socket_get_fd(sys->route_sock); + send(fd, (void*)&req, sizeof(req), 0); + + char * buf = malloc(10000); + iov.iov_base = buf; + + while (1) + { + int status; + int msglen = 0; + iov.iov_len = 10000; + status = recvmsg(fd, &msg, 0); + + if (status < 0 || status == 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "netlink receive error (%d) status %d %d ", fd, status, errno); + free(buf); + return 0; + } + struct nlmsghdr *n = (struct nlmsghdr*)buf; + msglen = status; + + while (NLMSG_OK(n, msglen)) + { + if (n->nlmsg_type != RTM_NEWADDR) + { + free(buf); + return 0; + } + struct ifaddrmsg *ifa; + ifa = NLMSG_DATA(n); + if (lif && lif->ifindex == ifa->ifa_index) + { + struct rtattr *rth = IFA_RTA(ifa); + int rtl = IFA_PAYLOAD(n); + + while (rtl && RTA_OK(rth, rtl)) + { + if (rth->rta_type == IFA_ADDRESS || rth->rta_type == IFA_LOCAL) + { + if (family == AF_INET && ifa->ifa_family == AF_INET) + { + if (*(uint32_t *)addr == ntohl(*((uint32_t *)RTA_DATA(rth)))) + { + free(buf); + return 1; + } + } + + if (family == AF_INET6 && ifa->ifa_family == AF_INET6) + { + void *addr_netlink; + addr_netlink = RTA_DATA(rth); + if (!memcmp((uint8_t *)addr_netlink, addr, 16)) + { + free(buf); + return 1; + } + } + } + rth = RTA_NEXT(rth, rtl); + } + } + n = NLMSG_NEXT(n, msglen); + } + } + + free(buf); + + return 0; +} + +int iccp_sys_local_if_list_get_addr() +{ + struct System *sys = NULL; + struct nl_cb *cb; + struct nl_cb *orig_cb; + struct rtgenmsg rt_hdr = { + .rtgen_family = AF_UNSPEC, + }; + int ret; + int retry = 1; + + if (!(sys = system_get_instance())) + return MCLAG_ERROR; + + while (retry) + { + retry = 0; + ret = nl_send_simple(sys->route_sock, RTM_GETADDR, NLM_F_DUMP, + &rt_hdr, sizeof(rt_hdr)); + + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); + return ret; + } + + orig_cb = nl_socket_get_cb(sys->route_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + { + ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); + return -ENOMEM; + } + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_addr_valid_handler, sys); + ret = nl_recvmsgs(sys->route_sock, cb); + nl_cb_put(cb); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Receive netlink msg error, ret = %d errno = %d .", ret, errno); + if (ret != -NLE_DUMP_INTR) + return ret; + retry = 1; + } + } + + return ret; +} + +static int iccp_route_event_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + unsigned int event = 1; + + switch (nlh->nlmsg_type) + { + case RTM_NEWLINK: + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type(RTM_NEWLINK)"); + iccp_parse_if_vlan_info_from_netlink(nlh); + break; + + case RTM_DELLINK: + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_dellink, NULL) < 0) + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type(RTM_DELLINK)"); + break; + + case RTM_NEWNEIGH: + case RTM_DELNEIGH: + do_one_neigh_request(nlh); + break; + + case RTM_NEWADDR: + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newaddr, NULL) < 0) + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type(RTM_NEWADDR)."); + break; + case RTM_DELADDR: + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_deladdr, NULL) < 0) + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type(RTM_DELADDR)."); + break; + default: + return NL_OK; + } + + return NL_STOP; +} + +/** + * SECTION: Context functions + */ +static int iccp_genric_event_handler(struct nl_msg *msg, void *arg) +{ + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + + switch (gnlh->cmd) + { + case TEAM_CMD_PORT_LIST_GET: + return iccp_get_portchannel_member_list_handler(msg, NULL); + } + + return NL_SKIP; +} + +int iccp_make_nd_socket(void) +{ + int sock; + int ret; + int val; + struct icmp6_filter filter; + + sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + + if (sock < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to create nd socket"); + return MCLAG_ERROR; + } + + val = 1; +#ifdef IPV6_RECVPKTINFO /* 2292bis-01 */ + if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)) < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set IPV6_RECVPKTINFO for nd socket"); + close(sock); + return MCLAG_ERROR; + } +#else /* RFC2292 */ + if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &val, sizeof(val)) < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set IPV6_PKTINFO for nd socket"); + close(sock); + return MCLAG_ERROR; + } +#endif + + ICMP6_FILTER_SETBLOCKALL(&filter); + ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter); + + ret = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(struct icmp6_filter)); + + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set ICMP6_FILTER"); + close(sock); + return MCLAG_ERROR; + } + + return sock; +} + +/*init netlink socket*/ +int iccp_system_init_netlink_socket() +{ + struct System* sys = NULL; + int val = 0; + int err = 0; + + if ((sys = system_get_instance()) == NULL ) + return MCLAG_ERROR; + + sys->genric_sock = nl_socket_alloc(); + if (!sys->genric_sock) + goto err_genric_sock_alloc; + + sys->genric_sock_seq = time(NULL); + err = genl_connect(sys->genric_sock); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sock sys->genric_sock."); + goto err_genric_sock_connect; + } + + sys->genric_event_sock = nl_socket_alloc(); + if (!sys->genric_event_sock) + goto err_genric_event_sock_alloc; + + err = genl_connect(sys->genric_event_sock); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sys->genric_event_sock."); + goto err_genric_event_sock_connect; + } + + sys->route_sock = nl_socket_alloc(); + if (!sys->route_sock) + goto err_route_sock_alloc; + err = nl_connect(sys->route_sock, NETLINK_ROUTE); + if (err) + goto err_route_sock_connect; + + err = nl_socket_set_buffer_size(sys->route_sock, 98304, 0); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink route event sock."); + goto err_route_sock_connect; + } + + sys->route_event_sock = nl_socket_alloc(); + if (!sys->route_event_sock) + goto err_route_event_sock_alloc; + + err = nl_connect(sys->route_event_sock, NETLINK_ROUTE); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sys->route_event_sock. "); + goto err_route_event_sock_connect; + } + + err = nl_socket_set_buffer_size(sys->route_event_sock, 983040, 0); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink route event sock."); + goto err_route_event_sock_connect; + } + + val = NETLINK_BROADCAST_SEND_ERROR; + err = setsockopt(nl_socket_get_fd(sys->genric_event_sock), SOL_NETLINK, + NETLINK_BROADCAST_ERROR, &val, sizeof(val)); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed set NETLINK_BROADCAST_ERROR on netlink event sock."); + goto err_return; + } + + err = nl_socket_set_buffer_size(sys->genric_sock, 98304, 0); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink sock."); + goto err_return; + } + + err = nl_socket_set_buffer_size(sys->genric_event_sock, 98304, 0); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink event sock."); + goto err_return; + } + + nl_socket_disable_seq_check(sys->genric_event_sock); + nl_socket_modify_cb(sys->genric_event_sock, NL_CB_VALID, NL_CB_CUSTOM, + iccp_genric_event_handler, sys); + + nl_socket_disable_seq_check(sys->route_event_sock); + nl_socket_modify_cb(sys->route_event_sock, NL_CB_VALID, NL_CB_CUSTOM, + iccp_route_event_handler, sys); + + err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_NEIGH); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + + err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_LINK); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + + err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_IPV4_IFADDR); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_IPV6_IFADDR); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + /* receive arp packet socket */ + sys->arp_receive_fd = socket(PF_PACKET, SOCK_DGRAM, 0); + if (sys->arp_receive_fd < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "socket error "); + goto err_return; + } + + if (1) + { + struct sockaddr_ll sll; + memset(&sll, 0, sizeof(sll)); + sll.sll_family = AF_PACKET; + sll.sll_protocol = htons(ETH_P_ARP); + sll.sll_ifindex = 0; + if (bind(sys->arp_receive_fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "socket bind error"); + goto err_return; + } + } + + sys->ndisc_receive_fd = iccp_make_nd_socket(); + + if (sys->ndisc_receive_fd < 0) + { + goto err_return; + } + + goto succes_return; + + err_return: + + err_route_event_sock_connect: + nl_socket_free(sys->route_event_sock); + + err_route_sock_alloc: + err_route_sock_connect: + nl_socket_free(sys->route_sock); + + err_route_event_sock_alloc: + err_genric_event_sock_connect: + nl_socket_free(sys->genric_event_sock); + + err_genric_event_sock_alloc: + err_genric_sock_connect: + nl_socket_free(sys->genric_sock); + + return err; + + err_genric_sock_alloc: + + succes_return: + return 0; +} + +void iccp_system_dinit_netlink_socket() +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL ) + return; + + nl_socket_free(sys->route_event_sock); + nl_socket_free(sys->route_sock); + nl_socket_free(sys->genric_event_sock); + nl_socket_free(sys->genric_sock); + return; +} + +static int iccp_get_netlink_genic_sock_event_fd(struct System *sys) +{ + return nl_socket_get_fd(sys->genric_event_sock); +} + +static int iccp_netlink_genic_sock_event_handler(struct System *sys) +{ + int ret = 0; + + ret = nl_recvmsgs_default(sys->genric_event_sock); + if (ret) + { + sys->need_sync_team_again = 1; + ICCPD_LOG_DEBUG(__FUNCTION__, "genric_event_sock %d recvmsg error ret = %d ", nl_socket_get_fd(sys->genric_event_sock), ret); + } + + return ret; +} + +static int iccp_get_netlink_route_sock_event_fd(struct System *sys) +{ + return nl_socket_get_fd(sys->route_event_sock); +} + +static int iccp_get_receive_arp_packet_sock_fd(struct System *sys) +{ + return sys->arp_receive_fd; +} + +static int iccp_get_receive_ndisc_packet_sock_fd(struct System *sys) +{ + return sys->ndisc_receive_fd; +} + +static int iccp_receive_arp_packet_handler(struct System *sys) +{ + unsigned char buf[1024]; + struct sockaddr_ll sll; + socklen_t sll_len = sizeof(sll); + struct arphdr *a = (struct arphdr*)buf; + int n; + unsigned int ifindex; + unsigned int addr; + uint8_t mac_addr[ETHER_ADDR_LEN]; + + n = recvfrom(sys->arp_receive_fd, buf, sizeof(buf), MSG_DONTWAIT, + (struct sockaddr*)&sll, &sll_len); + if (n < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "ARP recvfrom error: %s", buf); + return MCLAG_ERROR; + } + + /* Sanity checks */ + /*Only process ARPOP_REPLY*/ + if (n < sizeof(*a) || + a->ar_op != htons(ARPOP_REPLY) || + a->ar_pln != 4 || + a->ar_pro != htons(ETH_P_IP) || + a->ar_hln != sll.sll_halen || + sizeof(*a) + 2 * 4 + 2 * a->ar_hln > n) + return 0; + + ifindex = sll.sll_ifindex; + memcpy(mac_addr, (char*)(a + 1), ETHER_ADDR_LEN); + memcpy(&addr, (char*)(a + 1) + a->ar_hln, 4); + + do_arp_update_from_reply_packet(ifindex, addr, mac_addr); + + return 0; +} + +int iccp_receive_ndisc_packet_handler(struct System *sys) +{ + uint8_t buf[4096]; + uint8_t adata[1024]; + struct sockaddr_in6 from; + unsigned int ifindex = 0; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsgptr; + struct nd_msg *ndmsg = NULL; + struct nd_opt_hdr *nd_opt = NULL; + struct in6_addr target; + uint8_t mac_addr[ETHER_ADDR_LEN]; + int8_t *opt = NULL; + int opt_len = 0, l = 0; + int len; + + memset(mac_addr, 0, ETHER_ADDR_LEN); + + /* Fill in message and iovec. */ + msg.msg_name = (void *)(&from); + msg.msg_namelen = sizeof(struct sockaddr_in6); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = sizeof adata; + iov.iov_base = buf; + iov.iov_len = 4096; + + len = recvmsg(sys->ndisc_receive_fd, &msg, 0); + + if (len < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Ndisc recvmsg error!"); + return MCLAG_ERROR; + } + + if (msg.msg_controllen >= sizeof(struct cmsghdr)) + for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) + { + /* I want interface index which this packet comes from. */ + if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO) + { + struct in6_pktinfo *ptr; + + ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + ifindex = ptr->ipi6_ifindex; + } + } + + ndmsg = (struct nd_msg *)buf; + + if (ndmsg->icmph.icmp6_type != NDISC_NEIGHBOUR_ADVERTISEMENT) + return 0; + + memcpy((char *)(&target), (char *)(&ndmsg->target), sizeof(struct in6_addr)); + + opt = (char *)ndmsg->opt; + + opt_len = len - sizeof(struct nd_msg); + + if (opt && opt_len > 0) + { + while (opt_len) + { + if (opt_len < sizeof(struct nd_opt_hdr)) + return 0; + + nd_opt = (struct nd_opt_hdr *)opt; + + l = nd_opt->nd_opt_len << 3; + + if (l == 0) + return 0; + + if (nd_opt->nd_opt_type == ND_OPT_TARGET_LL_ADDR) + { + memcpy(mac_addr, (char *)((char *)nd_opt + sizeof(struct nd_opt_hdr)), ETHER_ADDR_LEN); + break; + } + + opt += l; + opt_len -= l; + } + } + + /* ICCPD_LOG_DEBUG(__FUNCTION__, "Recv na pkt(%s,%02X:%02X:%02X:%02X:%02X:%02X)!", show_ipv6_str((char *)&target), mac_addr[0], mac_addr[1], + mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); */ + do_ndisc_update_from_reply_packet(ifindex, (char *)&target, mac_addr); + + return 0; +} + +void iccp_netlink_sync_again() +{ + struct System* sys = NULL; + struct LocalInterface* lif = NULL; + + if ((sys = system_get_instance()) == NULL ) + return; + + if (sys->need_sync_netlink_again) + { + sys->need_sync_netlink_again = 0; + + /*Get kernel interface and port */ + iccp_sys_local_if_list_get_init(); + } + + if (sys->need_sync_team_again) + { + sys->need_sync_team_again = 0; + + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + if (lif->type == IF_T_PORT_CHANNEL) + { + iccp_get_port_member_list(lif); + } + } + } + + return; +} + +static int iccp_netlink_route_sock_event_handler(struct System *sys) +{ + int ret = 0; + + ret = nl_recvmsgs_default(sys->route_event_sock); + + if (ret) + { + sys->need_sync_netlink_again = 1; + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d recvmsg error ret = %d errno = %d ", nl_socket_get_fd(sys->route_event_sock), ret, errno); + } + /*get netlink info again when error happens */ + if (ret == 0 && sys->need_sync_netlink_again == 1) + { + iccp_netlink_sync_again(); + } + + return ret; +} + +extern int iccp_get_receive_fdb_sock_fd(struct System *sys); +extern int iccp_receive_fdb_handler_from_syncd(struct System *sys); + +/* cond HIDDEN_SYMBOLS */ +struct iccp_eventfd +{ + int (*get_fd)(struct System* sys); + int (*event_handler)(struct System* sys); +}; +/* endcond */ + +static const struct iccp_eventfd iccp_eventfds[] = { + { + .get_fd = iccp_get_server_sock_fd, + .event_handler = scheduler_server_accept, + }, + { + .get_fd = iccp_get_netlink_genic_sock_event_fd, + .event_handler = iccp_netlink_genic_sock_event_handler, + }, + { + .get_fd = iccp_get_netlink_route_sock_event_fd, + .event_handler = iccp_netlink_route_sock_event_handler, + }, + { + .get_fd = iccp_get_receive_arp_packet_sock_fd, + .event_handler = iccp_receive_arp_packet_handler, + }, + { + .get_fd = iccp_get_receive_ndisc_packet_sock_fd, + .event_handler = iccp_receive_ndisc_packet_handler, + } +}; + +/* \cond HIDDEN_SYMBOLS */ +#define ICCP_EVENT_FDS_COUNT ARRAY_SIZE(iccp_eventfds) +/* \endcond */ +/* + @return fd. + * + **/ + +int iccp_get_eventfd_fd(struct System *sys) +{ + return sys->epoll_fd; +} + +int iccp_init_netlink_event_fd(struct System *sys) +{ + int efd; + int i; + struct epoll_event event; + int err; + + efd = epoll_create1(0); + if (efd == -1) + return -errno; + + for (i = 0; i < ICCP_EVENT_FDS_COUNT; i++) + { + int fd = iccp_eventfds[i].get_fd(sys); + + event.data.fd = fd; + event.events = EPOLLIN; + err = epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event); + if (err == -1) + { + err = -errno; + goto close_efd; + } + } + + sys->epoll_fd = efd; + + return 0; + + close_efd: + close(efd); + + return err; +} + +/** + * + * @details Handler events which happened on event filedescriptor. + * + * @return Zero on success or negative number in case of an error. + **/ + +int iccp_handle_events(struct System * sys) +{ + struct epoll_event events[ICCP_EVENT_FDS_COUNT + sys->readfd_count]; + struct CSM* csm = NULL; + int nfds; + int n; + int i; + int err; + int max_nfds; + + max_nfds = ICCP_EVENT_FDS_COUNT + sys->readfd_count; + + nfds = epoll_wait(sys->epoll_fd, events, max_nfds, EPOLL_TIMEOUT_MSEC); + + /* Go over list of event fds and handle them sequentially */ + for (i = 0; i < nfds; i++) + { + for (n = 0; n < ICCP_EVENT_FDS_COUNT; n++) + { + const struct iccp_eventfd *eventfd = &iccp_eventfds[n]; + if (events[i].data.fd == eventfd->get_fd(sys)) + { + err = eventfd->event_handler(sys); + if (err) + ICCPD_LOG_INFO(__FUNCTION__, "Scheduler fd %d handler error %d !", events[i].data.fd, err ); + break; + } + } + + if (n < ICCP_EVENT_FDS_COUNT) + continue; + + if (events[i].data.fd == sys->sync_ctrl_fd) + { + int client_fd = mclagd_ctl_sock_accept(sys->sync_ctrl_fd); + if (client_fd > 0) + { + mclagd_ctl_interactive_process(client_fd); + close(client_fd); + } + continue; + } + + if (events[i].data.fd == sys->sync_fd) + { + iccp_receive_fdb_handler_from_syncd(sys); + + continue; + } + + if (events[i].data.fd == sys->sig_pipe_r) + { + iccp_receive_signal_handler(sys); + + continue; + } + + if (FD_ISSET(events[i].data.fd, &sys->readfd)) + { + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (csm->sock_fd == events[i].data.fd ) + { + scheduler_csm_read_callback(csm); + break; + } + } + } + } + + return 0; +} + diff --git a/src/iccpd/src/logger.c b/src/iccpd/src/logger.c new file mode 100644 index 000000000000..2c17610f7afc --- /dev/null +++ b/src/iccpd/src/logger.c @@ -0,0 +1,140 @@ +/* + * logger.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ +#include +#include +#include +#include + +#include "../include/cmd_option.h" +#include "../include/logger.h" + +static uint32_t _iccpd_log_level_map[] = +{ + LOG_CRIT, + LOG_ERR, + LOG_WARNING, + LOG_NOTICE, + LOG_INFO, + LOG_DEBUG, +}; + +char* log_level_to_string(int level) +{ + switch (level) + { + case CRITICAL_LOG_LEVEL: + return "CRITICAL"; + + case ERR_LOG_LEVEL: + return "ERROR"; + + case WARN_LOG_LEVEL: + return "WARN"; + + case NOTICE_LOG_LEVEL: + return "NOTICE"; + + case INFO_LOG_LEVEL: + return "INFO"; + + case DEBUG_LOG_LEVEL: + return "DEBUG"; + } + + return "INFO"; +} + +struct LoggerConfig* logger_get_configuration() +{ + static struct LoggerConfig config; + + if (config.init == 0) + { + config.console_log_enabled = 0; + config.log_level = NOTICE_LOG_LEVEL; + config.init = 1; + } + + return &config; +} + +void logger_set_configuration(int log_level) +{ + struct LoggerConfig* config = logger_get_configuration(); + + config->log_level = log_level; + config->init = 1; + + return; +} + +void log_init(struct CmdOptionParser* parser) +{ + struct LoggerConfig* config = logger_get_configuration(); + + config->console_log_enabled = parser->console_log; +} + +void log_finalize() +{ + /*do nothing*/ +} + +void write_log(const int level, const char* tag, const char* format, ...) +{ + struct LoggerConfig* config = logger_get_configuration(); + char buf[LOGBUF_SIZE]; + va_list args; + unsigned int prefix_len; + unsigned int avbl_buf_len; + unsigned int print_len; + +#if 0 + if (!config->console_log_enabled) + return; +#endif + + if (level > config->log_level) + return; + + prefix_len = snprintf(buf, LOGBUF_SIZE, "[%s.%s] ", tag, log_level_to_string(level)); + avbl_buf_len = LOGBUF_SIZE - prefix_len; + + va_start(args, format); + print_len = vsnprintf(buf + prefix_len, avbl_buf_len, format, args); + va_end(args); + + /* Since osal_vsnprintf doesn't always return the exact size written to the buffer, + * we must check if the user string length exceeds the remaing buffer size. + */ + if (print_len > avbl_buf_len) + { + print_len = avbl_buf_len; + } + + buf[prefix_len + print_len] = '\0'; + ICCPD_UTILS_SYSLOG(_iccpd_log_level_map[level], "%s", buf); + + return; +} + diff --git a/src/iccpd/src/mclagdctl/Makefile.am b/src/iccpd/src/mclagdctl/Makefile.am new file mode 100644 index 000000000000..124129c5d18e --- /dev/null +++ b/src/iccpd/src/mclagdctl/Makefile.am @@ -0,0 +1,10 @@ +bin_PROGRAMS = mclagdctl + +if DEBUG +DBGFLAGS = -ggdb -DDEBUG +else +DBGFLAGS = -g -DNDEBUG +endif + +mclagdctl_SOURCES = mclagdctl.c +mclagdctl_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) diff --git a/src/iccpd/src/mclagdctl/mclagdctl.c b/src/iccpd/src/mclagdctl/mclagdctl.c new file mode 100644 index 000000000000..630e333be6ed --- /dev/null +++ b/src/iccpd/src/mclagdctl/mclagdctl.c @@ -0,0 +1,943 @@ +/* + * Copyright(c) 2016-2019 Nephos. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: Jim Jiang from nephos + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mclagdctl.h" + +static int mclagdctl_sock_fd = -1; +char *mclagdctl_sock_path = "/var/run/iccpd/mclagdctl.sock"; + +/* + Already implemented command: + mclagdctl -i dump state + mclagdctl -i dump arp + mclagdctl -i dump mac + mclagdctl -i dump portlist local + mclagdctl -i dump portlist peer + */ + +static struct command_type command_types[] = +{ + { + .id = ID_CMDTYPE_D, + .name = "dump", + .enca_msg = NULL, + .parse_msg = NULL, + }, + { + .id = ID_CMDTYPE_D_S, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_STATE, + .name = "state", + .enca_msg = mclagdctl_enca_dump_state, + .parse_msg = mclagdctl_parse_dump_state, + }, + { + .id = ID_CMDTYPE_D_A, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_ARP, + .name = "arp", + .enca_msg = mclagdctl_enca_dump_arp, + .parse_msg = mclagdctl_parse_dump_arp, + }, + { + .id = ID_CMDTYPE_D_A, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_NDISC, + .name = "nd", + .enca_msg = mclagdctl_enca_dump_ndisc, + .parse_msg = mclagdctl_parse_dump_ndisc, + }, + { + .id = ID_CMDTYPE_D_A, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_MAC, + .name = "mac", + .enca_msg = mclagdctl_enca_dump_mac, + .parse_msg = mclagdctl_parse_dump_mac, + }, + { + .id = ID_CMDTYPE_D_P, + .parent_id = ID_CMDTYPE_D, + .name = "portlist", + }, + { + .id = ID_CMDTYPE_D_P_L, + .parent_id = ID_CMDTYPE_D_P, + .info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST, + .name = "local", + .enca_msg = mclagdctl_enca_dump_local_portlist, + .parse_msg = mclagdctl_parse_dump_local_portlist, + }, + { + .id = ID_CMDTYPE_D_P_P, + .parent_id = ID_CMDTYPE_D_P, + .info_type = INFO_TYPE_DUMP_PEER_PORTLIST, + .name = "peer", + .enca_msg = mclagdctl_enca_dump_peer_portlist, + .parse_msg = mclagdctl_parse_dump_peer_portlist, + }, + { + .id = ID_CMDTYPE_C, + .name = "config", + .enca_msg = NULL, + .parse_msg = NULL, + }, + { + .id = ID_CMDTYPE_C_L, + .parent_id = ID_CMDTYPE_C, + .info_type = INFO_TYPE_CONFIG_LOGLEVEL, + .name = "loglevel", + .enca_msg = mclagdctl_enca_config_loglevel, + .parse_msg = mclagdctl_parse_config_loglevel, + }, +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define COMMAND_TYPE_COUNT ARRAY_SIZE(command_types) + +int mclagdctl_sock_connect() +{ + struct sockaddr_un addr; + int addrlen = 0; + int ret = 0; + + if (mclagdctl_sock_fd >= 0) + return 0; + + if (strlen(mclagdctl_sock_path) <= 0) + return MCLAG_ERROR; + + mclagdctl_sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); + + if (mclagdctl_sock_fd < 0) + { + return MCLAG_ERROR; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "%s", mclagdctl_sock_path); + addrlen = sizeof(addr.sun_family) + strlen(mclagdctl_sock_path); + + if ((ret = connect(mclagdctl_sock_fd, (struct sockaddr*)&addr, addrlen)) < 0) + { + close(mclagdctl_sock_fd); + mclagdctl_sock_fd = -1; + return MCLAG_ERROR; + } + + return 0; +} + +void mclagdctl_sock_close() +{ + if (mclagdctl_sock_fd > 0) + { + close(mclagdctl_sock_fd); + mclagdctl_sock_fd = -1; + } + + return; +} + +int mclagdctl_sock_write(int fd, unsigned char *w_buf, int total_len) +{ + int write_len = 0; + int ret = 0; + + while (write_len < total_len) + { + ret = write(fd, w_buf + write_len, total_len - write_len); + if (ret <= 0) + { + return 0; + } + write_len += ret; + } + + return write_len; +} + +int mclagdctl_sock_read(int fd, unsigned char *r_buf, int total_len) +{ + int read_len = 0; + int ret = 0; + struct timeval tv = { 0 }; + fd_set read_fd; + + while (read_len < total_len) + { + FD_ZERO(&read_fd); + FD_SET(fd, &read_fd); + tv.tv_sec = 10; + tv.tv_usec = 0; + + switch ((ret = select(fd + 1, &read_fd, NULL, NULL, &tv))) + { + case -1: // error + fprintf(stdout, "Mclagdctl:Select return error:%s\n", strerror(errno)); + return MCLAG_ERROR; + + case 0: // timeout + fprintf(stdout, "Mclagdctl:Select timeout:%s\n", strerror(errno)); + return MCLAG_ERROR; + + default: + break; + } + + ret = read(fd, r_buf + read_len, total_len - read_len); + if (ret <= 0) + { + return MCLAG_ERROR; + } + read_len += ret; + } + + return read_len; +} + +int mclagdctl_enca_dump_state(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_STATE; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_state(char *msg, int data_len) +{ + struct mclagd_state * state_info = NULL; + int len = 0; + int count = 0; + int pos = 0; + + len = sizeof(struct mclagd_state); + + for (; data_len >= len; data_len -= len, count++) + { + state_info = (struct mclagd_state*)(msg + len * count); + + fprintf(stdout, "%s: %s\n", "The MCLAG's keepalive is", state_info->keepalive ? "OK" : "ERROR"); + + if (state_info->mclag_id <= 0) + fprintf(stdout, "%s: %s\n", "Domain id", "Unknown"); + else + fprintf(stdout, "%s: %d\n", "Domain id", state_info->mclag_id); + + fprintf(stdout, "%s: %s\n", "Local Ip", state_info->local_ip); + fprintf(stdout, "%s: %s\n", "Peer Ip", state_info->peer_ip); + fprintf(stdout, "%s: %s\n", "Peer Link Interface", state_info->peer_link_if); + + fprintf(stdout, "%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + "Peer Link Mac", + state_info->peer_link_mac[0], state_info->peer_link_mac[1], + state_info->peer_link_mac[2], state_info->peer_link_mac[3], + state_info->peer_link_mac[4], state_info->peer_link_mac[5]); + + if (state_info->role == 0) + fprintf(stdout, "%s: %s\n", "Role", "None"); + else if (state_info->role == 1) + fprintf(stdout, "%s: %s\n", "Role", "Active"); + else if (state_info->role == 2) + fprintf(stdout, "%s: %s\n", "Role", "Standby"); + + fprintf(stdout, "%s: %s\n", "MCLAG Interface", state_info->enabled_po); + + fprintf(stdout, "%s: %s\n", "Loglevel", state_info->loglevel); + } + + return 0; +} + +int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return MCLAG_ERROR; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_ARP; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_enca_dump_ndisc(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return MCLAG_ERROR; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_NDISC; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_arp(char *msg, int data_len) +{ + struct mclagd_arp_msg * arp_info = NULL; + int len = 0; + int count = 0; + + fprintf(stdout, "%-6s", "No."); + fprintf(stdout, "%-20s", "IP"); + fprintf(stdout, "%-20s", "MAC"); + fprintf(stdout, "%-20s", "DEV"); + fprintf(stdout, "\n"); + + len = sizeof(struct mclagd_arp_msg); + + for (; data_len >= len; data_len -= len, count++) + { + arp_info = (struct mclagd_arp_msg*)(msg + len * count); + + fprintf(stdout, "%-6d", count + 1); + fprintf(stdout, "%-20s", arp_info->ipv4_addr); + fprintf(stdout, "%02x:%02x:%02x:%02x:%02x:%02x", + arp_info->mac_addr[0], arp_info->mac_addr[1], + arp_info->mac_addr[2], arp_info->mac_addr[3], + arp_info->mac_addr[4], arp_info->mac_addr[5]); + fprintf(stdout, " "); + fprintf(stdout, "%-20s", arp_info->ifname); + fprintf(stdout, "\n"); + } + + return 0; +} + +int mclagdctl_parse_dump_ndisc(char *msg, int data_len) +{ + struct mclagd_ndisc_msg *ndisc_info = NULL; + int len = 0; + int count = 0; + + fprintf(stdout, "%-6s", "No."); + fprintf(stdout, "%-52s", "IPv6"); + fprintf(stdout, "%-20s", "MAC"); + fprintf(stdout, "%-20s", "DEV"); + fprintf(stdout, "\n"); + + len = sizeof(struct mclagd_ndisc_msg); + + for (; data_len >= len; data_len -= len, count++) + { + ndisc_info = (struct mclagd_ndisc_msg *)(msg + len * count); + + fprintf(stdout, "%-6d", count + 1); + fprintf(stdout, "%-52s", ndisc_info->ipv6_addr); + fprintf(stdout, "%02x:%02x:%02x:%02x:%02x:%02x", + ndisc_info->mac_addr[0], ndisc_info->mac_addr[1], + ndisc_info->mac_addr[2], ndisc_info->mac_addr[3], + ndisc_info->mac_addr[4], ndisc_info->mac_addr[5]); + fprintf(stdout, " "); + fprintf(stdout, "%-20s", ndisc_info->ifname); + fprintf(stdout, "\n"); + } + + return 0; +} + +int mclagdctl_enca_dump_mac(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return MCLAG_ERROR; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_MAC; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_mac(char *msg, int data_len) +{ + struct mclagd_mac_msg * mac_info = NULL; + int len = 0; + int count = 0; + + fprintf(stdout, "%-60s\n", "TYPE: S-STATIC, D-DYNAMIC; AGE: L-Local age, P-Peer age"); + + fprintf(stdout, "%-6s", "No."); + fprintf(stdout, "%-5s", "TYPE"); + fprintf(stdout, "%-20s", "MAC"); + fprintf(stdout, "%-5s", "VID"); + fprintf(stdout, "%-20s", "DEV"); + fprintf(stdout, "%-20s", "ORIGIN-DEV"); + fprintf(stdout, "%-5s", "AGE"); + fprintf(stdout, "\n"); + + len = sizeof(struct mclagd_mac_msg); + + for (; data_len >= len; data_len -= len, count++) + { + mac_info = (struct mclagd_mac_msg*)(msg + len * count); + + fprintf(stdout, "%-6d", count + 1); + + if (mac_info->fdb_type == MAC_TYPE_STATIC_CTL) + fprintf(stdout, "%-5s", "S"); + else + fprintf(stdout, "%-5s", "D"); + + fprintf(stdout, "%-20s", mac_info->mac_str); + fprintf(stdout, "%-5d", mac_info->vid); + fprintf(stdout, "%-20s", mac_info->ifname); + fprintf(stdout, "%-20s", mac_info->origin_ifname); + + if ((mac_info->age_flag & MAC_AGE_LOCAL_CTL) && (mac_info->age_flag & MAC_AGE_PEER_CTL)) + fprintf(stdout, "%-5s", "LP"); + else if (mac_info->age_flag & MAC_AGE_LOCAL_CTL) + fprintf(stdout, "%-5s", "L"); + else if (mac_info->age_flag & MAC_AGE_PEER_CTL) + fprintf(stdout, "%-5s", "P"); + else + fprintf(stdout, "%-5s", " "); + fprintf(stdout, "\n"); + } + + return 0; +} + +int mclagdctl_enca_dump_local_portlist(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return MCLAG_ERROR; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_local_portlist(char *msg, int data_len) +{ + struct mclagd_local_if * lif_info = NULL; + int len = 0; + int count = 0; + int pos = 0; + + len = sizeof(struct mclagd_local_if); + + for (; data_len >= len; data_len -= len, count++) + { + lif_info = (struct mclagd_local_if*)(msg + len * count); + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + + fprintf(stdout, "\n"); + + if (memcmp(lif_info->type, "PortChannel", 11) == 0) + { + fprintf(stdout, "%s: %d\n", "Ifindex", lif_info->ifindex); + fprintf(stdout, "%s: %s\n", "Type", lif_info->type); + fprintf(stdout, "%s: %s\n", "PortName", lif_info->name); + fprintf(stdout, "%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + "MAC", + lif_info->mac_addr[0], lif_info->mac_addr[1], + lif_info->mac_addr[2], lif_info->mac_addr[3], + lif_info->mac_addr[4], lif_info->mac_addr[5]); + + fprintf(stdout, "%s: %s\n", "IPv4Address", lif_info->ipv4_addr); + fprintf(stdout, "%s: %d\n", "Prefixlen", lif_info->prefixlen); + fprintf(stdout, "%s: %s\n", "State", lif_info->state); + fprintf(stdout, "%s: %s\n", "IsL3Interface", lif_info->l3_mode ? "Yes" : "No"); + /*fprintf(stdout, "%s: %s\n", "IsPeerlink", lif_info->is_peer_link ? "Yes" : "No");*/ + fprintf(stdout, "%s: %s\n", "MemberPorts", lif_info->portchannel_member_buf); + /*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id); + fprintf(stdout,"%s: %d\n" ,"PortchannelIsUp", lif_info->po_active); + fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state);*/ + fprintf(stdout, "%s: %s\n", "IsIsolateWithPeerlink", lif_info->isolate_to_peer_link ? "Yes" : "No"); + fprintf(stdout, "%s: %s\n", "VlanList", lif_info->vlanlist); + } + else + { + fprintf(stdout, "%s: %d\n", "Ifindex", lif_info->ifindex); + fprintf(stdout, "%s: %s\n", "Type", lif_info->type); + fprintf(stdout, "%s: %s\n", "PortName", lif_info->name); + fprintf(stdout, "%s: %s\n", "State", lif_info->state); + /*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id);*/ + } + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + + fprintf(stdout, "\n\n"); + } + + return 0; +} + +int mclagdctl_enca_dump_peer_portlist(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return MCLAG_ERROR; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_PEER_PORTLIST; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len) +{ + struct mclagd_peer_if * pif_info = NULL; + int len = 0; + int count = 0; + int pos = 0; + + len = sizeof(struct mclagd_peer_if); + + for (; data_len >= len; data_len -= len, count++) + { + pif_info = (struct mclagd_peer_if*)(msg + len * count); + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + + fprintf(stdout, "\n"); + + fprintf(stdout, "%s: %d\n", "Ifindex", pif_info->ifindex); + fprintf(stdout, "%s: %s\n", "Type", pif_info->type); + fprintf(stdout, "%s: %s\n", "PortName", pif_info->name); + fprintf(stdout, "%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + "MAC", + pif_info->mac_addr[0], pif_info->mac_addr[1], + pif_info->mac_addr[2], pif_info->mac_addr[3], + pif_info->mac_addr[4], pif_info->mac_addr[5]); + + fprintf(stdout, "%s: %s\n", "State", pif_info->state); + /*fprintf(stdout,"%s: %d\n" ,"PortchannelId", pif_info->po_id); + fprintf(stdout,"%s: %d\n" ,"PortchannelIsActive", pif_info->po_active);*/ + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + + fprintf(stdout, "\n\n"); + } + + return 0; +} + +int mclagdctl_enca_config_loglevel(char *msg, int log_level, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_CONFIG_LOGLEVEL; + req.mclag_id = log_level; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_config_loglevel(char *msg, int data_len) +{ + + int ret = *(int*)msg; + + if (ret == 0) + fprintf(stdout, "%s\n", "Config loglevel success!"); + else + fprintf(stdout, "%s\n", "Config loglevel failed!"); + + return 0; +} + +static bool __mclagdctl_cmd_executable(struct command_type *cmd_type) +{ + if (!cmd_type->enca_msg || !cmd_type->parse_msg) + return 0; + + return 1; +} + +static int __mclagdctl_cmd_param_cnt(struct command_type *cmd_type) +{ + int i = 0; + + while (cmd_type->params[i]) + i++; + + return i; +} + +static struct command_type *__mclagdctl_get_cmd_by_parent(char *cmd_name, + enum id_command_type parent_id) +{ + int i; + + for (i = 0; i < COMMAND_TYPE_COUNT; i++) + { + if (!strncmp(command_types[i].name, cmd_name, strlen(cmd_name)) + && command_types[i].parent_id == parent_id) + return &command_types[i]; + } + + return NULL; +} + +static struct command_type *__mclagdctl_get_cmd_by_id(enum id_command_type id) +{ + int i; + + for (i = 0; i < COMMAND_TYPE_COUNT; i++) + { + if (command_types[i].id == id) + return &command_types[i]; + } + + return NULL; +} + +static int mclagdctl_find_cmd(struct command_type **pcmd_type, int *argc, char ***argv) +{ + char *cmd_name; + enum id_command_type parent_id = ID_CMDTYPE_NONE; + struct command_type *cmd_type; + + while (1) + { + if (!*argc) + { + fprintf(stderr, "None or incomplete command\n"); + return -EINVAL; + } + + cmd_name = *argv[0]; + (*argc)--; + (*argv)++; + cmd_type = __mclagdctl_get_cmd_by_parent(cmd_name, parent_id); + + if (!cmd_type) + { + fprintf(stderr, "Unknown command \"%s\".\n", cmd_name); + return -EINVAL; + } + + if (__mclagdctl_cmd_executable(cmd_type) && __mclagdctl_cmd_param_cnt(cmd_type) >= *argc) + { + *pcmd_type = cmd_type; + return 0; + } + + parent_id = cmd_type->id; + } +} + +static int mclagdctl_check_cmd_params(struct command_type *cmd_type, + int argc, char **argv) +{ + int i = 0; + + while (cmd_type->params[i]) + { + if (i == argc) + { + fprintf(stderr, "Command line parameter \"%s\" expected.\n", cmd_type->params[i]); + return -EINVAL; + } + i++; + } + + return 0; +} + +static void mclagdctl_print_cmd(struct command_type *cmd_type) +{ + if (cmd_type->parent_id != ID_CMDTYPE_NONE) + { + mclagdctl_print_cmd(__mclagdctl_get_cmd_by_id(cmd_type->parent_id)); + fprintf(stdout, " "); + } + fprintf(stdout, "%s", cmd_type->name); +} + +static void mclagdctl_print_help(const char *argv0) +{ + int i, j; + struct command_type *cmd_type; + + fprintf(stdout, "%s [options] command [command args]\n" + " -h --help Show this help\n" + " -i --mclag-id Specify one mclag id\n" + " -l --level Specify log level critical,err,warn,notice,info,debug\n", + argv0); + fprintf(stdout, "Commands:\n"); + + for (i = 0; i < COMMAND_TYPE_COUNT; i++) + { + cmd_type = &command_types[i]; + if (!__mclagdctl_cmd_executable(cmd_type)) + continue; + fprintf(stdout, " "); + mclagdctl_print_cmd(cmd_type); + + for (j = 0; cmd_type->params[j]; j++) + fprintf(stdout, " %s", cmd_type->params[j]); + + fprintf(stdout, "\n"); + } +} + +int main(int argc, char **argv) +{ + char buf[MCLAGDCTL_CMD_SIZE] = { 0 }; + char *argv0 = argv[0]; + char *rcv_buf = NULL; + static const struct option long_options[] = + { + { "help", no_argument, NULL, 'h' }, + { "mclag id", required_argument, NULL, 'i' }, + { "log level", required_argument, NULL, 'l' }, + { NULL, 0, NULL, 0 } + }; + int opt; + int err; + struct command_type *cmd_type; + int ret; + unsigned para_int = 0; + + int len = 0; + char *data; + struct mclagd_reply_hdr *reply; + + while ((opt = getopt_long(argc, argv, "hi:l:", long_options, NULL)) >= 0) + { + switch (opt) + { + case 'h': + mclagdctl_print_help(argv0); + return EXIT_SUCCESS; + + case 'i': + para_int = atoi(optarg); + break; + + case 'l': + switch (tolower(optarg[0])) + { + case 'c': + para_int = CRITICAL; + break; + + case 'e': + para_int = ERR; + break; + + case 'w': + para_int = WARN; + break; + + case 'n': + para_int = NOTICE; + break; + + case 'i': + para_int = INFO; + break; + + case 'd': + para_int = DEBUG; + break; + + default: + fprintf(stderr, "unknown option \"%c\".\n", opt); + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + break; + + case '?': + fprintf(stderr, "unknown option.\n"); + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + + default: + fprintf(stderr, "unknown option \"%c\".\n", opt); + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + } + + argv += optind; + argc -= optind; + + err = mclagdctl_find_cmd(&cmd_type, &argc, &argv); + if (err) + { + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + + err = mclagdctl_check_cmd_params(cmd_type, argc, argv); + if (err) + { + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + + if (mclagdctl_sock_fd <= 0) + { + ret = mclagdctl_sock_connect(); + if (ret < 0) + return EXIT_FAILURE; + } + + if (cmd_type->enca_msg(buf, para_int, argc, argv) < 0) + { + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + ret = mclagdctl_sock_write(mclagdctl_sock_fd, buf, sizeof(struct mclagdctl_req_hdr)); + + if (ret <= 0) + { + fprintf(stderr, "Failed to send command to mclagd\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + /*read data length*/ + memset(buf, 0, MCLAGDCTL_CMD_SIZE); + ret = mclagdctl_sock_read(mclagdctl_sock_fd, buf, sizeof(int)); + if (ret <= 0) + { + fprintf(stderr, "Failed to read data length from mclagd\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + /*cont length*/ + len = *((int*)buf); + if (len <= 0) + { + ret = EXIT_FAILURE; + fprintf(stderr, "pkt len = %d, error\n", len); + goto mclagdctl_disconnect; + } + + rcv_buf = (char *)malloc(len); + if (!rcv_buf) + { + fprintf(stderr, "Failed to malloc rcv_buf for mclagdctl\n"); + goto mclagdctl_disconnect; + } + + /*read data*/ + ret = mclagdctl_sock_read(mclagdctl_sock_fd, rcv_buf, len); + if (ret <= 0) + { + fprintf(stderr, "Failed to read data from mclagd\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + reply = (struct mclagd_reply_hdr *)rcv_buf; + if (reply->info_type != cmd_type->info_type) + { + fprintf(stderr, "Reply info type from mclagd error\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + if (reply->exec_result == EXEC_TYPE_NO_EXIST_SYS) + { + fprintf(stderr, "No exist sys in iccpd!\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + if (reply->exec_result == EXEC_TYPE_NO_EXIST_MCLAGID) + { + fprintf(stderr, "Mclag-id %d hasn't been configured in iccpd!\n", para_int); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + if (reply->exec_result == EXEC_TYPE_FAILED) + { + fprintf(stderr, "exec error in iccpd!\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + cmd_type->parse_msg((char *)(rcv_buf + sizeof(struct mclagd_reply_hdr)), len - sizeof(struct mclagd_reply_hdr)); + + ret = EXIT_SUCCESS; + + mclagdctl_disconnect: + mclagdctl_sock_close(); + + if (rcv_buf) + free(rcv_buf); + + return ret; +} + diff --git a/src/iccpd/src/mclagdctl/mclagdctl.h b/src/iccpd/src/mclagdctl/mclagdctl.h new file mode 100644 index 000000000000..91155ecb7321 --- /dev/null +++ b/src/iccpd/src/mclagdctl/mclagdctl.h @@ -0,0 +1,210 @@ +/* Copyright(c) 2016-2019 Nephos. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: Jim Jiang from nephos + */ + +#define MCLAGDCTL_PARA1_LEN 16 +#define MCLAGDCTL_PARA2_LEN 32 +#define MCLAGDCTL_PARA3_LEN 64 +#define MCLAGDCTL_CMD_SIZE 4096 + +#define MCLAGDCTL_MAX_L_PORT_NANE 32 +#define MCLAGDCTL_INET_ADDR_LEN 32 +#define MCLAGDCTL_INET6_ADDR_LEN 64 +#define MCLAGDCTL_ETHER_ADDR_LEN 6 +#define MCLAGDCTL_PORT_MEMBER_BUF_LEN 512 +#define ETHER_ADDR_STR_LEN 18 + +typedef int (*call_enca_msg_fun)(char *msg, int mclag_id, int argc, char **argv); +typedef int (*call_parse_msg_fun)(char *msg, int data_len); + +enum MAC_TYPE_CTL +{ + MAC_TYPE_STATIC_CTL = 1, + MAC_TYPE_DYNAMIC_CTL = 2, +}; + +enum MAC_AGE_TYPE_CTL +{ + MAC_AGE_LOCAL_CTL = 1, /*MAC in local switch is ageout*/ + MAC_AGE_PEER_CTL = 2 /*MAC in peer switch is ageout*/ +}; + +enum id_command_type +{ + ID_CMDTYPE_NONE = 0, + ID_CMDTYPE_D, + ID_CMDTYPE_D_S, + ID_CMDTYPE_D_A, + ID_CMDTYPE_D_P, + ID_CMDTYPE_D_P_L, + ID_CMDTYPE_D_P_P, + ID_CMDTYPE_C, + ID_CMDTYPE_C_L, +}; + +enum mclagdctl_notify_peer_type +{ + INFO_TYPE_NONE = 0, + INFO_TYPE_DUMP_STATE, + INFO_TYPE_DUMP_ARP, + INFO_TYPE_DUMP_NDISC, + INFO_TYPE_DUMP_MAC, + INFO_TYPE_DUMP_LOCAL_PORTLIST, + INFO_TYPE_DUMP_PEER_PORTLIST, + INFO_TYPE_CONFIG_LOGLEVEL, + INFO_TYPE_FINISH, +}; + +enum log_level_type +{ + CRITICAL = 0, + ERR= 1, + WARN = 2, + NOTICE= 3, + INFO = 4, + DEBUG = 5 +}; + +struct mclagdctl_req_hdr +{ + int info_type; + int mclag_id; + char para1[MCLAGDCTL_PARA2_LEN]; + char para2[MCLAGDCTL_PARA2_LEN]; + char para3[MCLAGDCTL_PARA2_LEN]; +}; + +struct mclagd_reply_hdr +{ + int info_type; + int data_len; + int exec_result; +}; + +#define EXEC_TYPE_SUCCESS -1 +#define EXEC_TYPE_NO_EXIST_SYS -2 +#define EXEC_TYPE_NO_EXIST_MCLAGID -3 +#define EXEC_TYPE_FAILED -4 + +#define MCLAG_ERROR -1 + +#define MCLAGD_REPLY_INFO_HDR (sizeof(struct mclagd_reply_hdr) + sizeof(int)) + +#define MCLAGDCTL_COMMAND_PARAM_MAX_CNT 8 +struct command_type +{ + enum id_command_type id; + enum id_command_type parent_id; + enum mclagdctl_notify_peer_type info_type; + char *name; + char *params[MCLAGDCTL_COMMAND_PARAM_MAX_CNT]; + call_enca_msg_fun enca_msg; + call_parse_msg_fun parse_msg; +}; + +struct mclagd_state +{ + int mclag_id; + int keepalive; + char local_ip[MCLAGDCTL_INET_ADDR_LEN]; + char peer_ip[MCLAGDCTL_INET_ADDR_LEN]; + char peer_link_if[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char peer_link_mac[MCLAGDCTL_ETHER_ADDR_LEN]; + int role; + char enabled_po[MCLAGDCTL_PORT_MEMBER_BUF_LEN]; + char loglevel[MCLAGDCTL_PARA1_LEN]; +}; + +struct mclagd_arp_msg +{ + char op_type; + char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; + char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN]; + unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; +}; + +struct mclagd_ndisc_msg +{ + char op_type; + char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; + char ipv6_addr[MCLAGDCTL_INET6_ADDR_LEN]; + unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; +}; + +struct mclagd_mac_msg +{ + unsigned char op_type;/*add or del*/ + unsigned char fdb_type;/*static or dynamic*/ + char mac_str[ETHER_ADDR_STR_LEN]; + unsigned short vid; + /*Current if name that set in chip*/ + char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; + /*if we set the mac to peer-link, origin_ifname store the + original if name that learned from chip*/ + char origin_ifname[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char age_flag;/*local or peer is age?*/ +}; + +struct mclagd_local_if +{ + int ifindex; + char type[MCLAGDCTL_PARA1_LEN]; + char name[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; + char state[MCLAGDCTL_PARA1_LEN]; + char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN]; + unsigned char prefixlen; + + unsigned char l3_mode; + unsigned char is_peer_link; + char portchannel_member_buf[MCLAGDCTL_PORT_MEMBER_BUF_LEN]; + int po_id; /* Port Channel ID */ + unsigned char po_active; + char mlacp_state[MCLAGDCTL_PARA1_LEN]; + unsigned char isolate_to_peer_link; + + char vlanlist[MCLAGDCTL_PARA3_LEN]; +}; + +struct mclagd_peer_if +{ + int ifindex; + unsigned char type[MCLAGDCTL_PARA1_LEN]; + char name[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; + unsigned char state[MCLAGDCTL_PARA1_LEN]; + int po_id; + unsigned char po_active; +}; + +extern int mclagdctl_enca_dump_state(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_state(char *msg, int data_len); +extern int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_enca_dump_ndisc(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_arp(char *msg, int data_len); +extern int mclagdctl_parse_dump_ndisc(char *msg, int data_len); +extern int mclagdctl_enca_dump_mac(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_mac(char *msg, int data_len); +extern int mclagdctl_enca_dump_local_portlist(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_local_portlist(char *msg, int data_len); +extern int mclagdctl_enca_dump_peer_portlist(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len); +int mclagdctl_enca_config_loglevel(char *msg, int log_level, int argc, char **argv); +int mclagdctl_parse_config_loglevel(char *msg, int data_len); + diff --git a/src/iccpd/src/mlacp_fsm.c b/src/iccpd/src/mlacp_fsm.c new file mode 100644 index 000000000000..c56eb9051736 --- /dev/null +++ b/src/iccpd/src/mlacp_fsm.c @@ -0,0 +1,1293 @@ +/* + * mlacp_fsm.c + * mLACP finite state machine handler. + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include "../include/mlacp_tlv.h" +#include "../include/mlacp_sync_prepare.h" +#include "../include/mlacp_link_handler.h" +#include "../include/mlacp_sync_update.h" + +#include + +/***************************************** +* Define +* +* ***************************************/ +#define MLACP_MSG_QUEUE_REINIT(list) \ + { \ + struct Msg* msg = NULL; \ + while (!TAILQ_EMPTY(&(list))) { \ + msg = TAILQ_FIRST(&(list)); \ + TAILQ_REMOVE(&(list), msg, tail); \ + free(msg->buf); \ + free(msg); \ + } \ + TAILQ_INIT(&(list)); \ + } + +#define PIF_QUEUE_REINIT(list) \ + { \ + while (!LIST_EMPTY(&(list))) { \ + struct PeerInterface* peer_if = NULL; \ + peer_if = LIST_FIRST(&(list)); \ + LIST_REMOVE(peer_if, mlacp_next); \ + free(peer_if); \ + } \ + LIST_INIT(&(list)); \ + } + +#define LIF_QUEUE_REINIT(list) \ + { \ + while (!LIST_EMPTY(&(list))) { \ + struct LocalInterface* lif = NULL; \ + lif = LIST_FIRST(&(list)); \ + if (lif->type == IF_T_PORT_CHANNEL && lif->is_arp_accept) { \ + if ((set_sys_arp_accept_flag(lif->name, 0)) == 0) \ + lif->is_arp_accept = 0; \ + } \ + LIST_REMOVE (lif, mlacp_next); \ + } \ + LIST_INIT(&(list)); \ + } + +#define LIF_PURGE_QUEUE_REINIT(list) \ + { \ + while (!LIST_EMPTY(&(list))) { \ + struct LocalInterface* lif = NULL; \ + lif = LIST_FIRST(&(list)); \ + LIST_REMOVE(lif, mlacp_purge_next); \ + } \ + LIST_INIT(&(list)); \ + } + +#define WARM_REBOOT_TIMEOUT 90 + +/***************************************** +* Static Function +* +* ***************************************/ +static char *mlacp_state(struct CSM* csm); +static void mlacp_resync_arp(struct CSM* csm); +static void mlacp_resync_ndisc(struct CSM* csm); +static void mlacp_resync_mac(struct CSM* csm); +/* Sync Sender APIs*/ +static void mlacp_sync_send_sysConf(struct CSM* csm); +static void mlacp_sync_send_aggConf(struct CSM* csm); +static void mlacp_sync_send_aggState(struct CSM* csm); +static void mlacp_sync_send_syncArpInfo(struct CSM* csm); +static void mlacp_sync_send_syncNdiscInfo(struct CSM* csm); +static void mlacp_sync_send_heartbeat(struct CSM* csm); +static void mlacp_sync_send_syncDoneData(struct CSM* csm); +/* Sync Reciever APIs*/ +static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portConf(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portPrio(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portState(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_aggConf(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_aggState(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_syncData(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_syncReq(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portChanInfo(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_peerLlinkInfo(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_arpInfo(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg); + +/* Sync Handler*/ +static void mlacp_sync_send_nak_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_nak_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_sender_handler(struct CSM* csm); +static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_send_all_info_handler(struct CSM* csm); + +/* Sync State Handler*/ +static void mlacp_stage_sync_send_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_stage_sync_request_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_stage_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg); + +/****************************************************************** + * Sync Sender APIs + * + *****************************************************************/ +static void mlacp_sync_send_sysConf(struct CSM* csm) +{ + int msg_len = 0; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_sys_config(csm, g_csm_buf, CSM_BUFFER_SIZE); + if (msg_len > 0) + iccp_csm_send(csm, g_csm_buf, msg_len); + else + ICCPD_LOG_WARN(__FUNCTION__, "Invalid sysconf packet."); + + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] SysConf, len=[%d]", msg_len);*/ + + return; +} + +static void mlacp_sync_send_aggConf(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + struct LocalInterface* local_if = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if, 0); + iccp_csm_send(csm, g_csm_buf, msg_len); + local_if->port_config_sync = 0; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ + } + } + + return; +} + +static void mlacp_sync_send_aggState(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + struct LocalInterface* local_if = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if); + iccp_csm_send(csm, g_csm_buf, msg_len); + local_if->changed = 0; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ + } + } + + return; +} +#define MAX_MAC_ENTRY_NUM 30 +#define MAX_NEIGH_ENTRY_NUM 40 +static void mlacp_sync_send_syncMacInfo(struct CSM* csm) +{ + int msg_len = 0; + struct Msg* msg = NULL; + int count = 0; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + + while (!TAILQ_EMPTY(&(MLACP(csm).mac_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).mac_msg_list), msg, tail); + msg_len = mlacp_prepare_for_mac_info_to_peer(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct MACMsg*)msg->buf, count); + count++; + free(msg->buf); + free(msg); + if (count >= MAX_MAC_ENTRY_NUM) + { + iccp_csm_send(csm, g_csm_buf, msg_len); + count = 0; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + } + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] MacInfo,len=[%d]", msg_len);*/ + } + + if (count) + iccp_csm_send(csm, g_csm_buf, msg_len); + + return; +} + +static void mlacp_sync_send_syncArpInfo(struct CSM* csm) +{ + int msg_len = 0; + struct Msg* msg = NULL; + int count = 0; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + + while (!TAILQ_EMPTY(&(MLACP(csm).arp_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); + + msg_len = mlacp_prepare_for_arp_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct ARPMsg*)msg->buf, count); + count++; + free(msg->buf); + free(msg); + if (count >= MAX_NEIGH_ENTRY_NUM) + { + iccp_csm_send(csm, g_csm_buf, msg_len); + count = 0; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + } + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] ArpInfo,len=[%d]", msg_len);*/ + } + + if (count) + iccp_csm_send(csm, g_csm_buf, msg_len); + + return; +} + +static void mlacp_sync_send_syncNdiscInfo(struct CSM *csm) +{ + int msg_len = 0; + struct Msg *msg = NULL; + int count = 0; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + + while (!TAILQ_EMPTY(&(MLACP(csm).ndisc_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).ndisc_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).ndisc_msg_list), msg, tail); + + msg_len = mlacp_prepare_for_ndisc_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct NDISCMsg *)msg->buf, count); + count++; + free(msg->buf); + free(msg); + if (count >= MAX_NEIGH_ENTRY_NUM) + { + iccp_csm_send(csm, g_csm_buf, msg_len); + count = 0; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + } + /* ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] NDInfo,len=[%d]", msg_len); */ + } + + if (count) + iccp_csm_send(csm, g_csm_buf, msg_len); + + return; +} +static void mlacp_sync_send_syncPortChannelInfo(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + struct LocalInterface* local_if = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_port_channel_info(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if); + iccp_csm_send(csm, g_csm_buf, msg_len); + local_if->changed = 0; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ + } + } + + return; +} + +static void mlacp_sync_send_syncPeerLinkInfo(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + + if ((sys = system_get_instance()) == NULL) + return; + + if (csm->peer_link_if) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); + iccp_csm_send(csm, g_csm_buf, msg_len); + } + + return; +} + +static void mlacp_sync_send_heartbeat(struct CSM* csm) +{ + int msg_len = 0; + + if ((csm->heartbeat_send_time == 0) || + ((time(NULL) - csm->heartbeat_send_time) > 1)) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_heartbeat(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); + time(&csm->heartbeat_send_time); + } + + return; +} + +static void mlacp_sync_send_syncDoneData(struct CSM* csm) +{ + int msg_len = 0; + + /*Sync done & go to next stage*/ + MLACP(csm).wait_for_sync_data = 0; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_sync_data_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE, 1); + iccp_csm_send(csm, g_csm_buf, msg_len); + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] SyncDone, len=[%d]", msg_len);*/ + + return; +} + +/****************************************************************** + * Sync Receiver APIs + * + *****************************************************************/ +static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg) +{ + mLACPSysConfigTLV* sysconf = NULL; + + sysconf = (mLACPSysConfigTLV*)&(msg->buf[sizeof(ICCHdr)]); + + if (mlacp_fsm_update_system_conf(csm, sysconf) == MCLAG_ERROR) + { + /*NOTE: we just change the node ID local side without sending NAK msg*/ + ICCPD_LOG_WARN(__FUNCTION__, "Same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id); + mlacp_sync_send_nak_handler(csm, msg); + } + + return; +} + +static void mlacp_sync_recv_portConf(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_portPrio(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_portState(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_aggConf(struct CSM* csm, struct Msg* msg) +{ + mLACPAggConfigTLV* portconf = NULL; + + portconf = (mLACPAggConfigTLV*)&(msg->buf[sizeof(ICCHdr)]); + if (mlacp_fsm_update_Agg_conf(csm, portconf) == MCLAG_ERROR) + { + mlacp_sync_send_nak_handler(csm, msg); + } + + return; +} + +static void mlacp_sync_recv_aggState(struct CSM* csm, struct Msg* msg) +{ + mLACPAggPortStateTLV* portstate = NULL; + + portstate = (mLACPAggPortStateTLV*)&(msg->buf[sizeof(ICCHdr)]); + if (mlacp_fsm_update_Aggport_state(csm, portstate) == MCLAG_ERROR) + { + mlacp_sync_send_nak_handler(csm, msg); + /*MLACP(csm).error_msg = "Receive a port state update on an non-existed port. It is suggest to check the environment and re-initialize mLACP again.";*/ + return; + } + + return; +} + +static void mlacp_sync_recv_syncData(struct CSM* csm, struct Msg* msg) +{ + mLACPSyncDataTLV* syncdata = NULL; + + syncdata = (mLACPSyncDataTLV*)&(msg->buf[sizeof(ICCHdr)]); + if (ntohs(syncdata->flags) == 1) + { + /* Sync done*/ + MLACP(csm).wait_for_sync_data = 0; + } + + return; +} + +static void mlacp_sync_recv_syncReq(struct CSM* csm, struct Msg* msg) +{ + mLACPSyncReqTLV* mlacp_sync_req = NULL; + + mlacp_sync_req = (mLACPSyncReqTLV*)&msg->buf[sizeof(ICCHdr)]; + MLACP(csm).sync_req_num = ntohs(mlacp_sync_req->req_num); + + /* Reply the peer all sync info*/ + mlacp_sync_send_all_info_handler(csm); + + return; +} + +static void mlacp_sync_recv_portChanInfo(struct CSM* csm, struct Msg* msg) +{ + mLACPPortChannelInfoTLV* portconf = NULL; + + portconf = (mLACPPortChannelInfoTLV*)&(msg->buf[sizeof(ICCHdr)]); + if (mlacp_fsm_update_port_channel_info(csm, portconf) == MCLAG_ERROR) + { + mlacp_sync_send_nak_handler(csm, msg); + } + + return; +} + +static void mlacp_sync_recv_peerLlinkInfo(struct CSM* csm, struct Msg* msg) +{ + mLACPPeerLinkInfoTLV* peerlink = NULL; + + peerlink = (mLACPPeerLinkInfoTLV*)&(msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_peerlink_info( csm, peerlink); + + return; +} + +static void mlacp_sync_recv_macInfo(struct CSM* csm, struct Msg* msg) +{ + struct mLACPMACInfoTLV* mac_info = NULL; + + mac_info = (struct mLACPMACInfoTLV *)&(msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_mac_info_from_peer(csm, mac_info); + + return; +} + +static void mlacp_sync_recv_arpInfo(struct CSM* csm, struct Msg* msg) +{ + struct mLACPARPInfoTLV* arp_info = NULL; + + arp_info = (struct mLACPARPInfoTLV *)&(msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_arp_info(csm, arp_info); + + return; +} + +static void mlacp_sync_recv_ndiscInfo(struct CSM *csm, struct Msg *msg) +{ + struct mLACPNDISCInfoTLV *ndisc_info = NULL; + + ndisc_info = (struct mLACPNDISCInfoTLV *)&(msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_ndisc_info(csm, ndisc_info); + + return; +} +static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_heartbeat(struct CSM* csm, struct Msg* msg) +{ + struct mLACPHeartbeatTLV *tlv = NULL; + + tlv = (struct mLACPHeartbeatTLV *)(&msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_heartbeat(csm, tlv); + + return; +} + +static void mlacp_sync_recv_warmboot(struct CSM* csm, struct Msg* msg) +{ + struct mLACPWarmbootTLV *tlv = NULL; + + tlv = (struct mLACPWarmbootTLV *)(&msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_warmboot(csm, tlv); + + return; +} + +/***************************************** +* MLACP Init +* +* ***************************************/ +void mlacp_init(struct CSM* csm, int all) +{ + if (csm == NULL) + return; + + MLACP(csm).sync_req_num = -1; + MLACP(csm).need_to_sync = 0; + MLACP(csm).error_msg = NULL; + + MLACP(csm).current_state = MLACP_STATE_INIT; + memset(MLACP(csm).remote_system.system_id, 0, ETHER_ADDR_LEN); + + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); + PIF_QUEUE_REINIT(MLACP(csm).pif_list); + LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list); + + if (all != 0) + { + /* if no clean all, keep the arp info & local interface info for next connection*/ + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list); + LIF_QUEUE_REINIT(MLACP(csm).lif_list); + + MLACP(csm).node_id = MLACP_SYSCONF_NODEID_MSB_MASK; + MLACP(csm).node_id |= (((inet_addr(csm->sender_ip) >> 24) << 4) & MLACP_SYSCONF_NODEID_NODEID_MASK); + MLACP(csm).node_id |= rand() % MLACP_SYSCONF_NODEID_FREE_MASK; + } + + return; +} + +/***************************************** +* MLACP finalize +* +* ***************************************/ +void mlacp_finalize(struct CSM* csm) +{ + if (csm == NULL) + return; + + /* msg destroy*/ + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list); + + /* remove lif & lif-purge queue */ + LIF_QUEUE_REINIT(MLACP(csm).lif_list); + LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list); + /* remove & destroy pif queue */ + PIF_QUEUE_REINIT(MLACP(csm).pif_list); + + return; +} + +/***************************************** +* MLACP FSM Transit +* +* ***************************************/ +void mlacp_fsm_transit(struct CSM* csm) +{ + struct System* sys = NULL; + struct Msg* msg = NULL; + static MLACP_APP_STATE_E prev_state = MLACP_SYNC_SYSCONF; + ICCHdr* icc_hdr = NULL; + ICCParameter* icc_param = NULL; + int have_msg = 1; + + if (csm == NULL) + return; + if ((sys = system_get_instance()) == NULL) + return; + + /* torn down event */ + if (csm->sock_fd <= 0 || csm->app_csm.current_state != APP_OPERATIONAL) + { + /* drop all legacy mlacp msg*/ + if (MLACP(csm).current_state != MLACP_STATE_INIT) + { + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); + MLACP(csm).current_state = MLACP_STATE_INIT; + } + return; + } + + if (csm->warm_reboot_disconn_time != 0) + { + /*After peer warm reboot and disconnect, if peer connection is not establised more than 90s, + recover peer disconnection to normal process, such as add peer age flag for MACs etc*/ + if ((time(NULL) - csm->warm_reboot_disconn_time) >= WARM_REBOOT_TIMEOUT) + { + csm->warm_reboot_disconn_time = 0; + ICCPD_LOG_NOTICE(__FUNCTION__, "Peer warm reboot, reconnection timeout, recover to normal reboot!"); + mlacp_peer_disconn_handler(csm); + } + } + + mlacp_sync_send_heartbeat(csm); + + /* Dequeue msg if any*/ + while (have_msg) + { + if (MLACP(csm).current_state != MLACP_STATE_INIT) + { + /* Handler NAK First*/ + msg = mlacp_dequeue_msg(csm); + if (msg != NULL) + { + have_msg = 1; + icc_hdr = (ICCHdr*)msg->buf; + icc_param = (ICCParameter*)&msg->buf[sizeof(ICCHdr)]; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " SYNC: Message Type = %X, TLV=%s, Len=%d", icc_hdr->ldp_hdr.msg_type, get_tlv_type_string(icc_param->type), msg->len);*/ + + if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION && icc_param->type == TLV_T_NAK) + { + mlacp_sync_recv_nak_handler(csm, msg); + free(msg->buf); + free(msg); + continue; + } + } + else + { + have_msg = 0; + } + } + + if (prev_state != MLACP(csm).current_state) + { + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + mlacp_peer_conn_handler(csm); + prev_state = MLACP(csm).current_state; + } + + /* Sync State */ + if (MLACP(csm).current_state == MLACP_STATE_INIT) + { + MLACP(csm).wait_for_sync_data = 0; + MLACP(csm).current_state = MLACP_STATE_STAGE1; + mlacp_resync_arp(csm); + mlacp_resync_ndisc(csm); + } + + switch (MLACP(csm).current_state) + { + case MLACP_STATE_INIT: + case MLACP_STATE_ERROR: + /* should not be here*/ + break; + + case MLACP_STATE_STAGE1: + case MLACP_STATE_STAGE2: + mlacp_stage_handler(csm, msg); + break; + + case MLACP_STATE_EXCHANGE: + mlacp_exchange_handler(csm, msg); + break; + } + + /*ICCPD_LOG_DEBUG("mlacp_fsm", " Next State = %s", mlacp_state(csm));*/ + if (msg) + { + free(msg->buf); + free(msg); + } + } +} + +/* Helper function for dumping application state machine */ +static char* mlacp_state(struct CSM* csm) +{ + if (csm == NULL ) + return "MLACP_NULL"; + + switch (MLACP(csm).current_state) + { + case MLACP_STATE_INIT: + return "MLACP_STATE_INIT"; + + case MLACP_STATE_STAGE1: + return "MLACP_STATE_STAGE1"; + + case MLACP_STATE_STAGE2: + return "MLACP_STATE_STAGE2"; + + case MLACP_STATE_EXCHANGE: + return "MLACP_STATE_EXCHANGE"; + + case MLACP_STATE_ERROR: + return "MLACP_STATE_ERROR"; + } + + return "MLACP_UNKNOWN"; +} + +/* Add received message into message list */ +void mlacp_enqueue_msg(struct CSM* csm, struct Msg* msg) +{ + if (csm == NULL ) + { + if (msg != NULL ) + free(msg); + return; + } + + if (msg == NULL ) + return; + + #if 0 + icc_hdr = (ICCHdr*)msg->buf; + icc_param = (ICCParameter*)&msg->buf[sizeof(ICCHdr)]; + ICCPD_LOG_DEBUG("mlacp_fsm", " mLACP enqueue: tlv = 0x%04x", icc_param->type); + #endif + + TAILQ_INSERT_TAIL(&(MLACP(csm).mlacp_msg_list), msg, tail); + + return; +} + +/* Get received message from message list */ +struct Msg* mlacp_dequeue_msg(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (!TAILQ_EMPTY(&(MLACP(csm).mlacp_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).mlacp_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).mlacp_msg_list), msg, tail); + } + + return msg; +} + +/****************************************** +* When peerlink ready, prepare the MACMsg +* +******************************************/ +static void mlacp_resync_mac(struct CSM* csm) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + struct Msg *msg_send = NULL; + + /* recover MAC info sync from peer*/ + if (!TAILQ_EMPTY(&(MLACP(csm).mac_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*)msg->buf; + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } +} + +/****************************************** +* When peerlink ready, prepare the ARPMsg +* +******************************************/ +static void mlacp_resync_arp(struct CSM* csm) +{ + struct Msg* msg = NULL; + struct ARPMsg* arp_msg = NULL; + struct Msg *msg_send = NULL; + + /* recover ARP info sync from peer*/ + if (!TAILQ_EMPTY(&(MLACP(csm).arp_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_msg = (struct ARPMsg*)msg->buf; + arp_msg->op_type = NEIGH_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + } + } + } +} + +/****************************************** +* When peerlink ready, prepare the NDISCMsg +* +******************************************/ +static void mlacp_resync_ndisc(struct CSM *csm) +{ + struct Msg *msg = NULL; + struct NDISCMsg *ndisc_msg = NULL; + struct Msg *msg_send = NULL; + + /* recover ndisc info sync from peer */ + if (!TAILQ_EMPTY(&(MLACP(csm).ndisc_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail) + { + ndisc_msg = (struct NDISCMsg *)msg->buf; + ndisc_msg->op_type = NEIGH_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char *)ndisc_msg, sizeof(struct NDISCMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_msg_list), msg_send, tail); + } + } + } +} + +/***************************************** +* NAK handler +* +* ***************************************/ +static void mlacp_sync_send_nak_handler(struct CSM* csm, struct Msg* msg) +{ + int msg_len; + ICCHdr* icc_hdr = NULL; + + icc_hdr = (ICCHdr*)msg->buf; + + ICCPD_LOG_WARN(__FUNCTION__, "Send NAK"); + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + csm->app_csm.invalid_msg_id = ntohl(icc_hdr->ldp_hdr.msg_id); + msg_len = app_csm_prepare_nak_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); +} + +static void mlacp_sync_recv_nak_handler(struct CSM* csm, struct Msg* msg) +{ + NAKTLV* naktlv = NULL; + uint16_t tlvType = -1; + int i; + + ICCPD_LOG_WARN(__FUNCTION__, "Receive NAK "); + + /* Dequeuq NAK*/ + naktlv = (NAKTLV*)&msg->buf[sizeof(ICCHdr)]; + + /* Check NAK Type*/ + for (i = 0; i < MAX_MSG_LOG_SIZE; ++i) + { + if (ntohl(naktlv->rejected_msg_id) == csm->msg_log.msg[i].msg_id) + { + tlvType = csm->msg_log.msg[i].tlv; + break; + } + } + + if (tlvType) + { + switch (tlvType) + { + case TLV_T_MLACP_SYSTEM_CONFIG: + MLACP(csm).node_id--; + MLACP(csm).system_config_changed = 1; + ICCPD_LOG_WARN(__FUNCTION__, "[%X] change NodeID as %d", tlvType & 0x00FF, MLACP(csm).node_id); + break; + + default: + ICCPD_LOG_WARN(__FUNCTION__, " [%X]", tlvType & 0x00FF); + MLACP(csm).need_to_sync = 1; + break; + } + } + else + { + ICCPD_LOG_WARN(__FUNCTION__, "Unknow NAK"); + MLACP(csm).need_to_sync = 1; + } + + return; +} + +/***************************************** +* MLACP sync receiver +* +* ***************************************/ +static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg) +{ + ICCParameter *icc_param; + + /* No receive message...*/ + if (!csm || !msg) + return; + + icc_param = (ICCParameter*)&(msg->buf[sizeof(ICCHdr)]); + + /*fprintf(stderr, " Recv Type [%d]\n", icc_param->type);*/ + switch (icc_param->type) + { + case TLV_T_MLACP_SYSTEM_CONFIG: + mlacp_sync_recv_sysConf(csm, msg); + break; + + case TLV_T_MLACP_PORT_CONFIG: + mlacp_sync_recv_portConf(csm, msg); + break; + + case TLV_T_MLACP_PORT_PRIORITY: + mlacp_sync_recv_portPrio(csm, msg); + break; + + case TLV_T_MLACP_PORT_STATE: + mlacp_sync_recv_portState(csm, msg); + break; + + case TLV_T_MLACP_AGGREGATOR_CONFIG: + /* The following line will be uncommented when Aggregator related structures are supported. */ + mlacp_sync_recv_aggConf(csm, msg); + break; + + case TLV_T_MLACP_AGGREGATOR_STATE: + mlacp_sync_recv_aggState(csm, msg); + break; + + case TLV_T_MLACP_SYNC_DATA: + mlacp_sync_recv_syncData(csm, msg); + break; + + case TLV_T_MLACP_SYNC_REQUEST: + mlacp_sync_recv_syncReq(csm, msg); + break; + + case TLV_T_MLACP_PORT_CHANNEL_INFO: + mlacp_sync_recv_portChanInfo(csm, msg); + break; + + case TLV_T_MLACP_PEERLINK_INFO: + mlacp_sync_recv_peerLlinkInfo(csm, msg); + break; + + case TLV_T_MLACP_MAC_INFO: + mlacp_sync_recv_macInfo(csm, msg); + break; + + case TLV_T_MLACP_ARP_INFO: + mlacp_sync_recv_arpInfo(csm, msg); + break; + + case TLV_T_MLACP_NDISC_INFO: + mlacp_sync_recv_ndiscInfo(csm, msg); + break; + + case TLV_T_MLACP_STP_INFO: + mlacp_sync_recv_stpInfo(csm, msg); + break; + + case TLV_T_MLACP_HEARTBEAT: + mlacp_sync_recv_heartbeat(csm, msg); + break; + + case TLV_T_MLACP_WARMBOOT_FLAG: + mlacp_sync_recv_warmboot(csm, msg); + break; + } + + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [Sync Recv] %s... DONE", get_tlv_type_string(icc_param->type));*/ + + return; +} + +/***************************************** +* MLACP sync sender +* +* ***************************************/ +static void mlacp_sync_sender_handler(struct CSM* csm) +{ + switch (MLACP(csm).sync_state) + { + case MLACP_SYNC_SYSCONF: + mlacp_sync_send_sysConf(csm); + break; + + case MLACP_SYNC_AGGCONF: + /* Do nothing due to no support in this version. */ + mlacp_sync_send_aggConf(csm); + break; + + case MLACP_SYNC_AGGSTATE: + /* Do nothing due to no support in this version. */ + mlacp_sync_send_aggState(csm); + break; + + case MLACP_SYNC_AGGINFO: + mlacp_sync_send_syncPortChannelInfo(csm); + break; + + case MLACP_SYNC_PEERLINKINFO: + mlacp_sync_send_syncPeerLinkInfo(csm); + break; + + case MLACP_SYNC_ARP_INFO: + mlacp_sync_send_syncArpInfo(csm); + break; + + case MLACP_SYNC_NDISC_INFO: + mlacp_sync_send_syncNdiscInfo(csm); + break; + + case MLACP_SYNC_DONE: + mlacp_sync_send_syncDoneData(csm); + break; + + default: + break; + } + + return; +} + +static void mlacp_sync_send_all_info_handler(struct CSM* csm) +{ + size_t len = 0; + + /* Prepare for sync start reply*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_sync_data_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE, 0); + iccp_csm_send(csm, g_csm_buf, len); + + MLACP(csm).sync_state = MLACP_SYNC_SYSCONF; + + while (1) + { + mlacp_sync_sender_handler(csm); + if (MLACP(csm).sync_state != MLACP_SYNC_DONE) + { + MLACP(csm).sync_state++; + } + else + { + /*Next stage*/ + MLACP(csm).wait_for_sync_data = 0; + MLACP(csm).current_state++; + break; + } + } + + return; +} + +static void mlacp_stage_sync_send_handler(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + ICCParameter* icc_param = NULL; + mLACPSyncReqTLV* mlacp_sync_req = NULL; + + if (MLACP(csm).wait_for_sync_data == 0) + { + /* Waiting the peer sync request*/ + if (msg) + { + icc_hdr = (ICCHdr*)msg->buf; + icc_param = (ICCParameter*)&msg->buf[sizeof(ICCHdr)]; + + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA && icc_param->type == TLV_T_MLACP_SYNC_REQUEST) + { + mlacp_sync_req = (mLACPSyncReqTLV*)&msg->buf[sizeof(ICCHdr)]; + MLACP(csm).wait_for_sync_data = 1; + MLACP(csm).sync_req_num = ntohs(mlacp_sync_req->req_num); + + /* Reply the peer all sync info*/ + mlacp_sync_send_all_info_handler(csm); + } + } + } + + return; +} + +static void mlacp_stage_sync_request_handler(struct CSM* csm, struct Msg* msg) +{ + int msg_len = 0; + + /* Socket server send sync request first*/ + if (MLACP(csm).wait_for_sync_data == 0) + { + // Send out the request for ALL + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_sync_request_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); + MLACP(csm).wait_for_sync_data = 1; + } + else + { + mlacp_sync_receiver_handler(csm, msg); + if (MLACP(csm).wait_for_sync_data == 0) + { + MLACP(csm).current_state++; + } + } + + return; +} + +static void mlacp_stage_handler(struct CSM* csm, struct Msg* msg) +{ + if (MLACP(csm).current_state == MLACP_STATE_STAGE1) + { + /*Stage 1, role active send info first*/ + if (csm->role_type == STP_ROLE_ACTIVE) + mlacp_stage_sync_send_handler(csm, msg); + else + mlacp_stage_sync_request_handler(csm, msg); + } + else + { + /*Stage 2, role standby send info*/ + if (csm->role_type == STP_ROLE_ACTIVE) + mlacp_stage_sync_request_handler(csm, msg); + else + mlacp_stage_sync_send_handler(csm, msg); + } + + return; +} + +static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) +{ + int len; + struct System* sys = NULL; + struct LocalInterface* lif = NULL, *lif_purge = NULL; + + ICCHdr* icc_hdr = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + /* update system id*/ + /*update_system_id(csm);*/ + + /* Any msg?*/ + if (msg) + { + icc_hdr = (ICCHdr*)msg->buf; + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + /* Process receive APP info*/ + mlacp_sync_receiver_handler(csm, msg); + } + } + + if (MLACP(csm).need_to_sync != 0) + { + /* Send out the request for ALL info*/ + MLACP(csm).need_to_sync = 0; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_sync_request_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + } + + /* Send system config*/ + if (MLACP(csm).system_config_changed != 0) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_sys_config(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + + if (csm->peer_link_if) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); + iccp_csm_send(csm, g_csm_buf, len); + } + + MLACP(csm).system_config_changed = 0; + } + + /* Send mlag purge lif*/ + LIST_FOREACH(lif_purge, &(MLACP(csm).lif_purge_list), mlacp_purge_next) + { + /* Purge info*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif_purge, 1); + iccp_csm_send(csm, g_csm_buf, len); + /* Destroy old interface*/ + if (lif_purge != NULL) + LIST_REMOVE(lif_purge, mlacp_purge_next); + } + + /* Send mlag lif*/ + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type == IF_T_PORT_CHANNEL && lif->port_config_sync) + { + /* Send port channel information*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif, 0); + iccp_csm_send(csm, g_csm_buf, len); + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_port_channel_info(csm, g_csm_buf, CSM_BUFFER_SIZE, lif); + iccp_csm_send(csm, g_csm_buf, len); + + lif->port_config_sync = 0; + } + + /*send if portchannel state change */ + if (lif->type == IF_T_PORT_CHANNEL && lif->changed) + { + /* Send port channel state information*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, lif); + iccp_csm_send(csm, g_csm_buf, len); + lif->changed = 0; + } + } + + /* Send MAC info if any*/ + mlacp_sync_send_syncMacInfo(csm); + + /* Send ARP info if any*/ + mlacp_sync_send_syncArpInfo(csm); + + /* Send Ndisc info if any */ + mlacp_sync_send_syncNdiscInfo(csm); + + /*If peer is warm reboot*/ + if (csm->peer_warm_reboot_time != 0) + { + /*Peer warm reboot timeout(connection is not broken more than 90s), recover to normal reboot*/ + if ((time(NULL) - csm->peer_warm_reboot_time) >= WARM_REBOOT_TIMEOUT) + { + csm->peer_warm_reboot_time = 0; + ICCPD_LOG_NOTICE(__FUNCTION__, "Peer warm reboot timeout, recover to normal reboot!"); + } + } + + return; +} diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c new file mode 100644 index 000000000000..8bc533e387bd --- /dev/null +++ b/src/iccpd/src/mlacp_link_handler.c @@ -0,0 +1,2413 @@ +/* + * mlacp_link_handler.c + * mLACP link handler + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_tlv.h" + +#include "../include/iccp_csm.h" +#include "mclagdctl/mclagdctl.h" +#include "../include/iccp_cmd_show.h" +#include "../include/iccp_netlink.h" +/***************************************** +* Enum +* +* ***************************************/ +typedef enum route_manipulate_type +{ + ROUTE_NONE, + ROUTE_ADD, + ROUTE_DEL +} ROUTE_MANIPULATE_TYPE_E; + +/***************************************** +* Global +* +* ***************************************/ +char g_ipv4_str[INET_ADDRSTRLEN]; +char g_ipv6_str[INET6_ADDRSTRLEN]; + +/***************************************** +* Tool : show ip string +* +* ***************************************/ +char *show_ip_str(uint32_t ipv4_addr) +{ + struct in_addr in_addr; + + memset(g_ipv4_str, 0, sizeof(g_ipv4_str)); + in_addr.s_addr = ipv4_addr; + inet_ntop(AF_INET, &in_addr, g_ipv4_str, INET_ADDRSTRLEN); + + return g_ipv4_str; +} + +char *show_ipv6_str(char *ipv6_addr) +{ + memset(g_ipv6_str, 0, sizeof(g_ipv6_str)); + inet_ntop(AF_INET6, ipv6_addr, g_ipv6_str, INET6_ADDRSTRLEN); + + return g_ipv6_str; +} + +static int getHwAddr(char *buff, char *mac) +{ + int i = 0; + unsigned int p[6]; + + if ( buff == NULL || mac == NULL ) + { + return MCLAG_ERROR; + } + + if (sscanf(mac, "%x:%x:%x:%x:%x:%x", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]) < 6) + { + return MCLAG_ERROR; + } + + for (i = 0; i < 6; i++) + { + buff[i] = p[i]; + } + + return 0; +} + +static int arp_set_handler(struct CSM* csm, + struct LocalInterface* lif, + int add) +{ + struct Msg* msg = NULL; + struct ARPMsg* arp_msg = NULL; + char mac_str[18] = ""; + + if (!csm || !lif) + return 0; + + if (add) + goto add_arp; + else + goto del_arp; + + /* Process Add */ + add_arp: + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return 0; + + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + mac_str[0] = '\0'; + arp_msg = (struct ARPMsg*)msg->buf; + + /* only process add*/ + if (arp_msg->op_type == NEIGH_SYNC_DEL) + continue; + + /* find the ARP for lif_list*/ + if (strcmp(lif->name, arp_msg->ifname) != 0) + continue; + + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], + arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); + + iccp_netlink_neighbor_request(AF_INET, (uint8_t *)&arp_msg->ipv4_addr, 1, arp_msg->mac_addr, arp_msg->ifname); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Add dynamic ARP to kernel [%s]", + show_ip_str(arp_msg->ipv4_addr));*/ + } + goto done; + + del_arp: + /* Process Del */ + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_msg = (struct ARPMsg*)msg->buf; + + /* find the ARP for lif_list*/ + if (strcmp(lif->name, arp_msg->ifname) != 0) + continue; + + /* don't process del*/ + if (arp_msg->op_type == NEIGH_SYNC_DEL) + continue; + + /* link broken, del all dynamic arp on the lif*/ + iccp_netlink_neighbor_request(AF_INET, (uint8_t *)&arp_msg->ipv4_addr, 0, arp_msg->mac_addr, arp_msg->ifname); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Del dynamic ARP [%s]", + show_ip_str(arp_msg->ipv4_addr));*/ + } + + done: + return 0; +} + +static int ndisc_set_handler(struct CSM *csm, struct LocalInterface *lif, int add) +{ + struct Msg *msg = NULL; + struct NDISCMsg *ndisc_msg = NULL; + char mac_str[18] = ""; + + if (!csm || !lif) + return 0; + + if (add) + goto add_ndisc; + else + goto del_ndisc; + + /* Process Add */ +add_ndisc: + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return 0; + + TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail) + { + mac_str[0] = '\0'; + ndisc_msg = (struct NDISCMsg *)msg->buf; + + /* only process add */ + if (ndisc_msg->op_type == NEIGH_SYNC_DEL) + continue; + + /* find the ND for lif_list */ + if (strcmp(lif->name, ndisc_msg->ifname) != 0) + continue; + + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", ndisc_msg->mac_addr[0], ndisc_msg->mac_addr[1], ndisc_msg->mac_addr[2], + ndisc_msg->mac_addr[3], ndisc_msg->mac_addr[4], ndisc_msg->mac_addr[5]); + + iccp_netlink_neighbor_request(AF_INET6, (uint8_t *)ndisc_msg->ipv6_addr, 1, ndisc_msg->mac_addr, ndisc_msg->ifname); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Add dynamic ND to kernel [%s]", show_ipv6_str((char *)ndisc_msg->ipv6_addr));*/ + } + goto done; + +del_ndisc: + /* Process Del */ + TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail) + { + ndisc_msg = (struct NDISCMsg *)msg->buf; + + /* find the ND for lif_list */ + if (strcmp(lif->name, ndisc_msg->ifname) != 0) + continue; + + /* don't process del */ + if (ndisc_msg->op_type == NEIGH_SYNC_DEL) + continue; + + /* link broken, del all dynamic ndisc on the lif */ + iccp_netlink_neighbor_request(AF_INET6, (uint8_t *)ndisc_msg->ipv6_addr, 0, ndisc_msg->mac_addr, ndisc_msg->ifname); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Del dynamic ND [%s]", show_ipv6_str((char *)ndisc_msg->ipv6_addr));*/ + } + +done: + return 0; +} + +/***************************************** + * Port-Channel Status Handler + * + ****************************************/ +static void set_route_by_linux_route(struct CSM* csm, + struct LocalInterface *local_if, + int is_add) +{ + /* TODO Need to remove this function + when set static route with zebra works fine*/ + + char ipv4_dest_str[INET_ADDRSTRLEN]; + char syscmd[128]; + char *ptr; + int ret = 0; + + /* enable kernel forwarding support*/ + system("echo 1 > /proc/sys/net/ipv4/ip_forward"); + + if (!csm || !local_if) + return; + + sprintf(ipv4_dest_str, "%s", show_ip_str(htonl(local_if->ipv4_addr))); + ptr = strrchr(ipv4_dest_str, '.'); + strcpy(ptr, ".0\0"); + + /* set gw route */ + /* sprintf(syscmd, "ip route %s %s/%d proto static metric 200 nexthop via %s > /dev/null 2>&1", */ + sprintf(syscmd, "ip route %s %s/%d metric 200 nexthop via %s > /dev/null 2>&1", + (is_add) ? "add" : "del", ipv4_dest_str, local_if->prefixlen, csm->peer_ip); + + ret = system(syscmd); + ICCPD_LOG_DEBUG(__FUNCTION__, "%s ret = %d", syscmd, ret); + + return; +} + +static void update_vlan_if_info(struct CSM *csm, + struct LocalInterface *local_if, + struct LocalInterface *vlan_if, + int po_state) +{ + if (!csm || !local_if || !vlan_if) + return; + + vlan_if->mlacp_state = MLACP(csm).current_state; + + return; +} + +static void update_l3_if_info(struct CSM *csm, + struct LocalInterface *local_if, + struct LocalInterface *l3_if, + int po_state) +{ + if (!csm || !l3_if) + return; + + l3_if->mlacp_state = MLACP(csm).current_state; + + return; +} + +static void update_po_if_info(struct CSM *csm, + struct LocalInterface *local_if, + int po_state) +{ + if (!csm || !local_if) + return; + + /* update local po info*/ + if (local_if->po_active != po_state) + { + local_if->changed = 1; + local_if->po_active = (po_state != 0); + /*printf("update po [%s=%d]\n",local_if->name, local_if->po_active);*/ + } + local_if->mlacp_state = MLACP(csm).current_state; + + return; +} + +static void set_l3_itf_state(struct CSM *csm, + struct LocalInterface *set_l3_local_if, + ROUTE_MANIPULATE_TYPE_E route_type) +{ + if (!csm || !set_l3_local_if) + return; + + if (set_l3_local_if && (route_type != ROUTE_NONE)) + { + /*set_default_route(csm);*/ + + /*ICCPD_LOG_DEBUG(__FUNCTION__, " route set Interface = %s route type = %d route = %s nexthop via = %s ", + set_l3_local_if->name, route_type, show_ip_str(htonl(set_l3_local_if->ipv4_addr)), csm->peer_ip );*/ + + /* set static route*/ + if (route_type == ROUTE_ADD) + { + /*set_route_by_linux_route(csm, set_l3_local_if, 1);*/ /*add static route by linux route tool*/ + /*If the L3 intf is not Vlan, del ARP; else wait ARP age*/ + if (strncmp(set_l3_local_if->name, VLAN_PREFIX, 4) != 0) + { + arp_set_handler(csm, set_l3_local_if, 0); /* del arp*/ + ndisc_set_handler(csm, set_l3_local_if, 0); /* del nd */ + } + } + else if (route_type == ROUTE_DEL) + { + /*set_route_by_linux_route(csm, set_l3_local_if, 0);*/ /*del static route by linux route tool*/ + arp_set_handler(csm, set_l3_local_if, 1); /* add arp*/ + ndisc_set_handler(csm, set_l3_local_if, 1); /* add nd */ + } + } + + return; +} + +static int peer_po_is_alive(struct CSM *csm, int po_ifindex) +{ + struct PeerInterface *pif = NULL; + int pif_active = 0; + + if (!csm) + return 0; + + LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) + { + if (pif->type != IF_T_PORT_CHANNEL) + continue; + if (pif->po_id != po_ifindex) + continue; + + if (pif->po_active) + pif_active = 1; /*pif alive*/ + break; + } + + return pif_active; +} + +static void mlacp_clean_fdb(void) +{ + struct IccpSyncdHDr * msg_hdr; + char *msg_buf = g_csm_buf; + + struct System *sys; + + sys = system_get_instance(); + if (sys == NULL) + return; + memset(msg_buf, 0, CSM_BUFFER_SIZE); + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver = 1; + msg_hdr->type = MCLAG_MSG_TYPE_FLUSH_FDB; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + if (sys->sync_fd) + write(sys->sync_fd, msg_buf, msg_hdr->len); + + ICCPD_LOG_NOTICE(__FUNCTION__, "Notify mclagsyncd to clear FDB"); + + return; +} + +void set_peerlink_mlag_port_learn(struct LocalInterface *lif, int enable) +{ + struct IccpSyncdHDr * msg_hdr; + mclag_sub_option_hdr_t * sub_msg; + char *msg_buf = g_csm_buf; + int msg_len; + struct System *sys; + + sys = system_get_instance(); + if (sys == NULL) + return; + + if (!lif) + return; + memset(msg_buf, 0, CSM_BUFFER_SIZE); + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver = 1; + msg_hdr->type = MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE; + + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + sub_msg = (mclag_sub_option_hdr_t*)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE; + + if (enable) + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE; + + msg_len = strlen(lif->name); + memcpy(sub_msg->data, lif->name, msg_len); + + sub_msg->op_len = msg_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; + + ICCPD_LOG_NOTICE(__FUNCTION__, "Send %s port MAC learn msg to mclagsyncd for %s", + sub_msg->op_type == MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE ? "DISABLE":"ENABLE", lif->name); + + /*send msg*/ + if (sys->sync_fd) + write(sys->sync_fd, msg_buf, msg_hdr->len); + + return; +} + +static void set_peerlink_mlag_port_kernel_forward( + struct CSM *csm, + struct LocalInterface *lif, + int enable) +{ + if (!csm || !csm->peer_link_if || !lif) + return; + + char cmd[256] = { 0 }; + + sprintf(cmd, "ebtables %s FORWARD -i %s -o %s -j DROP", + "-D", csm->peer_link_if->name, lif->name); + ICCPD_LOG_NOTICE(__FUNCTION__, " ebtable cmd %s", cmd ); + system(cmd); + + sprintf(cmd, "ebtables %s FORWARD -i %s -o %s -j DROP", + (enable) ? "-A" : "-D", csm->peer_link_if->name, lif->name); + ICCPD_LOG_NOTICE(__FUNCTION__, " ebtable cmd %s", cmd ); + system(cmd); + + return; +} + +void update_peerlink_isolate_from_all_csm_lif( + struct CSM* csm) +{ + struct LocalInterface *lif = NULL; + struct IccpSyncdHDr * msg_hdr; + mclag_sub_option_hdr_t * sub_msg; + char msg_buf[4096]; + struct System *sys; + + char mlag_po_buf[512]; + int src_len = 0, dst_len = 0; + + sys = system_get_instance(); + if (sys == NULL) + return; + + if (!csm || !csm->peer_link_if) + return; + + memset(msg_buf, 0, 4095); + memset(mlag_po_buf, 0, 511); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver = 1; + msg_hdr->type = MCLAG_MSG_TYPE_PORT_ISOLATE; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + /*sub msg src*/ + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_ISOLATE_SRC; + + if (csm->peer_link_if->type == IF_T_VXLAN) + { + /*TBD: vxlan tunnel port isolation will be supportted later*/ + return; +#if 0 + int begin_eth_port = 0; + + /*VTTNL0001;Ethernet0001,Ethernet0002*/ + /*src_len= strlen(csm->peer_link_if->name); */ + src_len += snprintf(src_buf + src_len, sizeof(src_buf) - src_len, "%s", csm->peer_link_if->name); + src_len += snprintf(src_buf + src_len, sizeof(src_buf) - src_len, "%s", ";"); + + /*traverse all ethernet port */ + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + if (lif->type != IF_T_PORT) + continue; + + /* need to isolate port, get it's name */ + if (begin_eth_port != 0) + { + src_len += snprintf(src_buf + src_len, sizeof(src_buf) - src_len, "%s", ","); + } + + src_len += snprintf(src_buf + src_len, sizeof(src_buf) - src_len, "%s", lif->name); + begin_eth_port = 1; + } + memcpy(sub_msg->data, src_buf, src_len); + + ICCPD_LOG_DEBUG(__FUNCTION__, "isolate src %s, data %s, len %d", src_buf, sub_msg->data, src_len); +#endif + } + else + { + src_len = strlen(csm->peer_link_if->name); + memcpy(sub_msg->data, csm->peer_link_if->name, src_len); + } + sub_msg->op_len = src_len; + + /*sub msg dst */ + msg_hdr->len += sub_msg->op_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_ISOLATE_DST; + + /*traverse all portchannel member port and send msg to syncd */ + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type != IF_T_PORT_CHANNEL) + continue; + + /* check pif port state and lif pochannel state */ + if (lif->isolate_to_peer_link == 1) + { + /* need to isolate port, get it's member name */ + if (strlen(mlag_po_buf) != 0) + dst_len += snprintf(mlag_po_buf + dst_len, sizeof(mlag_po_buf) - dst_len, "%s", ","); + + dst_len += snprintf(mlag_po_buf + dst_len, sizeof(mlag_po_buf) - dst_len, "%s", lif->portchannel_member_buf); + } + } + + sub_msg->op_len = dst_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; + + if (dst_len) + { + memcpy(sub_msg->data, mlag_po_buf, dst_len); + ICCPD_LOG_NOTICE(__FUNCTION__, "Send port isolate msg to mclagsyncd, src port %s, dst port %s", csm->peer_link_if->name, mlag_po_buf); + } + else + { + ICCPD_LOG_NOTICE(__FUNCTION__, "Send port isolate msg to mclagsyncd, src port %s, dst port is NULL", csm->peer_link_if->name); + } + + /*send msg*/ + if (sys->sync_fd) + write(sys->sync_fd, msg_buf, msg_hdr->len); + + return; +} + +static void set_peerlink_mlag_port_isolate( + struct CSM *csm, + struct LocalInterface *lif, + int enable) +{ + if (!lif) + return; + + lif->isolate_to_peer_link = enable; + + if (!csm || !csm->peer_link_if ) + return; + + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + + ICCPD_LOG_DEBUG(__FUNCTION__, "%s port-isolate from %s to %s", + enable ? "Enable" : "Disable", csm->peer_link_if->name, lif->name); + update_peerlink_isolate_from_all_csm_lif(csm); + + /* Kernel also needs to block traffic from peerlink to mlag-port*/ + set_peerlink_mlag_port_kernel_forward(csm, lif, enable); + + return; +} + +void peerlink_port_isolate_cleanup(struct CSM* csm) +{ + struct LocalInterface *local_if = NULL; + + if (!csm) + return; + + /* Clean all port block*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) + { + set_peerlink_mlag_port_isolate(csm, local_if, 0); + } + } + + return; +} + +void update_peerlink_isolate_from_pif( + struct CSM *csm, + struct PeerInterface *pif, + int pif_po_state, + int new_create) +{ + struct LocalInterface *lif = NULL; + int lif_po_state = 1; + + if (!csm || !csm->peer_link_if || !pif) + return; + if (new_create == 0 && pif_po_state == pif->po_active) + return; + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + + /* peer link changed*/ + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (strcmp(lif->name, pif->name) != 0) + continue; + + lif_po_state = lif->po_active; + break; + } + + if (!lif) + { + ICCPD_LOG_WARN(__FUNCTION__, "Can't find local if for %s", pif->name); + return; + } + + ICCPD_LOG_DEBUG(__FUNCTION__, "From if %s local(%s) / peer(%s)", + lif->name, + (lif_po_state) ? "up" : "down", + (pif_po_state) ? "up" : "down"); + + if (lif_po_state == 1) + { + if (pif_po_state == 1) + { + /* both peer-pair link up, enable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Enable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 1); + } + else + { + /* local link up, and peer link changes to down, disable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Disable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 0); + } + } + else + { + ;/* local link down, do nothing*/ + } + + return; +} + +static void update_peerlink_isolate_from_lif( + struct CSM* csm, + struct LocalInterface* lif, + int lif_po_state) +{ + struct PeerInterface *pif = NULL; + int pif_po_state = 1; + + if (!csm || !csm->peer_link_if || !lif) + return; + /*if (lif_po_state == lif->po_active) return;*/ + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + + /* local link changed*/ + LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) + { + if (strcmp(pif->name, lif->name) != 0) + continue; + + pif_po_state = pif->po_active; + break; + } + + ICCPD_LOG_DEBUG(__FUNCTION__, "From if %s local(%s) / peer(%s)", + lif->name, (lif_po_state) ? "up" : "down", (pif_po_state) ? "up" : "down"); + + if (lif_po_state == 1) + { + if (pif_po_state == 1) + { + /* both peer-pair link up, enable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Enable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 1); + } + else + { + /* peer link down, local link changes to up, disable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, " Disable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 0); + } + } + else + { + ;/* local link down, do nothing*/ + } + + return; +} + +static void update_l2_po_state(struct CSM *csm, + struct LocalInterface *lif, + int po_state) +{ + ROUTE_MANIPULATE_TYPE_E route_type = ROUTE_NONE; + struct VLAN_ID *vlan = NULL; + struct LocalInterface *set_l3_vlan_if = NULL; + + if (!csm || !lif) + return; + + /*L2 po*/ + /*if (po_state != lif->po_active && po_state == 0) + { + mlacp_clean_fdb(); + }*/ + + /*Is there any L3 vlan over L2 po?*/ + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + route_type = ROUTE_NONE; + + if (!vlan->vlan_itf) + continue; + + /* If the po is under a vlan, update vlan state first*/ + update_vlan_if_info(csm, lif, vlan->vlan_itf, po_state); + + if (!local_if_is_l3_mode(vlan->vlan_itf)) + continue; + + /*NOTE + * assume only one mlag per vlan + * need to add rules for per mlag per vlan later (arp list?) + */ + set_l3_vlan_if = vlan->vlan_itf; + if (po_state != lif->po_active + || MLACP(csm).current_state != set_l3_vlan_if->mlacp_state) + { + if (po_state == 1) + { + route_type = ROUTE_DEL; + } + else if (po_state == 0 + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + if (peer_po_is_alive(csm, lif->ifindex) == 1) + route_type = ROUTE_ADD; + } + } + + /*update_po_arp_list(csm, set_l3_vlan_if);*/ + set_l3_itf_state(csm, set_l3_vlan_if, route_type); + update_l3_if_info(csm, lif, set_l3_vlan_if, po_state); + } + + return; +} + +static void update_l3_po_state(struct CSM *csm, + struct LocalInterface *lif, + int po_state) +{ + ROUTE_MANIPULATE_TYPE_E route_type = ROUTE_NONE; + struct LocalInterface *set_l3_lif = NULL; + + /*L3 po*/ + set_l3_lif = lif; + + if (!csm || !lif) + return; + + if (po_state != lif->po_active + && po_state == 1) + { + /* po alive, clean static route & recover the ARP*/ + route_type = ROUTE_DEL; + } + else if (po_state != lif->po_active + && po_state == 0 + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /* po is not alive & peer-link alive, set static route*/ + if (peer_po_is_alive(csm, lif->po_id) == 1) + route_type = ROUTE_ADD; + } + else if (MLACP(csm).current_state != lif->mlacp_state + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE + && po_state == 0) + { + /* when peer-pair link ready, set static route for broken po link*/ + if (peer_po_is_alive(csm, lif->po_id) == 1) + route_type = ROUTE_ADD; + } + + /*update_po_arp_list(csm, set_l3_lif);*/ + set_l3_itf_state(csm, set_l3_lif, route_type); + update_l3_if_info(csm, lif, set_l3_lif, po_state); + + return; +} + +int is_local_vlan_on(struct VLAN_ID* vlan_id_list) +{ + if (!vlan_id_list->vlan_itf) + return 0; + + return 1; +} + +void syn_arp_info_to_peer(struct CSM *csm, struct LocalInterface *local_if) +{ + struct Msg *msg = NULL; + struct ARPMsg *arp_msg = NULL, *arp_info = NULL; + struct Msg *msg_send = NULL; + + if (!csm || !local_if) + return; + + if (!TAILQ_EMPTY(&(MLACP(csm).arp_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_info = (struct ARPMsg*)msg->buf; + + if (strcmp(arp_info->ifname, local_if->name) != 0) + continue; + + arp_msg = (struct ARPMsg*)msg->buf; + arp_msg->op_type = NEIGH_SYNC_ADD; + + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + /*ICCPD_LOG_DEBUG( __FUNCTION__, "Enqueue ARP[ADD] for %s", + show_ip_str(htonl(arp_msg->ipv4_addr)));*/ + } + else + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + } + + return; +} + +void syn_ndisc_info_to_peer(struct CSM *csm, struct LocalInterface *local_if) +{ + struct Msg *msg = NULL; + struct NDISCMsg *ndisc_msg = NULL, *ndisc_info = NULL; + struct Msg *msg_send = NULL; + + if (!csm || !local_if) + return; + + if (!TAILQ_EMPTY(&(MLACP(csm).ndisc_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail) + { + ndisc_info = (struct NDISCMsg *)msg->buf; + + if (strcmp(ndisc_info->ifname, local_if->name) != 0) + continue; + + ndisc_msg = (struct NDISCMsg *)msg->buf; + ndisc_msg->op_type = NEIGH_SYNC_ADD; + + if (iccp_csm_init_msg(&msg_send, (char *)ndisc_msg, sizeof(struct NDISCMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_msg_list), msg_send, tail); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ND[ADD] for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr));*/ + } + else + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ND[ADD] for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); + } + } + + return; +} +void update_stp_peer_link(struct CSM *csm, + struct PeerInterface *pif, + int po_state, int new_create) +{ + struct LocalInterface *lif = NULL; + struct VLAN_ID *vlan = NULL; + + if (!csm || !pif) + return; + if (new_create == 0 && po_state == pif->po_active) + return; + + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (strcmp(lif->name, pif->name) != 0) + continue; + + /* update lif route if pif link status changes */ + if (local_if_is_l3_mode(lif)) + { + if (po_state == 1 && lif->po_active == 0) + set_l3_itf_state(csm, lif, ROUTE_ADD); + else if (po_state == 0 && lif->po_active == 0) + set_l3_itf_state(csm, lif, ROUTE_DEL); + + /*If pif change to active, and local is also active, syn arp to peer*/ + if (po_state == 1 && lif->po_active == 1) + { + syn_arp_info_to_peer(csm, lif); + syn_ndisc_info_to_peer(csm, lif); + } + } + else + { + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if (!is_local_vlan_on(vlan)) + continue; + if (!local_if_is_l3_mode(vlan->vlan_itf)) + continue; + + /*NOTE + * assume only one mlag per bridge + * need to add rules for per mlag per bridge later (arp list?) + */ + if (po_state == 1 && lif->po_active == 0) + set_l3_itf_state(csm, vlan->vlan_itf, ROUTE_ADD); + else if (po_state == 0 && lif->po_active == 0) + set_l3_itf_state(csm, vlan->vlan_itf, ROUTE_DEL); + + /*If pif change to active, and local is also active, syn arp to peer*/ + if (po_state == 1 && lif->po_active == 1) + { + syn_arp_info_to_peer(csm, vlan->vlan_itf); + syn_ndisc_info_to_peer(csm, vlan->vlan_itf); + } + } + } + + break; + } + + return; +} + +void iccp_get_fdb_change_from_syncd( void) +{ + struct IccpSyncdHDr * msg_hdr; + char msg_buf[512]; + struct System *sys; + + sys = system_get_instance(); + if (sys == NULL) + return; + + memset(msg_buf, 0, 512); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver = 1; + msg_hdr->type = MCLAG_MSG_TYPE_GET_FDB_CHANGES; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Send get fdb change msg to mclagsyncd"); + + /*send msg*/ + if (sys->sync_fd > 0) + write(sys->sync_fd, msg_buf, msg_hdr->len); + + return; +} + +void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg, uint8_t mac_type) +{ + struct IccpSyncdHDr * msg_hdr; + char msg_buf[512]; + struct System *sys; + struct mclag_fdb_info * mac_info; + + sys = system_get_instance(); + if (sys == NULL) + return; + + memset(msg_buf, 0, 512); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver = 1; + msg_hdr->type = MCLAG_MSG_TYPE_SET_FDB; + + /*mac msg */ + mac_info = (struct mclag_fdb_info *)&msg_buf[sizeof(struct IccpSyncdHDr)]; + mac_info->vid = mac_msg->vid; + memcpy(mac_info->port_name, mac_msg->ifname, MAX_L_PORT_NAME); + memcpy(mac_info->mac, mac_msg->mac_str, ETHER_ADDR_STR_LEN); + mac_info->type = mac_type; + mac_info->op_type = mac_msg->op_type; + msg_hdr->len = sizeof(struct IccpSyncdHDr) + sizeof(struct mclag_fdb_info); + + ICCPD_LOG_NOTICE(__FUNCTION__, "Send mac %s msg to mclagsyncd, vid %d ; ifname %s ; mac %s; type %s", + mac_info->op_type == MAC_SYNC_ADD ? "add" : "del", mac_info->vid, mac_info->port_name, mac_info->mac, mac_info->type == MAC_TYPE_STATIC ? "static" : "dynamic"); + + /*send msg*/ + if (sys->sync_fd > 0 ) + write(sys->sync_fd, msg_buf, msg_hdr->len); + + return; +} + +void add_mac_to_chip(struct MACMsg* mac_msg, uint8_t mac_type) +{ + mac_msg->op_type = MAC_SYNC_ADD; + iccp_send_fdb_entry_to_syncd( mac_msg, mac_type); + + return; +} + +void del_mac_from_chip(struct MACMsg* mac_msg) +{ + mac_msg->op_type = MAC_SYNC_DEL; + iccp_send_fdb_entry_to_syncd( mac_msg, mac_msg->fdb_type); + + return; +} + +uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t set ) +{ + uint8_t new_age_flag = 0; + struct Msg *msg = NULL; + + new_age_flag = mac_msg->age_flag; + + if (set == 0)/*remove age flag*/ + { + new_age_flag &= ~MAC_AGE_LOCAL; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove local age flag: %d ifname %s, add %s vlan-id %d, age_flag %d", + new_age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + + /*send mac MAC_SYNC_ADD message to peer*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag);*/ + } + else + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue MAC-msg-list: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } + else/*set age flag*/ + { + new_age_flag |= MAC_AGE_LOCAL; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Add local age flag: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + + /*send mac MAC_SYNC_DEL message to peer*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + mac_msg->op_type = MAC_SYNC_DEL; + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag);*/ + } + else + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue MAC-msg-list: %s, del %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } + + return new_age_flag; +} + +/*Deal with mac add,del,move when portchannel up or down*/ +static void update_l2_mac_state(struct CSM *csm, + struct LocalInterface *lif, + int po_state) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + + if (!csm || !lif) + return; + + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*)msg->buf; + + /* find the MAC for this interface*/ + if (strcmp(lif->name, mac_msg->origin_ifname) != 0) + continue; + + /*portchannel down*/ + if (po_state == 0) + { + ICCPD_LOG_NOTICE(__FUNCTION__, "Intf %s down, age local MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); + + if (mac_msg->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) + { + /*send mac del message to mclagsyncd.*/ + if (mac_msg->fdb_type != MAC_TYPE_STATIC) + del_mac_from_chip(mac_msg); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s down, del MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + /*If local and peer both aged, del the mac*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + else + { + /*If local is aged but peer is not aged, redirect the mac to peer-link*/ + if (strlen(csm->peer_itf_name) != 0) + { + /*Send mac add message to mclagsyncd. fdb_type is not changed*/ + /*Is need to delete the old item before add?(Old item probably is static)*/ + if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) + { + memcpy(mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + } + else + { + /*must redirect but peerlink is down, del mac from ASIC*/ + /*if peerlink change to up, mac will add back to ASIC*/ + del_mac_from_chip(mac_msg); + memcpy(mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + } + + ICCPD_LOG_NOTICE(__FUNCTION__, "Intf %s down, redirect MAC %s vlan-id %d to peer-link %s", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, csm->peer_itf_name); + } + else + { + /*peer-link is not configured, del mac from ASIC, mac still in mac_list*/ + del_mac_from_chip(mac_msg); + + ICCPD_LOG_NOTICE(__FUNCTION__, "Intf %s down, peer-link is not configured: MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + } + } + } + else /*portchannel up*/ + { + /*the old item is redirect to peerlink for portchannel down*/ + /*when this portchannel up, recover the mac back*/ + if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) + { + ICCPD_LOG_NOTICE(__FUNCTION__, "Intf %s up, redirect MAC %s vlan-id %d from peerlink to %s", + mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->origin_ifname); + + /*Remove MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 0); + + /*Reverse interface from peer-link to the original portchannel*/ + memcpy(mac_msg->ifname, mac_msg->origin_ifname, MAX_L_PORT_NAME); + + /*Send dynamic or static mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, mac_msg->fdb_type); + } + else + { + /*this may be peerlink is not configured and portchannel is down*/ + /*when this portchannel up, add the mac back to ASIC*/ + ICCPD_LOG_NOTICE(__FUNCTION__, "Intf %s up, add MAC %s vlan-id %d to ASIC", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + /*Remove MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 0); + + /*Send dynamic or static mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, mac_msg->fdb_type); + } + } + } + + return; +} + +void mlacp_portchannel_state_handler(struct CSM* csm, + struct LocalInterface* local_if, + int po_state) +{ + if (!csm || !local_if) + return; + + update_peerlink_isolate_from_lif(csm, local_if, po_state); + + update_l2_mac_state(csm, local_if, po_state); + + if (!local_if_is_l3_mode(local_if)) + update_l2_po_state(csm, local_if, po_state); + else + update_l3_po_state(csm, local_if, po_state); + + update_po_if_info(csm, local_if, po_state); + + return; +} + +static void mlacp_conn_handler_fdb(struct CSM* csm) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + struct Msg *msg_send = NULL; + + if (!csm) + return; + + if (!TAILQ_EMPTY(&(MLACP(csm).mac_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*)msg->buf; + + /*Wait the ACK from peer?*/ + /*mac_msg->age_flag &= ~MAC_AGE_PEER;*/ + + /*If MAC with local age flag, dont sync to peer. Such MAC only exist when peer is warm-reboot. + If peer is warm-reboot, peer age flag is not set when connection is lost. + When MAC is aged in local switch, this MAC is not deleted for no peer age flag. + After warm-reboot, this MAC must be learnt by peer and sync to local switch*/ + if (!(mac_msg->age_flag & MAC_AGE_LOCAL)) + { + /*Send mac add message to peer*/ + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + } + } + else + { + /*If MAC with local age flag and is point to MCLAG enabled port, reomove local age flag*/ + if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list not enqueue for local age flag: %s, mac %s vlan-id %d, remove local age flag", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + mac_msg->age_flag &= ~MAC_AGE_LOCAL; + } + } + } + } + + return; +} + +static void mlacp_fix_bridge_mac(struct CSM* csm) +{ + char syscmd[128]; + int ret = 0; + char macaddr[64]; + uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + if (memcmp(MLACP(csm).system_id, null_mac, ETHER_ADDR_LEN) != 0) + { + memset(macaddr, 0, 64); + snprintf(macaddr, 64, "%02x:%02x:%02x:%02x:%02x:%02x", + MLACP(csm).system_id[0], MLACP(csm).system_id[1], MLACP(csm).system_id[2], + MLACP(csm).system_id[3], MLACP(csm).system_id[4], MLACP(csm).system_id[5]); + + /*When changing the mac of a vlan member port, the mac of Bridge will be changed.*/ + /*The Bridge mac can not be the same as peer system id, so fix the Bridge MAC address here.*/ + sprintf(syscmd, "ip link set dev Bridge address %s > /dev/null 2>&1", macaddr); + ret = system(syscmd); + ICCPD_LOG_NOTICE(__FUNCTION__, " %s ret = %d", syscmd, ret); + } + + return; +} + +/***************************************** +* Peer connect/disconnect handler +* +* ***************************************/ +void mlacp_peer_conn_handler(struct CSM* csm) +{ + struct LocalInterface *lif = NULL; + static int once_connected = 0; + struct System* sys = NULL; + + if (!csm) + return; + + if ((sys = system_get_instance()) == NULL) + return; + + if (csm->warm_reboot_disconn_time != 0) + { + /*If peer reconnected, reset peer disconnect time*/ + csm->warm_reboot_disconn_time = 0; + ICCPD_LOG_NOTICE(__FUNCTION__, "Peer warm reboot and reconnect, reset peer disconnect time!"); + } + + if (csm->peer_link_if) + { + set_peerlink_mlag_port_learn(csm->peer_link_if, 0); + } + + /*If peer connect again, don't flush FDB*/ + if (once_connected == 0) + { + once_connected = 1; + mlacp_fix_bridge_mac(csm); + /*If warm reboot, don't flush FDB*/ + if (sys->warmboot_start != WARM_REBOOT) + mlacp_clean_fdb(); + } + + iccp_get_fdb_change_from_syncd(); + sys->csm_trans_time = time(NULL); + + mlacp_conn_handler_fdb(csm); + + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type == IF_T_PORT_CHANNEL) + { + mlacp_portchannel_state_handler(csm, lif, (lif->state == PORT_STATE_UP) ? 1 : 0); + } + } + + return; +} + +extern void recover_if_ipmac_on_standby(struct LocalInterface* lif_po); +void mlacp_peer_disconn_handler(struct CSM* csm) +{ + uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + struct LocalInterface* lif = NULL; + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + struct System* sys = NULL; + + if (!csm) + return; + + if ((sys = system_get_instance()) == NULL) + return; + + /*If warm reboot, don't change FDB and MAC address*/ + if (sys->warmboot_exit == WARM_REBOOT) + return; + + /*If peer is warm reboot, don't change FDB*/ + if (csm->peer_warm_reboot_time != 0) + { + /*If peer disconnected, recover peer to normal reboot for next time*/ + csm->peer_warm_reboot_time = 0; + /*peer connection must be establised again within 90s + from last disconnection for peer warm reboot*/ + time(&csm->warm_reboot_disconn_time); + ICCPD_LOG_NOTICE(__FUNCTION__, "Peer warm reboot and disconnect, recover to normal reboot for next time!"); + return; + } + + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*)msg->buf; + + mac_msg->age_flag |= MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + /* find the MAC that the port is peer-link or local and peer both aged, to be deleted*/ + if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0 && mac_msg->age_flag != (MAC_AGE_LOCAL | MAC_AGE_PEER)) + continue; + + ICCPD_LOG_NOTICE(__FUNCTION__, "Peer disconnect, del MAC for peer-link: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + /*Send mac del message to mclagsyncd, may be already deleted*/ + del_mac_from_chip(mac_msg); + + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + + /* Clean all port block*/ + peerlink_port_isolate_cleanup(csm); + + memcpy(MLACP(csm).remote_system.system_id, null_mac, ETHER_ADDR_LEN); + + /*If peer is disconnected, recover the MAC address.*/ + if (csm->role_type == STP_ROLE_STANDBY) + { + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + recover_if_ipmac_on_standby(lif); + } + } + + return; +} + +void mlacp_peerlink_up_handler(struct CSM* csm) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + + if (!csm) + return; + + /*If peer link up, set all the mac that point to the peer-link in ASIC*/ + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*)msg->buf; + + /* Find the MAC that the port is peer-link to be added*/ + if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) + continue; + + ICCPD_LOG_NOTICE(__FUNCTION__, "Peer link up, add MAC to ASIC for peer-link: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + /*Send mac add message to mclagsyncd, local age flag is already set*/ + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + } + + return; +} + +void mlacp_peerlink_down_handler(struct CSM* csm) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + + if (!csm) + return; + + /*If peer link down, remove all the mac that point to the peer-link*/ + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*)msg->buf; + + /* Find the MAC that the port is peer-link to be deleted*/ + if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) + continue; + + ICCPD_LOG_NOTICE(__FUNCTION__, "Peer link down, del MAC for peer-link: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); + + /*Send mac del message to mclagsyncd*/ + del_mac_from_chip(mac_msg); + + /*If peer is not age, keep the MAC in mac_list, but ASIC is deleted*/ + if (mac_msg->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) + { + /*If local and peer both aged, del the mac*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + } + + return; +} + +/***************************************** +* Po add/remove handler +* +*****************************************/ +void mlacp_mlag_link_add_handler(struct CSM *csm, struct LocalInterface *lif) +{ + if (!csm || !lif) + return; + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + + set_peerlink_mlag_port_isolate(csm, lif, 1); + + return; +} + +void mlacp_mlag_link_del_handler(struct CSM *csm, struct LocalInterface *lif) +{ + if (!csm || !lif) + return; + + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + + set_peerlink_mlag_port_isolate(csm, lif, 0); + + return; +} + +int iccp_connect_syncd() +{ + struct System* sys = NULL; + int ret = 0; + int fd = 0; + struct sockaddr_in serv; + static int count = 0; + struct epoll_event event; + + if ((sys = system_get_instance()) == NULL) + goto conn_fail; + + if (sys->sync_fd >= 0) + return 0; + + /*Print the fail log message every 60s*/ + if (count >= 600) + { + count = 0; + } + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) + { + if (count == 0) + ICCPD_LOG_WARN(__FUNCTION__, "Failed to create unix socket: %s", strerror(errno)); + goto conn_fail; + } + + /* Make server socket. */ + memset(&serv, 0, sizeof(serv)); + serv.sin_family = AF_INET; + serv.sin_port = htons(2626); +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + serv.sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ + serv.sin_addr.s_addr = htonl(0x7f000006); + + ret = connect(fd, (struct sockaddr *)&serv, sizeof(serv)); + if (ret < 0) + { + if (count == 0) + ICCPD_LOG_WARN(__FUNCTION__, "Failed to connect to mclag syncd: errno str %s", strerror(errno)); + close(fd); + goto conn_fail; + } + + ICCPD_LOG_NOTICE(__FUNCTION__, "Success to link syncd"); + sys->sync_fd = fd; + + event.data.fd = fd; + event.events = EPOLLIN; + ret = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, fd, &event); + + count = 0; + return 0; + + conn_fail: + if (count == 0) + ICCPD_LOG_DEBUG(__FUNCTION__, "Mclag syncd socket connect fail"); + + count++; + + return MCLAG_ERROR; +} + +void syncd_info_close() +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + if (sys->sync_fd > 0) + { + close(sys->sync_fd); + sys->sync_fd = -1; + } + + return; +} + +int iccp_get_receive_fdb_sock_fd(struct System *sys) +{ + return sys->sync_fd; +} + +/*When received MAC add and del packets from mclagsyncd, update mac information*/ +void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, char *ifname, uint8_t fdb_type, uint8_t op_type) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct MACMsg *mac_msg = NULL, *mac_info = NULL; + uint8_t mac_exist = 0; + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + uint8_t from_mclag_intf = 0;/*0: orphan port, 1: MCLAG port*/ + struct CSM *first_csm = NULL; + + struct LocalInterface *lif_po = NULL, *mac_lif = NULL; + + if (!(sys = system_get_instance())) + return; + + /* create MAC msg*/ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct MACMsg); + mac_msg = (struct MACMsg*)buf; + mac_msg->op_type = op_type; + mac_msg->fdb_type = fdb_type; + sprintf(mac_msg->mac_str, "%s", mac_str); + mac_msg->vid = vid; + + mac_msg->age_flag = 0; + + ICCPD_LOG_NOTICE(__FUNCTION__, "Recv MAC msg from mclagsyncd, vid %d mac %s port %s optype %s ", vid, mac_str, ifname, op_type == MAC_SYNC_ADD ? "add" : "del"); + + /* Find MLACP itf, may be mclag enabled port-channel*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (csm && !first_csm) + { + /*Record the first CSM, only one CSM in the system currently*/ + first_csm = csm; + } + + /*If MAC is from peer-link, break; peer-link is not in MLACP(csm).lif_list*/ + if (strcmp(ifname, csm->peer_itf_name) == 0) + break; + + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if (strcmp(lif_po->name, ifname) == 0) + { + from_mclag_intf = 1; + break; + } + } + + if (from_mclag_intf == 1) + break; + } + + if (!first_csm) + return; + + /*If support multiple CSM, the MAC list of orphan port must be moved to sys->mac_list*/ + csm = first_csm; + + /* find lif MAC+vid*/ + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_info = (struct MACMsg*)msg->buf; + + /*MAC and vid are equal*/ + if (strcmp(mac_info->mac_str, mac_str) == 0 && mac_info->vid == vid) + { + mac_exist = 1; + break; + } + } + + /*handle mac add*/ + if (op_type == MAC_SYNC_ADD) + { + /* Find local itf*/ + if (!(mac_lif = local_if_find_by_name(ifname))) + return; + + sprintf(mac_msg->ifname, "%s", ifname); + sprintf(mac_msg->origin_ifname, "%s", ifname); + + /*same MAC exist*/ + if (mac_exist) + { + /*If the recv mac port is peer-link, that is add from iccpd, no need to handle*/ + if (strcmp(csm->peer_itf_name, mac_msg->ifname) == 0) + { + return; + } + + /*If the current mac port is peer-link, it will handle by port up event*/ + /*if(strcmp(csm->peer_itf_name, mac_info->ifname) == 0) + { + return; + }*/ + + /* update MAC*/ + if (mac_info->fdb_type != mac_msg->fdb_type + || strcmp(mac_info->ifname, mac_msg->ifname) != 0 + || strcmp(mac_info->origin_ifname, mac_msg->ifname) != 0) + { + mac_info->fdb_type = mac_msg->fdb_type; + sprintf(mac_info->ifname, "%s", mac_msg->ifname); + sprintf(mac_info->origin_ifname, "%s", mac_msg->ifname); + + /*Remove MAC_AGE_LOCAL flag*/ + mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 0); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Update MAC for %s, ifname %s", mac_msg->mac_str, mac_msg->ifname); + } + else + { + /*All info are the same, Remove MAC_AGE_LOCAL flag, then return*/ + /*In theory, this will be happened that mac age and then learn*/ + mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 0); + + return; + } + } + else/*same MAC not exist*/ + { + /*If the port the mac learn is change to down before the mac + sync to iccp, this mac must be deleted */ + if (mac_lif->state == PORT_STATE_DOWN) + { + del_mac_from_chip(mac_msg); + + return; + } + + /*set MAC_AGE_PEER flag before send this item to peer*/ + mac_msg->age_flag |= MAC_AGE_PEER; + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag);*/ + mac_msg->op_type = MAC_SYNC_ADD; + + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + struct Msg *msg_send = NULL; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, msg_len) == 0) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + + /*ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag);*/ + } + else + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue MAC-msg-list: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + } + } + + /*enqueue mac to mac-list*/ + if (iccp_csm_init_msg(&msg, (char*)mac_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_list), msg, tail); + + /*ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-list enqueue: %s, add %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);*/ + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue MAC %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + } + } + else/*handle mac del*/ + { + /*same MAC exist*/ + if (mac_exist) + { + /*orphan port mac or origin from_mclag_intf but state is down*/ + if (strcmp(mac_info->ifname, csm->peer_itf_name) == 0) + { + /*Set MAC_AGE_LOCAL flag*/ + mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 1); + + if (mac_info->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(peer-link), del %s vlan-id %d", + mac_info->ifname, mac_info->mac_str, mac_info->vid); + + /*If peer link is down, del the mac*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + else if (csm->peer_link_if && csm->peer_link_if->state != PORT_STATE_DOWN) + { + /*peer-link learn mac is control by iccpd, ignore the chip del info*/ + add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); + + ICCPD_LOG_NOTICE(__FUNCTION__, "Recv MAC del msg: %s(peer-link is up), add back %s vlan-id %d", + mac_info->ifname, mac_info->mac_str, mac_info->vid); + } + + return; + } + + /*Add MAC_AGE_LOCAL flag*/ + mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 1); + + if (mac_info->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d", + mac_info->ifname, mac_info->mac_str, mac_info->vid); + + /*If local and peer both aged, del the mac (local orphan mac is here)*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + else + { + ICCPD_LOG_NOTICE(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d, peer is not age, add back to chip", + mac_info->ifname, mac_info->mac_str, mac_info->vid); + + mac_info->fdb_type = MAC_TYPE_DYNAMIC; + + if (from_mclag_intf && lif_po && lif_po->state == PORT_STATE_DOWN) + { + /*If local if is down, redirect the mac to peer-link*/ + if (strlen(csm->peer_itf_name) != 0) + { + memcpy(&mac_info->ifname, csm->peer_itf_name, IFNAMSIZ); + + if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) + { + add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); + ICCPD_LOG_NOTICE(__FUNCTION__, "Recv MAC del msg: %s(down), del %s vlan-id %d, redirect to peer-link", + mac_info->ifname, mac_info->mac_str, mac_info->vid); + } + } + + return; + } + + /*If local is aged but peer is not aged, Send mac add message to mclagsyncd*/ + /*it is from_mclag_intf and port state is up, local orphan mac can not be here*/ + /* Find local itf*/ + if (!(mac_lif = local_if_find_by_name(mac_info->ifname))) + return; + if (mac_lif->state == PORT_STATE_UP) + add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); + } + } + } + + return; +} + +int iccp_receive_fdb_handler_from_syncd(struct System *sys) +{ + char *msg_buf = g_csm_buf; + struct IccpSyncdHDr *msg_hdr; + struct mclag_fdb_info * mac_info; + size_t pos = 0; + int count = 0; + int i = 0; + int n = 0; + + if (sys == NULL) + return MCLAG_ERROR; + + memset(msg_buf, 0, CSM_BUFFER_SIZE); + + n = read(sys->sync_fd, msg_buf, CSM_BUFFER_SIZE); + if (n <= 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "read msg error!!!" ); + return MCLAG_ERROR; + } + + while (pos < n) + { + msg_hdr = (struct IccpSyncdHDr *)&msg_buf[pos]; + if (msg_hdr->ver != 1 || msg_hdr->type != MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION ) + { + ICCPD_LOG_ERR(__FUNCTION__, "msg version or type wrong!!!!! "); + return MCLAG_ERROR; + } + + count = ( msg_hdr->len - sizeof(struct IccpSyncdHDr )) / sizeof(struct mclag_fdb_info); + ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d ", count); + + for (i = 0; i < count; i++) + { + mac_info = (struct mclag_fdb_info *)&msg_buf[pos + sizeof(struct IccpSyncdHDr ) + i * sizeof(struct mclag_fdb_info)]; + /*ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d vid %d mac %s port %s optype %s ", i, mac_info->vid, mac_info->mac, mac_info->port_name, mac_info->op_type == MAC_SYNC_ADD ? "add" : "del");*/ + do_mac_update_from_syncd(mac_info->mac, mac_info->vid, mac_info->port_name, mac_info->type, mac_info->op_type); + } + + pos += msg_hdr->len; + } + + return 0; +} + +char * mclagd_ctl_cmd_str(int req_type) +{ + switch (req_type) + { + case INFO_TYPE_DUMP_STATE: + return "dump config"; + + case INFO_TYPE_DUMP_ARP: + return "dump arp"; + + case INFO_TYPE_DUMP_NDISC: + return "dump nd"; + + case INFO_TYPE_DUMP_MAC: + return "dump mac"; + + case INFO_TYPE_DUMP_LOCAL_PORTLIST: + return "dump local portlist"; + + case INFO_TYPE_DUMP_PEER_PORTLIST: + return "dump peer portlist"; + + case INFO_TYPE_CONFIG_LOGLEVEL: + return "config loglevel"; + default: + break; + } + + return "error req type"; +} + +int mclagd_ctl_sock_create() +{ + struct sockaddr_un addr; + struct System* sys = NULL; + struct epoll_event event; + int addr_len; + int ret = 0; + + if ((sys = system_get_instance()) == NULL) + return MCLAG_ERROR; + + if (sys->sync_ctrl_fd > 0) + return sys->sync_ctrl_fd; + + sys->sync_ctrl_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sys->sync_ctrl_fd < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to create mclagd ctl sock"); + return sys->sync_ctrl_fd; + } + + unlink(sys->mclagdctl_file_path); + + memset((void*)&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, 107, "%s", sys->mclagdctl_file_path); + addr_len = sizeof(addr.sun_family) + strlen(sys->mclagdctl_file_path); + + if ((ret = bind(sys->sync_ctrl_fd, (struct sockaddr*)&addr, addr_len)) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to bind mclagd ctl socket %s:%s", sys->mclagdctl_file_path, strerror(errno)); + close(sys->sync_ctrl_fd); + return MCLAG_ERROR; + } + + if (listen(sys->sync_ctrl_fd, 5) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to listen unix mclagd ctl socket%s:%s", sys->mclagdctl_file_path, strerror(errno)); + close(sys->sync_ctrl_fd); + return MCLAG_ERROR; + } + + event.data.fd = sys->sync_ctrl_fd; + event.events = EPOLLIN; + epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, sys->sync_ctrl_fd, &event); + FD_SET(sys->sync_ctrl_fd, &(sys->readfd)); + sys->readfd_count++; + + return sys->sync_ctrl_fd; +} + +int mclagd_ctl_sock_accept(int fd) +{ + struct sockaddr_in client_addr; + int client_fd = 0; + unsigned int addr_len = 0; + + client_fd = accept(fd, (struct sockaddr*)&client_addr, &addr_len); + if (client_fd < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to accept a client from mclagdctl"); + return MCLAG_ERROR; + } + + return client_fd; +} + +int mclagd_ctl_sock_read(int fd, char *r_buf, int total_len) +{ + int read_len = 0; + int ret = 0; + struct timeval tv = { 0 }; + fd_set read_fd; + + while (read_len < total_len) + { + FD_ZERO(&read_fd); + FD_SET(fd, &read_fd); + tv.tv_sec = 5; + tv.tv_usec = 0; + + switch ((ret = select(fd + 1, &read_fd, NULL, NULL, &tv))) + { + case -1: + /* error*/ + case 0: + /* timeout*/ + return MCLAG_ERROR; + + default: + break; + } + + if (FD_ISSET(fd, &read_fd)) + ret = read(fd, r_buf + read_len, total_len - read_len); + if (ret <= 0) + { + return MCLAG_ERROR; + } + read_len += ret; + } + + return read_len; +} + +int mclagd_ctl_sock_write(int fd, char *w_buf, int total_len) +{ + int write_len = 0; + int ret = 0; + + while (write_len < total_len) + { + ret = write(fd, w_buf + write_len, total_len - write_len); + if (ret <= 0) + { + return 0; + } + write_len += ret; + } + + return write_len; +} + +void mclagd_ctl_handle_dump_state(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = { 0 }; + int state_num = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + int len_tmp = 0; + + ret = iccp_mclag_config_dump(&Pbuf, &state_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + len_tmp = sizeof(struct mclagd_reply_hdr); + memcpy(buf, &len_tmp, sizeof(int)); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_STATE; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); + + if (Pbuf) + free(Pbuf); + + return; + } + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_STATE; + hd->data_len = state_num * sizeof(struct mclagd_state); + + len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + memcpy(Pbuf, &len_tmp, sizeof(int)); + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_arp(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = { 0 }; + int arp_num = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + int len_tmp = 0; + + ret = iccp_arp_dump(&Pbuf, &arp_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + len_tmp = sizeof(struct mclagd_reply_hdr); + memcpy(buf, &len_tmp, sizeof(int)); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_ARP; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_ARP; + hd->data_len = arp_num * sizeof(struct mclagd_arp_msg); + len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + memcpy(Pbuf, &len_tmp, sizeof(int)); + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_ndisc(int client_fd, int mclag_id) +{ + char *Pbuf = NULL; + char buf[512] = { 0 }; + int ndisc_num = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + int len_tmp = 0; + + ret = iccp_ndisc_dump(&Pbuf, &ndisc_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + len_tmp = sizeof(struct mclagd_reply_hdr); + memcpy(buf, &len_tmp, sizeof(int)); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_NDISC; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_NDISC; + hd->data_len = ndisc_num * sizeof(struct mclagd_ndisc_msg); + len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + memcpy(Pbuf, &len_tmp, sizeof(int)); + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_mac(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = { 0 }; + int mac_num = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + int len_tmp = 0; + + ret = iccp_mac_dump(&Pbuf, &mac_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + len_tmp = sizeof(struct mclagd_reply_hdr); + memcpy(buf, &len_tmp, sizeof(int)); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_MAC; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_MAC; + hd->data_len = mac_num * sizeof(struct mclagd_mac_msg); + + len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + memcpy(Pbuf, &len_tmp, sizeof(int)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_local_portlist(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = { 0 }; + int lif_num = 0;; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + int len_tmp = 0; + + ret = iccp_local_if_dump(&Pbuf, &lif_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + len_tmp = sizeof(struct mclagd_reply_hdr); + memcpy(buf, &len_tmp, sizeof(int)); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; + hd->data_len = lif_num * sizeof(struct mclagd_local_if); + len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + memcpy(Pbuf, &len_tmp, sizeof(int)); + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_peer_portlist(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = { 0 }; + int pif_num = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + int len_tmp = 0; + + ret = iccp_peer_if_dump(&Pbuf, &pif_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + len_tmp = sizeof(struct mclagd_reply_hdr); + memcpy(buf, &len_tmp, sizeof(int)); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_PEER_PORTLIST; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_PEER_PORTLIST; + hd->data_len = pif_num * sizeof(struct mclagd_peer_if); + len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + memcpy(Pbuf, &len_tmp, sizeof(int)); + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_config_loglevel(int client_fd, int log_level) +{ + char buf[sizeof(struct mclagd_reply_hdr)+sizeof(int)]; + struct mclagd_reply_hdr *hd = NULL; + int len_tmp = 0; + + logger_set_configuration(log_level); + + len_tmp = sizeof(struct mclagd_reply_hdr); + memcpy(buf, &len_tmp, sizeof(int)); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_CONFIG_LOGLEVEL; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); + + return; +} + +int mclagd_ctl_interactive_process(int client_fd) +{ + char buf[512] = { 0 }; + int ret = 0; + + struct mclagdctl_req_hdr* req = NULL; + + if (client_fd < 0) + return MCLAG_ERROR; + + ret = mclagd_ctl_sock_read(client_fd, buf, sizeof(struct mclagdctl_req_hdr)); + + if (ret < 0) + return MCLAG_ERROR; + + req = (struct mclagdctl_req_hdr*)buf; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Receive request %s from mclagdctl", mclagd_ctl_cmd_str(req->info_type)); + + switch (req->info_type) + { + case INFO_TYPE_DUMP_STATE: + mclagd_ctl_handle_dump_state(client_fd, req->mclag_id); + break; + + case INFO_TYPE_DUMP_ARP: + mclagd_ctl_handle_dump_arp(client_fd, req->mclag_id); + break; + + case INFO_TYPE_DUMP_NDISC: + mclagd_ctl_handle_dump_ndisc(client_fd, req->mclag_id); + break; + + case INFO_TYPE_DUMP_MAC: + mclagd_ctl_handle_dump_mac(client_fd, req->mclag_id); + break; + + case INFO_TYPE_DUMP_LOCAL_PORTLIST: + mclagd_ctl_handle_dump_local_portlist(client_fd, req->mclag_id); + break; + + case INFO_TYPE_DUMP_PEER_PORTLIST: + mclagd_ctl_handle_dump_peer_portlist(client_fd, req->mclag_id); + break; + + case INFO_TYPE_CONFIG_LOGLEVEL: + mclagd_ctl_handle_config_loglevel(client_fd, req->mclag_id); + break; + + default: + return MCLAG_ERROR; + } + + return 0; +} + + diff --git a/src/iccpd/src/mlacp_sync_prepare.c b/src/iccpd/src/mlacp_sync_prepare.c new file mode 100644 index 000000000000..ef1cd244a90a --- /dev/null +++ b/src/iccpd/src/mlacp_sync_prepare.c @@ -0,0 +1,677 @@ +/* + * MLACP Sync Infomation Preparation + * mlacp_sync_prepare.c + + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + * + */ + +#include +#include + +#include + +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_fsm.h" +#include "../include/mlacp_tlv.h" +#include "../include/mlacp_link_handler.h" +#include "../include/iccp_ifm.h" +#include "../include/iccp_csm.h" + +/***************************************** +* Static Function +* +* ***************************************/ +static int mlacp_fill_icc_header(struct CSM* csm, ICCHdr* icc_hdr, size_t msg_len); + +/***************************************** +* Create Sync Request TLV +* +* ***************************************/ +int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = NULL; + mLACPSyncReqTLV* tlv = NULL; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSyncReqTLV); + + if (csm == NULL) + return MCLAG_ERROR; + + if (buf == NULL) + return MCLAG_ERROR; + + if (msg_len > max_buf_size) + return MCLAG_ERROR; + + if ((sys = system_get_instance()) == NULL) + return MCLAG_ERROR; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*)buf; + tlv = (mLACPSyncReqTLV*)&buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* mLACP Synchronization Request TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_SYNC_REQUEST); + tlv->icc_parameter.len = htons(sizeof(mLACPSyncReqTLV) - sizeof(ICCParameter)); + + tlv->req_num = 0; + MLACP(csm).sync_req_num = 0; + + tlv->c_bit = 1; + tlv->s_bit = 1; + tlv->req_type = 0x3FFF; + *(uint16_t *)((uint8_t *)tlv + sizeof(ICCParameter) + sizeof(uint16_t)) = htons(*(uint16_t *)((uint8_t *)tlv + sizeof(ICCParameter) + sizeof(uint16_t))); + + tlv->port_num_agg_id = 0; + tlv->actor_key = 0; + + return msg_len; +} + +/***************************************** +* Prprare Sync Data TLV +* +* ***************************************/ +int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*)buf; + mLACPSyncDataTLV* tlv = (mLACPSyncDataTLV*)&buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSyncDataTLV); + + if (csm == NULL) + return MCLAG_ERROR; + + if (buf == NULL) + return MCLAG_ERROR; + + if (msg_len > max_buf_size) + return MCLAG_ERROR; + + if ((sys = system_get_instance()) == NULL) + return MCLAG_ERROR; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*)buf; + tlv = (mLACPSyncDataTLV*)&buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* mLACP Synchronization Data TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_SYNC_DATA); + tlv->icc_parameter.len = htons(sizeof(mLACPSyncDataTLV) - sizeof(ICCParameter)); + + tlv->req_num = htons(MLACP(csm).sync_req_num); + if (end == 0) + tlv->flags = 0x00; + else + tlv->flags = htons(0x01); + + return msg_len; +} + +/***************************************** +* Prprare Sync System-Config TLV +* +* ***************************************/ +int mlacp_prepare_for_sys_config(struct CSM* csm, char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*)buf; + mLACPSysConfigTLV* tlv = (mLACPSysConfigTLV*)&buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSysConfigTLV); + + if (csm == NULL) + return MCLAG_ERROR; + + if (buf == NULL) + return MCLAG_ERROR; + + if (msg_len > max_buf_size) + return MCLAG_ERROR; + + if ((sys = system_get_instance()) == NULL) + return MCLAG_ERROR; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*)buf; + tlv = (mLACPSysConfigTLV*)&buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* System Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_SYSTEM_CONFIG); + tlv->icc_parameter.len = htons(sizeof(mLACPSysConfigTLV) - sizeof(ICCParameter)); + + memcpy(tlv->sys_id, MLACP(csm).system_id, ETHER_ADDR_LEN); + tlv->sys_priority = htons(MLACP(csm).system_priority); + tlv->node_id = MLACP(csm).node_id; + return msg_len; +} + +/*Prprare Sync AggPort-State TLV */ +int mlacp_prepare_for_Aggport_state(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* local_if) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*)buf; + mLACPAggPortStateTLV* tlv = (mLACPAggPortStateTLV*)&buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPAggPortStateTLV); + + if (csm == NULL) + return MCLAG_ERROR; + + if (buf == NULL) + return MCLAG_ERROR; + + if (local_if == NULL) + return MCLAG_ERROR; + + if (local_if->type != IF_T_PORT_CHANNEL) + return MCLAG_ERROR; + + if (msg_len > max_buf_size) + return MCLAG_ERROR; + + if ((sys = system_get_instance()) == NULL) + return MCLAG_ERROR; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*)buf; + tlv = (mLACPAggPortStateTLV*)&buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port State TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_AGGREGATOR_STATE); + tlv->icc_parameter.len = htons(sizeof(mLACPAggPortStateTLV) - sizeof(ICCParameter)); + + tlv->partner_sys_priority = 0; + tlv->partner_key = 0; + tlv->agg_id = htons(local_if->po_id); + tlv->actor_key = 0; + tlv->agg_state = local_if->state; + + return msg_len; +} + +/***************************************** +* Prprare Sync Purge Port +* +* ***************************************/ +int mlacp_prepare_for_Aggport_config(struct CSM* csm, + char* buf, size_t max_buf_size, + struct LocalInterface* lif, int purge_flag) +{ + ICCHdr* icc_hdr = (ICCHdr*)buf; + mLACPAggConfigTLV* tlv = (mLACPAggConfigTLV*)&buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPAggConfigTLV); + + if (csm == NULL) + return MCLAG_ERROR; + + if (buf == NULL) + return MCLAG_ERROR; + + if (msg_len > max_buf_size) + return MCLAG_ERROR; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*)buf; + tlv = (mLACPAggConfigTLV*)&buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_AGGREGATOR_CONFIG); + + tlv->icc_parameter.len = htons(sizeof(mLACPAggConfigTLV) - sizeof(ICCParameter)); + tlv->agg_id = htons(lif->po_id); + if (purge_flag == 1) + tlv->flags = 0x02; /*purge*/ + else + tlv->flags = 0x1; + tlv->agg_name_len = strlen(lif->name); + memcpy(tlv->agg_name, lif->name, MAX_L_PORT_NAME); + memcpy(tlv->mac_addr, lif->mac_addr, ETHER_ADDR_LEN); + + return msg_len; +} + +/***************************************** +* Preprare Sync MAC-Info TLV +* +* ***************************************/ +int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg, int count) +{ + struct mLACPMACInfoTLV* tlv = NULL; + size_t msg_len = 0; + size_t tlv_len = 0; + ICCHdr* icc_hdr = NULL; + struct mLACPMACData *MacData; + + if (!csm) + return MCLAG_ERROR; + if (!buf) + return MCLAG_ERROR; + + tlv_len = sizeof(struct mLACPMACInfoTLV) + sizeof(struct mLACPMACData) * (count + 1); + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return MCLAG_ERROR; + + /* ICC header */ + icc_hdr = (ICCHdr*)buf; + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + /* Prepare for MAC information TLV */ + tlv = (struct mLACPMACInfoTLV*)&buf[sizeof(ICCHdr)]; + tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter)); + tlv->num_of_entry = htons(count + 1); + + if (count == 0) + { + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_MAC_INFO); + } + + MacData = (struct mLACPMACData *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPMACInfoTLV) + sizeof(struct mLACPMACData) * count]; + MacData->type = mac_msg->op_type; + sprintf(MacData->mac_str, "%s", mac_msg->mac_str); + sprintf(MacData->ifname, "%s", mac_msg->origin_ifname); + MacData->vid = htons(mac_msg->vid); + + ICCPD_LOG_NOTICE(__FUNCTION__, "Send MAC messge to peer, port %s mac = %s, vid = %d, type = %s count %d ", mac_msg->origin_ifname, + mac_msg->mac_str, mac_msg->vid, mac_msg->op_type == MAC_SYNC_ADD ? "add" : "del", count); + + return msg_len; +} + +/***************************************** +* Preprare Sync ARP-Info TLV +* +* ***************************************/ +int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count) +{ + struct mLACPARPInfoTLV* tlv = NULL; + size_t msg_len = 0; + size_t tlv_len = 0; + ICCHdr* icc_hdr = NULL; + struct ARPMsg* ArpData; + + if (!csm) + return MCLAG_ERROR; + if (!buf) + return MCLAG_ERROR; + + tlv_len = sizeof(struct mLACPARPInfoTLV) + sizeof(struct ARPMsg) * (count + 1); + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return MCLAG_ERROR; + + /* ICC header */ + icc_hdr = (ICCHdr*)buf; + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Prepare for ARP information TLV */ + tlv = (struct mLACPARPInfoTLV*)&buf[sizeof(ICCHdr)]; + tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter)); + tlv->num_of_entry = htons(count + 1); + + if (count == 0) + { + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_ARP_INFO); + } + + ArpData = (struct ARPMsg *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPARPInfoTLV) + sizeof(struct ARPMsg) * count]; + + ArpData->op_type = arp_msg->op_type; + sprintf(ArpData->ifname, "%s", arp_msg->ifname); + ArpData->ipv4_addr = arp_msg->ipv4_addr; + memcpy(ArpData->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); + + ICCPD_LOG_NOTICE(__FUNCTION__, "Send ARP messge to peer, if name %s mac %02x:%02x:%02x:%02x:%02x:%02x IP %s", ArpData->ifname, ArpData->mac_addr[0], ArpData->mac_addr[1], ArpData->mac_addr[2], + ArpData->mac_addr[3], ArpData->mac_addr[4], ArpData->mac_addr[5], show_ip_str(ArpData->ipv4_addr)); + + return msg_len; +} + +/***************************************** +* Preprare Sync NDISC-Info TLV +* +* ***************************************/ +int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size, struct NDISCMsg *ndisc_msg, int count) +{ + + struct mLACPNDISCInfoTLV *tlv = NULL; + size_t msg_len = 0; + size_t tlv_len = 0; + ICCHdr *icc_hdr = NULL; + struct NDISCMsg *NdiscData; + + if (!csm) + return -1; + if (!buf) + return -1; + + tlv_len = sizeof(struct mLACPNDISCInfoTLV) + sizeof(struct NDISCMsg) * (count + 1); + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return -1; + + /* ICC header */ + icc_hdr = (ICCHdr *)buf; + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Prepare for ND information TLV */ + tlv = (struct mLACPNDISCInfoTLV *)&buf[sizeof(ICCHdr)]; + tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter)); + tlv->num_of_entry = htons(count + 1); + + if (count == 0) + { + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_NDISC_INFO); + } + + NdiscData = (struct mLACPMACData *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPNDISCInfoTLV) + sizeof(struct NDISCMsg) * count]; + + NdiscData->op_type = ndisc_msg->op_type; + sprintf(NdiscData->ifname, "%s", ndisc_msg->ifname); + memcpy(NdiscData->ipv6_addr, ndisc_msg->ipv6_addr, 32); + memcpy(NdiscData->mac_addr, ndisc_msg->mac_addr, ETHER_ADDR_LEN); + + ICCPD_LOG_NOTICE(__FUNCTION__, "Send ND messge to peer, if name %s mac =%02x:%02x:%02x:%02x:%02x:%02x IPv6 %s", NdiscData->ifname, + NdiscData->mac_addr[0], NdiscData->mac_addr[1], NdiscData->mac_addr[2], NdiscData->mac_addr[3], NdiscData->mac_addr[4], + NdiscData->mac_addr[5], show_ipv6_str((char *)NdiscData->ipv6_addr)); + + return msg_len; +} + +/***************************************** +* Prprare Send portchannel info +* +* ***************************************/ +int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, + size_t max_buf_size, + struct LocalInterface* port_channel) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = NULL; + struct mLACPPortChannelInfoTLV* tlv = NULL; + size_t msg_len; + size_t tlv_len; + size_t name_len = MAX_L_PORT_NAME; + struct VLAN_ID* vlan_id = NULL; + int num_of_vlan_id = 0; + + if (csm == NULL ) + return MCLAG_ERROR; + if (buf == NULL ) + return MCLAG_ERROR; + if (port_channel == NULL ) + return MCLAG_ERROR; + if (port_channel->type == IF_T_PORT) + return MCLAG_ERROR; + if ((sys = system_get_instance()) == NULL ) + return MCLAG_ERROR; + + /* Calculate VLAN ID Length */ + LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next) + if (vlan_id != NULL) + num_of_vlan_id++; + + tlv_len = sizeof(struct mLACPPortChannelInfoTLV) + sizeof(struct mLACPVLANData) * num_of_vlan_id; + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return MCLAG_ERROR; + + /* Prepare for port channel info */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*)buf; + tlv = (struct mLACPPortChannelInfoTLV*)&buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port Channel Info TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_PORT_CHANNEL_INFO); + tlv->icc_parameter.len = htons(sizeof(struct mLACPPortChannelInfoTLV) - sizeof(ICCParameter) + sizeof(struct mLACPVLANData) * num_of_vlan_id); + tlv->agg_id = htons(port_channel->po_id); + tlv->ipv4_addr = htonl(port_channel->ipv4_addr); + tlv->l3_mode = port_channel->l3_mode; + tlv->po_id = htons(port_channel->po_id); + + if (strlen(port_channel->name) < name_len) + name_len = strlen(port_channel->name); + memcpy(tlv->if_name, port_channel->name, name_len); + tlv->if_name_len = name_len; + tlv->num_of_vlan_id = htons(num_of_vlan_id); + + num_of_vlan_id = 0; + LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next) + { + if (vlan_id != NULL ) + { + tlv->vlanData[num_of_vlan_id].vlan_id = htons(vlan_id->vid); + + num_of_vlan_id++; + ICCPD_LOG_DEBUG(__FUNCTION__, "PortChannel%d: ipv4 addr = %s vlan id %d num %d ", port_channel->po_id, show_ip_str( tlv->ipv4_addr), vlan_id->vid, num_of_vlan_id ); + } + } + + ICCPD_LOG_DEBUG(__FUNCTION__, "PortChannel%d: ipv4 addr = %s l3 mode %d", port_channel->po_id, show_ip_str( tlv->ipv4_addr), tlv->l3_mode); + + return msg_len; +} + +/***************************************** +* Prprare Send port peerlink info +* +* ***************************************/ +int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, + size_t max_buf_size, + struct LocalInterface* peerlink_port) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = NULL; + struct mLACPPeerLinkInfoTLV* tlv = NULL; + size_t msg_len; + size_t tlv_len; + + if (csm == NULL ) + return MCLAG_ERROR; + if (buf == NULL ) + return MCLAG_ERROR; + if (peerlink_port == NULL ) + return MCLAG_ERROR; + if ((sys = system_get_instance()) == NULL ) + return MCLAG_ERROR; + + /* Prepare for port channel info */ + memset(buf, 0, max_buf_size); + + tlv_len = sizeof(struct mLACPPeerLinkInfoTLV); + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return MCLAG_ERROR; + + icc_hdr = (ICCHdr*)buf; + tlv = (struct mLACPPeerLinkInfoTLV*)&buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port Channel Info TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_PEERLINK_INFO); + + tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter)); + memcpy(tlv->if_name, peerlink_port->name, MAX_L_PORT_NAME); + tlv->port_type = peerlink_port->type; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Peerlink port is %s, type = %d", tlv->if_name, tlv->port_type); + + return msg_len; +} + + +/***************************************** +* Prprare Send Heartbeat +* +* ***************************************/ +int mlacp_prepare_for_heartbeat(struct CSM* csm, char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*)buf; + struct mLACPHeartbeatTLV* tlv = (struct mLACPHeartbeatTLV*)&buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPHeartbeatTLV); + + if (csm == NULL) + return MCLAG_ERROR; + + if (buf == NULL) + return MCLAG_ERROR; + + if (msg_len > max_buf_size) + return MCLAG_ERROR; + + if ((sys = system_get_instance()) == NULL) + return MCLAG_ERROR; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*)buf; + tlv = (struct mLACPHeartbeatTLV*)&buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* System Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_HEARTBEAT); + + tlv->icc_parameter.len = htons(sizeof(struct mLACPHeartbeatTLV) - sizeof(ICCParameter)); + tlv->heartbeat = 0xFF; + return msg_len; +} + +/***************************************** +* Prepare Send warm-reboot flag +* +* ***************************************/ +int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*)buf; + struct mLACPWarmbootTLV* tlv = (struct mLACPWarmbootTLV*)&buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPWarmbootTLV); + + if (csm == NULL) + return MCLAG_ERROR; + + if (buf == NULL) + return MCLAG_ERROR; + + if (msg_len > max_buf_size) + return MCLAG_ERROR; + + if ((sys = system_get_instance()) == NULL) + return MCLAG_ERROR; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*)buf; + tlv = (struct mLACPWarmbootTLV*)&buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* System Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_WARMBOOT_FLAG); + + tlv->icc_parameter.len = htons(sizeof(struct mLACPWarmbootTLV) - sizeof(ICCParameter)); + tlv->warmboot = 0x1; + + ICCPD_LOG_NOTICE(__FUNCTION__, "Send warm reboot notification to peer!"); + return msg_len; +} + +/***************************************** +* Tool : Prepare ICC Header +* +* ***************************************/ +static int mlacp_fill_icc_header(struct CSM* csm, ICCHdr* icc_hdr, size_t msg_len) +{ + if (csm == NULL || icc_hdr == NULL) + return MCLAG_ERROR; + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = htons(MSG_T_RG_APP_DATA); + + icc_hdr->ldp_hdr.msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); + icc_hdr->ldp_hdr.msg_id = htonl(ICCP_MSG_ID); + ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + return 0; +} + diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c new file mode 100644 index 000000000000..b82fc1c16cb9 --- /dev/null +++ b/src/iccpd/src/mlacp_sync_update.c @@ -0,0 +1,946 @@ +/******************************************************************************** + * mlacp_sync_update.c + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + * + *******************************************************************************/ +#include +#include + +#include +#include + +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_tlv.h" +#include "../include/iccp_csm.h" +#include "../include/mlacp_link_handler.h" +#include "../include/iccp_consistency_check.h" +#include "../include/port.h" +#include "../include/iccp_netlink.h" +/***************************************** +* Port-Conf Update +* +* ***************************************/ +extern void update_if_ipmac_on_standby(struct LocalInterface* lif_po); +int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV*sysconf) +{ + struct LocalInterface* lif = NULL; + + /*NOTE + a little tricky, we change the NodeID local side if collision happened first time*/ + if (sysconf->node_id == MLACP(csm).node_id) + MLACP(csm).node_id++; + + memcpy(MLACP(csm).remote_system.system_id, sysconf->sys_id, ETHER_ADDR_LEN); + MLACP(csm).remote_system.system_priority = ntohs(sysconf->sys_priority); + MLACP(csm).remote_system.node_id = sysconf->node_id; + + ICCPD_LOG_DEBUG(__FUNCTION__, "SystemID [%02X:%02X:%02X:%02X:%02X:%02X], SystemPriority [%d], Remote NodeID [%d], NodeID [%d]", + MLACP(csm).remote_system.system_id[0], MLACP(csm).remote_system.system_id[1], MLACP(csm).remote_system.system_id[2], + MLACP(csm).remote_system.system_id[3], MLACP(csm).remote_system.system_id[4], MLACP(csm).remote_system.system_id[5], + MLACP(csm).remote_system.system_priority, + MLACP(csm).remote_system.node_id, + MLACP(csm).node_id); + + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + update_if_ipmac_on_standby(lif); + } + + return 0; +} + +/***************************************** +* Port-Conf Update +* +* ***************************************/ +int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf) +{ + struct PeerInterface* pif = NULL; + uint8_t po_active; + uint8_t new_create = 0; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Port name %s, po id %d flag %d MAC[%02x:%02x:%02x:%02x:%02x:%02x] ", + portconf->agg_name, ntohs(portconf->agg_id), portconf->flags, portconf->mac_addr[0], portconf->mac_addr[1], portconf->mac_addr[2], + portconf->mac_addr[3], portconf->mac_addr[4], portconf->mac_addr[5] ); + + /* Looking for the peer port instance, is any peer if exist?*/ + pif = peer_if_find_by_name(csm, portconf->agg_name); + + /* Process purge*/ + if (portconf->flags & 0x02) + { + /*Purge*/ + if (pif != NULL ) + peer_if_destroy(pif); + else + MLACP(csm).need_to_sync = 1; + /*ICCPD_LOG_INFO("mlacp_fsm", + " Peer port %s is removed from port-channel member.",portconf->port_name);*/ + + return 0; + } + + if (pif == NULL && portconf->flags & 0x01) + { + pif = peer_if_create(csm, ntohs(portconf->agg_id), IF_T_PORT_CHANNEL); + if (pif == NULL) + return MCLAG_ERROR; + + new_create = 1; + } + + pif->po_id = ntohs(portconf->agg_id); + memcpy(pif->name, portconf->agg_name, portconf->agg_name_len); + memcpy(pif->mac_addr, portconf->mac_addr, ETHER_ADDR_LEN); + + po_active = (pif->state == PORT_STATE_UP); + update_stp_peer_link(csm, pif, po_active, new_create); + update_peerlink_isolate_from_pif(csm, pif, po_active, new_create); + pif->po_active = po_active; + + return 0; +} + +/***************************************** +* Agg Port-State Update +* +* ***************************************/ +int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) +{ + struct PeerInterface* peer_if = NULL; + uint8_t po_active; + + if (csm == NULL || tlv == NULL) + return MCLAG_ERROR; + ICCPD_LOG_DEBUG(__FUNCTION__, "Portchannel id %d state %d", ntohs(tlv->agg_id), tlv->agg_state); + + po_active = (tlv->agg_state == PORT_STATE_UP); + + LIST_FOREACH(peer_if, &(MLACP(csm).pif_list), mlacp_next) + { + if (peer_if->type != IF_T_PORT_CHANNEL) + continue; + + if (peer_if->po_id != ntohs(tlv->agg_id)) + continue; + + peer_if->state = tlv->agg_state; + + update_stp_peer_link(csm, peer_if, po_active, 0); + update_peerlink_isolate_from_pif(csm, peer_if, po_active, 0); + + peer_if->po_active = po_active; + ICCPD_LOG_DEBUG(__FUNCTION__, "Update peer interface %s to state %s", peer_if->name, tlv->agg_state ? "down" : "up"); + + break; + } + + return 0; +} + +/***************************************** +* Recv from peer, MAC-Info Update +* ***************************************/ +int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData *MacData) +{ + + struct Msg* msg = NULL; + struct MACMsg *mac_msg = NULL, mac_data; + struct LocalInterface* local_if = NULL; + uint8_t from_mclag_intf = 0;/*0: orphan port, 1: MCLAG port*/ + + ICCPD_LOG_NOTICE(__FUNCTION__, + "Received MAC Info, port[%s] vid[%d] MAC[%s] type[%s]", + MacData->ifname, ntohs(MacData->vid), MacData->mac_str, MacData->type == MAC_SYNC_ADD ? "add" : "del"); + + /*Find the interface in MCLAG interface list*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL && strcmp(local_if->name, MacData->ifname) == 0) + { + from_mclag_intf = 1; + break; + } + } + + /* update MAC list*/ + TAILQ_FOREACH(msg, &(MLACP(csm).mac_list), tail) + { + mac_msg = (struct MACMsg*)msg->buf; + + /*Same MAC is exist in local switch, this may be mac move*/ + if (strcmp(mac_msg->mac_str, MacData->mac_str) == 0 && mac_msg->vid == ntohs(MacData->vid)) + { + if (MacData->type == MAC_SYNC_ADD) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, Remove peer age flag:%d ifname %s, MAC %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + /*mac_msg->fdb_type = tlv->fdb_type;*/ + /*The port ifname is different to the local item*/ + if (from_mclag_intf == 0 || strcmp(mac_msg->ifname, MacData->ifname) != 0 || strcmp(mac_msg->origin_ifname, MacData->ifname) != 0) + { + if (mac_msg->fdb_type != MAC_TYPE_STATIC) + { + /*Update local item*/ + memcpy(&mac_msg->origin_ifname, MacData->ifname, MAX_L_PORT_NAME); + } + + /*If the MAC is learned from orphan port, or from MCLAG port but the local port is down*/ + if (from_mclag_intf == 0 || (local_if->state == PORT_STATE_DOWN && strcmp(mac_msg->ifname, csm->peer_itf_name) != 0)) + { + /*Set MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); + + if (strlen(csm->peer_itf_name) != 0) + { + if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) + { + /* This MAC is already point to peer-link */ + return 0; + } + + if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) + { + /*Redirect the mac to peer-link*/ + memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + + /*Send mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + } + else + { + /*must redirect but peerlink is down, del mac from ASIC*/ + /*if peerlink change to up, mac will add back to ASIC*/ + del_mac_from_chip(mac_msg); + + /*Redirect the mac to peer-link*/ + memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + } + } + else + { + /*must redirect but no peerlink, del mac from ASIC*/ + del_mac_from_chip(mac_msg); + + /*Update local item*/ + memcpy(&mac_msg->ifname, MacData->ifname, MAX_L_PORT_NAME); + + /*if orphan port mac but no peerlink, don't keep this mac*/ + if (from_mclag_intf == 0) + { + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + return 0; + } + } + } + else + { + /*Remove MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 0); + + /*Update local item*/ + memcpy(&mac_msg->ifname, MacData->ifname, MAX_L_PORT_NAME); + + /*from MCLAG port and the local port is up, add mac to ASIC to update port*/ + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + } + } + } + + break; + } + } + + /* delete/add MAC list*/ + if (msg && MacData->type == MAC_SYNC_DEL) + { + mac_msg->age_flag |= MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv DEL, Add peer age flag: %d ifname %s, MAC %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + if (mac_msg->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) + { + /*send mac del message to mclagsyncd.*/ + del_mac_from_chip(mac_msg); + + /*If local and peer both aged, del the mac*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + else + { + return 0; + } + } + else if (!msg && MacData->type == MAC_SYNC_ADD) + { + mac_msg = (struct MACMsg*)&mac_data; + mac_msg->fdb_type = MAC_TYPE_DYNAMIC; + mac_msg->vid = ntohs(MacData->vid); + sprintf(mac_msg->mac_str, "%s", MacData->mac_str); + sprintf(mac_msg->ifname, "%s", MacData->ifname); + sprintf(mac_msg->origin_ifname, "%s", MacData->ifname); + mac_msg->age_flag = 0; + + /*If the MAC is learned from orphan port, or from MCLAG port but the local port is down*/ + if (from_mclag_intf == 0 || local_if->state == PORT_STATE_DOWN) + { + /*Set MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); + + if (strlen(csm->peer_itf_name) == 0) + { + ICCPD_LOG_NOTICE(__FUNCTION__, "From orphan port or portchannel is down, but peer-link is not configured: ifname %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + /*if orphan port mac but no peerlink, don't keep this mac*/ + if (from_mclag_intf == 0) + return 0; + } + else + { + /*Redirect the mac to peer-link*/ + memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + + ICCPD_LOG_NOTICE(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, MAC %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + } + } + else + { + /*Remove MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 0); + } + + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_list), msg, tail); + /*ICCPD_LOG_INFO(__FUNCTION__, "add mac queue successfully");*/ + + /*If the mac is from orphan port, or from MCLAG port but the local port is down*/ + if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) + { + /*Send mac add message to mclagsyncd*/ + if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) + add_mac_to_chip(mac_msg, mac_msg->fdb_type); + } + else + { + /*from MCLAG port and the local port is up*/ + add_mac_to_chip(mac_msg, mac_msg->fdb_type); + } + } + } + + return 0; +} + +int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* tlv) +{ + int count = 0; + int i; + + if (!csm || !tlv) + return MCLAG_ERROR; + count = ntohs(tlv->num_of_entry); + ICCPD_LOG_INFO(__FUNCTION__, "Received MAC Info count %d", count ); + + for (i = 0; i < count; i++) + { + mlacp_fsm_update_mac_entry_from_peer(csm, &(tlv->MacEntry[i])); + } +} + +/***************************************** + * Tool : Add ARP Info into ARP list + * + ****************************************/ +void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg) +{ + struct ARPMsg *arp_msg = NULL; + + if (!csm) + { + if (msg) + free(msg); + return; + } + if (!msg) + return; + + arp_msg = (struct ARPMsg*)msg->buf; + if (arp_msg->op_type != NEIGH_SYNC_DEL) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_list), msg, tail); + } + + return; +} + +/***************************************** + * Tool : Add Ndisc Info into ndisc list + * + ****************************************/ +void mlacp_enqueue_ndisc(struct CSM *csm, struct Msg *msg) +{ + struct NDISCMsg *ndisc_msg = NULL; + + if (!csm) + { + if (msg) + free(msg); + return; + } + if (!msg) + return; + + ndisc_msg = (struct NDISCMsg *)msg->buf; + if (ndisc_msg->op_type != NEIGH_SYNC_DEL) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_list), msg, tail); + } + + return; +} + +/***************************************** +* ARP-Info Update +* ***************************************/ +int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) +{ + struct Msg* msg = NULL; + struct ARPMsg *arp_msg = NULL, arp_data; + struct LocalInterface* local_if; + struct LocalInterface *peer_link_if = NULL; + struct VLAN_ID *vlan_id_list = NULL; + int set_arp_flag = 0; + char mac_str[18] = ""; + + if (!csm || !arp_entry) + return MCLAG_ERROR; + + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", arp_entry->mac_addr[0], arp_entry->mac_addr[1], arp_entry->mac_addr[2], + arp_entry->mac_addr[3], arp_entry->mac_addr[4], arp_entry->mac_addr[5]); + + ICCPD_LOG_NOTICE(__FUNCTION__, + "Received ARP Info, intf[%s] IP[%s], MAC[%02x:%02x:%02x:%02x:%02x:%02x]", + arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), + arp_entry->mac_addr[0], arp_entry->mac_addr[1], arp_entry->mac_addr[2], + arp_entry->mac_addr[3], arp_entry->mac_addr[4], arp_entry->mac_addr[5]); + + if (strncmp(arp_entry->ifname, "Vlan", 4) == 0) + { + peer_link_if = local_if_find_by_name(csm->peer_itf_name); + + if (peer_link_if && !local_if_is_l3_mode(peer_link_if)) + { + /* Is peer-linlk itf belong to a vlan the same as peer?*/ + LIST_FOREACH(vlan_id_list, &(peer_link_if->vlan_list), port_next) + { + if (!vlan_id_list->vlan_itf) + continue; + if (strcmp(vlan_id_list->vlan_itf->name, arp_entry->ifname) != 0) + continue; + if (!local_if_is_l3_mode(vlan_id_list->vlan_itf)) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is learnt from intf %s, peer-link %s is the member of this vlan", + vlan_id_list->vlan_itf->name, peer_link_if->name); + + /* Peer-link belong to L3 vlan is alive, set the ARP info*/ + set_arp_flag = 1; + + break; + } + } + } + + if (set_arp_flag == 0) + { + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) + { + if (!local_if_is_l3_mode(local_if)) + { + /* Is the L2 MLAG itf belong to a vlan the same as peer?*/ + LIST_FOREACH(vlan_id_list, &(local_if->vlan_list), port_next) + { + if (!vlan_id_list->vlan_itf) + continue; + if (strcmp(vlan_id_list->vlan_itf->name, arp_entry->ifname) != 0) + continue; + if (!local_if_is_l3_mode(vlan_id_list->vlan_itf)) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is learnt from intf %s, mclag %s is the member of this vlan", + vlan_id_list->vlan_itf->name, local_if->name); + break; + } + + if (vlan_id_list && local_if->po_active == 1) + { + /* Any po of L3 vlan is alive, set the ARP info*/ + set_arp_flag = 1; + break; + } + } + else + { + /* Is the ARP belong to a L3 mode MLAG itf?*/ + if (strcmp(local_if->name, arp_entry->ifname) == 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is learnt from mclag L3 intf %s", local_if->name); + if (local_if->po_active == 1) + { + /* po is alive, set the ARP info*/ + set_arp_flag = 1; + break; + } + } + else + { + continue; + } + } + } + } + } + + /* set dynamic ARP*/ + if (set_arp_flag == 1) + { + if (arp_entry->op_type == NEIGH_SYNC_ADD) + { + if (iccp_netlink_neighbor_request(AF_INET, (uint8_t *)&arp_entry->ipv4_addr, 1, arp_entry->mac_addr, arp_entry->ifname) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "ARP add failure for %s %s %s", + arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); + return MCLAG_ERROR; + } + } + else + { + if (iccp_netlink_neighbor_request(AF_INET, (uint8_t *)&arp_entry->ipv4_addr, 0, arp_entry->mac_addr, arp_entry->ifname) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "ARP delete failure for %s %s %s", + arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); + return MCLAG_ERROR; + } + } + + /*ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP update for %s %s %s", + __FUNCTION__, arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str);*/ + } + else + { + ICCPD_LOG_NOTICE(__FUNCTION__, "Failure: port-channel is not alive"); + /*TODO Set static route through peer-link or just skip it?*/ + } + + /* update ARP list*/ + TAILQ_FOREACH(msg, &(MLACP(csm).arp_list), tail) + { + arp_msg = (struct ARPMsg*)msg->buf; + if (arp_msg->ipv4_addr == arp_entry->ipv4_addr) + { + /*arp_msg->op_type = tlv->type;*/ + sprintf(arp_msg->ifname, "%s", arp_entry->ifname); + memcpy(arp_msg->mac_addr, arp_entry->mac_addr, ETHER_ADDR_LEN); + break; + } + } + + /* delete/add ARP list*/ + if (msg && arp_entry->op_type == NEIGH_SYNC_DEL) + { + TAILQ_REMOVE(&(MLACP(csm).arp_list), msg, tail); + free(msg->buf); + free(msg); + /*ICCPD_LOG_INFO(__FUNCTION__, "Del arp queue successfully");*/ + } + else if (!msg && arp_entry->op_type == NEIGH_SYNC_ADD) + { + arp_msg = (struct ARPMsg*)&arp_data; + sprintf(arp_msg->ifname, "%s", arp_entry->ifname); + arp_msg->ipv4_addr = arp_entry->ipv4_addr; + arp_msg->op_type = arp_entry->op_type; + memcpy(arp_msg->mac_addr, arp_entry->mac_addr, ETHER_ADDR_LEN); + if (iccp_csm_init_msg(&msg, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) + { + mlacp_enqueue_arp(csm, msg); + /*ICCPD_LOG_INFO(__FUNCTION__, "Add arp queue successfully");*/ + } + } + + /* remove all ARP msg queue, when receive peer's ARP list at the same time*/ + TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail) + { + arp_msg = (struct ARPMsg*)msg->buf; + if (arp_msg->ipv4_addr == arp_entry->ipv4_addr) + break; + } + + while (msg) + { + arp_msg = (struct ARPMsg*)msg->buf; + TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); + free(msg->buf); + free(msg); + TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail) + { + arp_msg = (struct ARPMsg*)msg->buf; + if (arp_msg->ipv4_addr == arp_entry->ipv4_addr) + break; + } + } + + return 0; +} + +int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) +{ + int count = 0; + int i; + + if (!csm || !tlv) + return MCLAG_ERROR; + count = ntohs(tlv->num_of_entry); + ICCPD_LOG_INFO(__FUNCTION__, "Received ARP Info count %d ", count ); + + for (i = 0; i < count; i++) + { + mlacp_fsm_update_arp_entry(csm, &(tlv->ArpEntry[i])); + } +} + +/***************************************** +* NDISC-Info Update +* ***************************************/ +int mlacp_fsm_update_ndisc_entry(struct CSM *csm, struct NDISCMsg *ndisc_entry) +{ + struct Msg *msg = NULL; + struct NDISCMsg *ndisc_msg = NULL, ndisc_data; + struct LocalInterface *local_if; + struct LocalInterface *peer_link_if = NULL; + struct VLAN_ID *vlan_id_list = NULL; + int set_ndisc_flag = 0; + char mac_str[18] = ""; + + if (!csm || !ndisc_entry) + return MCLAG_ERROR; + + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", ndisc_entry->mac_addr[0], ndisc_entry->mac_addr[1], ndisc_entry->mac_addr[2], + ndisc_entry->mac_addr[3], ndisc_entry->mac_addr[4], ndisc_entry->mac_addr[5]); + + ICCPD_LOG_NOTICE(__FUNCTION__, + "Received ND Info, intf[%s] IP[%s], MAC[%s]", ndisc_entry->ifname, show_ipv6_str((char *)ndisc_entry->ipv6_addr), mac_str); + + if (strncmp(ndisc_entry->ifname, "Vlan", 4) == 0) + { + peer_link_if = local_if_find_by_name(csm->peer_itf_name); + + if (peer_link_if && !local_if_is_l3_mode(peer_link_if)) + { + /* Is peer-linlk itf belong to a vlan the same as peer? */ + LIST_FOREACH(vlan_id_list, &(peer_link_if->vlan_list), port_next) + { + if (!vlan_id_list->vlan_itf) + continue; + if (strcmp(vlan_id_list->vlan_itf->name, ndisc_entry->ifname) != 0) + continue; + if (!local_if_is_l3_mode(vlan_id_list->vlan_itf)) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, + "ND is learnt from intf %s, peer-link %s is the member of this vlan", + vlan_id_list->vlan_itf->name, peer_link_if->name); + + /* Peer-link belong to L3 vlan is alive, set the NDISC info */ + set_ndisc_flag = 1; + + break; + } + } + } + + if (set_ndisc_flag == 0) + { + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) + { + if (!local_if_is_l3_mode(local_if)) + { + /* Is the L2 MLAG itf belong to a vlan the same as peer? */ + LIST_FOREACH(vlan_id_list, &(local_if->vlan_list), port_next) + { + if (!vlan_id_list->vlan_itf) + continue; + if (strcmp(vlan_id_list->vlan_itf->name, ndisc_entry->ifname) != 0) + continue; + if (!local_if_is_l3_mode(vlan_id_list->vlan_itf)) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, + "ND is learnt from intf %s, %s is the member of this vlan", vlan_id_list->vlan_itf->name, local_if->name); + break; + } + + if (vlan_id_list && local_if->po_active == 1) + { + /* Any po of L3 vlan is alive, set the NDISC info */ + set_ndisc_flag = 1; + break; + } + } + else + { + /* Is the ARP belong to a L3 mode MLAG itf? */ + if (strcmp(local_if->name, ndisc_entry->ifname) == 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "ND is learnt from mclag L3 intf %s", local_if->name); + if (local_if->po_active == 1) + { + /* po is alive, set the NDISC info */ + set_ndisc_flag = 1; + break; + } + } + else + { + continue; + } + } + } + } + } + + /* set dynamic Ndisc */ + if (set_ndisc_flag == 1) + { + if (ndisc_entry->op_type == NEIGH_SYNC_ADD) + { + if (iccp_netlink_neighbor_request(AF_INET6, (uint8_t *)ndisc_entry->ipv6_addr, 1, ndisc_entry->mac_addr, ndisc_entry->ifname) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to add nd entry(%s %s %s) to kernel", + ndisc_entry->ifname, show_ipv6_str((char *)ndisc_entry->ipv6_addr), mac_str); + return MCLAG_ERROR; + } + + } + else + { + if (iccp_netlink_neighbor_request(AF_INET6, (uint8_t *)ndisc_entry->ipv6_addr, 0, ndisc_entry->mac_addr, ndisc_entry->ifname) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to delete nd entry(%s %s %s) from kernel", + ndisc_entry->ifname, show_ipv6_str((char *)ndisc_entry->ipv6_addr), mac_str); + return MCLAG_ERROR; + } + + } + + /* ICCPD_LOG_DEBUG(__FUNCTION__, "NDISC update for %s %s %s", ndisc_entry->ifname, show_ipv6_str((char *)ndisc_entry->ipv6_addr), mac_str); */ + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Failure: port-channel is not alive"); + /* TODO Set static route through peer-link or just skip it? */ + } + + /* update NDISC list */ + TAILQ_FOREACH(msg, &(MLACP(csm).ndisc_list), tail) + { + ndisc_msg = (struct NDISCMsg *)msg->buf; + if (memcmp((char *)ndisc_msg->ipv6_addr, (char *)ndisc_entry->ipv6_addr, 16) == 0) + { + /* ndisc_msg->op_type = tlv->type; */ + sprintf(ndisc_msg->ifname, "%s", ndisc_entry->ifname); + memcpy(ndisc_msg->mac_addr, ndisc_entry->mac_addr, ETHER_ADDR_LEN); + break; + } + } + + /* delete/add NDISC list */ + if (msg && ndisc_entry->op_type == NEIGH_SYNC_DEL) + { + TAILQ_REMOVE(&(MLACP(csm).ndisc_list), msg, tail); + free(msg->buf); + free(msg); + /* ICCPD_LOG_INFO(__FUNCTION__, "Del ndisc queue successfully"); */ + } + else if (!msg && ndisc_entry->op_type == NEIGH_SYNC_ADD) + { + ndisc_msg = (struct NDISCMsg *)&ndisc_data; + sprintf(ndisc_msg->ifname, "%s", ndisc_entry->ifname); + memcpy((char *)ndisc_msg->ipv6_addr, (char *)ndisc_entry->ipv6_addr, 16); + ndisc_msg->op_type = ndisc_entry->op_type; + memcpy(ndisc_msg->mac_addr, ndisc_entry->mac_addr, ETHER_ADDR_LEN); + if (iccp_csm_init_msg(&msg, (char *)ndisc_msg, sizeof(struct NDISCMsg)) == 0) + { + mlacp_enqueue_ndisc(csm, msg); + /* ICCPD_LOG_INFO(__FUNCTION__, "Add ndisc queue successfully"); */ + } + } + + /* remove all NDISC msg queue, when receive peer's NDISC list at the same time */ + TAILQ_FOREACH(msg, &(MLACP(csm).ndisc_msg_list), tail) + { + ndisc_msg = (struct NDISCMsg *)msg->buf; + if (memcmp((char *)ndisc_msg->ipv6_addr, (char *)ndisc_entry->ipv6_addr, 16) == 0) + break; + } + + while (msg) + { + ndisc_msg = (struct NDISCMsg *)msg->buf; + TAILQ_REMOVE(&(MLACP(csm).ndisc_msg_list), msg, tail); + free(msg->buf); + free(msg); + TAILQ_FOREACH(msg, &(MLACP(csm).ndisc_msg_list), tail) + { + ndisc_msg = (struct NDISCMsg *)msg->buf; + if (memcmp((char *)ndisc_msg->ipv6_addr, (char *)ndisc_entry->ipv6_addr, 16) == 0) + break; + } + } + + return 0; +} + +int mlacp_fsm_update_ndisc_info(struct CSM *csm, struct mLACPNDISCInfoTLV *tlv) +{ + int count = 0; + int i; + + if (!csm || !tlv) + return MCLAG_ERROR; + count = ntohs(tlv->num_of_entry); + ICCPD_LOG_INFO(__FUNCTION__, "Received NDISC Info count %d ", count); + + for (i = 0; i < count; i++) + { + mlacp_fsm_update_ndisc_entry(csm, &(tlv->NdiscEntry[i])); + } +} + +/***************************************** +* Port-Channel-Info Update +* ***************************************/ +int mlacp_fsm_update_port_channel_info(struct CSM* csm, + struct mLACPPortChannelInfoTLV* tlv) +{ + struct PeerInterface* peer_if = NULL; + struct VLAN_ID* peer_vlan_id = NULL; + int i = 0; + + if (csm == NULL || tlv == NULL ) + return MCLAG_ERROR; + + LIST_FOREACH(peer_if, &(MLACP(csm).pif_list), mlacp_next) + { + if (peer_if->type != IF_T_PORT_CHANNEL) + continue; + + if (peer_if->po_id != ntohs(tlv->agg_id)) + continue; + + LIST_FOREACH(peer_vlan_id, &(peer_if->vlan_list), port_next) + { + peer_vlan_id->vlan_removed = 1; + } + + /* Record peer info*/ + peer_if->ipv4_addr = ntohl(tlv->ipv4_addr); + peer_if->l3_mode = tlv->l3_mode; + + for (i = 0; i < ntohs(tlv->num_of_vlan_id); i++) + { + peer_if_add_vlan(peer_if, ntohs(tlv->vlanData[i].vlan_id)); + } + + peer_if_clean_unused_vlan(peer_if); + + iccp_consistency_check(peer_if->name); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer intf %s info: ipv4 addr %s l3 mode %d", peer_if->name, show_ip_str( tlv->ipv4_addr), peer_if->l3_mode); + break; + } + + return 0; +} + +/***************************************** +* Peerlink port Update +* ***************************************/ +int mlacp_fsm_update_peerlink_info(struct CSM* csm, + struct mLACPPeerLinkInfoTLV* tlv) +{ + if (csm == NULL || tlv == NULL ) + return MCLAG_ERROR; + + if (!csm->peer_link_if) + { + ICCPD_LOG_WARN(__FUNCTION__, "Peerlink port info recv from peer, local peerlink is not exist!"); + return 0; + } + + if (csm->peer_link_if->type != tlv->port_type) + ICCPD_LOG_NOTICE(__FUNCTION__, "Peerlink port type of peer %d is not same with local %d !", tlv->port_type, csm->peer_link_if->type); + + if (tlv->port_type == IF_T_VXLAN && strncmp(csm->peer_itf_name, tlv->if_name, strlen(csm->peer_itf_name))) + ICCPD_LOG_NOTICE(__FUNCTION__, "Peerlink port is vxlan port, but peerlink port of peer %s is not same with local %s !", tlv->if_name, csm->peer_itf_name); + + return 0; +} + +/***************************************** +* Heartbeat Update +*****************************************/ +int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv) +{ + if (!csm || !tlv) + return MCLAG_ERROR; + + time(&csm->heartbeat_update_time); + + return 0; +} + +/***************************************** +* warm-reboot flag Update +*****************************************/ +int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv) +{ + if (!csm || !tlv) + return MCLAG_ERROR; + + time(&csm->peer_warm_reboot_time); + ICCPD_LOG_NOTICE(__FUNCTION__, "Receive warm reboot notification from peer!"); + + return 0; +} + diff --git a/src/iccpd/src/port.c b/src/iccpd/src/port.c new file mode 100644 index 000000000000..e63429a77c2e --- /dev/null +++ b/src/iccpd/src/port.c @@ -0,0 +1,668 @@ +/* + * port.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include +#include + +#include "../include/logger.h" +#include "../include/port.h" +#include "../include/system.h" +#include "../include/iccp_csm.h" +#include "../include/iccp_netlink.h" +#include "../include/scheduler.h" + +void local_if_init(struct LocalInterface* local_if) +{ + if (local_if == NULL) + return; + + memset(local_if, 0, sizeof(struct LocalInterface)); + local_if->po_id = -1; + local_if->po_active = 1; //always guess the po is active + local_if->mlacp_state = MLACP_STATE_INIT; + local_if->type = IF_T_UNKNOW; + local_if->changed = 1; + local_if->port_config_sync = 0; + local_if->is_peer_link = 0; + local_if->is_arp_accept = 0; + local_if->l3_mode = 0; + local_if->state = PORT_STATE_DOWN; + local_if->prefixlen = 32; + local_if->csm = NULL; + local_if->isolate_to_peer_link = 0; + LIST_INIT(&local_if->vlan_list); + + return; +} + +void vlan_info_init(struct VLAN_ID* vlan) +{ + vlan->vid = -1; + vlan->vlan_removed = 0; + vlan->vlan_itf = NULL; + + return; +} + +struct LocalInterface* local_if_create(int ifindex, char* ifname, int type) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + struct CSM* csm; + struct If_info * cif = NULL; + + if (!ifname) + return NULL; + + if (!(sys = system_get_instance())) + return NULL; + + if (ifindex < 0) + return NULL; + + if ((local_if = local_if_find_by_ifindex(ifindex))) + return local_if; + + if (!(local_if = (struct LocalInterface*)malloc(sizeof(struct LocalInterface)))) + { + ICCPD_LOG_WARN(__FUNCTION__, "Port ifindex = %d, malloc failed", ifindex); + return NULL; + } + + local_if_init(local_if); + local_if->ifindex = ifindex; + local_if->type = type; + + if (local_if->type == IF_T_PORT_CHANNEL) + { + int i; + int len; + len = strlen(ifname); + + for (i = 0; i < len; ++i) + if (ifname[i] >= '0' && ifname[i] <= '9') + break; + + if (i >= len) + return NULL; + + local_if->po_id = atoi(&ifname[i]); + } + + if (ifname) + snprintf(local_if->name, MAX_L_PORT_NAME, "%s", ifname); + + switch (type) + { + case IF_T_PORT_CHANNEL: + break; + + case IF_T_PORT: + break; + + case IF_T_VLAN: + /* do nothing currently. */ + break; + + case IF_T_VXLAN: + /* do nothing currently. */ + break; + + default: + ICCPD_LOG_WARN(__FUNCTION__, "The type of local interface (%s) is not acceptable", ifname); + if (local_if) + free(local_if); + return NULL; + } + + ICCPD_LOG_NOTICE(__FUNCTION__, + "Create a local_if = %s ifindex = %d MAC = %02x:%02x:%02x:%02x:%02x:%02x, state = %s", + ifname, local_if->ifindex, local_if->mac_addr[0], local_if->mac_addr[1], local_if->mac_addr[2], + local_if->mac_addr[3], local_if->mac_addr[4], local_if->mac_addr[5], local_if->state ? "down" : "up"); + + LIST_INSERT_HEAD(&(sys->lif_list), local_if, system_next); + + /*Check the intf is peer-link? Only support PortChannel and Ethernet currently*/ + /*When set peer-link, the local-if is probably not created*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (strcmp(local_if->name, csm->peer_itf_name) == 0) + { + local_if->is_peer_link = 1; + csm->peer_link_if = local_if; + break; + } + /*check the intf is bind with csm*/ + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + if (strcmp(ifname, cif->name) == 0) + mlacp_bind_port_channel_to_csm(csm, ifname); + } + } + + return local_if; +} + +struct LocalInterface* local_if_find_by_name(const char* ifname) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + + if (!ifname) + return NULL; + + if (!(sys = system_get_instance())) + return NULL; + + LIST_FOREACH(local_if, &(sys->lif_list), system_next) + { + if (strcmp(local_if->name, ifname) == 0) + return local_if; + } + + return NULL; +} + +struct LocalInterface* local_if_find_by_ifindex(int ifindex) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + + if ((sys = system_get_instance()) == NULL) + return NULL; + + LIST_FOREACH(local_if, &(sys->lif_list), system_next) + { + if (local_if->ifindex == ifindex) + return local_if; + } + + return NULL; +} + +struct LocalInterface* local_if_find_by_po_id(int po_id) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + + if ((sys = system_get_instance()) == NULL) + return NULL; + + LIST_FOREACH(local_if, &(sys->lif_list), system_next) + { + if (local_if->type == IF_T_PORT_CHANNEL && local_if->po_id == po_id) + return local_if; + } + + return NULL; +} + +static void local_if_vlan_remove(struct LocalInterface *lif_vlan) +{ + struct System *sys = NULL; + struct LocalInterface *lif = NULL; + struct VLAN_ID *vlan = NULL; + + if ((sys = system_get_instance()) != NULL) + { + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if (lif_vlan != vlan->vlan_itf) + continue; + + vlan->vlan_itf = NULL; + } + } + } + + return; +} + +static void local_if_po_remove(struct LocalInterface *lif_po) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct LocalInterface *lif = NULL; + + /* remove all po member*/ + if ((sys = system_get_instance()) != NULL) + { + csm = lif_po->csm; + if (csm) + { + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type != IF_T_PORT) + continue; + if (lif->po_id != lif_po->po_id) + continue; + + mlacp_unbind_local_if(lif); + } + } + } + + return; +} + +static void local_if_remove(struct LocalInterface *lif) +{ + mlacp_unbind_local_if(lif); + lif->po_id = -1; + + return; +} + +void local_if_destroy(char *ifname) +{ + struct LocalInterface* lif = NULL; + struct CSM *csm = NULL; + struct System *sys = NULL; + + if (!(sys = system_get_instance())) + return; + + lif = local_if_find_by_name(ifname); + if (!lif) + return; + + ICCPD_LOG_WARN(__FUNCTION__, "Destroy interface %s, %d\n", lif->name, lif->ifindex); + + if (lif->type == IF_T_VLAN) + local_if_vlan_remove(lif); + else if (lif->type == IF_T_PORT_CHANNEL) + local_if_po_remove(lif); + else + local_if_remove(lif); + + csm = lif->csm; + if (csm && csm->peer_link_if && strcmp(csm->peer_link_if->name, ifname) == 0) + { + /*if the peerlink interface is not created, peer connection can not establish*/ + scheduler_session_disconnect_handler(csm); + csm->peer_link_if->is_peer_link = 0; + csm->peer_link_if = NULL; + } + + if (csm && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + goto to_mlacp_purge; + else + goto to_sys_purge; + + to_sys_purge: + /* sys purge */ + LIST_REMOVE(lif, system_next); + if (lif->csm) + LIST_REMOVE(lif, mlacp_next); + LIST_INSERT_HEAD(&(sys->lif_purge_list), lif, system_purge_next); + return; + + to_mlacp_purge: + /* sys & mlacp purge */ + LIST_REMOVE(lif, system_next); + LIST_REMOVE(lif, mlacp_next); + LIST_INSERT_HEAD(&(sys->lif_purge_list), lif, system_purge_next); + LIST_INSERT_HEAD(&(MLACP(csm).lif_purge_list), lif, mlacp_purge_next); + return; +} + +int local_if_is_l3_mode(struct LocalInterface* local_if) +{ + int ret = 0; + char addr_null[16] = { 0 }; + + if (local_if == NULL) + return 0; + + if (local_if->ipv4_addr != 0 || memcmp(local_if->ipv6_addr, addr_null, 16) != 0) + ret = 1; + + return ret; +} + +void local_if_change_flag_clear(void) +{ + struct System* sys = NULL; + struct LocalInterface* lif = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + if (lif->changed == 1) + { + lif->changed = 0; + } + } + + return; +} + +void local_if_purge_clear(void) +{ + struct System* sys = NULL; + struct LocalInterface* lif = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + /* destroy purge if*/ + while (!LIST_EMPTY(&(sys->lif_purge_list))) + { + lif = LIST_FIRST(&(sys->lif_purge_list)); + ICCPD_LOG_DEBUG(__FUNCTION__, "Purge %s", lif->name); + LIST_REMOVE(lif, system_purge_next); + if (lif->mlacp_purge_next.le_next != 0 && lif->mlacp_purge_next.le_prev != 0) + LIST_REMOVE(lif, mlacp_purge_next); + local_if_del_all_vlan(lif); + free(lif); + } + + LIST_INIT(&(sys->lif_purge_list)); + + return; +} + +void local_if_finalize(struct LocalInterface* lif) +{ + if (lif == NULL) + return; + + local_if_del_all_vlan(lif); + + free(lif); + + return; +} + +struct PeerInterface* peer_if_create(struct CSM* csm, + int peer_if_number, int type) +{ + struct PeerInterface* peer_if = NULL; + + /* check csm*/ + if (csm == NULL) + return NULL; + + /* check id*/ + if (peer_if_number < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "peer interface id < 0"); + return NULL; + } + + /* check type*/ + if (type != IF_T_PORT && type != IF_T_PORT_CHANNEL) + { + ICCPD_LOG_WARN(__FUNCTION__, + "The type(%) of peer interface(%d) is not acceptable", + type, peer_if_number); + return NULL; + } + + /* create a new peer if*/ + if ((peer_if = (struct PeerInterface*)malloc(sizeof(struct PeerInterface))) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Peer port id = %d, malloc failed", peer_if_number); + return NULL; + } + memset(peer_if, 0, sizeof(struct PeerInterface)); + + if (type == IF_T_PORT) + { + peer_if->ifindex = peer_if_number; + peer_if->type = IF_T_PORT; + peer_if->csm = csm; + } + else if (type == IF_T_PORT_CHANNEL) + { + peer_if->ifindex = peer_if_number; + peer_if->type = IF_T_PORT_CHANNEL; + } + + LIST_INSERT_HEAD(&(MLACP(csm).pif_list), peer_if, mlacp_next); + + return peer_if; +} + +struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name) +{ + struct System* sys = NULL; + struct PeerInterface* peer_if = NULL; + + if ((sys = system_get_instance()) == NULL) + return NULL; + + if (csm == NULL) + return NULL; + + LIST_FOREACH(peer_if, &(csm->app_csm.mlacp.pif_list), mlacp_next) + { + if (strcmp(peer_if->name, name) == 0) + return peer_if; + } + + return NULL; +} + +void peer_if_del_all_vlan(struct PeerInterface* pif) +{ + struct VLAN_ID *pvlan = NULL; + + while (!LIST_EMPTY(&(pif->vlan_list))) + { + pvlan = LIST_FIRST(&(pif->vlan_list)); + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", + pif->name, pvlan->vid); + LIST_REMOVE(pvlan, port_next); + free(pvlan); + } + + return; +} + +void peer_if_destroy(struct PeerInterface* pif) +{ + ICCPD_LOG_WARN(__FUNCTION__, "Destroy peer's interface %s, %d", + pif->name, pif->ifindex); + + /* destroy if*/ + LIST_REMOVE(pif, mlacp_next); + peer_if_del_all_vlan(pif); + + free(pif); + return; +} + +int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid) +{ + struct VLAN_ID *vlan = NULL; + char vlan_name[16] = ""; + + sprintf(vlan_name, "Vlan%d", vid); + + /* traverse 1 time */ + LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) + { + if (vlan->vid == vid) + break; + } + + if (!vlan) + { + vlan = (struct VLAN_ID*)malloc(sizeof(struct VLAN_ID)); + if (!vlan) + return MCLAG_ERROR; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Add %s to VLAN %d", local_if->name, vid); + local_if->port_config_sync = 1; + LIST_INSERT_HEAD(&(local_if->vlan_list), vlan, port_next); + } + + vlan_info_init(vlan); + vlan->vid = vid; + vlan->vlan_removed = 0; + vlan->vlan_itf = local_if_find_by_name(vlan_name); + + update_if_ipmac_on_standby(local_if); + + return 0; +} + +void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid) +{ + struct VLAN_ID *vlan = NULL; + + /* traverse 1 time */ + LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) + { + if (vlan->vid == vid) + break; + } + + if (vlan != NULL) + { + LIST_REMOVE(vlan, port_next); + free(vlan); + local_if->port_config_sync = 1; + } + + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", local_if->name, vid); + + return; +} + +void local_if_del_all_vlan(struct LocalInterface* lif) +{ + struct VLAN_ID* vlan = NULL; + + while (!LIST_EMPTY(&(lif->vlan_list))) + { + vlan = LIST_FIRST(&(lif->vlan_list)); + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", lif->name, vlan->vid); + LIST_REMOVE(vlan, port_next); + free(vlan); + } + + return; +} + +/* Add VLAN from peer-link*/ +int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id) +{ + struct VLAN_ID *peer_vlan = NULL; + char vlan_name[16] = ""; + + sprintf(vlan_name, "Vlan%d", vlan_id); + + /* traverse 1 time */ + LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) + { + if (peer_vlan->vid == vlan_id) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Update VLAN ID %d for peer intf %s", peer_vlan->vid, peer_if->name); + break; + } + } + + if (!peer_vlan) + { + peer_vlan = (struct VLAN_ID*)malloc(sizeof(struct VLAN_ID)); + if (!peer_vlan) + return MCLAG_ERROR; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer intf %s to VLAN %d", peer_if->name, vlan_id); + LIST_INSERT_HEAD(&(peer_if->vlan_list), peer_vlan, port_next); + } + + vlan_info_init(peer_vlan); + peer_vlan->vid = vlan_id; + peer_vlan->vlan_removed = 0; + + return 0; +} + +/* Used by sync update*/ +int peer_if_clean_unused_vlan(struct PeerInterface* peer_if) +{ + struct VLAN_ID *peer_vlan = NULL; + struct VLAN_ID *peer_vlan_next = NULL; + + /* traverse 1 time */ + LIST_FOREACH(peer_vlan_next, &(peer_if->vlan_list), port_next) + { + if (peer_vlan != NULL) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", peer_if->name, peer_vlan->vid); + LIST_REMOVE(peer_vlan, port_next); + free(peer_vlan); + peer_vlan = NULL; + + } + if (peer_vlan_next->vlan_removed == 1) + peer_vlan = peer_vlan_next; + } + + if (peer_vlan != NULL) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", peer_if->name, peer_vlan->vid); + LIST_REMOVE(peer_vlan, port_next); + free(peer_vlan); + } + + return 0; +} + +int set_sys_arp_accept_flag(char* ifname, int flag) +{ + FILE *file_ptr = NULL; + char cmd[64]; + char arp_file[64]; + char buf[2]; + int result = MCLAG_ERROR; + + memset(arp_file, 0, 64); + snprintf(arp_file, 63, "/proc/sys/net/ipv4/conf/%s/arp_accept", ifname); + if (!(file_ptr = fopen(arp_file, "r"))) + { + ICCPD_LOG_WARN(__func__, "Failed to find device %s from %s", ifname, arp_file); + return result; + } + + fgets(buf, sizeof(buf), file_ptr); + if (atoi(buf) == flag) + result = 0; + else + { + memset(cmd, 0, 64); + snprintf(cmd, 63, "echo %d > /proc/sys/net/ipv4/conf/%s/arp_accept", flag, ifname); + if (system(cmd)) + ICCPD_LOG_WARN(__func__, "Failed to execute cmd = %s", flag, cmd); + } + + fclose(file_ptr); + return result; +} diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c new file mode 100644 index 000000000000..0ff9d4f5e083 --- /dev/null +++ b/src/iccpd/src/scheduler.c @@ -0,0 +1,773 @@ +/* + * scheduler.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/logger.h" +#include "../include/system.h" +#include "../include/scheduler.h" +#include "../include/iccp_csm.h" +#include "../include/iccp_ifm.h" +#include "../include/iccp_cmd.h" +#include "../include/mlacp_link_handler.h" +#include "../include/iccp_netlink.h" + +/****************************************************** +* +* Global Variable +* +******************************************************/ + +static int session_conn_thread_lock(pthread_mutex_t *conn_mutex) +{ + return 1; /*pthread_mutex_lock(conn_mutex);*/ +} + +static int session_conn_thread_trylock(pthread_mutex_t *conn_mutex) +{ + return 0; /*pthread_mutex_trylock(conn_mutex);*/ +} + +static int session_conn_thread_unlock(pthread_mutex_t *conn_mutex) +{ + return 1;/* pthread_mutex_unlock(conn_mutex);*/ +} + +static void heartbeat_check(struct CSM *csm) +{ + if (csm->heartbeat_update_time == 0) + { + time(&csm->heartbeat_update_time); + return; + } + + if ( (time(NULL) - csm->heartbeat_update_time) > HEARTBEAT_TIMEOUT_SEC) + { + /* hearbeat timeout*/ + ICCPD_LOG_WARN(__FUNCTION__, "iccpd connection timeout (heartbeat)"); + scheduler_session_disconnect_handler(csm); + } + + return; +} + +static void heartbeat_update(struct CSM *csm) +{ + if (csm->sock_fd > 0) + { + heartbeat_check(csm); + } + + return; +} + +/* Transit FSM of all connections */ +static int scheduler_transit_fsm() +{ + struct CSM* csm = NULL; + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return MCLAG_ERROR; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + heartbeat_update(csm); + iccp_csm_transit(csm); + app_csm_transit(csm); + mlacp_fsm_transit(csm); + + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE && (time(NULL) - sys->csm_trans_time) >= 60) + { + iccp_get_fdb_change_from_syncd(); + sys->csm_trans_time = time(NULL); + } + } + + local_if_change_flag_clear(); + local_if_purge_clear(); + + return 1; +} + +/* Receive packets call back function */ +int scheduler_csm_read_callback(struct CSM* csm) +{ + struct Msg* msg = NULL; + /*peer message*/ + char *peer_msg = g_csm_buf; + LDPHdr* ldp_hdr = (LDPHdr*)peer_msg; + char* data = &peer_msg[sizeof(LDPHdr)]; + size_t data_len = 0; + size_t pos = 0; + int recv_len = 0, len = 0, retval; + + if (csm->sock_fd <= 0) + return MCLAG_ERROR; + + memset(peer_msg, 0, CSM_BUFFER_SIZE); + + recv_len = 0; + + while (recv_len != sizeof(LDPHdr)) + { + len = recv(csm->sock_fd, peer_msg + recv_len, sizeof(LDPHdr) - recv_len, 0); + if (len == -1) + { + perror("recv(). Error"); + goto recv_err; + } + else if (len == 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Peer disconnect for receive error"); + goto recv_err; + } + recv_len += len; + /*usleep(100);*/ + } + + data_len = ntohs(ldp_hdr->msg_len) - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + pos = 0; + + while (data_len > 0) + { + recv_len = recv(csm->sock_fd, &data[pos], data_len, 0); + if (recv_len == -1) + { + perror("continue recv(). Error"); + goto recv_err; + } + else if (recv_len == 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Peer disconnect for read error"); + goto recv_err; + } + data_len -= recv_len; + pos += recv_len; + /*usleep(100);*/ + } + + retval = iccp_csm_init_msg(&msg, peer_msg, ntohs(ldp_hdr->msg_len) + MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); + if (retval == 0) + { + iccp_csm_enqueue_msg(csm, msg); + ++csm->icc_msg_in_count; + } + else + ++csm->i_msg_in_count; + + return 1; + + recv_err: + scheduler_session_disconnect_handler(csm); + return MCLAG_ERROR; +} + +/* Handle server accept client */ +int scheduler_server_accept() +{ + int new_fd; + int ret = MCLAG_ERROR; + struct CSM* csm = NULL; + struct System* sys = NULL; + struct sockaddr_in client_addr; + socklen_t addr_len; + + if ((sys = system_get_instance()) == NULL ) + { + return MCLAG_ERROR; + } + if (sys->server_fd <= 0) + { + return MCLAG_ERROR; + } + + addr_len = sizeof(struct sockaddr_in); + new_fd = accept(sys->server_fd, (struct sockaddr *)&client_addr, &addr_len); + if (new_fd == -1) + { + goto reject_client; + } + else + { + csm = system_get_csm_by_peer_ip(inet_ntoa(client_addr.sin_addr)); + if (!csm) + { + /* can't find csm with peer ip*/ + ICCPD_LOG_INFO(__FUNCTION__, "csm null with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); + goto reject_client; + } + + if (csm->sock_fd > 0) + { + /* peer already connected*/ + ICCPD_LOG_INFO(__FUNCTION__, "csm sock is connected with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); + goto reject_client; + } + + if ((ret = scheduler_check_csm_config(csm)) < 0) + { + /* csm config error*/ + ICCPD_LOG_INFO(__FUNCTION__, "csm config error with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); + goto reject_client; + } + } + + /* Accept*/ + goto accept_client; + + reject_client: + if (new_fd >= 0) + close(new_fd); + return MCLAG_ERROR; + + accept_client: + session_conn_thread_lock(&csm->conn_mutex); + ICCPD_LOG_INFO(__FUNCTION__, "Server Accept, SocketFD [%d], %p", new_fd, csm); + + struct epoll_event event; + int err; + event.data.fd = new_fd; + event.events = EPOLLIN; + err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, new_fd, &event); + if (err) + { + session_conn_thread_unlock(&csm->conn_mutex); + goto reject_client; + } + + csm->sock_fd = new_fd; + csm->current_state = ICCP_NONEXISTENT; + FD_SET(new_fd, &(sys->readfd)); + sys->readfd_count++; + session_conn_thread_unlock(&csm->conn_mutex); + return 0; +} + +void iccp_get_start_type(struct System* sys) +{ + FILE* fp; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + + fp = fopen("/proc/cmdline", "r"); + if (!fp) + { + ICCPD_LOG_WARN(__FUNCTION__, "Error: Can't open file /proc/cmdline!"); + return; + } + + fread(g_csm_buf, CSM_BUFFER_SIZE, 1, fp); + (void)fclose(fp); + + if (strstr(g_csm_buf, "SONIC_BOOT_TYPE=warm")) + sys->warmboot_start = WARM_REBOOT; + + return; +} + +/* scheduler initialization */ +void scheduler_init() +{ + struct System* sys = NULL; + + if (!(sys = system_get_instance())) + return; + + iccp_get_start_type(sys); + /*Get kernel interface and port */ + iccp_sys_local_if_list_get_init(); + iccp_sys_local_if_list_get_addr(); + /*Interfaces must be created before this func called*/ + iccp_config_from_file(sys->config_file_path); + + /*Get kernel ARP info */ + iccp_neigh_get_init(); + + if (iccp_connect_syncd() < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Syncd info socket connect fail"); + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Syncd info socket connect success"); + } + + if (mclagd_ctl_sock_create() < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Mclagd ctl info socket connect fail"); + } + + return; +} + +extern int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_size); +void mlacp_sync_send_warmboot_flag() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + int msg_len = 0; + + if ((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_warm_reboot(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); + } + } + + return; +} + +int iccp_receive_signal_handler(struct System* sys) +{ + char ctrl_byte; + int err = 0; + + err = read(sys->sig_pipe_r, &ctrl_byte, 1); + if (err == -1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Read sig_pipe_r fail !"); + return err; + } + + switch (ctrl_byte) + { + case 'w': + /*send packet to peer*/ + mlacp_sync_send_warmboot_flag(); + sys->warmboot_exit = WARM_REBOOT; + break; + + default: + break; + } + + return 0; +} + +/* Thread fetch to call */ +void scheduler_loop() +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + while (1) + { + if (sys->sync_fd <= 0) + { + iccp_connect_syncd(); + } + + /*handle socket slelect event ,If no message received, it will block 0.1s*/ + iccp_handle_events(sys); + /*csm, app state machine transit */ + scheduler_transit_fsm(); + + if (sys->warmboot_exit == WARM_REBOOT) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Warm reboot exit ......"); + return; + } + } + + return; +} + +/***************************************** +* Sync portchannel MAC with kernel +* +* ***************************************/ +int mlacp_sync_with_kernel_callback() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + + if ((sys = system_get_instance()) == NULL) + { + goto out; + } + + /* traverse all CSM */ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + /* Sync MLAG po state with kernel*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) + { + /* sync system info from one port-channel device*/ + if (memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) + { + memcpy(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN); + MLACP(csm).system_config_changed = 1; + break; + } + } + } + } + + out: + return 0; +} + +/* Scheduler start while loop */ +void scheduler_start() +{ + /*mlacp_sync_with_kernel_callback();*/ + + scheduler_loop(); + + return; +} + +/* Scheduler tear down */ +void scheduler_finalize() +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + syncd_info_close(); + + log_finalize(); + + ICCPD_LOG_INFO(__FUNCTION__, "Scheduler is terminated."); + + return; +} + +void session_client_conn_handler(struct CSM *csm) +{ + struct System* sys = NULL; + struct sockaddr_in peer_addr; + int connFd = -1, connStat = -1; + struct timeval con_tv; + socklen_t len = sizeof(con_tv); + int err = 0; + + struct sockaddr_in src_addr; + bzero(&(src_addr), sizeof(src_addr)); + src_addr.sin_family = PF_INET; + src_addr.sin_port = 0; + src_addr.sin_addr.s_addr = inet_addr(csm->sender_ip); + + /* Lock the thread*/ + session_conn_thread_lock(&csm->conn_mutex); + + sys = system_get_instance(); + if (!sys) + goto conn_fail; + + /* Create sock*/ + connFd = socket(PF_INET, SOCK_STREAM, 0); + bzero(&peer_addr, sizeof(peer_addr)); + peer_addr.sin_family = PF_INET; + peer_addr.sin_port = htons(ICCP_TCP_PORT); + peer_addr.sin_addr.s_addr = inet_addr(csm->peer_ip); + if (connFd == -1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer IP:%s Socket FD creation failed.", + csm->peer_ip); + goto conn_fail; + } + + /* Set connect timeout secs*/ + con_tv.tv_sec = 0; + con_tv.tv_usec = CONNECT_TIMEOUT_MSEC * 1000; + if (setsockopt(connFd, SOL_SOCKET, SO_SNDTIMEO, &con_tv, len) == -1) + { + ICCPD_LOG_INFO(__FUNCTION__, "Set socket timeout fail"); + } + + err = bind(connFd, (struct sockaddr*)&(src_addr), sizeof(src_addr)); + if (err < 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Bind socket failed. Error = %d errno = %d ",err,errno); + goto conn_fail; + } + + /* Try conn*/ + ICCPD_LOG_INFO(__FUNCTION__, "Connecting. peer ip = [%s], %p", csm->peer_ip, csm); + connStat = connect(connFd, (struct sockaddr*)&(peer_addr), sizeof(peer_addr)); + ICCPD_LOG_INFO(__FUNCTION__, "Connection. fd = [%d], status = [%d], %p", + connFd, connStat, csm); + + if (connStat != 0) + { + /* Conn Fail*/ + goto conn_fail; + } + else + { + /* Conn OK*/ + struct epoll_event event; + int err; + event.data.fd = connFd; + event.events = EPOLLIN; + err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, connFd, &event); + if (err) + goto conn_fail; + csm->sock_fd = connFd; + FD_SET(connFd, &(sys->readfd)); + sys->readfd_count++; + ICCPD_LOG_INFO(__FUNCTION__, "Connect to server %s sucess .", csm->peer_ip); + goto conn_ok; + } + + conn_fail: + if (connFd >= 0) + { + csm->sock_fd = -1; + close(connFd); + } + conn_ok: + time(&csm->connTimePrev); + session_conn_thread_unlock(&csm->conn_mutex); + return; +} + +/* Create socket connect to peer */ +int scheduler_prepare_session(struct CSM* csm) +{ + int ret = MCLAG_ERROR; + uint32_t local_ip = 0; + uint32_t peer_ip = 0; + + /* Init time_t*/ + if (csm->connTimePrev == 0) + { + time(&csm->connTimePrev); + } + + /* Don't conn to svr continously*/ + if ((time(NULL) - csm->connTimePrev) < CONNECT_INTERVAL_SEC) + { + goto no_time_update; + } + + /* Already conn?*/ + if (csm->sock_fd > 0) + { + goto time_update; + } + + if ((ret = scheduler_check_csm_config(csm)) < 0) + goto time_update; + + /* Who is client*/ + local_ip = inet_addr(csm->sender_ip); + peer_ip = inet_addr(csm->peer_ip); + if (local_ip > peer_ip) + { + goto time_update; + } + else if (local_ip == peer_ip) + { + ICCPD_LOG_WARN(__FUNCTION__, "Local IP must not be the same as the peer IP."); + goto time_update; + } + + if (session_conn_thread_trylock(&csm->conn_mutex) == 0) + { + session_client_conn_handler(csm); + session_conn_thread_unlock(&csm->conn_mutex); + } + + time_update: + time(&csm->connTimePrev); + return 0; + + no_time_update: + return 0; +} + +/* Server socket initialization */ +void scheduler_server_sock_init() +{ + int optval = 1; + struct System* sys = NULL; + struct sockaddr_in src_addr; + + if ((sys = system_get_instance()) == NULL) + return; + + sys->server_fd = socket(PF_INET, SOCK_STREAM, 0); + bzero(&(src_addr), sizeof(src_addr)); + src_addr.sin_family = PF_INET; + src_addr.sin_port = htons(ICCP_TCP_PORT); + src_addr.sin_addr.s_addr = INADDR_ANY; + + if (sys->server_fd == -1) + { + ICCPD_LOG_ERR(__FUNCTION__, "Server Socket FD creation failed."); + return; + } + + if (setsockopt(sys->server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) + { + ICCPD_LOG_INFO(__FUNCTION__, "Set socket option failed. Error"); + /*return;*/ + } + + if (bind(sys->server_fd, (struct sockaddr*)&(src_addr), sizeof(src_addr)) < 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Bind socket failed. Error"); + return; + } + + if (listen(sys->server_fd, MAX_ACCEPT_CONNETIONS) == -1) + { + ICCPD_LOG_INFO(__FUNCTION__, "Listen failed. Error"); + return; + } + + ICCPD_LOG_INFO(__FUNCTION__, "Server socket init done."); + + return; +} + +int iccp_get_server_sock_fd() +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return 0; + + return sys->server_fd; +} + +/* Server socket initialization */ +int scheduler_check_csm_config(struct CSM* csm) +{ + int ret = 1; + struct LocalInterface* lif = NULL; + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return MCLAG_ERROR; + + if (csm == NULL ) + return MCLAG_ERROR; + + if (csm->mlag_id <= 0) + ret = MCLAG_ERROR; + else if (strlen(csm->peer_ip) <= 0) + ret = MCLAG_ERROR; + else if (strlen(csm->sender_ip) <= 0) + ret = MCLAG_ERROR; + else if (strlen(csm->peer_itf_name) != 0) + { + lif = local_if_find_by_name(csm->peer_itf_name); + if (lif == NULL) + { + /*if peer-link is configured but the interface is not created, peer connection can not establish*/ + return MCLAG_ERROR; + } + else + { + lif->is_peer_link = 1; + csm->peer_link_if = lif; + } + } + + if (ret == MCLAG_ERROR) + ICCPD_LOG_INFO(__FUNCTION__, "mclag config is not complete or conflicting, please check!"); + + /* Decide STP role*/ + iccp_csm_stp_role_count(csm); + + return ret; +} + +int scheduler_unregister_sock_read_event_callback(struct CSM* csm) +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL ) + return MCLAG_ERROR; + + if (csm == NULL ) + { + return MCLAG_ERROR; + } + + if (csm->sock_fd > 0) + { + FD_CLR(csm->sock_fd, &(sys->readfd)); + } + + return 0; +} + +void scheduler_session_disconnect_handler(struct CSM* csm) +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL ) + return; + + struct epoll_event event; + + if (csm == NULL) + return; + + session_conn_thread_lock(&csm->conn_mutex); + scheduler_unregister_sock_read_event_callback(csm); + if (csm->sock_fd > 0) + { + event.data.fd = csm->sock_fd; + event.events = EPOLLIN; + epoll_ctl(sys->epoll_fd, EPOLL_CTL_DEL, csm->sock_fd, &event); + + close(csm->sock_fd); + csm->sock_fd = -1; + } + + mlacp_peer_disconn_handler(csm); + MLACP(csm).current_state = MLACP_STATE_INIT; + iccp_csm_status_reset(csm, 0); + time(&csm->connTimePrev); + session_conn_thread_unlock(&csm->conn_mutex); + + return; +} diff --git a/src/iccpd/src/system.c b/src/iccpd/src/system.c new file mode 100644 index 000000000000..33aca67f8079 --- /dev/null +++ b/src/iccpd/src/system.c @@ -0,0 +1,203 @@ +/* + * system.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * 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, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ + +#include + +#include "../include/iccp_csm.h" +#include "../include/logger.h" +#include "../include/iccp_netlink.h" +#include "../include/scheduler.h" + +/* Singleton */ +struct System* system_get_instance() +{ + static struct System* sys = NULL; + + if (sys == NULL ) + { + sys = (struct System*)malloc(sizeof(struct System)); + if (sys == NULL ) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain system instance."); + return NULL; + } + system_init(sys); + } + + return sys; +} + +/* System instance initialization */ +void system_init(struct System* sys) +{ + if (sys == NULL ) + return; + + sys->server_fd = -1; + sys->sync_fd = -1; + sys->sync_ctrl_fd = -1; + sys->arp_receive_fd = -1; + sys->ndisc_receive_fd = -1; + sys->epoll_fd = -1; + sys->family = -1; + sys->warmboot_start = 0; + sys->warmboot_exit = 0; + LIST_INIT(&(sys->csm_list)); + LIST_INIT(&(sys->lif_list)); + LIST_INIT(&(sys->lif_purge_list)); + + sys->log_file_path = strdup("/var/log/iccpd.log"); + sys->cmd_file_path = strdup("/var/run/iccpd/iccpd.vty"); + sys->config_file_path = strdup("/etc/iccpd/iccpd.conf"); + sys->mclagdctl_file_path = strdup("/var/run/iccpd/mclagdctl.sock"); + sys->pid_file_fd = 0; + sys->telnet_port = 2015; + FD_ZERO(&(sys->readfd)); + sys->readfd_count = 0; + sys->csm_trans_time = 0; + sys->need_sync_team_again = 0; + sys->need_sync_netlink_again = 0; + scheduler_server_sock_init(); + iccp_system_init_netlink_socket(); + iccp_init_netlink_event_fd(sys); +} + +/* System instance tear down */ +void system_finalize() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + + if ((sys = system_get_instance()) == NULL ) + return; + + ICCPD_LOG_INFO(__FUNCTION__, "System resource pool is destructing."); + + while (!LIST_EMPTY(&(sys->csm_list))) + { + csm = LIST_FIRST(&(sys->csm_list)); + iccp_csm_finalize(csm); + } + + /* Release all port objects */ + while (!LIST_EMPTY(&(sys->lif_list))) + { + local_if = LIST_FIRST(&(sys->lif_list)); + LIST_REMOVE(local_if, system_next); + local_if_finalize(local_if); + } + + while (!LIST_EMPTY(&(sys->lif_purge_list))) + { + local_if = LIST_FIRST(&(sys->lif_purge_list)); + LIST_REMOVE(local_if, system_purge_next); + local_if_finalize(local_if); + } + + iccp_system_dinit_netlink_socket(); + + if (sys->log_file_path != NULL ) + free(sys->log_file_path); + if (sys->cmd_file_path != NULL ) + free(sys->cmd_file_path); + if (sys->config_file_path != NULL ) + free(sys->config_file_path); + if (sys->pid_file_fd > 0) + close(sys->pid_file_fd); + if (sys->server_fd > 0) + close(sys->server_fd); + if (sys->sync_fd > 0) + close(sys->sync_fd); + if (sys->sync_ctrl_fd > 0) + close(sys->sync_ctrl_fd); + if (sys->arp_receive_fd > 0) + close(sys->arp_receive_fd); + if (sys->ndisc_receive_fd > 0) + close(sys->ndisc_receive_fd); + if (sys->sig_pipe_r > 0) + close(sys->sig_pipe_r); + if (sys->sig_pipe_w > 0) + close(sys->sig_pipe_w); + + if (sys->epoll_fd) + close(sys->epoll_fd); + + free(sys); + ICCPD_LOG_INFO(__FUNCTION__, "System resource pool destructed successfully..."); +} + +struct CSM* system_create_csm() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return NULL; + + /* Create a new csm */ + csm = (struct CSM*)malloc(sizeof(struct CSM)); + if (csm == NULL ) + return NULL; + else + memset(csm, 0, sizeof(struct CSM)); + iccp_csm_init(csm); + LIST_INSERT_HEAD(&(sys->csm_list), csm, next); + + return csm; +} + +/* Get connect state machine instance by peer ip */ +struct CSM* system_get_csm_by_peer_ip(const char* peer_ip) +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return NULL; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (strcmp(csm->peer_ip, peer_ip) == 0) + return csm; + } + + return NULL; +} + +struct CSM* system_get_csm_by_mlacp_id(int id) +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return NULL; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (csm->app_csm.mlacp.id == id) + return csm; + } + + return NULL; +} diff --git a/src/ifupdown2/.gitignore b/src/ifupdown2/.gitignore new file mode 100644 index 000000000000..d1cfec62d283 --- /dev/null +++ b/src/ifupdown2/.gitignore @@ -0,0 +1 @@ +ifupdown2-1.2.8-1/ diff --git a/src/ifupdown2/Makefile b/src/ifupdown2/Makefile new file mode 100644 index 000000000000..89228bedafae --- /dev/null +++ b/src/ifupdown2/Makefile @@ -0,0 +1,21 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(IFUPDOWN2) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./ifupdown2-$(IFUPDOWN2_VERSION) ./$(IFUPDOWN2_VERSION).tar.gz + + # Get ifupdown2 release + wget --no-check-certificate https://github.com/CumulusNetworks/ifupdown2/archive/$(IFUPDOWN2_VERSION).tar.gz + tar -z -f $(IFUPDOWN2_VERSION).tar.gz -x + pushd ./ifupdown2-$(IFUPDOWN2_VERSION) + + # Build source and Debian packages + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + # Move the newly-built .deb packages to the destination directory + mv $* $(DEST)/ diff --git a/src/initramfs-tools/.gitignore b/src/initramfs-tools/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/initramfs-tools/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/initramfs-tools/Makefile b/src/initramfs-tools/Makefile new file mode 100644 index 000000000000..f57b943d2d4f --- /dev/null +++ b/src/initramfs-tools/Makefile @@ -0,0 +1,27 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = initramfs-tools_$(INITRAMFS_TOOLS_VERSION)_all.deb +DERIVED_TARGETS = initramfs-tools-core_$(INITRAMFS_TOOLS_VERSION)_all.deb + +INITRAMFS_TOOLS_REVISION = 40e544e13611c1b2690eb99a8096fc16c1b9c74e + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtaining the initramfs-tools + rm -rf ./initramfs-tools + git clone --branch v0.133 https://salsa.debian.org/kernel-team/initramfs-tools.git ./initramfs-tools + + # Patch + pushd ./initramfs-tools + git checkout $(INITRAMFS_TOOLS_REVISION) + QUILT_PATCHES=.. quilt push -a + + # Build the package + rm -f debian/*.debhelper.log + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/initramfs-tools/loopback-file-offset-support.patch b/src/initramfs-tools/loopback-file-offset-support.patch new file mode 100644 index 000000000000..396e1c92007a --- /dev/null +++ b/src/initramfs-tools/loopback-file-offset-support.patch @@ -0,0 +1,73 @@ +From: Samuel Angebault +Date: Tue, 9 Jun 2020 14:43:31 -0700 +Subject: Add loopback from file support + +By providing the extra loopoffset= parameter, it becomes possible to +mount a rootfs from within the file pointed by loop= at a given offset. +This mechanism uses losetup to create a loopdevice +--- + init | 4 ++++ + initramfs-tools.7 | 5 +++++ + scripts/functions | 8 ++++++++ + 3 files changed, 17 insertions(+) + +diff --git a/init b/init +index fe1005a..5fb054f 100755 +--- a/init ++++ b/init +@@ -52,6 +52,7 @@ export ROOTFSTYPE= + export LOOP= + export LOOPFLAGS= + export LOOPFSTYPE= ++export LOOPOFFSET= + export IP= + export DEVICE= + export BOOT= +@@ -116,6 +117,9 @@ for x in $(cat /proc/cmdline); do + loopfstype=*) + LOOPFSTYPE="${x#loopfstype=}" + ;; ++ loopoffset=*) ++ LOOPOFFSET="${x#loopoffset=}" ++ ;; + nfsroot=*) + # shellcheck disable=SC2034 + NFSROOT="${x#nfsroot=}" +diff --git a/initramfs-tools.7 b/initramfs-tools.7 +index 745e7a0..a5d92b0 100644 +--- a/initramfs-tools.7 ++++ b/initramfs-tools.7 +@@ -66,6 +66,11 @@ set the loop file system mount option string, if applicable. + \fB\fI loopfstype + set the loop file system type, if applicable. + ++.TP ++\fB\fI loopoffset ++set the loop file offset from which to mount the loop, if applicable. ++The default is 0 and requires loop to be defined. ++ + .TP + \fB\fI nfsroot + can be either "auto" to try to get the relevant information from DHCP or a +diff --git a/scripts/functions b/scripts/functions +index a17e740..2bef5cb 100644 +--- a/scripts/functions ++++ b/scripts/functions +@@ -473,6 +473,14 @@ mount_loop_root() + modprobe loop + modprobe "${FSTYPE}" + ++ if [ ! -z "${LOOPOFFSET}" ]; then ++ # create a loop device for the fs within the file ++ loopdev="$(losetup -f)" ++ losetup -o "${LOOPOFFSET:-0}" "${loopdev}" "${loopfile}" || \ ++ panic "ALERT! $loopdev could not be setup using $loopfile" ++ loopfile="$loopdev" ++ fi ++ + # FIXME This has no error checking + if [ -z "${LOOPFLAGS}" ]; then + mount ${roflag} -o loop -t "${FSTYPE}" "$loopfile" "${rootmnt}" +-- +2.26.2 + diff --git a/patch/initramfs-tools/loopback-file-system-support.patch b/src/initramfs-tools/loopback-file-system-support.patch similarity index 56% rename from patch/initramfs-tools/loopback-file-system-support.patch rename to src/initramfs-tools/loopback-file-system-support.patch index e5b75478dc96..fbeb347f9d23 100644 --- a/patch/initramfs-tools/loopback-file-system-support.patch +++ b/src/initramfs-tools/loopback-file-system-support.patch @@ -13,11 +13,29 @@ And added NFS support! Full patch below... live well, vagrant +--- + init | 12 ++++++++++++ + initramfs-tools.7 | 13 +++++++++++++ + scripts/functions | 40 ++++++++++++++++++++++++++++++++++++++++ + scripts/local | 7 ++++++- + scripts/nfs | 4 ++++ + 5 files changed, 75 insertions(+), 1 deletion(-) + diff --git a/init b/init -index abf7f25..2760bcb 100755 +index 3dc9f6b..fe1005a 100755 --- a/init +++ b/init -@@ -98,6 +98,15 @@ for x in $(cat /proc/cmdline); do +@@ -49,6 +49,9 @@ export ROOT= + export ROOTDELAY= + export ROOTFLAGS= + export ROOTFSTYPE= ++export LOOP= ++export LOOPFLAGS= ++export LOOPFSTYPE= + export IP= + export DEVICE= + export BOOT= +@@ -104,6 +107,15 @@ for x in $(cat /proc/cmdline); do ;; esac ;; @@ -31,16 +49,17 @@ index abf7f25..2760bcb 100755 + LOOPFSTYPE="${x#loopfstype=}" + ;; nfsroot=*) + # shellcheck disable=SC2034 NFSROOT="${x#nfsroot=}" - ;; -diff --git a/initramfs-tools.8 b/initramfs-tools.8 -index ea8c098..ce8e830 100644 ---- a/initramfs-tools.8 -+++ b/initramfs-tools.8 -@@ -42,6 +42,19 @@ The default is 180 seconds. +diff --git a/initramfs-tools.7 b/initramfs-tools.7 +index 45b7de7..745e7a0 100644 +--- a/initramfs-tools.7 ++++ b/initramfs-tools.7 +@@ -53,6 +53,19 @@ The default is 180 seconds. + \fB\fI rootflags set the file system mount option string. - .TP ++.TP +\fB\fI loop +path within the original root file system to loop-mount and use as the +real root file system. @@ -53,15 +72,14 @@ index ea8c098..ce8e830 100644 +\fB\fI loopfstype +set the loop file system type, if applicable. + -+.TP + .TP \fB\fI nfsroot can be either "auto" to try to get the relevant information from DHCP or a - string of the form NFSSERVER:NFSPATH or NFSSERVER:NFSPATH:NFSOPTS. diff --git a/scripts/functions b/scripts/functions -index 8c1bb1f..2ed3ce3 100644 +index 077697f..a17e740 100644 --- a/scripts/functions +++ b/scripts/functions -@@ -426,6 +426,42 @@ mountfs() +@@ -445,6 +445,46 @@ mountfs() ${type}_mount_fs "$1" } @@ -69,14 +87,14 @@ index 8c1bb1f..2ed3ce3 100644 +mount_loop_root() +{ + mkdir -p /host -+ mount -o move ${rootmnt} /host ++ mount -o move "${rootmnt}" /host + loopfile="/host/${LOOP#/}" + + while [ ! -e "$loopfile" ]; do + panic "ALERT! $loopfile does not exist. Dropping to a shell!" + done + -+ if [ ${readonly} = y ]; then ++ if [ "${readonly?}" = "y" ]; then + roflag=-r + else + roflag=-w @@ -91,13 +109,17 @@ index 8c1bb1f..2ed3ce3 100644 + + # FIXME This has no error checking + modprobe loop -+ modprobe ${FSTYPE} ++ modprobe "${FSTYPE}" + + # FIXME This has no error checking -+ mount ${roflag} -o loop -t ${FSTYPE} ${LOOPFLAGS} "$loopfile" ${rootmnt} ++ if [ -z "${LOOPFLAGS}" ]; then ++ mount ${roflag} -o loop -t "${FSTYPE}" "$loopfile" "${rootmnt}" ++ else ++ mount ${roflag} -o loop -t "${FSTYPE}" "${LOOPFLAGS}" "$loopfile" "${rootmnt}" ++ fi + -+ if [ -d ${rootmnt}/host ]; then -+ mount -o move /host ${rootmnt}/host ++ if [ -d "${rootmnt}/host" ]; then ++ mount -o move /host "${rootmnt}/host" + fi +} + @@ -105,22 +127,22 @@ index 8c1bb1f..2ed3ce3 100644 # boot scripts. mountroot() diff --git a/scripts/local b/scripts/local -index f6424f0..072013e 100644 +index a103e68..2ef6413 100644 --- a/scripts/local +++ b/scripts/local -@@ -135,7 +135,8 @@ local_mount_root() +@@ -170,7 +170,8 @@ local_mount_root() - ROOT=$(resolve_device "$ROOT") + local_premount -- if [ "${readonly}" = "y" ]; then -+ if [ "${readonly}" = "y" ] && \ -+ ([ -z "$LOOP" ] || [ "${FSTYPE#ntfs}" = "$FSTYPE" ]); then +- if [ "${readonly?}" = "y" ]; then ++ if [ "${readonly?}" = "y" ] && \ ++ { [ -z "$LOOP" ] || [ "${FSTYPE#ntfs}" = "$FSTYPE" ]; }; then roflag=-r else roflag=-w -@@ -153,6 +154,10 @@ local_mount_root() - else - mount ${roflag} ${ROOTFLAGS} ${ROOT} ${rootmnt} +@@ -183,6 +184,10 @@ local_mount_root() + if ! mount ${roflag} ${FSTYPE:+-t "${FSTYPE}"} ${ROOTFLAGS} "${ROOT}" "${rootmnt?}"; then + panic "Failed to mount ${ROOT} as root file system." fi + + if [ "${LOOP}" ]; then @@ -130,13 +152,13 @@ index f6424f0..072013e 100644 local_mount_fs() diff --git a/scripts/nfs b/scripts/nfs -index 1c29850..d382413 100644 +index 40c92c7..dfa8e88 100644 --- a/scripts/nfs +++ b/scripts/nfs -@@ -72,6 +72,10 @@ nfs_mount_root_impl() - fi +@@ -73,6 +73,10 @@ nfs_mount_root_impl() - nfsmount -o nolock ${roflag} ${NFSOPTS} ${NFSROOT} ${rootmnt} + # shellcheck disable=SC2086 + nfsmount -o nolock ${roflag} ${NFSOPTS} "${NFSROOT}" "${rootmnt?}" + + if [ "${LOOP}" ]; then + mount_loop_root @@ -144,3 +166,6 @@ index 1c29850..d382413 100644 } # NFS root mounting +-- +2.17.1 + diff --git a/src/initramfs-tools/series b/src/initramfs-tools/series new file mode 100644 index 000000000000..ba6e8edfacd4 --- /dev/null +++ b/src/initramfs-tools/series @@ -0,0 +1,2 @@ +loopback-file-system-support.patch +loopback-file-offset-support.patch diff --git a/src/iproute2/.gitignore b/src/iproute2/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/iproute2/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/iproute2/Makefile b/src/iproute2/Makefile new file mode 100644 index 000000000000..5b354ce8b019 --- /dev/null +++ b/src/iproute2/Makefile @@ -0,0 +1,23 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + +IPROUTE2_VERSION = 4.9.0 +IPROUTE2_VERSION_FULL = $(IPROUTE2_VERSION)-1 + +MAIN_TARGET = iproute2_$(IPROUTE2_VERSION_FULL)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf iproute2-$(IPROUTE2_VERSION) + + wget -O iproute2_$(IPROUTE2_VERSION).orig.tar.xz -N "https://sonicstorage.blob.core.windows.net/packages/iproute2_4.9.0.orig.tar.xz?sv=2015-04-05&sr=b&sig=9nvybd1xkXyRQbaG6Fy6wBazPA8IbZV0AO41GWXPEP8%3D&se=2154-10-23T11%3A59%3A00Z&sp=r" + wget -O iproute2_$(IPROUTE2_VERSION_FULL).dsc -N "https://sonicstorage.blob.core.windows.net/packages/iproute2_4.9.0-1.dsc?sv=2015-04-05&sr=b&sig=m6FcMH9dOh8ggipBgOsONiXvDxoi6bfUO%2BxvidsMNMQ%3D&se=2154-10-23T11%3A59%3A53Z&sp=r" + wget -O iproute2_$(IPROUTE2_VERSION_FULL).debian.tar.xz -N "https://sonicstorage.blob.core.windows.net/packages/iproute2_4.9.0-1.debian.tar.xz?sv=2015-04-05&sr=b&sig=U5NFuwG5C3vZXlUUNvoPMnKDtMKk66zbweA9rQYbEVY%3D&se=2154-10-23T12%3A00%3A15Z&sp=r" + dpkg-source -x iproute2_$(IPROUTE2_VERSION_FULL).dsc + + pushd iproute2-$(IPROUTE2_VERSION) + dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $* $(DEST)/ diff --git a/src/iptables/.gitignore b/src/iptables/.gitignore new file mode 100644 index 000000000000..d19db76ab9a9 --- /dev/null +++ b/src/iptables/.gitignore @@ -0,0 +1,4 @@ +* +!.gitignore +!Makefile +!patch/ diff --git a/src/iptables/Makefile b/src/iptables/Makefile new file mode 100644 index 000000000000..681ef5d2dcc3 --- /dev/null +++ b/src/iptables/Makefile @@ -0,0 +1,47 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(IPTABLES) +DERIVED_TARGETS = libip4tc0_$(IPTABLES_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + libip6tc0_$(IPTABLES_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + libiptc0_$(IPTABLES_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + libxtables12_$(IPTABLES_VERSION_FULL)_$(CONFIGURED_ARCH).deb + +IPTABLES_URL = http://deb.debian.org/debian/pool/main/i/iptables + +DSC_FILE = iptables_$(IPTABLES_VERSION_FULL).dsc +ORIG_FILE = iptables_$(IPTABLES_VERSION).orig.tar.bz2 +DEBIAN_FILE = iptables_$(IPTABLES_VERSION_FULL).debian.tar.xz + +DSC_FILE_URL = $(IPTABLES_URL)/$(DSC_FILE) +ORIG_FILE_URL = $(IPTABLES_URL)/$(ORIG_FILE) +DEBIAN_FILE_URL = $(IPTABLES_URL)/$(DEBIAN_FILE) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./iptables-$(IPTABLES_VERSION) + + # Get iptables release + wget -NO "$(DSC_FILE)" $(DSC_FILE_URL) + wget -NO "$(ORIG_FILE)" $(ORIG_FILE_URL) + wget -NO "$(DEBIAN_FILE)" $(DEBIAN_FILE_URL) + dpkg-source -x iptables_$(IPTABLES_VERSION_FULL).dsc + + pushd iptables-$(IPTABLES_VERSION) + git init + git add -f * + git commit -m "unmodified iptables source" + + # Apply patches + stg init + stg import -s ../patch/series + + # Build source and Debian packages + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + # Move the newly-built .deb packages to the destination directory + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/iptables/patch/0001-Passing-fullcone-option-for-SNAT-and-DNAT.patch b/src/iptables/patch/0001-Passing-fullcone-option-for-SNAT-and-DNAT.patch new file mode 100644 index 000000000000..9ed886bb5dbd --- /dev/null +++ b/src/iptables/patch/0001-Passing-fullcone-option-for-SNAT-and-DNAT.patch @@ -0,0 +1,321 @@ +From 92f5aee7372748845f11b7a10d880f968769e860 Mon Sep 17 00:00:00 2001 +From: Kiran Kella +Date: Wed, 7 Aug 2019 07:22:42 -0700 +Subject: [PATCH] Passing fullcone option for SNAT and DNAT + +--- + extensions/libipt_DNAT.c | 22 +++++++++++++++++++++- + extensions/libipt_MASQUERADE.c | 21 ++++++++++++++++++++- + extensions/libipt_SNAT.c | 22 +++++++++++++++++++++- + 3 files changed, 62 insertions(+), 3 deletions(-) + +diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c +index 4907a2e..543421c 100644 +--- a/extensions/libipt_DNAT.c ++++ b/extensions/libipt_DNAT.c +@@ -8,14 +8,20 @@ + #include + #include + ++/* Temporarily defining here, need to be picked up from the ++ * new kernel header linux/netfilter/nf_nat.h */ ++#define NF_NAT_RANGE_FULLCONE (1 << 6) ++ + enum { + O_TO_DEST = 0, + O_RANDOM, + O_PERSISTENT, + O_X_TO_DEST, /* hidden flag */ ++ O_FULLCONE, + F_TO_DEST = 1 << O_TO_DEST, + F_RANDOM = 1 << O_RANDOM, + F_X_TO_DEST = 1 << O_X_TO_DEST, ++ F_FULLCONE = 1 << O_FULLCONE + }; + + /* Dest NAT data consists of a multi-range, indicating where to map +@@ -32,7 +38,7 @@ static void DNAT_help(void) + "DNAT target options:\n" + " --to-destination [[-]][:port[-port]]\n" + " Address to map destination to.\n" +-"[--random] [--persistent]\n"); ++"[--random] [--persistent] [--fullcone]\n"); + } + + static void DNAT_help_v2(void) +@@ -41,7 +47,7 @@ static void DNAT_help_v2(void) + "DNAT target options:\n" + " --to-destination [[-]][:port[-port[/port]]]\n" + " Address to map destination to.\n" +-"[--random] [--persistent]\n"); ++"[--random] [--persistent] [--fullcone]\n"); + } + + static const struct xt_option_entry DNAT_opts[] = { +@@ -49,6 +55,7 @@ static const struct xt_option_entry DNAT_opts[] = { + .flags = XTOPT_MAND | XTOPT_MULTI}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, ++ {.name = "fullcone", .id = O_FULLCONE, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, + }; + +@@ -194,10 +201,14 @@ static void DNAT_parse(struct xt_option_call *cb) + static void DNAT_fcheck(struct xt_fcheck_call *cb) + { + static const unsigned int f = F_TO_DEST | F_RANDOM; ++ static const unsigned int c = F_FULLCONE; + struct nf_nat_ipv4_multi_range_compat *mr = cb->data; + + if ((cb->xflags & f) == f) + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; ++ ++ if ((cb->xflags & c) == c) ++ mr->range[0].flags |= NF_NAT_RANGE_FULLCONE; + } + + static void print_range(const struct nf_nat_ipv4_range *r) +@@ -233,6 +244,8 @@ static void DNAT_print(const void *ip, const struct xt_entry_target *target, + printf(" random"); + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) + printf(" persistent"); ++ if (info->mr.range[i].flags & NF_NAT_RANGE_FULLCONE) ++ printf(" fullcone"); + } + } + +@@ -248,6 +261,8 @@ static void DNAT_save(const void *ip, const struct xt_entry_target *target) + printf(" --random"); + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) + printf(" --persistent"); ++ if (info->mr.range[i].flags & NF_NAT_RANGE_FULLCONE) ++ printf(" --fullcone"); + } + } + +@@ -291,6 +306,11 @@ static int DNAT_xlate(struct xt_xlate *xl, + sep = ","; + xt_xlate_add(xl, "%spersistent", sep); + } ++ if (info->mr.range[i].flags & NF_NAT_RANGE_FULLCONE) { ++ if (sep_need) ++ sep = ","; ++ xt_xlate_add(xl, "%sfullcone", sep); ++ } + } + + return 1; +@@ -426,10 +446,14 @@ static void DNAT_parse_v2(struct xt_option_call *cb) + static void DNAT_fcheck_v2(struct xt_fcheck_call *cb) + { + static const unsigned int f = F_TO_DEST | F_RANDOM; ++ static const unsigned int c = F_FULLCONE; + struct nf_nat_range2 *range = cb->data; + + if ((cb->xflags & f) == f) + range->flags |= NF_NAT_RANGE_PROTO_RANDOM; ++ ++ if ((cb->xflags & c) == c) ++ range->flags |= NF_NAT_RANGE_FULLCONE; + } + + static void print_range_v2(const struct nf_nat_range2 *range) +@@ -461,6 +485,8 @@ static void DNAT_print_v2(const void *ip, const struct xt_entry_target *target, + printf(" random"); + if (range->flags & NF_NAT_RANGE_PERSISTENT) + printf(" persistent"); ++ if (range->flags & NF_NAT_RANGE_FULLCONE) ++ printf(" fullcone"); + } + + static void DNAT_save_v2(const void *ip, const struct xt_entry_target *target) +@@ -473,6 +499,8 @@ static void DNAT_save_v2(const void *ip, const struct xt_entry_target *target) + printf(" --random"); + if (range->flags & NF_NAT_RANGE_PERSISTENT) + printf(" --persistent"); ++ if (range->flags & NF_NAT_RANGE_FULLCONE) ++ printf(" --fullcone"); + } + + static void print_range_xlate_v2(const struct nf_nat_range2 *range, +@@ -512,6 +540,11 @@ static int DNAT_xlate_v2(struct xt_xlate *xl, + sep = ","; + xt_xlate_add(xl, "%spersistent", sep); + } ++ if (range->flags & NF_NAT_RANGE_FULLCONE) { ++ if (sep_need) ++ sep = ","; ++ xt_xlate_add(xl, "%sfullcone", sep); ++ } + + return 1; + } +diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c +index 90bf606..169457d 100644 +--- a/extensions/libipt_MASQUERADE.c ++++ b/extensions/libipt_MASQUERADE.c +@@ -8,10 +8,15 @@ + #include + #include + ++/* Temporarily defining here, need to be picked up from the ++ * new kernel header linux/netfilter/nf_nat.h */ ++#define NF_NAT_RANGE_FULLCONE (1 << 6) ++ + enum { + O_TO_PORTS = 0, + O_RANDOM, + O_RANDOM_FULLY, ++ O_FULLCONE + }; + + static void MASQUERADE_help(void) +@@ -23,13 +28,16 @@ static void MASQUERADE_help(void) + " --random\n" + " Randomize source port.\n" + " --random-fully\n" +-" Fully randomize source port.\n"); ++" Fully randomize source port.\n" ++" --fullcone\n" ++" Do fullcone NAT mapping.\n"); + } + + static const struct xt_option_entry MASQUERADE_opts[] = { + {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING}, + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE}, ++ {.name = "fullcone", .id = O_FULLCONE, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, + }; + +@@ -104,6 +112,9 @@ static void MASQUERADE_parse(struct xt_option_call *cb) + case O_RANDOM_FULLY: + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY; + break; ++ case O_FULLCONE: ++ mr->range[0].flags |= NF_NAT_RANGE_FULLCONE; ++ break; + } + } + +@@ -126,6 +137,9 @@ MASQUERADE_print(const void *ip, const struct xt_entry_target *target, + + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) + printf(" random-fully"); ++ ++ if (r->flags & NF_NAT_RANGE_FULLCONE) ++ printf(" fullcone"); + } + + static void +@@ -145,6 +159,9 @@ MASQUERADE_save(const void *ip, const struct xt_entry_target *target) + + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) + printf(" --random-fully"); ++ ++ if (r->flags & NF_NAT_RANGE_FULLCONE) ++ printf(" --fullcone"); + } + + static int MASQUERADE_xlate(struct xt_xlate *xl, +@@ -166,6 +183,9 @@ static int MASQUERADE_xlate(struct xt_xlate *xl, + if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) + xt_xlate_add(xl, "random "); + ++ if (r->flags & NF_NAT_RANGE_FULLCONE) ++ xt_xlate_add(xl, "fullcone "); ++ + return 1; + } + +diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c +index e92d811..ad42b8c 100644 +--- a/extensions/libipt_SNAT.c ++++ b/extensions/libipt_SNAT.c +@@ -8,16 +8,22 @@ + #include + #include + ++/* Temporarily defining here, need to be picked up from the ++ * new kernel header linux/netfilter/nf_nat.h */ ++#define NF_NAT_RANGE_FULLCONE (1 << 6) ++ + enum { + O_TO_SRC = 0, + O_RANDOM, + O_RANDOM_FULLY, + O_PERSISTENT, + O_X_TO_SRC, ++ O_FULLCONE, + F_TO_SRC = 1 << O_TO_SRC, + F_RANDOM = 1 << O_RANDOM, + F_RANDOM_FULLY = 1 << O_RANDOM_FULLY, + F_X_TO_SRC = 1 << O_X_TO_SRC, ++ F_FULLCONE = 1 << O_FULLCONE + }; + + /* Source NAT data consists of a multi-range, indicating where to map +@@ -34,7 +40,7 @@ static void SNAT_help(void) + "SNAT target options:\n" + " --to-source [[-]][:port[-port]]\n" + " Address to map source to.\n" +-"[--random] [--random-fully] [--persistent]\n"); ++"[--random] [--random-fully] [--persistent] [--fullcone]\n"); + } + + static const struct xt_option_entry SNAT_opts[] = { +@@ -43,6 +49,7 @@ static const struct xt_option_entry SNAT_opts[] = { + {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, + {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE}, + {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, ++ {.name = "fullcone", .id = O_FULLCONE, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, + }; + +@@ -189,12 +196,15 @@ static void SNAT_fcheck(struct xt_fcheck_call *cb) + { + static const unsigned int f = F_TO_SRC | F_RANDOM; + static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY; ++ static const unsigned int c = F_TO_SRC | F_FULLCONE; + struct nf_nat_ipv4_multi_range_compat *mr = cb->data; + + if ((cb->xflags & f) == f) + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM; + if ((cb->xflags & r) == r) + mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY; ++ if ((cb->xflags & c) == c) ++ mr->range[0].flags |= NF_NAT_RANGE_FULLCONE; + } + + static void print_range(const struct nf_nat_ipv4_range *r) +@@ -232,6 +242,8 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target, + printf(" random-fully"); + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) + printf(" persistent"); ++ if (info->mr.range[i].flags & NF_NAT_RANGE_FULLCONE) ++ printf(" fullcone"); + } + } + +@@ -249,6 +261,8 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target) + printf(" --random-fully"); + if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT) + printf(" --persistent"); ++ if (info->mr.range[i].flags & NF_NAT_RANGE_FULLCONE) ++ printf(" --fullcone"); + } + } + +@@ -299,6 +313,12 @@ static int SNAT_xlate(struct xt_xlate *xl, + sep = ","; + xt_xlate_add(xl, "%spersistent", sep); + } ++ if (info->mr.range[i].flags & NF_NAT_RANGE_FULLCONE) { ++ if (sep_need) ++ sep = ","; ++ xt_xlate_add(xl, "%sfullcone", sep); ++ sep_need = true; ++ } + } + + return 1; diff --git a/src/iptables/patch/series b/src/iptables/patch/series new file mode 100644 index 000000000000..df084ed96ed3 --- /dev/null +++ b/src/iptables/patch/series @@ -0,0 +1 @@ +0001-Passing-fullcone-option-for-SNAT-and-DNAT.patch diff --git a/src/isc-dhcp/.gitignore b/src/isc-dhcp/.gitignore new file mode 100644 index 000000000000..d19db76ab9a9 --- /dev/null +++ b/src/isc-dhcp/.gitignore @@ -0,0 +1,4 @@ +* +!.gitignore +!Makefile +!patch/ diff --git a/src/isc-dhcp/Makefile b/src/isc-dhcp/Makefile new file mode 100644 index 000000000000..2adf6bba2aa3 --- /dev/null +++ b/src/isc-dhcp/Makefile @@ -0,0 +1,32 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(ISC_DHCP_RELAY) +DERIVED_TARGETS = $(ISC_DHCP_RELAY_DBG) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./isc-dhcp + + # Clone isc-dhcp repo + git clone https://salsa.debian.org/dhcp-team/isc-dhcp.git + pushd ./isc-dhcp + + # Reset HEAD to the commit of the proper tag + # NOTE: Using "git checkout " here detaches our HEAD, + # which stg doesn't like, so we use this method instead + git reset --hard debian/$(ISC_DHCP_VERSION_FULL) + + # Apply patches + stg init + stg import -s ../patch/series + + # Build source and Debian packages + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + # Move the newly-built .deb packages to the destination directory + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/isc-dhcp/patch/0001-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch b/src/isc-dhcp/patch/0001-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch new file mode 100644 index 000000000000..2ddbc1a90f93 --- /dev/null +++ b/src/isc-dhcp/patch/0001-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch @@ -0,0 +1,28 @@ +From 7c1cfd636be589317710a8556a7ec667debee53a Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Fri, 26 Apr 2019 01:37:54 +0000 +Subject: [PATCH] [Bugfix] Don't print log messages to stderr in release builds + +--- + omapip/errwarn.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/omapip/errwarn.c b/omapip/errwarn.c +index 7c91d9d..aa74fd8 100644 +--- a/omapip/errwarn.c ++++ b/omapip/errwarn.c +@@ -39,9 +39,9 @@ + #include + + #ifdef DEBUG +-int log_perror = -1; +-#else + int log_perror = 1; ++#else ++int log_perror = 0; + #endif + void (*log_cleanup) (void); + +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0002-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch b/src/isc-dhcp/patch/0002-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch new file mode 100644 index 000000000000..e6d09dedc711 --- /dev/null +++ b/src/isc-dhcp/patch/0002-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch @@ -0,0 +1,296 @@ +From 6b4c2e815118fb7312b8e8a07ac61a772b57e91a Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Thu, 25 Apr 2019 22:07:20 +0000 +Subject: [PATCH] Customizable Option 82 circuit ID and remote ID fields + +--- + relay/dhcrelay.c | 171 ++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 147 insertions(+), 24 deletions(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 0cb2ef6..418b943 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -75,6 +75,8 @@ int bad_circuit_id = 0; /* Circuit ID option in matching RAI option + did not match any known circuit ID. */ + int missing_circuit_id = 0; /* Circuit ID option in matching RAI option + was missing. */ ++const char *agent_circuit_id_fmt = NULL; /* Circuit ID custom format string. */ ++const char *agent_remote_id_fmt = NULL; /* Remote ID custom format string. */ + int max_hop_count = 10; /* Maximum hop count */ + + int no_daemon = 0; +@@ -151,10 +153,20 @@ static const char url[] = + + char *progname; + ++#define DHCRELAY_OPTION82_USAGE \ ++"circuit_id/remote_id interpreted sequences are:\n" \ ++"\n" \ ++" %%%% A single %%\n" \ ++" %%h Hostname of device\n" \ ++" %%p Name of interface that generated the request\n" \ ++" %%P Hardware address of interface that generated the request\n" \ ++" %%C Client hardware address\n" \ ++" %%I DHCP relay agent IP Address\n" \ ++ + #ifdef DHCPv6 + #ifdef RELAY_PORT + #define DHCRELAY_USAGE \ +-"Usage: %s [-4] [-d] [-q] [-a] [-D]\n" \ ++"Usage: %s [-4] [-d] [-q] [-a ] [-D]\n"\ + " [-A ] [-c ]\n" \ + " [-p | -rp ]\n" \ + " [-pf ] [--no-pid]\n"\ +@@ -171,11 +183,11 @@ char *progname; + " -l lower0 [ ... -l lowerN]\n" \ + " -u upper0 [ ... -u upperN]\n" \ + " lower (client link): [address%%]interface[#index]\n" \ +-" upper (server link): [address%%]interface\n\n" \ ++" upper (server link): [address%%]interface\n\n" DHCRELAY_OPTION82_USAGE \ + " %s {--version|--help|-h}" + #else + #define DHCRELAY_USAGE \ +-"Usage: %s [-4] [-d] [-q] [-a] [-D]\n" \ ++"Usage: %s [-4] [-d] [-q] [-a ] [-D]\n"\ + " [-A ] [-c ] [-p ]\n" \ + " [-pf ] [--no-pid]\n"\ + " [-m append|replace|forward|discard]\n" \ +@@ -190,13 +202,13 @@ char *progname; + " -l lower0 [ ... -l lowerN]\n" \ + " -u upper0 [ ... -u upperN]\n" \ + " lower (client link): [address%%]interface[#index]\n" \ +-" upper (server link): [address%%]interface\n\n" \ ++" upper (server link): [address%%]interface\n\n" DHCRELAY_OPTION82_USAGE \ + " %s {--version|--help|-h}" + #endif + #else /* !DHCPv6 */ + #ifdef RELAY_PORT + #define DHCRELAY_USAGE \ +-"Usage: %s [-d] [-q] [-a] [-D] [-A ] [-c ]\n" \ ++"Usage: %s [-d] [-q] [-a ] [-D] [-A ] [-c ]\n" \ + " [-p | -rp ]\n" \ + " [-pf ] [--no-pid]\n" \ + " [-m append|replace|forward|discard]\n" \ +@@ -204,18 +216,18 @@ char *progname; + " [-iu interface0 [ ... -iu interfaceN]\n" \ + " [-id interface0 [ ... -id interfaceN]\n" \ + " [-U interface]\n" \ +-" server0 [ ... serverN]\n\n" \ ++" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE \ + " %s {--version|--help|-h}" + #else + #define DHCRELAY_USAGE \ +-"Usage: %s [-d] [-q] [-a] [-D] [-A ] [-c ] [-p ]\n" \ ++"Usage: %s [-d] [-q] [-a ] [-D] [-A ] [-c ] [-p ]\n" \ + " [-pf ] [--no-pid]\n" \ + " [-m append|replace|forward|discard]\n" \ + " [-i interface0 [ ... -i interfaceN]\n" \ + " [-iu interface0 [ ... -iu interfaceN]\n" \ + " [-id interface0 [ ... -id interfaceN]\n" \ + " [-U interface]\n" \ +-" server0 [ ... serverN]\n\n" \ ++" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE \ + " %s {--version|--help|-h}" + #endif + #endif +@@ -471,6 +483,15 @@ main(int argc, char **argv) { + local_family_set = 1; + local_family = AF_INET; + #endif ++ if (++i == argc) ++ usage(use_noarg, argv[i-1]); ++ ++ if (argv[i] != NULL && argv[i][0] != '-') ++ agent_circuit_id_fmt = argv[i++]; ++ ++ if (argv[i] != NULL && argv[i][0] != '-') ++ agent_remote_id_fmt = argv[i]; ++ + add_agent_options = 1; + } else if (!strcmp(argv[i], "-A")) { + #ifdef DHCPv6 +@@ -1171,6 +1192,81 @@ find_interface_by_agent_option(struct dhcp_packet *packet, + return (-1); + } + ++/* ++ * Format the message that will be used by circuit_id and remote_id ++ */ ++static int ++format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_packet *packet, ++ const char *format, char *msg, size_t msgn) { ++ size_t len = 0; ++ char hostname[HOST_NAME_MAX] = { 0 }; ++ char ifname[IFNAMSIZ] = { 0 }; ++ char *buf = msg; ++ ++ for ( ; format && *format && len < msgn; ++format) { ++ size_t strn = 0; ++ const char *str = NULL; ++ ++ if (*format == '%') { ++ switch (*++format) { ++ case '\0': ++ --format; ++ break; ++ ++ case '%': /* A literal '%' */ ++ str = "%"; ++ break; ++ ++ case 'h': /* Hostname */ ++ gethostname(hostname, HOST_NAME_MAX); ++ hostname[HOST_NAME_MAX - 1] = '\0'; ++ str = hostname; ++ break; ++ ++ case 'p': /* Name of interface that we received the request from */ ++ strncpy(ifname, ip->name, IFNAMSIZ); ++ str = ifname; ++ break; ++ ++ case 'P': /* Physical address of interface that we received the request from */ ++ str = print_hw_addr(ip->hw_address.hbuf[0], ip->hw_address.hlen - 1, &ip->hw_address.hbuf[1]); ++ break; ++ ++ case 'C': /* 24: Client hardware address */ ++ str = print_hw_addr(packet->htype, packet->hlen, packet->chaddr); ++ break; ++ ++ case 'I': /* 20: DHCP relay agent IP address */ ++ str = inet_ntoa(packet->giaddr); ++ break; ++ ++ default: ++ log_error("Option %%%c is unrecognized and will not be formatted!", *format); ++ continue; ++ } ++ ++ if (str) { ++ strn = strlen(str); ++ } ++ } else { ++ str = format; ++ strn = 1; ++ } ++ ++ // Do we have room? ++ if ((strn+len) >= msgn) { ++ return 0; ++ } ++ ++ if (str && strn > 0) { ++ memcpy(buf+len, str, strn); ++ len += strn; ++ } ++ } ++ ++ return len; ++} ++ + /* + * Examine a packet to see if it's a candidate to have a Relay + * Agent Information option tacked onto its tail. If it is, tack +@@ -1180,9 +1276,12 @@ static int + add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + unsigned length, struct in_addr giaddr) { + int is_dhcp = 0, mms; +- unsigned optlen; ++ unsigned optlen = 0; + u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL; + int adding_link_select; ++ char circuit_id_buf[256] = { '\0' }; ++ char remote_id_buf[256] = { '\0' }; ++ size_t circuit_id_len = 0, remote_id_len = 0; + + /* If we're not adding agent options to packets, we can skip + this. */ +@@ -1316,17 +1415,40 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + op = sp; + #endif + +- /* Sanity check. Had better not ever happen. */ +- if ((ip->circuit_id_len > 255) ||(ip->circuit_id_len < 1)) +- log_fatal("Circuit ID length %d out of range [1-255] on " +- "%s\n", ip->circuit_id_len, ip->name); +- optlen = ip->circuit_id_len + 2; /* RAI_CIRCUIT_ID + len */ +- +- if (ip->remote_id) { +- if (ip->remote_id_len > 255 || ip->remote_id_len < 1) +- log_fatal("Remote ID length %d out of range [1-255] " +- "on %s\n", ip->remote_id_len, ip->name); +- optlen += ip->remote_id_len + 2; /* RAI_REMOTE_ID + len */ ++ /* option82: custom string for circuit_id */ ++ if (agent_circuit_id_fmt) { ++ circuit_id_len = format_relay_agent_rfc3046_msg(ip, packet, agent_circuit_id_fmt, ++ circuit_id_buf, sizeof(circuit_id_buf)); ++ ++ if (circuit_id_len == 0) { ++ strncpy(circuit_id_buf, ip->name, sizeof(ip->name)); ++ circuit_id_len = strlen(circuit_id_buf); ++ } ++ ++ /* Sanity check. Had better not ever happen. */ ++ if (circuit_id_len > 255 || circuit_id_len < 1) ++ log_fatal("Circuit ID length %d out of range [1-255] on %s\n", ++ (int)circuit_id_len, ip->name); ++ ++ optlen = circuit_id_len + 2; // RAI_CIRCUIT_ID + len ++ ++ //log_debug("Sending on %s option82:circuit_id='%s' (%d)", ++ // ip->name, circuit_id_buf, (int)circuit_id_len); ++ } ++ ++ /* option82: custom string for remote_id */ ++ if (agent_remote_id_fmt) { ++ remote_id_len = format_relay_agent_rfc3046_msg(ip, packet, agent_remote_id_fmt, ++ remote_id_buf, sizeof(remote_id_buf)); ++ ++ if (remote_id_len > 255 || remote_id_len < 1) ++ log_fatal("Remote ID length %d out of range [1-255] on %s\n", ++ (int)remote_id_len, ip->name); ++ ++ optlen += remote_id_len + 2; // RAI_REMOTE_ID + len ++ ++ //log_debug("Sending on %s option82:remote_id='%s' (%d)", ++ // ip->name, remote_id_buf, (int)remote_id_len); + } + + if (adding_link_select) { +@@ -1351,7 +1473,7 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + * If not, forward without adding the option. + */ + if (max - sp >= optlen + 3) { +- log_debug("Adding %d-byte relay agent option", optlen + 3); ++ //log_debug("Adding %d-byte relay agent option", optlen + 3); + + /* Okay, cons up *our* Relay Agent Information option. */ + *sp++ = DHO_DHCP_AGENT_OPTIONS; +@@ -1359,16 +1481,16 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + + /* Copy in the circuit id... */ + *sp++ = RAI_CIRCUIT_ID; +- *sp++ = ip->circuit_id_len; +- memcpy(sp, ip->circuit_id, ip->circuit_id_len); +- sp += ip->circuit_id_len; ++ *sp++ = circuit_id_len; ++ memcpy(sp, circuit_id_buf, circuit_id_len); ++ sp += circuit_id_len; + + /* Copy in remote ID... */ +- if (ip->remote_id) { ++ if (remote_id_len > 0) { + *sp++ = RAI_REMOTE_ID; +- *sp++ = ip->remote_id_len; +- memcpy(sp, ip->remote_id, ip->remote_id_len); +- sp += ip->remote_id_len; ++ *sp++ = remote_id_len; ++ memcpy(sp, remote_id_buf, remote_id_len); ++ sp += remote_id_len; + } + + /* RFC3527: Use the inbound packet's interface address in +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0003-Support-for-obtaining-name-of-physical-interface-tha.patch b/src/isc-dhcp/patch/0003-Support-for-obtaining-name-of-physical-interface-tha.patch new file mode 100644 index 000000000000..af3052e4b088 --- /dev/null +++ b/src/isc-dhcp/patch/0003-Support-for-obtaining-name-of-physical-interface-tha.patch @@ -0,0 +1,98 @@ +From ab0be27d3862c7287e3b181cc6a70effa054be1c Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Fri, 26 Apr 2019 01:06:49 +0000 +Subject: [PATCH] Support for obtaining name of physical interface that is a + member of a bridge interface + +--- + relay/dhcrelay.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 65 insertions(+), 2 deletions(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index db1af9c..f2418e8 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -1192,6 +1192,47 @@ find_interface_by_agent_option(struct dhcp_packet *packet, + return (-1); + } + ++static int ++_bridgefdbquery(const char *hwAddr, char *interface, int *vlanid) { ++ ++#define xstr(s) str(s) ++#define str(s) #s ++#define FDB_STRING_LEN 100 ++#define FDB_BUFFER_LEN (FDB_STRING_LEN + 1) ++ ++/* ++ * Format for sscanf() to read the 1st, 3th, and 5th ++ * space-delimited fields ++ * ++ * bridge fdb show output ++ * 6c:64:1a:00:06:13 dev swp35 vlan 0 master bridge permanent ++ */ ++#define FDB_LINE_FORMAT "%" xstr(FDB_STRING_LEN) "s %*s " \ ++ "%" xstr(FDB_STRING_LEN) "s %*s %d %*s" ++ ++ char cmdstr[FDB_BUFFER_LEN]; ++ char buf[FDB_BUFFER_LEN]; ++ char macAddr[FDB_BUFFER_LEN]; ++ ++ if ((interface == NULL) || (vlanid == NULL)) { ++ return 0; ++ } ++ sprintf(cmdstr, "bridge fdb show | grep -m 1 %s", hwAddr); ++ FILE *cmd = popen(cmdstr, "r"); ++ ++ if (cmd != NULL) { ++ while (fgets(buf, sizeof(buf), cmd)) { ++ sscanf(buf, FDB_LINE_FORMAT, macAddr, interface, vlanid); ++ //log_debug("bridgefdbquery: macAddr: %s interface: %s vlanid: %d", ++ // macAddr, interface, *vlanid); ++ } ++ pclose(cmd); ++ return 0; ++ } ++ ++ return -1; ++} ++ + /* + * Format the message that will be used by circuit_id and remote_id + */ +@@ -1224,8 +1265,30 @@ format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_pack + break; + + case 'p': /* Name of interface that we received the request from */ +- strncpy(ifname, ip->name, IFNAMSIZ); +- str = ifname; ++ /* ++ * Query FDB to identify the exact physical interface only when source MAC address ++ * is present and '20: DHCP relay agent IP address' (giaddr) is not present ++ */ ++ if (packet->htype && !packet->giaddr.s_addr) { ++ int ret = 0, vlanid = 0; ++ ++ ret = _bridgefdbquery(print_hw_addr(packet->htype, packet->hlen, packet->chaddr), ++ ifname, ++ &vlanid); ++ ++ // If we failed to find a physical interface using the source mac, default ++ // to the interface name we received it on. ++ if (ret < 0) { ++ //log_debug("MAC Address: %s (interface:%s vlan:%d) not found in bridge fdb show", ++ // print_hw_addr (packet->htype, packet->hlen, packet->chaddr), ++ // ip->name, ++ // vlanid); ++ ++ strncpy(ifname, ip->name, IFNAMSIZ); ++ } ++ ++ str = ifname; ++ } + break; + + case 'P': /* Physical address of interface that we received the request from */ +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0004-Support-for-loading-port-alias-map-file-to-replace-p.patch b/src/isc-dhcp/patch/0004-Support-for-loading-port-alias-map-file-to-replace-p.patch new file mode 100644 index 000000000000..f26871019b63 --- /dev/null +++ b/src/isc-dhcp/patch/0004-Support-for-loading-port-alias-map-file-to-replace-p.patch @@ -0,0 +1,189 @@ +From 9d255bbd7d7aadac5b57cba2ab4e29cecdf0180f Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Fri, 26 Apr 2019 01:26:45 +0000 +Subject: [PATCH] Support for loading port alias map file to replace port name + with alias in circuit id + +--- + relay/dhcrelay.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 104 insertions(+), 1 deletion(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 00c81d3..54f132a 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -129,6 +129,14 @@ static void setup_streams(void); + char *dhcrelay_sub_id = NULL; + #endif + ++struct interface_name_alias_tuple { ++ char if_name[IFNAMSIZ]; ++ char if_alias[IFNAMSIZ]; ++}; ++ ++static struct interface_name_alias_tuple *g_interface_name_alias_map = NULL; ++static size_t g_interface_name_alias_map_size = 0; ++ + static void do_relay4(struct interface_info *, struct dhcp_packet *, + unsigned int, unsigned int, struct iaddr, + struct hardware *); +@@ -143,6 +151,10 @@ static int strip_relay_agent_options(struct interface_info *, + + static void request_v4_interface(const char* name, int flags); + ++static int load_interface_alias_map(const char *port_alias_map_file_path); ++static int get_interface_alias_by_name(const char *if_name, char *if_alias_out); ++static void free_interface_alias_map(void); ++ + static const char copyright[] = + "Copyright 2004-2018 Internet Systems Consortium."; + static const char arr[] = "All rights reserved."; +@@ -158,7 +170,7 @@ char *progname; + "\n" \ + " %%%% A single %%\n" \ + " %%h Hostname of device\n" \ +-" %%p Name of interface that generated the request\n" \ ++" %%p Alias of interface that generated the request\n" \ + " %%P Hardware address of interface that generated the request\n" \ + " %%C Client hardware address\n" \ + " %%I DHCP relay agent IP Address\n" \ +@@ -171,6 +183,7 @@ char *progname; + " [-p | -rp ]\n" \ + " [-pf ] [--no-pid]\n"\ + " [-m append|replace|forward|discard]\n" \ ++" [--name-alias-map-file ]\n" \ + " [-i interface0 [ ... -i interfaceN]\n" \ + " [-iu interface0 [ ... -iu interfaceN]\n" \ + " [-id interface0 [ ... -id interfaceN]\n" \ +@@ -179,6 +192,7 @@ char *progname; + " %s -6 [-d] [-q] [-I] [-c ]\n" \ + " [-p | -rp ]\n" \ + " [-pf ] [--no-pid]\n" \ ++" [--name-alias-map-file ]\n" \ + " [-s ]\n" \ + " -l lower0 [ ... -l lowerN]\n" \ + " -u upper0 [ ... -u upperN]\n" \ +@@ -619,6 +633,11 @@ main(int argc, char **argv) { + no_dhcrelay_pid = ISC_TRUE; + } else if (!strcmp(argv[i], "--no-pid")) { + no_pid_file = ISC_TRUE; ++ } else if (!strcmp(argv[i], "--name-alias-map-file")) { ++ if (++i == argc) ++ usage(use_noarg, argv[i-1]); ++ if (load_interface_alias_map(argv[i]) != 0) ++ log_fatal("Failed to load interface name-alias map."); + } else if (argv[i][0] == '-') { + usage("Unknown command: %s", argv[i]); + } else { +@@ -841,6 +860,7 @@ main(int argc, char **argv) { + dispatch(); + + /* In fact dispatch() never returns. */ ++ free_interface_alias_map(); + return (0); + } + +@@ -1271,6 +1291,7 @@ format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_pack + */ + if (packet->htype && !packet->giaddr.s_addr) { + int ret = 0, vlanid = 0; ++ char ifalias[IFNAMSIZ] = { 0 }; + + ret = _bridgefdbquery(print_hw_addr(packet->htype, packet->hlen, packet->chaddr), + ifname, +@@ -1287,6 +1308,18 @@ format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_pack + strncpy(ifname, ip->name, IFNAMSIZ); + } + ++ // Attempt to translate SONiC interface name to vendor alias ++ ret = get_interface_alias_by_name(ifname, ifalias); ++ if (ret < 0) { ++ //log_debug("Failed to retrieve alias for interface name '%s'. Defaulting to interface name.", ifname); ++ } ++ else { ++ //log_debug("Mapped interface name '%s' to alias '%s'. Adding as option 82 interface alias for MAC Address %s", ++ // ifname, ifalias, print_hw_addr (packet->htype, packet->hlen, packet->chaddr)); ++ ++ strncpy(ifname, ifalias, IFNAMSIZ); ++ } ++ + str = ifname; + } + break; +@@ -2313,3 +2346,73 @@ void request_v4_interface(const char* name, int flags) { + interface_snorf(tmp, (INTERFACE_REQUESTED | flags)); + interface_dereference(&tmp, MDL); + } ++ ++#define MAX_PORT_CONFIG_LINE_LEN 1024 ++ ++// Allocates and loads global map g_interface_name_alias_map ++// Also sets global g_interface_name_alias_map_size ++static int ++load_interface_alias_map(const char *port_alias_map_file_path) { ++ int i = 0; ++ FILE *fp = NULL; ++ char line[MAX_PORT_CONFIG_LINE_LEN] = { 0 }; ++ ++ fp = fopen(port_alias_map_file_path,"r"); ++ if (fp == NULL) { ++ log_error("Unable to open %s", port_alias_map_file_path); ++ return -1; ++ } ++ ++ g_interface_name_alias_map_size = 0; ++ ++ // Count the number of interfaces listed in the file ++ while (fgets(line, sizeof(line), fp)) { ++ g_interface_name_alias_map_size++; ++ } ++ ++ // Allocate our map accordingly ++ g_interface_name_alias_map = ((struct interface_name_alias_tuple *) ++ dmalloc((sizeof(struct interface_name_alias_tuple) * g_interface_name_alias_map_size), ++ MDL)); ++ ++ // Reset file position indicator to beginning of file ++ fseek(fp, 0, SEEK_SET); ++ ++ // Every line should contain exactly one name-alias pair ++ while (fgets(line, sizeof(line), fp)) { ++ // Each line should read as "" ++ sscanf(line, "%s %s", g_interface_name_alias_map[i].if_name, g_interface_name_alias_map[i].if_alias); ++ i++; ++ } ++ ++ fclose(fp); ++ ++ log_info("Loaded %d interface name-alias mappings", i); ++ ++ return 0; ++} ++ ++// Locates alias for port named if_name, copies alias into if_alias_out, up to a ++// max of IFNAMSIZ bytes. ++// Returns 0 on success, -1 on failure ++static int ++get_interface_alias_by_name(const char *if_name, char *if_alias_out) { ++ int i = 0; ++ ++ for (i = 0; i < g_interface_name_alias_map_size; i++) { ++ if (strncmp(if_name, g_interface_name_alias_map[i].if_name, IFNAMSIZ) == 0) { ++ strncpy(if_alias_out, g_interface_name_alias_map[i].if_alias, IFNAMSIZ); ++ return 0; ++ } ++ } ++ ++ return -1; ++} ++ ++// Frees global map g_interface_name_alias_map ++// Sets g_interface_name_alias_map_size to 0 ++static void ++free_interface_alias_map(void) { ++ free(g_interface_name_alias_map); ++ g_interface_name_alias_map_size = 0; ++} +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0005-Add-enable-use-sockets-to-configure-flags-in-debian-.patch b/src/isc-dhcp/patch/0005-Add-enable-use-sockets-to-configure-flags-in-debian-.patch new file mode 100644 index 000000000000..7e9bcc30fb89 --- /dev/null +++ b/src/isc-dhcp/patch/0005-Add-enable-use-sockets-to-configure-flags-in-debian-.patch @@ -0,0 +1,26 @@ +From 5c64cb06e3ac50a1cbca85669625fe16439064ad Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Fri, 17 May 2019 21:49:00 +0000 +Subject: [PATCH 1/3] Add --enable-use-sockets to configure flags in + debian/rules + +--- + debian/rules | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/debian/rules b/debian/rules +index d3fcc1d..2a7219d 100755 +--- a/debian/rules ++++ b/debian/rules +@@ -24,7 +24,7 @@ CFLAGS+=-D_PATH_DHCLIENT_CONF='\"/etc/dhcp/dhclient.conf\"' + CFLAGS+=-D_PATH_DHCLIENT_DB='\"$(LEASE_PATH)/dhclient.leases\"' + CFLAGS+=-D_PATH_DHCLIENT6_DB='\"$(LEASE_PATH)/dhclient6.leases\"' + +-CONFFLAGS=--prefix=/usr --with-libbind=/usr --enable-log-pid --enable-paranoia ++CONFFLAGS=--prefix=/usr --with-libbind=/usr --enable-log-pid --enable-paranoia --enable-use-sockets + + # cross-architecture building + ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE)) +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0006-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch b/src/isc-dhcp/patch/0006-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch new file mode 100644 index 000000000000..5553180f40e2 --- /dev/null +++ b/src/isc-dhcp/patch/0006-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch @@ -0,0 +1,275 @@ +From 6620d4778fe36c89ce2e95d6932338cefc90df7d Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Fri, 17 May 2019 21:53:52 +0000 +Subject: [PATCH 2/3] Bugfix: Ensure HAVE_SO_BINDTODEVICE has a chance to be + defined before it is referenced + +--- + includes/osdep.h | 239 ++++++++++++++++++++++++----------------------- + 1 file changed, 120 insertions(+), 119 deletions(-) + +diff --git a/includes/osdep.h b/includes/osdep.h +index cfae90b..f07c43c 100644 +--- a/includes/osdep.h ++++ b/includes/osdep.h +@@ -48,37 +48,6 @@ + #define BYTE_ORDER DHCP_BYTE_ORDER + #endif /* BYTE_ORDER */ + +-/* Porting:: +- +- If you add a new network API, you must add a check for it below: */ +- +-#if !defined (USE_SOCKETS) && \ +- !defined (USE_SOCKET_SEND) && \ +- !defined (USE_SOCKET_RECEIVE) && \ +- !defined (USE_RAW_SOCKETS) && \ +- !defined (USE_RAW_SEND) && \ +- !defined (USE_SOCKET_RECEIVE) && \ +- !defined (USE_BPF) && \ +- !defined (USE_BPF_SEND) && \ +- !defined (USE_BPF_RECEIVE) && \ +- !defined (USE_LPF) && \ +- !defined (USE_LPF_SEND) && \ +- !defined (USE_LPF_RECEIVE) && \ +- !defined (USE_NIT) && \ +- !defined (USE_NIT_SEND) && \ +- !defined (USE_NIT_RECEIVE) && \ +- !defined (USE_DLPI_SEND) && \ +- !defined (USE_DLPI_RECEIVE) +-/* Determine default socket API to USE. */ +-# if defined(HAVE_BPF) +-# define USE_BPF 1 +-# elif defined(HAVE_LPF) +-# define USE_LPF 1 +-# elif defined(HAVE_DLPI) +-# define USE_DLPI 1 +-# endif +-#endif +- + #if !defined (TIME_MAX) + # define TIME_MAX 2147483647 + #endif +@@ -91,94 +60,6 @@ + # define vsnprintf isc_print_vsnprintf + #endif + +-/* Porting:: +- +- If you add a new network API, and have it set up so that it can be +- used for sending or receiving, but doesn't have to be used for both, +- then set up an ifdef like the ones below: */ +- +-#ifdef USE_SOCKETS +-# define USE_SOCKET_SEND +-# define USE_SOCKET_RECEIVE +-# if defined(HAVE_DLPI) && !defined(sun) && !defined(USE_V4_PKTINFO) +-# define USE_DLPI_HWADDR +-# elif defined(HAVE_LPF) +-# define USE_LPF_HWADDR +-# elif defined(HAVE_BPF) +-# define USE_BPF_HWADDR +-# endif +-#endif +- +-#ifdef USE_RAW_SOCKETS +-# define USE_RAW_SEND +-# define USE_SOCKET_RECEIVE +-#endif +- +-#ifdef USE_BPF +-# define USE_BPF_SEND +-# define USE_BPF_RECEIVE +-#endif +- +-#ifdef USE_LPF +-# define USE_LPF_SEND +-# define USE_LPF_RECEIVE +-#endif +- +-#ifdef USE_NIT +-# define USE_NIT_SEND +-# define USE_NIT_RECEIVE +-#endif +- +-#ifdef USE_DLPI +-# define USE_DLPI_SEND +-# define USE_DLPI_RECEIVE +-#endif +- +-#ifdef USE_UPF +-# define USE_UPF_SEND +-# define USE_UPF_RECEIVE +-#endif +- +-/* Porting:: +- +- If you add support for sending packets directly out an interface, +- and your support does not do ARP or routing, you must use a fallback +- mechanism to deal with packets that need to be sent to routers. +- Currently, all low-level packet interfaces use BSD sockets as a +- fallback. */ +- +-#if defined (USE_BPF_SEND) || defined (USE_NIT_SEND) || \ +- defined (USE_DLPI_SEND) || defined (USE_UPF_SEND) || \ +- defined (USE_LPF_SEND) || \ +- (defined (USE_SOCKET_SEND) && defined (HAVE_SO_BINDTODEVICE)) +-# define USE_SOCKET_FALLBACK +-# define USE_FALLBACK +-#endif +- +-/* Porting:: +- +- If you add support for sending packets directly out an interface +- and need to be able to assemble packets, add the USE_XXX_SEND +- definition for your interface to the list tested below. */ +- +-#if defined (USE_RAW_SEND) || defined (USE_BPF_SEND) || \ +- defined (USE_NIT_SEND) || defined (USE_UPF_SEND) || \ +- defined (USE_DLPI_SEND) || defined (USE_LPF_SEND) +-# define PACKET_ASSEMBLY +-#endif +- +-/* Porting:: +- +- If you add support for receiving packets directly from an interface +- and need to be able to decode raw packets, add the USE_XXX_RECEIVE +- definition for your interface to the list tested below. */ +- +-#if defined (USE_RAW_RECEIVE) || defined (USE_BPF_SEND) || \ +- defined (USE_NIT_RECEIVE) || defined (USE_UPF_RECEIVE) || \ +- defined (USE_DLPI_RECEIVE) || defined (USE_LPF_RECEIVE) +-# define PACKET_DECODING +-#endif +- + /* If we don't have a DLPI packet filter, we have to filter in userland. + Probably not worth doing, actually. */ + #if defined (USE_DLPI_RECEIVE) && !defined (USE_DLPI_PFMOD) +@@ -288,4 +169,124 @@ + # define STDERR_FILENO 2 + #endif + ++/* Porting:: ++ ++ If you add a new network API, you must add a check for it below: */ ++ ++#if !defined (USE_SOCKETS) && \ ++ !defined (USE_SOCKET_SEND) && \ ++ !defined (USE_SOCKET_RECEIVE) && \ ++ !defined (USE_RAW_SOCKETS) && \ ++ !defined (USE_RAW_SEND) && \ ++ !defined (USE_SOCKET_RECEIVE) && \ ++ !defined (USE_BPF) && \ ++ !defined (USE_BPF_SEND) && \ ++ !defined (USE_BPF_RECEIVE) && \ ++ !defined (USE_LPF) && \ ++ !defined (USE_LPF_SEND) && \ ++ !defined (USE_LPF_RECEIVE) && \ ++ !defined (USE_NIT) && \ ++ !defined (USE_NIT_SEND) && \ ++ !defined (USE_NIT_RECEIVE) && \ ++ !defined (USE_DLPI_SEND) && \ ++ !defined (USE_DLPI_RECEIVE) ++/* Determine default socket API to USE. */ ++# if defined(HAVE_BPF) ++# define USE_BPF 1 ++# elif defined(HAVE_LPF) ++# define USE_LPF 1 ++# elif defined(HAVE_DLPI) ++# define USE_DLPI 1 ++# endif ++#endif ++ ++/* Porting:: ++ ++ If you add a new network API, and have it set up so that it can be ++ used for sending or receiving, but doesn't have to be used for both, ++ then set up an ifdef like the ones below: */ ++ ++#ifdef USE_SOCKETS ++# define USE_SOCKET_SEND ++# define USE_SOCKET_RECEIVE ++# if defined(HAVE_DLPI) && !defined(sun) && !defined(USE_V4_PKTINFO) ++# define USE_DLPI_HWADDR ++# elif defined(HAVE_LPF) ++# define USE_LPF_HWADDR ++# elif defined(HAVE_BPF) ++# define USE_BPF_HWADDR ++# endif ++#endif ++ ++#ifdef USE_RAW_SOCKETS ++# define USE_RAW_SEND ++# define USE_SOCKET_RECEIVE ++#endif ++ ++#ifdef USE_BPF ++# define USE_BPF_SEND ++# define USE_BPF_RECEIVE ++#endif ++ ++#ifdef USE_LPF ++# define USE_LPF_SEND ++# define USE_LPF_RECEIVE ++#endif ++ ++#ifdef USE_NIT ++# define USE_NIT_SEND ++# define USE_NIT_RECEIVE ++#endif ++ ++#ifdef USE_DLPI ++# define USE_DLPI_SEND ++# define USE_DLPI_RECEIVE ++#endif ++ ++#ifdef USE_UPF ++# define USE_UPF_SEND ++# define USE_UPF_RECEIVE ++#endif ++ ++/* Porting:: ++ ++ If you add support for sending packets directly out an interface, ++ and your support does not do ARP or routing, you must use a fallback ++ mechanism to deal with packets that need to be sent to routers. ++ Currently, all low-level packet interfaces use BSD sockets as a ++ fallback. */ ++ ++#if defined (USE_BPF_SEND) || defined (USE_NIT_SEND) || \ ++ defined (USE_DLPI_SEND) || defined (USE_UPF_SEND) || \ ++ defined (USE_LPF_SEND) || \ ++ (defined (USE_SOCKET_SEND) && defined (HAVE_SO_BINDTODEVICE)) ++# define USE_SOCKET_FALLBACK ++# define USE_FALLBACK ++#endif ++ ++/* Porting:: ++ ++ If you add support for sending packets directly out an interface ++ and need to be able to assemble packets, add the USE_XXX_SEND ++ definition for your interface to the list tested below. */ ++ ++#if defined (USE_RAW_SEND) || defined (USE_BPF_SEND) || \ ++ defined (USE_NIT_SEND) || defined (USE_UPF_SEND) || \ ++ defined (USE_DLPI_SEND) || defined (USE_LPF_SEND) ++# define PACKET_ASSEMBLY ++#endif ++ ++/* Porting:: ++ ++ If you add support for receiving packets directly from an interface ++ and need to be able to decode raw packets, add the USE_XXX_RECEIVE ++ definition for your interface to the list tested below. */ ++ ++#if defined (USE_RAW_RECEIVE) || defined (USE_BPF_SEND) || \ ++ defined (USE_NIT_RECEIVE) || defined (USE_UPF_RECEIVE) || \ ++ defined (USE_DLPI_RECEIVE) || defined (USE_LPF_RECEIVE) ++# define PACKET_DECODING ++#endif ++ ++ + #endif /* __ISC_DHCP_OSDEP_H__ */ +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0007-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch b/src/isc-dhcp/patch/0007-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch new file mode 100644 index 000000000000..bf24e448ea1a --- /dev/null +++ b/src/isc-dhcp/patch/0007-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch @@ -0,0 +1,251 @@ +From fe50ed9721d79be0bb5045a219f5f5bb4cb8868e Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Fri, 17 May 2019 22:24:02 +0000 +Subject: [PATCH 3/3] If destination of BOOTREQUEST is directed broadcast, + forward on that interface. Otherwise forward on fallback or all upstream + interfaces + +--- + common/discover.c | 46 +++++++++++++++++++--- + includes/dhcpd.h | 3 ++ + relay/dhcrelay.c | 98 +++++++++++++++++++++++++++++++++++++++++------ + 3 files changed, 131 insertions(+), 16 deletions(-) + +diff --git a/common/discover.c b/common/discover.c +index 98ac46a..53afecc 100644 +--- a/common/discover.c ++++ b/common/discover.c +@@ -236,6 +236,7 @@ struct iface_conf_list { + struct iface_info { + char name[IF_NAMESIZE+1]; /* name of the interface, e.g. "bge0" */ + struct sockaddr_storage addr; /* address information */ ++ struct sockaddr_storage netmask; /* netmask information */ + isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */ + }; + +@@ -367,6 +368,17 @@ next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) { + } + info->flags = tmp.lifr_flags; + ++ if (ioctl(ifaces->sock, SIOCGIFNETMASK, &tmp) < 0) { ++ if (errno == EADDRNOTAVAIL) { ++ continue; ++ } ++ log_error("Error getting netmask " ++ "for '%s'; %m", name); ++ *err = 1; ++ return 0; ++ } ++ memcpy(&info->netmask, &tmp.ifr_netmask, sizeof(tmp.ifr_netmask)); ++ + ifaces->next++; + *err = 0; + return 1; +@@ -410,6 +422,7 @@ struct iface_conf_list { + struct iface_info { + char name[IFNAMSIZ]; /* name of the interface, e.g. "bge0" */ + struct sockaddr_storage addr; /* address information */ ++ struct sockaddr_storage netmask; /* netmask information */ + isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */ + }; + +@@ -487,7 +500,8 @@ end_iface_scan(struct iface_conf_list *ifaces) { + /* XXX: perhaps create drealloc() rather than do it manually */ + void + add_ipv4_addr_to_interface(struct interface_info *iface, +- const struct in_addr *addr) { ++ const struct in_addr *addr, ++ const struct in_addr *netmask) { + /* + * We don't expect a lot of addresses per IPv4 interface, so + * we use 4, as our "chunk size" for collecting addresses. +@@ -498,6 +512,11 @@ add_ipv4_addr_to_interface(struct interface_info *iface, + log_fatal("Out of memory saving IPv4 address " + "on interface."); + } ++ iface->netmasks = dmalloc(4 * sizeof(struct in_addr), MDL); ++ if (iface->netmasks == NULL) { ++ log_fatal("Out of memory saving IPv4 netmask " ++ "on interface."); ++ } + iface->address_count = 0; + iface->address_max = 4; + } else if (iface->address_count >= iface->address_max) { +@@ -515,9 +534,23 @@ add_ipv4_addr_to_interface(struct interface_info *iface, + iface->address_max * sizeof(struct in_addr)); + dfree(iface->addresses, MDL); + iface->addresses = tmp; ++ ++ tmp = dmalloc(new_max * sizeof(struct in_addr), MDL); ++ if (tmp == NULL) { ++ log_fatal("Out of memory saving IPv4 netmask " ++ "on interface."); ++ } ++ memcpy(tmp, ++ iface->netmasks, ++ iface->address_max * sizeof(struct in_addr)); ++ dfree(iface->netmasks, MDL); ++ iface->netmasks = tmp; ++ + iface->address_max = new_max; + } +- iface->addresses[iface->address_count++] = *addr; ++ iface->addresses[iface->address_count] = *addr; ++ iface->netmasks[iface->address_count] = *netmask; ++ iface->address_count++; + } + + #ifdef DHCPv6 +@@ -656,6 +689,7 @@ discover_interfaces(int state) { + if ((info.addr.ss_family == AF_INET) && + (local_family == AF_INET)) { + struct sockaddr_in *a = (struct sockaddr_in*)&info.addr; ++ struct sockaddr_in *n = (struct sockaddr_in*)&info.netmask; + struct iaddr addr; + + /* We don't want the loopback interface. */ +@@ -670,7 +704,7 @@ discover_interfaces(int state) { + if (a->sin_addr.s_addr != htonl(INADDR_ANY)) + tmp->configured = 1; + +- add_ipv4_addr_to_interface(tmp, &a->sin_addr); ++ add_ipv4_addr_to_interface(tmp, &a->sin_addr, &n->sin_addr); + + /* invoke the setup hook */ + addr.len = 4; +diff --git a/includes/dhcpd.h b/includes/dhcpd.h +index df3da59..2c7f059 100644 +--- a/includes/dhcpd.h ++++ b/includes/dhcpd.h +@@ -1369,6 +1369,9 @@ struct interface_info { + struct in_addr *addresses; /* Addresses associated with this + * interface. + */ ++ struct in_addr *netmasks; /* Netmask associated with this ++ * interface. ++ */ + int address_count; /* Number of addresses stored. */ + int address_max; /* Size of addresses buffer. */ + struct in6_addr *v6addresses; /* IPv6 addresses associated with +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 54f132a..beae977 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + + TIME default_lease_time = 43200; /* 12 hours... */ +@@ -1001,20 +1002,95 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, + /* Otherwise, it's a BOOTREQUEST, so forward it to all the + servers. */ + for (sp = servers; sp; sp = sp->next) { +- if (send_packet((fallback_interface +- ? fallback_interface : interfaces), +- NULL, packet, length, ip->addresses[0], +- &sp->to, NULL) < 0) { +- ++client_packet_errors; ++ int packet_relay_attempted = 0; ++ ++ log_debug("Server IP: %s", inet_ntoa(sp->to.sin_addr)); ++ ++ /* If the server's IP address is the broadcast IP of one ++ of our interfaces, we send it directly on that interface's ++ socket, because the kernel will drop directed broadcast ++ packets if we send on the fallback. */ ++ for (out = interfaces; out; out = out->next) { ++ int i = 0; ++ ++ // Only relay BOOTREQUEST on upstream interfaces ++ if (!(out->flags & INTERFACE_UPSTREAM)) ++ continue; ++ ++ if (!out->addresses || !out->netmasks) ++ continue; ++ ++ for (i = 0; i < out->address_count; i++) { ++ struct in_addr bcast_addr; ++ ++ log_debug("Iface %s addr: %s", out->name, inet_ntoa(out->addresses[i])); ++ log_debug("Iface %s netmask: %s", out->name, inet_ntoa(out->netmasks[i])); ++ ++ // Broadcast = ip_addr | ~netmask ++ bcast_addr.s_addr = out->addresses[i].s_addr | ~out->netmasks[i].s_addr; ++ log_debug("Iface %s broadcast: %s", out->name, inet_ntoa(bcast_addr)); ++ ++ if (sp->to.sin_addr.s_addr == bcast_addr.s_addr) { ++ log_debug("Packet destined for broadcast IP of %s", out->name); ++ if (send_packet(out, NULL, packet, ++ length, ip->addresses[0],&sp->to, NULL) < 0) { ++ ++client_packet_errors; ++ } else { ++ log_debug("Forwarded BOOTREQUEST for %s to %s on interface %s", ++ print_hw_addr(packet->htype, packet->hlen, ++ packet->chaddr), ++ inet_ntoa(sp->to.sin_addr), out->name); ++ ++ ++client_packets_relayed; ++ } ++ ++ packet_relay_attempted = 1; ++ ++ break; ++ } ++ } ++ ++ if (packet_relay_attempted) ++ break; ++ } ++ ++ if (packet_relay_attempted) ++ continue; ++ ++ /* Otherwise, if we have a fallback interface, we send the packet ++ on it. If not, we send the packet out all interfaces.*/ ++ if (fallback_interface) { ++ if (send_packet(fallback_interface, NULL, packet, ++ length, ip->addresses[0],&sp->to, NULL) < 0) { ++ ++client_packet_errors; ++ } else { ++ log_debug("Forwarded BOOTREQUEST for %s to %s on fallback interface", ++ print_hw_addr(packet->htype, packet->hlen, ++ packet->chaddr), ++ inet_ntoa(sp->to.sin_addr)); ++ ++ ++client_packets_relayed; ++ } + } else { +- log_debug("Forwarded BOOTREQUEST for %s to %s", +- print_hw_addr(packet->htype, packet->hlen, +- packet->chaddr), +- inet_ntoa(sp->to.sin_addr)); +- ++client_packets_relayed; ++ for (out = interfaces; out; out = out->next) { ++ // Only relay BOOTREQUEST on upstream interfaces ++ if (!(out->flags & INTERFACE_UPSTREAM)) ++ continue; ++ ++ if (send_packet(out, NULL, packet, ++ length, ip->addresses[0],&sp->to, NULL) < 0) { ++ ++client_packet_errors; ++ } else { ++ log_debug("Forwarded BOOTREQUEST for %s to %s on interface %s", ++ print_hw_addr(packet->htype, packet->hlen, ++ packet->chaddr), ++ inet_ntoa(sp->to.sin_addr), out->name); ++ ++ ++client_packets_relayed; ++ } ++ } + } + } +- + } + + /* Strip any Relay Agent Information options from the DHCP packet +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0008-Don-t-skip-down-interfaces-when-discovering-interfac.patch b/src/isc-dhcp/patch/0008-Don-t-skip-down-interfaces-when-discovering-interfac.patch new file mode 100644 index 000000000000..f088b035edb4 --- /dev/null +++ b/src/isc-dhcp/patch/0008-Don-t-skip-down-interfaces-when-discovering-interfac.patch @@ -0,0 +1,32 @@ +From 06850e9beb2c50b5cc23fc94168acd9ae58d8ef8 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Fri, 6 Dec 2019 05:53:09 +0000 +Subject: [PATCH] Don't skip down interfaces when discovering interfaces in + relay mode + +When discovering interfaces in relay mode, don't skip interfaces just +because they're down. If we fail to discover the interfaces because they +are down when the relay starts, but then are brought up at a later point +in time, the relay will discard any packets received on them because it +didn't discover the interface(s) when it started up. +--- + common/discover.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/common/discover.c b/common/discover.c +index 8d5b958..5efff49 100644 +--- a/common/discover.c ++++ b/common/discover.c +@@ -1016,7 +1016,8 @@ discover_interfaces(int state) { + info.flags & IFF_LOOPBACK || + info.flags & IFF_POINTOPOINT) && !tmp) || + (!(info.flags & IFF_UP) && +- state != DISCOVER_UNCONFIGURED)) ++ state != DISCOVER_UNCONFIGURED && ++ state != DISCOVER_RELAY)) + continue; + + /* If there isn't already an interface by this name, +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0009-Support-for-dual-tor-scenario.patch b/src/isc-dhcp/patch/0009-Support-for-dual-tor-scenario.patch new file mode 100644 index 000000000000..e918cc619106 --- /dev/null +++ b/src/isc-dhcp/patch/0009-Support-for-dual-tor-scenario.patch @@ -0,0 +1,269 @@ +From 768df61b57a0a7bda23aa8bc7e08c5b2a96a8087 Mon Sep 17 00:00:00 2001 +From: Tianrong Zhang +Date: Tue, 1 Dec 2020 16:33:34 -0800 +Subject: [PATCH] support for dual tor scenario + +--- + relay/dhcrelay.c | 117 +++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 98 insertions(+), 19 deletions(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index e158efe..055d97f 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -56,6 +56,8 @@ int bogus_agent_drops = 0; /* Packets dropped because agent option + specified. */ + int bogus_giaddr_drops = 0; /* Packets sent to us to relay back to a + client, but with a bogus giaddr. */ ++int bogus_yiaddr_drops = 0; /* Packets sent to us to relay back to a ++ client, but with a bogus yiaddr. */ + int client_packets_relayed = 0; /* Packets relayed from client to server. */ + int server_packet_errors = 0; /* Errors sending packets to servers. */ + int server_packets_relayed = 0; /* Packets relayed from server to client. */ +@@ -83,6 +85,13 @@ int max_hop_count = 10; /* Maximum hop count */ + int no_daemon = 0; + int dfd[2] = { -1, -1 }; + ++int enable_support_for_dual_tor = 0; ++ ++struct downstream_intf_list { ++ struct downstream_intf_list *next; ++ struct interface_info *interface; ++} *downstream_intfs = NULL; ++ + #ifdef DHCPv6 + /* Force use of DHCPv6 interface-id option. */ + isc_boolean_t use_if_id = ISC_FALSE; +@@ -156,6 +165,8 @@ static int load_interface_alias_map(const char *port_alias_map_file_path); + static int get_interface_alias_by_name(const char *if_name, char *if_alias_out); + static void free_interface_alias_map(void); + ++static void free_downstream_intfs(void); ++ + static const char copyright[] = + "Copyright 2004-2018 Internet Systems Consortium."; + static const char arr[] = "All rights reserved."; +@@ -189,6 +200,7 @@ char *progname; + " [-iu interface0 [ ... -iu interfaceN]\n" \ + " [-id interface0 [ ... -id interfaceN]\n" \ + " [-U interface]\n" \ ++" [-dt]\n"\ + " server0 [ ... serverN]\n\n" \ + " %s -6 [-d] [-q] [-I] [-c ]\n" \ + " [-p | -rp ]\n" \ +@@ -210,6 +222,7 @@ char *progname; + " [-iu interface0 [ ... -iu interfaceN]\n" \ + " [-id interface0 [ ... -id interfaceN]\n" \ + " [-U interface]\n" \ ++" [-dt]\n"\ + " server0 [ ... serverN]\n\n" \ + " %s -6 [-d] [-q] [-I] [-c ] [-p ]\n" \ + " [-pf ] [--no-pid]\n" \ +@@ -231,6 +244,7 @@ char *progname; + " [-iu interface0 [ ... -iu interfaceN]\n" \ + " [-id interface0 [ ... -id interfaceN]\n" \ + " [-U interface]\n" \ ++" [-dt]\n"\ + " server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE \ + " %s {--version|--help|-h}" + #else +@@ -242,6 +256,7 @@ char *progname; + " [-iu interface0 [ ... -iu interfaceN]\n" \ + " [-id interface0 [ ... -id interfaceN]\n" \ + " [-U interface]\n" \ ++" [-dt]\n"\ + " server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE \ + " %s {--version|--help|-h}" + #endif +@@ -639,7 +654,16 @@ main(int argc, char **argv) { + usage(use_noarg, argv[i-1]); + if (load_interface_alias_map(argv[i]) != 0) + log_fatal("Failed to load interface name-alias map."); +- } else if (argv[i][0] == '-') { ++ } else if (!strcmp(argv[i], "-dt")) { ++#ifdef DHCPv6 ++ if (local_family_set && (local_family == AF_INET6)) { ++ usage(use_v4command, argv[i]); ++ } ++ local_family_set = 1; ++ local_family = AF_INET; ++#endif ++ enable_support_for_dual_tor = 1; ++ } else if (argv[i][0] == '-') { + usage("Unknown command: %s", argv[i]); + } else { + struct hostent *he; +@@ -747,7 +771,6 @@ main(int argc, char **argv) { + log_fatal("No servers specified."); + } + +- + /* Set up the server sockaddrs. */ + for (sp = servers; sp; sp = sp->next) { + sp->to.sin_port = local_port; +@@ -862,6 +885,8 @@ main(int argc, char **argv) { + + /* In fact dispatch() never returns. */ + free_interface_alias_map(); ++ free_downstream_intfs(); ++ + return (0); + } + +@@ -885,25 +910,50 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, + return; + } + +- /* Find the interface that corresponds to the giaddr +- in the packet. */ +- if (packet->giaddr.s_addr) { +- for (out = interfaces; out; out = out->next) { +- int i; ++ if (enable_support_for_dual_tor) { ++ if (packet->yiaddr.s_addr) { ++ out = NULL; ++ ++ for (struct downstream_intf_list *cdi = downstream_intfs; cdi; cdi = cdi->next) { ++ int i = 0; ++ out = cdi->interface; ++ ++ for (i = 0 ; i < out->address_count ; i++ ) { ++ if ((out->addresses[i].s_addr & out->netmasks[i].s_addr) == (packet->yiaddr.s_addr & out->netmasks[i].s_addr)) { ++ i = -1; ++ break; ++ } ++ } + +- for (i = 0 ; i < out->address_count ; i++ ) { +- if (out->addresses[i].s_addr == +- packet->giaddr.s_addr) { +- i = -1; ++ if (i == -1) { + break; ++ } else { ++ out = NULL; + } + } +- +- if (i == -1) +- break; ++ } else { ++ out = NULL; + } + } else { +- out = NULL; ++ /* Find the interface that corresponds to the giaddr in the packet. */ ++ if (packet->giaddr.s_addr) { ++ for (out = interfaces; out; out = out->next) { ++ int i; ++ ++ for (i = 0 ; i < out->address_count ; i++ ) { ++ if (out->addresses[i].s_addr == ++ packet->giaddr.s_addr) { ++ i = -1; ++ break; ++ } ++ } ++ ++ if (i == -1) ++ break; ++ } ++ } else { ++ out = NULL; ++ } + } + + /* If it's a bootreply, forward it to the client. */ +@@ -913,6 +963,10 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, + return; + } + ++ /* This bootreply does not belong to the current vlan. */ ++ if (enable_support_for_dual_tor && !out) ++ return; ++ + if (!(packet->flags & htons(BOOTP_BROADCAST)) && + can_unicast_without_arp(out)) { + to.sin_addr = packet->yiaddr; +@@ -945,9 +999,13 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, + return; + + if (!out) { +- log_error("Packet to bogus giaddr %s.\n", +- inet_ntoa(packet->giaddr)); +- ++bogus_giaddr_drops; ++ if (!enable_support_for_dual_tor) { ++ log_error("Packet to bogus giaddr %s.\n", inet_ntoa(packet->giaddr)); ++ ++bogus_giaddr_drops; ++ } else { ++ log_error("Packet to bogus yiaddr %s.\n", inet_ntoa(packet->yiaddr)); ++ ++bogus_yiaddr_drops; ++ } + return; + } + +@@ -989,6 +1047,7 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, + that set giaddr, so we won't see it. */ + if (!packet->giaddr.s_addr) + packet->giaddr = ip->addresses[0]; ++ + if (packet->hops < max_hop_count) + packet->hops = packet->hops + 1; + else +@@ -1264,7 +1323,6 @@ find_interface_by_agent_option(struct dhcp_packet *packet, + + /* Scan the interface list looking for an interface whose + name matches the one specified in circuit_id. */ +- + for (ip = interfaces; ip; ip = ip->next) { + if (ip->circuit_id && + ip->circuit_id_len == circuit_id_len && +@@ -1668,6 +1726,7 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + *sp++ = 4u; + memcpy(sp, &giaddr.s_addr, 4); + sp += 4; ++ + packet->giaddr = uplink->addresses[0]; + log_debug ("Adding link selection suboption" + " with addr: %s", inet_ntoa(giaddr)); +@@ -2398,6 +2457,7 @@ void request_v4_interface(const char* name, int flags) { + struct interface_info *tmp = NULL; + int len = strlen(name); + isc_result_t status; ++ struct downstream_intf_list *ci = NULL; + + if (len >= sizeof(tmp->name)) { + log_fatal("%s: interface name too long (is %d)", name, len); +@@ -2413,6 +2473,15 @@ void request_v4_interface(const char* name, int flags) { + (flags & INTERFACE_UPSTREAM ? 'Y' : 'N'), + (flags & INTERFACE_DOWNSTREAM ? 'Y' : 'N')); + ++ if (flags & INTERFACE_DOWNSTREAM) { ++ ci = ((struct downstream_intf_list *)dmalloc(sizeof *ci, MDL)); ++ if (!ci) ++ log_fatal("no memory for downstream interface pointer.\n"); ++ ci->next = downstream_intfs; ++ downstream_intfs = ci; ++ ci->interface = tmp; ++ } ++ + strncpy(tmp->name, name, len); + interface_snorf(tmp, (INTERFACE_REQUESTED | flags)); + interface_dereference(&tmp, MDL); +@@ -2487,3 +2556,13 @@ free_interface_alias_map(void) { + free(g_interface_name_alias_map); + g_interface_name_alias_map_size = 0; + } ++ ++static void ++free_downstream_intfs(void) { ++ struct downstream_intf_list *cdi; ++ while (downstream_intfs) { ++ cdi = downstream_intfs; ++ downstream_intfs = downstream_intfs->next; ++ free(cdi); ++ } ++} +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0010-Bugfix-correctly-set-interface-netmask.patch b/src/isc-dhcp/patch/0010-Bugfix-correctly-set-interface-netmask.patch new file mode 100644 index 000000000000..409e2e32f30e --- /dev/null +++ b/src/isc-dhcp/patch/0010-Bugfix-correctly-set-interface-netmask.patch @@ -0,0 +1,24 @@ +From b19547b0574132e4b2efbda012f3169e4db7923c Mon Sep 17 00:00:00 2001 +From: Tianrong Zhang +Date: Mon, 30 Nov 2020 18:42:09 -0800 +Subject: [PATCH] Bugfix: correctly set interface netmask + +--- + common/discover.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/common/discover.c b/common/discover.c +index c6b2431..06e0b12 100644 +--- a/common/discover.c ++++ b/common/discover.c +@@ -479,6 +479,7 @@ next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) { + sa_len = ifaces->next->ifa_addr->sa_len; + #endif + memcpy(&info->addr, ifaces->next->ifa_addr, sa_len); ++ memcpy(&info->netmask, ifaces->next->ifa_netmask, sa_len); + } + info->flags = ifaces->next->ifa_flags; + ifaces->next = ifaces->next->ifa_next; +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0011-dhcp-relay-Prevent-Buffer-Overrun.patch b/src/isc-dhcp/patch/0011-dhcp-relay-Prevent-Buffer-Overrun.patch new file mode 100644 index 000000000000..fda59d9e69aa --- /dev/null +++ b/src/isc-dhcp/patch/0011-dhcp-relay-Prevent-Buffer-Overrun.patch @@ -0,0 +1,30 @@ +From 19e400c1040e3621db6a0d8dd70d18c431d1a848 Mon Sep 17 00:00:00 2001 +From: Tamer Ahmed +Date: Sat, 28 Nov 2020 16:28:37 -0800 +Subject: [PATCH] [dhcp-relay] Prevent Buffer Overrun + +The add/strip relay agent options do not take into account the buffer +length and so it is possible to overrun the buffer. The issue will +result in contents from previous packet being added to the current one. + +signed-off-by: Tamer Ahmed +--- + relay/dhcrelay.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 055d97f..1cd99b9 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -1527,7 +1527,7 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + /* Commence processing after the cookie. */ + sp = op = &packet->options[4]; + +- while (op < max) { ++ while ((op < max) && (op < (((u_int8_t *)packet) + length))) { + switch(*op) { + /* Skip padding... */ + case DHO_PAD: +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/series b/src/isc-dhcp/patch/series new file mode 100644 index 000000000000..a34b5bf4b0df --- /dev/null +++ b/src/isc-dhcp/patch/series @@ -0,0 +1,12 @@ +# This series applies on GIT commit d0d58776805d720029619ea06df5c57706eecd5a +0001-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch +0002-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch +0003-Support-for-obtaining-name-of-physical-interface-tha.patch +0004-Support-for-loading-port-alias-map-file-to-replace-p.patch +0005-Add-enable-use-sockets-to-configure-flags-in-debian-.patch +0006-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch +0007-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch +0008-Don-t-skip-down-interfaces-when-discovering-interfac.patch +0009-Support-for-dual-tor-scenario.patch +0010-Bugfix-correctly-set-interface-netmask.patch +0011-dhcp-relay-Prevent-Buffer-Overrun.patch diff --git a/src/ixgbe/.gitignore b/src/ixgbe/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/ixgbe/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/ixgbe/Makefile b/src/ixgbe/Makefile new file mode 100644 index 000000000000..90d20e606ef6 --- /dev/null +++ b/src/ixgbe/Makefile @@ -0,0 +1,22 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = ixgbe.ko + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf ./ixgbe-$(IXGBE_DRIVER_VERSION) + wget -O ixgbe-$(IXGBE_DRIVER_VERSION).tar.gz "https://sonicstorage.blob.core.windows.net/packages/ixgbe-5.2.4.tar.gz?sv=2015-04-05&sr=b&sig=AaqJHHaPiJRp8R3HKobi0GNDgHAVnqijk6hpahwJ0Mg%3D&se=2154-10-05T22%3A19%3A29Z&sp=r" + tar xzf ixgbe-$(IXGBE_DRIVER_VERSION).tar.gz + + # Patch + pushd ./ixgbe-$(IXGBE_DRIVER_VERSION) + + # Build the package + pushd src + export BUILD_KERNEL=$(KVERSION) + make + popd + + popd + mv ./ixgbe-$(IXGBE_DRIVER_VERSION)/src/$* $(DEST)/ diff --git a/src/kdump-tools/.gitignore b/src/kdump-tools/.gitignore new file mode 100644 index 000000000000..d19db76ab9a9 --- /dev/null +++ b/src/kdump-tools/.gitignore @@ -0,0 +1,4 @@ +* +!.gitignore +!Makefile +!patch/ diff --git a/src/kdump-tools/Makefile b/src/kdump-tools/Makefile new file mode 100644 index 000000000000..dadf08503af1 --- /dev/null +++ b/src/kdump-tools/Makefile @@ -0,0 +1,32 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(KDUMP_TOOLS) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./makedumpfile_$(KDUMP_TOOLS_VERSION_BASE).orig.tar.gz ./makedumpfile_$(KDUMP_TOOLS_VERSION).debian.tar.xz + rm -rf ./makedumpfile-$(KDUMP_TOOLS_VERSION_BASE) + + # Get makedumpfile release + wget http://deb.debian.org/debian/pool/main/m/makedumpfile/makedumpfile_$(KDUMP_TOOLS_VERSION_BASE).orig.tar.gz + wget http://deb.debian.org/debian/pool/main/m/makedumpfile/makedumpfile_$(KDUMP_TOOLS_VERSION).debian.tar.xz + tar -f makedumpfile_$(KDUMP_TOOLS_VERSION_BASE).orig.tar.gz -x + pushd ./makedumpfile-$(KDUMP_TOOLS_VERSION_BASE) + tar -f ../makedumpfile_$(KDUMP_TOOLS_VERSION).debian.tar.xz -x + + git init + git add -f * + git commit -m "unmodified kdump-tools source" + + # Apply patches + stg init + stg import -s ../patch/series + + # Build source and Debian packages + dpkg-buildpackage -rfakeroot -b -us -uc -Tbinary-indep -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + # Move the newly-built .deb packages to the destination directory + mv $* $(DEST)/ diff --git a/src/kdump-tools/patch/0001-Generate-initramfs-for-installed-kernels-in-chroot.patch b/src/kdump-tools/patch/0001-Generate-initramfs-for-installed-kernels-in-chroot.patch new file mode 100644 index 000000000000..1d994b88bd58 --- /dev/null +++ b/src/kdump-tools/patch/0001-Generate-initramfs-for-installed-kernels-in-chroot.patch @@ -0,0 +1,41 @@ +From 7e6c0d5b0c7299154f75f281c02cf02cf85fb80e Mon Sep 17 00:00:00 2001 +From: Benjamin Drung +Date: Thu, 2 Mar 2017 19:52:23 +0100 +Subject: [PATCH] Generate initramfs for installed kernels in chroot + +The postinst script from kdump-tools creates an initramfs for the +running kernel. When running inside a chroot, the running kernel (from +the host) might differ from the kernels that are available in the +chroot. + +Thus generate the initramfs only when the running kernel is installed in +the system. Otherwise generate the initramfs for all installed kernels. + +Bug-Debian: #856594 +--- + debian/kdump-tools.postinst | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/debian/kdump-tools.postinst b/debian/kdump-tools.postinst +index 4b6c6be..f604c8e 100755 +--- a/debian/kdump-tools.postinst ++++ b/debian/kdump-tools.postinst +@@ -33,7 +33,15 @@ update_param() { + case "$1" in + configure) + # create smaller initrd.img files for kdump use +- /etc/kernel/postinst.d/kdump-tools $(uname -r) > /dev/null 2>&1 ++ if test -d /lib/modules/$(uname -r); then ++ /etc/kernel/postinst.d/kdump-tools $(uname -r) > /dev/null 2>&1 ++ else ++ # Running kernel not installed. Running in chroot? ++ for kernel_release in $(ls /lib/modules/); do ++ /etc/kernel/postinst.d/kdump-tools $kernel_release > /dev/null 2>&1 ++ kdump-config symlinks $kernel_release ++ done ++ fi + + # Customize crashkernel= value according to architecture + ARCH="$(arch)" +-- +2.9.3 diff --git a/src/kdump-tools/patch/0002-core-file-prefixed-by-kdump.patch b/src/kdump-tools/patch/0002-core-file-prefixed-by-kdump.patch new file mode 100644 index 000000000000..2ed480b26175 --- /dev/null +++ b/src/kdump-tools/patch/0002-core-file-prefixed-by-kdump.patch @@ -0,0 +1,24 @@ +--- a/debian/kdump-config.orig 2019-10-24 09:38:19.006679000 -0700 ++++ b/debian/kdump-config 2019-10-24 12:16:23.791899000 -0700 +@@ -639,8 +639,8 @@ + { + KDUMP_STAMP=`date +"%Y%m%d%H%M"` + KDUMP_STAMPDIR=$(define_stampdir $KDUMP_STAMP) +- KDUMP_CORETEMP="$KDUMP_STAMPDIR/dump-incomplete" +- KDUMP_COREFILE="$KDUMP_STAMPDIR/dump.$KDUMP_STAMP" ++ KDUMP_CORETEMP="$KDUMP_STAMPDIR/kdump-incomplete" ++ KDUMP_COREFILE="$KDUMP_STAMPDIR/kdump.$KDUMP_STAMP" + KDUMP_DMESGFILE="$KDUMP_STAMPDIR/dmesg.$KDUMP_STAMP" + + # If we use NFS, verify that we can mount the FS +@@ -755,8 +755,8 @@ + KDUMP_STAMP=`date +"%Y%m%d%H%M"` + KDUMP_STAMPDIR=$(define_stampdir $KDUMP_STAMP) + +- KDUMP_CORETEMP="$KDUMP_STAMPDIR/dump-incomplete" +- KDUMP_COREFILE="$KDUMP_STAMPDIR/dump.$KDUMP_STAMP" ++ KDUMP_CORETEMP="$KDUMP_STAMPDIR/kdump-incomplete" ++ KDUMP_COREFILE="$KDUMP_STAMPDIR/kdump.$KDUMP_STAMP" + KDUMP_TMPDMESG="/tmp/dmesg.$KDUMP_STAMP" + KDUMP_DMESGFILE="$KDUMP_STAMPDIR/dmesg.$KDUMP_STAMP" + ERROR=0 diff --git a/src/kdump-tools/patch/series b/src/kdump-tools/patch/series new file mode 100644 index 000000000000..e1a26e55ca1b --- /dev/null +++ b/src/kdump-tools/patch/series @@ -0,0 +1,2 @@ +0001-Generate-initramfs-for-installed-kernels-in-chroot.patch +0002-core-file-prefixed-by-kdump.patch diff --git a/src/libnl3/.gitignore b/src/libnl3/.gitignore new file mode 100644 index 000000000000..906fc0b87997 --- /dev/null +++ b/src/libnl3/.gitignore @@ -0,0 +1,5 @@ +* +!.gitignore +!debian/ +debian/libnl-*/ +!Makefile diff --git a/src/libnl3/Makefile b/src/libnl3/Makefile new file mode 100644 index 000000000000..c45ac85b7288 --- /dev/null +++ b/src/libnl3/Makefile @@ -0,0 +1,29 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = libnl-3-200_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb +DERIVED_TARGETS = libnl-3-dev_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb \ + libnl-genl-3-200_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb \ + libnl-genl-3-dev_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb \ + libnl-route-3-200_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb \ + libnl-route-3-dev_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb \ + libnl-nf-3-200_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb \ + libnl-nf-3-dev_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb \ + libnl-cli-3-200_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb \ + libnl-cli-3-dev_$(LIBNL3_VERSION)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtaining the libnl3 + rm -rf ./libnl3-$(LIBNL3_VERSION_BASE) + git clone https://github.com/thom311/libnl libnl3-$(LIBNL3_VERSION_BASE) + pushd libnl3-$(LIBNL3_VERSION_BASE) + git checkout tags/libnl$(subst .,_,$(LIBNL3_VERSION_BASE)) + + ln -s ../debian debian + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/libnl3/debian/README.Debian b/src/libnl3/debian/README.Debian new file mode 100644 index 000000000000..002e249bbfcb --- /dev/null +++ b/src/libnl3/debian/README.Debian @@ -0,0 +1,17 @@ + +libnl versions explained +======================== + +Once libnl3 hits the archive there will exist 3 versions of libnl. +libnl1 with libnl-dev - up until March 2011 the stable version +libnl2 with libnl2-dev - development version that resulted in +libnl3 with libnl3-dev - the new stable (API and ABI wise) version + +libnl1 has currently a lot of users in the archive and a lot of changes +happened since its last upstream release in 2008-01. + +The plan is therefore to introduce libnl3, port the two users of libnl2 +(freesmartphone.org libs and powertop) to it, remove libnl2 and don't touch +libnl1 and libnl-dev for now. + + -- Heiko Stuebner Sat, 21 May 2011 19:25:13 +0200 diff --git a/src/libnl3/debian/README.source b/src/libnl3/debian/README.source new file mode 100644 index 000000000000..f6e8ee70da94 --- /dev/null +++ b/src/libnl3/debian/README.source @@ -0,0 +1,10 @@ +This package uses the simple-patchsys of cdbs. + +The following patches are used: +0001: Fixes the header inclusion in the Makefiles. + This for example make distcheck +0002: Includes all generated libraries as linktargets in the pkg-config file. + Reason: Currently libnl3 generates a bunch of child libraries. + These don't get individual .pc files from upstream at the moment but + programs linking against libnl3 using the .pc file mostly need these + additional libraries too. diff --git a/src/libnl3/debian/changelog b/src/libnl3/debian/changelog new file mode 100644 index 000000000000..c51ae1121796 --- /dev/null +++ b/src/libnl3/debian/changelog @@ -0,0 +1,1043 @@ +libnl3 (3.5.0-1) unstable; urgency=low + + [ skuklinski ] + * route/link: IFLA_VLAN_PROTOCOL added to vlan_put_attrs + + [ Thomas Haller ] + * rtnl/link: indicate capability NL_CAPABILITY_RTNL_LINK_VLAN_PROTOCOL_SERIALZE + + [ David Ahern ] + * route/vrf: add VRF support + * neigh: add support for NTF_SELF + + [ Beniamino Galvani ] + * route/link: fix parsing of 'remote' attribute for GRE links + + [ Thomas Haller ] + * route/vlan: allow clearing vlan ingress map + + [ David Ahern ] + * link/neigh: add flags option to link and neighbor caches + + [ Thomas Haller ] + * gitignore: ignore test binaries in "tests/" + + [ Beniamino Galvani ] + * route/link: add macvtap support + * route/link: fix dump of parent link for some link types + * route/link: add ipv6 support to vxlan links + + [ Tobias Jungel ] + * route/link: corrected array size for inet_policy + + [ David Ahern ] + * route/link: add link info compare operation + * route/link/vxlan: trivial rename VXLAN_HAS_ prefix and vxi_mask + * route/link/vxlan: add support for link_info compare + + [ Andrew Vagin ] + * libnl: don't use out-of-scope buffer in nl_send_iovec() + + [ David Ahern ] + * link: add AF operation to append attributes to a GETLINK message + * lib: handle family-based parsing of IFLA_AF_SPEC attribute + + [ Thomas Haller ] + * include/linux: update copy of kernel headers + + [ David Ahern ] + * bridge: add support for VLANs + + [ Tobias Jungel ] + * route/link: handle RTEXT_FILTER_BRVLAN_COMPRESSED + * route/link/bridge: fixed return type + + [ Quentin Armitage ] + * route/link: add support for IN6_ADDR_GEN_MODE_STABLE_PRIVACY + + [ Amit Khatri ] + * lib/route: potential memory leak in pktloc.c + + [ Nick Lewycky ] + * remove null dereference from netlink/link.h + + [ David Ahern ] + * lib: update ce-mask to uint64_t + + [ Thomas Haller ] + * libnl: add nl_object_diff64() to libnl-3.sym + * lib/utils: add NL_CAPABILITY_NL_OBJECT_DIFF64 capability + + [ Przemyslaw Szczerbik ] + * lib: add type casting for nla_for_each_nested macro + + [ Tobias Klauser ] + * build: move -rdynamic from CPPFLAGS to LDFLAGS + + [ Thomas Haller ] + * route: sort entries in libnl-route-3.sym by name + + [ Haishuang Yan ] + * ipgre: add support for gretap tunnel + + [ Thadeu Lima de Souza Cascardo ] + * sit: add 6RD support + + [ Thomas Haller ] + * sit/trivial: whitespace + * sit: don't print ip6rd_prefix as integer in sit_dump_details() + * sit: refactor IS_SIT_LINK_ASSERT() + * sit: fix invalid declaration of rtnl_link_sit_get_proto() in sit.h + * sit: add public API for sit 6RD support + + [ Jonas Johansson ] + * neigh: support neighbour flag NTF_SELF + * neigh: add function to look up neighbour (fdb) by ifindex, mac and vlan + + [ Jef Oliver ] + * link: support RTEXT_FILTER_VF + + [ Thomas Haller ] + * link: allow overwriting IFLA_EXT_MASK flag in ao_get_af() function + + [ Przemyslaw Szczerbik ] + * lib: return error on Netlink attribute length overflow + + [ Thomas Egerer ] + * xfrm: fix buffer overflow when copying keys + * xfrm: check length of alg_name before strcpying it + * xfrm: make character pointers in setters const + * xfrm: fix segfault when using encapsulation templates + + [ Thomas Haller ] + * xfrm: reuse encap data in xfrmnl_sa_set_encap_tmpl() + + [ Thomas Egerer ] + * xfrm: fix memory leak for encap original address + * xfrm: attach only one xfrm alg attribute to netlink message + + [ Thomas Haller ] + * xfrm: fix memleak in build_xfrm_sa_message() error-path + + [ Sabrina Dubroca ] + * pass flags through ->io_compare op + * vxlan: properly handle LOOSE_COMPARISON in ->io_compare + * import macsec uapi headers + * lib/route: add macsec support + + [ Thomas Haller ] + * xfrm: allow avoiding buffer overflow for key in xfrmnl_sa_get_*_params() + * route/addr: fix ID comparison for AF_INET and AF_INET6 addresses + * route/addr: fix handling peer addresses for IPv4 addresses + * route/addr: add capability NL_CAPABILITY_RTNL_ADDR_PEER_FIX to indicate address fixes + * build: fix adding macsec files to include/Makefile.am + * libnl-3.2.28-rc1 release + * libnl-3.2.28 release + + [ Craig Gallek ] + * build: fixup headers for C++ inclusion + + [ Peter Wu ] + * trivial: whitespace-only fixes for src and lib + * cli: add noreturn attributes + * xfrm: fix memleak in another error path of build_xfrm_sa_message + * exp: fix a GCC 6 -Wmisleading-indentation warning + * doc: fix URLs and typo + + [ Tobias Jungel ] + * route/addr: address attributes based on object + + [ Thomas Haller ] + * lib: capability NL_CAPABILITY_RTNL_ADDR_PEER_ID_FIX for ID comparison of v4 addresses + * nl-addr: avoid read-out-of-bound in nl_addr_fill_sockaddr() + + [ André Draszik ] + * lib: add utility function nl_strerror_l() + * lib: switch to using strerror_l() instead of strerror_r() + * src: switch to using strerror_l() instead of strerror_r() + + [ Jeff Squyres ] + * compat: add linux/socket.h for __kernel_sa_family_t + + [ Jef Oliver ] + * lib/route: allow override of message type during link change + * lib/route: set IFLA_PROTINFO attribute in request message + * lib/route: modify link/bridge to set attributes + + [ Davide Caratti ] + * macsec: fix endianness of 'sci' parameter + * macsec: fix maximum ICV length + * remove multiple implementations of htonll(), ntohll() + + [ Jef Oliver ] + * lib/route: Fix appending IFLA_BRPORT_FASTLEAVE + * lib/route: Add port state translation functions + * lib/route: Extend Bridge Flags + * lib/route: Allow override of IFLA_AF_SPEC nesting + * lib/route: Support IFLA_BRIDGE_MODE + + [ Thomas Haller ] + * trivial: whitespace + * bridge: change return values for rtnl_link_bridge_get_hwmode() + + [ Michael Braun ] + * macvlan: add support for "source" mode + + [ Thomas Haller ] + * macvlan: adjust types and merge MACVLAN_HAS_MACCOUNT and MACVLAN_HAS_MACDATA + + [ Brandon Carpenter ] + * vxlan: add support for additional VXLAN attributes. + + [ Thomas Haller ] + * vxlan: fix exporting new symbols + * vxlan: remove redundant enable/disable API from vxlan + * vxlan: restore previous VXLAN_ATTR flag values + * vxlan: don't store vxlan flags as ce_mask + * vxlan: refactor setting/getting vxlan flags + * vxlan: fix error code for missing attribute + + [ Jef Oliver ] + * lib/route: Export correct ipgre functionality + + [ Thomas Haller ] + * lib/route: preserve old ABI for rtnl_link_get_pmtudisc() + + [ Thomas Egerer ] + * xfrm: fix xfrm security context management + * xfrm: add capability reference to xfrmnl_sa_set_* + + [ Thomas Haller ] + * xfrm: remove unused struct xfrmnl_sec_ctx from header files + + [ Jef Oliver ] + * lib/route: SRIOV Parse and Read support + * lib/route: SRIOV Clone Support + * lib/route: SRIOV Utility Functions + * lib/route: SRIOV Info Dump Functions + * lib/route: SRIOV Set Functionality + + [ Thomas Haller ] + * route: remove symbols of internal API from ABI + + [ Tobias Klauser ] + * lib/route: keep link stats minlen compatible with kernel < 4.6 + + [ Thomas Haller ] + * utils: add internal _nl_offset_plus_sizeof() macro + * lib/route: use _nl_offset_plus_sizeof() macro for minlen field for rtln_link_policy + + [ Jonas Johansson ] + * Add PPP support + * ppp: update code after review + * ppp: rename local struct ppp_info* variables; pi -> info + * ppp: fix type of file descriptor; uint32_t -> int32_t + + [ Thomas Haller ] + * ppp: fix API in ppp.h header + + [ Sushma Sitaram ] + * route/cls: support setting of selector fields + + [ Tobias Klauser ] + * src: nl-link-stats: use correct rtnl link stats maximum + * lib/route: add rx_nohandler link stats field + + [ Thomas Haller ] + * nl-link-stats: prefer RTNL_LINK_STATS_MAX over __RTNL_LINK_STATS_MAX + * lib/route: pass sizeof() argument to nl_memcpy() + * link: set ifi_change flags for rtnl_link_build_add_request() + * lib: use MSG_PEEK by default for nl_recvmsgs() + + [ Tobias Jungel ] + * cache_mngr: add include callback v2 + + [ Tobias Klauser ] + * cache: fix GCC warning and avoid variable shadowing + + [ Sushma Sitaram ] + * route/act: add gact tc action + + [ Tobias Klauser ] + * link: add support for IFLA_CARRIER_CHANGES + * link: add support for IFLA_PHYS_PORT_NAME + * link: add support for IFLA_PHYS_SWITCH_ID + * link: add support for IFLA_GSO_MAX_SEGS and IFLA_GSO_MAX_SIZE + * link: fix documentation for rtnl_link_get_carrier_changes + + [ Thomas Haller ] + * libnl-3.2.29-rc1 release + * utils/trivial: rename internal _nl_offset_plus_sizeof() macro to _nl_offsetofend() + + [ Beniamino Galvani ] + * Revert "macsec: fix endianness of 'sci' parameter" + * macsec: document byte order for the SCI and port attributes + + [ Thomas Haller ] + * macsec: fix endianness of sci during dump() + * libnl-3.2.29 release + + [ Tobias Klauser ] + * route/tc: Remove unused function tca_set_kind() + + [ Laine Stump ] + * sriov: fix crash in rtnl_link_sriov_parse_vflist + + [ Thomas Haller ] + * sriov: avoid buffer overrun in rtnl_link_sriov_parse_vflist() + + [ Nick Kralevich ] + * lib/utils.c: lazy initialize user_hz and psched_hz + + [ Thomas Haller ] + * lib/utils.c: ensure calling get_psched_settings() for nl_us2ticks()/nl_ticks2us() + * lib/utils.c: add mutex to get_psched_settings() + + [ Nick Kralevich ] + * fopen: add O_CLOEXEC + + [ Thomas Haller ] + * lib/attr.c: check for valid length argument in nla_reserve() + + [ Tobias Klauser ] + * sit: Fix invalid function prototypes in public header + * sriov: Add missing prototype for rtnl_link_vf_vlan_free() + * qdisc/red: Add missing prototypes for rtnl_red_set_limit() and rtnl_red_get_limit() + * fib_lookup: Add missing prototypes to public header + * link/inet6: Include own public header for function prototypes + * link/ipip: Include own public header for function prototypes + * link/ipip: Add missing prototype for rtnl_link_is_ipip() + * link/ipvti: Include own public header for function prototypes + * link/ipvti: Fix and add function prototypes in public header + * link/macsec: Include own public header for function prototypes + * link/sit: Add missing prototype for rtnl_link_is_sit() + * link/ipgre: Add prototype for ABI-preserving wrapper rtnl_link_get_pmtudisc() + * netfilter/queue: Add missing prototype for nfnl_queue_msg_build_verdict_batch() + * netfilter/exp: Add missing function prototypes + * idiag/req: Add missing function prototype + * xfrm/ae: Include own public header for function prototypes + * xfrm/lifetime: Include own public header for function prototypes + * xfrm/sa: Include own public header for function prototypes + * xfrm/selector: Include own public header for function prototypes + * xfrm/template: Include own public header for function prototypes + * pktloc: Add missing function prototypes + * ematch: Add missing function prototypes + * build: Add -Wmissing-prototypes to CPPFLAGS + + [ Jeroen Roovers ] + * build: distribute in.h in6.h libc-compat.h + + [ Thomas Haller ] + * lib: fix comment for nl_recv() about return value for non-blocking read + * lib: check for integer-overflow in nlmsg_reserve() + * build: cleanup top-level Makefile.am + * build: merge include/Makefile.am into top-level makefile + * build: merge lib/Makefile.am into top-level makefile + * build: merge man/Makefile.am into top-level makefile + * build: merge python/Makefile.am into top-level makefile + * build: merge tests/Makefile.am into top-level makefile + * build: merge src/lib/Makefile.am into top-level makefile + * build: merge src/Makefile.am into top-level makefile + * build: enable building cli during tests + * build: move compiler warning flags to separate autoconf variable + * all: enable -Wmissing-prototype warning for all components + * build: enable more warnings + + [ Roopa Prabhu ] + * route: neigh: use NDA_MASTER for neigh->n_master if available + + [ Simon Buttgereit ] + * fix build_xfrm_sp_message index condition + * fix xfrmnl_sp_set_sec_ctx length attributes + * little style fixes. + * update sp_attr condition in build_xfrm_sp_message + * add possibity to delete policy without index + * update documentation of xfrmnl_sp_get_sec_ctx + * fix of boolean operators + + [ Thomas Haller ] + * xfrm: allow quering optional arguments from xfrmnl_sp_get_sec_ctx() + * xfrm: NUL terminate the ctx_str buffer in xfrmnl_sa_set_sec_ctx() + * build: ensure build directory for generated sources exist + * build: pass --disable-dependency-tracking to `make distcheck` + * build: fix creating directories for generated sources + * build: style cleanup in doc/Makefile.am + * build: reorder checks in configure.ac + * build: add tools/build_release.sh script + * include: don't include kernel headers in public libnl3 headers + * include: restore linux header includes in public headers + * libnl-3.3.0-rc1 release + + [ Alexey Brodkin ] + * lib: escape usage of strerror_l() if it doesn't exist in libc + + [ Thomas Haller ] + * all: don't use math.h or link with libm.so + * libnl-3.3.0 release + * tools: fix building doc in build_release.sh + + [ Markus Trapp ] + * route/link: add accessor API for IPv6 flags + + [ Santhosh Kumar ] + * Provide accessors for actions (rtnl_act). + * Do not increment refcount in rtnl_*_get_action APIs. + + [ Thomas Haller ] + * route: fix symbol versioning + + [ David Ahern ] + * route: Add support for netconf + * nl-monitor: All user to specify line format + * nl-monitor: Add support for netconf caches + * route: Add support for MPLS to netconf + * Update fib_rules.h to latest kernel + * rule: Add support for l3mdev in FIB rules + + [ Thomas Haller ] + * rule: change API for setting/getting l3mdev rule property + + [ Tobias Klauser ] + * addr: add AF_VSOCK to translation table + + [ Thomas Haller ] + * build: don't build cli libraries by default + * build: allow building cli without dynamic librarires support + + [ Tobias Klauser ] + * genl: drop usage of GENL_ID_GENERATE + + [ Rasmus Villemoes ] + * lib/cache_mngr.c: avoid memleak if realloc fails + * lib/cache_mgr.c: remove pointless goto + * lib/data.c: avoid memleak if realloc fails + * lib/route/cls/u32.c: remove pointless nl_data_append calls + * lib/route/cls/u32.c: avoid overflowing an unsigned char + * lib/route/cls/u32.c: let the compiler do pointer arithmetic + * lib/route/cls/u32.c: remove bogus comment + * lib/route/qdisc/netem.c: avoid memory leak if realloc fails + + [ Thomas Haller ] + * lib/route/cls/u32.c: use UCHAR_MAX define instead of numeric 255 + * lib/route/qdisc/netem.c/trivial: fix whitespace and indentation in netem_msg_fill_raw() + * lib/route/qdisc/netem.c/trivial: don't use braces for one-line blocks + + [ Rasmus Villemoes ] + * lib/xfrm/ae.c: fix memcpy(dst, dst) bug + * lib/genl/family.c: fix if (x) y; else y; + + [ Thomas Haller ] + * all: avoid compiler warnings -Wimplicit-fallthrough + * lib/route: add /usr/lib64/tc/ search path for netem dist file + + [ David Ahern ] + * Update rtnetlink.h from kernel tree + * Import mpls header from kernel tree + + [ Thomas Haller ] + * build: add include/linux-private/linux/mpls.h to Makefile.am + + [ David Ahern ] + * addr: Add implementations for mpls_ntop and mpls_pton + * addr: Add support for AF_MPLS + * route: Add support for MPLS address family + * route: Add support for ttl propagation in MPLS routes + * Add support for label stack in nl-route commands + * Import lwtunnel encap files from kernel + * route: Add support for lwtunnel encapsulations + * route: Add support for MPLS encap + + [ Thomas Haller ] + * build: add new include/netlink-private/route/*.h files to Makefile.am + + [ Amit Khatri ] + * Potential memory leak becaue of wrong variable check. + + [ Tobias Klauser ] + * cli: include sys/select.h for select(2) + + [ Thomas Haller ] + * libnl-3.4.0-rc1 release + + [ David Ahern ] + * netconf: Put nc reference in msg_parser + + [ Jeroen Roovers ] + * build: add missing headers for issue #152 + + [ Thomas Haller ] + * libnl-3.4.0 release + * nl: add "const" specifier for nla_policy argument of parse functions [ Roopa Prabhu ] + * route: link: add family to dump messages + * route: neigh: print family in neigh dumps + + [ Sebastian Bixl ] + * route/vlan: fix memory corruption in rtnl_link_vlan_set_egress_map + + [ Thomas Haller ] + * route/vlan: fix cloning vlan link in vlan_clone() + * route/vlan: grow buffer exponentially in rtnl_link_vlan_set_egress_map() + * route/vlan: add capability to indicate heap overflow fix in rtnl_link_vlan_set_egress_map() + * route: fix handling old_nh in rtnl_route_parse() and avoid leak + + [ Jef Oliver ] + * Change rtnl_link_af_ops.ao_override_rtm behavior + + [ Chris Grahn ] + * tests: fix bug in test-create-bridge.c + + [ Steffen Vogel ] + * route: add separate function to set netem qdisc delay distribution + + [ Thomas Haller ] + * all: declare all variables at the beginning of scope (-Wdeclaration-after-statement) + * route: add rtnl_netem_set_delay_distribution_data() to linker script + * route: mark data argument for rtnl_netem_set_delay_distribution_data() as const + * route: fix memleak in rtnl_netem_set_delay_distribution_data() + * route: free previous data in rtnl_netem_set_delay_distribution_data() + * travis: enable more warnings during build + + [ Marcos Paulo de Souza ] + * tests: Add test to {de}activate loopback interface + * lib/veth.c: Disassociate link name of peer name + + [ d0u9 ] + * Coding style format + * Add new function for setting ifindex and parent of a classifier cache. + + [ Thomas Haller ] + * route: rename rtnl_cls_cache_set_tcm_params() and fix symbol versioning + + [ d0u9 ] + * Fix for cgroup filter addition problem. + + [ Thomas Haller ] + * lib: merge implementations of nl_attr_end() and nl_attr_keep_empty() + + [ Wang Jian ] + * link: add Geneve support. + + [ Thomas Haller ] + * lib/rtnl: rename public define RTNL_GENEVE_ID_MAX + + [ Roopa Prabhu ] + * lib: route: rule: add rule_groups to cache ops + + [ Jonas Johansson ] + * route/vrf: initalize clone destination with NULL in vrf_clone() + + [ David Ahern ] + * Update fib_rules.h to latest kernel + * rule: Add support for protocol and port ranges + + [ Lukáš Karas ] + * add demo program for listen conntrack events + * nf-ct-add typo + + [ Thomas Haller ] + * build: sort entries in Makefile.am and .gitignore by name + * build: indent libnl-route-3.sym with tabs + + [ Tobias Jungel ] + * neigh: set correct AF for NDA_DST + * neigh: support bridge entries for vxlan interfaces + + [ Tuetuopay ] + * cache: make "result" output argument for nl_cache_mngr_add() optional + + [ Volodymyr Bendiuga ] + * include: copy entire pkt_cls.h from linux + * route:cls: add matchall classifier + + [ Thomas Haller ] + * route/mall: fix deep cloning mall + + [ Tuetuopay ] + * route/link: fix sequence number handling in rtnl_link_change() + + [ Thomas Haller ] + * route/link: assert in rtnl_link_change() that the sequence number is set as expected + * nl-msg: explicitly initialize nlmsg_seq and nlmsg_pid field in nlmsg_alloc_simple() + + [ d0u9 ] + * route/class: add new api rtnl_class_get_by_parent() + + [ Tobias Jungel ] + * neigh: correct symbol exposed + + [ Matthieu Baerts ] + * nl: fix function name in debug msg + + [ Tobias Jungel ] + * neigh: cache updates as well query AF_BRIDGE neigh + * whitespace cleanup + * nl-neigh-list: free allocated items + * neigh: add get/set functions for NEIGH_ATTR_MASTER + * neigh_dump_line: dump master as well + + [ d0u9 ] + * Add support for cloning cgroup filter object. + + [ Tuetuopay ] + * route/link/vxlan: Fix IPv4 set_local resetting ce_mask + + [ Tobias Jungel ] + * neigh: update neighbour.h and add missing flags + + [ Thomas Winter ] + * ipgre: Fix wrong array size initialization + * ipvti: Fix wrong array size initialization + * if_tunnel: Update IFLA defines up to FWMARK + + [ Thomas Haller ] + * include/linux: update copy of kernel headers + + [ Volodymyr Bendiuga ] + * include: import linux header pkt_sched.h + * route:qdisc: add MQPRIO Qdisc + + [ Thomas Haller ] + * build: cleanup Makefile.am + * lib/tc: ensure correct error code in rtnl_tc_msg_build() + * lib/qdisc: style fixes in "lib/route/qdisc/mqprio.c" + * lib/qdisc: avoid BUG() in "lib/route/qdisc/mqprio.c" + * build: sort entries in libnl-route-3.sym + * lib/tc: fix uninitalized err variable in rtnl_tc_msg_build() + + [ Volodymyr Bendiuga ] + * route:tc: allow to set chain index for tc objects + + [ Thomas Haller ] + * route/tc: return error code from rtnl_tc_get_chain() + + [ Volodymyr Bendiuga ] + * include: import tc_vlan.h + * route:act: add vlan action + + [ Thomas Haller ] + * route/act: style fixes in "lib/route/act/vlan.c" + * route/act: return error code from act-vlan getters + + [ Ilya Pronin ] + * route/cls: fix potential memory leak + + [ Patrick Havelange ] + * nla_ok: fix overrun in attribute iteration. + + [ Wang Jian ] + * link: macvlan fixes + + [ Thomas Haller ] + * route/macvlan: style fixes in "lib/route/link/macvlan.c" + + [ Tobias Jungel ] + * route/link: expose IFLA_INFO_SLAVE_KIND + + [ Thomas Haller ] + * route/link: avoid dangling pointer in rtnl_link_set_slave_type() + + [ Byeonggon Lee ] + * tests: use nl_send_auto() instead of deprecated nl_send_auto_complete() in test-genl.c + + [ Thomas Haller ] + * doc: fix typos in example in documentation + * attr: mark nested attributes as NLA_F_NESTED + + [ xinbao ] + * Add CTA_LABELS and CTA_LABELS_MASK to ctattr_type according to the new kernel + + [ Thomas Haller ] + * route: fix strncpy() warning from coverity about unterminated string + * link/sriov: fix memleak in rtnl_link_sriov_clone() + * utils: add internal helper macros for cleanup + * lib/genl: avoid VLA in cmd_msg_parser() + * travis: enable -Wvla compiler warning in tests + * travis: build tests with NL_MORE_ASSERTS enabled + * xfrm: fix memory corruption (dangling pointer) when when setting xfrmnl_sa + * route/inet6: fix strncpy() in inet6_dump_details() + * route/tc: ensure not string truncation in rtnl_tc_set_kind() + * genl: reject invalid group names in genl_family_add_grp() + + [ Yegor Yefremov ] + * Add SPDX identifiers + + [ Thomas Haller ] + * lib/genl: fix allocating buffer of too small size in cmd_msg_parser() + + [ Michael Forney ] + * dbg: Use __func__ instead of __PRETTY_FUNCTION__ + * all: Avoid pointer arithmetic on `void *` + * lib: Don't return expression in function returning void + * lib: Don't omit second operand to `?` operator + * all: Use __typeof__ instead of typeof + * route: Remove stray `;` at top-level + * Sync linux headers to 4.19.66 + + [ Thomas Haller ] + * idiag: workaround and add comment about idiagnl_send_simple() only handling 8 bit flags + * lib: accept %NULL arguments for nl_addr_cmp() + * lib: fix error code from nfnl_exp_build_message() + + [ Eyal Birger ] + * doc/route: fix example code comments + * xfrmi: introduce XFRM interfaces support + + [ Thomas Haller ] + * xfrmi: return error code from getters for XFRM links + * route/trivial: sort entries in "libnl-route-3.sym" asciibetically + + [ d0u9 ] + * Add 64bit rate/ceil support for htb class + + [ Thomas Haller ] + * route/qdisc: adjust API for 64 bit rate/ceil support for htb class + * libnl-3.5.0 release + + -- Tamer Ahmed Thu, 02 Jan 2020 10:25:18 -0800 + +libnl3 (3.2.27-2) unstable; urgency=low + + * Add upstream fix for CVE-2017-0553 (Closes: #859948) + + -- Heiko Stuebner Mon, 10 Apr 2017 11:48:23 +0200 + +libnl3 (3.2.27-1) unstable; urgency=low + + * New upstream release + Including fixes for unusable sockets after a failed portid + generation (Closes: #808213) + + -- Heiko Stuebner Sun, 24 Jan 2016 23:54:47 +0100 + +libnl3 (3.2.26-1) unstable; urgency=low + + * New upstream release + * Provide Multiarch:same dev packages + * Add new libnl-xfrm library handling packet transformations + * Update standards to 3.9.6 + + -- Heiko Stuebner Mon, 13 Jul 2015 14:16:22 +0200 + +libnl3 (3.2.24-2) unstable; urgency=low + + * Backport two upstream fixes to prevent issues with older kernels: + - dfd0a80ec845 (route: don't enforce minlen in inet6_parse_protinfo() + (IFLA_PROTINFO) and inet_parse_af() (IFLA_AF_SPEC) + - 5206c050504f (route/addr: only sent IFA_FLAGS when needed to workaround + picky older kernels) + + -- Heiko Stuebner Fri, 18 Apr 2014 17:19:37 +0200 + +libnl3 (3.2.24-1) unstable; urgency=low + + * New upstream release + * Add new libnl-idiag library handling inetdiag requests + + -- Heiko Stuebner Sun, 16 Feb 2014 14:23:26 +0100 + +libnl3 (3.2.21-1) unstable; urgency=low + + * New upstream release (Closes: #707081) + Including CAN support (Closes: #698954) + * Add symbols files (Closes: #654758) + * Provide static libraries (Closes: #693939, #693940) + * Update standards to 3.9.4 + * Removed doc package. Libnl3 documentation is released + separately now. + + -- Heiko Stuebner Tue, 21 May 2013 11:39:13 +0200 + +libnl3 (3.2.7-4) unstable; urgency=low + + * Add watch file (Closes: #679473) + * Use dh-autoreconf to update the build system (Closes: 679474) + + -- Heiko Stuebner Sat, 30 Jun 2012 15:54:25 +0200 + +libnl3 (3.2.7-3) unstable; urgency=low + + * Fix FTBFS due to failing gen-tags.sh (Closes: #674322) + * Convert to Multi-Arch (Closes: #676611) + * Update standards to 3.9.3 - no changes + * Switch to dpkg-source format 3.0 (quilt) + + -- Heiko Stuebner Mon, 18 Jun 2012 21:19:30 +0200 + +libnl3 (3.2.7-2) unstable; urgency=low + + * Force doxygen dot-threads to 1 to circumvent segfaults on armel + * Add missing build-dependency on ghostscript + + -- Heiko Stuebner Mon, 05 Mar 2012 23:29:10 +0100 + +libnl3 (3.2.7-1) unstable; urgency=low + + * New upstream release + * Build-depend on source-highlight (Closes: #657254) + + -- Heiko Stuebner Mon, 13 Feb 2012 18:59:30 +0100 + +libnl3 (3.2.3-2) unstable; urgency=low + + * Upload to unstable + * Split split udeb to be in line with regular packages + * Move libnl and libnl-genl to /lib for iw and wpa_supplicant. + + -- Heiko Stuebner Mon, 19 Dec 2011 20:43:21 +0100 + +libnl3 (3.2.3-1) experimental; urgency=low + + * Upload to experimental to not break debian-installer + * Split library and dev packages for the individual libraries + * Add utils package + + [Mathieu Trudel-Lapierre ] + * New upstream release (Closes: #648819) + * debian/patches/0001-fix-headers.patch, + debian/patches/0002-link-sub-libs.patch, + debian/patches/0003-fix-out-of-tree-build.patch: dropped. + * debian/patches/0004-more-out-of-tree-build-fixes.patch: new patch; adjust + Makefiles some more to properly deal with the out-of-tree build when + generating headers and documentation. + * debian/control: + - rename packages to follow upstream soname. + - add python-pygments, xmlstarlet, texlive-latex-base and asciidoc to + Build-Depends. + * debian/rules: update due to upstream soname changes. + * debian/*.install: rename and update due to upstream soname changes. + * debian/libnl-3-200.install: netlink config files should be installed to + /etc/libnl, not /etc/libnl3. + * debian/libnl-3-doc.install, + debian/libnl-3-doc.doc-base: update to take into account new paths. + + -- Heiko Stuebner Tue, 06 Nov 2011 21:23:12 +0200 + +libnl3 (3.0-2) unstable; urgency=low + + * Acknowledge NMU + * Install config-files to /etc/libnl3 (Closes: #632790) + + -- Heiko Stuebner Mon, 26 Sep 2011 20:27:45 +0200 + +libnl3 (3.0-1.1) unstable; urgency=low + + * Non-maintainer upload with agreement from Heiko Stuebner + * Add libnl3-udeb package with seperate build for + debian-installer (Closes: #635962). + + -- Gaudenz Steinlin Fri, 29 Jul 2011 23:25:48 +0200 + +libnl3 (3.0-1) unstable; urgency=low + + * New upstream release (Closes: #626098) + see README.Debian for version explanation. + * Update standards to 3.9.2 + + -- Heiko Stuebner Sat, 21 May 2011 19:25:13 +0200 + +libnl2 (2.0-1) unstable; urgency=low + + * New upstream release (Closes: #603765) + * Fix compilation with binutils-gold or ld --no-add-needed + (Closes: #615745) + * Update standards + * Update build dependencies - tetex-live is not necessary + anymore (Closes: #616260) + + -- Heiko Stuebner Sun, 06 Mar 2011 18:20:47 +0100 + +libnl2 (1.99+git20091216-2) unstable; urgency=low + + * add README.source describing the patches in use. + * remove libnl*-provides - libnl2 should stay sepparate + from libnl1 for now + + -- Heiko Stuebner Wed, 10 Mar 2010 18:03:35 +0100 + +libnl2 (1.99+git20091216-1) unstable; urgency=low + + * New upstream snapshot + * New source name to enable installing libnl and libnl2 side by side + * Set myself as new maintainer for libnl2 according to agreement + with Michael Biebl + * Add debug package + * README.Debian warns of possible breakage in this snapshot + * Add Patch 0001 which fixes some errors in the build system + * Add Patch 0002 which adds libnl-?? libs to linker statement + until I can resolve this with upstream + + -- Heiko Stuebner Mon, 15 Feb 2010 21:50:35 +0100 + +libnl (1.1-5) unstable; urgency=low + + * Add symbols file for libnl1. + + -- Michael Biebl Wed, 25 Feb 2009 00:26:05 +0100 + +libnl (1.1-4) unstable; urgency=low + + * debian/control + - Add ${misc:Depends} to all binary packages. + - Bump Build-Depends on debhelper to (>= 7). + * debian/compat + - Bump debhelper compat level to 7. + * debian/rules + - Include debhelper.mk before other files as recommended by the cdbs + documentation. + + -- Michael Biebl Wed, 18 Feb 2009 13:26:53 +0100 + +libnl (1.1-3) unstable; urgency=low + + * debian/control + - Bump Standards-Version to 3.8.0. + * Switch to quilt for patch management. + * Add README.source which refers to the quilt documentation. + * debian/patches/limits.patch + - Add missing include to limits.h. This is required when compiling against + glibc 2.8. Thanks to Kees Cook for the patch. Closes: #501485 + + -- Michael Biebl Wed, 08 Oct 2008 21:34:34 +0200 + +libnl (1.1-2) unstable; urgency=low + + * debian/libnl-doc.doc-base + - Register the API documentation with doc-base. + * debian/control + - Add Suggests: doc-base to libnl-doc. + + -- Michael Biebl Wed, 05 Mar 2008 00:42:54 +0100 + +libnl (1.1-1) unstable; urgency=low + + * New stable upstream release. + * debian/patches/01-ip_mg_alg_internal_only.patch + - Removed, merged upstream. + * debian/control + - Rename binary package libnl1-pre8 to libnl1. + - [libnl1] Add Conflicts/Replaces: libnl1-pre8. + - [libnl-dev] Change Depends to libnl1. + * Rename debian/libnl1-pre8.install to debian/libnl1.install + * debian/copyright + - Minor updates and additions. + + -- Michael Biebl Thu, 10 Jan 2008 16:58:12 +0100 + +libnl (1.0~pre8-1) unstable; urgency=low + + * New upstream release. Closes: #456175 + * debian/control + - Bump Standards-Version to 3.7.3. No further changes required. + - The Vcs-* fields are now officially supported, so remove the XS- prefix. + - Rename binary package libnl1-pre6 to libnl1-pre8. + - [libnl1-pre8] Add Conflicts/Replaces: libnl1-pre6. The two versions are + not coinstallable. + - [libnl-dev] Change Depends to libnl1-pre8. + * Rename debian/libnl1-pre6.install to debian/libnl1-pre8.install. + * debian/patches/10-amd64-linux-types.patch + - Removed, merged upstream. + * debian/patches/01-ip_mg_alg_internal_only.patch + - Pull a fix from upstream. The header linux/ip_mp_alg.h is no longer part + of the linux kernel headers (i.e. linux-libc-dev) so remove it from + netlink/netlink.h. + + -- Michael Biebl Thu, 20 Dec 2007 07:45:03 +0100 + +libnl (1.0~pre6-6) unstable; urgency=low + + * debian/control + - Use the new "Homepage:" field to specify the upstream URL. + - Replace deprecated ${Source-Version} substvar with ${binary:Version}. + - Change Build-Depends: gs-gpl | gs-esp to Build-Depends: ghostscript. + + -- Michael Biebl Mon, 22 Oct 2007 07:15:29 +0200 + +libnl (1.0~pre6-5) unstable; urgency=low + + * debian/control + - Add XS-Vcs-* fields. + - Replace Build-Depends: tetex-bin with texlive-latex-base. teTeX is now + gone, superseded by texlive. + - Add Build-Depends: graphviz, gs-gpl | gs-esp. + The "dot" program is needed for generating the diagram image and "gs" + for the ps to png conversion. + + -- Michael Biebl Sun, 15 Apr 2007 15:45:48 +0200 + +libnl (1.0~pre6-4) unstable; urgency=medium + + * Autobuilders do not distinguish between build-arch and build-indep, they + simply run build. So we have to move doxygen and tetex-bin from + Build-Depends-Indep to Build-Depends. Closes: #408719 + * Urgency medium, as it fixes a FTBFS bug. + + -- Michael Biebl Fri, 12 Jan 2007 11:23:52 +0100 + +libnl (1.0~pre6-3) unstable; urgency=low + + * Build and package the API documentation. Closes: #406497 + * debian/control + - Add Build-Depends-Indep on doxygen and tetex-bin (dvips). + - Add new package libnl-doc. + - Add a "Suggests: libnl-doc" to libnl-dev. + * debian/rules + - Call "make gendoc" to build the API documentation. + * debian/libnl-doc.install + - Added. List the files that should be installed. + + -- Michael Biebl Fri, 12 Jan 2007 10:30:40 +0100 + +libnl (1.0~pre6-2) unstable; urgency=low + + * Update maintainer email address to biebl@debian.org. + + -- Michael Biebl Thu, 19 Oct 2006 20:16:09 +0200 + +libnl (1.0~pre6-1) unstable; urgency=low + + * New upstream release. + * Removed 20-autoconf-dirs.patch, merged upstream. + * Updated debian/copyright, libnl is now licensed under the LGPL 2.1. + * Updated debian/watch. + + -- Michael Biebl Fri, 18 Aug 2006 00:40:34 +0200 + +libnl (1.0~pre6~svn30-1) unstable; urgency=low + + * Updated to svn revision 30. + * Bumped Standards-Version to 3.7.2, no further changes required. + * Now that dak officially supports ~ in the version number, let's make use + of it. + * Some install directories were not set correctly, 20-autoconf-dirs.patch + fixes that. + + -- Michael Biebl Thu, 10 Aug 2006 19:51:42 +0200 + +libnl (0.99+1.0.svn21-4) unstable; urgency=low + + * Do not create bogus /usr/lib/pkg-config directory. Closes: #364601 + + -- Michael Biebl Mon, 24 Apr 2006 15:40:23 +0200 + +libnl (0.99+1.0.svn21-3) unstable; urgency=low + + * Include simple-patchsys.mk in debian/rules. + * Merged debian/patches/10-amd64-linux-types.patch from Ubuntu which fixes + the FTBFS error on AMD64. Closes: #358887 + Thanks to Scott James Remnant for this patch. + + -- Michael Biebl Sat, 1 Apr 2006 04:52:13 +0200 + +libnl (0.99+1.0.svn21-2) unstable; urgency=low + + * Initial upload to unstable. + * Renamed libnl1 to libnl1-pre6 to match the currently used so-name. + Otherwise dependent packages like NM will break on upgrades of libnl. + + -- Michael Biebl Tue, 7 Mar 2006 21:22:09 +0100 + +libnl (0.99+1.0.svn21-1) experimental; urgency=low + + * Initial release. Closes: #286847 + + -- Michael Biebl Tue, 21 Feb 2006 18:36:35 +0100 diff --git a/src/libnl3/debian/compat b/src/libnl3/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/src/libnl3/debian/compat @@ -0,0 +1 @@ +9 diff --git a/src/libnl3/debian/control b/src/libnl3/debian/control new file mode 100644 index 000000000000..ba5062607bc1 --- /dev/null +++ b/src/libnl3/debian/control @@ -0,0 +1,245 @@ +Source: libnl3 +Section: net +Priority: optional +Maintainer: Heiko Stuebner +Build-Depends: debhelper (>= 9), dh-exec (>= 0.3), cdbs (>= 0.4.93~), bison, flex, + automake, autoconf, dh-autoreconf, linux-libc-dev (>= 3.2.41), pkg-config +Standards-Version: 3.9.6 +Homepage: http://www.infradead.org/~tgr/libnl/ +#Vcs-Git: https://github.com/thom311/libnl/ +#Vcs-Browser: https://github.com/thom311/libnl/ + +Package: libnl-3-200 +Architecture: linux-any +Section: libs +Pre-Depends: ${misc:Pre-Depends} +Depends: ${misc:Depends}, ${shlibs:Depends} +Multi-Arch: same +Description: library for dealing with netlink sockets + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + +Package: libnl-cli-3-200 +Architecture: linux-any +Section: libs +Pre-Depends: ${misc:Pre-Depends} +Depends: libnl-3-200 (= ${binary:Version}), libnl-genl-3-200 (= ${binary:Version}), libnl-nf-3-200 (= ${binary:Version}), libnl-route-3-200 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} +Multi-Arch: same +Description: library for dealing with netlink sockets - cli helpers + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + Library for cli helpers in libnl-utils. + +Package: libnl-utils +Architecture: linux-any +Section: libs +Depends: libnl-cli-3-200 (= ${binary:Version}), libnl-idiag-3-200 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} +Description: Utilities for dealing with netlink sockets + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + These utilities help dealing with netlink sockets. + +Package: libnl-genl-3-200 +Architecture: linux-any +Section: libs +Pre-Depends: ${misc:Pre-Depends} +Depends: libnl-3-200 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} +Multi-Arch: same +Description: library for dealing with netlink sockets - generic netlink + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + API to the generic netlink protocol, an extended version of the netlink + protocol. + +Package: libnl-idiag-3-200 +Architecture: linux-any +Section: libs +Pre-Depends: ${misc:Pre-Depends} +Depends: libnl-3-200 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} +Multi-Arch: same +Description: library for dealing with netlink sockets - inetdiag interface + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + API to the inetdiag netlink protocol, handling inetdiag requests + +Package: libnl-nf-3-200 +Architecture: linux-any +Section: libs +Pre-Depends: ${misc:Pre-Depends} +Depends: libnl-3-200 (= ${binary:Version}), libnl-route-3-200 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} +Multi-Arch: same +Description: library for dealing with netlink sockets - netfilter interface + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + API to netlink based netfilter configuration and monitoring interfaces. + +Package: libnl-route-3-200 +Architecture: linux-any +Section: libs +Pre-Depends: ${misc:Pre-Depends} +Depends: libnl-3-200 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} +Multi-Arch: same +Description: library for dealing with netlink sockets - route interface + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + API to the configuration interfaces of the NETLINK_ROUTE family. + +Package: libnl-xfrm-3-200 +Architecture: linux-any +Section: libs +Pre-Depends: ${misc:Pre-Depends} +Depends: libnl-3-200 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} +Multi-Arch: same +Description: library for dealing with netlink sockets - package transformations + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + API to netlink based package transformations (such as encrypting + their payloads). + +Package: libnl-3-dev +Architecture: linux-any +Section: libdevel +Depends: libnl-3-200 (= ${binary:Version}), ${misc:Depends} +Conflicts: libnl-dev, libnl2-dev +Breaks: libnl3-dev +Replaces: libnl3-dev +Multi-Arch: same +Description: development library and headers for libnl-3 + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + This package contains the headers needed by all libraries and the files + that are needed to build applications using libnl3. + +Package: libnl-cli-3-dev +Architecture: linux-any +Section: libdevel +Depends: libnl-3-dev (= ${binary:Version}), libnl-genl-3-dev (= ${binary:Version}), libnl-nf-3-dev (= ${binary:Version}), libnl-route-3-dev (= ${binary:Version}), libnl-cli-3-200 (= ${binary:Version}), ${misc:Depends} +Multi-Arch: same +Description: development library and headers for libnl-cli-3 + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + This package contains the files that are needed to build applications using + libnl-cli-3. + +Package: libnl-genl-3-dev +Architecture: linux-any +Section: libdevel +Depends: libnl-3-dev (= ${binary:Version}), libnl-genl-3-200 (= ${binary:Version}), ${misc:Depends} +Multi-Arch: same +Description: development library and headers for libnl-genl-3 + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + This package contains the files that are needed to build applications using + libnl-genl-3. + +Package: libnl-idiag-3-dev +Architecture: linux-any +Section: libdevel +Depends: libnl-3-dev (= ${binary:Version}), libnl-idiag-3-200 (= ${binary:Version}), ${misc:Depends} +Multi-Arch: same +Description: development library and headers for libnl-genl-3 + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + This package contains the files that are needed to build applications using + libnl-idiag-3. + +Package: libnl-nf-3-dev +Architecture: linux-any +Section: libdevel +Depends: libnl-3-dev (= ${binary:Version}), libnl-route-3-dev (= ${binary:Version}), libnl-nf-3-200 (= ${binary:Version}), ${misc:Depends} +Multi-Arch: same +Description: development library and headers for libnl-nf-3 + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + This package contains the files that are needed to build applications using + libnl-nf-3. + +Package: libnl-route-3-dev +Architecture: linux-any +Section: libdevel +Depends: libnl-3-dev (= ${binary:Version}), libnl-route-3-200 (= ${binary:Version}), ${misc:Depends} +Multi-Arch: same +Description: development library and headers for libnl-route-3 + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + This package contains the files that are needed to build applications using + libnl-route-3. + +Package: libnl-xfrm-3-dev +Architecture: linux-any +Section: libdevel +Depends: libnl-3-dev (= ${binary:Version}), libnl-xfrm-3-200 (= ${binary:Version}), ${misc:Depends} +Multi-Arch: same +Description: development library and headers for libnl-xfrm-3 + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + This package contains the files that are needed to build applications using + libnl-xfrm-3. + +Package: libnl-3-200-dbg +Architecture: linux-any +Section: debug +Depends: libnl-3-200 (= ${binary:Version}), ${misc:Depends} +Priority: extra +Description: debug symbols for libnl3 + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + This package contains unstripped shared libraries. It is provided primarily + to provide a backtrace with names in a debugger, this makes it somewhat easier + to interpret core dumps. The libraries are installed in /usr/lib/debug and + are automatically used by gdb. + +Package: libnl-3-200-udeb +Architecture: linux-any +XC-Package-Type: udeb +Section: debian-installer +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: library for dealing with netlink sockets + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + This package is a udeb. It's only useful inside of debian-installer. + +Package: libnl-genl-3-200-udeb +Architecture: linux-any +XC-Package-Type: udeb +Section: debian-installer +Depends: libnl-3-200-udeb (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} +Description: library for dealing with netlink sockets - generic netlink + This is a library for applications dealing with netlink sockets. + The library provides an interface for raw netlink messaging and various + netlink family specific interfaces. + . + This package is a udeb. It's only useful inside of debian-installer. diff --git a/src/libnl3/debian/copyright b/src/libnl3/debian/copyright new file mode 100644 index 000000000000..07457363bf67 --- /dev/null +++ b/src/libnl3/debian/copyright @@ -0,0 +1,160 @@ +This package was debianized by Tamer Ahmed on +Tue, 31 Decn 2019 12:00:46 +0000. +The packaging is based on Heiko Stuebner's original packaging +of libnl1. + +It was downloaded from https://github.com/thom311/libnl/releases + +Upstream Author: + Thomas Graf + + +Copyright: + +lib/route/addr.c +include/netlink/route/addr.h + + Copyright (c) Thomas Graf + Baruch Even + + +lib/route/cls/u32.c +lib/route/cls/fw.c +lib/route/sch/htb.c +include/netlink/route/cls/fw.h +include/netlink/route/sch/htb.h + + Copyright (c) Thomas Graf + Copyright (c) Petr Gotthard + Copyright (c) Siemens AG Oesterreich + + + +lib/netfilter/log_msg.c +lib/netfilter/ct.c +include/netlink/netfilter/log_msg.h +include/netlink/netfilter/log.h +lib/netfilter/log_obj.c + + Copyright (c) Thomas Graf + Copyright (c) Philip Craig + Copyright (c) Patrick McHardy + Copyright (c) Secure Computing Corporation + + + +include/netlink/netfilter/queue_msg.h +lib/netfilter/queue_msg_obj.c +lib/netfilter/queue_msg.c +lib/netfilter/queue.c +lib/netfilter/netfilter.c +lib/netfilter/queue_obj.c +include/netlink/netfilter/netfilter.h +include/netlink/netfilter/queue.h +src/nf-queue.c + + Copyright (c) Patrick McHardy + + + +include/netlink/xfrm/selector.h +include/netlink/xfrm/sa.h +include/netlink/xfrm/ae.h +include/netlink/xfrm/sp.h +include/netlink/xfrm/template.h +include/netlink/xfrm/lifetime.h +lib/xfrm/sa.c +lib/xfrm/template.c +lib/xfrm/ae.c +lib/xfrm/sp.c +lib/xfrm/selector.c +lib/xfrm/lifetime.c + + Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + + +All other *.c and *.h files not mentioned above are copyright of: + + Copyright (c) 2003-2006 Thomas Graf + + +License: + +src/nl-addr-add.c +src/nl-addr-list.c +src/nl-cls-add.c +src/cls/utils.c +src/cls/cgroup.c +src/cls/utils.h +src/cls/basic.c +src/nl-addr-delete.c: + + This library 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. + +On Debian GNU/Linux systems, the complete text of the GNU General +Public License can be found in /usr/share/common-licenses/GPL-2 + + +include/netlink/xfrm/selector.h +include/netlink/xfrm/sa.h +include/netlink/xfrm/ae.h +include/netlink/xfrm/sp.h +include/netlink/xfrm/template.h +include/netlink/xfrm/lifetime.h +lib/xfrm/sa.c +lib/xfrm/template.c +lib/xfrm/ae.c +lib/xfrm/sp.c +lib/xfrm/selector.c +lib/xfrm/lifetime.c + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 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. + + Neither the name of Texas Instruments Incorporated nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + 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. + + +All other *.c and *.h files not mentioned above: + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation version 2.1 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. + +On Debian GNU/Linux systems, the complete text of the GNU Lesser General +Public License can be found in /usr/share/common-licenses/LGPL-2.1 + diff --git a/src/libnl3/debian/gbp.conf b/src/libnl3/debian/gbp.conf new file mode 100644 index 000000000000..a504bacc7748 --- /dev/null +++ b/src/libnl3/debian/gbp.conf @@ -0,0 +1,16 @@ +# Configuration file for git-buildpackage and friends + +[DEFAULT] +# the default build command: +#builder = debuild -i -I +# the default clean command: +#cleaner = debuild clean +# the default branch for upstream sources: +upstream-branch = upstream-dist +# the default branch for the debian patch: +#debian-branch = master +# the default tag formats used: +#upstream-tag = upstream/%(version)s +#debian-tag = debian/%(version)s +# use pristine-tar: +pristine-tar = true diff --git a/src/libnl3/debian/libnl-3-200-udeb.install b/src/libnl3/debian/libnl-3-200-udeb.install new file mode 100644 index 000000000000..4b3a77ce011d --- /dev/null +++ b/src/libnl3/debian/libnl-3-200-udeb.install @@ -0,0 +1 @@ +usr/lib/*/libnl-3.so.* lib diff --git a/src/libnl3/debian/libnl-3-200.install b/src/libnl3/debian/libnl-3-200.install new file mode 100755 index 000000000000..0a6aa3850b2c --- /dev/null +++ b/src/libnl3/debian/libnl-3-200.install @@ -0,0 +1,3 @@ +#!/usr/bin/dh-exec +debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/libnl-3*.so.* lib/${DEB_HOST_MULTIARCH}/ +debian/tmp/etc/libnl/* etc/libnl-3 diff --git a/src/libnl3/debian/libnl-3-200.symbols b/src/libnl3/debian/libnl-3-200.symbols new file mode 100644 index 000000000000..119e0554920f --- /dev/null +++ b/src/libnl3/debian/libnl-3-200.symbols @@ -0,0 +1,661 @@ +libnl-3.so.200 libnl-3-200 #MINVER# + __flags2str@Base 3.5.0-1 + __flags2str@libnl_3 3.5.0-1 + __list_str2type@Base 3.5.0-1 + __list_str2type@libnl_3 3.5.0-1 + __list_type2str@Base 3.5.0-1 + __list_type2str@libnl_3 3.5.0-1 + __nl_cache_mngt_require@Base 3.5.0-1 + __nl_cache_mngt_require@libnl_3 3.5.0-1 + __nl_cache_ops_lookup@Base 3.5.0-1 + __nl_read_num_str_file@Base 3.5.0-1 + __nl_read_num_str_file@libnl_3 3.5.0-1 + __str2flags@Base 3.5.0-1 + __str2flags@libnl_3 3.5.0-1 + __str2type@Base 3.5.0-1 + __str2type@libnl_3 3.5.0-1 + __trans_list_add@Base 3.5.0-1 + __trans_list_add@libnl_3 3.5.0-1 + __trans_list_clear@Base 3.5.0-1 + __trans_list_clear@libnl_3 3.5.0-1 + __type2str@Base 3.5.0-1 + __type2str@libnl_3 3.5.0-1 + _nl_socket_generate_local_port_no_release@Base 3.5.0-1 + _nl_socket_is_local_port_unspecified@Base 3.5.0-1 + _nl_socket_set_local_port_no_release@Base 3.5.0-1 + _nl_socket_used_ports_release_all@Base 3.5.0-1 + _nl_socket_used_ports_set@Base 3.5.0-1 + dump_from_ops@Base 3.5.0-1 + libnl_3@libnl_3 3.5.0-1 + libnl_3_2_26@libnl_3_2_26 3.5.0-1 + libnl_3_2_27@libnl_3_2_27 3.5.0-1 + libnl_3_2_28@libnl_3_2_28 3.5.0-1 + libnl_3_2_29@libnl_3_2_29 3.5.0-1 + libnl_3_5@libnl_3_5 3.5.0-1 + nl_addr2str@Base 3.5.0-1 + nl_addr2str@libnl_3 3.5.0-1 + nl_addr_alloc@Base 3.5.0-1 + nl_addr_alloc@libnl_3 3.5.0-1 + nl_addr_alloc_attr@Base 3.5.0-1 + nl_addr_alloc_attr@libnl_3 3.5.0-1 + nl_addr_build@Base 3.5.0-1 + nl_addr_build@libnl_3 3.5.0-1 + nl_addr_clone@Base 3.5.0-1 + nl_addr_clone@libnl_3 3.5.0-1 + nl_addr_cmp@Base 3.5.0-1 + nl_addr_cmp@libnl_3 3.5.0-1 + nl_addr_cmp_prefix@Base 3.5.0-1 + nl_addr_cmp_prefix@libnl_3 3.5.0-1 + nl_addr_fill_sockaddr@Base 3.5.0-1 + nl_addr_fill_sockaddr@libnl_3 3.5.0-1 + nl_addr_get@Base 3.5.0-1 + nl_addr_get@libnl_3 3.5.0-1 + nl_addr_get_binary_addr@Base 3.5.0-1 + nl_addr_get_binary_addr@libnl_3 3.5.0-1 + nl_addr_get_family@Base 3.5.0-1 + nl_addr_get_family@libnl_3 3.5.0-1 + nl_addr_get_len@Base 3.5.0-1 + nl_addr_get_len@libnl_3 3.5.0-1 + nl_addr_get_prefixlen@Base 3.5.0-1 + nl_addr_get_prefixlen@libnl_3 3.5.0-1 + nl_addr_guess_family@Base 3.5.0-1 + nl_addr_guess_family@libnl_3 3.5.0-1 + nl_addr_info@Base 3.5.0-1 + nl_addr_info@libnl_3 3.5.0-1 + nl_addr_iszero@Base 3.5.0-1 + nl_addr_iszero@libnl_3 3.5.0-1 + nl_addr_parse@Base 3.5.0-1 + nl_addr_parse@libnl_3 3.5.0-1 + nl_addr_put@Base 3.5.0-1 + nl_addr_put@libnl_3 3.5.0-1 + nl_addr_resolve@Base 3.5.0-1 + nl_addr_resolve@libnl_3 3.5.0-1 + nl_addr_set_binary_addr@Base 3.5.0-1 + nl_addr_set_binary_addr@libnl_3 3.5.0-1 + nl_addr_set_family@Base 3.5.0-1 + nl_addr_set_family@libnl_3 3.5.0-1 + nl_addr_set_prefixlen@Base 3.5.0-1 + nl_addr_set_prefixlen@libnl_3 3.5.0-1 + nl_addr_shared@Base 3.5.0-1 + nl_addr_shared@libnl_3 3.5.0-1 + nl_addr_valid@Base 3.5.0-1 + nl_addr_valid@libnl_3 3.5.0-1 + nl_af2str@Base 3.5.0-1 + nl_af2str@libnl_3 3.5.0-1 + nl_auto_complete@Base 3.5.0-1 + nl_auto_complete@libnl_3 3.5.0-1 + nl_cache_add@Base 3.5.0-1 + nl_cache_add@libnl_3 3.5.0-1 + nl_cache_alloc@Base 3.5.0-1 + nl_cache_alloc@libnl_3 3.5.0-1 + nl_cache_alloc_and_fill@Base 3.5.0-1 + nl_cache_alloc_and_fill@libnl_3 3.5.0-1 + nl_cache_alloc_name@Base 3.5.0-1 + nl_cache_alloc_name@libnl_3 3.5.0-1 + nl_cache_clear@Base 3.5.0-1 + nl_cache_clear@libnl_3 3.5.0-1 + nl_cache_clone@Base 3.5.0-1 + nl_cache_clone@libnl_3 3.5.0-1 + nl_cache_dump@Base 3.5.0-1 + nl_cache_dump@libnl_3 3.5.0-1 + nl_cache_dump_filter@Base 3.5.0-1 + nl_cache_dump_filter@libnl_3 3.5.0-1 + nl_cache_find@Base 3.5.0-1 + nl_cache_find@libnl_3 3.5.0-1 + nl_cache_foreach@Base 3.5.0-1 + nl_cache_foreach@libnl_3 3.5.0-1 + nl_cache_foreach_filter@Base 3.5.0-1 + nl_cache_foreach_filter@libnl_3 3.5.0-1 + nl_cache_free@Base 3.5.0-1 + nl_cache_free@libnl_3 3.5.0-1 + nl_cache_get@Base 3.5.0-1 + nl_cache_get@libnl_3 3.5.0-1 + nl_cache_get_first@Base 3.5.0-1 + nl_cache_get_first@libnl_3 3.5.0-1 + nl_cache_get_last@Base 3.5.0-1 + nl_cache_get_last@libnl_3 3.5.0-1 + nl_cache_get_next@Base 3.5.0-1 + nl_cache_get_next@libnl_3 3.5.0-1 + nl_cache_get_ops@Base 3.5.0-1 + nl_cache_get_ops@libnl_3 3.5.0-1 + nl_cache_get_prev@Base 3.5.0-1 + nl_cache_get_prev@libnl_3 3.5.0-1 + nl_cache_include@Base 3.5.0-1 + nl_cache_include@libnl_3 3.5.0-1 + nl_cache_include_v2@libnl_3_2_29 3.5.0-1 + nl_cache_is_empty@Base 3.5.0-1 + nl_cache_is_empty@libnl_3 3.5.0-1 + nl_cache_mark_all@Base 3.5.0-1 + nl_cache_mark_all@libnl_3 3.5.0-1 + nl_cache_mngr_add@Base 3.5.0-1 + nl_cache_mngr_add@libnl_3 3.5.0-1 + nl_cache_mngr_add_cache@Base 3.5.0-1 + nl_cache_mngr_add_cache@libnl_3 3.5.0-1 + nl_cache_mngr_add_cache_v2@libnl_3_2_29 3.5.0-1 + nl_cache_mngr_alloc@Base 3.5.0-1 + nl_cache_mngr_alloc@libnl_3 3.5.0-1 + nl_cache_mngr_data_ready@Base 3.5.0-1 + nl_cache_mngr_data_ready@libnl_3 3.5.0-1 + nl_cache_mngr_free@Base 3.5.0-1 + nl_cache_mngr_free@libnl_3 3.5.0-1 + nl_cache_mngr_get_fd@Base 3.5.0-1 + nl_cache_mngr_get_fd@libnl_3 3.5.0-1 + nl_cache_mngr_info@Base 3.5.0-1 + nl_cache_mngr_info@libnl_3 3.5.0-1 + nl_cache_mngr_poll@Base 3.5.0-1 + nl_cache_mngr_poll@libnl_3 3.5.0-1 + nl_cache_mngt_provide@Base 3.5.0-1 + nl_cache_mngt_provide@libnl_3 3.5.0-1 + nl_cache_mngt_register@Base 3.5.0-1 + nl_cache_mngt_register@libnl_3 3.5.0-1 + nl_cache_mngt_require@Base 3.5.0-1 + nl_cache_mngt_require@libnl_3 3.5.0-1 + nl_cache_mngt_require_safe@Base 3.5.0-1 + nl_cache_mngt_require_safe@libnl_3 3.5.0-1 + nl_cache_mngt_unprovide@Base 3.5.0-1 + nl_cache_mngt_unprovide@libnl_3 3.5.0-1 + nl_cache_mngt_unregister@Base 3.5.0-1 + nl_cache_mngt_unregister@libnl_3 3.5.0-1 + nl_cache_move@Base 3.5.0-1 + nl_cache_move@libnl_3 3.5.0-1 + nl_cache_nitems@Base 3.5.0-1 + nl_cache_nitems@libnl_3 3.5.0-1 + nl_cache_nitems_filter@Base 3.5.0-1 + nl_cache_nitems_filter@libnl_3 3.5.0-1 + nl_cache_ops_associate@Base 3.5.0-1 + nl_cache_ops_associate@libnl_3 3.5.0-1 + nl_cache_ops_associate_safe@Base 3.5.0-1 + nl_cache_ops_associate_safe@libnl_3 3.5.0-1 + nl_cache_ops_foreach@Base 3.5.0-1 + nl_cache_ops_foreach@libnl_3 3.5.0-1 + nl_cache_ops_get@Base 3.5.0-1 + nl_cache_ops_get@libnl_3 3.5.0-1 + nl_cache_ops_lookup@Base 3.5.0-1 + nl_cache_ops_lookup@libnl_3 3.5.0-1 + nl_cache_ops_lookup_safe@Base 3.5.0-1 + nl_cache_ops_lookup_safe@libnl_3 3.5.0-1 + nl_cache_ops_put@Base 3.5.0-1 + nl_cache_ops_put@libnl_3 3.5.0-1 + nl_cache_ops_set_flags@Base 3.5.0-1 + nl_cache_ops_set_flags@libnl_3 3.5.0-1 + nl_cache_parse@Base 3.5.0-1 + nl_cache_parse@libnl_3 3.5.0-1 + nl_cache_parse_and_add@Base 3.5.0-1 + nl_cache_parse_and_add@libnl_3 3.5.0-1 + nl_cache_pickup@Base 3.5.0-1 + nl_cache_pickup@libnl_3 3.5.0-1 + nl_cache_pickup_checkdup@Base 3.5.0-1 + nl_cache_pickup_checkdup@libnl_3 3.5.0-1 + nl_cache_put@Base 3.5.0-1 + nl_cache_put@libnl_3 3.5.0-1 + nl_cache_refill@Base 3.5.0-1 + nl_cache_refill@libnl_3 3.5.0-1 + nl_cache_remove@Base 3.5.0-1 + nl_cache_remove@libnl_3 3.5.0-1 + nl_cache_resync@Base 3.5.0-1 + nl_cache_resync@libnl_3 3.5.0-1 + nl_cache_search@Base 3.5.0-1 + nl_cache_search@libnl_3 3.5.0-1 + nl_cache_set_arg1@Base 3.5.0-1 + nl_cache_set_arg1@libnl_3 3.5.0-1 + nl_cache_set_arg2@Base 3.5.0-1 + nl_cache_set_arg2@libnl_3 3.5.0-1 + nl_cache_set_flags@Base 3.5.0-1 + nl_cache_set_flags@libnl_3 3.5.0-1 + nl_cache_subset@Base 3.5.0-1 + nl_cache_subset@libnl_3 3.5.0-1 + nl_cancel_down_bits@Base 3.5.0-1 + nl_cancel_down_bits@libnl_3 3.5.0-1 + nl_cancel_down_bytes@Base 3.5.0-1 + nl_cancel_down_bytes@libnl_3 3.5.0-1 + nl_cancel_down_us@Base 3.5.0-1 + nl_cancel_down_us@libnl_3 3.5.0-1 + nl_cb_active_type@Base 3.5.0-1 + nl_cb_active_type@libnl_3 3.5.0-1 + nl_cb_alloc@Base 3.5.0-1 + nl_cb_alloc@libnl_3 3.5.0-1 + nl_cb_clone@Base 3.5.0-1 + nl_cb_clone@libnl_3 3.5.0-1 + nl_cb_err@Base 3.5.0-1 + nl_cb_err@libnl_3 3.5.0-1 + nl_cb_get@Base 3.5.0-1 + nl_cb_get@libnl_3 3.5.0-1 + nl_cb_overwrite_recv@Base 3.5.0-1 + nl_cb_overwrite_recv@libnl_3 3.5.0-1 + nl_cb_overwrite_recvmsgs@Base 3.5.0-1 + nl_cb_overwrite_recvmsgs@libnl_3 3.5.0-1 + nl_cb_overwrite_send@Base 3.5.0-1 + nl_cb_overwrite_send@libnl_3 3.5.0-1 + nl_cb_put@Base 3.5.0-1 + nl_cb_put@libnl_3 3.5.0-1 + nl_cb_set@Base 3.5.0-1 + nl_cb_set@libnl_3 3.5.0-1 + nl_cb_set_all@Base 3.5.0-1 + nl_cb_set_all@libnl_3 3.5.0-1 + nl_close@Base 3.5.0-1 + nl_close@libnl_3 3.5.0-1 + nl_complete_msg@Base 3.5.0-1 + nl_complete_msg@libnl_3 3.5.0-1 + nl_connect@Base 3.5.0-1 + nl_connect@libnl_3 3.5.0-1 + nl_data_alloc@Base 3.5.0-1 + nl_data_alloc@libnl_3 3.5.0-1 + nl_data_alloc_attr@Base 3.5.0-1 + nl_data_alloc_attr@libnl_3 3.5.0-1 + nl_data_append@Base 3.5.0-1 + nl_data_append@libnl_3 3.5.0-1 + nl_data_clone@Base 3.5.0-1 + nl_data_clone@libnl_3 3.5.0-1 + nl_data_cmp@Base 3.5.0-1 + nl_data_cmp@libnl_3 3.5.0-1 + nl_data_free@Base 3.5.0-1 + nl_data_free@libnl_3 3.5.0-1 + nl_data_get@Base 3.5.0-1 + nl_data_get@libnl_3 3.5.0-1 + nl_data_get_size@Base 3.5.0-1 + nl_data_get_size@libnl_3 3.5.0-1 + nl_debug@Base 3.5.0-1 + nl_debug@libnl_3 3.5.0-1 + nl_debug_dp@Base 3.5.0-1 + nl_debug_dp@libnl_3 3.5.0-1 + nl_dump@Base 3.5.0-1 + nl_dump@libnl_3 3.5.0-1 + nl_dump_line@Base 3.5.0-1 + nl_dump_line@libnl_3 3.5.0-1 + nl_ether_proto2str@Base 3.5.0-1 + nl_ether_proto2str@libnl_3 3.5.0-1 + nl_get_psched_hz@Base 3.5.0-1 + nl_get_psched_hz@libnl_3 3.5.0-1 + nl_get_user_hz@Base 3.5.0-1 + nl_get_user_hz@libnl_3 3.5.0-1 + nl_geterror@Base 3.5.0-1 + nl_geterror@libnl_3 3.5.0-1 + nl_has_capability@Base 3.5.0-1 + nl_has_capability@libnl_3 3.5.0-1 + nl_hash@Base 3.5.0-1 + nl_hash@libnl_3 3.5.0-1 + nl_hash_any@Base 3.5.0-1 + nl_hash_any@libnl_3 3.5.0-1 + nl_hash_table_add@Base 3.5.0-1 + nl_hash_table_add@libnl_3 3.5.0-1 + nl_hash_table_alloc@Base 3.5.0-1 + nl_hash_table_alloc@libnl_3 3.5.0-1 + nl_hash_table_del@Base 3.5.0-1 + nl_hash_table_del@libnl_3 3.5.0-1 + nl_hash_table_free@Base 3.5.0-1 + nl_hash_table_free@libnl_3 3.5.0-1 + nl_hash_table_lookup@Base 3.5.0-1 + nl_hash_table_lookup@libnl_3 3.5.0-1 + nl_ip_proto2str@Base 3.5.0-1 + nl_ip_proto2str@libnl_3 3.5.0-1 + nl_join_groups@Base 3.5.0-1 + nl_join_groups@libnl_3 3.5.0-1 + nl_llproto2str@Base 3.5.0-1 + nl_llproto2str@libnl_3 3.5.0-1 + nl_msec2str@Base 3.5.0-1 + nl_msec2str@libnl_3 3.5.0-1 + nl_msg_dump@Base 3.5.0-1 + nl_msg_dump@libnl_3 3.5.0-1 + nl_msg_parse@Base 3.5.0-1 + nl_msg_parse@libnl_3 3.5.0-1 + nl_msgtype_lookup@Base 3.5.0-1 + nl_msgtype_lookup@libnl_3 3.5.0-1 + nl_new_line@Base 3.5.0-1 + nl_new_line@libnl_3 3.5.0-1 + nl_nlfamily2str@Base 3.5.0-1 + nl_nlfamily2str@libnl_3 3.5.0-1 + nl_nlmsg_flags2str@Base 3.5.0-1 + nl_nlmsg_flags2str@libnl_3 3.5.0-1 + nl_nlmsgtype2str@Base 3.5.0-1 + nl_nlmsgtype2str@libnl_3 3.5.0-1 + nl_object_alloc@Base 3.5.0-1 + nl_object_alloc@libnl_3 3.5.0-1 + nl_object_alloc_name@Base 3.5.0-1 + nl_object_alloc_name@libnl_3 3.5.0-1 + nl_object_attr_list@Base 3.5.0-1 + nl_object_attr_list@libnl_3 3.5.0-1 + nl_object_attrs2str@Base 3.5.0-1 + nl_object_attrs2str@libnl_3 3.5.0-1 + nl_object_clone@Base 3.5.0-1 + nl_object_clone@libnl_3 3.5.0-1 + nl_object_diff64@libnl_3_2_28 3.5.0-1 + nl_object_diff@Base 3.5.0-1 + nl_object_diff@libnl_3 3.5.0-1 + nl_object_dump@Base 3.5.0-1 + nl_object_dump@libnl_3 3.5.0-1 + nl_object_dump_buf@Base 3.5.0-1 + nl_object_dump_buf@libnl_3 3.5.0-1 + nl_object_free@Base 3.5.0-1 + nl_object_free@libnl_3 3.5.0-1 + nl_object_get@Base 3.5.0-1 + nl_object_get@libnl_3 3.5.0-1 + nl_object_get_cache@Base 3.5.0-1 + nl_object_get_cache@libnl_3 3.5.0-1 + nl_object_get_id_attrs@Base 3.5.0-1 + nl_object_get_id_attrs@libnl_3 3.5.0-1 + nl_object_get_msgtype@Base 3.5.0-1 + nl_object_get_msgtype@libnl_3 3.5.0-1 + nl_object_get_ops@Base 3.5.0-1 + nl_object_get_ops@libnl_3 3.5.0-1 + nl_object_get_refcnt@Base 3.5.0-1 + nl_object_get_refcnt@libnl_3 3.5.0-1 + nl_object_get_type@Base 3.5.0-1 + nl_object_get_type@libnl_3 3.5.0-1 + nl_object_identical@Base 3.5.0-1 + nl_object_identical@libnl_3 3.5.0-1 + nl_object_is_marked@Base 3.5.0-1 + nl_object_is_marked@libnl_3 3.5.0-1 + nl_object_keygen@Base 3.5.0-1 + nl_object_keygen@libnl_3 3.5.0-1 + nl_object_mark@Base 3.5.0-1 + nl_object_mark@libnl_3 3.5.0-1 + nl_object_match_filter@Base 3.5.0-1 + nl_object_match_filter@libnl_3 3.5.0-1 + nl_object_put@Base 3.5.0-1 + nl_object_put@libnl_3 3.5.0-1 + nl_object_shared@Base 3.5.0-1 + nl_object_shared@libnl_3 3.5.0-1 + nl_object_unmark@Base 3.5.0-1 + nl_object_unmark@libnl_3 3.5.0-1 + nl_object_update@Base 3.5.0-1 + nl_object_update@libnl_3 3.5.0-1 + nl_perror@Base 3.5.0-1 + nl_perror@libnl_3 3.5.0-1 + nl_pickup@Base 3.5.0-1 + nl_pickup@libnl_3 3.5.0-1 + nl_pickup_keep_syserr@Base 3.5.0-1 + nl_pickup_keep_syserr@libnl_3 3.5.0-1 + nl_prob2int@Base 3.5.0-1 + nl_prob2int@libnl_3 3.5.0-1 + nl_rate2str@Base 3.5.0-1 + nl_rate2str@libnl_3 3.5.0-1 + nl_recv@Base 3.5.0-1 + nl_recv@libnl_3 3.5.0-1 + nl_recvmsgs@Base 3.5.0-1 + nl_recvmsgs@libnl_3 3.5.0-1 + nl_recvmsgs_default@Base 3.5.0-1 + nl_recvmsgs_default@libnl_3 3.5.0-1 + nl_recvmsgs_report@Base 3.5.0-1 + nl_recvmsgs_report@libnl_3 3.5.0-1 + nl_send@Base 3.5.0-1 + nl_send@libnl_3 3.5.0-1 + nl_send_auto@Base 3.5.0-1 + nl_send_auto@libnl_3 3.5.0-1 + nl_send_auto_complete@Base 3.5.0-1 + nl_send_auto_complete@libnl_3 3.5.0-1 + nl_send_iovec@Base 3.5.0-1 + nl_send_iovec@libnl_3 3.5.0-1 + nl_send_simple@Base 3.5.0-1 + nl_send_simple@libnl_3 3.5.0-1 + nl_send_sync@Base 3.5.0-1 + nl_send_sync@libnl_3 3.5.0-1 + nl_sendmsg@Base 3.5.0-1 + nl_sendmsg@libnl_3 3.5.0-1 + nl_sendto@Base 3.5.0-1 + nl_sendto@libnl_3 3.5.0-1 + nl_size2int@Base 3.5.0-1 + nl_size2int@libnl_3 3.5.0-1 + nl_size2str@Base 3.5.0-1 + nl_size2str@libnl_3 3.5.0-1 + nl_socket_add_membership@Base 3.5.0-1 + nl_socket_add_membership@libnl_3 3.5.0-1 + nl_socket_add_memberships@Base 3.5.0-1 + nl_socket_add_memberships@libnl_3 3.5.0-1 + nl_socket_alloc@Base 3.5.0-1 + nl_socket_alloc@libnl_3 3.5.0-1 + nl_socket_alloc_cb@Base 3.5.0-1 + nl_socket_alloc_cb@libnl_3 3.5.0-1 + nl_socket_disable_auto_ack@Base 3.5.0-1 + nl_socket_disable_auto_ack@libnl_3 3.5.0-1 + nl_socket_disable_msg_peek@Base 3.5.0-1 + nl_socket_disable_msg_peek@libnl_3 3.5.0-1 + nl_socket_disable_seq_check@Base 3.5.0-1 + nl_socket_disable_seq_check@libnl_3 3.5.0-1 + nl_socket_drop_membership@Base 3.5.0-1 + nl_socket_drop_membership@libnl_3 3.5.0-1 + nl_socket_drop_memberships@Base 3.5.0-1 + nl_socket_drop_memberships@libnl_3 3.5.0-1 + nl_socket_enable_auto_ack@Base 3.5.0-1 + nl_socket_enable_auto_ack@libnl_3 3.5.0-1 + nl_socket_enable_msg_peek@Base 3.5.0-1 + nl_socket_enable_msg_peek@libnl_3 3.5.0-1 + nl_socket_free@Base 3.5.0-1 + nl_socket_free@libnl_3 3.5.0-1 + nl_socket_get_cb@Base 3.5.0-1 + nl_socket_get_cb@libnl_3 3.5.0-1 + nl_socket_get_fd@Base 3.5.0-1 + nl_socket_get_fd@libnl_3 3.5.0-1 + nl_socket_get_local_port@Base 3.5.0-1 + nl_socket_get_local_port@libnl_3 3.5.0-1 + nl_socket_get_msg_buf_size@Base 3.5.0-1 + nl_socket_get_msg_buf_size@libnl_3 3.5.0-1 + nl_socket_get_peer_groups@Base 3.5.0-1 + nl_socket_get_peer_groups@libnl_3 3.5.0-1 + nl_socket_get_peer_port@Base 3.5.0-1 + nl_socket_get_peer_port@libnl_3 3.5.0-1 + nl_socket_modify_cb@Base 3.5.0-1 + nl_socket_modify_cb@libnl_3 3.5.0-1 + nl_socket_modify_err_cb@Base 3.5.0-1 + nl_socket_modify_err_cb@libnl_3 3.5.0-1 + nl_socket_recv_pktinfo@Base 3.5.0-1 + nl_socket_recv_pktinfo@libnl_3 3.5.0-1 + nl_socket_set_buffer_size@Base 3.5.0-1 + nl_socket_set_buffer_size@libnl_3 3.5.0-1 + nl_socket_set_cb@Base 3.5.0-1 + nl_socket_set_cb@libnl_3 3.5.0-1 + nl_socket_set_fd@Base 3.5.0-1 + nl_socket_set_fd@libnl_3_2_26 3.5.0-1 + nl_socket_set_local_port@Base 3.5.0-1 + nl_socket_set_local_port@libnl_3 3.5.0-1 + nl_socket_set_msg_buf_size@Base 3.5.0-1 + nl_socket_set_msg_buf_size@libnl_3 3.5.0-1 + nl_socket_set_nonblocking@Base 3.5.0-1 + nl_socket_set_nonblocking@libnl_3 3.5.0-1 + nl_socket_set_passcred@Base 3.5.0-1 + nl_socket_set_passcred@libnl_3 3.5.0-1 + nl_socket_set_peer_groups@Base 3.5.0-1 + nl_socket_set_peer_groups@libnl_3 3.5.0-1 + nl_socket_set_peer_port@Base 3.5.0-1 + nl_socket_set_peer_port@libnl_3 3.5.0-1 + nl_socket_use_seq@Base 3.5.0-1 + nl_socket_use_seq@libnl_3 3.5.0-1 + nl_str2af@Base 3.5.0-1 + nl_str2af@libnl_3 3.5.0-1 + nl_str2ether_proto@Base 3.5.0-1 + nl_str2ether_proto@libnl_3 3.5.0-1 + nl_str2ip_proto@Base 3.5.0-1 + nl_str2ip_proto@libnl_3 3.5.0-1 + nl_str2llproto@Base 3.5.0-1 + nl_str2llproto@libnl_3 3.5.0-1 + nl_str2msec@Base 3.5.0-1 + nl_str2msec@libnl_3 3.5.0-1 + nl_str2nlfamily@Base 3.5.0-1 + nl_str2nlfamily@libnl_3 3.5.0-1 + nl_str2nlmsgtype@Base 3.5.0-1 + nl_str2nlmsgtype@libnl_3 3.5.0-1 + nl_strerror_l@libnl_3_2_29 3.5.0-1 + nl_syserr2nlerr@Base 3.5.0-1 + nl_syserr2nlerr@libnl_3 3.5.0-1 + nl_ticks2us@Base 3.5.0-1 + nl_ticks2us@libnl_3 3.5.0-1 + nl_us2ticks@Base 3.5.0-1 + nl_us2ticks@libnl_3 3.5.0-1 + nl_ver_maj@Base 3.5.0-1 + nl_ver_maj@libnl_3 3.5.0-1 + nl_ver_mic@Base 3.5.0-1 + nl_ver_mic@libnl_3 3.5.0-1 + nl_ver_min@Base 3.5.0-1 + nl_ver_min@libnl_3 3.5.0-1 + nl_ver_num@Base 3.5.0-1 + nl_ver_num@libnl_3 3.5.0-1 + nl_wait_for_ack@Base 3.5.0-1 + nl_wait_for_ack@libnl_3 3.5.0-1 + nla_attr_size@Base 3.5.0-1 + nla_attr_size@libnl_3 3.5.0-1 + nla_data@Base 3.5.0-1 + nla_data@libnl_3 3.5.0-1 + nla_find@Base 3.5.0-1 + nla_find@libnl_3 3.5.0-1 + nla_get_flag@Base 3.5.0-1 + nla_get_flag@libnl_3 3.5.0-1 + nla_get_msecs@Base 3.5.0-1 + nla_get_msecs@libnl_3 3.5.0-1 + nla_get_s16@Base 3.5.0-1 + nla_get_s16@libnl_3_2_27 3.5.0-1 + nla_get_s32@Base 3.5.0-1 + nla_get_s32@libnl_3_2_27 3.5.0-1 + nla_get_s64@Base 3.5.0-1 + nla_get_s64@libnl_3_2_27 3.5.0-1 + nla_get_s8@Base 3.5.0-1 + nla_get_s8@libnl_3_2_27 3.5.0-1 + nla_get_string@Base 3.5.0-1 + nla_get_string@libnl_3 3.5.0-1 + nla_get_u16@Base 3.5.0-1 + nla_get_u16@libnl_3 3.5.0-1 + nla_get_u32@Base 3.5.0-1 + nla_get_u32@libnl_3 3.5.0-1 + nla_get_u64@Base 3.5.0-1 + nla_get_u64@libnl_3 3.5.0-1 + nla_get_u8@Base 3.5.0-1 + nla_get_u8@libnl_3 3.5.0-1 + nla_is_nested@Base 3.5.0-1 + nla_is_nested@libnl_3 3.5.0-1 + nla_len@Base 3.5.0-1 + nla_len@libnl_3 3.5.0-1 + nla_memcmp@Base 3.5.0-1 + nla_memcmp@libnl_3 3.5.0-1 + nla_memcpy@Base 3.5.0-1 + nla_memcpy@libnl_3 3.5.0-1 + nla_nest_cancel@Base 3.5.0-1 + nla_nest_cancel@libnl_3 3.5.0-1 + nla_nest_end@Base 3.5.0-1 + nla_nest_end@libnl_3 3.5.0-1 + nla_nest_end_keep_empty@libnl_3_5 3.5.0-1 + nla_nest_start@Base 3.5.0-1 + nla_nest_start@libnl_3 3.5.0-1 + nla_next@Base 3.5.0-1 + nla_next@libnl_3 3.5.0-1 + nla_ok@Base 3.5.0-1 + nla_ok@libnl_3 3.5.0-1 + nla_padlen@Base 3.5.0-1 + nla_padlen@libnl_3 3.5.0-1 + nla_parse@Base 3.5.0-1 + nla_parse@libnl_3 3.5.0-1 + nla_parse_nested@Base 3.5.0-1 + nla_parse_nested@libnl_3 3.5.0-1 + nla_put@Base 3.5.0-1 + nla_put@libnl_3 3.5.0-1 + nla_put_addr@Base 3.5.0-1 + nla_put_addr@libnl_3 3.5.0-1 + nla_put_data@Base 3.5.0-1 + nla_put_data@libnl_3 3.5.0-1 + nla_put_flag@Base 3.5.0-1 + nla_put_flag@libnl_3 3.5.0-1 + nla_put_msecs@Base 3.5.0-1 + nla_put_msecs@libnl_3 3.5.0-1 + nla_put_nested@Base 3.5.0-1 + nla_put_nested@libnl_3 3.5.0-1 + nla_put_s16@Base 3.5.0-1 + nla_put_s16@libnl_3_2_27 3.5.0-1 + nla_put_s32@Base 3.5.0-1 + nla_put_s32@libnl_3_2_27 3.5.0-1 + nla_put_s64@Base 3.5.0-1 + nla_put_s64@libnl_3_2_27 3.5.0-1 + nla_put_s8@Base 3.5.0-1 + nla_put_s8@libnl_3_2_27 3.5.0-1 + nla_put_string@Base 3.5.0-1 + nla_put_string@libnl_3 3.5.0-1 + nla_put_u16@Base 3.5.0-1 + nla_put_u16@libnl_3 3.5.0-1 + nla_put_u32@Base 3.5.0-1 + nla_put_u32@libnl_3 3.5.0-1 + nla_put_u64@Base 3.5.0-1 + nla_put_u64@libnl_3 3.5.0-1 + nla_put_u8@Base 3.5.0-1 + nla_put_u8@libnl_3 3.5.0-1 + nla_reserve@Base 3.5.0-1 + nla_reserve@libnl_3 3.5.0-1 + nla_strcmp@Base 3.5.0-1 + nla_strcmp@libnl_3 3.5.0-1 + nla_strdup@Base 3.5.0-1 + nla_strdup@libnl_3 3.5.0-1 + nla_strlcpy@Base 3.5.0-1 + nla_strlcpy@libnl_3 3.5.0-1 + nla_total_size@Base 3.5.0-1 + nla_total_size@libnl_3 3.5.0-1 + nla_type@Base 3.5.0-1 + nla_type@libnl_3 3.5.0-1 + nla_validate@Base 3.5.0-1 + nla_validate@libnl_3 3.5.0-1 + nlmsg_alloc@Base 3.5.0-1 + nlmsg_alloc@libnl_3 3.5.0-1 + nlmsg_alloc_simple@Base 3.5.0-1 + nlmsg_alloc_simple@libnl_3 3.5.0-1 + nlmsg_alloc_size@Base 3.5.0-1 + nlmsg_alloc_size@libnl_3 3.5.0-1 + nlmsg_append@Base 3.5.0-1 + nlmsg_append@libnl_3 3.5.0-1 + nlmsg_attrdata@Base 3.5.0-1 + nlmsg_attrdata@libnl_3 3.5.0-1 + nlmsg_attrlen@Base 3.5.0-1 + nlmsg_attrlen@libnl_3 3.5.0-1 + nlmsg_convert@Base 3.5.0-1 + nlmsg_convert@libnl_3 3.5.0-1 + nlmsg_data@Base 3.5.0-1 + nlmsg_data@libnl_3 3.5.0-1 + nlmsg_datalen@Base 3.5.0-1 + nlmsg_datalen@libnl_3 3.5.0-1 + nlmsg_expand@Base 3.5.0-1 + nlmsg_expand@libnl_3 3.5.0-1 + nlmsg_find_attr@Base 3.5.0-1 + nlmsg_find_attr@libnl_3 3.5.0-1 + nlmsg_free@Base 3.5.0-1 + nlmsg_free@libnl_3 3.5.0-1 + nlmsg_get@Base 3.5.0-1 + nlmsg_get@libnl_3 3.5.0-1 + nlmsg_get_creds@Base 3.5.0-1 + nlmsg_get_creds@libnl_3 3.5.0-1 + nlmsg_get_dst@Base 3.5.0-1 + nlmsg_get_dst@libnl_3 3.5.0-1 + nlmsg_get_max_size@Base 3.5.0-1 + nlmsg_get_max_size@libnl_3 3.5.0-1 + nlmsg_get_proto@Base 3.5.0-1 + nlmsg_get_proto@libnl_3 3.5.0-1 + nlmsg_get_src@Base 3.5.0-1 + nlmsg_get_src@libnl_3 3.5.0-1 + nlmsg_hdr@Base 3.5.0-1 + nlmsg_hdr@libnl_3 3.5.0-1 + nlmsg_inherit@Base 3.5.0-1 + nlmsg_inherit@libnl_3 3.5.0-1 + nlmsg_next@Base 3.5.0-1 + nlmsg_next@libnl_3 3.5.0-1 + nlmsg_ok@Base 3.5.0-1 + nlmsg_ok@libnl_3 3.5.0-1 + nlmsg_padlen@Base 3.5.0-1 + nlmsg_padlen@libnl_3 3.5.0-1 + nlmsg_parse@Base 3.5.0-1 + nlmsg_parse@libnl_3 3.5.0-1 + nlmsg_put@Base 3.5.0-1 + nlmsg_put@libnl_3 3.5.0-1 + nlmsg_reserve@Base 3.5.0-1 + nlmsg_reserve@libnl_3 3.5.0-1 + nlmsg_set_creds@Base 3.5.0-1 + nlmsg_set_creds@libnl_3 3.5.0-1 + nlmsg_set_default_size@Base 3.5.0-1 + nlmsg_set_default_size@libnl_3 3.5.0-1 + nlmsg_set_dst@Base 3.5.0-1 + nlmsg_set_dst@libnl_3 3.5.0-1 + nlmsg_set_proto@Base 3.5.0-1 + nlmsg_set_proto@libnl_3 3.5.0-1 + nlmsg_set_src@Base 3.5.0-1 + nlmsg_set_src@libnl_3 3.5.0-1 + nlmsg_size@Base 3.5.0-1 + nlmsg_size@libnl_3 3.5.0-1 + nlmsg_tail@Base 3.5.0-1 + nlmsg_tail@libnl_3 3.5.0-1 + nlmsg_total_size@Base 3.5.0-1 + nlmsg_total_size@libnl_3 3.5.0-1 + nlmsg_valid_hdr@Base 3.5.0-1 + nlmsg_valid_hdr@libnl_3 3.5.0-1 + nlmsg_validate@Base 3.5.0-1 + nlmsg_validate@libnl_3 3.5.0-1 diff --git a/src/libnl3/debian/libnl-3-dev.install b/src/libnl3/debian/libnl-3-dev.install new file mode 100755 index 000000000000..3715b8b22bbd --- /dev/null +++ b/src/libnl3/debian/libnl-3-dev.install @@ -0,0 +1,5 @@ +#!/usr/bin/dh-exec +debian/tmp/usr/include/* +debian/tmp/usr/lib/*/pkgconfig/libnl-3* +debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/libnl-3.so lib/${DEB_HOST_MULTIARCH}/ +debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/libnl-3.a lib/${DEB_HOST_MULTIARCH}/ diff --git a/src/libnl3/debian/libnl-cli-3-200.install b/src/libnl3/debian/libnl-cli-3-200.install new file mode 100755 index 000000000000..6735ec9d14b1 --- /dev/null +++ b/src/libnl3/debian/libnl-cli-3-200.install @@ -0,0 +1,4 @@ +#!/usr/bin/dh-exec +debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/libnl-cli-3*.so.* +debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/libnl/cli/cls/*.so usr/lib/${DEB_HOST_MULTIARCH}/libnl-3/cli/cls +debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/libnl/cli/qdisc/*.so usr/lib/${DEB_HOST_MULTIARCH}/libnl-3/cli/qdisc diff --git a/src/libnl3/debian/libnl-cli-3-200.symbols b/src/libnl3/debian/libnl-cli-3-200.symbols new file mode 100644 index 000000000000..2d21c139623c --- /dev/null +++ b/src/libnl3/debian/libnl-cli-3-200.symbols @@ -0,0 +1,226 @@ +basic.so libnl-cli-3-200 #MINVER# +bfifo.so libnl-cli-3-200 #MINVER# +blackhole.so libnl-cli-3-200 #MINVER# +cgroup.so libnl-cli-3-200 #MINVER# +fq_codel.so libnl-cli-3-200 #MINVER# +hfsc.so libnl-cli-3-200 #MINVER# +htb.so libnl-cli-3-200 #MINVER# +ingress.so libnl-cli-3-200 #MINVER# +libnl-cli-3.so.200 libnl-cli-3-200 #MINVER# + libnl_3@libnl_3 3.5.0-1 + libnl_3_2_28@libnl_3_2_28 3.5.0-1 + nl_cli_addr_alloc@Base 3.5.0-1 + nl_cli_addr_alloc@libnl_3 3.5.0-1 + nl_cli_addr_parse@Base 3.5.0-1 + nl_cli_addr_parse@libnl_3 3.5.0-1 + nl_cli_addr_parse_broadcast@Base 3.5.0-1 + nl_cli_addr_parse_broadcast@libnl_3 3.5.0-1 + nl_cli_addr_parse_dev@Base 3.5.0-1 + nl_cli_addr_parse_dev@libnl_3 3.5.0-1 + nl_cli_addr_parse_family@Base 3.5.0-1 + nl_cli_addr_parse_family@libnl_3 3.5.0-1 + nl_cli_addr_parse_label@Base 3.5.0-1 + nl_cli_addr_parse_label@libnl_3 3.5.0-1 + nl_cli_addr_parse_local@Base 3.5.0-1 + nl_cli_addr_parse_local@libnl_3 3.5.0-1 + nl_cli_addr_parse_peer@Base 3.5.0-1 + nl_cli_addr_parse_peer@libnl_3 3.5.0-1 + nl_cli_addr_parse_preferred@Base 3.5.0-1 + nl_cli_addr_parse_preferred@libnl_3 3.5.0-1 + nl_cli_addr_parse_scope@Base 3.5.0-1 + nl_cli_addr_parse_scope@libnl_3 3.5.0-1 + nl_cli_addr_parse_valid@Base 3.5.0-1 + nl_cli_addr_parse_valid@libnl_3 3.5.0-1 + nl_cli_alloc_cache@Base 3.5.0-1 + nl_cli_alloc_cache@libnl_3 3.5.0-1 + nl_cli_alloc_cache_flags@libnl_3_2_28 3.5.0-1 + nl_cli_alloc_socket@Base 3.5.0-1 + nl_cli_alloc_socket@libnl_3 3.5.0-1 + nl_cli_class_alloc@Base 3.5.0-1 + nl_cli_class_alloc@libnl_3 3.5.0-1 + nl_cli_class_alloc_cache@Base 3.5.0-1 + nl_cli_class_alloc_cache@libnl_3 3.5.0-1 + nl_cli_cls_alloc@Base 3.5.0-1 + nl_cli_cls_alloc@libnl_3 3.5.0-1 + nl_cli_cls_alloc_cache@Base 3.5.0-1 + nl_cli_cls_alloc_cache@libnl_3 3.5.0-1 + nl_cli_cls_parse_ematch@Base 3.5.0-1 + nl_cli_cls_parse_ematch@libnl_3 3.5.0-1 + nl_cli_cls_parse_proto@Base 3.5.0-1 + nl_cli_cls_parse_proto@libnl_3 3.5.0-1 + nl_cli_confirm@Base 3.5.0-1 + nl_cli_confirm@libnl_3 3.5.0-1 + nl_cli_connect@Base 3.5.0-1 + nl_cli_connect@libnl_3 3.5.0-1 + nl_cli_ct_alloc@Base 3.5.0-1 + nl_cli_ct_alloc@libnl_3 3.5.0-1 + nl_cli_ct_alloc_cache@Base 3.5.0-1 + nl_cli_ct_alloc_cache@libnl_3 3.5.0-1 + nl_cli_ct_parse_dst@Base 3.5.0-1 + nl_cli_ct_parse_dst@libnl_3 3.5.0-1 + nl_cli_ct_parse_dst_port@Base 3.5.0-1 + nl_cli_ct_parse_dst_port@libnl_3 3.5.0-1 + nl_cli_ct_parse_family@Base 3.5.0-1 + nl_cli_ct_parse_family@libnl_3 3.5.0-1 + nl_cli_ct_parse_id@Base 3.5.0-1 + nl_cli_ct_parse_id@libnl_3 3.5.0-1 + nl_cli_ct_parse_mark@Base 3.5.0-1 + nl_cli_ct_parse_mark@libnl_3 3.5.0-1 + nl_cli_ct_parse_protocol@Base 3.5.0-1 + nl_cli_ct_parse_protocol@libnl_3 3.5.0-1 + nl_cli_ct_parse_src@Base 3.5.0-1 + nl_cli_ct_parse_src@libnl_3 3.5.0-1 + nl_cli_ct_parse_src_port@Base 3.5.0-1 + nl_cli_ct_parse_src_port@libnl_3 3.5.0-1 + nl_cli_ct_parse_status@Base 3.5.0-1 + nl_cli_ct_parse_status@libnl_3 3.5.0-1 + nl_cli_ct_parse_tcp_state@Base 3.5.0-1 + nl_cli_ct_parse_tcp_state@libnl_3 3.5.0-1 + nl_cli_ct_parse_timeout@Base 3.5.0-1 + nl_cli_ct_parse_timeout@libnl_3 3.5.0-1 + nl_cli_ct_parse_use@Base 3.5.0-1 + nl_cli_ct_parse_use@libnl_3 3.5.0-1 + nl_cli_ct_parse_zone@Base 3.5.0-1 + nl_cli_ct_parse_zone@libnl_3 3.5.0-1 + nl_cli_exp_alloc@Base 3.5.0-1 + nl_cli_exp_alloc@libnl_3 3.5.0-1 + nl_cli_exp_alloc_cache@Base 3.5.0-1 + nl_cli_exp_alloc_cache@libnl_3 3.5.0-1 + nl_cli_exp_parse_class@Base 3.5.0-1 + nl_cli_exp_parse_class@libnl_3 3.5.0-1 + nl_cli_exp_parse_dst@Base 3.5.0-1 + nl_cli_exp_parse_dst@libnl_3 3.5.0-1 + nl_cli_exp_parse_dst_port@Base 3.5.0-1 + nl_cli_exp_parse_dst_port@libnl_3 3.5.0-1 + nl_cli_exp_parse_family@Base 3.5.0-1 + nl_cli_exp_parse_family@libnl_3 3.5.0-1 + nl_cli_exp_parse_flags@Base 3.5.0-1 + nl_cli_exp_parse_flags@libnl_3 3.5.0-1 + nl_cli_exp_parse_fn@Base 3.5.0-1 + nl_cli_exp_parse_fn@libnl_3 3.5.0-1 + nl_cli_exp_parse_helper_name@Base 3.5.0-1 + nl_cli_exp_parse_helper_name@libnl_3 3.5.0-1 + nl_cli_exp_parse_icmp_code@Base 3.5.0-1 + nl_cli_exp_parse_icmp_code@libnl_3 3.5.0-1 + nl_cli_exp_parse_icmp_id@Base 3.5.0-1 + nl_cli_exp_parse_icmp_id@libnl_3 3.5.0-1 + nl_cli_exp_parse_icmp_type@Base 3.5.0-1 + nl_cli_exp_parse_icmp_type@libnl_3 3.5.0-1 + nl_cli_exp_parse_id@Base 3.5.0-1 + nl_cli_exp_parse_id@libnl_3 3.5.0-1 + nl_cli_exp_parse_l4protonum@Base 3.5.0-1 + nl_cli_exp_parse_l4protonum@libnl_3 3.5.0-1 + nl_cli_exp_parse_nat_dir@Base 3.5.0-1 + nl_cli_exp_parse_nat_dir@libnl_3 3.5.0-1 + nl_cli_exp_parse_src@Base 3.5.0-1 + nl_cli_exp_parse_src@libnl_3 3.5.0-1 + nl_cli_exp_parse_src_port@Base 3.5.0-1 + nl_cli_exp_parse_src_port@libnl_3 3.5.0-1 + nl_cli_exp_parse_timeout@Base 3.5.0-1 + nl_cli_exp_parse_timeout@libnl_3 3.5.0-1 + nl_cli_exp_parse_zone@Base 3.5.0-1 + nl_cli_exp_parse_zone@libnl_3 3.5.0-1 + nl_cli_fatal@Base 3.5.0-1 + nl_cli_fatal@libnl_3 3.5.0-1 + nl_cli_link_alloc@Base 3.5.0-1 + nl_cli_link_alloc@libnl_3 3.5.0-1 + nl_cli_link_alloc_cache@Base 3.5.0-1 + nl_cli_link_alloc_cache@libnl_3 3.5.0-1 + nl_cli_link_alloc_cache_family@Base 3.5.0-1 + nl_cli_link_alloc_cache_family@libnl_3 3.5.0-1 + nl_cli_link_alloc_cache_family_flags@libnl_3_2_28 3.5.0-1 + nl_cli_link_alloc_cache_flags@libnl_3_2_28 3.5.0-1 + nl_cli_link_parse_family@Base 3.5.0-1 + nl_cli_link_parse_family@libnl_3 3.5.0-1 + nl_cli_link_parse_ifalias@Base 3.5.0-1 + nl_cli_link_parse_ifalias@libnl_3 3.5.0-1 + nl_cli_link_parse_ifindex@Base 3.5.0-1 + nl_cli_link_parse_ifindex@libnl_3 3.5.0-1 + nl_cli_link_parse_mtu@Base 3.5.0-1 + nl_cli_link_parse_mtu@libnl_3 3.5.0-1 + nl_cli_link_parse_name@Base 3.5.0-1 + nl_cli_link_parse_name@libnl_3 3.5.0-1 + nl_cli_link_parse_txqlen@Base 3.5.0-1 + nl_cli_link_parse_txqlen@libnl_3 3.5.0-1 + nl_cli_link_parse_weight@Base 3.5.0-1 + nl_cli_link_parse_weight@libnl_3 3.5.0-1 + nl_cli_load_module@Base 3.5.0-1 + nl_cli_load_module@libnl_3 3.5.0-1 + nl_cli_neigh_alloc@Base 3.5.0-1 + nl_cli_neigh_alloc@libnl_3 3.5.0-1 + nl_cli_neigh_parse_dev@Base 3.5.0-1 + nl_cli_neigh_parse_dev@libnl_3 3.5.0-1 + nl_cli_neigh_parse_dst@Base 3.5.0-1 + nl_cli_neigh_parse_dst@libnl_3 3.5.0-1 + nl_cli_neigh_parse_family@Base 3.5.0-1 + nl_cli_neigh_parse_family@libnl_3 3.5.0-1 + nl_cli_neigh_parse_lladdr@Base 3.5.0-1 + nl_cli_neigh_parse_lladdr@libnl_3 3.5.0-1 + nl_cli_neigh_parse_state@Base 3.5.0-1 + nl_cli_neigh_parse_state@libnl_3 3.5.0-1 + nl_cli_parse_dumptype@Base 3.5.0-1 + nl_cli_parse_dumptype@libnl_3 3.5.0-1 + nl_cli_parse_u32@Base 3.5.0-1 + nl_cli_parse_u32@libnl_3 3.5.0-1 + nl_cli_print_version@Base 3.5.0-1 + nl_cli_print_version@libnl_3 3.5.0-1 + nl_cli_qdisc_alloc@Base 3.5.0-1 + nl_cli_qdisc_alloc@libnl_3 3.5.0-1 + nl_cli_route_alloc@Base 3.5.0-1 + nl_cli_route_alloc@libnl_3 3.5.0-1 + nl_cli_route_alloc_cache@Base 3.5.0-1 + nl_cli_route_alloc_cache@libnl_3 3.5.0-1 + nl_cli_route_parse_dst@Base 3.5.0-1 + nl_cli_route_parse_dst@libnl_3 3.5.0-1 + nl_cli_route_parse_family@Base 3.5.0-1 + nl_cli_route_parse_family@libnl_3 3.5.0-1 + nl_cli_route_parse_iif@Base 3.5.0-1 + nl_cli_route_parse_iif@libnl_3 3.5.0-1 + nl_cli_route_parse_metric@Base 3.5.0-1 + nl_cli_route_parse_metric@libnl_3 3.5.0-1 + nl_cli_route_parse_nexthop@Base 3.5.0-1 + nl_cli_route_parse_nexthop@libnl_3 3.5.0-1 + nl_cli_route_parse_pref_src@Base 3.5.0-1 + nl_cli_route_parse_pref_src@libnl_3 3.5.0-1 + nl_cli_route_parse_prio@Base 3.5.0-1 + nl_cli_route_parse_prio@libnl_3 3.5.0-1 + nl_cli_route_parse_protocol@Base 3.5.0-1 + nl_cli_route_parse_protocol@libnl_3 3.5.0-1 + nl_cli_route_parse_scope@Base 3.5.0-1 + nl_cli_route_parse_scope@libnl_3 3.5.0-1 + nl_cli_route_parse_src@Base 3.5.0-1 + nl_cli_route_parse_src@libnl_3 3.5.0-1 + nl_cli_route_parse_table@Base 3.5.0-1 + nl_cli_route_parse_table@libnl_3 3.5.0-1 + nl_cli_route_parse_type@Base 3.5.0-1 + nl_cli_route_parse_type@libnl_3 3.5.0-1 + nl_cli_rule_alloc@Base 3.5.0-1 + nl_cli_rule_alloc@libnl_3 3.5.0-1 + nl_cli_rule_alloc_cache@Base 3.5.0-1 + nl_cli_rule_alloc_cache@libnl_3 3.5.0-1 + nl_cli_rule_parse_family@Base 3.5.0-1 + nl_cli_rule_parse_family@libnl_3 3.5.0-1 + nl_cli_tc_lookup@Base 3.5.0-1 + nl_cli_tc_lookup@libnl_3 3.5.0-1 + nl_cli_tc_parse_dev@Base 3.5.0-1 + nl_cli_tc_parse_dev@libnl_3 3.5.0-1 + nl_cli_tc_parse_handle@Base 3.5.0-1 + nl_cli_tc_parse_handle@libnl_3 3.5.0-1 + nl_cli_tc_parse_kind@Base 3.5.0-1 + nl_cli_tc_parse_kind@libnl_3 3.5.0-1 + nl_cli_tc_parse_linktype@Base 3.5.0-1 + nl_cli_tc_parse_linktype@libnl_3 3.5.0-1 + nl_cli_tc_parse_mpu@Base 3.5.0-1 + nl_cli_tc_parse_mpu@libnl_3 3.5.0-1 + nl_cli_tc_parse_mtu@Base 3.5.0-1 + nl_cli_tc_parse_mtu@libnl_3 3.5.0-1 + nl_cli_tc_parse_overhead@Base 3.5.0-1 + nl_cli_tc_parse_overhead@libnl_3 3.5.0-1 + nl_cli_tc_parse_parent@Base 3.5.0-1 + nl_cli_tc_parse_parent@libnl_3 3.5.0-1 + nl_cli_tc_register@Base 3.5.0-1 + nl_cli_tc_register@libnl_3 3.5.0-1 + nl_cli_tc_unregister@Base 3.5.0-1 + nl_cli_tc_unregister@libnl_3 3.5.0-1 +pfifo.so libnl-cli-3-200 #MINVER# +plug.so libnl-cli-3-200 #MINVER# diff --git a/src/libnl3/debian/libnl-cli-3-dev.install b/src/libnl3/debian/libnl-cli-3-dev.install new file mode 100644 index 000000000000..66aa3b3d9457 --- /dev/null +++ b/src/libnl3/debian/libnl-cli-3-dev.install @@ -0,0 +1,3 @@ +debian/tmp/usr/lib/*/pkgconfig/libnl-cli-3* +debian/tmp/usr/lib/*/libnl-cli-3*.so +debian/tmp/usr/lib/*/libnl-cli-3*.a diff --git a/src/libnl3/debian/libnl-genl-3-200-udeb.install b/src/libnl3/debian/libnl-genl-3-200-udeb.install new file mode 100755 index 000000000000..cb5597bf74da --- /dev/null +++ b/src/libnl3/debian/libnl-genl-3-200-udeb.install @@ -0,0 +1,2 @@ +#!/usr/bin/dh-exec +usr/lib/${DEB_HOST_MULTIARCH}/libnl-genl-3.so.* lib/${DEB_HOST_MULTIARCH}/ diff --git a/src/libnl3/debian/libnl-genl-3-200.install b/src/libnl3/debian/libnl-genl-3-200.install new file mode 100755 index 000000000000..d9d6fae40b21 --- /dev/null +++ b/src/libnl3/debian/libnl-genl-3-200.install @@ -0,0 +1,2 @@ +#!/usr/bin/dh-exec +debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/libnl-genl-3*.so.* lib/${DEB_HOST_MULTIARCH}/ diff --git a/src/libnl3/debian/libnl-genl-3-200.symbols b/src/libnl3/debian/libnl-genl-3-200.symbols new file mode 100644 index 000000000000..0eb2e3be4460 --- /dev/null +++ b/src/libnl3/debian/libnl-genl-3-200.symbols @@ -0,0 +1,88 @@ +libnl-genl-3.so.200 libnl-genl-3-200 #MINVER# + genl_connect@Base 3.5.0-1 + genl_connect@libnl_3 3.5.0-1 + genl_ctrl_alloc_cache@Base 3.5.0-1 + genl_ctrl_alloc_cache@libnl_3 3.5.0-1 + genl_ctrl_resolve@Base 3.5.0-1 + genl_ctrl_resolve@libnl_3 3.5.0-1 + genl_ctrl_resolve_grp@Base 3.5.0-1 + genl_ctrl_resolve_grp@libnl_3 3.5.0-1 + genl_ctrl_search@Base 3.5.0-1 + genl_ctrl_search@libnl_3 3.5.0-1 + genl_ctrl_search_by_name@Base 3.5.0-1 + genl_ctrl_search_by_name@libnl_3 3.5.0-1 + genl_family_add_grp@Base 3.5.0-1 + genl_family_add_grp@libnl_3 3.5.0-1 + genl_family_add_op@Base 3.5.0-1 + genl_family_add_op@libnl_3 3.5.0-1 + genl_family_alloc@Base 3.5.0-1 + genl_family_alloc@libnl_3 3.5.0-1 + genl_family_get_hdrsize@Base 3.5.0-1 + genl_family_get_hdrsize@libnl_3 3.5.0-1 + genl_family_get_id@Base 3.5.0-1 + genl_family_get_id@libnl_3 3.5.0-1 + genl_family_get_maxattr@Base 3.5.0-1 + genl_family_get_maxattr@libnl_3 3.5.0-1 + genl_family_get_name@Base 3.5.0-1 + genl_family_get_name@libnl_3 3.5.0-1 + genl_family_get_version@Base 3.5.0-1 + genl_family_get_version@libnl_3 3.5.0-1 + genl_family_ops@Base 3.5.0-1 + genl_family_ops@libnl_3 3.5.0-1 + genl_family_put@Base 3.5.0-1 + genl_family_put@libnl_3 3.5.0-1 + genl_family_set_hdrsize@Base 3.5.0-1 + genl_family_set_hdrsize@libnl_3 3.5.0-1 + genl_family_set_id@Base 3.5.0-1 + genl_family_set_id@libnl_3 3.5.0-1 + genl_family_set_maxattr@Base 3.5.0-1 + genl_family_set_maxattr@libnl_3 3.5.0-1 + genl_family_set_name@Base 3.5.0-1 + genl_family_set_name@libnl_3 3.5.0-1 + genl_family_set_version@Base 3.5.0-1 + genl_family_set_version@libnl_3 3.5.0-1 + genl_handle_msg@Base 3.5.0-1 + genl_handle_msg@libnl_3 3.5.0-1 + genl_mngt_resolve@Base 3.5.0-1 + genl_mngt_resolve@libnl_3 3.5.0-1 + genl_op2name@Base 3.5.0-1 + genl_op2name@libnl_3 3.5.0-1 + genl_ops_resolve@Base 3.5.0-1 + genl_ops_resolve@libnl_3 3.5.0-1 + genl_register@Base 3.5.0-1 + genl_register@libnl_3 3.5.0-1 + genl_register_family@Base 3.5.0-1 + genl_register_family@libnl_3 3.5.0-1 + genl_resolve_id@Base 3.5.0-1 + genl_resolve_id@libnl_3 3.5.0-1 + genl_send_simple@Base 3.5.0-1 + genl_send_simple@libnl_3 3.5.0-1 + genl_unregister@Base 3.5.0-1 + genl_unregister@libnl_3 3.5.0-1 + genl_unregister_family@Base 3.5.0-1 + genl_unregister_family@libnl_3 3.5.0-1 + genlmsg_attrdata@Base 3.5.0-1 + genlmsg_attrdata@libnl_3 3.5.0-1 + genlmsg_attrlen@Base 3.5.0-1 + genlmsg_attrlen@libnl_3 3.5.0-1 + genlmsg_data@Base 3.5.0-1 + genlmsg_data@libnl_3 3.5.0-1 + genlmsg_hdr@Base 3.5.0-1 + genlmsg_hdr@libnl_3 3.5.0-1 + genlmsg_len@Base 3.5.0-1 + genlmsg_len@libnl_3 3.5.0-1 + genlmsg_parse@Base 3.5.0-1 + genlmsg_parse@libnl_3 3.5.0-1 + genlmsg_put@Base 3.5.0-1 + genlmsg_put@libnl_3 3.5.0-1 + genlmsg_user_data@Base 3.5.0-1 + genlmsg_user_data@libnl_3 3.5.0-1 + genlmsg_user_datalen@Base 3.5.0-1 + genlmsg_user_datalen@libnl_3 3.5.0-1 + genlmsg_user_hdr@Base 3.5.0-1 + genlmsg_user_hdr@libnl_3 3.5.0-1 + genlmsg_valid_hdr@Base 3.5.0-1 + genlmsg_valid_hdr@libnl_3 3.5.0-1 + genlmsg_validate@Base 3.5.0-1 + genlmsg_validate@libnl_3 3.5.0-1 + libnl_3@libnl_3 3.5.0-1 diff --git a/src/libnl3/debian/libnl-genl-3-dev.install b/src/libnl3/debian/libnl-genl-3-dev.install new file mode 100755 index 000000000000..cbc6b51ef474 --- /dev/null +++ b/src/libnl3/debian/libnl-genl-3-dev.install @@ -0,0 +1,4 @@ +#!/usr/bin/dh-exec +debian/tmp/usr/lib/*/pkgconfig/libnl-genl-3* +debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/libnl-genl-3*.so lib/${DEB_HOST_MULTIARCH}/ +debian/tmp/usr/lib/${DEB_HOST_MULTIARCH}/libnl-genl-3*.a lib/${DEB_HOST_MULTIARCH}/ diff --git a/src/libnl3/debian/libnl-idiag-3-200.install b/src/libnl3/debian/libnl-idiag-3-200.install new file mode 100644 index 000000000000..f6d6b8064e5f --- /dev/null +++ b/src/libnl3/debian/libnl-idiag-3-200.install @@ -0,0 +1 @@ +debian/tmp/usr/lib/*/libnl-idiag-3*.so.* diff --git a/src/libnl3/debian/libnl-idiag-3-200.symbols b/src/libnl3/debian/libnl-idiag-3-200.symbols new file mode 100644 index 000000000000..13cf27c7c8ac --- /dev/null +++ b/src/libnl3/debian/libnl-idiag-3-200.symbols @@ -0,0 +1,206 @@ +libnl-idiag-3.so.200 libnl-idiag-3-200 #MINVER# + idiagnl_attrs2str@Base 3.5.0-1 + idiagnl_attrs2str@libnl_3 3.5.0-1 + idiagnl_connect@Base 3.5.0-1 + idiagnl_connect@libnl_3 3.5.0-1 + idiagnl_exts2str@Base 3.5.0-1 + idiagnl_exts2str@libnl_3 3.5.0-1 + idiagnl_meminfo_alloc@Base 3.5.0-1 + idiagnl_meminfo_alloc@libnl_3 3.5.0-1 + idiagnl_meminfo_get@Base 3.5.0-1 + idiagnl_meminfo_get@libnl_3 3.5.0-1 + idiagnl_meminfo_get_fmem@Base 3.5.0-1 + idiagnl_meminfo_get_fmem@libnl_3 3.5.0-1 + idiagnl_meminfo_get_rmem@Base 3.5.0-1 + idiagnl_meminfo_get_rmem@libnl_3 3.5.0-1 + idiagnl_meminfo_get_tmem@Base 3.5.0-1 + idiagnl_meminfo_get_tmem@libnl_3 3.5.0-1 + idiagnl_meminfo_get_wmem@Base 3.5.0-1 + idiagnl_meminfo_get_wmem@libnl_3 3.5.0-1 + idiagnl_meminfo_obj_ops@Base 3.5.0-1 + idiagnl_meminfo_obj_ops@libnl_3 3.5.0-1 + idiagnl_meminfo_put@Base 3.5.0-1 + idiagnl_meminfo_put@libnl_3 3.5.0-1 + idiagnl_meminfo_set_fmem@Base 3.5.0-1 + idiagnl_meminfo_set_fmem@libnl_3 3.5.0-1 + idiagnl_meminfo_set_rmem@Base 3.5.0-1 + idiagnl_meminfo_set_rmem@libnl_3 3.5.0-1 + idiagnl_meminfo_set_tmem@Base 3.5.0-1 + idiagnl_meminfo_set_tmem@libnl_3 3.5.0-1 + idiagnl_meminfo_set_wmem@Base 3.5.0-1 + idiagnl_meminfo_set_wmem@libnl_3 3.5.0-1 + idiagnl_msg_alloc@Base 3.5.0-1 + idiagnl_msg_alloc@libnl_3 3.5.0-1 + idiagnl_msg_alloc_cache@Base 3.5.0-1 + idiagnl_msg_alloc_cache@libnl_3 3.5.0-1 + idiagnl_msg_get@Base 3.5.0-1 + idiagnl_msg_get@libnl_3 3.5.0-1 + idiagnl_msg_get_cong@Base 3.5.0-1 + idiagnl_msg_get_cong@libnl_3 3.5.0-1 + idiagnl_msg_get_dport@Base 3.5.0-1 + idiagnl_msg_get_dport@libnl_3 3.5.0-1 + idiagnl_msg_get_dst@Base 3.5.0-1 + idiagnl_msg_get_dst@libnl_3 3.5.0-1 + idiagnl_msg_get_expires@Base 3.5.0-1 + idiagnl_msg_get_expires@libnl_3 3.5.0-1 + idiagnl_msg_get_family@Base 3.5.0-1 + idiagnl_msg_get_family@libnl_3 3.5.0-1 + idiagnl_msg_get_ifindex@Base 3.5.0-1 + idiagnl_msg_get_ifindex@libnl_3 3.5.0-1 + idiagnl_msg_get_inode@Base 3.5.0-1 + idiagnl_msg_get_inode@libnl_3 3.5.0-1 + idiagnl_msg_get_meminfo@Base 3.5.0-1 + idiagnl_msg_get_meminfo@libnl_3 3.5.0-1 + idiagnl_msg_get_retrans@Base 3.5.0-1 + idiagnl_msg_get_retrans@libnl_3 3.5.0-1 + idiagnl_msg_get_rqueue@Base 3.5.0-1 + idiagnl_msg_get_rqueue@libnl_3 3.5.0-1 + idiagnl_msg_get_shutdown@Base 3.5.0-1 + idiagnl_msg_get_shutdown@libnl_3 3.5.0-1 + idiagnl_msg_get_sport@Base 3.5.0-1 + idiagnl_msg_get_sport@libnl_3 3.5.0-1 + idiagnl_msg_get_src@Base 3.5.0-1 + idiagnl_msg_get_src@libnl_3 3.5.0-1 + idiagnl_msg_get_state@Base 3.5.0-1 + idiagnl_msg_get_state@libnl_3 3.5.0-1 + idiagnl_msg_get_tclass@Base 3.5.0-1 + idiagnl_msg_get_tclass@libnl_3 3.5.0-1 + idiagnl_msg_get_tcpinfo@Base 3.5.0-1 + idiagnl_msg_get_tcpinfo@libnl_3 3.5.0-1 + idiagnl_msg_get_timer@Base 3.5.0-1 + idiagnl_msg_get_timer@libnl_3 3.5.0-1 + idiagnl_msg_get_tos@Base 3.5.0-1 + idiagnl_msg_get_tos@libnl_3 3.5.0-1 + idiagnl_msg_get_uid@Base 3.5.0-1 + idiagnl_msg_get_uid@libnl_3 3.5.0-1 + idiagnl_msg_get_vegasinfo@Base 3.5.0-1 + idiagnl_msg_get_vegasinfo@libnl_3 3.5.0-1 + idiagnl_msg_get_wqueue@Base 3.5.0-1 + idiagnl_msg_get_wqueue@libnl_3 3.5.0-1 + idiagnl_msg_obj_ops@Base 3.5.0-1 + idiagnl_msg_obj_ops@libnl_3 3.5.0-1 + idiagnl_msg_parse@Base 3.5.0-1 + idiagnl_msg_parse@libnl_3 3.5.0-1 + idiagnl_msg_put@Base 3.5.0-1 + idiagnl_msg_put@libnl_3 3.5.0-1 + idiagnl_msg_set_cong@Base 3.5.0-1 + idiagnl_msg_set_cong@libnl_3 3.5.0-1 + idiagnl_msg_set_dport@Base 3.5.0-1 + idiagnl_msg_set_dport@libnl_3 3.5.0-1 + idiagnl_msg_set_dst@Base 3.5.0-1 + idiagnl_msg_set_dst@libnl_3 3.5.0-1 + idiagnl_msg_set_expires@Base 3.5.0-1 + idiagnl_msg_set_expires@libnl_3 3.5.0-1 + idiagnl_msg_set_family@Base 3.5.0-1 + idiagnl_msg_set_family@libnl_3 3.5.0-1 + idiagnl_msg_set_ifindex@Base 3.5.0-1 + idiagnl_msg_set_ifindex@libnl_3 3.5.0-1 + idiagnl_msg_set_inode@Base 3.5.0-1 + idiagnl_msg_set_inode@libnl_3 3.5.0-1 + idiagnl_msg_set_meminfo@Base 3.5.0-1 + idiagnl_msg_set_meminfo@libnl_3 3.5.0-1 + idiagnl_msg_set_retrans@Base 3.5.0-1 + idiagnl_msg_set_retrans@libnl_3 3.5.0-1 + idiagnl_msg_set_rqueue@Base 3.5.0-1 + idiagnl_msg_set_rqueue@libnl_3 3.5.0-1 + idiagnl_msg_set_shutdown@Base 3.5.0-1 + idiagnl_msg_set_shutdown@libnl_3 3.5.0-1 + idiagnl_msg_set_sport@Base 3.5.0-1 + idiagnl_msg_set_sport@libnl_3 3.5.0-1 + idiagnl_msg_set_src@Base 3.5.0-1 + idiagnl_msg_set_src@libnl_3 3.5.0-1 + idiagnl_msg_set_state@Base 3.5.0-1 + idiagnl_msg_set_state@libnl_3 3.5.0-1 + idiagnl_msg_set_tclass@Base 3.5.0-1 + idiagnl_msg_set_tclass@libnl_3 3.5.0-1 + idiagnl_msg_set_tcpinfo@Base 3.5.0-1 + idiagnl_msg_set_tcpinfo@libnl_3 3.5.0-1 + idiagnl_msg_set_timer@Base 3.5.0-1 + idiagnl_msg_set_timer@libnl_3 3.5.0-1 + idiagnl_msg_set_tos@Base 3.5.0-1 + idiagnl_msg_set_tos@libnl_3 3.5.0-1 + idiagnl_msg_set_uid@Base 3.5.0-1 + idiagnl_msg_set_uid@libnl_3 3.5.0-1 + idiagnl_msg_set_vegasinfo@Base 3.5.0-1 + idiagnl_msg_set_vegasinfo@libnl_3 3.5.0-1 + idiagnl_msg_set_wqueue@Base 3.5.0-1 + idiagnl_msg_set_wqueue@libnl_3 3.5.0-1 + idiagnl_req_alloc@Base 3.5.0-1 + idiagnl_req_alloc@libnl_3 3.5.0-1 + idiagnl_req_get@Base 3.5.0-1 + idiagnl_req_get@libnl_3 3.5.0-1 + idiagnl_req_get_dbs@Base 3.5.0-1 + idiagnl_req_get_dbs@libnl_3 3.5.0-1 + idiagnl_req_get_dst@Base 3.5.0-1 + idiagnl_req_get_dst@libnl_3 3.5.0-1 + idiagnl_req_get_ext@Base 3.5.0-1 + idiagnl_req_get_ext@libnl_3 3.5.0-1 + idiagnl_req_get_family@Base 3.5.0-1 + idiagnl_req_get_family@libnl_3 3.5.0-1 + idiagnl_req_get_ifindex@Base 3.5.0-1 + idiagnl_req_get_ifindex@libnl_3 3.5.0-1 + idiagnl_req_get_src@Base 3.5.0-1 + idiagnl_req_get_src@libnl_3 3.5.0-1 + idiagnl_req_get_states@Base 3.5.0-1 + idiagnl_req_get_states@libnl_3 3.5.0-1 + idiagnl_req_obj_ops@Base 3.5.0-1 + idiagnl_req_obj_ops@libnl_3 3.5.0-1 + idiagnl_req_parse@Base 3.5.0-1 + idiagnl_req_parse@libnl_3 3.5.0-1 + idiagnl_req_put@Base 3.5.0-1 + idiagnl_req_put@libnl_3 3.5.0-1 + idiagnl_req_set_dbs@Base 3.5.0-1 + idiagnl_req_set_dbs@libnl_3 3.5.0-1 + idiagnl_req_set_dst@Base 3.5.0-1 + idiagnl_req_set_dst@libnl_3 3.5.0-1 + idiagnl_req_set_ext@Base 3.5.0-1 + idiagnl_req_set_ext@libnl_3 3.5.0-1 + idiagnl_req_set_family@Base 3.5.0-1 + idiagnl_req_set_family@libnl_3 3.5.0-1 + idiagnl_req_set_ifindex@Base 3.5.0-1 + idiagnl_req_set_ifindex@libnl_3 3.5.0-1 + idiagnl_req_set_src@Base 3.5.0-1 + idiagnl_req_set_src@libnl_3 3.5.0-1 + idiagnl_req_set_states@Base 3.5.0-1 + idiagnl_req_set_states@libnl_3 3.5.0-1 + idiagnl_send_simple@Base 3.5.0-1 + idiagnl_send_simple@libnl_3 3.5.0-1 + idiagnl_shutdown2str@Base 3.5.0-1 + idiagnl_shutdown2str@libnl_3 3.5.0-1 + idiagnl_state2str@Base 3.5.0-1 + idiagnl_state2str@libnl_3 3.5.0-1 + idiagnl_str2state@Base 3.5.0-1 + idiagnl_str2state@libnl_3 3.5.0-1 + idiagnl_str2timer@Base 3.5.0-1 + idiagnl_str2timer@libnl_3 3.5.0-1 + idiagnl_tcpopts2str@Base 3.5.0-1 + idiagnl_tcpopts2str@libnl_3 3.5.0-1 + idiagnl_tcpstate2str@Base 3.5.0-1 + idiagnl_tcpstate2str@libnl_3 3.5.0-1 + idiagnl_timer2str@Base 3.5.0-1 + idiagnl_timer2str@libnl_3 3.5.0-1 + idiagnl_vegasinfo_alloc@Base 3.5.0-1 + idiagnl_vegasinfo_alloc@libnl_3 3.5.0-1 + idiagnl_vegasinfo_get@Base 3.5.0-1 + idiagnl_vegasinfo_get@libnl_3 3.5.0-1 + idiagnl_vegasinfo_get_enabled@Base 3.5.0-1 + idiagnl_vegasinfo_get_enabled@libnl_3 3.5.0-1 + idiagnl_vegasinfo_get_minrtt@Base 3.5.0-1 + idiagnl_vegasinfo_get_minrtt@libnl_3 3.5.0-1 + idiagnl_vegasinfo_get_rtt@Base 3.5.0-1 + idiagnl_vegasinfo_get_rtt@libnl_3 3.5.0-1 + idiagnl_vegasinfo_get_rttcnt@Base 3.5.0-1 + idiagnl_vegasinfo_get_rttcnt@libnl_3 3.5.0-1 + idiagnl_vegasinfo_obj_ops@Base 3.5.0-1 + idiagnl_vegasinfo_obj_ops@libnl_3 3.5.0-1 + idiagnl_vegasinfo_put@Base 3.5.0-1 + idiagnl_vegasinfo_put@libnl_3 3.5.0-1 + idiagnl_vegasinfo_set_enabled@Base 3.5.0-1 + idiagnl_vegasinfo_set_enabled@libnl_3 3.5.0-1 + idiagnl_vegasinfo_set_minrtt@Base 3.5.0-1 + idiagnl_vegasinfo_set_minrtt@libnl_3 3.5.0-1 + idiagnl_vegasinfo_set_rtt@Base 3.5.0-1 + idiagnl_vegasinfo_set_rtt@libnl_3 3.5.0-1 + idiagnl_vegasinfo_set_rttcnt@Base 3.5.0-1 + idiagnl_vegasinfo_set_rttcnt@libnl_3 3.5.0-1 + libnl_3@libnl_3 3.5.0-1 diff --git a/src/libnl3/debian/libnl-idiag-3-dev.install b/src/libnl3/debian/libnl-idiag-3-dev.install new file mode 100644 index 000000000000..6f19a6e83d61 --- /dev/null +++ b/src/libnl3/debian/libnl-idiag-3-dev.install @@ -0,0 +1,3 @@ +debian/tmp/usr/lib/*/pkgconfig/libnl-idiag-3* +debian/tmp/usr/lib/*/libnl-idiag-3*.so +debian/tmp/usr/lib/*/libnl-idiag-3*.a diff --git a/src/libnl3/debian/libnl-nf-3-200.install b/src/libnl3/debian/libnl-nf-3-200.install new file mode 100644 index 000000000000..6d65611ed34e --- /dev/null +++ b/src/libnl3/debian/libnl-nf-3-200.install @@ -0,0 +1 @@ +debian/tmp/usr/lib/*/libnl-nf-3*.so.* diff --git a/src/libnl3/debian/libnl-nf-3-200.symbols b/src/libnl3/debian/libnl-nf-3-200.symbols new file mode 100644 index 000000000000..2ce4d2ad0ffc --- /dev/null +++ b/src/libnl3/debian/libnl-nf-3-200.symbols @@ -0,0 +1,620 @@ +libnl-nf-3.so.200 libnl-nf-3-200 #MINVER# + ct_obj_ops@Base 3.5.0-1 + ct_obj_ops@libnl_3 3.5.0-1 + exp_obj_ops@Base 3.5.0-1 + exp_obj_ops@libnl_3 3.5.0-1 + libnl_3@libnl_3 3.5.0-1 + log_msg_obj_ops@Base 3.5.0-1 + log_msg_obj_ops@libnl_3 3.5.0-1 + log_obj_ops@Base 3.5.0-1 + log_obj_ops@libnl_3 3.5.0-1 + nfnl_connect@Base 3.5.0-1 + nfnl_connect@libnl_3 3.5.0-1 + nfnl_ct_add@Base 3.5.0-1 + nfnl_ct_add@libnl_3 3.5.0-1 + nfnl_ct_alloc@Base 3.5.0-1 + nfnl_ct_alloc@libnl_3 3.5.0-1 + nfnl_ct_alloc_cache@Base 3.5.0-1 + nfnl_ct_alloc_cache@libnl_3 3.5.0-1 + nfnl_ct_build_add_request@Base 3.5.0-1 + nfnl_ct_build_add_request@libnl_3 3.5.0-1 + nfnl_ct_build_delete_request@Base 3.5.0-1 + nfnl_ct_build_delete_request@libnl_3 3.5.0-1 + nfnl_ct_build_query_request@Base 3.5.0-1 + nfnl_ct_build_query_request@libnl_3 3.5.0-1 + nfnl_ct_del@Base 3.5.0-1 + nfnl_ct_del@libnl_3 3.5.0-1 + nfnl_ct_dump_request@Base 3.5.0-1 + nfnl_ct_dump_request@libnl_3 3.5.0-1 + nfnl_ct_get@Base 3.5.0-1 + nfnl_ct_get@libnl_3 3.5.0-1 + nfnl_ct_get_bytes@Base 3.5.0-1 + nfnl_ct_get_bytes@libnl_3 3.5.0-1 + nfnl_ct_get_dst@Base 3.5.0-1 + nfnl_ct_get_dst@libnl_3 3.5.0-1 + nfnl_ct_get_dst_port@Base 3.5.0-1 + nfnl_ct_get_dst_port@libnl_3 3.5.0-1 + nfnl_ct_get_family@Base 3.5.0-1 + nfnl_ct_get_family@libnl_3 3.5.0-1 + nfnl_ct_get_icmp_code@Base 3.5.0-1 + nfnl_ct_get_icmp_code@libnl_3 3.5.0-1 + nfnl_ct_get_icmp_id@Base 3.5.0-1 + nfnl_ct_get_icmp_id@libnl_3 3.5.0-1 + nfnl_ct_get_icmp_type@Base 3.5.0-1 + nfnl_ct_get_icmp_type@libnl_3 3.5.0-1 + nfnl_ct_get_id@Base 3.5.0-1 + nfnl_ct_get_id@libnl_3 3.5.0-1 + nfnl_ct_get_mark@Base 3.5.0-1 + nfnl_ct_get_mark@libnl_3 3.5.0-1 + nfnl_ct_get_packets@Base 3.5.0-1 + nfnl_ct_get_packets@libnl_3 3.5.0-1 + nfnl_ct_get_proto@Base 3.5.0-1 + nfnl_ct_get_proto@libnl_3 3.5.0-1 + nfnl_ct_get_src@Base 3.5.0-1 + nfnl_ct_get_src@libnl_3 3.5.0-1 + nfnl_ct_get_src_port@Base 3.5.0-1 + nfnl_ct_get_src_port@libnl_3 3.5.0-1 + nfnl_ct_get_status@Base 3.5.0-1 + nfnl_ct_get_status@libnl_3 3.5.0-1 + nfnl_ct_get_tcp_state@Base 3.5.0-1 + nfnl_ct_get_tcp_state@libnl_3 3.5.0-1 + nfnl_ct_get_timeout@Base 3.5.0-1 + nfnl_ct_get_timeout@libnl_3 3.5.0-1 + nfnl_ct_get_timestamp@Base 3.5.0-1 + nfnl_ct_get_timestamp@libnl_3 3.5.0-1 + nfnl_ct_get_use@Base 3.5.0-1 + nfnl_ct_get_use@libnl_3 3.5.0-1 + nfnl_ct_get_zone@Base 3.5.0-1 + nfnl_ct_get_zone@libnl_3 3.5.0-1 + nfnl_ct_put@Base 3.5.0-1 + nfnl_ct_put@libnl_3 3.5.0-1 + nfnl_ct_query@Base 3.5.0-1 + nfnl_ct_query@libnl_3 3.5.0-1 + nfnl_ct_set_bytes@Base 3.5.0-1 + nfnl_ct_set_bytes@libnl_3 3.5.0-1 + nfnl_ct_set_dst@Base 3.5.0-1 + nfnl_ct_set_dst@libnl_3 3.5.0-1 + nfnl_ct_set_dst_port@Base 3.5.0-1 + nfnl_ct_set_dst_port@libnl_3 3.5.0-1 + nfnl_ct_set_family@Base 3.5.0-1 + nfnl_ct_set_family@libnl_3 3.5.0-1 + nfnl_ct_set_icmp_code@Base 3.5.0-1 + nfnl_ct_set_icmp_code@libnl_3 3.5.0-1 + nfnl_ct_set_icmp_id@Base 3.5.0-1 + nfnl_ct_set_icmp_id@libnl_3 3.5.0-1 + nfnl_ct_set_icmp_type@Base 3.5.0-1 + nfnl_ct_set_icmp_type@libnl_3 3.5.0-1 + nfnl_ct_set_id@Base 3.5.0-1 + nfnl_ct_set_id@libnl_3 3.5.0-1 + nfnl_ct_set_mark@Base 3.5.0-1 + nfnl_ct_set_mark@libnl_3 3.5.0-1 + nfnl_ct_set_packets@Base 3.5.0-1 + nfnl_ct_set_packets@libnl_3 3.5.0-1 + nfnl_ct_set_proto@Base 3.5.0-1 + nfnl_ct_set_proto@libnl_3 3.5.0-1 + nfnl_ct_set_src@Base 3.5.0-1 + nfnl_ct_set_src@libnl_3 3.5.0-1 + nfnl_ct_set_src_port@Base 3.5.0-1 + nfnl_ct_set_src_port@libnl_3 3.5.0-1 + nfnl_ct_set_status@Base 3.5.0-1 + nfnl_ct_set_status@libnl_3 3.5.0-1 + nfnl_ct_set_tcp_state@Base 3.5.0-1 + nfnl_ct_set_tcp_state@libnl_3 3.5.0-1 + nfnl_ct_set_timeout@Base 3.5.0-1 + nfnl_ct_set_timeout@libnl_3 3.5.0-1 + nfnl_ct_set_timestamp@Base 3.5.0-1 + nfnl_ct_set_timestamp@libnl_3 3.5.0-1 + nfnl_ct_set_use@Base 3.5.0-1 + nfnl_ct_set_use@libnl_3 3.5.0-1 + nfnl_ct_set_zone@Base 3.5.0-1 + nfnl_ct_set_zone@libnl_3 3.5.0-1 + nfnl_ct_status2str@Base 3.5.0-1 + nfnl_ct_status2str@libnl_3 3.5.0-1 + nfnl_ct_str2status@Base 3.5.0-1 + nfnl_ct_str2status@libnl_3 3.5.0-1 + nfnl_ct_str2tcp_state@Base 3.5.0-1 + nfnl_ct_str2tcp_state@libnl_3 3.5.0-1 + nfnl_ct_tcp_state2str@Base 3.5.0-1 + nfnl_ct_tcp_state2str@libnl_3 3.5.0-1 + nfnl_ct_test_bytes@Base 3.5.0-1 + nfnl_ct_test_bytes@libnl_3 3.5.0-1 + nfnl_ct_test_dst_port@Base 3.5.0-1 + nfnl_ct_test_dst_port@libnl_3 3.5.0-1 + nfnl_ct_test_icmp_code@Base 3.5.0-1 + nfnl_ct_test_icmp_code@libnl_3 3.5.0-1 + nfnl_ct_test_icmp_id@Base 3.5.0-1 + nfnl_ct_test_icmp_id@libnl_3 3.5.0-1 + nfnl_ct_test_icmp_type@Base 3.5.0-1 + nfnl_ct_test_icmp_type@libnl_3 3.5.0-1 + nfnl_ct_test_id@Base 3.5.0-1 + nfnl_ct_test_id@libnl_3 3.5.0-1 + nfnl_ct_test_mark@Base 3.5.0-1 + nfnl_ct_test_mark@libnl_3 3.5.0-1 + nfnl_ct_test_packets@Base 3.5.0-1 + nfnl_ct_test_packets@libnl_3 3.5.0-1 + nfnl_ct_test_proto@Base 3.5.0-1 + nfnl_ct_test_proto@libnl_3 3.5.0-1 + nfnl_ct_test_src_port@Base 3.5.0-1 + nfnl_ct_test_src_port@libnl_3 3.5.0-1 + nfnl_ct_test_status@Base 3.5.0-1 + nfnl_ct_test_status@libnl_3 3.5.0-1 + nfnl_ct_test_tcp_state@Base 3.5.0-1 + nfnl_ct_test_tcp_state@libnl_3 3.5.0-1 + nfnl_ct_test_timeout@Base 3.5.0-1 + nfnl_ct_test_timeout@libnl_3 3.5.0-1 + nfnl_ct_test_timestamp@Base 3.5.0-1 + nfnl_ct_test_timestamp@libnl_3 3.5.0-1 + nfnl_ct_test_use@Base 3.5.0-1 + nfnl_ct_test_use@libnl_3 3.5.0-1 + nfnl_ct_test_zone@Base 3.5.0-1 + nfnl_ct_test_zone@libnl_3 3.5.0-1 + nfnl_ct_unset_status@Base 3.5.0-1 + nfnl_ct_unset_status@libnl_3 3.5.0-1 + nfnl_exp_add@Base 3.5.0-1 + nfnl_exp_add@libnl_3 3.5.0-1 + nfnl_exp_alloc@Base 3.5.0-1 + nfnl_exp_alloc@libnl_3 3.5.0-1 + nfnl_exp_alloc_cache@Base 3.5.0-1 + nfnl_exp_alloc_cache@libnl_3 3.5.0-1 + nfnl_exp_build_add_request@Base 3.5.0-1 + nfnl_exp_build_add_request@libnl_3 3.5.0-1 + nfnl_exp_build_delete_request@Base 3.5.0-1 + nfnl_exp_build_delete_request@libnl_3 3.5.0-1 + nfnl_exp_build_query_request@Base 3.5.0-1 + nfnl_exp_build_query_request@libnl_3 3.5.0-1 + nfnl_exp_del@Base 3.5.0-1 + nfnl_exp_del@libnl_3 3.5.0-1 + nfnl_exp_dump_request@Base 3.5.0-1 + nfnl_exp_dump_request@libnl_3 3.5.0-1 + nfnl_exp_flags2str@Base 3.5.0-1 + nfnl_exp_flags2str@libnl_3 3.5.0-1 + nfnl_exp_get@Base 3.5.0-1 + nfnl_exp_get@libnl_3 3.5.0-1 + nfnl_exp_get_class@Base 3.5.0-1 + nfnl_exp_get_class@libnl_3 3.5.0-1 + nfnl_exp_get_dst@Base 3.5.0-1 + nfnl_exp_get_dst@libnl_3 3.5.0-1 + nfnl_exp_get_dst_port@Base 3.5.0-1 + nfnl_exp_get_dst_port@libnl_3 3.5.0-1 + nfnl_exp_get_family@Base 3.5.0-1 + nfnl_exp_get_family@libnl_3 3.5.0-1 + nfnl_exp_get_flags@Base 3.5.0-1 + nfnl_exp_get_flags@libnl_3 3.5.0-1 + nfnl_exp_get_fn@Base 3.5.0-1 + nfnl_exp_get_fn@libnl_3 3.5.0-1 + nfnl_exp_get_helper_name@Base 3.5.0-1 + nfnl_exp_get_helper_name@libnl_3 3.5.0-1 + nfnl_exp_get_icmp_code@Base 3.5.0-1 + nfnl_exp_get_icmp_code@libnl_3 3.5.0-1 + nfnl_exp_get_icmp_id@Base 3.5.0-1 + nfnl_exp_get_icmp_id@libnl_3 3.5.0-1 + nfnl_exp_get_icmp_type@Base 3.5.0-1 + nfnl_exp_get_icmp_type@libnl_3 3.5.0-1 + nfnl_exp_get_id@Base 3.5.0-1 + nfnl_exp_get_id@libnl_3 3.5.0-1 + nfnl_exp_get_l4protonum@Base 3.5.0-1 + nfnl_exp_get_l4protonum@libnl_3 3.5.0-1 + nfnl_exp_get_nat_dir@Base 3.5.0-1 + nfnl_exp_get_nat_dir@libnl_3 3.5.0-1 + nfnl_exp_get_src@Base 3.5.0-1 + nfnl_exp_get_src@libnl_3 3.5.0-1 + nfnl_exp_get_src_port@Base 3.5.0-1 + nfnl_exp_get_src_port@libnl_3 3.5.0-1 + nfnl_exp_get_timeout@Base 3.5.0-1 + nfnl_exp_get_timeout@libnl_3 3.5.0-1 + nfnl_exp_get_zone@Base 3.5.0-1 + nfnl_exp_get_zone@libnl_3 3.5.0-1 + nfnl_exp_put@Base 3.5.0-1 + nfnl_exp_put@libnl_3 3.5.0-1 + nfnl_exp_query@Base 3.5.0-1 + nfnl_exp_query@libnl_3 3.5.0-1 + nfnl_exp_set_class@Base 3.5.0-1 + nfnl_exp_set_class@libnl_3 3.5.0-1 + nfnl_exp_set_dst@Base 3.5.0-1 + nfnl_exp_set_dst@libnl_3 3.5.0-1 + nfnl_exp_set_family@Base 3.5.0-1 + nfnl_exp_set_family@libnl_3 3.5.0-1 + nfnl_exp_set_flags@Base 3.5.0-1 + nfnl_exp_set_flags@libnl_3 3.5.0-1 + nfnl_exp_set_fn@Base 3.5.0-1 + nfnl_exp_set_fn@libnl_3 3.5.0-1 + nfnl_exp_set_helper_name@Base 3.5.0-1 + nfnl_exp_set_helper_name@libnl_3 3.5.0-1 + nfnl_exp_set_icmp@Base 3.5.0-1 + nfnl_exp_set_icmp@libnl_3 3.5.0-1 + nfnl_exp_set_id@Base 3.5.0-1 + nfnl_exp_set_id@libnl_3 3.5.0-1 + nfnl_exp_set_l4protonum@Base 3.5.0-1 + nfnl_exp_set_l4protonum@libnl_3 3.5.0-1 + nfnl_exp_set_nat_dir@Base 3.5.0-1 + nfnl_exp_set_nat_dir@libnl_3 3.5.0-1 + nfnl_exp_set_ports@Base 3.5.0-1 + nfnl_exp_set_ports@libnl_3 3.5.0-1 + nfnl_exp_set_src@Base 3.5.0-1 + nfnl_exp_set_src@libnl_3 3.5.0-1 + nfnl_exp_set_timeout@Base 3.5.0-1 + nfnl_exp_set_timeout@libnl_3 3.5.0-1 + nfnl_exp_set_zone@Base 3.5.0-1 + nfnl_exp_set_zone@libnl_3 3.5.0-1 + nfnl_exp_str2flags@Base 3.5.0-1 + nfnl_exp_str2flags@libnl_3 3.5.0-1 + nfnl_exp_test_class@Base 3.5.0-1 + nfnl_exp_test_class@libnl_3 3.5.0-1 + nfnl_exp_test_dst@Base 3.5.0-1 + nfnl_exp_test_dst@libnl_3 3.5.0-1 + nfnl_exp_test_flags@Base 3.5.0-1 + nfnl_exp_test_flags@libnl_3 3.5.0-1 + nfnl_exp_test_fn@Base 3.5.0-1 + nfnl_exp_test_fn@libnl_3 3.5.0-1 + nfnl_exp_test_helper_name@Base 3.5.0-1 + nfnl_exp_test_helper_name@libnl_3 3.5.0-1 + nfnl_exp_test_icmp@Base 3.5.0-1 + nfnl_exp_test_icmp@libnl_3 3.5.0-1 + nfnl_exp_test_id@Base 3.5.0-1 + nfnl_exp_test_id@libnl_3 3.5.0-1 + nfnl_exp_test_l4protonum@Base 3.5.0-1 + nfnl_exp_test_l4protonum@libnl_3 3.5.0-1 + nfnl_exp_test_nat_dir@Base 3.5.0-1 + nfnl_exp_test_nat_dir@libnl_3 3.5.0-1 + nfnl_exp_test_ports@Base 3.5.0-1 + nfnl_exp_test_ports@libnl_3 3.5.0-1 + nfnl_exp_test_src@Base 3.5.0-1 + nfnl_exp_test_src@libnl_3 3.5.0-1 + nfnl_exp_test_timeout@Base 3.5.0-1 + nfnl_exp_test_timeout@libnl_3 3.5.0-1 + nfnl_exp_test_zone@Base 3.5.0-1 + nfnl_exp_test_zone@libnl_3 3.5.0-1 + nfnl_exp_unset_flags@Base 3.5.0-1 + nfnl_exp_unset_flags@libnl_3 3.5.0-1 + nfnl_inet_hook2str@Base 3.5.0-1 + nfnl_inet_hook2str@libnl_3 3.5.0-1 + nfnl_log_alloc@Base 3.5.0-1 + nfnl_log_alloc@libnl_3 3.5.0-1 + nfnl_log_build_change_request@Base 3.5.0-1 + nfnl_log_build_change_request@libnl_3 3.5.0-1 + nfnl_log_build_create_request@Base 3.5.0-1 + nfnl_log_build_create_request@libnl_3 3.5.0-1 + nfnl_log_build_delete_request@Base 3.5.0-1 + nfnl_log_build_delete_request@libnl_3 3.5.0-1 + nfnl_log_build_pf_bind@Base 3.5.0-1 + nfnl_log_build_pf_bind@libnl_3 3.5.0-1 + nfnl_log_build_pf_unbind@Base 3.5.0-1 + nfnl_log_build_pf_unbind@libnl_3 3.5.0-1 + nfnl_log_change@Base 3.5.0-1 + nfnl_log_change@libnl_3 3.5.0-1 + nfnl_log_copy_mode2str@Base 3.5.0-1 + nfnl_log_copy_mode2str@libnl_3 3.5.0-1 + nfnl_log_create@Base 3.5.0-1 + nfnl_log_create@libnl_3 3.5.0-1 + nfnl_log_delete@Base 3.5.0-1 + nfnl_log_delete@libnl_3 3.5.0-1 + nfnl_log_flags2str@Base 3.5.0-1 + nfnl_log_flags2str@libnl_3 3.5.0-1 + nfnl_log_get@Base 3.5.0-1 + nfnl_log_get@libnl_3 3.5.0-1 + nfnl_log_get_alloc_size@Base 3.5.0-1 + nfnl_log_get_alloc_size@libnl_3 3.5.0-1 + nfnl_log_get_copy_mode@Base 3.5.0-1 + nfnl_log_get_copy_mode@libnl_3 3.5.0-1 + nfnl_log_get_copy_range@Base 3.5.0-1 + nfnl_log_get_copy_range@libnl_3 3.5.0-1 + nfnl_log_get_flush_timeout@Base 3.5.0-1 + nfnl_log_get_flush_timeout@libnl_3 3.5.0-1 + nfnl_log_get_group@Base 3.5.0-1 + nfnl_log_get_group@libnl_3 3.5.0-1 + nfnl_log_get_queue_threshold@Base 3.5.0-1 + nfnl_log_get_queue_threshold@libnl_3 3.5.0-1 + nfnl_log_msg_alloc@Base 3.5.0-1 + nfnl_log_msg_alloc@libnl_3 3.5.0-1 + nfnl_log_msg_get@Base 3.5.0-1 + nfnl_log_msg_get@libnl_3 3.5.0-1 + nfnl_log_msg_get_family@Base 3.5.0-1 + nfnl_log_msg_get_family@libnl_3 3.5.0-1 + nfnl_log_msg_get_gid@Base 3.5.0-1 + nfnl_log_msg_get_gid@libnl_3 3.5.0-1 + nfnl_log_msg_get_hook@Base 3.5.0-1 + nfnl_log_msg_get_hook@libnl_3 3.5.0-1 + nfnl_log_msg_get_hwaddr@Base 3.5.0-1 + nfnl_log_msg_get_hwaddr@libnl_3 3.5.0-1 + nfnl_log_msg_get_hwproto@Base 3.5.0-1 + nfnl_log_msg_get_hwproto@libnl_3 3.5.0-1 + nfnl_log_msg_get_indev@Base 3.5.0-1 + nfnl_log_msg_get_indev@libnl_3 3.5.0-1 + nfnl_log_msg_get_mark@Base 3.5.0-1 + nfnl_log_msg_get_mark@libnl_3 3.5.0-1 + nfnl_log_msg_get_outdev@Base 3.5.0-1 + nfnl_log_msg_get_outdev@libnl_3 3.5.0-1 + nfnl_log_msg_get_payload@Base 3.5.0-1 + nfnl_log_msg_get_payload@libnl_3 3.5.0-1 + nfnl_log_msg_get_physindev@Base 3.5.0-1 + nfnl_log_msg_get_physindev@libnl_3 3.5.0-1 + nfnl_log_msg_get_physoutdev@Base 3.5.0-1 + nfnl_log_msg_get_physoutdev@libnl_3 3.5.0-1 + nfnl_log_msg_get_prefix@Base 3.5.0-1 + nfnl_log_msg_get_prefix@libnl_3 3.5.0-1 + nfnl_log_msg_get_seq@Base 3.5.0-1 + nfnl_log_msg_get_seq@libnl_3 3.5.0-1 + nfnl_log_msg_get_seq_global@Base 3.5.0-1 + nfnl_log_msg_get_seq_global@libnl_3 3.5.0-1 + nfnl_log_msg_get_timestamp@Base 3.5.0-1 + nfnl_log_msg_get_timestamp@libnl_3 3.5.0-1 + nfnl_log_msg_get_uid@Base 3.5.0-1 + nfnl_log_msg_get_uid@libnl_3 3.5.0-1 + nfnl_log_msg_put@Base 3.5.0-1 + nfnl_log_msg_put@libnl_3 3.5.0-1 + nfnl_log_msg_set_family@Base 3.5.0-1 + nfnl_log_msg_set_family@libnl_3 3.5.0-1 + nfnl_log_msg_set_gid@Base 3.5.0-1 + nfnl_log_msg_set_gid@libnl_3 3.5.0-1 + nfnl_log_msg_set_hook@Base 3.5.0-1 + nfnl_log_msg_set_hook@libnl_3 3.5.0-1 + nfnl_log_msg_set_hwaddr@Base 3.5.0-1 + nfnl_log_msg_set_hwaddr@libnl_3 3.5.0-1 + nfnl_log_msg_set_hwproto@Base 3.5.0-1 + nfnl_log_msg_set_hwproto@libnl_3 3.5.0-1 + nfnl_log_msg_set_indev@Base 3.5.0-1 + nfnl_log_msg_set_indev@libnl_3 3.5.0-1 + nfnl_log_msg_set_mark@Base 3.5.0-1 + nfnl_log_msg_set_mark@libnl_3 3.5.0-1 + nfnl_log_msg_set_outdev@Base 3.5.0-1 + nfnl_log_msg_set_outdev@libnl_3 3.5.0-1 + nfnl_log_msg_set_payload@Base 3.5.0-1 + nfnl_log_msg_set_payload@libnl_3 3.5.0-1 + nfnl_log_msg_set_physindev@Base 3.5.0-1 + nfnl_log_msg_set_physindev@libnl_3 3.5.0-1 + nfnl_log_msg_set_physoutdev@Base 3.5.0-1 + nfnl_log_msg_set_physoutdev@libnl_3 3.5.0-1 + nfnl_log_msg_set_prefix@Base 3.5.0-1 + nfnl_log_msg_set_prefix@libnl_3 3.5.0-1 + nfnl_log_msg_set_seq@Base 3.5.0-1 + nfnl_log_msg_set_seq@libnl_3 3.5.0-1 + nfnl_log_msg_set_seq_global@Base 3.5.0-1 + nfnl_log_msg_set_seq_global@libnl_3 3.5.0-1 + nfnl_log_msg_set_timestamp@Base 3.5.0-1 + nfnl_log_msg_set_timestamp@libnl_3 3.5.0-1 + nfnl_log_msg_set_uid@Base 3.5.0-1 + nfnl_log_msg_set_uid@libnl_3 3.5.0-1 + nfnl_log_msg_test_gid@Base 3.5.0-1 + nfnl_log_msg_test_gid@libnl_3 3.5.0-1 + nfnl_log_msg_test_hook@Base 3.5.0-1 + nfnl_log_msg_test_hook@libnl_3 3.5.0-1 + nfnl_log_msg_test_hwproto@Base 3.5.0-1 + nfnl_log_msg_test_hwproto@libnl_3 3.5.0-1 + nfnl_log_msg_test_mark@Base 3.5.0-1 + nfnl_log_msg_test_mark@libnl_3 3.5.0-1 + nfnl_log_msg_test_seq@Base 3.5.0-1 + nfnl_log_msg_test_seq@libnl_3 3.5.0-1 + nfnl_log_msg_test_seq_global@Base 3.5.0-1 + nfnl_log_msg_test_seq_global@libnl_3 3.5.0-1 + nfnl_log_msg_test_uid@Base 3.5.0-1 + nfnl_log_msg_test_uid@libnl_3 3.5.0-1 + nfnl_log_pf_bind@Base 3.5.0-1 + nfnl_log_pf_bind@libnl_3 3.5.0-1 + nfnl_log_pf_unbind@Base 3.5.0-1 + nfnl_log_pf_unbind@libnl_3 3.5.0-1 + nfnl_log_put@Base 3.5.0-1 + nfnl_log_put@libnl_3 3.5.0-1 + nfnl_log_set_alloc_size@Base 3.5.0-1 + nfnl_log_set_alloc_size@libnl_3 3.5.0-1 + nfnl_log_set_copy_mode@Base 3.5.0-1 + nfnl_log_set_copy_mode@libnl_3 3.5.0-1 + nfnl_log_set_copy_range@Base 3.5.0-1 + nfnl_log_set_copy_range@libnl_3 3.5.0-1 + nfnl_log_set_flags@Base 3.5.0-1 + nfnl_log_set_flags@libnl_3 3.5.0-1 + nfnl_log_set_flush_timeout@Base 3.5.0-1 + nfnl_log_set_flush_timeout@libnl_3 3.5.0-1 + nfnl_log_set_group@Base 3.5.0-1 + nfnl_log_set_group@libnl_3 3.5.0-1 + nfnl_log_set_queue_threshold@Base 3.5.0-1 + nfnl_log_set_queue_threshold@libnl_3 3.5.0-1 + nfnl_log_str2copy_mode@Base 3.5.0-1 + nfnl_log_str2copy_mode@libnl_3 3.5.0-1 + nfnl_log_str2flags@Base 3.5.0-1 + nfnl_log_str2flags@libnl_3 3.5.0-1 + nfnl_log_test_alloc_size@Base 3.5.0-1 + nfnl_log_test_alloc_size@libnl_3 3.5.0-1 + nfnl_log_test_copy_mode@Base 3.5.0-1 + nfnl_log_test_copy_mode@libnl_3 3.5.0-1 + nfnl_log_test_copy_range@Base 3.5.0-1 + nfnl_log_test_copy_range@libnl_3 3.5.0-1 + nfnl_log_test_flush_timeout@Base 3.5.0-1 + nfnl_log_test_flush_timeout@libnl_3 3.5.0-1 + nfnl_log_test_group@Base 3.5.0-1 + nfnl_log_test_group@libnl_3 3.5.0-1 + nfnl_log_test_queue_threshold@Base 3.5.0-1 + nfnl_log_test_queue_threshold@libnl_3 3.5.0-1 + nfnl_log_unset_flags@Base 3.5.0-1 + nfnl_log_unset_flags@libnl_3 3.5.0-1 + nfnl_queue_alloc@Base 3.5.0-1 + nfnl_queue_alloc@libnl_3 3.5.0-1 + nfnl_queue_build_change_request@Base 3.5.0-1 + nfnl_queue_build_change_request@libnl_3 3.5.0-1 + nfnl_queue_build_create_request@Base 3.5.0-1 + nfnl_queue_build_create_request@libnl_3 3.5.0-1 + nfnl_queue_build_delete_request@Base 3.5.0-1 + nfnl_queue_build_delete_request@libnl_3 3.5.0-1 + nfnl_queue_build_pf_bind@Base 3.5.0-1 + nfnl_queue_build_pf_bind@libnl_3 3.5.0-1 + nfnl_queue_build_pf_unbind@Base 3.5.0-1 + nfnl_queue_build_pf_unbind@libnl_3 3.5.0-1 + nfnl_queue_change@Base 3.5.0-1 + nfnl_queue_change@libnl_3 3.5.0-1 + nfnl_queue_copy_mode2str@Base 3.5.0-1 + nfnl_queue_copy_mode2str@libnl_3 3.5.0-1 + nfnl_queue_create@Base 3.5.0-1 + nfnl_queue_create@libnl_3 3.5.0-1 + nfnl_queue_delete@Base 3.5.0-1 + nfnl_queue_delete@libnl_3 3.5.0-1 + nfnl_queue_get@Base 3.5.0-1 + nfnl_queue_get@libnl_3 3.5.0-1 + nfnl_queue_get_copy_mode@Base 3.5.0-1 + nfnl_queue_get_copy_mode@libnl_3 3.5.0-1 + nfnl_queue_get_copy_range@Base 3.5.0-1 + nfnl_queue_get_copy_range@libnl_3 3.5.0-1 + nfnl_queue_get_group@Base 3.5.0-1 + nfnl_queue_get_group@libnl_3 3.5.0-1 + nfnl_queue_get_maxlen@Base 3.5.0-1 + nfnl_queue_get_maxlen@libnl_3 3.5.0-1 + nfnl_queue_msg_alloc@Base 3.5.0-1 + nfnl_queue_msg_alloc@libnl_3 3.5.0-1 + nfnl_queue_msg_build_verdict@Base 3.5.0-1 + nfnl_queue_msg_build_verdict@libnl_3 3.5.0-1 + nfnl_queue_msg_build_verdict_batch@Base 3.5.0-1 + nfnl_queue_msg_build_verdict_batch@libnl_3 3.5.0-1 + nfnl_queue_msg_get@Base 3.5.0-1 + nfnl_queue_msg_get@libnl_3 3.5.0-1 + nfnl_queue_msg_get_family@Base 3.5.0-1 + nfnl_queue_msg_get_family@libnl_3 3.5.0-1 + nfnl_queue_msg_get_group@Base 3.5.0-1 + nfnl_queue_msg_get_group@libnl_3 3.5.0-1 + nfnl_queue_msg_get_hook@Base 3.5.0-1 + nfnl_queue_msg_get_hook@libnl_3 3.5.0-1 + nfnl_queue_msg_get_hwaddr@Base 3.5.0-1 + nfnl_queue_msg_get_hwaddr@libnl_3 3.5.0-1 + nfnl_queue_msg_get_hwproto@Base 3.5.0-1 + nfnl_queue_msg_get_hwproto@libnl_3 3.5.0-1 + nfnl_queue_msg_get_indev@Base 3.5.0-1 + nfnl_queue_msg_get_indev@libnl_3 3.5.0-1 + nfnl_queue_msg_get_mark@Base 3.5.0-1 + nfnl_queue_msg_get_mark@libnl_3 3.5.0-1 + nfnl_queue_msg_get_outdev@Base 3.5.0-1 + nfnl_queue_msg_get_outdev@libnl_3 3.5.0-1 + nfnl_queue_msg_get_packetid@Base 3.5.0-1 + nfnl_queue_msg_get_packetid@libnl_3 3.5.0-1 + nfnl_queue_msg_get_payload@Base 3.5.0-1 + nfnl_queue_msg_get_payload@libnl_3 3.5.0-1 + nfnl_queue_msg_get_physindev@Base 3.5.0-1 + nfnl_queue_msg_get_physindev@libnl_3 3.5.0-1 + nfnl_queue_msg_get_physoutdev@Base 3.5.0-1 + nfnl_queue_msg_get_physoutdev@libnl_3 3.5.0-1 + nfnl_queue_msg_get_timestamp@Base 3.5.0-1 + nfnl_queue_msg_get_timestamp@libnl_3 3.5.0-1 + nfnl_queue_msg_get_verdict@Base 3.5.0-1 + nfnl_queue_msg_get_verdict@libnl_3 3.5.0-1 + nfnl_queue_msg_put@Base 3.5.0-1 + nfnl_queue_msg_put@libnl_3 3.5.0-1 + nfnl_queue_msg_send_verdict@Base 3.5.0-1 + nfnl_queue_msg_send_verdict@libnl_3 3.5.0-1 + nfnl_queue_msg_send_verdict_batch@Base 3.5.0-1 + nfnl_queue_msg_send_verdict_batch@libnl_3 3.5.0-1 + nfnl_queue_msg_send_verdict_payload@Base 3.5.0-1 + nfnl_queue_msg_send_verdict_payload@libnl_3 3.5.0-1 + nfnl_queue_msg_set_family@Base 3.5.0-1 + nfnl_queue_msg_set_family@libnl_3 3.5.0-1 + nfnl_queue_msg_set_group@Base 3.5.0-1 + nfnl_queue_msg_set_group@libnl_3 3.5.0-1 + nfnl_queue_msg_set_hook@Base 3.5.0-1 + nfnl_queue_msg_set_hook@libnl_3 3.5.0-1 + nfnl_queue_msg_set_hwaddr@Base 3.5.0-1 + nfnl_queue_msg_set_hwaddr@libnl_3 3.5.0-1 + nfnl_queue_msg_set_hwproto@Base 3.5.0-1 + nfnl_queue_msg_set_hwproto@libnl_3 3.5.0-1 + nfnl_queue_msg_set_indev@Base 3.5.0-1 + nfnl_queue_msg_set_indev@libnl_3 3.5.0-1 + nfnl_queue_msg_set_mark@Base 3.5.0-1 + nfnl_queue_msg_set_mark@libnl_3 3.5.0-1 + nfnl_queue_msg_set_outdev@Base 3.5.0-1 + nfnl_queue_msg_set_outdev@libnl_3 3.5.0-1 + nfnl_queue_msg_set_packetid@Base 3.5.0-1 + nfnl_queue_msg_set_packetid@libnl_3 3.5.0-1 + nfnl_queue_msg_set_payload@Base 3.5.0-1 + nfnl_queue_msg_set_payload@libnl_3 3.5.0-1 + nfnl_queue_msg_set_physindev@Base 3.5.0-1 + nfnl_queue_msg_set_physindev@libnl_3 3.5.0-1 + nfnl_queue_msg_set_physoutdev@Base 3.5.0-1 + nfnl_queue_msg_set_physoutdev@libnl_3 3.5.0-1 + nfnl_queue_msg_set_timestamp@Base 3.5.0-1 + nfnl_queue_msg_set_timestamp@libnl_3 3.5.0-1 + nfnl_queue_msg_set_verdict@Base 3.5.0-1 + nfnl_queue_msg_set_verdict@libnl_3 3.5.0-1 + nfnl_queue_msg_test_family@Base 3.5.0-1 + nfnl_queue_msg_test_family@libnl_3 3.5.0-1 + nfnl_queue_msg_test_group@Base 3.5.0-1 + nfnl_queue_msg_test_group@libnl_3 3.5.0-1 + nfnl_queue_msg_test_hook@Base 3.5.0-1 + nfnl_queue_msg_test_hook@libnl_3 3.5.0-1 + nfnl_queue_msg_test_hwaddr@Base 3.5.0-1 + nfnl_queue_msg_test_hwaddr@libnl_3 3.5.0-1 + nfnl_queue_msg_test_hwproto@Base 3.5.0-1 + nfnl_queue_msg_test_hwproto@libnl_3 3.5.0-1 + nfnl_queue_msg_test_indev@Base 3.5.0-1 + nfnl_queue_msg_test_indev@libnl_3 3.5.0-1 + nfnl_queue_msg_test_mark@Base 3.5.0-1 + nfnl_queue_msg_test_mark@libnl_3 3.5.0-1 + nfnl_queue_msg_test_outdev@Base 3.5.0-1 + nfnl_queue_msg_test_outdev@libnl_3 3.5.0-1 + nfnl_queue_msg_test_packetid@Base 3.5.0-1 + nfnl_queue_msg_test_packetid@libnl_3 3.5.0-1 + nfnl_queue_msg_test_payload@Base 3.5.0-1 + nfnl_queue_msg_test_payload@libnl_3 3.5.0-1 + nfnl_queue_msg_test_physindev@Base 3.5.0-1 + nfnl_queue_msg_test_physindev@libnl_3 3.5.0-1 + nfnl_queue_msg_test_physoutdev@Base 3.5.0-1 + nfnl_queue_msg_test_physoutdev@libnl_3 3.5.0-1 + nfnl_queue_msg_test_timestamp@Base 3.5.0-1 + nfnl_queue_msg_test_timestamp@libnl_3 3.5.0-1 + nfnl_queue_msg_test_verdict@Base 3.5.0-1 + nfnl_queue_msg_test_verdict@libnl_3 3.5.0-1 + nfnl_queue_pf_bind@Base 3.5.0-1 + nfnl_queue_pf_bind@libnl_3 3.5.0-1 + nfnl_queue_pf_unbind@Base 3.5.0-1 + nfnl_queue_pf_unbind@libnl_3 3.5.0-1 + nfnl_queue_put@Base 3.5.0-1 + nfnl_queue_put@libnl_3 3.5.0-1 + nfnl_queue_set_copy_mode@Base 3.5.0-1 + nfnl_queue_set_copy_mode@libnl_3 3.5.0-1 + nfnl_queue_set_copy_range@Base 3.5.0-1 + nfnl_queue_set_copy_range@libnl_3 3.5.0-1 + nfnl_queue_set_group@Base 3.5.0-1 + nfnl_queue_set_group@libnl_3 3.5.0-1 + nfnl_queue_set_maxlen@Base 3.5.0-1 + nfnl_queue_set_maxlen@libnl_3 3.5.0-1 + nfnl_queue_socket_alloc@Base 3.5.0-1 + nfnl_queue_socket_alloc@libnl_3 3.5.0-1 + nfnl_queue_str2copy_mode@Base 3.5.0-1 + nfnl_queue_str2copy_mode@libnl_3 3.5.0-1 + nfnl_queue_test_copy_mode@Base 3.5.0-1 + nfnl_queue_test_copy_mode@libnl_3 3.5.0-1 + nfnl_queue_test_copy_range@Base 3.5.0-1 + nfnl_queue_test_copy_range@libnl_3 3.5.0-1 + nfnl_queue_test_group@Base 3.5.0-1 + nfnl_queue_test_group@libnl_3 3.5.0-1 + nfnl_queue_test_maxlen@Base 3.5.0-1 + nfnl_queue_test_maxlen@libnl_3 3.5.0-1 + nfnl_send_simple@Base 3.5.0-1 + nfnl_send_simple@libnl_3 3.5.0-1 + nfnl_str2inet_hook@Base 3.5.0-1 + nfnl_str2inet_hook@libnl_3 3.5.0-1 + nfnl_str2verdict@Base 3.5.0-1 + nfnl_str2verdict@libnl_3 3.5.0-1 + nfnl_verdict2str@Base 3.5.0-1 + nfnl_verdict2str@libnl_3 3.5.0-1 + nfnlmsg_alloc_simple@Base 3.5.0-1 + nfnlmsg_alloc_simple@libnl_3 3.5.0-1 + nfnlmsg_ct_group@Base 3.5.0-1 + nfnlmsg_ct_group@libnl_3 3.5.0-1 + nfnlmsg_ct_parse@Base 3.5.0-1 + nfnlmsg_ct_parse@libnl_3 3.5.0-1 + nfnlmsg_exp_group@Base 3.5.0-1 + nfnlmsg_exp_group@libnl_3 3.5.0-1 + nfnlmsg_exp_parse@Base 3.5.0-1 + nfnlmsg_exp_parse@libnl_3 3.5.0-1 + nfnlmsg_family@Base 3.5.0-1 + nfnlmsg_family@libnl_3 3.5.0-1 + nfnlmsg_log_msg_parse@Base 3.5.0-1 + nfnlmsg_log_msg_parse@libnl_3 3.5.0-1 + nfnlmsg_put@Base 3.5.0-1 + nfnlmsg_put@libnl_3 3.5.0-1 + nfnlmsg_queue_msg_parse@Base 3.5.0-1 + nfnlmsg_queue_msg_parse@libnl_3 3.5.0-1 + nfnlmsg_res_id@Base 3.5.0-1 + nfnlmsg_res_id@libnl_3 3.5.0-1 + nfnlmsg_subsys@Base 3.5.0-1 + nfnlmsg_subsys@libnl_3 3.5.0-1 + nfnlmsg_subtype@Base 3.5.0-1 + nfnlmsg_subtype@libnl_3 3.5.0-1 + queue_msg_obj_ops@Base 3.5.0-1 + queue_msg_obj_ops@libnl_3 3.5.0-1 + queue_obj_ops@Base 3.5.0-1 + queue_obj_ops@libnl_3 3.5.0-1 diff --git a/src/libnl3/debian/libnl-nf-3-dev.install b/src/libnl3/debian/libnl-nf-3-dev.install new file mode 100644 index 000000000000..d1307c751b84 --- /dev/null +++ b/src/libnl3/debian/libnl-nf-3-dev.install @@ -0,0 +1,3 @@ +debian/tmp/usr/lib/*/pkgconfig/libnl-nf-3* +debian/tmp/usr/lib/*/libnl-nf-3*.so +debian/tmp/usr/lib/*/libnl-nf-3*.a diff --git a/src/libnl3/debian/libnl-route-3-200.install b/src/libnl3/debian/libnl-route-3-200.install new file mode 100644 index 000000000000..44c7ec8cdfad --- /dev/null +++ b/src/libnl3/debian/libnl-route-3-200.install @@ -0,0 +1 @@ +debian/tmp/usr/lib/*/libnl-route-3*.so.* diff --git a/src/libnl3/debian/libnl-route-3-200.symbols b/src/libnl3/debian/libnl-route-3-200.symbols new file mode 100644 index 000000000000..e11157ba4e88 --- /dev/null +++ b/src/libnl3/debian/libnl-route-3-200.symbols @@ -0,0 +1,2051 @@ +libnl-route-3.so.200 libnl-route-3-200 #MINVER# + ematch__create_buffer@Base 3.5.0-1 + ematch__delete_buffer@Base 3.5.0-1 + ematch__flush_buffer@Base 3.5.0-1 + ematch__scan_buffer@Base 3.5.0-1 + ematch__scan_bytes@Base 3.5.0-1 + ematch__scan_string@Base 3.5.0-1 + ematch__switch_to_buffer@Base 3.5.0-1 + ematch_alloc@Base 3.5.0-1 + ematch_free@Base 3.5.0-1 + ematch_get_column@Base 3.5.0-1 + ematch_get_debug@Base 3.5.0-1 + ematch_get_extra@Base 3.5.0-1 + ematch_get_in@Base 3.5.0-1 + ematch_get_leng@Base 3.5.0-1 + ematch_get_lineno@Base 3.5.0-1 + ematch_get_lval@Base 3.5.0-1 + ematch_get_out@Base 3.5.0-1 + ematch_get_text@Base 3.5.0-1 + ematch_lex@Base 3.5.0-1 + ematch_lex_destroy@Base 3.5.0-1 + ematch_lex_init@Base 3.5.0-1 + ematch_lex_init_extra@Base 3.5.0-1 + ematch_parse@Base 3.5.0-1 + ematch_pop_buffer_state@Base 3.5.0-1 + ematch_push_buffer_state@Base 3.5.0-1 + ematch_realloc@Base 3.5.0-1 + ematch_restart@Base 3.5.0-1 + ematch_set_column@Base 3.5.0-1 + ematch_set_debug@Base 3.5.0-1 + ematch_set_extra@Base 3.5.0-1 + ematch_set_in@Base 3.5.0-1 + ematch_set_lineno@Base 3.5.0-1 + ematch_set_lval@Base 3.5.0-1 + ematch_set_out@Base 3.5.0-1 + flnl_lookup@Base 3.5.0-1 + flnl_lookup@libnl_3 3.5.0-1 + flnl_lookup_build_request@Base 3.5.0-1 + flnl_lookup_build_request@libnl_3 3.5.0-1 + flnl_request_alloc@Base 3.5.0-1 + flnl_request_alloc@libnl_3 3.5.0-1 + flnl_request_get_addr@Base 3.5.0-1 + flnl_request_get_addr@libnl_3 3.5.0-1 + flnl_request_get_fwmark@Base 3.5.0-1 + flnl_request_get_fwmark@libnl_3 3.5.0-1 + flnl_request_get_scope@Base 3.5.0-1 + flnl_request_get_scope@libnl_3 3.5.0-1 + flnl_request_get_table@Base 3.5.0-1 + flnl_request_get_table@libnl_3 3.5.0-1 + flnl_request_get_tos@Base 3.5.0-1 + flnl_request_get_tos@libnl_3 3.5.0-1 + flnl_request_set_addr@Base 3.5.0-1 + flnl_request_set_addr@libnl_3 3.5.0-1 + flnl_request_set_fwmark@Base 3.5.0-1 + flnl_request_set_fwmark@libnl_3 3.5.0-1 + flnl_request_set_scope@Base 3.5.0-1 + flnl_request_set_scope@libnl_3 3.5.0-1 + flnl_request_set_table@Base 3.5.0-1 + flnl_request_set_table@libnl_3 3.5.0-1 + flnl_request_set_tos@Base 3.5.0-1 + flnl_request_set_tos@libnl_3 3.5.0-1 + flnl_result_alloc@Base 3.5.0-1 + flnl_result_alloc@libnl_3 3.5.0-1 + flnl_result_alloc_cache@Base 3.5.0-1 + flnl_result_alloc_cache@libnl_3 3.5.0-1 + flnl_result_get_error@Base 3.5.0-1 + flnl_result_get_error@libnl_3 3.5.0-1 + flnl_result_get_nexthop_sel@Base 3.5.0-1 + flnl_result_get_nexthop_sel@libnl_3 3.5.0-1 + flnl_result_get_prefixlen@Base 3.5.0-1 + flnl_result_get_prefixlen@libnl_3 3.5.0-1 + flnl_result_get_scope@Base 3.5.0-1 + flnl_result_get_scope@libnl_3 3.5.0-1 + flnl_result_get_table_id@Base 3.5.0-1 + flnl_result_get_table_id@libnl_3 3.5.0-1 + flnl_result_get_type@Base 3.5.0-1 + flnl_result_get_type@libnl_3 3.5.0-1 + flnl_result_put@Base 3.5.0-1 + flnl_result_put@libnl_3 3.5.0-1 + libnl_3@libnl_3 3.5.0-1 + libnl_3_2_26@libnl_3_2_26 3.5.0-1 + libnl_3_2_27@libnl_3_2_27 3.5.0-1 + libnl_3_2_28@libnl_3_2_28 3.5.0-1 + libnl_3_2_29@libnl_3_2_29 3.5.0-1 + libnl_3_4@libnl_3_4 3.5.0-1 + libnl_3_5@libnl_3_5 3.5.0-1 + nl_ovl_strategy2str@Base 3.5.0-1 + nl_ovl_strategy2str@libnl_3 3.5.0-1 + nl_police2str@Base 3.5.0-1 + nl_police2str@libnl_3 3.5.0-1 + nl_rtgen_request@Base 3.5.0-1 + nl_rtgen_request@libnl_3 3.5.0-1 + nl_rtntype2str@Base 3.5.0-1 + nl_rtntype2str@libnl_3 3.5.0-1 + nl_str2ovl_strategy@Base 3.5.0-1 + nl_str2ovl_strategy@libnl_3 3.5.0-1 + nl_str2police@Base 3.5.0-1 + nl_str2police@libnl_3 3.5.0-1 + nl_str2rtntype@Base 3.5.0-1 + nl_str2rtntype@libnl_3 3.5.0-1 + pktloc__create_buffer@Base 3.5.0-1 + pktloc__delete_buffer@Base 3.5.0-1 + pktloc__flush_buffer@Base 3.5.0-1 + pktloc__scan_buffer@Base 3.5.0-1 + pktloc__scan_bytes@Base 3.5.0-1 + pktloc__scan_string@Base 3.5.0-1 + pktloc__switch_to_buffer@Base 3.5.0-1 + pktloc_alloc@Base 3.5.0-1 + pktloc_free@Base 3.5.0-1 + pktloc_get_column@Base 3.5.0-1 + pktloc_get_debug@Base 3.5.0-1 + pktloc_get_extra@Base 3.5.0-1 + pktloc_get_in@Base 3.5.0-1 + pktloc_get_leng@Base 3.5.0-1 + pktloc_get_lineno@Base 3.5.0-1 + pktloc_get_lloc@Base 3.5.0-1 + pktloc_get_lval@Base 3.5.0-1 + pktloc_get_out@Base 3.5.0-1 + pktloc_get_text@Base 3.5.0-1 + pktloc_lex@Base 3.5.0-1 + pktloc_lex_destroy@Base 3.5.0-1 + pktloc_lex_init@Base 3.5.0-1 + pktloc_lex_init_extra@Base 3.5.0-1 + pktloc_parse@Base 3.5.0-1 + pktloc_pop_buffer_state@Base 3.5.0-1 + pktloc_push_buffer_state@Base 3.5.0-1 + pktloc_realloc@Base 3.5.0-1 + pktloc_restart@Base 3.5.0-1 + pktloc_set_column@Base 3.5.0-1 + pktloc_set_debug@Base 3.5.0-1 + pktloc_set_extra@Base 3.5.0-1 + pktloc_set_in@Base 3.5.0-1 + pktloc_set_lineno@Base 3.5.0-1 + pktloc_set_lloc@Base 3.5.0-1 + + pktloc_set_lval@Base 3.5.0-1 + pktloc_set_out@Base 3.5.0-1 + route_obj_ops@Base 3.5.0-1 + route_obj_ops@libnl_3 3.5.0-1 + rtln_link_policy@Base 3.5.0-1 + rtln_link_policy@libnl_3 3.5.0-1 + rtnl_act_add@Base 3.5.0-1 + rtnl_act_add@libnl_3 3.5.0-1 + rtnl_act_alloc@Base 3.5.0-1 + rtnl_act_alloc@libnl_3 3.5.0-1 + rtnl_act_append@Base 3.5.0-1 + rtnl_act_append@libnl_3 3.5.0-1 + rtnl_act_build_add_request@Base 3.5.0-1 + rtnl_act_build_add_request@libnl_3 3.5.0-1 + rtnl_act_build_change_request@Base 3.5.0-1 + rtnl_act_build_change_request@libnl_3 3.5.0-1 + rtnl_act_build_delete_request@Base 3.5.0-1 + rtnl_act_build_delete_request@libnl_3 3.5.0-1 + rtnl_act_change@Base 3.5.0-1 + rtnl_act_change@libnl_3 3.5.0-1 + rtnl_act_delete@Base 3.5.0-1 + rtnl_act_delete@libnl_3 3.5.0-1 + rtnl_act_fill@Base 3.5.0-1 + rtnl_act_fill@libnl_3 3.5.0-1 + rtnl_act_get@Base 3.5.0-1 + rtnl_act_get@libnl_3 3.5.0-1 + rtnl_act_next@libnl_3_4 3.5.0-1 + rtnl_act_parse@Base 3.5.0-1 + rtnl_act_parse@libnl_3 3.5.0-1 + rtnl_act_put@Base 3.5.0-1 + rtnl_act_put@libnl_3 3.5.0-1 + rtnl_act_put_all@Base 3.5.0-1 + rtnl_act_put_all@libnl_3 3.5.0-1 + rtnl_act_remove@Base 3.5.0-1 + rtnl_act_remove@libnl_3 3.5.0-1 + rtnl_addr_add@Base 3.5.0-1 + rtnl_addr_add@libnl_3 3.5.0-1 + rtnl_addr_alloc@Base 3.5.0-1 + rtnl_addr_alloc@libnl_3 3.5.0-1 + rtnl_addr_alloc_cache@Base 3.5.0-1 + rtnl_addr_alloc_cache@libnl_3 3.5.0-1 + rtnl_addr_build_add_request@Base 3.5.0-1 + rtnl_addr_build_add_request@libnl_3 3.5.0-1 + rtnl_addr_build_delete_request@Base 3.5.0-1 + rtnl_addr_build_delete_request@libnl_3 3.5.0-1 + rtnl_addr_delete@Base 3.5.0-1 + rtnl_addr_delete@libnl_3 3.5.0-1 + rtnl_addr_flags2str@Base 3.5.0-1 + rtnl_addr_flags2str@libnl_3 3.5.0-1 + rtnl_addr_get@Base 3.5.0-1 + rtnl_addr_get@libnl_3 3.5.0-1 + rtnl_addr_get_anycast@Base 3.5.0-1 + rtnl_addr_get_anycast@libnl_3 3.5.0-1 + rtnl_addr_get_broadcast@Base 3.5.0-1 + rtnl_addr_get_broadcast@libnl_3 3.5.0-1 + rtnl_addr_get_create_time@Base 3.5.0-1 + rtnl_addr_get_create_time@libnl_3 3.5.0-1 + rtnl_addr_get_family@Base 3.5.0-1 + rtnl_addr_get_family@libnl_3 3.5.0-1 + rtnl_addr_get_flags@Base 3.5.0-1 + rtnl_addr_get_flags@libnl_3 3.5.0-1 + rtnl_addr_get_ifindex@Base 3.5.0-1 + rtnl_addr_get_ifindex@libnl_3 3.5.0-1 + rtnl_addr_get_label@Base 3.5.0-1 + rtnl_addr_get_label@libnl_3 3.5.0-1 + rtnl_addr_get_last_update_time@Base 3.5.0-1 + rtnl_addr_get_last_update_time@libnl_3 3.5.0-1 + rtnl_addr_get_link@Base 3.5.0-1 + rtnl_addr_get_link@libnl_3 3.5.0-1 + rtnl_addr_get_local@Base 3.5.0-1 + rtnl_addr_get_local@libnl_3 3.5.0-1 + rtnl_addr_get_multicast@Base 3.5.0-1 + rtnl_addr_get_multicast@libnl_3 3.5.0-1 + rtnl_addr_get_peer@Base 3.5.0-1 + rtnl_addr_get_peer@libnl_3 3.5.0-1 + rtnl_addr_get_preferred_lifetime@Base 3.5.0-1 + rtnl_addr_get_preferred_lifetime@libnl_3 3.5.0-1 + rtnl_addr_get_prefixlen@Base 3.5.0-1 + rtnl_addr_get_prefixlen@libnl_3 3.5.0-1 + rtnl_addr_get_scope@Base 3.5.0-1 + rtnl_addr_get_scope@libnl_3 3.5.0-1 + rtnl_addr_get_valid_lifetime@Base 3.5.0-1 + rtnl_addr_get_valid_lifetime@libnl_3 3.5.0-1 + rtnl_addr_put@Base 3.5.0-1 + rtnl_addr_put@libnl_3 3.5.0-1 + rtnl_addr_set_anycast@Base 3.5.0-1 + rtnl_addr_set_anycast@libnl_3 3.5.0-1 + rtnl_addr_set_broadcast@Base 3.5.0-1 + rtnl_addr_set_broadcast@libnl_3 3.5.0-1 + rtnl_addr_set_family@Base 3.5.0-1 + rtnl_addr_set_family@libnl_3 3.5.0-1 + rtnl_addr_set_flags@Base 3.5.0-1 + rtnl_addr_set_flags@libnl_3 3.5.0-1 + rtnl_addr_set_ifindex@Base 3.5.0-1 + rtnl_addr_set_ifindex@libnl_3 3.5.0-1 + rtnl_addr_set_label@Base 3.5.0-1 + rtnl_addr_set_label@libnl_3 3.5.0-1 + rtnl_addr_set_link@Base 3.5.0-1 + rtnl_addr_set_link@libnl_3 3.5.0-1 + rtnl_addr_set_local@Base 3.5.0-1 + rtnl_addr_set_local@libnl_3 3.5.0-1 + rtnl_addr_set_multicast@Base 3.5.0-1 + rtnl_addr_set_multicast@libnl_3 3.5.0-1 + rtnl_addr_set_peer@Base 3.5.0-1 + rtnl_addr_set_peer@libnl_3 3.5.0-1 + rtnl_addr_set_preferred_lifetime@Base 3.5.0-1 + rtnl_addr_set_preferred_lifetime@libnl_3 3.5.0-1 + rtnl_addr_set_prefixlen@Base 3.5.0-1 + rtnl_addr_set_prefixlen@libnl_3 3.5.0-1 + rtnl_addr_set_scope@Base 3.5.0-1 + rtnl_addr_set_scope@libnl_3 3.5.0-1 + rtnl_addr_set_valid_lifetime@Base 3.5.0-1 + rtnl_addr_set_valid_lifetime@libnl_3 3.5.0-1 + rtnl_addr_str2flags@Base 3.5.0-1 + rtnl_addr_str2flags@libnl_3 3.5.0-1 + rtnl_addr_unset_flags@Base 3.5.0-1 + rtnl_addr_unset_flags@libnl_3 3.5.0-1 + rtnl_basic_add_action@Base 3.5.0-1 + rtnl_basic_add_action@libnl_3 3.5.0-1 + rtnl_basic_del_action@Base 3.5.0-1 + rtnl_basic_del_action@libnl_3 3.5.0-1 + rtnl_basic_get_action@libnl_3_4 3.5.0-1 + rtnl_basic_get_ematch@Base 3.5.0-1 + rtnl_basic_get_ematch@libnl_3 3.5.0-1 + rtnl_basic_get_target@Base 3.5.0-1 + rtnl_basic_get_target@libnl_3 3.5.0-1 + rtnl_basic_set_ematch@Base 3.5.0-1 + rtnl_basic_set_ematch@libnl_3 3.5.0-1 + rtnl_basic_set_target@Base 3.5.0-1 + rtnl_basic_set_target@libnl_3 3.5.0-1 + rtnl_cgroup_get_ematch@Base 3.5.0-1 + rtnl_cgroup_get_ematch@libnl_3 3.5.0-1 + rtnl_cgroup_set_ematch@Base 3.5.0-1 + rtnl_cgroup_set_ematch@libnl_3 3.5.0-1 + rtnl_class_add@Base 3.5.0-1 + rtnl_class_add@libnl_3 3.5.0-1 + rtnl_class_alloc@Base 3.5.0-1 + rtnl_class_alloc@libnl_3 3.5.0-1 + rtnl_class_alloc_cache@Base 3.5.0-1 + rtnl_class_alloc_cache@libnl_3 3.5.0-1 + rtnl_class_build_add_request@Base 3.5.0-1 + rtnl_class_build_add_request@libnl_3 3.5.0-1 + rtnl_class_build_delete_request@Base 3.5.0-1 + rtnl_class_build_delete_request@libnl_3 3.5.0-1 + rtnl_class_delete@Base 3.5.0-1 + rtnl_class_delete@libnl_3 3.5.0-1 + rtnl_class_dsmark_get_bitmask@Base 3.5.0-1 + rtnl_class_dsmark_get_bitmask@libnl_3 3.5.0-1 + rtnl_class_dsmark_get_value@Base 3.5.0-1 + rtnl_class_dsmark_get_value@libnl_3 3.5.0-1 + rtnl_class_dsmark_set_bitmask@Base 3.5.0-1 + rtnl_class_dsmark_set_bitmask@libnl_3 3.5.0-1 + rtnl_class_dsmark_set_value@Base 3.5.0-1 + rtnl_class_dsmark_set_value@libnl_3 3.5.0-1 + rtnl_class_foreach_child@Base 3.5.0-1 + rtnl_class_foreach_child@libnl_3 3.5.0-1 + rtnl_class_foreach_cls@Base 3.5.0-1 + rtnl_class_foreach_cls@libnl_3 3.5.0-1 + rtnl_class_get@Base 3.5.0-1 + rtnl_class_get@libnl_3 3.5.0-1 + rtnl_class_get_by_parent@libnl_3_5 3.5.0-1 + rtnl_class_hfsc_get_fsc@Base 3.5.0-1 + rtnl_class_hfsc_get_fsc@libnl_3 3.5.0-1 + rtnl_class_hfsc_get_rsc@Base 3.5.0-1 + rtnl_class_hfsc_get_rsc@libnl_3 3.5.0-1 + rtnl_class_hfsc_get_usc@Base 3.5.0-1 + rtnl_class_hfsc_get_usc@libnl_3 3.5.0-1 + rtnl_class_hfsc_set_fsc@Base 3.5.0-1 + rtnl_class_hfsc_set_fsc@libnl_3 3.5.0-1 + rtnl_class_hfsc_set_rsc@Base 3.5.0-1 + rtnl_class_hfsc_set_rsc@libnl_3 3.5.0-1 + rtnl_class_hfsc_set_usc@Base 3.5.0-1 + rtnl_class_hfsc_set_usc@libnl_3 3.5.0-1 + rtnl_class_leaf_qdisc@Base 3.5.0-1 + rtnl_class_leaf_qdisc@libnl_3 3.5.0-1 + rtnl_class_put@Base 3.5.0-1 + rtnl_class_put@libnl_3 3.5.0-1 + rtnl_classid_generate@Base 3.5.0-1 + rtnl_classid_generate@libnl_3 3.5.0-1 + rtnl_cls_add@Base 3.5.0-1 + rtnl_cls_add@libnl_3 3.5.0-1 + rtnl_cls_alloc@Base 3.5.0-1 + rtnl_cls_alloc@libnl_3 3.5.0-1 + rtnl_cls_alloc_cache@Base 3.5.0-1 + rtnl_cls_alloc_cache@libnl_3 3.5.0-1 + rtnl_cls_build_add_request@Base 3.5.0-1 + rtnl_cls_build_add_request@libnl_3 3.5.0-1 + rtnl_cls_build_change_request@Base 3.5.0-1 + rtnl_cls_build_change_request@libnl_3 3.5.0-1 + rtnl_cls_build_delete_request@Base 3.5.0-1 + rtnl_cls_build_delete_request@libnl_3 3.5.0-1 + rtnl_cls_cache_set_tc_params@libnl_3_5 3.5.0-1 + rtnl_cls_change@Base 3.5.0-1 + rtnl_cls_change@libnl_3 3.5.0-1 + rtnl_cls_delete@Base 3.5.0-1 + rtnl_cls_delete@libnl_3 3.5.0-1 + rtnl_cls_get_prio@Base 3.5.0-1 + rtnl_cls_get_prio@libnl_3 3.5.0-1 + rtnl_cls_get_protocol@Base 3.5.0-1 + rtnl_cls_get_protocol@libnl_3 3.5.0-1 + rtnl_cls_put@Base 3.5.0-1 + rtnl_cls_put@libnl_3 3.5.0-1 + rtnl_cls_set_prio@Base 3.5.0-1 + rtnl_cls_set_prio@libnl_3 3.5.0-1 + rtnl_cls_set_protocol@Base 3.5.0-1 + rtnl_cls_set_protocol@libnl_3 3.5.0-1 + rtnl_ematch_add_child@Base 3.5.0-1 + rtnl_ematch_add_child@libnl_3 3.5.0-1 + rtnl_ematch_alloc@Base 3.5.0-1 + rtnl_ematch_alloc@libnl_3 3.5.0-1 + rtnl_ematch_cmp_get@Base 3.5.0-1 + rtnl_ematch_cmp_get@libnl_3 3.5.0-1 + rtnl_ematch_cmp_set@Base 3.5.0-1 + rtnl_ematch_cmp_set@libnl_3 3.5.0-1 + rtnl_ematch_data@Base 3.5.0-1 + rtnl_ematch_data@libnl_3 3.5.0-1 + rtnl_ematch_fill_attr@Base 3.5.0-1 + rtnl_ematch_fill_attr@libnl_3 3.5.0-1 + rtnl_ematch_free@Base 3.5.0-1 + rtnl_ematch_free@libnl_3 3.5.0-1 + rtnl_ematch_get_flags@Base 3.5.0-1 + rtnl_ematch_get_flags@libnl_3 3.5.0-1 + rtnl_ematch_lookup_ops@Base 3.5.0-1 + rtnl_ematch_lookup_ops@libnl_3 3.5.0-1 + rtnl_ematch_lookup_ops_by_name@Base 3.5.0-1 + rtnl_ematch_lookup_ops_by_name@libnl_3 3.5.0-1 + rtnl_ematch_meta_set_lvalue@Base 3.5.0-1 + rtnl_ematch_meta_set_lvalue@libnl_3 3.5.0-1 + rtnl_ematch_meta_set_operand@Base 3.5.0-1 + rtnl_ematch_meta_set_operand@libnl_3 3.5.0-1 + rtnl_ematch_meta_set_rvalue@Base 3.5.0-1 + rtnl_ematch_meta_set_rvalue@libnl_3 3.5.0-1 + rtnl_ematch_nbyte_get_layer@Base 3.5.0-1 + rtnl_ematch_nbyte_get_layer@libnl_3 3.5.0-1 + rtnl_ematch_nbyte_get_len@Base 3.5.0-1 + rtnl_ematch_nbyte_get_len@libnl_3 3.5.0-1 + rtnl_ematch_nbyte_get_offset@Base 3.5.0-1 + rtnl_ematch_nbyte_get_offset@libnl_3 3.5.0-1 + rtnl_ematch_nbyte_get_pattern@Base 3.5.0-1 + rtnl_ematch_nbyte_get_pattern@libnl_3 3.5.0-1 + rtnl_ematch_nbyte_set_offset@Base 3.5.0-1 + rtnl_ematch_nbyte_set_offset@libnl_3 3.5.0-1 + rtnl_ematch_nbyte_set_pattern@Base 3.5.0-1 + rtnl_ematch_nbyte_set_pattern@libnl_3 3.5.0-1 + rtnl_ematch_offset2txt@Base 3.5.0-1 + rtnl_ematch_offset2txt@libnl_3 3.5.0-1 + rtnl_ematch_opnd2txt@Base 3.5.0-1 + rtnl_ematch_opnd2txt@libnl_3 3.5.0-1 + rtnl_ematch_parse_attr@Base 3.5.0-1 + rtnl_ematch_parse_attr@libnl_3 3.5.0-1 + rtnl_ematch_parse_expr@Base 3.5.0-1 + rtnl_ematch_parse_expr@libnl_3 3.5.0-1 + rtnl_ematch_register@Base 3.5.0-1 + rtnl_ematch_register@libnl_3 3.5.0-1 + rtnl_ematch_set_flags@Base 3.5.0-1 + rtnl_ematch_set_flags@libnl_3 3.5.0-1 + rtnl_ematch_set_kind@Base 3.5.0-1 + rtnl_ematch_set_kind@libnl_3 3.5.0-1 + rtnl_ematch_set_name@Base 3.5.0-1 + rtnl_ematch_set_name@libnl_3 3.5.0-1 + rtnl_ematch_set_ops@Base 3.5.0-1 + rtnl_ematch_set_ops@libnl_3 3.5.0-1 + rtnl_ematch_text_get_algo@Base 3.5.0-1 + rtnl_ematch_text_get_algo@libnl_3 3.5.0-1 + rtnl_ematch_text_get_from_layer@Base 3.5.0-1 + rtnl_ematch_text_get_from_layer@libnl_3 3.5.0-1 + rtnl_ematch_text_get_from_offset@Base 3.5.0-1 + rtnl_ematch_text_get_from_offset@libnl_3 3.5.0-1 + rtnl_ematch_text_get_len@Base 3.5.0-1 + rtnl_ematch_text_get_len@libnl_3 3.5.0-1 + rtnl_ematch_text_get_pattern@Base 3.5.0-1 + rtnl_ematch_text_get_pattern@libnl_3 3.5.0-1 + rtnl_ematch_text_get_to_layer@Base 3.5.0-1 + rtnl_ematch_text_get_to_layer@libnl_3 3.5.0-1 + rtnl_ematch_text_get_to_offset@Base 3.5.0-1 + rtnl_ematch_text_get_to_offset@libnl_3 3.5.0-1 + rtnl_ematch_text_set_algo@Base 3.5.0-1 + rtnl_ematch_text_set_algo@libnl_3 3.5.0-1 + rtnl_ematch_text_set_from@Base 3.5.0-1 + rtnl_ematch_text_set_from@libnl_3 3.5.0-1 + rtnl_ematch_text_set_pattern@Base 3.5.0-1 + rtnl_ematch_text_set_pattern@libnl_3 3.5.0-1 + rtnl_ematch_text_set_to@Base 3.5.0-1 + rtnl_ematch_text_set_to@libnl_3 3.5.0-1 + rtnl_ematch_tree_add@Base 3.5.0-1 + rtnl_ematch_tree_add@libnl_3 3.5.0-1 + rtnl_ematch_tree_alloc@Base 3.5.0-1 + rtnl_ematch_tree_alloc@libnl_3 3.5.0-1 + rtnl_ematch_tree_clone@libnl_3_5 3.5.0-1 + rtnl_ematch_tree_dump@Base 3.5.0-1 + rtnl_ematch_tree_dump@libnl_3 3.5.0-1 + rtnl_ematch_tree_free@Base 3.5.0-1 + rtnl_ematch_tree_free@libnl_3 3.5.0-1 + rtnl_ematch_unlink@Base 3.5.0-1 + rtnl_ematch_unlink@libnl_3 3.5.0-1 + rtnl_ematch_unset_flags@Base 3.5.0-1 + rtnl_ematch_unset_flags@libnl_3 3.5.0-1 + rtnl_fw_set_classid@Base 3.5.0-1 + rtnl_fw_set_classid@libnl_3 3.5.0-1 + rtnl_fw_set_mask@Base 3.5.0-1 + rtnl_fw_set_mask@libnl_3 3.5.0-1 + rtnl_gact_get_action@libnl_3_2_29 3.5.0-1 + rtnl_gact_set_action@libnl_3_2_29 3.5.0-1 + rtnl_htb_get_cbuffer@Base 3.5.0-1 + rtnl_htb_get_cbuffer@libnl_3 3.5.0-1 + rtnl_htb_get_ceil64@libnl_3_5 3.5.0-1 + rtnl_htb_get_ceil@Base 3.5.0-1 + rtnl_htb_get_ceil@libnl_3 3.5.0-1 + rtnl_htb_get_defcls@Base 3.5.0-1 + rtnl_htb_get_defcls@libnl_3 3.5.0-1 + rtnl_htb_get_level@Base 3.5.0-1 + rtnl_htb_get_level@libnl_3 3.5.0-1 + rtnl_htb_get_prio@Base 3.5.0-1 + rtnl_htb_get_prio@libnl_3 3.5.0-1 + rtnl_htb_get_quantum@Base 3.5.0-1 + rtnl_htb_get_quantum@libnl_3 3.5.0-1 + rtnl_htb_get_rate2quantum@Base 3.5.0-1 + rtnl_htb_get_rate2quantum@libnl_3 3.5.0-1 + rtnl_htb_get_rate64@libnl_3_5 3.5.0-1 + rtnl_htb_get_rate@Base 3.5.0-1 + rtnl_htb_get_rate@libnl_3 3.5.0-1 + rtnl_htb_get_rbuffer@Base 3.5.0-1 + rtnl_htb_get_rbuffer@libnl_3 3.5.0-1 + rtnl_htb_set_cbuffer@Base 3.5.0-1 + rtnl_htb_set_cbuffer@libnl_3 3.5.0-1 + rtnl_htb_set_ceil64@libnl_3_5 3.5.0-1 + rtnl_htb_set_ceil@Base 3.5.0-1 + rtnl_htb_set_ceil@libnl_3 3.5.0-1 + rtnl_htb_set_defcls@Base 3.5.0-1 + rtnl_htb_set_defcls@libnl_3 3.5.0-1 + rtnl_htb_set_level@Base 3.5.0-1 + rtnl_htb_set_level@libnl_3 3.5.0-1 + rtnl_htb_set_prio@Base 3.5.0-1 + rtnl_htb_set_prio@libnl_3 3.5.0-1 + rtnl_htb_set_quantum@Base 3.5.0-1 + rtnl_htb_set_quantum@libnl_3 3.5.0-1 + rtnl_htb_set_rate2quantum@Base 3.5.0-1 + rtnl_htb_set_rate2quantum@libnl_3 3.5.0-1 + rtnl_htb_set_rate64@libnl_3_5 3.5.0-1 + rtnl_htb_set_rate@Base 3.5.0-1 + rtnl_htb_set_rate@libnl_3 3.5.0-1 + rtnl_htb_set_rbuffer@Base 3.5.0-1 + rtnl_htb_set_rbuffer@libnl_3 3.5.0-1 + rtnl_link_add@Base 3.5.0-1 + rtnl_link_add@libnl_3 3.5.0-1 + rtnl_link_af_alloc@Base 3.5.0-1 + rtnl_link_af_alloc@libnl_3 3.5.0-1 + rtnl_link_af_data@Base 3.5.0-1 + rtnl_link_af_data@libnl_3 3.5.0-1 + rtnl_link_af_data_compare@Base 3.5.0-1 + rtnl_link_af_data_compare@libnl_3 3.5.0-1 + rtnl_link_af_ops_lookup@Base 3.5.0-1 + rtnl_link_af_ops_lookup@libnl_3 3.5.0-1 + rtnl_link_af_ops_put@Base 3.5.0-1 + rtnl_link_af_ops_put@libnl_3 3.5.0-1 + rtnl_link_af_register@Base 3.5.0-1 + rtnl_link_af_register@libnl_3 3.5.0-1 + rtnl_link_af_unregister@Base 3.5.0-1 + rtnl_link_af_unregister@libnl_3 3.5.0-1 + rtnl_link_alloc@Base 3.5.0-1 + rtnl_link_alloc@libnl_3 3.5.0-1 + rtnl_link_alloc_cache@Base 3.5.0-1 + rtnl_link_alloc_cache@libnl_3 3.5.0-1 + rtnl_link_alloc_cache_flags@libnl_3_2_28 3.5.0-1 + rtnl_link_bond_add@Base 3.5.0-1 + rtnl_link_bond_add@libnl_3 3.5.0-1 + rtnl_link_bond_alloc@Base 3.5.0-1 + rtnl_link_bond_alloc@libnl_3 3.5.0-1 + rtnl_link_bond_enslave@Base 3.5.0-1 + rtnl_link_bond_enslave@libnl_3 3.5.0-1 + rtnl_link_bond_enslave_ifindex@Base 3.5.0-1 + rtnl_link_bond_enslave_ifindex@libnl_3 3.5.0-1 + rtnl_link_bond_release@Base 3.5.0-1 + rtnl_link_bond_release@libnl_3 3.5.0-1 + rtnl_link_bond_release_ifindex@Base 3.5.0-1 + rtnl_link_bond_release_ifindex@libnl_3 3.5.0-1 + rtnl_link_bridge_add@Base 3.5.0-1 + rtnl_link_bridge_add@libnl_3 3.5.0-1 + rtnl_link_bridge_alloc@Base 3.5.0-1 + rtnl_link_bridge_alloc@libnl_3 3.5.0-1 + rtnl_link_bridge_flags2str@Base 3.5.0-1 + rtnl_link_bridge_flags2str@libnl_3 3.5.0-1 + rtnl_link_bridge_get_cost@Base 3.5.0-1 + rtnl_link_bridge_get_cost@libnl_3 3.5.0-1 + rtnl_link_bridge_get_flags@Base 3.5.0-1 + rtnl_link_bridge_get_flags@libnl_3 3.5.0-1 + rtnl_link_bridge_get_hwmode@libnl_3_2_29 3.5.0-1 + rtnl_link_bridge_get_port_state@Base 3.5.0-1 + rtnl_link_bridge_get_port_state@libnl_3 3.5.0-1 + rtnl_link_bridge_get_port_vlan@libnl_3_2_28 3.5.0-1 + rtnl_link_bridge_get_priority@Base 3.5.0-1 + rtnl_link_bridge_get_priority@libnl_3 3.5.0-1 + rtnl_link_bridge_has_ext_info@Base 3.5.0-1 + rtnl_link_bridge_has_ext_info@libnl_3 3.5.0-1 + rtnl_link_bridge_has_vlan@libnl_3_2_28 3.5.0-1 + rtnl_link_bridge_hwmode2str@libnl_3_2_29 3.5.0-1 + rtnl_link_bridge_portstate2str@libnl_3_2_29 3.5.0-1 + rtnl_link_bridge_pvid@libnl_3_2_28 3.5.0-1 + rtnl_link_bridge_set_cost@Base 3.5.0-1 + rtnl_link_bridge_set_cost@libnl_3 3.5.0-1 + rtnl_link_bridge_set_flags@Base 3.5.0-1 + rtnl_link_bridge_set_flags@libnl_3 3.5.0-1 + rtnl_link_bridge_set_hwmode@libnl_3_2_29 3.5.0-1 + rtnl_link_bridge_set_port_state@Base 3.5.0-1 + rtnl_link_bridge_set_port_state@libnl_3 3.5.0-1 + rtnl_link_bridge_set_priority@Base 3.5.0-1 + rtnl_link_bridge_set_priority@libnl_3 3.5.0-1 + rtnl_link_bridge_set_self@libnl_3_2_29 3.5.0-1 + rtnl_link_bridge_str2flags@Base 3.5.0-1 + rtnl_link_bridge_str2flags@libnl_3 3.5.0-1 + rtnl_link_bridge_str2hwmode@libnl_3_2_29 3.5.0-1 + rtnl_link_bridge_str2portstate@libnl_3_2_29 3.5.0-1 + rtnl_link_bridge_unset_flags@Base 3.5.0-1 + rtnl_link_bridge_unset_flags@libnl_3 3.5.0-1 + rtnl_link_build_add_request@Base 3.5.0-1 + rtnl_link_build_add_request@libnl_3 3.5.0-1 + rtnl_link_build_change_request@Base 3.5.0-1 + rtnl_link_build_change_request@libnl_3 3.5.0-1 + rtnl_link_build_delete_request@Base 3.5.0-1 + rtnl_link_build_delete_request@libnl_3 3.5.0-1 + rtnl_link_build_get_request@Base 3.5.0-1 + rtnl_link_build_get_request@libnl_3 3.5.0-1 + rtnl_link_can_berr@Base 3.5.0-1 + rtnl_link_can_berr@libnl_3 3.5.0-1 + rtnl_link_can_berr_rx@Base 3.5.0-1 + rtnl_link_can_berr_rx@libnl_3 3.5.0-1 + rtnl_link_can_berr_tx@Base 3.5.0-1 + rtnl_link_can_berr_tx@libnl_3 3.5.0-1 + rtnl_link_can_ctrlmode2str@Base 3.5.0-1 + rtnl_link_can_ctrlmode2str@libnl_3 3.5.0-1 + rtnl_link_can_freq@Base 3.5.0-1 + rtnl_link_can_freq@libnl_3 3.5.0-1 + rtnl_link_can_get_bitrate@Base 3.5.0-1 + rtnl_link_can_get_bitrate@libnl_3 3.5.0-1 + rtnl_link_can_get_bittiming@Base 3.5.0-1 + rtnl_link_can_get_bittiming@libnl_3 3.5.0-1 + rtnl_link_can_get_bt_const@Base 3.5.0-1 + rtnl_link_can_get_bt_const@libnl_3 3.5.0-1 + rtnl_link_can_get_ctrlmode@Base 3.5.0-1 + rtnl_link_can_get_ctrlmode@libnl_3 3.5.0-1 + rtnl_link_can_get_restart_ms@Base 3.5.0-1 + rtnl_link_can_get_restart_ms@libnl_3 3.5.0-1 + rtnl_link_can_get_sample_point@Base 3.5.0-1 + rtnl_link_can_get_sample_point@libnl_3 3.5.0-1 + rtnl_link_can_restart@Base 3.5.0-1 + rtnl_link_can_restart@libnl_3 3.5.0-1 + rtnl_link_can_set_bitrate@Base 3.5.0-1 + rtnl_link_can_set_bitrate@libnl_3 3.5.0-1 + rtnl_link_can_set_bittiming@Base 3.5.0-1 + rtnl_link_can_set_bittiming@libnl_3 3.5.0-1 + rtnl_link_can_set_ctrlmode@Base 3.5.0-1 + rtnl_link_can_set_ctrlmode@libnl_3 3.5.0-1 + rtnl_link_can_set_restart_ms@Base 3.5.0-1 + rtnl_link_can_set_restart_ms@libnl_3 3.5.0-1 + rtnl_link_can_set_sample_point@Base 3.5.0-1 + rtnl_link_can_set_sample_point@libnl_3 3.5.0-1 + rtnl_link_can_state@Base 3.5.0-1 + rtnl_link_can_state@libnl_3 3.5.0-1 + rtnl_link_can_str2ctrlmode@Base 3.5.0-1 + rtnl_link_can_str2ctrlmode@libnl_3 3.5.0-1 + rtnl_link_can_unset_ctrlmode@Base 3.5.0-1 + rtnl_link_can_unset_ctrlmode@libnl_3 3.5.0-1 + rtnl_link_carrier2str@Base 3.5.0-1 + rtnl_link_carrier2str@libnl_3 3.5.0-1 + rtnl_link_change@Base 3.5.0-1 + rtnl_link_change@libnl_3 3.5.0-1 + rtnl_link_delete@Base 3.5.0-1 + rtnl_link_delete@libnl_3 3.5.0-1 + rtnl_link_enslave@Base 3.5.0-1 + rtnl_link_enslave@libnl_3 3.5.0-1 + rtnl_link_enslave_ifindex@Base 3.5.0-1 + rtnl_link_enslave_ifindex@libnl_3 3.5.0-1 + rtnl_link_fill_info@Base 3.5.0-1 + rtnl_link_fill_info@libnl_3 3.5.0-1 + rtnl_link_flags2str@Base 3.5.0-1 + rtnl_link_flags2str@libnl_3 3.5.0-1 + rtnl_link_geneve_alloc@libnl_3_5 3.5.0-1 + rtnl_link_geneve_get_flags@libnl_3_5 3.5.0-1 + rtnl_link_geneve_get_id@libnl_3_5 3.5.0-1 + rtnl_link_geneve_get_label@libnl_3_5 3.5.0-1 + rtnl_link_geneve_get_port@libnl_3_5 3.5.0-1 + rtnl_link_geneve_get_remote@libnl_3_5 3.5.0-1 + rtnl_link_geneve_get_tos@libnl_3_5 3.5.0-1 + rtnl_link_geneve_get_ttl@libnl_3_5 3.5.0-1 + rtnl_link_geneve_get_udp_csum@libnl_3_5 3.5.0-1 + rtnl_link_geneve_get_udp_zero_csum6_rx@libnl_3_5 3.5.0-1 + rtnl_link_geneve_get_udp_zero_csum6_tx@libnl_3_5 3.5.0-1 + rtnl_link_geneve_set_flags@libnl_3_5 3.5.0-1 + rtnl_link_geneve_set_id@libnl_3_5 3.5.0-1 + rtnl_link_geneve_set_label@libnl_3_5 3.5.0-1 + rtnl_link_geneve_set_port@libnl_3_5 3.5.0-1 + rtnl_link_geneve_set_remote@libnl_3_5 3.5.0-1 + rtnl_link_geneve_set_tos@libnl_3_5 3.5.0-1 + rtnl_link_geneve_set_ttl@libnl_3_5 3.5.0-1 + rtnl_link_geneve_set_udp_csum@libnl_3_5 3.5.0-1 + rtnl_link_geneve_set_udp_zero_csum6_rx@libnl_3_5 3.5.0-1 + rtnl_link_geneve_set_udp_zero_csum6_tx@libnl_3_5 3.5.0-1 + rtnl_link_get@Base 3.5.0-1 + rtnl_link_get@libnl_3 3.5.0-1 + rtnl_link_get_addr@Base 3.5.0-1 + rtnl_link_get_addr@libnl_3 3.5.0-1 + rtnl_link_get_arptype@Base 3.5.0-1 + rtnl_link_get_arptype@libnl_3 3.5.0-1 + rtnl_link_get_broadcast@Base 3.5.0-1 + rtnl_link_get_broadcast@libnl_3 3.5.0-1 + rtnl_link_get_by_name@Base 3.5.0-1 + rtnl_link_get_by_name@libnl_3 3.5.0-1 + rtnl_link_get_carrier@Base 3.5.0-1 + rtnl_link_get_carrier@libnl_3 3.5.0-1 + rtnl_link_get_carrier_changes@libnl_3_2_29 3.5.0-1 + rtnl_link_get_family@Base 3.5.0-1 + rtnl_link_get_family@libnl_3 3.5.0-1 + rtnl_link_get_flags@Base 3.5.0-1 + rtnl_link_get_flags@libnl_3 3.5.0-1 + rtnl_link_get_group@Base 3.5.0-1 + rtnl_link_get_group@libnl_3 3.5.0-1 + rtnl_link_get_gso_max_segs@libnl_3_2_29 3.5.0-1 + rtnl_link_get_gso_max_size@libnl_3_2_29 3.5.0-1 + rtnl_link_get_ifalias@Base 3.5.0-1 + rtnl_link_get_ifalias@libnl_3 3.5.0-1 + rtnl_link_get_ifindex@Base 3.5.0-1 + rtnl_link_get_ifindex@libnl_3 3.5.0-1 + rtnl_link_get_info_type@Base 3.5.0-1 + rtnl_link_get_info_type@libnl_3 3.5.0-1 + rtnl_link_get_kernel@Base 3.5.0-1 + rtnl_link_get_kernel@libnl_3 3.5.0-1 + rtnl_link_get_link@Base 3.5.0-1 + rtnl_link_get_link@libnl_3 3.5.0-1 + rtnl_link_get_link_netnsid@Base 3.5.0-1 + rtnl_link_get_link_netnsid@libnl_3_2_27 3.5.0-1 + rtnl_link_get_linkmode@Base 3.5.0-1 + rtnl_link_get_linkmode@libnl_3 3.5.0-1 + rtnl_link_get_master@Base 3.5.0-1 + rtnl_link_get_master@libnl_3 3.5.0-1 + rtnl_link_get_mtu@Base 3.5.0-1 + rtnl_link_get_mtu@libnl_3 3.5.0-1 + rtnl_link_get_name@Base 3.5.0-1 + rtnl_link_get_name@libnl_3 3.5.0-1 + rtnl_link_get_ns_fd@Base 3.5.0-1 + rtnl_link_get_ns_fd@libnl_3 3.5.0-1 + rtnl_link_get_ns_pid@Base 3.5.0-1 + rtnl_link_get_ns_pid@libnl_3 3.5.0-1 + rtnl_link_get_num_rx_queues@Base 3.5.0-1 + rtnl_link_get_num_rx_queues@libnl_3 3.5.0-1 + rtnl_link_get_num_tx_queues@Base 3.5.0-1 + rtnl_link_get_num_tx_queues@libnl_3 3.5.0-1 + rtnl_link_get_num_vf@Base 3.5.0-1 + rtnl_link_get_num_vf@libnl_3 3.5.0-1 + rtnl_link_get_operstate@Base 3.5.0-1 + rtnl_link_get_operstate@libnl_3 3.5.0-1 + rtnl_link_get_phys_port_id@Base 3.5.0-1 + rtnl_link_get_phys_port_id@libnl_3 3.5.0-1 + rtnl_link_get_phys_port_name@libnl_3_2_29 3.5.0-1 + rtnl_link_get_phys_switch_id@libnl_3_2_29 3.5.0-1 + rtnl_link_get_pmtudisc@Base 3.5.0-1 + rtnl_link_get_pmtudisc@libnl_3 3.5.0-1 + rtnl_link_get_promiscuity@Base 3.5.0-1 + rtnl_link_get_promiscuity@libnl_3 3.5.0-1 + rtnl_link_get_qdisc@Base 3.5.0-1 + rtnl_link_get_qdisc@libnl_3 3.5.0-1 + rtnl_link_get_slave_type@libnl_3_5 3.5.0-1 + rtnl_link_get_stat@Base 3.5.0-1 + rtnl_link_get_stat@libnl_3 3.5.0-1 + rtnl_link_get_txqlen@Base 3.5.0-1 + rtnl_link_get_txqlen@libnl_3 3.5.0-1 + rtnl_link_get_type@Base 3.5.0-1 + rtnl_link_get_type@libnl_3 3.5.0-1 + rtnl_link_get_weight@Base 3.5.0-1 + rtnl_link_get_weight@libnl_3 3.5.0-1 + rtnl_link_has_vf_list@libnl_3_2_29 3.5.0-1 + rtnl_link_i2name@Base 3.5.0-1 + rtnl_link_i2name@libnl_3 3.5.0-1 + rtnl_link_inet6_addrgenmode2str@Base 3.5.0-1 + rtnl_link_inet6_addrgenmode2str@libnl_3 3.5.0-1 + rtnl_link_inet6_flags2str@libnl_3_4 3.5.0-1 + rtnl_link_inet6_get_addr_gen_mode@Base 3.5.0-1 + rtnl_link_inet6_get_addr_gen_mode@libnl_3 3.5.0-1 + rtnl_link_inet6_get_flags@libnl_3_4 3.5.0-1 + rtnl_link_inet6_get_token@Base 3.5.0-1 + rtnl_link_inet6_get_token@libnl_3 3.5.0-1 + rtnl_link_inet6_set_addr_gen_mode@Base 3.5.0-1 + rtnl_link_inet6_set_addr_gen_mode@libnl_3 3.5.0-1 + rtnl_link_inet6_set_flags@libnl_3_4 3.5.0-1 + rtnl_link_inet6_set_token@Base 3.5.0-1 + rtnl_link_inet6_set_token@libnl_3 3.5.0-1 + rtnl_link_inet6_str2addrgenmode@Base 3.5.0-1 + rtnl_link_inet6_str2addrgenmode@libnl_3 3.5.0-1 + rtnl_link_inet6_str2flags@libnl_3_4 3.5.0-1 + rtnl_link_inet_devconf2str@Base 3.5.0-1 + rtnl_link_inet_devconf2str@libnl_3 3.5.0-1 + rtnl_link_inet_get_conf@Base 3.5.0-1 + rtnl_link_inet_get_conf@libnl_3 3.5.0-1 + rtnl_link_inet_set_conf@Base 3.5.0-1 + rtnl_link_inet_set_conf@libnl_3 3.5.0-1 + rtnl_link_inet_str2devconf@Base 3.5.0-1 + rtnl_link_inet_str2devconf@libnl_3 3.5.0-1 + rtnl_link_info_ops_lookup@Base 3.5.0-1 + rtnl_link_info_ops_lookup@libnl_3 3.5.0-1 + rtnl_link_info_ops_put@Base 3.5.0-1 + rtnl_link_info_ops_put@libnl_3 3.5.0-1 + rtnl_link_info_parse@Base 3.5.0-1 + rtnl_link_info_parse@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_add@Base 3.5.0-1 + rtnl_link_ip6_tnl_add@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_alloc@Base 3.5.0-1 + rtnl_link_ip6_tnl_alloc@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_get_encaplimit@Base 3.5.0-1 + rtnl_link_ip6_tnl_get_encaplimit@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_get_flags@Base 3.5.0-1 + rtnl_link_ip6_tnl_get_flags@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_get_flowinfo@Base 3.5.0-1 + rtnl_link_ip6_tnl_get_flowinfo@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_get_link@Base 3.5.0-1 + rtnl_link_ip6_tnl_get_link@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_get_local@Base 3.5.0-1 + rtnl_link_ip6_tnl_get_local@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_get_proto@Base 3.5.0-1 + rtnl_link_ip6_tnl_get_proto@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_get_remote@Base 3.5.0-1 + rtnl_link_ip6_tnl_get_remote@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_get_tos@Base 3.5.0-1 + rtnl_link_ip6_tnl_get_tos@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_get_ttl@Base 3.5.0-1 + rtnl_link_ip6_tnl_get_ttl@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_set_encaplimit@Base 3.5.0-1 + rtnl_link_ip6_tnl_set_encaplimit@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_set_flags@Base 3.5.0-1 + rtnl_link_ip6_tnl_set_flags@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_set_flowinfo@Base 3.5.0-1 + rtnl_link_ip6_tnl_set_flowinfo@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_set_link@Base 3.5.0-1 + rtnl_link_ip6_tnl_set_link@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_set_local@Base 3.5.0-1 + rtnl_link_ip6_tnl_set_local@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_set_proto@Base 3.5.0-1 + rtnl_link_ip6_tnl_set_proto@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_set_remote@Base 3.5.0-1 + rtnl_link_ip6_tnl_set_remote@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_set_tos@Base 3.5.0-1 + rtnl_link_ip6_tnl_set_tos@libnl_3 3.5.0-1 + rtnl_link_ip6_tnl_set_ttl@Base 3.5.0-1 + rtnl_link_ip6_tnl_set_ttl@libnl_3 3.5.0-1 + rtnl_link_ipgre_add@Base 3.5.0-1 + rtnl_link_ipgre_add@libnl_3 3.5.0-1 + rtnl_link_ipgre_alloc@Base 3.5.0-1 + rtnl_link_ipgre_alloc@libnl_3 3.5.0-1 + rtnl_link_ipgre_get_iflags@Base 3.5.0-1 + rtnl_link_ipgre_get_iflags@libnl_3 3.5.0-1 + rtnl_link_ipgre_get_ikey@Base 3.5.0-1 + rtnl_link_ipgre_get_ikey@libnl_3 3.5.0-1 + rtnl_link_ipgre_get_link@Base 3.5.0-1 + rtnl_link_ipgre_get_link@libnl_3 3.5.0-1 + rtnl_link_ipgre_get_local@Base 3.5.0-1 + rtnl_link_ipgre_get_local@libnl_3 3.5.0-1 + rtnl_link_ipgre_get_oflags@Base 3.5.0-1 + rtnl_link_ipgre_get_oflags@libnl_3 3.5.0-1 + rtnl_link_ipgre_get_okey@Base 3.5.0-1 + rtnl_link_ipgre_get_okey@libnl_3 3.5.0-1 + rtnl_link_ipgre_get_pmtudisc@libnl_3_2_29 3.5.0-1 + rtnl_link_ipgre_get_remote@Base 3.5.0-1 + rtnl_link_ipgre_get_remote@libnl_3 3.5.0-1 + rtnl_link_ipgre_get_tos@Base 3.5.0-1 + rtnl_link_ipgre_get_tos@libnl_3 3.5.0-1 + rtnl_link_ipgre_get_ttl@Base 3.5.0-1 + rtnl_link_ipgre_get_ttl@libnl_3 3.5.0-1 + rtnl_link_ipgre_set_iflags@Base 3.5.0-1 + rtnl_link_ipgre_set_iflags@libnl_3 3.5.0-1 + rtnl_link_ipgre_set_ikey@Base 3.5.0-1 + rtnl_link_ipgre_set_ikey@libnl_3 3.5.0-1 + rtnl_link_ipgre_set_link@Base 3.5.0-1 + rtnl_link_ipgre_set_link@libnl_3 3.5.0-1 + rtnl_link_ipgre_set_local@Base 3.5.0-1 + rtnl_link_ipgre_set_local@libnl_3 3.5.0-1 + rtnl_link_ipgre_set_oflags@Base 3.5.0-1 + rtnl_link_ipgre_set_oflags@libnl_3 3.5.0-1 + rtnl_link_ipgre_set_okey@Base 3.5.0-1 + rtnl_link_ipgre_set_okey@libnl_3 3.5.0-1 + rtnl_link_ipgre_set_pmtudisc@Base 3.5.0-1 + rtnl_link_ipgre_set_pmtudisc@libnl_3 3.5.0-1 + rtnl_link_ipgre_set_remote@Base 3.5.0-1 + rtnl_link_ipgre_set_remote@libnl_3 3.5.0-1 + rtnl_link_ipgre_set_tos@Base 3.5.0-1 + rtnl_link_ipgre_set_tos@libnl_3 3.5.0-1 + rtnl_link_ipgre_set_ttl@Base 3.5.0-1 + rtnl_link_ipgre_set_ttl@libnl_3 3.5.0-1 + rtnl_link_ipgretap_add@libnl_3_2_28 3.5.0-1 + rtnl_link_ipgretap_alloc@libnl_3_2_28 3.5.0-1 + rtnl_link_ipip_add@Base 3.5.0-1 + rtnl_link_ipip_add@libnl_3 3.5.0-1 + rtnl_link_ipip_alloc@Base 3.5.0-1 + rtnl_link_ipip_alloc@libnl_3 3.5.0-1 + rtnl_link_ipip_get_link@Base 3.5.0-1 + rtnl_link_ipip_get_link@libnl_3 3.5.0-1 + rtnl_link_ipip_get_local@Base 3.5.0-1 + rtnl_link_ipip_get_local@libnl_3 3.5.0-1 + rtnl_link_ipip_get_pmtudisc@Base 3.5.0-1 + rtnl_link_ipip_get_pmtudisc@libnl_3 3.5.0-1 + rtnl_link_ipip_get_remote@Base 3.5.0-1 + rtnl_link_ipip_get_remote@libnl_3 3.5.0-1 + rtnl_link_ipip_get_tos@Base 3.5.0-1 + rtnl_link_ipip_get_tos@libnl_3 3.5.0-1 + rtnl_link_ipip_get_ttl@Base 3.5.0-1 + rtnl_link_ipip_get_ttl@libnl_3 3.5.0-1 + rtnl_link_ipip_set_link@Base 3.5.0-1 + rtnl_link_ipip_set_link@libnl_3 3.5.0-1 + rtnl_link_ipip_set_local@Base 3.5.0-1 + rtnl_link_ipip_set_local@libnl_3 3.5.0-1 + rtnl_link_ipip_set_pmtudisc@Base 3.5.0-1 + rtnl_link_ipip_set_pmtudisc@libnl_3 3.5.0-1 + rtnl_link_ipip_set_remote@Base 3.5.0-1 + rtnl_link_ipip_set_remote@libnl_3 3.5.0-1 + rtnl_link_ipip_set_tos@Base 3.5.0-1 + rtnl_link_ipip_set_tos@libnl_3 3.5.0-1 + rtnl_link_ipip_set_ttl@Base 3.5.0-1 + rtnl_link_ipip_set_ttl@libnl_3 3.5.0-1 + rtnl_link_ipvlan_alloc@Base 3.5.0-1 + rtnl_link_ipvlan_alloc@libnl_3_2_27 3.5.0-1 + rtnl_link_ipvlan_get_mode@Base 3.5.0-1 + rtnl_link_ipvlan_get_mode@libnl_3_2_27 3.5.0-1 + rtnl_link_ipvlan_mode2str@Base 3.5.0-1 + rtnl_link_ipvlan_mode2str@libnl_3_2_27 3.5.0-1 + rtnl_link_ipvlan_set_mode@Base 3.5.0-1 + rtnl_link_ipvlan_set_mode@libnl_3_2_27 3.5.0-1 + rtnl_link_ipvlan_str2mode@Base 3.5.0-1 + rtnl_link_ipvlan_str2mode@libnl_3_2_27 3.5.0-1 + rtnl_link_ipvti_add@Base 3.5.0-1 + rtnl_link_ipvti_add@libnl_3 3.5.0-1 + rtnl_link_ipvti_alloc@Base 3.5.0-1 + rtnl_link_ipvti_alloc@libnl_3 3.5.0-1 + rtnl_link_ipvti_get_ikey@Base 3.5.0-1 + rtnl_link_ipvti_get_ikey@libnl_3 3.5.0-1 + rtnl_link_ipvti_get_link@Base 3.5.0-1 + rtnl_link_ipvti_get_link@libnl_3 3.5.0-1 + rtnl_link_ipvti_get_local@Base 3.5.0-1 + rtnl_link_ipvti_get_local@libnl_3 3.5.0-1 + rtnl_link_ipvti_get_okey@Base 3.5.0-1 + rtnl_link_ipvti_get_okey@libnl_3 3.5.0-1 + rtnl_link_ipvti_get_remote@Base 3.5.0-1 + rtnl_link_ipvti_get_remote@libnl_3 3.5.0-1 + rtnl_link_ipvti_set_ikey@Base 3.5.0-1 + rtnl_link_ipvti_set_ikey@libnl_3 3.5.0-1 + rtnl_link_ipvti_set_link@Base 3.5.0-1 + rtnl_link_ipvti_set_link@libnl_3 3.5.0-1 + rtnl_link_ipvti_set_local@Base 3.5.0-1 + rtnl_link_ipvti_set_local@libnl_3 3.5.0-1 + rtnl_link_ipvti_set_okey@Base 3.5.0-1 + rtnl_link_ipvti_set_okey@libnl_3 3.5.0-1 + rtnl_link_ipvti_set_remote@Base 3.5.0-1 + rtnl_link_ipvti_set_remote@libnl_3 3.5.0-1 + rtnl_link_is_bridge@Base 3.5.0-1 + rtnl_link_is_bridge@libnl_3 3.5.0-1 + rtnl_link_is_can@Base 3.5.0-1 + rtnl_link_is_can@libnl_3 3.5.0-1 + rtnl_link_is_geneve@libnl_3_5 3.5.0-1 + rtnl_link_is_ip6_tnl@Base 3.5.0-1 + rtnl_link_is_ip6_tnl@libnl_3 3.5.0-1 + rtnl_link_is_ipgre@Base 3.5.0-1 + rtnl_link_is_ipgre@libnl_3 3.5.0-1 + rtnl_link_is_ipgretap@libnl_3_2_29 3.5.0-1 + rtnl_link_is_ipip@Base 3.5.0-1 + rtnl_link_is_ipip@libnl_3 3.5.0-1 + rtnl_link_is_ipvlan@Base 3.5.0-1 + rtnl_link_is_ipvlan@libnl_3_2_27 3.5.0-1 + rtnl_link_is_ipvti@Base 3.5.0-1 + rtnl_link_is_ipvti@libnl_3 3.5.0-1 + rtnl_link_is_macvlan@Base 3.5.0-1 + rtnl_link_is_macvlan@libnl_3 3.5.0-1 + rtnl_link_is_macvtap@libnl_3_2_28 3.5.0-1 + rtnl_link_is_sit@Base 3.5.0-1 + rtnl_link_is_sit@libnl_3 3.5.0-1 + rtnl_link_is_veth@Base 3.5.0-1 + rtnl_link_is_veth@libnl_3 3.5.0-1 + rtnl_link_is_vlan@Base 3.5.0-1 + rtnl_link_is_vlan@libnl_3 3.5.0-1 + rtnl_link_is_vrf@libnl_3_2_28 3.5.0-1 + rtnl_link_is_vxlan@Base 3.5.0-1 + rtnl_link_is_vxlan@libnl_3 3.5.0-1 + rtnl_link_is_xfrmi@libnl_3_5 3.5.0-1 + rtnl_link_macsec_alloc@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_cipher_suite@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_encoding_sa@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_encrypt@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_end_station@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_icv_len@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_port@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_protect@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_replay_protect@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_scb@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_sci@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_send_sci@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_validation_type@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_get_window@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_cipher_suite@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_encoding_sa@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_encrypt@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_end_station@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_icv_len@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_port@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_protect@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_replay_protect@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_scb@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_sci@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_send_sci@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_validation_type@libnl_3_2_28 3.5.0-1 + rtnl_link_macsec_set_window@libnl_3_2_28 3.5.0-1 + rtnl_link_macvlan_add_macaddr@libnl_3_2_29 3.5.0-1 + rtnl_link_macvlan_alloc@Base 3.5.0-1 + rtnl_link_macvlan_alloc@libnl_3 3.5.0-1 + rtnl_link_macvlan_count_macaddr@libnl_3_2_29 3.5.0-1 + rtnl_link_macvlan_del_macaddr@libnl_3_2_29 3.5.0-1 + rtnl_link_macvlan_flags2str@Base 3.5.0-1 + rtnl_link_macvlan_flags2str@libnl_3 3.5.0-1 + rtnl_link_macvlan_get_flags@Base 3.5.0-1 + rtnl_link_macvlan_get_flags@libnl_3 3.5.0-1 + rtnl_link_macvlan_get_macaddr@libnl_3_2_29 3.5.0-1 + rtnl_link_macvlan_get_macmode@libnl_3_2_29 3.5.0-1 + rtnl_link_macvlan_get_mode@Base 3.5.0-1 + rtnl_link_macvlan_get_mode@libnl_3 3.5.0-1 + rtnl_link_macvlan_macmode2str@libnl_3_2_29 3.5.0-1 + rtnl_link_macvlan_mode2str@Base 3.5.0-1 + rtnl_link_macvlan_mode2str@libnl_3 3.5.0-1 + rtnl_link_macvlan_set_flags@Base 3.5.0-1 + rtnl_link_macvlan_set_flags@libnl_3 3.5.0-1 + rtnl_link_macvlan_set_macmode@libnl_3_2_29 3.5.0-1 + rtnl_link_macvlan_set_mode@Base 3.5.0-1 + rtnl_link_macvlan_set_mode@libnl_3 3.5.0-1 + rtnl_link_macvlan_str2flags@Base 3.5.0-1 + rtnl_link_macvlan_str2flags@libnl_3 3.5.0-1 + rtnl_link_macvlan_str2macmode@libnl_3_2_29 3.5.0-1 + rtnl_link_macvlan_str2mode@Base 3.5.0-1 + rtnl_link_macvlan_str2mode@libnl_3 3.5.0-1 + rtnl_link_macvlan_unset_flags@Base 3.5.0-1 + rtnl_link_macvlan_unset_flags@libnl_3 3.5.0-1 + rtnl_link_macvtap_alloc@libnl_3_2_28 3.5.0-1 + rtnl_link_macvtap_flags2str@libnl_3_2_28 3.5.0-1 + rtnl_link_macvtap_get_flags@libnl_3_2_28 3.5.0-1 + rtnl_link_macvtap_get_mode@libnl_3_2_28 3.5.0-1 + rtnl_link_macvtap_mode2str@libnl_3_2_28 3.5.0-1 + rtnl_link_macvtap_set_flags@libnl_3_2_28 3.5.0-1 + rtnl_link_macvtap_set_mode@libnl_3_2_28 3.5.0-1 + rtnl_link_macvtap_str2flags@libnl_3_2_28 3.5.0-1 + rtnl_link_macvtap_str2mode@libnl_3_2_28 3.5.0-1 + rtnl_link_macvtap_unset_flags@libnl_3_2_28 3.5.0-1 + rtnl_link_mode2str@Base 3.5.0-1 + rtnl_link_mode2str@libnl_3 3.5.0-1 + rtnl_link_name2i@Base 3.5.0-1 + rtnl_link_name2i@libnl_3 3.5.0-1 + rtnl_link_operstate2str@Base 3.5.0-1 + rtnl_link_operstate2str@libnl_3 3.5.0-1 + rtnl_link_ppp_alloc@libnl_3_2_29 3.5.0-1 + rtnl_link_ppp_get_fd@libnl_3_2_29 3.5.0-1 + rtnl_link_ppp_set_fd@libnl_3_2_29 3.5.0-1 + rtnl_link_put@Base 3.5.0-1 + rtnl_link_put@libnl_3 3.5.0-1 + rtnl_link_register_info@Base 3.5.0-1 + rtnl_link_register_info@libnl_3 3.5.0-1 + rtnl_link_release@Base 3.5.0-1 + rtnl_link_release@libnl_3 3.5.0-1 + rtnl_link_release_ifindex@Base 3.5.0-1 + rtnl_link_release_ifindex@libnl_3 3.5.0-1 + rtnl_link_set_addr@Base 3.5.0-1 + rtnl_link_set_addr@libnl_3 3.5.0-1 + rtnl_link_set_arptype@Base 3.5.0-1 + rtnl_link_set_arptype@libnl_3 3.5.0-1 + rtnl_link_set_broadcast@Base 3.5.0-1 + rtnl_link_set_broadcast@libnl_3 3.5.0-1 + rtnl_link_set_carrier@Base 3.5.0-1 + rtnl_link_set_carrier@libnl_3 3.5.0-1 + rtnl_link_set_family@Base 3.5.0-1 + rtnl_link_set_family@libnl_3 3.5.0-1 + rtnl_link_set_flags@Base 3.5.0-1 + rtnl_link_set_flags@libnl_3 3.5.0-1 + rtnl_link_set_group@Base 3.5.0-1 + rtnl_link_set_group@libnl_3 3.5.0-1 + rtnl_link_set_ifalias@Base 3.5.0-1 + rtnl_link_set_ifalias@libnl_3 3.5.0-1 + rtnl_link_set_ifindex@Base 3.5.0-1 + rtnl_link_set_ifindex@libnl_3 3.5.0-1 + rtnl_link_set_info_type@Base 3.5.0-1 + rtnl_link_set_info_type@libnl_3 3.5.0-1 + rtnl_link_set_link@Base 3.5.0-1 + rtnl_link_set_link@libnl_3 3.5.0-1 + rtnl_link_set_link_netnsid@Base 3.5.0-1 + rtnl_link_set_link_netnsid@libnl_3_2_27 3.5.0-1 + rtnl_link_set_linkmode@Base 3.5.0-1 + rtnl_link_set_linkmode@libnl_3 3.5.0-1 + rtnl_link_set_master@Base 3.5.0-1 + rtnl_link_set_master@libnl_3 3.5.0-1 + rtnl_link_set_mtu@Base 3.5.0-1 + rtnl_link_set_mtu@libnl_3 3.5.0-1 + rtnl_link_set_name@Base 3.5.0-1 + rtnl_link_set_name@libnl_3 3.5.0-1 + rtnl_link_set_ns_fd@Base 3.5.0-1 + rtnl_link_set_ns_fd@libnl_3 3.5.0-1 + rtnl_link_set_ns_pid@Base 3.5.0-1 + rtnl_link_set_ns_pid@libnl_3 3.5.0-1 + rtnl_link_set_num_rx_queues@Base 3.5.0-1 + rtnl_link_set_num_rx_queues@libnl_3 3.5.0-1 + rtnl_link_set_num_tx_queues@Base 3.5.0-1 + rtnl_link_set_num_tx_queues@libnl_3 3.5.0-1 + rtnl_link_set_operstate@Base 3.5.0-1 + rtnl_link_set_operstate@libnl_3 3.5.0-1 + rtnl_link_set_promiscuity@Base 3.5.0-1 + rtnl_link_set_promiscuity@libnl_3 3.5.0-1 + rtnl_link_set_qdisc@Base 3.5.0-1 + rtnl_link_set_qdisc@libnl_3 3.5.0-1 + rtnl_link_set_slave_type@libnl_3_5 3.5.0-1 + rtnl_link_set_stat@Base 3.5.0-1 + rtnl_link_set_stat@libnl_3 3.5.0-1 + rtnl_link_set_txqlen@Base 3.5.0-1 + rtnl_link_set_txqlen@libnl_3 3.5.0-1 + rtnl_link_set_type@Base 3.5.0-1 + rtnl_link_set_type@libnl_3 3.5.0-1 + rtnl_link_set_vf_list@libnl_3_2_29 3.5.0-1 + rtnl_link_set_weight@Base 3.5.0-1 + rtnl_link_set_weight@libnl_3 3.5.0-1 + rtnl_link_sit_add@Base 3.5.0-1 + rtnl_link_sit_add@libnl_3 3.5.0-1 + rtnl_link_sit_alloc@Base 3.5.0-1 + rtnl_link_sit_alloc@libnl_3 3.5.0-1 + rtnl_link_sit_get_flags@Base 3.5.0-1 + rtnl_link_sit_get_flags@libnl_3 3.5.0-1 + rtnl_link_sit_get_ip6rd_prefix@libnl_3_2_28 3.5.0-1 + rtnl_link_sit_get_ip6rd_prefixlen@libnl_3_2_28 3.5.0-1 + rtnl_link_sit_get_ip6rd_relay_prefix@libnl_3_2_28 3.5.0-1 + rtnl_link_sit_get_ip6rd_relay_prefixlen@libnl_3_2_28 3.5.0-1 + rtnl_link_sit_get_link@Base 3.5.0-1 + rtnl_link_sit_get_link@libnl_3 3.5.0-1 + rtnl_link_sit_get_local@Base 3.5.0-1 + rtnl_link_sit_get_local@libnl_3 3.5.0-1 + rtnl_link_sit_get_pmtudisc@Base 3.5.0-1 + rtnl_link_sit_get_pmtudisc@libnl_3 3.5.0-1 + rtnl_link_sit_get_proto@Base 3.5.0-1 + rtnl_link_sit_get_proto@libnl_3 3.5.0-1 + rtnl_link_sit_get_remote@Base 3.5.0-1 + rtnl_link_sit_get_remote@libnl_3 3.5.0-1 + rtnl_link_sit_get_tos@Base 3.5.0-1 + rtnl_link_sit_get_tos@libnl_3 3.5.0-1 + rtnl_link_sit_get_ttl@Base 3.5.0-1 + rtnl_link_sit_get_ttl@libnl_3 3.5.0-1 + rtnl_link_sit_set_flags@Base 3.5.0-1 + rtnl_link_sit_set_flags@libnl_3 3.5.0-1 + rtnl_link_sit_set_ip6rd_prefix@libnl_3_2_28 3.5.0-1 + rtnl_link_sit_set_ip6rd_prefixlen@libnl_3_2_28 3.5.0-1 + rtnl_link_sit_set_ip6rd_relay_prefix@libnl_3_2_28 3.5.0-1 + rtnl_link_sit_set_ip6rd_relay_prefixlen@libnl_3_2_28 3.5.0-1 + rtnl_link_sit_set_link@Base 3.5.0-1 + rtnl_link_sit_set_link@libnl_3 3.5.0-1 + rtnl_link_sit_set_local@Base 3.5.0-1 + rtnl_link_sit_set_local@libnl_3 3.5.0-1 + rtnl_link_sit_set_pmtudisc@Base 3.5.0-1 + rtnl_link_sit_set_pmtudisc@libnl_3 3.5.0-1 + rtnl_link_sit_set_proto@Base 3.5.0-1 + rtnl_link_sit_set_proto@libnl_3 3.5.0-1 + rtnl_link_sit_set_remote@Base 3.5.0-1 + rtnl_link_sit_set_remote@libnl_3 3.5.0-1 + rtnl_link_sit_set_tos@Base 3.5.0-1 + rtnl_link_sit_set_tos@libnl_3 3.5.0-1 + rtnl_link_sit_set_ttl@Base 3.5.0-1 + rtnl_link_sit_set_ttl@libnl_3 3.5.0-1 + rtnl_link_stat2str@Base 3.5.0-1 + rtnl_link_stat2str@libnl_3 3.5.0-1 + rtnl_link_str2carrier@Base 3.5.0-1 + rtnl_link_str2carrier@libnl_3 3.5.0-1 + rtnl_link_str2flags@Base 3.5.0-1 + rtnl_link_str2flags@libnl_3 3.5.0-1 + rtnl_link_str2mode@Base 3.5.0-1 + rtnl_link_str2mode@libnl_3 3.5.0-1 + rtnl_link_str2operstate@Base 3.5.0-1 + rtnl_link_str2operstate@libnl_3 3.5.0-1 + rtnl_link_str2stat@Base 3.5.0-1 + rtnl_link_str2stat@libnl_3 3.5.0-1 + rtnl_link_unregister_info@Base 3.5.0-1 + rtnl_link_unregister_info@libnl_3 3.5.0-1 + rtnl_link_unset_flags@Base 3.5.0-1 + rtnl_link_unset_flags@libnl_3 3.5.0-1 + rtnl_link_unset_vf_list@libnl_3_2_29 3.5.0-1 + rtnl_link_veth_add@Base 3.5.0-1 + rtnl_link_veth_add@libnl_3 3.5.0-1 + rtnl_link_veth_alloc@Base 3.5.0-1 + rtnl_link_veth_alloc@libnl_3 3.5.0-1 + rtnl_link_veth_get_peer@Base 3.5.0-1 + rtnl_link_veth_get_peer@libnl_3 3.5.0-1 + rtnl_link_veth_release@Base 3.5.0-1 + rtnl_link_veth_release@libnl_3 3.5.0-1 + rtnl_link_vf_add@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_alloc@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_free@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_get@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_get_addr@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_get_index@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_get_linkstate@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_get_rate@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_get_rss_query_en@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_get_spoofchk@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_get_stat@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_get_trust@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_get_vlans@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_linkstate2str@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_put@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_set_addr@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_set_ib_node_guid@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_set_ib_port_guid@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_set_index@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_set_linkstate@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_set_rate@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_set_rss_query_en@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_set_spoofchk@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_set_trust@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_set_vlans@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_str2guid@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_str2linkstate@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_str2vlanproto@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_vlan_alloc@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_vlan_free@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_vlan_put@libnl_3_2_29 3.5.0-1 + rtnl_link_vf_vlanproto2str@libnl_3_2_29 3.5.0-1 + rtnl_link_vlan_alloc@Base 3.5.0-1 + rtnl_link_vlan_alloc@libnl_3 3.5.0-1 + rtnl_link_vlan_flags2str@Base 3.5.0-1 + rtnl_link_vlan_flags2str@libnl_3 3.5.0-1 + rtnl_link_vlan_get_egress_map@Base 3.5.0-1 + rtnl_link_vlan_get_egress_map@libnl_3 3.5.0-1 + rtnl_link_vlan_get_flags@Base 3.5.0-1 + rtnl_link_vlan_get_flags@libnl_3 3.5.0-1 + rtnl_link_vlan_get_id@Base 3.5.0-1 + rtnl_link_vlan_get_id@libnl_3 3.5.0-1 + rtnl_link_vlan_get_ingress_map@Base 3.5.0-1 + rtnl_link_vlan_get_ingress_map@libnl_3 3.5.0-1 + rtnl_link_vlan_get_protocol@Base 3.5.0-1 + rtnl_link_vlan_get_protocol@libnl_3 3.5.0-1 + rtnl_link_vlan_set_egress_map@Base 3.5.0-1 + rtnl_link_vlan_set_egress_map@libnl_3 3.5.0-1 + rtnl_link_vlan_set_flags@Base 3.5.0-1 + rtnl_link_vlan_set_flags@libnl_3 3.5.0-1 + rtnl_link_vlan_set_id@Base 3.5.0-1 + rtnl_link_vlan_set_id@libnl_3 3.5.0-1 + rtnl_link_vlan_set_ingress_map@Base 3.5.0-1 + rtnl_link_vlan_set_ingress_map@libnl_3 3.5.0-1 + rtnl_link_vlan_set_protocol@Base 3.5.0-1 + rtnl_link_vlan_set_protocol@libnl_3 3.5.0-1 + rtnl_link_vlan_str2flags@Base 3.5.0-1 + rtnl_link_vlan_str2flags@libnl_3 3.5.0-1 + rtnl_link_vlan_unset_flags@Base 3.5.0-1 + rtnl_link_vlan_unset_flags@libnl_3 3.5.0-1 + rtnl_link_vrf_alloc@libnl_3_2_28 3.5.0-1 + rtnl_link_vrf_get_tableid@libnl_3_2_28 3.5.0-1 + rtnl_link_vrf_set_tableid@libnl_3_2_28 3.5.0-1 + rtnl_link_vxlan_alloc@Base 3.5.0-1 + rtnl_link_vxlan_alloc@libnl_3 3.5.0-1 + rtnl_link_vxlan_disable_l2miss@Base 3.5.0-1 + rtnl_link_vxlan_disable_l2miss@libnl_3 3.5.0-1 + rtnl_link_vxlan_disable_l3miss@Base 3.5.0-1 + rtnl_link_vxlan_disable_l3miss@libnl_3 3.5.0-1 + rtnl_link_vxlan_disable_learning@Base 3.5.0-1 + rtnl_link_vxlan_disable_learning@libnl_3 3.5.0-1 + rtnl_link_vxlan_disable_proxy@Base 3.5.0-1 + rtnl_link_vxlan_disable_proxy@libnl_3 3.5.0-1 + rtnl_link_vxlan_disable_rsc@Base 3.5.0-1 + rtnl_link_vxlan_disable_rsc@libnl_3 3.5.0-1 + rtnl_link_vxlan_enable_l2miss@Base 3.5.0-1 + rtnl_link_vxlan_enable_l2miss@libnl_3 3.5.0-1 + rtnl_link_vxlan_enable_l3miss@Base 3.5.0-1 + rtnl_link_vxlan_enable_l3miss@libnl_3 3.5.0-1 + rtnl_link_vxlan_enable_learning@Base 3.5.0-1 + rtnl_link_vxlan_enable_learning@libnl_3 3.5.0-1 + rtnl_link_vxlan_enable_proxy@Base 3.5.0-1 + rtnl_link_vxlan_enable_proxy@libnl_3 3.5.0-1 + rtnl_link_vxlan_enable_rsc@Base 3.5.0-1 + rtnl_link_vxlan_enable_rsc@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_ageing@Base 3.5.0-1 + rtnl_link_vxlan_get_ageing@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_collect_metadata@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_get_flags@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_get_group@Base 3.5.0-1 + rtnl_link_vxlan_get_group@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_id@Base 3.5.0-1 + rtnl_link_vxlan_get_id@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_l2miss@Base 3.5.0-1 + rtnl_link_vxlan_get_l2miss@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_l3miss@Base 3.5.0-1 + rtnl_link_vxlan_get_l3miss@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_label@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_get_learning@Base 3.5.0-1 + rtnl_link_vxlan_get_learning@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_limit@Base 3.5.0-1 + rtnl_link_vxlan_get_limit@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_link@Base 3.5.0-1 + rtnl_link_vxlan_get_link@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_local@Base 3.5.0-1 + rtnl_link_vxlan_get_local@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_port@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_get_port_range@Base 3.5.0-1 + rtnl_link_vxlan_get_port_range@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_proxy@Base 3.5.0-1 + rtnl_link_vxlan_get_proxy@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_remcsum_rx@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_get_remcsum_tx@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_get_rsc@Base 3.5.0-1 + rtnl_link_vxlan_get_rsc@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_tos@Base 3.5.0-1 + rtnl_link_vxlan_get_tos@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_ttl@Base 3.5.0-1 + rtnl_link_vxlan_get_ttl@libnl_3 3.5.0-1 + rtnl_link_vxlan_get_udp_csum@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_get_udp_zero_csum6_rx@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_get_udp_zero_csum6_tx@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_set_ageing@Base 3.5.0-1 + rtnl_link_vxlan_set_ageing@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_collect_metadata@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_set_flags@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_set_group@Base 3.5.0-1 + rtnl_link_vxlan_set_group@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_id@Base 3.5.0-1 + rtnl_link_vxlan_set_id@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_l2miss@Base 3.5.0-1 + rtnl_link_vxlan_set_l2miss@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_l3miss@Base 3.5.0-1 + rtnl_link_vxlan_set_l3miss@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_label@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_set_learning@Base 3.5.0-1 + rtnl_link_vxlan_set_learning@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_limit@Base 3.5.0-1 + rtnl_link_vxlan_set_limit@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_link@Base 3.5.0-1 + rtnl_link_vxlan_set_link@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_local@Base 3.5.0-1 + rtnl_link_vxlan_set_local@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_port@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_set_port_range@Base 3.5.0-1 + rtnl_link_vxlan_set_port_range@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_proxy@Base 3.5.0-1 + rtnl_link_vxlan_set_proxy@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_remcsum_rx@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_set_remcsum_tx@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_set_rsc@Base 3.5.0-1 + rtnl_link_vxlan_set_rsc@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_tos@Base 3.5.0-1 + rtnl_link_vxlan_set_tos@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_ttl@Base 3.5.0-1 + rtnl_link_vxlan_set_ttl@libnl_3 3.5.0-1 + rtnl_link_vxlan_set_udp_csum@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_set_udp_zero_csum6_rx@libnl_3_2_29 3.5.0-1 + rtnl_link_vxlan_set_udp_zero_csum6_tx@libnl_3_2_29 3.5.0-1 + rtnl_link_xfrmi_alloc@libnl_3_5 3.5.0-1 + rtnl_link_xfrmi_get_if_id@libnl_3_5 3.5.0-1 + rtnl_link_xfrmi_get_link@libnl_3_5 3.5.0-1 + rtnl_link_xfrmi_set_if_id@libnl_3_5 3.5.0-1 + rtnl_link_xfrmi_set_link@libnl_3_5 3.5.0-1 + rtnl_mall_append_action@libnl_3_5 3.5.0-1 + rtnl_mall_del_action@libnl_3_5 3.5.0-1 + rtnl_mall_get_classid@libnl_3_5 3.5.0-1 + rtnl_mall_get_first_action@libnl_3_5 3.5.0-1 + rtnl_mall_get_flags@libnl_3_5 3.5.0-1 + rtnl_mall_set_classid@libnl_3_5 3.5.0-1 + rtnl_mall_set_flags@libnl_3_5 3.5.0-1 + rtnl_meta_value_alloc_id@Base 3.5.0-1 + rtnl_meta_value_alloc_id@libnl_3 3.5.0-1 + rtnl_meta_value_alloc_int@Base 3.5.0-1 + rtnl_meta_value_alloc_int@libnl_3 3.5.0-1 + rtnl_meta_value_alloc_var@Base 3.5.0-1 + rtnl_meta_value_alloc_var@libnl_3 3.5.0-1 + rtnl_meta_value_put@Base 3.5.0-1 + rtnl_meta_value_put@libnl_3 3.5.0-1 + rtnl_mirred_get_action@Base 3.5.0-1 + rtnl_mirred_get_action@libnl_3 3.5.0-1 + rtnl_mirred_get_ifindex@Base 3.5.0-1 + rtnl_mirred_get_ifindex@libnl_3 3.5.0-1 + rtnl_mirred_get_policy@Base 3.5.0-1 + rtnl_mirred_get_policy@libnl_3 3.5.0-1 + rtnl_mirred_set_action@Base 3.5.0-1 + rtnl_mirred_set_action@libnl_3 3.5.0-1 + rtnl_mirred_set_ifindex@Base 3.5.0-1 + rtnl_mirred_set_ifindex@libnl_3 3.5.0-1 + rtnl_mirred_set_policy@Base 3.5.0-1 + rtnl_mirred_set_policy@libnl_3 3.5.0-1 + rtnl_neigh_add@Base 3.5.0-1 + rtnl_neigh_add@libnl_3 3.5.0-1 + rtnl_neigh_alloc@Base 3.5.0-1 + rtnl_neigh_alloc@libnl_3 3.5.0-1 + rtnl_neigh_alloc_cache@Base 3.5.0-1 + rtnl_neigh_alloc_cache@libnl_3 3.5.0-1 + rtnl_neigh_alloc_cache_flags@libnl_3_2_28 3.5.0-1 + rtnl_neigh_build_add_request@Base 3.5.0-1 + rtnl_neigh_build_add_request@libnl_3 3.5.0-1 + rtnl_neigh_build_delete_request@Base 3.5.0-1 + rtnl_neigh_build_delete_request@libnl_3 3.5.0-1 + rtnl_neigh_delete@Base 3.5.0-1 + rtnl_neigh_delete@libnl_3 3.5.0-1 + rtnl_neigh_flags2str@Base 3.5.0-1 + rtnl_neigh_flags2str@libnl_3 3.5.0-1 + rtnl_neigh_get@Base 3.5.0-1 + rtnl_neigh_get@libnl_3 3.5.0-1 + rtnl_neigh_get_by_vlan@libnl_3_5 3.5.0-1 + rtnl_neigh_get_dst@Base 3.5.0-1 + rtnl_neigh_get_dst@libnl_3 3.5.0-1 + rtnl_neigh_get_family@Base 3.5.0-1 + rtnl_neigh_get_family@libnl_3 3.5.0-1 + rtnl_neigh_get_flags@Base 3.5.0-1 + rtnl_neigh_get_flags@libnl_3 3.5.0-1 + rtnl_neigh_get_ifindex@Base 3.5.0-1 + rtnl_neigh_get_ifindex@libnl_3 3.5.0-1 + rtnl_neigh_get_lladdr@Base 3.5.0-1 + rtnl_neigh_get_lladdr@libnl_3 3.5.0-1 + rtnl_neigh_get_master@libnl_3_5 3.5.0-1 + rtnl_neigh_get_state@Base 3.5.0-1 + rtnl_neigh_get_state@libnl_3 3.5.0-1 + rtnl_neigh_get_type@Base 3.5.0-1 + rtnl_neigh_get_type@libnl_3 3.5.0-1 + rtnl_neigh_get_vlan@Base 3.5.0-1 + rtnl_neigh_get_vlan@libnl_3_2_26 3.5.0-1 + rtnl_neigh_parse@Base 3.5.0-1 + rtnl_neigh_parse@libnl_3 3.5.0-1 + rtnl_neigh_put@Base 3.5.0-1 + rtnl_neigh_put@libnl_3 3.5.0-1 + rtnl_neigh_set_dst@Base 3.5.0-1 + rtnl_neigh_set_dst@libnl_3 3.5.0-1 + rtnl_neigh_set_family@Base 3.5.0-1 + rtnl_neigh_set_family@libnl_3 3.5.0-1 + rtnl_neigh_set_flags@Base 3.5.0-1 + rtnl_neigh_set_flags@libnl_3 3.5.0-1 + rtnl_neigh_set_ifindex@Base 3.5.0-1 + rtnl_neigh_set_ifindex@libnl_3 3.5.0-1 + rtnl_neigh_set_lladdr@Base 3.5.0-1 + rtnl_neigh_set_lladdr@libnl_3 3.5.0-1 + rtnl_neigh_set_master@libnl_3_5 3.5.0-1 + rtnl_neigh_set_state@Base 3.5.0-1 + rtnl_neigh_set_state@libnl_3 3.5.0-1 + rtnl_neigh_set_type@Base 3.5.0-1 + rtnl_neigh_set_type@libnl_3 3.5.0-1 + rtnl_neigh_set_vlan@Base 3.5.0-1 + rtnl_neigh_set_vlan@libnl_3_2_26 3.5.0-1 + rtnl_neigh_state2str@Base 3.5.0-1 + rtnl_neigh_state2str@libnl_3 3.5.0-1 + rtnl_neigh_str2flag@Base 3.5.0-1 + rtnl_neigh_str2flag@libnl_3 3.5.0-1 + rtnl_neigh_str2state@Base 3.5.0-1 + rtnl_neigh_str2state@libnl_3 3.5.0-1 + rtnl_neigh_unset_flags@Base 3.5.0-1 + rtnl_neigh_unset_flags@libnl_3 3.5.0-1 + rtnl_neigh_unset_state@Base 3.5.0-1 + rtnl_neigh_unset_state@libnl_3 3.5.0-1 + rtnl_neightbl_alloc@Base 3.5.0-1 + rtnl_neightbl_alloc@libnl_3 3.5.0-1 + rtnl_neightbl_alloc_cache@Base 3.5.0-1 + rtnl_neightbl_alloc_cache@libnl_3 3.5.0-1 + rtnl_neightbl_build_change_request@Base 3.5.0-1 + rtnl_neightbl_build_change_request@libnl_3 3.5.0-1 + rtnl_neightbl_change@Base 3.5.0-1 + rtnl_neightbl_change@libnl_3 3.5.0-1 + rtnl_neightbl_get@Base 3.5.0-1 + rtnl_neightbl_get@libnl_3 3.5.0-1 + rtnl_neightbl_put@Base 3.5.0-1 + rtnl_neightbl_put@libnl_3 3.5.0-1 + rtnl_neightbl_set_anycast_delay@Base 3.5.0-1 + rtnl_neightbl_set_anycast_delay@libnl_3 3.5.0-1 + rtnl_neightbl_set_app_probes@Base 3.5.0-1 + rtnl_neightbl_set_app_probes@libnl_3 3.5.0-1 + rtnl_neightbl_set_base_reachable_time@Base 3.5.0-1 + rtnl_neightbl_set_base_reachable_time@libnl_3 3.5.0-1 + rtnl_neightbl_set_delay_probe_time@Base 3.5.0-1 + rtnl_neightbl_set_delay_probe_time@libnl_3 3.5.0-1 + rtnl_neightbl_set_dev@Base 3.5.0-1 + rtnl_neightbl_set_dev@libnl_3 3.5.0-1 + rtnl_neightbl_set_family@Base 3.5.0-1 + rtnl_neightbl_set_family@libnl_3 3.5.0-1 + rtnl_neightbl_set_gc_interval@Base 3.5.0-1 + rtnl_neightbl_set_gc_interval@libnl_3 3.5.0-1 + rtnl_neightbl_set_gc_stale_time@Base 3.5.0-1 + rtnl_neightbl_set_gc_stale_time@libnl_3 3.5.0-1 + rtnl_neightbl_set_gc_tresh1@Base 3.5.0-1 + rtnl_neightbl_set_gc_tresh1@libnl_3 3.5.0-1 + rtnl_neightbl_set_gc_tresh2@Base 3.5.0-1 + rtnl_neightbl_set_gc_tresh2@libnl_3 3.5.0-1 + rtnl_neightbl_set_gc_tresh3@Base 3.5.0-1 + rtnl_neightbl_set_gc_tresh3@libnl_3 3.5.0-1 + rtnl_neightbl_set_locktime@Base 3.5.0-1 + rtnl_neightbl_set_locktime@libnl_3 3.5.0-1 + rtnl_neightbl_set_mcast_probes@Base 3.5.0-1 + rtnl_neightbl_set_mcast_probes@libnl_3 3.5.0-1 + rtnl_neightbl_set_name@Base 3.5.0-1 + rtnl_neightbl_set_name@libnl_3 3.5.0-1 + rtnl_neightbl_set_proxy_delay@Base 3.5.0-1 + rtnl_neightbl_set_proxy_delay@libnl_3 3.5.0-1 + rtnl_neightbl_set_proxy_queue_len@Base 3.5.0-1 + rtnl_neightbl_set_proxy_queue_len@libnl_3 3.5.0-1 + rtnl_neightbl_set_queue_len@Base 3.5.0-1 + rtnl_neightbl_set_queue_len@libnl_3 3.5.0-1 + rtnl_neightbl_set_retrans_time@Base 3.5.0-1 + rtnl_neightbl_set_retrans_time@libnl_3 3.5.0-1 + rtnl_neightbl_set_ucast_probes@Base 3.5.0-1 + rtnl_neightbl_set_ucast_probes@libnl_3 3.5.0-1 + rtnl_netconf_get_all@libnl_3_4 3.5.0-1 + rtnl_netconf_get_by_idx@libnl_3_4 3.5.0-1 + rtnl_netconf_get_default@libnl_3_4 3.5.0-1 + rtnl_netconf_get_family@libnl_3_4 3.5.0-1 + rtnl_netconf_get_forwarding@libnl_3_4 3.5.0-1 + rtnl_netconf_get_ifindex@libnl_3_4 3.5.0-1 + rtnl_netconf_get_input@libnl_3_4 3.5.0-1 + rtnl_netconf_get_mc_forwarding@libnl_3_4 3.5.0-1 + rtnl_netconf_get_rp_filter@libnl_3_4 3.5.0-1 + rtnl_netconf_put@libnl_3_4 3.5.0-1 + rtnl_netem_get_corruption_correlation@Base 3.5.0-1 + rtnl_netem_get_corruption_correlation@libnl_3 3.5.0-1 + rtnl_netem_get_corruption_probability@Base 3.5.0-1 + rtnl_netem_get_corruption_probability@libnl_3 3.5.0-1 + rtnl_netem_get_delay@Base 3.5.0-1 + rtnl_netem_get_delay@libnl_3 3.5.0-1 + rtnl_netem_get_delay_correlation@Base 3.5.0-1 + rtnl_netem_get_delay_correlation@libnl_3 3.5.0-1 + rtnl_netem_get_delay_distribution@Base 3.5.0-1 + rtnl_netem_get_delay_distribution@libnl_3 3.5.0-1 + rtnl_netem_get_delay_distribution_size@Base 3.5.0-1 + rtnl_netem_get_delay_distribution_size@libnl_3 3.5.0-1 + rtnl_netem_get_duplicate@Base 3.5.0-1 + rtnl_netem_get_duplicate@libnl_3 3.5.0-1 + rtnl_netem_get_duplicate_correlation@Base 3.5.0-1 + rtnl_netem_get_duplicate_correlation@libnl_3 3.5.0-1 + rtnl_netem_get_gap@Base 3.5.0-1 + rtnl_netem_get_gap@libnl_3 3.5.0-1 + rtnl_netem_get_jitter@Base 3.5.0-1 + rtnl_netem_get_jitter@libnl_3 3.5.0-1 + rtnl_netem_get_limit@Base 3.5.0-1 + rtnl_netem_get_limit@libnl_3 3.5.0-1 + rtnl_netem_get_loss@Base 3.5.0-1 + rtnl_netem_get_loss@libnl_3 3.5.0-1 + rtnl_netem_get_loss_correlation@Base 3.5.0-1 + rtnl_netem_get_loss_correlation@libnl_3 3.5.0-1 + rtnl_netem_get_reorder_correlation@Base 3.5.0-1 + rtnl_netem_get_reorder_correlation@libnl_3 3.5.0-1 + rtnl_netem_get_reorder_probability@Base 3.5.0-1 + rtnl_netem_get_reorder_probability@libnl_3 3.5.0-1 + rtnl_netem_set_corruption_correlation@Base 3.5.0-1 + rtnl_netem_set_corruption_correlation@libnl_3 3.5.0-1 + rtnl_netem_set_corruption_probability@Base 3.5.0-1 + rtnl_netem_set_corruption_probability@libnl_3 3.5.0-1 + rtnl_netem_set_delay@Base 3.5.0-1 + rtnl_netem_set_delay@libnl_3 3.5.0-1 + rtnl_netem_set_delay_correlation@Base 3.5.0-1 + rtnl_netem_set_delay_correlation@libnl_3 3.5.0-1 + rtnl_netem_set_delay_distribution@Base 3.5.0-1 + rtnl_netem_set_delay_distribution@libnl_3 3.5.0-1 + rtnl_netem_set_delay_distribution_data@libnl_3_5 3.5.0-1 + rtnl_netem_set_duplicate@Base 3.5.0-1 + rtnl_netem_set_duplicate@libnl_3 3.5.0-1 + rtnl_netem_set_duplicate_correlation@Base 3.5.0-1 + rtnl_netem_set_duplicate_correlation@libnl_3 3.5.0-1 + rtnl_netem_set_gap@Base 3.5.0-1 + rtnl_netem_set_gap@libnl_3 3.5.0-1 + rtnl_netem_set_jitter@Base 3.5.0-1 + rtnl_netem_set_jitter@libnl_3 3.5.0-1 + rtnl_netem_set_limit@Base 3.5.0-1 + rtnl_netem_set_limit@libnl_3 3.5.0-1 + rtnl_netem_set_loss@Base 3.5.0-1 + rtnl_netem_set_loss@libnl_3 3.5.0-1 + rtnl_netem_set_loss_correlation@Base 3.5.0-1 + rtnl_netem_set_loss_correlation@libnl_3 3.5.0-1 + rtnl_netem_set_reorder_correlation@Base 3.5.0-1 + rtnl_netem_set_reorder_correlation@libnl_3 3.5.0-1 + rtnl_netem_set_reorder_probability@Base 3.5.0-1 + rtnl_netem_set_reorder_probability@libnl_3 3.5.0-1 + rtnl_pktloc_add@Base 3.5.0-1 + rtnl_pktloc_add@libnl_3 3.5.0-1 + rtnl_pktloc_alloc@Base 3.5.0-1 + rtnl_pktloc_alloc@libnl_3 3.5.0-1 + rtnl_pktloc_foreach@Base 3.5.0-1 + rtnl_pktloc_foreach@libnl_3 3.5.0-1 + rtnl_pktloc_lookup@Base 3.5.0-1 + rtnl_pktloc_lookup@libnl_3 3.5.0-1 + rtnl_pktloc_put@Base 3.5.0-1 + rtnl_pktloc_put@libnl_3 3.5.0-1 + rtnl_prio2str@Base 3.5.0-1 + rtnl_prio2str@libnl_3 3.5.0-1 + rtnl_qdisc_add@Base 3.5.0-1 + rtnl_qdisc_add@libnl_3 3.5.0-1 + rtnl_qdisc_alloc@Base 3.5.0-1 + rtnl_qdisc_alloc@libnl_3 3.5.0-1 + rtnl_qdisc_alloc_cache@Base 3.5.0-1 + rtnl_qdisc_alloc_cache@libnl_3 3.5.0-1 + rtnl_qdisc_build_add_request@Base 3.5.0-1 + rtnl_qdisc_build_add_request@libnl_3 3.5.0-1 + rtnl_qdisc_build_change_request@Base 3.5.0-1 + rtnl_qdisc_build_change_request@libnl_3 3.5.0-1 + rtnl_qdisc_build_delete_request@Base 3.5.0-1 + rtnl_qdisc_build_delete_request@libnl_3 3.5.0-1 + rtnl_qdisc_build_update_request@Base 3.5.0-1 + rtnl_qdisc_build_update_request@libnl_3 3.5.0-1 + rtnl_qdisc_change@Base 3.5.0-1 + rtnl_qdisc_change@libnl_3 3.5.0-1 + rtnl_qdisc_delete@Base 3.5.0-1 + rtnl_qdisc_delete@libnl_3 3.5.0-1 + rtnl_qdisc_dsmark_get_default_index@Base 3.5.0-1 + rtnl_qdisc_dsmark_get_default_index@libnl_3 3.5.0-1 + rtnl_qdisc_dsmark_get_indices@Base 3.5.0-1 + rtnl_qdisc_dsmark_get_indices@libnl_3 3.5.0-1 + rtnl_qdisc_dsmark_get_set_tc_index@Base 3.5.0-1 + rtnl_qdisc_dsmark_get_set_tc_index@libnl_3 3.5.0-1 + rtnl_qdisc_dsmark_set_default_index@Base 3.5.0-1 + rtnl_qdisc_dsmark_set_default_index@libnl_3 3.5.0-1 + rtnl_qdisc_dsmark_set_indices@Base 3.5.0-1 + rtnl_qdisc_dsmark_set_indices@libnl_3 3.5.0-1 + rtnl_qdisc_dsmark_set_set_tc_index@Base 3.5.0-1 + rtnl_qdisc_dsmark_set_set_tc_index@libnl_3 3.5.0-1 + rtnl_qdisc_fifo_get_limit@Base 3.5.0-1 + rtnl_qdisc_fifo_get_limit@libnl_3 3.5.0-1 + rtnl_qdisc_fifo_set_limit@Base 3.5.0-1 + rtnl_qdisc_fifo_set_limit@libnl_3 3.5.0-1 + rtnl_qdisc_foreach_child@Base 3.5.0-1 + rtnl_qdisc_foreach_child@libnl_3 3.5.0-1 + rtnl_qdisc_foreach_cls@Base 3.5.0-1 + rtnl_qdisc_foreach_cls@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_get_ecn@Base 3.5.0-1 + rtnl_qdisc_fq_codel_get_ecn@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_get_flows@Base 3.5.0-1 + rtnl_qdisc_fq_codel_get_flows@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_get_interval@Base 3.5.0-1 + rtnl_qdisc_fq_codel_get_interval@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_get_limit@Base 3.5.0-1 + rtnl_qdisc_fq_codel_get_limit@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_get_quantum@Base 3.5.0-1 + rtnl_qdisc_fq_codel_get_quantum@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_get_target@Base 3.5.0-1 + rtnl_qdisc_fq_codel_get_target@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_set_ecn@Base 3.5.0-1 + rtnl_qdisc_fq_codel_set_ecn@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_set_flows@Base 3.5.0-1 + rtnl_qdisc_fq_codel_set_flows@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_set_interval@Base 3.5.0-1 + rtnl_qdisc_fq_codel_set_interval@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_set_limit@Base 3.5.0-1 + rtnl_qdisc_fq_codel_set_limit@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_set_quantum@Base 3.5.0-1 + rtnl_qdisc_fq_codel_set_quantum@libnl_3 3.5.0-1 + rtnl_qdisc_fq_codel_set_target@Base 3.5.0-1 + rtnl_qdisc_fq_codel_set_target@libnl_3 3.5.0-1 + rtnl_qdisc_get@Base 3.5.0-1 + rtnl_qdisc_get@libnl_3 3.5.0-1 + rtnl_qdisc_get_by_parent@Base 3.5.0-1 + rtnl_qdisc_get_by_parent@libnl_3 3.5.0-1 + rtnl_qdisc_hfsc_get_defcls@Base 3.5.0-1 + rtnl_qdisc_hfsc_get_defcls@libnl_3 3.5.0-1 + rtnl_qdisc_hfsc_set_defcls@Base 3.5.0-1 + rtnl_qdisc_hfsc_set_defcls@libnl_3 3.5.0-1 + rtnl_qdisc_mqprio_get_hw_offload@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_get_max_rate@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_get_min_rate@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_get_mode@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_get_num_tc@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_get_priomap@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_get_queue@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_get_shaper@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_hw_offload@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_set_max_rate@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_set_min_rate@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_set_mode@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_set_num_tc@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_set_priomap@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_set_queue@libnl_3_5 3.5.0-1 + rtnl_qdisc_mqprio_set_shaper@libnl_3_5 3.5.0-1 + rtnl_qdisc_plug_buffer@Base 3.5.0-1 + rtnl_qdisc_plug_buffer@libnl_3 3.5.0-1 + rtnl_qdisc_plug_release_indefinite@Base 3.5.0-1 + rtnl_qdisc_plug_release_indefinite@libnl_3 3.5.0-1 + rtnl_qdisc_plug_release_one@Base 3.5.0-1 + rtnl_qdisc_plug_release_one@libnl_3 3.5.0-1 + rtnl_qdisc_plug_set_limit@Base 3.5.0-1 + rtnl_qdisc_plug_set_limit@libnl_3 3.5.0-1 + rtnl_qdisc_prio_get_bands@Base 3.5.0-1 + rtnl_qdisc_prio_get_bands@libnl_3 3.5.0-1 + rtnl_qdisc_prio_get_priomap@Base 3.5.0-1 + rtnl_qdisc_prio_get_priomap@libnl_3 3.5.0-1 + rtnl_qdisc_prio_set_bands@Base 3.5.0-1 + rtnl_qdisc_prio_set_bands@libnl_3 3.5.0-1 + rtnl_qdisc_prio_set_priomap@Base 3.5.0-1 + rtnl_qdisc_prio_set_priomap@libnl_3 3.5.0-1 + rtnl_qdisc_put@Base 3.5.0-1 + rtnl_qdisc_put@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_get_limit@Base 3.5.0-1 + rtnl_qdisc_tbf_get_limit@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_get_peakrate@Base 3.5.0-1 + rtnl_qdisc_tbf_get_peakrate@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_get_peakrate_bucket@Base 3.5.0-1 + rtnl_qdisc_tbf_get_peakrate_bucket@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_get_peakrate_cell@Base 3.5.0-1 + rtnl_qdisc_tbf_get_peakrate_cell@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_get_rate@Base 3.5.0-1 + rtnl_qdisc_tbf_get_rate@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_get_rate_bucket@Base 3.5.0-1 + rtnl_qdisc_tbf_get_rate_bucket@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_get_rate_cell@Base 3.5.0-1 + rtnl_qdisc_tbf_get_rate_cell@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_set_limit@Base 3.5.0-1 + rtnl_qdisc_tbf_set_limit@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_set_limit_by_latency@Base 3.5.0-1 + rtnl_qdisc_tbf_set_limit_by_latency@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_set_peakrate@Base 3.5.0-1 + rtnl_qdisc_tbf_set_peakrate@libnl_3 3.5.0-1 + rtnl_qdisc_tbf_set_rate@Base 3.5.0-1 + rtnl_qdisc_tbf_set_rate@libnl_3 3.5.0-1 + rtnl_qdisc_update@Base 3.5.0-1 + rtnl_qdisc_update@libnl_3 3.5.0-1 + rtnl_realms2str@Base 3.5.0-1 + rtnl_realms2str@libnl_3 3.5.0-1 + rtnl_red_get_limit@Base 3.5.0-1 + rtnl_red_get_limit@libnl_3 3.5.0-1 + rtnl_red_set_limit@Base 3.5.0-1 + rtnl_red_set_limit@libnl_3 3.5.0-1 + rtnl_route_add@Base 3.5.0-1 + rtnl_route_add@libnl_3 3.5.0-1 + rtnl_route_add_nexthop@Base 3.5.0-1 + rtnl_route_add_nexthop@libnl_3 3.5.0-1 + rtnl_route_alloc@Base 3.5.0-1 + rtnl_route_alloc@libnl_3 3.5.0-1 + rtnl_route_alloc_cache@Base 3.5.0-1 + rtnl_route_alloc_cache@libnl_3 3.5.0-1 + rtnl_route_build_add_request@Base 3.5.0-1 + rtnl_route_build_add_request@libnl_3 3.5.0-1 + rtnl_route_build_del_request@Base 3.5.0-1 + rtnl_route_build_del_request@libnl_3 3.5.0-1 + rtnl_route_build_msg@Base 3.5.0-1 + rtnl_route_build_msg@libnl_3 3.5.0-1 + rtnl_route_delete@Base 3.5.0-1 + rtnl_route_delete@libnl_3 3.5.0-1 + rtnl_route_foreach_nexthop@Base 3.5.0-1 + rtnl_route_foreach_nexthop@libnl_3 3.5.0-1 + rtnl_route_get@Base 3.5.0-1 + rtnl_route_get@libnl_3 3.5.0-1 + rtnl_route_get_dst@Base 3.5.0-1 + rtnl_route_get_dst@libnl_3 3.5.0-1 + rtnl_route_get_family@Base 3.5.0-1 + rtnl_route_get_family@libnl_3 3.5.0-1 + rtnl_route_get_flags@Base 3.5.0-1 + rtnl_route_get_flags@libnl_3 3.5.0-1 + rtnl_route_get_iif@Base 3.5.0-1 + rtnl_route_get_iif@libnl_3 3.5.0-1 + rtnl_route_get_metric@Base 3.5.0-1 + rtnl_route_get_metric@libnl_3 3.5.0-1 + rtnl_route_get_nexthops@Base 3.5.0-1 + rtnl_route_get_nexthops@libnl_3 3.5.0-1 + rtnl_route_get_nnexthops@Base 3.5.0-1 + rtnl_route_get_nnexthops@libnl_3 3.5.0-1 + rtnl_route_get_pref_src@Base 3.5.0-1 + rtnl_route_get_pref_src@libnl_3 3.5.0-1 + rtnl_route_get_priority@Base 3.5.0-1 + rtnl_route_get_priority@libnl_3 3.5.0-1 + rtnl_route_get_protocol@Base 3.5.0-1 + rtnl_route_get_protocol@libnl_3 3.5.0-1 + rtnl_route_get_scope@Base 3.5.0-1 + rtnl_route_get_scope@libnl_3 3.5.0-1 + rtnl_route_get_src@Base 3.5.0-1 + rtnl_route_get_src@libnl_3 3.5.0-1 + rtnl_route_get_table@Base 3.5.0-1 + rtnl_route_get_table@libnl_3 3.5.0-1 + rtnl_route_get_tos@Base 3.5.0-1 + rtnl_route_get_tos@libnl_3 3.5.0-1 + rtnl_route_get_ttl_propagate@libnl_3_4 3.5.0-1 + rtnl_route_get_type@Base 3.5.0-1 + rtnl_route_get_type@libnl_3 3.5.0-1 + rtnl_route_guess_scope@Base 3.5.0-1 + rtnl_route_guess_scope@libnl_3 3.5.0-1 + rtnl_route_metric2str@Base 3.5.0-1 + rtnl_route_metric2str@libnl_3 3.5.0-1 + rtnl_route_nexthop_n@Base 3.5.0-1 + rtnl_route_nexthop_n@libnl_3 3.5.0-1 + rtnl_route_nh_alloc@Base 3.5.0-1 + rtnl_route_nh_alloc@libnl_3 3.5.0-1 + rtnl_route_nh_clone@Base 3.5.0-1 + rtnl_route_nh_clone@libnl_3 3.5.0-1 + rtnl_route_nh_compare@Base 3.5.0-1 + rtnl_route_nh_compare@libnl_3 3.5.0-1 + rtnl_route_nh_dump@Base 3.5.0-1 + rtnl_route_nh_dump@libnl_3 3.5.0-1 + rtnl_route_nh_encap_mpls@libnl_3_4 3.5.0-1 + rtnl_route_nh_flags2str@Base 3.5.0-1 + rtnl_route_nh_flags2str@libnl_3 3.5.0-1 + rtnl_route_nh_free@Base 3.5.0-1 + rtnl_route_nh_free@libnl_3 3.5.0-1 + rtnl_route_nh_get_flags@Base 3.5.0-1 + rtnl_route_nh_get_flags@libnl_3 3.5.0-1 + rtnl_route_nh_get_gateway@Base 3.5.0-1 + rtnl_route_nh_get_gateway@libnl_3 3.5.0-1 + rtnl_route_nh_get_ifindex@Base 3.5.0-1 + rtnl_route_nh_get_ifindex@libnl_3 3.5.0-1 + rtnl_route_nh_get_newdst@libnl_3_4 3.5.0-1 + rtnl_route_nh_get_realms@Base 3.5.0-1 + rtnl_route_nh_get_realms@libnl_3 3.5.0-1 + rtnl_route_nh_get_via@libnl_3_4 3.5.0-1 + rtnl_route_nh_get_weight@Base 3.5.0-1 + rtnl_route_nh_get_weight@libnl_3 3.5.0-1 + rtnl_route_nh_set_flags@Base 3.5.0-1 + rtnl_route_nh_set_flags@libnl_3 3.5.0-1 + rtnl_route_nh_set_gateway@Base 3.5.0-1 + rtnl_route_nh_set_gateway@libnl_3 3.5.0-1 + rtnl_route_nh_set_ifindex@Base 3.5.0-1 + rtnl_route_nh_set_ifindex@libnl_3 3.5.0-1 + rtnl_route_nh_set_newdst@libnl_3_4 3.5.0-1 + rtnl_route_nh_set_realms@Base 3.5.0-1 + rtnl_route_nh_set_realms@libnl_3 3.5.0-1 + rtnl_route_nh_set_via@libnl_3_4 3.5.0-1 + rtnl_route_nh_set_weight@Base 3.5.0-1 + rtnl_route_nh_set_weight@libnl_3 3.5.0-1 + rtnl_route_nh_str2flags@Base 3.5.0-1 + rtnl_route_nh_str2flags@libnl_3 3.5.0-1 + rtnl_route_nh_unset_flags@Base 3.5.0-1 + rtnl_route_nh_unset_flags@libnl_3 3.5.0-1 + rtnl_route_parse@Base 3.5.0-1 + rtnl_route_parse@libnl_3 3.5.0-1 + rtnl_route_proto2str@Base 3.5.0-1 + rtnl_route_proto2str@libnl_3 3.5.0-1 + rtnl_route_put@Base 3.5.0-1 + rtnl_route_put@libnl_3 3.5.0-1 + rtnl_route_read_protocol_names@Base 3.5.0-1 + rtnl_route_read_protocol_names@libnl_3 3.5.0-1 + rtnl_route_read_table_names@Base 3.5.0-1 + rtnl_route_read_table_names@libnl_3 3.5.0-1 + rtnl_route_remove_nexthop@Base 3.5.0-1 + rtnl_route_remove_nexthop@libnl_3 3.5.0-1 + rtnl_route_set_dst@Base 3.5.0-1 + rtnl_route_set_dst@libnl_3 3.5.0-1 + rtnl_route_set_family@Base 3.5.0-1 + rtnl_route_set_family@libnl_3 3.5.0-1 + rtnl_route_set_flags@Base 3.5.0-1 + rtnl_route_set_flags@libnl_3 3.5.0-1 + rtnl_route_set_iif@Base 3.5.0-1 + rtnl_route_set_iif@libnl_3 3.5.0-1 + rtnl_route_set_metric@Base 3.5.0-1 + rtnl_route_set_metric@libnl_3 3.5.0-1 + rtnl_route_set_pref_src@Base 3.5.0-1 + rtnl_route_set_pref_src@libnl_3 3.5.0-1 + rtnl_route_set_priority@Base 3.5.0-1 + rtnl_route_set_priority@libnl_3 3.5.0-1 + rtnl_route_set_protocol@Base 3.5.0-1 + rtnl_route_set_protocol@libnl_3 3.5.0-1 + rtnl_route_set_scope@Base 3.5.0-1 + rtnl_route_set_scope@libnl_3 3.5.0-1 + rtnl_route_set_src@Base 3.5.0-1 + rtnl_route_set_src@libnl_3 3.5.0-1 + rtnl_route_set_table@Base 3.5.0-1 + rtnl_route_set_table@libnl_3 3.5.0-1 + rtnl_route_set_tos@Base 3.5.0-1 + rtnl_route_set_tos@libnl_3 3.5.0-1 + rtnl_route_set_ttl_propagate@libnl_3_4 3.5.0-1 + rtnl_route_set_type@Base 3.5.0-1 + rtnl_route_set_type@libnl_3 3.5.0-1 + rtnl_route_str2metric@Base 3.5.0-1 + rtnl_route_str2metric@libnl_3 3.5.0-1 + rtnl_route_str2proto@Base 3.5.0-1 + rtnl_route_str2proto@libnl_3 3.5.0-1 + rtnl_route_str2table@Base 3.5.0-1 + rtnl_route_str2table@libnl_3 3.5.0-1 + rtnl_route_table2str@Base 3.5.0-1 + rtnl_route_table2str@libnl_3 3.5.0-1 + rtnl_route_unset_flags@Base 3.5.0-1 + rtnl_route_unset_flags@libnl_3 3.5.0-1 + rtnl_route_unset_metric@Base 3.5.0-1 + rtnl_route_unset_metric@libnl_3 3.5.0-1 + rtnl_rule_add@Base 3.5.0-1 + rtnl_rule_add@libnl_3 3.5.0-1 + rtnl_rule_alloc@Base 3.5.0-1 + rtnl_rule_alloc@libnl_3 3.5.0-1 + rtnl_rule_alloc_cache@Base 3.5.0-1 + rtnl_rule_alloc_cache@libnl_3 3.5.0-1 + rtnl_rule_build_add_request@Base 3.5.0-1 + rtnl_rule_build_add_request@libnl_3 3.5.0-1 + rtnl_rule_build_delete_request@Base 3.5.0-1 + rtnl_rule_build_delete_request@libnl_3 3.5.0-1 + rtnl_rule_delete@Base 3.5.0-1 + rtnl_rule_delete@libnl_3 3.5.0-1 + rtnl_rule_get_action@Base 3.5.0-1 + rtnl_rule_get_action@libnl_3 3.5.0-1 + rtnl_rule_get_dport@libnl_3_5 3.5.0-1 + rtnl_rule_get_dsfield@Base 3.5.0-1 + rtnl_rule_get_dsfield@libnl_3 3.5.0-1 + rtnl_rule_get_dst@Base 3.5.0-1 + rtnl_rule_get_dst@libnl_3 3.5.0-1 + rtnl_rule_get_family@Base 3.5.0-1 + rtnl_rule_get_family@libnl_3 3.5.0-1 + rtnl_rule_get_goto@Base 3.5.0-1 + rtnl_rule_get_goto@libnl_3 3.5.0-1 + rtnl_rule_get_iif@Base 3.5.0-1 + rtnl_rule_get_iif@libnl_3 3.5.0-1 + rtnl_rule_get_ipproto@libnl_3_5 3.5.0-1 + rtnl_rule_get_l3mdev@libnl_3_4 3.5.0-1 + rtnl_rule_get_mark@Base 3.5.0-1 + rtnl_rule_get_mark@libnl_3 3.5.0-1 + rtnl_rule_get_mask@Base 3.5.0-1 + rtnl_rule_get_mask@libnl_3 3.5.0-1 + rtnl_rule_get_oif@Base 3.5.0-1 + rtnl_rule_get_oif@libnl_3 3.5.0-1 + rtnl_rule_get_prio@Base 3.5.0-1 + rtnl_rule_get_prio@libnl_3 3.5.0-1 + rtnl_rule_get_protocol@libnl_3_5 3.5.0-1 + rtnl_rule_get_realms@Base 3.5.0-1 + rtnl_rule_get_realms@libnl_3 3.5.0-1 + rtnl_rule_get_sport@libnl_3_5 3.5.0-1 + rtnl_rule_get_src@Base 3.5.0-1 + rtnl_rule_get_src@libnl_3 3.5.0-1 + rtnl_rule_get_table@Base 3.5.0-1 + rtnl_rule_get_table@libnl_3 3.5.0-1 + rtnl_rule_put@Base 3.5.0-1 + rtnl_rule_put@libnl_3 3.5.0-1 + rtnl_rule_set_action@Base 3.5.0-1 + rtnl_rule_set_action@libnl_3 3.5.0-1 + rtnl_rule_set_dport@libnl_3_5 3.5.0-1 + rtnl_rule_set_dport_range@libnl_3_5 3.5.0-1 + rtnl_rule_set_dsfield@Base 3.5.0-1 + rtnl_rule_set_dsfield@libnl_3 3.5.0-1 + rtnl_rule_set_dst@Base 3.5.0-1 + rtnl_rule_set_dst@libnl_3 3.5.0-1 + rtnl_rule_set_family@Base 3.5.0-1 + rtnl_rule_set_family@libnl_3 3.5.0-1 + rtnl_rule_set_goto@Base 3.5.0-1 + rtnl_rule_set_goto@libnl_3 3.5.0-1 + rtnl_rule_set_iif@Base 3.5.0-1 + rtnl_rule_set_iif@libnl_3 3.5.0-1 + rtnl_rule_set_ipproto@libnl_3_5 3.5.0-1 + rtnl_rule_set_l3mdev@libnl_3_4 3.5.0-1 + rtnl_rule_set_mark@Base 3.5.0-1 + rtnl_rule_set_mark@libnl_3 3.5.0-1 + rtnl_rule_set_mask@Base 3.5.0-1 + rtnl_rule_set_mask@libnl_3 3.5.0-1 + rtnl_rule_set_oif@Base 3.5.0-1 + rtnl_rule_set_oif@libnl_3 3.5.0-1 + rtnl_rule_set_prio@Base 3.5.0-1 + rtnl_rule_set_prio@libnl_3 3.5.0-1 + rtnl_rule_set_protocol@libnl_3_5 3.5.0-1 + rtnl_rule_set_realms@Base 3.5.0-1 + rtnl_rule_set_realms@libnl_3 3.5.0-1 + rtnl_rule_set_sport@libnl_3_5 3.5.0-1 + rtnl_rule_set_sport_range@libnl_3_5 3.5.0-1 + rtnl_rule_set_src@Base 3.5.0-1 + rtnl_rule_set_src@libnl_3 3.5.0-1 + rtnl_rule_set_table@Base 3.5.0-1 + rtnl_rule_set_table@libnl_3 3.5.0-1 + rtnl_scope2str@Base 3.5.0-1 + rtnl_scope2str@libnl_3 3.5.0-1 + rtnl_sfq_get_divisor@Base 3.5.0-1 + rtnl_sfq_get_divisor@libnl_3 3.5.0-1 + rtnl_sfq_get_limit@Base 3.5.0-1 + rtnl_sfq_get_limit@libnl_3 3.5.0-1 + rtnl_sfq_get_perturb@Base 3.5.0-1 + rtnl_sfq_get_perturb@libnl_3 3.5.0-1 + rtnl_sfq_get_quantum@Base 3.5.0-1 + rtnl_sfq_get_quantum@libnl_3 3.5.0-1 + rtnl_sfq_set_limit@Base 3.5.0-1 + rtnl_sfq_set_limit@libnl_3 3.5.0-1 + rtnl_sfq_set_perturb@Base 3.5.0-1 + rtnl_sfq_set_perturb@libnl_3 3.5.0-1 + rtnl_sfq_set_quantum@Base 3.5.0-1 + rtnl_sfq_set_quantum@libnl_3 3.5.0-1 + rtnl_skbedit_get_action@Base 3.5.0-1 + rtnl_skbedit_get_action@libnl_3_2_26 3.5.0-1 + rtnl_skbedit_get_mark@Base 3.5.0-1 + rtnl_skbedit_get_mark@libnl_3_2_26 3.5.0-1 + rtnl_skbedit_get_priority@Base 3.5.0-1 + rtnl_skbedit_get_priority@libnl_3_2_26 3.5.0-1 + rtnl_skbedit_get_queue_mapping@Base 3.5.0-1 + rtnl_skbedit_get_queue_mapping@libnl_3_2_26 3.5.0-1 + rtnl_skbedit_set_action@Base 3.5.0-1 + rtnl_skbedit_set_action@libnl_3_2_26 3.5.0-1 + rtnl_skbedit_set_mark@Base 3.5.0-1 + rtnl_skbedit_set_mark@libnl_3_2_26 3.5.0-1 + rtnl_skbedit_set_priority@Base 3.5.0-1 + rtnl_skbedit_set_priority@libnl_3_2_26 3.5.0-1 + rtnl_skbedit_set_queue_mapping@Base 3.5.0-1 + rtnl_skbedit_set_queue_mapping@libnl_3_2_26 3.5.0-1 + rtnl_str2prio@Base 3.5.0-1 + rtnl_str2prio@libnl_3 3.5.0-1 + rtnl_str2scope@Base 3.5.0-1 + rtnl_str2scope@libnl_3 3.5.0-1 + rtnl_tc_build_rate_table@Base 3.5.0-1 + rtnl_tc_build_rate_table@libnl_3 3.5.0-1 + rtnl_tc_calc_bufsize@Base 3.5.0-1 + rtnl_tc_calc_bufsize@libnl_3 3.5.0-1 + rtnl_tc_calc_cell_log@Base 3.5.0-1 + rtnl_tc_calc_cell_log@libnl_3 3.5.0-1 + rtnl_tc_calc_txtime@Base 3.5.0-1 + rtnl_tc_calc_txtime@libnl_3 3.5.0-1 + rtnl_tc_clone@Base 3.5.0-1 + rtnl_tc_clone@libnl_3 3.5.0-1 + rtnl_tc_compare@Base 3.5.0-1 + rtnl_tc_compare@libnl_3 3.5.0-1 + rtnl_tc_data@Base 3.5.0-1 + rtnl_tc_data@libnl_3 3.5.0-1 + rtnl_tc_data_check@Base 3.5.0-1 + rtnl_tc_data_check@libnl_3 3.5.0-1 + rtnl_tc_data_peek@Base 3.5.0-1 + rtnl_tc_dump_details@Base 3.5.0-1 + rtnl_tc_dump_details@libnl_3 3.5.0-1 + rtnl_tc_dump_line@Base 3.5.0-1 + rtnl_tc_dump_line@libnl_3 3.5.0-1 + rtnl_tc_dump_stats@Base 3.5.0-1 + rtnl_tc_dump_stats@libnl_3 3.5.0-1 + rtnl_tc_free_data@Base 3.5.0-1 + rtnl_tc_free_data@libnl_3 3.5.0-1 + rtnl_tc_get_chain@libnl_3_5 3.5.0-1 + rtnl_tc_get_handle@Base 3.5.0-1 + rtnl_tc_get_handle@libnl_3 3.5.0-1 + rtnl_tc_get_ifindex@Base 3.5.0-1 + rtnl_tc_get_ifindex@libnl_3 3.5.0-1 + rtnl_tc_get_kind@Base 3.5.0-1 + rtnl_tc_get_kind@libnl_3 3.5.0-1 + rtnl_tc_get_link@Base 3.5.0-1 + rtnl_tc_get_link@libnl_3 3.5.0-1 + rtnl_tc_get_linktype@Base 3.5.0-1 + rtnl_tc_get_linktype@libnl_3 3.5.0-1 + rtnl_tc_get_mpu@Base 3.5.0-1 + rtnl_tc_get_mpu@libnl_3 3.5.0-1 + rtnl_tc_get_mtu@Base 3.5.0-1 + rtnl_tc_get_mtu@libnl_3 3.5.0-1 + rtnl_tc_get_ops@Base 3.5.0-1 + rtnl_tc_get_ops@libnl_3 3.5.0-1 + rtnl_tc_get_overhead@Base 3.5.0-1 + rtnl_tc_get_overhead@libnl_3 3.5.0-1 + rtnl_tc_get_parent@Base 3.5.0-1 + rtnl_tc_get_parent@libnl_3 3.5.0-1 + rtnl_tc_get_stat@Base 3.5.0-1 + rtnl_tc_get_stat@libnl_3 3.5.0-1 + rtnl_tc_handle2str@Base 3.5.0-1 + rtnl_tc_handle2str@libnl_3 3.5.0-1 + rtnl_tc_lookup_ops@Base 3.5.0-1 + rtnl_tc_lookup_ops@libnl_3 3.5.0-1 + rtnl_tc_msg_build@Base 3.5.0-1 + rtnl_tc_msg_build@libnl_3 3.5.0-1 + rtnl_tc_msg_parse@Base 3.5.0-1 + rtnl_tc_msg_parse@libnl_3 3.5.0-1 + rtnl_tc_read_classid_file@Base 3.5.0-1 + rtnl_tc_read_classid_file@libnl_3 3.5.0-1 + rtnl_tc_register@Base 3.5.0-1 + rtnl_tc_register@libnl_3 3.5.0-1 + rtnl_tc_set_chain@libnl_3_5 3.5.0-1 + rtnl_tc_set_handle@Base 3.5.0-1 + rtnl_tc_set_handle@libnl_3 3.5.0-1 + rtnl_tc_set_ifindex@Base 3.5.0-1 + rtnl_tc_set_ifindex@libnl_3 3.5.0-1 + rtnl_tc_set_kind@Base 3.5.0-1 + rtnl_tc_set_kind@libnl_3 3.5.0-1 + rtnl_tc_set_link@Base 3.5.0-1 + rtnl_tc_set_link@libnl_3 3.5.0-1 + rtnl_tc_set_linktype@Base 3.5.0-1 + rtnl_tc_set_linktype@libnl_3 3.5.0-1 + rtnl_tc_set_mpu@Base 3.5.0-1 + rtnl_tc_set_mpu@libnl_3 3.5.0-1 + rtnl_tc_set_mtu@Base 3.5.0-1 + rtnl_tc_set_mtu@libnl_3 3.5.0-1 + rtnl_tc_set_overhead@Base 3.5.0-1 + rtnl_tc_set_overhead@libnl_3 3.5.0-1 + rtnl_tc_set_parent@Base 3.5.0-1 + rtnl_tc_set_parent@libnl_3 3.5.0-1 + rtnl_tc_stat2str@Base 3.5.0-1 + rtnl_tc_stat2str@libnl_3_2_26 3.5.0-1 + rtnl_tc_str2handle@Base 3.5.0-1 + rtnl_tc_str2handle@libnl_3 3.5.0-1 + rtnl_tc_str2stat@Base 3.5.0-1 + rtnl_tc_str2stat@libnl_3_2_26 3.5.0-1 + rtnl_tc_type_register@Base 3.5.0-1 + rtnl_tc_type_register@libnl_3 3.5.0-1 + rtnl_tc_type_unregister@Base 3.5.0-1 + rtnl_tc_type_unregister@libnl_3 3.5.0-1 + rtnl_tc_unregister@Base 3.5.0-1 + rtnl_tc_unregister@libnl_3 3.5.0-1 + rtnl_u32_add_action@Base 3.5.0-1 + rtnl_u32_add_action@libnl_3 3.5.0-1 + rtnl_u32_add_key@Base 3.5.0-1 + rtnl_u32_add_key@libnl_3 3.5.0-1 + rtnl_u32_add_key_in6_addr@Base 3.5.0-1 + rtnl_u32_add_key_in6_addr@libnl_3 3.5.0-1 + rtnl_u32_add_key_in_addr@Base 3.5.0-1 + rtnl_u32_add_key_in_addr@libnl_3 3.5.0-1 + rtnl_u32_add_key_uint16@Base 3.5.0-1 + rtnl_u32_add_key_uint16@libnl_3 3.5.0-1 + rtnl_u32_add_key_uint32@Base 3.5.0-1 + rtnl_u32_add_key_uint32@libnl_3 3.5.0-1 + rtnl_u32_add_key_uint8@Base 3.5.0-1 + rtnl_u32_add_key_uint8@libnl_3 3.5.0-1 + rtnl_u32_add_mark@Base 3.5.0-1 + rtnl_u32_add_mark@libnl_3 3.5.0-1 + rtnl_u32_del_action@Base 3.5.0-1 + rtnl_u32_del_action@libnl_3 3.5.0-1 + rtnl_u32_del_mark@Base 3.5.0-1 + rtnl_u32_del_mark@libnl_3 3.5.0-1 + rtnl_u32_get_action@libnl_3_4 3.5.0-1 + rtnl_u32_get_classid@Base 3.5.0-1 + rtnl_u32_get_classid@libnl_3_2_26 3.5.0-1 + rtnl_u32_get_key@Base 3.5.0-1 + rtnl_u32_get_key@libnl_3 3.5.0-1 + rtnl_u32_set_classid@Base 3.5.0-1 + rtnl_u32_set_classid@libnl_3 3.5.0-1 + rtnl_u32_set_cls_terminal@Base 3.5.0-1 + rtnl_u32_set_cls_terminal@libnl_3 3.5.0-1 + rtnl_u32_set_divisor@Base 3.5.0-1 + rtnl_u32_set_divisor@libnl_3 3.5.0-1 + rtnl_u32_set_flags@Base 3.5.0-1 + rtnl_u32_set_flags@libnl_3 3.5.0-1 + rtnl_u32_set_handle@Base 3.5.0-1 + rtnl_u32_set_handle@libnl_3 3.5.0-1 + rtnl_u32_set_hashmask@Base 3.5.0-1 + rtnl_u32_set_hashmask@libnl_3 3.5.0-1 + rtnl_u32_set_hashtable@Base 3.5.0-1 + rtnl_u32_set_hashtable@libnl_3 3.5.0-1 + rtnl_u32_set_link@Base 3.5.0-1 + rtnl_u32_set_link@libnl_3 3.5.0-1 + rtnl_u32_set_selector@libnl_3_2_29 3.5.0-1 + rtnl_vlan_get_action@libnl_3_5 3.5.0-1 + rtnl_vlan_get_mode@libnl_3_5 3.5.0-1 + rtnl_vlan_get_protocol@libnl_3_5 3.5.0-1 + rtnl_vlan_get_vlan_id@libnl_3_5 3.5.0-1 + rtnl_vlan_get_vlan_prio@libnl_3_5 3.5.0-1 + rtnl_vlan_set_action@libnl_3_5 3.5.0-1 + rtnl_vlan_set_mode@libnl_3_5 3.5.0-1 + rtnl_vlan_set_protocol@libnl_3_5 3.5.0-1 + rtnl_vlan_set_vlan_id@libnl_3_5 3.5.0-1 + rtnl_vlan_set_vlan_prio@libnl_3_5 3.5.0-1 + tc_groups@Base 3.5.0-1 + tca_parse@Base 3.5.0-1 + tca_set_kind@Base 3.5.0-1 diff --git a/src/libnl3/debian/libnl-route-3-dev.install b/src/libnl3/debian/libnl-route-3-dev.install new file mode 100644 index 000000000000..37e248c3ed5b --- /dev/null +++ b/src/libnl3/debian/libnl-route-3-dev.install @@ -0,0 +1,3 @@ +debian/tmp/usr/lib/*/pkgconfig/libnl-route-3* +debian/tmp/usr/lib/*/libnl-route-3*.so +debian/tmp/usr/lib/*/libnl-route-3*.a diff --git a/src/libnl3/debian/libnl-utils.install b/src/libnl3/debian/libnl-utils.install new file mode 100644 index 000000000000..8ffdce84e93a --- /dev/null +++ b/src/libnl3/debian/libnl-utils.install @@ -0,0 +1 @@ +debian/tmp/usr/bin/* diff --git a/src/libnl3/debian/libnl-utils.manpages b/src/libnl3/debian/libnl-utils.manpages new file mode 100644 index 000000000000..0b2dcacf5b84 --- /dev/null +++ b/src/libnl3/debian/libnl-utils.manpages @@ -0,0 +1 @@ +debian/tmp/usr/share/man/man8/* diff --git a/src/libnl3/debian/libnl-xfrm-3-200.install b/src/libnl3/debian/libnl-xfrm-3-200.install new file mode 100644 index 000000000000..89b2d4e0c9e0 --- /dev/null +++ b/src/libnl3/debian/libnl-xfrm-3-200.install @@ -0,0 +1 @@ +debian/tmp/usr/lib/*/libnl-xfrm-3*.so.* diff --git a/src/libnl3/debian/libnl-xfrm-3-200.symbols b/src/libnl3/debian/libnl-xfrm-3-200.symbols new file mode 100644 index 000000000000..3704a7aa4384 --- /dev/null +++ b/src/libnl3/debian/libnl-xfrm-3-200.symbols @@ -0,0 +1,484 @@ +libnl-xfrm-3.so.200 libnl-xfrm-3-200 #MINVER# + libnl_3@libnl_3 3.5.0-1 + xfrmnl_ae_alloc@Base 3.5.0-1 + xfrmnl_ae_alloc@libnl_3 3.5.0-1 + xfrmnl_ae_build_get_request@Base 3.5.0-1 + xfrmnl_ae_build_get_request@libnl_3 3.5.0-1 + xfrmnl_ae_flags2str@Base 3.5.0-1 + xfrmnl_ae_flags2str@libnl_3 3.5.0-1 + xfrmnl_ae_get_curlifetime@Base 3.5.0-1 + xfrmnl_ae_get_curlifetime@libnl_3 3.5.0-1 + xfrmnl_ae_get_daddr@Base 3.5.0-1 + xfrmnl_ae_get_daddr@libnl_3 3.5.0-1 + xfrmnl_ae_get_family@Base 3.5.0-1 + xfrmnl_ae_get_family@libnl_3 3.5.0-1 + xfrmnl_ae_get_flags@Base 3.5.0-1 + xfrmnl_ae_get_flags@libnl_3 3.5.0-1 + xfrmnl_ae_get_kernel@Base 3.5.0-1 + xfrmnl_ae_get_kernel@libnl_3 3.5.0-1 + xfrmnl_ae_get_mark@Base 3.5.0-1 + xfrmnl_ae_get_mark@libnl_3 3.5.0-1 + xfrmnl_ae_get_proto@Base 3.5.0-1 + xfrmnl_ae_get_proto@libnl_3 3.5.0-1 + xfrmnl_ae_get_replay_maxage@Base 3.5.0-1 + xfrmnl_ae_get_replay_maxage@libnl_3 3.5.0-1 + xfrmnl_ae_get_replay_maxdiff@Base 3.5.0-1 + xfrmnl_ae_get_replay_maxdiff@libnl_3 3.5.0-1 + xfrmnl_ae_get_replay_state@Base 3.5.0-1 + xfrmnl_ae_get_replay_state@libnl_3 3.5.0-1 + xfrmnl_ae_get_replay_state_esn@Base 3.5.0-1 + xfrmnl_ae_get_replay_state_esn@libnl_3 3.5.0-1 + xfrmnl_ae_get_reqid@Base 3.5.0-1 + xfrmnl_ae_get_reqid@libnl_3 3.5.0-1 + xfrmnl_ae_get_saddr@Base 3.5.0-1 + xfrmnl_ae_get_saddr@libnl_3 3.5.0-1 + xfrmnl_ae_get_spi@Base 3.5.0-1 + xfrmnl_ae_get_spi@libnl_3 3.5.0-1 + xfrmnl_ae_parse@Base 3.5.0-1 + xfrmnl_ae_parse@libnl_3 3.5.0-1 + xfrmnl_ae_put@Base 3.5.0-1 + xfrmnl_ae_put@libnl_3 3.5.0-1 + xfrmnl_ae_set@Base 3.5.0-1 + xfrmnl_ae_set@libnl_3 3.5.0-1 + xfrmnl_ae_set_curlifetime@Base 3.5.0-1 + xfrmnl_ae_set_curlifetime@libnl_3 3.5.0-1 + xfrmnl_ae_set_daddr@Base 3.5.0-1 + xfrmnl_ae_set_daddr@libnl_3 3.5.0-1 + xfrmnl_ae_set_family@Base 3.5.0-1 + xfrmnl_ae_set_family@libnl_3 3.5.0-1 + xfrmnl_ae_set_flags@Base 3.5.0-1 + xfrmnl_ae_set_flags@libnl_3 3.5.0-1 + xfrmnl_ae_set_mark@Base 3.5.0-1 + xfrmnl_ae_set_mark@libnl_3 3.5.0-1 + xfrmnl_ae_set_proto@Base 3.5.0-1 + xfrmnl_ae_set_proto@libnl_3 3.5.0-1 + xfrmnl_ae_set_replay_maxage@Base 3.5.0-1 + xfrmnl_ae_set_replay_maxage@libnl_3 3.5.0-1 + xfrmnl_ae_set_replay_maxdiff@Base 3.5.0-1 + xfrmnl_ae_set_replay_maxdiff@libnl_3 3.5.0-1 + xfrmnl_ae_set_replay_state@Base 3.5.0-1 + xfrmnl_ae_set_replay_state@libnl_3 3.5.0-1 + xfrmnl_ae_set_replay_state_esn@Base 3.5.0-1 + xfrmnl_ae_set_replay_state_esn@libnl_3 3.5.0-1 + xfrmnl_ae_set_reqid@Base 3.5.0-1 + xfrmnl_ae_set_reqid@libnl_3 3.5.0-1 + xfrmnl_ae_set_saddr@Base 3.5.0-1 + xfrmnl_ae_set_saddr@libnl_3 3.5.0-1 + xfrmnl_ae_set_spi@Base 3.5.0-1 + xfrmnl_ae_set_spi@libnl_3 3.5.0-1 + xfrmnl_ae_str2flag@Base 3.5.0-1 + xfrmnl_ae_str2flag@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_alloc@Base 3.5.0-1 + xfrmnl_ltime_cfg_alloc@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_clone@Base 3.5.0-1 + xfrmnl_ltime_cfg_clone@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_cmp@Base 3.5.0-1 + xfrmnl_ltime_cfg_cmp@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_get@Base 3.5.0-1 + xfrmnl_ltime_cfg_get@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_get_hard_addexpires@Base 3.5.0-1 + xfrmnl_ltime_cfg_get_hard_addexpires@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_get_hard_bytelimit@Base 3.5.0-1 + xfrmnl_ltime_cfg_get_hard_bytelimit@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_get_hard_packetlimit@Base 3.5.0-1 + xfrmnl_ltime_cfg_get_hard_packetlimit@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_get_hard_useexpires@Base 3.5.0-1 + xfrmnl_ltime_cfg_get_hard_useexpires@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_get_soft_addexpires@Base 3.5.0-1 + xfrmnl_ltime_cfg_get_soft_addexpires@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_get_soft_bytelimit@Base 3.5.0-1 + xfrmnl_ltime_cfg_get_soft_bytelimit@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_get_soft_packetlimit@Base 3.5.0-1 + xfrmnl_ltime_cfg_get_soft_packetlimit@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_get_soft_useexpires@Base 3.5.0-1 + xfrmnl_ltime_cfg_get_soft_useexpires@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_put@Base 3.5.0-1 + xfrmnl_ltime_cfg_put@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_set_hard_addexpires@Base 3.5.0-1 + xfrmnl_ltime_cfg_set_hard_addexpires@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_set_hard_bytelimit@Base 3.5.0-1 + xfrmnl_ltime_cfg_set_hard_bytelimit@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_set_hard_packetlimit@Base 3.5.0-1 + xfrmnl_ltime_cfg_set_hard_packetlimit@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_set_hard_useexpires@Base 3.5.0-1 + xfrmnl_ltime_cfg_set_hard_useexpires@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_set_soft_addexpires@Base 3.5.0-1 + xfrmnl_ltime_cfg_set_soft_addexpires@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_set_soft_bytelimit@Base 3.5.0-1 + xfrmnl_ltime_cfg_set_soft_bytelimit@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_set_soft_packetlimit@Base 3.5.0-1 + xfrmnl_ltime_cfg_set_soft_packetlimit@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_set_soft_useexpires@Base 3.5.0-1 + xfrmnl_ltime_cfg_set_soft_useexpires@libnl_3 3.5.0-1 + xfrmnl_ltime_cfg_shared@Base 3.5.0-1 + xfrmnl_ltime_cfg_shared@libnl_3 3.5.0-1 + xfrmnl_sa_add@Base 3.5.0-1 + xfrmnl_sa_add@libnl_3 3.5.0-1 + xfrmnl_sa_alloc@Base 3.5.0-1 + xfrmnl_sa_alloc@libnl_3 3.5.0-1 + xfrmnl_sa_alloc_cache@Base 3.5.0-1 + xfrmnl_sa_alloc_cache@libnl_3 3.5.0-1 + xfrmnl_sa_build_add_request@Base 3.5.0-1 + xfrmnl_sa_build_add_request@libnl_3 3.5.0-1 + xfrmnl_sa_build_delete_request@Base 3.5.0-1 + xfrmnl_sa_build_delete_request@libnl_3 3.5.0-1 + xfrmnl_sa_build_get_request@Base 3.5.0-1 + xfrmnl_sa_build_get_request@libnl_3 3.5.0-1 + xfrmnl_sa_build_update_request@Base 3.5.0-1 + xfrmnl_sa_build_update_request@libnl_3 3.5.0-1 + xfrmnl_sa_delete@Base 3.5.0-1 + xfrmnl_sa_delete@libnl_3 3.5.0-1 + xfrmnl_sa_flags2str@Base 3.5.0-1 + xfrmnl_sa_flags2str@libnl_3 3.5.0-1 + xfrmnl_sa_get@Base 3.5.0-1 + xfrmnl_sa_get@libnl_3 3.5.0-1 + xfrmnl_sa_get_aead_params@Base 3.5.0-1 + xfrmnl_sa_get_aead_params@libnl_3 3.5.0-1 + xfrmnl_sa_get_auth_params@Base 3.5.0-1 + xfrmnl_sa_get_auth_params@libnl_3 3.5.0-1 + xfrmnl_sa_get_coaddr@Base 3.5.0-1 + xfrmnl_sa_get_coaddr@libnl_3 3.5.0-1 + xfrmnl_sa_get_comp_params@Base 3.5.0-1 + xfrmnl_sa_get_comp_params@libnl_3 3.5.0-1 + xfrmnl_sa_get_crypto_params@Base 3.5.0-1 + xfrmnl_sa_get_crypto_params@libnl_3 3.5.0-1 + xfrmnl_sa_get_curlifetime@Base 3.5.0-1 + xfrmnl_sa_get_curlifetime@libnl_3 3.5.0-1 + xfrmnl_sa_get_daddr@Base 3.5.0-1 + xfrmnl_sa_get_daddr@libnl_3 3.5.0-1 + xfrmnl_sa_get_encap_tmpl@Base 3.5.0-1 + xfrmnl_sa_get_encap_tmpl@libnl_3 3.5.0-1 + xfrmnl_sa_get_family@Base 3.5.0-1 + xfrmnl_sa_get_family@libnl_3 3.5.0-1 + xfrmnl_sa_get_flags@Base 3.5.0-1 + xfrmnl_sa_get_flags@libnl_3 3.5.0-1 + xfrmnl_sa_get_kernel@Base 3.5.0-1 + xfrmnl_sa_get_kernel@libnl_3 3.5.0-1 + xfrmnl_sa_get_lifetime_cfg@Base 3.5.0-1 + xfrmnl_sa_get_lifetime_cfg@libnl_3 3.5.0-1 + xfrmnl_sa_get_mark@Base 3.5.0-1 + xfrmnl_sa_get_mark@libnl_3 3.5.0-1 + xfrmnl_sa_get_mode@Base 3.5.0-1 + xfrmnl_sa_get_mode@libnl_3 3.5.0-1 + xfrmnl_sa_get_proto@Base 3.5.0-1 + xfrmnl_sa_get_proto@libnl_3 3.5.0-1 + xfrmnl_sa_get_replay_maxage@Base 3.5.0-1 + xfrmnl_sa_get_replay_maxage@libnl_3 3.5.0-1 + xfrmnl_sa_get_replay_maxdiff@Base 3.5.0-1 + xfrmnl_sa_get_replay_maxdiff@libnl_3 3.5.0-1 + xfrmnl_sa_get_replay_state@Base 3.5.0-1 + xfrmnl_sa_get_replay_state@libnl_3 3.5.0-1 + xfrmnl_sa_get_replay_state_esn@Base 3.5.0-1 + xfrmnl_sa_get_replay_state_esn@libnl_3 3.5.0-1 + xfrmnl_sa_get_replay_window@Base 3.5.0-1 + xfrmnl_sa_get_replay_window@libnl_3 3.5.0-1 + xfrmnl_sa_get_reqid@Base 3.5.0-1 + xfrmnl_sa_get_reqid@libnl_3 3.5.0-1 + xfrmnl_sa_get_saddr@Base 3.5.0-1 + xfrmnl_sa_get_saddr@libnl_3 3.5.0-1 + xfrmnl_sa_get_sec_ctx@Base 3.5.0-1 + xfrmnl_sa_get_sec_ctx@libnl_3 3.5.0-1 + xfrmnl_sa_get_sel@Base 3.5.0-1 + xfrmnl_sa_get_sel@libnl_3 3.5.0-1 + xfrmnl_sa_get_seq@Base 3.5.0-1 + xfrmnl_sa_get_seq@libnl_3 3.5.0-1 + xfrmnl_sa_get_spi@Base 3.5.0-1 + xfrmnl_sa_get_spi@libnl_3 3.5.0-1 + xfrmnl_sa_get_stats@Base 3.5.0-1 + xfrmnl_sa_get_stats@libnl_3 3.5.0-1 + xfrmnl_sa_get_tfcpad@Base 3.5.0-1 + xfrmnl_sa_get_tfcpad@libnl_3 3.5.0-1 + xfrmnl_sa_is_expiry_reached@Base 3.5.0-1 + xfrmnl_sa_is_expiry_reached@libnl_3 3.5.0-1 + xfrmnl_sa_is_hardexpiry_reached@Base 3.5.0-1 + xfrmnl_sa_is_hardexpiry_reached@libnl_3 3.5.0-1 + xfrmnl_sa_mode2str@Base 3.5.0-1 + xfrmnl_sa_mode2str@libnl_3 3.5.0-1 + xfrmnl_sa_parse@Base 3.5.0-1 + xfrmnl_sa_parse@libnl_3 3.5.0-1 + xfrmnl_sa_put@Base 3.5.0-1 + xfrmnl_sa_put@libnl_3 3.5.0-1 + xfrmnl_sa_set_aead_params@Base 3.5.0-1 + xfrmnl_sa_set_aead_params@libnl_3 3.5.0-1 + xfrmnl_sa_set_auth_params@Base 3.5.0-1 + xfrmnl_sa_set_auth_params@libnl_3 3.5.0-1 + xfrmnl_sa_set_coaddr@Base 3.5.0-1 + xfrmnl_sa_set_coaddr@libnl_3 3.5.0-1 + xfrmnl_sa_set_comp_params@Base 3.5.0-1 + xfrmnl_sa_set_comp_params@libnl_3 3.5.0-1 + xfrmnl_sa_set_crypto_params@Base 3.5.0-1 + xfrmnl_sa_set_crypto_params@libnl_3 3.5.0-1 + xfrmnl_sa_set_daddr@Base 3.5.0-1 + xfrmnl_sa_set_daddr@libnl_3 3.5.0-1 + xfrmnl_sa_set_encap_tmpl@Base 3.5.0-1 + xfrmnl_sa_set_encap_tmpl@libnl_3 3.5.0-1 + xfrmnl_sa_set_family@Base 3.5.0-1 + xfrmnl_sa_set_family@libnl_3 3.5.0-1 + xfrmnl_sa_set_flags@Base 3.5.0-1 + xfrmnl_sa_set_flags@libnl_3 3.5.0-1 + xfrmnl_sa_set_lifetime_cfg@Base 3.5.0-1 + xfrmnl_sa_set_lifetime_cfg@libnl_3 3.5.0-1 + xfrmnl_sa_set_mark@Base 3.5.0-1 + xfrmnl_sa_set_mark@libnl_3 3.5.0-1 + xfrmnl_sa_set_mode@Base 3.5.0-1 + xfrmnl_sa_set_mode@libnl_3 3.5.0-1 + xfrmnl_sa_set_proto@Base 3.5.0-1 + xfrmnl_sa_set_proto@libnl_3 3.5.0-1 + xfrmnl_sa_set_replay_maxage@Base 3.5.0-1 + xfrmnl_sa_set_replay_maxage@libnl_3 3.5.0-1 + xfrmnl_sa_set_replay_maxdiff@Base 3.5.0-1 + xfrmnl_sa_set_replay_maxdiff@libnl_3 3.5.0-1 + xfrmnl_sa_set_replay_state@Base 3.5.0-1 + xfrmnl_sa_set_replay_state@libnl_3 3.5.0-1 + xfrmnl_sa_set_replay_state_esn@Base 3.5.0-1 + xfrmnl_sa_set_replay_state_esn@libnl_3 3.5.0-1 + xfrmnl_sa_set_replay_window@Base 3.5.0-1 + xfrmnl_sa_set_replay_window@libnl_3 3.5.0-1 + xfrmnl_sa_set_reqid@Base 3.5.0-1 + xfrmnl_sa_set_reqid@libnl_3 3.5.0-1 + xfrmnl_sa_set_saddr@Base 3.5.0-1 + xfrmnl_sa_set_saddr@libnl_3 3.5.0-1 + xfrmnl_sa_set_sec_ctx@Base 3.5.0-1 + xfrmnl_sa_set_sec_ctx@libnl_3 3.5.0-1 + xfrmnl_sa_set_sel@Base 3.5.0-1 + xfrmnl_sa_set_sel@libnl_3 3.5.0-1 + xfrmnl_sa_set_spi@Base 3.5.0-1 + xfrmnl_sa_set_spi@libnl_3 3.5.0-1 + xfrmnl_sa_set_tfcpad@Base 3.5.0-1 + xfrmnl_sa_set_tfcpad@libnl_3 3.5.0-1 + xfrmnl_sa_str2flag@Base 3.5.0-1 + xfrmnl_sa_str2flag@libnl_3 3.5.0-1 + xfrmnl_sa_str2mode@Base 3.5.0-1 + xfrmnl_sa_str2mode@libnl_3 3.5.0-1 + xfrmnl_sa_update@Base 3.5.0-1 + xfrmnl_sa_update@libnl_3 3.5.0-1 + xfrmnl_sel_alloc@Base 3.5.0-1 + xfrmnl_sel_alloc@libnl_3 3.5.0-1 + xfrmnl_sel_clone@Base 3.5.0-1 + xfrmnl_sel_clone@libnl_3 3.5.0-1 + xfrmnl_sel_cmp@Base 3.5.0-1 + xfrmnl_sel_cmp@libnl_3 3.5.0-1 + xfrmnl_sel_dump@Base 3.5.0-1 + xfrmnl_sel_dump@libnl_3 3.5.0-1 + xfrmnl_sel_get@Base 3.5.0-1 + xfrmnl_sel_get@libnl_3 3.5.0-1 + xfrmnl_sel_get_daddr@Base 3.5.0-1 + xfrmnl_sel_get_daddr@libnl_3 3.5.0-1 + xfrmnl_sel_get_dport@Base 3.5.0-1 + xfrmnl_sel_get_dport@libnl_3 3.5.0-1 + xfrmnl_sel_get_dportmask@Base 3.5.0-1 + xfrmnl_sel_get_dportmask@libnl_3 3.5.0-1 + xfrmnl_sel_get_family@Base 3.5.0-1 + xfrmnl_sel_get_family@libnl_3 3.5.0-1 + xfrmnl_sel_get_ifindex@Base 3.5.0-1 + xfrmnl_sel_get_ifindex@libnl_3 3.5.0-1 + xfrmnl_sel_get_prefixlen_d@Base 3.5.0-1 + xfrmnl_sel_get_prefixlen_d@libnl_3 3.5.0-1 + xfrmnl_sel_get_prefixlen_s@Base 3.5.0-1 + xfrmnl_sel_get_prefixlen_s@libnl_3 3.5.0-1 + xfrmnl_sel_get_proto@Base 3.5.0-1 + xfrmnl_sel_get_proto@libnl_3 3.5.0-1 + xfrmnl_sel_get_saddr@Base 3.5.0-1 + xfrmnl_sel_get_saddr@libnl_3 3.5.0-1 + xfrmnl_sel_get_sport@Base 3.5.0-1 + xfrmnl_sel_get_sport@libnl_3 3.5.0-1 + xfrmnl_sel_get_sportmask@Base 3.5.0-1 + xfrmnl_sel_get_sportmask@libnl_3 3.5.0-1 + xfrmnl_sel_get_userid@Base 3.5.0-1 + xfrmnl_sel_get_userid@libnl_3 3.5.0-1 + xfrmnl_sel_put@Base 3.5.0-1 + xfrmnl_sel_put@libnl_3 3.5.0-1 + xfrmnl_sel_set_daddr@Base 3.5.0-1 + xfrmnl_sel_set_daddr@libnl_3 3.5.0-1 + xfrmnl_sel_set_dport@Base 3.5.0-1 + xfrmnl_sel_set_dport@libnl_3 3.5.0-1 + xfrmnl_sel_set_dportmask@Base 3.5.0-1 + xfrmnl_sel_set_dportmask@libnl_3 3.5.0-1 + xfrmnl_sel_set_family@Base 3.5.0-1 + xfrmnl_sel_set_family@libnl_3 3.5.0-1 + xfrmnl_sel_set_ifindex@Base 3.5.0-1 + xfrmnl_sel_set_ifindex@libnl_3 3.5.0-1 + xfrmnl_sel_set_prefixlen_d@Base 3.5.0-1 + xfrmnl_sel_set_prefixlen_d@libnl_3 3.5.0-1 + xfrmnl_sel_set_prefixlen_s@Base 3.5.0-1 + xfrmnl_sel_set_prefixlen_s@libnl_3 3.5.0-1 + xfrmnl_sel_set_proto@Base 3.5.0-1 + xfrmnl_sel_set_proto@libnl_3 3.5.0-1 + xfrmnl_sel_set_saddr@Base 3.5.0-1 + xfrmnl_sel_set_saddr@libnl_3 3.5.0-1 + xfrmnl_sel_set_sport@Base 3.5.0-1 + xfrmnl_sel_set_sport@libnl_3 3.5.0-1 + xfrmnl_sel_set_sportmask@Base 3.5.0-1 + xfrmnl_sel_set_sportmask@libnl_3 3.5.0-1 + xfrmnl_sel_set_userid@Base 3.5.0-1 + xfrmnl_sel_set_userid@libnl_3 3.5.0-1 + xfrmnl_sel_shared@Base 3.5.0-1 + xfrmnl_sel_shared@libnl_3 3.5.0-1 + xfrmnl_sp_action2str@Base 3.5.0-1 + xfrmnl_sp_action2str@libnl_3 3.5.0-1 + xfrmnl_sp_add@Base 3.5.0-1 + xfrmnl_sp_add@libnl_3 3.5.0-1 + xfrmnl_sp_add_usertemplate@Base 3.5.0-1 + xfrmnl_sp_add_usertemplate@libnl_3 3.5.0-1 + xfrmnl_sp_alloc@Base 3.5.0-1 + xfrmnl_sp_alloc@libnl_3 3.5.0-1 + xfrmnl_sp_alloc_cache@Base 3.5.0-1 + xfrmnl_sp_alloc_cache@libnl_3 3.5.0-1 + xfrmnl_sp_build_add_request@Base 3.5.0-1 + xfrmnl_sp_build_add_request@libnl_3 3.5.0-1 + xfrmnl_sp_build_delete_request@Base 3.5.0-1 + xfrmnl_sp_build_delete_request@libnl_3 3.5.0-1 + xfrmnl_sp_build_get_request@Base 3.5.0-1 + xfrmnl_sp_build_get_request@libnl_3 3.5.0-1 + xfrmnl_sp_build_update_request@Base 3.5.0-1 + xfrmnl_sp_build_update_request@libnl_3 3.5.0-1 + xfrmnl_sp_delete@Base 3.5.0-1 + xfrmnl_sp_delete@libnl_3 3.5.0-1 + xfrmnl_sp_dir2str@Base 3.5.0-1 + xfrmnl_sp_dir2str@libnl_3 3.5.0-1 + xfrmnl_sp_flags2str@Base 3.5.0-1 + xfrmnl_sp_flags2str@libnl_3 3.5.0-1 + xfrmnl_sp_foreach_usertemplate@Base 3.5.0-1 + xfrmnl_sp_foreach_usertemplate@libnl_3 3.5.0-1 + xfrmnl_sp_get@Base 3.5.0-1 + xfrmnl_sp_get@libnl_3 3.5.0-1 + xfrmnl_sp_get_action@Base 3.5.0-1 + xfrmnl_sp_get_action@libnl_3 3.5.0-1 + xfrmnl_sp_get_curlifetime@Base 3.5.0-1 + xfrmnl_sp_get_curlifetime@libnl_3 3.5.0-1 + xfrmnl_sp_get_dir@Base 3.5.0-1 + xfrmnl_sp_get_dir@libnl_3 3.5.0-1 + xfrmnl_sp_get_flags@Base 3.5.0-1 + xfrmnl_sp_get_flags@libnl_3 3.5.0-1 + xfrmnl_sp_get_index@Base 3.5.0-1 + xfrmnl_sp_get_index@libnl_3 3.5.0-1 + xfrmnl_sp_get_kernel@Base 3.5.0-1 + xfrmnl_sp_get_kernel@libnl_3 3.5.0-1 + xfrmnl_sp_get_lifetime_cfg@Base 3.5.0-1 + xfrmnl_sp_get_lifetime_cfg@libnl_3 3.5.0-1 + xfrmnl_sp_get_mark@Base 3.5.0-1 + xfrmnl_sp_get_mark@libnl_3 3.5.0-1 + xfrmnl_sp_get_nusertemplates@Base 3.5.0-1 + xfrmnl_sp_get_nusertemplates@libnl_3 3.5.0-1 + xfrmnl_sp_get_priority@Base 3.5.0-1 + xfrmnl_sp_get_priority@libnl_3 3.5.0-1 + xfrmnl_sp_get_sec_ctx@Base 3.5.0-1 + xfrmnl_sp_get_sec_ctx@libnl_3 3.5.0-1 + xfrmnl_sp_get_sel@Base 3.5.0-1 + xfrmnl_sp_get_sel@libnl_3 3.5.0-1 + xfrmnl_sp_get_share@Base 3.5.0-1 + xfrmnl_sp_get_share@libnl_3 3.5.0-1 + xfrmnl_sp_get_userpolicy_type@Base 3.5.0-1 + xfrmnl_sp_get_userpolicy_type@libnl_3 3.5.0-1 + xfrmnl_sp_get_usertemplates@Base 3.5.0-1 + xfrmnl_sp_get_usertemplates@libnl_3 3.5.0-1 + xfrmnl_sp_index2dir@Base 3.5.0-1 + xfrmnl_sp_index2dir@libnl_3 3.5.0-1 + xfrmnl_sp_parse@Base 3.5.0-1 + xfrmnl_sp_parse@libnl_3 3.5.0-1 + xfrmnl_sp_put@Base 3.5.0-1 + xfrmnl_sp_put@libnl_3 3.5.0-1 + xfrmnl_sp_remove_usertemplate@Base 3.5.0-1 + xfrmnl_sp_remove_usertemplate@libnl_3 3.5.0-1 + xfrmnl_sp_set_action@Base 3.5.0-1 + xfrmnl_sp_set_action@libnl_3 3.5.0-1 + xfrmnl_sp_set_dir@Base 3.5.0-1 + xfrmnl_sp_set_dir@libnl_3 3.5.0-1 + xfrmnl_sp_set_flags@Base 3.5.0-1 + xfrmnl_sp_set_flags@libnl_3 3.5.0-1 + xfrmnl_sp_set_index@Base 3.5.0-1 + xfrmnl_sp_set_index@libnl_3 3.5.0-1 + xfrmnl_sp_set_lifetime_cfg@Base 3.5.0-1 + xfrmnl_sp_set_lifetime_cfg@libnl_3 3.5.0-1 + xfrmnl_sp_set_mark@Base 3.5.0-1 + xfrmnl_sp_set_mark@libnl_3 3.5.0-1 + xfrmnl_sp_set_priority@Base 3.5.0-1 + xfrmnl_sp_set_priority@libnl_3 3.5.0-1 + xfrmnl_sp_set_sec_ctx@Base 3.5.0-1 + xfrmnl_sp_set_sec_ctx@libnl_3 3.5.0-1 + xfrmnl_sp_set_sel@Base 3.5.0-1 + xfrmnl_sp_set_sel@libnl_3 3.5.0-1 + xfrmnl_sp_set_share@Base 3.5.0-1 + xfrmnl_sp_set_share@libnl_3 3.5.0-1 + xfrmnl_sp_set_userpolicy_type@Base 3.5.0-1 + xfrmnl_sp_set_userpolicy_type@libnl_3 3.5.0-1 + xfrmnl_sp_share2str@Base 3.5.0-1 + xfrmnl_sp_share2str@libnl_3 3.5.0-1 + xfrmnl_sp_str2action@Base 3.5.0-1 + xfrmnl_sp_str2action@libnl_3 3.5.0-1 + xfrmnl_sp_str2dir@Base 3.5.0-1 + xfrmnl_sp_str2dir@libnl_3 3.5.0-1 + xfrmnl_sp_str2flag@Base 3.5.0-1 + xfrmnl_sp_str2flag@libnl_3 3.5.0-1 + xfrmnl_sp_str2share@Base 3.5.0-1 + xfrmnl_sp_str2share@libnl_3 3.5.0-1 + xfrmnl_sp_str2type@Base 3.5.0-1 + xfrmnl_sp_str2type@libnl_3 3.5.0-1 + xfrmnl_sp_type2str@Base 3.5.0-1 + xfrmnl_sp_type2str@libnl_3 3.5.0-1 + xfrmnl_sp_update@Base 3.5.0-1 + xfrmnl_sp_update@libnl_3 3.5.0-1 + xfrmnl_sp_usertemplate_n@Base 3.5.0-1 + xfrmnl_sp_usertemplate_n@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_alloc@Base 3.5.0-1 + xfrmnl_user_tmpl_alloc@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_clone@Base 3.5.0-1 + xfrmnl_user_tmpl_clone@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_cmp@Base 3.5.0-1 + xfrmnl_user_tmpl_cmp@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_dump@Base 3.5.0-1 + xfrmnl_user_tmpl_dump@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_free@Base 3.5.0-1 + xfrmnl_user_tmpl_free@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_aalgos@Base 3.5.0-1 + xfrmnl_user_tmpl_get_aalgos@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_calgos@Base 3.5.0-1 + xfrmnl_user_tmpl_get_calgos@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_daddr@Base 3.5.0-1 + xfrmnl_user_tmpl_get_daddr@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_ealgos@Base 3.5.0-1 + xfrmnl_user_tmpl_get_ealgos@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_family@Base 3.5.0-1 + xfrmnl_user_tmpl_get_family@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_mode@Base 3.5.0-1 + xfrmnl_user_tmpl_get_mode@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_optional@Base 3.5.0-1 + xfrmnl_user_tmpl_get_optional@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_proto@Base 3.5.0-1 + xfrmnl_user_tmpl_get_proto@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_reqid@Base 3.5.0-1 + xfrmnl_user_tmpl_get_reqid@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_saddr@Base 3.5.0-1 + xfrmnl_user_tmpl_get_saddr@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_share@Base 3.5.0-1 + xfrmnl_user_tmpl_get_share@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_get_spi@Base 3.5.0-1 + xfrmnl_user_tmpl_get_spi@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_mode2str@Base 3.5.0-1 + xfrmnl_user_tmpl_mode2str@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_aalgos@Base 3.5.0-1 + xfrmnl_user_tmpl_set_aalgos@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_calgos@Base 3.5.0-1 + xfrmnl_user_tmpl_set_calgos@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_daddr@Base 3.5.0-1 + xfrmnl_user_tmpl_set_daddr@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_ealgos@Base 3.5.0-1 + xfrmnl_user_tmpl_set_ealgos@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_family@Base 3.5.0-1 + xfrmnl_user_tmpl_set_family@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_mode@Base 3.5.0-1 + xfrmnl_user_tmpl_set_mode@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_optional@Base 3.5.0-1 + xfrmnl_user_tmpl_set_optional@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_proto@Base 3.5.0-1 + xfrmnl_user_tmpl_set_proto@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_reqid@Base 3.5.0-1 + xfrmnl_user_tmpl_set_reqid@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_saddr@Base 3.5.0-1 + xfrmnl_user_tmpl_set_saddr@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_share@Base 3.5.0-1 + xfrmnl_user_tmpl_set_share@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_set_spi@Base 3.5.0-1 + xfrmnl_user_tmpl_set_spi@libnl_3 3.5.0-1 + xfrmnl_user_tmpl_str2mode@Base 3.5.0-1 + xfrmnl_user_tmpl_str2mode@libnl_3 3.5.0-1 diff --git a/src/libnl3/debian/libnl-xfrm-3-dev.install b/src/libnl3/debian/libnl-xfrm-3-dev.install new file mode 100644 index 000000000000..f57e152c5aae --- /dev/null +++ b/src/libnl3/debian/libnl-xfrm-3-dev.install @@ -0,0 +1,3 @@ +debian/tmp/usr/lib/*/pkgconfig/libnl-xfrm-3* +debian/tmp/usr/lib/*/libnl-xfrm-3*.so +debian/tmp/usr/lib/*/libnl-xfrm-3*.a diff --git a/src/libnl3/debian/patches/series b/src/libnl3/debian/patches/series new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/libnl3/debian/rules b/src/libnl3/debian/rules new file mode 100755 index 000000000000..bb33dda05a64 --- /dev/null +++ b/src/libnl3/debian/rules @@ -0,0 +1,39 @@ +#!/usr/bin/make -f + +DEB_BUILDDIR = debian/build +DEB_MAKE_FLAVORS = main udeb + +udeb_libnl=libnl-3-200-udeb +udeb_libnl_genl=libnl-genl-3-200-udeb + +TG_BRANCHES := debian/etc-libnl-3,debian/out-of-tree,debian/no-symvers + +-include /usr/share/topgit/tg2quilt.mk + +# to export the patch series use +# debian/rules tg-clean +# debian/rules tg-export + + +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/rules/autoreconf.mk +include /usr/share/cdbs/1/class/autotools.mk + +# FIXME: not honoured +#CFLAGS_udeb += $(CFLAGS) -Os +CFLAGS += $(if $(findstring udeb,$(cdbs_make_curflavor)),-Os) + +DEB_DH_STRIP_ARGS := --dbg-package=libnl-3-200-dbg +DEB_DH_MAKESHLIBS_ARGS_libnl-3-200 := --add-udeb=$(udeb_libnl) +DEB_DH_MAKESHLIBS_ARGS_libnl-genl-3-200 := --add-udeb=$(udeb_libnl_genl) + +DEB_MAKE_DESTDIRSKEL = $(CURDIR)/debian/tmp +DEB_MAKE_DESTDIRSKEL_udeb = $(CURDIR)/debian/tmp/udeb + +DEB_DH_INSTALL_ARGS_$(udeb) += --sourcedir=debian/tmp/udeb + +DEB_CONFIGURE_EXTRA_FLAGS += --libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH) + +clean:: + # from some unknown reason CDBS does not remove the builddir + rm -rf $(DEB_BUILDDIR) diff --git a/src/libnl3/debian/source/format b/src/libnl3/debian/source/format new file mode 100644 index 000000000000..163aaf8d82b6 --- /dev/null +++ b/src/libnl3/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/src/libnl3/debian/watch b/src/libnl3/debian/watch new file mode 100644 index 000000000000..9939913ca0e0 --- /dev/null +++ b/src/libnl3/debian/watch @@ -0,0 +1,2 @@ +version=3 +https://github.com/thom311/libnl/releases/libnl-(.*)\.tar\.gz diff --git a/src/libteam/.gitignore b/src/libteam/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/libteam/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/libteam/Makefile b/src/libteam/Makefile new file mode 100644 index 000000000000..47f9d1dd21bf --- /dev/null +++ b/src/libteam/Makefile @@ -0,0 +1,39 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = libteam5_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb +DERIVED_TARGETS = libteam-dev_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb \ + libteamdctl0_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb \ + libteam-utils_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb \ + libteam5-dbgsym_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb \ + libteamdctl0-dbgsym_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb \ + libteam-utils-dbgsym_$(LIBTEAM_VERSION)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtain libteam + rm -rf ./libteam + git clone https://github.com/jpirko/libteam.git + pushd ./libteam + git checkout -b teamd -f c7237377dead39ae4a711297203bacf7edb9fa41 + + # Apply patch series + stg init + stg import -s ../patch/series + popd + + # Obtain debian packaging + git clone https://salsa.debian.org/debian/libteam.git tmp + pushd ./tmp + git checkout -f debian/1.30-1 + popd + + mv tmp/debian libteam/ + rm -rf tmp + pushd ./libteam + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/libteam/patch/0001-libteam-Temporarily-remove-redundant-debug-messages.patch b/src/libteam/patch/0001-libteam-Temporarily-remove-redundant-debug-messages.patch new file mode 100644 index 000000000000..bd5f2857c4bf --- /dev/null +++ b/src/libteam/patch/0001-libteam-Temporarily-remove-redundant-debug-messages.patch @@ -0,0 +1,25 @@ +From fa8c4604e739abde29278b403a1a1d502337c21b Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 3 Mar 2020 12:47:32 -0800 +Subject: [PATCH] libteam: Temporarily remove redundant debug messages + +--- + teamd/teamd_runner_lacp.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index ec01237..2d5a823 100644 +--- a/teamd/teamd_runner_lacp.c ++++ b/teamd/teamd_runner_lacp.c +@@ -929,8 +929,6 @@ static void lacp_port_actor_update(struct lacp_port *lacp_port) + state |= INFO_STATE_DEFAULTED; + if (teamd_port_count(lacp_port->ctx) > 0) + state |= INFO_STATE_AGGREGATION; +- teamd_log_dbg(lacp_port->ctx, "%s: lacp info state: 0x%02X.", +- lacp_port->tdport->ifname, state); + lacp_port->actor.state = state; + } + +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/0002-teamd-lacp-runner-will-send-lacp-update-right-after-.patch b/src/libteam/patch/0002-teamd-lacp-runner-will-send-lacp-update-right-after-.patch new file mode 100644 index 000000000000..00b4badce883 --- /dev/null +++ b/src/libteam/patch/0002-teamd-lacp-runner-will-send-lacp-update-right-after-.patch @@ -0,0 +1,100 @@ +From 9e697b0c9fbd01f024acfea8aa25334816425c2b Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 3 Mar 2020 12:50:23 -0800 +Subject: [PATCH] [teamd] lacp runner will send lacp update right after it + received SIGINT signal + +--- + teamd/teamd.c | 1 + + teamd/teamd.h | 3 +++ + teamd/teamd_events.c | 13 +++++++++++++ + teamd/teamd_runner_lacp.c | 11 +++++++++++ + 4 files changed, 28 insertions(+) + +diff --git a/teamd/teamd.c b/teamd/teamd.c +index e035ac5..dc46a62 100644 +--- a/teamd/teamd.c ++++ b/teamd/teamd.c +@@ -392,6 +392,7 @@ static int teamd_run_loop_run(struct teamd_context *ctx) + case 'q': + if (quit_in_progress) + return -EBUSY; ++ teamd_refresh_ports(ctx); + err = teamd_flush_ports(ctx); + if (err) + return err; +diff --git a/teamd/teamd.h b/teamd/teamd.h +index f94c918..01ebc84 100644 +--- a/teamd/teamd.h ++++ b/teamd/teamd.h +@@ -193,11 +193,14 @@ struct teamd_event_watch_ops { + int (*port_master_ifindex_changed)(struct teamd_context *ctx, + struct teamd_port *tdport, + void *priv); ++ void (*refresh)(struct teamd_context *ctx, ++ struct teamd_port *tdport, void *priv); + int (*option_changed)(struct teamd_context *ctx, + struct team_option *option, void *priv); + char *option_changed_match_name; + }; + ++void teamd_refresh_ports(struct teamd_context *ctx); + int teamd_event_port_added(struct teamd_context *ctx, + struct teamd_port *tdport); + void teamd_event_port_removed(struct teamd_context *ctx, +diff --git a/teamd/teamd_events.c b/teamd/teamd_events.c +index 65aa46a..221803e 100644 +--- a/teamd/teamd_events.c ++++ b/teamd/teamd_events.c +@@ -34,6 +34,19 @@ struct event_watch_item { + void *priv; + }; + ++void teamd_refresh_ports(struct teamd_context *ctx) ++{ ++ struct teamd_port *tdport; ++ struct event_watch_item *watch; ++ ++ teamd_for_each_tdport(tdport, ctx) { ++ list_for_each_node_entry(watch, &ctx->event_watch_list, list) { ++ if (!watch->ops->refresh) continue; ++ watch->ops->refresh(ctx, tdport, watch->priv); ++ } ++ } ++} ++ + int teamd_event_port_added(struct teamd_context *ctx, + struct teamd_port *tdport) + { +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index 2d5a823..7592b01 100644 +--- a/teamd/teamd_runner_lacp.c ++++ b/teamd/teamd_runner_lacp.c +@@ -1421,6 +1421,16 @@ static int lacp_event_watch_port_changed(struct teamd_context *ctx, + return lacp_port_link_update(lacp_port); + } + ++static void lacp_event_watch_refresh(struct teamd_context *ctx, ++ struct teamd_port *tdport, void *priv) ++{ ++ struct lacp *lacp = priv; ++ struct lacp_port *lacp_port = lacp_port_get(lacp, tdport); ++ ++ if (lacp_port_selected(lacp_port)) ++ (void) lacpdu_send(lacp_port); ++} ++ + static const struct teamd_event_watch_ops lacp_event_watch_ops = { + .hwaddr_changed = lacp_event_watch_hwaddr_changed, + .port_hwaddr_changed = lacp_event_watch_port_hwaddr_changed, +@@ -1428,6 +1438,7 @@ static const struct teamd_event_watch_ops lacp_event_watch_ops = { + .port_removed = lacp_event_watch_port_removed, + .port_changed = lacp_event_watch_port_changed, + .admin_state_changed = lacp_event_watch_admin_state_changed, ++ .refresh = lacp_event_watch_refresh, + }; + + static int lacp_carrier_init(struct teamd_context *ctx, struct lacp *lacp) +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/0003-libteam-Add-fallback-support-for-single-member-port-.patch b/src/libteam/patch/0003-libteam-Add-fallback-support-for-single-member-port-.patch new file mode 100644 index 000000000000..742db5fc6a98 --- /dev/null +++ b/src/libteam/patch/0003-libteam-Add-fallback-support-for-single-member-port-.patch @@ -0,0 +1,122 @@ +From 4696acb51172dbe486d175073bdce8c94817f422 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 3 Mar 2020 12:52:28 -0800 +Subject: [PATCH] [libteam] Add fallback support for single-member-port LAG + +--- + teamd/teamd_runner_lacp.c | 48 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 44 insertions(+), 4 deletions(-) + +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index 7592b01..2062bf2 100644 +--- a/teamd/teamd_runner_lacp.c ++++ b/teamd/teamd_runner_lacp.c +@@ -138,6 +138,8 @@ struct lacp { + #define LACP_CFG_DFLT_SYS_PRIO 0xffff + bool fast_rate; + #define LACP_CFG_DFLT_FAST_RATE false ++ bool fallback; ++#define LACP_CFG_DFLT_FALLBACK false + int min_ports; + #define LACP_CFG_DFLT_MIN_PORTS 1 + enum lacp_agg_select_policy agg_select_policy; +@@ -272,6 +274,11 @@ static int lacp_load_config(struct teamd_context *ctx, struct lacp *lacp) + lacp->cfg.fast_rate = LACP_CFG_DFLT_FAST_RATE; + teamd_log_dbg(ctx, "Using fast_rate \"%d\".", lacp->cfg.fast_rate); + ++ err = teamd_config_bool_get(ctx, &lacp->cfg.fallback, "$.runner.fallback"); ++ if (err) ++ lacp->cfg.fallback = LACP_CFG_DFLT_FALLBACK; ++ teamd_log_dbg(ctx, "Using fallback \"%d\".", lacp->cfg.fallback); ++ + err = teamd_config_int_get(ctx, &tmp, "$.runner.min_ports"); + if (err) { + lacp->cfg.min_ports = LACP_CFG_DFLT_MIN_PORTS; +@@ -308,9 +315,24 @@ static bool lacp_port_loopback_free(struct lacp_port *lacp_port) + return true; + } + ++/* ++ * is_lacp_fallback_eligible - is lacp_port eligible to go into lacp fallback mode ++ * ++ * Return true if it is, false otherwise ++ */ ++static bool is_lacp_fallback_eligible(struct lacp_port *lacp_port) ++{ ++ teamd_log_dbg(lacp_port->ctx, "%s fallback eligible state \"%d \" cfg \"%d\".", ++ lacp_port->tdport->ifname, lacp_port->state, ++ lacp_port->lacp->cfg.fallback); ++ return lacp_port->state == PORT_STATE_DEFAULTED && ++ lacp_port->lacp->cfg.fallback; ++} ++ + static bool lacp_port_selectable_state(struct lacp_port *lacp_port) + { +- if (lacp_port->state == PORT_STATE_CURRENT) ++ if (lacp_port->state == PORT_STATE_CURRENT || ++ is_lacp_fallback_eligible(lacp_port)) + return true; + return false; + } +@@ -318,7 +340,8 @@ static bool lacp_port_selectable_state(struct lacp_port *lacp_port) + static bool lacp_port_unselectable_state(struct lacp_port *lacp_port) + { + if (lacp_port->state == PORT_STATE_CURRENT || +- lacp_port->state == PORT_STATE_EXPIRED) ++ lacp_port->state == PORT_STATE_EXPIRED || ++ is_lacp_fallback_eligible(lacp_port)) + return false; + return true; + } +@@ -334,7 +357,8 @@ static int lacp_port_should_be_enabled(struct lacp_port *lacp_port) + + if (lacp_port_selected(lacp_port) && + lacp_port->agg_lead == lacp->selected_agg_lead && +- lacp_port->partner.state & INFO_STATE_SYNCHRONIZATION) ++ (lacp_port->partner.state & INFO_STATE_SYNCHRONIZATION || ++ is_lacp_fallback_eligible(lacp_port))) + return true; + return false; + } +@@ -345,7 +369,8 @@ static int lacp_port_should_be_disabled(struct lacp_port *lacp_port) + + if (!lacp_port_selected(lacp_port) || + lacp_port->agg_lead != lacp->selected_agg_lead || +- !(lacp_port->partner.state & INFO_STATE_SYNCHRONIZATION)) ++ (!(lacp_port->partner.state & INFO_STATE_SYNCHRONIZATION) && ++ !is_lacp_fallback_eligible(lacp_port))) + return true; + return false; + } +@@ -1502,6 +1527,16 @@ static int lacp_state_fast_rate_get(struct teamd_context *ctx, + return 0; + } + ++static int lacp_state_fallback_get(struct teamd_context *ctx, ++ struct team_state_gsc *gsc, ++ void *priv) ++{ ++ struct lacp *lacp = priv; ++ ++ gsc->data.bool_val = lacp->cfg.fallback; ++ return 0; ++} ++ + static int lacp_state_select_policy_get(struct teamd_context *ctx, + struct team_state_gsc *gsc, + void *priv) +@@ -1528,6 +1563,11 @@ static const struct teamd_state_val lacp_state_vals[] = { + .type = TEAMD_STATE_ITEM_TYPE_BOOL, + .getter = lacp_state_fast_rate_get, + }, ++ { ++ .subpath = "fallback", ++ .type = TEAMD_STATE_ITEM_TYPE_BOOL, ++ .getter = lacp_state_fallback_get, ++ }, + { + .subpath = "select_policy", + .type = TEAMD_STATE_ITEM_TYPE_STRING, +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/0004-Skip-setting-the-same-hwaddr-to-lag-port-to-avoid-di.patch b/src/libteam/patch/0004-Skip-setting-the-same-hwaddr-to-lag-port-to-avoid-di.patch new file mode 100644 index 000000000000..8f3a8592814a --- /dev/null +++ b/src/libteam/patch/0004-Skip-setting-the-same-hwaddr-to-lag-port-to-avoid-di.patch @@ -0,0 +1,33 @@ +From 09af7e3106720c871cdbadff9f661685aa1bdb16 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 3 Mar 2020 12:54:09 -0800 +Subject: [PATCH] Skip setting the same hwaddr to lag port to avoid disrupting + +--- + teamd/teamd.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/teamd/teamd.c b/teamd/teamd.c +index dc46a62..bf42347 100644 +--- a/teamd/teamd.c ++++ b/teamd/teamd.c +@@ -834,7 +834,15 @@ static int teamd_set_hwaddr(struct teamd_context *ctx) + err = -EINVAL; + goto free_hwaddr; + } +- err = team_hwaddr_set(ctx->th, ctx->ifindex, hwaddr, hwaddr_len); ++ ++ if(!memcmp(hwaddr, ctx->hwaddr, hwaddr_len)) { ++ err = 0; ++ teamd_log_dbg(ctx, "Skip setting same hwaddr string: \"%s\".", hwaddr_str); ++ } ++ else{ ++ err = team_hwaddr_set(ctx->th, ctx->ifindex, hwaddr, hwaddr_len); ++ } ++ + if (!err) + ctx->hwaddr_explicit = true; + free_hwaddr: +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/0005-Increase-default-buffer-size-from-98304-to-983040.patch b/src/libteam/patch/0005-Increase-default-buffer-size-from-98304-to-983040.patch new file mode 100644 index 000000000000..ac86c549b686 --- /dev/null +++ b/src/libteam/patch/0005-Increase-default-buffer-size-from-98304-to-983040.patch @@ -0,0 +1,28 @@ +From fcb9932bdb9212e9b18302de4ffb4d64003e93ab Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 3 Mar 2020 12:55:50 -0800 +Subject: [PATCH] Increase default buffer size from 98304 to 983040 + +--- + libteam/libteam.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libteam/libteam.c b/libteam/libteam.c +index 9c9c93a..2cc80ca 100644 +--- a/libteam/libteam.c ++++ b/libteam/libteam.c +@@ -551,9 +551,9 @@ int team_destroy(struct team_handle *th) + /* \endcond */ + + /* libnl uses default 32k socket receive buffer size, +- * which can get too small. Use 192k for all sockets. ++ * which can get too small. Use 960k for all sockets. + */ +-#define NETLINK_RCVBUF 196608 ++#define NETLINK_RCVBUF 983040 + + /** + * @param th libteam library context +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/0006-teamd-Administratively-shutdown-port-channel-has-mem.patch b/src/libteam/patch/0006-teamd-Administratively-shutdown-port-channel-has-mem.patch new file mode 100644 index 000000000000..7cc4e52c8a0f --- /dev/null +++ b/src/libteam/patch/0006-teamd-Administratively-shutdown-port-channel-has-mem.patch @@ -0,0 +1,35 @@ +From b188ed48f9ea6873a2c9263d5e036a3634c0f4ba Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 3 Mar 2020 12:59:09 -0800 +Subject: [PATCH] [teamd]: Administratively shutdown port channel has member + ports in deselected state and traffic is not forwarded + +--- + teamd/teamd_runner_lacp.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index 2062bf2..fa732ba 100644 +--- a/teamd/teamd_runner_lacp.c ++++ b/teamd/teamd_runner_lacp.c +@@ -1103,12 +1103,17 @@ static int lacpdu_recv(struct lacp_port *lacp_port) + struct lacpdu lacpdu; + struct sockaddr_ll ll_from; + int err; ++ bool admin_state; + + err = teamd_recvfrom(lacp_port->sock, &lacpdu, sizeof(lacpdu), 0, + (struct sockaddr *) &ll_from, sizeof(ll_from)); + if (err <= 0) + return err; + ++ admin_state = team_get_ifinfo_admin_state(lacp_port->ctx->ifinfo); ++ if (!admin_state) ++ return 0; ++ + if (!teamd_port_present(lacp_port->ctx, lacp_port->tdport)) + return 0; + +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/0007-Send-LACP-PDU-immediately-if-our-state-changed.patch b/src/libteam/patch/0007-Send-LACP-PDU-immediately-if-our-state-changed.patch new file mode 100644 index 000000000000..f4af9169ae1e --- /dev/null +++ b/src/libteam/patch/0007-Send-LACP-PDU-immediately-if-our-state-changed.patch @@ -0,0 +1,39 @@ +From 780cc967a5544d3ab6f43cba4076b5e0dbb48395 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 3 Mar 2020 13:01:14 -0800 +Subject: [PATCH] Send LACP PDU immediately if our state changed + +--- + teamd/teamd_runner_lacp.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index fa732ba..55abe88 100644 +--- a/teamd/teamd_runner_lacp.c ++++ b/teamd/teamd_runner_lacp.c +@@ -1019,8 +1019,7 @@ static int lacp_port_set_state(struct lacp_port *lacp_port, + return err; + + lacp_port_actor_update(lacp_port); +- if (lacp_port->periodic_on) +- return 0; ++ + return lacpdu_send(lacp_port); + } + +@@ -1138,9 +1137,10 @@ static int lacpdu_recv(struct lacp_port *lacp_port) + if (err) + return err; + ++ lacp_port_actor_update(lacp_port); ++ + /* Check if the other side has correct info about us */ +- if (!lacp_port->periodic_on && +- memcmp(&lacpdu.partner, &lacp_port->actor, ++ if (memcmp(&lacpdu.partner, &lacp_port->actor, + sizeof(struct lacpdu_info))) { + err = lacpdu_send(lacp_port); + if (err) +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/0008-libteam-Add-warm_reboot-mode.patch b/src/libteam/patch/0008-libteam-Add-warm_reboot-mode.patch new file mode 100644 index 000000000000..440d351a8b6e --- /dev/null +++ b/src/libteam/patch/0008-libteam-Add-warm_reboot-mode.patch @@ -0,0 +1,884 @@ +From a4ab4de68134f6425f704a2ddcda33a4930645de Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 3 Mar 2020 13:04:57 -0800 +Subject: [PATCH] [libteam]: Reimplement Warm-Reboot procedure' + +--- + libteam/ifinfo.c | 6 +- + teamd/teamd.c | 51 +++- + teamd/teamd.h | 6 + + teamd/teamd_events.c | 13 ++ + teamd/teamd_per_port.c | 6 + + teamd/teamd_runner_lacp.c | 474 +++++++++++++++++++++++++++++++++++--- + 6 files changed, 512 insertions(+), 44 deletions(-) + +diff --git a/libteam/ifinfo.c b/libteam/ifinfo.c +index 46d56a2..b86d34c 100644 +--- a/libteam/ifinfo.c ++++ b/libteam/ifinfo.c +@@ -109,15 +109,13 @@ static void update_hwaddr(struct team_ifinfo *ifinfo, struct rtnl_link *link) + hwaddr_len = nl_addr_get_len(nl_addr); + if (ifinfo->hwaddr_len != hwaddr_len) { + ifinfo->hwaddr_len = hwaddr_len; +- if (!ifinfo->master_ifindex) +- ifinfo->orig_hwaddr_len = hwaddr_len; ++ ifinfo->orig_hwaddr_len = hwaddr_len; + set_changed(ifinfo, CHANGED_HWADDR_LEN); + } + hwaddr = nl_addr_get_binary_addr(nl_addr); + if (memcmp(ifinfo->hwaddr, hwaddr, hwaddr_len)) { + memcpy(ifinfo->hwaddr, hwaddr, hwaddr_len); +- if (!ifinfo->master_ifindex) +- memcpy(ifinfo->orig_hwaddr, hwaddr, hwaddr_len); ++ memcpy(ifinfo->orig_hwaddr, hwaddr, hwaddr_len); + set_changed(ifinfo, CHANGED_HWADDR); + } + } +diff --git a/teamd/teamd.c b/teamd/teamd.c +index bf42347..221d71d 100644 +--- a/teamd/teamd.c ++++ b/teamd/teamd.c +@@ -117,7 +117,9 @@ static void print_help(const struct teamd_context *ctx) { + " -D --dbus-enable Enable D-Bus interface\n" + " -Z --zmq-enable=ADDRESS Enable ZeroMQ interface\n" + " -U --usock-enable Enable UNIX domain socket interface\n" +- " -u --usock-disable Disable UNIX domain socket interface\n", ++ " -u --usock-disable Disable UNIX domain socket interface\n" ++ " -w --warm-start Warm-start startup mode\n" ++ " -L --lacp-directory Directory for saving lacp pdu dumps\n", + ctx->argv0); + printf("Available runners: "); + for (i = 0; i < TEAMD_RUNNER_LIST_SIZE; i++) { +@@ -151,10 +153,12 @@ static int parse_command_line(struct teamd_context *ctx, + { "zmq-enable", required_argument, NULL, 'Z' }, + { "usock-enable", no_argument, NULL, 'U' }, + { "usock-disable", no_argument, NULL, 'u' }, ++ { "warm-start", no_argument, NULL, 'w' }, ++ { "lacp-directory", required_argument, NULL, 'L' }, + { NULL, 0, NULL, 0 } + }; + +- while ((opt = getopt_long(argc, argv, "hdkevf:c:p:gl:roNt:nDZ:Uu", ++ while ((opt = getopt_long(argc, argv, "hdkevf:c:p:gl:roNt:nDZ:UuwL:", + long_options, NULL)) >= 0) { + + switch(opt) { +@@ -236,11 +240,27 @@ static int parse_command_line(struct teamd_context *ctx, + case 'u': + ctx->usock.enabled = false; + break; ++ case 'w': ++ ctx->warm_start_mode = true; ++ break; ++ case 'L': ++ ctx->lacp_directory = strdup(optarg); ++ if (access(ctx->lacp_directory, R_OK | W_OK | X_OK) != 0) { ++ fprintf(stderr, "Can't write to the lacp directory '%s': %s\n", ctx->lacp_directory, strerror(errno)); ++ free(ctx->lacp_directory); ++ ctx->lacp_directory = NULL; ++ } ++ break; + default: + return -1; + } + } + ++ if (ctx->warm_start_mode && !ctx->lacp_directory) { ++ fprintf(stderr, "Can't enable warm-start mode without lacp-directory specified\n"); ++ ctx->warm_start_mode = false; ++ } ++ + if (optind < argc) { + fprintf(stderr, "Too many arguments\n"); + return -1; +@@ -390,9 +410,18 @@ static int teamd_run_loop_run(struct teamd_context *ctx) + if (err != -1) { + switch(ctrl_byte) { + case 'q': ++ case 'f': ++ case 'w': + if (quit_in_progress) + return -EBUSY; +- teamd_refresh_ports(ctx); ++ if (ctrl_byte == 'w' || ctrl_byte == 'f') { ++ ctx->keep_ports = true; ++ ctx->no_quit_destroy = true; ++ teamd_refresh_ports(ctx); ++ if (ctrl_byte == 'w') ++ teamd_ports_flush_data(ctx); ++ } ++ + err = teamd_flush_ports(ctx); + if (err) + return err; +@@ -434,6 +463,12 @@ void teamd_run_loop_quit(struct teamd_context *ctx, int err) + teamd_run_loop_sent_ctrl_byte(ctx, 'q'); + } + ++static void teamd_run_loop_quit_a_boot(struct teamd_context *ctx, char type, int err) ++{ ++ ctx->run_loop.err = err; ++ teamd_run_loop_sent_ctrl_byte(ctx, type); ++} ++ + void teamd_run_loop_restart(struct teamd_context *ctx) + { + teamd_run_loop_sent_ctrl_byte(ctx, 'r'); +@@ -700,6 +735,14 @@ static int callback_daemon_signal(struct teamd_context *ctx, int events, + teamd_log_warn("Got SIGINT, SIGQUIT or SIGTERM."); + teamd_run_loop_quit(ctx, 0); + break; ++ case SIGUSR1: ++ teamd_log_warn("Got SIGUSR1."); ++ teamd_run_loop_quit_a_boot(ctx, 'w', 0); ++ break; ++ case SIGUSR2: ++ teamd_log_warn("Got SIGUSR2."); ++ teamd_run_loop_quit_a_boot(ctx, 'f', 0); ++ break; + } + return 0; + } +@@ -1533,7 +1576,7 @@ static int teamd_start(struct teamd_context *ctx, enum teamd_exit_code *p_ret) + return -errno; + } + +- if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) < 0) { ++ if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGUSR1, SIGUSR2, 0) < 0) { + teamd_log_err("Could not register signal handlers."); + daemon_retval_send(errno); + err = -errno; +diff --git a/teamd/teamd.h b/teamd/teamd.h +index 01ebc84..701a6a4 100644 +--- a/teamd/teamd.h ++++ b/teamd/teamd.h +@@ -126,6 +126,9 @@ struct teamd_context { + char * hwaddr; + uint32_t hwaddr_len; + bool hwaddr_explicit; ++ bool warm_start_mode; ++ bool keep_ports; ++ char * lacp_directory; + struct { + struct list_item callback_list; + int ctrl_pipe_r; +@@ -195,12 +198,15 @@ struct teamd_event_watch_ops { + void *priv); + void (*refresh)(struct teamd_context *ctx, + struct teamd_port *tdport, void *priv); ++ void (*port_flush_data)(struct teamd_context *ctx, ++ struct teamd_port *tdport, void *priv); + int (*option_changed)(struct teamd_context *ctx, + struct team_option *option, void *priv); + char *option_changed_match_name; + }; + + void teamd_refresh_ports(struct teamd_context *ctx); ++void teamd_ports_flush_data(struct teamd_context *ctx); + int teamd_event_port_added(struct teamd_context *ctx, + struct teamd_port *tdport); + void teamd_event_port_removed(struct teamd_context *ctx, +diff --git a/teamd/teamd_events.c b/teamd/teamd_events.c +index 221803e..bd4dcc1 100644 +--- a/teamd/teamd_events.c ++++ b/teamd/teamd_events.c +@@ -47,6 +47,19 @@ void teamd_refresh_ports(struct teamd_context *ctx) + } + } + ++void teamd_ports_flush_data(struct teamd_context *ctx) ++{ ++ struct teamd_port *tdport; ++ struct event_watch_item *watch; ++ ++ teamd_for_each_tdport(tdport, ctx) { ++ list_for_each_node_entry(watch, &ctx->event_watch_list, list) { ++ if (!watch->ops->port_flush_data) continue; ++ watch->ops->port_flush_data(ctx, tdport, watch->priv); ++ } ++ } ++} ++ + int teamd_event_port_added(struct teamd_context *ctx, + struct teamd_port *tdport) + { +diff --git a/teamd/teamd_per_port.c b/teamd/teamd_per_port.c +index 166da57..03f8d63 100644 +--- a/teamd/teamd_per_port.c ++++ b/teamd/teamd_per_port.c +@@ -350,6 +350,12 @@ static int teamd_port_remove(struct teamd_context *ctx, + { + int err; + ++ if (ctx->keep_ports) { ++ teamd_log_dbg(ctx, "%s: Keeping port (found ifindex \"%d\").", ++ tdport->ifname, tdport->ifindex); ++ return 0; ++ } ++ + teamd_log_dbg(ctx, "%s: Removing port (found ifindex \"%d\").", + tdport->ifname, tdport->ifindex); + err = team_port_remove(ctx->th, tdport->ifindex); +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index 55abe88..f225fb2 100644 +--- a/teamd/teamd_runner_lacp.c ++++ b/teamd/teamd_runner_lacp.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include "teamd.h" + #include "teamd_config.h" +@@ -127,10 +128,18 @@ static const char *lacp_agg_select_policy_names_list[] = { + + struct lacp_port; + ++struct wr_tdport_state ++{ ++ char name[IFNAMSIZ+1]; ++ bool enabled; ++ bool checked; ++}; ++ + struct lacp { + struct teamd_context *ctx; + struct lacp_port *selected_agg_lead; /* leading port of selected aggregator */ + bool carrier_up; ++ time_t warm_start_mode_timer; + struct { + bool active; + #define LACP_CFG_DFLT_ACTIVE true +@@ -145,6 +154,11 @@ struct lacp { + enum lacp_agg_select_policy agg_select_policy; + #define LACP_CFG_DFLT_AGG_SELECT_POLICY LACP_AGG_SELECT_LACP_PRIO + } cfg; ++ struct { ++ bool carrier_up; ++ uint16_t nr_of_tdports; ++ struct wr_tdport_state *state; ++ } wr; + struct teamd_balancer *tb; + }; + +@@ -174,6 +188,8 @@ struct lacp_port { + struct lacp_port *agg_lead; /* leading port of aggregator. + * NULL in case this port is not selected */ + enum lacp_port_state state; ++ bool lacpdu_saved; ++ struct lacpdu last_pdu; + struct { + uint32_t speed; + uint8_t duplex; +@@ -189,6 +205,201 @@ struct lacp_port { + } cfg; + }; + ++static void generate_path(struct teamd_context *ctx, char path[PATH_MAX], const char* filename) ++{ ++ strcpy(path, ctx->lacp_directory); ++ /* Add trailing slash if we don't have one in the filename */ ++ if (path[strlen(path) - 1] != '/') ++ strcat(path, "/"); ++ strcat(path, filename); ++} ++ ++static int find_wr_info(struct lacp_port *lacp_port) { ++ struct lacp* lacp = lacp_port->lacp; ++ int i, found = -1; ++ ++ for (i = 0; i < lacp->wr.nr_of_tdports; ++i) { ++ if (strcmp(lacp->wr.state[i].name, lacp_port->tdport->ifname) == 0) { ++ found = i; ++ break; ++ } ++ } ++ ++ if (found == -1) ++ teamd_log_warn("WR-mode. Found a newly added LAG member port: '%s' after restart. " ++ "The configuration was changed?", lacp_port->tdport->ifname); ++ ++ return found; ++} ++ ++static void remove_file(struct teamd_context *ctx, const char *name) { ++ char filename[PATH_MAX]; ++ int err; ++ ++ generate_path(ctx, filename, name); ++ ++ err = access(filename, R_OK); ++ if (err != 0) { ++ /* file is not present. Skip it */ ++ return; ++ } ++ ++ err = unlink(filename); ++ if (err < 0) { ++ teamd_log_err("WR-mode. Can't remove file %s: %s", filename, strerror(errno)); ++ } ++} ++ ++static void stop_wr_mode(struct lacp *lacp) { ++ int i; ++ ++ teamd_log_info("WR-mode. Stopping WR start mode"); ++ ++ lacp->ctx->warm_start_mode = false; ++ lacp->warm_start_mode_timer = 0; ++ ++ remove_file(lacp->ctx, lacp->ctx->team_devname); ++ for (i = 0; i < lacp->wr.nr_of_tdports; ++i) { ++ remove_file(lacp->ctx, lacp->wr.state[i].name); ++ } ++ ++ lacp->wr.nr_of_tdports = 0; ++ if (lacp->wr.state) ++ free(lacp->wr.state); ++ lacp->wr.state = NULL; ++} ++ ++static int lacpdu_read(struct lacp_port *lacp_port, struct lacpdu *lacpdu) ++{ ++ FILE* fp; ++ char filename[PATH_MAX]; ++ int err, nitems; ++ ++ teamd_log_dbg(lacp_port->ctx, "WR-mode. function lacpdu_read(): %s", lacp_port->tdport->ifname); ++ ++ generate_path(lacp_port->ctx, filename, lacp_port->tdport->ifname); ++ ++ /* check that file is readable. if there is no file, don't do anything */ ++ err = access(filename, R_OK); ++ if (err != 0) { ++ teamd_log_err("WR-mode. LACPDU state file '%s' is unreadable", filename); ++ return err; ++ } ++ ++ fp = fopen(filename, "r"); ++ if (!fp) { ++ teamd_log_err("WR-mode. Can't open lacp-saved dump from file '%s': %s", filename, strerror(errno)); ++ return errno; ++ } ++ ++ nitems = fread(lacpdu, sizeof(struct lacpdu), 1, fp); ++ (void)fclose(fp); ++ ++ err = unlink(filename); ++ if (err < 0) { ++ teamd_log_err("WR-mode. Can't remove file '%s': %s", filename, strerror(errno)); ++ } ++ ++ if (nitems != 1) { ++ teamd_log_err("WR-mode. Can't read lacp-saved dump from file '%s': %s", filename, strerror(errno)); ++ return -EINVAL; ++ } ++ ++ teamd_log_info("WR-mode. LACP state was read for port '%s'", lacp_port->tdport->ifname); ++ ++ return 0; ++} ++ ++static void lacp_state_save(struct teamd_context *ctx, struct lacp *lacp) ++{ ++ char filename[PATH_MAX]; ++ FILE *fp; ++ int i, err; ++ ++ generate_path(ctx, filename, ctx->team_devname); ++ ++ fp = fopen(filename, "wt"); ++ if (!fp) { ++ teamd_log_err("WR-mode. Can't open the file '%s' to save the lacp dump: %s", filename, strerror(errno)); ++ goto error; ++ } ++ ++ err = fprintf(fp, "%d\n%d\n", lacp->carrier_up ? 1 : 0, lacp->wr.nr_of_tdports); ++ if (err < 0) { ++ teamd_log_err("WR-mode. Can't write to the file '%s' to save the lacp dump: %s", filename, strerror(errno)); ++ goto error_with_close; ++ } ++ ++ for (i = 0; i < lacp->wr.nr_of_tdports; ++i) { ++ err = fprintf(fp, "%s\n%d\n", lacp->wr.state[i].name, lacp->wr.state[i].enabled ? 1 : 0); ++ if (err < 0) { ++ teamd_log_err("WR-mode. Can't write to the file '%s' to save the lacp dump: %s", filename, strerror(errno)); ++ goto error_with_close; ++ } ++ } ++ ++error_with_close: ++ (void)fclose(fp); ++ ++error: ++ (void)free(lacp->wr.state); ++ lacp->wr.state = NULL; ++ lacp->wr.nr_of_tdports = 0; ++} ++ ++static int lacp_state_load(struct teamd_context *ctx, struct lacp *lacp) ++{ ++ char filename[PATH_MAX]; ++ FILE *fp; ++ int data1, data2, i, err; ++ ++ teamd_log_dbg(ctx, "WR-mode. function lacp_state_load()"); ++ ++ generate_path(ctx, filename, ctx->team_devname); ++ ++ fp = fopen(filename, "rt"); ++ if (!fp) { ++ teamd_log_err("WR-mode. Can't open the file '%s' to load the lacp dump: %s", filename, strerror(errno)); ++ return errno; ++ } ++ ++ err = fscanf(fp, "%d\n%d\n", &data1, &data2); ++ if (err != 2) { ++ teamd_log_err("WR-mode. Can't read the file '%s'. Wrong format", filename); ++ (void)fclose(fp); ++ return -1; ++ } ++ lacp->wr.carrier_up = data1 == 1; ++ lacp->wr.nr_of_tdports = data2; ++ ++ lacp->wr.state = calloc(lacp->wr.nr_of_tdports, sizeof(struct wr_tdport_state)); ++ if (!lacp->wr.state) { ++ teamd_log_err("WR-mode. lacp_state_load: Not enough memory. %s", ctx->team_devname); ++ return -1; ++ } ++ for (i = 0; i < lacp->wr.nr_of_tdports; ++i) { ++ err = fscanf(fp, "%16s\n%d\n", &lacp->wr.state[i].name[0], &data1); ++ if (err != 2) { ++ teamd_log_err("WR-mode. Can't read the file '%s'. Wrong format", filename); ++ (void)free(lacp->wr.state); ++ lacp->wr.state = NULL; ++ (void)fclose(fp); ++ return -1; ++ } ++ lacp->wr.state[i].enabled = data1 == 1; ++ lacp->wr.state[i].checked = false; ++ } ++ ++ (void)fclose(fp); ++ ++ err = unlink(filename); ++ if (err < 0) { ++ teamd_log_err("WR-mode. Can't remove file %s: %s", filename, strerror(errno)); ++ } ++ ++ return 0; ++} ++ + static struct lacp_port *lacp_port_get(struct lacp *lacp, + struct teamd_port *tdport) + { +@@ -488,20 +699,95 @@ static int lacp_set_carrier(struct lacp *lacp, bool carrier_up) + return 0; + } + ++static int lacpdu_process(struct lacp_port *lacp_port, struct lacpdu* lacpdu); ++ ++#define LACP_WARM_START_CARRIER_TIMEOUT 3 ++ + static int lacp_update_carrier(struct lacp *lacp) + { + struct teamd_port *tdport; + int ports_enabled; +- bool state; + int err; + ++ if (lacp->ctx->warm_start_mode) { ++ teamd_log_dbg(lacp->ctx, "WR-mode. function lacp_update_carrier()"); ++ } ++ + ports_enabled = 0; + teamd_for_each_tdport(tdport, lacp->ctx) { ++ bool state; + err = teamd_port_enabled(lacp->ctx, tdport, &state); + if (err) + return err; +- if (state && ++ports_enabled >= lacp->cfg.min_ports) +- return lacp_set_carrier(lacp, true); ++ ++ if (state) ++ ++ports_enabled; ++ ++ if (lacp->ctx->warm_start_mode) { ++ int found; ++ struct lacp_port* lacp_port; ++ bool linkup; ++ ++ lacp_port = lacp_port_get(lacp, tdport); ++ found = find_wr_info(lacp_port); ++ if (found < 0) /* newly added port was found */ ++ continue; ++ ++ linkup = team_is_port_link_up(lacp_port->tdport->team_port); ++ if (linkup) { /* read when the port is in carrier up state */ ++ if (!lacp->wr.state[found].checked) { ++ lacp->wr.state[found].checked = true; ++ ++ if(lacp->wr.state[found].enabled) { ++ /* the port was up before the WR. Trying to restore it */ ++ struct lacpdu lacpdu; ++ err = lacpdu_read(lacp_port, &lacpdu); ++ if (err) /* Can't read, so the port will start from scratch */ ++ continue; ++ teamd_log_info("WR-mode. State of the LAG member port '%s' was restored.", ++ tdport->ifname); ++ return lacpdu_process(lacp_port, &lacpdu); /* it runs lacp_update_carrier() inside of it */ ++ } else { ++ teamd_log_info("WR-mode. State of the LAG member port '%s' was down before the restart. Nothing to read", ++ tdport->ifname); ++ } ++ } ++ } ++ } ++ } ++ ++ if (lacp->ctx->warm_start_mode) { ++ int i; ++ bool has_all_ports_added = true; ++ for (i = 0; i < lacp->wr.nr_of_tdports; ++i) ++ has_all_ports_added = has_all_ports_added && lacp->wr.state[i].checked; ++ ++ if (has_all_ports_added) { ++ teamd_log_info("WR-mode. The state for all %d LAG member ports was restored.", ++ lacp->wr.nr_of_tdports); ++ stop_wr_mode(lacp); ++ } ++ } ++ ++ if (lacp->ctx->warm_start_mode) { ++ if (lacp->warm_start_mode_timer == 0) { ++ lacp->warm_start_mode_timer = time(NULL) + LACP_WARM_START_CARRIER_TIMEOUT; ++ } else if (time(NULL) >= lacp->warm_start_mode_timer) { ++ teamd_log_err("WR-mode. Timeout occured. Can't start in WR mode in %d seconds", ++ LACP_WARM_START_CARRIER_TIMEOUT); ++ stop_wr_mode(lacp); ++ } ++ } ++ ++ if (ports_enabled >= lacp->cfg.min_ports) { ++ teamd_log_dbg(lacp->ctx, "Enable carrier. Number of enabled ports %d >= configured min_ports %d", ++ ports_enabled, lacp->cfg.min_ports); ++ return lacp_set_carrier(lacp, true); ++ } ++ ++ if (lacp->ctx->warm_start_mode) { ++ teamd_log_info("WR-mode. lacp_update_carrier(): Keep LAG interface up because of WR start mode"); ++ return lacp_set_carrier(lacp, true); + } + + return lacp_set_carrier(lacp, false); +@@ -921,6 +1207,18 @@ static void lacp_port_actor_system_update(struct lacp_port *lacp_port) + memcpy(actor->system, lacp_port->ctx->hwaddr, ETH_ALEN); + } + ++static int lacp_portname_to_port_id(const char* name) ++{ ++#define PORT_PREFIX "Ethernet" ++ const char* strport_id = name + sizeof(PORT_PREFIX) - 1; ++ const int port_id = atoi(strport_id); ++ if ((port_id == 0) && strcmp(strport_id, "0")) { ++ teamd_log_err("%s: Can't convert from port name to port id. Port id is equal to 0, but this is not expected", name); ++ } ++ ++ return htons(port_id + 1); ++} ++ + static void lacp_port_actor_init(struct lacp_port *lacp_port) + { + struct lacpdu_info *actor = &lacp_port->actor; +@@ -928,7 +1226,7 @@ static void lacp_port_actor_init(struct lacp_port *lacp_port) + actor->system_priority = htons(lacp_port->lacp->cfg.sys_prio); + actor->key = htons(lacp_port->cfg.lacp_key); + actor->port_priority = htons(lacp_port->cfg.lacp_prio); +- actor->port = htons(lacp_port->tdport->ifindex); ++ actor->port = lacp_portname_to_port_id(lacp_port->tdport->ifname); + lacp_port_actor_system_update(lacp_port); + } + +@@ -1008,6 +1306,13 @@ static int lacp_port_set_state(struct lacp_port *lacp_port, + break; + } + ++ if (new_state != PORT_STATE_CURRENT) { ++ /* clean saved lacp pdu up when the current port: ++ disabled, expired, or defaulted */ ++ (void)memset(&lacp_port->last_pdu, 0, sizeof(struct lacpdu)); ++ lacp_port->lacpdu_saved = false; ++ } ++ + teamd_log_info("%s: Changed port state: \"%s\" -> \"%s\"", + lacp_port->tdport->ifname, + lacp_port_state_name[lacp_port->state], +@@ -1097,34 +1402,23 @@ static int lacpdu_send(struct lacp_port *lacp_port) + return err; + } + +-static int lacpdu_recv(struct lacp_port *lacp_port) ++static int lacpdu_process(struct lacp_port *lacp_port, struct lacpdu* lacpdu) + { +- struct lacpdu lacpdu; +- struct sockaddr_ll ll_from; + int err; +- bool admin_state; +- +- err = teamd_recvfrom(lacp_port->sock, &lacpdu, sizeof(lacpdu), 0, +- (struct sockaddr *) &ll_from, sizeof(ll_from)); +- if (err <= 0) +- return err; +- +- admin_state = team_get_ifinfo_admin_state(lacp_port->ctx->ifinfo); +- if (!admin_state) +- return 0; +- +- if (!teamd_port_present(lacp_port->ctx, lacp_port->tdport)) +- return 0; + +- if (!lacpdu_check(&lacpdu)) { ++ if (!lacpdu_check(lacpdu)) { + teamd_log_warn("malformed LACP PDU came."); + return 0; + } + ++ /* save received lacp pdu frame */ ++ (void)memcpy(&lacp_port->last_pdu, lacpdu, sizeof(struct lacpdu)); ++ lacp_port->lacpdu_saved = true; ++ + /* Check if we have correct info about the other side */ +- if (memcmp(&lacpdu.actor, &lacp_port->partner, ++ if (memcmp(&lacpdu->actor, &lacp_port->partner, + sizeof(struct lacpdu_info))) { +- lacp_port->partner = lacpdu.actor; ++ lacp_port->partner = lacpdu->actor; + err = lacp_port_partner_update(lacp_port); + if (err) + return err; +@@ -1140,21 +1434,56 @@ static int lacpdu_recv(struct lacp_port *lacp_port) + lacp_port_actor_update(lacp_port); + + /* Check if the other side has correct info about us */ +- if (memcmp(&lacpdu.partner, &lacp_port->actor, ++ if (memcmp(&lacpdu->partner, &lacp_port->actor, + sizeof(struct lacpdu_info))) { + err = lacpdu_send(lacp_port); + if (err) + return err; + } + err = lacp_port_timeout_set(lacp_port, false); +- if (err) { ++ if (err) + return err; +- } ++ + teamd_loop_callback_enable(lacp_port->ctx, + LACP_TIMEOUT_CB_NAME, lacp_port); + return 0; + } + ++static int lacpdu_recv(struct lacp_port *lacp_port) ++{ ++ struct lacpdu lacpdu; ++ struct sockaddr_ll ll_from; ++ int err; ++ bool admin_state; ++ ++ err = teamd_recvfrom(lacp_port->sock, &lacpdu, sizeof(lacpdu), 0, ++ (struct sockaddr *) &ll_from, sizeof(ll_from)); ++ if (err <= 0) ++ return err; ++ ++ if (!teamd_port_present(lacp_port->ctx, lacp_port->tdport)) ++ return 0; ++ ++ admin_state = team_get_ifinfo_admin_state(lacp_port->ctx->ifinfo); ++ if (!admin_state) ++ return 0; ++ ++ /* if the lacpdu wasn't read yet, don't process received pdu */ ++ if (lacp_port->ctx->warm_start_mode) { ++ int found; ++ ++ found = find_wr_info(lacp_port); ++ if (found >= 0 && !lacp_port->lacp->wr.state[found].checked) { ++ teamd_log_info("WR-mode. Received LACP PDU on %s. " ++ "But saved LACP PDU wasn't processed yet.", ++ lacp_port->tdport->ifname); ++ return 0; ++ } ++ } ++ ++ return lacpdu_process(lacp_port, &lacpdu); ++} ++ + static int lacp_callback_timeout(struct teamd_context *ctx, int events, + void *priv) + { +@@ -1260,6 +1589,8 @@ static int lacp_port_added(struct teamd_context *ctx, + struct lacp *lacp = creator_priv; + int err; + ++ teamd_log_dbg(ctx, "function lacp_port_added(): %s", tdport->ifname); ++ + lacp_port->ctx = ctx; + lacp_port->tdport = tdport; + lacp_port->lacp = lacp; +@@ -1306,6 +1637,13 @@ static int lacp_port_added(struct teamd_context *ctx, + goto periodic_callback_del; + } + ++ /* refresh ports from the kernel */ ++ err = team_refresh(ctx->th); ++ if (err) { ++ teamd_log_err("%s: Team refresh failed.", tdport->ifname); ++ goto timeout_callback_del; ++ } ++ + /* Newly added ports are disabled */ + err = team_set_port_enabled(ctx->th, tdport->ifindex, false); + if (err) { +@@ -1343,7 +1681,13 @@ static void lacp_port_removed(struct teamd_context *ctx, + { + struct lacp_port *lacp_port = priv; + +- lacp_port_set_state(lacp_port, PORT_STATE_DISABLED); ++ teamd_log_dbg(lacp_port->ctx, "function lacp_port_removed(): %s", tdport->ifname); ++ ++ if (!lacp_port->ctx->keep_ports) { ++ /* Don't transition into DISABLED state, ++ which sends EXPIRED LACP PDU update */ ++ lacp_port_set_state(lacp_port, PORT_STATE_DISABLED); ++ } + teamd_loop_callback_del(ctx, LACP_TIMEOUT_CB_NAME, lacp_port); + teamd_loop_callback_del(ctx, LACP_PERIODIC_CB_NAME, lacp_port); + teamd_loop_callback_del(ctx, LACP_SOCKET_CB_NAME, lacp_port); +@@ -1451,16 +1795,51 @@ static int lacp_event_watch_port_changed(struct teamd_context *ctx, + return lacp_port_link_update(lacp_port); + } + +-static void lacp_event_watch_refresh(struct teamd_context *ctx, +- struct teamd_port *tdport, void *priv) ++static void lacp_event_watch_refresh(struct teamd_context *ctx, struct teamd_port *tdport, void *priv) + { + struct lacp *lacp = priv; +- struct lacp_port *lacp_port = lacp_port_get(lacp, tdport); + ++ struct lacp_port *lacp_port = lacp_port_get(lacp, tdport); + if (lacp_port_selected(lacp_port)) + (void) lacpdu_send(lacp_port); + } + ++static void lacp_event_watch_port_flush_data(struct teamd_context *ctx, struct teamd_port *tdport, void *priv) ++{ ++ struct lacp *lacp = priv; ++ ++ /* save dump information for each tdport */ ++ lacp->wr.nr_of_tdports++; ++ lacp->wr.state = realloc(lacp->wr.state, sizeof(struct wr_tdport_state) * lacp->wr.nr_of_tdports); ++ if (lacp->wr.state) { ++ int err; ++ strcpy(lacp->wr.state[lacp->wr.nr_of_tdports-1].name, tdport->ifname); ++ err = teamd_port_enabled(ctx, tdport, &lacp->wr.state[lacp->wr.nr_of_tdports-1].enabled); ++ if (err) ++ lacp->wr.state[lacp->wr.nr_of_tdports-1].enabled = false; ++ } else { ++ teamd_log_err("WR-mode. Can't reallocate memory for LACP member %s dump", tdport->ifname); ++ lacp->wr.nr_of_tdports = 0; ++ } ++ ++ struct lacp_port *lacp_port = lacp_port_get(lacp, tdport); ++ if (lacp_port->lacpdu_saved && lacp_port->ctx->lacp_directory) { ++ char filename[PATH_MAX]; ++ generate_path(lacp_port->ctx, filename, lacp_port->tdport->ifname); ++ FILE *fp = fopen(filename, "wb"); ++ if (fp != NULL) { ++ (void)fwrite(&lacp_port->last_pdu, sizeof(struct lacpdu), 1, fp); ++ (void)fclose(fp); ++ } else { ++ teamd_log_err("WR-mode. Can't open file %s for writing %s", filename, strerror(errno)); ++ } ++ } else { ++ if (lacp_port->ctx->lacp_directory == NULL) ++ teamd_log_err("WR-mode. Can't dump received lacp pdu for port %s. " ++ "LACP directory wasn't configured", lacp_port->tdport->ifname); ++ } ++} ++ + static const struct teamd_event_watch_ops lacp_event_watch_ops = { + .hwaddr_changed = lacp_event_watch_hwaddr_changed, + .port_hwaddr_changed = lacp_event_watch_port_hwaddr_changed, +@@ -1469,21 +1848,35 @@ static const struct teamd_event_watch_ops lacp_event_watch_ops = { + .port_changed = lacp_event_watch_port_changed, + .admin_state_changed = lacp_event_watch_admin_state_changed, + .refresh = lacp_event_watch_refresh, ++ .port_flush_data = lacp_event_watch_port_flush_data, + }; + + static int lacp_carrier_init(struct teamd_context *ctx, struct lacp *lacp) + { + int err; + +- /* initialize carrier control */ +- err = team_carrier_set(ctx->th, false); ++ lacp->carrier_up = false; ++ ++ if (ctx->warm_start_mode) { ++ teamd_log_dbg(ctx, "WR-mode. function lacp_carrier_init()"); ++ ++ /* Disable WR start mode if LAG interface was down */ ++ if (lacp->wr.carrier_up) { ++ teamd_log_info("WR-mode. Starting in WR mode"); ++ } else { ++ teamd_log_info("WR-mode. Starting in normal mode. The LAG interface was down before restart"); ++ } ++ ctx->warm_start_mode = lacp->wr.carrier_up; ++ lacp->carrier_up = lacp->wr.carrier_up; ++ lacp->warm_start_mode_timer = 0; ++ } ++ ++ err = team_carrier_set(ctx->th, lacp->carrier_up); + if (err && err != -EOPNOTSUPP) { +- teamd_log_err("Failed to set carrier down."); ++ teamd_log_err("Failed to set carrier"); + return err; + } + +- lacp->carrier_up = false; +- + return 0; + } + +@@ -1951,6 +2344,12 @@ static int lacp_init(struct teamd_context *ctx, void *priv) + } + + lacp->ctx = ctx; ++ if (ctx->warm_start_mode) { ++ err = lacp_state_load(ctx, lacp); ++ if (err) ++ stop_wr_mode(lacp); ++ } ++ + err = teamd_hash_func_set(ctx); + if (err) + return err; +@@ -1992,10 +2391,13 @@ static void lacp_fini(struct teamd_context *ctx, void *priv) + { + struct lacp *lacp = priv; + ++ if (ctx->lacp_directory) ++ lacp_state_save(ctx, lacp); + teamd_state_val_unregister(ctx, &lacp_state_vg, lacp); + teamd_balancer_fini(lacp->tb); + teamd_event_watch_unregister(ctx, &lacp_event_watch_ops, lacp); +- lacp_carrier_fini(ctx, lacp); ++ if (!ctx->keep_ports) ++ lacp_carrier_fini(ctx, lacp); + } + + const struct teamd_runner teamd_runner_lacp = { +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/0009-Fix-ifinfo_link_with_port-race-condition-with-newlink.patch b/src/libteam/patch/0009-Fix-ifinfo_link_with_port-race-condition-with-newlink.patch new file mode 100644 index 000000000000..e2193345f576 --- /dev/null +++ b/src/libteam/patch/0009-Fix-ifinfo_link_with_port-race-condition-with-newlink.patch @@ -0,0 +1,43 @@ +From a678d9087b05aaf6947e15f0cc9a93ace299466f Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 3 Mar 2020 13:14:13 -0800 +Subject: [PATCH] Fix ifinfo_link_with_port race condition with newlink + +The race condition could happen like this: +When an interface is enslaved into the port channel immediately after +it is created, the order of creating the ifinfo and linking the ifinfo to +the port is not guaranteed. + +The team handler will listen to both netlink message to track new links +get created to allocate the ifinfo and add the ifinfo into its linked list, +and the team port change message to link the new port with ifinfo found +in its linkedin list. However, when the ifinfo is not yet created, the error +message "Failed to link port with ifinfo" is thrown with member port failed +to be added into the team handler's port list. + +This fix adds a condition to check if ifinfo_link_with_port is linking ifinfo +to a port or to the team interface itself. If it is a port, ifinfo_find_create +function is used to fix the race condition. +--- + libteam/ifinfo.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/libteam/ifinfo.c b/libteam/ifinfo.c +index b86d34c..e48193e 100644 +--- a/libteam/ifinfo.c ++++ b/libteam/ifinfo.c +@@ -451,7 +451,10 @@ int ifinfo_link_with_port(struct team_handle *th, uint32_t ifindex, + { + struct team_ifinfo *ifinfo; + +- ifinfo = ifinfo_find(th, ifindex); ++ if (port) ++ ifinfo = ifinfo_find_create(th, ifindex); ++ else ++ ifinfo = ifinfo_find(th, ifindex); + if (!ifinfo) + return -ENOENT; + if (ifinfo->linked) +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/0010-When-read-of-timerfd-returned-0-don-t-consider-this-.patch b/src/libteam/patch/0010-When-read-of-timerfd-returned-0-don-t-consider-this-.patch new file mode 100644 index 000000000000..37eb10d20d49 --- /dev/null +++ b/src/libteam/patch/0010-When-read-of-timerfd-returned-0-don-t-consider-this-.patch @@ -0,0 +1,39 @@ +From e6cd756eac31e3818afb32662469ddf7797c71df Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 3 Mar 2020 13:19:28 -0800 +Subject: [PATCH] When read of timerfd returned 0, don't consider this an error + +Just skip this event. +--- + teamd/teamd.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/teamd/teamd.c b/teamd/teamd.c +index 221d71d..530302b 100644 +--- a/teamd/teamd.c ++++ b/teamd/teamd.c +@@ -285,6 +285,10 @@ static int handle_period_fd(int fd) + teamd_log_err("read() failed."); + return -errno; + } ++ if (ret == 0) { ++ teamd_log_warn("read() for timer_fd returned 0."); ++ return 1; ++ } + if (ret != sizeof(uint64_t)) { + teamd_log_err("read() returned unexpected number of bytes."); + return -EINVAL; +@@ -345,7 +349,9 @@ static int teamd_run_loop_do_callbacks(struct list_item *lcb_list, fd_set *fds, + continue; + if (lcb->is_period) { + err = handle_period_fd(lcb->fd); +- if (err) ++ if (err == 1) ++ continue; /* timerfd returned 0. Don't do anything */ ++ if (err < 0) + return err; + } + err = lcb->func(ctx, events, lcb->priv); +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/0011-Remove-extensive-debug-output.patch b/src/libteam/patch/0011-Remove-extensive-debug-output.patch new file mode 100644 index 000000000000..429ac56697d5 --- /dev/null +++ b/src/libteam/patch/0011-Remove-extensive-debug-output.patch @@ -0,0 +1,25 @@ +From 19928173ce022f499c59b719179e7ad9a4bafb7f Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Mon, 9 Nov 2020 13:21:55 -0800 +Subject: [PATCH] Remove extensive debug output + +--- + libteamdctl/cli_usock.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libteamdctl/cli_usock.c b/libteamdctl/cli_usock.c +index 0dc97ae..d3fbdba 100644 +--- a/libteamdctl/cli_usock.c ++++ b/libteamdctl/cli_usock.c +@@ -163,7 +163,7 @@ static int cli_usock_method_call(struct teamdctl *tdc, const char *method_name, + char *replystr; + int err; + +- dbg(tdc, "usock: Calling method \"%s\"", method_name); ++ /* dbg(tdc, "usock: Calling method \"%s\"", method_name); */ + err= myasprintf(&msg, "%s\n%s\n", TEAMD_USOCK_REQUEST_PREFIX, + method_name); + if (err) +-- +2.29.2.windows.2 + diff --git a/src/libteam/patch/series b/src/libteam/patch/series new file mode 100644 index 000000000000..5350d37e4653 --- /dev/null +++ b/src/libteam/patch/series @@ -0,0 +1,11 @@ +0001-libteam-Temporarily-remove-redundant-debug-messages.patch +0002-teamd-lacp-runner-will-send-lacp-update-right-after-.patch +0003-libteam-Add-fallback-support-for-single-member-port-.patch +0004-Skip-setting-the-same-hwaddr-to-lag-port-to-avoid-di.patch +0005-Increase-default-buffer-size-from-98304-to-983040.patch +0006-teamd-Administratively-shutdown-port-channel-has-mem.patch +0007-Send-LACP-PDU-immediately-if-our-state-changed.patch +0008-libteam-Add-warm_reboot-mode.patch +0009-Fix-ifinfo_link_with_port-race-condition-with-newlink.patch +0010-When-read-of-timerfd-returned-0-don-t-consider-this-.patch +0011-Remove-extensive-debug-output.patch diff --git a/src/libyang/.gitignore b/src/libyang/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/libyang/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/libyang/Makefile b/src/libyang/Makefile new file mode 100644 index 000000000000..32cabdf13bdf --- /dev/null +++ b/src/libyang/Makefile @@ -0,0 +1,28 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(LIBYANG) +DERIVED_TARGETS = $(LIBYANG_DEV) $(LIBYANG_DBG) $(LIBYANG_PY2) $(LIBYANG_PY3) $(LIBYANG_CPP) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtaining the libyang + rm -fr ./libyang-$(LIBYANG_VERSION) + git clone https://github.com/CESNET/libyang.git libyang-$(LIBYANG_VERSION) + pushd libyang-$(LIBYANG_VERSION) + git checkout tags/v1.0-r4 -b libyang + # Apply patch series + stg init + stg import -s ../patch/series + + mkdir build + pushd build + cmake .. + make build-deb + + pushd debs + mv $* $(DEST)/ + mv $(DERIVED_TARGETS) $(DEST)/ + popd + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/libyang/patch/large_file_support_arm32.patch b/src/libyang/patch/large_file_support_arm32.patch new file mode 100644 index 000000000000..e3fb2b739055 --- /dev/null +++ b/src/libyang/patch/large_file_support_arm32.patch @@ -0,0 +1,11 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 8635ba1..39f0741 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -436,3 +436,6 @@ endif(ENABLE_BUILD_FUZZ_TARGETS) + if(GEN_LANGUAGE_BINDINGS AND GEN_CPP_BINDINGS) + add_subdirectory(swig) + endif() ++ ++#Enable large file support for 32-bit arch ++add_definitions(-D_FILE_OFFSET_BITS=64) diff --git a/src/libyang/patch/libyang.patch b/src/libyang/patch/libyang.patch new file mode 100644 index 000000000000..a950d85086ab --- /dev/null +++ b/src/libyang/patch/libyang.patch @@ -0,0 +1,134 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index fa562dd3..8635ba15 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -33,6 +33,7 @@ set(LIBYANG_MICRO_SOVERSION 2) + set(LIBYANG_SOVERSION_FULL ${LIBYANG_MAJOR_SOVERSION}.${LIBYANG_MINOR_SOVERSION}.${LIBYANG_MICRO_SOVERSION}) + set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_SOVERSION}) + ++set(CMAKE_INSTALL_PREFIX /usr) + # set default build type if not specified by user + if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE debug) +diff --git a/packages/debian.control.in b/packages/debian.control.in +index da6588b9..fb3ede48 100644 +--- a/packages/debian.control.in ++++ b/packages/debian.control.in +@@ -53,3 +53,15 @@ Depends: python3-yang@PACKAGE_PART_NAME@ (=@LIBYANG_VERSION@) + Section: debug + Architecture: any + Description: Debug symbols of python3 bidings of libyang library. ++ ++Package: python2-yang@PACKAGE_PART_NAME@ ++Depends: @PACKAGE_NAME@ (=@LIBYANG_VERSION@), libyang-cpp@PACKAGE_PART_NAME@ (=@LIBYANG_VERSION@) ++Section: libs ++Architecture: any ++Description: Bindings of libyang library to python2 language. ++ ++Package: python2-yang@PACKAGE_PART_NAME@-dbg ++Depends: python2-yang@PACKAGE_PART_NAME@ (=@LIBYANG_VERSION@) ++Section: debug ++Architecture: any ++Description: Debug symbols of python2 bidings of libyang library. +diff --git a/packages/debian.python2-yang.install b/packages/debian.python2-yang.install +new file mode 100644 +index 00000000..14ce2f3c +--- /dev/null ++++ b/packages/debian.python2-yang.install +@@ -0,0 +1 @@ ++usr/lib/python2.7/dist-packages/* +diff --git a/packages/debian.rules.in b/packages/debian.rules.in +index d565819e..e92fe4a1 100644 +--- a/packages/debian.rules.in ++++ b/packages/debian.rules.in +@@ -9,10 +9,14 @@ export DH_VERBOSE=1 + override_dh_strip: + dh_strip -plibyang@PACKAGE_PART_NAME@ --dbg-package=libyang@PACKAGE_PART_NAME@-dbg + dh_strip -plibyang-cpp@PACKAGE_PART_NAME@ --dbg-package=libyang-cpp@PACKAGE_PART_NAME@-dbg ++ dh_strip -ppython2-yang@PACKAGE_PART_NAME@ --dbg-package=python2-yang@PACKAGE_PART_NAME@-dbg + dh_strip -ppython3-yang@PACKAGE_PART_NAME@ --dbg-package=python3-yang@PACKAGE_PART_NAME@-dbg + + override_dh_auto_configure: +- cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_BUILD_TYPE:String="@BUILD_TYPE@" -DGEN_LANGUAGE_BINDINGS=ON . ++ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_BUILD_TYPE:String="@BUILD_TYPE@" -DENABLE_LYD_PRIV=ON -DGEN_LANGUAGE_BINDINGS=ON -DGEN_PYTHON_VERSION=2 . ++ ++override_dh_makeshlibs: ++ dh_makeshlibs -Xextensions -Xuser_types + + override_dh_auto_test: + ctest --output-on-failure +diff --git a/packages/libyang.dsc.in b/packages/libyang.dsc.in +index fdfa402b..f75ba184 100644 +--- a/packages/libyang.dsc.in ++++ b/packages/libyang.dsc.in +@@ -1,10 +1,10 @@ + Format: 3.0 (quilt) + Source: @PACKAGE_NAME@ +-Binary: @PACKAGE_NAME@, @PACKAGE_NAME@-dbg, @PACKAGE_NAME@-dev, libyang-cpp@PACKAGE_PART_NAME@, libyang-cpp@PACKAGE_PART_NAME@-dev, libyang-cpp@PACKAGE_PART_NAME@-dbg, python3-yang@PACKAGE_PART_NAME@, python3-yang@PACKAGE_PART_NAME@-dbg ++Binary: @PACKAGE_NAME@, @PACKAGE_NAME@-dbg, @PACKAGE_NAME@-dev, libyang-cpp@PACKAGE_PART_NAME@, libyang-cpp@PACKAGE_PART_NAME@-dev, libyang-cpp@PACKAGE_PART_NAME@-dbg, python3-yang@PACKAGE_PART_NAME@, python3-yang@PACKAGE_PART_NAME@-dbg python2-yang@PACKAGE_PART_NAME@, python2-yang@PACKAGE_PART_NAME@-dbg + Maintainer: CESNET + Version: @LIBYANG_VERSION@ + Architecture: any + Standards-Version: 3.8.2 + Homepage: https://github.com/CESNET/libyang + Vcs-Git: https://github.com/CESNET/libyang +-Build-Depends: debhelper (>= 9), make, gcc, doxygen, cmake, pkg-config, libpcre3-dev, libcmocka-dev, python3-dev, g++, swig (>= 3.0.12) ++Build-Depends: debhelper (>= 9), make, gcc, doxygen, cmake, pkg-config, libpcre3-dev, libcmocka-dev, python3-dev, python2-dev, g++, swig (>= 3.0.12) +diff --git a/packages/libyang.spec.in b/packages/libyang.spec.in +index 6a4ac615..6939f028 100644 +--- a/packages/libyang.spec.in ++++ b/packages/libyang.spec.in +@@ -46,6 +46,8 @@ BuildRequires: python3-devel + %else + BuildRequires: python34-devel + %endif ++ ++BuildRequires: python2-devel + %endif + + Conflicts: @CONFLICT_PACKAGE_NAME@ = @LIBYANG_MAJOR_VERSION@.@LIBYANG_MINOR_VERSION@ +@@ -70,6 +72,11 @@ Summary: Binding to python + Requires: libyang-cpp@PACKAGE_PART_NAME@ = %{version}-%{release} + Requires: %{name} = %{version}-%{release} + ++%package -n python2-yang@PACKAGE_PART_NAME@ ++Summary: Binding to python ++Requires: libyang-cpp@PACKAGE_PART_NAME@ = %{version}-%{release} ++Requires: %{name} = %{version}-%{release} ++ + %description -n libyang-cpp@PACKAGE_PART_NAME@ + Bindings of libyang library to C++ language. + +@@ -80,6 +87,10 @@ Headers of bindings to c++ language. + Bindings of libyang library to python language. + %endif + ++%description -n python2-yang@PACKAGE_PART_NAME@ ++Bindings of libyang library to python language. ++%endif ++ + %description devel + Headers of libyang library. + +@@ -167,4 +178,9 @@ make DESTDIR=%{buildroot} install + %{_libdir}/python* + %endif + ++%files -n python2-yang@PACKAGE_PART_NAME@ ++%defattr(-,root,root) ++%{_libdir}/python* ++%endif ++ + %changelog +diff --git a/packages/local-deb.sh.in b/packages/local-deb.sh.in +index 057bbc67..4318a49d 100755 +--- a/packages/local-deb.sh.in ++++ b/packages/local-deb.sh.in +@@ -18,6 +18,7 @@ fi + cp "@PROJECT_SOURCE_DIR@/packages/debian.libyang-dev.install" debian/@PACKAGE_NAME@-dev.install + cp "@PROJECT_SOURCE_DIR@/packages/debian.libyang-cpp.install" debian/libyang-cpp@PACKAGE_PART_NAME@.install + cp "@PROJECT_SOURCE_DIR@/packages/debian.libyang-cpp-dev.install" debian/libyang-cpp@PACKAGE_PART_NAME@-dev.install ++cp "@PROJECT_SOURCE_DIR@/packages/debian.python2-yang.install" debian/python2-yang@PACKAGE_PART_NAME@.install + cp "@PROJECT_SOURCE_DIR@/packages/debian.python3-yang.install" debian/python3-yang@PACKAGE_PART_NAME@.install + echo -e "@PACKAGE_NAME@ (@LIBYANG_VERSION@) stable; urgency=low\n" >debian/changelog + git log -10 --pretty=format:' * %s (%aN)%n' 2>/dev/null >>debian/changelog || echo -e " * unknown changes \n" >>debian/changelog diff --git a/src/libyang/patch/libyang_mgmt_framework.patch b/src/libyang/patch/libyang_mgmt_framework.patch new file mode 100644 index 000000000000..03b7ea3476b7 --- /dev/null +++ b/src/libyang/patch/libyang_mgmt_framework.patch @@ -0,0 +1,13 @@ +diff --git a/src/tree_data.c b/src/tree_data.c +index 04653a46..65dca211 100644 +--- a/src/tree_data.c ++++ b/src/tree_data.c +@@ -842,7 +842,7 @@ error: + return ret; + } + +-int ++API int + lyd_check_mandatory_tree(struct lyd_node *root, struct ly_ctx *ctx, const struct lys_module **modules, int mod_count, + int options) + { diff --git a/src/libyang/patch/series b/src/libyang/patch/series new file mode 100644 index 000000000000..28352b9628e5 --- /dev/null +++ b/src/libyang/patch/series @@ -0,0 +1,4 @@ +libyang.patch +libyang_mgmt_framework.patch +swig.patch +large_file_support_arm32.patch diff --git a/src/libyang/patch/swig.patch b/src/libyang/patch/swig.patch new file mode 100644 index 000000000000..a6f798c18224 --- /dev/null +++ b/src/libyang/patch/swig.patch @@ -0,0 +1,136 @@ +diff --git a/swig/CMakeLists.txt b/swig/CMakeLists.txt +index 4cee36ec..0baa69ab 100644 +--- a/swig/CMakeLists.txt ++++ b/swig/CMakeLists.txt +@@ -20,27 +20,34 @@ endif() + + # find Python package + if(GEN_PYTHON_BINDINGS AND SWIG_FOUND) +- message(STATUS "Python version ${GEN_PYTHON_VERSION} was selected") +- unset(PYTHON_LIBRARY CACHE) +- unset(PYTHON_EXECUTABLE CACHE) +- unset(PYTHON_INCLUDE_DIR CACHE) +- unset(PYTHON_LIBRARY_DEBUG CACHE) +- if(${GEN_PYTHON_VERSION} STREQUAL "2") +- find_package(PythonLibs 2 REQUIRED) +- find_package(PythonInterp 2 REQUIRED) +- if(NOT PYTHONLIBS_FOUND) +- message(WARNING "Did not found Python version 2.x") +- message(STATUS "Sysrepo supports Python 2.x and Python 3.x") +- endif() +- elseif(${GEN_PYTHON_VERSION} STREQUAL "3") +- find_package(PythonLibs 3 REQUIRED) +- find_package(PythonInterp 3 REQUIRED) +- if(NOT PYTHONLIBS_FOUND) +- message(WARNING "Did not found Python version 3.x") +- message(STATUS "Sysrepo supports Python 2.x and Python 3.x") +- endif() ++ if(ENABLE_STATIC) ++ message(WARNING "Can't create a static Python module") + else() +- message(WARNING "Sysrepo supports Python 2.x and Python 3.x") ++ set(GEN_PYTHON_VERSION 2 3) ++ foreach(CUR_PYTHON_VERSION ${GEN_PYTHON_VERSION}) ++ message(STATUS "Python version ${CUR_PYTHON_VERSION} was selected") ++ ++ unset(PYTHON_EXECUTABLE CACHE) ++ unset(PYTHON_INCLUDE_PATH CACHE) ++ unset(PYTHON_EXT_SUFFIX CACHE) ++ unset(PYTHON_MODULE_PATH CACHE) ++ set(PYTHON_EXT_SUFFIX ".so") ++ ++ find_program(PYTHON_EXECUTABLE NAMES python${CUR_PYTHON_VERSION}) ++ execute_process(COMMAND ${PYTHON_EXECUTABLE} -c ++ "from distutils.sysconfig import get_config_var; print(get_config_var('INCLUDEPY'))" ++ OUTPUT_VARIABLE PYTHON_INCLUDE_PATH ++ OUTPUT_STRIP_TRAILING_WHITESPACE ) ++ #execute_process(COMMAND ${PYTHON_EXECUTABLE} -c ++ # "from distutils.sysconfig import get_config_var; print(get_config_var('EXT_SUFFIX'))" ++ # OUTPUT_VARIABLE PYTHON_EXT_SUFFIX ++ # OUTPUT_STRIP_TRAILING_WHITESPACE ) ++ execute_process(COMMAND ${PYTHON_EXECUTABLE} -c ++ "from distutils.sysconfig import get_python_lib; print(get_python_lib(plat_specific=True))" ++ OUTPUT_VARIABLE PYTHON_MODULE_PATH ++ OUTPUT_STRIP_TRAILING_WHITESPACE ) ++ add_subdirectory(python python${CUR_PYTHON_VERSION}) ++ endforeach(CUR_PYTHON_VERSION) + endif() + endif() + +@@ -99,12 +106,6 @@ if (GEN_CPP_BINDINGS) + endif() + endif() + +-if(ENABLE_STATIC AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND AND (${GEN_PYTHON_VERSION} STREQUAL "2" OR ${GEN_PYTHON_VERSION} STREQUAL "3")) +- message(WARNING "Can't create a static Python module") +-elseif(PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND AND (${GEN_PYTHON_VERSION} STREQUAL "2" OR ${GEN_PYTHON_VERSION} STREQUAL "3")) +- add_subdirectory(python) +-endif() +- + if(NOT ENABLE_STATIC AND GEN_JAVASCRIPT_BINDINGS) + message(WARNING "Can't create Javascript bindings with a shared library, please use -DENABLE_STATIC") + elseif(ENABLE_STATIC AND GEN_JAVASCRIPT_BINDINGS) +diff --git a/swig/python/CMakeLists.txt b/swig/python/CMakeLists.txt +index 994b1234..5d18b8bf 100644 +--- a/swig/python/CMakeLists.txt ++++ b/swig/python/CMakeLists.txt +@@ -1,30 +1,38 @@ + set(PYTHON_SWIG_BINDING yang) ++set(PYTHON_SWIG_TARGET yang${CUR_PYTHON_VERSION}) + include_directories(${PYTHON_INCLUDE_PATH}) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) ++include_directories(${PROJECT_SOURCE_DIR}/cpp/src) + + set(CMAKE_SWIG_FLAGS "-c++") +-set(CMAKE_SWIG_FLAGS "-I${PROJECT_SOURCE_DIR}") ++set(CMAKE_SWIG_FLAGS "-I${PROJECT_SOURCE_DIR}" "-I${PROJECT_SOURCE_DIR}/cpp/src") + set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}) + +-set_source_files_properties(${PYTHON_SWIG_BINDING}.i PROPERTIES CPLUSPLUS ON PREFIX "") ++set_source_files_properties(${PYTHON_SWIG_BINDING}.i PROPERTIES CPLUSPLUS ON PREFIX "" SWIG_MODULE_NAME ${PYTHON_SWIG_BINDING}) + + if(${CMAKE_VERSION} VERSION_LESS "3.8.0") +- swig_add_module(${PYTHON_SWIG_BINDING} python ${PYTHON_SWIG_BINDING}.i) ++ swig_add_module(${PYTHON_SWIG_TARGET} python ${PYTHON_SWIG_BINDING}.i) + else() +- swig_add_library(${PYTHON_SWIG_BINDING} LANGUAGE python SOURCES ${PYTHON_SWIG_BINDING}.i) ++ swig_add_library(${PYTHON_SWIG_TARGET} LANGUAGE python SOURCES ${PYTHON_SWIG_BINDING}.i) + endif() +-swig_link_libraries(${PYTHON_SWIG_BINDING} ${PYTHON_LIBRARIES} libyang-cpp) ++swig_link_libraries(${PYTHON_SWIG_TARGET} ${PYTHON_LIBRARIES} libyang-cpp) ++ ++set_target_properties(_${PYTHON_SWIG_TARGET} PROPERTIES OUTPUT_NAME "_yang${PYTHON_EXT_SUFFIX}" SUFFIX "") + + # Generate header with SWIG run-time functions + execute_process(COMMAND ${SWIG_EXECUTABLE} -python -external-runtime ${CMAKE_CURRENT_BINARY_DIR}/swigpyrun.h) + +-file(COPY "examples" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) ++add_custom_command(TARGET ${PYTHON_SWIG_TARGET}_swig_compilation POST_BUILD ++ COMMAND sed -e "'s/\\(inst =.*tp_new.*\\)Py_None, Py_None);/PyObject *tup = PyTuple_New(0); \\1tup, Py_None); Py_DECREF(tup);/'" < swigpyrun.h > swigpyrun.h.new ++ COMMAND sed -e "'s/\\(inst =.*tp_new.*\\)Py_None, Py_None);/PyObject *tup = PyTuple_New(0); \\1tup, Py_None); Py_DECREF(tup);/'" < yangPYTHON_wrap.cxx > yangPYTHON_wrap.cxx.new ++ COMMAND diff -q swigpyrun.h swigpyrun.h.new || mv swigpyrun.h.new swigpyrun.h ++ COMMAND diff -q yangPYTHON_wrap.cxx yangPYTHON_wrap.cxx.new || mv yangPYTHON_wrap.cxx.new yangPYTHON_wrap.cxx ++ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ++ ) + +-execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(plat_specific=True))" +- OUTPUT_VARIABLE PYTHON_MODULE_PATH +- OUTPUT_STRIP_TRAILING_WHITESPACE ) ++file(COPY "examples" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +-install( TARGETS _${PYTHON_SWIG_BINDING} DESTINATION ${PYTHON_MODULE_PATH}) ++install( TARGETS _${PYTHON_SWIG_TARGET} DESTINATION ${PYTHON_MODULE_PATH}) + install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PYTHON_SWIG_BINDING}.py" DESTINATION ${PYTHON_MODULE_PATH}) + install( FILES "${CMAKE_CURRENT_BINARY_DIR}/swigpyrun.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libyang) + +@@ -51,8 +59,8 @@ if(ENABLE_BUILD_TESTS) + ADD_PYTHON_TEST(test_tree_data) + ADD_PYTHON_TEST(test_tree_schema) + +- add_custom_command(TARGET ${SWIG_MODULE_${PYTHON_SWIG_BINDING}_REAL_NAME} POST_BUILD +- COMMAND cp "${CMAKE_CURRENT_BINARY_DIR}/_${PYTHON_SWIG_BINDING}.so" ${PY2_SWIG_DIR}/tests ++ add_custom_command(TARGET ${SWIG_MODULE_${PYTHON_SWIG_TARGET}_REAL_NAME} POST_BUILD ++ COMMAND cp "${CMAKE_CURRENT_BINARY_DIR}/_yang${PYTHON_EXT_SUFFIX}" ${PY2_SWIG_DIR}/tests/_yang.so + COMMAND cp "${CMAKE_CURRENT_BINARY_DIR}/${PYTHON_SWIG_BINDING}.py" ${PY2_SWIG_DIR}/tests + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) diff --git a/src/libyang1/.gitignore b/src/libyang1/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/libyang1/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/libyang1/Makefile b/src/libyang1/Makefile new file mode 100644 index 000000000000..834893eb0bbe --- /dev/null +++ b/src/libyang1/Makefile @@ -0,0 +1,40 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +LIBYANG_URL = https://sonicstorage.blob.core.windows.net/debian/pool/main/liby/libyang + +DSC_FILE = libyang_$(LIBYANG1_FULLVERSION).dsc +ORIG_FILE = libyang_$(LIBYANG1_VERSION).orig.tar.gz +DEBIAN_FILE = libyang_$(LIBYANG1_FULLVERSION).debian.tar.xz + +DSC_FILE_URL = $(LIBYANG_URL)/$(DSC_FILE) +ORIG_FILE_URL = $(LIBYANG_URL)/$(ORIG_FILE) +DEBIAN_FILE_URL = $(LIBYANG_URL)/$(DEBIAN_FILE) + +MAIN_TARGET = $(LIBYANG1) +DERIVED_TARGETS = $(LIBYANG1_DEV) $(LIBYANG1_DBG) $(LIBYANG1_CPP) $(LIBYANG1_CPP_DEV) $(LIBYANG1_CPP_DBG) $(YANG_TOOLS) $(LIBYANG1_TOOLS) $(LIBYANG1_TOOLS_DBG) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtaining the libyang + rm -fr ./libyang-$(LIBYANG1_VERSION) + + # download debian libyang + wget -NO "$(DSC_FILE)" $(DSC_FILE_URL) + wget -NO "$(ORIG_FILE)" $(ORIG_FILE_URL) + wget -NO "$(DEBIAN_FILE)" $(DEBIAN_FILE_URL) + dpkg-source -x libyang_$(LIBYANG1_FULLVERSION).dsc + + pushd libyang-$(LIBYANG1_VERSION) + sed -i 's/set(LIBYANG_MAJOR_SOVERSION 1)/set(LIBYANG_MAJOR_SOVERSION 2)/' CMakeLists.txt + sed -i 's/libyang1/libyang2/' debian/libyang1.install + # Enable large file support for 32-bit arch + echo 'add_definitions(-D_FILE_OFFSET_BITS=64)' >> CMakeLists.txt + + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + # Move the newly-built .deb packages to the destination directory + mv $* $(DERIVED_TARGETS) $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/lldpd/.gitignore b/src/lldpd/.gitignore new file mode 100644 index 000000000000..d19db76ab9a9 --- /dev/null +++ b/src/lldpd/.gitignore @@ -0,0 +1,4 @@ +* +!.gitignore +!Makefile +!patch/ diff --git a/src/lldpd/Makefile b/src/lldpd/Makefile new file mode 100644 index 000000000000..a336f1e989ae --- /dev/null +++ b/src/lldpd/Makefile @@ -0,0 +1,44 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(LLDPD) +DERIVED_TARGETS = $(LIBLLDPCTL) $(LLDPD_DBG) + +LLDP_URL = https://sonicstorage.blob.core.windows.net/debian/pool/main/l/lldpd + +DSC_FILE = lldpd_$(LLDPD_VERSION_FULL).dsc +ORIG_FILE = lldpd_$(LLDPD_VERSION).orig.tar.gz +DEBIAN_FILE = lldpd_$(LLDPD_VERSION_FULL).debian.tar.xz + +DSC_FILE_URL = $(LLDP_URL)/$(DSC_FILE) +ORIG_FILE_URL = $(LLDP_URL)/$(ORIG_FILE) +DEBIAN_FILE_URL = $(LLDP_URL)/$(DEBIAN_FILE) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf lldpd-$(LLDPD_VERSION) + + # download debian LLDPDD + wget -NO "$(DSC_FILE)" $(DSC_FILE_URL) + wget -NO "$(ORIG_FILE)" $(ORIG_FILE_URL) + wget -NO "$(DEBIAN_FILE)" $(DEBIAN_FILE_URL) + dpkg-source -x lldpd_$(LLDPD_VERSION_FULL).dsc + + pushd lldpd-$(LLDPD_VERSION) + git init + git add -f * + git commit -m "unmodified lldp source" + + # Apply patches + stg init + stg import -s ../patch/series + + # Build source and Debian packages + env "with_netlink_receive_bufsize=1024*1024" dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + # Move the newly-built .deb packages to the destination directory + mv $* $(DERIVED_TARGETS) $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/lldpd/patch/0001-return-error-when-port-does-not-exist.patch b/src/lldpd/patch/0001-return-error-when-port-does-not-exist.patch new file mode 100644 index 000000000000..e17d09a386d4 --- /dev/null +++ b/src/lldpd/patch/0001-return-error-when-port-does-not-exist.patch @@ -0,0 +1,39 @@ +From 15e692fb82a61203624829cdd872315211920077 Mon Sep 17 00:00:00 2001 +From: Guohan Lu +Date: Tue, 6 Mar 2018 09:36:51 +0000 +Subject: [PATCH] return error when port does not exist + +--- + src/client/conf-lldp.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/client/conf-lldp.c b/src/client/conf-lldp.c +index c16219b..b51e4eb 100644 +--- a/src/client/conf-lldp.c ++++ b/src/client/conf-lldp.c +@@ -148,6 +148,8 @@ cmd_portid_type_local(struct lldpctl_conn_t *conn, struct writer *w, + const char *name; + const char *id = cmdenv_get(env, "port-id"); + const char *descr = cmdenv_get(env, "port-descr"); ++ const char *portname = cmdenv_get(env, "ports"); ++ int find_port = 0; + + log_debug("lldpctl", "lldp PortID TLV Subtype Local port-id '%s' port-descr '%s'", id, descr); + +@@ -165,6 +167,12 @@ cmd_portid_type_local(struct lldpctl_conn_t *conn, struct writer *w, + log_warnx("lldpctl", "unable to set LLDP Port Description for %s." + " %s", name, lldpctl_last_strerror(conn)); + } ++ find_port = 1; ++ } ++ ++ if (!find_port) { ++ log_warnx("lldpctl", "cannot find port %s", portname); ++ return 0; + } + + return 1; +-- +2.7.4 + + diff --git a/src/lldpd/patch/0004-lldpctl-put-a-lock-around-some-commands-to-avoid-rac.patch b/src/lldpd/patch/0004-lldpctl-put-a-lock-around-some-commands-to-avoid-rac.patch new file mode 100644 index 000000000000..df7f26131dd4 --- /dev/null +++ b/src/lldpd/patch/0004-lldpctl-put-a-lock-around-some-commands-to-avoid-rac.patch @@ -0,0 +1,169 @@ +From 46aa45d0fa3e8879ecdca1c156cb2d91194c45e9 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Thu, 12 Dec 2019 13:47:17 -0800 +Subject: [PATCH 1/1] lldpctl: put a lock around some commands to avoid race + conditions + +--- + src/client/client.h | 3 +++ + src/client/commands.c | 58 ++++++++++++++++++++++++++++++++++++++++--- + src/client/conf.c | 4 +-- + 3 files changed, 60 insertions(+), 5 deletions(-) + +diff --git a/src/client/client.h b/src/client/client.h +index e3ee352..6c3e30d 100644 +--- a/src/client/client.h ++++ b/src/client/client.h +@@ -62,6 +62,8 @@ extern void add_history (); + #endif + #undef NEWLINE + ++extern const char *ctlname; ++ + /* commands.c */ + #define NEWLINE "" + struct cmd_node; +@@ -76,6 +78,7 @@ struct cmd_node *commands_new( + struct cmd_env*, void *), + void *); + struct cmd_node* commands_privileged(struct cmd_node *); ++struct cmd_node* commands_lock(struct cmd_node *); + struct cmd_node* commands_hidden(struct cmd_node *); + void commands_free(struct cmd_node *); + const char *cmdenv_arg(struct cmd_env*); +diff --git a/src/client/commands.c b/src/client/commands.c +index beedbf1..58df4a7 100644 +--- a/src/client/commands.c ++++ b/src/client/commands.c +@@ -18,6 +18,9 @@ + #include "client.h" + #include + #include ++#include ++#include ++#include + + /** + * An element of the environment (a key and a value). +@@ -68,6 +71,7 @@ struct cmd_node { + const char *token; /**< Token to enter this cnode */ + const char *doc; /**< Documentation string */ + int privileged; /**< Privileged command? */ ++ int lock; /**< Lock required for execution? */ + int hidden; /**< Hidden command? */ + + /** +@@ -113,6 +117,21 @@ commands_privileged(struct cmd_node *node) + return node; + } + ++/** ++ * Make a node accessible only with a lock. ++ * ++ * @param node node to use lock to execute ++ * @return the modified node ++ * ++ * The node is modified. It is returned to ease chaining. ++ */ ++struct cmd_node* ++commands_lock(struct cmd_node *node) ++{ ++ if (node) node->lock = 1; ++ return node; ++} ++ + /** + * Hide a node from help or completion. + * +@@ -344,6 +363,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w, + int n, rc = 0, completion = (word != NULL); + int help = 0; /* Are we asking for help? */ + int complete = 0; /* Are we asking for possible completions? */ ++ int needlock = 0; /* Do we need a lock? */ + struct cmd_env env = { + .elements = TAILQ_HEAD_INITIALIZER(env.elements), + .stack = TAILQ_HEAD_INITIALIZER(env.stack), +@@ -351,6 +371,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w, + .argv = argv, + .argp = 0 + }; ++ static int lockfd = -1; + cmdenv_push(&env, root); + if (!completion) + for (n = 0; n < argc; n++) +@@ -388,6 +409,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w, + !strcmp(candidate->token, token)) { + /* Exact match */ + best = candidate; ++ needlock = needlock || candidate->lock; + break; + } + if (!best) best = candidate; +@@ -406,6 +428,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w, + if (!candidate->token && + CAN_EXECUTE(candidate)) { + best = candidate; ++ needlock = needlock || candidate->lock; + break; + } + } +@@ -421,9 +444,38 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w, + + /* Push and execute */ + cmdenv_push(&env, best); +- if (best->execute && best->execute(conn, w, &env, best->arg) != 1) { +- rc = -1; +- goto end; ++ if (best->execute) { ++ struct sockaddr_un su; ++ if (needlock) { ++ if (lockfd == -1) { ++ log_debug("lldpctl", "reopen %s for locking", ctlname); ++ if ((lockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { ++ log_warn("lldpctl", "cannot open for lock %s", ctlname); ++ rc = -1; ++ goto end; ++ } ++ su.sun_family = AF_UNIX; ++ strlcpy(su.sun_path, ctlname, sizeof(su.sun_path)); ++ if (connect(lockfd, (struct sockaddr *)&su, sizeof(struct sockaddr_un)) == -1) { ++ log_warn("lldpctl", "cannot connect to socket %s", ctlname); ++ rc = -1; ++ close(lockfd); lockfd = -1; ++ goto end; ++ } ++ } ++ if (lockf(lockfd, F_LOCK, 0) == -1) { ++ log_warn("lldpctl", "cannot get lock on %s", ctlname); ++ rc = -1; ++ close(lockfd); lockfd = -1; ++ goto end; ++ } ++ } ++ rc = best->execute(conn, w, &env, best->arg) != 1 ? -1 : rc; ++ if (needlock && lockf(lockfd, F_ULOCK, 0) == -1) { ++ log_warn("lldpctl", "cannot unlock %s", ctlname); ++ close(lockfd); lockfd = -1; ++ } ++ if (rc == -1) goto end; + } + env.argp++; + } +diff --git a/src/client/conf.c b/src/client/conf.c +index 1a14981..ba5743f 100644 +--- a/src/client/conf.c ++++ b/src/client/conf.c +@@ -37,8 +37,8 @@ register_commands_configure(struct cmd_node *root) + "unconfigure", + "Unconfigure system settings", + NULL, NULL, NULL); +- commands_privileged(configure); +- commands_privileged(unconfigure); ++ commands_privileged(commands_lock(configure)); ++ commands_privileged(commands_lock(unconfigure)); + cmd_restrict_ports(configure); + cmd_restrict_ports(unconfigure); + +-- +2.17.1.windows.2 + diff --git a/src/lldpd/patch/0006-lib-fix-memory-leak.patch b/src/lldpd/patch/0006-lib-fix-memory-leak.patch new file mode 100644 index 000000000000..765b5fb751e7 --- /dev/null +++ b/src/lldpd/patch/0006-lib-fix-memory-leak.patch @@ -0,0 +1,24 @@ +From 833653dffb9be40110142af2a7cb4076a0dd24f5 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Thu, 12 Dec 2019 12:48:47 -0800 +Subject: [PATCH 1/1] lib: fix memory leak + +--- + src/lib/connection.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/lib/connection.c b/src/lib/connection.c +index 88bbc99..aa88dad 100644 +--- a/src/lib/connection.c ++++ b/src/lib/connection.c +@@ -114,6 +114,7 @@ lldpctl_new_name(const char *ctlname, lldpctl_send_callback send, lldpctl_recv_c + } + if (!send && !recv) { + if ((data = malloc(sizeof(struct lldpctl_conn_sync_t))) == NULL) { ++ free(conn->ctlname); + free(conn); + return NULL; + } +-- +2.17.1.windows.2 + diff --git a/src/lldpd/patch/0007-lib-fix-memory-leak-when-handling-I-O.patch b/src/lldpd/patch/0007-lib-fix-memory-leak-when-handling-I-O.patch new file mode 100644 index 000000000000..cad8bf2fd48a --- /dev/null +++ b/src/lldpd/patch/0007-lib-fix-memory-leak-when-handling-I-O.patch @@ -0,0 +1,85 @@ +From f6086575e63b5e089814ca116aa637d7588bfcd3 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Thu, 12 Dec 2019 13:52:42 -0800 +Subject: [PATCH 1/1] lib: fix memory leak when handling I/O. + +--- + src/lib/atom.c | 11 ++++++----- + src/lib/atom.h | 9 ++++----- + src/lib/atoms/port.c | 2 +- + 3 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/src/lib/atom.c b/src/lib/atom.c +index 955f434..f81d3bb 100644 +--- a/src/lib/atom.c ++++ b/src/lib/atom.c +@@ -322,10 +322,12 @@ _lldpctl_do_something(lldpctl_conn_t *conn, + return SET_ERROR(conn, LLDPCTL_ERR_SERIALIZATION); + conn->state = state_send; + if (state_data) +- conn->state_data = strdup(state_data); ++ strlcpy(conn->state_data, state_data, sizeof(conn->state_data)); ++ else ++ conn->state_data[0] = 0; + } + if (conn->state == state_send && +- (state_data == NULL || !strcmp(conn->state_data, state_data))) { ++ (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data)))) { + /* We need to send the currently built message */ + rc = lldpctl_send(conn); + if (rc < 0) +@@ -333,7 +335,7 @@ _lldpctl_do_something(lldpctl_conn_t *conn, + conn->state = state_recv; + } + if (conn->state == state_recv && +- (state_data == NULL || !strcmp(conn->state_data, state_data))) { ++ (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data)))) { + /* We need to receive the answer */ + while ((rc = ctl_msg_recv_unserialized(&conn->input_buffer, + &conn->input_buffer_len, +@@ -347,8 +349,7 @@ _lldpctl_do_something(lldpctl_conn_t *conn, + return SET_ERROR(conn, LLDPCTL_ERR_SERIALIZATION); + /* rc == 0 */ + conn->state = CONN_STATE_IDLE; +- free(conn->state_data); +- conn->state_data = NULL; ++ conn->state_data[0] = 0; + return 0; + } else + return SET_ERROR(conn, LLDPCTL_ERR_INVALID_STATE); +diff --git a/src/lib/atom.h b/src/lib/atom.h +index 265c0a7..ab7037d 100644 +--- a/src/lib/atom.h ++++ b/src/lib/atom.h +@@ -55,11 +55,10 @@ struct lldpctl_conn_t { + #define CONN_STATE_GET_DEFAULT_PORT_SEND 14 + #define CONN_STATE_GET_DEFAULT_PORT_RECV 15 + int state; /* Current state */ +- char *state_data; /* Data attached to the state. It is used to +- * check that we are using the same data as a +- * previous call until the state machine goes to +- * CONN_STATE_IDLE. */ +- ++ /* Data attached to the state. It is used to check that we are using the ++ * same data as a previous call until the state machine goes to ++ * CONN_STATE_IDLE. */ ++ char state_data[IFNAMSIZ + 64]; + /* Error handling */ + lldpctl_error_t error; /* Last error */ + +diff --git a/src/lib/atoms/port.c b/src/lib/atoms/port.c +index 545155c..d902188 100644 +--- a/src/lib/atoms/port.c ++++ b/src/lib/atoms/port.c +@@ -329,7 +329,7 @@ _lldpctl_atom_set_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key, lldpctl_ato + struct lldpd_hardware *hardware = p->hardware; + struct lldpd_port_set set = {}; + int rc; +- char *canary; ++ char *canary = NULL; + + #ifdef ENABLE_DOT3 + struct _lldpctl_atom_dot3_power_t *dpow; +-- +2.17.1.windows.2 + diff --git a/src/lldpd/patch/0010-Ported-fix-for-length-exceeded-from-lldp-community.patch b/src/lldpd/patch/0010-Ported-fix-for-length-exceeded-from-lldp-community.patch new file mode 100644 index 000000000000..072790641206 --- /dev/null +++ b/src/lldpd/patch/0010-Ported-fix-for-length-exceeded-from-lldp-community.patch @@ -0,0 +1,35 @@ +From fdb789c348fdcde6d5ef8b837d7f33718bc0862b Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Mon, 23 Nov 2020 20:47:28 -0800 +Subject: [PATCH] Ported fix for https://github.com/lldpd/lldpd/issues/408 from + community + +--- + src/lib/atom.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/lib/atom.c b/src/lib/atom.c +index f81d3bb..75c1275 100644 +--- a/src/lib/atom.c ++++ b/src/lib/atom.c +@@ -327,7 +327,7 @@ _lldpctl_do_something(lldpctl_conn_t *conn, + conn->state_data[0] = 0; + } + if (conn->state == state_send && +- (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data)))) { ++ (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data) - 1))) { + /* We need to send the currently built message */ + rc = lldpctl_send(conn); + if (rc < 0) +@@ -335,7 +335,7 @@ _lldpctl_do_something(lldpctl_conn_t *conn, + conn->state = state_recv; + } + if (conn->state == state_recv && +- (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data)))) { ++ (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data) - 1))) { + /* We need to receive the answer */ + while ((rc = ctl_msg_recv_unserialized(&conn->input_buffer, + &conn->input_buffer_len, +-- +2.12.2 + diff --git a/src/lldpd/patch/0011-fix-med-location-len.patch b/src/lldpd/patch/0011-fix-med-location-len.patch new file mode 100644 index 000000000000..2290a94442c1 --- /dev/null +++ b/src/lldpd/patch/0011-fix-med-location-len.patch @@ -0,0 +1,47 @@ +From e9bf329eee94d6d49a17da35aea189179aeed3c6 Mon Sep 17 00:00:00 2001 +From: sudhanshukumar22 +Date: Thu, 24 Dec 2020 09:27:49 -0800 +Subject: [PATCH] From 5c3479463a919193213213e2d8634c754c09aa51 Mon Sep 17 + 00:00:00 2001 From: Vincent Bernat Date: Sun, 6 Dec 2020 + 14:21:04 +0100 Subject: [PATCH] lib: fix LLDP-MED location parsing in + liblldpctl + +Some bounds were not checked correctly when parsing LLDP-MED civic +location fields. This triggers out-of-bound reads (no write) in +lldpcli, ultimately leading to a crash. + +Fix #420 +Signed-off-by: sudhanshukumar22 +--- + src/lib/atoms/med.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/lib/atoms/med.c b/src/lib/atoms/med.c +index e1b20fd..595dba4 100644 +--- a/src/lib/atoms/med.c ++++ b/src/lib/atoms/med.c +@@ -540,6 +540,7 @@ _lldpctl_atom_get_str_med_location(lldpctl_atom_t *atom, lldpctl_key_t key) + return NULL; + case lldpctl_k_med_location_country: + if (m->location->format != LLDP_MED_LOCFORMAT_CIVIC) break; ++ if (m->location->data_len < 4) return NULL; + value = _lldpctl_alloc_in_atom(atom, 3); + if (!value) return NULL; + memcpy(value, m->location->data + 2, 2); +@@ -732,8 +733,11 @@ _lldpctl_atom_iter_med_caelements_list(lldpctl_atom_t *atom) + { + struct _lldpctl_atom_med_caelements_list_t *plist = + (struct _lldpctl_atom_med_caelements_list_t *)atom; +- struct ca_iter *iter = _lldpctl_alloc_in_atom(atom, sizeof(struct ca_iter)); +- if (!iter) return NULL; ++ struct ca_iter *iter; ++ if (plist->parent->location->data_len < 4 || ++ *(uint8_t*)plist->parent->location->data < 3 || ++ !(iter = _lldpctl_alloc_in_atom(atom, sizeof(struct ca_iter)))) ++ return NULL; + iter->data = (uint8_t*)plist->parent->location->data + 4; + iter->data_len = *(uint8_t*)plist->parent->location->data - 3; + return (lldpctl_atom_iter_t*)iter; +-- +2.12.2 + diff --git a/src/lldpd/patch/series b/src/lldpd/patch/series new file mode 100644 index 000000000000..32fd4c0ca9a7 --- /dev/null +++ b/src/lldpd/patch/series @@ -0,0 +1,7 @@ +# This series applies on GIT commit 396961a038a38675d46f96eaa7b430b2a1f8701b +0001-return-error-when-port-does-not-exist.patch +0004-lldpctl-put-a-lock-around-some-commands-to-avoid-rac.patch +0006-lib-fix-memory-leak.patch +0007-lib-fix-memory-leak-when-handling-I-O.patch +0010-Ported-fix-for-length-exceeded-from-lldp-community.patch +0011-fix-med-location-len.patch diff --git a/src/lm-sensors/.gitignore b/src/lm-sensors/.gitignore new file mode 100644 index 000000000000..dfa47d4833b3 --- /dev/null +++ b/src/lm-sensors/.gitignore @@ -0,0 +1,4 @@ +* +!.gitignore +!Makefile +!patch/* diff --git a/src/lm-sensors/Makefile b/src/lm-sensors/Makefile new file mode 100644 index 000000000000..a5aa3ba7d885 --- /dev/null +++ b/src/lm-sensors/Makefile @@ -0,0 +1,33 @@ +SHELL = /bin/bash +.ONESHELL: + .SHELLFLAGS += -e + + +MAIN_TARGET = $(LM_SENSORS) +DERIVED_TARGETS = fancontrol_$(LM_SENSORS_VERSION_FULL)_all.deb \ + $(LIBSENSORS) \ + sensord_$(LM_SENSORS_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + $(LM_SENSORS_DBG) \ + $(LIBSENSORS_DBG) \ + $(SENSORD_DBG) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf lm-sensors-$(LM_SENSORS_VERSION) + dget -u http://deb.debian.org/debian/pool/main/l/lm-sensors/lm-sensors_$(LM_SENSORS_VERSION_FULL).dsc + pushd lm-sensors-$(LM_SENSORS_VERSION) + + # Initialize as git repository + git init + git add -f * + git commit -m "unmodified lm-sensors sources" + + # Apply patches + stg init + stg import -s ../patch/series + + DEB_BUILD_OPTIONS=nocheck PROG_EXTRA=sensord dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/lm-sensors/patch/0001-patch-the-debian-package-info-to-get-sensord.patch b/src/lm-sensors/patch/0001-patch-the-debian-package-info-to-get-sensord.patch new file mode 100644 index 000000000000..262c7bca3f46 --- /dev/null +++ b/src/lm-sensors/patch/0001-patch-the-debian-package-info-to-get-sensord.patch @@ -0,0 +1,256 @@ +From a8047116d3724bf77cb4306f0440ea62f0a453ca Mon Sep 17 00:00:00 2001 +From: Mykola Faryma +Date: Tue, 19 Mar 2019 14:41:15 +0000 +Subject: [PATCH] patch the debian package info to get sensord + +Signed-off-by: Mykola Faryma +--- + debian/sensord.NEWS | 12 ++++ + debian/sensord.README.Debian | 23 ++++++++ + debian/sensord.default | 20 +++++++ + debian/sensord.dirs | 3 + + debian/sensord.init | 64 ++++++++++++++++++++++ + debian/sensord.install | 2 + + debian/sensord.maintscript | 2 + + debian/sensord.postinst | 23 ++++++++ + debian/sensord.substvars | 2 + + debian/control | 14 ++++++++++++++ + 11 files changed, 167 insertions(+), 1 deletion(-) + create mode 100644 /debian/sensord.NEWS + create mode 100644 /debian/sensord.README.Debian + create mode 100644 /debian/sensord.default + create mode 100644 /debian/sensord.dirs + create mode 100644 /debian/sensord.init + create mode 100644 /debian/sensord.install + create mode 100644 /debian/sensord.maintscript + create mode 100644 /debian/sensord.postinst + create mode 100644 /debian/sensord.substvars + +diff --git a/debian/sensord.NEWS b/debian/sensord.NEWS +new file mode 100644 +index 0000000..4bcfdb9 +--- /dev/null ++++ b/debian/sensord.NEWS +@@ -0,0 +1,12 @@ ++lm-sensors (1:2.9.0-7) unstable; urgency=low ++ ++ Since version 2.9.0 sensord doesn't scale the loadavg itself (* 10) as ++ RRDs work with floating-point values and thus do very well with ++ non-integer values even < 1. ++ ++ They can even be scaled later at display time by rrdtool itself using: ++ DEF:load=sensord.rrd:loadavg:AVERAGE ++ CDEF:load10=load,10,* ++ ++ -- Aurelien Jarno Tue, 11 Jan 2005 22:41:34 +0100 ++ +diff --git a/debian/sensord.README.Debian b/debian/sensord.README.Debian +new file mode 100644 +index 0000000..9159fbc +--- /dev/null ++++ b/debian/sensord.README.Debian +@@ -0,0 +1,23 @@ ++This is the Debian packaging of sensord, the sensord logging daemon. ++ ++The file /etc/default/sensord specifies the configuration parameters ++used to start the daemon. In particular, the syslog facility is set ++to `daemon' and not `local4'. ++ ++You must load the appropriate lm-sensors modules during system boot in ++order for the daemon to function correctly. ++ ++The file /etc/modules is a useful place to list these modules; for ++example, you might list i2c-amd756 (an I2C/SMBUS module) and w83781d ++(a sensor chip module). ++ ++The daemon does not setup the sensors limits from /etc/sensors3.conf, ++this is the job of sensors, when called with -s. Note that 'sensors -s' ++is called at boot time from /etc/init.d/lm-sensors, so that the sensors ++limits should be the right ones in normal use. Don't forget to run ++sensors -s again if you changed the limits in /etc/sensors3.conf. ++ ++For full documentation on setting up lm-sensors on your system, ++see /usr/share/doc/lm-sensors. ++ ++-- David Z. Maze +diff --git a/debian/sensord.default b/debian/sensord.default +new file mode 100644 +index 0000000..589b94c +--- /dev/null ++++ b/debian/sensord.default +@@ -0,0 +1,20 @@ ++# Interval between scanning for alarms; e.g., 30s, 1m, 1h ++# ALARM_INTERVAL=1m ++# Interval between logging sensor measurements; e.g., 30s, 1m, 1h ++# LOG_INTERVAL=30m ++# Syslog facility to use ++SYSLOG_FACILITY=daemon ++# Libsensors config file to use ++# CONFIG_FILE=/etc/sensors3.conf ++# Chips to scan ++# SCAN_CHIPS=... ++ ++# Uncomment this to enable a 7-day round-robin database of sensor ++# readings. See the ROUND ROBIN DATABASES section of the sensord ++# manual page for details. ++# RRD_FILE=/var/log/sensord.rrd ++# Interval between RRD readings; e.g. 30s, 5m (default), 1h ++# RRD_INTERVAL=5m ++# Include the load average in the RRD file. If you enable this you ++# must remove your old RRD file and rebuild your CGI script. ++# RRD_LOADAVG=yes +diff --git a/debian/sensord.dirs b/debian/sensord.dirs +new file mode 100644 +index 0000000..b9cd814 +--- /dev/null ++++ b/debian/sensord.dirs +@@ -0,0 +1,3 @@ ++usr/sbin ++usr/share/man/man8 ++etc/default +diff --git a/debian/sensord.init b/debian/sensord.init +new file mode 100644 +index 0000000..4d70d43 +--- /dev/null ++++ b/debian/sensord.init +@@ -0,0 +1,64 @@ ++#!/bin/sh ++ ++### BEGIN INIT INFO ++# Provides: sensord ++# Required-Start: $remote_fs $syslog lm-sensors ++# Required-Stop: $remote_fs $syslog ++# Default-Start: 2 3 4 5 ++# Default-Stop: ++# Short-Description: lm-sensors daemon ++# Description: hardware sensor information logging daemon ++### END INIT INFO ++ ++. /lib/lsb/init-functions ++ ++[ -f /etc/default/rcS ] && . /etc/default/rcS ++PATH=/bin:/usr/bin:/sbin:/usr/sbin ++DAEMON=/usr/sbin/sensord ++DESC="sensor daemon" ++NAME="sensord" ++PIDFILE=/var/run/sensord.pid ++CONFIG=/etc/default/sensord ++ ++test -x $DAEMON || exit 0 ++ ++if [ -f $CONFIG ]; then . $CONFIG; fi ++ ++if [ -n "$ALARM_INTERVAL" ]; then ALARM_INTERVAL="-i $ALARM_INTERVAL"; fi ++if [ -n "$LOG_INTERVAL" ]; then LOG_INTERVAL="-l $LOG_INTERVAL"; fi ++if [ -n "$SYSLOG_FACILITY" ]; then SYSLOG_FACILITY="-f $SYSLOG_FACILITY"; fi ++if [ -n "$CONFIG_FILE" ]; then CONFIG_FILE="-c $CONFIG_FILE"; fi ++if [ -n "$RRD_FILE" ]; then RRD_FILE="-r $RRD_FILE"; fi ++if [ -n "$RRD_INTERVAL" ]; then RRD_INTERVAL="-t $RRD_INTERVAL"; fi ++if [ -n "$RRD_LOADAVG" ]; then RRD_LOADAVG="-a"; fi ++ ++case "$1" in ++ start) ++ log_daemon_msg "Starting $DESC" "$NAME" ++ /sbin/start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $ALARM_INTERVAL $LOG_INTERVAL $SYSLOG_FACILITY $RRD_INTERVAL $RRD_FILE $RRD_LOADAVG $CONFIG_FILE $SCAN_CHIPS ++ log_end_msg $? ++ ;; ++ stop) ++ log_daemon_msg "Stopping $DESC" "$NAME" ++ start-stop-daemon --stop --quiet --pidfile $PIDFILE --oknodo --exec $DAEMON ++ log_end_msg $? ++ ;; ++ restart) ++ $0 stop ++ sleep 1 ++ $0 start ++ ;; ++ force-reload) ++ if start-stop-daemon --stop --test --quiet --pidfile $PIDFILE --exec $DAEMON ; then ++ $0 restart ++ fi ++ ;; ++ status) ++ status_of_proc $DAEMON $NAME && exit 0 || exit $? ++ ;; ++ *) ++ echo "Usage: /etc/init.d/sensord {start|stop|restart|force-reload|status}" ++ exit 1 ++esac ++ ++exit 0 +diff --git a/debian/sensord.install b/debian/sensord.install +new file mode 100644 +index 0000000..9713fee +--- /dev/null ++++ b/debian/sensord.install +@@ -0,0 +1,2 @@ ++usr/sbin/sensord ++usr/share/man/man8/sensord.8 +diff --git a/debian/sensord.maintscript b/debian/sensord.maintscript +new file mode 100644 +index 0000000..0e0ff03 +--- /dev/null ++++ b/debian/sensord.maintscript +@@ -0,0 +1,2 @@ ++# Remove old logcheck ignore file ++rm_conffile /etc/logcheck/ignore.d.server/sensord 1:3.3.5-1~ +diff --git a/debian/sensord.postinst b/debian/sensord.postinst +new file mode 100644 +index 0000000..3418fa6 +--- /dev/null ++++ b/debian/sensord.postinst +@@ -0,0 +1,23 @@ ++#!/bin/sh ++# postinst script for sensord ++# ++# see: dh_installdeb(1) ++set -e ++ ++case "$1" in ++ configure) ++ # Remove shutdown and reboot links; this init script does not need them. ++ if dpkg --compare-versions "$2" lt "1:3.1.1-5"; then ++ rm -f /etc/rc0.d/K[0-9][0-9]sensord /etc/rc1.d/K[0-9][0-9]sensord /etc/rc6.d/K[0-9][0-9]sensord ++ fi ++ ;; ++ abort-upgrade|abort-remove|abort-deconfigure) ++ ;; ++ ++ *) ++ echo "postinst called with unknown argument \`$1'" >&2 ++ exit 1 ++ ;; ++esac ++ ++#DEBHELPER# +diff --git a/debian/sensord.substvars b/debian/sensord.substvars +new file mode 100644 +index 0000000..978fc8b +--- /dev/null ++++ b/debian/sensord.substvars +@@ -0,0 +1,2 @@ ++misc:Depends= ++misc:Pre-Depends= +diff --git a/debian/control b/debian/control +--- a/debian/control ++++ b/debian/control +@@ -68,3 +68,17 @@ Description: utility to control the fan speed + and sets the corresponding PWM outputs to the computed values. This is + useful when this feature is not provided by the BIOS or ACPI, which should + normally be the case on a laptop. ++ ++Package: sensord ++Architecture: any ++Section: utils ++Depends: lm-sensors, lsb-base (>= 3.2-13), ${shlibs:Depends}, ${misc:Depends} ++Suggests: rrdtool ++Description: hardware sensor information logging daemon ++ Lm-sensors is a hardware health monitoring package for Linux. It allows you ++ to access information from temperature, voltage, and fan speed sensors. It ++ works with most newer systems. ++ . ++ This package contains a daemon that logs hardware health status to the ++ system log with optional warnings on potential system problems. ++ +-- +1.9.1 diff --git a/src/lm-sensors/patch/0002-Patch-to-peform-dh_installinit-to-include-sensord.in.patch b/src/lm-sensors/patch/0002-Patch-to-peform-dh_installinit-to-include-sensord.in.patch new file mode 100644 index 000000000000..7bfdee11e3be --- /dev/null +++ b/src/lm-sensors/patch/0002-Patch-to-peform-dh_installinit-to-include-sensord.in.patch @@ -0,0 +1,23 @@ +From b11fd3d516b62c01513d289bc901820aa150c63e Mon Sep 17 00:00:00 2001 +From: Charlie Chen +Date: Wed, 1 Apr 2020 06:59:06 +0000 +Subject: Patch to peform dh_installinit to include sensord.install in the + packed deb + +Signed-off-by: Charlie Chen +--- + debian/rules | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/debian/rules b/debian/rules +index 5ebda06..1d77e28 100755 +--- a/debian/rules ++++ b/debian/rules +@@ -56,3 +56,4 @@ override_dh_auto_install-arch: + + override_dh_installinit-arch: + dh_installinit -plm-sensors --no-start ++ dh_installinit -psensord --no-start +-- +2.17.1 + diff --git a/src/lm-sensors/patch/series b/src/lm-sensors/patch/series new file mode 100644 index 000000000000..43980ccab4db --- /dev/null +++ b/src/lm-sensors/patch/series @@ -0,0 +1,2 @@ +0001-patch-the-debian-package-info-to-get-sensord.patch +0002-Patch-to-peform-dh_installinit-to-include-sensord.in.patch diff --git a/src/monit/.gitignore b/src/monit/.gitignore new file mode 100644 index 000000000000..d19db76ab9a9 --- /dev/null +++ b/src/monit/.gitignore @@ -0,0 +1,4 @@ +* +!.gitignore +!Makefile +!patch/ diff --git a/src/monit/Makefile b/src/monit/Makefile new file mode 100644 index 000000000000..570f30cf60f8 --- /dev/null +++ b/src/monit/Makefile @@ -0,0 +1,33 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = monit_$(MONIT_VERSION)_$(CONFIGURED_ARCH).deb +DERIVED_TARGETS = monit-dbgsym_$(MONIT_VERSION)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./monit + + # Clone monit repo + git clone https://salsa.debian.org/sk-guest/monit.git + pushd ./monit + + # Reset HEAD to the commit of the proper tag + # NOTE: Using "git checkout " here detaches our HEAD, + # which stg doesn't like, so we use this method instead + # NOTE: For some reason, tags in the Debian monit repo are prefixed with "1%" + git reset --hard debian/1\%$(MONIT_VERSION) + + # Apply patches + stg init + stg import -s ../patch/series + + # Build source and Debian packages + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + # Move the newly-built .deb packages to the destination directory + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/monit/patch/0001-used_system_memory_sysdep-Use-MemAvailable-value-if-.patch b/src/monit/patch/0001-used_system_memory_sysdep-Use-MemAvailable-value-if-.patch new file mode 100644 index 000000000000..9c67d153cbbb --- /dev/null +++ b/src/monit/patch/0001-used_system_memory_sysdep-Use-MemAvailable-value-if-.patch @@ -0,0 +1,70 @@ +From c392362c9c1d57256b7e8ab7c77926824677fd73 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Tue, 19 Nov 2019 01:51:13 +0000 +Subject: [PATCH] [used_system_memory_sysdep] Use 'MemAvailable' value if + available + +--- + src/process/sysdep_LINUX.c | 35 +++++++++++++++++++++++------------ + 1 file changed, 23 insertions(+), 12 deletions(-) + +diff --git a/src/process/sysdep_LINUX.c b/src/process/sysdep_LINUX.c +index 0d18f85..221e785 100644 +--- a/src/process/sysdep_LINUX.c ++++ b/src/process/sysdep_LINUX.c +@@ -335,6 +335,7 @@ int getloadavg_sysdep(double *loadv, int nelem) { + boolean_t used_system_memory_sysdep(SystemInfo_T *si) { + char *ptr; + char buf[2048]; ++ unsigned long mem_available = 0UL; + unsigned long mem_free = 0UL; + unsigned long buffers = 0UL; + unsigned long cached = 0UL; +@@ -343,22 +344,32 @@ boolean_t used_system_memory_sysdep(SystemInfo_T *si) { + unsigned long swap_free = 0UL; + + if (! file_readProc(buf, sizeof(buf), "meminfo", -1, NULL)) { +- LogError("system statistic error -- cannot get real memory free amount\n"); ++ LogError("system statistic error -- cannot read /proc/meminfo\n"); + goto error; + } + +- /* Memory */ +- if (! (ptr = strstr(buf, "MemFree:")) || sscanf(ptr + 8, "%ld", &mem_free) != 1) { +- LogError("system statistic error -- cannot get real memory free amount\n"); +- goto error; ++ /* ++ * Memory ++ * ++ * First, check if the "MemAvailable" value is available on this system. If it is, we will ++ * use it. Otherwise we will attempt to calculate the amount of available memory ourself. ++ */ ++ if ((ptr = strstr(buf, "MemAvailable:")) && sscanf(ptr + 13, "%ld", &mem_available) == 1) { ++ si->total_mem = systeminfo.mem_max - (uint64_t)mem_available * 1024; ++ } else { ++ DEBUG("'MemAvailable' value not available on this system. Attempting to calculate available memory manually...\n"); ++ if (! (ptr = strstr(buf, "MemFree:")) || sscanf(ptr + 8, "%ld", &mem_free) != 1) { ++ LogError("system statistic error -- cannot get real memory free amount\n"); ++ goto error; ++ } ++ if (! (ptr = strstr(buf, "Buffers:")) || sscanf(ptr + 8, "%ld", &buffers) != 1) ++ DEBUG("system statistic error -- cannot get real memory buffers amount\n"); ++ if (! (ptr = strstr(buf, "Cached:")) || sscanf(ptr + 7, "%ld", &cached) != 1) ++ DEBUG("system statistic error -- cannot get real memory cache amount\n"); ++ if (! (ptr = strstr(buf, "SReclaimable:")) || sscanf(ptr + 13, "%ld", &slabreclaimable) != 1) ++ DEBUG("system statistic error -- cannot get slab reclaimable memory amount\n"); ++ si->total_mem = systeminfo.mem_max - (uint64_t)(mem_free + buffers + cached + slabreclaimable) * 1024; + } +- if (! (ptr = strstr(buf, "Buffers:")) || sscanf(ptr + 8, "%ld", &buffers) != 1) +- DEBUG("system statistic error -- cannot get real memory buffers amount\n"); +- if (! (ptr = strstr(buf, "Cached:")) || sscanf(ptr + 7, "%ld", &cached) != 1) +- DEBUG("system statistic error -- cannot get real memory cache amount\n"); +- if (! (ptr = strstr(buf, "SReclaimable:")) || sscanf(ptr + 13, "%ld", &slabreclaimable) != 1) +- DEBUG("system statistic error -- cannot get slab reclaimable memory amount\n"); +- si->total_mem = systeminfo.mem_max - (uint64_t)(mem_free + buffers + cached + slabreclaimable) * 1024; + + /* Swap */ + if (! (ptr = strstr(buf, "SwapTotal:")) || sscanf(ptr + 10, "%ld", &swap_total) != 1) { +-- +2.17.1 + diff --git a/src/monit/patch/0002-change_monit_alert_log_error.patch b/src/monit/patch/0002-change_monit_alert_log_error.patch new file mode 100644 index 000000000000..1e43078e6215 --- /dev/null +++ b/src/monit/patch/0002-change_monit_alert_log_error.patch @@ -0,0 +1,64 @@ +From 97a5defc6a7fcc6a00f691bb5314ceb8fb7704e9 Mon Sep 17 00:00:00 2001 +From: Abhishek Dosi +Date: Mon, 26 Oct 2020 11:40:02 -0700 +Subject: [PATCH] Patch on top of commit Patch is addressing these changes:- + +a) Enable repeat keyword for alert action . Using this we can log +syslog error message for persistent failure condition + +b) Make sure error message is loggged if state is changed to fail first time (fault tolerance condition) +or we have repeat clause for alert + +Signed-off-by: Abhishek Dosi + +--- + src/event.c | 6 +++++- + src/p.y | 8 +++++++- + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/event.c b/src/event.c +index ed363ee..9d08fc0 100644 +--- a/src/event.c ++++ b/src/event.c +@@ -336,7 +336,8 @@ static void _handleEvent(Service_T S, Event_T E) { + if (E->state != State_Init || E->state_map & 0x1) { + if (E->state == State_Succeeded || E->state == State_ChangedNot || E->id == Event_Instance || E->id == Event_Action) + LogInfo("'%s' %s\n", S->name, E->message); +- else ++ /* Send Error log if state change to failed for 1st time or if we have repeat clause then do periodically */ ++ else if ((E->state_changed) || (E->state == State_Failed && E->action->failed->repeat && E->count % E->action->failed->repeat == 0)) + LogError("'%s' %s\n", S->name, E->message); + } + if (E->state == State_Init) + return; +diff --git a/src/p.y b/src/p.y +index a57807d..b46b1a1 100644 +--- a/src/p.y ++++ b/src/p.y +@@ -2250,9 +2250,12 @@ repeat : /* EMPTY */ { + } + ; + +-action : ALERT { ++action : ALERT repeat{ + $$ = Action_Alert; + } ++ | ALERT { ++ $$ = Action_Alert; ++ } + | EXEC argumentlist repeat { + $$ = Action_Exec; + } +@@ -2281,6 +2284,9 @@ action1 : action { + repeat = 0; + command1 = command; + command = NULL; ++ } else if ($1 == Action_Alert) { ++ repeat1 = repeat; ++ repeat = 0; + } + } + ; +-- +2.17.1 + diff --git a/src/monit/patch/series b/src/monit/patch/series new file mode 100644 index 000000000000..f5534d0f554f --- /dev/null +++ b/src/monit/patch/series @@ -0,0 +1,3 @@ +# This series applies on GIT commit dc9bc1c949125140d967edfc598dfad47eedc552 +0001-used_system_memory_sysdep-Use-MemAvailable-value-if-.patch +0002-change_monit_alert_log_error.patch diff --git a/src/mpdecimal/.gitignore b/src/mpdecimal/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/mpdecimal/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/mpdecimal/Makefile b/src/mpdecimal/Makefile new file mode 100644 index 000000000000..b7f82ba702e5 --- /dev/null +++ b/src/mpdecimal/Makefile @@ -0,0 +1,22 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = libmpdec2_$(MPDECIMAL_VERSION_FULL)_$(CONFIGURED_ARCH).deb +DERIVED_TARGETS = libmpdec-dev_$(MPDECIMAL_VERSION_FULL)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf mpdecimal-$(MPDECIMAL_VERSION) + + wget -N -O mpdecimal_$(MPDECIMAL_VERSION).orig.tar.gz http://http.debian.net/debian/pool/main/m/mpdecimal/mpdecimal_$(MPDECIMAL_VERSION).orig.tar.gz + wget -N -O mpdecimal_$(MPDECIMAL_VERSION_FULL).debian.tar.xz http://http.debian.net/debian/pool/main/m/mpdecimal/mpdecimal_$(MPDECIMAL_VERSION_FULL).debian.tar.xz + wget -N -O mpdecimal_$(MPDECIMAL_VERSION_FULL).dsc http://http.debian.net/debian/pool/main/m/mpdecimal/mpdecimal_$(MPDECIMAL_VERSION_FULL).dsc + + dpkg-source -x mpdecimal_$(MPDECIMAL_VERSION_FULL).dsc + pushd mpdecimal-$(MPDECIMAL_VERSION) + dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $* $(DERIVED_TARGETS) $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/ntp/.gitignore b/src/ntp/.gitignore new file mode 100644 index 000000000000..1b46fe753f41 --- /dev/null +++ b/src/ntp/.gitignore @@ -0,0 +1,5 @@ +*+dfsg +*.buildinfo +*.changes +*.xz +*.deb diff --git a/src/ntp/Makefile b/src/ntp/Makefile new file mode 100644 index 000000000000..6d96010be156 --- /dev/null +++ b/src/ntp/Makefile @@ -0,0 +1,48 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(NTP) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./ntp-$(NTP_VERSION) ./ntp_$(NTP_VERSION).orig.tar.xz ./ntp_$(NTP_VERSION)-4.debian.tar.xz + + # Get ntp release, debian files + wget http://deb.debian.org/debian/pool/main/n/ntp/ntp_$(NTP_VERSION).orig.tar.xz + wget http://deb.debian.org/debian/pool/main/n/ntp/ntp_$(NTP_VERSION)-4.debian.tar.xz + + # UnTar ntp release + xzcat ntp_$(NTP_VERSION).orig.tar.xz | tar -xvf - + + pushd ./ntp-4.2.8p12 + + # UnTar debian files + xzcat ../ntp_$(NTP_VERSION)-4.debian.tar.xz | tar -xvf - + + # Add the additional patch + cp ../patch/bug1970-UNLINK_EXPR_SLIST_empty_list.patch debian/patches/ + cp ../patch/update_ENOBUFS_log_level.patch debian/patches/ + cat ../patch/series >> debian/patches/series + + # Update the changelog + cat ../patch/changelog debian/changelog > debian/changelog.new + rm debian/changelog ; mv debian/changelog.new debian/changelog + + # The debian mirror build likely took place on a system without + # libevent installed, thus adding the below for SONiC + sed -i 's/--with-locfile=legacy/--with-locfile=legacy --enable-local-libevent/' debian/rules + + # Fix the apparmor profile to avoid the following message + # "Failed name lookup - disconnected path" + # and go into learning mode. + sed -i 's/\/usr\/sbin\/ntpd {/\/usr\/sbin\/ntpd flags=(attach_disconnected complain) {/' debian/apparmor-profile + + # Build source and Debian packages with the symbols + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + + popd + + # Move the newly-built .deb packages to the destination directory + mv $* $(DEST)/ + diff --git a/src/ntp/patch/bug1970-UNLINK_EXPR_SLIST_empty_list.patch b/src/ntp/patch/bug1970-UNLINK_EXPR_SLIST_empty_list.patch new file mode 100644 index 000000000000..701dc0103944 --- /dev/null +++ b/src/ntp/patch/bug1970-UNLINK_EXPR_SLIST_empty_list.patch @@ -0,0 +1,26 @@ +Bug 1970 UNLINK_EXPR_SLIST() causes crash if list is empty + +From: Arun Barboza + + +--- + include/ntp_lists.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/ntp_lists.h b/include/ntp_lists.h +index d741974..f90bf23 100644 +--- a/include/ntp_lists.h ++++ b/include/ntp_lists.h +@@ -184,7 +184,11 @@ do { \ + do { \ + entrytype **ppentry; \ + \ +- ppentry = &(listhead); \ ++ if (!listhead) { \ ++ (punlinked) = NULL; \ ++ break; \ ++ } \ ++ else ppentry = &(listhead); \ + \ + while (!(expr)) \ + if (*ppentry != NULL && \ diff --git a/src/ntp/patch/changelog b/src/ntp/patch/changelog new file mode 100644 index 000000000000..8fa477cca266 --- /dev/null +++ b/src/ntp/patch/changelog @@ -0,0 +1,12 @@ +ntp (1:4.2.8p12+dfsg-4+deb10u2) stretch; urgency=medium + + * Adjust the ENOBUFS syslog level on the Netlink routing to LOG_WARNING. + + -- Arun Barboza Mon, 09 Sep 2019 10:15:35 -0700 + +ntp (1:4.2.8p12+dfsg-4+deb10u1) stretch; urgency=medium + + * Apply Bug1970 fix for UNLINK_EXPR_SLIST_empty_list from dev branch. + + -- Arun Barboza Tue, 25 Jun 2019 14:35:24 -0700 + diff --git a/src/ntp/patch/series b/src/ntp/patch/series new file mode 100644 index 000000000000..9ce40f13e21a --- /dev/null +++ b/src/ntp/patch/series @@ -0,0 +1,3 @@ +# This series applies on GIT commit d09f041a49c61971f59fc29f505446c63aea51b1 +bug1970-UNLINK_EXPR_SLIST_empty_list.patch +update_ENOBUFS_log_level.patch diff --git a/src/ntp/patch/update_ENOBUFS_log_level.patch b/src/ntp/patch/update_ENOBUFS_log_level.patch new file mode 100644 index 000000000000..618fc323b105 --- /dev/null +++ b/src/ntp/patch/update_ENOBUFS_log_level.patch @@ -0,0 +1,22 @@ +Adjust the ENOBUFS syslog level on the Netlink routing to LOG_WARNING. + +From: Arun Barboza + + +--- + ntpd/ntp_io.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: b/ntpd/ntp_io.c +=================================================================== +--- a/ntpd/ntp_io.c ++++ b/ntpd/ntp_io.c +@@ -4709,7 +4709,7 @@ process_routing_msgs(struct asyncio_read + + if (cnt < 0) { + if (errno == ENOBUFS) { +- msyslog(LOG_ERR, ++ msyslog(LOG_WARNING, + "routing socket reports: %m"); + } else { + msyslog(LOG_ERR, diff --git a/src/openssh/Makefile b/src/openssh/Makefile new file mode 100644 index 000000000000..0fd8642b1285 --- /dev/null +++ b/src/openssh/Makefile @@ -0,0 +1,28 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = openssh-server_$(OPENSSH_VERSION)_$(CONFIGURED_ARCH).deb +DERIVED_TARGETS = openssh-server-dbgsym_$(OPENSSH_VERSION)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Obtain openssh: https://salsa.debian.org/ssh-team/openssh/-/tree/debian/1%257.9p1-10+deb10u2 + rm -rf ./openssh-server + git clone https://salsa.debian.org/ssh-team/openssh.git openssh-server + pushd ./openssh-server + + # Check out tag: debian/1%7.9p1-10+deb10u2 + git checkout -b openssh-src -f 6d9ca74c48d9911342c6ca5aaac8a25974fa2619 + + # Apply patch series + stg init + stg import -s ../patch/series + + # Build package + sudo http_proxy=$(http_proxy) apt-get -y build-dep openssh + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/openssh/patch/0001-Put-style-as-line-number-to-ssh-session-environment-.patch b/src/openssh/patch/0001-Put-style-as-line-number-to-ssh-session-environment-.patch new file mode 100644 index 000000000000..a11c7bf46c37 --- /dev/null +++ b/src/openssh/patch/0001-Put-style-as-line-number-to-ssh-session-environment-.patch @@ -0,0 +1,36 @@ +From 6e8cca780dab4680292192058b90a4a28f35d4ab Mon Sep 17 00:00:00 2001 +From: Blueve +Date: Mon, 26 Oct 2020 06:44:59 +0000 +Subject: [PATCH 1/1] Put style as line number to ssh session environment + variable + +By default, the content between : and @ will be trimmed by sshd before it do +authentication and the trimmed string will be dropped silently. To use this +segment as line number for reverse SSH feature, we need to modify the source +code of OpenSSH and put this segment to a environment variable +SSH_TARGET_CONSOLE_LINE, then we can insert a short script into /etc/bash.bashrc +and run command consutil connect $SSH_TARGET_CONSOLE_LINE to enter the +management session automatically after user login. +--- + session.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/session.c b/session.c +index 19f38637e..654371447 100644 +--- a/session.c ++++ b/session.c +@@ -1209,6 +1209,11 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) + child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", + original_command); + ++ /* Take advantage of authentication style field */ ++ if (s->authctxt->style) ++ child_set_env(&env, &envsize, "SSH_TARGET_CONSOLE_LINE", ++ s->authctxt->style); ++ + if (debug_flag) { + /* dump the environment */ + fprintf(stderr, "Environment:\n"); +-- +2.25.1 + diff --git a/src/openssh/patch/series b/src/openssh/patch/series new file mode 100644 index 000000000000..a645ad25833f --- /dev/null +++ b/src/openssh/patch/series @@ -0,0 +1 @@ +0001-Put-style-as-line-number-to-ssh-session-environment-.patch diff --git a/src/ptf b/src/ptf new file mode 160000 index 000000000000..36a3e3d9ac04 --- /dev/null +++ b/src/ptf @@ -0,0 +1 @@ +Subproject commit 36a3e3d9ac0447d28161d24028401239d756875f diff --git a/src/redis-dump-load b/src/redis-dump-load new file mode 160000 index 000000000000..758549795174 --- /dev/null +++ b/src/redis-dump-load @@ -0,0 +1 @@ +Subproject commit 758549795174dc6b3be70810e0e4d6308f80f1a3 diff --git a/src/redis-dump-load.patch/0001-Use-pipelines-when-dumping-52.patch b/src/redis-dump-load.patch/0001-Use-pipelines-when-dumping-52.patch new file mode 100644 index 000000000000..c37cbd9f4bf1 --- /dev/null +++ b/src/redis-dump-load.patch/0001-Use-pipelines-when-dumping-52.patch @@ -0,0 +1,155 @@ +From ed20dced07d8b2d140e2c1d79d506be0e12f339e Mon Sep 17 00:00:00 2001 +From: Oleg Pudeyev +Date: Sat, 28 Jan 2017 15:37:43 -0500 +Subject: [PATCH] Use pipelines when dumping, #52 + +--- + redisdl.py | 102 +++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 75 insertions(+), 27 deletions(-) + +diff --git a/redisdl.py b/redisdl.py +index df2870b..1b6063b 100755 +--- a/redisdl.py ++++ b/redisdl.py +@@ -141,18 +141,18 @@ def dumps(host='localhost', port=6379, password=None, db=0, pretty=False, + class BytesWriteWrapper(object): + def __init__(self, stream): + self.stream = stream +- ++ + def write(self, str): + return self.stream.write(str.encode()) + + def dump(fp, host='localhost', port=6379, password=None, db=0, pretty=False, + unix_socket_path=None, encoding='utf-8', keys='*'): +- ++ + try: + fp.write('') + except TypeError: + fp = BytesWriteWrapper(fp) +- ++ + if pretty: + # hack to avoid implementing pretty printing + fp.write(dumps(host=host, port=port, password=password, db=db, +@@ -276,28 +276,77 @@ def _read_key(key, r, pretty, encoding): + return (type, ttl, value) + + def _reader(r, pretty, encoding, keys='*'): +- for encoded_key in r.keys(keys): +- key = encoded_key.decode(encoding) +- handled = False +- for i in range(10): +- try: +- type, ttl, value = _read_key(encoded_key, r, pretty, encoding) +- yield key, type, ttl, value +- handled = True +- break +- except KeyDeletedError: +- # do not dump the key +- handled = True +- break +- except redis.WatchError: +- # same logic as key type changed +- pass +- except KeyTypeChangedError: +- # retry reading type again +- pass +- if not handled: +- # ran out of retries +- raise ConcurrentModificationError('Key %s is being concurrently modified' % key) ++ encoded_keys = r.keys(keys) ++ i = 0 ++ while i < len(encoded_keys): ++ for key, type, ttl, value in _read_keys(r, encoded_keys[i:i+10000], ++ pretty=pretty, encoding=encoding): ++ yield key, type, ttl, value ++ i += 10000 ++ ++def _read_keys(r, encoded_keys, pretty, encoding): ++ decoded_keys = [encoded_key.decode(encoding) for encoded_key in encoded_keys] ++ do_keys = decoded_keys ++ retries = 5 ++ type_results = None ++ while len(do_keys) > 0 and retries > 0: ++ next_do_keys = [] ++ next_type_results = [] ++ ++ if type_results is None: ++ # first pass, need to get the types. ++ # on subsequent passes we know the types ++ # because the previous pass retrieved them and ++ # found a type mismatch ++ p = r.pipeline() ++ for key in do_keys: ++ p.type(key) ++ encoded_type_results = p.execute() ++ type_results = [encoded_type_result.decode('ascii') for encoded_type_result in encoded_type_results] ++ ++ p = r.pipeline() ++ for i in range(len(do_keys)): ++ key = decoded_keys[i] ++ type = type_results[i] ++ if type == 'none': ++ # key was deleted by a concurrent operation on the data store. ++ # issue noops so that the number of results does not change ++ p.type(key) ++ p.type(key) ++ p.type(key) ++ continue ++ reader = readers.get(type) ++ if reader is None: ++ raise UnknownTypeError("Unknown key type: %s" % type) ++ reader.send_command(p, key) ++ r.pttl_or_ttl_pipeline(p, key) ++ p.type(key) ++ results = p.execute() ++ ++ for i in range(len(do_keys)): ++ key = decoded_keys[i] ++ original_type = type_results[i] ++ if original_type == 'none': ++ # this is where we actually skip a key that was deleted ++ # by concurrent operations ++ continue ++ final_type = results[i*3+2].decode('ascii') ++ if original_type != final_type: ++ # type changed, will retry ++ next_do_keys.append(key) ++ # need to update expected type ++ next_type_results.append(final_type) ++ continue ++ reader = readers.get(original_type) ++ value = reader.handle_response(results[i*3], pretty, encoding) ++ ttl = r.decode_pttl_or_ttl_pipeline_value(results[i*3+1]) ++ yield key, final_type, ttl, value ++ retries -= 1 ++ do_keys = next_do_keys ++ type_results = next_type_results ++ ++ if len(do_keys) > 0: ++ raise ConcurrentModificationError('Keys %s are being concurrently modified' % ', '.join(do_keys)) + + def _empty(r): + for key in r.keys(): +@@ -372,14 +420,14 @@ def ijson_top_level_items(file, local_streaming_backend): + class TextReadWrapper(object): + def __init__(self, fp): + self.fp = fp +- ++ + def read(self, *args, **kwargs): + return self.fp.read(*args, **kwargs).decode() + + class BytesReadWrapper(object): + def __init__(self, fp): + self.fp = fp +- ++ + def read(self, *args, **kwargs): + return self.fp.read(*args, **kwargs).encode('utf-8') + +-- +2.18.0 + diff --git a/src/redis-dump-load.patch/0002-Fix-setup.py-for-test-and-bdist_wheel.patch b/src/redis-dump-load.patch/0002-Fix-setup.py-for-test-and-bdist_wheel.patch new file mode 100644 index 000000000000..5bb319a61738 --- /dev/null +++ b/src/redis-dump-load.patch/0002-Fix-setup.py-for-test-and-bdist_wheel.patch @@ -0,0 +1,26 @@ +From c2c93fa3b702a4f2364383fd4ae69763068686d2 Mon Sep 17 00:00:00 2001 +From: Qi Luo +Date: Tue, 20 Nov 2018 03:21:31 +0000 +Subject: [PATCH] Fix setup.py for test and bdist_wheel + +Signed-off-by: Qi Luo +--- + setup.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/setup.py b/setup.py +index 8ccf31f..6457163 100644 +--- a/setup.py ++++ b/setup.py +@@ -1,7 +1,7 @@ + #!/usr/bin/env python + + import os.path +-from distutils.core import setup ++from setuptools import setup, find_packages + + package_name = 'redis-dump-load' + package_version = '1.1' +-- +2.18.0 + diff --git a/src/redis-dump-load.patch/series b/src/redis-dump-load.patch/series new file mode 100644 index 000000000000..c73c3b5caa97 --- /dev/null +++ b/src/redis-dump-load.patch/series @@ -0,0 +1,2 @@ +0001-Use-pipelines-when-dumping-52.patch +0002-Fix-setup.py-for-test-and-bdist_wheel.patch diff --git a/src/redis/.gitignore b/src/redis/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/redis/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/redis/Makefile b/src/redis/Makefile new file mode 100644 index 000000000000..3a4fe3f4844c --- /dev/null +++ b/src/redis/Makefile @@ -0,0 +1,31 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + +REDIS_VERSION = 5.0.3 +REDIS_VERSION_FULL = $(REDIS_VERSION)-3~bpo9+2 + +MAIN_TARGET = redis-server_$(REDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb +DERIVED_TARGETS = redis-tools_$(REDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + redis-sentinel_$(REDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + redis-tools-dbgsym_$(REDIS_VERSION_FULL)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf redis_build + mkdir redis_build + pushd redis_build + + wget -O redis_$(REDIS_VERSION).orig.tar.gz -N "http://http.debian.net/debian/pool/main/r/redis/redis_$(REDIS_VERSION).orig.tar.gz" + wget -O redis_$(REDIS_VERSION_FULL).dsc -N "http://http.debian.net/debian/pool/main/r/redis/redis_$(REDIS_VERSION_FULL).dsc" + wget -O redis_$(REDIS_VERSION_FULL).debian.tar.xz -N "http://http.debian.net/debian/pool/main/r/redis/redis_$(REDIS_VERSION_FULL).debian.tar.xz" + dpkg-source -x redis_$(REDIS_VERSION_FULL).dsc + + pushd redis-$(REDIS_VERSION) + export ARCH="" + DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + popd + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/sflow/hsflowd/.gitignore b/src/sflow/hsflowd/.gitignore new file mode 100644 index 000000000000..d19db76ab9a9 --- /dev/null +++ b/src/sflow/hsflowd/.gitignore @@ -0,0 +1,4 @@ +* +!.gitignore +!Makefile +!patch/ diff --git a/src/sflow/hsflowd/Makefile b/src/sflow/hsflowd/Makefile new file mode 100644 index 000000000000..e29dbcc199bb --- /dev/null +++ b/src/sflow/hsflowd/Makefile @@ -0,0 +1,29 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(HSFLOWD) +DERIVED_TARGET = $(HSFLOWD_DBG) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -fr ./host-sflow + git clone https://github.com/sflow/host-sflow + + pushd ./host-sflow + git checkout -b sflow tags/v$(HSFLOWD_VERSION)-$(HSFLOWD_SUBVERSION) + + # Apply patch series + stg init + stg import -s ../patch/series + + mkdir -p debian + cp -r DEBIAN_build/* debian + chmod u+x debian/rules + sed -i -e s/_VERSION_/$(HSFLOWD_VERSION)-$(HSFLOWD_SUBVERSION)/g debian/changelog + + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) --buildinfo-option=-u. --changes-option=-u. + + mv $(DERIVED_TARGET) $* $(DEST)/ + popd + +$(addprefix $(DEST)/, $(DERIVED_TARGET)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/sflow/hsflowd/patch/0001-host_sflow_psample.patch b/src/sflow/hsflowd/patch/0001-host_sflow_psample.patch new file mode 100644 index 000000000000..d0672f80cd5b --- /dev/null +++ b/src/sflow/hsflowd/patch/0001-host_sflow_psample.patch @@ -0,0 +1,39 @@ +diff -ruN a/src/Linux/linux/psample.h b/src/Linux/linux/psample.h +--- a/src/Linux/linux/psample.h 1969-12-31 16:00:00.000000000 -0800 ++++ b/src/Linux/linux/psample.h 2019-07-20 08:45:58.715748881 -0700 +@@ -0,0 +1,35 @@ ++#ifndef __UAPI_PSAMPLE_H ++#define __UAPI_PSAMPLE_H ++ ++enum { ++ /* sampled packet metadata */ ++ PSAMPLE_ATTR_IIFINDEX, ++ PSAMPLE_ATTR_OIFINDEX, ++ PSAMPLE_ATTR_ORIGSIZE, ++ PSAMPLE_ATTR_SAMPLE_GROUP, ++ PSAMPLE_ATTR_GROUP_SEQ, ++ PSAMPLE_ATTR_SAMPLE_RATE, ++ PSAMPLE_ATTR_DATA, ++ ++ /* commands attributes */ ++ PSAMPLE_ATTR_GROUP_REFCOUNT, ++ ++ __PSAMPLE_ATTR_MAX ++}; ++ ++enum psample_command { ++ PSAMPLE_CMD_SAMPLE, ++ PSAMPLE_CMD_GET_GROUP, ++ PSAMPLE_CMD_NEW_GROUP, ++ PSAMPLE_CMD_DEL_GROUP, ++}; ++ ++/* Can be overridden at runtime by module option */ ++#define PSAMPLE_ATTR_MAX (__PSAMPLE_ATTR_MAX - 1) ++ ++#define PSAMPLE_NL_MCGRP_CONFIG_NAME "config" ++#define PSAMPLE_NL_MCGRP_SAMPLE_NAME "packets" ++#define PSAMPLE_GENL_NAME "psample" ++#define PSAMPLE_GENL_VERSION 1 ++ ++#endif diff --git a/src/sflow/hsflowd/patch/0002-host_sflow_debian.patch b/src/sflow/hsflowd/patch/0002-host_sflow_debian.patch new file mode 100644 index 000000000000..86ebab723351 --- /dev/null +++ b/src/sflow/hsflowd/patch/0002-host_sflow_debian.patch @@ -0,0 +1,108 @@ +diff -ruN a/DEBIAN_build/changelog b/DEBIAN_build/changelog +--- a/DEBIAN_build/changelog 1969-12-31 19:00:00.000000000 -0500 ++++ b/DEBIAN_build/changelog 2019-08-19 22:52:10.171736403 -0400 +@@ -0,0 +1,6 @@ ++hsflowd (_VERSION_) stable; urgency=medium ++ ++ [ DellEMC ] ++ * Initial release : hsflowd ++ ++ -- DellEMC Mon, 29 Jul 2019 07:08:02 -0400 +diff -ruN a/DEBIAN_build/compat b/DEBIAN_build/compat +--- a/DEBIAN_build/compat 1969-12-31 19:00:00.000000000 -0500 ++++ b/DEBIAN_build/compat 2019-08-16 23:28:58.020938096 -0400 +@@ -0,0 +1 @@ ++9 +diff -ruN a/DEBIAN_build/control b/DEBIAN_build/control +--- a/DEBIAN_build/control 2019-08-16 05:11:33.974949327 -0400 ++++ b/DEBIAN_build/control 2019-08-19 21:28:07.155722725 -0400 +@@ -1,9 +1,22 @@ +-Package: _PACKAGE_ +-Version: _VERSION_ +-Section: admin ++Source: hsflowd ++Maintainer: Neil McKee [neil.mckee@inmon.com] ++Uploaders: DellEMC ++Section: net ++Priority: optional ++Build-Depends: dh-exec (>=0.3), debhelper (>= 9), autotools-dev ++Standards-Version: 1.0.0 ++ ++Package: hsflowd ++Section: admin + Priority: optional +-Architecture: all ++Architecture: any + Essential: no +-Maintainer: Neil McKee [neil.mckee@inmon.com] + Description: sFlow(R) monitoring agent + Homepage: sflow.net ++ ++Package: hsflowd-dbg ++Architecture: any ++Section: debug ++Priority: extra ++Depends: hsflowd ++Description: debugging symbols for hsflowd +diff -ruN a/DEBIAN_build/rules b/DEBIAN_build/rules +--- a/DEBIAN_build/rules 1969-12-31 19:00:00.000000000 -0500 ++++ b/DEBIAN_build/rules 2019-08-19 22:20:42.998569601 -0400 +@@ -0,0 +1,31 @@ ++#!/usr/bin/make -f ++ ++# See debhelper(7) (uncomment to enable) ++# output every command that modifies files on the build system. ++export DH_VERBOSE = 1 ++ ++# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/* ++DPKG_EXPORT_BUILDFLAGS = 1 ++include /usr/share/dpkg/default.mk ++ ++%: ++ dh $@ ++ ++binary: ++ dh_gencontrol ++ dh_strip -phsflowd --dbg-package=hsflowd-dbg ++ dpkg-deb --build debian/hsflowd-dbg hsflowd-dbg_$(HSFLOWD_VERSION)-$(HSFLOWD_SUBVERSION)_$(CONFIGURED_ARCH).deb ++ dpkg-deb --build debian/hsflowd hsflowd_$(HSFLOWD_VERSION)-$(HSFLOWD_SUBVERSION)_$(CONFIGURED_ARCH).deb ++ ++override_dh_auto_build: ++ make sonic-deb FEATURES="SONIC" ++ ++override_dh_auto_configure: ++ ++override_dh_auto_install: ++ ++override_dh_auto_test: ++ ++override_dh_auto_clean: ++ ++override_dh_clean: +diff -ruN a/Makefile b/Makefile +--- a/Makefile 2019-08-16 21:34:25.167679297 -0400 ++++ b/Makefile 2019-08-19 22:20:23.758479002 -0400 +@@ -146,6 +146,23 @@ + cd ..; \ + dpkg-deb --build debian hsflowd_$${MYVER}-$${MYREL}_$$MYARCH.deb + ++sonic-deb: $(PROG) ++ MYARCH=`uname -m|sed 's/x86_64/amd64/'`; \ ++ MYVER=`./getVersion`; \ ++ MYREL=`./getRelease`; \ ++ PLATFORM=`uname`; \ ++ mkdir -p debian/usr/sbin; \ ++ mkdir -p debian/etc/init.d; \ ++ mkdir -p debian/etc/hsflowd/modules; \ ++ mkdir -p debian/lib/systemd/system; \ ++ mkdir -p debian/etc/dbus-1/system.d; \ ++ cd src/$$PLATFORM; $(MAKE) VERSION=$$MYVER RELEASE=$$MYREL INSTROOT="../../debian/hsflowd" install; cd ../..; \ ++ pwd; \ ++ cd debian/hsflowd; \ ++ find . -type d | xargs chmod 755; \ ++ md5sum `find usr etc -type f` > md5sums; \ ++ cd ../..; ++ + xenserver: xenrpm + cd xenserver-ddk; $(MAKE) clean; $(MAKE) + diff --git a/src/sflow/hsflowd/patch/series b/src/sflow/hsflowd/patch/series new file mode 100644 index 000000000000..90f9e47462e5 --- /dev/null +++ b/src/sflow/hsflowd/patch/series @@ -0,0 +1,2 @@ +0001-host_sflow_psample.patch +0002-host_sflow_debian.patch diff --git a/src/sflow/psample/.gitignore b/src/sflow/psample/.gitignore new file mode 100644 index 000000000000..eec3a10fb01e --- /dev/null +++ b/src/sflow/psample/.gitignore @@ -0,0 +1,8 @@ +* +!.gitignore +!debian/changelog +!debian/compat +!debian/control +!debian/psample.install +!debian/rules +!Makefile diff --git a/src/sflow/psample/Makefile b/src/sflow/psample/Makefile new file mode 100644 index 000000000000..bbdefde2289b --- /dev/null +++ b/src/sflow/psample/Makefile @@ -0,0 +1,20 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(PSAMPLE) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + + rm -fr ./libpsample + git clone https://github.com/Mellanox/libpsample.git + cp -r debian libpsample + + pushd ./libpsample + git checkout -b libpsample -f e48fad2 + + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $* $(DEST)/ + diff --git a/src/sflow/psample/debian/changelog b/src/sflow/psample/debian/changelog new file mode 100644 index 000000000000..be9af0d6d42a --- /dev/null +++ b/src/sflow/psample/debian/changelog @@ -0,0 +1,6 @@ +psample (1.1-1) UNRELEASED; urgency=medium + + [ DellEMC ] + * Initial release : based on https://github.com/Mellanox/libpsample + + -- DellEMC Mon, 29 Jul 2019 07:08:02 -0400 diff --git a/src/sflow/psample/debian/compat b/src/sflow/psample/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/src/sflow/psample/debian/compat @@ -0,0 +1 @@ +9 diff --git a/src/sflow/psample/debian/control b/src/sflow/psample/debian/control new file mode 100644 index 000000000000..5c65e1e774a6 --- /dev/null +++ b/src/sflow/psample/debian/control @@ -0,0 +1,11 @@ +Source: psample +Maintainer: DellEMC +Section: devel +Priority: optional +Build-Depends: dh-exec (>=0.3), debhelper (>= 9), autotools-dev +Standards-Version: 1.0.0 + +Package: psample +Architecture: any +Depends: ${shlibs:Depends} +Description: This package contains psample from https://github.com/Mellanox/libpsample diff --git a/src/sflow/psample/debian/psample.install b/src/sflow/psample/debian/psample.install new file mode 100644 index 000000000000..36d4eac1a85b --- /dev/null +++ b/src/sflow/psample/debian/psample.install @@ -0,0 +1,4 @@ +bin/psample usr/bin +lib/libpsample.so.1.0 lib/x86_64-linux-gnu +lib/libpsample.so.1 lib/x86_64-linux-gnu +lib/libpsample.so lib/x86_64-linux-gnu diff --git a/src/sflow/psample/debian/rules b/src/sflow/psample/debian/rules new file mode 100755 index 000000000000..73f484d32581 --- /dev/null +++ b/src/sflow/psample/debian/rules @@ -0,0 +1,19 @@ +#!/usr/bin/make -f + +# main packaging script based on dh7 syntax +%: + dh $@ + +override_dh_auto_build: + cmake . && make + +override_dh_auto_install: + +override_dh_auto_test: + +override_dh_auto_clean: + +override_dh_strip: + +override_dh_clean: + diff --git a/src/sflow/sflowtool/.gitignore b/src/sflow/sflowtool/.gitignore new file mode 100644 index 000000000000..138e705d63f0 --- /dev/null +++ b/src/sflow/sflowtool/.gitignore @@ -0,0 +1,8 @@ +* +!.gitignore +!debian/changelog +!debian/compat +!debian/control +!debian/sflowtool.install +!debian/rules +!Makefile diff --git a/src/sflow/sflowtool/Makefile b/src/sflow/sflowtool/Makefile new file mode 100644 index 000000000000..5f2ad995a585 --- /dev/null +++ b/src/sflow/sflowtool/Makefile @@ -0,0 +1,19 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = $(SFLOWTOOL) + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + + rm -fr ./sflowtool + git clone https://github.com/sflow/sflowtool + cp -r debian sflowtool + + pushd ./sflowtool + git checkout -b sflowtool -f 6c2963b + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $* $(DEST)/ + diff --git a/src/sflow/sflowtool/debian/changelog b/src/sflow/sflowtool/debian/changelog new file mode 100644 index 000000000000..df40c7c37de1 --- /dev/null +++ b/src/sflow/sflowtool/debian/changelog @@ -0,0 +1,6 @@ +sflowtool (5.04) UNRELEASED; urgency=medium + + [ DellEMC ] + * Initial release : based on https://github.com/sflow/sflowtool + + -- DellEMC Mon, 29 Jul 2019 07:08:02 -0400 diff --git a/src/sflow/sflowtool/debian/compat b/src/sflow/sflowtool/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/src/sflow/sflowtool/debian/compat @@ -0,0 +1 @@ +9 diff --git a/src/sflow/sflowtool/debian/control b/src/sflow/sflowtool/debian/control new file mode 100644 index 000000000000..f2d971aee2bd --- /dev/null +++ b/src/sflow/sflowtool/debian/control @@ -0,0 +1,11 @@ +Source: sflowtool +Maintainer: DellEMC +Section: devel +Priority: optional +Build-Depends: dh-exec (>=0.3), debhelper (>= 9), autotools-dev +Standards-Version: 1.0.0 + +Package: sflowtool +Architecture: any +Depends: ${shlibs:Depends} +Description: This package contains sflowtool from https://github.com/sflow/sflowtool diff --git a/src/sflow/sflowtool/debian/rules b/src/sflow/sflowtool/debian/rules new file mode 100755 index 000000000000..37ee344a2a4a --- /dev/null +++ b/src/sflow/sflowtool/debian/rules @@ -0,0 +1,19 @@ +#!/usr/bin/make -f + +# main packaging script based on dh7 syntax +%: + dh $@ + +override_dh_auto_build: + ./boot.sh && ./configure && make + +override_dh_auto_install: + +override_dh_auto_test: + +override_dh_auto_clean: + +override_dh_strip: + +override_dh_clean: + diff --git a/src/sflow/sflowtool/debian/sflowtool.install b/src/sflow/sflowtool/debian/sflowtool.install new file mode 100644 index 000000000000..9b32e0709b5a --- /dev/null +++ b/src/sflow/sflowtool/debian/sflowtool.install @@ -0,0 +1 @@ +src/sflowtool usr/bin diff --git a/src/smartmontools/.gitignore b/src/smartmontools/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/smartmontools/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/smartmontools/Makefile b/src/smartmontools/Makefile new file mode 100644 index 000000000000..8f0f0695659f --- /dev/null +++ b/src/smartmontools/Makefile @@ -0,0 +1,19 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + + +MAIN_TARGET = smartmontools_$(SMARTMONTOOLS_VERSION_FULL)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf smartmontools-$(SMARTMONTOOLS_VERSION_MAJOR) + wget -O smartmontools_$(SMARTMONTOOLS_VERSION_MAJOR).orig.tar.gz -N "https://sonicstorage.blob.core.windows.net/packages/debian/smartmontools_$(SMARTMONTOOLS_VERSION_MAJOR).orig.tar.gz?sv=2015-04-05&sr=b&sig=JZx4qiLuO36T0rsGqk4V2RDuWjRw6NztsLK7vlBYAkg%3D&se=2046-08-20T23%3A47%3A13Z&sp=r" + wget -O smartmontools_$(SMARTMONTOOLS_VERSION_FULL).dsc -N "https://sonicstorage.blob.core.windows.net/packages/debian/smartmontools_$(SMARTMONTOOLS_VERSION_FULL).dsc?sv=2015-04-05&sr=b&sig=IS7FKUN%2Bvq0T55f4X2hGAViB70Y%2FgzjGgvzpUJLyUfA%3D&se=2046-08-20T23%3A46%3A57Z&sp=r" + wget -O smartmontools_$(SMARTMONTOOLS_VERSION_FULL).debian.tar.xz -N "https://sonicstorage.blob.core.windows.net/packages/debian/smartmontools_$(SMARTMONTOOLS_VERSION_FULL).debian.tar.xz?sv=2015-04-05&sr=b&sig=H0RFeC41MCvhTQCln85DuPLn5v2goozwz%2FB9sA9p5eQ%3D&se=2046-08-20T23%3A46%3A02Z&sp=r" + dpkg-source -x smartmontools_$(SMARTMONTOOLS_VERSION_FULL).dsc + + pushd smartmontools-$(SMARTMONTOOLS_VERSION_MAJOR) + dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + mv $* $(DEST)/ diff --git a/src/snmpd/.gitignore b/src/snmpd/.gitignore new file mode 100644 index 000000000000..a0991ff4402b --- /dev/null +++ b/src/snmpd/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!Makefile diff --git a/src/snmpd/Makefile b/src/snmpd/Makefile new file mode 100644 index 000000000000..2e0ac828169c --- /dev/null +++ b/src/snmpd/Makefile @@ -0,0 +1,41 @@ +SHELL = /bin/bash +.ONESHELL: +.SHELLFLAGS += -e + +MAIN_TARGET = libsnmp-base_$(SNMPD_VERSION_FULL)_all.deb +DERIVED_TARGETS = snmptrapd_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + snmp_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + snmpd_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + snmp-dbgsym_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + snmpd-dbgsym_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + libsnmp30_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + libsnmp30-dbg_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + libsnmp-dev_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + libsnmp-perl_$(SNMPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb \ + tkmib_$(SNMPD_VERSION_FULL)_all.deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + rm -rf net-snmp-$(SNMPD_VERSION) + + # download debian net-snmp + dget -u https://sonicstorage.blob.core.windows.net/debian/pool/main/n/net-snmp/net-snmp_$(SNMPD_VERSION_FULL).dsc + + pushd net-snmp-$(SNMPD_VERSION) + git init + git add -f * + git commit -m "unmodified snmpd source" + + # Apply patches + stg init + stg import -s ../patch-$(SNMPD_VERSION)/series + +ifeq ($(CONFIGURED_ARCH), arm64) + dpkg-buildpackage -rfakeroot -b -d -us -uc -j1 --admindir $(SONIC_DPKG_ADMINDIR) +else + dpkg-buildpackage -rfakeroot -b -d -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) +endif + popd + + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/snmpd/patch-5.7.3+dfsg/0001-SNMP-Stop-spamming-logs-with-statfs-permission-denie.patch b/src/snmpd/patch-5.7.3+dfsg/0001-SNMP-Stop-spamming-logs-with-statfs-permission-denie.patch new file mode 100644 index 000000000000..f832d0044071 --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/0001-SNMP-Stop-spamming-logs-with-statfs-permission-denie.patch @@ -0,0 +1,40 @@ +From a1edbce39e46b5c8bd5bd7db17fc11fa30e7dd73 Mon Sep 17 00:00:00 2001 +From: pavel-shirshov +Date: Mon, 27 Aug 2018 16:50:16 +0800 +Subject: [PATCH] [SNMP] Stop spamming logs with statfs permission denied log + message #1668 + +--- + agent/mibgroup/hardware/fsys/fsys_mntctl.c | 2 -- + agent/mibgroup/hardware/fsys/fsys_mntent.c | 2 -- + 2 files changed, 4 deletions(-) + +diff --git a/agent/mibgroup/hardware/fsys/fsys_mntctl.c b/agent/mibgroup/hardware/fsys/fsys_mntctl.c +index 9fbb068..adc38d6 100644 +--- a/agent/mibgroup/hardware/fsys/fsys_mntctl.c ++++ b/agent/mibgroup/hardware/fsys/fsys_mntctl.c +@@ -163,8 +163,6 @@ netsnmp_fsys_arch_load( void ) + continue; + + if ( statfs( entry->path, &stat_buf ) < 0 ) { +- snprintf( tmpbuf, sizeof(tmpbuf), "Cannot statfs %s", entry->path ); +- snmp_log_perror( tmpbuf ); + continue; + } + entry->units = stat_buf.f_bsize; +diff --git a/agent/mibgroup/hardware/fsys/fsys_mntent.c b/agent/mibgroup/hardware/fsys/fsys_mntent.c +index 94d23db..5ad5e43 100644 +--- a/agent/mibgroup/hardware/fsys/fsys_mntent.c ++++ b/agent/mibgroup/hardware/fsys/fsys_mntent.c +@@ -238,8 +238,6 @@ netsnmp_fsys_arch_load( void ) + if ( NSFS_STATFS( entry->path, &stat_buf ) < 0 ) + #endif + { +- snprintf( tmpbuf, sizeof(tmpbuf), "Cannot statfs %s", entry->path ); +- snmp_log_perror( tmpbuf ); + continue; + } + entry->units = stat_buf.NSFS_SIZE; +-- +2.7.4 + diff --git a/src/snmpd/patch-5.7.3+dfsg/0002-at.c-properly-check-return-status-from-realloc.-Than.patch b/src/snmpd/patch-5.7.3+dfsg/0002-at.c-properly-check-return-status-from-realloc.-Than.patch new file mode 100644 index 000000000000..ceb0c68352bf --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/0002-at.c-properly-check-return-status-from-realloc.-Than.patch @@ -0,0 +1,31 @@ +From e370973f273ffc1b32673bc94c5a46f75a846d82 Mon Sep 17 00:00:00 2001 +From: Niels Baggesen +Date: Wed, 31 Aug 2016 21:43:36 +0200 +Subject: [PATCH] at.c: properly check return status from realloc. Thanks to + Daniel Eiland (bug 2678) + +--- + agent/mibgroup/mibII/at.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/agent/mibgroup/mibII/at.c b/agent/mibgroup/mibII/at.c +index f57ba2a..a73fb8c 100644 +--- a/agent/mibgroup/mibII/at.c ++++ b/agent/mibgroup/mibII/at.c +@@ -638,11 +638,12 @@ ARP_Scan_Init(void) + struct arptab *newtab = (struct arptab *) + realloc(at, (sizeof(struct arptab) * + (arptab_curr_max_size + ARP_CACHE_INCR))); +- if (newtab == at) { ++ if (newtab == NULL) { + snmp_log(LOG_ERR, + "Error allocating more space for arpcache. " + "Cache will continue to be limited to %d entries", + arptab_curr_max_size); ++ newtab = at; + break; + } else { + arptab_curr_max_size += ARP_CACHE_INCR; +-- +2.7.4 + diff --git a/src/snmpd/patch-5.7.3+dfsg/0003-CHANGES-BUG-2743-snmpd-crashes-when-receiving-a-GetN.patch b/src/snmpd/patch-5.7.3+dfsg/0003-CHANGES-BUG-2743-snmpd-crashes-when-receiving-a-GetN.patch new file mode 100644 index 000000000000..cdf9b94be934 --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/0003-CHANGES-BUG-2743-snmpd-crashes-when-receiving-a-GetN.patch @@ -0,0 +1,36 @@ +From 2170e345858738e65d3156a49d3186e4a9288821 Mon Sep 17 00:00:00 2001 +From: Zhenggen Xu +Date: Fri, 12 Oct 2018 17:13:54 -0700 +Subject: [PATCH] Subject: [PATCH] CHANGES: BUG: 2743: snmpd crashes when + receiving a GetNext PDU with multiple Varbinds + +skip out-of-range varbinds when calling next handler +--- + agent/helpers/table.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/agent/helpers/table.c b/agent/helpers/table.c +index 882e84c..b943d6e 100644 +--- a/agent/helpers/table.c ++++ b/agent/helpers/table.c +@@ -406,6 +406,8 @@ table_helper_handler(netsnmp_mib_handler *handler, + if (reqinfo->mode == MODE_GET) + table_helper_cleanup(reqinfo, request, + SNMP_NOSUCHOBJECT); ++ else ++ request->processed = 1; /* skip if next handler called */ + continue; + } + +@@ -483,6 +485,8 @@ table_helper_handler(netsnmp_mib_handler *handler, + #endif /* NETSNMP_NO_WRITE_SUPPORT */ + table_helper_cleanup(reqinfo, request, + SNMP_NOSUCHOBJECT); ++ else ++ request->processed = 1; /* skip if next handler called */ + continue; + } + /* +-- +2.18.0 + diff --git a/src/snmpd/patch-5.7.3+dfsg/0006-From-Jiri-Cervenka-snmpd-Fixed-agentx-crashing-and-or-freezing-on-timeout.patch b/src/snmpd/patch-5.7.3+dfsg/0006-From-Jiri-Cervenka-snmpd-Fixed-agentx-crashing-and-or-freezing-on-timeout.patch new file mode 100644 index 000000000000..d11a9d6d75e9 --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/0006-From-Jiri-Cervenka-snmpd-Fixed-agentx-crashing-and-or-freezing-on-timeout.patch @@ -0,0 +1,211 @@ +From a5782d0673044ad0c621daed7975f53238bb038e Mon Sep 17 00:00:00 2001 +From: Renuka Manavalan +Date: Tue, 10 Sep 2019 17:51:45 +0000 +Subject: [PATCH] Patch from SourceForge: net-snmp commit #793d59 Avoids snmpd + crash when sub agent timesout. + +--- + agent/mibgroup/agentx/master_admin.c | 1 + + agent/snmp_agent.c | 81 ++++++++++++++++++---------- + include/net-snmp/agent/snmp_agent.h | 5 ++ + 3 files changed, 60 insertions(+), 27 deletions(-) + +diff --git a/agent/mibgroup/agentx/master_admin.c b/agent/mibgroup/agentx/master_admin.c +index 4dc1aa7..8c1d194 100644 +--- a/agent/mibgroup/agentx/master_admin.c ++++ b/agent/mibgroup/agentx/master_admin.c +@@ -158,6 +158,7 @@ close_agentx_session(netsnmp_session * session, int sessid) + for (sp = session->subsession; sp != NULL; sp = sp->next) { + + if (sp->sessid == sessid) { ++ netsnmp_remove_delegated_requests_for_session(sp); + unregister_mibs_by_session(sp); + unregister_index_by_session(sp); + unregister_sysORTable_by_session(sp); +diff --git a/agent/snmp_agent.c b/agent/snmp_agent.c +index b96d650..7cacd1a 100644 +--- a/agent/snmp_agent.c ++++ b/agent/snmp_agent.c +@@ -1409,6 +1409,7 @@ init_agent_snmp_session(netsnmp_session * session, netsnmp_pdu *pdu) + asp->treecache_num = -1; + asp->treecache_len = 0; + asp->reqinfo = SNMP_MALLOC_TYPEDEF(netsnmp_agent_request_info); ++ asp->flags = SNMP_AGENT_FLAGS_NONE; + DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p created\n", + asp, asp->reqinfo)); + +@@ -1457,6 +1458,9 @@ netsnmp_check_for_delegated(netsnmp_agent_session *asp) + + if (NULL == asp->treecache) + return 0; ++ ++ if (asp->flags & SNMP_AGENT_FLAGS_CANCEL_IN_PROGRESS) ++ return 0; + + for (i = 0; i <= asp->treecache_num; i++) { + for (request = asp->treecache[i].requests_begin; request; +@@ -1535,39 +1539,48 @@ int + netsnmp_remove_delegated_requests_for_session(netsnmp_session *sess) + { + netsnmp_agent_session *asp; +- int count = 0; ++ int total_count = 0; + + for (asp = agent_delegated_list; asp; asp = asp->next) { + /* + * check each request + */ ++ int i; ++ int count = 0; + netsnmp_request_info *request; +- for(request = asp->requests; request; request = request->next) { +- /* +- * check session +- */ +- netsnmp_assert(NULL!=request->subtree); +- if(request->subtree->session != sess) +- continue; ++ for (i = 0; i <= asp->treecache_num; i++) { ++ for (request = asp->treecache[i].requests_begin; request; ++ request = request->next) { ++ /* ++ * check session ++ */ ++ netsnmp_assert(NULL!=request->subtree); ++ if(request->subtree->session != sess) ++ continue; + +- /* +- * matched! mark request as done +- */ +- netsnmp_request_set_error(request, SNMP_ERR_GENERR); +- ++count; ++ /* ++ * matched! mark request as done ++ */ ++ netsnmp_request_set_error(request, SNMP_ERR_GENERR); ++ ++count; ++ } ++ } ++ if (count) { ++ asp->flags |= SNMP_AGENT_FLAGS_CANCEL_IN_PROGRESS; ++ total_count += count; + } + } + + /* + * if we found any, that request may be finished now + */ +- if(count) { ++ if(total_count) { + DEBUGMSGTL(("snmp_agent", "removed %d delegated request(s) for session " +- "%8p\n", count, sess)); +- netsnmp_check_outstanding_agent_requests(); ++ "%8p\n", total_count, sess)); ++ netsnmp_check_delegated_requests(); + } + +- return count; ++ return total_count; + } + + int +@@ -2739,19 +2752,11 @@ handle_var_requests(netsnmp_agent_session *asp) + return final_status; + } + +-/* +- * loop through our sessions known delegated sessions and check to see +- * if they've completed yet. If there are no more delegated sessions, +- * check for and process any queued requests +- */ + void +-netsnmp_check_outstanding_agent_requests(void) ++netsnmp_check_delegated_requests(void) + { + netsnmp_agent_session *asp, *prev_asp = NULL, *next_asp = NULL; + +- /* +- * deal with delegated requests +- */ + for (asp = agent_delegated_list; asp; asp = next_asp) { + next_asp = asp->next; /* save in case we clean up asp */ + if (!netsnmp_check_for_delegated(asp)) { +@@ -2790,6 +2795,23 @@ netsnmp_check_outstanding_agent_requests(void) + prev_asp = asp; + } + } ++} ++ ++ ++/* ++ * loop through our sessions known delegated sessions and check to see ++ * if they've completed yet. If there are no more delegated sessions, ++ * check for and process any queued requests ++ */ ++void ++netsnmp_check_outstanding_agent_requests(void) ++{ ++ netsnmp_agent_session *asp; ++ ++ /* ++ * deal with delegated requests ++ */ ++ netsnmp_check_delegated_requests(); + + /* + * if we are processing a set and there are more delegated +@@ -2819,7 +2841,8 @@ netsnmp_check_outstanding_agent_requests(void) + + netsnmp_processing_set = netsnmp_agent_queued_list; + DEBUGMSGTL(("snmp_agent", "SET request remains queued while " +- "delegated requests finish, asp = %8p\n", asp)); ++ "delegated requests finish, asp = %8p\n", ++ agent_delegated_list)); + break; + } + #endif /* NETSNMP_NO_WRITE_SUPPORT */ +@@ -2880,6 +2903,10 @@ check_delayed_request(netsnmp_agent_session *asp) + case SNMP_MSG_GETBULK: + case SNMP_MSG_GETNEXT: + netsnmp_check_all_requests_status(asp, 0); ++ if (asp->flags & SNMP_AGENT_FLAGS_CANCEL_IN_PROGRESS) { ++ DEBUGMSGTL(("snmp_agent","canceling next walk for asp %p\n", asp)); ++ break; ++ } + handle_getnext_loop(asp); + if (netsnmp_check_for_delegated(asp) && + netsnmp_check_transaction_id(asp->pdu->transid) != +diff --git a/include/net-snmp/agent/snmp_agent.h b/include/net-snmp/agent/snmp_agent.h +index aad8837..43f4fff 100644 +--- a/include/net-snmp/agent/snmp_agent.h ++++ b/include/net-snmp/agent/snmp_agent.h +@@ -32,6 +32,9 @@ extern "C" { + #define SNMP_MAX_PDU_SIZE 64000 /* local constraint on PDU size sent by agent + * (see also SNMP_MAX_MSG_SIZE in snmp_api.h) */ + ++#define SNMP_AGENT_FLAGS_NONE 0x0 ++#define SNMP_AGENT_FLAGS_CANCEL_IN_PROGRESS 0x1 ++ + /* + * If non-zero, causes the addresses of peers to be logged when receptions + * occur. +@@ -205,6 +208,7 @@ extern "C" { + int treecache_num; /* number of current cache entries */ + netsnmp_cachemap *cache_store; + int vbcount; ++ int flags; + } netsnmp_agent_session; + + /* +@@ -240,6 +244,7 @@ extern "C" { + int init_master_agent(void); + void shutdown_master_agent(void); + int agent_check_and_process(int block); ++ void netsnmp_check_delegated_requests(void); + void netsnmp_check_outstanding_agent_requests(void); + + int netsnmp_request_set_error(netsnmp_request_info *request, +-- +2.17.1 + diff --git a/src/snmpd/patch-5.7.3+dfsg/0007-Linux-VRF-5.7.3-Support.patch b/src/snmpd/patch-5.7.3+dfsg/0007-Linux-VRF-5.7.3-Support.patch new file mode 100755 index 000000000000..48d13d7f62d6 --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/0007-Linux-VRF-5.7.3-Support.patch @@ -0,0 +1,799 @@ +From 49ce7fc078dfa8c1a1688e05de4e2d151dbcd76a Mon Sep 17 00:00:00 2001 +From: Harish Venkatraman +Date: Wed, 17 Oct 2018 15:22:04 -0700 +Subject: [PATCH] Linux-VRF 5.7.3 Support from https://sourceforge.net/p/net-snmp/patches/1376/ + +Sourceforge commits related to this consolidated patch are given below. +https://sourceforge.net/p/net-snmp/code/ci/0b637fea62c7b6dc467b94206d0bd2dec6f912ca/ +https://sourceforge.net/p/net-snmp/code/ci/19ba7b0a6b56d201a8563fe6505cd82e313c1c9c/ +https://sourceforge.net/p/net-snmp/code/ci/76336fb63bb74b4dede5dda5c14fb8cf2d60be8e/ +https://sourceforge.net/p/net-snmp/code/ci/c7398de4122102b3250e6dac7c09dbc5d09f1840/ +https://sourceforge.net/p/net-snmp/code/ci/0831ed64a39a34dc040eabe39d0229b07fa2a8a5/ +https://sourceforge.net/p/net-snmp/code/ci/62f6babcc7cfc54c79b442b8a7f45662b4ddc807/ +https://sourceforge.net/p/net-snmp/code/ci/313949522c4d0ddfeac72195fa63512955d9eb28/ + + +This consolidated patch adds native support for VRFs to snmpd. NCLU patches in this same +CCR will be added shortly. The VRF is specified for both listening +addresses as well as TRAP sinks with the 'ipaddr%iface' syntax: + +agentAddress 10.0.1.7%mgmt,22.22.22.22%red +trapsink 10.0.1.9%mgmt +trap2sink 22.22.22.25%red + +The SO_BINDTODEVICE socket option is used to bind a VRF to a particular +socket. + +Testing done included VRFs as well as non-VRF functionality with traps +(v1, v2, and v3) + +--- + agent/agent_trap.c | 20 ++++++++++-- + agent/mibgroup/agentx/master.c | 2 +- + agent/mibgroup/agentx/subagent.c | 2 +- + agent/mibgroup/target/target.c | 3 +- + agent/snmp_agent.c | 21 ++++++++++++- + apps/agentxtrap.c | 2 +- + apps/snmptrap.c | 2 +- + apps/snmptrapd.c | 2 +- + include/net-snmp/library/snmpTCPDomain.h | 2 +- + include/net-snmp/library/snmpUDPBaseDomain.h | 2 +- + include/net-snmp/library/snmpUDPDomain.h | 2 +- + include/net-snmp/library/snmpUDPIPv4BaseDomain.h | 2 +- + include/net-snmp/library/snmpUDPIPv6Domain.h | 2 +- + include/net-snmp/library/snmp_transport.h | 19 +++++++----- + snmplib/snmp_api.c | 4 +-- + snmplib/snmp_transport.c | 26 ++++++++-------- + snmplib/transports/snmpAliasDomain.c | 6 ++-- + snmplib/transports/snmpTCPDomain.c | 16 +++++++--- + snmplib/transports/snmpUDPBaseDomain.c | 39 ++++++++++++++++++------ + snmplib/transports/snmpUDPDomain.c | 15 ++++----- + snmplib/transports/snmpUDPIPv4BaseDomain.c | 4 +-- + snmplib/transports/snmpUDPIPv6Domain.c | 19 ++++----- + snmplib/transports/snmpUnixDomain.c | 5 +-- + 23 files changed, 141 insertions(+), 76 deletions(-) + +diff --git a/agent/agent_trap.c b/agent/agent_trap.c +index 080b8bf..c488ac9 100644 +--- a/agent/agent_trap.c ++++ b/agent/agent_trap.c +@@ -226,6 +226,7 @@ create_trap_session2(const char *sink, const char* sinkport, + { + netsnmp_transport *t; + netsnmp_session session, *sesp; ++ char *iface; + + memset(&session, 0, sizeof(netsnmp_session)); + session.version = version; +@@ -250,7 +251,14 @@ create_trap_session2(const char *sink, const char* sinkport, + ((0 == strcmp("localhost",sink)) || (0 == strcmp("127.0.0.1",sink)))) + session.localname = strdup("localhost"); + +- t = netsnmp_tdomain_transport_full("snmptrap", sink, 0, NULL, sinkport); ++ /* ++ * if given an iface (ip%iface) in sink, send the iface too ++ */ ++ iface = strchr(sink, '%'); ++ if (iface) ++ *iface++ = '\0'; ++ ++ t = netsnmp_tdomain_transport_full("snmptrap", sink, 0, NULL, sinkport, iface); + if (t != NULL) { + sesp = snmp_add(&session, t, NULL, NULL); + +@@ -1219,6 +1227,7 @@ snmpd_parse_config_trapsess(const char *word, char *cptr) + netsnmp_session session, *ss; + netsnmp_transport *transport; + size_t len; ++ char *iface; + + /* + * inform or trap? default to trap +@@ -1240,7 +1249,14 @@ snmpd_parse_config_trapsess(const char *word, char *cptr) + NETSNMP_PARSE_ARGS_NOLOGGING | + NETSNMP_PARSE_ARGS_NOZERO); + +- transport = netsnmp_transport_open_client("snmptrap", session.peername); ++ /* ++ * if iface is given in peer, we will need to bind to that iface ++ */ ++ iface = strchr(session.peername, '%'); ++ if (iface) ++ *iface++ = '\0'; ++ ++ transport = netsnmp_transport_open_client("snmptrap", session.peername, iface); + if (transport == NULL) { + config_perror("snmpd: failed to parse this line."); + return; +diff --git a/agent/mibgroup/agentx/master.c b/agent/mibgroup/agentx/master.c +index baeebaf..6733e7f 100644 +--- a/agent/mibgroup/agentx/master.c ++++ b/agent/mibgroup/agentx/master.c +@@ -126,7 +126,7 @@ real_init_master(void) + sess.remote_port = 0; + sess.callback = handle_master_agentx_packet; + errno = 0; +- t = netsnmp_transport_open_server("agentx", sess.peername); ++ t = netsnmp_transport_open_server("agentx", sess.peername, NULL); + if (t == NULL) { + /* + * diagnose snmp_open errors with the input netsnmp_session +diff --git a/agent/mibgroup/agentx/subagent.c b/agent/mibgroup/agentx/subagent.c +index 1f9d31c..6d38a34 100644 +--- a/agent/mibgroup/agentx/subagent.c ++++ b/agent/mibgroup/agentx/subagent.c +@@ -843,7 +843,7 @@ subagent_open_master_session(void) + + agentx_socket = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, + NETSNMP_DS_AGENT_X_SOCKET); +- t = netsnmp_transport_open_client("agentx", agentx_socket); ++ t = netsnmp_transport_open_client("agentx", agentx_socket, NULL); + if (t == NULL) { + /* + * Diagnose snmp_open errors with the input +diff --git a/agent/mibgroup/target/target.c b/agent/mibgroup/target/target.c +index 5619e35..6f58817 100644 +--- a/agent/mibgroup/target/target.c ++++ b/agent/mibgroup/target/target.c +@@ -154,7 +154,8 @@ get_target_sessions(char *taglist, TargetFilterFunction * filterfunct, + tAddress, + targaddrs-> + tAddressLen, +- 0); ++ 0, ++ NULL); + if (t == NULL) { + DEBUGMSGTL(("target_sessions", + "bad dest \"")); +diff --git a/agent/snmp_agent.c b/agent/snmp_agent.c +index b96d650..281e8b2 100644 +--- a/agent/snmp_agent.c ++++ b/agent/snmp_agent.c +@@ -1270,6 +1270,7 @@ init_master_agent(void) + char *cptr; + char *buf = NULL; + char *st; ++ char *iface; + + /* default to a default cache size */ + netsnmp_set_lookup_cache_size(-1); +@@ -1318,6 +1319,9 @@ init_master_agent(void) + * AAL5PVC:itf.vpi.vci (if supported) + * IPX:[network]:node[/port] (if supported) + * ++ * ++ * New format to specify an interface for binding along with IP address ++ * address%iface + */ + + cptr = st; +@@ -1334,7 +1338,22 @@ init_master_agent(void) + "requested\n")); + break; + } +- transport = netsnmp_transport_open_server("snmp", cptr); ++ ++ /* ++ * at some point, we may want to add the special listendevice ++ * keyword support. Not sure how to interact with ip%iface ++ iface = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, ++ NETSNMP_DS_AGENT_LISTEN_DEVICE); ++ */ ++ ++ /* Look for %iface so we can send along a specific interface to ++ setsockopt SO_BINDTODEVICE later. */ ++ iface = strchr(cptr, '%'); ++ if (iface) ++ *iface++ = '\0'; ++ ++ transport = netsnmp_transport_open_server("snmp", cptr, iface); ++ + + if (transport == NULL) { + snmp_log(LOG_ERR, "Error opening specified endpoint \"%s\"\n", +diff --git a/apps/agentxtrap.c b/apps/agentxtrap.c +index 4df423c..ebd81a3 100644 +--- a/apps/agentxtrap.c ++++ b/apps/agentxtrap.c +@@ -231,7 +231,7 @@ ConnectingEntry(UNUSED tState self) + + if(!(t = netsnmp_transport_open_client( + "agentx", netsnmp_ds_get_string( +- NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET)))) { ++ NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET), NULL))) { + snmp_log(LOG_ERR, "Failed to connect to AgentX server\n"); + change_state(&Exit); + } else if(!(sess = snmp_sess_add_ex( +diff --git a/apps/snmptrap.c b/apps/snmptrap.c +index 7c086db..28d5257 100644 +--- a/apps/snmptrap.c ++++ b/apps/snmptrap.c +@@ -215,7 +215,7 @@ main(int argc, char *argv[]) + } + + ss = snmp_add(&session, +- netsnmp_transport_open_client("snmptrap", session.peername), ++ netsnmp_transport_open_client("snmptrap", session.peername, NULL), + NULL, NULL); + if (ss == NULL) { + /* +diff --git a/apps/snmptrapd.c b/apps/snmptrapd.c +index bce0d47..122a502 100644 +--- a/apps/snmptrapd.c ++++ b/apps/snmptrapd.c +@@ -1186,7 +1186,7 @@ main(int argc, char *argv[]) + *sep = 0; + } + +- transport = netsnmp_transport_open_server("snmptrap", cp); ++ transport = netsnmp_transport_open_server("snmptrap", cp, NULL); + if (transport == NULL) { + snmp_log(LOG_ERR, "couldn't open %s -- errno %d (\"%s\")\n", + cp, errno, strerror(errno)); +diff --git a/include/net-snmp/library/snmpTCPDomain.h b/include/net-snmp/library/snmpTCPDomain.h +index c45856b..3b1fef5 100644 +--- a/include/net-snmp/library/snmpTCPDomain.h ++++ b/include/net-snmp/library/snmpTCPDomain.h +@@ -25,7 +25,7 @@ extern "C" { + #define TRANSPORT_DOMAIN_TCP_IP 1,3,6,1,2,1,100,1,5 + NETSNMP_IMPORT oid netsnmp_snmpTCPDomain[]; + +-netsnmp_transport *netsnmp_tcp_transport(struct sockaddr_in *addr, int local); ++netsnmp_transport *netsnmp_tcp_transport(struct sockaddr_in *addr, int local, char *iface); + + /* + * "Constructor" for transport domain object. +diff --git a/include/net-snmp/library/snmpUDPBaseDomain.h b/include/net-snmp/library/snmpUDPBaseDomain.h +index b9d2c34..0ab2fe5 100644 +--- a/include/net-snmp/library/snmpUDPBaseDomain.h ++++ b/include/net-snmp/library/snmpUDPBaseDomain.h +@@ -18,7 +18,7 @@ extern "C" { + /* + * Prototypes + */ +- void _netsnmp_udp_sockopt_set(int fd, int local); ++ void _netsnmp_udp_sockopt_set(int fd, int local, char *iface); + int netsnmp_udpbase_recv(netsnmp_transport *t, void *buf, int size, + void **opaque, int *olength); + int netsnmp_udpbase_send(netsnmp_transport *t, void *buf, int size, +diff --git a/include/net-snmp/library/snmpUDPDomain.h b/include/net-snmp/library/snmpUDPDomain.h +index 3a09dfd..e402cd8 100644 +--- a/include/net-snmp/library/snmpUDPDomain.h ++++ b/include/net-snmp/library/snmpUDPDomain.h +@@ -18,7 +18,7 @@ extern "C" { + config_require(UDPIPv4Base) + #include + +-netsnmp_transport *netsnmp_udp_transport(struct sockaddr_in *addr, int local); ++netsnmp_transport *netsnmp_udp_transport(struct sockaddr_in *addr, int local, char*iface); + + + /* +diff --git a/include/net-snmp/library/snmpUDPIPv4BaseDomain.h b/include/net-snmp/library/snmpUDPIPv4BaseDomain.h +index 6f7f2c2..8d3e906 100644 +--- a/include/net-snmp/library/snmpUDPIPv4BaseDomain.h ++++ b/include/net-snmp/library/snmpUDPIPv4BaseDomain.h +@@ -25,7 +25,7 @@ extern "C" { + */ + + netsnmp_transport *netsnmp_udpipv4base_transport(struct sockaddr_in *addr, +- int local); ++ int local, char *iface); + + #if defined(HAVE_IP_PKTINFO) || defined(HAVE_IP_RECVDSTADDR) + int netsnmp_udpipv4_recvfrom(int s, void *buf, int len, +diff --git a/include/net-snmp/library/snmpUDPIPv6Domain.h b/include/net-snmp/library/snmpUDPIPv6Domain.h +index 83eba2c..009c510 100644 +--- a/include/net-snmp/library/snmpUDPIPv6Domain.h ++++ b/include/net-snmp/library/snmpUDPIPv6Domain.h +@@ -23,7 +23,7 @@ config_require(UDPBase) + NETSNMP_IMPORT oid netsnmp_UDPIPv6Domain[]; + + netsnmp_transport *netsnmp_udp6_transport(struct sockaddr_in6 *addr, +- int local); ++ int local, char *iface); + + + /* +diff --git a/include/net-snmp/library/snmp_transport.h b/include/net-snmp/library/snmp_transport.h +index 4162897..a3deda7 100644 +--- a/include/net-snmp/library/snmp_transport.h ++++ b/include/net-snmp/library/snmp_transport.h +@@ -206,14 +206,14 @@ typedef struct netsnmp_tdomain_s { + * The f_create_from_tstring field is deprecated, please do not use it + * for new code and try to migrate old code away from using it. + */ +- netsnmp_transport *(*f_create_from_tstring) (const char *, int); ++ netsnmp_transport *(*f_create_from_tstring) (const char *, int, char *); + +- netsnmp_transport *(*f_create_from_ostring) (const u_char *, size_t, int); ++ netsnmp_transport *(*f_create_from_ostring) (const u_char *, size_t, int, char *); + + struct netsnmp_tdomain_s *next; + + netsnmp_transport *(*f_create_from_tstring_new) (const char *, int, +- const char*); ++ const char*, char *); + + } netsnmp_tdomain; + +@@ -273,29 +273,32 @@ void netsnmp_tdomain_init(void); + NETSNMP_IMPORT + netsnmp_transport *netsnmp_tdomain_transport(const char *str, + int local, +- const char *default_domain); ++ const char *default_domain, ++ char *iface); + + NETSNMP_IMPORT + netsnmp_transport *netsnmp_tdomain_transport_full(const char *application, + const char *str, + int local, + const char *default_domain, +- const char *default_target); ++ const char *default_target, ++ char *iface); + + NETSNMP_IMPORT + netsnmp_transport *netsnmp_tdomain_transport_oid(const oid * dom, + size_t dom_len, + const u_char * o, + size_t o_len, +- int local); ++ int local, ++ char *iface); + + NETSNMP_IMPORT + netsnmp_transport* +-netsnmp_transport_open_client(const char* application, const char* str); ++netsnmp_transport_open_client(const char* application, const char* str, char *iface); + + NETSNMP_IMPORT + netsnmp_transport* +-netsnmp_transport_open_server(const char* application, const char* str); ++netsnmp_transport_open_server(const char* application, const char* str, char *iface); + + netsnmp_transport* + netsnmp_transport_open(const char* application, const char* str, int local); +diff --git a/snmplib/snmp_api.c b/snmplib/snmp_api.c +index d155c99..5128c56 100644 +--- a/snmplib/snmp_api.c ++++ b/snmplib/snmp_api.c +@@ -1557,12 +1557,12 @@ _sess_open(netsnmp_session * in_session) + transport = + netsnmp_tdomain_transport_full("snmp", in_session->peername, + in_session->local_port, "tcp,tcp6", +- NULL); ++ NULL, NULL); + } else { + transport = + netsnmp_tdomain_transport_full("snmp", in_session->peername, + in_session->local_port, "udp,udp6", +- NULL); ++ NULL, NULL); + } + + if (NULL != clientaddr_save) +diff --git a/snmplib/snmp_transport.c b/snmplib/snmp_transport.c +index ada4781..40cd631 100644 +--- a/snmplib/snmp_transport.c ++++ b/snmplib/snmp_transport.c +@@ -491,7 +491,8 @@ netsnmp_transport * + netsnmp_tdomain_transport_full(const char *application, + const char *str, int local, + const char *default_domain, +- const char *default_target) ++ const char *default_target, ++ char *iface) + { + netsnmp_tdomain *match = NULL; + const char *addr = NULL; +@@ -646,10 +647,10 @@ netsnmp_tdomain_transport_full(const char *application, + NETSNMP_LOGONCE((LOG_WARNING, + "transport domain %s uses deprecated f_create_from_tstring\n", + match->prefix[0])); +- t = match->f_create_from_tstring(addr, local); ++ t = match->f_create_from_tstring(addr, local, iface); + } + else +- t = match->f_create_from_tstring_new(addr, local, addr2); ++ t = match->f_create_from_tstring_new(addr, local, addr2, iface); + if (t) { + if (lspec) { + free(lspec[0]); +@@ -676,10 +677,11 @@ netsnmp_tdomain_transport_full(const char *application, + + netsnmp_transport * + netsnmp_tdomain_transport(const char *str, int local, +- const char *default_domain) ++ const char *default_domain, ++ char *iface) + { + return netsnmp_tdomain_transport_full("snmp", str, local, default_domain, +- NULL); ++ NULL, iface); + } + + +@@ -687,7 +689,7 @@ netsnmp_tdomain_transport(const char *str, int local, + netsnmp_transport * + netsnmp_tdomain_transport_oid(const oid * dom, + size_t dom_len, +- const u_char * o, size_t o_len, int local) ++ const u_char * o, size_t o_len, int local, char *iface) + { + netsnmp_tdomain *d; + int i; +@@ -700,7 +702,7 @@ netsnmp_tdomain_transport_oid(const oid * dom, + for (i = 0; d->prefix[i] != NULL; i++) { + if (netsnmp_oid_equals(dom, dom_len, d->name, d->name_length) == + 0) { +- return d->f_create_from_ostring(o, o_len, local); ++ return d->f_create_from_ostring(o, o_len, local, iface); + } + } + } +@@ -713,19 +715,19 @@ netsnmp_tdomain_transport_oid(const oid * dom, + netsnmp_transport* + netsnmp_transport_open(const char* application, const char* str, int local) + { +- return netsnmp_tdomain_transport_full(application, str, local, NULL, NULL); ++ return netsnmp_tdomain_transport_full(application, str, local, NULL, NULL, NULL); + } + + netsnmp_transport* +-netsnmp_transport_open_server(const char* application, const char* str) ++netsnmp_transport_open_server(const char* application, const char* str, char *iface) + { +- return netsnmp_tdomain_transport_full(application, str, 1, NULL, NULL); ++ return netsnmp_tdomain_transport_full(application, str, 1, NULL, NULL, iface); + } + + netsnmp_transport* +-netsnmp_transport_open_client(const char* application, const char* str) ++netsnmp_transport_open_client(const char* application, const char* str, char *iface) + { +- return netsnmp_tdomain_transport_full(application, str, 0, NULL, NULL); ++ return netsnmp_tdomain_transport_full(application, str, 0, NULL, NULL, iface); + } + + /** adds a transport to a linked list of transports. +diff --git a/snmplib/transports/snmpAliasDomain.c b/snmplib/transports/snmpAliasDomain.c +index eb50cad..dd7a007 100644 +--- a/snmplib/transports/snmpAliasDomain.c ++++ b/snmplib/transports/snmpAliasDomain.c +@@ -75,7 +75,7 @@ free_alias_config(void) { + + netsnmp_transport * + netsnmp_alias_create_tstring(const char *str, int local, +- const char *default_target) ++ const char *default_target, char *iface) + { + const char *aliasdata; + +@@ -85,13 +85,13 @@ netsnmp_alias_create_tstring(const char *str, int local, + return NULL; + } + +- return netsnmp_tdomain_transport(aliasdata,local,default_target); ++ return netsnmp_tdomain_transport(aliasdata,local,default_target, iface); + } + + + + netsnmp_transport * +-netsnmp_alias_create_ostring(const u_char * o, size_t o_len, int local) ++netsnmp_alias_create_ostring(const u_char * o, size_t o_len, int local, char *iface) + { + fprintf(stderr, "make ostring\n"); + return NULL; +diff --git a/snmplib/transports/snmpTCPDomain.c b/snmplib/transports/snmpTCPDomain.c +index 7feb028..6eb717e 100644 +--- a/snmplib/transports/snmpTCPDomain.c ++++ b/snmplib/transports/snmpTCPDomain.c +@@ -144,7 +144,7 @@ netsnmp_tcp_accept(netsnmp_transport *t) + */ + + netsnmp_transport * +-netsnmp_tcp_transport(struct sockaddr_in *addr, int local) ++netsnmp_tcp_transport(struct sockaddr_in *addr, int local, char *iface) + { + netsnmp_transport *t = NULL; + netsnmp_udp_addr_pair *addr_pair = NULL; +@@ -212,6 +212,11 @@ netsnmp_tcp_transport(struct sockaddr_in *addr, int local) + * We should set SO_REUSEADDR too. + */ + ++ if (iface && setsockopt(t->sock, SOL_SOCKET, SO_BINDTODEVICE, ++ iface, strlen(iface)) == -1) ++ snmp_log(LOG_ERR, "Bind interface %s to socket: %s\n", ++ iface, strerror(errno)); ++ + setsockopt(t->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, + sizeof(opt)); + +@@ -305,12 +310,13 @@ netsnmp_tcp_transport(struct sockaddr_in *addr, int local) + + netsnmp_transport * + netsnmp_tcp_create_tstring(const char *str, int local, +- const char *default_target) ++ const char *default_target, ++ char *iface) + { + struct sockaddr_in addr; + + if (netsnmp_sockaddr_in2(&addr, str, default_target)) { +- return netsnmp_tcp_transport(&addr, local); ++ return netsnmp_tcp_transport(&addr, local, iface); + } else { + return NULL; + } +@@ -319,7 +325,7 @@ netsnmp_tcp_create_tstring(const char *str, int local, + + + netsnmp_transport * +-netsnmp_tcp_create_ostring(const u_char * o, size_t o_len, int local) ++netsnmp_tcp_create_ostring(const u_char * o, size_t o_len, int local, char *iface) + { + struct sockaddr_in addr; + +@@ -328,7 +334,7 @@ netsnmp_tcp_create_ostring(const u_char * o, size_t o_len, int local) + addr.sin_family = AF_INET; + memcpy((u_char *) & (addr.sin_addr.s_addr), o, 4); + addr.sin_port = htons(porttmp); +- return netsnmp_tcp_transport(&addr, local); ++ return netsnmp_tcp_transport(&addr, local, iface); + } + return NULL; + } +diff --git a/snmplib/transports/snmpUDPBaseDomain.c b/snmplib/transports/snmpUDPBaseDomain.c +index 8497f71..7b415bc 100644 +--- a/snmplib/transports/snmpUDPBaseDomain.c ++++ b/snmplib/transports/snmpUDPBaseDomain.c +@@ -21,6 +21,9 @@ + #if HAVE_NETINET_IN_H + #include + #endif ++#if HAVE_NET_IF_H ++#include ++#endif + #if HAVE_ARPA_INET_H + #include + #endif +@@ -53,8 +56,14 @@ + #endif + + void +-_netsnmp_udp_sockopt_set(int fd, int local) ++_netsnmp_udp_sockopt_set(int fd, int local, char *iface) + { ++ ++ if (iface && setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface)) == -1) ++ snmp_log(LOG_ERR, "Bind socket on interface: %s: %s\n", iface, strerror(errno)); ++ else if (iface) ++ DEBUGMSGTL(("socket:option", "setting SO_BINDTODEVICE to %s\n", iface)); ++ + #ifdef SO_BSDCOMPAT + /* + * Patch for Linux. Without this, UDP packets that fail get an ICMP +@@ -237,7 +246,10 @@ int netsnmp_udpbase_sendto(int fd, struct in_addr *srcip, int if_index, + struct msghdr m = { 0 }; + char cmsg[CMSG_SPACE(cmsg_data_size)]; + int rc; +- ++ char iface[IFNAMSIZ]; ++ socklen_t ifacelen = IFNAMSIZ; ++ ++ iface[0] = '\0'; + iov.iov_base = data; + iov.iov_len = len; + +@@ -269,14 +281,23 @@ int netsnmp_udpbase_sendto(int fd, struct in_addr *srcip, int if_index, + + memset(&ipi, 0, sizeof(ipi)); + /* +- * Except in the case of responding +- * to a broadcast, setting the ifindex +- * when responding results in incorrect +- * behavior of changing the source address +- * that the manager sees the response +- * come from. ++ * For asymmetric multihomed users, we only set ifindex to 0 ++ * to let kernel handle return if there was no iface bound to the socket. + */ +- ipi.ipi_ifindex = 0; ++ if (getsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, iface, &ifacelen) != 0) { ++ DEBUGMSGTL(("socket:option", "error getsockopt %s\n", strerror(errno))); ++ DEBUGMSGTL(("socket:option", "sendto: SO_BINDTODEVICE not set ifindex=0\n")); ++ ipi.ipi_ifindex = 0; ++ } else if (!ifacelen) { ++ DEBUGMSGTL(("socket:option", "sendto: SO_BINDTODEVICE not set ifacelen=%d ifindex=0\n", ++ ifacelen)); ++ ipi.ipi_ifindex = 0; ++ } else { ++ DEBUGMSGTL(("socket:option", "sendto: SO_BINDTODEVICE dev=%s using ifindex=%d\n", ++ iface, if_index)); ++ ipi.ipi_ifindex = if_index; ++ } ++ + #if defined(cygwin) + ipi.ipi_addr.s_addr = srcip->s_addr; + #else +diff --git a/snmplib/transports/snmpUDPDomain.c b/snmplib/transports/snmpUDPDomain.c +index a0abd8c..fc68303 100644 +--- a/snmplib/transports/snmpUDPDomain.c ++++ b/snmplib/transports/snmpUDPDomain.c +@@ -84,7 +84,7 @@ typedef netsnmp_indexed_addr_pair netsnmp_udp_addr_pair; + * not static, since snmpUDPIPv6Domain needs it, but not public, either. + * (ie don't put it in a public header.) + */ +-void _netsnmp_udp_sockopt_set(int fd, int server); ++void _netsnmp_udp_sockopt_set(int fd, int server, char *iface); + int + netsnmp_sockaddr_in2(struct sockaddr_in *addr, + const char *inpeername, const char *default_target); +@@ -125,11 +125,11 @@ int netsnmp_udp_sendto(int fd, struct in_addr *srcip, int if_index, struct socka + */ + + netsnmp_transport * +-netsnmp_udp_transport(struct sockaddr_in *addr, int local) ++netsnmp_udp_transport(struct sockaddr_in *addr, int local, char *iface) + { + netsnmp_transport *t = NULL; + +- t = netsnmp_udpipv4base_transport(addr, local); ++ t = netsnmp_udpipv4base_transport(addr, local, iface); + if (NULL == t) { + return NULL; + } +@@ -473,12 +473,13 @@ netsnmp_udp_getSecName(void *opaque, int olength, + + netsnmp_transport * + netsnmp_udp_create_tstring(const char *str, int local, +- const char *default_target) ++ const char *default_target, ++ char *iface) + { + struct sockaddr_in addr; + + if (netsnmp_sockaddr_in2(&addr, str, default_target)) { +- return netsnmp_udp_transport(&addr, local); ++ return netsnmp_udp_transport(&addr, local, iface); + } else { + return NULL; + } +@@ -486,7 +487,7 @@ netsnmp_udp_create_tstring(const char *str, int local, + + + netsnmp_transport * +-netsnmp_udp_create_ostring(const u_char * o, size_t o_len, int local) ++netsnmp_udp_create_ostring(const u_char * o, size_t o_len, int local, char *iface) + { + struct sockaddr_in addr; + +@@ -495,7 +496,7 @@ netsnmp_udp_create_ostring(const u_char * o, size_t o_len, int local) + addr.sin_family = AF_INET; + memcpy((u_char *) & (addr.sin_addr.s_addr), o, 4); + addr.sin_port = htons(porttmp); +- return netsnmp_udp_transport(&addr, local); ++ return netsnmp_udp_transport(&addr, local, iface); + } + return NULL; + } +diff --git a/snmplib/transports/snmpUDPIPv4BaseDomain.c b/snmplib/transports/snmpUDPIPv4BaseDomain.c +index 8c0fb05..7991b6a 100644 +--- a/snmplib/transports/snmpUDPIPv4BaseDomain.c ++++ b/snmplib/transports/snmpUDPIPv4BaseDomain.c +@@ -57,7 +57,7 @@ int netsnmp_udpipv4_sendto(int fd, struct in_addr *srcip, int if_index, + #endif /* HAVE_IP_PKTINFO || HAVE_IP_RECVDSTADDR */ + + netsnmp_transport * +-netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int local) ++netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int local, char *iface) + { + netsnmp_transport *t = NULL; + int rc = 0, rc2; +@@ -95,7 +95,7 @@ netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int local) + return NULL; + } + +- _netsnmp_udp_sockopt_set(t->sock, local); ++ _netsnmp_udp_sockopt_set(t->sock, local, iface); + + if (local) { + #ifndef NETSNMP_NO_LISTEN_SUPPORT +diff --git a/snmplib/transports/snmpUDPIPv6Domain.c b/snmplib/transports/snmpUDPIPv6Domain.c +index 18de876..6b44b22 100644 +--- a/snmplib/transports/snmpUDPIPv6Domain.c ++++ b/snmplib/transports/snmpUDPIPv6Domain.c +@@ -74,12 +74,6 @@ oid netsnmp_UDPIPv6Domain[] = { TRANSPORT_DOMAIN_UDP_IPV6 }; + static netsnmp_tdomain udp6Domain; + + /* +- * from snmpUDPDomain. not static, but not public, either. +- * (ie don't put it in a public header.) +- */ +-extern void _netsnmp_udp_sockopt_set(int fd, int server); +- +-/* + * Return a string representing the address in data, or else the "far end" + * address if data is NULL. + */ +@@ -186,7 +186,7 @@ netsnmp_udp6_send(netsnmp_transport *t, void *buf, int size, + */ + + netsnmp_transport * +-netsnmp_udp6_transport(struct sockaddr_in6 *addr, int local) ++netsnmp_udp6_transport(struct sockaddr_in6 *addr, int local, char *iface) + { + netsnmp_transport *t = NULL; + int rc = 0; +@@ -223,7 +223,7 @@ netsnmp_udp6_transport(struct sockaddr_in6 *addr, int local) + return NULL; + } + +- _netsnmp_udp_sockopt_set(t->sock, local); ++ _netsnmp_udp_sockopt_set(t->sock, local, iface); + + if (local) { + #ifndef NETSNMP_NO_LISTEN_SUPPORT +@@ -724,12 +724,13 @@ netsnmp_udp6_getSecName(void *opaque, int olength, + + netsnmp_transport * + netsnmp_udp6_create_tstring(const char *str, int local, +- const char *default_target) ++ const char *default_target, ++ char *iface) + { + struct sockaddr_in6 addr; + + if (netsnmp_sockaddr_in6_2(&addr, str, default_target)) { +- return netsnmp_udp6_transport(&addr, local); ++ return netsnmp_udp6_transport(&addr, local, iface); + } else { + return NULL; + } +@@ -746,7 +747,7 @@ netsnmp_udp6_create_tstring(const char *str, int local, + */ + + netsnmp_transport * +-netsnmp_udp6_create_ostring(const u_char * o, size_t o_len, int local) ++netsnmp_udp6_create_ostring(const u_char * o, size_t o_len, int local, char *iface) + { + struct sockaddr_in6 addr; + +@@ -755,7 +756,7 @@ netsnmp_udp6_create_ostring(const u_char * o, size_t o_len, int local) + addr.sin6_family = AF_INET6; + memcpy((u_char *) & (addr.sin6_addr.s6_addr), o, 16); + addr.sin6_port = htons((o[16] << 8) + o[17]); +- return netsnmp_udp6_transport(&addr, local); ++ return netsnmp_udp6_transport(&addr, local, iface); + } + return NULL; + } +diff --git a/snmplib/transports/snmpUnixDomain.c b/snmplib/transports/snmpUnixDomain.c +index 47dffc1..af56c5d 100644 +--- a/snmplib/transports/snmpUnixDomain.c ++++ b/snmplib/transports/snmpUnixDomain.c +@@ -450,7 +450,8 @@ netsnmp_unix_transport(struct sockaddr_un *addr, int local) + + netsnmp_transport * + netsnmp_unix_create_tstring(const char *string, int local, +- const char *default_target) ++ const char *default_target, ++ char *iface) + { + struct sockaddr_un addr; + +@@ -476,7 +477,7 @@ netsnmp_unix_create_tstring(const char *string, int local, + + + netsnmp_transport * +-netsnmp_unix_create_ostring(const u_char * o, size_t o_len, int local) ++netsnmp_unix_create_ostring(const u_char * o, size_t o_len, int local, char *iface) + { + struct sockaddr_un addr; + +-- +2.7.4 + diff --git a/src/snmpd/patch-5.7.3+dfsg/0008-Enable-macro-DEB_BUILD_ARCH_OS-in-order-to-build-ipv.patch b/src/snmpd/patch-5.7.3+dfsg/0008-Enable-macro-DEB_BUILD_ARCH_OS-in-order-to-build-ipv.patch new file mode 100644 index 000000000000..c41b5b5a6638 --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/0008-Enable-macro-DEB_BUILD_ARCH_OS-in-order-to-build-ipv.patch @@ -0,0 +1,22 @@ +From 6e038423d7a3269dbfd85b3d7ada6015479f1559 Mon Sep 17 00:00:00 2001 +From: Qi Luo +Date: Fri, 20 Sep 2019 00:42:19 +0000 +Subject: [PATCH] Enable macro DEB_BUILD_ARCH_OS in order to build ipv6 feature + +--- + debian/rules | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/debian/rules b/debian/rules +index 4c3b5b6..1fab6a4 100755 +--- a/debian/rules ++++ b/debian/rules +@@ -4,4 +4,5 @@ + export DEB_BUILD_MAINT_OPTIONS := hardening=+all + DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) ++DEB_BUILD_ARCH_OS ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH_OS) + + LIB_VERSION = 30 +-- +2.18.0 + diff --git a/src/snmpd/patch-5.7.3+dfsg/series b/src/snmpd/patch-5.7.3+dfsg/series new file mode 100644 index 000000000000..31b251845dea --- /dev/null +++ b/src/snmpd/patch-5.7.3+dfsg/series @@ -0,0 +1,5 @@ +0001-SNMP-Stop-spamming-logs-with-statfs-permission-denie.patch +0002-at.c-properly-check-return-status-from-realloc.-Than.patch +0006-From-Jiri-Cervenka-snmpd-Fixed-agentx-crashing-and-or-freezing-on-timeout.patch +0007-Linux-VRF-5.7.3-Support.patch +0008-Enable-macro-DEB_BUILD_ARCH_OS-in-order-to-build-ipv.patch diff --git a/src/socat/.gitignore b/src/socat/.gitignore new file mode 100644 index 000000000000..d19db76ab9a9 --- /dev/null +++ b/src/socat/.gitignore @@ -0,0 +1,4 @@ +* +!.gitignore +!Makefile +!patch/ diff --git a/src/socat/Makefile b/src/socat/Makefile new file mode 100644 index 000000000000..cc2cd7238684 --- /dev/null +++ b/src/socat/Makefile @@ -0,0 +1,28 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = socat_$(SOCAT_VERSION)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./socat-1.7.3.1 + + # Get source package + wget -NO socat_$(SOCAT_VERSION).dsc "https://sonicstorage.blob.core.windows.net/packages/debian/socat_1.7.3.1-2+deb9u1.dsc?sv=2015-04-05&sr=b&sig=Ph7aMqb%2F%2FE%2F8qwxMXoXb5oK1YPkfVt6PV8mBBv5Wi%2F4%3D&se=2155-07-05T11%3A42%3A29Z&sp=r" + wget -NO socat_$(SOCAT_VERSION).debian.tar.xz "https://sonicstorage.blob.core.windows.net/packages/debian/socat_1.7.3.1-2+deb9u1.debian.tar.xz?sv=2015-04-05&sr=b&sig=yv77Fr5RtZgRTPmJK3j0lZ0BzsCiGaSs2i7NqQKEy2Y%3D&se=2155-07-05T11%3A39%3A59Z&sp=r" + wget -NO socat_1.7.3.1.orig.tar.gz "https://sonicstorage.blob.core.windows.net/packages/debian/socat_1.7.3.1.orig.tar.gz?sv=2015-04-05&sr=b&sig=0Ai1FM604aGsF5uBu2yN8w9O1a6zNjIDCdaiTo24DyQ%3D&se=2155-07-05T11%3A40%3A14Z&sp=r" + + dpkg-source -x socat_$(SOCAT_VERSION).dsc + + # Build source and Debian packages + pushd socat-1.7.3.1 + patch -p0 < ../enable_readline.patch + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + popd + + # Move the newly-built .deb packages to the destination directory + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) + diff --git a/src/socat/enable_readline.patch b/src/socat/enable_readline.patch new file mode 100644 index 000000000000..f1914d3cb494 --- /dev/null +++ b/src/socat/enable_readline.patch @@ -0,0 +1,13 @@ +--- debian/rules.old 2018-08-12 11:48:42.220230100 +0000 ++++ debian/rules 2018-08-12 11:48:52.072230100 +0000 +@@ -12,9 +12,6 @@ + %: + dh $@ --with=autoreconf + +-override_dh_auto_configure: +- dh_auto_configure -- --disable-readline +- + override_dh_auto_test: + +-.PHONY: override_dh_auto_configure override_dh_auto_test ++.PHONY: override_dh_auto_test diff --git a/src/sonic-bgpcfgd/.gitignore b/src/sonic-bgpcfgd/.gitignore new file mode 100644 index 000000000000..7611d6274601 --- /dev/null +++ b/src/sonic-bgpcfgd/.gitignore @@ -0,0 +1,12 @@ +.eggs/ +build/ +dist/ +*.egg-info/ +bgpcfgd/*.pyc +tests/*.pyc +tests/__pycache__/ +.idea +.coverage +bgpcfgd/__pycache__/ +venv +tests/.coverage* diff --git a/src/sonic-bgpcfgd/bgpcfgd/__init__.py b/src/sonic-bgpcfgd/bgpcfgd/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-bgpcfgd/bgpcfgd/__main__.py b/src/sonic-bgpcfgd/bgpcfgd/__main__.py new file mode 100644 index 000000000000..413eeee346d0 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/__main__.py @@ -0,0 +1,4 @@ +from .main import main + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/config.py b/src/sonic-bgpcfgd/bgpcfgd/config.py new file mode 100644 index 000000000000..bba45133c9df --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/config.py @@ -0,0 +1,114 @@ +class ConfigMgr(object): + """ The class represents frr configuration """ + def __init__(self, frr): + self.frr = frr + self.current_config = None + self.current_config_raw = None + self.changes = "" + self.peer_groups_to_restart = [] + + def reset(self): + """ Reset stored config """ + self.current_config = None + self.current_config_raw = None + self.changes = "" + self.peer_groups_to_restart = [] + + def update(self): + """ Read current config from FRR """ + self.current_config = None + self.current_config_raw = None + out = self.frr.get_config() + text = [] + for line in out.split('\n'): + if line.lstrip().startswith('!'): + continue + text.append(line) + text += [" "] # Add empty line to have something to work on, if there is no text + self.current_config_raw = text + self.current_config = self.to_canonical(out) # FIXME: use text as an input + + def push_list(self, cmdlist): + """ + Prepare new changes for FRR. The changes should be committed by self.commit() + :param cmdlist: configuration change for FRR. Type: List of Strings + """ + self.changes += "\n".join(cmdlist) + "\n" + + def push(self, cmd): + """ + Prepare new changes for FRR. The changes should be committed by self.commit() + :param cmd: configuration change for FRR. Type: String + """ + self.changes += cmd + "\n" + return True + + def restart_peer_groups(self, peer_groups): + """ + Schedule peer_groups for restart on commit + :param peer_groups: List of peer_groups + """ + self.peer_groups_to_restart.extend(peer_groups) + + def commit(self): + """ + Write configuration change to FRR. + :return: True if change was applied successfully, False otherwise + """ + if self.changes.strip() == "": + return True + rc_write = self.frr.write(self.changes) + rc_restart = self.frr.restart_peer_groups(self.peer_groups_to_restart) + self.reset() + return rc_write and rc_restart + + def get_text(self): + return self.current_config_raw + + @staticmethod + def to_canonical(raw_config): + """ + Convert FRR config into canonical format + :param raw_config: config in frr format + :return: frr config in canonical format + """ + parsed_config = [] + lines_with_comments = raw_config.split("\n") + lines = [line for line in lines_with_comments + if not line.strip().startswith('!') and line.strip() != ''] + if len(lines) == 0: + return [] + cur_path = [lines[0]] + cur_offset = ConfigMgr.count_spaces(lines[0]) + for line in lines: + n_spaces = ConfigMgr.count_spaces(line) + s_line = line.strip() + if n_spaces == cur_offset: + cur_path[-1] = s_line + elif n_spaces > cur_offset: + cur_path.append(s_line) + elif n_spaces < cur_offset: + cur_path = cur_path[:-2] + cur_path.append(s_line) + parsed_config.append(cur_path[:]) + cur_offset = n_spaces + return parsed_config + + @staticmethod + def count_spaces(line): + """ Count leading spaces in the line """ + return len(line) - len(line.lstrip()) + + @staticmethod + def from_canonical(canonical_config): + """ + Convert config from canonical format into FRR raw format + :param canonical_config: config in a canonical format + :return: config in the FRR raw format + """ + out = "" + for lines in canonical_config: + spaces = len(lines) - 1 + out += " " * spaces + lines[-1] + "\n" + + return out \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/directory.py b/src/sonic-bgpcfgd/bgpcfgd/directory.py new file mode 100644 index 000000000000..d2dfc915c037 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/directory.py @@ -0,0 +1,159 @@ +from collections import defaultdict + +from .log import log_err + + +class Directory(object): + """ This class stores values and notifies callbacks which were registered to be executed as soon + as some value is changed. This class works as DB cache mostly """ + def __init__(self): + self.data = defaultdict(dict) # storage. A key is a slot name, a value is a dictionary with data + self.notify = defaultdict(lambda: defaultdict(list)) # registered callbacks: slot -> path -> handlers[] + + @staticmethod + def get_slot_name(db, table): + """ Convert db, table pair into a slot name """ + return db + "__" + table + + def path_traverse(self, slot, path): + """ + Traverse a path in the storage. + If the path is an empty string, it returns a value as it is. + If the path is not an empty string, the method will traverse through the dictionary value. + Example: + self.data["key_1"] = { "abc": { "cde": { "fgh": "val_1", "ijk": "val_2" } } } + self.path_traverse("key_1", "abc/cde") will return True, { "fgh": "val_1", "ijk": "val_2" } + :param slot: storage key + :param path: storage path as a string where each internal key is separated by '/' + :return: a pair: True if the path was found, object if it was found + """ + if slot not in self.data: + return False, None + elif path == '': + return True, self.data[slot] + d = self.data[slot] + for p in path.split("/"): + if p not in d: + return False, None + d = d[p] + return True, d + + def path_exist(self, db, table, path): + """ + Check if the path exists in the storage + :param db: db name + :param table: table name + :param path: requested path + :return: True if the path is available, False otherwise + """ + slot = self.get_slot_name(db, table) + return self.path_traverse(slot, path)[0] + + def get_path(self, db, table, path): + """ + Return the requested path from the storage + :param db: db name + :param table: table name + :param path: requested path + :return: object if the path was found, None otherwise + """ + slot = self.get_slot_name(db, table) + return self.path_traverse(slot, path)[1] + + def put(self, db, table, key, value): + """ + Put information into the storage. Notify handlers which are dependant to the information + :param db: db name + :param table: table name + :param key: key to change + :param value: value to put + :return: + """ + slot = self.get_slot_name(db, table) + self.data[slot][key] = value + if slot in self.notify: + for path in self.notify[slot].keys(): + if self.path_exist(db, table, path): + for handler in self.notify[slot][path]: + handler() + + def get(self, db, table, key): + """ + Get a value from the storage + :param db: db name + :param table: table name + :param key: ket to get + :return: value for the key + """ + slot = self.get_slot_name(db, table) + return self.data[slot][key] + + def get_slot(self, db, table): + """ + Get an object from the storage + :param db: db name + :param table: table name + :return: object for the slot + """ + slot = self.get_slot_name(db, table) + return self.data[slot] + + def remove(self, db, table, key): + """ + Remove a value from the storage + :param db: db name + :param table: table name + :param key: key to remove + """ + slot = self.get_slot_name(db, table) + if slot in self.data: + if key in self.data[slot]: + del self.data[slot][key] + else: + log_err("Directory: Can't remove key '%s' from slot '%s'. The key doesn't exist" % (key, slot)) + else: + log_err("Directory: Can't remove key '%s' from slot '%s'. The slot doesn't exist" % (key, slot)) + + def remove_slot(self, db, table): + """ + Remove an object from the storage + :param db: db name + :param table: table name + """ + slot = self.get_slot_name(db, table) + if slot in self.data: + del self.data[slot] + else: + log_err("Directory: Can't remove slot '%s'. The slot doesn't exist" % slot) + + def available(self, db, table): + """ + Check if the table is available + :param db: db name + :param table: table name + :return: True if the slot is available, False if not + """ + slot = self.get_slot_name(db, table) + return slot in self.data + + def available_deps(self, deps): + """ + Check if all items from the deps list is available in the storage + :param deps: list of dependencies + :return: True if all dependencies are presented, False otherwise + """ + res = True + for db, table, path in deps: + res = res and self.path_exist(db, table, path) + return res + + def subscribe(self, deps, handler): + """ + Subscribe the handler to be run as soon as all dependencies are presented + :param deps: + :param handler: + :return: + """ + for db, table, path in deps: + slot = self.get_slot_name(db, table) + self.notify[slot][path].append(handler) \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/frr.py b/src/sonic-bgpcfgd/bgpcfgd/frr.py new file mode 100644 index 000000000000..6b88e5ee47f5 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/frr.py @@ -0,0 +1,70 @@ +import os +import datetime +import time +import tempfile + +from bgpcfgd.log import log_err, log_info, log_warn, log_crit +from .vars import g_debug +from .utils import run_command + + +class FRR(object): + """Proxy object with FRR""" + def __init__(self, daemons): + self.daemons = daemons + + def wait_for_daemons(self, seconds): + """ + Wait until FRR daemons are ready for requests + :param seconds: number of seconds to wait, until raise an error + """ + stop_time = datetime.datetime.now() + datetime.timedelta(seconds=seconds) + log_info("Start waiting for FRR daemons: %s" % str(datetime.datetime.now())) + while datetime.datetime.now() < stop_time: + ret_code, out, err = run_command(["vtysh", "-c", "show daemons"], hide_errors=True) + if ret_code == 0 and all(daemon in out for daemon in self.daemons): + log_info("All required daemons have connected to vtysh: %s" % str(datetime.datetime.now())) + return + else: + log_warn("Can't read daemon status from FRR: %s" % str(err)) + time.sleep(0.1) # sleep 100 ms + raise RuntimeError("FRR daemons hasn't been started in %d seconds" % seconds) + + @staticmethod + def get_config(): + ret_code, out, err = run_command(["vtysh", "-c", "show running-config"]) + if ret_code != 0: + log_crit("can't update running config: rc=%d out='%s' err='%s'" % (ret_code, out, err)) + return "" + return out + + @staticmethod + def write(config_text): + fd, tmp_filename = tempfile.mkstemp(dir='/tmp') + os.close(fd) + with open(tmp_filename, 'w') as fp: + fp.write("%s\n" % config_text) + command = ["vtysh", "-f", tmp_filename] + ret_code, out, err = run_command(command) + if ret_code != 0: + err_tuple = tmp_filename, ret_code, out, err + log_err("ConfigMgr::commit(): can't push configuration from file='%s', rc='%d', stdout='%s', stderr='%s'" % err_tuple) + else: + if not g_debug: + os.remove(tmp_filename) + return ret_code == 0 + + @staticmethod + def restart_peer_groups(peer_groups): + """ Restart peer-groups which support BBR + :param peer_groups: List of peer_groups to restart + :return: True if restart of all peer-groups was successful, False otherwise + """ + res = True + for peer_group in sorted(peer_groups): + rc, out, err = run_command(["vtysh", "-c", "clear bgp peer-group %s soft in" % peer_group]) + if rc != 0: + log_value = peer_group, rc, out, err + log_crit("Can't restart bgp peer-group '%s'. rc='%d', out='%s', err='%s'" % log_value) + res = res and (rc == 0) + return res diff --git a/src/sonic-bgpcfgd/bgpcfgd/log.py b/src/sonic-bgpcfgd/bgpcfgd/log.py new file mode 100644 index 000000000000..4083b13aa6ad --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/log.py @@ -0,0 +1,33 @@ +import syslog + +from .vars import g_debug + +def log_debug(msg): + """ Send a message msg to the syslog as DEBUG """ + if g_debug: + syslog.syslog(syslog.LOG_DEBUG, msg) + + +def log_notice(msg): + """ Send a message msg to the syslog as NOTICE """ + syslog.syslog(syslog.LOG_NOTICE, msg) + + +def log_info(msg): + """ Send a message msg to the syslog as INFO """ + syslog.syslog(syslog.LOG_INFO, msg) + + +def log_warn(msg): + """ Send a message msg to the syslog as WARNING """ + syslog.syslog(syslog.LOG_WARNING, msg) + + +def log_err(msg): + """ Send a message msg to the syslog as ERR """ + syslog.syslog(syslog.LOG_ERR, msg) + + +def log_crit(msg): + """ Send a message msg to the syslog as CRIT """ + syslog.syslog(syslog.LOG_CRIT, msg) \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/main.py b/src/sonic-bgpcfgd/bgpcfgd/main.py new file mode 100644 index 000000000000..360b54dc11aa --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/main.py @@ -0,0 +1,87 @@ +import os +import signal +import sys +import syslog +import traceback + +from swsscommon import swsscommon + +from .config import ConfigMgr +from .directory import Directory +from .log import log_notice, log_crit +from .managers_allow_list import BGPAllowListMgr +from .managers_bbr import BBRMgr +from .managers_bgp import BGPPeerMgrBase +from .managers_db import BGPDataBaseMgr +from .managers_intf import InterfaceMgr +from .managers_setsrc import ZebraSetSrc +from .runner import Runner, signal_handler +from .template import TemplateFabric +from .utils import read_constants +from .frr import FRR +from .vars import g_debug + + +def do_work(): + """ Main function """ + frr = FRR(["bgpd", "zebra", "staticd"]) + frr.wait_for_daemons(seconds=20) + # + common_objs = { + 'directory': Directory(), + 'cfg_mgr': ConfigMgr(frr), + 'tf': TemplateFabric(), + 'constants': read_constants(), + } + managers = [ + # Config DB managers + BGPDataBaseMgr(common_objs, "CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME), + BGPDataBaseMgr(common_objs, "CONFIG_DB", swsscommon.CFG_DEVICE_NEIGHBOR_METADATA_TABLE_NAME), + # Interface managers + InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_INTF_TABLE_NAME), + InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_LOOPBACK_INTERFACE_TABLE_NAME), + InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_VLAN_INTF_TABLE_NAME), + InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_LAG_INTF_TABLE_NAME), + # State DB managers + ZebraSetSrc(common_objs, "STATE_DB", swsscommon.STATE_INTERFACE_TABLE_NAME), + # Peer Managers + BGPPeerMgrBase(common_objs, "CONFIG_DB", swsscommon.CFG_BGP_NEIGHBOR_TABLE_NAME, "general", True), + BGPPeerMgrBase(common_objs, "CONFIG_DB", swsscommon.CFG_BGP_INTERNAL_NEIGHBOR_TABLE_NAME, "internal", False), + BGPPeerMgrBase(common_objs, "CONFIG_DB", "BGP_MONITORS", "monitors", False), + BGPPeerMgrBase(common_objs, "CONFIG_DB", "BGP_PEER_RANGE", "dynamic", False), + # AllowList Managers + BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES"), + # BBR Manager + BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR"), + ] + runner = Runner(common_objs['cfg_mgr']) + for mgr in managers: + runner.add_manager(mgr) + runner.run() + + +def main(): + rc = 0 + try: + syslog.openlog('bgpcfgd') + signal.signal(signal.SIGTERM, signal_handler) + signal.signal(signal.SIGINT, signal_handler) + do_work() + except KeyboardInterrupt: + log_notice("Keyboard interrupt") + except RuntimeError as exc: + log_crit(str(exc)) + rc = -2 + if g_debug: + raise + except Exception as exc: + log_crit("Got an exception %s: Traceback: %s" % (str(exc), traceback.format_exc())) + rc = -1 + if g_debug: + raise + finally: + syslog.closelog() + try: + sys.exit(rc) + except SystemExit: + os._exit(rc) diff --git a/src/sonic-bgpcfgd/bgpcfgd/manager.py b/src/sonic-bgpcfgd/bgpcfgd/manager.py new file mode 100644 index 000000000000..6966a20f4b35 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/manager.py @@ -0,0 +1,71 @@ +from swsscommon import swsscommon + +from .log import log_debug, log_err + + +class Manager(object): + """ This class represents a SONiC DB table """ + def __init__(self, common_objs, deps, database, table_name): + """ + Initialize class + :param common_objs: common object dictionary + :param deps: dependencies list + :param database: database name + :param table_name: table name + """ + self.directory = common_objs['directory'] + self.cfg_mgr = common_objs['cfg_mgr'] + self.constants = common_objs['constants'] + self.deps = deps + self.db_name = database + self.table_name = table_name + self.set_queue = [] + self.directory.subscribe(deps, self.on_deps_change) # subscribe this class method on directory changes + + def get_database(self): + """ Return associated database """ + return self.db_name + + def get_table_name(self): + """ Return associated table name""" + return self.table_name + + def handler(self, key, op, data): + """ + This method is executed on each add/remove event on the table. + :param key: key of the table entry + :param op: operation on the table entry. Could be either 'SET' or 'DEL' + :param data: associated data of the event. Empty for 'DEL' operation. + """ + if op == swsscommon.SET_COMMAND: + if self.directory.available_deps(self.deps): # all required dependencies are set in the Directory? + res = self.set_handler(key, data) + if not res: # set handler returned False, which means it is not ready to process is. Save it for later. + log_debug("'SET' handler returned NOT_READY for the Manager: %s" % self.__class__) + self.set_queue.append((key, data)) + else: + log_debug("Not all dependencies are met for the Manager: %s" % self.__class__) + self.set_queue.append((key, data)) + elif op == swsscommon.DEL_COMMAND: + self.del_handler(key) + else: + log_err("Invalid operation '%s' for key '%s'" % (op, key)) + + def on_deps_change(self): + """ This method is being executed on every dependency change """ + if not self.directory.available_deps(self.deps): + return + new_queue = [] + for key, data in self.set_queue: + res = self.set_handler(key, data) + if not res: + new_queue.append((key, data)) + self.set_queue = new_queue + + def set_handler(self, key, data): + """ Placeholder for 'SET' command """ + log_err("set_handler() wasn't implemented for %s" % self.__class__.__name__) + + def del_handler(self, key): + """ Placeholder for 'DEL' command """ + log_err("del_handler wasn't implemented for %s" % self.__class__.__name__) \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_allow_list.py b/src/sonic-bgpcfgd/bgpcfgd/managers_allow_list.py new file mode 100644 index 000000000000..435be91d20d2 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_allow_list.py @@ -0,0 +1,703 @@ +""" +Implementation of "allow-list" feature +""" +import re + +from .log import log_debug, log_info, log_err, log_warn +from .template import TemplateFabric +from .manager import Manager + + +class BGPAllowListMgr(Manager): + """ This class initialize "AllowList" settings """ + ALLOW_ADDRESS_PL_NAME_TMPL = "ALLOW_ADDRESS_%d_%s" # template for a name for the ALLOW_ADDRESS prefix-list ??? + EMPTY_COMMUNITY = "empty" + PL_NAME_TMPL = "PL_ALLOW_LIST_DEPLOYMENT_ID_%d_COMMUNITY_%s_V%s" + COMMUNITY_NAME_TMPL = "COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_%d_COMMUNITY_%s" + RM_NAME_TMPL = "ALLOW_LIST_DEPLOYMENT_ID_%d_V%s" + ROUTE_MAP_ENTRY_WITH_COMMUNITY_START = 10 + ROUTE_MAP_ENTRY_WITH_COMMUNITY_END = 29990 + ROUTE_MAP_ENTRY_WITHOUT_COMMUNITY_START = 30000 + ROUTE_MAP_ENTRY_WITHOUT_COMMUNITY_END = 65530 + + V4 = "v4" # constant for af enum: V4 + V6 = "v6" # constant for af enum: V6 + + def __init__(self, common_objs, db, table): + """ + Initialize the object + :param common_objs: common object dictionary + :param db: name of the db + :param table: name of the table in the db + """ + super(BGPAllowListMgr, self).__init__( + common_objs, + [], + db, + table, + ) + self.key_re = re.compile(r"^DEPLOYMENT_ID\|\d+\|\S+$|^DEPLOYMENT_ID\|\d+$") + self.enabled = self.__get_enabled() + self.__load_constant_lists() + + def set_handler(self, key, data): + """ + Manager method which runs on receiving 'SET' message + :param key: ket of the 'SET' message + :param data: data of the 'SET' message + :return: True if the message was executed, False - the message should be postponed. + """ + if not self.enabled: + log_warn("BGPAllowListMgr::Received 'SET' command, but this feature is disabled in constants") + return True + if not self.__set_handler_validate(key, data): + return True + key = key.replace("DEPLOYMENT_ID|", "") + deployment_id, community_value = key.split('|', 1) if '|' in key else (key, BGPAllowListMgr.EMPTY_COMMUNITY) + deployment_id = int(deployment_id) + prefixes_v4 = [] + prefixes_v6 = [] + if "prefixes_v4" in data: + prefixes_v4 = str(data['prefixes_v4']).split(",") + if "prefixes_v6" in data: + prefixes_v6 = str(data['prefixes_v6']).split(",") + default_action_community = self.__get_default_action_community(data) + self.__update_policy(deployment_id, community_value, prefixes_v4, prefixes_v6, default_action_community) + return True + + def __set_handler_validate(self, key, data): + """ + Validate parameters of a "Set" message + :param key: ket of the 'SET' message + :param data: data of the 'SET' message + :return: True if parameters are valid, False if parameters are invalid + """ + if data is None: + log_err("BGPAllowListMgr::Received BGP ALLOWED 'SET' message without data") + return False + if not self.key_re.match(key): + log_err("BGPAllowListMgr::Received BGP ALLOWED 'SET' message with invalid key: '%s'" % key) + return False + prefixes_v4 = [] + prefixes_v6 = [] + if "prefixes_v4" in data: + prefixes_v4 = str(data["prefixes_v4"]).split(",") + if not all(TemplateFabric.is_ipv4(prefix) for prefix in prefixes_v4): + arguments = "prefixes_v4", str(data["prefixes_v4"]) + log_err("BGPAllowListMgr::Received BGP ALLOWED 'SET' message with invalid input[%s]:'%s'" % arguments) + return False + if "prefixes_v6" in data: + prefixes_v6 = str(data["prefixes_v6"]).split(",") + if not all(TemplateFabric.is_ipv6(prefix) for prefix in prefixes_v6): + arguments = "prefixes_v6", str(data["prefixes_v6"]) + log_err("BGPAllowListMgr::Received BGP ALLOWED 'SET' message with invalid input[%s]:'%s'" % arguments) + return False + if not prefixes_v4 and not prefixes_v6: + log_err("BGPAllowListMgr::Received BGP ALLOWED 'SET' message with no prefixes specified: %s" % str(data)) + return False + if "default_action" in data and data["default_action"] != "permit" and data["default_action"] != "deny": + log_err("BGPAllowListMgr::Received BGP ALLOWED 'SET' message with invalid 'default_action' field: '%s'" % str(data)) + return False + return True + + def del_handler(self, key): + """ + Manager method which runs on "DEL" message + :param key: a key of "DEL" message + """ + if not self.enabled: + log_warn("BGPAllowListMgr::Received 'DEL' command, but this feature is disabled in constants") + return + if not self.__del_handler_validate(key): + return + key = key.replace('DEPLOYMENT_ID|', '') + deployment_id, community = key.split('|', 1) if '|' in key else (key, BGPAllowListMgr.EMPTY_COMMUNITY) + deployment_id = int(deployment_id) + self.__remove_policy(deployment_id, community) + + def __del_handler_validate(self, key): + """ + Validate "DEL" method parameters + :param key: a key of "DEL" message + :return: True if parameters are valid, False if parameters are invalid + """ + if not self.key_re.match(key): + log_err("BGPAllowListMgr::Received BGP ALLOWED 'DEL' message with invalid key: '$s'" % key) + return False + return True + + def __update_policy(self, deployment_id, community_value, prefixes_v4, prefixes_v6, default_action): + """ + Update "allow list" policy with parameters + :param deployment_id: deployment id which policy will be changed + :param community_value: community value to match for the updated policy + :param prefixes_v4: a list of v4 prefixes for the updated policy + :param prefixes_v6: a list of v6 prefixes for the updated policy + :param default_action: the default action for the policy. should be either 'permit' or 'deny' + """ + # update all related entries with the information + info = deployment_id, community_value, str(prefixes_v4), str(prefixes_v6) + msg = "BGPAllowListMgr::Updating 'Allow list' policy." + msg += " deployment_id '%s'. community: '%s'" + msg += " prefix_v4 '%s'. prefix_v6: '%s'" + log_info(msg % info) + names = self.__generate_names(deployment_id, community_value) + self.cfg_mgr.update() + cmds = [] + cmds += self.__update_prefix_list(self.V4, names['pl_v4'], prefixes_v4) + cmds += self.__update_prefix_list(self.V6, names['pl_v6'], prefixes_v6) + cmds += self.__update_community(names['community'], community_value) + cmds += self.__update_allow_route_map_entry(self.V4, names['pl_v4'], names['community'], names['rm_v4']) + cmds += self.__update_allow_route_map_entry(self.V6, names['pl_v6'], names['community'], names['rm_v6']) + cmds += self.__update_default_route_map_entry(names['rm_v4'], default_action) + cmds += self.__update_default_route_map_entry(names['rm_v6'], default_action) + if cmds: + self.cfg_mgr.push_list(cmds) + peer_groups = self.__find_peer_group_by_deployment_id(deployment_id) + self.cfg_mgr.restart_peer_groups(peer_groups) + log_debug("BGPAllowListMgr::__update_policy. The peers configuration scheduled for updates") + else: + log_debug("BGPAllowListMgr::__update_policy. Nothing to update") + log_info("BGPAllowListMgr::Done") + + def __remove_policy(self, deployment_id, community_value): + """ + Remove "allow list" policy for given deployment_id and community_value + :param deployment_id: deployment id which policy will be removed + :param community_value: community value to match for the removed policy + """ + # remove all related entries from the configuration + # put default rule to the route-map + info = deployment_id, community_value + msg = "BGPAllowListMgr::Removing 'Allow list' policy." + msg += " deployment_id '%s'. community: '%s'" + log_info(msg % info) + + default_action = self.__get_default_action_community() + names = self.__generate_names(deployment_id, community_value) + self.cfg_mgr.update() + cmds = [] + cmds += self.__remove_allow_route_map_entry(self.V4, names['pl_v4'], names['community'], names['rm_v4']) + cmds += self.__remove_allow_route_map_entry(self.V6, names['pl_v6'], names['community'], names['rm_v6']) + cmds += self.__remove_prefix_list(self.V4, names['pl_v4']) + cmds += self.__remove_prefix_list(self.V6, names['pl_v6']) + cmds += self.__remove_community(names['community']) + cmds += self.__update_default_route_map_entry(names['rm_v4'], default_action) + cmds += self.__update_default_route_map_entry(names['rm_v6'], default_action) + if cmds: + self.cfg_mgr.push_list(cmds) + peer_groups = self.__find_peer_group_by_deployment_id(deployment_id) + self.cfg_mgr.restart_peer_groups(peer_groups) + log_debug("BGPAllowListMgr::__remove_policy. 'Allow list' policy was scheduled for removal") + else: + log_debug("BGPAllowListMgr::__remove_policy. Nothing to remove") + log_info('BGPAllowListMgr::Done') + + @staticmethod + def __generate_names(deployment_id, community_value): + """ + Generate prefix-list names for a given peer_ip and community value + :param deployment_id: deployment_id for which we're going to filter prefixes + :param community_value: community, which we want to use to filter prefixes + :return: a dictionary with names + """ + if community_value == BGPAllowListMgr.EMPTY_COMMUNITY: + community_name = BGPAllowListMgr.EMPTY_COMMUNITY + else: + community_name = BGPAllowListMgr.COMMUNITY_NAME_TMPL % (deployment_id, community_value) + names = { + "pl_v4": BGPAllowListMgr.PL_NAME_TMPL % (deployment_id, community_value, '4'), + "pl_v6": BGPAllowListMgr.PL_NAME_TMPL % (deployment_id, community_value, '6'), + "rm_v4": BGPAllowListMgr.RM_NAME_TMPL % (deployment_id, '4'), + "rm_v6": BGPAllowListMgr.RM_NAME_TMPL % (deployment_id, '6'), + "community": community_name, + } + arguments = deployment_id, community_value, str(names) + log_debug("BGPAllowListMgr::__generate_names. deployment_id: %d, community: %s. names: %s" % arguments) + return names + + def __update_prefix_list(self, af, pl_name, allow_list): + """ + Create or update a prefix-list with name pl_name. + :param af: "v4" to create ipv4 prefix-list, "v6" to create ipv6 prefix-list + :param pl_name: prefix-list name + :param allow_list: prefix-list entries + :return: True if updating was successful, False otherwise + """ + assert af == self.V4 or af == self.V6 + constant_list = self.__get_constant_list(af) + allow_list = self.__to_prefix_list(af, allow_list) + log_debug("BGPAllowListMgr::__update_prefix_list. af='%s' prefix-list name=%s" % (af, pl_name)) + exist, correct = self.__is_prefix_list_valid(af, pl_name, allow_list, constant_list) + if correct: + log_debug("BGPAllowListMgr::__update_prefix_list. the prefix-list '%s' exists and correct" % pl_name) + return [] + family = self.__af_to_family(af) + cmds = [] + seq_no = 10 + if exist: + cmds.append('no %s prefix-list %s' % (family, pl_name)) + for entry in constant_list + allow_list: + cmds.append('%s prefix-list %s seq %d %s' % (family, pl_name, seq_no, entry)) + seq_no += 10 + return cmds + + def __remove_prefix_list(self, af, pl_name): + """ + Remove prefix-list in the address-family af. + :param af: "v4" to create ipv4 prefix-list, "v6" to create ipv6 prefix-list + :param pl_name: list of prefix-list names + :return: True if operation was successful, False otherwise + """ + assert af == self.V4 or af == self.V6 + log_debug("BGPAllowListMgr::__remove_prefix_lists. af='%s' pl_names='%s'" % (af, pl_name)) + exist, _ = self.__is_prefix_list_valid(af, pl_name, [], []) + if not exist: + log_debug("BGPAllowListMgr::__remove_prefix_lists: prefix_list '%s' not found" % pl_name) + return [] + family = self.__af_to_family(af) + return ["no %s prefix-list %s" % (family, pl_name)] + + def __is_prefix_list_valid(self, af, pl_name, allow_list, constant_list): + """ + Check that a prefix list exists and it has valid entries + :param af: address family of the checked prefix-list + :param pl_name: prefix-list name + :param allow_list: a prefix-list which must be a part of the valid prefix list + :param constant_list: a constant list which must be on top of each "allow" prefix list on the device + :return: a tuple. The first element of the tuple has True if the prefix-list exists, False otherwise, + The second element of the tuple has True if the prefix-list contains correct entries, False if not + """ + assert af == self.V4 or af == self.V6 + family = self.__af_to_family(af) + match_string = '%s prefix-list %s seq ' % (family, pl_name) + conf = self.cfg_mgr.get_text() + if not any(line.strip().startswith(match_string) for line in conf): + return False, False # if the prefix list is not exists, it is not correct + constant_set = set(constant_list) + allow_set = set(allow_list) + for line in conf: + if line.startswith(match_string): + found = line[len(match_string):].strip().split(' ') + rule = " ".join(found[1:]) + if rule in constant_set: + constant_set.discard(rule) + elif rule in allow_set: + if constant_set: + return True, False # Not everything from constant set is presented + else: + allow_set.discard(rule) + return True, len(allow_set) == 0 # allow_set should be presented all + + def __update_community(self, community_name, community_value): + """ + Update community for a peer + :param community_name: name of the community to update + :param community_value: community value for the peer + :return: True if operation was successful, False otherwise + """ + log_debug("BGPAllowListMgr::__update_community. community_name='%s' community='%s'" % (community_name, community_value)) + if community_value == self.EMPTY_COMMUNITY: # we don't need to do anything for EMPTY community + log_debug("BGPAllowListMgr::__update_community. Empty community. exiting") + return [] + cmds = [] + exists, found_community_value = self.__is_community_presented(community_name) + if exists: + if community_value == found_community_value: + log_debug("BGPAllowListMgr::__update_community. community '%s' is already presented" % community_name) + return [] + else: + msg = "BGPAllowListMgr::__update_community. " + msg += "community '%s' is already presented, but community value should be updated" % community_name + log_debug(msg) + cmds.append("no bgp community-list standard %s" % community_name) + cmds.append('bgp community-list standard %s permit %s' % (community_name, community_value)) + return cmds + + def __remove_community(self, community_name): + """ + Remove community for a peer + :param community_name: community value for the peer + :return: True if operation was successful, False otherwise + """ + log_debug("BGPAllowListMgr::__remove_community. community='%s'" % community_name) + if community_name == self.EMPTY_COMMUNITY: # we don't need to do anything for EMPTY community + log_debug("BGPAllowListMgr::__remove_community. There is nothing to remove in empty community") + return [] + exists, _ = self.__is_community_presented(community_name) + if not exists: + log_debug("BGPAllowListMgr::__remove_community. Community is already removed.") + return [] + return ['no bgp community-list standard %s' % community_name] + + def __is_community_presented(self, community_name): + """ + Return True if community for the peer_ip exists + :param community_name: community value for the peer + :return: A tuple. First element: True if operation was successful, False otherwise + Second element: community value if the first element is True no value otherwise + """ + log_debug("BGPAllowListMgr::__is_community_presented. community='%s'" % community_name) + match_string = 'bgp community-list standard %s permit ' % community_name + conf = self.cfg_mgr.get_text() + found = [line.strip() for line in conf if line.strip().startswith(match_string)] + if not found: + return False, None + community_value = found[0].replace(match_string, '') + return True, community_value + + def __update_allow_route_map_entry(self, af, allow_address_pl_name, community_name, route_map_name): + """ + Add or update a "Allow address" route-map entry with the parameters + :param af: "v4" to create ipv4 prefix-list, "v6" to create ipv6 prefix-list + :return: True if operation was successful, False otherwise + """ + assert af == self.V4 or af == self.V6 + info = af, route_map_name, allow_address_pl_name, community_name + log_debug("BGPAllowListMgr::__update_allow_route_map_entry. af='%s' Allow rm='%s' pl='%s' cl='%s'" % info) + entries = self.__parse_allow_route_map_entries(af, route_map_name) + found, _ = self.__find_route_map_entry(entries, allow_address_pl_name, community_name) + if found: + log_debug("BGPAllowListMgr::__update_allow_route_map_entry. route-map='%s' is already found" % route_map_name) + return [] + seq_number = self.__find_next_seq_number(entries.keys(), community_name != self.EMPTY_COMMUNITY, route_map_name) + info = af, seq_number, allow_address_pl_name, community_name + out = "af='%s' seqno='%d' Allow pl='%s' cl='%s'" % info + log_debug("BGPAllowListMgr::__update_allow_route_map_entry. %s" % out) + ip_version = "" if af == self.V4 else "v6" + cmds = [ + 'route-map %s permit %d' % (route_map_name, seq_number), + ' match ip%s address prefix-list %s' % (ip_version, allow_address_pl_name) + ] + if not community_name.endswith(self.EMPTY_COMMUNITY): + cmds.append(" match community %s" % community_name) + return cmds + + def __update_default_route_map_entry(self, route_map_name, default_action_community): + """ + Add or update default action rule for the route-map. + Default action rule is hardcoded into route-map permit 65535 + :param route_map_name: name of the target route_map + :param default_action_community: community value to mark not-matched prefixes + """ + info = route_map_name, default_action_community + log_debug("BGPAllowListMgr::__update_default_route_map_entry. rm='%s' set_community='%s'" % info) + current_default_action_value = self.__parse_default_action_route_map_entry(route_map_name) + if current_default_action_value != default_action_community: + return [ + 'route-map %s permit 65535' % route_map_name, + ' set community %s additive' % default_action_community + ] + else: + return [] + + def __parse_default_action_route_map_entry(self, route_map_name): + """ + Parse default-action route-map entry + :param route_map_name: Name of the route-map to parse + :return: a community value used for default action + """ + log_debug("BGPAllowListMgr::__parse_default_action_route_map_entries. rm='%s'" % route_map_name) + match_string = 'route-map %s permit 65535' % route_map_name + match_community = re.compile(r'^set community (\S+) additive$') + inside_route_map = False + community_value = "" + conf = self.cfg_mgr.get_text() + for line in conf + [""]: + s_line = line.strip() + if inside_route_map: + matched = match_community.match(s_line) + if matched: + community_value = matched.group(1) + break + else: + log_err("BGPAllowListMgr::Found incomplete route-map '%s' entry. seq_no=65535" % route_map_name) + inside_route_map = False + elif s_line == match_string: + inside_route_map = True + if community_value == "": + log_err("BGPAllowListMgr::Default action community value is not found. route-map '%s' entry. seq_no=65535" % route_map_name) + return community_value + + def __remove_allow_route_map_entry(self, af, allow_address_pl_name, community_name, route_map_name): + """ + Add or update a "Allow address" route-map entry with the parameters + :param af: "v4" to create ipv4 prefix-list, "v6" to create ipv6 prefix-list + :return: True if operation was successful, False otherwise + """ + assert af == self.V4 or af == self.V6 + info = af, route_map_name, allow_address_pl_name, community_name + log_debug("BGPAllowListMgr::__update_allow_route_map_entry. af='%s' Allow rm='%s' pl='%s' cl='%s'" % info) + entries = self.__parse_allow_route_map_entries(af, route_map_name) + found, seq_number = self.__find_route_map_entry(entries, allow_address_pl_name, community_name) + if not found: + log_debug("BGPAllowListMgr::__update_allow_route_map_entry. Not found route-map '%s' entry" % allow_address_pl_name) + return [] + return ['no route-map %s permit %d' % (route_map_name, seq_number)] + + @staticmethod + def __find_route_map_entry(entries, allow_address_pl_name, community_name): + """ + Find route-map entry with given allow_address prefix list name and community name in the parsed route-map. + :param entries: entries of parsed route-map + :param allow_address_pl_name: name of the "allow address" prefix-list + :param community_name: name of the "allow address" community name + :return: a tuple. The first element of the tuple is True, if the route-map entry was found, False otherwise. + The second element of the tuple has a sequence number of the entry. + """ + for sequence_number, values in entries.items(): + if sequence_number == 65535: + continue + allow_list_presented = values['pl_allow_list'] == allow_address_pl_name + community_presented = values['community'] == community_name + if allow_list_presented and community_presented: + log_debug("BGPAllowListMgr::__find_route_map_entry. found route-map '%s' entry" % allow_address_pl_name) + return True, sequence_number + return False, None + + def __parse_allow_route_map_entries(self, af, route_map_name): + """ + Parse "Allow list" route-map entries. + :param af: "v4" to create ipv4 prefix-list, "v6" to create ipv6 prefix-list + :return: A tuple, First element: True if operation was successful, False otherwise + Second element: list of object with parsed route-map entries + """ + assert af == self.V4 or af == self.V6 + log_debug("BGPAllowListMgr::__parse_allow_route_map_entries. af='%s', rm='%s'" % (af, route_map_name)) + match_string = 'route-map %s permit ' % route_map_name + entries = {} + inside_route_map = False + route_map_seq_number = None + pl_allow_list_name = None + community_name = self.EMPTY_COMMUNITY + if af == self.V4: + match_pl_allow_list = 'match ip address prefix-list ' + else: # self.V6 + match_pl_allow_list = 'match ipv6 address prefix-list ' + match_community = 'match community ' + conf = self.cfg_mgr.get_text() + for line in conf + [""]: + if inside_route_map: + if line.strip().startswith(match_pl_allow_list): + pl_allow_list_name = line.strip()[len(match_pl_allow_list):] + continue + elif line.strip().startswith(match_community): + community_name = line.strip()[len(match_community):] + continue + else: + if pl_allow_list_name is not None: + entries[route_map_seq_number] = { + 'pl_allow_list': pl_allow_list_name, + 'community': community_name, + } + else: + if route_map_seq_number != 65535: + log_warn("BGPAllowListMgr::Found incomplete route-map '%s' entry. seq_no=%d" % (route_map_name, route_map_seq_number)) + inside_route_map = False + pl_allow_list_name = None + community_name = self.EMPTY_COMMUNITY + route_map_seq_number = None + if line.startswith(match_string): + found = line[len(match_string):] + assert found.isdigit() + route_map_seq_number = int(found) + inside_route_map = True + return entries + + @staticmethod + def __find_next_seq_number(seq_numbers, has_community, route_map_name): + """ + Find a next available "Allow list" route-map entry number + :param seq_numbers: a list of already used sequence numbers + :param has_community: True, if the route-map entry has community + :return: next available route-map sequence number + """ + used_sequence_numbers = set(seq_numbers) + sequence_number = None + if has_community: # put entries without communities after 29999 + start_seq = BGPAllowListMgr.ROUTE_MAP_ENTRY_WITH_COMMUNITY_START + end_seq = BGPAllowListMgr.ROUTE_MAP_ENTRY_WITH_COMMUNITY_END + else: + start_seq = BGPAllowListMgr.ROUTE_MAP_ENTRY_WITHOUT_COMMUNITY_START + end_seq = BGPAllowListMgr.ROUTE_MAP_ENTRY_WITHOUT_COMMUNITY_END + for i in range(start_seq, end_seq, 10): + if i not in used_sequence_numbers: + sequence_number = i + break + if sequence_number is None: + raise RuntimeError("No free sequence numbers for '%s'" % route_map_name) + info = sequence_number, "yes" if has_community else "no" + log_debug("BGPAllowListMgr::__find_next_seq_number '%d' has_community='%s'" % info) + return sequence_number + + def __extract_peer_group_names(self): + """ + Extract names of all peer-groups defined in the config + :return: list of peer-group names + """ + # Find all peer-groups entries + re_peer_group = re.compile(r'^\s*neighbor (\S+) peer-group$') + peer_groups = [] + for line in self.cfg_mgr.get_text(): + result = re_peer_group.match(line) + if result: + peer_groups.append(result.group(1)) + return peer_groups + + def __get_peer_group_to_route_map(self, peer_groups): + """ + Extract names of route-maps which is connected to peer-groups defines as peer_groups + :peer_groups: a list of peer-group names + :return: dictionary where key is a peer-group, value is a route-map name which is defined as route-map in + for the peer_group. + """ + pg_2_rm = {} + for pg in peer_groups: + re_peer_group_rm = re.compile(r'^\s*neighbor %s route-map (\S+) in$' % pg) + for line in self.cfg_mgr.get_text(): + result = re_peer_group_rm.match(line) + if result: + pg_2_rm[pg] = result.group(1) + break + return pg_2_rm + + def __get_route_map_calls(self, rms): + """ + Find mapping between route-maps and route-map call names, defined for the route-maps + :rms: a set with route-map names + :return: a dictionary: key - name of a route-map, value - name of a route-map call defined for the route-map + """ + rm_2_call = {} + re_rm = re.compile(r'^route-map (\S+) permit \d+$') + re_call = re.compile(r'^\s*call (\S+)$') + inside_name = None + for line in self.cfg_mgr.get_text(): + if inside_name: + inside_result = re_call.match(line) + if inside_result: + rm_2_call[inside_name] = inside_result.group(1) + inside_name = None + continue + result = re_rm.match(line) + if not result: + continue + inside_name = None + if result.group(1) not in rms: + continue + inside_name = result.group(1) + return rm_2_call + + @staticmethod + def __get_peer_group_to_restart(deployment_id, pg_2_rm, rm_2_call): + """ + Get peer_groups which are assigned to deployment_id + :deployment_id: deployment_id number + :pg_2_rm: a dictionary where key is a peer-group, value is a route-map name which is defined as route-map in + for the peer_group. + :rm_2_call: a dictionary: key - name of a route-map, value - name of a route-map call defined for the route-map + """ + ret = set() + target_allow_list_prefix = 'ALLOW_LIST_DEPLOYMENT_ID_%d_V' % deployment_id + for peer_group, route_map in pg_2_rm.items(): + if route_map in rm_2_call: + if rm_2_call[route_map].startswith(target_allow_list_prefix): + ret.add(peer_group) + return list(ret) + + def __find_peer_group_by_deployment_id(self, deployment_id): + """ + Deduce peer-group names which are connected to devices with requested deployment_id + :param deployment_id: deployment_id number + :return: a list of peer-groups which a used by devices with requested deployment_id number + """ + self.cfg_mgr.update() + peer_groups = self.__extract_peer_group_names() + pg_2_rm = self.__get_peer_group_to_route_map(peer_groups) + rm_2_call = self.__get_route_map_calls(set(pg_2_rm.values())) + ret = self.__get_peer_group_to_restart(deployment_id, pg_2_rm, rm_2_call) + return list(ret) + + def __get_enabled(self): + """ + Load enable/disabled property from constants + :return: True if enabled, False otherwise + """ + return 'bgp' in self.constants \ + and 'allow_list' in self.constants["bgp"] \ + and "enabled" in self.constants["bgp"]["allow_list"] \ + and self.constants["bgp"]["allow_list"]["enabled"] + + def __load_constant_lists(self): + """ + Load default prefix-list entries from constants.yml file + """ + if 'bgp' in self.constants and 'allow_list' in self.constants["bgp"] \ + and "default_pl_rules" in self.constants["bgp"]["allow_list"]: + obj = self.constants["bgp"]["allow_list"]["default_pl_rules"] + if "v4" in obj: + self.constants_v4 = obj["v4"] + else: + self.constants_v4 = [] + if "v6" in obj: + self.constants_v6 = obj["v6"] + else: + self.constants_v6 = [] + + def __get_constant_list(self, af): + """ + Return loaded default prefix-list entries bases on address family + :param af: address family + :return: default prefix-list entries + """ + if af == self.V4: + return self.constants_v4 + else: + return self.constants_v6 + + def __to_prefix_list(self, af, allow_list): + """ + Convert "allow list" prefix list, to a prefix-list rules + :param af: address-family + :param allow_list: "allow list" prefix list + :return: prefix-list rules + """ + res = [] + prefix_mask_default = 32 if af == self.V4 else 128 + for prefix in allow_list: + prefix_mask = int(prefix.split("/")[1]) + if prefix_mask == prefix_mask_default: + res.append("permit %s" % prefix) + else: + res.append("permit %s le %d" % (prefix, prefix_mask_default)) + return res + + def __af_to_family(self, af): + """ + Convert address family into prefix list family + :param af: address family + :return: prefix list ip family + """ + return 'ip' if af == self.V4 else 'ipv6' + + def __get_default_action_community(self, data=None): + """ + Determine the default action community based on the request. + If request doesn't contain "default_action" field - the default_action value + from the constants is being used + :param data: SET request data + :return: returns community value for "default_action" + """ + drop_community = self.constants["bgp"]["allow_list"]["drop_community"] + if data and "default_action" in data: + if data["default_action"] == "deny": + return "no-export" + else: # "permit" + return drop_community + else: + if "default_action" in self.constants["bgp"]["allow_list"]: + if self.constants["bgp"]["allow_list"]["default_action"].strip() == "deny": + return "no-export" + else: + return drop_community + else: + return drop_community diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_bbr.py b/src/sonic-bgpcfgd/bgpcfgd/managers_bbr.py new file mode 100644 index 000000000000..0e82d0a4b6d5 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_bbr.py @@ -0,0 +1,134 @@ +import re + +from swsscommon import swsscommon + +from .log import log_err, log_info +from .manager import Manager + + +class BBRMgr(Manager): + """ This class initialize "BBR" feature for """ + def __init__(self, common_objs, db, table): + """ + Initialize the object + :param common_objs: common object dictionary + :param db: name of the db + :param table: name of the table in the db + """ + super(BBRMgr, self).__init__( + common_objs, + [("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, "localhost/bgp_asn"),], + db, + table, + ) + self.enabled = False + self.bbr_enabled_pgs = {} + self.directory.put(self.db_name, self.table_name, 'status', "disabled") + self.__init() + + def set_handler(self, key, data): + """ Implementation of 'SET' command for this class """ + if not self.enabled: + log_info("BBRMgr::BBR is disabled. Drop the request") + return True + if not self.__set_validation(key, data): + return True + cmds, peer_groups_to_restart = self.__set_prepare_config(data['status']) + self.cfg_mgr.push_list(cmds) + self.cfg_mgr.restart_peer_groups(peer_groups_to_restart) + log_info("BBRMgr::Scheduled BBR update") + return True + + def del_handler(self, key): + """ Implementation of 'DEL' command for this class """ + log_err("The '%s' table shouldn't be removed from the db" % self.table_name) + + def __init(self): + """ Initialize BBRMgr. Extracted from constructor """ + if not 'bgp' in self.constants: + log_err("BBRMgr::Disabled: 'bgp' key is not found in constants") + return + if 'bbr' in self.constants['bgp'] \ + and 'enabled' in self.constants['bgp']['bbr'] \ + and self.constants['bgp']['bbr']['enabled']: + self.bbr_enabled_pgs = self.__read_pgs() + if self.bbr_enabled_pgs: + self.enabled = True + if 'default_state' in self.constants['bgp']['bbr'] \ + and self.constants['bgp']['bbr']['default_state'] == 'enabled': + default_status = "enabled" + else: + default_status = "disabled" + self.directory.put(self.db_name, self.table_name, 'status', default_status) + log_info("BBRMgr::Initialized and enabled. Default state: '%s'" % default_status) + else: + log_info("BBRMgr::Disabled: no BBR enabled peers") + else: + log_info("BBRMgr::Disabled: no bgp.bbr.enabled in the constants") + + def __read_pgs(self): + """ + Read peer-group bbr settings from constants file + :return: return bbr information from constant peer-group settings + """ + if 'peers' not in self.constants['bgp']: + log_info("BBRMgr::no 'peers' was found in constants") + return {} + res = {} + for peer_name, value in self.constants['bgp']['peers'].items(): + if 'bbr' not in value: + continue + for pg_name, pg_afs in value['bbr'].items(): + res[pg_name] = pg_afs + return res + + def __set_validation(self, key, data): + """ Validate set-command arguments + :param key: key of 'set' command + :param data: data of 'set' command + :return: True is the parameters are valid, False otherwise + """ + if key != 'all': + log_err("Invalid key '%s' for table '%s'. Only key value 'all' is supported" % (key, self.table_name)) + return False + if 'status' not in data: + log_err("Invalid value '%s' for table '%s', key '%s'. Key 'status' in data is expected" % (data, self.table_name, key)) + return False + if data['status'] != "enabled" and data['status'] != "disabled": + log_err("Invalid value '%s' for table '%s', key '%s'. Only 'enabled' and 'disabled' are supported" % (data, self.table_name, key)) + return False + return True + + def __set_prepare_config(self, status): + """ + Generate FFR configuration to apply changes + :param status: either "enabled" or "disabled" + :return: list of commands prepared for FRR + """ + bgp_asn = self.directory.get_slot("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME)["localhost"]["bgp_asn"] + available_peer_groups = self.__get_available_peer_groups() + cmds = ["router bgp %s" % bgp_asn] + prefix_of_commands = "" if status == "enabled" else "no " + peer_groups_to_restart = set() + for af in ["ipv4", "ipv6"]: + cmds.append(" address-family %s" % af) + for pg_name in sorted(self.bbr_enabled_pgs.keys()): + for peer_group_name in available_peer_groups: + if peer_group_name.startswith(pg_name) and af in self.bbr_enabled_pgs[pg_name]: + cmds.append(" %sneighbor %s allowas-in 1" % (prefix_of_commands, peer_group_name)) + peer_groups_to_restart.add(peer_group_name) + return cmds, list(peer_groups_to_restart) + + def __get_available_peer_groups(self): + """ + Extract configured peer-groups from the config + :return: set of available peer-groups + """ + re_pg = re.compile(r'^\s*neighbor\s+(\S+)\s+peer-group\s*$') + res = set() + self.cfg_mgr.update() + for line in self.cfg_mgr.get_text(): + m = re_pg.match(line) + if m: + res.add(m.group(1)) + return res diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_bgp.py b/src/sonic-bgpcfgd/bgpcfgd/managers_bgp.py new file mode 100644 index 000000000000..f6108bfb61c4 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_bgp.py @@ -0,0 +1,387 @@ +import json +from swsscommon import swsscommon + +import jinja2 +import netaddr + +from .log import log_warn, log_err, log_info, log_debug, log_crit +from .manager import Manager +from .template import TemplateFabric +from .utils import run_command + + +class BGPPeerGroupMgr(object): + """ This class represents peer-group and routing policy for the peer_type """ + def __init__(self, common_objs, base_template): + """ + Construct the object + :param common_objs: common objects + :param base_template: path to the directory with Jinja2 templates + """ + self.cfg_mgr = common_objs['cfg_mgr'] + self.constants = common_objs['constants'] + tf = common_objs['tf'] + self.policy_template = tf.from_file(base_template + "policies.conf.j2") + self.peergroup_template = tf.from_file(base_template + "peer-group.conf.j2") + + def update(self, name, **kwargs): + """ + Update peer-group and routing policy for the peer with the name + :param name: name of the peer. Used for logging only + :param kwargs: dictionary with parameters for rendering + """ + rc_policy = self.update_policy(name, **kwargs) + rc_pg = self.update_pg(name, **kwargs) + return rc_policy and rc_pg + + def update_policy(self, name, **kwargs): + """ + Update routing policy for the peer + :param name: name of the peer. Used for logging only + :param kwargs: dictionary with parameters for rendering + """ + try: + policy = self.policy_template.render(**kwargs) + except jinja2.TemplateError as e: + log_err("Can't render policy template name: '%s': %s" % (name, str(e))) + return False + self.update_entity(policy, "Routing policy for peer '%s'" % name) + return True + + def update_pg(self, name, **kwargs): + """ + Update peer-group for the peer + :param name: name of the peer. Used for logging only + :param kwargs: dictionary with parameters for rendering + """ + try: + pg = self.peergroup_template.render(**kwargs) + except jinja2.TemplateError as e: + log_err("Can't render peer-group template: '%s': %s" % (name, str(e))) + return False + + if kwargs['vrf'] == 'default': + cmd = ('router bgp %s\n' % kwargs['bgp_asn']) + pg + else: + cmd = ('router bgp %s vrf %s\n' % (kwargs['bgp_asn'], kwargs['vrf'])) + pg + self.update_entity(cmd, "Peer-group for peer '%s'" % name) + return True + + def update_entity(self, cmd, txt): + """ + Send commands to FRR + :param cmd: commands to send in a raw form + :param txt: text for the syslog output + :return: + """ + self.cfg_mgr.push(cmd) + log_info("%s has been scheduled to be updated" % txt) + return True + + +class BGPPeerMgrBase(Manager): + """ Manager of BGP peers """ + def __init__(self, common_objs, db_name, table_name, peer_type, check_neig_meta): + """ + Initialize the object + :param common_objs: common objects + :param table_name: name of the table with peers + :param peer_type: type of the peers. It is used to find right templates + """ + self.common_objs = common_objs + self.constants = self.common_objs["constants"] + self.fabric = common_objs['tf'] + self.peer_type = peer_type + + base_template = "bgpd/templates/" + self.constants["bgp"]["peers"][peer_type]["template_dir"] + "/" + self.templates = { + "add": self.fabric.from_file(base_template + "instance.conf.j2"), + "delete": self.fabric.from_string('no neighbor {{ neighbor_addr }}'), + "shutdown": self.fabric.from_string('neighbor {{ neighbor_addr }} shutdown'), + "no shutdown": self.fabric.from_string('no neighbor {{ neighbor_addr }} shutdown'), + } + + deps = [ + ("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, "localhost/bgp_asn"), + ("CONFIG_DB", swsscommon.CFG_LOOPBACK_INTERFACE_TABLE_NAME, "Loopback0"), + ("LOCAL", "local_addresses", ""), + ("LOCAL", "interfaces", ""), + ] + + if check_neig_meta: + self.check_neig_meta = 'bgp' in self.constants \ + and 'use_neighbors_meta' in self.constants['bgp'] \ + and self.constants['bgp']['use_neighbors_meta'] + else: + self.check_neig_meta = False + + self.check_deployment_id = 'bgp' in self.constants \ + and 'use_deployment_id' in self.constants['bgp'] \ + and self.constants['bgp']['use_deployment_id'] + + if self.check_neig_meta: + deps.append(("CONFIG_DB", swsscommon.CFG_DEVICE_NEIGHBOR_METADATA_TABLE_NAME, "")) + + if self.check_deployment_id: + deps.append(("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, "localhost/deployment_id")) + + super(BGPPeerMgrBase, self).__init__( + common_objs, + deps, + db_name, + table_name, + ) + + self.peers = self.load_peers() + self.peer_group_mgr = BGPPeerGroupMgr(self.common_objs, base_template) + return + + def set_handler(self, key, data): + """ + It runs on 'SET' command + :param key: key of the changed table + :param data: the data associated with the change + """ + vrf, nbr = self.split_key(key) + peer_key = (vrf, nbr) + if peer_key not in self.peers: + return self.add_peer(vrf, nbr, data) + else: + return self.update_peer(vrf, nbr, data) + + def add_peer(self, vrf, nbr, data): + """ + Add a peer into FRR. This is used if the peer is not existed in FRR yet + :param vrf: vrf name. Name is equal "default" for the global vrf + :param nbr: neighbor ip address (name for dynamic peer type) + :param data: associated data + :return: True if this adding was successful, False otherwise + """ + print_data = vrf, nbr, data + bgp_asn = self.directory.get_slot("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME)["localhost"]["bgp_asn"] + # + lo0_ipv4 = self.get_lo0_ipv4() + if lo0_ipv4 is None: + log_warn("Loopback0 ipv4 address is not presented yet") + return False + # + if "local_addr" not in data: + log_warn("Peer %s. Missing attribute 'local_addr'" % nbr) + 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. + data["local_addr"] = str(netaddr.IPNetwork(str(data["local_addr"])).ip) + interface = self.get_local_interface(data["local_addr"]) + if not interface: + print_data = nbr, data["local_addr"] + log_debug("Peer '%s' with local address '%s' wait for the corresponding interface to be set" % print_data) + return False + vnet = self.get_vnet(interface) + if vnet: + # Ignore the bgp session that is in a vnet + log_info("Ignore the BGP peer '%s' as the interface '%s' is in vnet '%s'" % (nbr, interface, vnet)) + return True + + kwargs = { + 'CONFIG_DB__DEVICE_METADATA': self.directory.get_slot("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME), + 'CONFIG_DB__BGP_BBR': self.directory.get_slot('CONFIG_DB', 'BGP_BBR'), + 'constants': self.constants, + 'bgp_asn': bgp_asn, + 'vrf': vrf, + 'neighbor_addr': nbr, + 'bgp_session': data, + 'loopback0_ipv4': lo0_ipv4, + } + if self.check_neig_meta: + neigmeta = self.directory.get_slot("CONFIG_DB", swsscommon.CFG_DEVICE_NEIGHBOR_METADATA_TABLE_NAME) + if 'name' in data and data["name"] not in neigmeta: + log_info("DEVICE_NEIGHBOR_METADATA is not ready for neighbor '%s' - '%s'" % (nbr, data['name'])) + return False + kwargs['CONFIG_DB__DEVICE_NEIGHBOR_METADATA'] = neigmeta + + tag = data['name'] if 'name' in data else nbr + self.peer_group_mgr.update(tag, **kwargs) + + try: + cmd = self.templates["add"].render(**kwargs) + except jinja2.TemplateError as e: + msg = "Peer '(%s|%s)'. Error in rendering the template for 'SET' command '%s'" % print_data + log_err("%s: %s" % (msg, str(e))) + return True + if cmd is not None: + self.apply_op(cmd, vrf) + key = (vrf, nbr) + self.peers.add(key) + log_info("Peer '(%s|%s)' has been scheduled to be added with attributes '%s'" % print_data) + + return True + + def update_peer(self, vrf, nbr, data): + """ + Update a peer. This is used when the peer is already in the FRR + Update support only "admin_status" for now + :param vrf: vrf name. Name is equal "default" for the global vrf + :param nbr: neighbor ip address (name for dynamic peer type) + :param data: associated data + :return: True if this adding was successful, False otherwise + """ + if "admin_status" in data: + self.change_admin_status(vrf, nbr, data) + else: + log_err("Peer '(%s|%s)': Can't update the peer. Only 'admin_status' attribute is supported" % (vrf, nbr)) + + return True + + def change_admin_status(self, vrf, nbr, data): + """ + Change admin status of a peer + :param vrf: vrf name. Name is equal "default" for the global vrf + :param nbr: neighbor ip address (name for dynamic peer type) + :param data: associated data + :return: True if this adding was successful, False otherwise + """ + if data['admin_status'] == 'up': + self.apply_admin_status(vrf, nbr, "no shutdown", "up") + elif data['admin_status'] == 'down': + self.apply_admin_status(vrf, nbr, "shutdown", "down") + else: + print_data = vrf, nbr, data['admin_status'] + log_err("Peer '%s|%s': Can't update the peer. It has wrong attribute value attr['admin_status'] = '%s'" % print_data) + + def apply_admin_status(self, vrf, nbr, template_name, admin_state): + """ + Render admin state template and apply the command to the FRR + :param vrf: vrf name. Name is equal "default" for the global vrf + :param nbr: neighbor ip address (name for dynamic peer type) + :param template_name: name of the template to render + :param admin_state: desired admin state + :return: True if this adding was successful, False otherwise + """ + print_data = vrf, nbr, admin_state + ret_code = self.apply_op(self.templates[template_name].render(neighbor_addr=nbr), vrf) + if ret_code: + log_info("Peer '%s|%s' admin state is set to '%s'" % print_data) + else: + log_err("Can't set peer '%s|%s' admin state to '%s'." % print_data) + + def del_handler(self, key): + """ + 'DEL' handler for the BGP PEER tables + :param key: key of the neighbor + """ + vrf, nbr = self.split_key(key) + peer_key = (vrf, nbr) + if peer_key not in self.peers: + log_warn("Peer '(%s|%s)' has not been found" % (vrf, nbr)) + return + cmd = self.templates["delete"].render(neighbor_addr=nbr) + ret_code = self.apply_op(cmd, vrf) + if ret_code: + log_info("Peer '(%s|%s)' has been removed" % (vrf, nbr)) + self.peers.remove(peer_key) + else: + log_err("Peer '(%s|%s)' hasn't been removed" % (vrf, nbr)) + + def apply_op(self, cmd, vrf): + """ + Push commands cmd into FRR + :param cmd: commands in raw format + :param vrf: vrf where the commands should be applied + :return: True if no errors, False if there are errors + """ + bgp_asn = self.directory.get_slot("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME)["localhost"]["bgp_asn"] + if vrf == 'default': + cmd = ('router bgp %s\n' % bgp_asn) + cmd + else: + cmd = ('router bgp %s vrf %s\n' % (bgp_asn, vrf)) + cmd + self.cfg_mgr.push(cmd) + return True + + def get_lo0_ipv4(self): + """ + Extract Loopback0 ipv4 address from the Directory + :return: ipv4 address for Loopback0, None if nothing found + """ + loopback0_ipv4 = None + for loopback in self.directory.get_slot("CONFIG_DB", swsscommon.CFG_LOOPBACK_INTERFACE_TABLE_NAME).keys(): + if loopback.startswith("Loopback0|"): + loopback0_prefix_str = loopback.replace("Loopback0|", "") + loopback0_ip_str = loopback0_prefix_str[:loopback0_prefix_str.find('/')] + if TemplateFabric.is_ipv4(loopback0_ip_str): + loopback0_ipv4 = loopback0_ip_str + break + + return loopback0_ipv4 + + def get_local_interface(self, local_addr): + """ + 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 = self.directory.get_slot("LOCAL", "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 = self.directory.get_slot("LOCAL", "interfaces") + # Check if the information for the interface of this local address has been set + if "interface" in local_address and local_address["interface"] in interfaces: + return interfaces[local_address["interface"]] + else: + return None + + @staticmethod + def get_vnet(interface): + """ + 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 "vnet_name" in interface and interface["vnet_name"]: + return interface["vnet_name"] + else: + return None + + @staticmethod + def split_key(key): + """ + Split key into ip address and vrf name. If there is no vrf, "default" would be return for vrf + :param key: key to split + :return: vrf name extracted from the key, peer ip address extracted from the key + """ + if '|' not in key: + return 'default', key + else: + return tuple(key.split('|', 1)) + + @staticmethod + def load_peers(): + """ + Load peers from FRR. + :return: set of peers, which are already installed in FRR + """ + command = ["vtysh", "-c", "show bgp vrfs json"] + ret_code, out, err = run_command(command) + if ret_code == 0: + js_vrf = json.loads(out) + vrfs = js_vrf['vrfs'].keys() + else: + log_crit("Can't read bgp vrfs: %s" % err) + raise Exception("Can't read bgp vrfs: %s" % err) + peers = set() + for vrf in vrfs: + command = ["vtysh", "-c", 'show bgp vrf %s neighbors json' % str(vrf)] + ret_code, out, err = run_command(command) + if ret_code == 0: + js_bgp = json.loads(out) + for nbr in js_bgp.keys(): + peers.add((vrf, nbr)) + else: + log_crit("Can't read vrf '%s' neighbors: %s" % (vrf, str(err))) + raise Exception("Can't read vrf '%s' neighbors: %s" % (vrf, str(err))) + + return peers \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_db.py b/src/sonic-bgpcfgd/bgpcfgd/managers_db.py new file mode 100644 index 000000000000..37d2eee99a8f --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_db.py @@ -0,0 +1,28 @@ +from .manager import Manager + + +class BGPDataBaseMgr(Manager): + """ This class updates the Directory object when db table is updated """ + def __init__(self, common_objs, db, table): + """ + Initialize the object + :param common_objs: common object dictionary + :param db: name of the db + :param table: name of the table in the db + """ + super(BGPDataBaseMgr, self).__init__( + common_objs, + [], + db, + table, + ) + + def set_handler(self, key, data): + """ Implementation of 'SET' command for this class """ + self.directory.put(self.db_name, self.table_name, key, data) + + return True + + def del_handler(self, key): + """ Implementation of 'DEL' command for this class """ + self.directory.remove(self.db_name, self.table_name, key) \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_intf.py b/src/sonic-bgpcfgd/bgpcfgd/managers_intf.py new file mode 100644 index 000000000000..c633c43046e0 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_intf.py @@ -0,0 +1,56 @@ +import netaddr + +from .log import log_warn +from .manager import Manager + + +class InterfaceMgr(Manager): + """ This class updates the Directory object when interface-related table is updated """ + def __init__(self, common_objs, db, table): + """ + Initialize the object + :param common_objs: common object dictionary + :param db: name of the db + :param table: name of the table in the db + """ + super(InterfaceMgr, self).__init__( + common_objs, + [], + db, + table, + ) + + def set_handler(self, key, data): + """ Implementation of 'SET' command. + Similar to BGPDataBaseMgr but enriches data object with additional data """ + # Interface table can have two keys, + # one with ip prefix and one without ip prefix + if '|' in key: + interface_name, network_str = key.split('|', 1) + try: + network = netaddr.IPNetwork(str(network_str)) + except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): + log_warn("Subnet '%s' format is wrong for interface '%s'" % (network_str, interface_name)) + return True + data["interface"] = interface_name + data["prefixlen"] = str(network.prefixlen) + ip = str(network.ip) + self.directory.put("LOCAL", "local_addresses", ip, data) + self.directory.put(self.db_name, self.table_name, key, data) + self.directory.put("LOCAL", "interfaces", key, data) + return True + + def del_handler(self, key): + """ Implementation of 'DEL' command + Also removes data object enrichment """ + if '|' in key: + interface, network = key.split('|', 1) + try: + network = netaddr.IPNetwork(str(network)) + except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): + log_warn("Subnet '%s' format is wrong for interface '%s'" % (network, interface)) + return + ip = str(network.ip) + self.directory.remove("LOCAL", "local_addresses", ip) + self.directory.remove(self.db_name, self.table_name, key) + self.directory.remove("LOCAL", "interfaces", key) \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_setsrc.py b/src/sonic-bgpcfgd/bgpcfgd/managers_setsrc.py new file mode 100644 index 000000000000..d1de585b0520 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_setsrc.py @@ -0,0 +1,67 @@ +import jinja2 + +from .log import log_err, log_warn, log_info +from .manager import Manager +from .template import TemplateFabric + + +class ZebraSetSrc(Manager): + """ This class initialize "set src" settings for zebra """ + def __init__(self, common_objs, db, table): + """ + Initialize the object + :param common_objs: common object dictionary + :param db: name of the db + :param table: name of the table in the db + """ + super(ZebraSetSrc, self).__init__( + common_objs, + [], + db, + table, + ) + tf = common_objs['tf'] + self.zebra_set_src_template = tf.from_file("zebra/zebra.set_src.conf.j2") + self.lo_ipv4 = None + self.lo_ipv6 = None + + def set_handler(self, key, data): + """ Implementation of 'SET' command for this class """ + self.directory.put(self.db_name, self.table_name, key, data) + # + if key.startswith("Loopback0|") and "state" in data and data["state"] == "ok": + ip_addr_w_mask = key.replace("Loopback0|", "") + slash_pos = ip_addr_w_mask.rfind("/") + if slash_pos == -1: + log_err("Wrong Loopback0 ip prefix: '%s'" % ip_addr_w_mask) + return True + ip_addr = ip_addr_w_mask[:slash_pos] + try: + if TemplateFabric.is_ipv4(ip_addr): + if self.lo_ipv4 is None: + self.lo_ipv4 = ip_addr + txt = self.zebra_set_src_template.render(rm_name="RM_SET_SRC", lo_ip=ip_addr, ip_proto="") + else: + log_warn("Update command is not supported for set src templates. current ip='%s'. new ip='%s'" % (self.lo_ipv4, ip_addr)) + return True + elif TemplateFabric.is_ipv6(ip_addr): + if self.lo_ipv6 is None: + self.lo_ipv6 = ip_addr + txt = self.zebra_set_src_template.render(rm_name="RM_SET_SRC6", lo_ip=ip_addr, ip_proto="v6") + else: + log_warn("Update command is not supported for set src templates. current ip='%s'. new ip='%s'" % (self.lo_ipv6, ip_addr)) + return True + else: + log_err("Got ambiguous ip address '%s'" % ip_addr) + return True + except jinja2.TemplateError as e: + log_err("Error while rendering 'set src' template: %s" % str(e)) + return True + self.cfg_mgr.push(txt) + log_info("The 'set src' configuration with Loopback0 ip '%s' has been scheduled to be added" % ip_addr) + return True + + def del_handler(self, key): + """ Implementation of 'DEL' command for this class """ + self.directory.remove(self.db_name, self.table_name, key) + log_warn("Delete command is not supported for 'zebra set src' templates") \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/runner.py b/src/sonic-bgpcfgd/bgpcfgd/runner.py new file mode 100644 index 000000000000..4c160e5967cf --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/runner.py @@ -0,0 +1,70 @@ +from collections import defaultdict +from swsscommon import swsscommon + +from .log import log_debug, log_crit + + +g_run = True + + +def signal_handler(_, __): # signal_handler(signum, frame) + """ signal handler """ + global g_run + g_run = False + + +class Runner(object): + """ Implements main io-loop of the application + It will run event handlers inside of Manager objects + when corresponding db/table is updated + """ + SELECT_TIMEOUT = 1000 + + def __init__(self, cfg_manager): + """ Constructor """ + self.cfg_manager = cfg_manager + self.db_connectors = {} + self.selector = swsscommon.Select() + self.callbacks = defaultdict(lambda: defaultdict(list)) # db -> table -> handlers[] + self.subscribers = set() + + def add_manager(self, manager): + """ + Add a manager to the Runner. + As soon as new events will be receiving by Runner, + handlers of corresponding objects will be executed + :param manager: an object implementing Manager + """ + db_name = manager.get_database() + table_name = manager.get_table_name() + db = swsscommon.SonicDBConfig.getDbId(db_name) + if db not in self.db_connectors: + self.db_connectors[db] = swsscommon.DBConnector(db_name, 0) + + if table_name not in self.callbacks[db]: + conn = self.db_connectors[db] + subscriber = swsscommon.SubscriberStateTable(conn, table_name) + self.subscribers.add(subscriber) + self.selector.addSelectable(subscriber) + self.callbacks[db][table_name].append(manager.handler) + + def run(self): + """ Main loop """ + while g_run: + state, _ = self.selector.select(Runner.SELECT_TIMEOUT) + if state == self.selector.TIMEOUT: + continue + elif state == self.selector.ERROR: + raise Exception("Received error from select") + + for subscriber in self.subscribers: + while True: + key, op, fvs = subscriber.pop() + if not key: + break + log_debug("Received message : '%s'" % str((key, op, fvs))) + for callback in self.callbacks[subscriber.getDbConnector().getDbId()][subscriber.getTableName()]: + callback(key, op, dict(fvs)) + rc = self.cfg_manager.commit() + if not rc: + log_crit("Runner::commit was unsuccessful") diff --git a/src/sonic-bgpcfgd/bgpcfgd/template.py b/src/sonic-bgpcfgd/bgpcfgd/template.py new file mode 100644 index 000000000000..e88073881171 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/template.py @@ -0,0 +1,108 @@ +from collections import OrderedDict +from functools import partial + +import jinja2 +import netaddr + +from .log import log_err + +class TemplateFabric(object): + """ Fabric for rendering jinja2 templates """ + def __init__(self, template_path = '/usr/share/sonic/templates'): + j2_template_paths = [template_path] + j2_loader = jinja2.FileSystemLoader(j2_template_paths) + j2_env = jinja2.Environment(loader=j2_loader, trim_blocks=False) + j2_env.filters['ipv4'] = self.is_ipv4 + j2_env.filters['ipv6'] = self.is_ipv6 + j2_env.filters['pfx_filter'] = self.pfx_filter + for attr in ['ip', 'network', 'prefixlen', 'netmask']: + j2_env.filters[attr] = partial(self.prefix_attr, attr) + self.env = j2_env + + def from_file(self, filename): + """ + Read a template from a file + :param filename: filename of the file. Type String + :return: Jinja2 template object + """ + return self.env.get_template(filename) + + def from_string(self, tmpl): + """ + Read a template from a string + :param tmpl: Text representation of Jinja2 template + :return: Jinja2 template object + """ + return self.env.from_string(tmpl) + + @staticmethod + def is_ipv4(value): + """ Return True if the value is an ipv4 address """ + if not value: + return False + if isinstance(value, netaddr.IPNetwork): + addr = value + else: + try: + addr = netaddr.IPNetwork(str(value)) + except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): + return False + return addr.version == 4 + + @staticmethod + def is_ipv6(value): + """ Return True if the value is an ipv6 address """ + if not value: + return False + if isinstance(value, netaddr.IPNetwork): + addr = value + else: + try: + addr = netaddr.IPNetwork(str(value)) + except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): + return False + return addr.version == 6 + + @staticmethod + def prefix_attr(attr, value): + """ + Extract attribute from IPNetwork object + :param attr: attribute to extract + :param value: the string representation of ip prefix which will be converted to IPNetwork. + :return: the value of the extracted attribute + """ + if not value: + return None + else: + try: + prefix = netaddr.IPNetwork(str(value)) + except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): + return None + return str(getattr(prefix, attr)) + + @staticmethod + def pfx_filter(value): + """INTERFACE Table can have keys in one of the two formats: + string or tuple - This filter skips the string keys and only + take into account the tuple. + For eg - VLAN_INTERFACE|Vlan1000 vs VLAN_INTERFACE|Vlan1000|192.168.0.1/21 + """ + table = OrderedDict() + + if not value: + return table + + for key, val in value.items(): + if not isinstance(key, tuple): + continue + intf, ip_address = key + if '/' not in ip_address: + if TemplateFabric.is_ipv4(ip_address): + table[(intf, "%s/32" % ip_address)] = val + elif TemplateFabric.is_ipv6(ip_address): + table[(intf, "%s/128" % ip_address)] = val + else: + log_err("'%s' is invalid ip address" % ip_address) + else: + table[key] = val + return table \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/utils.py b/src/sonic-bgpcfgd/bgpcfgd/utils.py new file mode 100644 index 000000000000..01c21b0f4872 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/utils.py @@ -0,0 +1,33 @@ +import subprocess +import yaml + +from .log import log_crit, log_debug, log_err + + +def run_command(command, shell=False, hide_errors=False): + """ + Run a linux command. The command is defined as a list. See subprocess.Popen documentation on format + :param command: command to execute. Type: List of strings + :param shell: execute the command through shell when True. Type: Boolean + :param hide_errors: don't report errors to syslog when True. Type: Boolean + :return: Tuple: integer exit code from the command, stdout as a string, stderr as a string + """ + log_debug("execute command '%s'." % str(command)) + p = subprocess.Popen(command, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8') + stdout, stderr = p.communicate() + if p.returncode != 0: + if not hide_errors: + print_tuple = p.returncode, str(command), stdout, stderr + log_err("command execution returned %d. Command: '%s', stdout: '%s', stderr: '%s'" % print_tuple) + + return p.returncode, stdout, stderr + + +def read_constants(): + """ Read file with constants values from /etc/sonic/constants.yml """ + with open('/etc/sonic/constants.yml') as fp: + content = yaml.load(fp) # FIXME: , Loader=yaml.FullLoader) + if "constants" not in content: + log_crit("/etc/sonic/constants.yml doesn't have 'constants' key") + raise Exception("/etc/sonic/constants.yml doesn't have 'constants' key") + return content["constants"] \ No newline at end of file diff --git a/src/sonic-bgpcfgd/bgpcfgd/vars.py b/src/sonic-bgpcfgd/bgpcfgd/vars.py new file mode 100644 index 000000000000..18bee5578e25 --- /dev/null +++ b/src/sonic-bgpcfgd/bgpcfgd/vars.py @@ -0,0 +1 @@ +g_debug = True # FIXME: read from env variable, or from constants diff --git a/src/sonic-bgpcfgd/bgpmon/__init__.py b/src/sonic-bgpcfgd/bgpmon/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-bgpcfgd/bgpmon/bgpmon.py b/src/sonic-bgpcfgd/bgpmon/bgpmon.py new file mode 100755 index 000000000000..2b50bd6cf58d --- /dev/null +++ b/src/sonic-bgpcfgd/bgpmon/bgpmon.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 + +"""" +Description: bgpmon.py -- populating bgp related information in stateDB. + script is started by supervisord in bgp docker when the docker is started. + + Initial creation of this daemon is to assist SNMP agent in obtaining the + BGP related information for its MIB support. The MIB that this daemon is + assisting is for the CiscoBgp4MIB (Neighbor state only). If there are other + BGP related items that needs to be updated in a periodic manner in the + future, then more can be added into this process. + + The script check if there are any bgp activities by monitoring the bgp + frr.log file timestamp. If activity is detected, then it will request bgp + neighbor state via vtysh cli interface. This bgp activity monitoring is + done periodically (every 15 second). When triggered, it looks specifically + for the neighbor state in the json output of show ip bgp neighbors json + and update the state DB for each neighbor accordingly. + In order to not disturb and hold on to the State DB access too long and + removal of the stale neighbors (neighbors that was there previously on + previous get request but no longer there in the current get request), a + "previous" neighbor dictionary will be kept and used to determine if there + is a need to perform update or the peer is stale to be removed from the + state DB +""" +import subprocess +import json +import os +import syslog +import swsssdk +import time + +PIPE_BATCH_MAX_COUNT = 50 + +class BgpStateGet: + def __init__(self): + # set peer_l stores the Neighbor peer Ip address + # dic peer_state stores the Neighbor peer state entries + # set new_peer_l stores the new snapshot of Neighbor peer ip address + # dic new_peer_state stores the new snapshot of Neighbor peer states + self.peer_l = set() + self.peer_state = {} + self.new_peer_l = set() + self.new_peer_state = {} + self.cached_timestamp = 0 + self.db = swsssdk.SonicV2Connector() + self.db.connect(self.db.STATE_DB, False) + client = self.db.get_redis_client(self.db.STATE_DB) + self.pipe = client.pipeline() + self.db.delete_all_by_pattern(self.db.STATE_DB, "NEIGH_STATE_TABLE|*" ) + + # A quick way to check if there are anything happening within BGP is to + # check its log file has any activities. This is by checking its modified + # timestamp against the cached timestamp that we keep and if there is a + # difference, there is activity detected. In case the log file got wiped + # out, it will default back to constant pulling every 15 seconds + def bgp_activity_detected(self): + try: + timestamp = os.stat("/var/log/frr/frr.log").st_mtime + if timestamp != self.cached_timestamp: + self.cached_timestamp = timestamp + return True + else: + return False + except (IOError, OSError): + return True + + def update_new_peer_states(self, peer_dict): + peer_l = peer_dict["peers"].keys() + self.new_peer_l.update(peer_l) + for peer in peer_l: + self.new_peer_state[peer] = peer_dict["peers"][peer]["state"] + + # Get a new snapshot of BGP neighbors and store them in the "new" location + def get_all_neigh_states(self): + cmd = "vtysh -c 'show bgp summary json'" + rc, output = subprocess.getstatusoutput(cmd) + if rc: + syslog.syslog(syslog.LOG_ERR, "*ERROR* Failed with rc:{} when execute: {}".format(rc, cmd)) + return + + peer_info = json.loads(output) + # cmd ran successfully, safe to Clean the "new" set/dict for new snapshot + self.new_peer_l.clear() + self.new_peer_state.clear() + for key, value in peer_info.items(): + if key == "ipv4Unicast" or key == "ipv6Unicast": + self.update_new_peer_states(value) + + # This method will take the caller's dictionary which contains the peer state operation + # That need to be updated in StateDB using Redis pipeline. + # The data{} will be cleared at the end of this method before returning to caller. + def flush_pipe(self, data): + """Dump each entry in data{} into State DB via redis pipeline. + Args: + data: Neighbor state in dictionary format + { + 'NEIGH_STATE_TABLE|ip_address_a': {'state':state}, + 'NEIGH_STATE_TABLE|ip_address_b': {'state':state}, + 'NEIGH_STATE_TABLE|ip_address_c': {'state':state}, + 'NEIGH_STATE_TABLE|ip_address_x': None, + 'NEIGH_STATE_TABLE|ip_address_z': None + ... + } + """ + for key, value in data.items(): + if value is None: + # delete case + self.pipe.delete(key) + else: + # Add or Modify case + self.pipe.hmset(key, value) + self.pipe.execute() + data.clear() + + def update_neigh_states(self): + data = {} + for peer in self.new_peer_l: + key = "NEIGH_STATE_TABLE|%s" % peer + if peer in self.peer_l: + # only update the entry if state changed + if self.peer_state[peer] != self.new_peer_state[peer]: + # state changed. Update state DB for this entry + state = self.new_peer_state[peer] + data[key] = {'state':state} + self.peer_state[peer] = state + # remove this neighbor from old set since it is accounted for + self.peer_l.remove(peer) + else: + # New neighbor found case. Add to dictionary and state DB + state = self.new_peer_state[peer] + data[key] = {'state':state} + self.peer_state[peer] = state + if len(data) > PIPE_BATCH_MAX_COUNT: + self.flush_pipe(data) + # Check for stale state entries to be cleaned up + for peer in self.peer_l: + # remove this from the stateDB and the current neighbor state entry + del_key = "NEIGH_STATE_TABLE|%s" % peer + data[del_key] = None + if peer in self.peer_state: + del self.peer_state[peer] + if len(data) > PIPE_BATCH_MAX_COUNT: + self.flush_pipe(data) + # If anything in the pipeline not yet flushed, flush them now + if len(data) > 0: + self.flush_pipe(data) + # Save the new set + self.peer_l = self.new_peer_l.copy() + +def main(): + + syslog.syslog(syslog.LOG_INFO, "bgpmon service started") + bgp_state_get = None + try: + bgp_state_get = BgpStateGet() + except Exception as e: + syslog.syslog(syslog.LOG_ERR, "{}: error exit 1, reason {}".format("THIS_MODULE", str(e))) + exit(1) + + # periodically obtain the new neighbor information and update if necessary + while True: + time.sleep(15) + if bgp_state_get.bgp_activity_detected(): + bgp_state_get.get_all_neigh_states() + bgp_state_get.update_neigh_states() + +if __name__ == '__main__': + main() diff --git a/src/sonic-bgpcfgd/pytest.ini b/src/sonic-bgpcfgd/pytest.ini new file mode 100644 index 000000000000..a49b58e45f0f --- /dev/null +++ b/src/sonic-bgpcfgd/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = --cov=bgpcfgd --cov-report term diff --git a/src/sonic-bgpcfgd/setup.cfg b/src/sonic-bgpcfgd/setup.cfg new file mode 100644 index 000000000000..00ed5efbcbad --- /dev/null +++ b/src/sonic-bgpcfgd/setup.cfg @@ -0,0 +1,5 @@ +[aliases] +test=pytest +[tool:pytest] +addopts = --verbose +python_files = tests/*.py diff --git a/src/sonic-bgpcfgd/setup.py b/src/sonic-bgpcfgd/setup.py new file mode 100755 index 000000000000..ab86ca20ec19 --- /dev/null +++ b/src/sonic-bgpcfgd/setup.py @@ -0,0 +1,31 @@ +import setuptools + +setuptools.setup( + name = 'sonic-bgpcfgd', + version = '1.0', + description = 'Utility to dynamically generate BGP configuration for FRR', + author = 'Pavel Shirshov', + author_email = 'pavelsh@microsoft.com', + url = 'https://github.com/Azure/sonic-buildimage', + packages = setuptools.find_packages(), + entry_points = { + 'console_scripts': [ + 'bgpcfgd = bgpcfgd.main:main', + 'bgpmon = bgpmon.bgpmon:main', + ] + }, + install_requires = [ + 'jinja2>=2.10', + 'netaddr==0.8.0', + 'pyyaml==5.4.1', + ], + setup_requires = [ + 'pytest-runner', + 'wheel' + ], + tests_require = [ + 'pytest', + 'pytest-cov', + 'sonic-config-engine' + ] +) diff --git a/src/sonic-bgpcfgd/tests/__init__.py b/src/sonic-bgpcfgd/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_all.json new file mode 100644 index 000000000000..c4134ff29806 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_all.json @@ -0,0 +1,21 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "deployment_id": "5" + } + }, + "CONFIG_DB__LOOPBACK_INTERFACE": { + "Loopback1|55.55.55.55/32": {} + }, + "bgp_session": { + "ip_range": "10.10.20.0/24,20.20.20.0/24", + "name": "dyn_name", + "peer_asn": "11111", + "src_address": "1.1.1.1" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_base.json b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_base.json new file mode 100644 index 000000000000..04fd24fa0819 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_base.json @@ -0,0 +1,19 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "deployment_id": "5" + } + }, + "CONFIG_DB__LOOPBACK_INTERFACE": { + "Loopback1|55.55.55.55/32": {} + }, + "bgp_session": { + "ip_range": "10.10.20.0/24,20.20.20.0/24", + "name": "dyn_name" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_all.conf new file mode 100644 index 000000000000..1ffc3d34343e --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_all.conf @@ -0,0 +1,22 @@ +! +! template: bgpd/templates/dynamic/instance.conf.j2 +! + neighbor dyn_name peer-group + neighbor dyn_name passive + neighbor dyn_name ebgp-multihop 255 + neighbor dyn_name soft-reconfiguration inbound + neighbor dyn_name route-map FROM_BGP_SPEAKER in + neighbor dyn_name route-map TO_BGP_SPEAKER out + neighbor dyn_name remote-as 11111 + bgp listen range 10.10.20.0/24 peer-group dyn_name + bgp listen range 20.20.20.0/24 peer-group dyn_name + neighbor dyn_name update-source 1.1.1.1 + address-family ipv4 + neighbor dyn_name activate + exit-address-family + address-family ipv6 + neighbor dyn_name activate + exit-address-family +! +! end of template: bgpd/templates/dynamic/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_base.conf b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_base.conf new file mode 100644 index 000000000000..ac2a4f3e18d7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_base.conf @@ -0,0 +1,22 @@ +! +! template: bgpd/templates/dynamic/instance.conf.j2 +! + neighbor dyn_name peer-group + neighbor dyn_name passive + neighbor dyn_name ebgp-multihop 255 + neighbor dyn_name soft-reconfiguration inbound + neighbor dyn_name route-map FROM_BGP_SPEAKER in + neighbor dyn_name route-map TO_BGP_SPEAKER out + neighbor dyn_name remote-as 51111 + bgp listen range 10.10.20.0/24 peer-group dyn_name + bgp listen range 20.20.20.0/24 peer-group dyn_name + neighbor dyn_name update-source 55.55.55.55 + address-family ipv4 + neighbor dyn_name activate + exit-address-family + address-family ipv6 + neighbor dyn_name activate + exit-address-family +! +! end of template: bgpd/templates/dynamic/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/param_all.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/param_all.json @@ -0,0 +1 @@ +{} diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/result_all.conf new file mode 100644 index 000000000000..86d5c0297227 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/result_all.conf @@ -0,0 +1,7 @@ +! +! template: bgpd/templates/BGP_SPEAKER/peer-group.conf.j2 +! +! nothing is here +! +! end of template: bgpd/templates/BGP_SPEAKER/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/param_all.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/param_all.json @@ -0,0 +1 @@ +{} diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/result_all.conf new file mode 100644 index 000000000000..17ca09ec2a36 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/result_all.conf @@ -0,0 +1,9 @@ +! +! template: bgpd/templates/BGP_SPEAKER/policies.conf.j2 +! +route-map FROM_BGP_SPEAKER permit 10 +! +route-map TO_BGP_SPEAKER deny 1 +! +! end of template: bgpd/templates/BGP_SPEAKER/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v4.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v4.json new file mode 100644 index 000000000000..4afd00f38da1 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v4.json @@ -0,0 +1,18 @@ +{ + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "keepalive": "5", + "holdtime": "30", + "admin_status": "down", + "ASIC": "something", + "rrclient": "1", + "nhopself": "1" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v6.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v6.json new file mode 100644 index 000000000000..115f5a32c941 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v6.json @@ -0,0 +1,18 @@ +{ + "neighbor_addr": "fc::10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "keepalive": "5", + "holdtime": "30", + "admin_status": "down", + "ASIC": "something", + "rrclient": "1", + "nhopself": "1" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v4.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v4.json new file mode 100644 index 000000000000..e2e59575cbb3 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v4.json @@ -0,0 +1,15 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": {} + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v6.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v6.json new file mode 100644 index 000000000000..5e79378e3e00 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v6.json @@ -0,0 +1,15 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": {} + }, + "neighbor_addr": "fc00::2", + "bgp_session": { + "asn": "555", + "name": "remote_peer" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_l2vpn.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_l2vpn.json new file mode 100644 index 000000000000..e679bff08435 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_l2vpn.json @@ -0,0 +1,18 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "SpineChassisFrontendRouter" + } + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + }, + "bgp_asn": "555" +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_1.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_1.json new file mode 100644 index 000000000000..b7c1e2075f02 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_1.json @@ -0,0 +1,17 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "default_bgp_status": "down" + } + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_2.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_2.json new file mode 100644 index 000000000000..610254a2b2ba --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_2.json @@ -0,0 +1,17 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "default_bgp_status": "up" + } + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_1.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_1.json new file mode 100644 index 000000000000..88d2b6defb2a --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_1.json @@ -0,0 +1,16 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": {} + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "keepalive": "5" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_2.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_2.json new file mode 100644 index 000000000000..4b5c2bec220b --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_2.json @@ -0,0 +1,16 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": {} + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "holdtime": "240" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v4.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v4.conf new file mode 100644 index 000000000000..a6102cdb87a2 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v4.conf @@ -0,0 +1,16 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + neighbor 10.10.10.10 timers 5 30 + neighbor 10.10.10.10 shutdown + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 route-reflector-client + neighbor 10.10.10.10 next-hop-self + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v6.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v6.conf new file mode 100644 index 000000000000..aa06657d91a8 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v6.conf @@ -0,0 +1,16 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor fc::10 remote-as 555 + neighbor fc::10 description remote_peer + neighbor fc::10 timers 5 30 + neighbor fc::10 shutdown + address-family ipv6 + neighbor fc::10 peer-group PEER_V6 + neighbor fc::10 route-reflector-client + neighbor fc::10 next-hop-self + neighbor fc::10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v4.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v4.conf new file mode 100644 index 000000000000..2990d5aef7c7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v4.conf @@ -0,0 +1,12 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v6.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v6.conf new file mode 100644 index 000000000000..38ec714894ae --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v6.conf @@ -0,0 +1,12 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor fc00::2 remote-as 555 + neighbor fc00::2 description remote_peer + address-family ipv6 + neighbor fc00::2 peer-group PEER_V6 + neighbor fc00::2 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_l2vpn.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_l2vpn.conf new file mode 100644 index 000000000000..b30eaaa62a35 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_l2vpn.conf @@ -0,0 +1,16 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family + address-family l2vpn evpn + neighbor 10.10.10.10 activate + advertise-all-vni + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_1.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_1.conf new file mode 100644 index 000000000000..9303e3b9ab7f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_1.conf @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + neighbor 10.10.10.10 shutdown + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_2.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_2.conf new file mode 100644 index 000000000000..2990d5aef7c7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_2.conf @@ -0,0 +1,12 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_1.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_1.conf new file mode 100644 index 000000000000..ffca0e6b69e6 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_1.conf @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + neighbor 10.10.10.10 timers 5 180 + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_2.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_2.conf new file mode 100644 index 000000000000..3a8ac3d90e3f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_2.conf @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + neighbor 10.10.10.10 timers 60 240 + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_all.json new file mode 100644 index 000000000000..0820dd4050f9 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_all.json @@ -0,0 +1,10 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "ToRRouter" + } + }, + "CONFIG_DB__BGP_BBR": { + "status": "enabled" + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_base.json b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_base.json new file mode 100644 index 000000000000..efee873fe726 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_base.json @@ -0,0 +1,10 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "LeafRouter" + } + }, + "CONFIG_DB__BGP_BBR": { + "status": "disabled" + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all.conf new file mode 100644 index 000000000000..afa7201b742a --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all.conf @@ -0,0 +1,20 @@ +! +! template: bgpd/templates/general/peer-group.conf.j2 +! + neighbor PEER_V4 peer-group + neighbor PEER_V6 peer-group + address-family ipv4 + neighbor PEER_V4 allowas-in 1 + neighbor PEER_V4 soft-reconfiguration inbound + neighbor PEER_V4 route-map FROM_BGP_PEER_V4 in + neighbor PEER_V4 route-map TO_BGP_PEER_V4 out + exit-address-family + address-family ipv6 + neighbor PEER_V6 allowas-in 1 + neighbor PEER_V6 soft-reconfiguration inbound + neighbor PEER_V6 route-map FROM_BGP_PEER_V6 in + neighbor PEER_V6 route-map TO_BGP_PEER_V6 out + exit-address-family +! +! end of template: bgpd/templates/general/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_base.conf b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_base.conf new file mode 100644 index 000000000000..3bef9fe4fdc2 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_base.conf @@ -0,0 +1,18 @@ +! +! template: bgpd/templates/general/peer-group.conf.j2 +! + neighbor PEER_V4 peer-group + neighbor PEER_V6 peer-group + address-family ipv4 + neighbor PEER_V4 soft-reconfiguration inbound + neighbor PEER_V4 route-map FROM_BGP_PEER_V4 in + neighbor PEER_V4 route-map TO_BGP_PEER_V4 out + exit-address-family + address-family ipv6 + neighbor PEER_V6 soft-reconfiguration inbound + neighbor PEER_V6 route-map FROM_BGP_PEER_V6 in + neighbor PEER_V6 route-map TO_BGP_PEER_V6 out + exit-address-family +! +! end of template: bgpd/templates/general/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_all.json new file mode 100644 index 000000000000..0e08c6a51d03 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_all.json @@ -0,0 +1,12 @@ +{ + "loopback0_ipv4": "10.10.10.10/32", + "constants": { + "bgp": { + "allow_list": { + "enabled": true, + "drop_community": "12345:12345" + } + } + }, + "allow_list_default_action": "permit" +} diff --git a/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_base.json b/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_base.json new file mode 100644 index 000000000000..b752581e3096 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_base.json @@ -0,0 +1,10 @@ +{ + "loopback0_ipv4": "10.10.10.10/32", + "constants": { + "bgp": { + "allow_list": { + "enabled": false + } + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_deny.json b/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_deny.json new file mode 100644 index 000000000000..b2799abfaa0f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_deny.json @@ -0,0 +1,12 @@ +{ + "loopback0_ipv4": "10.10.10.10/32", + "constants": { + "bgp": { + "allow_list": { + "enabled": true, + "drop_community": "12345:12345" + } + } + }, + "allow_list_default_action": "deny" +} diff --git a/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_all.conf new file mode 100644 index 000000000000..8d0c17d592b8 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_all.conf @@ -0,0 +1,44 @@ +! +! template: bgpd/templates/general/policies.conf.j2 +! +! please don't remove. 65535 entries are default rules +! which works when allow_list is enabled, but new configuration +! is not applied +! +route-map ALLOW_LIST_DEPLOYMENT_ID_0_V4 permit 65535 + set community 12345:12345 additive +! +route-map ALLOW_LIST_DEPLOYMENT_ID_0_V6 permit 65535 + set community 12345:12345 additive +! +bgp community-list standard allow_list_default_community permit no-export +bgp community-list standard allow_list_default_community permit 12345:12345 +! +route-map FROM_BGP_PEER_V4 permit 10 + call ALLOW_LIST_DEPLOYMENT_ID_0_V4 + on-match next +! +route-map FROM_BGP_PEER_V4 permit 11 + match community allow_list_default_community +! +route-map FROM_BGP_PEER_V6 permit 10 + call ALLOW_LIST_DEPLOYMENT_ID_0_V6 + on-match next +! +route-map FROM_BGP_PEER_V6 permit 11 + match community allow_list_default_community +! +route-map FROM_BGP_PEER_V4 permit 100 +! +route-map TO_BGP_PEER_V4 permit 100 +! +route-map FROM_BGP_PEER_V6 permit 1 + on-match next + set ipv6 next-hop prefer-global +! +route-map FROM_BGP_PEER_V6 permit 100 +! +route-map TO_BGP_PEER_V6 permit 100 +! +! end of template: bgpd/templates/general/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_base.conf b/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_base.conf new file mode 100644 index 000000000000..8f7631caabd8 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_base.conf @@ -0,0 +1,17 @@ +! +! template: bgpd/templates/general/policies.conf.j2 +! +route-map FROM_BGP_PEER_V4 permit 100 +! +route-map TO_BGP_PEER_V4 permit 100 +! +route-map FROM_BGP_PEER_V6 permit 1 + on-match next + set ipv6 next-hop prefer-global +! +route-map FROM_BGP_PEER_V6 permit 100 +! +route-map TO_BGP_PEER_V6 permit 100 +! +! end of template: bgpd/templates/general/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_deny.conf b/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_deny.conf new file mode 100644 index 000000000000..661414bd579c --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_deny.conf @@ -0,0 +1,44 @@ +! +! template: bgpd/templates/general/policies.conf.j2 +! +! please don't remove. 65535 entries are default rules +! which works when allow_list is enabled, but new configuration +! is not applied +! +route-map ALLOW_LIST_DEPLOYMENT_ID_0_V4 permit 65535 + set community no-export additive +! +route-map ALLOW_LIST_DEPLOYMENT_ID_0_V6 permit 65535 + set community no-export additive +! +bgp community-list standard allow_list_default_community permit no-export +bgp community-list standard allow_list_default_community permit 12345:12345 +! +route-map FROM_BGP_PEER_V4 permit 10 + call ALLOW_LIST_DEPLOYMENT_ID_0_V4 + on-match next +! +route-map FROM_BGP_PEER_V4 permit 11 + match community allow_list_default_community +! +route-map FROM_BGP_PEER_V6 permit 10 + call ALLOW_LIST_DEPLOYMENT_ID_0_V6 + on-match next +! +route-map FROM_BGP_PEER_V6 permit 11 + match community allow_list_default_community +! +route-map FROM_BGP_PEER_V4 permit 100 +! +route-map TO_BGP_PEER_V4 permit 100 +! +route-map FROM_BGP_PEER_V6 permit 1 + on-match next + set ipv6 next-hop prefer-global +! +route-map FROM_BGP_PEER_V6 permit 100 +! +route-map TO_BGP_PEER_V6 permit 100 +! +! end of template: bgpd/templates/general/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_back_v4.json b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_back_v4.json new file mode 100644 index 000000000000..c2391674a56e --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_back_v4.json @@ -0,0 +1,23 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "sub_role": "BackEnd" + } + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "keepalive": "5", + "holdtime": "30", + "admin_status": "down", + "ASIC": "something", + "rrclient": "1", + "nhopself": "1" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_back_v6.json b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_back_v6.json new file mode 100644 index 000000000000..d19139a75a88 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_back_v6.json @@ -0,0 +1,23 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "sub_role": "BackEnd" + } + }, + "neighbor_addr": "fc::10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "keepalive": "5", + "holdtime": "30", + "admin_status": "down", + "ASIC": "something", + "rrclient": "1", + "nhopself": "1" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_front_v4.json b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_front_v4.json new file mode 100644 index 000000000000..6f1b5a735355 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_front_v4.json @@ -0,0 +1,21 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "sub_role": "FrontEnd" + } + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "keepalive": "5", + "holdtime": "30", + "admin_status": "down", + "ASIC": "something" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_front_v6.json b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_front_v6.json new file mode 100644 index 000000000000..becb1f00fbfe --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/param_front_v6.json @@ -0,0 +1,21 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "sub_role": "FrontEnd" + } + }, + "neighbor_addr": "fc::10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "keepalive": "5", + "holdtime": "30", + "admin_status": "down", + "ASIC": "something" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_back_v4.conf b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_back_v4.conf new file mode 100644 index 000000000000..fc7b82a64acc --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_back_v4.conf @@ -0,0 +1,16 @@ +! +! template: bgpd/templates/internal/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + neighbor 10.10.10.10 timers 3 10 + address-family ipv4 + neighbor 10.10.10.10 peer-group INTERNAL_PEER_V4 + neighbor 10.10.10.10 route-map FROM_BGP_INTERNAL_PEER_V4 in + neighbor 10.10.10.10 route-reflector-client + neighbor 10.10.10.10 next-hop-self force + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/internal/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_back_v6.conf b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_back_v6.conf new file mode 100644 index 000000000000..74cececad969 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_back_v6.conf @@ -0,0 +1,16 @@ +! +! template: bgpd/templates/internal/instance.conf.j2 +! + neighbor fc::10 remote-as 555 + neighbor fc::10 description remote_peer + neighbor fc::10 timers 3 10 + address-family ipv6 + neighbor fc::10 peer-group INTERNAL_PEER_V6 + neighbor fc::10 route-map FROM_BGP_INTERNAL_PEER_V6 in + neighbor fc::10 route-reflector-client + neighbor fc::10 next-hop-self force + neighbor fc::10 activate + exit-address-family +! +! end of template: bgpd/templates/internal/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_front_v4.conf b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_front_v4.conf new file mode 100644 index 000000000000..95eb985b1546 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_front_v4.conf @@ -0,0 +1,14 @@ +! +! template: bgpd/templates/internal/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + neighbor 10.10.10.10 timers 3 10 + address-family ipv4 + neighbor 10.10.10.10 peer-group INTERNAL_PEER_V4 + neighbor 10.10.10.10 next-hop-self force + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/internal/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_front_v6.conf b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_front_v6.conf new file mode 100644 index 000000000000..a4a4648e4855 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/instance.conf/result_front_v6.conf @@ -0,0 +1,14 @@ +! +! template: bgpd/templates/internal/instance.conf.j2 +! + neighbor fc::10 remote-as 555 + neighbor fc::10 description remote_peer + neighbor fc::10 timers 3 10 + address-family ipv6 + neighbor fc::10 peer-group INTERNAL_PEER_V6 + neighbor fc::10 next-hop-self force + neighbor fc::10 activate + exit-address-family +! +! end of template: bgpd/templates/internal/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/param_back.json b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/param_back.json new file mode 100644 index 000000000000..c3269a7da0e5 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/param_back.json @@ -0,0 +1,8 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "LeafRouter", + "sub_role": "BackEnd" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/param_front.json b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/param_front.json new file mode 100644 index 000000000000..2fbedc92c963 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/param_front.json @@ -0,0 +1,8 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "LeafRouter", + "sub_role": "FrontEnd" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_back.conf b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_back.conf new file mode 100644 index 000000000000..15076685eb1a --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_back.conf @@ -0,0 +1,20 @@ +! +! template: bgpd/templates/internal/peer-group.conf.j2 +! + neighbor INTERNAL_PEER_V4 peer-group + neighbor INTERNAL_PEER_V6 peer-group + address-family ipv4 + neighbor INTERNAL_PEER_V4 route-reflector-client + neighbor INTERNAL_PEER_V4 soft-reconfiguration inbound + neighbor INTERNAL_PEER_V4 route-map FROM_BGP_INTERNAL_PEER_V4 in + neighbor INTERNAL_PEER_V4 route-map TO_BGP_INTERNAL_PEER_V4 out + exit-address-family + address-family ipv6 + neighbor INTERNAL_PEER_V6 route-reflector-client + neighbor INTERNAL_PEER_V6 soft-reconfiguration inbound + neighbor INTERNAL_PEER_V6 route-map FROM_BGP_INTERNAL_PEER_V6 in + neighbor INTERNAL_PEER_V6 route-map TO_BGP_INTERNAL_PEER_V6 out + exit-address-family +! +! end of template: bgpd/templates/internal/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_front.conf b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_front.conf new file mode 100644 index 000000000000..8f4aa450f5db --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_front.conf @@ -0,0 +1,18 @@ +! +! template: bgpd/templates/internal/peer-group.conf.j2 +! + neighbor INTERNAL_PEER_V4 peer-group + neighbor INTERNAL_PEER_V6 peer-group + address-family ipv4 + neighbor INTERNAL_PEER_V4 soft-reconfiguration inbound + neighbor INTERNAL_PEER_V4 route-map FROM_BGP_INTERNAL_PEER_V4 in + neighbor INTERNAL_PEER_V4 route-map TO_BGP_INTERNAL_PEER_V4 out + exit-address-family + address-family ipv6 + neighbor INTERNAL_PEER_V6 soft-reconfiguration inbound + neighbor INTERNAL_PEER_V6 route-map FROM_BGP_INTERNAL_PEER_V6 in + neighbor INTERNAL_PEER_V6 route-map TO_BGP_INTERNAL_PEER_V6 out + exit-address-family +! +! end of template: bgpd/templates/internal/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_back.json b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_back.json new file mode 100644 index 000000000000..148456fe960f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_back.json @@ -0,0 +1,8 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "sub_role": "BackEnd" + } + }, + "loopback0_ipv4": "10.10.10.10/32" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_front.json b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_front.json new file mode 100644 index 000000000000..68c27766d257 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_front.json @@ -0,0 +1,8 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "sub_role": "FrontkEnd" + } + }, + "loopback0_ipv4": "10.10.10.10/32" +} diff --git a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_back.conf b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_back.conf new file mode 100644 index 000000000000..81bf0808f77a --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_back.conf @@ -0,0 +1,23 @@ +! +! template: bgpd/templates/internal/policies.conf.j2 +! +route-map FROM_BGP_INTERNAL_PEER_V4 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V4 permit 100 +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 1 + on-match next + set ipv6 next-hop prefer-global +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V6 permit 100 +! +route-map FROM_BGP_INTERNAL_PEER_V4 permit 2 + set originator-id 10.10.10.10 +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 2 + set originator-id 10.10.10.10 +! +! end of template: bgpd/templates/internal/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_front.conf b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_front.conf new file mode 100644 index 000000000000..94dc55a5458f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_front.conf @@ -0,0 +1,17 @@ +! +! template: bgpd/templates/internal/policies.conf.j2 +! +route-map FROM_BGP_INTERNAL_PEER_V4 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V4 permit 100 +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 1 + on-match next + set ipv6 next-hop prefer-global +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V6 permit 100 +! +! end of template: bgpd/templates/internal/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/param_all.json new file mode 100644 index 000000000000..9ac3ceda978a --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/param_all.json @@ -0,0 +1,12 @@ +{ + "bgp_asn": "555", + "neighbor_addr": "10.20.30.40", + "bgp_session": { + "name": "monitor" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/result_all.conf new file mode 100644 index 000000000000..c8faaa895bd7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/result_all.conf @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/monitors/instance.conf.j2 +! + neighbor 10.20.30.40 remote-as 555 + neighbor 10.20.30.40 peer-group BGPMON + neighbor 10.20.30.40 description monitor + neighbor 10.20.30.40 activate + address-family ipv6 + neighbor 10.20.30.40 activate + exit-address-family +! +! end of template: bgpd/templates/BGPMON/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/param_all.json new file mode 100644 index 000000000000..4f45f8a0f3f4 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/param_all.json @@ -0,0 +1,3 @@ +{ + "loopback0_ipv4": "1.1.1.1/32" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/result_all.conf new file mode 100644 index 000000000000..d5e9624ff1a5 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/result_all.conf @@ -0,0 +1,12 @@ +! +! template: bgpd/templates/BGPMON/peer-group.conf.j2 +! + neighbor BGPMON peer-group + neighbor BGPMON update-source 1.1.1.1 + neighbor BGPMON route-map FROM_BGPMON in + neighbor BGPMON route-map TO_BGPMON out + neighbor BGPMON send-community + neighbor BGPMON maximum-prefix 1 +! +! end of template: bgpd/templates/BGPMON/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/param_all.json new file mode 100644 index 000000000000..9e26dfeeb6e6 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/param_all.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/result_all.conf new file mode 100644 index 000000000000..8d53991064de --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/result_all.conf @@ -0,0 +1,9 @@ +! +! template: bgpd/templates/BGPMON/policies.conf.j2 +! +route-map FROM_BGPMON deny 10 +! +route-map TO_BGPMON permit 10 +! +! end of template: bgpd/templates/BGPMON/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.conf new file mode 100644 index 000000000000..43a65bd2dd61 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.conf @@ -0,0 +1,81 @@ +! +! template: bgpd/bgpd.conf.j2 +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +! template: common/daemons.common.conf.j2 +! +hostname new_hostname +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +agentx +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 55.55.55.55/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00::/64 +! +ip prefix-list LOCAL_VLAN_IPV4_PREFIX seq 5 permit 10.10.10.0/24 +! +ipv6 prefix-list LOCAL_VLAN_IPV6_PREFIX seq 10 permit fc01::/64 +! +route-map HIDE_INTERNAL permit 10 + set community local-AS +! +router bgp 55555 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 480 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 55.55.55.55 +! + network 55.55.55.55/32 +! + address-family ipv6 + network fc00::1/64 + exit-address-family +! + network 10.10.10.1/24 + address-family ipv6 + network fc01::1/64 + exit-address-family +! + address-family ipv4 + redistribute connected route-map HIDE_INTERNAL + exit-address-family + address-family ipv6 + redistribute connected route-map HIDE_INTERNAL + exit-address-family +! + address-family ipv4 + maximum-paths 32 + exit-address-family + address-family ipv6 + maximum-paths 32 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +!! +! end of template: bgpd/bgpd.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.json new file mode 100644 index 000000000000..17e32589d84c --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.json @@ -0,0 +1,33 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "new_hostname", + "bgp_asn": "55555", + "sub_role": "FrontEnd" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|55.55.55.55/32": {}, + "Loopback0|fc00::1/128": {} + }, + "VLAN_INTERFACE": { + "Vlan10|10.10.10.1/24": {}, + "Vlan10|fc01::1/64": {} + }, + "constants": { + "bgp": { + "multipath_relax": { + "enabled": true + }, + "graceful_restart": { + "enabled": true, + "restart_time": 480 + }, + "maximum_paths": { + "enabled": true, + "ipv4": 32, + "ipv6": 32 + } + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.conf new file mode 100644 index 000000000000..4a749516fe18 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.conf @@ -0,0 +1,61 @@ +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 55.55.55.55/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00::/64 +! +ip prefix-list LOCAL_VLAN_IPV4_PREFIX seq 5 permit 10.10.10.0/24 +! +ipv6 prefix-list LOCAL_VLAN_IPV6_PREFIX seq 10 permit fc01::/64 +! +route-map HIDE_INTERNAL permit 10 + set community local-AS +! +router bgp 55555 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 480 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 55.55.55.55 +! + network 55.55.55.55/32 +! + address-family ipv6 + network fc00::1/64 + exit-address-family +! + network 10.10.10.1/24 + address-family ipv6 + network fc01::1/64 + exit-address-family +! + address-family ipv4 + redistribute connected route-map HIDE_INTERNAL + exit-address-family + address-family ipv6 + redistribute connected route-map HIDE_INTERNAL + exit-address-family +! + address-family ipv4 + maximum-paths 32 + exit-address-family + address-family ipv6 + maximum-paths 32 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.json new file mode 100644 index 000000000000..3d5d07d95f09 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.json @@ -0,0 +1,35 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "55555", + "sub_role": "FrontEnd" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|55.55.55.55/32": {}, + "Loopback0|fc00::1/128": {} + }, + "VLAN_INTERFACE": { + "Vlan10|10.10.10.1/24": {}, + "Vlan10|fc01::1/64": {}, + "Vlan20": {"vnet_name": "Vnet1"}, + "Vlan20|20.20.20.1/24": {}, + "Vlan20|fd01::1/64": {} + }, + "constants": { + "bgp": { + "multipath_relax": { + "enabled": true + }, + "graceful_restart": { + "enabled": true, + "restart_time": 480 + }, + "maximum_paths": { + "enabled": true, + "ipv4": 32, + "ipv6": 32 + } + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.conf new file mode 100644 index 000000000000..77cc9d6fffd8 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.conf @@ -0,0 +1,23 @@ +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 55.55.55.55/32 +! +router bgp 55555 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp router-id 55.55.55.55 +! + network 55.55.55.55/32 +! +! end of template: bgpd/bgpd.main.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.json new file mode 100644 index 000000000000..692d4c78f0b9 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.json @@ -0,0 +1,19 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "55555", + "sub_role": "" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|55.55.55.55/32": {}, + "Loopback1|fc00::1/128": {} + }, + "constants": { + "bgp": { + "multipath_relax": {}, + "graceful_restart": {}, + "maximum_paths": {} + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.conf new file mode 100644 index 000000000000..30fc479d6af8 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.conf @@ -0,0 +1,61 @@ +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 55.55.55.55/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00::/64 +! +ip prefix-list LOCAL_VLAN_IPV4_PREFIX seq 5 permit 10.10.10.0/24 +! +ipv6 prefix-list LOCAL_VLAN_IPV6_PREFIX seq 10 permit fc01::/64 +! +route-map HIDE_INTERNAL permit 10 + set community local-AS +! +router bgp 55555 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 55.55.55.55 +! + network 55.55.55.55/32 +! + address-family ipv6 + network fc00::1/64 + exit-address-family +! + network 10.10.10.1/24 + address-family ipv6 + network fc01::1/64 + exit-address-family +! + address-family ipv4 + redistribute connected route-map HIDE_INTERNAL + exit-address-family + address-family ipv6 + redistribute connected route-map HIDE_INTERNAL + exit-address-family +! + address-family ipv4 + maximum-paths 64 + exit-address-family + address-family ipv6 + maximum-paths 64 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.json new file mode 100644 index 000000000000..e841437650ac --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.json @@ -0,0 +1,32 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "55555", + "sub_role": "FrontEnd" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|55.55.55.55/32": {}, + "Loopback0|fc00::1/128": {} + }, + "VLAN_INTERFACE": { + "Vlan10|10.10.10.1/24": {}, + "Vlan10|fc01::1/64": {}, + "Vlan20": {"vnet_name": "Vnet1"}, + "Vlan20|20.20.20.1/24": {}, + "Vlan20|fd01::1/64": {} + }, + "constants": { + "bgp": { + "multipath_relax": { + "enabled": true + }, + "graceful_restart": { + "enabled": true + }, + "maximum_paths": { + "enabled": true + } + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.conf new file mode 100644 index 000000000000..581eb107ec23 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.conf @@ -0,0 +1,39 @@ +! +! Vnet BGP instance +router bgp 555 vrf First + no bgp default ipv4-unicast + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp router-id 10.20.30.40 + neighbor 10.10.10.1 remote-as 10 + neighbor 10.10.10.1 description session1 + address-family ipv4 unicast + neighbor 10.10.10.1 activate + neighbor 10.10.10.1 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + address-family l2vpn evpn + advertise ipv4 unicast + exit-address-family +router bgp 555 vrf Second + no bgp default ipv4-unicast + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp router-id 10.20.30.40 + neighbor 20.20.20.1 remote-as 20 + neighbor 20.20.20.1 description session2 + address-family ipv4 unicast + neighbor 20.20.20.1 activate + neighbor 20.20.20.1 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + address-family l2vpn evpn + advertise ipv4 unicast + exit-address-family +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.json new file mode 100644 index 000000000000..d6f09fb1139e --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.json @@ -0,0 +1,42 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "555" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|10.20.30.40/32": {} + }, + "VNET": { + "First": { + "vni": 10 + }, + "Second": { + "vni": 20 + } + }, + "INTERFACE": { + "Ethernet0": { + "vnet_name": "First" + }, + "Ethernet0|10.10.10.10/24": {}, + "Ethernet8": { + "vnet_name": "Second" + }, + "Ethernet8|20.20.20.20/24": {}, + "Ethernet10": {}, + "Ethernet10|20.20.20.20/24": {} + }, + "BGP_NEIGHBOR": { + "10.10.10.1": { + "asn": "10", + "name": "session1", + "local_addr": "10.10.10.10" + }, + "20.20.20.1": { + "asn": "20", + "name": "session2", + "local_addr": "20.20.20.20" + } + } +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf new file mode 100644 index 000000000000..14d7b99d07ed --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf @@ -0,0 +1,10 @@ +! template: common/daemons.common.conf.j2 +! +hostname test_hostname +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2 diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf.json new file mode 100644 index 000000000000..8ef3e43694a7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf.json @@ -0,0 +1,7 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "test_hostname" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf @@ -0,0 +1 @@ + diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf.json new file mode 100644 index 000000000000..9e26dfeeb6e6 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.conf new file mode 100644 index 000000000000..37b7691ad95f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.conf @@ -0,0 +1,103 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr.conf.j2 with config DB data +! file: frr.conf +! +! template: common/daemons.common.conf.j2 +! +hostname test_hostname +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +agentx +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface Ethernet0 +link-detect +! +interface Ethernet4 +link-detect +! +interface PortChannel10 +link-detect +! +interface PortChannel20 +link-detect +! +!! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.10.10.1 200 +!! +! +! +! add static ipv6 /64 loopback route to allow bgpd to advertise the loopback route prefix +ipv6 route fc00::/64 Loopback0 +! +!! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 55.55.55.55/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00::/64 +! +ip prefix-list LOCAL_VLAN_IPV4_PREFIX seq 5 permit 10.10.10.0/24 +! +ipv6 prefix-list LOCAL_VLAN_IPV6_PREFIX seq 10 permit fc01::/64 +! +route-map HIDE_INTERNAL permit 10 + set community local-AS +! +router bgp 55555 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 480 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 55.55.55.55 +! + network 55.55.55.55/32 +! + address-family ipv6 + network fc00::1/64 + exit-address-family +! + network 10.10.10.1/24 + address-family ipv6 + network fc01::1/64 + exit-address-family +! + address-family ipv4 + redistribute connected route-map HIDE_INTERNAL + exit-address-family + address-family ipv6 + redistribute connected route-map HIDE_INTERNAL + exit-address-family +! + address-family ipv4 + maximum-paths 32 + exit-address-family + address-family ipv6 + maximum-paths 32 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +!! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.json new file mode 100644 index 000000000000..d81eba2b0fe6 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.json @@ -0,0 +1,46 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "55555", + "hostname": "test_hostname", + "sub_role": "FrontEnd" + } + }, + "INTERFACE": { + "Ethernet0|10.20.30.40/24": {}, + "Ethernet4|20.20.30.40/24": {} + }, + "PORTCHANNEL": { + "PortChannel10": {}, + "PortChannel20": {} + }, + "MGMT_INTERFACE": { + "eth0|10.10.10.10/24": { + "gwaddr": "10.10.10.1" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|55.55.55.55/32": {}, + "Loopback0|fc00::1/128": {} + }, + "VLAN_INTERFACE": { + "Vlan10|10.10.10.1/24": {}, + "Vlan10|fc01::1/64": {} + }, + "constants": { + "bgp": { + "multipath_relax": { + "enabled": true + }, + "graceful_restart": { + "enabled": true, + "restart_time": 480 + }, + "maximum_paths": { + "enabled": true, + "ipv4": 32, + "ipv6": 32 + } + } + } +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate new file mode 100644 index 000000000000..74f107495298 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate @@ -0,0 +1,17 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? +## vtysh script start from next line, which line number MUST equal in 'sed' command above +configure terminal + router bgp 12345 + neighbor 10.20.30.40 route-map ISOLATE out + address-family ipv6 + neighbor fc00::1 route-map ISOLATE out + exit-address-family + exit +exit +clear ip bgp 10.20.30.40 soft out +clear ip bgp fc00::1 soft out diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate.json new file mode 100644 index 000000000000..012b69ef3036 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate.json @@ -0,0 +1,11 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "12345" + } + }, + "BGP_NEIGHBOR": { + "10.20.30.40": {}, + "fc00::1": {} + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate new file mode 100644 index 000000000000..b9476d0b7107 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate @@ -0,0 +1,17 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? +## vtysh script start from next line, which line number MUST equal in 'sed' command above +configure terminal + router bgp 12345 + no neighbor 10.20.30.40 route-map ISOLATE out + address-family ipv6 + no neighbor fc00::1 route-map ISOLATE out + exit-address-family + exit +exit +clear ip bgp 10.20.30.40 soft out +clear ip bgp fc00::1 soft out diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate.json new file mode 100644 index 000000000000..012b69ef3036 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate.json @@ -0,0 +1,11 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "12345" + } + }, + "BGP_NEIGHBOR": { + "10.20.30.40": {}, + "fc00::1": {} + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf new file mode 100644 index 000000000000..59bbe983af76 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf @@ -0,0 +1,23 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr/staticd.conf.j2 using config DB data +! file: staticd.conf +! +! template: common/daemons.common.conf.j2 +! +hostname new_hostname +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.10.10.1 200 +!! +! +! add static ipv6 /64 loopback route to allow bgpd to advertise the loopback route prefix +ipv6 route fc00:1::/64 Loopback0 +!! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf.json new file mode 100644 index 000000000000..0cbd67c7ef68 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf.json @@ -0,0 +1,15 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "new_hostname" + } + }, + "MGMT_INTERFACE": { + "eth0|10.10.10.10/24": { + "gwaddr": "10.10.10.1" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|FC00:1::32/128": {} + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf new file mode 100644 index 000000000000..11adb98ebc3c --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf @@ -0,0 +1,4 @@ +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.10.10.1 200 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf.json new file mode 100644 index 000000000000..80cd218a790e --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf.json @@ -0,0 +1,7 @@ +{ + "MGMT_INTERFACE": { + "eth0|10.10.10.10/24": { + "gwaddr": "10.10.10.1" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.loopback_route.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.loopback_route.conf new file mode 100644 index 000000000000..27078305d461 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.loopback_route.conf @@ -0,0 +1,4 @@ +! +! add static ipv6 /64 loopback route to allow bgpd to advertise the loopback route prefix +ipv6 route fc00:1::/64 Loopback0 +!! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.loopback_route.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.loopback_route.conf.json new file mode 100644 index 000000000000..ffd3c2a2a117 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.loopback_route.conf.json @@ -0,0 +1,5 @@ +{ + "LOOPBACK_INTERFACE": { + "Loopback0|FC00:1::32/128": {} + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.conf new file mode 100644 index 000000000000..2ea4111dfc26 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.conf @@ -0,0 +1,5 @@ +route-map test_rm_name permit 20 + match ip address prefix-list PL_LoopbackV4 + set community 12345:555 +route-map test_rm_name deny 30 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.json new file mode 100644 index 000000000000..807dfe7e1a0c --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.json @@ -0,0 +1,10 @@ +{ + "constants": { + "bgp": { + "traffic_shift_community": "12345:555" + } + }, + "route_map_name": "test_rm_name", + "ip_version": "V4", + "ip_protocol": "ip" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.conf new file mode 100644 index 000000000000..2adeac6e0ef7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.conf @@ -0,0 +1,3 @@ +no route-map test_rm permit 20 +no route-map test_rm deny 30 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.json new file mode 100644 index 000000000000..da070431493d --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.json @@ -0,0 +1,3 @@ +{ + "route_map_name": "test_rm" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.conf new file mode 100644 index 000000000000..ddd129bcd18b --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.conf @@ -0,0 +1,16 @@ +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface Ethernet0 +link-detect +! +interface Ethernet4 +link-detect +! +interface PortChannel10 +link-detect +! +interface PortChannel20 +link-detect +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.json new file mode 100644 index 000000000000..e9c1bcba418d --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.json @@ -0,0 +1,10 @@ +{ + "INTERFACE": { + "Ethernet0|10.20.30.40/24": {}, + "Ethernet4|20.20.30.40/24": {} + }, + "PORTCHANNEL": { + "PortChannel10": {}, + "PortChannel20": {} + } +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.conf new file mode 100644 index 000000000000..b543d24e0023 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.conf @@ -0,0 +1,8 @@ +! +! Set ip source to loopback for bgp learned routes +! +route-map new_rm_name permit 10 + set src 10.20.30.40 +! +ipv4 protocol bgp route-map new_rm_name +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.json new file mode 100644 index 000000000000..2e76d46fd106 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.json @@ -0,0 +1,5 @@ +{ + "rm_name": "new_rm_name", + "lo_ip": "10.20.30.40", + "ip_proto": "v4" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf new file mode 100644 index 000000000000..ac2d8dac88f2 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf @@ -0,0 +1,38 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/zebra/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! template: common/daemons.common.conf.j2 +! +hostname new_hostname +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +vrf First +vni 10 +! +vrf Second +vni 20 +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface Ethernet0 +link-detect +! +interface Ethernet4 +link-detect +! +interface PortChannel10 +link-detect +! +interface PortChannel20 +link-detect +! +!! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf.json new file mode 100644 index 000000000000..9b63ff526fb9 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf.json @@ -0,0 +1,23 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "new_hostname" + } + }, + "VNET": { + "First": { + "vni": 10 + }, + "Second": { + "vni": 20 + } + }, + "INTERFACE": { + "Ethernet0|10.20.30.40/24": {}, + "Ethernet4|20.20.30.40/24": {} + }, + "PORTCHANNEL": { + "PortChannel10": {}, + "PortChannel20": {} + } +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/swsscommon_test.py b/src/sonic-bgpcfgd/tests/swsscommon_test.py new file mode 100644 index 000000000000..46984bafc609 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/swsscommon_test.py @@ -0,0 +1,4 @@ +from unittest.mock import MagicMock + + +swsscommon = MagicMock(CFG_DEVICE_METADATA_TABLE_NAME = "DEVICE_METADATA") diff --git a/src/sonic-bgpcfgd/tests/test_allow_list.py b/src/sonic-bgpcfgd/tests/test_allow_list.py new file mode 100644 index 000000000000..cb0896982a39 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_allow_list.py @@ -0,0 +1,959 @@ +from unittest.mock import MagicMock, patch + +import bgpcfgd.frr +from bgpcfgd.directory import Directory +from bgpcfgd.template import TemplateFabric +import bgpcfgd +from copy import deepcopy + + +swsscommon_module_mock = MagicMock() + +global_constants = { + "bgp": { + "allow_list": { + "enabled": True, + "default_pl_rules": { + "v4": [ "deny 0.0.0.0/0 le 17" ], + "v6": [ + "deny 0::/0 le 59", + "deny 0::/0 ge 65" + ] + }, + "default_action": "permit", + "drop_community": "123:123" + } + } +} + +@patch.dict("sys.modules", swsscommon=swsscommon_module_mock) +def set_del_test(op, args, currect_config, expected_config, update_global_default_action=None): + from bgpcfgd.managers_allow_list import BGPAllowListMgr + set_del_test.push_list_called = False + def push_list(args): + set_del_test.push_list_called = True + assert args == expected_config + return True + # + bgpcfgd.frr.run_command = lambda cmd: (0, "", "") + # + cfg_mgr = MagicMock() + cfg_mgr.update.return_value = None + cfg_mgr.push_list = push_list + cfg_mgr.get_text.return_value = currect_config + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': deepcopy(global_constants), + } + + mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") + if update_global_default_action: + mgr.constants["bgp"]["allow_list"]["default_action"] = update_global_default_action + if op == "SET": + mgr.set_handler(*args) + elif op == "DEL": + mgr.del_handler(*args) + else: + assert False, "Wrong operation" + if expected_config: + assert set_del_test.push_list_called, "cfg_mgr.push_list wasn't called" + else: + assert not set_del_test.push_list_called, "cfg_mgr.push_list was called" + +def test_set_handler_with_community(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5|1010:2020", { + "prefixes_v4": "10.20.30.0/24,30.50.0.0/16", + "prefixes_v6": "fc00:20::/64,fc00:30::/64", + }), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive' + ], + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 le 128', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + ] + ) +def test_set_handler_with_community_and_permit_action(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5|1010:2020", { + "prefixes_v4": "10.20.30.0/24,30.50.0.0/16", + "prefixes_v6": "fc00:20::/64,fc00:30::/64", + "default_action":"permit" + }), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive' + ], + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 le 128', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + ] + ) + +def test_set_handler_with_community_and_deny_action(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5|1010:2020", { + "prefixes_v4": "10.20.30.0/24,30.50.0.0/16", + "prefixes_v6": "fc00:20::/64,fc00:30::/64", + "default_action":"deny" + }), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive' + ], + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 le 128', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive' + ] + ) + + +def test_set_handler_no_community(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5", { + "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", + "prefixes_v6": "fc01:20::/64,fc01:30::/64", + }), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + ], + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 le 128', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + ] + ) +def test_set_handler_no_community_with_permit_action(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5", { + "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", + "prefixes_v6": "fc01:20::/64,fc01:30::/64", + "default_action":"permit" + }), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + ], + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 le 128', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + ] + ) +def test_set_handler_no_community_with_deny_action(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5", { + "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", + "prefixes_v6": "fc01:20::/64,fc01:30::/64", + "default_action":"deny" + }), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + ], + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 le 128', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive' + ] + ) + +def test_del_handler_with_community(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5|1010:2020",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 ge 65', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + 'no bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + ] + ) + +def test_del_handler_with_exiting_community_deny_action(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5|1010:2020",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 ge 65', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + 'no bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + ] + ) + + +def test_del_handler_with_exiting_community_permit_action(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5|1010:2020",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 ge 65', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + 'no bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + ] + ) + +def test_del_handler_with_exiting_community_deny_action_global_deny(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5|1010:2020",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 ge 65', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + 'no bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + ], + "deny" + ) + + +def test_del_handler_with_exiting_community_permit_action_global_deny(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5|1010:2020",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 ge 65', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + 'no bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive', + ], + "deny" + ) + + +def test_del_handler_no_community(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 ge 65', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + " " + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + ] + ) +def test_del_handler_with_no_community_deny_action(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 ge 65', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + ] + ) +def test_del_handler_with_no_community_permit_action_global_deny(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 ge 65', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive', + ], + "deny" + ) + + + +def test_set_handler_with_community_data_is_already_presented(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5|1010:2020", { + "prefixes_v4": "10.20.30.0/24,30.50.0.0/16", + "prefixes_v6": "fc00:20::/64,fc00:30::/64", + }), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 le 128', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" + ], + [] + ) + +@patch.dict("sys.modules", swsscommon=swsscommon_module_mock) +def test_set_handler_no_community_data_is_already_presented(): + from bgpcfgd.managers_allow_list import BGPAllowListMgr + cfg_mgr = MagicMock() + cfg_mgr.update.return_value = None + cfg_mgr.get_text.return_value = [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 le 128', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" + ] + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': global_constants, + } + mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") + mgr.set_handler("DEPLOYMENT_ID|5", { + "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", + "prefixes_v6": "fc01:20::/64,fc01:30::/64", + }) + assert not cfg_mgr.push_list.called, "cfg_mgr.push_list was called, but it shouldn't have been" + +def test_del_handler_with_community_no_data(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5|1010:2020",), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive' + ], + [] + ) + +def test_del_handler_no_community_no_data(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5",), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive' + ], + [] + ) + +def test_set_handler_with_community_update_prefixes_add(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5|1010:2020", { + "prefixes_v4": "10.20.30.0/24,30.50.0.0/16,80.90.0.0/16", + "prefixes_v6": "fc00:20::/64,fc00:30::/64,fc02::/64", + }), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 le 128', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" + ], + [ + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 40 permit 80.90.0.0/16 le 32', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 50 permit fc02::/64 le 128', + ] + ) + +def test_set_handler_no_community_update_prefixes_add(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5", { + "prefixes_v4": "20.20.30.0/24,40.50.0.0/16,80.90.0.0/16", + "prefixes_v6": "fc01:20::/64,fc01:30::/64,fc02::/64", + }), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 le 128', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" + ], + [ + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 40 permit 80.90.0.0/16 le 32', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 50 permit fc02::/64 le 128', + ] + ) + +@patch.dict("sys.modules", swsscommon=swsscommon_module_mock) +def test___set_handler_validate(): + from bgpcfgd.managers_allow_list import BGPAllowListMgr + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': global_constants, + } + mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") + data = { + "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", + "prefixes_v6": "fc01:20::/64,fc01:30::/64", + } + assert not mgr._BGPAllowListMgr__set_handler_validate("DEPLOYMENT_ID|5|1010:2020", None) + assert not mgr._BGPAllowListMgr__set_handler_validate("DEPLOYMENT_ID1|5|1010:2020", data) + assert not mgr._BGPAllowListMgr__set_handler_validate("DEPLOYMENT_ID|z|1010:2020", data) + assert not mgr._BGPAllowListMgr__set_handler_validate("DEPLOYMENT_ID|5|1010:2020", { + "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", + "prefixes_v6": "20.20.30.0/24,40.50.0.0/16", + }) + assert not mgr._BGPAllowListMgr__set_handler_validate("DEPLOYMENT_ID|5|1010:2020", { + "prefixes_v4": "fc01:20::/64,fc01:30::/64", + "prefixes_v6": "fc01:20::/64,fc01:30::/64", + }) + +@patch.dict("sys.modules", swsscommon=swsscommon_module_mock) +def test___find_peer_group_by_deployment_id(): + from bgpcfgd.managers_allow_list import BGPAllowListMgr + cfg_mgr = MagicMock() + cfg_mgr.update.return_value = None + cfg_mgr.get_text.return_value = [ + 'router bgp 64601', + ' neighbor BGPSLBPassive peer-group', + ' neighbor BGPSLBPassive remote-as 65432', + ' neighbor BGPSLBPassive passive', + ' neighbor BGPSLBPassive ebgp-multihop 255', + ' neighbor BGPSLBPassive update-source 10.1.0.32', + ' neighbor PEER_V4 peer-group', + ' neighbor PEER_V4_INT peer-group', + ' neighbor PEER_V6 peer-group', + ' neighbor PEER_V6_INT peer-group', + ' neighbor 10.0.0.1 remote-as 64802', + ' neighbor 10.0.0.1 peer-group PEER_V4', + ' neighbor 10.0.0.1 description ARISTA01T1', + ' neighbor 10.0.0.1 timers 3 10', + ' neighbor fc00::2 remote-as 64802', + ' neighbor fc00::2 peer-group PEER_V6', + ' neighbor fc00::2 description ARISTA01T1', + ' neighbor fc00::2 timers 3 10', + ' address-family ipv4 unicast', + ' neighbor BGPSLBPassive activate', + ' neighbor BGPSLBPassive soft-reconfiguration inbound', + ' neighbor BGPSLBPassive route-map FROM_BGP_SPEAKER in', + ' neighbor BGPSLBPassive route-map TO_BGP_SPEAKER out', + ' neighbor PEER_V4 soft-reconfiguration inbound', + ' neighbor PEER_V4 allowas-in 1', + ' neighbor PEER_V4 route-map FROM_BGP_PEER_V4 in', + ' neighbor PEER_V4 route-map TO_BGP_PEER_V4 out', + ' neighbor PEER_V4_INT soft-reconfiguration inbound', + ' neighbor PEER_V4_INT allowas-in 1', + ' neighbor PEER_V4_INT route-map FROM_BGP_PEER_V4 in', + ' neighbor PEER_V4_INT route-map TO_BGP_PEER_V4 out', + ' neighbor 10.0.0.1 activate', + ' exit-address-family', + ' address-family ipv6 unicast', + ' neighbor BGPSLBPassive activate', + ' neighbor PEER_V6 soft-reconfiguration inbound', + ' neighbor PEER_V6 allowas-in 1', + ' neighbor PEER_V6 route-map FROM_BGP_PEER_V6 in', + ' neighbor PEER_V6 route-map TO_BGP_PEER_V6 out', + ' neighbor PEER_V6_INT soft-reconfiguration inbound', + ' neighbor PEER_V6_INT allowas-in 1', + ' neighbor PEER_V6_INT route-map FROM_BGP_PEER_V6 in', + ' neighbor PEER_V6_INT route-map TO_BGP_PEER_V6 out', + ' neighbor fc00::2 activate', + ' exit-address-family', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V4 permit 10', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_1010:1010', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_1010:1010_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V4 permit 65535', + ' set community 5060:12345 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V6 permit 10', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_1010:1010', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_1010:1010_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V6 permit 65535', + ' set community 5060:12345 additive', + 'route-map FROM_BGP_PEER_V4 permit 100', + 'route-map FROM_BGP_PEER_V4 permit 2', + ' call ALLOW_LIST_DEPLOYMENT_ID_0_V4', + ' on-match next', + 'route-map FROM_BGP_PEER_V6 permit 1', + ' set ipv6 next-hop prefer-global ', + 'route-map FROM_BGP_PEER_V6 permit 100', + 'route-map FROM_BGP_PEER_V6 permit 2', + ' call ALLOW_LIST_DEPLOYMENT_ID_0_V6', + ' on-match next', + 'route-map FROM_BGP_SPEAKER permit 10', + 'route-map RM_SET_SRC permit 10', + ' set src 10.1.0.32', + 'route-map RM_SET_SRC6 permit 10', + ' set src FC00:1::32', + 'route-map TO_BGP_PEER_V4 permit 100', + 'route-map TO_BGP_PEER_V6 permit 100', + 'route-map TO_BGP_SPEAKER deny 1', + ] + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': global_constants, + } + mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") + values = mgr._BGPAllowListMgr__find_peer_group_by_deployment_id(0) + assert set(values) == {'PEER_V4_INT', 'PEER_V6_INT', 'PEER_V6', 'PEER_V4'} + +@patch.dict("sys.modules", swsscommon=swsscommon_module_mock) +def test___to_prefix_list(): + from bgpcfgd.managers_allow_list import BGPAllowListMgr + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': global_constants, + } + mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") + + res_v4 = mgr._BGPAllowListMgr__to_prefix_list(mgr.V4, ["1.2.3.4/32", "10.20.20.10/24"]) + assert res_v4 == ["permit 1.2.3.4/32", "permit 10.20.20.10/24 le 32"] + res_v6 = mgr._BGPAllowListMgr__to_prefix_list(mgr.V6, ["fc00::1/128", "fc00::/64"]) + assert res_v6 == ["permit fc00::1/128", "permit fc00::/64 le 128"] + +@patch.dict("sys.modules", swsscommon=swsscommon_module_mock) +def construct_BGPAllowListMgr(constants): + from bgpcfgd.managers_allow_list import BGPAllowListMgr + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': constants, + } + mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") + return mgr + +def test___get_enabled_enabled(): + constants = { + "bgp": { + "allow_list": { + "enabled": True, + } + } + } + mgr = construct_BGPAllowListMgr(constants) + assert mgr._BGPAllowListMgr__get_enabled() + +def test___get_enabled_disabled_1(): + constants = { + "bgp": { + "allow_list": { + "enabled": False, + } + } + } + mgr = construct_BGPAllowListMgr(constants) + assert not mgr._BGPAllowListMgr__get_enabled() + +def test___get_enabled_disabled_2(): + constants = { + "bgp": { + "allow_list": {} + } + } + mgr = construct_BGPAllowListMgr(constants) + assert not mgr._BGPAllowListMgr__get_enabled() + +def test___get_enabled_disabled_3(): + constants = { + "bgp": {} + } + mgr = construct_BGPAllowListMgr(constants) + assert not mgr._BGPAllowListMgr__get_enabled() + +def test___get_enabled_disabled_4(): + constants = {} + mgr = construct_BGPAllowListMgr(constants) + assert not mgr._BGPAllowListMgr__get_enabled() + +def test___get_default_action_deny(): + constants = { + "bgp": { + "allow_list": { + "enabled": True, + "default_action": "deny", + "drop_community": "123:123" + } + } + } + data = {} + mgr = construct_BGPAllowListMgr(constants) + assert mgr._BGPAllowListMgr__get_default_action_community(data) == "no-export" + +def test___get_default_action_permit_1(): + constants = { + "bgp": { + "allow_list": { + "enabled": True, + "default_action": "permit", + "drop_community": "123:123" + } + } + } + data = {} + mgr = construct_BGPAllowListMgr(constants) + assert mgr._BGPAllowListMgr__get_default_action_community(data) == "123:123" + +def test___get_default_action_permit_2(): + constants = { + "bgp": { + "allow_list": { + "enabled": True, + "drop_community": "123:123" + } + } + } + data = {} + mgr = construct_BGPAllowListMgr(constants) + assert mgr._BGPAllowListMgr__get_default_action_community(data) == "123:123" + +def test___get_default_action_permit_3(): + constants = { + "bgp": { + "allow_list": { + "enabled": False, + "drop_community": "123:123" + } + } + } + data = {} + mgr = construct_BGPAllowListMgr(constants) + assert mgr._BGPAllowListMgr__get_default_action_community(data) == "123:123" + +# FIXME: more testcases for coverage diff --git a/src/sonic-bgpcfgd/tests/test_bbr.py b/src/sonic-bgpcfgd/tests/test_bbr.py new file mode 100644 index 000000000000..b11277bae7b8 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_bbr.py @@ -0,0 +1,393 @@ +from unittest.mock import MagicMock, patch + +from bgpcfgd.directory import Directory +from bgpcfgd.template import TemplateFabric +from copy import deepcopy +from . import swsscommon_test + + +with patch.dict("sys.modules", swsscommon=swsscommon_test): + from bgpcfgd.managers_bbr import BBRMgr + +global_constants = { + "bgp": { + "allow_list": { + "enabled": True, + "default_pl_rules": { + "v4": [ "deny 0.0.0.0/0 le 17" ], + "v6": [ + "deny 0::/0 le 59", + "deny 0::/0 ge 65" + ] + } + } + } +} + +def test_constructor():#m1, m2, m3): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': {}, + } + m = BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR") + assert not m.enabled + assert len(m.bbr_enabled_pgs) == 0 + assert m.directory.get("CONFIG_DB", "BGP_BBR", "status") == "disabled" + +@patch('bgpcfgd.managers_bbr.log_info') +def set_handler_common(key, value, + is_enabled, is_valid, + mocked_log_info): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': global_constants, + } + m = BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR") + m.enabled = is_enabled + prepare_config_return_value = ( + [ + ["vtysh", "-c", "clear bgp peer-group PEER_V4 soft in"], + ["vtysh", "-c", "clear bgp peer-group PEER_V6 soft in"] + ], + [ + "PEER_V4", + "PEER_V6" + ] + ) + m._BBRMgr__set_prepare_config = MagicMock(return_value = prepare_config_return_value) + m.cfg_mgr.push_list = MagicMock(return_value = None) + m.cfg_mgr.restart_peer_groups = MagicMock(return_value = None) # FIXME: check for input + res = m.set_handler(key, value) + assert res, "Returns always True" + if not is_enabled: + mocked_log_info.assert_called_with('BBRMgr::BBR is disabled. Drop the request') + else: + if is_valid: + m._BBRMgr__set_prepare_config.assert_called_once_with(value["status"]) + m.cfg_mgr.push_list.assert_called_once_with(prepare_config_return_value[0]) + m.cfg_mgr.restart_peer_groups.assert_called_once_with(prepare_config_return_value[1]) + else: + m._BBRMgr__set_prepare_config.assert_not_called() + m.cfg_mgr.push_list.assert_not_called() + m.cfg_mgr.restart_peer_groups.assert_not_called() + +def test_set_handler_not_enabled_not_valid(): + set_handler_common("anything", {}, False, False) + +def test_set_handler_enabled_not_valid(): + set_handler_common("anything", {}, True, False) + +def test_set_handler_enabled_valid(): + set_handler_common("all", {"status": "enabled"}, True, True) + +@patch('bgpcfgd.managers_bbr.log_err') +def test_del_handler(mocked_log_err): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': global_constants, + } + m = BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR") + m.del_handler("anything") + mocked_log_err.assert_called_with("The 'BGP_BBR' table shouldn't be removed from the db") + +@patch('bgpcfgd.managers_bbr.log_info') +@patch('bgpcfgd.managers_bbr.log_err') +def __init_common(constants, + expected_log_info, expected_log_err, expected_bbr_enabled_pgs, expected_status, + mocked_log_err, mocked_log_info): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': constants, + } + m = BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR") + m._BBRMgr__init() + assert m.bbr_enabled_pgs == expected_bbr_enabled_pgs + assert m.directory.get("CONFIG_DB", "BGP_BBR", "status") == expected_status + if expected_status == "enabled": + assert m.enabled + if expected_log_err is not None: + mocked_log_err.assert_called_with(expected_log_err) + if expected_log_info is not None: + mocked_log_info.assert_called_with(expected_log_info) + +def test___init_1(): + __init_common({}, None, "BBRMgr::Disabled: 'bgp' key is not found in constants", {}, "disabled") + +def test___init_2(): + constants = deepcopy(global_constants) + __init_common(constants, "BBRMgr::Disabled: no bgp.bbr.enabled in the constants", None, {}, "disabled") + +def test___init_3(): + constants = deepcopy(global_constants) + constants["bgp"]["bbr"] = { "123" : False } + __init_common(constants, "BBRMgr::Disabled: no bgp.bbr.enabled in the constants", None, {}, "disabled") + +def test___init_4(): + constants = deepcopy(global_constants) + constants["bgp"]["bbr"] = { "enabled" : False } + __init_common(constants, "BBRMgr::Disabled: no bgp.bbr.enabled in the constants", None, {}, "disabled") + +def test___init_5(): + constants = deepcopy(global_constants) + constants["bgp"]["bbr"] = { "enabled" : True } + __init_common(constants, "BBRMgr::Disabled: no BBR enabled peers", None, {}, "disabled") + +def test___init_6(): + expected_bbr_entries = { + "PEER_V4": ["ipv4"], + "PEER_V6": ["ipv6"], + } + constants = deepcopy(global_constants) + constants["bgp"]["bbr"] = { "enabled" : True } + constants["bgp"]["peers"] = { + "general": { + "bbr": expected_bbr_entries, + } + } + __init_common(constants, "BBRMgr::Initialized and enabled. Default state: 'disabled'", None, expected_bbr_entries, "disabled") + +def test___init_7(): + expected_bbr_entries = { + "PEER_V4": ["ipv4"], + "PEER_V6": ["ipv6"], + } + constants = deepcopy(global_constants) + constants["bgp"]["bbr"] = { "enabled" : True, "default_state": "disabled" } + constants["bgp"]["peers"] = { + "general": { + "bbr": expected_bbr_entries, + } + } + __init_common(constants, "BBRMgr::Initialized and enabled. Default state: 'disabled'", None, expected_bbr_entries, "disabled") + +def test___init_8(): + expected_bbr_entries = { + "PEER_V4": ["ipv4"], + "PEER_V6": ["ipv6"], + } + constants = deepcopy(global_constants) + constants["bgp"]["bbr"] = { "enabled" : True, "default_state": "enabled" } + constants["bgp"]["peers"] = { + "general": { + "bbr": expected_bbr_entries, + } + } + __init_common(constants, "BBRMgr::Initialized and enabled. Default state: 'enabled'", None, expected_bbr_entries, "enabled") + +@patch('bgpcfgd.managers_bbr.log_info') +def read_pgs_common(constants, expected_log_info, expected_bbr_enabled_pgs, mocked_log_info): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': constants, + } + m = BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR") + res = m._BBRMgr__read_pgs() + assert res == expected_bbr_enabled_pgs + if expected_log_info is not None: + mocked_log_info.assert_called_with(expected_log_info) + +def test___read_pgs_no_configuration(): + read_pgs_common(global_constants, "BBRMgr::no 'peers' was found in constants", {}) + +def test___read_pgs_parse_configuration(): + expected_bbr_entries = { + "PEER_V4": ["ipv4", "ipv6"], + "PEER_V6": ["ipv6"], + } + constants = deepcopy(global_constants) + constants["bgp"]["peers"] = { + "general": { + "bbr": expected_bbr_entries, + }, + "dynamic": { + "123": { + "PEER_V8": ["ipv10", "ipv20"], + } + } + } + read_pgs_common(constants, None, expected_bbr_entries) + +@patch('bgpcfgd.managers_bbr.log_err') +def __set_validation_common(key, data, expected_log_err, expected_result, mocked_log_err): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': global_constants, + } + m = BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR") + res = m._BBRMgr__set_validation(key, data) + assert res == expected_result + if expected_log_err is not None: + mocked_log_err.assert_called_with(expected_log_err) + +def test___set_validation_1(): + __set_validation_common("all1", {}, "Invalid key 'all1' for table 'BGP_BBR'. Only key value 'all' is supported", False) + +def test___set_validation_2(): + __set_validation_common("all", {"stat": "enabled"}, "Invalid value '{'stat': 'enabled'}' for table 'BGP_BBR', key 'all'. Key 'status' in data is expected", False) + +def test___set_validation_3(): + __set_validation_common("all", {"status": "enabled1"}, "Invalid value '{'status': 'enabled1'}' for table 'BGP_BBR', key 'all'. Only 'enabled' and 'disabled' are supported", False) + +def test___set_validation_4(): + __set_validation_common("all", {"status": "enabled"}, None, True) + +def test___set_validation_5(): + __set_validation_common("all", {"status": "disabled"}, None, True) + +def __set_prepare_config_common(status, bbr_enabled_pgs, available_pgs, expected_cmds, bbr_applied_pgs=None): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': global_constants, + } + m = BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR") + m.directory.data = {"CONFIG_DB__DEVICE_METADATA": + { + "localhost": { + "bgp_asn": "65500" + } + } + } + m.bbr_enabled_pgs = bbr_enabled_pgs + m._BBRMgr__get_available_peer_groups = MagicMock(return_value = sorted(available_pgs)) + cmds, peer_groups = m._BBRMgr__set_prepare_config(status) + assert cmds == expected_cmds + assert set(peer_groups) == (available_pgs if not bbr_applied_pgs else bbr_applied_pgs) + +def test___set_prepare_config_enabled(): + __set_prepare_config_common("enabled", { + "PEER_V4": ["ipv4", "ipv6"], + "PEER_V6": ["ipv6"], + }, {"PEER_V4", "PEER_V6"}, [ + 'router bgp 65500', + ' address-family ipv4', + ' neighbor PEER_V4 allowas-in 1', + ' address-family ipv6', + ' neighbor PEER_V4 allowas-in 1', + ' neighbor PEER_V6 allowas-in 1', + ]) + +def test___set_prepare_config_disabled(): + __set_prepare_config_common("disabled", { + "PEER_V4": ["ipv4", "ipv6"], + "PEER_V6": ["ipv6"], + }, {"PEER_V4", "PEER_V6"}, [ + 'router bgp 65500', + ' address-family ipv4', + ' no neighbor PEER_V4 allowas-in 1', + ' address-family ipv6', + ' no neighbor PEER_V4 allowas-in 1', + ' no neighbor PEER_V6 allowas-in 1', + ]) + +def test___set_prepare_config_enabled_part(): + __set_prepare_config_common("enabled", { + "PEER_V4": ["ipv4", "ipv6"], + "PEER_V6": ["ipv6"], + "PEER_V8": ["ipv4"] + }, {"PEER_V4", "PEER_V6"}, [ + 'router bgp 65500', + ' address-family ipv4', + ' neighbor PEER_V4 allowas-in 1', + ' address-family ipv6', + ' neighbor PEER_V4 allowas-in 1', + ' neighbor PEER_V6 allowas-in 1', + ]) + +def test___set_prepare_config_disabled_part(): + __set_prepare_config_common("disabled", { + "PEER_V4": ["ipv4", "ipv6"], + "PEER_V6": ["ipv6"], + "PEER_v10": ["ipv4"], + }, {"PEER_V4", "PEER_V6"}, [ + 'router bgp 65500', + ' address-family ipv4', + ' no neighbor PEER_V4 allowas-in 1', + ' address-family ipv6', + ' no neighbor PEER_V4 allowas-in 1', + ' no neighbor PEER_V6 allowas-in 1', + ]) +def test___set_prepare_config_enabled_multiple_peers(): + __set_prepare_config_common("enabled", { + "PEER_V4": ["ipv4"], + "PEER_V6": ["ipv6"], + }, {"PEER_V4", "PEER_V4_DEPLOYMENT_ID_0", "PEER_V4_DEPLOYMENT_ID_1", "PEER_V6", "PEER_V6_DEPLOYMENT_ID_0", "PEER_V6_DEPLOYMENT_ID_1", "PEER_INVALID"}, + [ + 'router bgp 65500', + ' address-family ipv4', + ' neighbor PEER_V4 allowas-in 1', + ' neighbor PEER_V4_DEPLOYMENT_ID_0 allowas-in 1', + ' neighbor PEER_V4_DEPLOYMENT_ID_1 allowas-in 1', + ' address-family ipv6', + ' neighbor PEER_V6 allowas-in 1', + ' neighbor PEER_V6_DEPLOYMENT_ID_0 allowas-in 1', + ' neighbor PEER_V6_DEPLOYMENT_ID_1 allowas-in 1', + ], + {"PEER_V4", "PEER_V4_DEPLOYMENT_ID_0", "PEER_V4_DEPLOYMENT_ID_1", "PEER_V6", "PEER_V6_DEPLOYMENT_ID_0", "PEER_V6_DEPLOYMENT_ID_1"}) + +def test___set_prepare_config_disabled_multiple_peers(): + __set_prepare_config_common("disabled", { + "PEER_V4": ["ipv4"], + "PEER_V6": ["ipv6"], + }, {"PEER_V4", "PEER_V4_DEPLOYMENT_ID_0", "PEER_V4_DEPLOYMENT_ID_1", "PEER_V6", "PEER_V6_DEPLOYMENT_ID_0", "PEER_V6_DEPLOYMENT_ID_1", "PEER_INVALID"}, + [ + 'router bgp 65500', + ' address-family ipv4', + ' no neighbor PEER_V4 allowas-in 1', + ' no neighbor PEER_V4_DEPLOYMENT_ID_0 allowas-in 1', + ' no neighbor PEER_V4_DEPLOYMENT_ID_1 allowas-in 1', + ' address-family ipv6', + ' no neighbor PEER_V6 allowas-in 1', + ' no neighbor PEER_V6_DEPLOYMENT_ID_0 allowas-in 1', + ' no neighbor PEER_V6_DEPLOYMENT_ID_1 allowas-in 1', + ], + {"PEER_V4", "PEER_V4_DEPLOYMENT_ID_0", "PEER_V4_DEPLOYMENT_ID_1", "PEER_V6", "PEER_V6_DEPLOYMENT_ID_0", "PEER_V6_DEPLOYMENT_ID_1"}) + +def test__get_available_peer_groups(): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': global_constants, + } + m = BBRMgr(common_objs, "CONFIG_DB", "BGP_BBR") + m.cfg_mgr.get_text = MagicMock(return_value=[ + ' neighbor PEER_V4 peer-group', + ' neighbor PEER_V6 peer-group', + ' address-family ipv4', + ' neighbor PEER_V4 allowas-in 1', + ' neighbor PEER_V4 soft-reconfiguration inbound', + ' neighbor PEER_V4 route-map FROM_BGP_PEER_V4 in', + ' neighbor PEER_V4 route-map TO_BGP_PEER_V4 out', + ' exit-address-family', + ' address-family ipv6', + ' neighbor PEER_V6 allowas-in 1', + ' neighbor PEER_V6 soft-reconfiguration inbound', + ' neighbor PEER_V6 route-map FROM_BGP_PEER_V6 in', + ' neighbor PEER_V6 route-map TO_BGP_PEER_V6 out', + ' exit-address-family', + ' ', + ]) + res = m._BBRMgr__get_available_peer_groups() + assert res == {"PEER_V4", "PEER_V6"} diff --git a/src/sonic-bgpcfgd/tests/test_bbr_templates.py b/src/sonic-bgpcfgd/tests/test_bbr_templates.py new file mode 100644 index 000000000000..989734d79714 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_bbr_templates.py @@ -0,0 +1,70 @@ +import itertools +import os +import re + +from .util import load_constants_dir_mappings, load_constants + + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr/bgpd/templates') + + +def find_all_files(path): + paths_to_check = [path] + res = [] + while paths_to_check: + path = paths_to_check[0] + paths_to_check = paths_to_check[1:] + for name in os.listdir(path): + full_path = "%s/%s" % (path, name) + if os.path.isfile(full_path): + res.append(full_path) + elif os.path.isdir(full_path): + paths_to_check.append(full_path) + return res + +def get_files_to_check(): + directories = load_constants_dir_mappings() + general_path = "%s/%s" % (TEMPLATE_PATH, directories['general']) + files = find_all_files(general_path) + return files + +def get_peer_groups_with_bbr(filename): + re_bbr = re.compile(r".+CONFIG_DB__BGP_BBR.+") #\['status'\] == 'enabled'") + re_endif = re.compile(r'^\s*{% +endif +%}\s*$') + re_peer = re.compile(r'^\s*neighbor\s+(\S+)\s+allowas-in\s+1\s*$') + inside_bbr = False + res = [] + with open(filename) as fp: + for line in fp: + s_line = line.strip() + if s_line == '': + continue + elif s_line.startswith('!'): + continue + elif re_bbr.match(s_line): + inside_bbr = True + elif re_peer.match(s_line) and inside_bbr: + m = re_peer.match(s_line) + pg = m.group(1) + res.append(pg) + elif re_endif.match(s_line) and inside_bbr: + inside_bbr = False + return res + +def load_constants_bbr(): + data = load_constants() + assert "bgp" in data["constants"], "'bgp' key not found in constants.yml" + assert "peers" in data["constants"]["bgp"], "'peers' key not found in constants.yml" + assert "general" in data["constants"]["bgp"]['peers'], "'general' key not found in constants.yml" + return data["constants"]["bgp"]["peers"]['general'] + +def test_bbr_templates(): + files_to_check = get_files_to_check() + pg_with_bbr_per_file = [ get_peer_groups_with_bbr(name) for name in files_to_check ] + pg_with_bbr = set(itertools.chain.from_iterable(pg_with_bbr_per_file)) + general = load_constants_bbr() + if pg_with_bbr: + assert 'bbr' in general, "BBR is not defined in 'general', but BBR is enabled for %s" % pg_with_bbr + for pg in pg_with_bbr: + assert pg in general['bbr'], "peer-group '%s' has BBR enabled, but it is not configured in constants.yml" + diff --git a/src/sonic-bgpcfgd/tests/test_bgp.py b/src/sonic-bgpcfgd/tests/test_bgp.py new file mode 100644 index 000000000000..a4c5ef997725 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_bgp.py @@ -0,0 +1,112 @@ +from unittest.mock import MagicMock, patch + +import os +from bgpcfgd.directory import Directory +from bgpcfgd.template import TemplateFabric +from . import swsscommon_test +from .util import load_constants +from swsscommon import swsscommon +import bgpcfgd.managers_bgp + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') + +def constructor(): + cfg_mgr = MagicMock() + constants = load_constants()['constants'] + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(TEMPLATE_PATH), + 'constants': constants + } + + return_value_map = { + "['vtysh', '-c', 'show bgp vrfs json']": (0, "{\"vrfs\": {\"default\": {}}}", ""), + "['vtysh', '-c', 'show bgp vrf default neighbors json']": (0, "{\"10.10.10.1\": {}, \"20.20.20.1\": {}, \"fc00:10::1\": {}}", "") + } + + bgpcfgd.managers_bgp.run_command = lambda cmd: return_value_map[str(cmd)] + m = bgpcfgd.managers_bgp.BGPPeerMgrBase(common_objs, "CONFIG_DB", swsscommon.CFG_BGP_NEIGHBOR_TABLE_NAME, "general", True) + assert m.peer_type == "general" + assert m.check_neig_meta == ('bgp' in constants and 'use_neighbors_meta' in constants['bgp'] and constants['bgp']['use_neighbors_meta']) + + m.directory.put("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, "localhost", {"bgp_asn": "65100"}) + m.directory.put("CONFIG_DB", swsscommon.CFG_LOOPBACK_INTERFACE_TABLE_NAME, "Loopback0|11.11.11.11/32", {}) + m.directory.put("CONFIG_DB", swsscommon.CFG_LOOPBACK_INTERFACE_TABLE_NAME, "Loopback0|FC00:1::32/128", {}) + m.directory.put("LOCAL", "local_addresses", "30.30.30.30", {"interface": "Ethernet4|30.30.30.30/24"}) + m.directory.put("LOCAL", "local_addresses", "fc00:20::20", {"interface": "Ethernet8|fc00:20::20/96"}) + m.directory.put("LOCAL", "interfaces", "Ethernet4|30.30.30.30/24", {"anything": "anything"}) + m.directory.put("LOCAL", "interfaces", "Ethernet8|fc00:20::20/96", {"anything": "anything"}) + + return m + +@patch('bgpcfgd.managers_bgp.log_info') +def test_update_peer_up(mocked_log_info): + m = constructor() + res = m.set_handler("10.10.10.1", {"admin_status": "up"}) + assert res, "Expect True return value for peer update" + mocked_log_info.assert_called_with("Peer 'default|10.10.10.1' admin state is set to 'up'") + +@patch('bgpcfgd.managers_bgp.log_info') +def test_update_peer_up_ipv6(mocked_log_info): + m = constructor() + res = m.set_handler("fc00:10::1", {"admin_status": "up"}) + assert res, "Expect True return value for peer update" + mocked_log_info.assert_called_with("Peer 'default|fc00:10::1' admin state is set to 'up'") + +@patch('bgpcfgd.managers_bgp.log_info') +def test_update_peer_down(mocked_log_info): + m = constructor() + res = m.set_handler("10.10.10.1", {"admin_status": "down"}) + assert res, "Expect True return value for peer update" + mocked_log_info.assert_called_with("Peer 'default|10.10.10.1' admin state is set to 'down'") + +@patch('bgpcfgd.managers_bgp.log_err') +def test_update_peer_no_admin_status(mocked_log_err): + m = constructor() + res = m.set_handler("10.10.10.1", {"anything": "anything"}) + assert res, "Expect True return value for peer update" + mocked_log_err.assert_called_with("Peer '(default|10.10.10.1)': Can't update the peer. Only 'admin_status' attribute is supported") + +@patch('bgpcfgd.managers_bgp.log_err') +def test_update_peer_invalid_admin_status(mocked_log_err): + m = constructor() + res = m.set_handler("10.10.10.1", {"admin_status": "invalid"}) + assert res, "Expect True return value for peer update" + mocked_log_err.assert_called_with("Peer 'default|10.10.10.1': Can't update the peer. It has wrong attribute value attr['admin_status'] = 'invalid'") + +def test_add_peer(): + m = constructor() + res = m.set_handler("30.30.30.1", {"local_addr": "30.30.30.30", "admin_status": "up"}) + assert res, "Expect True return value" + +def test_add_peer_ipv6(): + m = constructor() + res = m.set_handler("fc00:20::1", {"local_addr": "fc00:20::20", "admin_status": "up"}) + assert res, "Expect True return value" + +@patch('bgpcfgd.managers_bgp.log_warn') +def test_add_peer_no_local_addr(mocked_log_warn): + m = constructor() + res = m.set_handler("30.30.30.1", {"admin_status": "up"}) + assert res, "Expect True return value" + mocked_log_warn.assert_called_with("Peer 30.30.30.1. Missing attribute 'local_addr'") + +@patch('bgpcfgd.managers_bgp.log_debug') +def test_add_peer_invalid_local_addr(mocked_log_debug): + m = constructor() + res = m.set_handler("30.30.30.1", {"local_addr": "40.40.40.40", "admin_status": "up"}) + assert not res, "Expect False return value" + mocked_log_debug.assert_called_with("Peer '30.30.30.1' with local address '40.40.40.40' wait for the corresponding interface to be set") + +@patch('bgpcfgd.managers_bgp.log_info') +def test_del_handler(mocked_log_info): + m = constructor() + m.del_handler("10.10.10.1") + mocked_log_info.assert_called_with("Peer '(default|10.10.10.1)' has been removed") + +@patch('bgpcfgd.managers_bgp.log_warn') +def test_del_handler_nonexist_peer(mocked_log_warn): + m = constructor() + m.del_handler("40.40.40.1") + mocked_log_warn.assert_called_with("Peer '(default|40.40.40.1)' has not been found") diff --git a/src/sonic-bgpcfgd/tests/test_config.py b/src/sonic-bgpcfgd/tests/test_config.py new file mode 100644 index 000000000000..c8bd0c9ca2be --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_config.py @@ -0,0 +1,207 @@ +from unittest.mock import MagicMock + +from bgpcfgd.config import ConfigMgr + + +def test_constructor(): + frr = MagicMock() + c = ConfigMgr(frr) + assert c.frr == frr + assert c.current_config is None + assert c.current_config_raw is None + assert c.changes == "" + assert c.peer_groups_to_restart == [] + +def test_reset(): + frr = MagicMock() + c = ConfigMgr(frr) + c.reset() + assert c.frr == frr + assert c.current_config is None + assert c.current_config_raw is None + assert c.changes == "" + assert c.peer_groups_to_restart == [] + +def test_update(): + frr = MagicMock() + frr.get_config = MagicMock(return_value = """! + text1 + ! comment + text2 + text3 + ! comment + text4 + """) + c = ConfigMgr(frr) + c.update() + assert c.current_config_raw == [' text1', ' text2', ' text3', ' text4', ' ', ' '] + assert c.current_config == [['text1'], ['text2'], ['text3'], ['text4']] + +def test_push_list(): + frr = MagicMock() + c = ConfigMgr(frr) + c.push_list(["change1", "change2"]) + assert c.changes == "change1\nchange2\n" + c.push_list(["change3", "change4"]) + assert c.changes == "change1\nchange2\nchange3\nchange4\n" + +def test_push(): + frr = MagicMock() + c = ConfigMgr(frr) + c.push("update1\nupdate2\n") + assert c.changes == "update1\nupdate2\n\n" + c.push("update3\nupdate4\n") + assert c.changes == "update1\nupdate2\n\nupdate3\nupdate4\n\n" + +def test_push_and_push_list(): + frr = MagicMock() + c = ConfigMgr(frr) + c.push("update1\nupdate2\n") + c.push_list(["change1", "change2"]) + assert c.changes == "update1\nupdate2\n\nchange1\nchange2\n" + +def test_restart_peer_groups(): + frr = MagicMock() + c = ConfigMgr(frr) + c.restart_peer_groups(["pg_1", "pg_2"]) + assert c.peer_groups_to_restart == ["pg_1", "pg_2"] + c.restart_peer_groups(["pg_3", "pg_4"]) + assert c.peer_groups_to_restart == ["pg_1", "pg_2", "pg_3", "pg_4"] + +def test_commit_empty_changes(): + frr = MagicMock() + c = ConfigMgr(frr) + res = c.commit() + assert res + assert not frr.write.called + +def commit_changes_common(write_error, restart_error, result): + frr = MagicMock() + frr.write = MagicMock(return_value = write_error) + frr.restart_peer_groups = MagicMock(return_value = restart_error) + c = ConfigMgr(frr) + c.reset = MagicMock() + c.push_list(["change1", "change2"]) + c.restart_peer_groups(["pg1", "pg2"]) + res = c.commit() + assert res == result + assert c.reset.called + frr.write.assert_called_with('change1\nchange2\n') + frr.restart_peer_groups.assert_called_with(["pg1", "pg2"]) + +def test_commit_changes_no_errors(): + commit_changes_common(True, True, True) + +def test_commit_changes_write_error(): + commit_changes_common(False, True, False) + +def test_commit_changes_restart_error(): + commit_changes_common(True, False, False) + +def test_commit_changes_both_errors(): + commit_changes_common(False, False, False) + +def test_restart_get_text(): + frr = MagicMock() + frr.get_config = MagicMock(return_value = """! + text1 + ! comment + text2 + text3 + ! comment + text4 + """) + c = ConfigMgr(frr) + c.update() + assert c.get_text() == [' text1', ' text2', ' text3', ' text4', ' ', ' '] + +def to_canonical_common(raw_text, expected_canonical): + frr = MagicMock() + c = ConfigMgr(frr) + assert c.to_canonical(raw_text) == expected_canonical + +def test_to_canonical_empty(): + raw_config = """ +! + ! + ! + ! + + ! + +""" + to_canonical_common(raw_config, []) + +def test_to_canonical_(): + raw_config = """ +! +router bgp 12345 + bgp router-id 1020 + address-family ipv4 + neighbor PEER_V4 peer-group + neighbor PEER_V4 route-map A10 in + exit-address-family + address-family ipv6 + neighbor PEER_V6 peer-group + neighbor PEER_V6 route-map A20 in + exit-address-family +route-map A10 permit 10 +! +route-map A20 permit 10 +! + +""" + expected = [ + ['router bgp 12345'], + ['router bgp 12345', 'bgp router-id 1020'], + ['router bgp 12345', 'address-family ipv4'], + ['router bgp 12345', 'address-family ipv4', 'neighbor PEER_V4 peer-group'], + ['router bgp 12345', 'address-family ipv4', 'neighbor PEER_V4 route-map A10 in'], + ['router bgp 12345', 'exit-address-family'], + ['router bgp 12345', 'address-family ipv6'], + ['router bgp 12345', 'address-family ipv6', 'neighbor PEER_V6 peer-group'], + ['router bgp 12345', 'address-family ipv6', 'neighbor PEER_V6 route-map A20 in'], + ['router bgp 12345', 'exit-address-family'], + ['route-map A10 permit 10'], + ['route-map A20 permit 10'] + ] + to_canonical_common(raw_config, expected) + +def test_count_spaces(): + frr = MagicMock() + c = ConfigMgr(frr) + assert c.count_spaces(" !") == 2 + assert c.count_spaces("!") == 0 + assert c.count_spaces("") == 0 + +def test_from_canonical(): + canonical = [ + ['router bgp 12345'], + ['router bgp 12345', 'bgp router-id 1020'], + ['router bgp 12345', 'address-family ipv4'], + ['router bgp 12345', 'address-family ipv4', 'neighbor PEER_V4 peer-group'], + ['router bgp 12345', 'address-family ipv4', 'neighbor PEER_V4 route-map A10 in'], + ['router bgp 12345', 'exit-address-family'], + ['router bgp 12345', 'address-family ipv6'], + ['router bgp 12345', 'address-family ipv6', 'neighbor PEER_V6 peer-group'], + ['router bgp 12345', 'address-family ipv6', 'neighbor PEER_V6 route-map A20 in'], + ['router bgp 12345', 'exit-address-family'], + ['route-map A10 permit 10'], + ['route-map A20 permit 10'] + ] + expected = 'router bgp 12345\n' \ + ' bgp router-id 1020\n' \ + ' address-family ipv4\n' \ + ' neighbor PEER_V4 peer-group\n' \ + ' neighbor PEER_V4 route-map A10 in\n' \ + ' exit-address-family\n' \ + ' address-family ipv6\n' \ + ' neighbor PEER_V6 peer-group\n' \ + ' neighbor PEER_V6 route-map A20 in\n' \ + ' exit-address-family\n' \ + 'route-map A10 permit 10\n' \ + 'route-map A20 permit 10\n' + frr = MagicMock() + c = ConfigMgr(frr) + raw = c.from_canonical(canonical) + assert raw == expected diff --git a/src/sonic-bgpcfgd/tests/test_db.py b/src/sonic-bgpcfgd/tests/test_db.py new file mode 100644 index 000000000000..7078bc2735f0 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_db.py @@ -0,0 +1,40 @@ +from unittest.mock import MagicMock, patch + +from bgpcfgd.directory import Directory +from bgpcfgd.template import TemplateFabric +from . import swsscommon_test +from swsscommon import swsscommon + +with patch.dict("sys.modules", swsscommon=swsscommon_test): + from bgpcfgd.managers_db import BGPDataBaseMgr + +def test_set_del_handler(): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': {}, + } + m = BGPDataBaseMgr(common_objs, "CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME) + assert m.constants == {} + + # test set_handler + res = m.set_handler("test_key1", {"test_value1"}) + assert res, "Returns always True" + assert "test_key1" in m.directory.get_slot(m.db_name, m.table_name) + assert m.directory.get(m.db_name, m.table_name, "test_key1") == {"test_value1"} + + res = m.set_handler("test_key2", {}) + assert res, "Returns always True" + assert "test_key2" in m.directory.get_slot(m.db_name, m.table_name) + assert m.directory.get(m.db_name, m.table_name, "test_key2") == {} + + # test del_handler + m.del_handler("test_key") + assert "test_key" not in m.directory.get_slot(m.db_name, m.table_name) + assert "test_key2" in m.directory.get_slot(m.db_name, m.table_name) + assert m.directory.get(m.db_name, m.table_name, "test_key2") == {} + + m.del_handler("test_key2") + assert "test_key2" not in m.directory.get_slot(m.db_name, m.table_name) diff --git a/src/sonic-bgpcfgd/tests/test_directory.py b/src/sonic-bgpcfgd/tests/test_directory.py new file mode 100644 index 000000000000..b20803ed32c5 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_directory.py @@ -0,0 +1,57 @@ +from unittest.mock import MagicMock, patch +from bgpcfgd.directory import Directory + +@patch('bgpcfgd.directory.log_err') +def test_directory(mocked_log_err): + test_values = { + "key1": { + "key1_1": { + "key1_1_1": "value1_1_1", + "key1_1_2": "value1_1_2", + "key1_1_3": "value1_1_3" + } + }, + "key2": { + "value2" + } + } + + directory = Directory() + + # Put test values + directory.put("db_name", "table", "key1", test_values["key1"]) + directory.put("db_name", "table", "key2", test_values["key2"]) + + # Test get_path() + assert directory.get_path("db_name", "table", "") == test_values + assert directory.get_path("db_name", "table", "key1/key1_1/key1_1_1") == "value1_1_1" + assert directory.get_path("db_name", "table", "key1/key_nonexist") == None + + # Test path_exist() + assert directory.path_exist("db_name", "table", "key1/key1_1/key1_1_1") + assert not directory.path_exist("db_name", "table_nonexist", "") + assert not directory.path_exist("db_name", "table", "key1/key_nonexist") + + # Test get_slot() + assert directory.get_slot("db_name", "table") == test_values + + # Test get() + assert directory.get("db_name", "table", "key2") == test_values["key2"] + + # Test remove() + directory.remove("db_name", "table", "key2") + assert not directory.path_exist("db_name", "table", "key2") + + # Test remove() with invalid input + directory.remove("db_name", "table_nonexist", "key2") + mocked_log_err.assert_called_with("Directory: Can't remove key 'key2' from slot 'db_name__table_nonexist'. The slot doesn't exist") + directory.remove("db_name", "table", "key_nonexist") + mocked_log_err.assert_called_with("Directory: Can't remove key 'key_nonexist' from slot 'db_name__table'. The key doesn't exist") + + # Test remove_slot() + directory.remove_slot("db_name", "table") + assert not directory.available("db_name", "table") + + # Test remove_slot() with nonexist table + directory.remove_slot("db_name", "table_nonexist") + mocked_log_err.assert_called_with("Directory: Can't remove slot 'db_name__table_nonexist'. The slot doesn't exist") diff --git a/src/sonic-bgpcfgd/tests/test_frr.py b/src/sonic-bgpcfgd/tests/test_frr.py new file mode 100644 index 000000000000..5a20281fa553 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_frr.py @@ -0,0 +1,68 @@ +from unittest.mock import patch +import bgpcfgd.frr +import pytest + +def test_constructor(): + f = bgpcfgd.frr.FRR(["abc", "cde"]) + assert f.daemons == ["abc", "cde"] + +def test_wait_for_daemons(): + bgpcfgd.frr.run_command = lambda cmd, **kwargs: (0, ["abc", "cde"], "") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + f.wait_for_daemons(5) + +def test_wait_for_daemons_fail(): + bgpcfgd.frr.run_command = lambda cmd, **kwargs: (0, ["abc", "non_expected"], "") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + with pytest.raises(Exception): + assert f.wait_for_daemons(5) + +def test_wait_for_daemons_error(): + bgpcfgd.frr.run_command = lambda cmd, **kwargs: (1, ["abc", "cde"], "some error") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + with pytest.raises(Exception): + assert f.wait_for_daemons(5) + +def test_get_config(): + bgpcfgd.frr.run_command = lambda cmd: (0, "expected config", "") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + out = f.get_config() + assert out == "expected config" + +@patch('bgpcfgd.frr.log_crit') +def test_get_config_fail(mocked_log_crit): + bgpcfgd.frr.run_command = lambda cmd: (1, "some config", "some error") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + out = f.get_config() + assert out == "" + mocked_log_crit.assert_called_with("can't update running config: rc=1 out='some config' err='some error'") + +def test_write(): + bgpcfgd.frr.run_command = lambda cmd: (0, "some output", "") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + res = f.write("config context") + assert res, "Expect True return value" + +def test_write_fail(): + bgpcfgd.frr.run_command = lambda cmd: (1, "some output", "some error") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + res = f.write("config context") + assert not res, "Expect False return value" + +def test_restart_peer_groups(): + bgpcfgd.frr.run_command = lambda cmd: (0, "some output", "") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + res = f.restart_peer_groups(["pg_1", "pg_2"]) + assert res, "Expect True return value" + +@patch('bgpcfgd.frr.log_crit') +def test_restart_peer_groups_fail(mocked_log_crit): + return_value_map = { + "['vtysh', '-c', 'clear bgp peer-group pg_1 soft in']": (0, "", ""), + "['vtysh', '-c', 'clear bgp peer-group pg_2 soft in']": (1, "some output", "some error") + } + bgpcfgd.frr.run_command = lambda cmd: return_value_map[str(cmd)] + f = bgpcfgd.frr.FRR(["abc", "cde"]) + res = f.restart_peer_groups(["pg_1", "pg_2"]) + assert not res, "Expect False return value" + mocked_log_crit.assert_called_with("Can't restart bgp peer-group 'pg_2'. rc='1', out='some output', err='some error'") diff --git a/src/sonic-bgpcfgd/tests/test_intf.py b/src/sonic-bgpcfgd/tests/test_intf.py new file mode 100644 index 000000000000..74fa8e471ac6 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_intf.py @@ -0,0 +1,52 @@ +from unittest.mock import MagicMock, patch + +from bgpcfgd.directory import Directory +from bgpcfgd.template import TemplateFabric +from swsscommon import swsscommon +from bgpcfgd.managers_intf import InterfaceMgr + +def set_handler_test(manager, key, value): + res = manager.set_handler(key, value) + assert res, "Returns always True" + assert manager.directory.get(manager.db_name, manager.table_name, key) == value + +def del_handler_test(manager, key): + manager.del_handler(key) + assert manager.directory.get_path(manager.db_name, manager.table_name, key) == None + +@patch('bgpcfgd.managers_intf.log_warn') +def test_intf(mocked_log_warn): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': {}, + } + m = InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_VLAN_INTF_TABLE_NAME) + + set_handler_test(m, "Vlan1000", {}) + set_handler_test(m, "Vlan1000|192.168.0.1/21", {}) + + # test set handler with invalid ip network + res = m.set_handler("Vlan1000|invalid_netowrk", {}) + assert res, "Returns always True" + mocked_log_warn.assert_called_with("Subnet 'invalid_netowrk' format is wrong for interface 'Vlan1000'") + + del_handler_test(m, "Vlan1000") + del_handler_test(m, "Vlan1000|192.168.0.1/21") + del_handler_test(m, "Vlan1000|invalid_netowrk") + mocked_log_warn.assert_called_with("Subnet 'invalid_netowrk' format is wrong for interface 'Vlan1000'") + +def test_intf_ipv6(): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': {}, + } + m = InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_VLAN_INTF_TABLE_NAME) + + set_handler_test(m, "Vlan1000|fc02:1000::1/64", {}) + del_handler_test(m, "Vlan1000|fc02:1000::1/64") diff --git a/src/sonic-bgpcfgd/tests/test_ipv6_nexthop_global.py b/src/sonic-bgpcfgd/tests/test_ipv6_nexthop_global.py new file mode 100644 index 000000000000..398c8a19f3f7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_ipv6_nexthop_global.py @@ -0,0 +1,129 @@ +import os +import re + +from bgpcfgd.template import TemplateFabric +from .util import load_constants_dir_mappings + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') + + +def parse_instance_conf(filename): + activate_re = re.compile(r'^neighbor\s+(\S+)\s+activate$') + with open(filename) as fp: + lines = [line.strip() for line in fp if not line.strip().startswith('!') and line.strip() != ''] + # Search all v6 neighbors + neighbors = {} + for line in lines: + if activate_re.match(line): + neighbor = activate_re.match(line).group(1) + if TemplateFabric.is_ipv6(neighbor): + neighbors[neighbor] = {} + # Extract peer-groups and route-maps + for neighbor, neighbor_data in neighbors.items(): + route_map_in_re = re.compile(r'^neighbor\s+%s\s+route-map\s+(\S+) in$' % neighbor) + peer_group_re = re.compile(r'^neighbor\s+%s\s+peer-group\s+(\S+)$' % neighbor) + for line in lines: + if route_map_in_re.match(line): + assert "route-map" not in neighbor_data + neighbor_data["route-map"] = route_map_in_re.match(line).group(1) + if peer_group_re.match(line): + assert "peer-group" not in neighbor_data + neighbor_data["peer-group"] = peer_group_re.match(line).group(1) + # Ensure that every ivp6 neighbor has either route-map or peer-group + for neighbor, neighbor_data in neighbors.items(): + assert "route-map" in neighbor_data or "peer-group" in neighbor_data,\ + "IPv6 neighbor '%s' must have either route-map in or peer-group %s" % (neighbor, neighbor_data) + return neighbors + +def load_results(path, dir_name): + result_files = [] + for fname in os.listdir(os.path.join(path, dir_name)): + if not fname.startswith("result_"): + continue + full_fname = os.path.join(path, dir_name, fname) + if not os.path.isfile(full_fname): + continue + result_files.append(full_fname) + return result_files + +def process_instances(path): + result_files = load_results(path, "instance.conf") + # search for ipv6 neighbors + neighbors_list = [] + for fname in result_files: + neighbors = parse_instance_conf(fname) + if neighbors: + neighbors_list.append(neighbors) + return neighbors_list + +def parse_peer_group_conf(filename, pg_name): + route_map_re = re.compile(r'^neighbor\s+%s\s+route-map\s+(\S+)\s+in$' % pg_name) + with open(filename) as fp: + lines = [line.strip() for line in fp if not line.strip().startswith('!') and line.strip() != ''] + route_maps = set() + for line in lines: + if route_map_re.match(line): + route_map = route_map_re.match(line).group(1) + route_maps.add(route_map) + return route_maps + +def extract_rm_from_peer_group(path, peer_group_name): + result_files = load_results(path, "peer-group.conf") + rm_set = set() + for fname in result_files: + route_maps = parse_peer_group_conf(fname, peer_group_name) + if route_maps: + rm_set |= route_maps + return list(rm_set) + +def check_routemap_in_file(filename, route_map_name): + route_map_re = re.compile(r'^route-map\s+%s\s+permit\s+(\d+)' % route_map_name) + set_re = re.compile(r'set ipv6 next-hop prefer-global') + next_re = re.compile(r'on-match next') + with open(filename) as fp: + lines = [line.strip() for line in fp if not line.strip().startswith('!') and line.strip() != ''] + found_entry = False + found_seq_no = None + route_map_entries = {} + for line in lines: + if found_entry: + if set_re.match(line): + route_map_entries[found_seq_no][0] = True + elif next_re.match(line): + route_map_entries[found_seq_no][1] = True + else: + found_entry = False + found_seq_no = None + if route_map_re.match(line): + found_seq_no = None + seq_n_txt = route_map_re.match(line).group(1) + assert seq_n_txt.isdigit(), "wrong sequence number for line '%s'" % line + found_seq_no = int(seq_n_txt) + assert found_seq_no not in route_map_entries, "Route-map has duplicate entries: %s - %d" % (route_map_name, found_seq_no) + found_entry = True + route_map_entries[found_seq_no] = [False, False] + results = [route_map_entries[seq] for seq in sorted(route_map_entries.keys())] + err_msg = "route-map %s doesn't have mandatory permit entry for 'set ipv6 next-hop prefer-global" % route_map_name + assert len(results), err_msg + assert all(results[0]), "first ipv6 route-map entry doesn't have set ipv6 nexthop" + return True + +def check_routemap(path, route_map_name): + result_files = load_results(path, "policies.conf") + checked = False + for fname in result_files: + checked = checked or check_routemap_in_file(fname, route_map_name) + assert checked, "route-map %s wasn't found" % route_map_name + +def test_v6_next_hop_global(): + paths = ["tests/data/%s" % value for value in load_constants_dir_mappings().values()] + for path in paths: + test_cases = process_instances(path) + for test_case in test_cases: + for neighbor_value in test_case.values(): + if 'route-map' in neighbor_value: + check_routemap(path, neighbor_value['route-map']) + elif 'peer-group' in neighbor_value: + route_map_in_list = extract_rm_from_peer_group(path, neighbor_value['peer-group']) + for route_map_in in route_map_in_list: + check_routemap(path, route_map_in) diff --git a/src/sonic-bgpcfgd/tests/test_pfx_filter.py b/src/sonic-bgpcfgd/tests/test_pfx_filter.py new file mode 100644 index 000000000000..0714be56a892 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_pfx_filter.py @@ -0,0 +1,139 @@ +from bgpcfgd.template import TemplateFabric +from collections import OrderedDict +import pytest + + +def test_pfx_filter_none(): + res = TemplateFabric.pfx_filter(None) + assert isinstance(res, OrderedDict) and len(res) == 0 + +def test_pfx_filter_empty_tuple(): + res = TemplateFabric.pfx_filter(()) + assert isinstance(res, OrderedDict) and len(res) == 0 + +def test_pfx_filter_empty_list(): + res = TemplateFabric.pfx_filter([]) + assert isinstance(res, OrderedDict) and len(res) == 0 + +def test_pfx_filter_empty_dict(): + res = TemplateFabric.pfx_filter({}) + assert isinstance(res, OrderedDict) and len(res) == 0 + +def test_pfx_filter_strings(): + src = { + 'Loopback0': {}, + 'Loopback1': {}, + } + expected = OrderedDict([]) + res = TemplateFabric.pfx_filter(src) + assert res == expected + +def test_pfx_filter_mixed_keys(): + src = { + 'Loopback0': {}, + ('Loopback0', '11.11.11.11/32'): {}, + 'Loopback1': {}, + ('Loopback1', '55.55.55.55/32'): {}, + } + expected = OrderedDict( + [ + (('Loopback1', '55.55.55.55/32'), {}), + (('Loopback0', '11.11.11.11/32'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert dict(res) == dict(expected) + + +def test_pfx_filter_pfx_v4_w_mask(): + src = { + ('Loopback0', '11.11.11.11/32'): {}, + ('Loopback1', '55.55.55.55/32'): {}, + } + expected = OrderedDict( + [ + (('Loopback1', '55.55.55.55/32'), {}), + (('Loopback0', '11.11.11.11/32'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert dict(res) == dict(expected) + +def test_pfx_filter_pfx_v6_w_mask(): + src = { + ('Loopback0', 'fc00::/128'): {}, + ('Loopback1', 'fc00::1/128'): {}, + } + expected = OrderedDict( + [ + (('Loopback0', 'fc00::/128'), {}), + (('Loopback1', 'fc00::1/128'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert res == expected + +def test_pfx_filter_pfx_v4_no_mask(): + src = { + ('Loopback0', '11.11.11.11'): {}, + ('Loopback1', '55.55.55.55'): {}, + } + expected = OrderedDict( + [ + (('Loopback1', '55.55.55.55/32'), {}), + (('Loopback0', '11.11.11.11/32'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert dict(res) == dict(expected) + +def test_pfx_filter_pfx_v6_no_mask(): + src = { + ('Loopback0', 'fc00::'): {}, + ('Loopback1', 'fc00::1'): {}, + } + expected = OrderedDict( + [ + (('Loopback0', 'fc00::/128'), {}), + (('Loopback1', 'fc00::1/128'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert res == expected + + +def test_pfx_filter_pfx_comprehensive(): + src = { + 'Loopback0': {}, + ('Loopback0', 'fc00::'): {}, + 'Loopback1': {}, + ('Loopback1', 'fc00::1/128'): {}, + ('Loopback2', '11.11.11.11/32'): {}, + ('Loopback3', '55.55.55.55'): {}, + 'Loopback2': {}, + 'Loopback3': {}, + ('Loopback5', '22.22.22.1/24'): {}, + ('Loopback6', 'fc00::55/64'): {}, + } + expected = OrderedDict( + [ + (('Loopback1', 'fc00::1/128'), {}), + (('Loopback3', '55.55.55.55/32'), {}), + (('Loopback6', 'fc00::55/64'), {}), + (('Loopback2', '11.11.11.11/32'), {}), + (('Loopback0', 'fc00::/128'), {}), + (('Loopback5', '22.22.22.1/24'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert dict(res) == dict(expected) + +@pytest.fixture +def test_pfx_filter_wrong_ip(caplog): + src = { + ('Loopback0', 'wrong_ip'): {}, + } + res = TemplateFabric.pfx_filter(src) + assert "'wrong_ip' is invalid ip address" in caplog.text + assert isinstance(res, OrderedDict) and len(res) == 0 + diff --git a/src/sonic-bgpcfgd/tests/test_setsrc.py b/src/sonic-bgpcfgd/tests/test_setsrc.py new file mode 100644 index 000000000000..5d1a81908837 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_setsrc.py @@ -0,0 +1,62 @@ +from unittest.mock import MagicMock, patch + +import os +from bgpcfgd.directory import Directory +from bgpcfgd.template import TemplateFabric +from copy import deepcopy +from . import swsscommon_test +from swsscommon import swsscommon + +with patch.dict("sys.modules", swsscommon=swsscommon_test): + from bgpcfgd.managers_setsrc import ZebraSetSrc + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') + +def constructor(): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(TEMPLATE_PATH), + 'constants': {}, + } + + m = ZebraSetSrc(common_objs, "STATE_DB", swsscommon.STATE_INTERFACE_TABLE_NAME) + assert m.lo_ipv4 == None + assert m.lo_ipv6 == None + + return m + +@patch('bgpcfgd.managers_setsrc.log_info') +def test_set_handler(mocked_log_info): + m = constructor() + res = m.set_handler("Loopback0|10.1.0.32/32", {"state": "ok"}) + assert res, "Returns always True" + mocked_log_info.assert_called_with("The 'set src' configuration with Loopback0 ip '10.1.0.32' has been scheduled to be added") + +@patch('bgpcfgd.managers_setsrc.log_err') +def test_set_handler_no_slash(mocked_log_err): + m = constructor() + res = m.set_handler("Loopback0|10.1.0.32", {"state": "ok"}) + assert res, "Returns always True" + mocked_log_err.assert_called_with("Wrong Loopback0 ip prefix: '10.1.0.32'") + +@patch('bgpcfgd.managers_setsrc.log_info') +def test_set_handler_ipv6(mocked_log_info): + m = constructor() + res = m.set_handler("Loopback0|FC00:1::32/128", {"state": "ok"}) + assert res, "Returns always True" + mocked_log_info.assert_called_with("The 'set src' configuration with Loopback0 ip 'FC00:1::32' has been scheduled to be added") + +@patch('bgpcfgd.managers_setsrc.log_err') +def test_set_handler_invalid_ip(mocked_log_err): + m = constructor() + res = m.set_handler("Loopback0|invalid/ip", {"state": "ok"}) + assert res, "Returns always True" + mocked_log_err.assert_called_with("Got ambiguous ip address 'invalid'") + +@patch('bgpcfgd.managers_setsrc.log_warn') +def test_del_handler(mocked_log_warn): + m = constructor() + m.del_handler("Loopback0|10.1.0.32/32") + mocked_log_warn.assert_called_with("Delete command is not supported for 'zebra set src' templates") diff --git a/src/sonic-bgpcfgd/tests/test_sonic-cfggen.py b/src/sonic-bgpcfgd/tests/test_sonic-cfggen.py new file mode 100644 index 000000000000..a9c93749d5c4 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_sonic-cfggen.py @@ -0,0 +1,136 @@ +import os +import subprocess + +from bgpcfgd.config import ConfigMgr + + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') +DATA_PATH = "tests/data/sonic-cfggen/" +CONSTANTS_PATH = os.path.abspath('../../files/image_config/constants/constants.yml') + + +def run_test(name, template_path, json_path, match_path): + template_path = os.path.join(TEMPLATE_PATH, template_path) + json_path = os.path.join(DATA_PATH, json_path) + command = ['sonic-cfggen', "-T", TEMPLATE_PATH, "-t", template_path, "-y", json_path] + p = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + assert p.returncode == 0, "sonic-cfggen for %s test returned %d code. stderr='%s'" % (name, p.returncode, stderr) + raw_generated_result = stdout.decode("ascii") + assert "None" not in raw_generated_result, "Test %s" % name + canonical_generated_result = ConfigMgr.to_canonical(raw_generated_result) + match_path = os.path.join(DATA_PATH, match_path) + # only for development write_result(match_path, raw_generated_result) + with open(match_path) as result_fp: + raw_saved_result = result_fp.read() + canonical_saved_result = ConfigMgr.to_canonical(raw_saved_result) + assert canonical_saved_result == canonical_generated_result, "Test %s" % name + + +def test_bgpd_main_conf_base(): + run_test("Base bgpd.main.conf.j2", + "bgpd/bgpd.main.conf.j2", + "bgpd.main.conf.j2/base.json", + "bgpd.main.conf.j2/base.conf") + +def test_bgpd_main_conf_comprehensive(): + run_test("Comprehensive bgpd.main.conf.j2", + "bgpd/bgpd.main.conf.j2", + "bgpd.main.conf.j2/all.json", + "bgpd.main.conf.j2/all.conf") + +def test_bgpd_main_conf_defaults(): + run_test("Defaults bgpd.main.conf.j2", + "bgpd/bgpd.main.conf.j2", + "bgpd.main.conf.j2/defaults.json", + "bgpd.main.conf.j2/defaults.conf") + +def test_tsa_isolate(): + run_test("tsa/bgpd.tsa.isolate.conf.j2", + "bgpd/tsa/bgpd.tsa.isolate.conf.j2", + "tsa/isolate.json", + "tsa/isolate.conf") + +def test_tsa_unisolate(): + run_test("tsa/bgpd.tsa.unisolate.conf.j2", + "bgpd/tsa/bgpd.tsa.unisolate.conf.j2", + "tsa/unisolate.json", + "tsa/unisolate.conf") + +def test_common_daemons(): + run_test("daemons.common.conf.j2", + "common/daemons.common.conf.j2", + "common/daemons.common.conf.json", + "common/daemons.common.conf") + +def test_common_functions(): + run_test("functions.conf.j2", + "common/functions.conf.j2", + "common/functions.conf.json", + "common/functions.conf") + +def test_staticd_default_route(): + run_test("staticd.default_route.conf.j2", + "staticd/staticd.default_route.conf.j2", + "staticd/staticd.default_route.conf.json", + "staticd/staticd.default_route.conf") + +def test_staticd_loopback_route(): + run_test("staticd.loopback_route.conf.j2", + "staticd/staticd.loopback_route.conf.j2", + "staticd/staticd.loopback_route.conf.json", + "staticd/staticd.loopback_route.conf") + +def test_staticd(): + run_test("staticd.conf.j2", + "staticd/staticd.conf.j2", + "staticd/staticd.conf.json", + "staticd/staticd.conf") + +def test_zebra_interfaces(): + run_test("zebra.interfaces.conf.j2", + "zebra/zebra.interfaces.conf.j2", + "zebra/interfaces.json", + "zebra/interfaces.conf") + +def test_zebra_set_src(): + run_test("zebra.set_src.conf.j2", + "zebra/zebra.set_src.conf.j2", + "zebra/set_src.json", + "zebra/set_src.conf") + +def test_zebra(): + run_test("zebra.conf.j2", + "zebra/zebra.conf.j2", + "zebra/zebra.conf.json", + "zebra/zebra.conf") + +def test_isolate(): + run_test("isolate.j2", + "isolate.j2", + "isolate/isolate.json", + "isolate/isolate") + +def test_unisolate(): + run_test("unisolate.j2", + "unisolate.j2", + "isolate/unisolate.json", + "isolate/unisolate") + +def test_frr_conf(): + run_test("frr.conf.j2", + "frr.conf.j2", + "frr.conf.j2/all.json", + "frr.conf.j2/all.conf") + +def test_l3vpn_base(): + run_test("bgpd spine_chassis_frontend_router.conf.j2", + "bgpd/bgpd.spine_chassis_frontend_router.conf.j2", + "bgpd.spine_chassis_frontend_router.conf.j2/base.json", + "bgpd.spine_chassis_frontend_router.conf.j2/base.conf") + +def test_bgp_conf_all(): + run_test("bgpd/bgpd.conf", + "bgpd/bgpd.conf.j2", + "bgpd.conf.j2/all.json", + "bgpd.conf.j2/all.conf") diff --git a/src/sonic-bgpcfgd/tests/test_templates.py b/src/sonic-bgpcfgd/tests/test_templates.py new file mode 100644 index 000000000000..7d3bc773ad16 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_templates.py @@ -0,0 +1,142 @@ +import os +import json + + +from bgpcfgd.template import TemplateFabric +from bgpcfgd.config import ConfigMgr +from .util import load_constants_dir_mappings + + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') + + +def load_tests(peer_type, template_name): + constants = load_constants_dir_mappings() + path = "tests/data/%s/%s" % (constants[peer_type], template_name) + param_files = [name for name in os.listdir(path) + if os.path.isfile(os.path.join(path, name)) and name.startswith("param_")] + tests = [] + for param_fname in param_files: + casename = param_fname.replace("param_", "").replace(".json", "") + result_fname = "result_%s.conf" % casename + full_param_fname = os.path.join(path, param_fname) + full_result_fname = os.path.join(path, result_fname) + tests.append((casename, full_param_fname, full_result_fname)) + tmpl_path = os.path.join("bgpd", "templates", constants[peer_type], "%s.j2" % template_name) + return tmpl_path, tests + +def load_json(fname): + with open(fname) as param_fp: + raw_params = json.load(param_fp) + params = {} + for table_key, table_entries in raw_params.items(): + if table_key.startswith("CONFIG_DB__"): + # convert CONFIG_DB__* entries keys into tuple if needed + new_table_entries = {} + for entry_key, entry_value in table_entries.items(): + if '|' in entry_key: + new_key = tuple(entry_key.split('|')) + else: + new_key = entry_key + new_table_entries[new_key] = entry_value + params[table_key] = new_table_entries + else: + params[table_key] = table_entries + return params + +def compress_comments(raw_config): + comment_counter = 0 + output = [] + for line in raw_config.split('\n'): + stripped_line = line.strip() + # Skip empty lines + if stripped_line == '': + pass + # Write lines without comments + elif not stripped_line.startswith('!'): + if comment_counter > 0: + output.append("!") + comment_counter = 0 + output.append(line) + # Write non-empty comments + elif stripped_line.startswith('!') and len(stripped_line) > 1: + if comment_counter > 0: + output.append("!") + comment_counter = 0 + output.append(line) + # Count empty comments + else: # stripped_line == '!' + comment_counter += 1 + # Flush last comment if we have one + if comment_counter > 0: + output.append("!") + return "\n".join(output) + "\n" + +def write_result(fname, raw_result): + with open(fname, 'w') as fp: + raw_result_w_commpressed_comments = compress_comments(raw_result) + fp.write(raw_result_w_commpressed_comments) + +def run_tests(test_name, template_fname, tests): + tf = TemplateFabric(TEMPLATE_PATH) + template = tf.from_file(template_fname) + for case_name, param_fname, result_fname in tests: + params = load_json(param_fname) + raw_generated_result = str(template.render(params)) + assert "None" not in raw_generated_result, "Test %s.%s" % (test_name, case_name) + # this is used only for initial generation write_result(result_fname, raw_generated_result) + canonical_generated_result = ConfigMgr.to_canonical(raw_generated_result) + with open(result_fname) as result_fp: + raw_saved_result = result_fp.read() + canonical_saved_result = ConfigMgr.to_canonical(raw_saved_result) + assert canonical_saved_result == canonical_generated_result, "Test %s.%s" % (test_name, case_name) + +# Tests + +def test_general_policies(): + test_data = load_tests("general", "policies.conf") + run_tests("general_policies", *test_data) + +def test_general_pg(): + test_data = load_tests("general", "peer-group.conf") + run_tests("general_pg", *test_data) + +def test_general_instance(): + test_data = load_tests("general", "instance.conf") + run_tests("general_instance", *test_data) + +def test_internal_policies(): + test_data = load_tests("internal", "policies.conf") + run_tests("internal_policies", *test_data) + +def test_internal_pg(): + test_data = load_tests("internal", "peer-group.conf") + run_tests("internal_pg", *test_data) + +def test_internal_instance(): + test_data = load_tests("internal", "instance.conf") + run_tests("internal_instance", *test_data) + +def test_dynamic_policies(): + test_data = load_tests("dynamic", "policies.conf") + run_tests("dynamic_policies", *test_data) + +def test_dynamic_pg(): + test_data = load_tests("dynamic", "peer-group.conf") + run_tests("dynamic_pg", *test_data) + +def test_dynamic_instance(): + test_data = load_tests("dynamic", "instance.conf") + run_tests("dynamic_instance", *test_data) + +def test_monitors_policies(): + test_data = load_tests("monitors", "policies.conf") + run_tests("monitors_policies", *test_data) + +def test_monitors_pg(): + test_data = load_tests("monitors", "peer-group.conf") + run_tests("monitors_pg", *test_data) + +def test_monitors_instance(): + test_data = load_tests("monitors", "instance.conf") + run_tests("monitors_instance", *test_data) diff --git a/src/sonic-bgpcfgd/tests/util.py b/src/sonic-bgpcfgd/tests/util.py new file mode 100644 index 000000000000..a328a272c836 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/util.py @@ -0,0 +1,20 @@ +import os +import yaml + +CONSTANTS_PATH = os.path.abspath('../../files/image_config/constants/constants.yml') + +def load_constants_dir_mappings(): + data = load_constants() + result = {} + assert "bgp" in data["constants"], "'bgp' key not found in constants.yml" + assert "peers" in data["constants"]["bgp"], "'peers' key not found in constants.yml" + for name, value in data["constants"]["bgp"]["peers"].items(): + assert "template_dir" in value, "'template_dir' key not found for peer '%s'" % name + result[name] = value["template_dir"] + return result + +def load_constants(): + with open(CONSTANTS_PATH) as f: + data = yaml.load(f) # FIXME" , Loader=yaml.FullLoader) + assert "constants" in data, "'constants' key not found in constants.yml" + return data diff --git a/src/sonic-build-hooks/.gitignore b/src/sonic-build-hooks/.gitignore new file mode 100644 index 000000000000..4490afae4a5e --- /dev/null +++ b/src/sonic-build-hooks/.gitignore @@ -0,0 +1,2 @@ +buildinfo +tmp diff --git a/src/sonic-build-hooks/Makefile b/src/sonic-build-hooks/Makefile new file mode 100644 index 000000000000..786af9056332 --- /dev/null +++ b/src/sonic-build-hooks/Makefile @@ -0,0 +1,39 @@ +SONIC_BUILD_HOOKS = sonic-build-hooks +SONIC_BUILD_HOOKS_VERSION = 1.0 +SONIC_BUILD_HOOKS_PACKAGE = $(SONIC_BUILD_HOOKS)_$(SONIC_BUILD_HOOKS_VERSION)_all.deb + +BUILDINFO_DIR = buildinfo +TMP_DIR = tmp +SYMBOL_LINKS_SRC_DIR = ../../usr/local/share/buildinfo/scripts +SYMBOL_LINKS = symlink_build_hooks post_run_buildinfo pre_run_buildinfo collect_version_files +SONIC_BUILD_HOOKS_TARGET = $(BUILDINFO_DIR)/$(SONIC_BUILD_HOOKS_PACKAGE) +BUILD_ROOT_DIR = $(TMP_DIR)/$(SONIC_BUILD_HOOKS) +DEBIAN_DIR = $(BUILD_ROOT_DIR)/DEBIAN +TRUSTED_GPG_PATH = $(BUILD_ROOT_DIR)/etc/apt/trusted.gpg.d +INSTALL_PATH = $(BUILD_ROOT_DIR)/usr/local/share/buildinfo +SYMBOL_LINK_PATH = $(BUILD_ROOT_DIR)/usr/sbin +SCRIPTS_PATH = $(INSTALL_PATH)/scripts +HOOKS_PATH = $(INSTALL_PATH)/hooks +DPKGTOOL = $(shell which dpkg-deb) + + +# If the depk-deb not installed, use the docker container to make the debian package +ifeq ($(shell which dpkg-deb),) +BUILD_COMMAND=docker run --user $(shell id -u):$(shell id -g) --rm -v $(shell pwd):/build debian:buster bash -c 'cd /build; dpkg-deb --build $(TMP_DIR)/$(SONIC_BUILD_HOOKS) $(SONIC_BUILD_HOOKS_TARGET)' +else +BUILD_COMMAND=dpkg-deb --build $(TMP_DIR)/$(SONIC_BUILD_HOOKS) $(SONIC_BUILD_HOOKS_TARGET) +endif + +DEPENDS := $(shell find scripts hooks debian -type f) +$(SONIC_BUILD_HOOKS_TARGET): $(DEPENDS) + @rm -rf $(BUILDINFO_DIR)/$(SONIC_BUILD_HOOKS) $(TMP_DIR) + @mkdir -p $(DEBIAN_DIR) $(SCRIPTS_PATH) $(HOOKS_PATH) $(SYMBOL_LINK_PATH) $(TRUSTED_GPG_PATH) $(BUILDINFO_DIR) + @chmod 0775 $(DEBIAN_DIR) + @cp debian/* $(DEBIAN_DIR)/ + @cp scripts/* $(SCRIPTS_PATH)/ + @cp hooks/* $(HOOKS_PATH)/ + @for url in $$(echo $(TRUSTED_GPG_URLS) | sed 's/[,;]/ /g'); do wget -q "$$url" -P "$(TRUSTED_GPG_PATH)/"; done + @for f in $(SYMBOL_LINKS); do ln -s $(SYMBOL_LINKS_SRC_DIR)/$$f $(SYMBOL_LINK_PATH)/$$f; done + @$(BUILD_COMMAND) + +all: $(SONIC_BUILD_HOOKS_TARGET) diff --git a/src/sonic-build-hooks/debian/control b/src/sonic-build-hooks/debian/control new file mode 100644 index 000000000000..9e2454be9d95 --- /dev/null +++ b/src/sonic-build-hooks/debian/control @@ -0,0 +1,10 @@ +Package: sonic-build-hooks +Version: 1.0 +Section: devel +Priority: optional +Architecture: all +Depends: +Maintainer: SONiC +Description: sonic build hooks + Hooks the build tools, such as apt-get, wget, pip, etc. + It is used to monitor and control the packages installed during the build. diff --git a/src/sonic-build-hooks/hooks/apt-get b/src/sonic-build-hooks/hooks/apt-get new file mode 100755 index 000000000000..9ae50a118650 --- /dev/null +++ b/src/sonic-build-hooks/hooks/apt-get @@ -0,0 +1,38 @@ +#!/bin/bash + +INSTALL= +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh + +REAL_COMMAND=$(get_command apt-get) +if [ -z "$REAL_COMMAND" ]; then + echo "The command apt-get does not exist." 1>&2 + exit 1 +fi + +VERSION_FILE="/usr/local/share/buildinfo/versions/versions-deb" +if [ "$ENABLE_VERSION_CONTROL_DEB" == "y" ]; then + for para in $@ + do + if [[ "$para" != -* ]]; then + continue + fi + if [ ! -z "$INSTALL" ]; then + if [[ "$para" == *=* ]]; then + continue + elif [[ "$para" == *=* ]]; then + continue + else + package=$para + if ! grep -q "^${package}=" $VERSION_FILE; then + echo "The version of the package ${package} is not specified." + exit 1 + fi + fi + elif [[ "$para" == "install" ]]; then + INSTALL=y + fi + done +fi + + +$REAL_COMMAND "$@" diff --git a/src/sonic-build-hooks/hooks/curl b/src/sonic-build-hooks/hooks/curl new file mode 100755 index 000000000000..58bfe0395e55 --- /dev/null +++ b/src/sonic-build-hooks/hooks/curl @@ -0,0 +1,6 @@ +#!/bin/bash + +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh +[ -z $REAL_COMMAND ] && REAL_COMMAND=/usr/bin/curl + +REAL_COMMAND=$REAL_COMMAND download_packages "$@" diff --git a/src/sonic-build-hooks/hooks/git b/src/sonic-build-hooks/hooks/git new file mode 100755 index 000000000000..644a01d5fe1e --- /dev/null +++ b/src/sonic-build-hooks/hooks/git @@ -0,0 +1,76 @@ +#!/bin/bash + +parse_config(){ + . /usr/local/share/buildinfo/scripts/buildinfo_base.sh + REAL_COMMAND=$(get_command git) + + version_file=$VERSION_PATH/versions-git + new_version_file=$BUILD_VERSION_PATH/versions-git + + MODE_CLONE=0 + # parse input parameters + for i in "$@" + do + if [[ $i == "clone" ]];then + MODE_CLONE=1 + fi + done +} + +get_clone_path(){ + # get paremater of clone path + while (( "$#" )); do + case $1 in + -b|--branch|--reference|--reference-if-able|-c|--config|--origin|-u|--upload-pack|-j|--jobs|--depth|--dissociate) + shift 2 + ;; + clone|-l|--local|--no-hardlinks|-s|--shared|--dissociate|-q|--quiet|-v|--verbose|--progress|--server-option=*|--bare|--sparse|--filter=*|--template=*|--mirror|--reference|--shallow-*|--no-tags|--recurse-submodules*|--remote-submodules|--no-remote-submodules|--separate-git-dir*) + shift 1 + ;; + *) + if [[ $URL == "" ]];then + URL=$1 + else + clone_PATH=$1 + fi + shift 1 + ;; + esac + done + + # if not specific clone path, get default clone path + [ -z $clone_PATH ] && clone_PATH=`echo $URL | rev | awk -F/ '{print$1}' | rev | awk -F. '{print$1}'` +} + +main(){ + parse_config "$@" + + # execute git. + $REAL_COMMAND "$@" + result=$? + + # if sub command is not "clone", exit + if [[ $MODE_CLONE != 1 ]];then + exit $result + fi + + get_clone_path "$@" + pushd $clone_PATH &> /dev/null + commit_latest=`$REAL_COMMAND log -n 1 | head -n 1| awk '{print$2}'` + [ -f $version_file ] && commit=`grep $URL $version_file | awk -F, '{print$2}'` + + # control version or record version file + if [[ $ENABLE_VERSION_CONTROL_GIT == "y" ]];then + # control version + [ ! -z $commit ] && $REAL_COMMAND reset --hard $commit &> /dev/null + else + # record version file + echo "$URL==$commit_latest" >> $new_version_file + sort $new_version_file -o $new_version_file -u &> /dev/null + fi + popd &> /dev/null + + exit $result +} + +main "$@" diff --git a/src/sonic-build-hooks/hooks/pip b/src/sonic-build-hooks/hooks/pip new file mode 120000 index 000000000000..b31c5d8ca9d0 --- /dev/null +++ b/src/sonic-build-hooks/hooks/pip @@ -0,0 +1 @@ +pip2 \ No newline at end of file diff --git a/src/sonic-build-hooks/hooks/pip2 b/src/sonic-build-hooks/hooks/pip2 new file mode 100755 index 000000000000..e2ccfff2aac0 --- /dev/null +++ b/src/sonic-build-hooks/hooks/pip2 @@ -0,0 +1,13 @@ +#!/bin/bash + +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh + +VERSION_FILE="$BUILDINFO_PATH/versions/versions-py2" +REAL_COMMAND=$(get_command pip2) + +if [ ! -x "$REAL_COMMAND" ]; then + echo "The command pip2 not found" 1>&2 + exit 1 +fi + +PIP_VERSION_FILE=$VERSION_FILE ENABLE_VERSION_CONTROL_PY=$ENABLE_VERSION_CONTROL_PY2 REAL_COMMAND=$REAL_COMMAND run_pip_command "$@" diff --git a/src/sonic-build-hooks/hooks/pip3 b/src/sonic-build-hooks/hooks/pip3 new file mode 100755 index 000000000000..36a8fd93a13d --- /dev/null +++ b/src/sonic-build-hooks/hooks/pip3 @@ -0,0 +1,12 @@ +#!/bin/bash + +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh + +VERSION_FILE="$BUILDINFO_PATH/versions/versions-py3" +REAL_COMMAND=$(get_command pip3) +if [ ! -x "$REAL_COMMAND" ]; then + echo "The command pip3 not found" 1>&2 + exit 1 +fi + +PIP_VERSION_FILE=$VERSION_FILE ENABLE_VERSION_CONTROL_PY=$ENABLE_VERSION_CONTROL_PY2 REAL_COMMAND=$REAL_COMMAND run_pip_command "$@" diff --git a/src/sonic-build-hooks/hooks/wget b/src/sonic-build-hooks/hooks/wget new file mode 100755 index 000000000000..c4cb1a3d1be9 --- /dev/null +++ b/src/sonic-build-hooks/hooks/wget @@ -0,0 +1,15 @@ +#!/bin/bash + +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh +[ -z $REAL_COMMAND ] && REAL_COMMAND=$(get_command wget) +if [ -z "$REAL_COMMAND" ]; then + echo "The command wget does not exist." 1>&2 + exit 1 +fi + +if [ "$SKIP_BUILD_HOOK" == y ]; then + $REAL_COMMAND "$@" + exit $? +fi + +REAL_COMMAND=$REAL_COMMAND download_packages "$@" diff --git a/src/sonic-build-hooks/scripts/buildinfo_base.sh b/src/sonic-build-hooks/scripts/buildinfo_base.sh new file mode 100755 index 000000000000..ae85c2dcf129 --- /dev/null +++ b/src/sonic-build-hooks/scripts/buildinfo_base.sh @@ -0,0 +1,161 @@ +#!/bin/bash + +BUILDINFO_PATH=/usr/local/share/buildinfo + +LOG_PATH=$BUILDINFO_PATH/log +VERSION_PATH=$BUILDINFO_PATH/versions +PRE_VERSION_PATH=$BUILDINFO_PATH/pre-versions +DIFF_VERSION_PATH=$BUILDINFO_PATH/diff-versions +BUILD_VERSION_PATH=$BUILDINFO_PATH/build-versions +POST_VERSION_PATH=$BUILDINFO_PATH/post-versions +VERSION_DEB_PREFERENCE=$BUILDINFO_PATH/versions/01-versions-deb +WEB_VERSION_FILE=$VERSION_PATH/versions-web +BUILD_WEB_VERSION_FILE=$BUILD_VERSION_PATH/versions-web + +. $BUILDINFO_PATH/config/buildinfo.config + +URL_PREFIX=$(echo "${PACKAGE_URL_PREFIX}" | sed -E "s#(//[^/]*/).*#\1#") + +log_err() +{ + echo "$1" >> $LOG_PATH/error.log + echo "$1" 1>&2 +} + +# Get the real command not hooked by sonic-build-hook package +get_command() +{ + # Change the PATH env to get the real command by excluding the command in the hooked folders + local path=$(echo $PATH | sed 's#[^:]*buildinfo/scripts:##' | sed "s#/usr/local/sbin:##") + local command=$(PATH=$path which $1) + echo $command +} + +check_version_control() +{ + # The env variable SONIC_VERSION_CONTROL_COMPONENTS examples: + # all -- match all components + # py2,py3,deb -- match py2, py3 and deb only + if [[ ",$SONIC_VERSION_CONTROL_COMPONENTS," == *,all,* ]] || [[ ",$SONIC_VERSION_CONTROL_COMPONENTS," == *,$1,* ]]; then + echo "y" + else + echo "n" + fi +} + +get_url_version() +{ + local package_url=$1 + /usr/bin/curl -Lks $package_url | md5sum | cut -d' ' -f1 +} + +check_if_url_exist() +{ + local url=$1 + if /usr/bin/curl --output /dev/null --silent --head --fail "$1" > /dev/null 2>&1; then + echo y + else + echo n + fi +} + +download_packages() +{ + local parameters=("$@") + local filenames= + declare -A filenames + for (( i=0; i<${#parameters[@]}; i++ )) + do + local para=${parameters[$i]} + local nexti=$((i+1)) + if [[ "$para" == *://* ]]; then + local url=$para + local real_version= + if [ "$ENABLE_VERSION_CONTROL_WEB" == y ]; then + local version= + local filename=$(echo $url | awk -F"/" '{print $NF}' | cut -d? -f1 | cut -d# -f1) + [ -f $WEB_VERSION_FILE ] && version=$(grep "^${url}=" $WEB_VERSION_FILE | awk -F"==" '{print $NF}') + if [ -z "$version" ]; then + echo "Failed to verify the package: $url, the version is not specified" 2>&1 + exit 1 + fi + + local version_filename="${filename}-${version}" + local proxy_url="${PACKAGE_URL_PREFIX}/${version_filename}" + local url_exist=$(check_if_url_exist $proxy_url) + if [ "$url_exist" == y ]; then + parameters[$i]=$proxy_url + filenames[$version_filename]=$filename + real_version=$version + else + real_version=$(get_url_version $url) + if [ "$real_version" != "$version" ]; then + echo "Failed to verify url: $url, real hash value: $real_version, expected value: $version_filename" 1>&2 + exit 1 + fi + fi + else + real_version=$(get_url_version $url) + fi + + echo "$url==$real_version" >> ${BUILD_WEB_VERSION_FILE} + fi + done + + $REAL_COMMAND "${parameters[@]}" + local result=$? + + for filename in "${!filenames[@]}" + do + [ -f "$filename" ] && mv "$filename" "${filenames[$filename]}" + done + + return $result +} + +run_pip_command() +{ + parameters=("$@") + + if [ ! -x "$REAL_COMMAND" ] && [ " $1" == "freeze" ]; then + return 1 + fi + + if [ "$ENABLE_VERSION_CONTROL_PY" != "y" ]; then + $REAL_COMMAND "$@" + return $? + fi + + local found=n + local install=n + local pip_version_file=$PIP_VERSION_FILE + local tmp_version_file=$(mktemp) + [ -f "$pip_version_file" ] && cp -f $pip_version_file $tmp_version_file + for para in "${parameters[@]}" + do + ([ "$para" == "-c" ] || [ "$para" == "--constraint" ]) && found=y + if [ "$para" == "install" ]; then + install=y + elif [[ "$para" == *.whl ]]; then + package_name=$(echo $para | cut -d- -f1 | tr _ .) + sed "/^${package_name}==/d" -i $tmp_version_file + fi + done + + if [ "$found" == "n" ] && [ "$install" == "y" ]; then + parameters+=("-c") + parameters+=("${tmp_version_file}") + fi + + $REAL_COMMAND "${parameters[@]}" + local result=$? + rm $tmp_version_file + return $result +} + +ENABLE_VERSION_CONTROL_DEB=$(check_version_control "deb") +ENABLE_VERSION_CONTROL_PY2=$(check_version_control "py2") +ENABLE_VERSION_CONTROL_PY3=$(check_version_control "py3") +ENABLE_VERSION_CONTROL_WEB=$(check_version_control "web") +ENABLE_VERSION_CONTROL_GIT=$(check_version_control "git") +ENABLE_VERSION_CONTROL_DOCKER=$(check_version_control "docker") diff --git a/src/sonic-build-hooks/scripts/collect_version_files b/src/sonic-build-hooks/scripts/collect_version_files new file mode 100755 index 000000000000..b62beb4a2115 --- /dev/null +++ b/src/sonic-build-hooks/scripts/collect_version_files @@ -0,0 +1,14 @@ +#!/bin/bash + +TARGET_PATH=$1 +ARCH=$(dpkg --print-architecture) +DIST=$(grep VERSION_CODENAME /etc/os-release | cut -d= -f2) +([ -z "$DIST" ] && grep -q jessie /etc/os-release) && DIST=jessie + +mkdir -p $TARGET_PATH +chmod a+rw $TARGET_PATH +dpkg-query -W -f '${Package}==${Version}\n' > "${TARGET_PATH}/versions-deb-${DIST}-${ARCH}" +([ -x "/usr/local/bin/pip2" ] || [ -x "/usr/bin/pip2" ]) && pip2 freeze > "${TARGET_PATH}/versions-py2-${DIST}-${ARCH}" +([ -x "/usr/local/bin/pip3" ] || [ -x "/usr/bin/pip3" ]) && pip3 freeze > "${TARGET_PATH}/versions-py3-${DIST}-${ARCH}" + +exit 0 diff --git a/src/sonic-build-hooks/scripts/post_run_buildinfo b/src/sonic-build-hooks/scripts/post_run_buildinfo new file mode 100755 index 000000000000..a8dab41021b1 --- /dev/null +++ b/src/sonic-build-hooks/scripts/post_run_buildinfo @@ -0,0 +1,14 @@ +#!/bin/bash + +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh + +[ -d $POST_VERSION_PATH ] && rm -rf $POST_VERSION_PATH + +# Collect the version files +collect_version_files $POST_VERSION_PATH + +[ -d $BUILD_VERSION_PATH ] && [ ! -z "$(ls -A $BUILD_VERSION_PATH)" ] && cp -rf $BUILD_VERSION_PATH/* $POST_VERSION_PATH +rm -rf $BUILD_VERSION_PATH/* + +# Disable the build hooks +symlink_build_hooks -d diff --git a/src/sonic-build-hooks/scripts/pre_run_buildinfo b/src/sonic-build-hooks/scripts/pre_run_buildinfo new file mode 100755 index 000000000000..a8450690b6ff --- /dev/null +++ b/src/sonic-build-hooks/scripts/pre_run_buildinfo @@ -0,0 +1,20 @@ +#!/bin/bash + +. /usr/local/share/buildinfo/scripts/buildinfo_base.sh + +[ -d $DIFF_VERSION_PATH ] && rm -rf $DIFF_VERSION_PATH +mkdir -p $DIFF_VERSION_PATH +mkdir -p $BUILD_VERSION_PATH +mkdir -p $LOG_PATH + +[ -d $PRE_VERSION_PATH ] && rm -rf $PRE_VERSION_PATH +collect_version_files $PRE_VERSION_PATH +symlink_build_hooks + +chmod -R a+rw $BUILDINFO_PATH + +if [ "$ENABLE_VERSION_CONTROL_DEB" == "y" ] && [ -f $VERSION_DEB_PREFERENCE ]; then + cp -f $VERSION_DEB_PREFERENCE /etc/apt/preferences.d/ +fi + +exit 0 diff --git a/src/sonic-build-hooks/scripts/symlink_build_hooks b/src/sonic-build-hooks/scripts/symlink_build_hooks new file mode 100755 index 000000000000..2ce5ec27720f --- /dev/null +++ b/src/sonic-build-hooks/scripts/symlink_build_hooks @@ -0,0 +1,34 @@ +#!/bin/bash + +HOOK_PATH=/usr/local/share/buildinfo/hooks +TARGET_PATH=/usr/local/sbin +FILES=$(ls $HOOK_PATH) + +usage() +{ + echo "Usage: $0 [-d]" + exit 1 +} + +DISABLE=n +while getopts "d" opt; do + case $opt in + d) + DISABLE=y + ;; + *) + usage + ;; + esac +done + +for f in $FILES +do + if [ $DISABLE == "n" ]; then + [ ! -e $TARGET_PATH/$f ] && ln -s $HOOK_PATH/$f $TARGET_PATH/$f + else + ([ -e $TARGET_PATH/$f ] && ls -l $TARGET_PATH/$f | grep -q $HOOK_PATH) && rm -f $TARGET_PATH/$f + fi +done + +exit 0 diff --git a/src/sonic-config-engine/.gitignore b/src/sonic-config-engine/.gitignore new file mode 100644 index 000000000000..8562c3d1344c --- /dev/null +++ b/src/sonic-config-engine/.gitignore @@ -0,0 +1,7 @@ +**/*.pyc +*.egg-info/ +.eggs/ +build/ +dist/ +tests/output +tests/output2 diff --git a/src/sonic-config-engine/MANIFEST.in b/src/sonic-config-engine/MANIFEST.in new file mode 100644 index 000000000000..8861dd66030e --- /dev/null +++ b/src/sonic-config-engine/MANIFEST.in @@ -0,0 +1 @@ +recursive-include tests *.j2 *.yml *.xml *.json diff --git a/src/sonic-config-engine/__init__.py b/src/sonic-config-engine/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-config-engine/config_samples.py b/src/sonic-config-engine/config_samples.py new file mode 100644 index 000000000000..9072e0209c3e --- /dev/null +++ b/src/sonic-config-engine/config_samples.py @@ -0,0 +1,60 @@ +from natsort import natsorted + +def generate_t1_sample_config(data): + data['DEVICE_METADATA']['localhost']['hostname'] = 'sonic' + data['DEVICE_METADATA']['localhost']['type'] = 'LeafRouter' + data['DEVICE_METADATA']['localhost']['bgp_asn'] = '65100' + data['LOOPBACK_INTERFACE'] = {"Loopback0|10.1.0.1/32": {}} + data['BGP_NEIGHBOR'] = {} + data['DEVICE_NEIGHBOR'] = {} + data['INTERFACE'] = {} + port_count = 0 + total_port_amount = len(data['PORT']) + for port in natsorted(data['PORT']): + data['PORT'][port]['admin_status'] = 'up' + data['PORT'][port]['mtu'] = '9100' + local_addr = '10.0.{}.{}'.format(2 * port_count // 256, 2 * port_count % 256) + peer_addr = '10.0.{}.{}'.format(2 * port_count // 256, 2 * port_count % 256 + 1) + peer_name='ARISTA{0:02d}{1}'.format(1+port_count%(total_port_amount // 2), 'T2' if port_count < (total_port_amount // 2) else 'T0') + peer_asn = 65200 if port_count < (total_port_amount // 2) else 64001 + port_count - (total_port_amount // 2) + data['INTERFACE']['{}|{}/31'.format(port, local_addr)] = {} + data['BGP_NEIGHBOR'][peer_addr] = { + 'rrclient': 0, + 'name': peer_name, + 'local_addr': local_addr, + 'nhopself': 0, + 'holdtime': '180', + 'asn': str(peer_asn), + 'keepalive': '60' + } + port_count += 1 + return data; + +def generate_empty_config(data): + new_data = {'DEVICE_METADATA': data['DEVICE_METADATA']} + if 'hostname' not in new_data['DEVICE_METADATA']['localhost']: + new_data['DEVICE_METADATA']['localhost']['hostname'] = 'sonic' + if 'type' not in new_data['DEVICE_METADATA']['localhost']: + new_data['DEVICE_METADATA']['localhost']['type'] = 'LeafRouter' + return new_data + +def generate_l2_config(data): + data['VLAN'] = {'Vlan1000': {'vlanid': '1000'}} + data['VLAN_MEMBER'] = {} + for port in natsorted(data['PORT']): + data['PORT'][port].setdefault('admin_status', 'up') + data['VLAN_MEMBER']['Vlan1000|{}'.format(port)] = {'tagging_mode': 'untagged'} + return data + +_sample_generators = { + 't1': generate_t1_sample_config, + 'l2': generate_l2_config, + 'empty': generate_empty_config + } + +def get_available_config(): + return list(_sample_generators.keys()) + +def generate_sample_config(data, setting_name): + return _sample_generators[setting_name.lower()](data) + diff --git a/src/sonic-config-engine/data/l2switch.j2 b/src/sonic-config-engine/data/l2switch.j2 new file mode 100644 index 000000000000..22de3158c589 --- /dev/null +++ b/src/sonic-config-engine/data/l2switch.j2 @@ -0,0 +1,37 @@ +{ + "DEVICE_METADATA": {{ DEVICE_METADATA | tojson }}, + {% set ns = {'firstPrinted': False} -%} + "PORT": { + {%- for key, value in PORT.items() -%} + {%- if ns.firstPrinted %},{% endif %} + + "{{ key }}": { + {%- for keyPort, valuePort in value.items() %} + + {% if keyPort != "admin_status" %}"{{ keyPort }}": "{{ valuePort }}",{% endif %} + {%- endfor %} + + "admin_status": "{{ value.admin_status|default("up") }}" + } + {%- if ns.update({'firstPrinted': True}) %}{% endif -%} + {%- endfor %} + + }, + "VLAN": { + "Vlan1000": { + "vlanid": "1000" + } + }, + {% set ns = {'firstPrinted': False} -%} + "VLAN_MEMBER": { + {%- for port in PORT -%} + {%- if ns.firstPrinted %},{% endif %} + + "Vlan1000|{{ port }}": { + "tagging_mode": "untagged" + } + {%- if ns.update({'firstPrinted': True}) %}{% endif -%} + {%- endfor %} + + } +} diff --git a/src/sonic-config-engine/lazy_re.py b/src/sonic-config-engine/lazy_re.py new file mode 100644 index 000000000000..b51c385c1cc6 --- /dev/null +++ b/src/sonic-config-engine/lazy_re.py @@ -0,0 +1,22 @@ +# monkey patch re.compile to improve import time of some packages + +import re + +_orig_re_compile = re.compile + + +def __re_compile(*args, **kwargs): + class __LazyReCompile(object): + def __init__(self, *args, **kwargs): + self.args = args + self.kwargs = kwargs + self.pattern_obj = None + + def __getattr__(self, name): + if self.pattern_obj is None: + self.pattern_obj = _orig_re_compile(*self.args, **self.kwargs) + return getattr(self.pattern_obj, name) + return __LazyReCompile(*args, **kwargs) + +re.compile = __re_compile + diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py new file mode 100644 index 000000000000..0635f9171ebd --- /dev/null +++ b/src/sonic-config-engine/minigraph.py @@ -0,0 +1,1605 @@ +from __future__ import print_function + +import ipaddress +import math +import os +import sys +import json +from collections import defaultdict + +from lxml import etree as ET +from lxml.etree import QName + + +from portconfig import get_port_config +from sonic_py_common.multi_asic import get_asic_id_from_name +from sonic_py_common.interface import backplane_prefix + +# TODO: Remove this once we no longer support Python 2 +if sys.version_info.major == 3: + UNICODE_TYPE = str +else: + UNICODE_TYPE = unicode + +"""minigraph.py +version_added: "1.9" +author: Guohan Lu (gulv@microsoft.com) +short_description: Parse minigraph xml file and device description xml file +""" + +ns = "Microsoft.Search.Autopilot.Evolution" +ns1 = "http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution" +ns2 = "Microsoft.Search.Autopilot.NetMux" +ns3 = "http://www.w3.org/2001/XMLSchema-instance" + +# Device types +spine_chassis_frontend_role = 'SpineChassisFrontendRouter' +chassis_backend_role = 'ChassisBackendRouter' + +backend_device_types = ['BackEndToRRouter', 'BackEndLeafRouter'] +console_device_types = ['MgmtTsToR'] +VLAN_SUB_INTERFACE_SEPARATOR = '.' +VLAN_SUB_INTERFACE_VLAN_ID = '10' + +FRONTEND_ASIC_SUB_ROLE = 'FrontEnd' +BACKEND_ASIC_SUB_ROLE = 'BackEnd' + +# Default Virtual Network Index (VNI) +vni_default = 8000 + +############################################################################### +# +# Minigraph parsing functions +# +############################################################################### + +class minigraph_encoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, ( + ipaddress.IPv4Network, ipaddress.IPv6Network, + ipaddress.IPv4Address, ipaddress.IPv6Address + )): + return str(obj) + return json.JSONEncoder.default(self, obj) + +def get_peer_switch_info(link_metadata, devices): + peer_switch_table = {} + for data in link_metadata.values(): + if "PeerSwitch" in data: + peer_hostname = data["PeerSwitch"] + peer_lo_addr_str = devices[peer_hostname]["lo_addr"] + peer_lo_addr = ipaddress.ip_network(UNICODE_TYPE(peer_lo_addr_str)) if peer_lo_addr_str else None + + peer_switch_table[peer_hostname] = { + 'address_ipv4': str(peer_lo_addr.network_address) if peer_lo_addr else peer_lo_addr_str + } + + return peer_switch_table + +def parse_device(device): + lo_prefix = None + lo_prefix_v6 = None + mgmt_prefix = None + d_type = None # don't shadow type() + hwsku = None + name = None + deployment_id = None + cluster = None + + for node in device: + if node.tag == str(QName(ns, "Address")): + lo_prefix = node.find(str(QName(ns2, "IPPrefix"))).text + elif node.tag == str(QName(ns, "AddressV6")): + lo_prefix_v6 = node.find(str(QName(ns2, "IPPrefix"))).text + elif node.tag == str(QName(ns, "ManagementAddress")): + mgmt_prefix = node.find(str(QName(ns2, "IPPrefix"))).text + elif node.tag == str(QName(ns, "Hostname")): + name = node.text + elif node.tag == str(QName(ns, "HwSku")): + hwsku = node.text + elif node.tag == str(QName(ns, "DeploymentId")): + deployment_id = node.text + elif node.tag == str(QName(ns, "ElementType")): + d_type = node.text + elif node.tag == str(QName(ns, "ClusterName")): + cluster = node.text + + if d_type is None and str(QName(ns3, "type")) in device.attrib: + d_type = device.attrib[str(QName(ns3, "type"))] + + return (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster) + +def calculate_lcm_for_ecmp (nhdevices_bank_map, nhip_bank_map): + banks_enumerated = {} + lcm_array = [] + for value in nhdevices_bank_map.values(): + for key in nhip_bank_map.keys(): + if nhip_bank_map[key] == value: + if value not in banks_enumerated: + banks_enumerated[value] = 1 + else: + banks_enumerated[value] = banks_enumerated[value] + 1 + for bank_enumeration in banks_enumerated.values(): + lcm_list = range(1, bank_enumeration+1) + lcm_comp = lcm_list[0] + for i in lcm_list[1:]: + lcm_comp = lcm_comp * i / calculate_gcd(lcm_comp, i) + lcm_array.append(lcm_comp) + + LCM = sum(lcm_array) + return int(LCM) + +def calculate_gcd(x, y): + while y != 0: + (x, y) = (y, x % y) + return int(x) + +def formulate_fine_grained_ecmp(version, dpg_ecmp_content, port_device_map, port_alias_map): + family = "" + tag = "" + neigh_key = [] + if version == "ipv4": + family = "IPV4" + tag = "fgnhg_v4" + elif version == "ipv6": + family = "IPV6" + tag = "fgnhg_v6" + + port_nhip_map = dpg_ecmp_content['port_nhip_map'] + nhgaddr = dpg_ecmp_content['nhgaddr'] + nhg_int = dpg_ecmp_content['nhg_int'] + + nhip_device_map = {port_nhip_map[x]: port_device_map[x] for x in port_device_map + if x in port_nhip_map} + nhip_devices = sorted(list(set(nhip_device_map.values()))) + nhdevices_ip_bank_map = {device: bank for bank, device in enumerate(nhip_devices)} + nhip_bank_map = {ip: nhdevices_ip_bank_map[device] for ip, device in nhip_device_map.items()} + LCM = calculate_lcm_for_ecmp(nhdevices_ip_bank_map, nhip_bank_map) + + FG_NHG_MEMBER = {ip: {"FG_NHG": tag, "bank": bank} for ip, bank in nhip_bank_map.items()} + nhip_port_map = dict(zip(port_nhip_map.values(), port_nhip_map.keys())) + + + + for nhip, memberinfo in FG_NHG_MEMBER.items(): + if nhip in nhip_port_map: + memberinfo["link"] = port_alias_map[nhip_port_map[nhip]] + FG_NHG_MEMBER[nhip] = memberinfo + + FG_NHG_PREFIX = {nhgaddr: {"FG_NHG": tag}} + FG_NHG = {tag: {"bucket_size": LCM}} + for ip in nhip_bank_map: + neigh_key.append(str(nhg_int + "|" + ip)) + NEIGH = {neigh_key: {"family": family} for neigh_key in neigh_key} + + fine_grained_content = {"FG_NHG_MEMBER": FG_NHG_MEMBER, "FG_NHG": FG_NHG, "FG_NHG_PREFIX": FG_NHG_PREFIX, "NEIGH": NEIGH} + return fine_grained_content + +def parse_png(png, hname, dpg_ecmp_content = None): + neighbors = {} + devices = {} + console_dev = '' + console_port = '' + mgmt_dev = '' + mgmt_port = '' + port_speeds = {} + console_ports = {} + mux_cable_ports = {} + is_storage_device = False + port_device_map = {} + png_ecmp_content = {} + FG_NHG_MEMBER = {} + FG_NHG_PREFIX = {} + FG_NHG = {} + NEIGH = {} + + for child in png: + if child.tag == str(QName(ns, "DeviceInterfaceLinks")): + for link in child.findall(str(QName(ns, "DeviceLinkBase"))): + linktype = link.find(str(QName(ns, "ElementType"))).text + if linktype == "DeviceSerialLink": + enddevice = link.find(str(QName(ns, "EndDevice"))).text + endport = link.find(str(QName(ns, "EndPort"))).text + startdevice = link.find(str(QName(ns, "StartDevice"))).text + startport = link.find(str(QName(ns, "StartPort"))).text + baudrate = link.find(str(QName(ns, "Bandwidth"))).text + flowcontrol = 1 if link.find(str(QName(ns, "FlowControl"))) is not None and link.find(str(QName(ns, "FlowControl"))).text == 'true' else 0 + if enddevice.lower() == hname.lower(): + console_ports[endport] = { + 'remote_device': startdevice, + 'baud_rate': baudrate, + 'flow_control': flowcontrol + } + else: + console_ports[startport] = { + 'remote_device': enddevice, + 'baud_rate': baudrate, + 'flow_control': flowcontrol + } + continue + + if linktype == "DeviceInterfaceLink": + endport = link.find(str(QName(ns, "EndPort"))).text + startdevice = link.find(str(QName(ns, "StartDevice"))).text + port_device_map[endport] = startdevice + + if linktype != "DeviceInterfaceLink" and linktype != "UnderlayInterfaceLink": + continue + + enddevice = link.find(str(QName(ns, "EndDevice"))).text + endport = link.find(str(QName(ns, "EndPort"))).text + startdevice = link.find(str(QName(ns, "StartDevice"))).text + startport = link.find(str(QName(ns, "StartPort"))).text + bandwidth_node = link.find(str(QName(ns, "Bandwidth"))) + bandwidth = bandwidth_node.text if bandwidth_node is not None else None + if enddevice.lower() == hname.lower(): + if endport in port_alias_map: + endport = port_alias_map[endport] + neighbors[endport] = {'name': startdevice, 'port': startport} + if bandwidth: + port_speeds[endport] = bandwidth + elif startdevice.lower() == hname.lower(): + if startport in port_alias_map: + startport = port_alias_map[startport] + neighbors[startport] = {'name': enddevice, 'port': endport} + if bandwidth: + port_speeds[startport] = bandwidth + + if child.tag == str(QName(ns, "Devices")): + for device in child.findall(str(QName(ns, "Device"))): + (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster) = parse_device(device) + device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku } + if cluster: + device_data['cluster'] = cluster + if deployment_id: + device_data['deployment_id'] = deployment_id + if lo_prefix_v6: + device_data['lo_addr_v6'] = lo_prefix_v6 + devices[name] = device_data + + if name == hname: + if cluster and "str" in cluster.lower(): + is_storage_device = True + + if child.tag == str(QName(ns, "DeviceInterfaceLinks")): + for if_link in child.findall(str(QName(ns, 'DeviceLinkBase'))): + if str(QName(ns3, "type")) in if_link.attrib: + link_type = if_link.attrib[str(QName(ns3, "type"))] + if link_type == 'DeviceSerialLink': + for node in if_link: + if node.tag == str(QName(ns, "EndPort")): + console_port = node.text.split()[-1] + elif node.tag == str(QName(ns, "EndDevice")): + console_dev = node.text + elif link_type == 'DeviceMgmtLink': + for node in if_link: + if node.tag == str(QName(ns, "EndPort")): + mgmt_port = node.text.split()[-1] + elif node.tag == str(QName(ns, "EndDevice")): + mgmt_dev = node.text + + + if child.tag == str(QName(ns, "DeviceInterfaceLinks")): + for link in child.findall(str(QName(ns, 'DeviceLinkBase'))): + if link.find(str(QName(ns, "ElementType"))).text == "LogicalLink": + intf_name = link.find(str(QName(ns, "EndPort"))).text + if intf_name in port_alias_map: + intf_name = port_alias_map[intf_name] + + mux_cable_ports[intf_name] = "true" + + if (len(dpg_ecmp_content)): + for version, content in dpg_ecmp_content.items(): # version is ipv4 or ipv6 + fine_grained_content = formulate_fine_grained_ecmp(version, content, port_device_map, port_alias_map) # port_alias_map + FG_NHG_MEMBER.update(fine_grained_content['FG_NHG_MEMBER']) + FG_NHG_PREFIX.update(fine_grained_content['FG_NHG_PREFIX']) + FG_NHG.update(fine_grained_content['FG_NHG']) + NEIGH.update(fine_grained_content['NEIGH']) + + png_ecmp_content = {"FG_NHG_PREFIX": FG_NHG_PREFIX, "FG_NHG_MEMBER": FG_NHG_MEMBER, "FG_NHG": FG_NHG, + "NEIGH": NEIGH} + + return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speeds, console_ports, mux_cable_ports, is_storage_device, png_ecmp_content) + + +def parse_asic_external_link(link, asic_name, hostname): + neighbors = {} + port_speeds = {} + enddevice = link.find(str(QName(ns, "EndDevice"))).text + endport = link.find(str(QName(ns, "EndPort"))).text + startdevice = link.find(str(QName(ns, "StartDevice"))).text + startport = link.find(str(QName(ns, "StartPort"))).text + bandwidth_node = link.find(str(QName(ns, "Bandwidth"))) + bandwidth = bandwidth_node.text if bandwidth_node is not None else None + # if chassis internal is false, the interface name will be + # interface alias which should be converted to asic port name + if (enddevice.lower() == hostname.lower()): + if ((endport in port_alias_asic_map) and + (asic_name.lower() in port_alias_asic_map[endport].lower())): + endport = port_alias_asic_map[endport] + neighbors[port_alias_map[endport]] = {'name': startdevice, 'port': startport} + if bandwidth: + port_speeds[port_alias_map[endport]] = bandwidth + elif (startdevice.lower() == hostname.lower()): + if ((startport in port_alias_asic_map) and + (asic_name.lower() in port_alias_asic_map[startport].lower())): + startport = port_alias_asic_map[startport] + neighbors[port_alias_map[startport]] = {'name': enddevice, 'port': endport} + if bandwidth: + port_speeds[port_alias_map[startport]] = bandwidth + + return neighbors, port_speeds + +def parse_asic_internal_link(link, asic_name, hostname): + neighbors = {} + port_speeds = {} + enddevice = link.find(str(QName(ns, "EndDevice"))).text + endport = link.find(str(QName(ns, "EndPort"))).text + startdevice = link.find(str(QName(ns, "StartDevice"))).text + startport = link.find(str(QName(ns, "StartPort"))).text + bandwidth_node = link.find(str(QName(ns, "Bandwidth"))) + bandwidth = bandwidth_node.text if bandwidth_node is not None else None + if ((enddevice.lower() == asic_name.lower()) and + (startdevice.lower() != hostname.lower())): + if endport in port_alias_map: + endport = port_alias_map[endport] + neighbors[endport] = {'name': startdevice, 'port': startport} + if bandwidth: + port_speeds[endport] = bandwidth + elif ((startdevice.lower() == asic_name.lower()) and + (enddevice.lower() != hostname.lower())): + if startport in port_alias_map: + startport = port_alias_map[startport] + neighbors[startport] = {'name': enddevice, 'port': endport} + if bandwidth: + port_speeds[startport] = bandwidth + + return neighbors, port_speeds + +def parse_asic_png(png, asic_name, hostname): + neighbors = {} + devices = {} + port_speeds = {} + for child in png: + if child.tag == str(QName(ns, "DeviceInterfaceLinks")): + for link in child.findall(str(QName(ns, "DeviceLinkBase"))): + # Chassis internal node is used in multi-asic device or chassis minigraph + # where the minigraph will contain the internal asic connectivity and + # external neighbor information. The ChassisInternal node will be used to + # determine if the link is internal to the device or chassis. + chassis_internal_node = link.find(str(QName(ns, "ChassisInternal"))) + chassis_internal = chassis_internal_node.text if chassis_internal_node is not None else "false" + + # If the link is an external link include the external neighbor + # information in ASIC ports table + if chassis_internal.lower() == "false": + ext_neighbors, ext_port_speeds = parse_asic_external_link(link, asic_name, hostname) + neighbors.update(ext_neighbors) + port_speeds.update(ext_port_speeds) + else: + int_neighbors, int_port_speeds = parse_asic_internal_link(link, asic_name, hostname) + neighbors.update(int_neighbors) + port_speeds.update(int_port_speeds) + + if child.tag == str(QName(ns, "Devices")): + for device in child.findall(str(QName(ns, "Device"))): + (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster) = parse_device(device) + device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku } + if cluster: + device_data['cluster'] = cluster + if deployment_id: + device_data['deployment_id'] = deployment_id + if lo_prefix_v6: + device_data['lo_addr_v6']= lo_prefix_v6 + devices[name] = device_data + + + return (neighbors, devices, port_speeds) + +def parse_loopback_intf(child): + lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces"))) + lo_intfs = {} + for lointf in lointfs.findall(str(QName(ns1, "LoopbackIPInterface"))): + intfname = lointf.find(str(QName(ns, "AttachTo"))).text + ipprefix = lointf.find(str(QName(ns1, "PrefixStr"))).text + lo_intfs[(intfname, ipprefix)] = {} + return lo_intfs + +def parse_dpg(dpg, hname): + aclintfs = None + mgmtintfs = None + tunnelintfs = defaultdict(dict) + for child in dpg: + """ + In Multi-NPU platforms the acl intfs are defined only for the host not for individual asic. + There is just one aclintf node in the minigraph + Get the aclintfs node first. + """ + if aclintfs is None and child.find(str(QName(ns, "AclInterfaces"))) is not None: + aclintfs = child.find(str(QName(ns, "AclInterfaces"))) + """ + In Multi-NPU platforms the mgmt intfs are defined only for the host not for individual asic + There is just one mgmtintf node in the minigraph + Get the mgmtintfs node first. We need mgmt intf to get mgmt ip in per asic dockers. + """ + if mgmtintfs is None and child.find(str(QName(ns, "ManagementIPInterfaces"))) is not None: + mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces"))) + hostname = child.find(str(QName(ns, "Hostname"))) + if hostname.text.lower() != hname.lower(): + continue + + vni = vni_default + vni_element = child.find(str(QName(ns, "VNI"))) + if vni_element != None: + if vni_element.text.isdigit(): + vni = int(vni_element.text) + else: + print("VNI must be an integer (use default VNI %d instead)" % vni_default, file=sys.stderr) + + ipintfs = child.find(str(QName(ns, "IPInterfaces"))) + intfs = {} + ip_intfs_map = {} + for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))): + intfalias = ipintf.find(str(QName(ns, "AttachTo"))).text + intfname = port_alias_map.get(intfalias, intfalias) + ipprefix = ipintf.find(str(QName(ns, "Prefix"))).text + intfs[(intfname, ipprefix)] = {} + ip_intfs_map[ipprefix] = intfalias + lo_intfs = parse_loopback_intf(child) + + mvrfConfigs = child.find(str(QName(ns, "MgmtVrfConfigs"))) + mvrf = {} + if mvrfConfigs != None: + mv = mvrfConfigs.find(str(QName(ns1, "MgmtVrfGlobal"))) + if mv != None: + mvrf_en_flag = mv.find(str(QName(ns, "mgmtVrfEnabled"))).text + mvrf["vrf_global"] = {"mgmtVrfEnabled": mvrf_en_flag} + + mgmt_intf = {} + for mgmtintf in mgmtintfs.findall(str(QName(ns1, "ManagementIPInterface"))): + intfname = mgmtintf.find(str(QName(ns, "AttachTo"))).text + ipprefix = mgmtintf.find(str(QName(ns1, "PrefixStr"))).text + mgmtipn = ipaddress.ip_network(UNICODE_TYPE(ipprefix), False) + gwaddr = ipaddress.ip_address(next(mgmtipn.hosts())) + mgmt_intf[(intfname, ipprefix)] = {'gwaddr': gwaddr} + + pcintfs = child.find(str(QName(ns, "PortChannelInterfaces"))) + pc_intfs = [] + pcs = {} + pc_members = {} + intfs_inpc = [] # List to hold all the LAG member interfaces + for pcintf in pcintfs.findall(str(QName(ns, "PortChannel"))): + pcintfname = pcintf.find(str(QName(ns, "Name"))).text + pcintfmbr = pcintf.find(str(QName(ns, "AttachTo"))).text + pcmbr_list = pcintfmbr.split(';') + pc_intfs.append(pcintfname) + for i, member in enumerate(pcmbr_list): + pcmbr_list[i] = port_alias_map.get(member, member) + intfs_inpc.append(pcmbr_list[i]) + pc_members[(pcintfname, pcmbr_list[i])] = {'NULL': 'NULL'} + if pcintf.find(str(QName(ns, "Fallback"))) != None: + pcs[pcintfname] = {'members': pcmbr_list, 'fallback': pcintf.find(str(QName(ns, "Fallback"))).text, 'min_links': str(int(math.ceil(len() * 0.75)))} + else: + pcs[pcintfname] = {'members': pcmbr_list, 'min_links': str(int(math.ceil(len(pcmbr_list) * 0.75)))} + port_nhipv4_map = {} + port_nhipv6_map = {} + nhgaddr = ["", ""] + nhg_int = "" + nhportlist = [] + dpg_ecmp_content = {} + ipnhs = child.find(str(QName(ns, "IPNextHops"))) + if ipnhs is not None: + for ipnh in ipnhs.findall(str(QName(ns, "IPNextHop"))): + if ipnh.find(str(QName(ns, "Type"))).text == 'FineGrainedECMPGroupMember': + ipnhfmbr = ipnh.find(str(QName(ns, "AttachTo"))).text + ipnhaddr = ipnh.find(str(QName(ns, "Address"))).text + nhportlist.append(ipnhfmbr) + if "." in ipnhaddr: + port_nhipv4_map[ipnhfmbr] = ipnhaddr + elif ":" in ipnhaddr: + port_nhipv6_map[ipnhfmbr] = ipnhaddr + + if port_nhipv4_map is not None and port_nhipv6_map is not None: + subnet_check_ip = list(port_nhipv4_map.values())[0] + for subnet_range in ip_intfs_map: + if ("." in subnet_range): + a = ipaddress.ip_address(UNICODE_TYPE(subnet_check_ip)) + n = list(ipaddress.ip_network(UNICODE_TYPE(subnet_range), False).hosts()) + if a in n: + nhg_int = ip_intfs_map[subnet_range] + dwnstrms = child.find(str(QName(ns, "DownstreamSummarySet"))) + for dwnstrm in dwnstrms.findall(str(QName(ns, "DownstreamSummary"))): + dwnstrmentry = str(ET.tostring(dwnstrm)) + if ("FineGrainedECMPGroupDestination" in dwnstrmentry): + subnet_ip = dwnstrm.find(str(QName(ns1, "Subnet"))).text + truncsubnet_ip = subnet_ip.split("/")[0] + if "." in (truncsubnet_ip): + nhgaddr[0] = subnet_ip + elif ":" in (truncsubnet_ip): + nhgaddr[1] = subnet_ip + ipv4_content = {"port_nhip_map": port_nhipv4_map, "nhgaddr": nhgaddr[0], "nhg_int": nhg_int} + ipv6_content = {"port_nhip_map": port_nhipv6_map, "nhgaddr": nhgaddr[1], "nhg_int": nhg_int} + dpg_ecmp_content['ipv4'] = ipv4_content + dpg_ecmp_content['ipv6'] = ipv6_content + vlanintfs = child.find(str(QName(ns, "VlanInterfaces"))) + vlan_intfs = [] + vlans = {} + vlan_members = {} + vlantype_name = "" + intf_vlan_mbr = defaultdict(list) + for vintf in vlanintfs.findall(str(QName(ns, "VlanInterface"))): + vlanid = vintf.find(str(QName(ns, "VlanID"))).text + vintfmbr = vintf.find(str(QName(ns, "AttachTo"))).text + vmbr_list = vintfmbr.split(';') + for i, member in enumerate(vmbr_list): + intf_vlan_mbr[member].append(vlanid) + for vintf in vlanintfs.findall(str(QName(ns, "VlanInterface"))): + vintfname = vintf.find(str(QName(ns, "Name"))).text + vlanid = vintf.find(str(QName(ns, "VlanID"))).text + vintfmbr = vintf.find(str(QName(ns, "AttachTo"))).text + vlantype = vintf.find(str(QName(ns, "Type"))) + if vlantype != None: + vlantype_name = vintf.find(str(QName(ns, "Type"))).text + vmbr_list = vintfmbr.split(';') + for i, member in enumerate(vmbr_list): + vmbr_list[i] = port_alias_map.get(member, member) + sonic_vlan_member_name = "Vlan%s" % (vlanid) + if vlantype_name == "Tagged": + vlan_members[(sonic_vlan_member_name, vmbr_list[i])] = {'tagging_mode': 'tagged'} + elif len(intf_vlan_mbr[member]) > 1: + vlan_members[(sonic_vlan_member_name, vmbr_list[i])] = {'tagging_mode': 'tagged'} + else: + vlan_members[(sonic_vlan_member_name, vmbr_list[i])] = {'tagging_mode': 'untagged'} + + vlan_attributes = {'vlanid': vlanid} + + # If this VLAN requires a DHCP relay agent, it will contain a element + # containing a list of DHCP server IPs + vintf_node = vintf.find(str(QName(ns, "DhcpRelays"))) + if vintf_node is not None and vintf_node.text is not None: + vintfdhcpservers = vintf_node.text + vdhcpserver_list = vintfdhcpservers.split(';') + vlan_attributes['dhcp_servers'] = vdhcpserver_list + + vlanmac = vintf.find(str(QName(ns, "MacAddress"))) + if vlanmac != None: + vlan_attributes['mac'] = vlanmac.text + + sonic_vlan_name = "Vlan%s" % vlanid + if sonic_vlan_name != vintfname: + vlan_attributes['alias'] = vintfname + vlans[sonic_vlan_name] = vlan_attributes + + acls = {} + for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))): + if aclintf.find(str(QName(ns, "InAcl"))) is not None: + aclname = aclintf.find(str(QName(ns, "InAcl"))).text.upper().replace(" ", "_").replace("-", "_") + stage = "ingress" + elif aclintf.find(str(QName(ns, "OutAcl"))) is not None: + aclname = aclintf.find(str(QName(ns, "OutAcl"))).text.upper().replace(" ", "_").replace("-", "_") + stage = "egress" + else: + system.exit("Error: 'AclInterface' must contain either an 'InAcl' or 'OutAcl' subelement.") + aclattach = aclintf.find(str(QName(ns, "AttachTo"))).text.split(';') + acl_intfs = [] + is_mirror = False + is_mirror_v6 = False + + # TODO: Ensure that acl_intfs will only ever contain front-panel interfaces (e.g., + # maybe we should explicity ignore management and loopback interfaces?) because we + # decide an ACL is a Control Plane ACL if acl_intfs is empty below. + for member in aclattach: + member = member.strip() + if member in pcs: + # If try to attach ACL to a LAG interface then we shall add the LAG to + # to acl_intfs directly instead of break it into member ports, ACL attach + # to LAG will be applied to all the LAG members internally by SAI/SDK + acl_intfs.append(member) + elif member in vlans: + acl_intfs.append(member) + elif member in port_alias_map: + acl_intfs.append(port_alias_map[member]) + # Give a warning if trying to attach ACL to a LAG member interface, correct way is to attach ACL to the LAG interface + if port_alias_map[member] in intfs_inpc: + print("Warning: ACL " + aclname + " is attached to a LAG member interface " + port_alias_map[member] + ", instead of LAG interface", file=sys.stderr) + elif member.lower().startswith('erspan') or member.lower().startswith('egress_erspan'): + if member.lower().startswith('erspanv6') or member.lower().startswith('egress_erspanv6'): + is_mirror_v6 = True + else: + is_mirror = True + # Erspan session will be attached to all front panel ports + # initially. If panel ports is a member port of LAG, then + # the LAG will be added to acl table instead of the panel + # ports. Non-active ports will be removed from this list + # later after the rest of the minigraph has been parsed. + acl_intfs = pc_intfs[:] + for panel_port in port_alias_map.values(): + # because of port_alias_asic_map we can have duplicate in port_alias_map + # so check if already present do not add + if panel_port not in intfs_inpc and panel_port not in acl_intfs: + acl_intfs.append(panel_port) + break + if acl_intfs: + acls[aclname] = {'policy_desc': aclname, + 'stage': stage, + 'ports': acl_intfs} + if is_mirror: + acls[aclname]['type'] = 'MIRROR' + elif is_mirror_v6: + acls[aclname]['type'] = 'MIRRORV6' + else: + acls[aclname]['type'] = 'L3V6' if 'v6' in aclname.lower() else 'L3' + else: + # This ACL has no interfaces to attach to -- consider this a control plane ACL + try: + aclservice = aclintf.find(str(QName(ns, "Type"))).text + + # If we already have an ACL with this name and this ACL is bound to a different service, + # append the service to our list of services + if aclname in acls: + if acls[aclname]['type'] != 'CTRLPLANE': + print("Warning: ACL '%s' type mismatch. Not updating ACL." % aclname, file=sys.stderr) + elif acls[aclname]['services'] == aclservice: + print("Warning: ACL '%s' already contains service '%s'. Not updating ACL." % (aclname, aclservice), file=sys.stderr) + else: + acls[aclname]['services'].append(aclservice) + else: + acls[aclname] = {'policy_desc': aclname, + 'type': 'CTRLPLANE', + 'stage': stage, + 'services': [aclservice]} + except: + print("Warning: Ignoring Control Plane ACL %s without type" % aclname, file=sys.stderr) + + + mg_tunnels = child.find(str(QName(ns, "TunnelInterfaces"))) + if mg_tunnels is not None: + table_key_to_mg_key_map = {"encap_ecn_mode": "EcnEncapsulationMode", + "ecn_mode": "EcnDecapsulationMode", + "dscp_mode": "DifferentiatedServicesCodePointMode", + "ttl_mode": "TtlMode"} + for mg_tunnel in mg_tunnels.findall(str(QName(ns, "TunnelInterface"))): + tunnel_type = mg_tunnel.attrib["Type"] + tunnel_name = mg_tunnel.attrib["Name"] + tunnelintfs[tunnel_type][tunnel_name] = { + "tunnel_type": mg_tunnel.attrib["Type"].upper(), + } + + for table_key, mg_key in table_key_to_mg_key_map.items(): + # If the minigraph has the key, add the corresponding config DB key to the table + if mg_key in mg_tunnel.attrib: + tunnelintfs[tunnel_type][tunnel_name][table_key] = mg_tunnel.attrib[mg_key] + + return intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni, tunnelintfs, dpg_ecmp_content + return None, None, None, None, None, None, None, None, None, None + +def parse_host_loopback(dpg, hname): + for child in dpg: + hostname = child.find(str(QName(ns, "Hostname"))) + if hostname.text.lower() != hname.lower(): + continue + lo_intfs = parse_loopback_intf(child) + return lo_intfs + +def parse_cpg(cpg, hname, local_devices=[]): + bgp_sessions = {} + bgp_internal_sessions = {} + myasn = None + bgp_peers_with_range = {} + for child in cpg: + tag = child.tag + if tag == str(QName(ns, "PeeringSessions")): + for session in child.findall(str(QName(ns, "BGPSession"))): + start_router = session.find(str(QName(ns, "StartRouter"))).text + start_peer = session.find(str(QName(ns, "StartPeer"))).text + end_router = session.find(str(QName(ns, "EndRouter"))).text + end_peer = session.find(str(QName(ns, "EndPeer"))).text + rrclient = 1 if session.find(str(QName(ns, "RRClient"))) is not None else 0 + if session.find(str(QName(ns, "HoldTime"))) is not None: + holdtime = session.find(str(QName(ns, "HoldTime"))).text + else: + holdtime = 180 + if session.find(str(QName(ns, "KeepAliveTime"))) is not None: + keepalive = session.find(str(QName(ns, "KeepAliveTime"))).text + else: + keepalive = 60 + nhopself = 1 if session.find(str(QName(ns, "NextHopSelf"))) is not None else 0 + + if end_router.lower() == hname.lower(): + if end_router.lower() in local_devices and start_router.lower() in local_devices: + bgp_internal_sessions[start_peer.lower()] = { + 'name': start_router, + 'local_addr': end_peer.lower(), + 'rrclient': rrclient, + 'holdtime': holdtime, + 'keepalive': keepalive, + 'nhopself': nhopself, + 'admin_status': 'up' + } + else: + bgp_sessions[start_peer.lower()] = { + 'name': start_router, + 'local_addr': end_peer.lower(), + 'rrclient': rrclient, + 'holdtime': holdtime, + 'keepalive': keepalive, + 'nhopself': nhopself + } + elif start_router.lower() == hname.lower(): + if end_router.lower() in local_devices and start_router.lower() in local_devices: + bgp_internal_sessions[end_peer.lower()] = { + 'name': end_router, + 'local_addr': start_peer.lower(), + 'rrclient': rrclient, + 'holdtime': holdtime, + 'keepalive': keepalive, + 'nhopself': nhopself, + 'admin_status': 'up' + } + else: + bgp_sessions[end_peer.lower()] = { + 'name': end_router, + 'local_addr': start_peer.lower(), + 'rrclient': rrclient, + 'holdtime': holdtime, + 'keepalive': keepalive, + 'nhopself': nhopself + } + elif child.tag == str(QName(ns, "Routers")): + for router in child.findall(str(QName(ns1, "BGPRouterDeclaration"))): + asn = router.find(str(QName(ns1, "ASN"))).text + hostname = router.find(str(QName(ns1, "Hostname"))).text + if hostname.lower() == hname.lower(): + myasn = asn + peers = router.find(str(QName(ns1, "Peers"))) + for bgpPeer in peers.findall(str(QName(ns, "BGPPeer"))): + addr = bgpPeer.find(str(QName(ns, "Address"))).text + if bgpPeer.find(str(QName(ns1, "PeersRange"))) is not None: # FIXME: is better to check for type BGPPeerPassive + name = bgpPeer.find(str(QName(ns1, "Name"))).text + ip_range = bgpPeer.find(str(QName(ns1, "PeersRange"))).text + ip_range_group = ip_range.split(';') if ip_range and ip_range != "" else [] + bgp_peers_with_range[name] = { + 'name': name, + 'ip_range': ip_range_group + } + if bgpPeer.find(str(QName(ns, "Address"))) is not None: + bgp_peers_with_range[name]['src_address'] = bgpPeer.find(str(QName(ns, "Address"))).text + if bgpPeer.find(str(QName(ns1, "PeerAsn"))) is not None: + bgp_peers_with_range[name]['peer_asn'] = bgpPeer.find(str(QName(ns1, "PeerAsn"))).text + else: + for peer in bgp_sessions: + bgp_session = bgp_sessions[peer] + if hostname.lower() == bgp_session['name'].lower(): + bgp_session['asn'] = asn + for peer in bgp_internal_sessions: + bgp_internal_session = bgp_internal_sessions[peer] + if hostname.lower() == bgp_internal_session['name'].lower(): + bgp_internal_session['asn'] = asn + + bgp_monitors = { key: bgp_sessions[key] for key in bgp_sessions if 'asn' in bgp_sessions[key] and bgp_sessions[key]['name'] == 'BGPMonitor' } + bgp_sessions = { key: bgp_sessions[key] for key in bgp_sessions if 'asn' in bgp_sessions[key] and int(bgp_sessions[key]['asn']) != 0 } + bgp_internal_sessions = { key: bgp_internal_sessions[key] for key in bgp_internal_sessions if 'asn' in bgp_internal_sessions[key] and int(bgp_internal_sessions[key]['asn']) != 0 } + + return bgp_sessions, bgp_internal_sessions, myasn, bgp_peers_with_range, bgp_monitors + + +def parse_meta(meta, hname): + syslog_servers = [] + dhcp_servers = [] + ntp_servers = [] + tacacs_servers = [] + mgmt_routes = [] + erspan_dst = [] + deployment_id = None + region = None + cloudtype = None + resource_type = None + kube_data = {} + device_metas = meta.find(str(QName(ns, "Devices"))) + for device in device_metas.findall(str(QName(ns1, "DeviceMetadata"))): + if device.find(str(QName(ns1, "Name"))).text.lower() == hname.lower(): + properties = device.find(str(QName(ns1, "Properties"))) + for device_property in properties.findall(str(QName(ns1, "DeviceProperty"))): + name = device_property.find(str(QName(ns1, "Name"))).text + value = device_property.find(str(QName(ns1, "Value"))).text + value_group = value.strip().split(';') if value and value != "" else [] + if name == "DhcpResources": + dhcp_servers = value_group + elif name == "NtpResources": + ntp_servers = value_group + elif name == "SyslogResources": + syslog_servers = value_group + elif name == "TacacsServer": + tacacs_servers = value_group + elif name == "ForcedMgmtRoutes": + mgmt_routes = value_group + elif name == "ErspanDestinationIpv4": + erspan_dst = value_group + elif name == "DeploymentId": + deployment_id = value + elif name == "Region": + region = value + elif name == "CloudType": + cloudtype = value + elif name == "ResourceType": + resource_type = value + elif name == "KubernetesEnabled": + kube_data["enable"] = value + elif name == "KubernetesServerIp": + kube_data["ip"] = value + return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, resource_type, kube_data + + +def parse_linkmeta(meta, hname): + link = meta.find(str(QName(ns, "Link"))) + linkmetas = {} + for linkmeta in link.findall(str(QName(ns1, "LinkMetadata"))): + port = None + fec_disabled = None + + # Sample: ARISTA05T1:Ethernet1/33;switch-t0:fortyGigE0/4 + key = linkmeta.find(str(QName(ns1, "Key"))).text + endpoints = key.split(';') + for endpoint in endpoints: + t = endpoint.split(':') + if len(t) == 2 and t[0].lower() == hname.lower(): + port = t[1] + break + else: + # Cannot find a matching hname, something went wrong + continue + + has_peer_switch = False + upper_tor_hostname = '' + lower_tor_hostname = '' + + properties = linkmeta.find(str(QName(ns1, "Properties"))) + for device_property in properties.findall(str(QName(ns1, "DeviceProperty"))): + name = device_property.find(str(QName(ns1, "Name"))).text + value = device_property.find(str(QName(ns1, "Value"))).text + if name == "FECDisabled": + fec_disabled = value + elif name == "GeminiPeeringLink": + has_peer_switch = True + elif name == "UpperTOR": + upper_tor_hostname = value + elif name == "LowerTOR": + lower_tor_hostname = value + + linkmetas[port] = {} + if fec_disabled: + linkmetas[port]["FECDisabled"] = fec_disabled + if has_peer_switch: + if upper_tor_hostname == hname: + linkmetas[port]["PeerSwitch"] = lower_tor_hostname + else: + linkmetas[port]["PeerSwitch"] = upper_tor_hostname + return linkmetas + + +def parse_asic_meta(meta, hname): + sub_role = None + device_metas = meta.find(str(QName(ns, "Devices"))) + for device in device_metas.findall(str(QName(ns1, "DeviceMetadata"))): + if device.find(str(QName(ns1, "Name"))).text.lower() == hname.lower(): + properties = device.find(str(QName(ns1, "Properties"))) + for device_property in properties.findall(str(QName(ns1, "DeviceProperty"))): + name = device_property.find(str(QName(ns1, "Name"))).text + value = device_property.find(str(QName(ns1, "Value"))).text + if name == "SubRole": + sub_role = value + return sub_role + +def parse_deviceinfo(meta, hwsku): + port_speeds = {} + port_descriptions = {} + for device_info in meta.findall(str(QName(ns, "DeviceInfo"))): + dev_sku = device_info.find(str(QName(ns, "HwSku"))).text + if dev_sku == hwsku: + interfaces = device_info.find(str(QName(ns, "EthernetInterfaces"))).findall(str(QName(ns1, "EthernetInterface"))) + interfaces = interfaces + device_info.find(str(QName(ns, "ManagementInterfaces"))).findall(str(QName(ns1, "ManagementInterface"))) + for interface in interfaces: + alias = interface.find(str(QName(ns, "InterfaceName"))).text + speed = interface.find(str(QName(ns, "Speed"))).text + desc = interface.find(str(QName(ns, "Description"))) + if desc != None: + port_descriptions[port_alias_map.get(alias, alias)] = desc.text + port_speeds[port_alias_map.get(alias, alias)] = speed + return port_speeds, port_descriptions + +# Function to check if IP address is present in the key. +# If it is present, then the key would be a tuple. +def is_ip_prefix_in_key(key): + return (isinstance(key, tuple)) + +# Special parsing for spine chassis frontend +def parse_spine_chassis_fe(results, vni, lo_intfs, phyport_intfs, pc_intfs, pc_members, devices): + chassis_vnet ='VnetFE' + chassis_vxlan_tunnel = 'TunnelInt' + chassis_vni = vni + + # Vxlan tunnel information + lo_addr = '0.0.0.0' + for lo in lo_intfs: + lo_network = ipaddress.ip_network(UNICODE_TYPE(lo[1]), False) + if lo_network.version == 4: + lo_addr = str(lo_network.network_address) + break + results['VXLAN_TUNNEL'] = {chassis_vxlan_tunnel: { + 'src_ip': lo_addr + }} + + # Vnet information + results['VNET'] = {chassis_vnet: { + 'vxlan_tunnel': chassis_vxlan_tunnel, + 'vni': chassis_vni + }} + + # For each IP interface + for intf in phyport_intfs: + # A IP interface may have multiple entries. + # For example, "Ethernet0": {}", "Ethernet0|192.168.1.1": {}" + # We only care about the one without IP information + if is_ip_prefix_in_key(intf) == True: + continue + + neighbor_router = results['DEVICE_NEIGHBOR'][intf]['name'] + + # If the neighbor router is an external router + if devices[neighbor_router]['type'] != chassis_backend_role: + # Enslave the interface to a Vnet + phyport_intfs[intf] = {'vnet_name': chassis_vnet} + + # For each port channel IP interface + for pc_intf in pc_intfs: + # A port channel IP interface may have multiple entries. + # For example, "Portchannel0": {}", "Portchannel0|192.168.1.1": {}" + # We only care about the one without IP information + if is_ip_prefix_in_key(pc_intf) == True: + continue + + intf_name = None + # Get a physical interface that belongs to this port channel + for pc_member in pc_members: + if pc_member[0] == pc_intf: + intf_name = pc_member[1] + break + + if intf_name is None: + print('Warning: cannot find any interfaces that belong to %s' % (pc_intf), file=sys.stderr) + continue + + # Get the neighbor router of this port channel interface + neighbor_router = results['DEVICE_NEIGHBOR'][intf_name]['name'] + + # If the neighbor router is an external router + if devices[neighbor_router]['type'] != chassis_backend_role: + # Enslave the port channel interface to a Vnet + pc_intfs[pc_intf] = {'vnet_name': chassis_vnet} + +############################################################################### +# +# Post-processing functions +# +############################################################################### + +def filter_acl_table_bindings(acls, neighbors, port_channels, sub_role): + filter_acls = {} + + # If the asic role is BackEnd no ACL Table (Ctrl/Data/Everflow) is binded. + # This will be applicable in Multi-NPU Platforms. + + if sub_role == BACKEND_ASIC_SUB_ROLE: + return filter_acls + + front_port_channel_intf = [] + + # List of Backplane ports + backplane_port_list = [v for k,v in port_alias_map.items() if v.startswith(backplane_prefix())] + + # Get the front panel port channel. + for port_channel_intf in port_channels: + backend_port_channel = any(lag_member in backplane_port_list \ + for lag_member in port_channels[port_channel_intf]['members']) + if not backend_port_channel: + front_port_channel_intf.append(port_channel_intf) + + for acl_table, group_params in acls.items(): + group_type = group_params.get('type', None) + filter_acls[acl_table] = acls[acl_table] + + # For Control Plane and Data ACL no filtering is needed + # Control Plane ACL has no Interface associated and + # Data Plane ACL Interface are attached via minigraph + # AclInterface. + if group_type != 'MIRROR' and group_type != 'MIRRORV6': + continue + + # Filters out back-panel ports from the binding list for Everflow (Mirror) + # ACL tables. We define an "back-panel" port as one that is a member of a + # port channel connected to back asic or directly connected to back asic. + # This will be applicable in Multi-NPU Platforms. + front_panel_ports = [] + for port in group_params.get('ports', []): + # Filter out backplane ports + if port in backplane_port_list: + continue + # Filter out backplane port channels + if port in port_channels and port not in front_port_channel_intf: + continue + front_panel_ports.append(port) + + # Filters out inactive front-panel ports from the binding list for mirror + # ACL tables. We define an "active" port as one that is a member of a + # front pannel port channel or one that is connected to a neighboring device via front panel port. + active_ports = [port for port in front_panel_ports if port in neighbors.keys() or port in front_port_channel_intf] + + if not active_ports: + print('Warning: mirror table {} in ACL_TABLE does not have any ports bound to it'.format(acl_table), file=sys.stderr) + + filter_acls[acl_table]['ports'] = active_ports + + return filter_acls + +def enable_internal_bgp_session(bgp_sessions, filename, asic_name): + ''' + In Multi-NPU session the internal sessions will always be up. + So adding the admin-status 'up' configuration to bgp sessions + BGP session between FrontEnd and BackEnd Asics are internal bgp sessions + ''' + local_sub_role = parse_asic_sub_role(filename, asic_name) + + for peer_ip in bgp_sessions.keys(): + peer_name = bgp_sessions[peer_ip]['name'] + peer_sub_role = parse_asic_sub_role(filename, peer_name) + if ((local_sub_role == FRONTEND_ASIC_SUB_ROLE and peer_sub_role == BACKEND_ASIC_SUB_ROLE) or + (local_sub_role == BACKEND_ASIC_SUB_ROLE and peer_sub_role == FRONTEND_ASIC_SUB_ROLE)): + bgp_sessions[peer_ip].update({'admin_status': 'up'}) + +############################################################################### +# +# Main functions +# +############################################################################### +def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hwsku_config_file=None): + """ Parse minigraph xml file. + + Keyword arguments: + filename -- minigraph file name + platform -- device platform + port_config_file -- port config file name + asic_name -- asic name; to parse multi-asic device minigraph to + generate asic specific configuration. + """ + + root = ET.parse(filename).getroot() + + u_neighbors = None + u_devices = None + hwsku = None + bgp_sessions = None + bgp_monitors = [] + bgp_asn = None + intfs = None + dpg_ecmp_content = {} + png_ecmp_content = {} + vlan_intfs = None + pc_intfs = None + tunnel_intfs = None + vlans = None + vlan_members = None + pcs = None + mgmt_intf = None + lo_intfs = None + neighbors = None + devices = None + sub_role = None + resource_type = None + docker_routing_config_mode = "separated" + port_speeds_default = {} + port_speed_png = {} + port_descriptions = {} + console_ports = {} + mux_cable_ports = {} + syslog_servers = [] + dhcp_servers = [] + ntp_servers = [] + tacacs_servers = [] + mgmt_routes = [] + erspan_dst = [] + bgp_peers_with_range = None + deployment_id = None + region = None + cloudtype = None + hostname = None + linkmetas = {} + host_lo_intfs = None + is_storage_device = False + local_devices = [] + kube_data = {} + + # hostname is the asic_name, get the asic_id from the asic_name + if asic_name is not None: + asic_id = get_asic_id_from_name(asic_name) + else: + asic_id = None + + hwsku_qn = QName(ns, "HwSku") + hostname_qn = QName(ns, "Hostname") + docker_routing_config_mode_qn = QName(ns, "DockerRoutingConfigMode") + for child in root: + if child.tag == str(hwsku_qn): + hwsku = child.text + if child.tag == str(hostname_qn): + hostname = child.text + if child.tag == str(docker_routing_config_mode_qn): + docker_routing_config_mode = child.text + + (ports, alias_map, alias_asic_map) = get_port_config(hwsku=hwsku, platform=platform, port_config_file=port_config_file, asic=asic_id, hwsku_config_file=hwsku_config_file) + port_alias_map.update(alias_map) + port_alias_asic_map.update(alias_asic_map) + + # Get the local device node from DeviceMetadata + local_devices = parse_asic_meta_get_devices(root) + + for child in root: + if asic_name is None: + if child.tag == str(QName(ns, "DpgDec")): + (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, hostname) + elif child.tag == str(QName(ns, "CpgDec")): + (bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, hostname) + elif child.tag == str(QName(ns, "PngDec")): + (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speed_png, console_ports, mux_cable_ports, is_storage_device, png_ecmp_content) = parse_png(child, hostname, dpg_ecmp_content) + elif child.tag == str(QName(ns, "UngDec")): + (u_neighbors, u_devices, _, _, _, _, _, _) = parse_png(child, hostname, None) + elif child.tag == str(QName(ns, "MetadataDeclaration")): + (syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, resource_type, kube_data) = parse_meta(child, hostname) + elif child.tag == str(QName(ns, "LinkMetadataDeclaration")): + linkmetas = parse_linkmeta(child, hostname) + elif child.tag == str(QName(ns, "DeviceInfos")): + (port_speeds_default, port_descriptions) = parse_deviceinfo(child, hwsku) + else: + if child.tag == str(QName(ns, "DpgDec")): + (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, asic_name) + host_lo_intfs = parse_host_loopback(child, hostname) + elif child.tag == str(QName(ns, "CpgDec")): + (bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, asic_name, local_devices) + elif child.tag == str(QName(ns, "PngDec")): + (neighbors, devices, port_speed_png) = parse_asic_png(child, asic_name, hostname) + elif child.tag == str(QName(ns, "MetadataDeclaration")): + (sub_role) = parse_asic_meta(child, asic_name) + elif child.tag == str(QName(ns, "LinkMetadataDeclaration")): + linkmetas = parse_linkmeta(child, hostname) + elif child.tag == str(QName(ns, "DeviceInfos")): + (port_speeds_default, port_descriptions) = parse_deviceinfo(child, hwsku) + + # set the host device type in asic metadata also + device_type = [devices[key]['type'] for key in devices if key.lower() == hostname.lower()][0] + if asic_name is None: + current_device = [devices[key] for key in devices if key.lower() == hostname.lower()][0] + else: + current_device = [devices[key] for key in devices if key.lower() == asic_name.lower()][0] + + results = {} + results['DEVICE_METADATA'] = {'localhost': { + 'bgp_asn': bgp_asn, + 'deployment_id': deployment_id, + 'region': region, + 'cloudtype': cloudtype, + 'docker_routing_config_mode': docker_routing_config_mode, + 'hostname': hostname, + 'hwsku': hwsku, + 'type': device_type, + 'synchronous_mode': 'enable' + } + } + + cluster = [devices[key] for key in devices if key.lower() == hostname.lower()][0].get('cluster', "") + if cluster: + results['DEVICE_METADATA']['localhost']['cluster'] = cluster + + if kube_data: + results['KUBERNETES_MASTER'] = { + 'SERVER': { + 'disable': str(kube_data.get('enable', '0') == '0'), + 'ip': kube_data.get('ip', '') + } + } + + results['PEER_SWITCH'] = get_peer_switch_info(linkmetas, devices) + + if bool(results['PEER_SWITCH']): + results['DEVICE_METADATA']['localhost']['subtype'] = 'DualToR' + if len(results['PEER_SWITCH'].keys()) > 1: + print("Warning: more than one peer switch was found. Only the first will be parsed: {}".format(results['PEER_SWITCH'].keys()[0])) + + results['DEVICE_METADATA']['localhost']['peer_switch'] = list(results['PEER_SWITCH'].keys())[0] + + if is_storage_device: + results['DEVICE_METADATA']['localhost']['storage_device'] = "true" + + # for this hostname, if sub_role is defined, add sub_role in + # device_metadata + if sub_role is not None: + current_device['sub_role'] = sub_role + results['DEVICE_METADATA']['localhost']['sub_role'] = sub_role + results['DEVICE_METADATA']['localhost']['asic_name'] = asic_name + + if resource_type is not None: + results['DEVICE_METADATA']['localhost']['resource_type'] = resource_type + + results['BGP_NEIGHBOR'] = bgp_sessions + results['BGP_MONITORS'] = bgp_monitors + results['BGP_PEER_RANGE'] = bgp_peers_with_range + results['BGP_INTERNAL_NEIGHBOR'] = bgp_internal_sessions + if mgmt_routes: + # TODO: differentiate v4 and v6 + next(iter(mgmt_intf.values()))['forced_mgmt_routes'] = mgmt_routes + results['MGMT_PORT'] = {} + results['MGMT_INTERFACE'] = {} + mgmt_intf_count = 0 + mgmt_alias_reverse_mapping = {} + for key in mgmt_intf: + alias = key[0] + if alias in mgmt_alias_reverse_mapping: + name = mgmt_alias_reverse_mapping[alias] + else: + name = 'eth' + str(mgmt_intf_count) + mgmt_intf_count += 1 + mgmt_alias_reverse_mapping[alias] = name + results['MGMT_PORT'][name] = {'alias': alias, 'admin_status': 'up'} + if alias in port_speeds_default: + results['MGMT_PORT'][name]['speed'] = port_speeds_default[alias] + results['MGMT_INTERFACE'][(name, key[1])] = mgmt_intf[key] + results['LOOPBACK_INTERFACE'] = {} + for lo_intf in lo_intfs: + results['LOOPBACK_INTERFACE'][lo_intf] = lo_intfs[lo_intf] + results['LOOPBACK_INTERFACE'][lo_intf[0]] = {} + + if host_lo_intfs is not None: + for host_lo_intf in host_lo_intfs: + results['LOOPBACK_INTERFACE'][host_lo_intf] = host_lo_intfs[host_lo_intf] + results['LOOPBACK_INTERFACE'][host_lo_intf[0]] = {} + + results['MGMT_VRF_CONFIG'] = mvrf + + phyport_intfs = {} + vlan_intfs = {} + pc_intfs = {} + vlan_invert_mapping = { v['alias']:k for k,v in vlans.items() if 'alias' in v } + vlan_sub_intfs = {} + + for intf in intfs: + if intf[0][0:4] == 'Vlan': + vlan_intfs[intf] = {} + + if bool(results['PEER_SWITCH']): + vlan_intfs[intf[0]] = { + 'proxy_arp': 'enabled', + 'grat_arp': 'enabled' + } + else: + vlan_intfs[intf[0]] = {} + elif intf[0] in vlan_invert_mapping: + vlan_intfs[(vlan_invert_mapping[intf[0]], intf[1])] = {} + + if bool(results['PEER_SWITCH']): + vlan_intfs[vlan_invert_mapping[intf[0]]] = { + 'proxy_arp': 'enabled', + 'grat_arp': 'enabled' + } + else: + vlan_intfs[vlan_invert_mapping[intf[0]]] = {} + elif intf[0][0:11] == 'PortChannel': + pc_intfs[intf] = {} + pc_intfs[intf[0]] = {} + else: + phyport_intfs[intf] = {} + phyport_intfs[intf[0]] = {} + + results['INTERFACE'] = phyport_intfs + results['VLAN_INTERFACE'] = vlan_intfs + + for port_name in port_speeds_default: + # ignore port not in port_config.ini + if port_name not in ports: + continue + + ports.setdefault(port_name, {})['speed'] = port_speeds_default[port_name] + + for port_name in port_speed_png: + # not consider port not in port_config.ini + # If no port_config_file is found ports is empty so ignore this error + if port_config_file is not None: + if port_name not in ports: + print("Warning: ignore interface '%s' as it is not in the port_config.ini" % port_name, file=sys.stderr) + continue + + ports.setdefault(port_name, {})['speed'] = port_speed_png[port_name] + + for port_name, port in list(ports.items()): + # get port alias from port_config.ini + alias = port.get('alias', port_name) + # generate default 100G FEC + # Note: FECDisabled only be effective on 100G port right now + if port.get('speed') == '100000' and linkmetas.get(alias, {}).get('FECDisabled', '').lower() != 'true': + port['fec'] = 'rs' + + # If connected to a smart cable, get the connection position + for port_name, port in ports.items(): + if port_name in mux_cable_ports: + port['mux_cable'] = mux_cable_ports[port_name] + + # set port description if parsed from deviceinfo + for port_name in port_descriptions: + # ignore port not in port_config.ini + if port_name not in ports: + continue + + ports.setdefault(port_name, {})['description'] = port_descriptions[port_name] + + for port_name, port in ports.items(): + if not port.get('description'): + if port_name in neighbors: + # for the ports w/o description set it to neighbor name:port + port['description'] = "%s:%s" % (neighbors[port_name]['name'], neighbors[port_name]['port']) + else: + # for the ports w/o neighbor info, set it to port alias + port['description'] = port.get('alias', port_name) + + # set default port MTU as 9100 + for port in ports.values(): + port['mtu'] = '9100' + + # asymmetric PFC is disabled by default + for port in ports.values(): + port['pfc_asym'] = 'off' + + # set physical port default admin status up + for port in phyport_intfs: + if port[0] in ports: + ports.get(port[0])['admin_status'] = 'up' + + for member in list(pc_members.keys()) + list(vlan_members.keys()): + port = ports.get(member[1]) + if port: + port['admin_status'] = 'up' + + for port in neighbors.keys(): + if port in ports.keys(): + # make all neighbors connected ports to 'admin_up' + ports[port]['admin_status'] = 'up' + + results['PORT'] = ports + results['CONSOLE_PORT'] = console_ports + + if port_config_file: + port_set = set(ports.keys()) + for (pc_name, mbr_map) in list(pcs.items()): + # remove portchannels that contain ports not existing in port_config.ini + # when port_config.ini exists + if not set(mbr_map['members']).issubset(port_set): + print("Warning: ignore '%s' as part of its member interfaces is not in the port_config.ini" % pc_name, file=sys.stderr) + del pcs[pc_name] + + # set default port channel MTU as 9100 and admin status up + for pc in pcs.values(): + pc['mtu'] = '9100' + pc['admin_status'] = 'up' + + results['PORTCHANNEL'] = pcs + results['PORTCHANNEL_MEMBER'] = pc_members + + for pc_intf in list(pc_intfs.keys()): + # remove portchannels not in PORTCHANNEL dictionary + if isinstance(pc_intf, tuple) and pc_intf[0] not in pcs: + print("Warning: ignore '%s' interface '%s' as '%s' is not in the valid PortChannel list" % (pc_intf[0], pc_intf[1], pc_intf[0]), file=sys.stderr) + del pc_intfs[pc_intf] + pc_intfs.pop(pc_intf[0], None) + + results['PORTCHANNEL_INTERFACE'] = pc_intfs + + if current_device['type'] in backend_device_types and is_storage_device: + del results['INTERFACE'] + del results['PORTCHANNEL_INTERFACE'] + + for intf in phyport_intfs.keys(): + if isinstance(intf, tuple): + intf_info = list(intf) + intf_info[0] = intf_info[0] + VLAN_SUB_INTERFACE_SEPARATOR + VLAN_SUB_INTERFACE_VLAN_ID + sub_intf = tuple(intf_info) + vlan_sub_intfs[sub_intf] = {} + else: + sub_intf = intf + VLAN_SUB_INTERFACE_SEPARATOR + VLAN_SUB_INTERFACE_VLAN_ID + vlan_sub_intfs[sub_intf] = {"admin_status" : "up"} + + for pc_intf in pc_intfs.keys(): + if isinstance(pc_intf, tuple): + pc_intf_info = list(pc_intf) + pc_intf_info[0] = pc_intf_info[0] + VLAN_SUB_INTERFACE_SEPARATOR + VLAN_SUB_INTERFACE_VLAN_ID + sub_intf = tuple(pc_intf_info) + vlan_sub_intfs[sub_intf] = {} + else: + sub_intf = pc_intf + VLAN_SUB_INTERFACE_SEPARATOR + VLAN_SUB_INTERFACE_VLAN_ID + vlan_sub_intfs[sub_intf] = {"admin_status" : "up"} + + results['VLAN_SUB_INTERFACE'] = vlan_sub_intfs + + results['VLAN'] = vlans + results['VLAN_MEMBER'] = vlan_members + + results['TUNNEL'] = get_tunnel_entries(tunnel_intfs, lo_intfs, hostname) + + results['MUX_CABLE'] = get_mux_cable_entries(mux_cable_ports, neighbors, devices) + + for nghbr in list(neighbors.keys()): + # remove port not in port_config.ini + if nghbr not in ports: + if port_config_file is not None: + print("Warning: ignore interface '%s' in DEVICE_NEIGHBOR as it is not in the port_config.ini" % nghbr, file=sys.stderr) + del neighbors[nghbr] + results['DEVICE_NEIGHBOR'] = neighbors + if asic_name is None: + results['DEVICE_NEIGHBOR_METADATA'] = { key:devices[key] for key in devices if key.lower() != hostname.lower() } + else: + results['DEVICE_NEIGHBOR_METADATA'] = { key:devices[key] for key in devices if key in {device['name'] for device in neighbors.values()} } + results['SYSLOG_SERVER'] = dict((item, {}) for item in syslog_servers) + results['DHCP_SERVER'] = dict((item, {}) for item in dhcp_servers) + results['NTP_SERVER'] = dict((item, {}) for item in ntp_servers) + results['TACPLUS_SERVER'] = dict((item, {'priority': '1', 'tcp_port': '49'}) for item in tacacs_servers) + results['ACL_TABLE'] = filter_acl_table_bindings(acls, neighbors, pcs, sub_role) + results['FEATURE'] = { + 'telemetry': { + 'status': 'enabled' + } + } + results['TELEMETRY'] = { + 'gnmi': { + 'client_auth': 'true', + 'port': '50051', + 'log_level': '2' + }, + 'certs': { + 'server_crt': '/etc/sonic/telemetry/streamingtelemetryserver.cer', + 'server_key': '/etc/sonic/telemetry/streamingtelemetryserver.key', + 'ca_crt': '/etc/sonic/telemetry/dsmsroot.cer' + } + } + results['RESTAPI'] = { + 'config': { + 'client_auth': 'true', + 'allow_insecure': 'false', + 'log_level': 'trace' + }, + 'certs': { + 'server_crt': '/etc/sonic/credentials/restapiserver.crt', + 'server_key': '/etc/sonic/credentials/restapiserver.key', + 'ca_crt': '/etc/sonic/credentials/restapica.crt', + 'client_crt_cname': 'client.restapi.sonic' + } + } + + if len(png_ecmp_content): + results['FG_NHG_MEMBER'] = png_ecmp_content['FG_NHG_MEMBER'] + results['FG_NHG_PREFIX'] = png_ecmp_content['FG_NHG_PREFIX'] + results['FG_NHG'] = png_ecmp_content['FG_NHG'] + results['NEIGH'] = png_ecmp_content['NEIGH'] + + # Do not configure the minigraph's mirror session, which is currently unused + # mirror_sessions = {} + # if erspan_dst: + # lo_addr = '0.0.0.0' + # for lo in lo_intfs: + # lo_network = ipaddress.ip_network(UNICODE_TYPE(lo[1]), False) + # if lo_network.version == 4: + # lo_addr = str(lo_network.network_address) + # break + # count = 0 + # for dst in erspan_dst: + # mirror_sessions['everflow{}'.format(count)] = {"dst_ip": dst, "src_ip": lo_addr} + # count += 1 + # results['MIRROR_SESSION'] = mirror_sessions + + # Special parsing for spine chassis frontend routers + if current_device['type'] == spine_chassis_frontend_role: + parse_spine_chassis_fe(results, vni, lo_intfs, phyport_intfs, pc_intfs, pc_members, devices) + + # Enable console management feature for console swtich + results['CONSOLE_SWITCH'] = { + 'console_mgmt' : { + 'enabled' : 'yes' if current_device['type'] in console_device_types else 'no' + } + } + + return results + +def get_tunnel_entries(tunnel_intfs, lo_intfs, hostname): + lo_addr = '' + # Use the first IPv4 loopback as the tunnel destination IP + for addr in lo_intfs.keys(): + ip_addr = ipaddress.ip_network(UNICODE_TYPE(addr[1])) + if isinstance(ip_addr, ipaddress.IPv4Network): + lo_addr = str(ip_addr.network_address) + break + + tunnels = {} + for type, tunnel_dict in tunnel_intfs.items(): + for tunnel_key, tunnel_attr in tunnel_dict.items(): + tunnel_attr['dst_ip'] = lo_addr + tunnels[tunnel_key] = tunnel_attr + return tunnels + +def get_mux_cable_entries(mux_cable_ports, neighbors, devices): + mux_cable_table = {} + + for intf in mux_cable_ports: + if intf in neighbors: + entry = {} + neighbor = neighbors[intf]['name'] + entry['state'] = 'auto' + + if devices[neighbor]['lo_addr'] is not None: + # Always force a /32 prefix for server IPv4 loopbacks + server_ipv4_lo_addr = devices[neighbor]['lo_addr'].split("/")[0] + server_ipv4_lo_prefix = ipaddress.ip_network(UNICODE_TYPE(server_ipv4_lo_addr)) + entry['server_ipv4'] = str(server_ipv4_lo_prefix) + + if 'lo_addr_v6' in devices[neighbor] and devices[neighbor]['lo_addr_v6'] is not None: + server_ipv6_lo_addr = devices[neighbor]['lo_addr_v6'].split('/')[0] + server_ipv6_lo_prefix = ipaddress.ip_network(UNICODE_TYPE(server_ipv6_lo_addr)) + entry['server_ipv6'] = str(server_ipv6_lo_prefix) + mux_cable_table[intf] = entry + else: + print("Warning: no server IPv4 loopback found for {}, skipping mux cable table entry".format(neighbor)) + + return mux_cable_table + +def parse_device_desc_xml(filename): + root = ET.parse(filename).getroot() + (lo_prefix, lo_prefix_v6, mgmt_prefix, hostname, hwsku, d_type, _, _) = parse_device(root) + + results = {} + results['DEVICE_METADATA'] = {'localhost': { + 'hostname': hostname, + 'hwsku': hwsku, + }} + + results['LOOPBACK_INTERFACE'] = {('lo', lo_prefix): {}} + if lo_prefix_v6: + results['LOOPBACK_INTERFACE'] = {('lo_v6', lo_prefix_v6): {}} + + mgmt_intf = {} + mgmtipn = ipaddress.ip_network(UNICODE_TYPE(mgmt_prefix), False) + gwaddr = ipaddress.ip_address((next(mgmtipn.hosts()))) + results['MGMT_INTERFACE'] = {('eth0', mgmt_prefix): {'gwaddr': gwaddr}} + + return results + +def parse_asic_sub_role(filename, asic_name): + if not os.path.isfile(filename): + return None + root = ET.parse(filename).getroot() + for child in root: + if child.tag == str(QName(ns, "MetadataDeclaration")): + sub_role = parse_asic_meta(child, asic_name) + return sub_role + +def parse_asic_meta_get_devices(root): + local_devices = [] + + for child in root: + if child.tag == str(QName(ns, "MetadataDeclaration")): + device_metas = child.find(str(QName(ns, "Devices"))) + for device in device_metas.findall(str(QName(ns1, "DeviceMetadata"))): + name = device.find(str(QName(ns1, "Name"))).text.lower() + local_devices.append(name) + + return local_devices + +port_alias_map = {} +port_alias_asic_map = {} + + +def print_parse_xml(filename): + results = parse_xml(filename) + print((json.dumps(results, indent=3, cls=minigraph_encoder))) diff --git a/src/sonic-config-engine/openconfig_acl.py b/src/sonic-config-engine/openconfig_acl.py new file mode 100644 index 000000000000..c49f79c70175 --- /dev/null +++ b/src/sonic-config-engine/openconfig_acl.py @@ -0,0 +1,7352 @@ +# This file is auto generated by pyangbind: https://github.com/robshakir/pyangbind +# from https://github.com/openconfig/public/blob/master/release/models/acl/openconfig-acl.yang +# +# Detail step to regenerate this file: +# 1. Sync openconfig ACL yang models from https://github.com/openconfig/public/tree/master/release/models/acl +# 2. Sync inet yang models which contain type dependencies for openconfig ACL yang models from https://github.com/YangModels/yang/tree/master/standard/ietf/RFC , and put them in the same folder with models from step 1. +# 3. Install PyangBind: +# pip install pyangbind +# 4. Get PyangBind install path: +# export PYBINDPLUGIN=`/usr/bin/env python -c \ +# 'import pyangbind; import os; print "%s/plugin" % os.path.dirname(pyangbind.__file__)'` +# 5. Generate this file with pyang: +# pyang --plugindir $PYBINDPLUGIN -f pybind -o openconfig_acl.py openconfig-acl.yang + +from operator import attrgetter +from pyangbind.lib.yangtypes import RestrictedPrecisionDecimalType, RestrictedClassType, TypedListType +from pyangbind.lib.yangtypes import YANGBool, YANGListType, YANGDynClass, ReferenceType +from pyangbind.lib.base import PybindBase +from decimal import Decimal +from bitarray import bitarray + +import builtins + +class yc_state_openconfig_acl__acl_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Global operational state data for ACLs + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__counter_capability',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__counter_capability = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-acl:AGGREGATE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:INTERFACE_AGGREGATE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'AGGREGATE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'INTERFACE_AGGREGATE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'INTERFACE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:INTERFACE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), is_leaf=True, yang_name="counter-capability", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'state'] + + def _get_counter_capability(self): + """ + Getter method for counter_capability, mapped from YANG variable /acl/state/counter_capability (identityref) + + YANG Description: System reported indication of how ACL counters are reported +by the target + """ + return self.__counter_capability + + def _set_counter_capability(self, v, load=False): + """ + Setter method for counter_capability, mapped from YANG variable /acl/state/counter_capability (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_counter_capability is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_counter_capability() directly. + + YANG Description: System reported indication of how ACL counters are reported +by the target + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-acl:AGGREGATE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:INTERFACE_AGGREGATE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'AGGREGATE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'INTERFACE_AGGREGATE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'INTERFACE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:INTERFACE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), is_leaf=True, yang_name="counter-capability", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """counter_capability must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-acl:AGGREGATE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:INTERFACE_AGGREGATE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'AGGREGATE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'INTERFACE_AGGREGATE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'INTERFACE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:INTERFACE_ONLY': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="counter-capability", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False)""", + }) + + self.__counter_capability = t + if hasattr(self, '_set'): + self._set() + + def _unset_counter_capability(self): + self.__counter_capability = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-acl:AGGREGATE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:INTERFACE_AGGREGATE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'AGGREGATE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'INTERFACE_AGGREGATE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'INTERFACE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:INTERFACE_ONLY': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), is_leaf=True, yang_name="counter-capability", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + counter_capability = builtins.property(_get_counter_capability) + + + _pyangbind_elements = {'counter_capability': counter_capability, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Access list config + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__name','__description',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__name = YANGDynClass(base=str, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + self.__description = YANGDynClass(base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'config'] + + def _get_name(self): + """ + Getter method for name, mapped from YANG variable /acl/acl_sets/acl_set/config/name (string) + + YANG Description: The name of the access-list set + """ + return self.__name + + def _set_name(self, v, load=False): + """ + Setter method for name, mapped from YANG variable /acl/acl_sets/acl_set/config/name (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_name() directly. + + YANG Description: The name of the access-list set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """name must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True)""", + }) + + self.__name = t + if hasattr(self, '_set'): + self._set() + + def _unset_name(self): + self.__name = YANGDynClass(base=str, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + + + def _get_description(self): + """ + Getter method for description, mapped from YANG variable /acl/acl_sets/acl_set/config/description (string) + + YANG Description: Description, or comment, for the ACL set + """ + return self.__description + + def _set_description(self, v, load=False): + """ + Setter method for description, mapped from YANG variable /acl/acl_sets/acl_set/config/description (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_description is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_description() directly. + + YANG Description: Description, or comment, for the ACL set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """description must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True)""", + }) + + self.__description = t + if hasattr(self, '_set'): + self._set() + + def _unset_description(self): + self.__description = YANGDynClass(base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + + name = builtins.property(_get_name, _set_name) + description = builtins.property(_get_description, _set_description) + + + _pyangbind_elements = {'name': name, 'description': description, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Access list state information + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__name','__description',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__name = YANGDynClass(base=str, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + self.__description = YANGDynClass(base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'state'] + + def _get_name(self): + """ + Getter method for name, mapped from YANG variable /acl/acl_sets/acl_set/state/name (string) + + YANG Description: The name of the access-list set + """ + return self.__name + + def _set_name(self, v, load=False): + """ + Setter method for name, mapped from YANG variable /acl/acl_sets/acl_set/state/name (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_name() directly. + + YANG Description: The name of the access-list set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """name must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False)""", + }) + + self.__name = t + if hasattr(self, '_set'): + self._set() + + def _unset_name(self): + self.__name = YANGDynClass(base=str, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + + + def _get_description(self): + """ + Getter method for description, mapped from YANG variable /acl/acl_sets/acl_set/state/description (string) + + YANG Description: Description, or comment, for the ACL set + """ + return self.__description + + def _set_description(self, v, load=False): + """ + Setter method for description, mapped from YANG variable /acl/acl_sets/acl_set/state/description (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_description is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_description() directly. + + YANG Description: Description, or comment, for the ACL set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """description must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False)""", + }) + + self.__description = t + if hasattr(self, '_set'): + self._set() + + def _unset_description(self): + self.__description = YANGDynClass(base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + + name = builtins.property(_get_name) + description = builtins.property(_get_description) + + + _pyangbind_elements = {'name': name, 'description': description, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Access list entries config + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__description',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__sequence_id = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=True) + self.__description = YANGDynClass(base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'config'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config/sequence_id (uint32) + + YANG Description: The sequence id determines the order in which ACL entries +are applied. The sequence id must be unique for each entry +in an ACL set. Target devices should apply the ACL entry +rules in the order determined by sequence id, rather than +the relying only on order in the list. + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config/sequence_id (uint32) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: The sequence id determines the order in which ACL entries +are applied. The sequence id must be unique for each entry +in an ACL set. Target devices should apply the ACL entry +rules in the order determined by sequence id, rather than +the relying only on order in the list. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with uint32""", + 'defined-type': "uint32", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=True)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=True) + + + def _get_description(self): + """ + Getter method for description, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config/description (string) + + YANG Description: A user-defined description, or comment, for this Access List +Entry. + """ + return self.__description + + def _set_description(self, v, load=False): + """ + Setter method for description, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config/description (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_description is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_description() directly. + + YANG Description: A user-defined description, or comment, for this Access List +Entry. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """description must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True)""", + }) + + self.__description = t + if hasattr(self, '_set'): + self._set() + + def _unset_description(self): + self.__description = YANGDynClass(base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=True) + + sequence_id = builtins.property(_get_sequence_id, _set_sequence_id) + description = builtins.property(_get_description, _set_description) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'description': description, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: State information for ACL entries + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__description','__matched_packets','__matched_octets',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + self.__sequence_id = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=False) + self.__description = YANGDynClass(base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'state'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/sequence_id (uint32) + + YANG Description: The sequence id determines the order in which ACL entries +are applied. The sequence id must be unique for each entry +in an ACL set. Target devices should apply the ACL entry +rules in the order determined by sequence id, rather than +the relying only on order in the list. + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/sequence_id (uint32) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: The sequence id determines the order in which ACL entries +are applied. The sequence id must be unique for each entry +in an ACL set. Target devices should apply the ACL entry +rules in the order determined by sequence id, rather than +the relying only on order in the list. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with uint32""", + 'defined-type': "uint32", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=False)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint32', is_config=False) + + + def _get_description(self): + """ + Getter method for description, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/description (string) + + YANG Description: A user-defined description, or comment, for this Access List +Entry. + """ + return self.__description + + def _set_description(self, v, load=False): + """ + Setter method for description, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/description (string) + If this variable is read-only (config: false) in the + source YANG file, then _set_description is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_description() directly. + + YANG Description: A user-defined description, or comment, for this Access List +Entry. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """description must be of a type compatible with string""", + 'defined-type': "string", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False)""", + }) + + self.__description = t + if hasattr(self, '_set'): + self._set() + + def _unset_description(self): + self.__description = YANGDynClass(base=str, is_leaf=True, yang_name="description", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='string', is_config=False) + + + def _get_matched_packets(self): + """ + Getter method for matched_packets, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_packets + + def _set_matched_packets(self, v, load=False): + """ + Setter method for matched_packets, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_packets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_packets() directly. + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_packets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_packets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_packets(self): + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + + def _get_matched_octets(self): + """ + Getter method for matched_octets, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_octets + + def _set_matched_octets(self, v, load=False): + """ + Setter method for matched_octets, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_octets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_octets() directly. + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_octets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_octets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_octets(self): + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + sequence_id = builtins.property(_get_sequence_id) + description = builtins.property(_get_description) + matched_packets = builtins.property(_get_matched_packets) + matched_octets = builtins.property(_get_matched_octets) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'description': description, 'matched_packets': matched_packets, 'matched_octets': matched_octets, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/l2/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__source_mac','__source_mac_mask','__destination_mac','__destination_mac_mask','__ethertype',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__source_mac = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + self.__destination_mac = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + self.__destination_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + self.__ethertype = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['1..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=True) + self.__source_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'l2', 'config'] + + def _get_source_mac(self): + """ + Getter method for source_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/source_mac (yang:mac-address) + + YANG Description: Source IEEE 802 MAC address. + """ + return self.__source_mac + + def _set_source_mac(self, v, load=False): + """ + Setter method for source_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/source_mac (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_mac is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_mac() directly. + + YANG Description: Source IEEE 802 MAC address. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_mac must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True)""", + }) + + self.__source_mac = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_mac(self): + self.__source_mac = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + + + def _get_source_mac_mask(self): + """ + Getter method for source_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/source_mac_mask (yang:mac-address) + + YANG Description: Source IEEE 802 MAC address mask. + """ + return self.__source_mac_mask + + def _set_source_mac_mask(self, v, load=False): + """ + Setter method for source_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/source_mac_mask (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_mac_mask is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_mac_mask() directly. + + YANG Description: Source IEEE 802 MAC address mask. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_mac_mask must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True)""", + }) + + self.__source_mac_mask = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_mac_mask(self): + self.__source_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + + + def _get_destination_mac(self): + """ + Getter method for destination_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/destination_mac (yang:mac-address) + + YANG Description: Destination IEEE 802 MAC address. + """ + return self.__destination_mac + + def _set_destination_mac(self, v, load=False): + """ + Setter method for destination_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/destination_mac (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_mac is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_mac() directly. + + YANG Description: Destination IEEE 802 MAC address. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_mac must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True)""", + }) + + self.__destination_mac = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_mac(self): + self.__destination_mac = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + + + def _get_destination_mac_mask(self): + """ + Getter method for destination_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/destination_mac_mask (yang:mac-address) + + YANG Description: Destination IEEE 802 MAC address mask. + """ + return self.__destination_mac_mask + + def _set_destination_mac_mask(self, v, load=False): + """ + Setter method for destination_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/destination_mac_mask (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_mac_mask is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_mac_mask() directly. + + YANG Description: Destination IEEE 802 MAC address mask. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_mac_mask must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True)""", + }) + + self.__destination_mac_mask = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_mac_mask(self): + self.__destination_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=True) + + + def _get_ethertype(self): + """ + Getter method for ethertype, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/ethertype (oc-pkt-match-types:ethertype-type) + + YANG Description: Ethertype field to match in Ethernet packets + """ + return self.__ethertype + + def _set_ethertype(self, v, load=False): + """ + Setter method for ethertype, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config/ethertype (oc-pkt-match-types:ethertype-type) + If this variable is read-only (config: false) in the + source YANG file, then _set_ethertype is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ethertype() directly. + + YANG Description: Ethertype field to match in Ethernet packets + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['1..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ethertype must be of a type compatible with oc-pkt-match-types:ethertype-type""", + 'defined-type': "oc-pkt-match-types:ethertype-type", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'1..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=True)""", + }) + + self.__ethertype = t + if hasattr(self, '_set'): + self._set() + + def _unset_ethertype(self): + self.__ethertype = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['1..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=True) + + source_mac = builtins.property(_get_source_mac, _set_source_mac) + source_mac_mask = builtins.property(_get_source_mac_mask, _set_source_mac_mask) + destination_mac = builtins.property(_get_destination_mac, _set_destination_mac) + destination_mac_mask = builtins.property(_get_destination_mac_mask, _set_destination_mac_mask) + ethertype = builtins.property(_get_ethertype, _set_ethertype) + + + _pyangbind_elements = {'source_mac': source_mac, 'source_mac_mask': source_mac_mask, 'destination_mac': destination_mac, 'destination_mac_mask': destination_mac_mask, 'ethertype': ethertype, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/l2/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: State Information. + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__source_mac','__source_mac_mask','__destination_mac','__destination_mac_mask','__ethertype',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__source_mac = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + self.__destination_mac = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + self.__destination_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + self.__ethertype = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['1..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=False) + self.__source_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'l2', 'state'] + + def _get_source_mac(self): + """ + Getter method for source_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/source_mac (yang:mac-address) + + YANG Description: Source IEEE 802 MAC address. + """ + return self.__source_mac + + def _set_source_mac(self, v, load=False): + """ + Setter method for source_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/source_mac (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_mac is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_mac() directly. + + YANG Description: Source IEEE 802 MAC address. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_mac must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False)""", + }) + + self.__source_mac = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_mac(self): + self.__source_mac = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + + + def _get_source_mac_mask(self): + """ + Getter method for source_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/source_mac_mask (yang:mac-address) + + YANG Description: Source IEEE 802 MAC address mask. + """ + return self.__source_mac_mask + + def _set_source_mac_mask(self, v, load=False): + """ + Setter method for source_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/source_mac_mask (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_mac_mask is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_mac_mask() directly. + + YANG Description: Source IEEE 802 MAC address mask. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_mac_mask must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False)""", + }) + + self.__source_mac_mask = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_mac_mask(self): + self.__source_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="source-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + + + def _get_destination_mac(self): + """ + Getter method for destination_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/destination_mac (yang:mac-address) + + YANG Description: Destination IEEE 802 MAC address. + """ + return self.__destination_mac + + def _set_destination_mac(self, v, load=False): + """ + Setter method for destination_mac, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/destination_mac (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_mac is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_mac() directly. + + YANG Description: Destination IEEE 802 MAC address. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_mac must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False)""", + }) + + self.__destination_mac = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_mac(self): + self.__destination_mac = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + + + def _get_destination_mac_mask(self): + """ + Getter method for destination_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/destination_mac_mask (yang:mac-address) + + YANG Description: Destination IEEE 802 MAC address mask. + """ + return self.__destination_mac_mask + + def _set_destination_mac_mask(self, v, load=False): + """ + Setter method for destination_mac_mask, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/destination_mac_mask (yang:mac-address) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_mac_mask is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_mac_mask() directly. + + YANG Description: Destination IEEE 802 MAC address mask. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_mac_mask must be of a type compatible with yang:mac-address""", + 'defined-type': "yang:mac-address", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False)""", + }) + + self.__destination_mac_mask = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_mac_mask(self): + self.__destination_mac_mask = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_dict={'pattern': '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'}), is_leaf=True, yang_name="destination-mac-mask", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:mac-address', is_config=False) + + + def _get_ethertype(self): + """ + Getter method for ethertype, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/ethertype (oc-pkt-match-types:ethertype-type) + + YANG Description: Ethertype field to match in Ethernet packets + """ + return self.__ethertype + + def _set_ethertype(self, v, load=False): + """ + Setter method for ethertype, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state/ethertype (oc-pkt-match-types:ethertype-type) + If this variable is read-only (config: false) in the + source YANG file, then _set_ethertype is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ethertype() directly. + + YANG Description: Ethertype field to match in Ethernet packets + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['1..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ethertype must be of a type compatible with oc-pkt-match-types:ethertype-type""", + 'defined-type': "oc-pkt-match-types:ethertype-type", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'1..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_ARP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_VLAN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_MPLS': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'ETHERTYPE_LLDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=False)""", + }) + + self.__ethertype = t + if hasattr(self, '_set'): + self._set() + + def _unset_ethertype(self): + self.__ethertype = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['1..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_ARP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_VLAN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_ROCE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV6': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_MPLS': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:ETHERTYPE_IPV4': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'ETHERTYPE_LLDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="ethertype", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ethertype-type', is_config=False) + + source_mac = builtins.property(_get_source_mac) + source_mac_mask = builtins.property(_get_source_mac_mask) + destination_mac = builtins.property(_get_destination_mac) + destination_mac_mask = builtins.property(_get_destination_mac_mask) + ethertype = builtins.property(_get_ethertype) + + + _pyangbind_elements = {'source_mac': source_mac, 'source_mac_mask': source_mac_mask, 'destination_mac': destination_mac, 'destination_mac_mask': destination_mac_mask, 'ethertype': ethertype, } + + +class yc_l2_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/l2. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Ethernet header fields + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'l2' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'l2'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config (container) + + YANG Description: Configuration data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state (container) + + YANG Description: State Information. + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: State Information. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/ip/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__ip_version','__source_ip_address','__source_ip_flow_label','__destination_ip_address','__destination_ip_flow_label','__dscp','__protocol','__hop_limit',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__hop_limit = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=True) + self.__protocol = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..254']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=True) + self.__dscp = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=True) + self.__source_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + self.__destination_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + self.__ip_version = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'unknown': {'value': 0}, 'ipv4': {'value': 1}, 'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=True) + self.__destination_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + self.__source_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'ip', 'config'] + + def _get_ip_version(self): + """ + Getter method for ip_version, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/ip_version (inet:ip-version) + + YANG Description: IP version of the header. + """ + return self.__ip_version + + def _set_ip_version(self, v, load=False): + """ + Setter method for ip_version, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/ip_version (inet:ip-version) + If this variable is read-only (config: false) in the + source YANG file, then _set_ip_version is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ip_version() directly. + + YANG Description: IP version of the header. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'unknown': {'value': 0}, 'ipv4': {'value': 1}, 'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ip_version must be of a type compatible with inet:ip-version""", + 'defined-type': "inet:ip-version", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'unknown': {'value': 0}, u'ipv4': {'value': 1}, u'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=True)""", + }) + + self.__ip_version = t + if hasattr(self, '_set'): + self._set() + + def _unset_ip_version(self): + self.__ip_version = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'unknown': {'value': 0}, 'ipv4': {'value': 1}, 'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=True) + + + def _get_source_ip_address(self): + """ + Getter method for source_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/source_ip_address (inet:ip-prefix) + + YANG Description: Destination IP address prefix. + """ + return self.__source_ip_address + + def _set_source_ip_address(self, v, load=False): + """ + Setter method for source_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/source_ip_address (inet:ip-prefix) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_ip_address is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_ip_address() directly. + + YANG Description: Destination IP address prefix. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_ip_address must be of a type compatible with inet:ip-prefix""", + 'defined-type': "inet:ip-prefix", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True)""", + }) + + self.__source_ip_address = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_ip_address(self): + self.__source_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + + + def _get_source_ip_flow_label(self): + """ + Getter method for source_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/source_ip_flow_label (inet:ipv6-flow-label) + + YANG Description: Source IPv6 Flow label. + """ + return self.__source_ip_flow_label + + def _set_source_ip_flow_label(self, v, load=False): + """ + Setter method for source_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/source_ip_flow_label (inet:ipv6-flow-label) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_ip_flow_label is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_ip_flow_label() directly. + + YANG Description: Source IPv6 Flow label. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_ip_flow_label must be of a type compatible with inet:ipv6-flow-label""", + 'defined-type': "inet:ipv6-flow-label", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True)""", + }) + + self.__source_ip_flow_label = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_ip_flow_label(self): + self.__source_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + + + def _get_destination_ip_address(self): + """ + Getter method for destination_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/destination_ip_address (inet:ip-prefix) + + YANG Description: Destination IP address prefix. + """ + return self.__destination_ip_address + + def _set_destination_ip_address(self, v, load=False): + """ + Setter method for destination_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/destination_ip_address (inet:ip-prefix) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_ip_address is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_ip_address() directly. + + YANG Description: Destination IP address prefix. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_ip_address must be of a type compatible with inet:ip-prefix""", + 'defined-type': "inet:ip-prefix", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True)""", + }) + + self.__destination_ip_address = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_ip_address(self): + self.__destination_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=True) + + + def _get_destination_ip_flow_label(self): + """ + Getter method for destination_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/destination_ip_flow_label (inet:ipv6-flow-label) + + YANG Description: Destination IPv6 Flow label. + """ + return self.__destination_ip_flow_label + + def _set_destination_ip_flow_label(self, v, load=False): + """ + Setter method for destination_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/destination_ip_flow_label (inet:ipv6-flow-label) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_ip_flow_label is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_ip_flow_label() directly. + + YANG Description: Destination IPv6 Flow label. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_ip_flow_label must be of a type compatible with inet:ipv6-flow-label""", + 'defined-type': "inet:ipv6-flow-label", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True)""", + }) + + self.__destination_ip_flow_label = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_ip_flow_label(self): + self.__destination_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=True) + + + def _get_dscp(self): + """ + Getter method for dscp, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/dscp (inet:dscp) + + YANG Description: Value of diffserv codepoint. + """ + return self.__dscp + + def _set_dscp(self, v, load=False): + """ + Setter method for dscp, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/dscp (inet:dscp) + If this variable is read-only (config: false) in the + source YANG file, then _set_dscp is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_dscp() directly. + + YANG Description: Value of diffserv codepoint. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """dscp must be of a type compatible with inet:dscp""", + 'defined-type': "inet:dscp", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=True)""", + }) + + self.__dscp = t + if hasattr(self, '_set'): + self._set() + + def _unset_dscp(self): + self.__dscp = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=True) + + + def _get_protocol(self): + """ + Getter method for protocol, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/protocol (oc-pkt-match-types:ip-protocol-type) + + YANG Description: Internet Protocol number. + """ + return self.__protocol + + def _set_protocol(self, v, load=False): + """ + Setter method for protocol, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/protocol (oc-pkt-match-types:ip-protocol-type) + If this variable is read-only (config: false) in the + source YANG file, then _set_protocol is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_protocol() directly. + + YANG Description: Internet Protocol number. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..254']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """protocol must be of a type compatible with oc-pkt-match-types:ip-protocol-type""", + 'defined-type': "oc-pkt-match-types:ip-protocol-type", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..254']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=True)""", + }) + + self.__protocol = t + if hasattr(self, '_set'): + self._set() + + def _unset_protocol(self): + self.__protocol = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..254']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=True) + + + def _get_hop_limit(self): + """ + Getter method for hop_limit, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/hop_limit (uint8) + + YANG Description: The IP packet's hop limit -- known as TTL (in hops) in +IPv4 packets, and hop limit in IPv6 + """ + return self.__hop_limit + + def _set_hop_limit(self, v, load=False): + """ + Setter method for hop_limit, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config/hop_limit (uint8) + If this variable is read-only (config: false) in the + source YANG file, then _set_hop_limit is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_hop_limit() directly. + + YANG Description: The IP packet's hop limit -- known as TTL (in hops) in +IPv4 packets, and hop limit in IPv6 + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """hop_limit must be of a type compatible with uint8""", + 'defined-type': "uint8", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=True)""", + }) + + self.__hop_limit = t + if hasattr(self, '_set'): + self._set() + + def _unset_hop_limit(self): + self.__hop_limit = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=True) + + ip_version = builtins.property(_get_ip_version, _set_ip_version) + source_ip_address = builtins.property(_get_source_ip_address, _set_source_ip_address) + source_ip_flow_label = builtins.property(_get_source_ip_flow_label, _set_source_ip_flow_label) + destination_ip_address = builtins.property(_get_destination_ip_address, _set_destination_ip_address) + destination_ip_flow_label = builtins.property(_get_destination_ip_flow_label, _set_destination_ip_flow_label) + dscp = builtins.property(_get_dscp, _set_dscp) + protocol = builtins.property(_get_protocol, _set_protocol) + hop_limit = builtins.property(_get_hop_limit, _set_hop_limit) + + + _pyangbind_elements = {'ip_version': ip_version, 'source_ip_address': source_ip_address, 'source_ip_flow_label': source_ip_flow_label, 'destination_ip_address': destination_ip_address, 'destination_ip_flow_label': destination_ip_flow_label, 'dscp': dscp, 'protocol': protocol, 'hop_limit': hop_limit, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/ip/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: State information + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__ip_version','__source_ip_address','__source_ip_flow_label','__destination_ip_address','__destination_ip_flow_label','__dscp','__protocol','__hop_limit',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__hop_limit = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=False) + self.__protocol = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..254']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=False) + self.__dscp = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=False) + self.__source_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + self.__destination_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + self.__ip_version = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'unknown': {'value': 0}, 'ipv4': {'value': 1}, 'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=False) + self.__destination_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + self.__source_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'ip', 'state'] + + def _get_ip_version(self): + """ + Getter method for ip_version, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/ip_version (inet:ip-version) + + YANG Description: IP version of the header. + """ + return self.__ip_version + + def _set_ip_version(self, v, load=False): + """ + Setter method for ip_version, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/ip_version (inet:ip-version) + If this variable is read-only (config: false) in the + source YANG file, then _set_ip_version is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ip_version() directly. + + YANG Description: IP version of the header. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'unknown': {'value': 0}, 'ipv4': {'value': 1}, 'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ip_version must be of a type compatible with inet:ip-version""", + 'defined-type': "inet:ip-version", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'unknown': {'value': 0}, u'ipv4': {'value': 1}, u'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=False)""", + }) + + self.__ip_version = t + if hasattr(self, '_set'): + self._set() + + def _unset_ip_version(self): + self.__ip_version = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'unknown': {'value': 0}, 'ipv4': {'value': 1}, 'ipv6': {'value': 2}},), is_leaf=True, yang_name="ip-version", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-version', is_config=False) + + + def _get_source_ip_address(self): + """ + Getter method for source_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/source_ip_address (inet:ip-prefix) + + YANG Description: Destination IP address prefix. + """ + return self.__source_ip_address + + def _set_source_ip_address(self, v, load=False): + """ + Setter method for source_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/source_ip_address (inet:ip-prefix) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_ip_address is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_ip_address() directly. + + YANG Description: Destination IP address prefix. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_ip_address must be of a type compatible with inet:ip-prefix""", + 'defined-type': "inet:ip-prefix", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False)""", + }) + + self.__source_ip_address = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_ip_address(self): + self.__source_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="source-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + + + def _get_source_ip_flow_label(self): + """ + Getter method for source_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/source_ip_flow_label (inet:ipv6-flow-label) + + YANG Description: Source IPv6 Flow label. + """ + return self.__source_ip_flow_label + + def _set_source_ip_flow_label(self, v, load=False): + """ + Setter method for source_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/source_ip_flow_label (inet:ipv6-flow-label) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_ip_flow_label is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_ip_flow_label() directly. + + YANG Description: Source IPv6 Flow label. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_ip_flow_label must be of a type compatible with inet:ipv6-flow-label""", + 'defined-type': "inet:ipv6-flow-label", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False)""", + }) + + self.__source_ip_flow_label = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_ip_flow_label(self): + self.__source_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="source-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + + + def _get_destination_ip_address(self): + """ + Getter method for destination_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/destination_ip_address (inet:ip-prefix) + + YANG Description: Destination IP address prefix. + """ + return self.__destination_ip_address + + def _set_destination_ip_address(self, v, load=False): + """ + Setter method for destination_ip_address, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/destination_ip_address (inet:ip-prefix) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_ip_address is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_ip_address() directly. + + YANG Description: Destination IP address prefix. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_ip_address must be of a type compatible with inet:ip-prefix""", + 'defined-type': "inet:ip-prefix", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False)""", + }) + + self.__destination_ip_address = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_ip_address(self): + self.__destination_ip_address = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))'}),RestrictedClassType(base_type=str, restriction_dict={'pattern': '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'}),], is_leaf=True, yang_name="destination-ip-address", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ip-prefix', is_config=False) + + + def _get_destination_ip_flow_label(self): + """ + Getter method for destination_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/destination_ip_flow_label (inet:ipv6-flow-label) + + YANG Description: Destination IPv6 Flow label. + """ + return self.__destination_ip_flow_label + + def _set_destination_ip_flow_label(self, v, load=False): + """ + Setter method for destination_ip_flow_label, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/destination_ip_flow_label (inet:ipv6-flow-label) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_ip_flow_label is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_ip_flow_label() directly. + + YANG Description: Destination IPv6 Flow label. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_ip_flow_label must be of a type compatible with inet:ipv6-flow-label""", + 'defined-type': "inet:ipv6-flow-label", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': [u'0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False)""", + }) + + self.__destination_ip_flow_label = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_ip_flow_label(self): + self.__destination_ip_flow_label = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..4294967295']}, int_size=32), restriction_dict={'range': ['0..1048575']}), is_leaf=True, yang_name="destination-ip-flow-label", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:ipv6-flow-label', is_config=False) + + + def _get_dscp(self): + """ + Getter method for dscp, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/dscp (inet:dscp) + + YANG Description: Value of diffserv codepoint. + """ + return self.__dscp + + def _set_dscp(self, v, load=False): + """ + Setter method for dscp, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/dscp (inet:dscp) + If this variable is read-only (config: false) in the + source YANG file, then _set_dscp is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_dscp() directly. + + YANG Description: Value of diffserv codepoint. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """dscp must be of a type compatible with inet:dscp""", + 'defined-type': "inet:dscp", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=False)""", + }) + + self.__dscp = t + if hasattr(self, '_set'): + self._set() + + def _unset_dscp(self): + self.__dscp = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..63']}), is_leaf=True, yang_name="dscp", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='inet:dscp', is_config=False) + + + def _get_protocol(self): + """ + Getter method for protocol, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/protocol (oc-pkt-match-types:ip-protocol-type) + + YANG Description: Internet Protocol number. + """ + return self.__protocol + + def _set_protocol(self, v, load=False): + """ + Setter method for protocol, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/protocol (oc-pkt-match-types:ip-protocol-type) + If this variable is read-only (config: false) in the + source YANG file, then _set_protocol is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_protocol() directly. + + YANG Description: Internet Protocol number. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..254']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """protocol must be of a type compatible with oc-pkt-match-types:ip-protocol-type""", + 'defined-type': "oc-pkt-match-types:ip-protocol-type", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..254']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'oc-pkt-match-types:IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_L2TP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_TCP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_AUTH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_GRE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_RSVP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_PIM': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_UDP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:IP_IGMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'IP_ICMP': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=False)""", + }) + + self.__protocol = t + if hasattr(self, '_set'): + self._set() + + def _unset_protocol(self): + self.__protocol = YANGDynClass(base=[RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..254']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'oc-pkt-match-types:IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_L2TP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_TCP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_AUTH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_GRE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_RSVP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_PIM': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_UDP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:IP_IGMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'IP_ICMP': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},),], is_leaf=True, yang_name="protocol", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:ip-protocol-type', is_config=False) + + + def _get_hop_limit(self): + """ + Getter method for hop_limit, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/hop_limit (uint8) + + YANG Description: The IP packet's hop limit -- known as TTL (in hops) in +IPv4 packets, and hop limit in IPv6 + """ + return self.__hop_limit + + def _set_hop_limit(self, v, load=False): + """ + Setter method for hop_limit, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state/hop_limit (uint8) + If this variable is read-only (config: false) in the + source YANG file, then _set_hop_limit is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_hop_limit() directly. + + YANG Description: The IP packet's hop limit -- known as TTL (in hops) in +IPv4 packets, and hop limit in IPv6 + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """hop_limit must be of a type compatible with uint8""", + 'defined-type': "uint8", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': [u'0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=False)""", + }) + + self.__hop_limit = t + if hasattr(self, '_set'): + self._set() + + def _unset_hop_limit(self): + self.__hop_limit = YANGDynClass(base=RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..255']}, int_size=8), restriction_dict={'range': ['0..255']}), is_leaf=True, yang_name="hop-limit", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='uint8', is_config=False) + + ip_version = builtins.property(_get_ip_version) + source_ip_address = builtins.property(_get_source_ip_address) + source_ip_flow_label = builtins.property(_get_source_ip_flow_label) + destination_ip_address = builtins.property(_get_destination_ip_address) + destination_ip_flow_label = builtins.property(_get_destination_ip_flow_label) + dscp = builtins.property(_get_dscp) + protocol = builtins.property(_get_protocol) + hop_limit = builtins.property(_get_hop_limit) + + + _pyangbind_elements = {'ip_version': ip_version, 'source_ip_address': source_ip_address, 'source_ip_flow_label': source_ip_flow_label, 'destination_ip_address': destination_ip_address, 'destination_ip_flow_label': destination_ip_flow_label, 'dscp': dscp, 'protocol': protocol, 'hop_limit': hop_limit, } + + +class yc_ip_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/ip. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Top level container + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'ip' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'ip'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config (container) + + YANG Description: Configuration data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state (container) + + YANG Description: State information + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: State information + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/transport/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__source_port','__destination_port','__tcp_flags',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__source_port = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + self.__tcp_flags = YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + self.__destination_port = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'transport', 'config'] + + def _get_source_port(self): + """ + Getter method for source_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/source_port (oc-pkt-match-types:port-num-range) + + YANG Description: Source port or range + """ + return self.__source_port + + def _set_source_port(self, v, load=False): + """ + Setter method for source_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/source_port (oc-pkt-match-types:port-num-range) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_port is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_port() directly. + + YANG Description: Source port or range + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_port must be of a type compatible with oc-pkt-match-types:port-num-range""", + 'defined-type': "oc-pkt-match-types:port-num-range", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True)""", + }) + + self.__source_port = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_port(self): + self.__source_port = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + + + def _get_destination_port(self): + """ + Getter method for destination_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/destination_port (oc-pkt-match-types:port-num-range) + + YANG Description: Destination port or range + """ + return self.__destination_port + + def _set_destination_port(self, v, load=False): + """ + Setter method for destination_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/destination_port (oc-pkt-match-types:port-num-range) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_port is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_port() directly. + + YANG Description: Destination port or range + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_port must be of a type compatible with oc-pkt-match-types:port-num-range""", + 'defined-type': "oc-pkt-match-types:port-num-range", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True)""", + }) + + self.__destination_port = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_port(self): + self.__destination_port = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=True) + + + def _get_tcp_flags(self): + """ + Getter method for tcp_flags, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/tcp_flags (identityref) + + YANG Description: List of TCP flags to match + """ + return self.__tcp_flags + + def _set_tcp_flags(self, v, load=False): + """ + Setter method for tcp_flags, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config/tcp_flags (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_tcp_flags is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_tcp_flags() directly. + + YANG Description: List of TCP flags to match + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=TypedListType(allowed_type=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """tcp_flags must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True)""", + }) + + self.__tcp_flags = t + if hasattr(self, '_set'): + self._set() + + def _unset_tcp_flags(self): + self.__tcp_flags = YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + + source_port = builtins.property(_get_source_port, _set_source_port) + destination_port = builtins.property(_get_destination_port, _set_destination_port) + tcp_flags = builtins.property(_get_tcp_flags, _set_tcp_flags) + + + _pyangbind_elements = {'source_port': source_port, 'destination_port': destination_port, 'tcp_flags': tcp_flags, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/transport/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: State data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__source_port','__destination_port','__tcp_flags',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__source_port = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + self.__tcp_flags = YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + self.__destination_port = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'transport', 'state'] + + def _get_source_port(self): + """ + Getter method for source_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/source_port (oc-pkt-match-types:port-num-range) + + YANG Description: Source port or range + """ + return self.__source_port + + def _set_source_port(self, v, load=False): + """ + Setter method for source_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/source_port (oc-pkt-match-types:port-num-range) + If this variable is read-only (config: false) in the + source YANG file, then _set_source_port is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_source_port() directly. + + YANG Description: Source port or range + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """source_port must be of a type compatible with oc-pkt-match-types:port-num-range""", + 'defined-type': "oc-pkt-match-types:port-num-range", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False)""", + }) + + self.__source_port = t + if hasattr(self, '_set'): + self._set() + + def _unset_source_port(self): + self.__source_port = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="source-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + + + def _get_destination_port(self): + """ + Getter method for destination_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/destination_port (oc-pkt-match-types:port-num-range) + + YANG Description: Destination port or range + """ + return self.__destination_port + + def _set_destination_port(self, v, load=False): + """ + Setter method for destination_port, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/destination_port (oc-pkt-match-types:port-num-range) + If this variable is read-only (config: false) in the + source YANG file, then _set_destination_port is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_destination_port() directly. + + YANG Description: Destination port or range + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """destination_port must be of a type compatible with oc-pkt-match-types:port-num-range""", + 'defined-type': "oc-pkt-match-types:port-num-range", + 'generated-type': """YANGDynClass(base=[RestrictedClassType(base_type=unicode, restriction_dict={'pattern': u'^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': [u'0..65535']}),RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False)""", + }) + + self.__destination_port = t + if hasattr(self, '_set'): + self._set() + + def _unset_destination_port(self): + self.__destination_port = YANGDynClass(base=[RestrictedClassType(base_type=str, restriction_dict={'pattern': '^(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)\\.\\.(6[0-5][0-5][0-3][0-5]|[0-5]?[0-9]?[0-9]?[0-9]?[0-9]?)$'}),RestrictedClassType(base_type=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..65535']},int_size=16), restriction_dict={'range': ['0..65535']}),RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'ANY': {}},),], is_leaf=True, yang_name="destination-port", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-pkt-match-types:port-num-range', is_config=False) + + + def _get_tcp_flags(self): + """ + Getter method for tcp_flags, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/tcp_flags (identityref) + + YANG Description: List of TCP flags to match + """ + return self.__tcp_flags + + def _set_tcp_flags(self, v, load=False): + """ + Setter method for tcp_flags, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state/tcp_flags (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_tcp_flags is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_tcp_flags() directly. + + YANG Description: List of TCP flags to match + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=TypedListType(allowed_type=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """tcp_flags must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ACK': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_SYN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_CWR': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_URG': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_RST': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_FIN': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_ECE': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}, u'oc-pkt-match-types:TCP_PSH': {'@namespace': u'http://openconfig.net/yang/packet-match-types', '@module': u'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False)""", + }) + + self.__tcp_flags = t + if hasattr(self, '_set'): + self._set() + + def _unset_tcp_flags(self): + self.__tcp_flags = YANGDynClass(base=TypedListType(allowed_type=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ACK': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_SYN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_CWR': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_URG': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_RST': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_FIN': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_ECE': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}, 'oc-pkt-match-types:TCP_PSH': {'@namespace': 'http://openconfig.net/yang/packet-match-types', '@module': 'openconfig-packet-match-types'}},)), is_leaf=False, yang_name="tcp-flags", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + source_port = builtins.property(_get_source_port) + destination_port = builtins.property(_get_destination_port) + tcp_flags = builtins.property(_get_tcp_flags) + + + _pyangbind_elements = {'source_port': source_port, 'destination_port': destination_port, 'tcp_flags': tcp_flags, } + + +class yc_transport_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/transport. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Transport fields container + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'transport' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'transport'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config (container) + + YANG Description: Configuration data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state (container) + + YANG Description: State data + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: State data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/input-interface/interface-ref/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configured reference to interface / subinterface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface','__subinterface',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__interface = YANGDynClass(base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__subinterface = YANGDynClass(base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'input-interface', 'interface-ref', 'config'] + + def _get_interface(self): + """ + Getter method for interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config/interface (leafref) + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + return self.__interface + + def _set_interface(self, v, load=False): + """ + Setter method for interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config/interface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface() directly. + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface(self): + self.__interface = YANGDynClass(base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_subinterface(self): + """ + Getter method for subinterface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config/subinterface (leafref) + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + return self.__subinterface + + def _set_subinterface(self, v, load=False): + """ + Setter method for subinterface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config/subinterface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_subinterface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_subinterface() directly. + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """subinterface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__subinterface = t + if hasattr(self, '_set'): + self._set() + + def _unset_subinterface(self): + self.__subinterface = YANGDynClass(base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + interface = builtins.property(_get_interface, _set_interface) + subinterface = builtins.property(_get_subinterface, _set_subinterface) + + + _pyangbind_elements = {'interface': interface, 'subinterface': subinterface, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/input-interface/interface-ref/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state for interface-ref + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface','__subinterface',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__interface = YANGDynClass(base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__subinterface = YANGDynClass(base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'input-interface', 'interface-ref', 'state'] + + def _get_interface(self): + """ + Getter method for interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state/interface (leafref) + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + return self.__interface + + def _set_interface(self, v, load=False): + """ + Setter method for interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state/interface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface() directly. + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface(self): + self.__interface = YANGDynClass(base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_subinterface(self): + """ + Getter method for subinterface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state/subinterface (leafref) + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + return self.__subinterface + + def _set_subinterface(self, v, load=False): + """ + Setter method for subinterface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state/subinterface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_subinterface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_subinterface() directly. + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """subinterface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__subinterface = t + if hasattr(self, '_set'): + self._set() + + def _unset_subinterface(self): + self.__subinterface = YANGDynClass(base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + interface = builtins.property(_get_interface) + subinterface = builtins.property(_get_subinterface) + + + _pyangbind_elements = {'interface': interface, 'subinterface': subinterface, } + + +class yc_interface_ref_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/input-interface/interface-ref. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Reference to an interface or subinterface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'interface-ref' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'input-interface', 'interface-ref'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config (container) + + YANG Description: Configured reference to interface / subinterface + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configured reference to interface / subinterface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state (container) + + YANG Description: Operational state for interface-ref + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state for interface-ref + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_input_interface_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/input-interface. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Input interface container + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface_ref',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'input-interface' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__interface_ref = YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'input-interface'] + + def _get_interface_ref(self): + """ + Getter method for interface_ref, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref (container) + + YANG Description: Reference to an interface or subinterface + """ + return self.__interface_ref + + def _set_interface_ref(self, v, load=False): + """ + Setter method for interface_ref, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface/interface_ref (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface_ref is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface_ref() directly. + + YANG Description: Reference to an interface or subinterface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_interface_ref_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface_ref must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__interface_ref = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface_ref(self): + self.__interface_ref = YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + interface_ref = builtins.property(_get_interface_ref, _set_interface_ref) + + + _pyangbind_elements = {'interface_ref': interface_ref, } + + +class yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/actions/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Config data for ACL actions + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__forwarding_action','__log_action',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__forwarding_action = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + self.__log_action = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), default=str("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'actions', 'config'] + + def _get_forwarding_action(self): + """ + Getter method for forwarding_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config/forwarding_action (identityref) + + YANG Description: Specifies the forwarding action. One forwarding action +must be specified for each ACL entry + """ + return self.__forwarding_action + + def _set_forwarding_action(self, v, load=False): + """ + Setter method for forwarding_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config/forwarding_action (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_forwarding_action is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_forwarding_action() directly. + + YANG Description: Specifies the forwarding action. One forwarding action +must be specified for each ACL entry + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """forwarding_action must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True)""", + }) + + self.__forwarding_action = t + if hasattr(self, '_set'): + self._set() + + def _unset_forwarding_action(self): + self.__forwarding_action = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + + + def _get_log_action(self): + """ + Getter method for log_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config/log_action (identityref) + + YANG Description: Specifies the log action and destination for +matched packets. The default is not to log the +packet. + """ + return self.__log_action + + def _set_log_action(self, v, load=False): + """ + Setter method for log_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config/log_action (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_log_action is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_log_action() directly. + + YANG Description: Specifies the log action and destination for +matched packets. The default is not to log the +packet. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), default=str("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """log_action must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), default=unicode("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True)""", + }) + + self.__log_action = t + if hasattr(self, '_set'): + self._set() + + def _unset_log_action(self): + self.__log_action = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), default=str("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=True) + + forwarding_action = builtins.property(_get_forwarding_action, _set_forwarding_action) + log_action = builtins.property(_get_log_action, _set_log_action) + + + _pyangbind_elements = {'forwarding_action': forwarding_action, 'log_action': log_action, } + + +class yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/actions/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: State information for ACL actions + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__forwarding_action','__log_action',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__forwarding_action = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + self.__log_action = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), default=str("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'actions', 'state'] + + def _get_forwarding_action(self): + """ + Getter method for forwarding_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state/forwarding_action (identityref) + + YANG Description: Specifies the forwarding action. One forwarding action +must be specified for each ACL entry + """ + return self.__forwarding_action + + def _set_forwarding_action(self, v, load=False): + """ + Setter method for forwarding_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state/forwarding_action (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_forwarding_action is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_forwarding_action() directly. + + YANG Description: Specifies the forwarding action. One forwarding action +must be specified for each ACL entry + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """forwarding_action must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'REJECT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:ACCEPT': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:DROP': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False)""", + }) + + self.__forwarding_action = t + if hasattr(self, '_set'): + self._set() + + def _unset_forwarding_action(self): + self.__forwarding_action = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'REJECT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:ACCEPT': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:DROP': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), is_leaf=True, yang_name="forwarding-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + + def _get_log_action(self): + """ + Getter method for log_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state/log_action (identityref) + + YANG Description: Specifies the log action and destination for +matched packets. The default is not to log the +packet. + """ + return self.__log_action + + def _set_log_action(self, v, load=False): + """ + Setter method for log_action, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state/log_action (identityref) + If this variable is read-only (config: false) in the + source YANG file, then _set_log_action is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_log_action() directly. + + YANG Description: Specifies the log action and destination for +matched packets. The default is not to log the +packet. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), default=str("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """log_action must be of a type compatible with identityref""", + 'defined-type': "openconfig-acl:identityref", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=unicode, restriction_type="dict_key", restriction_arg={u'LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_SYSLOG': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}, u'oc-acl:LOG_NONE': {'@namespace': u'http://openconfig.net/yang/acl', '@module': u'openconfig-acl'}},), default=unicode("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False)""", + }) + + self.__log_action = t + if hasattr(self, '_set'): + self._set() + + def _unset_log_action(self): + self.__log_action = YANGDynClass(base=RestrictedClassType(base_type=str, restriction_type="dict_key", restriction_arg={'LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_SYSLOG': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}, 'oc-acl:LOG_NONE': {'@namespace': 'http://openconfig.net/yang/acl', '@module': 'openconfig-acl'}},), default=str("LOG_NONE"), is_leaf=True, yang_name="log-action", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='identityref', is_config=False) + + forwarding_action = builtins.property(_get_forwarding_action) + log_action = builtins.property(_get_log_action) + + + _pyangbind_elements = {'forwarding_action': forwarding_action, 'log_action': log_action, } + + +class yc_actions_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry/actions. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container for list of ACL actions associated +with an entry + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'actions' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry', 'actions'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config (container) + + YANG Description: Config data for ACL actions + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Config data for ACL actions + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state (container) + + YANG Description: State information for ACL actions + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: State information for ACL actions + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_acl_entry_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries/acl-entry. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of ACL entries comprising an ACL set + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__config','__state','__l2','__ip','__transport','__input_interface','__actions',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'acl-entry' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__ip = YANGDynClass(base=yc_ip_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip, is_container='container', yang_name="ip", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__input_interface = YANGDynClass(base=yc_input_interface_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface, is_container='container', yang_name="input-interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__actions = YANGDynClass(base=yc_actions_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions, is_container='container', yang_name="actions", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__sequence_id = YANGDynClass(base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__l2 = YANGDynClass(base=yc_l2_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2, is_container='container', yang_name="l2", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__transport = YANGDynClass(base=yc_transport_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport, is_container='container', yang_name="transport", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries', 'acl-entry'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/sequence_id (leafref) + + YANG Description: references the list key + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/sequence_id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: references the list key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config (container) + + YANG Description: Access list entries config + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Access list entries config + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state (container) + + YANG Description: State information for ACL entries + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: State information for ACL entries + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_l2(self): + """ + Getter method for l2, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2 (container) + + YANG Description: Ethernet header fields + """ + return self.__l2 + + def _set_l2(self, v, load=False): + """ + Setter method for l2, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/l2 (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_l2 is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_l2() directly. + + YANG Description: Ethernet header fields + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_l2_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2, is_container='container', yang_name="l2", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """l2 must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_l2_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2, is_container='container', yang_name="l2", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__l2 = t + if hasattr(self, '_set'): + self._set() + + def _unset_l2(self): + self.__l2 = YANGDynClass(base=yc_l2_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_l2, is_container='container', yang_name="l2", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_ip(self): + """ + Getter method for ip, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip (container) + + YANG Description: Top level container + """ + return self.__ip + + def _set_ip(self, v, load=False): + """ + Setter method for ip, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/ip (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_ip is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ip() directly. + + YANG Description: Top level container + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_ip_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip, is_container='container', yang_name="ip", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ip must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_ip_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip, is_container='container', yang_name="ip", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__ip = t + if hasattr(self, '_set'): + self._set() + + def _unset_ip(self): + self.__ip = YANGDynClass(base=yc_ip_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_ip, is_container='container', yang_name="ip", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_transport(self): + """ + Getter method for transport, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport (container) + + YANG Description: Transport fields container + """ + return self.__transport + + def _set_transport(self, v, load=False): + """ + Setter method for transport, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/transport (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_transport is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_transport() directly. + + YANG Description: Transport fields container + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_transport_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport, is_container='container', yang_name="transport", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """transport must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_transport_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport, is_container='container', yang_name="transport", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__transport = t + if hasattr(self, '_set'): + self._set() + + def _unset_transport(self): + self.__transport = YANGDynClass(base=yc_transport_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_transport, is_container='container', yang_name="transport", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_input_interface(self): + """ + Getter method for input_interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface (container) + + YANG Description: Input interface container + """ + return self.__input_interface + + def _set_input_interface(self, v, load=False): + """ + Setter method for input_interface, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/input_interface (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_input_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_input_interface() directly. + + YANG Description: Input interface container + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_input_interface_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface, is_container='container', yang_name="input-interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """input_interface must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_input_interface_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface, is_container='container', yang_name="input-interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__input_interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_input_interface(self): + self.__input_interface = YANGDynClass(base=yc_input_interface_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_input_interface, is_container='container', yang_name="input-interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_actions(self): + """ + Getter method for actions, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions (container) + + YANG Description: Enclosing container for list of ACL actions associated +with an entry + """ + return self.__actions + + def _set_actions(self, v, load=False): + """ + Setter method for actions, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry/actions (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_actions is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_actions() directly. + + YANG Description: Enclosing container for list of ACL actions associated +with an entry + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_actions_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions, is_container='container', yang_name="actions", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """actions must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_actions_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions, is_container='container', yang_name="actions", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__actions = t + if hasattr(self, '_set'): + self._set() + + def _unset_actions(self): + self.__actions = YANGDynClass(base=yc_actions_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry_actions, is_container='container', yang_name="actions", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + sequence_id = builtins.property(_get_sequence_id, _set_sequence_id) + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + l2 = builtins.property(_get_l2, _set_l2) + ip = builtins.property(_get_ip, _set_ip) + transport = builtins.property(_get_transport, _set_transport) + input_interface = builtins.property(_get_input_interface, _set_input_interface) + actions = builtins.property(_get_actions, _set_actions) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'config': config, 'state': state, 'l2': l2, 'ip': ip, 'transport': transport, 'input_interface': input_interface, 'actions': actions, } + + +class yc_acl_entries_openconfig_acl__acl_acl_sets_acl_set_acl_entries(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set/acl-entries. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Access list entries container + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__acl_entry',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'acl-entries' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set', 'acl-entries'] + + def _get_acl_entry(self): + """ + Getter method for acl_entry, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry (list) + + YANG Description: List of ACL entries comprising an ACL set + """ + return self.__acl_entry + + def _set_acl_entry(self, v, load=False): + """ + Setter method for acl_entry, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries/acl_entry (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entry is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entry() directly. + + YANG Description: List of ACL entries comprising an ACL set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entry must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True)""", + }) + + self.__acl_entry = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entry(self): + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_acl_sets_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + acl_entry = builtins.property(_get_acl_entry, _set_acl_entry) + + + _pyangbind_elements = {'acl_entry': acl_entry, } + + +class yc_acl_set_openconfig_acl__acl_acl_sets_acl_set(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets/acl-set. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of ACL sets, each comprising of a list of ACL +entries + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__name','__config','__state','__acl_entries',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'acl-set' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__name = YANGDynClass(base=str, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_acl_sets_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets', 'acl-set'] + + def _get_name(self): + """ + Getter method for name, mapped from YANG variable /acl/acl_sets/acl_set/name (leafref) + + YANG Description: Reference to the name list key + """ + return self.__name + + def _set_name(self, v, load=False): + """ + Setter method for name, mapped from YANG variable /acl/acl_sets/acl_set/name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_name() directly. + + YANG Description: Reference to the name list key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__name = t + if hasattr(self, '_set'): + self._set() + + def _unset_name(self): + self.__name = YANGDynClass(base=str, is_leaf=True, yang_name="name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/acl_sets/acl_set/config (container) + + YANG Description: Access list config + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/acl_sets/acl_set/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Access list config + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_acl_sets_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_acl_sets_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/acl_sets/acl_set/state (container) + + YANG Description: Access list state information + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/acl_sets/acl_set/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Access list state information + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_acl_sets_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_acl_sets_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_acl_entries(self): + """ + Getter method for acl_entries, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries (container) + + YANG Description: Access list entries container + """ + return self.__acl_entries + + def _set_acl_entries(self, v, load=False): + """ + Setter method for acl_entries, mapped from YANG variable /acl/acl_sets/acl_set/acl_entries (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entries is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entries() directly. + + YANG Description: Access list entries container + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_acl_entries_openconfig_acl__acl_acl_sets_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entries must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_acl_sets_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__acl_entries = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entries(self): + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_acl_sets_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + name = builtins.property(_get_name, _set_name) + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + acl_entries = builtins.property(_get_acl_entries, _set_acl_entries) + + + _pyangbind_elements = {'name': name, 'config': config, 'state': state, 'acl_entries': acl_entries, } + + +class yc_acl_sets_openconfig_acl__acl_acl_sets(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/acl-sets. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Access list entries variables enclosing container + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__acl_set',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'acl-sets' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__acl_set = YANGDynClass(base=YANGListType("name",yc_acl_set_openconfig_acl__acl_acl_sets_acl_set, yang_name="acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='name', extensions=None), is_container='list', yang_name="acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'acl-sets'] + + def _get_acl_set(self): + """ + Getter method for acl_set, mapped from YANG variable /acl/acl_sets/acl_set (list) + + YANG Description: List of ACL sets, each comprising of a list of ACL +entries + """ + return self.__acl_set + + def _set_acl_set(self, v, load=False): + """ + Setter method for acl_set, mapped from YANG variable /acl/acl_sets/acl_set (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_set is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_set() directly. + + YANG Description: List of ACL sets, each comprising of a list of ACL +entries + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("name",yc_acl_set_openconfig_acl__acl_acl_sets_acl_set, yang_name="acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='name', extensions=None), is_container='list', yang_name="acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_set must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("name",yc_acl_set_openconfig_acl__acl_acl_sets_acl_set, yang_name="acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='name', extensions=None), is_container='list', yang_name="acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True)""", + }) + + self.__acl_set = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_set(self): + self.__acl_set = YANGDynClass(base=YANGListType("name",yc_acl_set_openconfig_acl__acl_acl_sets_acl_set, yang_name="acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='name', extensions=None), is_container='list', yang_name="acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + acl_set = builtins.property(_get_acl_set, _set_acl_set) + + + _pyangbind_elements = {'acl_set': acl_set, } + + +class yc_config_openconfig_acl__acl_interfaces_interface_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration for ACL per-interface data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__id',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__id = YANGDynClass(base=str, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'config'] + + def _get_id(self): + """ + Getter method for id, mapped from YANG variable /acl/interfaces/interface/config/id (oc-if:interface-id) + + YANG Description: User-defined identifier for the interface -- a common +convention could be '.' + """ + return self.__id + + def _set_id(self, v, load=False): + """ + Setter method for id, mapped from YANG variable /acl/interfaces/interface/config/id (oc-if:interface-id) + If this variable is read-only (config: false) in the + source YANG file, then _set_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_id() directly. + + YANG Description: User-defined identifier for the interface -- a common +convention could be '.' + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """id must be of a type compatible with oc-if:interface-id""", + 'defined-type': "oc-if:interface-id", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=True)""", + }) + + self.__id = t + if hasattr(self, '_set'): + self._set() + + def _unset_id(self): + self.__id = YANGDynClass(base=str, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=True) + + id = builtins.property(_get_id, _set_id) + + + _pyangbind_elements = {'id': id, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state for ACL per-interface data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__id',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__id = YANGDynClass(base=str, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'state'] + + def _get_id(self): + """ + Getter method for id, mapped from YANG variable /acl/interfaces/interface/state/id (oc-if:interface-id) + + YANG Description: User-defined identifier for the interface -- a common +convention could be '.' + """ + return self.__id + + def _set_id(self, v, load=False): + """ + Setter method for id, mapped from YANG variable /acl/interfaces/interface/state/id (oc-if:interface-id) + If this variable is read-only (config: false) in the + source YANG file, then _set_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_id() directly. + + YANG Description: User-defined identifier for the interface -- a common +convention could be '.' + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """id must be of a type compatible with oc-if:interface-id""", + 'defined-type': "oc-if:interface-id", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=False)""", + }) + + self.__id = t + if hasattr(self, '_set'): + self._set() + + def _unset_id(self): + self.__id = YANGDynClass(base=str, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='oc-if:interface-id', is_config=False) + + id = builtins.property(_get_id) + + + _pyangbind_elements = {'id': id, } + + +class yc_config_openconfig_acl__acl_interfaces_interface_interface_ref_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/interface-ref/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configured reference to interface / subinterface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface','__subinterface',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__interface = YANGDynClass(base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__subinterface = YANGDynClass(base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'interface-ref', 'config'] + + def _get_interface(self): + """ + Getter method for interface, mapped from YANG variable /acl/interfaces/interface/interface_ref/config/interface (leafref) + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + return self.__interface + + def _set_interface(self, v, load=False): + """ + Setter method for interface, mapped from YANG variable /acl/interfaces/interface/interface_ref/config/interface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface() directly. + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface(self): + self.__interface = YANGDynClass(base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_subinterface(self): + """ + Getter method for subinterface, mapped from YANG variable /acl/interfaces/interface/interface_ref/config/subinterface (leafref) + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + return self.__subinterface + + def _set_subinterface(self, v, load=False): + """ + Setter method for subinterface, mapped from YANG variable /acl/interfaces/interface/interface_ref/config/subinterface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_subinterface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_subinterface() directly. + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """subinterface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__subinterface = t + if hasattr(self, '_set'): + self._set() + + def _unset_subinterface(self): + self.__subinterface = YANGDynClass(base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + interface = builtins.property(_get_interface, _set_interface) + subinterface = builtins.property(_get_subinterface, _set_subinterface) + + + _pyangbind_elements = {'interface': interface, 'subinterface': subinterface, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_interface_ref_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/interface-ref/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state for interface-ref + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface','__subinterface',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__interface = YANGDynClass(base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__subinterface = YANGDynClass(base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'interface-ref', 'state'] + + def _get_interface(self): + """ + Getter method for interface, mapped from YANG variable /acl/interfaces/interface/interface_ref/state/interface (leafref) + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + return self.__interface + + def _set_interface(self, v, load=False): + """ + Setter method for interface, mapped from YANG variable /acl/interfaces/interface/interface_ref/state/interface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface() directly. + + YANG Description: Reference to a base interface. If a reference to a +subinterface is required, this leaf must be specified +to indicate the base interface. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface(self): + self.__interface = YANGDynClass(base=str, is_leaf=True, yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_subinterface(self): + """ + Getter method for subinterface, mapped from YANG variable /acl/interfaces/interface/interface_ref/state/subinterface (leafref) + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + return self.__subinterface + + def _set_subinterface(self, v, load=False): + """ + Setter method for subinterface, mapped from YANG variable /acl/interfaces/interface/interface_ref/state/subinterface (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_subinterface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_subinterface() directly. + + YANG Description: Reference to a subinterface -- this requires the base +interface to be specified using the interface leaf in +this container. If only a reference to a base interface +is requuired, this leaf should not be set. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """subinterface must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__subinterface = t + if hasattr(self, '_set'): + self._set() + + def _unset_subinterface(self): + self.__subinterface = YANGDynClass(base=str, is_leaf=True, yang_name="subinterface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + interface = builtins.property(_get_interface) + subinterface = builtins.property(_get_subinterface) + + + _pyangbind_elements = {'interface': interface, 'subinterface': subinterface, } + + +class yc_interface_ref_openconfig_acl__acl_interfaces_interface_interface_ref(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/interface-ref. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Reference to an interface or subinterface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__config','__state',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'interface-ref' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'interface-ref'] + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/interfaces/interface/interface_ref/config (container) + + YANG Description: Configured reference to interface / subinterface + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/interfaces/interface/interface_ref/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configured reference to interface / subinterface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_interfaces_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_interface_ref_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/interface_ref/state (container) + + YANG Description: Operational state for interface-ref + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/interface_ref/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state for interface-ref + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_interface_ref_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + + + _pyangbind_elements = {'config': config, 'state': state, } + + +class yc_config_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'ingress-acl-sets', 'ingress-acl-set', 'config'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/config/set_name (leafref) + + YANG Description: Reference to the ACL set applied on ingress + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/config/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to the ACL set applied on ingress + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + set_name = builtins.property(_get_set_name, _set_set_name) + + + _pyangbind_elements = {'set_name': set_name, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state data for interface ingress ACLs + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'ingress-acl-sets', 'ingress-acl-set', 'state'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/state/set_name (leafref) + + YANG Description: Reference to the ACL set applied on ingress + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/state/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to the ACL set applied on ingress + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + set_name = builtins.property(_get_set_name) + + + _pyangbind_elements = {'set_name': set_name, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set/acl-entries/acl-entry/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state data for per-interface ACL entries + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__matched_packets','__matched_octets',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__sequence_id = YANGDynClass(base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'ingress-acl-sets', 'ingress-acl-set', 'acl-entries', 'acl-entry', 'state'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/sequence_id (leafref) + + YANG Description: Reference to an entry in the ACL set applied to an +interface + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/sequence_id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: Reference to an entry in the ACL set applied to an +interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_matched_packets(self): + """ + Getter method for matched_packets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_packets + + def _set_matched_packets(self, v, load=False): + """ + Setter method for matched_packets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_packets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_packets() directly. + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_packets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_packets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_packets(self): + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + + def _get_matched_octets(self): + """ + Getter method for matched_octets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_octets + + def _set_matched_octets(self, v, load=False): + """ + Setter method for matched_octets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_octets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_octets() directly. + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_octets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_octets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_octets(self): + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + sequence_id = builtins.property(_get_sequence_id) + matched_packets = builtins.property(_get_matched_packets) + matched_octets = builtins.property(_get_matched_octets) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'matched_packets': matched_packets, 'matched_octets': matched_octets, } + + +class yc_acl_entry_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set/acl-entries/acl-entry. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of ACL entries assigned to an interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__state',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'acl-entry' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__sequence_id = YANGDynClass(base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'ingress-acl-sets', 'ingress-acl-set', 'acl-entries', 'acl-entry'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/sequence_id (leafref) + + YANG Description: Reference to per-interface acl entry key + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/sequence_id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: Reference to per-interface acl entry key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state (container) + + YANG Description: Operational state data for per-interface ACL entries + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state data for per-interface ACL entries + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + + sequence_id = builtins.property(_get_sequence_id) + state = builtins.property(_get_state) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'state': state, } + + +class yc_acl_entries_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set/acl-entries. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container for list of references to ACLs + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__acl_entry',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'acl-entries' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'ingress-acl-sets', 'ingress-acl-set', 'acl-entries'] + + def _get_acl_entry(self): + """ + Getter method for acl_entry, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry (list) + + YANG Description: List of ACL entries assigned to an interface + """ + return self.__acl_entry + + def _set_acl_entry(self, v, load=False): + """ + Setter method for acl_entry, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries/acl_entry (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entry is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entry() directly. + + YANG Description: List of ACL entries assigned to an interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entry must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False)""", + }) + + self.__acl_entry = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entry(self): + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + + acl_entry = builtins.property(_get_acl_entry) + + + _pyangbind_elements = {'acl_entry': acl_entry, } + + +class yc_ingress_acl_set_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets/ingress-acl-set. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of ingress ACLs on the interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name','__config','__state','__acl_entries',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'ingress-acl-set' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'ingress-acl-sets', 'ingress-acl-set'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/set_name (leafref) + + YANG Description: Reference to set name list key + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to set name list key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/config (container) + + YANG Description: Configuration data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/state (container) + + YANG Description: Operational state data for interface ingress ACLs + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state data for interface ingress ACLs + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_acl_entries(self): + """ + Getter method for acl_entries, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries (container) + + YANG Description: Enclosing container for list of references to ACLs + """ + return self.__acl_entries + + def _set_acl_entries(self, v, load=False): + """ + Setter method for acl_entries, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set/acl_entries (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entries is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entries() directly. + + YANG Description: Enclosing container for list of references to ACLs + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entries must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__acl_entries = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entries(self): + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + set_name = builtins.property(_get_set_name, _set_set_name) + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + acl_entries = builtins.property(_get_acl_entries, _set_acl_entries) + + + _pyangbind_elements = {'set_name': set_name, 'config': config, 'state': state, 'acl_entries': acl_entries, } + + +class yc_ingress_acl_sets_openconfig_acl__acl_interfaces_interface_ingress_acl_sets(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/ingress-acl-sets. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container the list of ingress ACLs on the +interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__ingress_acl_set',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'ingress-acl-sets' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__ingress_acl_set = YANGDynClass(base=YANGListType("set_name",yc_ingress_acl_set_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set, yang_name="ingress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="ingress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'ingress-acl-sets'] + + def _get_ingress_acl_set(self): + """ + Getter method for ingress_acl_set, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set (list) + + YANG Description: List of ingress ACLs on the interface + """ + return self.__ingress_acl_set + + def _set_ingress_acl_set(self, v, load=False): + """ + Setter method for ingress_acl_set, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets/ingress_acl_set (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_ingress_acl_set is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ingress_acl_set() directly. + + YANG Description: List of ingress ACLs on the interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("set_name",yc_ingress_acl_set_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set, yang_name="ingress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="ingress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ingress_acl_set must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("set_name",yc_ingress_acl_set_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set, yang_name="ingress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="ingress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True)""", + }) + + self.__ingress_acl_set = t + if hasattr(self, '_set'): + self._set() + + def _unset_ingress_acl_set(self): + self.__ingress_acl_set = YANGDynClass(base=YANGListType("set_name",yc_ingress_acl_set_openconfig_acl__acl_interfaces_interface_ingress_acl_sets_ingress_acl_set, yang_name="ingress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="ingress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + ingress_acl_set = builtins.property(_get_ingress_acl_set, _set_ingress_acl_set) + + + _pyangbind_elements = {'ingress_acl_set': ingress_acl_set, } + + +class yc_config_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_config(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set/config. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Configuration data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'config' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'egress-acl-sets', 'egress-acl-set', 'config'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/config/set_name (leafref) + + YANG Description: Reference to the ACL set applied on egress + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/config/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to the ACL set applied on egress + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + set_name = builtins.property(_get_set_name, _set_set_name) + + + _pyangbind_elements = {'set_name': set_name, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state data for interface egress ACLs + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'egress-acl-sets', 'egress-acl-set', 'state'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/state/set_name (leafref) + + YANG Description: Reference to the ACL set applied on egress + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/state/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to the ACL set applied on egress + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + set_name = builtins.property(_get_set_name) + + + _pyangbind_elements = {'set_name': set_name, } + + +class yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry_state(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set/acl-entries/acl-entry/state. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Operational state data for per-interface ACL entries + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__matched_packets','__matched_octets',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'state' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__sequence_id = YANGDynClass(base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'egress-acl-sets', 'egress-acl-set', 'acl-entries', 'acl-entry', 'state'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/sequence_id (leafref) + + YANG Description: Reference to an entry in the ACL set applied to an +interface + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/sequence_id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: Reference to an entry in the ACL set applied to an +interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_matched_packets(self): + """ + Getter method for matched_packets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_packets + + def _set_matched_packets(self, v, load=False): + """ + Setter method for matched_packets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/matched_packets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_packets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_packets() directly. + + YANG Description: Count of the number of packets matching the current ACL +entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_packets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_packets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_packets(self): + self.__matched_packets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-packets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + + def _get_matched_octets(self): + """ + Getter method for matched_octets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + return self.__matched_octets + + def _set_matched_octets(self, v, load=False): + """ + Setter method for matched_octets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state/matched_octets (yang:counter64) + If this variable is read-only (config: false) in the + source YANG file, then _set_matched_octets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_matched_octets() directly. + + YANG Description: Count of the number of octets (bytes) matching the current +ACL entry. + +An implementation should provide this counter on a +per-interface per-ACL-entry if possible. + +If an implementation only supports ACL counters per entry +(i.e., not broken out per interface), then the value +should be equal to the aggregate count across all interfaces. + +An implementation that provides counters per entry per +interface is not required to also provide an aggregate count, +e.g., per entry -- the user is expected to be able implement +the required aggregation if such a count is needed. + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """matched_octets must be of a type compatible with yang:counter64""", + 'defined-type': "yang:counter64", + 'generated-type': """YANGDynClass(base=RestrictedClassType(base_type=long, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False)""", + }) + + self.__matched_octets = t + if hasattr(self, '_set'): + self._set() + + def _unset_matched_octets(self): + self.__matched_octets = YANGDynClass(base=RestrictedClassType(base_type=int, restriction_dict={'range': ['0..18446744073709551615']}, int_size=64), is_leaf=True, yang_name="matched-octets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='yang:counter64', is_config=False) + + sequence_id = builtins.property(_get_sequence_id) + matched_packets = builtins.property(_get_matched_packets) + matched_octets = builtins.property(_get_matched_octets) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'matched_packets': matched_packets, 'matched_octets': matched_octets, } + + +class yc_acl_entry_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set/acl-entries/acl-entry. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of ACL entries assigned to an interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__sequence_id','__state',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'acl-entry' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__sequence_id = YANGDynClass(base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'egress-acl-sets', 'egress-acl-set', 'acl-entries', 'acl-entry'] + + def _get_sequence_id(self): + """ + Getter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/sequence_id (leafref) + + YANG Description: Reference to per-interface acl entry key + """ + return self.__sequence_id + + def _set_sequence_id(self, v, load=False): + """ + Setter method for sequence_id, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/sequence_id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_sequence_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_sequence_id() directly. + + YANG Description: Reference to per-interface acl entry key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """sequence_id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False)""", + }) + + self.__sequence_id = t + if hasattr(self, '_set'): + self._set() + + def _unset_sequence_id(self): + self.__sequence_id = YANGDynClass(base=str, is_leaf=True, yang_name="sequence-id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=False) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state (container) + + YANG Description: Operational state data for per-interface ACL entries + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state data for per-interface ACL entries + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=False) + + sequence_id = builtins.property(_get_sequence_id) + state = builtins.property(_get_state) + + + _pyangbind_elements = {'sequence_id': sequence_id, 'state': state, } + + +class yc_acl_entries_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set/acl-entries. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container for list of references to ACLs + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__acl_entry',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'acl-entries' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'egress-acl-sets', 'egress-acl-set', 'acl-entries'] + + def _get_acl_entry(self): + """ + Getter method for acl_entry, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry (list) + + YANG Description: List of ACL entries assigned to an interface + """ + return self.__acl_entry + + def _set_acl_entry(self, v, load=False): + """ + Setter method for acl_entry, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries/acl_entry (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entry is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entry() directly. + + YANG Description: List of ACL entries assigned to an interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entry must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False)""", + }) + + self.__acl_entry = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entry(self): + self.__acl_entry = YANGDynClass(base=YANGListType("sequence_id",yc_acl_entry_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries_acl_entry, yang_name="acl-entry", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='sequence-id', extensions=None), is_container='list', yang_name="acl-entry", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=False) + + acl_entry = builtins.property(_get_acl_entry) + + + _pyangbind_elements = {'acl_entry': acl_entry, } + + +class yc_egress_acl_set_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets/egress-acl-set. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of egress ACLs on the interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__set_name','__config','__state','__acl_entries',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'egress-acl-set' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'egress-acl-sets', 'egress-acl-set'] + + def _get_set_name(self): + """ + Getter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/set_name (leafref) + + YANG Description: Reference to set name list key + """ + return self.__set_name + + def _set_set_name(self, v, load=False): + """ + Setter method for set_name, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/set_name (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_set_name is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_set_name() directly. + + YANG Description: Reference to set name list key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """set_name must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__set_name = t + if hasattr(self, '_set'): + self._set() + + def _unset_set_name(self): + self.__set_name = YANGDynClass(base=str, is_leaf=True, yang_name="set-name", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/config (container) + + YANG Description: Configuration data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/state (container) + + YANG Description: Operational state data for interface egress ACLs + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state data for interface egress ACLs + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_acl_entries(self): + """ + Getter method for acl_entries, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries (container) + + YANG Description: Enclosing container for list of references to ACLs + """ + return self.__acl_entries + + def _set_acl_entries(self, v, load=False): + """ + Setter method for acl_entries, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set/acl_entries (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_entries is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_entries() directly. + + YANG Description: Enclosing container for list of references to ACLs + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_entries must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__acl_entries = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_entries(self): + self.__acl_entries = YANGDynClass(base=yc_acl_entries_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set_acl_entries, is_container='container', yang_name="acl-entries", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + set_name = builtins.property(_get_set_name, _set_set_name) + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + acl_entries = builtins.property(_get_acl_entries, _set_acl_entries) + + + _pyangbind_elements = {'set_name': set_name, 'config': config, 'state': state, 'acl_entries': acl_entries, } + + +class yc_egress_acl_sets_openconfig_acl__acl_interfaces_interface_egress_acl_sets(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface/egress-acl-sets. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container the list of egress ACLs on the +interface + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__egress_acl_set',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'egress-acl-sets' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__egress_acl_set = YANGDynClass(base=YANGListType("set_name",yc_egress_acl_set_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set, yang_name="egress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="egress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface', 'egress-acl-sets'] + + def _get_egress_acl_set(self): + """ + Getter method for egress_acl_set, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set (list) + + YANG Description: List of egress ACLs on the interface + """ + return self.__egress_acl_set + + def _set_egress_acl_set(self, v, load=False): + """ + Setter method for egress_acl_set, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets/egress_acl_set (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_egress_acl_set is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_egress_acl_set() directly. + + YANG Description: List of egress ACLs on the interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("set_name",yc_egress_acl_set_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set, yang_name="egress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="egress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """egress_acl_set must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("set_name",yc_egress_acl_set_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set, yang_name="egress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="egress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True)""", + }) + + self.__egress_acl_set = t + if hasattr(self, '_set'): + self._set() + + def _unset_egress_acl_set(self): + self.__egress_acl_set = YANGDynClass(base=YANGListType("set_name",yc_egress_acl_set_openconfig_acl__acl_interfaces_interface_egress_acl_sets_egress_acl_set, yang_name="egress-acl-set", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='set-name', extensions=None), is_container='list', yang_name="egress-acl-set", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + egress_acl_set = builtins.property(_get_egress_acl_set, _set_egress_acl_set) + + + _pyangbind_elements = {'egress_acl_set': egress_acl_set, } + + +class yc_interface_openconfig_acl__acl_interfaces_interface(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces/interface. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: List of interfaces on which ACLs are set + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__id','__config','__state','__interface_ref','__ingress_acl_sets','__egress_acl_sets',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'interface' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__ingress_acl_sets = YANGDynClass(base=yc_ingress_acl_sets_openconfig_acl__acl_interfaces_interface_ingress_acl_sets, is_container='container', yang_name="ingress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__egress_acl_sets = YANGDynClass(base=yc_egress_acl_sets_openconfig_acl__acl_interfaces_interface_egress_acl_sets, is_container='container', yang_name="egress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__id = YANGDynClass(base=str, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + self.__interface_ref = YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_interfaces_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces', 'interface'] + + def _get_id(self): + """ + Getter method for id, mapped from YANG variable /acl/interfaces/interface/id (leafref) + + YANG Description: Reference to the interface id list key + """ + return self.__id + + def _set_id(self, v, load=False): + """ + Setter method for id, mapped from YANG variable /acl/interfaces/interface/id (leafref) + If this variable is read-only (config: false) in the + source YANG file, then _set_id is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_id() directly. + + YANG Description: Reference to the interface id list key + """ + parent = getattr(self, "_parent", None) + if parent is not None and load is False: + raise AttributeError("Cannot set keys directly when" + + " within an instantiated list") + + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=str, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """id must be of a type compatible with leafref""", + 'defined-type': "leafref", + 'generated-type': """YANGDynClass(base=unicode, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True)""", + }) + + self.__id = t + if hasattr(self, '_set'): + self._set() + + def _unset_id(self): + self.__id = YANGDynClass(base=str, is_leaf=True, yang_name="id", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, is_keyval=True, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='leafref', is_config=True) + + + def _get_config(self): + """ + Getter method for config, mapped from YANG variable /acl/interfaces/interface/config (container) + + YANG Description: Configuration for ACL per-interface data + """ + return self.__config + + def _set_config(self, v, load=False): + """ + Setter method for config, mapped from YANG variable /acl/interfaces/interface/config (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_config is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_config() directly. + + YANG Description: Configuration for ACL per-interface data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_config_openconfig_acl__acl_interfaces_interface_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """config must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__config = t + if hasattr(self, '_set'): + self._set() + + def _unset_config(self): + self.__config = YANGDynClass(base=yc_config_openconfig_acl__acl_interfaces_interface_config, is_container='container', yang_name="config", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/interfaces/interface/state (container) + + YANG Description: Operational state for ACL per-interface data + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/interfaces/interface/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Operational state for ACL per-interface data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_interfaces_interface_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_interfaces_interface_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_interface_ref(self): + """ + Getter method for interface_ref, mapped from YANG variable /acl/interfaces/interface/interface_ref (container) + + YANG Description: Reference to an interface or subinterface + """ + return self.__interface_ref + + def _set_interface_ref(self, v, load=False): + """ + Setter method for interface_ref, mapped from YANG variable /acl/interfaces/interface/interface_ref (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface_ref is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface_ref() directly. + + YANG Description: Reference to an interface or subinterface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_interface_ref_openconfig_acl__acl_interfaces_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface_ref must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_interfaces_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__interface_ref = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface_ref(self): + self.__interface_ref = YANGDynClass(base=yc_interface_ref_openconfig_acl__acl_interfaces_interface_interface_ref, is_container='container', yang_name="interface-ref", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_ingress_acl_sets(self): + """ + Getter method for ingress_acl_sets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets (container) + + YANG Description: Enclosing container the list of ingress ACLs on the +interface + """ + return self.__ingress_acl_sets + + def _set_ingress_acl_sets(self, v, load=False): + """ + Setter method for ingress_acl_sets, mapped from YANG variable /acl/interfaces/interface/ingress_acl_sets (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_ingress_acl_sets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_ingress_acl_sets() directly. + + YANG Description: Enclosing container the list of ingress ACLs on the +interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_ingress_acl_sets_openconfig_acl__acl_interfaces_interface_ingress_acl_sets, is_container='container', yang_name="ingress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """ingress_acl_sets must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_ingress_acl_sets_openconfig_acl__acl_interfaces_interface_ingress_acl_sets, is_container='container', yang_name="ingress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__ingress_acl_sets = t + if hasattr(self, '_set'): + self._set() + + def _unset_ingress_acl_sets(self): + self.__ingress_acl_sets = YANGDynClass(base=yc_ingress_acl_sets_openconfig_acl__acl_interfaces_interface_ingress_acl_sets, is_container='container', yang_name="ingress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_egress_acl_sets(self): + """ + Getter method for egress_acl_sets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets (container) + + YANG Description: Enclosing container the list of egress ACLs on the +interface + """ + return self.__egress_acl_sets + + def _set_egress_acl_sets(self, v, load=False): + """ + Setter method for egress_acl_sets, mapped from YANG variable /acl/interfaces/interface/egress_acl_sets (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_egress_acl_sets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_egress_acl_sets() directly. + + YANG Description: Enclosing container the list of egress ACLs on the +interface + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_egress_acl_sets_openconfig_acl__acl_interfaces_interface_egress_acl_sets, is_container='container', yang_name="egress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """egress_acl_sets must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_egress_acl_sets_openconfig_acl__acl_interfaces_interface_egress_acl_sets, is_container='container', yang_name="egress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__egress_acl_sets = t + if hasattr(self, '_set'): + self._set() + + def _unset_egress_acl_sets(self): + self.__egress_acl_sets = YANGDynClass(base=yc_egress_acl_sets_openconfig_acl__acl_interfaces_interface_egress_acl_sets, is_container='container', yang_name="egress-acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + id = builtins.property(_get_id, _set_id) + config = builtins.property(_get_config, _set_config) + state = builtins.property(_get_state, _set_state) + interface_ref = builtins.property(_get_interface_ref, _set_interface_ref) + ingress_acl_sets = builtins.property(_get_ingress_acl_sets, _set_ingress_acl_sets) + egress_acl_sets = builtins.property(_get_egress_acl_sets, _set_egress_acl_sets) + + + _pyangbind_elements = {'id': id, 'config': config, 'state': state, 'interface_ref': interface_ref, 'ingress_acl_sets': ingress_acl_sets, 'egress_acl_sets': egress_acl_sets, } + + +class yc_interfaces_openconfig_acl__acl_interfaces(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl/interfaces. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Enclosing container for the list of interfaces on which +ACLs are set + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__interface',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'interfaces' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__interface = YANGDynClass(base=YANGListType("id",yc_interface_openconfig_acl__acl_interfaces_interface, yang_name="interface", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='id', extensions=None), is_container='list', yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl', 'interfaces'] + + def _get_interface(self): + """ + Getter method for interface, mapped from YANG variable /acl/interfaces/interface (list) + + YANG Description: List of interfaces on which ACLs are set + """ + return self.__interface + + def _set_interface(self, v, load=False): + """ + Setter method for interface, mapped from YANG variable /acl/interfaces/interface (list) + If this variable is read-only (config: false) in the + source YANG file, then _set_interface is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interface() directly. + + YANG Description: List of interfaces on which ACLs are set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=YANGListType("id",yc_interface_openconfig_acl__acl_interfaces_interface, yang_name="interface", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='id', extensions=None), is_container='list', yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interface must be of a type compatible with list""", + 'defined-type': "list", + 'generated-type': """YANGDynClass(base=YANGListType("id",yc_interface_openconfig_acl__acl_interfaces_interface, yang_name="interface", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='id', extensions=None), is_container='list', yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True)""", + }) + + self.__interface = t + if hasattr(self, '_set'): + self._set() + + def _unset_interface(self): + self.__interface = YANGDynClass(base=YANGListType("id",yc_interface_openconfig_acl__acl_interfaces_interface, yang_name="interface", parent=self, is_container='list', user_ordered=False, path_helper=self._path_helper, yang_keys='id', extensions=None), is_container='list', yang_name="interface", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='list', is_config=True) + + interface = builtins.property(_get_interface, _set_interface) + + + _pyangbind_elements = {'interface': interface, } + + +class yc_acl_openconfig_acl__acl(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /acl. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: Top level enclosing container for ACL model config +and operational state data + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__state','__acl_sets','__interfaces',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'acl' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__acl_sets = YANGDynClass(base=yc_acl_sets_openconfig_acl__acl_acl_sets, is_container='container', yang_name="acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + self.__interfaces = YANGDynClass(base=yc_interfaces_openconfig_acl__acl_interfaces, is_container='container', yang_name="interfaces", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return ['acl'] + + def _get_state(self): + """ + Getter method for state, mapped from YANG variable /acl/state (container) + + YANG Description: Global operational state data for ACLs + """ + return self.__state + + def _set_state(self, v, load=False): + """ + Setter method for state, mapped from YANG variable /acl/state (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_state is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_state() directly. + + YANG Description: Global operational state data for ACLs + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_state_openconfig_acl__acl_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """state must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_state_openconfig_acl__acl_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__state = t + if hasattr(self, '_set'): + self._set() + + def _unset_state(self): + self.__state = YANGDynClass(base=yc_state_openconfig_acl__acl_state, is_container='container', yang_name="state", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_acl_sets(self): + """ + Getter method for acl_sets, mapped from YANG variable /acl/acl_sets (container) + + YANG Description: Access list entries variables enclosing container + """ + return self.__acl_sets + + def _set_acl_sets(self, v, load=False): + """ + Setter method for acl_sets, mapped from YANG variable /acl/acl_sets (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl_sets is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl_sets() directly. + + YANG Description: Access list entries variables enclosing container + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_acl_sets_openconfig_acl__acl_acl_sets, is_container='container', yang_name="acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl_sets must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_acl_sets_openconfig_acl__acl_acl_sets, is_container='container', yang_name="acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__acl_sets = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl_sets(self): + self.__acl_sets = YANGDynClass(base=yc_acl_sets_openconfig_acl__acl_acl_sets, is_container='container', yang_name="acl-sets", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + + def _get_interfaces(self): + """ + Getter method for interfaces, mapped from YANG variable /acl/interfaces (container) + + YANG Description: Enclosing container for the list of interfaces on which +ACLs are set + """ + return self.__interfaces + + def _set_interfaces(self, v, load=False): + """ + Setter method for interfaces, mapped from YANG variable /acl/interfaces (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_interfaces is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_interfaces() directly. + + YANG Description: Enclosing container for the list of interfaces on which +ACLs are set + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_interfaces_openconfig_acl__acl_interfaces, is_container='container', yang_name="interfaces", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """interfaces must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_interfaces_openconfig_acl__acl_interfaces, is_container='container', yang_name="interfaces", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__interfaces = t + if hasattr(self, '_set'): + self._set() + + def _unset_interfaces(self): + self.__interfaces = YANGDynClass(base=yc_interfaces_openconfig_acl__acl_interfaces, is_container='container', yang_name="interfaces", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + state = builtins.property(_get_state, _set_state) + acl_sets = builtins.property(_get_acl_sets, _set_acl_sets) + interfaces = builtins.property(_get_interfaces, _set_interfaces) + + + _pyangbind_elements = {'state': state, 'acl_sets': acl_sets, 'interfaces': interfaces, } + + +class openconfig_acl(PybindBase): + """ + This class was auto-generated by the PythonClass plugin for PYANG + from YANG module openconfig-acl - based on the path /openconfig-acl. Each member element of + the container is represented as a class variable - with a specific + YANG type. + + YANG Description: This module defines configuration and operational state +data for network access control lists (i.e., filters, rules, +etc.). ACLs are organized into ACL sets, with each set +containing one or more ACL entries. ACL sets are identified +by a unique name, while each entry within a set is assigned +a sequence-id that determines the order in which the ACL +rules are applied to a packet. + +The model allows individual ACL rules to combine match criteria +from various fields in the packet, along with an action that +defines how matching packets should be handled. Note that some +device implementations may require separate entries for match +criteria that cross protocol layers, e.g., MAC layer and IP +layer matches. + """ + __slots__ = ('_pybind_generated_by', '_path_helper', '_yang_name', '_extmethods', '__acl',) + + def __init__(self, *args, **kwargs): + self._yang_name = 'openconfig-acl' + self._pybind_generated_by = 'container' + self._path_helper = False + self._extmethods = False + self.__acl = YANGDynClass(base=yc_acl_openconfig_acl__acl, is_container='container', yang_name="acl", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + load = kwargs.pop("load", None) + if args: + if len(args) > 1: + raise TypeError("cannot create a YANG container with >1 argument") + all_attr = True + for e in self._pyangbind_elements: + if not hasattr(args[0], e): + all_attr = False + break + if not all_attr: + raise ValueError("Supplied object did not have the correct attributes") + for e in self._pyangbind_elements: + nobj = getattr(args[0], e) + if nobj._changed() is False: + continue + setmethod = getattr(self, "_set_%s" % e) + if load is None: + setmethod(getattr(args[0], e)) + else: + setmethod(getattr(args[0], e), load=load) + + def _path(self): + if hasattr(self, "_parent"): + return self._parent._path()+[self._yang_name] + else: + return [] + + def _get_acl(self): + """ + Getter method for acl, mapped from YANG variable /acl (container) + + YANG Description: Top level enclosing container for ACL model config +and operational state data + """ + return self.__acl + + def _set_acl(self, v, load=False): + """ + Setter method for acl, mapped from YANG variable /acl (container) + If this variable is read-only (config: false) in the + source YANG file, then _set_acl is considered as a private + method. Backends looking to populate this variable should + do so via calling thisObj._set_acl() directly. + + YANG Description: Top level enclosing container for ACL model config +and operational state data + """ + if hasattr(v, "_utype"): + v = v._utype(v) + try: + t = YANGDynClass(v,base=yc_acl_openconfig_acl__acl, is_container='container', yang_name="acl", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + except (TypeError, ValueError): + raise ValueError({ + 'error-string': """acl must be of a type compatible with container""", + 'defined-type': "container", + 'generated-type': """YANGDynClass(base=yc_acl_openconfig_acl__acl, is_container='container', yang_name="acl", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True)""", + }) + + self.__acl = t + if hasattr(self, '_set'): + self._set() + + def _unset_acl(self): + self.__acl = YANGDynClass(base=yc_acl_openconfig_acl__acl, is_container='container', yang_name="acl", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/acl', defining_module='openconfig-acl', yang_type='container', is_config=True) + + acl = builtins.property(_get_acl, _set_acl) + + + _pyangbind_elements = {'acl': acl, } diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py new file mode 100644 index 000000000000..011642b2b812 --- /dev/null +++ b/src/sonic-config-engine/portconfig.py @@ -0,0 +1,296 @@ +try: + import ast + import json + import os + import re + import sys + + from swsscommon.swsscommon import ConfigDBConnector + from sonic_py_common import device_info +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +# Global Variable +PLATFORM_ROOT_PATH = '/usr/share/sonic/device' +PLATFORM_ROOT_PATH_DOCKER = '/usr/share/sonic/platform' +SONIC_ROOT_PATH = '/usr/share/sonic' +HWSKU_ROOT_PATH = '/usr/share/sonic/hwsku' + +PLATFORM_JSON = 'platform.json' +PORT_CONFIG_INI = 'port_config.ini' +HWSKU_JSON = 'hwsku.json' + +PORT_STR = "Ethernet" +BRKOUT_MODE = "default_brkout_mode" +CUR_BRKOUT_MODE = "brkout_mode" +INTF_KEY = "interfaces" +OPTIONAL_HWSKU_ATTRIBUTES = ["fec", "autoneg"] + +BRKOUT_PATTERN = r'(\d{1,3})x(\d{1,3}G)(\[(\d{1,3}G,?)*\])?(\((\d{1,3})\))?' + +# +# Helper Functions +# +def readJson(filename): + # Read 'platform.json' or 'hwsku.json' file + try: + with open(filename) as fp: + try: + data = json.load(fp) + except json.JSONDecodeError: + print("Json file does not exist") + data_dict = ast.literal_eval(json.dumps(data)) + return data_dict + except Exception as e: + print("error occurred while parsing json: {}".format(sys.exc_info()[1])) + return None + +def db_connect_configdb(): + """ + Connect to configdb + """ + config_db = ConfigDBConnector() + if config_db is None: + return None + try: + """ + This could be blocking during the config load_minigraph phase, + as the CONFIG_DB_INITIALIZED is not yet set in the configDB. + We can ignore the check by using config_db.db_connect('CONFIG_DB') instead + """ + # Connect only if available & initialized + config_db.connect(wait_for_init=False) + except Exception as e: + config_db = None + return config_db + +def get_hwsku_file_name(hwsku=None, platform=None): + hwsku_candidates_Json = [] + hwsku_candidates_Json.append(os.path.join(HWSKU_ROOT_PATH, HWSKU_JSON)) + if hwsku: + if platform: + hwsku_candidates_Json.append(os.path.join(PLATFORM_ROOT_PATH, platform, hwsku, HWSKU_JSON)) + hwsku_candidates_Json.append(os.path.join(PLATFORM_ROOT_PATH_DOCKER, hwsku, HWSKU_JSON)) + hwsku_candidates_Json.append(os.path.join(SONIC_ROOT_PATH, hwsku, HWSKU_JSON)) + for candidate in hwsku_candidates_Json: + if os.path.isfile(candidate): + return candidate + return None + +def get_port_config(hwsku=None, platform=None, port_config_file=None, hwsku_config_file=None, asic=None): + config_db = db_connect_configdb() + # If available, Read from CONFIG DB first + if config_db is not None and port_config_file is None: + + port_data = config_db.get_table("PORT") + if bool(port_data): + ports = ast.literal_eval(json.dumps(port_data)) + port_alias_map = {} + port_alias_asic_map = {} + for intf_name in ports.keys(): + port_alias_map[ports[intf_name]["alias"]] = intf_name + return (ports, port_alias_map, port_alias_asic_map) + + if not port_config_file: + port_config_file = device_info.get_path_to_port_config_file(hwsku, asic) + if not port_config_file: + return ({}, {}, {}) + + + # Read from 'platform.json' file + if port_config_file.endswith('.json'): + if not hwsku_config_file: + hwsku_json_file = get_hwsku_file_name(hwsku, platform) + if not hwsku_json_file: + return ({}, {}, {}) + else: + hwsku_json_file = hwsku_config_file + + return parse_platform_json_file(hwsku_json_file, port_config_file) + + # If 'platform.json' file is not available, read from 'port_config.ini' + else: + return parse_port_config_file(port_config_file) + +def parse_port_config_file(port_config_file): + ports = {} + port_alias_map = {} + port_alias_asic_map = {} + # Default column definition + titles = ['name', 'lanes', 'alias', 'index'] + with open(port_config_file) as data: + for line in data: + if line.startswith('#'): + if "name" in line: + titles = line.strip('#').split() + continue; + tokens = line.split() + if len(tokens) < 2: + continue + name_index = titles.index('name') + name = tokens[name_index] + data = {} + for i, item in enumerate(tokens): + if i == name_index: + continue + data[titles[i]] = item + data.setdefault('alias', name) + ports[name] = data + port_alias_map[data['alias']] = name + # asic_port_name to sonic_name mapping also included in + # port_alias_map + if (('asic_port_name' in data) and + (data['asic_port_name'] != name)): + port_alias_map[data['asic_port_name']] = name + # alias to asic_port_name mapping + if 'asic_port_name' in data: + port_alias_asic_map[data['alias']] = data['asic_port_name'].strip() + return (ports, port_alias_map, port_alias_asic_map) + +# Generate configs (i.e. alias, lanes, speed, index) for port +def gen_port_config(ports, parent_intf_id, index, alias_list, lanes, k, offset): + if k is not None: + num_lane_used, speed, alt_speed, _, _ , assigned_lane = k[0], k[1], k[2], k[3], k[4], k[5] + + # In case of symmetric mode + if assigned_lane is None: + assigned_lane = len(lanes.split(",")) + + parent_intf_id = int(offset)+int(parent_intf_id) + alias_position = 0 + int(offset)//int(num_lane_used) + lanes_start = 0 + int(offset) + + step = int(assigned_lane)//int(num_lane_used) + for i in range(0,int(assigned_lane), step): + intf_name = PORT_STR + str(parent_intf_id) + ports[intf_name] = {} + ports[intf_name]['alias'] = alias_list[alias_position] + ports[intf_name]['lanes'] = ','.join(lanes.split(",")[lanes_start:lanes_start+step]) + if speed: + speed_pat = re.search("^((\d+)G|\d+)$", speed.upper()) + if speed_pat is None: + raise Exception('{} speed is not Supported...'.format(speed)) + speed_G, speed_orig = speed_pat.group(2), speed_pat.group(1) + if speed_G: + conv_speed = int(speed_G)*1000 + else: + conv_speed = int(speed_orig) + ports[intf_name]['speed'] = str(conv_speed) + else: + raise Exception('Regex return for speed is None...') + + ports[intf_name]['index'] = index.split(",")[alias_position] + ports[intf_name]['admin_status'] = "up" + + parent_intf_id += step + alias_position += 1 + lanes_start += step + + offset = int(assigned_lane) + int(offset) + return offset + else: + raise Exception('Regex return for k is None...') + +""" +Given a port and breakout mode, this method returns +the list of child ports using platform_json file +""" +def get_child_ports(interface, breakout_mode, platform_json_file): + child_ports = {} + + port_dict = readJson(platform_json_file) + + index = port_dict[INTF_KEY][interface]['index'] + alias_list = port_dict[INTF_KEY][interface]['breakout_modes'][breakout_mode] + lanes = port_dict[INTF_KEY][interface]['lanes'] + + """ + Example of match_list for some breakout_mode using regex + Breakout Mode -------> Match_list + ----------------------------- + 2x25G(2)+1x50G(2) ---> [('2', '25G', None, '(2)', '2'), ('1', '50G', None, '(2)', '2')] + 1x50G(2)+2x25G(2) ---> [('1', '50G', None, '(2)', '2'), ('2', '25G', None, '(2)', '2')] + 1x100G[40G] ---------> [('1', '100G', '[40G]', None, None)] + 2x50G ---------------> [('2', '50G', None, None, None)] + """ + # Asymmetric breakout mode + if re.search("\+",breakout_mode) is not None: + breakout_parts = breakout_mode.split("+") + match_list = [re.match(BRKOUT_PATTERN, i).groups() for i in breakout_parts] + + # Symmetric breakout mode + else: + match_list = [re.match(BRKOUT_PATTERN, breakout_mode).groups()] + + offset = 0 + parent_intf_id = int(re.search("Ethernet(\d+)", interface).group(1)) + for k in match_list: + offset = gen_port_config(child_ports, parent_intf_id, index, alias_list, lanes, k, offset) + return child_ports + +def parse_platform_json_file(hwsku_json_file, platform_json_file): + ports = {} + port_alias_map = {} + port_alias_asic_map = {} + + port_dict = readJson(platform_json_file) + hwsku_dict = readJson(hwsku_json_file) + + if not port_dict: + raise Exception("port_dict is none") + if not hwsku_dict: + raise Exception("hwsku_dict is none") + + if INTF_KEY not in port_dict or INTF_KEY not in hwsku_dict: + raise Exception("INTF_KEY is not present in appropriate file") + + for intf in port_dict[INTF_KEY]: + if intf not in hwsku_dict[INTF_KEY]: + raise Exception("{} is not available in hwsku_dict".format(intf)) + + # take default_brkout_mode from hwsku.json + brkout_mode = hwsku_dict[INTF_KEY][intf][BRKOUT_MODE] + + child_ports = get_child_ports(intf, brkout_mode, platform_json_file) + + # take optional fields from hwsku.json + for key, item in hwsku_dict[INTF_KEY][intf].items(): + if key in OPTIONAL_HWSKU_ATTRIBUTES: + child_ports.get(intf)[key] = item + + ports.update(child_ports) + + if not ports: + raise Exception("Ports dictionary is empty") + + for i in ports.keys(): + port_alias_map[ports[i]["alias"]]= i + return (ports, port_alias_map, port_alias_asic_map) + + +def get_breakout_mode(hwsku=None, platform=None, port_config_file=None): + if not port_config_file: + port_config_file = device_info.get_path_to_port_config_file(hwsku) + if not port_config_file: + return None + if port_config_file.endswith('.json'): + hwsku_json_file = get_hwsku_file_name(hwsku, platform) + if not hwsku_json_file: + raise Exception("'hwsku_json' file does not exist!!! This file is necessary to proceed forward.") + + return parse_breakout_mode(hwsku_json_file) + else: + return None + +def parse_breakout_mode(hwsku_json_file): + brkout_table = {} + hwsku_dict = readJson(hwsku_json_file) + if not hwsku_dict: + raise Exception("hwsku_dict is empty") + if INTF_KEY not in hwsku_dict: + raise Exception("INTF_KEY is not present in hwsku_dict") + + for intf in hwsku_dict[INTF_KEY]: + brkout_table[intf] = {} + brkout_table[intf][CUR_BRKOUT_MODE] = hwsku_dict[INTF_KEY][intf][BRKOUT_MODE] + return brkout_table diff --git a/src/sonic-config-engine/redis_bcc.py b/src/sonic-config-engine/redis_bcc.py new file mode 100644 index 000000000000..c9d3ebca239f --- /dev/null +++ b/src/sonic-config-engine/redis_bcc.py @@ -0,0 +1,29 @@ +import jinja2 + +from base64 import b64encode, b64decode + +class RedisBytecodeCache(jinja2.BytecodeCache): + """ A bytecode cache for jinja2 template that stores bytecode in Redis """ + + REDIS_HASH = 'JINJA2_CACHE' + + def __init__(self, client): + self._client = client + try: + self._client.connect(self._client.LOGLEVEL_DB, retry_on=False) + except Exception: + self._client = None + + def load_bytecode(self, bucket): + if self._client is None: + return + code = self._client.get(self._client.LOGLEVEL_DB, self.REDIS_HASH, bucket.key) + if code is not None: + bucket.bytecode_from_string(b64decode(code.encode())) + + def dump_bytecode(self, bucket): + if self._client is None: + return + self._client.set(self._client.LOGLEVEL_DB, self.REDIS_HASH, + bucket.key, b64encode(bucket.bytecode_to_string()).decode()) + diff --git a/src/sonic-config-engine/setup.py b/src/sonic-config-engine/setup.py new file mode 100644 index 000000000000..d167e0566438 --- /dev/null +++ b/src/sonic-config-engine/setup.py @@ -0,0 +1,79 @@ +import glob +import sys + +from setuptools import setup + +# Common dependencies for Python 2 and 3 +dependencies = [ + 'bitarray==1.5.3', + 'ipaddress==1.0.23', + 'lxml==4.6.2', + 'netaddr==0.8.0', + 'pyyaml==5.4.1', + 'sonic-py-common', +] + +if sys.version_info.major == 3: + # Python 3-only dependencies + dependencies += [ + # pyangbind v0.8.1 pull down enum43 which causes 're' package to malfunction. + # Python3 has enum module and so pyangbind should be installed outside + # dependencies section of setuptools followed by uninstall of enum43 + # 'pyangbind==0.8.1', + 'Jinja2>=2.10' + ] +else: + # Python 2-only dependencies + dependencies += [ + # Jinja2 v3.0.0+ dropped support for Python 2.7 and causes setuptools to + # malfunction on stretch slave docker. + 'future', + 'Jinja2<3.0.0', + 'pyangbind==0.6.0', + 'zipp==1.2.0', # importlib-resources needs zipp and seems to have a bug where it will try to install too new of a version for Python 2 + 'importlib-resources==3.3.1' # importlib-resources v4.0.0 was released 2020-12-23 and drops support for Python 2 + ] + + +setup( + name = 'sonic-config-engine', + version = '1.0', + description = 'Utilities for generating SONiC configuration files', + author = 'Taoyu Li', + author_email = 'taoyl@microsoft.com', + url = 'https://github.com/Azure/sonic-buildimage', + py_modules = [ + 'config_samples', + 'lazy_re', + 'minigraph', + 'openconfig_acl', + 'portconfig', + 'redis_bcc', + ], + scripts = [ + 'sonic-cfggen', + ], + install_requires = dependencies, + data_files = [ + ('/usr/share/sonic/templates', glob.glob('data/*')), + ], + setup_requires= [ + 'pytest-runner', + 'wheel' + ], + tests_require=[ + 'pytest', + ], + classifiers = [ + 'Intended Audience :: Developers', + 'Natural Language :: English', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + ], + keywords = 'SONiC sonic-cfggen config-engine PYTHON python' +) diff --git a/src/sonic-config-engine/sonic-cfggen b/src/sonic-config-engine/sonic-cfggen new file mode 100755 index 000000000000..0f9ffafad635 --- /dev/null +++ b/src/sonic-config-engine/sonic-cfggen @@ -0,0 +1,432 @@ +#!/usr/bin/env python +"""sonic-cfggen + +A tool to read SONiC config data from one or more of the following sources: +minigraph file, config DB, json file(s), yaml files(s), command line input, +and write the data into DB, print as json, or render a jinja2 config template. + +Examples: + Render template with minigraph: + sonic-cfggen -m -t /usr/share/template/bgpd.conf.j2 + Dump config DB content into json file: + sonic-cfggen -d --print-data > db_dump.json + Load content of json file into config DB: + sonic-cfggen -j db_dump.json --write-to-db +See usage string for detail description for arguments. +""" + +from __future__ import print_function + +# monkey patch re.compile to do lazy regular expression compilation. +# This is done to improve import time of jinja2, yaml, natsort modules, because they +# do many regexp compilation at import time, so it will speed up sonic-cfggen invocations +# that do not require template generation or yaml loading. sonic-cfggen is used in so many places +# during system boot up that importing jinja2, yaml, natsort every time +# without lazy regular expression compilation affect boot up time. +# FIXME: remove this once sonic-cfggen and templates dependencies are replaced with a faster approach +import lazy_re + +import argparse +import contextlib +import jinja2 +import json +import netaddr +import os +import sys +import yaml + +from collections import OrderedDict +from config_samples import generate_sample_config, get_available_config +from functools import partial +from minigraph import minigraph_encoder, parse_xml, parse_device_desc_xml, parse_asic_sub_role +from portconfig import get_port_config, get_breakout_mode +from redis_bcc import RedisBytecodeCache +from sonic_py_common.multi_asic import get_asic_id_from_name, is_multi_asic +from sonic_py_common import device_info +from swsscommon.swsscommon import SonicV2Connector, ConfigDBConnector, SonicDBConfig, ConfigDBPipeConnector + + +PY3x = sys.version_info >= (3, 0) + +#TODO: Remove STR_TYPE, FILE_TYPE once SONiC moves to Python 3.x +if PY3x: + from io import IOBase + STR_TYPE = str + FILE_TYPE = IOBase +else: + STR_TYPE = unicode + FILE_TYPE = file + +def sort_by_port_index(value): + if not value: + return + if isinstance(value, list): + # In multi-ASIC platforms backend ethernet ports are identified as + # 'Ethernet-BPxy'. Add 1024 to sort backend ports to the end. + value.sort( + key = lambda k: int(k[8:]) if "BP" not in k else int(k[11:]) + 1024 + ) + +def is_ipv4(value): + if not value: + return False + if isinstance(value, netaddr.IPNetwork): + addr = value + else: + try: + addr = netaddr.IPNetwork(str(value)) + except: + return False + return addr.version == 4 + +def is_ipv6(value): + if not value: + return False + if isinstance(value, netaddr.IPNetwork): + addr = value + else: + try: + addr = netaddr.IPNetwork(str(value)) + except: + return False + return addr.version == 6 + +def prefix_attr(attr, value): + if not value: + return None + else: + try: + prefix = netaddr.IPNetwork(str(value)) + except: + return None + return str(getattr(prefix, attr)) + +def unique_name(l): + name_list = [] + new_list = [] + for item in l: + if item['name'] not in name_list: + name_list.append(item['name']) + new_list.append(item) + return new_list + +def pfx_filter(value): + """INTERFACE Table can have keys in one of the two formats: + string or tuple - This filter skips the string keys and only + take into account the tuple. + For eg - VLAN_INTERFACE|Vlan1000 vs VLAN_INTERFACE|Vlan1000|192.168.0.1/21 + """ + table = OrderedDict() + + if not value: + return table + + for key,val in value.items(): + if not isinstance(key, tuple): + continue + intf, ip_address = key + if '/' not in ip_address: + if is_ipv4(ip_address): + new_ip_address = "%s/32" % ip_address + elif is_ipv6(ip_address): + new_ip_address = "%s/128" % ip_address + else: + raise ValueError("'%s' is invalid ip address" % ip_address) + table[(intf, new_ip_address)] = val + else: + table[key] = val + return table + +def ip_network(value): + """ Extract network for network prefix """ + try: + r_v = netaddr.IPNetwork(value) + except: + return "Invalid ip address %s" % value + return r_v.network + +class FormatConverter: + """Convert config DB based schema to legacy minigraph based schema for backward capability. +We will move to DB schema and remove this class when the config templates are modified. + +TODO(taoyl): Current version of config db only supports BGP admin states. + All other configuration are still loaded from minigraph. Plan to remove + minigraph and move everything into config db in a later commit. + """ + @staticmethod + def db_to_output(db_data): + return db_data + + @staticmethod + def output_to_db(output_data): + db_data = {} + for table_name in output_data: + if table_name[0].isupper(): + db_data[table_name] = output_data[table_name] + return db_data + + @staticmethod + def to_serialized(data, lookup_key = None): + if type(data) is dict: + if lookup_key is not None: + newData = {} + for key in data.keys(): + if ((type(key) is STR_TYPE and lookup_key == key) or (type(key) is tuple and lookup_key in key)): + newData[ConfigDBConnector.serialize_key(key)] = data.pop(key) + break + return newData + + current_keys = list(data.keys()) + for key in current_keys: + new_key = ConfigDBConnector.serialize_key(key) + if new_key != key: + data[new_key] = data.pop(key) + data[new_key] = FormatConverter.to_serialized(data[new_key]) + return data + + @staticmethod + def to_deserialized(data): + for table in data: + if type(data[table]) is dict: + current_keys = list(data[table].keys()) + for key in current_keys: + new_key = ConfigDBConnector.deserialize_key(key) + if new_key != key: + data[table][new_key] = data[table].pop(key) + return data + + +def deep_update(dst, src): + """ Deep update of dst dict with contest of src dict""" + pending_nodes = [(dst, src)] + while len(pending_nodes) > 0: + d, s = pending_nodes.pop(0) + for key, value in s.items(): + if isinstance(value, dict): + node = d.setdefault(key, type(value)()) + pending_nodes.append((node, value)) + else: + d[key] = value + return dst + +# sort_data is required as it is being imported by config/config_mgmt module in sonic_utilities +def sort_data(data): + for table in data: + if type(data[table]) is dict: + data[table] = OrderedDict(natsorted(data[table].items())) + return data + +@contextlib.contextmanager +def smart_open(filename=None, mode=None): + """ + Provide contextual file descriptor of filename if it is not a file descriptor + """ + smart_file = open(filename, mode) if not isinstance(filename, FILE_TYPE) else filename + try: + yield smart_file + finally: + if not isinstance(filename, FILE_TYPE): + smart_file.close() + +def _process_json(args, data): + """ + Process JSON file and update switch configuration data + """ + for json_file in args.json: + with open(json_file, 'r') as stream: + deep_update(data, FormatConverter.to_deserialized(json.load(stream))) + +def _get_jinja2_env(paths): + """ + Retreive Jinj2 env used to render configuration templates + """ + loader = jinja2.FileSystemLoader(paths) + redis_bcc = RedisBytecodeCache(SonicV2Connector(host='127.0.0.1')) + env = jinja2.Environment(loader=loader, trim_blocks=True, bytecode_cache=redis_bcc) + env.filters['sort_by_port_index'] = sort_by_port_index + env.filters['ipv4'] = is_ipv4 + env.filters['ipv6'] = is_ipv6 + env.filters['unique_name'] = unique_name + env.filters['pfx_filter'] = pfx_filter + env.filters['ip_network'] = ip_network + for attr in ['ip', 'network', 'prefixlen', 'netmask', 'broadcast']: + env.filters[attr] = partial(prefix_attr, attr) + # Pass the is_multi_asic function as global + env.globals['multi_asic'] = is_multi_asic + + return env + +def main(): + parser=argparse.ArgumentParser(description="Render configuration file from minigraph data and jinja2 template.") + group = parser.add_mutually_exclusive_group() + group.add_argument("-m", "--minigraph", help="minigraph xml file", nargs='?', const='/etc/sonic/minigraph.xml') + group.add_argument("-M", "--device-description", help="device description xml file") + group.add_argument("-k", "--hwsku", help="HwSKU") + parser.add_argument("-n", "--namespace", help="namespace name", nargs='?', const=None, default=None) + parser.add_argument("-p", "--port-config", help="port config file, used with -m or -k", nargs='?', const=None) + parser.add_argument("-S", "--hwsku-config", help="hwsku config file, used with -p and -m or -k", nargs='?', const=None) + parser.add_argument("-y", "--yaml", help="yaml file that contains additional variables", action='append', default=[]) + parser.add_argument("-j", "--json", help="json file that contains additional variables", action='append', default=[]) + parser.add_argument("-a", "--additional-data", help="addition data, in json string") + parser.add_argument("-d", "--from-db", help="read config from configdb", action='store_true') + parser.add_argument("-H", "--platform-info", help="read platform and hardware info", action='store_true') + parser.add_argument("-s", "--redis-unix-sock-file", help="unix sock file for redis connection") + group = parser.add_mutually_exclusive_group() + group.add_argument("-t", "--template", help="render the data with the template file", action="append", default=[], + type=lambda opt_value: tuple(opt_value.split(',')) if ',' in opt_value else (opt_value, sys.stdout)) + parser.add_argument("-T", "--template_dir", help="search base for the template files", action='store') + group.add_argument("-v", "--var", help="print the value of a variable, support jinja2 expression") + group.add_argument("--var-json", help="print the value of a variable, in json format") + group.add_argument("--preset", help="generate sample configuration from a preset template", choices=get_available_config()) + group = parser.add_mutually_exclusive_group() + group.add_argument("--print-data", help="print all data", action='store_true') + group.add_argument("-w", "--write-to-db", help="write config into configdb", action='store_true') + group.add_argument("-K", "--key", help="Lookup for a specific key") + args = parser.parse_args() + + platform = device_info.get_platform() + + db_kwargs = {} + if args.redis_unix_sock_file is not None: + db_kwargs['unix_socket_path'] = args.redis_unix_sock_file + + data = {} + hwsku = args.hwsku + asic_name = args.namespace + asic_id = None + if asic_name is not None: + asic_id = get_asic_id_from_name(asic_name) + # get the namespace ID + namespace_id = os.getenv("NAMESPACE_ID") + if namespace_id: + deep_update(data, { + 'DEVICE_METADATA': { + 'localhost': {'namespace_id': namespace_id} + } + }) + # Load the database config for the namespace from global database json + if args.namespace is not None: + SonicDBConfig.load_sonic_global_db_config(namespace=args.namespace) + + if hwsku is not None: + hardware_data = {'DEVICE_METADATA': {'localhost': { + 'hwsku': hwsku + }}} + deep_update(data, hardware_data) + if args.port_config is None: + args.port_config = device_info.get_path_to_port_config_file(hwsku) + (ports, _, _) = get_port_config(hwsku, platform, args.port_config, asic_id) + if not ports: + print('Failed to get port config', file=sys.stderr) + sys.exit(1) + deep_update(data, {'PORT': ports}) + + brkout_table = get_breakout_mode(hwsku, platform, args.port_config) + if brkout_table is not None: + deep_update(data, {'BREAKOUT_CFG': brkout_table}) + + _process_json(args, data) + + if args.minigraph is not None: + minigraph = args.minigraph + if platform: + if args.port_config is not None: + deep_update(data, parse_xml(minigraph, platform, args.port_config, asic_name=asic_name, hwsku_config_file=args.hwsku_config)) + else: + deep_update(data, parse_xml(minigraph, platform, asic_name=asic_name)) + else: + deep_update(data, parse_xml(minigraph, port_config_file=args.port_config, asic_name=asic_name, hwsku_config_file=args.hwsku_config)) + + if args.device_description is not None: + deep_update(data, parse_device_desc_xml(args.device_description)) + + for yaml_file in args.yaml: + with open(yaml_file, 'r') as stream: + if yaml.__version__ >= "5.1": + additional_data = yaml.full_load(stream) + else: + additional_data = yaml.load(stream) + deep_update(data, FormatConverter.to_deserialized(additional_data)) + + if args.additional_data is not None: + deep_update(data, json.loads(args.additional_data)) + + if args.from_db: + if args.namespace is None: + configdb = ConfigDBPipeConnector(use_unix_socket_path=True, **db_kwargs) + else: + configdb = ConfigDBPipeConnector(use_unix_socket_path=True, namespace=args.namespace, **db_kwargs) + + configdb.connect() + deep_update(data, FormatConverter.db_to_output(configdb.get_config())) + + + # the minigraph file must be provided to get the mac address for backend asics + if args.platform_info: + asic_role = None + if asic_name is not None: + if args.minigraph is not None: + asic_role = parse_asic_sub_role(args.minigraph, asic_name) + + if asic_role is not None and asic_role.lower() == "backend": + mac = device_info.get_system_mac(namespace=asic_name) + else: + mac = device_info.get_system_mac() + else: + mac = device_info.get_system_mac() + + hardware_data = {'DEVICE_METADATA': {'localhost': { + 'platform': platform, + 'mac': mac, + }}} + # The ID needs to be passed to the SAI to identify the asic. + if asic_name is not None: + hardware_data['DEVICE_METADATA']['localhost'].update(asic_id=asic_id) + deep_update(data, hardware_data) + + paths = ['/', '/usr/share/sonic/templates'] + if args.template_dir: + paths.append(os.path.abspath(args.template_dir)) + + if args.template: + for template_file, _ in args.template: + paths.append(os.path.dirname(os.path.abspath(template_file))) + env = _get_jinja2_env(paths) + for template_file, dest_file in args.template: + template = env.get_template(os.path.basename(template_file)) + template_data = template.render(data) + if dest_file == "config-db": + deep_update(data, FormatConverter.to_deserialized(json.loads(template_data))) + else: + with smart_open(dest_file, 'w') as df: + print(template_data, file=df) + + if args.var is not None: + template = jinja2.Template('{{' + args.var + '}}') + print(template.render(data)) + + if args.var_json is not None and args.var_json in data: + if args.key is not None: + print(json.dumps(FormatConverter.to_serialized(data[args.var_json], args.key), indent=4, cls=minigraph_encoder)) + else: + print(json.dumps(FormatConverter.to_serialized(data[args.var_json]), indent=4, cls=minigraph_encoder)) + + if args.write_to_db: + if args.namespace is None: + configdb = ConfigDBPipeConnector(use_unix_socket_path=True, **db_kwargs) + else: + configdb = ConfigDBPipeConnector(use_unix_socket_path=True, namespace=args.namespace, **db_kwargs) + + configdb.connect(False) + configdb.mod_config(FormatConverter.output_to_db(data)) + + if args.print_data: + print(json.dumps(FormatConverter.to_serialized(data), indent=4, cls=minigraph_encoder)) + + if args.preset is not None: + data = generate_sample_config(data, args.preset) + print(json.dumps(FormatConverter.to_serialized(data), indent=4, cls=minigraph_encoder)) + + +if __name__ == "__main__": + main() diff --git a/src/sonic-config-engine/tests/.gitignore b/src/sonic-config-engine/tests/.gitignore new file mode 100644 index 000000000000..bee8a64b79a9 --- /dev/null +++ b/src/sonic-config-engine/tests/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/src/sonic-config-engine/tests/__init__.py b/src/sonic-config-engine/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-config-engine/tests/common_utils.py b/src/sonic-config-engine/tests/common_utils.py new file mode 100644 index 000000000000..3d8a3029dad9 --- /dev/null +++ b/src/sonic-config-engine/tests/common_utils.py @@ -0,0 +1,33 @@ +import json +import re +import sys + +PY3x = sys.version_info >= (3, 0) +PYvX_DIR = "py3" if PY3x else "py2" +PYTHON_INTERPRETTER = "python3" if PY3x else "python2" + +def tuple_to_str(tuplestr): + """ Convert Python tuple '('elem1', 'elem2')' representation into string on the for "elem1|elem2" """ + def to_str(tupleobj): + tupleobj = re.sub(r"([\(\)])", '"', tupleobj.group(0)) + return re.sub(r"( *, *)", '|', tupleobj).replace("'", '') + + return re.sub(r"(\(.*?\))", to_str, tuplestr) + +def to_dict(dictstr): + """ Convert string represention of Python dict into dict """ + # handle tuple elements + dictstr = tuple_to_str(dictstr) + + return json.loads(dictstr.replace("'", '"')) + +def liststr_to_dict(liststr): + """ Convert string represention of Python list into dict with list key and sorted liststr as its value """ + # handle tuple elements + liststr = tuple_to_str(liststr) + + list_obj = json.loads("{\"list\":" + liststr.replace("'", '"') +'}') + list_obj["list"] = sorted(list_obj["list"]) + + return list_obj + diff --git a/src/sonic-config-engine/tests/data/lldp/mgmt_iface_ipv4.json b/src/sonic-config-engine/tests/data/lldp/mgmt_iface_ipv4.json new file mode 100644 index 000000000000..c38b677aad7a --- /dev/null +++ b/src/sonic-config-engine/tests/data/lldp/mgmt_iface_ipv4.json @@ -0,0 +1,12 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "switch-t0" + } + }, + "MGMT_INTERFACE": { + "eth0|10.0.0.100/24": { + "gwaddr": "10.0.0.100" + } + } +} diff --git a/src/sonic-config-engine/tests/data/lldp/mgmt_iface_ipv4_and_ipv6.json b/src/sonic-config-engine/tests/data/lldp/mgmt_iface_ipv4_and_ipv6.json new file mode 100644 index 000000000000..87f887fb870d --- /dev/null +++ b/src/sonic-config-engine/tests/data/lldp/mgmt_iface_ipv4_and_ipv6.json @@ -0,0 +1,15 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "switch-t0" + } + }, + "MGMT_INTERFACE": { + "eth0|10.0.0.100/24": { + "gwaddr": "10.0.0.100" + }, + "eth0|2603:10e2:0:2902::8/64": { + "gwaddr": "2603:10e2:0:2902::8" + } + } +} diff --git a/src/sonic-config-engine/tests/data/lldp/mgmt_iface_ipv6.json b/src/sonic-config-engine/tests/data/lldp/mgmt_iface_ipv6.json new file mode 100644 index 000000000000..c1dd4964c6bf --- /dev/null +++ b/src/sonic-config-engine/tests/data/lldp/mgmt_iface_ipv6.json @@ -0,0 +1,12 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "switch-t0" + } + }, + "MGMT_INTERFACE": { + "eth0|2603:10e2:0:2902::8/64": { + "gwaddr": "2603:10e2:0:2902::8" + } + } +} diff --git a/src/sonic-config-engine/tests/data/ndppd/vlan_interfaces.json b/src/sonic-config-engine/tests/data/ndppd/vlan_interfaces.json new file mode 100644 index 000000000000..d45214827642 --- /dev/null +++ b/src/sonic-config-engine/tests/data/ndppd/vlan_interfaces.json @@ -0,0 +1,20 @@ +{ + "VLAN_INTERFACE": { + "Vlan1000": { + "proxy_arp": "enabled" + }, + "Vlan1000|192.168.0.1/21": {}, + "Vlan1000|fc01:1000::1/64": {}, + "Vlan1000|fc02:1000::1/64": {}, + "Vlan1000|fc03:1000::1/64": {}, + "Vlan2000": { + "proxy_arp": "enabled" + }, + "Vlan2000|fc01:2000::1/64": {}, + "Vlan3000|fc01:3000::1/64": {}, + "Vlan4000": { + "proxy_arp": "disabled" + }, + "Vlan4000|fc01:4000::1/64": {} + } +} \ No newline at end of file diff --git a/src/sonic-config-engine/tests/data/pfx_filter/param_1.json b/src/sonic-config-engine/tests/data/pfx_filter/param_1.json new file mode 100644 index 000000000000..ce6cd21886a2 --- /dev/null +++ b/src/sonic-config-engine/tests/data/pfx_filter/param_1.json @@ -0,0 +1,12 @@ +{ + "VLAN_INTERFACE": { + "Vlan1": {}, + "Vlan1|1.1.1.1/32": {}, + "Vlan2": {}, + "Vlan2|2.2.2.2": {}, + "Vlan3": {}, + "Vlan3|fc00::1": {}, + "Vlan4": {}, + "Vlan4|fc00::2/64": {} + } +} diff --git a/src/sonic-config-engine/tests/data/pfx_filter/result_1.txt b/src/sonic-config-engine/tests/data/pfx_filter/result_1.txt new file mode 100644 index 000000000000..d8ea7d304222 --- /dev/null +++ b/src/sonic-config-engine/tests/data/pfx_filter/result_1.txt @@ -0,0 +1,5 @@ +"Vlan1"="1.1.1.1/32" +"Vlan2"="2.2.2.2/32" +"Vlan3"="fc00::1/128" +"Vlan4"="fc00::2/64" + diff --git a/src/sonic-config-engine/tests/data/pfx_filter/tmpl_1.txt.j2 b/src/sonic-config-engine/tests/data/pfx_filter/tmpl_1.txt.j2 new file mode 100644 index 000000000000..2612fe4a2936 --- /dev/null +++ b/src/sonic-config-engine/tests/data/pfx_filter/tmpl_1.txt.j2 @@ -0,0 +1,3 @@ +{% for intf, addr in VLAN_INTERFACE|pfx_filter %} +"{{ intf }}"="{{ addr }}" +{% endfor %} diff --git a/src/sonic-config-engine/tests/device.xml b/src/sonic-config-engine/tests/device.xml new file mode 100644 index 000000000000..2995c4dde133 --- /dev/null +++ b/src/sonic-config-engine/tests/device.xml @@ -0,0 +1,17 @@ + + ToRRouter +
+ 10.10.0.12/32 +
+ + ::/0 + + + 10.0.1.5/28 + + + ::/0 + + switch1 + ACS-MSN2700 +
diff --git a/src/sonic-config-engine/tests/fg-ecmp-sample-minigraph.xml b/src/sonic-config-engine/tests/fg-ecmp-sample-minigraph.xml new file mode 100644 index 000000000000..f8fcf1e0fce7 --- /dev/null +++ b/src/sonic-config-engine/tests/fg-ecmp-sample-minigraph.xml @@ -0,0 +1,1591 @@ + + + + + + + false + str2-sn3800-azd + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 10 + 3 + + + str2-sn3800-azd + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 10 + 3 + + + false + str2-sn3800-azd + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 10 + 3 + + + str2-sn3800-azd + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 10 + 3 + + + false + str2-sn3800-azd + 10.0.0.60 + ARISTA03T1 + 10.0.0.61 + 1 + 10 + 3 + + + str2-sn3800-azd + FC00::79 + ARISTA03T1 + FC00::7A + 1 + 10 + 3 + + + false + str2-sn3800-azd + 10.0.0.62 + ARISTA04T1 + 10.0.0.63 + 1 + 10 + 3 + + + str2-sn3800-azd + FC00::7D + ARISTA04T1 + FC00::7E + 1 + 10 + 3 + + + + + 65100 + str2-sn3800-azd + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+ +
10.0.0.61
+ + + +
+ +
10.0.0.63
+ + + +
+ + BGPPeer +
10.1.0.32
+ + + + BGPSLBPassive + 10.255.0.0/25 +
+ + BGPPeer +
10.1.0.32
+ + + + BGPVac + 192.168.0.0/21 +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.3.146.183/23 + + 10.3.146.183/23 + + + V6HostIP + eth0 + + FC00:2::32/64 + + FC00:2::32/64 + + + + + + + str2-sn3800-azd + + + PortChannel0001 + etp29 + + + + PortChannel0002 + etp30 + + + + PortChannel0003 + etp31 + + + + PortChannel0004 + etp32 + + + + + + Vlan1000 + etp2;etp3;etp4;etp5;etp6;etp7;etp8;etp9;etp10;etp11;etp12;etp13;etp14;etp15;etp16;etp17;etp18;etp19;etp20;etp21;etp22;etp23;etp24;etp25 + False + 0.0.0.0/0 + + 192.0.0.1;192.0.0.2;192.0.0.3;192.0.0.4;192.0.0.5;192.0.0.6;192.0.0.7;192.0.0.8;192.0.0.9;192.0.0.10;192.0.0.11;192.0.0.12;192.0.0.13;192.0.0.14;192.0.0.15;192.0.0.16;192.0.0.17;192.0.0.18;192.0.0.19;192.0.0.20;192.0.0.21;192.0.0.22;192.0.0.23;192.0.0.24;192.0.0.25;192.0.0.26;192.0.0.27;192.0.0.28;192.0.0.29;192.0.0.30;192.0.0.31;192.0.0.32;192.0.0.33;192.0.0.34;192.0.0.35;192.0.0.36;192.0.0.37;192.0.0.38;192.0.0.39;192.0.0.40;192.0.0.41;192.0.0.42;192.0.0.43;192.0.0.44;192.0.0.45;192.0.0.46;192.0.0.47;192.0.0.48 + 1000 + 1000 + 192.168.0.0/21 + + + + + + PortChannel0001 + 10.0.0.56/31 + + + + PortChannel0001 + FC00::71/126 + + + + PortChannel0002 + 10.0.0.58/31 + + + + PortChannel0002 + FC00::75/126 + + + + PortChannel0003 + 10.0.0.60/31 + + + + PortChannel0003 + FC00::79/126 + + + + PortChannel0004 + 10.0.0.62/31 + + + + PortChannel0004 + FC00::7D/126 + + + + Vlan1000 + 192.168.0.1/21 + + + + Vlan31 + 200.200.200.0/27 + + + + + + SNMP_ACL + SNMP + SNMP + + + ERSPAN + fg-ecmp-sample-minigraphfg-ecmp-sample-minigraph + Everflow + Everflow + + + ERSPANV6 + EverflowV6 + EverflowV6 + + + VTY_LINE + ssh-only + SSH + + + PortChannel0001;PortChannel0002;PortChannel0003;PortChannel0004 + DataAcl + DataPlane + + + + + + false + 100.50.25.12/32 + FineGrainedECMPGroupDestination + + + true + 2603:10b0:10d:e07::/64 + DeviceAggregate + + + false + fc:5::/128 + FineGrainedECMPGroupDestination + + + + + IPNextHop + + etp10 +
200.200.200.1
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp11 +
200.200.200.2
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp12 +
200.200.200.3
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp13 +
200.200.200.4
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp14 +
200.200.200.5
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp15 +
200.200.200.6
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp16 +
200.200.200.7
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp17 +
200.200.200.8
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp18 +
200.200.200.9
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp19 +
200.200.200.10
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp10 +
200:200:200:200::1
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp11 +
200:200:200:200::2
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp12 +
200:200:200:200::3
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp13 +
200:200:200:200::4
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp14 +
200:200:200:200::5
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp15 +
200:200:200:200::6
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp16 +
200:200:200:200::7
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp17 +
200:200:200:200::8
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp18 +
200:200:200:200::9
+ FineGrainedECMPGroupMember +
+ + IPNextHop + + etp19 +
200:200:200:200::10
+ FineGrainedECMPGroupMember +
+
+
+
+ + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1 + str2-sn3800-azd + etp29 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1 + str2-sn3800-azd + etp30 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1 + str2-sn3800-azd + etp31 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1 + str2-sn3800-azd + etp32 + + + DeviceInterfaceLink + str2-sn3800-azd + etp2 + Servers0 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp5 + Servers3 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp6 + Servers4 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp9 + Servers7 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp10 + Servers10 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp11 + Servers11 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp12 + Servers10 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp13 + Servers11 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp14 + Servers10 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp15 + Servers11 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp16 + Servers10 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp17 + Servers11 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp18 + Servers10 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp19 + Servers11 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp20 + Servers10 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp21 + Servers11 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp22 + Servers20 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp23 + Servers21 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp24 + Servers22 + eth0 + + + DeviceInterfaceLink + str2-sn3800-azd + etp25 + Servers23 + eth0 + + + + + str2-sn3800-azd + ACS-MSN3800 + + 10.3.146.183 + + + + ARISTA04T1 + + 172.16.134.63 + + Arista-VM + + + ARISTA03T1 + + 172.16.134.62 + + Arista-VM + + + ARISTA02T1 + + 172.16.134.61 + + Arista-VM + + + ARISTA01T1 + + 172.16.134.60 + + Arista-VM + + + + + + true + + + DeviceInterface + + true + true + 1 + etp1 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp2 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp3 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp4 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp5 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp6 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp7 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp8 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp9 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp10 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp11 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp12 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp13 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp14 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp15 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp16 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp17 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp18 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp19 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp20 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp21 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp22 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp23 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp24 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp25 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp26 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp27 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp28 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp29 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp30 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp31 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp32 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp33 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp34 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp35 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp36 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp37 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp38 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp39 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp40 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp41 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp42 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp43 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp44 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp45 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp46 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp47 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp48 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp49 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp50 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp51 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp52 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp53 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp54 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp55 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp56 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp57 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp58 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp59 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp60 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp61 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp62 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp63 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + true + 1 + etp64 + + false + 0 + 0 + 100000 + + + true + 0 + ACS-MSN3800 + + + + + + + str2-sn3800-azd + + + DeploymentId + + 26 + + + QosProfile + + Profile0 + + + DhcpResources + + 192.0.0.1;192.0.0.2;192.0.0.3;192.0.0.4;192.0.0.5;192.0.0.6;192.0.0.7;192.0.0.8;192.0.0.9;192.0.0.10;192.0.0.11;192.0.0.12;192.0.0.13;192.0.0.14;192.0.0.15;192.0.0.16;192.0.0.17;192.0.0.18;192.0.0.19;192.0.0.20;192.0.0.21;192.0.0.22;192.0.0.23;192.0.0.24;192.0.0.25;192.0.0.26;192.0.0.27;192.0.0.28;192.0.0.29;192.0.0.30;192.0.0.31;192.0.0.32;192.0.0.33;192.0.0.34;192.0.0.35;192.0.0.36;192.0.0.37;192.0.0.38;192.0.0.39;192.0.0.40;192.0.0.41;192.0.0.42;192.0.0.43;192.0.0.44;192.0.0.45;192.0.0.46;192.0.0.47;192.0.0.48 + + + NtpResources + + 10.20.8.129;10.20.8.130 + + + SnmpResources + + 10.3.145.98 + + + SyslogResources + + 10.3.145.8;100.127.20.21 + + + TacacsGroup + + Starlab + + + TacacsServer + + 100.127.20.21 + + + ForcedMgmtRoutes + + 10.3.145.98/31;10.3.145.8;100.127.20.16/28;10.3.149.170/31;40.122.216.24;13.91.48.226;10.3.145.14 + + + ErspanDestinationIpv4 + + 10.20.6.16 + + + + + + + str2-sn3800-azd + ACS-MSN3800 +
\ No newline at end of file diff --git a/src/sonic-config-engine/tests/mellanox-sample-port-config.ini b/src/sonic-config-engine/tests/mellanox-sample-port-config.ini new file mode 100644 index 000000000000..2af5aa67ff3a --- /dev/null +++ b/src/sonic-config-engine/tests/mellanox-sample-port-config.ini @@ -0,0 +1,65 @@ +# name lanes alias index +Ethernet0 0,1,2,3 etp1 1 +Ethernet4 4,5,6,7 etp2 2 +Ethernet8 8,9,10,11 etp3 3 +Ethernet12 12,13,14,15 etp4 4 +Ethernet16 16,17,18,19 etp5 5 +Ethernet20 20,21,22,23 etp6 6 +Ethernet24 24,25,26,27 etp7 7 +Ethernet28 28,29,30,31 etp8 8 +Ethernet32 32,33,34,35 etp9 9 +Ethernet36 36,37,38,39 etp10 10 +Ethernet40 40,41,42,43 etp11 11 +Ethernet44 44,45,46,47 etp12 12 +Ethernet48 48,49,50,51 etp13 13 +Ethernet52 52,53,54,55 etp14 14 +Ethernet56 56,57,58,59 etp15 15 +Ethernet60 60,61,62,63 etp16 16 +Ethernet64 64,65,66,67 etp17 17 +Ethernet68 68,69,70,71 etp18 18 +Ethernet72 72,73,74,75 etp19 19 +Ethernet76 76,77,78,79 etp20 20 +Ethernet80 80,81,82,83 etp21 21 +Ethernet84 84,85,86,87 etp22 22 +Ethernet88 88,89,90,91 etp23 23 +Ethernet92 92,93,94,95 etp24 24 +Ethernet96 96,97,98,99 etp25 25 +Ethernet100 100,101,102,103 etp26 26 +Ethernet104 104,105,106,107 etp27 27 +Ethernet108 108,109,110,111 etp28 28 +Ethernet112 112,113,114,115 etp29 29 +Ethernet116 116,117,118,119 etp30 30 +Ethernet120 120,121,122,123 etp31 31 +Ethernet124 124,125,126,127 etp32 32 +Ethernet128 128,129,130,131 etp33 33 +Ethernet132 132,133,134,135 etp34 34 +Ethernet136 136,137,138,139 etp35 35 +Ethernet140 140,141,142,143 etp36 36 +Ethernet144 144,145,146,147 etp37 37 +Ethernet148 148,149,150,151 etp38 38 +Ethernet152 152,153,154,155 etp39 39 +Ethernet156 156,157,158,159 etp40 40 +Ethernet160 160,161,162,163 etp41 41 +Ethernet164 164,165,166,167 etp42 42 +Ethernet168 168,169,170,171 etp43 43 +Ethernet172 172,173,174,175 etp44 44 +Ethernet176 176,177,178,179 etp45 45 +Ethernet180 180,181,182,183 etp46 46 +Ethernet184 184,185,186,187 etp47 47 +Ethernet188 188,189,190,191 etp48 48 +Ethernet192 192,193,194,195 etp49 49 +Ethernet196 196,197,198,199 etp50 50 +Ethernet200 200,201,202,203 etp51 51 +Ethernet204 204,205,206,207 etp52 52 +Ethernet208 208,209,210,211 etp53 53 +Ethernet212 212,213,214,215 etp54 54 +Ethernet216 216,217,218,219 etp55 55 +Ethernet220 220,221,222,223 etp56 56 +Ethernet224 224,225,226,227 etp57 57 +Ethernet228 228,229,230,231 etp58 58 +Ethernet232 232,233,234,235 etp59 59 +Ethernet236 236,237,238,239 etp60 60 +Ethernet240 240,241,242,243 etp61 61 +Ethernet244 244,245,246,247 etp62 62 +Ethernet248 248,249,250,251 etp63 63 +Ethernet252 252,253,254,255 etp64 64 \ No newline at end of file diff --git a/src/sonic-config-engine/tests/multi_npu_data/py2/ipinip.json b/src/sonic-config-engine/tests/multi_npu_data/py2/ipinip.json new file mode 100644 index 000000000000..3e8d4429d77d --- /dev/null +++ b/src/sonic-config-engine/tests/multi_npu_data/py2/ipinip.json @@ -0,0 +1,23 @@ +[ + { + "TUNNEL_DECAP_TABLE:IPINIP_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"10.0.0.0,10.1.0.1,10.1.0.3,10.1.0.32,8.0.0.0", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", + "ttl_mode":"pipe" + }, + "OP": "SET" + } + , + { + "TUNNEL_DECAP_TABLE:IPINIP_V6_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"fc00:1::32,fc00::1,fd00:1::32", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", + "ttl_mode":"pipe" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/multi_npu_data/py3/ipinip.json b/src/sonic-config-engine/tests/multi_npu_data/py3/ipinip.json new file mode 100644 index 000000000000..3e8d4429d77d --- /dev/null +++ b/src/sonic-config-engine/tests/multi_npu_data/py3/ipinip.json @@ -0,0 +1,23 @@ +[ + { + "TUNNEL_DECAP_TABLE:IPINIP_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"10.0.0.0,10.1.0.1,10.1.0.3,10.1.0.32,8.0.0.0", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", + "ttl_mode":"pipe" + }, + "OP": "SET" + } + , + { + "TUNNEL_DECAP_TABLE:IPINIP_V6_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"fc00:1::32,fc00::1,fd00:1::32", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", + "ttl_mode":"pipe" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/multi_npu_data/sample-minigraph.xml b/src/sonic-config-engine/tests/multi_npu_data/sample-minigraph.xml new file mode 100644 index 000000000000..412262315b4e --- /dev/null +++ b/src/sonic-config-engine/tests/multi_npu_data/sample-minigraph.xml @@ -0,0 +1,1246 @@ + + + + + + false + multi_npu_platform_01 + 10.0.0.0 + 01T2 + 10.0.0.1 + 1 + 10 + 3 + + + multi_npu_platform_01 + FC00::1 + 01T2 + FC00::2 + 1 + 10 + 3 + + + false + multi_npu_platform_01 + 10.0.0.8 + 05T2 + 10.0.0.9 + 1 + 10 + 3 + + + multi_npu_platform_01 + FC00::9 + 05T2 + FC00::A + 1 + 10 + 3 + + + BGPSession + false + ASIC2 + 10.1.0.0 + ASIC0 + 10.1.0.1 + 1 + 0 + 0 + + + BGPSession + false + ASIC2 + 10.1.0.4 + ASIC1 + 10.1.0.5 + 1 + 0 + 0 + + + BGPSession + false + ASIC3 + 10.1.0.2 + ASIC0 + 10.1.0.3 + 1 + 0 + 0 + + + BGPSession + false + ASIC3 + 10.1.0.6 + ASIC1 + 10.1.0.7 + 1 + 0 + 0 + + + false + ASIC0 + 10.0.0.0 + 01T2 + 10.0.0.1 + 1 + 10 + 3 + + + ASIC0 + FC00::1 + 01T2 + FC00::2 + 1 + 10 + 3 + + + false + ASIC1 + 10.0.0.8 + 05T2 + 10.0.0.9 + 1 + 10 + 3 + + + ASIC1 + FC00::9 + 05T2 + FC00::A + 1 + 10 + 3 + + + + + 65100 + multi_npu_platform_01 + + +
10.0.0.1
+ + + +
+ +
10.0.0.9
+ + + +
+
+ +
+ + 65100 + + ASIC0 + + + BGPPeer +
10.1.0.1
+ + + +
+ + BGPPeer +
10.1.0.3
+ + + +
+ + BGPPeer +
10.0.0.1
+ + + +
+ + BGPPeer +
FC00::1
+ + + +
+
+ +
+ + 65100 + + ASIC1 + + + BGPPeer +
10.1.0.5
+ + + +
+ + BGPPeer +
10.1.0.7
+ + + +
+ + BGPPeer +
10.0.0.9
+ + + +
+ + BGPPeer +
FC00::A
+ + + +
+
+ +
+ + 65100 + + ASIC2 + + + BGPPeer +
10.1.0.0
+ + + +
+ + BGPPeer +
10.1.0.4
+ + + +
+
+ +
+ + 65100 + + ASIC3 + + + BGPPeer +
10.1.0.2
+ + + +
+ + BGPPeer +
10.1.0.6
+ + + +
+
+ +
+ + 65200 + 01T2 + + + + 65200 + 05T2 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 3.10.147.150/23 + + 3.10.147.150/23 + + + V6HostIP + eth0 + + FC00:2::32/64 + + FC00:2::32/64 + + + + + + + multi_npu_platform_01 + + + PortChannel0002 + Ethernet1/1;Ethernet1/2 + + + + PortChannel0008 + Ethernet1/5;Ethernet1/6 + + + + + + + + PortChannel0002 + 10.0.0.0/31 + + + + PortChannel0002 + FC00::1/126 + + + + PortChannel0008 + 10.0.0.8/31 + + + + PortChannel0008 + FC00::9/126 + + + + + + SNMP_ACL + SNMP + SNMP + + + ERSPAN + Everflow + Everflow + + + ERSPANV6 + EverflowV6 + EverflowV6 + + + VTY_LINE + ssh-only + SSH + + + ;PortChannel0002;PortChannel0008 + DataAcl + DataPlane + + + + + + + + + + LoopbackInterface + HostIP + Loopback4096 + + 8.0.0.0/32 + + 8.0.0.0/32 + + + HostIP1 + Loopback4096 + + FD00:1::32/128 + + FD00:1::32/128 + + + + + + + + ASIC0 + + + PortChannelInterface + PortChannel4001 + Eth4-ASIC0;Eth5-ASIC0 + + + + PortChannelInterface + PortChannel4002 + Eth6-ASIC0;Eth7-ASIC0 + + + + PortChannelInterface + PortChannel0002 + Eth0-ASIC0;Eth1-ASIC0 + + + + + + + + IPInterface + + PortChannel4001 + 10.1.0.1/31 + + + IPInterface + + PortChannel4002 + 10.1.0.3/31 + + + + PortChannel0002 + 10.0.0.0/31 + + + + PortChannel0002 + FC00::1/126 + + + + + + + + + + + + LoopbackInterface + HostIP + Loopback4096 + + 8.0.0.1/32 + + 8.0.0.1/32 + + + HostIP1 + Loopback4096 + + FD00:2::32/128 + + FD00:2::32/128 + + + + + + + + ASIC1 + + + PortChannelInterface + PortChannel4003 + Eth4-ASIC1;Eth5-ASIC1 + + + + PortChannelInterface + PortChannel4004 + Eth6-ASIC1;Eth7-ASIC1 + + + + PortChannel0008 + Eth0-ASIC1;Eth1-ASIC1 + + + + + + + + IPInterface + + PortChannel4003 + 10.1.0.5/31 + + + IPInterface + + PortChannel4004 + 10.1.0.7/31 + + + + PortChannel0008 + 10.0.0.8/31 + + + + PortChannel0008 + FC00::9/126 + + + + + + + + + + + + LoopbackInterface + HostIP + Loopback4096 + + 8.0.0.4/32 + + 8.0.0.4/32 + + + HostIP1 + Loopback4096 + + FD00:3::32/128 + + FD00:3::32/128 + + + + + + + + ASIC2 + + + PortChannelInterface + PortChannel4009 + Eth0-ASIC2;Eth1-ASIC2 + + + + PortChannelInterface + PortChannel4010 + Eth2-ASIC2;Eth3-ASIC2 + + + + + + + + IPInterface + + PortChannel4009 + 10.1.0.0/31 + + + IPInterface + + PortChannel4010 + 10.1.0.4/31 + + + + + + + + + + + + LoopbackInterface + HostIP + Loopback4096 + + 8.0.0.5/32 + + 8.0.0.5/32 + + + HostIP1 + Loopback4096 + + FD00:4::32/128 + + FD00:4::32/128 + + + + + + + + ASIC3 + + + PortChannelInterface + PortChannel4013 + Eth0-ASIC3;Eth1-ASIC3 + + + + PortChannelInterface + PortChannel4014 + Eth2-ASIC3;Eth3-ASIC3 + + + + + + + + IPInterface + + PortChannel4013 + 10.1.0.2/31 + + + IPInterface + + PortChannel4014 + 10.1.0.6/31 + + + + + + + + + + + + DeviceInterfaceLink + 01T2 + Ethernet1 + multi_npu_platform_01 + Ethernet1/1 + + + DeviceInterfaceLink + 01T2 + Ethernet2 + multi_npu_platform_01 + Ethernet1/2 + + + DeviceInterfaceLink + 05T2 + Ethernet1 + multi_npu_platform_01 + Ethernet1/5 + + + DeviceInterfaceLink + 05T2 + Ethernet2 + multi_npu_platform_01 + Ethernet1/6 + + + DeviceInterfaceLink + 40000 + true + ASIC2 + Eth0-ASIC2 + true + ASIC0 + Eth4-ASIC0 + true + + + DeviceInterfaceLink + 40000 + true + ASIC2 + Eth1-ASIC2 + true + ASIC0 + Eth5-ASIC0 + true + + + DeviceInterfaceLink + 40000 + true + ASIC3 + Eth0-ASIC3 + true + ASIC0 + Eth6-ASIC0 + true + + + DeviceInterfaceLink + 40000 + true + ASIC3 + Eth1-ASIC3 + true + ASIC0 + Eth7-ASIC0 + true + + + DeviceInterfaceLink + 40000 + true + ASIC2 + Eth2-ASIC2 + true + ASIC1 + Eth4-ASIC1 + true + + + DeviceInterfaceLink + 40000 + true + ASIC2 + Eth3-ASIC2 + true + ASIC1 + Eth5-ASIC1 + true + + + DeviceInterfaceLink + 40000 + true + ASIC3 + Eth2-ASIC3 + true + ASIC1 + Eth6-ASIC1 + true + + + DeviceInterfaceLink + 40000 + true + ASIC3 + Eth3-ASIC3 + true + ASIC1 + Eth7-ASIC1 + true + + + DeviceInterfaceLink + 40000 + true + ASIC0 + Eth0-ASIC0 + true + multi_npu_platform_01 + Ethernet1/1 + true + + + DeviceInterfaceLink + 40000 + true + ASIC0 + Eth1-ASIC0 + true + multi_npu_platform_01 + Ethernet1/2 + true + + + DeviceInterfaceLink + 40000 + true + ASIC0 + Eth2-ASIC0 + true + multi_npu_platform_01 + Ethernet1/3 + true + + + DeviceInterfaceLink + 40000 + true + ASIC0 + Eth3-ASIC0 + true + multi_npu_platform_01 + Ethernet1/4 + true + + + DeviceInterfaceLink + 40000 + true + ASIC1 + Eth0-ASIC1 + true + multi_npu_platform_01 + Ethernet1/5 + true + + + DeviceInterfaceLink + 40000 + true + ASIC1 + Eth1-ASIC1 + true + multi_npu_platform_01 + Ethernet1/6 + true + + + DeviceInterfaceLink + 40000 + true + ASIC1 + Eth2-ASIC1 + true + multi_npu_platform_01 + Ethernet1/7 + true + + + DeviceInterfaceLink + 40000 + true + ASIC1 + Eth3-ASIC1 + true + multi_npu_platform_01 + Ethernet1/8 + true + + + + + multi_npu_platform_01 + multi-npu-01 + + 3.10.147.150 + + + + 07T2 + + 89.139.132.43 + + VM + + + 01T2 + + 89.139.132.40 + + VM + + + 05T2 + + 89.139.132.42 + + VM + + + 03T2 + + 89.139.132.41 + + VM + + + Asic +
+ 0.0.0.0/0 +
+ + ::/0 + + + + + + + + + + 0.0.0.0/0 + + + ::/0 + + + ASIC0 + multi-npu-asic +
+ + Asic +
+ 0.0.0.0/0 +
+ + ::/0 + + + + + + + + + + 0.0.0.0/0 + + + ::/0 + + + ASIC1 + multi-npu-asic +
+ + Asic +
+ 0.0.0.0/0 +
+ + ::/0 + + + + + + + + + + 0.0.0.0/0 + + + ::/0 + + + ASIC2 + multi-npu-asic +
+ + Asic +
+ 0.0.0.0/0 +
+ + ::/0 + + + + + + + + + + 0.0.0.0/0 + + + ::/0 + + + ASIC3 + multi-npu-asic +
+
+
+ + + true + + + DeviceInterface + + true + true + 1 + Ethernet1/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet1/2 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet1/3 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet1/4 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet1/5 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet1/6 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet1/7 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet1/8 + + false + 0 + 0 + 40000 + + + true + 0 + multi-npu-01 + + + + + + + multi_npu_platform_01 + + + DeploymentId + + 1 + + + QosProfile + + Profile0 + + + DhcpResources + + 169.118.23.1;169.118.23.2;169.118.23.3;169.118.23.4;169.118.23.5;169.118.23.6;169.118.23.7;169.118.23.8;169.118.23.9;169.118.23.10;169.118.23.11;169.118.23.12;169.118.23.13;169.118.23.14;169.118.23.15;169.118.23.16;169.118.23.17;169.118.23.18;169.118.23.19;169.118.23.20;169.118.23.21;169.118.23.22;169.118.23.23;169.118.23.24;169.118.23.25;169.118.23.26;169.118.23.27;169.118.23.28;169.118.23.29;169.118.23.30;169.118.23.31;169.118.23.32;169.118.23.33;169.118.23.34;169.118.23.35;169.118.23.36;169.118.23.37;169.118.23.38;169.118.23.39;169.118.23.40;169.118.23.41;169.118.23.42;169.118.23.43;169.118.23.44;169.118.23.45;169.118.23.46;169.118.23.47;169.118.23.48 + + + NtpResources + + 17.39.1.129;17.39.1.130 + + + SnmpResources + + 71.49.219.98 + + + SyslogResources + + 71.49.219.8;123.46.98.21 + + + TacacsGroup + + Starlab + + + TacacsServer + + 123.46.98.21 + + + ForcedMgmtRoutes + + 71.49.219.98/31;71.49.219.8;123.46.98.16/28;10.3.149.170/31;40.122.216.24;13.91.48.226;71.49.219.14 + + + ErspanDestinationIpv4 + + 10.20.6.16 + + + + + ASIC0 + + + SubRole + + FrontEnd + + + + + ASIC1 + + + SubRole + + FrontEnd + + + + + ASIC2 + + + SubRole + + FrontEnd + + + + + ASIC3 + + + SubRole + + FrontEnd + + + + + ASIC2 + + + SubRole + + BackEnd + + + + + ASIC3 + + + SubRole + + BackEnd + + + + + + + multi_npu_platform_01 + multi-npu-01 +
diff --git a/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-0.ini b/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-0.ini new file mode 100644 index 000000000000..b6b0379f6072 --- /dev/null +++ b/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-0.ini @@ -0,0 +1,9 @@ +# name lanes alias index asic_port_name role +Ethernet0 33,34,35,36 Ethernet1/1 0 Eth0-ASIC0 Ext +Ethernet4 29,30,31,32 Ethernet1/2 1 Eth1-ASIC0 Ext +Ethernet8 41,42,43,44 Ethernet1/3 2 Eth2-ASIC0 Ext +Ethernet12 37,38,39,40 Ethernet1/4 3 Eth3-ASIC0 Ext +Ethernet-BP0 13,14,15,16 Eth4-ASIC0 0 Eth4-ASIC0 Int +Ethernet-BP4 17,18,19,20 Eth5-ASIC0 1 Eth5-ASIC0 Int +Ethernet-BP8 21,22,23,24 Eth6-ASIC0 2 Eth6-ASIC0 Int +Ethernet-BP12 25,26,27,28 Eth7-ASIC0 3 Eth7-ASIC0 Int diff --git a/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-1.ini b/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-1.ini new file mode 100644 index 000000000000..a581b19fd61a --- /dev/null +++ b/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-1.ini @@ -0,0 +1,9 @@ +# name lanes alias index asic_port_name role +Ethernet16 33,34,35,36 Ethernet1/5 4 Eth0-ASIC1 Ext +Ethernet20 29,30,31,32 Ethernet1/6 5 Eth1-ASIC1 Ext +Ethernet24 41,42,43,44 Ethernet1/7 6 Eth2-ASIC1 Ext +Ethernet28 37,38,39,40 Ethernet1/8 7 Eth3-ASIC1 Ext +Ethernet-BP16 13,14,15,16 Eth4-ASIC1 4 Eth4-ASIC1 Int +Ethernet-BP20 17,18,19,20 Eth5-ASIC1 5 Eth5-ASIC1 Int +Ethernet-BP24 21,22,23,24 Eth6-ASIC1 6 Eth6-ASIC1 Int +Ethernet-BP28 25,26,27,28 Eth7-ASIC1 7 Eth7-ASIC1 Int diff --git a/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-2.ini b/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-2.ini new file mode 100644 index 000000000000..71467a9a6ec4 --- /dev/null +++ b/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-2.ini @@ -0,0 +1,9 @@ +# name lanes alias index asic_port_name role +Ethernet-BP256 61,62,63,64 Eth0-ASIC2 8 Eth0-ASIC2 Int +Ethernet-BP260 57,58,59,60 Eth1-ASIC2 9 Eth1-ASIC2 Int +Ethernet-BP264 53,54,55,56 Eth2-ASIC2 10 Eth2-ASIC2 Int +Ethernet-BP268 49,50,51,52 Eth3-ASIC2 11 Eth3-ASIC2 Int +Ethernet-BP272 45,46,47,48 Eth4-ASIC2 12 Eth4-ASIC2 Int +Ethernet-BP276 41,42,43,44 Eth5-ASIC2 13 Eth5-ASIC2 Int +Ethernet-BP280 37,38,39,40 Eth6-ASIC2 14 Eth6-ASIC2 Int +Ethernet-BP284 33,34,35,36 Eth7-ASIC2 15 Eth7-ASIC2 Int diff --git a/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-3.ini b/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-3.ini new file mode 100644 index 000000000000..e786bbdd8f62 --- /dev/null +++ b/src/sonic-config-engine/tests/multi_npu_data/sample_port_config-3.ini @@ -0,0 +1,9 @@ +# name lanes alias index asic_port_name role +Ethernet-BP384 29,30,31,32 Eth0-ASIC3 16 Eth0-ASIC3 Int +Ethernet-BP388 25,26,27,28 Eth1-ASIC3 17 Eth1-ASIC3 Int +Ethernet-BP392 21,22,23,24 Eth2-ASIC3 18 Eth2-ASIC3 Int +Ethernet-BP396 17,18,19,20 Eth3-ASIC3 19 Eth3-ASIC3 Int +Ethernet-BP400 13,14,15,16 Eth4-ASIC3 20 Eth4-ASIC3 Int +Ethernet-BP404 9,10,11,12 Eth5-ASIC3 21 Eth5-ASIC3 Int +Ethernet-BP408 5,6,7,8 Eth6-ASIC3 22 Eth6-ASIC3 Int +Ethernet-BP412 1,2,3,4 Eth7-ASIC3 23 Eth7-ASIC3 Int diff --git a/src/sonic-config-engine/tests/ndppd.conf.j2 b/src/sonic-config-engine/tests/ndppd.conf.j2 new file mode 120000 index 000000000000..e6f2f543eee4 --- /dev/null +++ b/src/sonic-config-engine/tests/ndppd.conf.j2 @@ -0,0 +1 @@ +../../../dockers/docker-orchagent/ndppd.conf.j2 \ No newline at end of file diff --git a/src/sonic-config-engine/tests/pc-test-graph.xml b/src/sonic-config-engine/tests/pc-test-graph.xml new file mode 100644 index 000000000000..6709d65c4969 --- /dev/null +++ b/src/sonic-config-engine/tests/pc-test-graph.xml @@ -0,0 +1,207 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/112;fortyGigE0/116;fortyGigE0/120;fortyGigE0/124 + + + + + + Vlan1000 + fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 + False + 0.0.0.0/0 + + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + Vlan1000 + 192.168.0.1/27 + + + + + + PortChannel01;PortChannel02;PortChannel03;PortChannel04 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1/1 + switch-t0 + fortyGigE0/112 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1/1 + switch-t0 + fortyGigE0/116 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1/1 + switch-t0 + fortyGigE0/120 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1/1 + switch-t0 + fortyGigE0/124 + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/sample-arista-7050-t0-minigraph.xml b/src/sonic-config-engine/tests/sample-arista-7050-t0-minigraph.xml new file mode 100644 index 000000000000..4fd1ba9ba128 --- /dev/null +++ b/src/sonic-config-engine/tests/sample-arista-7050-t0-minigraph.xml @@ -0,0 +1,907 @@ + + + + + + s7050-dev-1 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 10 + 3 + + + s7050-dev-1 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 10 + 3 + + + s7050-dev-1 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 10 + 3 + + + s7050-dev-1 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 10 + 3 + + + s7050-dev-1 + 10.0.0.60 + ARISTA03T1 + 10.0.0.61 + 1 + 10 + 3 + + + s7050-dev-1 + FC00::79 + ARISTA03T1 + FC00::7A + 1 + 10 + 3 + + + s7050-dev-1 + 10.0.0.62 + ARISTA04T1 + 10.0.0.63 + 1 + 10 + 3 + + + s7050-dev-1 + FC00::7D + ARISTA04T1 + FC00::7E + 1 + 10 + 3 + + + + + 65100 + s7050-dev-1 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+ +
10.0.0.61
+ + + +
+ +
10.0.0.63
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.243/23 + + 10.0.0.243/23 + + + + + + s7050-dev-1 + + + PortChannel0001 + Ethernet33 + + + + PortChannel0002 + Ethernet34 + + + + PortChannel0003 + Ethernet35 + + + + PortChannel0004 + Ethernet36 + + + + + + Vlan1000 + Ethernet6/1;Ethernet7/1;Ethernet8/1;Ethernet9/1;Ethernet10/1;Ethernet11/1;Ethernet12/1;Ethernet13/1;Ethernet14/1;Ethernet15/1;Ethernet16/1;Ethernet17/1;Ethernet18/1;Ethernet19/1;Ethernet20/1;Ethernet21/1;Ethernet22/1;Ethernet23/1;Ethernet24/1;Ethernet25/1;Ethernet26/1;Ethernet27/1;Ethernet28/1;Ethernet29 + False + 0.0.0.0/0 + + 1000 + 1000 + 192.168.0.0/21 + + + + + + PortChannel0001 + 10.0.0.56/31 + + + + PortChannel0001 + FC00::71/126 + + + + PortChannel0002 + 10.0.0.58/31 + + + + PortChannel0002 + FC00::75/126 + + + + PortChannel0003 + 10.0.0.60/31 + + + + PortChannel0003 + FC00::79/126 + + + + PortChannel0004 + 10.0.0.62/31 + + + + PortChannel0004 + FC00::7D/126 + + + + Vlan1000 + 192.168.0.1/21 + + + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1 + s7050-dev-1 + Ethernet33 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1 + s7050-dev-1 + Ethernet34 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1 + s7050-dev-1 + Ethernet35 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1 + s7050-dev-1 + Ethernet36 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet6/1 + Servers0 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet7/1 + Servers1 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet8/1 + Servers2 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet9/1 + Servers3 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet10/1 + Servers4 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet11/1 + Servers5 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet12/1 + Servers6 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet13/1 + Servers7 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet14/1 + Servers8 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet15/1 + Servers9 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet16/1 + Servers10 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet17/1 + Servers11 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet18/1 + Servers12 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet19/1 + Servers13 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet20/1 + Servers14 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet21/1 + Servers15 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet22/1 + Servers16 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet23/1 + Servers17 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet24/1 + Servers18 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet25/1 + Servers19 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet26/1 + Servers20 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet27/1 + Servers21 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet28/1 + Servers22 + eth0 + + + DeviceInterfaceLink + s7050-dev-1 + Ethernet29 + Servers23 + eth0 + + + + + s7050-dev-1 + Arista-7050-QX-32S + + 10.0.0.243 + + + + + + + true + + + DeviceInterface + + true + true + 1 + Ethernet5/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet6/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet7/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet8/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet9/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet10/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet11/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet12/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet13/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet14/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet15/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet16/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet17/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet18/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet19/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet20/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet21/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet22/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet23/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet24/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet25/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet26/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet27/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet28/1 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet29 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet30 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet31 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet32 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet33 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet34 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet35 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet36 + + false + 0 + 0 + 40000 + + + true + 0 + Arista-7050-QX-32S + + + + + + + s7050-dev-1 + + + ErspanDestinationIpv4 + + 10.0.0.16 + + + + + + + s7050-dev-1 + Arista-7050-QX-32S +
diff --git a/src/sonic-config-engine/tests/sample-dell-6100-t0-minigraph.xml b/src/sonic-config-engine/tests/sample-dell-6100-t0-minigraph.xml new file mode 100644 index 000000000000..536a2c8a73c7 --- /dev/null +++ b/src/sonic-config-engine/tests/sample-dell-6100-t0-minigraph.xml @@ -0,0 +1,770 @@ + + + + + + ARISTA01T1 + 10.0.0.1 + s6100-dev-1 + 10.0.0.0 + 1 + 180 + 60 + + + ARISTA02T1 + 10.0.0.5 + s6100-dev-1 + 10.0.0.4 + 1 + 180 + 60 + + + ARISTA03T1 + 10.0.0.9 + s6100-dev-1 + 10.0.0.8 + 1 + 180 + 60 + + + ARISTA04T1 + 10.0.0.13 + s6100-dev-1 + 10.0.0.12 + 1 + 180 + 60 + + + ARISTA01T1 + FC00::2 + s6100-dev-1 + FC00::1 + 1 + 180 + 60 + + + ARISTA02T1 + FC00::A + s6100-dev-1 + FC00::9 + 1 + 180 + 60 + + + ARISTA03T1 + FC00::12 + s6100-dev-1 + FC00::11 + 1 + 180 + 60 + + + ARISTA04T1 + FC00::1A + s6100-dev-1 + FC00::19 + 1 + 180 + 60 + + + + + 64601 + s6100-dev-1 + + + BGPPeer +
10.0.0.1
+ + + +
+ + BGPPeer +
10.0.0.5
+ + + +
+ + BGPPeer +
10.0.0.9
+ + + +
+ + BGPPeer +
10.0.0.13
+ + + +
+ + BGPPeer +
FC00::2
+ + + +
+ + BGPPeer +
FC00::A
+ + + +
+ + BGPPeer +
FC00::12
+ + + +
+ + BGPPeer +
FC00::1A
+ + + +
+
+ +
+ + 64802 + ARISTA01T1 + + + + 64802 + ARISTA02T1 + + + + 64802 + ARISTA03T1 + + + + 64802 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.243/23 + + 10.0.0.243/23 + + + + + + s6100-dev-1 + + + PortChannelInterface + PortChannel1 + fortyGigE1/1/1;fortyGigE1/1/2 + + + + PortChannelInterface + PortChannel4 + fortyGigE1/1/5;fortyGigE1/1/6 + + + + PortChannelInterface + PortChannel16 + fortyGigE1/2/1;fortyGigE1/2/2 + + + + PortChannelInterface + PortChannel20 + fortyGigE1/2/5;fortyGigE1/2/6 + + + + + + VlanInterface + Vlan2 + fortyGigE1/1/7;fortyGigE1/1/8;fortyGigE1/1/9;fortyGigE1/1/10;fortyGigE1/1/11;fortyGigE1/1/12;fortyGigE1/1/13;fortyGigE1/1/14;fortyGigE1/1/15;fortyGigE1/1/16;fortyGigE1/3/1;fortyGigE1/3/5;fortyGigE1/3/6;fortyGigE1/3/7;fortyGigE1/3/8;fortyGigE1/3/9;fortyGigE1/3/10;fortyGigE1/3/11;fortyGigE1/2/7;fortyGigE1/2/8;fortyGigE1/2/9;fortyGigE1/2/10;fortyGigE1/2/11;fortyGigE1/2/12;fortyGigE1/2/13;fortyGigE1/2/14;fortyGigE1/2/15;fortyGigE1/2/16;fortyGigE1/4/1;fortyGigE1/4/5;fortyGigE1/4/6;fortyGigE1/4/7;fortyGigE1/4/8;fortyGigE1/4/9;fortyGigE1/4/10;fortyGigE1/4/11 + False + 0.0.0.0/0 + + 2 + 2 + 172.0.0.0/21 + + + + + IPInterface + + PortChannel1 + 10.0.0.0/31 + + + IPInterface + + PortChannel4 + 10.0.0.4/31 + + + IPInterface + + PortChannel16 + 10.0.0.8/31 + + + IPInterface + + PortChannel20 + 10.0.0.12/31 + + + IPInterface + + PortChannel1 + FC00::1/126 + + + IPInterface + + PortChannel4 + FC00::9/126 + + + IPInterface + + PortChannel16 + FC00::11/126 + + + IPInterface + + PortChannel20 + FC00::19/126 + + + IPInterface + + Vlan2 + 172.0.0.1/21 + + + + + + + + + + + + DeviceInterfaceLink + true + 40000 + ARISTA01T1 + Ethernet1 + true + s6100-dev-1 + fortyGigE1/1/1 + + + DeviceInterfaceLink + true + 40000 + ARISTA01T1 + Ethernet2 + true + s6100-dev-1 + fortyGigE1/1/2 + + + DeviceInterfaceLink + true + 40000 + ARISTA02T1 + Ethernet1 + true + s6100-dev-1 + fortyGigE1/1/5 + + + DeviceInterfaceLink + true + 40000 + ARISTA02T1 + Ethernet2 + true + s6100-dev-1 + fortyGigE1/1/6 + + + DeviceInterfaceLink + true + 40000 + ARISTA03T1 + Ethernet1 + true + s6100-dev-1 + fortyGigE1/2/1 + + + DeviceInterfaceLink + true + 40000 + ARISTA03T1 + Ethernet2 + true + s6100-dev-1 + fortyGigE1/2/2 + + + DeviceInterfaceLink + true + 40000 + ARISTA04T1 + Ethernet1 + true + s6100-dev-1 + fortyGigE1/2/5 + + + DeviceInterfaceLink + true + 40000 + ARISTA04T1 + Ethernet2 + true + s6100-dev-1 + fortyGigE1/2/6 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/7 + true + server-01 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/8 + true + server-02 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/9 + true + server-03 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/10 + true + server-04 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/11 + true + server-05 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/12 + true + server-06 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/13 + true + server-07 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/14 + true + server-08 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/15 + true + server-09 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/1/16 + true + server-10 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/1 + true + server-11 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/5 + true + server-12 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/6 + true + server-13 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/7 + true + server-14 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/8 + true + server-15 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/9 + true + server-16 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/10 + true + server-17 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/3/11 + true + server-18 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/7 + true + server-19 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/8 + true + server-20 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/9 + true + server-21 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/10 + true + server-22 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/11 + true + server-23 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/12 + true + server-24 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/13 + true + server-25 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/14 + true + server-26 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/15 + true + server-27 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/2/16 + true + server-28 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/1 + true + server-29 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/5 + true + server-30 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/6 + true + server-31 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/7 + true + server-32 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/8 + true + server-33 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/9 + true + server-34 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/10 + true + server-35 + 0 + + + DeviceInterfaceLink + true + 40000 + s6100-dev-1 + fortyGigE1/4/11 + true + server-36 + 0 + + + + + s6100-dev-1 + Force10-S6100 + + 10.0.0.243 + + + + + + + + s6100-dev-1 + + + ErspanDestinationIpv4 + + 10.0.0.16 + + + + + + + s6100-dev-1 + Force10-S6100 +
\ No newline at end of file diff --git a/src/sonic-config-engine/tests/sample-port-config-mlnx.ini b/src/sonic-config-engine/tests/sample-port-config-mlnx.ini new file mode 100644 index 000000000000..816bb0e94a70 --- /dev/null +++ b/src/sonic-config-engine/tests/sample-port-config-mlnx.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 0,1,2,3 +Ethernet4 4,5,6,7 +Ethernet8 8,9,10,11 +Ethernet12 12,13,14,15 +Ethernet16 16,17,18,19 +Ethernet20 20,21,22,23 +Ethernet24 24,25,26,27 +Ethernet28 28,29,30,31 +Ethernet32 32,33,34,35 +Ethernet36 36,37,38,39 +Ethernet40 40,41,42,43 +Ethernet44 44,45,46,47 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 64,65,66,67 +Ethernet68 68,69,70,71 +Ethernet72 72,73,74,75 +Ethernet76 76,77,78,79 +Ethernet80 80,81,82,83 +Ethernet84 84,85,86,87 +Ethernet88 88,89,90,91 +Ethernet92 92,93,94,95 +Ethernet96 96,97,98,99 +Ethernet100 100,101,102,103 +Ethernet104 104,105,106,107 +Ethernet108 108,109,110,111 +Ethernet112 112,113,114,115 +Ethernet116 116,117,118,119 +Ethernet120 120,121,122,123 +Ethernet124 124,125,126,127 diff --git a/src/sonic-config-engine/tests/sample-template-1.json.j2 b/src/sonic-config-engine/tests/sample-template-1.json.j2 new file mode 100644 index 000000000000..96051b502fb7 --- /dev/null +++ b/src/sonic-config-engine/tests/sample-template-1.json.j2 @@ -0,0 +1,4 @@ +{ + "jk1_1": "{{ key1_1 }}", + "jk1_2": "{{ key1_2 }}" +} diff --git a/src/sonic-config-engine/tests/sample-template-2.json.j2 b/src/sonic-config-engine/tests/sample-template-2.json.j2 new file mode 100644 index 000000000000..3de91ab36edb --- /dev/null +++ b/src/sonic-config-engine/tests/sample-template-2.json.j2 @@ -0,0 +1,4 @@ +{ + "jk2_1": "{{ key2_1 }}", + "jk2_2": "{{ key2_2 }}" +} diff --git a/src/sonic-config-engine/tests/sample_graph.xml b/src/sonic-config-engine/tests/sample_graph.xml new file mode 100644 index 000000000000..47efabf7d81c --- /dev/null +++ b/src/sonic-config-engine/tests/sample_graph.xml @@ -0,0 +1,129 @@ + + + + + + OCPSCH0104001MS + 10.10.1.14 + OCPSCH01040DDLF + 10.10.1.13 + 1 + 10 + 3 + + + OCPSCH0104002MS + 10.10.2.14 + OCPSCH01040DDLF + 10.10.2.13 + 1 + 10 + 3 + + + + + 64536 + OCPSCH01040DDLF + + +
10.10.1.14
+ + +
+ +
10.10.2.14
+ + +
+
+ +
+ + 64542 + OCPSCH0104001MS + + + + 64543 + OCPSCH0104002MS + + +
+
+ + + + + + HostIP + Loopback0 + + 100.0.0.6/32 + + 100.0.0.6/32 + + + + + ManagementIP1 + Management0 + + 192.168.200.15/24 + + 192.168.200.15/24 + + + + + + OCPSCH01040DDLF + + + + + + Ethernet0 + 10.10.1.13/30 + + + + Ethernet1 + 10.10.2.13/30 + + + + + + + + + + + + 40000 + DeviceInterfaceLink + OCPSCH01040DDLF + Ethernet0 + OCPSCH0104012MS + Ethernet12 + + + 40000 + DeviceInterfaceLink + OCPCH01040DDLF + Ethernet1 + OCPSCH0104002MS + Ethernet12 + + + + + OCPSCH01040DDLF + Force10-Z9100 + + + + OCPSCH01040DDLF + Force10-Z9100 +
diff --git a/src/sonic-config-engine/tests/sample_hwsku.json b/src/sonic-config-engine/tests/sample_hwsku.json new file mode 100644 index 000000000000..b4864d40eb11 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet4": { + "default_brkout_mode": "2x50G" + }, + "Ethernet8": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet12": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet16": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet24": { + "default_brkout_mode": "2x50G" + }, + "Ethernet28": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet32": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet36": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet44": { + "default_brkout_mode": "2x50G[40G,25G,10G,1G]" + }, + "Ethernet48": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet52": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet56": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet64": { + "default_brkout_mode": "2x50G" + }, + "Ethernet68": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet72": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet76": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet84": { + "default_brkout_mode": "2x50G" + }, + "Ethernet88": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet92": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet96": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet104": { + "default_brkout_mode": "2x50G" + }, + "Ethernet108": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet112": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet116": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet124": { + "default_brkout_mode": "2x50G" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/msn27.32ports.json b/src/sonic-config-engine/tests/sample_output/msn27.32ports.json new file mode 100644 index 000000000000..fd457c4be9b4 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/msn27.32ports.json @@ -0,0 +1,120 @@ +{ + "CABLE_LENGTH": { + "AZURE": { + "Ethernet0": "300m", + "Ethernet4": "300m", + "Ethernet8": "300m", + "Ethernet12": "300m", + "Ethernet16": "300m", + "Ethernet20": "300m", + "Ethernet24": "300m", + "Ethernet28": "300m", + "Ethernet32": "300m", + "Ethernet36": "300m", + "Ethernet40": "300m", + "Ethernet44": "300m", + "Ethernet48": "300m", + "Ethernet52": "300m", + "Ethernet56": "300m", + "Ethernet60": "300m", + "Ethernet64": "300m", + "Ethernet68": "300m", + "Ethernet72": "300m", + "Ethernet76": "300m", + "Ethernet80": "300m", + "Ethernet84": "300m", + "Ethernet88": "300m", + "Ethernet92": "300m", + "Ethernet96": "300m", + "Ethernet100": "300m", + "Ethernet104": "300m", + "Ethernet108": "300m", + "Ethernet112": "300m", + "Ethernet116": "300m", + "Ethernet120": "300m", + "Ethernet124": "300m" + } + }, + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "2097152", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "5242880", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "16777152", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "5242880", + "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" + }, + "pg_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + }, + "q_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "dynamic_th":"7" + }, + "q_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"0", + "dynamic_th":"3" + } + }, + "BUFFER_PORT_INGRESS_PROFILE_LIST": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "profile_list" : "[BUFFER_PROFILE|ingress_lossless_profile],[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + "BUFFER_PORT_EGRESS_PROFILE_LIST": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "profile_list" : "[BUFFER_PROFILE|egress_lossless_profile],[BUFFER_PROFILE|egress_lossy_profile]" + } + }, + "BUFFER_PG": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0-1": { + "profile" : "[BUFFER_PROFILE|pg_lossy_profile]" + } + }, + "BUFFER_QUEUE": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4": { + "profile" : "[BUFFER_PROFILE|q_lossless_profile]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/platform_output.json b/src/sonic-config-engine/tests/sample_output/platform_output.json new file mode 100644 index 000000000000..bcc0f3468caa --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/platform_output.json @@ -0,0 +1,819 @@ +{ + "Ethernet8": { + "index": "3", + "lanes": "8", + "description": "Eth3/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth3/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet9": { + "index": "3", + "lanes": "9", + "description": "Eth3/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth3/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet36": { + "index": "10", + "lanes": "36,37", + "description": "Eth10/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth10/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet98": { + "index": "25", + "lanes": "98", + "description": "Eth25/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth25/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet0": { + "index": "1", + "lanes": "0,1,2,3", + "fec": "rs", + "description": "Eth1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth1", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet6": { + "index": "2", + "lanes": "6,7", + "description": "Eth2/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth2/2", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet4": { + "index": "2", + "lanes": "4,5", + "description": "Eth2/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth2/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet109": { + "index": "28", + "lanes": "109", + "description": "Eth28/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth28/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet108": { + "index": "28", + "lanes": "108", + "description": "Eth28/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth28/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet18": { + "index": "5", + "lanes": "18", + "description": "Eth5/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth5/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet100": { + "index": "26", + "lanes": "100,101,102,103", + "fec": "rs", + "description": "Eth26", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth26", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet34": { + "index": "9", + "lanes": "34,35", + "description": "Eth9/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth9/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet104": { + "index": "27", + "lanes": "104,105", + "description": "Eth27/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth27/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet106": { + "index": "27", + "lanes": "106,107", + "description": "Eth27/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth27/2", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet94": { + "index": "24", + "lanes": "94,95", + "description": "Eth24/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth24/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet126": { + "index": "32", + "lanes": "126,127", + "description": "Eth32/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth32/2", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet96": { + "index": "25", + "lanes": "96,97", + "description": "Eth25/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth25/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet124": { + "index": "32", + "lanes": "124,125", + "description": "Eth32/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth32/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet90": { + "index": "23", + "lanes": "90", + "description": "Eth23/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth23/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet91": { + "index": "23", + "lanes": "91", + "description": "Eth23/4", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth23/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet92": { + "index": "24", + "lanes": "92", + "description": "Eth24/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth24/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet93": { + "index": "24", + "lanes": "93", + "description": "Eth24/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth24/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet50": { + "index": "13", + "lanes": "50", + "description": "Eth13/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth13/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet51": { + "index": "13", + "lanes": "51", + "description": "Eth13/4", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth13/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet52": { + "index": "14", + "lanes": "52", + "description": "Eth14/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth14/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet53": { + "index": "14", + "lanes": "53", + "description": "Eth14/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth14/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet54": { + "index": "14", + "lanes": "54,55", + "description": "Eth14/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth14/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet99": { + "index": "25", + "lanes": "99", + "description": "Eth25/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth25/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet56": { + "index": "15", + "lanes": "56,57", + "description": "Eth15/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth15/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet113": { + "index": "29", + "lanes": "113", + "description": "Eth29/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth29/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet76": { + "index": "20", + "lanes": "76,77", + "description": "Eth20/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth20/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet74": { + "index": "19", + "lanes": "74,75", + "description": "Eth19/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth19/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet39": { + "index": "10", + "lanes": "39", + "description": "Eth10/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth10/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet72": { + "index": "19", + "lanes": "72", + "description": "Eth19/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth19/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet73": { + "index": "19", + "lanes": "73", + "description": "Eth19/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth19/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet70": { + "index": "18", + "lanes": "70", + "description": "Eth18/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth18/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet71": { + "index": "18", + "lanes": "71", + "description": "Eth18/4", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth18/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet32": { + "index": "9", + "lanes": "32", + "description": "Eth9/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth9/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet33": { + "index": "9", + "lanes": "33", + "description": "Eth9/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth9/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet16": { + "index": "5", + "lanes": "16,17", + "description": "Eth5/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth5/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet111": { + "index": "28", + "lanes": "111", + "description": "Eth28/4", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth28/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet10": { + "index": "3", + "lanes": "10", + "description": "Eth3/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth3/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet11": { + "index": "3", + "lanes": "11", + "description": "Eth3/4", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth3/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet12": { + "index": "4", + "lanes": "12", + "description": "Eth4/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth4/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet13": { + "index": "4", + "lanes": "13", + "description": "Eth4/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth4/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet58": { + "index": "15", + "lanes": "58", + "description": "Eth15/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth15/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet19": { + "index": "5", + "lanes": "19", + "description": "Eth5/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth5/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet59": { + "index": "15", + "lanes": "59", + "description": "Eth15/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth15/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet38": { + "index": "10", + "lanes": "38", + "description": "Eth10/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth10/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet78": { + "index": "20", + "lanes": "78", + "description": "Eth20/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth20/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet68": { + "index": "18", + "lanes": "68", + "description": "Eth18/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth18/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet14": { + "index": "4", + "lanes": "14,15", + "description": "Eth4/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth4/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet89": { + "index": "23", + "lanes": "89", + "description": "Eth23/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth23/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet88": { + "index": "23", + "lanes": "88", + "description": "Eth23/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth23/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet118": { + "index": "30", + "lanes": "118", + "description": "Eth30/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth30/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet119": { + "index": "30", + "lanes": "119", + "description": "Eth30/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth30/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet116": { + "index": "30", + "lanes": "116,117", + "description": "Eth30/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth30/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet114": { + "index": "29", + "lanes": "114,115", + "description": "Eth29/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth29/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet80": { + "index": "21", + "lanes": "80,81,82,83", + "fec": "rs", + "description": "Eth21", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth21", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet112": { + "index": "29", + "lanes": "112", + "description": "Eth29/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth29/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet86": { + "index": "22", + "lanes": "86,87", + "description": "Eth22/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth22/2", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet110": { + "index": "28", + "lanes": "110", + "description": "Eth28/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth28/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet84": { + "index": "22", + "lanes": "84,85", + "description": "Eth22/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth22/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet31": { + "index": "8", + "lanes": "31", + "description": "Eth8/4", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth8/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet49": { + "index": "13", + "lanes": "49", + "description": "Eth13/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth13/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet48": { + "index": "13", + "lanes": "48", + "description": "Eth13/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth13/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet46": { + "index": "12", + "lanes": "46,47", + "description": "Eth12/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth12/2", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet30": { + "index": "8", + "lanes": "30", + "description": "Eth8/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth8/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet29": { + "index": "8", + "lanes": "29", + "description": "Eth8/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth8/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet40": { + "index": "11", + "lanes": "40,41,42,43", + "fec": "rs", + "description": "Eth11", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth11", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet120": { + "index": "31", + "lanes": "120,121,122,123", + "fec": "rs", + "description": "Eth31", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth31", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet28": { + "index": "8", + "lanes": "28", + "description": "Eth8/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth8/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet66": { + "index": "17", + "lanes": "66,67", + "description": "Eth17/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth17/2", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet60": { + "index": "16", + "lanes": "60,61,62,63", + "fec": "rs", + "description": "Eth16", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth16", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet64": { + "index": "17", + "lanes": "64,65", + "description": "Eth17/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth17/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet44": { + "index": "12", + "lanes": "44,45", + "description": "Eth12/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth12/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet20": { + "index": "6", + "lanes": "20,21,22,23", + "fec": "rs", + "description": "Eth6", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth6", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet79": { + "index": "20", + "lanes": "79", + "description": "Eth20/3", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth20/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet69": { + "index": "18", + "lanes": "69", + "description": "Eth18/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth18/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet24": { + "index": "7", + "lanes": "24,25", + "description": "Eth7/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth7/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet26": { + "index": "7", + "lanes": "26,27", + "description": "Eth7/2", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth7/2", + "pfc_asym": "off", + "speed": "50000" + } +} diff --git a/src/sonic-config-engine/tests/sample_output/py2/bgpd_frr.conf b/src/sonic-config-engine/tests/sample_output/py2/bgpd_frr.conf new file mode 100644 index 000000000000..a312e7532620 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/bgpd_frr.conf @@ -0,0 +1,74 @@ +! +! template: bgpd/bgpd.conf.j2 +! +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname switch-t0 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +agentx +! +! +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 10.1.0.32/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00:1::/64 +! +ip prefix-list LOCAL_VLAN_IPV4_PREFIX seq 5 permit 192.168.0.0/27 +! +! +! +router bgp 65100 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 10.1.0.32 +! + network 10.1.0.32/32 +! + address-family ipv6 + network fc00:1::32/64 + exit-address-family +! + network 192.168.0.1/27 +! +! +! + address-family ipv4 + maximum-paths 64 + exit-address-family + address-family ipv6 + maximum-paths 64 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +!! +! end of template: bgpd/bgpd.conf.j2 +! diff --git a/src/sonic-config-engine/tests/sample_output/py2/bgpd_quagga.conf b/src/sonic-config-engine/tests/sample_output/py2/bgpd_quagga.conf new file mode 100644 index 000000000000..f75d9de9a30e --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/bgpd_quagga.conf @@ -0,0 +1,100 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +! +hostname switch-t0 +password zebra +log syslog informational +log facility local4 +! enable password ! +! +! bgp multiple-instance +! +route-map FROM_BGP_SPEAKER_V4 permit 10 +! +route-map TO_BGP_SPEAKER_V4 deny 10 +! +router bgp 65100 + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp router-id 10.1.0.32 + address-family ipv6 + network fc00:1::32/64 + exit-address-family + network 10.1.0.32/32 + network 192.168.0.1/27 + neighbor 10.0.0.59 remote-as 64600 + neighbor 10.0.0.59 description ARISTA02T1 + address-family ipv4 + neighbor 10.0.0.59 allowas-in 1 + neighbor 10.0.0.59 activate + neighbor 10.0.0.59 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.61 remote-as 64600 + neighbor 10.0.0.61 description ARISTA03T1 + address-family ipv4 + neighbor 10.0.0.61 allowas-in 1 + neighbor 10.0.0.61 activate + neighbor 10.0.0.61 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.63 remote-as 64600 + neighbor 10.0.0.63 description ARISTA04T1 + address-family ipv4 + neighbor 10.0.0.63 allowas-in 1 + neighbor 10.0.0.63 activate + neighbor 10.0.0.63 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::7e remote-as 64600 + neighbor fc00::7e description ARISTA04T1 + address-family ipv6 + neighbor fc00::7e allowas-in 1 + neighbor fc00::7e activate + neighbor fc00::7e soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::7a remote-as 64600 + neighbor fc00::7a description ARISTA03T1 + address-family ipv6 + neighbor fc00::7a allowas-in 1 + neighbor fc00::7a activate + neighbor fc00::7a soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.57 remote-as 64600 + neighbor 10.0.0.57 description ARISTA01T1 + address-family ipv4 + neighbor 10.0.0.57 allowas-in 1 + neighbor 10.0.0.57 activate + neighbor 10.0.0.57 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::76 remote-as 64600 + neighbor fc00::76 description ARISTA02T1 + address-family ipv6 + neighbor fc00::76 allowas-in 1 + neighbor fc00::76 activate + neighbor fc00::76 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::72 remote-as 64600 + neighbor fc00::72 description ARISTA01T1 + address-family ipv6 + neighbor fc00::72 allowas-in 1 + neighbor fc00::72 activate + neighbor fc00::72 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family +! +maximum-paths 64 +! +route-map ISOLATE permit 10 +set as-path prepend 65100 +! diff --git a/src/sonic-config-engine/tests/sample_output/py2/buffers-dell6100.json b/src/sonic-config-engine/tests/sample_output/py2/buffers-dell6100.json new file mode 100644 index 000000000000..56de7500c1ad --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/buffers-dell6100.json @@ -0,0 +1,640 @@ + +{ + "CABLE_LENGTH": { + "AZURE": { + "Ethernet8": "5m", + "Ethernet9": "5m", + "Ethernet2": "5m", + "Ethernet3": "5m", + "Ethernet0": "5m", + "Ethernet1": "5m", + "Ethernet6": "5m", + "Ethernet7": "5m", + "Ethernet4": "5m", + "Ethernet5": "5m", + "Ethernet46": "5m", + "Ethernet34": "5m", + "Ethernet22": "5m", + "Ethernet58": "5m", + "Ethernet59": "5m", + "Ethernet50": "5m", + "Ethernet51": "5m", + "Ethernet52": "5m", + "Ethernet53": "5m", + "Ethernet54": "5m", + "Ethernet55": "5m", + "Ethernet56": "5m", + "Ethernet57": "5m", + "Ethernet38": "5m", + "Ethernet39": "5m", + "Ethernet18": "5m", + "Ethernet19": "5m", + "Ethernet14": "5m", + "Ethernet15": "5m", + "Ethernet16": "5m", + "Ethernet17": "5m", + "Ethernet10": "5m", + "Ethernet11": "5m", + "Ethernet12": "5m", + "Ethernet35": "5m", + "Ethernet37": "5m", + "Ethernet32": "5m", + "Ethernet33": "5m", + "Ethernet30": "5m", + "Ethernet31": "5m", + "Ethernet49": "5m", + "Ethernet48": "5m", + "Ethernet47": "5m", + "Ethernet36": "5m", + "Ethernet45": "5m", + "Ethernet44": "5m", + "Ethernet43": "5m", + "Ethernet42": "5m", + "Ethernet41": "5m", + "Ethernet40": "5m", + "Ethernet29": "5m", + "Ethernet28": "5m", + "Ethernet61": "5m", + "Ethernet60": "5m", + "Ethernet63": "5m", + "Ethernet62": "5m", + "Ethernet21": "5m", + "Ethernet20": "5m", + "Ethernet23": "5m", + "Ethernet13": "5m", + "Ethernet25": "5m", + "Ethernet24": "5m", + "Ethernet27": "5m", + "Ethernet26": "5m" + } + }, + + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "Ethernet8|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet9|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet0|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet1|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet6|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet7|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet4|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet5|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet58|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet52|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet53|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet54|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet55|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet56|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet57|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet38|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet39|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet32|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet15|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet16|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet17|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet36|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet37|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet12|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet13|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet14|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet30|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet31|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet48|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet10|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet42|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet41|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet40|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet29|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet28|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet11|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet21|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet20|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet23|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet22|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet25|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet24|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet27|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet26|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + + "BUFFER_QUEUE": { + "Ethernet8|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet9|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet0|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet1|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet6|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet7|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet4|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet5|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet58|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet52|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet53|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet54|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet55|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet56|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet57|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet38|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet39|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet32|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet15|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet16|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet17|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet36|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet37|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet12|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet13|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet14|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet30|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet31|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet48|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet10|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet42|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet41|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet40|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet29|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet28|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet11|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet21|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet20|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet23|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet22|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet25|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet24|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet27|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet26|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet8|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet9|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet0|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet1|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet6|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet7|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet4|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet5|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet58|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet52|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet53|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet54|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet55|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet56|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet57|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet38|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet39|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet32|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet15|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet16|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet17|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet36|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet37|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet12|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet13|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet14|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet30|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet31|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet48|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet10|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet42|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet41|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet40|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet29|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet28|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet11|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet21|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet20|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet23|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet22|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet25|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet24|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet27|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet26|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet8|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet9|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet0|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet1|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet6|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet7|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet4|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet5|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet58|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet52|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet53|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet54|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet55|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet56|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet57|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet38|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet39|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet32|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet15|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet16|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet17|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet36|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet37|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet12|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet13|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet14|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet30|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet31|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet48|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet10|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet42|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet41|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet40|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet29|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet28|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet11|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet21|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet20|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet23|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet22|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet25|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet24|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet27|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet26|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf b/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf new file mode 100644 index 000000000000..dad758947f22 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf @@ -0,0 +1,69 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=50 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name dhcp_relay +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[group:isc-dhcp-relay] +programs=isc-dhcp-relay-Vlan1000 + +[program:isc-dhcp-relay-Vlan1000] +command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id Vlan1000 -iu PortChannel02 -iu PortChannel03 -iu PortChannel04 -iu PortChannel01 192.0.0.1 192.0.0.2 +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + + +[group:dhcpmon] +programs=dhcpmon-Vlan1000 + +[program:dhcpmon-Vlan1000] +command=/usr/sbin/dhcpmon -id Vlan1000 -iu PortChannel02 -iu PortChannel03 -iu PortChannel04 -iu PortChannel01 -im eth0 +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=isc-dhcp-relay-Vlan1000:running + + + diff --git a/src/sonic-config-engine/tests/sample_output/py2/frr.conf b/src/sonic-config-engine/tests/sample_output/py2/frr.conf new file mode 100644 index 000000000000..43df66c3f4e7 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/frr.conf @@ -0,0 +1,95 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr.conf.j2 with config DB data +! file: frr.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname switch-t0 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +agentx +! +! +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface PortChannel03 +link-detect +! +interface PortChannel02 +link-detect +! +interface PortChannel01 +link-detect +! +interface PortChannel04 +link-detect +! +!! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.0.0.1 200 +!! +! +! +! add static ipv6 /64 loopback route to allow bgpd to advertise the loopback route prefix +ipv6 route fc00:1::/64 Loopback0 +!! +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 10.1.0.32/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00:1::/64 +! +ip prefix-list LOCAL_VLAN_IPV4_PREFIX seq 5 permit 192.168.0.0/27 +! +! +! +router bgp 65100 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 10.1.0.32 +! + network 10.1.0.32/32 +! + address-family ipv6 + network fc00:1::32/64 + exit-address-family +! + network 192.168.0.1/27 +! +! +! + address-family ipv4 + maximum-paths 64 + exit-address-family + address-family ipv6 + maximum-paths 64 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +!! diff --git a/src/sonic-config-engine/tests/sample_output/py2/interfaces b/src/sonic-config-engine/tests/sample_output/py2/interfaces new file mode 100644 index 000000000000..6e952d6f71ea --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/interfaces @@ -0,0 +1,46 @@ +# +# =============== Managed by SONiC Config Engine DO NOT EDIT! =============== +# generated from /usr/share/sonic/templates/interfaces.j2 using sonic-cfggen +# file: /etc/network/interfaces +# +# The loopback network interface +auto lo +iface lo inet loopback + address 127.0.0.1 + netmask 255.255.0.0 + post-up ip addr del 127.0.0.1/8 dev lo + +# The management network interface +auto eth0 +iface eth0 inet static + address 10.0.0.100 + netmask 255.255.255.0 + network 10.0.0.0 + broadcast 10.0.0.255 + ########## management network policy routing rules + # management port up rules + up ip -4 route add default via 10.0.0.1 dev eth0 table default metric 201 + up ip -4 route add 10.0.0.0/24 dev eth0 table default + up ip -4 rule add pref 32765 from 10.0.0.100/32 table default + # management port down rules + pre-down ip -4 route delete default via 10.0.0.1 dev eth0 table default + pre-down ip -4 route delete 10.0.0.0/24 dev eth0 table default + pre-down ip -4 rule delete pref 32765 from 10.0.0.100/32 table default +iface eth0 inet6 static + address 2603:10e2:0:2902::8 + netmask 64 + network 2603:10e2:0:2902:: + broadcast 2603:10e2:0:2902:ffff:ffff:ffff:ffff + ########## management network policy routing rules + # management port up rules + up ip -6 route add default via 2603:10e2:0:2902::1 dev eth0 table default metric 201 + up ip -6 route add 2603:10e2:0:2902::/64 dev eth0 table default + up ip -6 rule add pref 32765 from 2603:10e2:0:2902::8/128 table default + # management port down rules + pre-down ip -6 route delete default via 2603:10e2:0:2902::1 dev eth0 table default + pre-down ip -6 route delete 2603:10e2:0:2902::/64 dev eth0 table default + pre-down ip -6 rule delete pref 32765 from 2603:10e2:0:2902::8/128 table default +# +source /etc/network/interfaces.d/* +# + diff --git a/src/sonic-config-engine/tests/sample_output/py2/ipinip.json b/src/sonic-config-engine/tests/sample_output/py2/ipinip.json new file mode 100644 index 000000000000..db70ea403121 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/ipinip.json @@ -0,0 +1,23 @@ +[ + { + "TUNNEL_DECAP_TABLE:IPINIP_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"10.0.0.56,10.0.0.58,10.0.0.60,10.0.0.62,10.1.0.32,192.168.0.1", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", + "ttl_mode":"pipe" + }, + "OP": "SET" + } + , + { + "TUNNEL_DECAP_TABLE:IPINIP_V6_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"fc00:1::32,fc00::71,fc00::75,fc00::79,fc00::7d", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", + "ttl_mode":"pipe" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/sample_output/py2/l2switch.json b/src/sonic-config-engine/tests/sample_output/py2/l2switch.json new file mode 100644 index 000000000000..1c9e0ebbcd2e --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/l2switch.json @@ -0,0 +1,268 @@ +{ + "DEVICE_METADATA": {"localhost": {"hwsku": "Mellanox-SN2700"}}, + "PORT": { + "Ethernet8": { + "alias": "fortyGigE0/8", + "lanes": "37,38,39,40", + "admin_status": "up" + }, + "Ethernet0": { + "alias": "fortyGigE0/0", + "lanes": "29,30,31,32", + "admin_status": "up" + }, + "Ethernet4": { + "alias": "fortyGigE0/4", + "lanes": "25,26,27,28", + "admin_status": "up" + }, + "Ethernet108": { + "alias": "fortyGigE0/108", + "lanes": "81,82,83,84", + "admin_status": "up" + }, + "Ethernet100": { + "alias": "fortyGigE0/100", + "lanes": "125,126,127,128", + "admin_status": "up" + }, + "Ethernet104": { + "alias": "fortyGigE0/104", + "lanes": "85,86,87,88", + "admin_status": "up" + }, + "Ethernet68": { + "alias": "fortyGigE0/68", + "lanes": "69,70,71,72", + "admin_status": "up" + }, + "Ethernet96": { + "alias": "fortyGigE0/96", + "lanes": "121,122,123,124", + "admin_status": "up" + }, + "Ethernet124": { + "alias": "fortyGigE0/124", + "lanes": "101,102,103,104", + "admin_status": "up" + }, + "Ethernet92": { + "alias": "fortyGigE0/92", + "lanes": "113,114,115,116", + "admin_status": "up" + }, + "Ethernet120": { + "alias": "fortyGigE0/120", + "lanes": "97,98,99,100", + "admin_status": "up" + }, + "Ethernet52": { + "alias": "fortyGigE0/52", + "lanes": "53,54,55,56", + "admin_status": "up" + }, + "Ethernet56": { + "alias": "fortyGigE0/56", + "lanes": "61,62,63,64", + "admin_status": "up" + }, + "Ethernet76": { + "alias": "fortyGigE0/76", + "lanes": "73,74,75,76", + "admin_status": "up" + }, + "Ethernet72": { + "alias": "fortyGigE0/72", + "lanes": "77,78,79,80", + "admin_status": "up" + }, + "Ethernet64": { + "alias": "fortyGigE0/64", + "lanes": "65,66,67,68", + "admin_status": "up" + }, + "Ethernet32": { + "alias": "fortyGigE0/32", + "lanes": "9,10,11,12", + "admin_status": "up" + }, + "Ethernet16": { + "alias": "fortyGigE0/16", + "lanes": "41,42,43,44", + "admin_status": "up" + }, + "Ethernet36": { + "alias": "fortyGigE0/36", + "lanes": "13,14,15,16", + "admin_status": "up" + }, + "Ethernet12": { + "alias": "fortyGigE0/12", + "lanes": "33,34,35,36", + "admin_status": "up" + }, + "Ethernet88": { + "alias": "fortyGigE0/88", + "lanes": "117,118,119,120", + "admin_status": "up" + }, + "Ethernet116": { + "alias": "fortyGigE0/116", + "lanes": "93,94,95,96", + "admin_status": "up" + }, + "Ethernet80": { + "alias": "fortyGigE0/80", + "lanes": "105,106,107,108", + "admin_status": "up" + }, + "Ethernet112": { + "alias": "fortyGigE0/112", + "lanes": "89,90,91,92", + "admin_status": "up" + }, + "Ethernet84": { + "alias": "fortyGigE0/84", + "lanes": "109,110,111,112", + "admin_status": "up" + }, + "Ethernet48": { + "alias": "fortyGigE0/48", + "lanes": "49,50,51,52", + "admin_status": "up" + }, + "Ethernet44": { + "alias": "fortyGigE0/44", + "lanes": "17,18,19,20", + "admin_status": "up" + }, + "Ethernet40": { + "alias": "fortyGigE0/40", + "lanes": "21,22,23,24", + "admin_status": "up" + }, + "Ethernet28": { + "alias": "fortyGigE0/28", + "lanes": "1,2,3,4", + "admin_status": "up" + }, + "Ethernet60": { + "alias": "fortyGigE0/60", + "lanes": "57,58,59,60", + "admin_status": "up" + }, + "Ethernet20": { + "alias": "fortyGigE0/20", + "lanes": "45,46,47,48", + "admin_status": "up" + }, + "Ethernet24": { + "alias": "fortyGigE0/24", + "lanes": "5,6,7,8", + "admin_status": "up" + } + }, + "VLAN": { + "Vlan1000": { + "vlanid": "1000" + } + }, + "VLAN_MEMBER": { + "Vlan1000|Ethernet8": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet0": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet4": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet108": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet100": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet104": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet68": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet96": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet124": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet92": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet120": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet52": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet56": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet76": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet72": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet64": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet32": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet16": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet36": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet12": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet88": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet116": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet80": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet112": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet84": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet48": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet44": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet40": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet28": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet60": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet20": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet24": { + "tagging_mode": "untagged" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/py2/lldp_conf/lldpd-ipv4-iface.conf b/src/sonic-config-engine/tests/sample_output/py2/lldp_conf/lldpd-ipv4-iface.conf new file mode 100644 index 000000000000..c9cb2c8123dd --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/lldp_conf/lldpd-ipv4-iface.conf @@ -0,0 +1,4 @@ +configure ports eth0 lldp portidsubtype local eth0 +configure system ip management pattern 10.0.0.100 +configure system hostname switch-t0 +pause diff --git a/src/sonic-config-engine/tests/sample_output/py2/lldp_conf/lldpd-ipv6-iface.conf b/src/sonic-config-engine/tests/sample_output/py2/lldp_conf/lldpd-ipv6-iface.conf new file mode 100644 index 000000000000..f5727556fdf3 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/lldp_conf/lldpd-ipv6-iface.conf @@ -0,0 +1,2 @@ +configure system hostname switch-t0 +pause diff --git a/src/sonic-config-engine/tests/sample_output/py2/mvrf_interfaces b/src/sonic-config-engine/tests/sample_output/py2/mvrf_interfaces new file mode 100644 index 000000000000..9e5c8a4261cf --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/mvrf_interfaces @@ -0,0 +1,61 @@ +# +# =============== Managed by SONiC Config Engine DO NOT EDIT! =============== +# generated from /usr/share/sonic/templates/interfaces.j2 using sonic-cfggen +# file: /etc/network/interfaces +# +auto mgmt +iface mgmt + vrf-table 5000 +# 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/16 dev lo-m + up ip link set lo-m up + down ip link delete dev lo-m +# The loopback network interface +auto lo +iface lo inet loopback + address 127.0.0.1 + netmask 255.255.0.0 + post-up ip addr del 127.0.0.1/8 dev lo + +# The management network interface +auto eth0 +iface eth0 inet static + address 10.0.0.100 + netmask 255.255.255.0 + network 10.0.0.0 + broadcast 10.0.0.255 + vrf mgmt + ########## management network policy routing rules + # management port up rules + up ip -4 route add default via 10.0.0.1 dev eth0 table 5000 metric 201 + up ip -4 route add 10.0.0.0/24 dev eth0 table 5000 + up ip -4 rule add pref 32765 from 10.0.0.100/32 table 5000 + up ip rule add pref 32764 to 11.11.11.11 table 5000 + up ip rule add pref 32764 to 22.22.22.0/23 table 5000 + # management port down rules + pre-down ip -4 route delete default via 10.0.0.1 dev eth0 table 5000 + pre-down ip -4 route delete 10.0.0.0/24 dev eth0 table 5000 + pre-down ip -4 rule delete pref 32765 from 10.0.0.100/32 table 5000 + pre-down ip rule delete pref 32764 to 11.11.11.11 table 5000 + pre-down ip rule delete pref 32764 to 22.22.22.0/23 table 5000 +iface eth0 inet6 static + address 2603:10e2:0:2902::8 + netmask 64 + network 2603:10e2:0:2902:: + broadcast 2603:10e2:0:2902:ffff:ffff:ffff:ffff + vrf mgmt + ########## management network policy routing rules + # management port up rules + up ip -6 route add default via 2603:10e2:0:2902::1 dev eth0 table 5000 metric 201 + up ip -6 route add 2603:10e2:0:2902::/64 dev eth0 table 5000 + up ip -6 rule add pref 32765 from 2603:10e2:0:2902::8/128 table 5000 + # management port down rules + pre-down ip -6 route delete default via 2603:10e2:0:2902::1 dev eth0 table 5000 + pre-down ip -6 route delete 2603:10e2:0:2902::/64 dev eth0 table 5000 + pre-down ip -6 rule delete pref 32765 from 2603:10e2:0:2902::8/128 table 5000 +# +source /etc/network/interfaces.d/* +# + diff --git a/src/sonic-config-engine/tests/sample_output/py2/ndppd.conf b/src/sonic-config-engine/tests/sample_output/py2/ndppd.conf new file mode 100644 index 000000000000..71ff1dfaf9ca --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/ndppd.conf @@ -0,0 +1,25 @@ +# =========== Managed by sonic-cfggen -- DO NOT edit manually! ==================== +# Generated by /usr/share/sonic/templates/ndppd.conf.j2 using config DB data +# File: /etc/ndppd.conf +# +# Config file for ndppd, the NDP Proxy Daemon +# See man page for ndppd.conf.5 for descriptions of all available options + +proxy Vlan1000 { + rule fc02:1000::/64 { + static + } + rule fc03:1000::/64 { + static + } + rule fc01:1000::/64 { + static + } +} + +proxy Vlan2000 { + rule fc01:2000::/64 { + static + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/py2/ports.json b/src/sonic-config-engine/tests/sample_output/py2/ports.json new file mode 100644 index 000000000000..0e174972fbe4 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/ports.json @@ -0,0 +1,30 @@ +[ + { + "PORT_TABLE:Ethernet8": { + "speed": "1000", + "description": "Interface description" + }, + "OP": "SET" + }, + { + "PORT_TABLE:Ethernet0": { + "speed": "10000", + "description": "fortyGigE0/0" + }, + "OP": "SET" + }, + { + "PORT_TABLE:Ethernet4": { + "speed": "25000", + "description": "fortyGigE0/4" + }, + "OP": "SET" + }, + { + "PORT_TABLE:Ethernet12": { + "speed": "100000", + "description": "Interface description" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/sample_output/py2/qos-arista7050.json b/src/sonic-config-engine/tests/sample_output/py2/qos-arista7050.json new file mode 100644 index 000000000000..aa05ef4ec36c --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/qos-arista7050.json @@ -0,0 +1,977 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "0", + "2": "0", + "3": "3", + "4": "4", + "5": "0", + "6": "0", + "7": "7" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0" : "1", + "1" : "1", + "2" : "1", + "3" : "3", + "4" : "4", + "5" : "2", + "6" : "1", + "7" : "1", + "8" : "0", + "9" : "1", + "10": "1", + "11": "1", + "12": "1", + "13": "1", + "14": "1", + "15": "1", + "16": "1", + "17": "1", + "18": "1", + "19": "1", + "20": "1", + "21": "1", + "22": "1", + "23": "1", + "24": "1", + "25": "1", + "26": "1", + "27": "1", + "28": "1", + "29": "1", + "30": "1", + "31": "1", + "32": "1", + "33": "1", + "34": "1", + "35": "1", + "36": "1", + "37": "1", + "38": "1", + "39": "1", + "40": "1", + "41": "1", + "42": "1", + "43": "1", + "44": "1", + "45": "1", + "46": "5", + "47": "1", + "48": "6", + "49": "1", + "50": "1", + "51": "1", + "52": "1", + "53": "1", + "54": "1", + "55": "1", + "56": "1", + "57": "1", + "58": "1", + "59": "1", + "60": "1", + "61": "1", + "62": "1", + "63": "1" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "14" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "15" + } + }, + "PORT_QOS_MAP": { + "Ethernet4": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet8": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet12": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet16": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet20": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet24": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet28": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet32": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet36": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet40": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet44": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet48": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet52": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet56": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet60": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet64": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet68": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet72": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet76": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet80": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet84": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet88": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet92": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet96": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet112": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet116": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet120": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet124": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "1048576", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, + "QUEUE": { + "Ethernet4|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet8|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet12|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet16|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet20|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet24|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet28|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet32|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet36|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet40|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet44|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet48|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet52|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet56|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet60|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet64|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet68|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet72|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet76|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet80|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet84|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet88|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet92|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet96|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet112|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet116|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet120|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet124|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet4|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet8|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet12|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet16|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet20|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet24|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet28|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet32|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet36|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet40|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet44|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet48|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet52|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet56|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet60|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet64|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet68|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet72|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet76|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet80|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet84|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet88|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet92|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet96|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet112|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet116|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet120|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet124|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet4|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet44|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet60|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet64|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet68|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet72|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet76|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet80|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet84|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet88|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet92|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet96|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet112|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet116|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet120|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet124|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet44|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet60|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet64|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet68|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet72|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet76|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet80|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet84|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet88|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet92|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet96|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet112|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet116|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet120|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet124|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet44|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet60|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet64|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet68|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet72|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet76|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet80|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet84|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet88|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet92|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet96|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet112|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet116|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet120|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet124|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet44|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet60|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet64|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet68|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet72|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet76|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet80|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet84|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet88|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet92|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet96|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet112|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet116|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet120|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet124|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet44|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet60|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet64|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet68|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet72|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet76|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet80|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet84|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet88|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet92|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet96|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet112|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet116|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet120|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet124|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/py2/qos-dell6100.json b/src/sonic-config-engine/tests/sample_output/py2/qos-dell6100.json new file mode 100644 index 000000000000..75d9b3a87eee --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/qos-dell6100.json @@ -0,0 +1,1457 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "0", + "2": "0", + "3": "3", + "4": "4", + "5": "0", + "6": "0", + "7": "7" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0" : "1", + "1" : "1", + "2" : "1", + "3" : "3", + "4" : "4", + "5" : "2", + "6" : "1", + "7" : "1", + "8" : "0", + "9" : "1", + "10": "1", + "11": "1", + "12": "1", + "13": "1", + "14": "1", + "15": "1", + "16": "1", + "17": "1", + "18": "1", + "19": "1", + "20": "1", + "21": "1", + "22": "1", + "23": "1", + "24": "1", + "25": "1", + "26": "1", + "27": "1", + "28": "1", + "29": "1", + "30": "1", + "31": "1", + "32": "1", + "33": "1", + "34": "1", + "35": "1", + "36": "1", + "37": "1", + "38": "1", + "39": "1", + "40": "1", + "41": "1", + "42": "1", + "43": "1", + "44": "1", + "45": "1", + "46": "5", + "47": "1", + "48": "6", + "49": "1", + "50": "1", + "51": "1", + "52": "1", + "53": "1", + "54": "1", + "55": "1", + "56": "1", + "57": "1", + "58": "1", + "59": "1", + "60": "1", + "61": "1", + "62": "1", + "63": "1" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "14" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "15" + } + }, + "PORT_QOS_MAP": { + "Ethernet0": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet1": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet4": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet5": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet6": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet7": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet8": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet9": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet10": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet11": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet12": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet13": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet14": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet15": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet16": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet17": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet20": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet21": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet22": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet23": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet24": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet25": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet26": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet27": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet28": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet29": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet30": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet31": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet32": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet36": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet37": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet38": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet39": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet40": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet41": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet42": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet48": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet52": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet53": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet54": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet55": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet56": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet57": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet58": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "250000", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, + "QUEUE": { + "Ethernet0|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet1|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet4|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet5|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet6|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet7|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet8|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet9|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet10|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet11|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet12|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet13|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet14|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet15|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet16|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet17|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet20|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet21|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet22|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet23|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet24|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet25|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet26|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet27|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet28|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet29|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet30|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet31|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet32|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet36|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet37|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet38|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet39|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet40|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet41|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet42|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet48|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet52|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet53|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet54|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet55|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet56|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet57|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet58|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet1|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet4|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet5|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet6|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet7|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet8|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet9|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet10|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet11|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet12|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet13|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet14|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet15|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet16|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet17|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet20|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet21|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet22|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet23|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet24|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet25|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet26|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet27|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet28|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet29|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet30|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet31|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet32|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet36|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet37|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet38|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet39|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet40|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet41|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet42|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet48|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet52|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet53|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet54|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet55|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet56|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet57|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet58|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet0|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet0|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet0|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet0|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/py2/staticd_frr.conf b/src/sonic-config-engine/tests/sample_output/py2/staticd_frr.conf new file mode 100644 index 000000000000..54d83525b1f0 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/staticd_frr.conf @@ -0,0 +1,25 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr/staticd.conf.j2 using config DB data +! file: staticd.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname switch-t0 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.0.0.1 200 +!! +! +! +! add static ipv6 /64 loopback route to allow bgpd to advertise the loopback route prefix +ipv6 route fc00:1::/64 Loopback0 +!! diff --git a/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-bgpd.conf b/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-bgpd.conf new file mode 100644 index 000000000000..7633ac117bf7 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-bgpd.conf @@ -0,0 +1,88 @@ +! +! template: bgpd/bgpd.conf.j2 +! +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname SpineFront01 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +agentx +! +! +! Vnet BGP instance +router bgp 4000 vrf VnetFE + no bgp default ipv4-unicast + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp router-id 4.0.0.0 + neighbor 192.168.0.1 remote-as 3000 + neighbor 192.168.0.1 description Leaf01 + neighbor 192.168.0.1 timers 3 10 + address-family ipv4 unicast + neighbor 192.168.0.1 activate + neighbor 192.168.0.1 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + address-family l2vpn evpn + advertise ipv4 unicast + exit-address-family +!! +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 4.0.0.0/32 +! +! +! +! +router bgp 4000 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 4.0.0.0 +! + network 4.0.0.0/32 +! +! +! +! +! + address-family ipv4 + maximum-paths 64 + exit-address-family + address-family ipv6 + maximum-paths 64 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +!! +! end of template: bgpd/bgpd.conf.j2 +! diff --git a/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-vni-zebra.conf b/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-vni-zebra.conf new file mode 100644 index 000000000000..fb441f69f6f0 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-vni-zebra.conf @@ -0,0 +1,34 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/zebra/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname SpineFront01 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +vrf VnetFE +vni 9000 +! +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface Ethernet8 +link-detect +! +interface Ethernet4 +link-detect +! +interface Ethernet0 +link-detect +! +!! diff --git a/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-zebra.conf b/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-zebra.conf new file mode 100644 index 000000000000..908280e2ddfa --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-zebra.conf @@ -0,0 +1,34 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/zebra/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname SpineFront01 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +vrf VnetFE +vni 8000 +! +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface Ethernet8 +link-detect +! +interface Ethernet4 +link-detect +! +interface Ethernet0 +link-detect +! +!! diff --git a/src/sonic-config-engine/tests/sample_output/py2/wait_for_intf.sh b/src/sonic-config-engine/tests/sample_output/py2/wait_for_intf.sh new file mode 100644 index 000000000000..2af5cee2f005 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/wait_for_intf.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +function wait_until_iface_ready +{ + IFACE_NAME=$1 + IFACE_CIDR=$2 + + echo "Waiting until interface ${IFACE_NAME} is ready..." + + # Wait for the interface to come up + # (i.e., interface is present in STATE_DB and state is "ok") + while true; do + 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 + + sleep 1 + done + + echo "Interface ${IFACE_NAME} is ready!" +} + + +# Wait for all interfaces with IPv4 addresses to be up and ready +wait_until_iface_ready Vlan1000 192.168.0.1/27 +wait_until_iface_ready PortChannel02 10.0.0.58/31 +wait_until_iface_ready PortChannel03 10.0.0.60/31 +wait_until_iface_ready PortChannel04 10.0.0.62/31 +wait_until_iface_ready PortChannel01 10.0.0.56/31 + diff --git a/src/sonic-config-engine/tests/sample_output/py2/zebra_frr.conf b/src/sonic-config-engine/tests/sample_output/py2/zebra_frr.conf new file mode 100644 index 000000000000..4024f4b340e2 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/zebra_frr.conf @@ -0,0 +1,34 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/zebra/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname switch-t0 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface PortChannel03 +link-detect +! +interface PortChannel02 +link-detect +! +interface PortChannel01 +link-detect +! +interface PortChannel04 +link-detect +! +!! diff --git a/src/sonic-config-engine/tests/sample_output/py2/zebra_quagga.conf b/src/sonic-config-engine/tests/sample_output/py2/zebra_quagga.conf new file mode 100644 index 000000000000..b1b791b252e8 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/zebra_quagga.conf @@ -0,0 +1,44 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! +hostname switch-t0 +password zebra +enable password zebra +! +! Enable link-detect (default disabled) +interface PortChannel03 +link-detect +! +interface PortChannel02 +link-detect +! +interface PortChannel01 +link-detect +! +interface PortChannel04 +link-detect +! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.0.0.1 200 +! +! Set ip source to loopback for bgp learned routes +route-map RM_SET_SRC permit 10 + set src 10.1.0.32 +! + +route-map RM_SET_SRC6 permit 10 + set src fc00:1::32 +! +ip protocol bgp route-map RM_SET_SRC +! +ipv6 protocol bgp route-map RM_SET_SRC6 +! +! +log syslog informational +log facility local4 +! + diff --git a/src/sonic-config-engine/tests/sample_output/py3/bgpd_frr.conf b/src/sonic-config-engine/tests/sample_output/py3/bgpd_frr.conf new file mode 100644 index 000000000000..a312e7532620 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/bgpd_frr.conf @@ -0,0 +1,74 @@ +! +! template: bgpd/bgpd.conf.j2 +! +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname switch-t0 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +agentx +! +! +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 10.1.0.32/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00:1::/64 +! +ip prefix-list LOCAL_VLAN_IPV4_PREFIX seq 5 permit 192.168.0.0/27 +! +! +! +router bgp 65100 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 10.1.0.32 +! + network 10.1.0.32/32 +! + address-family ipv6 + network fc00:1::32/64 + exit-address-family +! + network 192.168.0.1/27 +! +! +! + address-family ipv4 + maximum-paths 64 + exit-address-family + address-family ipv6 + maximum-paths 64 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +!! +! end of template: bgpd/bgpd.conf.j2 +! diff --git a/src/sonic-config-engine/tests/sample_output/py3/bgpd_quagga.conf b/src/sonic-config-engine/tests/sample_output/py3/bgpd_quagga.conf new file mode 100644 index 000000000000..16eb6095463b --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/bgpd_quagga.conf @@ -0,0 +1,100 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +! +hostname switch-t0 +password zebra +log syslog informational +log facility local4 +! enable password ! +! +! bgp multiple-instance +! +route-map FROM_BGP_SPEAKER_V4 permit 10 +! +route-map TO_BGP_SPEAKER_V4 deny 10 +! +router bgp 65100 + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp router-id 10.1.0.32 + network 10.1.0.32/32 + address-family ipv6 + network fc00:1::32/64 + exit-address-family + network 192.168.0.1/27 + neighbor 10.0.0.57 remote-as 64600 + neighbor 10.0.0.57 description ARISTA01T1 + address-family ipv4 + neighbor 10.0.0.57 allowas-in 1 + neighbor 10.0.0.57 activate + neighbor 10.0.0.57 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::72 remote-as 64600 + neighbor fc00::72 description ARISTA01T1 + address-family ipv6 + neighbor fc00::72 allowas-in 1 + neighbor fc00::72 activate + neighbor fc00::72 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.59 remote-as 64600 + neighbor 10.0.0.59 description ARISTA02T1 + address-family ipv4 + neighbor 10.0.0.59 allowas-in 1 + neighbor 10.0.0.59 activate + neighbor 10.0.0.59 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::76 remote-as 64600 + neighbor fc00::76 description ARISTA02T1 + address-family ipv6 + neighbor fc00::76 allowas-in 1 + neighbor fc00::76 activate + neighbor fc00::76 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.61 remote-as 64600 + neighbor 10.0.0.61 description ARISTA03T1 + address-family ipv4 + neighbor 10.0.0.61 allowas-in 1 + neighbor 10.0.0.61 activate + neighbor 10.0.0.61 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::7a remote-as 64600 + neighbor fc00::7a description ARISTA03T1 + address-family ipv6 + neighbor fc00::7a allowas-in 1 + neighbor fc00::7a activate + neighbor fc00::7a soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor 10.0.0.63 remote-as 64600 + neighbor 10.0.0.63 description ARISTA04T1 + address-family ipv4 + neighbor 10.0.0.63 allowas-in 1 + neighbor 10.0.0.63 activate + neighbor 10.0.0.63 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + neighbor fc00::7e remote-as 64600 + neighbor fc00::7e description ARISTA04T1 + address-family ipv6 + neighbor fc00::7e allowas-in 1 + neighbor fc00::7e activate + neighbor fc00::7e soft-reconfiguration inbound + maximum-paths 64 + exit-address-family +! +maximum-paths 64 +! +route-map ISOLATE permit 10 +set as-path prepend 65100 +! diff --git a/src/sonic-config-engine/tests/sample_output/py3/buffers-dell6100.json b/src/sonic-config-engine/tests/sample_output/py3/buffers-dell6100.json new file mode 100644 index 000000000000..39fb042cc4cb --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/buffers-dell6100.json @@ -0,0 +1,640 @@ + +{ + "CABLE_LENGTH": { + "AZURE": { + "Ethernet0": "5m", + "Ethernet1": "5m", + "Ethernet2": "5m", + "Ethernet3": "5m", + "Ethernet4": "5m", + "Ethernet5": "5m", + "Ethernet6": "5m", + "Ethernet7": "5m", + "Ethernet8": "5m", + "Ethernet9": "5m", + "Ethernet10": "5m", + "Ethernet11": "5m", + "Ethernet12": "5m", + "Ethernet13": "5m", + "Ethernet14": "5m", + "Ethernet15": "5m", + "Ethernet16": "5m", + "Ethernet17": "5m", + "Ethernet18": "5m", + "Ethernet19": "5m", + "Ethernet20": "5m", + "Ethernet21": "5m", + "Ethernet22": "5m", + "Ethernet23": "5m", + "Ethernet24": "5m", + "Ethernet25": "5m", + "Ethernet26": "5m", + "Ethernet27": "5m", + "Ethernet28": "5m", + "Ethernet29": "5m", + "Ethernet30": "5m", + "Ethernet31": "5m", + "Ethernet32": "5m", + "Ethernet33": "5m", + "Ethernet34": "5m", + "Ethernet35": "5m", + "Ethernet36": "5m", + "Ethernet37": "5m", + "Ethernet38": "5m", + "Ethernet39": "5m", + "Ethernet40": "5m", + "Ethernet41": "5m", + "Ethernet42": "5m", + "Ethernet43": "5m", + "Ethernet44": "5m", + "Ethernet45": "5m", + "Ethernet46": "5m", + "Ethernet47": "5m", + "Ethernet48": "5m", + "Ethernet49": "5m", + "Ethernet50": "5m", + "Ethernet51": "5m", + "Ethernet52": "5m", + "Ethernet53": "5m", + "Ethernet54": "5m", + "Ethernet55": "5m", + "Ethernet56": "5m", + "Ethernet57": "5m", + "Ethernet58": "5m", + "Ethernet59": "5m", + "Ethernet60": "5m", + "Ethernet61": "5m", + "Ethernet62": "5m", + "Ethernet63": "5m" + } + }, + + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10875072", + "type": "ingress", + "mode": "dynamic", + "xoff": "4194112" + }, + "egress_lossy_pool": { + "size": "9243812", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"15982720" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, + "BUFFER_PG": { + "Ethernet0|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet1|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet4|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet5|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet16|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet17|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet20|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet21|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet6|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet7|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet8|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet9|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet10|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet11|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet12|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet13|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet14|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet15|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet32|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet36|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet37|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet38|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet39|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet40|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet41|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet42|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet22|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet23|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet24|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet25|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet26|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet27|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet28|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet29|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet30|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet31|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet48|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet52|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet53|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet54|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet55|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet56|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet57|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + }, + "Ethernet58|0": { + "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]" + } + }, + + "BUFFER_QUEUE": { + "Ethernet0|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet1|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet4|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet5|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet16|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet17|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet20|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet21|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet6|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet7|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet8|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet9|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet10|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet11|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet12|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet13|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet14|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet15|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet32|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet36|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet37|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet38|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet39|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet40|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet41|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet42|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet22|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet23|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet24|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet25|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet26|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet27|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet28|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet29|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet30|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet31|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet48|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet52|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet53|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet54|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet55|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet56|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet57|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet58|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "Ethernet0|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet1|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet4|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet5|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet16|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet17|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet20|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet21|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet6|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet7|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet8|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet9|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet10|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet11|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet12|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet13|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet14|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet15|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet32|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet36|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet37|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet38|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet39|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet40|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet41|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet42|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet22|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet23|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet24|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet25|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet26|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet27|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet28|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet29|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet30|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet31|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet48|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet52|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet53|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet54|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet55|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet56|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet57|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet58|0-2": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet0|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet1|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet4|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet5|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet16|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet17|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet20|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet21|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet6|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet7|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet8|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet9|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet10|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet11|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet12|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet13|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet14|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet15|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet32|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet36|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet37|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet38|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet39|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet40|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet41|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet42|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet22|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet23|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet24|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet25|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet26|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet27|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet28|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet29|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet30|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet31|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet48|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet52|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet53|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet54|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet55|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet56|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet57|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + }, + "Ethernet58|5-6": { + "profile" : "[BUFFER_PROFILE|egress_lossy_profile]" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf b/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf new file mode 100644 index 000000000000..e2135d05296b --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf @@ -0,0 +1,69 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=50 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/bin/supervisor-proc-exit-listener --container-name dhcp_relay +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=1 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true + +[program:start] +command=/usr/bin/start.sh +priority=2 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[group:isc-dhcp-relay] +programs=isc-dhcp-relay-Vlan1000 + +[program:isc-dhcp-relay-Vlan1000] +command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id Vlan1000 -iu PortChannel01 -iu PortChannel02 -iu PortChannel03 -iu PortChannel04 192.0.0.1 192.0.0.2 +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=start:exited + + +[group:dhcpmon] +programs=dhcpmon-Vlan1000 + +[program:dhcpmon-Vlan1000] +command=/usr/sbin/dhcpmon -id Vlan1000 -iu PortChannel01 -iu PortChannel02 -iu PortChannel03 -iu PortChannel04 -im eth0 +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=isc-dhcp-relay-Vlan1000:running + + + diff --git a/src/sonic-config-engine/tests/sample_output/py3/frr.conf b/src/sonic-config-engine/tests/sample_output/py3/frr.conf new file mode 100644 index 000000000000..bb3c4e214e20 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/frr.conf @@ -0,0 +1,95 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr.conf.j2 with config DB data +! file: frr.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname switch-t0 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +agentx +! +! +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface PortChannel01 +link-detect +! +interface PortChannel02 +link-detect +! +interface PortChannel03 +link-detect +! +interface PortChannel04 +link-detect +! +!! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.0.0.1 200 +!! +! +! +! add static ipv6 /64 loopback route to allow bgpd to advertise the loopback route prefix +ipv6 route fc00:1::/64 Loopback0 +!! +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 10.1.0.32/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00:1::/64 +! +ip prefix-list LOCAL_VLAN_IPV4_PREFIX seq 5 permit 192.168.0.0/27 +! +! +! +router bgp 65100 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 10.1.0.32 +! + network 10.1.0.32/32 +! + address-family ipv6 + network fc00:1::32/64 + exit-address-family +! + network 192.168.0.1/27 +! +! +! + address-family ipv4 + maximum-paths 64 + exit-address-family + address-family ipv6 + maximum-paths 64 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +!! diff --git a/src/sonic-config-engine/tests/sample_output/py3/interfaces b/src/sonic-config-engine/tests/sample_output/py3/interfaces new file mode 100644 index 000000000000..6e952d6f71ea --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/interfaces @@ -0,0 +1,46 @@ +# +# =============== Managed by SONiC Config Engine DO NOT EDIT! =============== +# generated from /usr/share/sonic/templates/interfaces.j2 using sonic-cfggen +# file: /etc/network/interfaces +# +# The loopback network interface +auto lo +iface lo inet loopback + address 127.0.0.1 + netmask 255.255.0.0 + post-up ip addr del 127.0.0.1/8 dev lo + +# The management network interface +auto eth0 +iface eth0 inet static + address 10.0.0.100 + netmask 255.255.255.0 + network 10.0.0.0 + broadcast 10.0.0.255 + ########## management network policy routing rules + # management port up rules + up ip -4 route add default via 10.0.0.1 dev eth0 table default metric 201 + up ip -4 route add 10.0.0.0/24 dev eth0 table default + up ip -4 rule add pref 32765 from 10.0.0.100/32 table default + # management port down rules + pre-down ip -4 route delete default via 10.0.0.1 dev eth0 table default + pre-down ip -4 route delete 10.0.0.0/24 dev eth0 table default + pre-down ip -4 rule delete pref 32765 from 10.0.0.100/32 table default +iface eth0 inet6 static + address 2603:10e2:0:2902::8 + netmask 64 + network 2603:10e2:0:2902:: + broadcast 2603:10e2:0:2902:ffff:ffff:ffff:ffff + ########## management network policy routing rules + # management port up rules + up ip -6 route add default via 2603:10e2:0:2902::1 dev eth0 table default metric 201 + up ip -6 route add 2603:10e2:0:2902::/64 dev eth0 table default + up ip -6 rule add pref 32765 from 2603:10e2:0:2902::8/128 table default + # management port down rules + pre-down ip -6 route delete default via 2603:10e2:0:2902::1 dev eth0 table default + pre-down ip -6 route delete 2603:10e2:0:2902::/64 dev eth0 table default + pre-down ip -6 rule delete pref 32765 from 2603:10e2:0:2902::8/128 table default +# +source /etc/network/interfaces.d/* +# + diff --git a/src/sonic-config-engine/tests/sample_output/py3/ipinip.json b/src/sonic-config-engine/tests/sample_output/py3/ipinip.json new file mode 100644 index 000000000000..db70ea403121 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/ipinip.json @@ -0,0 +1,23 @@ +[ + { + "TUNNEL_DECAP_TABLE:IPINIP_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"10.0.0.56,10.0.0.58,10.0.0.60,10.0.0.62,10.1.0.32,192.168.0.1", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", + "ttl_mode":"pipe" + }, + "OP": "SET" + } + , + { + "TUNNEL_DECAP_TABLE:IPINIP_V6_TUNNEL" : { + "tunnel_type":"IPINIP", + "dst_ip":"fc00:1::32,fc00::71,fc00::75,fc00::79,fc00::7d", + "dscp_mode":"pipe", + "ecn_mode":"copy_from_outer", + "ttl_mode":"pipe" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/sample_output/py3/l2switch.json b/src/sonic-config-engine/tests/sample_output/py3/l2switch.json new file mode 100644 index 000000000000..fd83589153ea --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/l2switch.json @@ -0,0 +1,268 @@ +{ + "DEVICE_METADATA": {"localhost": {"hwsku": "Mellanox-SN2700"}}, + "PORT": { + "Ethernet0": { + "alias": "fortyGigE0/0", + "lanes": "29,30,31,32", + "admin_status": "up" + }, + "Ethernet4": { + "alias": "fortyGigE0/4", + "lanes": "25,26,27,28", + "admin_status": "up" + }, + "Ethernet8": { + "alias": "fortyGigE0/8", + "lanes": "37,38,39,40", + "admin_status": "up" + }, + "Ethernet12": { + "alias": "fortyGigE0/12", + "lanes": "33,34,35,36", + "admin_status": "up" + }, + "Ethernet16": { + "alias": "fortyGigE0/16", + "lanes": "41,42,43,44", + "admin_status": "up" + }, + "Ethernet20": { + "alias": "fortyGigE0/20", + "lanes": "45,46,47,48", + "admin_status": "up" + }, + "Ethernet24": { + "alias": "fortyGigE0/24", + "lanes": "5,6,7,8", + "admin_status": "up" + }, + "Ethernet28": { + "alias": "fortyGigE0/28", + "lanes": "1,2,3,4", + "admin_status": "up" + }, + "Ethernet32": { + "alias": "fortyGigE0/32", + "lanes": "9,10,11,12", + "admin_status": "up" + }, + "Ethernet36": { + "alias": "fortyGigE0/36", + "lanes": "13,14,15,16", + "admin_status": "up" + }, + "Ethernet40": { + "alias": "fortyGigE0/40", + "lanes": "21,22,23,24", + "admin_status": "up" + }, + "Ethernet44": { + "alias": "fortyGigE0/44", + "lanes": "17,18,19,20", + "admin_status": "up" + }, + "Ethernet48": { + "alias": "fortyGigE0/48", + "lanes": "49,50,51,52", + "admin_status": "up" + }, + "Ethernet52": { + "alias": "fortyGigE0/52", + "lanes": "53,54,55,56", + "admin_status": "up" + }, + "Ethernet56": { + "alias": "fortyGigE0/56", + "lanes": "61,62,63,64", + "admin_status": "up" + }, + "Ethernet60": { + "alias": "fortyGigE0/60", + "lanes": "57,58,59,60", + "admin_status": "up" + }, + "Ethernet64": { + "alias": "fortyGigE0/64", + "lanes": "65,66,67,68", + "admin_status": "up" + }, + "Ethernet68": { + "alias": "fortyGigE0/68", + "lanes": "69,70,71,72", + "admin_status": "up" + }, + "Ethernet72": { + "alias": "fortyGigE0/72", + "lanes": "77,78,79,80", + "admin_status": "up" + }, + "Ethernet76": { + "alias": "fortyGigE0/76", + "lanes": "73,74,75,76", + "admin_status": "up" + }, + "Ethernet80": { + "alias": "fortyGigE0/80", + "lanes": "105,106,107,108", + "admin_status": "up" + }, + "Ethernet84": { + "alias": "fortyGigE0/84", + "lanes": "109,110,111,112", + "admin_status": "up" + }, + "Ethernet88": { + "alias": "fortyGigE0/88", + "lanes": "117,118,119,120", + "admin_status": "up" + }, + "Ethernet92": { + "alias": "fortyGigE0/92", + "lanes": "113,114,115,116", + "admin_status": "up" + }, + "Ethernet96": { + "alias": "fortyGigE0/96", + "lanes": "121,122,123,124", + "admin_status": "up" + }, + "Ethernet100": { + "alias": "fortyGigE0/100", + "lanes": "125,126,127,128", + "admin_status": "up" + }, + "Ethernet104": { + "alias": "fortyGigE0/104", + "lanes": "85,86,87,88", + "admin_status": "up" + }, + "Ethernet108": { + "alias": "fortyGigE0/108", + "lanes": "81,82,83,84", + "admin_status": "up" + }, + "Ethernet112": { + "alias": "fortyGigE0/112", + "lanes": "89,90,91,92", + "admin_status": "up" + }, + "Ethernet116": { + "alias": "fortyGigE0/116", + "lanes": "93,94,95,96", + "admin_status": "up" + }, + "Ethernet120": { + "alias": "fortyGigE0/120", + "lanes": "97,98,99,100", + "admin_status": "up" + }, + "Ethernet124": { + "alias": "fortyGigE0/124", + "lanes": "101,102,103,104", + "admin_status": "up" + } + }, + "VLAN": { + "Vlan1000": { + "vlanid": "1000" + } + }, + "VLAN_MEMBER": { + "Vlan1000|Ethernet0": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet4": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet8": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet12": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet16": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet20": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet24": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet28": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet32": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet36": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet40": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet44": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet48": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet52": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet56": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet60": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet64": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet68": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet72": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet76": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet80": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet84": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet88": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet92": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet96": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet100": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet104": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet108": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet112": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet116": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet120": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet124": { + "tagging_mode": "untagged" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/py3/lldp_conf/lldpd-ipv4-iface.conf b/src/sonic-config-engine/tests/sample_output/py3/lldp_conf/lldpd-ipv4-iface.conf new file mode 100644 index 000000000000..c9cb2c8123dd --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/lldp_conf/lldpd-ipv4-iface.conf @@ -0,0 +1,4 @@ +configure ports eth0 lldp portidsubtype local eth0 +configure system ip management pattern 10.0.0.100 +configure system hostname switch-t0 +pause diff --git a/src/sonic-config-engine/tests/sample_output/py3/lldp_conf/lldpd-ipv6-iface.conf b/src/sonic-config-engine/tests/sample_output/py3/lldp_conf/lldpd-ipv6-iface.conf new file mode 100644 index 000000000000..f5727556fdf3 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/lldp_conf/lldpd-ipv6-iface.conf @@ -0,0 +1,2 @@ +configure system hostname switch-t0 +pause diff --git a/src/sonic-config-engine/tests/sample_output/py3/mvrf_interfaces b/src/sonic-config-engine/tests/sample_output/py3/mvrf_interfaces new file mode 100644 index 000000000000..9e5c8a4261cf --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/mvrf_interfaces @@ -0,0 +1,61 @@ +# +# =============== Managed by SONiC Config Engine DO NOT EDIT! =============== +# generated from /usr/share/sonic/templates/interfaces.j2 using sonic-cfggen +# file: /etc/network/interfaces +# +auto mgmt +iface mgmt + vrf-table 5000 +# 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/16 dev lo-m + up ip link set lo-m up + down ip link delete dev lo-m +# The loopback network interface +auto lo +iface lo inet loopback + address 127.0.0.1 + netmask 255.255.0.0 + post-up ip addr del 127.0.0.1/8 dev lo + +# The management network interface +auto eth0 +iface eth0 inet static + address 10.0.0.100 + netmask 255.255.255.0 + network 10.0.0.0 + broadcast 10.0.0.255 + vrf mgmt + ########## management network policy routing rules + # management port up rules + up ip -4 route add default via 10.0.0.1 dev eth0 table 5000 metric 201 + up ip -4 route add 10.0.0.0/24 dev eth0 table 5000 + up ip -4 rule add pref 32765 from 10.0.0.100/32 table 5000 + up ip rule add pref 32764 to 11.11.11.11 table 5000 + up ip rule add pref 32764 to 22.22.22.0/23 table 5000 + # management port down rules + pre-down ip -4 route delete default via 10.0.0.1 dev eth0 table 5000 + pre-down ip -4 route delete 10.0.0.0/24 dev eth0 table 5000 + pre-down ip -4 rule delete pref 32765 from 10.0.0.100/32 table 5000 + pre-down ip rule delete pref 32764 to 11.11.11.11 table 5000 + pre-down ip rule delete pref 32764 to 22.22.22.0/23 table 5000 +iface eth0 inet6 static + address 2603:10e2:0:2902::8 + netmask 64 + network 2603:10e2:0:2902:: + broadcast 2603:10e2:0:2902:ffff:ffff:ffff:ffff + vrf mgmt + ########## management network policy routing rules + # management port up rules + up ip -6 route add default via 2603:10e2:0:2902::1 dev eth0 table 5000 metric 201 + up ip -6 route add 2603:10e2:0:2902::/64 dev eth0 table 5000 + up ip -6 rule add pref 32765 from 2603:10e2:0:2902::8/128 table 5000 + # management port down rules + pre-down ip -6 route delete default via 2603:10e2:0:2902::1 dev eth0 table 5000 + pre-down ip -6 route delete 2603:10e2:0:2902::/64 dev eth0 table 5000 + pre-down ip -6 rule delete pref 32765 from 2603:10e2:0:2902::8/128 table 5000 +# +source /etc/network/interfaces.d/* +# + diff --git a/src/sonic-config-engine/tests/sample_output/py3/ndppd.conf b/src/sonic-config-engine/tests/sample_output/py3/ndppd.conf new file mode 100644 index 000000000000..28a239006d24 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/ndppd.conf @@ -0,0 +1,25 @@ +# =========== Managed by sonic-cfggen -- DO NOT edit manually! ==================== +# Generated by /usr/share/sonic/templates/ndppd.conf.j2 using config DB data +# File: /etc/ndppd.conf +# +# Config file for ndppd, the NDP Proxy Daemon +# See man page for ndppd.conf.5 for descriptions of all available options + +proxy Vlan1000 { + rule fc01:1000::/64 { + static + } + rule fc02:1000::/64 { + static + } + rule fc03:1000::/64 { + static + } +} + +proxy Vlan2000 { + rule fc01:2000::/64 { + static + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/py3/ports.json b/src/sonic-config-engine/tests/sample_output/py3/ports.json new file mode 100644 index 000000000000..36f5ad117c39 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/ports.json @@ -0,0 +1,30 @@ +[ + { + "PORT_TABLE:Ethernet0": { + "speed": "10000", + "description": "fortyGigE0/0" + }, + "OP": "SET" + }, + { + "PORT_TABLE:Ethernet4": { + "speed": "25000", + "description": "fortyGigE0/4" + }, + "OP": "SET" + }, + { + "PORT_TABLE:Ethernet8": { + "speed": "1000", + "description": "Interface description" + }, + "OP": "SET" + }, + { + "PORT_TABLE:Ethernet12": { + "speed": "100000", + "description": "Interface description" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/sample_output/py3/qos-arista7050.json b/src/sonic-config-engine/tests/sample_output/py3/qos-arista7050.json new file mode 100644 index 000000000000..aa05ef4ec36c --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/qos-arista7050.json @@ -0,0 +1,977 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "0", + "2": "0", + "3": "3", + "4": "4", + "5": "0", + "6": "0", + "7": "7" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0" : "1", + "1" : "1", + "2" : "1", + "3" : "3", + "4" : "4", + "5" : "2", + "6" : "1", + "7" : "1", + "8" : "0", + "9" : "1", + "10": "1", + "11": "1", + "12": "1", + "13": "1", + "14": "1", + "15": "1", + "16": "1", + "17": "1", + "18": "1", + "19": "1", + "20": "1", + "21": "1", + "22": "1", + "23": "1", + "24": "1", + "25": "1", + "26": "1", + "27": "1", + "28": "1", + "29": "1", + "30": "1", + "31": "1", + "32": "1", + "33": "1", + "34": "1", + "35": "1", + "36": "1", + "37": "1", + "38": "1", + "39": "1", + "40": "1", + "41": "1", + "42": "1", + "43": "1", + "44": "1", + "45": "1", + "46": "5", + "47": "1", + "48": "6", + "49": "1", + "50": "1", + "51": "1", + "52": "1", + "53": "1", + "54": "1", + "55": "1", + "56": "1", + "57": "1", + "58": "1", + "59": "1", + "60": "1", + "61": "1", + "62": "1", + "63": "1" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "14" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "15" + } + }, + "PORT_QOS_MAP": { + "Ethernet4": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet8": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet12": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet16": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet20": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet24": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet28": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet32": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet36": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet40": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet44": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet48": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet52": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet56": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet60": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet64": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet68": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet72": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet76": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet80": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet84": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet88": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet92": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet96": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet112": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet116": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet120": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet124": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "1048576", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, + "QUEUE": { + "Ethernet4|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet8|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet12|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet16|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet20|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet24|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet28|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet32|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet36|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet40|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet44|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet48|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet52|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet56|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet60|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet64|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet68|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet72|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet76|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet80|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet84|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet88|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet92|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet96|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet112|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet116|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet120|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet124|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet4|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet8|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet12|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet16|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet20|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet24|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet28|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet32|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet36|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet40|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet44|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet48|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet52|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet56|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet60|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet64|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet68|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet72|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet76|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet80|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet84|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet88|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet92|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet96|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet112|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet116|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet120|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet124|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet4|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet44|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet60|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet64|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet68|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet72|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet76|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet80|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet84|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet88|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet92|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet96|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet112|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet116|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet120|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet124|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet44|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet60|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet64|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet68|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet72|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet76|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet80|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet84|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet88|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet92|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet96|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet112|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet116|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet120|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet124|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet44|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet60|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet64|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet68|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet72|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet76|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet80|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet84|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet88|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet92|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet96|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet112|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet116|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet120|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet124|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet44|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet60|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet64|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet68|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet72|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet76|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet80|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet84|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet88|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet92|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet96|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet112|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet116|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet120|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet124|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet44|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet60|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet64|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet68|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet72|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet76|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet80|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet84|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet88|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet92|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet96|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet112|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet116|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet120|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet124|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/py3/qos-dell6100.json b/src/sonic-config-engine/tests/sample_output/py3/qos-dell6100.json new file mode 100644 index 000000000000..75d9b3a87eee --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/qos-dell6100.json @@ -0,0 +1,1457 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "0", + "2": "0", + "3": "3", + "4": "4", + "5": "0", + "6": "0", + "7": "7" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0" : "1", + "1" : "1", + "2" : "1", + "3" : "3", + "4" : "4", + "5" : "2", + "6" : "1", + "7" : "1", + "8" : "0", + "9" : "1", + "10": "1", + "11": "1", + "12": "1", + "13": "1", + "14": "1", + "15": "1", + "16": "1", + "17": "1", + "18": "1", + "19": "1", + "20": "1", + "21": "1", + "22": "1", + "23": "1", + "24": "1", + "25": "1", + "26": "1", + "27": "1", + "28": "1", + "29": "1", + "30": "1", + "31": "1", + "32": "1", + "33": "1", + "34": "1", + "35": "1", + "36": "1", + "37": "1", + "38": "1", + "39": "1", + "40": "1", + "41": "1", + "42": "1", + "43": "1", + "44": "1", + "45": "1", + "46": "5", + "47": "1", + "48": "6", + "49": "1", + "50": "1", + "51": "1", + "52": "1", + "53": "1", + "54": "1", + "55": "1", + "56": "1", + "57": "1", + "58": "1", + "59": "1", + "60": "1", + "61": "1", + "62": "1", + "63": "1" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "14" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "15" + } + }, + "PORT_QOS_MAP": { + "Ethernet0": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet1": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet4": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet5": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet6": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet7": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet8": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet9": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet10": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet11": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet12": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet13": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet14": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet15": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet16": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet17": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet20": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet21": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet22": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet23": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet24": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet25": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet26": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet27": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet28": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet29": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet30": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet31": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet32": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet36": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet37": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet38": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet39": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet40": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet41": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet42": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet48": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet52": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet53": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet54": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet55": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet56": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet57": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + }, + "Ethernet58": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable" : "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable" : "true", + "wred_yellow_enable" : "true", + "wred_red_enable" : "true", + "ecn" : "ecn_all", + "green_max_threshold" : "2097152", + "green_min_threshold" : "250000", + "yellow_max_threshold" : "2097152", + "yellow_min_threshold" : "1048576", + "red_max_threshold" : "2097152", + "red_min_threshold" : "1048576", + "green_drop_probability" : "5", + "yellow_drop_probability": "5", + "red_drop_probability" : "5" + } + }, + "QUEUE": { + "Ethernet0|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet1|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet4|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet5|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet6|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet7|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet8|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet9|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet10|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet11|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet12|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet13|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet14|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet15|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet16|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet17|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet20|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet21|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet22|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet23|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet24|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet25|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet26|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet27|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet28|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet29|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet30|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet31|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet32|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet36|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet37|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet38|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet39|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet40|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet41|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet42|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet48|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet52|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet53|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet54|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet55|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet56|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet57|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet58|3": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet1|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet4|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet5|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet6|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet7|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet8|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet9|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet10|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet11|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet12|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet13|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet14|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet15|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet16|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet17|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet20|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet21|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet22|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet23|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet24|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet25|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet26|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet27|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet28|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet29|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet30|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet31|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet32|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet36|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet37|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet38|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet39|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet40|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet41|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet42|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet48|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet52|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet53|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet54|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet55|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet56|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet57|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet58|4": { + "scheduler" : "[SCHEDULER|scheduler.1]", + "wred_profile": "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|0": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet0|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|1": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet0|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|2": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet0|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|5": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet0|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet1|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet4|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet5|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet6|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet7|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet8|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet9|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet10|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet11|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet12|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet13|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet14|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet15|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet16|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet17|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet20|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet21|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet22|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet23|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet24|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet25|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet26|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet27|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet28|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet29|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet30|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet31|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet32|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet36|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet37|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet38|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet39|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet40|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet41|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet42|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet48|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet52|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet53|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet54|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet55|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet56|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet57|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + }, + "Ethernet58|6": { + "scheduler": "[SCHEDULER|scheduler.0]" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/py3/staticd_frr.conf b/src/sonic-config-engine/tests/sample_output/py3/staticd_frr.conf new file mode 100644 index 000000000000..54d83525b1f0 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/staticd_frr.conf @@ -0,0 +1,25 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr/staticd.conf.j2 using config DB data +! file: staticd.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname switch-t0 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.0.0.1 200 +!! +! +! +! add static ipv6 /64 loopback route to allow bgpd to advertise the loopback route prefix +ipv6 route fc00:1::/64 Loopback0 +!! diff --git a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-bgpd.conf b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-bgpd.conf new file mode 100644 index 000000000000..7633ac117bf7 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-bgpd.conf @@ -0,0 +1,88 @@ +! +! template: bgpd/bgpd.conf.j2 +! +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname SpineFront01 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +agentx +! +! +! Vnet BGP instance +router bgp 4000 vrf VnetFE + no bgp default ipv4-unicast + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp router-id 4.0.0.0 + neighbor 192.168.0.1 remote-as 3000 + neighbor 192.168.0.1 description Leaf01 + neighbor 192.168.0.1 timers 3 10 + address-family ipv4 unicast + neighbor 192.168.0.1 activate + neighbor 192.168.0.1 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + address-family l2vpn evpn + advertise ipv4 unicast + exit-address-family +!! +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 4.0.0.0/32 +! +! +! +! +router bgp 4000 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast + no bgp ebgp-requires-policy +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 4.0.0.0 +! + network 4.0.0.0/32 +! +! +! +! +! + address-family ipv4 + maximum-paths 64 + exit-address-family + address-family ipv6 + maximum-paths 64 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +!! +! end of template: bgpd/bgpd.conf.j2 +! diff --git a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf new file mode 100644 index 000000000000..7b7987650d61 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf @@ -0,0 +1,34 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/zebra/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname SpineFront01 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +vrf VnetFE +vni 9000 +! +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface Ethernet0 +link-detect +! +interface Ethernet4 +link-detect +! +interface Ethernet8 +link-detect +! +!! diff --git a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf new file mode 100644 index 000000000000..fc8a8a2fb3bf --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf @@ -0,0 +1,34 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/zebra/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname SpineFront01 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +vrf VnetFE +vni 8000 +! +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface Ethernet0 +link-detect +! +interface Ethernet4 +link-detect +! +interface Ethernet8 +link-detect +! +!! diff --git a/src/sonic-config-engine/tests/sample_output/py3/wait_for_intf.sh b/src/sonic-config-engine/tests/sample_output/py3/wait_for_intf.sh new file mode 100644 index 000000000000..6d90afa60ad7 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/wait_for_intf.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +function wait_until_iface_ready +{ + IFACE_NAME=$1 + IFACE_CIDR=$2 + + echo "Waiting until interface ${IFACE_NAME} is ready..." + + # Wait for the interface to come up + # (i.e., interface is present in STATE_DB and state is "ok") + while true; do + 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 + + sleep 1 + done + + echo "Interface ${IFACE_NAME} is ready!" +} + + +# Wait for all interfaces with IPv4 addresses to be up and ready +wait_until_iface_ready Vlan1000 192.168.0.1/27 +wait_until_iface_ready PortChannel01 10.0.0.56/31 +wait_until_iface_ready PortChannel02 10.0.0.58/31 +wait_until_iface_ready PortChannel03 10.0.0.60/31 +wait_until_iface_ready PortChannel04 10.0.0.62/31 + diff --git a/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf b/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf new file mode 100644 index 000000000000..f596c5579d3b --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf @@ -0,0 +1,34 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/zebra/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! +! template: common/daemons.common.conf.j2 +! +hostname switch-t0 +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface PortChannel01 +link-detect +! +interface PortChannel02 +link-detect +! +interface PortChannel03 +link-detect +! +interface PortChannel04 +link-detect +! +!! diff --git a/src/sonic-config-engine/tests/sample_output/py3/zebra_quagga.conf b/src/sonic-config-engine/tests/sample_output/py3/zebra_quagga.conf new file mode 100644 index 000000000000..aa3486b0163a --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/zebra_quagga.conf @@ -0,0 +1,44 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! +hostname switch-t0 +password zebra +enable password zebra +! +! Enable link-detect (default disabled) +interface PortChannel01 +link-detect +! +interface PortChannel02 +link-detect +! +interface PortChannel03 +link-detect +! +interface PortChannel04 +link-detect +! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.0.0.1 200 +! +! Set ip source to loopback for bgp learned routes +route-map RM_SET_SRC permit 10 + set src 10.1.0.32 +! + +route-map RM_SET_SRC6 permit 10 + set src fc00:1::32 +! +ip protocol bgp route-map RM_SET_SRC +! +ipv6 protocol bgp route-map RM_SET_SRC6 +! +! +log syslog informational +log facility local4 +! + diff --git a/src/sonic-config-engine/tests/sample_output/t0-switch-masic1.json b/src/sonic-config-engine/tests/sample_output/t0-switch-masic1.json new file mode 100644 index 000000000000..34fd946da361 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0-switch-masic1.json @@ -0,0 +1,10 @@ +[ + { + "SWITCH_TABLE:switch": { + "ecmp_hash_seed": "11", + "lag_hash_seed": "11", + "fdb_aging_time": "600" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/sample_output/t0-switch-masic3.json b/src/sonic-config-engine/tests/sample_output/t0-switch-masic3.json new file mode 100644 index 000000000000..d9f929679cbc --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0-switch-masic3.json @@ -0,0 +1,10 @@ +[ + { + "SWITCH_TABLE:switch": { + "ecmp_hash_seed": "13", + "lag_hash_seed": "13", + "fdb_aging_time": "600" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/sample_output/t0-switch.json b/src/sonic-config-engine/tests/sample_output/t0-switch.json new file mode 100644 index 000000000000..414e53b8a356 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0-switch.json @@ -0,0 +1,10 @@ +[ + { + "SWITCH_TABLE:switch": { + "ecmp_hash_seed": "0", + "lag_hash_seed": "0", + "fdb_aging_time": "600" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel01.conf b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel01.conf new file mode 100644 index 000000000000..d69c0d6697b2 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel01.conf @@ -0,0 +1,17 @@ +{ + "device": "PortChannel01", + "hwaddr": "e4:1d:2d:a5:f3:ad", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet112": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel02.conf b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel02.conf new file mode 100644 index 000000000000..e9b2ff4f1ad9 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel02.conf @@ -0,0 +1,17 @@ +{ + "device": "PortChannel02", + "hwaddr": "e4:1d:2d:a5:f3:ad", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet116": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel03.conf b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel03.conf new file mode 100644 index 000000000000..a73617abade0 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel03.conf @@ -0,0 +1,17 @@ +{ + "device": "PortChannel03", + "hwaddr": "e4:1d:2d:a5:f3:ad", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet120": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel04.conf b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel04.conf new file mode 100644 index 000000000000..073b8057d461 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t0_sample_output/PortChannel04.conf @@ -0,0 +1,17 @@ +{ + "device": "PortChannel04", + "hwaddr": "e4:1d:2d:a5:f3:ad", + "runner": { + "name": "lacp", + "active": true, + "min_ports": 1, + "tx_hash": ["eth", "ipv4", "ipv6"] + }, + "link_watch": { + "name": "ethtool" + }, + "ports": { + "Ethernet124": {} + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/t1-switch.json b/src/sonic-config-engine/tests/sample_output/t1-switch.json new file mode 100644 index 000000000000..fdae474251f0 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t1-switch.json @@ -0,0 +1,10 @@ +[ + { + "SWITCH_TABLE:switch": { + "ecmp_hash_seed": "10", + "lag_hash_seed": "10", + "fdb_aging_time": "600" + }, + "OP": "SET" + } +] diff --git a/src/sonic-config-engine/tests/sample_output/t2-chassis-fe-pc-zebra.conf b/src/sonic-config-engine/tests/sample_output/t2-chassis-fe-pc-zebra.conf new file mode 100644 index 000000000000..be261bab99a8 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/t2-chassis-fe-pc-zebra.conf @@ -0,0 +1,38 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! +hostname SpineFront01 +password zebra +enable password zebra +! +vrf VnetFE +vni 8000 +! +! +! Enable nht through default route +ip nht resolve-via-default +! Enable link-detect (default disabled) +interface PortChannel0 +link-detect +! +interface PortChannel4 +link-detect +! +interface PortChannel8 +link-detect +! +! +! Set ip source to loopback for bgp learned routes +route-map RM_SET_SRC permit 10 + set src 4.0.0.0 +! +ip protocol bgp route-map RM_SET_SRC +! +! +log syslog informational +log facility local4 +! + diff --git a/src/sonic-config-engine/tests/sample_platform.json b/src/sonic-config-engine/tests/sample_platform.json new file mode 100644 index 000000000000..1d8887920c9e --- /dev/null +++ b/src/sonic-config-engine/tests/sample_platform.json @@ -0,0 +1,355 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "breakout_modes": { + "1x100G[40G]": ["Eth1"], + "2x50G": ["Eth1/1", "Eth1/2"], + "4x25G[10G]": ["Eth1/1", "Eth1/2", "Eth1/3", "Eth1/4"], + "2x25G(2)+1x50G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"], + "1x50G(2)+2x25G(2)": ["Eth1/1", "Eth1/2", "Eth1/3"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "breakout_modes": { + "1x100G[40G]": ["Eth2"], + "2x50G": ["Eth2/1", "Eth2/2"], + "4x25G[10G]": ["Eth2/1", "Eth2/2", "Eth2/3", "Eth2/4"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "breakout_modes": { + "1x100G[40G]": ["Eth3"], + "2x50G": ["Eth3/1", "Eth3/2"], + "4x25G[10G]": ["Eth3/1", "Eth3/2", "Eth3/3", "Eth3/4"], + "2x25G(2)+1x50G(2)": ["Eth3/1", "Eth3/2", "Eth3/3"], + "1x50G(2)+2x25G(2)": ["Eth3/1", "Eth3/2", "Eth3/3"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "breakout_modes": { + "1x100G[40G]": ["Eth4"], + "2x50G": ["Eth4/1", "Eth4/2"], + "4x25G[10G]": ["Eth4/1", "Eth4/2", "Eth4/3", "Eth4/4"], + "2x25G(2)+1x50G(2)": ["Eth4/1", "Eth4/2", "Eth4/3"], + "1x50G(2)+2x25G(2)": ["Eth4/1", "Eth4/2", "Eth4/3"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "breakout_modes": { + "1x100G[40G]": ["Eth5"], + "2x50G": ["Eth5/1", "Eth5/2"], + "4x25G[10G]": ["Eth5/1", "Eth5/2", "Eth5/3", "Eth5/4"], + "2x25G(2)+1x50G(2)": ["Eth5/1", "Eth5/2", "Eth5/3"], + "1x50G(2)+2x25G(2)": ["Eth5/1", "Eth5/2", "Eth5/3"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "breakout_modes": { + "1x100G[40G]": ["Eth6"], + "2x50G": ["Eth6/1", "Eth6/2"], + "4x25G[10G]": ["Eth6/1", "Eth6/2", "Eth6/3", "Eth6/4"], + "2x25G(2)+1x50G(2)": ["Eth6/1", "Eth6/2", "Eth6/3"], + "1x50G(2)+2x25G(2)": ["Eth6/1", "Eth6/2", "Eth6/3"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "breakout_modes": { + "1x100G[40G]": ["Eth7"], + "2x50G": ["Eth7/1", "Eth7/2"], + "4x25G[10G]": ["Eth7/1", "Eth7/2", "Eth7/3", "Eth7/4"], + "2x25G(2)+1x50G(2)": ["Eth7/1", "Eth7/2", "Eth7/3"], + "1x50G(2)+2x25G(2)": ["Eth7/1", "Eth7/2", "Eth7/3"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "breakout_modes": { + "1x100G[40G]": ["Eth8"], + "2x50G": ["Eth8/1", "Eth8/2"], + "4x25G[10G]": ["Eth8/1", "Eth8/2", "Eth8/3", "Eth8/4"], + "2x25G(2)+1x50G(2)": ["Eth8/1", "Eth8/2", "Eth8/3"], + "1x50G(2)+2x25G(2)": ["Eth8/1", "Eth8/2", "Eth8/3"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "breakout_modes": { + "1x100G[40G]": ["Eth9"], + "2x50G": ["Eth9/1", "Eth9/2"], + "4x25G[10G]": ["Eth9/1", "Eth9/2", "Eth9/3", "Eth9/4"], + "2x25G(2)+1x50G(2)": ["Eth9/1", "Eth9/2", "Eth9/3"], + "1x50G(2)+2x25G(2)": ["Eth9/1", "Eth9/2", "Eth9/3"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "breakout_modes": { + "1x100G[40G]": ["Eth10"], + "2x50G": ["Eth10/1", "Eth10/2"], + "4x25G[10G]": ["Eth10/1", "Eth10/2", "Eth10/3", "Eth10/4"], + "2x25G(2)+1x50G(2)": ["Eth10/1", "Eth10/2", "Eth10/3"], + "1x50G(2)+2x25G(2)": ["Eth10/1", "Eth10/2", "Eth10/3"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["Eth11"], + "2x50G[40G,25G,10G,1G]": ["Eth11/1", "Eth11/2"], + "4x25G[10G]": ["Eth11/1", "Eth11/2", "Eth11/3", "Eth11/4"], + "2x25G(2)+1x50G(2)": ["Eth11/1", "Eth11/2", "Eth11/3"], + "1x50G(2)+2x25G(2)": ["Eth11/1", "Eth11/2", "Eth11/3"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "breakout_modes": { + "1x100G[50G,40G,25G,10G,1G]": ["Eth12"], + "2x50G[40G,25G,10G,1G]": ["Eth12/1", "Eth12/2"], + "4x25G[10G]": ["Eth12/1", "Eth12/2", "Eth12/3", "Eth12/4"], + "2x25G(2)+1x50G(2)": ["Eth12/1", "Eth12/2", "Eth12/3"], + "1x50G(2)+2x25G(2)": ["Eth12/1", "Eth12/2", "Eth12/3"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "breakout_modes": { + "1x100G[40G]": ["Eth13"], + "2x50G": ["Eth13/1", "Eth13/2"], + "4x25G[10G]": ["Eth13/1", "Eth13/2", "Eth13/3", "Eth13/4"], + "2x25G(2)+1x50G(2)": ["Eth13/1", "Eth13/2", "Eth13/3"], + "1x50G(2)+2x25G(2)": ["Eth13/1", "Eth13/2", "Eth13/3"] + } + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "breakout_modes": { + "1x100G[40G]": ["Eth14"], + "2x50G": ["Eth14/1", "Eth14/2"], + "4x25G[10G]": ["Eth14/1", "Eth14/2", "Eth14/3", "Eth14/4"], + "2x25G(2)+1x50G(2)": ["Eth14/1", "Eth14/2", "Eth14/3"], + "1x50G(2)+2x25G(2)": ["Eth14/1", "Eth14/2", "Eth14/3"] + } + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "breakout_modes": { + "1x100G[40G]": ["Eth15"], + "2x50G": ["Eth15/1", "Eth15/2"], + "4x25G[10G]": ["Eth15/1", "Eth15/2", "Eth15/3", "Eth15/4"], + "2x25G(2)+1x50G(2)": ["Eth15/1", "Eth15/2", "Eth15/3"], + "1x50G(2)+2x25G(2)": ["Eth15/1", "Eth15/2", "Eth15/3"] + } + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "breakout_modes": { + "1x100G[40G]": ["Eth16"], + "2x50G": ["Eth16/1", "Eth16/2"], + "4x25G[10G]": ["Eth16/1", "Eth16/2", "Eth16/3", "Eth16/4"], + "2x25G(2)+1x50G(2)": ["Eth16/1", "Eth16/2", "Eth16/3"], + "1x50G(2)+2x25G(2)": ["Eth16/1", "Eth16/2", "Eth16/3"] + } + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "64,65,66,67", + "breakout_modes": { + "1x100G[40G]": ["Eth17"], + "2x50G": ["Eth17/1", "Eth17/2"], + "4x25G[10G]": ["Eth17/1", "Eth17/2", "Eth17/3", "Eth17/4"], + "2x25G(2)+1x50G(2)": ["Eth17/1", "Eth17/2", "Eth17/3"], + "1x50G(2)+2x25G(2)": ["Eth17/1", "Eth17/2", "Eth17/3"] + } + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "68,69,70,71", + "breakout_modes": { + "1x100G[40G]": ["Eth18"], + "2x50G": ["Eth18/1", "Eth18/2"], + "4x25G[10G]": ["Eth18/1", "Eth18/2", "Eth18/3", "Eth18/4"], + "2x25G(2)+1x50G(2)": ["Eth18/1", "Eth18/2", "Eth18/3"], + "1x50G(2)+2x25G(2)": ["Eth18/1", "Eth18/2", "Eth18/3"] + } + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "breakout_modes": { + "1x100G[40G]": ["Eth19"], + "2x50G": ["Eth19/1", "Eth19/2"], + "4x25G[10G]": ["Eth19/1", "Eth19/2", "Eth19/3", "Eth19/4"], + "2x25G(2)+1x50G(2)": ["Eth19/1", "Eth19/2", "Eth19/3"], + "1x50G(2)+2x25G(2)": ["Eth19/1", "Eth19/2", "Eth19/3"] + } + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "breakout_modes": { + "1x100G[40G]": ["Eth20"], + "2x50G": ["Eth20/1", "Eth20/2"], + "4x25G[10G]": ["Eth20/1", "Eth20/2", "Eth20/3", "Eth20/4"], + "2x25G(2)+1x50G(2)": ["Eth20/1", "Eth20/2", "Eth20/3"], + "1x50G(2)+2x25G(2)": ["Eth20/1", "Eth20/2", "Eth20/3"] + } + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "breakout_modes": { + "1x100G[40G]": ["Eth21"], + "2x50G": ["Eth21/1", "Eth21/2"], + "4x25G[10G]": ["Eth21/1", "Eth21/2", "Eth21/3", "Eth21/4"], + "2x25G(2)+1x50G(2)": ["Eth21/1", "Eth21/2", "Eth21/3"], + "1x50G(2)+2x25G(2)": ["Eth21/1", "Eth21/2", "Eth21/3"] + } + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "breakout_modes": { + "1x100G[40G]": ["Eth22"], + "2x50G": ["Eth22/1", "Eth22/2"], + "4x25G[10G]": ["Eth22/1", "Eth22/2", "Eth22/3", "Eth22/4"], + "2x25G(2)+1x50G(2)": ["Eth22/1", "Eth22/2", "Eth22/3"], + "1x50G(2)+2x25G(2)": ["Eth22/1", "Eth22/2", "Eth22/3"] + } + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "88,89,90,91", + "alias_at_lanes": "Eth23/1, Eth23/2, Eth23/3, Eth23/4", + "breakout_modes": { + "1x100G[40G]": ["Eth23"], + "2x50G": ["Eth23/1", "Eth23/2"], + "4x25G[10G]": ["Eth23/1", "Eth23/2", "Eth23/3", "Eth23/4"], + "2x25G(2)+1x50G(2)": ["Eth23/1", "Eth23/2", "Eth23/3"], + "1x50G(2)+2x25G(2)": ["Eth23/1", "Eth23/2", "Eth23/3"] + } + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "92,93,94,95", + "breakout_modes": { + "1x100G[40G]": ["Eth24"], + "2x50G": ["Eth24/1", "Eth24/2"], + "4x25G[10G]": ["Eth24/1", "Eth24/2", "Eth24/3", "Eth24/4"], + "2x25G(2)+1x50G(2)": ["Eth24/1", "Eth24/2", "Eth24/3"], + "1x50G(2)+2x25G(2)": ["Eth24/1", "Eth24/2", "Eth24/3"] + } + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "96,97,98,99", + "breakout_modes": { + "1x100G[40G]": ["Eth25"], + "2x50G": ["Eth25/1", "Eth25/2"], + "4x25G[10G]": ["Eth25/1", "Eth25/2", "Eth25/3", "Eth25/4"], + "2x25G(2)+1x50G(2)": ["Eth25/1", "Eth25/2", "Eth25/3"], + "1x50G(2)+2x25G(2)": ["Eth25/1", "Eth25/2", "Eth25/3"] + } + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "100,101,102,103", + "breakout_modes": { + "1x100G[40G]": ["Eth26"], + "2x50G": ["Eth26/1", "Eth26/2"], + "4x25G[10G]": ["Eth26/1", "Eth26/2", "Eth26/3", "Eth26/4"], + "2x25G(2)+1x50G(2)": ["Eth26/1", "Eth26/2", "Eth26/3"], + "1x50G(2)+2x25G(2)": ["Eth26/1", "Eth26/2", "Eth26/3"] + } + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "104,105,106,107", + "breakout_modes": { + "1x100G[40G]": ["Eth27"], + "2x50G": ["Eth27/1", "Eth27/2"], + "4x25G[10G]": ["Eth27/1", "Eth27/2", "Eth27/3", "Eth27/4"], + "2x25G(2)+1x50G(2)": ["Eth27/1", "Eth27/2", "Eth27/3"], + "1x50G(2)+2x25G(2)": ["Eth27/1", "Eth27/2", "Eth27/3"] + } + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "108,109,110,111", + "breakout_modes": { + "1x100G[40G]": ["Eth28"], + "2x50G": ["Eth28/1", "Eth28/2"], + "4x25G[10G]": ["Eth28/1", "Eth28/2", "Eth28/3", "Eth28/4"], + "2x25G(2)+1x50G(2)": ["Eth28/1", "Eth28/2", "Eth28/3"], + "1x50G(2)+2x25G(2)": ["Eth28/1", "Eth28/2", "Eth28/3"] + } + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "112,113,114,115", + "breakout_modes": { + "1x100G[40G]": ["Eth29"], + "2x50G": ["Eth29/1", "Eth29/2"], + "4x25G[10G]": ["Eth29/1", "Eth29/2", "Eth29/3", "Eth29/4"], + "2x25G(2)+1x50G(2)": ["Eth29/1", "Eth29/2", "Eth29/3"], + "1x50G(2)+2x25G(2)": ["Eth29/1", "Eth29/2", "Eth29/3"] + } + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "116,117,118,119", + "breakout_modes": { + "1x100G[40G]": ["Eth30"], + "2x50G": ["Eth30/1", "Eth30/2"], + "4x25G[10G]": ["Eth30/1", "Eth30/2", "Eth30/3", "Eth30/4"], + "2x25G(2)+1x50G(2)": ["Eth30/1", "Eth30/2", "Eth30/3"], + "1x50G(2)+2x25G(2)": ["Eth30/1", "Eth30/2", "Eth30/3"] + } + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "120,121,122,123", + "breakout_modes": { + "1x100G[40G]": ["Eth31"], + "2x50G": ["Eth31/1", "Eth31/2"], + "4x25G[10G]": ["Eth31/1", "Eth31/2", "Eth31/3", "Eth31/4"], + "2x25G(2)+1x50G(2)": ["Eth31/1", "Eth31/2", "Eth31/3"], + "1x50G(2)+2x25G(2)": ["Eth31/1", "Eth31/2", "Eth31/3"] + } + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "124,125,126,127", + "breakout_modes": { + "1x100G[40G]": ["Eth32"], + "2x50G": ["Eth32/1", "Eth32/2"], + "4x25G[10G]": ["Eth32/1", "Eth32/2", "Eth32/3", "Eth32/4"], + "2x25G(2)+1x50G(2)": ["Eth32/1", "Eth32/2", "Eth32/3"], + "1x50G(2)+2x25G(2)": ["Eth32/1", "Eth32/2", "Eth32/3"] + } + } + } +} diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case.xml b/src/sonic-config-engine/tests/simple-sample-graph-case.xml new file mode 100644 index 000000000000..95f501200c83 --- /dev/null +++ b/src/sonic-config-engine/tests/simple-sample-graph-case.xml @@ -0,0 +1,487 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/4 + + + + + + + + + ab1 + fortyGigE0/8 + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + 00:aa:bb:cc:dd:ee + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + fortyGigE0/0 + 10.0.0.58/31 + + + + fortyGigE0/0 + FC00::75/126 + + + + ab1 + 192.168.0.1/27 + + + + + + PortChannel01 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + DeviceSerialLink + 9600 + switch-t0 + 1 + true + managed_device + console + + + DeviceInterfaceLink + true + 10000 + switch-t0 + fortyGigE0/0 + switch-01t1 + port1 + + + DeviceInterfaceLink + true + 10000 + switch-t0 + fortyGigE0/12 + switch-02t1 + port1 + + + DeviceInterfaceLink + true + 25000 + switch-t0 + fortyGigE0/4 + server1 + port1 + + + DeviceInterfaceLink + true + 40000 + switch-t0 + fortyGigE0/8 + server2 + port1 + + + LogicalLink + 10000 + false + switch-t0 + fortyGigE0/4 + true + mux-cable + L + true + + + LogicalLink + 10000 + false + switch-t0 + fortyGigE0/8 + true + mux-cable + U + true + + + LogicalLink + 0 + false + switch-t0 + MuxTunnel0 + false + switch2-t0 + MuxTunnel0 + true + + + + + ToRRouter +
+ 26.1.1.10/32 +
+ switch-t0 + Force10-S6000 + AAA00PrdStr00 +
+ +
+ 25.1.1.10/32 +
+ + 10.7.0.196/26 + + switch2-t0 + Force10-S6000 +
+ + switch-01t1 +
+ 10.1.0.186/32 +
+ 2 + + + 10.7.0.196/26 + + Force10-S6000 +
+ + Server +
+ 10.10.10.1/32 +
+ + fe80::0001/80 + + + 10.0.0.1/32 + + server1 + server-sku +
+ + Server +
+ 10.10.10.2/32 +
+ + fe80::0002/128 + + + 10.0.0.2/32 + + server2 + server-sku +
+
+
+ + + + + + + GeminiPeeringLink + + True + + + UpperTOR + + switch-t0 + + + LowerTOR + + switch2-t0 + + + switch2-t0:MuxTunnel0;switch-t0:MuxTunnel0 + + + + + + + switch-t0 + + + DeploymentId + + 1 + + + ErspanDestinationIpv4 + + 10.0.100.1 + + + NtpResources + + 10.0.10.1;10.0.10.2 + + + + SnmpResources + + 10.0.10.3;10.0.10.4 + + + + SyslogResources + + 10.0.10.5;10.0.10.6; + + + + TacacsServer + + 10.0.10.7;10.0.10.8 + + + KubernetesEnabled + + 0 + + + KubernetesServerIp + + 10.10.10.10 + + + + + + + + + true + + + DeviceInterface + + true + true + 1 + fortyGigE0/0 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/4 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/8 + + false + 0 + 0 + 40000 + Interface description + + + DeviceInterface + + true + true + 1 + fortyGigE0/12 + + false + 0 + 0 + 100000 + Interface description + + + true + 0 + Force10-S6000 + + + DeviceInterface + + true + true + 1 + eth0 + false + eth0 + 1000 + + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml b/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml new file mode 100644 index 000000000000..2b3368b7a9c7 --- /dev/null +++ b/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml @@ -0,0 +1,345 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/4 + + + + + + ab1 + fortyGigE0/8 + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + fortyGigE0/0 + 10.0.0.58/31 + + + + fortyGigE0/0 + FC00::75/126 + + + + ab1 + 192.168.0.1/27 + + + + + + PortChannel01 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + + switch-t0 + + + DeploymentId + + 1 + + + Region + + usfoo + + + CloudType + + Public + + + ErspanDestinationIpv4 + + 10.0.100.1 + + + NtpResources + + 10.0.10.1;10.0.10.2 + + + + SnmpResources + + 10.0.10.3;10.0.10.4 + + + + SyslogResources + + 10.0.10.5;10.0.10.6; + + + + TacacsServer + + 10.0.10.7;10.0.10.8 + + + ResourceType + + resource_type_x + + + + + + + + + true + + + DeviceInterface + + true + true + 1 + fortyGigE0/0 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/4 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/8 + + false + 0 + 0 + 40000 + Interface description + + + DeviceInterface + + true + true + 1 + fortyGigE0/12 + + false + 0 + 0 + 100000 + Interface description + + + true + 0 + Force10-S6000 + + + DeviceInterface + + true + true + 1 + Management1 + false + mgmt1 + 1000 + + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/simple-sample-graph.xml b/src/sonic-config-engine/tests/simple-sample-graph.xml new file mode 100644 index 000000000000..703a005ea5bc --- /dev/null +++ b/src/sonic-config-engine/tests/simple-sample-graph.xml @@ -0,0 +1,411 @@ + + + + + + switch-t0 + 10.1.0.32 + BGPMonitor + 10.20.30.40 + 30 + 10 + 3 + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + + + 0 + + BGPMonitor + + + BGPPeer +
10.1.0.32
+ + + +
+
+ +
+ + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/4 + + + + PortChannel1001 + fortyGigE0/1;fortyGigE0/2 + + + + + + ab1 + fortyGigE0/8 + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + kk1 + fortyGigE0/12 + 192.0.0.1;192.0.0.2 + 2020 + 2020 + Tagged + 192.168.0.0/28 + + + ab2 + fortyGigE0/12 + 192.0.0.1;192.0.0.2 + 2000 + 2000 + 192.168.0.240/27 + + + ab3 + fortyGigE0/12 + 192.0.0.1;192.0.0.2 + 2001 + 2001 + 192.168.0.240/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel1001 + 10.0.0.57/31 + + + + PortChannel1001 + FC00::72/126 + + + + fortyGigE0/0 + 10.0.0.58/31 + + + + fortyGigE0/0 + FC00::75/126 + + + + ab1 + 192.168.0.1/27 + + + + + + PortChannel01 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + DeviceInterfaceLink + true + 1000 + ARISTA01T1 + et1 + true + switch-t0 + fortyGigE0/8 + true + + + DeviceInterfaceLink + true + 10000 + switch-t0 + fortyGigE0/1 + true + ARISTA05T1 + Ethernet1/32 + true + + + DeviceInterfaceLink + true + 10000 + switch-t0 + fortyGigE0/2 + true + ARISTA06T1 + Ethernet1/33 + true + + + + + switch-t0 + Force10-S6000 + AAA00PrdStr00 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + true + + + DeviceInterface + + true + true + 1 + fortyGigE0/0 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + true + 1 + Ethernet1 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + true + 1 + Ethernet2 + + false + 0 + 0 + 10000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/4 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + true + 1 + fortyGigE0/8 + + false + 0 + 0 + 40000 + Interface description + + + DeviceInterface + + true + true + 1 + fortyGigE0/12 + + false + 0 + 0 + 100000 + Interface description + + + true + 0 + Force10-S6000 + + + DeviceInterface + + true + 1 + Management1 + false + mgmt1 + 1000 + + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t0-sample-acl.json b/src/sonic-config-engine/tests/t0-sample-acl.json new file mode 100644 index 000000000000..1caf2ff02959 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-acl.json @@ -0,0 +1,176 @@ +{ + "acl": { + "acl-sets": { + "acl-set": { + "dataacl": { + "acl-entries": { + "acl-entry": { + "1": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 1 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "10.0.0.0/8" + } + } + }, + "2": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 2 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "100.64.0.0/10" + } + } + }, + "3": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 3 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "25.0.0.0/8" + } + } + }, + "4": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 4 + }, + "ip": { + "config": { + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "tcp-flags": [ + "TCP_ACK" + ] + } + } + } + } + }, + "config": { + "name": "dataacl" + } + }, + "everflow": { + "acl-entries": { + "acl-entry": { + "1": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 1 + }, + "ip": { + "config": { + "destination-ip-address": "127.0.0.1/32", + "protocol": "IP_TCP", + "source-ip-address": "127.0.0.1/32" + } + }, + "transport": { + "config": { + "destination-port": "0", + "source-port": "0" + } + } + } + } + }, + "config": { + "name": "everflow" + } + }, + "SNMP-ACL": { + "acl-entries": { + "acl-entry": { + "1": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 1 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "10.0.0.0/8" + } + } + }, + "2": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 2 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "100.64.0.0/10" + } + } + }, + "3": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 3 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "25.0.0.0/8" + } + } + } + } + }, + "config": { + "name": "SNMP-ACL" + } + } + } + } + } +} diff --git a/src/sonic-config-engine/tests/t0-sample-bgp-speaker.xml b/src/sonic-config-engine/tests/t0-sample-bgp-speaker.xml new file mode 100644 index 000000000000..f2690985d9f3 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-bgp-speaker.xml @@ -0,0 +1,351 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.60 + ARISTA03T1 + 10.0.0.61 + 1 + 180 + 60 + + + switch-t0 + FC00::79 + ARISTA03T1 + FC00::7A + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.62 + ARISTA04T1 + 10.0.0.63 + 1 + 180 + 60 + + + switch-t0 + FC00::7D + ARISTA04T1 + FC00::7E + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+ +
10.0.0.61
+ + + +
+ +
10.0.0.63
+ + + +
+ +
10.1.0.32
+ BGPSLBPassive + 10.10.10.10/26;100.100.100.100/26 +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/112 + + + + PortChannel02 + fortyGigE0/116 + + + + PortChannel03 + fortyGigE0/120 + + + + PortChannel04 + fortyGigE0/124 + + + + + + Vlan1000 + fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 + False + 0.0.0.0/0 + + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel02 + 10.0.0.58/31 + + + + PortChannel02 + FC00::75/126 + + + + PortChannel03 + 10.0.0.60/31 + + + + PortChannel03 + FC00::79/126 + + + + PortChannel04 + 10.0.0.62/31 + + + + PortChannel04 + FC00::7D/126 + + + + Vlan1000 + 192.168.0.1/27 + + + + + + PortChannel01;PortChannel02;PortChannel03;PortChannel04 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1/1 + switch-t0 + fortyGigE0/112 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1/1 + switch-t0 + fortyGigE0/116 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1/1 + switch-t0 + fortyGigE0/120 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1/1 + switch-t0 + fortyGigE0/124 + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + + switch-t0 + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + DeploymentId + 1 + + + + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t0-sample-graph-mvrf.xml b/src/sonic-config-engine/tests/t0-sample-graph-mvrf.xml new file mode 100644 index 000000000000..ee633c18bd1e --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-graph-mvrf.xml @@ -0,0 +1,413 @@ + + + + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.60 + ARISTA03T1 + 10.0.0.61 + 1 + 180 + 60 + + + switch-t0 + FC00::79 + ARISTA03T1 + FC00::7A + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.62 + ARISTA04T1 + 10.0.0.63 + 1 + 180 + 60 + + + switch-t0 + FC00::7D + ARISTA04T1 + FC00::7E + 1 + 180 + 60 + + + + + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+ +
10.0.0.61
+ + + +
+ +
10.0.0.63
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + LoopbackIP1 + Loopback1 + + 10.10.0.99/32 + + 10.10.0.99/32 + + + + + true + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + HostIP + eth0 + + 2603:10e2:0:2902::8/64 + + 2603:10e2:0:2902::8/64 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/112 + + + + PortChannel02 + fortyGigE0/116 + + + + PortChannel03 + fortyGigE0/120 + + + + PortChannel04 + fortyGigE0/124 + + + + + + Vlan1000 + fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 + False + 0.0.0.0/0 + + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel02 + 10.0.0.58/31 + + + + PortChannel02 + FC00::75/126 + + + + PortChannel03 + 10.0.0.60/31 + + + + PortChannel03 + FC00::79/126 + + + + PortChannel04 + 10.0.0.62/31 + + + + PortChannel04 + FC00::7D/126 + + + + Vlan1000 + 192.168.0.1/27 + + + + + + ERSPAN + everflow + Everflow + + + ERSPANv6 + everflowV6 + Everflow + + + PortChannel01;PortChannel02;PortChannel03;PortChannel04 + DataAcl + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + NTP + NTP_ACL + NTP + + + SSH + SSH_ACL + SSH + + + SSH + ROUTER-PROTECT + SSH + + + SNMP + ROUTER-PROTECT + SNMP + + + NTP + NTP_ACL + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1/1 + switch-t0 + fortyGigE0/112 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1/1 + switch-t0 + fortyGigE0/116 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1/1 + switch-t0 + fortyGigE0/120 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1/1 + switch-t0 + fortyGigE0/124 + + + DeviceInterfaceLink + true + 10000 + switch-t0 + fortyGigE0/2 + true + ARISTA05T1 + Ethernet1/33 + true + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + + switch-t0 + + + ForcedMgmtRoutes + + 11.11.11.11;22.22.22.0/23 + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t0-sample-graph.xml b/src/sonic-config-engine/tests/t0-sample-graph.xml new file mode 100644 index 000000000000..63f892fe6d04 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-graph.xml @@ -0,0 +1,495 @@ + + + + + + switch-t0 + 10.1.0.32 + BGPMonitor + 10.20.30.40 + 30 + 10 + 3 + + + false + switch-t0 + 10.0.0.56 + ARISTA01T1 + 10.0.0.57 + 1 + 180 + 60 + + + switch-t0 + FC00::71 + ARISTA01T1 + FC00::72 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.58 + ARISTA02T1 + 10.0.0.59 + 1 + 180 + 60 + + + switch-t0 + FC00::75 + ARISTA02T1 + FC00::76 + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.60 + ARISTA03T1 + 10.0.0.61 + 1 + 180 + 60 + + + switch-t0 + FC00::79 + ARISTA03T1 + FC00::7A + 1 + 180 + 60 + + + false + switch-t0 + 10.0.0.62 + ARISTA04T1 + 10.0.0.63 + 1 + 180 + 60 + + + switch-t0 + FC00::7D + ARISTA04T1 + FC00::7E + 1 + 180 + 60 + + + + + 0 + + BGPMonitor + + + BGPPeer +
10.1.0.32
+ + + +
+
+ +
+ + 65100 + switch-t0 + + +
10.0.0.57
+ + + +
+ +
10.0.0.59
+ + + +
+ +
10.0.0.61
+ + + +
+ +
10.0.0.63
+ + + +
+
+ +
+ + 64600 + ARISTA01T1 + + + + 64600 + ARISTA02T1 + + + + 64600 + ARISTA03T1 + + + + 64600 + ARISTA04T1 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + LoopbackIP1 + Loopback1 + + 10.10.0.99/32 + + 10.10.0.99/32 + + + + + HostIP + eth0 + + 10.0.0.100/24 + + 10.0.0.100/24 + + + HostIP + eth0 + + 2603:10e2:0:2902::8/64 + + 2603:10e2:0:2902::8/64 + + + + + + + switch-t0 + + + PortChannel01 + fortyGigE0/112 + + + + PortChannel02 + fortyGigE0/116 + + + + PortChannel03 + fortyGigE0/120 + + + + PortChannel04 + fortyGigE0/124 + + + + + + Vlan1000 + fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 + False + 0.0.0.0/0 + + + 192.0.0.1;192.0.0.2 + 1000 + 1000 + 192.168.0.0/27 + + + + + Vlan99 + fortyGigE0/100 + False + 0.0.0.0/0 + + UserDefinedL2Vlan + 192.0.0.1;192.0.0.2 + 99 + 99 + + + + + + + + + PortChannel01 + 10.0.0.56/31 + + + + PortChannel01 + FC00::71/126 + + + + PortChannel02 + 10.0.0.58/31 + + + + PortChannel02 + FC00::75/126 + + + + PortChannel03 + 10.0.0.60/31 + + + + PortChannel03 + FC00::79/126 + + + + PortChannel04 + 10.0.0.62/31 + + + + PortChannel04 + FC00::7D/126 + + + + Vlan1000 + 192.168.0.1/27 + + + + + + ERSPAN + everflow + Everflow + + + ERSPANv6 + everflowV6 + Everflow + + + EGRESS_ERSPAN + everflow_egress + Everflow + + + PortChannel01;PortChannel02;PortChannel03;PortChannel04 + DataAclIngress + DataPlane + + + PortChannel01;PortChannel02 + DataAclEgress + DataPlane + + + SNMP + SNMP_ACL + SNMP + + + NTP + NTP_ACL + NTP + + + SSH + SSH_ACL + SSH + + + SSH + ROUTER-PROTECT + SSH + + + SNMP + ROUTER-PROTECT + SNMP + + + NTP + NTP_ACL + + + + + + + + + + DeviceInterfaceLink + ARISTA01T1 + Ethernet1/1 + switch-t0 + fortyGigE0/112 + + + DeviceInterfaceLink + ARISTA02T1 + Ethernet1/1 + switch-t0 + fortyGigE0/116 + + + DeviceInterfaceLink + ARISTA03T1 + Ethernet1/1 + switch-t0 + fortyGigE0/120 + + + DeviceInterfaceLink + ARISTA04T1 + Ethernet1/1 + switch-t0 + fortyGigE0/124 + 100000 + + + DeviceInterfaceLink + true + 100000 + switch-t0 + fortyGigE0/4 + true + ARISTA05T1 + Ethernet1/33 + true + + + DeviceInterfaceLink + Servers0 + eth0 + switch-t0 + fortyGigE0/4 + + + DeviceInterfaceLink + Servers100 + eth0 + switch-t0 + fortyGigE0/100 + + + + + switch-t0 + Force10-S6000 + + + ARISTA01T1 + Arista + + + ARISTA02T1 + Arista + + + ARISTA03T1 + Arista + + + ARISTA04T1 + Arista + + + + + + + switch-t0 + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + + + + + + + + + + + FECDisabled + + True + + + ARISTA05T1:Ethernet1/33;switch-t0:fortyGigE0/4 + + + + + + FECDisabled + + True + + + ARISTA06T1:Ethernet1/34;switch-t0:fortyGigE0/8 + + + + switch-t0 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t0-sample-port-config.ini b/src/sonic-config-engine/tests/t0-sample-port-config.ini new file mode 100644 index 000000000000..06898f1d7964 --- /dev/null +++ b/src/sonic-config-engine/tests/t0-sample-port-config.ini @@ -0,0 +1,33 @@ +# name lanes alias +Ethernet0 29,30,31,32 fortyGigE0/0 +Ethernet4 25,26,27,28 fortyGigE0/4 +Ethernet8 37,38,39,40 fortyGigE0/8 +Ethernet12 33,34,35,36 fortyGigE0/12 +Ethernet16 41,42,43,44 fortyGigE0/16 +Ethernet20 45,46,47,48 fortyGigE0/20 +Ethernet24 5,6,7,8 fortyGigE0/24 +Ethernet28 1,2,3,4 fortyGigE0/28 +Ethernet32 9,10,11,12 fortyGigE0/32 +Ethernet36 13,14,15,16 fortyGigE0/36 +Ethernet40 21,22,23,24 fortyGigE0/40 +Ethernet44 17,18,19,20 fortyGigE0/44 +Ethernet48 49,50,51,52 fortyGigE0/48 +Ethernet52 53,54,55,56 fortyGigE0/52 +Ethernet56 61,62,63,64 fortyGigE0/56 +Ethernet60 57,58,59,60 fortyGigE0/60 +Ethernet64 65,66,67,68 fortyGigE0/64 +Ethernet68 69,70,71,72 fortyGigE0/68 +Ethernet72 77,78,79,80 fortyGigE0/72 +Ethernet76 73,74,75,76 fortyGigE0/76 +Ethernet80 105,106,107,108 fortyGigE0/80 +Ethernet84 109,110,111,112 fortyGigE0/84 +Ethernet88 117,118,119,120 fortyGigE0/88 +Ethernet92 113,114,115,116 fortyGigE0/92 +Ethernet96 121,122,123,124 fortyGigE0/96 +Ethernet100 125,126,127,128 fortyGigE0/100 +Ethernet104 85,86,87,88 fortyGigE0/104 +Ethernet108 81,82,83,84 fortyGigE0/108 +Ethernet112 89,90,91,92 fortyGigE0/112 +Ethernet116 93,94,95,96 fortyGigE0/116 +Ethernet120 97,98,99,100 fortyGigE0/120 +Ethernet124 101,102,103,104 fortyGigE0/124 diff --git a/src/sonic-config-engine/tests/t1-sample-graph-mlnx.xml b/src/sonic-config-engine/tests/t1-sample-graph-mlnx.xml new file mode 100644 index 000000000000..04fc88c34370 --- /dev/null +++ b/src/sonic-config-engine/tests/t1-sample-graph-mlnx.xml @@ -0,0 +1,2240 @@ + + + + + + ARISTA01T0 + 10.0.0.33 + arc-switch1026 + 10.0.0.32 + 1 + 10 + 3 + + + ARISTA01T0 + FC00::42 + arc-switch1026 + FC00::41 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.0 + ARISTA01T2 + 10.0.0.1 + 1 + 10 + 3 + + + arc-switch1026 + FC00::1 + ARISTA01T2 + FC00::2 + 1 + 10 + 3 + + + ARISTA02T0 + 10.0.0.35 + arc-switch1026 + 10.0.0.34 + 1 + 10 + 3 + + + ARISTA02T0 + FC00::46 + arc-switch1026 + FC00::45 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.2 + ARISTA02T2 + 10.0.0.3 + 1 + 10 + 3 + + + arc-switch1026 + FC00::5 + ARISTA02T2 + FC00::6 + 1 + 10 + 3 + + + ARISTA03T0 + 10.0.0.37 + arc-switch1026 + 10.0.0.36 + 1 + 10 + 3 + + + ARISTA03T0 + FC00::4A + arc-switch1026 + FC00::49 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.4 + ARISTA03T2 + 10.0.0.5 + 1 + 10 + 3 + + + arc-switch1026 + FC00::9 + ARISTA03T2 + FC00::A + 1 + 10 + 3 + + + ARISTA04T0 + 10.0.0.39 + arc-switch1026 + 10.0.0.38 + 1 + 10 + 3 + + + ARISTA04T0 + FC00::4E + arc-switch1026 + FC00::4D + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.6 + ARISTA04T2 + 10.0.0.7 + 1 + 10 + 3 + + + arc-switch1026 + FC00::D + ARISTA04T2 + FC00::E + 1 + 10 + 3 + + + ARISTA05T0 + 10.0.0.41 + arc-switch1026 + 10.0.0.40 + 1 + 10 + 3 + + + ARISTA05T0 + FC00::52 + arc-switch1026 + FC00::51 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.8 + ARISTA05T2 + 10.0.0.9 + 1 + 10 + 3 + + + arc-switch1026 + FC00::11 + ARISTA05T2 + FC00::12 + 1 + 10 + 3 + + + ARISTA06T0 + 10.0.0.43 + arc-switch1026 + 10.0.0.42 + 1 + 10 + 3 + + + ARISTA06T0 + FC00::56 + arc-switch1026 + FC00::55 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.10 + ARISTA06T2 + 10.0.0.11 + 1 + 10 + 3 + + + arc-switch1026 + FC00::15 + ARISTA06T2 + FC00::16 + 1 + 10 + 3 + + + ARISTA07T0 + 10.0.0.45 + arc-switch1026 + 10.0.0.44 + 1 + 10 + 3 + + + ARISTA07T0 + FC00::5A + arc-switch1026 + FC00::59 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.12 + ARISTA07T2 + 10.0.0.13 + 1 + 10 + 3 + + + arc-switch1026 + FC00::19 + ARISTA07T2 + FC00::1A + 1 + 10 + 3 + + + ARISTA08T0 + 10.0.0.47 + arc-switch1026 + 10.0.0.46 + 1 + 10 + 3 + + + ARISTA08T0 + FC00::5E + arc-switch1026 + FC00::5D + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.14 + ARISTA08T2 + 10.0.0.15 + 1 + 10 + 3 + + + arc-switch1026 + FC00::1D + ARISTA08T2 + FC00::1E + 1 + 10 + 3 + + + ARISTA09T0 + 10.0.0.49 + arc-switch1026 + 10.0.0.48 + 1 + 10 + 3 + + + ARISTA09T0 + FC00::62 + arc-switch1026 + FC00::61 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.16 + ARISTA09T2 + 10.0.0.17 + 1 + 10 + 3 + + + arc-switch1026 + FC00::21 + ARISTA09T2 + FC00::22 + 1 + 10 + 3 + + + ARISTA10T0 + 10.0.0.51 + arc-switch1026 + 10.0.0.50 + 1 + 10 + 3 + + + ARISTA10T0 + FC00::66 + arc-switch1026 + FC00::65 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.18 + ARISTA10T2 + 10.0.0.19 + 1 + 10 + 3 + + + arc-switch1026 + FC00::25 + ARISTA10T2 + FC00::26 + 1 + 10 + 3 + + + ARISTA11T0 + 10.0.0.53 + arc-switch1026 + 10.0.0.52 + 1 + 10 + 3 + + + ARISTA11T0 + FC00::6A + arc-switch1026 + FC00::69 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.20 + ARISTA11T2 + 10.0.0.21 + 1 + 10 + 3 + + + arc-switch1026 + FC00::29 + ARISTA11T2 + FC00::2A + 1 + 10 + 3 + + + ARISTA12T0 + 10.0.0.55 + arc-switch1026 + 10.0.0.54 + 1 + 10 + 3 + + + ARISTA12T0 + FC00::6E + arc-switch1026 + FC00::6D + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.22 + ARISTA12T2 + 10.0.0.23 + 1 + 10 + 3 + + + arc-switch1026 + FC00::2D + ARISTA12T2 + FC00::2E + 1 + 10 + 3 + + + ARISTA13T0 + 10.0.0.57 + arc-switch1026 + 10.0.0.56 + 1 + 10 + 3 + + + ARISTA13T0 + FC00::72 + arc-switch1026 + FC00::71 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.24 + ARISTA13T2 + 10.0.0.25 + 1 + 10 + 3 + + + arc-switch1026 + FC00::31 + ARISTA13T2 + FC00::32 + 1 + 10 + 3 + + + ARISTA14T0 + 10.0.0.59 + arc-switch1026 + 10.0.0.58 + 1 + 10 + 3 + + + ARISTA14T0 + FC00::76 + arc-switch1026 + FC00::75 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.26 + ARISTA14T2 + 10.0.0.27 + 1 + 10 + 3 + + + arc-switch1026 + FC00::35 + ARISTA14T2 + FC00::36 + 1 + 10 + 3 + + + ARISTA15T0 + 10.0.0.61 + arc-switch1026 + 10.0.0.60 + 1 + 10 + 3 + + + ARISTA15T0 + FC00::7A + arc-switch1026 + FC00::79 + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.28 + ARISTA15T2 + 10.0.0.29 + 1 + 10 + 3 + + + arc-switch1026 + FC00::39 + ARISTA15T2 + FC00::3A + 1 + 10 + 3 + + + ARISTA16T0 + 10.0.0.63 + arc-switch1026 + 10.0.0.62 + 1 + 10 + 3 + + + ARISTA16T0 + FC00::7E + arc-switch1026 + FC00::7D + 1 + 10 + 3 + + + arc-switch1026 + 10.0.0.30 + ARISTA16T2 + 10.0.0.31 + 1 + 10 + 3 + + + arc-switch1026 + FC00::3D + ARISTA16T2 + FC00::3E + 1 + 10 + 3 + + + + + 65100 + arc-switch1026 + + +
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 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + 10.224.23.80/24 + + 10.224.23.80/24 + + + V6HostIP + eth0 + + FC00:2::32/64 + + FC00:2::32/64 + + + + + + arc-switch1026 + + + + + + Ethernet0 + 10.0.0.0/31 + + + + Ethernet0 + FC00::1/126 + + + + Ethernet4 + 10.0.0.2/31 + + + + Ethernet4 + FC00::5/126 + + + + Ethernet8 + 10.0.0.4/31 + + + + Ethernet8 + FC00::9/126 + + + + Ethernet12 + 10.0.0.6/31 + + + + Ethernet12 + FC00::D/126 + + + + Ethernet16 + 10.0.0.8/31 + + + + Ethernet16 + FC00::11/126 + + + + Ethernet20 + 10.0.0.10/31 + + + + Ethernet20 + FC00::15/126 + + + + Ethernet24 + 10.0.0.12/31 + + + + Ethernet24 + FC00::19/126 + + + + Ethernet28 + 10.0.0.14/31 + + + + Ethernet28 + FC00::1D/126 + + + + Ethernet32 + 10.0.0.16/31 + + + + Ethernet32 + FC00::21/126 + + + + Ethernet36 + 10.0.0.18/31 + + + + Ethernet36 + FC00::25/126 + + + + Ethernet40 + 10.0.0.20/31 + + + + Ethernet40 + FC00::29/126 + + + + Ethernet44 + 10.0.0.22/31 + + + + Ethernet44 + FC00::2D/126 + + + + Ethernet48 + 10.0.0.24/31 + + + + Ethernet48 + FC00::31/126 + + + + Ethernet52 + 10.0.0.26/31 + + + + Ethernet52 + FC00::35/126 + + + + Ethernet56 + 10.0.0.28/31 + + + + Ethernet56 + FC00::39/126 + + + + Ethernet60 + 10.0.0.30/31 + + + + Ethernet60 + FC00::3D/126 + + + + Ethernet64 + 10.0.0.32/31 + + + + Ethernet64 + FC00::41/126 + + + + Ethernet68 + 10.0.0.34/31 + + + + Ethernet68 + FC00::45/126 + + + + Ethernet72 + 10.0.0.36/31 + + + + Ethernet72 + FC00::49/126 + + + + Ethernet76 + 10.0.0.38/31 + + + + Ethernet76 + FC00::4D/126 + + + + Ethernet80 + 10.0.0.40/31 + + + + Ethernet80 + FC00::51/126 + + + + Ethernet84 + 10.0.0.42/31 + + + + Ethernet84 + FC00::55/126 + + + + Ethernet88 + 10.0.0.44/31 + + + + Ethernet88 + FC00::59/126 + + + + Ethernet92 + 10.0.0.46/31 + + + + Ethernet92 + FC00::5D/126 + + + + Ethernet96 + 10.0.0.48/31 + + + + Ethernet96 + FC00::61/126 + + + + Ethernet100 + 10.0.0.50/31 + + + + Ethernet100 + FC00::65/126 + + + + Ethernet104 + 10.0.0.52/31 + + + + Ethernet104 + FC00::69/126 + + + + Ethernet108 + 10.0.0.54/31 + + + + Ethernet108 + FC00::6D/126 + + + + Ethernet112 + 10.0.0.56/31 + + + + Ethernet112 + FC00::71/126 + + + + Ethernet116 + 10.0.0.58/31 + + + + Ethernet116 + FC00::75/126 + + + + Ethernet120 + 10.0.0.60/31 + + + + Ethernet120 + FC00::79/126 + + + + Ethernet124 + 10.0.0.62/31 + + + + Ethernet124 + FC00::7D/126 + + + + + + + + + + + + DeviceInterfaceLink + arc-switch1026 + Ethernet0 + ARISTA01T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet4 + ARISTA02T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet8 + ARISTA03T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet12 + ARISTA04T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet16 + ARISTA05T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet20 + ARISTA06T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet24 + ARISTA07T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet28 + ARISTA08T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet32 + ARISTA09T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet36 + ARISTA10T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet40 + ARISTA11T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet44 + ARISTA12T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet48 + ARISTA13T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet52 + ARISTA14T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet56 + ARISTA15T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet60 + ARISTA16T2 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet64 + ARISTA01T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet68 + ARISTA02T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet72 + ARISTA03T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet76 + ARISTA04T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet80 + ARISTA05T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet84 + ARISTA06T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet88 + ARISTA07T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet92 + ARISTA08T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet96 + ARISTA09T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet100 + ARISTA10T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet104 + ARISTA11T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet108 + ARISTA12T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet112 + ARISTA13T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet116 + ARISTA14T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet120 + ARISTA15T0 + Ethernet1 + + + DeviceInterfaceLink + arc-switch1026 + Ethernet124 + ARISTA16T0 + Ethernet1 + + + + + arc-switch1026 + ACS-MSN2700 + + 10.224.23.80 + + + + "ARISTA01T0" + Arista-VM + + 10.224.23.196 + + + + "ARISTA01T2" + Arista-VM + + 10.224.23.180 + + + + "ARISTA02T0" + Arista-VM + + 10.224.23.197 + + + + "ARISTA02T2" + Arista-VM + + 10.224.23.181 + + + + "ARISTA03T0" + Arista-VM + + 10.224.23.198 + + + + "ARISTA03T2" + Arista-VM + + 10.224.23.182 + + + + "ARISTA04T0" + Arista-VM + + 10.224.23.199 + + + + "ARISTA04T2" + Arista-VM + + 10.224.23.183 + + + + "ARISTA05T0" + Arista-VM + + 10.224.23.200 + + + + "ARISTA05T2" + Arista-VM + + 10.224.23.184 + + + + "ARISTA06T0" + Arista-VM + + 10.224.23.201 + + + + "ARISTA06T2" + Arista-VM + + 10.224.23.185 + + + + "ARISTA07T0" + Arista-VM + + 10.224.23.202 + + + + "ARISTA07T2" + Arista-VM + + 10.224.23.186 + + + + "ARISTA08T0" + Arista-VM + + 10.224.23.203 + + + + "ARISTA08T2" + Arista-VM + + 10.224.23.187 + + + + "ARISTA09T0" + Arista-VM + + 10.224.23.152 + + + + "ARISTA09T2" + Arista-VM + + 10.224.23.188 + + + + "ARISTA10T0" + Arista-VM + + 10.224.23.153 + + + + "ARISTA10T2" + Arista-VM + + 10.224.23.189 + + + + "ARISTA11T0" + Arista-VM + + 10.224.23.154 + + + + "ARISTA11T2" + Arista-VM + + 10.224.23.190 + + + + "ARISTA12T0" + Arista-VM + + 10.224.23.155 + + + + "ARISTA12T2" + Arista-VM + + 10.224.23.191 + + + + "ARISTA13T0" + Arista-VM + + 10.224.23.156 + + + + "ARISTA13T2" + Arista-VM + + 10.224.23.192 + + + + "ARISTA14T0" + Arista-VM + + 10.224.23.157 + + + + "ARISTA14T2" + Arista-VM + + 10.224.23.193 + + + + "ARISTA15T0" + Arista-VM + + 10.224.23.158 + + + + "ARISTA15T2" + Arista-VM + + 10.224.23.194 + + + + "ARISTA16T0" + Arista-VM + + 10.224.23.159 + + + + "ARISTA16T2" + Arista-VM + + 10.224.23.195 + + + + + + + true + + + DeviceInterface + + true + true + 1 + Ethernet0 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet4 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet8 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet12 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet16 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet20 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet24 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet28 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet32 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet36 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet40 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet44 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet48 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet52 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet56 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet60 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet64 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet68 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet72 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet76 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet80 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet84 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet88 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet92 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet96 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet100 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet104 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet108 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet112 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet116 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet120 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + true + 1 + Ethernet124 + + false + 0 + 0 + 40000 + + + true + 0 + ACS-MSN2700 + + + + + + + arc-switch1026 + + + DhcpResources + + 10.0.0.1 + + + NTPResources + + 10.0.0.1;10.0.0.2 + + + DeploymentId + + 1 + + + QosProfile + + Profile0 + + + RadiusResources + + + + + SnmpResources + + 10.0.0.9 + + + SyslogResources + + 10.0.0.5;10.0.0.6 + + + TacacsGroup + + testlab + + + TacacsServer + + 10.0.0.9;10.0.0.8 + + + ForcedMgmtRoutes + + 10.0.0.100/31;10.250.0.8;10.255.0.0/28 + + + ErspanDestinationIpv4 + + 10.0.0.7 + + + + + + + arc-switch1026 + ACS-MSN2700 +
diff --git a/src/sonic-config-engine/tests/t2-chassis-fe-graph-pc.xml b/src/sonic-config-engine/tests/t2-chassis-fe-graph-pc.xml new file mode 100644 index 000000000000..3fb744ce91fd --- /dev/null +++ b/src/sonic-config-engine/tests/t2-chassis-fe-graph-pc.xml @@ -0,0 +1,324 @@ + + + + + + SpineFront01 + 192.168.0.2 + Leaf01 + 192.168.0.1 + 1 + 10 + 3 + + + SpineFront01 + 172.16.0.1 + SpineBack01 + 172.16.0.2 + 1 + 10 + 3 + + + SpineFront01 + 172.16.0.9 + SpineBack02 + 172.16.0.10 + 1 + 10 + 3 + + + SpineFront01 + 4.0.0.0 + SpineFront02 + 4.0.0.1 + 10 + 10 + 3 + + + + + 4000 + SpineFront01 + + +
192.168.0.1
+ + + +
+ +
172.16.0.2
+ + + +
+ +
172.16.0.10
+ + + +
+ +
4.0.0.1
+ + + +
+
+ +
+ + 3000 + Leaf01 + + + + 5000 + SpineBack01 + + + + 5000 + SpineBack02 + + + + 4000 + SpineFront02 + + +
+
+ + + + + + HostIP + Loopback0 + + 4.0.0.0/32 + + 4.0.0.0/32 + + + + + + + + SpineFront01 + + + PortChannel0 + Ethernet0;Ethernet4 + + + + PortChannel4 + Ethernet8;Ethernet12 + + + + PortChannel8 + Ethernet16;Ethernet20 + + + + + + + + PortChannel0 + 192.168.0.2/30 + + + + PortChannel4 + 172.16.0.1/30 + + + + PortChannel8 + 172.16.0.9/30 + + + + + + + + + + + + DeviceInterfaceLink + Leaf01 + Ethernet0 + SpineFront01 + Ethernet0 + + + DeviceInterfaceLink + Leaf01 + Ethernet4 + SpineFront01 + Ethernet4 + + + DeviceInterfaceLink + SpineBack01 + Ethernet8 + SpineFront01 + Ethernet8 + + + DeviceInterfaceLink + SpineBack01 + Ethernet12 + SpineFront01 + Ethernet12 + + + DeviceInterfaceLink + SpineBack02 + Ethernet16 + SpineFront01 + Ethernet16 + + + DeviceInterfaceLink + SpineBack02 + Ethernet20 + SpineFront01 + Ethernet20 + + + + + SpineFront01 + Force10-S6000 + + + SpineFront02 + Force10-S6000 + + + Leaf01 + Force10-S6000 + + + SpineBack01 + Force10-S6000 + + + SpineBack02 + Force10-S6000 + + + + + + true + + + DeviceInterface + + true + false + 1 + Ethernet0 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + false + 1 + Ethernet4 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + false + 1 + Ethernet8 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + false + 1 + Ethernet12 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + false + 1 + Ethernet16 + + false + 0 + 0 + 25000 + + + DeviceInterface + + true + false + 1 + Ethernet20 + + false + 0 + 0 + 25000 + + + false + 0 + Force10-S6000 + + + + + + + SpineFront01 + + + + + + SpineFront01 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t2-chassis-fe-graph-vni.xml b/src/sonic-config-engine/tests/t2-chassis-fe-graph-vni.xml new file mode 100644 index 000000000000..f820b180f701 --- /dev/null +++ b/src/sonic-config-engine/tests/t2-chassis-fe-graph-vni.xml @@ -0,0 +1,249 @@ + + + + + + SpineFront01 + 192.168.0.2 + Leaf01 + 192.168.0.1 + 1 + 10 + 3 + + + SpineFront01 + 172.16.0.1 + SpineBack01 + 172.16.0.2 + 1 + 10 + 3 + + + SpineFront01 + 172.16.0.9 + SpineBack02 + 172.16.0.10 + 1 + 10 + 3 + + + SpineFront01 + 4.0.0.0 + SpineFront02 + 4.0.0.1 + 10 + 10 + 3 + + + + + 4000 + SpineFront01 + + +
192.168.0.1
+ + + +
+ +
172.16.0.2
+ + + +
+ +
172.16.0.10
+ + + +
+ +
4.0.0.1
+ + + +
+
+ +
+ + 3000 + Leaf01 + + + + 5000 + SpineBack01 + + + + 5000 + SpineBack02 + + + + 4000 + SpineFront02 + + +
+
+ + + 9000 + + + + HostIP + Loopback0 + + 4.0.0.0/32 + + 4.0.0.0/32 + + + + + + + + SpineFront01 + + + + + + Ethernet0 + 192.168.0.2/30 + + + + Ethernet4 + 172.16.0.1/30 + + + + Ethernet8 + 172.16.0.9/30 + + + + + + + + + + + + DeviceInterfaceLink + Leaf01 + Ethernet4 + SpineFront01 + Ethernet0 + + + DeviceInterfaceLink + SpineBack01 + Ethernet0 + SpineFront01 + Ethernet4 + + + DeviceInterfaceLink + SpineBack02 + Ethernet4 + SpineFront01 + Ethernet8 + + + + + SpineFront01 + Force10-S6000 + + + SpineFront02 + Force10-S6000 + + + Leaf01 + Force10-S6000 + + + SpineBack01 + Force10-S6000 + + + SpineBack02 + Force10-S6000 + + + + + + true + + + DeviceInterface + + true + false + 1 + Ethernet0 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + false + 1 + Ethernet4 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + false + 1 + Ethernet8 + + false + 0 + 0 + 40000 + + + false + 0 + Force10-S6000 + + + + + + + SpineFront01 + + + + + + SpineFront01 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t2-chassis-fe-graph.xml b/src/sonic-config-engine/tests/t2-chassis-fe-graph.xml new file mode 100644 index 000000000000..76320b766be5 --- /dev/null +++ b/src/sonic-config-engine/tests/t2-chassis-fe-graph.xml @@ -0,0 +1,248 @@ + + + + + + SpineFront01 + 192.168.0.2 + Leaf01 + 192.168.0.1 + 1 + 10 + 3 + + + SpineFront01 + 172.16.0.1 + SpineBack01 + 172.16.0.2 + 1 + 10 + 3 + + + SpineFront01 + 172.16.0.9 + SpineBack02 + 172.16.0.10 + 1 + 10 + 3 + + + SpineFront01 + 4.0.0.0 + SpineFront02 + 4.0.0.1 + 10 + 10 + 3 + + + + + 4000 + SpineFront01 + + +
192.168.0.1
+ + + +
+ +
172.16.0.2
+ + + +
+ +
172.16.0.10
+ + + +
+ +
4.0.0.1
+ + + +
+
+ +
+ + 3000 + Leaf01 + + + + 5000 + SpineBack01 + + + + 5000 + SpineBack02 + + + + 4000 + SpineFront02 + + +
+
+ + + + + + HostIP + Loopback0 + + 4.0.0.0/32 + + 4.0.0.0/32 + + + + + + + + SpineFront01 + + + + + + Ethernet0 + 192.168.0.2/30 + + + + Ethernet4 + 172.16.0.1/30 + + + + Ethernet8 + 172.16.0.9/30 + + + + + + + + + + + + DeviceInterfaceLink + Leaf01 + Ethernet4 + SpineFront01 + Ethernet0 + + + DeviceInterfaceLink + SpineBack01 + Ethernet0 + SpineFront01 + Ethernet4 + + + DeviceInterfaceLink + SpineBack02 + Ethernet4 + SpineFront01 + Ethernet8 + + + + + SpineFront01 + Force10-S6000 + + + SpineFront02 + Force10-S6000 + + + Leaf01 + Force10-S6000 + + + SpineBack01 + Force10-S6000 + + + SpineBack02 + Force10-S6000 + + + + + + true + + + DeviceInterface + + true + false + 1 + Ethernet0 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + false + 1 + Ethernet4 + + false + 0 + 0 + 40000 + + + DeviceInterface + + true + false + 1 + Ethernet8 + + false + 0 + 0 + 40000 + + + false + 0 + Force10-S6000 + + + + + + + SpineFront01 + + + + + + SpineFront01 + Force10-S6000 +
diff --git a/src/sonic-config-engine/tests/t2-chassis-fe-port-config.ini b/src/sonic-config-engine/tests/t2-chassis-fe-port-config.ini new file mode 100644 index 000000000000..1a9786c590e6 --- /dev/null +++ b/src/sonic-config-engine/tests/t2-chassis-fe-port-config.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 0,1,2,3 +Ethernet4 4,5,6,7 +Ethernet8 8,9,10,11 +Ethernet12 12,13,14,15 +Ethernet16 16,17,18,19 +Ethernet20 20,21,22,23 +Ethernet24 24,25,26,27 +Ethernet28 28,29,30,31 +Ethernet32 32,33,34,35 +Ethernet36 36,37,38,39 +Ethernet40 40,41,42,43 +Ethernet44 44,45,46,47 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 64,65,66,67 +Ethernet68 68,69,70,71 +Ethernet72 72,73,74,75 +Ethernet76 76,77,78,79 +Ethernet80 80,81,82,83 +Ethernet84 84,85,86,87 +Ethernet88 88,89,90,91 +Ethernet92 92,93,94,95 +Ethernet96 96,97,98,99 +Ethernet100 100,101,102,103 +Ethernet104 104,105,106,107 +Ethernet108 108,109,110,111 +Ethernet112 112,113,114,115 +Ethernet116 116,117,118,119 +Ethernet120 120,121,122,123 +Ethernet124 124,125,126,127 \ No newline at end of file diff --git a/src/sonic-config-engine/tests/test.j2 b/src/sonic-config-engine/tests/test.j2 new file mode 100644 index 000000000000..787a1f0a2c41 --- /dev/null +++ b/src/sonic-config-engine/tests/test.j2 @@ -0,0 +1,3 @@ +{% for item in yml_item -%} +{{ item }} +{% endfor %} diff --git a/src/sonic-config-engine/tests/test.yml b/src/sonic-config-engine/tests/test.yml new file mode 100644 index 000000000000..dc08eb66bed1 --- /dev/null +++ b/src/sonic-config-engine/tests/test.yml @@ -0,0 +1,3 @@ +yml_item: + - value1 + - value2 diff --git a/src/sonic-config-engine/tests/test2.j2 b/src/sonic-config-engine/tests/test2.j2 new file mode 100644 index 000000000000..df36b83cf382 --- /dev/null +++ b/src/sonic-config-engine/tests/test2.j2 @@ -0,0 +1 @@ +{{ key1 }} diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py new file mode 100644 index 000000000000..9fbf351c3a47 --- /dev/null +++ b/src/sonic-config-engine/tests/test_cfggen.py @@ -0,0 +1,566 @@ +import json +import subprocess +import os + +import tests.common_utils as utils + +from unittest import TestCase + +TOR_ROUTER = 'ToRRouter' +BACKEND_TOR_ROUTER = 'BackEndToRRouter' + +class TestCfgGen(TestCase): + + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.sample_graph = os.path.join(self.test_dir, 'sample_graph.xml') + self.sample_graph_t0 = os.path.join(self.test_dir, 't0-sample-graph.xml') + self.sample_graph_simple = os.path.join(self.test_dir, 'simple-sample-graph.xml') + self.sample_graph_simple_case = os.path.join(self.test_dir, 'simple-sample-graph-case.xml') + self.sample_graph_metadata = os.path.join(self.test_dir, 'simple-sample-graph-metadata.xml') + self.sample_graph_pc_test = os.path.join(self.test_dir, 'pc-test-graph.xml') + self.sample_graph_bgp_speaker = os.path.join(self.test_dir, 't0-sample-bgp-speaker.xml') + self.sample_device_desc = os.path.join(self.test_dir, 'device.xml') + self.port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') + self.mlnx_port_config = os.path.join(self.test_dir, 'mellanox-sample-port-config.ini') + self.output_file = os.path.join(self.test_dir, 'output') + self.output2_file = os.path.join(self.test_dir, 'output2') + self.ecmp_graph = os.path.join(self.test_dir, 'fg-ecmp-sample-minigraph.xml') + + def tearDown(self): + try: + os.remove(self.output_file) + os.remove(self.output2_file) + except OSError: + pass + + def run_script(self, argument, check_stderr=False): + print('\n Running sonic-cfggen ' + argument) + if check_stderr: + output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + if utils.PY3x: + output = output.decode() + + linecount = output.strip().count('\n') + if linecount <= 0: + print(' Output: ' + output.strip()) + else: + print(' Output: ({0} lines, {1} bytes)'.format(linecount + 1, len(output))) + return output + + def test_dummy_run(self): + argument = '' + output = self.run_script(argument) + self.assertEqual(output, '') + + def test_device_desc(self): + argument = '-v "DEVICE_METADATA[\'localhost\'][\'hwsku\']" -M "' + self.sample_device_desc + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'ACS-MSN2700') + + def test_device_desc_mgmt_ip(self): + argument = '-v "(MGMT_INTERFACE.keys()|list)[0]" -M "' + self.sample_device_desc + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "('eth0', '10.0.1.5/28')") + + def test_minigraph_sku(self): + argument = '-v "DEVICE_METADATA[\'localhost\'][\'hwsku\']" -m "' + self.sample_graph + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'Force10-Z9100') + + def test_minigraph_region(self): + argument = '-v "DEVICE_METADATA[\'localhost\'][\'region\']" -m "' + self.sample_graph_metadata + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'usfoo') + + def test_minigraph_cloudtype(self): + argument = '-v "DEVICE_METADATA[\'localhost\'][\'cloudtype\']" -m "' + self.sample_graph_metadata + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'Public') + + def test_minigraph_resourcetype(self): + argument = '-v "DEVICE_METADATA[\'localhost\'][\'resource_type\']" -m "' + self.sample_graph_metadata + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'resource_type_x') + + def test_print_data(self): + argument = '-m "' + self.sample_graph + '" --print-data' + output = self.run_script(argument) + self.assertTrue(len(output.strip()) > 0) + + def test_jinja_expression(self, graph=None, expected_router_type='LeafRouter'): + if graph is None: + graph = self.sample_graph + argument = '-m "' + graph + '" -v "DEVICE_METADATA[\'localhost\'][\'type\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), expected_router_type) + + def test_additional_json_data(self): + argument = '-a \'{"key1":"value1"}\' -v key1' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'value1') + + def test_additional_json_data_level1_key(self): + argument = '-a \'{"k1":{"k11":"v11","k12":"v12"}, "k2":{"k22":"v22"}}\' --var-json k1' + output = self.run_script(argument) + self.assertEqual(utils.to_dict(output.strip()), utils.to_dict('{\n "k11": "v11", \n "k12": "v12"\n}')) + + def test_additional_json_data_level2_key(self): + argument = '-a \'{"k1":{"k11":"v11","k12":"v12"},"k2":{"k22":"v22"}}\' --var-json k1 -K k11' + output = self.run_script(argument) + self.assertEqual(utils.to_dict(output.strip()), utils.to_dict('{\n "k11": "v11"\n}')) + + def test_var_json_data(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" --var-json VLAN_MEMBER' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + '{\n "Vlan1000|Ethernet8": {\n "tagging_mode": "untagged"\n },' + ' \n "Vlan2000|Ethernet12": {\n "tagging_mode": "tagged"\n },' + ' \n "Vlan2001|Ethernet12": {\n "tagging_mode": "tagged"\n },' + ' \n "Vlan2020|Ethernet12": {\n "tagging_mode": "tagged"\n }\n}' + ) + ) + + def test_read_yaml(self): + argument = '-v yml_item -y ' + os.path.join(self.test_dir, 'test.yml') + output = self.run_script(argument) + self.assertEqual(output.strip(), '[\'value1\', \'value2\']') + + def test_render_template(self): + argument = '-y ' + os.path.join(self.test_dir, 'test.yml') + ' -t ' + os.path.join(self.test_dir, 'test.j2') + output = self.run_script(argument) + self.assertEqual(output.strip(), 'value1\nvalue2') + + def test_template_batch_mode(self): + argument = '-y ' + os.path.join(self.test_dir, 'test.yml') + argument += ' -a \'{"key1":"value"}\'' + argument += ' -t ' + os.path.join(self.test_dir, 'test.j2') + ',' + self.output_file + argument += ' -t ' + os.path.join(self.test_dir, 'test2.j2') + ',' + self.output2_file + output = self.run_script(argument) + assert(os.path.exists(self.output_file)) + assert(os.path.exists(self.output2_file)) + with open(self.output_file) as tf: + self.assertEqual(tf.read().strip(), 'value1\nvalue2') + with open(self.output2_file) as tf: + self.assertEqual(tf.read().strip(), 'value') + + def test_template_json_batch_mode(self): + data = {"key1_1":"value1_1", "key1_2":"value1_2", "key2_1":"value2_1", "key2_2":"value2_2"} + argument = " -a '{0}'".format(repr(data).replace('\'', '"')) + argument += ' -t ' + os.path.join(self.test_dir, 'sample-template-1.json.j2') + ",config-db" + argument += ' -t ' + os.path.join(self.test_dir, 'sample-template-2.json.j2') + ",config-db" + argument += ' --print-data' + output = self.run_script(argument) + output_data = json.loads(output) + for key, value in data.items(): + self.assertEqual(output_data[key.replace("key", "jk")], value) + + # FIXME: This test depends heavily on the ordering of the interfaces and + # it is not at all intuitive what that ordering should be. Could make it + # more robust by adding better parsing logic. + def test_minigraph_acl(self): + argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v ACL_TABLE' + output = self.run_script(argument, True) + self.assertEqual( + utils.to_dict(output.strip().replace("Warning: Ignoring Control Plane ACL NTP_ACL without type\n", '')), + utils.to_dict( + "{'NTP_ACL': {'services': ['NTP'], 'type': 'CTRLPLANE', 'policy_desc': 'NTP_ACL', 'stage': 'ingress'}, " + "'EVERFLOW': {'stage': 'ingress', 'type': 'MIRROR', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04', 'Ethernet4', 'Ethernet100'], 'policy_desc': 'EVERFLOW'}, " + "'EVERFLOW_EGRESS': {'stage': 'egress', 'type': 'MIRROR', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04', 'Ethernet4', 'Ethernet100'], 'policy_desc': 'EVERFLOW_EGRESS'}, " + "'ROUTER_PROTECT': {'services': ['SSH', 'SNMP'], 'type': 'CTRLPLANE', 'policy_desc': 'ROUTER_PROTECT', 'stage': 'ingress'}, " + "'DATAACLINGRESS': {'stage': 'ingress', 'type': 'L3', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04'], 'policy_desc': 'DATAACLINGRESS'}, " + "'SNMP_ACL': {'services': ['SNMP'], 'type': 'CTRLPLANE', 'policy_desc': 'SNMP_ACL', 'stage': 'ingress'}, " + "'SSH_ACL': {'services': ['SSH'], 'type': 'CTRLPLANE', 'policy_desc': 'SSH_ACL', 'stage': 'ingress'}, " + "'DATAACLEGRESS': {'stage': 'egress', 'type': 'L3', 'ports': ['PortChannel01', 'PortChannel02'], 'policy_desc': 'DATAACLEGRESS'}, " + "'EVERFLOWV6': {'stage': 'ingress', 'type': 'MIRRORV6', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04', 'Ethernet4', 'Ethernet100'], 'policy_desc': 'EVERFLOWV6'}}" + ) + ) + +# everflow portion is not used +# def test_minigraph_everflow(self): +# argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v MIRROR_SESSION' +# output = self.run_script(argument) +# self.assertEqual(output.strip(), "{'everflow0': {'src_ip': '10.1.0.32', 'dst_ip': '2.2.2.2'}}") + + def test_minigraph_mgmt_ports(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v MGMT_PORT' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'eth0': {'alias': 'Management0', 'admin_status': 'up'}}") + ) + + def test_minigraph_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "INTERFACE.keys()|list"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[('Ethernet0', '10.0.0.58/31'), 'Ethernet0', ('Ethernet0', 'FC00::75/126')]") + + def test_minigraph_vlans(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + "{'Vlan1000': {'alias': 'ab1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '1000'}, " + "'Vlan2001': {'alias': 'ab3', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '2001'}," + "'Vlan2000': {'alias': 'ab2', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '2000'}," + "'Vlan2020': {'alias': 'kk1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '2020'}}" + ) + ) + + def test_minigraph_vlan_members(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN_MEMBER' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + "{('Vlan2000', 'Ethernet12'): {'tagging_mode': 'tagged'}, " + "('Vlan1000', 'Ethernet8'): {'tagging_mode': 'untagged'}, " + "('Vlan2020', 'Ethernet12'): {'tagging_mode': 'tagged'}, " + "('Vlan2001', 'Ethernet12'): {'tagging_mode': 'tagged'}}" + ) + ) + + def test_minigraph_vlan_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE.keys()|list"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[('Vlan1000', '192.168.0.1/27'), 'Vlan1000']") + + def test_minigraph_ecmp_fg_nhg(self): + argument = '-m "' + self.ecmp_graph + '" -p "' + self.mlnx_port_config + '" -v \"FG_NHG.values()|list\"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[{'bucket_size': 120}, {'bucket_size': 120}]") + + def test_minigraph_ecmp_members(self): + argument = '-m "' + self.ecmp_graph + '" -p "' + self.mlnx_port_config + '" -v "FG_NHG_MEMBER.keys()|list|sort"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "['200.200.200.1', '200.200.200.10', '200.200.200.2', '200.200.200.3', '200.200.200.4', '200.200.200.5'," + " '200.200.200.6', '200.200.200.7', '200.200.200.8', '200.200.200.9', '200:200:200:200::1', '200:200:200:200::10'," + " '200:200:200:200::2', '200:200:200:200::3', '200:200:200:200::4', '200:200:200:200::5', '200:200:200:200::6'," + " '200:200:200:200::7', '200:200:200:200::8', '200:200:200:200::9']") + + def test_minigraph_ecmp_neighbors(self): + argument = '-m "' + self.ecmp_graph + '" -p "' + self.mlnx_port_config + '" -v "NEIGH.keys()|list|sort"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "['Vlan31|200.200.200.1', 'Vlan31|200.200.200.10', 'Vlan31|200.200.200.2', 'Vlan31|200.200.200.3'," + " 'Vlan31|200.200.200.4', 'Vlan31|200.200.200.5', 'Vlan31|200.200.200.6', 'Vlan31|200.200.200.7'," + " 'Vlan31|200.200.200.8', 'Vlan31|200.200.200.9', 'Vlan31|200:200:200:200::1', 'Vlan31|200:200:200:200::10'," + " 'Vlan31|200:200:200:200::2', 'Vlan31|200:200:200:200::3', 'Vlan31|200:200:200:200::4', 'Vlan31|200:200:200:200::5', " + "'Vlan31|200:200:200:200::6', 'Vlan31|200:200:200:200::7', 'Vlan31|200:200:200:200::8', 'Vlan31|200:200:200:200::9']") + + def test_minigraph_ecmp_prefixes(self): + argument = '-m "' + self.ecmp_graph + '" -p "' + self.mlnx_port_config + '" -v "FG_NHG_PREFIX.keys()|list|sort"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "['100.50.25.12/32', 'fc:5::/128']") + + + def test_minigraph_portchannels(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v PORTCHANNEL' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'PortChannel01': {'admin_status': 'up', 'min_links': '1', 'members': ['Ethernet4'], 'mtu': '9100'}}") + ) + + def test_minigraph_portchannel_with_more_member(self): + argument = '-m "' + self.sample_graph_pc_test + '" -p "' + self.port_config + '" -v PORTCHANNEL' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'PortChannel01': {'admin_status': 'up', 'min_links': '3', 'members': ['Ethernet112', 'Ethernet116', 'Ethernet120', 'Ethernet124'], 'mtu': '9100'}}") + ) + + def test_minigraph_portchannel_members(self): + argument = '-m "' + self.sample_graph_pc_test + '" -p "' + self.port_config + '" -v "PORTCHANNEL_MEMBER.keys()|list"' + output = self.run_script(argument) + self.assertEqual( + utils.liststr_to_dict(output.strip()), + utils.liststr_to_dict("[('PortChannel01', 'Ethernet120'), ('PortChannel01', 'Ethernet116'), ('PortChannel01', 'Ethernet124'), ('PortChannel01', 'Ethernet112')]") + ) + + def test_minigraph_portchannel_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORTCHANNEL_INTERFACE.keys()|list"' + output = self.run_script(argument) + self.assertEqual( + utils.liststr_to_dict(output.strip()), + utils.liststr_to_dict("['PortChannel01', ('PortChannel01', '10.0.0.56/31'), ('PortChannel01', 'FC00::71/126')]") + ) + + def test_minigraph_neighbors(self): + argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v "DEVICE_NEIGHBOR[\'Ethernet124\']"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'name': 'ARISTA04T1', 'port': 'Ethernet1/1'}") + ) + + # FIXME: This test depends heavily on the ordering of the interfaces and + # it is not at all intuitive what that ordering should be. Could make it + # more robust by adding better parsing logic. + def test_minigraph_extra_neighbors(self): + argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v DEVICE_NEIGHBOR' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + "{'Ethernet124': {'name': 'ARISTA04T1', 'port': 'Ethernet1/1'}, " + "'Ethernet120': {'name': 'ARISTA03T1', 'port': 'Ethernet1/1'}, " + "'Ethernet4': {'name': 'Servers0', 'port': 'eth0'}, " + "'Ethernet116': {'name': 'ARISTA02T1', 'port': 'Ethernet1/1'}, " + "'Ethernet100': {'name': 'Servers100', 'port': 'eth0'}, " + "'Ethernet112': {'name': 'ARISTA01T1', 'port': 'Ethernet1/1'}}") + ) + + def test_minigraph_port_description(self): + argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet124\']"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'lanes': '101,102,103,104', 'fec': 'rs', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/124', 'admin_status': 'up', 'speed': '100000', 'description': 'ARISTA04T1:Ethernet1/1'}") + ) + + def test_minigraph_port_fec_disabled(self): + # Test for FECDisabled + argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet4\']"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'lanes': '25,26,27,28', 'description': 'Servers0:eth0', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/4', 'admin_status': 'up', 'speed': '100000'}") + ) + + def test_minigraph_port_rs(self): + argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet124\']"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'lanes': '101,102,103,104', 'fec': 'rs', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/124', 'admin_status': 'up', 'speed': '100000', 'description': 'ARISTA04T1:Ethernet1/1'}") + ) + + def test_minigraph_bgp(self): + argument = '-m "' + self.sample_graph_bgp_speaker + '" -p "' + self.port_config + '" -v "BGP_NEIGHBOR[\'10.0.0.59\']"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'rrclient': 0, 'name': 'ARISTA02T1', 'local_addr': '10.0.0.58', 'nhopself': 0, 'holdtime': '180', 'asn': '64600', 'keepalive': '60'}") + ) + + def test_minigraph_peers_with_range(self): + argument = "-m " + self.sample_graph_bgp_speaker + " -p " + self.port_config + " -v \"BGP_PEER_RANGE.values()|list\"" + output = self.run_script(argument) + self.assertEqual( + utils.liststr_to_dict(output.strip()), + utils.liststr_to_dict("[{'src_address': '10.1.0.32', 'name': 'BGPSLBPassive', 'ip_range': ['10.10.10.10/26', '100.100.100.100/26']}]") + ) + + def test_minigraph_deployment_id(self): + argument = '-m "' + self.sample_graph_bgp_speaker + '" -p "' + self.port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'deployment_id\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "1") + + def test_minigraph_ethernet_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet8\']"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'lanes': '37,38,39,40', 'description': 'Interface description', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/8', 'admin_status': 'up', 'speed': '1000'}") + ) + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet12\']"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'lanes': '33,34,35,36', 'fec': 'rs', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/12', 'admin_status': 'up', 'speed': '100000', 'description': 'Interface description'}") + ) + + def test_minigraph_neighbor_interfaces(self): + argument = '-m "' + self.sample_graph_simple_case + '" -p "' + self.port_config + '" -v "PORT"' + output = self.run_script(argument) + + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + "{'Ethernet8': {'lanes': '37,38,39,40', 'description': 'Interface description', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/8', 'admin_status': 'up', 'speed': '40000', 'mux_cable': 'true'}, " + "'Ethernet0': {'lanes': '29,30,31,32', 'description': 'switch-01t1:port1', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/0', 'admin_status': 'up', 'speed': '10000'}, " + "'Ethernet4': {'lanes': '25,26,27,28', 'description': 'server1:port1', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/4', 'admin_status': 'up', 'speed': '25000', 'mux_cable': 'true'}, " + "'Ethernet108': {'alias': 'fortyGigE0/108', 'pfc_asym': 'off', 'lanes': '81,82,83,84', 'description': 'fortyGigE0/108', 'mtu': '9100'}, " + "'Ethernet100': {'alias': 'fortyGigE0/100', 'pfc_asym': 'off', 'lanes': '125,126,127,128', 'description': 'fortyGigE0/100', 'mtu': '9100'}, " + "'Ethernet104': {'alias': 'fortyGigE0/104', 'pfc_asym': 'off', 'lanes': '85,86,87,88', 'description': 'fortyGigE0/104', 'mtu': '9100'}, " + "'Ethernet68': {'alias': 'fortyGigE0/68', 'pfc_asym': 'off', 'lanes': '69,70,71,72', 'description': 'fortyGigE0/68', 'mtu': '9100'}, " + "'Ethernet96': {'alias': 'fortyGigE0/96', 'pfc_asym': 'off', 'lanes': '121,122,123,124', 'description': 'fortyGigE0/96', 'mtu': '9100'}, " + "'Ethernet124': {'alias': 'fortyGigE0/124', 'pfc_asym': 'off', 'lanes': '101,102,103,104', 'description': 'fortyGigE0/124', 'mtu': '9100'}, " + "'Ethernet92': {'alias': 'fortyGigE0/92', 'pfc_asym': 'off', 'lanes': '113,114,115,116', 'description': 'fortyGigE0/92', 'mtu': '9100'}, " + "'Ethernet120': {'alias': 'fortyGigE0/120', 'pfc_asym': 'off', 'lanes': '97,98,99,100', 'description': 'fortyGigE0/120', 'mtu': '9100'}, " + "'Ethernet52': {'alias': 'fortyGigE0/52', 'pfc_asym': 'off', 'lanes': '53,54,55,56', 'description': 'fortyGigE0/52', 'mtu': '9100'}, " + "'Ethernet56': {'alias': 'fortyGigE0/56', 'pfc_asym': 'off', 'lanes': '61,62,63,64', 'description': 'fortyGigE0/56', 'mtu': '9100'}, " + "'Ethernet76': {'alias': 'fortyGigE0/76', 'pfc_asym': 'off', 'lanes': '73,74,75,76', 'description': 'fortyGigE0/76', 'mtu': '9100'}, " + "'Ethernet72': {'alias': 'fortyGigE0/72', 'pfc_asym': 'off', 'lanes': '77,78,79,80', 'description': 'fortyGigE0/72', 'mtu': '9100'}, " + "'Ethernet64': {'alias': 'fortyGigE0/64', 'pfc_asym': 'off', 'lanes': '65,66,67,68', 'description': 'fortyGigE0/64', 'mtu': '9100'}, " + "'Ethernet32': {'alias': 'fortyGigE0/32', 'pfc_asym': 'off', 'lanes': '9,10,11,12', 'description': 'fortyGigE0/32', 'mtu': '9100'}, " + "'Ethernet16': {'alias': 'fortyGigE0/16', 'pfc_asym': 'off', 'lanes': '41,42,43,44', 'description': 'fortyGigE0/16', 'mtu': '9100'}, " + "'Ethernet36': {'alias': 'fortyGigE0/36', 'pfc_asym': 'off', 'lanes': '13,14,15,16', 'description': 'fortyGigE0/36', 'mtu': '9100'}, " + "'Ethernet12': {'lanes': '33,34,35,36', 'description': 'Interface description', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/12', 'admin_status': 'up', 'speed': '10000'}, " + "'Ethernet88': {'alias': 'fortyGigE0/88', 'pfc_asym': 'off', 'lanes': '117,118,119,120', 'description': 'fortyGigE0/88', 'mtu': '9100'}, " + "'Ethernet116': {'alias': 'fortyGigE0/116', 'pfc_asym': 'off', 'lanes': '93,94,95,96', 'description': 'fortyGigE0/116', 'mtu': '9100'}, " + "'Ethernet80': {'alias': 'fortyGigE0/80', 'pfc_asym': 'off', 'lanes': '105,106,107,108', 'description': 'fortyGigE0/80', 'mtu': '9100'}, " + "'Ethernet112': {'alias': 'fortyGigE0/112', 'pfc_asym': 'off', 'lanes': '89,90,91,92', 'description': 'fortyGigE0/112', 'mtu': '9100'}, " + "'Ethernet84': {'alias': 'fortyGigE0/84', 'pfc_asym': 'off', 'lanes': '109,110,111,112', 'description': 'fortyGigE0/84', 'mtu': '9100'}, " + "'Ethernet48': {'alias': 'fortyGigE0/48', 'pfc_asym': 'off', 'lanes': '49,50,51,52', 'description': 'fortyGigE0/48', 'mtu': '9100'}, " + "'Ethernet44': {'alias': 'fortyGigE0/44', 'pfc_asym': 'off', 'lanes': '17,18,19,20', 'description': 'fortyGigE0/44', 'mtu': '9100'}, " + "'Ethernet40': {'alias': 'fortyGigE0/40', 'pfc_asym': 'off', 'lanes': '21,22,23,24', 'description': 'fortyGigE0/40', 'mtu': '9100'}, " + "'Ethernet28': {'alias': 'fortyGigE0/28', 'pfc_asym': 'off', 'lanes': '1,2,3,4', 'description': 'fortyGigE0/28', 'mtu': '9100'}, " + "'Ethernet60': {'alias': 'fortyGigE0/60', 'pfc_asym': 'off', 'lanes': '57,58,59,60', 'description': 'fortyGigE0/60', 'mtu': '9100'}, " + "'Ethernet20': {'alias': 'fortyGigE0/20', 'pfc_asym': 'off', 'lanes': '45,46,47,48', 'description': 'fortyGigE0/20', 'mtu': '9100'}, " + "'Ethernet24': {'alias': 'fortyGigE0/24', 'pfc_asym': 'off', 'lanes': '5,6,7,8', 'description': 'fortyGigE0/24', 'mtu': '9100'}}" + ) + ) + + def test_minigraph_extra_ethernet_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT"' + output = self.run_script(argument) + + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + "{'Ethernet8': {'lanes': '37,38,39,40', 'description': 'Interface description', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/8', 'admin_status': 'up', 'speed': '1000'}, " + "'Ethernet0': {'lanes': '29,30,31,32', 'description': 'fortyGigE0/0', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/0', 'admin_status': 'up', 'speed': '10000'}, " + "'Ethernet4': {'lanes': '25,26,27,28', 'description': 'fortyGigE0/4', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/4', 'admin_status': 'up', 'speed': '25000'}, " + "'Ethernet108': {'alias': 'fortyGigE0/108', 'pfc_asym': 'off', 'lanes': '81,82,83,84', 'description': 'fortyGigE0/108', 'mtu': '9100'}, " + "'Ethernet100': {'alias': 'fortyGigE0/100', 'pfc_asym': 'off', 'lanes': '125,126,127,128', 'description': 'fortyGigE0/100', 'mtu': '9100'}, " + "'Ethernet104': {'alias': 'fortyGigE0/104', 'pfc_asym': 'off', 'lanes': '85,86,87,88', 'description': 'fortyGigE0/104', 'mtu': '9100'}, " + "'Ethernet68': {'alias': 'fortyGigE0/68', 'pfc_asym': 'off', 'lanes': '69,70,71,72', 'description': 'fortyGigE0/68', 'mtu': '9100'}, " + "'Ethernet96': {'alias': 'fortyGigE0/96', 'pfc_asym': 'off', 'lanes': '121,122,123,124', 'description': 'fortyGigE0/96', 'mtu': '9100'}, " + "'Ethernet124': {'alias': 'fortyGigE0/124', 'pfc_asym': 'off', 'lanes': '101,102,103,104', 'description': 'fortyGigE0/124', 'mtu': '9100'}, " + "'Ethernet92': {'alias': 'fortyGigE0/92', 'pfc_asym': 'off', 'lanes': '113,114,115,116', 'description': 'fortyGigE0/92', 'mtu': '9100'}, " + "'Ethernet120': {'alias': 'fortyGigE0/120', 'pfc_asym': 'off', 'lanes': '97,98,99,100', 'description': 'fortyGigE0/120', 'mtu': '9100'}, " + "'Ethernet52': {'alias': 'fortyGigE0/52', 'pfc_asym': 'off', 'lanes': '53,54,55,56', 'description': 'fortyGigE0/52', 'mtu': '9100'}, " + "'Ethernet56': {'alias': 'fortyGigE0/56', 'pfc_asym': 'off', 'lanes': '61,62,63,64', 'description': 'fortyGigE0/56', 'mtu': '9100'}, " + "'Ethernet76': {'alias': 'fortyGigE0/76', 'pfc_asym': 'off', 'lanes': '73,74,75,76', 'description': 'fortyGigE0/76', 'mtu': '9100'}, " + "'Ethernet72': {'alias': 'fortyGigE0/72', 'pfc_asym': 'off', 'lanes': '77,78,79,80', 'description': 'fortyGigE0/72', 'mtu': '9100'}, " + "'Ethernet64': {'alias': 'fortyGigE0/64', 'pfc_asym': 'off', 'lanes': '65,66,67,68', 'description': 'fortyGigE0/64', 'mtu': '9100'}, " + "'Ethernet32': {'alias': 'fortyGigE0/32', 'pfc_asym': 'off', 'lanes': '9,10,11,12', 'description': 'fortyGigE0/32', 'mtu': '9100'}, " + "'Ethernet16': {'alias': 'fortyGigE0/16', 'pfc_asym': 'off', 'lanes': '41,42,43,44', 'description': 'fortyGigE0/16', 'mtu': '9100'}, " + "'Ethernet36': {'alias': 'fortyGigE0/36', 'pfc_asym': 'off', 'lanes': '13,14,15,16', 'description': 'fortyGigE0/36', 'mtu': '9100'}, " + "'Ethernet12': {'lanes': '33,34,35,36', 'fec': 'rs', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/12', 'admin_status': 'up', 'speed': '100000', 'description': 'Interface description'}, " + "'Ethernet88': {'alias': 'fortyGigE0/88', 'pfc_asym': 'off', 'lanes': '117,118,119,120', 'description': 'fortyGigE0/88', 'mtu': '9100'}, " + "'Ethernet116': {'alias': 'fortyGigE0/116', 'pfc_asym': 'off', 'lanes': '93,94,95,96', 'description': 'fortyGigE0/116', 'mtu': '9100'}, " + "'Ethernet80': {'alias': 'fortyGigE0/80', 'pfc_asym': 'off', 'lanes': '105,106,107,108', 'description': 'fortyGigE0/80', 'mtu': '9100'}, " + "'Ethernet112': {'alias': 'fortyGigE0/112', 'pfc_asym': 'off', 'lanes': '89,90,91,92', 'description': 'fortyGigE0/112', 'mtu': '9100'}, " + "'Ethernet84': {'alias': 'fortyGigE0/84', 'pfc_asym': 'off', 'lanes': '109,110,111,112', 'description': 'fortyGigE0/84', 'mtu': '9100'}, " + "'Ethernet48': {'alias': 'fortyGigE0/48', 'pfc_asym': 'off', 'lanes': '49,50,51,52', 'description': 'fortyGigE0/48', 'mtu': '9100'}, " + "'Ethernet44': {'alias': 'fortyGigE0/44', 'pfc_asym': 'off', 'lanes': '17,18,19,20', 'description': 'fortyGigE0/44', 'mtu': '9100'}, " + "'Ethernet40': {'alias': 'fortyGigE0/40', 'pfc_asym': 'off', 'lanes': '21,22,23,24', 'description': 'fortyGigE0/40', 'mtu': '9100'}, " + "'Ethernet28': {'alias': 'fortyGigE0/28', 'pfc_asym': 'off', 'lanes': '1,2,3,4', 'description': 'fortyGigE0/28', 'mtu': '9100'}, " + "'Ethernet60': {'alias': 'fortyGigE0/60', 'pfc_asym': 'off', 'lanes': '57,58,59,60', 'description': 'fortyGigE0/60', 'mtu': '9100'}, " + "'Ethernet20': {'alias': 'fortyGigE0/20', 'pfc_asym': 'off', 'lanes': '45,46,47,48', 'description': 'fortyGigE0/20', 'mtu': '9100'}, " + "'Ethernet24': {'alias': 'fortyGigE0/24', 'pfc_asym': 'off', 'lanes': '5,6,7,8', 'description': 'fortyGigE0/24', 'mtu': '9100'}}" + ) + ) + +# everflow portion is not used +# def test_metadata_everflow(self): +# argument = '-m "' + self.sample_graph_metadata + '" -p "' + self.port_config + '" -v "MIRROR_SESSION"' +# output = self.run_script(argument) +# self.assertEqual(output.strip(), "{'everflow0': {'src_ip': '10.1.0.32', 'dst_ip': '10.0.100.1'}}") + + def test_metadata_tacacs(self): + argument = '-m "' + self.sample_graph_metadata + '" -p "' + self.port_config + '" -v "TACPLUS_SERVER"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'10.0.10.7': {'priority': '1', 'tcp_port': '49'}, '10.0.10.8': {'priority': '1', 'tcp_port': '49'}}") + ) + + def test_metadata_ntp(self): + argument = '-m "' + self.sample_graph_metadata + '" -p "' + self.port_config + '" -v "NTP_SERVER"' + output = self.run_script(argument) + self.assertEqual(utils.to_dict(output.strip()), utils.to_dict("{'10.0.10.1': {}, '10.0.10.2': {}}")) + + def test_minigraph_vnet(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "VNET"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "") + + def test_minigraph_vxlan(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "VXLAN_TUNNEL"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "") + + def test_minigraph_bgp_mon(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "BGP_MONITORS"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'10.20.30.40': {'rrclient': 0, 'name': 'BGPMonitor', 'local_addr': '10.1.0.32', 'nhopself': 0, 'holdtime': '10', 'asn': '0', 'keepalive': '3'}}") + ) + + def test_minigraph_sub_port_interfaces(self, check_stderr=True): + try: + print('\n Change device type to %s' % (BACKEND_TOR_ROUTER)) + if check_stderr: + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (TOR_ROUTER, BACKEND_TOR_ROUTER, self.sample_graph_simple), stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (TOR_ROUTER, BACKEND_TOR_ROUTER, self.sample_graph_simple), shell=True) + + self.test_jinja_expression(self.sample_graph_simple, BACKEND_TOR_ROUTER) + + + # INTERFACE table does not exist + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "INTERFACE"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "") + + # PORTCHANNEL_INTERFACE table does not exist + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORTCHANNEL_INTERFACE"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "") + + # All the other tables stay unchanged + self.test_var_json_data() + self.test_minigraph_vlans() + self.test_minigraph_vlan_members() + self.test_minigraph_vlan_interfaces() + self.test_minigraph_portchannels() + self.test_minigraph_ethernet_interfaces() + self.test_minigraph_extra_ethernet_interfaces() + self.test_minigraph_vnet() + self.test_minigraph_vxlan() + + # VLAN_SUB_INTERFACE + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN_SUB_INTERFACE' + output = self.run_script(argument) + print(output.strip()) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + "{('PortChannel01.10', '10.0.0.56/31'): {}, " + "'Ethernet0.10': {'admin_status': 'up'}, " + "('Ethernet0.10', '10.0.0.58/31'): {}, " + "('PortChannel01.10', 'FC00::71/126'): {}, " + "'PortChannel01.10': {'admin_status': 'up'}, " + "('Ethernet0.10', 'FC00::75/126'): {}}" + ) + ) + + finally: + print('\n Change device type back to %s' % (TOR_ROUTER)) + if check_stderr: + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (BACKEND_TOR_ROUTER, TOR_ROUTER, self.sample_graph_simple), stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output("sed -i \'s/%s/%s/g\' %s" % (BACKEND_TOR_ROUTER, TOR_ROUTER, self.sample_graph_simple), shell=True) + + self.test_jinja_expression(self.sample_graph_simple, TOR_ROUTER) + + def test_show_run_acl(self): + argument = '-a \'{"key1":"value"}\' --var-json ACL_RULE' + output = self.run_script(argument) + self.assertEqual(output, '') + + def test_show_run_interfaces(self): + argument = '-a \'{"key1":"value"}\' --var-json INTERFACE' + output = self.run_script(argument) + self.assertEqual(output, '') diff --git a/src/sonic-config-engine/tests/test_cfggen_pfx_filter.py b/src/sonic-config-engine/tests/test_cfggen_pfx_filter.py new file mode 100644 index 000000000000..1ac2b7f7f5f3 --- /dev/null +++ b/src/sonic-config-engine/tests/test_cfggen_pfx_filter.py @@ -0,0 +1,21 @@ +import subprocess + +import tests.common_utils as utils + +from unittest import TestCase + + +class TestPfxFilter(TestCase): + def test_comprehensive(self): + # Generate output + data_dir = "tests/data/pfx_filter" + cmd = "{} ./sonic-cfggen -j {}/param_1.json -t {}/tmpl_1.txt.j2 > /tmp/result_1.txt".format( + utils.PYTHON_INTERPRETTER, data_dir, data_dir + ) + subprocess.check_output(cmd, shell=True) + # Compare outputs + cmd = "diff -u tests/data/pfx_filter/result_1.txt /tmp/result_1.txt" + try: + res = subprocess.check_output(cmd, shell=True) + except subprocess.CalledProcessError as e: + assert False, "Wrong output. return code: %d, Diff: %s" % (e.returncode, e.output) diff --git a/src/sonic-config-engine/tests/test_cfggen_platformJson.py b/src/sonic-config-engine/tests/test_cfggen_platformJson.py new file mode 100644 index 000000000000..254ec77ae00d --- /dev/null +++ b/src/sonic-config-engine/tests/test_cfggen_platformJson.py @@ -0,0 +1,83 @@ +import ast +import json +import os +import subprocess + +import tests.common_utils as utils + +from unittest import TestCase + + +# Global Variable +PLATFORM_OUTPUT_FILE = "platform_output.json" + +class TestCfgGenPlatformJson(TestCase): + + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.sample_graph_simple = os.path.join(self.test_dir, 'simple-sample-graph.xml') + self.platform_json = os.path.join(self.test_dir, 'sample_platform.json') + self.hwsku_json = os.path.join(self.test_dir, 'sample_hwsku.json') + + def run_script(self, argument, check_stderr=False): + print('\n Running sonic-cfggen ' + argument) + if check_stderr: + output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + if utils.PY3x: + output = output.decode() + + linecount = output.strip().count('\n') + if linecount <= 0: + print(' Output: ' + output.strip()) + else: + print(' Output: ({0} lines, {1} bytes)'.format(linecount + 1, len(output))) + return output + + def test_dummy_run(self): + argument = '' + output = self.run_script(argument) + self.assertEqual(output, '') + + def test_print_data(self): + argument = '-m "' + self.sample_graph_simple + '" --print-data' + output = self.run_script(argument) + self.assertTrue(len(output.strip()) > 0) + + # Check whether all interfaces present or not as per platform.json + def test_platform_json_interfaces_keys(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT.keys()|list"' + output = self.run_script(argument) + expected = "['Ethernet8', 'Ethernet9', 'Ethernet36', 'Ethernet98', 'Ethernet0', 'Ethernet6', 'Ethernet4', 'Ethernet109', 'Ethernet108', 'Ethernet18', 'Ethernet100', 'Ethernet34', 'Ethernet104', 'Ethernet106', 'Ethernet94', 'Ethernet126', 'Ethernet96', 'Ethernet124', 'Ethernet90', 'Ethernet91', 'Ethernet92', 'Ethernet93', 'Ethernet50', 'Ethernet51', 'Ethernet52', 'Ethernet53', 'Ethernet54', 'Ethernet99', 'Ethernet56', 'Ethernet113', 'Ethernet76', 'Ethernet74', 'Ethernet39', 'Ethernet72', 'Ethernet73', 'Ethernet70', 'Ethernet71', 'Ethernet32', 'Ethernet33', 'Ethernet16', 'Ethernet111', 'Ethernet10', 'Ethernet11', 'Ethernet12', 'Ethernet13', 'Ethernet58', 'Ethernet19', 'Ethernet59', 'Ethernet38', 'Ethernet78', 'Ethernet68', 'Ethernet14', 'Ethernet89', 'Ethernet88', 'Ethernet118', 'Ethernet119', 'Ethernet116', 'Ethernet114', 'Ethernet80', 'Ethernet112', 'Ethernet86', 'Ethernet110', 'Ethernet84', 'Ethernet31', 'Ethernet49', 'Ethernet48', 'Ethernet46', 'Ethernet30', 'Ethernet29', 'Ethernet40', 'Ethernet120', 'Ethernet28', 'Ethernet66', 'Ethernet60', 'Ethernet64', 'Ethernet44', 'Ethernet20', 'Ethernet79', 'Ethernet69', 'Ethernet24', 'Ethernet26']" + + self.assertEqual(sorted(output.strip()), sorted(expected)) + + # Check specific Interface with it's proper configuration as per platform.json + def test_platform_json_specific_ethernet_interfaces(self): + + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT[\'Ethernet8\']"' + output = self.run_script(argument) + expected = "{'index': '3', 'lanes': '8', 'description': 'Eth3/1', 'admin_status': 'up', 'mtu': '9100', 'alias': 'Eth3/1', 'pfc_asym': 'off', 'speed': '25000'}" + self.assertEqual(utils.to_dict(output.strip()), utils.to_dict(expected)) + + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT[\'Ethernet112\']"' + output = self.run_script(argument) + expected = "{'index': '29', 'lanes': '112', 'description': 'Eth29/1', 'admin_status': 'up', 'mtu': '9100', 'alias': 'Eth29/1', 'pfc_asym': 'off', 'speed': '25000'}" + self.assertEqual(utils.to_dict(output.strip()), utils.to_dict(expected)) + + # Check all Interface with it's proper configuration as per platform.json + def test_platform_json_all_ethernet_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT"' + output = self.run_script(argument) + + sample_file = os.path.join(self.test_dir, 'sample_output', PLATFORM_OUTPUT_FILE) + fh = open(sample_file, 'rb') + fh_data = json.load(fh) + fh.close() + + output_dict = ast.literal_eval(output.strip()) + expected = ast.literal_eval(json.dumps(fh_data)) + self.assertDictEqual(output_dict, expected) diff --git a/src/sonic-config-engine/tests/test_cfggen_t2_chassis_fe.py b/src/sonic-config-engine/tests/test_cfggen_t2_chassis_fe.py new file mode 100644 index 000000000000..a3d6d02a7ff2 --- /dev/null +++ b/src/sonic-config-engine/tests/test_cfggen_t2_chassis_fe.py @@ -0,0 +1,86 @@ +import os +import subprocess + +import tests.common_utils as utils + +from unittest import TestCase + + +class TestCfgGenT2ChassisFe(TestCase): + + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.sample_graph_t2_chassis_fe = os.path.join(self.test_dir, 't2-chassis-fe-graph.xml') + self.sample_graph_t2_chassis_fe_vni = os.path.join(self.test_dir, 't2-chassis-fe-graph-vni.xml') + self.sample_graph_t2_chassis_fe_pc = os.path.join(self.test_dir, 't2-chassis-fe-graph-pc.xml') + self.t2_chassis_fe_port_config = os.path.join(self.test_dir, 't2-chassis-fe-port-config.ini') + + def run_script(self, argument, check_stderr=False): + print('\n Running sonic-cfggen ' + argument) + if check_stderr: + output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + if utils.PY3x: + output = output.decode() + + linecount = output.strip().count('\n') + if linecount <= 0: + print(' Output: ' + output.strip()) + else: + print(' Output: ({0} lines, {1} bytes)'.format(linecount + 1, len(output))) + return output + + def test_minigraph_t2_chassis_fe_type(self): + argument = '-m "' + self.sample_graph_t2_chassis_fe + '" -p "' + self.t2_chassis_fe_port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'type\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'SpineChassisFrontendRouter') + + def test_minigraph_t2_chassis_fe_interfaces(self): + argument = '-m "' + self.sample_graph_t2_chassis_fe + '" -p "' + self.t2_chassis_fe_port_config + '" -v "INTERFACE"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + "{'Ethernet8': {}, " + "('Ethernet8', '172.16.0.9/30'): {}, " + "'Ethernet0': {'vnet_name': 'VnetFE'}, " + "('Ethernet4', '172.16.0.1/30'): {}, " + "('Ethernet0', '192.168.0.2/30'): {}, " + "'Ethernet4': {}}" + ) + ) + def test_minigraph_t2_chassis_fe_pc_interfaces(self): + argument = '-m "' + self.sample_graph_t2_chassis_fe_pc + '" -p "' + self.t2_chassis_fe_port_config + '" -v "PORTCHANNEL_INTERFACE"' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict( + "{'PortChannel8': {}, " + "('PortChannel0', '192.168.0.2/30'): {}, " + "('PortChannel4', '172.16.0.1/30'): {}, " + "'PortChannel4': {}, " + "('PortChannel8', '172.16.0.9/30'): {}, " + "'PortChannel0': {'vnet_name': 'VnetFE'}}" + ) + ) + + # Test a minigraph file where VNI is not specified + # Default VNI is 8000 + def test_minigraph_t2_chassis_fe_vnet_default(self): + argument = '-m "' + self.sample_graph_t2_chassis_fe + '" -p "' + self.t2_chassis_fe_port_config + '" -v "VNET"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'VnetFE': {'vxlan_tunnel': 'TunnelInt', 'vni': 8000}}") + + # Test a minigraph file where VNI is specified + def test_minigraph_t2_chassis_fe_vnet(self): + argument = '-m "' + self.sample_graph_t2_chassis_fe_vni + '" -p "' + self.t2_chassis_fe_port_config + '" -v "VNET"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'VnetFE': {'vxlan_tunnel': 'TunnelInt', 'vni': 9000}}") + + def test_minigraph_t2_chassis_fe_vxlan(self): + argument = '-m "' + self.sample_graph_t2_chassis_fe + '" -p "' + self.t2_chassis_fe_port_config + '" -v "VXLAN_TUNNEL"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'TunnelInt': {'src_ip': '4.0.0.0'}}") diff --git a/src/sonic-config-engine/tests/test_frr.py b/src/sonic-config-engine/tests/test_frr.py new file mode 100644 index 000000000000..4998db2d5b25 --- /dev/null +++ b/src/sonic-config-engine/tests/test_frr.py @@ -0,0 +1,74 @@ +import filecmp +import os +import subprocess + +import tests.common_utils as utils + +from unittest import TestCase + +class TestCfgGen(TestCase): + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.t0_minigraph = os.path.join(self.test_dir, 't0-sample-graph.xml') + self.t0_port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') + self.output_file = os.path.join(self.test_dir, 'output') + + def tearDown(self): + try: + os.remove(self.output_file) + except OSError: + pass + + + def run_script(self, argument, check_stderr=False): +# print '\n Running sonic-cfggen ' + argument + if check_stderr: + output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + if utils.PY3x: + output = output.decode() + + linecount = output.strip().count('\n') + if linecount <= 0: + print(' Output: ' + output.strip()) + else: + print(' Output: ({0} lines, {1} bytes)'.format(linecount + 1, len(output))) + return output + + def run_diff(self, file1, file2): + output = subprocess.check_output('diff -u {} {} || true'.format(file1, file2), shell=True) + + if utils.PY3x: + output = output.decode() + + return output + + def run_case(self, template, target): + template_dir = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', "frr") + conf_template = os.path.join(template_dir, template) + constants = os.path.join(self.test_dir, '..', '..', '..', 'files', 'image_config', 'constants', 'constants.yml') + cmd_args = self.t0_minigraph, self.t0_port_config, constants, conf_template, template_dir, self.output_file + cmd = "-m %s -p %s -y %s -t %s -T %s > %s" % cmd_args + self.run_script(cmd) + + original_filename = os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, target) + r = filecmp.cmp(original_filename, self.output_file) + diff_output = self.run_diff(original_filename, self.output_file) if not r else "" + + return r, "Diff:\n" + diff_output + + def test_config_frr(self): + self.assertTrue(*self.run_case('frr.conf.j2', 'frr.conf')) + + def test_bgpd_frr(self): + self.assertTrue(*self.run_case('bgpd/bgpd.conf.j2', 'bgpd_frr.conf')) + + def test_zebra_frr(self): + self.assertTrue(*self.run_case('zebra/zebra.conf.j2', 'zebra_frr.conf')) + + def test_staticd_frr(self): + self.assertTrue(*self.run_case('staticd/staticd.conf.j2', 'staticd_frr.conf')) + diff --git a/src/sonic-config-engine/tests/test_j2files.py b/src/sonic-config-engine/tests/test_j2files.py new file mode 100644 index 000000000000..a66cd99820be --- /dev/null +++ b/src/sonic-config-engine/tests/test_j2files.py @@ -0,0 +1,275 @@ +import filecmp +import json +import os +import shutil +import subprocess + +from unittest import TestCase +import tests.common_utils as utils + + +class TestJ2Files(TestCase): + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.simple_minigraph = os.path.join(self.test_dir, 'simple-sample-graph.xml') + self.t0_minigraph = os.path.join(self.test_dir, 't0-sample-graph.xml') + self.t0_mvrf_minigraph = os.path.join(self.test_dir, 't0-sample-graph-mvrf.xml') + self.pc_minigraph = os.path.join(self.test_dir, 'pc-test-graph.xml') + self.t0_port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') + self.t1_mlnx_minigraph = os.path.join(self.test_dir, 't1-sample-graph-mlnx.xml') + self.mlnx_port_config = os.path.join(self.test_dir, 'sample-port-config-mlnx.ini') + self.dell6100_t0_minigraph = os.path.join(self.test_dir, 'sample-dell-6100-t0-minigraph.xml') + self.arista7050_t0_minigraph = os.path.join(self.test_dir, 'sample-arista-7050-t0-minigraph.xml') + self.multi_asic_minigraph = os.path.join(self.test_dir, 'multi_npu_data', 'sample-minigraph.xml') + self.multi_asic_port_config = os.path.join(self.test_dir, 'multi_npu_data', 'sample_port_config-0.ini') + self.output_file = os.path.join(self.test_dir, 'output') + + def run_script(self, argument): + print('CMD: sonic-cfggen ' + argument) + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + if utils.PY3x: + output = output.decode() + + return output + + def run_diff(self, file1, file2): + return subprocess.check_output('diff -u {} {} || true'.format(file1, file2), shell=True) + + def test_interfaces(self): + interfaces_template = os.path.join(self.test_dir, '..', '..', '..', 'files', 'image_config', 'interfaces', 'interfaces.j2') + argument = '-m ' + self.t0_minigraph + ' -a \'{\"hwaddr\":\"e4:1d:2d:a5:f3:ad\"}\' -t ' + interfaces_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'interfaces'), self.output_file)) + + argument = '-m ' + self.t0_mvrf_minigraph + ' -a \'{\"hwaddr\":\"e4:1d:2d:a5:f3:ad\"}\' -t ' + interfaces_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'mvrf_interfaces'), self.output_file)) + + def test_ports_json(self): + ports_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent', 'ports.json.j2') + argument = '-m ' + self.simple_minigraph + ' -p ' + self.t0_port_config + ' -t ' + ports_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'ports.json'), self.output_file)) + + def test_dhcp_relay(self): + # Test generation of wait_for_intf.sh + template_path = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-dhcp-relay', 'wait_for_intf.sh.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + template_path + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'wait_for_intf.sh'), self.output_file)) + + # Test generation of docker-dhcp-relay.supervisord.conf + template_path = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-dhcp-relay', 'docker-dhcp-relay.supervisord.conf.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + template_path + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'docker-dhcp-relay.supervisord.conf'), self.output_file)) + + def test_lldp(self): + lldpd_conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-lldp', 'lldpd.conf.j2') + + expected_mgmt_ipv4 = os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'lldp_conf', 'lldpd-ipv4-iface.conf') + expected_mgmt_ipv6 = os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'lldp_conf', 'lldpd-ipv6-iface.conf') + expected_mgmt_ipv4_and_ipv6 = expected_mgmt_ipv4 + + # Test generation of lldpd.conf if IPv4 and IPv6 management interfaces exist + mgmt_iface_ipv4_and_ipv6_json = os.path.join(self.test_dir, "data", "lldp", "mgmt_iface_ipv4_and_ipv6.json") + argument = '-j {} -t {} > {}'.format(mgmt_iface_ipv4_and_ipv6_json, lldpd_conf_template, self.output_file) + self.run_script(argument) + self.assertTrue(filecmp.cmp(expected_mgmt_ipv4_and_ipv6, self.output_file)) + + # Test generation of lldpd.conf if management interface IPv4 only exist + mgmt_iface_ipv4_json = os.path.join(self.test_dir, "data", "lldp", "mgmt_iface_ipv4.json") + argument = '-j {} -t {} > {}'.format(mgmt_iface_ipv4_json, lldpd_conf_template, self.output_file) + self.run_script(argument) + self.assertTrue(filecmp.cmp(expected_mgmt_ipv4, self.output_file)) + + # Test generation of lldpd.conf if Management interface IPv6 only exist + mgmt_iface_ipv6_json = os.path.join(self.test_dir, "data", "lldp", "mgmt_iface_ipv6.json") + argument = '-j {} -t {} > {}'.format(mgmt_iface_ipv6_json, lldpd_conf_template, self.output_file) + self.run_script(argument) + self.assertTrue(filecmp.cmp(expected_mgmt_ipv6, self.output_file)) + + def test_bgpd_quagga(self): + conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-quagga', 'bgpd.conf.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + conf_template + ' > ' + self.output_file + self.run_script(argument) + original_filename = os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'bgpd_quagga.conf') + r = filecmp.cmp(original_filename, self.output_file) + diff_output = self.run_diff(original_filename, self.output_file) if not r else "" + self.assertTrue(r, "Diff:\n" + diff_output) + + def test_zebra_quagga(self): + conf_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-quagga', 'zebra.conf.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + conf_template + ' > ' + self.output_file + self.run_script(argument) + self.assertTrue(filecmp.cmp(os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'zebra_quagga.conf'), self.output_file)) + + def test_ipinip(self): + ipinip_file = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent', 'ipinip.json.j2') + argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -t ' + ipinip_file + ' > ' + self.output_file + self.run_script(argument) + + sample_output_file = os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'ipinip.json') + assert filecmp.cmp(sample_output_file, self.output_file) + + def test_l2switch_template(self): + argument = '-k Mellanox-SN2700 --preset l2 -p ' + self.t0_port_config + output = self.run_script(argument) + output_json = json.loads(output) + + sample_output_file = os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'l2switch.json') + with open(sample_output_file) as sample_output_fd: + sample_output_json = json.load(sample_output_fd) + + self.assertTrue(json.dumps(sample_output_json, sort_keys=True) == json.dumps(output_json, sort_keys=True)) + + template_dir = os.path.join(self.test_dir, '..', 'data', 'l2switch.j2') + argument = '-t ' + template_dir + ' -k Mellanox-SN2700 -p ' + self.t0_port_config + output = self.run_script(argument) + output_json = json.loads(output) + + self.assertTrue(json.dumps(sample_output_json, sort_keys=True) == json.dumps(output_json, sort_keys=True)) + + def test_qos_arista7050_render_template(self): + arista_dir_path = os.path.join(self.test_dir, '..', '..', '..', 'device', 'arista', 'x86_64-arista_7050_qx32s', 'Arista-7050-QX-32S') + qos_file = os.path.join(arista_dir_path, 'qos.json.j2') + port_config_ini_file = os.path.join(arista_dir_path, 'port_config.ini') + + # copy qos_config.j2 to the Arista 7050 directory to have all templates in one directory + qos_config_file = os.path.join(self.test_dir, '..', '..', '..', 'files', 'build_templates', 'qos_config.j2') + shutil.copy2(qos_config_file, arista_dir_path) + + argument = '-m ' + self.arista7050_t0_minigraph + ' -p ' + port_config_ini_file + ' -t ' + qos_file + ' > ' + self.output_file + self.run_script(argument) + + # cleanup + qos_config_file_new = os.path.join(arista_dir_path, 'qos_config.j2') + os.remove(qos_config_file_new) + + sample_output_file = os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'qos-arista7050.json') + assert filecmp.cmp(sample_output_file, self.output_file) + + def test_qos_dell6100_render_template(self): + dell_dir_path = os.path.join(self.test_dir, '..', '..', '..', 'device', 'dell', 'x86_64-dell_s6100_c2538-r0', 'Force10-S6100') + qos_file = os.path.join(dell_dir_path, 'qos.json.j2') + port_config_ini_file = os.path.join(dell_dir_path, 'port_config.ini') + + # copy qos_config.j2 to the Dell S6100 directory to have all templates in one directory + qos_config_file = os.path.join(self.test_dir, '..', '..', '..', 'files', 'build_templates', 'qos_config.j2') + shutil.copy2(qos_config_file, dell_dir_path) + + argument = '-m ' + self.dell6100_t0_minigraph + ' -p ' + port_config_ini_file + ' -t ' + qos_file + ' > ' + self.output_file + self.run_script(argument) + + # cleanup + qos_config_file_new = os.path.join(dell_dir_path, 'qos_config.j2') + os.remove(qos_config_file_new) + + sample_output_file = os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'qos-dell6100.json') + assert filecmp.cmp(sample_output_file, self.output_file) + + def test_buffers_dell6100_render_template(self): + dell_dir_path = os.path.join(self.test_dir, '..', '..', '..', 'device', 'dell', 'x86_64-dell_s6100_c2538-r0', 'Force10-S6100') + buffers_file = os.path.join(dell_dir_path, 'buffers.json.j2') + port_config_ini_file = os.path.join(dell_dir_path, 'port_config.ini') + + # copy buffers_config.j2 to the Dell S6100 directory to have all templates in one directory + buffers_config_file = os.path.join(self.test_dir, '..', '..', '..', 'files', 'build_templates', 'buffers_config.j2') + shutil.copy2(buffers_config_file, dell_dir_path) + + argument = '-m ' + self.dell6100_t0_minigraph + ' -p ' + port_config_ini_file + ' -t ' + buffers_file + ' > ' + self.output_file + self.run_script(argument) + + # cleanup + buffers_config_file_new = os.path.join(dell_dir_path, 'buffers_config.j2') + os.remove(buffers_config_file_new) + + sample_output_file = os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, 'buffers-dell6100.json') + assert filecmp.cmp(sample_output_file, self.output_file) + + def test_ipinip_multi_asic(self): + ipinip_file = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent', 'ipinip.json.j2') + argument = '-m ' + self.multi_asic_minigraph + ' -p ' + self.multi_asic_port_config + ' -t ' + ipinip_file + ' -n asic0 ' + ' > ' + self.output_file + print(argument) + self.run_script(argument) + sample_output_file = os.path.join(self.test_dir, 'multi_npu_data', utils.PYvX_DIR, 'ipinip.json') + assert filecmp.cmp(sample_output_file, self.output_file) + + def test_swss_switch_render_template(self): + switch_template = os.path.join( + self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent', + 'switch.json.j2' + ) + constants_yml = os.path.join( + self.test_dir, '..', '..', '..', 'files', 'image_config', + 'constants', 'constants.yml' + ) + test_list = { + "t1": { + "graph": self.t1_mlnx_minigraph, + "output": "t1-switch.json" + }, + "t0": { + "graph": self.t0_minigraph, + "output": "t0-switch.json" + }, + } + for _, v in test_list.items(): + argument = " -m {} -y {} -t {} > {}".format( + v["graph"], constants_yml, switch_template, self.output_file + ) + sample_output_file = os.path.join( + self.test_dir, 'sample_output', v["output"] + ) + self.run_script(argument) + assert filecmp.cmp(sample_output_file, self.output_file) + + def test_swss_switch_render_template_multi_asic(self): + # verify the ECMP hash seed changes per namespace + switch_template = os.path.join( + self.test_dir, '..', '..', '..', 'dockers', 'docker-orchagent', + 'switch.json.j2' + ) + constants_yml = os.path.join( + self.test_dir, '..', '..', '..', 'files', 'image_config', + 'constants', 'constants.yml' + ) + test_list = { + "0": { + "namespace_id": "1", + "output": "t0-switch-masic1.json" + }, + "1": { + "namespace_id": "3", + "output": "t0-switch-masic3.json" + }, + } + for _, v in test_list.items(): + os.environ["NAMESPACE_ID"] = v["namespace_id"] + argument = " -m {} -y {} -t {} > {}".format( + self.t1_mlnx_minigraph, constants_yml, switch_template, + self.output_file + ) + sample_output_file = os.path.join( + self.test_dir, 'sample_output', v["output"] + ) + self.run_script(argument) + assert filecmp.cmp(sample_output_file, self.output_file) + os.environ["NAMESPACE_ID"] = "" + + def test_ndppd_conf(self): + conf_template = os.path.join(self.test_dir, "ndppd.conf.j2") + vlan_interfaces_json = os.path.join(self.test_dir, "data", "ndppd", "vlan_interfaces.json") + expected = os.path.join(self.test_dir, "sample_output", utils.PYvX_DIR, "ndppd.conf") + + argument = '-j {} -t {} > {}'.format(vlan_interfaces_json, conf_template, self.output_file) + self.run_script(argument) + assert filecmp.cmp(expected, self.output_file), self.run_diff(expected, self.output_file) + + def tearDown(self): + try: + os.remove(self.output_file) + except OSError: + pass diff --git a/src/sonic-config-engine/tests/test_j2files_t2_chassis_fe.py b/src/sonic-config-engine/tests/test_j2files_t2_chassis_fe.py new file mode 100644 index 000000000000..e6bc82941bf6 --- /dev/null +++ b/src/sonic-config-engine/tests/test_j2files_t2_chassis_fe.py @@ -0,0 +1,64 @@ +import filecmp +import json +import os +import shutil +import subprocess + +from unittest import TestCase +import tests.common_utils as utils + + +class TestJ2FilesT2ChassisFe(TestCase): + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.t2_chassis_fe_minigraph = os.path.join(self.test_dir, 't2-chassis-fe-graph.xml') + self.t2_chassis_fe_vni_minigraph = os.path.join(self.test_dir, 't2-chassis-fe-graph-vni.xml') + self.t2_chassis_fe_pc_minigraph = os.path.join(self.test_dir, 't2-chassis-fe-graph-pc.xml') + self.t2_chassis_fe_port_config = os.path.join(self.test_dir, 't2-chassis-fe-port-config.ini') + self.output_file = os.path.join(self.test_dir, 'output') + + def tearDown(self): + try: + os.remove(self.output_file) + except OSError: + pass + + def run_script(self, argument): + print('CMD: sonic-cfggen ' + argument) + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + if utils.PY3x: + output = output.decode() + + return output + + def run_diff(self, file1, file2): + return subprocess.check_output('diff -u {} {} || true'.format(file1, file2), shell=True) + + def run_case(self, minigraph, template, target): + template_dir = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-fpm-frr', "frr") + conf_template = os.path.join(template_dir, template) + constants = os.path.join(self.test_dir, '..', '..', '..', 'files', 'image_config', 'constants', 'constants.yml') + cmd_args = minigraph, self.t2_chassis_fe_port_config, constants, conf_template, template_dir, self.output_file + cmd = "-m %s -p %s -y %s -t %s -T %s > %s" % cmd_args + self.run_script(cmd) + + original_filename = os.path.join(self.test_dir, 'sample_output', utils.PYvX_DIR, target) + r = filecmp.cmp(original_filename, self.output_file) + diff_output = self.run_diff(original_filename, self.output_file) if not r else "" + + return r, "Diff:\n" + diff_output + + # Test zebra.conf in FRR docker for a T2 chassis frontend (fe) + def test_t2_chassis_fe_zebra_frr(self): + self.assertTrue(*self.run_case(self.t2_chassis_fe_minigraph, 'zebra/zebra.conf.j2', 't2-chassis-fe-zebra.conf')) + + # Test zebra.conf in FRR docker for a T2 chassis frontend (fe) switch with specified VNI + def test_t2_chassis_fe_vni_zebra_frr(self): + self.assertTrue(*self.run_case(self.t2_chassis_fe_vni_minigraph, 'zebra/zebra.conf.j2', 't2-chassis-fe-vni-zebra.conf')) + + # Test bgpd.conf in FRR docker for a T2 chassis frontend (fe) + def test_t2_chassis_frontend_bgpd_frr(self): + self.assertTrue(*self.run_case(self.t2_chassis_fe_minigraph, 'bgpd/bgpd.conf.j2', 't2-chassis-fe-bgpd.conf')) + diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py new file mode 100644 index 000000000000..64e0bb09d730 --- /dev/null +++ b/src/sonic-config-engine/tests/test_minigraph_case.py @@ -0,0 +1,303 @@ +import json +import os +import subprocess + +import tests.common_utils as utils +import minigraph + +from unittest import TestCase + + +class TestCfgGenCaseInsensitive(TestCase): + + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.sample_graph = os.path.join(self.test_dir, 'simple-sample-graph-case.xml') + self.port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini') + + def run_script(self, argument, check_stderr=False): + print('\n Running sonic-cfggen ' + argument) + if check_stderr: + output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + if utils.PY3x: + output = output.decode() + + linecount = output.strip().count('\n') + if linecount <= 0: + print(' Output: ' + output.strip()) + else: + print(' Output: ({0} lines, {1} bytes)'.format(linecount + 1, len(output))) + return output + + def test_dummy_run(self): + argument = '' + output = self.run_script(argument) + self.assertEqual(output, '') + + def test_minigraph_sku(self): + argument = '-v "DEVICE_METADATA[\'localhost\'][\'hwsku\']" -m "' + self.sample_graph + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'Force10-S6000') + + def test_print_data(self): + argument = '-m "' + self.sample_graph + '" --print-data' + output = self.run_script(argument) + self.assertTrue(len(output.strip()) > 0) + + def test_jinja_expression(self): + argument = '-m "' + self.sample_graph + '" -v "DEVICE_METADATA[\'localhost\'][\'type\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'ToRRouter') + + def test_minigraph_subtype(self): + argument = '-m "' + self.sample_graph + '" -v "DEVICE_METADATA[\'localhost\'][\'subtype\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'DualToR') + + def test_minigraph_peer_switch_hostname(self): + argument = '-m "' + self.sample_graph + '" -v "DEVICE_METADATA[\'localhost\'][\'peer_switch\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'switch2-t0') + + def test_additional_json_data(self): + argument = '-a \'{"key1":"value1"}\' -v key1' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'value1') + + def test_read_yaml(self): + argument = '-v yml_item -y ' + os.path.join(self.test_dir, 'test.yml') + output = self.run_script(argument) + self.assertEqual(output.strip(), '[\'value1\', \'value2\']') + + def test_render_template(self): + argument = '-y ' + os.path.join(self.test_dir, 'test.yml') + ' -t ' + os.path.join(self.test_dir, 'test.j2') + output = self.run_script(argument) + self.assertEqual(output.strip(), 'value1\nvalue2') + +# everflow portion is not used +# def test_minigraph_everflow(self): +# argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v MIRROR_SESSION' +# output = self.run_script(argument) +# self.assertEqual(output.strip(), "{'everflow0': {'src_ip': '10.1.0.32', 'dst_ip': '10.0.100.1'}}") + + def test_minigraph_interfaces(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v \'INTERFACE.keys()|list\'' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[('Ethernet0', '10.0.0.58/31'), 'Ethernet0', ('Ethernet0', 'FC00::75/126')]") + + def test_minigraph_vlans(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v VLAN' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'Vlan1000': {'alias': 'ab1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '1000', 'mac': '00:aa:bb:cc:dd:ee' }}") + ) + + def test_minigraph_vlan_members(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v VLAN_MEMBER' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{('Vlan1000', 'Ethernet8'): {'tagging_mode': 'untagged'}}") + + def test_minigraph_vlan_interfaces_keys(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE.keys()|list"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "[('Vlan1000', '192.168.0.1/27'), 'Vlan1000']") + + def test_minigraph_vlan_interfaces(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE"' + output = self.run_script(argument) + expected_table = { + 'Vlan1000|192.168.0.1/27': {}, + 'Vlan1000': { + 'proxy_arp': 'enabled', + 'grat_arp': 'enabled' + } + } + self.assertEqual(utils.to_dict(output.strip()), expected_table) + + def test_minigraph_portchannels(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v PORTCHANNEL' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'PortChannel01': {'admin_status': 'up', 'min_links': '1', 'members': ['Ethernet4'], 'mtu': '9100'}}") + ) + + def test_minigraph_console_mgmt_feature(self): + argument = '-m "' + self.sample_graph + '" -v CONSOLE_SWITCH' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'console_mgmt': {'enabled': 'no'}}")) + + def test_minigraph_console_port(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v CONSOLE_PORT' + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + utils.to_dict("{'1': {'baud_rate': '9600', 'remote_device': 'managed_device', 'flow_control': 1}}")) + + def test_minigraph_deployment_id(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'deployment_id\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "1") + + def test_minigraph_cluster(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'cluster\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "AAA00PrdStr00") + + def test_minigraph_neighbor_metadata(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_NEIGHBOR_METADATA"' + + expected_table = { + 'switch-01t1': { + 'lo_addr': '10.1.0.186/32', + 'mgmt_addr': '10.7.0.196/26', + 'hwsku': 'Force10-S6000', + 'type': 'LeafRouter', + 'deployment_id': '2' + }, + 'switch2-t0': { + 'hwsku': 'Force10-S6000', + 'lo_addr': '25.1.1.10/32', + 'mgmt_addr': '10.7.0.196/26', + 'type': 'ToRRouter' + }, + 'server1': { + 'hwsku': 'server-sku', + 'lo_addr': '10.10.10.1/32', + 'lo_addr_v6': 'fe80::0001/80', + 'mgmt_addr': '10.0.0.1/32', + 'type': 'Server' + }, + 'server2': { + 'hwsku': 'server-sku', + 'lo_addr': '10.10.10.2/32', + 'lo_addr_v6': 'fe80::0002/128', + 'mgmt_addr': '10.0.0.2/32', + 'type': 'Server' + } + } + output = self.run_script(argument) + self.maxDiff = None + self.assertEqual( + utils.to_dict(output.strip()), + expected_table + ) + +# everflow portion is not used +# def test_metadata_everflow(self): +# argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "MIRROR_SESSION"' +# output = self.run_script(argument) +# self.assertEqual(output.strip(), "{'everflow0': {'src_ip': '10.1.0.32', 'dst_ip': '10.0.100.1'}}") + + def test_metadata_tacacs(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "TACPLUS_SERVER"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'10.0.10.7': {'priority': '1', 'tcp_port': '49'}, '10.0.10.8': {'priority': '1', 'tcp_port': '49'}}") + + def test_metadata_kube(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "KUBERNETES_MASTER[\'SERVER\']"' + output = self.run_script(argument) + self.assertEqual(json.loads(output.strip().replace("'", "\"")), + json.loads('{"ip": "10.10.10.10", "disable": "True"}')) + + def test_minigraph_mgmt_port(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "MGMT_PORT"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'eth0': {'alias': 'eth0', 'admin_status': 'up', 'speed': '1000'}}") + + def test_metadata_ntp(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "NTP_SERVER"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{'10.0.10.1': {}, '10.0.10.2': {}}") + + def test_minigraph_vnet(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "VNET"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "") + + def test_minigraph_vxlan(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "VXLAN_TUNNEL"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "") + + def test_minigraph_bgp_mon(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "BGP_MONITORS"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "{}") + + def test_minigraph_peer_switch(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "PEER_SWITCH"' + expected_table = { + 'switch2-t0': { + 'address_ipv4': "25.1.1.10" + } + } + + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + expected_table + ) + + def test_mux_cable_parsing(self): + result = minigraph.parse_xml(self.sample_graph, port_config_file=self.port_config) + + expected_mux_cable_ports = ["Ethernet4", "Ethernet8"] + port_table = result['PORT'] + for port_name, port in port_table.items(): + if port_name in expected_mux_cable_ports: + self.assertTrue(port["mux_cable"]) + else: + self.assertTrue("mux_cable" not in port) + + def test_minigraph_storage_device(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'storage_device\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "true") + + def test_minigraph_tunnel_table(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "TUNNEL"' + expected_tunnel = { + "MuxTunnel0": { + "tunnel_type": "IPINIP", + "dst_ip": "10.1.0.32", + "dscp_mode": "uniform", + "encap_ecn_mode": "standard", + "ecn_mode": "copy_from_outer", + "ttl_mode": "pipe" + } + } + + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + expected_tunnel + ) + + def test_minigraph_mux_cable_table(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "MUX_CABLE"' + expected_table = { + 'Ethernet4': { + 'state': 'auto', + 'server_ipv4': '10.10.10.1/32', + 'server_ipv6': 'fe80::1/128' + }, + 'Ethernet8': { + 'state': 'auto', + 'server_ipv4': '10.10.10.2/32', + 'server_ipv6': 'fe80::2/128' + } + } + + output = self.run_script(argument) + self.assertEqual( + utils.to_dict(output.strip()), + expected_table + ) diff --git a/src/sonic-config-engine/tests/test_multinpu_cfggen.py b/src/sonic-config-engine/tests/test_multinpu_cfggen.py new file mode 100644 index 000000000000..83955925c9e5 --- /dev/null +++ b/src/sonic-config-engine/tests/test_multinpu_cfggen.py @@ -0,0 +1,354 @@ +import json +import os +import shutil +import subprocess +import unittest +import yaml + +import tests.common_utils as utils + +from unittest import TestCase + + +SKU = 'multi-npu-01' +ASIC_SKU = 'multi-npu-asic' +NUM_ASIC = 4 +HOSTNAME = 'multi_npu_platform_01' +DEVICE_TYPE = 'LeafRouter' + +class TestMultiNpuCfgGen(TestCase): + + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.test_data_dir = os.path.join(self.test_dir, 'multi_npu_data') + self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.sample_graph = os.path.join(self.test_data_dir, 'sample-minigraph.xml') + self.port_config = [] + for asic in range(NUM_ASIC): + self.port_config.append(os.path.join(self.test_data_dir, "sample_port_config-{}.ini".format(asic))) + + def run_script(self, argument, check_stderr=False): + print('\n Running sonic-cfggen ' + argument) + if check_stderr: + output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + if utils.PY3x: + output = output.decode() + + linecount = output.strip().count('\n') + if linecount <= 0: + print(' Output: ' + output.strip()) + else: + print(' Output: ({0} lines, {1} bytes)'.format(linecount + 1, len(output))) + return output + + def run_diff(self, file1, file2): + return subprocess.check_output('diff -u {} {} || true'.format(file1, file2), shell=True) + + def run_script_for_asic(self,argument,asic, port_config=None): + argument = "{} -n asic{} ".format(argument, asic) + if port_config: + argument += "-p {}".format(port_config) + output = self.run_script(argument) + return output + + def test_dummy_run(self): + argument = '' + output = self.run_script(argument) + self.assertEqual(output, '') + + def test_hwsku(self): + argument = "-v \"DEVICE_METADATA[\'localhost\'][\'hwsku\']\" -m \"{}\"".format(self.sample_graph) + output = self.run_script(argument) + self.assertEqual(output.strip(), SKU) + for asic in range(NUM_ASIC): + output = self.run_script_for_asic(argument, asic) + self.assertEqual(output.strip(), SKU) + + def test_print_data(self): + argument = "-m \"{}\" --print-data".format(self.sample_graph) + output = self.run_script(argument) + self.assertGreater(len(output.strip()) , 0) + for asic in range(NUM_ASIC): + output = self.run_script_for_asic(argument, asic) + self.assertGreater(len(output.strip()) , 0) + + def test_additional_json_data(self): + argument = '-a \'{"key1":"value1"}\' -v key1' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'value1') + for asic in range(NUM_ASIC): + output = self.run_script_for_asic(argument, asic) + self.assertEqual(output.strip(), 'value1') + + def test_read_yaml(self): + argument = '-v yml_item -y ' + os.path.join(self.test_dir, 'test.yml') + output = yaml.load(self.run_script(argument)) + self.assertListEqual(output, ['value1', 'value2']) + for asic in range(NUM_ASIC): + output = yaml.load(self.run_script_for_asic(argument, asic)) + self.assertListEqual(output, ['value1', 'value2']) + + def test_render_template(self): + argument = '-y ' + os.path.join(self.test_dir, 'test.yml') + ' -t ' + os.path.join(self.test_dir, 'test.j2') + output = self.run_script(argument) + self.assertEqual(output.strip(), 'value1\nvalue2') + for asic in range(NUM_ASIC): + output = self.run_script_for_asic(argument, asic) + self.assertEqual(output.strip(), 'value1\nvalue2') + + def test_metadata_tacacs(self): + argument = '-m "' + self.sample_graph + '" --var-json "TACPLUS_SERVER"' + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {'123.46.98.21': {'priority': '1', 'tcp_port': '49'}}) + #TACPLUS_SERVER not present in the asic configuration. + for asic in range(NUM_ASIC): + output = json.loads(self.run_script_for_asic(argument, asic, self.port_config[asic])) + self.assertDictEqual(output, {}) + + def test_metadata_ntp(self): + argument = '-m "' + self.sample_graph + '" --var-json "NTP_SERVER"' + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {'17.39.1.130': {}, '17.39.1.129': {}}) + #NTP data is present only in the host config + for asic in range(NUM_ASIC): + output = json.loads(self.run_script_for_asic(argument, asic, self.port_config[asic])) + print("Log:asic{} sku {}".format(asic,output)) + self.assertDictEqual(output, {}) + + def test_mgmt_port(self): + argument = '-m "' + self.sample_graph + '" --var-json "MGMT_PORT"' + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {'eth0': {'alias': 'eth0', 'admin_status': 'up'}}) + for asic in range(NUM_ASIC): + output = json.loads(self.run_script_for_asic(argument, asic, self.port_config[asic])) + self.assertDictEqual(output, {'eth0': {'alias': 'eth0', 'admin_status': 'up'}}) + + def test_frontend_asic_portchannels(self): + argument = "-m {} -p {} -n asic0 --var-json \"PORTCHANNEL\"".format(self.sample_graph, self.port_config[0]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, \ + {'PortChannel0002': {'admin_status': 'up', 'min_links': '2', 'members': ['Ethernet0', 'Ethernet4'], 'mtu': '9100'}, + 'PortChannel4001': {'admin_status': 'up', 'min_links': '2', 'members': ['Ethernet-BP0', 'Ethernet-BP4'], 'mtu': '9100'}, + 'PortChannel4002': {'admin_status': 'up', 'min_links': '2', 'members': ['Ethernet-BP8', 'Ethernet-BP12'], 'mtu': '9100'}}) + + def test_backend_asic_portchannels(self): + argument = "-m {} -p {} -n asic3 --var-json \"PORTCHANNEL\"".format(self.sample_graph, self.port_config[3]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, \ + {'PortChannel4013': {'admin_status': 'up', 'min_links': '2', 'members': ['Ethernet-BP384', 'Ethernet-BP388'], 'mtu': '9100'}, + 'PortChannel4014': {'admin_status': 'up', 'min_links': '2', 'members': ['Ethernet-BP392', 'Ethernet-BP396'], 'mtu': '9100'}}) + + def test_frontend_asic_portchannel_mem(self): + argument = "-m {} -p {} -n asic0 -v \"PORTCHANNEL_MEMBER.keys()|list\"".format(self.sample_graph, self.port_config[0]) + output = self.run_script(argument) + self.assertEqual( + utils.liststr_to_dict(output.strip()), + utils.liststr_to_dict("['PortChannel4002|Ethernet-BP8', 'PortChannel0002|Ethernet0', 'PortChannel0002|Ethernet4', 'PortChannel4002|Ethernet-BP12', 'PortChannel4001|Ethernet-BP0', 'PortChannel4001|Ethernet-BP4']") + ) + + def test_backend_asic_portchannels_mem(self): + argument = "-m {} -p {} -n asic3 -v \"PORTCHANNEL_MEMBER.keys()|list\"".format(self.sample_graph, self.port_config[3]) + output = self.run_script(argument) + self.assertEqual( + utils.liststr_to_dict(output.strip()), + utils.liststr_to_dict("['PortChannel4013|Ethernet-BP384', 'PortChannel4014|Ethernet-BP392', 'PortChannel4014|Ethernet-BP396', 'PortChannel4013|Ethernet-BP388']") + ) + + def test_frontend_asic_portchannel_intf(self): + argument = "-m {} -p {} -n asic0 -v \"PORTCHANNEL_INTERFACE.keys()|list\"".format(self.sample_graph, self.port_config[0]) + output = self.run_script(argument) + self.assertEqual( + utils.liststr_to_dict(output.strip()), + utils.liststr_to_dict("['PortChannel4001|10.1.0.1/31', 'PortChannel0002|FC00::1/126', 'PortChannel4002|10.1.0.3/31', 'PortChannel0002', 'PortChannel0002|10.0.0.0/31', 'PortChannel4001', 'PortChannel4002']") + ) + + def test_backend_asic_portchannel_intf(self): + argument = "-m {} -p {} -n asic3 -v \"PORTCHANNEL_INTERFACE.keys()|list\"".format(self.sample_graph, self.port_config[3]) + output = self.run_script(argument) + self.assertEqual( + utils.liststr_to_dict(output.strip()), + utils.liststr_to_dict("['PortChannel4013', 'PortChannel4013|10.1.0.2/31', 'PortChannel4014', 'PortChannel4014|10.1.0.6/31']") + ) + + def test_frontend_asic_ports(self): + argument = "-m {} -p {} -n asic0 --var-json \"PORT\"".format(self.sample_graph, self.port_config[0]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, \ + {"Ethernet0": { "admin_status": "up", "alias": "Ethernet1/1", "asic_port_name": "Eth0-ASIC0", "description": "01T2:Ethernet1", "index": "0", "lanes": "33,34,35,36", "mtu": "9100", "pfc_asym": "off", "role": "Ext", "speed": "40000" }, + "Ethernet4": { "admin_status": "up", "alias": "Ethernet1/2", "asic_port_name": "Eth1-ASIC0", "description": "01T2:Ethernet2", "index": "1", "lanes": "29,30,31,32", "mtu": "9100", "pfc_asym": "off", "role": "Ext", "speed": "40000" }, + "Ethernet8": { "alias": "Ethernet1/3", "asic_port_name": "Eth2-ASIC0", "description": "Ethernet1/3", "index": "2", "lanes": "41,42,43,44", "mtu": "9100", "pfc_asym": "off", "role": "Ext", "speed": "40000" }, + "Ethernet12": { "alias": "Ethernet1/4", "asic_port_name": "Eth3-ASIC0", "description": "Ethernet1/4", "index": "3", "lanes": "37,38,39,40", "mtu": "9100", "pfc_asym": "off", "role": "Ext", "speed": "40000" }, + "Ethernet-BP0": { "admin_status": "up", "alias": "Eth4-ASIC0", "asic_port_name": "Eth4-ASIC0", "description": "ASIC2:Eth0-ASIC2", "index": "0", "lanes": "13,14,15,16", "mtu": "9100", "pfc_asym": "off", "role": "Int", "speed": "40000" }, + "Ethernet-BP4": { "admin_status": "up", "alias": "Eth5-ASIC0", "asic_port_name": "Eth5-ASIC0", "description": "ASIC2:Eth1-ASIC2", "index": "1", "lanes": "17,18,19,20", "mtu": "9100", "pfc_asym": "off", "role": "Int", "speed": "40000" }, + "Ethernet-BP8": { "admin_status": "up", "alias": "Eth6-ASIC0", "asic_port_name": "Eth6-ASIC0", "description": "ASIC3:Eth0-ASIC3", "index": "2", "lanes": "21,22,23,24", "mtu": "9100", "pfc_asym": "off", "role": "Int", "speed": "40000" }, + "Ethernet-BP12": { "admin_status": "up", "alias": "Eth7-ASIC0", "asic_port_name": "Eth7-ASIC0", "description": "ASIC3:Eth1-ASIC3", "index": "3", "lanes": "25,26,27,28", "mtu": "9100", "pfc_asym": "off", "role": "Int", "speed": "40000" }}) + + def test_frontend_asic_device_neigh(self): + argument = "-m {} -p {} -n asic0 --var-json \"DEVICE_NEIGHBOR\"".format(self.sample_graph, self.port_config[0]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, \ + {'Ethernet0': {'name': '01T2', 'port': 'Ethernet1'}, + 'Ethernet4': {'name': '01T2', 'port': 'Ethernet2'}, + 'Ethernet-BP4': {'name': 'ASIC2', 'port': 'Eth1-ASIC2'}, + 'Ethernet-BP12': {'name': 'ASIC3', 'port': 'Eth1-ASIC3'}, + 'Ethernet-BP0': {'name': 'ASIC2', 'port': 'Eth0-ASIC2'}, + 'Ethernet-BP8': {'name': 'ASIC3', 'port': 'Eth0-ASIC3'}}) + + def test_frontend_asic_device_neigh_metadata(self): + argument = "-m {} -p {} -n asic0 --var-json \"DEVICE_NEIGHBOR_METADATA\"".format(self.sample_graph, self.port_config[0]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, \ + {'01T2': {'lo_addr': None, 'mgmt_addr': '89.139.132.40', 'hwsku': 'VM', 'type': 'SpineRouter'}, + 'ASIC3': {'lo_addr': '0.0.0.0/0', 'lo_addr_v6': '::/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'}, + 'ASIC2': {'lo_addr': '0.0.0.0/0', 'lo_addr_v6': '::/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'}}) + + def test_backend_asic_device_neigh(self): + argument = "-m {} -p {} -n asic3 --var-json \"DEVICE_NEIGHBOR\"".format(self.sample_graph, self.port_config[3]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, \ + {'Ethernet-BP396': {'name': 'ASIC1', 'port': 'Eth7-ASIC1'}, + 'Ethernet-BP384': {'name': 'ASIC0', 'port': 'Eth6-ASIC0'}, + 'Ethernet-BP392': {'name': 'ASIC1', 'port': 'Eth6-ASIC1'}, + 'Ethernet-BP388': {'name': 'ASIC0', 'port': 'Eth7-ASIC0'}}) + + def test_backend_device_neigh_metadata(self): + argument = "-m {} -p {} -n asic3 --var-json \"DEVICE_NEIGHBOR_METADATA\"".format(self.sample_graph, self.port_config[3]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, \ + {'ASIC1': {'lo_addr': '0.0.0.0/0', 'lo_addr_v6': '::/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'}, + 'ASIC0': {'lo_addr': '0.0.0.0/0', 'lo_addr_v6': '::/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'}}) + + def test_frontend_bgp_neighbor(self): + argument = "-m {} -p {} -n asic0 --var-json \"BGP_NEIGHBOR\"".format(self.sample_graph, self.port_config[0]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, \ + {'10.0.0.1': {'rrclient': 0, 'name': '01T2', 'local_addr': '10.0.0.0', 'nhopself': 0, 'holdtime': '10', 'asn': '65200', 'keepalive': '3'}, + 'fc00::2': {'rrclient': 0, 'name': '01T2', 'local_addr': 'fc00::1', 'nhopself': 0, 'holdtime': '10', 'asn': '65200', 'keepalive': '3'}}) + + def test_frontend_asic_bgp_neighbor(self): + argument = "-m {} -p {} -n asic0 --var-json \"BGP_INTERNAL_NEIGHBOR\"".format(self.sample_graph, self.port_config[3]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, \ + {'10.1.0.0': {'rrclient': 0, 'name': 'ASIC2', 'local_addr': '10.1.0.1', 'nhopself': 0, 'admin_status': 'up', 'holdtime': '0', 'asn': '65100', 'keepalive': '0'}, + '10.1.0.2': {'rrclient': 0, 'name': 'ASIC3', 'local_addr': '10.1.0.3', 'nhopself': 0, 'admin_status': 'up', 'holdtime': '0', 'asn': '65100', 'keepalive': '0'}}) + + def test_backend_asic_bgp_neighbor(self): + argument = "-m {} -p {} -n asic3 --var-json \"BGP_INTERNAL_NEIGHBOR\"".format(self.sample_graph, self.port_config[3]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, \ + {'10.1.0.7': {'rrclient': 0, 'name': 'ASIC1', 'local_addr': '10.1.0.6', 'nhopself': 0, 'admin_status': 'up', 'holdtime': '0', 'asn': '65100', 'keepalive': '0'}, + '10.1.0.3': {'rrclient': 0, 'name': 'ASIC0', 'local_addr': '10.1.0.2', 'nhopself': 0, 'admin_status': 'up', 'holdtime': '0', 'asn': '65100', 'keepalive': '0'}}) + + def test_device_asic_metadata(self): + argument = "-m {} --var-json DEVICE_METADATA".format(self.sample_graph) + for asic in range(NUM_ASIC): + output = json.loads(self.run_script_for_asic(argument, asic,self.port_config[asic])) + asic_name = "asic{}".format(asic) + self.assertEqual(output['localhost']['hostname'], 'multi_npu_platform_01') + self.assertEqual(output['localhost']['asic_name'], asic_name) + self.assertEqual(output['localhost']['type'], DEVICE_TYPE) + if asic == 0 or asic == 1: + self.assertEqual(output['localhost']['sub_role'], 'FrontEnd') + else: + self.assertEqual(output['localhost']['sub_role'], 'BackEnd') + + def test_global_asic_acl(self): + argument = "-m {} --var-json \"ACL_TABLE\"".format(self.sample_graph) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {\ + 'DATAACL': {'policy_desc': 'DATAACL', 'ports': ['PortChannel0002','PortChannel0008'], 'stage': 'ingress', 'type': 'L3'}, + 'EVERFLOW': {'policy_desc': 'EVERFLOW', 'ports': ['PortChannel0002','PortChannel0008'], 'stage': 'ingress', 'type': 'MIRROR'}, + 'EVERFLOWV6':{'policy_desc': 'EVERFLOWV6', 'ports': ['PortChannel0002','PortChannel0008'], 'stage': 'ingress', 'type': 'MIRRORV6'}, + 'SNMP_ACL': {'policy_desc': 'SNMP_ACL', 'services': ['SNMP'], 'stage': 'ingress', 'type': 'CTRLPLANE'}, + 'SSH_ONLY': {'policy_desc': 'SSH_ONLY', 'services': ['SSH'], 'stage': 'ingress', 'type': 'CTRLPLANE'}}) + + def test_front_end_asic_acl(self): + argument = "-m {} -p {} -n asic0 --var-json \"ACL_TABLE\"".format(self.sample_graph, self.port_config[0]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {\ + 'DATAACL': {'policy_desc': 'DATAACL', 'ports': ['PortChannel0002'], 'stage': 'ingress', 'type': 'L3'}, + 'EVERFLOW': {'policy_desc': 'EVERFLOW', 'ports': ['PortChannel0002'], 'stage': 'ingress', 'type': 'MIRROR'}, + 'EVERFLOWV6':{'policy_desc': 'EVERFLOWV6', 'ports': ['PortChannel0002'], 'stage': 'ingress', 'type': 'MIRRORV6'}, + 'SNMP_ACL': {'policy_desc': 'SNMP_ACL', 'services': ['SNMP'], 'stage': 'ingress', 'type': 'CTRLPLANE'}, + 'SSH_ONLY': {'policy_desc': 'SSH_ONLY', 'services': ['SSH'], 'stage': 'ingress', 'type': 'CTRLPLANE'}}) + + def test_back_end_asic_acl(self): + argument = "-m {} -p {} -n asic3 --var-json \"ACL_TABLE\"".format(self.sample_graph, self.port_config[3]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {}) + + def test_loopback_intfs(self): + argument = "-m {} --var-json \"LOOPBACK_INTERFACE\"".format(self.sample_graph) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {\ + "Loopback0": {}, + "Loopback0|10.1.0.32/32": {}, + "Loopback0|FC00:1::32/128": {}}) + + # The asic configuration should have 2 loopback interfaces + argument = "-m {} -n asic0 --var-json \"LOOPBACK_INTERFACE\"".format(self.sample_graph) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, { \ + "Loopback0": {}, + "Loopback4096": {}, + "Loopback0|10.1.0.32/32": {}, + "Loopback0|FC00:1::32/128": {}, + "Loopback4096|8.0.0.0/32": {}, + "Loopback4096|FD00:1::32/128": {}}) + + argument = "-m {} -n asic3 --var-json \"LOOPBACK_INTERFACE\"".format(self.sample_graph) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {\ + "Loopback0": {}, + "Loopback4096": {}, + "Loopback0|10.1.0.32/32": {}, + "Loopback0|FC00:1::32/128": {}, + "Loopback4096|8.0.0.5/32": {}, + "Loopback4096|FD00:4::32/128": {}}) + + def test_buffers_multi_asic_template(self): + build_root_dir = os.path.join( + self.test_dir, "..", "..", ".." + ) + # using Trident2 buffer configuration + device_config_dir = os.path.join( + build_root_dir, + "device", + "arista", + "x86_64-arista_7050_qx32", + "Arista-7050-QX32" + ) + device_buffer_template = os.path.join( + device_config_dir, "buffers.json.j2" + ) + buffer_template = os.path.join( + build_root_dir, "files", "build_templates", "buffers_config.j2" + ) + port_config_ini_asic0 = os.path.join( + self.test_data_dir, "sample_port_config-0.ini" + ) + # asic0 - mix of front end and back end ports + shutil.copy2(buffer_template, device_config_dir) + argument = "-m {} -p {} -n asic0 -t {}".format( + self.sample_graph, port_config_ini_asic0, device_buffer_template + ) + output = json.loads(self.run_script(argument)) + os.remove(os.path.join(device_config_dir, "buffers_config.j2")) + self.assertDictEqual( + output['CABLE_LENGTH'], + { + 'AZURE': { + 'Ethernet8': '300m', + 'Ethernet0': '300m', + 'Ethernet4': '300m', + 'Ethernet-BP4': '5m', + 'Ethernet-BP0': '5m', + 'Ethernet-BP12': '5m', + 'Ethernet-BP8': '5m', + 'Ethernet12': '300m' + } + } + ) diff --git a/src/sonic-ctrmgrd/.gitignore b/src/sonic-ctrmgrd/.gitignore new file mode 100644 index 000000000000..bdebd5e838cd --- /dev/null +++ b/src/sonic-ctrmgrd/.gitignore @@ -0,0 +1,12 @@ +.eggs/ +build/ +dist/ +*.egg-info/ +ctrmgr/*.pyc +tests/*.pyc +tests/__pycache__/ +.idea +.coverage +ctrmgr/__pycache__/ +venv +tests/.coverage* diff --git a/src/sonic-ctrmgrd/README.rst b/src/sonic-ctrmgrd/README.rst new file mode 100644 index 000000000000..30207f44b3ee --- /dev/null +++ b/src/sonic-ctrmgrd/README.rst @@ -0,0 +1,3 @@ +" +This Package contains modules required for remote container management. +" diff --git a/src/sonic-ctrmgrd/ctrmgr/__init__.py b/src/sonic-ctrmgrd/ctrmgr/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-ctrmgrd/ctrmgr/container b/src/sonic-ctrmgrd/ctrmgr/container new file mode 100755 index 000000000000..ff3706a6a7a7 --- /dev/null +++ b/src/sonic-ctrmgrd/ctrmgr/container @@ -0,0 +1,413 @@ +#!/usr/bin/env python3 + +import argparse +import os +import inspect +import json +import syslog +import time +import datetime + +import docker +from swsscommon import swsscommon + +CTR_STATE_SCR_PATH = '/usr/share/sonic/scripts/container_startup.py' + +state_db = None + +# DB field names +FEATURE_TABLE = "FEATURE" +SET_OWNER = "set_owner" +NO_FALLBACK = "no_fallback_to_local" + +CURRENT_OWNER = "current_owner" +UPD_TIMESTAMP = "update_time" +CONTAINER_ID = "container_id" +REMOTE_STATE = "remote_state" +VERSION = "container_version" +SYSTEM_STATE = "system_state" + +KUBE_LABEL_TABLE = "KUBE_LABELS" +KUBE_LABEL_SET_KEY = "SET" + +# Get seconds to wait for remote docker to start. +# If not, revert to local +# +SONIC_CTR_CONFIG = "/etc/sonic/remote_ctr.config.json" +SONIC_CTR_CONFIG_PEND_SECS = "revert_to_local_on_wait_seconds" +DEFAULT_PEND_SECS = ( 5 * 60 ) +WAIT_POLL_SECS = 2 + +remote_ctr_enabled = False + +def debug_msg(m): + msg = "{}: {}".format(inspect.stack()[1][3], m) + # print(msg) + syslog.syslog(syslog.LOG_DEBUG, msg) + + +def init(): + """ Get DB connections """ + global state_db, cfg_db, remote_ctr_enabled + + cfg_db = swsscommon.DBConnector("CONFIG_DB", 0) + state_db = swsscommon.DBConnector("STATE_DB", 0) + + remote_ctr_enabled = os.path.exists(CTR_STATE_SCR_PATH) + + +def get_config_data(fld, dflt): + """ Read entry from kube config file """ + if os.path.exists(SONIC_CTR_CONFIG): + with open(SONIC_CTR_CONFIG, "r") as s: + d = json.load(s) + if fld in d: + return d[fld] + return dflt + + +def read_data(is_config, feature, fields): + """ Read data from DB for desired fields using given defaults""" + ret = [] + + db = cfg_db if is_config else state_db + + tbl = swsscommon.Table(db, FEATURE_TABLE) + + data = dict(tbl.get(feature)[1]) + for (field, default) in fields: + val = data.get(field, default) + ret += [val] + + debug_msg("config:{} feature:{} fields:{} val:{}".format( + is_config, feature, str(fields), str(ret))) + + return tuple(ret) + + +def read_config(feature): + """ Read requried feature config """ + set_owner, no_fallback = read_data(True, feature, + [(SET_OWNER, "local"), (NO_FALLBACK, False)]) + + return (set_owner, not no_fallback) + + +def read_state(feature): + """ Read requried feature state """ + + return read_data(False, feature, + [(CURRENT_OWNER, "none"), (REMOTE_STATE, "none"), (CONTAINER_ID, "")]) + + +def docker_action(action, feature, **kwargs): + """ Execute docker action """ + try: + client = docker.from_env() + container = client.containers.get(feature) + getattr(container, action)(**kwargs) + syslog.syslog(syslog.LOG_INFO, "docker cmd: {} for {}".format(action, feature)) + return 0 + + except (docker.errors.NotFound, docker.errors.APIError) as err: + syslog.syslog(syslog.LOG_ERR, "docker cmd: {} for {} failed with {}". + format(action, feature, str(err))) + return -1 + + +def set_label(feature, create): + """ Set/drop label as required + Update is done in state-db. + ctrmgrd sets it with kube API server as required + """ + if remote_ctr_enabled: + tbl = swsscommon.Table(state_db, KUBE_LABEL_TABLE) + fld = "{}_enabled".format(feature) + + # redundant set (data already exist) can still raise subscriber + # notification. So check & set. + # Redundant delete (data doesn't exist) does not raise any + # subscriber notification. So no need to pre-check for delete. + # + tbl.set(KUBE_LABEL_SET_KEY, [(fld, "true" if create else "false")]) + + +def update_data(feature, data): + if remote_ctr_enabled: + debug_msg("feature:{} data:{}".format(feature, str(data))) + tbl = swsscommon.Table(state_db, FEATURE_TABLE) + tbl.set(feature, list(data.items())) + + +def container_id(feature): + """ + Return the container ID for the feature. + + if current_owner is local, use feature name as the start/stop + of local image is synchronous. + Else get it from FEATURE table in STATE-DB + + :param feature: Name of the feature to start. + + """ + init() + + tbl = swsscommon.Table(state_db, "FEATURE") + data = dict(tbl.get(feature)[1]) + + if (data.get(CURRENT_OWNER, "").lower() == "local"): + return feature + else: + return data.get(CONTAINER_ID, feature) + + +def container_start(feature, **kwargs): + """ + Starts a container for given feature. + + Starts from local image and/or trigger kubernetes to deploy the image + for this feature. Marks the feature state up in STATE-DB FEATURE table. + + If feature's set_owner is local, invoke docker start. + If feature's set_owner is kube, it creates a node label that + would trigger kubernetes to start the container. With kube as + owner, if fallback is enabled and remote_state==none, it starts + the local image using docker, which will run until kube + deployment occurs. + + :param feature: Name of the feature to start. + + """ + START_LOCAL = 1 + START_KUBE = 2 + + ret = 0 + debug_msg("BEGIN") + + init() + + set_owner, fallback = read_config(feature) + _, remote_state, _ = read_state(feature) + + debug_msg("{}: set_owner:{} fallback:{} remote_state:{}".format( + feature, set_owner, fallback, remote_state)) + + data = { + SYSTEM_STATE: "up", + UPD_TIMESTAMP: str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + } + + + start_val = 0 + if set_owner == "local": + start_val = START_LOCAL + else: + start_val = START_KUBE + if fallback and (remote_state == "none"): + start_val |= START_LOCAL + + if start_val == START_LOCAL: + # Implies *only* local. + # Ensure label is not there, to block kube deployment. + set_label(feature, False) + data[REMOTE_STATE] = "none" + + if (start_val & START_LOCAL): + data[CURRENT_OWNER] = "local" + data[CONTAINER_ID] = feature + + update_data(feature, data) + + if (start_val & START_LOCAL): + ret = docker_action("start", feature, **kwargs) + + if (start_val & START_KUBE): + set_label(feature, True) + debug_msg("END") + return ret + + +def container_stop(feature, **kwargs): + """ + Stops the running container for this feature. + + Instruct/ensure kube terminates, by removing label, unless + an kube upgrade is happening. + + Gets the container ID for this feature and call docker stop. + + Marks the feature state down in STATE-DB FEATURE table. + + :param feature: Name of the feature to stop. + + """ + debug_msg("BEGIN") + + init() + + set_owner, _ = read_config(feature) + current_owner, remote_state, _ = read_state(feature) + docker_id = container_id(feature) + remove_label = (remote_state != "pending") or (set_owner == "local") + + debug_msg("{}: set_owner:{} current_owner:{} remote_state:{} docker_id:{}".format( + feature, set_owner, current_owner, remote_state, docker_id)) + + if remove_label: + set_label(feature, False) + + if docker_id: + docker_action("stop", docker_id, **kwargs) + else: + syslog.syslog( + syslog.LOG_ERR if current_owner != "none" else syslog.LOG_INFO, + "docker stop skipped as no docker-id for {}".format(feature)) + + # Container could get killed or crashed. In either case + # it does not have opportunity to mark itself down. + # Even during normal termination, with SIGTERM received + # container process may not have enough window of time to + # mark itself down and has the potential to get aborted. + # + # systemctl ensures that it handles only one instance for + # a feature at anytime and however the feature container + # exits, upon stop/kill/crash, systemctl-stop process + # is assured to get called. So mark the feature down here. + # + data = { + CURRENT_OWNER: "none", + UPD_TIMESTAMP: str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")), + CONTAINER_ID: "", + VERSION: "", + SYSTEM_STATE: "down" + } + if remote_state == "running": + data[REMOTE_STATE] = "stopped" + + update_data(feature, data) + + debug_msg("END") + + +def container_kill(feature, **kwargs): + """ + Kills the running container for this feature. + + Instruct/ensure kube terminates, by removing label. + + :param feature: Name of the feature to kill. + + """ + debug_msg("BEGIN") + + init() + + set_owner, _ = read_config(feature) + current_owner, remote_state, _ = read_state(feature) + docker_id = container_id(feature) + remove_label = (set_owner != "local") or (current_owner != "local") + + debug_msg("{}: set_owner:{} current_owner:{} remote_state:{} docker_id:{}".format( + feature, set_owner, current_owner, remote_state, docker_id)) + + if remove_label: + set_label(feature, False) + + if docker_id: + docker_action("kill", docker_id, **kwargs) + + else: + syslog.syslog( + syslog.LOG_ERR if current_owner != "none" else syslog.LOG_INFO, + "docker stop skipped as no docker-id for {}".format(feature)) + + + debug_msg("END") + + +def container_wait(feature, **kwargs): + """ + Waits on the running container for this feature. + + Get the container-id and call docker wait. + + If docker-id can't be obtained for a configurable fail-duration + the wait clears the feature's remote-state in STATE-DB FEATURE + table and exit. + + :param feature: Name of the feature to wait. + + """ + debug_msg("BEGIN") + + init() + + set_owner, fallback = read_config(feature) + current_owner, remote_state, _ = read_state(feature) + docker_id = container_id(feature) + pend_wait_secs = 0 + + if not docker_id and fallback: + pend_wait_secs = get_config_data( + SONIC_CTR_CONFIG_PEND_SECS, DEFAULT_PEND_SECS) + + debug_msg("{}: set_owner:{} ct_owner:{} state:{} id:{} pend={}".format( + feature, set_owner, current_owner, remote_state, docker_id, + pend_wait_secs)) + + while not docker_id: + if fallback: + pend_wait_secs = pend_wait_secs - WAIT_POLL_SECS + if pend_wait_secs < 0: + break + + time.sleep(WAIT_POLL_SECS) + + current_owner, remote_state, docker_id = read_state(feature) + + debug_msg("wait_loop: {} = {} {} {}".format(feature, current_owner, remote_state, docker_id)) + + if (remote_state == "pending"): + update_data(feature, {REMOTE_STATE: "ready"}) + + if not docker_id: + # Clear remote state and exit. + # systemd would restart and fallback to local + update_data(feature, { REMOTE_STATE: "none" }) + debug_msg("{}: Exiting to fallback as remote is *not* starting". + format(feature)) + else: + debug_msg("END -- transitioning to docker wait") + docker_action("wait", docker_id, **kwargs) + + +def main(): + parser=argparse.ArgumentParser(description="container commands for start/stop/wait/kill/id") + parser.add_argument("action", choices=["start", "stop", "wait", "kill", "id"]) + parser.add_argument('-t', '--timeout', type=int, help='container action timeout value', default=None) + parser.add_argument("name") + + args = parser.parse_args() + kwargs = {} + + if args.action == "start": + container_start(args.name, **kwargs) + + elif args.action == "stop": + if args.timeout is not None: + kwargs['timeout'] = args.timeout + container_stop(args.name, **kwargs) + + elif args.action == "kill": + container_kill(args.name, **kwargs) + + elif args.action == "wait": + container_wait(args.name, **kwargs) + + elif args.action == "id": + id = container_id(args.name, **kwargs) + print(id) + + +if __name__ == "__main__": + main() diff --git a/src/sonic-ctrmgrd/ctrmgr/container_startup.py b/src/sonic-ctrmgrd/ctrmgr/container_startup.py new file mode 100755 index 000000000000..c56160aa488d --- /dev/null +++ b/src/sonic-ctrmgrd/ctrmgr/container_startup.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python3 + +import argparse +import datetime +import inspect +import json +import subprocess +import syslog +import time + +from swsscommon import swsscommon + +# DB field names +SET_OWNER = "set_owner" + +CURRENT_OWNER = "current_owner" +UPD_TIMESTAMP = "update_time" +DOCKER_ID = "container_id" +REMOTE_STATE = "remote_state" +VERSION = "container_version" +SYSTEM_STATE = "system_state" + +KUBE_LABEL_TABLE = "KUBE_LABELS" +KUBE_LABEL_SET_KEY = "SET" + +UNIT_TESTING = 0 + + +def debug_msg(m): + msg = "{}: {}".format(inspect.stack()[1][3], m) + print(msg) + syslog.syslog(syslog.LOG_DEBUG, msg) + + +def _get_version_key(feature, version): + # Coin label for version control + return "{}_{}_enabled".format(feature, version) + + +def read_data(feature): + state_data = { + CURRENT_OWNER: "none", + UPD_TIMESTAMP: "", + DOCKER_ID: "", + REMOTE_STATE: "none", + VERSION: "0.0.0", + SYSTEM_STATE: "" + } + + set_owner = "local" + + # read owner from config-db and current state data from state-db. + db = swsscommon.DBConnector("CONFIG_DB", 0) + tbl = swsscommon.Table(db, 'FEATURE') + data = dict(tbl.get(feature)[1]) + + if (SET_OWNER in data): + set_owner = data[SET_OWNER] + + state_db = swsscommon.DBConnector("STATE_DB", 0) + tbl = swsscommon.Table(state_db, 'FEATURE') + state_data.update(dict(tbl.get(feature)[1])) + + return (state_db, set_owner, state_data) + + +def read_fields(state_db, feature, fields): + # Read directly from STATE-DB, given fields + # for given feature. + # Fields is a list of tuples (, ) + # + tbl = swsscommon.Table(state_db, 'FEATURE') + ret = [] + + # tbl.get for non-existing feature would return + # [False, {} ] + # + data = dict(tbl.get(feature)[1]) + for (field, default) in fields: + val = data[field] if field in data else default + ret += [val] + + return tuple(ret) + + +def check_version_blocked(state_db, feature, version): + # Ensure this version is *not* blocked explicitly. + # + tbl = swsscommon.Table(state_db, KUBE_LABEL_TABLE) + labels = dict(tbl.get(KUBE_LABEL_SET_KEY)[1]) + key = _get_version_key(feature, version) + return (key in labels) and (labels[key].lower() == "false") + + +def drop_label(state_db, feature, version): + # Mark given feature version as dropped in labels. + # Update is done in state-db. + # ctrmgrd sets it with kube API server per reaschability + + tbl = swsscommon.Table(state_db, KUBE_LABEL_TABLE) + name = _get_version_key(feature, version) + tbl.set(KUBE_LABEL_SET_KEY, [ (name, "false")]) + + +def update_data(state_db, feature, data): + # Update STATE-DB entry for this feature with given data + # + debug_msg("{}: {}".format(feature, str(data))) + tbl = swsscommon.Table(state_db, "FEATURE") + tbl.set(feature, list(data.items())) + + +def get_docker_id(): + # Read the container-id + # Note: This script runs inside the context of container + # + cmd = 'cat /proc/self/cgroup | grep -e ":memory:" | rev | cut -f1 -d\'/\' | rev' + proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) + output = proc.communicate()[0].decode("utf-8") + return output.strip()[:12] + + +def instance_higher(feature, ct_version, version): + # Compares given version against current version in STATE-DB. + # Return True if this version is higher than current. + # + ret = False + if ct_version: + ct = ct_version.split('.') + nxt = version.split('.') + for cs, ns in zip(ct, nxt): + c = int(cs) + n = int(ns) + if n < c: + break + elif n > c: + ret = True + break + else: + # Empty version implies no one is running. + ret = True + + debug_msg("compare version: new:{} current:{} res={}".format( + version, ct_version, ret)) + return ret + + +def is_active(feature, system_state): + # Check current system state of the feature + if system_state == "up": + return True + else: + syslog.syslog(syslog.LOG_ERR, "Found inactive for {}".format(feature)) + return False + + +def update_state(state_db, feature, owner=None, version=None): + """ + sets owner, version & container-id for this feature in state-db. + + If owner is local, update label to block remote deploying same version or + if kube, sets state to "running". + + """ + data = { + CURRENT_OWNER: owner, + DOCKER_ID: get_docker_id() if owner != "local" else feature, + UPD_TIMESTAMP: str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")), + "hello": "world", + VERSION: version + } + + if (owner == "local"): + # Disable deployment of this version as available locally + drop_label(state_db, feature, version) + else: + data[REMOTE_STATE] = "running" + + debug_msg("{} up data:{}".format(feature, str(data))) + update_data(state_db, feature, data) + + +def do_freeze(feat, m): + # Exiting will kick off the container to run. + # So sleep forever with periodic logs. + # + while True: + syslog.syslog(syslog.LOG_ERR, "Blocking .... feat:{} docker_id:{} msg:{}".format( + feat, get_docker_id(), m)) + if UNIT_TESTING: + break + time.sleep(60) + + +def container_up(feature, owner, version): + """ + This is called by container upon post start. + + The container will run its application, only upon this call + complete. + + This call does the basic check for if this starting-container can be allowed + to run based on current state, and owner & version of this starting + container. + + If allowed to proceed, this info is recorded in state-db and return + to enable container start the main application. Else it proceeds to + sleep forever, blocking the container from starting the main application. + + """ + debug_msg("BEGIN") + (state_db, set_owner, state_data) = read_data(feature) + + debug_msg("args: feature={}, owner={}, version={} DB: set_owner={} state_data={}".format( + feature, owner, version, set_owner, json.dumps(state_data, indent=4))) + + if owner == "local": + update_state(state_db, feature, owner, version) + else: + if (set_owner == "local"): + do_freeze(feature, "bail out as set_owner is local") + return + + if not is_active(feature, state_data[SYSTEM_STATE]): + do_freeze(feature, "bail out as system state not active") + return + + if check_version_blocked(state_db, feature, version): + do_freeze(feature, "This version is marked disabled. Exiting ...") + return + + if not instance_higher(feature, state_data[VERSION], version): + # TODO: May Remove label __enabled + # Else kubelet will continue to re-deploy every 5 mins, until + # master removes the lable to un-deploy. + # + do_freeze(feature, "bail out as current deploy version {} is not higher". + format(version)) + return + + update_data(state_db, feature, { VERSION: version }) + + mode = state_data[REMOTE_STATE] + if mode in ("none", "running", "stopped"): + update_data(state_db, feature, { REMOTE_STATE: "pending" }) + mode = "pending" + else: + debug_msg("{}: Skip remote_state({}) update".format(feature, mode)) + + + i = 0 + while (mode != "ready"): + if (i % 10) == 0: + debug_msg("{}: remote_state={}. Waiting to go ready".format(feature, mode)) + i += 1 + + time.sleep(2) + mode, db_version = read_fields(state_db, + feature, [(REMOTE_STATE, "none"), (VERSION, "")]) + if version != db_version: + # looks like another instance has overwritten. Exit for now. + # If this happens to be higher version, next deploy by kube will fix + # This is a very rare window of opportunity, for this version to be higher. + # + do_freeze(feature, + "bail out as current deploy version={} is different than {}. re-deploy higher one". + format(version, db_version)) + return + if UNIT_TESTING: + return + + + update_state(state_db, feature, owner, version) + + debug_msg("END") + + +def main(): + parser = argparse.ArgumentParser(description="container_startup kube/local []") + + parser.add_argument("-f", "--feature", required=True) + parser.add_argument("-o", "--owner", choices=["local", "kube"], required=True) + parser.add_argument("-v", "--version", required=True) + + args = parser.parse_args() + container_up(args.feature, args.owner, args.version) + + + +if __name__ == "__main__": + main() diff --git a/src/sonic-ctrmgrd/ctrmgr/ctrmgr_tools.py b/src/sonic-ctrmgrd/ctrmgr/ctrmgr_tools.py new file mode 100755 index 000000000000..d85f76c4f955 --- /dev/null +++ b/src/sonic-ctrmgrd/ctrmgr/ctrmgr_tools.py @@ -0,0 +1,147 @@ +#! /usr/bin/env python3 + +import argparse +import json +import os +import syslog + +import docker +from swsscommon import swsscommon + +CTR_NAMES_FILE = "/usr/share/sonic/templates/ctr_image_names.json" + +LATEST_TAG = "latest" + +# DB fields +CT_OWNER = 'current_owner' +CT_ID = 'container_id' +SYSTEM_STATE = 'system_state' + +def _get_local_image_name(feature): + d = {} + if os.path.exists(CTR_NAMES_FILE): + with open(CTR_NAMES_FILE, "r") as s: + d = json.load(s) + return d[feature] if feature in d else None + + +def _remove_container(client, feature): + try: + # Remove stopped container instance, if any for this feature + container = client.containers.get(feature) + container.remove() + syslog.syslog(syslog.LOG_INFO, "Removed container for {}". + format(feature)) + return 0 + except Exception as err: + syslog.syslog(syslog.LOG_INFO, "No container to remove for {} err={}". + format(feature, str(err))) + return -1 + + +def _tag_container_image(feature, container_id, image_name, image_tag): + client = docker.from_env() + + try: + container = client.containers.get(container_id) + + # Tag this image for given name & tag + container.image.tag(image_name, image_tag, force=True) + + syslog.syslog(syslog.LOG_INFO, + "Tagged image for {} with container-id={} to {}:{}". + format(feature, container_id, image_name, image_tag)) + ret = _remove_container(client, feature) + return ret + + except Exception as err: + syslog.syslog(syslog.LOG_ERR, "Image tag: container:{} {}:{} failed with {}". + format(container_id, image_name, image_tag, str(err))) + return -1 + + +def tag_feature(feature=None, image_name=None, image_tag=None): + ret = 0 + state_db = swsscommon.DBConnector("STATE_DB", 0) + tbl = swsscommon.Table(state_db, 'FEATURE') + keys = tbl.getKeys() + for k in keys: + if (not feature) or (k == feature): + d = dict(tbl.get(k)[1]) + owner = d.get(CT_OWNER, "") + id = d.get(CT_ID, "") + if not image_name: + image_name = _get_local_image_name(k) + if not image_tag: + image_tag = LATEST_TAG + if id and (owner == "kube") and image_name: + ret = _tag_container_image(k, id, image_name, image_tag) + else: + syslog.syslog(syslog.LOG_ERR, + "Skip to tag feature={} image={} tag={}".format( + k, str(image_name), str(image_tag))) + ret = -1 + + image_name=None + return ret + + +def func_tag_feature(args): + return tag_feature(args.feature, args.image_name, args.image_tag) + + +def func_tag_all(args): + return tag_feature() + + +def func_kill_all(args): + client = docker.from_env() + state_db = swsscommon.DBConnector("STATE_DB", 0) + tbl = swsscommon.Table(state_db, 'FEATURE') + + keys = tbl.getKeys() + for k in keys: + data = dict(tbl.get(k)[1]) + is_up = data.get(SYSTEM_STATE, "").lower() == "up" + id = data.get(CT_ID, "") if is_up else "" + if id: + try: + container = client.containers.get(id) + container.kill() + syslog.syslog(syslog.LOG_INFO, + "Killed container for {} with id={}".format(k, id)) + except Exception as err: + syslog.syslog(syslog.LOG_ERR, + "kill: feature={} id={} unable to get container". + format(k, id)) + return -1 + return 0 + + +def main(): + parser = argparse.ArgumentParser(description="Remote container mgmt tools") + subparsers = parser.add_subparsers(title="ctrmgr_tools") + + parser_tag = subparsers.add_parser('tag') + parser_tag.add_argument("-f", "--feature", required=True) + parser_tag.add_argument("-n", "--image-name") + parser_tag.add_argument("-t", "--image-tag") + parser_tag.set_defaults(func=func_tag_feature) + + parser_tag_all = subparsers.add_parser('tag-all') + parser_tag_all.set_defaults(func=func_tag_all) + + parser_kill_all = subparsers.add_parser('kill-all') + parser_kill_all.set_defaults(func=func_kill_all) + + args = parser.parse_args() + if len(args.__dict__) < 1: + parser.print_help() + return -1 + + ret = args.func(args) + return ret + + +if __name__ == "__main__": + main() diff --git a/src/sonic-ctrmgrd/ctrmgr/ctrmgrd.py b/src/sonic-ctrmgrd/ctrmgr/ctrmgrd.py new file mode 100755 index 000000000000..ba4f0057bd05 --- /dev/null +++ b/src/sonic-ctrmgrd/ctrmgr/ctrmgrd.py @@ -0,0 +1,598 @@ +#!/usr/bin/env python3 + +import datetime +import inspect +import json +import os +import sys +import syslog + +from collections import defaultdict + +from swsscommon import swsscommon +from sonic_py_common import device_info + +sys.path.append(os.path.dirname(os.path.realpath(__file__))) +import kube_commands + +UNIT_TESTING = 0 +UNIT_TESTING_ACTIVE = 0 + +# Kube config file +SONIC_CTR_CONFIG = "/etc/sonic/remote_ctr.config.json" + +CONFIG_DB_NAME = "CONFIG_DB" +STATE_DB_NAME = "STATE_DB" + +# DB SERVER +SERVER_TABLE = "KUBERNETES_MASTER" +SERVER_KEY = "SERVER" +CFG_SER_IP = "ip" +CFG_SER_PORT = "port" +CFG_SER_DISABLE = "disable" +CFG_SER_INSECURE = "insecure" + +ST_SER_IP = "ip" +ST_SER_PORT = "port" +ST_SER_CONNECTED = "connected" +ST_SER_UPDATE_TS = "update_time" + +# DB FEATURE +FEATURE_TABLE = "FEATURE" +CFG_FEAT_OWNER = "set_owner" +CFG_FEAT_NO_FALLBACK = "no_fallback_to_local" +CFG_FEAT_FAIL_DETECTION = "remote_fail_detection" + +ST_FEAT_OWNER = "current_owner" +ST_FEAT_UPDATE_TS = "update_time" +ST_FEAT_CTR_ID = "container_id" +ST_FEAT_CTR_VER = "container_version" +ST_FEAT_REMOTE_STATE = "remote_state" +ST_FEAT_SYS_STATE = "system_state" + +KUBE_LABEL_TABLE = "KUBE_LABELS" +KUBE_LABEL_SET_KEY = "SET" + +remote_connected = False + +dflt_cfg_ser = { + CFG_SER_IP: "", + CFG_SER_PORT: "6443", + CFG_SER_DISABLE: "false", + CFG_SER_INSECURE: "false" + } + +dflt_st_ser = { + ST_SER_IP: "", + ST_SER_PORT: "", + ST_SER_CONNECTED: "", + ST_SER_UPDATE_TS: "" + } + +dflt_cfg_feat= { + CFG_FEAT_OWNER: "local", + CFG_FEAT_NO_FALLBACK: "false", + CFG_FEAT_FAIL_DETECTION: "300" + } + +dflt_st_feat= { + ST_FEAT_OWNER: "none", + ST_FEAT_UPDATE_TS: "", + ST_FEAT_CTR_ID: "", + ST_FEAT_CTR_VER: "", + ST_FEAT_REMOTE_STATE: "none", + ST_FEAT_SYS_STATE: "" + } + +JOIN_LATENCY = "join_latency_on_boot_seconds" +JOIN_RETRY = "retry_join_interval_seconds" +LABEL_RETRY = "retry_labels_update_seconds" + +remote_ctr_config = { + JOIN_LATENCY: 10, + JOIN_RETRY: 10, + LABEL_RETRY: 2 + } + +def log_debug(m): + msg = "{}: {}".format(inspect.stack()[1][3], m) + print(msg) + syslog.syslog(syslog.LOG_DEBUG, msg) + + +def log_error(m): + syslog.syslog(syslog.LOG_ERR, msg) + + +def log_info(m): + syslog.syslog(syslog.LOG_INFO, msg) + + +def ts_now(): + return str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + + +def is_systemd_active(feat): + if not UNIT_TESTING: + status = os.system('systemctl is-active --quiet {}'.format(feat)) + else: + status = UNIT_TESTING_ACTIVE + log_debug("system status for {}: {}".format(feat, str(status))) + return status == 0 + + +def restart_systemd_service(server, feat, owner): + log_debug("Restart service {} to owner:{}".format(feat, owner)) + if not UNIT_TESTING: + status = os.system("systemctl restart {}".format(feat)) + else: + server.mod_db_entry(STATE_DB_NAME, + FEATURE_TABLE, feat, {"restart": "true"}) + status = 0 + if status != 0: + syslog.syslog(syslog.LOG_ERR, + "Failed to restart {} to switch to {}".format(feat, owner)) + else: + syslog.syslog(syslog.LOG_INFO, + "Restarted {} to switch to {}".format(feat, owner)) + return status + + +def init(): + if os.path.exists(SONIC_CTR_CONFIG): + with open(SONIC_CTR_CONFIG, "r") as s: + d = json.load(s) + remote_ctr_config.update(d) + + +class MainServer: + """ Implements main io-loop of the application + Accept handler registration per db/table. + Call handler on update + """ + + SELECT_TIMEOUT = 1000 + + def __init__(self): + """ Constructor """ + self.db_connectors = {} + self.selector = swsscommon.Select() + self.callbacks = defaultdict(lambda: defaultdict(list)) # db -> table -> handlers[] + self.timer_handlers = defaultdict(list) + self.subscribers = set() + + def register_db(self, db_name): + """ Get DB connector, if not there """ + if db_name not in self.db_connectors: + self.db_connectors[db_name] = swsscommon.DBConnector(db_name, 0) + + + def register_timer(self, ts, handler): + """ Register timer based handler. + The handler will be called on/after give timestamp, ts + """ + self.timer_handlers[ts].append(handler) + + + def register_handler(self, db_name, table_name, handler): + """ + Handler registration for any update in given table + in given db. The handler will be called for any update + to the table in this db. + """ + self.register_db(db_name) + + if table_name not in self.callbacks[db_name]: + conn = self.db_connectors[db_name] + subscriber = swsscommon.SubscriberStateTable(conn, table_name) + self.subscribers.add(subscriber) + self.selector.addSelectable(subscriber) + self.callbacks[db_name][table_name].append(handler) + + + def get_db_entry(self, db_name, table_name, key): + """ Return empty dict if key not present """ + conn = self.db_connectors[db_name] + tbl = swsscommon.Table(conn, table_name) + return dict(tbl.get(key)[1]) + + + def mod_db_entry(self, db_name, table_name, key, data): + """ Modify entry for given table|key with given dict type data """ + conn = self.db_connectors[db_name] + tbl = swsscommon.Table(conn, table_name) + print("mod_db_entry: db={} tbl={} key={} data={}".format(db_name, table_name, key, str(data))) + tbl.set(key, list(data.items())) + + + def set_db_entry(self, db_name, table_name, key, data): + """ Set given data as complete data, which includes + removing any fields that are in DB but not in data + """ + conn = self.db_connectors[db_name] + tbl = swsscommon.Table(conn, table_name) + ct_data = dict(tbl.get(key)[1]) + for k in ct_data: + if k not in data: + # Drop fields that are not in data + tbl.hdel(key, k) + tbl.set(key, list(data.items())) + + + def run(self): + """ Main loop """ + while True: + timeout = MainServer.SELECT_TIMEOUT + ct_ts = datetime.datetime.now() + while self.timer_handlers: + k = sorted(self.timer_handlers.keys())[0] + if k <= ct_ts: + lst = self.timer_handlers[k] + del self.timer_handlers[k] + for fn in lst: + fn() + else: + timeout = (k - ct_ts).seconds + break + + state, _ = self.selector.select(timeout) + if state == self.selector.TIMEOUT: + continue + elif state == self.selector.ERROR: + if not UNIT_TESTING: + raise Exception("Received error from select") + else: + print("Skipped Exception; Received error from select") + return + + for subscriber in self.subscribers: + key, op, fvs = subscriber.pop() + if not key: + continue + log_debug("Received message : '%s'" % str((key, op, fvs))) + for callback in (self.callbacks + [subscriber.getDbConnector().getDbName()] + [subscriber.getTableName()]): + callback(key, op, dict(fvs)) + + + +def set_node_labels(server): + labels = {} + + version_info = (device_info.get_sonic_version_info() if not UNIT_TESTING + else { "build_version": "20201230.111"}) + dev_data = server.get_db_entry(CONFIG_DB_NAME, 'DEVICE_METADATA', + 'localhost') + dep_type = dev_data['type'] if 'type' in dev_data else "unknown" + + labels["sonic_version"] = version_info['build_version'] + labels["hwsku"] = device_info.get_hwsku() if not UNIT_TESTING else "mock" + labels["deployment_type"] = dep_type + server.mod_db_entry(STATE_DB_NAME, + KUBE_LABEL_TABLE, KUBE_LABEL_SET_KEY, labels) + + +def _update_entry(ct, upd): + # Helper function, to update with case lowered. + ret = dict(ct) + for (k, v) in upd.items(): + ret[k.lower()] = v.lower() + + return ret + + +# +# SERVER-config changes: +# Act if IP or disable changes. +# If disabled or IP removed: +# reset connection +# else: +# join +# Update state-DB appropriately +# +class RemoteServerHandler: + def __init__(self, server): + """ Register self for updates """ + self.server = server + + server.register_handler( + CONFIG_DB_NAME, SERVER_TABLE, self.on_config_update) + self.cfg_server = _update_entry(dflt_cfg_ser, server.get_db_entry( + CONFIG_DB_NAME, SERVER_TABLE, SERVER_KEY)) + + log_debug("startup config: {}".format(str(self.cfg_server))) + + server.register_db(STATE_DB_NAME) + self.st_server = _update_entry(dflt_st_ser, server.get_db_entry( + STATE_DB_NAME, SERVER_TABLE, SERVER_KEY)) + + self.start_time = datetime.datetime.now() + + if not self.st_server[ST_FEAT_UPDATE_TS]: + # This is upon system start. Sleep 10m before join + self.start_time += datetime.timedelta( + seconds=remote_ctr_config[JOIN_LATENCY]) + server.register_timer(self.start_time, self.handle_update) + self.pending = True + log_debug("Pause to join {} seconds @ {}".format( + remote_ctr_config[JOIN_LATENCY], self.start_time)) + else: + self.pending = False + self.handle_update() + + + + def on_config_update(self, key, op, data): + """ On config update """ + if key != SERVER_KEY: + return + + cfg_data = _update_entry(dflt_cfg_ser, data) + if self.cfg_server == cfg_data: + log_debug("No change in server config") + return + + log_debug("Received config update: {}".format(str(data))) + self.cfg_server = cfg_data + + if self.pending: + tnow = datetime.datetime.now() + if tnow < self.start_time: + # Pausing for initial latency since reboot or last retry + due_secs = (self.start_time - tnow).seconds + else: + due_secs = 0 + log_debug("Pending to start in {} seconds at {}".format( + due_secs, self.start_time)) + return + + self.handle_update() + + + def handle_update(self): + # Called upon start and upon any config-update only. + # Called by timer / main thread. + # Main thread calls only if timer is not running. + # + self.pending = False + + ip = self.cfg_server[CFG_SER_IP] + disable = self.cfg_server[CFG_SER_DISABLE] != "false" + + pre_state = dict(self.st_server) + log_debug("server: handle_update: disable={} ip={}".format(disable, ip)) + if disable or not ip: + self.do_reset() + else: + self.do_join(ip, self.cfg_server[ST_SER_PORT], + self.cfg_server[CFG_SER_INSECURE]) + + if pre_state != self.st_server: + self.st_server[ST_SER_UPDATE_TS] = ts_now() + self.server.set_db_entry(STATE_DB_NAME, + SERVER_TABLE, SERVER_KEY, self.st_server) + log_debug("Update server state={}".format(str(self.st_server))) + + + def do_reset(self): + global remote_connected + + kube_commands.kube_reset_master(True) + + self.st_server[ST_SER_CONNECTED] = "false" + log_debug("kube_reset_master called") + + remote_connected = False + + + def do_join(self, ip, port, insecure): + global remote_connected + (ret, out, err) = kube_commands.kube_join_master( + ip, port, insecure) + + if ret == 0: + self.st_server[ST_SER_CONNECTED] = "true" + self.st_server[ST_SER_IP] = ip + self.st_server[ST_SER_PORT] = port + remote_connected = True + + set_node_labels(self.server) + log_debug("kube_join_master succeeded") + else: + # Ensure state reflects the current status + self.st_server[ST_SER_CONNECTED] = "false" + remote_connected = False + + # Join failed. Retry after an interval + self.start_time = datetime.datetime.now() + self.start_time += datetime.timedelta( + seconds=remote_ctr_config[JOIN_RETRY]) + self.server.register_timer(self.start_time, self.handle_update) + self.pending = True + + log_debug("kube_join_master failed retry after {} seconds @{}". + format(remote_ctr_config[JOIN_RETRY], self.start_time)) + + +# +# Feature changes +# +# Handle Set_owner change: +# restart service and/or label add/drop +# +# Handle remote_state change: +# When pending, trigger restart +# +class FeatureTransitionHandler: + def __init__(self, server): + self.server = server + self.cfg_data = defaultdict(lambda: defaultdict(str)) + self.st_data = defaultdict(lambda: defaultdict(str)) + server.register_handler( + CONFIG_DB_NAME, FEATURE_TABLE, self.on_config_update) + server.register_handler( + STATE_DB_NAME, FEATURE_TABLE, self.on_state_update) + return + + + def handle_update(self, feat, set_owner, ct_owner, remote_state): + # Called upon startup once for every feature in config & state DBs. + # There after only called upon changes in either that requires action + # + if not is_systemd_active(feat): + # Nothing todo, if system state is down + return + + label_add = set_owner == "kube" + service_restart = False + + if set_owner == "local": + if ct_owner != "local": + service_restart = True + else: + if (ct_owner != "none") and (remote_state == "pending"): + service_restart = True + + log_debug( + "feat={} set={} ct={} state={} restart={} label_add={}".format( + feat, set_owner, ct_owner, remote_state, service_restart, + label_add)) + # read labels and add/drop if different + self.server.mod_db_entry(STATE_DB_NAME, KUBE_LABEL_TABLE, KUBE_LABEL_SET_KEY, + { "{}_enabled".format(feat): ("true" if label_add else "false") }) + + + # service_restart + if service_restart: + restart_systemd_service(self.server, feat, set_owner) + + + + def on_config_update(self, key, op, data): + # Hint/Note: + # If the key don't pre-exist: + # This attempt to read will create the key for given + # field with empty string as value and return empty string + + init = key not in self.cfg_data + old_set_owner = self.cfg_data[key][CFG_FEAT_OWNER] + + self.cfg_data[key] = _update_entry(dflt_cfg_feat, data) + set_owner = self.cfg_data[key][CFG_FEAT_OWNER] + + if (not init) and (old_set_owner == set_owner): + # No change, bail out + log_debug("No change in feat={} set_owner={}. Bail out.".format( + key, set_owner)) + return + + if key in self.st_data: + log_debug("{} init={} old_set_owner={} owner={}".format(key, init, old_set_owner, set_owner)) + self.handle_update(key, set_owner, + self.st_data[key][ST_FEAT_OWNER], + self.st_data[key][ST_FEAT_REMOTE_STATE]) + + else: + # Handle it upon data from state-db, which must come + # if systemd is up + log_debug("Yet to get state info key={}. Bail out.".format(key)) + return + + + def on_state_update(self, key, op, data): + # Hint/Note: + # If the key don't pre-exist: + # This attempt to read will create the key for given + # field with empty string as value and return empty string + + init = key not in self.st_data + old_remote_state = self.st_data[key][ST_FEAT_REMOTE_STATE] + + self.st_data[key] = _update_entry(dflt_st_feat, data) + remote_state = self.st_data[key][ST_FEAT_REMOTE_STATE] + + if (not init) and ( + (old_remote_state == remote_state) or (remote_state != "pending")): + # no change or nothing to do. + return + + if key in self.cfg_data: + log_debug("{} init={} old_remote_state={} remote_state={}".format(key, init, old_remote_state, remote_state)) + self.handle_update(key, self.cfg_data[key][CFG_FEAT_OWNER], + self.st_data[key][ST_FEAT_OWNER], + remote_state) + return + + +# +# Label re-sync +# When labels applied at remote are pending, start monitoring +# API server reachability and trigger the label handler to +# apply the labels +# +# Non-empty KUBE_LABELS|PENDING, monitor API Server reachability +# +class LabelsPendingHandler: + def __init__(self, server): + server.register_handler(STATE_DB_NAME, KUBE_LABEL_TABLE, self.on_update) + self.server = server + self.pending = False + self.set_labels = {} + return + + + def on_update(self, key, op, data): + # For any update sync with kube API server. + # Don't optimize, as API server could differ with DB's contents + # in many ways. + # + if (key == KUBE_LABEL_SET_KEY): + self.set_labels = dict(data) + else: + return + + if remote_connected and not self.pending: + self.update_node_labels() + else: + log_debug("Skip label update: connected:{} pending:{}". + format(remote_connected, self.pending)) + + + + def update_node_labels(self): + # Called on config update by main thread upon init or config-change or + # it was not connected during last config update + # NOTE: remote-server-handler forces a config update notification upon + # join. + # Or it could be called by timer thread, if last upate to API server + # failed. + # + self.pending = False + ret = kube_commands.kube_write_labels(self.set_labels) + if (ret != 0): + self.pending = True + pause = remote_ctr_config[LABEL_RETRY] + ts = (datetime.datetime.now() + datetime.timedelta(seconds=pause)) + self.server.register_timer(ts, self.update_node_labels) + + log_debug("ret={} set={} pending={}".format(ret, + str(self.set_labels), self.pending)) + return + + +def main(): + init() + server = MainServer() + RemoteServerHandler(server) + FeatureTransitionHandler(server) + LabelsPendingHandler(server) + server.run() + print("ctrmgrd.py main called") + return 0 + + +if __name__ == '__main__': + if os.geteuid() != 0: + exit("Please run as root. Exiting ...") + main() diff --git a/src/sonic-ctrmgrd/ctrmgr/ctrmgrd.service b/src/sonic-ctrmgrd/ctrmgr/ctrmgrd.service new file mode 100644 index 000000000000..6052c10785da --- /dev/null +++ b/src/sonic-ctrmgrd/ctrmgr/ctrmgrd.service @@ -0,0 +1,14 @@ +[Unit] +Description=Container Manager watcher daemon +Requires=updategraph.service +After=updategraph.service + + +[Service] +Type=simple +ExecStart=/usr/local/bin/ctrmgrd.py +Restart=always +RestartSec=30 + +[Install] +WantedBy=multi-user.target diff --git a/src/sonic-ctrmgrd/ctrmgr/kube_commands.py b/src/sonic-ctrmgrd/ctrmgr/kube_commands.py new file mode 100755 index 000000000000..1ebfa606f07f --- /dev/null +++ b/src/sonic-ctrmgrd/ctrmgr/kube_commands.py @@ -0,0 +1,391 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import argparse +import fcntl +import inspect +import json +import os +import shutil +import ssl +import subprocess +import sys +import syslog +import tempfile +import urllib.request +from urllib.parse import urlparse + +import yaml +from sonic_py_common import device_info + +KUBE_ADMIN_CONF = "/etc/sonic/kube_admin.conf" +KUBELET_YAML = "/var/lib/kubelet/config.yaml" +SERVER_ADMIN_URL = "https://{}/admin.conf" +LOCK_FILE = "/var/lock/kube_join.lock" + +# kubectl --kubeconfig label nodes +#